--- linux-ec2-2.6.32.orig/Makefile
+++ linux-ec2-2.6.32/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 32
-EXTRAVERSION =
+EXTRAVERSION = .41+drm33.18
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -331,14 +331,23 @@
 AFLAGS_KERNEL	=
 CFLAGS_GCOV	= -fprofile-arcs -ftest-coverage
 
+# Prefer linux-backports-modules
+ifneq ($(KBUILD_SRC),)
+ifneq ($(shell if test -e $(KBUILD_OUTPUT)/ubuntu-build; then echo yes; fi),yes)
+UBUNTUINCLUDE := -I/usr/src/linux-headers-lbm-$(KERNELRELEASE)
+endif
+endif
 
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
-LINUXINCLUDE    := -Iinclude \
+LINUXINCLUDE    := $(UBUNTUINCLUDE) -Iinclude \
                    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
                    -I$(srctree)/arch/$(hdr-arch)/include               \
                    -include include/linux/autoconf.h
 
+# UBUNTU: Include our third party driver stuff too
+LINUXINCLUDE   += -Iubuntu/include $(if $(KBUILD_SRC),-I$(srctree)/ubuntu/include)
+
 KBUILD_CPPFLAGS := -D__KERNEL__
 
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
@@ -464,12 +473,12 @@
 # Carefully list dependencies so we do not try to build scripts twice
 # in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/auto.conf
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
 	$(Q)$(MAKE) $(build)=$(@)
 
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y		:= init/
-drivers-y	:= drivers/ sound/ firmware/
+drivers-y	:= drivers/ sound/ firmware/ ubuntu/
 net-y		:= net/
 libs-y		:= lib/
 core-y		:= usr/
@@ -491,7 +500,7 @@
 # with it and forgot to run make oldconfig.
 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
-include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
 	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
 # external modules needs include/linux/autoconf.h and include/config/auto.conf
@@ -876,6 +885,9 @@
 PHONY += $(vmlinux-dirs)
 $(vmlinux-dirs): prepare scripts
 	$(Q)$(MAKE) $(build)=$@
+ifdef CONFIG_MODULES
+	$(Q)$(MAKE) $(modbuiltin)=$@
+endif
 
 # Build the kernel release string
 #
@@ -1126,6 +1138,7 @@
 PHONY += modules
 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
+	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.builtin) > $(objtree)/modules.builtin
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
@@ -1155,6 +1168,7 @@
 		ln -s $(objtree) $(MODLIB)/build ; \
 	fi
 	@cp -f $(objtree)/modules.order $(MODLIB)/
+	@cp -f $(objtree)/modules.builtin $(MODLIB)/
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
 
 # This depmod is only for convenience to give the initial
@@ -1218,6 +1232,7 @@
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
 		-o -name '*.symtypes' -o -name 'modules.order' \
 		-o -name 'Module.markers' -o -name '.tmp_*.o.*' \
+		-o -name 'modules.builtin' \
 		-o -name '*.gcno' \) -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -1416,7 +1431,8 @@
 clean:	rm-dirs := $(MODVERDIR)
 clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
                    $(KBUILD_EXTMOD)/Module.markers \
-                   $(KBUILD_EXTMOD)/modules.order
+                   $(KBUILD_EXTMOD)/modules.order \
+                   $(KBUILD_EXTMOD)/modules.builtin
 clean: $(clean-dirs)
 	$(call cmd,rmdirs)
 	$(call cmd,rmfiles)
--- linux-ec2-2.6.32.orig/MAINTAINERS
+++ linux-ec2-2.6.32/MAINTAINERS
@@ -1974,6 +1974,12 @@
 S:	Maintained
 F:	drivers/platform/x86/eeepc-laptop.c
 
+EFIFB FRAMEBUFFER DRIVER
+L:	linux-fbdev@vger.kernel.org
+M:	Peter Jones <pjones@redhat.com>
+S:	Maintained
+F:	drivers/video/efifb.c
+
 EFS FILESYSTEM
 W:	http://aeschi.ch.eu.org/efs/
 S:	Orphan
@@ -5004,7 +5010,6 @@
 
 STABLE BRANCH
 M:	Greg Kroah-Hartman <greg@kroah.com>
-M:	Chris Wright <chrisw@sous-sol.org>
 L:	stable@kernel.org
 S:	Maintained
 
@@ -5594,9 +5599,11 @@
 F:	drivers/net/wireless/rndis_wlan.c
 
 USB XHCI DRIVER
-M:	Sarah Sharp <sarah.a.sharp@intel.com>
+M:	Sarah Sharp <sarah.a.sharp@linux.intel.com>
 L:	linux-usb@vger.kernel.org
 S:	Supported
+F:	drivers/usb/host/xhci*
+F:	drivers/usb/host/pci-quirks*
 
 USB ZC0301 DRIVER
 M:	Luca Risolia <luca.risolia@studio.unibo.it>
@@ -5718,6 +5725,14 @@
 S:	Maintained
 F:	drivers/net/vmxnet3/
 
+VMware PVSCSI driver
+M:	Alok Kataria <akataria@vmware.com>
+M:	VMware PV-Drivers <pv-drivers@vmware.com>
+L:	linux-scsi@vger.kernel.org
+S:	Maintained
+F:	drivers/scsi/vmw_pvscsi.c
+F:	drivers/scsi/vmw_pvscsi.h
+
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 M:	Liam Girdwood <lrg@slimlogic.co.uk>
 M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
--- linux-ec2-2.6.32.orig/firmware/Makefile
+++ linux-ec2-2.6.32/firmware/Makefile
@@ -140,7 +140,7 @@
 fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
 
 # Directories which we _might_ need to create, so we have a rule for them.
-firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all))))
+firmware-dirs := $(sort $(addprefix $(objtree)/$(obj)/,$(dir $(fw-external-y) $(fw-shipped-all))))
 
 quiet_cmd_mkdir = MKDIR   $(patsubst $(objtree)/%,%,$@)
       cmd_mkdir = mkdir -p $@
--- linux-ec2-2.6.32.orig/kernel/cgroup_freezer.c
+++ linux-ec2-2.6.32/kernel/cgroup_freezer.c
@@ -47,17 +47,20 @@
 			    struct freezer, css);
 }
 
-int cgroup_frozen(struct task_struct *task)
+int cgroup_freezing_or_frozen(struct task_struct *task)
 {
 	struct freezer *freezer;
 	enum freezer_state state;
 
 	task_lock(task);
 	freezer = task_freezer(task);
-	state = freezer->state;
+	if (!freezer->css.cgroup->parent)
+		state = CGROUP_THAWED; /* root cgroup can't be frozen */
+	else
+		state = freezer->state;
 	task_unlock(task);
 
-	return state == CGROUP_FROZEN;
+	return (state == CGROUP_FREEZING) || (state == CGROUP_FROZEN);
 }
 
 /*
--- linux-ec2-2.6.32.orig/kernel/hrtimer.c
+++ linux-ec2-2.6.32/kernel/hrtimer.c
@@ -557,7 +557,7 @@
 static int hrtimer_reprogram(struct hrtimer *timer,
 			     struct hrtimer_clock_base *base)
 {
-	ktime_t *expires_next = &__get_cpu_var(hrtimer_bases).expires_next;
+	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
 	int res;
 
@@ -582,7 +582,16 @@
 	if (expires.tv64 < 0)
 		return -ETIME;
 
-	if (expires.tv64 >= expires_next->tv64)
+	if (expires.tv64 >= cpu_base->expires_next.tv64)
+		return 0;
+
+	/*
+	 * If a hang was detected in the last timer interrupt then we
+	 * do not schedule a timer which is earlier than the expiry
+	 * which we enforced in the hang detection. We want the system
+	 * to make progress.
+	 */
+	if (cpu_base->hang_detected)
 		return 0;
 
 	/*
@@ -590,7 +599,7 @@
 	 */
 	res = tick_program_event(expires, 0);
 	if (!IS_ERR_VALUE(res))
-		*expires_next = expires;
+		cpu_base->expires_next = expires;
 	return res;
 }
 
@@ -911,6 +920,7 @@
 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
 	if (hrtimer_is_queued(timer)) {
+		unsigned long state;
 		int reprogram;
 
 		/*
@@ -924,8 +934,13 @@
 		debug_deactivate(timer);
 		timer_stats_hrtimer_clear_start_info(timer);
 		reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
-		__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
-				 reprogram);
+		/*
+		 * We must preserve the CALLBACK state flag here,
+		 * otherwise we could move the timer base in
+		 * switch_hrtimer_base.
+		 */
+		state = timer->state & HRTIMER_STATE_CALLBACK;
+		__remove_hrtimer(timer, base, state, reprogram);
 		return 1;
 	}
 	return 0;
@@ -1083,7 +1098,7 @@
 }
 EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
 
-#ifdef CONFIG_NO_HZ
+#if defined(CONFIG_NO_HZ) || defined(CONFIG_NO_IDLE_HZ)
 /**
  * hrtimer_get_next_event - get the time until next expiry event
  *
@@ -1212,34 +1227,14 @@
 		BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
 		enqueue_hrtimer(timer, base);
 	}
+
+	WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));
+
 	timer->state &= ~HRTIMER_STATE_CALLBACK;
 }
 
 #ifdef CONFIG_HIGH_RES_TIMERS
 
-static int force_clock_reprogram;
-
-/*
- * After 5 iteration's attempts, we consider that hrtimer_interrupt()
- * is hanging, which could happen with something that slows the interrupt
- * such as the tracing. Then we force the clock reprogramming for each future
- * hrtimer interrupts to avoid infinite loops and use the min_delta_ns
- * threshold that we will overwrite.
- * The next tick event will be scheduled to 3 times we currently spend on
- * hrtimer_interrupt(). This gives a good compromise, the cpus will spend
- * 1/4 of their time to process the hrtimer interrupts. This is enough to
- * let it running without serious starvation.
- */
-
-static inline void
-hrtimer_interrupt_hanging(struct clock_event_device *dev,
-			ktime_t try_time)
-{
-	force_clock_reprogram = 1;
-	dev->min_delta_ns = (unsigned long)try_time.tv64 * 3;
-	printk(KERN_WARNING "hrtimer: interrupt too slow, "
-		"forcing clock min delta to %lu ns\n", dev->min_delta_ns);
-}
 /*
  * High resolution timer interrupt
  * Called with interrupts disabled
@@ -1248,21 +1243,15 @@
 {
 	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
 	struct hrtimer_clock_base *base;
-	ktime_t expires_next, now;
-	int nr_retries = 0;
-	int i;
+	ktime_t expires_next, now, entry_time, delta;
+	int i, retries = 0;
 
 	BUG_ON(!cpu_base->hres_active);
 	cpu_base->nr_events++;
 	dev->next_event.tv64 = KTIME_MAX;
 
- retry:
-	/* 5 retries is enough to notice a hang */
-	if (!(++nr_retries % 5))
-		hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now));
-
-	now = ktime_get();
-
+	entry_time = now = ktime_get();
+retry:
 	expires_next.tv64 = KTIME_MAX;
 
 	spin_lock(&cpu_base->lock);
@@ -1324,10 +1313,48 @@
 	spin_unlock(&cpu_base->lock);
 
 	/* Reprogramming necessary ? */
-	if (expires_next.tv64 != KTIME_MAX) {
-		if (tick_program_event(expires_next, force_clock_reprogram))
-			goto retry;
+	if (expires_next.tv64 == KTIME_MAX ||
+	    !tick_program_event(expires_next, 0)) {
+		cpu_base->hang_detected = 0;
+		return;
 	}
+
+	/*
+	 * The next timer was already expired due to:
+	 * - tracing
+	 * - long lasting callbacks
+	 * - being scheduled away when running in a VM
+	 *
+	 * We need to prevent that we loop forever in the hrtimer
+	 * interrupt routine. We give it 3 attempts to avoid
+	 * overreacting on some spurious event.
+	 */
+	now = ktime_get();
+	cpu_base->nr_retries++;
+	if (++retries < 3)
+		goto retry;
+	/*
+	 * Give the system a chance to do something else than looping
+	 * here. We stored the entry time, so we know exactly how long
+	 * we spent here. We schedule the next event this amount of
+	 * time away.
+	 */
+	cpu_base->nr_hangs++;
+	cpu_base->hang_detected = 1;
+	delta = ktime_sub(now, entry_time);
+	if (delta.tv64 > cpu_base->max_hang_time.tv64)
+		cpu_base->max_hang_time = delta;
+	/*
+	 * Limit it to a sensible value as we enforce a longer
+	 * delay. Give the CPU at least 100ms to catch up.
+	 */
+	if (delta.tv64 > 100 * NSEC_PER_MSEC)
+		expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC);
+	else
+		expires_next = ktime_add(now, delta);
+	tick_program_event(expires_next, 1);
+	printk_once(KERN_WARNING "hrtimer: interrupt took %llu ns\n",
+		    ktime_to_ns(delta));
 }
 
 /*
--- linux-ec2-2.6.32.orig/kernel/rcutree.c
+++ linux-ec2-2.6.32/kernel/rcutree.c
@@ -176,9 +176,29 @@
 	return &rsp->node[0];
 }
 
+/*
+ * Record the specified "completed" value, which is later used to validate
+ * dynticks counter manipulations and CPU-offline checks.  Specify
+ * "rsp->completed - 1" to unconditionally invalidate any future dynticks
+ * manipulations and CPU-offline checks.  Such invalidation is useful at
+ * the beginning of a grace period.
+ */
+static void dyntick_record_completed(struct rcu_state *rsp, long comp)
+{
+	rsp->dynticks_completed = comp;
+}
+
 #ifdef CONFIG_SMP
 
 /*
+ * Recall the previously recorded value of the completion for dynticks.
+ */
+static long dyntick_recall_completed(struct rcu_state *rsp)
+{
+	return rsp->dynticks_completed;
+}
+
+/*
  * If the specified CPU is offline, tell the caller that it is in
  * a quiescent state.  Otherwise, whack it with a reschedule IPI.
  * Grace periods can end up waiting on an offline CPU when that
@@ -335,28 +355,9 @@
 		set_need_resched();
 }
 
-/*
- * Record the specified "completed" value, which is later used to validate
- * dynticks counter manipulations.  Specify "rsp->completed - 1" to
- * unconditionally invalidate any future dynticks manipulations (which is
- * useful at the beginning of a grace period).
- */
-static void dyntick_record_completed(struct rcu_state *rsp, long comp)
-{
-	rsp->dynticks_completed = comp;
-}
-
 #ifdef CONFIG_SMP
 
 /*
- * Recall the previously recorded value of the completion for dynticks.
- */
-static long dyntick_recall_completed(struct rcu_state *rsp)
-{
-	return rsp->dynticks_completed;
-}
-
-/*
  * Snapshot the specified CPU's dynticks counter so that we can later
  * credit them with an implicit quiescent state.  Return 1 if this CPU
  * is in dynticks idle mode, which is an extended quiescent state.
@@ -419,24 +420,8 @@
 
 #else /* #ifdef CONFIG_NO_HZ */
 
-static void dyntick_record_completed(struct rcu_state *rsp, long comp)
-{
-}
-
 #ifdef CONFIG_SMP
 
-/*
- * If there are no dynticks, then the only way that a CPU can passively
- * be in a quiescent state is to be offline.  Unlike dynticks idle, which
- * is a point in time during the prior (already finished) grace period,
- * an offline CPU is always in a quiescent state, and thus can be
- * unconditionally applied.  So just return the current value of completed.
- */
-static long dyntick_recall_completed(struct rcu_state *rsp)
-{
-	return rsp->completed;
-}
-
 static int dyntick_save_progress_counter(struct rcu_data *rdp)
 {
 	return 0;
@@ -553,13 +538,33 @@
 /*
  * Update CPU-local rcu_data state to record the newly noticed grace period.
  * This is used both when we started the grace period and when we notice
- * that someone else started the grace period.
- */
+ * that someone else started the grace period.  The caller must hold the
+ * ->lock of the leaf rcu_node structure corresponding to the current CPU,
+ *  and must have irqs disabled.
+ */
+static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp)
+{
+	if (rdp->gpnum != rnp->gpnum) {
+		rdp->qs_pending = 1;
+		rdp->passed_quiesc = 0;
+		rdp->gpnum = rnp->gpnum;
+	}
+}
+
 static void note_new_gpnum(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	rdp->qs_pending = 1;
-	rdp->passed_quiesc = 0;
-	rdp->gpnum = rsp->gpnum;
+	unsigned long flags;
+	struct rcu_node *rnp;
+
+	local_irq_save(flags);
+	rnp = rdp->mynode;
+	if (rdp->gpnum == ACCESS_ONCE(rnp->gpnum) || /* outside lock. */
+	    !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */
+		local_irq_restore(flags);
+		return;
+	}
+	__note_new_gpnum(rsp, rnp, rdp);
+	spin_unlock_irqrestore(&rnp->lock, flags);
 }
 
 /*
@@ -583,6 +588,79 @@
 }
 
 /*
+ * Advance this CPU's callbacks, but only if the current grace period
+ * has ended.  This may be called only from the CPU to whom the rdp
+ * belongs.  In addition, the corresponding leaf rcu_node structure's
+ * ->lock must be held by the caller, with irqs disabled.
+ */
+static void
+__rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp)
+{
+	/* Did another grace period end? */
+	if (rdp->completed != rnp->completed) {
+
+		/* Advance callbacks.  No harm if list empty. */
+		rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL];
+		rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL];
+		rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+
+		/* Remember that we saw this grace-period completion. */
+		rdp->completed = rnp->completed;
+	}
+}
+
+/*
+ * Advance this CPU's callbacks, but only if the current grace period
+ * has ended.  This may be called only from the CPU to whom the rdp
+ * belongs.
+ */
+static void
+rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp)
+{
+	unsigned long flags;
+	struct rcu_node *rnp;
+
+	local_irq_save(flags);
+	rnp = rdp->mynode;
+	if (rdp->completed == ACCESS_ONCE(rnp->completed) || /* outside lock. */
+	    !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */
+		local_irq_restore(flags);
+		return;
+	}
+	__rcu_process_gp_end(rsp, rnp, rdp);
+	spin_unlock_irqrestore(&rnp->lock, flags);
+}
+
+/*
+ * Do per-CPU grace-period initialization for running CPU.  The caller
+ * must hold the lock of the leaf rcu_node structure corresponding to
+ * this CPU.
+ */
+static void
+rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp)
+{
+	/* Prior grace period ended, so advance callbacks for current CPU. */
+	__rcu_process_gp_end(rsp, rnp, rdp);
+
+	/*
+	 * Because this CPU just now started the new grace period, we know
+	 * that all of its callbacks will be covered by this upcoming grace
+	 * period, even the ones that were registered arbitrarily recently.
+	 * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL.
+	 *
+	 * Other CPUs cannot be sure exactly when the grace period started.
+	 * Therefore, their recently registered callbacks must pass through
+	 * an additional RCU_NEXT_READY stage, so that they will be handled
+	 * by the next RCU grace period.
+	 */
+	rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+	rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
+
+	/* Set state so that this CPU will detect the next quiescent state. */
+	__note_new_gpnum(rsp, rnp, rdp);
+}
+
+/*
  * Start a new RCU grace period if warranted, re-initializing the hierarchy
  * in preparation for detecting the next grace period.  The caller must hold
  * the root node's ->lock, which is released before return.  Hard irqs must
@@ -607,28 +685,15 @@
 	rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
 	record_gp_stall_check_time(rsp);
 	dyntick_record_completed(rsp, rsp->completed - 1);
-	note_new_gpnum(rsp, rdp);
-
-	/*
-	 * Because this CPU just now started the new grace period, we know
-	 * that all of its callbacks will be covered by this upcoming grace
-	 * period, even the ones that were registered arbitrarily recently.
-	 * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL.
-	 *
-	 * Other CPUs cannot be sure exactly when the grace period started.
-	 * Therefore, their recently registered callbacks must pass through
-	 * an additional RCU_NEXT_READY stage, so that they will be handled
-	 * by the next RCU grace period.
-	 */
-	rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
-	rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
 
 	/* Special-case the common single-level case. */
 	if (NUM_RCU_NODES == 1) {
 		rcu_preempt_check_blocked_tasks(rnp);
 		rnp->qsmask = rnp->qsmaskinit;
 		rnp->gpnum = rsp->gpnum;
+		rnp->completed = rsp->completed;
 		rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */
+		rcu_start_gp_per_cpu(rsp, rnp, rdp);
 		spin_unlock_irqrestore(&rnp->lock, flags);
 		return;
 	}
@@ -661,6 +726,9 @@
 		rcu_preempt_check_blocked_tasks(rnp);
 		rnp->qsmask = rnp->qsmaskinit;
 		rnp->gpnum = rsp->gpnum;
+		rnp->completed = rsp->completed;
+		if (rnp == rdp->mynode)
+			rcu_start_gp_per_cpu(rsp, rnp, rdp);
 		spin_unlock(&rnp->lock);	/* irqs remain disabled. */
 	}
 
@@ -672,34 +740,6 @@
 }
 
 /*
- * Advance this CPU's callbacks, but only if the current grace period
- * has ended.  This may be called only from the CPU to whom the rdp
- * belongs.
- */
-static void
-rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp)
-{
-	long completed_snap;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	completed_snap = ACCESS_ONCE(rsp->completed);  /* outside of lock. */
-
-	/* Did another grace period end? */
-	if (rdp->completed != completed_snap) {
-
-		/* Advance callbacks.  No harm if list empty. */
-		rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL];
-		rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL];
-		rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
-
-		/* Remember that we saw this grace-period completion. */
-		rdp->completed = completed_snap;
-	}
-	local_irq_restore(flags);
-}
-
-/*
  * Clean up after the prior grace period and let rcu_start_gp() start up
  * the next grace period if one is needed.  Note that the caller must
  * hold rnp->lock, as required by rcu_start_gp(), which will release it.
@@ -710,7 +750,6 @@
 	WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
 	rsp->completed = rsp->gpnum;
 	rsp->signaled = RCU_GP_IDLE;
-	rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]);
 	rcu_start_gp(rsp, flags);  /* releases root node's rnp->lock. */
 }
 
@@ -1144,6 +1183,7 @@
 	long lastcomp;
 	struct rcu_node *rnp = rcu_get_root(rsp);
 	u8 signaled;
+	u8 forcenow;
 
 	if (!rcu_gp_in_progress(rsp))
 		return;  /* No grace period in progress, nothing to force. */
@@ -1180,16 +1220,23 @@
 		if (rcu_process_dyntick(rsp, lastcomp,
 					dyntick_save_progress_counter))
 			goto unlock_ret;
+		/* fall into next case. */
+
+	case RCU_SAVE_COMPLETED:
 
 		/* Update state, record completion counter. */
+		forcenow = 0;
 		spin_lock(&rnp->lock);
 		if (lastcomp == rsp->completed &&
-		    rsp->signaled == RCU_SAVE_DYNTICK) {
+		    rsp->signaled == signaled) {
 			rsp->signaled = RCU_FORCE_QS;
 			dyntick_record_completed(rsp, lastcomp);
+			forcenow = signaled == RCU_SAVE_COMPLETED;
 		}
 		spin_unlock(&rnp->lock);
-		break;
+		if (!forcenow)
+			break;
+		/* fall into next case. */
 
 	case RCU_FORCE_QS:
 
@@ -1544,21 +1591,16 @@
 rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
 {
 	unsigned long flags;
-	long lastcomp;
 	unsigned long mask;
 	struct rcu_data *rdp = rsp->rda[cpu];
 	struct rcu_node *rnp = rcu_get_root(rsp);
 
 	/* Set up local state, ensuring consistent view of global state. */
 	spin_lock_irqsave(&rnp->lock, flags);
-	lastcomp = rsp->completed;
-	rdp->completed = lastcomp;
-	rdp->gpnum = lastcomp;
 	rdp->passed_quiesc = 0;  /* We could be racing with new GP, */
 	rdp->qs_pending = 1;	 /*  so set up to respond to current GP. */
 	rdp->beenonline = 1;	 /* We have now been online. */
 	rdp->preemptable = preemptable;
-	rdp->passed_quiesc_completed = lastcomp - 1;
 	rdp->qlen_last_fqs_check = 0;
 	rdp->n_force_qs_snap = rsp->n_force_qs;
 	rdp->blimit = blimit;
@@ -1580,6 +1622,11 @@
 		spin_lock(&rnp->lock);	/* irqs already disabled. */
 		rnp->qsmaskinit |= mask;
 		mask = rnp->grpmask;
+		if (rnp == rdp->mynode) {
+			rdp->gpnum = rnp->completed; /* if GP in progress... */
+			rdp->completed = rnp->completed;
+			rdp->passed_quiesc_completed = rnp->completed - 1;
+		}
 		spin_unlock(&rnp->lock); /* irqs already disabled. */
 		rnp = rnp->parent;
 	} while (rnp != NULL && !(rnp->qsmaskinit & mask));
--- linux-ec2-2.6.32.orig/kernel/groups.c
+++ linux-ec2-2.6.32/kernel/groups.c
@@ -143,10 +143,9 @@
 	right = group_info->ngroups;
 	while (left < right) {
 		unsigned int mid = (left+right)/2;
-		int cmp = grp - GROUP_AT(group_info, mid);
-		if (cmp > 0)
+		if (grp > GROUP_AT(group_info, mid))
 			left = mid + 1;
-		else if (cmp < 0)
+		else if (grp < GROUP_AT(group_info, mid))
 			right = mid;
 		else
 			return 1;
--- linux-ec2-2.6.32.orig/kernel/kexec.c
+++ linux-ec2-2.6.32/kernel/kexec.c
@@ -38,12 +38,18 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 
+#ifndef CONFIG_XEN
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t* crash_notes;
+#endif
 
 /* vmcoreinfo stuff */
 static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
-u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+u32
+#if defined(CONFIG_XEN) && defined(CONFIG_X86)
+__page_aligned_bss
+#endif
+vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 size_t vmcoreinfo_size;
 size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
@@ -352,13 +358,26 @@
 	return 0;
 }
 
-static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
+static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order, unsigned long limit)
 {
 	struct page *pages;
 
 	pages = alloc_pages(gfp_mask, order);
 	if (pages) {
 		unsigned int count, i;
+#ifdef CONFIG_XEN
+		int address_bits;
+
+		if (limit == ~0UL)
+			address_bits = BITS_PER_LONG;
+		else
+			address_bits = ilog2(limit);
+
+		if (xen_limit_pages_to_max_mfn(pages, order, address_bits) < 0) {
+			__free_pages(pages, order);
+			return NULL;
+		}
+#endif
 		pages->mapping = NULL;
 		set_page_private(pages, order);
 		count = 1 << order;
@@ -422,10 +441,10 @@
 	do {
 		unsigned long pfn, epfn, addr, eaddr;
 
-		pages = kimage_alloc_pages(GFP_KERNEL, order);
+		pages = kimage_alloc_pages(GFP_KERNEL, order, KEXEC_CONTROL_MEMORY_LIMIT);
 		if (!pages)
 			break;
-		pfn   = page_to_pfn(pages);
+		pfn   = kexec_page_to_pfn(pages);
 		epfn  = pfn + count;
 		addr  = pfn << PAGE_SHIFT;
 		eaddr = epfn << PAGE_SHIFT;
@@ -459,6 +478,7 @@
 	return pages;
 }
 
+#ifndef CONFIG_XEN
 static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
 						      unsigned int order)
 {
@@ -512,7 +532,7 @@
 		}
 		/* If I don't overlap any segments I have found my hole! */
 		if (i == image->nr_segments) {
-			pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+			pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
 			break;
 		}
 	}
@@ -539,6 +559,13 @@
 
 	return pages;
 }
+#else /* !CONFIG_XEN */
+struct page *kimage_alloc_control_pages(struct kimage *image,
+					 unsigned int order)
+{
+	return kimage_alloc_normal_control_pages(image, order);
+}
+#endif
 
 static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
 {
@@ -554,7 +581,7 @@
 			return -ENOMEM;
 
 		ind_page = page_address(page);
-		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+		*image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
 		image->entry = ind_page;
 		image->last_entry = ind_page +
 				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -613,13 +640,13 @@
 #define for_each_kimage_entry(image, ptr, entry) \
 	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
 		ptr = (entry & IND_INDIRECTION)? \
-			phys_to_virt((entry & PAGE_MASK)): ptr +1)
+			kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
 
 static void kimage_free_entry(kimage_entry_t entry)
 {
 	struct page *page;
 
-	page = pfn_to_page(entry >> PAGE_SHIFT);
+	page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
 	kimage_free_pages(page);
 }
 
@@ -631,6 +658,10 @@
 	if (!image)
 		return;
 
+#ifdef CONFIG_XEN
+	xen_machine_kexec_unload(image);
+#endif
+
 	kimage_free_extra_pages(image);
 	for_each_kimage_entry(image, ptr, entry) {
 		if (entry & IND_INDIRECTION) {
@@ -706,7 +737,7 @@
 	 * have a match.
 	 */
 	list_for_each_entry(page, &image->dest_pages, lru) {
-		addr = page_to_pfn(page) << PAGE_SHIFT;
+		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
 		if (addr == destination) {
 			list_del(&page->lru);
 			return page;
@@ -717,16 +748,16 @@
 		kimage_entry_t *old;
 
 		/* Allocate a page, if we run out of memory give up */
-		page = kimage_alloc_pages(gfp_mask, 0);
+		page = kimage_alloc_pages(gfp_mask, 0, KEXEC_SOURCE_MEMORY_LIMIT);
 		if (!page)
 			return NULL;
 		/* If the page cannot be used file it away */
-		if (page_to_pfn(page) >
+		if (kexec_page_to_pfn(page) >
 				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
 			list_add(&page->lru, &image->unuseable_pages);
 			continue;
 		}
-		addr = page_to_pfn(page) << PAGE_SHIFT;
+		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
 
 		/* If it is the destination page we want use it */
 		if (addr == destination)
@@ -749,7 +780,7 @@
 			struct page *old_page;
 
 			old_addr = *old & PAGE_MASK;
-			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+			old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
 			copy_highpage(page, old_page);
 			*old = addr | (*old & ~PAGE_MASK);
 
@@ -805,7 +836,7 @@
 			result  = -ENOMEM;
 			goto out;
 		}
-		result = kimage_add_page(image, page_to_pfn(page)
+		result = kimage_add_page(image, kexec_page_to_pfn(page)
 								<< PAGE_SHIFT);
 		if (result < 0)
 			goto out;
@@ -837,6 +868,7 @@
 	return result;
 }
 
+#ifndef CONFIG_XEN
 static int kimage_load_crash_segment(struct kimage *image,
 					struct kexec_segment *segment)
 {
@@ -859,7 +891,7 @@
 		char *ptr;
 		size_t uchunk, mchunk;
 
-		page = pfn_to_page(maddr >> PAGE_SHIFT);
+		page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
 		if (!page) {
 			result  = -ENOMEM;
 			goto out;
@@ -908,6 +940,13 @@
 
 	return result;
 }
+#else /* CONFIG_XEN */
+static int kimage_load_segment(struct kimage *image,
+				struct kexec_segment *segment)
+{
+	return kimage_load_normal_segment(image, segment);
+}
+#endif
 
 /*
  * Exec Kernel system call: for obvious reasons only root may call it.
@@ -1011,6 +1050,13 @@
 		}
 		kimage_terminate(image);
 	}
+#ifdef CONFIG_XEN
+	if (image) {
+		result = xen_machine_kexec_load(image);
+		if (result)
+			goto out;
+	}
+#endif
 	/* Install the new kernel, and  Uninstall the old */
 	image = xchg(dest_image, image);
 
@@ -1110,6 +1156,7 @@
 	memcpy(buf, &note, sizeof(note));
 }
 
+#ifndef CONFIG_XEN
 void crash_save_cpu(struct pt_regs *regs, int cpu)
 {
 	struct elf_prstatus prstatus;
@@ -1135,9 +1182,11 @@
 		      	      &prstatus, sizeof(prstatus));
 	final_note(buf);
 }
+#endif
 
 static int __init crash_notes_memory_init(void)
 {
+#ifndef CONFIG_XEN
 	/* Allocate memory for saving cpu registers. */
 	crash_notes = alloc_percpu(note_buf_t);
 	if (!crash_notes) {
@@ -1145,11 +1194,13 @@
 		" states failed\n");
 		return -ENOMEM;
 	}
+#endif
 	return 0;
 }
 module_init(crash_notes_memory_init)
 
 
+#ifndef CONFIG_XEN
 /*
  * parsing the "crashkernel" commandline
  *
@@ -1312,7 +1363,7 @@
 
 	return 0;
 }
-
+#endif
 
 
 void crash_save_vmcoreinfo(void)
@@ -1369,7 +1420,18 @@
 
 	VMCOREINFO_SYMBOL(init_uts_ns);
 	VMCOREINFO_SYMBOL(node_online_map);
+#ifndef CONFIG_X86_XEN
 	VMCOREINFO_SYMBOL(swapper_pg_dir);
+#else
+/*
+ * Since for x86-32 Xen swapper_pg_dir is a pointer rather than an array,
+ * make the value stored consistent with native (i.e. the base address of
+ * the page directory).
+ */
+# define swapper_pg_dir *swapper_pg_dir
+	VMCOREINFO_SYMBOL(swapper_pg_dir);
+# undef swapper_pg_dir
+#endif
 	VMCOREINFO_SYMBOL(_stext);
 	VMCOREINFO_SYMBOL(vmlist);
 
--- linux-ec2-2.6.32.orig/kernel/exit.c
+++ linux-ec2-2.6.32/kernel/exit.c
@@ -54,7 +54,6 @@
 #include <asm/unistd.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include "cred-internals.h"
 
 static void exit_mm(struct task_struct * tsk);
 
@@ -92,6 +91,14 @@
 		posix_cpu_timers_exit_group(tsk);
 	else {
 		/*
+		 * This can only happen if the caller is de_thread().
+		 * FIXME: this is the temporary hack, we should teach
+		 * posix-cpu-timers to handle this case correctly.
+		 */
+		if (unlikely(has_group_leader_pid(tsk)))
+			posix_cpu_timers_exit_group(tsk);
+
+		/*
 		 * If there is any task waiting for the group exit
 		 * then notify it:
 		 */
@@ -110,8 +117,8 @@
 		 * We won't ever get here for the group leader, since it
 		 * will have been the last reference on the signal_struct.
 		 */
-		sig->utime = cputime_add(sig->utime, task_utime(tsk));
-		sig->stime = cputime_add(sig->stime, task_stime(tsk));
+		sig->utime = cputime_add(sig->utime, tsk->utime);
+		sig->stime = cputime_add(sig->stime, tsk->stime);
 		sig->gtime = cputime_add(sig->gtime, task_gtime(tsk));
 		sig->min_flt += tsk->min_flt;
 		sig->maj_flt += tsk->maj_flt;
@@ -899,6 +906,15 @@
 	if (unlikely(!tsk->pid))
 		panic("Attempted to kill the idle task!");
 
+	/*
+	 * If do_exit is called because this processes oopsed, it's possible
+	 * that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
+	 * continuing. Amongst other possible reasons, this is to prevent
+	 * mm_release()->clear_child_tid() from writing to a user-controlled
+	 * kernel address.
+	 */
+	set_fs(USER_DS);
+
 	tracehook_report_exit(&code);
 
 	validate_creds_for_do_exit(tsk);
@@ -1205,6 +1221,7 @@
 		struct signal_struct *psig;
 		struct signal_struct *sig;
 		unsigned long maxrss;
+		cputime_t tgutime, tgstime;
 
 		/*
 		 * The resource counters for the group leader are in its
@@ -1220,20 +1237,23 @@
 		 * need to protect the access to parent->signal fields,
 		 * as other threads in the parent group can be right
 		 * here reaping other children at the same time.
+		 *
+		 * We use thread_group_times() to get times for the thread
+		 * group, which consolidates times for all threads in the
+		 * group including the group leader.
 		 */
+		thread_group_times(p, &tgutime, &tgstime);
 		spin_lock_irq(&p->real_parent->sighand->siglock);
 		psig = p->real_parent->signal;
 		sig = p->signal;
 		psig->cutime =
 			cputime_add(psig->cutime,
-			cputime_add(p->utime,
-			cputime_add(sig->utime,
-				    sig->cutime)));
+			cputime_add(tgutime,
+				    sig->cutime));
 		psig->cstime =
 			cputime_add(psig->cstime,
-			cputime_add(p->stime,
-			cputime_add(sig->stime,
-				    sig->cstime)));
+			cputime_add(tgstime,
+				    sig->cstime));
 		psig->cgtime =
 			cputime_add(psig->cgtime,
 			cputime_add(p->gtime,
@@ -1370,8 +1390,7 @@
 	if (!unlikely(wo->wo_flags & WNOWAIT))
 		*p_code = 0;
 
-	/* don't need the RCU readlock here as we're holding a spinlock */
-	uid = __task_cred(p)->uid;
+	uid = task_uid(p);
 unlock_sig:
 	spin_unlock_irq(&p->sighand->siglock);
 	if (!exit_code)
@@ -1444,7 +1463,7 @@
 	}
 	if (!unlikely(wo->wo_flags & WNOWAIT))
 		p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
-	uid = __task_cred(p)->uid;
+	uid = task_uid(p);
 	spin_unlock_irq(&p->sighand->siglock);
 
 	pid = task_pid_vnr(p);
--- linux-ec2-2.6.32.orig/kernel/posix-timers.c
+++ linux-ec2-2.6.32/kernel/posix-timers.c
@@ -559,14 +559,7 @@
 	new_timer->it_id = (timer_t) new_timer_id;
 	new_timer->it_clock = which_clock;
 	new_timer->it_overrun = -1;
-	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
-	if (error)
-		goto out;
 
-	/*
-	 * return the timer_id now.  The next step is hard to
-	 * back out if there is an error.
-	 */
 	if (copy_to_user(created_timer_id,
 			 &new_timer_id, sizeof (new_timer_id))) {
 		error = -EFAULT;
@@ -597,6 +590,10 @@
 	new_timer->sigq->info.si_tid   = new_timer->it_id;
 	new_timer->sigq->info.si_code  = SI_TIMER;
 
+	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+	if (error)
+		goto out;
+
 	spin_lock_irq(&current->sighand->siglock);
 	new_timer->it_signal = current->signal;
 	list_add(&new_timer->list, &current->signal->posix_timers);
--- linux-ec2-2.6.32.orig/kernel/fork.c
+++ linux-ec2-2.6.32/kernel/fork.c
@@ -277,7 +277,7 @@
 #ifdef CONFIG_MMU
 static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 {
-	struct vm_area_struct *mpnt, *tmp, **pprev;
+	struct vm_area_struct *mpnt, *tmp, *prev, **pprev;
 	struct rb_node **rb_link, *rb_parent;
 	int retval;
 	unsigned long charge;
@@ -305,6 +305,7 @@
 	if (retval)
 		goto out;
 
+	prev = NULL;
 	for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) {
 		struct file *file;
 
@@ -333,7 +334,7 @@
 		vma_set_policy(tmp, pol);
 		tmp->vm_flags &= ~VM_LOCKED;
 		tmp->vm_mm = mm;
-		tmp->vm_next = NULL;
+		tmp->vm_next = tmp->vm_prev = NULL;
 		anon_vma_link(tmp);
 		file = tmp->vm_file;
 		if (file) {
@@ -367,6 +368,8 @@
 		 */
 		*pprev = tmp;
 		pprev = &tmp->vm_next;
+		tmp->vm_prev = prev;
+		prev = tmp;
 
 		__vma_link_rb(mm, tmp, rb_link, rb_parent);
 		rb_link = &tmp->vm_rb.rb_right;
@@ -884,6 +887,9 @@
 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
 	sig->gtime = cputime_zero;
 	sig->cgtime = cputime_zero;
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+	sig->prev_utime = sig->prev_stime = cputime_zero;
+#endif
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
 	sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
@@ -1123,8 +1129,6 @@
 
 	p->bts = NULL;
 
-	p->stack_start = stack_start;
-
 	/* Perform scheduler related setup. Assign this task to a CPU. */
 	sched_fork(p, clone_flags);
 
@@ -1229,21 +1233,6 @@
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 
-	/*
-	 * The task hasn't been attached yet, so its cpus_allowed mask will
-	 * not be changed, nor will its assigned CPU.
-	 *
-	 * The cpus_allowed mask of the parent may have changed after it was
-	 * copied first time - so re-copy it here, then check the child's CPU
-	 * to ensure it is on a valid CPU (and if not, just force it back to
-	 * parent's CPU). This avoids alot of nasty races.
-	 */
-	p->cpus_allowed = current->cpus_allowed;
-	p->rt.nr_cpus_allowed = current->rt.nr_cpus_allowed;
-	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) ||
-			!cpu_online(task_cpu(p))))
-		set_task_cpu(p, smp_processor_id());
-
 	/* CLONE_PARENT re-uses the old parent */
 	if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
 		p->real_parent = current->real_parent;
--- linux-ec2-2.6.32.orig/kernel/printk.c
+++ linux-ec2-2.6.32/kernel/printk.c
@@ -33,6 +33,7 @@
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
 #include <linux/kexec.h>
+#include <linux/syslog.h>
 
 #include <asm/uaccess.h>
 
@@ -271,14 +272,14 @@
  *	9 -- Return number of unread characters in the log buffer
  *     10 -- Return size of the log buffer
  */
-int do_syslog(int type, char __user *buf, int len)
+int do_syslog(int type, char __user *buf, int len, bool from_file)
 {
 	unsigned i, j, limit, count;
 	int do_clear = 0;
 	char c;
 	int error = 0;
 
-	error = security_syslog(type);
+	error = security_syslog(type, from_file);
 	if (error)
 		return error;
 
@@ -415,7 +416,7 @@
 
 SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
 {
-	return do_syslog(type, buf, len);
+	return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
 }
 
 /*
@@ -1014,6 +1015,8 @@
 
 int printk_needs_cpu(int cpu)
 {
+	if (unlikely(cpu_is_offline(cpu)))
+		printk_tick();
 	return per_cpu(printk_pending, cpu);
 }
 
--- linux-ec2-2.6.32.orig/kernel/mutex.c
+++ linux-ec2-2.6.32/kernel/mutex.c
@@ -172,6 +172,13 @@
 		struct thread_info *owner;
 
 		/*
+		 * If we own the BKL, then don't spin. The owner of
+		 * the mutex might be waiting on us to release the BKL.
+		 */
+		if (unlikely(current->lock_depth >= 0))
+			break;
+
+		/*
 		 * If there's an owner, wait for it to either
 		 * release the lock or go to sleep.
 		 */
--- linux-ec2-2.6.32.orig/kernel/timer.c
+++ linux-ec2-2.6.32/kernel/timer.c
@@ -1044,7 +1044,7 @@
 	spin_unlock_irq(&base->lock);
 }
 
-#ifdef CONFIG_NO_HZ
+#if defined(CONFIG_NO_HZ) || defined(CONFIG_NO_IDLE_HZ)
 /*
  * Find out when the next timer event is due to happen. This
  * is used on S/390 to stop all activity when a CPU is idle.
@@ -1173,6 +1173,12 @@
 	struct tvec_base *base = __get_cpu_var(tvec_bases);
 	unsigned long expires;
 
+	/*
+	 * Pretend that there is no timer pending if the cpu is offline.
+	 * Possible pending timers will be migrated later to an active cpu.
+	 */
+	if (cpu_is_offline(smp_processor_id()))
+		return now + NEXT_TIMER_MAX_DELTA;
 	spin_lock(&base->lock);
 	if (time_before_eq(base->next_timer, base->timer_jiffies))
 		base->next_timer = __next_timer_interrupt(base);
--- linux-ec2-2.6.32.orig/kernel/signal.c
+++ linux-ec2-2.6.32/kernel/signal.c
@@ -591,7 +591,7 @@
 static int check_kill_permission(int sig, struct siginfo *info,
 				 struct task_struct *t)
 {
-	const struct cred *cred = current_cred(), *tcred;
+	const struct cred *cred, *tcred;
 	struct pid *sid;
 	int error;
 
@@ -605,8 +605,10 @@
 	if (error)
 		return error;
 
+	cred = current_cred();
 	tcred = __task_cred(t);
-	if ((cred->euid ^ tcred->suid) &&
+	if (!same_thread_group(current, t) &&
+	    (cred->euid ^ tcred->suid) &&
 	    (cred->euid ^ tcred->uid) &&
 	    (cred->uid  ^ tcred->suid) &&
 	    (cred->uid  ^ tcred->uid) &&
@@ -939,7 +941,8 @@
 		for (i = 0; i < 16; i++) {
 			unsigned char insn;
 
-			__get_user(insn, (unsigned char *)(regs->ip + i));
+			if (get_user(insn, (unsigned char *)(regs->ip + i)))
+				break;
 			printk("%02x ", insn);
 		}
 	}
@@ -2348,9 +2351,13 @@
 		return -EFAULT;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info.si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info.si_code >= 0 || info.si_code == SI_TKILL) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info.si_code < 0);
 		return -EPERM;
+	}
 	info.si_signo = sig;
 
 	/* POSIX.1b doesn't mention process groups.  */
@@ -2364,9 +2371,13 @@
 		return -EINVAL;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info->si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info->si_code >= 0 || info->si_code == SI_TKILL) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info->si_code < 0);
 		return -EPERM;
+	}
 	info->si_signo = sig;
 
 	return do_send_specific(tgid, pid, sig, info);
--- linux-ec2-2.6.32.orig/kernel/sysctl.c
+++ linux-ec2-2.6.32/kernel/sysctl.c
@@ -762,6 +762,7 @@
 		.mode           = 0644,
 		.proc_handler   = &proc_dointvec,
 	},
+#ifdef ARCH_HAS_NMI_WATCHDOG
 	{
 		.procname       = "nmi_watchdog",
 		.data           = &nmi_watchdog_enabled,
@@ -770,6 +771,7 @@
 		.proc_handler   = &proc_nmi_enabled,
 	},
 #endif
+#endif
 #if defined(CONFIG_X86)
 	{
 		.ctl_name	= KERN_PANIC_ON_NMI,
@@ -840,7 +842,7 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
-#if	defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
+#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) && !defined(CONFIG_ACPI_PV_SLEEP)
 	{
 		.procname	= "acpi_video_flags",
 		.data		= &acpi_realmode_flags,
@@ -1345,6 +1347,7 @@
 		.strategy	= &sysctl_jiffies,
 	},
 #endif
+#ifdef CONFIG_MMU
 	{
 		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "mmap_min_addr",
@@ -1353,6 +1356,7 @@
 		.mode		= 0644,
 		.proc_handler	= &mmap_min_addr_handler,
 	},
+#endif
 #ifdef CONFIG_NUMA
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -1398,6 +1402,18 @@
 		.mode		= 0644,
 		.proc_handler	= &scan_unevictable_handler,
 	},
+#ifdef CONFIG_PRESWAP
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "preswap",
+		.data		= NULL,
+		.maxlen		= sizeof(unsigned long),
+		.mode		= 0644,
+		.proc_handler	= &preswap_sysctl_handler,
+		.extra1		= (void *)&preswap_zero,
+		.extra2		= (void *)&preswap_infinity,
+	},
+#endif
 #ifdef CONFIG_MEMORY_FAILURE
 	{
 		.ctl_name	= CTL_UNNUMBERED,
@@ -1605,7 +1621,8 @@
 		.data		= &show_unhandled_signals,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
 	},
 #endif
 	{ .ctl_name = 0 }
--- linux-ec2-2.6.32.orig/kernel/smp.c
+++ linux-ec2-2.6.32/kernel/smp.c
@@ -193,6 +193,24 @@
 	list_for_each_entry_rcu(data, &call_function.queue, csd.list) {
 		int refs;
 
+		/*
+		 * Since we walk the list without any locks, we might
+		 * see an entry that was completed, removed from the
+		 * list and is in the process of being reused.
+		 *
+		 * We must check that the cpu is in the cpumask before
+		 * checking the refs, and both must be set before
+		 * executing the callback on this cpu.
+		 */
+
+		if (!cpumask_test_cpu(cpu, data->cpumask))
+			continue;
+
+		smp_rmb();
+
+		if (atomic_read(&data->refs) == 0)
+			continue;
+
 		if (!cpumask_test_and_clear_cpu(cpu, data->cpumask))
 			continue;
 
@@ -201,6 +219,8 @@
 		refs = atomic_dec_return(&data->refs);
 		WARN_ON(refs < 0);
 		if (!refs) {
+			WARN_ON(!cpumask_empty(data->cpumask));
+
 			spin_lock(&call_function.lock);
 			list_del_rcu(&data->csd.list);
 			spin_unlock(&call_function.lock);
@@ -368,7 +388,7 @@
 {
 	struct call_function_data *data;
 	unsigned long flags;
-	int cpu, next_cpu, this_cpu = smp_processor_id();
+	int refs, cpu, next_cpu, this_cpu = smp_processor_id();
 
 	/*
 	 * Can deadlock when called with interrupts disabled.
@@ -379,7 +399,7 @@
 	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
 		     && !oops_in_progress);
 
-	/* So, what's a CPU they want? Ignoring this one. */
+	/* Try to fastpath.  So, what's a CPU they want? Ignoring this one. */
 	cpu = cpumask_first_and(mask, cpu_online_mask);
 	if (cpu == this_cpu)
 		cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
@@ -402,11 +422,48 @@
 	data = &__get_cpu_var(cfd_data);
 	csd_lock(&data->csd);
 
+	/* This BUG_ON verifies our reuse assertions and can be removed */
+	BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask));
+
+	/*
+	 * The global call function queue list add and delete are protected
+	 * by a lock, but the list is traversed without any lock, relying
+	 * on the rcu list add and delete to allow safe concurrent traversal.
+	 * We reuse the call function data without waiting for any grace
+	 * period after some other cpu removes it from the global queue.
+	 * This means a cpu might find our data block as it is being
+	 * filled out.
+	 *
+	 * We hold off the interrupt handler on the other cpu by
+	 * ordering our writes to the cpu mask vs our setting of the
+	 * refs counter.  We assert only the cpu owning the data block
+	 * will set a bit in cpumask, and each bit will only be cleared
+	 * by the subject cpu.  Each cpu must first find its bit is
+	 * set and then check that refs is set indicating the element is
+	 * ready to be processed, otherwise it must skip the entry.
+	 *
+	 * On the previous iteration refs was set to 0 by another cpu.
+	 * To avoid the use of transitivity, set the counter to 0 here
+	 * so the wmb will pair with the rmb in the interrupt handler.
+	 */
+	atomic_set(&data->refs, 0);	/* convert 3rd to 1st party write */
+
 	data->csd.func = func;
 	data->csd.info = info;
+
+	/* Ensure 0 refs is visible before mask.  Also orders func and info */
+	smp_wmb();
+
+	/* We rely on the "and" being processed before the store */
 	cpumask_and(data->cpumask, mask, cpu_online_mask);
 	cpumask_clear_cpu(this_cpu, data->cpumask);
-	atomic_set(&data->refs, cpumask_weight(data->cpumask));
+	refs = cpumask_weight(data->cpumask);
+
+	/* Some callers race with other cpus changing the passed mask */
+	if (unlikely(!refs)) {
+		csd_unlock(&data->csd);
+		return;
+	}
 
 	spin_lock_irqsave(&call_function.lock, flags);
 	/*
@@ -415,6 +472,12 @@
 	 * will not miss any other list entries:
 	 */
 	list_add_rcu(&data->csd.list, &call_function.queue);
+	/*
+	 * We rely on the wmb() in list_add_rcu to complete our writes
+	 * to the cpumask before this write to refs, which indicates
+	 * data is on the list and is ready to be processed.
+	 */
+	atomic_set(&data->refs, refs);
 	spin_unlock_irqrestore(&call_function.lock, flags);
 
 	/*
--- linux-ec2-2.6.32.orig/kernel/sys.c
+++ linux-ec2-2.6.32/kernel/sys.c
@@ -567,11 +567,6 @@
 	if (!new_user)
 		return -EAGAIN;
 
-	if (!task_can_switch_user(new_user, current)) {
-		free_uid(new_user);
-		return -EINVAL;
-	}
-
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
 			new_user != INIT_USER) {
@@ -911,16 +906,15 @@
 
 void do_sys_times(struct tms *tms)
 {
-	struct task_cputime cputime;
-	cputime_t cutime, cstime;
+	cputime_t tgutime, tgstime, cutime, cstime;
 
-	thread_group_cputime(current, &cputime);
 	spin_lock_irq(&current->sighand->siglock);
+	thread_group_times(current, &tgutime, &tgstime);
 	cutime = current->signal->cutime;
 	cstime = current->signal->cstime;
 	spin_unlock_irq(&current->sighand->siglock);
-	tms->tms_utime = cputime_to_clock_t(cputime.utime);
-	tms->tms_stime = cputime_to_clock_t(cputime.stime);
+	tms->tms_utime = cputime_to_clock_t(tgutime);
+	tms->tms_stime = cputime_to_clock_t(tgstime);
 	tms->tms_cutime = cputime_to_clock_t(cutime);
 	tms->tms_cstime = cputime_to_clock_t(cstime);
 }
@@ -963,6 +957,7 @@
 		pgid = pid;
 	if (pgid < 0)
 		return -EINVAL;
+	rcu_read_lock();
 
 	/* From this point forward we keep holding onto the tasklist lock
 	 * so that our parent does not change from under us. -DaveM
@@ -1016,6 +1011,7 @@
 out:
 	/* All paths lead to here, thus we are safe. -DaveM */
 	write_unlock_irq(&tasklist_lock);
+	rcu_read_unlock();
 	return err;
 }
 
@@ -1338,8 +1334,7 @@
 {
 	struct task_struct *t;
 	unsigned long flags;
-	cputime_t utime, stime;
-	struct task_cputime cputime;
+	cputime_t tgutime, tgstime, utime, stime;
 	unsigned long maxrss = 0;
 
 	memset((char *) r, 0, sizeof *r);
@@ -1373,9 +1368,9 @@
 				break;
 
 		case RUSAGE_SELF:
-			thread_group_cputime(p, &cputime);
-			utime = cputime_add(utime, cputime.utime);
-			stime = cputime_add(stime, cputime.stime);
+			thread_group_times(p, &tgutime, &tgstime);
+			utime = cputime_add(utime, tgutime);
+			stime = cputime_add(stime, tgstime);
 			r->ru_nvcsw += p->signal->nvcsw;
 			r->ru_nivcsw += p->signal->nivcsw;
 			r->ru_minflt += p->signal->min_flt;
--- linux-ec2-2.6.32.orig/kernel/delayacct.c
+++ linux-ec2-2.6.32/kernel/delayacct.c
@@ -20,15 +20,15 @@
 #include <linux/sysctl.h>
 #include <linux/delayacct.h>
 
-int delayacct_on __read_mostly = 1;	/* Delay accounting turned on/off */
+int delayacct_on __read_mostly = 0;	/* Delay accounting turned on/off */
 struct kmem_cache *delayacct_cache;
 
-static int __init delayacct_setup_disable(char *str)
+static int __init delayacct_setup_enable(char *str)
 {
-	delayacct_on = 0;
+	delayacct_on = 1;
 	return 1;
 }
-__setup("nodelayacct", delayacct_setup_disable);
+__setup("delayacct", delayacct_setup_enable);
 
 void delayacct_init(void)
 {
--- linux-ec2-2.6.32.orig/kernel/sched_debug.c
+++ linux-ec2-2.6.32/kernel/sched_debug.c
@@ -173,11 +173,6 @@
 	task_group_path(tg, path, sizeof(path));
 
 	SEQ_printf(m, "\ncfs_rq[%d]:%s\n", cpu, path);
-#elif defined(CONFIG_USER_SCHED) && defined(CONFIG_FAIR_GROUP_SCHED)
-	{
-		uid_t uid = cfs_rq->tg->uid;
-		SEQ_printf(m, "\ncfs_rq[%d] for UID: %u\n", cpu, uid);
-	}
 #else
 	SEQ_printf(m, "\ncfs_rq[%d]:\n", cpu);
 #endif
@@ -285,12 +280,16 @@
 
 #ifdef CONFIG_SCHEDSTATS
 #define P(n) SEQ_printf(m, "  .%-30s: %d\n", #n, rq->n);
+#define P64(n) SEQ_printf(m, "  .%-30s: %Ld\n", #n, rq->n);
 
 	P(yld_count);
 
 	P(sched_switch);
 	P(sched_count);
 	P(sched_goidle);
+#ifdef CONFIG_SMP
+	P64(avg_idle);
+#endif
 
 	P(ttwu_count);
 	P(ttwu_local);
@@ -419,7 +418,6 @@
 	P(se.nr_failed_migrations_running);
 	P(se.nr_failed_migrations_hot);
 	P(se.nr_forced_migrations);
-	P(se.nr_forced2_migrations);
 	P(se.nr_wakeups);
 	P(se.nr_wakeups_sync);
 	P(se.nr_wakeups_migrate);
@@ -495,7 +493,6 @@
 	p->se.nr_failed_migrations_running	= 0;
 	p->se.nr_failed_migrations_hot		= 0;
 	p->se.nr_forced_migrations		= 0;
-	p->se.nr_forced2_migrations		= 0;
 	p->se.nr_wakeups			= 0;
 	p->se.nr_wakeups_sync			= 0;
 	p->se.nr_wakeups_migrate		= 0;
--- linux-ec2-2.6.32.orig/kernel/audit_tree.c
+++ linux-ec2-2.6.32/kernel/audit_tree.c
@@ -277,7 +277,7 @@
 		owner->root = NULL;
 	}
 
-	for (i = j = 0; i < size; i++, j++) {
+	for (i = j = 0; j <= size; i++, j++) {
 		struct audit_tree *s;
 		if (&chunk->owners[j] == p) {
 			list_del_init(&p->list);
@@ -290,7 +290,7 @@
 		if (!s) /* result of earlier fallback */
 			continue;
 		get_tree(s);
-		list_replace_init(&chunk->owners[i].list, &new->owners[j].list);
+		list_replace_init(&chunk->owners[j].list, &new->owners[i].list);
 	}
 
 	list_replace_rcu(&chunk->hash, &new->hash);
@@ -373,15 +373,17 @@
 	for (n = 0; n < old->count; n++) {
 		if (old->owners[n].owner == tree) {
 			spin_unlock(&hash_lock);
-			put_inotify_watch(watch);
+			put_inotify_watch(&old->watch);
 			return 0;
 		}
 	}
 	spin_unlock(&hash_lock);
 
 	chunk = alloc_chunk(old->count + 1);
-	if (!chunk)
+	if (!chunk) {
+		put_inotify_watch(&old->watch);
 		return -ENOMEM;
+	}
 
 	mutex_lock(&inode->inotify_mutex);
 	if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
@@ -425,7 +427,8 @@
 	spin_unlock(&hash_lock);
 	inotify_evict_watch(&old->watch);
 	mutex_unlock(&inode->inotify_mutex);
-	put_inotify_watch(&old->watch);
+	put_inotify_watch(&old->watch); /* pair to inotify_find_watch */
+	put_inotify_watch(&old->watch); /* and kill it */
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/kernel/Kconfig.preempt
+++ linux-ec2-2.6.32/kernel/Kconfig.preempt
@@ -35,6 +35,7 @@
 
 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)
--- linux-ec2-2.6.32.orig/kernel/ptrace.c
+++ linux-ec2-2.6.32/kernel/ptrace.c
@@ -314,7 +314,7 @@
 		child->exit_code = data;
 		dead = __ptrace_detach(current, child);
 		if (!child->exit_state)
-			wake_up_process(child);
+			wake_up_state(child, TASK_TRACED | TASK_STOPPED);
 	}
 	write_unlock_irq(&tasklist_lock);
 
--- linux-ec2-2.6.32.orig/kernel/sched_rt.c
+++ linux-ec2-2.6.32/kernel/sched_rt.c
@@ -194,7 +194,7 @@
 	return rt_se->my_q;
 }
 
-static void enqueue_rt_entity(struct sched_rt_entity *rt_se);
+static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head);
 static void dequeue_rt_entity(struct sched_rt_entity *rt_se);
 
 static void sched_rt_rq_enqueue(struct rt_rq *rt_rq)
@@ -204,7 +204,7 @@
 
 	if (rt_rq->rt_nr_running) {
 		if (rt_se && !on_rt_rq(rt_se))
-			enqueue_rt_entity(rt_se);
+			enqueue_rt_entity(rt_se, false);
 		if (rt_rq->highest_prio.curr < curr->prio)
 			resched_task(curr);
 	}
@@ -603,7 +603,7 @@
 	if (!task_has_rt_policy(curr))
 		return;
 
-	delta_exec = rq->clock - curr->se.exec_start;
+	delta_exec = rq->clock_task - curr->se.exec_start;
 	if (unlikely((s64)delta_exec < 0))
 		delta_exec = 0;
 
@@ -612,7 +612,7 @@
 	curr->se.sum_exec_runtime += delta_exec;
 	account_group_exec_runtime(curr, delta_exec);
 
-	curr->se.exec_start = rq->clock;
+	curr->se.exec_start = rq->clock_task;
 	cpuacct_charge(curr, delta_exec);
 
 	sched_rt_avg_update(rq, delta_exec);
@@ -803,7 +803,7 @@
 	dec_rt_group(rt_se, rt_rq);
 }
 
-static void __enqueue_rt_entity(struct sched_rt_entity *rt_se)
+static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
 {
 	struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
 	struct rt_prio_array *array = &rt_rq->active;
@@ -819,7 +819,10 @@
 	if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
 		return;
 
-	list_add_tail(&rt_se->run_list, queue);
+	if (head)
+		list_add(&rt_se->run_list, queue);
+	else
+		list_add_tail(&rt_se->run_list, queue);
 	__set_bit(rt_se_prio(rt_se), array->bitmap);
 
 	inc_rt_tasks(rt_se, rt_rq);
@@ -856,11 +859,11 @@
 	}
 }
 
-static void enqueue_rt_entity(struct sched_rt_entity *rt_se)
+static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
 {
 	dequeue_rt_stack(rt_se);
 	for_each_sched_rt_entity(rt_se)
-		__enqueue_rt_entity(rt_se);
+		__enqueue_rt_entity(rt_se, head);
 }
 
 static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
@@ -871,21 +874,22 @@
 		struct rt_rq *rt_rq = group_rt_rq(rt_se);
 
 		if (rt_rq && rt_rq->rt_nr_running)
-			__enqueue_rt_entity(rt_se);
+			__enqueue_rt_entity(rt_se, false);
 	}
 }
 
 /*
  * Adding/removing a task to/from a priority array:
  */
-static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
+static void
+enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, bool head)
 {
 	struct sched_rt_entity *rt_se = &p->rt;
 
 	if (wakeup)
 		rt_se->timeout = 0;
 
-	enqueue_rt_entity(rt_se);
+	enqueue_rt_entity(rt_se, head);
 
 	if (!task_current(rq, p) && p->rt.nr_cpus_allowed > 1)
 		enqueue_pushable_task(rq, p);
@@ -938,10 +942,9 @@
 #ifdef CONFIG_SMP
 static int find_lowest_rq(struct task_struct *task);
 
-static int select_task_rq_rt(struct task_struct *p, int sd_flag, int flags)
+static int
+select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
 {
-	struct rq *rq = task_rq(p);
-
 	if (sd_flag != SD_BALANCE_WAKE)
 		return smp_processor_id();
 
@@ -951,18 +954,19 @@
 	 * runqueue. Otherwise simply start this RT task
 	 * on its current runqueue.
 	 *
-	 * We want to avoid overloading runqueues. Even if
-	 * the RT task is of higher priority than the current RT task.
-	 * RT tasks behave differently than other tasks. If
-	 * one gets preempted, we try to push it off to another queue.
-	 * So trying to keep a preempting RT task on the same
-	 * cache hot CPU will force the running RT task to
-	 * a cold CPU. So we waste all the cache for the lower
-	 * RT task in hopes of saving some of a RT task
-	 * that is just being woken and probably will have
-	 * cold cache anyway.
+	 * We want to avoid overloading runqueues. If the woken
+	 * task is a higher priority, then it will stay on this CPU
+	 * and the lower prio task should be moved to another CPU.
+	 * Even though this will probably make the lower prio task
+	 * lose its cache, we do not want to bounce a higher task
+	 * around just because it gave up its CPU, perhaps for a
+	 * lock?
+	 *
+	 * For equal prio tasks, we just let the scheduler sort it out.
 	 */
 	if (unlikely(rt_task(rq->curr)) &&
+	    (rq->curr->rt.nr_cpus_allowed < 2 ||
+	     rq->curr->prio < p->prio) &&
 	    (p->rt.nr_cpus_allowed > 1)) {
 		int cpu = find_lowest_rq(p);
 
@@ -1065,7 +1069,7 @@
 	} while (rt_rq);
 
 	p = rt_task_of(rt_se);
-	p->se.exec_start = rq->clock;
+	p->se.exec_start = rq->clock_task;
 
 	return p;
 }
@@ -1485,12 +1489,15 @@
  * If we are not running and we are not going to reschedule soon, we should
  * try to push tasks away now
  */
-static void task_wake_up_rt(struct rq *rq, struct task_struct *p)
+static void task_woken_rt(struct rq *rq, struct task_struct *p)
 {
 	if (!task_running(rq, p) &&
 	    !test_tsk_need_resched(rq->curr) &&
 	    has_pushable_tasks(rq) &&
-	    p->rt.nr_cpus_allowed > 1)
+	    p->rt.nr_cpus_allowed > 1 &&
+	    rt_task(rq->curr) &&
+	    (rq->curr->rt.nr_cpus_allowed < 2 ||
+	     rq->curr->prio < p->prio))
 		push_rt_tasks(rq);
 }
 
@@ -1728,13 +1735,13 @@
 {
 	struct task_struct *p = rq->curr;
 
-	p->se.exec_start = rq->clock;
+	p->se.exec_start = rq->clock_task;
 
 	/* The running task is never eligible for pushing */
 	dequeue_pushable_task(rq, p);
 }
 
-unsigned int get_rr_interval_rt(struct task_struct *task)
+unsigned int get_rr_interval_rt(struct rq *rq, struct task_struct *task)
 {
 	/*
 	 * Time slice is 0 for SCHED_FIFO tasks
@@ -1766,7 +1773,7 @@
 	.rq_offline             = rq_offline_rt,
 	.pre_schedule		= pre_schedule_rt,
 	.post_schedule		= post_schedule_rt,
-	.task_wake_up		= task_wake_up_rt,
+	.task_woken		= task_woken_rt,
 	.switched_from		= switched_from_rt,
 #endif
 
--- linux-ec2-2.6.32.orig/kernel/compat.c
+++ linux-ec2-2.6.32/kernel/compat.c
@@ -25,6 +25,7 @@
 #include <linux/posix-timers.h>
 #include <linux/times.h>
 #include <linux/ptrace.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 
@@ -494,29 +495,26 @@
 {
 	int ret;
 	cpumask_var_t mask;
-	unsigned long *k;
-	unsigned int min_length = cpumask_size();
-
-	if (nr_cpu_ids <= BITS_PER_COMPAT_LONG)
-		min_length = sizeof(compat_ulong_t);
 
-	if (len < min_length)
+	if ((len * BITS_PER_BYTE) < nr_cpu_ids)
+		return -EINVAL;
+	if (len & (sizeof(compat_ulong_t)-1))
 		return -EINVAL;
 
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
 		return -ENOMEM;
 
 	ret = sched_getaffinity(pid, mask);
-	if (ret < 0)
-		goto out;
+	if (ret == 0) {
+		size_t retlen = min_t(size_t, len, cpumask_size());
 
-	k = cpumask_bits(mask);
-	ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
-	if (ret == 0)
-		ret = min_length;
-
-out:
+		if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8))
+			ret = -EFAULT;
+		else
+			ret = retlen;
+	}
 	free_cpumask_var(mask);
+
 	return ret;
 }
 
@@ -1139,3 +1137,24 @@
 
 	return 0;
 }
+
+/*
+ * Allocate user-space memory for the duration of a single system call,
+ * in order to marshall parameters inside a compat thunk.
+ */
+void __user *compat_alloc_user_space(unsigned long len)
+{
+	void __user *ptr;
+
+	/* If len would occupy more than half of the entire compat space... */
+	if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
+		return NULL;
+
+	ptr = arch_compat_alloc_user_space(len);
+
+	if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
+		return NULL;
+
+	return ptr;
+}
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
--- linux-ec2-2.6.32.orig/kernel/slow-work.c
+++ linux-ec2-2.6.32/kernel/slow-work.c
@@ -640,7 +640,7 @@
 			goto cancelled;
 
 		/* the timer holds a reference whilst it is pending */
-		ret = work->ops->get_ref(work);
+		ret = slow_work_get_ref(work);
 		if (ret < 0)
 			goto cant_get_ref;
 
--- linux-ec2-2.6.32.orig/kernel/capability.c
+++ linux-ec2-2.6.32/kernel/capability.c
@@ -15,7 +15,6 @@
 #include <linux/syscalls.h>
 #include <linux/pid_namespace.h>
 #include <asm/uaccess.h>
-#include "cred-internals.h"
 
 /*
  * Leveraged for setting/resetting capabilities
--- linux-ec2-2.6.32.orig/kernel/pid.c
+++ linux-ec2-2.6.32/kernel/pid.c
@@ -182,11 +182,14 @@
 	return -1;
 }
 
-int next_pidmap(struct pid_namespace *pid_ns, int last)
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
 {
 	int offset;
 	struct pidmap *map, *end;
 
+	if (last >= PID_MAX_LIMIT)
+		return -1;
+
 	offset = (last + 1) & BITS_PER_PAGE_MASK;
 	map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
 	end = &pid_ns->pidmap[PIDMAP_ENTRIES];
--- linux-ec2-2.6.32.orig/kernel/profile.c
+++ linux-ec2-2.6.32/kernel/profile.c
@@ -127,8 +127,10 @@
 		return 0;
 
 	prof_buffer = vmalloc(buffer_bytes);
-	if (prof_buffer)
+	if (prof_buffer) {
+		memset(prof_buffer, 0, buffer_bytes);
 		return 0;
+	}
 
 	free_cpumask_var(prof_cpu_mask);
 	return -ENOMEM;
--- linux-ec2-2.6.32.orig/kernel/softlockup.c
+++ linux-ec2-2.6.32/kernel/softlockup.c
@@ -140,11 +140,11 @@
 	 * Wake up the high-prio watchdog task twice per
 	 * threshold timespan.
 	 */
-	if (now > touch_timestamp + softlockup_thresh/2)
+	if (time_after(now - softlockup_thresh/2, touch_timestamp))
 		wake_up_process(per_cpu(watchdog_task, this_cpu));
 
 	/* Warn about unreasonable delays: */
-	if (now <= (touch_timestamp + softlockup_thresh))
+	if (time_before_eq(now - softlockup_thresh, touch_timestamp))
 		return;
 
 	per_cpu(print_timestamp, this_cpu) = touch_timestamp;
--- linux-ec2-2.6.32.orig/kernel/kgdb.c
+++ linux-ec2-2.6.32/kernel/kgdb.c
@@ -1001,10 +1001,8 @@
 	switch (remcom_in_buffer[1]) {
 	case 's':
 	case 'f':
-		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) {
-			error_packet(remcom_out_buffer, -EINVAL);
+		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10))
 			break;
-		}
 
 		i = 0;
 		remcom_out_buffer[0] = 'm';
@@ -1045,10 +1043,9 @@
 		pack_threadid(remcom_out_buffer + 2, thref);
 		break;
 	case 'T':
-		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) {
-			error_packet(remcom_out_buffer, -EINVAL);
+		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16))
 			break;
-		}
+
 		ks->threadid = 0;
 		ptr = remcom_in_buffer + 17;
 		kgdb_hex2long(&ptr, &ks->threadid);
--- linux-ec2-2.6.32.orig/kernel/rcutree_plugin.h
+++ linux-ec2-2.6.32/kernel/rcutree_plugin.h
@@ -33,7 +33,7 @@
 /*
  * Tell them what RCU they are running.
  */
-static inline void rcu_bootup_announce(void)
+static void rcu_bootup_announce(void)
 {
 	printk(KERN_INFO
 	       "Experimental preemptable hierarchical RCU implementation.\n");
@@ -481,7 +481,7 @@
 /*
  * Tell them what RCU they are running.
  */
-static inline void rcu_bootup_announce(void)
+static void rcu_bootup_announce(void)
 {
 	printk(KERN_INFO "Hierarchical RCU implementation.\n");
 }
--- linux-ec2-2.6.32.orig/kernel/cgroup.c
+++ linux-ec2-2.6.32/kernel/cgroup.c
@@ -2468,7 +2468,6 @@
 			/* make sure l doesn't vanish out from under us */
 			down_write(&l->mutex);
 			mutex_unlock(&cgrp->pidlist_mutex);
-			l->use_count++;
 			return l;
 		}
 	}
--- linux-ec2-2.6.32.orig/kernel/latencytop.c
+++ linux-ec2-2.6.32/kernel/latencytop.c
@@ -195,14 +195,7 @@
 
 	account_global_scheduler_latency(tsk, &lat);
 
-	/*
-	 * short term hack; if we're > 32 we stop; future we recycle:
-	 */
-	tsk->latency_record_count++;
-	if (tsk->latency_record_count >= LT_SAVECOUNT)
-		goto out_unlock;
-
-	for (i = 0; i < LT_SAVECOUNT; i++) {
+	for (i = 0; i < tsk->latency_record_count; i++) {
 		struct latency_record *mylat;
 		int same = 1;
 
@@ -228,8 +221,14 @@
 		}
 	}
 
+	/*
+	 * short term hack; if we're > 32 we stop; future we recycle:
+	 */
+	if (tsk->latency_record_count >= LT_SAVECOUNT)
+		goto out_unlock;
+
 	/* Allocated a new one: */
-	i = tsk->latency_record_count;
+	i = tsk->latency_record_count++;
 	memcpy(&tsk->latency_record[i], &lat, sizeof(struct latency_record));
 
 out_unlock:
--- linux-ec2-2.6.32.orig/kernel/acct.c
+++ linux-ec2-2.6.32/kernel/acct.c
@@ -536,7 +536,8 @@
 	do_div(elapsed, AHZ);
 	ac.ac_btime = get_seconds() - elapsed;
 	/* we really need to bite the bullet and change layout */
-	current_uid_gid(&ac.ac_uid, &ac.ac_gid);
+	ac.ac_uid = orig_cred->uid;
+	ac.ac_gid = orig_cred->gid;
 #if ACCT_VERSION==2
 	ac.ac_ahz = AHZ;
 #endif
--- linux-ec2-2.6.32.orig/kernel/sched_idletask.c
+++ linux-ec2-2.6.32/kernel/sched_idletask.c
@@ -6,7 +6,8 @@
  */
 
 #ifdef CONFIG_SMP
-static int select_task_rq_idle(struct task_struct *p, int sd_flag, int flags)
+static int
+select_task_rq_idle(struct rq *rq, struct task_struct *p, int sd_flag, int flags)
 {
 	return task_cpu(p); /* IDLE tasks as never migrated */
 }
@@ -97,7 +98,7 @@
 		check_preempt_curr(rq, p, 0);
 }
 
-unsigned int get_rr_interval_idle(struct task_struct *task)
+unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task)
 {
 	return 0;
 }
--- linux-ec2-2.6.32.orig/kernel/futex.c
+++ linux-ec2-2.6.32/kernel/futex.c
@@ -203,8 +203,6 @@
  * @uaddr:	virtual address of the futex
  * @fshared:	0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
  * @key:	address where result is stored.
- * @rw:		mapping needs to be read/write (values: VERIFY_READ,
- * 		VERIFY_WRITE)
  *
  * Returns a negative error code or 0
  * The key words are stored in *key on success.
@@ -216,7 +214,7 @@
  * lock_page() might sleep, the caller should not hold a spinlock.
  */
 static int
-get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
+get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
 {
 	unsigned long address = (unsigned long)uaddr;
 	struct mm_struct *mm = current->mm;
@@ -239,7 +237,7 @@
 	 *        but access_ok() should be faster than find_vma()
 	 */
 	if (!fshared) {
-		if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
+		if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 			return -EFAULT;
 		key->private.mm = mm;
 		key->private.address = address;
@@ -248,7 +246,7 @@
 	}
 
 again:
-	err = get_user_pages_fast(address, 1, rw == VERIFY_WRITE, &page);
+	err = get_user_pages_fast(address, 1, 1, &page);
 	if (err < 0)
 		return err;
 
@@ -304,8 +302,14 @@
  */
 static int fault_in_user_writeable(u32 __user *uaddr)
 {
-	int ret = get_user_pages(current, current->mm, (unsigned long)uaddr,
-				 1, 1, 0, NULL, NULL);
+	struct mm_struct *mm = current->mm;
+	int ret;
+
+	down_read(&mm->mmap_sem);
+	ret = get_user_pages(current, mm, (unsigned long)uaddr,
+			     1, 1, 0, NULL, NULL);
+	up_read(&mm->mmap_sem);
+
 	return ret < 0 ? ret : 0;
 }
 
@@ -425,20 +429,11 @@
 static struct task_struct * futex_find_get_task(pid_t pid)
 {
 	struct task_struct *p;
-	const struct cred *cred = current_cred(), *pcred;
 
 	rcu_read_lock();
 	p = find_task_by_vpid(pid);
-	if (!p) {
-		p = ERR_PTR(-ESRCH);
-	} else {
-		pcred = __task_cred(p);
-		if (cred->euid != pcred->euid &&
-		    cred->euid != pcred->uid)
-			p = ERR_PTR(-ESRCH);
-		else
-			get_task_struct(p);
-	}
+	if (p)
+		get_task_struct(p);
 
 	rcu_read_unlock();
 
@@ -526,8 +521,25 @@
 				return -EINVAL;
 
 			WARN_ON(!atomic_read(&pi_state->refcount));
-			WARN_ON(pid && pi_state->owner &&
-				pi_state->owner->pid != pid);
+
+			/*
+			 * When pi_state->owner is NULL then the owner died
+			 * and another waiter is on the fly. pi_state->owner
+			 * is fixed up by the task which acquires
+			 * pi_state->rt_mutex.
+			 *
+			 * We do not check for pid == 0 which can happen when
+			 * the owner died and robust_list_exit() cleared the
+			 * TID.
+			 */
+			if (pid && pi_state->owner) {
+				/*
+				 * Bail out if user space manipulated the
+				 * futex value.
+				 */
+				if (pid != task_pid_vnr(pi_state->owner))
+					return -EINVAL;
+			}
 
 			atomic_inc(&pi_state->refcount);
 			*ps = pi_state;
@@ -543,8 +555,8 @@
 	if (!pid)
 		return -ESRCH;
 	p = futex_find_get_task(pid);
-	if (IS_ERR(p))
-		return PTR_ERR(p);
+	if (!p)
+		return -ESRCH;
 
 	/*
 	 * We need to look at the task state flags to figure out,
@@ -754,6 +766,13 @@
 	if (!pi_state)
 		return -EINVAL;
 
+	/*
+	 * If current does not own the pi_state then the futex is
+	 * inconsistent and user space fiddled with the futex value.
+	 */
+	if (pi_state->owner != current)
+		return -EINVAL;
+
 	spin_lock(&pi_state->pi_mutex.wait_lock);
 	new_owner = rt_mutex_next_owner(&pi_state->pi_mutex);
 
@@ -861,7 +880,7 @@
 	if (!bitset)
 		return -EINVAL;
 
-	ret = get_futex_key(uaddr, fshared, &key, VERIFY_READ);
+	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -907,10 +926,10 @@
 	int ret, op_ret;
 
 retry:
-	ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ);
+	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
 		goto out;
-	ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
+	ret = get_futex_key(uaddr2, fshared, &key2);
 	if (unlikely(ret != 0))
 		goto out_put_key1;
 
@@ -1169,11 +1188,10 @@
 		pi_state = NULL;
 	}
 
-	ret = get_futex_key(uaddr1, fshared, &key1, VERIFY_READ);
+	ret = get_futex_key(uaddr1, fshared, &key1);
 	if (unlikely(ret != 0))
 		goto out;
-	ret = get_futex_key(uaddr2, fshared, &key2,
-			    requeue_pi ? VERIFY_WRITE : VERIFY_READ);
+	ret = get_futex_key(uaddr2, fshared, &key2);
 	if (unlikely(ret != 0))
 		goto out_put_key1;
 
@@ -1345,7 +1363,6 @@
 {
 	struct futex_hash_bucket *hb;
 
-	get_futex_key_refs(&q->key);
 	hb = hash_futex(&q->key);
 	q->lock_ptr = &hb->lock;
 
@@ -1357,7 +1374,6 @@
 queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
 {
 	spin_unlock(&hb->lock);
-	drop_futex_key_refs(&q->key);
 }
 
 /**
@@ -1462,8 +1478,6 @@
 	q->pi_state = NULL;
 
 	spin_unlock(q->lock_ptr);
-
-	drop_futex_key_refs(&q->key);
 }
 
 /*
@@ -1732,7 +1746,7 @@
 	 */
 retry:
 	q->key = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr, fshared, &q->key, VERIFY_READ);
+	ret = get_futex_key(uaddr, fshared, &q->key);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1794,7 +1808,10 @@
 	}
 
 retry:
-	/* Prepare to wait on uaddr. */
+	/*
+	 * Prepare to wait on uaddr. On success, holds hb lock and increments
+	 * q.key refs.
+	 */
 	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
 	if (ret)
 		goto out;
@@ -1804,24 +1821,23 @@
 
 	/* If we were woken (and unqueued), we succeeded, whatever. */
 	ret = 0;
+	/* unqueue_me() drops q.key ref */
 	if (!unqueue_me(&q))
-		goto out_put_key;
+		goto out;
 	ret = -ETIMEDOUT;
 	if (to && !to->task)
-		goto out_put_key;
+		goto out;
 
 	/*
 	 * We expect signal_pending(current), but we might be the
 	 * victim of a spurious wakeup as well.
 	 */
-	if (!signal_pending(current)) {
-		put_futex_key(fshared, &q.key);
+	if (!signal_pending(current))
 		goto retry;
-	}
 
 	ret = -ERESTARTSYS;
 	if (!abs_time)
-		goto out_put_key;
+		goto out;
 
 	restart = &current_thread_info()->restart_block;
 	restart->fn = futex_wait_restart;
@@ -1838,8 +1854,6 @@
 
 	ret = -ERESTART_RESTARTBLOCK;
 
-out_put_key:
-	put_futex_key(fshared, &q.key);
 out:
 	if (to) {
 		hrtimer_cancel(&to->timer);
@@ -1898,7 +1912,7 @@
 	q.requeue_pi_key = NULL;
 retry:
 	q.key = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE);
+	ret = get_futex_key(uaddr, fshared, &q.key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -1968,7 +1982,7 @@
 	/* Unqueue and drop the lock */
 	unqueue_me_pi(&q);
 
-	goto out;
+	goto out_put_key;
 
 out_unlock_put_key:
 	queue_unlock(&q, hb);
@@ -2017,7 +2031,7 @@
 	if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
 		return -EPERM;
 
-	ret = get_futex_key(uaddr, fshared, &key, VERIFY_WRITE);
+	ret = get_futex_key(uaddr, fshared, &key);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -2209,7 +2223,7 @@
 	rt_waiter.task = NULL;
 
 	key2 = FUTEX_KEY_INIT;
-	ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
+	ret = get_futex_key(uaddr2, fshared, &key2);
 	if (unlikely(ret != 0))
 		goto out;
 
@@ -2218,7 +2232,10 @@
 	q.rt_waiter = &rt_waiter;
 	q.requeue_pi_key = &key2;
 
-	/* Prepare to wait on uaddr. */
+	/*
+	 * Prepare to wait on uaddr. On success, increments q.key (key1) ref
+	 * count.
+	 */
 	ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
 	if (ret)
 		goto out_key2;
@@ -2236,7 +2253,9 @@
 	 * In order for us to be here, we know our q.key == key2, and since
 	 * we took the hb->lock above, we also know that futex_requeue() has
 	 * completed and we no longer have to concern ourselves with a wakeup
-	 * race with the atomic proxy lock acquition by the requeue code.
+	 * race with the atomic proxy lock acquisition by the requeue code. The
+	 * futex_requeue dropped our key1 reference and incremented our key2
+	 * reference count.
 	 */
 
 	/* Check if the requeue code acquired the second futex for us. */
--- linux-ec2-2.6.32.orig/kernel/cpu.c
+++ linux-ec2-2.6.32/kernel/cpu.c
@@ -151,7 +151,7 @@
 
 	write_lock_irq(&tasklist_lock);
 	for_each_process(p) {
-		if (task_cpu(p) == cpu &&
+		if (task_cpu(p) == cpu && p->state == TASK_RUNNING &&
 		    (!cputime_eq(p->utime, cputime_zero) ||
 		     !cputime_eq(p->stime, cputime_zero)))
 			printk(KERN_WARNING "Task %s (pid = %d) is on cpu %d\
@@ -163,6 +163,7 @@
 }
 
 struct take_cpu_down_param {
+	struct task_struct *caller;
 	unsigned long mod;
 	void *hcpu;
 };
@@ -171,6 +172,7 @@
 static int __ref take_cpu_down(void *_param)
 {
 	struct take_cpu_down_param *param = _param;
+	unsigned int cpu = (unsigned long)param->hcpu;
 	int err;
 
 	/* Ensure this CPU doesn't handle any more interrupts. */
@@ -181,6 +183,8 @@
 	raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod,
 				param->hcpu);
 
+	if (task_cpu(param->caller) == cpu)
+		move_task_off_dead_cpu(cpu, param->caller);
 	/* Force idle task to run as soon as we yield: it should
 	   immediately notice cpu is offline and die quickly. */
 	sched_idle_next();
@@ -191,10 +195,10 @@
 static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 {
 	int err, nr_calls = 0;
-	cpumask_var_t old_allowed;
 	void *hcpu = (void *)(long)cpu;
 	unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
 	struct take_cpu_down_param tcd_param = {
+		.caller = current,
 		.mod = mod,
 		.hcpu = hcpu,
 	};
@@ -205,13 +209,13 @@
 	if (!cpu_online(cpu))
 		return -EINVAL;
 
-	if (!alloc_cpumask_var(&old_allowed, GFP_KERNEL))
-		return -ENOMEM;
-
 	cpu_hotplug_begin();
+	set_cpu_active(cpu, false);
 	err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
 					hcpu, -1, &nr_calls);
 	if (err == NOTIFY_BAD) {
+		set_cpu_active(cpu, true);
+
 		nr_calls--;
 		__raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
 					  hcpu, nr_calls, NULL);
@@ -221,19 +225,15 @@
 		goto out_release;
 	}
 
-	/* Ensure that we are not runnable on dying cpu */
-	cpumask_copy(old_allowed, &current->cpus_allowed);
-	set_cpus_allowed_ptr(current,
-			     cpumask_of(cpumask_any_but(cpu_online_mask, cpu)));
-
 	err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
 	if (err) {
+		set_cpu_active(cpu, true);
 		/* CPU didn't die: tell everyone.  Can't complain. */
 		if (raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
 					    hcpu) == NOTIFY_BAD)
 			BUG();
 
-		goto out_allowed;
+		goto out_release;
 	}
 	BUG_ON(cpu_online(cpu));
 
@@ -251,8 +251,6 @@
 
 	check_for_tasks(cpu);
 
-out_allowed:
-	set_cpus_allowed_ptr(current, old_allowed);
 out_release:
 	cpu_hotplug_done();
 	if (!err) {
@@ -260,7 +258,6 @@
 					    hcpu) == NOTIFY_BAD)
 			BUG();
 	}
-	free_cpumask_var(old_allowed);
 	return err;
 }
 
@@ -278,23 +275,8 @@
 		goto out;
 	}
 
-	set_cpu_active(cpu, false);
-
-	/*
-	 * Make sure the all cpus did the reschedule and are not
-	 * using stale version of the cpu_active_mask.
-	 * This is not strictly necessary becuase stop_machine()
-	 * that we run down the line already provides the required
-	 * synchronization. But it's really a side effect and we do not
-	 * want to depend on the innards of the stop_machine here.
-	 */
-	synchronize_sched();
-
 	err = _cpu_down(cpu, 0);
 
-	if (cpu_online(cpu))
-		set_cpu_active(cpu, true);
-
 out:
 	cpu_maps_update_done();
 	stop_machine_destroy();
@@ -383,19 +365,20 @@
 		return error;
 	cpu_maps_update_begin();
 	first_cpu = cpumask_first(cpu_online_mask);
-	/* We take down all of the non-boot CPUs in one shot to avoid races
+	/*
+	 * We take down all of the non-boot CPUs in one shot to avoid races
 	 * with the userspace trying to use the CPU hotplug at the same time
 	 */
 	cpumask_clear(frozen_cpus);
+
 	printk("Disabling non-boot CPUs ...\n");
 	for_each_online_cpu(cpu) {
 		if (cpu == first_cpu)
 			continue;
 		error = _cpu_down(cpu, 1);
-		if (!error) {
+		if (!error)
 			cpumask_set_cpu(cpu, frozen_cpus);
-			printk("CPU%d is down\n", cpu);
-		} else {
+		else {
 			printk(KERN_ERR "Error taking CPU%d down: %d\n",
 				cpu, error);
 			break;
--- linux-ec2-2.6.32.orig/kernel/ksysfs.c
+++ linux-ec2-2.6.32/kernel/ksysfs.c
@@ -176,16 +176,8 @@
 			goto group_exit;
 	}
 
-	/* create the /sys/kernel/uids/ directory */
-	error = uids_sysfs_init();
-	if (error)
-		goto notes_exit;
-
 	return 0;
 
-notes_exit:
-	if (notes_size > 0)
-		sysfs_remove_bin_file(kernel_kobj, &notes_attr);
 group_exit:
 	sysfs_remove_group(kernel_kobj, &kernel_attr_group);
 kset_exit:
--- linux-ec2-2.6.32.orig/kernel/cpuset.c
+++ linux-ec2-2.6.32/kernel/cpuset.c
@@ -873,7 +873,7 @@
 		if (retval < 0)
 			return retval;
 
-		if (!cpumask_subset(trialcs->cpus_allowed, cpu_online_mask))
+		if (!cpumask_subset(trialcs->cpus_allowed, cpu_active_mask))
 			return -EINVAL;
 	}
 	retval = validate_change(cs, trialcs);
@@ -921,9 +921,6 @@
  *    call to guarantee_online_mems(), as we know no one is changing
  *    our task's cpuset.
  *
- *    Hold callback_mutex around the two modifications of our tasks
- *    mems_allowed to synchronize with cpuset_mems_allowed().
- *
  *    While the mm_struct we are migrating is typically from some
  *    other task, the task_struct mems_allowed that we are hacking
  *    is for our current task, which must allocate new pages for that
@@ -1392,11 +1389,10 @@
 
 	if (cs == &top_cpuset) {
 		cpumask_copy(cpus_attach, cpu_possible_mask);
-		to = node_possible_map;
 	} else {
 		guarantee_online_cpus(cs, cpus_attach);
-		guarantee_online_mems(cs, &to);
 	}
+	guarantee_online_mems(cs, &to);
 
 	/* do per-task migration stuff possibly for each in the threadgroup */
 	cpuset_attach_task(tsk, &to, cs);
@@ -1518,8 +1514,10 @@
 		return -ENODEV;
 
 	trialcs = alloc_trial_cpuset(cs);
-	if (!trialcs)
-		return -ENOMEM;
+	if (!trialcs) {
+		retval = -ENOMEM;
+		goto out;
+	}
 
 	switch (cft->private) {
 	case FILE_CPULIST:
@@ -1534,6 +1532,7 @@
 	}
 
 	free_trial_cpuset(trialcs);
+out:
 	cgroup_unlock();
 	return retval;
 }
@@ -2011,7 +2010,7 @@
 		}
 
 		/* Continue past cpusets with all cpus, mems online */
-		if (cpumask_subset(cp->cpus_allowed, cpu_online_mask) &&
+		if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
 		    nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
 			continue;
 
@@ -2020,7 +2019,7 @@
 		/* Remove offline cpus and mems from this cpuset. */
 		mutex_lock(&callback_mutex);
 		cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
-			    cpu_online_mask);
+			    cpu_active_mask);
 		nodes_and(cp->mems_allowed, cp->mems_allowed,
 						node_states[N_HIGH_MEMORY]);
 		mutex_unlock(&callback_mutex);
@@ -2058,8 +2057,10 @@
 	switch (phase) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
 		break;
 
 	default:
@@ -2068,7 +2069,7 @@
 
 	cgroup_lock();
 	mutex_lock(&callback_mutex);
-	cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask);
+	cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
 	mutex_unlock(&callback_mutex);
 	scan_for_empty_cpusets(&top_cpuset);
 	ndoms = generate_sched_domains(&doms, &attr);
@@ -2089,15 +2090,23 @@
 static int cpuset_track_online_nodes(struct notifier_block *self,
 				unsigned long action, void *arg)
 {
+	nodemask_t oldmems;
+
 	cgroup_lock();
 	switch (action) {
 	case MEM_ONLINE:
-	case MEM_OFFLINE:
+		oldmems = top_cpuset.mems_allowed;
 		mutex_lock(&callback_mutex);
 		top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
 		mutex_unlock(&callback_mutex);
-		if (action == MEM_OFFLINE)
-			scan_for_empty_cpusets(&top_cpuset);
+		update_tasks_nodemask(&top_cpuset, &oldmems, NULL);
+		break;
+	case MEM_OFFLINE:
+		/*
+		 * needn't update top_cpuset.mems_allowed explicitly because
+		 * scan_for_empty_cpusets() will update it.
+		 */
+		scan_for_empty_cpusets(&top_cpuset);
 		break;
 	default:
 		break;
@@ -2115,7 +2124,7 @@
 
 void __init cpuset_init_smp(void)
 {
-	cpumask_copy(top_cpuset.cpus_allowed, cpu_online_mask);
+	cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
 	top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
 
 	hotcpu_notifier(cpuset_track_online_cpus, 0);
@@ -2139,19 +2148,52 @@
 void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
 {
 	mutex_lock(&callback_mutex);
-	cpuset_cpus_allowed_locked(tsk, pmask);
+	task_lock(tsk);
+	guarantee_online_cpus(task_cs(tsk), pmask);
+	task_unlock(tsk);
 	mutex_unlock(&callback_mutex);
 }
 
-/**
- * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset.
- * Must be called with callback_mutex held.
- **/
-void cpuset_cpus_allowed_locked(struct task_struct *tsk, struct cpumask *pmask)
+int cpuset_cpus_allowed_fallback(struct task_struct *tsk)
 {
-	task_lock(tsk);
-	guarantee_online_cpus(task_cs(tsk), pmask);
-	task_unlock(tsk);
+	const struct cpuset *cs;
+	int cpu;
+
+	rcu_read_lock();
+	cs = task_cs(tsk);
+	if (cs)
+		cpumask_copy(&tsk->cpus_allowed, cs->cpus_allowed);
+	rcu_read_unlock();
+
+	/*
+	 * We own tsk->cpus_allowed, nobody can change it under us.
+	 *
+	 * But we used cs && cs->cpus_allowed lockless and thus can
+	 * race with cgroup_attach_task() or update_cpumask() and get
+	 * the wrong tsk->cpus_allowed. However, both cases imply the
+	 * subsequent cpuset_change_cpumask()->set_cpus_allowed_ptr()
+	 * which takes task_rq_lock().
+	 *
+	 * If we are called after it dropped the lock we must see all
+	 * changes in tsk_cs()->cpus_allowed. Otherwise we can temporary
+	 * set any mask even if it is not right from task_cs() pov,
+	 * the pending set_cpus_allowed_ptr() will fix things.
+	 */
+
+	cpu = cpumask_any_and(&tsk->cpus_allowed, cpu_active_mask);
+	if (cpu >= nr_cpu_ids) {
+		/*
+		 * Either tsk->cpus_allowed is wrong (see above) or it
+		 * is actually empty. The latter case is only possible
+		 * if we are racing with remove_tasks_in_empty_cpuset().
+		 * Like above we can temporary set any mask and rely on
+		 * set_cpus_allowed_ptr() as synchronization point.
+		 */
+		cpumask_copy(&tsk->cpus_allowed, cpu_possible_mask);
+		cpu = cpumask_any(cpu_active_mask);
+	}
+
+	return cpu;
 }
 
 void cpuset_init_current_mems_allowed(void)
@@ -2340,22 +2382,6 @@
 }
 
 /**
- * cpuset_lock - lock out any changes to cpuset structures
- *
- * The out of memory (oom) code needs to mutex_lock cpusets
- * from being changed while it scans the tasklist looking for a
- * task in an overlapping cpuset.  Expose callback_mutex via this
- * cpuset_lock() routine, so the oom code can lock it, before
- * locking the task list.  The tasklist_lock is a spinlock, so
- * must be taken inside callback_mutex.
- */
-
-void cpuset_lock(void)
-{
-	mutex_lock(&callback_mutex);
-}
-
-/**
  * cpuset_unlock - release lock on cpuset changes
  *
  * Undo the lock taken in a previous cpuset_lock() call.
--- linux-ec2-2.6.32.orig/kernel/sched_features.h
+++ linux-ec2-2.6.32/kernel/sched_features.h
@@ -121,3 +121,8 @@
  * release the lock. Decreases scheduling overhead.
  */
 SCHED_FEAT(OWNER_SPIN, 1)
+
+/*
+ * Decrement CPU power based on irq activity
+ */
+SCHED_FEAT(NONIRQ_POWER, 1)
--- linux-ec2-2.6.32.orig/kernel/softirq.c
+++ linux-ec2-2.6.32/kernel/softirq.c
@@ -77,11 +77,21 @@
 }
 
 /*
+ * preempt_count and SOFTIRQ_OFFSET usage:
+ * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
+ *   softirq processing.
+ * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
+ *   on local_bh_disable or local_bh_enable.
+ * This lets us distinguish between whether we are currently processing
+ * softirq and whether we just have bh disabled.
+ */
+
+/*
  * This one is for softirq.c-internal use,
  * where hardirqs are disabled legitimately:
  */
 #ifdef CONFIG_TRACE_IRQFLAGS
-static void __local_bh_disable(unsigned long ip)
+static void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
 	unsigned long flags;
 
@@ -95,32 +105,43 @@
 	 * We must manually increment preempt_count here and manually
 	 * call the trace_preempt_off later.
 	 */
-	preempt_count() += SOFTIRQ_OFFSET;
+	preempt_count() += cnt;
 	/*
 	 * Were softirqs turned off above:
 	 */
-	if (softirq_count() == SOFTIRQ_OFFSET)
+	if (softirq_count() == cnt)
 		trace_softirqs_off(ip);
 	raw_local_irq_restore(flags);
 
-	if (preempt_count() == SOFTIRQ_OFFSET)
+	if (preempt_count() == cnt)
 		trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
 }
 #else /* !CONFIG_TRACE_IRQFLAGS */
-static inline void __local_bh_disable(unsigned long ip)
+static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
-	add_preempt_count(SOFTIRQ_OFFSET);
+	add_preempt_count(cnt);
 	barrier();
 }
 #endif /* CONFIG_TRACE_IRQFLAGS */
 
 void local_bh_disable(void)
 {
-	__local_bh_disable((unsigned long)__builtin_return_address(0));
+	__local_bh_disable((unsigned long)__builtin_return_address(0),
+				SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(local_bh_disable);
 
+static void __local_bh_enable(unsigned int cnt)
+{
+	WARN_ON_ONCE(in_irq());
+	WARN_ON_ONCE(!irqs_disabled());
+
+	if (softirq_count() == cnt)
+		trace_softirqs_on((unsigned long)__builtin_return_address(0));
+	sub_preempt_count(cnt);
+}
+
 /*
  * Special-case - softirqs can safely be enabled in
  * cond_resched_softirq(), or by __do_softirq(),
@@ -128,12 +149,7 @@
  */
 void _local_bh_enable(void)
 {
-	WARN_ON_ONCE(in_irq());
-	WARN_ON_ONCE(!irqs_disabled());
-
-	if (softirq_count() == SOFTIRQ_OFFSET)
-		trace_softirqs_on((unsigned long)__builtin_return_address(0));
-	sub_preempt_count(SOFTIRQ_OFFSET);
+	__local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
 }
 
 EXPORT_SYMBOL(_local_bh_enable);
@@ -147,13 +163,13 @@
 	/*
 	 * Are softirqs going to be turned on now:
 	 */
-	if (softirq_count() == SOFTIRQ_OFFSET)
+	if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
 		trace_softirqs_on(ip);
 	/*
 	 * Keep preemption disabled until we are done with
 	 * softirq processing:
  	 */
- 	sub_preempt_count(SOFTIRQ_OFFSET - 1);
+	sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
 
 	if (unlikely(!in_interrupt() && local_softirq_pending()))
 		do_softirq();
@@ -198,7 +214,8 @@
 	pending = local_softirq_pending();
 	account_system_vtime(current);
 
-	__local_bh_disable((unsigned long)__builtin_return_address(0));
+	__local_bh_disable((unsigned long)__builtin_return_address(0),
+				SOFTIRQ_OFFSET);
 	lockdep_softirq_enter();
 
 	cpu = smp_processor_id();
@@ -245,7 +262,7 @@
 	lockdep_softirq_exit();
 
 	account_system_vtime(current);
-	_local_bh_enable();
+	__local_bh_enable(SOFTIRQ_OFFSET);
 }
 
 #ifndef __ARCH_HAS_DO_SOFTIRQ
@@ -279,10 +296,16 @@
 
 	rcu_irq_enter();
 	if (idle_cpu(cpu) && !in_interrupt()) {
-		__irq_enter();
+		/*
+		 * Prevent raise_softirq from needlessly waking up ksoftirqd
+		 * here, as softirq will be serviced on return from interrupt.
+		 */
+		local_bh_disable();
 		tick_check_idle(cpu);
-	} else
-		__irq_enter();
+		_local_bh_enable();
+	}
+
+	__irq_enter();
 }
 
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
@@ -701,6 +724,7 @@
 {
 	set_current_state(TASK_INTERRUPTIBLE);
 
+	current->flags |= PF_KSOFTIRQD;
 	while (!kthread_should_stop()) {
 		preempt_disable();
 		if (!local_softirq_pending()) {
--- linux-ec2-2.6.32.orig/kernel/sched_clock.c
+++ linux-ec2-2.6.32/kernel/sched_clock.c
@@ -236,6 +236,18 @@
 }
 EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
 
+unsigned long long cpu_clock(int cpu)
+{
+	unsigned long long clock;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	clock = sched_clock_cpu(cpu);
+	local_irq_restore(flags);
+
+	return clock;
+}
+
 #else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
 void sched_clock_init(void)
@@ -251,17 +263,12 @@
 	return sched_clock();
 }
 
-#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
 unsigned long long cpu_clock(int cpu)
 {
-	unsigned long long clock;
-	unsigned long flags;
+	return sched_clock_cpu(cpu);
+}
 
-	local_irq_save(flags);
-	clock = sched_clock_cpu(cpu);
-	local_irq_restore(flags);
+#endif /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
 
-	return clock;
-}
 EXPORT_SYMBOL_GPL(cpu_clock);
--- linux-ec2-2.6.32.orig/kernel/sched.c
+++ linux-ec2-2.6.32/kernel/sched.c
@@ -233,7 +233,7 @@
  */
 static DEFINE_MUTEX(sched_domains_mutex);
 
-#ifdef CONFIG_GROUP_SCHED
+#ifdef CONFIG_CGROUP_SCHED
 
 #include <linux/cgroup.h>
 
@@ -243,13 +243,7 @@
 
 /* task group related information */
 struct task_group {
-#ifdef CONFIG_CGROUP_SCHED
 	struct cgroup_subsys_state css;
-#endif
-
-#ifdef CONFIG_USER_SCHED
-	uid_t uid;
-#endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* schedulable entities of this group on each cpu */
@@ -274,35 +268,7 @@
 	struct list_head children;
 };
 
-#ifdef CONFIG_USER_SCHED
-
-/* Helper function to pass uid information to create_sched_user() */
-void set_tg_uid(struct user_struct *user)
-{
-	user->tg->uid = user->uid;
-}
-
-/*
- * Root task group.
- *	Every UID task group (including init_task_group aka UID-0) will
- *	be a child to this group.
- */
-struct task_group root_task_group;
-
-#ifdef CONFIG_FAIR_GROUP_SCHED
-/* Default task group's sched entity on each cpu */
-static DEFINE_PER_CPU(struct sched_entity, init_sched_entity);
-/* Default task group's cfs_rq on each cpu */
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct cfs_rq, init_tg_cfs_rq);
-#endif /* CONFIG_FAIR_GROUP_SCHED */
-
-#ifdef CONFIG_RT_GROUP_SCHED
-static DEFINE_PER_CPU(struct sched_rt_entity, init_sched_rt_entity);
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct rt_rq, init_rt_rq);
-#endif /* CONFIG_RT_GROUP_SCHED */
-#else /* !CONFIG_USER_SCHED */
 #define root_task_group init_task_group
-#endif /* CONFIG_USER_SCHED */
 
 /* task_group_lock serializes add/remove of task groups and also changes to
  * a task group's cpu shares.
@@ -318,11 +284,7 @@
 }
 #endif
 
-#ifdef CONFIG_USER_SCHED
-# define INIT_TASK_GROUP_LOAD	(2*NICE_0_LOAD)
-#else /* !CONFIG_USER_SCHED */
 # define INIT_TASK_GROUP_LOAD	NICE_0_LOAD
-#endif /* CONFIG_USER_SCHED */
 
 /*
  * A weight of 0 or 1 can cause arithmetics problems.
@@ -348,11 +310,7 @@
 {
 	struct task_group *tg;
 
-#ifdef CONFIG_USER_SCHED
-	rcu_read_lock();
-	tg = __task_cred(p)->user->tg;
-	rcu_read_unlock();
-#elif defined(CONFIG_CGROUP_SCHED)
+#ifdef CONFIG_CGROUP_SCHED
 	tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
 				struct task_group, css);
 #else
@@ -383,7 +341,7 @@
 	return NULL;
 }
 
-#endif	/* CONFIG_GROUP_SCHED */
+#endif	/* CONFIG_CGROUP_SCHED */
 
 /* CFS-related fields in a runqueue */
 struct cfs_rq {
@@ -542,7 +500,6 @@
 	struct load_weight load;
 	unsigned long nr_load_updates;
 	u64 nr_switches;
-	u64 nr_migrations_in;
 
 	struct cfs_rq cfs;
 	struct rt_rq rt;
@@ -568,6 +525,7 @@
 	struct mm_struct *prev_mm;
 
 	u64 clock;
+	u64 clock_task;
 
 	atomic_t nr_iowait;
 
@@ -575,6 +533,8 @@
 	struct root_domain *rd;
 	struct sched_domain *sd;
 
+	unsigned long cpu_power;
+
 	unsigned char idle_at_tick;
 	/* For active balancing */
 	int post_schedule;
@@ -591,6 +551,12 @@
 
 	u64 rt_avg;
 	u64 age_stamp;
+	u64 idle_stamp;
+	u64 avg_idle;
+#endif
+
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+	u64 prev_irq_time;
 #endif
 
 	/* calc_load related fields */
@@ -630,11 +596,7 @@
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
 
-static inline
-void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
-{
-	rq->curr->sched_class->check_preempt_curr(rq, p, flags);
-}
+static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags);
 
 static inline int cpu_of(struct rq *rq)
 {
@@ -661,9 +623,20 @@
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 #define raw_rq()		(&__raw_get_cpu_var(runqueues))
 
+static u64 irq_time_cpu(int cpu);
+static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+
 inline void update_rq_clock(struct rq *rq)
 {
+	int cpu = cpu_of(rq);
+	u64 irq_time;
+
 	rq->clock = sched_clock_cpu(cpu_of(rq));
+	irq_time = irq_time_cpu(cpu);
+	if (rq->clock - irq_time > rq->clock_task)
+		rq->clock_task = rq->clock - irq_time;
+
+	sched_irq_time_avg_update(rq, irq_time);
 }
 
 /*
@@ -740,7 +713,7 @@
 		size_t cnt, loff_t *ppos)
 {
 	char buf[64];
-	char *cmp = buf;
+	char *cmp;
 	int neg = 0;
 	int i;
 
@@ -751,6 +724,7 @@
 		return -EFAULT;
 
 	buf[cnt] = 0;
+	cmp = strstrip(buf);
 
 	if (strncmp(buf, "NO_", 3) == 0) {
 		neg = 1;
@@ -758,9 +732,7 @@
 	}
 
 	for (i = 0; sched_feat_names[i]; i++) {
-		int len = strlen(sched_feat_names[i]);
-
-		if (strncmp(cmp, sched_feat_names[i], len) == 0) {
+		if (strcmp(cmp, sched_feat_names[i]) == 0) {
 			if (neg)
 				sysctl_sched_features &= ~(1UL << i);
 			else
@@ -814,6 +786,7 @@
  * default: 0.25ms
  */
 unsigned int sysctl_sched_shares_ratelimit = 250000;
+unsigned int normalized_sysctl_sched_shares_ratelimit = 250000;
 
 /*
  * Inject some fuzzyness into changing the per-cpu group shares
@@ -940,14 +913,25 @@
 #endif /* __ARCH_WANT_UNLOCKED_CTXSW */
 
 /*
+ * Check whether the task is waking, we use this to synchronize ->cpus_allowed
+ * against ttwu().
+ */
+static inline int task_is_waking(struct task_struct *p)
+{
+	return unlikely(p->state == TASK_WAKING);
+}
+
+/*
  * __task_rq_lock - lock the runqueue a given task resides on.
  * Must be called interrupts disabled.
  */
 static inline struct rq *__task_rq_lock(struct task_struct *p)
 	__acquires(rq->lock)
 {
+	struct rq *rq;
+
 	for (;;) {
-		struct rq *rq = task_rq(p);
+		rq = task_rq(p);
 		spin_lock(&rq->lock);
 		if (likely(rq == task_rq(p)))
 			return rq;
@@ -1258,6 +1242,12 @@
 	s64 period = sched_avg_period();
 
 	while ((s64)(rq->clock - rq->age_stamp) > period) {
+		/*
+		 * Inline assembly required to prevent the compiler
+		 * optimising this loop into a divmod call.
+		 * See __iter_div_u64_rem() for another example of this.
+		 */
+		asm("" : "+rm" (rq->age_stamp));
 		rq->age_stamp += period;
 		rq->rt_avg /= 2;
 	}
@@ -1279,6 +1269,10 @@
 static void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
 {
 }
+
+static void sched_avg_update(struct rq *rq)
+{
+}
 #endif /* CONFIG_SMP */
 
 #if BITS_PER_LONG == 32
@@ -1528,24 +1522,9 @@
 	return max(rq->cpu_load[type-1], total);
 }
 
-static struct sched_group *group_of(int cpu)
-{
-	struct sched_domain *sd = rcu_dereference(cpu_rq(cpu)->sd);
-
-	if (!sd)
-		return NULL;
-
-	return sd->groups;
-}
-
 static unsigned long power_of(int cpu)
 {
-	struct sched_group *group = group_of(cpu);
-
-	if (!group)
-		return SCHED_LOAD_SCALE;
-
-	return group->cpu_power;
+	return cpu_rq(cpu)->cpu_power;
 }
 
 static int task_hot(struct task_struct *p, u64 now, struct sched_domain *sd);
@@ -1614,7 +1593,7 @@
  */
 static int tg_shares_up(struct task_group *tg, void *data)
 {
-	unsigned long weight, rq_weight = 0, shares = 0;
+	unsigned long weight, rq_weight = 0, sum_weight = 0, shares = 0;
 	unsigned long *usd_rq_weight;
 	struct sched_domain *sd = data;
 	unsigned long flags;
@@ -1630,6 +1609,7 @@
 		weight = tg->cfs_rq[i]->load.weight;
 		usd_rq_weight[i] = weight;
 
+		rq_weight += weight;
 		/*
 		 * If there are currently no tasks on the cpu pretend there
 		 * is one of average load so that when a new task gets to
@@ -1638,10 +1618,13 @@
 		if (!weight)
 			weight = NICE_0_LOAD;
 
-		rq_weight += weight;
+		sum_weight += weight;
 		shares += tg->cfs_rq[i]->shares;
 	}
 
+	if (!rq_weight)
+		rq_weight = sum_weight;
+
 	if ((!shares && rq_weight) || shares > tg->shares)
 		shares = tg->shares;
 
@@ -1708,9 +1691,6 @@
 
 static void update_h_load(long cpu)
 {
-	if (root_task_group_empty())
-		return;
-
 	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);
 }
 
@@ -1810,6 +1790,109 @@
 #endif
 
 static void calc_load_account_active(struct rq *this_rq);
+static void update_sysctl(void);
+
+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
+{
+	set_task_rq(p, cpu);
+#ifdef CONFIG_SMP
+	/*
+	 * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be
+	 * successfuly executed on another CPU. We must ensure that updates of
+	 * per-task data have been completed by this moment.
+	 */
+	smp_wmb();
+	task_thread_info(p)->cpu = cpu;
+#endif
+}
+
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+
+/*
+ * There are no locks covering percpu hardirq/softirq time.
+ * They are only modified in account_system_vtime, on corresponding CPU
+ * with interrupts disabled. So, writes are safe.
+ * They are read and saved off onto struct rq in update_rq_clock().
+ * This may result in other CPU reading this CPU's irq time and can
+ * race with irq/account_system_vtime on this CPU. We would either get old
+ * or new value (or semi updated value on 32 bit) with a side effect of
+ * accounting a slice of irq time to wrong task when irq is in progress
+ * while we read rq->clock. That is a worthy compromise in place of having
+ * locks on each irq in account_system_time.
+ */
+static DEFINE_PER_CPU(u64, cpu_hardirq_time);
+static DEFINE_PER_CPU(u64, cpu_softirq_time);
+
+static DEFINE_PER_CPU(u64, irq_start_time);
+static int sched_clock_irqtime;
+
+void enable_sched_clock_irqtime(void)
+{
+	sched_clock_irqtime = 1;
+}
+
+void disable_sched_clock_irqtime(void)
+{
+	sched_clock_irqtime = 0;
+}
+
+static u64 irq_time_cpu(int cpu)
+{
+	if (!sched_clock_irqtime)
+		return 0;
+
+	return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
+}
+
+void account_system_vtime(struct task_struct *curr)
+{
+	unsigned long flags;
+	int cpu;
+	u64 now, delta;
+
+	if (!sched_clock_irqtime)
+		return;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+	now = sched_clock_cpu(cpu);
+	delta = now - per_cpu(irq_start_time, cpu);
+	per_cpu(irq_start_time, cpu) = now;
+	/*
+	 * We do not account for softirq time from ksoftirqd here.
+	 * We want to continue accounting softirq time to ksoftirqd thread
+	 * in that case, so as not to confuse scheduler with a special task
+	 * that do not consume any time, but still wants to run.
+	 */
+	if (hardirq_count())
+		per_cpu(cpu_hardirq_time, cpu) += delta;
+	else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
+		per_cpu(cpu_softirq_time, cpu) += delta;
+
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(account_system_vtime);
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+{
+	if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
+		u64 delta_irq = curr_irq_time - rq->prev_irq_time;
+		rq->prev_irq_time = curr_irq_time;
+		sched_rt_avg_update(rq, delta_irq);
+	}
+}
+
+#else
+
+static u64 irq_time_cpu(int cpu)
+{
+	return 0;
+}
+
+static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
+
+#endif
 
 #include "sched_stats.h"
 #include "sched_idletask.c"
@@ -1836,8 +1919,8 @@
 static void set_load_weight(struct task_struct *p)
 {
 	if (task_has_rt_policy(p)) {
-		p->se.load.weight = prio_to_weight[0] * 2;
-		p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+		p->se.load.weight = 0;
+		p->se.load.inv_weight = WMULT_CONST;
 		return;
 	}
 
@@ -1860,13 +1943,14 @@
 	*avg += diff >> 3;
 }
 
-static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup)
+static void
+enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head)
 {
 	if (wakeup)
 		p->se.start_runtime = p->se.sum_exec_runtime;
 
 	sched_info_queued(p);
-	p->sched_class->enqueue_task(rq, p, wakeup);
+	p->sched_class->enqueue_task(rq, p, wakeup, head);
 	p->se.on_rq = 1;
 }
 
@@ -1942,7 +2026,7 @@
 	if (task_contributes_to_load(p))
 		rq->nr_uninterruptible--;
 
-	enqueue_task(rq, p, wakeup);
+	enqueue_task(rq, p, wakeup, false);
 	inc_nr_running(rq);
 }
 
@@ -1967,20 +2051,6 @@
 	return cpu_curr(task_cpu(p)) == p;
 }
 
-static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
-{
-	set_task_rq(p, cpu);
-#ifdef CONFIG_SMP
-	/*
-	 * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be
-	 * successfuly executed on another CPU. We must ensure that updates of
-	 * per-task data have been completed by this moment.
-	 */
-	smp_wmb();
-	task_thread_info(p)->cpu = cpu;
-#endif
-}
-
 static inline void check_class_changed(struct rq *rq, struct task_struct *p,
 				       const struct sched_class *prev_class,
 				       int oldprio, int running)
@@ -2007,21 +2077,15 @@
  */
 void kthread_bind(struct task_struct *p, unsigned int cpu)
 {
-	struct rq *rq = cpu_rq(cpu);
-	unsigned long flags;
-
 	/* Must have done schedule() in kthread() before we set_task_cpu */
 	if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
 		WARN_ON(1);
 		return;
 	}
 
-	spin_lock_irqsave(&rq->lock, flags);
-	set_task_cpu(p, cpu);
 	p->cpus_allowed = cpumask_of_cpu(cpu);
 	p->rt.nr_cpus_allowed = 1;
 	p->flags |= PF_THREAD_BOUND;
-	spin_unlock_irqrestore(&rq->lock, flags);
 }
 EXPORT_SYMBOL(kthread_bind);
 
@@ -2034,6 +2098,12 @@
 {
 	s64 delta;
 
+	if (p->sched_class != &fair_sched_class)
+		return 0;
+
+	if (unlikely(p->policy == SCHED_IDLE))
+		return 0;
+
 	/*
 	 * Buddy candidates are cache hot:
 	 */
@@ -2042,9 +2112,6 @@
 			 &p->se == cfs_rq_of(&p->se)->last))
 		return 1;
 
-	if (p->sched_class != &fair_sched_class)
-		return 0;
-
 	if (sysctl_sched_migration_cost == -1)
 		return 1;
 	if (sysctl_sched_migration_cost == 0)
@@ -2059,35 +2126,23 @@
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
 	int old_cpu = task_cpu(p);
-	struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
-	struct cfs_rq *old_cfsrq = task_cfs_rq(p),
-		      *new_cfsrq = cpu_cfs_rq(old_cfsrq, new_cpu);
-	u64 clock_offset;
 
-	clock_offset = old_rq->clock - new_rq->clock;
+#ifdef CONFIG_SCHED_DEBUG
+	/*
+	 * We should never call set_task_cpu() on a blocked task,
+	 * ttwu() will sort out the placement.
+	 */
+	WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
+			!(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
+#endif
 
 	trace_sched_migrate_task(p, new_cpu);
 
-#ifdef CONFIG_SCHEDSTATS
-	if (p->se.wait_start)
-		p->se.wait_start -= clock_offset;
-	if (p->se.sleep_start)
-		p->se.sleep_start -= clock_offset;
-	if (p->se.block_start)
-		p->se.block_start -= clock_offset;
-#endif
 	if (old_cpu != new_cpu) {
 		p->se.nr_migrations++;
-		new_rq->nr_migrations_in++;
-#ifdef CONFIG_SCHEDSTATS
-		if (task_hot(p, old_rq->clock, NULL))
-			schedstat_inc(p, se.nr_forced2_migrations);
-#endif
 		perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS,
 				     1, 1, NULL, 0);
 	}
-	p->se.vruntime -= old_cfsrq->min_vruntime -
-					 new_cfsrq->min_vruntime;
 
 	__set_task_cpu(p, new_cpu);
 }
@@ -2112,12 +2167,10 @@
 
 	/*
 	 * If the task is not on a runqueue (and not running), then
-	 * it is sufficient to simply update the task's cpu field.
+	 * the next wake-up will properly place the task.
 	 */
-	if (!p->se.on_rq && !task_running(rq, p)) {
-		set_task_cpu(p, dest_cpu);
+	if (!p->se.on_rq && !task_running(rq, p))
 		return 0;
-	}
 
 	init_completion(&req->done);
 	req->task = p;
@@ -2322,6 +2375,87 @@
 	preempt_enable();
 }
 
+static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
+{
+	const struct sched_class *class;
+
+	if (p->sched_class == rq->curr->sched_class) {
+		rq->curr->sched_class->check_preempt_curr(rq, p, flags);
+	} else {
+		for_each_class(class) {
+			if (class == rq->curr->sched_class)
+				break;
+			if (class == p->sched_class) {
+				resched_task(rq->curr);
+				break;
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_SMP
+/*
+ * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held.
+ */
+static int select_fallback_rq(int cpu, struct task_struct *p)
+{
+	int dest_cpu;
+	const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(cpu));
+
+	/* Look for allowed, online CPU in same node. */
+	for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
+		if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
+			return dest_cpu;
+
+	/* Any allowed, online CPU? */
+	dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask);
+	if (dest_cpu < nr_cpu_ids)
+		return dest_cpu;
+
+	/* No more Mr. Nice Guy. */
+	if (unlikely(dest_cpu >= nr_cpu_ids)) {
+		dest_cpu = cpuset_cpus_allowed_fallback(p);
+		/*
+		 * Don't tell them about moving exiting tasks or
+		 * kernel threads (both mm NULL), since they never
+		 * leave kernel.
+		 */
+		if (p->mm && printk_ratelimit()) {
+			printk(KERN_INFO "process %d (%s) no "
+			       "longer affine to cpu%d\n",
+			       task_pid_nr(p), p->comm, cpu);
+		}
+	}
+
+	return dest_cpu;
+}
+
+/*
+ * The caller (fork, wakeup) owns TASK_WAKING, ->cpus_allowed is stable.
+ */
+static inline
+int select_task_rq(struct rq *rq, struct task_struct *p, int sd_flags, int wake_flags)
+{
+	int cpu = p->sched_class->select_task_rq(rq, p, sd_flags, wake_flags);
+
+	/*
+	 * In order not to call set_task_cpu() on a blocking task we need
+	 * to rely on ttwu() to place the task on a valid ->cpus_allowed
+	 * cpu.
+	 *
+	 * Since this is common to all placement strategies, this lives here.
+	 *
+	 * [ this allows ->select_task() to simply return task_cpu(p) and
+	 *   not worry about this generic constraint ]
+	 */
+	if (unlikely(!cpumask_test_cpu(cpu, &p->cpus_allowed) ||
+		     !cpu_online(cpu)))
+		cpu = select_fallback_rq(task_cpu(p), p);
+
+	return cpu;
+}
+#endif
+
 /***
  * try_to_wake_up - wake up a thread
  * @p: the to-be-woken-up thread
@@ -2370,22 +2504,34 @@
 	 *
 	 * First fix up the nr_uninterruptible count:
 	 */
-	if (task_contributes_to_load(p))
-		rq->nr_uninterruptible--;
+	if (task_contributes_to_load(p)) {
+		if (likely(cpu_online(orig_cpu)))
+			rq->nr_uninterruptible--;
+		else
+			this_rq()->nr_uninterruptible--;
+	}
 	p->state = TASK_WAKING;
-	task_rq_unlock(rq, &flags);
 
-	cpu = p->sched_class->select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
+	if (p->sched_class->task_waking)
+		p->sched_class->task_waking(rq, p);
+
+	cpu = select_task_rq(rq, p, SD_BALANCE_WAKE, wake_flags);
 	if (cpu != orig_cpu)
 		set_task_cpu(p, cpu);
+	__task_rq_unlock(rq);
 
-	rq = task_rq_lock(p, &flags);
-
-	if (rq != orig_rq)
-		update_rq_clock(rq);
+	rq = cpu_rq(cpu);
+	spin_lock(&rq->lock);
+	update_rq_clock(rq);
 
+	/*
+	 * We migrated the task without holding either rq->lock, however
+	 * since the task is not on the task list itself, nobody else
+	 * will try and migrate the task, hence the rq should match the
+	 * cpu we just moved it to.
+	 */
+	WARN_ON(task_cpu(p) != cpu);
 	WARN_ON(p->state != TASK_WAKING);
-	cpu = task_cpu(p);
 
 #ifdef CONFIG_SCHEDSTATS
 	schedstat_inc(rq, ttwu_count);
@@ -2438,8 +2584,19 @@
 
 	p->state = TASK_RUNNING;
 #ifdef CONFIG_SMP
-	if (p->sched_class->task_wake_up)
-		p->sched_class->task_wake_up(rq, p);
+	if (p->sched_class->task_woken)
+		p->sched_class->task_woken(rq, p);
+
+	if (unlikely(rq->idle_stamp)) {
+		u64 delta = rq->clock - rq->idle_stamp;
+		u64 max = 2*sysctl_sched_migration_cost;
+
+		if (delta > max)
+			rq->avg_idle = max;
+		else
+			update_avg(&rq->avg_idle, delta);
+		rq->idle_stamp = 0;
+	}
 #endif
 out:
 	task_rq_unlock(rq, &flags);
@@ -2508,7 +2665,6 @@
 	p->se.nr_failed_migrations_running	= 0;
 	p->se.nr_failed_migrations_hot		= 0;
 	p->se.nr_forced_migrations		= 0;
-	p->se.nr_forced2_migrations		= 0;
 
 	p->se.nr_wakeups			= 0;
 	p->se.nr_wakeups_sync			= 0;
@@ -2529,14 +2685,6 @@
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 	INIT_HLIST_HEAD(&p->preempt_notifiers);
 #endif
-
-	/*
-	 * We mark the process as running here, but have not actually
-	 * inserted it onto the runqueue yet. This guarantees that
-	 * nobody will actually run it, and a signal or other external
-	 * event cannot wake it up and insert it on the runqueue either.
-	 */
-	p->state = TASK_RUNNING;
 }
 
 /*
@@ -2547,6 +2695,12 @@
 	int cpu = get_cpu();
 
 	__sched_fork(p);
+	/*
+	 * We mark the process as running here. This guarantees that
+	 * nobody will actually run it, and a signal or other external
+	 * event cannot wake it up and insert it on the runqueue either.
+	 */
+	p->state = TASK_RUNNING;
 
 	/*
 	 * Revert to default priority/policy on fork if requested.
@@ -2578,9 +2732,9 @@
 	if (!rt_prio(p->prio))
 		p->sched_class = &fair_sched_class;
 
-#ifdef CONFIG_SMP
-	cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0);
-#endif
+	if (p->sched_class->task_fork)
+		p->sched_class->task_fork(p);
+
 	set_task_cpu(p, cpu);
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
@@ -2610,28 +2764,38 @@
 {
 	unsigned long flags;
 	struct rq *rq;
+	int cpu = get_cpu();
 
+#ifdef CONFIG_SMP
 	rq = task_rq_lock(p, &flags);
-	BUG_ON(p->state != TASK_RUNNING);
-	update_rq_clock(rq);
+	p->state = TASK_WAKING;
 
-	if (!p->sched_class->task_new || !current->se.on_rq) {
-		activate_task(rq, p, 0);
-	} else {
-		/*
-		 * Let the scheduling class do new task startup
-		 * management (if any):
-		 */
-		p->sched_class->task_new(rq, p);
-		inc_nr_running(rq);
-	}
+	/*
+	 * Fork balancing, do it here and not earlier because:
+	 *  - cpus_allowed can change in the fork path
+	 *  - any previously selected cpu might disappear through hotplug
+	 *
+	 * We set TASK_WAKING so that select_task_rq() can drop rq->lock
+	 * without people poking at ->cpus_allowed.
+	 */
+	cpu = select_task_rq(rq, p, SD_BALANCE_FORK, 0);
+	set_task_cpu(p, cpu);
+
+	p->state = TASK_RUNNING;
+	task_rq_unlock(rq, &flags);
+#endif
+
+	rq = task_rq_lock(p, &flags);
+	update_rq_clock(rq);
+	activate_task(rq, p, 0);
 	trace_sched_wakeup_new(rq, p, 1);
 	check_preempt_curr(rq, p, WF_FORK);
 #ifdef CONFIG_SMP
-	if (p->sched_class->task_wake_up)
-		p->sched_class->task_wake_up(rq, p);
+	if (p->sched_class->task_woken)
+		p->sched_class->task_woken(rq, p);
 #endif
 	task_rq_unlock(rq, &flags);
+	put_cpu();
 }
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
@@ -3018,15 +3182,6 @@
 }
 
 /*
- * Externally visible per-cpu scheduler statistics:
- * cpu_nr_migrations(cpu) - number of migrations into that cpu
- */
-u64 cpu_nr_migrations(int cpu)
-{
-	return cpu_rq(cpu)->nr_migrations_in;
-}
-
-/*
  * Update rq->cpu_load[] statistics. This function is usually called every
  * scheduler tick (TICK_NSEC).
  */
@@ -3059,6 +3214,8 @@
 		this_rq->calc_load_update += LOAD_FREQ;
 		calc_load_account_active(this_rq);
 	}
+
+	sched_avg_update(this_rq);
 }
 
 #ifdef CONFIG_SMP
@@ -3108,50 +3265,41 @@
 }
 
 /*
- * If dest_cpu is allowed for this process, migrate the task to it.
- * This is accomplished by forcing the cpu_allowed mask to only
- * allow dest_cpu, which will force the cpu onto dest_cpu. Then
- * the cpu_allowed mask is restored.
+ * sched_exec - execve() is a valuable balancing opportunity, because at
+ * this point the task has the smallest effective memory and cache footprint.
  */
-static void sched_migrate_task(struct task_struct *p, int dest_cpu)
+void sched_exec(void)
 {
+	struct task_struct *p = current;
 	struct migration_req req;
 	unsigned long flags;
 	struct rq *rq;
+	int dest_cpu;
 
 	rq = task_rq_lock(p, &flags);
-	if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed)
-	    || unlikely(!cpu_active(dest_cpu)))
-		goto out;
+	dest_cpu = p->sched_class->select_task_rq(rq, p, SD_BALANCE_EXEC, 0);
+	if (dest_cpu == smp_processor_id())
+		goto unlock;
 
-	/* force the process onto the specified CPU */
-	if (migrate_task(p, dest_cpu, &req)) {
+	/*
+	 * select_task_rq() can race against ->cpus_allowed
+	 */
+	if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) &&
+	    likely(cpu_active(dest_cpu)) &&
+	    migrate_task(p, dest_cpu, &req)) {
 		/* Need to wait for migration thread (might exit: take ref). */
 		struct task_struct *mt = rq->migration_thread;
 
 		get_task_struct(mt);
-		task_rq_unlock(rq, &flags);
-		wake_up_process(mt);
-		put_task_struct(mt);
-		wait_for_completion(&req.done);
-
-		return;
-	}
-out:
-	task_rq_unlock(rq, &flags);
-}
-
-/*
- * sched_exec - execve() is a valuable balancing opportunity, because at
- * this point the task has the smallest effective memory and cache footprint.
- */
-void sched_exec(void)
-{
-	int new_cpu, this_cpu = get_cpu();
-	new_cpu = current->sched_class->select_task_rq(current, SD_BALANCE_EXEC, 0);
-	put_cpu();
-	if (new_cpu != this_cpu)
-		sched_migrate_task(current, new_cpu);
+		task_rq_unlock(rq, &flags);
+		wake_up_process(mt);
+		put_task_struct(mt);
+		wait_for_completion(&req.done);
+
+		return;
+	}
+unlock:
+	task_rq_unlock(rq, &flags);
 }
 
 /*
@@ -3164,10 +3312,6 @@
 	deactivate_task(src_rq, p, 0);
 	set_task_cpu(p, this_cpu);
 	activate_task(this_rq, p, 0);
-	/*
-	 * Note that idle threads have a prio of MAX_PRIO, for this test
-	 * to be always true for them.
-	 */
 	check_preempt_curr(this_rq, p, 0);
 }
 
@@ -3203,7 +3347,7 @@
 	 * 2) too many balance attempts have failed.
 	 */
 
-	tsk_cache_hot = task_hot(p, rq->clock, sd);
+	tsk_cache_hot = task_hot(p, rq->clock_task, sd);
 	if (!tsk_cache_hot ||
 		sd->nr_balance_failed > sd->cache_nice_tries) {
 #ifdef CONFIG_SCHEDSTATS
@@ -3386,11 +3530,17 @@
 	unsigned long this_load;
 	unsigned long this_load_per_task;
 	unsigned long this_nr_running;
+	unsigned long this_has_capacity;
+	unsigned int  this_idle_cpus;
 
 	/* Statistics of the busiest group */
+	unsigned int  busiest_idle_cpus;
 	unsigned long max_load;
 	unsigned long busiest_load_per_task;
 	unsigned long busiest_nr_running;
+	unsigned long busiest_group_capacity;
+	unsigned long busiest_has_capacity;
+	unsigned int  busiest_group_weight;
 
 	int group_imb; /* Is there imbalance in this sd */
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
@@ -3412,7 +3562,10 @@
 	unsigned long sum_nr_running; /* Nr tasks running in the group */
 	unsigned long sum_weighted_load; /* Weighted load of group's tasks */
 	unsigned long group_capacity;
+	unsigned long idle_cpus;
+	unsigned long group_weight;
 	int group_imb; /* Is there an imbalance in the group ? */
+	int group_has_capacity; /* Is there extra capacity in the group? */
 };
 
 /**
@@ -3604,7 +3757,7 @@
 
 unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu)
 {
-	unsigned long weight = cpumask_weight(sched_domain_span(sd));
+	unsigned long weight = sd->span_weight;
 	unsigned long smt_gain = sd->smt_gain;
 
 	smt_gain /= weight;
@@ -3622,10 +3775,14 @@
 	struct rq *rq = cpu_rq(cpu);
 	u64 total, available;
 
-	sched_avg_update(rq);
-
 	total = sched_avg_period() + (rq->clock - rq->age_stamp);
-	available = total - rq->rt_avg;
+
+	if (unlikely(total < rq->rt_avg)) {
+		/* Ensures that power won't end up being negative */
+		available = 0;
+	} else {
+		available = total - rq->rt_avg;
+	}
 
 	if (unlikely((s64)total < SCHED_LOAD_SCALE))
 		total = SCHED_LOAD_SCALE;
@@ -3637,9 +3794,10 @@
 
 static void update_cpu_power(struct sched_domain *sd, int cpu)
 {
-	unsigned long weight = cpumask_weight(sched_domain_span(sd));
+	unsigned long weight = sd->span_weight;
 	unsigned long power = SCHED_LOAD_SCALE;
 	struct sched_group *sdg = sd->groups;
+	unsigned long scale_rt;
 
 	if (sched_feat(ARCH_POWER))
 		power *= arch_scale_freq_power(sd, cpu);
@@ -3657,12 +3815,19 @@
 		power >>= SCHED_LOAD_SHIFT;
 	}
 
-	power *= scale_rt_power(cpu);
+	scale_rt = scale_rt_power(cpu);
+	power *= scale_rt;
+
 	power >>= SCHED_LOAD_SHIFT;
 
 	if (!power)
 		power = 1;
 
+	if (WARN_ON((long) power <= 0))
+		printk(KERN_ERR "cpu_power = %ld; scale_rt = %ld\n",
+			power, scale_rt);
+
+	cpu_rq(cpu)->cpu_power = power;
 	sdg->cpu_power = power;
 }
 
@@ -3686,6 +3851,9 @@
 	} while (group != child->groups);
 
 	sdg->cpu_power = power;
+
+	if (WARN_ON((long) power <= 0))
+		printk(KERN_ERR "cpu_power = %ld\n", power);
 }
 
 /**
@@ -3707,11 +3875,10 @@
 			int local_group, const struct cpumask *cpus,
 			int *balance, struct sg_lb_stats *sgs)
 {
-	unsigned long load, max_cpu_load, min_cpu_load;
+	unsigned long load, max_cpu_load, min_cpu_load, max_nr_running;
 	int i;
 	unsigned int balance_cpu = -1, first_idle_cpu = 0;
-	unsigned long sum_avg_load_per_task;
-	unsigned long avg_load_per_task;
+	unsigned long avg_load_per_task = 0;
 
 	if (local_group) {
 		balance_cpu = group_first_cpu(group);
@@ -3720,9 +3887,9 @@
 	}
 
 	/* Tally up the load of all CPUs in the group */
-	sum_avg_load_per_task = avg_load_per_task = 0;
 	max_cpu_load = 0;
 	min_cpu_load = ~0UL;
+	max_nr_running = 0;
 
 	for_each_cpu_and(i, sched_group_cpus(group), cpus) {
 		struct rq *rq = cpu_rq(i);
@@ -3740,8 +3907,10 @@
 			load = target_load(i, load_idx);
 		} else {
 			load = source_load(i, load_idx);
-			if (load > max_cpu_load)
+			if (load > max_cpu_load) {
 				max_cpu_load = load;
+				max_nr_running = rq->nr_running;
+			}
 			if (min_cpu_load > load)
 				min_cpu_load = load;
 		}
@@ -3749,8 +3918,8 @@
 		sgs->group_load += load;
 		sgs->sum_nr_running += rq->nr_running;
 		sgs->sum_weighted_load += weighted_cpuload(i);
-
-		sum_avg_load_per_task += cpu_avg_load_per_task(i);
+		if (idle_cpu(i))
+			sgs->idle_cpus++;
 	}
 
 	/*
@@ -3766,8 +3935,9 @@
 	}
 
 	/* Adjust by relative CPU power of the group */
-	sgs->avg_load = (sgs->group_load * SCHED_LOAD_SCALE) / group->cpu_power;
-
+	sgs->avg_load = (sgs->group_load * SCHED_LOAD_SCALE);
+	if (group->cpu_power)
+		sgs->avg_load /= group->cpu_power;
 
 	/*
 	 * Consider the group unbalanced when the imbalance is larger
@@ -3778,14 +3948,17 @@
 	 *      normalized nr_running number somewhere that negates
 	 *      the hierarchy?
 	 */
-	avg_load_per_task = (sum_avg_load_per_task * SCHED_LOAD_SCALE) /
-		group->cpu_power;
+	if (sgs->sum_nr_running)
+		avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
 
-	if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task)
+	if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task && max_nr_running > 1)
 		sgs->group_imb = 1;
 
-	sgs->group_capacity =
-		DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
+	sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
+	sgs->group_weight = group->group_weight;
+
+	if (sgs->group_capacity > sgs->sum_nr_running)
+		sgs->group_has_capacity = 1;
 }
 
 /**
@@ -3832,9 +4005,14 @@
 		/*
 		 * In case the child domain prefers tasks go to siblings
 		 * first, lower the group capacity to one so that we'll try
-		 * and move all the excess tasks away.
+		 * and move all the excess tasks away. We lower the capacity
+		 * of a group only if the local group has the capacity to fit
+		 * these excess tasks, i.e. nr_running < group_capacity. The
+		 * extra check prevents the case where you always pull from the
+		 * heaviest group when it is already under-utilized (possible
+		 * with a large weight task outweighs the tasks on the system).
 		 */
-		if (prefer_sibling)
+		if (prefer_sibling && !local_group && sds->this_has_capacity)
 			sgs.group_capacity = min(sgs.group_capacity, 1UL);
 
 		if (local_group) {
@@ -3842,13 +4020,19 @@
 			sds->this = group;
 			sds->this_nr_running = sgs.sum_nr_running;
 			sds->this_load_per_task = sgs.sum_weighted_load;
+			sds->this_has_capacity = sgs.group_has_capacity;
+			sds->this_idle_cpus = sgs.idle_cpus;
 		} else if (sgs.avg_load > sds->max_load &&
 			   (sgs.sum_nr_running > sgs.group_capacity ||
 				sgs.group_imb)) {
 			sds->max_load = sgs.avg_load;
 			sds->busiest = group;
 			sds->busiest_nr_running = sgs.sum_nr_running;
+			sds->busiest_idle_cpus = sgs.idle_cpus;
+			sds->busiest_group_capacity = sgs.group_capacity;
+			sds->busiest_group_weight = sgs.group_weight;
 			sds->busiest_load_per_task = sgs.sum_weighted_load;
+			sds->busiest_has_capacity = sgs.group_has_capacity;
 			sds->group_imb = sgs.group_imb;
 		}
 
@@ -3870,6 +4054,7 @@
 {
 	unsigned long tmp, pwr_now = 0, pwr_move = 0;
 	unsigned int imbn = 2;
+	unsigned long scaled_busy_load_per_task;
 
 	if (sds->this_nr_running) {
 		sds->this_load_per_task /= sds->this_nr_running;
@@ -3880,8 +4065,12 @@
 		sds->this_load_per_task =
 			cpu_avg_load_per_task(this_cpu);
 
-	if (sds->max_load - sds->this_load + sds->busiest_load_per_task >=
-			sds->busiest_load_per_task * imbn) {
+	scaled_busy_load_per_task = sds->busiest_load_per_task
+						 * SCHED_LOAD_SCALE;
+	scaled_busy_load_per_task /= sds->busiest->cpu_power;
+
+	if (sds->max_load - sds->this_load + scaled_busy_load_per_task >=
+			(scaled_busy_load_per_task * imbn)) {
 		*imbalance = sds->busiest_load_per_task;
 		return;
 	}
@@ -3932,7 +4121,14 @@
 static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
 		unsigned long *imbalance)
 {
-	unsigned long max_pull;
+	unsigned long max_pull, load_above_capacity = ~0UL;
+
+	sds->busiest_load_per_task /= sds->busiest_nr_running;
+	if (sds->group_imb) {
+		sds->busiest_load_per_task =
+			min(sds->busiest_load_per_task, sds->avg_load);
+	}
+
 	/*
 	 * In the presence of smp nice balancing, certain scenarios can have
 	 * max load less than avg load(as we skip the groups at or below
@@ -3943,9 +4139,29 @@
 		return fix_small_imbalance(sds, this_cpu, imbalance);
 	}
 
-	/* Don't want to pull so many tasks that a group would go idle */
-	max_pull = min(sds->max_load - sds->avg_load,
-			sds->max_load - sds->busiest_load_per_task);
+	if (!sds->group_imb) {
+		/*
+		 * Don't want to pull so many tasks that a group would go idle.
+		 */
+		load_above_capacity = (sds->busiest_nr_running -
+						sds->busiest_group_capacity);
+
+		load_above_capacity *= (SCHED_LOAD_SCALE * SCHED_LOAD_SCALE);
+
+		load_above_capacity /= sds->busiest->cpu_power;
+	}
+
+	/*
+	 * We're trying to get all the cpus to the average_load, so we don't
+	 * want to push ourselves above the average load, nor do we wish to
+	 * reduce the max loaded cpu below the average load. At the same time,
+	 * we also don't want to reduce the group load below the group capacity
+	 * (so that we can implement power-savings policies etc). Thus we look
+	 * for the minimum possible imbalance.
+	 * Be careful of negative numbers as they'll appear as very large values
+	 * with unsigned longs.
+	 */
+	max_pull = min(sds->max_load - sds->avg_load, load_above_capacity);
 
 	/* How much load to actually move to equalise the imbalance */
 	*imbalance = min(max_pull * sds->busiest->cpu_power,
@@ -3962,6 +4178,7 @@
 		return fix_small_imbalance(sds, this_cpu, imbalance);
 
 }
+
 /******* find_busiest_group() helpers end here *********************/
 
 /**
@@ -4013,14 +4230,23 @@
 	 * 4) This group is more busy than the avg busieness at this
 	 *    sched_domain.
 	 * 5) The imbalance is within the specified limit.
-	 * 6) Any rebalance would lead to ping-pong
+	 *
+	 * Note: when doing newidle balance, if the local group has excess
+	 * capacity (i.e. nr_running < group_capacity) and the busiest group
+	 * does not have any capacity, we force a load balance to pull tasks
+	 * to the local group. In this case, we skip past checks 3, 4 and 5.
 	 */
 	if (balance && !(*balance))
 		goto ret;
 
-	if (!sds.busiest || sds.busiest_nr_running == 0)
+	if (!sds.busiest || sds.busiest_nr_running == 0 || sds.total_pwr == 0)
 		goto out_balanced;
 
+	/*  SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
+	if (idle == CPU_NEWLY_IDLE && sds.this_has_capacity &&
+			!sds.busiest_has_capacity)
+		goto force_balance;
+
 	if (sds.this_load >= sds.max_load)
 		goto out_balanced;
 
@@ -4029,28 +4255,28 @@
 	if (sds.this_load >= sds.avg_load)
 		goto out_balanced;
 
-	if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
-		goto out_balanced;
-
-	sds.busiest_load_per_task /= sds.busiest_nr_running;
-	if (sds.group_imb)
-		sds.busiest_load_per_task =
-			min(sds.busiest_load_per_task, sds.avg_load);
-
 	/*
-	 * We're trying to get all the cpus to the average_load, so we don't
-	 * want to push ourselves above the average load, nor do we wish to
-	 * reduce the max loaded cpu below the average load, as either of these
-	 * actions would just result in more rebalancing later, and ping-pong
-	 * tasks around. Thus we look for the minimum possible imbalance.
-	 * Negative imbalances (*we* are more loaded than anyone else) will
-	 * be counted as no imbalance for these purposes -- we can't fix that
-	 * by pulling tasks to us. Be careful of negative numbers as they'll
-	 * appear as very large values with unsigned longs.
+	 * In the CPU_NEWLY_IDLE, use imbalance_pct to be conservative.
+	 * And to check for busy balance use !idle_cpu instead of
+	 * CPU_NOT_IDLE. This is because HT siblings will use CPU_NOT_IDLE
+	 * even when they are idle.
 	 */
-	if (sds.max_load <= sds.busiest_load_per_task)
-		goto out_balanced;
+	if (idle == CPU_NEWLY_IDLE || !idle_cpu(this_cpu)) {
+		if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
+			goto out_balanced;
+	} else {
+		/*
+		 * This cpu is idle. If the busiest group load doesn't
+		 * have more tasks than the number of available cpu's and
+		 * there is no imbalance between this and busiest group
+		 * wrt to idle cpu's, it is balanced.
+		 */
+		if ((sds.this_idle_cpus  <= sds.busiest_idle_cpus + 1) &&
+		    sds.busiest_nr_running <= sds.busiest_group_weight)
+			goto out_balanced;
+	}
 
+force_balance:
 	/* Looks like there is an imbalance. Compute it */
 	calculate_imbalance(&sds, this_cpu, imbalance);
 	return sds.busiest;
@@ -4087,12 +4313,25 @@
 			continue;
 
 		rq = cpu_rq(i);
-		wl = weighted_cpuload(i) * SCHED_LOAD_SCALE;
-		wl /= power;
+		wl = weighted_cpuload(i);
 
+		/*
+		 * When comparing with imbalance, use weighted_cpuload()
+		 * which is not scaled with the cpu power.
+		 */
 		if (capacity && rq->nr_running == 1 && wl > imbalance)
 			continue;
 
+		/*
+		 * For the load comparisons with the other cpu's, consider
+		 * the weighted_cpuload() scaled with the cpu power, so that
+		 * the load can be moved away from the cpu that is potentially
+		 * running at a lower capacity.
+		 */
+		wl = (wl * SCHED_LOAD_SCALE);
+		if (power)
+			wl /= power;
+
 		if (wl > max_load) {
 			max_load = wl;
 			busiest = rq;
@@ -4126,7 +4365,7 @@
 	unsigned long flags;
 	struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
-	cpumask_setall(cpus);
+	cpumask_copy(cpus, cpu_active_mask);
 
 	/*
 	 * When power savings policy is enabled for the parent domain, idle
@@ -4195,7 +4434,14 @@
 
 	if (!ld_moved) {
 		schedstat_inc(sd, lb_failed[idle]);
-		sd->nr_balance_failed++;
+		/*
+		 * Increment the failure counter only on periodic balance.
+		 * We do not want newidle balance, which can be very
+		 * frequent, pollute the failure counter causing
+		 * excessive cache_hot migrations and active balances.
+		 */
+		if (idle != CPU_NEWLY_IDLE)
+			sd->nr_balance_failed++;
 
 		if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
 
@@ -4289,7 +4535,7 @@
 	int all_pinned = 0;
 	struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
 
-	cpumask_setall(cpus);
+	cpumask_copy(cpus, cpu_active_mask);
 
 	/*
 	 * When power savings policy is enabled for the parent domain, idle
@@ -4429,6 +4675,11 @@
 	int pulled_task = 0;
 	unsigned long next_balance = jiffies + HZ;
 
+	this_rq->idle_stamp = this_rq->clock;
+
+	if (this_rq->avg_idle < sysctl_sched_migration_cost)
+		return;
+
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
 
@@ -4443,8 +4694,10 @@
 		interval = msecs_to_jiffies(sd->balance_interval);
 		if (time_after(next_balance, sd->last_balance + interval))
 			next_balance = sd->last_balance + interval;
-		if (pulled_task)
+		if (pulled_task) {
+			this_rq->idle_stamp = 0;
 			break;
+		}
 	}
 	if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
 		/*
@@ -4679,7 +4932,7 @@
 		cpumask_set_cpu(cpu, nohz.cpu_mask);
 
 		/* time for ilb owner also to sleep */
-		if (cpumask_weight(nohz.cpu_mask) == num_online_cpus()) {
+		if (cpumask_weight(nohz.cpu_mask) == num_active_cpus()) {
 			if (atomic_read(&nohz.load_balancer) == cpu)
 				atomic_set(&nohz.load_balancer, -1);
 			return 0;
@@ -4933,7 +5186,7 @@
 
 	if (task_current(rq, p)) {
 		update_rq_clock(rq);
-		ns = rq->clock - p->se.exec_start;
+		ns = rq->clock_task - p->se.exec_start;
 		if ((s64)ns < 0)
 			ns = 0;
 	}
@@ -5077,7 +5330,7 @@
 	tmp = cputime_to_cputime64(cputime);
 	if (hardirq_count() - hardirq_offset)
 		cpustat->irq = cputime64_add(cpustat->irq, tmp);
-	else if (softirq_count())
+	else if (in_serving_softirq())
 		cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
 	else
 		cpustat->system = cputime64_add(cpustat->system, tmp);
@@ -5171,45 +5424,90 @@
 {
 	return p->stime;
 }
+
+void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
+{
+	struct task_cputime cputime;
+
+	thread_group_cputime(p, &cputime);
+
+	*ut = cputime.utime;
+	*st = cputime.stime;
+}
 #else
+
+#ifndef nsecs_to_cputime
+# define nsecs_to_cputime(__nsecs) \
+	msecs_to_cputime(div_u64((__nsecs), NSEC_PER_MSEC))
+#endif
+
 cputime_t task_utime(struct task_struct *p)
 {
-	clock_t utime = cputime_to_clock_t(p->utime),
-		total = utime + cputime_to_clock_t(p->stime);
+	cputime_t utime = p->utime, total = utime + p->stime;
 	u64 temp;
 
 	/*
 	 * Use CFS's precise accounting:
 	 */
-	temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+	temp = (u64)nsecs_to_cputime(p->se.sum_exec_runtime);
 
 	if (total) {
 		temp *= utime;
 		do_div(temp, total);
 	}
-	utime = (clock_t)temp;
+	utime = (cputime_t)temp;
 
-	p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime));
+	p->prev_utime = max(p->prev_utime, utime);
 	return p->prev_utime;
 }
 
 cputime_t task_stime(struct task_struct *p)
 {
-	clock_t stime;
+	cputime_t stime;
 
 	/*
 	 * Use CFS's precise accounting. (we subtract utime from
 	 * the total, to make sure the total observed by userspace
 	 * grows monotonically - apps rely on that):
 	 */
-	stime = nsec_to_clock_t(p->se.sum_exec_runtime) -
-			cputime_to_clock_t(task_utime(p));
+	stime = nsecs_to_cputime(p->se.sum_exec_runtime) - task_utime(p);
 
 	if (stime >= 0)
-		p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime));
+		p->prev_stime = max(p->prev_stime, stime);
 
 	return p->prev_stime;
 }
+
+/*
+ * Must be called with siglock held.
+ */
+void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)
+{
+	struct signal_struct *sig = p->signal;
+	struct task_cputime cputime;
+	cputime_t rtime, utime, total;
+
+	thread_group_cputime(p, &cputime);
+
+	total = cputime_add(cputime.utime, cputime.stime);
+	rtime = nsecs_to_cputime(cputime.sum_exec_runtime);
+
+	if (total) {
+		u64 temp = rtime;
+
+		temp *= cputime.utime;
+		do_div(temp, total);
+		utime = (cputime_t)temp;
+	} else
+		utime = rtime;
+
+	sig->prev_utime = max(sig->prev_utime, utime);
+	sig->prev_stime = max(sig->prev_stime,
+			      cputime_sub(rtime, sig->prev_utime));
+
+	*ut = sig->prev_utime;
+	*st = sig->prev_stime;
+}
 #endif
 
 inline cputime_t task_gtime(struct task_struct *p)
@@ -5312,6 +5610,8 @@
 {
 	struct pt_regs *regs = get_irq_regs();
 
+	tracing_off();
+
 	printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
 		prev->comm, prev->pid, preempt_count());
 
@@ -5501,7 +5801,7 @@
 	 * the mutex owner just released it and exited.
 	 */
 	if (probe_kernel_address(&owner->cpu, cpu))
-		goto out;
+		return 0;
 #else
 	cpu = owner->cpu;
 #endif
@@ -5511,14 +5811,14 @@
 	 * the cpu field may no longer be valid.
 	 */
 	if (cpu >= nr_cpumask_bits)
-		goto out;
+		return 0;
 
 	/*
 	 * We need to validate that we can do a
 	 * get_cpu() and that we have the percpu area.
 	 */
 	if (!cpu_online(cpu))
-		goto out;
+		return 0;
 
 	rq = cpu_rq(cpu);
 
@@ -5537,7 +5837,7 @@
 
 		cpu_relax();
 	}
-out:
+
 	return 1;
 }
 #endif
@@ -5885,14 +6185,15 @@
  */
 bool try_wait_for_completion(struct completion *x)
 {
+	unsigned long flags;
 	int ret = 1;
 
-	spin_lock_irq(&x->wait.lock);
+	spin_lock_irqsave(&x->wait.lock, flags);
 	if (!x->done)
 		ret = 0;
 	else
 		x->done--;
-	spin_unlock_irq(&x->wait.lock);
+	spin_unlock_irqrestore(&x->wait.lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(try_wait_for_completion);
@@ -5907,12 +6208,13 @@
  */
 bool completion_done(struct completion *x)
 {
+	unsigned long flags;
 	int ret = 1;
 
-	spin_lock_irq(&x->wait.lock);
+	spin_lock_irqsave(&x->wait.lock, flags);
 	if (!x->done)
 		ret = 0;
-	spin_unlock_irq(&x->wait.lock);
+	spin_unlock_irqrestore(&x->wait.lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(completion_done);
@@ -5980,7 +6282,7 @@
 	unsigned long flags;
 	int oldprio, on_rq, running;
 	struct rq *rq;
-	const struct sched_class *prev_class = p->sched_class;
+	const struct sched_class *prev_class;
 
 	BUG_ON(prio < 0 || prio > MAX_PRIO);
 
@@ -5988,6 +6290,7 @@
 	update_rq_clock(rq);
 
 	oldprio = p->prio;
+	prev_class = p->sched_class;
 	on_rq = p->se.on_rq;
 	running = task_current(rq, p);
 	if (on_rq)
@@ -6005,7 +6308,7 @@
 	if (running)
 		p->sched_class->set_curr_task(rq);
 	if (on_rq) {
-		enqueue_task(rq, p, 0);
+		enqueue_task(rq, p, 0, oldprio < prio);
 
 		check_class_changed(rq, p, prev_class, oldprio, running);
 	}
@@ -6049,7 +6352,7 @@
 	delta = p->prio - old_prio;
 
 	if (on_rq) {
-		enqueue_task(rq, p, 0);
+		enqueue_task(rq, p, 0, false);
 		/*
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
@@ -6215,7 +6518,7 @@
 {
 	int retval, oldprio, oldpolicy = -1, on_rq, running;
 	unsigned long flags;
-	const struct sched_class *prev_class = p->sched_class;
+	const struct sched_class *prev_class;
 	struct rq *rq;
 	int reset_on_fork;
 
@@ -6329,6 +6632,7 @@
 	p->sched_reset_on_fork = reset_on_fork;
 
 	oldprio = p->prio;
+	prev_class = p->sched_class;
 	__setscheduler(rq, p, policy, param->sched_priority);
 
 	if (running)
@@ -6439,7 +6743,7 @@
 		return -EINVAL;
 
 	retval = -ESRCH;
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	p = find_process_by_pid(pid);
 	if (p) {
 		retval = security_task_getscheduler(p);
@@ -6447,7 +6751,7 @@
 			retval = p->policy
 				| (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0);
 	}
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -6465,7 +6769,7 @@
 	if (!param || pid < 0)
 		return -EINVAL;
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	p = find_process_by_pid(pid);
 	retval = -ESRCH;
 	if (!p)
@@ -6476,7 +6780,7 @@
 		goto out_unlock;
 
 	lp.sched_priority = p->rt_priority;
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	/*
 	 * This one might sleep, we cannot do it with a spinlock held ...
@@ -6486,7 +6790,7 @@
 	return retval;
 
 out_unlock:
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -6497,22 +6801,18 @@
 	int retval;
 
 	get_online_cpus();
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 
 	p = find_process_by_pid(pid);
 	if (!p) {
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 		put_online_cpus();
 		return -ESRCH;
 	}
 
-	/*
-	 * It is not safe to call set_cpus_allowed with the
-	 * tasklist_lock held. We will bump the task_struct's
-	 * usage count and then drop tasklist_lock.
-	 */
+	/* Prevent p going away */
 	get_task_struct(p);
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
 		retval = -ENOMEM;
@@ -6593,10 +6893,12 @@
 long sched_getaffinity(pid_t pid, struct cpumask *mask)
 {
 	struct task_struct *p;
+	unsigned long flags;
+	struct rq *rq;
 	int retval;
 
 	get_online_cpus();
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 
 	retval = -ESRCH;
 	p = find_process_by_pid(pid);
@@ -6607,10 +6909,12 @@
 	if (retval)
 		goto out_unlock;
 
+	rq = task_rq_lock(p, &flags);
 	cpumask_and(mask, &p->cpus_allowed, cpu_online_mask);
+	task_rq_unlock(rq, &flags);
 
 out_unlock:
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	put_online_cpus();
 
 	return retval;
@@ -6628,7 +6932,9 @@
 	int ret;
 	cpumask_var_t mask;
 
-	if (len < cpumask_size())
+	if ((len * BITS_PER_BYTE) < nr_cpu_ids)
+		return -EINVAL;
+	if (len & (sizeof(unsigned long)-1))
 		return -EINVAL;
 
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
@@ -6636,10 +6942,12 @@
 
 	ret = sched_getaffinity(pid, mask);
 	if (ret == 0) {
-		if (copy_to_user(user_mask_ptr, mask, cpumask_size()))
+		size_t retlen = min_t(size_t, len, cpumask_size());
+
+		if (copy_to_user(user_mask_ptr, mask, retlen))
 			ret = -EFAULT;
 		else
-			ret = cpumask_size();
+			ret = retlen;
 	}
 	free_cpumask_var(mask);
 
@@ -6845,6 +7153,8 @@
 {
 	struct task_struct *p;
 	unsigned int time_slice;
+	unsigned long flags;
+	struct rq *rq;
 	int retval;
 	struct timespec t;
 
@@ -6852,7 +7162,7 @@
 		return -EINVAL;
 
 	retval = -ESRCH;
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	p = find_process_by_pid(pid);
 	if (!p)
 		goto out_unlock;
@@ -6861,15 +7171,17 @@
 	if (retval)
 		goto out_unlock;
 
-	time_slice = p->sched_class->get_rr_interval(p);
+	rq = task_rq_lock(p, &flags);
+	time_slice = p->sched_class->get_rr_interval(rq, p);
+	task_rq_unlock(rq, &flags);
 
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	jiffies_to_timespec(time_slice, &t);
 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
 	return retval;
 
 out_unlock:
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	return retval;
 }
 
@@ -6960,11 +7272,23 @@
 	spin_lock_irqsave(&rq->lock, flags);
 
 	__sched_fork(idle);
+	idle->state = TASK_RUNNING;
 	idle->se.exec_start = sched_clock();
 
-	idle->prio = idle->normal_prio = MAX_PRIO;
 	cpumask_copy(&idle->cpus_allowed, cpumask_of(cpu));
+	/*
+	 * We're having a chicken and egg problem, even though we are
+	 * holding rq->lock, the cpu isn't yet set to this cpu so the
+	 * lockdep check in task_group() will fail.
+	 *
+	 * Similar case to sched_fork(). / Alternatively we could
+	 * use task_rq_lock() here and obtain the other rq->lock.
+	 *
+	 * Silence PROVE_RCU
+	 */
+	rcu_read_lock();
 	__set_task_cpu(idle, cpu);
+	rcu_read_unlock();
 
 	rq->curr = rq->idle = idle;
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -6982,7 +7306,7 @@
 	 * The idle tasks have their own, simple scheduling class:
 	 */
 	idle->sched_class = &idle_sched_class;
-	ftrace_graph_init_task(idle);
+	ftrace_graph_init_idle_task(idle, cpu);
 }
 
 /*
@@ -7003,22 +7327,23 @@
  *
  * This idea comes from the SD scheduler of Con Kolivas:
  */
-static inline void sched_init_granularity(void)
+static void update_sysctl(void)
 {
-	unsigned int factor = 1 + ilog2(num_online_cpus());
-	const unsigned long limit = 200000000;
+	unsigned int cpus = min(num_online_cpus(), 8U);
+	unsigned int factor = 1 + ilog2(cpus);
 
-	sysctl_sched_min_granularity *= factor;
-	if (sysctl_sched_min_granularity > limit)
-		sysctl_sched_min_granularity = limit;
-
-	sysctl_sched_latency *= factor;
-	if (sysctl_sched_latency > limit)
-		sysctl_sched_latency = limit;
-
-	sysctl_sched_wakeup_granularity *= factor;
+#define SET_SYSCTL(name) \
+	(sysctl_##name = (factor) * normalized_sysctl_##name)
+	SET_SYSCTL(sched_min_granularity);
+	SET_SYSCTL(sched_latency);
+	SET_SYSCTL(sched_wakeup_granularity);
+	SET_SYSCTL(sched_shares_ratelimit);
+#undef SET_SYSCTL
+}
 
-	sysctl_sched_shares_ratelimit *= factor;
+static inline void sched_init_granularity(void)
+{
+	update_sysctl();
 }
 
 #ifdef CONFIG_SMP
@@ -7054,8 +7379,20 @@
 	struct rq *rq;
 	int ret = 0;
 
+	/*
+	 * Serialize against TASK_WAKING so that ttwu() and wunt() can
+	 * drop the rq->lock and still rely on ->cpus_allowed.
+	 */
+again:
+	while (task_is_waking(p))
+		cpu_relax();
 	rq = task_rq_lock(p, &flags);
-	if (!cpumask_intersects(new_mask, cpu_online_mask)) {
+	if (task_is_waking(p)) {
+		task_rq_unlock(rq, &flags);
+		goto again;
+	}
+
+	if (!cpumask_intersects(new_mask, cpu_active_mask)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -7077,13 +7414,13 @@
 	if (cpumask_test_cpu(task_cpu(p), new_mask))
 		goto out;
 
-	if (migrate_task(p, cpumask_any_and(cpu_online_mask, new_mask), &req)) {
+	if (migrate_task(p, cpumask_any_and(cpu_active_mask, new_mask), &req)) {
 		/* Need help from migration thread: drop lock and wait. */
 		struct task_struct *mt = rq->migration_thread;
 
 		get_task_struct(mt);
 		task_rq_unlock(rq, &flags);
-		wake_up_process(rq->migration_thread);
+		wake_up_process(mt);
 		put_task_struct(mt);
 		wait_for_completion(&req.done);
 		tlb_migrate_finish(p->mm);
@@ -7110,7 +7447,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
-	int ret = 0, on_rq;
+	int ret = 0;
 
 	if (unlikely(!cpu_active(dest_cpu)))
 		return ret;
@@ -7126,12 +7463,13 @@
 	if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
 		goto fail;
 
-	on_rq = p->se.on_rq;
-	if (on_rq)
+	/*
+	 * If we're not on a rq, the next wake-up will ensure we're
+	 * placed properly.
+	 */
+	if (p->se.on_rq) {
 		deactivate_task(rq_src, p, 0);
-
-	set_task_cpu(p, dest_cpu);
-	if (on_rq) {
+		set_task_cpu(p, dest_cpu);
 		activate_task(rq_dest, p, 0);
 		check_preempt_curr(rq_dest, p, 0);
 	}
@@ -7210,57 +7548,29 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-
-static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu)
-{
-	int ret;
-
-	local_irq_disable();
-	ret = __migrate_task(p, src_cpu, dest_cpu);
-	local_irq_enable();
-	return ret;
-}
-
 /*
  * Figure out where task on dead CPU should go, use force if necessary.
  */
-static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
+void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
 {
-	int dest_cpu;
-	const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(dead_cpu));
-
-again:
-	/* Look for allowed, online CPU in same node. */
-	for_each_cpu_and(dest_cpu, nodemask, cpu_online_mask)
-		if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
-			goto move;
-
-	/* Any allowed, online CPU? */
-	dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_online_mask);
-	if (dest_cpu < nr_cpu_ids)
-		goto move;
-
-	/* No more Mr. Nice Guy. */
-	if (dest_cpu >= nr_cpu_ids) {
-		cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
-		dest_cpu = cpumask_any_and(cpu_online_mask, &p->cpus_allowed);
+	struct rq *rq = cpu_rq(dead_cpu);
+	int needs_cpu, uninitialized_var(dest_cpu);
+	unsigned long flags;
 
-		/*
-		 * Don't tell them about moving exiting tasks or
-		 * kernel threads (both mm NULL), since they never
-		 * leave kernel.
-		 */
-		if (p->mm && printk_ratelimit()) {
-			printk(KERN_INFO "process %d (%s) no "
-			       "longer affine to cpu%d\n",
-			       task_pid_nr(p), p->comm, dead_cpu);
-		}
-	}
+	local_irq_save(flags);
 
-move:
-	/* It can have affinity changed while we were choosing. */
-	if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu)))
-		goto again;
+	spin_lock(&rq->lock);
+	needs_cpu = (task_cpu(p) == dead_cpu) && (p->state != TASK_WAKING);
+	if (needs_cpu)
+		dest_cpu = select_fallback_rq(dead_cpu, p);
+	spin_unlock(&rq->lock);
+	/*
+	 * It can only fail if we race with set_cpus_allowed(),
+	 * in the racer should migrate the task anyway.
+	 */
+	if (needs_cpu)
+		__migrate_task(p, dead_cpu, dest_cpu);
+	local_irq_restore(flags);
 }
 
 /*
@@ -7272,7 +7582,7 @@
  */
 static void migrate_nr_uninterruptible(struct rq *rq_src)
 {
-	struct rq *rq_dest = cpu_rq(cpumask_any(cpu_online_mask));
+	struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -7526,7 +7836,7 @@
 static struct ctl_table_header *sd_sysctl_header;
 static void register_sched_domain_sysctl(void)
 {
-	int i, cpu_num = num_online_cpus();
+	int i, cpu_num = num_possible_cpus();
 	struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
 	char buf[32];
 
@@ -7536,7 +7846,7 @@
 	if (entry == NULL)
 		return;
 
-	for_each_online_cpu(i) {
+	for_each_possible_cpu(i) {
 		snprintf(buf, 32, "cpu%d", i);
 		entry->procname = kstrdup(buf, GFP_KERNEL);
 		entry->mode = 0555;
@@ -7608,10 +7918,9 @@
 	unsigned long flags;
 	struct rq *rq;
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 
 	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
 		p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
 		if (IS_ERR(p))
 			return NOTIFY_BAD;
@@ -7626,7 +7935,6 @@
 		break;
 
 	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
 		/* Strictly unnecessary, as first user will wake it. */
 		wake_up_process(cpu_rq(cpu)->migration_thread);
 
@@ -7643,7 +7951,6 @@
 
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
 		if (!cpu_rq(cpu)->migration_thread)
 			break;
 		/* Unbind it from offline cpu so it can run. Fall thru. */
@@ -7654,24 +7961,30 @@
 		cpu_rq(cpu)->migration_thread = NULL;
 		break;
 
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		cpuset_lock(); /* around calls to cpuset_cpus_allowed_lock() */
-		migrate_live_tasks(cpu);
+	case CPU_POST_DEAD:
+		/*
+		 * Bring the migration thread down in CPU_POST_DEAD event,
+		 * since the timers should have got migrated by now and thus
+		 * we should not see a deadlock between trying to kill the
+		 * migration thread and the sched_rt_period_timer.
+		 */
 		rq = cpu_rq(cpu);
 		kthread_stop(rq->migration_thread);
 		put_task_struct(rq->migration_thread);
 		rq->migration_thread = NULL;
+		break;
+
+	case CPU_DEAD:
+		migrate_live_tasks(cpu);
+		rq = cpu_rq(cpu);
 		/* Idle task back to normal (off runqueue, low prio) */
 		spin_lock_irq(&rq->lock);
 		update_rq_clock(rq);
 		deactivate_task(rq, rq->idle, 0);
-		rq->idle->static_prio = MAX_PRIO;
 		__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
 		rq->idle->sched_class = &idle_sched_class;
 		migrate_dead_tasks(cpu);
 		spin_unlock_irq(&rq->lock);
-		cpuset_unlock();
 		migrate_nr_uninterruptible(rq);
 		BUG_ON(rq->nr_running != 0);
 		calc_global_load_remove(rq);
@@ -7695,7 +8008,6 @@
 		break;
 
 	case CPU_DYING:
-	case CPU_DYING_FROZEN:
 		/* Update our root-domain */
 		rq = cpu_rq(cpu);
 		spin_lock_irqsave(&rq->lock, flags);
@@ -7905,6 +8217,8 @@
 
 static void free_rootdomain(struct root_domain *rd)
 {
+	synchronize_sched();
+
 	cpupri_cleanup(&rd->cpupri);
 
 	free_cpumask_var(rd->rto_mask);
@@ -8013,6 +8327,9 @@
 	struct rq *rq = cpu_rq(cpu);
 	struct sched_domain *tmp;
 
+	for (tmp = sd; tmp; tmp = tmp->parent)
+		tmp->span_weight = cpumask_weight(sched_domain_span(tmp));
+
 	/* Remove the sched domains which do not contribute to scheduling. */
 	for (tmp = sd; tmp; ) {
 		struct sched_domain *parent = tmp->parent;
@@ -8045,6 +8362,7 @@
 /* Setup the mask of cpus configured for isolated domains */
 static int __init isolated_cpu_setup(char *str)
 {
+	alloc_bootmem_cpumask_var(&cpu_isolated_map);
 	cpulist_parse(str, cpu_isolated_map);
 	return 1;
 }
@@ -8477,6 +8795,8 @@
 	if (cpu != group_first_cpu(sd->groups))
 		return;
 
+	sd->groups->group_weight = cpumask_weight(sched_group_cpus(sd->groups));
+
 	child = sd->child;
 
 	sd->groups->cpu_power = 0;
@@ -9022,7 +9342,7 @@
 	if (doms_new == NULL) {
 		ndoms_cur = 0;
 		doms_new = fallback_doms;
-		cpumask_andnot(&doms_new[0], cpu_online_mask, cpu_isolated_map);
+		cpumask_andnot(&doms_new[0], cpu_active_mask, cpu_isolated_map);
 		WARN_ON_ONCE(dattr_new);
 	}
 
@@ -9153,8 +9473,10 @@
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+	case CPU_DOWN_FAILED:
+	case CPU_DOWN_FAILED_FROZEN:
 		partition_sched_domains(1, NULL, NULL);
 		return NOTIFY_OK;
 
@@ -9201,7 +9523,7 @@
 #endif
 	get_online_cpus();
 	mutex_lock(&sched_domains_mutex);
-	arch_init_sched_domains(cpu_online_mask);
+	arch_init_sched_domains(cpu_active_mask);
 	cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map);
 	if (cpumask_empty(non_isolated_cpus))
 		cpumask_set_cpu(smp_processor_id(), non_isolated_cpus);
@@ -9358,9 +9680,6 @@
 #ifdef CONFIG_RT_GROUP_SCHED
 	alloc_size += 2 * nr_cpu_ids * sizeof(void **);
 #endif
-#ifdef CONFIG_USER_SCHED
-	alloc_size *= 2;
-#endif
 #ifdef CONFIG_CPUMASK_OFFSTACK
 	alloc_size += num_possible_cpus() * cpumask_size();
 #endif
@@ -9378,13 +9697,6 @@
 		init_task_group.cfs_rq = (struct cfs_rq **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
-#ifdef CONFIG_USER_SCHED
-		root_task_group.se = (struct sched_entity **)ptr;
-		ptr += nr_cpu_ids * sizeof(void **);
-
-		root_task_group.cfs_rq = (struct cfs_rq **)ptr;
-		ptr += nr_cpu_ids * sizeof(void **);
-#endif /* CONFIG_USER_SCHED */
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 #ifdef CONFIG_RT_GROUP_SCHED
 		init_task_group.rt_se = (struct sched_rt_entity **)ptr;
@@ -9393,13 +9705,6 @@
 		init_task_group.rt_rq = (struct rt_rq **)ptr;
 		ptr += nr_cpu_ids * sizeof(void **);
 
-#ifdef CONFIG_USER_SCHED
-		root_task_group.rt_se = (struct sched_rt_entity **)ptr;
-		ptr += nr_cpu_ids * sizeof(void **);
-
-		root_task_group.rt_rq = (struct rt_rq **)ptr;
-		ptr += nr_cpu_ids * sizeof(void **);
-#endif /* CONFIG_USER_SCHED */
 #endif /* CONFIG_RT_GROUP_SCHED */
 #ifdef CONFIG_CPUMASK_OFFSTACK
 		for_each_possible_cpu(i) {
@@ -9419,22 +9724,13 @@
 #ifdef CONFIG_RT_GROUP_SCHED
 	init_rt_bandwidth(&init_task_group.rt_bandwidth,
 			global_rt_period(), global_rt_runtime());
-#ifdef CONFIG_USER_SCHED
-	init_rt_bandwidth(&root_task_group.rt_bandwidth,
-			global_rt_period(), RUNTIME_INF);
-#endif /* CONFIG_USER_SCHED */
 #endif /* CONFIG_RT_GROUP_SCHED */
 
-#ifdef CONFIG_GROUP_SCHED
+#ifdef CONFIG_CGROUP_SCHED
 	list_add(&init_task_group.list, &task_groups);
 	INIT_LIST_HEAD(&init_task_group.children);
 
-#ifdef CONFIG_USER_SCHED
-	INIT_LIST_HEAD(&root_task_group.children);
-	init_task_group.parent = &root_task_group;
-	list_add(&init_task_group.siblings, &root_task_group.children);
-#endif /* CONFIG_USER_SCHED */
-#endif /* CONFIG_GROUP_SCHED */
+#endif /* CONFIG_CGROUP_SCHED */
 
 #if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
 	update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
@@ -9474,25 +9770,6 @@
 		 * directly in rq->cfs (i.e init_task_group->se[] = NULL).
 		 */
 		init_tg_cfs_entry(&init_task_group, &rq->cfs, NULL, i, 1, NULL);
-#elif defined CONFIG_USER_SCHED
-		root_task_group.shares = NICE_0_LOAD;
-		init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i, 0, NULL);
-		/*
-		 * In case of task-groups formed thr' the user id of tasks,
-		 * init_task_group represents tasks belonging to root user.
-		 * Hence it forms a sibling of all subsequent groups formed.
-		 * In this case, init_task_group gets only a fraction of overall
-		 * system cpu resource, based on the weight assigned to root
-		 * user's cpu share (INIT_TASK_GROUP_LOAD). This is accomplished
-		 * by letting tasks of init_task_group sit in a separate cfs_rq
-		 * (init_tg_cfs_rq) and having one entity represent this group of
-		 * tasks in rq->cfs (i.e init_task_group->se[] != NULL).
-		 */
-		init_tg_cfs_entry(&init_task_group,
-				&per_cpu(init_tg_cfs_rq, i),
-				&per_cpu(init_sched_entity, i), i, 1,
-				root_task_group.se[i]);
-
 #endif
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
@@ -9515,6 +9792,7 @@
 #ifdef CONFIG_SMP
 		rq->sd = NULL;
 		rq->rd = NULL;
+		rq->cpu_power = SCHED_LOAD_SCALE;
 		rq->post_schedule = 0;
 		rq->active_balance = 0;
 		rq->next_balance = jiffies;
@@ -9522,6 +9800,8 @@
 		rq->cpu = i;
 		rq->online = 0;
 		rq->migration_thread = NULL;
+		rq->idle_stamp = 0;
+		rq->avg_idle = 2*sysctl_sched_migration_cost;
 		INIT_LIST_HEAD(&rq->migration_queue);
 		rq_attach_root(rq, &def_root_domain);
 #endif
@@ -9571,7 +9851,9 @@
 	zalloc_cpumask_var(&nohz.cpu_mask, GFP_NOWAIT);
 	alloc_cpumask_var(&nohz.ilb_grp_nohz_mask, GFP_NOWAIT);
 #endif
-	zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
+	/* May be allocated at isolcpus cmdline parse time */
+	if (cpu_isolated_map == NULL)
+		zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT);
 #endif /* SMP */
 
 	perf_event_init();
@@ -9894,7 +10176,7 @@
 }
 #endif /* CONFIG_RT_GROUP_SCHED */
 
-#ifdef CONFIG_GROUP_SCHED
+#ifdef CONFIG_CGROUP_SCHED
 static void free_sched_group(struct task_group *tg)
 {
 	free_fair_sched_group(tg);
@@ -9989,21 +10271,21 @@
 	if (unlikely(running))
 		tsk->sched_class->put_prev_task(rq, tsk);
 
-	set_task_rq(tsk, task_cpu(tsk));
-
 #ifdef CONFIG_FAIR_GROUP_SCHED
-	if (tsk->sched_class->moved_group)
-		tsk->sched_class->moved_group(tsk);
+	if (tsk->sched_class->task_move_group)
+		tsk->sched_class->task_move_group(tsk, on_rq);
+	else
 #endif
+		set_task_rq(tsk, task_cpu(tsk));
 
 	if (unlikely(running))
 		tsk->sched_class->set_curr_task(rq);
 	if (on_rq)
-		enqueue_task(rq, tsk, 0);
+		enqueue_task(rq, tsk, 0, false);
 
 	task_rq_unlock(rq, &flags);
 }
-#endif /* CONFIG_GROUP_SCHED */
+#endif /* CONFIG_CGROUP_SCHED */
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void __set_se_shares(struct sched_entity *se, unsigned long shares)
@@ -10145,13 +10427,6 @@
 		runtime = d->rt_runtime;
 	}
 
-#ifdef CONFIG_USER_SCHED
-	if (tg == &root_task_group) {
-		period = global_rt_period();
-		runtime = global_rt_runtime();
-	}
-#endif
-
 	/*
 	 * Cannot have more runtime than the period.
 	 */
@@ -10771,12 +11046,30 @@
 }
 
 /*
+ * When CONFIG_VIRT_CPU_ACCOUNTING is enabled one jiffy can be very large
+ * in cputime_t units. As a result, cpuacct_update_stats calls
+ * percpu_counter_add with values large enough to always overflow the
+ * per cpu batch limit causing bad SMP scalability.
+ *
+ * To fix this we scale percpu_counter_batch by cputime_one_jiffy so we
+ * batch the same amount of time with CONFIG_VIRT_CPU_ACCOUNTING disabled
+ * and enabled. We cap it at INT_MAX which is the largest allowed batch value.
+ */
+#ifdef CONFIG_SMP
+#define CPUACCT_BATCH	\
+	min_t(long, percpu_counter_batch * cputime_one_jiffy, INT_MAX)
+#else
+#define CPUACCT_BATCH	0
+#endif
+
+/*
  * Charge the system/user time to the task's accounting group.
  */
 static void cpuacct_update_stats(struct task_struct *tsk,
 		enum cpuacct_stat_index idx, cputime_t val)
 {
 	struct cpuacct *ca;
+	int batch = CPUACCT_BATCH;
 
 	if (unlikely(!cpuacct_subsys.active))
 		return;
@@ -10785,7 +11078,7 @@
 	ca = task_ca(tsk);
 
 	do {
-		percpu_counter_add(&ca->cpustat[idx], val);
+		__percpu_counter_add(&ca->cpustat[idx], val, batch);
 		ca = ca->parent;
 	} while (ca);
 	rcu_read_unlock();
--- linux-ec2-2.6.32.orig/kernel/perf_event.c
+++ linux-ec2-2.6.32/kernel/perf_event.c
@@ -69,7 +69,8 @@
 	return sysctl_perf_event_paranoid > 1;
 }
 
-int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
+/* Minimum for 128 pages + 1 for the user control page */
+int sysctl_perf_event_mlock __read_mostly = 516; /* 'free' kb per user */
 
 /*
  * max perf event sample rate
@@ -1359,6 +1360,9 @@
 		if (event->state != PERF_EVENT_STATE_ACTIVE)
 			continue;
 
+		if (event->cpu != -1 && event->cpu != smp_processor_id())
+			continue;
+
 		hwc = &event->hw;
 
 		interrupts = hwc->interrupts;
@@ -1583,7 +1587,7 @@
 		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
 			return ERR_PTR(-EACCES);
 
-		if (cpu < 0 || cpu > num_possible_cpus())
+		if (cpu < 0 || cpu >= nr_cpumask_bits)
 			return ERR_PTR(-EINVAL);
 
 		/*
@@ -2174,6 +2178,7 @@
 	perf_mmap_free_page((unsigned long)data->user_page);
 	for (i = 0; i < data->nr_pages; i++)
 		perf_mmap_free_page((unsigned long)data->data_pages[i]);
+	kfree(data);
 }
 
 #else
@@ -2214,6 +2219,7 @@
 		perf_mmap_unmark_page(base + (i * PAGE_SIZE));
 
 	vfree(base);
+	kfree(data);
 }
 
 static void perf_mmap_data_free(struct perf_mmap_data *data)
@@ -2319,7 +2325,6 @@
 
 	data = container_of(rcu_head, struct perf_mmap_data, rcu_head);
 	perf_mmap_data_free(data);
-	kfree(data);
 }
 
 static void perf_mmap_data_release(struct perf_event *event)
@@ -3225,6 +3230,12 @@
 
 static int perf_event_task_match(struct perf_event *event)
 {
+	if (event->state != PERF_EVENT_STATE_ACTIVE)
+		return 0;
+
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		return 0;
+
 	if (event->attr.comm || event->attr.mmap || event->attr.task)
 		return 1;
 
@@ -3254,13 +3265,13 @@
 
 	cpuctx = &get_cpu_var(perf_cpu_context);
 	perf_event_task_ctx(&cpuctx->ctx, task_event);
-	put_cpu_var(perf_cpu_context);
 
 	rcu_read_lock();
 	if (!ctx)
 		ctx = rcu_dereference(task_event->task->perf_event_ctxp);
 	if (ctx)
 		perf_event_task_ctx(ctx, task_event);
+	put_cpu_var(perf_cpu_context);
 	rcu_read_unlock();
 }
 
@@ -3337,6 +3348,12 @@
 
 static int perf_event_comm_match(struct perf_event *event)
 {
+	if (event->state != PERF_EVENT_STATE_ACTIVE)
+		return 0;
+
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		return 0;
+
 	if (event->attr.comm)
 		return 1;
 
@@ -3377,7 +3394,6 @@
 
 	cpuctx = &get_cpu_var(perf_cpu_context);
 	perf_event_comm_ctx(&cpuctx->ctx, comm_event);
-	put_cpu_var(perf_cpu_context);
 
 	rcu_read_lock();
 	/*
@@ -3387,6 +3403,7 @@
 	ctx = rcu_dereference(current->perf_event_ctxp);
 	if (ctx)
 		perf_event_comm_ctx(ctx, comm_event);
+	put_cpu_var(perf_cpu_context);
 	rcu_read_unlock();
 }
 
@@ -3461,6 +3478,12 @@
 static int perf_event_mmap_match(struct perf_event *event,
 				   struct perf_mmap_event *mmap_event)
 {
+	if (event->state != PERF_EVENT_STATE_ACTIVE)
+		return 0;
+
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		return 0;
+
 	if (event->attr.mmap)
 		return 1;
 
@@ -3538,7 +3561,6 @@
 
 	cpuctx = &get_cpu_var(perf_cpu_context);
 	perf_event_mmap_ctx(&cpuctx->ctx, mmap_event);
-	put_cpu_var(perf_cpu_context);
 
 	rcu_read_lock();
 	/*
@@ -3548,6 +3570,7 @@
 	ctx = rcu_dereference(current->perf_event_ctxp);
 	if (ctx)
 		perf_event_mmap_ctx(ctx, mmap_event);
+	put_cpu_var(perf_cpu_context);
 	rcu_read_unlock();
 
 	kfree(buf);
@@ -3810,6 +3833,9 @@
 				enum perf_type_id type,
 				u32 event_id, struct pt_regs *regs)
 {
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		return 0;
+
 	if (!perf_swevent_is_counting(event))
 		return 0;
 
@@ -3949,6 +3975,7 @@
 	event->pmu->read(event);
 
 	data.addr = 0;
+	data.period = event->hw.last_period;
 	regs = get_irq_regs();
 	/*
 	 * In case we exclude kernel IPs or are somehow not in interrupt
@@ -4484,8 +4511,8 @@
 	struct perf_event_context *ctx;
 	struct file *event_file = NULL;
 	struct file *group_file = NULL;
+	int event_fd;
 	int fput_needed = 0;
-	int fput_needed2 = 0;
 	int err;
 
 	/* for future expandability... */
@@ -4506,12 +4533,18 @@
 			return -EINVAL;
 	}
 
+	event_fd = get_unused_fd_flags(O_RDWR);
+	if (event_fd < 0)
+		return event_fd;
+
 	/*
 	 * Get the target context (task or percpu):
 	 */
 	ctx = find_get_context(pid, cpu);
-	if (IS_ERR(ctx))
-		return PTR_ERR(ctx);
+	if (IS_ERR(ctx)) {
+		err = PTR_ERR(ctx);
+		goto err_fd;
+	}
 
 	/*
 	 * Look up the group leader (we will attach this event to it):
@@ -4551,13 +4584,11 @@
 	if (IS_ERR(event))
 		goto err_put_context;
 
-	err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0);
-	if (err < 0)
-		goto err_free_put_context;
-
-	event_file = fget_light(err, &fput_needed2);
-	if (!event_file)
+	event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, O_RDWR);
+	if (IS_ERR(event_file)) {
+		err = PTR_ERR(event_file);
 		goto err_free_put_context;
+	}
 
 	if (flags & PERF_FLAG_FD_OUTPUT) {
 		err = perf_event_set_output(event, group_fd);
@@ -4578,19 +4609,19 @@
 	list_add_tail(&event->owner_entry, &current->perf_event_list);
 	mutex_unlock(&current->perf_event_mutex);
 
-err_fput_free_put_context:
-	fput_light(event_file, fput_needed2);
+	fput_light(group_file, fput_needed);
+	fd_install(event_fd, event_file);
+	return event_fd;
 
+err_fput_free_put_context:
+	fput(event_file);
 err_free_put_context:
-	if (err < 0)
-		kfree(event);
-
+	free_event(event);
 err_put_context:
-	if (err < 0)
-		put_ctx(ctx);
-
 	fput_light(group_file, fput_needed);
-
+	put_ctx(ctx);
+err_fd:
+	put_unused_fd(event_fd);
 	return err;
 }
 
@@ -4955,12 +4986,22 @@
 	return ret;
 }
 
+static void __init perf_event_init_all_cpus(void)
+{
+	int cpu;
+	struct perf_cpu_context *cpuctx;
+
+	for_each_possible_cpu(cpu) {
+		cpuctx = &per_cpu(perf_cpu_context, cpu);
+		__perf_event_init_context(&cpuctx->ctx, NULL);
+	}
+}
+
 static void __cpuinit perf_event_init_cpu(int cpu)
 {
 	struct perf_cpu_context *cpuctx;
 
 	cpuctx = &per_cpu(perf_cpu_context, cpu);
-	__perf_event_init_context(&cpuctx->ctx, NULL);
 
 	spin_lock(&perf_resource_lock);
 	cpuctx->max_pertask = perf_max_events - perf_reserved_percpu;
@@ -5031,6 +5072,7 @@
 
 void __init perf_event_init(void)
 {
+	perf_event_init_all_cpus();
 	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE,
 			(void *)(long)smp_processor_id());
 	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
--- linux-ec2-2.6.32.orig/kernel/module.c
+++ linux-ec2-2.6.32/kernel/module.c
@@ -870,7 +870,6 @@
 	mutex_lock(&module_mutex);
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
-	ddebug_remove_module(mod->name);
 	free_module(mod);
 
  out:
@@ -1030,11 +1029,23 @@
 }
 
 #ifdef CONFIG_MODVERSIONS
+/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
+static unsigned long maybe_relocated(unsigned long crc,
+				     const struct module *crc_owner)
+{
+#ifdef ARCH_RELOCATES_KCRCTAB
+	if (crc_owner == NULL)
+		return crc - (unsigned long)reloc_start;
+#endif
+	return crc;
+}
+
 static int check_version(Elf_Shdr *sechdrs,
 			 unsigned int versindex,
 			 const char *symname,
 			 struct module *mod, 
-			 const unsigned long *crc)
+			 const unsigned long *crc,
+			 const struct module *crc_owner)
 {
 	unsigned int i, num_versions;
 	struct modversion_info *versions;
@@ -1055,10 +1066,10 @@
 		if (strcmp(versions[i].name, symname) != 0)
 			continue;
 
-		if (versions[i].crc == *crc)
+		if (versions[i].crc == maybe_relocated(*crc, crc_owner))
 			return 1;
 		DEBUGP("Found checksum %lX vs module %lX\n",
-		       *crc, versions[i].crc);
+		       maybe_relocated(*crc, crc_owner), versions[i].crc);
 		goto bad_version;
 	}
 
@@ -1081,7 +1092,8 @@
 	if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
 			 &crc, true, false))
 		BUG();
-	return check_version(sechdrs, versindex, "module_layout", mod, crc);
+	return check_version(sechdrs, versindex, "module_layout", mod, crc,
+			     NULL);
 }
 
 /* First part is kernel version, which we ignore if module has crcs. */
@@ -1099,7 +1111,8 @@
 				unsigned int versindex,
 				const char *symname,
 				struct module *mod, 
-				const unsigned long *crc)
+				const unsigned long *crc,
+				const struct module *crc_owner)
 {
 	return 1;
 }
@@ -1134,8 +1147,8 @@
 	/* use_module can fail due to OOM,
 	   or module initialization or unloading */
 	if (sym) {
-		if (!check_version(sechdrs, versindex, name, mod, crc) ||
-		    !use_module(mod, owner))
+		if (!check_version(sechdrs, versindex, name, mod, crc, owner)
+		    || !use_module(mod, owner))
 			sym = NULL;
 	}
 	return sym;
@@ -1146,6 +1159,12 @@
  * J. Corbet <corbet@lwn.net>
  */
 #if defined(CONFIG_KALLSYMS) && defined(CONFIG_SYSFS)
+
+static inline bool sect_empty(const Elf_Shdr *sect)
+{
+	return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
+}
+
 struct module_sect_attr
 {
 	struct module_attribute mattr;
@@ -1187,8 +1206,7 @@
 
 	/* Count loaded sections and allocate structures */
 	for (i = 0; i < nsect; i++)
-		if (sechdrs[i].sh_flags & SHF_ALLOC
-		    && sechdrs[i].sh_size)
+		if (!sect_empty(&sechdrs[i]))
 			nloaded++;
 	size[0] = ALIGN(sizeof(*sect_attrs)
 			+ nloaded * sizeof(sect_attrs->attrs[0]),
@@ -1206,9 +1224,7 @@
 	sattr = &sect_attrs->attrs[0];
 	gattr = &sect_attrs->grp.attrs[0];
 	for (i = 0; i < nsect; i++) {
-		if (! (sechdrs[i].sh_flags & SHF_ALLOC))
-			continue;
-		if (!sechdrs[i].sh_size)
+		if (sect_empty(&sechdrs[i]))
 			continue;
 		sattr->address = sechdrs[i].sh_addr;
 		sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,
@@ -1292,7 +1308,7 @@
 	/* Count notes sections and allocate structures.  */
 	notes = 0;
 	for (i = 0; i < nsect; i++)
-		if ((sechdrs[i].sh_flags & SHF_ALLOC) &&
+		if (!sect_empty(&sechdrs[i]) &&
 		    (sechdrs[i].sh_type == SHT_NOTE))
 			++notes;
 
@@ -1308,7 +1324,7 @@
 	notes_attrs->notes = notes;
 	nattr = &notes_attrs->attrs[0];
 	for (loaded = i = 0; i < nsect; ++i) {
-		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+		if (sect_empty(&sechdrs[i]))
 			continue;
 		if (sechdrs[i].sh_type == SHT_NOTE) {
 			nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
@@ -1516,6 +1532,9 @@
 	remove_sect_attrs(mod);
 	mod_kobject_remove(mod);
 
+	/* Remove dynamic debug info */
+	ddebug_remove_module(mod->name);
+
 	/* Arch-specific cleanup. */
 	module_arch_cleanup(mod);
 
--- linux-ec2-2.6.32.orig/kernel/user.c
+++ linux-ec2-2.6.32/kernel/user.c
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/user_namespace.h>
-#include "cred-internals.h"
 
 struct user_namespace init_user_ns = {
 	.kref = {
@@ -56,9 +55,6 @@
 	.sigpending	= ATOMIC_INIT(0),
 	.locked_shm     = 0,
 	.user_ns	= &init_user_ns,
-#ifdef CONFIG_USER_SCHED
-	.tg		= &init_task_group,
-#endif
 };
 
 /*
@@ -75,268 +71,6 @@
 	put_user_ns(up->user_ns);
 }
 
-#ifdef CONFIG_USER_SCHED
-
-static void sched_destroy_user(struct user_struct *up)
-{
-	sched_destroy_group(up->tg);
-}
-
-static int sched_create_user(struct user_struct *up)
-{
-	int rc = 0;
-
-	up->tg = sched_create_group(&root_task_group);
-	if (IS_ERR(up->tg))
-		rc = -ENOMEM;
-
-	set_tg_uid(up);
-
-	return rc;
-}
-
-#else	/* CONFIG_USER_SCHED */
-
-static void sched_destroy_user(struct user_struct *up) { }
-static int sched_create_user(struct user_struct *up) { return 0; }
-
-#endif	/* CONFIG_USER_SCHED */
-
-#if defined(CONFIG_USER_SCHED) && defined(CONFIG_SYSFS)
-
-static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
-{
-	struct user_struct *user;
-	struct hlist_node *h;
-
-	hlist_for_each_entry(user, h, hashent, uidhash_node) {
-		if (user->uid == uid) {
-			/* possibly resurrect an "almost deleted" object */
-			if (atomic_inc_return(&user->__count) == 1)
-				cancel_delayed_work(&user->work);
-			return user;
-		}
-	}
-
-	return NULL;
-}
-
-static struct kset *uids_kset; /* represents the /sys/kernel/uids/ directory */
-static DEFINE_MUTEX(uids_mutex);
-
-static inline void uids_mutex_lock(void)
-{
-	mutex_lock(&uids_mutex);
-}
-
-static inline void uids_mutex_unlock(void)
-{
-	mutex_unlock(&uids_mutex);
-}
-
-/* uid directory attributes */
-#ifdef CONFIG_FAIR_GROUP_SCHED
-static ssize_t cpu_shares_show(struct kobject *kobj,
-			       struct kobj_attribute *attr,
-			       char *buf)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-
-	return sprintf(buf, "%lu\n", sched_group_shares(up->tg));
-}
-
-static ssize_t cpu_shares_store(struct kobject *kobj,
-				struct kobj_attribute *attr,
-				const char *buf, size_t size)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-	unsigned long shares;
-	int rc;
-
-	sscanf(buf, "%lu", &shares);
-
-	rc = sched_group_set_shares(up->tg, shares);
-
-	return (rc ? rc : size);
-}
-
-static struct kobj_attribute cpu_share_attr =
-	__ATTR(cpu_share, 0644, cpu_shares_show, cpu_shares_store);
-#endif
-
-#ifdef CONFIG_RT_GROUP_SCHED
-static ssize_t cpu_rt_runtime_show(struct kobject *kobj,
-				   struct kobj_attribute *attr,
-				   char *buf)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-
-	return sprintf(buf, "%ld\n", sched_group_rt_runtime(up->tg));
-}
-
-static ssize_t cpu_rt_runtime_store(struct kobject *kobj,
-				    struct kobj_attribute *attr,
-				    const char *buf, size_t size)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-	unsigned long rt_runtime;
-	int rc;
-
-	sscanf(buf, "%ld", &rt_runtime);
-
-	rc = sched_group_set_rt_runtime(up->tg, rt_runtime);
-
-	return (rc ? rc : size);
-}
-
-static struct kobj_attribute cpu_rt_runtime_attr =
-	__ATTR(cpu_rt_runtime, 0644, cpu_rt_runtime_show, cpu_rt_runtime_store);
-
-static ssize_t cpu_rt_period_show(struct kobject *kobj,
-				   struct kobj_attribute *attr,
-				   char *buf)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-
-	return sprintf(buf, "%lu\n", sched_group_rt_period(up->tg));
-}
-
-static ssize_t cpu_rt_period_store(struct kobject *kobj,
-				    struct kobj_attribute *attr,
-				    const char *buf, size_t size)
-{
-	struct user_struct *up = container_of(kobj, struct user_struct, kobj);
-	unsigned long rt_period;
-	int rc;
-
-	sscanf(buf, "%lu", &rt_period);
-
-	rc = sched_group_set_rt_period(up->tg, rt_period);
-
-	return (rc ? rc : size);
-}
-
-static struct kobj_attribute cpu_rt_period_attr =
-	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
-#endif
-
-/* default attributes per uid directory */
-static struct attribute *uids_attributes[] = {
-#ifdef CONFIG_FAIR_GROUP_SCHED
-	&cpu_share_attr.attr,
-#endif
-#ifdef CONFIG_RT_GROUP_SCHED
-	&cpu_rt_runtime_attr.attr,
-	&cpu_rt_period_attr.attr,
-#endif
-	NULL
-};
-
-/* the lifetime of user_struct is not managed by the core (now) */
-static void uids_release(struct kobject *kobj)
-{
-	return;
-}
-
-static struct kobj_type uids_ktype = {
-	.sysfs_ops = &kobj_sysfs_ops,
-	.default_attrs = uids_attributes,
-	.release = uids_release,
-};
-
-/*
- * Create /sys/kernel/uids/<uid>/cpu_share file for this user
- * We do not create this file for users in a user namespace (until
- * sysfs tagging is implemented).
- *
- * See Documentation/scheduler/sched-design-CFS.txt for ramifications.
- */
-static int uids_user_create(struct user_struct *up)
-{
-	struct kobject *kobj = &up->kobj;
-	int error;
-
-	memset(kobj, 0, sizeof(struct kobject));
-	if (up->user_ns != &init_user_ns)
-		return 0;
-	kobj->kset = uids_kset;
-	error = kobject_init_and_add(kobj, &uids_ktype, NULL, "%d", up->uid);
-	if (error) {
-		kobject_put(kobj);
-		goto done;
-	}
-
-	kobject_uevent(kobj, KOBJ_ADD);
-done:
-	return error;
-}
-
-/* create these entries in sysfs:
- * 	"/sys/kernel/uids" directory
- * 	"/sys/kernel/uids/0" directory (for root user)
- * 	"/sys/kernel/uids/0/cpu_share" file (for root user)
- */
-int __init uids_sysfs_init(void)
-{
-	uids_kset = kset_create_and_add("uids", NULL, kernel_kobj);
-	if (!uids_kset)
-		return -ENOMEM;
-
-	return uids_user_create(&root_user);
-}
-
-/* delayed work function to remove sysfs directory for a user and free up
- * corresponding structures.
- */
-static void cleanup_user_struct(struct work_struct *w)
-{
-	struct user_struct *up = container_of(w, struct user_struct, work.work);
-	unsigned long flags;
-	int remove_user = 0;
-
-	/* Make uid_hash_remove() + sysfs_remove_file() + kobject_del()
-	 * atomic.
-	 */
-	uids_mutex_lock();
-
-	spin_lock_irqsave(&uidhash_lock, flags);
-	if (atomic_read(&up->__count) == 0) {
-		uid_hash_remove(up);
-		remove_user = 1;
-	}
-	spin_unlock_irqrestore(&uidhash_lock, flags);
-
-	if (!remove_user)
-		goto done;
-
-	if (up->user_ns == &init_user_ns) {
-		kobject_uevent(&up->kobj, KOBJ_REMOVE);
-		kobject_del(&up->kobj);
-		kobject_put(&up->kobj);
-	}
-
-	sched_destroy_user(up);
-	key_put(up->uid_keyring);
-	key_put(up->session_keyring);
-	kmem_cache_free(uid_cachep, up);
-
-done:
-	uids_mutex_unlock();
-}
-
-/* IRQs are disabled and uidhash_lock is held upon function entry.
- * IRQ state (as stored in flags) is restored and uidhash_lock released
- * upon function exit.
- */
-static void free_user(struct user_struct *up, unsigned long flags)
-{
-	INIT_DELAYED_WORK(&up->work, cleanup_user_struct);
-	schedule_delayed_work(&up->work, msecs_to_jiffies(1000));
-	spin_unlock_irqrestore(&uidhash_lock, flags);
-}
-
-#else	/* CONFIG_USER_SCHED && CONFIG_SYSFS */
-
 static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
 {
 	struct user_struct *user;
@@ -352,45 +86,20 @@
 	return NULL;
 }
 
-int uids_sysfs_init(void) { return 0; }
-static inline int uids_user_create(struct user_struct *up) { return 0; }
-static inline void uids_mutex_lock(void) { }
-static inline void uids_mutex_unlock(void) { }
-
 /* IRQs are disabled and uidhash_lock is held upon function entry.
  * IRQ state (as stored in flags) is restored and uidhash_lock released
  * upon function exit.
  */
 static void free_user(struct user_struct *up, unsigned long flags)
+	__releases(&uidhash_lock)
 {
 	uid_hash_remove(up);
 	spin_unlock_irqrestore(&uidhash_lock, flags);
-	sched_destroy_user(up);
 	key_put(up->uid_keyring);
 	key_put(up->session_keyring);
 	kmem_cache_free(uid_cachep, up);
 }
 
-#endif
-
-#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
-/*
- * We need to check if a setuid can take place. This function should be called
- * before successfully completing the setuid.
- */
-int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
-{
-
-	return sched_rt_can_attach(up->tg, tsk);
-
-}
-#else
-int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
-{
-	return 1;
-}
-#endif
-
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
@@ -428,11 +137,7 @@
 	struct hlist_head *hashent = uidhashentry(ns, uid);
 	struct user_struct *up, *new;
 
-	/* Make uid_hash_find() + uids_user_create() + uid_hash_insert()
-	 * atomic.
-	 */
-	uids_mutex_lock();
-
+	/* Make uid_hash_find() + uid_hash_insert() atomic. */
 	spin_lock_irq(&uidhash_lock);
 	up = uid_hash_find(uid, hashent);
 	spin_unlock_irq(&uidhash_lock);
@@ -445,14 +150,8 @@
 		new->uid = uid;
 		atomic_set(&new->__count, 1);
 
-		if (sched_create_user(new) < 0)
-			goto out_free_user;
-
 		new->user_ns = get_user_ns(ns);
 
-		if (uids_user_create(new))
-			goto out_destoy_sched;
-
 		/*
 		 * Before adding this, check whether we raced
 		 * on adding the same user already..
@@ -460,11 +159,6 @@
 		spin_lock_irq(&uidhash_lock);
 		up = uid_hash_find(uid, hashent);
 		if (up) {
-			/* This case is not possible when CONFIG_USER_SCHED
-			 * is defined, since we serialize alloc_uid() using
-			 * uids_mutex. Hence no need to call
-			 * sched_destroy_user() or remove_user_sysfs_dir().
-			 */
 			key_put(new->uid_keyring);
 			key_put(new->session_keyring);
 			kmem_cache_free(uid_cachep, new);
@@ -475,17 +169,9 @@
 		spin_unlock_irq(&uidhash_lock);
 	}
 
-	uids_mutex_unlock();
-
 	return up;
 
-out_destoy_sched:
-	sched_destroy_user(new);
-	put_user_ns(new->user_ns);
-out_free_user:
-	kmem_cache_free(uid_cachep, new);
 out_unlock:
-	uids_mutex_unlock();
 	return NULL;
 }
 
--- linux-ec2-2.6.32.orig/kernel/sysctl_check.c
+++ linux-ec2-2.6.32/kernel/sysctl_check.c
@@ -4,6 +4,7 @@
 #include <linux/sunrpc/debug.h>
 #include <linux/string.h>
 #include <net/ip_vs.h>
+#include <xen/sysctl.h>
 
 struct trans_ctl_table {
 	int			ctl_name;
@@ -220,6 +221,7 @@
 	{ NET_IPV4_CONF_PROMOTE_SECONDARIES,	"promote_secondaries" },
 	{ NET_IPV4_CONF_ARP_ACCEPT,		"arp_accept" },
 	{ NET_IPV4_CONF_ARP_NOTIFY,		"arp_notify" },
+	{ NET_IPV4_CONF_SRC_VMARK,		"src_valid_mark" },
 	{}
 };
 
@@ -893,6 +895,14 @@
 	{}
 };
 
+#ifdef CONFIG_XEN
+static const struct trans_ctl_table trans_xen_table[] = {
+	{ CTL_XEN_INDEPENDENT_WALLCLOCK,	"independent_wallclock" },
+	{ CTL_XEN_PERMITTED_CLOCK_JITTER,	"permitted_clock_jitter" },
+	{}
+};
+#endif
+
 static const struct trans_ctl_table trans_arlan_conf_table0[] = {
 	{ 1,	"spreadingCode" },
 	{ 2,	"channelNumber" },
@@ -1228,6 +1238,9 @@
 	{ CTL_BUS,	"bus",		trans_bus_table },
 	{ CTL_ABI,	"abi" },
 	/* CTL_CPU not used */
+#ifdef CONFIG_XEN
+	{ CTL_XEN,	"xen",		trans_xen_table },
+#endif
 	{ CTL_ARLAN,	"arlan",	trans_arlan_table },
 	{ CTL_S390DBF,	"s390dbf",	trans_s390dbf_table },
 	{ CTL_SUNRPC,	"sunrpc",	trans_sunrpc_table },
--- linux-ec2-2.6.32.orig/kernel/sched_fair.c
+++ linux-ec2-2.6.32/kernel/sched_fair.c
@@ -35,12 +35,14 @@
  *  run vmstat and monitor the context-switches (cs) field)
  */
 unsigned int sysctl_sched_latency = 5000000ULL;
+unsigned int normalized_sysctl_sched_latency = 5000000ULL;
 
 /*
  * Minimal preemption granularity for CPU-bound tasks:
  * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
  */
 unsigned int sysctl_sched_min_granularity = 1000000ULL;
+unsigned int normalized_sysctl_sched_min_granularity = 1000000ULL;
 
 /*
  * is kept at sysctl_sched_latency / sysctl_sched_min_granularity
@@ -70,6 +72,7 @@
  * have immediate wakeup/sleep latencies.
  */
 unsigned int sysctl_sched_wakeup_granularity = 1000000UL;
+unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL;
 
 const_debug unsigned int sysctl_sched_migration_cost = 500000UL;
 
@@ -485,6 +488,7 @@
 	curr->sum_exec_runtime += delta_exec;
 	schedstat_add(cfs_rq, exec_clock, delta_exec);
 	delta_exec_weighted = calc_delta_fair(delta_exec, curr);
+
 	curr->vruntime += delta_exec_weighted;
 	update_min_vruntime(cfs_rq);
 }
@@ -492,7 +496,7 @@
 static void update_curr(struct cfs_rq *cfs_rq)
 {
 	struct sched_entity *curr = cfs_rq->curr;
-	u64 now = rq_of(cfs_rq)->clock;
+	u64 now = rq_of(cfs_rq)->clock_task;
 	unsigned long delta_exec;
 
 	if (unlikely(!curr))
@@ -575,7 +579,7 @@
 	/*
 	 * We are starting a new run period:
 	 */
-	se->exec_start = rq_of(cfs_rq)->clock;
+	se->exec_start = rq_of(cfs_rq)->clock_task;
 }
 
 /**************************************************
@@ -740,16 +744,26 @@
 	se->vruntime = vruntime;
 }
 
+#define ENQUEUE_WAKEUP	1
+#define ENQUEUE_MIGRATE 2
+
 static void
-enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 {
 	/*
+	 * Update the normalized vruntime before updating min_vruntime
+	 * through callig update_curr().
+	 */
+	if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_MIGRATE))
+		se->vruntime += cfs_rq->min_vruntime;
+
+	/*
 	 * Update run-time statistics of the 'current'.
 	 */
 	update_curr(cfs_rq);
 	account_entity_enqueue(cfs_rq, se);
 
-	if (wakeup) {
+	if (flags & ENQUEUE_WAKEUP) {
 		place_entity(cfs_rq, se, 0);
 		enqueue_sleeper(cfs_rq, se);
 	}
@@ -803,6 +817,14 @@
 		__dequeue_entity(cfs_rq, se);
 	account_entity_dequeue(cfs_rq, se);
 	update_min_vruntime(cfs_rq);
+
+	/*
+	 * Normalize the entity after updating the min_vruntime because the
+	 * update can refer to the ->curr item and we need to reflect this
+	 * movement in our normalized position.
+	 */
+	if (!sleep)
+		se->vruntime -= cfs_rq->min_vruntime;
 }
 
 /*
@@ -1009,17 +1031,24 @@
  * increased. Here we update the fair scheduling stats and
  * then put the task into the rbtree:
  */
-static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
+static void
+enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, bool head)
 {
 	struct cfs_rq *cfs_rq;
 	struct sched_entity *se = &p->se;
+	int flags = 0;
+
+	if (wakeup)
+		flags |= ENQUEUE_WAKEUP;
+	if (p->state == TASK_WAKING)
+		flags |= ENQUEUE_MIGRATE;
 
 	for_each_sched_entity(se) {
 		if (se->on_rq)
 			break;
 		cfs_rq = cfs_rq_of(se);
-		enqueue_entity(cfs_rq, se, wakeup);
-		wakeup = 1;
+		enqueue_entity(cfs_rq, se, flags);
+		flags = ENQUEUE_WAKEUP;
 	}
 
 	hrtick_update(rq);
@@ -1095,6 +1124,14 @@
 
 #ifdef CONFIG_SMP
 
+static void task_waking_fair(struct rq *rq, struct task_struct *p)
+{
+	struct sched_entity *se = &p->se;
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+	se->vruntime -= cfs_rq->min_vruntime;
+}
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 /*
  * effective_load() calculates the load change as seen from the root_task_group
@@ -1185,7 +1222,6 @@
 	unsigned long this_load, load;
 	int idx, this_cpu, prev_cpu;
 	unsigned long tl_per_task;
-	unsigned int imbalance;
 	struct task_group *tg;
 	unsigned long weight;
 	int balanced;
@@ -1213,6 +1249,7 @@
 	 * effect of the currently running task from the load
 	 * of the current CPU:
 	 */
+	rcu_read_lock();
 	if (sync) {
 		tg = task_group(current);
 		weight = current->se.load.weight;
@@ -1224,8 +1261,6 @@
 	tg = task_group(p);
 	weight = p->se.load.weight;
 
-	imbalance = 100 + (sd->imbalance_pct - 100) / 2;
-
 	/*
 	 * In low-load situations, where prev_cpu is idle and this_cpu is idle
 	 * due to the sync cause above having dropped this_load to 0, we'll
@@ -1235,9 +1270,23 @@
 	 * Otherwise check if either cpus are near enough in load to allow this
 	 * task to be woken on this_cpu.
 	 */
-	balanced = !this_load ||
-		100*(this_load + effective_load(tg, this_cpu, weight, weight)) <=
-		imbalance*(load + effective_load(tg, prev_cpu, 0, weight));
+	if (this_load) {
+		unsigned long this_eff_load, prev_eff_load;
+
+		this_eff_load = 100;
+		this_eff_load *= power_of(prev_cpu);
+		this_eff_load *= this_load +
+			effective_load(tg, this_cpu, weight, weight);
+
+		prev_eff_load = 100 + (sd->imbalance_pct - 100) / 2;
+		prev_eff_load *= power_of(this_cpu);
+		prev_eff_load *= load + effective_load(tg, prev_cpu, 0, weight);
+
+		balanced = this_eff_load <= prev_eff_load;
+	} else
+		balanced = true;
+
+	rcu_read_unlock();
 
 	/*
 	 * If the currently running task will sleep within
@@ -1305,7 +1354,9 @@
 		}
 
 		/* Adjust by relative CPU power of the group */
-		avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
+		avg_load = (avg_load * SCHED_LOAD_SCALE);
+		if (group->cpu_power)
+			avg_load /= group->cpu_power;
 
 		if (local_group) {
 			this_load = avg_load;
@@ -1345,6 +1396,56 @@
 }
 
 /*
+ * Try and locate an idle CPU in the sched_domain.
+ */
+static int select_idle_sibling(struct task_struct *p, int target)
+{
+	int cpu = smp_processor_id();
+	int prev_cpu = task_cpu(p);
+	struct sched_domain *sd;
+	int i;
+
+	/*
+	 * If the task is going to be woken-up on this cpu and if it is
+	 * already idle, then it is the right target.
+	 */
+	if (target == cpu && idle_cpu(cpu))
+		return cpu;
+
+	/*
+	 * If the task is going to be woken-up on the cpu where it previously
+	 * ran and if it is currently idle, then it the right target.
+	 */
+	if (target == prev_cpu && idle_cpu(prev_cpu))
+		return prev_cpu;
+
+	/*
+	 * Otherwise, iterate the domains and find an elegible idle cpu.
+	 */
+	for_each_domain(target, sd) {
+		if (!(sd->flags & SD_SHARE_PKG_RESOURCES))
+			break;
+
+		for_each_cpu_and(i, sched_domain_span(sd), &p->cpus_allowed) {
+			if (idle_cpu(i)) {
+				target = i;
+				break;
+			}
+		}
+
+		/*
+		 * Lets stop looking for an idle sibling when we reached
+		 * the domain that spans the current cpu and prev_cpu.
+		 */
+		if (cpumask_test_cpu(cpu, sched_domain_span(sd)) &&
+		    cpumask_test_cpu(prev_cpu, sched_domain_span(sd)))
+			break;
+	}
+
+	return target;
+}
+
+/*
  * sched_balance_self: balance the current task (running on cpu) in domains
  * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
  * SD_BALANCE_EXEC.
@@ -1355,7 +1456,8 @@
  *
  * preempt must be disabled.
  */
-static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
+static int
+select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_flags)
 {
 	struct sched_domain *tmp, *affine_sd = NULL, *sd = NULL;
 	int cpu = smp_processor_id();
@@ -1372,8 +1474,10 @@
 		new_cpu = prev_cpu;
 	}
 
-	rcu_read_lock();
 	for_each_domain(cpu, tmp) {
+		if (!(tmp->flags & SD_LOAD_BALANCE))
+			continue;
+
 		/*
 		 * If power savings logic is enabled for a domain, see if we
 		 * are not overloaded, if so, don't balance wider.
@@ -1398,9 +1502,12 @@
 				want_sd = 0;
 		}
 
+		/*
+		 * If both cpu and prev_cpu are part of this domain,
+		 * cpu is a valid SD_WAKE_AFFINE target.
+		 */
 		if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
 		    cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
-
 			affine_sd = tmp;
 			want_affine = 0;
 		}
@@ -1415,23 +1522,28 @@
 			sd = tmp;
 	}
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
 	if (sched_feat(LB_SHARES_UPDATE)) {
 		/*
 		 * Pick the largest domain to update shares over
 		 */
 		tmp = sd;
-		if (affine_sd && (!tmp ||
-				  cpumask_weight(sched_domain_span(affine_sd)) >
-				  cpumask_weight(sched_domain_span(sd))))
+		if (affine_sd && (!tmp || affine_sd->span_weight > sd->span_weight))
 			tmp = affine_sd;
 
-		if (tmp)
+		if (tmp) {
+			spin_unlock(&rq->lock);
 			update_shares(tmp);
+			spin_lock(&rq->lock);
+		}
 	}
+#endif
 
-	if (affine_sd && wake_affine(affine_sd, p, sync)) {
-		new_cpu = cpu;
-		goto out;
+	if (affine_sd) {
+		if (cpu == prev_cpu || wake_affine(affine_sd, p, sync))
+			return select_idle_sibling(p, cpu);
+		else
+			return select_idle_sibling(p, prev_cpu);
 	}
 
 	while (sd) {
@@ -1462,10 +1574,10 @@
 
 		/* Now try balancing at a lower domain level of new_cpu */
 		cpu = new_cpu;
-		weight = cpumask_weight(sched_domain_span(sd));
+		weight = sd->span_weight;
 		sd = NULL;
 		for_each_domain(cpu, tmp) {
-			if (weight <= cpumask_weight(sched_domain_span(tmp)))
+			if (weight <= tmp->span_weight)
 				break;
 			if (tmp->flags & sd_flag)
 				sd = tmp;
@@ -1473,8 +1585,6 @@
 		/* while loop will break here if sd == NULL */
 	}
 
-out:
-	rcu_read_unlock();
 	return new_cpu;
 }
 #endif /* CONFIG_SMP */
@@ -1850,6 +1960,17 @@
 
 	return 0;
 }
+
+static void rq_online_fair(struct rq *rq)
+{
+	update_sysctl();
+}
+
+static void rq_offline_fair(struct rq *rq)
+{
+	update_sysctl();
+}
+
 #endif /* CONFIG_SMP */
 
 /*
@@ -1867,28 +1988,35 @@
 }
 
 /*
- * Share the fairness runtime between parent and child, thus the
- * total amount of pressure for CPU stays equal - new tasks
- * get a chance to run but frequent forkers are not allowed to
- * monopolize the CPU. Note: the parent runqueue is locked,
- * the child is not running yet.
+ * called on fork with the child task as argument from the parent's context
+ *  - child not yet on the tasklist
+ *  - preemption disabled
  */
-static void task_new_fair(struct rq *rq, struct task_struct *p)
+static void task_fork_fair(struct task_struct *p)
 {
-	struct cfs_rq *cfs_rq = task_cfs_rq(p);
+	struct cfs_rq *cfs_rq = task_cfs_rq(current);
 	struct sched_entity *se = &p->se, *curr = cfs_rq->curr;
 	int this_cpu = smp_processor_id();
+	struct rq *rq = this_rq();
+	unsigned long flags;
+
+	spin_lock_irqsave(&rq->lock, flags);
+
+	update_rq_clock(rq);
 
-	sched_info_queued(p);
+	if (unlikely(task_cpu(p) != this_cpu)) {
+		rcu_read_lock();
+		__set_task_cpu(p, this_cpu);
+		rcu_read_unlock();
+	}
 
 	update_curr(cfs_rq);
+
 	if (curr)
 		se->vruntime = curr->vruntime;
 	place_entity(cfs_rq, se, 1);
 
-	/* 'curr' will be NULL if the child belongs to a different group */
-	if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) &&
-			curr && entity_before(curr, se)) {
+	if (sysctl_sched_child_runs_first && curr && entity_before(curr, se)) {
 		/*
 		 * Upon rescheduling, sched_class::put_prev_task() will place
 		 * 'current' within the tree based on its new key value.
@@ -1897,7 +2025,9 @@
 		resched_task(rq->curr);
 	}
 
-	enqueue_task_fair(rq, p, 0);
+	se->vruntime -= cfs_rq->min_vruntime;
+
+	spin_unlock_irqrestore(&rq->lock, flags);
 }
 
 /*
@@ -1950,30 +2080,40 @@
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-static void moved_group_fair(struct task_struct *p)
+static void task_move_group_fair(struct task_struct *p, int on_rq)
 {
-	struct cfs_rq *cfs_rq = task_cfs_rq(p);
-
-	update_curr(cfs_rq);
-	place_entity(cfs_rq, &p->se, 1);
+	/*
+	 * If the task was not on the rq at the time of this cgroup movement
+	 * it must have been asleep, sleeping tasks keep their ->vruntime
+	 * absolute on their old rq until wakeup (needed for the fair sleeper
+	 * bonus in place_entity()).
+	 *
+	 * If it was on the rq, we've just 'preempted' it, which does convert
+	 * ->vruntime to a relative base.
+	 *
+	 * Make sure both cases convert their relative position when migrating
+	 * to another cgroup's rq. This does somewhat interfere with the
+	 * fair sleeper stuff for the first placement, but who cares.
+	 */
+	if (!on_rq)
+		p->se.vruntime -= cfs_rq_of(&p->se)->min_vruntime;
+	set_task_rq(p, task_cpu(p));
+	if (!on_rq)
+		p->se.vruntime += cfs_rq_of(&p->se)->min_vruntime;
 }
 #endif
 
-unsigned int get_rr_interval_fair(struct task_struct *task)
+unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task)
 {
 	struct sched_entity *se = &task->se;
-	unsigned long flags;
-	struct rq *rq;
 	unsigned int rr_interval = 0;
 
 	/*
 	 * Time slice is 0 for SCHED_OTHER tasks that are on an otherwise
 	 * idle runqueue:
 	 */
-	rq = task_rq_lock(task, &flags);
 	if (rq->cfs.load.weight)
 		rr_interval = NS_TO_JIFFIES(sched_slice(&rq->cfs, se));
-	task_rq_unlock(rq, &flags);
 
 	return rr_interval;
 }
@@ -1997,11 +2137,15 @@
 
 	.load_balance		= load_balance_fair,
 	.move_one_task		= move_one_task_fair,
+	.rq_online		= rq_online_fair,
+	.rq_offline		= rq_offline_fair,
+
+	.task_waking		= task_waking_fair,
 #endif
 
 	.set_curr_task          = set_curr_task_fair,
 	.task_tick		= task_tick_fair,
-	.task_new		= task_new_fair,
+	.task_fork		= task_fork_fair,
 
 	.prio_changed		= prio_changed_fair,
 	.switched_to		= switched_to_fair,
@@ -2009,7 +2153,7 @@
 	.get_rr_interval	= get_rr_interval_fair,
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-	.moved_group		= moved_group_fair,
+	.task_move_group	= task_move_group_fair,
 #endif
 };
 
--- linux-ec2-2.6.32.orig/kernel/cred.c
+++ linux-ec2-2.6.32/kernel/cred.c
@@ -16,7 +16,6 @@
 #include <linux/init_task.h>
 #include <linux/security.h>
 #include <linux/cn_proc.h>
-#include "cred-internals.h"
 
 #if 0
 #define kdebug(FMT, ...) \
@@ -209,6 +208,31 @@
 	}
 }
 
+/**
+ * get_task_cred - Get another task's objective credentials
+ * @task: The task to query
+ *
+ * Get the objective credentials of a task, pinning them so that they can't go
+ * away.  Accessing a task's credentials directly is not permitted.
+ *
+ * The caller must also make sure task doesn't get deleted, either by holding a
+ * ref on task or by holding tasklist_lock to prevent it from being unlinked.
+ */
+const struct cred *get_task_cred(struct task_struct *task)
+{
+	const struct cred *cred;
+
+	rcu_read_lock();
+
+	do {
+		cred = __task_cred((task));
+		BUG_ON(!cred);
+	} while (!atomic_inc_not_zero(&((struct cred *)cred)->usage));
+
+	rcu_read_unlock();
+	return cred;
+}
+
 /*
  * Allocate blank credentials, such that the credentials can be filled in at a
  * later date without risk of ENOMEM.
@@ -224,20 +248,20 @@
 #ifdef CONFIG_KEYS
 	new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
 	if (!new->tgcred) {
-		kfree(new);
+		kmem_cache_free(cred_jar, new);
 		return NULL;
 	}
 	atomic_set(&new->tgcred->usage, 1);
 #endif
 
 	atomic_set(&new->usage, 1);
+#ifdef CONFIG_DEBUG_CREDENTIALS
+	new->magic = CRED_MAGIC;
+#endif
 
 	if (security_cred_alloc_blank(new, GFP_KERNEL) < 0)
 		goto error;
 
-#ifdef CONFIG_DEBUG_CREDENTIALS
-	new->magic = CRED_MAGIC;
-#endif
 	return new;
 
 error:
@@ -553,8 +577,6 @@
 		atomic_dec(&old->user->processes);
 	alter_cred_subscribers(old, -2);
 
-	sched_switch_user(task);
-
 	/* send notifications */
 	if (new->uid   != old->uid  ||
 	    new->euid  != old->euid ||
@@ -696,6 +718,8 @@
 	validate_creds(old);
 
 	*new = *old;
+	atomic_set(&new->usage, 1);
+	set_cred_subscribers(new, 0);
 	get_uid(new->user);
 	get_group_info(new->group_info);
 
@@ -713,8 +737,6 @@
 	if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
 		goto error;
 
-	atomic_set(&new->usage, 1);
-	set_cred_subscribers(new, 0);
 	put_cred(old);
 	validate_creds(new);
 	return new;
@@ -786,10 +808,12 @@
 {
 	if (cred->magic != CRED_MAGIC)
 		return true;
-	if (atomic_read(&cred->usage) < atomic_read(&cred->subscribers))
-		return true;
 #ifdef CONFIG_SECURITY_SELINUX
-	if (selinux_is_enabled()) {
+	/*
+	 * cred->security == NULL if security_cred_alloc_blank() or
+	 * security_prepare_creds() returned an error.
+	 */
+	if (selinux_is_enabled() && cred->security) {
 		if ((unsigned long) cred->security < PAGE_SIZE)
 			return true;
 		if ((*(u32 *)cred->security & 0xffffff00) ==
--- linux-ec2-2.6.32.orig/kernel/kthread.c
+++ linux-ec2-2.6.32/kernel/kthread.c
@@ -196,7 +196,7 @@
 	set_task_comm(tsk, "kthreadd");
 	ignore_signals(tsk);
 	set_cpus_allowed_ptr(tsk, cpu_all_mask);
-	set_mems_allowed(node_possible_map);
+	set_mems_allowed(node_states[N_HIGH_MEMORY]);
 
 	current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
 
--- linux-ec2-2.6.32.orig/kernel/rcutree.h
+++ linux-ec2-2.6.32/kernel/rcutree.h
@@ -84,6 +84,9 @@
 	long	gpnum;		/* Current grace period for this node. */
 				/*  This will either be equal to or one */
 				/*  behind the root rcu_node's gpnum. */
+	long	completed;	/* Last grace period completed for this node. */
+				/*  This will either be equal to or one */
+				/*  behind the root rcu_node's gpnum. */
 	unsigned long qsmask;	/* CPUs or groups that need to switch in */
 				/*  order for current grace period to proceed.*/
 				/*  In leaf rcu_node, each bit corresponds to */
@@ -204,11 +207,12 @@
 #define RCU_GP_IDLE		0	/* No grace period in progress. */
 #define RCU_GP_INIT		1	/* Grace period being initialized. */
 #define RCU_SAVE_DYNTICK	2	/* Need to scan dyntick state. */
-#define RCU_FORCE_QS		3	/* Need to force quiescent state. */
+#define RCU_SAVE_COMPLETED	3	/* Need to save rsp->completed. */
+#define RCU_FORCE_QS		4	/* Need to force quiescent state. */
 #ifdef CONFIG_NO_HZ
 #define RCU_SIGNAL_INIT		RCU_SAVE_DYNTICK
 #else /* #ifdef CONFIG_NO_HZ */
-#define RCU_SIGNAL_INIT		RCU_FORCE_QS
+#define RCU_SIGNAL_INIT		RCU_SAVE_COMPLETED
 #endif /* #else #ifdef CONFIG_NO_HZ */
 
 #define RCU_JIFFIES_TILL_FORCE_QS	 3	/* for rsp->jiffies_force_qs */
@@ -274,9 +278,8 @@
 	unsigned long jiffies_stall;		/* Time at which to check */
 						/*  for CPU stalls. */
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-#ifdef CONFIG_NO_HZ
 	long dynticks_completed;		/* Value of completed @ snap. */
-#endif /* #ifdef CONFIG_NO_HZ */
+						/*  Protected by fqslock. */
 };
 
 #ifdef RCU_TREE_NONCORE
@@ -298,7 +301,7 @@
 #else /* #ifdef RCU_TREE_NONCORE */
 
 /* Forward declarations for rcutree_plugin.h */
-static inline void rcu_bootup_announce(void);
+static void rcu_bootup_announce(void);
 long rcu_batches_completed(void);
 static void rcu_preempt_note_context_switch(int cpu);
 static int rcu_preempted_readers(struct rcu_node *rnp);
--- linux-ec2-2.6.32.orig/kernel/power/process.c
+++ linux-ec2-2.6.32/kernel/power/process.c
@@ -139,7 +139,7 @@
 		if (nosig_only && should_send_signal(p))
 			continue;
 
-		if (cgroup_frozen(p))
+		if (cgroup_freezing_or_frozen(p))
 			continue;
 
 		thaw_process(p);
--- linux-ec2-2.6.32.orig/kernel/power/snapshot.c
+++ linux-ec2-2.6.32/kernel/power/snapshot.c
@@ -1181,7 +1181,7 @@
 
 	memory_bm_position_reset(&copy_bm);
 
-	while (to_free_normal > 0 && to_free_highmem > 0) {
+	while (to_free_normal > 0 || to_free_highmem > 0) {
 		unsigned long pfn = memory_bm_next_pfn(&copy_bm);
 		struct page *page = pfn_to_page(pfn);
 
@@ -1466,11 +1466,8 @@
 swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm,
 		unsigned int nr_pages, unsigned int nr_highmem)
 {
-	int error = 0;
-
 	if (nr_highmem > 0) {
-		error = get_highmem_buffer(PG_ANY);
-		if (error)
+		if (get_highmem_buffer(PG_ANY))
 			goto err_out;
 		if (nr_highmem > alloc_highmem) {
 			nr_highmem -= alloc_highmem;
@@ -1493,7 +1490,7 @@
 
  err_out:
 	swsusp_free();
-	return error;
+	return -ENOMEM;
 }
 
 asmlinkage int swsusp_save(void)
--- linux-ec2-2.6.32.orig/kernel/power/Kconfig
+++ linux-ec2-2.6.32/kernel/power/Kconfig
@@ -119,6 +119,21 @@
 config HIBERNATION_NVS
 	bool
 
+config PM_DISABLE_CONSOLE
+	bool "Disable Power Management messing with the active console"
+	depends on PM
+	default n
+	---help---
+	  By default, PM will take over the active console (generally, this means
+	  switching to the console when suspending from X). This can at times cause
+	  problems, especially if userspace suspend scripts try to do things with
+	  the console before or after suspending (e.g. calling vbestate).
+
+	  To work around this, enable this option so that PM will not handle the
+	  console.
+
+	  If unsure, say N.
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
--- linux-ec2-2.6.32.orig/kernel/power/console.c
+++ linux-ec2-2.6.32/kernel/power/console.c
@@ -17,20 +17,24 @@
 
 int pm_prepare_console(void)
 {
+#ifndef CONFIG_PM_DISABLE_CONSOLE
 	orig_fgconsole = vt_move_to_console(SUSPEND_CONSOLE, 1);
 	if (orig_fgconsole < 0)
 		return 1;
 
 	orig_kmsg = kmsg_redirect;
 	kmsg_redirect = SUSPEND_CONSOLE;
+#endif
 	return 0;
 }
 
 void pm_restore_console(void)
 {
+#ifndef CONFIG_PM_DISABLE_CONSOLE
 	if (orig_fgconsole >= 0) {
 		vt_move_to_console(orig_fgconsole, 0);
 		kmsg_redirect = orig_kmsg;
 	}
+#endif
 }
 #endif
--- linux-ec2-2.6.32.orig/kernel/power/user.c
+++ linux-ec2-2.6.32/kernel/power/user.c
@@ -137,7 +137,7 @@
 	free_all_swap_pages(data->swap);
 	if (data->frozen)
 		thaw_processes();
-	pm_notifier_call_chain(data->mode == O_WRONLY ?
+	pm_notifier_call_chain(data->mode == O_RDONLY ?
 			PM_POST_HIBERNATION : PM_POST_RESTORE);
 	atomic_inc(&snapshot_device_available);
 
--- linux-ec2-2.6.32.orig/kernel/time/timekeeping.c
+++ linux-ec2-2.6.32/kernel/time/timekeeping.c
@@ -168,8 +168,15 @@
 static struct timespec xtime_cache __attribute__ ((aligned (16)));
 void update_xtime_cache(u64 nsec)
 {
-	xtime_cache = xtime;
-	timespec_add_ns(&xtime_cache, nsec);
+	/*
+	 * Use temporary variable so get_seconds() cannot catch
+	 * an intermediate xtime_cache.tv_sec value.
+	 * The ACCESS_ONCE() keeps the compiler from optimizing
+	 * out the intermediate value.
+	 */
+	struct timespec ts = xtime;
+	timespec_add_ns(&ts, nsec);
+	ACCESS_ONCE(xtime_cache) = ts;
 }
 
 /* must hold xtime_lock */
@@ -177,7 +184,7 @@
 {
 	xtime.tv_sec += leapsecond;
 	wall_to_monotonic.tv_sec -= leapsecond;
-	update_vsyscall(&xtime, timekeeper.clock);
+	update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
 }
 
 #ifdef CONFIG_GENERIC_TIME
@@ -337,7 +344,7 @@
 	timekeeper.ntp_error = 0;
 	ntp_clear();
 
-	update_vsyscall(&xtime, timekeeper.clock);
+	update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
@@ -488,6 +495,17 @@
 }
 
 /**
+ * timekeeping_max_deferment - Returns max time the clocksource can be deferred
+ *
+ * Caller must observe xtime_lock via read_seqbegin/read_seqretry to
+ * ensure that the clocksource does not change!
+ */
+u64 timekeeping_max_deferment(void)
+{
+	return timekeeper.clock->max_idle_ns;
+}
+
+/**
  * read_persistent_clock -  Return time from the persistent clock.
  *
  * Weak dummy function for arches that do not yet support it.
@@ -811,7 +829,7 @@
 	update_xtime_cache(nsecs);
 
 	/* check to see if there is a new clocksource to use */
-	update_vsyscall(&xtime, timekeeper.clock);
+	update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
 }
 
 /**
@@ -834,6 +852,7 @@
 
 	set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec);
 }
+EXPORT_SYMBOL_GPL(getboottime);
 
 /**
  * monotonic_to_bootbased - Convert the monotonic time to boot based.
@@ -843,6 +862,7 @@
 {
 	*ts = timespec_add_safe(*ts, total_sleep_time);
 }
+EXPORT_SYMBOL_GPL(monotonic_to_bootbased);
 
 unsigned long get_seconds(void)
 {
--- linux-ec2-2.6.32.orig/kernel/time/tick-broadcast.c
+++ linux-ec2-2.6.32/kernel/time/tick-broadcast.c
@@ -523,10 +523,11 @@
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
+	int cpu = smp_processor_id();
+
 	/* Set it up only once ! */
 	if (bc->event_handler != tick_handle_oneshot_broadcast) {
 		int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
-		int cpu = smp_processor_id();
 
 		bc->event_handler = tick_handle_oneshot_broadcast;
 		clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
@@ -552,6 +553,15 @@
 			tick_broadcast_set_event(tick_next_period, 1);
 		} else
 			bc->next_event.tv64 = KTIME_MAX;
+	} else {
+		/*
+		 * The first cpu which switches to oneshot mode sets
+		 * the bit for all other cpus which are in the general
+		 * (periodic) broadcast mask. So the bit is set and
+		 * would prevent the first broadcast enter after this
+		 * to program the bc device.
+		 */
+		tick_broadcast_clear_oneshot(cpu);
 	}
 }
 
@@ -600,4 +610,14 @@
 	return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT;
 }
 
+/*
+ * Check whether the broadcast device supports oneshot.
+ */
+bool tick_broadcast_oneshot_available(void)
+{
+	struct clock_event_device *bc = tick_broadcast_device.evtdev;
+
+	return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false;
+}
+
 #endif
--- linux-ec2-2.6.32.orig/kernel/time/timer_list.c
+++ linux-ec2-2.6.32/kernel/time/timer_list.c
@@ -150,6 +150,9 @@
 	P_ns(expires_next);
 	P(hres_active);
 	P(nr_events);
+	P(nr_retries);
+	P(nr_hangs);
+	P_ns(max_hang_time);
 #endif
 #undef P
 #undef P_ns
@@ -252,7 +255,7 @@
 	u64 now = ktime_to_ns(ktime_get());
 	int cpu;
 
-	SEQ_printf(m, "Timer List Version: v0.4\n");
+	SEQ_printf(m, "Timer List Version: v0.5\n");
 	SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
 	SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
 
--- linux-ec2-2.6.32.orig/kernel/time/tick-common.c
+++ linux-ec2-2.6.32/kernel/time/tick-common.c
@@ -51,7 +51,11 @@
 {
 	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
 
-	return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT);
+	if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT))
+		return 0;
+	if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
+		return 1;
+	return tick_broadcast_oneshot_available();
 }
 
 /*
--- linux-ec2-2.6.32.orig/kernel/time/tick-internal.h
+++ linux-ec2-2.6.32/kernel/time/tick-internal.h
@@ -37,6 +37,7 @@
 extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 extern int tick_broadcast_oneshot_active(void);
 extern void tick_check_oneshot_broadcast(int cpu);
+bool tick_broadcast_oneshot_available(void);
 # else /* BROADCAST */
 static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
@@ -47,6 +48,7 @@
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
 static inline void tick_check_oneshot_broadcast(int cpu) { }
+static inline bool tick_broadcast_oneshot_available(void) { return true; }
 # endif /* !BROADCAST */
 
 #else /* !ONESHOT */
@@ -77,6 +79,7 @@
 	return 0;
 }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
+static inline bool tick_broadcast_oneshot_available(void) { return false; }
 #endif /* !TICK_ONESHOT */
 
 /*
--- linux-ec2-2.6.32.orig/kernel/time/clocksource.c
+++ linux-ec2-2.6.32/kernel/time/clocksource.c
@@ -413,6 +413,47 @@
 	clocksource_resume_watchdog();
 }
 
+/**
+ * clocksource_max_deferment - Returns max time the clocksource can be deferred
+ * @cs:         Pointer to clocksource
+ *
+ */
+static u64 clocksource_max_deferment(struct clocksource *cs)
+{
+	u64 max_nsecs, max_cycles;
+
+	/*
+	 * Calculate the maximum number of cycles that we can pass to the
+	 * cyc2ns function without overflowing a 64-bit signed result. The
+	 * maximum number of cycles is equal to ULLONG_MAX/cs->mult which
+	 * is equivalent to the below.
+	 * max_cycles < (2^63)/cs->mult
+	 * max_cycles < 2^(log2((2^63)/cs->mult))
+	 * max_cycles < 2^(log2(2^63) - log2(cs->mult))
+	 * max_cycles < 2^(63 - log2(cs->mult))
+	 * max_cycles < 1 << (63 - log2(cs->mult))
+	 * Please note that we add 1 to the result of the log2 to account for
+	 * any rounding errors, ensure the above inequality is satisfied and
+	 * no overflow will occur.
+	 */
+	max_cycles = 1ULL << (63 - (ilog2(cs->mult) + 1));
+
+	/*
+	 * The actual maximum number of cycles we can defer the clocksource is
+	 * determined by the minimum of max_cycles and cs->mask.
+	 */
+	max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
+	max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift);
+
+	/*
+	 * To ensure that the clocksource does not wrap whilst we are idle,
+	 * limit the time the clocksource can be deferred by 12.5%. Please
+	 * note a margin of 12.5% is used because this can be computed with
+	 * a shift, versus say 10% which would require division.
+	 */
+	return max_nsecs - (max_nsecs >> 5);
+}
+
 #ifdef CONFIG_GENERIC_TIME
 
 /**
@@ -474,6 +515,10 @@
  */
 static int __init clocksource_done_booting(void)
 {
+	mutex_lock(&clocksource_mutex);
+	curr_clocksource = clocksource_default_clock();
+	mutex_unlock(&clocksource_mutex);
+
 	finished_booting = 1;
 
 	/*
@@ -511,10 +556,13 @@
  */
 int clocksource_register(struct clocksource *cs)
 {
+	/* calculate max idle time permitted for this clocksource */
+	cs->max_idle_ns = clocksource_max_deferment(cs);
+
 	mutex_lock(&clocksource_mutex);
 	clocksource_enqueue(cs);
-	clocksource_select();
 	clocksource_enqueue_watchdog(cs);
+	clocksource_select();
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
--- linux-ec2-2.6.32.orig/kernel/time/tick-sched.c
+++ linux-ec2-2.6.32/kernel/time/tick-sched.c
@@ -134,18 +134,13 @@
  * value. We do this unconditionally on any cpu, as we don't know whether the
  * cpu, which has the update task assigned is in a long sleep.
  */
-static void tick_nohz_update_jiffies(void)
+static void tick_nohz_update_jiffies(ktime_t now)
 {
 	int cpu = smp_processor_id();
 	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
 	unsigned long flags;
-	ktime_t now;
-
-	if (!ts->tick_stopped)
-		return;
 
 	cpumask_clear_cpu(cpu, nohz_cpu_mask);
-	now = ktime_get();
 	ts->idle_waketime = now;
 
 	local_irq_save(flags);
@@ -155,20 +150,17 @@
 	touch_softlockup_watchdog();
 }
 
-static void tick_nohz_stop_idle(int cpu)
+static void tick_nohz_stop_idle(int cpu, ktime_t now)
 {
 	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+	ktime_t delta;
 
-	if (ts->idle_active) {
-		ktime_t now, delta;
-		now = ktime_get();
-		delta = ktime_sub(now, ts->idle_entrytime);
-		ts->idle_lastupdate = now;
-		ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
-		ts->idle_active = 0;
+	delta = ktime_sub(now, ts->idle_entrytime);
+	ts->idle_lastupdate = now;
+	ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
+	ts->idle_active = 0;
 
-		sched_clock_idle_wakeup_event(0);
-	}
+	sched_clock_idle_wakeup_event(0);
 }
 
 static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
@@ -216,6 +208,7 @@
 	struct tick_sched *ts;
 	ktime_t last_update, expires, now;
 	struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+	u64 time_delta;
 	int cpu;
 
 	local_irq_save(flags);
@@ -275,14 +268,28 @@
 		seq = read_seqbegin(&xtime_lock);
 		last_update = last_jiffies_update;
 		last_jiffies = jiffies;
-	} while (read_seqretry(&xtime_lock, seq));
 
-	/* Get the next timer wheel timer */
-	next_jiffies = get_next_timer_interrupt(last_jiffies);
-	delta_jiffies = next_jiffies - last_jiffies;
+		/*
+		 * On SMP we really should only care for the CPU which
+		 * has the do_timer duty assigned. All other CPUs can
+		 * sleep as long as they want.
+		 */
+		if (cpu == tick_do_timer_cpu ||
+		    tick_do_timer_cpu == TICK_DO_TIMER_NONE)
+			time_delta = timekeeping_max_deferment();
+		else
+			time_delta = KTIME_MAX;
+	} while (read_seqretry(&xtime_lock, seq));
 
-	if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
+	if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
+	    arch_needs_cpu(cpu)) {
+		next_jiffies = last_jiffies + 1;
 		delta_jiffies = 1;
+	} else {
+		/* Get the next timer wheel timer */
+		next_jiffies = get_next_timer_interrupt(last_jiffies);
+		delta_jiffies = next_jiffies - last_jiffies;
+	}
 	/*
 	 * Do not stop the tick, if we are only one off
 	 * or if the cpu is required for rcu
@@ -294,11 +301,26 @@
 	if ((long)delta_jiffies >= 1) {
 
 		/*
-		* calculate the expiry time for the next timer wheel
-		* timer
-		*/
-		expires = ktime_add_ns(last_update, tick_period.tv64 *
-				   delta_jiffies);
+		 * calculate the expiry time for the next timer wheel
+		 * timer. delta_jiffies >= NEXT_TIMER_MAX_DELTA signals
+		 * that there is no timer pending or at least extremely
+		 * far into the future (12 days for HZ=1000). In this
+		 * case we set the expiry to the end of time.
+		 */
+		if (likely(delta_jiffies < NEXT_TIMER_MAX_DELTA)) {
+			/*
+			 * Calculate the time delta for the next timer event.
+			 * If the time delta exceeds the maximum time delta
+			 * permitted by the current clocksource then adjust
+			 * the time delta accordingly to ensure the
+			 * clocksource does not wrap.
+			 */
+			time_delta = min_t(u64, time_delta,
+					   tick_period.tv64 * delta_jiffies);
+			expires = ktime_add_ns(last_update, time_delta);
+		} else {
+			expires.tv64 = KTIME_MAX;
+		}
 
 		/*
 		 * If this cpu is the one which updates jiffies, then
@@ -342,22 +364,19 @@
 
 		ts->idle_sleeps++;
 
+		/* Mark expires */
+		ts->idle_expires = expires;
+
 		/*
-		 * delta_jiffies >= NEXT_TIMER_MAX_DELTA signals that
-		 * there is no timer pending or at least extremly far
-		 * into the future (12 days for HZ=1000). In this case
-		 * we simply stop the tick timer:
+		 * If the expiration time == KTIME_MAX, then
+		 * in this case we simply stop the tick timer.
 		 */
-		if (unlikely(delta_jiffies >= NEXT_TIMER_MAX_DELTA)) {
-			ts->idle_expires.tv64 = KTIME_MAX;
+		 if (unlikely(expires.tv64 == KTIME_MAX)) {
 			if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
 				hrtimer_cancel(&ts->sched_timer);
 			goto out;
 		}
 
-		/* Mark expiries */
-		ts->idle_expires = expires;
-
 		if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
 			hrtimer_start(&ts->sched_timer, expires,
 				      HRTIMER_MODE_ABS_PINNED);
@@ -436,7 +455,11 @@
 	ktime_t now;
 
 	local_irq_disable();
-	tick_nohz_stop_idle(cpu);
+	if (ts->idle_active || (ts->inidle && ts->tick_stopped))
+		now = ktime_get();
+
+	if (ts->idle_active)
+		tick_nohz_stop_idle(cpu, now);
 
 	if (!ts->inidle || !ts->tick_stopped) {
 		ts->inidle = 0;
@@ -450,7 +473,6 @@
 
 	/* Update jiffies first */
 	select_nohz_load_balancer(0);
-	now = ktime_get();
 	tick_do_update_jiffies64(now);
 	cpumask_clear_cpu(cpu, nohz_cpu_mask);
 
@@ -584,22 +606,18 @@
  * timer and do not touch the other magic bits which need to be done
  * when idle is left.
  */
-static void tick_nohz_kick_tick(int cpu)
+static void tick_nohz_kick_tick(int cpu, ktime_t now)
 {
 #if 0
 	/* Switch back to 2.6.27 behaviour */
 
 	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-	ktime_t delta, now;
-
-	if (!ts->tick_stopped)
-		return;
+	ktime_t delta;
 
 	/*
 	 * Do not touch the tick device, when the next expiry is either
 	 * already reached or less/equal than the tick period.
 	 */
-	now = ktime_get();
 	delta =	ktime_sub(hrtimer_get_expires(&ts->sched_timer), now);
 	if (delta.tv64 <= tick_period.tv64)
 		return;
@@ -608,9 +626,26 @@
 #endif
 }
 
+static inline void tick_check_nohz(int cpu)
+{
+	struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
+	ktime_t now;
+
+	if (!ts->idle_active && !ts->tick_stopped)
+		return;
+	now = ktime_get();
+	if (ts->idle_active)
+		tick_nohz_stop_idle(cpu, now);
+	if (ts->tick_stopped) {
+		tick_nohz_update_jiffies(now);
+		tick_nohz_kick_tick(cpu, now);
+	}
+}
+
 #else
 
 static inline void tick_nohz_switch_to_nohz(void) { }
+static inline void tick_check_nohz(int cpu) { }
 
 #endif /* NO_HZ */
 
@@ -620,11 +655,7 @@
 void tick_check_idle(int cpu)
 {
 	tick_check_oneshot_broadcast(cpu);
-#ifdef CONFIG_NO_HZ
-	tick_nohz_stop_idle(cpu);
-	tick_nohz_update_jiffies();
-	tick_nohz_kick_tick(cpu);
-#endif
+	tick_check_nohz(cpu);
 }
 
 /*
--- linux-ec2-2.6.32.orig/kernel/time/clockevents.c
+++ linux-ec2-2.6.32/kernel/time/clockevents.c
@@ -20,6 +20,8 @@
 #include <linux/sysdev.h>
 #include <linux/tick.h>
 
+#include "tick-internal.h"
+
 /* The registered clock event devices */
 static LIST_HEAD(clockevent_devices);
 static LIST_HEAD(clockevents_released);
@@ -237,8 +239,9 @@
  */
 void clockevents_notify(unsigned long reason, void *arg)
 {
-	struct list_head *node, *tmp;
+	struct clock_event_device *dev, *tmp;
 	unsigned long flags;
+	int cpu;
 
 	spin_lock_irqsave(&clockevents_lock, flags);
 	clockevents_do_notify(reason, arg);
@@ -249,8 +252,20 @@
 		 * Unregister the clock event devices which were
 		 * released from the users in the notify chain.
 		 */
-		list_for_each_safe(node, tmp, &clockevents_released)
-			list_del(node);
+		list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
+			list_del(&dev->list);
+		/*
+		 * Now check whether the CPU has left unused per cpu devices
+		 */
+		cpu = *((int *)arg);
+		list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
+			if (cpumask_test_cpu(cpu, dev->cpumask) &&
+			    cpumask_weight(dev->cpumask) == 1 &&
+			    !tick_is_broadcast_device(dev)) {
+				BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
+				list_del(&dev->list);
+			}
+		}
 		break;
 	default:
 		break;
--- linux-ec2-2.6.32.orig/kernel/irq/manage.c
+++ linux-ec2-2.6.32/kernel/irq/manage.c
@@ -200,7 +200,7 @@
 void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
 {
 	if (suspend) {
-		if (!desc->action || (desc->action->flags & IRQF_TIMER))
+		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
 			return;
 		desc->status |= IRQ_SUSPENDED;
 	}
@@ -436,6 +436,9 @@
 		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
 		desc->status |= flags;
+
+		if (chip != desc->chip)
+			irq_chip_set_defaults(desc->chip);
 	}
 
 	return ret;
@@ -735,6 +738,16 @@
 		if (new->flags & IRQF_ONESHOT)
 			desc->status |= IRQ_ONESHOT;
 
+		/*
+		 * Force MSI interrupts to run with interrupts
+		 * disabled. The multi vector cards can cause stack
+		 * overflows due to nested interrupts when enough of
+		 * them are directed to a core and fire at the same
+		 * time.
+		 */
+		if (desc->msi_desc)
+			new->flags |= IRQF_DISABLED;
+
 		if (!(desc->status & IRQ_NOAUTOEN)) {
 			desc->depth = 0;
 			desc->status &= ~IRQ_DISABLED;
@@ -1066,7 +1079,7 @@
 	if (retval)
 		kfree(action);
 
-#ifdef CONFIG_DEBUG_SHIRQ
+#ifdef CONFIG_DEBUG_SHIRQ_FIXME
 	if (irqflags & IRQF_SHARED) {
 		/*
 		 * It's a shared IRQ -- the driver ought to be prepared for it
--- linux-ec2-2.6.32.orig/kernel/irq/chip.c
+++ linux-ec2-2.6.32/kernel/irq/chip.c
@@ -18,11 +18,7 @@
 
 #include "internals.h"
 
-/**
- *	dynamic_irq_init - initialize a dynamically allocated irq
- *	@irq:	irq number to initialize
- */
-void dynamic_irq_init(unsigned int irq)
+static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data)
 {
 	struct irq_desc *desc;
 	unsigned long flags;
@@ -41,7 +37,8 @@
 	desc->depth = 1;
 	desc->msi_desc = NULL;
 	desc->handler_data = NULL;
-	desc->chip_data = NULL;
+	if (!keep_chip_data)
+		desc->chip_data = NULL;
 	desc->action = NULL;
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
@@ -55,10 +52,26 @@
 }
 
 /**
- *	dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ *	dynamic_irq_init - initialize a dynamically allocated irq
  *	@irq:	irq number to initialize
  */
-void dynamic_irq_cleanup(unsigned int irq)
+void dynamic_irq_init(unsigned int irq)
+{
+	dynamic_irq_init_x(irq, false);
+}
+
+/**
+ *	dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ *
+ *	does not set irq_to_desc(irq)->chip_data to NULL
+ */
+void dynamic_irq_init_keep_chip_data(unsigned int irq)
+{
+	dynamic_irq_init_x(irq, true);
+}
+
+static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
@@ -77,7 +90,8 @@
 	}
 	desc->msi_desc = NULL;
 	desc->handler_data = NULL;
-	desc->chip_data = NULL;
+	if (!keep_chip_data)
+		desc->chip_data = NULL;
 	desc->handle_irq = handle_bad_irq;
 	desc->chip = &no_irq_chip;
 	desc->name = NULL;
@@ -85,6 +99,26 @@
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+/**
+ *	dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ */
+void dynamic_irq_cleanup(unsigned int irq)
+{
+	dynamic_irq_cleanup_x(irq, false);
+}
+
+/**
+ *	dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ *
+ *	does not set irq_to_desc(irq)->chip_data to NULL
+ */
+void dynamic_irq_cleanup_keep_chip_data(unsigned int irq)
+{
+	dynamic_irq_cleanup_x(irq, true);
+}
+
 
 /**
  *	set_irq_chip - set the irq chip for an irq
--- linux-ec2-2.6.32.orig/kernel/irq/spurious.c
+++ linux-ec2-2.6.32/kernel/irq/spurious.c
@@ -237,7 +237,7 @@
 		 */
 		if (time_after(jiffies, desc->last_unhandled + HZ/10))
 			desc->irqs_unhandled = 1;
-		else
+		else if (!irq_ignore_unhandled(irq))
 			desc->irqs_unhandled++;
 		desc->last_unhandled = jiffies;
 		if (unlikely(action_ret != IRQ_NONE))
--- linux-ec2-2.6.32.orig/kernel/gcov/fs.c
+++ linux-ec2-2.6.32/kernel/gcov/fs.c
@@ -33,10 +33,11 @@
  * @children: child nodes
  * @all: list head for list of all nodes
  * @parent: parent node
- * @info: associated profiling data structure if not a directory
- * @ghost: when an object file containing profiling data is unloaded we keep a
- *         copy of the profiling data here to allow collecting coverage data
- *         for cleanup code. Such a node is called a "ghost".
+ * @loaded_info: array of pointers to profiling data sets for loaded object
+ *   files.
+ * @num_loaded: number of profiling data sets for loaded object files.
+ * @unloaded_info: accumulated copy of profiling data sets for unloaded
+ *   object files. Used only when gcov_persist=1.
  * @dentry: main debugfs entry, either a directory or data file
  * @links: associated symbolic links
  * @name: data file basename
@@ -51,10 +52,11 @@
 	struct list_head children;
 	struct list_head all;
 	struct gcov_node *parent;
-	struct gcov_info *info;
-	struct gcov_info *ghost;
+	struct gcov_info **loaded_info;
+	struct gcov_info *unloaded_info;
 	struct dentry *dentry;
 	struct dentry **links;
+	int num_loaded;
 	char name[0];
 };
 
@@ -136,16 +138,37 @@
 };
 
 /*
- * Return the profiling data set for a given node. This can either be the
- * original profiling data structure or a duplicate (also called "ghost")
- * in case the associated object file has been unloaded.
+ * Return a profiling data set associated with the given node. This is
+ * either a data set for a loaded object file or a data set copy in case
+ * all associated object files have been unloaded.
  */
 static struct gcov_info *get_node_info(struct gcov_node *node)
 {
-	if (node->info)
-		return node->info;
+	if (node->num_loaded > 0)
+		return node->loaded_info[0];
 
-	return node->ghost;
+	return node->unloaded_info;
+}
+
+/*
+ * Return a newly allocated profiling data set which contains the sum of
+ * all profiling data associated with the given node.
+ */
+static struct gcov_info *get_accumulated_info(struct gcov_node *node)
+{
+	struct gcov_info *info;
+	int i = 0;
+
+	if (node->unloaded_info)
+		info = gcov_info_dup(node->unloaded_info);
+	else
+		info = gcov_info_dup(node->loaded_info[i++]);
+	if (!info)
+		return NULL;
+	for (; i < node->num_loaded; i++)
+		gcov_info_add(info, node->loaded_info[i]);
+
+	return info;
 }
 
 /*
@@ -163,9 +186,10 @@
 	mutex_lock(&node_lock);
 	/*
 	 * Read from a profiling data copy to minimize reference tracking
-	 * complexity and concurrent access.
+	 * complexity and concurrent access and to keep accumulating multiple
+	 * profiling data sets associated with one node simple.
 	 */
-	info = gcov_info_dup(get_node_info(node));
+	info = get_accumulated_info(node);
 	if (!info)
 		goto out_unlock;
 	iter = gcov_iter_new(info);
@@ -225,12 +249,25 @@
 	return NULL;
 }
 
+/*
+ * Reset all profiling data associated with the specified node.
+ */
+static void reset_node(struct gcov_node *node)
+{
+	int i;
+
+	if (node->unloaded_info)
+		gcov_info_reset(node->unloaded_info);
+	for (i = 0; i < node->num_loaded; i++)
+		gcov_info_reset(node->loaded_info[i]);
+}
+
 static void remove_node(struct gcov_node *node);
 
 /*
  * write() implementation for gcov data files. Reset profiling data for the
- * associated file. If the object file has been unloaded (i.e. this is
- * a "ghost" node), remove the debug fs node as well.
+ * corresponding file. If all associated object files have been unloaded,
+ * remove the debug fs node as well.
  */
 static ssize_t gcov_seq_write(struct file *file, const char __user *addr,
 			      size_t len, loff_t *pos)
@@ -245,10 +282,10 @@
 	node = get_node_by_name(info->filename);
 	if (node) {
 		/* Reset counts or remove node for unloaded modules. */
-		if (node->ghost)
+		if (node->num_loaded == 0)
 			remove_node(node);
 		else
-			gcov_info_reset(node->info);
+			reset_node(node);
 	}
 	/* Reset counts for open file. */
 	gcov_info_reset(info);
@@ -378,7 +415,10 @@
 	INIT_LIST_HEAD(&node->list);
 	INIT_LIST_HEAD(&node->children);
 	INIT_LIST_HEAD(&node->all);
-	node->info = info;
+	if (node->loaded_info) {
+		node->loaded_info[0] = info;
+		node->num_loaded = 1;
+	}
 	node->parent = parent;
 	if (name)
 		strcpy(node->name, name);
@@ -394,9 +434,13 @@
 	struct gcov_node *node;
 
 	node = kzalloc(sizeof(struct gcov_node) + strlen(name) + 1, GFP_KERNEL);
-	if (!node) {
-		pr_warning("out of memory\n");
-		return NULL;
+	if (!node)
+		goto err_nomem;
+	if (info) {
+		node->loaded_info = kcalloc(1, sizeof(struct gcov_info *),
+					   GFP_KERNEL);
+		if (!node->loaded_info)
+			goto err_nomem;
 	}
 	init_node(node, info, name, parent);
 	/* Differentiate between gcov data file nodes and directory nodes. */
@@ -416,6 +460,11 @@
 	list_add(&node->all, &all_head);
 
 	return node;
+
+err_nomem:
+	kfree(node);
+	pr_warning("out of memory\n");
+	return NULL;
 }
 
 /* Remove symbolic links associated with node. */
@@ -441,8 +490,9 @@
 	list_del(&node->all);
 	debugfs_remove(node->dentry);
 	remove_links(node);
-	if (node->ghost)
-		gcov_info_free(node->ghost);
+	kfree(node->loaded_info);
+	if (node->unloaded_info)
+		gcov_info_free(node->unloaded_info);
 	kfree(node);
 }
 
@@ -477,7 +527,7 @@
 
 /*
  * write() implementation for reset file. Reset all profiling data to zero
- * and remove ghost nodes.
+ * and remove nodes for which all associated object files are unloaded.
  */
 static ssize_t reset_write(struct file *file, const char __user *addr,
 			   size_t len, loff_t *pos)
@@ -487,8 +537,8 @@
 	mutex_lock(&node_lock);
 restart:
 	list_for_each_entry(node, &all_head, all) {
-		if (node->info)
-			gcov_info_reset(node->info);
+		if (node->num_loaded > 0)
+			reset_node(node);
 		else if (list_empty(&node->children)) {
 			remove_node(node);
 			/* Several nodes may have gone - restart loop. */
@@ -564,37 +614,115 @@
 }
 
 /*
- * The profiling data set associated with this node is being unloaded. Store a
- * copy of the profiling data and turn this node into a "ghost".
+ * Associate a profiling data set with an existing node. Needs to be called
+ * with node_lock held.
  */
-static int ghost_node(struct gcov_node *node)
+static void add_info(struct gcov_node *node, struct gcov_info *info)
 {
-	node->ghost = gcov_info_dup(node->info);
-	if (!node->ghost) {
-		pr_warning("could not save data for '%s' (out of memory)\n",
-			   node->info->filename);
-		return -ENOMEM;
+	struct gcov_info **loaded_info;
+	int num = node->num_loaded;
+
+	/*
+	 * Prepare new array. This is done first to simplify cleanup in
+	 * case the new data set is incompatible, the node only contains
+	 * unloaded data sets and there's not enough memory for the array.
+	 */
+	loaded_info = kcalloc(num + 1, sizeof(struct gcov_info *), GFP_KERNEL);
+	if (!loaded_info) {
+		pr_warning("could not add '%s' (out of memory)\n",
+			   info->filename);
+		return;
+	}
+	memcpy(loaded_info, node->loaded_info,
+	       num * sizeof(struct gcov_info *));
+	loaded_info[num] = info;
+	/* Check if the new data set is compatible. */
+	if (num == 0) {
+		/*
+		 * A module was unloaded, modified and reloaded. The new
+		 * data set replaces the copy of the last one.
+		 */
+		if (!gcov_info_is_compatible(node->unloaded_info, info)) {
+			pr_warning("discarding saved data for %s "
+				   "(incompatible version)\n", info->filename);
+			gcov_info_free(node->unloaded_info);
+			node->unloaded_info = NULL;
+		}
+	} else {
+		/*
+		 * Two different versions of the same object file are loaded.
+		 * The initial one takes precedence.
+		 */
+		if (!gcov_info_is_compatible(node->loaded_info[0], info)) {
+			pr_warning("could not add '%s' (incompatible "
+				   "version)\n", info->filename);
+			kfree(loaded_info);
+			return;
+		}
 	}
-	node->info = NULL;
+	/* Overwrite previous array. */
+	kfree(node->loaded_info);
+	node->loaded_info = loaded_info;
+	node->num_loaded = num + 1;
+}
 
-	return 0;
+/*
+ * Return the index of a profiling data set associated with a node.
+ */
+static int get_info_index(struct gcov_node *node, struct gcov_info *info)
+{
+	int i;
+
+	for (i = 0; i < node->num_loaded; i++) {
+		if (node->loaded_info[i] == info)
+			return i;
+	}
+	return -ENOENT;
 }
 
 /*
- * Profiling data for this node has been loaded again. Add profiling data
- * from previous instantiation and turn this node into a regular node.
+ * Save the data of a profiling data set which is being unloaded.
  */
-static void revive_node(struct gcov_node *node, struct gcov_info *info)
+static void save_info(struct gcov_node *node, struct gcov_info *info)
 {
-	if (gcov_info_is_compatible(node->ghost, info))
-		gcov_info_add(info, node->ghost);
+	if (node->unloaded_info)
+		gcov_info_add(node->unloaded_info, info);
 	else {
-		pr_warning("discarding saved data for '%s' (version changed)\n",
+		node->unloaded_info = gcov_info_dup(info);
+		if (!node->unloaded_info) {
+			pr_warning("could not save data for '%s' "
+				   "(out of memory)\n", info->filename);
+		}
+	}
+}
+
+/*
+ * Disassociate a profiling data set from a node. Needs to be called with
+ * node_lock held.
+ */
+static void remove_info(struct gcov_node *node, struct gcov_info *info)
+{
+	int i;
+
+	i = get_info_index(node, info);
+	if (i < 0) {
+		pr_warning("could not remove '%s' (not found)\n",
 			   info->filename);
+		return;
 	}
-	gcov_info_free(node->ghost);
-	node->ghost = NULL;
-	node->info = info;
+	if (gcov_persist)
+		save_info(node, info);
+	/* Shrink array. */
+	node->loaded_info[i] = node->loaded_info[node->num_loaded - 1];
+	node->num_loaded--;
+	if (node->num_loaded > 0)
+		return;
+	/* Last loaded data set was removed. */
+	kfree(node->loaded_info);
+	node->loaded_info = NULL;
+	node->num_loaded = 0;
+	if (!node->unloaded_info)
+		remove_node(node);
 }
 
 /*
@@ -609,30 +737,18 @@
 	node = get_node_by_name(info->filename);
 	switch (action) {
 	case GCOV_ADD:
-		/* Add new node or revive ghost. */
-		if (!node) {
+		if (node)
+			add_info(node, info);
+		else
 			add_node(info);
-			break;
-		}
-		if (gcov_persist)
-			revive_node(node, info);
-		else {
-			pr_warning("could not add '%s' (already exists)\n",
-				   info->filename);
-		}
 		break;
 	case GCOV_REMOVE:
-		/* Remove node or turn into ghost. */
-		if (!node) {
+		if (node)
+			remove_info(node, info);
+		else {
 			pr_warning("could not remove '%s' (not found)\n",
 				   info->filename);
-			break;
 		}
-		if (gcov_persist) {
-			if (!ghost_node(node))
-				break;
-		}
-		remove_node(node);
 		break;
 	}
 	mutex_unlock(&node_lock);
--- linux-ec2-2.6.32.orig/kernel/trace/trace.c
+++ linux-ec2-2.6.32/kernel/trace/trace.c
@@ -748,10 +748,10 @@
 	mutex_unlock(&trace_types_lock);
 }
 
-static void __tracing_reset(struct trace_array *tr, int cpu)
+static void __tracing_reset(struct ring_buffer *buffer, int cpu)
 {
 	ftrace_disable_cpu();
-	ring_buffer_reset_cpu(tr->buffer, cpu);
+	ring_buffer_reset_cpu(buffer, cpu);
 	ftrace_enable_cpu();
 }
 
@@ -763,7 +763,7 @@
 
 	/* Make sure all commits have finished */
 	synchronize_sched();
-	__tracing_reset(tr, cpu);
+	__tracing_reset(buffer, cpu);
 
 	ring_buffer_record_enable(buffer);
 }
@@ -781,7 +781,7 @@
 	tr->time_start = ftrace_now(tr->cpu);
 
 	for_each_online_cpu(cpu)
-		__tracing_reset(tr, cpu);
+		__tracing_reset(buffer, cpu);
 
 	ring_buffer_record_enable(buffer);
 }
@@ -858,6 +858,8 @@
 		goto out;
 	}
 
+	/* Prevent the buffers from switching */
+	__raw_spin_lock(&ftrace_max_lock);
 
 	buffer = global_trace.buffer;
 	if (buffer)
@@ -867,6 +869,8 @@
 	if (buffer)
 		ring_buffer_record_enable(buffer);
 
+	__raw_spin_unlock(&ftrace_max_lock);
+
 	ftrace_start();
  out:
 	spin_unlock_irqrestore(&tracing_start_lock, flags);
@@ -888,6 +892,9 @@
 	if (trace_stop_count++)
 		goto out;
 
+	/* Prevent the buffers from switching */
+	__raw_spin_lock(&ftrace_max_lock);
+
 	buffer = global_trace.buffer;
 	if (buffer)
 		ring_buffer_record_disable(buffer);
@@ -896,6 +903,8 @@
 	if (buffer)
 		ring_buffer_record_disable(buffer);
 
+	__raw_spin_unlock(&ftrace_max_lock);
+
  out:
 	spin_unlock_irqrestore(&tracing_start_lock, flags);
 }
@@ -1162,6 +1171,13 @@
 	if (!(trace_flags & TRACE_ITER_USERSTACKTRACE))
 		return;
 
+	/*
+	 * NMIs can not handle page faults, even with fix ups.
+	 * The save user stack can (and often does) fault.
+	 */
+	if (unlikely(in_nmi()))
+		return;
+
 	event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,
 					  sizeof(*entry), flags, pc);
 	if (!event)
@@ -2183,11 +2199,19 @@
 	return count;
 }
 
+static loff_t tracing_seek(struct file *file, loff_t offset, int origin)
+{
+	if (file->f_mode & FMODE_READ)
+		return seq_lseek(file, offset, origin);
+	else
+		return 0;
+}
+
 static const struct file_operations tracing_fops = {
 	.open		= tracing_open,
 	.read		= seq_read,
 	.write		= tracing_write_stub,
-	.llseek		= seq_lseek,
+	.llseek		= tracing_seek,
 	.release	= tracing_release,
 };
 
--- linux-ec2-2.6.32.orig/kernel/trace/ring_buffer.c
+++ linux-ec2-2.6.32/kernel/trace/ring_buffer.c
@@ -389,7 +389,7 @@
 #define BUF_MAX_DATA_SIZE (BUF_PAGE_SIZE - (sizeof(u32) * 2))
 
 /* Max number of timestamps that can fit on a page */
-#define RB_TIMESTAMPS_PER_PAGE	(BUF_PAGE_SIZE / RB_LEN_TIME_STAMP)
+#define RB_TIMESTAMPS_PER_PAGE	(BUF_PAGE_SIZE / RB_LEN_TIME_EXTEND)
 
 int ring_buffer_print_page_header(struct trace_seq *s)
 {
@@ -2237,12 +2237,12 @@
 	if (ring_buffer_flags != RB_BUFFERS_ON)
 		return NULL;
 
-	if (atomic_read(&buffer->record_disabled))
-		return NULL;
-
 	/* If we are tracing schedule, we don't want to recurse */
 	resched = ftrace_preempt_disable();
 
+	if (atomic_read(&buffer->record_disabled))
+		goto out_nocheck;
+
 	if (trace_recursive_lock())
 		goto out_nocheck;
 
@@ -2474,11 +2474,11 @@
 	if (ring_buffer_flags != RB_BUFFERS_ON)
 		return -EBUSY;
 
-	if (atomic_read(&buffer->record_disabled))
-		return -EBUSY;
-
 	resched = ftrace_preempt_disable();
 
+	if (atomic_read(&buffer->record_disabled))
+		goto out;
+
 	cpu = raw_smp_processor_id();
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
--- linux-ec2-2.6.32.orig/kernel/trace/ftrace.c
+++ linux-ec2-2.6.32/kernel/trace/ftrace.c
@@ -369,11 +369,18 @@
 {
 	struct ftrace_profile *rec = v;
 	char str[KSYM_SYMBOL_LEN];
+	int ret = 0;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	static DEFINE_MUTEX(mutex);
 	static struct trace_seq s;
 	unsigned long long avg;
 #endif
+	mutex_lock(&ftrace_profile_lock);
+
+	/* we raced with function_profile_reset() */
+	if (unlikely(rec->counter == 0)) {
+		ret = -EBUSY;
+		goto out;
+	}
 
 	kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
 	seq_printf(m, "  %-30.30s  %10lu", str, rec->counter);
@@ -383,17 +390,17 @@
 	avg = rec->time;
 	do_div(avg, rec->counter);
 
-	mutex_lock(&mutex);
 	trace_seq_init(&s);
 	trace_print_graph_duration(rec->time, &s);
 	trace_seq_puts(&s, "    ");
 	trace_print_graph_duration(avg, &s);
 	trace_print_seq(m, &s);
-	mutex_unlock(&mutex);
 #endif
 	seq_putc(m, '\n');
+out:
+	mutex_unlock(&ftrace_profile_lock);
 
-	return 0;
+	return ret;
 }
 
 static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
@@ -1473,6 +1480,8 @@
 		if (*pos > 0)
 			return t_hash_start(m, pos);
 		iter->flags |= FTRACE_ITER_PRINTALL;
+		/* reset in case of seek/pread */
+		iter->flags &= ~FTRACE_ITER_HASH;
 		return iter;
 	}
 
@@ -2393,7 +2402,7 @@
 	.open = ftrace_filter_open,
 	.read = seq_read,
 	.write = ftrace_filter_write,
-	.llseek = ftrace_regex_lseek,
+	.llseek = no_llseek,
 	.release = ftrace_filter_release,
 };
 
@@ -3163,7 +3172,7 @@
 	/* The cpu_boot init_task->ret_stack will never be freed */
 	for_each_online_cpu(cpu) {
 		if (!idle_task(cpu)->ret_stack)
-			ftrace_graph_init_task(idle_task(cpu));
+			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
 	}
 
 	do {
@@ -3253,11 +3262,55 @@
 	mutex_unlock(&ftrace_lock);
 }
 
+static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
+
+static void
+graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
+{
+	atomic_set(&t->tracing_graph_pause, 0);
+	atomic_set(&t->trace_overrun, 0);
+	t->ftrace_timestamp = 0;
+	/* make curr_ret_stack visable before we add the ret_stack */
+	smp_wmb();
+	t->ret_stack = ret_stack;
+}
+
+/*
+ * Allocate a return stack for the idle task. May be the first
+ * time through, or it may be done by CPU hotplug online.
+ */
+void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
+{
+	t->curr_ret_stack = -1;
+	/*
+	 * The idle task has no parent, it either has its own
+	 * stack or no stack at all.
+	 */
+	if (t->ret_stack)
+		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
+
+	if (ftrace_graph_active) {
+		struct ftrace_ret_stack *ret_stack;
+
+		ret_stack = per_cpu(idle_ret_stack, cpu);
+		if (!ret_stack) {
+			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
+					    * sizeof(struct ftrace_ret_stack),
+					    GFP_KERNEL);
+			if (!ret_stack)
+				return;
+			per_cpu(idle_ret_stack, cpu) = ret_stack;
+		}
+		graph_init_task(t, ret_stack);
+	}
+}
+
 /* Allocate a return stack for newly created task */
 void ftrace_graph_init_task(struct task_struct *t)
 {
 	/* Make sure we do not use the parent ret_stack */
 	t->ret_stack = NULL;
+	t->curr_ret_stack = -1;
 
 	if (ftrace_graph_active) {
 		struct ftrace_ret_stack *ret_stack;
@@ -3267,13 +3320,7 @@
 				GFP_KERNEL);
 		if (!ret_stack)
 			return;
-		t->curr_ret_stack = -1;
-		atomic_set(&t->tracing_graph_pause, 0);
-		atomic_set(&t->trace_overrun, 0);
-		t->ftrace_timestamp = 0;
-		/* make curr_ret_stack visable before we add the ret_stack */
-		smp_wmb();
-		t->ret_stack = ret_stack;
+		graph_init_task(t, ret_stack);
 	}
 }
 
--- linux-ec2-2.6.32.orig/kernel/trace/trace.h
+++ linux-ec2-2.6.32/kernel/trace/trace.h
@@ -746,7 +746,8 @@
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, id, tstruct, print)		\
-	extern struct ftrace_event_call event_##call;
+	extern struct ftrace_event_call					\
+	__attribute__((__aligned__(4))) event_##call;
 #undef FTRACE_ENTRY_DUP
 #define FTRACE_ENTRY_DUP(call, struct_name, id, tstruct, print)		\
 	FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
--- linux-ec2-2.6.32.orig/sound/mips/sgio2audio.c
+++ linux-ec2-2.6.32/sound/mips/sgio2audio.c
@@ -609,7 +609,7 @@
 	/* alloc virtual 'dma' area */
 	if (runtime->dma_area)
 		vfree(runtime->dma_area);
-	runtime->dma_area = vmalloc(size);
+	runtime->dma_area = vmalloc_user(size);
 	if (runtime->dma_area == NULL)
 		return -ENOMEM;
 	runtime->dma_bytes = size;
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8776.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8776.c
@@ -93,7 +93,6 @@
 
 static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
 SND_SOC_DAPM_INPUT("AUX"),
-SND_SOC_DAPM_INPUT("AUX"),
 
 SND_SOC_DAPM_INPUT("AIN1"),
 SND_SOC_DAPM_INPUT("AIN2"),
@@ -178,13 +177,6 @@
 	case SND_SOC_DAIFMT_LEFT_J:
 		iface |= 0x0001;
 		break;
-		/* FIXME: CHECK A/B */
-	case SND_SOC_DAIFMT_DSP_A:
-		iface |= 0x0003;
-		break;
-	case SND_SOC_DAIFMT_DSP_B:
-		iface |= 0x0007;
-		break;
 	default:
 		return -EINVAL;
 	}
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8400.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8400.c
@@ -106,21 +106,21 @@
 	wm8400_reset_codec_reg_cache(wm8400->wm8400);
 }
 
-static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0);
 
-static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
+static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0);
+static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
+static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
+static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
+static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);
 
-static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
+static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
+static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
 
 static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
         struct snd_ctl_elem_value *ucontrol)
@@ -439,7 +439,7 @@
 /* INMIX dB values */
 static const unsigned int in_mix_tlv[] = {
 	TLV_DB_RANGE_HEAD(1),
-	0,7, TLV_DB_LINEAR_ITEM(-1200, 600),
+	0,7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
 };
 
 /* Left In PGA Connections */
--- linux-ec2-2.6.32.orig/sound/soc/codecs/ak4104.c
+++ linux-ec2-2.6.32/sound/soc/codecs/ak4104.c
@@ -90,12 +90,10 @@
 	if (reg >= codec->reg_cache_size)
 		return -EINVAL;
 
-	reg &= AK4104_REG_MASK;
-	reg |= AK4104_WRITE;
-
 	/* only write to the hardware if value has changed */
 	if (cache[reg] != value) {
-		u8 tmp[2] = { reg, value };
+		u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
+
 		if (spi_write(spi, tmp, sizeof(tmp))) {
 			dev_err(&spi->dev, "SPI write failed\n");
 			return -EIO;
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8903.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8903.c
@@ -1506,7 +1506,7 @@
 	struct i2c_client *i2c = codec->control_data;
 	int i;
 	u16 *reg_cache = codec->reg_cache;
-	u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults),
+	u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
 				 GFP_KERNEL);
 
 	/* Bring the codec back up to standby first to minimise pop/clicks */
@@ -1518,6 +1518,7 @@
 		for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
 			if (tmp_cache[i] != reg_cache[i])
 				snd_soc_write(codec, i, tmp_cache[i]);
+		kfree(tmp_cache);
 	} else {
 		dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
 	}
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm9712.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm9712.c
@@ -464,7 +464,8 @@
 {
 	u16 *cache = codec->reg_cache;
 
-	soc_ac97_ops.write(codec->ac97, reg, val);
+	if (reg < 0x7c)
+		soc_ac97_ops.write(codec->ac97, reg, val);
 	reg = reg >> 1;
 	if (reg < (ARRAY_SIZE(wm9712_reg)))
 		cache[reg] = val;
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8990.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8990.c
@@ -110,21 +110,21 @@
 
 #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
 
-static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0);
 
-static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
+static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100);
+static const DECLARE_TLV_DB_SCALE(out_mix_tlv, 0, -2100, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
+static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
+static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
+static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);
 
-static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
+static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);
 
-static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
+static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);
 
 static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
@@ -450,7 +450,7 @@
 /* INMIX dB values */
 static const unsigned int in_mix_tlv[] = {
 	TLV_DB_RANGE_HEAD(1),
-	0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
+	0, 7, TLV_DB_SCALE_ITEM(-1200, 600, 0),
 };
 
 /* Left In PGA Connections */
@@ -1185,7 +1185,7 @@
 				     WM8990_VMIDTOG);
 
 			/* Delay to allow output caps to discharge */
-			msleep(msecs_to_jiffies(300));
+			msleep(300);
 
 			/* Disable VMIDTOG */
 			snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
@@ -1197,17 +1197,17 @@
 			/* Enable outputs */
 			snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
 
-			msleep(msecs_to_jiffies(50));
+			msleep(50);
 
 			/* Enable VMID at 2x50k */
 			snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
 
-			msleep(msecs_to_jiffies(100));
+			msleep(100);
 
 			/* Enable VREF */
 			snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
 
-			msleep(msecs_to_jiffies(600));
+			msleep(600);
 
 			/* Enable BUFIOEN */
 			snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
@@ -1252,7 +1252,7 @@
 		/* Disable VMID */
 		snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
 
-		msleep(msecs_to_jiffies(300));
+		msleep(300);
 
 		/* Enable all output discharge bits */
 		snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8510.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8510.c
@@ -425,23 +425,23 @@
 
 	/* filter coefficient */
 	switch (params_rate(params)) {
-	case SNDRV_PCM_RATE_8000:
+	case 8000:
 		adn |= 0x5 << 1;
 		break;
-	case SNDRV_PCM_RATE_11025:
+	case 11025:
 		adn |= 0x4 << 1;
 		break;
-	case SNDRV_PCM_RATE_16000:
+	case 16000:
 		adn |= 0x3 << 1;
 		break;
-	case SNDRV_PCM_RATE_22050:
+	case 22050:
 		adn |= 0x2 << 1;
 		break;
-	case SNDRV_PCM_RATE_32000:
+	case 32000:
 		adn |= 0x1 << 1;
 		break;
-	case SNDRV_PCM_RATE_44100:
-	case SNDRV_PCM_RATE_48000:
+	case 44100:
+	case 48000:
 		break;
 	}
 
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8350.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8350.c
@@ -423,8 +423,8 @@
 	SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr),
 };
 
-static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525);
-static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600);
+static DECLARE_TLV_DB_SCALE(pre_amp_tlv, -1200, 3525, 0);
+static DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 600, 0);
 static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1);
 static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1);
 static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1);
@@ -925,7 +925,7 @@
 		iface |= 0x3 << 8;
 		break;
 	case SND_SOC_DAIFMT_DSP_B:
-		iface |= 0x3 << 8;	/* lg not sure which mode */
+		iface |= 0x3 << 8 | WM8350_AIF_LRCLK_INV;
 		break;
 	default:
 		return -EINVAL;
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8974.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8974.c
@@ -47,7 +47,7 @@
 };
 
 #define WM8974_POWER1_BIASEN  0x08
-#define WM8974_POWER1_BUFIOEN 0x10
+#define WM8974_POWER1_BUFIOEN 0x04
 
 struct wm8974_priv {
 	struct snd_soc_codec codec;
@@ -480,23 +480,23 @@
 
 	/* filter coefficient */
 	switch (params_rate(params)) {
-	case SNDRV_PCM_RATE_8000:
+	case 8000:
 		adn |= 0x5 << 1;
 		break;
-	case SNDRV_PCM_RATE_11025:
+	case 11025:
 		adn |= 0x4 << 1;
 		break;
-	case SNDRV_PCM_RATE_16000:
+	case 16000:
 		adn |= 0x3 << 1;
 		break;
-	case SNDRV_PCM_RATE_22050:
+	case 22050:
 		adn |= 0x2 << 1;
 		break;
-	case SNDRV_PCM_RATE_32000:
+	case 32000:
 		adn |= 0x1 << 1;
 		break;
-	case SNDRV_PCM_RATE_44100:
-	case SNDRV_PCM_RATE_48000:
+	case 44100:
+	case 48000:
 		break;
 	}
 
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8580.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8580.c
@@ -268,9 +268,9 @@
 SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4,  4, 5, 1, 0),
 
 SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0),
-SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 0),
-SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 0),
-SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 0),
+SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
+SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
+SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),
 
 SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
 SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm_hubs.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm_hubs.c
@@ -593,12 +593,12 @@
 
 	{ "SPKL", "Input Switch", "MIXINL" },
 	{ "SPKL", "IN1LP Switch", "IN1LP" },
-	{ "SPKL", "Output Switch", "Left Output Mixer" },
+	{ "SPKL", "Output Switch", "Left Output PGA" },
 	{ "SPKL", NULL, "TOCLK" },
 
 	{ "SPKR", "Input Switch", "MIXINR" },
 	{ "SPKR", "IN1RP Switch", "IN1RP" },
-	{ "SPKR", "Output Switch", "Right Output Mixer" },
+	{ "SPKR", "Output Switch", "Right Output PGA" },
 	{ "SPKR", NULL, "TOCLK" },
 
 	{ "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
@@ -620,8 +620,8 @@
 	{ "SPKOUTRP", NULL, "SPKR Driver" },
 	{ "SPKOUTRN", NULL, "SPKR Driver" },
 
-	{ "Left Headphone Mux", "Mixer", "Left Output Mixer" },
-	{ "Right Headphone Mux", "Mixer", "Right Output Mixer" },
+	{ "Left Headphone Mux", "Mixer", "Left Output PGA" },
+	{ "Right Headphone Mux", "Mixer", "Right Output PGA" },
 
 	{ "Headphone PGA", NULL, "Left Headphone Mux" },
 	{ "Headphone PGA", NULL, "Right Headphone Mux" },
--- linux-ec2-2.6.32.orig/sound/soc/codecs/wm8940.c
+++ linux-ec2-2.6.32/sound/soc/codecs/wm8940.c
@@ -379,23 +379,23 @@
 		iface |= (1 << 9);
 
 	switch (params_rate(params)) {
-	case SNDRV_PCM_RATE_8000:
+	case 8000:
 		addcntrl |= (0x5 << 1);
 		break;
-	case SNDRV_PCM_RATE_11025:
+	case 11025:
 		addcntrl |= (0x4 << 1);
 		break;
-	case SNDRV_PCM_RATE_16000:
+	case 16000:
 		addcntrl |= (0x3 << 1);
 		break;
-	case SNDRV_PCM_RATE_22050:
+	case 22050:
 		addcntrl |= (0x2 << 1);
 		break;
-	case SNDRV_PCM_RATE_32000:
+	case 32000:
 		addcntrl |= (0x1 << 1);
 		break;
-	case SNDRV_PCM_RATE_44100:
-	case SNDRV_PCM_RATE_48000:
+	case 44100:
+	case 48000:
 		break;
 	}
 	ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl);
--- linux-ec2-2.6.32.orig/sound/soc/blackfin/bf5xx-ac97.c
+++ linux-ec2-2.6.32/sound/soc/blackfin/bf5xx-ac97.c
@@ -260,9 +260,9 @@
 	pr_debug("%s : sport %d\n", __func__, dai->id);
 	if (!dai->active)
 		return 0;
-	if (dai->capture.active)
+	if (dai->capture_active)
 		sport_rx_stop(sport);
-	if (dai->playback.active)
+	if (dai->playback_active)
 		sport_tx_stop(sport);
 	return 0;
 }
--- linux-ec2-2.6.32.orig/sound/pci/via82xx.c
+++ linux-ec2-2.6.32/sound/pci/via82xx.c
@@ -1791,6 +1791,12 @@
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
+		.subvendor = 0x110a,
+		.subdevice = 0x0079,
+		.name = "Fujitsu Siemens D1289",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.subvendor = 0x1019,
 		.subdevice = 0x0a81,
 		.name = "ECS K7VTA3",
--- linux-ec2-2.6.32.orig/sound/pci/maestro3.c
+++ linux-ec2-2.6.32/sound/pci/maestro3.c
@@ -849,6 +849,7 @@
 	struct snd_kcontrol *master_switch;
 	struct snd_kcontrol *master_volume;
 	struct tasklet_struct hwvol_tq;
+	unsigned int in_suspend;
 
 #ifdef CONFIG_PM
 	u16 *suspend_mem;
@@ -884,6 +885,7 @@
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
 static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c),
 	SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
 	SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
 	SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03),
@@ -1613,6 +1615,11 @@
 	outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
 	outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);
 
+	/* Ignore spurious HV interrupts during suspend / resume, this avoids
+	   mistaking them for a mute button press. */
+	if (chip->in_suspend)
+		return;
+
 	if (!chip->master_switch || !chip->master_volume)
 		return;
 
@@ -2424,6 +2431,7 @@
 	if (chip->suspend_mem == NULL)
 		return 0;
 
+	chip->in_suspend = 1;
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
@@ -2497,6 +2505,7 @@
 	snd_m3_hv_init(chip);
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	chip->in_suspend = 0;
 	return 0;
 }
 #endif /* CONFIG_PM */
--- linux-ec2-2.6.32.orig/sound/pci/ens1370.c
+++ linux-ec2-2.6.32/sound/pci/ens1370.c
@@ -229,6 +229,7 @@
 #define ES_REG_1371_CODEC 0x14	/* W/R: Codec Read/Write register address */
 #define   ES_1371_CODEC_RDY	   (1<<31)	/* codec ready */
 #define   ES_1371_CODEC_WIP	   (1<<30)	/* codec register access in progress */
+#define   EV_1938_CODEC_MAGIC	   (1<<26)
 #define   ES_1371_CODEC_PIRD	   (1<<23)	/* codec read/write select register */
 #define   ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0))
 #define   ES_1371_CODEC_READS(a)   ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD)
@@ -603,12 +604,18 @@
 
 #ifdef CHIP1371
 
+static inline bool is_ev1938(struct ensoniq *ensoniq)
+{
+	return ensoniq->pci->device == 0x8938;
+}
+
 static void snd_es1371_codec_write(struct snd_ac97 *ac97,
 				   unsigned short reg, unsigned short val)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x;
+	unsigned int t, x, flag;
 
+	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
 	mutex_lock(&ensoniq->src_mutex);
 	for (t = 0; t < POLL_COUNT; t++) {
 		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
@@ -630,7 +637,8 @@
 				    0x00010000)
 					break;
 			}
-			outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
+			outl(ES_1371_CODEC_WRITE(reg, val) | flag,
+			     ES_REG(ensoniq, 1371_CODEC));
 			/* restore SRC reg */
 			snd_es1371_wait_src_ready(ensoniq);
 			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
@@ -647,8 +655,9 @@
 					    unsigned short reg)
 {
 	struct ensoniq *ensoniq = ac97->private_data;
-	unsigned int t, x, fail = 0;
+	unsigned int t, x, flag, fail = 0;
 
+	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
       __again:
 	mutex_lock(&ensoniq->src_mutex);
 	for (t = 0; t < POLL_COUNT; t++) {
@@ -671,7 +680,8 @@
 				    0x00010000)
 					break;
 			}
-			outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
+			outl(ES_1371_CODEC_READS(reg) | flag,
+			     ES_REG(ensoniq, 1371_CODEC));
 			/* restore SRC reg */
 			snd_es1371_wait_src_ready(ensoniq);
 			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
@@ -683,6 +693,11 @@
 			/* now wait for the stinkin' data (RDY) */
 			for (t = 0; t < POLL_COUNT; t++) {
 				if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) {
+					if (is_ev1938(ensoniq)) {
+						for (t = 0; t < 100; t++)
+							inl(ES_REG(ensoniq, CONTROL));
+						x = inl(ES_REG(ensoniq, 1371_CODEC));
+					}
 					mutex_unlock(&ensoniq->src_mutex);
 					return ES_1371_CODEC_READ(x);
 				}
--- linux-ec2-2.6.32.orig/sound/pci/atiixp.c
+++ linux-ec2-2.6.32/sound/pci/atiixp.c
@@ -297,6 +297,7 @@
 MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
 
 static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
+	SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
 	SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
 	{ } /* terminator */
 };
--- linux-ec2-2.6.32.orig/sound/pci/intel8x0.c
+++ linux-ec2-2.6.32/sound/pci/intel8x0.c
@@ -1776,6 +1776,12 @@
         },
 	{
 		.subvendor = 0x1014,
+		.subdevice = 0x0534,
+		.name = "ThinkPad X31",
+		.type = AC97_TUNE_INV_EAPD
+	},
+	{
+		.subvendor = 0x1014,
 		.subdevice = 0x1f00,
 		.name = "MS-9128",
 		.type = AC97_TUNE_ALC_JACK
@@ -1860,6 +1866,12 @@
 	},
 	{
 		.subvendor = 0x1028,
+		.subdevice = 0x0182,
+		.name = "Dell Latitude D610",	/* STAC9750/51 */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.subvendor = 0x1028,
 		.subdevice = 0x0186,
 		.name = "Dell Latitude D810", /* cf. Malone #41015 */
 		.type = AC97_TUNE_HP_MUTE_LED
--- linux-ec2-2.6.32.orig/sound/pci/cmipci.c
+++ linux-ec2-2.6.32/sound/pci/cmipci.c
@@ -941,13 +941,21 @@
 						struct snd_pcm_substream *substream)
 {
 	size_t ptr;
-	unsigned int reg;
+	unsigned int reg, rem, tries;
+
 	if (!rec->running)
 		return 0;
 #if 1 // this seems better..
 	reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
-	ptr = rec->dma_size - (snd_cmipci_read_w(cm, reg) + 1);
-	ptr >>= rec->shift;
+	for (tries = 0; tries < 3; tries++) {
+		rem = snd_cmipci_read_w(cm, reg);
+		if (rem < rec->dma_size)
+			goto ok;
+	}
+	printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem);
+	return SNDRV_PCM_POS_XRUN;
+ok:
+	ptr = (rec->dma_size - (rem + 1)) >> rec->shift;
 #else
 	reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
 	ptr = snd_cmipci_read(cm, reg) - rec->offset;
--- linux-ec2-2.6.32.orig/sound/pci/ctxfi/ctvmem.h
+++ linux-ec2-2.6.32/sound/pci/ctxfi/ctvmem.h
@@ -22,6 +22,8 @@
 
 #include <linux/mutex.h>
 #include <linux/list.h>
+#include <linux/pci.h>
+#include <sound/memalloc.h>
 
 /* The chip can handle the page table of 4k pages
  * (emu20k1 can handle even 8k pages, but we don't use it right now)
@@ -41,7 +43,7 @@
 
 /* Virtual memory management object for card device */
 struct ct_vm {
-	void *ptp[CT_PTP_NUM];		/* Device page table pages */
+	struct snd_dma_buffer ptp[CT_PTP_NUM];	/* Device page table pages */
 	unsigned int size;		/* Available addr space in bytes */
 	struct list_head unused;	/* List of unused blocks */
 	struct list_head used;		/* List of used blocks */
@@ -52,10 +54,10 @@
 				   int size);
 	/* Unmap device logical addr area. */
 	void (*unmap)(struct ct_vm *, struct ct_vm_block *block);
-	void *(*get_ptp_virt)(struct ct_vm *vm, int index);
+	dma_addr_t (*get_ptp_phys)(struct ct_vm *vm, int index);
 };
 
-int ct_vm_create(struct ct_vm **rvm);
+int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci);
 void ct_vm_destroy(struct ct_vm *vm);
 
 #endif /* CTVMEM_H */
--- linux-ec2-2.6.32.orig/sound/pci/ctxfi/ctatc.c
+++ linux-ec2-2.6.32/sound/pci/ctxfi/ctatc.c
@@ -166,18 +166,7 @@
 
 static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index)
 {
-	struct ct_vm *vm;
-	void *kvirt_addr;
-	unsigned long phys_addr;
-
-	vm = atc->vm;
-	kvirt_addr = vm->get_ptp_virt(vm, index);
-	if (kvirt_addr == NULL)
-		phys_addr = (~0UL);
-	else
-		phys_addr = virt_to_phys(kvirt_addr);
-
-	return phys_addr;
+	return atc->vm->get_ptp_phys(atc->vm, index);
 }
 
 static unsigned int convert_format(snd_pcm_format_t snd_format)
@@ -879,7 +868,7 @@
 	mutex_lock(&atc->atc_mutex);
 	dao->ops->get_spos(dao, &status);
 	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
-		status &= ((~IEC958_AES3_CON_FS) << 24);
+		status &= ~(IEC958_AES3_CON_FS << 24);
 		status |= (iec958_con_fs << 24);
 		dao->ops->set_spos(dao, status);
 		dao->ops->commit_write(dao);
@@ -1669,7 +1658,7 @@
 	}
 
 	/* Set up device virtual memory management object */
-	err = ct_vm_create(&atc->vm);
+	err = ct_vm_create(&atc->vm, pci);
 	if (err < 0)
 		goto error1;
 
--- linux-ec2-2.6.32.orig/sound/pci/ctxfi/ctdaio.c
+++ linux-ec2-2.6.32/sound/pci/ctxfi/ctdaio.c
@@ -176,6 +176,7 @@
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_left_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscl.ops->master(&daio->rscl);
@@ -204,6 +205,7 @@
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_right_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscr.ops->master(&daio->rscr);
--- linux-ec2-2.6.32.orig/sound/pci/ctxfi/ctmixer.c
+++ linux-ec2-2.6.32/sound/pci/ctxfi/ctmixer.c
@@ -566,19 +566,6 @@
 	return 0;
 }
 
-static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
-
-	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
-	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
-	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
-	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
-
-	return 0;
-}
-
 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
@@ -586,6 +573,10 @@
 	unsigned int status;
 
 	atc->spdif_out_get_status(atc, &status);
+
+	if (status == 0)
+		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
+
 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
@@ -629,7 +620,7 @@
 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 	.count		= 1,
 	.info		= ct_spdif_info,
-	.get		= ct_spdif_default_get,
+	.get		= ct_spdif_get,
 	.put		= ct_spdif_put,
 	.private_value	= MIXER_IEC958_DEFAULT
 };
--- linux-ec2-2.6.32.orig/sound/pci/ctxfi/ctvmem.c
+++ linux-ec2-2.6.32/sound/pci/ctxfi/ctvmem.c
@@ -138,7 +138,7 @@
 		return NULL;
 	}
 
-	ptp = vm->ptp[0];
+	ptp = (unsigned long *)vm->ptp[0].area;
 	pte_start = (block->addr >> CT_PAGE_SHIFT);
 	pages = block->size >> CT_PAGE_SHIFT;
 	for (i = 0; i < pages; i++) {
@@ -158,25 +158,25 @@
 }
 
 /* *
- * return the host (kmalloced) addr of the @index-th device
- * page talbe page on success, or NULL on failure.
- * The first returned NULL indicates the termination.
+ * return the host physical addr of the @index-th device
+ * page table page on success, or ~0UL on failure.
+ * The first returned ~0UL indicates the termination.
  * */
-static void *
-ct_get_ptp_virt(struct ct_vm *vm, int index)
+static dma_addr_t
+ct_get_ptp_phys(struct ct_vm *vm, int index)
 {
-	void *addr;
+	dma_addr_t addr;
 
-	addr = (index >= CT_PTP_NUM) ? NULL : vm->ptp[index];
+	addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr;
 
 	return addr;
 }
 
-int ct_vm_create(struct ct_vm **rvm)
+int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci)
 {
 	struct ct_vm *vm;
 	struct ct_vm_block *block;
-	int i;
+	int i, err = 0;
 
 	*rvm = NULL;
 
@@ -188,23 +188,21 @@
 
 	/* Allocate page table pages */
 	for (i = 0; i < CT_PTP_NUM; i++) {
-		vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (!vm->ptp[i])
+		err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+					  snd_dma_pci_data(pci),
+					  PAGE_SIZE, &vm->ptp[i]);
+		if (err < 0)
 			break;
 	}
-	if (!i) {
+	if (err < 0) {
 		/* no page table pages are allocated */
-		kfree(vm);
+		ct_vm_destroy(vm);
 		return -ENOMEM;
 	}
 	vm->size = CT_ADDRS_PER_PAGE * i;
-	/* Initialise remaining ptps */
-	for (; i < CT_PTP_NUM; i++)
-		vm->ptp[i] = NULL;
-
 	vm->map = ct_vm_map;
 	vm->unmap = ct_vm_unmap;
-	vm->get_ptp_virt = ct_get_ptp_virt;
+	vm->get_ptp_phys = ct_get_ptp_phys;
 	INIT_LIST_HEAD(&vm->unused);
 	INIT_LIST_HEAD(&vm->used);
 	block = kzalloc(sizeof(*block), GFP_KERNEL);
@@ -242,7 +240,7 @@
 
 	/* free allocated page table pages */
 	for (i = 0; i < CT_PTP_NUM; i++)
-		kfree(vm->ptp[i]);
+		snd_dma_free_pages(&vm->ptp[i]);
 
 	vm->size = 0;
 
--- linux-ec2-2.6.32.orig/sound/pci/ac97/ac97_patch.c
+++ linux-ec2-2.6.32/sound/pci/ac97/ac97_patch.c
@@ -1867,11 +1867,14 @@
 	0x10140523, /* Thinkpad R40 */
 	0x10140534, /* Thinkpad X31 */
 	0x10140537, /* Thinkpad T41p */
+	0x1014053e, /* Thinkpad R40e */
 	0x10140554, /* Thinkpad T42p/R50p */
 	0x10140567, /* Thinkpad T43p 2668-G7U */
 	0x10140581, /* Thinkpad X41-2527 */
+	0x10280160, /* Dell Dimension 2400 */
 	0x104380b0, /* Asus A7V8X-MX */
 	0x11790241, /* Toshiba Satellite A-15 S127 */
+	0x1179ff10, /* Toshiba P500 */
 	0x144dc01a, /* Samsung NP-X20C004/SEG */
 	0 /* end */
 };
--- linux-ec2-2.6.32.orig/sound/pci/au88x0/au88x0_pcm.c
+++ linux-ec2-2.6.32/sound/pci/au88x0/au88x0_pcm.c
@@ -42,11 +42,7 @@
 	.rate_min = 5000,
 	.rate_max = 48000,
 	.channels_min = 1,
-#ifdef CHIP_AU8830
-	.channels_max = 4,
-#else
 	.channels_max = 2,
-#endif
 	.buffer_bytes_max = 0x10000,
 	.period_bytes_min = 0x1,
 	.period_bytes_max = 0x1000,
@@ -115,6 +111,17 @@
 	.periods_max = 64,
 };
 #endif
+#ifdef CHIP_AU8830
+static unsigned int au8830_channels[3] = {
+	1, 2, 4,
+};
+
+static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
+	.count = ARRAY_SIZE(au8830_channels),
+	.list = au8830_channels,
+	.mask = 0,
+};
+#endif
 /* open callback */
 static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
 {
@@ -156,6 +163,15 @@
 		if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB
 		    || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S)
 			runtime->hw = snd_vortex_playback_hw_adb;
+#ifdef CHIP_AU8830
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+			VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+			runtime->hw.channels_max = 4;
+			snd_pcm_hw_constraint_list(runtime, 0,
+				SNDRV_PCM_HW_PARAM_CHANNELS,
+				&hw_constraints_au8830_channels);
+		}
+#endif
 		substream->runtime->private_data = NULL;
 	}
 #ifndef CHIP_AU8810
--- linux-ec2-2.6.32.orig/sound/pci/emu10k1/emupcm.c
+++ linux-ec2-2.6.32/sound/pci/emu10k1/emupcm.c
@@ -332,7 +332,7 @@
 		evoice->epcm->ccca_start_addr = start_addr + ccis;
 		if (extra) {
 			start_addr += ccis;
-			end_addr += ccis;
+			end_addr += ccis + emu->delay_pcm_irq;
 		}
 		if (stereo && !extra) {
 			snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK);
@@ -360,7 +360,9 @@
 	/* Assumption that PT is already 0 so no harm overwriting */
 	snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
 	snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
-	snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
+	snd_emu10k1_ptr_write(emu, PSST, voice,
+			(start_addr + (extra ? emu->delay_pcm_irq : 0)) |
+			(send_amount[2] << 24));
 	if (emu->card_capabilities->emu_model)
 		pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
 	else 
@@ -732,6 +734,23 @@
 	snd_emu10k1_ptr_write(emu, IP, voice, 0);
 }
 
+static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu,
+		struct snd_emu10k1_pcm *epcm,
+		struct snd_pcm_substream *substream,
+		struct snd_pcm_runtime *runtime)
+{
+	unsigned int ptr, period_pos;
+
+	/* try to sychronize the current position for the interrupt
+	   source voice */
+	period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt;
+	period_pos %= runtime->period_size;
+	ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number);
+	ptr &= ~0x00ffffff;
+	ptr |= epcm->ccca_start_addr + period_pos;
+	snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr);
+}
+
 static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
 				        int cmd)
 {
@@ -753,6 +772,8 @@
 		/* follow thru */
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 	case SNDRV_PCM_TRIGGER_RESUME:
+		if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE)
+			snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime);
 		mix = &emu->pcm_mixer[substream->number];
 		snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
 		snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
@@ -869,8 +890,9 @@
 #endif
 	/*
 	printk(KERN_DEBUG
-	       "ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n",
-	       ptr, runtime->buffer_size, runtime->period_size);
+	       "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n",
+	       (long)ptr, (long)runtime->buffer_size,
+	       (long)runtime->period_size);
 	*/
 	return ptr;
 }
--- linux-ec2-2.6.32.orig/sound/pci/emu10k1/emu10k1.c
+++ linux-ec2-2.6.32/sound/pci/emu10k1/emu10k1.c
@@ -52,6 +52,7 @@
 static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128};
 static int enable_ir[SNDRV_CARDS];
 static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
+static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
@@ -73,6 +74,8 @@
 MODULE_PARM_DESC(enable_ir, "Enable IR.");
 module_param_array(subsystem, uint, NULL, 0444);
 MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
+module_param_array(delay_pcm_irq, uint, NULL, 0444);
+MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0).");
 /*
  * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value  Model:SB0400
  */
@@ -127,6 +130,7 @@
 				      &emu)) < 0)
 		goto error;
 	card->private_data = emu;
+	emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
 	if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0)
 		goto error;
 	if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0)
--- linux-ec2-2.6.32.orig/sound/pci/emu10k1/memory.c
+++ linux-ec2-2.6.32/sound/pci/emu10k1/memory.c
@@ -309,8 +309,10 @@
 	if (snd_BUG_ON(!hdr))
 		return NULL;
 
+	idx = runtime->period_size >= runtime->buffer_size ?
+					(emu->delay_pcm_irq * 2) : 0;
 	mutex_lock(&hdr->block_mutex);
-	blk = search_empty(emu, runtime->dma_bytes);
+	blk = search_empty(emu, runtime->dma_bytes + idx);
 	if (blk == NULL) {
 		mutex_unlock(&hdr->block_mutex);
 		return NULL;
--- linux-ec2-2.6.32.orig/sound/pci/rme9652/hdsp.c
+++ linux-ec2-2.6.32/sound/pci/rme9652/hdsp.c
@@ -4610,6 +4610,7 @@
 		if (err < 0)
 			return err;
 
+		memset(&info, 0, sizeof(info));
 		spin_lock_irqsave(&hdsp->lock, flags);
 		info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
 		info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
--- linux-ec2-2.6.32.orig/sound/pci/rme9652/hdspm.c
+++ linux-ec2-2.6.32/sound/pci/rme9652/hdspm.c
@@ -4127,6 +4127,7 @@
 
 	case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
 
+		memset(&info, 0, sizeof(info));
 		spin_lock_irq(&hdspm->lock);
 		info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
 		info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
--- linux-ec2-2.6.32.orig/sound/pci/echoaudio/echoaudio.c
+++ linux-ec2-2.6.32/sound/pci/echoaudio/echoaudio.c
@@ -1821,7 +1821,9 @@
 	/* The hardware doesn't tell us which substream caused the irq,
 	thus we have to check all running substreams. */
 	for (ss = 0; ss < DSP_MAXPIPES; ss++) {
-		if ((substream = chip->substream[ss])) {
+		substream = chip->substream[ss];
+		if (substream && ((struct audiopipe *)substream->runtime->
+				private_data)->state == PIPE_STATE_STARTED) {
 			period = pcm_pointer(substream) /
 				substream->runtime->period_size;
 			if (period != chip->last_period[ss]) {
--- linux-ec2-2.6.32.orig/sound/pci/mixart/mixart.c
+++ linux-ec2-2.6.32/sound/pci/mixart/mixart.c
@@ -1161,13 +1161,15 @@
 				unsigned long count, unsigned long pos)
 {
 	struct mixart_mgr *mgr = entry->private_data;
+	unsigned long maxsize;
 
-	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
-	if(count <= 0)
+	if (pos >= MIXART_BA0_SIZE)
 		return 0;
-	if(pos + count > MIXART_BA0_SIZE)
-		count = (long)(MIXART_BA0_SIZE - pos);
-	if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count))
+	maxsize = MIXART_BA0_SIZE - pos;
+	if (count > maxsize)
+		count = maxsize;
+	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+	if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
 		return -EFAULT;
 	return count;
 }
@@ -1180,13 +1182,15 @@
 				unsigned long count, unsigned long pos)
 {
 	struct mixart_mgr *mgr = entry->private_data;
+	unsigned long maxsize;
 
-	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
-	if(count <= 0)
+	if (pos > MIXART_BA1_SIZE)
 		return 0;
-	if(pos + count > MIXART_BA1_SIZE)
-		count = (long)(MIXART_BA1_SIZE - pos);
-	if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count))
+	maxsize = MIXART_BA1_SIZE - pos;
+	if (count > maxsize)
+		count = maxsize;
+	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+	if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
 		return -EFAULT;
 	return count;
 }
--- linux-ec2-2.6.32.orig/sound/pci/oxygen/oxygen.c
+++ linux-ec2-2.6.32/sound/pci/oxygen/oxygen.c
@@ -393,6 +393,10 @@
 		chip->model.suspend = claro_suspend;
 		chip->model.resume = claro_resume;
 		chip->model.set_adc_params = set_ak5385_params;
+		chip->model.device_config = PLAYBACK_0_TO_I2S |
+					    PLAYBACK_1_TO_SPDIF |
+					    CAPTURE_0_FROM_I2S_2 |
+					    CAPTURE_1_FROM_SPDIF;
 		break;
 	}
 	if (id->driver_data == MODEL_MERIDIAN ||
--- linux-ec2-2.6.32.orig/sound/pci/ice1712/maya44.c
+++ linux-ec2-2.6.32/sound/pci/ice1712/maya44.c
@@ -347,7 +347,7 @@
 
 /* known working input slots (0-4) */
 #define MAYA_LINE_IN	1	/* in-2 */
-#define MAYA_MIC_IN	4	/* in-5 */
+#define MAYA_MIC_IN	3	/* in-4 */
 
 static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
 {
@@ -393,8 +393,8 @@
 	int changed;
 
 	mutex_lock(&chip->mutex);
-	changed = maya_set_gpio_bits(chip->ice, GPIO_MIC_RELAY,
-				     sel ? GPIO_MIC_RELAY : 0);
+	changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
+				     sel ? (1 << GPIO_MIC_RELAY) : 0);
 	wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
 	mutex_unlock(&chip->mutex);
 	return changed;
--- linux-ec2-2.6.32.orig/sound/pci/ice1712/juli.c
+++ linux-ec2-2.6.32/sound/pci/ice1712/juli.c
@@ -504,6 +504,31 @@
 }
 
 /*
+ * suspend/resume
+ * */
+
+#ifdef CONFIG_PM
+static int juli_resume(struct snd_ice1712 *ice)
+{
+	struct snd_akm4xxx *ak = ice->akm;
+	struct juli_spec *spec = ice->spec;
+	/* akm4358 un-reset, un-mute */
+	snd_akm4xxx_reset(ak, 0);
+	/* reinit ak4114 */
+	snd_ak4114_reinit(spec->ak4114);
+	return 0;
+}
+
+static int juli_suspend(struct snd_ice1712 *ice)
+{
+	struct snd_akm4xxx *ak = ice->akm;
+	/* akm4358 reset and soft-mute */
+	snd_akm4xxx_reset(ak, 1);
+	return 0;
+}
+#endif
+
+/*
  * initialize the chip
  */
 
@@ -646,6 +671,13 @@
 	ice->set_spdif_clock = juli_set_spdif_clock;
 
 	ice->spdif.ops.open = juli_spdif_in_open;
+
+#ifdef CONFIG_PM
+	ice->pm_resume = juli_resume;
+	ice->pm_suspend = juli_suspend;
+	ice->pm_suspend_enabled = 1;
+#endif
+
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/sound/pci/riptide/riptide.c
+++ linux-ec2-2.6.32/sound/pci/riptide/riptide.c
@@ -1224,15 +1224,14 @@
 		    firmware.firmware.ASIC, firmware.firmware.CODEC,
 		    firmware.firmware.AUXDSP, firmware.firmware.PROG);
 
+	if (!chip)
+		return 1;
+
 	for (i = 0; i < FIRMWARE_VERSIONS; i++) {
 		if (!memcmp(&firmware_versions[i], &firmware, sizeof(firmware)))
-			break;
-	}
-	if (i >= FIRMWARE_VERSIONS)
-		return 0; /* no match */
+			return 1; /* OK */
 
-	if (!chip)
-		return 1; /* OK */
+	}
 
 	snd_printdd("Writing Firmware\n");
 	if (!chip->fw_entry) {
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_codec.h
+++ linux-ec2-2.6.32/sound/pci/hda/hda_codec.h
@@ -811,6 +811,9 @@
 	unsigned int power_transition :1; /* power-state in transition */
 	int power_count;	/* current (global) power refcount */
 	struct delayed_work power_work; /* delayed task for powerdown */
+	unsigned long power_on_acct;
+	unsigned long power_off_acct;
+	unsigned long power_jiffies;
 #endif
 
 	/* codec-specific additional proc output */
@@ -933,6 +936,7 @@
 void snd_hda_power_up(struct hda_codec *codec);
 void snd_hda_power_down(struct hda_codec *codec);
 #define snd_hda_codec_needs_resume(codec) codec->power_count
+void snd_hda_update_power_acct(struct hda_codec *codec);
 #else
 static inline void snd_hda_power_up(struct hda_codec *codec) {}
 static inline void snd_hda_power_down(struct hda_codec *codec) {}
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_codec.c
+++ linux-ec2-2.6.32/sound/pci/hda/hda_codec.c
@@ -515,6 +515,7 @@
 	struct hda_codec *codec;
 	list_for_each_entry(codec, &bus->codec_list, list) {
 		snd_hda_hwdep_add_sysfs(codec);
+		snd_hda_hwdep_add_power_sysfs(codec);
 	}
 	return 0;
 }
@@ -2452,9 +2453,11 @@
 			    codec->afg ? codec->afg : codec->mfg,
 			    AC_PWRST_D3);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+	snd_hda_update_power_acct(codec);
 	cancel_delayed_work(&codec->power_work);
 	codec->power_on = 0;
 	codec->power_transition = 0;
+	codec->power_jiffies = jiffies;
 #endif
 }
 
@@ -3207,6 +3210,17 @@
 {
 	codec->power_count++;
 	codec->power_on = 1;
+	codec->power_jiffies = jiffies;
+}
+
+void snd_hda_update_power_acct(struct hda_codec *codec)
+{
+	unsigned long delta = jiffies - codec->power_jiffies;
+	if (codec->power_on)
+		codec->power_on_acct += delta;
+	else
+		codec->power_off_acct += delta;
+	codec->power_jiffies += delta;
 }
 
 void snd_hda_power_up(struct hda_codec *codec)
@@ -3217,7 +3231,9 @@
 	if (codec->power_on || codec->power_transition)
 		return;
 
+	snd_hda_update_power_acct(codec);
 	codec->power_on = 1;
+	codec->power_jiffies = jiffies;
 	if (bus->ops.pm_notify)
 		bus->ops.pm_notify(bus);
 	hda_call_codec_resume(codec);
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_eld.c
+++ linux-ec2-2.6.32/sound/pci/hda/hda_eld.c
@@ -383,7 +383,7 @@
 	snd_print_pcm_rates(a->rates, buf, sizeof(buf));
 
 	if (a->format == AUDIO_CODING_TYPE_LPCM)
-		snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8));
+		snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8);
 	else if (a->max_bitrate)
 		snprintf(buf2, sizeof(buf2),
 				", max bitrate = %d", a->max_bitrate);
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_realtek.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_realtek.c
@@ -400,6 +400,8 @@
 	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
 	if (mux_idx >= spec->num_mux_defs)
 		mux_idx = 0;
+	if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
+		mux_idx = 0;
 	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
 }
 
@@ -428,6 +430,8 @@
 
 	mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
 	imux = &spec->input_mux[mux_idx];
+	if (!imux->num_items && mux_idx > 0)
+		imux = &spec->input_mux[0];
 
 	type = get_wcaps_type(get_wcaps(codec, nid));
 	if (type == AC_WID_AUD_MIX) {
@@ -1149,7 +1153,7 @@
 		case 0x10ec0883:
 		case 0x10ec0885:
 		case 0x10ec0887:
-		case 0x10ec0889:
+		/*case 0x10ec0889:*/ /* this causes an SPDIF problem */
 			alc889_coef_init(codec);
 			break;
 		case 0x10ec0888:
@@ -2401,6 +2405,8 @@
 	"Speaker Playback Switch",
 	"Mono Playback Switch",
 	"IEC958 Playback Switch",
+	"Line-Out Playback Switch",
+	"PCM Playback Switch",
 	NULL,
 };
 
@@ -3965,10 +3971,11 @@
 	SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
 	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
-	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
+	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
 	SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
 	SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
 	SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+	SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
 	SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
 	SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
 	SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
@@ -6246,6 +6253,7 @@
 
 static struct snd_pci_quirk alc260_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
+	SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
 	SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
 	SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
 	SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
@@ -6275,7 +6283,7 @@
 		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
 		.dac_nids = alc260_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
-		.adc_nids = alc260_adc_nids,
+		.adc_nids = alc260_dual_adc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
 		.input_mux = &alc260_capture_source,
@@ -6448,6 +6456,7 @@
 
 	spec->stream_analog_playback = &alc260_pcm_analog_playback;
 	spec->stream_analog_capture = &alc260_pcm_analog_capture;
+	spec->stream_analog_alt_capture = &alc260_pcm_analog_capture;
 
 	spec->stream_digital_playback = &alc260_pcm_digital_playback;
 	spec->stream_digital_capture = &alc260_pcm_digital_capture;
@@ -6581,7 +6590,7 @@
 	.num_items = 4,
 	.items = {
 		{ "Mic", 0x0 },
-		{ "iMic", 0x1 },
+		{ "Int Mic", 0x1 },
 		{ "Line", 0x2 },
 		{ "CD", 0x4 },
 	},
@@ -7040,8 +7049,8 @@
 	HDA_BIND_MUTE   ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
 	HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
-	HDA_BIND_MUTE   ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+	HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@ -7428,6 +7437,7 @@
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
 	/* Front Mic pin: input vref at 80% */
 	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@ -7552,6 +7562,27 @@
 	spec->autocfg.speaker_pins[0] = 0x14;
 }
 
+static void alc885_mb5_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+	snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+
+}
+
+static void alc885_mb5_unsol_event(struct hda_codec *codec,
+				    unsigned int res)
+{
+	/* Headphone insertion or removal. */
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc885_mb5_automute(codec);
+}
+
 
 static struct hda_verb alc882_targa_verbs[] = {
 	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -8008,8 +8039,8 @@
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	{ } /* end */
 };
 
@@ -8839,7 +8870,7 @@
 	SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
 	SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
-	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+	SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
 	SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
@@ -8866,6 +8897,7 @@
 	SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
 
 	SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
 	SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
 	SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
 	SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
@@ -8893,7 +8925,7 @@
 	SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
 	SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
 	SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
-	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
+	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
 
 	{}
 };
@@ -8907,10 +8939,12 @@
 	SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
 	SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
 	SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
+	SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
 	SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
 	SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
 	SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
 	SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
+	SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
 	/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
 	 * so apparently no perfect solution yet
 	 */
@@ -8994,6 +9028,8 @@
 		.input_mux = &mb5_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
+		.unsol_event = alc885_mb5_unsol_event,
+		.init_hook = alc885_mb5_automute,
 	},
 	[ALC885_MACPRO] = {
 		.mixers = { alc882_macpro_mixer },
@@ -9141,6 +9177,8 @@
 		.dac_nids = alc883_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
 		.adc_nids = alc889_adc_nids,
+		.capsrc_nids = alc889_capsrc_nids,
+		.capsrc_nids = alc889_capsrc_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
 		.dig_in_nid = ALC883_DIGIN_NID,
 		.slave_dig_outs = alc883_slave_dig_outs,
@@ -9187,6 +9225,7 @@
 		.dac_nids = alc883_dac_nids,
 		.adc_nids = alc883_adc_nids_alt,
 		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
 		.dig_out_nid = ALC883_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
@@ -9333,6 +9372,7 @@
 		.dac_nids = alc883_dac_nids,
 		.adc_nids = alc883_adc_nids_alt,
 		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
 		.input_mux = &alc883_capture_source,
@@ -9394,6 +9434,7 @@
 		.dac_nids = alc883_dac_nids,
 		.adc_nids = alc883_adc_nids_alt,
 		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+		.capsrc_nids = alc883_capsrc_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_lenovo_101e_capture_source,
@@ -9573,6 +9614,7 @@
 			alc880_gpio1_init_verbs },
 		.adc_nids = alc883_adc_nids,
 		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.capsrc_nids = alc883_capsrc_nids,
 		.dac_nids = alc883_dac_nids,
 		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
 		.channel_mode = alc889A_mb31_6ch_modes,
@@ -9711,6 +9753,8 @@
 			continue;
 		mux_idx = c >= spec->num_mux_defs ? 0 : c;
 		imux = &spec->input_mux[mux_idx];
+		if (!imux->num_items && mux_idx > 0)
+			imux = &spec->input_mux[0];
 		for (idx = 0; idx < conns; idx++) {
 			/* if the current connection is the selected one,
 			 * unmute it as default - otherwise mute it
@@ -10146,7 +10190,7 @@
 	struct alc_spec *spec = codec->spec;
 
 	spec->autocfg.hp_pins[0] = 0x15;
-	spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */
+	spec->autocfg.speaker_pins[0] = 0x14;
 }
 
 static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -10581,6 +10625,13 @@
 	{}
 };
 
+static struct hda_verb alc262_lenovo_3000_init_verbs[] = {
+	/* Front Mic pin: input vref at 50% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{}
+};
+
 static struct hda_input_mux alc262_fujitsu_capture_source = {
 	.num_items = 3,
 	.items = {
@@ -11580,9 +11631,9 @@
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hp_t5735_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HP_RP5700] = {
 		.mixers = { alc262_hp_rp5700_mixer },
@@ -11648,7 +11699,8 @@
 	[ALC262_LENOVO_3000] = {
 		.mixers = { alc262_lenovo_3000_mixer },
 		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
-				alc262_lenovo_3000_unsol_verbs },
+				alc262_lenovo_3000_unsol_verbs,
+				alc262_lenovo_3000_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc262_dac_nids),
 		.dac_nids = alc262_dac_nids,
 		.hp_nid = 0x03,
@@ -12338,6 +12390,9 @@
 		dac = 0x02;
 		break;
 	case 0x15:
+	case 0x1a: /* ALC259/269 only */
+	case 0x1b: /* ALC259/269 only */
+	case 0x21: /* ALC269vb has this pin, too */
 		dac = 0x03;
 		break;
 	default:
@@ -14679,6 +14734,8 @@
 	spec->stream_digital_playback = &alc861_pcm_digital_playback;
 	spec->stream_digital_capture = &alc861_pcm_digital_capture;
 
+	if (!spec->cap_mixer)
+		set_capture_mixer(codec);
 	set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
 
 	spec->vmaster_nid = 0x03;
@@ -15317,7 +15374,7 @@
 static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
 						const struct auto_pin_cfg *cfg)
 {
-	return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
+	return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0);
 }
 
 
@@ -17204,6 +17261,8 @@
 		return 0x02;
 	else if (nid >= 0x0c && nid <= 0x0e)
 		return nid - 0x0c + 0x02;
+	else if (nid == 0x26) /* ALC887-VD has this DAC too */
+		return 0x25;
 	else
 		return 0;
 }
@@ -17212,7 +17271,7 @@
 static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
 				   hda_nid_t dac)
 {
-	hda_nid_t mix[4];
+	hda_nid_t mix[5];
 	int i, num;
 
 	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_intel.c
+++ linux-ec2-2.6.32/sound/pci/hda/hda_intel.c
@@ -116,6 +116,7 @@
 			 "{Intel, ICH9},"
 			 "{Intel, ICH10},"
 			 "{Intel, PCH},"
+			 "{Intel, CPT},"
 			 "{Intel, SCH},"
 			 "{ATI, SB450},"
 			 "{ATI, SB600},"
@@ -437,6 +438,7 @@
 /* driver types */
 enum {
 	AZX_DRIVER_ICH,
+	AZX_DRIVER_PCH,
 	AZX_DRIVER_SCH,
 	AZX_DRIVER_ATI,
 	AZX_DRIVER_ATIHDMI,
@@ -451,6 +453,7 @@
 
 static char *driver_short_names[] __devinitdata = {
 	[AZX_DRIVER_ICH] = "HDA Intel",
+	[AZX_DRIVER_PCH] = "HDA Intel PCH",
 	[AZX_DRIVER_SCH] = "HDA Intel MID",
 	[AZX_DRIVER_ATI] = "HDA ATI SB",
 	[AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
@@ -1039,6 +1042,7 @@
 				0x01, NVIDIA_HDA_ENABLE_COHBIT);
 		break;
 	case AZX_DRIVER_SCH:
+	case AZX_DRIVER_PCH:
 		pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
 		if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
 			pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
@@ -1858,6 +1862,9 @@
 
 	if (!bdl_pos_adj[chip->dev_index])
 		return 1; /* no delayed ack */
+	if (WARN_ONCE(!azx_dev->period_bytes,
+		      "hda-intel: zero azx_dev->period_bytes"))
+		return 0; /* this shouldn't happen! */
 	if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
 		return 0; /* NG - it's below the period boundary */
 	return 1; /* OK, it's fine */
@@ -1944,6 +1951,7 @@
 	struct azx_pcm *apcm;
 	int pcm_dev = cpcm->device;
 	int s, err;
+	size_t prealloc_min = 64*1024;	/* 64KB */
 
 	if (pcm_dev >= AZX_MAX_PCMS) {
 		snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
@@ -1977,10 +1985,21 @@
 		if (cpcm->stream[s].substreams)
 			snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
 	}
+
 	/* buffer pre-allocation */
+
+	/* subtle, don't allocate a big buffer for modems...
+	 * also, don't just test 32BIT_MASK, since azx supports
+	 * 64-bit DMA in some cases.
+	 */
+	/* lennart wants a 2.2MB buffer for 2sec of 48khz */
+	if (pcm->dev_class == SNDRV_PCM_CLASS_GENERIC &&
+	    chip->pci->dma_mask >= DMA_32BIT_MASK)
+		prealloc_min = 4 * 1024 * 1024;	/* 4MB */
+
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 					      snd_dma_pci_data(chip->pci),
-					      1024 * 64, 32 * 1024 * 1024);
+					      prealloc_min, 32 * 1024 * 1024);
 	return 0;
 }
 
@@ -2219,9 +2238,27 @@
  * white/black-listing for position_fix
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+	SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1043, 0x8410, "ASUS", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB),
 	{}
 };
 
@@ -2309,6 +2346,7 @@
 static struct snd_pci_quirk msi_white_list[] __devinitdata = {
 	SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1),
 	SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1),
+	SND_PCI_QUIRK(0x107b, 0x0380, "Gateway M-6866", 1),
 	{}
 };
 
@@ -2325,6 +2363,13 @@
 		       "hda_intel: msi for device %04x:%04x set to %d\n",
 		       q->subvendor, q->subdevice, q->value);
 		chip->msi = q->value;
+		return;
+	}
+
+	/* NVidia chipsets seem to cause troubles with MSI */
+	if (chip->driver_type == AZX_DRIVER_NVIDIA) {
+		printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n");
+		chip->msi = 0;
 	}
 }
 
@@ -2374,6 +2419,7 @@
 	if (bdl_pos_adj[dev] < 0) {
 		switch (chip->driver_type) {
 		case AZX_DRIVER_ICH:
+		case AZX_DRIVER_PCH:
 			bdl_pos_adj[dev] = 1;
 			break;
 		default:
@@ -2436,6 +2482,11 @@
 		}
 	}
 
+	/* disable 64bit DMA address for Teradici */
+	/* it does not work with device 6549:1200 subsys e4a2:040b */
+	if (chip->driver_type == AZX_DRIVER_TERA)
+		gcap &= ~ICH6_GCAP_64OK;
+
 	/* allow 64bit DMA address if supported by H/W */
 	if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
 		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
@@ -2643,6 +2694,9 @@
 	{ PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
 	/* PCH */
 	{ PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
+	{ PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
+	/* CPT */
+	{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
 	/* SCH */
 	{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
 	/* ATI SB 450/600 */
@@ -2689,6 +2743,9 @@
 	{ PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA },
+	{ PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
 	{ PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_hwdep.c
+++ linux-ec2-2.6.32/sound/pci/hda/hda_hwdep.c
@@ -154,6 +154,44 @@
 	return 0;
 }
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static ssize_t power_on_acct_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	snd_hda_update_power_acct(codec);
+	return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
+}
+
+static ssize_t power_off_acct_show(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
+	struct hda_codec *codec = hwdep->private_data;
+	snd_hda_update_power_acct(codec);
+	return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
+}
+
+static struct device_attribute power_attrs[] = {
+	__ATTR_RO(power_on_acct),
+	__ATTR_RO(power_off_acct),
+};
+
+int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
+{
+	struct snd_hwdep *hwdep = codec->hwdep;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(power_attrs); i++)
+		snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
+					  hwdep->device, &power_attrs[i]);
+	return 0;
+}
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
 #ifdef CONFIG_SND_HDA_RECONFIG
 
 /*
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_analog.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_analog.c
@@ -1003,7 +1003,7 @@
 	SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
-	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
 	SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
@@ -1789,6 +1789,14 @@
 	case AD1981_THINKPAD:
 		spec->mixers[0] = ad1981_thinkpad_mixers;
 		spec->input_mux = &ad1981_thinkpad_capture_source;
+		/* set the upper-limit for mixer amp to 0dB for avoiding the
+		 * possible damage by overloading
+		 */
+		snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
+					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+					  (1 << AC_AMPCAP_MUTE_SHIFT));
 		break;
 	case AD1981_TOSHIBA:
 		spec->mixers[0] = ad1981_hp_mixers;
@@ -3502,6 +3510,7 @@
 	/* Lenovo Thinkpad T61/X61 */
 	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD),
 	SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP),
+	SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP),
 	{}
 };
 
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_sigmatel.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_sigmatel.c
@@ -727,7 +727,7 @@
 	struct sigmatel_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int idx, prev_idx;
+	unsigned int idx, prev_idx, didx;
 
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
@@ -739,7 +739,8 @@
 		snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
 					  imux->items[idx].index);
-		if (prev_idx >= spec->num_analog_muxes) {
+		if (prev_idx >= spec->num_analog_muxes &&
+		    spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) {
 			imux = spec->dinput_mux;
 			/* 0 = analog */
 			snd_hda_codec_write_cache(codec,
@@ -749,9 +750,13 @@
 		}
 	} else {
 		imux = spec->dinput_mux;
+		/* first dimux item is hardcoded to select analog imux,
+		 * so lets skip it
+		 */
+		didx = idx - spec->num_analog_muxes + 1;
 		snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
-					  imux->items[idx - 1].index);
+					  imux->items[didx].index);
 	}
 	spec->cur_mux[adc_idx] = idx;
 	return 1;
@@ -1592,12 +1597,18 @@
 				"Dell Studio 1555", STAC_DELL_M6_DMIC),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
 				"Dell Studio 1557", STAC_DELL_M6_DMIC),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
+				"Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
+				"Dell Studio 1558", STAC_DELL_M6_BOTH),
 	{} /* terminator */
 };
 
 static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1,
 		      "Alienware M17x", STAC_ALIENWARE_M17X),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
+		      "Alienware M17x", STAC_ALIENWARE_M17X),
 	{} /* terminator */
 };
 
@@ -1712,6 +1723,8 @@
 		      "HP HDX", STAC_HP_HDX),  /* HDX16 */
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620,
 		      "HP dv6", STAC_HP_DV5),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061,
+		      "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010,
 		      "HP", STAC_HP_DV5),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233,
@@ -2053,12 +2066,12 @@
 	SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000,
 			   "Intel D965", STAC_D965_3ST),
 	/* Dell 3 stack systems */
-	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01dd, "Dell Dimension E520", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01ed, "Dell     ", STAC_DELL_3ST),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f4, "Dell     ", STAC_DELL_3ST),
 	/* Dell 3 stack systems with verb table in BIOS */
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x01f7, "Dell XPS M1730", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x0227, "Dell Vostro 1400  ", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022e, "Dell     ", STAC_DELL_BIOS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL,  0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_conexant.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_conexant.c
@@ -366,10 +366,16 @@
 	struct conexant_spec *spec;
 	struct conexant_jack *jack;
 	const char *name;
-	int err;
+	int i, err;
 
 	spec = codec->spec;
 	snd_array_init(&spec->jacks, sizeof(*jack), 32);
+
+	jack = spec->jacks.list;
+	for (i = 0; i < spec->jacks.used; i++, jack++)
+		if (jack->nid == nid)
+			return 0 ; /* already present */
+
 	jack = snd_array_new(&spec->jacks);
 	name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
 
@@ -1175,9 +1181,12 @@
 
 	switch (codec->subsystem_id >> 16) {
 	case 0x103c:
-		/* HP laptop has a really bad sound over 0dB on NID 0x17.
-		 * Fix max PCM level to 0 dB
-		 * (originall it has 0x2b steps with 0dB offset 0x14)
+	case 0x1631:
+	case 0x1734:
+	case 0x17aa:
+		/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
+		 * really bad sound over 0dB on NID 0x17. Fix max PCM level to
+		 * 0 dB (originally it has 0x2b steps with 0dB offset 0x14)
 		 */
 		snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
 					  (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -1581,6 +1590,21 @@
 #endif	
 	}
 	spec->vmaster_nid = 0x13;
+
+	switch (codec->subsystem_id >> 16) {
+	case 0x103c:
+		/* HP laptops have really bad sound over 0 dB on NID 0x10.
+		 * Fix max PCM level to 0 dB (originally it has 0x1e steps
+		 * with 0 dB offset 0x17)
+		 */
+		snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
+					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+					  (1 << AC_AMPCAP_MUTE_SHIFT));
+		break;
+	}
+
 	return 0;
 }
 
@@ -2333,6 +2357,8 @@
 	SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
 		      CXT5066_DELL_LAPTOP),
 	SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
+	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
+	SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
 	{}
 };
 
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_intelhdmi.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_intelhdmi.c
@@ -684,7 +684,7 @@
 	{ .id = 0x80862801, .name = "G45 DEVBLC", .patch = patch_intel_hdmi },
 	{ .id = 0x80862802, .name = "G45 DEVCTG", .patch = patch_intel_hdmi },
 	{ .id = 0x80862803, .name = "G45 DEVELK", .patch = patch_intel_hdmi },
-	{ .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi },
+	{ .id = 0x80862804, .name = "G45 DEVIBX", .patch = patch_intel_hdmi_ibexpeak },
 	{ .id = 0x80860054, .name = "Q57 DEVIBX", .patch = patch_intel_hdmi_ibexpeak },
 	{ .id = 0x10951392, .name = "SiI1392 HDMI",     .patch = patch_intel_hdmi },
 	{} /* terminator */
--- linux-ec2-2.6.32.orig/sound/pci/hda/patch_cirrus.c
+++ linux-ec2-2.6.32/sound/pci/hda/patch_cirrus.c
@@ -65,7 +65,9 @@
 
 /* available models */
 enum {
+	CS420X_MBP53,
 	CS420X_MBP55,
+	CS420X_IMAC27,
 	CS420X_AUTO,
 	CS420X_MODELS
 };
@@ -832,7 +834,9 @@
 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
 				    hp_present ? 0 : PIN_OUT);
 	}
-	if (spec->board_config == CS420X_MBP55) {
+	if (spec->board_config == CS420X_MBP53 ||
+	    spec->board_config == CS420X_MBP55 ||
+	    spec->board_config == CS420X_IMAC27) {
 		unsigned int gpio = hp_present ? 0x02 : 0x08;
 		snd_hda_codec_write(codec, 0x01, 0,
 				    AC_VERB_SET_GPIO_DATA, gpio);
@@ -1077,13 +1081,19 @@
 }
 
 static const char *cs420x_models[CS420X_MODELS] = {
+	[CS420X_MBP53] = "mbp53",
 	[CS420X_MBP55] = "mbp55",
+	[CS420X_IMAC27] = "imac27",
 	[CS420X_AUTO] = "auto",
 };
 
 
 static struct snd_pci_quirk cs420x_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
+	SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
 	SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+	SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
+	SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
 	{} /* terminator */
 };
 
@@ -1092,6 +1102,20 @@
 	u32 val;
 };
 
+static struct cs_pincfg mbp53_pincfgs[] = {
+	{ 0x09, 0x012b4050 },
+	{ 0x0a, 0x90100141 },
+	{ 0x0b, 0x90100140 },
+	{ 0x0c, 0x018b3020 },
+	{ 0x0d, 0x90a00110 },
+	{ 0x0e, 0x400000f0 },
+	{ 0x0f, 0x01cbe030 },
+	{ 0x10, 0x014be060 },
+	{ 0x12, 0x400000f0 },
+	{ 0x15, 0x400000f0 },
+	{} /* terminator */
+};
+
 static struct cs_pincfg mbp55_pincfgs[] = {
 	{ 0x09, 0x012b4030 },
 	{ 0x0a, 0x90100121 },
@@ -1106,8 +1130,24 @@
 	{} /* terminator */
 };
 
+static struct cs_pincfg imac27_pincfgs[] = {
+	{ 0x09, 0x012b4050 },
+	{ 0x0a, 0x90100140 },
+	{ 0x0b, 0x90100142 },
+	{ 0x0c, 0x018b3020 },
+	{ 0x0d, 0x90a00110 },
+	{ 0x0e, 0x400000f0 },
+	{ 0x0f, 0x01cbe030 },
+	{ 0x10, 0x014be060 },
+	{ 0x12, 0x01ab9070 },
+	{ 0x15, 0x400000f0 },
+	{} /* terminator */
+};
+
 static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
+	[CS420X_MBP53] = mbp53_pincfgs,
 	[CS420X_MBP55] = mbp55_pincfgs,
+	[CS420X_IMAC27] = imac27_pincfgs,
 };
 
 static void fix_pincfg(struct hda_codec *codec, int model)
@@ -1137,6 +1177,8 @@
 		fix_pincfg(codec, spec->board_config);
 
 	switch (spec->board_config) {
+	case CS420X_IMAC27:
+	case CS420X_MBP53:
 	case CS420X_MBP55:
 		/* GPIO1 = headphones */
 		/* GPIO3 = speakers */
--- linux-ec2-2.6.32.orig/sound/pci/hda/hda_local.h
+++ linux-ec2-2.6.32/sound/pci/hda/hda_local.h
@@ -437,6 +437,15 @@
 static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
 #endif
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec);
+#else
+static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SND_HDA_RECONFIG
 int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
 #else
--- linux-ec2-2.6.32.orig/sound/core/control.c
+++ linux-ec2-2.6.32/sound/core/control.c
@@ -31,6 +31,7 @@
 
 /* max number of user-defined controls */
 #define MAX_USER_CONTROLS	32
+#define MAX_CONTROL_COUNT	1028
 
 struct snd_kctl_ioctl {
 	struct list_head list;		/* list of all ioctls */
@@ -190,6 +191,10 @@
 	
 	if (snd_BUG_ON(!control || !control->count))
 		return NULL;
+
+	if (control->count > MAX_CONTROL_COUNT)
+		return NULL;
+
 	kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
 	if (kctl == NULL) {
 		snd_printk(KERN_ERR "Cannot allocate control instance\n");
--- linux-ec2-2.6.32.orig/sound/core/hrtimer.c
+++ linux-ec2-2.6.32/sound/core/hrtimer.c
@@ -37,14 +37,23 @@
 struct snd_hrtimer {
 	struct snd_timer *timer;
 	struct hrtimer hrt;
+	atomic_t running;
 };
 
 static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
 {
 	struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
 	struct snd_timer *t = stime->timer;
-	hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
-	snd_timer_interrupt(stime->timer, t->sticks);
+	unsigned long oruns;
+
+	if (!atomic_read(&stime->running))
+		return HRTIMER_NORESTART;
+
+	oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
+	snd_timer_interrupt(stime->timer, t->sticks * oruns);
+
+	if (!atomic_read(&stime->running))
+		return HRTIMER_NORESTART;
 	return HRTIMER_RESTART;
 }
 
@@ -58,6 +67,7 @@
 	hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	stime->timer = t;
 	stime->hrt.function = snd_hrtimer_callback;
+	atomic_set(&stime->running, 0);
 	t->private_data = stime;
 	return 0;
 }
@@ -78,16 +88,18 @@
 {
 	struct snd_hrtimer *stime = t->private_data;
 
+	atomic_set(&stime->running, 0);
+	hrtimer_cancel(&stime->hrt);
 	hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
 		      HRTIMER_MODE_REL);
+	atomic_set(&stime->running, 1);
 	return 0;
 }
 
 static int snd_hrtimer_stop(struct snd_timer *t)
 {
 	struct snd_hrtimer *stime = t->private_data;
-
-	hrtimer_cancel(&stime->hrt);
+	atomic_set(&stime->running, 0);
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/sound/core/rawmidi.c
+++ linux-ec2-2.6.32/sound/core/rawmidi.c
@@ -530,13 +530,15 @@
 {
 	struct snd_rawmidi_file *rfile;
 	struct snd_rawmidi *rmidi;
+	struct module *module;
 
 	rfile = file->private_data;
 	rmidi = rfile->rmidi;
 	rawmidi_release_priv(rfile);
 	kfree(rfile);
+	module = rmidi->card->module;
 	snd_card_file_remove(rmidi->card, file);
-	module_put(rmidi->card->module);
+	module_put(module);
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/sound/core/init.c
+++ linux-ec2-2.6.32/sound/core/init.c
@@ -848,6 +848,7 @@
 		return -ENOMEM;
 	mfile->file = file;
 	mfile->disconnected_f_op = NULL;
+	INIT_LIST_HEAD(&mfile->shutdown_list);
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
@@ -883,6 +884,9 @@
 	list_for_each_entry(mfile, &card->files_list, list) {
 		if (mfile->file == file) {
 			list_del(&mfile->list);
+			spin_lock(&shutdown_lock);
+			list_del(&mfile->shutdown_list);
+			spin_unlock(&shutdown_lock);
 			if (mfile->disconnected_f_op)
 				fops_put(mfile->disconnected_f_op);
 			found = mfile;
--- linux-ec2-2.6.32.orig/sound/core/pcm_native.c
+++ linux-ec2-2.6.32/sound/core/pcm_native.c
@@ -314,10 +314,10 @@
 	if (!params->info)
 		params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
 	if (!params->fifo_size) {
-		if (snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) ==
-		    snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT]) &&
-                    snd_mask_min(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS]) ==
-                    snd_mask_max(&params->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) {
+		m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+		if (snd_mask_min(m) == snd_mask_max(m) &&
+                    snd_interval_min(i) == snd_interval_max(i)) {
 			changed = substream->ops->ioctl(substream,
 					SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
 			if (changed < 0)
@@ -972,6 +972,10 @@
 {
 	if (substream->runtime->trigger_master != substream)
 		return 0;
+	/* some drivers might use hw_ptr to recover from the pause -
+	   update the hw_ptr now */
+	if (push)
+		snd_pcm_update_hw_ptr(substream);
 	/* The jiffies check in snd_pcm_update_hw_ptr*() is done by
 	 * a delta betwen the current jiffies, this gives a large enough
 	 * delta, effectively to skip the check once.
--- linux-ec2-2.6.32.orig/sound/core/seq/oss/seq_oss_init.c
+++ linux-ec2-2.6.32/sound/core/seq/oss/seq_oss_init.c
@@ -280,13 +280,10 @@
 	return 0;
 
  _error:
-	snd_seq_oss_writeq_delete(dp->writeq);
-	snd_seq_oss_readq_delete(dp->readq);
 	snd_seq_oss_synth_cleanup(dp);
 	snd_seq_oss_midi_cleanup(dp);
-	delete_port(dp);
 	delete_seq_queue(dp->queue);
-	kfree(dp);
+	delete_port(dp);
 
 	return rc;
 }
@@ -349,8 +346,10 @@
 static int
 delete_port(struct seq_oss_devinfo *dp)
 {
-	if (dp->port < 0)
+	if (dp->port < 0) {
+		kfree(dp);
 		return 0;
+	}
 
 	debug_printk(("delete_port %i\n", dp->port));
 	return snd_seq_event_port_detach(dp->cseq, dp->port);
--- linux-ec2-2.6.32.orig/sound/synth/emux/emux_hwdep.c
+++ linux-ec2-2.6.32/sound/synth/emux/emux_hwdep.c
@@ -128,6 +128,9 @@
 	strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
 	hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
 	hw->ops.ioctl = snd_emux_hwdep_ioctl;
+	/* The ioctl parameter types are compatible between 32- and
+	 * 64-bit architectures, so use the same function. */
+	hw->ops.ioctl_compat = snd_emux_hwdep_ioctl;
 	hw->exclusive = 1;
 	hw->private_data = emu;
 	if ((err = snd_card_register(emu->card)) < 0)
--- linux-ec2-2.6.32.orig/sound/usb/usbquirks.h
+++ linux-ec2-2.6.32/sound/usb/usbquirks.h
@@ -2050,6 +2050,33 @@
 	}
 },
 
+/* Access Music devices */
+{
+	/* VirusTI Desktop */
+	USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815),
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = &(const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 3,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = &(const struct snd_usb_midi_endpoint_info) {
+					.out_cables = 0x0003,
+					.in_cables  = 0x0003
+				}
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 /* */
 {
 	/* aka. Serato Scratch Live DJ Box */
--- linux-ec2-2.6.32.orig/sound/usb/usbaudio.c
+++ linux-ec2-2.6.32/sound/usb/usbaudio.c
@@ -752,7 +752,7 @@
 			return 0; /* already large enough */
 		vfree(runtime->dma_area);
 	}
-	runtime->dma_area = vmalloc(size);
+	runtime->dma_area = vmalloc_user(size);
 	if (!runtime->dma_area)
 		return -ENOMEM;
 	runtime->dma_bytes = size;
@@ -1936,7 +1936,7 @@
 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
 	struct snd_usb_substream *subs = &as->substream[direction];
 
-	if (subs->interface >= 0) {
+	if (!as->chip->shutdown && subs->interface >= 0) {
 		usb_set_interface(subs->dev, subs->interface, 0);
 		subs->interface = -1;
 	}
@@ -3326,6 +3326,32 @@
 }
 
 /*
+ * This call will put the synth in "USB send" mode, i.e it will send MIDI
+ * messages through USB (this is disabled at startup). The synth will
+ * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB
+ * sign on its LCD. Values here are chosen based on sniffing USB traffic
+ * under Windows.
+ */
+static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
+{
+	int err, actual_length;
+
+	/* "midi send" enable */
+	static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
+
+	void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf,
+			ARRAY_SIZE(seq), &actual_length, 1000);
+	kfree(buf);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/*
  * Setup quirks
  */
 #define AUDIOPHILE_SET			0x01 /* if set, parse device_setup */
@@ -3616,6 +3642,12 @@
 			goto __err_val;
 	}
 
+	/* Access Music VirusTI Desktop */
+	if (id == USB_ID(0x133e, 0x0815)) {
+		if (snd_usb_accessmusic_boot_quirk(dev) < 0)
+			goto __err_val;
+	}
+
 	/*
 	 * found a config.  now register to ALSA
 	 */
--- linux-ec2-2.6.32.orig/sound/usb/usbmidi.c
+++ linux-ec2-2.6.32/sound/usb/usbmidi.c
@@ -931,6 +931,8 @@
 	DEFINE_WAIT(wait);
 	long timeout = msecs_to_jiffies(50);
 
+	if (ep->umidi->disconnected)
+		return;
 	/*
 	 * The substream buffer is empty, but some data might still be in the
 	 * currently active URBs, so we have to wait for those to complete.
@@ -1075,14 +1077,21 @@
  * Frees an output endpoint.
  * May be called when ep hasn't been initialized completely.
  */
-static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep)
 {
 	unsigned int i;
 
 	for (i = 0; i < OUTPUT_URBS; ++i)
-		if (ep->urbs[i].urb)
+		if (ep->urbs[i].urb) {
 			free_urb_and_buffer(ep->umidi, ep->urbs[i].urb,
 					    ep->max_transfer);
+			ep->urbs[i].urb = NULL;
+		}
+}
+
+static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep)
+{
+	snd_usbmidi_out_endpoint_clear(ep);
 	kfree(ep);
 }
 
@@ -1201,15 +1210,18 @@
 				usb_kill_urb(ep->out->urbs[j].urb);
 			if (umidi->usb_protocol_ops->finish_out_endpoint)
 				umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
+			ep->out->active_urbs = 0;
+			if (ep->out->drain_urbs) {
+				ep->out->drain_urbs = 0;
+				wake_up(&ep->out->drain_wait);
+			}
 		}
 		if (ep->in)
 			for (j = 0; j < INPUT_URBS; ++j)
 				usb_kill_urb(ep->in->urbs[j]);
 		/* free endpoints here; later call can result in Oops */
-		if (ep->out) {
-			snd_usbmidi_out_endpoint_delete(ep->out);
-			ep->out = NULL;
-		}
+		if (ep->out)
+			snd_usbmidi_out_endpoint_clear(ep->out);
 		if (ep->in) {
 			snd_usbmidi_in_endpoint_delete(ep->in);
 			ep->in = NULL;
@@ -1360,6 +1372,12 @@
 	EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
 	EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
 	EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
+	/* Access Music Virus TI */
+	EXTERNAL_PORT(0x133e, 0x0815, 0, "%s MIDI"),
+	PORT_INFO(0x133e, 0x0815, 1, "%s Synth", 0,
+		SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
+		SNDRV_SEQ_PORT_TYPE_HARDWARE |
+		SNDRV_SEQ_PORT_TYPE_SYNTHESIZER),
 };
 
 static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
--- linux-ec2-2.6.32.orig/sound/usb/caiaq/midi.c
+++ linux-ec2-2.6.32/sound/usb/caiaq/midi.c
@@ -135,7 +135,7 @@
 	if (ret < 0)
 		return ret;
 
-	strcpy(rmidi->name, device->product_name);
+	strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name));
 
 	rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = device;
--- linux-ec2-2.6.32.orig/sound/usb/caiaq/audio.c
+++ linux-ec2-2.6.32/sound/usb/caiaq/audio.c
@@ -639,7 +639,7 @@
 	}
 
 	dev->pcm->private_data = dev;
-	strcpy(dev->pcm->name, dev->product_name);
+	strlcpy(dev->pcm->name, dev->product_name, sizeof(dev->pcm->name));
 
 	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
 	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
--- linux-ec2-2.6.32.orig/sound/usb/usx2y/us122l.c
+++ linux-ec2-2.6.32/sound/usb/usx2y/us122l.c
@@ -234,29 +234,26 @@
 					  struct file *file, poll_table *wait)
 {
 	struct us122l	*us122l = hw->private_data;
-	struct usb_stream *s = us122l->sk.s;
 	unsigned	*polled;
 	unsigned int	mask;
 
 	poll_wait(file, &us122l->sk.sleep, wait);
 
-	switch (s->state) {
-	case usb_stream_ready:
-		if (us122l->first == file)
-			polled = &s->periods_polled;
-		else
-			polled = &us122l->second_periods_polled;
-		if (*polled != s->periods_done) {
-			*polled = s->periods_done;
-			mask = POLLIN | POLLOUT | POLLWRNORM;
-			break;
+	mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR;
+	if (mutex_trylock(&us122l->mutex)) {
+		struct usb_stream *s = us122l->sk.s;
+		if (s && s->state == usb_stream_ready) {
+			if (us122l->first == file)
+				polled = &s->periods_polled;
+			else
+				polled = &us122l->second_periods_polled;
+			if (*polled != s->periods_done) {
+				*polled = s->periods_done;
+				mask = POLLIN | POLLOUT | POLLWRNORM;
+			} else
+				mask = 0;
 		}
-		/* Fall through */
-		mask = 0;
-		break;
-	default:
-		mask = POLLIN | POLLOUT | POLLWRNORM | POLLERR;
-		break;
+		mutex_unlock(&us122l->mutex);
 	}
 	return mask;
 }
@@ -342,6 +339,7 @@
 {
 	struct usb_stream_config *cfg;
 	struct us122l *us122l = hw->private_data;
+	struct usb_stream *s;
 	unsigned min_period_frames;
 	int err = 0;
 	bool high_speed;
@@ -387,18 +385,18 @@
 	snd_power_wait(hw->card, SNDRV_CTL_POWER_D0);
 
 	mutex_lock(&us122l->mutex);
+	s = us122l->sk.s;
 	if (!us122l->master)
 		us122l->master = file;
 	else if (us122l->master != file) {
-		if (memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg))) {
+		if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg))) {
 			err = -EIO;
 			goto unlock;
 		}
 		us122l->slave = file;
 	}
-	if (!us122l->sk.s ||
-	    memcmp(cfg, &us122l->sk.s->cfg, sizeof(*cfg)) ||
-	    us122l->sk.s->state == usb_stream_xrun) {
+	if (!s || memcmp(cfg, &s->cfg, sizeof(*cfg)) ||
+	    s->state == usb_stream_xrun) {
 		us122l_stop(us122l);
 		if (!us122l_start(us122l, cfg->sample_rate, cfg->period_frames))
 			err = -EIO;
@@ -409,6 +407,7 @@
 	mutex_unlock(&us122l->mutex);
 free:
 	kfree(cfg);
+	wake_up_all(&us122l->sk.sleep);
 	return err;
 }
 
--- linux-ec2-2.6.32.orig/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ linux-ec2-2.6.32/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -51,7 +51,7 @@
 			return 0; /* already enough large */
 		vfree(runtime->dma_area);
 	}
-	runtime->dma_area = vmalloc_32(size);
+	runtime->dma_area = vmalloc_32_user(size);
 	if (! runtime->dma_area)
 		return -ENOMEM;
 	runtime->dma_bytes = size;
--- linux-ec2-2.6.32.orig/sound/oss/midi_synth.h
+++ linux-ec2-2.6.32/sound/oss/midi_synth.h
@@ -8,7 +8,7 @@
 void midi_synth_close (int dev);
 void midi_synth_hw_control (int dev, unsigned char *event);
 int midi_synth_load_patch (int dev, int format, const char __user * addr,
-		 int offs, int count, int pmgr_flag);
+		 int count, int pmgr_flag);
 void midi_synth_panning (int dev, int channel, int pressure);
 void midi_synth_aftertouch (int dev, int channel, int pressure);
 void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
--- linux-ec2-2.6.32.orig/sound/oss/sb_mixer.c
+++ linux-ec2-2.6.32/sound/oss/sb_mixer.c
@@ -230,7 +230,7 @@
 	return 1;
 }
 
-static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
+static void __change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
 {
 	unsigned char mask;
 	int shift;
@@ -282,7 +282,7 @@
 		return -EINVAL;
 
 	val = sb_getmixer(devc, regoffs);
-	change_bits(devc, &val, dev, LEFT_CHN, left);
+	__change_bits(devc, &val, dev, LEFT_CHN, left);
 
 	if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)	/*
 								 * Change register
@@ -302,7 +302,7 @@
 							 * Read the new one
 							 */
 	}
-	change_bits(devc, &val, dev, RIGHT_CHN, right);
+	__change_bits(devc, &val, dev, RIGHT_CHN, right);
 
 	sb_setmixer(devc, regoffs, val);
 
--- linux-ec2-2.6.32.orig/sound/oss/ad1848.c
+++ linux-ec2-2.6.32/sound/oss/ad1848.c
@@ -457,7 +457,7 @@
 	return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval,
+static void __change_bits(ad1848_info * devc, unsigned char *regval,
 			unsigned char *muteval, int dev, int chn, int newval)
 {
 	unsigned char mask;
@@ -515,10 +515,10 @@
 
 	if (muteregoffs != regoffs) {
 		muteval = ad_read(devc, muteregoffs);
-		change_bits(devc, &val, &muteval, dev, channel, value);
+		__change_bits(devc, &val, &muteval, dev, channel, value);
 	}
 	else
-		change_bits(devc, &val, &val, dev, channel, value);
+		__change_bits(devc, &val, &val, dev, channel, value);
 
 	spin_lock_irqsave(&devc->lock,flags);
 	ad_write(devc, regoffs, val);
--- linux-ec2-2.6.32.orig/sound/oss/opl3.c
+++ linux-ec2-2.6.32/sound/oss/opl3.c
@@ -819,7 +819,7 @@
 }
 
 static int opl3_load_patch(int dev, int format, const char __user *addr,
-		int offs, int count, int pmgr_flag)
+		int count, int pmgr_flag)
 {
 	struct sbi_instrument ins;
 
@@ -829,11 +829,7 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * What the fuck is going on here?  We leave junk in the beginning
-	 * of ins and then check the field pretty close to that beginning?
-	 */
-	if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs))
+	if (copy_from_user(&ins, addr, sizeof(ins)))
 		return -EFAULT;
 
 	if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
@@ -848,6 +844,10 @@
 
 static void opl3_panning(int dev, int voice, int value)
 {
+
+	if (voice < 0 || voice >= devc->nr_voice)
+		return;
+
 	devc->voc[voice].panning = value;
 }
 
@@ -1065,8 +1065,15 @@
 
 static void opl3_setup_voice(int dev, int voice, int chn)
 {
-	struct channel_info *info =
-	&synth_devs[dev]->chn_info[chn];
+	struct channel_info *info;
+
+	if (voice < 0 || voice >= devc->nr_voice)
+		return;
+
+	if (chn < 0 || chn > 15)
+		return;
+
+	info = &synth_devs[dev]->chn_info[chn];
 
 	opl3_set_instr(dev, voice, info->pgm_num);
 
--- linux-ec2-2.6.32.orig/sound/oss/dev_table.h
+++ linux-ec2-2.6.32/sound/oss/dev_table.h
@@ -271,7 +271,7 @@
 	void (*reset) (int dev);
 	void (*hw_control) (int dev, unsigned char *event);
 	int (*load_patch) (int dev, int format, const char __user *addr,
-	     int offs, int count, int pmgr_flag);
+	     int count, int pmgr_flag);
 	void (*aftertouch) (int dev, int voice, int pressure);
 	void (*controller) (int dev, int voice, int ctrl_num, int value);
 	void (*panning) (int dev, int voice, int value);
--- linux-ec2-2.6.32.orig/sound/oss/soundcard.c
+++ linux-ec2-2.6.32/sound/oss/soundcard.c
@@ -87,7 +87,7 @@
 	int             i, n;
 
 	for (i = 0; i < num_mixer_volumes; i++) {
-		if (strcmp(name, mixer_vols[i].name) == 0) {
+		if (strncmp(name, mixer_vols[i].name, 32) == 0) {
 			if (present)
 				mixer_vols[i].num = i;
 			return mixer_vols[i].levels;
@@ -99,7 +99,7 @@
 	}
 	n = num_mixer_volumes++;
 
-	strcpy(mixer_vols[n].name, name);
+	strncpy(mixer_vols[n].name, name, 32);
 
 	if (present)
 		mixer_vols[n].num = n;
--- linux-ec2-2.6.32.orig/sound/oss/midi_synth.c
+++ linux-ec2-2.6.32/sound/oss/midi_synth.c
@@ -476,7 +476,7 @@
 
 int
 midi_synth_load_patch(int dev, int format, const char __user *addr,
-		      int offs, int count, int pmgr_flag)
+		      int count, int pmgr_flag)
 {
 	int             orig_dev = synth_devs[dev]->midi_dev;
 
@@ -491,39 +491,37 @@
 	if (!prefix_cmd(orig_dev, 0xf0))
 		return 0;
 
+	/* Invalid patch format */
 	if (format != SYSEX_PATCH)
-	{
-/*		  printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
 		  return -EINVAL;
-	}
+
+	/* Patch header too short */
 	if (count < hdr_size)
-	{
-/*		printk("MIDI Error: Patch header too short\n");*/
 		return -EINVAL;
-	}
+
 	count -= hdr_size;
 
 	/*
-	 * Copy the header from user space but ignore the first bytes which have
-	 * been transferred already.
+	 * Copy the header from user space
 	 */
 
-	if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
+	if (copy_from_user(&sysex, addr, hdr_size))
 		return -EFAULT;
- 
- 	if (count < sysex.len)
-	{
-/*		printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
+
+	/* Sysex record too short */
+	if ((unsigned)count < (unsigned)sysex.len)
 		sysex.len = count;
-	}
-  	left = sysex.len;
-  	src_offs = 0;
+
+	left = sysex.len;
+	src_offs = 0;
 
 	for (i = 0; i < left && !signal_pending(current); i++)
 	{
 		unsigned char   data;
 
-		get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i]));
+		if (get_user(data,
+		    (unsigned char __user *)(addr + hdr_size + i)))
+			return -EFAULT;
 
 		eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
--- linux-ec2-2.6.32.orig/sound/oss/sequencer.c
+++ linux-ec2-2.6.32/sound/oss/sequencer.c
@@ -241,7 +241,7 @@
 				return -ENXIO;
 
 			fmt = (*(short *) &event_rec[0]) & 0xffff;
-			err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0);
+			err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0);
 			if (err < 0)
 				return err;
 
--- linux-ec2-2.6.32.orig/sound/ppc/tumbler.c
+++ linux-ec2-2.6.32/sound/ppc/tumbler.c
@@ -30,6 +30,7 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -46,6 +47,8 @@
 #define DBG(fmt...)
 #endif
 
+#define IS_G4DA (machine_is_compatible("PowerMac3,4"))
+
 /* i2c address for tumbler */
 #define TAS_I2C_ADDR	0x34
 
@@ -1134,7 +1137,8 @@
 		gp->inactive_val = (*base) ? 0x4 : 0x5;
 	} else {
 		const u32 *prop = NULL;
-		gp->active_state = 0;
+		gp->active_state = IS_G4DA
+				&& !strncmp(device, "keywest-gpio1", 13);
 		gp->active_val = 0x4;
 		gp->inactive_val = 0x5;
 		/* Here are some crude hacks to extract the GPIO polarity and
@@ -1312,6 +1316,9 @@
  	if (irq <= NO_IRQ)
 		irq = tumbler_find_device("line-output-detect",
 					  NULL, &mix->line_detect, 1);
+	if (IS_G4DA && irq <= NO_IRQ)
+		irq = tumbler_find_device("keywest-gpio16",
+					  NULL, &mix->line_detect, 1);
 	mix->lineout_irq = irq;
 
 	tumbler_reset_audio(chip);
--- linux-ec2-2.6.32.orig/security/security.c
+++ linux-ec2-2.6.32/security/security.c
@@ -18,7 +18,8 @@
 #include <linux/security.h>
 
 /* Boot-time LSM user choice */
-static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
+static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
+	CONFIG_DEFAULT_SECURITY;
 
 /* things that live in capability.c */
 extern struct security_operations default_security_ops;
@@ -79,8 +80,10 @@
  *
  * Return true if:
  *	-The passed LSM is the one chosen by user at boot time,
- *	-or user didn't specify a specific LSM and we're the first to ask
- *	 for registration permission,
+ *	-or the passed LSM is configured as the default and the user did not
+ *	 choose an alternate LSM at boot time,
+ *	-or there is no default LSM set and the user didn't specify a
+ *	 specific LSM and we're the first to ask for registration permission,
  *	-or the passed LSM is currently loaded.
  * Otherwise, return false.
  */
@@ -199,9 +202,9 @@
 	return security_ops->quota_on(dentry);
 }
 
-int security_syslog(int type)
+int security_syslog(int type, bool from_file)
 {
-	return security_ops->syslog(type);
+	return security_ops->syslog(type, from_file);
 }
 
 int security_settime(struct timespec *ts, struct timezone *tz)
@@ -386,6 +389,7 @@
 		return 0;
 	return security_ops->path_mkdir(path, dentry, mode);
 }
+EXPORT_SYMBOL(security_path_mkdir);
 
 int security_path_rmdir(struct path *path, struct dentry *dentry)
 {
@@ -393,6 +397,7 @@
 		return 0;
 	return security_ops->path_rmdir(path, dentry);
 }
+EXPORT_SYMBOL(security_path_rmdir);
 
 int security_path_unlink(struct path *path, struct dentry *dentry)
 {
@@ -400,6 +405,7 @@
 		return 0;
 	return security_ops->path_unlink(path, dentry);
 }
+EXPORT_SYMBOL(security_path_unlink);
 
 int security_path_symlink(struct path *path, struct dentry *dentry,
 			  const char *old_name)
@@ -408,6 +414,7 @@
 		return 0;
 	return security_ops->path_symlink(path, dentry, old_name);
 }
+EXPORT_SYMBOL(security_path_symlink);
 
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
 		       struct dentry *new_dentry)
@@ -416,6 +423,7 @@
 		return 0;
 	return security_ops->path_link(old_dentry, new_dir, new_dentry);
 }
+EXPORT_SYMBOL(security_path_link);
 
 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
 			 struct path *new_dir, struct dentry *new_dentry)
@@ -426,6 +434,7 @@
 	return security_ops->path_rename(old_dir, old_dentry, new_dir,
 					 new_dentry);
 }
+EXPORT_SYMBOL(security_path_rename);
 
 int security_path_truncate(struct path *path, loff_t length,
 			   unsigned int time_attrs)
@@ -434,6 +443,27 @@
 		return 0;
 	return security_ops->path_truncate(path, length, time_attrs);
 }
+
+int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+			mode_t mode)
+{
+	if (unlikely(IS_PRIVATE(dentry->d_inode)))
+		return 0;
+	return security_ops->path_chmod(dentry, mnt, mode);
+}
+
+int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+		return 0;
+	return security_ops->path_chown(path, uid, gid);
+}
+
+int security_path_chroot(struct path *path)
+{
+	return security_ops->path_chroot(path);
+}
+EXPORT_SYMBOL(security_path_truncate);
 #endif
 
 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
@@ -505,6 +535,7 @@
 		return 0;
 	return security_ops->inode_readlink(dentry);
 }
+EXPORT_SYMBOL(security_inode_readlink);
 
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
@@ -519,6 +550,7 @@
 		return 0;
 	return security_ops->inode_permission(inode, mask);
 }
+EXPORT_SYMBOL(security_inode_permission);
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
@@ -619,6 +651,7 @@
 {
 	return security_ops->file_permission(file, mask);
 }
+EXPORT_SYMBOL(security_file_permission);
 
 int security_file_alloc(struct file *file)
 {
--- linux-ec2-2.6.32.orig/security/device_cgroup.c
+++ linux-ec2-2.6.32/security/device_cgroup.c
@@ -514,6 +514,7 @@
 
 	return -EPERM;
 }
+EXPORT_SYMBOL(devcgroup_inode_permission);
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
--- linux-ec2-2.6.32.orig/security/commoncap.c
+++ linux-ec2-2.6.32/security/commoncap.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/prctl.h>
 #include <linux/securebits.h>
+#include <linux/syslog.h>
 
 /*
  * If a non-root user executes a setuid-root binary in
@@ -956,12 +957,16 @@
 /**
  * cap_syslog - Determine whether syslog function is permitted
  * @type: Function requested
+ * @from_file: Whether this request came from an open file (i.e. /proc)
  *
  * Determine whether the current process is permitted to use a particular
  * syslog function, returning 0 if permission is granted, -ve if not.
  */
-int cap_syslog(int type)
+int cap_syslog(int type, bool from_file)
 {
+	/* /proc/kmsg can open be opened by CAP_SYS_ADMIN */
+	if (type != 1 && from_file)
+		return 0;
 	if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	return 0;
--- linux-ec2-2.6.32.orig/security/Makefile
+++ linux-ec2-2.6.32/security/Makefile
@@ -6,9 +6,11 @@
 subdir-$(CONFIG_SECURITY_SELINUX)	+= selinux
 subdir-$(CONFIG_SECURITY_SMACK)		+= smack
 subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
+subdir-$(CONFIG_SECURITY_APPARMOR)	+= apparmor
 
 # always enable default capabilities
-obj-y		+= commoncap.o min_addr.o
+obj-y					+= commoncap.o
+obj-$(CONFIG_MMU)			+= min_addr.o
 
 # Object file lists
 obj-$(CONFIG_SECURITY)			+= security.o capability.o
@@ -18,6 +20,7 @@
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
 obj-$(CONFIG_AUDIT)			+= lsm_audit.o
 obj-$(CONFIG_SECURITY_TOMOYO)		+= tomoyo/built-in.o
+obj-$(CONFIG_SECURITY_APPARMOR)		+= apparmor/built-in.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
 
--- linux-ec2-2.6.32.orig/security/Kconfig
+++ linux-ec2-2.6.32/security/Kconfig
@@ -162,8 +162,46 @@
 source security/selinux/Kconfig
 source security/smack/Kconfig
 source security/tomoyo/Kconfig
+source security/apparmor/Kconfig
 
 source security/integrity/ima/Kconfig
 
+choice
+	prompt "Default security module"
+	default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
+	default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
+	default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
+	default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
+	default DEFAULT_SECURITY_DAC
+
+	help
+	  Select the security module that will be used by default if the
+	  kernel parameter security= is not specified.
+
+	config DEFAULT_SECURITY_SELINUX
+		bool "SELinux" if SECURITY_SELINUX=y
+
+	config DEFAULT_SECURITY_SMACK
+		bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y
+
+	config DEFAULT_SECURITY_TOMOYO
+		bool "TOMOYO" if SECURITY_TOMOYO=y
+
+	config DEFAULT_SECURITY_APPARMOR
+		bool "AppArmor" if SECURITY_APPARMOR=y
+
+	config DEFAULT_SECURITY_DAC
+		bool "Unix Discretionary Access Controls"
+
+endchoice
+
+config DEFAULT_SECURITY
+	string
+	default "selinux" if DEFAULT_SECURITY_SELINUX
+	default "smack" if DEFAULT_SECURITY_SMACK
+	default "tomoyo" if DEFAULT_SECURITY_TOMOYO
+	default "apparmor" if DEFAULT_SECURITY_APPARMOR
+	default "" if DEFAULT_SECURITY_DAC
+
 endmenu
 
--- linux-ec2-2.6.32.orig/security/capability.c
+++ linux-ec2-2.6.32/security/capability.c
@@ -308,6 +308,22 @@
 {
 	return 0;
 }
+
+static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+			  mode_t mode)
+{
+	return 0;
+}
+
+static int cap_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+	return 0;
+}
+
+static int cap_path_chroot(struct path *root)
+{
+	return 0;
+}
 #endif
 
 static int cap_file_permission(struct file *file, int mask)
@@ -977,6 +993,9 @@
 	set_to_cap_if_null(ops, path_link);
 	set_to_cap_if_null(ops, path_rename);
 	set_to_cap_if_null(ops, path_truncate);
+	set_to_cap_if_null(ops, path_chmod);
+	set_to_cap_if_null(ops, path_chown);
+	set_to_cap_if_null(ops, path_chroot);
 #endif
 	set_to_cap_if_null(ops, file_permission);
 	set_to_cap_if_null(ops, file_alloc_security);
--- linux-ec2-2.6.32.orig/security/inode.c
+++ linux-ec2-2.6.32/security/inode.c
@@ -168,13 +168,13 @@
 
 	mutex_lock(&parent->d_inode->i_mutex);
 	*dentry = lookup_one_len(name, parent, strlen(name));
-	if (!IS_ERR(dentry)) {
+	if (!IS_ERR(*dentry)) {
 		if ((mode & S_IFMT) == S_IFDIR)
 			error = mkdir(parent->d_inode, *dentry, mode);
 		else
 			error = create(parent->d_inode, *dentry, mode);
 	} else
-		error = PTR_ERR(dentry);
+		error = PTR_ERR(*dentry);
 	mutex_unlock(&parent->d_inode->i_mutex);
 
 	return error;
--- linux-ec2-2.6.32.orig/security/min_addr.c
+++ linux-ec2-2.6.32/security/min_addr.c
@@ -33,6 +33,9 @@
 {
 	int ret;
 
+	if (write && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
 	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 
 	update_mmap_min_addr();
--- linux-ec2-2.6.32.orig/security/apparmor/Makefile
+++ linux-ec2-2.6.32/security/apparmor/Makefile
@@ -0,0 +1,24 @@
+# Makefile for AppArmor Linux Security Module
+#
+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
+
+apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
+              path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
+              resource.o sid.o file.o net.o
+
+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
+
+clean-files: capability_names.h af_names.h
+
+quiet_cmd_make-caps = GEN     $@
+cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
+
+quiet_cmd_make-af = GEN     $@
+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
+
+$(obj)/capability.o : $(obj)/capability_names.h
+$(obj)/net.o : $(obj)/af_names.h
+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
+	$(call cmd,make-caps)
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
+	$(call cmd,make-af)
--- linux-ec2-2.6.32.orig/security/apparmor/ipc.c
+++ linux-ec2-2.6.32/security/apparmor/ipc.c
@@ -0,0 +1,124 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor ipc mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/gfp.h>
+#include <linux/ptrace.h>
+
+#include "include/audit.h"
+#include "include/capability.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+struct aa_audit_ptrace {
+	struct aa_audit base;
+
+	pid_t tracer, tracee;
+};
+
+/* call back to audit ptrace fields */
+static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_ptrace *sa = container_of(va, struct aa_audit_ptrace,
+						  base);
+	audit_log_format(ab, " tracer=%d tracee=%d", sa->tracer, sa->tracee);
+}
+
+/**
+ * aa_audit_ptrace - do auditing for ptrace
+ * @profile: profile being enforced  (NOT NULL)
+ * @sa: audit structure  (NOT NULL)
+ *
+ * Returns: %0 or error code
+ */
+static int aa_audit_ptrace(struct aa_profile *profile,
+			   struct aa_audit_ptrace *sa)
+{
+	return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa->base, audit_cb);
+}
+
+/**
+ * aa_may_ptrace - test if tracer task can trace the tracee
+ * @tracer_task: task who will do the tracing  (NOT NULL)
+ * @tracer: profile of the task doing the tracing  (NOT NULL)
+ * @tracee: task to be traced
+ * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
+ *
+ * Returns: %0 else error code if permission denied or error
+ */
+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
+		  struct aa_profile *tracee, unsigned int mode)
+{
+	/* TODO: currently only based on capability, not extended ptrace
+	 *       rules,
+	 *       Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
+	 */
+
+	if (!tracer || tracer == tracee)
+		return 0;
+	/* log this capability request */
+	return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
+}
+
+/**
+ * aa_ptrace - do ptrace permission check and auditing
+ * @tracer: task doing the tracing
+ * @tracee: task being traced
+ * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
+ *
+ * Returns: %0 else error code if permission denied or error
+ */
+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
+	      unsigned int mode)
+{
+	/*
+	 * tracer can ptrace tracee when
+	 * - tracer is unconfined ||
+	 * - tracer & tracee are in the same namespace &&
+	 *   - tracer is in complain mode
+	 *   - tracer has rules allowing it to trace tracee currently this is:
+	 *       - confined by the same profile ||
+	 *       - tracer profile has CAP_SYS_PTRACE
+	 */
+
+	struct aa_profile *tracer_p;
+	/* cred released below */
+	const struct cred *cred = get_task_cred(tracer);
+	int error = 0;
+	tracer_p = aa_cred_profile(cred);
+
+	if (!unconfined(tracer_p)) {
+		struct aa_audit_ptrace sa = {
+			.base.operation = "ptrace",
+			.base.gfp_mask = GFP_ATOMIC,
+			.tracer = tracer->pid,
+			.tracee = tracee->pid,
+		};
+		/* FIXME: different namespace restriction can be lifted
+		 * if, namespace are matched to AppArmor namespaces
+		 */
+		struct aa_profile *tracee_p;
+		/* lcred released below */
+		struct cred *lcred = get_task_cred(tracee);
+		tracee_p = aa_cred_profile(lcred);
+
+		sa.base.error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
+		sa.base.error = aa_audit_ptrace(tracer_p, &sa);
+
+		put_cred(lcred);
+		error = sa.base.error;
+	}
+	put_cred(cred);
+
+	return error;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/match.c
+++ linux-ec2-2.6.32/security/apparmor/match.c
@@ -0,0 +1,391 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor dfa based regular expression matching engine
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/err.h>
+#include <linux/kref.h>
+
+#include "include/match.h"
+
+/**
+ * do_vfree - workqueue routine for freeing vmalloced memory
+ * @work: data to be freed
+ *
+ * The work_struct is overlayed to the data being freed, as at the point
+ * the work is scheduled the data is no longer valid, be its freeing
+ * needs to be delayed until safe.
+ */
+static void do_vfree(struct work_struct *work)
+{
+	vfree(work);
+}
+
+/**
+ * free_table - free a table allocated by unpack table
+ * @table: table to unpack  (MAYBE NULL)
+ */
+static void free_table(struct table_header *table)
+{
+	if (!table)
+		return;
+
+	if (is_vmalloc_addr(table)) {
+		/* Data is no longer valid so just use the allocated space
+		 * as the work_struct
+		 */
+		struct work_struct *work = (struct work_struct *) table;
+		INIT_WORK(work, do_vfree);
+		schedule_work(work);	  
+	} else
+		kzfree(table);
+}
+
+/**
+ * unpack_table - unpack a dfa table (one of accept, default, base, next check)
+ * @blob: data to unpack
+ * @bsize: size of blob
+ *
+ * Returns: pointer to table else NULL on failure
+ *
+ * NOTE: must be freed by free_table (not kmalloc)
+ */
+static struct table_header *unpack_table(char *blob, size_t bsize)
+{
+	struct table_header *table = NULL;
+	struct table_header th;
+	int unmap_alias = 0;
+	size_t tsize;
+
+	if (bsize < sizeof(struct table_header))
+		goto out;
+
+	/* loaded td_id's start at 1, subtract 1 now to avoid doing
+	 * it every time we use td_id as an index
+	 */
+	th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
+	th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
+	th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
+	blob += sizeof(struct table_header);
+
+	if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
+	      th.td_flags == YYTD_DATA8))
+		goto out;
+
+	tsize = table_size(th.td_lolen, th.td_flags);
+	if (bsize < tsize)
+		goto out;
+
+	/* freed by free_table */
+	table = kmalloc(tsize, GFP_KERNEL | __GFP_NOWARN);
+	if (!table) {
+		tsize = tsize < sizeof(struct work_struct) ?
+			sizeof(struct work_struct) : tsize;
+		unmap_alias = 1;
+		table = vmalloc(tsize);
+	}
+	if (table) {
+		*table = th;
+		if (th.td_flags == YYTD_DATA8)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u8, byte_to_byte);
+		else if (th.td_flags == YYTD_DATA16)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u16, be16_to_cpu);
+		else if (th.td_flags == YYTD_DATA32)
+			UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
+				     u32, be32_to_cpu);
+		else
+			goto fail;
+	}
+
+out:
+	if (unmap_alias)
+		vm_unmap_aliases();
+	return table;
+fail:
+	free_table(table);
+	return NULL;
+}
+
+/**
+ * verify_dfa - verify that all the transitions and states in the dfa tables
+ *              are in bounds.
+ * @dfa: dfa to test  (NOT NULL)
+ * @flags: flags controlling what type of accept table are acceptable
+ *
+ * Assumes dfa has gone through the first pass verification done by unpacking
+ * NOTE: this does not valid accept table values
+ *
+ * Returns: %0 else error code on failure to verify
+ */
+static int verify_dfa(struct aa_dfa *dfa, int flags)
+{
+	size_t i, state_count, trans_count;
+	int error = -EPROTO;
+
+	/* check that required tables exist */
+	if (!(dfa->tables[YYTD_ID_DEF] &&
+	      dfa->tables[YYTD_ID_BASE] &&
+	      dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
+		goto out;
+
+	/* accept.size == default.size == base.size */
+	state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
+	if (ACCEPT1_FLAGS(flags)) {
+		if (!dfa->tables[YYTD_ID_ACCEPT])
+			goto out;
+		if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen)
+			goto out;
+	}
+	if (ACCEPT2_FLAGS(flags)) {
+		if (!dfa->tables[YYTD_ID_ACCEPT2])
+			goto out;
+		if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen)
+			goto out;
+	}
+	if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen)
+		goto out;
+
+	/* next.size == chk.size */
+	trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
+	if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen)
+		goto out;
+
+	/* if equivalence classes then its table size must be 256 */
+	if (dfa->tables[YYTD_ID_EC] &&
+	    dfa->tables[YYTD_ID_EC]->td_lolen != 256)
+		goto out;
+
+	if (flags & DFA_FLAG_VERIFY_STATES) {
+		for (i = 0; i < state_count; i++) {
+			if (DEFAULT_TABLE(dfa)[i] >= state_count)
+				goto out;
+			/* TODO: do check that DEF state recursion terminates */
+			if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
+				printk("AppArmor DFA next/check upper bounds error\n");
+				goto out;
+			}
+		}
+
+		for (i = 0; i < trans_count; i++) {
+			if (NEXT_TABLE(dfa)[i] >= state_count)
+				goto out;
+			if (CHECK_TABLE(dfa)[i] >= state_count)
+				goto out;
+		}
+	}
+
+	error = 0;
+out:
+	return error;
+}
+
+/**
+ * aa_dfa_free - free a dfa allocated by aa_dfa_unpack
+ * @dfa: the dfa to free  (MAYBE NULL)
+ *
+ * Requires: reference count to dfa == 0
+ */
+static void aa_dfa_free(struct aa_dfa *dfa)
+{
+	if (dfa) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
+			free_table(dfa->tables[i]);
+			dfa->tables[i] = NULL;
+		}
+	}
+	kfree(dfa);
+}
+
+/**
+ * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
+ * @kr: kref callback for freeing of a dfa  (NOT NULL)
+ */
+void aa_dfa_free_kref(struct kref *kref)
+{
+	struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
+	aa_dfa_free(dfa);
+}
+
+/**
+ * aa_dfa_unpack - unpack the binary tables of a serialized dfa
+ * @blob: aligned serialized stream of data to unpack  (NOT NULL)
+ * @size: size of data to unpack
+ * @flags: flags controlling what type of accept tables are acceptable
+ *
+ * Unpack a dfa that has been serialized.  Dfa format and information in
+ * Documentation/AppArmor/dfa.txt
+ * Assumes the dfa @blob stream has been aligned on a 8 byte boundry
+ *
+ * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
+ */
+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
+{
+	int hsize;
+	int error = -ENOMEM;
+	char *data = blob;
+	struct table_header *table = NULL;
+	struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
+	if (!dfa)
+		goto fail;
+
+	kref_init(&dfa->count);
+
+	error = -EPROTO;
+
+	/* get dfa table set header */
+	if (size < sizeof(struct table_set_header))
+		goto fail;
+
+	if (ntohl(*(u32 *) data) != YYTH_MAGIC)
+		goto fail;
+
+	hsize = ntohl(*(u32 *) (data + 4));
+	if (size < hsize)
+		goto fail;
+
+	dfa->flags = ntohs(*(u16 *) (data + 12));
+	data += hsize;
+	size -= hsize;
+
+	while (size > 0) {
+		table = unpack_table(data, size);
+		if (!table)
+			goto fail;
+
+		switch (table->td_id) {
+		case YYTD_ID_ACCEPT:
+			if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
+				goto fail;
+			break;
+		case YYTD_ID_ACCEPT2:
+			if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
+				goto fail;
+			break;
+		case YYTD_ID_BASE:
+			if (table->td_flags != YYTD_DATA32)
+				goto fail;
+			break;
+		case YYTD_ID_DEF:
+		case YYTD_ID_NXT:
+		case YYTD_ID_CHK:
+			if (table->td_flags != YYTD_DATA16)
+				goto fail;
+			break;
+		case YYTD_ID_EC:
+			if (table->td_flags != YYTD_DATA8)
+				goto fail;
+			break;
+		default:
+			goto fail;
+		}
+		/* check for duplicate table entry */
+		if (dfa->tables[table->td_id])
+			goto fail;
+		dfa->tables[table->td_id] = table;
+		data += table_size(table->td_lolen, table->td_flags);
+		size -= table_size(table->td_lolen, table->td_flags);
+		table = NULL;
+	}
+
+	error = verify_dfa(dfa, flags);
+	if (error)
+		goto fail;
+
+	return dfa;
+
+fail:
+	free_table(table);
+	aa_dfa_free(dfa);
+	return ERR_PTR(error);
+}
+
+/**
+ * aa_dfa_match_len - traverse @dfa to find state @str stops at
+ * @dfa: the dfa to match @str against  (NOT NULL)
+ * @start: the state of the dfa to start matching in
+ * @str: the string of bytes to match against the dfa  (NOT NULL)
+ * @len: length of the string of bytes to match
+ *
+ * aa_dfa_match_len will match @str against the dfa and return the state it
+ * finished matching in. The final state can be used to look up the accepting
+ * label, or as the start state of a continuing match.
+ *
+ * This function will happily match again the 0 byte and only finishes
+ * when @len input is consumed.
+ *
+ * Returns: final state reached after input is consumed
+ */
+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
+			      const char *str, int len)
+{
+	u16 *def = DEFAULT_TABLE(dfa);
+	u32 *base = BASE_TABLE(dfa);
+	u16 *next = NEXT_TABLE(dfa);
+	u16 *check = CHECK_TABLE(dfa);
+	unsigned int state = start, pos;
+
+	if (state == 0)
+		return 0;
+
+	/* current state is <state>, matching character *str */
+	if (dfa->tables[YYTD_ID_EC]) {
+		/* Equivalence class table defined */
+		u8 *equiv = EQUIV_TABLE(dfa);
+		/* default is direct to next state */
+		for (; len; len--) {
+			pos = base[state] + equiv[(u8) *str++];
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	} else {
+		/* default is direct to next state */
+		for (; len; len--) {
+			pos = base[state] + (u8) *str++;
+			if (check[pos] == state)
+				state = next[pos];
+			else
+				state = def[state];
+		}
+	}
+
+	return state;
+}
+
+/**
+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
+ * @dfa: the dfa to match @str against  (NOT NULL)
+ * @start: the state of the dfa to start matching in
+ * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
+ *
+ * aa_dfa_next_state will match @str against the dfa and return the state it
+ * finished matching in. The final state can be used to look up the accepting
+ * label, or as the start state of a continuing match.
+ *
+ * Returns: final state reached after input is consumed
+ */
+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
+			  const char *str)
+{
+	return aa_dfa_match_len(dfa, start, str, strlen(str));
+}
--- linux-ec2-2.6.32.orig/security/apparmor/audit.c
+++ linux-ec2-2.6.32/security/apparmor/audit.c
@@ -0,0 +1,162 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor auditing functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/audit.h>
+#include <linux/socket.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/policy.h"
+
+const char *audit_mode_names[] = {
+	"normal",
+	"quiet_denied",
+	"quiet",
+	"noquiet",
+	"all"
+};
+
+static char *aa_audit_type[] = {
+	"APPARMOR_AUDIT",
+	"APPARMOR_ALLOWED",
+	"APPARMOR_DENIED",
+	"APPARMOR_HINT",
+	"APPARMOR_STATUS",
+	"APPARMOR_ERROR",
+	"APPARMOR_KILLED"
+};
+
+/*
+ * Currently AppArmor auditing is fed straight into the audit framework.
+ *
+ * TODO:
+ * convert to LSM audit
+ * netlink interface for complain mode
+ * user auditing, - send user auditing to netlink interface
+ * system control of whether user audit messages go to system log
+ */
+
+/**
+ * aa_audit_base - core AppArmor function.
+ * @type: type of audit message (see include/linux/apparmor.h)
+ * @profile: active profile for event (MAY BE NULL)
+ * @sa: audit structure containing data to audit
+ * @audit_cxt: audit_cxt that event is under
+ * @cb: audit cb for this event
+ *
+ * Record an audit message for data is @sa, and handle deal with kill and
+ * complain messages switches.
+ *
+ * Returns: 0 or sa->error on success, else error
+ */
+static int aa_audit_base(int type, struct aa_profile *profile,
+			 struct aa_audit *sa, struct audit_context *audit_cxt,
+			 void (*cb) (struct audit_buffer *, struct aa_audit *))
+{
+	struct audit_buffer *ab = NULL;
+	struct task_struct *task = sa->task ? sa->task : current;
+
+	if (profile && DO_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
+		type = AUDIT_APPARMOR_KILL;
+
+	/* ab freed below in audit_log_end */
+	ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
+
+	if (!ab) {
+		AA_ERROR("(%d) Unable to log event of type (%d)\n",
+			 -ENOMEM, type);
+		sa->error = -ENOMEM;
+		goto out;
+	}
+
+	if (aa_g_audit_header) {
+		audit_log_format(ab, " type=");
+		audit_log_string(ab, aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
+	}
+
+	if (sa->operation) {
+		audit_log_format(ab, " operation=");
+		audit_log_string(ab, sa->operation);
+	}
+
+	if (sa->info) {
+		audit_log_format(ab, " info=");
+		audit_log_string(ab, sa->info);
+		if (sa->error)
+			audit_log_format(ab, " error=%d", sa->error);
+	}
+
+	audit_log_format(ab, " pid=%d", task->pid);
+
+	if (profile && !unconfined(profile)) {
+		pid_t pid;
+		rcu_read_lock();
+		pid = task->real_parent->pid;
+		rcu_read_unlock();
+		audit_log_format(ab, " parent=%d", pid);
+		audit_log_format(ab, " profile=");
+		audit_log_untrustedstring(ab, profile->base.hname);
+
+		if (profile->ns != root_ns) {
+			audit_log_format(ab, " namespace=");
+			audit_log_untrustedstring(ab, profile->ns->base.hname);
+		}
+	}
+
+	if (cb)
+		cb(ab, sa);
+
+	audit_log_end(ab);
+
+out:
+	if (type == AUDIT_APPARMOR_KILL)
+		(void)send_sig_info(SIGKILL, NULL, task);
+
+	return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
+}
+
+/**
+ * aa_audit - Log an audit event to the audit subsystem
+ * @type: audit type for the message
+ * @profile: profile to check against
+ * @sa: audit event
+ * @cb: optional callback fn for type specific fields
+ *
+ * Handle default message switching based off of audit mode flags
+ *
+ * Returns: error on failure
+ */
+int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
+	     void (*cb) (struct audit_buffer *, struct aa_audit *))
+{
+	struct audit_context *audit_cxt;
+	audit_cxt = aa_g_logsyscall ? current->audit_context : NULL;
+
+	if (type == AUDIT_APPARMOR_AUTO) {
+		if (likely(!sa->error)) {
+			if (AUDIT_MODE(profile) != AUDIT_ALL)
+				return 0;
+			type = AUDIT_APPARMOR_AUDIT;
+		} else if (COMPLAIN_MODE(profile))
+			type = AUDIT_APPARMOR_ALLOWED;
+		else
+			type = AUDIT_APPARMOR_DENIED;
+	}
+	if (AUDIT_MODE(profile) == AUDIT_QUIET ||
+	    (type == AUDIT_APPARMOR_DENIED &&
+	     AUDIT_MODE(profile) == AUDIT_QUIET))
+		return sa->error;
+
+	return aa_audit_base(type, profile, sa, audit_cxt, cb);
+}
--- linux-ec2-2.6.32.orig/security/apparmor/policy_unpack.c
+++ linux-ec2-2.6.32/security/apparmor/policy_unpack.c
@@ -0,0 +1,725 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor functions for unpacking policy loaded from
+ * userspace.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * AppArmor uses a serialized binary format for loading policy.
+ * The policy format is documented in Documentation/???
+ * All policy is validated all before it is used.
+ */
+
+#include <asm/unaligned.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/match.h"
+#include "include/policy.h"
+#include "include/policy_unpack.h"
+#include "include/sid.h"
+
+/*
+ * The AppArmor interface treats data as a type byte followed by the
+ * actual data.  The interface has the notion of a a named entry
+ * which has a name (AA_NAME typecode followed by name string) followed by
+ * the entries typecode and data.  Named types allow for optional
+ * elements and extensions to be added and tested for without breaking
+ * backwards compatability.
+ */
+
+enum aa_code {
+	AA_U8,
+	AA_U16,
+	AA_U32,
+	AA_U64,
+	AA_NAME,		/* same as string except it is items name */
+	AA_STRING,
+	AA_BLOB,
+	AA_STRUCT,
+	AA_STRUCTEND,
+	AA_LIST,
+	AA_LISTEND,
+	AA_ARRAY,
+	AA_ARRAYEND,
+};
+
+/*
+ * aa_ext is the read of the buffer containing the serialized profile.  The
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
+ * the unpack routines.
+ */
+struct aa_ext {
+	void *start;
+	void *end;
+	void *pos;		/* pointer to current position in the buffer */
+	u32 version;
+};
+
+/* audit callback for unpack fields */
+static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_iface *sa = container_of(va, struct aa_audit_iface,
+						 base);
+
+	if (sa->name) {
+		audit_log_format(ab, " name=");
+		audit_log_string(ab, sa->name);
+	}
+	if (sa->name2) {
+		audit_log_format(ab, " namespace=");
+		audit_log_string(ab, sa->name2);
+	}
+	if (sa->base.error && sa->pos)
+		audit_log_format(ab, " offset=%ld", sa->pos);
+}
+
+/**
+ * aa_audit_iface - do audit message for policy unpacking/load/replace/remove
+ * @sa: audit date to send to audit  (NOT NULL)
+ *
+ * Returns: %0 or error
+ */
+int aa_audit_iface(struct aa_audit_iface *sa)
+{
+	struct aa_profile *profile;
+	const struct cred *cred = get_current_cred();
+	int error;
+	profile = aa_cred_profile(cred);
+	error = aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa->base, audit_cb);
+	put_cred(cred);
+	return error;
+}
+
+/* test if read will be in packed data bounds */
+static bool aa_inbounds(struct aa_ext *e, size_t size)
+{
+	return (size <= e->end - e->pos);
+}
+
+/**
+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
+ * @e: serialized data read head
+ * @chunk: start address for chunk of data
+ *
+ * Returns: the size of chunk found with the read head at the end of the chunk.
+ */
+static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
+{
+	size_t size = 0;
+
+	if (!aa_inbounds(e, sizeof(u16)))
+		return 0;
+	size = le16_to_cpu(get_unaligned((u16 *) e->pos));
+	e->pos += sizeof(u16);
+	if (!aa_inbounds(e, size))
+		return 0;
+	*chunk = e->pos;
+	e->pos += size;
+	return size;
+}
+
+/* unpack control byte */
+static bool unpack_X(struct aa_ext *e, enum aa_code code)
+{
+	if (!aa_inbounds(e, 1))
+		return 0;
+	if (*(u8 *) e->pos != code)
+		return 0;
+	e->pos++;
+	return 1;
+}
+
+/**
+ * unpack_nameX - check is the next element is of type X with a name of @name
+ * @e: serialized data extent information  (NOT NULL)
+ * @code: type code
+ * @name: name to match to the serialized element.  (MAYBE NULL)
+ *
+ * check that the next serialized data element is of type X and has a tag
+ * name @name.  If @name is specified then there must be a matching
+ * name element in the stream.  If @name is NULL any name element will be
+ * skipped and only the typecode will be tested.
+ * returns 1 on success (both type code and name tests match) and the read
+ * head is advanced past the headers
+ *
+ * Returns: 0 if either match failes, the read head does not move
+ */
+static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
+{
+	/*
+	 * May need to reset pos if name or type doesn't match
+	 */
+	void *pos = e->pos;
+	/*
+	 * Check for presence of a tagname, and if present name size
+	 * AA_NAME tag value is a u16.
+	 */
+	if (unpack_X(e, AA_NAME)) {
+		char *tag = NULL;
+		size_t size = unpack_u16_chunk(e, &tag);
+		/* if a name is specified it must match. otherwise skip tag */
+		if (name && (!size || strcmp(name, tag)))
+			goto fail;
+	} else if (name) {
+		/* if a name is specified and there is no name tag fail */
+		goto fail;
+	}
+
+	/* now check if type code matches */
+	if (unpack_X(e, code))
+		return 1;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
+{
+	if (unpack_nameX(e, AA_U16, name)) {
+		if (!aa_inbounds(e, sizeof(u16)))
+			return 0;
+		if (data)
+			*data = le16_to_cpu(get_unaligned((u16 *) e->pos));
+		e->pos += sizeof(u16);
+		return 1;
+	}
+	return 0;
+}
+
+static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
+{
+	if (unpack_nameX(e, AA_U32, name)) {
+		if (!aa_inbounds(e, sizeof(u32)))
+			return 0;
+		if (data)
+			*data = le32_to_cpu(get_unaligned((u32 *) e->pos));
+		e->pos += sizeof(u32);
+		return 1;
+	}
+	return 0;
+}
+
+static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
+{
+	if (unpack_nameX(e, AA_U64, name)) {
+		if (!aa_inbounds(e, sizeof(u64)))
+			return 0;
+		if (data)
+			*data = le64_to_cpu(get_unaligned((u64 *) e->pos));
+		e->pos += sizeof(u64);
+		return 1;
+	}
+	return 0;
+}
+
+static size_t unpack_array(struct aa_ext *e, const char *name)
+{
+	if (unpack_nameX(e, AA_ARRAY, name)) {
+		int size;
+		if (!aa_inbounds(e, sizeof(u16)))
+			return 0;
+		size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
+		e->pos += sizeof(u16);
+		return size;
+	}
+	return 0;
+}
+
+static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
+{
+	if (unpack_nameX(e, AA_BLOB, name)) {
+		u32 size;
+		if (!aa_inbounds(e, sizeof(u32)))
+			return 0;
+		size = le32_to_cpu(get_unaligned((u32 *) e->pos));
+		e->pos += sizeof(u32);
+		if (aa_inbounds(e, (size_t) size)) {
+			*blob = e->pos;
+			e->pos += size;
+			return size;
+		}
+	}
+	return 0;
+}
+
+static int unpack_str(struct aa_ext *e, const char **string, const char *name)
+{
+	char *src_str;
+	size_t size = 0;
+	void *pos = e->pos;
+	*string = NULL;
+	if (unpack_nameX(e, AA_STRING, name)) {
+		size = unpack_u16_chunk(e, &src_str);
+		if (size) {
+			/* strings are null terminated, length is size - 1 */
+			if (src_str[size - 1] != 0)
+				goto fail;
+			*string = src_str;
+		}
+	}
+	return size;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
+{
+	const char *tmp;
+	void *pos = e->pos;
+	int res = unpack_str(e, &tmp, name);
+	*string = NULL;
+
+	if (!res)
+		return 0;
+
+	*string = kmemdup(tmp, res, GFP_KERNEL);
+	if (!*string) {
+		e->pos = pos;
+		return 0;
+	}
+
+	return res;
+}
+
+static bool verify_accept(struct aa_dfa *dfa, int flags)
+{
+	int i;
+
+	/* verify accept permissions */
+	for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
+		int mode = ACCEPT_TABLE(dfa)[i];
+
+		if (mode & ~DFA_VALID_PERM_MASK)
+			return 0;
+
+		if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
+			return 0;
+	}
+	return 1;
+}
+
+/**
+ * unpack_dfa - unpack a file rule dfa
+ * @e: serialized data extent information
+ *
+ * returns dfa or ERR_PTR or NULL if no dfa
+ */
+static struct aa_dfa *unpack_dfa(struct aa_ext *e)
+{
+	char *blob = NULL;
+	size_t size;
+	struct aa_dfa *dfa = NULL;
+
+	size = unpack_blob(e, &blob, "aadfa");
+	if (size) {
+		/*
+		 * The dfa is aligned with in the blob to 8 bytes
+		 * from the beginning of the stream.
+		 */
+		size_t sz = blob - (char *)e->start;
+		size_t pad = ALIGN(sz, 8) - sz;
+		int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
+			TO_ACCEPT2_FLAG(YYTD_DATA32);
+
+
+		if (aa_g_paranoid_load)
+			flags |= DFA_FLAG_VERIFY_STATES;
+
+		dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
+		
+		if (!IS_ERR(dfa) && !verify_accept(dfa, flags))
+			goto fail;
+	}
+
+	return dfa;
+
+fail:
+	aa_put_dfa(dfa);
+	return ERR_PTR(-EPROTO);
+}
+
+static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
+{
+	void *pos = e->pos;
+
+	/* exec table is optional */
+	if (unpack_nameX(e, AA_STRUCT, "xtable")) {
+		int i, size;
+
+		size = unpack_array(e, NULL);
+		/* currently 4 exec bits and entries 0-3 are reserved iupcx */
+		if (size > 16 - 4)
+			goto fail;
+		profile->file.trans.table = kzalloc(sizeof(char *) * size,
+						    GFP_KERNEL);
+		if (!profile->file.trans.table)
+			goto fail;
+
+		profile->file.trans.size = size;
+		for (i = 0; i < size; i++) {
+			char *str;
+			int c, j, size = unpack_strdup(e, &str, NULL);
+			if (!size)
+				goto fail;
+			profile->file.trans.table[i] = str;
+			/* verify that name doesn't start with space */
+			if (isspace(*str))
+				goto fail;
+
+			/* count internal #  of internal \0 */
+			for (c = j = 0; j < size - 2; j++) {
+				if (!str[j])
+					c++;
+			}
+			if (*str == ':') {
+				/* beginning with : requires an embedded \0 */
+				if (c != 1)
+					goto fail;
+				/* first character after : must be valid */
+				if (!str[1])
+					goto fail;
+			} else if (c)
+				/* fail - all other cases with embedded \0 */
+				goto fail;
+		}
+		if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+			goto fail;
+		if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+			goto fail;
+	}
+	return 1;
+
+fail:
+	aa_free_domain_entries(&profile->file.trans);
+	e->pos = pos;
+	return 0;
+}
+
+static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
+{
+	void *pos = e->pos;
+
+	/* rlimits are optional */
+	if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
+		int i, size;
+		u32 tmp = 0;
+		if (!unpack_u32(e, &tmp, NULL))
+			goto fail;
+		profile->rlimits.mask = tmp;
+
+		size = unpack_array(e, NULL);
+		if (size > RLIM_NLIMITS)
+			goto fail;
+		for (i = 0; i < size; i++) {
+			u64 tmp = 0;
+			if (!unpack_u64(e, &tmp, NULL))
+				goto fail;
+			profile->rlimits.limits[i].rlim_max = tmp;
+		}
+		if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+			goto fail;
+		if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+			goto fail;
+	}
+	return 1;
+
+fail:
+	e->pos = pos;
+	return 0;
+}
+
+/**
+ * unpack_profile - unpack a serialized profile
+ * @e: serialized data extent information
+ * @sa: audit struct for the operation
+ *
+ * NOTE: unpack profile sets audit struct if there is a failure
+ */
+static struct aa_profile *unpack_profile(struct aa_ext *e,
+					 struct aa_audit_iface *sa)
+{
+	struct aa_profile *profile = NULL;
+	const char *name = NULL;
+	size_t size = 0;
+	int i, error = -EPROTO;
+	kernel_cap_t tmpcap;
+	u32 tmp;
+	u64 tmp64;
+
+	/* check that we have the right struct being passed */
+	if (!unpack_nameX(e, AA_STRUCT, "profile"))
+		goto fail;
+	if (!unpack_str(e, &name, NULL))
+		goto fail;
+
+	profile = aa_alloc_profile(name);
+	if (!profile)
+		return ERR_PTR(-ENOMEM);
+
+	/* profile renaming is optional */
+	(void) unpack_str(e, &profile->rename, "rename");
+
+	/* xmatch is optional and may be NULL */
+	profile->xmatch = unpack_dfa(e);
+	if (IS_ERR(profile->xmatch)) {
+		error = PTR_ERR(profile->xmatch);
+		profile->xmatch = NULL;
+		goto fail;
+	}
+	/* xmatch_len is not optional if xmatch is set */
+	if (profile->xmatch) {
+		if (!unpack_u32(e, &tmp, NULL))
+			goto fail;
+		profile->xmatch_len = tmp;
+	}
+
+	/* per profile debug flags (complain, audit) */
+	if (!unpack_nameX(e, AA_STRUCT, "flags"))
+		goto fail;
+	if (!unpack_u32(e, &tmp, NULL))
+		goto fail;
+	if (tmp)
+		profile->flags |= PFLAG_HAT;
+	if (!unpack_u32(e, &tmp, NULL))
+		goto fail;
+	if (tmp)
+		profile->mode = APPARMOR_COMPLAIN;
+	if (!unpack_u32(e, &tmp, NULL))
+		goto fail;
+	if (tmp)
+		profile->audit = AUDIT_ALL;
+
+	if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	/* path_flags is optional */
+	if (unpack_u32(e, &profile->path_flags, "path_flags"))
+		profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
+	else
+		/* default to */
+		profile->path_flags = PFLAG_MEDIATE_DELETED;
+
+	/* mmap_min_addr is optional */
+	if (unpack_u64(e, &tmp64, "mmap_min_addr")) {
+		profile->mmap_min_addr = (unsigned long)tmp64;
+		if (((u64) profile->mmap_min_addr) == tmp64) {
+			profile->flags |= PFLAG_MMAP_MIN_ADDR;
+		} else {
+			sa->base.info = "invalid set mmap_min_addr";
+			goto fail;
+		}
+	}
+
+	if (!unpack_u32(e, &(profile->caps.allowed.cap[0]), NULL))
+		goto fail;
+	if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
+		goto fail;
+	if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
+		goto fail;
+	if (!unpack_u32(e, &tmpcap.cap[0], NULL))
+		goto fail;
+
+	if (unpack_nameX(e, AA_STRUCT, "caps64")) {
+		/* optional upper half of 64 bit caps */
+		if (!unpack_u32(e, &(profile->caps.allowed.cap[1]), NULL))
+			goto fail;
+		if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
+			goto fail;
+		if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
+			goto fail;
+		if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
+			goto fail;
+		if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+			goto fail;
+	}
+
+	if (unpack_nameX(e, AA_STRUCT, "capsx")) {
+		/* optional extended caps mediation mask */
+		if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
+			goto fail;
+		if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
+			goto fail;
+	}
+
+	if (!unpack_rlimits(e, profile))
+		goto fail;
+
+	size = unpack_array(e, "net_allowed_af");
+	if (size) {
+		if (size > AF_MAX)
+			goto fail;
+
+		for (i = 0; i < size; i++) {
+			if (!unpack_u16(e, &profile->net.allowed[i], NULL))
+				goto fail;
+			if (!unpack_u16(e, &profile->net.audit[i], NULL))
+				goto fail;
+			if (!unpack_u16(e, &profile->net.quiet[i], NULL))
+				goto fail;
+		}
+		if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+			goto fail;
+		/*
+		 * allow unix domain and netlink sockets they are handled
+		 * by IPC
+		 */
+	}
+	profile->net.allowed[AF_UNIX] = 0xffff;
+	profile->net.allowed[AF_NETLINK] = 0xffff;
+
+	/* get file rules */
+	profile->file.dfa = unpack_dfa(e);
+	if (IS_ERR(profile->file.dfa)) {
+		error = PTR_ERR(profile->file.dfa);
+		profile->file.dfa = NULL;
+		goto fail;
+	}
+
+	if (!unpack_u32(e, &profile->file.start, "dfa_start"))
+		/* default start state */
+		profile->file.start = DFA_START;
+
+	if (!unpack_trans_table(e, profile))
+		goto fail;
+
+	if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+		goto fail;
+
+	return profile;
+
+fail:
+	sa->name = name ? name : "unknown";
+	if (!sa->base.info)
+		sa->base.info = "failed to unpack profile";
+
+	aa_put_profile(profile);
+
+	return ERR_PTR(error);
+}
+
+/**
+ * aa_verify_head - unpack serialized stream header
+ * @e: serialized data read head
+ * @operation: operation header is being verified for
+ *
+ * Returns: error or 0 if header is good
+ */
+static int aa_verify_header(struct aa_ext *e, struct aa_audit_iface *sa)
+{
+	/* get the interface version */
+	if (!unpack_u32(e, &e->version, "version")) {
+		sa->base.info = "invalid profile format";
+		aa_audit_iface(sa);
+		return -EPROTONOSUPPORT;
+	}
+
+	/* check that the interface version is currently supported */
+	if (e->version != 5) {
+		sa->base.info = "unsupported interface version";
+		aa_audit_iface(sa);
+		return -EPROTONOSUPPORT;
+	}
+
+	/* read the namespace if present */
+	if (!unpack_str(e, &sa->name2, "namespace"))
+		sa->name2 = NULL;
+
+	return 0;
+}
+
+/**
+ * verify_profile - Do post unpack analysis to verify profile consistency
+ * @profile: profile to verify
+ *
+ * Returns: 0 if passes verification else error
+ */
+static bool verify_xindex(int xindex, int table_size)
+{
+	int index, xtype;
+	xtype = xindex & AA_X_TYPE_MASK;
+	index = xindex & AA_X_INDEX_MASK;
+	if (xtype == AA_X_TABLE && index > table_size)
+		return 0;
+	return 1;
+}
+
+/* verify dfa xindexes are in range of transition tables */
+static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
+{
+	int i;
+	for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
+		if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
+			return 0;
+		if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
+			return 0;
+	}
+	return 1;
+}
+
+static int verify_profile(struct aa_profile *profile, struct aa_audit_iface *sa)
+{
+	if (aa_g_paranoid_load) {
+		if (profile->file.dfa &&
+		    !verify_dfa_xindex(profile->file.dfa,
+				       profile->file.trans.size)) {
+			sa->base.info = "Invalid named transition";
+			return -EPROTO;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * aa_unpack - unpack packed binary profile data loaded from user space
+ * @udata: user data copied to kmem  (NOT NULL)
+ * @size: the size of the user data
+ * @sa: audit struct for unpacking  (NOT NULL)
+ *
+ * Unpack user data and return refcounted allocated profile or ERR_PTR
+ *
+ * Returns: profile else error pointer if fails to unpack
+ */
+struct aa_profile *aa_unpack(void *udata, size_t size,
+			     struct aa_audit_iface *sa)
+{
+	struct aa_profile *profile;
+	int error;
+	struct aa_ext e = {
+		.start = udata,
+		.end = udata + size,
+		.pos = udata,
+	};
+
+	error = aa_verify_header(&e, sa);
+	if (error)
+		return ERR_PTR(error);
+
+	profile = unpack_profile(&e, sa);
+	if (IS_ERR(profile)) {
+		sa->pos = e.pos - e.start;
+		return profile;
+	}
+	error = verify_profile(profile, sa);
+	if (error) {
+		aa_put_profile(profile);
+		profile = ERR_PTR(error);
+	}
+
+	/* return refcount */
+	return profile;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/lib.c
+++ linux-ec2-2.6.32/security/apparmor/lib.c
@@ -0,0 +1,100 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains basic common functions used in AppArmor
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+
+#include "include/audit.h"
+
+/**
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * From: 2.6.33 lib/string.c
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ */
+char *skip_spaces(const char *str)
+{
+        while (isspace(*str))
+                ++str;
+        return (char *)str;
+}
+
+/**
+ * aa_split_fqname - split a fqname into a profile and namespace name
+ * @fqname: a full qualified name in namespace profile format
+ * @ns_name: pointer to portion of the string containing the ns name
+ *
+ * Returns: profile name or NULL if one is not specified
+ *
+ * Split a namespace name from a profile name (see policy.c for naming
+ * description).  If a portion of the name is missing it returns NULL for
+ * that portion.
+ *
+ * NOTE: may modifiy the @fqname string.  The pointers returned point
+ *       into the @fqname string.
+ */
+char *aa_split_fqname(char *fqname, char **ns_name)
+{
+	char *name = strstrip(fqname);
+
+	*ns_name = NULL;
+	if (name[0] == ':') {
+		char *split = strchr(&name[1], ':');
+		if (split) {
+			/* overwrite ':' with \0 */
+			*split = 0;
+			name = skip_spaces(split + 1);
+		} else
+			/* a ns name without a following profile is allowed */
+			name = NULL;
+		*ns_name = &name[1];
+	}
+	if (name && *name == 0)
+		name = NULL;
+
+	return name;
+}
+
+/**
+ * aa_strneq - compare null terminated @str to a non null terminated substring
+ * @str: a null terminated string
+ * @sub: a substring, not necessarily null terminated
+ * @len: length of @sub to compare
+ *
+ * The @str string must be full consumed for this to be considered a match
+ */
+bool aa_strneq(const char *str, const char *sub, int len)
+{
+	int res = strncmp(str, sub, len);
+	if (res)
+		return 0;
+	if (str[len] == 0)
+		return 1;
+	return 0;
+}
+
+void aa_info_message(const char *str)
+{
+	struct aa_audit sa = {
+		.gfp_mask = GFP_KERNEL,
+		.info = str,
+	};
+	printk(KERN_INFO "AppArmor: %s\n", str);
+	if (audit_enabled)
+		aa_audit(AUDIT_APPARMOR_STATUS, NULL, &sa, NULL);
+}
+
--- linux-ec2-2.6.32.orig/security/apparmor/Kconfig
+++ linux-ec2-2.6.32/security/apparmor/Kconfig
@@ -0,0 +1,40 @@
+config SECURITY_APPARMOR
+	bool "AppArmor support"
+	depends on SECURITY
+	select AUDIT
+	select SECURITY_PATH
+	select SECURITYFS
+	select SECURITY_NETWORK
+	default n
+	help
+	  This enables the AppArmor security module.
+	  Required userspace tools (if they are not included in your
+	  distribution) and further information may be found at
+	  <http://forge.novell.com/modules/xfmod/project/?apparmor>
+
+	  If you are unsure how to answer this question, answer N.
+
+config SECURITY_APPARMOR_BOOTPARAM_VALUE
+	int "AppArmor boot parameter default value"
+	depends on SECURITY_APPARMOR
+	range 0 1
+	default 1
+	help
+	  This option sets the default value for the kernel parameter
+	  'apparmor', which allows AppArmor to be enabled or disabled
+          at boot.  If this option is set to 0 (zero), the AppArmor
+	  kernel parameter will default to 0, disabling AppArmor at
+	  bootup.  If this option is set to 1 (one), the AppArmor
+	  kernel parameter will default to 1, enabling AppArmor at
+	  bootup.
+
+	  If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_COMPAT_24
+	bool "Enable AppArmor 2.4 compatability"
+	depends on SECURITY_APPARMOR
+	default y
+	help
+	  This option enables compatability with AppArmor 2.4.  It is
+          recommended if compatability with older versions of AppArmor
+          is desired.
--- linux-ec2-2.6.32.orig/security/apparmor/procattr.c
+++ linux-ec2-2.6.32/security/apparmor/procattr.c
@@ -0,0 +1,152 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /proc/<pid>/attr/ interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/policy.h"
+#include "include/domain.h"
+
+/**
+ * aa_getprocattr - Return the profile information for @profile
+ * @profile: the profile to print profile info about  (NOT NULL)
+ * @string: the string that will contain the profile and namespace info (!NULL)
+ *
+ * Returns: length of @string on success else error on failure
+ *
+ * Requires: profile != NULL
+ *
+ * Creates a string containing the namespace_name://profile_name for
+ * @profile.
+ *
+ * Returns: size of string placed in @string else error code on failure
+ */
+int aa_getprocattr(struct aa_profile *profile, char **string)
+{
+	char *str;
+	int len = 0, mode_len, name_len, ns_len = 0;
+	const char *mode_str = profile_mode_names[profile->mode];
+	struct aa_namespace *ns = profile->ns;
+	char *s;
+
+	mode_len = strlen(mode_str) + 3;	/* + 3 for _() */
+	name_len = strlen(profile->base.hname);
+	if (ns != root_ns)
+		ns_len = strlen(ns->base.name) + 3; /*+ 3 for :// */
+	len = mode_len + ns_len + name_len + 1;	    /*+ 1 for \n */
+	s = str = kmalloc(len + 1, GFP_ATOMIC);	    /* + 1 \0 */
+	if (!str)
+		return -ENOMEM;
+
+	if (ns_len) {
+		sprintf(s, "%s://", ns->base.name);
+		s += ns_len;
+	}
+	if (profile->flags & PFLAG_UNCONFINED) {
+		sprintf(s, "%s\n", profile->base.hname);
+		/* mode string not being appended so reduce string size */
+		len -= mode_len;
+	} else
+		sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
+	*string = str;
+
+	/* NOTE: len does not include \0 of string, not saved as part of file */
+	return len;
+}
+
+/**
+ * split_token_from_name - separate a string of form  <token>^<name>
+ * @op: operation name  (NOT NULL)
+ * @args: string to parse  (NOT NULL)
+ * @token: stores returned parsed token value  (NOT NULL)
+ *
+ * Returns: start position of name after token else NULL on failure
+ */
+static char *split_token_from_name(const char *op, char *args, u64 * token)
+{
+	char *name;
+
+	*token = simple_strtoull(args, &name, 16);
+	if ((name == args) || *name != '^') {
+		AA_ERROR("%s: Invalid input '%s'", op, args);
+		return ERR_PTR(-EINVAL);
+	}
+
+	name++;			/* skip ^ */
+	if (!*name)
+		name = NULL;
+	return name;
+}
+
+/**
+ * aa_setprocattr_chagnehat - handle procattr interface to change_hat
+ * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
+ * @size: size of the args
+ * @test: true if this is a test of change_hat permissions
+ *
+ * Returns: %0 or error code if change_hat fails
+ */
+int aa_setprocattr_changehat(char *args, size_t size, int test)
+{
+	char *hat;
+	u64 token;
+	const char *hats[16];		/* current hard limit on # of names */
+	int count = 0;
+
+	hat = split_token_from_name("change_hat", args, &token);
+	if (IS_ERR(hat))
+		return PTR_ERR(hat);
+
+	if (!hat && !token) {
+		AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
+		return -EINVAL;
+	}
+
+	if (hat) {
+		/* set up hat name vector, args guarenteed null terminated
+		 * at args[size]
+		 */
+		char *end = args + size;
+		for (count = 0; (hat < end) && count < 16; ++count) {
+			char *next = hat + strlen(hat) + 1;
+			hats[count] = hat;
+			hat = next;
+		}
+	}
+
+	AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
+		 __func__, token, hat ? hat : NULL);
+
+	return aa_change_hat(hats, count, token, test);
+}
+
+/**
+ * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
+ * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
+ * @onexec: true if change_profile should be delayed until exec
+ * @test: true if this is a test of change_profile permissions
+ *
+ * Returns: %0 or error code if change_profile fails
+ */
+int aa_setprocattr_changeprofile(char *fqname, int onexec, int test)
+{
+	char *name, *ns_name;
+
+	name = aa_split_fqname(fqname, &ns_name);
+	return aa_change_profile(ns_name, name, onexec, test);
+}
+
+int aa_setprocattr_permipc(char *fqname)
+{
+	/* TODO: add ipc permission querying */
+	return -ENOTSUPP;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/policy.c
+++ linux-ec2-2.6.32/security/apparmor/policy.c
@@ -0,0 +1,1098 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy manipulation functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * AppArmor policy is based around profiles, which contain the rules a
+ * task is confined by.  Every task in the sytem has a profile attached
+ * to it determined either by matching "unconfined" tasks against the
+ * visible set of profiles or by following a profiles attachment rules.
+ *
+ * Each profile exists in a profile namespace which is a container of
+ * visible profiles.  Each namespace contains a special "unconfined" profile,
+ * which doesn't enforce any confinement on a task beyond DAC.
+ *
+ * Namespace and profile names can be written together in either
+ * of two syntaxes.
+ *	:namespace:profile - used by kernel interfaces for easy detection
+ *	namespace://profile - used by policy
+ *
+ * Profile names can not start with : or @ or ^ and may not contain \0
+ * 
+ * Reserved profile names
+ *	unconfined - special automatically generated unconfined profile
+ *	inherit - special name to indicate profile inheritance
+ *	null-XXXX-YYYY - special automically generated learning profiles
+ *
+ * Namespace names may not start with / or @ and may not contain \0 or :
+ * Reserved namespace namespace
+ *	user-XXXX - user defined profiles
+ *
+ * a // in a profile or namespace name indicates a hierarcical name with the
+ * name before the // being the parent and the name after the child.
+ *
+ * Profile and namespace hierachies serve two different but similar purposes.
+ * The namespace contains the set of visible profiles that are considered
+ * for attachment.  The hierarchy of namespaces allows for virtualizing
+ * the namespace so that for example a chroot can have its own set of profiles
+ * which may define some local user namespaces.
+ * The profile hierachy severs two distinct purposes,
+ * -  it allows for sub profiles or hats, which allows an application to run
+ *    subprograms under its own profile with different restriction than it
+ *    self, and not have it use the system profile.
+ *    eg. if a mail program starts an editor, the policy might make the
+ *        restrictions tighter on the editor tighter than the mail program,
+ *        and definitely different than general editor restrictions
+ * - it allows for binary hierarchy of profiles, so that execution history
+ *   is preserved.  This feature isn't exploited by AppArmor reference policy
+ *   but is allowed.  NOTE: this is currently suboptimal because profile
+ *   aliasing is not currently implemented so that a profile for each
+ *   level must be defined.
+ *   eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
+ *       from /bin/bash
+ *
+ *   A profile or namespace name that can contain one or more // seperators
+ *   is refered to as an hname (hierarchical).
+ *   eg.  /bin/bash//bin/ls
+ *
+ *   An fqname is a name that may contain both namespace and profile hnames.
+ *   eg. :ns:/bin/bash//bin/ls
+ *
+ * NOTES:
+ *   - locking of profile lists is currently fairly coarse.  All profile
+ *     lists within a namespace use the namespace lock.
+ * FIXME: move profile lists to using rcu_lists
+ */
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include "include/apparmor.h"
+#include "include/capability.h"
+#include "include/context.h"
+#include "include/file.h"
+#include "include/ipc.h"
+#include "include/match.h"
+#include "include/path.h"
+#include "include/policy.h"
+#include "include/policy_unpack.h"
+#include "include/resource.h"
+#include "include/sid.h"
+
+
+/* root profile namespace */
+struct aa_namespace *root_ns;
+
+const char *profile_mode_names[] = {
+	"enforce",
+	"complain",
+	"kill",
+};
+
+/**
+ * hname_tail - find the last component of an hname
+ * @name: hname to find the tail component of  (NOT NULL)
+ *
+ * Returns: the tail name component of an hname
+ */
+static const char *hname_tail(const char *hname)
+{
+	char *split;
+	hname = strstrip((char *)hname);
+	for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
+		hname = split + 2;
+
+	return hname;
+}
+
+/**
+ * policy_init - initialize a policy structure
+ * @policy: policy to initialize  (NOT NULL)
+ * @name: name of the policy, init will make a copy of it  (NOT NULL)
+ */
+static bool policy_init(struct aa_policy *policy, const char *name)
+{
+	/* freed by policy_free */
+	policy->hname = kstrdup(name, GFP_KERNEL);
+	if (!policy->hname)
+		return 0;
+	/* base.name is a substring of fqname */
+	policy->name = (char *)hname_tail(policy->hname);
+
+	INIT_LIST_HEAD(&policy->list);
+	INIT_LIST_HEAD(&policy->profiles);
+	kref_init(&policy->count);
+
+	return 1;
+}
+
+/**
+ * policy_destroy - free the elements referenced by @policy
+ * @policy: policy that is to have its elements freed  (NOT NULL)
+ */
+static void policy_destroy(struct aa_policy *policy)
+{
+	/* still contains profiles -- invalid */
+	if (!list_empty(&policy->profiles)) {
+		AA_ERROR("%s: internal error, "
+			 "policy '%s' still contains profiles\n",
+			 __func__, policy->name);
+		BUG();
+	}
+	if (!list_empty(&policy->list)) {
+		AA_ERROR("%s: internal error, policy '%s' still on list\n",
+			 __func__, policy->name);
+		BUG();
+	}
+
+	/* don't free name as its a subset of hname */
+	kzfree(policy->hname);
+}
+
+/**
+ * __policy_find - find a policy by @name on a policy list
+ * @head: list to search  (NOT NULL)
+ * @name: name to search for  (NOT NULL)
+ *
+ * Requires: correct locks for the @head list be held
+ *
+ * Returns: policy that match @name or NULL if not found
+ */
+static struct aa_policy *__policy_find(struct list_head *head, const char *name)
+{
+	struct aa_policy *policy;
+
+	list_for_each_entry(policy, head, list) {
+		if (!strcmp(policy->name, name))
+			return policy;
+	}
+	return NULL;
+}
+
+/**
+ * __policy_strn_find - find a policy thats name matches @len chars of @str
+ * @head: list to search  (NOT NULL)
+ * @str: string to search for  (NOT NULL)
+ * @len: length of match required
+ *
+ * Requires: correct locks for the @head list be held
+ *
+ * Returns: policy that match @str or NULL if not found
+ *
+ * if @len == strlen(@strlen) then this is equiv to __policy_find
+ * other wise it allows searching for policy by a partial match of name
+ */
+static struct aa_policy *__policy_strn_find(struct list_head *head,
+					    const char *str, int len)
+{
+	struct aa_policy *policy;
+
+	list_for_each_entry(policy, head, list) {
+		if (aa_strneq(policy->name, str, len))
+			return policy;
+	}
+
+	return NULL;
+}
+
+/*
+ * Routines for AppArmor namespaces
+ */
+
+/**
+ * aa_alloc_namespace - allocate, initialize and return a new namespace
+ * @name: a preallocated name  (NOT NULL)
+ *
+ * Returns: NULL on failure.
+ */
+static struct aa_namespace *aa_alloc_namespace(const char *name)
+{
+	struct aa_namespace *ns;
+
+	ns = kzalloc(sizeof(*ns), GFP_KERNEL);
+	AA_DEBUG("%s(%p)\n", __func__, ns);
+	if (!ns)
+		return NULL;
+
+	if (!policy_init(&ns->base, name))
+		goto fail_ns;
+	INIT_LIST_HEAD(&ns->sub_ns);
+	rwlock_init(&ns->lock);
+
+	/* released by aa_free_namespace */
+	ns->unconfined = aa_alloc_profile("unconfined");
+	if (!ns->unconfined)
+		goto fail_unconfined;
+
+	ns->unconfined->sid = aa_alloc_sid();
+	ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
+	    PFLAG_IMMUTABLE;
+
+	/*
+	 * released by aa_free_namespace, however aa_remove_namespace breaks
+	 * the cyclic references (ns->unconfined, and unconfined->ns) and
+	 * replaces with refs to parent namespace unconfined
+	 */
+	ns->unconfined->ns = aa_get_namespace(ns);
+
+	return ns;
+
+fail_unconfined:
+	kzfree(ns->base.name);
+fail_ns:
+	kzfree(ns);
+	return NULL;
+}
+
+/**
+ * aa_free_namespace - free a profile namespace
+ * @ns: the namespace to free  (MAYBE NULL)
+ *
+ * Requires: All references to the namespace must have been put, if the
+ *           namespace was referenced by a profile confining a task,
+ */
+static void aa_free_namespace(struct aa_namespace *ns)
+{
+	if (!ns)
+		return;
+
+	policy_destroy(&ns->base);
+	aa_put_namespace(ns->parent);
+
+	if (ns->unconfined && ns->unconfined->ns == ns)
+		ns->unconfined->ns = NULL;
+
+	aa_put_profile(ns->unconfined);
+	kzfree(ns);
+}
+
+/**
+ * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
+ * @kr: kref callback for freeing of a namespace  (NOT NULL)
+ */
+void aa_free_namespace_kref(struct kref *kref)
+{
+	aa_free_namespace(container_of(kref, struct aa_namespace, base.count));
+}
+
+/**
+ * __aa_find_namespace - find a namespace on a list by @name
+ * @head: list to search for namespace on  (NOT NULL)
+ * @name: name of namespace to look for  (NOT NULL)
+ *
+ * Returns: unrefcounted namespace
+ *
+ * Requires: ns lock be held
+ */
+static struct aa_namespace *__aa_find_namespace(struct list_head *head,
+						const char *name)
+{
+	return (struct aa_namespace *)__policy_find(head, name);
+}
+
+/**
+ * aa_find_namespace  -  look up a profile namespace on the namespace list
+ * @root: namespace to search in  (NOT NULL)
+ * @name: name of namespace to find  (NOT NULL)
+ *
+ * Returns: a pointer to the namespace on the list, or NULL if no namespace
+ * called @name exists.
+ *
+ * refcount released by caller
+ */
+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
+				       const char *name)
+{
+	struct aa_namespace *ns = NULL;
+
+	read_lock(&root->lock);
+	ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
+	read_unlock(&root->lock);
+
+	return ns;
+}
+
+/**
+ * aa_prepare_namespace - find an existing or create a new namespace of @name
+ * @name: the namespace to find or add  (NOT NULL)
+ *
+ * Returns: refcounted namespace or NULL if failed to create one
+ */
+static struct aa_namespace *aa_prepare_namespace(const char *name)
+{
+	struct aa_namespace *ns, *root;
+
+	root = aa_current_profile()->ns;
+
+	write_lock(&root->lock);
+
+	/* if name isn't specified the profile is loaded to the current ns */
+	if (!name) {
+		/* released by caller */
+		ns = aa_get_namespace(root);
+		goto out;
+	}
+
+	/* try and find the specified ns and if it doesn't exist create it */
+	/* released by caller */
+	ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
+	if (!ns) {
+		/* name && namespace not found */
+		struct aa_namespace *new_ns;
+		write_unlock(&root->lock);
+		new_ns = aa_alloc_namespace(name);
+		if (!new_ns)
+			return NULL;
+		write_lock(&root->lock);
+		/* test for race when new_ns was allocated */
+		ns = __aa_find_namespace(&root->sub_ns, name);
+		if (!ns) {
+			/* add parent ref */
+			new_ns->parent = aa_get_namespace(root);
+
+			list_add(&new_ns->base.list, &root->sub_ns);
+			/* add list ref */
+			ns = aa_get_namespace(new_ns);
+		} else {
+			/* raced so free the new one */
+			aa_free_namespace(new_ns);
+			/* get reference on namespace */
+			aa_get_namespace(ns);
+		}
+	}
+out:
+	write_unlock(&root->lock);
+
+	/* return ref */
+	return ns;
+}
+
+/**
+ * __aa_add_profile - add a profile to a list
+ * @list: list to add it to  (NOT NULL)
+ * @profile: the profile to add  (NOT NULL)
+ *
+ * refcount @profile, should be put by __aa_remove_profile
+ *
+ * Requires: namespace lock be held, or list not be shared
+ */
+static void __aa_add_profile(struct list_head *list,
+			     struct aa_profile *profile)
+{
+	list_add(&profile->base.list, list);
+	/* get list reference */
+	aa_get_profile(profile);
+}
+
+/**
+ * __aa_remove_profile - remove a profile from the list it is one
+ * @profile: the profile to remove  (NOT NULL)
+ *
+ * remove a profile from the list, warning generally removal should
+ * be done with __aa_replace_profile as most profile removals are
+ * replacements to the unconfined profile.
+ *
+ * put @profile list refcount
+ *
+ * Requires: namespace lock be held, or list not have been live
+ */
+static void __aa_remove_profile(struct aa_profile *profile)
+{
+	list_del_init(&profile->base.list);
+	if (!(profile->flags & PFLAG_NO_LIST_REF))
+		/* release list reference */
+		aa_put_profile(profile);
+}
+
+/**
+ * __aa_replace_profile - replace @old with @new on a list
+ * @old: profile to be replaced  (NOT NULL)
+ * @new: profile to replace @old with  (MAYBE NULL)
+ *
+ * Will duplicaticate and refcount elements that @new inherits from @old
+ * and will inherit @old children.  If new is NULL it will replace to the
+ * unconfined profile for old's namespace.
+ *
+ * refcount @new for list, put @old list refcount
+ *
+ * Requires: namespace list lock be held, or list not be shared
+ */
+static void __aa_replace_profile(struct aa_profile *old,
+				 struct aa_profile *new)
+{
+	struct aa_policy *policy;
+	struct aa_profile *child, *tmp;
+
+	if (old->parent)
+		policy = &old->parent->base;
+	else
+		policy = &old->ns->base;
+
+	if (new) {
+		/* released when @new is freed */
+		new->parent = aa_get_profile(old->parent);
+		new->ns = aa_get_namespace(old->ns);
+		new->sid = old->sid;
+		__aa_add_profile(&policy->profiles, new);
+	} else {
+		/* refcount not taken, held via @old refcount */
+		new = old->ns->unconfined;
+	}
+
+	/* inherit children */
+	list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
+		aa_put_profile(child->parent);
+		child->parent = aa_get_profile(new);
+		/* list refcount transfered to @new*/
+		list_move(&child->base.list, &new->base.profiles);
+	}
+
+	/* released by aa_free_profile */
+	old->replacedby = aa_get_profile(new);
+	__aa_remove_profile(old);
+}
+
+/**
+ * __aa_profile_list_release - remove all profiles on the list and put refs
+ * @head: list of profiles  (NOT NULL)
+ *
+ * Requires: namespace lock be held
+ */
+static void __aa_profile_list_release(struct list_head *head)
+{
+	struct aa_profile *profile, *tmp;
+	list_for_each_entry_safe(profile, tmp, head, base.list) {
+		/* release any children lists first */
+		__aa_profile_list_release(&profile->base.profiles);
+		__aa_replace_profile(profile, NULL);
+	}
+}
+
+static void __aa_remove_namespace(struct aa_namespace *ns);
+
+/**
+ * __aa_ns_list_release - remove all profile namespaces on the list put refs
+ * @head: list of profile namespaces  (NOT NULL)
+ *
+ * Requires: namespace lock be held
+ */
+static void __aa_ns_list_release(struct list_head *head)
+{
+	struct aa_namespace *ns, *tmp;
+	list_for_each_entry_safe(ns, tmp, head, base.list)
+		__aa_remove_namespace(ns);
+
+}
+
+/**
+ * aa_destroy_namespace - remove everything contained by @ns
+ * @ns: namespace to have it contents removed  (NOT NULL)
+ */
+static void aa_destroy_namespace(struct aa_namespace *ns)
+{
+	if (!ns)
+		return;
+
+	write_lock(&ns->lock);
+	/* release all profiles in this namespace */
+	__aa_profile_list_release(&ns->base.profiles);
+
+	/* release all sub namespaces */
+	__aa_ns_list_release(&ns->sub_ns);
+
+	write_unlock(&ns->lock);
+}
+
+/**
+ * __aa_remove_namespace - remove a namespace and all its children
+ * @ns: namespace to be removed  (NOT NULL)
+ * 
+ * Requires: ns->parent->lock be held and ns removed from parent.
+ */
+static void __aa_remove_namespace(struct aa_namespace *ns)
+{
+	struct aa_profile *unconfined = ns->unconfined;
+
+	/* remove ns from namespace list */
+	list_del_init(&ns->base.list);
+
+	/*
+	 * break the ns, unconfined profile cyclic reference and forward
+	 * all new unconfined profiles requests to the parent namespace
+	 * This will result in all confined tasks that have a profile
+	 * being removed, inheriting the parent->unconfined profile.
+	 */
+	if (ns->parent)
+		ns->unconfined = aa_get_profile(ns->parent->unconfined);
+
+	aa_destroy_namespace(ns);
+
+	/* release original ns->unconfined ref */
+	aa_put_profile(unconfined);
+	/* release ns->base.list ref, from removal above */
+	aa_put_namespace(ns);
+}
+
+/**
+ * aa_alloc_root_ns - allocate the root profile namespace
+ *
+ * Returns: %0 on success else error
+ *
+ */
+int __init aa_alloc_root_ns(void)
+{
+	/* released by aa_free_root_ns - used as list ref*/
+	root_ns = aa_alloc_namespace("root");
+	if (!root_ns)
+		return -ENOMEM;
+
+	return 0;
+}
+
+ /**
+  * aa_free_root_ns - free the root profile namespace
+  */
+void aa_free_root_ns(void)
+ {
+	 struct aa_namespace *ns = root_ns;
+	 root_ns = NULL;
+ 
+	 aa_destroy_namespace(ns);
+	 aa_put_namespace(ns);
+}
+
+/**
+ * aa_alloc_profile - allocate, initialize and return a new profile
+ * @hname: name of the profile  (NOT NULL)
+ *
+ * Returns: NULL on failure, else refcounted profile
+ */
+struct aa_profile *aa_alloc_profile(const char *hname)
+{
+	struct aa_profile *profile;
+
+	/* freed by aa_free_profile - usually through aa_put_profile */
+	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
+	if (!profile)
+		return NULL;
+
+	if (!policy_init(&profile->base, hname)) {
+		kzfree(profile);
+		return NULL;
+	}
+
+	/* return ref */
+	return profile;
+}
+
+/**
+ * aa_new_null_profile - create a new null-X learning profile
+ * @parent: profile that caused this profile to be created (NOT NULL)
+ * @hat: true if the null- learning profile is a hat
+ *
+ * Create a null- complain mode profile used in learning mode.  The name of
+ * the profile is unique and follows the format of parent//null-sid.
+ *
+ * null profiles are added to the profile list but the list does not
+ * hold a count on them so that they are automatically released when
+ * not in use.
+ *
+ * Returns: new profile else NULL on failure
+ */
+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
+{
+	struct aa_profile *profile = NULL;
+	char *name;
+	u32 sid = aa_alloc_sid();
+
+	/* freed below */
+	name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
+	if (!name)
+		goto fail;
+	sprintf(name, "%s//null-%x", parent->base.hname, sid);
+
+	profile = aa_alloc_profile(name);
+	kfree(name);
+	if (!profile)
+		goto fail;
+
+	profile->sid = sid;
+	profile->mode = APPARMOR_COMPLAIN;
+	profile->flags = PFLAG_NULL;
+	if (hat)
+		profile->flags |= PFLAG_HAT;
+
+	/* released on aa_free_profile */
+	profile->parent = aa_get_profile(parent);
+	profile->ns = aa_get_namespace(parent->ns);
+
+	write_lock(&profile->ns->lock);
+	__aa_add_profile(&parent->base.profiles, profile);
+	write_unlock(&profile->ns->lock);
+
+	return profile;
+
+fail:
+	aa_free_sid(sid);
+	return NULL;
+}
+
+/**
+ * aa_free_profile - free a profile
+ * @profile: the profile to free  (MAYBE NULL)
+ *
+ * Free a profile, its hats and null_profile. All references to the profile,
+ * its hats and null_profile must have been put.
+ *
+ * If the profile was referenced from a task context, aa_free_profile() will
+ * be called from an rcu callback routine, so we must not sleep here.
+ */
+static void aa_free_profile(struct aa_profile *profile)
+{
+	AA_DEBUG("%s(%p)\n", __func__, profile);
+
+	if (!profile)
+		return;
+
+	if (!list_empty(&profile->base.list)) {
+		AA_ERROR("%s: internal error, "
+			 "profile '%s' still on ns list\n",
+			 __func__, profile->base.name);
+		BUG();
+	}
+
+	/* free children profiles */
+	policy_destroy(&profile->base);
+	aa_put_profile(profile->parent);
+
+	aa_put_namespace(profile->ns);
+
+	aa_free_file_rules(&profile->file);
+	aa_free_cap_rules(&profile->caps);
+	aa_free_net_rules(&profile->net);
+	aa_free_rlimit_rules(&profile->rlimits);
+
+	aa_free_sid(profile->sid);
+	aa_put_dfa(profile->xmatch);
+
+	if (profile->replacedby)
+		aa_put_profile(profile->replacedby);
+
+	kzfree(profile);
+}
+
+/**
+ * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
+ * @kr: kref callback for freeing of a profile  (NOT NULL)
+ */
+void aa_free_profile_kref(struct kref *kref)
+{
+	struct aa_profile *p = container_of(kref, struct aa_profile,
+					    base.count);
+
+	aa_free_profile(p);
+}
+
+/* TODO: profile count accounting - setup in remove */
+
+/**
+ * __aa_find_child - find a profile on @head list with a name matching @name
+ * @head: list to search  (NOT NULL)
+ * @name: name of profile (NOT NULL)
+ *
+ * Requires: ns lock protecting list be held
+ *
+ * Returns: unrefcounted profile ptr, or NULL if not found
+ */
+static struct aa_profile *__aa_find_child(struct list_head *head,
+					  const char *name)
+{
+	return (struct aa_profile *)__policy_find(head, name);
+}
+
+/**
+ * __aa_strn_find_child - find a profile on @head list using substring of @name
+ * @head: list to search  (NOT NULL)
+ * @name: name of profile (NOT NULL)
+ * @len: length of @name substring to match
+ *
+ * Requires: ns lock protecting list be held
+ *
+ * Returns: unrefcounted profile ptr, or NULL if not found
+ */
+static struct aa_profile *__aa_strn_find_child(struct list_head *head,
+					       const char *name, int len)
+{
+	return (struct aa_profile *)__policy_strn_find(head, name, len);
+}
+
+/**
+ * aa_find_child - find a profile by @name in @parent
+ * @parent: profile to search  (NOT NULL)
+ * @name: profile name to search for  (NOT NULL)
+ *
+ * Returns: a ref counted profile or NULL if not found
+ */
+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
+{
+	struct aa_profile *profile;
+
+	read_lock(&parent->ns->lock);
+	profile = aa_get_profile(__aa_find_child(&parent->base.profiles, name));
+	read_unlock(&parent->ns->lock);
+
+	return profile;
+}
+
+/**
+ * __aa_find_parent - lookup the parent of a profile of name @hname
+ * @ns: namespace to lookup profile in  (NOT NULL)
+ * @hname: hierarchical profile name to find parent of  (NOT NULL)
+ *
+ * Lookups up the parent of a fully qualified profile name, the profile
+ * that matches hname does not need to exist, in general this
+ * is used to load a new profile.
+ *
+ * Requires: ns->lock be held
+ *
+ * Returns: unrefcounted policy or NULL if not found
+ */
+static struct aa_policy *__aa_find_parent(struct aa_namespace *ns,
+					  const char *hname)
+{
+	struct aa_policy *policy;
+	struct aa_profile *profile = NULL;
+	char *split;
+
+	policy = &ns->base;
+
+	for (split = strstr(hname, "//"); split;) {
+		profile = __aa_strn_find_child(&policy->profiles, hname,
+					       split - hname);
+		if (!profile)
+			return NULL;
+		policy = &profile->base;
+		hname = split + 2;
+		split = strstr(hname, "//");
+	}
+	if (!profile)
+		return &ns->base;
+	return &profile->base;
+}
+
+/**
+ * __aa_find_profile - lookup the profile matching @hname
+ * @base: base list to start looking up profile name from  (NOT NULL)
+ * @hname: hierarchical profile name  (NOT NULL)
+ *
+ * Requires: ns->lock be held
+ *
+ * Returns: unrefcounted profile pointer or NULL if not found
+ *
+ * Do a relative name lookup, recursing through profile tree.
+ */
+static struct aa_profile *__aa_find_profile(struct aa_policy *base,
+					    const char *hname)
+{
+	struct aa_profile *profile = NULL;
+	char *split;
+
+	for (split = strstr(hname, "//"); split;) {
+		profile = __aa_strn_find_child(&base->profiles, hname,
+					       split - hname);
+		if (!profile)
+			return NULL;
+
+		base = &profile->base;
+		hname = split + 2;
+		split = strstr(hname, "//");
+	}
+
+	profile = __aa_find_child(&base->profiles, hname);
+
+	return profile;
+}
+
+/**
+ * aa_find_profile_by_name - find a profile by its full or partial name
+ * @ns: the namespace to start from
+ * @hname: name to do lookup on.  Does not contain namespace prefix
+ *
+ * Returns: refcounted profile or NULL if not found
+ */
+struct aa_profile *aa_find_profile(struct aa_namespace *ns, const char *hname)
+{
+	struct aa_profile *profile;
+
+	read_lock(&ns->lock);
+	profile = aa_get_profile(__aa_find_profile(&ns->base, hname));
+	read_unlock(&ns->lock);
+	return profile;
+}
+
+/**
+ * replacement_allowed - test to see if replacement is allowed
+ * @profile: profile to test if it can be replaced  (MAYBE NULL)
+ * @sa: audit data  (NOT NULL)
+ * @add_only: true if replacement shouldn't be allowed but addition is okay
+ *
+ * Returns: %1 if replacement allowed else %0
+ */
+static bool replacement_allowed(struct aa_profile *profile,
+				struct aa_audit_iface *sa,
+				int add_only)
+{
+	if (profile) {
+		if (profile->flags & PFLAG_IMMUTABLE) {
+			sa->base.info = "cannot replace immutible profile";
+			sa->base.error = -EPERM;
+			return 0;
+		} else if (add_only) {
+			sa->base.info = "profile already exists";
+			sa->base.error = -EEXIST;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**
+ * __add_new_profile - simple wrapper around __aa_add_profile
+ * @ns: namespace that profile is being added to  (NOT NULL)
+ * @policy: the policy container to add the profile to  (NOT NULL)
+ * @profile: profile to add  (NOT NULL)
+ *
+ * add a profile to a list and do other required basic allocations
+ */
+static void __add_new_profile(struct aa_namespace *ns,
+			      struct aa_policy *policy,
+			      struct aa_profile *profile)
+{
+	if (policy != &ns->base)
+		/* released on profile replacement or aa_free_profile */
+		profile->parent = aa_get_profile((struct aa_profile *) policy);
+	__aa_add_profile(&policy->profiles, profile);
+	/* released on aa_free_profile */
+	profile->sid = aa_alloc_sid();
+	profile->ns = aa_get_namespace(ns);
+}
+
+/**
+ * aa_interface_replace_profiles - replace profile(s) on the profile list
+ * @udata: serialized data stream  (NOT NULL)
+ * @size: size of the serialized data stream
+ * @add_only: true if only doing addition, no replacement allowed
+ *
+ * unpack and replace a profile on the profile list and uses of that profile
+ * by any aa_task_cxt.  If the profile does not exist on the profile list
+ * it is added.
+ *
+ * Returns: size of data consumed else error code on failure.
+ */
+ssize_t aa_interface_replace_profiles(void *udata, size_t size, bool add_only)
+{
+	struct aa_policy *policy;
+	struct aa_profile *old_profile = NULL, *new_profile = NULL;
+	struct aa_profile *rename_profile = NULL;
+	struct aa_namespace *ns = NULL;
+	ssize_t error;
+	struct aa_audit_iface sa = {
+		.base.operation = "profile_replace",
+		.base.gfp_mask = GFP_ATOMIC,
+	};
+
+	/* check if loading policy is locked out */
+	if (aa_g_lock_policy) {
+		sa.base.info = "policy locked";
+		sa.base.error = -EACCES;
+		goto fail;
+	}
+
+	/* released below */
+	new_profile = aa_unpack(udata, size, &sa);
+	if (IS_ERR(new_profile)) {
+		sa.base.error = PTR_ERR(new_profile);
+		new_profile = NULL;
+		goto fail;
+	}
+
+	/* released below */
+	ns = aa_prepare_namespace(sa.name2);
+	if (!ns) {
+		sa.base.info = "failed to prepare namespace";
+		sa.base.error = -ENOMEM;
+		goto fail;
+	}
+
+	sa.name = new_profile->base.hname;
+
+	write_lock(&ns->lock);
+	/* no ref on policy only use inside lock */
+	policy = __aa_find_parent(ns, new_profile->base.hname);
+
+	if (!policy) {
+		sa.base.info = "parent does not exist";
+		sa.base.error = -ENOENT;
+		goto audit;
+	}
+
+	old_profile = __aa_find_child(&policy->profiles,
+				      new_profile->base.name);
+	/* released below */
+	aa_get_profile(old_profile);
+
+	if (new_profile->rename) {
+		rename_profile = __aa_find_profile(&ns->base,
+						   new_profile->rename);
+		/* released below */
+		aa_get_profile(rename_profile);
+
+		if (!rename_profile) {
+			sa.base.info = "profile to rename does not exist";
+			sa.name = new_profile->rename;
+			sa.base.error = -ENOENT;
+			goto audit;
+		}
+	}
+
+	if (!replacement_allowed(old_profile, &sa, add_only))
+		goto audit;
+
+	if (!replacement_allowed(rename_profile, &sa, add_only))
+		goto audit;
+
+audit:
+	if (!old_profile && !rename_profile)
+		sa.base.operation = "profile_load";
+
+	error = aa_audit_iface(&sa);
+
+	/* rename field must be cleared as it is shared with replaced-by */
+	if (new_profile->rename) {
+		kzfree(new_profile->rename);
+		new_profile->rename = NULL;
+	}
+
+	if (!error) {
+		if (old_profile)
+			__aa_replace_profile(old_profile, new_profile);
+		if (rename_profile)
+			__aa_replace_profile(rename_profile, new_profile);
+		if (!(old_profile || rename_profile))
+			__add_new_profile(ns, policy, new_profile);
+	}
+	write_unlock(&ns->lock);
+
+out:
+	aa_put_namespace(ns);
+	aa_put_profile(rename_profile);
+	aa_put_profile(old_profile);
+	aa_put_profile(new_profile);
+	if (error)
+		return error;
+	return size;
+
+fail:
+	error = aa_audit_iface(&sa);
+	goto out;
+}
+
+/**
+ * aa_interface_remove_profiles - remove profile(s) from the system
+ * @fqname: name of the profile or namespace to remove  (NOT NULL)
+ * @size: size of the name
+ *
+ * Remove a profile or sub namespace from the current namespace, so that
+ * they can not be found anymore and mark them as replaced by unconfined
+ *
+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
+ *
+ * Returns: size of data consume else error code if fails
+ */
+ssize_t aa_interface_remove_profiles(char *fqname, size_t size)
+{
+	struct aa_namespace *root, *ns = NULL;
+	struct aa_profile *profile = NULL;
+	struct aa_audit_iface sa = {
+		.base.operation = "profile_remove",
+		.base.gfp_mask = GFP_ATOMIC,
+	};
+	const char *name = fqname;
+	int error;
+
+	/* check if loading policy is locked out */
+	if (aa_g_lock_policy) {
+		sa.base.info = "policy locked";
+		sa.base.error = -EACCES;
+		goto fail;
+	}
+
+	if (*fqname == 0) {
+		sa.base.info = "no profile specified";
+		sa.base.error = -ENOENT;
+		goto fail;
+	}
+
+	/* ref count held by cred */
+	root = aa_current_profile()->ns;
+
+	if (fqname[0] == ':') {
+		char *ns_name;
+		name = aa_split_fqname(fqname, &ns_name);
+		if (ns_name)
+			/* released below */
+			ns = aa_find_namespace(root, ns_name);
+	} else
+		/* released below */
+		ns = aa_get_namespace(root);
+
+	if (!ns) {
+		sa.base.info = "namespace does not exist";
+		sa.base.error = -ENOENT;
+		goto fail;
+	}
+
+	sa.name2 = ns->base.name;
+	write_lock(&ns->lock);
+	if (!name) {
+		/* remove namespace - can only happen if fqname[0] == ':' */
+		__aa_remove_namespace(ns);
+	} else {
+		/* remove profile */
+		profile = aa_get_profile(__aa_find_profile(&ns->base, name));
+		if (!profile) {
+			sa.name = name;
+			sa.base.error = -ENOENT;
+			sa.base.info = "profile does not exist";
+			goto fail_ns_lock;
+		}
+		sa.name = profile->base.hname;
+		__aa_profile_list_release(&profile->base.profiles);
+		__aa_replace_profile(profile, NULL);
+	}
+	write_unlock(&ns->lock);
+
+	/* don't fail removal if audit fails */
+	(void) aa_audit_iface(&sa);
+	aa_put_namespace(ns);
+	aa_put_profile(profile);
+	return size;
+
+fail_ns_lock:
+	write_unlock(&ns->lock);
+	aa_put_namespace(ns);
+
+fail:
+	error = aa_audit_iface(&sa);
+	return error;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/capability.c
+++ linux-ec2-2.6.32/security/apparmor/capability.c
@@ -0,0 +1,146 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor capability mediation functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+
+#include "include/apparmor.h"
+#include "include/capability.h"
+#include "include/context.h"
+#include "include/policy.h"
+#include "include/audit.h"
+
+/*
+ * Table of capability names: we generate it from capabilities.h.
+ */
+#include "capability_names.h"
+
+struct audit_cache {
+	struct aa_profile *profile;
+	kernel_cap_t caps;
+};
+
+static DEFINE_PER_CPU(struct audit_cache, audit_cache);
+
+struct aa_audit_caps {
+	struct aa_audit base;
+
+	int cap;
+};
+
+/**
+ * audit_cb - call back for capability components of audit struct
+ * @ab - audit buffer   (NOT NULL)
+ * @va - audit struct to audit data from  (NOT NULL)
+ */
+static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_caps *sa = container_of(va, struct aa_audit_caps, base);
+
+	audit_log_format(ab, " name=");
+	audit_log_untrustedstring(ab, capability_names[sa->cap]);
+}
+
+/**
+ * aa_audit_caps - audit a capability
+ * @profile: profile confining task
+ * @sa: audit structure containing data to audit
+ *
+ * Do auditing of capability and handle, audit/complain/kill modes switching
+ * and duplicate message elimination.
+ *
+ * returns: 0 or sa->error on succes,  error code on failure
+ */
+static int aa_audit_caps(struct aa_profile *profile, struct aa_audit_caps *sa)
+{
+	struct audit_cache *ent;
+	int type = AUDIT_APPARMOR_AUTO;
+
+	if (likely(!sa->base.error)) {
+		/* test if auditing is being forced */
+		if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+			   !cap_raised(profile->caps.audit, sa->cap)))
+			return 0;
+		type = AUDIT_APPARMOR_AUDIT;
+	} else if (DO_KILL(profile) ||
+		   cap_raised(profile->caps.kill, sa->cap)) {
+		type = AUDIT_APPARMOR_KILL;
+	} else if (cap_raised(profile->caps.quiet, sa->cap) &&
+		   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+		   AUDIT_MODE(profile) != AUDIT_ALL) {
+		/* quiet auditing */
+		return sa->base.error;
+	}
+
+	/* Do simple duplicate message elimination */
+	ent = &get_cpu_var(audit_cache);
+	if (profile == ent->profile && cap_raised(ent->caps, sa->cap)) {
+		put_cpu_var(audit_cache);
+		if (COMPLAIN_MODE(profile))
+			return 0;
+		return sa->base.error;
+	} else {
+		aa_put_profile(ent->profile);
+		ent->profile = aa_get_profile(profile);
+		cap_raise(ent->caps, sa->cap);
+	}
+	put_cpu_var(audit_cache);
+
+	return aa_audit(type, profile, &sa->base, audit_cb);
+}
+
+/**
+ * aa_profile_capable - test if profile allows use of capability @cap
+ * @profile: profile being enforced    (NOT NULL, NOT unconfined)
+ * @cap: capability to test if allowed
+ *
+ * Returns: 0 if allowed else -EPERM
+ */
+static int aa_profile_capable(struct aa_profile *profile, int cap)
+{
+	return cap_raised(profile->caps.allowed, cap) ? 0 : -EPERM;
+}
+
+/**
+ * aa_capable - test permission to use capability
+ * @task: task doing capability test against
+ * @profile: profile confining @task
+ * @cap: capability to be tested
+ * @audit: whether an audit record should be generated
+ *
+ * Look up capability in profile capability set.
+ *
+ * Returns: 0 on success, or else an error code.
+ */
+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
+	       int audit)
+{
+	int error = aa_profile_capable(profile, cap);
+	struct aa_audit_caps sa = {
+		.base.operation = "capable",
+		.base.task = task,
+		.base.gfp_mask = GFP_ATOMIC,
+		.base.error = error,
+		.cap = cap,
+	};
+
+	if (!audit) {
+		if (COMPLAIN_MODE(profile))
+			return 0;
+		return error;
+	}
+
+	return aa_audit_caps(profile, &sa);
+}
--- linux-ec2-2.6.32.orig/security/apparmor/net.c
+++ linux-ec2-2.6.32/security/apparmor/net.c
@@ -0,0 +1,167 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/net.h"
+#include "include/policy.h"
+
+#include "af_names.h"
+
+static const char *sock_type_names[] = {
+	"unknown(0)",
+	"stream",
+	"dgram",
+	"raw",
+	"rdm",
+	"seqpacket",
+	"dccp",
+	"unknown(7)",
+	"unknown(8)",
+	"unknown(9)",
+	"packet",
+};
+
+struct aa_audit_net {
+	struct aa_audit base;
+
+	int family, type, protocol;
+
+};
+
+/* audit callback for net specific fields */
+static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_net *sa = container_of(va, struct aa_audit_net, base);
+
+	if (sa->family || sa->type) {
+		if (address_family_names[sa->family]) {
+			audit_log_format(ab, " family=");
+			audit_log_string(ab, address_family_names[sa->family]);
+		} else {
+			audit_log_format(ab, " family=\"unknown(%d)\"",
+					 sa->family);
+		}
+		if (sock_type_names[sa->type]) {
+			audit_log_format(ab, " sock_type=");
+			audit_log_string(ab, sock_type_names[sa->type]);
+		} else {
+			audit_log_format(ab, " sock_type=\"unknown(%d)\"",
+					 sa->type);
+		}
+		audit_log_format(ab, " protocol=%d", sa->protocol);
+	}
+
+}
+
+/**
+ * aa_audit_net - audit network access
+ * @profile: profile being enforced  (NOT NULL)
+ * @sa: audit data  (NOT NULL)
+ *
+ * Returns: %0 or sa->error else other errorcode on failure
+ */
+static int aa_audit_net(struct aa_profile *profile, struct aa_audit_net *sa)
+{
+	int type = AUDIT_APPARMOR_AUTO;
+
+	if (likely(!sa->base.error)) {
+		u16 audit_mask = profile->net.audit[sa->family];
+		if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
+			   !(1 << sa->type & audit_mask)))
+			return 0;
+		type = AUDIT_APPARMOR_AUDIT;
+	} else {
+		u16 quiet_mask = profile->net.quiet[sa->family];
+		u16 kill_mask = 0;
+		u16 denied = (1 << sa->type) & ~quiet_mask;
+
+		if (denied & kill_mask)
+			type = AUDIT_APPARMOR_KILL;
+
+		if ((denied & quiet_mask) &&
+		    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+		    AUDIT_MODE(profile) != AUDIT_ALL)
+			return COMPLAIN_MODE(profile) ? 0 : sa->base.error;
+	}
+
+	return aa_audit(type, profile, &sa->base, audit_cb);
+}
+
+/**
+ * aa_net_perm - very course network access check
+ * @profile: profile being enforced  (NOT NULL)
+ * @operation: name of the operation being checked  (NOT NULL)
+ * @family: network family
+ * @type:   network type
+ * @protocol: network protocol
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_net_perm(struct aa_profile *profile, char *operation,
+		int family, int type, int protocol)
+{
+	u16 family_mask;
+	struct aa_audit_net sa = {
+		.base.operation = operation,
+		.base.gfp_mask = GFP_KERNEL,
+		.family = family,
+		.type = type,
+		.protocol = protocol,
+	};
+
+	if ((family < 0) || (family >= AF_MAX))
+		return -EINVAL;
+
+	if ((type < 0) || (type >= SOCK_MAX))
+		return -EINVAL;
+
+	/* unix domain and netlink sockets are handled by ipc */
+	if (family == AF_UNIX || family == AF_NETLINK)
+		return 0;
+
+	family_mask = profile->net.allowed[family];
+
+	sa.base.error = (family_mask & (1 << type)) ? 0 : -EACCES;
+
+	return aa_audit_net(profile, &sa);
+}
+
+/**
+ * aa_revalidate_sk - Revalidate access to a sock
+ * @sk: sock being revalidated  (NOT NULL)
+ * @operation: name of operation being checked  (NOT NULL)
+ *
+ * Returns: %0 else error if permission denied
+ */
+int aa_revalidate_sk(struct sock *sk, char *operation)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	/* aa_revalidate_sk should not be called from interrupt context
+	 * don't mediate these calls as they are not task related
+	 */
+	if (in_interrupt())
+		return 0;
+
+	profile = __aa_current_profile();
+	if (!unconfined(profile))
+		error = aa_net_perm(profile, operation,
+				    sk->sk_family, sk->sk_type,
+				    sk->sk_protocol);
+
+	return error;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/sid.c
+++ linux-ec2-2.6.32/security/apparmor/sid.c
@@ -0,0 +1,55 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor security identifier (sid) manipulation fns
+ *
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * AppArmor allocates a unique sid for every profile loaded.  If a profile
+ * is replaced it receive the sid of the profile it is replacing.
+ *
+ * The sid value of 0 is invalid.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include "include/sid.h"
+
+/* global counter from which sids are allocated */
+static u32 global_sid;
+static DEFINE_SPINLOCK(sid_lock);
+
+/* TODO FIXME: add sid to profile mapping, and sid recycling */
+
+/**
+ * aa_alloc_sid - allocate a new sid for a profile
+ */
+u32 aa_alloc_sid(void)
+{
+	u32 sid;
+
+	/*
+	 * TODO FIXME: sid recycling - part of profile mapping table
+	 */
+	spin_lock(&sid_lock);
+	sid = (++global_sid);
+	spin_unlock(&sid_lock);
+	return sid;
+}
+
+/**
+ * aa_free_sid - free a sid
+ * @sid: sid to free
+ */
+void aa_free_sid(u32 sid)
+{
+	;			/* NOP ATM */
+}
--- linux-ec2-2.6.32.orig/security/apparmor/domain.c
+++ linux-ec2-2.6.32/security/apparmor/domain.c
@@ -0,0 +1,796 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy attachment and domain transitions
+ *
+ * Copyright (C) 2002-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/errno.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/syscalls.h>
+#include <linux/tracehook.h>
+#include <linux/personality.h>
+
+#include "include/audit.h"
+#include "include/apparmorfs.h"
+#include "include/context.h"
+#include "include/domain.h"
+#include "include/file.h"
+#include "include/ipc.h"
+#include "include/match.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+/**
+ * aa_free_domain_entries - free entries in a domain table
+ * @domain: the domain table to free  (MAYBE NULL)
+ */
+void aa_free_domain_entries(struct aa_domain *domain)
+{
+	int i;
+	if (domain) {
+		if (!domain->table)
+			return;
+
+		for (i = 0; i < domain->size; i++)
+			kzfree(domain->table[i]);
+		kzfree(domain->table);
+		domain->table = NULL;
+	}
+}
+
+/**
+ * aa_may_change_ptraced_domain - check if can change profile on ptraced task
+ * @task: task we want to change profile of   (NOT NULL)
+ * @to_profile: profile to change to  (NOT NULL)
+ *
+ * Check if the task is ptraced and if so if the tracing task is allowed
+ * to trace the new domain
+ *
+ * Returns: %0 or error if change not allowed
+ */
+static int aa_may_change_ptraced_domain(struct task_struct *task,
+					struct aa_profile *to_profile)
+{
+	struct task_struct *tracer;
+	struct cred *cred = NULL;
+	struct aa_profile *tracerp = NULL;
+	int error = 0;
+
+	rcu_read_lock();
+	tracer = tracehook_tracer_task(task);
+	if (tracer) {
+		/* released below */
+		cred = get_task_cred(tracer);
+		tracerp = aa_cred_profile(cred);
+	}
+	rcu_read_unlock();
+
+	/* not ptraced */
+	if (!tracer || unconfined(tracerp))
+		goto out;
+
+	error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
+
+out:
+	if (cred)
+		put_cred(cred);
+
+	return error;
+}
+
+/**
+ * change_profile_perms - find permissions for change_profile
+ * @profile: the current profile  (NOT NULL)
+ * @ns: the namespace being switched to  (NOT NULL)
+ * @name: the name of the profile to change to  (NOT NULL)
+ * @rstate: if !NULL will contain the state the match finished in (MAYBE NULL)
+ *
+ * Returns: permission set
+ */
+static struct file_perms change_profile_perms(struct aa_profile *profile,
+					      struct aa_namespace *ns,
+					      const char *name,
+					      unsigned int *rstate)
+{
+	struct file_perms perms;
+	struct path_cond cond = { };
+	unsigned int state;
+
+	if (unconfined(profile)) {
+		perms.allowed = AA_MAY_CHANGE_PROFILE;
+		perms.xindex = perms.xdelegate = perms.dindex = 0;
+		perms.audit = perms.quiet = perms.kill = 0;
+		if (rstate)
+			*rstate = 0;
+		return perms;
+	} else if (!profile->file.dfa) {
+		return nullperms;
+	} else if ((ns == profile->ns)) {
+		/* try matching against rules with out namespace prependend */
+		perms = aa_str_perms(profile->file.dfa, profile->file.start,
+				     name, &cond, rstate);
+		if (COMBINED_PERM_MASK(perms) & AA_MAY_CHANGE_PROFILE)
+			return perms;
+	}
+
+	/* try matching with namespace name and then profile */
+	state = aa_dfa_match(profile->file.dfa, profile->file.start,
+			     ns->base.name);
+	state = aa_dfa_null_transition(profile->file.dfa, state, 0);
+	return aa_str_perms(profile->file.dfa, state, name, &cond, rstate);
+}
+
+/**
+ * __aa_attach_match_ - find an attachment match
+ * @name - to match against  (NOT NULL)
+ * @head - profile list to walk  (NOT NULL)
+ *
+ * Do a linear search on the profiles in the list.  There is a matching
+ * preference where an exact match is prefered over a name which uses
+ * expressions to match, and matching expressions with the greatest
+ * xmatch_len are prefered.
+ *
+ * Requires: @head not be shared or have appropriate locks held
+ *
+ * Returns: profile or NULL if no match found
+ */
+static struct aa_profile *__aa_attach_match(const char *name,
+					    struct list_head *head)
+{
+	int len = 0;
+	struct aa_profile *profile, *candidate = NULL;
+
+	list_for_each_entry(profile, head, base.list) {
+		if (profile->flags & PFLAG_NULL)
+			continue;
+		if (profile->xmatch && profile->xmatch_len > len) {
+			unsigned int state = aa_dfa_match(profile->xmatch,
+							  DFA_START, name);
+			u16 perm = dfa_user_allow(profile->xmatch, state);
+			/* any accepting state means a valid match. */
+			if (perm & MAY_EXEC) {
+				candidate = profile;
+				len = profile->xmatch_len;
+			}
+		} else if (!strcmp(profile->base.name, name))
+			/* exact non-re match, no more searching required */
+			return profile;
+	}
+
+	return candidate;
+}
+
+/**
+ * aa_find_attach - do attachment search for unconfined processes
+ * @ns: the current namespace  (NOT NULL)
+ * @list: list to search  (NOT NULL)
+ * @name: the executable name to match against  (NOT NULL)
+ *
+ * Returns: profile or NULL if no match found
+ */
+static struct aa_profile *aa_find_attach(struct aa_namespace *ns,
+					 struct list_head *list,
+					 const char *name)
+{
+	struct aa_profile *profile;
+
+	read_lock(&ns->lock);
+	profile = aa_get_profile(__aa_attach_match(name, list));
+	read_unlock(&ns->lock);
+
+	return profile;
+}
+
+/**
+ * separate_fqname - separate the namespace and profile names
+ * @fqname: the fqname name to split  (NOT NULL)
+ * @ns_name: the namespace name if it exists  (NOT NULL)
+ *
+ * This is the xtable equivalent routine of aa_split_fqname.  It finds the
+ * split in an xtable fqname which contains an embedded \0 instead of a :
+ * if a namespace is specified.  This is done so the xtable is constant and
+ * isn't resplit on every lookup.
+ *
+ * Either the profile or namespace name may be optional but if the namespace
+ * is specified the profile name termination must be present.  This results
+ * in the following possible encodings:
+ * profile_name\0
+ * :ns_name\0profile_name\0
+ * :ns_name\0\0
+ *
+ * NOTE: the xtable fqname is prevalidated at load time in unpack_trans_table
+ *
+ * Returns: profile name if it is specified else NULL
+ */
+static const char *separate_fqname(const char *fqname, const char **ns_name)
+{
+	const char *name;
+
+	if (fqname[0] == ':') {
+		*ns_name = fqname + 1;		/* skip : */
+		name = *ns_name + strlen(*ns_name) + 1;
+		if (!*name)
+			name = NULL;
+	} else {
+		*ns_name = NULL;
+		name = fqname;
+	}
+
+	return name;
+}
+
+static const char *next_name(int xtype, const char *name)
+{
+	return NULL;
+}
+
+/**
+ * x_to_profile - get target profile for a given xindex
+ * @profile: current profile  (NOT NULL)
+ * @name: to to lookup if specified  (NOT NULL)
+ * @xindex: index into x transition table
+ *
+ * find profile for a transition index
+ *
+ * Returns: refcounted profile or NULL if not found available
+ */
+static struct aa_profile *x_to_profile(struct aa_profile *profile,
+				       const char *name, u16 xindex)
+{
+	struct aa_profile *new_profile = NULL;
+	struct aa_namespace *ns = profile->ns;
+	u16 xtype = xindex & AA_X_TYPE_MASK;
+	int index = xindex & AA_X_INDEX_MASK;
+
+	switch (xtype) {
+	case AA_X_NONE:
+		/* fail exec unless ix || ux fallback - handled by caller */
+		return NULL;
+	case AA_X_NAME:
+		if (xindex & AA_X_CHILD)
+			/* released by caller */
+			new_profile = aa_find_attach(ns,
+						     &profile->base.profiles,
+						     name);
+		else
+			/* released by caller */
+			new_profile = aa_find_attach(ns, &ns->base.profiles,
+						     name);
+		/* released by caller */
+		return new_profile;
+	case AA_X_TABLE:
+		/* index is guarenteed to be in range */
+		name = profile->file.trans.table[index];
+		break;
+	}
+
+	for (; !new_profile && name; name = next_name(xtype, name)) {
+		struct aa_namespace *new_ns;
+		const char *xname = NULL;
+
+		new_ns = NULL;
+		if (xindex & AA_X_CHILD) {
+			/* release by caller */
+			new_profile = aa_find_child(profile, name);
+			if (new_profile)
+				return new_profile;
+			continue;
+		} else if (*name == ':') {
+			/* switching namespace */
+			const char *ns_name;
+			xname = name = separate_fqname(name, &ns_name);
+			if (!xname)
+				/* no name so use profile name */
+				xname = profile->base.hname;
+			if (*ns_name == '@') {
+				/* TODO: variable support */
+				;
+			}
+			/* released below */
+			new_ns = aa_find_namespace(ns, ns_name);
+			if (!new_ns)
+				continue;
+		} else if (*name == '@') {
+			/* TODO: variable support */
+			continue;
+		} else {
+			xname = name;
+		}
+
+		/* released by caller */
+		new_profile = aa_find_profile(new_ns ? new_ns : ns, xname);
+		aa_put_namespace(new_ns);
+	}
+
+	/* released by caller */
+	return new_profile;
+}
+
+/**
+ * apparmor_bprm_set_creds - set the new creds on the bprm struct
+ * @bprm: binprm for the exec  (NOT NULL)
+ *
+ * Returns: %0 or error on failure
+ */
+int apparmor_bprm_set_creds(struct linux_binprm *bprm)
+{
+	struct aa_task_cxt *cxt;
+	struct aa_profile *profile, *new_profile = NULL;
+	struct aa_namespace *ns;
+	char *buffer = NULL;
+	unsigned int state;
+	struct path_cond cond = {
+		bprm->file->f_path.dentry->d_inode->i_uid,
+		bprm->file->f_path.dentry->d_inode->i_mode
+	};
+	struct aa_audit_file sa = {
+		.base.operation = "exec",
+		.base.gfp_mask = GFP_KERNEL,
+		.request = MAY_EXEC,
+		.cond = &cond,
+	};
+
+	sa.base.error = cap_bprm_set_creds(bprm);
+	if (sa.base.error)
+		return sa.base.error;
+
+	if (bprm->cred_prepared)
+		return 0;
+
+	cxt = bprm->cred->security;
+	BUG_ON(!cxt);
+
+	profile = aa_get_profile(aa_newest_version(cxt->profile));
+	/*
+	 * get the namespace from the replacement profile as replacement
+	 * can change the namespace
+	 */
+	ns = profile->ns;
+	state = profile->file.start;
+
+	/* buffer freed below, name is pointer inside of buffer */
+	sa.base.error = aa_get_name(&bprm->file->f_path, profile->path_flags,
+				    &buffer, (char **)&sa.name);
+	if (sa.base.error) {
+		if (profile->flags &
+		    (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
+			sa.base.error = 0;
+		sa.base.info = "Exec failed name resolution";
+		sa.name = bprm->filename;
+		goto audit;
+	}
+
+	if (unconfined(profile)) {
+		/* unconfined task - attach profile if one matches */
+		new_profile = aa_find_attach(ns, &ns->base.profiles, sa.name);
+		if (!new_profile)
+			goto cleanup;
+		goto apply;
+	} else if (cxt->onexec) {
+		/*
+		 * onexec permissions are stored in a pair, rewalk the
+		 * dfa to get start of the exec path match.
+		 */
+		sa.perms = change_profile_perms(profile, cxt->onexec->ns,
+						sa.name, &state);
+		state = aa_dfa_null_transition(profile->file.dfa, state, 0);
+	}
+	sa.perms = aa_str_perms(profile->file.dfa, state, sa.name, &cond, NULL);
+	if (cxt->onexec && sa.perms.allowed & AA_MAY_ONEXEC) {
+		/* transfer the onexec reference, this is allowed as the
+		 * cred is being prepared, and isn't committed yet.
+		 */
+		new_profile = cxt->onexec;
+		cxt->onexec = NULL;
+		sa.base.info = "change_profile onexec";
+	} else if (sa.perms.allowed & MAY_EXEC) {
+		new_profile = x_to_profile(profile, sa.name, sa.perms.xindex);
+		if (!new_profile) {
+			if (sa.perms.xindex & AA_X_INHERIT) {
+				/* (p|c|n)ix - don't change profile */
+				sa.base.info = "ix fallback";
+				goto x_clear;
+			} else if (sa.perms.xindex & AA_X_UNCONFINED) {
+				new_profile = aa_get_profile(ns->unconfined);
+				sa.base.info = "ux fallback";
+			} else {
+				sa.base.error = -ENOENT;
+				sa.base.info = "profile not found";
+			}
+		}
+	} else if (COMPLAIN_MODE(profile)) {
+		new_profile = aa_new_null_profile(profile, 0);
+		sa.base.error = -EACCES;
+		if (!new_profile) {
+			sa.base.error = -ENOMEM;
+			sa.base.info = "could not create null profile";
+		} else
+			sa.name2 = new_profile->base.hname;
+		sa.perms.xindex |= AA_X_UNSAFE;
+	} else {
+		sa.base.error = -EACCES;
+	}
+
+	if (!new_profile)
+		goto audit;
+
+	if (profile == new_profile)
+		goto abort;
+
+	if (bprm->unsafe & LSM_UNSAFE_SHARE) {
+		/* FIXME: currently don't mediate shared state */
+		;
+	}
+
+	if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
+		sa.base.error = aa_may_change_ptraced_domain(current,
+							     new_profile);
+		if (sa.base.error)
+			goto abort;
+	}
+
+	/* Determine if secure exec is needed.
+	 * Can be at this point for the following reasons:
+	 * 1. unconfined switching to confined
+	 * 2. confined switching to different confinement
+	 * 3. confined switching to unconfined
+	 *
+	 * Cases 2 and 3 are marked as requiring secure exec
+	 * (unless policy specified "unsafe exec")
+	 *
+	 * bprm->unsafe is used to cache the AA_X_UNSAFE permission
+	 * to avoid having to recompute in secureexec
+	 */
+	if (!(sa.perms.xindex & AA_X_UNSAFE)) {
+		AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
+			 sa.name, new_profile->base.hname);
+		bprm->unsafe |= AA_SECURE_X_NEEDED;
+	}
+apply:
+	sa.name2 = new_profile->base.hname;
+	/* When switching namespace ensure its part of audit message */
+	if (new_profile->ns != ns)
+		sa.name3 = new_profile->ns->base.hname;
+
+	/* when transitioning profiles clear unsafe personality bits */
+	bprm->per_clear |= PER_CLEAR_ON_SETID;
+
+	aa_put_profile(cxt->profile);
+	/* transfer new profile reference will be released when cxt is freed */
+	cxt->profile = new_profile;
+
+x_clear:
+	aa_put_profile(cxt->previous);
+	aa_put_profile(cxt->onexec);
+	cxt->previous = NULL;
+	cxt->onexec = NULL;
+	cxt->token = 0;
+
+audit:
+	sa.base.error = aa_audit_file(profile, &sa);
+
+cleanup:
+	aa_put_profile(profile);
+	kfree(buffer);
+
+	return sa.base.error;
+
+abort:
+	aa_put_profile(new_profile);
+	goto audit;
+}
+
+/**
+ * apparmor_bprm_secureexec - determine if secureexec is needed
+ * @bprm: binprm for exec  (NOT NULL)
+ *
+ * Returns: %1 if secureexec is needed else %0
+ */
+int apparmor_bprm_secureexec(struct linux_binprm *bprm)
+{
+	int ret = cap_bprm_secureexec(bprm);
+
+	/* the decision to use secure exec is computed in set_creds
+	 * and stored in bprm->unsafe.
+	 */
+	if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
+		ret = 1;
+
+	return ret;
+}
+
+/**
+ * apparmor_bprm_committing_creds - do task cleanup on committing new creds
+ * @bprm: binprm for the exec  (NOT NULL)
+ */
+void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
+{
+	struct aa_profile *profile = __aa_current_profile();
+	struct aa_task_cxt *new_cxt = bprm->cred->security;
+
+	/* bail out if unconfined or not changing profile */
+	if ((new_cxt->profile == profile) ||
+	    (unconfined(new_cxt->profile)))
+		return;
+
+	current->pdeath_signal = 0;
+
+	/* reset soft limits and set hard limits for the new profile */
+	__aa_transition_rlimits(profile, new_cxt->profile);
+}
+
+/**
+ * apparmor_bprm_commited_cred - do cleanup after new creds committed
+ * @bprm: binprm for the exec  (NOT NULL)
+ */
+void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
+{
+	/* TODO: cleanup signals - ipc mediation */
+	return;
+}
+
+/*
+ * Functions for self directed profile change
+ */
+
+/**
+ * new_compound_name - create an hname with @n2 appended to @n1
+ * @n1: base of hname  (NOT NULL)
+ * @n2: name to append (NOT NULL)
+ *
+ * Returns: new name or NULL on error
+ */
+static char *new_compound_name(const char *n1, const char *n2)
+{
+	char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
+	if (name)
+		sprintf(name, "%s//%s", n1, n2);
+	return name;
+}
+
+/**
+ * aa_change_hat - change hat to/from subprofile
+ * @hats: vector of hat names to try changing into (unused if @count == 0)
+ * @count: number of hat names in @hats
+ * @token: magic value to validate the hat change
+ * @permtest: true if this is just a permission test
+ *
+ * Change to the first profile specified in @hats that exists, and store
+ * the @hat_magic in the current task context.  If the count == 0 and the
+ * @token matches that stored in the current task context, return to the
+ * top level profile.
+ *
+ * Returns %0 on success, error otherwise.
+ */
+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
+{
+	const struct cred *cred;
+	struct aa_task_cxt *cxt;
+	struct aa_profile *profile, *previous_profile, *hat = NULL;
+	struct aa_audit_file sa = {
+		.base.gfp_mask = GFP_KERNEL,
+		.base.operation = "change_hat",
+		.request = AA_MAY_CHANGEHAT,
+	};
+	char *name = NULL;
+	int i;
+
+	/* released below */
+	cred = get_current_cred();
+	cxt = cred->security;
+	profile = aa_cred_profile(cred);
+	previous_profile = cxt->previous;
+
+	if (unconfined(profile)) {
+		sa.base.info = "unconfined";
+		sa.base.error = -EPERM;
+		goto audit;
+	}
+
+	if (count) {
+		/* attempting to change into a new hat or switch to a sibling */
+		struct aa_profile *root;
+		root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
+		sa.name2 = profile->ns->base.hname;
+
+		/* find first matching hat */
+		for (i = 0; i < count && !hat; i++)
+			/* released below */
+			hat = aa_find_child(root, hats[i]);
+		if (!hat) {
+			if (!COMPLAIN_MODE(root) || permtest) {
+				sa.base.info = "hat not found";
+				if (list_empty(&root->base.profiles))
+					sa.base.error = -ECHILD;
+				else
+					sa.base.error = -ENOENT;
+				goto out;
+			}
+
+			/*
+			 * In complain mode and failed to match any hats.
+			 * Audit the failure based off of the first hat
+			 * supplied.  This is done due how userspace
+			 * interacts with change_hat.
+			 *
+			 * TODO: Add logging of all failed hats
+			 */
+
+			/* freed below */
+			name = new_compound_name(root->base.hname, hats[0]);
+			sa.name = name;
+			/* released below */
+			hat = aa_new_null_profile(profile, 1);
+			if (!hat) {
+				sa.base.info = "failed null profile create";
+				sa.base.error = -ENOMEM;
+				goto audit;
+			}
+		} else {
+			sa.name = hat->base.hname;
+			if (!PROFILE_IS_HAT(hat)) {
+				sa.base.info = "target not hat";
+				sa.base.error = -EPERM;
+				goto audit;
+			}
+		}
+
+		sa.base.error = aa_may_change_ptraced_domain(current, hat);
+		if (sa.base.error) {
+			sa.base.info = "ptraced";
+			sa.base.error = -EPERM;
+			goto audit;
+		}
+
+		if (!permtest) {
+			sa.base.error = aa_set_current_hat(hat, token);
+			if (sa.base.error == -EACCES)
+				/* kill task incase of brute force attacks */
+				sa.perms.kill = AA_MAY_CHANGEHAT;
+			else if (name && !sa.base.error)
+				/* reset error for learning of new hats */
+				sa.base.error = -ENOENT;
+		}
+	} else if (previous_profile) {
+		/* Return to saved profile.  Kill task if restore fails
+		 * to avoid brute force attacks
+		 */
+		sa.name = previous_profile->base.hname;
+		sa.base.error = aa_restore_previous_profile(token);
+		sa.perms.kill = AA_MAY_CHANGEHAT;
+	} else
+		/* ignore restores when there is no saved profile */
+		goto out;
+
+audit:
+	if (!permtest)
+		sa.base.error = aa_audit_file(profile, &sa);
+
+out:
+	aa_put_profile(hat);
+	kfree(name);
+	put_cred(cred);
+
+	return sa.base.error;
+}
+
+/**
+ * aa_change_profile - perform a one-way profile transition
+ * @ns_name: name of the profile namespace to change to
+ * @hname: name of profile to change to
+ * @onexec: whether this transition is to take place immediately or at exec
+ * @permtest: true if this is just a permission test
+ *
+ * Change to new profile @name.  Unlike with hats, there is no way
+ * to change back.  If @onexec then the transition is delayed until
+ * the next exec.
+ *
+ * Returns %0 on success, error otherwise.
+ */
+int aa_change_profile(const char *ns_name, const char *hname, int onexec,
+		      bool permtest)
+{
+	const struct cred *cred;
+	struct aa_task_cxt *cxt;
+	struct aa_profile *profile, *target = NULL;
+	struct aa_namespace *ns = NULL;
+	struct aa_audit_file sa = {
+		.request = AA_MAY_CHANGE_PROFILE,
+		.base.gfp_mask = GFP_KERNEL,
+	};
+
+	if (!hname && !ns_name)
+		return -EINVAL;
+
+	if (onexec)
+		sa.base.operation = "change_onexec";
+	else
+		sa.base.operation = "change_profile";
+
+	cred = get_current_cred();
+	cxt = cred->security;
+	profile = aa_cred_profile(cred);
+
+	if (ns_name) {
+		/* released below */
+		ns = aa_find_namespace(profile->ns, ns_name);
+		if (!ns) {
+			/* we don't create new namespace in complain mode */
+			sa.name2 = ns_name;
+			sa.base.info = "namespace not found";
+			sa.base.error = -ENOENT;
+			goto audit;
+		}
+		sa.name2 = ns->base.hname;
+	} else {
+		/* released below */
+		ns = aa_get_namespace(profile->ns);
+		sa.name2 = ns->base.hname;
+	}
+
+	/* if the name was not specified, use the name of the current profile */
+	if (!hname) {
+		if (unconfined(profile))
+			hname = ns->unconfined->base.hname;
+		else
+			hname = profile->base.hname;
+	}
+	sa.name = hname;
+
+	sa.perms = change_profile_perms(profile, ns, hname, NULL);
+	if (!(sa.perms.allowed & AA_MAY_CHANGE_PROFILE)) {
+		sa.base.error = -EACCES;
+		goto audit;
+	}
+
+	/* released below */
+	target = aa_find_profile(ns, hname);
+	if (!target) {
+		sa.base.info = "profile not found";
+		sa.base.error = -ENOENT;
+		if (permtest || !COMPLAIN_MODE(profile))
+			goto audit;
+		/* release below */
+		target = aa_new_null_profile(profile, 0);
+		if (!target) {
+			sa.base.info = "failed null profile create";
+			sa.base.error = -ENOMEM;
+			goto audit;
+		}
+	}
+
+	/* check if tracing task is allowed to trace target domain */
+	sa.base.error = aa_may_change_ptraced_domain(current, target);
+	if (sa.base.error) {
+		sa.base.info = "ptrace prevents transition";
+		goto audit;
+	}
+
+	if (permtest)
+		goto audit;
+
+	if (onexec)
+		sa.base.error = aa_set_current_onexec(target);
+	else
+		sa.base.error = aa_replace_current_profiles(target);
+
+audit:
+	if (!permtest)
+		sa.base.error = aa_audit_file(profile, &sa);
+
+	aa_put_namespace(ns);
+	aa_put_profile(target);
+	put_cred(cred);
+
+	return sa.base.error;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/apparmorfs.c
+++ linux-ec2-2.6.32/security/apparmor/apparmorfs.c
@@ -0,0 +1,561 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/security/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/apparmorfs.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+/**
+ * kvmalloc - do allocation prefering kmalloc but falling back to vmalloc
+ * @size: size of allocation
+ *
+ * Return: allocated buffer or NULL if failed
+ *
+ * It is possible that policy being loaded from the user is larger than
+ * what can be allocated by kmalloc, in those cases fall back to vmalloc.
+ */
+static void *kvmalloc(size_t size)
+{
+	void *buffer;
+
+	if (size == 0)
+		return NULL;
+
+	buffer = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
+	if (!buffer)
+		buffer = vmalloc(size);
+	return buffer;
+}
+
+/**
+ * kvfree - free an allocation do by kvmalloc
+ * @buffer: buffer to free
+ *
+ * Free a buffer allocated by kvmalloc
+ */
+static void kvfree(void *buffer)
+{
+	if (!buffer)
+		return;
+
+	if (is_vmalloc_addr(buffer))
+		vfree(buffer);
+	else
+		kfree(buffer);
+}
+
+/**
+ * aa_simple_write_to_buffer - common routine for getting policy from user
+ * @userbuf: user buffer to copy data from  (NOT NULL)
+ * @alloc_size: size of user buffer
+ * @copy_size: size of data to copy from user buffer
+ * @pos: position write is at in the file
+ * @operation: name of operation doing the user buffer copy (NOT NULL)
+ *
+ * Returns: kernel buffer containing copy of user buffer data or an
+ *          ERR_PTR on failure.
+ */
+static char *aa_simple_write_to_buffer(const char __user *userbuf,
+				       size_t alloc_size, size_t copy_size,
+				       loff_t *pos, const char *operation)
+{
+	char *data;
+
+	if (*pos != 0) {
+		/* only writes from pos 0, that is complete writes */
+		data = ERR_PTR(-ESPIPE);
+		goto out;
+	}
+
+	/*
+	 * Don't allow profile load/replace/remove from profiles that don't
+	 * have CAP_MAC_ADMIN
+	 */
+	if (!capable(CAP_MAC_ADMIN)) {
+		struct aa_profile *profile = NULL;
+		struct aa_audit sa = {
+			.operation = operation,
+			.gfp_mask = GFP_KERNEL,
+			.error = -EACCES,
+		};
+		profile = aa_current_profile();
+		data = ERR_PTR(aa_audit(AUDIT_APPARMOR_DENIED, profile, &sa,
+					NULL));
+		goto out;
+	}
+	/* freed by caller to aa_simple_write_to_buffer */
+	data = kvmalloc(alloc_size);
+	if (data == NULL) {
+		data = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	if (copy_from_user(data, userbuf, copy_size)) {
+		kvfree(data);
+		data = ERR_PTR(-EFAULT);
+		goto out;
+	}
+
+out:
+	return data;
+}
+
+
+/* .load file hook fn to load policy */
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+			       size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
+
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		error = aa_interface_replace_profiles(data, size, 1);
+		kvfree(data);
+	}
+
+	return error;
+}
+
+static const struct file_operations aa_fs_profile_load = {
+	.write = aa_profile_load
+};
+
+/* .replace file hook fn to load and/or replace policy */
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+				  size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	data = aa_simple_write_to_buffer(buf, size, size, pos,
+					 "profile_replace");
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		error = aa_interface_replace_profiles(data, size, 0);
+		kvfree(data);
+	}
+
+	return error;
+}
+
+static const struct file_operations aa_fs_profile_replace = {
+	.write = aa_profile_replace
+};
+
+/* .remove file hook fn to remove loaded policy */
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+				 size_t size, loff_t *pos)
+{
+	char *data;
+	ssize_t error;
+
+	/*
+	 * aa_remove_profile needs a null terminated string so 1 extra
+	 * byte is allocated and the copied data is null terminated.
+	 */
+	data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
+					 "profile_remove");
+
+	error = PTR_ERR(data);
+	if (!IS_ERR(data)) {
+		data[size] = 0;
+		error = aa_interface_remove_profiles(data, size);
+		kvfree(data);
+	}
+
+	return error;
+}
+
+static const struct file_operations aa_fs_profile_remove = {
+	.write = aa_profile_remove
+};
+
+
+/**
+ * __next_namespace - find the next namespace to list
+ * @root: root namespace to stop search at (NOT NULL)
+ * @ns: current ns position (NOT NULL)
+ *
+ * Find the next namespace from @ns under @root and handle all locking needed
+ * while switching current namespace.
+ *
+ * Returns: next namespace or NULL if at last namespace under @root
+ * NOTE: will not unlock root->lock
+ */
+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
+					     struct aa_namespace *ns)
+{
+	struct aa_namespace *parent;
+
+	/* is next namespace a child */
+	if (!list_empty(&ns->sub_ns)) {
+		struct aa_namespace *next;
+		next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
+		read_lock(&next->lock);
+		return next;
+	}
+
+	/* check if the next ns is a sibling, parent, gp, .. */
+	parent = ns->parent;
+	while (parent) {
+		read_unlock(&ns->lock);
+		list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
+			read_lock(&ns->lock);
+			return ns;
+		}
+		if (parent == root)
+			return NULL;
+		ns = parent;
+		parent = parent->parent;
+	}
+
+	return NULL;
+}
+
+/**
+ * __first_profile - find the first profile in a namespace
+ * @root: namespace that is root of profiles being displayed (NOT NULL)
+ * @ns: namespace to start in   (NOT NULL)
+ *
+ * Returns: unrefcounted profile or NULL if no profile
+ */
+	static struct aa_profile *__first_profile(struct aa_namespace *root,
+						  struct aa_namespace *ns)
+{
+	for ( ; ns; ns = __next_namespace(root, ns)) {
+		if (!list_empty(&ns->base.profiles))
+			return list_first_entry(&ns->base.profiles,
+						struct aa_profile, base.list);
+	}
+	return NULL;
+}
+
+/**
+ * __next_profile - step to the next profile in a profile tree
+ * @profile: current profile in tree (NOT NULL)
+ *
+ * Perform a depth first taversal on the profile tree in a namespace
+ *
+ * Returns: next profile or NULL if done
+ * Requires: profile->ns.lock to be held
+ */
+static struct aa_profile *__next_profile(struct aa_profile *p)
+{
+	struct aa_profile *parent;
+	struct aa_namespace *ns = p->ns;
+
+	/* is next profile a child */
+	if (!list_empty(&p->base.profiles))
+		return list_first_entry(&p->base.profiles, typeof(*p),
+					base.list);
+
+	/* is next profile a sibling, parent sibling, gp, subling, .. */
+	parent = p->parent;
+	while (parent) {
+		list_for_each_entry_continue(p, &parent->base.profiles,
+					     base.list)
+				return p;
+		p = parent;
+		parent = parent->parent;
+	}
+
+	/* is next another profile in the namespace */
+	list_for_each_entry_continue(p, &ns->base.profiles, base.list)
+		return p;
+
+	return NULL;
+}
+
+/**
+ * next_profile - step to the next profile in where ever it may be
+ * @root: root namespace  (NOT NULL)
+ * @profile: current profile  (NOT NULL)
+ *
+ * Returns: next profile or NULL if there isn't one
+ */
+static struct aa_profile *next_profile(struct aa_namespace *root,
+				       struct aa_profile *profile)
+{
+	struct aa_profile *next = __next_profile(profile);
+	if (next)
+		return next;
+
+	/* finished all profiles in namespace move to next namespace */
+	return __first_profile(root, __next_namespace(root, profile->ns));
+}
+
+/**
+ * p_start - start a depth first traversal of profile tree
+ * @f: seq_file to fill
+ * @pos: current position
+ *
+ * Returns: first profile under current namespace or NULL if none found
+ *
+ * acquires first ns->lock
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+	__acquires(root->lock)
+{
+	struct aa_profile *profile = NULL;
+	struct aa_namespace *root = aa_current_profile()->ns;
+	loff_t l = *pos;
+	f->private = aa_get_namespace(root);
+
+
+	/* find the first profile */
+	read_lock(&root->lock);
+	profile = __first_profile(root, root);
+
+	/* skip to position */
+	for (; profile && l > 0; l--)
+		profile = next_profile(root, profile);
+
+	return profile;
+}
+
+/**
+ * p_next - read the next profile entry
+ * @f: seq_file to fill
+ * @p: profile previously returned
+ * @pos: current position
+ *
+ * Returns: next profile after @p or NULL if none
+ *
+ * may acquire/release locks in namespace tree as necessary
+ */
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+	struct aa_profile *profile = p;
+	struct aa_namespace *root = f->private;
+	(*pos)++;
+
+	return next_profile(root, profile);
+}
+
+/**
+ * p_stop - stop depth first traversal
+ * @f: seq_file we are filling
+ * @p: the last profile writen
+ *
+ * Release all locking done by p_start/p_next on namespace tree
+ */
+static void p_stop(struct seq_file *f, void *p)
+	__releases(root->lock)
+{
+	struct aa_profile *profile = p;
+	struct aa_namespace *root = f->private, *ns;
+
+	if (profile) {
+		for (ns = profile->ns; ns && ns != root; ns = ns->parent)
+			read_unlock(&ns->lock);
+	}
+	read_unlock(&root->lock);
+	aa_put_namespace(root);
+}
+
+/**
+ * print_ns_name - print a namespace name back to @root
+ * @root: root namespace to stop at
+ * @ns: namespace to gen name for
+ *
+ * Returns: true if it printed a name
+ */
+static bool print_ns_name(struct seq_file *f, struct aa_namespace *root,
+			  struct aa_namespace *ns)
+{
+	if (!ns || ns == root)
+		return 0;
+
+	if (ns->parent && print_ns_name(f, root, ns->parent))
+		seq_printf(f, "//");
+
+	seq_printf(f, "%s", ns->base.name);
+	return 1;
+}
+
+/**
+ * seq_show_profile - 
+ * @f: seq_file to file
+ * @p: current position (profile)    (NOT NULL)
+ *
+ * Returns: error on failure
+ */
+static int seq_show_profile(struct seq_file *f, void *p)
+{
+	struct aa_profile *profile = (struct aa_profile *)p;
+	struct aa_namespace *root = f->private;
+
+	if (profile->ns != root)
+		seq_printf(f, ":");
+	if (print_ns_name(f, root, profile->ns))
+		seq_printf(f, "://");
+	seq_printf(f, "%s (%s)\n", profile->base.hname,
+		   COMPLAIN_MODE(profile) ? "complain" : "enforce");
+
+	return 0;
+}
+
+static const struct seq_operations aa_fs_profiles_op = {
+	.start = p_start,
+	.next = p_next,
+	.stop = p_stop,
+	.show = seq_show_profile,
+};
+
+static int aa_profiles_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &aa_fs_profiles_op);
+}
+
+static int aa_profiles_release(struct inode *inode, struct file *file)
+{
+	return seq_release(inode, file);
+}
+
+static const struct file_operations aa_fs_profiles_fops = {
+	.open = aa_profiles_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = aa_profiles_release,
+};
+
+
+/** Base file system setup **/
+
+static struct dentry *aa_fs_dentry;
+struct dentry *aa_fs_null;
+struct vfsmount *aa_fs_mnt;
+
+static void aafs_remove(const char *name)
+{
+	struct dentry *dentry;
+
+	dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
+	if (!IS_ERR(dentry)) {
+		securityfs_remove(dentry);
+		dput(dentry);
+	}
+}
+
+/**
+ * aafs_create - create an entry in the apparmor filesystem
+ * @name: name of the entry
+ * @mask: file permission mask of the file
+ * @fops: file operations for the file
+ *
+ * Used aafs_remove to remove entries created with this fn.
+ */
+static int aafs_create(const char *name, int mask,
+		       const struct file_operations *fops)
+{
+	struct dentry *dentry;
+
+	dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
+					NULL, fops);
+
+	return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
+}
+
+/**
+ * aa_destroy_aafs - cleanup and free aafs
+ *
+ * releases dentries allocated by aa_create_aafs
+ */
+void aa_destroy_aafs(void)
+{
+	if (aa_fs_dentry) {
+		aafs_remove(".remove");
+		aafs_remove(".replace");
+		aafs_remove(".load");
+		aafs_remove("profiles");
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+		aafs_remove("matching");
+		aafs_remove("features");
+#endif
+		securityfs_remove(aa_fs_dentry);
+		aa_fs_dentry = NULL;
+	}
+}
+
+/**
+ * aa_create_aafs - create the apparmor security filesystem
+ *
+ * dentries created here are released by aa_destroy_aafs
+ *
+ * Returns: error on failure
+ */
+int aa_create_aafs(void)
+{
+	int error;
+
+	if (!apparmor_initialized)
+		return 0;
+
+	if (aa_fs_dentry) {
+		AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
+		return -EEXIST;
+	}
+
+	aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
+	if (IS_ERR(aa_fs_dentry)) {
+		error = PTR_ERR(aa_fs_dentry);
+		aa_fs_dentry = NULL;
+		goto error;
+	}
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+	error = aafs_create("matching", 0444, &aa_fs_matching_fops);
+	if (error)
+		goto error;
+	error = aafs_create("features", 0444, &aa_fs_features_fops);
+	if (error)
+		goto error;
+#endif
+	error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
+	if (error)
+		goto error;
+	error = aafs_create(".load", 0640, &aa_fs_profile_load);
+	if (error)
+		goto error;
+	error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
+	if (error)
+		goto error;
+	error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
+	if (error)
+		goto error;
+
+	/* TODO: add support for apparmorfs_null and apparmorfs_mnt */
+
+	/* Report that AppArmor fs is enabled */
+	aa_info_message("AppArmor Filesystem Enabled");
+	return 0;
+
+error:
+	aa_destroy_aafs();
+	AA_ERROR("Error creating AppArmor securityfs\n");
+	return error;
+}
+
+fs_initcall(aa_create_aafs);
--- linux-ec2-2.6.32.orig/security/apparmor/resource.c
+++ linux-ec2-2.6.32/security/apparmor/resource.c
@@ -0,0 +1,119 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor resource mediation and attachment
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/audit.h>
+
+#include "include/audit.h"
+#include "include/resource.h"
+#include "include/policy.h"
+
+struct aa_audit_resource {
+	struct aa_audit base;
+
+	int rlimit;
+};
+
+/* audit callback for resource specific fields */
+static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_resource *sa = container_of(va,
+						    struct aa_audit_resource,
+						    base);
+
+	if (sa->rlimit)
+		audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
+}
+
+/**
+ * aa_audit_resource - audit setting resource limit
+ * @profile: profile being enforced  (NOT NULL)
+ * @sa: audit data  (NOT NULL)
+ *
+ * Returns: 0 or sa->error else other error code on failure
+ */
+static int aa_audit_resource(struct aa_profile *profile,
+			     struct aa_audit_resource *sa)
+{
+	return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa->base, audit_cb);
+}
+
+/**
+ * aa_task_setrlimit - test permission to set an rlimit
+ * @profile - profile confining the task  (NOT NULL)
+ * @resource - the resource being set
+ * @new_rlim - the new resource limit  (NOT NULL)
+ *
+ * Control raising the processes hard limit.
+ *
+ * Returns: 0 or error code if setting resource failed
+ */
+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+		      struct rlimit *new_rlim)
+{
+	struct aa_audit_resource sa = {
+		.base.operation = "setrlimit",
+		.base.gfp_mask = GFP_KERNEL,
+		.rlimit = resource + 1,
+	};
+	int error = 0;
+
+	if (profile->rlimits.mask & (1 << resource) &&
+	    new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
+		sa.base.error = -EACCES;
+
+		error = aa_audit_resource(profile, &sa);
+	}
+
+	return error;
+}
+
+/**
+ * __aa_transition_rlimits - apply new profile rlimits
+ * @old: old profile on task  (MAYBE NULL)
+ * @new: new profile with rlimits to apply  (NOT NULL)
+ */
+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
+{
+	unsigned int mask = 0;
+	struct rlimit *rlim, *initrlim;
+	int i;
+
+	/* for any rlimits the profile controlled reset the soft limit
+	 * to the less of the tasks hard limit and the init tasks soft limit
+	 */
+	if (old && old->rlimits.mask) {
+		for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
+			if (old->rlimits.mask & mask) {
+				rlim = current->signal->rlim + i;
+				initrlim = init_task.signal->rlim + i;
+				rlim->rlim_cur = min(rlim->rlim_max,
+						     initrlim->rlim_cur);
+			}
+		}
+	}
+
+	/* set any new hard limits as dictated by the new profile */
+	if (!(new && new->rlimits.mask))
+		return;
+	for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
+		if (!(new->rlimits.mask & mask))
+			continue;
+
+		rlim = current->signal->rlim + i;
+		rlim->rlim_max = min(rlim->rlim_max,
+				     new->rlimits.limits[i].rlim_max);
+		/* soft limit should not exceed hard limit */
+		rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
+	}
+}
--- linux-ec2-2.6.32.orig/security/apparmor/lsm.c
+++ linux-ec2-2.6.32/security/apparmor/lsm.c
@@ -0,0 +1,1079 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor LSM hooks.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/security.h>
+#include <linux/moduleparam.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/ptrace.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/audit.h>
+#include <net/sock.h>
+
+#include "include/apparmor.h"
+#include "include/apparmorfs.h"
+#include "include/audit.h"
+#include "include/capability.h"
+#include "include/context.h"
+#include "include/file.h"
+#include "include/ipc.h"
+#include "include/net.h"
+#include "include/path.h"
+#include "include/policy.h"
+#include "include/procattr.h"
+
+/* Flag indicating whether initialization completed */
+int apparmor_initialized;
+
+/*
+ * LSM hook functions
+ */
+
+/*
+ * free the associated aa_task_cxt and put its profiles
+ */
+static void apparmor_cred_free(struct cred *cred)
+{
+	aa_free_task_context(cred->security);
+	cred->security = NULL;
+}
+
+/*
+ * allocate the apparmor part of blank credentials
+ */
+static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
+{
+	/* freed by apparmor_cred_free */
+	struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
+	if (!cxt)
+		return -ENOMEM;
+
+	cred->security = cxt;
+	return 0;
+}
+
+/*
+ * prepare new aa_task_cxt for modification by prepare_cred block
+ */
+static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
+				 gfp_t gfp)
+{
+	/* freed by apparmor_cred_free */
+	struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
+	if (!cxt)
+		return -ENOMEM;
+
+	aa_dup_task_context(cxt, old->security);
+	new->security = cxt;
+	return 0;
+}
+
+/*
+ * transfer the apparmor data to a blank set of creds
+ */
+static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
+{
+	const struct aa_task_cxt *old_cxt = old->security;
+	struct aa_task_cxt *new_cxt = new->security;
+
+	aa_dup_task_context(new_cxt, old_cxt);
+}
+
+static int apparmor_ptrace_access_check(struct task_struct *child,
+					unsigned int mode)
+{
+	int rc;
+
+	rc = cap_ptrace_access_check(child, mode);
+	if (rc)
+		return rc;
+
+	return aa_ptrace(current, child, mode);
+}
+
+static int apparmor_ptrace_traceme(struct task_struct *parent)
+{
+	return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
+}
+
+/* Derived from security/commoncap.c:cap_capget */
+static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
+			   kernel_cap_t *inheritable, kernel_cap_t *permitted)
+{
+	struct aa_profile *profile;
+	const struct cred *cred;
+
+	rcu_read_lock();
+	cred = __task_cred(target);
+	profile = aa_cred_profile(cred);
+
+	*effective = cred->cap_effective;
+	*inheritable = cred->cap_inheritable;
+	*permitted = cred->cap_permitted;
+
+	if (!unconfined(profile))
+		*effective = cap_intersect(*effective, profile->caps.allowed);
+	rcu_read_unlock();
+
+	return 0;
+}
+
+static int apparmor_capable(struct task_struct *task, const struct cred *cred,
+			    int cap, int audit)
+{
+	struct aa_profile *profile;
+	/* cap_capable returns 0 on success, else -EPERM */
+	int error = cap_capable(task, cred, cap, audit);
+
+	profile = aa_cred_profile(cred);
+	if (!error  && !unconfined(profile))
+		error = aa_capable(task, profile, cap, audit);
+
+	return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+	int error = 0;
+	struct aa_profile *profile = aa_current_profile();
+
+	if (!unconfined(profile)) {
+		char *buffer, *name;
+		int mask;
+
+		mask = 0;
+		if (op & 4)
+			mask |= MAY_READ;
+		if (op & 2)
+			mask |= MAY_WRITE;
+
+		error = -ENOMEM;
+		/* freed below */
+		buffer = (char *)__get_free_page(GFP_KERNEL);
+		if (!buffer)
+			goto out;
+
+		/*
+		 * TODO: convert this over to using a global or per
+		 * namespace control instead of a hard coded /proc
+		 */
+		name = sysctl_pathname(table, buffer, PAGE_SIZE);
+		if (name && name - buffer >= 5) {
+			struct path_cond cond = { 0, S_IFREG };
+			name -= 5;
+			memcpy(name, "/proc", 5);
+			error = aa_pathstr_perm(profile, "sysctl", name, mask,
+						&cond);
+		}
+		free_page((unsigned long)buffer);
+	}
+
+out:
+	return error;
+}
+
+/**
+ * common_perm - basic common permission check wrapper fn for paths
+ * @op: operation name  (NOT NULL)
+ * @path: path to check permission of  (NOT NULL)
+ * @mask: requested permissions mask
+ * @cond: conditional info for the permission request  (NOT NULL)
+ *
+ * Returns: %0 else error code if error or permission denied
+ */
+static int common_perm(const char *op, struct path *path, u16 mask,
+		       struct path_cond *cond)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	profile = __aa_current_profile();
+	if (!unconfined(profile))
+		error = aa_path_perm(profile, op, path, mask, cond);
+
+	return error;
+}
+
+/**
+ * common_perm_dentry - common permission wrapper when path is dir, dentry
+ * @op: operation name  (NOT NULL)
+ * @dir: directory of the dentry  (NOT NULL)
+ * @dentry: dentry to check  (NOT NULL)
+ * @mask: requested permissions mask
+ * @cond: conditional info for the permission request  (NOT NULL)
+ *
+ * Returns: %0 else error code if error or permission denied
+ */
+static int common_perm_dentry(const char *op, struct path *dir,
+			      struct dentry *dentry, u16 mask,
+			      struct path_cond *cond)
+{
+	struct path path = { dir->mnt, dentry };
+
+	return common_perm(op, &path, mask, cond);
+}
+
+/**
+ * common_perm_rm - common permission wrapper for operations doing rm
+ * @op: operation name  (NOT NULL)
+ * @dir: directory that the dentry is in  (NOT NULL)
+ * @dentry: dentry being rm'd  (NOT NULL)
+ * @mask: requested permission mask
+ *
+ * Returns: %0 else error code if error or permission denied
+ */
+static int common_perm_rm(const char *op, struct path *dir,
+			  struct dentry *dentry, u16 mask)
+{
+	struct inode *inode = dentry->d_inode;
+	struct path_cond cond = { };
+
+	if (!dir->mnt || !inode || !mediated_filesystem(inode))
+		return 0;
+
+	cond.uid = inode->i_uid;
+	cond.mode = inode->i_mode;
+
+	return common_perm_dentry(op, dir, dentry, mask, &cond);
+}
+
+/**
+ * common_perm_create - common permission wrapper for operations doing create
+ * @op: operation name  (NOT NULL)
+ * @dir: directory that dentry will be created in  (NOT NULL)
+ * @dentry: dentry to create   (NOT NULL)
+ * @mask: request permission mask
+ * @mode: created file mode
+ *
+ * Returns: %0 else error code if error or permission denied
+ */
+static int common_perm_create(const char *op, struct path *dir,
+			      struct dentry *dentry, u16 mask, umode_t mode)
+{
+	struct path_cond cond = { current_fsuid(), mode };
+
+	if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
+		return 0;
+
+	return common_perm_dentry(op, dir, dentry, mask, &cond);
+}
+
+static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
+{
+	return common_perm_rm("unlink", dir, dentry, AA_MAY_DELETE);
+}
+
+static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
+			       int mode)
+{
+	return common_perm_create("mkdir", dir, dentry, AA_MAY_CREATE, S_IFDIR);
+}
+
+static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
+{
+	return common_perm_rm("rmdir", dir, dentry, AA_MAY_DELETE);
+}
+
+static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
+			       int mode, unsigned int dev)
+{
+	return common_perm_create("mknod", dir, dentry, AA_MAY_CREATE, mode);
+}
+
+static int apparmor_path_truncate(struct path *path, loff_t length,
+				  unsigned int time_attrs)
+{
+	struct path_cond cond = { path->dentry->d_inode->i_uid,
+				  path->dentry->d_inode->i_mode
+	};
+
+	if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
+		return 0;
+	return common_perm("truncate", path, MAY_WRITE, &cond);
+}
+
+static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
+				 const char *old_name)
+{
+	return common_perm_create("symlink_create", dir, dentry, AA_MAY_CREATE,
+				  S_IFLNK);
+}
+
+static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
+			      struct dentry *new_dentry)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mediated_filesystem(old_dentry->d_inode))
+		return 0;
+
+	profile = aa_current_profile();
+	if (!unconfined(profile))
+		error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
+	return error;
+}
+
+static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
+				struct path *new_dir, struct dentry *new_dentry)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mediated_filesystem(old_dentry->d_inode))
+		return 0;
+
+	profile = aa_current_profile();
+	if (!unconfined(profile)) {
+		struct path old_path = { old_dir->mnt, old_dentry };
+		struct path new_path = { new_dir->mnt, new_dentry };
+		struct path_cond cond = { old_dentry->d_inode->i_uid,
+					  old_dentry->d_inode->i_mode
+		};
+
+		error = aa_path_perm(profile, "rename_src", &old_path,
+				     MAY_READ | MAY_WRITE, &cond);
+		if (!error)
+			error = aa_path_perm(profile, "rename_dest", &new_path,
+					     AA_MAY_CREATE | MAY_WRITE, &cond);
+
+	}
+	return error;
+}
+
+static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+			       mode_t mode)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mediated_filesystem(dentry->d_inode))
+		return 0;
+
+	profile = aa_current_profile();
+	if (!unconfined(profile)) {
+		struct path path = { mnt, dentry };
+		struct path_cond cond = { dentry->d_inode->i_uid,
+					  dentry->d_inode->i_mode
+		};
+
+		error = aa_path_perm(profile, "chmod", &path, AA_MAY_CHMOD,
+			&cond);
+	}
+
+	return error;
+}
+
+static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (!mediated_filesystem(path->dentry->d_inode))
+		return 0;
+
+	profile = aa_current_profile();
+	if (!unconfined(profile)) {
+		struct path_cond cond =  { path->dentry->d_inode->i_uid,
+					   path->dentry->d_inode->i_mode
+		};
+		error = aa_path_perm(profile, "chown", path, AA_MAY_CHOWN,
+				     &cond);
+	}
+
+	return error;
+}
+
+static int apparmor_dentry_open(struct file *file, const struct cred *cred)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	/* If in exec, permission is handled by bprm hooks */
+	if (current->in_execve ||
+	    !mediated_filesystem(file->f_path.dentry->d_inode))
+		return 0;
+
+	profile = aa_cred_profile(cred);
+	if (!unconfined(profile)) {
+		struct aa_file_cxt *fcxt = file->f_security;
+		struct inode *inode = file->f_path.dentry->d_inode;
+		struct path_cond cond = { inode->i_uid, inode->i_mode };
+
+		error = aa_path_perm(profile, "open", &file->f_path,
+				     aa_map_file_to_perms(file), &cond);
+		/* released by aa_free_file_context */
+		fcxt->profile = aa_get_profile(profile);
+		/* todo cache actual allowed permissions */
+		fcxt->allowed = aa_map_file_to_perms(file);
+	}
+
+	return error;
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+	/* freed by apparmor_file_free_security */
+	file->f_security = aa_alloc_file_context(GFP_KERNEL);
+	if (!file->f_security)
+		return -ENOMEM;
+	return 0;
+
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+	struct aa_file_cxt *cxt = file->f_security;
+
+	aa_free_file_context(cxt);
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+	/*
+	 * TODO: cache profiles that have revalidated?
+	 */
+	struct aa_file_cxt *fcxt = file->f_security;
+	struct aa_profile *profile, *fprofile = aa_newest_version(fcxt->profile);
+	int error = 0;
+
+	if (!fprofile || !file->f_path.mnt ||
+	    !mediated_filesystem(file->f_path.dentry->d_inode))
+		return 0;
+
+	profile = __aa_current_profile();
+
+	if (!unconfined(profile) &&
+	    ((fprofile != profile) || (mask & ~fcxt->allowed)))
+		error = aa_file_perm(profile, "file_perm", file, mask);
+
+	return error;
+}
+
+static int common_file_perm(const char *op, struct file *file, u16 mask)
+{
+	const struct aa_file_cxt *fcxt = file->f_security;
+	struct aa_profile *profile, *fprofile = fcxt->profile;
+	int error = 0;
+
+	if (!fprofile || !file->f_path.mnt ||
+	    !mediated_filesystem(file->f_path.dentry->d_inode))
+		return 0;
+
+	profile = aa_current_profile();
+	if (!unconfined(profile) && ((fprofile != profile) ||
+				     (mask & ~fcxt->allowed)))
+		error = aa_file_perm(profile, op, file, mask);
+
+	return error;
+}
+
+static int apparmor_file_lock(struct file *file, unsigned int cmd)
+{
+	u16 mask = AA_MAY_LOCK;
+
+	if (cmd == F_WRLCK)
+		mask |= MAY_WRITE;
+
+	return common_file_perm("file_lock", file, mask);
+}
+
+static int common_mmap(struct file *file, const char *operation,
+		       unsigned long prot, unsigned long flags)
+{
+	struct dentry *dentry;
+	int mask = 0;
+
+	if (!file || !file->f_security)
+		return 0;
+
+	if (prot & PROT_READ)
+		mask |= MAY_READ;
+	/*
+	 * Private mappings don't require write perms since they don't
+	 * write back to the files
+	 */
+	if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
+		mask |= MAY_WRITE;
+	if (prot & PROT_EXEC)
+		mask |= AA_EXEC_MMAP;
+
+	dentry = file->f_path.dentry;
+	return common_file_perm(operation, file, mask);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+			      unsigned long prot, unsigned long flags,
+			      unsigned long addr, unsigned long addr_only)
+{
+	int rc = 0;
+
+	/* do DAC check */
+	rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
+	if (rc || addr_only)
+		return rc;
+
+	return common_mmap(file, "file_mmap", prot, flags);
+}
+
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
+				  unsigned long reqprot, unsigned long prot)
+{
+	return common_mmap(vma->vm_file, "file_mprotect", prot,
+			   !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+}
+
+static int apparmor_getprocattr(struct task_struct *task, char *name,
+				char **value)
+{
+	int error = -ENOENT;
+	struct aa_profile *profile;
+	/* released below */
+	const struct cred *cred = get_task_cred(task);
+	struct aa_task_cxt *cxt = cred->security;
+	profile = aa_cred_profile(cred);
+
+	if (strcmp(name, "current") == 0)
+		error = aa_getprocattr(aa_newest_version(cxt->profile),
+				       value);
+	else if (strcmp(name, "prev") == 0  && cxt->previous)
+		error = aa_getprocattr(aa_newest_version(cxt->previous),
+				       value);
+	else if (strcmp(name, "exec") == 0 && cxt->onexec)
+		error = aa_getprocattr(aa_newest_version(cxt->onexec),
+				       value);
+	else
+		error = -EINVAL;
+
+	put_cred(cred);
+
+	return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *task, char *name,
+				void *value, size_t size)
+{
+	char *command, *args;
+	size_t arg_size;
+	int error;
+
+	if (size == 0 || size >= PAGE_SIZE)
+		return -EINVAL;
+
+	/* task can only write its own attributes */
+	if (current != task)
+		return -EACCES;
+
+	args = value;
+	args[size] = '\0';
+	args = strstrip(args);
+	command = strsep(&args, " ");
+	if (!args)
+		return -EINVAL;
+	args = skip_spaces(args);
+	if (!*args)
+		return -EINVAL;
+
+	arg_size = size - (args - (char *) value);
+	if (strcmp(name, "current") == 0) {
+		if (strcmp(command, "changehat") == 0) {
+			error = aa_setprocattr_changehat(args, arg_size,
+							 !AA_DO_TEST);
+		} else if (strcmp(command, "permhat") == 0) {
+			error = aa_setprocattr_changehat(args, arg_size,
+							 AA_DO_TEST);
+		} else if (strcmp(command, "changeprofile") == 0) {
+			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
+							     !AA_DO_TEST);
+		} else if (strcmp(command, "permprofile") == 0) {
+			error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
+							     AA_DO_TEST);
+		} else if (strcmp(command, "permipc") == 0) {
+			error = aa_setprocattr_permipc(args);
+		} else {
+			struct aa_audit sa = {
+				.operation = "setprocattr",
+				.gfp_mask = GFP_KERNEL,
+				.info = name,
+				.error = -EINVAL,
+			};
+			return aa_audit(AUDIT_APPARMOR_DENIED, NULL, &sa, NULL);
+		}
+	} else if (strcmp(name, "exec") == 0) {
+		error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
+						     !AA_DO_TEST);
+	} else {
+		/* only support the "current" and "exec" process attributes */
+		return -EINVAL;
+	}
+	if (!error)
+		error = size;
+	return error;
+}
+
+static int apparmor_task_setrlimit(unsigned int resource,
+				   struct rlimit *new_rlim)
+{
+	struct aa_profile *profile = aa_current_profile();
+	int error = 0;
+
+	if (!unconfined(profile))
+		error = aa_task_setrlimit(profile, resource, new_rlim);
+
+	return error;
+}
+
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
+{
+	struct aa_profile *profile;
+	int error = 0;
+
+	if (kern)
+		return 0;
+
+	profile = __aa_current_profile();
+	if (!unconfined(profile))
+		error = aa_net_perm(profile, "socket_create", family,
+				    type, protocol);
+	return error;
+}
+
+static int apparmor_socket_post_create(struct socket *sock, int family,
+				       int type, int protocol, int kern)
+{
+	struct sock *sk = sock->sk;
+
+	if (kern)
+		return 0;
+
+	return aa_revalidate_sk(sk, "socket_post_create");
+}
+
+static int apparmor_socket_bind(struct socket *sock,
+				struct sockaddr *address, int addrlen)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_bind");
+}
+
+static int apparmor_socket_connect(struct socket *sock,
+				   struct sockaddr *address, int addrlen)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_connect");
+}
+
+static int apparmor_socket_listen(struct socket *sock, int backlog)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_listen");
+}
+
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_accept");
+}
+
+static int apparmor_socket_sendmsg(struct socket *sock,
+				   struct msghdr *msg, int size)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_sendmsg");
+}
+
+static int apparmor_socket_recvmsg(struct socket *sock,
+				   struct msghdr *msg, int size, int flags)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_recvmsg");
+}
+
+static int apparmor_socket_getsockname(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getsockname");
+}
+
+static int apparmor_socket_getpeername(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getpeername");
+}
+
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
+				      int optname)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_getsockopt");
+}
+
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
+				      int optname)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_setsockopt");
+}
+
+static int apparmor_socket_shutdown(struct socket *sock, int how)
+{
+	struct sock *sk = sock->sk;
+
+	return aa_revalidate_sk(sk, "socket_shutdown");
+}
+
+static struct security_operations apparmor_ops = {
+	.name =				"apparmor",
+
+	.ptrace_access_check =		apparmor_ptrace_access_check,
+	.ptrace_traceme =		apparmor_ptrace_traceme,
+	.capget =			apparmor_capget,
+	.sysctl =			apparmor_sysctl,
+	.capable =			apparmor_capable,
+
+	.path_link =			apparmor_path_link,
+	.path_unlink =			apparmor_path_unlink,
+	.path_symlink =			apparmor_path_symlink,
+	.path_mkdir =			apparmor_path_mkdir,
+	.path_rmdir =			apparmor_path_rmdir,
+	.path_mknod =			apparmor_path_mknod,
+	.path_rename =			apparmor_path_rename,
+	.path_chmod =			apparmor_path_chmod,
+	.path_chown =			apparmor_path_chown,
+	.path_truncate =		apparmor_path_truncate,
+	.dentry_open =			apparmor_dentry_open,
+
+	.file_permission =		apparmor_file_permission,
+	.file_alloc_security =		apparmor_file_alloc_security,
+	.file_free_security =		apparmor_file_free_security,
+	.file_mmap =			apparmor_file_mmap,
+	.file_mprotect =		apparmor_file_mprotect,
+	.file_lock =			apparmor_file_lock,
+
+	.getprocattr =			apparmor_getprocattr,
+	.setprocattr =			apparmor_setprocattr,
+
+	.socket_create =		apparmor_socket_create,
+	.socket_post_create =		apparmor_socket_post_create,
+	.socket_bind =			apparmor_socket_bind,
+	.socket_connect =		apparmor_socket_connect,
+	.socket_listen =		apparmor_socket_listen,
+	.socket_accept =		apparmor_socket_accept,
+	.socket_sendmsg =		apparmor_socket_sendmsg,
+	.socket_recvmsg =		apparmor_socket_recvmsg,
+	.socket_getsockname =		apparmor_socket_getsockname,
+	.socket_getpeername =		apparmor_socket_getpeername,
+	.socket_getsockopt =		apparmor_socket_getsockopt,
+	.socket_setsockopt =		apparmor_socket_setsockopt,
+	.socket_shutdown =		apparmor_socket_shutdown,
+
+	.cred_alloc_blank =		apparmor_cred_alloc_blank,
+	.cred_free =			apparmor_cred_free,
+	.cred_prepare =			apparmor_cred_prepare,
+	.cred_transfer =		apparmor_cred_transfer,
+
+	.bprm_set_creds =		apparmor_bprm_set_creds,
+	.bprm_committing_creds =	apparmor_bprm_committing_creds,
+	.bprm_committed_creds =		apparmor_bprm_committed_creds,
+	.bprm_secureexec =		apparmor_bprm_secureexec,
+
+	.task_setrlimit =		apparmor_task_setrlimit,
+};
+
+/*
+ * AppArmor sysfs module parameters
+ */
+
+static int param_set_aabool(const char *val, struct kernel_param *kp);
+static int param_get_aabool(char *buffer, struct kernel_param *kp);
+#define param_check_aabool(name, p) __param_check(name, p, int)
+
+static int param_set_aauint(const char *val, struct kernel_param *kp);
+static int param_get_aauint(char *buffer, struct kernel_param *kp);
+#define param_check_aauint(name, p) __param_check(name, p, int)
+
+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
+#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
+
+static int param_set_audit(const char *val, struct kernel_param *kp);
+static int param_get_audit(char *buffer, struct kernel_param *kp);
+#define param_check_audit(name, p) __param_check(name, p, int)
+
+static int param_set_mode(const char *val, struct kernel_param *kp);
+static int param_get_mode(char *buffer, struct kernel_param *kp);
+#define param_check_mode(name, p) __param_check(name, p, int)
+
+/* Flag values, also controllable via /sys/module/apparmor/parameters
+ * We define special types as we want to do additional mediation.
+ */
+
+/* AppArmor global enforcement switch - complain, enforce, kill */
+enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE;
+module_param_call(mode, param_set_mode, param_get_mode,
+		  &aa_g_profile_mode, S_IRUSR | S_IWUSR);
+
+/* Debug mode */
+int aa_g_debug;
+module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
+
+/* Audit mode */
+enum audit_mode aa_g_audit;
+module_param_call(audit, param_set_audit, param_get_audit,
+		  &aa_g_audit, S_IRUSR | S_IWUSR);
+
+/* Determines if audit header is included in audited messages.  This
+ * provides more context if the audit daemon is not running
+ */
+int aa_g_audit_header;
+module_param_named(audit_header, aa_g_audit_header, aabool,
+		   S_IRUSR | S_IWUSR);
+
+/* lock out loading/removal of policy
+ * TODO: add in at boot loading of policy, which is the only way to
+ *       load policy, if lock_policy is set
+ */
+int aa_g_lock_policy;
+module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
+		   S_IRUSR | S_IWUSR);
+
+/* Syscall logging mode */
+int aa_g_logsyscall;
+module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
+
+/* Maximum pathname length before accesses will start getting rejected */
+unsigned int aa_g_path_max = 2 * PATH_MAX;
+module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
+
+/* Determines how paranoid loading of policy is and how much verification
+ * on the loaded policy is done.
+ */
+int aa_g_paranoid_load = 1;
+module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
+		   S_IRUSR | S_IWUSR);
+
+/* Boot time disable flag */
+static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
+
+static int __init apparmor_enabled_setup(char *str)
+{
+	unsigned long enabled;
+	int error = strict_strtoul(str, 0, &enabled);
+	if (!error)
+		apparmor_enabled = enabled ? 1 : 0;
+	return 1;
+}
+
+__setup("apparmor=", apparmor_enabled_setup);
+
+/* set global flag turning off the ability to load policy */
+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	if (aa_g_lock_policy)
+		return -EACCES;
+	return param_set_bool(val, kp);
+}
+
+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	return param_get_bool(buffer, kp);
+}
+
+static int param_set_aabool(const char *val, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	return param_set_bool(val, kp);
+}
+
+static int param_get_aabool(char *buffer, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	return param_get_bool(buffer, kp);
+}
+
+static int param_set_aauint(const char *val, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	return param_set_uint(val, kp);
+}
+
+static int param_get_aauint(char *buffer, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+	return param_get_uint(buffer, kp);
+}
+
+static int param_get_audit(char *buffer, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (!apparmor_enabled)
+		return -EINVAL;
+
+	return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
+}
+
+static int param_set_audit(const char *val, struct kernel_param *kp)
+{
+	int i;
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (!apparmor_enabled)
+		return -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	for (i = 0; i < AUDIT_MAX_INDEX; i++) {
+		if (strcmp(val, audit_mode_names[i]) == 0) {
+			aa_g_audit = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int param_get_mode(char *buffer, struct kernel_param *kp)
+{
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (!apparmor_enabled)
+		return -EINVAL;
+
+	return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
+}
+
+static int param_set_mode(const char *val, struct kernel_param *kp)
+{
+	int i;
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	if (!apparmor_enabled)
+		return -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
+		if (strcmp(val, profile_mode_names[i]) == 0) {
+			aa_g_profile_mode = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * AppArmor init functions
+ */
+
+/**
+ * set_init_cxt - set a task context and profile on the first task.
+ *
+ * TODO: allow setting an alternate profile than unconfined
+ */
+static int __init set_init_cxt(void)
+{
+	struct cred *cred = (struct cred *)current->real_cred;
+	struct aa_task_cxt *cxt;
+
+	cxt = aa_alloc_task_context(GFP_KERNEL);
+	if (!cxt)
+		return -ENOMEM;
+
+	cxt->profile = aa_get_profile(root_ns->unconfined);
+	cred->security = cxt;
+
+	return 0;
+}
+
+static int __init apparmor_init(void)
+{
+	int error;
+
+	if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
+		aa_info_message("AppArmor disabled by boot time parameter\n");
+		apparmor_enabled = 0;
+		return 0;
+	}
+
+	error = aa_alloc_root_ns();
+	if (error) {
+		AA_ERROR("Unable to allocate default profile namespace\n");
+		goto alloc_out;
+	}
+
+	error = set_init_cxt();
+	if (error) {
+		AA_ERROR("Failed to set context on init task\n");
+		goto register_security_out;
+	}
+
+	error = register_security(&apparmor_ops);
+	if (error) {
+		AA_ERROR("Unable to register AppArmor\n");
+		goto register_security_out;
+	}
+
+	/* Report that AppArmor successfully initialized */
+	apparmor_initialized = 1;
+	if (aa_g_profile_mode == APPARMOR_COMPLAIN)
+		aa_info_message("AppArmor initialized: complain mode enabled");
+	else if (aa_g_profile_mode == APPARMOR_KILL)
+		aa_info_message("AppArmor initialized: kill mode enabled");
+	else
+		aa_info_message("AppArmor initialized");
+
+	return error;
+
+register_security_out:
+	aa_free_root_ns();
+
+alloc_out:
+	aa_destroy_aafs();
+
+	apparmor_enabled = 0;
+	return error;
+
+}
+
+security_initcall(apparmor_init);
--- linux-ec2-2.6.32.orig/security/apparmor/context.c
+++ linux-ec2-2.6.32/security/apparmor/context.c
@@ -0,0 +1,226 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor functions used to manipulate object security
+ * contexts.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * AppArmor sets confinement on every task, via the the aa_task_cxt and
+ * the aa_task_cxt profile, both of which are required and are not allowed
+ * to be NULL.  The aa_task_cxt is not reference counted and is unique
+ * to each cred (which is reference count).  The profile pointed to by
+ * the task_cxt is reference counted.
+ *
+ * TODO
+ * If a task uses change_hat it currently does not return to the old
+ * cred or task context but instead creates a new one.  Ideally the task
+ * should return to the previous cred if it has not been modified.
+ *
+ */
+
+#include "include/context.h"
+#include "include/policy.h"
+
+/**
+ * aa_alloc_task_context - allocat a new task_cxt
+ * @flags: gfp flags for allocation
+ *
+ * Returns: allocated buffer or NULL on failure
+ */
+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
+{
+	return kzalloc(sizeof(struct aa_task_cxt), flags);
+}
+
+/**
+ * aa_free_task_context - free a task_cxt
+ * @cxt: task_cxt to free (MAYBE NULL)
+ */
+void aa_free_task_context(struct aa_task_cxt *cxt)
+{
+	if (cxt) {
+		aa_put_profile(cxt->profile);
+		aa_put_profile(cxt->previous);
+		aa_put_profile(cxt->onexec);
+
+		kzfree(cxt);
+	}
+}
+
+/**
+ * aa_dup_task_context - duplicate a task context, incrementing reference counts
+ * @new: a blank task context      (NOT NULL)
+ * @old: the task context to copy  (NOT NULL)
+ */
+void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
+{
+	*new = *old;
+	aa_get_profile(new->profile);
+	aa_get_profile(new->previous);
+	aa_get_profile(new->onexec);
+}
+
+/**
+ * replace_cxt - replace a context profile
+ * @cxt: task context  (NOT NULL)
+ * @profile: profile to replace cxt group  (NOT NULL)
+ *
+ * Replace context grouping profile reference with @profile
+ */
+static void replace_group(struct aa_task_cxt *cxt, struct aa_profile *profile)
+{
+	if (cxt->profile == profile)
+		return;
+
+	BUG_ON(!profile);
+	if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
+		/* if switching to unconfined or a different profile namespace
+		 * clear out context state
+		 */
+		aa_put_profile(cxt->previous);
+		aa_put_profile(cxt->onexec);
+		cxt->previous = NULL;
+		cxt->onexec = NULL;
+		cxt->token = 0;
+	}
+	/* be careful switching cxt->profile, when racing replacement it
+	 * is possible that cxt->profile->replacedby is the reference keeping
+	 * @profile valid, so make sure to get its reference before dropping
+	 * the reference on cxt->profile */
+	aa_get_profile(profile);
+	aa_put_profile(cxt->profile);
+	cxt->profile = profile;
+}
+
+/**
+ * aa_replace_current_profiles - replace the current tasks profiles
+ * @profile: new profile  (NOT NULL)
+ *
+ * Returns: 0 or error on failure
+ */
+int aa_replace_current_profiles(struct aa_profile *profile)
+{
+	struct aa_task_cxt *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	replace_group(cxt, profile);
+	/* todo add user group */
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_set_current_onexec - set the tasks change_profile to happen onexec
+ * @profile: system profile to set at exec  (MAYBE NULL)
+ *
+ * Returns: 0 or error on failure
+ */
+int aa_set_current_onexec(struct aa_profile *profile)
+{
+	struct aa_task_cxt *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	aa_get_profile(profile);
+	aa_put_profile(cxt->onexec);
+	cxt->onexec = profile;
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_set_current_hat - set the current tasks hat
+ * @profile: profile to set as the current hat  (NOT NULL)
+ * @token: token value that must be specified to change from the hat
+ *
+ * Do switch of tasks hat.  If the task is currently in a hat
+ * validate the token to match.
+ *
+ * Returns: 0 or error on failure
+ */
+int aa_set_current_hat(struct aa_profile *profile, u64 token)
+{
+	struct aa_task_cxt *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+	BUG_ON(!profile);
+
+	cxt = new->security;
+	if (!cxt->previous) {
+		cxt->previous = cxt->profile;
+		cxt->token = token;
+	} else if (cxt->token == token) {
+		aa_put_profile(cxt->profile);
+	} else {
+		/* previous_profile && cxt->token != token */
+		abort_creds(new);
+		return -EACCES;
+	}
+	cxt->profile = aa_get_profile(aa_newest_version(profile));
+	/* clear exec on switching context */
+	aa_put_profile(cxt->onexec);
+	cxt->onexec = NULL;
+
+	commit_creds(new);
+	return 0;
+}
+
+/**
+ * aa_restore_previous_profile - exit from hat context restoring the profile
+ * @token: the token that must be matched to exit hat context
+ *
+ * Attempt to return out of a hat to the previous profile.  The token
+ * must match the stored token value.
+ *
+ * Returns: 0 or error of failure
+ */
+int aa_restore_previous_profile(u64 token)
+{
+	struct aa_task_cxt *cxt;
+	struct cred *new = prepare_creds();
+	if (!new)
+		return -ENOMEM;
+
+	cxt = new->security;
+	if (cxt->token != token) {
+		abort_creds(new);
+		return -EACCES;
+	}
+	/* ignore restores when there is no saved profile */
+	if (!cxt->previous) {
+		abort_creds(new);
+		return 0;
+	}
+
+	aa_put_profile(cxt->profile);
+	cxt->profile = aa_newest_version(cxt->previous);
+	BUG_ON(!cxt->profile);
+	if (unlikely(cxt->profile != cxt->previous)) {
+		aa_get_profile(cxt->profile);
+		aa_put_profile(cxt->previous);
+	}
+	/* clear exec && prev information when restoring to previous context */
+	cxt->previous = NULL;
+	cxt->token = 0;
+	aa_put_profile(cxt->onexec);
+	cxt->onexec = NULL;
+
+	commit_creds(new);
+	return 0;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/apparmorfs-24.c
+++ linux-ec2-2.6.32/security/apparmor/apparmorfs-24.c
@@ -0,0 +1,61 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * This file contain functions providing an interface for <= AppArmor 2.4
+ * compatibility.  It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
+ * being set (see Makefile).
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/namei.h>
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/context.h"
+#include "include/policy.h"
+
+
+/* apparmor/matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+				size_t size, loff_t *ppos)
+{
+	const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
+	    "user::other";
+
+	return simple_read_from_buffer(buf, size, ppos, matching,
+				       sizeof(matching) - 1);
+}
+
+const struct file_operations aa_fs_matching_fops = {
+	.read = aa_matching_read,
+};
+
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+				size_t size, loff_t *ppos)
+{
+	const char features[] = "file=3.1 capability=2.0 network=1.0 "
+	    "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
+
+	return simple_read_from_buffer(buf, size, ppos, features,
+				       sizeof(features) - 1);
+}
+
+const struct file_operations aa_fs_features_fops = {
+	.read = aa_features_read,
+};
--- linux-ec2-2.6.32.orig/security/apparmor/file.c
+++ linux-ec2-2.6.32/security/apparmor/file.c
@@ -0,0 +1,556 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor mediation of files
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include "include/apparmor.h"
+#include "include/audit.h"
+#include "include/file.h"
+#include "include/match.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+struct file_perms nullperms;
+
+/**
+ * aa_audit_file_sub_mask - convert a permission mask into string
+ * @buffer: buffer to write string to  (NOT NULL)
+ * @mask: permission mask to convert
+ * @xindex: xindex
+ *
+ * NOTE: caller must make sure buffer is large enough for @mask
+ */
+static void aa_audit_file_sub_mask(char *buffer, u16 mask, u16 xindex)
+{
+	char *m = buffer;
+
+	if (mask & AA_EXEC_MMAP)
+		*m++ = 'm';
+	if (mask & MAY_READ)
+		*m++ = 'r';
+	if (mask & (MAY_WRITE | AA_MAY_CHMOD | AA_MAY_CHOWN))
+		*m++ = 'w';
+	else if (mask & MAY_APPEND)
+		*m++ = 'a';
+	if (mask & AA_MAY_CREATE)
+		*m++ = 'c';
+	if (mask & AA_MAY_DELETE)
+		*m++ = 'd';
+	if (mask & AA_MAY_LINK)
+		*m++ = 'l';
+	if (mask & AA_MAY_LOCK)
+		*m++ = 'k';
+	if (mask & MAY_EXEC)
+		*m++ = 'x';
+	*m++ = '\0';
+}
+
+/**
+ * aa_audit_file_mask - convert mask to owner::other string
+ * @buffer: buffer to write string to (NOT NULL)
+ * @mask: permission mask to convert
+ * @xindex: xindex
+ * @owner: if the mask is for owner or other
+ */
+static void aa_audit_file_mask(struct audit_buffer *ab, u16 mask, int xindex,
+			       int owner)
+{
+	char str[10];
+
+	if (owner) {
+		aa_audit_file_sub_mask(str, mask, xindex);
+		strcat(str, "::");
+	} else {
+		strcpy(str, "::");
+		aa_audit_file_sub_mask(str + 2, mask, xindex);
+	}
+	audit_log_string(ab, str);
+}
+
+/**
+ * file_audit_cb - call back for file specific audit fields
+ * @ab: audit_buffer  (NOT NULL)
+ * @va: audit struct to audit values of  (NOT NULL)
+ */
+static void file_audit_cb(struct audit_buffer *ab, struct aa_audit *va)
+{
+	struct aa_audit_file *sa = container_of(va, struct aa_audit_file, base);
+	u16 denied = sa->request & ~sa->perms.allowed;
+	uid_t fsuid;
+
+	fsuid = current_fsuid();
+
+	if (sa->request & AA_AUDIT_FILE_MASK) {
+		audit_log_format(ab, " requested_mask=");
+		aa_audit_file_mask(ab, sa->request, AA_X_NONE,
+				   fsuid == sa->cond->uid);
+	}
+	if (denied & AA_AUDIT_FILE_MASK) {
+		audit_log_format(ab, " denied_mask=");
+		aa_audit_file_mask(ab, denied, sa->perms.xindex,
+				   fsuid == sa->cond->uid);
+	}
+	if (sa->request & AA_AUDIT_FILE_MASK) {
+		audit_log_format(ab, " fsuid=%d", fsuid);
+		audit_log_format(ab, " ouid=%d", sa->cond->uid);
+	}
+
+	if (sa->name) {
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, sa->name);
+	}
+
+	if (sa->name2) {
+		audit_log_format(ab, " name2=");
+		audit_log_untrustedstring(ab, sa->name2);
+	}
+
+	if (sa->name3) {
+		audit_log_format(ab, " name3=");
+		audit_log_untrustedstring(ab, sa->name3);
+	}
+}
+
+/**
+ * aa_audit_file - handle the auditing of file operations
+ * @profile: the profile being enforced  (NOT NULL)
+ * @sa: file auditing context  (NOT NULL)
+ *
+ * Returns: %0 or error on failure
+ */
+int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa)
+{
+	int type = AUDIT_APPARMOR_AUTO;
+
+	if (likely(!sa->base.error)) {
+		u16 mask = sa->perms.audit;
+
+		if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
+			mask = 0xffff;
+
+		/* mask off perms that are not being force audited */
+		sa->request &= mask;
+
+		if (likely(!sa->request))
+			return 0;
+		type = AUDIT_APPARMOR_AUDIT;
+	} else {
+		/* only report permissions that were denied */
+		sa->request = sa->request & ~sa->perms.allowed;
+
+		if (sa->request & sa->perms.kill)
+			type = AUDIT_APPARMOR_KILL;
+
+		/* quiet known rejects, assumes quiet and kill do not overlap */
+		if ((sa->request & sa->perms.quiet) &&
+		    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
+		    AUDIT_MODE(profile) != AUDIT_ALL)
+			sa->request &= ~sa->perms.quiet;
+
+		if (!sa->request)
+			return COMPLAIN_MODE(profile) ? 0 : sa->base.error;
+	}
+	return aa_audit(type, profile, &sa->base, file_audit_cb);
+}
+
+/**
+ * aa_compute_perms - convert dfa compressed perms to internal perms
+ * @dfa: dfa to compute perms for   (NOT NULL)
+ * @state: state in dfa
+ * @cond:  conditions to consider  (NOT NULL)
+ *
+ * TODO: convert from dfa + state to permission entry, do computation conversion
+ *       at load time.
+ *
+ * Returns: computed permission set
+ */
+static struct file_perms aa_compute_perms(struct aa_dfa *dfa,
+					  unsigned int state,
+					  struct path_cond *cond)
+{
+	struct file_perms perms;
+
+	/* FIXME: change over to new dfa format
+	 * currently file perms are encoded in the dfa, new format
+	 * splits the permissions from the dfa.  This mapping can be
+	 * done at profile load
+	 */
+	perms.kill = 0;
+	perms.dindex = 0;
+
+	if (current_fsuid() == cond->uid) {
+		perms.allowed = dfa_user_allow(dfa, state);
+		perms.audit = dfa_user_audit(dfa, state);
+		perms.quiet = dfa_user_quiet(dfa, state);
+		perms.xindex = dfa_user_xindex(dfa, state);
+	} else {
+		perms.allowed = dfa_other_allow(dfa, state);
+		perms.audit = dfa_other_audit(dfa, state);
+		perms.quiet = dfa_other_quiet(dfa, state);
+		perms.xindex = dfa_other_xindex(dfa, state);
+	}
+	/* in the old mapping MAY_WRITE implies
+	 * AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN */
+	if (perms.allowed & MAY_WRITE)
+		perms.allowed |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
+			AA_MAY_DELETE;
+	if (perms.audit & MAY_WRITE)
+		perms.audit |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
+			AA_MAY_DELETE;
+	if (perms.quiet & MAY_WRITE)
+		perms.quiet |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
+			AA_MAY_DELETE;
+
+	/* in the old mapping AA_MAY_LOCK and link subset are overlayed
+	 * and only determined by which part of a pair they are  in
+	 */
+	if (perms.allowed & AA_MAY_LOCK)
+		perms.allowed |= AA_LINK_SUBSET;
+
+	/* change_profile wasn't determined by ownership in old mapping */
+	if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
+		perms.allowed |= AA_MAY_CHANGE_PROFILE;
+
+	return perms;
+}
+
+/**
+ * aa_str_perms - find permission that match @name
+ * @dfa: to match against  (NOT NULL)
+ * @state: state to start matching in
+ * @name: string to match against dfa  (NOT NULL)
+ * @cond: conditions to consider for permission set computation  (NOT NULL)
+ * @rstate: if !NULL return state match finished in (MAYBE NULL)
+ *
+ * TODO: Update when permission mapping is moved to load time
+ *
+ * Returns: file permission for @name
+ */
+struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
+			       const char *name, struct path_cond *cond,
+			       unsigned int *rstate)
+{
+	unsigned int state;
+	if (!dfa)
+		return nullperms;
+
+	state = aa_dfa_match(dfa, start, name);
+
+	if (rstate)
+		*rstate = state;
+
+	/* TODO: convert to new dfa format */
+
+	return aa_compute_perms(dfa, state, cond);
+}
+
+/**
+ * aa_pathstr_perm - do permission check & audit for @name
+ * @profile: profile being enforced  (NOT NULL)
+ * @op: name of the operation  (NOT NULL)
+ * @name: path string to check permission for  (NOT NULL)
+ * @request: requested permissions
+ * @cond: conditional info for this request  (NOT NULL)
+ *
+ * Do permission check for paths that are predefined.  This fn will
+ * be removed once security_sysctl goes away.
+ *
+ * Returns: %0 else error if access denied or other error
+ */
+int aa_pathstr_perm(struct aa_profile *profile, const char *op,
+		    const char *name, u16 request, struct path_cond *cond)
+{
+	struct aa_audit_file sa = {
+		.base.operation = op,
+		.base.gfp_mask = GFP_KERNEL,
+		.request = request,
+		.name = name,
+		.cond = cond,
+	};
+
+	sa.perms = aa_str_perms(profile->file.dfa, profile->file.start, sa.name,
+				cond,
+				NULL);
+	if (request & ~sa.perms.allowed)
+		sa.base.error = -EACCES;
+	return aa_audit_file(profile, &sa);
+}
+
+/**
+ * aa_path_perm - do permissions check & audit for @path
+ * @profile: profile being enforced  (NOT NULL)
+ * @operation: name of the operation being enforced  (NOT NULL)
+ * @path: path to check permissions of  (NOT NULL)
+ * @request: requested permissions
+ * @cond: conditional info for this request  (NOT NULL)
+ *
+ * Returns: %0 else error if access denied or other error
+ */
+int aa_path_perm(struct aa_profile *profile, const char *operation,
+		 struct path *path, u16 request, struct path_cond *cond)
+{
+	char *buffer, *name;
+	struct aa_audit_file sa = {
+		.base.operation = operation,
+		.base.gfp_mask = GFP_KERNEL,
+		.request = request,
+		.cond = cond,
+	};
+	int flags = profile->path_flags |
+		(S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
+	/* buffer freed below - name is pointer inside buffer */
+	sa.base.error = aa_get_name(path, flags, &buffer, &name);
+	sa.name = name;
+	if (sa.base.error) {
+		sa.perms = nullperms;
+		if (sa.base.error == -ENOENT)
+			sa.base.info = "Failed name lookup - deleted entry";
+		else if (sa.base.error == -ESTALE)
+			sa.base.info = "Failed name lookup - disconnected path";
+		else if (sa.base.error == -ENAMETOOLONG)
+			sa.base.info = "Failed name lookup - name too long";
+		else
+			sa.base.info = "Failed name lookup";
+	} else {
+		sa.perms = aa_str_perms(profile->file.dfa, profile->file.start,
+					sa.name, cond, NULL);
+		if (request & ~sa.perms.allowed)
+			sa.base.error = -EACCES;
+	}
+	sa.base.error = aa_audit_file(profile, &sa);
+	kfree(buffer);
+
+	return sa.base.error;
+}
+
+/**
+ * xindex_is_subset - helper for aa_path_link
+ * @link: link permission set
+ * @target: target permission set
+ *
+ * test target x permissions are equal OR a subset of link x permissions
+ * this is done as part of the subset test, where a hardlink must have
+ * a subset of permissions that the target has.
+ *
+ * Returns: %1 if subset else %0
+ */
+static inline bool xindex_is_subset(u16 link, u16 target)
+{
+	if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
+	    ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
+		return 0;
+
+	return 1;
+}
+
+/**
+ * aa_path_link - Handle hard link permission check
+ * @profile: the profile being enforced  (NOT NULL)
+ * @old_dentry: the target dentry  (NOT NULL)
+ * @new_dir: directory the new link will be created in  (NOT NULL)
+ * @new_dentry: the link being created  (NOT NULL)
+ *
+ * Handle the permission test for a link & target pair.  Permission
+ * is encoded as a pair where the link permission is determined
+ * first, and if allowed, the target is tested.  The target test
+ * is done from the point of the link match (not start of DFA)
+ * making the target permission dependent on the link permission match.
+ *
+ * The subset test if required forces that permissions granted
+ * on link are a subset of the permission granted to target.
+ *
+ * Returns: %0 if allowed else error
+ */
+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
+		 struct path *new_dir, struct dentry *new_dentry)
+{
+	struct path link = { new_dir->mnt, new_dentry };
+	struct path target = { new_dir->mnt, old_dentry };
+	struct path_cond cond = {
+		old_dentry->d_inode->i_uid,
+		old_dentry->d_inode->i_mode
+	};
+	char *buffer = NULL, *buffer2 = NULL;
+	char *lname, *tname;
+	struct file_perms perms;
+	unsigned int state;
+
+	struct aa_audit_file sa = {
+		.base.operation = "link",
+		.base.gfp_mask = GFP_KERNEL,
+		.request = AA_MAY_LINK,
+		.cond = &cond,
+		.perms = nullperms,
+	};
+	/* buffer freed below, lname is pointer in buffer */
+	sa.base.error = aa_get_name(&link, profile->path_flags, &buffer,
+				    &lname);
+	sa.name = lname;
+	if (sa.base.error)
+		goto audit;
+
+	/* buffer2 freed below, tname is pointer in buffer2 */
+	sa.base.error = aa_get_name(&target, profile->path_flags, &buffer2,
+				    &tname);
+	sa.name2 = tname;
+	if (sa.base.error)
+		goto audit;
+
+	sa.base.error = -EACCES;
+
+	/* aa_str_perms - handles the case of the dfa being NULL */
+	sa.perms = aa_str_perms(profile->file.dfa, profile->file.start, lname,
+				&cond, &state);
+	sa.perms.audit &= AA_MAY_LINK;
+	sa.perms.quiet &= AA_MAY_LINK;
+	sa.perms.kill &= AA_MAY_LINK;
+
+	if (!(sa.perms.allowed & AA_MAY_LINK))
+		goto audit;
+
+	/* test to see if target can be paired with link */
+	state = aa_dfa_null_transition(profile->file.dfa, state,
+				       profile->flags & PFLAG_OLD_NULL_TRANS);
+	perms = aa_str_perms(profile->file.dfa, state, tname, &cond, NULL);
+	if (!(perms.allowed & AA_MAY_LINK)) {
+		sa.base.info = "target restricted";
+		goto audit;
+	}
+
+	/* done if link subset test is not required */
+	if (!(perms.allowed & AA_LINK_SUBSET))
+		goto done_tests;
+
+	/* Do link perm subset test requiring allowed permission on link are a
+	 * subset of the allowed permissions on target.
+	 */
+	perms = aa_str_perms(profile->file.dfa, profile->file.start, tname,
+			     &cond, NULL);
+
+	/* AA_MAY_LINK is not considered in the subset test */
+	sa.request = sa.perms.allowed & ~AA_MAY_LINK;
+	sa.perms.allowed &= perms.allowed | AA_MAY_LINK;
+
+	sa.request |= AA_AUDIT_FILE_MASK & (sa.perms.allowed & ~perms.allowed);
+	if (sa.request & ~sa.perms.allowed) {
+		goto audit;
+	} else if ((sa.perms.allowed & MAY_EXEC) &&
+		   !xindex_is_subset(sa.perms.xindex, perms.xindex)) {
+		sa.perms.allowed &= ~MAY_EXEC;
+		sa.request |= MAY_EXEC;
+		sa.base.info = "link not subset of target";
+		goto audit;
+	}
+
+done_tests:
+	sa.base.error = 0;
+
+audit:
+	sa.base.error = aa_audit_file(profile, &sa);
+	kfree(buffer);
+	kfree(buffer2);
+
+	return sa.base.error;
+}
+
+/**
+ * aa_is_deleted_file - test if a file has been completely unlinked
+ * @dentry: dentry of file to test for deletion  (NOT NULL)
+ *
+ * Returns: %1 if deleted else %0
+ */
+static inline bool aa_is_deleted_file(struct dentry *dentry)
+{
+	if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
+		return 1;
+	return 0;
+}
+
+/**
+ * aa_file_common_perm - core permission check & audit for files
+ * @profile: profile being enforced   (NOT NULL)
+ * @operation: name of operation      (NOT NULL)
+ * @file: file to check permissions of  (NOT NULL)
+ * @request: requested permissions
+ * @name: path name to revalidate permission on  (MAYBE NULL if @error != 0)
+ * @error: error result of name lookup when find @name
+ *
+ * Returns: %0 if access allowed else %1
+ */
+static int aa_file_common_perm(struct aa_profile *profile,
+			       const char *operation, struct file *file,
+			       u16 request, const char *name, int error)
+{
+	struct path_cond cond = {
+		.uid = file->f_path.dentry->d_inode->i_uid,
+		.mode = file->f_path.dentry->d_inode->i_mode
+	};
+	struct aa_audit_file sa = {
+		.base.operation = operation,
+		.base.gfp_mask = GFP_KERNEL,
+		.request = request,
+		.base.error = error,
+		.name = name,
+		.cond = &cond,
+	};
+
+	if (sa.base.error) {
+		sa.perms = nullperms;
+		if (sa.base.error == -ENOENT &&
+		    aa_is_deleted_file(file->f_path.dentry)) {
+			/* Access to open files that are deleted are
+			 * give a pass (implicit delegation)
+			 */
+			sa.base.error = 0;
+			sa.perms.allowed = sa.request;
+		} else if (sa.base.error == -ENOENT)
+			sa.base.info = "Failed name lookup - deleted entry";
+		else if (sa.base.error == -ESTALE)
+			sa.base.info = "Failed name lookup - disconnected path";
+		else if (sa.base.error == -ENAMETOOLONG)
+			sa.base.info = "Failed name lookup - name too long";
+		else
+			sa.base.info = "Failed name lookup";
+	} else {
+		sa.perms = aa_str_perms(profile->file.dfa, profile->file.start,
+					sa.name, &cond, NULL);
+		if (request & ~sa.perms.allowed)
+			sa.base.error = -EACCES;
+	}
+	sa.base.error = aa_audit_file(profile, &sa);
+
+	return sa.base.error;
+}
+
+/**
+ * aa_file_perm - do permission revalidation check & audit for @file
+ * @profile: profile being enforced   (NOT NULL)
+ * @operation: name of the operation  (NOT NULL)
+ * @file: file to revalidate access permissions on  (NOT NULL)
+ * @request: requested permissions
+ *
+ * Returns: %0 if access allowed else error
+ */
+int aa_file_perm(struct aa_profile *profile, const char *operation,
+		 struct file *file, u16 request)
+{
+	char *buffer, *name;
+	umode_t mode = file->f_path.dentry->d_inode->i_mode;
+	/* buffer freed below, name is a pointer inside of buffer */
+	int flags = profile->path_flags | (S_ISDIR(mode) ? PATH_IS_DIR : 0);
+	int error = aa_get_name(&file->f_path, flags, &buffer, &name);
+
+	error = aa_file_common_perm(profile, operation, file, request, name,
+				    error);
+	kfree(buffer);
+	return error;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/path.c
+++ linux-ec2-2.6.32/security/apparmor/path.c
@@ -0,0 +1,243 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor function for pathnames
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/mnt_namespace.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/nsproxy.h>
+#include <linux/path.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/fs_struct.h>
+
+#include "include/apparmor.h"
+#include "include/path.h"
+#include "include/policy.h"
+
+/**
+ * d_namespace_path - lookup a name associated with a given path
+ * @path: path to lookup  (NOT NULL)
+ * @buf:  buffer to store path to  (NOT NULL)
+ * @buflen: length of @buf
+ * @name: return pointer for start of path name with in @buf  (NOT NULL)
+ * @flags: flags controling path lookup
+ *
+ * Handle path name lookup.
+ *
+ * Returns: %0 else error code if path lookup fails
+ *          When no error the path name is returned in @name which points to
+ *          to a position in @buf
+ */
+static int d_namespace_path(struct path *path, char *buf, int buflen,
+			    char **name, int flags)
+{
+	struct path root, tmp;
+	char *res;
+	int deleted, connected;
+	int error = 0;
+
+	/* Get the root we want to resolve too */
+	if (flags & PATH_CHROOT_REL) {
+		/* resolve paths relative to chroot */
+		read_lock(&current->fs->lock);
+		root = current->fs->root;
+		/* released below */
+		path_get(&root);
+		read_unlock(&current->fs->lock);
+	} else {
+		/* resolve paths relative to namespace */
+		root.mnt = current->nsproxy->mnt_ns->root;
+		root.dentry = root.mnt->mnt_root;
+		/* released below */
+		path_get(&root);
+	}
+
+	spin_lock(&dcache_lock);
+	/* There is a race window between path lookup here and the
+	 * need to strip the " (deleted) string that __d_path applies
+	 * Detect the race and relookup the path
+	 *
+	 * The stripping of (deleted) is a hack that could be removed
+	 * with an updated __d_path
+	 */
+	do {
+		tmp = root;
+		deleted = d_unlinked(path->dentry);
+		res = __d_path(path, &tmp, buf, buflen);
+
+	} while (deleted != d_unlinked(path->dentry));
+	spin_unlock(&dcache_lock);
+
+	*name = res;
+	/* handle error conditions - and still allow a partial path to
+	 * be returned.
+	 */
+	if (IS_ERR(res)) {
+		error = PTR_ERR(res);
+		*name = buf;
+		goto out;
+	}
+	if (deleted) {
+		/* On some filesystems, newly allocated dentries appear to the
+		 * security_path hooks as a deleted dentry except without an
+		 * inode allocated.
+		 *
+		 * Remove the appended deleted text and return as string for
+		 * normal mediation, or auditing.  The (deleted) string is
+		 * guarenteed to be added in this case, so just strip it.
+		 */
+		buf[buflen - 11] = 0;	/* - (len(" (deleted)") +\0) */
+
+		if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
+			error = -ENOENT;
+			goto out;
+		}
+	}
+
+	/* Determine if the path is connected to the expected root */
+	connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
+
+	/* If the path is not connected, then remove any leading / that
+	 * __d_path may have returned.
+	 * Unless
+	 *     specifically directed to connect the path,
+	 * OR
+	 *     if in a chroot and doing chroot relative paths and the path
+	 *     resolves to the namespace root (would be connected outside
+	 *     of chroot) and specifically directed to connect paths to
+	 *     namespace root.
+	 */
+	if (!connected && 
+	    !(flags & PATH_CONNECT_PATH) &&
+	    !((flags & PATH_CHROOT_REL) && (flags & PATH_CHROOT_NSCONNECT) &&
+	      (tmp.mnt == current->nsproxy->mnt_ns->root &&
+	       tmp.dentry == current->nsproxy->mnt_ns->root->mnt_root))) {
+		/* disconnected path, don't return pathname starting with '/' */
+		error = -ESTALE;
+		if (*res == '/')
+			*name = res + 1;
+	}
+
+out:
+	path_put(&root);
+
+	return error;
+}
+
+/**
+ * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended
+ * @path: path to get name for  (NOT NULL)
+ * @flags: flags controlling path lookup
+ * @buffer: buffer to put name in  (NOT NULL)
+ * @size: size of buffer
+ * @name: on return contains position of path name in @buffer  (NOT NULL)
+ *
+ * Returns: %0 else error on failure
+ */
+static int get_name_to_buffer(struct path *path, int flags, char *buffer,
+			      int size, char **name)
+{
+	int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
+	int error = d_namespace_path(path, buffer, size - adjust, name, flags);
+
+	if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
+		/*
+		 * Append "/" to the pathname.  The root directory is a special
+		 * case; it already ends in slash.
+		 */
+		strcpy(&buffer[size - 2], "/");
+
+	return error;
+}
+
+/**
+ * aa_get_name - compute the pathname of a file
+ * @path: path the file  (NOT NULL)
+ * @flags: flags controling path name generation
+ * @buffer: buffer that aa_get_name() allocated  (NOT NULL)
+ * @name: the generated path name if !error
+ *
+ * @name is a pointer to the beginning of the pathname (which usually differs
+ * from the beginning of the buffer), or NULL.  If there is an error @name
+ * may contain a partial or invalid name that can be used for audit purposes,
+ * but it can not be used for mediation.
+ *
+ * We need PATH_IS_DIR to indicate whether the file is a directory or not
+ * because the file may not yet exist, and so we cannot check the inode's
+ * file type.
+ *
+ * Returns: %0 else error code if could retrieve name
+ */
+int aa_get_name(struct path *path, int flags, char **buffer, char **name)
+{
+	char *buf, *str = NULL;
+	int size = 256;
+	int error;
+
+	*name = NULL;
+	*buffer = NULL;
+	for (;;) {
+		/* freed by caller */
+		buf = kmalloc(size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		error = get_name_to_buffer(path, flags, buf, size, &str);
+		if (!error || (error == -ENOENT) || (error == -ESTALE))
+			break;
+
+		kfree(buf);
+		size <<= 1;
+		if (size > aa_g_path_max)
+			return -ENAMETOOLONG;
+	}
+	*buffer = buf;
+	*name = str;
+
+	return error;
+}
+
+/**
+ * sysctl_pathname - generate a pathname for a sysctl
+ * @table: sysctl name table  (NOT NULL)
+ * @buffer: buffer to put name in  (NOT NULL)
+ * @buflen: length of @buffer
+ *
+ * Returns: sysctl path name in @buffer or NULL on error
+ */
+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
+{
+	if (buflen < 1)
+		return NULL;
+	buffer += --buflen;
+	*buffer = '\0';
+
+	while (table) {
+		int namelen = strlen(table->procname);
+
+		if (buflen < namelen + 1)
+			return NULL;
+		buflen -= namelen + 1;
+		buffer -= namelen;
+		memcpy(buffer, table->procname, namelen);
+		*--buffer = '/';
+		table = table->parent;
+	}
+	if (buflen < 4)
+		return NULL;
+	buffer -= 4;
+	memcpy(buffer, "/sys", 4);
+
+	return buffer;
+}
--- linux-ec2-2.6.32.orig/security/apparmor/include/apparmorfs.h
+++ linux-ec2-2.6.32/security/apparmor/include/apparmorfs.h
@@ -0,0 +1,28 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor filesystem definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_APPARMORFS_H
+#define __AA_APPARMORFS_H
+
+extern struct dentry *aa_fs_null;
+extern struct vfsmount *aa_fs_mnt;
+
+extern void aa_destroy_aafs(void);
+
+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
+extern const struct file_operations aa_fs_matching_fops;
+extern const struct file_operations aa_fs_features_fops;
+#endif
+
+#endif /* __AA_APPARMORFS_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/resource.h
+++ linux-ec2-2.6.32/security/apparmor/include/resource.h
@@ -0,0 +1,45 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor resource limits function defintions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_RESOURCE_H
+#define __AA_RESOURCE_H
+
+#include <linux/resource.h>
+#include <linux/sched.h>
+
+struct aa_profile;
+
+/* struct aa_rlimit - rlimits settings for the profile
+ * @mask: which hard limits to set
+ * @limits: rlimit values that override task limits
+ *
+ * AppArmor rlimits are used to set confined task rlimits.  Only the
+ * limits specified in @mask will be controlled by apparmor.
+ */
+struct aa_rlimit {
+	unsigned int mask;
+	struct rlimit limits[RLIM_NLIMITS];
+};
+
+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
+		      struct rlimit *new_rlim);
+
+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
+
+static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
+{
+	/* NOP */
+}
+
+#endif /* __AA_RESOURCE_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/domain.h
+++ linux-ec2-2.6.32/security/apparmor/include/domain.h
@@ -0,0 +1,36 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor security domain transition function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/binfmts.h>
+#include <linux/types.h>
+
+#ifndef __AA_DOMAIN_H
+#define __AA_DOMAIN_H
+
+struct aa_domain {
+	int size;
+	char **table;
+};
+
+int apparmor_bprm_set_creds(struct linux_binprm *bprm);
+int apparmor_bprm_secureexec(struct linux_binprm *bprm);
+void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
+void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
+
+void aa_free_domain_entries(struct aa_domain *domain);
+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
+int aa_change_profile(const char *ns_name, const char *name, int onexec,
+		      bool permtest);
+
+#endif /* __AA_DOMAIN_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/capability.h
+++ linux-ec2-2.6.32/security/apparmor/include/capability.h
@@ -0,0 +1,45 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor capability mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_CAPABILITY_H
+#define __AA_CAPABILITY_H
+
+#include <linux/sched.h>
+
+struct aa_profile;
+
+/* aa_caps - confinement data for capabilities
+ * @allowed: capabilities mask
+ * @audit: caps that are to be audited
+ * @quiet: caps that should not be audited
+ * @kill: caps that when requested will result in the task being killed
+ * @extended: caps that are subject finer grained mediation
+ */
+struct aa_caps {
+	kernel_cap_t allowed;
+	kernel_cap_t audit;
+	kernel_cap_t quiet;
+	kernel_cap_t kill;
+	kernel_cap_t extended;
+};
+
+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
+	       int audit);
+
+static inline void aa_free_cap_rules(struct aa_caps *caps)
+{
+	/* NOP */
+}
+
+#endif /* __AA_CAPBILITY_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/ipc.h
+++ linux-ec2-2.6.32/security/apparmor/include/ipc.h
@@ -0,0 +1,28 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor ipc mediation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_IPC_H
+#define __AA_IPC_H
+
+#include <linux/sched.h>
+
+struct aa_profile;
+
+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
+		  struct aa_profile *tracee, unsigned int mode);
+
+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
+	      unsigned int mode);
+
+#endif /* __AA_IPC_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/procattr.h
+++ linux-ec2-2.6.32/security/apparmor/include/procattr.h
@@ -0,0 +1,26 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /proc/<pid>/attr/ interface function defintions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_PROCATTR_H
+#define __AA_PROCATTR_H
+
+#define AA_DO_TEST 1
+#define AA_ONEXEC  1
+
+int aa_getprocattr(struct aa_profile *profile, char **string);
+int aa_setprocattr_changehat(char *args, size_t size, int test);
+int aa_setprocattr_changeprofile(char *fqname, int onexec, int test);
+int aa_setprocattr_permipc(char *fqname);
+
+#endif /* __AA_PROCATTR_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/policy.h
+++ linux-ec2-2.6.32/security/apparmor/include/policy.h
@@ -0,0 +1,307 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_POLICY_H
+#define __AA_POLICY_H
+
+#include <linux/capability.h>
+#include <linux/cred.h>
+#include <linux/kref.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+
+#include "apparmor.h"
+#include "audit.h"
+#include "capability.h"
+#include "domain.h"
+#include "file.h"
+#include "net.h"
+#include "resource.h"
+
+extern const char *profile_mode_names[];
+#define APPARMOR_NAMES_MAX_INDEX 3
+
+#define COMPLAIN_MODE(_profile)				\
+	((aa_g_profile_mode == APPARMOR_COMPLAIN) || ((_profile) &&	\
+					(_profile)->mode == APPARMOR_COMPLAIN))
+
+#define DO_KILL(_profile)					\
+	((aa_g_profile_mode == APPARMOR_KILL) || ((_profile) &&	\
+					(_profile)->mode == APPARMOR_KILL))
+
+#define PROFILE_IS_HAT(_profile) \
+	((_profile) && (_profile)->flags & PFLAG_HAT)
+
+/*
+ * FIXME: currently need a clean way to replace and remove profiles as a
+ * set.  It should be done at the namespace level.
+ * Either, with a set of profiles loaded at the namespace level or via
+ * a mark and remove marked interface.
+ */
+enum profile_mode {
+	APPARMOR_ENFORCE,	/* enforce access rules */
+	APPARMOR_COMPLAIN,	/* allow and log access violations */
+	APPARMOR_KILL,		/* kill task on access violation */
+};
+
+enum profile_flags {
+	PFLAG_HAT = 1,			/* profile is a hat */
+	PFLAG_UNCONFINED = 2,		/* profile is the unconfined profile */
+	PFLAG_NULL = 4,			/* profile is null learning profile */
+	PFLAG_IX_ON_NAME_ERROR = 8,	/* fallback to ix on name lookup fail */
+	PFLAG_IMMUTABLE = 0x10,		/* don't allow changes/replacement */
+	PFLAG_USER_DEFINED = 0x20,	/* user based profile */
+	PFLAG_NO_LIST_REF = 0x40,	/* list doesn't keep profile ref */
+	PFLAG_MMAP_MIN_ADDR = 0x80,	/* profile controls mmap_min_addr */
+	PFLAG_OLD_NULL_TRANS = 0x100,	/* use // as the null transition */
+
+	/* These flags must coorespond with PATH_flags */
+	PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
+};
+
+#define AA_NEW_SID 0
+
+struct aa_profile;
+
+/* struct aa_policy - common part of both namespaces and profiles
+ * @name: name of the object
+ * @hname - The hierarchical name
+ * @count: reference count of the obj
+ * @list: list policy object is on
+ * @profiles: head of the profiles list contained in the object
+ */
+struct aa_policy {
+	char *name;
+	char *hname;
+	struct kref count;
+	struct list_head list;
+	struct list_head profiles;
+};
+
+/* struct aa_ns_acct - accounting of profiles in namespace
+ * @max_size: maximum space allowed for all profiles in namespace
+ * @max_count: maximum number of profiles that can be in this namespace
+ * @size: current size of profiles
+ * @count: current count of profiles (includes null profiles)
+ */
+struct aa_ns_acct {
+	int max_size;
+	int max_count;
+	int size;
+	int count;
+};
+
+/* struct aa_namespace - namespace for a set of profiles
+ * @base: common policy
+ * @parent: parent of namespace
+ * @lock: lock for modifying the object
+ * @acct: accounting for the namespace
+ * @unconfined: special unconfined profile for the namespace
+ * @sub_ns: list of namespaces under the current namespace.
+ *
+ * An aa_namespace defines the set profiles that are searched to determine
+ * which profile to attach to a task.  Profiles can not be shared between
+ * aa_namespaces and profile names within a namespace are guarenteed to be
+ * unique.  When profiles in seperate namespaces have the same name they
+ * are NOT considered to be equivalent.
+ *
+ * Namespaces are hierarchical and only namespaces and profiles below the
+ * current namespace are visible.
+ *
+ * Namespace names must be unique and can not contain the characters :/\0
+ *
+ * FIXME TODO: add vserver support so a vserer (can it all be done in userspace)
+ */
+struct aa_namespace {
+	struct aa_policy base;
+	struct aa_namespace *parent;
+	rwlock_t lock;
+	struct aa_ns_acct acct;
+	struct aa_profile *unconfined;
+	struct list_head sub_ns;
+};
+
+/* struct aa_profile - basic confinement data
+ * @base - base componets of the profile (name, refcount, lists, lock ...)
+ * @parent: parent of profile
+ * @ns: namespace the profile is in
+ * @replacedby: is set profile that replaced this profile
+ * @xmatch: optional extended matching for unconfined executables names
+ * @xmatch_len: xmatch prefix len, used to determine xmatch priority
+ * @sid: the unique security id number of this profile
+ * @audit: the auditing mode of the profile
+ * @mode: the enforcement mode of the profile
+ * @flags: flags controlling profile behavior
+ * @path_flags: flags controlling path generation behavior
+ * @size: the memory consumed by this profiles rules
+ * @file: The set of rules governing basic file access and domain transitions
+ * @caps: capabilities for the profile
+ * @net: network controls for the profile
+ * @rlimits: rlimits for the profile
+ *
+ * The AppArmor profile contains the basic confinement data.  Each profile
+ * has a name, and exist in a namespace.  The @name and @exec_match are
+ * used to determine profile attachment against unconfined tasks.  All other
+ * attachments are determined by in profile X transition rules.
+ *
+ * The @replacedby field is write protected by the profile lock.  Reads
+ * are assumed to be atomic, and are done without locking.
+ *
+ * Profiles have a hierachy where hats and children profiles keep
+ * a reference to their parent.
+ *
+ * Profile names can not begin with a : and can not contain the \0
+ * character.  If a profile name begins with / it will be considered when
+ * determining profile attachment on "unconfined" tasks.
+ */
+struct aa_profile {
+	struct aa_policy base;
+	struct aa_profile *parent;
+
+	struct aa_namespace *ns;
+	union {
+		struct aa_profile *replacedby;
+		const char *rename;
+	};
+	struct aa_dfa *xmatch;
+	int xmatch_len;
+	u32 sid;
+	enum audit_mode audit;
+	enum profile_mode mode;
+	u32 flags;
+	u32 path_flags;
+	int size;
+
+	unsigned long mmap_min_addr;
+
+	struct aa_file_rules file;
+	struct aa_caps caps;
+	struct aa_net net;
+	struct aa_rlimit rlimits;
+};
+
+extern struct aa_namespace *root_ns;
+extern enum profile_mode aa_g_profile_mode;
+
+void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
+
+int aa_alloc_root_ns(void);
+void aa_free_root_ns(void);
+void aa_free_namespace_kref(struct kref *kref);
+
+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
+				       const char *name);
+
+static inline struct aa_policy *aa_get_common(struct aa_policy *c)
+{
+	if (c)
+		kref_get(&c->count);
+
+	return c;
+}
+
+/**
+ * aa_get_namespace - increment references count on @ns
+ * @ns: namespace to increment reference count of (MAYBE NULL)
+ *
+ * Returns: pointer to @ns if @ns is NULL returns NULL
+ * Requires: @ns must be held with valid refcount when called
+ */
+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
+{
+	if (ns)
+		kref_get(&(ns->base.count));
+
+	return ns;
+}
+
+/**
+ * aa_put_namespace - decrement refcount on @ns
+ * @ns: namespace to put reference to
+ *
+ * Decrement reference count to @ns and if no longer in use free it
+ */
+static inline void aa_put_namespace(struct aa_namespace *ns)
+{
+	if (ns)
+		kref_put(&ns->base.count, aa_free_namespace_kref);
+}
+
+struct aa_profile *aa_alloc_profile(const char *name);
+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
+void aa_free_profile_kref(struct kref *kref);
+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
+struct aa_profile *aa_find_profile(struct aa_namespace *ns, const char *name);
+struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
+
+ssize_t aa_interface_replace_profiles(void *udata, size_t size, bool add_only);
+ssize_t aa_interface_remove_profiles(char *name, size_t size);
+
+#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
+
+/**
+ * aa_newest_version - find the newest version of @profile
+ * @profile: the profile to check for newer versions of (NOT NULL)
+ *
+ * Returns: newest version of @profile, if @profile is the newest version
+ *          return @profile.
+ *
+ * NOTE: the profile returned is not refcounted, The refcount on @profile
+ * must be held until the caller decides what to do with the returned newest
+ * version.
+ */
+static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
+{
+	if (unlikely(profile && profile->replacedby))
+		for (; profile->replacedby; profile = profile->replacedby) ;
+
+	return profile;
+}
+
+/**
+ * aa_get_profile - increment refcount on profile @p
+ * @p: profile  (MAYBE NULL)
+ *
+ * Returns: pointer to @p if @p is NULL will return NULL
+ * Requires: @p must be held with valid refcount when called
+ */
+static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
+{
+	if (p)
+		kref_get(&(p->base.count));
+
+	return p;
+}
+
+/**
+ * aa_put_profile - decrement refcount on profile @p
+ * @p: profile  (MAYBE NULL)
+ */
+static inline void aa_put_profile(struct aa_profile *p)
+{
+	if (p)
+		kref_put(&p->base.count, aa_free_profile_kref);
+}
+
+static inline int AUDIT_MODE(struct aa_profile *profile)
+{
+	if (aa_g_audit != AUDIT_NORMAL)
+		return aa_g_audit;
+	if (profile)
+		return profile->audit;
+	return AUDIT_NORMAL;
+}
+
+#endif /* __AA_POLICY_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/apparmor.h
+++ linux-ec2-2.6.32/security/apparmor/include/apparmor.h
@@ -0,0 +1,83 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor basic global and lib definitions
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __APPARMOR_H
+#define __APPARMOR_H
+
+#include <linux/fs.h>
+
+#include "match.h"
+
+/* Control parameters settable thru module/boot flags or
+ * via /sys/kernel/security/apparmor/control */
+extern enum audit_mode aa_g_audit;
+extern int aa_g_audit_header;
+extern int aa_g_debug;
+extern int aa_g_lock_policy;
+extern int aa_g_logsyscall;
+extern int aa_g_paranoid_load;
+extern unsigned int aa_g_path_max;
+
+/*
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
+ * which is not related to profile accesses.
+ */
+
+#define AA_DEBUG(fmt, args...)						\
+	do {								\
+		if (aa_g_debug && printk_ratelimit())			\
+			printk(KERN_DEBUG "AppArmor: " fmt, ##args);	\
+	} while (0)
+
+#define AA_ERROR(fmt, args...)						\
+	do {								\
+		if (printk_ratelimit())					\
+			printk(KERN_ERR "AppArmor: " fmt, ##args);	\
+	} while (0)
+
+/* Flag indicating whether initialization completed */
+extern int apparmor_initialized;
+void apparmor_disable(void);
+
+/* fn's in lib */
+char *aa_split_fqname(char *args, char **ns_name);
+bool aa_strneq(const char *str, const char *sub, int len);
+void aa_info_message(const char *str);
+char *skip_spaces(const char *str);
+
+/**
+ * aa_dfa_null_transition - step to next state after null character
+ * @dfa: the dfa to match against
+ * @start: the state of the dfa to start matching in
+ * @old: true if using // as the null transition
+ *
+ * aa_dfa_null_transition transitions to the next state after a null
+ * character which is not used in standard matching and is only
+ * used to seperate pairs.
+ */
+static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
+						  unsigned int start, bool old)
+{
+	if (unlikely(old))
+		return aa_dfa_match_len(dfa, start, "//", 2);
+	else
+		return aa_dfa_match_len(dfa, start, "\0", 1);
+}
+
+static inline bool mediated_filesystem(struct inode *inode)
+{
+	return !(inode->i_sb->s_flags & MS_NOUSER);
+}
+
+#endif /* __APPARMOR_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/match.h
+++ linux-ec2-2.6.32/security/apparmor/include/match.h
@@ -0,0 +1,130 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy dfa matching engine definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_MATCH_H
+#define __AA_MATCH_H
+
+#define DFA_NOMATCH			0
+#define DFA_START			1
+
+#define DFA_VALID_PERM_MASK		0xffffffff
+#define DFA_VALID_PERM2_MASK		0xffffffff
+
+/**
+ * The format used for transition tables is based on the GNU flex table
+ * file format (--tables-file option; see Table File Format in the flex
+ * info pages and the flex sources for documentation). The magic number
+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
+ * slightly differently (see the apparmor-parser package).
+ */
+
+#define YYTH_MAGIC	0x1B5E783D
+#define YYTH_DEF_RECURSE 0x1			/* DEF Table is recursive */
+
+struct table_set_header {
+	u32 th_magic;		/* YYTH_MAGIC */
+	u32 th_hsize;
+	u32 th_ssize;
+	u16 th_flags;
+	char th_version[];
+};
+
+/* The YYTD_ID are one less than flex table mappings.  The flex id
+ * has 1 subtracted at table load time, this allows us to directly use the
+ * ID's as indexes.
+ */
+#define	YYTD_ID_ACCEPT	0
+#define YYTD_ID_BASE	1
+#define YYTD_ID_CHK	2
+#define YYTD_ID_DEF	3
+#define YYTD_ID_EC	4
+#define YYTD_ID_META	5
+#define YYTD_ID_ACCEPT2 6
+#define YYTD_ID_NXT	7
+#define YYTD_ID_TSIZE	8
+
+#define YYTD_DATA8	1
+#define YYTD_DATA16	2
+#define YYTD_DATA32	4
+#define YYTD_DATA64	8
+
+/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
+ * first flags
+ */
+#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
+#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
+#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
+#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
+#define DFA_FLAG_VERIFY_STATES 0x1000
+
+struct table_header {
+	u16 td_id;
+	u16 td_flags;
+	u32 td_hilen;
+	u32 td_lolen;
+	char td_data[];
+};
+
+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
+
+struct aa_dfa {
+	struct kref count;
+	u16 flags;
+	struct table_header *tables[YYTD_ID_TSIZE];
+};
+
+#define byte_to_byte(X) (X)
+
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
+	do { \
+		typeof(LEN) __i; \
+		TYPE *__t = (TYPE *) TABLE; \
+		TYPE *__b = (TYPE *) BLOB; \
+		for (__i = 0; __i < LEN; __i++) { \
+			__t[__i] = NTOHX(__b[__i]); \
+		} \
+	} while (0)
+
+static inline size_t table_size(size_t len, size_t el_size)
+{
+	return ALIGN(sizeof(struct table_header) + len * el_size, 8);
+}
+
+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
+			      const char *str, int len);
+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
+			  const char *str);
+void aa_dfa_free_kref(struct kref *kref);
+
+/**
+ * aa_put_dfa - put a dfa refcount
+ * @dfa: dfa to put refcount   (MAYBE NULL)
+ *
+ * Requires: if @dfa != NULL that valid refcount be held
+ */
+static inline void aa_put_dfa(struct aa_dfa *dfa)
+{
+	if (dfa)
+		kref_put(&dfa->count, aa_dfa_free_kref);
+}
+
+#endif /* __AA_MATCH_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/context.h
+++ linux-ec2-2.6.32/security/apparmor/include/context.h
@@ -0,0 +1,154 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor contexts used to associate "labels" to objects.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_CONTEXT_H
+#define __AA_CONTEXT_H
+
+#include <linux/cred.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "policy.h"
+
+/* struct aa_file_cxt - the AppArmor context the file was opened in
+ * @profile: the profile the file was opened under
+ * @perms: the permission the file was opened with
+ */
+struct aa_file_cxt {
+	struct aa_profile *profile;
+	u16 allowed;
+};
+
+/**
+ * aa_alloc_file_context - allocate file_cxt
+ * @gfp: gfp flags for allocation
+ *
+ * Returns: file_cxt or NULL on failure
+ */
+static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
+{
+	return kzalloc(sizeof(struct aa_file_cxt), gfp);
+}
+
+/**
+ * aa_free_file_context - free a file_cxt
+ * @cxt: file_cxt to free  (MAYBE_NULL)
+ */
+static inline void aa_free_file_context(struct aa_file_cxt *cxt)
+{
+	if (cxt) {
+		aa_put_profile(cxt->profile);
+		kzfree(cxt);
+	}
+}
+
+/**
+ * struct aa_task_cxt - primary label for confined tasks
+ * @profile: the current profile   (NOT NULL)
+ * @exec: profile to transition to on next exec  (MAYBE NULL)
+ * @previous: profile the task may return to     (MAYBE NULL)
+ * @token: magic value the task must know for returning to @previous_profile
+ *
+ * Contains the task's current profile (which could change due to
+ * change_hat).  Plus the hat_magic needed during change_hat.
+ *
+ * TODO: make so a task can be confined by a stack of contexts
+ */
+struct aa_task_cxt {
+	struct aa_profile *profile;
+	struct aa_profile *onexec;
+	struct aa_profile *previous;
+	u64 token;
+};
+
+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
+void aa_free_task_context(struct aa_task_cxt *cxt);
+void aa_dup_task_context(struct aa_task_cxt *new,
+			 const struct aa_task_cxt *old);
+int aa_replace_current_profiles(struct aa_profile *profile);
+int aa_set_current_onexec(struct aa_profile *profile);
+int aa_set_current_hat(struct aa_profile *profile, u64 token);
+int aa_restore_previous_profile(u64 cookie);
+
+/**
+ * __aa_task_is_confined - determine if @task has any confinement
+ * @task: task to check confinement of  (NOT NULL)
+ *
+ * If @task != current needs to be called in RCU safe critical section
+ */
+static inline bool __aa_task_is_confined(struct task_struct *task)
+{
+	struct aa_task_cxt *cxt = __task_cred(task)->security;
+
+	BUG_ON(!cxt || !cxt->profile);
+	if (unconfined(aa_newest_version(cxt->profile)))
+		return 0;
+
+	return 1;
+}
+
+/**
+ * aa_cred_profile - obtain cred's profiles
+ * @cred: cred to obtain profiles from  (NOT NULL)
+ *
+ * Returns: confining profile
+ *
+ * does NOT increment reference count
+ */
+static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
+{
+	struct aa_task_cxt *cxt = cred->security;
+	BUG_ON(!cxt || !cxt->profile);
+	return aa_newest_version(cxt->profile);
+}
+
+/**
+ * __aa_current_profile - find the current tasks confining profile
+ *
+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
+ *
+ * This fn will not update the tasks cred to the most up to date version
+ * of the profile so it is safe to call when inside of locks.
+ */
+static inline struct aa_profile *__aa_current_profile(void)
+{
+	return aa_cred_profile(current_cred());
+}
+
+/**
+ * aa_current_profile - find the current tasks confining profile and do updates
+ *
+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
+ *
+ * This fn will update the tasks cred structure if the profile has been
+ * replaced.  Not safe to call inside locks
+ */
+static inline struct aa_profile *aa_current_profile(void)
+{
+	const struct aa_task_cxt *cxt = current_cred()->security;
+	struct aa_profile *profile;
+	BUG_ON(!cxt || !cxt->profile);
+
+	profile = aa_newest_version(cxt->profile);
+	/*
+	 * Whether or not replacement succeeds, use newest profile so
+	 * there is no need to update it after replacement.
+	 */
+	if (unlikely((cxt->profile != profile)))
+		aa_replace_current_profiles(profile);
+
+	return profile;
+}
+
+#endif /* __AA_CONTEXT_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/net.h
+++ linux-ec2-2.6.32/security/apparmor/include/net.h
@@ -0,0 +1,40 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+
+/* struct aa_net - network confinement data
+ * @allowed: basic network families permissions
+ * @audit_network: which network permissions to force audit
+ * @quiet_network: which network permissions to quiet rejects
+ */
+struct aa_net {
+	u16 allowed[AF_MAX];
+	u16 audit[AF_MAX];
+	u16 quiet[AF_MAX];
+};
+
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
+		       int family, int type, int protocol);
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
+
+static inline void aa_free_net_rules(struct aa_net *new)
+{
+	/* NOP */
+}
+
+#endif /* __AA_NET_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/sid.h
+++ linux-ec2-2.6.32/security/apparmor/include/sid.h
@@ -0,0 +1,24 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor security identifier (sid) definitions
+ *
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_SID_H
+#define __AA_SID_H
+
+#include <linux/types.h>
+
+struct aa_profile;
+
+u32 aa_alloc_sid(void);
+void aa_free_sid(u32 sid);
+
+#endif /* __AA_SID_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/audit.h
+++ linux-ec2-2.6.32/security/apparmor/include/audit.h
@@ -0,0 +1,54 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor auditing function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_AUDIT_H
+#define __AA_AUDIT_H
+
+#include <linux/audit.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+struct aa_profile;
+
+extern const char *audit_mode_names[];
+#define AUDIT_MAX_INDEX 5
+
+#define AUDIT_APPARMOR_AUTO 0	/* auto choose audit message type */
+
+enum audit_mode {
+	AUDIT_NORMAL,		/* follow normal auditing of accesses */
+	AUDIT_QUIET_DENIED,	/* quiet all denied access messages */
+	AUDIT_QUIET,		/* quiet all messages */
+	AUDIT_NOQUIET,		/* do not quiet audit messages */
+	AUDIT_ALL		/* audit all accesses */
+};
+
+/*
+ * aa_audit - AppArmor auditing structure
+ * Structure is populated by access control code and passed to aa_audit which
+ * provides for a single point of logging.
+ */
+struct aa_audit {
+	struct task_struct *task;
+	gfp_t gfp_mask;
+	int error;
+	const char *operation;
+	const char *info;
+};
+
+int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
+	     void (*cb) (struct audit_buffer *, struct aa_audit *));
+
+#endif /* __AA_AUDIT_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/policy_unpack.h
+++ linux-ec2-2.6.32/security/apparmor/include/policy_unpack.h
@@ -0,0 +1,30 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy loading interface function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __POLICY_INTERFACE_H
+#define __POLICY_INTERFACE_H
+
+struct aa_audit_iface {
+	struct aa_audit base;
+
+	const char *name;
+	const char *name2;
+	long pos;
+};
+
+int aa_audit_iface(struct aa_audit_iface *sa);
+struct aa_profile *aa_unpack(void *udata, size_t size,
+			     struct aa_audit_iface *sa);
+
+#endif /* __POLICY_INTERFACE_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/file.h
+++ linux-ec2-2.6.32/security/apparmor/include/file.h
@@ -0,0 +1,228 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_FILE_H
+#define __AA_FILE_H
+
+#include <linux/path.h>
+
+#include "audit.h"
+#include "domain.h"
+#include "match.h"
+
+struct aa_profile;
+
+/*
+ * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
+ * for profile permissions
+ */
+#define AA_MAY_LINK			0x0010
+#define AA_MAY_LOCK			0x0020
+#define AA_EXEC_MMAP			0x0040
+
+#define AA_MAY_CREATE			0x0080
+#define AA_MAY_DELETE			0x0100
+#define AA_MAY_CHMOD			0x0200
+#define AA_MAY_CHOWN			0x0400
+
+#define AA_LINK_SUBSET			0x0800
+#define AA_MAY_CHANGEHAT		0x2000	/* ctrl auditing only */
+#define AA_MAY_ONEXEC			0x4000	/* exec allows onexec */
+#define AA_MAY_CHANGE_PROFILE		0x8000
+
+#define AA_AUDIT_FILE_MASK	(MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
+				 AA_MAY_LINK | AA_MAY_LOCK | AA_EXEC_MMAP | \
+				 AA_MAY_CREATE | AA_MAY_DELETE | AA_MAY_CHMOD |\
+				 AA_MAY_CHOWN)
+
+/*
+ * The xindex is broken into 3 parts
+ * - index - an index into either the exec name table or the variable table
+ * - exec type - which determines how the executable name and index are used
+ * - flags - which modify how the destination name is applied
+ */
+#define AA_X_INDEX_MASK		0x03ff
+
+#define AA_X_TYPE_MASK		0x0c00
+#define AA_X_TYPE_SHIFT		10
+#define AA_X_NONE		0x0000
+#define AA_X_NAME		0x0400	/* use executable name px */
+#define AA_X_TABLE		0x0800	/* use a specified name ->n# */
+
+#define AA_X_UNSAFE		0x1000
+#define AA_X_CHILD		0x2000	/* make >AA_X_NONE apply to children */
+#define AA_X_INHERIT		0x4000
+#define AA_X_UNCONFINED		0x8000
+
+/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
+#define AA_SECURE_X_NEEDED	0x8000
+
+/* need to conditionalize which ones are being set */
+struct path_cond {
+	uid_t uid;
+	umode_t mode;
+};
+
+/* struct file_perms - file permission fo
+ * @allowed: mask of permissions that are allowed
+ * @audit: mask of permissions to force an audit message for
+ * @quiet: mask of permissions to quiet audit messages for
+ * @kill: mask of permissions that when matched will kill the task
+ * @xindex: exec transition index if @allowed contains MAY_EXEC
+ * @xdelegate: used by exec to determine set of delegates allowed
+ * @dindex: delegate table index, 0 if no delegation allowed
+ *
+ * The @audit and @queit mask should be mutually exclusive.
+ */
+struct file_perms {
+	u16 allowed;
+	u16 audit;
+	u16 quiet;
+	u16 kill;
+	u16 xindex;
+	u16 xdelegate;
+	u16 dindex;
+};
+
+extern struct file_perms nullperms;
+
+#define COMBINED_PERM_MASK(X) ((X).allowed | (X).audit | (X).quiet | (X).kill)
+
+/* FIXME: split perms from dfa and match this to description
+ *        also add delegation info.
+ */
+static inline u16 dfa_map_xindex(u16 mask)
+{
+	u16 old_index = (mask >> 10) & 0xf;
+	u16 index = 0;
+
+	if (mask & 0x100)
+		index |= AA_X_UNSAFE;
+	if (mask & 0x200)
+		index |= AA_X_INHERIT;
+	if (mask & 0x80)
+		index |= AA_X_UNCONFINED;
+
+	if (old_index == 1) {
+		index |= AA_X_UNCONFINED;
+	} else if (old_index == 2) {
+		index |= AA_X_NAME;
+	} else if (old_index == 3) {
+		index |= AA_X_NAME | AA_X_CHILD;
+	} else {
+		index |= AA_X_TABLE;
+		index |= old_index - 4;
+	}
+
+	return index;
+}
+
+/*
+ * map old dfa inline permissions to new format
+ */
+#define dfa_user_allow(dfa, state) ((ACCEPT_TABLE(dfa)[state]) & 0x7f)
+#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
+#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
+#define dfa_user_xindex(dfa, state) \
+	(dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
+
+#define dfa_other_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 14) & 0x7f)
+#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
+#define dfa_other_quiet(dfa, state) \
+	((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
+#define dfa_other_xindex(dfa, state) \
+	dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
+
+struct aa_audit_file {
+	struct aa_audit base;
+
+	const char *name;
+	const char *name2;
+	const char *name3;
+	struct file_perms perms;
+	u16 request;
+	struct path_cond *cond;
+};
+
+int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa);
+
+/**
+ * struct aa_file_rules - components used for file rule permissions
+ * @dfa: dfa to match path names and conditionals against
+ * @perms: permission table indexed by the matched state accept entry of @dfa
+ * @trans: transition table for indexed by named x transitions
+ *
+ * File permission are determined by matching a path against @dfa and then
+ * then using the value of the accept entry for the matching state as
+ * an index into @perms.  If a named exec transition is required it is
+ * looked up in the transition table.
+ */
+struct aa_file_rules {
+	unsigned int start;
+	struct aa_dfa *dfa;
+	/* struct perms perms; */
+	struct aa_domain trans;
+	/* TODO: add delegate table */
+};
+
+struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
+			       const char *name, struct path_cond *cond,
+			       unsigned int *rstate);
+
+int aa_pathstr_perm(struct aa_profile *profile, const char *op,
+		    const char *name, u16 request, struct path_cond *cond);
+
+int aa_path_perm(struct aa_profile *profile, const char *operation,
+		 struct path *path, u16 request, struct path_cond *cond);
+
+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
+		 struct path *new_dir, struct dentry *new_dentry);
+
+int aa_file_perm(struct aa_profile *profile, const char *operation,
+		 struct file *file, u16 request);
+
+static inline void aa_free_file_rules(struct aa_file_rules *rules)
+{
+	aa_put_dfa(rules->dfa);
+	aa_free_domain_entries(&rules->trans);
+}
+
+#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
+
+/* from namei.c */
+#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
+
+/**
+ * aa_map_file_perms - map file flags to AppArmor permissions
+ * @file: open file to map flags to AppArmor permissions
+ *
+ * Returns: apparmor permission set for the file
+ */
+static inline u16 aa_map_file_to_perms(struct file *file)
+{
+	int flags = MAP_OPEN_FLAGS(file->f_flags);
+	u16 perms = ACC_FMODE(file->f_mode);
+
+	if ((flags & O_APPEND) && (perms & MAY_WRITE))
+		perms = (perms & ~MAY_WRITE) | MAY_APPEND;
+	/* trunc implies write permission */
+	if (flags & O_TRUNC)
+		perms |= MAY_WRITE;
+	if (flags & O_CREAT)
+		perms |= AA_MAY_CREATE;
+
+	return perms;
+}
+
+#endif /* __AA_FILE_H */
--- linux-ec2-2.6.32.orig/security/apparmor/include/path.h
+++ linux-ec2-2.6.32/security/apparmor/include/path.h
@@ -0,0 +1,31 @@
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor basic path manipulation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __AA_PATH_H
+#define __AA_PATH_H
+
+
+enum path_flags {
+	PATH_IS_DIR = 0x1,		/* path is a directory */
+	PATH_CONNECT_PATH = 0x4,	/* connect disconnected paths to / */
+	PATH_CHROOT_REL = 0x8,		/* do path lookup relative to chroot */
+	PATH_CHROOT_NSCONNECT = 0x10,	/* connect paths that are at ns root */
+
+	PATH_MEDIATE_DELETED = 0x10000,	/* mediate deleted paths */
+};
+
+int aa_get_name(struct path *path, int flags, char **buffer, char **name);
+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen);
+
+#endif /* __AA_PATH_H */
--- linux-ec2-2.6.32.orig/security/selinux/nlmsgtab.c
+++ linux-ec2-2.6.32/security/selinux/nlmsgtab.c
@@ -66,6 +66,8 @@
 	{ RTM_NEWADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_DELADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_GETADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_GETDCB,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_SETDCB,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 };
 
 static struct nlmsg_perm nlmsg_firewall_perms[] =
--- linux-ec2-2.6.32.orig/security/selinux/hooks.c
+++ linux-ec2-2.6.32/security/selinux/hooks.c
@@ -76,6 +76,7 @@
 #include <linux/selinux.h>
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
+#include <linux/syslog.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -2050,11 +2051,11 @@
 	return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 }
 
-static int selinux_syslog(int type)
+static int selinux_syslog(int type, bool from_file)
 {
 	int rc;
 
-	rc = cap_syslog(type);
+	rc = cap_syslog(type, from_file);
 	if (rc)
 		return rc;
 
@@ -2366,7 +2367,7 @@
 			initrlim = init_task.signal->rlim + i;
 			rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
 		}
-		update_rlimit_cpu(rlim->rlim_cur);
+		update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur);
 	}
 }
 
@@ -2601,7 +2602,10 @@
 	sid = tsec->sid;
 	newsid = tsec->create_sid;
 
-	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+	if ((sbsec->flags & SE_SBINITIALIZED) &&
+	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
+		newsid = sbsec->mntpoint_sid;
+	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
 		rc = security_transition_sid(sid, dsec->sid,
 					     inode_mode_to_security_class(inode->i_mode),
 					     &newsid);
@@ -3259,7 +3263,11 @@
 {
 	struct task_security_struct *tsec = cred->security;
 
-	BUG_ON((unsigned long) cred->security < PAGE_SIZE);
+	/*
+	 * cred->security == NULL if security_cred_alloc_blank() or
+	 * security_prepare_creds() returned an error.
+	 */
+	BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
 	cred->security = (void *) 0x7UL;
 	kfree(tsec);
 }
--- linux-ec2-2.6.32.orig/security/selinux/ss/ebitmap.c
+++ linux-ec2-2.6.32/security/selinux/ss/ebitmap.c
@@ -128,7 +128,7 @@
 			cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
 			cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
 			c_iter->bitmap[cmap_idx]
-				|= e_iter->maps[cmap_idx] << cmap_sft;
+				|= e_iter->maps[i] << cmap_sft;
 		}
 		e_iter = e_iter->next;
 	}
--- linux-ec2-2.6.32.orig/security/integrity/ima/ima_main.c
+++ linux-ec2-2.6.32/security/integrity/ima/ima_main.c
@@ -324,6 +324,7 @@
 					 MAY_EXEC, FILE_MMAP);
 	return 0;
 }
+EXPORT_SYMBOL(ima_file_mmap);
 
 /**
  * ima_bprm_check - based on policy, collect/store measurement.
--- linux-ec2-2.6.32.orig/security/integrity/ima/ima_policy.c
+++ linux-ec2-2.6.32/security/integrity/ima/ima_policy.c
@@ -249,6 +249,8 @@
 	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
 					   Audit_equal, args,
 					   &entry->lsm[lsm_rule].rule);
+	if (!entry->lsm[lsm_rule].rule)
+		return -EINVAL;
 	return result;
 }
 
--- linux-ec2-2.6.32.orig/security/smack/smack_lsm.c
+++ linux-ec2-2.6.32/security/smack/smack_lsm.c
@@ -157,12 +157,12 @@
  *
  * Returns 0 on success, error code otherwise.
  */
-static int smack_syslog(int type)
+static int smack_syslog(int type, bool from_file)
 {
 	int rc;
 	char *sp = current_security();
 
-	rc = cap_syslog(type);
+	rc = cap_syslog(type, from_file);
 	if (rc != 0)
 		return rc;
 
--- linux-ec2-2.6.32.orig/security/keys/request_key.c
+++ linux-ec2-2.6.32/security/keys/request_key.c
@@ -336,8 +336,10 @@
 
 key_already_present:
 	mutex_unlock(&key_construction_mutex);
-	if (dest_keyring)
+	if (dest_keyring) {
+		__key_link(dest_keyring, key_ref_to_ptr(key_ref));
 		up_write(&dest_keyring->sem);
+	}
 	mutex_unlock(&user->cons_lock);
 	key_put(key);
 	*_key = key = key_ref_to_ptr(key_ref);
@@ -428,6 +430,11 @@
 
 	if (!IS_ERR(key_ref)) {
 		key = key_ref_to_ptr(key_ref);
+		if (dest_keyring) {
+			construct_get_dest_keyring(&dest_keyring);
+			key_link(dest_keyring, key);
+			key_put(dest_keyring);
+		}
 	} else if (PTR_ERR(key_ref) != -EAGAIN) {
 		key = ERR_CAST(key_ref);
 	} else  {
--- linux-ec2-2.6.32.orig/security/keys/keyring.c
+++ linux-ec2-2.6.32/security/keys/keyring.c
@@ -524,9 +524,8 @@
 	struct key *keyring;
 	int bucket;
 
-	keyring = ERR_PTR(-EINVAL);
 	if (!name)
-		goto error;
+		return ERR_PTR(-EINVAL);
 
 	bucket = keyring_hash(name);
 
@@ -553,17 +552,18 @@
 					   KEY_SEARCH) < 0)
 				continue;
 
-			/* we've got a match */
-			atomic_inc(&keyring->usage);
-			read_unlock(&keyring_name_lock);
-			goto error;
+			/* we've got a match but we might end up racing with
+			 * key_cleanup() if the keyring is currently 'dead'
+			 * (ie. it has a zero usage count) */
+			if (!atomic_inc_not_zero(&keyring->usage))
+				continue;
+			goto out;
 		}
 	}
 
-	read_unlock(&keyring_name_lock);
 	keyring = ERR_PTR(-ENOKEY);
-
- error:
+out:
+	read_unlock(&keyring_name_lock);
 	return keyring;
 
 } /* end find_keyring_by_name() */
--- linux-ec2-2.6.32.orig/security/keys/process_keys.c
+++ linux-ec2-2.6.32/security/keys/process_keys.c
@@ -509,7 +509,7 @@
 
 			ret = install_thread_keyring();
 			if (ret < 0) {
-				key = ERR_PTR(ret);
+				key_ref = ERR_PTR(ret);
 				goto error;
 			}
 			goto reget_creds;
@@ -527,7 +527,7 @@
 
 			ret = install_process_keyring();
 			if (ret < 0) {
-				key = ERR_PTR(ret);
+				key_ref = ERR_PTR(ret);
 				goto error;
 			}
 			goto reget_creds;
@@ -586,7 +586,7 @@
 
 	case KEY_SPEC_GROUP_KEYRING:
 		/* group keyrings are not yet supported */
-		key = ERR_PTR(-EINVAL);
+		key_ref = ERR_PTR(-EINVAL);
 		goto error;
 
 	case KEY_SPEC_REQKEY_AUTH_KEY:
--- linux-ec2-2.6.32.orig/security/keys/keyctl.c
+++ linux-ec2-2.6.32/security/keys/keyctl.c
@@ -1236,6 +1236,7 @@
  */
 long keyctl_session_to_parent(void)
 {
+#ifdef TIF_NOTIFY_RESUME
 	struct task_struct *me, *parent;
 	const struct cred *mycred, *pcred;
 	struct cred *cred, *oldcred;
@@ -1258,6 +1259,7 @@
 	keyring_r = NULL;
 
 	me = current;
+	rcu_read_lock();
 	write_lock_irq(&tasklist_lock);
 
 	parent = me->real_parent;
@@ -1290,7 +1292,8 @@
 		goto not_permitted;
 
 	/* the keyrings must have the same UID */
-	if (pcred ->tgcred->session_keyring->uid != mycred->euid ||
+	if ((pcred->tgcred->session_keyring &&
+	    pcred->tgcred->session_keyring->uid != mycred->euid) ||
 	    mycred->tgcred->session_keyring->uid != mycred->euid)
 		goto not_permitted;
 
@@ -1312,6 +1315,7 @@
 	set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
 
 	write_unlock_irq(&tasklist_lock);
+	rcu_read_unlock();
 	if (oldcred)
 		put_cred(oldcred);
 	return 0;
@@ -1320,12 +1324,22 @@
 	ret = 0;
 not_permitted:
 	write_unlock_irq(&tasklist_lock);
+	rcu_read_unlock();
 	put_cred(cred);
 	return ret;
 
 error_keyring:
 	key_ref_put(keyring_r);
 	return ret;
+
+#else /* !TIF_NOTIFY_RESUME */
+	/*
+	 * To be removed when TIF_NOTIFY_RESUME has been implemented on
+	 * m68k/xtensa
+	 */
+#warning TIF_NOTIFY_RESUME not implemented
+	return -EOPNOTSUPP;
+#endif /* !TIF_NOTIFY_RESUME */
 }
 
 /*****************************************************************************/
--- linux-ec2-2.6.32.orig/block/blk-settings.c
+++ linux-ec2-2.6.32/block/blk-settings.c
@@ -8,6 +8,7 @@
 #include <linux/blkdev.h>
 #include <linux/bootmem.h>	/* for max_pfn/max_low_pfn */
 #include <linux/gcd.h>
+#include <linux/lcm.h>
 
 #include "blk.h"
 
@@ -102,7 +103,7 @@
 	lim->alignment_offset = 0;
 	lim->io_opt = 0;
 	lim->misaligned = 0;
-	lim->no_cluster = 0;
+	lim->cluster = 1;
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 
@@ -351,7 +352,7 @@
  *   hardware can operate on without reverting to read-modify-write
  *   operations.
  */
-void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
 {
 	q->limits.physical_block_size = size;
 
@@ -476,32 +477,36 @@
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
 	blk_stack_limits(&t->limits, &b->limits, 0);
-
-	if (!t->queue_lock)
-		WARN_ON_ONCE(1);
-	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-		unsigned long flags;
-		spin_lock_irqsave(t->queue_lock, flags);
-		queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-		spin_unlock_irqrestore(t->queue_lock, flags);
-	}
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
 /**
  * blk_stack_limits - adjust queue_limits for stacked devices
- * @t:	the stacking driver limits (top)
- * @b:  the underlying queue limits (bottom)
+ * @t:	the stacking driver limits (top device)
+ * @b:  the underlying queue limits (bottom, component device)
  * @offset:  offset to beginning of data within component device
  *
  * Description:
- *    Merges two queue_limit structs.  Returns 0 if alignment didn't
- *    change.  Returns -1 if adding the bottom device caused
- *    misalignment.
+ *    This function is used by stacking drivers like MD and DM to ensure
+ *    that all component devices have compatible block sizes and
+ *    alignments.  The stacking driver must provide a queue_limits
+ *    struct (top) and then iteratively call the stacking function for
+ *    all component (bottom) devices.  The stacking function will
+ *    attempt to combine the values and ensure proper alignment.
+ *
+ *    Returns 0 if the top and bottom queue_limits are compatible.  The
+ *    top device's block sizes and alignment offsets may be adjusted to
+ *    ensure alignment with the bottom device. If no compatible sizes
+ *    and alignments exist, -1 is returned and the resulting top
+ *    queue_limits will have the misaligned flag set to indicate that
+ *    the alignment_offset is undefined.
  */
 int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 		     sector_t offset)
 {
+	sector_t alignment;
+	unsigned int top, bottom, ret = 0;
+
 	t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
 	t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
 	t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
@@ -518,6 +523,26 @@
 	t->max_segment_size = min_not_zero(t->max_segment_size,
 					   b->max_segment_size);
 
+	t->misaligned |= b->misaligned;
+
+	alignment = queue_limit_alignment_offset(b, offset);
+
+	/* Bottom device has different alignment.  Check that it is
+	 * compatible with the current top alignment.
+	 */
+	if (t->alignment_offset != alignment) {
+
+		top = max(t->physical_block_size, t->io_min)
+			+ t->alignment_offset;
+		bottom = max(b->physical_block_size, b->io_min) + alignment;
+
+		/* Verify that top and bottom intervals line up */
+		if (max(top, bottom) & (min(top, bottom) - 1)) {
+			t->misaligned = 1;
+			ret = -1;
+		}
+	}
+
 	t->logical_block_size = max(t->logical_block_size,
 				    b->logical_block_size);
 
@@ -525,41 +550,72 @@
 				     b->physical_block_size);
 
 	t->io_min = max(t->io_min, b->io_min);
-	t->no_cluster |= b->no_cluster;
+	t->io_opt = lcm(t->io_opt, b->io_opt);
 
-	/* Bottom device offset aligned? */
-	if (offset &&
-	    (offset & (b->physical_block_size - 1)) != b->alignment_offset) {
+	t->cluster &= b->cluster;
+
+	/* Physical block size a multiple of the logical block size? */
+	if (t->physical_block_size & (t->logical_block_size - 1)) {
+		t->physical_block_size = t->logical_block_size;
 		t->misaligned = 1;
-		return -1;
+		ret = -1;
 	}
 
-	/* If top has no alignment offset, inherit from bottom */
-	if (!t->alignment_offset)
-		t->alignment_offset =
-			b->alignment_offset & (b->physical_block_size - 1);
+	/* Minimum I/O a multiple of the physical block size? */
+	if (t->io_min & (t->physical_block_size - 1)) {
+		t->io_min = t->physical_block_size;
+		t->misaligned = 1;
+		ret = -1;
+	}
 
-	/* Top device aligned on logical block boundary? */
+	/* Optimal I/O a multiple of the physical block size? */
+	if (t->io_opt & (t->physical_block_size - 1)) {
+		t->io_opt = 0;
+		t->misaligned = 1;
+		ret = -1;
+	}
+
+	/* Find lowest common alignment_offset */
+	t->alignment_offset = lcm(t->alignment_offset, alignment)
+		& (max(t->physical_block_size, t->io_min) - 1);
+
+	/* Verify that new alignment_offset is on a logical block boundary */
 	if (t->alignment_offset & (t->logical_block_size - 1)) {
 		t->misaligned = 1;
-		return -1;
+		ret = -1;
 	}
 
-	/* Find lcm() of optimal I/O size */
-	if (t->io_opt && b->io_opt)
-		t->io_opt = (t->io_opt * b->io_opt) / gcd(t->io_opt, b->io_opt);
-	else if (b->io_opt)
-		t->io_opt = b->io_opt;
-
-	/* Verify that optimal I/O size is a multiple of io_min */
-	if (t->io_min && t->io_opt % t->io_min)
-		return -1;
+	/* Discard */
+	t->max_discard_sectors = min_not_zero(t->max_discard_sectors,
+					      b->max_discard_sectors);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(blk_stack_limits);
 
 /**
+ * bdev_stack_limits - adjust queue limits for stacked drivers
+ * @t:	the stacking driver limits (top device)
+ * @bdev:  the component block_device (bottom)
+ * @start:  first data sector within component device
+ *
+ * Description:
+ *    Merges queue limits for a top device and a block_device.  Returns
+ *    0 if alignment didn't change.  Returns -1 if adding the bottom
+ *    device caused misalignment.
+ */
+int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
+		      sector_t start)
+{
+	struct request_queue *bq = bdev_get_queue(bdev);
+
+	start += get_start_sect(bdev);
+
+	return blk_stack_limits(t, &bq->limits, start << 9);
+}
+EXPORT_SYMBOL(bdev_stack_limits);
+
+/**
  * disk_stack_limits - adjust queue limits for stacked drivers
  * @disk:  MD/DM gendisk (top)
  * @bdev:  the underlying block device (bottom)
@@ -587,17 +643,6 @@
 		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
 		       top, bottom);
 	}
-
-	if (!t->queue_lock)
-		WARN_ON_ONCE(1);
-	else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-		unsigned long flags;
-
-		spin_lock_irqsave(t->queue_lock, flags);
-		if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-			queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-		spin_unlock_irqrestore(t->queue_lock, flags);
-	}
 }
 EXPORT_SYMBOL(disk_stack_limits);
 
--- linux-ec2-2.6.32.orig/block/blk-merge.c
+++ linux-ec2-2.6.32/block/blk-merge.c
@@ -22,7 +22,7 @@
 		return 0;
 
 	fbio = bio;
-	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	cluster = blk_queue_cluster(q);
 	seg_size = 0;
 	phys_size = nr_phys_segs = 0;
 	for_each_bio(bio) {
@@ -88,7 +88,7 @@
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
 				   struct bio *nxt)
 {
-	if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+	if (!blk_queue_cluster(q))
 		return 0;
 
 	if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -124,7 +124,7 @@
 	int nsegs, cluster;
 
 	nsegs = 0;
-	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	cluster = blk_queue_cluster(q);
 
 	/*
 	 * for each bio in rq
--- linux-ec2-2.6.32.orig/block/blk-map.c
+++ linux-ec2-2.6.32/block/blk-map.c
@@ -201,6 +201,9 @@
 	for (i = 0; i < iov_count; i++) {
 		unsigned long uaddr = (unsigned long)iov[i].iov_base;
 
+		if (!iov[i].iov_len)
+			return -EINVAL;
+
 		if (uaddr & queue_dma_alignment(q)) {
 			unaligned = 1;
 			break;
--- linux-ec2-2.6.32.orig/block/blk-timeout.c
+++ linux-ec2-2.6.32/block/blk-timeout.c
@@ -109,6 +109,7 @@
 	struct request_queue *q = (struct request_queue *) data;
 	unsigned long flags, next = 0;
 	struct request *rq, *tmp;
+	int next_set = 0;
 
 	spin_lock_irqsave(q->queue_lock, flags);
 
@@ -122,16 +123,13 @@
 			if (blk_mark_rq_complete(rq))
 				continue;
 			blk_rq_timed_out(rq);
-		} else if (!next || time_after(next, rq->deadline))
+		} else if (!next_set || time_after(next, rq->deadline)) {
 			next = rq->deadline;
+			next_set = 1;
+		}
 	}
 
-	/*
-	 * next can never be 0 here with the list non-empty, since we always
-	 * bump ->deadline to 1 so we can detect if the timer was ever added
-	 * or not. See comment in blk_add_timer()
-	 */
-	if (next)
+	if (next_set)
 		mod_timer(&q->timeout, round_jiffies_up(next));
 
 	spin_unlock_irqrestore(q->queue_lock, flags);
--- linux-ec2-2.6.32.orig/block/bsg.c
+++ linux-ec2-2.6.32/block/bsg.c
@@ -424,7 +424,7 @@
 	/*
 	 * fill in all the output members
 	 */
-	hdr->device_status = status_byte(rq->errors);
+	hdr->device_status = rq->errors & 0xff;
 	hdr->transport_status = host_byte(rq->errors);
 	hdr->driver_status = driver_byte(rq->errors);
 	hdr->info = 0;
--- linux-ec2-2.6.32.orig/block/blk-sysfs.c
+++ linux-ec2-2.6.32/block/blk-sysfs.c
@@ -440,8 +440,10 @@
 		return ret;
 
 	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
-	if (ret < 0)
+	if (ret < 0) {
+		blk_trace_remove_sysfs(dev);
 		return ret;
+	}
 
 	kobject_uevent(&q->kobj, KOBJ_ADD);
 
--- linux-ec2-2.6.32.orig/block/scsi_ioctl.c
+++ linux-ec2-2.6.32/block/scsi_ioctl.c
@@ -319,33 +319,47 @@
 	if (hdr->iovec_count) {
 		const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
 		size_t iov_data_len;
-		struct sg_iovec *iov;
+		struct sg_iovec *sg_iov;
+		struct iovec *iov;
+		int i;
 
-		iov = kmalloc(size, GFP_KERNEL);
-		if (!iov) {
+		sg_iov = kmalloc(size, GFP_KERNEL);
+		if (!sg_iov) {
 			ret = -ENOMEM;
 			goto out;
 		}
 
-		if (copy_from_user(iov, hdr->dxferp, size)) {
-			kfree(iov);
+		if (copy_from_user(sg_iov, hdr->dxferp, size)) {
+			kfree(sg_iov);
 			ret = -EFAULT;
 			goto out;
 		}
 
+		/*
+		 * Sum up the vecs, making sure they don't overflow
+		 */
+		iov = (struct iovec *) sg_iov;
+		iov_data_len = 0;
+		for (i = 0; i < hdr->iovec_count; i++) {
+			if (iov_data_len + iov[i].iov_len < iov_data_len) {
+				kfree(sg_iov);
+				ret = -EINVAL;
+				goto out;
+			}
+			iov_data_len += iov[i].iov_len;
+		}
+
 		/* SG_IO howto says that the shorter of the two wins */
-		iov_data_len = iov_length((struct iovec *)iov,
-					  hdr->iovec_count);
 		if (hdr->dxfer_len < iov_data_len) {
-			hdr->iovec_count = iov_shorten((struct iovec *)iov,
+			hdr->iovec_count = iov_shorten(iov,
 						       hdr->iovec_count,
 						       hdr->dxfer_len);
 			iov_data_len = hdr->dxfer_len;
 		}
 
-		ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count,
+		ret = blk_rq_map_user_iov(q, rq, NULL, sg_iov, hdr->iovec_count,
 					  iov_data_len, GFP_KERNEL);
-		kfree(iov);
+		kfree(sg_iov);
 	} else if (hdr->dxfer_len)
 		ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len,
 				      GFP_KERNEL);
--- linux-ec2-2.6.32.orig/debian/changelog
+++ linux-ec2-2.6.32/debian/changelog
@@ -0,0 +1,8971 @@
+linux-ec2 (2.6.32-317.36) lucid-proposed; urgency=low
+
+  [Stefan Bader]
+
+  * Release Tracking Bug
+    - LP: #807505
+
+  [ Stefan Bader ]
+
+  * Revert "XEN: x86: Flush TLB if PGD entry is changed in i386 PAE mode"
+    - LP: #805209
+  * Rebased to 2.6.32-33.70
+
+  [ Ubuntu: 2.6.32-33.70 ]
+
+  * Revert "x86: Flush TLB if PGD entry is changed in i386 PAE mode"
+    - LP: #805209
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 Jul 2011 09:57:36 +0000
+
+linux-ec2 (2.6.32-317.35) lucid-proposed; urgency=low
+
+  [Stefan Bader]
+
+  * Release Tracking Bug
+    - LP: #806968
+  * Rebased to 2.6.32-33.69
+
+  [ Ubuntu: 2.6.32-33.69 ]
+
+  * Revert "af_unix: Only allow recv on connected seqpacket sockets."
+
+  [ Ubuntu: 2.6.32-33.68 ]
+
+  * Fix abi directory
+
+  [ Ubuntu: 2.6.32-33.67 ]
+
+  * Revert "iwlagn: Support new 5000 microcode."
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 07 Jul 2011 15:09:59 +0200
+
+linux-ec2 (2.6.32-317.34) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Release Tracking Bug
+    - LP: #794420
+  * Rebased to 2.6.32-33.66
+
+  [ Ubuntu: 2.6.32-33.66 ]
+
+  * Revert "xhci: Fix full speed bInterval encoding."
+  * Revert "USB: xhci - fix math in xhci_get_endpoint_interval()"
+  * Revert "USB: xhci - fix unsafe macro definitions"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 08 Jun 2011 09:58:47 +0200
+
+linux-ec2 (2.6.32-317.33) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Release Tracking Bug
+    - LP: #793566
+  * Rebased to 2.6.32-33.65
+
+  [ Ubuntu: 2.6.32-33.65 ]
+
+  * xhci: Fix full speed bInterval encoding.
+    - LP: #792959
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 06 Jun 2011 14:06:42 +0000
+
+linux-ec2 (2.6.32-317.32) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * SAUCE: XEN: Sync with x86, cpu: AMD errata checking framework
+    - LP: #770050
+  * SAUCE: XEN: Sync with x86, cpu: Clean up AMD erratum 400 workaround
+    - LP: #770050
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-33.64
+
+  [ Ubuntu: 2.6.32-33.64 ]
+
+   * Release Tracking Bug
+     - LP: #789325
+  * SAUCE: (no-up) Fix up KVM: VMX: Fix host userspace gsbase corruption
+    - LP: #787675
+  * SAUCE: vesafb: mtrr module parameter is uint, not bool
+    - LP: #778043
+  * Revert "(pre-stable): input: Support Clickpad devices in ClickZone
+    mode"
+    - LP: #780588
+  * Revert "GFS2: Fix writing to non-page aligned gfs2_quota structures"
+    - LP: #780588
+  * Revert "mmc: build fix: mmc_pm_notify is only available with
+    CONFIG_PM=y"
+    - LP: #780588
+  * Revert "mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume"
+    - LP: #780588
+  * Revert "econet: fix CVE-2010-3848"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "xen: set max_pfn_mapped to the last pfn mapped"
+  * cifs: always do is_path_accessible check in cifs_mount
+    - LP: #770050
+  * video: sn9c102: world-wirtable sysfs files
+    - LP: #770050
+  * UBIFS: restrict world-writable debugfs files
+    - LP: #770050
+  * NET: cdc-phonet, handle empty phonet header
+    - LP: #770050
+  * x86: Fix a bogus unwind annotation in lib/semaphore_32.S
+    - LP: #770050
+  * tioca: Fix assignment from incompatible pointer warnings
+    - LP: #770050
+  * mca.c: Fix cast from integer to pointer warning
+    - LP: #770050
+  * ramfs: fix memleak on no-mmu arch
+    - LP: #770050
+  * MAINTAINERS: update STABLE BRANCH info
+    - LP: #770050
+  * UBIFS: fix oops when R/O file-system is fsync'ed
+    - LP: #770050
+  * x86, cpu: AMD errata checking framework
+    - LP: #770050
+  * x86, cpu: Clean up AMD erratum 400 workaround
+    - LP: #770050
+  * x86, AMD: Set ARAT feature on AMD processors
+    - LP: #770050
+  * x86, amd: Disable GartTlbWlkErr when BIOS forgets it
+    - LP: #770050
+  * USB: ftdi_sio: Added IDs for CTI USB Serial Devices
+    - LP: #770050
+  * USB: ftdi_sio: add PID for OCT DK201 docking station
+    - LP: #770050
+  * USB: ftdi_sio: add ids for Hameg HO720 and HO730
+    - LP: #770050
+  * USB: option: Add new ONDA vendor id and product id for ONDA MT825UP
+    - LP: #770050
+  * USB: option: Added support for Samsung GT-B3730/GT-B3710 LTE USB modem.
+    - LP: #770050
+  * next_pidmap: fix overflow condition
+    - LP: #770050
+  * proc: do proper range check on readdir offset
+    - LP: #770050
+  * USB: EHCI: unlink unused QHs when the controller is stopped
+    - LP: #770050
+  * USB: fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices
+    - LP: #770050
+  * USB: xhci - fix unsafe macro definitions
+    - LP: #770050
+  * USB: xhci - fix math in xhci_get_endpoint_interval()
+    - LP: #770050
+  * x86, cpu: Fix regression in AMD errata checking code
+    - LP: #770050
+  * Linux 2.6.32.39
+    - LP: #770050
+  * fs/partitions/ldm.c: fix oops caused by corrupted partition table,
+    CVE-2011-1017
+    - LP: #771382
+    - CVE-2011-1017
+  * drm/i915: set DIDL using the ACPI video output device _ADR method
+    return.
+    - LP: #775547
+  * drm/radeon/kms: MC vram map needs to be >= pci aperture size
+    - LP: #775547
+  * drm/radeon/kms: make sure blit addr masks are 64 bit
+    - LP: #775547
+  * drm/radeon/kms: fix handling of tex lookup disable in cs checker on
+    r2xx
+    - LP: #775547
+  * drm/i915: Free hardware status page on unload when physically mapped
+    - LP: #775547
+  * drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to
+    writing.
+    - LP: #775547
+  * drm/radeon/kms/atom: set sane defaults in atombios_get_encoder_mode()
+    - LP: #775547
+  * drm/radeon/kms: fix typos in disabled vbios code
+    - LP: #775547
+  * drm/radeon/kms: add workaround for dce3 ddc line vbios bug
+    - LP: #775547
+  * drm/radeon/kms: fix interlaced and doublescan handling
+    - LP: #775547
+  * drm/i915/sdvo: Always add a 30ms delay to make SDVO TV detection
+    reliable
+    - LP: #775547
+  * drm/radeon/kms: don't apply 7xx HDP flush workaround on AGP
+    - LP: #775547
+  * drm/ttm: Fix two race conditions + fix busy codepaths
+    - LP: #775547
+  * drm/i915: overlay on gen2 can't address above 1G
+    - LP: #775547
+  * drm/i915: fix memory corruption with GM965 and >4GB RAM
+    - LP: #775547
+  * drm/radeon: add quirk to make HP nx6125 laptop resume.
+    - LP: #775547
+  * drm/radeon/kms: add quirk to make HP DV5000 laptop resume
+    - LP: #775547
+  * ath: add missing regdomain pair 0x5c mapping
+    - LP: #780588
+  * block, blk-sysfs: Fix an err return path in blk_register_queue()
+    - LP: #780588
+  * p54: Initialize extra_len in p54_tx_80211
+    - LP: #780588
+  * intel-iommu: Unlink domain from iommu
+    - LP: #780588
+  * intel-iommu: Fix get_domain_for_dev() error path
+    - LP: #780588
+  * NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount
+    - LP: #780588
+  * serial/imx: read cts state only after acking cts change irq
+    - LP: #780588
+  * ASoC: Fix output PGA enabling in wm_hubs CODECs
+    - LP: #780588
+  * kconfig: Avoid buffer underrun in choice input
+    - LP: #780588
+  * UBIFS: fix master node recovery
+    - LP: #780588
+  * Remove extra struct page member from the buffer info structure
+    - LP: #780588
+  * dasd: correct device table
+    - LP: #780588
+  * iwlagn: Support new 5000 microcode.
+    - LP: #780588
+  * atl1c: duplicate atl1c_get_tpd
+    - LP: #780588
+  * udp: Fix bogus UFO packet generation
+    - LP: #780588
+  * slub: fix panic with DISCONTIGMEM
+    - LP: #780588
+  * set memory ranges in N_NORMAL_MEMORY when onlined
+    - LP: #780588
+  * FLEXCOP-PCI: fix __xlate_proc_name-warning for flexcop-pci
+    - LP: #780588
+  * m68k/mm: Set all online nodes in N_NORMAL_MEMORY
+    - LP: #780588
+  * nfs: don't lose MS_SYNCHRONOUS on remount of noac mount
+    - LP: #780588
+  * NFSv4.1: Ensure state manager thread dies on last umount
+    - LP: #780588
+  * agp: fix arbitrary kernel memory writes
+    - LP: #780588
+  * agp: fix OOM and buffer overflow
+    - LP: #780588
+  * Input: xen-kbdfront - fix mouse getting stuck after save/restore
+    - LP: #780588
+  * pmcraid: reject negative request size
+    - LP: #780588
+  * mpt2sas: prevent heap overflows and unchecked reads
+    - LP: #780588
+  * put stricter guards on queue dead checks
+    - LP: #780588
+  * mmc: sdhci-pci: Fix error case in sdhci_pci_probe_slot()
+    - LP: #780588
+  * mmc: sdhci: Check mrq->cmd in sdhci_tasklet_finish
+    - LP: #780588
+  * mmc: sdhci: Check mrq != NULL in sdhci_tasklet_finish
+    - LP: #780588
+  * USB: fix regression in usbip by setting has_tt flag
+    - LP: #780588
+  * af_unix: Only allow recv on connected seqpacket sockets.
+    - LP: #780588
+  * ARM: 6891/1: prevent heap corruption in OABI semtimedop
+    - LP: #780588
+  * i8k: Tell gcc that *regs gets clobbered
+    - LP: #780588
+  * Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again)
+    - LP: #780588
+  * Open with O_CREAT flag set fails to open existing files on non writable
+    directories
+    - LP: #780588
+  * can: Add missing socket check in can/bcm release.
+    - LP: #780588
+  * netxen: module firmware hints
+    - LP: #780588
+  * bnx2x: declare MODULE_FIRMWARE
+    - LP: #780588
+  * cxgb3: declare MODULE_FIRMWARE
+    - LP: #780588
+  * myri10ge: declare MODULE_FIRMWARE
+    - LP: #780588
+  * netx: declare MODULE_FIRMWARE
+    - LP: #780588
+  * pcnet-cs: declare MODULE_FIRMWARE
+    - LP: #780588
+  * spider-net: declare MODULE_FIRMWARE
+    - LP: #780588
+  * tms380tr: declare MODULE_FIRMWARE
+    - LP: #780588
+  * Input: Add support of Synaptics Clickpad device
+    - LP: #780588
+  * Input: elantech - do not advertise relative events
+    - LP: #780588
+  * Input: elantech - fix firmware version check
+    - LP: #780588
+  * Input: elantech - allow forcing Elantech protocol
+    - LP: #780588
+  * Input: elantech - ignore high bits in the position coordinates
+    - LP: #780588
+  * Input: elantech - use all 3 bytes when checking version
+    - LP: #780588
+  * Input: elantech - relax signature checks
+    - LP: #780588
+  * Input: elantech - discard the first 2 positions on some firmwares
+    - LP: #780588
+  * Staging: rtl8192su: check for skb == NULL
+    - LP: #780588
+  * Staging: rtl8192su: Clean up in case of an error in module
+    initialisation
+    - LP: #780588
+  * Staging: rtl8192su: Fix procfs code for interfaces not named wlan0
+    - LP: #780588
+  * Staging: rtl8192su: remove device ids
+    - LP: #780588
+  * Staging: rtl8192su: add device ids
+    - LP: #780588
+  * USB: retain USB device power/wakeup setting across reconfiguration
+    - LP: #780588
+  * USB: don't enable remote wakeup by default
+    - LP: #780588
+  * USB: teach "devices" file about Wireless and SuperSpeed USB
+    - LP: #780588
+  * GFS2: Clean up gfs2_adjust_quota() and do_glock()
+    - LP: #780588
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - LP: #780588
+  * GFS2: BUG in gfs2_adjust_quota
+    - LP: #780588
+  * SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494)
+    - LP: #780588
+  * nfs4: Ensure that ACL pages sent over NFS were not allocated from the
+    slab (v3)
+    - LP: #780588
+  * nfs: fix compilation warning
+    - LP: #780588
+  * Fix corrupted OSF partition table parsing
+    - LP: #780588
+  * Increase OSF partition limit from 8 to 18
+    - LP: #780588
+  * Please add support for Microsoft MN-120 PCMCIA network card
+    - LP: #780588
+  * hwmon: (applesmc) Add iMac9,1 and MacBookPro2,2 support
+    - LP: #780588
+  * hwmon: (applesmc) Add support for MacBook Pro 5,3 and 5,4
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 6
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 7
+    - LP: #780588
+  * hwmon: (applesmc) Add MacBookAir3,1(3,2) support
+    - LP: #780588
+  * ALSA: emux: Add trivial compat ioctl handler
+    - LP: #780588
+  * ALSA: powermac - Reverse HP detection on G4 DA
+    - LP: #780588
+  * ALSA: powermac - Lineout detection on G4 DA
+    - LP: #780588
+  * ALSA: hda - Add support for the new 27 inch IMacs
+    - LP: #780588
+  * ALSA: hda - MacBookPro 5,3 line-in support
+    - LP: #780588
+  * ALSA: hda - Add model=mbp55 entry for MacBookPro 7,1
+    - LP: #780588
+  * ALSA: hda - MacBookAir3,1(3,2) alsa support
+    - LP: #780588
+  * virtio_net: fix oom handling on tx
+    - LP: #780588
+  * mac80211: Add define for TX headroom reserved by mac80211 itself.
+    - LP: #780588
+  * rt2x00: Centralize setting of extra TX headroom requested by rt2x00.
+    - LP: #780588
+  * rt2x00: Properly request tx headroom for alignment operations.
+    - LP: #780588
+  * rt2x00: use correct headroom for transmission
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 6,2
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 7,1
+    - LP: #780588
+  * Bluetooth: Add MacBookAir3,1(2) support
+    - LP: #780588
+  * perf tools: Display better error messages on missing packages
+    - LP: #780588
+  * perf tools: Add 'make DEBUG=1' to remove the -O6 cflag
+    - LP: #780588
+  * perf tools: Test -fstack-protector-all compiler option for inclusion in
+    CFLAGS
+    - LP: #780588
+  * perf tools: Support static build
+    - LP: #780588
+  * perf tools: Add V=2 option to help debug config issues
+    - LP: #780588
+  * perf tools: Suggest static libraries as well
+    - LP: #780588
+  * perf: Use default compiler mode by default
+    - LP: #780588
+  * perf tools: Move QUIET_STDERR def to before first use
+    - LP: #780588
+  * perf tools: Check if /dev/null can be used as the -o gcc argument
+    - LP: #780588
+  * perf symbols: allow forcing use of cplus_demangle
+    - LP: #780588
+  * V4L/DVB: Add Elgato EyeTV Diversity to dibcom driver
+    - LP: #780588
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #780588
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #780588
+  * b43: Fix warning at drivers/mmc/core/core.c:237 in mmc_wait_for_cmd
+    - LP: #780588
+  * econet: Fix redeclaration of symbol len
+    - LP: #780588
+  * econet: fix CVE-2010-3848
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop to the DMI whitelist
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #780588
+  * scsi_dh_emc: fix mode select request setup
+    - LP: #780588
+  * scsi_dh_emc: request flag cleanup
+    - LP: #780588
+  * cifs: fix another memleak, in cifs_root_iget
+    - LP: #780588
+  * e1000e: Reset 82577/82578 PHY before first PHY register read
+    - LP: #780588
+  * e1000: fix Tx hangs by disabling 64-bit DMA
+    - LP: #780588
+  * btrfs: Require CAP_SYS_ADMIN for filesystem rebalance
+    - LP: #780588
+  * af_unix: limit recursion level
+    - LP: #780588
+  * init, sched: Fix race between init and kthreadd
+    - LP: #780588
+  * backlight: MacBookAir3,1(3,2) mbp-nvidia-bl support
+    - LP: #780588
+  * bonding: Ensure that we unshare skbs prior to calling pskb_may_pull
+    - LP: #780588
+  * HID: add MacBookAir 3,1 and 3,2 support
+    - LP: #780588
+  * intel-iommu: Force-disable IOMMU for iGFX on broken Cantiga revisions.
+    - LP: #780588
+  * ipg: Remove device claimed by dl2k from pci id table
+    - LP: #780588
+  * ipv6: Silence privacy extensions initialization
+    - LP: #780588
+  * l2tp: Fix UDP socket reference count bugs in the pppol2tp driver
+    - LP: #780588
+  * MIPS: DMA: Fix computation of DMA flags from device's
+    coherent_dma_mask.
+    - LP: #780588
+  * mpt2sas: fix the incorrect scsi_dma_map error checking
+    - LP: #780588
+  * Phonet: device notifier only runs on initial namespace
+    - LP: #780588
+  * powerpc/boot/dts: Install dts from the right directory
+    - LP: #780588
+  * rt2500usb: fallback to SW encryption for TKIP+AES
+    - LP: #780588
+  * sata_via: Delay on vt6420 when starting ATAPI DMA write
+    - LP: #780588
+  * tehuti: Firmware filename is tehuti/bdx.bin
+    - LP: #780588
+  * wireless: b43: fix error path in SDIO
+    - LP: #780588
+  * libata: set queue DMA alignment to sector size for ATAPI too
+    - LP: #780588
+  * usb: musb: core: set has_tt flag
+    - LP: #780588
+  * iwlwifi: fix skb usage after free
+    - LP: #780588
+  * can: add missing socket check in can/raw release
+    - LP: #780588
+  * fix oops in scsi_run_queue()
+    - LP: #780588
+  * Linux 2.6.32.40
+    - LP: #780588
+  * PCI: allow matching of prefetchable resources to non-prefetchable
+    windows
+    - LP: #424142
+  * cifs: check for bytes_remaining going to zero in CIFS_SessSetup
+    - LP: #788602
+  * Validate size of EFI GUID partition entries.
+    - LP: #788602
+  * dccp: handle invalid feature options length
+    - LP: #788602
+  * CIFS: Fix memory over bound bug in cifs_parse_mount_options
+    - LP: #788602
+  * Fix time() inconsistencies caused by intermediate xtime_cache values
+    being read
+    - LP: #788602
+  * ehea: fix wrongly reported speed and port
+    - LP: #788602
+  * NET: slip, fix ldisc->open retval
+    - LP: #788602
+  * ne-h8300: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * hydra: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * libertas: fix cmdpendingq locking
+    - LP: #788602
+  * zorro8390: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * cifs: add fallback in is_path_accessible for old servers
+    - LP: #788602
+  * x86, AMD: Fix ARAT feature setting again
+    - LP: #788602
+  * clocksource: Install completely before selecting
+    - LP: #788602
+  * tick: Clear broadcast active bit when switching to oneshot
+    - LP: #788602
+  * x86, apic: Fix spurious error interrupts triggering on all non-boot APs
+    - LP: #788602
+  * x86, mce, AMD: Fix leaving freed data in a list
+    - LP: #788602
+  * megaraid_sas: Sanity check user supplied length before passing it to
+    dma_alloc_coherent()
+    - LP: #788602
+  * vmxnet3: Fix inconsistent LRO state after initialization
+    - LP: #788602
+  * netxen: Remove references to unified firmware file
+    - LP: #788602
+  * Linux 2.6.32.41
+    - LP: #788602
+  * drm/radeon/kms: fix bad shift in atom iio table parser
+    - LP: #788602
+  * Linux 2.6.32.41+drm33.18
+    - LP: #788602
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 01 Jun 2011 16:22:08 +0200
+
+linux-ec2 (2.6.32-316.31) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * XEN: x86: Flush TLB if PGD entry is changed in i386 PAE mode
+    - LP: #742056
+  * XEN: x86: Emit "mem=nopentium ignored" warning when not supported
+    - LP: #742056
+  * XEN: x86: Fix panic when handling "mem={invalid}" param
+    - LP: #742056
+  * XEN: x86/mm: Handle mm_fault_error() in kernel space
+    - LP: #742056
+  * SAUCE: XEN: Do not force sched_clock_stable
+    - LP: #727459
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 02 May 2011 15:17:30 +0200
+
+linux-ec2 (2.6.32-316.30) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #767978
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-32.62
+
+  [ Ubuntu: 2.6.32-32.62 ]
+
+  * Release Tracking Bug
+    - LP: #767370
+  * (config) Disable CONFIG_NET_NS
+    - LP: #720095
+  * Revert "drm/radeon/kms: Fix retrying ttm_bo_init() after it failed
+    once."
+    - LP: #736234
+  * Revert "drm/radeon: fall back to GTT if bo creation/validation in VRAM
+    fails."
+    - LP: #736234
+  * x86: pvclock: Move scale_delta into common header
+  * KVM: x86: Fix a possible backwards warp of kvmclock
+  * KVM: x86: Fix kvmclock bug
+  * cpuset: add a missing unlock in cpuset_write_resmask()
+    - LP: #736234
+  * keyboard: integer underflow bug
+    - LP: #736234
+  * RxRPC: Fix v1 keys
+    - LP: #736234
+  * ixgbe: fix for 82599 erratum on Header Splitting
+    - LP: #736234
+  * mm: fix possible cause of a page_mapped BUG
+    - LP: #736234
+  * powerpc/kdump: CPUs assume the context of the oopsing CPU
+    - LP: #736234
+  * powerpc/kdump: Use chip->shutdown to disable IRQs
+    - LP: #736234
+  * powerpc: Use more accurate limit for first segment memory allocations
+    - LP: #736234
+  * powerpc/pseries: Add hcall to read 4 ptes at a time in real mode
+    - LP: #736234
+  * powerpc/kexec: Speedup kexec hash PTE tear down
+    - LP: #736234
+  * powerpc/crashdump: Do not fail on NULL pointer dereferencing
+    - LP: #736234
+  * powerpc/kexec: Fix orphaned offline CPUs across kexec
+    - LP: #736234
+  * netfilter: nf_log: avoid oops in (un)bind with invalid nfproto values
+    - LP: #736234
+  * nfsd: wrong index used in inner loop
+    - LP: #736234
+  * r8169: use RxFIFO overflow workaround for 8168c chipset.
+    - LP: #736234
+  * Staging: comedi: jr3_pci: Don't ioremap too much space. Check result.
+    - LP: #736234
+  * net: don't allow CAP_NET_ADMIN to load non-netdev kernel modules,
+    CVE-2011-1019
+    - LP: #736234
+    - CVE-2011-1019
+  * ip6ip6: autoload ip6 tunnel
+    - LP: #736234
+  * Linux 2.6.32.33
+    - LP: #736234
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934, #736234
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934, #736234
+  * drm: fix unsigned vs signed comparison issue in modeset ctl ioctl,
+    CVE-2011-1013
+    - LP: #736234
+    - CVE-2011-1013
+  * Linux 2.6.32.33+drm33.15
+    - LP: #736234
+  * econet: Fix crash in aun_incoming(). CVE-2010-4342
+    - LP: #736394
+    - CVE-2010-4342
+  * igb: only use vlan_gro_receive if vlans are registered, CVE-2010-4263
+    - LP: #737024
+    - CVE-2010-4263
+  * irda: prevent integer underflow in IRLMP_ENUMDEVICES, CVE-2010-4529
+    - LP: #737823
+    - CVE-2010-4529
+  * hwmon/f71882fg: Set platform drvdata to NULL later
+    - LP: #742056
+  * mtd: add "platform:" prefix for platform modalias
+    - LP: #742056
+  * libata: no special completion processing for EH commands
+    - LP: #742056
+  * MIPS: MTX-1: Make au1000_eth probe all PHY addresses
+    - LP: #742056
+  * x86/mm: Handle mm_fault_error() in kernel space
+    - LP: #742056
+  * ftrace: Fix memory leak with function graph and cpu hotplug
+    - LP: #742056
+  * x86: Fix panic when handling "mem={invalid}" param
+    - LP: #553464, #742056
+  * x86: Emit "mem=nopentium ignored" warning when not supported
+    - LP: #553464, #742056
+  * ahci: AHCI and RAID mode SATA patch for Intel Patsburg DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel DH89xxCC DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel Patsburg SATA RAID controller
+    - LP: #742056
+  * RDMA/cma: Fix crash in request handlers
+    - LP: #742056
+  * IB/cm: Bump reference count on cm_id before invoking callback
+    - LP: #742056
+  * ath9k_hw: Fix incorrect macversion and macrev checks
+    - LP: #742056
+  * USB: serial/kobil_sct, fix potential tty NULL dereference
+    - LP: #742056
+  * USB: serial: ch341: add new id
+    - LP: #742056
+  * xhci: Fix cycle bit calculation during stall handling.
+    - LP: #742056
+  * ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
+    - LP: #742056
+  * PCI: remove quirk for pre-production systems
+    - LP: #742056
+  * PCI: add more checking to ICH region quirks
+    - LP: #742056
+  * PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH
+    - LP: #742056
+  * PCI: sysfs: Fix failure path for addition of "vpd" attribute
+    - LP: #742056
+  * ALSA: ctxfi - Fix incorrect SPDIF status bit mask
+    - LP: #742056
+  * ALSA: ctxfi - Fix SPDIF status retrieval
+    - LP: #742056
+  * ALSA: ctxfi - Clear input settings before initialization
+    - LP: #742056
+  * SUNRPC: Ensure we always run the tk_callback before tk_action
+    - LP: #742056
+  * perf, powerpc: Handle events that raise an exception without
+    overflowing
+    - LP: #742056
+  * ext3: Always set dx_node's fake_dirent explicitly.
+    - LP: #742056
+  * call_function_many: fix list delete vs add race
+    - LP: #742056
+  * call_function_many: add missing ordering
+    - LP: #742056
+  * x86: Flush TLB if PGD entry is changed in i386 PAE mode
+    - LP: #742056
+  * isdn: avoid calling tty_ldisc_flush() in atomic context
+    - LP: #742056
+  * smp_call_function_many: handle concurrent clearing of mask
+    - LP: #742056
+  * fix per-cpu flag problem in the cpu affinity checkers
+    - LP: #742056
+  * i2c: Fix typo in instantiating-devices document
+    - LP: #742056
+  * mmc: sdio: remember new card RCA when redetecting card
+    - LP: #742056
+  * powerpc/kexec: Fix race in kexec shutdown
+    - LP: #742056
+  * powerpc/kdump: Fix race in kdump shutdown
+    - LP: #742056
+  * powerpc: rtas_flash needs to use rtas_data_buf
+    - LP: #742056
+  * x86, binutils, xen: Fix another wrong size directive
+    - LP: #742056
+  * hwmon: (sht15) Fix integer overflow in humidity calculation
+    - LP: #742056
+  * Linux 2.6.32.34
+    - LP: #742056
+  * Linux 2.6.32.35
+    - LP: #742056
+  * aio: wake all waiters when destroying ctx
+    - LP: #744921
+  * shmem: let shared anonymous be nonlinear again
+    - LP: #744921
+  * PCI hotplug: acpiphp: set current_state to D0 in register_slot
+    - LP: #744921
+  * xen: set max_pfn_mapped to the last pfn mapped
+    - LP: #744921
+  * PCI: return correct value when writing to the "reset" attribute
+    - LP: #744921
+  * Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal
+    code
+    - LP: #744921
+  * ext3: skip orphan cleanup on rocompat fs
+    - LP: #744921
+  * procfs: fix /proc/<pid>/maps heap check
+    - LP: #744921
+  * proc: protect mm start_code/end_code in /proc/pid/stat, CVE-2011-0726
+    - LP: #744921
+    - CVE-2011-0726
+  * fbcon: Bugfix soft cursor detection in Tile Blitting
+    - LP: #744921
+  * nfsd41: modify the members value of nfsd4_op_flags
+    - LP: #744921
+  * nfsd: wrong index used in inner loop
+    - LP: #744921
+  * uvcvideo: Fix uvc_fixup_video_ctrl() format search
+    - LP: #744921
+  * ehci-hcd: Bug fix: don't set a QH's Halt bit
+    - LP: #744921
+  * USB: uss720 fixup refcount position
+    - LP: #744921
+  * USB: cdc-acm: fix memory corruption / panic
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference on disconnect
+    - LP: #744921
+  * Input: xen-kbdfront - advertise either absolute or relative coordinates
+    - LP: #744921
+  * SUNRPC: Never reuse the socket port after an xs_close()
+    - LP: #744921
+  * fs: call security_d_instantiate in d_obtain_alias V2
+    - LP: #744921
+  * dcdbas: force SMI to happen when expected
+    - LP: #744921
+  * Linux 2.6.32.36
+    - LP: #744921
+  * drm/radeon/kms: check AA resolve registers on r300, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * drm/radeon: fix regression with AA resolve checking, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * xen: events: do not unmask event channels on resume
+    - LP: #681083
+  * drm/radeon/kms: check AA resolve registers on r300
+    - LP: #754584
+  * drm/radeon: fix regression with AA resolve checking
+    - LP: #754584
+  * Linux 2.6.32.36+drm33.16
+    - LP: #754584
+  * ALSA: hda - Fix SPDIF out regression on ALC889
+    - LP: #764685
+  * ALSA: Fix yet another race in disconnection
+    - LP: #764685
+  * perf: Better fit max unprivileged mlock pages for tools needs
+    - LP: #764685
+  * myri10ge: fix rmmod crash
+    - LP: #764685
+  * cciss: fix lost command issue
+    - LP: #764685
+  * sound/oss/opl3: validate voice and channel indexes
+    - LP: #764685
+  * mac80211: initialize sta->last_rx in sta_info_alloc
+    - LP: #764685
+  * ses: show devices for enclosures with no page 7
+    - LP: #764685
+  * ses: Avoid kernel panic when lun 0 is not mapped
+    - LP: #764685
+  * eCryptfs: Unlock page in write_begin error path
+    - LP: #764685
+  * eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix
+    - LP: #764685
+  * staging: usbip: bugfixes related to kthread conversion
+    - LP: #764685
+  * staging: usbip: bugfix add number of packets for isochronous frames
+    - LP: #764685
+  * staging: usbip: bugfix for isochronous packets and optimization
+    - LP: #764685
+  * staging: hv: Fix GARP not sent after Quick Migration
+    - LP: #764685
+  * staging: hv: use sync_bitops when interacting with the hypervisor
+    - LP: #764685
+  * Relax si_code check in rt_sigqueueinfo and rt_tgsigqueueinfo
+    - LP: #764685
+  * xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1
+    - LP: #764685
+  * irda: validate peer name and attribute lengths
+    - LP: #764685
+  * irda: prevent heap corruption on invalid nickname
+    - LP: #764685
+  * nilfs2: fix data loss in mmap page write for hole blocks
+    - LP: #764685
+  * ASoC: Explicitly say registerless widgets have no register
+    - LP: #764685
+  * ALSA: ens1371: fix Creative Ectiva support
+    - LP: #764685
+  * ROSE: prevent heap corruption with bad facilities
+    - LP: #764685
+  * Btrfs: Fix uninitialized root flags for subvolumes
+    - LP: #764685
+  * x86, mtrr, pat: Fix one cpu getting out of sync during resume
+    - LP: #764685
+  * ath9k: fix a chip wakeup related crash in ath9k_start
+    - LP: #764685
+  * UBIFS: do not read flash unnecessarily
+    - LP: #764685
+  * UBIFS: fix oops on error path in read_pnode
+    - LP: #764685
+  * UBIFS: fix debugging failure in dbg_check_space_info
+    - LP: #764685
+  * quota: Don't write quota info in dquot_commit()
+    - LP: #764685
+  * mm: avoid wrapping vm_pgoff in mremap()
+    - LP: #764685
+  * p54usb: IDs for two new devices
+    - LP: #764685
+  * b43: allocate receive buffers big enough for max frame len + offset
+    - LP: #764685
+  * Bluetooth: sco: fix information leak to userspace
+    - LP: #764685
+  * bridge: netfilter: fix information leak
+    - LP: #764685
+  * Bluetooth: bnep: fix buffer overflow
+    - LP: #764685
+  * Bluetooth: add support for Apple MacBook Pro 8,2
+    - LP: #764685
+  * Treat writes as new when holes span across page boundaries
+    - LP: #764685
+  * char/tpm: Fix unitialized usage of data buffer
+    - LP: #764685
+  * netfilter: ip_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: arp_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: ipt_CLUSTERIP: fix buffer overflow
+    - LP: #764685
+  * ipv6: netfilter: ip6_tables: fix infoleak to userspace
+    - LP: #764685
+  * mfd: ab3100: world-writable debugfs *_priv files
+    - LP: #764685
+  * drivers/rtc/rtc-ds1511.c: world-writable sysfs nvram file
+    - LP: #764685
+  * drivers/misc/ep93xx_pwm.c: world-writable sysfs files
+    - LP: #764685
+  * econet: 4 byte infoleak to the network
+    - LP: #764685
+  * sound/oss: remove offset from load_patch callbacks
+    - LP: #764685
+  * sound: oss: midi_synth: check get_user() return value
+    - LP: #764685
+  * repair gdbstub to match the gdbserial protocol specification
+    - LP: #764685
+  * gro: Reset dev pointer on reuse
+    - LP: #764685
+  * gro: reset skb_iif on reuse
+    - LP: #764685
+  * x86, amd-ucode: Remove needless log messages
+    - LP: #764685
+  * x86, microcode, AMD: Extend ucode size verification
+    - LP: #764685
+  * powerpc/kexec: Add ifdef CONFIG_PPC_STD_MMU_64 to PPC64 code
+    - LP: #764685
+  * powerpc: Fix default_machine_crash_shutdown #ifdef botch
+    - LP: #764685
+  * Squashfs: handle corruption of directory structure
+    - LP: #764685
+  * sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
+    - LP: #764685
+  * atm/solos-pci: Don't include frame pseudo-header on transmit hex-dump
+    - LP: #764685
+  * ext4: fix credits computing for indirect mapped files
+    - LP: #764685
+  * nfsd: fix auth_domain reference leak on nlm operations
+    - LP: #764685
+  * CAN: Use inode instead of kernel address for /proc file
+    - LP: #764685
+  * exec: make argv/envp memory visible to oom-killer
+    - LP: #764685
+  * exec: copy-and-paste the fixes into compat_do_execve() paths
+    - LP: #764685
+  * xfs: zero proper structure size for geometry calls
+    - LP: #764685
+  * Linux 2.6.32.37
+    - LP: #764685
+  * Linux 2.6.32.38
+    - LP: #764685
+
+ -- Brad Figg <brad.figg@canonical.com>  Wed, 20 Apr 2011 18:25:39 -0700
+
+linux-ec2 (2.6.32-315.29) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-31.61
+
+  [ Ubuntu: 2.6.32-31.61 ]
+
+  * Release Tracking Bug
+    - LP: #754842
+  * x86, quirk: Fix SB600 revision check
+    - LP: #742056
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 14 Apr 2011 18:28:11 +0200
+
+linux-ec2 (2.6.32-315.28) lucid-proposed; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-31.60
+
+  [ Ubuntu: 2.6.32-31.60 ]
+
+  * Release Tracking Bug
+    - LP: #734950
+  * SAUCE: Clear new_profile in error path
+    - LP: #732700
+  * [Config] CONFIG_BOOT_PRINTK_DELAY=y
+    - LP: #733191
+  * Revert "drm/radeon/bo: add some fallback placements for VRAM only
+    objects."
+    - LP: #652934
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934
+  * xfs: always use iget in bulkstat
+    - LP: #692848
+  * drm/radeon/kms: make the mac rv630 quirk generic
+    - LP: #728687
+  * drm/radeon/kms: add pll debugging output
+    - LP: #728687
+  * drm/radeon: remove 0x4243 pci id
+    - LP: #728687
+  * drm/radeon/kms: fix s/r issues with bios scratch regs
+    - LP: #728687
+  * drm/i915/lvds: Add AOpen i915GMm-HFS to the list of false-positive LVDS
+    - LP: #728687
+  * drm/i915: Add dependency on CONFIG_TMPFS
+    - LP: #728687
+  * Linux 2.6.32.29+drm33.14
+    - LP: #728687
+  * NFSD: memory corruption due to writing beyond the stat array
+    - LP: #728687
+  * mptfusion: mptctl_release is required in mptctl.c
+    - LP: #728687
+  * mptfusion: Fix Incorrect return value in mptscsih_dev_reset
+    - LP: #728687
+  * ocfs2_connection_find() returns pointer to bad structure
+    - LP: #728687
+  * x25: decrement netdev reference counts on unload
+    - LP: #728687
+  * x86, hpet: Disable per-cpu hpet timer if ARAT is supported
+    - LP: #728687
+  * OHCI: work around for nVidia shutdown problem
+    - LP: #728687
+  * x86/pvclock: Zero last_value on resume
+    - LP: #728687
+  * av7110: check for negative array offset
+    - LP: #728687
+  * CRED: Fix get_task_cred() and task_state() to not resurrect dead
+    credentials
+    - LP: #728687
+  * bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion
+    - LP: #728687
+  * CRED: Fix kernel panic upon security_file_alloc() failure.
+    - LP: #728687
+  * CRED: Fix BUG() upon security_cred_alloc_blank() failure
+    - LP: #728687
+  * CRED: Fix memory and refcount leaks upon security_prepare_creds()
+    failure
+    - LP: #728687
+  * sendfile(): check f_op.splice_write() rather than f_op.sendpage()
+    - LP: #728687
+  * isdn: hisax: Replace the bogus access to irq stats
+    - LP: #728687
+  * ixgbe: add support for 82599 based Express Module X520-P2
+    - LP: #728687
+  * ixgbe: prevent speculative processing of descriptors before ready
+    - LP: #728687
+  * scsi_dh_alua: add netapp to dev list
+    - LP: #728687
+  * scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list
+    - LP: #728687
+  * dm raid1: fail writes if errors are not handled and log fails
+    - LP: #728687
+  * GFS2: Fix bmap allocation corner-case bug
+    - LP: #728687
+  * dm raid1: fix null pointer dereference in suspend
+    - LP: #728687
+  * sunrpc/cache: fix module refcnt leak in a failure path
+    - LP: #728687
+  * be2net: Maintain tx and rx counters in driver
+    - LP: #728687
+  * tcp: Make TCP_MAXSEG minimum more correct.
+    - LP: #728687
+  * nfsd: correctly handle return value from nfsd_map_name_to_*
+    - LP: #728687
+  * s390: remove task_show_regs
+    - LP: #728687
+  * PM / Hibernate: Return error code when alloc_image_page() fails
+    - LP: #728687
+  * fs/partitions: Validate map_count in Mac partition tables
+    - LP: #728687
+  * ALSA: HDA: Add position_fix quirk for an Asus device
+    - LP: #718402, #728687
+  * ALSA: caiaq - Fix possible string-buffer overflow
+    - LP: #728687
+  * radio-aimslab.c needs #include <linux/delay.h>
+    - LP: #728687
+  * ARM: Ensure predictable endian state on signal handler entry
+    - LP: #728687
+  * acer-wmi: Fix capitalisation of GUID
+    - LP: #728687
+  * eCryptfs: Copy up lower inode attrs in getattr
+    - LP: #728687
+  * platform: x86: acer-wmi: world-writable sysfs threeg file
+    - LP: #728687
+  * platform: x86: asus_acpi: world-writable procfs files
+    - LP: #728687
+  * platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial
+    files
+    - LP: #728687
+  * genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now
+    - LP: #728687
+  * usb: musb: omap2430: fix kernel panic on reboot
+    - LP: #728687
+  * USB: add quirks entry for Keytouch QWERTY Panel
+    - LP: #728687
+  * USB: Add Samsung SGH-I500/Android modem ID switch to visor driver
+    - LP: #728687
+  * USB: Add quirk for Samsung Android phone modem
+    - LP: #728687
+  * p54pci: update receive dma buffers before and after processing
+    - LP: #728687
+  * sierra: add new ID for Airprime/Sierra USB IP modem
+    - LP: #728687
+  * staging: usbip: vhci: update reference count for usb_device
+    - LP: #728687
+  * staging: usbip: vhci: give back URBs from in-flight unlink requests
+    - LP: #728687
+  * staging: usbip: vhci: refuse to enqueue for dead connections
+    - LP: #728687
+  * staging: usbip: vhci: use urb->dev->portnum to find port
+    - LP: #728687
+  * epoll: prevent creating circular epoll structures
+    - LP: #728687
+  * ldm: corrupted partition table can cause kernel oops
+    - LP: #728687
+  * md: correctly handle probe of an 'mdp' device.
+    - LP: #728687
+  * x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems
+    - LP: #728687
+  * xhci: Avoid BUG() in interrupt context
+    - LP: #728687
+  * xhci: Clarify some expressions in the TRB math
+    - LP: #728687
+  * xhci: Fix errors in the running total calculations in the TRB math
+    - LP: #728687
+  * xhci: Fix an error in count_sg_trbs_needed()
+    - LP: #728687
+  * x25: Do not reference freed memory.
+    - LP: #728687
+  * Linux 2.6.32.30
+    - LP: #728687
+  * Linux 2.6.32.31
+    - LP: #728687
+  * Ocfs2/refcounttree: Fix a bug for refcounttree to writeback clusters in
+    a right number.
+    - LP: #731226
+  * mfd: Fix NULL pointer due to non-initialized ucb1x00-ts absinfo
+    - LP: #731226
+  * x86: Use u32 instead of long to set reset vector back to 0
+    - LP: #731226
+  * fuse: fix hang of single threaded fuseblk filesystem
+    - LP: #731226
+  * clockevents: Prevent oneshot mode when broadcast device is periodic
+    - LP: #731226
+  * ext2: Fix link count corruption under heavy link+rename load
+    - LP: #731226
+  * sctp: Fix oops when sending queued ASCONF chunks
+    - LP: #731226
+  * virtio: set pci bus master enable bit
+    - LP: #731226
+  * netxen: fix set mac addr
+    - LP: #731226
+  * HID: add support for Acan FG-8100 barcode reader
+    - LP: #731226
+  * p54usb: add Senao NUB-350 usbid
+    - LP: #731226
+  * dccp: fix oops on Reset after close
+    - LP: #731226
+  * e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup
+    instead
+    - LP: #731226
+  * r8169: disable ASPM
+    - LP: #731226
+  * usb: iowarrior: don't trust report_size for buffer size
+    - LP: #731226
+  * arp_notify: unconditionally send gratuitous ARP for
+    NETDEV_NOTIFY_PEERS.
+    - LP: #731226
+  * CIFS: Fix oplock break handling (try #2)
+    - LP: #731226
+  * Linux 2.6.32.32
+    - LP: #731226
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 18 Mar 2011 18:23:16 +0100
+
+linux-ec2 (2.6.32-314.27) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Release Tracking Bug
+    - LP: #728089
+
+  [ Stefan Bader ]
+
+  * SAUCE: XEN: Import f9dee15f07cc3e6625734f3cf667054a5ff5ac2b
+    - LP: #717177
+  * SAUCE: XEN: Import 65d64895d4ed4250448ac6906de25777470b5180
+    - LP: #717177
+  * SAUCE: XEN: Import cf383fb0c59287a81d6e71ebb7fafffd104a3983
+    - LP: #717177
+  * SAUCE: XEN: Import ffd91af58e011821332cc56019d1709f7d9a8a54
+    - LP: #717177
+  * SAUCE: XEN: Import 97a21d3ae6477ef00e39f21e47ce767a8ca1a22a
+    - LP: #717177
+  * SAUCE: XEN: Import b5d6492343e5897eba863ed1d08ca51552657d1f
+    - LP: #717177
+  * SAUCE: XEN: Import 9fb860778805809529f4c27b896370f2a945e945
+    - LP: #717177
+  * SAUCE: XEN: Import 20af80bf13116eb2d0d4bd6a307a4260cd277095
+    - LP: #717177
+  * SAUCE: XEN: Import 481710c9b5d154e81d388e9460fa2851a4ea7c94
+    - LP: #717177
+  * SAUCE: XEN: Import 9512754e274895426d5305d09a4c667d8621f420
+    - LP: #717177
+  * SAUCE: XEN: Update import 2444b629ee518745f54c2f7cf9e4de3d48e834cb
+    - LP: #717177
+  * SAUCE: XEN: Import 28995d0c0ef1958ecffdcc80091c46233daea29a
+    - LP: #717177
+  * SAUCE: XEN: Import fc04955bae3662eecaa8216694fd82b36256cfc6
+    - LP: #717177
+  * SAUCE: XEN: Import 4bbd3ea6754dc11fdb96a8ab9dfa13e24b1a6599
+    - LP: #717177
+  * SAUCE: XEN: Import 5a6ca212d5400dfcd8734da1f282b83a01a04d9e
+    - LP: #717177
+  * SAUCE: XEN: Import cde0c191416d1470a2aa30d893f7ea987363386b
+    - LP: #717177
+  * SAUCE: XEN: Import fe304738902627ec07c5195664ddb7a6f7750272
+    - LP: #717177
+  * SAUCE: XEN: Import 941f392437b3005d2d220a7254d48fbc342b6829
+    - LP: #717177
+  * SAUCE: XEN: Import 7ad50ac196fde9cf57a55b5908764227d9d7f8e6
+    - LP: #717177
+  * SAUCE: XEN: Import eeb31bcc98f8497dc83c5e7c8ef5c9a9438cb689
+    - LP: #717177
+  * SAUCE: XEN: Import d5324680becdc93bd37cbbc9581c727959c57ad9
+    - LP: #717177
+  * SAUCE: XEN: Import f2bb11b1573330fca6ddba33a5cff3695d1a690c
+    - LP: #717177
+  * SAUCE: XEN: Import 7e3ff59bf997c554ebd14b17b9ba4246448e80c7
+    - LP: #717177
+  * SAUCE: XEN: Import c19aaf77a85ba61de84de2bf6922e269d78223a0
+    - LP: #717177
+  * SAUCE: XEN: Import 77b49ffdcd22f66180778085716512d508ab2617
+    - LP: #717177
+  * SAUCE: XEN: Import 34ebf644aafc699db42a5c2d109b6f057ee6b4f3
+    - LP: #717177
+  * SAUCE: XEN: Import c4dad435c692830c634ab7001b62b6a90b5ae530
+    - LP: #717177
+  * SAUCE: XEN: Import 52c82b295371158c61f8b06d7a03daaaeedfea00
+    - LP: #717177
+  * SAUCE: XEN: Import f3a8bea7094f487ed6139a6b6254d0e4147a866d
+    - LP: #717177
+  * SAUCE: XEN: Import 2e911f0f7f1590fc8c4cb2a331ac1c1799a8385b
+    - LP: #717177
+  * SAUCE: XEN: Import 7aa0c2220a675805f38b43313228544a0cce7488
+    - LP: #717177
+  * SAUCE: XEN: Import a805c0009da4770f72dab3f3c71cd263f79894aa
+    - LP: #717177
+  * SAUCE: XEN: Import 26ab8408157fbbc669e1aab1f271bb3cb1c433d0
+    - LP: #717177
+  * SAUCE: XEN: Import ca51d9445c9b51d6b1c800c9c04e5472d55f0845
+    - LP: #717177
+  * SAUCE: XEN: Import 831d52bc153971b70e64eccfbed2b232394f22f8
+    - LP: #723819
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-30.59
+
+  [ Ubuntu: 2.6.32-30.59 ]
+
+  * Release Tracking Bug
+    - LP: #727336
+  * [Config] CONFIG_IRQ_TIME_ACCOUNTING=n
+    - LP: #723819
+  * virtio_net: Add schedule check to napi_enable call
+    - LP: #579276
+  * NFS: fix the return value of nfs_file_fsync()
+    - LP: #585657
+  * block: check for proper length of iov entries earlier in
+    blk_rq_map_user_iov(), CVE-2010-4163
+    - LP: #721504
+    - CVE-2010-4163
+  * filter: make sure filters dont read uninitialized memory
+    - LP: #721282
+    - CVE-2010-4158
+  * tty: Make tiocgicount a handler, CVE-2010-4076, CVE-2010-4077
+    - LP: #720189
+    - CVE-2010-4077
+  * staging: usbip: remove double giveback of URB
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD SB800
+    - LP: #723819
+  * rt2x00: add device id for windy31 usb device
+    - LP: #723819
+  * ALSA: snd-usb-us122l: Fix missing NULL checks
+    - LP: #723819
+  * hwmon: (via686a) Initialize fan_div values
+    - LP: #723819
+  * USB: serial: handle Data Carrier Detect changes
+    - LP: #723819
+  * USB: CP210x Add two device IDs
+    - LP: #723819
+  * USB: CP210x Removed incorrect device ID
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for Cypress ATACB
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for TrekStor DataStation maxi g.u
+    external hard drive enclosure
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for CamSport Evo
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for Coby MP3 player
+    - LP: #723819
+  * USB: serial: Updated support for ICOM devices
+    - LP: #723819
+  * USB: adding USB support for Cinterion's HC2x, EU3 and PH8 products
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD Hudson
+    - LP: #723819
+  * USB: EHCI: fix DMA deallocation bug
+    - LP: #723819
+  * USB: g_printer: fix bug in module parameter definitions
+    - LP: #723819
+  * USB: io_edgeport: fix the reported firmware major and minor
+    - LP: #723819
+  * USB: ti_usb: fix module removal
+    - LP: #723819
+  * USB: Storage: Add unusual_devs entry for VTech Kidizoom
+    - LP: #723819
+  * USB: ftdi_sio: add ST Micro Connect Lite uart support
+    - LP: #723819
+  * USB: cdc-acm: Adding second ACM channel support for Nokia N8
+    - LP: #723819
+  * USB: ftdi_sio: Add VID=0x0647, PID=0x0100 for Acton Research
+    spectrograph
+    - LP: #723819
+  * USB: prevent buggy hubs from crashing the USB stack
+    - LP: #723819
+  * staging: comedi: add support for newer jr3 1-channel pci board
+    - LP: #723819
+  * staging: comedi: ni_labpc: Use shared IRQ for PCMCIA card
+    - LP: #723819
+  * Staging: hv: fix sysfs symlink on hv block device
+    - LP: #723819
+  * staging: hv: Enable sending GARP packet after live migration
+    - LP: #723819
+  * hvc_iucv: allocate memory buffers for IUCV in zone DMA
+    - LP: #723819
+  * iwlagn: enable only rfkill interrupt when device is down
+    - LP: #723819
+  * ath9k: Fix bug in delimiter padding computation
+    - LP: #723819
+  * correct vdso version string
+    - LP: #723819
+  * fix medium error problems with some arrays which can cause data
+    corruption
+    - LP: #723819
+  * libsas: fix runaway error handler problem
+    - LP: #723819
+  * mpt2sas: Fix device removal handshake for zoned devices
+    - LP: #723819
+  * mpt2sas: Correct resizing calculation for max_queue_depth
+    - LP: #723819
+  * mpt2sas: Kernel Panic during Large Topology discovery
+    - LP: #723819
+  * radio-aimslab.c: Fix gcc 4.5+ bug
+    - LP: #723819
+  * em28xx: Fix audio input for Terratec Grabby
+    - LP: #723819
+  * ALSA : au88x0 - Limit number of channels to fix Oops via OSS emu
+    - LP: #723819
+  * ALSA: HDA: Fix dmesg output of HDMI supported bits
+    - LP: #723819
+  * ALSA: hda - Fix memory leaks in conexant jack arrays
+    - LP: #723819
+  * input: bcm5974: Add support for MacBookAir3
+    - LP: #723819
+  * ALSA: hrtimer: handle delayed timer interrupts
+    - LP: #723819
+  * ASoC: WM8990: msleep() takes milliseconds not jiffies
+    - LP: #723819
+  * ASoC: Blackfin AC97: fix build error after multi-component update
+    - LP: #723819
+  * NFS: Fix "kernel BUG at fs/aio.c:554!"
+    - LP: #723819
+  * rtc-cmos: fix suspend/resume
+    - LP: #723819
+  * iwlagn: Re-enable RF_KILL interrupt when down
+    - LP: #723819
+  * rapidio: fix hang on RapidIO doorbell queue full condition
+    - LP: #723819
+  * PCI: pci-stub: ignore zero-length id parameters
+    - LP: #723819
+  * virtio: remove virtio-pci root device
+    - LP: #723819
+  * ds2760_battery: Fix calculation of time_to_empty_now
+    - LP: #723819
+  * p54: fix sequence no. accounting off-by-one error
+    - LP: #723819
+  * i2c: Unregister dummy devices last on adapter removal
+    - LP: #723819
+  * serial: unbreak billionton CF card
+    - LP: #723819
+  * ptrace: use safer wake up on ptrace_detach()
+    - LP: #723819
+  * x86, mtrr: Avoid MTRR reprogramming on BP during boot on UP platforms
+    - LP: #723819
+  * fix jiffy calculations in calibrate_delay_direct to handle overflow
+    - LP: #723819
+  * USB: serial: pl2303: Hybrid reader Uniform HCR331
+    - LP: #723819
+  * drivers: update to pl2303 usb-serial to support Motorola cables
+    - LP: #723819
+  * klist: Fix object alignment on 64-bit.
+    - LP: #723819
+  * powerpc: Fix some 6xx/7xxx CPU setup functions
+    - LP: #723819
+  * parisc : Remove broken line wrapping handling pdc_iodc_print()
+    - LP: #723819
+  * kernel/smp.c: fix smp_call_function_many() SMP race
+    - LP: #723819
+  * hostap_cs: fix sleeping function called from invalid context
+    - LP: #723819
+  * md: fix regression with re-adding devices to arrays with no metadata
+    - LP: #723819
+  * pata_mpc52xx: inherit from ata_bmdma_port_ops
+    - LP: #723819
+  * TPM: Long default timeout fix
+    - LP: #723819
+  * tpm_tis: Use timeouts returned from TPM
+    - LP: #723819
+  * SELinux: define permissions for DCB netlink messages
+    - LP: #723819
+  * SELinux: do not compute transition labels on mountpoint labeled
+    filesystems
+    - LP: #723819
+  * ieee80211: correct IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK macro
+    - LP: #723819
+  * dm: dont take i_mutex to change device size
+    - LP: #723819
+  * dm mpath: disable blk_abort_queue
+    - LP: #723819
+  * x86, mm: avoid possible bogus tlb entries by clearing prev mm_cpumask
+    after switching mm
+    - LP: #723819
+  * usb: Realloc xHCI structures after a hub is verified.
+    - LP: #723819
+  * sched: Remove USER_SCHED
+    - LP: #723819
+  * sched: Remove remaining USER_SCHED code
+    - LP: #723819
+  * sched: Move sched_avg_update() to update_cpu_load()
+    - LP: #723819
+  * sched: Increment cache_nice_tries only on periodic lb
+    - LP: #723819
+  * sched: Try not to migrate higher priority RT tasks
+    - LP: #723819
+  * sched: Give CPU bound RT tasks preference
+    - LP: #723819
+  * sched: suppress RCU lockdep splat in task_fork_fair
+    - LP: #723819
+  * sched: fix RCU lockdep splat from task_group()
+    - LP: #723819
+  * sched: Do not consider SCHED_IDLE tasks to be cache hot
+    - LP: #723819
+  * sched: Set group_imb only a task can be pulled from the busiest cpu
+    - LP: #723819
+  * sched: Force balancing on newidle balance if local group has capacity
+    - LP: #723819
+  * sched: Drop group_capacity to 1 only if local group has extra capacity
+    - LP: #723819
+  * sched: Fix softirq time accounting
+    - LP: #723819
+  * sched: Consolidate account_system_vtime extern declaration
+    - LP: #723819
+  * sched: Remove unused PF_ALIGNWARN flag
+    - LP: #723819
+  * sched: Add a PF flag for ksoftirqd identification
+    - LP: #723819
+  * sched: Add IRQ_TIME_ACCOUNTING, finer accounting of irq time
+    - LP: #723819
+  * x86: Add IRQ_TIME_ACCOUNTING
+    - LP: #723819
+  * sched: Do not account irq time to current task
+    - LP: #723819
+  * sched: Remove irq time from available CPU power
+    - LP: #723819
+  * sched: Call tick_check_idle before __irq_enter
+    - LP: #723819
+  * sched: Export account_system_vtime()
+    - LP: #723819
+  * sched, cgroup: Fixup broken cgroup movement
+    - LP: #723819
+  * sched: Use group weight, idle cpu metrics to fix imbalances during idle
+    - LP: #723819
+  * sched: Fix cross-sched-class wakeup preemption
+    - LP: #723819
+  * sched: Fix volanomark performance regression
+    - LP: #723819
+  * sched: Fix idle balancing
+    - LP: #723819
+  * sched: Fix wake_affine() vs RT tasks
+    - LP: #723819
+  * sched: Remove some dead code
+    - LP: #723819
+  * kernel/user.c: add lock release annotation on free_user()
+    - LP: #723819
+  * Linux 2.6.32.29
+    - LP: #723819
+  * rds: Integer overflow in RDS cmsg handling, CVE-2010-4175
+    - LP: #721455
+    - CVE-2010-4175
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 02 Mar 2011 14:59:29 +0100
+
+linux-ec2 (2.6.32-313.26) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #716657
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #712864
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-29.58
+
+  [ Ubuntu: 2.6.32-29.58 ]
+
+  * Release Tracking Bug
+    - LP: #716551
+  * net: fix rds_iovec page count overflow, CVE-2010-3865
+    - LP: #709153
+    - CVE-2010-3865
+  * net: ax25: fix information leak to userland, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: ax25: fix information leak to userland harder, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: packet: fix information leak to userland, CVE-2010-3876
+    - LP: #710714
+    - CVE-2010-3876
+  * net: tipc: fix information leak to userland, CVE-2010-3877
+    - LP: #711291
+    - CVE-2010-3877
+  * inet_diag: Make sure we actually run the same bytecode we audited,
+    CVE-2010-3880
+    - LP: #711865
+    - CVE-2010-3880
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 10 Feb 2011 11:03:57 -0800
+
+linux-ec2 (2.6.32-313.25) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Tracking Bug
+    - LP: #708890
+
+  [ Andrew Dickinson ]
+
+  * SAUCE: sched: Prevent divide by zero when cpu_power is 0
+    - LP: #614853
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-29.57
+
+  [ Stefan Bader ]
+
+  * SAUCE: sched: Try tp catch cpu_power being set to 0
+    - LP: #614853
+
+  [ Upstream Kernel Changes ]
+
+  * SRU: xen: events: do not unmask event channels on resume
+    - LP: #681083
+
+  [ Ubuntu: 2.6.32-29.57 ]
+
+  * Tracking Bug
+    - LP: #708864
+  * [Config] Set CONFIG_NR_CPUS=256 for amd64 server
+    - LP: #706058
+  * Input: i8042 - introduce 'notimeout' blacklist for Dell Vostro V13
+    - LP: #380126
+  * tun: avoid BUG, dump packet on GSO errors
+    - LP: #698883
+  * TTY: Fix error return from tty_ldisc_open()
+    - LP: #705045
+  * x86, hotplug: Use mwait to offline a processor, fix the legacy case
+    - LP: #705045
+  * fuse: verify ioctl retries
+    - LP: #705045
+  * fuse: fix ioctl when server is 32bit
+    - LP: #705045
+  * ALSA: hda: Use model=lg quirk for LG P1 Express to enable playback and
+    capture
+    - LP: #595482, #705045
+  * nohz: Fix printk_needs_cpu() return value on offline cpus
+    - LP: #705045
+  * nohz: Fix get_next_timer_interrupt() vs cpu hotplug
+    - LP: #705045
+  * nfsd: Fix possible BUG_ON firing in set_change_info
+    - LP: #705045
+  * NFS: Fix fcntl F_GETLK not reporting some conflicts
+    - LP: #705045
+  * sunrpc: prevent use-after-free on clearing XPT_BUSY
+    - LP: #705045
+  * hwmon: (adm1026) Allow 1 as a valid divider value
+    - LP: #705045
+  * hwmon: (adm1026) Fix setting fan_div
+    - LP: #705045
+  * amd64_edac: Fix interleaving check
+    - LP: #705045
+  * IB/uverbs: Handle large number of entries in poll CQ
+    - LP: #705045
+  * PM / Hibernate: Fix PM_POST_* notification with user-space suspend
+    - LP: #705045
+  * ACPICA: Fix Scope() op in module level code
+    - LP: #705045
+  * ACPI: EC: Add another dmi match entry for MSI hardware
+    - LP: #705045
+  * orinoco: fix TKIP countermeasure behaviour
+    - LP: #705045
+  * orinoco: clear countermeasure setting on commit
+    - LP: #705045
+  * x86, amd: Fix panic on AMD CPU family 0x15
+    - LP: #705045
+  * md: fix bug with re-adding of partially recovered device.
+    - LP: #705045
+  * tracing: Fix panic when lseek() called on "trace" opened for writing
+    - LP: #705045
+  * x86, gcc-4.6: Use gcc -m options when building vdso
+    - LP: #705045
+  * x86: Enable the intr-remap fault handling after local APIC setup
+    - LP: #705045
+  * x86, vt-d: Handle previous faults after enabling fault handling
+    - LP: #705045
+  * x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode
+    - LP: #705045
+  * x86, vt-d: Quirk for masking vtd spec errors to platform error handling
+    logic
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove, again
+    - LP: #705045
+  * HID: hidraw: fix window in hidraw_release
+    - LP: #705045
+  * bfa: fix system crash when reading sysfs fc_host statistics
+    - LP: #705045
+  * net: release dst entry while cache-hot for GSO case too
+    - LP: #705045
+  * install_special_mapping skips security_file_mmap check.
+    - LP: #705045
+  * USB: misc: uss720.c: add another vendor/product ID
+    - LP: #705045
+  * USB: ftdi_sio: Add D.O.Tec PID
+    - LP: #705045
+  * USB: usb-storage: unusual_devs entry for the Samsung YP-CP3
+    - LP: #705045
+  * p54usb: add 5 more USBIDs
+    - LP: #705045
+  * p54usb: New USB ID for Gemtek WUBI-100GW
+    - LP: #705045
+  * sound: Prevent buffer overflow in OSS load_mixer_volumes
+    - LP: #705045
+  * mv_xor: fix race in tasklet function
+    - LP: #705045
+  * ima: fix add LSM rule bug
+    - LP: #705045
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #705045
+  * ALSA: hda: Use LPIB quirk for Dell Inspiron m101z/1120
+    - LP: #705045
+  * block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead
+    - LP: #705045
+  * sctp: Fix a race between ICMP protocol unreachable and connect()
+    - LP: #705045
+  * posix-cpu-timers: workaround to suppress the problems with mt exec
+    - LP: #705045
+  * Linux 2.6.32.28
+    - LP: #705045
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * drm/ttm: Clear the ghost cpu_writers flag on
+    ttm_buffer_object_transfer.
+    - LP: #708769
+  * drm/kms: remove spaces from connector names (v2)
+    - LP: #708769
+  * Linux 2.6.32.28+drm33.13
+    - LP: #708769
+
+  [ Ubuntu: 2.6.32-28.56 ]
+
+  * Tracking Bug
+    - LP: #705565
+  * Just a build number increment for a new upload. There was an issue
+    in the previous upload that prevented ARMEL from building. The
+    issue has been resolved in the PPA and a new upload should produce
+    the requisite images.
+
+  [ Ubuntu: 2.6.32-28.55 ]
+
+  * Another version bump because of abi check failure
+  * Tracking Bug
+    - LP: #699885
+
+  [ Ubuntu: 2.6.32-28.54 ]
+
+  * Another version bump because of upload failure
+
+  [ Ubuntu: 2.6.32-28.53 ]
+
+  * Another version bump because of upload failure
+
+ -- Brad Figg <brad.figg@canonical.com>  Wed, 19 Jan 2011 12:23:49 -0800
+
+linux-ec2 (2.6.32-312.24) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Tracking bug
+  - LP: #698345
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-28.52
+
+  [ Ubuntu: 2.6.32-28.52 ]
+
+
+  [ Ubuntu: 2.6.32-28.51 ]
+
+  * bumped version due to build fail
+
+  [ Ubuntu: 2.6.32-28.50 ]
+
+  * SAUCE: Change nodelayacct boot parameter polarity.
+    - LP: #493156
+  * [Config] CONFIG_TASK_DELAY_ACCT=y
+    - LP: #493156
+  * ipc: initialize structure memory to zero for compat functions
+  * tcp: Increase TCP_MAXSEG socket option minimum.
+    - CVE-2010-4165
+  * perf_events: Fix perf_counter_mmap() hook in mprotect()
+    - CVE-2010-4169
+  * af_unix: limit unix_tot_inflight
+    - CVE-2010-4249
+  * AppArmor: fix the upper bound check for the next/check table
+    - LP: #581525
+  * NFS: Fix panic after nfs_umount()
+    - LP: #683938
+  * block: Ensure physical block size is unsigned int
+    - LP: #688669
+  * block: limit vec count in bio_kmalloc() and bio_alloc_map_data()
+    - LP: #688669
+  * block: take care not to overflow when calculating total iov length
+    - LP: #688669
+  * block: check for proper length of iov entries in blk_rq_map_user_iov()
+    - LP: #688669
+  * jme: Fix PHY power-off error
+    - LP: #688669
+  * irda: Fix parameter extraction stack overflow
+    - LP: #688669
+  * irda: Fix heap memory corruption in iriap.c
+    - LP: #688669
+  * i2c-pca-platform: Change device name of request_irq
+    - LP: #688669
+  * microblaze: Fix build with make 3.82
+    - LP: #688669
+  * Staging: asus_oled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * Staging: asus_oled: fix up my fixup for some sysfs attribute
+    permissions
+    - LP: #688669
+  * Staging: line6: fix up some sysfs attribute permissions
+    - LP: #688669
+  * hpet: fix unwanted interrupt due to stale irq status bit
+    - LP: #688669
+  * hpet: unmap unused I/O space
+    - LP: #688669
+  * olpc_battery: Fix endian neutral breakage for s16 values
+    - LP: #688669
+  * percpu: fix list_head init bug in __percpu_counter_init()
+    - LP: #688669
+  * um: remove PAGE_SIZE alignment in linker script causing kernel
+    segfault.
+    - LP: #688669
+  * um: fix global timer issue when using CONFIG_NO_HZ
+    - LP: #688669
+  * numa: fix slab_node(MPOL_BIND)
+    - LP: #688669
+  * hwmon: (lm85) Fix ADT7468 frequency table
+    - LP: #688669
+  * mm: fix return value of scan_lru_pages in memory unplug
+    - LP: #688669
+  * mm: fix is_mem_section_removable() page_order BUG_ON check
+    - LP: #688669
+  * ssb: b43-pci-bridge: Add new vendor for BCM4318
+    - LP: #688669
+  * sgi-xpc: XPC fails to discover partitions with all nasids above 128
+    - LP: #688669
+  * xen: ensure that all event channels start off bound to VCPU 0
+    - LP: #688669
+  * xen: don't bother to stop other cpus on shutdown/reboot
+    - LP: #688669
+  * sys_semctl: fix kernel stack leakage
+    - LP: #688669
+  * net: NETIF_F_HW_CSUM does not imply FCoE CRC offload
+    - LP: #688669
+  * drivers/char/vt_ioctl.c: fix VT_OPENQRY error value
+    - LP: #688669
+  * viafb: use proper register for colour when doing fill ops
+    - LP: #688669
+  * eCryptfs: Clear LOOKUP_OPEN flag when creating lower file
+    - LP: #688669
+  * md/raid1: really fix recovery looping when single good device fails.
+    - LP: #688669
+  * md: fix return value of rdev_size_change()
+    - LP: #688669
+  * x86: AMD Northbridge: Verify NB's node is online
+    - LP: #688669
+  * tty: prevent DOS in the flush_to_ldisc
+    - LP: #688669
+  * TTY: restore tty_ldisc_wait_idle
+    - LP: #688669
+  * tty_ldisc: Fix BUG() on hangup
+    - LP: #688669
+  * TTY: ldisc, fix open flag handling
+    - LP: #688669
+  * KVM: VMX: fix vmx null pointer dereference on debug register access
+    - LP: #688669
+    - CVE-2010-0435
+  * KVM: x86: fix information leak to userland
+    - LP: #688669
+  * firewire: cdev: fix information leak
+    - LP: #688669
+  * firewire: core: fix an information leak
+    - LP: #688669
+  * firewire: ohci: fix buffer overflow in AR split packet handling
+    - LP: #688669
+  * firewire: ohci: fix race in AR split packet handling
+    - LP: #688669
+  * ALSA: ac97: Apply quirk for Dell Latitude D610 binding Master and
+    Headphone controls
+    - LP: #669279, #688669
+  * ALSA: HDA: Add an extra DAC for Realtek ALC887-VD
+    - LP: #688669
+  * ALSA: hda: Use "alienware" model quirk for another SSID
+    - LP: #683695, #688669
+  * netfilter: nf_conntrack: allow nf_ct_alloc_hashtable() to get highmem
+    pages
+    - LP: #688669
+  * latencytop: fix per task accumulator
+    - LP: #688669
+  * mm/vfs: revalidate page->mapping in do_generic_file_read()
+    - LP: #688669
+  * bio: take care not overflow page count when mapping/copying user data
+    - LP: #688669
+  * libata-scsi passthru: fix bug which truncated LBA48 return values
+    - LP: #688669
+  * libata: fix NULL sdev dereference race in atapi_qc_complete()
+    - LP: #688669
+  * PCI: fix size checks for mmap() on /proc/bus/pci files
+    - LP: #688669
+  * PCI: fix offset check for sysfs mmapped files
+    - LP: #688669
+  * efifb: check that the base address is plausible on pci systems
+    - LP: #688669
+  * USB: gadget: AT91: fix typo in atmel_usba_udc driver
+    - LP: #688669
+  * USB: ftdi_sio: add device IDs for Milkymist One JTAG/serial
+    - LP: #688669
+  * USB: option: fix when the driver is loaded incorrectly for some Huawei
+    devices.
+    - LP: #688669
+  * usb: misc: sisusbvga: fix information leak to userland
+    - LP: #688669
+  * usb: misc: iowarrior: fix information leak to userland
+    - LP: #688669
+  * usb: core: fix information leak to userland
+    - LP: #688669
+  * USB: EHCI: fix obscure race in ehci_endpoint_disable
+    - LP: #688669
+  * USB: storage: sierra_ms: fix sysfs file attribute
+    - LP: #688669
+  * USB: atm: ueagle-atm: fix up some permissions on the sysfs files
+    - LP: #688669
+  * USB: misc: cypress_cy7c63: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: misc: usbled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes"
+    - LP: #688669
+  * USB: misc: trancevibrator: fix up a sysfs attribute permission
+    - LP: #688669
+  * USB: misc: usbsevseg: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: Add ID for RT Systems USB-29B radio cable
+    - LP: #688669
+  * USB: serial: ftdi_sio: Vardaan USB RS422/485 converter PID added
+    - LP: #688669
+  * acpi-cpufreq: fix a memleak when unloading driver
+    - LP: #688669
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #688669
+  * fuse: fix attributes after open(O_TRUNC)
+    - LP: #688669
+  * do_exit(): make sure that we run with get_fs() == USER_DS
+    - LP: #688669
+  * uml: disable winch irq before freeing handler data
+    - LP: #688669
+  * backlight: grab ops_lock before testing bd->ops
+    - LP: #688669
+  * nommu: yield CPU while disposing VM
+    - LP: #688669
+  * DECnet: don't leak uninitialized stack byte
+    - LP: #688669
+  * ARM: 6489/1: thumb2: fix incorrect optimisation in usracc
+    - LP: #688669
+  * ARM: 6482/2: Fix find_next_zero_bit and related assembly
+    - LP: #688669
+  * Staging: frontier: fix up some sysfs attribute permissions
+    - LP: #688669
+  * staging: rtl8187se: Change panic to warn when RF switch turned off
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_ioctl
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_write
+    - LP: #688669
+  * gianfar: Fix crashes on RX path (Was Re: [Bugme-new] [Bug 19692] New:
+    linux-2.6.36-rc5 crash with gianfar ethernet at full line rate traffic)
+    - LP: #688669
+  * Limit sysctl_tcp_mem and sysctl_udp_mem initializers to prevent integer
+    overflows.
+    - LP: #688669
+  * sparc64: Fix race in signal instruction flushing.
+    - LP: #688669
+  * sparc: Don't mask signal when we can't setup signal frame.
+    - LP: #688669
+  * sparc: Prevent no-handler signal syscall restart recursion.
+    - LP: #688669
+  * x86, UV: Delete unneeded boot messages
+    - LP: #688669
+  * x86, UV: Fix initialization of max_pnode
+    - LP: #688669
+  * drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook
+    Pro 5,1
+    - LP: #688669
+  * efifb: support the EFI framebuffer on more Apple hardware
+    - LP: #688669
+  * V4L/DVB (13154): uvcvideo: Handle garbage at the end of streaming
+    interface descriptors
+    - LP: #688669
+  * Input: i8042 - add Sony VAIO VPCZ122GX to nomux list
+    - LP: #688669
+  * x25: Patch to fix bug 15678 - x25 accesses fields beyond end of packet.
+    - LP: #688669
+  * memory corruption in X.25 facilities parsing
+    - LP: #688669
+  * can-bcm: fix minor heap overflow
+    - LP: #688669
+  * V4L/DVB: ivtvfb: prevent reading uninitialized stack memory
+    - LP: #688669
+  * x25: Prevent crashing when parsing bad X.25 facilities
+    - LP: #688669
+  * crypto: padlock - Fix AES-CBC handling on odd-block-sized input
+    - LP: #688669
+  * x86-32: Separate 1:1 pagetables from swapper_pg_dir
+    - LP: #688669
+  * x86, mm: Fix CONFIG_VMSPLIT_1G and 2G_OPT trampoline
+    - LP: #688669
+  * x86-32: Fix dummy trampoline-related inline stubs
+    - LP: #688669
+  * rds: Integer overflow in RDS cmsg handling
+    - LP: #688669
+  * net: Truncate recvfrom and sendto length to INT_MAX.
+    - LP: #688669
+  * net: Limit socket I/O iovec total length to INT_MAX.
+    - LP: #688669
+  * nmi: fix clock comparator revalidation
+    - LP: #688669
+  * UV - XPC: pass nasid instead of nid to gru_create_message_queue
+    - LP: #688669
+  * x86: uv: XPC receive message reuse triggers invalid BUG_ON()
+    - LP: #688669
+  * X86: uv: xpc_make_first_contact hang due to not accepting ACTIVE state
+    - LP: #688669
+  * x86: uv: xpc NULL deref when mesq becomes empty
+    - LP: #688669
+  * Linux 2.6.32.27
+    - LP: #688669
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 06 Jan 2011 14:07:09 -0800
+
+linux-ec2 (2.6.32-311.23) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-27.49
+
+  [ Upstream Kernel Changes ]
+
+  * xen, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * xen, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * xen: Match cpu_get_cap() with upstream changes
+    - LP: #668380
+
+  [ Ubuntu: 2.6.32-27.49 ]
+
+  * Revert "SAUCE: AF_ECONET prevent kernel stack overflow"
+  * Revert "SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges"
+  * Revert "SAUCE: AF_ECONET saddr->cookie prevent NULL pointer
+    dereference"
+  * [Config] Added be2net, be2scsi to udebs
+    - LP: #628776
+  * [Config] Use correct be2iscsi module name in d-i/modules/scsi-modules
+    - LP: #628776
+  * Revert "(pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume"
+  * Revert "mm: (pre-stable) Move vma_stack_continue into mm.h"
+  * x86, cpu: After uncapping CPUID, re-run CPU feature detection
+    - LP: #668380
+  * ALSA: sound/pci/rme9652: prevent reading uninitialized stack memory
+    - LP: #668380
+  * ALSA: oxygen: fix analog capture on Claro halo cards
+    - LP: #668380
+  * ALSA: hda - Add Dell Latitude E6400 model quirk
+    - LP: #643891, #668380
+  * ALSA: rawmidi: fix oops (use after free) when unloading a driver module
+    - LP: #668380
+  * USB: fix bug in initialization of interface minor numbers
+    - LP: #668380
+  * usb: musb: gadget: fix kernel panic if using out ep with FIFO_TXRX
+    style
+    - LP: #668380
+  * usb: musb: gadget: restart request on clearing endpoint halt
+    - LP: #668380
+  * oprofile: Add Support for Intel CPU Family 6 / Model 29
+    - LP: #668380
+  * RDMA/cxgb3: Turn off RX coalescing for iWARP connections
+    - LP: #668380
+  * mmc: sdhci-s3c: fix NULL ptr access in sdhci_s3c_remove
+    - LP: #668380
+  * x86/amd-iommu: Set iommu configuration flags in enable-loop
+    - LP: #668380
+  * x86/amd-iommu: Fix rounding-bug in __unmap_single
+    - LP: #668380
+  * x86/amd-iommu: Work around S3 BIOS bug
+    - LP: #668380
+  * tracing/x86: Don't use mcount in pvclock.c
+    - LP: #668380
+  * tracing/x86: Don't use mcount in kvmclock.c
+    - LP: #668380
+  * v4l1: fix 32-bit compat microcode loading translation
+    - LP: #668380
+  * V4L/DVB: cx231xx: Avoid an OOPS when card is unknown (card=0)
+    - LP: #668380
+  * V4L/DVB (13966): DVB-T regression fix for saa7134 cards
+    - LP: #668380
+  * Input: joydev - fix JSIOCSAXMAP ioctl
+    - LP: #668380
+  * x86, hpet: Fix bogus error check in hpet_assign_irq()
+    - LP: #668380
+  * x86, irq: Plug memory leak in sparse irq
+    - LP: #668380
+  * ubd: fix incorrect sector handling during request restart
+    - LP: #668380
+  * ring-buffer: Fix typo of time extends per page
+    - LP: #668380
+  * dmaengine: fix interrupt clearing for mv_xor
+    - LP: #668380
+  * hrtimer: Preserve timer state in remove_hrtimer()
+    - LP: #668380
+  * i2c-pca: Fix waitforcompletion() return value
+    - LP: #668380
+  * wext: fix potential private ioctl memory content leak
+    - LP: #668380
+  * atl1: fix resume
+    - LP: #668380
+  * x86, AMD, MCE thresholding: Fix the MCi_MISCj iteration order
+    - LP: #668380
+  * De-pessimize rds_page_copy_user
+    - LP: #668380
+  * xfrm4: strip ECN and IP Precedence bits in policy lookup
+    - LP: #668380
+  * tcp: Fix >4GB writes on 64-bit.
+    - LP: #668380
+  * net: Fix the condition passed to sk_wait_event()
+    - LP: #668380
+  * Phonet: Correct header retrieval after pskb_may_pull
+    - LP: #668380
+  * net: Fix IPv6 PMTU disc. w/ asymmetric routes
+    - LP: #668380
+  * ip: fix truesize mismatch in ip fragmentation
+    - LP: #668380
+  * net: clear heap allocations for privileged ethtool actions
+    - LP: #668380
+  * tcp: Fix race in tcp_poll
+    - LP: #668380
+  * netxen: dont set skb->truesize
+    - LP: #668380
+  * net: blackhole route should always be recalculated
+    - LP: #668380
+  * skge: add quirk to limit DMA
+    - LP: #668380
+  * r8169: allocate with GFP_KERNEL flag when able to sleep
+    - LP: #668380
+  * bsg: fix incorrect device_status value
+    - LP: #668380
+  * r6040: fix r6040_multicast_list
+    - LP: #668380
+  * r6040: Fix multicast list iteration when hash filter is used
+    - LP: #668380
+  * powerpc: Initialise paca->kstack before early_setup_secondary
+    - LP: #668380
+  * powerpc: Don't use kernel stack with translation off
+    - LP: #668380
+  * b44: fix carrier detection on bind
+    - LP: #668380
+  * ACPI: enable repeated PCIEXP wakeup by clearing PCIEXP_WAKE_STS on
+    resume
+    - LP: #613381, #668380
+  * intel_idle: PCI quirk to prevent Lenovo Ideapad s10-3 boot hang
+    - LP: #668380
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #668380
+  * ACPI: delete ZEPTO idle=nomwait DMI quirk
+    - LP: #668380
+  * ACPI: Disable Windows Vista compatibility for Toshiba P305D
+    - LP: #668380
+  * x86: detect scattered cpuid features earlier
+    - LP: #668380
+  * fix 2.6.32.23 suspend regression caused by commit 6f6198a
+    - LP: #668380
+  * setup_arg_pages: diagnose excessive argument size
+    - LP: #668380
+  * execve: improve interactivity with large arguments
+    - LP: #668380
+  * execve: make responsive to SIGKILL with large arguments
+    - LP: #668380
+  * Phonet: disable network namespace support
+    - LP: #668380
+  * mm: Move vma_stack_continue into mm.h
+    - LP: #668380
+  * Linux 2.6.32.25
+    - LP: #668380
+  * xfs: validate untrusted inode numbers during lookup
+    - CVE-2010-2943
+  * xfs: rename XFS_IGET_BULKSTAT to XFS_IGET_UNTRUSTED
+    - CVE-2010-2943
+  * xfs: remove block number from inode lookup code
+    - CVE-2010-2943
+  * xfs: fix untrusted inode number lookup
+    - CVE-2010-2943
+  * drm/i915: Sanity check pread/pwrite
+    - CVE-2010-2962
+  * drm/i915: Rephrase pwrite bounds checking to avoid any potential
+    overflow
+    - CVE-2010-2962
+  * net: clear heap allocation for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3861
+  * ipc: shm: fix information leak to userland
+    - CVE-2010-4072
+  * staging: usbip: Notify usb core of port status changes
+    - LP: #681132
+  * staging: usbip: Process event flags without delay
+    - LP: #681132
+  * powerpc/perf: Fix sampling enable for PPC970
+    - LP: #681132
+  * pcmcia: synclink_cs: fix information leak to userland
+    - LP: #681132
+  * sched: Fix string comparison in /proc/sched_features
+    - LP: #681132
+  * bluetooth: Fix missing NULL check
+    - LP: #681132
+  * futex: Fix errors in nested key ref-counting
+    - LP: #681132
+  * mm, x86: Saving vmcore with non-lazy freeing of vmas
+    - LP: #681132
+  * x86, cpu: Fix renamed, not-yet-shipping AMD CPUID feature bit
+    - LP: #681132
+  * x86, kexec: Make sure to stop all CPUs before exiting the kernel
+    - LP: #681132
+  * x86, olpc: Don't retry EC commands forever
+    - LP: #681132
+  * x86, mtrr: Assume SYS_CFG[Tom2ForceMemTypeWB] exists on all future AMD
+    CPUs
+    - LP: #681132
+  * x86, intr-remap: Set redirection hint in the IRTE
+    - LP: #681132
+  * x86, kdump: Change copy_oldmem_page() to use cached addressing
+    - LP: #681132
+  * KVM: SVM: Fix wrong intercept masks on 32 bit
+    - LP: #681132
+  * KVM: MMU: fix direct sps access corrupted
+    - LP: #681132
+  * KVM: MMU: fix conflict access permissions in direct sp
+    - LP: #681132
+  * KVM: VMX: Fix host GDT.LIMIT corruption
+    - LP: #681132
+  * KVM: SVM: Adjust tsc_offset only if tsc_unstable
+    - LP: #681132
+  * KVM: x86: Fix SVM VMCB reset
+    - LP: #681132
+  * KVM: x86: Move TSC reset out of vmcb_init
+    - LP: #681132
+  * KVM: Fix fs/gs reload oops with invalid ldt
+    - LP: #681132
+  * KVM: Correct ordering of ldt reload wrt fs/gs reload
+  * KVM: VMX: Fix host userspace gsbase corruption
+  * pipe: fix failure to return error code on ->confirm()
+    - LP: #681132
+  * p54usb: fix off-by-one on !CONFIG_PM
+    - LP: #681132
+  * p54usb: add five more USBIDs
+    - LP: #681132
+  * drivers/net/wireless/p54/eeprom.c: Return -ENOMEM on memory allocation
+    failure
+    - LP: #681132
+  * USB: ftdi_sio: Add PID for accesio products
+    - LP: #681132
+  * USB: add PID for FTDI based OpenDCC hardware
+    - LP: #681132
+  * USB: ftdi_sio: new VID/PIDs for various Papouch devices
+    - LP: #681132
+  * USB: ftdi_sio: add device ids for ScienceScope
+    - LP: #681132
+  * usb: musb: blackfin: call gpio_free() on error path in
+    musb_platform_init()
+    - LP: #681132
+  * USB: option: Add more ZTE modem USB id's
+    - LP: #681132
+  * USB: cp210x: Add Renesas RX-Stick device ID
+    - LP: #681132
+  * USB: cp210x: Add WAGO 750-923 Service Cable device ID
+    - LP: #681132
+  * USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request
+    failled
+    - LP: #681132
+  * USB: disable endpoints after unbinding interfaces, not before
+    - LP: #681132
+  * USB: opticon: Fix long-standing bugs in opticon driver
+    - LP: #681132
+  * USB: accept some invalid ep0-maxpacket values
+    - LP: #681132
+  * sd name space exhaustion causes system hang
+    - LP: #681132
+  * libsas: fix NCQ mixing with non-NCQ
+    - LP: #681132
+  * gdth: integer overflow in ioctl
+    - LP: #681132
+  * Fix race when removing SCSI devices
+    - LP: #681132
+  * Fix regressions in scsi_internal_device_block
+    - LP: #681132
+  * sgi-xp: incoming XPC channel messages can come in after the channel's
+    partition structures have been torn down
+    - LP: #681132
+  * Linux 2.6.32.26
+    - LP: #681132
+  * drm/radeon: fix PCI ID 5657 to be an RV410
+    - LP: #683257
+  * Linux 2.6.32.26+drm33.12
+    - LP: #683257
+  * econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849
+    - CVE-2010-3849
+  * econet: fix CVE-2010-3850
+    - CVE-2010-3850
+  * econet: fix CVE-2010-3848
+    - CVE-2010-3848
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 01 Dec 2010 08:13:05 +0100
+
+linux-ec2 (2.6.32-310.21) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-26.48
+
+  [ Ubuntu: 2.6.32-26.48 ]
+
+  * SAUCE: AF_ECONET prevent kernel stack overflow
+    - CVE-2010-3848
+  * SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges
+    - CVE-2010-3850
+  * SAUCE: AF_ECONET saddr->cookie prevent NULL pointer dereference
+    - CVE-2010-3849
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 24 Nov 2010 10:34:37 +0100
+
+linux-ec2 (2.6.32-310.20) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-26.47
+
+  [ Ubuntu: 2.6.32-26.47 ]
+
+  * Revert "SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell
+    E6510"
+  * Revert "[Config] Added be2net, be2scsi to udebs"
+  * Revert "(ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony
+    laptops with ALC269"
+  * Revert "(pre-stable) ALSA: HDA: Correctly apply position_fix quirks for
+    ATI and VIA controllers"
+  * Revert "ALSA: hda: Use LPIB for another mainboard"
+  * Revert "ALSA: hda: Use LPIB for ASUS M2V"
+  * Revert "ALSA: hda: Use LPIB for an ASUS device"
+  * Buglink Fixup for reverted unverified fixes
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 19 Nov 2010 17:03:52 +0100
+
+linux-ec2 (2.6.32-310.19) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-26.46
+
+  [ Ubuntu: 2.6.32-26.46 ]
+
+  * SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510
+    - See: #605047, #628961
+  * [Config] Added be2net, be2scsi to udebs
+    - See: #628776
+  * Revert "(pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure we shut off the panel in eDP
+    configs"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure eDP panel is turned on"
+    - LP: #645444
+  * Revert "(pre-stable) drm/radeon/kms: initialize set_surface_reg reg for
+    rs600 asic"
+    - LP: #645371
+  * Revert "drm/nouveau: Fix fbcon corruption with font width not divisible
+    by 8"
+    - LP: #663176
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #477106
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #477106
+  * hwmon: (k8temp) Differentiate between AM2 and ASB1
+    - LP: #644694
+  * xen: handle events as edge-triggered
+    - LP: #644694
+  * xen: use percpu interrupts for IPIs and VIRQs
+    - LP: #644694
+  * ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763
+    - LP: #605101, #644694
+  * sata_mv: fix broken DSM/TRIM support (v2)
+    - LP: #644694
+  * x86, tsc, sched: Recompute cyc2ns_offset's during resume from sleep
+    states
+    - LP: #644694
+  * PCI: MSI: Remove unsafe and unnecessary hardware access
+    - LP: #644694
+  * PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
+    - LP: #644694
+  * sched: kill migration thread in CPU_POST_DEAD instead of CPU_DEAD
+    - LP: #644694
+  * sched: revert stable c6fc81a sched: Fix a race between ttwu() and
+    migrate_task()
+    - LP: #644694
+  * staging: hv: Fix missing functions for net_device_ops
+    - LP: #644694
+  * staging: hv: Fixed bounce kmap problem by using correct index
+    - LP: #644694
+  * staging: hv: Fixed the value of the 64bit-hole inside ring buffer
+    - LP: #644694
+  * staging: hv: Increased storvsc ringbuffer and max_io_requests
+    - LP: #644694
+  * staging: hv: Fixed lockup problem with bounce_buffer scatter list
+    - LP: #644694
+  * fuse: flush background queue on connection close
+    - LP: #644694
+  * ath9k_hw: fix parsing of HT40 5 GHz CTLs
+    - LP: #644694
+  * ocfs2: Fix incorrect checksum validation error
+    - LP: #644694
+  * USB: ehci-ppc-of: problems in unwind
+    - LP: #644694
+  * USB: Fix kernel oops with g_ether and Windows
+    - LP: #644694
+  * USB: CP210x Add new device ID
+    - LP: #644694
+  * USB: cp210x: Add B&G H3000 link cable ID
+    - LP: #644694
+  * USB: ftdi_sio: Added custom PIDs for ChamSys products
+    - LP: #644694
+  * USB: serial: Extra device/vendor ID for mos7840 driver
+    - LP: #644694
+  * usb: serial: mos7840: Add USB ID to support the B&B Electronics
+    USOPTL4-2P.
+    - LP: #644694
+  * USB: mos7840: fix DMA buffers on stack and endianess bugs
+    - LP: #644694
+  * usb: serial: mos7840: Add USB IDs to support more B&B USB/RS485
+    converters.
+    - LP: #644694
+  * USB: Exposing second ACM channel as tty for Nokia S60 phones.
+    - LP: #644694
+  * USB: cdc-acm: add another device quirk
+    - LP: #644694
+  * USB: Expose vendor-specific ACM channel on Nokia 5230
+    - LP: #644694
+  * USB: cdc-acm: Adding second ACM channel support for various Nokia and
+    one Samsung phones
+    - LP: #644694
+  * USB: cdc-acm: Add pseudo modem without AT command capabilities
+    - LP: #644694
+  * USB: cdc-acm: Fixing crash when ACM probing interfaces with no endpoint
+    descriptors.
+    - LP: #644694
+  * ALSA: hda - Fix auto-parser of ALC269vb for HP pin NID 0x21
+    - LP: #644694
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - LP: #644694
+  * sysfs: checking for NULL instead of ERR_PTR
+    - LP: #644694
+  * tun: Don't add sysfs attributes to devices without sysfs directories
+    - LP: #644694
+  * oprofile: fix crash when accessing freed task structs
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs error handling
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs() function stub
+    - LP: #644694
+  * HID: usbhid: initialize interface pointers early enough
+    - LP: #644694
+  * HID: fix suspend crash by moving initializations earlier
+    - LP: #644694
+  * libata: skip EH autopsy and recovery during suspend
+    - LP: #644694
+  * tracing: Fix a race in function profile
+    - LP: #644694
+  * tracing: Do not allow llseek to set_ftrace_filter
+    - LP: #644694
+  * tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread
+    - LP: #644694
+  * irda: off by one
+    - LP: #644694
+  * gcov: fix null-pointer dereference for certain module types
+    - LP: #644694
+  * tmio_mmc: don't clear unhandled pending interrupts
+    - LP: #644694
+  * mmc: fix the use of kunmap_atomic() in tmio_mmc.h
+    - LP: #644694
+  * bounce: call flush_dcache_page() after bounce_copy_vec()
+    - LP: #644694
+  * kernel/groups.c: fix integer overflow in groups_search
+    - LP: #644694
+  * binfmt_misc: fix binfmt_misc priority
+    - LP: #644694
+  * Input: i8042 - fix device removal on unload
+    - LP: #644694
+  * memory hotplug: fix next block calculation in is_removable
+    - LP: #644694
+  * perf: Initialize callchains roots's childen hits
+    - LP: #644694
+  * p54: fix tx feedback status flag check
+    - LP: #644694
+  * ath5k: check return value of ieee80211_get_tx_rate
+    - LP: #644694
+  * wireless extensions: fix kernel heap content leak
+    - LP: #644694
+  * x86, tsc: Fix a preemption leak in restore_sched_clock_state()
+    - LP: #644694
+  * sched: Protect task->cpus_allowed access in sched_getaffinity()
+    - LP: #644694
+  * sched: Protect sched_rr_get_param() access to task->sched_class
+    - LP: #644694
+  * sched: Consolidate select_task_rq() callers
+    - LP: #644694
+  * sched: Remove unused cpu_nr_migrations()
+    - LP: #644694
+  * sched: Remove rq->clock coupling from set_task_cpu()
+    - LP: #644694
+  * sched: Clean up ttwu() rq locking
+    - LP: #644694
+  * sched: Sanitize fork() handling
+    - LP: #644694
+  * sched: Remove forced2_migrations stats
+    - LP: #644694
+  * sched: Make wakeup side and atomic variants of completion API irq safe
+    - LP: #644694
+  * sched: Use rcu in sys_sched_getscheduler/sys_sched_getparam()
+    - LP: #644694
+  * sched: Use rcu in sched_get/set_affinity()
+    - LP: #644694
+  * sched: Use rcu in sched_get_rr_param()
+    - LP: #644694
+  * sched: Fix set_cpu_active() in cpu_down()
+    - LP: #644694
+  * sched: Use TASK_WAKING for fork wakups
+    - LP: #644694
+  * sched: Ensure set_task_cpu() is never called on blocked tasks
+    - LP: #644694
+  * sched: Make warning less noisy
+    - LP: #644694
+  * sched: Fix broken assertion
+    - LP: #644694
+  * sched: Fix sched_exec() balancing
+    - LP: #644694
+  * sched: Fix select_task_rq() vs hotplug issues
+    - LP: #644694
+  * sched: Add pre and post wakeup hooks
+    - LP: #644694
+  * sched: Remove the cfs_rq dependency from set_task_cpu()
+    - LP: #644694
+  * sched: Fix hotplug hang
+    - LP: #644694
+  * sched: Fix fork vs hotplug vs cpuset namespaces
+    - LP: #644694
+  * sched: Fix incorrect sanity check
+    - LP: #644694
+  * sched: Fix race between ttwu() and task_rq_lock()
+    - LP: #644694
+  * sched: Extend enqueue_task to allow head queueing
+    - LP: #644694
+  * sched: Implement head queueing for sched_rt
+    - LP: #644694
+  * sched: Queue a deboosted task to the head of the RT prio queue
+    - LP: #644694
+  * sched: set_cpus_allowed_ptr(): Don't use rq->migration_thread after
+    unlock
+    - LP: #644694
+  * sched: Kill the broken and deadlockable
+    cpuset_lock/cpuset_cpus_allowed_locked code
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Take rq->lock around
+    select_fallback_rq()
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Remove retry logic
+    - LP: #644694
+  * sched: sched_exec(): Remove the select_fallback_rq() logic
+    - LP: #644694
+  * sched: _cpu_down(): Don't play with current->cpus_allowed
+    - LP: #644694
+  * sched: Make select_fallback_rq() cpuset friendly
+    - LP: #644694
+  * sched: Fix TASK_WAKING vs fork deadlock
+    - LP: #644694
+  * sched: Optimize task_rq_lock()
+    - LP: #644694
+  * sched: Fix nr_uninterruptible count
+    - LP: #644694
+  * sched: Fix rq->clock synchronization when migrating tasks
+    - LP: #644694
+  * sched: Remove unnecessary RCU exclusion
+    - LP: #644694
+  * sched: apply RCU protection to wake_affine()
+    - LP: #644694
+  * sched: Cleanup select_task_rq_fair()
+    - LP: #644694
+  * sched: More generic WAKE_AFFINE vs select_idle_sibling()
+    - LP: #644694
+  * sched: Fix vmark regression on big machines
+    - LP: #644694
+  * sched: Fix select_idle_sibling()
+    - LP: #644694
+  * sched: Pre-compute cpumask_weight(sched_domain_span(sd))
+    - LP: #644694
+  * sched: Fix select_idle_sibling() logic in select_task_rq_fair()
+    - LP: #644694
+  * sched: cpuacct: Use bigger percpu counter batch values for stats
+    counters
+    - LP: #644694
+  * ALSA: hda - Handle missing NID 0x1b on ALC259 codec
+    - LP: #644694
+  * ALSA: hda - Handle pin NID 0x1a on ALC259/269
+    - LP: #644694
+  * arm: fix really nasty sigreturn bug
+    - LP: #644694
+  * hwmon: (f75375s) Shift control mode to the correct bit position
+    - LP: #644694
+  * hwmon: (f75375s) Do not overwrite values read from registers
+    - LP: #644694
+  * apm_power: Add missing break statement
+    - LP: #644694
+  * NFS: Fix a typo in nfs_sockaddr_match_ipaddr6
+    - LP: #644694
+  * SUNRPC: Fix race corrupting rpc upcall
+    - LP: #644694
+  * Linux 2.6.32.22
+    - LP: #644694
+  * drm/i915: don't access FW_BLC_SELF on 965G
+    - LP: #645444
+  * drm/i915: gen3 page flipping fixes
+    - LP: #645444
+  * drm/i915: don't queue flips during a flip pending event
+    - LP: #645444
+  * drm/i915: Hold the spinlock whilst resetting unpin_work along error
+    path
+    - LP: #645444
+  * drm/i915: handle shared framebuffers when flipping
+    - LP: #645444
+  * drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #645444
+  * drm/i915: make sure eDP panel is turned on
+    - LP: #645444
+  * drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #645444
+  * Linux 2.6.32.22+drm33.9
+    - LP: #645444
+  * drm/radeon/kms/igp: sideport is AMD only
+    - LP: #645371
+  * drm/radeon/kms: flush HDP cache on GART table updates.
+    - LP: #645371
+  * drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush
+    - LP: #645371
+  * drm/i915: Check overlay stride errata for i830 and i845
+    - LP: #645371
+  * i915: fix ironlake edp panel setup (v4)
+    - LP: #645371
+  * drm/radeon/kms: add additional quirk for Acer rv620 laptop
+    - LP: #645371
+  * drm/i915: fixup pageflip ringbuffer commands for i8xx
+    - LP: #645371
+  * drm/i915: i8xx also doesn't like multiple oustanding pageflips
+    - LP: #645371
+  * drm/i915/edp: Flush the write before waiting for PLLs
+    - LP: #645371
+  * drm/radeon/kms: disable MSI on IGP chips
+    - LP: #645371
+  * drm/radeon/kms: don't enable MSIs on AGP boards
+    - LP: #645371
+  * drm/radeon/kms: fix typo in radeon_compute_pll_gain
+    - LP: #645371
+  * drm/radeon/kms/DCE3+: switch pads to ddc mode when going i2c
+    - LP: #645371
+  * drm/radeon/kms: fix sideport detection on newer rs880 boards
+    - LP: #645371
+  * drm/i915: Don't touch PORT_HOTPLUG_EN in intel_dp_detect()
+    - LP: #645371
+  * drm/i915: Kill dangerous pending-flip debugging
+    - LP: #645371
+  * drm/radeon/kms: release AGP bridge at suspend
+    - LP: #645371
+  * drm/radeon/kms: initialize set_surface_reg reg for rs600 asic
+    - LP: #645371
+  * drm/radeon/kms: fix a regression on r7xx AGP due to the HDP flush fix
+    - LP: #645371
+  * Linux 2.6.32.22+drm33.10
+    - LP: #645371
+  * USB: serial/mos*: prevent reading uninitialized stack memory
+    - LP: #649483
+  * sparc: Provide io{read,write}{16,32}be().
+    - LP: #649483
+  * gro: fix different skb headrooms
+    - LP: #649483
+  * gro: Re-fix different skb headrooms
+    - LP: #649483
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - LP: #649483
+  * tcp: select(writefds) don't hang up when a peer close connection
+    - LP: #649483
+  * tcp: Combat per-cpu skew in orphan tests.
+    - LP: #649483
+  * tcp: fix three tcp sysctls tuning
+    - LP: #649483
+  * bridge: Clear IPCB before possible entry into IP stack
+    - LP: #649483
+  * bridge: Clear INET control block of SKBs passed into ip_fragment().
+    - LP: #649483
+  * net: Fix oops from tcp_collapse() when using splice()
+    - LP: #649483
+  * rds: fix a leak of kernel memory
+    - LP: #649483
+  * tcp: Prevent overzealous packetization by SWS logic.
+    - LP: #649483
+  * UNIX: Do not loop forever at unix_autobind().
+    - LP: #649483
+  * r8169: fix random mdio_write failures
+    - LP: #649483
+  * r8169: fix mdio_read and update mdio_write according to hw specs
+    - LP: #649483
+  * sparc64: Get rid of indirect p1275 PROM call buffer.
+    - LP: #649483
+  * drivers/net/usb/hso.c: prevent reading uninitialized memory
+    - LP: #649483
+  * drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * drivers/net/eql.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * bonding: correctly process non-linear skbs
+    - LP: #649483
+  * Staging: vt6655: fix buffer overflow
+    - LP: #649483
+  * net/llc: make opt unsigned in llc_ui_setsockopt()
+    - LP: #649483
+  * pid: make setpgid() system call use RCU read-side critical section
+    - LP: #649483
+  * sched: Fix user time incorrectly accounted as system time on 32-bit
+    - LP: #649483
+  * oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron
+    540)
+    - LP: #649483
+  * char: Mark /dev/zero and /dev/kmem as not capable of writeback
+    - LP: #649483
+  * drivers/pci/intel-iommu.c: fix build with older gcc's
+    - LP: #649483
+  * drivers/video/sis/sis_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * percpu: fix pcpu_last_unit_cpu
+    - LP: #649483
+  * aio: check for multiplication overflow in do_io_submit
+    - LP: #649483
+  * inotify: send IN_UNMOUNT events
+    - LP: #649483
+  * SCSI: mptsas: fix hangs caused by ATA pass-through
+    - LP: #649483
+  * ext4: Fix remaining racy updates of EXT4_I(inode)->i_flags
+    - LP: #649483
+  * IA64: fix siglock
+    - LP: #649483
+  * IA64: Optimize ticket spinlocks in fsys_rt_sigprocmask
+    - LP: #649483
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - LP: #649483
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - LP: #649483
+  * xfs: prevent reading uninitialized stack memory
+    - LP: #649483
+  * drivers/video/via/ioctl.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * ACPI: disable _OSI(Windows 2009) on Asus K50IJ
+    - LP: #649483
+  * bnx2: Fix netpoll crash.
+    - LP: #649483
+  * bnx2: Fix hang during rmmod bnx2.
+    - LP: #649483
+  * AT91: change dma resource index
+    - LP: #649483
+  * cxgb3: fix hot plug removal crash
+    - LP: #649483
+  * mm: page allocator: drain per-cpu lists after direct reclaim allocation
+    fails
+    - LP: #649483
+  * mm: page allocator: calculate a better estimate of NR_FREE_PAGES when
+    memory is low and kswapd is awake
+    - LP: #649483
+  * mm: page allocator: update free page counters after pages are placed on
+    the free list
+    - LP: #649483
+  * guard page for stacks that grow upwards
+    - LP: #649483
+  * Fix unprotected access to task credentials in waitid()
+    - LP: #649483
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - LP: #649483
+  * 3c503: Fix IRQ probing
+    - LP: #649483
+  * asix: fix setting mac address for AX88772
+    - LP: #649483
+  * dasd: use correct label location for diag fba disks
+    - LP: #649483
+  * clocksource: sh_tmu: compute mult and shift before registration
+    - LP: #649483
+  * gro: Fix bogus gso_size on the first fraglist entry
+    - LP: #649483
+  * hostap_pci: set dev->base_addr during probe
+    - LP: #649483
+  * inotify: fix inotify oneshot support
+    - LP: #649483
+  * Input: add compat support for sysfs and /proc capabilities output
+    - LP: #649483
+  * MIPS: Quit using undefined behavior of ADDU in 64-bit atomic
+    operations.
+    - LP: #649483
+  * MIPS: Set io_map_base for several PCI bridges lacking it
+    - LP: #649483
+  * MIPS: uasm: Add OR instruction.
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for Promise UDMA33 cards
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for PDC2026x chipsets
+    - LP: #649483
+  * MIPS: Sibyte: Fix M3 TLB exception handler workaround.
+    - LP: #649483
+  * sis-agp: Remove SIS 760, handled by amd64-agp
+    - LP: #649483
+  * alpha: Fix printk format errors
+    - LP: #649483
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #649483
+  * Linux 2.6.32.23
+    - LP: #649483
+  * (pre-stable) [SCSI] megaraid_sas: Add new megaraid SAS 2 controller
+    support to the driver
+    - LP: #546091
+  * (pre-stable) [SCSI] megaraid_sas: allocate the application cmds to sas2
+    controller
+    - LP: #546091
+  * Xen: fix typo in previous patch
+    - LP: #655456
+  * Linux 2.6.32.24
+    - LP: #655456
+  * (ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony laptops
+    with ALC269
+    - See: #546769, #598938, #637291, #642892, #648871, #655386
+  * (pre-stable) ALSA: HDA: Correctly apply position_fix quirks for ATI and
+    VIA controllers
+    - See: #465942, #580749, #587546
+  * (pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume
+    - LP: #613381
+  * i915: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * i915_gem: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * drm/i915: Prevent double dpms on
+    - LP: #663176
+  * drm: Only decouple the old_fb from the crtc is we call mode_set*
+    - LP: #663176
+  * drm/radeon/kms: fix potential segfault in r600_ioctl_wait_idle
+    - LP: #663176
+  * drm/i915: Unset cursor if out-of-bounds upon mode change (v4)
+    - LP: #586325, #663176
+  * drm/i915: disable FBC when more than one pipe is active
+    - LP: #663176
+  * drm/radeon/kms: fix macbookpro connector quirk
+    - LP: #663176
+  * drm/nouveau: use ALIGN instead of open coding it
+    - LP: #663176
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #663176
+  * drm/i915,agp/intel: Add second set of PCI-IDs for B43
+    - LP: #640214, #663176
+  * Linux 2.6.32.24+drm33.11
+    - LP: #663176
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 26 Oct 2010 15:16:00 -0400
+
+linux-ec2 (2.6.32-309.18) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-25.45
+
+  [ Ubuntu: 2.6.32-25.45 ]
+
+  * v4l: disable dangerous buggy compat function
+    - CVE-2010-2963
+  * Local privilege escalation vulnerability in RDS sockets
+    - CVE-2010-3904
+  * mm: (pre-stable) Move vma_stack_continue into mm.h
+    - LP: #646114
+  * net sched: fix some kernel memory leaks
+    - CVE-2010-2942
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - CVE-2010-2954
+  * wireless extensions: fix kernel heap content leak
+    - CVE-2010-2955
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - CVE-2010-2960
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - CVE-2010-2960
+  * aio: check for multiplication overflow in do_io_submit
+    - CVE-2010-3067
+  * xfs: prevent reading uninitialized stack memory
+    - CVE-2010-3078
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - CVE-2010-3080
+  * niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3084
+  * rose: Fix signedness issues wrt. digi count.
+    - CVE-2010-3310
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - CVE-2010-3432
+  * Fix pktcdvd ioctl dev_minor range check
+    - CVE-2010-3437
+  * ALSA: prevent heap corruption in snd_ctl_new()
+    - CVE-2010-3442
+  * net sched: fix kernel leak in act_police
+    - CVE-2010-3477
+  * Fix out-of-bounds reading in sctp_asoc_get_hmac()
+    - CVE-2010-3705
+  * ocfs2: Don't walk off the end of fast symlinks.
+    - CVE-2010-NNN2
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 18 Oct 2010 10:01:36 +0200
+
+linux-ec2 (2.6.32-309.17) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-25.44
+
+  [ John Johansen ]
+
+  * SAUCE: Revert "sched: update load count only once per cpu in 10 tick
+    update window"
+    - LP: #574910
+
+  [ Ubuntu: 2.6.32-25.44 ]
+
+  * SAUCE: (no-up) Modularize vesafb -- fix initialization
+    - LP: #611471
+  * Revert "SAUCE: sync before umount to reduce time taken by ext4 umount"
+    - LP: #543617, #585092
+  * Revert "SAUCE: tulip: Let dmfe handle davicom on non-sparc"
+    - LP: #607824
+  * [Config] Added ums-cypress to udeb
+    - LP: #576066
+  * Revert "PCI quirk: Disable MSI on VIA K8T890 systems"
+    - LP: #607824
+  * Revert "PCI quirks: disable msi on AMD rs4xx internal gfx bridges"
+    - LP: #607824
+  * Revert "(pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting"
+    - LP: #607824
+  * Revert "jbd: jbd-debug and jbd2-debug should be writable"
+    - LP: #607824
+  * Revert "ext4: Make fsync sync new parent directories in no-journal
+    mode"
+    - LP: #615548
+  * Revert "ext4: Fix compat EXT4_IOC_ADD_GROUP"
+    - LP: #615548
+  * Revert "ext4: Conditionally define compat ioctl numbers"
+    - LP: #615548
+  * Revert "ext4: restart ext4_ext_remove_space() after transaction
+    restart"
+    - LP: #615548
+  * Revert "ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted"
+    - LP: #615548
+  * Revert "ext4: Avoid crashing on NULL ptr dereference on a filesystem
+    error"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify i_flags in struct
+    ext4_inode_info"
+    - LP: #615548
+  * Revert "ext4: Show journal_checksum option"
+    - LP: #615548
+  * Revert "ext4: check for a good block group before loading buddy pages"
+    - LP: #615548
+  * Revert "ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate"
+    - LP: #615548
+  * Revert "ext4: Remove extraneous newlines in ext4_msg() calls"
+    - LP: #615548
+  * Revert "ext4: init statistics after journal recovery"
+    - LP: #615548
+  * Revert "ext4: clean up inode bitmaps manipulation in ext4_free_inode"
+    - LP: #615548
+  * Revert "ext4: Do not zero out uninitialized extents beyond i_size"
+    - LP: #615548
+  * Revert "ext4: don't scan/accumulate more pages than mballoc will
+    allocate"
+    - LP: #615548
+  * Revert "ext4: stop issuing discards if not supported by device"
+    - LP: #615548
+  * Revert "ext4: check s_log_groups_per_flex in online resize code"
+    - LP: #615548
+  * Revert "ext4: fix quota accounting in case of fallocate"
+    - LP: #615548
+  * Revert "ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode"
+    - LP: #615548
+  * Revert "ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()"
+    - LP: #615548
+  * Revert "ext4: Remove unnecessary call to ext4_get_group_desc() in
+    mballoc"
+    - LP: #615548
+  * Revert "ext4: fix memory leaks in error path handling of
+    ext4_ext_zeroout()"
+    - LP: #615548
+  * Revert "ext4: check missed return value in ext4_sync_file()"
+    - LP: #615548
+  * Revert "ext4: Issue the discard operation *before* releasing the blocks
+    to be reused"
+    - LP: #615548
+  * Revert "ext4: Fix buffer head leaks after calls to
+    ext4_get_inode_loc()"
+    - LP: #615548
+  * Revert "ext4: Fix possible lost inode write in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Fixed inode allocator to correctly track a flex_bg's
+    used_dirs"
+    - LP: #615548
+  * Revert "ext4: Fix estimate of # of blocks needed to write
+    indirect-mapped files"
+    - LP: #615548
+  * Revert "ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl"
+    - LP: #615548
+  * Revert "ext4: Fix the NULL reference in double_down_write_data_sem()"
+    - LP: #615548
+  * Revert "ext4: Fix insertion point of extent in
+    mext_insert_across_blocks()"
+    - LP: #615548
+  * Revert "ext4: make "offset" consistent in ext4_check_dir_entry()"
+    - LP: #615548
+  * Revert "ext4: Handle non empty on-disk orphan link"
+    - LP: #615548
+  * Revert "ext4: explicitly remove inode from orphan list after failed
+    direct io"
+    - LP: #615548
+  * Revert "ext4: fix error handling in migrate"
+    - LP: #615548
+  * Revert "ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation."
+    - LP: #615548
+  * Revert "ext4: Add flag to files with blocks intentionally past EOF"
+    - LP: #615548
+  * Revert "ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify EXT4_I(inode)->i_state"
+    - LP: #615548
+  * Revert "ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag"
+    - LP: #615548
+  * Revert "ext4: Fix quota accounting error with fallocate"
+    - LP: #615548
+  * Revert "ext4: Handle -EDQUOT error on write"
+    - LP: #615548
+  * Revert "ext4: Calculate metadata requirements more accurately"
+    - LP: #615548
+  * Revert "ext4: Fix accounting of reserved metadata blocks"
+    - LP: #615548
+  * Revert "ext4: Patch up how we claim metadata blocks for quota purposes"
+    - LP: #615548
+  * Revert "ext4: Ensure zeroout blocks have no dirty metadata"
+    - LP: #615548
+  * Revert "ext4: return correct wbc.nr_to_write in ext4_da_writepages"
+    - LP: #615548
+  * Revert "ext4: Eliminate potential double free on error path"
+    - LP: #615548
+  * Revert "ext4, jbd2: Add barriers for file systems with exernal
+    journals"
+    - LP: #615548
+  * Revert "ext4: replace BUG() with return -EIO in ext4_ext_get_blocks"
+    - LP: #615548
+  * Revert "ext4: Fix potential quota deadlock"
+    - LP: #615548
+  * Revert "ext4: don't return to userspace after freezing the fs with a
+    mutex held"
+    - LP: #615548
+  * ixgbe: Fix return of invalid txq
+    - LP: #607824
+  * oprofile/x86: fix uninitialized counter usage during cpu hotplug
+    - LP: #607824
+  * oprofile: remove double ring buffering
+    - LP: #607824
+  * cpumask: fix compat getaffinity
+    - LP: #607824
+  * NFSD: don't report compiled-out versions as present
+    - LP: #607824
+  * sata_nv: use ata_pci_sff_activate_host() instead of ata_host_activate()
+    - LP: #607824
+  * ARCNET: Limit com20020 PCI ID matches for SOHARD cards
+    - LP: #607824
+  * rtl8180: fix tx status reporting
+    - LP: #607824
+  * Staging: add Add Sitecom WL-349 to rtl8192su
+    - LP: #607824
+  * staging: vt6655: Fix kernel BUG on driver wpa initialization
+    - LP: #607824
+  * Fix racy use of anon_inode_getfd() in perf_event.c
+    - LP: #607824
+  * posix_timer: Fix error path in timer_create
+    - LP: #607824
+  * libata: disable ATAPI AN by default
+    - LP: #607824
+  * libata: don't flush dcache on slab pages
+    - LP: #607824
+  * mutex: Fix optimistic spinning vs. BKL
+    - LP: #607824
+  * ALSA: hda: Fix model quirk for Dell M1730
+    - LP: #576160, #607824
+  * ALSA: hda: Use LPIB for Toshiba A100-259
+    - LP: #549560, #607824
+  * ALSA: hda: Use LPIB for Acer Aspire 5110
+    - LP: #583983, #607824
+  * ALSA: hda: Use LPIB for Sony VPCS11V9E
+    - LP: #586347, #607824
+  * ALSA: hda: Use LPIB for a Shuttle device
+    - LP: #551949, #607824
+  * ACPI: video: fix acpi_backlight=video
+    - LP: #573120, #607824
+  * V4L/DVB: gspca - stv06xx: Remove the 046d:08da from the stv06xx driver
+    - LP: #607824
+  * HID: Add the GYR4101US USB ID to hid-gyration
+    - LP: #607824
+  * ar9170usb: add a couple more USB IDs
+    - LP: #607824
+  * ar9170usb: fix panic triggered by undersized rxstream buffer
+    - LP: #607824
+  * USB: visor: fix memory leak
+    - LP: #607824
+  * USB: CP210x New Device IDs 11 New device IDs
+    - LP: #607824
+  * USB: kobil: fix memory leak
+    - LP: #607824
+  * USB: option: add PID for ZTE product
+    - LP: #607824
+  * USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem
+    interface is 0xff
+    - LP: #607824
+  * USB: serial: option: add cinterion device id
+    - LP: #607824
+  * USB: option.c: OLIVETTI OLICARD100 support
+    - LP: #607824
+  * USB: ir-usb: fix double free
+    - LP: #607824
+  * USB: kl5usb105: fix memory leak
+    - LP: #607824
+  * USB: mxc: gadget: Fix bitfield for calculating maximum packet size
+    - LP: #607824
+  * USB: unusual-dev: Add bad sense flag for Appotech ax203 based picture
+    frames
+    - LP: #607824
+  * USB: EHCI: clear PHCD before resuming
+    - LP: #607824
+  * USB: xhci: Fix issue with set interface after stall.
+    - LP: #607824
+  * USB: xhci: Fix check for room on the ring.
+    - LP: #607824
+  * USB: xHCI: Fix wrong usage of macro TRB_TYPE
+    - LP: #607824
+  * mac80211: give warning if building w/out rate ctrl algorithm
+    - LP: #607824
+  * mac80211: Fix robust management frame handling (MFP)
+    - LP: #607824
+  * mac80211: fix rts threshold check
+    - LP: #607824
+  * drivers/base/cpu.c: fix the output from /sys/devices/system/cpu/offline
+    - LP: #607824
+  * can: Fix SJA1000 command register writes on SMP systems
+    - LP: #607824
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #607824
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #607824
+  * PCI: Disable MSI for MCP55 on P5N32-E SLI
+    - LP: #607824
+  * virtio_net: Make delayed refill more reliable
+    - LP: #607824
+  * mm: hugetlb: fix clear_huge_page()
+    - LP: #607824
+  * powerpc: Fix handling of strncmp with zero len
+    - LP: #607824
+  * powerpc/pseries: Only call start-cpu when a CPU is stopped
+    - LP: #607824
+  * powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu
+    - LP: #607824
+  * powerpc/oprofile: fix potential buffer overrun in op_model_cell.c
+    - LP: #607824
+  * writeback: disable periodic old data writeback for
+    !dirty_writeback_centisecs
+    - LP: #607824
+  * md/raid1: fix counting of write targets.
+    - LP: #607824
+  * md: Fix read balancing in RAID1 and RAID10 on drives > 2TB
+    - LP: #607824
+  * md: set mddev readonly flag on blkdev BLKROSET ioctl
+    - LP: #607824
+  * x86/amd-iommu: Fix suspend/resume with IOMMU
+    - LP: #607824
+  * exofs: confusion between kmap() and kmap_atomic() api
+    - LP: #607824
+  * mn10300: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * m68k: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * rtc-cmos: do dev_set_drvdata() earlier in the initialization
+    - LP: #607824
+  * rtc: s3c: initialize driver data before using it
+    - LP: #607824
+  * frv: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * xtensa: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * Blackfin: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * tmpfs: insert tmpfs cache pages to inactive list at first
+    - LP: #607824
+  * mlx4_core: Fix possible chunk sg list overflow in mlx4_alloc_icm()
+    - LP: #607824
+  * ARM: 6166/1: Proper prefetch abort handling on pre-ARMv6
+    - LP: #607824
+  * ARM: 6164/1: Add kto and kfrom to input operands list.
+    - LP: #607824
+  * ARM: 6146/1: sa1111: Prevent deadlock in resume path
+    - LP: #607824
+  * ARM: 6144/1: TCM memory bug freeing bug
+    - LP: #607824
+  * ARM: VFP: Fix vfp_put_double() for d16-d31
+    - LP: #607824
+  * ASoC: Fix dB scales for WM835x
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8400
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8990
+    - LP: #607824
+  * hwmon: (ltc4245) Read only one GPIO pin
+    - LP: #607824
+  * signals: check_kill_permission(): don't check creds if
+    same_thread_group()
+    - LP: #607824
+  * do_generic_file_read: clear page errors when issuing a fresh read of
+    the page
+    - LP: #607824
+  * ipmi: handle run_to_completion properly in deliver_recv_msg()
+    - LP: #607824
+  * x86, setup: Phoenix BIOS fixup is needed on Dell Inspiron Mini 1012
+    - LP: #607824
+  * xen: ensure timer tick is resumed even on CPU driving the resume
+    - LP: #607824
+  * xen: avoid allocation causing potential swap activity on the resume
+    path
+    - LP: #607824
+  * ALSA: hda: Use LPIB for an ASUS device
+    - See: #465942, #607824
+  * ALSA: hda: Use mb31 quirk for an iMac model
+    - LP: #542550, #607824
+  * ALSA: hda: Use LPIB for another mainboard
+    - See: #580749, #607824
+  * ALSA: hda: Use LPIB for ASUS M2V
+    - See: #587546, #607824
+  * Staging: comedi - correct parameter gainlkup for DAQCard-6024E in
+    driver ni_mio_cs.c
+    - LP: #607824
+  * clocksource: sh_cmt: compute mult and shift before registration
+    - LP: #607824
+  * ath5k: retain promiscuous setting
+    - LP: #607824
+  * ahci: add pci quirk for JMB362
+    - LP: #607824
+  * firewire: core: check for 1394a compliant IRM, fix inaccessibility of
+    Sony camcorder
+    - LP: #607824
+  * perf_events: Fix resource leak in x86 __hw_perf_event_init()
+    - LP: #607824
+  * sata_nv: don't diddle with nIEN on mcp55
+    - LP: #607824
+  * sata_via: magic vt6421 fix for transmission problems w/ WD drives
+    - LP: #422994, #607824
+  * USB: mos7840: fix null-pointer dereference
+    - LP: #607824
+  * USB: xhci: Wait for host to start running.
+    - LP: #607824
+  * USB: xhci: Wait for controller to be ready after reset.
+    - LP: #607824
+  * USB: ftdi_sio: fix DTR/RTS line modes
+    - LP: #607824
+  * USB: cdc-acm: fix resource reclaim in error path of acm_probe
+    - LP: #607824
+  * p54usb: Add device ID for Dell WLA3310 USB
+    - LP: #607824
+  * atl1e: Allow TX checksum offload and TSO to be disabled and reenabled
+    - LP: #607824
+  * via-velocity: Give RX descriptors to the NIC later on open or MTU
+    change
+    - LP: #607824
+  * dmfe/tulip: Let dmfe handle DM910x except for SPARC on-board chips
+    - LP: #607824
+  * Documentation/3c509: document ethtool support
+    - LP: #607824
+  * wireless: report reasonable bitrate for MCS rates through wext
+    - LP: #607824
+  * ath9k: add support for 802.11n bonded out AR2427
+    - LP: #607824
+  * wrong type for 'magic' argument in simple_fill_super()
+    - LP: #607824
+  * iwlwifi: check for aggregation frame and queue
+    - LP: #607824
+  * iwlwifi: recalculate average tpt if not current
+    - LP: #607824
+  * iwlwifi: update supported PCI_ID list for 5xx0 series
+    - LP: #607824
+  * wl1251: fix a memory leak in probe
+    - LP: #607824
+  * vfs: add NOFOLLOW flag to umount(2)
+    - LP: #607824
+  * l2tp: Fix oops in pppol2tp_xmit
+    - LP: #607824
+  * ucc_geth: Fix empty TX queue processing
+    - LP: #607824
+  * ucc_geth: Fix netdev watchdog triggering on link changes
+    - LP: #607824
+  * ucc_geth: Fix full TX queue processing
+    - LP: #607824
+  * Input: psmouse - reset all types of mice before reconnecting
+    - LP: #607824
+  * KVM: s390: Fix possible memory leak of in kvm_arch_vcpu_create()
+    - LP: #607824
+  * KVM: PPC: Do not create debugfs if fail to create vcpu
+    - LP: #607824
+  * x86, paravirt: Add a global synchronization point for pvclock
+    - LP: #607824
+  * KVM: Don't allow lmsw to clear cr0.pe
+    - LP: #607824
+  * KVM: x86: Check LMA bit before set_efer
+    - LP: #607824
+  * KVM: MMU: Segregate shadow pages with different cr0.wp
+    - LP: #607824
+  * KVM: VMX: enable VMXON check with SMX enabled (Intel TXT)
+    - LP: #607824
+  * KVM: MMU: Don't read pdptrs with mmu spinlock held in mmu_alloc_roots
+    - LP: #607824
+  * KVM: Fix wallclock version writing race
+    - LP: #607824
+  * KVM: x86: Add missing locking to arch specific vcpu ioctls
+    - LP: #607824
+  * KVM: x86: Inject #GP with the right rip on efer writes
+    - LP: #607824
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #607824
+  * parisc: clear floating point exception flag on SIGFPE signal
+    - LP: #607824
+  * dm snapshot: simplify sector_to_chunk expression
+    - LP: #607824
+  * KEYS: Return more accurate error codes
+    - LP: #607824
+  * qla2xxx: Disable MSI on qla24xx chips other than QLA2432.
+    - LP: #607824
+  * Linux 2.6.32.16
+    - LP: #607824
+  * drm/i915: Fix 82854 PCI ID, and treat it like other 85X
+    - LP: #607824
+  * drm/i915: Reject bind_to_gtt() early if object > aperture
+    - LP: #607824
+  * drm/edid: Fix 1024x768@85Hz
+    - LP: #607824
+  * drm/radeon/kms: reset ddc_bus in object header parsing
+    - LP: #607824
+  * drm/radeon/kms/atom: fix typo in LVDS panel info parsing
+    - LP: #607824
+  * drm/radeon: r100/r200 ums: block ability for userspace app to trash 0
+    page and beyond
+    - LP: #607824
+  * drm/radeon: fix the r100/r200 ums block 0 page fix
+    - LP: #607824
+  * drm/i915: Rebind bo if currently bound with incorrect alignment.
+    - LP: #607824
+  * Linux 2.6.32.16+drm33.6
+    - LP: #607824
+  * virtio-pci: disable msi at startup
+    - LP: #615548
+  * hwmon: (k8temp) Bypass core swapping on single-core processors
+    - LP: #615548
+  * hwmon: (k8temp) Fix temperature reporting for ASB1 processor revisions
+    - LP: #615548
+  * hwmon: (coretemp) Properly label the sensors
+    - LP: #615548
+  * hwmon: (coretemp) Skip duplicate CPU entries
+    - LP: #615548
+  * hwmon: (it87) Fix in7 on IT8720F
+    - LP: #615548
+  * cifs: remove bogus first_time check in NTLMv2 session setup code
+    - LP: #615548
+  * cifs: don't attempt busy-file rename unless it's in same directory
+    - LP: #615548
+  * CIFS: Fix a malicious redirect problem in the DNS lookup code
+    - LP: #615548
+  * ALSA: hda - Add Macbook 5,2 quirk
+    - LP: #463178, #615548
+  * cpmac: do not leak struct net_device on phy_connect errors
+    - LP: #615548
+  * sky2: enable rx/tx in sky2_phy_reinit()
+    - LP: #615548
+  * sparc: Fix use of uid16_t and gid16_t in asm/stat.h
+    - LP: #615548
+  * math-emu: correct test for downshifting fraction in _FP_FROM_INT()
+    - LP: #615548
+  * NFSv4: Fix an embarassing typo in encode_attrs()
+    - LP: #615548
+  * NFSv4: Ensure that /proc/self/mountinfo displays the minor version
+    number
+    - LP: #615548
+  * SUNRPC: Fix a re-entrancy bug in xs_tcp_read_calldir()
+    - LP: #615548
+  * ath5k: drop warning on jumbo frames
+    - LP: #615548
+  * ath9k: re-enable ps by default for new single chip families
+    - LP: #615548
+  * ath9k: Avoid corrupt frames being forwarded to mac80211.
+    - LP: #615548
+  * hostap: Protect against initialization interrupt
+    - LP: #615548
+  * TPM: ReadPubEK output struct fix
+    - LP: #615548
+  * fb: fix colliding defines for fb flags.
+    - LP: #615548
+  * iwlwifi: cancel scan watchdog in iwl_bg_abort_scan
+    - LP: #615548
+  * mac80211: do not wip out old supported rates
+    - LP: #615548
+  * mac80211: Handle mesh action frames in ieee80211_rx_h_action
+    - LP: #615548
+  * Btrfs: fix checks in BTRFS_IOC_CLONE_RANGE
+    - LP: #615548
+  * p54pci: add Symbol AP-300 minipci adapters pciid
+    - LP: #615548
+  * dynamic debug: move ddebug_remove_module() down into free_module()
+    - LP: #615548
+  * tpm_tis: fix subsequent suspend failures
+    - LP: #615548
+  * ipvs: Add missing locking during connection table hashing and unhashing
+    - LP: #615548
+  * netfilter: ip6t_REJECT: fix a dst leak in ipv6 REJECT
+    - LP: #615548
+  * SCSI: aacraid: Eliminate use after free
+    - LP: #615548
+  * amd64-agp: Probe unknown AGP devices the right way
+    - LP: #615548
+  * perf: Resurrect flat callchains
+    - LP: #615548
+  * x86: Fix vsyscall on gcc 4.5 with -Os
+    - LP: #615548
+  * x86, Calgary: Increase max PHB number
+    - LP: #615548
+  * x86, Calgary: Limit the max PHB number to 256
+    - LP: #615548
+  * sched: Prevent compiler from optimising the sched_avg_update() loop
+    - LP: #615548
+  * sched: Fix over-scheduling bug
+    - LP: #615548
+  * genirq: Deal with desc->set_type() changing desc->chip
+    - LP: #615548
+  * serial: cpm_uart: implement the cpm_uart_early_write() function for
+    console poll
+    - LP: #615548
+  * cmd640: fix kernel oops in test_irq() method
+    - LP: #615548
+  * ide: Fix IDE taskfile with cfq scheduler
+    - LP: #615548
+  * net/core: neighbour update Oops
+    - LP: #615548
+  * tcp: fix crash in tcp_xmit_retransmit_queue
+    - LP: #615548
+  * rtc: fix ds1388 time corruption
+    - LP: #615548
+  * ethtool: Fix potential kernel buffer overflow in ETHTOOL_GRXCLSRLALL
+    - LP: #615548
+  * sdhci-s3c: add missing remove function
+    - LP: #615548
+  * ASoC: Remove duplicate AUX definition from WM8776
+    - LP: #615548
+  * x86: Fix x2apic preenabled system with kexec
+    - LP: #615548
+  * IPoIB: Fix world-writable child interface control sysfs attributes
+    - LP: #615548
+  * Input: i8042 - add Gigabyte Spring Peak to dmi_noloop_table
+    - LP: #580664, #615548
+  * Input: twl40300-keypad - fix handling of "all ground" rows
+    - LP: #615548
+  * ARM: 6201/1: RealView: Do not use outer_sync() on ARM11MPCore boards
+    with L220
+    - LP: #615548
+  * ARM: 6226/1: fix kprobe bug in ldr instruction emulation
+    - LP: #615548
+  * x86: Do not try to disable hpet if it hasn't been initialized before
+    - LP: #615548
+  * staging: rtl8192su: add USB VID/PID for HWNUm-300
+    - LP: #615548
+  * Staging: rtl8192su: add USB ID for 0bda:8171
+    - LP: #615548
+  * USB: obey the sysfs power/wakeup setting
+    - LP: #615548
+  * USB: g_serial: don't set low_latency flag
+    - LP: #615548
+  * USB: g_serial: fix tty cleanup on unload
+    - LP: #615548
+  * USB: option: add support for 1da5:4518
+    - LP: #615548
+  * USB: Add PID for Sierra 250U to drivers/usb/serial/sierra.c
+    - LP: #599569, #615548
+  * USB: ftdi_sio: support for Signalyzer tools based on FTDI chips
+    - LP: #615548
+  * USB: option: Add support for AMOI Skypephone S2
+    - LP: #615548
+  * USB: adds Artisman USB dongle to list of quirky devices
+    - LP: #615548
+  * USB: sisusbvga: Fix for USB 3.0
+    - LP: #615548
+  * USB: add quirk for Broadcom BT dongle
+    - LP: #615548
+  * USB: FTDI: Add support for the RT System VX-7 radio programming cable
+    - LP: #615548
+  * ethtool: Fix potential user buffer overflow for ETHTOOL_{G, S}RXFH
+    - LP: #615548
+  * ext4: Fix potential quota deadlock
+    - LP: #615548
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #615548
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #615548
+  * ext4: Eliminate potential double free on error path
+    - LP: #615548
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #615548
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #615548
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #615548
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #615548
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #615548
+  * ext4: Handle -EDQUOT error on write
+    - LP: #615548
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #615548
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #615548
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #615548
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #615548
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #615548
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #615548
+  * ext4: fix error handling in migrate
+    - LP: #615548
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #615548
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #615548
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #615548
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #615548
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #615548
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #615548
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #615548
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #615548
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #615548
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #615548
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #615548
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #615548
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #615548
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #615548
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #615548
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #615548
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #615548
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #615548
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #615548
+  * ext4: stop issuing discards if not supported by device
+    - LP: #615548
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #615548
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #615548
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #615548
+  * ext4: init statistics after journal recovery
+    - LP: #615548
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #615548
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #615548
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #615548
+  * ext4: Show journal_checksum option
+    - LP: #615548
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #615548
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #615548
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #615548
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #615548
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #615548
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #615548
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #615548
+  * KVM: MMU: Remove user access when allowing kernel access to gpte.w=0
+    page
+    - LP: #615548
+  * KVM: SVM: Handle MCEs early in the vmexit process
+    - LP: #615548
+  * KVM: SVM: Implement workaround for Erratum 383
+    - LP: #615548
+  * KVM: MMU: invalidate and flush on spte small->large page size change
+    - LP: #615548
+  * futex: futex_find_get_task remove credentails check
+    - LP: #615548
+  * GFS2: Fix up system xattrs
+    - LP: #615548
+  * PM / x86: Save/restore MISC_ENABLE register
+    - LP: #615548
+  * ACPI: skip checking BM_STS if the BIOS doesn't ask for it
+    - LP: #615548
+  * ACPI: Unconditionally set SCI_EN on resume
+    - LP: #615548
+  * libertas/sdio: 8686: set ECSI bit for 1-bit transfers
+    - LP: #615548
+  * dm9000: fix "BUG: spinlock recursion"
+    - LP: #615548
+  * firmware_class: fix memory leak - free allocated pages
+    - LP: #615548
+  * revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second
+    call site)"
+    - LP: #615548
+  * ALSA: Echoaudio, fix Guru Meditation #00000005.48454C50
+    - LP: #615548
+  * V4L/DVB: dvb-core: Fix ULE decapsulation bug
+    - LP: #615548
+  * V4L/DVB: FusionHDTV: Use quick reads for I2C IR device probing
+    - LP: #615548
+  * forcedeth: fix tx limit2 flag check
+    - LP: #615548
+  * staging: rtl8192su: add Support for Belkin F5D8053 v6
+    - LP: #615548
+  * MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1
+    - LP: #615548
+  * V4L/DVB: budget: Select correct frontends
+    - LP: #615548
+  * cxgb3: fix linkup issue
+    - LP: #615548
+  * mac80211: fix supported rates IE if AP doesn't give us it's rates
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for unbranded Arkmicro 18ec:3290 webcams
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for Packard Bell EasyNote MX52
+    integrated webcam
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for V4L2_PIX_FMT_Y16
+    - LP: #615548
+  * iwlagn: verify flow id in compressed BA packet
+    - LP: #615548
+  * kbuild: Fix modpost segfault
+    - LP: #615548
+  * eeepc-laptop: check wireless hotplug events
+    - LP: #615548
+  * Fix spinaphore down_spin()
+    - LP: #615548
+  * ath5k: initialize ah->ah_current_channel
+    - LP: #615548
+  * Input: RX51 keymap - fix recent compile breakage
+    - LP: #615548
+  * V4L/DVB (13830): uvcvideo: add another YUYV format GUID for iSight
+    cameras
+    - LP: #615548
+  * Linux 2.6.32.17
+    - LP: #615548
+  * drm/i915: fix hibernation since i915 self-reclaim fixes
+    - LP: #615548
+  * drm/i915: add 'reclaimable' to i915 self-reclaimable page allocations
+    - LP: #615548
+  * i915: fix lock imbalance on error path...
+    - LP: #615548
+  * drm/i915: Define MI_ARB_STATE bits
+    - LP: #615548
+  * drm/i915: enable low power render writes on GEN3 hardware.
+    - LP: #615548
+  * drm/i915: Make G4X-style PLL search more permissive
+    - LP: #615548
+  * drm/radeon/r200: handle more hw tex coord types
+    - LP: #615548
+  * drm/radeon/r100/r200: fix calculation of compressed cube maps
+    - LP: #615548
+  * drm/radeon/kms: CS checker texture fixes for r1xx/r2xx/r3xx
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc handling
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc harder
+    - LP: #615548
+  * drm/radeon/kms: add quirk for ASUS HD 3600 board
+    - LP: #615548
+  * drm/radeon/kms: fix possible mis-detection of sideport on rs690/rs740
+    - LP: #615548
+  * drm/radeon/kms: fix legacy LVDS dpms sequence
+    - LP: #615548
+  * drm/radeon/kms: fix legacy tv-out pal mode
+    - LP: #615548
+  * Linux 2.6.32.17+drm33.7
+    - LP: #615548
+  * (pre-stable) writeback: remove the always false
+    bdi_cap_writeback_dirty() test
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove unused nonblocking and congestion checks
+    - LP: #543617, #585092
+  * (pre-stable) vfs: improve writeback_inodes_wb()
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing kernel-doc notation
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback completion notifications
+    - LP: #543617, #585092
+  * (pre-stable) writeback: queue work on stack in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: enforce s_umount locking in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback_inodes_wb from
+    writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify wakeup_flusher_threads
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify and split bdi_start_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing requeue_io in writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix pin_sb_for_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove writeback_inodes_wbc
+    - LP: #543617, #585092
+  * (pre-stable) writeback: split writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify the write back thread queue
+    - LP: #543617, #585092
+  * (pre-stable) Fix compiling NFS when backporting writeback
+    - LP: #543617, #585092
+  * sched: cgroup: Implement different treatment for idle shares
+    - LP: #620755
+  * mm: fix ia64 crash when gcore reads gate area
+    - LP: #620755
+  * acl trouble after upgrading ubuntu
+    - LP: #620755
+  * comedi: Uncripple 8255-based DIO subdevices
+    - LP: #620755
+  * NFS: kswapd must not block in nfs_release_page
+    - LP: #620755
+  * PARISC: led.c - fix potential stack overflow in led_proc_write()
+    - LP: #620755
+  * arm/imx/gpio: add spinlock protection
+    - LP: #620755
+  * parisc: pass through '\t' to early (iodc) console
+    - LP: #620755
+  * amd64_edac: Fix DCT base address selector
+    - LP: #620755
+  * amd64_edac: Correct scrub rate setting
+    - LP: #620755
+  * e1000e: don't inadvertently re-set INTX_DISABLE
+    - LP: #620755
+  * e1000e: 82577/82578 PHY register access issues
+    - LP: #620755
+  * 9p: strlen() doesn't count the terminator
+    - LP: #620755
+  * ath9k: enable serialize_regmode for non-PCIE AR9160
+    - LP: #620755
+  * ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation
+    - LP: #620755
+  * ath9k: fix TSF after reset on AR913x
+    - LP: #620755
+  * ath9k: fix yet another buffer leak in the tx aggregation code
+    - LP: #620755
+  * iwlwifi: fix scan abort
+    - LP: #620755
+  * cfg80211: ignore spurious deauth
+    - LP: #620755
+  * cfg80211: don't get expired BSSes
+    - LP: #620755
+  * xfs: prevent swapext from operating on write-only files
+    - LP: #620755
+  * SCSI: enclosure: fix error path - actually return ERR_PTR() on error
+    - LP: #620755
+  * GFS2: rename causes kernel Oops
+    - LP: #620755
+  * slow-work: use get_ref wrapper instead of directly calling get_ref
+    - LP: #620755
+  * CIFS: Remove __exit mark from cifs_exit_dns_resolver()
+    - LP: #620755
+  * CIFS: Fix compile error with __init in cifs_init_dns_resolver()
+    definition
+    - LP: #620755
+  * xen: drop xen_sched_clock in favour of using plain wallclock time
+    - LP: #620755
+  * ssb: do not read SPROM if it does not exist
+    - LP: #620755
+  * ssb: Look for SPROM at different offset on higher rev CC
+    - LP: #620755
+  * ssb: fix NULL ptr deref when pcihost_wrapper is used
+    - LP: #620755
+  * ssb: Handle alternate SSPROM location
+    - LP: #620755
+  * Linux 2.6.32.18
+    - LP: #620755
+  * ata_piix: fix locking around SIDPR access
+    - LP: #622877
+  * powerpc: fix build with make 3.82
+    - LP: #622877
+  * nvram: Fix write beyond end condition; prove to gcc copy is safe
+    - LP: #622877
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #622877
+  * x86, vmware: Preset lpj values when on VMware.
+    - LP: #622877
+  * Staging: line6: needs to select SND_PCM
+    - LP: #622877
+  * Staging: panel: Prevent double-calling of parport_release - fix oops.
+    - LP: #622877
+  * PCI: Do not run NVidia quirks related to MSI with MSI disabled
+    - LP: #622877
+  * PCI: disable MSI on VIA K8M800
+    - LP: #622877
+  * solos-pci: Fix race condition in tasklet RX handling
+    - LP: #622877
+  * splice: fix misuse of SPLICE_F_NONBLOCK
+    - LP: #622877
+  * drivers/video/w100fb.c: ignore void return value / fix build failure
+    - LP: #622877
+  * ide-cd: Do not access completed requests in the irq handler
+    - LP: #622877
+  * md/raid10: fix deadlock with unaligned read during resync
+    - LP: #622877
+  * blkdev: cgroup whitelist permission fix
+    - LP: #622877
+  * eCryptfs: Handle ioctl calls with unlocked and compat functions
+    - LP: #622877
+  * ecryptfs: release reference to lower mount if interpose fails
+    - LP: #622877
+  * fs/ecryptfs/file.c: introduce missing free
+    - LP: #622877
+  * bio, fs: update RWA_MASK, READA and SWRITE to match the corresponding
+    BIO_RW_* bits
+    - LP: #622877
+  * signalfd: fill in ssi_int for posix timers and message queues
+    - LP: #622877
+  * smsc911x: Add spinlocks around registers access
+    - LP: #622877
+  * ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast
+    a faulty ASID
+    - LP: #622877
+  * ARM: 6280/1: imx: Fix build failure when including <mach/gpio.h>
+    without <linux/spinlock.h>
+    - LP: #622877
+  * USB: resizing usbmon binary interface buffer causes protection faults
+    - LP: #622877
+  * USB delay init quirk for logitech Harmony 700-series devices
+    - LP: #622877
+  * USB: serial: enabling support for Segway RMP in ftdi_sio
+    - LP: #622877
+  * USB: option: Huawei ETS 1220 support added
+    - LP: #622877
+  * USB: option: add huawei k3765 k4505 devices to work properly
+    - LP: #622877
+  * USB: ftdi_sio: device id for Navitator
+    - LP: #622877
+  * USB: cp210x: Add four new device IDs
+    - LP: #622877
+  * USB: usbtest: avoid to free coherent buffer in atomic context
+    - LP: #622877
+  * USB: fix thread-unsafe anchor utiliy routines
+    - LP: #622877
+  * drm/edid: Fix the HDTV hack sync adjustment
+    - LP: #622877
+  * Bluetooth: Added support for controller shipped with iMac i5
+    - LP: #622877
+  * jfs: don't allow os2 xattr namespace overlap with others
+    - LP: #622877
+  * arp_notify: allow drivers to explicitly request a notification event.
+    - LP: #622877
+  * xen: netfront: explicitly generate arp_notify event after migration.
+    - LP: #622877
+  * net: Fix NETDEV_NOTIFY_PEERS to not conflict with
+    NETDEV_BONDING_DESLAVE.
+    - LP: #622877
+  * irq: Add new IRQ flag IRQF_NO_SUSPEND
+    - LP: #622877
+  * xen: Do not suspend IPI IRQs.
+    - LP: #622877
+  * drm/i915: Use RSEN instead of HTPLG for tfp410 monitor detection.
+    - LP: #622877
+  * Btrfs: Avoid superfluous tree-log writeout
+    - LP: #622877
+  * Btrfs: Add btrfs_duplicate_item
+    - LP: #622877
+  * Btrfs: Rewrite btrfs_drop_extents
+    - LP: #622877
+  * Btrfs: Fix disk_i_size update corner case
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup while replaying log
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup during committing transaction
+    - LP: #622877
+  * Btrfs: Make fallocate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Make truncate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Pass transaction handle to security and ACL initialization
+    functions
+    - LP: #622877
+  * Btrfs: Add delayed iput
+    - LP: #622877
+  * Btrfs: Fix btrfs_drop_extent_cache for skip pinned case
+    - LP: #622877
+  * Btrfs: Fix per root used space accounting
+    - LP: #622877
+  * Btrfs: don't add extent 0 to the free space cache v2
+    - LP: #622877
+  * Btrfs: fail mount on bad mount options
+    - LP: #622877
+  * Btrfs: deny sys_link across subvolumes.
+    - LP: #622877
+  * Btrfs: Show discard option in /proc/mounts
+    - LP: #622877
+  * Btrfs: make metadata chunks smaller
+    - LP: #622877
+  * Btrfs: make sure fallocate properly starts a transaction
+    - LP: #622877
+  * btrfs: fix missing last-entry in readdir(3)
+    - LP: #622877
+  * Btrfs: align offsets for btrfs_ordered_update_i_size
+    - LP: #622877
+  * Btrfs, fix memory leaks in error paths
+    - LP: #622877
+  * Btrfs: Fix race in btrfs_mark_extent_written
+    - LP: #622877
+  * Btrfs: fix regression in orphan cleanup
+    - LP: #622877
+  * Btrfs: deal with NULL acl sent to btrfs_set_acl
+    - LP: #622877
+  * Btrfs: fix possible panic on unmount
+    - LP: #622877
+  * Btrfs: Use correct values when updating inode i_size on fallocate
+    - LP: #622877
+  * Btrfs: fix a memory leak in btrfs_init_acl
+    - LP: #622877
+  * Btrfs: run orphan cleanup on default fs root
+    - LP: #622877
+  * Btrfs: do not mark the chunk as readonly if in degraded mode
+    - LP: #622877
+  * Btrfs: check return value of open_bdev_exclusive properly
+    - LP: #622877
+  * Btrfs: check total number of devices when removing missing
+    - LP: #622877
+  * Btrfs: fix race between allocate and release extent buffer.
+    - LP: #622877
+  * Btrfs: make error return negative in btrfs_sync_file()
+    - LP: #622877
+  * Btrfs: remove BUG_ON() due to mounting bad filesystem
+    - LP: #622877
+  * Btrfs: Fix oopsen when dropping empty tree.
+    - LP: #622877
+  * Btrfs: do not try and lookup the file extent when finishing ordered io
+    - LP: #622877
+  * Btrfs: apply updated fallocate i_size fix
+    - LP: #622877
+  * Btrfs: btrfs_mark_extent_written uses the wrong slot
+    - LP: #622877
+  * Btrfs: kfree correct pointer during mount option parsing
+    - LP: #622877
+  * nohz: Introduce arch_needs_cpu
+    - LP: #622877
+  * nohz: Reuse ktime in sub-functions of tick_check_idle.
+    - LP: #622877
+  * timekeeping: Fix clock_gettime vsyscall time warp
+    - LP: #622877
+  * sched: Fix granularity of task_u/stime()
+    - LP: #622877
+  * sched, cputime: Introduce thread_group_times()
+    - LP: #622877
+  * mutex: Don't spin when the owner CPU is offline or other weird cases
+    - LP: #622877
+  * fix SBA IOMMU to handle allocation failure properly
+    - LP: #622877
+  * crypto: testmgr - Fix complain about lack test for internal used
+    algorithm
+    - LP: #622877
+  * memory hotplug: fix a bug on /dev/mem for 64-bit kernels
+    - LP: #622877
+  * x86: Fix out of order of gsi
+    - LP: #622877
+  * HWPOISON: remove the anonymous entry
+    - LP: #622877
+  * HWPOISON: abort on failed unmap
+    - LP: #622877
+  * powerpc/eeh: Fix a bug when pci structure is null
+    - LP: #622877
+  * ACPI: Fix regression where _PPC is not read at boot even when
+    ignore_ppc=0
+    - LP: #622877
+  * ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files
+    - LP: #622877
+  * ext4: Fix optional-arg mount options
+    - LP: #622877
+  * reiserfs: properly honor read-only devices
+    - LP: #622877
+  * reiserfs: fix oops while creating privroot with selinux enabled
+    - LP: #622877
+  * dlm: always use GFP_NOFS
+    - LP: #622877
+  * dlm: fix ordering of bast and cast
+    - LP: #622877
+  * dlm: send reply before bast
+    - LP: #622877
+  * ocfs2: Find proper end cpos for a leaf refcount block.
+    - LP: #622877
+  * ocfs2: Set MS_POSIXACL on remount
+    - LP: #622877
+  * Skip check for mandatory locks when unlocking
+    - LP: #622877
+  * loop: Update mtime when writing using aops
+    - LP: #622877
+  * aic79xx: check for non-NULL scb in ahd_handle_nonpkt_busfree
+    - LP: #622877
+  * ibmvfc: Fix command completion handling
+    - LP: #622877
+  * ibmvfc: Reduce error recovery timeout
+    - LP: #622877
+  * md/raid1: delay reads that could overtake behind-writes.
+    - LP: #622877
+  * mm: fix corruption of hibernation caused by reusing swap during image
+    saving
+    - LP: #622877
+  * Linux 2.6.32.19
+    - LP: #622877
+  * Linux 2.6.32.20
+    - LP: #622882
+  * memstick: fix hangs on unexpected device removal in mspro_blk
+    - LP: #625392
+  * ASoC: Fix inverted mute controls for WM8580
+    - LP: #625392
+  * ASoC: Remove DSP mode support for WM8776
+    - LP: #625392
+  * ALSA: riptide - Fix detection / load of firmware files
+    - LP: #625392
+  * ALSA: emu10k1 - delay the PCM interrupts (add pcm_irq_delay parameter)
+    - LP: #625392
+  * ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA
+    codec
+    - LP: #625392
+  * ocfs2: do not overwrite error codes in ocfs2_init_acl
+    - LP: #625392
+  * ocfs2/dlm: fix a dead lock
+    - LP: #625392
+  * ocfs2 fix o2dlm dlm run purgelist (rev 3)
+    - LP: #625392
+  * ocfs2: Count more refcount records in file system fragmentation.
+    - LP: #625392
+  * ocfs2/dlm: avoid incorrect bit set in refmap on recovery master
+    - LP: #625392
+  * ocfs2/dlm: remove potential deadlock -V3
+    - LP: #625392
+  * x86, hotplug: Serialize CPU hotplug to avoid bringup concurrency issues
+    - LP: #625392
+  * x86, apic: Fix apic=debug boot crash
+    - LP: #625392
+  * Fix the nested PR lock calling issue in ACL
+    - LP: #625392
+  * hwmon: (pc87360) Fix device resource declaration
+    - LP: #625392
+  * ARM: Tighten check for allowable CPSR values
+    - LP: #625392
+  * nfs: Add "lookupcache" to displayed mount options
+    - LP: #625392
+  * ath5k: disable ASPM L0s for all cards
+    - LP: #625392
+  * pxa3xx: fix ns2cycle equation
+    - LP: #625392
+  * dm mpath: fix NULL pointer dereference when path parameters missing
+    - LP: #625392
+  * dm ioctl: release _hash_lock between devices in remove_all
+    - LP: #625392
+  * mm: make the vma list be doubly linked
+    - LP: #625392
+  * mm: make the mlock() stack guard page checks stricter
+    - LP: #625392
+  * mm: make stack guard page logic use vm_prev pointer
+    - LP: #625392
+  * slab: fix object alignment
+    - LP: #625392
+  * sunxvr500: Ignore secondary output PCI devices.
+    - LP: #625392
+  * sparc64: Add missing ID to parport probing code.
+    - LP: #625392
+  * sparc64: Fix rwsem constant bug leading to hangs.
+    - LP: #625392
+  * sparc64: Fix atomic64_t routine return values.
+    - LP: #625392
+  * net: Fix a memmove bug in dev_gro_receive()
+    - LP: #625392
+  * isdn: fix information leak
+    - LP: #625392
+  * act_nat: the checksum of ICMP doesn't have pseudo header
+    - LP: #625392
+  * vmscan: raise the bar to PAGEOUT_IO_SYNC stalls
+    - LP: #625392
+  * pcmcia: avoid buffer overflow in pcmcia_setup_isa_irq
+    - LP: #625392
+  * ext4: consolidate in_range() definitions
+    - LP: #625392
+  * Oprofile: Change CPUIDS from decimal to hex, and add some comments
+    - LP: #625392
+  * oprofile: add support for Intel processor model 30
+    - LP: #625392
+  * fixes for using make 3.82
+    - LP: #625392
+  * ALSA: intel8x0: Mute External Amplifier by default for ThinkPad X31
+    - LP: #619439, #625392
+  * netlink: fix compat recvmsg
+    - LP: #625392
+  * powerpc: Fix typo in uImage target
+    - LP: #625392
+  * USB: option: add Celot CT-650
+    - LP: #625392
+  * USB: add device IDs for igotu to navman
+    - LP: #625392
+  * USB: pl2303: New vendor and product id
+    - LP: #625392
+  * USB: CP210x Fix Break On/Off
+    - LP: #625392
+  * USB: ftdi_sio: fix endianess of max packet size
+    - LP: #625392
+  * USB: io_ti: check firmware version before updating
+    - LP: #625392
+  * USB: xhci: Remove buggy assignment in next_trb()
+    - LP: #625392
+  * USB: ftdi_sio: Add ID for Ionics PlugComputer
+    - LP: #625392
+  * USB: ftdi_sio: add product ID for Lenz LI-USB
+    - LP: #625392
+  * x86, apic: ack all pending irqs when crashed/on kexec
+    - LP: #625392
+  * Linux 2.6.32.21
+    - LP: #625392
+
+  [ Ubuntu: 2.6.32-24.43 ]
+
+  * x86-64, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * x86-64, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * compat: Make compat_alloc_user_space() incorporate the access_ok()
+    - CVE-2010-3081
+
+  [ Ubuntu: 2.6.32-24.42 ]
+
+  * (pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #561802, #578673
+  * (pre-stable) drm/i915: make sure eDP panel is turned on
+    - LP: #578673
+  * (pre-stable) drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #578673
+
+ -- Brad Figg <brad.figg@canonical.com>  Fri, 01 Oct 2010 10:39:03 -0700
+
+linux-ec2 (2.6.32-308.16) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.43
+
+  [ Ubuntu: 2.6.32-24.43 ]
+
+  * x86-64, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * x86-64, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * compat: Make compat_alloc_user_space() incorporate the access_ok()
+    - CVE-2010-3081
+
+  [ Ubuntu: 2.6.32-24.42 ]
+
+  * (pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #561802, #578673
+  * (pre-stable) drm/i915: make sure eDP panel is turned on
+    - LP: #578673
+  * (pre-stable) drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #578673
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 16 Sep 2010 10:39:18 +0200
+
+linux-ec2 (2.6.32-308.15) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.41
+
+  [ Ubuntu: 2.6.32-24.41 ]
+
+  * (pre-stable) ext4: fix freeze deadlock under IO
+    - LP: #595489
+  * drm: Initialize ioctl struct when no user data is present
+    - CVE-2010-2803
+  * can: add limit for nframes and clean up signed/unsigned variables
+    - CVE-2010-2959
+  * mm: keep a guard page below a grow-down stack segment
+    - CVE-2010-2240
+  * mm: fix missing page table unmap for stack guard page failure case
+    - CVE-2010-2240
+  * mm: fix page table unmap for stack guard page properly
+    - CVE-2010-2240
+  * mm: fix up some user-visible effects of the stack guard page
+    - CVE-2010-2240
+  * x86: don't send SIGBUS for kernel page faults
+    - CVE-2010-2240
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 18 Aug 2010 14:33:06 +0200
+
+linux-ec2 (2.6.32-308.14) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.39
+
+  [ Ubuntu: 2.6.32-24.39 ]
+
+  * sctp: Fix skb_over_panic resulting from multiple invalid parameter
+    errors (CVE-2010-1173) (v4)
+    - CVE-2010-1173
+  * sctp: fix append error cause to ERROR chunk correctly
+    - CVE-2010-1173
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - CVE-2010-1436
+  * KEYS: find_keyring_by_name() can gain access to a freed keyring
+    - CVE-2010-1437
+  * GFS2: Fix permissions checking for setflags ioctl()
+    - CVE-2010-1641
+  * Btrfs: should add a permission check for setfacl
+    - CVE-2010-2071
+  * ecryptfs: Bugfix for error related to ecryptfs_hash_buckets
+    - CVE-2010-2492
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 21 Jul 2010 10:58:47 +0200
+
+linux-ec2 (2.6.32-308.13) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.38
+
+  [ Ubuntu: 2.6.32-24.38 ]
+
+  * SAUCE: dell-laptop: fire SMI when toggling hardware killswitch
+    (revised)
+    - LP: #590607
+  * sfc: Wait at most 10ms for the MC to finish reading out MAC statistics
+    - LP: #590783
+  * sfc: Always close net device at the end of a disabling reset
+    - LP: #590783
+  * sfc: Change falcon_probe_board() to fail for unsupported boards
+    - LP: #590783
+  * ext4: Fix potential quota deadlock
+    - LP: #588069
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #588069
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #588069
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #588069
+  * ext4: Eliminate potential double free on error path
+    - LP: #588069
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #588069
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #588069
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #588069
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #588069
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #588069
+  * ext4: Handle -EDQUOT error on write
+    - LP: #588069
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #588069
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #588069
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #588069
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #588069
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #588069
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #588069
+  * ext4: fix error handling in migrate
+    - LP: #588069
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #588069
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #588069
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #588069
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #588069
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #588069
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #588069
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #588069
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #588069
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #588069
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #588069
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #588069
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #588069
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #588069
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #588069
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #588069
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #588069
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #588069
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #588069
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #588069
+  * ext4: stop issuing discards if not supported by device
+    - LP: #588069
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #588069
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #588069
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #588069
+  * ext4: init statistics after journal recovery
+    - LP: #588069
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #588069
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #588069
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #588069
+  * ext4: Show journal_checksum option
+    - LP: #588069
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #588069
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #588069
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #588069
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #588069
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #588069
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #588069
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #588069
+  * (pre-stable) ahci,ata_generic: let ata_generic handle new MBP w/ MCP89
+    - LP: #576601
+  * (pre-stable) ata_generic: implement ATA_GEN_* flags and force enable
+    DMA on MBP 7,1
+    - LP: #576601
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 08 Jul 2010 10:53:59 +0200
+
+linux-ec2 (2.6.32-307.12) lucid-proposed; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-23.37
+  * update to ubuntu-debian:7e708d33054c373faf41da23b73e8b48c342d958
+    - LP: #570500, #576274
+  * xen: follow changes to smp headers adding wbinvd
+    - LP: #575853
+
+  [ Ubuntu: 2.6.32-23.37 ]
+
+  * SAUCE: drm/radeon/kms/atom: fix dual-link DVI on DCE3.2/4.0
+    - LP: #564559
+  * [Config] ports -- build in dm-mod to enable LVM boot
+    - LP: #560717
+  * tools -- fix perf version extraction for multi-part flavours
+    - LP: #555130
+  * [Config] enforce -- ensure dm_mod is built-in for LVM
+    - LP: #560717
+  * update to ubuntu-debian:7e708d33054c373faf41da23b73e8b48c342d958
+    - LP: #570500, #576274
+  * Revert "(pre-stable): input: ALPS - Add signature for HP Pavilion dm3
+    laptops"
+    - LP: #550625
+  * Enable ftrace function profiler
+    - LP: #570389
+  * enforce CONFIG_TMPFS_POSIX_ACL=y
+    - LP: #575940
+  * Revert "staging/comdi -- disable"
+    - LP: #563436
+  * [Config] Enable multicast routing for sparc
+    - LP: #416266
+  * [Config] Add ahci.ko to virtual sub-flavour
+    - LP: #570542
+  * Revert "SAUCE: drm/i915: Disable FBC on 915GM and 945GM"
+    - LP: #588832
+  * [Config] Add atl1c to nic-modules udeb
+    - LP: #557130
+  * Revert "(pre-stable) iwlwifi: fix nfreed--"
+    - LP: #575853
+  * Revert "backlight: mbp_nvidia_bl - add five more MacBook variants"
+    - LP: #575853
+  * Revert "(pre-stable) pata_via: Add VIA VX900 support"
+    - LP: #575853
+  * Revert "(pre-stable) x86-32, resume: do a global tlb flush in S4
+    resume"
+    - LP: #575853
+  * Revert "x86: disable IOMMUs on kernel crash"
+    - LP: #575853
+  * Revert "sunrpc: fix peername failed on closed listener"
+    - LP: #575853
+  * Revert "sunrpc: move the close processing after do recvfrom method"
+    - LP: #575853
+  * Revert "(pre-stable) drm/edid: allow certain bogus edids to hit a fixup
+    path rather than fail"
+    - LP: #575853
+  * Revert "drm/radeon/kms: don't print error on -ERESTARTSYS."
+    - LP: #575853
+  * Revert "ath9k: fix lockdep warning when unloading module" on stable
+    kernels
+    - LP: #588832
+  * Staging: comedi: removed "depricated" from COMEDI_CB_BLOCK
+    - LP: #483343
+  * fat: fix buffer overflow in vfat_create_shortname()
+    - LP: #575853
+  * xfs: simplify inode teardown
+    - LP: #575853
+  * xfs: fix mmap_sem/iolock inversion in xfs_free_eofblocks
+    - LP: #575853
+  * xfs: I/O completion handlers must use NOFS allocations
+    - LP: #575853
+  * xfs: Wrapped journal record corruption on read at recovery
+    - LP: #575853
+  * xfs: Fix error return for fallocate() on XFS
+    - LP: #575853
+  * xfs: check for not fully initialized inodes in xfs_ireclaim
+    - LP: #575853
+  * xfs: fix timestamp handling in xfs_setattr
+    - LP: #575853
+  * xfs: Don't flush stale inodes
+    - LP: #575853
+  * xfs: Ensure we force all busy extents in range to disk
+    - LP: #575853
+  * xfs: reclaim inodes under a write lock
+    - LP: #575853
+  * xfs: Avoid inodes in reclaim when flushing from inode cache
+    - LP: #575853
+  * xfs: reclaim all inodes by background tree walks
+    - LP: #575853
+  * xfs: fix stale inode flush avoidance
+    - LP: #575853
+  * xfs: xfs_swap_extents needs to handle dynamic fork offsets
+    - LP: #575853
+  * xfs: quota limit statvfs available blocks
+    - LP: #575853
+  * xfs: don't hold onto reserved blocks on remount, ro
+    - LP: #575853
+  * xfs: remove invalid barrier optimization from xfs_fsync
+    - LP: #575853
+  * xfs: Non-blocking inode locking in IO completion
+    - LP: #575853
+  * xfs: fix locking for inode cache radix tree tag updates
+    - LP: #575853
+  * sh: Enable the mmu in start_secondary()
+    - LP: #575853
+  * sh: Fix FDPIC binary loader
+    - LP: #575853
+  * libiscsi: Fix recovery slowdown regression
+    - LP: #575853
+  * Freezer: Fix buggy resume test for tasks frozen with cgroup freezer
+    - LP: #575853
+  * iwlwifi: counting number of tfds can be free for 4965
+    - LP: #575853
+  * iwlwifi: fix nfreed--
+    - LP: #575853
+  * iwlwifi: range checking issue
+    - LP: #575853
+  * setup correct int pipe type in ar9170_usb_exec_cmd
+    - LP: #575853
+  * mac80211: move netdev queue enabling to correct spot
+    - LP: #575853
+  * mac80211: tear down all agg queues when restart/reconfig hw
+    - LP: #575853
+  * WATCHDOG: hpwdt - fix lower timeout limit
+    - LP: #575853
+  * WATCHDOG: iTCO_wdt: TCO Watchdog patch for additional Intel Cougar
+    Point DeviceIDs
+    - LP: #575853
+  * genirq: Force MSI irq handlers to run with interrupts disabled
+    - LP: #575853
+  * lis3: fix show rate for 8 bits chips
+    - LP: #575853
+  * pata_ali: Fix regression with old devices
+    - LP: #575853
+  * HID: fix oops in gyration_event()
+    - LP: #575853
+  * raw: fsync method is now required
+    - LP: #575853
+  * readahead: fix NULL filp dereference
+    - LP: #575853
+  * ALSA: mixart: range checking proc file
+    - LP: #575853
+  * ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981
+    - LP: #551606, #575853
+  * x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config
+    space
+    - LP: #575853
+  * resource: move kernel function inside __KERNEL__
+    - LP: #575853
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #575853
+  * pata_via: Add VIA VX900 support
+    - LP: #575853
+  * ext3: Don't update the superblock in ext3_statfs()
+    - LP: #575853
+  * ext3: journal all modifications in ext3_xattr_set_handle
+    - LP: #575853
+  * eeepc-laptop: disable cpu speed control on EeePC 701
+    - LP: #575853
+  * eeepc-laptop: dmi blacklist to disable pci hotplug code
+    - LP: #575853
+  * eeepc-laptop: add hotplug_disable parameter
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1201N
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1005PE
+    - LP: #575853
+  * libata: disable NCQ on Crucial C300 SSD
+    - LP: #575853
+  * cifs: Fix a kernel BUG with remote OS/2 server (try #3)
+    - LP: #575853
+  * CIFS: initialize nbytes at the beginning of CIFSSMBWrite()
+    - LP: #575853
+  * iwlwifi: need check for valid qos packet before free
+    - LP: #575853
+  * ARM: 6031/1: fix Thumb-2 decompressor
+    - LP: #575853
+  * x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #575853
+  * x86: hpet: Make WARN_ON understandable
+    - LP: #575853
+  * x86, hpet: Erratum workaround for read after write of HPET comparator
+    - LP: #575853
+  * x86: Fix double enable_IR_x2apic() call on SMP kernel on !SMP boards
+    - LP: #575853
+  * sched: sched_getaffinity(): Allow less than NR_CPUS length
+    - LP: #575853
+  * sched: Fix sched_getaffinity()
+    - LP: #575853
+  * NFSv4: Fall back to ordinary lookup if nfs4_atomic_open() returns
+    EISDIR
+    - LP: #575853
+  * NFSv4: fix delegated locking
+    - LP: #575853
+  * ALSA: hda - add a quirk for Clevo M570U laptop
+    - LP: #575853
+  * ALSA: usb - Fix Oops after usb-midi disconnection
+    - LP: #575853
+  * hwmon: (sht15) Fix sht15_calc_temp interpolation function
+    - LP: #575853
+  * hwmon: (sht15) Properly handle the case CONFIG_REGULATOR=n
+    - LP: #575853
+  * x86/amd-iommu: Use helper function to destroy domain
+    - LP: #575853
+  * x86/amd-iommu: enable iommu before attaching devices
+    - LP: #575853
+  * x86, lib: Add wbinvd smp helpers
+    - LP: #575853
+  * x86, cacheinfo: Fix disabling of L3 cache indices
+    - LP: #575853
+  * intel-agp: Switch to wbinvd_on_all_cpus
+    - LP: #575853
+  * x86, cacheinfo: Add cache index disable sysfs attrs only to L3 caches
+    - LP: #575853
+  * x86, cacheinfo: Calculate L3 indices
+    - LP: #575853
+  * x86, cacheinfo: Remove NUMA dependency, fix for AMD Fam10h rev D1
+    - LP: #575853
+  * x86, cacheinfo: Enable L3 CID only on AMD
+    - LP: #575853
+  * vgaarb: fix "target=default" passing
+    - LP: #575853
+  * x86-32: clean up rwsem inline asm statements
+    - LP: #575853
+  * x86: clean up rwsem type system
+    - LP: #575853
+  * x86-64, rwsem: 64-bit xadd rwsem implementation
+    - LP: #575853
+  * x86-64: support native xadd rwsem implementation
+    - LP: #575853
+  * x86: Fix breakage of UML from the changes in the rwsem system
+    - LP: #575853
+  * x86-64, rwsem: Avoid store forwarding hazard in __downgrade_write
+    - LP: #575853
+  * fix NFS4 handling of mountpoint stat
+    - LP: #575853
+  * dm mpath: fix stall when requeueing io
+    - LP: #575853
+  * quota: Fix possible dq_flags corruption
+    - LP: #575853
+  * Staging: comedi: fix usbdux timeout bug
+    - LP: #483343, #575853
+  * Staging: comedi: usbdux.c: fix locking up of the driver when the comedi
+    ringbuffer runs empty
+    - LP: #483343, #575853
+  * ocfs2: set i_mode on disk during acl operations
+    - LP: #575853
+  * ocfs2: Change bg_chain check for ocfs2_validate_gd_parent.
+    - LP: #575853
+  * 9p: Skip check for mandatory locks when unlocking
+    - LP: #575853
+  * fc class: fail fast bsg requests
+    - LP: #575853
+  * SCSI: add scsi target reset support to scsi ioctl
+    - LP: #575853
+  * PCIe AER: prevent AER injection if hardware masks error reporting
+    - LP: #575853
+  * vgaarb: Fix VGA arbiter to accept PCI domains other than 0
+    - LP: #575853
+  * SCSI: fc-transport: Use packed modifier for fc_bsg_request structure.
+    - LP: #575853
+  * pci: Update pci_set_vga_state() to call arch functions
+    - LP: #575853
+  * PCI: kill off pci_register_set_vga_state() symbol export.
+    - LP: #575853
+  * PCI: fix nested spinlock hang in aer_inject
+    - LP: #575853
+  * IPoIB: Fix TX queue lockup with mixed UD/CM traffic
+    - LP: #575853
+  * x86/PCI: irq and pci_ids patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda_intel: ALSA HD Audio patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda - enable snoop for Intel Cougar Point
+    - LP: #575853
+  * ata_piix: IDE Mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ahci: AHCI and RAID mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * i2c-i801: Add Intel Cougar Point device IDs
+    - LP: #575853
+  * b43: Remove reset after fatal DMA error
+    - LP: #575853
+  * b43: Allow PIO mode to be selected at module load
+    - LP: #575853
+  * b43: fall back gracefully to PIO mode after fatal DMA errors
+    - LP: #575853
+  * ALSA: hda - Add position_fix quirk for Biostar mobo
+    - LP: #575853
+  * agp/hp: fixup hp agp after ACPI changes
+    - LP: #575853
+  * b43: Optimize PIO scratchbuffer usage
+    - LP: #575853
+  * ecryptfs: fix use with tmpfs by removing d_drop from
+    ecryptfs_destroy_inode
+    - LP: #575853
+  * eCryptfs: Decrypt symlink target for stat size
+    - LP: #575853
+  * ecryptfs: fix error code for missing xattrs in lower fs
+    - LP: #575853
+  * sched: Fix a race between ttwu() and migrate_task()
+    - LP: #575853
+  * USB: cdc-acm: Update to new autopm API
+    - LP: #575853
+  * USB: cdc-acm: Fix stupid NULL pointer in resume()
+    - LP: #575853
+  * iwlwifi: clear all tx queues when firmware ready
+    - LP: #575853
+  * iwlwifi: fix scan race
+    - LP: #575853
+  * e1000e: stop cleaning when we reach tx_ring->next_to_use
+    - LP: #575853
+  * tcp: fix ICMP-RTO war
+    - LP: #575853
+  * perf_events, x86: Implement Intel Westmere/Nehalem-EX support
+    - LP: #575853
+  * Input: wacom - switch mode upon system resume
+    - LP: #575853
+  * md: deal with merge_bvec_fn in component devices better.
+    - LP: #575853
+  * nfsd4: don't try to map gid's in generic rpc code
+    - LP: #575853
+  * nfsd: ensure sockets are closed on error
+    - LP: #575853
+  * ALSA: hda: Set Front Mic to input vref 50% for Lenovo 3000 Y410
+    - LP: #479373, #575853
+  * mac80211: fix deferred hardware scan requests
+    - LP: #575853
+  * fs-writeback: Add helper function to start writeback if idle
+    - LP: #575853
+  * ext4: flush delalloc blocks when space is low
+    - LP: #575853
+  * ext4: fix async i/o writes beyond 4GB to a sparse file
+    - LP: #575853
+  * tpm: autoload tpm_tis based on system PnP IDs
+    - LP: #575853
+  * IB/iser: Rewrite SG handling for RDMA logic
+    - LP: #575853
+  * mptctl : Remove printk which floods unnecessary messages to
+    var/log/message
+    - LP: #575853
+  * mptspi: Fix for incorrect data underrun errata
+    - LP: #575853
+  * sched: Use proper type in sched_getaffinity()
+    - LP: #575853
+  * KVM: SVM: Fix memory leaks that happen when svm_create_vcpu() fails
+    - LP: #575853
+  * KVM: Don't spam kernel log when injecting exceptions due to bad cr
+    writes
+    - LP: #575853
+  * KVM: allow bit 10 to be cleared in MSR_IA32_MC4_CTL
+    - LP: #575853
+  * KVM: VMX: Save/restore rflags.vm correctly in real mode
+    - LP: #575853
+  * KVM: MMU: fix kvm_mmu_zap_page() and its calling path
+    - LP: #575853
+  * KVM: fix the handling of dirty bitmaps to avoid overflows
+    - LP: #575853
+  * KVM: Increase NR_IOBUS_DEVS limit to 200
+    - LP: #575853
+  * KVM: x86: Fix TSS size check for 16-bit tasks
+    - LP: #575853
+  * x86/gart: Disable GART explicitly before initialization
+    - LP: #575853
+  * r8169: clean up my printk uglyness
+    - LP: #562742, #575853
+  * Linux 2.6.32.12
+    - LP: #575853
+  * drm/edid: allow certain bogus edids to hit a fixup path rather than
+    fail
+    - LP: #575853
+  * drm/radeon: add new RS880 pci id
+    - LP: #575853
+  * drm: remove the EDID blob stored in the EDID property when it is
+    disconnected
+    - LP: #575853
+  * drm/radeon/kms: never treat rs4xx as AGP
+    - LP: #575853
+  * drm/radeon/kms: Fix NULL pointer dereference if memory allocation
+    failed in a simple way
+    - LP: #575853
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #575853
+  * drm/radeon/kms: fix pal tv-out support on legacy IGP chips
+    - LP: #575853
+  * drm: Return ENODEV if the inode mapping changes
+    - LP: #575853
+  * drm/edid/quirks: Envision EN2028
+    - LP: #575853
+  * drm/radeon: R300 AD only has one quad pipe.
+    - LP: #575853
+  * drm/radeon/kms: fix washed out image on legacy tv dac
+    - LP: #575853
+  * drm/radeon/kms/combios: verify dac_adj values are valid
+    - LP: #575853
+  * drm/i915: Add no_lvds entry for the Clientron U800
+    - LP: #544671, #575853
+  * drm/radeon/kms: more atom parser fixes (v2)
+    - LP: #575853
+  * drm/radeon/kms: disable the tv encoder when tv/cv is not in use
+    - LP: #575853
+  * drm/radeon/kms: fix tv dac conflict resolver
+    - LP: #575853
+  * drm/radeon/kms: fix rs600 tlb flush
+    - LP: #575853
+  * drm/radeon/kms: add FireMV 2400 PCI ID.
+    - LP: #575853
+  * Linux 2.6.32.12+drm33.3
+    - LP: #575853
+  * USB: EHCI: defer reclamation of siTDs
+    - LP: #583414
+  * p54usb: Add usbid for Corega CG-WLUSB2GT.
+    - LP: #583414
+  * md/raid5: allow for more than 2^31 chunks.
+    - LP: #583414
+  * md/raid5: fix previous patch.
+    - LP: #583414
+  * libata: fix locking around blk_abort_request()
+    - LP: #583414
+  * libata: ensure NCQ error result taskfile is fully initialized before
+    returning it via qc->result_tf.
+    - LP: #583414
+  * w1: w1 temp: fix negative termperature calculation
+    - LP: #583414
+  * memcg: fix prepare migration
+    - LP: #583414
+  * mac80211: remove bogus TX agg state assignment
+    - LP: #583414
+  * flex_array: fix the panic when calling flex_array_alloc() without
+    __GFP_ZERO
+    - LP: #583414
+  * core, x86: make LIST_POISON less deadly
+    - LP: #583414
+  * hugetlb: fix infinite loop in get_futex_key() when backed by huge pages
+    - LP: #583414
+  * reiserfs: fix corruption during shrinking of xattrs
+    - LP: #583414
+  * nfsd4: bug in read_buf
+    - LP: #583414
+  * keys: the request_key() syscall should link an existing key to the dest
+    keyring
+    - LP: #583414
+  * staging: usbip: Fix deadlock
+    - LP: #583414
+  * USB: fix remote wakeup settings during system sleep
+    - LP: #583414
+  * USB: Add id for HP ev2210 a.k.a Sierra MC5725 miniPCI-e Cell Modem.
+    - LP: #511066, #583414
+  * USB: fix testing the wrong variable in fs_create_by_name()
+    - LP: #583414
+  * USB: don't choose configs with no interfaces
+    - LP: #583414
+  * USB: OHCI: don't look at the root hub to get the number of ports
+    - LP: #583414
+  * USB: xhci: properly set the "Mult" field of the endpoint context.
+    - LP: #583414
+  * USB: xhci: properly set endpoint context fields for periodic eps.
+    - LP: #583414
+  * procfs: fix tid fdinfo
+    - LP: #583414
+  * ocfs2: Update VFS inode's id info after reflink.
+    - LP: #583414
+  * ocfs2: potential ERR_PTR dereference on error paths
+    - LP: #583414
+  * ocfs2: Compute metaecc for superblocks during online resize.
+    - LP: #583414
+  * ocfs2_dlmfs: Fix math error when reading LVB.
+    - LP: #583414
+  * powernow-k8: Fix frequency reporting
+    - LP: #572348, #583414
+  * nfs d_revalidate() is too trigger-happy with d_drop()
+    - LP: #583414
+  * NFS: rsize and wsize settings ignored on v4 mounts
+    - LP: #583414
+  * Staging: hv: Fix a bug affecting IPv6
+    - LP: #583414
+  * Staging: hv: Fix up memory leak on HvCleanup
+    - LP: #583414
+  * Staging: hv: name network device ethX rather than sethX
+    - LP: #583414
+  * i2c: Fix probing of FSC hardware monitoring chips
+    - LP: #583414
+  * perf: Fix resource leak in failure path of perf_event_open()
+    - LP: #583414
+  * raid6: fix recovery performance regression
+    - LP: #583414
+  * serial: 8250_pnp - add Fujitsu Wacom device
+    - LP: #583414
+  * block: ensure jiffies wrap is handled correctly in
+    blk_rq_timed_out_timer
+    - LP: #583414
+  * dm9601: fix phy/eeprom write routine
+    - LP: #583414
+  * p54pci: fix bugs in p54p_check_tx_ring
+    - LP: #583414
+  * edac, mce: Fix wrong mask and macro usage
+    - LP: #583414
+  * x86-64: Clear a 64-bit FS/GS base on fork if selector is nonzero
+    - LP: #583414
+  * x86: Disable large pages on CPUs with Atom erratum AAE44
+    - LP: #583414
+  * x86, k8 nb: Fix boot crash: enable k8_northbridges unconditionally on
+    AMD systems
+    - LP: #583414
+  * x86, AMD: Fix stale cpuid4_info shared_map data in shared_cpu_map
+    cpumasks
+    - LP: #583414
+  * ALSA: hda: Use LPIB quirk for DG965OT board version AAD63733-203
+    - LP: #459083, #583414
+  * ALSA: hda - Add PCI quirk for HP dv6-1110ax.
+    - LP: #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio XPS 1645
+    - LP: #553002, #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio 1558
+    - LP: #568600, #583414
+  * ALSA: hda: Use ALC880_F1734 quirk for Fujitsu Siemens AMILO Xi 1526
+    - LP: #567494, #583414
+  * ALSA: snd-meastro3: Add amp_gpio quirk for Compaq EVO N600C
+    - LP: #583414
+  * ALSA: snd-meastro3: Ignore spurious HV interrupts during suspend /
+    resume
+    - LP: #583414
+  * ALSA: hda: Fix max PCM level to 0 dB for Fujitsu-Siemens laptops using
+    CX20549 (Venice)
+    - LP: #583414
+  * ALSA: hda: Fix 0 dB for Packard Bell models using Conexant CX20549
+    (Venice)
+    - LP: #541802, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite Pro T130-15F
+    - LP: #573284, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite
+    P500-PSPGSC-01800T
+    - LP: #549267, #583414
+  * libata: Fix accesses at LBA28 boundary (old bug, but nasty) (v2)
+    - LP: #583414
+  * ext4: correctly calculate number of blocks for fiemap
+    - LP: #474597, #583414
+  * initramfs: handle unrecognised decompressor when unpacking
+    - LP: #583414
+  * CRED: Fix a race in creds_are_invalid() in credentials debugging
+    - LP: #583414
+  * jfs: fix diAllocExt error in resizing filesystem
+    - LP: #583414
+  * ACPI: introduce kernel parameter acpi_sleep=sci_force_enable
+    - LP: #553498, #583414
+  * p54pci: rx frame length check
+    - LP: #583414
+  * drivers/net/wireless/p54/txrx.c Fix off by one error
+    - LP: #583414
+  * dccp_probe: Fix module load dependencies between dccp and dccp_probe
+    - LP: #583414
+  * KVM: remove unused load_segment_descriptor_to_kvm_desct
+    - LP: #583414
+  * kgdb: don't needlessly skip PAGE_USER test for Fsl booke
+    - LP: #583414
+  * r8169: use correct barrier between cacheable and non-cacheable memory
+    - LP: #562742, #583414
+  * r8169: fix broken register writes
+    - LP: #562742, #583414
+  * r8169: more broken register writes workaround
+    - LP: #562742, #583414
+  * PCI: Ensure we re-enable devices on resume
+    - LP: #566149, #583414
+  * skip sense logging for some ATA PASS-THROUGH cdbs
+    - LP: #583128, #583414
+  * tg3: Fix INTx fallback when MSI fails
+    - LP: #583414
+  * xfs: add a shrinker to background inode reclaim
+    - LP: #583414
+  * qla2xxx: Properly handle UNDERRUN completion statuses.
+    - LP: #583414
+  * bnx2: Fix lost MSI-X problem on 5709 NICs.
+    - LP: #583414
+  * tracing: Fix ftrace_event_call alignment for use with gcc 4.5
+    - LP: #583414
+  * security: testing the wrong variable in create_by_name()
+    - LP: #583414
+  * md: restore ability of spare drives to spin down.
+    - LP: #583414
+  * virtio: initialize earlier
+    - LP: #583414
+  * md/raid6: Fix raid-6 read-error correction in degraded state
+    - LP: #583414
+  * V4L/DVB: budget: Oops: "BUG: unable to handle kernel NULL pointer
+    dereference"
+    - LP: #583414
+  * ACPI: DMI init_set_sci_en_on_resume for multiple Lenovo ThinkPads
+    - LP: #583414
+  * power_meter: acpi_device_class "power_meter_resource" too long
+    - LP: #583414
+  * ACPI: sleep: init_set_sci_en_on_resume for Dell Studio 155x
+    - LP: #553498, #583414
+  * cpuidle: Fix incorrect optimization
+    - LP: #583414
+  * pxa/colibri: fix missing #include <mach/mfp.h> in colibri.h
+    - LP: #583414
+  * SCSI: fix locking around blk_abort_request()
+    - LP: #583414
+  * SCSI: libiscsi: regression: fix header digest errors
+    - LP: #583414
+  * scsi_debug: virtual_gb ignores sector_size
+    - LP: #583414
+  * Enable retries for SYNCRONIZE_CACHE commands to fix I/O error
+    - LP: #583414
+  * SCSI: Retry commands with UNIT_ATTENTION sense codes to fix ext3/ext4
+    I/O error
+    - LP: #583414
+  * MIPS: Sibyte: Apply M3 workaround only on affected chip types and
+    versions.
+    - LP: #583414
+  * Linux 2.6.32.13
+    - LP: #583414
+  * drm/i915: Add initial bits for VGA modesetting bringup on Sandybridge.
+    - LP: #583414
+  * drm/i915: fix tiling limits for i915 class hw v2
+    - LP: #583414
+  * Linux 2.6.32.13+drm33.4
+    - LP: #583414
+  * (pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting
+    - LP: #551234
+  * ipv4: udp: fix short packet and bad checksum logging
+    - LP: #588832
+  * hp_accel: fix race in device removal
+    - LP: #588832
+  * fbdev: bfin-t350mcqb-fb: fix fbmem allocation with blanking lines
+    - LP: #588832
+  * hugetlbfs: kill applications that use MAP_NORESERVE with SIGBUS instead
+    of OOM-killer
+    - LP: #588832
+  * dma-mapping: fix dma_sync_single_range_*
+    - LP: #588832
+  * ACPI: sleep: eliminate duplicate entries in acpisleep_dmi_table[]
+    - LP: #588832
+  * mmc: atmel-mci: fix two parameters swapped
+    - LP: #588832
+  * mmc: atmel-mci: prevent kernel oops while removing card
+    - LP: #588832
+  * mmc: atmel-mci: remove data error interrupt after xfer
+    - LP: #588832
+  * ptrace: fix return value of do_syscall_trace_enter()
+    - LP: #588832
+  * powerpc/perf_event: Fix oops due to perf_event_do_pending call
+    - LP: #588832
+  * cifs: guard against hardlinking directories
+    - LP: #588832
+  * serial: imx.c: fix CTS trigger level lower to avoid lost chars
+    - LP: #588832
+  * ALSA: ice1724 - Fix ESI Maya44 capture source control
+    - LP: #588832
+  * ALSA: hda: Fix 0 dB for Lenovo models using Conexant CX20549 (Venice)
+    - LP: #588832
+  * inotify: race use after free/double free in inotify inode marks
+    - LP: #588832
+  * inotify: don't leak user struct on inotify release
+    - LP: #588832
+  * profile: fix stats and data leakage
+    - LP: #588832
+  * x86, k8: Fix build error when K8_NB is disabled
+    - LP: #588832
+  * x86, cacheinfo: Turn off L3 cache index disable feature in virtualized
+    environments
+    - LP: #588832
+  * x86, amd: Check X86_FEATURE_OSVW bit before accessing OSVW MSRs
+    - LP: #588832
+  * Btrfs: check for read permission on src file in the clone ioctl
+    - LP: #588832
+  * ALSA: hda - New Intel HDA controller
+    - LP: #588832
+  * proc: partially revert "procfs: provide stack information for threads"
+    - LP: #588832
+  * revert "procfs: provide stack information for threads" and its fixup
+    commits
+    - LP: #588832
+  * iwlwifi: clear all the stop_queue flag after load firmware
+    - LP: #588832
+  * p54: disable channels with incomplete calibration data sets
+    - LP: #588832
+  * CacheFiles: Fix error handling in cachefiles_determine_cache_security()
+    - LP: #588832
+  * megaraid_sas: fix for 32bit apps
+    - LP: #588832
+  * mmap_min_addr check CAP_SYS_RAWIO only for write
+    - LP: #588832
+  * nilfs2: fix sync silent failure
+    - LP: #588832
+  * crypto: authenc - Add EINPROGRESS check
+    - LP: #588832
+  * Linux 2.6.32.14
+    - LP: #588832
+  * drm/i915: use PIPE_CONTROL instruction on Ironlake and Sandy Bridge
+    - LP: #588832
+  * drm/i915: fix non-Ironlake 965 class crashes
+    - LP: #588832
+  * drm/i915: Disable FBC on 915GM and 945GM.
+    - LP: #492392, #588832
+  * Linux 2.6.32.14+drm33.5
+    - LP: #588832
+  * Linux 2.6.32.15+drm33.5
+    - LP: #588832
+  * HID: remove MODULE_VERSION from new drivers
+    - LP: #583531
+  * HID: fix N-trig touch panel with recent firmware
+    - LP: #583531
+  * HID: ntrig: explain firmware quirk
+    - LP: #583531
+  * HID: ntrig: Emit TOUCH with DOUBLETAP for single touch
+    - LP: #583531
+  * HID: ntrig: TipSwitch for single touch mode touch.
+    - LP: #583531
+  * HID: ntrig: Remove unused macro, TripleTap and QuadTap
+    - LP: #583531
+  * (pre-stable) drm/radeon/kms: initialize set_surface_reg reg for rs600
+    asic
+    - LP: #544590
+
+  [ Ubuntu: 2.6.32-22.36 ]
+
+  * Revert "kvm: restrict writing of segment selectors to segment
+    registers"
+    - LP: #589223
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Sat, 12 Jun 2010 16:24:14 +0200
+
+linux-ec2 (2.6.32-306.11) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebase to 2.6.32-22.35
+  * [Config] EC2: Set CONFIG_BLK_DEV_DM=y to match enforcer settings
+
+  [ Ubuntu: 2.6.32-22.35 ]
+
+  * kvm: restrict writing of segment selectors to segment registers
+    - CVE-2010-0419
+  * tty: release_one_tty() forgets to put pids
+    - CVE-2010-1162
+  * oom: fix the unsafe usage of badness() in proc_oom_score()
+    - CVE-2010-1488
+  * Attempt #2 to handle null nameidata
+    - CVE-2010-1148
+  * reiserfs: fix permissions on .reiserfs_priv
+    - CVE-2010-1146
+  * r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)
+    - CVE-2009-4537
+
+  [ Ubuntu: 2.6.32-22.33 ]
+
+  * SAUCE: ACPI: EC: Allow multibyte access to EC (v3)
+    - LP: #526354
+  * ubuntu: rtl8192se -- update to version 0015.0127.2010
+    - LP: #567016
+
+  [ Ubuntu: 2.6.32-21.32 ]
+
+  * SAUCE: i915 KMS -- support disabling KMS for known broken devices
+    - LP: #563277
+  * SAUCE: i915 KMS -- blacklist i830
+    - LP: #542208, #563277
+  * SAUCE: i915 KMS -- blacklist i845g
+    - LP: #541492, #563277
+  * SAUCE: i915 KMS -- blacklist i855
+    - LP: #511001, #541511, #563277
+  * SAUCE: radeon KMS -- support disabling KMS for known broken devices
+    - LP: #546743
+  * SAUCE: radeon KMS -- blacklist ES1000
+    - LP: #546743
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 01 Jun 2010 12:14:05 +0200
+
+linux-ec2 (2.6.32-305.9) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-21.31
+  * SAUCE: xen -- TSC is not available under XEN
+
+  [ John Johansen ]
+
+  * [Config] enable NETFILTER_XT_MATCH_RECENT for ec2 kernels
+    - LP: #532553
+
+  [ Ubuntu: 2.6.32-21.31 ]
+
+  * allow modules.builtin to be optional
+  * d-i: add mpt2sas to the message-modules udeb
+    - LP: #530361
+  * SAUCE: Nouveau: Add quirk framework to disable acceleration
+    - LP: #544088, #546393
+  * SAUCE: Nouveau: Disable acceleration on MacBook Pros
+    - LP: #546393
+  * SAUCE: Nouveau: Disable acceleration on GeForce3 cards
+    - LP: #544088
+  * SAUCE: Nouveau: Disable acceleration on 6100 cards
+    - LP: #542950
+  * SAUCE: dma-mapping: Remove WARN_ON in dma_free_coherent
+    - LP: #458201
+  * SAUCE: sync before umount to reduce time taken by ext4 umount
+    - LP: #543617
+  * tipc: Fix oops on send prior to entering networked mode (v3)
+    - CVE-2010-1187
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - LP: #561425
+  * KVM: x86 emulator: fix memory access during x86 emulation
+    - LP: #561425
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - LP: #561425
+  * KVM: x86 emulator: Fix popf emulation
+    - LP: #561425
+  * KVM: Fix segment descriptor loading
+    - LP: #561425
+  * KVM: VMX: Update instruction length on intercepted BP
+    - LP: #561425
+  * KVM: VMX: Use macros instead of hex value on cr0 initialization
+    - LP: #561425
+  * KVM: SVM: Reset cr0 properly on vcpu reset
+    - LP: #561425
+  * KVM: VMX: Disable unrestricted guest when EPT disabled
+    - LP: #561425
+  * KVM: x86: disable paravirt mmu reporting
+    - LP: #561425
+  * AppArmor: Fix put of unassigned ns if aa_unpack fails
+  * AppArmor: Fix refcount bug when exec fails
+    - LP: #562063
+  * AppArmor: Take refcount on cxt->profile to ensure it remains a valid
+    reference
+    - LP: #367499
+  * AppArmor: fix typo in scrubbing environment variable warning
+    - LP: #562060
+  * AppArmor: fix regression by setting default to mediate deleted files
+    - LP: #562056
+  * AppArmor: fix refcount order bug that can trigger during replacement
+    - LP: #367499
+  * AppArmor: Make sure to unmap aliases for vmalloced dfas before they are
+    live
+    - LP: #529288
+  * AppArmor: address performance regression of replaced profile
+    - LP: #549428
+  * AppArmor: make the global side the correct type
+    - LP: #562047
+  * AppArmor: use the kernel shared workqueue to free vmalloc'ed dfas
+  * sky2: add register definitions for new chips
+    - LP: #537168
+  * sky2: 88E8059 support
+    - LP: #537168
+  * net: Fix Yukon-2 Optima TCP offload setup
+    - LP: #537168
+  * net: Add missing TST_CFG_WRITE bits around sky2_pci_write
+    - LP: #537168
+  * sky2: print Optima chip name
+    - LP: #537168
+  * (Upstream) dell-laptop: defer dell_rfkill_update to worker thread
+    - LP: #555261
+  * drm/nv40: add LVDS table quirk for Dell Latitude D620
+    - LP: #539730
+
+  [ Ubuntu: 2.6.32-20.30 ]
+
+  * Revert "(pre-stable) ACPI: EC: Allow multibyte access to EC"
+    - LP: #561151
+
+  [ Ubuntu: 2.6.32-20.29 ]
+
+  * Revert "SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915"
+    - LP: #542251
+  * add Breaks: against hardy lvm2
+    - LP: #528155
+  * d-i -- enable udebs for generic-pae
+    - LP: #160366
+  * [Config] Add xen netboot support
+    - LP: #160366
+  * (pre-stable): input: Support Clickpad devices in ClickZone mode
+    - LP: #516329
+  * Revert "(pre-stable) Bluetooth: Fix sleeping function in RFCOMM within
+    invalid context"
+    - LP: #553837
+  * Revert "(pre-stable) USB: fix usbfs regression"
+    - LP: #553837
+  * Revert "(pre-stable) softlockup: Stop spurious softlockup messages due
+    to overflow"
+    - LP: #553837
+  * Revert "(pre-stable) drm/nouveau: report unknown connector state if lid
+    closed"
+    - LP: #553837
+  * drivers/scsi/ses.c: eliminate double free
+    - LP: #553837
+  * decompress: fix new decompressor for PIC
+    - LP: #553837
+  * ARM: Fix decompressor's kernel size estimation for ROM=y
+    - LP: #553837
+  * MIPS: Cleanup forgotten label_module_alloc in tlbex.c
+    - LP: #553837
+  * tg3: Fix tg3_poll_controller() passing wrong pointer to tg3_interrupt()
+    - LP: #553837
+  * tg3: Fix 5906 transmit hangs
+    - LP: #553837
+  * ALSA: hda - Fix input source elements of secondary ADCs on Realtek
+    - LP: #553837
+  * ALSA: hda: enable MSI for Gateway M-6866
+    - LP: #538918, #553837
+  * timekeeping: Prevent oops when GENERIC_TIME=n
+    - LP: #553837
+  * Input: alps - add support for the touchpad on Toshiba Tecra A11-11L
+    - LP: #553837
+  * Input: i8042 - add ALDI/MEDION netbook E1222 to qurik reset table
+    - LP: #553837
+  * i2c-i801: Don't use the block buffer for I2C block writes
+    - LP: #553837
+  * ath5k: dont use external sleep clock in AP mode
+    - LP: #553837
+  * ath5k: fix setup for CAB queue
+    - LP: #553837
+  * ring-buffer: Move disabled check into preempt disable section
+    - LP: #553837
+  * function-graph: Init curr_ret_stack with ret_stack
+    - LP: #553837
+  * Bluetooth: Fix sleeping function in RFCOMM within invalid context
+    - LP: #553837
+  * tracing: Use same local variable when resetting the ring buffer
+    - LP: #553837
+  * tracing: Disable buffer switching when starting or stopping trace
+    - LP: #553837
+  * tracing: Do not record user stack trace from NMI context
+    - LP: #553837
+  * PCI: unconditionally clear AER uncorr status register during cleanup
+    - LP: #553837
+  * efifb: fix framebuffer handoff
+    - LP: #553837
+  * coredump: suppress uid comparison test if core output files are pipes
+    - LP: #553837
+  * V4L/DVB (13961): em28xx-dvb: fix memleak in dvb_fini()
+    - LP: #553837
+  * hrtimer: Tune hrtimer_interrupt hang logic
+    - LP: #553837
+  * x86, apic: Don't use logical-flat mode when CPU hotplug may exceed 8
+    CPUs
+    - LP: #553837
+  * mvsas: add support for Adaptec ASC-1045/1405 SAS/SATA HBA
+    - LP: #553837
+  * pci: add support for 82576NS serdes to existing SR-IOV quirk
+    - LP: #553837
+  * sched: Mark boot-cpu active before smp_init()
+    - LP: #553837
+  * sparc64: Make prom entry spinlock NMI safe.
+    - LP: #553837
+  * sysctl: require CAP_SYS_RAWIO to set mmap_min_addr
+    - LP: #553837
+  * e1000e: enable new 82567V-3 device
+    - LP: #553837
+  * ixgbe: add support for 82599 KR device 0x1517
+    - LP: #553837
+  * ath9k: fix lockdep warning when unloading module
+    - LP: #553837
+  * mqueue: fix mq_open() file descriptor leak on user-space processes
+    - LP: #553837
+  * virtio: fix out of range array access
+    - LP: #553837
+  * sched: Fix SCHED_MC regression caused by change in sched cpu_power
+    - LP: #553837
+  * readahead: add blk_run_backing_dev
+    - LP: #553837
+  * ALSA: hda: Use LPIB and 6stack-dig for eMachines T5212
+    - LP: #538895, #553837
+  * ALSA: hda - Disable MSI for Nvidia controller
+    - LP: #553837
+  * ALSA: hda - Fix secondary ADC of ALC260 basic model
+    - LP: #553837
+  * ALSA: hda: Fix 0 dB offset for HP laptops using CX20551 (Waikiki)
+    - LP: #420578, #553837
+  * ALSA: cmipci: work around invalid PCM pointer
+    - LP: #553837
+  * gigaset: correct clearing of at_state strings on RING
+    - LP: #553837
+  * gigaset: prune use of tty_buffer_request_room
+    - LP: #553837
+  * perf: Make the install relative to DESTDIR if specified
+    - LP: #553837
+  * perf_event: Fix oops triggered by cpu offline/online
+    - LP: #553837
+  * tmpfs: fix oops on mounts with mpol=default
+    - LP: #553837
+  * tmpfs: mpol=bind:0 don't cause mount error.
+    - LP: #553837
+  * tmpfs: handle MPOL_LOCAL mount option properly
+    - LP: #553837
+  * tmpfs: cleanup mpol_parse_str()
+    - LP: #553837
+  * doc: add the documentation for mpol=local
+    - LP: #553837
+  * SCSI: scsi_transport_fc: Fix synchronization issue while deleting vport
+    - LP: #553837
+  * NFSv4: Don't ignore the NFS_INO_REVAL_FORCED flag in
+    nfs_revalidate_inode()
+    - LP: #553837
+  * NFS: Avoid a deadlock in nfs_release_page
+    - LP: #553837
+  * NFS: Prevent another deadlock in nfs_release_page()
+    - LP: #553837
+  * tty: Keep the default buffering to sub-page units
+    - LP: #553837
+  * tty: Take a 256 byte padding into account when buffering below sub-page
+    units
+    - LP: #553837
+  * USB: fix usbfs regression
+    - LP: #553837
+  * USB: EHCI: fix ITD list order
+    - LP: #553837
+  * USB: EHCI: adjust ehci_iso_stream for changes in ehci_qh
+    - LP: #553837
+  * USB: qcserial: add new device ids
+    - LP: #553837
+  * USB: xHCI: re-initialize cmd_completion
+    - LP: #553837
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #553837
+  * USB: option: fix incorrect manufacturer name in usb/serial/option:
+    MAXON->CMOTECH
+    - LP: #553837
+  * USB: option: move hardcoded PID to a macro in usb/serial/option
+    - LP: #553837
+  * USB: option: add support for a new CMOTECH device to usb/serial/option
+    - LP: #553837
+  * usb: r8a66597-hcd: fix removed from an attached hub
+    - LP: #553837
+  * wl1251: fix potential crash
+    - LP: #553837
+  * jme: Fix VLAN memory leak
+    - LP: #553837
+  * jme: Protect vlgrp structure by pause RX actions.
+    - LP: #553837
+  * edac, mce: Filter out invalid values
+    - LP: #553837
+  * iwlwifi: use dma_alloc_coherent
+    - LP: #553837
+  * iwlwifi: Silence tfds_in_queue message
+    - LP: #553837
+  * SUNRPC: Fix a potential memory leak in auth_gss
+    - LP: #553837
+  * sunrpc: handle allocation errors from __rpc_lookup_create()
+    - LP: #553837
+  * if_tunnel.h: add missing ams/byteorder.h include
+    - LP: #553837
+  * fs/partitions/msdos: add support for large disks
+    - LP: #553837
+  * fs/partition/msdos: fix unusable extended partition for > 512B sector
+    - LP: #553837
+  * PCI: fix return value from pcix_get_max_mmrbc()
+    - LP: #553837
+  * PCI: fix access of PCI_X_CMD by pcix get and set mmrbc functions
+    - LP: #553837
+  * PCI: cleanup error return for pcix get and set mmrbc functions
+    - LP: #553837
+  * rt2860sta: Fix argument to linux_pci_unmap_single()
+    - LP: #553837
+  * ath9k: fix BUG_ON triggered by PAE frames
+    - LP: #553837
+  * cpuset: fix the problem that cpuset_mem_spread_node() returns an
+    offline node
+    - LP: #553837
+  * softlockup: Stop spurious softlockup messages due to overflow
+    - LP: #553837
+  * netfilter: xt_recent: fix regression in rules using a zero hit_count
+    - LP: #553837
+  * x86: Fix placement of FIX_OHCI1394_BASE
+    - LP: #553837
+  * x86, amd: Restrict usage of c1e_idle()
+    - LP: #553837
+  * hwmon: (coretemp) Add missing newline to dev_warn() message
+    - LP: #553837
+  * ALSA: hda: Use LPIB for ga-ma770-ud3 board
+    - LP: #553837
+  * ALSA: ac97: Add Toshiba P500 to ac97 jack sense blacklist
+    - LP: #481058, #553837
+  * ALSA: ac97: Add IBM ThinkPad R40e to Headphone/Line Jack Sense
+    blacklist
+    - LP: #303789, #553837
+  * ALSA: hda: Use ALC260_WILL quirk for another Acer model (0x1025007f)
+    - LP: #418627, #553837
+  * ath9k: Enable TIM timer interrupt only when needed.
+    - LP: #553837
+  * mac80211: Retry null data frame for power save
+    - LP: #553837
+  * ath9k: Enable IEEE80211_HW_REPORTS_TX_ACK_STATUS flag for ath9k
+    - LP: #553837
+  * mac80211: Reset dynamic ps timer in Rx path.
+    - LP: #553837
+  * leds-gpio: fix default state handling on OF platforms
+    - LP: #553837
+  * quota: manage reserved space when quota is not active [v2]
+    - LP: #553837
+  * quota: Fix warning when a delayed write happens before quota is enabled
+    - LP: #553837
+  * ahci: use BIOS date in broken_suspend list
+    - LP: #553837
+  * Bluetooth: Fix potential bad memory access with sysfs files
+    - LP: #553837
+  * Bluetooth: Fix kernel crash on L2CAP stress tests
+    - LP: #553837
+  * sh: Fix zImage boot using fixed PMB.
+    - LP: #553837
+  * b43: Workaround circular locking in hw-tkip key update callback
+    - LP: #553837
+  * block: Backport of various I/O topology fixes from 2.6.33 and 2.6.34
+    - LP: #553837
+  * s3cmci: initialize default platform data no_wprotect and no_detect with
+    1
+    - LP: #553837
+  * x86: Fix sched_clock_cpu for systems with unsynchronized TSC
+    - LP: #553837
+  * GFS2: Skip check for mandatory locks when unlocking
+    - LP: #553837
+  * Linux 2.6.32.11
+    - LP: #553837
+  * drm/i915: fix small leak on overlay error path
+    - LP: #553837
+  * drm/i915: Avoid NULL deref in get_pages() unwind after error.
+    - LP: #553837
+  * drm/nouveau: report unknown connector state if lid closed
+    - LP: #553837
+  * Linux-2.6.32.11+drm33.2
+    - LP: #553837
+  * mmc: add module parameter to set whether cards are assumed removable
+    - LP: #477106
+  * (pre-stable) ACPI: EC: Allow multibyte access to EC
+    - LP: #526354
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #509273
+  * drm/i915: Add dependency on the intel agp module
+    - LP: #542251
+  * (pre-stable) drm/edid: allow certain bogus edids to hit a fixup path
+    rather than fail
+    - LP: #540632
+  * drm/radeon/kms: rework pll algo selection
+    - LP: #538377
+  * drm/radeon/kms: update new pll algo
+    - LP: #538377
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #544741
+  * sched: update load count only once per cpu in 10 tick update window
+    - LP: #513848
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 14 Apr 2010 13:09:10 +0100
+
+linux-ec2 (2.6.32-304.8) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-19.28
+  * updateconfigs after rebase to Ubuntu-2.6.32-19.28
+
+  [ John Johansen ]
+
+  * [Config] fix EC2 config to remove soft lockup issue
+    - LP: #527208, #540378
+
+  [ Ubuntu: 2.6.32-19.28 ]
+
+  * [Config] enable various multitouch devices
+    - LP: #541453
+  * (pre-stable): input: ALPS - Add signature for HP Pavilion dm3 laptops
+    - LP: #545307
+  * SAUCE: Disable function tracing after hitting __schedule_bug
+  * SAUCE: Reduce ACPI resource conflict message to KERN_INFO, printf
+    cleanup
+    - LP: #440470
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+  * SAUCE: AppArmor: Remove null_profile's use of PFLAG_NO_LIST_REF
+    - LP: #539437
+  * SAUCE: AppArmor: Stop page allocation warnings that can occur on policy
+    load
+    - LP: #458299
+  * SAUCE: AppArmor: Return string len rather than the allocation size
+    - LP: #551844
+  * SAUCE: AppArmor: Fix oops in profile verification if profile unpack
+    fails.
+  * [Config] Enable Nouveau DRM module on powerpc
+  * SAUCE: Pull in thinkpad-acpi from v2.6.34-rc1
+    - LP: #357673
+  * [Config] Enable thinkpad-acpi ALSA volume control
+    - LP: #357673
+  * SAUCE: drm/i915: Disable FBC on 915GM and 945GM
+    - LP: #492392, #539609
+  * Revert "(pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP,
+    Dell Inspiron 700m"
+    - LP: #515246
+  * (pre-stable) softlockup: Stop spurious softlockup messages due to
+    overflow
+    - LP: #551068
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #511965
+  * drm/nv04-nv40: Fix up the programmed horizontal sync pulse delay.
+    - LP: #529130
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #544739
+  * (pre-stable) USB: fix usbfs regression
+  * drm/radeon/bo: add some fallback placements for VRAM only objects.
+    - LP: #507148
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #507148
+  * Input: add the ABS_MT_PRESSURE event
+    - LP: #541453
+  * HID: Support for 3M multitouch panel
+    - LP: #541453
+  * HID: make 3M PCT touchscreen driver standalone config option
+    - LP: #541453
+  * HID: add support for Stantum multitouch panel
+    - LP: #541453
+  * HID: make Stantum driver standalone config option
+    - LP: #541453
+  * HID: add support for Acer T230H multitouch
+    - LP: #541453
+  * HID: add support for Pixart Imaging Optical Touch Screen
+    - LP: #541453
+  * HID: fixed bug in single-touch emulation on the stantum panel
+    - LP: #541453
+  * HID: add pressure support for the Stantum multitouch panel
+    - LP: #541453
+  * HID: Support for MosArt multitouch panel
+    - LP: #541453
+  * HID: hid-ntrig add multi input quirk and clean up
+    - LP: #541453
+  * HID: n-trig: remove unnecessary tool switching
+    - LP: #541453
+  * HID: hid-ntrig: multitouch cleanup and fix
+    - LP: #541453
+  * HID: hid-ntrig: Single touch mode tap
+    - LP: #541453
+  * hid: ntrig touch events
+    - LP: #541453
+  * (pre-stable) x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #531309
+  * drm/i915: Part of: Add initial bits for VGA modesetting bringup on
+    Sandybridge.
+    - LP: #515246
+  * drm/i915: Stop trying to use ACPI lid status to determine LVDS
+    connection.
+    - LP: #515246
+
+  [ Ubuntu: 2.6.32-18.27 ]
+
+  * SAUCE: Don't register vga16fb framebuffer if other framebuffers are
+    present
+    - LP: #527369
+  * [Config] armel/versatile: Set CRAMFS=m
+    - LP: #524893
+  * [Config] armel: Reset default command-line
+    - LP: #524893
+  * build/modules: Update d-i to reflect recent config changes
+    - LP: #546929
+  * (pre-stable) drm/nouveau: report unknown connector state if lid closed
+    - LP: #523072
+  * (pre-stable) Staging: rt2870: Add USB ID for Buffalo Airstation
+    WLI-UC-GN
+    - LP: #441990
+  * (pre-stable) iwlwifi: fix nfreed--
+    - LP: #545585
+  * (pre-stable) pata_via: Add VIA VX900 support
+    - LP: #548675
+
+  [ Ubuntu: 2.6.32-17.26 ]
+
+  * [Config] SECURITY_FILE_CAPABILITIES dissapeared in 2.6.33
+  * rules -- allow architecture configurations to be missing
+  * SAUCE: cdrom -- default to not locking the tray when in use
+    - LP: #397734
+  * expose the kernel EXTRAVERSION in dmesg and /proc/version_signature
+  * record the drm version in EXTRAVERSION
+  * linux-tools -- pull out the perf binary into a binary package
+  * [Config] enable MMIOTRACE for graphics debugging
+  * [Config] enable BLK_DEV_BSG
+  * debian -- fix builds when tools are disabled
+  * allow us to build default configs for automated builds
+  * config -- allow locally specified configuration overrides
+  * [Config] de-modularise PATA disk controllers
+  * [Config] de-modularise SATA disk controllers
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow"
+    - LP: #540231
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix false match"
+    - LP: #540231
+  * [Config] Update configs for 2.6.32.10
+    - LP: #540231
+  * [Config] Add vmw_pvscsi and vmxnet3 to -virtual flavour
+    - LP: #531017
+  * SAUCE: igb: Supress an upstream compiler complaint
+  * [Config] Fix sub-flavours package conflicts
+    - LP: #454827
+  * Revert "tpm_tis: TPM_STS_DATA_EXPECT workaround"
+    - LP: #540231
+  * Revert "(pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()"
+    - LP: #540231
+  * (pre-stable) Bluetooth: Fix sleeping function in RFCOMM within invalid
+    context
+    - LP: #534549
+  * igb: remove unused temp variable from stats clearing path
+  * igb: update comments for serdes config and update to handle duplex
+  * igb: update the approach taken to acquiring and releasing the phy lock
+  * igb: add locking to reads of the i2c interface
+  * igb: add combined function for setting rar and pool bits
+  * igb: make use of the uta to allow for promiscous mode filter
+  * igb: add support for 82576NS SerDes adapter
+  * igb: add function to handle mailbox lock
+  * igb: fix a few items where weren't correctly setup for mbx timeout
+  * igb: change how we handle alternate mac addresses
+  * igb: remove microwire support from igb
+  * igb: move the generic copper link setup code into e1000_phy.c
+  * igb: add code to retry a phy read in the event of failure on link check
+  * igb: add additional error handling to the phy code
+  * igb: add flushes between RAR writes when setting mac address
+  * igb: Use the instance of net_device_stats from net_device.
+  * igb: Fix erroneous display of stats by ethtool -S
+  * igb: add new data structure for handling interrupts and NAPI
+  * igb: remove rx checksum good counter
+  * igb: increase minimum rx buffer size to 1K
+  * igb: move the tx and rx ring specific config into seperate functions
+  * igb: remove rx_ps_hdr_len
+  * igb: move SRRCTL register configuration into ring specific config
+  * igb: change the head and tail offsets into pointers
+  * igb: add pci device pointer to ring structure
+  * igb: move rx_buffer_len into the ring structure
+  * igb: move alloc_failed and csum_err stats into per rx-ring stat
+  * igb: add a flags value to the ring
+  * igb: place a pointer to the netdev struct in the ring itself
+  * igb: move the multiple receive queue configuration into seperate
+    function
+  * igb: delay VF reset notification until after interrupts are enabed
+  * igb: setup vlan tag replication stripping in igb_vmm_control
+  * igb: re-use ring configuration code in ethtool testing
+  * igb: make tx ring map and free functionality non-static
+  * igb: make ethtool use core xmit map and free functionality
+  * igb: add single vector msi-x testing to interrupt test
+  * igb: cleanup "todo" code found in igb_ethtool.c
+  * igb: add support for seperate tx-usecs setting in ethtool
+  * igb: cleanup some of the code related to hw timestamping
+  * igb: misc cleanups within igb_ethtool.c
+  * igb: use packet buffer sizes from RXPBS register
+  * igb: replace the VF clear_to_send with a flags value
+  * igb: rework use of VMOLR in regards to PF and VFs
+  * igb: rework handling of the vfta and vlvf registers in relation to
+    mng_vlan
+  * igb: move vf init into a seperate function
+  * igb: only process global stats in igb_update_stats
+  * igb: move global_quad_port_a from global into local static define
+  * igb: make tx hang check multiqueue, check eop descriptor
+  * igb: cleanup code related to ring resource allocation and free
+  * igb: change queue ordering for 82576 based adapters
+  * igb: cleanup interrupt enablement in regards to msix_other
+  * igb: Remove invalid stats counters
+  * igb: cleanup igb.h header whitespace and some structure formatting
+  * igb: cleanup igb xmit frame path
+  * igb: cleanup clean_rx_irq_adv and alloc_rx_buffers_adv
+  * igb: replace unecessary &adapter->hw with just hw where applicable
+  * igb: add pci_dev in few spots to clean up use of dev_err/info/warn
+  * igb: limit minimum mtu to 68 to keep ip bound to interface
+  * igb: open up SCTP checksum offloads to all MACs 82576 and newer
+  * igb: cleanup whitespace issues in igb_main.c
+  * igb: Fix warnings in igb_set_ringparam()
+  * igb: change type for ring sizes to u16 in igb_set_ring_param
+  * igb: move timesync init into a seperate function
+  * igb: when number of CPUs > 4 combine tx/rx queues to allow more queues
+  * igb: Rework how netdev->stats is handled
+  * igb: removed unused tx/rx total bytes/packets from adapter struct
+  * igb: check for packets on all tx rings when link is down
+  * igb: only recycle page if it is on our numa node
+  * igb: add support for the 82580 phy
+  * igb: add support for 82580 MAC
+  * igb: Add full support for 82580 devices
+  * igb: remove use of skb_dma_map from driver
+  * igb: fix handling of mailbox collisions between PF/VF
+  * igb: do not force pcs link when in KX mode
+  * igb: do not force retry count to 1 on 82580 phy
+  * igb: correctly offset 82575 flow control watermarks by 16 bytes
+  * igb: check both function bits in status register in wol exception
+  * igb: make certain to reassign legacy interrupt vectors after reset
+  * igb/igbvf: cleanup exception handling in tx_map_adv
+  * fix LOOKUP_FOLLOW on automount "symlinks"
+    - LP: #540231
+  * ARM: 5944/1: scsi: fix timer setup in fas216.c
+    - LP: #540231
+  * V4L/DVB: dvb: l64781.ko broken with gcc 4.5
+    - LP: #540231
+  * bfin: fix max timeout calculation
+    - LP: #540231
+  * V4L/DVB: Video : pwc : Fix regression in pwc_set_shutter_speed caused
+    by bad constant => sizeof conversion.
+    - LP: #540231
+  * V4L/DVB: bttv: Move I2C IR initialization
+    - LP: #540231
+  * V4L/DVB: cxusb: Select all required frontend and tuner modules
+    - LP: #540231
+  * memcg: fix oom killing a child process in an other cgroup
+    - LP: #540231
+  * fs/exec.c: fix initial stack reservation
+    - LP: #540231
+  * iwlwifi: error checking for number of tfds in queue
+    - LP: #540231
+  * iwlwifi: set HT flags after channel in rxon
+    - LP: #540231
+  * iwlwifi: sanity check before counting number of tfds can be free
+    - LP: #540231
+  * netlabel: fix export of SELinux categories > 127
+    - LP: #540231
+  * ahci: disable FPDMA auto-activate optimization on NVIDIA AHCI
+    - LP: #540231
+  * PCI hotplug: ibmphp: read the length of ebda and map entire ebda region
+    - LP: #540231
+  * PCI hotplug: check ioremap() return value in ibmphp_ebda.c
+    - LP: #540231
+  * ACPI: remove Asus P2B-DS from acpi=ht blacklist
+    - LP: #540231
+  * ACPI: fix "acpi=ht" boot option
+    - LP: #540231
+  * thinkpad-acpi: wrong thermal attribute_group removed in thermal_exit()
+    - LP: #540231
+  * ACPI: Be in TS_POLLING state during mwait based C-state entry
+    - LP: #540231
+  * mpt2sas: Delete volume before HBA detach.
+    - LP: #540231
+  * slab: initialize unused alien cache entry as NULL at
+    alloc_alien_cache().
+    - LP: #540231
+  * mac80211: quit addba_resp_timer if Tx BA session is torn down
+    - LP: #540231
+  * V4L/DVB (13991): gspca_mr973010a: Fix cif type 1 cameras not streaming
+    on UHCI controllers
+    - LP: #540231
+  * vfs: take f_lock on modifying f_mode after open time
+    - LP: #540231
+  * readahead: introduce FMODE_RANDOM for POSIX_FADV_RANDOM
+    - LP: #540231
+  * HID: remove TENX iBuddy from blacklist
+    - LP: #540231
+  * HID: add multi-input quirk for NextWindow Touchscreen.
+    - LP: #540231
+  * HID: usbhid: introduce timeout for stuck ctrl/out URBs
+    - LP: #540231
+  * airo: fix setting zero length WEP key
+    - LP: #540231
+  * idr: fix a critical misallocation bug, take#2
+    - LP: #540231
+  * Switch proc/self to nd_set_link()
+    - LP: #540231
+  * sparc: Align clone and signal stacks to 16 bytes.
+    - LP: #540231
+  * sparc32: Fix page_to_phys().
+    - LP: #540231
+  * sparc32: Fix struct stat uid/gid types.
+    - LP: #540231
+  * sparc: leds_resource.end assigned to itself in clock_board_probe()
+    - LP: #540231
+  * sparc64: Fix sun4u execute bit check in TSB I-TLB load.
+    - LP: #540231
+  * net: Fix sysctl restarts...
+    - LP: #540231
+  * net-sysfs: Use rtnl_trylock in wireless sysfs methods.
+    - LP: #540231
+  * net: bug fix for vlan + gro issue
+    - LP: #540231
+  * inet: Remove bogus IGMPv3 report handling
+    - LP: #540231
+  * ipv6: conntrack: Add member of user to nf_ct_frag6_queue structure
+    - LP: #540231
+  * drivers/net: ks8851_mll ethernet network driver
+    - LP: #540231
+  * sky2: fix transmit DMA map leakage
+    - LP: #540231
+  * SCSI: qla2xxx: Obtain proper host structure during response-queue
+    processing.
+    - LP: #540231
+  * rtc-core: fix memory leak
+    - LP: #540231
+  * offb: Add support for framebuffer handoff to offb.
+    - LP: #540231
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #540231
+  * rndis_wlan: handle NL80211_AUTHTYPE_AUTOMATIC
+    - LP: #540231
+  * rndis_wlan: fix buffer overflow in rndis_query_oid
+    - LP: #540231
+  * rndis_wlan: disable stall workaround
+    - LP: #540231
+  * net/via-rhine: Fix scheduling while atomic bugs
+    - LP: #540231
+  * clocksource: Fix up a registration/IRQ race in the sh drivers.
+    - LP: #540231
+  * SCSI: qla1280: Drop host_lock while requesting firmware
+    - LP: #540231
+  * Staging: hv: add a pci device table
+    - LP: #540231
+  * Staging: hv: match on DMI values to know if we should run.
+    - LP: #540231
+  * Staging: mimio: remove the mimio driver
+    - LP: #540231
+  * dvb-core: Fix DoS bug in ULE decapsulation code that can be triggered
+    by an invalid Payload Pointer
+    - LP: #540231
+  * V4L/DVB (13148): uvcvideo: Handle V4L2_CTRL_TYPE_BUTTON control type in
+    VIDIOC_QUERYCTRL
+    - LP: #540231
+  * PM / Hibernate: Fix preallocating of memory
+    - LP: #540231
+  * macintosh/therm_adt746x: Fix sysfs attributes lifetime
+    - LP: #540231
+  * macintosh/hwmon/ams: Fix device removal sequence
+    - LP: #540231
+  * oprofile/x86: fix perfctr nmi reservation for mulitplexing
+    - LP: #540231
+  * oprofile: remove tracing build dependency
+    - LP: #540231
+  * oprofile/x86: remove node check in AMD IBS initialization
+    - LP: #540231
+  * oprofile/x86: use kzalloc() instead of kmalloc()
+    - LP: #540231
+  * oprofile/x86: fix msr access to reserved counters
+    - LP: #540231
+  * ALSA: hda: Use 3stack quirk for Toshiba Satellite L40-10Q
+    - LP: #524948, #540231
+  * ALSA: via82xx: add quirk for D1289 motherboard
+    - LP: #540231
+  * ALSA: pcm core - fix fifo_size channels interval check
+    - LP: #540231
+  * ALSA: USB MIDI support for Access Music VirusTI
+    - LP: #540231
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #540231
+  * ALSA: hda: Use LPIB for a Biostar Microtech board
+    - LP: #523953, #540231
+  * ALSA: hda - Add a position_fix quirk for MSI Wind U115
+    - LP: #540231
+  * ALSA: hda - Add position_fix quirk for HP dv3
+    - LP: #540231
+  * ALSA: hda-intel: Add position_fix quirk for ASUS M2V-MX SE.
+    - LP: #540231
+  * ASoC: fix ak4104 register array access
+    - LP: #540231
+  * driver-core: fix race condition in get_device_parent()
+    - LP: #540231
+  * Driver-Core: devtmpfs - reset inode permissions before unlinking
+    - LP: #540231
+  * tty: Fix the ldisc hangup race
+    - LP: #540231
+  * serial: imx: fix NULL dereference Oops when pdata == NULL
+    - LP: #540231
+  * USB: serial: sierra driver indat_callback fix
+    - LP: #511157, #540231
+  * USB: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor
+    USB20SVGA-MB-PLUS
+    - LP: #540231
+  * USB: fix I2C API usage in ohci-pnx4008.
+    - LP: #540231
+  * p54usb: Add the USB ID for Belkin (Accton) FD7050E ver 1010ec
+    - LP: #540231
+  * p54pci: handle dma mapping errors
+    - LP: #540231
+  * gpiolib: Actually set output state in wm831x_gpio_direction_output()
+    - LP: #540231
+  * hwmon: (tmp421) Fix temperature conversions
+    - LP: #540231
+  * hwmon: (tmp421) Restore missing inputs
+    - LP: #540231
+  * pata_hpt3x2n: always stretch UltraDMA timing
+    - LP: #540231
+  * scm: Only support SCM_RIGHTS on unix domain sockets.
+    - LP: #540231
+  * ath9k: fix beacon timer restart after a card reset
+    - LP: #540231
+  * ath9k: fix rate control fallback rate selection
+    - LP: #540231
+  * ath9k: disable RIFS search for AR91xx based chips
+    - LP: #540231
+  * ath5k: use correct packet type when transmitting
+    - LP: #540231
+  * b43/b43legacy: Wake queues in wireless_core_start
+    - LP: #540231
+  * netfilter: xt_recent: fix buffer overflow
+    - LP: #540231
+  * netfilter: xt_recent: fix false match
+    - LP: #540231
+  * sunxvr500: Additional PCI id for sunxvr500 driver
+    - LP: #540231
+  * thinkpad-acpi: fix poll thread auto-start
+    - LP: #540231
+  * thinkpad-acpi: R52 brightness_mode has been confirmed
+    - LP: #540231
+  * thinkpad-acpi: document HKEY event 3006
+    - LP: #540231
+  * thinkpad-acpi: make driver events work in NVRAM poll mode
+    - LP: #540231
+  * thinkpad-acpi: fix bluetooth/wwan resume
+    - LP: #540231
+  * ocfs2: Only bug out in direct io write for reflinked extent.
+    - LP: #540231
+  * x86, ia32_aout: do not kill argument mapping
+    - LP: #540231
+  * x86: Add iMac9,1 to pci_reboot_dmi_table
+    - LP: #540231
+  * x86, xen: Disable highmem PTE allocation even when CONFIG_HIGHPTE=y
+    - LP: #540231
+  * x86: Avoid race condition in pci_enable_msix()
+    - LP: #540231
+  * x86: Fix SCI on IOAPIC != 0
+    - LP: #540231
+  * USB: xhci: Fix finding extended capabilities registers
+    - LP: #540231
+  * USB: fix the idProduct value for USB-3.0 root hubs
+    - LP: #540231
+  * USB: fix crash in uhci_scan_schedule
+    - LP: #540231
+  * USB: remove debugging message for uevent constructions
+    - LP: #540231
+  * USB: Move hcd free_dev call into usb_disconnect to fix oops
+    - LP: #540231
+  * USB: ftdi_sio: isolate all device IDs to new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: sort PID/VID entries in new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: new device id for papouch AD4USB
+    - LP: #540231
+  * USB: ftdi_sio: add device IDs (several ELV, one Mindstorms NXT)
+    - LP: #540231
+  * USB: add new ftdi_sio device ids
+    - LP: #540231
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #540231
+  * USB: cp210x: Add 81E8 (Zephyr Bioharness)
+    - LP: #540231
+  * USB: unusual_devs: Add support for multiple Option 3G sticks
+    - LP: #540231
+  * sunrpc: remove unnecessary svc_xprt_put
+    - LP: #540231
+  * SUNRPC: Handle EINVAL error returns from the TCP connect operation
+    - LP: #540231
+  * s3cmci: s3cmci_card_present: Use no_detect to decide whether there is a
+    card detect pin
+    - LP: #540231
+  * rtc-coh901331: fix braces in resume code
+    - LP: #540231
+  * NFS: Fix an allocation-under-spinlock bug
+    - LP: #540231
+  * dm: free dm_io before bio_endio not after
+    - LP: #540231
+  * KVM: x86 emulator: Add group8 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Forbid modifying CS segment register by mov
+    instruction
+    - LP: #540231
+  * KVM: x86 emulator: Add group9 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - LP: #540231
+  * sched: Fix sched_mv_power_savings for !SMT
+    - LP: #540231
+  * sched: Fix SMT scheduler regression in find_busiest_queue()
+    - LP: #540231
+  * sched: Don't use possibly stale sched_class
+    - LP: #540231
+  * x86, mm: Allow highmem user page tables to be disabled at boot time
+    - LP: #540231
+  * Linux 2.6.32.10
+    - LP: #540231
+  * drm/i915: give up on 8xx lid status
+    - LP: #540231
+  * drm/i915: Use a dmi quirk to skip a broken SDVO TV output.
+    - LP: #540231
+  * drm/ttm: handle OOM in ttm_tt_swapout
+    - LP: #540231
+  * drm/radeon/kms/atom: fix shr/shl ops
+    - LP: #540231
+  * Linux 2.6.32.10+drm33.1
+    - LP: #540231
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 31 Mar 2010 20:09:01 +0100
+
+linux-ec2 (2.6.32-303.7) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * sync with master abstraction cleanup
+  * rebase to Ubuntu-2.6.32-12.17
+  * [Config] fix MMAP_MIN_ADDR/DEV_KMEM/USB_DEVICEFS
+  * rebase to Ubuntu-2.6.32-15.22
+  * [Config] update configs following rebase to Ubuntu-2.6.32-15.22
+  * SAUCE: XEN -- drop references to TIF_ABI_PENDING
+  * [Config] updateconfigs following rebase to Ubuntu-2.6.32-15.22
+  * rename the debug packages to match archive standard
+    - LP: #527837
+  * [Config] cpu_debug module is no longer built
+  * updateconfigs following rebase to Ubuntu-2.6.32-16.24
+  * lintian -- update debhelper package version dependancy
+  * lintian -- fix ghostscript dependancy
+  * lintian -- add required misc:Depends
+  * update to standards version 3.8.4.0
+  * linux-tools -- disable linux-tools generation
+  * rebase to Ubuntu-2.6.32-16.25
+  * d-i -- do not generate any udebs
+  * disable linux-libc-dev for ec2
+
+  [ John Johansen ]
+
+  * rebase to Ubuntu-2.6.32-16.24
+
+  [ Upstream Kernel Changes ]
+
+  * Linux 2.6.32.4
+
+  [ Ubuntu: 2.6.32-16.25 ]
+
+  * linux-tools -- move to Suggests: with explicit seeding
+    - LP: #534635
+  * [Config] CONFIG_HID=m
+  * (pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()
+  * KVM: introduce kvm_vcpu_on_spin
+  * KVM: VMX: Add support for Pause-Loop Exiting
+
+  [ Ubuntu: 2.6.32-16.24 ]
+
+  * armel -- perf userspace does not support arm
+  * ia64 -- libelf-dev/binutils-dev to not provide necessary libraries
+
+  [ Ubuntu: 2.6.32-16.23 ]
+
+  * SAUCE: PM report driver and device suspend/resume times -- move config
+  * update to standards version 3.8.4.0
+  * printenv -- expose all of the package selectors
+  * source package -- cleanup source content control
+  * doc package -- ensure we do build package content on buildd
+  * lintian -- correct the address in the debian/copyright
+  * lintian -- update debhelper package version dependancy
+  * lintian -- fix ghostscript dependancy
+  * lintian -- add required misc:Depends
+  * lintian -- move our debhelper compat level to debian/compat
+  * perf -- build the kernel carried tools
+  * perf -- add linux-tools carrying the version switches and manuals
+  * SAUCE: fix up Kconfig for staging drivers
+  * [Config] enable NOUVEAU etc following drm backport
+  * update DRM to mainline v2.6.33
+  * [Config] Remove AppArmor config options that no longer exist (ports)
+  * [Config] updateportsconfigs following drm update
+  * ubuntu: AppArmor -- update to mainline 2010-03-04
+  * SAUCE: AppArmor: Reintroduce AppArmor 2.4 compatibility
+  * SAUCE: AppArmor: replace strim with strstrip for 2.6.32 kernels
+  * [Config] Remove AppArmor config options that no longer exist
+  * ubuntu: rtl8192se -- version 2010-0115,0014
+    - LP: #530275
+  * [Config] added CONFIG_RTL8192SE module.
+    - LP: #530275
+  * [Config] Added vmw_pvscsi to d-i/scsi-modules
+    - LP: #531017
+  * [Upstream] netfilter: xt_recent: Add an entry reaper
+  * Revert "KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Fix popf emulation"
+  * Revert "KVM: x86 emulator: Check IOPL level during io instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Add Virtual-8086 mode of emulation"
+  * Revert "KVM: fix memory access during x86 emulation."
+  * Add vlan (8021.Q) module package for d-i.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+  * [Upstream] docbook: need xmldoclinks for all doc types
+  * x86: set_personality_ia32() misses force_personality32
+  * lib: Introduce generic list_sort function
+  * drm/nv50: Implement ctxprog/state generation.
+  * drm/nv50: Remove redundant/incorrect ctxvals initialisation.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+
+  [ Ubuntu: 2.6.32-15.22 ]
+
+  * Revert "[Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT"
+  * Revert "SAUCE: PM report driver and device suspend/resume times."
+  * [Config] set CONFIG_SR_REPORT_TIME_LIMIT
+  * SAUCE: PM report driver and device suspend/resume times.
+
+  [ Ubuntu: 2.6.32-15.21 ]
+
+  * Revert "(pre-stable) drm/i915: Increase fb alignment to 64k"
+  * Revert "[Config] lenovo-sl-laptop -- enable"
+  * Revert "ubuntu: lenovo-sl-laptop -- git tip (b19a08f81f)"
+  * armel -- cramfs module will no longer be built
+  * d-i -- make all modules optional
+  * rename the debug packages to match archive standard
+    - LP: #527837
+  * lenovo-sl-laptop is no longer built
+  * Disable 4MB page tables for Atom, work around errata AAE44
+    - LP: #523112
+  * ubuntu: dm-raid4-5: Depend on XOR_BLOCKS
+  * ubuntu: fsam7400: Depend on CHECK_SIGNATURE
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+  * [Config] armel Update versatile initrd configs
+    - LP: #524893
+  * SAUCE: [um] Don't use nx_enabled under UML
+    - LP: #524849
+  * [Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT
+  * SAUCE: v3 - Add Dell Business Class Netbook LED driver
+  * SAUCE: PM report driver and device suspend/resume times.
+  * Revert "[Upstream] e1000e: enhance frame fragment detection"
+    - CVE-2009-4538
+  * Revert "[Upstream] e1000: enhance frame fragment detection"
+    - CVE-2009-4536
+  * [Config] Enabled CONFIG_LEDS_DELL_NETBOOKS=m
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix false match
+  * Revert "(pre-stable) eCryptfs: Add getattr function"
+  * Fix potential crash with sys_move_pages
+  * futex_lock_pi() key refcnt fix
+  * futex: Handle user space corruption gracefully
+  * futex: Handle futex value corruption gracefully
+  * Fix race in tty_fasync() properly
+  * hwmon: (w83781d) Request I/O ports individually for probing
+  * hwmon: (lm78) Request I/O ports individually for probing
+  * hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT
+  * ALSA: ctxfi - fix PTP address initialization
+  * drm/i915: disable hotplug detect before Ironlake CRT detect
+  * drm/i915: enable self-refresh on 965
+  * drm/i915: Disable SR when more than one pipe is enabled
+  * drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.
+  * drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list
+  * drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop
+  * drm/i915: Add MALATA PC-81005 to ACPI LID quirk list
+  * usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers.
+  * i2c-tiny-usb: Fix on big-endian systems
+  * drm/i915: handle FBC and self-refresh better
+  * drm/i915: Increase fb alignment to 64k
+  * drm/i915: Update write_domains on active list after flush.
+  * regulator: Fix display of null constraints for regulators
+  * ALSA: hda-intel: Avoid divide by zero crash
+  * CPUFREQ: Fix use after free of struct powernow_k8_data
+  * freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb
+  * cciss: Make cciss_seq_show handle holes in the h->drv[] array
+  * ioat: fix infinite timeout checking in ioat2_quiesce
+  * resource: add helpers for fetching rlimits
+  * fs/exec.c: restrict initial stack space expansion to rlimit
+  * cifs: fix length calculation for converted unicode readdir names
+  * NFS: Fix a reference leak in nfs_wb_cancel_page()
+  * NFS: Try to commit unstable writes in nfs_release_page()
+  * NFSv4: Don't allow posix locking against servers that don't support it
+  * NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
+  * NFS: Fix an Oops when truncating a file
+  * NFS: Fix a umount race
+  * NFS: Fix a bug in nfs_fscache_release_page()
+  * NFS: Fix the mapping of the NFSERR_SERVERFAULT error
+  * md: fix 'degraded' calculation when starting a reshape.
+  * V4L/DVB: dvb-core: fix initialization of feeds list in demux filter
+  * Export the symbol of getboottime and mmonotonic_to_bootbased
+  * kvmclock: count total_sleep_time when updating guest clock
+  * KVM: PIT: control word is write-only
+  * tpm_infineon: fix suspend/resume handler for pnp_driver
+  * amd64_edac: Do not falsely trigger kerneloops
+  * netfilter: nf_conntrack: fix memory corruption with multiple namespaces
+  * netfilter: nf_conntrack: per netns nf_conntrack_cachep
+  * netfilter: nf_conntrack: restrict runtime expect hashsize modifications
+  * netfilter: xtables: compat out of scope fix
+  * netfilter: nf_conntrack: fix hash resizing with namespaces
+  * drm/i915: remove full registers dump debug
+  * drm/i915: add i915_lp_ring_sync helper
+  * drm/i915: Don't wait interruptible for possible plane buffer flush
+  * dasd: remove strings from s390dbf
+  * crypto: padlock-sha - Add import/export support
+  * wmi: Free the allocated acpi objects through wmi_get_event_data
+  * dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value
+  * /dev/mem: introduce size_inside_page()
+  * devmem: check vmalloc address on kmem read/write
+  * devmem: fix kmem write bug on memory holes
+  * SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead
+    of value 0.
+  * sh: Couple kernel and user write page perm bits for CONFIG_X2TLB
+  * ALSA: hda - use WARN_ON_ONCE() for zero-division detection
+  * dst: call cond_resched() in dst_gc_task()
+  * ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support
+  * befs: fix leak
+  * rtc-fm3130: add missing braces
+  * Call flush_dcache_page after PIO data transfers in libata-sff.c
+  * ahci: add Acer G725 to broken suspend list
+  * pktgen: Fix freezing problem
+  * x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt
+  * x86/amd-iommu: Fix deassignment of a device from the pt_domain
+  * x86: Re-get cfg_new in case reuse/move irq_desc
+  * Staging: fix rtl8187se compilation errors with mac80211
+  * ALSA: usb-audio - Avoid Oops after disconnect
+  * serial: 8250: add serial transmitter fully empty test
+  * sysfs: sysfs_sd_setattr set iattrs unconditionally
+  * class: Free the class private data in class_release
+  * USB: usbfs: only copy the actual data received
+  * USB: usbfs: properly clean up the as structure on error paths
+  * rtl8187: Add new device ID
+  * ACPI: Add NULL pointer check in acpi_bus_start
+  * ACPI: fix High cpu temperature with 2.6.32
+  * drm/radeon/kms: use udelay for short delays
+  * NFS: Too many GETATTR and ACCESS calls after direct I/O
+  * eCryptfs: Add getattr function
+  * b43: Fix throughput regression
+  * ath9k: Fix sequence numbers for PAE frames
+  * mac80211: Fix probe request filtering in IBSS mode
+  * iwlwifi: Fix to set correct ht configuration
+  * dm stripe: avoid divide by zero with invalid stripe count
+  * dm log: userspace fix overhead_size calcuations
+  * Linux 2.6.32.9
+  * sfc: Fix SFE4002 initialisation
+  * sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
+  * sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances
+  * (pre-stable) HID: handle joysticks with large number of buttons
+    - LP: #492056
+  * (pre-stable) HID: extend mask for BUTTON usage page
+    - LP: #492056
+  * PM: Measure device suspend and resume times
+  * e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+  * KVM: fix memory access during x86 emulation.
+    - CVE-2010-0306
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Fix popf emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - CVE-2010-0306
+  * Input: wacom - ensure the device is initialized properly upon resume
+  * Input: wacom - add defines for packet lengths of various devices
+  * Input: wacom - add support for new LCD tablets
+    - LP: #516777
+
+  [ Ubuntu: 2.6.32-14.20 ]
+
+  * rebuild following the GCC update to match compiler for out of tree modules
+  * Revert "[Config] drbd -- enable"
+  * Revert "ubuntu: drbd -- version 8.3.1"
+  * SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU
+    - LP: #510937
+
+  [ Ubuntu: 2.6.32-14.19 ]
+
+  * ensure we build the source package contents when enabled
+    - LP: #522308
+  * [Config] enable CONFIG_X86_MCE_XEON75XX
+  * SAUCE: AppArmor -- add linux/kref.h for struct kref
+  * [Config] enable CONFIG_HID_ORTEK
+  * enable udeb generation for arm versatile flavour
+    - LP: #522515
+  * ubuntu: AppArmor -- update to mainline 2010-02-18
+    - LP: #439560, #496110, #507069
+  * SAUCE: HID: add support for Ortek WKB-2000
+    - LP: #405390
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #490487
+  * x86, mce: Xeon75xx specific interface to get corrected memory error
+    information
+  * x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll
+  * x86, mce: Make xeon75xx memory driver dependent on PCI
+  * drm/edid: Unify detailed block parsing between base and extension
+    blocks
+    - LP: #500999
+  * (pre-stable) eCryptfs: Add getattr function
+    - LP: #390833
+
+  [ Ubuntu: 2.6.32-13.18 ]
+
+  * Revert "enforcer -- make the enforcement configuration common"
+  * Revert "(pre-stable) Input: ALPS - add interleaved protocol support
+    (Dell E6x00 series)"
+  * Revert "(pre-stable) driver-core: fix devtmpfs crash on s390"
+  * Revert "(pre-stable) Driver-Core: devtmpfs - set root directory mode to
+    0755"
+  * Revert "SAUCE: Adds support for COMPAL JHL90 webcam"
+  * Revert "SAUCE: fix kernel oops in VirtualBox during paravirt patching"
+  * Revert "SAUCE: make fc transport removal of target configurable"
+  * enforcer -- make the enforcement configuration common
+  * getabis -- add preempt flavour to the list
+  * [Config] enforce DEVTMPFS options
+  * [Config] armel -- cleanup to-be builtin modules
+  * [Config] cleanup ports configs
+  * [Config] enable CRYPTO_GHASH_CLMUL_NI_INTEL
+    - LP: #485536
+  * add printdebian target to find branch target
+  * distclean -- do not remove debian.env
+  * [Config] generic-pae switch to M586TSC
+    - LP: #519448
+  * git-ubuntu-log -- commonise duplicated log handling
+  * git-ubuntu-log -- tighten up Bug: NNNN matching
+  * git-ubuntu-log -- sort the bug numbers
+  * (pre-stable) drm/i915: Increase fb alignment to 64k
+    - LP: #404064
+  * arm -- enable ubuntu/ directory
+  * SAUCE: crypto: ghash - Add PCLMULQDQ accelerated implementation
+  * SAUCE: crypto: ghash-intel - Fix building failure on x86_32
+  * [Config] cleanup preempt configuration
+  * [Config] versatile: Fix video output
+    - LP: #517594
+  * [Config] armel DEFAULT_MMAP_MIN_ADDR=32768
+  * [Config] Large update to armel/versatile
+  * [Config] versatile: Add RTC support
+  * [Config] armel: Enable NEON
+  * [Config] versatile: Builtin MMC support
+  * [Config] versatile Builtin SCSI controller
+  * [Config] armel Disable dma_cache_sync callers
+  * [Config] armel Disable asm/time.h users
+  * [Config] armel Disable out of range udelay()
+  * [Config] armel Disable flush_cache_range() users
+  * [Config] armel -- Enable ubuntu/ drivers
+  * SAUCE: drm/i915: Add display hotplug event on Ironlake
+  * SAUCE: drm/i915: Add ACPI OpRegion support for Ironlake
+  * Revert "[Upstream]: oprofile/x86: add Xeon 7500 series support"
+  * Revert "Revert "[Bluetooth] Eliminate checks for impossible conditions
+    in IRQ handler""
+  * clockevent: Don't remove broadcast device when cpu is dead
+  * clockevents: Add missing include to pacify sparse
+  * ACPI: don't cond_resched if irq is disabled
+  * be2net: Add support for next generation of BladeEngine device.
+  * be2net: Add the new PCI IDs to PCI_DEVICE_TABLE.
+  * mpt2sas: New device SAS2208 support is added
+  * ar9170: Add support for D-Link DWA 160 A2
+  * powerpc/fsl: Add PCI device ids for new QoirQ chips
+  * davinci: dm646x: Add support for 3.x silicon revision
+  * Input: ALPS - add interleaved protocol support (Dell E6x00 series)
+  * Driver-Core: devtmpfs - set root directory mode to 0755
+  * driver-core: fix devtmpfs crash on s390
+  * vfs: get_sb_single() - do not pass options twice
+  * ALSA: hda - Add PCI IDs for Nvidia G2xx-series
+  * V4L/DVB (13569): smsusb: add autodetection support for five additional
+    Hauppauge USB IDs
+  * USB: mos7840: add device IDs for B&B electronics devices
+  * USB: ftdi_sio: add USB device ID's for B&B Electronics line
+  * V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134
+    SubVendor ID: 0x1043 Device ID: 0x4847)
+  * iTCO_wdt: Add support for Intel Ibex Peak
+  * atl1c:use common_task instead of reset_task and link_chg_task
+  * atl1e:disable NETIF_F_TSO6 for hardware limit
+  * V4L/DVB (13680a): DocBook/media: copy images after building HTML
+  * V4L/DVB (13680b): DocBook/media: create links for included sources
+  * netfilter: xtables: fix conntrack match v1 ipt-save output
+  * partitions: read whole sector with EFI GPT header
+  * partitions: use sector size for EFI GPT
+  * ALSA: ice1724 - Patch for suspend/resume for ESI Juli@
+  * sched: Fix isolcpus boot option
+  * sched: Fix missing sched tunable recalculation on cpu add/remove
+  * nohz: Prevent clocksource wrapping during idle
+  * nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups
+  * timers, init: Limit the number of per cpu calibration bootup messages
+  * PCI: Always set prefetchable base/limit upper32 registers
+  * iscsi class: modify handling of replacement timeout
+  * NFS: Revert default r/wsize behavior
+  * HID: fixup quirk for NCR devices
+  * scsi_devinfo: update Hitachi entries (v2)
+  * scsi_dh: create sysfs file, dh_state for all SCSI disk devices
+  * scsi_transport_fc: remove invalid BUG_ON
+  * lpfc: fix hang on SGI ia64 platform
+  * libfc: fix typo in retry check on received PRLI
+  * libfc: fix ddp in fc_fcp for 0 xid
+  * fcoe: remove redundant checking of netdev->netdev_ops
+  * libfc: Fix wrong scsi return status under FC_DATA_UNDRUN
+  * libfc: lport: fix minor documentation errors
+  * libfc: don't WARN_ON in lport_timeout for RESET state
+  * fcoe: initialize return value in fcoe_destroy
+  * libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data
+  * libfc: fix memory corruption caused by double frees and bad error
+    handling
+  * libfc: fix free of fc_rport_priv with timer pending
+  * libfc: remote port gets stuck in restart state without really
+    restarting
+  * fcoe, libfc: fix an libfc issue with queue ramp down in libfc
+  * fcoe: Fix checking san mac address
+  * fcoe: Fix getting san mac for VLAN interface
+  * qlge: Remove explicit setting of PCI Dev CTL reg.
+  * qlge: Set PCIE max read request size.
+  * qlge: Don't fail open when port is not initialized.
+  * qlge: Add handler for DCBX firmware event.
+  * qlge: Bonding fix for mode 6.
+  * PCI: AER: fix aer inject result in kernel oops
+  * DMI: allow omitting ident strings in DMI tables
+  * Input: i8042 - remove identification strings from DMI tables
+  * Input: i8042 - add Gigabyte M1022M to the noloop list
+  * Input: i8042 - add Dritek quirk for Acer Aspire 5610.
+  * ALSA: hda - select IbexPeak handler for Calpella
+  * ALSA: hda - Fix quirk for Maxdata obook4-1
+  * ALSA: hda - Add missing Line-Out and PCM switches as slave
+  * iTCO_wdt.c - cleanup chipset documentation
+  * iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC
+  * iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs
+  * ahci: disable SNotification capability for ich8
+  * ata_piix: fix MWDMA handling on PIIX3
+  * md: fix small irregularity with start_ro module parameter
+  * V4L/DVB (13826): uvcvideo: Fix controls blacklisting
+  * cio: fix double free in case of probe failure
+  * cio: dont panic in non-fatal conditions
+  * netiucv: displayed TX bytes value much too high
+  * ipc ns: fix memory leak (idr)
+  * ALSA: hda - Fix HP T5735 automute
+  * hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog
+  * UBI: fix memory leak in update path
+  * UBI: initialise update marker
+  * ASoC: fix a memory-leak in wm8903
+  * mac80211: check that ieee80211_set_power_mgmt only handles STA
+    interfaces.
+  * cfg80211: fix channel setting for wext
+  * KVM: S390: fix potential array overrun in intercept handling
+  * KVM: only allow one gsi per fd
+  * KVM: Fix race between APIC TMR and IRR
+  * KVM: MMU: bail out pagewalk on kvm_read_guest error
+  * KVM: x86: Fix host_mapping_level()
+  * KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks
+  * KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init()
+  * KVM: fix lock imbalance in kvm_*_irq_source_id()
+  * KVM: only clear irq_source_id if irqchip is present
+  * IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc()
+  * x86: Reenable TSC sync check at boot, even with NONSTOP_TSC
+  * ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
+    - LP: #516325
+  * iwlwifi: Fix throughput stall issue in HT mode for 5000
+  * fnctl: f_modown should call write_lock_irqsave/restore
+  * x86, msr/cpuid: Pass the number of minors when unregistering MSR and
+    CPUID drivers.
+  * Linux 2.6.32.7
+  * scsi_lib: Fix bug in completion of bidi commands
+  * mptsas: Fix issue with chain pools allocation on katmai
+  * mm: add new 'read_cache_page_gfp()' helper function
+  * drm/i915: Selectively enable self-reclaim
+  * firewire: ohci: fix crashes with TSB43AB23 on 64bit systems
+  * S390: fix single stepped svcs with TRACE_IRQFLAGS=y
+  * x86: Set hotpluggable nodes in nodes_possible_map
+  * x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG)
+  * libata: retry FS IOs even if it has failed with AC_ERR_INVALID
+  * zcrypt: Do not remove coprocessor for error 8/72
+  * dasd: fix possible NULL pointer errors
+  * ACPI: Add a generic API for _OSC -v2
+  * ACPI: Add platform-wide _OSC support.
+  * ACPI: fix OSC regression that caused aer and pciehp not to load
+  * ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes
+  * UBI: fix volume creation input checking
+  * e1000/e1000e: don't use small hardware rx buffers
+  * drm/i915: Reload hangcheck timer too for Ironlake
+  * Fix a leak in affs_fill_super()
+  * Fix failure exits in bfs_fill_super()
+  * fix oops in fs/9p late mount failure
+  * fix leak in romfs_fill_super()
+  * Fix remount races with symlink handling in affs
+  * fix affs parse_options()
+  * Fix failure exit in ipathfs
+  * mm: fix migratetype bug which slowed swapping
+  * FDPIC: Respect PT_GNU_STACK exec protection markings when creating
+    NOMMU stack
+  * Split 'flush_old_exec' into two functions
+  * sparc: TIF_ABI_PENDING bit removal
+  * x86: get rid of the insane TIF_ABI_PENDING bit
+  * Input: winbond-cir - remove dmesg spam
+  * x86: Disable HPET MSI on ATI SB700/SB800
+  * iwlwifi: set default aggregation frame count limit to 31
+  * drm/i915: only enable hotplug for detected outputs
+  * firewire: core: add_descriptor size check
+  * SECURITY: selinux, fix update_rlimit_cpu parameter
+  * regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints
+  * x86: Add Dell OptiPlex 760 reboot quirk
+    - LP: #488319
+  * x86: Add quirk for Intel DG45FC board to avoid low memory corruption
+  * x86/amd-iommu: Fix possible integer overflow
+  * clocksource: fix compilation if no GENERIC_TIME
+  * tcp: update the netstamp_needed counter when cloning sockets
+  * sky2: Fix oops in sky2_xmit_frame() after TX timeout
+  * net: restore ip source validation
+  * af_packet: Don't use skb after dev_queue_xmit()
+  * ax25: netrom: rose: Fix timer oopses
+  * KVM: allow userspace to adjust kvmclock offset
+  * oprofile/x86: add Xeon 7500 series support
+  * oprofile/x86: fix crash when profiling more than 28 events
+  * libata: retry link resume if necessary
+  * mm: percpu-vmap fix RCU list walking
+  * mm: purge fragmented percpu vmap blocks
+  * block: fix bio_add_page for non trivial merge_bvec_fn case
+  * Fix 'flush_old_exec()/setup_new_exec()' split
+  * random: drop weird m_time/a_time manipulation
+  * random: Remove unused inode variable
+  * block: fix bugs in bio-integrity mempool usage
+  * usb: r8a66597-hdc disable interrupts fix
+  * connector: Delete buggy notification code.
+  * be2net: Bug fix to support newer generation of BE ASIC
+  * be2net: Fix memset() arg ordering.
+  * mm: flush dcache before writing into page to avoid alias
+  * mac80211: fix NULL pointer dereference when ftrace is enabled
+  * imxfb: correct location of callbacks in suspend and resume
+  * mx3fb: some debug and initialisation fixes
+  * starfire: clean up properly if firmware loading fails
+  * kernel/cred.c: use kmem_cache_free
+  * uartlite: fix crash when using as console
+  * pktcdvd: removing device does not remove its sysfs dir
+  * ath9k: fix eeprom INI values override for 2GHz-only cards
+  * ath9k: fix beacon slot/buffer leak
+  * powerpc: TIF_ABI_PENDING bit removal
+  * NET: fix oops at bootime in sysctl code
+  * Linux 2.6.32.8
+
+  [ Ubuntu: 2.6.32-12.17 ]
+
+  * restore linux-image prefix -- master
+  * enforce -- we require SELINUX enabled -- master
+  * enforce -- ensure APPARMOR is our default LSM -- master
+  * make doc package completely optional -- master
+  * make source package completely optional -- master
+  * make linux-libc-dev completly optional -- master
+  * convert package disable to a deps list -- master
+  * allow common headers to switch from indep to arch -- master
+  * convert binary package disable to a deps list -- master
+  * add configuration option for a full source build tree -- master
+  * add support for uImage kernels in package control scripts
+  * getabis -- cleanup and parameterise repository list -- master
+  * getabis -- move configuration to etc/getabi -- master
+  * kernelconfig -- move configuration to etc -- master
+  * rules -- make debian/debian.env master for branch name
+  * set the current branch name -- master
+  * pull back common debian.master files into debian -- master
+  * enforcer -- make the enforcement configuration common
+  * insert-changes -- correctly link to debian/rules in DROOT
+  * future-proof ddeb handling against buildd changes
+  * SAUCE: Make CONFIG_{OMNIBOOK, AVERATEC_5100P, PACKARDBELL_E5} depend on
+    X86
+  * Add modules.builtin.bin to prerm rm list
+    - LP: #516584
+  * [Config] Implement the amd64 preempt flavour
+  * syslog: distinguish between /proc/kmsg and syscalls
+    - LP: #515623
+  * sfc: Fix polling for slow MCDI operations
+  * sfc: Fix conditions for MDIO self-test
+  * sfc: QT202x: Remove unreliable MMD check at initialisation
+  * sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer
+  * sfc: Use fixed-size buffers for MCDI NVRAM requests
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 09 Mar 2010 16:09:44 +0000
+
+linux-ec2 (2.6.32-302.6) lucid; urgency=low
+
+  [ John Johansen ]
+
+  * rebase to Ubuntu-2.6.32-11.15
+  * import raw xen patchset
+  * import series file for the xen patchset
+  * rebase to Ubuntu-2.6.32-12.16
+  * [Config] update ec2 configs to make them closer to -server flavor
+    - LP: #510130
+
+  [ Ubuntu: 2.6.32-12.16 ]
+
+  * Revert "SAUCE: acpi battery -- delay first lookup of the battery until
+    first use"
+  * SAUCE: acpi battery -- move first lookup asynchronous
+    - LP: #507211
+  * [Config] update configs to cleanup generic configs
+  * [Config] disable CONFIG_X86_CPU_DEBUG for amd64
+  * [Config] enable USER_NS
+    - LP: #480739, #509808
+  * (pre-stable) driver-core: fix devtmpfs crash on s390
+    - LP: #512370
+  * [Config] for server and virtual flavours make CONFIG_SCSI_SYM53C8XX_2=y
+    - LP: #494565
+  * [Config] VIRTIO=y for server/virtual flavours
+    - LP: #494565
+  * (pre-stable) Driver-Core: devtmpfs - set root directory mode to 0755
+    - LP: #512370
+  * SAUCE: x86: brk away from exec rand area
+    - LP: #452175
+  * [Upstream] e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * [Upstream] e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+  * (pre-stable) Input: ALPS - add interleaved protocol support (Dell E6x00
+    series)
+    - LP: #296610
+  * inotify: do not reuse watch descriptors
+    - LP: #485556
+  * inotify: only warn once for inotify problems
+  * revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC
+    Framebuffer"
+  * memcg: ensure list is empty at rmdir
+  * drm/i915: remove loop in Ironlake interrupt handler
+  * block: Fix incorrect reporting of partition alignment
+  * x86, mce: Thermal monitoring depends on APIC being enabled
+  * futexes: Remove rw parameter from get_futex_key()
+  * page allocator: update NR_FREE_PAGES only when necessary
+  * x86, apic: use physical mode for IBM summit platforms
+  * edac: i5000_edac critical fix panic out of bounds
+  * x86: SGI UV: Fix mapping of MMIO registers
+  * mfd: WM835x GPIO direction register is not locked
+  * mfd: Correct WM835x ISINK ramp time defines
+  * ALSA: hda - Fix missing capture mixer for ALC861/660 codecs
+  * V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned.
+  * reiserfs: truncate blocks not used by a write
+  * HID: add device IDs for new model of Apple Wireless Keyboard
+  * PCI/cardbus: Add a fixup hook and fix powerpc
+  * Input: pmouse - move Sentelic probe down the list
+  * asus-laptop: add Lenovo SL hotkey support
+  * sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
+  * sparc64: Fix NMI programming when perf events are active.
+  * sparc64: Fix Niagara2 perf event handling.
+  * i2c: Do not use device name after device_unregister
+  * i2c/pca: Don't use *_interruptible
+  * serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device
+  * sched: Fix task priority bug
+  * vfs: Fix vmtruncate() regression
+  * Linux 2.6.32.5
+  * x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers
+  * V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges.
+  * Staging: asus_oled: fix oops in 2.6.32.2
+  * Staging: hv: fix smp problems in the hyperv core code
+  * tty: fix race in tty_fasync
+  * ecryptfs: use after free
+  * ecryptfs: initialize private persistent file before dereferencing
+    pointer
+  * nozomi: quick fix for the close/close bug
+  * serial: 8250_pnp: use wildcard for serial Wacom tablets
+  * usb: serial: fix memory leak in generic driver
+  * USB: fix bitmask merge error
+  * USB: Don't use GFP_KERNEL while we cannot reset a storage device
+  * USB: EHCI: fix handling of unusual interrupt intervals
+  * USB: EHCI & UHCI: fix race between root-hub suspend and port resume
+  * USB: add missing delay during remote wakeup
+  * USB: add speed values for USB 3.0 and wireless controllers
+  * ACPI: EC: Accelerate query execution
+  * ACPI: EC: Add wait for irq storm
+  * SCSI: enclosure: fix oops while iterating enclosure_status array
+  * drm/i915: Read the response after issuing DDC bus switch command
+  * drm/i915: try another possible DDC bus for the SDVO device with
+    multiple outputs
+  * block: bdev_stack_limits wrapper
+  * DM: Fix device mapper topology stacking
+  * x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled
+  * USB: fix usbstorage for 2770:915d delivers no FAT
+  * vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE
+  * perf timechart: Use tid not pid for COMM change
+  * perf events: Dont report side-band events on each cpu for
+    per-task-per-cpu events
+  * perf: Honour event state for aux stream data
+  * Linux 2.6.32.6
+
+  [ Ubuntu: 2.6.32-11.15 ]
+
+  * Revert "(pre-stable) drm/radeon/kms: fix crtc vblank update for r600"
+  * Revert "(pre-stable) sched: Fix balance vs hotplug race"
+  * Revert "[Upstream] acerhdf: Limit modalias matching to supported
+    boards"
+  * Revert "[Upstream] mmc: prevent dangling block device from accessing
+    stale queues"
+  * Revert "SAUCE: Fix nx_enable reporting"
+  * Revert "SAUCE: [x86] fix report of cs-limit nx-emulation"
+  * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32"
+  * SAUCE: i915 -- disable powersave by default
+    - LP: #492392
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+  * [Upstream] b43: Declare all possible firmware files.
+    - LP: #488636
+  * [Config] updateconfigs after adding pvscsi
+    - LP: #497156
+  * [Config] CONFIG_BT=m
+  * Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu
+    for pre-Pentium"
+  * SCSI: ipr: fix EEH recovery
+  * SCSI: qla2xxx: dpc thread can execute before scsi host has been added
+  * SCSI: st: fix mdata->page_order handling
+  * SCSI: fc class: fix fc_transport_init error handling
+  * sched: Fix task_hot() test order
+  * x86, cpuid: Add "volatile" to asm in native_cpuid()
+  * sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE
+  * clockevents: Prevent clockevent_devices list corruption on cpu hotplug
+  * pata_hpt3x2n: fix clock turnaround
+  * pata_cmd64x: fix overclocking of UDMA0-2 modes
+  * ASoC: wm8974: fix a wrong bit definition
+  * sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer
+  * ALSA: hda - Fix missing capsrc_nids for ALC88x
+  * acerhdf: limit modalias matching to supported
+    - LP: #435958
+  * ACPI: EC: Fix MSI DMI detection
+  * ACPI: Use the return result of ACPI lid notifier chain correctly
+  * powerpc: Handle VSX alignment faults correctly in little-endian mode
+  * ASoC: Do not write to invalid registers on the wm9712.
+  * drm/radeon: fix build on 64-bit with some compilers.
+  * USB: emi62: fix crash when trying to load EMI 6|2 firmware
+  * USB: option: support hi speed for modem Haier CE100
+  * USB: Fix a bug on appledisplay.c regarding signedness
+  * USB: musb: gadget_ep0: avoid SetupEnd interrupt
+  * Bluetooth: Prevent ill-timed autosuspend in USB driver
+  * USB: rename usb_configure_device
+  * USB: fix bugs in usb_(de)authorize_device
+  * drivers/net/usb: Correct code taking the size of a pointer
+  * x86: SGI UV: Fix writes to led registers on remote uv hubs
+  * md: Fix unfortunate interaction with evms
+  * dma: at_hdmac: correct incompatible type for argument 1 of
+    'spin_lock_bh'
+  * dma-debug: Do not add notifier when dma debugging is disabled.
+  * dma-debug: Fix bug causing build warning
+  * cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS
+    referrals
+  * x86/amd-iommu: Fix initialization failure panic
+  * ioat3: fix p-disabled q-continuation
+  * ioat2,3: put channel hardware in known state at init
+  * KVM: MMU: remove prefault from invlpg handler
+  * KVM: LAPIC: make sure IRR bitmap is scanned after vm load
+  * Libertas: fix buffer overflow in lbs_get_essid()
+  * iwmc3200wifi: fix array out-of-boundary access
+  * mac80211: fix propagation of failed hardware reconfigurations
+  * mac80211: fix WMM AP settings application
+  * mac80211: Fix IBSS merge
+  * cfg80211: fix race between deauth and assoc response
+  * ath5k: fix SWI calibration interrupt storm
+  * ath9k: wake hardware for interface IBSS/AP/Mesh removal
+  * ath9k: Fix TX queue draining
+  * ath9k: fix missed error codes in the tx status check
+  * ath9k: wake hardware during AMPDU TX actions
+  * ath9k: fix suspend by waking device prior to stop
+  * ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on
+    64-bit
+  * ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value
+    in 0x4054
+  * iwl3945: disable power save
+  * iwl3945: fix panic in iwl3945 driver
+  * iwlwifi: fix EEPROM/OTP reading endian annotations and a bug
+  * iwlwifi: fix more eeprom endian bugs
+  * iwlwifi: fix 40MHz operation setting on cards that do not allow it
+  * mac80211: fix race with suspend and dynamic_ps_disable_work
+  * NOMMU: Optimise away the {dac_,}mmap_min_addr tests
+  * 'sysctl_max_map_count' should be non-negative
+  * kernel/sysctl.c: fix the incomplete part of
+    sysctl_max_map_count-should-be-non-negative.patch
+  * V4L/DVB (13596): ov511.c typo: lock => unlock
+  * x86/ptrace: make genregs[32]_get/set more robust
+  * memcg: avoid oom-killing innocent task in case of use_hierarchy
+  * e100: Fix broken cbs accounting due to missing memset.
+  * ipv6: reassembly: use seperate reassembly queues for conntrack and
+    local delivery
+  * netfilter: fix crashes in bridge netfilter caused by fragment jumps
+  * hwmon: (sht15) Off-by-one error in array index + incorrect constants
+  * b43: avoid PPC fault during resume
+  * Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture
+    support
+  * sched: Fix balance vs hotplug race
+  * drm/radeon/kms: fix crtc vblank update for r600
+  * drm: disable all the possible outputs/crtcs before entering KMS mode
+  * S390: dasd: support DIAG access for read-only devices
+  * xen: fix is_disconnected_device/exists_disconnected_device
+  * xen: improvement to wait_for_devices()
+  * xen: wait up to 5 minutes for device connetion
+  * orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled
+  * udf: Try harder when looking for VAT inode
+  * Add unlocked version of inode_add_bytes() function
+  * quota: decouple fs reserved space from quota reservation
+  * ext4: Convert to generic reserved quota's space management.
+  * ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
+  * x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus
+  * cpumask: use modern cpumask style in drivers/edac/amd64_edac.c
+  * amd64_edac: unify MCGCTL ECC switching
+  * x86, msr: Add support for non-contiguous cpumasks
+  * x86, msr: msrs_alloc/free for CONFIG_SMP=n
+  * amd64_edac: fix driver instance freeing
+  * amd64_edac: make driver loading more robust
+  * amd64_edac: fix forcing module load/unload
+  * sched: Sched_rt_periodic_timer vs cpu hotplug
+  * ext4: Update documentation to correct the inode_readahead_blks option
+    name
+  * lguest: fix bug in setting guest GDT entry
+  * vmscan: do not evict inactive pages when skipping an active list scan
+  * ksm: fix mlockfreed to munlocked
+  * rt2x00: Disable powersaving for rt61pci and rt2800pci.
+  * generic_permission: MAY_OPEN is not write access
+  * Linux 2.6.32.3
+  * untangle the do_mremap() mess
+  * fasync: split 'fasync_helper()' into separate add/remove functions
+  * ASoC: fix params_rate() macro use in several codecs
+  * modules: Skip empty sections when exporting section notes
+  * exofs: simple_write_end does not mark_inode_dirty
+  * nfsd: make sure data is on disk before calling ->fsync
+  * sunrpc: fix peername failed on closed listener
+  * SUNRPC: Fix up an error return value in
+    gss_import_sec_context_kerberos()
+  * SUNRPC: Fix the return value in gss_import_sec_context()
+  * sunrpc: on successful gss error pipe write, don't return error
+  * drm/i915: Update LVDS connector status when receiving ACPI LID event
+  * drm/i915: fix order of fence release wrt flushing
+  * drm/i915: Permit pinning whilst the device is 'suspended'
+  * drm: remove address mask param for drm_pci_alloc()
+  * drm/i915: Enable/disable the dithering for LVDS based on VBT setting
+  * drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in
+    pipeconf on Ironlake
+  * drm/i915: Select the correct BPC for LVDS on Ironlake
+  * drm/i915: fix unused var
+  * rtc_cmos: convert shutdown to new pnp_driver->shutdown
+  * drivers/cpuidle/governors/menu.c: fix undefined reference to
+    `__udivdi3'
+  * cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput()
+  * lib/rational.c needs module.h
+  * dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with
+    DMA_FROM_DEVICE and
+  * kernel/signal.c: fix kernel information leak with print-fatal-signals=1
+  * mmc_block: add dev_t initialization check
+  * mmc_block: fix probe error cleanup bug
+  * mmc_block: fix queue cleanup
+  * ALSA: hda - Fix ALC861-VD capture source mixer
+  * ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense
+    blacklist
+  * ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2
+    - LP: #498863
+  * ASoC: Fix WM8350 DSP mode B configuration
+  * netfilter: ebtables: enforce CAP_NET_ADMIN
+  * netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq()
+  * hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs
+  * hwmon: (adt7462) Fix pin 28 monitoring
+  * quota: Fix dquot_transfer for filesystems different from ext4
+  * xen: fix hang on suspend.
+  * iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr
+  * ath5k: Fix eeprom checksum check for custom sized eeproms
+  * cfg80211: fix syntax error on user regulatory hints
+  * iwl: off by one bug
+  * mac80211: add missing sanity checks for action frames
+  * drm/i915: remove render reclock support
+  * libertas: Remove carrier signaling from the scan code
+  * kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr
+  * mac80211: fix skb buffering issue (and fixes to that)
+  * fix braindamage in audit_tree.c untag_chunk()
+  * fix more leaks in audit_tree.c tag_chunk()
+  * module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y
+  * ipv6: skb_dst() can be NULL in ipv6_hop_jumbo().
+  * agp/intel-agp: Clear entire GTT on startup
+  * Linux 2.6.32.4
+  * ethtool: Add reset operation
+  * gro: Name the GRO result enumeration type
+  * gro: Change all receive functions to return GRO result codes
+  * sfc: 10Xpress: Initialise pause advertising flags
+  * sfc: 10Xpress: Report support for pause frames
+  * sfc: Remove redundant header gmii.h
+  * sfc: Remove redundant hardware initialisation
+  * sfc: Rename Falcon-specific board code and types
+  * sfc: Remove boards.h, moving last remaining declaration to falcon.h
+  * sfc: Remove versioned bitfield macros
+  * sfc: Move RX data FIFO thresholds out of struct efx_nic_type
+  * sfc: Update hardware definitions for Siena
+  * sfc: Rename register I/O header and functions used by both Falcon and
+    Siena
+  * sfc: Eliminate indirect lookups of queue size constants
+  * sfc: Define DMA address mask explicitly in terms of descriptor field
+    width
+  * sfc: Move all TX DMA length limiting into tx.c
+  * sfc: Change order of device removal to reverse of probe order
+  * sfc: Remove declarations of nonexistent functions
+  * sfc: Move efx_xmit_done() declaration into correct stanza
+  * sfc: Move shared members of struct falcon_nic_data into struct efx_nic
+  * sfc: Maintain interrupt moderation values in ticks, not microseconds
+  * sfc: Removed kernel-doc for nonexistent member of efx_phy_operations
+  * sfc: Remove pointless abstraction of memory BAR number
+  * sfc: Remove incorrect assertion from efx_pci_remove_main()
+  * sfc: Remove unnecessary tests of efx->membase
+  * sfc: Move MTD probe after netdev registration and name allocation
+  * sfc: Remove unused code for non-autoneg speed/duplex switching
+  * sfc: Rename 'xfp' file and functions to reflect reality
+  * sfc: Really allow RX checksum offload to be disabled
+  * sfc: Feed GRO result into RX allocation policy and interrupt moderation
+  * sfc: Enable heuristic selection between page and skb RX buffers
+  * sfc: Remove pointless abstraction of memory BAR number (2)
+  * sfc: Remove redundant gotos from __efx_rx_packet()
+  * sfc: Remove ridiculously paranoid assertions
+  * sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro()
+  * sfc: Record RX queue number on GRO path
+  * sfc: SFT9001: Reset LED configuration correctly after blinking
+  * sfc: Use a single blink implementation
+  * sfc: Rename efx_board::init_leds to init_phy and use for SFN4111T
+  * sfc: Make board information explicitly Falcon-specific
+  * sfc: Move definition of struct falcon_nic_data into falcon.h
+  * sfc: Move struct falcon_board into struct falcon_nic_data
+  * sfc: Move all I2C stuff into struct falcon_board
+  * sfc: Gather link state fields in struct efx_nic into new struct
+    efx_link_state
+  * sfc: Remove unnecessary casts to struct sk_buff *
+  * sfc: Remove redundant efx_xmit() function
+  * sfc: Combine high-level header files
+  * sfc: Log interrupt and reset type names, not numbers
+  * sfc: Fix descriptor cache sizes
+  * sfc: Treat all MAC registers as 128-bit
+  * sfc: Strengthen EFX_ASSERT_RESET_SERIALISED
+  * sfc: Comment corrections
+  * sfc: Remove unused constant
+  * sfc: Clean up struct falcon_board and struct falcon_board_data
+  * sfc: Fix bugs in RX queue flushing
+  * sfc: Remove unused function efx_flush_queues()
+  * sfc: Only switch Falcon MAC clocks as necessary
+  * sfc: Hold MAC lock for longer in efx_init_port()
+  * sfc: Split MAC stats DMA initiation and completion
+  * sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c
+  * sfc: Simplify XMAC link polling
+  * sfc: Change MAC promiscuity and multicast hash at the same time
+  * sfc: Move inline comment into kernel-doc
+  * sfc: Do not set net_device::trans_start in self-test
+  * sfc: Simplify PHY polling
+  * sfc: QT202x: Reset before reading PHY id
+  * sfc: Replace MDIO spinlock with mutex
+  * sfc: Always start Falcon using the XMAC
+  * sfc: Limit some hardware workarounds to Falcon
+  * sfc: Remove EFX_WORKAROUND_9141 macro
+  * sfc: Remove another unused workaround macro
+  * sfc: Remove some redundant whitespace
+  * sfc: Decouple NIC revision number from Falcon PCI revision number
+  * sfc: Move descriptor cache base addresses to struct efx_nic_type
+  * sfc: Clean up RX event handling
+  * sfc: Remove redundant writes to INT_ADR_KER
+  * sfc: Remove duplicate hardware structure definitions
+  * sfc: Turn pause frame generation on and off at the MAC, not the RX FIFO
+  * sfc: Move Falcon NIC operations to efx_nic_type
+  * sfc: Refactor link configuration
+  * sfc: Generalise link state monitoring
+  * sfc: Add power-management and wake-on-LAN support
+  * sfc: Implement ethtool reset operation
+  * sfc: Add efx_nic_type operation for register self-test
+  * sfc: Add efx_nic_type operation for NVRAM self-test
+  * sfc: Add efx_nic_type operation for identity LED control
+  * sfc: Separate shared NIC code from Falcon-specific and rename
+    accordingly
+  * sfc: Fold falcon_probe_nic_variant() into falcon_probe_nic()
+  * sfc: Extend loopback mode enumeration
+  * sfc: Remove static PHY data and enumerations
+  * sfc: Extend MTD driver for use with new NICs
+  * sfc: Allow for additional checksum offload features
+  * sfc: Rename falcon.h to nic.h
+  * sfc: Move shared NIC code from falcon.c to new source file nic.c
+  * sfc: Add firmware protocol definitions (MCDI)
+  * sfc: Add support for SFC9000 family (1)
+  * sfc: Add support for SFC9000 family (2)
+  * sfc: Implement TSO for TCP/IPv6
+  * sfc: Update version, copyright dates, authors
+  * drivers/net/sfc: Correct code taking the size of a pointer
+  * sfc: Move PHY software state initialisation from init() into probe()
+  * sfc: Include XGXS in XMAC link status check except in XGMII loopback
+  * sfc: Fix DMA mapping cleanup in case of an error in TSO
+  * sfc: QT2025C: Work around PHY bug
+  * sfc: QT2025C: Switch into self-configure mode when not in loopback
+  * sfc: QT2025C: Work around PHY firmware initialisation bug
+  * sfc: QT2025C: Add error message for suspected bad SFP+ cables
+  * sfc: Disable TX descriptor prefetch watchdog
+  * [SCSI] vmw_pvscsi: SCSI driver for VMware's virtual HBA.
+    - LP: #497156
+
+  [ Ubuntu: 2.6.32-10.14 ]
+
+  * SAUCE: drm/radeon/kms: fix LVDS setup on r4xx
+    - LP: #493795
+  * Revert "(pre-stable) acpi: Use the ARB_DISABLE for the CPU which model
+    id is less than 0x0f."
+  * config-check -- ensure the checks get run at build time
+  * config-check -- check the processed config during updateconfigs
+  * config-check -- CONFIG_SECCOMP may not be present
+  * TUN is now built in ignore
+  * SAUCE: acpi battery -- delay first lookup of the battery until first
+    use
+  * SAUCE: async_populate_rootfs: move rootfs init earlier
+  * ubuntu: AppArmor -- update to mainline 2010-01-06
+  * SAUCE: move RLIMIT_CORE pipe dumper marker to 1
+    - LP: #498525
+  * (pre-stable) drm/radeon/kms: fix crtc vblank update for r600
+  * Add asix to nic-usb-modules file
+    - LP: #499785
+  * (pre-stable) sched: Fix balance vs hotplug race
+  * [Config] Enable CONFIG_FUNCTION_TRACER
+    - LP: #497989
+  * [Config] Drop lpia from getabis
+  * [Config] Build in TUN/TAP driver
+    - LP: #499491
+  * [Config] DH_COMPAT=5
+  * Revert "(pre-stable) drm/i915: Avoid NULL dereference with
+    component_only tv_modes"
+  * Revert "(pre-stable) drm/i915: Fix sync to vblank when VGA output is
+    turned off"
+  * USB: usb-storage: fix bug in fill_inquiry
+  * USB: option: add pid for ZTE
+  * firewire: ohci: handle receive packets with a data length of zero
+  * rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling
+    of ->completed counter
+  * rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed
+    counter
+  * rcu: Fix note_new_gpnum() uses of ->gpnum
+  * rcu: Remove inline from forward-referenced functions
+  * perf_event: Fix invalid type in ioctl definition
+  * perf_event: Initialize data.period in perf_swevent_hrtimer()
+  * perf: Don't free perf_mmap_data until work has been done
+  * PM / Runtime: Fix lockdep warning in __pm_runtime_set_status()
+  * sched: Check for an idle shared cache in select_task_rq_fair()
+  * sched: Fix affinity logic in select_task_rq_fair()
+  * sched: Rate-limit newidle
+  * sched: Fix and clean up rate-limit newidle code
+  * x86/amd-iommu: attach devices to pre-allocated domains early
+  * x86/amd-iommu: un__init iommu_setup_msi
+  * x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking
+    up the PCI tree
+  * x86: Fix iommu=nodac parameter handling
+  * x86: GART: pci-gart_64.c: Use correct length in strncmp
+  * x86: ASUS P4S800 reboot=bios quirk
+    - LP: #366682
+  * x86, apic: Enable lapic nmi watchdog on AMD Family 11h
+  * ssb: Fix range check in sprom write
+  * ath5k: allow setting txpower to 0
+  * ath5k: enable EEPROM checksum check
+  * hrtimer: Fix /proc/timer_list regression
+  * ALSA: hrtimer - Fix lock-up
+  * ALSA: hda - Terradici HDA controllers does not support 64-bit mode
+  * KVM: x86 emulator: limit instructions to 15 bytes
+  * KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c
+  * KVM: s390: Make psw available on all exits, not just a subset
+  * KVM: fix irq_source_id size verification
+  * KVM: x86: include pvclock MSRs in msrs_to_save
+  * x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage
+  * x86: Use -maccumulate-outgoing-args for sane mcount prologues
+  * x86, mce: don't restart timer if disabled
+  * x86/mce: Set up timer unconditionally
+  * x86: SGI UV: Fix BAU initialization
+  * x86: Fix duplicated UV BAU interrupt vector
+  * x86: Add new Intel CPU cache size descriptors
+  * x86: Fix typo in Intel CPU cache size descriptor
+  * pata_hpt{37x|3x2n}: fix timing register masks (take 2)
+  * s390: clear high-order bits of registers after sam64
+  * V4L/DVB: Fix test in copy_reg_bits()
+  * bsdacct: fix uid/gid misreporting
+  * UBI: flush wl before clearing update marker
+  * jbd2: don't wipe the journal on a failed journal checksum
+  * USB: xhci: Add correct email and files to MAINTAINERS entry.
+  * USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again
+  * USB: option.c: add support for D-Link DWM-162-U5
+  * USB: usbtmc: repeat usb_bulk_msg until whole message is transfered
+  * USB: usb-storage: add BAD_SENSE flag
+  * USB: Close usb_find_interface race v3
+  * pxa/em-x270: fix usb hub power up/reset sequence
+  * hfs: fix a potential buffer overflow
+  * SUNRPC: IS_ERR/PTR_ERR confusion
+  * NFS: Fix nfs_migrate_page()
+  * md/bitmap: protect against bitmap removal while being updated.
+  * futex: Take mmap_sem for get_user_pages in fault_in_user_writeable
+  * devpts_get_tty() should validate inode
+  * debugfs: fix create mutex racy fops and private data
+  * Driver core: fix race in dev_driver_string
+  * Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN
+  * mac80211: Fix bug in computing crc over dynamic IEs in beacon
+  * mac80211: Fixed bug in mesh portal paths
+  * mac80211: Revert 'Use correct sign for mesh active path refresh'
+  * mac80211: fix scan abort sanity checks
+  * wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC
+  * rtl8187: Fix wrong rfkill switch mask for some models
+  * x86: Fix bogus warning in apic_noop.apic_write()
+  * mm: hugetlb: fix hugepage memory leak in mincore()
+  * mm: hugetlb: fix hugepage memory leak in walk_page_range()
+  * powerpc/windfarm: Add detection for second cpu pump
+  * powerpc/therm_adt746x: Record pwm invert bit at module load time]
+  * powerpc: Fix usage of 64-bit instruction in 32-bit altivec code
+  * drm/radeon/kms: Add quirk for HIS X1300 board
+  * drm/radeon/kms: handle vblanks properly with dpms on
+  * drm/radeon/kms: fix legacy crtc2 dpms
+  * drm/radeon/kms: fix vram setup on rs600
+  * drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size
+  * drm/ttm: Fix build failure due to missing struct page
+  * drm/i915: Set the error code after failing to insert new offset into mm
+    ht.
+  * drm/i915: Add the missing clonemask for display port on Ironlake
+  * xen/xenbus: make DEVICE_ATTR()s static
+  * xen: re-register runstate area earlier on resume.
+  * xen: restore runstate_info even if !have_vcpu_info_placement
+  * xen: correctly restore pfn_to_mfn_list_list after resume
+  * xen: register timer interrupt with IRQF_TIMER
+  * xen: register runstate on secondary CPUs
+  * xen: don't call dpm_resume_noirq() with interrupts disabled.
+  * xen: register runstate info for boot CPU early
+  * xen: call clock resume notifier on all CPUs
+  * xen: improve error handling in do_suspend.
+  * xen: don't leak IRQs over suspend/resume.
+  * xen: use iret for return from 64b kernel to 32b usermode
+  * xen: explicitly create/destroy stop_machine workqueues outside
+    suspend/resume region.
+  * Xen balloon: fix totalram_pages counting.
+  * xen: try harder to balloon up under memory pressure.
+  * dm exception store: free tmp_store on persistent flag error
+  * dm snapshot: only take lock for statustype info not table
+  * dm crypt: move private iv fields to structs
+  * dm crypt: restructure essiv error path
+  * dm: avoid _hash_lock deadlock
+  * dm snapshot: cope with chunk size larger than origin
+  * dm crypt: separate essiv allocation from initialisation
+  * dm crypt: make wipe message also wipe essiv key
+  * slc90e66: fix UDMA handling
+  * tcp: Stalling connections: Fix timeout calculation routine
+  * ip_fragment: also adjust skb->truesize for packets not owned by a
+    socket
+  * b44 WOL setup: one-bit-off stack corruption kernel panic fix
+  * sparc64: Don't specify IRQF_SHARED for LDC interrupts.
+  * sparc64: Fix overly strict range type matching for PCI devices.
+  * sparc64: Fix stack debugging IRQ stack regression.
+  * sparc: Set UTS_MACHINE correctly.
+  * b43legacy: avoid PPC fault during resume
+  * tracing: Fix event format export
+  * ath9k: Fix TX hang poll routine
+  * ath9k: fix processing of TX PS null data frames
+  * ath9k: Fix maximum tx fifo settings for single stream devices
+  * ath9k: fix tx status reporting
+  * mac80211: Fix dynamic power save for scanning.
+  * drm/i915: Fix sync to vblank when VGA output is turned off
+  * memcg: fix memory.memsw.usage_in_bytes for root cgroup
+  * thinkpad-acpi: fix default brightness_mode for R50e/R51
+  * thinkpad-acpi: preserve rfkill state across suspend/resume
+  * ipw2100: fix rebooting hang with driver loaded
+  * matroxfb: fix problems with display stability
+  * acerhdf: add new BIOS versions
+  * asus-laptop: change light sens default values.
+  * vmalloc: conditionalize build of pcpu_get_vm_areas()
+  * ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f.
+  * net: Fix userspace RTM_NEWLINK notifications.
+  * ext3: Fix data / filesystem corruption when write fails to copy data
+  * V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added.
+  * bcm63xx_enet: fix compilation failure after get_stats_count removal
+  * x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value
+  * drm/i915: Avoid NULL dereference with component_only tv_modes
+  * drm/i915: PineView only has LVDS and CRT ports
+  * drm/i915: Fix LVDS stability issue on Ironlake
+  * mm: sigbus instead of abusing oom
+  * ipvs: zero usvc and udest
+  * jffs2: Fix long-standing bug with symlink garbage collection.
+  * intel-iommu: Detect DMAR in hyperspace at probe time.
+  * intel-iommu: Apply BIOS sanity checks for interrupt remapping too.
+  * intel-iommu: Check for an RMRR which ends before it starts.
+  * intel-iommu: Fix oops with intel_iommu=igfx_off
+  * intel-iommu: ignore page table validation in pass through mode
+  * netfilter: xtables: document minimal required version
+  * perf_event: Fix incorrect range check on cpu number
+  * implement early_io{re,un}map for ia64
+  * Linux 2.6.32.2
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 06 Feb 2010 18:04:10 +0000
+
+linux-ec2 (2.6.32-301.5) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-9.13
+  * [Config] update configs following rebase to Ubuntu-2.6.31-9.13
+
+  [ Ubuntu: 2.6.32-9.13 ]
+
+  * [Config] enable CONFIG_B43_PHY_LP
+    - LP: #493059
+  * include modules.builtin in the binary debs
+  * config-check -- add a configuration enforcer
+  * config-check -- add a unit-test suite to the checker
+  * [Config] Enable CONFIG_SYN_COOKIES for versatile
+  * [Config] Enable CONFIG_SECURITY_SMACK for ports
+  * [Config] Enable CONFIG_SECURITY_FILE_CAPABILITIES for ports
+  * [Config] Disable CONFIG_COMPAT_BRK for ports
+  * getabis -- add armel versatile to the list
+  * SAUCE: Increase the default prealloc buffer for HDA audio devices
+    (non-modem)
+  * ubuntu: onmibook -- Added missing BOM file
+  * ubuntu: fsam7400 -- Cleanup Makefile
+  * Revert "ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT"
+  * signal: Fix alternate signal stack check
+  * SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects
+  * SCSI: osd_protocol.h: Add missing #include
+  * SCSI: megaraid_sas: fix 64 bit sense pointer truncation
+  * ext4: fix potential buffer head leak when add_dirent_to_buf() returns
+    ENOSPC
+  * ext4: avoid divide by zero when trying to mount a corrupted file system
+  * ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails
+  * ext4: fix lock order problem in ext4_move_extents()
+  * ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT
+  * ext4: plug a buffer_head leak in an error path of ext4_iget()
+  * ext4: make sure directory and symlink blocks are revoked
+  * ext4: fix i_flags access in ext4_da_writepages_trans_blocks()
+  * ext4: journal all modifications in ext4_xattr_set_handle
+  * ext4: don't update the superblock in ext4_statfs()
+  * ext4: fix uninit block bitmap initialization when s_meta_first_bg is
+    non-zero
+  * ext4: fix block validity checks so they work correctly with meta_bg
+  * ext4: avoid issuing unnecessary barriers
+  * ext4: fix error handling in ext4_ind_get_blocks()
+  * ext4: make trim/discard optional (and off by default)
+  * ext4: make "norecovery" an alias for "noload"
+  * ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT
+  * ext4: initialize moved_len before calling ext4_move_extents()
+  * ext4: move_extent_per_page() cleanup
+  * jbd2: Add ENOMEM checking in and for
+    jbd2_journal_write_metadata_buffer()
+  * ext4: Return the PTR_ERR of the correct pointer in
+    setup_new_group_blocks()
+  * ext4: Avoid data / filesystem corruption when write fails to copy data
+  * ext4: wait for log to commit when umounting
+  * ext4: remove blocks from inode prealloc list on failure
+  * ext4: ext4_get_reserved_space() must return bytes instead of blocks
+  * ext4: quota macros cleanup
+  * ext4: fix incorrect block reservation on quota transfer.
+  * ext4: Wait for proper transaction commit on fsync
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+  * ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem)
+  * Linux 2.6.32.1
+  * kbuild: generate modules.builtin
+  * (pre-stable) drm/i915: Fix sync to vblank when VGA output is turned off
+    - LP: #494461
+  * (pre-stable) drm/i915: Avoid NULL dereference with component_only
+    tv_modes
+    - LP: #494045
+  * (pre-stable) acpi: Use the ARB_DISABLE for the CPU which model id is
+    less than 0x0f.
+    - LP: #481765
+
+  [ Ubuntu: 2.6.32-8.12 ]
+
+  * SAUCE: AppArmor -- add linux/err.h for ERR_PTR
+
+  [ Ubuntu: 2.6.32-8.11 ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches
+    up"
+  * Revert "SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition."
+  * Revert "SAUCE: AppArmor: Fix refcounting bug causing leak of creds"
+  * Revert "SAUCE: AppArmor: Fix cap audit_caching preemption disabling"
+  * Revert "SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds"
+  * Revert "SAUCE: AppArmor: Fix oops after profile removal"
+  * Revert "SAUCE: AppArmor: AppArmor disallows truncate of deleted files."
+  * Revert "SAUCE: AppArmor: AppArmor fails to audit change_hat correctly"
+  * Revert "SAUCE: AppArmor: Policy load and replacement can fail to alloc
+    mem"
+  * Revert "SAUCE: AppArmor: AppArmor wrongly reports allow perms as
+    denied"
+  * Revert "SAUCE: AppArmor: Fix mediation of "deleted" paths"
+  * Revert "SAUCE: AppArmor: Fix off by 2 error in getprocattr mem
+    allocation"
+  * Revert "SAUCE: AppArmor: Set error code after structure
+    initialization."
+  * Revert "AppArmor -- fix pstrace_may_access rename"
+  * Revert "ubuntu: AppArmor security module"
+  * Revert "SAUCE: Add config option to set a default LSM"
+  * Revert "ubuntu: fsam7400 -- sw kill switch driver"
+  * Revert "[Config] fsam7400 -- enable"
+  * Revert "[Config] AUFS -- enable"
+  * Revert "ubuntu: AUFS -- aufs2-30 20090727"
+  * Revert "ubuntu: AUFS -- export various core functions -- fixes"
+  * Revert "ubuntu: AUFS -- export various core functions"
+  * Revert "[Config] ubuntu/iscsitarget -- disable"
+  * Revert "[Config] iscsitarget -- enable"
+  * Revert "ubuntu: iscsitarget -- SVN revision r214"
+  * update Vcs-Git to point to the correct repository
+    - LP: #493589
+  * update build environment overrides to lucid
+    - LP: #493589
+  * [Config] enable CONFIG_DEVTMPFS
+  * [Config] update all configs following AppArmor 2009-12-08 update
+  * SAUCE: isapnp_init: make isa PNP scans occur async
+  * [Config] fsam7400 -- enable
+  * [Config] omnibook -- enable
+  * [Config] cleanup CONFIG_AUDIT
+  * ubuntu: AUFS -- export various core functions (aufs2-base.patch)
+  * ubuntu: AUFS -- export various core functions (aufs2-standalone.patch)
+  * ubuntu: AUFS -- aufs2 20091209
+  * [Config] AUFS -- enable
+  * [Config] iscsitarget -- enable
+  * SAUCE: KMS: cache the EDID information of the LVDS
+  * bnx2: update d-i firmware filenames
+    - LP: #494052
+  * add cdc_ether to nic-usb-modules udeb
+    - LP: #495060
+  * ubuntu: AppArmor -- mainline 2009-10-08
+  * ubuntu: fsam7400 -- kill switch for Fujitsu Siemens Amilo M 7400
+  * ubuntu: omnibook -- support Toshiba (HP) netbooks
+  * ubuntu: iscsitarget --- version 1.4.19
+    - LP: #494693
+  * SAUCE: Make populate_rootfs asynchronous
+  * Parallelize flavour builds and packaging
+  * [Config] Enable CONFIG_KSM
+  * Config option to set a default LSM
+  * LSM: Add security_path_chroot().
+  * LSM: Add security_path_chroot().
+  * LSM: Move security_path_chmod()/security_path_chown() to after
+    mutex_lock().
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 19:04:09 +0000
+
+linux-ec2 (2.6.32-301.4) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * sort out previous ABI files to fix FTBFS
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 15:00:05 +0000
+
+linux-ec2 (2.6.32-301.3) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * drop generated files to fix FTBFS
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 13:36:44 +0000
+
+linux-ec2 (2.6.32-301.2) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-7.9
+  * [Config] update configs following rebase to Ubuntu-2.6.32-7.9
+  * rebase to Ubuntu-2.6.32-7.10
+
+  [ Ubuntu: 2.6.32-7.10 ]
+
+  * [Config] disable CONFIG_THUMB2_KERNEL to fix arm FTBFS
+
+  [ Ubuntu: 2.6.32-7.9 ]
+
+  * SAUCE: set /proc/acpi/video/*/DOS to 4 by default
+    - LP: #458982
+  * SAUCE: ensure vga16fb loads if no other driver claims the VGA device
+  * [Config] update configs following versatile switch to V7
+  * rebased to v2.6.32
+  * [Config] update configs following rebase to v2.6.32
+  * [Config] update ports configs following rebase to v2.6.32
+  * SAUCE: vfs: Add a trace point in the mark_inode_dirty function
+  * [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable
+    permissions
+    - CVE-2009-3939
+  * SAUCE: select a v7 CPU for versatile
+  * SAUCE: ALSA: hda - Add power on/off counter
+  * rebased to v2.6.32
+
+  [ Ubuntu: 2.6.32-6.8 ]
+
+  * [Config] disable SSB devices for armel
+
+  [ Ubuntu: 2.6.32-6.7 ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches up"
+  * Revert "SAUCE: Dell XPS710 reboot quirk"
+  * Revert "SAUCE: Link acpi-cpufreq.o first"
+  * Revert "SAUCE: LPIA  Logical reset of USB port on resume"
+  * Revert "SAUCE: LPIA Reboot fix for Intel Crownbeach development boards"
+  * Revert "SAUCE: Enable HDMI audio codec on Studio XPS 1340"
+  * Revert "SAUCE: Dell laptop digital mic does not work, PCI 1028:0271"
+  * Revert "Add Dell Dimension 9200 reboot quirk"
+  * Revert "SAUCE: Correctly blacklist Thinkpad r40e in ACPI"
+  * Revert "SAUCE: tulip: Define ULI PCI ID's"
+  * Revert "SAUCE: Lower warning level of some PCI messages"
+  * Revert "mac80211: fix two issues in debugfs"
+    Drop a number of known redundant commits as identified in the Ubuntu
+    delta review blueprint.
+  * reenable armel versatile flavour
+  * [Config] disable CONFIG_USB_DEVICEFS
+  * [Config] udeb: Add squashfs to fs-core-modules
+    - LP: #352615
+  * [Config] Create a real squashfs udeb
+    - LP: #352615
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 07 Dec 2009 21:10:30 +0000
+
+linux-ec2 (2.6.32-300.1) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: fix nx-emulation when disabled by XEN
+  * SAUCE: fix disable of KERNEL_IMAGE_SIZE for i386 XEN builds
+
+  [ John Johansen ]
+
+  * Fix recursive include
+  * SAUCE: Fix build ASSERT for 3.0.2 compatibility
+  * SAUCE: ec2: Default domU console to tty.
+    - LP: #431103
+  * [Config] Setup EC2 commit
+  * update configs for 2.6.32
+  * rebase to Ubuntu-2.6.32-5.6
+
+  [ Ubuntu: 2.6.32-5.6 ]
+
+  * rebase to v2.6.32-rc8
+  * update configs following rebase to v2.6.32-rc8
+  * update ports configs since rebase to v2.6.32-rc8
+  * [Config] enable cgroup options
+    - LP: #480739
+  * rebase to v2.6.32-rc8
+
+  [ Ubuntu: 2.6.32-4.5 ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * rebase to v2.6.32-rc7
+  * resync with Karmic proposed
+  * SAUCE: AppArmor: Fix oops after profile removal
+    - LP: #475619
+  * SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds
+    - LP: #437258
+  * SAUCE: AppArmor: Fix cap audit_caching preemption disabling
+    - LP: #479102
+  * SAUCE: AppArmor: Fix refcounting bug causing leak of creds
+    - LP: #479115
+  * SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition.
+    - LP: #480112
+  * resync with Karmic proposed (ddbc670a86a3dee18541a3734149f250ff307adf)
+  * rebase to v2.6.32-rc7
+
+  [ Ubuntu: 2.6.32-3.4 ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * [Upstream] add local prefix to oss local change_bits
+  * mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/
+  * mtd/maps: gpio-addr-flash: depend on GPIO arch support
+
+  [ Ubuntu: 2.6.32-3.3 ]
+
+  * rebase to v2.6.32-rc6
+  * [Config] update configs following rebase to v2.6.32-rc6
+  * [Config] update ports configs following rebase to v2.6.32-rc6
+  * resync with Karmic Ubuntu-2.6.31-15.49
+  * [Config] add module ignores for broken drivers
+  * SAUCE: AppArmor: AppArmor wrongly reports allow perms as denied
+    - LP: #453335
+  * SAUCE: AppArmor: Policy load and replacement can fail to alloc mem
+    - LP: #458299
+  * SAUCE: AppArmor: AppArmor fails to audit change_hat correctly
+    - LP: #462824
+  * SAUCE: AppArmor: AppArmor disallows truncate of deleted files.
+    - LP: #451375
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+  * Revert "SAUCE: trace: add trace_event for the open() syscall"
+  * SAUCE: trace: add trace events for open(), exec() and uselib()
+    - LP: #462111
+  * SAUCE: Fix sub-flavour script to not stop on missing directories
+    - LP: #453073
+  * resync with Karmic Ubuntu-2.6.31-15.49
+  * rebase to v2.6.32-rc6
+    - LP: #464552
+
+  [ Ubuntu: 2.6.32-2.2 ]
+
+  * install the full changelog with the binary package
+  * changelog -- explicitly note rebases and clean history
+  * reinstate armel.mk with no flavours
+    - LP: #449637
+  * [Upstream] block: silently error unsupported empty barriers too
+    - LP: #420423
+  * [Config] udate configs following karmic resync
+  * [Config] update ports configs following karmic resync
+  * [Upstream] lirc -- follow removal of .id element
+  * Use section 'admin' rather than 'base'
+  * Add more e100 firmware to nic-modules
+    - LP: #451872
+  * Add qla1280 firmware to scsi-modules
+    - LP: #381037
+  * SAUCE: AppArmor: Set error code after structure initialization.
+    - LP: #427948
+  * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation
+    - LP: #446595
+  * SAUCE: AppArmor: Fix mediation of "deleted" paths
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+  * SAUCE: (drop after 2.6.31) input: Add support for filtering input
+    events
+    - LP: #430809
+  * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi
+    toggle switch press
+    - LP: #430809
+  * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc
+  * [Config] Add sd_mod to scsi-modules udeb for powerpc
+  * SAUCE: Update to LIRC 0.8.6
+    - LP: #432678
+  * SAUCE: dell-laptop: Store the HW switch status internally rather than
+    requerying every time
+    - LP: #430809
+  * SAUCE: dell-laptop: Blacklist machines not supporting dell-laptop
+    - LP: #430809
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    - LP: #435958
+  * [Upstream] i915: Fix i2c init message
+    - LP: #409361
+  * [Config] Add sym53c8xx.ko to virtual sub-flavour
+    - LP: #439415
+  * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules
+    - LP: #439456
+  * [Config] Set default I/O scheduler back to CFQ for desktop flavours
+    - LP: #381300
+  * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros
+    - LP: #430694
+  * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915
+    - LP: #430694
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT
+    - LP: #430694
+  * SAUCE: Raise the default console 'quiet' level to 2
+  * [Config] CONFIG_X86_PAT=y
+  * [Config] Add armel arch to linux-libc-dev arches.
+    - LP: #449637
+  * [Config] CONFIG_X86_MCE
+  * [Upstream] (drop after 2.6.31) Input: synaptics - add another Protege
+    M300 to rate blacklist
+    - LP: #433801
+  * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584
+  * drm/i915: Fix FDI M/N setting according with correct color depth
+    - LP: #416792
+
+  [ Ubuntu: 2.6.32-1.1 ]
+
+  * rebase to v2.6.32-rc3
+  * [Config] update configs following rebase to 2.6.32-rc3
+  * [Config] update ports configs following rebase to 2.6.32-rc3
+  * AppArmor -- fix pstrace_may_access rename
+  * staging/android -- disable
+  * ubuntu: dm-raid-45 -- update to compile with 2.6.32
+  * ubuntu: drbd -- disable
+  * staging/comdi -- disable
+  * staging/go7007 -- disable
+  * [Config] staging/winbond -- disable
+  * [Config] ubuntu/iscsitarget -- disable
+  * [d-i] cbc and ecb are builtin make them optional in udebs
+  * rebase to v2.6.32-rc5
+  * [Config] update configs following rebase to v2.6.32-rc5
+  * [Config] update ports configs following rebase to v2.6.31-rc5
+  * [Config] Add cpio as a build dependency.
+  * rebase to v2.6.32-rc3
+  * rebase to v2.6.32-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 30 Nov 2009 12:48:46 +0000
+
+linux-ec2 (2.6.31-302.7) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Updateconfigs after rebase to 2.6.31-14.46
+
+  * Rebased against linux (2.6.31-14.46)
+
+  [ Andy Whitcroft ]
+
+  * reinstate armel.mk with no flavours
+    - LP: #449637
+  * [Upstream] elevator: fix fastfail checks to allow merge of readahead
+    requests
+    - LP: #444915
+  * [Upstream] block: silently error unsupported empty barriers too
+    - LP: #420423
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix mediation of "deleted" paths
+    - LP: #415632
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_X86_MCE
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007584.html
+  * Revert "appletalk: Fix skb leak when ipddp interface is not loaded,
+    CVE-2009-2903" - Use patch from 2.6.31.4 which is slightly different.
+
+  [ Upstream Kernel Changes ]
+
+  * x86: fix csum_ipv6_magic asm memory clobber
+  * tty: Avoid dropping ldisc_mutex over hangup tty re-initialization
+  * x86: Don't leak 64-bit kernel register values to 32-bit processes
+  * tracing: correct module boundaries for ftrace_release
+  * ftrace: check for failure for all conversions
+  * futex: fix requeue_pi key imbalance
+  * futex: Move exit_pi_state() call to release_mm()
+  * futex: Nullify robust lists after cleanup
+  * futex: Fix locking imbalance
+  * NOHZ: update idle state also when NOHZ is inactive
+  * ima: ecryptfs fix imbalance message
+  * libata: fix incorrect link online check during probe
+  * sound: via82xx: move DXS volume controls to PCM interface
+  * ASoC: WM8350 capture PGA mutes are inverted
+  * KVM: Prevent overflow in KVM_GET_SUPPORTED_CPUID
+  * KVM: VMX: flush TLB with INVEPT on cpu migration
+  * KVM: fix LAPIC timer period overflow
+  * KVM: SVM: Fix tsc offset adjustment when running nested
+  * KVM: SVM: Handle tsc in svm_get_msr/svm_set_msr correctly
+  * net: Fix wrong sizeof
+  * mm: add_to_swap_cache() must not sleep
+  * sis5513: fix PIO setup for ATAPI devices
+  * PIT fixes to unbreak suspend/resume (bug #14222)
+  * IMA: open new file for read
+  * ACPI: Clarify resource conflict message
+  * ACPI: fix Compaq Evo N800c (Pentium 4m) boot hang regression
+  * net: restore tx timestamping for accelerated vlans
+  * net: unix: fix sending fds in multiple buffers
+  * tun: Return -EINVAL if neither IFF_TUN nor IFF_TAP is set.
+  * tcp: fix CONFIG_TCP_MD5SIG + CONFIG_PREEMPT timer BUG()
+  * net: Fix sock_wfree() race
+  * smsc95xx: fix transmission where ZLP is expected
+  * sky2: Set SKY2_HW_RAM_BUFFER in sky2_init
+  * appletalk: Fix skb leak when ipddp interface is not loaded
+  * ax25: Fix possible oops in ax25_make_new
+  * ax25: Fix SIOCAX25GETINFO ioctl
+  * sit: fix off-by-one in ipip6_tunnel_get_prl
+  * Linux 2.6.31.4
+  * drm/i915: Fix FDI M/N setting according with correct color depth
+    - LP: #416792
+
+  * linux (2.6.31-13.45)
+
+  [ Luke Yelavich ]
+
+  * [Config] Add sd_mod to scsi-modules udeb for powerpc
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Update to LIRC 0.8.6
+    - LP: #432678
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_X86_PAT=y
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007477.html
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007534.html
+
+  * [Config] Add armel arch to linux-libc-dev arches.
+    - LP: #449637
+
+  [ Upstream Kernel Changes ]
+
+  * e1000e: swap max hw supported frame size between 82574 and 82583
+  * drm/i915: Initialize HDMI outputs as HDMI connectors, not DVI.
+    - LP: #392017
+  * ALSA: hda - Add quirks for some HP laptops
+    - LP: #449742
+  * ALSA: hda - Add support for HP dv6
+    - LP: #449742
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 12 Oct 2009 11:27:10 -0600
+
+  * linux (2.6.31-13.44)
+
+  [ Upstream Kernel Changes ]
+
+  * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584
+  * appletalk: Fix skb leak when ipddp interface is not loaded,
+    CVE-2009-2903
+    Note - This patch causes an ABI change in the symbol aarp_send_ddp
+    which I'm ignoring.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 13 Oct 2009 12:00:22 -0600
+
+linux-ec2 (2.6.31-301.6) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Added cpio as a build dependency.
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * [Config] Disable CONFIG_UEVENT_HELPER_PATH
+  * [Config] Enable CONFIG_USB_GADGET_DUMMY_HCD
+  * [Config] Disable Intel AGP/DRM
+
+  * Rebased against linux (2.6.31-13.43) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Upstream] acerhdf: Limit modalias matching to supported
+    boards"
+
+  [ Colin Watson ]
+
+  * Use section 'admin' rather than 'base'
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Set error code after structure initialization.
+    - LP: #427948
+  * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation
+    - LP: #446595
+
+  [ Luke Yelavich ]
+
+  * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc
+
+  [ Stefan Bader ]
+
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    (supersedes previous revert made by Andy Whitcroft)
+    - LP: #435958
+
+  * Rebased against linux (2.6.31-13.42) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * SAUCE: (drop after 2.6.31) input: Add support for filtering input
+    events
+    - LP: #430809
+  * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi
+    toggle switch press
+    - LP: #430809
+
+  [ Tim Gardner ]
+
+  * SAUCE: Raise the default console 'quiet' level to 2
+    This supresses all but critical and emergency level messages.
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007476.html
+
+  [ Upstream Kernel Changes ]
+
+  * TTY: fix typos
+  * Linux 2.6.31.3
+  * V4L/DVB (12439): cx88: add support for WinFast DTV2000H rev. J
+    - LP: #433904
+
+  * Rebased against linux (2.6.31-12.41) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT
+    The original patch failed to work for amd64.
+    - LP: #430694
+
+  [ Upstream Kernel Changes ]
+
+  * ALSA: hda - Add a white-list for MSI option
+    Upstream cherry-pick: Infrastructure support for #445580
+  * ALSA: hda - Add HP Pavilion dv4t-1300 to MSI whitelist
+    - LP: #445580
+  * ALSA: intel8x0 - Mute External Amplifier by default for Sony VAIO
+    VGN-T350P
+    - LP: #410933
+  * ALSA: intel8x0 - Mute External Amplifier by default for Sony VAIO
+    VGN-B1VP
+    - LP: #410933
+
+  * Rebased against linux (2.6.31-12.40) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros
+    - LP: #430694
+  * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915
+    - LP: #430694
+
+  [ Upstream Kernel Changes ]
+
+  * V4L/DVB (12352): gspca - vc032x: Fix mi1310_soc preview and LED
+    - LP: #310760
+
+  * Rebased against linux (2.6.31-12.39) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * install the full changelog with the binary package
+  * changelog -- explicitly note rebases and clean history
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (drop after 2.6.31) Disable iwl-1000 series wireless
+    adapters"
+  * Revert "SAUCE: (drop after 2.6.31) eCryptfs: Prevent lower dentry from
+    going negative during unlink"
+  * Revert "SAUCE: (drop after 2.6.31) em28xx: ir-kbd-i2c init data needs a
+    persistent object"
+  * Revert "SAUCE: (drop after 2.6.31) saa7134: ir-kbd-i2c init data needs
+    a persistent object"
+  * Revert "drm/i915: Check that the relocation points to within the
+    target"
+  * Revert "drm/i915: fix tiling on IGDNG"
+  * Revert "Driver core: add new device to bus's list before probing"
+  * Revert "HID: completely remove apple mightymouse from blacklist"
+  * Revert "KVM: x86: check for cr3 validity in ioctl_set_sregs"
+
+    All reverts superseded by corresponding v2.6.31.2 patches
+
+  * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules
+    - LP: #439456
+  * [Config] Enabled CONFIG_SND_HDA_HWDEP
+    - LP: #443117
+  * [Config] Add cpio as a build dependency.
+  * [Config] Set default I/O scheduler back to CFQ for desktop flavours
+    - LP: #381300
+
+  [ Upstream Kernel Changes ]
+
+  * KVM: VMX: Fix EPT with WP bit change during paging
+  * pata_amd: do not filter out valid modes in nv_mode_filter
+  * p54usb: add Zcomax XG-705A usbid
+  * x86: Increase MIN_GAP to include randomized stack
+  * serial: bfin_5xx: fix building as module when early printk is enabled
+  * USB: option.c Add support for ZTE AC2726 EVDO modem
+  * USB: option: TELIT UC864G support
+  * video: s3c_fb.c: fix build with CONFIG_HOTPLUG=n
+  * kbuild: fix cc1 options check to ensure we do not use -fPIC when
+    compiling
+  * drivers/mfd/ab3100-core.c: fix powerpc build error
+  * thinkpad-acpi: don't ask about brightness_mode for fw. 1V and 1R
+  * ACPI: pci_slot.ko wants a 64-bit _SUN
+  * fbcon: only unbind from console if successfully registered
+  * kallsyms: fix segfault in prefix_underscores_count()
+  * sisfb: change SiS_DDC_Port type to SISIOADDRESS
+  * mmc_spi: fail gracefully if host or card do not support the switch
+    command
+  * alpha: AGP update (fixes compile failure)
+  * fs: make sure data stored into inode is properly seen before unlocking
+    new inode
+  * eCryptfs: Handle unrecognized tag 3 cipher codes
+  * eCryptfs: Check for O_RDONLY lower inodes when opening lower files
+  * eCryptfs: Filename encryption only supports password auth tokens
+  * eCryptfs: Validate global auth tok keys
+  * eCryptfs: Prevent lower dentry from going negative during unlink
+  * Re-enable Lanman security
+  * xen: make -fstack-protector work under Xen
+  * xen: only enable interrupts while actually blocking for spinlock
+  * xen: use stronger barrier after unlocking lock
+  * xen: check EFER for NX before setting up GDT mapping
+  * perf_counter: Fix perf_copy_attr() pointer arithmetic
+  * perf tools: Fix buffer allocation
+  * tty: serial/pcmcia: add ID for Advantech card
+  * PM / PCMCIA: Drop second argument of pcmcia_socket_dev_suspend()
+  * PM / yenta: Fix cardbus suspend/resume regression
+  * sony-laptop: check for rfkill hard block at load time
+  * nilfs2: fix missing zero-fill initialization of btree node cache
+  * ar9170usb: add usbid for TP-Link TL-WN821N v2
+  * mtd: nand: fix ECC Correction bug for SMC ordering for NDFC driver
+  * mtd: ofpart: Check availability of reg property instead of name
+    property
+  * mtd: cfi_cmdset_0002: add 0xFF intolerance for M29W128G
+  * USB: serial: ftdi_sio: new hardware support - hameg power supply
+  * USB: add PIDs for FTDI based OpenDCC hardware
+  * USB: serial: ftdi: handle gnICE+ JTAG adaptors
+  * USB: CDC WDM driver doesn't support non-blocking reads
+  * USB: fix cdc-acm regression in open
+  * cdc_acm: Fix to use modern speed interfaces
+  * tty: remove dtr/rts use from the driver open methods
+  * tty: gigaset: really fix chars_in_buffer
+  * kaweth: Fix memory leak in kaweth_control()
+  * x86: SGI UV: Fix IPI macros
+  * USB: serial: pl2303: new hardware support - sanwa multimeter
+  * USB: storage: fix a resume path GFP_NOIO must be used
+  * USB: usb-storage fails to attach to Huawei Datacard cdrom device
+  * USB: usbtmc: sanity checks for DEV_DEP_MSG_IN urbs
+  * USB: sl811-hcd: Fix device disconnect:
+  * drm/i915: remove restore in resume
+  * drm/i915: Only destroy a constructed mmap offset
+  * drm/i915: prevent FIFO calculation overflows on 32 bits with high
+    dotclocks
+  * drm/i915: Add buffer to inactive list immediately during fault
+  * drm/i915: Check that the relocation points to within the target
+  * drm/i915: Fix typo for wrong LVDS clock setting on IGDNG
+  * drm/i915: Fix SSC frequence for IGDNG
+  * drm/i915: Remove DAC disable in CRT force detect on IGDNG
+  * drm/i915: Fix LVDS panel fitting on Arrandale
+  * drm/I915: Use the CRT DDC to get the EDID for DVI-connector on Mac
+  * drm/i915: fix tiling on IGDNG
+  * agp/intel: Fix the pre-9xx chipset flush.
+  * nfsd4: fix null dereference creating nfsv4 callback client
+  * can: fix NOHZ local_softirq_pending 08 warning
+  * ahci: restore pci_intx() handling
+  * pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume
+  * net ax25: Fix signed comparison in the sockopt handler
+  * net: Make the copy length in af_packet sockopt handler unsigned
+  * pty_write: don't do a tty_wakeup() when the buffers are full
+  * KVM: fix cpuid E2BIG handling for extended request types
+  * KVM: MMU: fix missing locking in alloc_mmu_pages
+  * KVM: MMU: fix bogus alloc_mmu_pages assignment
+  * KVM: Protect update_cr8_intercept() when running without an apic
+  * Fix NULL ptr regression in powernow-k8
+  * perf tools: do not complain if root is owning perf.data
+  * netfilter: nf_nat: fix inverted logic for persistent NAT mappings
+  * netfilter: nf_conntrack: netns fix re reliable conntrack event delivery
+  * netfilter: bridge: refcount fix
+  * netfilter: ebt_ulog: fix checkentry return value
+  * ath5k: Wakeup fixes
+  * ath5k: do not release irq across suspend/resume
+  * Driver core: add new device to bus's list before probing
+  * tty: Add a full port_close function
+  * tty: USB hangup is racy
+  * tty: USB can now use the shutdown method for kref based freeing of
+    ports
+  * hwmon: (asus_atk0110) Add maintainer information
+  * tty: USB serial termios bits
+  * usb-serial: change referencing of port and serial structures
+  * usb-serial: put subroutines in logical order
+  * usb-serial: change logic of serial lookups
+  * usb-serial: acquire references when a new tty is installed
+  * usb-serial: fix termios initialization logic
+  * usb-serial: rename subroutines
+  * usb-serial: add missing tests and debug lines
+  * usb-serial: straighten out serial_open
+  * USB serial: update the console driver
+  * USB: xhci: Work around for chain bit in link TRBs.
+  * USB: xhci: Fix slot and endpoint context debugging.
+  * USB: xhci: Configure endpoint code refactoring.
+  * USB: xhci: Set correct max packet size for HS/FS control endpoints.
+  * USB: xhci: Support full speed devices.
+  * USB: xhci: Handle stalled control endpoints.
+  * USB: xhci: Add quirk for Fresco Logic xHCI hardware.
+  * USB: xhci: Make TRB completion code comparison readable.
+  * USB: xhci: Handle babbling endpoints correctly.
+  * USB: xhci: Don't touch xhci_td after it's freed.
+  * USB: xhci: Check URB's actual transfer buffer size.
+  * USB: xhci: Check URB_SHORT_NOT_OK before setting short packet status.
+  * USB: xhci: Set -EREMOTEIO when xHC gives bad transfer length.
+  * USB: xhci: Support interrupt transfers.
+  * USB: Fix SS endpoint companion descriptor parsing.
+  * /proc/kcore: work around a BUG()
+  * hugetlb: restore interleaving of bootmem huge pages (2.6.31)
+  * page-allocator: limit the number of MIGRATE_RESERVE pageblocks per zone
+  * mm: munlock use follow_page
+  * mm: fix anonymous dirtying
+  * mmap: avoid unnecessary anon_vma lock acquisition in vma_adjust()
+  * Fix idle time field in /proc/uptime
+  * drm/i915: Handle ERESTARTSYS during page fault
+  * em28xx: ir-kbd-i2c init data needs a persistent object
+  * saa7134: ir-kbd-i2c init data needs a persistent object
+  * powerpc/8xx: Fix regression introduced by cache coherency rewrite
+  * powerpc: Fix incorrect setting of __HAVE_ARCH_PTE_SPECIAL
+  * HID: completely remove apple mightymouse from blacklist
+  * mptsas : PAE Kernel more than 4 GB kernel panic
+  * NOMMU: Fix MAP_PRIVATE mmap() of objects where the data can be mapped
+    directly
+  * iwlwifi: Handle new firmware file with ucode build number in header
+  * iwlwifi: update 1000 series API version to match firmware
+  * iwlagn: modify digital SVR for 1000
+  * iwlwifi: traverse linklist to find the valid OTP block
+  * iwlwifi: fix unloading driver while scanning
+  * Linux 2.6.31.2
+
+  * Rebased against linux (2.6.31-11.38) karmic; urgency=low
+
+  [ Stefan Bader ]
+
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    - LP: #435958
+
+  [ Tim Gardner ]
+
+  * [Config] Added sata_via to d-i/modules/sata-modules
+    - LP: #434827
+  * SAUCE: (drop after 2.6.31) Disable iwl-1000 series wireless adapters
+    - LP: #439285
+  * [Upstream] i915: Fix i2c init message
+    - LP: #409361
+  * [Config] Add sym53c8xx.ko to virtual sub-flavour
+    - LP: #439415
+
+  [ Upstream Kernel Changes ]
+
+  * sched: Disable NEW_FAIR_SLEEPERS for now
+    - LP: #436342
+
+  * ACPI video: ignore buggy _BQC
+  * ACPI video: work-around BIOS AML bug in _BQC
+    - LP: #428910
+  * ALSA: hda - Added quirk to enable sound on Toshiba NB200
+    - LP: #438318
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 09 Oct 2009 10:42:15 -0600
+
+linux-ec2 (2.6.31-300.5) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Fix header package names and dependencies
+    - LP: #437784
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 30 Sep 2009 08:07:32 -0600
+
+linux-ec2 (2.6.31-300.4) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Disable Lenovo laptop config
+  * Rebase against master Ubuntu-2.6.31-11.37
+
+  [ Upstream Kernel Changes ]
+
+  * n_tty: honor opost flag for echoes
+  * n_tty: move echoctl check and clean up logic
+    - LP: #438310
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 28 Sep 2009 22:15:20 -0600
+
+linux-ec2 (2.6.31-300.3) karmic; urgency=low
+
+  [ Chuck Short ]
+
+  * SAUCE: ec2: Default domU console to tty.
+    - LP: #431103
+
+  [ Tim Gardner ]
+
+  * [Config] Remove dependency on wireless-crda
+    - LP: #434755
+  * [Config] Drop bootloaders as a recommendation
+    - LP: #434755
+  * [Config] Drop virtual sub flavours
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 25 Sep 2009 15:18:34 -0600
+
+linux-ec2 (2.6.31-300.2) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Use gawk in xen makefiles
+  * [Config] CONFIG_DMI=n for XEN_UNPRIVILEGED_GUEST
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 22:54:48 -0600
+
+linux-ec2 (2.6.31-300.1) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * Revert "[Config] Let lenovo-sl-laptop build"
+  * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32"
+  * [Config] Initial EC2 commit
+  * [Config] Removed ports
+  * [Config] Removed lpia
+  * [Config] Settled on the single EC2 flavour
+  * [Config] Disable udebs
+  * SAUCE: Prepare swap.h for Xen patches
+  * SAUCE: Xen 3.02
+  * [Config] Target vmlinuz
+  * [Config] Build with correct arch
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "PCI SR-IOV: correct broken resource alignment calculations"
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 20:31:57 -0600
+
+linux-ec2 (2.6.31-300.0) karmic; urgency=low
+
+  * Dummy entry
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 20:31:57 -0600
+
+linux (2.6.31-10.30) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Enable CONFIG_USB_DEVICEFS
+    - LP: #417748
+  * [Config] Populate the config-update template a bit more
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.31-rc9
+  * [Config] update configs following rebase to v2.6.31-rc9
+  * [Config] update ports configs following rebase to v2.6.31-rc9
+
+  [ Colin Ian King ]
+
+  * SAUCE: wireless: hostap, fix oops due to early probing interrupt
+    - LP: #254837
+
+  [ Jerone Young ]
+
+  * [Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux)
+    white-list
+    - LP: #281732
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix profile attachment for regexp based profile names
+    - LP: #419308
+  * SAUCE: AppArmor: Return the correct error codes on profile
+    addition/removal
+    - LP: #408473
+  * SAUCE: AppArmor: Fix OOPS in profile listing, and display full list
+    - LP: #408454
+  * SAUCE: AppArmor: Fix mapping of pux to new internal permission format
+    - LP: #419222
+  * SAUCE: AppArmor: Fix change_profile failure
+    - LP: #401931
+  * SAUCE: AppArmor: Tell git to ignore generated include files
+    - LP: #419505
+
+  [ Stefan Bader ]
+
+  * [Upstream] acpi: video: Loosen strictness of video bus detection code
+    - LP: #333386
+  * SAUCE: Remove ov511 driver from ubuntu subdirectory
+
+  [ Tim Gardner ]
+
+  * [Config] Exclude char-modules from non-x86 udeb creation
+  * SAUCE: Notify the ACPI call chain of AC events
+  * [Config] CONFIG_SATA_VIA=m
+    - LP: #403385
+  * [Config] Build in all phylib support modules.
+  * [Config] Don't fail when sub-flavour files are missing
+    - LP: #423426
+  * [Config] Set CONFIG_LSM_MMAP_MIN_ADDR=0
+    - LP: #423513
+
+  [ Upstream ]
+
+  * Rebased against v2.6.31-rc9
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 07 Sep 2009 11:33:45 +0100
+
+linux (2.6.31-9.29) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] agp/intel: support for new chip variant of IGDNG mobile
+    - LP: #419993
+  * [Config] d-i/modules: Add new char-modules file, initialize with
+    intel-agp
+    - LP: #420605
+
+  [ Upstream ]
+
+  * Rebased against 2.6.31-rc8 plus some inotify regression patches:
+    up through git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+    adda766193ea1cf3137484a9521972d080d0b7af.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 28 Aug 2009 06:31:30 -0600
+
+linux (2.6.31-8.28) karmic; urgency=low
+
+  [ Ike Panhc ]
+
+  * [Config] Let nic-shared-modules depends on crypto-modules
+    - LP: #360966
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] (drop after 2.6.31) drm/i915: increase default latency
+    constant
+    - LP: #412492
+
+  [ Mario Limonciello ]
+
+  * [Upstream]: (drop after 2.6.31) dell-laptop: don't change softblock
+    status if HW switch is disabled
+    - LP: #418721
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Add support for known
+    Compal made Dell laptops
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Replace sysfs support
+    with rfkill support
+
+  [ Tim Gardner ]
+
+  * [Config] Add acpiphp to virtual sub-flavour
+    - LP: #364916
+  * Drop KSM patch set for now because of instabilities with encrypted swap.
+    - LP: #418781
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 26 Aug 2009 08:14:26 -0600
+
+linux (2.6.31-7.27) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] updateconfigs updateportsconfigs after 2.6.31-rc7 rebase
+  * SAUCE: (drop after 2.6.31) Added KSM from mmotm-2009-08-20-19-18
+    Replaces previous ksm patches from 2.6.31-6.25
+  * [Config] KSM=y
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 22 Aug 2009 20:32:11 -0600
+
+linux (2.6.31-6.26) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] enable CONFIG_AUFS_BR_RAMFS
+    - LP: #414738
+  * split out debian directory ready for abstraction
+  * add printdebian target to find branch target
+  * abstracted debian -- debian/files is not abstracted
+  * abstracted debian -- packages must be built in debian/<pkg>
+  * abstracted debian -- kernel-wedge needs to work in debian/
+  * abstracted debian -- ensure we install the copyright file
+  * abstracted-debian -- drop the debian directories from headers
+  * abstracted-debian -- drop the debian directories from headers part 2
+  * SAUCE: ubuntu-insert-changes -- follow abstracted debian
+  * [Upstream] aoe: ensure we initialise the request_queue correctly V2
+    - LP: #410198
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Disable CONFIG_CPU_FREQ_DEBUG on powerpc-smp
+  * [Config] Ports: Re-enable windfarm modules on powerpc64-smp
+    - LP: #413150
+  * [Config] Ports: Build all cpu frequency scaling governors into ports
+    kernels
+  * [Config] Ports: Build ext2 and ext3 modules into ports kernels
+  * [Config] Ports: CONFIG_PACKET=y for all ports kernels
+  * [Config] Ports: Enable PS3 network driver
+
+  [ Stefan Bader ]
+
+  * abstracted debian -- call $(DEBIAN)/rules using make
+
+  [ Tim Gardner ]
+
+  * [Config] Abstract the debian directory
+  * SAUCE: Improve error reporting in postinst
+    - LP: #358564
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 16 Aug 2009 20:33:28 -0600
+
+linux (2.6.31-6.25) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * script to generate Ubuntu changes from changelog
+  * [Config] standardise ANDROID options
+  * [Config] standardise CONFIG_ATM as module
+  * [Config] standardise CONFIG_LIB80211 as module
+  * [Config] disable CONFIG_PRINT_QUOTA_WARNING
+  * [Config] set CONFIG_CRAMFS as module
+  * [Config] enable CONFIG_DAB and modules
+  * [Config] set CONFIG_MAC80211_HWSIM as module
+  * [Config] set CONFIG_NET_CLS_FLOW as module
+  * [Config] set CONFIG_NF_CONNTRACK_SANE as module
+  * [Config] set CONFIG_NF_CT_PROTO_DCCP as module
+  * [Config] set CONFIG_RTC_DRV_DS1511 as module
+  * [Config] set CONFIG_RTC_DRV_R9701 as module
+  * [Config] set CONFIG_RTC_DRV_S35390A as module
+  * [Config] set CONFIG_TOIM3232_DONGLE as module
+  * [Config] standardise CONFIG_USB_MIDI_GADGET as module
+  * [Config] standardise CONFIG_USB_G_PRINTER as module
+  * [Config] standardise CONFIG_USB_SERIAL_IR as module
+  * [Config] set CONFIG_USB_SERIAL_IUU as module
+  * [Config] standardise CONFIG_USB_STORAGE_CYPRESS_ATACB as module
+  * [Config] standardise CONFIG_USB_STORAGE_ONETOUCH as module
+  * cleanup remains of dm-loop
+  * drop thinkpad ec and smapi support
+  * drop appleir
+  * [Config] update configs following rebase to v2.6.31-rc6
+
+  [ Hugh Dickins ]
+
+  * SAUCE: ksm patch 1, drop after 2.6.31
+  * SAUCE: ksm patch 2, drop after 2.6.31
+  * SAUCE: ksm patch 3, drop after 2.6.31
+  * SAUCE: ksm patch 4, drop after 2.6.31
+  * SAUCE: ksm patch 5, drop after 2.6.31
+  * SAUCE: ksm patch 7, drop after 2.6.31
+
+  [ Izik Eidus ]
+
+  * SAUCE: ksm patch 0, drop after 2.6.31
+  * SAUCE: ksm patch 6, drop after 2.6.31
+  * SAUCE: ksm patch 8, drop after 2.6.31
+  * SAUCE: ksm patch 9, drop after 2.6.31
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Re-add PS3 modules to udebs
+
+  [ Michael Casadevall ]
+
+  * [Config] Update SPARC config and d-i files to reflect what can be built
+
+  [ Tim Gardner ]
+
+  * [Config] Removed armel package support
+  * [Config] Enabled CONFIG_KSM=y
+
+  [ Upstream Kernel Changes ]
+
+  * ARM: Cleanup: Revert "ARM: Add more cache memory types macros"
+  * ARM: Cleanup: Revert "Do not use OOB with MLC NAND"
+  * ARM: Cleanup: Revert "ARM: Make ARM arch aware of ubuntu/ drivers"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make video capture drivers compile"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix isl29003 HWMON driver for i2c
+    changes"
+  * ARM: Cleanup: Revert "ARM: IMX51: IPU irq handler deadlock fix"
+  * ARM: Cleanup: Revert "ARM: IMX51: Babbage 2.5 needs a different system
+    revision"
+  * ARM: Cleanup: Revert "ARM: IMX51: Compile-in the IMX51 cpufreq driver
+    by default"
+  * ARM: Cleanup: Revert "ARM: IMX51: Enable ZONE_DMA for ARCH_MXC"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make ARCH_MXC auto-enable
+    ARCH_MXC_CANONICAL"
+  * ARM: Cleanup: Revert "ARM: IMX51: Unconditionally disable
+    CONFIG_GPIOLIB"
+  * ARM: Cleanup: Revert "ARM: IMX51: Minimal changes for USB to work on
+    2.6.31"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix plat-mxc/timer.c to handle imx51"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make it compile."
+  * ARM: Cleanup: Revert "ARM: IMX51: Clean-up the craziness of including
+    mxc_uart.h _everywhere_"
+  * ARM: Cleanup: Revert "ARM: IMX51: Move board-mx51* header files to the
+    correct location"
+  * ARM: Cleanup: Revert "ARM: IMX51: Changed from snd_card_new to
+    snd_card_create"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix up merge error in Kconfig"
+  * ARM: Cleanup: Revert "ARM: IMX51: mxc_timer_init prototype"
+  * ARM: Cleanup: Revert "ARM: IMX51: Removed the mxc_gpio_port structure."
+  * ARM: Cleanup: Revert "ARM: IMX51: Added external declaration for
+    mxc_map_io."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: snd_soc_machine structure replaced
+    with snd_soc_card."
+  * ARM: Cleanup: Revert "ARM: IMX51: codec structure was moved to the card
+    structure"
+  * ARM: Cleanup: Revert "ARM: IMX51: Hack to add defines for
+    DMA_MODE_READ/WRITE/MASK"
+  * ARM: Cleanup: Revert "ARM: IMX51: Add SoC and board support for
+    Freescale mx51 platform"
+  * Driver core: add new device to bus's list before probing
+  * [Upstream] (drop after 2.6.31) ALSA: hda - Reduce click noise at
+    power-saving
+    - LP: #381693, #399750, #380892
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 14 Aug 2009 11:32:23 +0100
+
+linux (2.6.31-5.24) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Make video capture drivers compile
+  * [Config] IMX51: Config updates
+
+  [ Andy Whitcroft ]
+
+  * remove leftovers of dm-bbr
+
+  [ Leann Ogasawara ]
+
+  * Add pata_cs5535 to pata-modules
+    - LP: #318805
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_PPC64=y for powerpc64-smp
+  * [Config] Set the maximum number of CPUs to 1024 for powerpc64-smp
+  * [Config] CONFIG_PPC_PS3=y for powerpc64-smp
+  * [Config] CONFIG_PPC_MAPLE=y on powerpc64-smp
+  * [Config] CONFIG_PPC_PASEMI=y on powerpc64-smp
+  * [Config] CONFIG_CPU_FREQ_PMAC64=y on powerpc64-smp
+  * [Config] Enable all PS3 drivers in powerpc64-smp
+
+  [ Mario Limonciello ]
+
+  * LIRC -- fix lirc-i2c 2.6.31 compilation
+
+  [ Matthew Garrett ]
+
+  * [Upstream] dell-laptop: Fix rfkill state queries
+
+  [ Tim Gardner ]
+
+  * [Config] Ignore armel ABI and module changes
+  * [Config] Update configs after rebase against 2.6.31-rc5
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 28 Jul 2009 10:10:09 +0100
+
+linux (2.6.31-4.23) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * AUFS -- update to aufs2-30 20090727
+  * [Config] enable AUFS FUSE support
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_JFS_FS=m on sparc
+
+  [ Tim Gardner ]
+
+  * [Upstream] dell-laptop: Fix rfkill state setting.
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 27 Jul 2009 11:11:47 +0100
+
+linux (2.6.31-4.22) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Add SoC and board support for Freescale mx51 platform
+  * ARM: IMX51: Move board-mx51* header files to the correct location
+  * ARM: IMX51: Clean-up the craziness of including mxc_uart.h _everywhere_
+  * ARM: IMX51: Make it compile.
+  * ARM: IMX51: Unconditionally disable CONFIG_GPIOLIB
+  * ARM: IMX51: Make ARCH_MXC auto-enable ARCH_MXC_CANONICAL
+  * ARM: IMX51: Enable ZONE_DMA for ARCH_MXC
+  * ARM: IMX51: Compile-in the IMX51 cpufreq driver by default
+  * ARM: IMX51: Fix isl29003 HWMON driver for i2c changes
+  * ARM: USB: musb: Refer to musb_otg_timer_func under correct #ifdef
+  * ARM: staging: udlfb: Add vmalloc.h include
+  * UBUNTU [Config]: Bring imx51 config upto date with other flavours
+
+  [ Brad Figg ]
+
+  * ARM: IMX51: Hack to add defines for DMA_MODE_READ/WRITE/MASK
+  * ARM: IMX51: codec structure was moved to the card structure
+  * ARM: IMX51: snd_soc_machine structure replaced with snd_soc_card.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Added external declaration for mxc_map_io.
+  * ARM: IMX51: Removed the mxc_gpio_port structure.
+  * ARM: IMX51: mxc_timer_init prototype
+  * ARM: IMX51: Fix up merge error in Kconfig
+  * ARM: IMX51: Changed from snd_card_new to snd_card_create
+
+  [ Dinh Nguyen ]
+
+  * ARM: IMX51: Fix plat-mxc/timer.c to handle imx51
+  * ARM: IMX51: Minimal changes for USB to work on 2.6.31
+  * ARM: IMX51: Babbage 2.5 needs a different system revision
+  * ARM: IMX51: IPU irq handler deadlock fix
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CONFIG_CAN=m
+    - LP: #327243
+  * [Config] Enabled CONFIG_SERIAL=m
+    - LP: #397189
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 24 Jul 2009 06:19:10 -0600
+
+linux (2.6.31-4.21) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * dm-raid-4-5: Add missing brackets around test_bit()
+
+  [ John Johansen ]
+
+  * AppArmor: Fix change_profile failing lpn401931
+  * AppArmor: Fix determination of forced AUDIT messages.
+  * AppArmor: Fix oops in auditing of the policy interface offset
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 19:18:30 +0100
+
+linux (2.6.31-4.20) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: iscsitarget -- update to SVN revision r214
+  * SAUCE: iscsitarget -- renable driver
+  * [Config] consolidate lpia/lpia and i386/generic configs
+  * [Config] enable CRYPTO modules for all architectures
+  * [Config] enable cryptoloop
+  * [Config] enable various filesystems for armel
+  * [Config] sync i386 generic and generic-pae
+  * [Config] add the 386 (486 processors and above) flavour
+  * [Config] re-set DEFAULT_MMAP_MIN_ADDR
+    - LP: #399914
+  * add genconfigs/genportsconfigs to extract the built configs
+  * updateconfigs -- alter concatenation order allow easier updates
+  * intelfb -- INTELFB now conflicts with DRM_I915
+  * printchanges -- rebase tree does not have stable tags use changelog
+  * AppArmor: fix argument size missmatch on 64 bit builds
+
+  [ Ike Panhc ]
+
+  * Ship bnx2x firmware in nic-modules udeb
+    - LP: #360966
+
+  [ Jeff Mahoney ]
+
+  * AppArmor: fix build failure on ia64
+
+  [ John Johansen ]
+
+  * AppArmour: ensure apparmor enabled parmater is off if AppArmor fails to
+    initialize.
+  * AppArmour: fix auditing of domain transitions to include target profile
+    information
+  * AppArmor: fix C99 violation
+  * AppArmor: revert reporting of create to write permission.
+  * SAUCE: Add config option to set a default LSM
+  * [Config] enable AppArmor by default
+  * AppArmor: Fix NULL pointer dereference oops in profile attachment.
+
+  [ Keith Packard ]
+
+  * SAUCE: drm/i915: Allow frame buffers up to 4096x4096 on 915/945 class
+    hardware
+    - LP: #351756
+
+  [ Luke Yelavich ]
+
+  * [Config] add .o files found in arch/powerpc/lib to all powerpc kernel
+    header packages
+    - LP: #355344
+
+  [ Michael Casadevall ]
+
+  * [Config] update SPARC config files to allow success build
+
+  [ Scott James Remnant ]
+
+  * SAUCE: trace: add trace_event for the open() syscall
+
+  [ Stefan Bader ]
+
+  * SAUCE: jfs: Fix early release of acl in jfs_get_acl
+    - LP: #396780
+
+  [ Tim Gardner ]
+
+  * [Upstream] Fix Soltech TA12 volume hotkeys not sending key release
+    - LP: #397499
+  * [Upstream] USB Option driver - Add USB ID for Novatel MC727/U727/USB727
+    refresh
+    - LP: #365291
+  * [Config] SSB/B44 are common across all arches/flavours.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc4
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 08:41:39 +0100
+
+linux (2.6.31-3.19) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Config] Disabled NDISWRAPPER"
+  * ndiswrapper -- fix i386 compilation failures on cmpxchg8b
+  * AUFS -- export various core functions
+  * AUFS -- export various core functions -- fixes
+  * AUFS -- core filesystem
+  * AUFS -- track changes in v2.6.31
+  * [Config] Enable AUFS
+  * droppped 'iwl3945: do not send scan command if channel count zero' as it
+    is already upstream but failed to auto-drop on rebase.
+
+  [ Eric Paris ]
+
+  * SAUCE: fsnotify: use def_bool in kconfig instead of letting the user
+    choose
+  * SAUCE: inotify: check filename before dropping repeat events
+  * SAUCE: fsnotify: fix inotify tail drop check with path entries
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 14 Jul 2009 12:52:55 +0100
+
+linux (2.6.31-3.18) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "Add splice-2.6.23.patch from AUFS to export a symbol needed by
+    AUFS"
+  * Revert "Add put_filp.patch from AUFS to export a symbol needed by AUFS"
+  * Revert "Add sec_perm-2.6.24.patch from AUFS - export
+    security_inode_permission"
+  * clear out left over AUFS files and modifications
+
+  [ Luke Yelavich ]
+
+  * [Config] Enable CONFIG_USB_ISP116X_HCD on sparc
+  * SAUCE: Explicitly include header files to allow apparmor to build on
+    powerpc
+  * [Config] Enable CONFIG_BLK_DEV_IDECD on powerpc
+
+  [ Tim Gardner ]
+
+  * [Config] Dropped ubuntu/misc/wireless/acx
+  * [Config] Disabled NDISWRAPPER until the compile issues are fixed.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc3
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 18:59:33 +0100
+
+linux (2.6.31-2.17) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_BLK_DEV_CRYPTOLOOP=m for sparc
+  * compcache -- remove redundant Kconfig entries part 2
+  * compcache -- clean up CCFLAGS declarations
+  * [Config] enable AppArmor
+  * AppArmor: fix operator precidence issue in as_path_link
+
+  [ John Johansen ]
+
+  * AppArmor security module
+  * AppArmor: Correct mapping of file permissions.
+  * AppArmor: Turn auditing of ptrace on
+
+  [ Luke Yelavich ]
+
+  * [Config] disable CONFIG_DM_RAID45 on powerpc
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 15:02:05 +0100
+
+linux (2.6.31-2.16) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * compcache -- remove redundant Kconfig entries
+    added ignore and ignore.modules for all arches since the compcache update
+    changes the modules names as well as some compcache ABI values.
+
+  [ Manoj Iyer ]
+
+  * SAUCE: updated dm-raid45 module version to 2009.04.24 (2.6.30-rc3)
+  * SAUCE: update compcache version to 0.5.3
+
+  [ Tim Gardner ]
+
+  * [Config]: Fix sparc FTBS by adding ignore.modules
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 06 Jul 2009 13:35:29 -0600
+
+linux (2.6.31-2.15) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: default ATI Radeon KMS to off until userspace catches up
+  * [Config] Update configs following rebase to 2.6.31-rc2
+  * [Config] update ports configs following update to 2.6.31-rc2
+
+  [ Luke Yelavich ]
+
+  * [Config] powerpc - Disable CONFIG_RDS
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to mainline 2.6.31-rc2
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 04 Jul 2009 17:39:13 +0100
+
+linux (2.6.31-1.14) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update ndiswrapper to 1.55
+  * remove leftovers of gfs
+  * [Config] powerpc: enable CONFIG_PPC_DISABLE_WERROR
+
+  [ Luke Yelavich ]
+
+  * [Config] re-enable and build the ide-pmac driver into powerpc kernels
+  * [Config] Build the ServerWorks Frodo / Apple K2 SATA driver into the
+    kernel
+
+  [ Manoj Iyer ]
+
+  * Remove snd-bt-sco ubuntu driver
+
+  [ Michael Casadevall ]
+
+  * [Config] updates ia64 config and d-i folders to allow succesful build
+  * [Config] Update powerpc and sparc for 2.6.31
+
+  [ Upstream Kernel Changes ]
+
+  * intel-iommu: fix Identity Mapping to be arch independent
+    - LP: #384695
+  * ACPI: video: prevent NULL deref in acpi_get_pci_dev()
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 30 Jun 2009 17:47:32 +0100
+
+linux (2.6.31-1.13) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * REBASE: rebased to mainline 2.6.31-rc1
+    - "UBUNTU: SAUCE: UHCI USB quirk for resume"
+      no longer applies, using deprecated interfaces, LPIA only, dropped
+    - "UBUNTU: SAUCE: Mask off garbage in Dell WMI scan code data"
+      changes now upstream, dropped
+  * [Config] Update configs following rebase to 2.6.31-rc1
+  * [Config] update ports configs following update to 2.6.31-rc1
+
+  * [Config] disable broken staging driver CONFIG_STLC45XX
+  * SAUCE: fix compcache to use updates accessors
+  * [Config] disable staging driver CONFIG_VT6655
+  * SAUCE: fix DRDB to use updates accessors
+  * [Disable] ndiswrapper needs update
+  * [Disable] LIRC I2C needs update
+  * [Disable] CONFIG_LENOVO_SL_LAPTOP needs update
+  * [Config] disable I2C_DESIGNWARE does not compile
+  * [Config] disable CONFIG_TLSUP for lpia
+  * [Config] disable CONFIG_FB_UDL for arm
+  * SAUCE: disable adding scsi headers to linux-libc-dev
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Add LIRC drivers
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 25 Jun 2009 12:06:22 +0100
+
+linux (2.6.30-10.12) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] split out the ports configs into their own family
+  * [Config] update configs following introduction of ports family
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "Rename linux-doc-PKGVER to linux-doc and clean up its
+    description". Fixes linux-doc package name conflicts for now.
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 22 Jun 2009 09:17:14 -0600
+
+linux (2.6.30-10.11) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Comment splitconfig.pl and misc cleanup
+  * [Config] Rename all configs to the new naming scheme
+  * [Config] Splitconfig rework
+  * [Config] Rename scripts/misc/oldconfig to kernelconfig
+  * [Config] Fix build system for new config split
+  * [Config] Run updateconfigs after the splitconfig rework
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: Default to i915.modeset=0 if CONFIG_DRM_I915_KMS=y"
+  * [Config] standardise CONFIG_STAGING=y
+  * [Config] standardise CONFIG_RD_LZMA=y
+  * [Config] CONFIG_PCI_IOV=y
+  * [Config] CONFIG_PCI_STUB=m
+  * [Config] merge kernel configs more agressively
+
+  [ Colin Watson ]
+
+  * [Config] Run kernel-wedge in $(builddir) rather than at the top level
+  * [Config] Add support for including firmware in udebs
+  * [Config] Ship bnx2 firmware in nic-modules udeb
+    - LP: #384861
+
+  [ Luke Yelavich ]
+
+  * [Config] ports - Import of ports architectures into kernel packaging
+    infrastructure
+  * [Config] ports - Do not update ports kernel configurations by default
+  * [Config] ports - Disable ABI checking for ports architectures
+  * [Config] ports - Build drivers in ubuntu sub-directory on powerpc
+  * [Config] ports - Add control.d/vars.* files for ports architectures
+  * [Config] ports - Add ports architectures for linux-libc-dev
+  * [Config] ports - Create powerpc specific message-modules and
+    block-modules udebs
+  * [Config] ports - Add configuration files for ports architectures
+
+  [ Manoj Iyer ]
+
+  * [Config] Enable CONFIG_BLK_DEV_AEC62XX=m for amd64 and i386
+    - LP: #329864
+
+  [ Michael Casadevall ]
+
+  * [Config] ports - Fix compression of kernels
+
+  [ Stefan Bader ]
+
+  * [Upstream] mmc: prevent dangling block device from accessing stale
+    queues
+    - LP: #383668
+
+  [ Tim Gardner ]
+
+  * [Config] Recommend grub-pc in linux-image
+    - LP: #385741
+  * [Config] Implement i386 generic and generic-pae flavours
+  * [Config] ports - Add control info after integrating ports arches
+  * [Config] Removed auto-generated files from git
+  * [Config] Added netxen_nic to nic-modules
+    - LP: #389603
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 15 Jun 2009 14:38:26 -0600
+
+linux (2.6.30-9.10) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_SECURITY_TOMOYO=y (amd64, i386, lpia)
+  * [Config] CONFIG_KEXEC_JUMP=y (amd64, lpia)
+  * [Config] CONFIG_LENOVO_SL_LAPTOP=m (amd64, lpia)
+  * [Config] CONFIG_POHMELFS_CRYPTO=y (i386, amd64)
+  * [Config] CONFIG_SERIAL_MAX3100=m (i386, amd64, lpia)
+  * [Config] CONFIG_VIDEO_GO7007=m (amd64, i386)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30 final
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 05 Jun 2009 11:42:53 +0100
+
+linux (2.6.30-8.9) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Config update removed the following options:
+        CONFIG_EDAC_AMD8111=m
+        CONFIG_EDAC_AMD8131=m
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc8
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 03 Jun 2009 09:21:13 +0100
+
+linux (2.6.30-7.8) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Enabled NEW configration options:
+      Paravirtualization layer for spinlocks (PARAVIRT_SPINLOCKS) [N/y/?] Y
+      Cisco FNIC Driver (FCOE_FNIC) [N/m/y/?] M
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc7
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 23 May 2009 23:47:24 +0100
+
+linux (2.6.30-6.7) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Dropped: UBUNTU: SAUCE: input: Blacklist digitizers from joydev.c (now
+    upstream)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc6
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 18 May 2009 18:05:54 +0100
+
+linux (2.6.30-5.6) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enable Keyspan USB serial device firmware in kernel module
+    - LP: #334285
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc5
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 11 May 2009 12:02:16 -0600
+
+linux (2.6.30-4.5) karmic; urgency=low
+
+  [ Colin Watson ]
+
+  * Build-Conflict with findutils (= 4.4.1-1ubuntu1), to avoid
+    /usr/include/asm/* going missing
+    - LP: #373214
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 May 2009 11:09:08 +0200
+
+linux (2.6.30-3.4) karmic; urgency=low
+
+  [ Kees Cook ]
+
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+
+  [ Stefan Bader ]
+
+  * SAUCE: input: Blacklist digitizers from joydev.c
+    - LP: #300143
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 01 May 2009 14:00:42 -0600
+
+linux (2.6.30-2.3) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CC_STACKPROTECTOR=y for all x86en
+    - LP: #369152
+  * SAUCE: Default to i915_modeset=0 if CONFIG_DRM_I915_KMS=y
+  * [Config] CONFIG_DRM_I915_KMS=y
+  * [Config] Set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR to appropriate ARCH
+    minimums
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc4
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 30 Apr 2009 09:17:05 -0600
+
+linux (2.6.30-1.2) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] armel: disable staging drivers, fixes FTBS
+  * [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS
+
+  [ Upstream Kernel Changes ]
+
+  * mpt2sas: Change reset_type enum to avoid namespace collision.
+    Submitted upstream.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 28 Apr 2009 16:54:41 -0600
+
+linux (2.6.30-1.1) karmic; urgency=low
+
+  * Initial release after rebasing against v2.6.30-rc3
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 12 Mar 2009 19:16:07 -0600
--- linux-ec2-2.6.32.orig/debian/debian.env
+++ linux-ec2-2.6.32/debian/debian.env
@@ -0,0 +1 @@
+DEBIAN=debian.ec2
--- linux-ec2-2.6.32.orig/debian/rules
+++ linux-ec2-2.6.32/debian/rules
@@ -0,0 +1,226 @@
+#!/usr/bin/make -f
+#
+# $(DEBIAN)/rules for Ubuntu linux
+#
+# Use this however you want, just give credit where credit is due.
+#
+# Copyright (c) 2007 Ben Collins <bcollins@ubuntu.com>
+#
+
+DEBIAN=$(shell awk -F= '($$1 == "DEBIAN") { print $$2 }' <debian/debian.env)
+
+# dpkg-buildpackage passes options that are incomptatible
+# with the kernel build.
+unexport CFLAGS
+unexport LDFLAGS
+
+export LC_ALL=C
+export SHELL=/bin/bash -e
+
+# Where do we find the common configuration.
+export DROOT=debian
+
+# Common variables for all architectures
+include $(DROOT)/rules.d/0-common-vars.mk
+
+# Pull in some arch specific stuff
+-include $(DEBIAN)/rules.d/$(arch).mk
+
+# Maintainer targets
+include $(DROOT)/rules.d/1-maintainer.mk
+
+# Debian Build System targets
+binary: binary-indep binary-arch
+
+build: build-arch build-indep
+
+clean: debian/control
+	dh_testdir
+	dh_testroot
+	dh_clean
+
+	# d-i stuff
+	rm -rf $(DEBIAN)/d-i-$(arch)
+
+	# normal build junk
+	rm -rf $(DEBIAN)/abi/$(release)-$(revision)
+	rm -rf $(builddir)
+	rm -f $(stampdir)/stamp-*
+	rm -rf $(DEBIAN)/linux-*
+
+	# This gets rid of the d-i packages in control
+	cp -f $(DEBIAN)/control.stub $(DEBIAN)/control
+	cp $(DEBIAN)/changelog debian/changelog
+
+	# Install the copyright information.
+	cp $(DEBIAN)/copyright debian/copyright
+
+distclean: clean
+	rm -rf $(DEBIAN)/control $(DEBIAN)/control.stub \
+		$(DEBIAN)/d-i/kernel-versions debian/changelog \
+		debian/control debian/control.stub debian/copyright
+
+# Builds the image, arch headers and debug packages
+include $(DROOT)/rules.d/2-binary-arch.mk
+
+# Rules for building the udebs ($(DEBIAN)-installer)
+include $(DROOT)/rules.d/5-udebs.mk
+
+# Builds the source, doc and linux-headers indep packages
+include $(DROOT)/rules.d/3-binary-indep.mk
+
+# Various checks to be performed on builds
+include $(DROOT)/rules.d/4-checks.mk
+
+# Misc stuff
+$(DEBIAN)/control.stub: $(DEBIAN)/d-i/kernel-versions.in	\
+		$(DROOT)/scripts/control-create		\
+		$(DEBIAN)/control.stub.in			\
+		$(DEBIAN)/changelog			\
+		$(wildcard $(DEBIAN)/control.d/* $(DEBIAN)/sub-flavours/*.vars)
+	for i in $(DEBIAN)/d-i/kernel-versions.in $(DEBIAN)/control.stub.in; do	\
+	  new=`echo $$i | sed 's/\.in$$//'`;					\
+	  cat $$i | sed -e 's/PKGVER/$(release)/g'                              \
+	        -e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+	  > $$new;								\
+	done
+	flavours="$(wildcard $(DEBIAN)/control.d/vars.* $(DEBIAN)/sub-flavours/*.vars)";\
+	for i in $$flavours; do							\
+	  $(SHELL) $(DROOT)/scripts/control-create $$i |				\
+		sed -e 's/PKGVER/$(release)/g'                                  \
+		-e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+		>> $(DEBIAN)/control.stub;						\
+	done
+	cp $(DEBIAN)/control.stub $(DEBIAN)/control
+
+.PHONY: debian/control
+debian/control: $(DEBIAN)/control.stub
+	rm -rf $(builddir)/modules $(builddir)/firmware			\
+		$(builddir)/kernel-versions $(builddir)/package-list	\
+		$(builddir)/$(DEBIAN)
+	mkdir -p $(builddir)/modules/$(arch)/
+	cp $(DEBIAN)/d-i/modules/* $(builddir)/modules/$(arch)/
+	mkdir -p $(builddir)/firmware/$(arch)/
+	cp $(DEBIAN)/d-i/firmware/* $(builddir)/firmware/$(arch)/
+	cp $(DEBIAN)/d-i/package-list $(DEBIAN)/d-i/kernel-versions $(builddir)/
+	touch $(builddir)/modules/$(arch)/kernel-image
+	# kernel-wedge needs to poke around in $(DEBIAN)/
+	ln -nsf $(CURDIR)/debian $(builddir)/debian
+
+	# Some files may need to differ between architectures
+	if [ -d $(DEBIAN)/d-i/modules-$(arch) ]; then			\
+	    cp $(DEBIAN)/d-i/modules-$(arch)/* \
+		$(builddir)/modules/$(arch)/;				\
+	fi
+	if [ -d $(DEBIAN)/d-i/firmware-$(arch) ]; then			\
+	    cp $(DEBIAN)/d-i/firmware-$(arch)/* \
+		$(builddir)/firmware/$(arch)/;				\
+	fi
+
+	# Remove unwanted stuff for this architecture
+	if [ -r "$(DEBIAN)/d-i/exclude-modules.$(arch)" ]; then		\
+	    (cat $(DEBIAN)/d-i/exclude-modules.$(arch);			\
+	     ls $(builddir)/modules/$(arch)/) | sort | uniq -d |	\
+		(cd $(builddir)/modules/$(arch)/; xargs rm -f);		\
+	fi
+	if [ -r "$(DEBIAN)/d-i/exclude-firmware.$(arch)" ]; then		\
+	    (cat $(DEBIAN)/d-i/exclude-firmware.$(arch);			\
+	     ls $(builddir)/firmware/$(arch)/) | sort | uniq -d |	\
+		(cd $(builddir)/firmware/$(arch)/; xargs rm -f);	\
+	fi
+
+	# Per flavour module lists
+	flavour_modules=`ls $(DEBIAN)/d-i/modules.$(arch)-* 2>/dev/null`	\
+		|| true;						\
+	if [ "$$flavour_modules" != "" ]; then				\
+	    for flav in $$flavour_modules; do				\
+		name=`echo $$flav | sed 's/.*\/modules.$(arch)-//'`;	\
+		mkdir $(builddir)/modules/$(arch)-$$name;		\
+		(cd $(builddir)/modules/; tar cf - `cat ../$$flav`) |	\
+		    (cd $(builddir)/modules/$(arch)-$$name/; tar xf -);	\
+		touch $(builddir)/modules/$(arch)-$$name/kernel-image;	\
+	    done;							\
+	fi
+	flavour_firmware=`ls $(DEBIAN)/d-i/firmware.$(arch)-* 2>/dev/null`	\
+		|| true;						\
+	if [ "$$flavour_firmware" != "" ]; then				\
+	    for flav in $$flavour_firmware; do				\
+		name=`echo $$flav | sed 's/.*\/firmware.$(arch)-//'`;	\
+		mkdir $(builddir)/firmware/$(arch)-$$name;		\
+		(cd $(builddir)/firmware/; tar cf - `cat ../$$flav`) |	\
+		    (cd $(builddir)/firmware/$(arch)-$$name/; tar xf -);\
+		touch $(builddir)/firmware/$(arch)-$$name/kernel-image;	\
+	    done;							\
+	fi
+
+	# Some files may need to differ between flavours
+	flavour_module_dirs=`ls -d $(DEBIAN)/d-i/modules-$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_module_dirs" ]; then				\
+	    for flav in $$flavour_module_dirs; do			\
+		name=`echo $$flav | sed 's/.*\/modules-$(arch)-//'`;	\
+		[ -d $(builddir)/modules/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/modules/$(arch)			\
+			modules/$(arch)-$$name;				\
+		cp $$flav/* $(builddir)/modules/$(arch)-$$name/;	\
+	    done;							\
+	fi
+	flavour_firmware_dirs=`ls -d $(DEBIAN)/d-i/firmware-$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_firmware_dirs" ]; then				\
+	    for flav in $$flavour_firmware_dirs; do			\
+		name=`echo $$flav | sed 's/.*\/firmware-$(arch)-//'`;	\
+		[ -d $(builddir)/firmware/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/firmware/$(arch)			\
+			firmware/$(arch)-$$name;			\
+		cp $$flav/* $(builddir)/firmware/$(arch)-$$name/;	\
+	    done;							\
+	fi
+
+	# Remove unwanted stuff for each flavour
+	flavour_exclude=`ls $(DEBIAN)/d-i/exclude-modules.$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_exclude" ]; then				\
+	    for flav in $$flavour_exclude; do				\
+		name=`echo $$flav | sed 's/.*\/exclude-modules.$(arch)-//'`;\
+		[ -d $(builddir)/modules/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/modules/$(arch) 			\
+			$(builddir)/modules/$(arch)-$$name;		\
+		(cat $$flav;						\
+		 ls $(builddir)/modules/$(arch)-$$name) |		\
+		 sort |	uniq -d |					\
+		    (cd $(builddir)/modules/$(arch)-$$name/;		\
+		     xargs rm -f);					\
+	    done;							\
+	fi
+	flavour_exclude=`ls $(DEBIAN)/d-i/exclude-firmware.$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_exclude" ]; then				\
+	    for flav in $$flavour_exclude; do				\
+		name=`echo $$flav | sed 's/.*\/exclude-firmware.$(arch)-//'`;\
+		[ -d $(builddir)/firmware/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/firmware/$(arch) 			\
+			$(builddir)/firmware/$(arch)-$$name;		\
+		(cat $$flav;						\
+		 ls $(builddir)/firmware/$(arch)-$$name) |		\
+		 sort |	uniq -d |					\
+		    (cd $(builddir)/firmware/$(arch)-$$name/;		\
+		     xargs rm -f);					\
+	    done;							\
+	fi
+
+	if [ ! -d $(builddir)/modules/$(build_arch) ]; then		\
+		mkdir -p $(builddir)/modules/$(build_arch);		\
+		cp $(builddir)/modules/$(arch)/*			\
+			$(builddir)/modules/$(build_arch);		\
+	fi
+	if [ ! -d $(builddir)/firmware/$(build_arch) ]; then		\
+		mkdir -p $(builddir)/firmware/$(build_arch);		\
+		cp $(builddir)/firmware/$(arch)/*			\
+			$(builddir)/firmware/$(build_arch);		\
+	fi
+
+	cp $(DEBIAN)/control.stub debian/control.stub
+	cd $(builddir) && kernel-wedge gen-control > $(CURDIR)/debian/control
--- linux-ec2-2.6.32.orig/debian/control
+++ linux-ec2-2.6.32/debian/control
@@ -0,0 +1,112 @@
+Source: linux-ec2
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.8.4.0
+Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], gawk
+Build-Depends-Indep: xmlto, docbook-utils, ghostscript, transfig, bzip2, sharutils
+Build-Conflicts: findutils (= 4.4.1-1ubuntu1)
+Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-karmic.git
+
+Package: linux-ec2-source-2.6.32
+Architecture: all
+Section: devel
+Priority: optional
+Provides: linux-ec2-source, linux-ec2-source-2.6
+Depends: ${misc:Depends}, binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version 2.6.32 with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ 2.6.32.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: linux-ec2-doc
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Conflicts: linux-ec2-doc-2.6
+Replaces: linux-ec2-doc-2.6
+Description: Linux kernel specific documentation for version 2.6.32
+ This package provides the various documents in the 2.6.32 kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/linux-ec2-doc/00-INDEX for a list of what is
+ contained in each file.
+
+Package: linux-headers-2.6.32-317
+Architecture: all
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0)
+#Provides: linux-headers, linux-headers-2.6
+Description: Header files related to Linux kernel version 2.6.32
+ This package provides kernel header files for version 2.6.32, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details
+
+
+Package: linux-image-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9
+Depends: ${misc:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1)
+Recommends: 
+Suggests: fdutils, linux-ec2-doc-2.6.32 | linux-ec2-source-2.6.32
+Description: Linux kernel image for version 2.6.32 on x86/x86_64
+ This package contains the Linux kernel image for version 2.6.32 on
+ x86/x86_64.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Generic processors.
+ .
+ Geared toward desktop systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-ec2 meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.32-317, ${shlibs:Depends}
+Description: Linux kernel headers for version 2.6.32 on x86/x86_64
+ This package provides kernel header files for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details.
+
+Package: linux-image-2.6.32-317-ec2-dbgsym
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version 2.6.32 on x86/x86_64
+ This package provides a kernel debug image for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
--- linux-ec2-2.6.32.orig/debian/compat
+++ linux-ec2-2.6.32/debian/compat
@@ -0,0 +1 @@
+5
--- linux-ec2-2.6.32.orig/debian/control.stub
+++ linux-ec2-2.6.32/debian/control.stub
@@ -0,0 +1,112 @@
+Source: linux-ec2
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.8.4.0
+Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], gawk
+Build-Depends-Indep: xmlto, docbook-utils, ghostscript, transfig, bzip2, sharutils
+Build-Conflicts: findutils (= 4.4.1-1ubuntu1)
+Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-karmic.git
+
+Package: linux-ec2-source-2.6.32
+Architecture: all
+Section: devel
+Priority: optional
+Provides: linux-ec2-source, linux-ec2-source-2.6
+Depends: ${misc:Depends}, binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version 2.6.32 with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ 2.6.32.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: linux-ec2-doc
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Conflicts: linux-ec2-doc-2.6
+Replaces: linux-ec2-doc-2.6
+Description: Linux kernel specific documentation for version 2.6.32
+ This package provides the various documents in the 2.6.32 kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/linux-ec2-doc/00-INDEX for a list of what is
+ contained in each file.
+
+Package: linux-headers-2.6.32-317
+Architecture: all
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0)
+#Provides: linux-headers, linux-headers-2.6
+Description: Header files related to Linux kernel version 2.6.32
+ This package provides kernel header files for version 2.6.32, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details
+
+
+Package: linux-image-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9
+Depends: ${misc:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1)
+Recommends: 
+Suggests: fdutils, linux-ec2-doc-2.6.32 | linux-ec2-source-2.6.32
+Description: Linux kernel image for version 2.6.32 on x86/x86_64
+ This package contains the Linux kernel image for version 2.6.32 on
+ x86/x86_64.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Generic processors.
+ .
+ Geared toward desktop systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-ec2 meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.32-317, ${shlibs:Depends}
+Description: Linux kernel headers for version 2.6.32 on x86/x86_64
+ This package provides kernel header files for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details.
+
+Package: linux-image-2.6.32-317-ec2-dbgsym
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version 2.6.32 on x86/x86_64
+ This package provides a kernel debug image for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
--- linux-ec2-2.6.32.orig/debian/copyright
+++ linux-ec2-2.6.32/debian/copyright
@@ -0,0 +1,30 @@
+This is the Ubuntu prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
+and others.
+
+This package was put together by the Ubuntu Kernel Team, from
+sources retrieved from upstream linux git.
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package is currently maintained by the
+Ubuntu Kernel Team <ubuntu-kernel@lists.ubuntu.com>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   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.
+
+On Ubuntu Linux systems, the complete text of the GNU General
+Public License v2 can be found in `/usr/share/common-licenses/GPL-2'.
--- linux-ec2-2.6.32.orig/debian/rules.d/5-udebs.mk
+++ linux-ec2-2.6.32/debian/rules.d/5-udebs.mk
@@ -0,0 +1,38 @@
+# Do udebs if not disabled in the arch-specific makefile
+binary-udebs: binary-debs debian/control
+ifeq ($(disable_d_i),)
+	@$(MAKE) --no-print-directory -f $(DROOT)/rules DEBIAN=$(DEBIAN) \
+		do-binary-udebs
+endif
+
+do-binary-udebs:
+	dh_testdir
+	dh_testroot
+
+	# unpack the kernels into a temporary directory
+	mkdir -p debian/d-i-${arch}
+
+	imagelist=$$(cat $(builddir)/kernel-versions | grep ^${arch} | awk '{print $$4}') && \
+	for i in $$imagelist; do \
+	  dpkg -x $$(ls ../linux-image-$$i\_$(release)-$(revision)_${arch}.deb) \
+		debian/d-i-${arch}; \
+	  /sbin/depmod -b debian/d-i-${arch} $$i; \
+	done
+
+	# kernel-wedge will error if no modules unless this is touched
+	touch $(CURDIR)/debian/build/no-modules
+
+	touch ignore-dups
+	export SOURCEDIR=$(CURDIR)/debian/d-i-${arch} && \
+	  cd $(builddir) && \
+	  kernel-wedge install-files && \
+	  kernel-wedge check
+
+        # Build just the udebs
+	dilist=$$(dh_listpackages -s | grep "\-di$$") && \
+	[ -z "$dilist" ] || \
+	for i in $$dilist; do \
+	  dh_fixperms -p$$i; \
+	  dh_gencontrol -p$$i; \
+	  dh_builddeb -p$$i; \
+	done
--- linux-ec2-2.6.32.orig/debian/rules.d/2-binary-arch.mk
+++ linux-ec2-2.6.32/debian/rules.d/2-binary-arch.mk
@@ -0,0 +1,392 @@
+# We don't want make removing intermediary stamps
+.SECONDARY :
+
+# Prepare the out-of-tree build directory
+ifeq ($(do_full_source),true)
+build_cd = cd $(builddir)/build-$*; #
+build_O  =
+else
+build_cd =
+build_O  = O=$(builddir)/build-$*
+endif
+
+prepare-%: $(stampdir)/stamp-prepare-%
+	@# Empty for make to be happy
+$(stampdir)/stamp-prepare-%: $(stampdir)/stamp-prepare-tree-% prepare-checks-%
+	@touch $@
+$(stampdir)/stamp-prepare-tree-%: target_flavour = $*
+$(stampdir)/stamp-prepare-tree-%: $(commonconfdir)/config.common.$(family) $(archconfdir)/config.common.$(arch) $(archconfdir)/config.flavour.%
+	@echo "Preparing $*..."
+	install -d $(builddir)/build-$*
+	touch $(builddir)/build-$*/ubuntu-build
+	[ "$(do_full_source)" != 'true' ] && true || \
+		rsync -a --exclude debian --exclude debian.master --exclude $(DEBIAN) * $(builddir)/build-$*
+	cat $^ | sed -e 's/.*CONFIG_VERSION_SIGNATURE.*/CONFIG_VERSION_SIGNATURE="Ubuntu $(release)-$(revision)-$* $(release)$(extraversion)"/' > $(builddir)/build-$*/.config
+	find $(builddir)/build-$* -name "*.ko" | xargs rm -f
+	$(build_cd) $(kmake) $(build_O) silentoldconfig prepare scripts
+	touch $@
+
+# Do the actual build, including image and modules
+build-%: $(stampdir)/stamp-build-%
+	@# Empty for make to be happy
+$(stampdir)/stamp-build-%: target_flavour = $*
+$(stampdir)/stamp-build-%: prepare-%
+	@echo "Building $*..."
+	$(build_cd) $(kmake) $(build_O) $(conc_level) $(build_image)
+	$(build_cd) $(kmake) $(build_O) $(conc_level) modules
+	@touch $@
+
+# Install the finished build
+install-%: pkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*
+install-%: bindoc = $(pkgdir)/usr/share/doc/$(bin_pkg_name)-$*
+install-%: dbgpkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*-dbgsym
+install-%: basepkg = $(hdrs_pkg_name)
+install-%: hdrdir = $(CURDIR)/debian/$(basepkg)-$*/usr/src/$(basepkg)-$*
+install-%: target_flavour = $*
+install-%: $(stampdir)/stamp-build-% checks-%
+	dh_testdir
+	dh_testroot
+	dh_clean -k -p$(bin_pkg_name)-$*
+	dh_clean -k -p$(hdrs_pkg_name)-$*
+	dh_clean -k -p$(dbg_pkg_name)-$*
+
+	# The main image
+	# compress_file logic required because not all architectures
+	# generate a zImage automatically out of the box
+ifeq ($(compress_file),)
+	install -m644 -D $(builddir)/build-$*/$(kernel_file) \
+		$(pkgdir)/boot/$(install_file)-$(abi_release)-$*
+else
+	install -d $(pkgdir)/boot
+	gzip -c9v $(builddir)/build-$*/$(kernel_file) > \
+		$(pkgdir)/boot/$(install_file)-$(abi_release)-$*
+	chmod 644 $(pkgdir)/boot/$(install_file)-$(abi_release)-$*
+endif
+
+	install -m644 $(builddir)/build-$*/.config \
+		$(pkgdir)/boot/config-$(abi_release)-$*
+	install -m644 $(abidir)/$* \
+		$(pkgdir)/boot/abi-$(abi_release)-$*
+	install -m644 $(builddir)/build-$*/System.map \
+		$(pkgdir)/boot/System.map-$(abi_release)-$*
+ifeq ($(no_dumpfile),)
+	makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \
+		-x $(builddir)/build-$*/vmlinux
+endif
+
+	$(build_cd) $(kmake) $(build_O) modules_install \
+		INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$(pkgdir)/ \
+		INSTALL_FW_PATH=$(pkgdir)/lib/firmware/$(abi_release)-$*
+
+	#
+	# Remove all modules not in the inclusion list.
+	#
+	if [ -f $(DEBIAN)/control.d/$(target_flavour).inclusion-list ] ; then \
+		$(DROOT)/scripts/module-inclusion $(pkgdir)/lib/modules/$(abi_release)-$*/kernel \
+			$(DEBIAN)/control.d/$(target_flavour).inclusion-list 2>&1 | \
+				tee $(target_flavour).inclusion-list.log; \
+		/sbin/depmod -b $(pkgdir) -ea -F $(pkgdir)/boot/System.map-$(abi_release)-$* \
+			$(abi_release)-$* 2>&1 |tee $(target_flavour).depmod.log; \
+	fi
+
+ifeq ($(no_dumpfile),)
+	makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \
+		-x $(builddir)/build-$*/vmlinux
+endif
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/build
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/source
+
+	# Some initramfs-tools specific modules
+	install -d $(pkgdir)/lib/modules/$(abi_release)-$*/initrd
+	if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko ]; then\
+	  ln -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/initrd/; \
+	fi
+
+	# Now the image scripts
+	install -d $(pkgdir)/DEBIAN
+	for script in postinst postrm preinst prerm; do				\
+	  sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g'		\
+	      -e 's/=L/$(loader)/g'         -e 's@=B@$(build_arch)@g'		\
+	       $(DROOT)/control-scripts/$$script > $(pkgdir)/DEBIAN/$$script;	\
+	  chmod 755 $(pkgdir)/DEBIAN/$$script;					\
+	done
+
+	# Install the full changelog.
+ifeq ($(do_doc_package),true)
+	install -d $(bindoc)
+	cat $(DEBIAN)/changelog $(DEBIAN)/changelog.historical | \
+		gzip -9 >$(bindoc)/changelog.Debian.old.gz
+	chmod 644 $(bindoc)/changelog.Debian.old.gz
+endif
+
+ifneq ($(skipsub),true)
+	for sub in $($(*)_sub); do					\
+		if ! (TO=$$sub FROM=$* ABI_RELEASE=$(abi_release) $(SHELL)		\
+			$(DROOT)/scripts/sub-flavour); then exit 1; fi;		\
+		/sbin/depmod -b debian/$(bin_pkg_name)-$$sub		\
+			-ea -F debian/$(bin_pkg_name)-$$sub/boot/System.map-$(abi_release)-$* \
+			$(abi_release)-$*;					\
+		install -d debian/$(bin_pkg_name)-$$sub/DEBIAN;	\
+		for script in postinst postrm preinst prerm; do			\
+			sed -e 's/=V/$(abi_release)-$*/g'			\
+			    -e 's/=K/$(install_file)/g'				\
+			    -e 's/=L/$(loader)/g'				\
+			    -e 's@=B@$(build_arch)@g'				\
+				$(DROOT)/control-scripts/$$script >		\
+				debian/$(bin_pkg_name)-$$sub/DEBIAN/$$script;\
+			chmod 755  debian/$(bin_pkg_name)-$$sub/DEBIAN/$$script;\
+		done;								\
+	done
+endif
+
+ifneq ($(skipdbg),true)
+	# Debug image is simple
+	install -m644 -D $(builddir)/build-$*/vmlinux \
+		$(dbgpkgdir)/usr/lib/debug/boot/vmlinux-$(abi_release)-$*
+	$(build_cd) $(kmake) $(build_O) modules_install \
+		INSTALL_MOD_PATH=$(dbgpkgdir)/usr/lib/debug
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/build
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/source
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/modules.*
+	rm -fr $(dbgpkgdir)/usr/lib/debug/lib/firmware
+endif
+
+	# The flavour specific headers image
+	# TODO: Would be nice if we didn't have to dupe the original builddir
+	install -d -m755 $(hdrdir)
+	cat $(builddir)/build-$*/.config | \
+		sed -e 's/.*CONFIG_DEBUG_INFO=.*/# CONFIG_DEBUG_INFO is not set/g' > \
+		$(hdrdir)/.config
+	chmod 644 $(hdrdir)/.config
+	$(kmake) O=$(hdrdir) silentoldconfig prepare scripts
+	# We'll symlink this stuff
+	rm -f $(hdrdir)/Makefile
+	rm -rf $(hdrdir)/include2
+	# powerpc seems to need some .o files for external module linking. Add them in.
+ifeq ($(arch),powerpc)
+	mkdir -p $(hdrdir)/arch/powerpc/lib
+	cp $(builddir)/build-$*/arch/powerpc/lib/*.o $(hdrdir)/arch/powerpc/lib
+endif
+	# Script to symlink everything up
+	$(SHELL) $(DROOT)/scripts/link-headers "$(hdrdir)" "$(basepkg)" "$*"
+	# Setup the proper asm symlink
+	rm -f $(hdrdir)/include/asm
+	ln -s asm-$(asm_link) $(hdrdir)/include/asm
+	# The build symlink
+	install -d debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*
+	ln -s /usr/src/$(basepkg)-$* \
+		debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*/build
+	# And finally the symvers
+	install -m644 $(builddir)/build-$*/Module.symvers \
+		$(hdrdir)/Module.symvers
+
+	# Now the header scripts
+	install -d $(CURDIR)/debian/$(basepkg)-$*/DEBIAN
+	for script in postinst; do						\
+	  sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g'	\
+		$(DROOT)/control-scripts/headers-$$script > 			\
+			$(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script;		\
+	  chmod 755 $(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script;		\
+	done
+
+	# At the end of the package prep, call the tests
+	DPKG_ARCH="$(arch)" KERN_ARCH="$(build_arch)" FLAVOUR="$*"	\
+	 VERSION="$(abi_release)" REVISION="$(revision)"		\
+	 PREV_REVISION="$(prev_revision)" ABI_NUM="$(abinum)"		\
+	 PREV_ABI_NUM="$(prev_abinum)" BUILD_DIR="$(builddir)/build-$*"	\
+	 INSTALL_DIR="$(pkgdir)" SOURCE_DIR="$(CURDIR)"			\
+	 run-parts -v $(DROOT)/tests
+
+	#
+	# Remove files which are generated at installation by postinst,
+	# except for modules.order and modules.builtin
+	#
+	mkdir $(pkgdir)/lib/modules/$(abi_release)-$*/_
+	mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.order \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/_
+	if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin ] ; then \
+	    mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/_; \
+	fi
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.*
+	mv $(pkgdir)/lib/modules/$(abi_release)-$*/_/* \
+		$(pkgdir)/lib/modules/$(abi_release)-$*
+	rmdir $(pkgdir)/lib/modules/$(abi_release)-$*/_
+
+headers_tmp := $(CURDIR)/debian/tmp-headers
+headers_dir := $(CURDIR)/debian/linux-libc-dev
+
+hmake := $(MAKE) -C $(CURDIR) O=$(headers_tmp) SUBLEVEL=$(SUBLEVEL) \
+	EXTRAVERSION=-$(abinum) INSTALL_HDR_PATH=$(headers_tmp)/install \
+	SHELL="$(SHELL)" ARCH=$(header_arch)
+
+install-arch-headers:
+	dh_testdir
+	dh_testroot
+	dh_clean -k -plinux-libc-dev
+
+	rm -rf $(headers_tmp)
+	install -d $(headers_tmp) $(headers_dir)/usr/include/
+
+	$(hmake) $(defconfig)
+	mv $(headers_tmp)/.config $(headers_tmp)/.config.old
+	sed -e 's/^# \(CONFIG_MODVERSIONS\) is not set$$/\1=y/' \
+	  -e 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/' \
+	  $(headers_tmp)/.config.old > $(headers_tmp)/.config
+	$(hmake) silentoldconfig
+	$(hmake) headers_install
+
+	( cd $(headers_tmp)/install/include/ && \
+		find . -name '.' -o -name '.*' -prune -o -print | \
+                cpio -pvd --preserve-modification-time \
+			$(headers_dir)/usr/include/ )
+
+	rm -rf $(headers_tmp)
+
+binary-arch-headers: install-arch-headers
+	dh_testdir
+	dh_testroot
+ifeq ($(do_libc_dev_package),true)
+	dh_installchangelogs -plinux-libc-dev
+	dh_installdocs -plinux-libc-dev
+	dh_compress -plinux-libc-dev
+	dh_fixperms -plinux-libc-dev
+	dh_installdeb -plinux-libc-dev
+	dh_gencontrol -plinux-libc-dev
+	dh_md5sums -plinux-libc-dev
+	dh_builddeb -plinux-libc-dev
+endif
+
+binary-%: pkgimg = $(bin_pkg_name)-$*
+binary-%: pkghdr = $(hdrs_pkg_name)-$*
+binary-%: dbgpkg = $(bin_pkg_name)-$*-dbgsym
+binary-%: install-%
+	dh_testdir
+	dh_testroot
+
+	dh_installchangelogs -p$(pkgimg)
+	dh_installdocs -p$(pkgimg)
+	dh_compress -p$(pkgimg)
+	dh_fixperms -p$(pkgimg)
+	dh_installdeb -p$(pkgimg)
+	dh_shlibdeps -p$(pkgimg)
+	dh_gencontrol -p$(pkgimg)
+	dh_md5sums -p$(pkgimg)
+	dh_builddeb -p$(pkgimg) -- -Zbzip2 -z9
+
+	dh_installchangelogs -p$(pkghdr)
+	dh_installdocs -p$(pkghdr)
+	dh_compress -p$(pkghdr)
+	dh_fixperms -p$(pkghdr)
+	dh_shlibdeps -p$(pkghdr)
+	dh_installdeb -p$(pkghdr)
+	dh_gencontrol -p$(pkghdr)
+	dh_md5sums -p$(pkghdr)
+	dh_builddeb -p$(pkghdr)
+
+ifneq ($(skipsub),true)
+	@set -e; for sub in $($(*)_sub); do		\
+		pkg=$(bin_pkg_name)-$$sub;	\
+		dh_installchangelogs -p$$pkg;		\
+		dh_installdocs -p$$pkg;			\
+		dh_compress -p$$pkg;			\
+		dh_fixperms -p$$pkg;			\
+		dh_shlibdeps -p$$pkg;			\
+		dh_installdeb -p$$pkg;			\
+		dh_gencontrol -p$$pkg;			\
+		dh_md5sums -p$$pkg;			\
+		dh_builddeb -p$$pkg;			\
+	done
+endif
+
+ifneq ($(skipdbg),true)
+	dh_installchangelogs -p$(dbgpkg)
+	dh_installdocs -p$(dbgpkg)
+	dh_compress -p$(dbgpkg)
+	dh_fixperms -p$(dbgpkg)
+	dh_installdeb -p$(dbgpkg)
+	dh_gencontrol -p$(dbgpkg)
+	dh_md5sums -p$(dbgpkg)
+	dh_builddeb -p$(dbgpkg)
+
+	# Hokay...here's where we do a little twiddling...
+	# Renaming the debug package prevents it from getting into
+	# the primary archive, and therefore prevents this very large
+	# package from being mirrored. It is instead, through some
+	# archive admin hackery, copied to http://ddebs.ubuntu.com.
+	#
+	mv ../$(dbgpkg)_$(release)-$(revision)_$(arch).deb \
+		../$(dbgpkg)_$(release)-$(revision)_$(arch).ddeb
+	set -e; \
+	if grep -qs '^Build-Debug-Symbols: yes$$' /CurrentlyBuilding; then \
+		sed -i '/^$(dbgpkg)_/s/\.deb /.ddeb /' debian/files; \
+	else \
+		grep -v '^$(dbgpkg)_.*$$' debian/files > debian/files.new; \
+		mv debian/files.new debian/files; \
+	fi
+	# Now, the package wont get into the archive, but it will get put
+	# into the debug system.
+endif
+
+$(stampdir)/stamp-flavours:
+	@echo $(flavours) > $@
+
+#
+# per-architecture packages
+#
+$(stampdir)/stamp-prepare-perarch:
+	@echo "Preparing perarch ..."
+ifeq ($(do_tools),true)
+	install -d $(builddir)/tools-$*
+	for i in *; do ln -s $(CURDIR)/$$i $(builddir)/tools-$*/; done
+	rm $(builddir)/tools-$*/tools
+	rsync -a tools/ $(builddir)/tools-$*/tools/
+endif
+	touch $@
+
+$(stampdir)/stamp-build-perarch: prepare-perarch
+ifeq ($(do_tools),true)
+	cd $(builddir)/tools-$*/tools/perf && make
+endif
+	@touch $@
+
+install-perarch: toolspkgdir = $(CURDIR)/debian/$(tools_pkg_name)
+install-perarch: $(stampdir)/stamp-build-perarch
+	# Add the tools.
+ifeq ($(do_tools),true)
+	install -d $(toolspkgdir)/usr/bin
+	install -s -m755 $(builddir)/tools-$*/tools/perf/perf \
+		$(toolspkgdir)/usr/bin/perf_$(abi_release)
+endif
+
+binary-perarch: toolspkg = $(tools_pkg_name)
+binary-perarch: install-perarch
+	@# Empty for make to be happy
+ifeq ($(do_tools),true)
+	dh_installchangelogs -p$(toolspkg)
+	dh_installdocs -p$(toolspkg)
+	dh_compress -p$(toolspkg)
+	dh_fixperms -p$(toolspkg)
+	dh_shlibdeps -p$(toolspkg)
+	dh_installdeb -p$(toolspkg)
+	dh_gencontrol -p$(toolspkg)
+	dh_md5sums -p$(toolspkg)
+	dh_builddeb -p$(toolspkg)
+endif
+
+binary-debs: binary-perarch $(stampdir)/stamp-flavours $(addprefix binary-,$(flavours))
+
+build-arch:  $(addprefix build-,$(flavours))
+
+binary-arch-deps = binary-debs
+ifeq ($(AUTOBUILD),)
+binary-arch-deps += binary-udebs
+endif
+ifeq ($(do_libc_dev_package),true)
+binary-arch-deps += binary-arch-headers
+endif
+ifneq ($(do_common_headers_indep),true)
+binary-arch-deps += binary-headers
+endif
+binary-arch: $(binary-arch-deps)
--- linux-ec2-2.6.32.orig/debian/rules.d/4-checks.mk
+++ linux-ec2-2.6.32/debian/rules.d/4-checks.mk
@@ -0,0 +1,34 @@
+# Check ABI for package against last release (if not same abinum)
+abi-%: $(abidir)/%
+	@# Empty for make to be happy
+$(abidir)/%: $(stampdir)/stamp-build-%
+	install -d $(abidir)
+	sed -e 's/^\(.\+\)[[:space:]]\+\(.\+\)[[:space:]]\(.\+\)$$/\3 \2 \1/'	\
+		$(builddir)/build-$*/Module.symvers | sort > $@
+
+abi-check-%: $(abidir)/%
+	@perl -f $(DROOT)/scripts/abi-check "$*" "$(prev_abinum)" "$(abinum)" \
+		"$(prev_abidir)" "$(abidir)" "$(skipabi)"
+
+# Check the module list against the last release (always)
+module-%: $(abidir)/%.modules
+	@# Empty for make to be happy
+$(abidir)/%.modules: $(stampdir)/stamp-build-%
+	install -d $(abidir)
+	find $(builddir)/build-$*/ -name \*.ko | \
+		sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > $@
+
+module-check-%: $(abidir)/%.modules
+	@perl -f $(DROOT)/scripts/module-check "$*" \
+		"$(prev_abidir)" "$(abidir)" $(skipmodule)
+
+checks-%: abi-check-% module-check-%
+	@# Will be calling more stuff later
+
+# Check the config against the known options list.
+config-prepare-check-%: $(stampdir)/stamp-prepare-tree-%
+	@perl -f $(DROOT)/scripts/config-check \
+		$(builddir)/build-$*/.config "$(arch)" "$*" "$(sharedconfdir)" "$(skipconfig)"
+
+prepare-checks-%: config-prepare-check-%
+	@# Will be calling more stuff later
--- linux-ec2-2.6.32.orig/debian/rules.d/0-common-vars.mk
+++ linux-ec2-2.6.32/debian/rules.d/0-common-vars.mk
@@ -0,0 +1,182 @@
+#
+# The source package name will be the first token from $(DEBIAN)/changelog
+#
+src_pkg_name=$(shell sed -n '1s/^\(.*\) (.*).*$$/\1/p' $(DEBIAN)/changelog)
+
+# Get some version info
+series := lucid
+release := $(shell sed -n '1s/^$(src_pkg_name).*(\(.*\)-.*).*$$/\1/p' $(DEBIAN)/changelog)
+revisions := $(shell sed -n 's/^$(src_pkg_name)\ .*($(release)-\(.*\)).*$$/\1/p' $(DEBIAN)/changelog | tac)
+revision ?= $(word $(words $(revisions)),$(revisions))
+prev_revisions := $(filter-out $(revision),0.0 $(revisions))
+prev_revision := $(word $(words $(prev_revisions)),$(prev_revisions))
+
+family=ubuntu
+
+# This is an internally used mechanism for the daily kernel builds. It
+# creates packages whose ABI is suffixed with a minimal representation of
+# the current git HEAD sha. If .git/HEAD is not present, then it uses the
+# uuidgen program,
+#
+# AUTOBUILD can also be used by anyone wanting to build a custom kernel
+# image, or rebuild the entire set of Ubuntu packages using custom patches
+# or configs.
+AUTOBUILD=
+
+#
+# This is a way to support some external variables. A good example is
+# a local setup for ccache and distcc See LOCAL_ENV_CC and
+# LOCAL_ENV_DISTCC_HOSTS in the definition of kmake.
+# For example:
+#      LOCAL_ENV_CC="ccache distcc"
+#      LOCAL_ENV_DISTCC_HOSTS="localhost 10.0.2.5 10.0.2.221"
+#
+-include $(CURDIR)/../.$(series)-env
+
+ifneq ($(AUTOBUILD),)
+skipabi		= true
+skipmodule	= true
+skipdbg		= true
+gitver=$(shell if test -f .git/HEAD; then cat .git/HEAD; else uuidgen; fi)
+gitverpre=$(shell echo $(gitver) | cut -b -3)
+gitverpost=$(shell echo $(gitver) | cut -b 38-40)
+abi_suffix = -$(gitverpre)$(gitverpost)
+endif
+
+ifneq ($(NOKERNLOG),)
+ubuntu_log_opts += --no-kern-log
+endif
+ifneq ($(PRINTSHAS),)
+ubuntu_log_opts += --print-shas
+endif
+
+# Get the kernels own extra version to be added to the release signature.
+extraversion=$(shell awk '/EXTRAVERSION =/ { print $$3 }' <Makefile)
+
+#
+# full_build -- are we doing a full buildd style build
+#
+ifeq ($(wildcard /CurrentlyBuilding),)
+full_build?=false
+else
+full_build?=true
+endif
+
+#
+# The debug packages are ginormous, so you probably want to skip
+# building them (as a developer).
+#
+ifeq ($(full_build),false)
+skipdbg=true
+endif
+
+abinum		:= $(shell echo $(revision) | sed -e 's/\..*//')$(abi_suffix)
+prev_abinum	:= $(shell echo $(prev_revision) | sed -e 's/\..*//')$(abi_suffix)
+abi_release	:= $(release)-$(abinum)
+
+uploadnum	:= $(shell echo $(revision) | sed -e 's/.*\.//')
+ifneq ($(full_build),false)
+  uploadnum	:= $(uploadnum)-Ubuntu
+endif
+
+# We force the sublevel to be exactly what we want. The actual source may
+# be an in development git tree. We want to force it here instead of
+# committing changes to the top level Makefile
+SUBLEVEL	:= $(shell echo $(release) | awk -F. '{print $$3}')
+
+arch		:= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+abidir		:= $(CURDIR)/$(DEBIAN)/abi/$(release)-$(revision)/$(arch)
+prev_abidir	:= $(CURDIR)/$(DEBIAN)/abi/$(release)-$(prev_revision)/$(arch)
+commonconfdir	:= $(CURDIR)/$(DEBIAN)/config
+archconfdir	:= $(CURDIR)/$(DEBIAN)/config/$(arch)
+sharedconfdir	:= $(CURDIR)/debian.master/config
+builddir	:= $(CURDIR)/debian/build
+stampdir	:= $(CURDIR)/debian/stamps
+
+#
+# The binary package name always starts with linux-image-$KVER-$ABI.$UPLOAD_NUM. There
+# are places that you'll find linux-image hard coded, but I guess thats OK since the
+# assumption that the binary package always starts with linux-image will never change.
+#
+bin_pkg_name=linux-image-$(abi_release)
+hdrs_pkg_name=linux-headers-$(abi_release)
+#
+# The generation of content in the doc package depends on both 'AUTOBUILD=' and
+# 'do_doc_package_content=true'. There are usually build errors during the development
+# cycle, so its OK to leave 'do_doc_package_content=false' until those build
+# failures get sorted out. Finally, the doc package doesn't really need to be built
+# for developer testing (its kind of slow), so only do it if on a buildd.
+do_doc_package=true
+do_doc_package_content=true
+ifeq ($(full_build),false)
+do_doc_package_content=false
+endif
+doc_pkg_name=$(src_pkg_name)-doc
+
+#
+# Similarly with the linux-source package, you need not build it as a developer. Its
+# somewhat I/O intensive and utterly useless.
+#
+do_source_package=true
+do_source_package_content=true
+ifeq ($(full_build),false)
+do_source_package_content=false
+endif
+
+# linux-libc-dev may not be needed, default to building it.
+do_libc_dev_package=true
+
+# common headers normally is built as an indep package, but may be arch
+do_common_headers_indep=true
+
+# add a 'full source' mode
+do_full_source=false
+
+# build tools
+ifneq ($(wildcard $(CURDIR)/tools),)
+do_tools?=true
+else
+do_tools?=false
+endif
+tools_pkg_name=$(src_pkg_name)-tools-$(abi_release)
+tools_common_pkg_name=$(src_pkg_name)-tools-common
+
+# Support parallel=<n> in DEB_BUILD_OPTIONS (see #209008)
+#
+# These 2 environment variables set the -j value of the kernel build. For example,
+# CONCURRENCY_LEVEL=16 fakeroot $(DEBIAN)/rules binary-debs
+# or
+# DEB_BUILD_OPTIONS=parallel=16 fakeroot $(DEBIAN)/rules binary-debs
+#
+# The default is to use the number of CPUs.
+#
+COMMA=,
+DEB_BUILD_OPTIONS_PARA = $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
+ifneq (,$(DEB_BUILD_OPTIONS_PARA))
+  CONCURRENCY_LEVEL := $(DEB_BUILD_OPTIONS_PARA)
+endif
+
+ifeq ($(CONCURRENCY_LEVEL),)
+  # Check the environment
+  CONCURRENCY_LEVEL := $(shell echo $$CONCURRENCY_LEVEL)
+  # No? Then build with the number of CPUs on the host.
+  ifeq ($(CONCURRENCY_LEVEL),)
+      CONCURRENCY_LEVEL := $(shell expr `getconf _NPROCESSORS_ONLN` \* 1)
+  endif
+  # Oh hell, give 'em one
+  ifeq ($(CONCURRENCY_LEVEL),)
+    CONCURRENCY_LEVEL := 1
+  endif
+endif
+
+conc_level		= -j$(CONCURRENCY_LEVEL)
+
+# target_flavour is filled in for each step
+kmake = make ARCH=$(build_arch) \
+	EXTRAVERSION=-$(abinum)-$(target_flavour) \
+	CONFIG_DEBUG_SECTION_MISMATCH=y SUBLEVEL=$(SUBLEVEL) \
+	KBUILD_BUILD_VERSION="$(uploadnum)" \
+	LOCALVERSION=
+ifneq ($(LOCAL_ENV_CC),)
+kmake += CC=$(LOCAL_ENV_CC) DISTCC_HOSTS=$(LOCAL_ENV_DISTCC_HOSTS)
+endif
--- linux-ec2-2.6.32.orig/debian/rules.d/1-maintainer.mk
+++ linux-ec2-2.6.32/debian/rules.d/1-maintainer.mk
@@ -0,0 +1,137 @@
+# The following targets are for the maintainer only! do not run if you don't
+# know what they do.
+
+.PHONY: printenv updateconfigs printchanges insertchanges startnewrelease diffupstream help updateportsconfigs editportsconfigs
+
+help:
+	@echo "These are the targets in addition to the normal $(DEBIAN) ones:"
+	@echo
+	@echo "  printenv        : Print some variables used in the build"
+	@echo
+	@echo "  updateconfigs        : Update core arch configs"
+	@echo
+	@echo "  editconfigs          : Update core arch configs interractively"
+	@echo "  genconfigs           : Generate core arch configs in CONFIGS/*"
+	@echo
+	@echo "  updateportsconfigs   : Update ports arch configs"
+	@echo
+	@echo "  editportsconfigs     : Update ports arch configs interactivly"
+	@echo "  genportconfigs       : Generate ports arch configs in CONFIGS/*"
+	@echo
+	@echo "  printchanges    : Print the current changelog entries (from git)"
+	@echo
+	@echo "  insertchanges   : Insert current changelog entries (from git)"
+	@echo
+	@echo "  startnewrelease : Start a new changelog set"
+	@echo
+	@echo "  diffupstream    : Diff stock kernel code against upstream (git)"
+	@echo
+	@echo "  help            : If you are kernel hacking, you need the professional"
+	@echo "                    version of this"
+	@echo
+	@echo "Environment variables:"
+	@echo
+	@echo "  NOKERNLOG       : Do not add upstream kernel commits to changelog"
+	@echo "  CONCURRENCY_LEVEL=X"
+	@echo "                  : Use -jX for kernel compile"
+	@echo "  PRINTSHAS       : Include SHAs for commits in changelog"
+
+printdebian:
+	@echo "$(DEBIAN)"
+
+updateconfigs:
+	dh_testdir;
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig oldconfig
+	rm -rf build
+
+defaultconfigs:
+	dh_testdir;
+	yes "" | $(SHELL) $(DROOT)/scripts/misc/kernelconfig defaultconfig
+	rm -rf build
+
+editconfigs:
+	dh_testdir
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig editconfig
+	rm -rf build
+
+genconfigs:
+	dh_testdir
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig genconfig
+	rm -rf build
+
+updateportsconfigs:
+	dh_testdir;
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig oldconfig ports
+	rm -rf build
+
+editportsconfigs:
+	dh_testdir
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig editconfig ports
+	rm -rf build
+
+genportsconfigs:
+	dh_testdir
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig genconfig ports
+	rm -rf build
+
+printenv:
+	dh_testdir
+	@echo "src package name  = $(src_pkg_name)"
+	@echo "release           = $(release)"
+	@echo "revisions         = $(revisions)"
+	@echo "revision          = $(revision)"
+	@echo "uploadnum         = $(uploadnum)"
+	@echo "prev_revisions    = $(prev_revisions)"
+	@echo "prev_revision     = $(prev_revision)"
+	@echo "abinum            = $(abinum)"
+	@echo "gitver            = $(gitver)"
+	@echo "flavours          = $(flavours)"
+	@echo "skipabi           = $(skipabi)"
+	@echo "skipmodule        = $(skipmodule)"
+	@echo "skipdbg           = $(skipdbg)"
+	@echo "ubuntu_log_opts   = $(ubuntu_log_opts)"
+ifneq ($(SUBLEVEL),)
+	@echo "SUBLEVEL          = $(SUBLEVEL)"
+endif
+	@echo "CONCURRENCY_LEVEL = $(CONCURRENCY_LEVEL)"
+	@echo "bin package name  = $(bin_pkg_name)"
+	@echo "hdr package name  = $(hdrs_pkg_name)"
+	@echo "doc package name  = $(doc_pkg_name)"
+	@echo "do_doc_package            = $(do_doc_package)"
+	@echo "do_doc_package_content    = $(do_doc_package_content)"
+	@echo "do_source_package         = $(do_source_package)"
+	@echo "do_source_package_content = $(do_source_package_content)"
+	@echo "do_libc_dev_package       = $(do_libc_dev_package)"
+	@echo "do_common_headers_indep   = $(do_common_headers_indep)"
+	@echo "do_full_source            = $(do_full_source)"
+	@echo "do_tools                  = $(do_tools)"
+
+printchanges:
+	@baseCommit=$$(git log --pretty=format:'%H %s' | \
+		awk '/UBUNTU: '".*Ubuntu-$(release)-$(prev_revision)"'$$/ { print $$1; exit }'); \
+		git log "$$baseCommit"..HEAD | \
+		perl -w -f $(DROOT)/scripts/misc/git-ubuntu-log $(ubuntu_log_opts)
+
+insertchanges:
+	@perl -w -f $(DROOT)/scripts/misc/insert-changes.pl $(DROOT) $(DEBIAN) 
+
+diffupstream:
+	@git diff-tree -p refs/remotes/linux-2.6/master..HEAD $(shell ls | grep -vE '^(ubuntu|$(DEBIAN)|\.git.*)')
+
+startnewrelease:
+	dh_testdir
+	@nextminor=$(shell expr `echo $(revision) | awk -F. '{print $$2}'` + 1); \
+	now="$(shell date -R)"; \
+	echo "Creating new changelog set for $(abi_release).$$nextminor..."; \
+	echo -e "$(src_pkg_name) ($(abi_release).$$nextminor) UNRELEASED; urgency=low\n" > $(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Do not edit directly. Autogenerated at release." >> \
+		$(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Use the printchanges target to see the curent changes." \
+		>> $(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Use the insertchanges target to create the final log." \
+		>> $(DEBIAN)/changelog.new; \
+	echo -e "\n -- $$DEBFULLNAME <$$DEBEMAIL>  $$now\n" >> \
+		$(DEBIAN)/changelog.new ; \
+	cat $(DEBIAN)/changelog >> $(DEBIAN)/changelog.new; \
+	mv $(DEBIAN)/changelog.new $(DEBIAN)/changelog
+
--- linux-ec2-2.6.32.orig/debian/rules.d/3-binary-indep.mk
+++ linux-ec2-2.6.32/debian/rules.d/3-binary-indep.mk
@@ -0,0 +1,127 @@
+build-indep:
+
+docpkg = $(doc_pkg_name)
+docdir = $(CURDIR)/debian/$(docpkg)/usr/share/doc/$(docpkg)
+install-doc:
+	dh_testdir
+	dh_testroot
+	dh_clean -k -p$(docpkg)
+
+	install -d $(docdir)
+ifeq ($(do_doc_package_content),true)
+	# First the html docs. We skip these for autobuilds
+	if [ -z "$(AUTOBUILD)" ]; then \
+		install -d $(docdir)/$(doc_pkg_name)-tmp; \
+		$(kmake) O=$(docdir)/$(doc_pkg_name)-tmp htmldocs; \
+		mv $(docdir)/$(doc_pkg_name)-tmp/Documentation/DocBook \
+			$(docdir)/html; \
+		rm -rf $(docdir)/$(doc_pkg_name)-tmp; \
+	fi
+endif
+	# Copy the rest
+	cp -a Documentation/* $(docdir)
+	rm -rf $(docdir)/DocBook
+	find $(docdir) -name .gitignore | xargs rm -f
+
+indep_hdrpkg = $(hdrs_pkg_name)
+indep_hdrdir = $(CURDIR)/debian/$(indep_hdrpkg)/usr/src/$(indep_hdrpkg)
+install-headers:
+	dh_testdir
+	dh_testroot
+	dh_clean -k -p$(indep_hdrpkg)
+
+	install -d $(indep_hdrdir)
+	find . -path './debian' -prune -o -path './$(DEBIAN)' -prune \
+	  -o -path './include/*' -prune \
+	  -o -path './scripts/*' -prune -o -type f \
+	  \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \
+	     -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) \
+	  -print | cpio -pd --preserve-modification-time $(indep_hdrdir)
+	cp -a drivers/media/dvb/dvb-core/*.h $(indep_hdrdir)/drivers/media/dvb/dvb-core
+	cp -a drivers/media/video/*.h $(indep_hdrdir)/drivers/media/video
+	cp -a drivers/media/dvb/frontends/*.h $(indep_hdrdir)/drivers/media/dvb/frontends
+	cp -a scripts include $(indep_hdrdir)
+	(find arch -name include -type d -print | \
+		xargs -n1 -i: find : -type f) | \
+		cpio -pd --preserve-modification-time $(indep_hdrdir)
+
+srcpkg = $(src_pkg_name)-source-$(release)
+srcdir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg)
+install-source:
+	dh_testdir
+	dh_testroot
+	dh_clean -k -p$(srcpkg)
+
+	install -d $(srcdir)
+ifeq ($(do_source_package_content),true)
+	find . -path './debian' -prune -o -path './$(DEBIAN)' -prune -o \
+		-path './.*' -prune -o -print | \
+		cpio -pd --preserve-modification-time $(srcdir)
+	(cd $(srcdir)/..; tar cf - $(srcpkg)) | bzip2 -9c > \
+		$(srcdir).tar.bz2
+	rm -rf $(srcdir)
+endif
+
+install-tools: toolspkg = $(tools_common_pkg_name)
+install-tools: toolsbin = $(CURDIR)/debian/$(toolspkg)/usr/bin
+install-tools: toolsman = $(CURDIR)/debian/$(toolspkg)/usr/share/man
+install-tools:
+	dh_testdir
+	dh_testroot
+	dh_clean -k -p$(toolspkg)
+
+	install -d $(toolsbin)
+	install -d $(toolsman)/man1
+
+	install -m755 debian/tools/perf $(toolsbin)/perf
+
+	install -d $(builddir)/tools
+	for i in *; do ln -s $(CURDIR)/$$i $(builddir)/tools/; done
+	rm $(builddir)/tools/tools
+	rsync -a tools/ $(builddir)/tools/tools/
+
+	cd $(builddir)/tools/tools/perf && make man
+	install -m644 $(builddir)/tools/tools/perf/Documentation/*.1 \
+		$(toolsman)/man1
+
+install-indep-deps =
+ifeq ($(do_common_headers_indep),true)
+install-indep-deps += install-headers
+endif
+ifeq ($(do_doc_package),true)
+install-indep-deps += install-doc
+endif
+ifeq ($(do_source_package),true)
+install-indep-deps += install-source
+endif
+ifeq ($(do_tools),true)
+install-indep-deps += install-tools
+endif
+install-indep: $(install-indep-deps)
+
+# This is just to make it easy to call manually. Normally done in
+# binary-indep target during builds.
+binary-headers: install-headers
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs -p$(indep_hdrpkg)
+	dh_installdocs -p$(indep_hdrpkg)
+	dh_compress -p$(indep_hdrpkg)
+	dh_fixperms -p$(indep_hdrpkg)
+	dh_installdeb -p$(indep_hdrpkg)
+	dh_gencontrol -p$(indep_hdrpkg)
+	dh_md5sums -p$(indep_hdrpkg)
+	dh_builddeb -p$(indep_hdrpkg)
+
+binary-indep: install-indep
+	dh_testdir
+	dh_testroot
+
+	dh_installchangelogs -i
+	dh_installdocs -i
+	dh_compress -i
+	dh_fixperms -i
+	dh_installdeb -i
+	dh_gencontrol -i
+	dh_md5sums -i
+	dh_builddeb -i
--- linux-ec2-2.6.32.orig/debian/scripts/control-create
+++ linux-ec2-2.6.32/debian/scripts/control-create
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+. debian/debian.env
+
+vars=$1
+
+. $vars
+
+if [ "$is_sub" = "" ]; then
+	flavour=$(basename $vars | sed 's/.*\.//')
+	stub=${DEBIAN}/control.d/flavour-control.stub
+else
+	flavour=$(basename $vars .vars)
+	stub=${DEBIAN}/sub-flavours/control.stub
+fi
+
+cat $stub | grep -v '^#' | sed			\
+	-e "s#FLAVOUR#$flavour#g"		\
+	-e "s#DESC#$desc#g"			\
+	-e "s#ARCH#$arch#g"			\
+	-e "s#SUPPORTED#$supported#g"		\
+	-e "s#TARGET#$target#g"			\
+	-e "s#BOOTLOADER#$bootloader#g" 	\
+	-e "s#=PROVIDES=#$provides#g"		\
+	-e "s#=CONFLICTS=#$conflicts#g"
--- linux-ec2-2.6.32.orig/debian/scripts/module-inclusion
+++ linux-ec2-2.6.32/debian/scripts/module-inclusion
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+#
+# Build a new directory of modules based on an inclusion list.
+# The includsion list format must be a bash regular expression.
+#
+# usage: $0 ROOT INCLUSION_LIST
+# example: $0 debian/build/build-virtual debian.master/control.d/virtual.inclusion-list
+ROOT=$1
+ILIST=$2
+
+NROOT=${ROOT}.new
+
+#
+# Prep a destination directory.
+#
+mkdir -p ${NROOT}
+rsync -a --exclude="*.ko" ${ROOT}/ ${NROOT}
+
+cat ${ILIST} |while read i
+do
+	#
+	# 'find' blurts a warning if it cannot find any ko files.
+	#
+	if echo "$i" | grep '\*' > /dev/null
+	then
+		(cd ${ROOT}; eval find "${i}" -name "*.ko") |while read f
+		do
+			mkdir -p ${NROOT}/`dirname $f`
+			cp ${ROOT}/$f ${NROOT}/$f
+		done
+	else
+		if [ -f "${ROOT}/$i" ]
+		then
+			mkdir -p ${NROOT}/`dirname $i`
+			cp ${ROOT}/$i ${NROOT}/$i
+		else
+			echo Warning: Could not find ${ROOT}/$i
+		fi
+	fi
+
+done
+
+#
+# Cleanup
+#
+rm -rf ${ROOT}
+mv ${NROOT} ${ROOT}
+
+exit 0
+
--- linux-ec2-2.6.32.orig/debian/scripts/config-check
+++ linux-ec2-2.6.32/debian/scripts/config-check
@@ -0,0 +1,389 @@
+#!/usr/bin/perl
+#
+# check-config -- check the current config for issues
+#
+use strict;
+
+my $P = 'check-config';
+
+my $test = -1;
+if ($ARGV[0] eq '--test') {
+	$test = $ARGV[1] + 0;
+} elsif ($#ARGV != 4) {
+	die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only>\n";
+}
+
+my ($config, $arch, $flavour, $commonconfig, $warn_only) = @ARGV;
+
+my $checks = "$commonconfig/enforce";
+my %values = ();
+
+# If we are in overridden then still perform the checks and emit the messages
+# but do not return failure.  Those items marked FATAL will alway trigger
+# failure.
+my $fail_exit = 1;
+$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
+my $exit_val = 0;
+
+# Predicate execution engine.
+sub pred_first {
+	my ($rest) = @_;
+	my $depth = 0;
+	my $off;
+	my $char;
+	my $pred;
+	
+	for ($off = 0; $off <= length($rest); $off++) {
+		$char = substr($rest, $off, 1);
+		if ($char eq '(') {
+			$depth++;
+		} elsif ($char eq ')') {
+			$depth--;
+		} elsif ($depth == 0 && $char eq '&') {
+			last;
+		} elsif ($depth == 0 && $char eq '|') {
+			last;
+		}
+	}
+	if ($depth > 0) {
+		die "$P: $rest: missing close parenthesis ')'\n";
+	} elsif ($depth < 0) {
+		die "$P: $rest: missing open parenthesis '('\n";
+	}
+
+	($pred, $rest) = (substr($rest, 0, $off), substr($rest, $off + 1));
+
+	$pred =~ s/^\s*//;
+	$pred =~ s/\s*$//;
+
+	#print "pred<$pred> rest<$rest> char<$char>\n";
+	($pred, $rest, $char);
+}
+		
+sub pred_do {
+	my ($pred) = @_;
+	my (@a) = split(' ', $pred);
+
+	if ($a[0] eq 'arch') {
+		die "$P: $pred: malformed -- $pred <arch>\n" if ($#a != 1);
+		#print "    *** ARCH<$arch ?? $a[1]>\n";
+		return ($arch eq $a[1])
+	} elsif ($a[0] eq 'flavour') {
+		die "$P: $pred: malformed -- $pred <flavour>\n" if ($#a != 1);
+		#print "    *** FLAVOUR<$flavour ?? $a[1]>\n";
+		return ($flavour eq $a[1])
+	} elsif ($a[0] eq 'value') {
+		die "$P: $pred: malformed -- $pred <name> <val>\n" if ($#a != 2);
+		#print "    *** CHECK<$a[1] $a[2] ?? " . $values{$a[1]} . ">\n";
+		return ($values{$a[1]} eq $a[2]);
+	} elsif ($a[0] eq 'exists') {
+		die "$P: $pred: malformed -- $pred <name>\n" if ($#a != 1);
+		return (defined $values{$a[1]});
+	} else {
+		die "$P: $pred: unknown predicate\n";
+	}
+	return 1;
+}
+sub pred_exec {
+	my ($rest) = @_;
+	my $pred;
+	my $res;
+	my $sep;
+
+	#print "pred_exec<$rest>\n";
+
+	($pred, $rest, $sep) = pred_first($rest);
+
+	# Leading ! implies inversion.
+	if ($pred =~ /^\s*!\s*(.*)$/) {
+		#print " invert<$1>\n";
+		$res = !pred_exec($1);
+
+	# Recurse left for complex expressions.
+	} elsif ($pred =~ /^\s*\((.*)\)\s*$/) {
+		#print " left<$1>\n";
+		$res = pred_exec($1);
+
+	# Check for common syntax issues.
+	} elsif ($pred eq '') {
+		if ($sep eq '&' || $sep eq '|') {
+			die "$P: $pred$rest: malformed binary operator\n";
+		} else {
+			die "$P: $pred$rest: syntax error\n";
+		}
+		
+	# A predicate, execute it.
+	} else {
+		#print " DO<$pred> sep<$sep>\n";
+		$res = pred_do($pred);
+	}
+
+	#print " pre-return res<$res> sep<$sep>\n";
+	if ($sep eq '') {
+		#
+		
+	# Recurse right for binary operators -- note these are lazy.
+	} elsif ($sep eq '&' || $sep eq '|') {
+		#print " right<$rest> ? sep<$sep> res<$res>\n";
+		if ($rest =~ /^\s*($|\||\&)/) {
+			die "$P: $pred$rest: malformed binary operator\n";
+		}
+		if (($res && $sep eq '&') || (!$res && $sep eq '|')) {
+			#print " right<$rest>\n";
+			$res = pred_exec($rest);
+		}
+
+	} else {
+		die "$P: $pred$rest: malformed predicate\n";
+	}
+	#print " return res<$res> sep<$sep>\n";
+	return $res;
+}
+
+#
+# PREDICATE TESTS
+#
+my $test_total = 1;
+my $test_good = 0;
+sub pred_test {
+	my ($pred, $eres, $eerr) = @_;
+	my ($res, $err, $fail);
+
+	$test_total++;
+	if ($test != 0 && $test != $test_total - 1) {
+		return;
+	}
+
+	eval {
+		$res = pred_exec($pred);
+	};
+	$err = $@;
+	chomp($err);
+
+	$res = !!$res;
+	$eres = !!$eres;
+
+	$fail = '';
+	if (defined $eres && $res != $eres) {
+		$fail = "result missmatch, expected $eres returned $res";
+	}
+	if (defined $eerr && $err eq '') {
+		$fail = "error missmatch, expected '$eerr' returned success";
+	} elsif (defined $eerr && $err !~ /$eerr/) {
+		$fail = "error missmatch, expected '$eerr' returned '$err'";
+	} elsif (!defined $eerr && $err ne '') {
+		$fail = "error missmatch, expected success returned '$err'";
+	}
+	
+	if ($fail eq '') {
+		$test_good++;
+	} else {
+		print "$pred: $test_total: FAIL: $fail\n";
+	}
+	#print "TEST<$pred> eres<$eres> eerr<$eerr> res<$res> err<$err>\n";
+}
+if ($test >= 0) {
+	$arch = 'MYARCH';
+	$flavour = 'MYFLAVOUR';
+	%values = ( 'ENABLED' => 'y', 'DISABLED' => 'n' );
+
+	# Errors.
+	my $eunkn = 'unknown predicate';
+	my $epred = 'malformed';
+	my $eclose = 'missing close parenthesis';
+	my $eopen = 'missing open parenthesis';
+	my $ebinary = 'malformed binary operator';
+
+	# Basic predicate tests.
+	print "TEST: $test_total: basic predicate tests ...\n";
+
+	pred_test('nosuchcommand', undef, $eunkn);
+	pred_test('arch', undef, $epred);
+	pred_test('arch MYARCH MYARCH', undef, $epred);
+	pred_test('arch MYARCH', 1, undef);
+	pred_test('arch NOTMYARCH', 0, undef);
+
+	pred_test('flavour', undef, $epred);
+	pred_test('flavour MYFLAVOUR myflavour', undef, $epred);
+	pred_test('flavour MYFLAVOUR', 1, undef);
+	pred_test('flavour NOTMYFLAVOUR', 0, undef);
+
+	pred_test('value', undef, $epred);
+	pred_test('value ENABLED', undef, $epred);
+	pred_test('value ENABLED ENABLED ENABLED', undef, $epred);
+	pred_test('value ENABLED y', 1, undef);
+	pred_test('value ENABLED n', 0, undef);
+	pred_test('value DISABLED n', 1, undef);
+	pred_test('value DISABLED y', 0, undef);
+
+	pred_test('exists', undef, $epred);
+	pred_test('exists ENABLED ENABLED', undef, $epred);
+	pred_test('exists ENABLED', 1, undef);
+	pred_test('exists DISABLED', 1, undef);
+	pred_test('exists MISSING', 0, undef);
+
+	print "TEST: $test_total: inversion tests ...\n";	
+	pred_test('!exists ENABLED', 0, undef);
+	pred_test('!exists MISSING', 1, undef);
+	pred_test('!!exists ENABLED', 1, undef);
+	pred_test('!!exists MISSING', 0, undef);
+	pred_test('!!!exists ENABLED', 0, undef);
+	pred_test('!!!exists MISSING', 1, undef);
+
+	print "TEST: $test_total: parentheses tests ...\n";	
+	pred_test('(exists ENABLED)', 1, undef);
+	pred_test('((exists ENABLED))', 1, undef);
+	pred_test('(((exists ENABLED)))', 1, undef);
+	pred_test('(exists MISSING)', 0, undef);
+	pred_test('((exists MISSING))', 0, undef);
+	pred_test('(((exists MISSING)))', 0, undef);
+
+	pred_test('(!exists ENABLED)', 0, undef);
+	pred_test('((!exists ENABLED))', 0, undef);
+	pred_test('(((!exists ENABLED)))', 0, undef);
+	pred_test('(!exists MISSING)', 1, undef);
+	pred_test('((!exists MISSING))', 1, undef);
+	pred_test('(((!exists MISSING)))', 1, undef);
+
+	pred_test('((!(exists ENABLED)))', 0, undef);
+	pred_test('((!(exists MISSING)))', 1, undef);
+	pred_test('(!((exists ENABLED)))', 0, undef);
+	pred_test('(!((exists MISSING)))', 1, undef);
+	pred_test('!(((exists ENABLED)))', 0, undef);
+	pred_test('!(((exists MISSING)))', 1, undef);
+	pred_test('!((!(exists ENABLED)))', 1, undef);
+	pred_test('!((!(exists MISSING)))', 0, undef);
+	pred_test('!(!(!(exists ENABLED)))', 0, undef);
+	pred_test('!(!(!(exists MISSING)))', 1, undef);
+
+	pred_test('(', undef, $eclose);
+	pred_test('()(', undef, $eclose);
+	pred_test('(())(', undef, $eclose);
+	pred_test('((()))(', undef, $eclose);
+	pred_test('(()', undef, $eclose);
+	pred_test('((())', undef, $eclose);
+	pred_test('(((()))', undef, $eclose);
+	pred_test('(()()', undef, $eclose);
+	pred_test('((())()', undef, $eclose);
+
+	pred_test(')', undef, $eopen);
+	pred_test('())', undef, $eopen);
+	pred_test('(()))', undef, $eopen);
+	pred_test('((())))', undef, $eopen);
+
+	print "TEST: $test_total: binary and tests ...\n";
+
+	pred_test('exists ENABLED &', undef, $ebinary);
+	pred_test('& exists ENABLED', undef, $ebinary);
+	pred_test('exists ENABLED & & exists ENABLED', undef, $ebinary);
+
+	pred_test('exists MISSING & exists MISSING', 0, undef);
+	pred_test('exists MISSING & exists ENABLED', 0, undef);
+	pred_test('exists ENABLED & exists MISSING', 0, undef);
+	pred_test('exists ENABLED & exists ENABLED', 1, undef);
+
+	pred_test('exists MISSING & exists MISSING & exists MISSING', 0, undef);
+	pred_test('exists MISSING & exists MISSING & exists ENABLED', 0, undef);
+	pred_test('exists MISSING & exists ENABLED & exists MISSING', 0, undef);
+	pred_test('exists MISSING & exists ENABLED & exists ENABLED', 0, undef);
+	pred_test('exists ENABLED & exists MISSING & exists MISSING', 0, undef);
+	pred_test('exists ENABLED & exists MISSING & exists ENABLED', 0, undef);
+	pred_test('exists ENABLED & exists ENABLED & exists MISSING', 0, undef);
+	pred_test('exists ENABLED & exists ENABLED & exists ENABLED', 1, undef);
+
+	print "TEST: $test_total: binary or tests ...\n";
+
+	pred_test('exists ENABLED |', undef, $ebinary);
+	pred_test('| exists ENABLED', undef, $ebinary);
+	pred_test('exists ENABLED | | exists ENABLED', undef, $ebinary);
+
+	pred_test('exists MISSING | exists MISSING', 0, undef);
+	pred_test('exists MISSING | exists ENABLED', 1, undef);
+	pred_test('exists ENABLED | exists MISSING', 1, undef);
+	pred_test('exists ENABLED | exists ENABLED', 1, undef);
+
+	pred_test('exists MISSING | exists MISSING | exists MISSING', 0, undef);
+	pred_test('exists MISSING | exists MISSING | exists ENABLED', 1, undef);
+	pred_test('exists MISSING | exists ENABLED | exists MISSING', 1, undef);
+	pred_test('exists MISSING | exists ENABLED | exists ENABLED', 1, undef);
+	pred_test('exists ENABLED | exists MISSING | exists MISSING', 1, undef);
+	pred_test('exists ENABLED | exists MISSING | exists ENABLED', 1, undef);
+	pred_test('exists ENABLED | exists ENABLED | exists MISSING', 1, undef);
+	pred_test('exists ENABLED | exists ENABLED | exists ENABLED', 1, undef);
+
+	print "TEST: $test_total: binary or/and combination tests ...\n";
+
+	pred_test('exists MISSING | exists MISSING & exists MISSING', 0, undef);
+	pred_test('exists MISSING | exists MISSING & exists ENABLED', 0, undef);
+	pred_test('exists MISSING | exists ENABLED & exists MISSING', 0, undef);
+	pred_test('exists MISSING | exists ENABLED & exists ENABLED', 1, undef);
+	pred_test('exists ENABLED | exists MISSING & exists MISSING', 1, undef);
+	pred_test('exists ENABLED | exists MISSING & exists ENABLED', 1, undef);
+	pred_test('exists ENABLED | exists ENABLED & exists MISSING', 1, undef);
+	pred_test('exists ENABLED | exists ENABLED & exists ENABLED', 1, undef);
+
+	print "TEST: $test_total: binary and/or combination tests ...\n";
+
+	pred_test('exists MISSING & exists MISSING | exists MISSING', 0, undef);
+	pred_test('exists MISSING & exists MISSING | exists ENABLED', 0, undef);
+	pred_test('exists MISSING & exists ENABLED | exists MISSING', 0, undef);
+	pred_test('exists MISSING & exists ENABLED | exists ENABLED', 0, undef);
+	pred_test('exists ENABLED & exists MISSING | exists MISSING', 0, undef);
+	pred_test('exists ENABLED & exists MISSING | exists ENABLED', 1, undef);
+	pred_test('exists ENABLED & exists ENABLED | exists MISSING', 1, undef);
+	pred_test('exists ENABLED & exists ENABLED | exists ENABLED', 1, undef);
+
+	$test_total--;
+	print "TEST: $test_good/$test_total succeeded\n";
+
+	exit $exit_val;
+}
+
+# Load up the current configuration values -- FATAL if this fails
+print "$P: $config: loading config\n";
+open(CONFIG, "<$config") || die "$P: $config: open failed -- $! -- aborting\n";
+while (<CONFIG>) {
+	# Pull out values.
+	/^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next;
+	if ($2 eq 'is not set') {
+		$values{$1} = 'n';
+	} else {
+		$values{$1} = $2;
+	}
+}
+close(CONFIG);
+
+# FATAL: Check if we have an enforcement list.
+my $pass = 0;
+my $total = 0;
+my $line = '';
+print "$P: $checks: loading checks\n";
+open(CHECKS, "<$checks") || die "$P: $checks: open failed -- $! -- aborting\n";
+while (<CHECKS>) {
+	/^#/ && next;
+	chomp;
+
+	$line .= $_;
+	if ($line =~ /\\$/) {
+		chop($line);
+		$line .= " ";
+		next;
+	}
+	$line =~ /^\s*$/ && next;
+
+	#print "CHECK: <$line>\n";
+	$total++;
+	my $result = pred_exec($line);
+	if (!$result) {
+		print "$P: FAIL: $line\n";
+		$exit_val = $fail_exit;
+	} else {
+		$pass++;
+	}
+
+	$line = '';
+}
+close(CHECKS);
+
+print "$P: $pass/$total checks passed -- exit $exit_val\n";
+exit $exit_val;
--- linux-ec2-2.6.32.orig/debian/scripts/link-headers
+++ linux-ec2-2.6.32/debian/scripts/link-headers
@@ -0,0 +1,42 @@
+#!/bin/bash -e
+
+. debian/debian.env
+
+hdrdir="$1"
+symdir="$2"
+flavour="$3"
+
+echo "Symlinking and copying headers for $flavour..."
+
+excludes="( -path ./debian -prune -o -path ./${DEBIAN} -prune -o -path ./.git ) -prune -o"
+
+(
+find . $excludes  -type f \
+	\( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \
+	-name '*.sh' -o -name '*.pl' -o -name '*.lds' \) -print
+find ./include ./scripts -name .gitignore -prune -o -type f -print
+find ./include -mindepth 1 -maxdepth 1 $excludes -type d -print
+) | (
+while read file; do
+	dir=$file
+	lastdir=$file
+
+	if [ -e "$hdrdir/$file" -o -L "$hdrdir/$file" ]; then
+		continue
+	fi
+
+	while [ ! -e "$hdrdir/$dir" -a ! -L "$hdrdir/$dir" ]; do
+		lastdir=$dir
+		dir=`dirname $dir`
+	done
+	# If the last item to exist is a symlink we assume all is good
+	if [ ! -L "$hdrdir/$dir" ]; then
+		# Turns things like "./foo" into "../"
+		deref="`echo -n $lastdir | sed -e 's/^\.//' -e's,/[^/]*,../,g'`"
+		item="`echo -n $lastdir | sed -e 's/^\.\///'`"
+		ln -s $deref$symdir/$item $hdrdir/$item
+	fi
+done
+)
+
+exit
--- linux-ec2-2.6.32.orig/debian/scripts/module-check
+++ linux-ec2-2.6.32/debian/scripts/module-check
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+$flavour = shift;
+$prev_abidir = shift;
+$abidir = shift;
+$skipmodule = shift;
+
+print "II: Checking modules for $flavour...";
+
+if (-f "$prev_abidir/ignore.modules"
+    or -f "$prev_abidir/$flavour.ignore.modules") {
+	print "explicitly ignoring modules\n";
+	exit(0);
+}
+
+if (not -f "$abidir/$flavour.modules" or not -f
+    "$prev_abidir/$flavour.modules") {
+	print "previous or current modules file missing!\n";
+	print "   $abidir/$flavour.modules\n";
+	print "   $prev_abidir/$flavour.modules\n";
+	if (defined($skipmodule)) {
+		exit(0);
+	} else {
+		exit(1);
+	}
+}
+
+print "\n";
+
+my %modules;
+my %modules_ignore;
+my $missing = 0;
+my $new = 0;
+my $errors = 0;
+
+# See if we have any ignores
+if (-f "$prev_abidir/../modules.ignore") {
+	my $ignore = 0;
+	open(IGNORE, "< $prev_abidir/../modules.ignore") or
+		die "Could not open $prev_abidir/../modules.ignore";
+	print "   reading modules to ignore...";
+	while (<IGNORE>) {
+		chomp;
+		next if /\s*#/;
+		$modules_ignore{$_} = 1;
+		$ignore++;
+	}
+	close(IGNORE);
+	print "read $ignore modules.\n";
+}
+
+# Read new modules first
+print "   reading new modules...";
+$new_count = 0;
+open(NEW, "< $abidir/$flavour.modules") or
+	die "Could not open $abidir/$flavour.modules";
+while (<NEW>) {
+	chomp;
+	$modules{$_} = 1;
+	$new_count++;
+}
+close(NEW);
+print "read $new_count modules.\n";
+
+# Now the old modules, checking for missing ones
+print "   reading old modules...";
+$old_count = 0;
+open(OLD, "< $prev_abidir/$flavour.modules") or
+	die "Could not open $prev_abidir/$flavour.modules";
+while (<OLD>) {
+	chomp;
+	if (not defined($modules{$_})) {
+		print "\n" if not $missing;
+		$missing++;
+		if (not defined($modules_ignore{$_})) {
+			print "      MISS: $_\n";
+			$errors++;
+		} else {
+			print "      MISS: $_ (ignored)\n";
+		}
+	} else {
+		$modules{$_}++;
+	}
+	$old_count++;
+}
+close(OLD);
+# Check for new modules
+foreach $mod (keys(%modules)) {
+	if ($modules{$mod} < 2) {
+		print "\n" if not $missing and not $new;
+		print "      NEW : $mod\n";
+		$new++;
+	}
+}
+if ($new or $missing) {
+	print "      read $old_count modules : new($new)  missing($missing)\n";
+} else {
+	print "read $old_count modules.\n";
+}
+
+
+# Let's see where we stand...
+if ($errors) {
+	if (defined($skipmodule)) {
+		print "WW: Explicitly asked to ignore failures (probably not good)\n";
+	} else {
+		print "EE: Missing modules (start begging for mercy)\n";
+		exit 1
+	}
+}
+
+if ($new) {
+	print "II: New modules (you've been busy, wipe the poop off your nose)\n";
+} else {
+	print "II: No new modules (hope you're happy, slacker)\n";
+}
+
+print "II: Done\n";
+
+exit(0);
--- linux-ec2-2.6.32.orig/debian/scripts/abi-check
+++ linux-ec2-2.6.32/debian/scripts/abi-check
@@ -0,0 +1,210 @@
+#!/usr/bin/perl -w
+
+my $flavour = shift;
+my $prev_abinum = shift;
+my $abinum = shift;
+my $prev_abidir = shift;
+my $abidir = shift;
+my $skipabi = shift;
+
+my $fail_exit = 1;
+my $EE = "EE:";
+my $errors = 0;
+my $abiskip = 0;
+
+my $count;
+
+print "II: Checking ABI for $flavour...\n";
+
+if (-f "$prev_abidir/ignore"
+    or -f "$prev_abidir/$flavour.ignore" or "$skipabi" eq "true") {
+	print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n";
+	$fail_exit = 0;
+	$abiskip = 1;
+	$EE = "WW:";
+}
+
+if ($prev_abinum != $abinum) {
+	print "II: Different ABI's, running in no-fail mode\n";
+	$fail_exit = 0;
+	$EE = "WW:";
+}
+
+if (not -f "$abidir/$flavour" or not -f "$prev_abidir/$flavour") {
+	print "EE: Previous or current ABI file missing!\n";
+	print "    $abidir/$flavour\n" if not -f "$abidir/$flavour";
+	print "    $prev_abidir/$flavour\n" if not -f "$prev_abidir/$flavour";
+
+	# Exit if the ABI files are missing, but return status based on whether
+	# skip ABI was indicated.
+	if ("$abiskip" eq "1") {
+		exit(0);
+	} else {
+		exit(1);
+	}
+}
+
+my %symbols;
+my %symbols_ignore;
+my %modules_ignore;
+my %module_syms;
+
+# See if we have any ignores
+my $ignore = 0;
+print "    Reading symbols/modules to ignore...";
+
+for $file ("$prev_abidir/../blacklist", "$prev_abidir/../../perm-blacklist") {
+	if (-f $file) {
+		open(IGNORE, "< $file") or
+			die "Could not open $file";
+		while (<IGNORE>) {
+			chomp;
+			if ($_ =~ m/M: (.*)/) {
+				$modules_ignore{$1} = 1;
+			} else {
+				$symbols_ignore{$_} = 1;
+			}
+			$ignore++;
+		}
+		close(IGNORE);
+	}
+}
+print "read $ignore symbols/modules.\n";
+
+sub is_ignored($$) {
+	my ($mod, $sym) = @_;
+
+	die "Missing module name in is_ignored()" if not defined($mod);
+	die "Missing symbol name in is_ignored()" if not defined($sym);
+
+	if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) {
+		return 1;
+	}
+	return 0;
+}
+
+# Read new syms first
+print "    Reading new symbols ($abinum)...";
+$count = 0;
+open(NEW, "< $abidir/$flavour") or
+	die "Could not open $abidir/$flavour";
+while (<NEW>) {
+	chomp;
+	m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
+	$symbols{$4}{'type'} = $1;
+	$symbols{$4}{'loc'} = $2;
+	$symbols{$4}{'hash'} = $3;
+	$module_syms{$2} = 0;
+	$count++;
+}
+close(NEW);
+print "read $count symbols.\n";
+
+# Now the old symbols, checking for missing ones
+print "    Reading old symbols ($prev_abinum)...";
+$count = 0;
+open(OLD, "< $prev_abidir/$flavour") or
+	die "Could not open $prev_abidir/$flavour";
+while (<OLD>) {
+	chomp;
+	m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/;
+	$symbols{$4}{'old_type'} = $1;
+	$symbols{$4}{'old_loc'} = $2;
+	$symbols{$4}{'old_hash'} = $3;
+	$count++;
+}
+close(OLD);
+
+print "read $count symbols.\n";
+
+print "II: Checking for missing symbols in new ABI...";
+$count = 0;
+foreach $sym (keys(%symbols)) {
+	if (!defined($symbols{$sym}{'type'})) {
+		print "\n" if not $count;
+		printf("    MISS : %s%s\n", $sym,
+			is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : "");
+		$count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym);
+	}
+}
+print "    " if $count;
+print "found $count missing symbols\n";
+if ($count) {
+	print "$EE Symbols gone missing (what did you do!?!)\n";
+	$errors++;
+}
+
+
+print "II: Checking for new symbols in new ABI...";
+$count = 0;
+foreach $sym (keys(%symbols)) {
+	if (!defined($symbols{$sym}{'old_type'})) {
+		print "\n" if not $count;
+		print "    NEW : $sym\n";
+		$count++;
+	}
+}
+print "    " if $count;
+print "found $count new symbols\n";
+if ($count and $prev_abinum == $abinum) {
+	print "WW: Found new symbols within same ABI. Not recommended\n";
+}
+
+print "II: Checking for changes to ABI...\n";
+$count = 0;
+my $moved = 0;
+my $changed_type = 0;
+my $changed_hash = 0;
+foreach $sym (keys(%symbols)) {
+	if (!defined($symbols{$sym}{'old_type'}) or
+	    !defined($symbols{$sym}{'type'})) {
+		next;
+	}
+
+	# Changes in location don't hurt us, but log it anyway
+	if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) {
+		printf("    MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'},
+			$symbols{$sym}{'loc'});
+		$moved++;
+	}
+
+	# Changes to export type are only bad if new type isn't
+	# EXPORT_SYMBOL. Changing things to GPL are bad.
+	if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) {
+		printf("    TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}.
+			$symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym)
+			? " (ignored)" : "");
+		$changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL"
+			and !is_ignored($symbols{$sym}{'loc'}, $sym);
+	}
+
+	# Changes to the hash are always bad
+	if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) {
+		printf("    HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'},
+			$symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym)
+			? " (ignored)" : "");
+		$changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym);
+		$module_syms{$symbols{$sym}{'loc'}}++;
+	}
+}
+
+print "WW: $moved symbols changed location\n" if $moved;
+print "$EE $changed_type symbols changed export type and weren't ignored\n" if $changed_type;
+print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed_hash;
+
+$errors++ if $changed_hash or $changed_type;
+if ($changed_hash) {
+	print "II: Module hash change summary...\n";
+	foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) {
+		next if ! $module_syms{$mod};
+		printf("    %-40s: %d\n", $mod, $module_syms{$mod});
+	}
+}
+
+print "II: Done\n";
+
+if ($errors) {
+	exit($fail_exit);
+} else {
+	exit(0);
+}
--- linux-ec2-2.6.32.orig/debian/scripts/sub-flavour
+++ linux-ec2-2.6.32/debian/scripts/sub-flavour
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+. debian/debian.env
+
+echo "SUB_PROCESS $FROM => $TO"
+
+export from_pkg="linux-image-$ABI_RELEASE-$FROM"
+export to_pkg="linux-image-$ABI_RELEASE-$TO"
+
+from_moddir="debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM"
+to_moddir="debian/$to_pkg/lib/modules/$ABI_RELEASE-$FROM"
+
+install -d "debian/$to_pkg/boot"
+install -m644 debian/$from_pkg/boot/{vmlinuz,System.map,config}-$ABI_RELEASE-$FROM \
+	debian/$to_pkg/boot/
+
+#
+# Print some warnings if there are files in the sub-flavours list
+# that do not actually exist.
+#
+cat ${DEBIAN}/sub-flavours/$TO.list | while read line
+do
+(
+	cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel;
+	#
+	# If its a wildcard, then check that there are files that match.
+	#
+	if echo "$line" | grep '\*' > /dev/null
+	then
+		if [ `eval find "$line" -name '*.ko' 2>/dev/null|wc -l` -lt 1 ]
+		then
+			echo SUB_INST Warning - No files in $line
+		fi
+	#
+	# Else it should be a single file reference.
+	#
+	elif [ ! -f "$line" ]
+	then
+		echo SUB_INST Warning - could not find "$line"
+	fi
+)
+done
+
+cat ${DEBIAN}/sub-flavours/$TO.list | while read line; do
+	(
+	cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel;
+	if echo "$line" | grep '\*' > /dev/null
+	then
+		eval find "$line" -name '*.ko' 2>/dev/null || true
+	elif [ -f "$line" ]
+	then
+		echo "$line"
+	fi
+	);
+done | while read mod; do
+	echo "SUB_INST checking: $mod"
+	fromdir="/lib/modules/$ABI_RELEASE-$FROM/"
+	egrep "^($fromdir)?kernel/$mod:" \
+		$from_moddir/modules.dep | sed -e "s|^$fromdir||" -e 's/://' -e 's/ /\n/g' | \
+	while read m; do
+		m="${fromdir}$m"
+		test -f debian/$to_pkg/$m && continue
+		echo "SUB_INST installing: $m"
+		install -D -m644 debian/$from_pkg/$m \
+			debian/$to_pkg/$m
+	done
+done
--- linux-ec2-2.6.32.orig/debian/scripts/misc/splitconfig.pl
+++ linux-ec2-2.6.32/debian/scripts/misc/splitconfig.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/perl -w
+
+%allconfigs = ();
+%common = ();
+
+print "Reading config's ...\n";
+
+opendir(DIR, ".");
+
+while (defined($config = readdir(DIR))) {
+	# Only config.*
+	next if $config !~ /^config\..*/;
+	# Nothing that is disabled, or remnant
+	next if $config =~ /.*\.(default|disabled|stub)$/;
+
+	%{$allconfigs{$config}} = ();
+
+	print "  processing $config ... ";
+
+	open(CONFIG, "< $config");
+
+	while (<CONFIG>) {
+		# Skip comments
+		/^#*\s*CONFIG_(\w+)[\s=](.*)$/ or next;
+
+		${$allconfigs{$config}}{$1} = $2;
+
+		$common{$1} = $2;
+	}
+
+	close(CONFIG);
+
+	print "done.\n";
+}
+
+closedir(DIR);
+
+print "\n";
+
+print "Merging lists ... \n";
+
+# %options - pointer to flavour config inside the allconfigs array
+for $config (keys(%allconfigs)) {
+	my %options = %{$allconfigs{$config}};
+
+	print "   processing $config ... ";
+
+	for $key (keys(%common)) {
+		next if not defined $common{$key};
+
+		# If we don't have the common option, then it isn't
+		# common. If we do have that option, it must have the same
+		# value.  EXCEPT where this file does not have a value at all
+		# which may safely be merged with any other value; the value
+		# will be elided during recombination of the parts.
+		if (!defined($options{$key})) {
+			# Its ok really ... let it merge
+		} elsif (not defined($options{$key})) {
+			undef $common{$key};
+		} elsif ($common{$key} ne $options{$key}) {
+			undef $common{$key};
+		}
+	}
+
+	print "done.\n";
+}
+
+print "\n";
+
+print "Creating common config ... ";
+
+open(COMMON, "> config.common");
+print COMMON "#\n# Common config options automatically generated by splitconfig.pl\n#\n";
+
+for $key (sort(keys(%common))) {
+	if (not defined $common{$key}) {
+		print COMMON "# CONFIG_$key is UNMERGABLE\n";
+	} elsif ($common{$key} eq "is not set") {
+		print COMMON "# CONFIG_$key is not set\n";
+	} else {
+		print COMMON "CONFIG_$key=$common{$key}\n";
+	}
+}
+close(COMMON);
+
+print "done.\n\n";
+
+print "Creating stub configs ...\n";
+
+for $config (keys(%allconfigs)) {
+	my %options = %{$allconfigs{$config}};
+
+	print "  processing $config ... ";
+
+	open(STUB, "> $config");
+	print STUB "#\n# Config options for $config automatically generated by splitconfig.pl\n#\n";
+
+	for $key (sort(keys(%options))) {
+		next if defined $common{$key};
+
+		if ($options{$key} =~ /^is /) {
+			print STUB "# CONFIG_$key $options{$key}\n";
+		} else {
+			print STUB "CONFIG_$key=$options{$key}\n";
+		}
+	}
+
+	close(STUB);
+
+	print "done.\n";
+}
--- linux-ec2-2.6.32.orig/debian/scripts/misc/getabis
+++ linux-ec2-2.6.32/debian/scripts/misc/getabis
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+. debian/debian.env
+
+if [ "$#" != "2" ]; then
+	echo "Usage: $0 <release> <revision>" 1>&2
+	exit 1
+fi
+
+ver=$1
+revision=$2
+abi=$(echo $revision | awk -F. '{print $1}')
+
+verabi=$ver-$abi
+verfull=$ver-$revision
+
+WGET="wget --quiet -c"
+
+abidir="`pwd`/$DEBIAN/abi/$verfull"
+tmpdir="`pwd`/abi-tmp-$verfull"
+origdir="`pwd`"
+
+test -d $tmpdir || mkdir $tmpdir
+
+getall() {
+	arch=$1
+	shift
+
+	mkdir -p $abidir/$arch
+
+	for sub in $@; do
+		if [ -f $abidir/$arch/$sub ]; then
+			echo "Exists: $sub"
+			continue
+		fi
+		echo -n "Fetching $sub..."
+		filename=linux-image-${verabi}-${sub}_${verfull}_${arch}.deb
+		cd $tmpdir
+		for r in "${repo_list[@]}"
+		do
+			if ! [ -f $filename ]; then
+				$WGET $r/$filename
+			fi
+		done
+		if [ "$?" = "0" ]; then
+			echo -n "extracting..."
+			dpkg-deb --extract $filename tmp
+			if [ -f tmp/boot/abi-* ]; then
+				mv tmp/boot/abi-* $abidir/$arch/$sub
+			else
+				echo -n "NO ABI FILE..."
+			fi
+			(cd tmp; find lib/modules/$verabi-$sub/kernel -name '*.ko') | \
+				sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > \
+				$abidir/$arch/$sub.modules
+			rm -rf tmp $filename
+			echo "done."
+		else
+			echo "FAILED."
+		fi
+		cd $origdir
+	done
+}
+
+# MAIN
+
+# Setup abi directory
+mkdir -p $abidir
+echo $abi > $abidir/abiname
+
+# NOTE: The flavours are hardcoded, because they may have changed from the
+# current build.
+
+. $DEBIAN/etc/getabis
+
+rmdir $tmpdir
--- linux-ec2-2.6.32.orig/debian/scripts/misc/insert-changes.pl
+++ linux-ec2-2.6.32/debian/scripts/misc/insert-changes.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+my $debian;
+$droot = $ARGV[0] if (defined $ARGV[0]);
+$droot = 'debian' if (!defined $droot);
+$debian = $ARGV[1] if (defined $ARGV[1]);
+$debian = 'debian.master' if (!defined $debian);
+
+system("make -s -f $droot/rules printchanges > $debian/changes");
+
+open(CHANGELOG, "< $debian/changelog") or die "Cannot open changelog";
+open(CHANGES, "< $debian/changes") or die "Cannot open new changes";
+open(NEW, "> $debian/changelog.new") or die "Cannot open new changelog";
+
+$printed = 0;
+
+while (<CHANGELOG>) {
+	if (/^  CHANGELOG: /) {
+		next if $printed;
+
+		while (<CHANGES>) {
+			print NEW;
+		}
+
+		$printed = 1;
+	} else {
+		print NEW;
+	}
+}
+
+close(NEW);
+close(CHANGES);
+close(CHANGELOG);
+
+rename("$debian/changelog.new", "$debian/changelog");
+unlink("$debian/changes");
--- linux-ec2-2.6.32.orig/debian/scripts/misc/retag
+++ linux-ec2-2.6.32/debian/scripts/misc/retag
@@ -0,0 +1,34 @@
+#!/usr/bin/perl -w
+
+open(TAGS, "git tag -l |") or die "Could not get list of tags";
+@tags = <TAGS>;
+close(TAGS);
+
+open(LOGS, "git log --pretty=short |") or die "ERROR: Calling git log";
+my $commit = "";
+
+while (<LOGS>) {
+	my $origtag;
+
+	if (m|^commit (.*)$|) {
+		$commit = $1;
+		next;
+	}
+
+	m|\s*UBUNTU: (Ubuntu-2\.6\..*)| or next;
+
+	$tag = $1;
+
+	($origtag) = grep(/^$tag.orig$/, @tags);
+
+	if (!defined($origtag)) {
+		print "I: Adding original tag for $tag\n";
+		system("git tag -m $tag $tag.orig $tag");
+	}
+
+	print "I: Tagging $tag => $commit\n";
+
+	system("git tag -f -m $tag $tag $commit");
+}
+
+close(LOGS);
--- linux-ec2-2.6.32.orig/debian/scripts/misc/git-ubuntu-log
+++ linux-ec2-2.6.32/debian/scripts/misc/git-ubuntu-log
@@ -0,0 +1,232 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Text::Wrap;
+
+my $kernel_auth = "Upstream Kernel Changes";
+
+my (%map, @reverts);
+my $pstate = 1;
+my $no_kern_log = 0;
+my $print_shas = 0;
+my $first_print = 1;
+
+while (@ARGV) {
+	my $opt = $ARGV[0];
+	shift;
+	if ($opt eq "--no-kern-log") {
+		$no_kern_log = 1;
+	} elsif ($opt eq "--print-shas") {
+		$print_shas = 1;
+	} else {
+		print STDERR "Unknown options: $opt\n";
+		exit(1);
+	}
+}
+
+sub check_reverts($) {
+	my ($entry) = @_;
+	my ($check);
+
+	foreach $check (reverse @reverts) {
+		my $desc = "Revert \"" . $entry->{'desc'} . "\"";
+		if ($check->{'desc'} eq $desc) {
+			@reverts = grep($_->{'desc'} ne $desc, @reverts);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+sub add_entry($) {
+	my ($entry) = @_;
+	my $key = $entry->{'author'};
+
+        # store description in array, in email->{desc list} map
+        if (exists $map{$key}) {
+                # grab ref
+                my $obj = $map{$key};
+
+                # add desc to array
+                push(@$obj, $entry);
+        } else {
+                # create new array, containing 1 item
+                my @arr = ($entry);
+
+                # store ref to array
+                $map{$key} = \@arr;
+        }
+}
+
+sub shortlog_entry($$$$$) {
+	my ($name, $desc, $bug, $cve, $commit) = @_;
+	my $entry;
+
+	$desc =~ s#/pub/scm/linux/kernel/git/#/.../#g;
+	$desc =~ s#\[PATCH\] ##g;
+
+	$desc =~ s#^\s*##g;
+	$desc =~ s# *UBUNTU: ##g;
+
+	$entry->{'desc'} = $desc;
+	if ($bug ne '') {
+		$entry->{'bugno'} = $bug;
+	}
+	$entry->{'cve'} = $cve;
+	$entry->{'commit'} = $commit;
+	$entry->{'author'} = $name;
+
+	if ($desc =~ /^Revert "/) {
+		push(@reverts, $entry);
+		return;
+	}
+
+	return if check_reverts($entry);
+
+	add_entry($entry);
+}
+
+# sort comparison function
+sub by_name($$) {
+	my ($a, $b) = @_;
+
+	uc($a) cmp uc($b);
+}
+
+sub shortlog_output {
+	my ($obj, $key, $entry);
+
+	foreach $key (sort by_name keys %map) {
+		next if $key eq $kernel_auth and $no_kern_log;
+
+		print "\n" unless $first_print;
+		$first_print = 0;
+
+		# output author
+		printf "  [ %s ]\n\n", $key;
+
+		# output author's 1-line summaries
+		$obj = $map{$key};
+		foreach $entry (reverse @$obj) {
+			print wrap("  * ", "    ", $entry->{'desc'}) . "\n";
+			# For non upstream changes, add other info.
+			if ($key ne $kernel_auth) {
+				if ($print_shas) {
+					print "    - GIT-SHA " . $entry->{'commit'} .
+						"\n";
+				}
+			}
+			if (defined($entry->{'bugno'})) {
+				print "    - LP: #" .  $entry->{'bugno'} . "\n";
+			}
+			if (defined($entry->{'cve'})) {
+				print "    - " . $entry->{'cve'} . "\n";
+			}
+		}
+	}
+}
+
+sub changelog_input {
+	my ($author, $desc, $commit, $entry, $cve);
+
+	while (<STDIN>) {
+		# get commit
+		if ($pstate == 1) {
+			next unless /^commit (.*)/;
+
+			$commit = $1;
+
+			$pstate++;
+		}
+
+		# get author and email
+		elsif ($pstate == 2) {
+			my ($email);
+
+			next unless /^[Aa]uthor:?\s*(.*?)\s*<(.*)>/;
+
+			$author = $1;
+			$email = $2;
+			$desc = undef;
+			$cve = undef;
+
+			# cset author fixups
+			if (!$author) {
+				$author = $email;
+			}
+			$pstate++;
+		}
+
+		# skip to blank line
+		elsif ($pstate == 3) {
+			next unless /^\s*$/;
+			$pstate++;
+		}
+
+		# skip to non-blank line
+		elsif ($pstate == 4) {
+			next unless /^\s*?(.*)/;
+			my $ignore = 0;
+			my $do_ignore = 0;
+			my $bug = undef;
+			my %bugz = ();
+			my $k;
+
+			# skip lines that are obviously not
+			# a 1-line cset description
+			next if /^\s*From: /;
+
+			chomp;
+			$desc = $1;
+
+			if ($desc =~ /^ *(Revert "|)UBUNTU:/) {
+				$do_ignore = 1;
+			} else {
+				$do_ignore = 0;
+				$author = $kernel_auth;
+				$ignore = 1 if $desc =~ /Merge /;
+			}
+			while (<STDIN>) {
+				$ignore  =  1 if ($do_ignore && /^ *Ignore: yes/i);
+				if    (/^ *Bug: *(#|)([0-9#,\s]*)\s*$/i) {
+					foreach $k (split('(,|\s)\s*(#|)', $2)) {
+						$bugz{$k} = 1 if (($k ne '') and ($k =~ /[0-9]+/));
+					}
+				}
+				elsif (/^ *BugLink: *http.*:\/\/.*\/([0-9]+)/i) {
+					$bugz{$1} = 1;
+				}
+				elsif (/^ *(CVE-.*)/) {
+					$cve = $1
+				}
+				last if /^commit /;
+			}
+
+                        $bug = join(", #", sort keys(%bugz));
+			if (!$ignore) {
+				&shortlog_entry($author, $desc, $bug,
+						$cve, $commit, 0);
+			}
+
+			$pstate = 1;
+			if ($_ && /^commit (.*)/) {
+				$commit = $1;
+				$pstate++;
+			}
+		}
+	
+		else {
+			die "invalid parse state $pstate";
+		}
+	}
+
+	foreach $entry (@reverts) {
+		add_entry($entry);
+	}	
+}
+
+&changelog_input;
+&shortlog_output;
+
+exit(0);
--- linux-ec2-2.6.32.orig/debian/scripts/misc/kernelconfig
+++ linux-ec2-2.6.32/debian/scripts/misc/kernelconfig
@@ -0,0 +1,171 @@
+#!/bin/bash
+
+. debian/debian.env
+
+# Script to merge all configs and run 'make silentoldconfig' on it to wade out bad juju.
+# Then split the configs into distro-commmon and flavour-specific parts
+
+# We have to be in the top level kernel source directory
+if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then
+	echo "This does not appear to be the kernel source directory." 1>&2
+	exit 1
+fi
+
+mode=${1:?"Usage: $0 [oldconfig|editconfig]"}
+case "$mode" in
+    oldconfig)  ;; # All is good
+    defaultconfig)  ;; # All is good
+    editconfig) ;; # All is good
+    genconfig)  ;; # All is good
+    *) echo "$0 called with invalid mode" 1>&2
+       exit 1 ;;
+esac
+kerneldir="`pwd`"
+confdir="$kerneldir/${DEBIAN}/config"
+sharedconfdir="$kerneldir/debian.master/config"
+variant="$2"
+
+. $DEBIAN/etc/kernelconfig
+
+bindir="`pwd`/${DROOT}/scripts/misc"
+common_conf="$confdir/config.common.$family"
+tmpdir=`mktemp -d`
+mkdir "$tmpdir/CONFIGS"
+
+if [ "$mode" = "genconfig" ]; then
+	keep=1
+	mode="oldconfig"
+	test -d CONFIGS || mkdir CONFIGS
+fi
+
+for arch in $archs; do
+	rm -rf build
+	mkdir build
+
+	# Map debian archs to kernel archs
+	case "$arch" in
+		amd64)	kernarch="x86_64"	;;
+		lpia)   kernarch="x86" 		;;
+		sparc)	kernarch="sparc64"	;;
+		armel)	kernarch="arm"		;;
+		*)	kernarch="$arch"	;;
+	esac
+
+	archconfdir=$confdir/$arch
+	flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+
+	# Merge configs
+	# We merge config.common.ubuntu + config.common.<arch> +
+	# config.flavour.<flavour>
+
+	for config in $flavourconfigs; do
+		fullconf="$tmpdir/$arch-$config-full"
+		case $config in
+		*)
+			: >"$fullconf"
+			if [ -f $common_conf ]; then
+				cat $common_conf >> "$fullconf"
+			fi
+			if [ -f $archconfdir/config.common.$arch ]; then
+				cat $archconfdir/config.common.$arch >> "$fullconf"
+			fi
+			cat "$archconfdir/$config" >>"$fullconf"
+			if [ -f $confdir/OVERRIDES ]; then
+				cat $confdir/OVERRIDES >> "$fullconf"
+			fi
+			;;
+		esac
+	done
+
+	for config in $flavourconfigs; do
+		if [ -f $archconfdir/$config ]; then
+			fullconf="$tmpdir/$arch-$config-full"
+			cat "$fullconf" > build/.config
+			# Call oldconfig or menuconfig
+			case "$mode" in
+			    oldconfig)
+				# Weed out incorrect config parameters
+				echo "* Run silentoldconfig on $arch/$config ..."
+				make O=`pwd`/build ARCH=$kernarch silentoldconfig ;;
+			    defaultconfig)
+				# Weed out incorrect config parameters
+				echo "* Run oldconfig on $arch/$config ..."
+				make O=`pwd`/build ARCH=$kernarch oldconfig ;;
+			    editconfig)
+				# Interactively edit config parameters
+				while : ; do
+					echo -n "Do you want to edit config: $arch/$config? [Y/n] "
+					read choice
+					
+					case "$choice" in
+					y* | Y* | "" )
+						make O=`pwd`/build ARCH=$kernarch menuconfig
+						break ;;
+					n* | N* )
+						break ;;
+					*)
+						echo "Entry not valid"
+					esac
+				done
+				;;
+			    *)  # Bad!
+				exit 1 ;;
+			esac
+			cat build/.config > $archconfdir/$config
+			cat build/.config > "$tmpdir/CONFIGS/$arch-$config"
+			if [ "$keep" = "1" ]; then
+				cat build/.config > CONFIGS/$arch-$config
+			fi
+		else
+			echo "!! Config not found $archconfdir/$config..."
+		fi
+	done
+
+	echo "Running splitconfig.pl for $arch"
+	echo
+
+	# Can we make this more robust by avoiding $tmpdir completely?
+	# This approach was used for now because I didn't want to change
+	# splitconfig.pl
+	(cd $archconfdir; $bindir/splitconfig.pl; mv config.common \
+	 config.common.$arch; cp config.common.$arch $tmpdir)
+done
+
+rm -f $common_conf
+
+# Now run splitconfig.pl on all the config.common.<arch> copied to
+# $tmpdir
+(cd $tmpdir; $bindir/splitconfig.pl)
+(
+	cd $confdir;
+	rm -f *-full
+	grep -v 'is UNMERGABLE' <$tmpdir/config.common >$common_conf
+	for arch in $archs; do
+		grep -v 'is UNMERGABLE' <$tmpdir/config.common.$arch \
+			>$arch/config.common.$arch
+	done
+)
+
+echo ""
+echo "Running config-check for all configurations ..."
+echo ""
+fail=0
+for arch in $archs; do
+	archconfdir=$confdir/$arch
+	flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+	for config in $flavourconfigs; do
+		if [ -f $archconfdir/$config ]; then
+			fullconf="$tmpdir/CONFIGS/$arch-$config"
+			"$bindir/../config-check" "$fullconf" "$arch" "$config" "$sharedconfdir" "0" || let "fail=$fail+1"
+		fi
+	done
+done
+
+if [ "$fail" != 0 ]; then
+	echo ""
+	echo "*** ERROR: $fail config-check failures detected"
+	echo ""
+fi
+
+rm -rf build
+
--- linux-ec2-2.6.32.orig/debian/scripts/misc/insert-ubuntu-changes
+++ linux-ec2-2.6.32/debian/scripts/misc/insert-ubuntu-changes
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+
+if ($#ARGV != 2) {
+	die "Usage: $0 <changelog> <stop at> <start at>\n";
+}
+my ($changelog, $end, $start) = @ARGV;
+
+$end =~ s/.*\.//;
+$start =~ s/.*\.//;
+
+my @changes = ();
+my $output = 0;
+open(CHG, "<debian.master/changelog") ||
+	open(CHG, "<debian/changelog") ||
+	die "$0: debian/changelog: open failed - $!\n";
+while (<CHG>) {
+	if (/^\S+\s+\((.*\.(\d+))\)/) {
+		if ($2 <= $end) {
+			last;
+		}
+		if ($2 == $start) {
+			$output = 1;
+		}
+		if ($output) {
+			push(@changes, "\n  [ Ubuntu: $1 ]\n\n");
+			next;
+		}
+	}
+	next if ($output == 0);
+
+	next if (/^\s*$/);
+	next if (/^\s--/);
+	next if (/^\s\s[^\*\s]/);
+
+	push(@changes, $_);
+}
+close(CHG);
+
+open(CHANGELOG, "< $changelog") or die "Cannot open changelog";
+open(NEW, "> $changelog.new") or die "Cannot open new changelog";
+
+$printed = 3;
+while (<CHANGELOG>) {
+	if (/^  CHANGELOG: /) {
+		$printed--;
+		print NEW;
+		if ($printed == 0) {
+			print NEW @changes;
+		}
+		next;
+	}
+	print NEW;
+}
+
+close(NEW);
+close(CHANGELOG);
+
+rename("$changelog.new", "$changelog");
--- linux-ec2-2.6.32.orig/debian/tools/perf
+++ linux-ec2-2.6.32/debian/tools/perf
@@ -0,0 +1,16 @@
+#!/bin/bash
+full_version=`uname -r`
+
+# Removing flavour from version i.e. generic or server.
+flavour_abi=${full_version#*-}
+flavour=${flavour_abi#*-}
+version=${full_version%-$flavour}
+perf="perf_$version"
+
+if ! which "$perf" > /dev/null; then
+    echo "$perf not found" >&2
+    echo "You may need to install linux-tools-$version" >&2
+    exit 2
+fi
+
+exec "$perf" "$@"
--- linux-ec2-2.6.32.orig/debian/control-scripts/preinst
+++ linux-ec2-2.6.32/debian/control-scripts/preinst
@@ -0,0 +1,299 @@
+#! /usr/bin/perl
+#                              -*- Mode: Cperl -*-
+# image.preinst ---
+# Author           : Manoj Srivastava ( srivasta@tiamat.datasync.com )
+# Created On       : Sun Jun 14 03:38:02 1998
+# Created On Node  : tiamat.datasync.com
+# Last Modified By : Manoj Srivastava
+# Last Modified On : Sun Sep 24 14:04:42 2006
+# Last Machine Used: glaurung.internal.golden-gryphon.com
+# Update Count     : 99
+# Status           : Unknown, Use with caution!
+# HISTORY          :
+# Description      :
+#
+#
+
+#
+#use strict; #for debugging
+
+use Debconf::Client::ConfModule qw(:all);
+version('2.0');
+my $capb=capb("backup");
+
+$|=1;
+
+# Predefined values:
+my $version         = "=V";
+my $link_in_boot    = "";     # Should be empty, mostly
+my $no_symlink      = "";     # Should be empty, mostly
+my $reverse_symlink = "";     # Should be empty, mostly
+my $do_symlink      = "Yes";	# target machine defined
+my $do_boot_enable  = "Yes";	# target machine defined
+my $do_bootfloppy   = "Yes";	# target machine defined
+my $do_bootloader   = "Yes";	# target machine defined
+my $move_image      = '';       # target machine defined
+my $kimage          = "=K";     # Should be empty, mostly
+my $loader          = "=L";     # lilo, silo, quik, palo, vmelilo, nettrom
+                                # or elilo
+my $image_dir       = "/boot";     # where the image is located
+my $initrd          = "YES";     # initrd kernel
+my $use_hard_links  = '';       # hardlinks do not wirk across fs boundaries
+my $postinst_hook   = '';       #Normally we do not
+my $postrm_hook     = '';       #Normally we do not
+my $preinst_hook    = '';       #Normally we do not
+my $prerm_hook      = '';       #Normally we do not
+my $minimal_swap    = '';       # Do not swap symlinks
+my $ignore_depmod_err = '';    # normally we do not
+my $relink_src_link   = 'YES';	# There is no harm in checking the link
+my $relink_build_link = 'YES'; # There is no harm in checking the link
+my $force_build_link  = '';	 # There is no harm in checking the link
+my $kernel_arch       = "=B";
+my $ramdisk           = "/usr/sbin/update-initramfs";  # List of tools to create initial ram fs.
+my $package_name    = "linux-image-$version";
+
+my $Loader          = "NoLOADER"; #
+$Loader             = "LILO"     if $loader =~ /^lilo/io;
+$Loader             = "SILO"     if $loader =~ /^silo/io;
+$Loader             = "QUIK"     if $loader =~ /^quik/io;
+$Loader             = "yaboot"   if $loader =~ /^yaboot/io;
+$Loader             = "PALO"     if $loader =~ /^palo/io;
+$Loader             = "NETTROM"  if $loader =~ /^nettrom/io;
+$Loader             = "VMELILO"  if $loader =~ /^vmelilo/io;
+$Loader             = "ZIPL"     if $loader =~ /^zipl/io;
+$Loader             = "ELILO"    if $loader =~ /^elilo/io;
+
+
+#known variables
+my @boilerplate     = ();
+my @silotemplate    = ();
+my @quiktemplate    = ();
+my @palotemplate    = ();
+my @vmelilotemplate = ();
+my $bootdevice      = '';
+my $rootdevice      = '';
+my $rootdisk        = '';
+my $rootpartition   = '';
+my $image_dest      = "/";
+my $realimageloc    = "/$image_dir/";
+my $have_conffile   = "";
+my $CONF_LOC        = '/etc/kernel-img.conf';
+my $relative_links  = '';
+my $silent_loader   = '';
+my $warn_reboot     = '';        # Warn that we are installing a version of
+                                 # the kernel we are running
+
+my $modules_base    = '/lib/modules';
+
+die "Pre inst Internal error. Aborting." unless $version;
+
+exit 0 if $ARGV[0] =~ /abort-upgrade/;
+exit 1 unless $ARGV[0] =~ /(install|upgrade)/;
+
+# remove multiple leading slashes; make sure there is at least one.
+$realimageloc  =~ s|^/*|/|o;
+$realimageloc  =~ s|/+|/|o;
+
+if (-r "$CONF_LOC" && -f "$CONF_LOC"  ) {
+  if (open(CONF, "$CONF_LOC")) {
+    while (<CONF>) {
+      chomp;
+      s/\#.*$//g;
+      next if /^\s*$/;
+
+      $do_symlink      = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $no_symlink      = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $move_image      = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig;
+      $do_boot_enable  = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig;
+      $do_bootfloppy   = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig;
+      $do_bootloader   = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig;
+      $relative_links  = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig;
+      $use_hard_links  = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig;
+      $silent_loader   = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig;
+      $warn_reboot     = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig;
+      $minimal_swap    = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig;
+      $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig;
+      $relink_src_link   = '' if /^\s*relink_src_link\s*=\s*(no|false|0)\s*$/ig;
+      $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig;
+      $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig;
+
+      $do_symlink      = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $no_symlink      = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $move_image      = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig;
+      $do_boot_enable  = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootfloppy   = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootloader   = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig;
+      $relative_links  = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig;
+      $use_hard_links  = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_loader   = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig;
+      $warn_reboot     = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig;
+      $minimal_swap    = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig;
+      $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig;
+      $relink_src_link   = 'Yes' if /^\s*relink_src_link\s*=\s*(yes|true|1)\s*$/ig;
+      $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig;
+      $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig;
+
+      $image_dest      = "$1"  if /^\s*image_dest\s*=\s*(\S+)/ig;
+      $postinst_hook   = "$1"  if /^\s*postinst_hook\s*=\s*(\S+)/ig;
+      $postrm_hook     = "$1"  if /^\s*postrm_hook\s*=\s*(\S+)/ig;
+      $preinst_hook    = "$1"  if /^\s*preinst_hook\s*=\s*(\S+)/ig;
+      $prerm_hook      = "$1"  if /^\s*prerm_hook\s*=\s*(\S+)/ig;
+      $ramdisk         = "$1"  if /^\s*ramdisk\s*=\s*(.+)$/ig;
+    }
+    close CONF;
+    $have_conffile = "Yes";
+    $have_conffile = "Yes";	# stop perl complaining
+  }
+}
+
+$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch;
+
+# About to upgrade this package from version $2 TO THIS VERSION.
+# "prerm upgrade" has already been called for the old version of
+# this package.
+
+sub find_initrd_tool {
+  my $hostversion = shift;
+  my $version = shift;
+  my @ramdisks =
+    grep {
+      my $args = 
+        "$_ " .
+          "--supported-host-version=$hostversion " .
+            "--supported-target-version=$version " .
+              "1>/dev/null 2>&1"
+                ;
+      system($args) == 0;
+    }
+      split (/[:,\s]+/, $ramdisk);
+}
+
+sub check {
+  my $version = shift;
+  my $lib_modules="$modules_base/$version";
+  my $message = '';
+
+  if (-d "$lib_modules") {
+    opendir(DIR, $lib_modules) || die "can’t opendir $lib_modules: $!";
+    my @children = readdir(DIR);
+    if ($#children > 1) {
+      my @dirs  = grep { -d "$lib_modules/$_" } @children;
+      if ($#dirs > 1) { # we have subdirs
+        my $dir_message='';
+        for my $dir (@dirs) {
+          if ($dir =~/kernel$/) {
+            $dir_message="An older install was detected.\n";
+          }
+          else {
+            $dir_message="Module sub-directories were detected.\n"
+              unless $dir_message;
+          }
+        }
+        $message += $dir_message if $dir_message;
+      }
+
+      my @links = grep { -l "$lib_modules/$_" } @children;
+      if ($#links > -1) {
+        my $links_message = '';
+        for my $link (@links) {
+          next if ($link =~ /^build$/);
+          next if ($link =~ /^source$/);
+          $links_message = "Symbolic links were detected in $modules_base/$version.\n";
+        }
+        $message += $links_message if $links_message;
+      }
+      my @files = grep { -f "$lib_modules/$_" } @children;
+      $message += "Additional files also exist in $modules_base/$version.\n"
+        if ($#files > -1);
+    }
+  }
+  else { $message .= "$lib_modules does not exist. ";}
+  return $message;
+}
+
+if (-d "$modules_base/$version") {
+  my $errors=check($version);
+  warn "Info:\n$errors\n" if $errors;
+}
+
+# set the env var stem
+$ENV{'STEM'} = "linux";
+
+sub exec_script {
+  my $type   = shift;
+  my $script = shift;
+  print STDERR "Running $type hook script $script.\n";
+  system ("$script $version $realimageloc$kimage-$version") &&
+    print STDERR "User $type hook script [$script] ";
+  if ($?) {
+    if ($? == -1) {
+      print STDERR "failed to execute: $!\n";
+    }
+    elsif ($? & 127) {
+      printf STDERR "died with signal %d, %s coredump\n",
+        ($? & 127),  ($? & 128) ? 'with' : 'without';
+    }
+    else {
+      printf STDERR "exited with value %d\n", $? >> 8;
+    }
+    exit $? >> 8;
+  }
+}
+sub run_hook {
+  my $type   = shift;
+  my $script = shift;
+  if ($script =~ m,^/,) {
+    # Full path provided for the hook script
+    if (-x "$script") {
+      &exec_script($type,$script);
+    }
+    else {
+      die "The provided $type hook script [$script] could not be run.\n";
+    }
+  }
+  else {
+    # Look for it in a safe path
+    for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') {
+      if (-x "$path/$script") {
+        &exec_script($type, "$path/$script");
+        return 0;
+      }
+    }
+    # No luck
+    print STDERR "Could not find $type hook script [$script].\n";
+    die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n";
+  }
+}
+
+
+## Run user hook script here, if any
+if (-x "$preinst_hook") {
+  &run_hook("preinst", $preinst_hook);
+}
+if (-d "/etc/kernel/preinst.d") {
+  print STDERR "Examining /etc/kernel/preinst.d/\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version" .
+          " --arg=$realimageloc$kimage-$version" .
+          " /etc/kernel/preinst.d") &&
+            die "Failed to process /etc/kernel/preinst.d";
+}
+if (-d "/etc/kernel/preinst.d/$version") {
+  print STDERR "Examining /etc/kernel/preinst.d/$version.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version" .
+          " --arg=$realimageloc$kimage-$version" .
+          " /etc/kernel/preinst.d/$version") &&
+            die "Failed to process /etc/kernel/preinst.d/$version";
+}
+print STDERR "Done.\n";
+
+exit 0;
+
+__END__
+
+
--- linux-ec2-2.6.32.orig/debian/control-scripts/prerm
+++ linux-ec2-2.6.32/debian/control-scripts/prerm
@@ -0,0 +1,308 @@
+#! /usr/bin/perl
+#                              -*- Mode: Perl -*- 
+# image.prerm --- 
+# Author           : root ( root@melkor.pilgrim.umass.edu ) 
+# Created On       : Fri May 17 03:28:59 1996
+# Created On Node  : melkor.pilgrim.umass.edu
+# Last Modified By : Manoj Srivastava
+# Last Modified On : Sat Aug  5 13:14:17 2006
+# Last Machine Used: glaurung.internal.golden-gryphon.com
+# Update Count     : 85
+# Status           : Unknown, Use with caution!
+# HISTORY          : 
+# Description      : 
+# 
+#
+#    $Id: image.prerm,v 1.22 2003/10/07 16:24:20 srivasta Exp $
+#
+# 
+#use strict;
+
+$|=1;
+# Predefined values:
+my $version         = "=V";
+my $link_in_boot    = "";	# Should be empty, mostly
+my $no_symlink      = "";	# Should be empty, mostly
+my $reverse_symlink = "";	# Should be empty, mostly
+my $do_symlinks     = "Yes";	# target machine defined
+my $do_boot_enable  = "Yes";	# target machine defined
+my $do_bootfloppy   = "Yes";	# target machine defined
+my $do_bootloader   = "Yes";	# target machine defined
+my $move_image      = '';       # target machine defined
+my $kimage          = "=K";	# Should be empty, mostly
+my $loader          = "=L";     # lilo, silo, quik, palo, vmelilo, or nettrom
+my $image_dir       = "/boot";     # where the image is located
+my $clobber_modules = '';       # target machine defined
+my $initrd          = "YES";     # initrd kernel
+my $use_hard_links  = '';       # hardlinks do not wirk across fs boundaries
+my $postinst_hook   = '';       #Normally we do not
+my $postrm_hook     = '';       #Normally we do not
+my $preinst_hook    = '';       #Normally we do not
+my $prerm_hook      = '';       #Normally we do not
+my $minimal_swap    = '';       # Do not swap symlinks
+my $ignore_depmod_err = '';	# normally we do not
+my $relink_build_link = 'YES';	# There is no harm in checking the link
+my $force_build_link = '';	# There is no harm in checking the link
+my $kernel_arch       = "=B";
+my $ramdisk           = "/usr/sbin/update-initramfs";
+my $package_name    = "linux-image-$version";
+
+my $Loader          = "NoLOADER"; # 
+$Loader             = "LILO"     if $loader =~ /^lilo/io;
+$Loader             = "SILO"     if $loader =~ /^silo/io;
+$Loader             = "QUIK"     if $loader =~ /^quik/io;
+$Loader             = "yaboot"   if $loader =~ /^yaboot/io;
+$Loader             = "PALO"     if $loader =~ /^palo/io;
+$Loader             = "NETTROM"  if $loader =~ /^nettrom/io;
+$Loader             = "VMELILO"  if $loader =~ /^vmelilo/io;
+$Loader             = "ZIPL"     if $loader =~ /^zipl/io;
+$Loader             = "ELILO"    if $loader =~ /^elilo/io;
+
+
+# This should not point to /tmp, because of security risks.
+my $temp_file_name = "/var/log/$loader" . "_log.$$";
+
+#known variables
+my $image_dest      = "/";
+my $realimageloc    = "/$image_dir/";
+my $have_conffile   = "";
+my $CONF_LOC        = '/etc/kernel-img.conf';
+my $relative_links = '';
+my $silent_loader   = '';
+my $warn_reboot     = 'Yes';     # Warn that we are installing a version of
+                                 # the kernel we are running
+
+# remove multiple leading slashes; make sure there is at least one.
+$realimageloc  =~ s|^/*|/|o;
+$realimageloc  =~ s|/+|/|o;
+
+my $DEBUG = 0;
+
+# Variables used
+my $image='';
+my $ret=0;
+my $seen='';
+my $answer='';
+my $running = '';
+my $WouldInvalidate = 0;
+
+if ($ARGV[0] && ($ARGV[0] =~ /remove/ || $ARGV[0] =~ /upgrade/)) {
+  if (-l "/usr/doc/linux-image-$version") {
+    unlink "/usr/doc/linux-image-$version";
+  }
+}
+
+# Ignore all invocations uxcept when called on to remove
+exit 0 unless ($ARGV[0] && $ARGV[0] =~ /remove/) ;
+
+# Paranoid check to make sure that the correct value is put in there
+if (! $kimage)                    { $kimage = "vmlinuz";} # Hmm. empty
+elsif ($kimage =~ m/^b?uImage$/o) { $kimage = "vmlinuz";} # these produce vmlinuz
+elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz";} # these produce vmlinuz
+elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage;  }
+elsif ($kimage =~ m/^vmlinux$/o)  { my $nop = $kimage;  }
+else                              { $kimage = "vmlinuz";} # Default
+
+if (-r "$CONF_LOC" && -f "$CONF_LOC"  ) {
+  if (open(CONF, "$CONF_LOC")) {
+    while (<CONF>) {
+      chomp;
+      s/\#.*$//g;
+      next if /^\s*$/;
+
+      $do_symlink      = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $no_symlink      = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $move_image      = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig;
+      $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig;
+      $do_boot_enable  = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig;
+      $do_bootfloppy   = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig;
+      $relative_links  = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig;
+      $do_bootloader   = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig;
+      $do_initrd       = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig;
+      $use_hard_links  = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig;
+      $silent_loader   = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig;
+      $warn_reboot     = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig;
+      $minimal_swap    = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig;
+      $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig;
+      $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig;
+      $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig;
+
+
+      $do_symlink      = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $no_symlink      = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $move_image      = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig;
+      $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig;
+      $do_boot_enable  = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootfloppy   = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootloader   = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig;
+      $relative_links  = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig;
+      $do_initrd       = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig;
+      $use_hard_links  = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_loader   = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig;
+      $warn_reboot     = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig;
+      $minimal_swap    = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig;
+      $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig;
+      $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig;
+      $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig;
+
+      $image_dest      = "$1"  if /^\s*image_dest\s*=\s*(\S+)/ig;
+      $postinst_hook   = "$1"  if /^\s*postinst_hook\s*=\s*(\S+)/ig;
+      $postrm_hook     = "$1"  if /^\s*postrm_hook\s*=\s*(\S+)/ig;
+      $preinst_hook    = "$1"  if /^\s*preinst_hook\s*=\s*(\S+)/ig;
+      $prerm_hook      = "$1"  if /^\s*prerm_hook\s*=\s*(\S+)/ig;
+      $ramdisk         = "$1"  if /^\s*ramdisk\s*=\s*(.+)$/ig;
+    }
+    close CONF;
+    $have_conffile = "Yes";
+  }
+}
+
+
+$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch;
+
+#check to see if we are trying to remove a running kernel
+# if so we abort right now.
+chop($running=`uname -r`);
+if ($running eq $version) {
+  print STDERR "WARN: Proceeding with removing running kernel image.\n";
+}
+
+#Now, they have an alternate kernel which they are currently running
+
+# This is just us being nice to lilo users.
+
+chdir("/") or die "could not chdir to /:$!\n";
+
+if (-f "/etc/$loader.conf") { #I know, could be a link, but ..
+  open (LILO, "/etc/$loader.conf") || &success(); # this is not critical
+  while (<LILO>) {
+    chop;
+    s/\#.*//;			  # nix the comments
+    next unless /^\s*image\s*=\s(\S+)/o;
+    $image = $1;
+    if ($image && -e $image) {
+      while (defined($image) && -l $image) {
+	$image = readlink ($image);
+      }
+      if (defined($image) && -e $image) {
+	$WouldInvalidate |= $image =~ /$kimage-$version/;
+      }
+      else {
+	&success(); # invalid $loader.conf file
+      }
+    }
+    else {
+      &success(); # invalid $loader.conf file
+    }
+  }
+  close (LILO);
+  if ($WouldInvalidate) {
+    print STFERR "WARN: Proceeding with removing running kernel image.\n";
+    &success();
+  }
+}
+
+
+# set the env var stem
+$ENV{'STEM'} = "linux";
+
+sub exec_script {
+  my $type   = shift;
+  my $script = shift;
+  print STDERR "Running $type hook script $script.\n";
+  system ("$script $version $realimageloc$kimage-$version") &&
+    print STDERR "User $type hook script [$script] ";
+  if ($?) {
+    if ($? == -1) {
+      print STDERR "failed to execute: $!\n";
+    }
+    elsif ($? & 127) {
+      printf STDERR "died with signal %d, %s coredump\n",
+        ($? & 127),  ($? & 128) ? 'with' : 'without';
+    }
+    else {
+      printf STDERR "exited with value %d\n", $? >> 8;
+    }
+    exit $? >> 8;
+  }
+}
+sub run_hook {
+  my $type   = shift;
+  my $script = shift;
+  if ($script =~ m,^/,) {
+    # Full path provided for the hook script
+    if (-x "$script") {
+      &exec_script($type,$script);
+    }
+    else {
+      die "The provided $type hook script [$script] could not be run.\n";
+    }
+  }
+  else {
+    # Look for it in a safe path
+    for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') {
+      if (-x "$path/$script") {
+        &exec_script($type, "$path/$script");
+        return 0;
+      }
+    }
+    # No luck
+    print STDERR "Could not find $type hook script [$script].\n";
+    die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n";
+  }
+}
+
+
+## Run user hook script here, if any
+if (-x "$prerm_hook") {
+  &run_hook("prerm", $prerm_hook);
+}
+if (-d "/etc/kernel/prerm.d") {
+  print STDERR "Examining /etc/kernel/prerm.d.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " . 
+          "--arg=$realimageloc$kimage-$version /etc/kernel/prerm.d") &&
+            die "Failed to process /etc/kernel/prerm.d";
+}
+if (-d "/etc/kernel/prerm.d/$version") {
+  print STDERR "Examining /etc/kernel/prerm.d/$version.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version" .
+          " --arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/prerm.d/$version") &&
+            die "Failed to process /etc/kernel/prerm.d/$version";
+}
+
+sub success () {
+  my @files_to_remove = qw{
+    modules.dep modules.isapnpmap modules.pcimap
+    modules.usbmap modules.parportmap
+    modules.generic_string modules.ieee1394map
+    modules.ieee1394map modules.pnpbiosmap
+    modules.alias modules.ccwmap modules.inputmap
+    modules.symbols modules.ofmap modules.seriomap
+    modules.alias.bin modules.builtin.bin modules.dep.bin modules.symbols.bin
+  };
+
+  foreach my $extra_file (@files_to_remove) {
+    if (-f "/lib/modules/$version/$extra_file") {
+      unlink "/lib/modules/$version/$extra_file";
+    }
+  }
+  exit 0;
+}
+
+
+
+&success();
+exit 0;
+__END__
+
+
+
+
+
--- linux-ec2-2.6.32.orig/debian/control-scripts/postrm
+++ linux-ec2-2.6.32/debian/control-scripts/postrm
@@ -0,0 +1,354 @@
+#! /usr/bin/perl
+#                              -*- Mode: Cperl -*- 
+# image.postrm --- 
+# Author           : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com ) 
+# Created On       : Sat May 15 11:05:13 1999
+# Created On Node  : glaurung.green-gryphon.com
+# Last Modified By : Manoj Srivastava
+# Last Modified On : Wed Sep 13 11:26:19 2006
+# Last Machine Used: glaurung.internal.golden-gryphon.com
+# Update Count     : 57
+# Status           : Unknown, Use with caution!
+# HISTORY          : 
+# Description      : 
+# 
+#     $Id: image.postrm,v 1.31 2003/10/07 16:24:20 srivasta Exp $
+#
+
+
+# 
+#use strict; #for debugging
+use Cwd 'abs_path';
+
+$|=1;
+
+# Predefined values:
+my $version           = "=V";
+my $link_in_boot      = "";	# Should be empty, mostly
+my $no_symlink        = "";	# Should be empty, mostly
+my $reverse_symlink   = "";	# Should be empty, mostly
+my $do_symlink        = "Yes";	# target machine defined
+my $do_boot_enable    = "Yes";	# target machine defined
+my $do_bootfloppy     = "Yes";	# target machine defined
+my $do_bootloader     = "Yes";	# target machine defined
+my $move_image        = '';       # target machine defined
+my $kimage            = "=K";	# Should be empty, mostly
+my $loader            = "=L";     # lilo, silo, quik, palo, vmelilo, or nettrom
+my $image_dir         = "/boot";     # where the image is located
+my $clobber_modules   = '';       # target machine defined
+my $initrd            = "YES";     # initrd kernel
+my $do_initrd         = '';       # Normally, we don't
+my $warn_initrd       = 'YES';    # Normally we do
+my $use_hard_links    = '';       # hardlinks do not work across fs boundaries
+my $postinst_hook     = '';       #Normally we do not
+my $postrm_hook       = '';       #Normally we do not
+my $preinst_hook      = '';       #Normally we do not
+my $prerm_hook        = '';       #Normally we do not
+my $minimal_swap      = '';       # Do not swap symlinks
+my $ignore_depmod_err = '';	# normally we do not
+my $relink_build_link = 'YES';	# There is no harm in checking the link
+my $force_build_link  = '';	# we shall not create a dangling link
+my $kernel_arch       = "=B";
+my $ramdisk           = "/usr/sbin/update-initramfs";
+my $package_name    = "linux-image-$version";
+
+my $Loader          = "NoLOADER"; # 
+$Loader             = "LILO"     if $loader =~ /^lilo/io;
+$Loader             = "SILO"     if $loader =~ /^silo/io;
+$Loader             = "QUIK"     if $loader =~ /^quik/io;
+$Loader             = "yaboot"   if $loader =~ /^yaboot/io;
+$Loader             = "PALO"     if $loader =~ /^palo/io;
+$Loader             = "NETTROM"  if $loader =~ /^nettrom/io;
+$Loader             = "VMELILO"  if $loader =~ /^vmelilo/io;
+$Loader             = "ZIPL"     if $loader =~ /^zipl/io;
+$Loader             = "ELILO"    if $loader =~ /^elilo/io;
+
+
+# This should not point to /tmp, because of security risks.
+my $temp_file_name = "/var/log/$loader" . "_log.$$";
+
+#known variables
+my @boilerplate     = ();
+my @silotemplate    = ();
+my @quiktemplate    = ();
+my @palotemplate    = ();
+my @vmelilotemplate = ();
+my $bootdevice      = '';
+my $rootdevice      = '';
+my $rootdisk        = '';
+my $rootpartition   = '';
+my $image_dest      = "/";
+my $realimageloc    = "/$image_dir/";
+my $have_conffile   = "";
+my $CONF_LOC        = '/etc/kernel-img.conf';
+my $relative_links = '';
+my $silent_modules  = '';
+my $silent_loader   = '';
+my $warn_reboot     = 'Yes';     # Warn that we are installing a version of
+                                 # the kernel we are running
+
+chdir('/')           or die "could not chdir to /:$!\n";
+# remove multiple leading slashes; make sure there is at least one.
+$realimageloc  =~ s|^/*|/|o;
+$realimageloc  =~ s|/+|/|o;
+
+
+if (-r "$CONF_LOC" && -f "$CONF_LOC"  ) {
+  if (open(CONF, "$CONF_LOC")) {
+    while (<CONF>) {
+      chomp;
+      s/\#.*$//g;
+      next if /^\s*$/;
+
+      $do_symlink      = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $no_symlink      = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $move_image      = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig;
+      $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig;
+      $do_boot_enable  = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig;
+      $do_bootfloppy   = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig;
+      $relative_links  = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig;
+      $do_bootloader   = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig;
+      $do_initrd       = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig;
+      $warn_initrd     = '' if /^\s*warn_initrd\s*=\s*(no|false|0)\s*$/ig;
+      $use_hard_links  = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig;
+      $silent_modules  = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig;
+      $silent_loader   = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig;
+      $warn_reboot     = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig;
+      $minimal_swap    = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig;
+      $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig;
+      $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig;
+      $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig;
+
+      $do_symlink      = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $no_symlink      = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $move_image      = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig;
+      $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig;
+      $do_boot_enable  = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootfloppy   = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootloader   = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig;
+      $relative_links  = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig;
+      $do_initrd       = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig;
+      $warn_initrd     = "Yes" if /^\s*warn_initrd\s*=\s*(yes|true|1)\s*$/ig;
+      $use_hard_links  = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_modules  = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_loader   = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig;
+      $warn_reboot     = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig;
+      $minimal_swap    = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig;
+      $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig;
+      $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig;
+      $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig;
+
+      $image_dest      = "$1"  if /^\s*image_dest\s*=\s*(\S+)/ig;
+      $postinst_hook   = "$1"  if /^\s*postinst_hook\s*=\s*(\S+)/ig;
+      $postrm_hook     = "$1"  if /^\s*postrm_hook\s*=\s*(\S+)/ig;
+      $preinst_hook    = "$1"  if /^\s*preinst_hook\s*=\s*(\S+)/ig;
+      $prerm_hook      = "$1"  if /^\s*prerm_hook\s*=\s*(\S+)/ig;
+      $ramdisk         = "$1"  if /^\s*ramdisk\s*=\s*(.+)$/ig;
+    }
+    close CONF;
+    $have_conffile = "Yes";
+  }
+}
+
+if ($link_in_boot) {
+  $image_dest = "/$image_dir/";
+  $image_dest =~ s|^/*|/|o;
+}
+
+$image_dest = "$image_dest/";
+$image_dest =~ s|/+$|/|o;
+
+# The destdir may be gone by now.
+if (-d "$image_dest") {
+  chdir("$image_dest") or die "could not chdir to $image_dest:$!\n";
+}
+
+# Paranoid check to make sure that the correct value is put in there
+if (! $kimage)                    {$kimage = "vmlinuz"} # Hmm. empty
+elsif ($kimage =~ m/^b?uImage$/o) {$kimage = "vmlinuz"} # these produce vmlinuz
+elsif ($kimage =~ m/^b?zImage$/o) {$kimage = "vmlinuz"} # these produce vmlinuz
+elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage;}
+elsif ($kimage =~ m/^vmlinux$/o)  { my $nop = $kimage;}
+else                              {$kimage = "vmlinuz"} # default
+
+$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch;
+
+
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+sub remove_sym_link {
+  my $bad_image = $_[0];
+
+  warn "Removing symbolic link $bad_image \n";
+  if ($loader =~ /lilo/i) 
+    {
+      warn "Unless you used the optional flag in lilo, \n";
+    }
+  warn " you may need to re-run your boot loader" . ($loader ? "[$loader]":"")
+    . "\n";
+  # Remove the dangling link
+  unlink "$bad_image";
+}
+
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+sub CanonicalizePath {
+  my $path = join '/', @_;
+  my @work = split '/', $path;
+  my @out;
+  my $is_absolute;
+
+  if (@work && $work[0] eq "") { $is_absolute = 1; shift @work; }
+
+  while (@work) {
+    my $seg = shift @work;
+    if ($seg eq "." || $seg eq "") {
+    } elsif ($seg eq "..") {
+      if (@out && $out[-1] ne "..") {
+        pop @out;
+      } else {
+        # Leading "..", or "../..", etc.
+        push @out, $seg;
+      }
+    } else {
+      push @out, $seg;
+    }
+  }
+
+  unshift @out, "" if $is_absolute;
+  return join('/', @out);
+}
+
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+# This removes dangling symlinks. What do we do about hard links? Surely a 
+# something with the nane $image_dest . "$kimage" ought not to be left behind? 
+sub image_magic {
+  my $kimage = $_[0];
+  my $image_dest = $_[1];
+
+  if (-l "$kimage") {
+    # There is a symbolic link
+    my $force_move = 0;
+    my $vmlinuz_target = readlink "$kimage";
+    my $real_target = '';
+    $real_target = abs_path($vmlinuz_target) if defined ($vmlinuz_target);
+    if (!defined($vmlinuz_target) || ! -f "$real_target") {
+      # what, a dangling symlink?
+      warn "The link "  . $image_dest . "$kimage is a damaged link\n";
+      # Remove the dangling link
+      &remove_sym_link("$kimage");
+    }
+    else {
+      my $canonical_target = CanonicalizePath("$vmlinuz_target");
+      if (! -e $canonical_target) {
+	warn "The link "  . $image_dest . "$kimage is a dangling link\n";
+	&remove_sym_link("$kimage");
+      }
+    }
+  }
+}
+
+# set the env var stem
+$ENV{'STEM'} = "linux";
+
+sub exec_script {
+  my $type   = shift;
+  my $script = shift;
+  print STDERR "Running $type hook script $script.\n";
+  system ("$script $version $realimageloc$kimage-$version") &&
+    print STDERR "User $type hook script [$script] ";
+  if ($?) {
+    if ($? == -1) {
+      print STDERR "failed to execute: $!\n";
+    }
+    elsif ($? & 127) {
+      printf STDERR "died with signal %d, %s coredump\n",
+        ($? & 127),  ($? & 128) ? 'with' : 'without';
+    }
+    else {
+      printf STDERR "exited with value %d\n", $? >> 8;
+    }
+  }
+}
+sub run_hook {
+  my $type   = shift;
+  my $script = shift;
+  if ($script =~ m,^/,) {
+    # Full path provided for the hook script
+    if (-x "$script") {
+      &exec_script($type,$script);
+    }
+    else {
+      warn "The provided $type hook script [$script] could not be run.\n";
+    }
+  }
+  else {
+    # Look for it in a safe path
+    for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') {
+      if (-x "$path/$script") {
+        &exec_script($type, "$path/$script");
+        return 0;
+      }
+    }
+    # No luck
+    print STDERR "Could not find $type hook script [$script].\n";
+    warn "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n";
+  }
+}
+
+## Run user hook script here, if any
+if ($postrm_hook) {
+  &run_hook("postrm", $postrm_hook);
+}
+if (-d "/etc/kernel/postrm.d") {
+  warn "Examining /etc/kernel/postrm.d .\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/postrm.d") &&
+            die "Failed to process /etc/kernel/postrm.d";
+}
+if (-d "/etc/kernel/postrm.d/$version") {
+  warn "Examining /etc/kernel/postrm.d/$version .\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/postrm.d/$version") &&
+            die "Failed to process /etc/kernel/postrm.d/$version";
+}
+
+# check and remove damaged and dangling symlinks
+if ($ARGV[0] !~ /upgrade/) {
+  system("$ramdisk -d -k " . $version . " > /dev/null 2>&1");
+  if (-f $realimageloc . "initrd.img-$version.bak") {
+    unlink $realimageloc . "initrd.img-$version.bak";
+  }
+  image_magic($kimage,          $image_dest);
+  image_magic($kimage . ".old", $image_dest);
+  image_magic("initrd.img",     $image_dest) if $initrd;
+  image_magic("initrd.img.old", $image_dest) if $initrd;
+}
+
+exit 0;
+
+__END__
+
+
+
+
+
+
--- linux-ec2-2.6.32.orig/debian/control-scripts/headers-postinst
+++ linux-ec2-2.6.32/debian/control-scripts/headers-postinst
@@ -0,0 +1,126 @@
+#!/usr/bin/perl
+#                              -*- Mode: Cperl -*- 
+# debian.postinst ---
+# Author           : Manoj Srivastava ( srivasta@pilgrim.umass.edu )
+# Created On       : Sat Apr 27 05:42:43 1996
+# Created On Node  : melkor.pilgrim.umass.edu
+# Last Modified By : Manoj Srivastava
+# Last Modified On : Sat Aug  5 13:20:22 2006
+# Last Machine Used: glaurung.internal.golden-gryphon.com
+# Update Count     : 45
+# Status           : Unknown, Use with caution!
+# HISTORY          :
+# Description      :
+#
+#
+#
+#  arch-tag: 1c716174-2f0a-476d-a626-a1322e62503a
+#
+
+
+$|=1;
+
+# Predefined values:
+my $version           = "=V";
+my $kimage            = "=K";
+my $package_name    = "linux-image-$version";
+
+
+# Ignore all invocations uxcept when called on to configure.
+exit 0 unless ($ARGV[0] && $ARGV[0] =~ /configure/);
+
+#known variables
+my $image_dest      = "/";
+my $realimageloc    = "/boot/";
+my $silent_modules  = '';
+my $modules_base    = '/lib/modules';
+my $CONF_LOC        = '/etc/kernel-img.conf';
+# remove multiple leading slashes; make sure there is at least one.
+$realimageloc  =~ s|^/*|/|o;
+$realimageloc  =~ s|/+|/|o;
+
+chdir '/usr/src' or die "Could not chdir to /usr/src:$!";
+
+if (-r "$CONF_LOC" && -f "$CONF_LOC"  ) {
+  if (open(CONF, "$CONF_LOC")) {
+    while (<CONF>) {
+      chomp;
+      s/\#.*$//g;
+      next if /^\s*$/;
+
+      $header_postinst_hook   = "$1"  if /^\s*header_postinst_hook\s*=\s*(\S+)/ig;
+    }
+    close CONF;
+  }
+}
+
+sub exec_script {
+  my $type   = shift;
+  my $script = shift;
+  print STDERR "Running $type hook script $script.\n";
+  system ("$script $version $realimageloc$kimage-$version") &&
+    print STDERR "User $type hook script [$script] ";
+  if ($?) {
+    if ($? == -1) {
+      print STDERR "failed to execute: $!\n";
+    }
+    elsif ($? & 127) {
+      printf STDERR "died with signal %d, %s coredump\n",
+        ($? & 127),  ($? & 128) ? 'with' : 'without';
+    }
+    else {
+      printf STDERR "exited with value %d\n", $? >> 8;
+    }
+    exit $? >> 8;
+  }
+}
+sub run_hook {
+  my $type   = shift;
+  my $script = shift;
+  if ($script =~ m,^/,) {
+    # Full path provided for the hook script
+    if (-x "$script") {
+      &exec_script($type,$script);
+    }
+    else {
+      die "The provided $type hook script [$script] could not be run.\n";
+    }
+  }
+  else {
+    # Look for it in a safe path
+    for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') {
+      if (-x "$path/$script") {
+        &exec_script($type, "$path/$script");
+        return 0;
+      }
+    }
+    # No luck
+    print STDERR "Could not find $type hook script [$script].\n";
+    die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n";
+  }
+}
+
+## Run user hook script here, if any
+if (-x "$header_postinst_hook") {
+  &run_hook("postinst", $header_postinst_hook);
+}
+
+if (-d "/etc/kernel/header_postinst.d") {
+  print STDERR "Examining /etc/kernel/header_postinst.d.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/header_postinst.d") &&
+            die "Failed to process /etc/kernel/header_postinst.d";
+}
+
+if (-d "/etc/kernel/header_postinst.d/$version") {
+  print STDERR "Examining /etc/kernel/header_postinst.d/$version.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/header_postinst.d/$version") &&
+            die "Failed to process /etc/kernel/header_postinst.d/$version";
+}
+
+exit 0;
+
+__END__
--- linux-ec2-2.6.32.orig/debian/control-scripts/postinst
+++ linux-ec2-2.6.32/debian/control-scripts/postinst
@@ -0,0 +1,1088 @@
+#! /usr/bin/perl
+# OriginalAuthor : Manoj Srivastava ( srivasta@pilgrim.umass.edu )
+#
+# Customized for Ubuntu by: Ben Collins <bcollins@ubuntu.com>
+
+#use strict; #for debugging
+use Cwd 'abs_path';
+
+$|=1;
+
+# Predefined values:
+my $version           = "=V";
+my $link_in_boot      = "";  # Should be empty, mostly
+my $no_symlink        = "";   # Should be empty, mostly
+my $reverse_symlink   = "";   # Should be empty, mostly
+my $do_symlink        = "Yes";  # target machine defined
+my $do_boot_enable    = "Yes";  # target machine defined
+my $do_bootfloppy     = "Yes";  # target machine defined
+my $do_bootloader     = "Yes";  # target machine defined
+my $move_image        = '';     # target machine defined
+my $kimage            = "=K";   # Should be empty, mostly
+my $loader            = "=L"; # lilo, silo, quik, palo, vmelilo, nettrom, arcboot or delo
+my $image_dir         = "/boot";        # where the image is located
+my $clobber_modules   = '';          # target machine defined
+my $relative_links    = "";          # target machine defined
+my $initrd            = "YES";        # initrd kernel
+my $do_initrd         = '';     # Normally we do not
+my $use_hard_links    = ''; # hardlinks do not work across fs boundaries
+my $postinst_hook     = '';          #Normally we do not
+my $postrm_hook       = '';          #Normally we do not
+my $preinst_hook      = '';          #Normally we do not
+my $prerm_hook        = '';          #Normally we do not
+my $minimal_swap      = '';          # Do not swap symlinks
+my $ignore_depmod_err = '';          # normally we do not
+my $kernel_arch       = "=B";
+my $ramdisk           = "/usr/sbin/update-initramfs";  # List of tools to create initial ram fs.
+my $notifier          = "/usr/share/update-notifier/notify-reboot-required";
+my $package_name      = "linux-image-$version";
+my $explicit_do_loader = 'Yes';
+
+my $Loader          = "NoLOADER"; #
+$Loader             = "LILO"     if $loader =~ /^lilo/io;
+$Loader             = "SILO"     if $loader =~ /^silo/io;
+$Loader             = "QUIK"     if $loader =~ /^quik/io;
+$Loader             = "yaboot"   if $loader =~ /^yaboot/io;
+$Loader             = "PALO"     if $loader =~ /^palo/io;
+$Loader             = "NETTROM"  if $loader =~ /^nettrom/io;
+$Loader             = "VMELILO"  if $loader =~ /^vmelilo/io;
+$Loader             = "ZIPL"     if $loader =~ /^zipl/io;
+$Loader             = "ELILO"    if $loader =~ /^elilo/io;
+$Loader             = "ARCBOOT"  if $loader =~ /^arcboot/io;
+$Loader             = "DELO"     if $loader =~ /^delo/io;
+
+# This should not point to /tmp, because of security risks.
+my $temp_file_name = "/var/log/$loader" . "_log.$$";
+
+#known variables
+my $image_dest      = "/";
+my $realimageloc    = "/$image_dir/";
+my $have_conffile   = "";
+my $silent_modules  = '';
+my $silent_loader   = '';
+my $warn_reboot     = 'Yes';     # Warn that we are installing a version of
+                                 # the kernel we are running
+
+my $modules_base    = '/lib/modules';
+my $CONF_LOC        = '/etc/kernel-img.conf';
+
+# Ignore all invocations except when called on to configure.
+exit 0 unless $ARGV[0] =~ /configure/;
+
+my $DEBUG = 0;
+
+# Do some preliminary sanity checks here to ensure we actually have an
+# valid image dir
+chdir('/')           or die "could not chdir to /:$!\n";
+die "Internal Error: ($image_dir) is not a directory!\n"
+  unless -d $image_dir;
+
+# remove multiple leading slashes; make sure there is at least one.
+$realimageloc  =~ s|^/*|/|o;
+$realimageloc  =~ s|/+|/|o;
+die "Internal Error: ($realimageloc) is not a directory!\n"
+  unless -d $realimageloc;
+
+if (-r "$CONF_LOC" && -f "$CONF_LOC"  ) {
+  if (open(CONF, "$CONF_LOC")) {
+    while (<CONF>) {
+      chomp;
+      s/\#.*$//g;
+      next if /^\s*$/;
+
+      $do_symlink      = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $no_symlink      = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig;
+      $reverse_symlink = "" if /^\s*reverse_symlink\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $link_in_boot    = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig;
+      $move_image      = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig;
+      $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig;
+      $do_boot_enable  = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig;
+      $do_bootfloppy   = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig;
+      $relative_links  = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig;
+      $do_bootloader   = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig;
+      $explicit_do_loader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig;
+      $do_initrd       = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig;
+      $use_hard_links  = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig;
+      $silent_modules  = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig;
+      $silent_loader   = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig;
+      $warn_reboot     = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig;
+      $minimal_swap    = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig;
+      $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig;
+
+      $do_symlink      = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $no_symlink      = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $link_in_boot    = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig;
+      $move_image      = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig;
+      $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig;
+      $do_boot_enable  = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootfloppy   = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig;
+      $do_bootloader   = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig;
+      $explicit_do_loader = "YES" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig;
+      $relative_links  = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig;
+      $do_initrd       = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig;
+      $use_hard_links  = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_modules  = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig;
+      $silent_loader   = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig;
+      $warn_reboot     = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig;
+      $minimal_swap    = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig;
+      $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig;
+
+      $image_dest      = "$1"  if /^\s*image_dest\s*=\s*(\S+)/ig;
+      $postinst_hook   = "$1"  if /^\s*postinst_hook\s*=\s*(\S+)/ig;
+      $postrm_hook     = "$1"  if /^\s*postrm_hook\s*=\s*(\S+)/ig;
+      $preinst_hook    = "$1"  if /^\s*preinst_hook\s*=\s*(\S+)/ig;
+      $prerm_hook      = "$1"  if /^\s*prerm_hook\s*=\s*(\S+)/ig;
+      $ramdisk         = "$1"  if /^\s*ramdisk\s*=\s*(.+)$/ig;
+    }
+    close CONF;
+    $have_conffile = "Yes";
+  }
+}
+
+
+
+# For some versions of kernel-package, we had this warning in the
+# postinst, but the rules did not really interpolate the value in.
+# Here is a sanity check.
+my $pattern = "=" . "I";
+$initrd=~ s/^$pattern$//;
+
+if ($link_in_boot) {
+  $image_dest = "/$image_dir/"; # same as realimageloc
+}
+
+# Tack on at least one trainling /
+$image_dest = "$image_dest/";
+$image_dest =~ s|^/*|/|o;
+$image_dest =~ s|/+$|/|o;
+
+if (! -d "$image_dest") {
+  die "Expected Image Destination dir ($image_dest) to be a valid directory!\n";
+}
+
+# sanity
+if (!($do_bootfloppy || $do_bootloader)) {
+  $do_boot_enable = '';
+}
+if ($do_symlink && $no_symlink) {
+  warn "Both do_symlinks and no_symlinks options enabled; disabling no_symlinks\n";
+  $no_symlink = 0;
+}
+
+# most of our work is done in $image_dest (nominally /)
+chdir("$image_dest") or die "could not chdir to $image_dest:$!\n";
+
+# Paranoid check to make sure that the correct value is put in there
+if    (! $kimage)                 { $kimage = "vmlinuz"; } # Hmm. empty
+elsif ($kimage =~ m/^b?uImage$/o) { $kimage = "vmlinuz"; } # these produce vmlinuz
+elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz"; } # these produce vmlinuz
+elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage;   }
+elsif ($kimage =~ m/^vmlinux$/o)  { my $nop = $kimage;   }
+else                              { $kimage = "vmlinuz"; } # Default
+
+$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch;
+
+
+die "Internal Error: Could not find image (" . $realimageloc
+  . "$kimage-$version)\n" unless -e $realimageloc
+  . "$kimage-$version";
+
+# search for the boot loader in the path
+my $loader_exec;
+($loader_exec = $loader)  =~ s|.*/||;
+my ($loaderloc) = grep -x, map "$_/$loader_exec",
+  map { length($_) ? $_ : "." }  split /:/, $ENV{PATH};
+
+
+######################################################################
+######################################################################
+###########        Test whether a relative symlinkwould be OK #######
+######################################################################
+######################################################################
+sub test_relative {
+  my %params = @_;
+  my $cwd;
+
+  die "Internal Error: Missing Required paramater 'Old Dir' "
+    unless $params{'Old Dir'};
+  die "Internal Error: Missing Required paramater New Dir' "
+    unless $params{'New Dir'};
+
+
+  die "Internal Error: No such dir $params{'Old Dir'} "
+    unless -d $params{'Old Dir'};
+  die "Internal Error: No such dir $params{'New Dir'} "
+    unless -d $params{'New Dir'};
+
+  warn "Test relative: testing $params{'Old Dir'} -> $params{'New Dir'}"
+    if $DEBUG;
+  chomp($cwd = `pwd`);
+  chdir ($params{'New Dir'}) or die "Could not chdir to $params{'New Dir'}:$!";
+  my $ok = 0;
+  $params{'Old Dir'}  =~ s|^/*||o;
+  if (-d $params{'Old Dir'} ) {
+    if (defined $params{'Test File'}) {
+      if (-e $params{'Old Dir'} . $params{'Test File'}) {
+        $ok  = 1;
+      }
+    } else {
+      $ok = 1;                  # well, backward compatibility
+    }
+  }
+  chdir ($cwd) or die "Could not chdir to $params{'New Dir'}:$!";
+  return $ok;
+}
+
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+# sub CanonicalizePath {
+#   my $path = join '/', @_;
+#   my @work = split '/', $path;
+#   my @out;
+#   my $is_absolute;
+
+#   if (@work && $work[0] eq "") {
+#     $is_absolute = 1; shift @work;
+#   }
+
+#   while (@work) {
+#     my $seg = shift @work;
+#     if ($seg eq "." || $seg eq "") {
+#     } 
+#     elsif ($seg eq "..") {
+#       if (@out && $out[-1] ne "..") {
+#         pop @out;
+#       } 
+#       else {
+#         # Leading "..", or "../..", etc.
+#         push @out, $seg;
+#       }
+#     } 
+#     else {
+#       push @out, $seg;
+#     }
+#   }
+
+#   unshift @out, "" if $is_absolute;
+#   return join('/', @out);
+# }
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+
+sub spath {
+  my %params = @_;
+
+  die "Missing Required paramater 'Old'" unless $params{'Old'};
+  die "Missing Required paramater 'New'" unless  $params{'New'};
+
+  my @olddir  = split '/', `readlink -q -m $params{'Old'}`;
+  my @newdir  = split '/', `readlink -q -m $params{'New'}`;
+  my @outdir  = @olddir;
+
+  my $out = '';
+  my $i;
+  for ($i = 0; $i <= $#olddir && $i <= $#newdir; $i++) {
+    $out++ if ($olddir[$i] ne $newdir[$i]);
+    shift @outdir unless $out;
+    unshift @outdir, ".." if $out;
+  }
+  if ($#newdir > $#olddir) {
+    for ($i=0; $i < $#newdir; $i++) {
+      unshift @outdir, "..";
+    }
+  }
+  return join ('/', @outdir);
+}
+######################################################################
+######################################################################
+############
+######################################################################
+######################################################################
+
+
+# This routine actually moves the kernel image
+# From: $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12)
+# To:   $image_dest/$kimage-$version   (/vmlinuz-2.6.12)
+# Note that the image is moved to a versioned destination, but ordinary
+# symlinks we create otherwise are not normally versioned
+sub really_move_image {
+  my $src_dir  = $_[0];
+  my $target   = $_[1];
+  my $dest_dir = $_[2];
+
+  warn "Really move image: src_dir=$src_dir, target=$target,\n destdir=$dest_dir"
+    if $DEBUG;
+  if (-e "$target") {
+    # we should be in dir $dest_dir == $image_dest /, normally
+    rename("$target", "$target.$$") ||
+      die "failed to move " . $dest_dir . "$target:$!";
+    warn "mv $target $target.$$" if $DEBUG;
+  }
+  warn "mv -f $src_dir$target $target" if $DEBUG;
+  my $ret = system("mv -f " . $src_dir . "$target " .
+                   " $target");
+  if ($ret) {
+    die("Failed to move " . $src_dir . "$target to "
+        . $dest_dir . "$target.\n");
+  }
+  # Ok, now we may clobber the previous .old files
+  if (-e "$target.$$") {
+    rename("$target.$$", "$target.old") ||
+      die "failed to move " . $dest_dir . "$target:$!";
+    warn "mv $target.$$ $target " if $DEBUG;
+  }
+}
+
+# Normally called after really_move_image; and only called if we asked for 
+# reversed link this routine reverses the symbolic link that is notmally 
+# created. Since the real kernel image has been moved over to 
+# $image_dest/$kimage-$version. So, this routine links
+# From:   $image_dest/$kimage-$version   (/vmlinuz-2.6.12)
+# To:     $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12)
+sub really_reverse_link {
+  my $src_dir    = $_[0];
+  my $link_name  = $_[1];
+  my $dest_dir   = $_[2];
+  warn "Really reverse link: src_dir=$src_dir, link name=$link_name\n" .
+    "\tdestdir=$dest_dir" if $DEBUG;
+
+  my $Old = $dest_dir;
+  if (test_relative ('Old Dir' => $Old, 'New Dir' => $src_dir,
+                     'Test File' => "$link_name")) {
+    $Old   =~ s|^/*||o;
+  }
+  # Special case is they are in the same dir
+  my $rel_path = spath('Old' => "$Old", 'New' => "$src_dir" );
+  $Old ="" if $rel_path =~ m/^\s*$/o;
+
+  if ($use_hard_links =~ m/YES/i) {
+    link($Old . "$link_name", $src_dir . "$link_name") ||
+      die("Failed to link " . $dest_dir . "$link_name to " . $src_dir . 
+          "$link_name .\n");
+    warn "ln " . $Old . "$link_name " . $src_dir . "$link_name"  if $DEBUG;
+  }
+  else {
+    symlink($Old . "$link_name", $src_dir . "$link_name") ||
+      die("Failed to symbolic-link " . $dest_dir . "$link_name to " . $src_dir
+          . "$link_name : $!\n");
+    warn "ln -s " . $Old . "$link_name " . $src_dir . "$link_name" if $DEBUG;
+  }
+}
+
+# This routine is invoked if there is a symbolic link in place
+# in $image_dest/$kimage -- so a symlink exists in the destination.
+# What we are trying to determine is if we need to move the symbolic link over
+# to the the .old location
+sub move_p {
+  my $kimage     = $_[0];       # Name of the symbolic link
+  my $image_dest = $_[1];       # The directory the links goes into
+  my $image_name = $_[2]; 
+  my $src_dir    = $_[3]; 
+  my $force_move = 0;
+  warn "Move?: kimage=$kimage, image_dest=$image_dest, \n" .
+    "\timage_name=$image_name, src_dir=$src_dir" if $DEBUG;
+
+  if ($no_symlink || $reverse_symlink) {
+    # we do not want links, yet we have a symbolic link here!
+    warn "found a symbolic link in " . $image_dest . "$kimage \n" .
+      "even though no_symlink is defined\n" if $no_symlink;
+    warn "found a symbolic link in " . $image_dest . "$kimage \n" .
+      "even though reverse_symlink is defined\n" if $reverse_symlink;
+    # make sure we change this state of affairs
+    $force_move = 1;
+    return $force_move;
+  }
+
+  warn "DEBUG: OK. We found symlink, and we should have a symlink here.\n"
+    if $DEBUG;
+  my $vmlinuz_target = readlink "$kimage";
+  my $real_target = '';
+  my $target = `readlink -q -m "${realimageloc}${kimage-$version}"`;
+  $real_target = abs_path($vmlinuz_target) if defined($vmlinuz_target);
+
+  if (!defined($vmlinuz_target) || ! -f "$real_target") {
+    # what, a dangling symlink?
+    warn "The link "  . $image_dest . "$kimage is a dangling link" .
+      "to $real_target\n";
+    $force_move = 1;
+    return $force_move;
+  }
+
+
+  warn "DEBUG: The link $kimage points to ($vmlinuz_target)\n" if $DEBUG;
+  warn "DEBUG: ($vmlinuz_target) is really ($real_target)\n" if $DEBUG;
+  my $cwd;
+  chomp ($cwd=`pwd`);
+  if ($vmlinuz_target !~ m|^/|o) {
+    $vmlinuz_target = $cwd . "/" . $vmlinuz_target;
+    $vmlinuz_target =~ s|/+|/|o;
+  }
+  $vmlinuz_target = `readlink -q -m $vmlinuz_target`;
+
+  if ("$vmlinuz_target" ne "$target") {
+    warn "DEBUG: We need to handle this.\n" if $DEBUG;
+    if ($minimal_swap) {
+      warn "DEBUG: Minimal swap.\n" if $DEBUG;
+      if (-l "$kimage.old") {
+        warn "DEBUG: There is an old link at $kimage.old\n" if $DEBUG;
+        my $old_target = readlink "$kimage.old";
+        my $real_old_target = '';
+        $real_old_target=abs_path($old_target) if defined ($old_target);
+
+        if ($real_old_target  && -f "$real_old_target") {
+          if ($old_target !~ m|^/|o) {
+            $old_target = $cwd . "/" . $old_target;
+            $old_target =~ s|/+|/|o;
+          }
+          $old_target = `readlink -q -m $old_target`;
+          if ("$old_target"  ne "$target") {
+            $force_move = 1;
+            warn "DEBUG: Old link ($old_target) does not point to us ($target)\n"
+              if $DEBUG;
+          } 
+          else {            # The .old points to the current
+            warn "$kimage.old --> $target -- doing nothing";
+            $force_move = 0;
+          }
+        } 
+        else { 
+          warn "DEBUG: Well, the old link does not exist -- so we move\n"
+            if $DEBUG;
+          $force_move = 1;
+        }
+      } 
+      else {
+        warn "DEBUG: No .old link -- OK to move\n"
+          if $DEBUG;
+        $force_move = 1;
+      }
+    } 
+    else {
+      warn "DEBUG: ok, minimal swap is no-- so we move.\n"
+        if $DEBUG;
+      $force_move = 1;
+    }
+  }
+  else {                  # already have proper link
+    warn "$kimage($vmlinuz_target) points to $target ($real_target) -- doing nothing";
+    $force_move = 0;
+  }
+  return $force_move;
+}
+
+
+# This routine moves the symbolic link around (/vmlinuz -> /vmlinuz.old)
+# It pays attention to whether we should the fact whether we should be using
+# hard links or not.
+sub really_move_link {
+  my $kimage     = $_[0];       # Name of the symbolic link
+  my $image_dest = $_[1];       # The directory the links goes into
+  my $image_name = $_[2]; 
+  my $src_dir    = $_[3]; 
+  warn "really_move_link: kimage=$kimage, image_dest=$image_dest\n" .
+    "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG;
+
+  # don't clobber $kimage.old quite yet
+  rename("$kimage", "$kimage.$$") ||
+    die "failed to move " . $image_dest . "$kimage:$!";
+  warn "mv $kimage $kimage.$$" if $DEBUG;
+  my $Old = $src_dir;
+  my $cwd;
+
+  chomp($cwd=`pwd`);
+  if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd,
+                     'Test File' => "$image_name")) {
+    $Old   =~ s|^/*||o;
+  }
+  # Special case is they are in the same dir
+  my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" );
+  $Old ="" if $rel_path =~ m/^\s*$/o;
+
+  if ($use_hard_links =~ m/YES/i) {
+    warn "ln ${Old}${image_name} $kimage" if $DEBUG;
+    if (! link("${Old}${image_name}", "$kimage")) {
+      rename("$kimage.$$", "$kimage");
+      die("Failed to link ${Old}${image_name} to " .
+          "${image_dest}${kimage}.\n");
+    }
+  } 
+  else {
+    warn "ln -s ${Old}${image_name} $kimage" if $DEBUG;
+    if (! symlink("${Old}${image_name}", "$kimage")) {
+      rename("$kimage.$$", "$kimage");
+      die("Failed to symbolic-link ${Old}${image_name} to " .
+          "${image_dest}${kimage}: $!\n");
+    }
+  }
+
+  # Ok, now we may clobber the previous .old file
+  if (-l "$kimage.old" || ! -e "$kimage.old" ) {
+    rename("$kimage.$$", "$kimage.old");
+    warn "mv $kimage.$$ $kimage.old" if $DEBUG;
+  }
+  else {
+    warn "$kimage.old is not a symlink, not clobbering\n";
+    warn "rm $kimage.$$";
+    unlink "$kimage.$$" if $DEBUG;
+  }
+}
+
+# This routine handles a request to do symlinks, but there is no
+# symlink file already there.  Either we are supposed to use copy, or we are
+# installing on a pristine system, or the user does not want symbolic links at
+# all.  We use a configuration file to tell the last two cases apart, creating
+# a config file if needed.
+sub handle_missing_link {
+  my $kimage     = $_[0];       # Name of the symbolic link
+  my $image_dest = $_[1];       # The directory the links goes into
+  my $image_name = $_[2]; 
+  my $src_dir    = $_[3]; 
+  warn "handle_missing_link: kimage=$kimage, image_dest=$image_dest\n" .
+    "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG;
+
+  if ($no_symlink) {
+    warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG;
+    my $ret = system("cp -a --backup=t " . $realimageloc .
+                     "$image_name "   . " $kimage");
+    if ($ret) {
+      die("Failed to copy " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+  } 
+  elsif ($reverse_symlink) {
+    warn "mv -f $realimageloc$image_name $kimage" if $DEBUG;
+    my $ret = system("mv -f " . $realimageloc . "$image_name "
+                     . "$kimage");
+    if ($ret) {
+      die("Failed to move " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+  } 
+  else {
+    if (! $have_conffile) {
+      my $ret;
+      my $answer='';
+      $do_symlink = "Yes";
+
+      if (open(CONF, ">$CONF_LOC")) {
+        print CONF "# Kernel Image management overrides\n";
+        print CONF "# See kernel-img.conf(5) for details\n";
+        if ($loader =~ /palo/i) {
+          print CONF "link_in_boot = Yes\n";
+          print CONF "do_symlinks = Yes\n";
+          print CONF "relative_links = Yes\n";
+          print CONF "do_bootloader = No\n";
+        } else {
+          print CONF "do_symlinks = $do_symlink\n";
+        }
+        close CONF;
+      }
+      $have_conffile = "Yes";
+    }
+  }
+
+  if (! $no_symlink && $do_symlink =~ /Yes/i) {
+    my $Old = $realimageloc;
+    my $New = $image_dest;
+    my $Name = "$image_name";
+    my $Link_Dest = "$kimage";
+
+    if ($reverse_symlink) {
+      $Old = $image_dest;
+      $New = $realimageloc;
+      $Name = "$kimage";
+      $Link_Dest = $realimageloc . "$image_name";
+    }
+    if (test_relative ('Old Dir' => $Old,
+                       'New Dir' => $New,
+                       'Test File' => $Name)) {
+      $Old   =~ s|^/*||o;
+    }
+    # Special case is they are in the same dir
+    my $rel_path = spath('Old' => "$Old", 'New' => "$New" );
+    $Old ="" if $rel_path =~ m/^\s*$/o;
+
+    symlink($Old . "$Name", "$Link_Dest") ||
+      die("Failed to symbolic-link ${Old}$Name to $Link_Dest: $!\n");
+    warn "ln -s ${Old}$Name $Link_Dest" if $DEBUG;
+
+  }
+}
+
+# This routine handles the rest of the cases, where the user has requested 
+# non-traditional handling, like using cp, or reverse symlinks, or hard links.
+sub handle_non_symlinks {
+  my $kimage     = $_[0];       # Name of the symbolic link
+  my $image_dest = $_[1];       # The directory the links goes into
+  my $image_name = $_[2]; 
+  my $src_dir    = $_[3]; 
+  warn "handle_non_link: kimage=$kimage, image_dest=$image_dest\n" .
+    "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG;
+
+  # Save the current image. We do this in all four cases
+  rename("$kimage", "$kimage.$$") || 
+    die "failed to move " . $image_dest . "$kimage:$!";
+  warn "mv $kimage $kimage.$$" if $DEBUG;
+
+  ##,#### 
+  # case One
+  #`####
+  if ($no_symlink) {
+    # Maybe /$image_dest is on a dos system?
+    warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG;
+    my $ret = system("cp -a --backup=t " . $realimageloc
+                     . "$image_name " . "$kimage");
+    if ($ret) {
+      if (-e "$kimage.$$") {
+        rename("$kimage.$$", "$kimage");
+        warn "mv $kimage.$$ $kimage" if $DEBUG;
+      }
+      die("Failed to copy " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+  }
+  ##,#### 
+  # case Two
+  #`####
+  elsif ($reverse_symlink) {  # Maybe /$image_dest is on a dos system?
+    warn "mv -f  $realimageloc$image_name $kimage" if $DEBUG;
+    my $ret = system("mv -f " . $realimageloc . "$image_name "
+                     . $image_dest . "$kimage");
+    if ($ret) {
+      if (-e "$kimage.$$") {
+        rename("$kimage.$$", "$kimage");
+        warn "mv $kimage.$$ $kimage" if $DEBUG;
+      }
+      die("Failed to move " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+    my $Old = $image_dest;
+    if (test_relative ('Old Dir' => $Old, 'New Dir' => $realimageloc,
+                       'Test File' => "$kimage")) {
+      $Old   =~ s|^/*||o;
+    }
+    # Special case is they are in the same dir
+    my $rel_path = spath('Old' => "$Old", 'New' => "$realimageloc" );
+    $Old ="" if $rel_path =~ m/^\s*$/o;
+
+    if ($use_hard_links =~ m/YES/i) {
+      warn "ln " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG;
+      if (! link($Old . "$kimage", $realimageloc . "$image_name")) {
+        warn "Could not link " . $image_dest .
+          "$kimage to $image_name :$!";
+      }
+    }
+    else {
+      warn "ln -s " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG;
+      if (! symlink($Old . "$kimage", $realimageloc . "$image_name")) {
+        warn "Could not symlink " . $image_dest .
+          "$kimage to $image_name :$!";
+      }
+    }
+  }
+  ##,####
+  # case Three
+  #`####
+  elsif ($use_hard_links =~ m/YES/i ) {
+    # Ok then. this ought to be a hard link, and hence fair game
+    # don't clobber $kimage.old quite yet
+    my $Old = $realimageloc;
+    my $cwd;
+    chomp($cwd=`pwd`);
+    if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd,
+                       'Test File' => "$image_name")) {
+      $Old   =~ s|^/*||o;
+    }
+    # Special case is they are in the same dir
+    my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" );
+    $Old ="" if $rel_path =~ m/^\s*$/o;
+
+    warn "ln " . $Old . "$image_name " . "$kimage" if $DEBUG;
+    if (! link($Old . "$image_name", "$kimage")) {
+      warn "mv $kimage.$$ $kimage" if $DEBUG;
+      rename("$kimage.$$", "$kimage");
+      die("Failed to link " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+  }
+  ##,####
+  # case Four
+  #`####
+  else {
+    # We just use cp
+    warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG;
+    my $ret = system("cp -a --backup=t " . $realimageloc
+                     . "$image_name " . "$kimage");
+    if ($ret) {
+      if (-e "$kimage.$$") {
+        warn "mv $kimage.$$ $kimage" if $DEBUG;
+        rename("$kimage.$$", "$kimage");
+      }
+      die("Failed to copy " . $realimageloc . "$image_name to "
+          . $image_dest . "$kimage .\n");
+    }
+  }
+  # Ok, now we may clobber the previous .old file
+  warn "mv $kimage.$$ $kimage.old if -e $kimage.$$" if $DEBUG;
+  rename("$kimage.$$", "$kimage.old") if -e "$kimage.$$";
+}
+
+# This routine is responsible for setting up the symbolic links
+# So, the actual kernel image lives in
+# $realimageloc/$image_name (/boot/vmlinuz-2.6.12).
+# This routine creates symbolic links in $image_dest/$kimage (/vmlinuz)
+sub image_magic {
+  my $kimage     = $_[0];       # Name of the symbolic link
+  my $image_dest = $_[1];       # The directory the links goes into
+  my $image_name = "$kimage-$version";
+  my $src_dir    = $realimageloc;
+  warn "image_magic: kimage=$kimage, image_dest=$image_dest\n" .
+    "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG;
+
+  # Well, in any case, if the destination (the symlink we are trying
+  # to create) is a directory, we should do nothing, except throw a
+  # diagnostic.
+  if (-d "$kimage" ) {
+    die ("Hmm. $kimage is a directory, which I did not expect.  I am\n" .
+         "trying to create a symbolic link with that name linked to \n" .
+         "$image_dest . Since a directory exists here, my assumptions \n" .
+         "are way off, and I am aborting.\n" );
+    exit (3);
+  }
+
+  if ($move_image) {   # Maybe $image_dest is in on dos, or something?
+    #                   source dir,    link name,        dest dir
+    really_move_image(  $realimageloc, $image_name, $image_dest);
+    really_reverse_link($realimageloc, $image_name, $image_dest)
+      if $reverse_symlink;
+    return;
+  }
+
+  if (-l "$kimage") {           # There is a symbolic link
+    warn "DEBUG: There is a symlink for $kimage\n" if $DEBUG;
+    my $force_move = move_p($kimage, $image_dest, $image_name, $src_dir);
+
+    if ($force_move) {
+      really_move_link($kimage, $image_dest, $image_name, $src_dir);
+    }
+  }
+  elsif (! -e "$kimage") {
+    # Hmm. Pristine system? How can that be? Installing from scratch?
+    # Or maybe the user does not want a symbolic link here.
+    # Possibly they do not want a link here. (we should be in /
+    # here[$image_dest, really]
+    handle_missing_link($kimage, $image_dest, $image_name, $src_dir);
+  }
+  elsif (-e "$kimage" ) {
+    # OK, $kimage exists -- but is not a link
+    handle_non_symlinks($kimage, $image_dest, $image_name, $src_dir);
+  }
+}
+
+######################################################################
+######################################################################
+######################################################################
+######################################################################
+
+# We may not have any modules installed
+if ( -d "$modules_base/$version" ) {
+  print STDERR "Running depmod.\n";
+  my $ret = system("depmod -a $version");
+  if ($ret) {
+    print STDERR "Failed to run depmod\n";
+    exit(1);
+  }
+}
+
+
+
+sub find_initrd_tool {
+  my $hostversion = shift;
+  my $version = shift;
+  print STDERR "Finding valid ramdisk creators.\n";
+  my @ramdisks =
+    grep {
+      my $args = 
+        "$_ " .
+          "--supported-host-version=$hostversion " .
+            "--supported-target-version=$version " .
+              "1>/dev/null 2>&1"
+                ;
+      system($args) == 0;
+    }
+      split (/[:,\s]+/, $ramdisk);
+}
+
+# The initrd symlink should probably be in the same dir that the
+# symlinks are in
+if ($initrd) {
+  my $success = 0;
+
+  # Update-initramfs is called slightly different than mkinitrd and
+  # mkinitramfs. XXX It should really be made compatible with this stuff
+  # some how.
+  my $upgrading = 1;
+  if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m/<unknown>/og) {
+    $upgrading = 0;
+  }
+  my $ret = system("$ramdisk " . ($upgrading ? "-u" : "-c") . " -k " . $version . " >&2");
+  $success = 1 unless $ret;
+  die "Failed to create initrd image.\n" unless $success;
+  if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m/<unknown>/og) {
+    image_magic("initrd.img", $image_dest);
+  }
+  else {
+    if (! -e "initrd.img") {
+      handle_missing_link("initrd.img", $image_dest, "initrd.img-$version",
+                          $realimageloc);
+    }
+    else {
+      print STDERR
+        "Not updating initrd symbolic links since we are being updated/reinstalled \n";
+      print STDERR
+        "($ARGV[1] was configured last, according to dpkg)\n";
+    }
+  }
+
+  if ($initrd && -l "initrd" ) {
+    unlink "initrd";
+  }
+
+  if ($initrd && -l "$image_dir/initrd" && ! $link_in_boot) {
+    unlink "$image_dir/initrd";
+  }
+}
+else {                        # Not making an initrd emage
+  if (-l "initrd.img") {
+    # Ooh, last image was an initrd image? in any case, we should move it. 
+    my $target = readlink "initrd.img";
+    my $real_target = '';
+    $real_target = abs_path($target) if defined ($target);
+
+    if (!defined($target) || ! -f "$real_target") {
+      # Eh. dangling link. can safely be removed.
+      unlink("initrd.img");
+    } else {
+      if (-l "initrd.img.old" || ! -e "initrd.img.old" ) {
+        rename("initrd.img", "initrd.img.old");
+      } else {
+        warn "initrd.img.old is not a symlink, not clobbering\n";
+        unlink("initrd.img");
+      }
+    }
+  }
+}
+
+# Warn of a reboot
+if (-x $notifier) {
+  system($notifier);
+}
+
+# Let programs know not to hibernate if the kernel that would be used for
+# resume-from-hibernate is likely to differ from the currently running kernel.
+system("mountpoint -q /var/run");
+if ($? eq 0) {
+	system("touch /var/run/do-not-hibernate");
+}
+
+# Only change the symlinks if we are not being upgraded
+if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m/<unknown>/og) {
+  image_magic($kimage, $image_dest);
+}
+else {
+  if (! -e "$kimage") {
+    handle_missing_link($kimage, $image_dest, "$kimage-$version", 
+                        $realimageloc);
+  }
+  else {
+    print STDERR
+      "Not updating image symbolic links since we are being updated/reinstalled \n";
+    print STDERR
+      "($ARGV[1] was configured last, according to dpkg)\n";
+  }
+}
+
+# We used to have System.* files in /
+if (-e "/System.map" || -e "/System.old") {
+  unlink '/System.map' if -e '/System.map';
+  unlink '/System.old' if -e '/System.old';
+}
+
+# creating some info about kernel and initrd
+if ($DEBUG) {
+  my $ksize=sprintf("%.0f",(stat($realimageloc .
+                                 "$kimage-$version"))[7]/1024)."kB";
+  my $initrdsize='';
+  if ($initrd) {
+    $initrdsize=sprintf("%.0f",(stat($realimageloc .
+                                     "initrd.img-$version"))[7]/1024)."kB";
+  }
+
+  print STDERR <<"EOMSG";
+A new kernel image has been installed at $realimageloc$kimage-$version
+ (Size: $ksize)
+
+Symbolic links, unless otherwise specified, can be found in $image_dest
+
+EOMSG
+  ;
+
+  if ($initrd) {
+    print STDERR <<"EOMSGA";
+
+ Initial rootdisk image: ${realimageloc}initrd.img-$version (Size: $initrdsize)
+EOMSGA
+    ;
+  }
+}
+
+# set the env var stem
+$ENV{'STEM'} = "linux";
+sub exec_script {
+  my $type   = shift;
+  my $script = shift;
+  print STDERR "Running $type hook script $script.\n";
+  system ("$script $version $realimageloc$kimage-$version") &&
+    print STDERR "User $type hook script [$script] ";
+  if ($?) {
+    if ($? == -1) {
+      print STDERR "failed to execute: $!\n";
+    }
+    elsif ($? & 127) {
+      printf STDERR "died with signal %d, %s coredump\n",
+        ($? & 127),  ($? & 128) ? 'with' : 'without';
+    }
+    else {
+      printf STDERR "exited with value %d\n", $? >> 8;
+    }
+    exit $? >> 8;
+  }
+}
+sub run_hook {
+  my $type   = shift;
+  my $script = shift;
+  if ($script =~ m,^/,) {
+    # Full path provided for the hook script
+    if (-x "$script") {
+      &exec_script($type,$script);
+    }
+    else {
+      die "The provided $type hook script [$script] could not be run.\n";
+    }
+  }
+  else {
+    # Look for it in a safe path
+    for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') {
+      if (-x "$path/$script") {
+        &exec_script($type, "$path/$script");
+        return 0;
+      }
+    }
+    # No luck
+    print STDERR "Could not find $type hook script [$script].\n";
+    die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n";
+  }
+}
+
+## Run user hook script here, if any
+if ($postinst_hook) {
+  &run_hook("postinst", $postinst_hook);
+}
+
+if (-d "/etc/kernel/postinst.d") {
+  print STDERR "Examining /etc/kernel/postinst.d.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/postinst.d") &&
+            die "Failed to process /etc/kernel/postinst.d";
+}
+
+if (-d "/etc/kernel/postinst.d/$version") {
+  print STDERR "Examining /etc/kernel/postinst.d/$version.\n";
+  system ("run-parts --verbose --exit-on-error --arg=$version " .
+          "--arg=$realimageloc$kimage-$version " .
+          "/etc/kernel/postinst.d/$version") &&
+            die "Failed to process /etc/kernel/postinst.d/$version";
+}
+
+LOADER: {
+  last unless $do_boot_enable; # Exit if explicitly asked to
+
+  last if $loader =~ /silo/i; # SILO does not have to be executed.
+  last if $loader =~ /yaboot/i; # yaboot does not have to be executed.
+  last if $loader =~ /milo/i; # MILO does not have to be executed.
+  last if $loader =~ /nettrom/i; # NETTROM does not have to be executed.
+  last if $loader =~ /arcboot/i; # ARCBOOT does not have to be executed.
+  last if $loader =~ /delo/i; # DELO does not have to be executed.
+  last if $loader =~ /quik/i; # maintainer asked quik invocation to be ignored
+
+  last unless $loaderloc;
+  last unless -x $loaderloc;
+  last unless $do_bootloader;
+
+  if (-T "/etc/$loader.conf") {
+    # Trust and use the existing lilo.conf.
+    print STDERR "You already have a $Loader configuration in /etc/$loader.conf\n";
+    my $ret = &run_lilo();
+    exit $ret if $ret;
+  }
+}
+
+
+sub run_lilo (){
+  my $ret;
+  # Try and figure out if the user really wants lilo to be run --
+  # since the default is to run the boot laoder, which is ! grub -- but
+  # the user may be using grub now, and not changed the default.
+
+  # So, if the user has explicitly asked for the loader to be run, or
+  # if there is no postinst hook, or if there is no grub installed --
+  # we are OK. Or else, we ask.
+  if ($explicit_do_loader || (! ($postinst_hook && -x '/usr/sbin/grub')))  {
+    print STDERR "Running boot loader as requested\n";
+  } else {
+    print STDERR "Ok, not running $loader\n";
+  }
+  if ($loader =~ /^lilo/io or $loader =~ /vmelilo/io) {
+    print STDERR "Testing $loader.conf ... \n";
+    unlink $temp_file_name;     # security
+    $ret = system("$loaderloc -t >$temp_file_name 2>&1");
+    if ($ret) {
+      print STDERR "Boot loader test failed\n";
+      return $ret;
+    }
+    unlink "$temp_file_name";
+    print STDERR "Testing successful.\n";
+    print STDERR "Installing the ";
+    print STDERR "partition " if $loader =~ /^lilo/io;
+    print STDERR "boot sector... \n";
+  }
+
+  print STDERR "Running $loaderloc  ... \n";
+  if ($loader =~ /^elilo/io) {
+    $ret = system("$loaderloc 2>&1 | tee $temp_file_name");
+  } else {
+    $ret = system("$loaderloc >$temp_file_name 2>&1");
+  }
+  if ($ret) {
+    print STDERR "Boot loader failed to run\n";
+    return $ret;
+  }
+  unlink $temp_file_name;
+  print STDERR "Installation successful.\n";
+  return 0;
+}
+
+exit 0;
+
+__END__
+
--- linux-ec2-2.6.32.orig/debian/stamps/keep-dir
+++ linux-ec2-2.6.32/debian/stamps/keep-dir
@@ -0,0 +1 @@
+Place holder
--- linux-ec2-2.6.32.orig/debian/docs/README.inclusion-list
+++ linux-ec2-2.6.32/debian/docs/README.inclusion-list
@@ -0,0 +1,51 @@
+This README describes the reason for, and the use of, module
+inclusion lists.
+
+The original Hardy release had the notion of sub-flavours,
+e.g., a flavour that was constructed as a subset of an existing flavour.
+For example, the virtual flavour was extracted from the server flavour using
+a subset of the server flavour modules. However, there were some difficult
+mainteneance issues with regard to packaging, make rules, and scripts. This
+re-implementation of the sub-flavours philosophy is hopefully simpler,
+and retrofitable to all releases.
+
+A module inclusion list looks at the problem of of constructing a package
+from the perspective of what modules do we _want_ in the package, as opposed
+to what modules we _don't_ want. As the kernel matures, more and more devices are added
+which makes the problem of configuration maintenance a real pain in the ass.
+If we took the approach of disabling all of the config options that we don't want,
+then the differences between flavours will quickly become quite large, making
+it difficult to quickly compare the individual flavour configs.  Each time a
+new config option is added then we also have to make a decision about disabling in
+order to continue to keep the minimal number of modules.
+
+A module inclusion list is applied on a per-flavour basis. For example,
+debian.<BRANCH>/control.d/${flavour}.inclusion-list. For example, the
+config for virtual is very close to server and generic, but the inclusion list
+causes the virtual package to be constructed with _only_ the modules described 
+in the inclusion list.
+
+The inclusion list format is a simple bash regular expression list of files. For example,
+
+arch/*/{crypto,kernel,oprofile}
+drivers/acpi/*
+drivers/ata/ahci.ko
+
+These 3 regular expression forms are suitable for expansion by bash and as inputs to 'find'.
+See debian/scripts/module-inclusion for details.
+
+There are 2 log files created as a side effect of the application of the module
+inclusion list; $(flavour).inclusion-list.log and $(flavour).depmod.log.
+
+$(flavour).inclusion-list.log : This log is created while the inclusion list
+modules are being copied. If any are missing, then those warnings go in this log.
+While its not considered a fatal error, you should endevour to correct your inclusion
+list such that there are no missing modules.
+
+$(flavour).depmod.log : The log is created as a result of running depmod on the
+resulting set of modules. If there are missing symbols then you'll find that information
+here. Again, you should modify your inclusion list such that there are no missing
+symbols.
+
+Tim Gardner <tim.gardner@canonical.com>
+June 2, 2010
--- linux-ec2-2.6.32.orig/debian/tests/check-aliases
+++ linux-ec2-2.6.32/debian/tests/check-aliases
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+my %map;
+
+print "Checking for dupe aliases in $ENV{'FLAVOUR'}...\n";
+
+$aliases =
+  "$ENV{'INSTALL_DIR'}/lib/modules/$ENV{'VERSION'}-$ENV{'FLAVOUR'}/modules.alias";
+
+open(ALIASES, "< $aliases") or die "Could not open $aliases";
+
+while (<ALIASES>) {
+	chomp;
+	my ($junk, $alias, $module) = split;
+
+	if (defined($map{$alias})) {
+		printf("%s %20s / %-20s : %s \n", ("$map{$alias}" eq "$module")
+			? "INT" : "   ", $map{$alias}, $module, $alias);
+	} else {
+		$map{$alias} = $module;
+	}
+}
+
+exit(0);
--- linux-ec2-2.6.32.orig/debian/tests/README
+++ linux-ec2-2.6.32/debian/tests/README
@@ -0,0 +1,21 @@
+Scripts placed in this directory get called one at a time by run-parts(8).
+The scripts are expected to perform some sort of sanity checks on the
+finished build. Scripts will be called once for each flavour.
+
+Some environment variables are exported to make life a little easier:
+
+DPKG_ARCH     : The dpkg architecture (e.g. "amd64")
+KERN_ARCH     : The kernel architecture (e.g. "x86_64")
+FLAVOUR       : The specific flavour for this run (e.g. "generic")
+VERSION       : The full version of this build (e.g. 2.6.22-1)
+REVISION      : The exact revision of this build (e.g. 1.3)
+PREV_REVISION : The revision prior to this one
+ABI_NUM       : The specific ABI number for this build (e.g. 2)
+PREV_ABI_NUM  : The previous ABI number. Can be the same as ABI_NUM.
+BUILD_DIR     : The directory where this build took place
+INSTALL_DIR   : The directory where the package is prepared
+SOURCE_DIR    : Where the main kernel source is
+
+Scripts are expected to have a zero exit status when no problems occur,
+and non-zero when an error occurs that should stop the build. Scripts
+should print whatever info they deem needed to deduce the problem.
--- linux-ec2-2.6.32.orig/debian/commit-templates/missing-modules
+++ linux-ec2-2.6.32/debian/commit-templates/missing-modules
@@ -0,0 +1,3 @@
+UBUNTU: build/modules: Add modules that have intentionally gone missing
+
+Ignore: yes
--- linux-ec2-2.6.32.orig/debian/commit-templates/sauce-patch
+++ linux-ec2-2.6.32/debian/commit-templates/sauce-patch
@@ -0,0 +1,40 @@
+# Ubuntu commit template.
+#
+# NOTE: This gets reformatted for debian/changelog
+#
+#
+# SAUCE refers to the fact that this patch might not go upstream, but we need to
+# carry it to successive releases. In most cases you DONOT want to use this
+# template. 
+#
+# An example of a SAUCE patch is the ACPI DSDT-in-initramfs patch which has been
+# refused upstream, but still provides useful functionality to users with broken
+# BIOSes.
+#
+#-------------------------------------------------------------------------
+#
+# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be
+# referenced to the Author in the debian/changelog entry.
+#
+# The text following is the short message that will be placed in the
+# changelog. Extra text on the following lines will be ignored, but left
+# in the git commit. Lines with # will be ignored in the commit.
+#
+# OriginalAuthor allows for alternate attribution.
+#
+# OriginalLocation allows for a URL or description of where the patch came
+# from.
+#
+# BugLink is a URL to a Malone bug.
+#
+# Ignore: yes will keep this commit from showing up in the changelog.
+#
+UBUNTU: SAUCE: 
+
+<Why is this patch not going upstream?>
+
+# OriginalAuthor: 
+# OriginalLocation: 
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-ec2-2.6.32.orig/debian/commit-templates/upstream-patch
+++ linux-ec2-2.6.32/debian/commit-templates/upstream-patch
@@ -0,0 +1,27 @@
+# Ubuntu commit template.
+#
+# NOTE: This gets reformatted for debian/changelog
+#
+# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be
+# referenced to the Author in the debian/changelog entry.
+#
+# The text following is the short message that will be placed in the
+# changelog. Extra text on the following lines will be ignored, but left
+# in the git commit. Lines with # will be ignored in the commit.
+#
+# OriginalAuthor allows for alternate attribution.
+#
+# OriginalLocation allows for a URL or description of where the patch came
+# from.
+#
+# BugLink is a URL to a Malone bug.
+#
+# Ignore: yes will keep this commit from showing up in the changelog.
+#
+UBUNTU: [Upstream]
+
+# OriginalAuthor: 
+# OriginalLocation: 
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-ec2-2.6.32.orig/debian/commit-templates/newrelease
+++ linux-ec2-2.6.32/debian/commit-templates/newrelease
@@ -0,0 +1,3 @@
+UBUNTU: Start new release
+
+Ignore: yes
--- linux-ec2-2.6.32.orig/debian/commit-templates/external-driver
+++ linux-ec2-2.6.32/debian/commit-templates/external-driver
@@ -0,0 +1,20 @@
+# Ubuntu external driver commit.
+#
+# NOTE: This gets reformatted for README.Ubuntu-External-Drivers and
+# debian/changelog.
+#
+# This is only needed when a driver is added, updated or removed. It is
+# not needed when patches or fixes are applied to the driver. If the
+# driver is being removed, add the line:
+#
+# Removing: yes
+#
+# to the commit, and you can remove all other tags (except UBUNTU:).
+#
+UBUNTU: 
+
+ExternalDriver: 
+Description:
+Url:
+Mask:
+Version:
--- linux-ec2-2.6.32.orig/debian/commit-templates/bumpabi
+++ linux-ec2-2.6.32/debian/commit-templates/bumpabi
@@ -0,0 +1,3 @@
+UBUNTU: Bump ABI
+
+Ignore: yes
--- linux-ec2-2.6.32.orig/debian/commit-templates/config-updates
+++ linux-ec2-2.6.32/debian/commit-templates/config-updates
@@ -0,0 +1,15 @@
+#
+# This template is used for commit messages that don't need to
+# show up in debian/changelog. Administrative stuff like config
+# updates, ABI bumps, etc. Setting 'Ignore: yes' prevents
+# 'debian/rules insertchanges' from inserting this commit meesage
+# as a changelog entry.
+#
+# Please give a one-line description of the config change followed
+# by a detailed explanation if necessary
+
+UBUNTU: [Config] XXXX
+
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-ec2-2.6.32.orig/lib/rational.c
+++ linux-ec2-2.6.32/lib/rational.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/rational.h>
+#include <linux/module.h>
 
 /*
  * calculate best rational approximation for a given fraction
--- linux-ec2-2.6.32.orig/lib/swiotlb-xen.c
+++ linux-ec2-2.6.32/lib/swiotlb-xen.c
@@ -0,0 +1,750 @@
+/*
+ * Dynamic DMA mapping support.
+ *
+ * This implementation is a fallback for platforms that do not support
+ * I/O TLBs (aka DMA address translation hardware).
+ * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com>
+ * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com>
+ * Copyright (C) 2000, 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2005 Keir Fraser <keir@xensource.com>
+ * 08/12/11 beckyb	Add highmem support
+ */
+
+#include <linux/cache.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/swiotlb.h>
+#include <linux/pfn.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/iommu-helper.h>
+#include <linux/highmem.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <xen/gnttab.h>
+#include <xen/interface/memory.h>
+#include <asm/gnttab_dma.h>
+
+#define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
+
+int swiotlb;
+int swiotlb_force;
+
+/*
+ * Used to do a quick range check in unmap_single and
+ * sync_single_*, to see if the memory was in fact allocated by this
+ * API.
+ */
+static char *io_tlb_start, *io_tlb_end;
+
+/*
+ * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and
+ * io_tlb_end.  This is command line adjustable via setup_io_tlb_npages.
+ */
+static unsigned long io_tlb_nslabs;
+
+/*
+ * When the IOMMU overflows we return a fallback buffer. This sets the size.
+ */
+static unsigned long io_tlb_overflow = 32*1024;
+
+void *io_tlb_overflow_buffer;
+
+/*
+ * This is a free list describing the number of free entries available from
+ * each index
+ */
+static unsigned int *io_tlb_list;
+static unsigned int io_tlb_index;
+
+/*
+ * We need to save away the original address corresponding to a mapped entry
+ * for the sync operations.
+ */
+static phys_addr_t *io_tlb_orig_addr;
+
+/*
+ * Protect the above data structures in the map and unmap calls
+ */
+static DEFINE_SPINLOCK(io_tlb_lock);
+
+static unsigned int dma_bits;
+static unsigned int __initdata max_dma_bits = 32;
+static int __init
+setup_dma_bits(char *str)
+{
+	max_dma_bits = simple_strtoul(str, NULL, 0);
+	return 0;
+}
+__setup("dma_bits=", setup_dma_bits);
+
+static int __init
+setup_io_tlb_npages(char *str)
+{
+	/* Unlike ia64, the size is aperture in megabytes, not 'slabs'! */
+	if (isdigit(*str)) {
+		io_tlb_nslabs = simple_strtoul(str, &str, 0) <<
+			(20 - IO_TLB_SHIFT);
+		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+	}
+	if (*str == ',')
+		++str;
+	/*
+         * NB. 'force' enables the swiotlb, but doesn't force its use for
+         * every DMA like it does on native Linux. 'off' forcibly disables
+         * use of the swiotlb.
+         */
+	if (!strcmp(str, "force"))
+		swiotlb_force = 1;
+	else if (!strcmp(str, "off"))
+		swiotlb_force = -1;
+	return 1;
+}
+__setup("swiotlb=", setup_io_tlb_npages);
+/* make io_tlb_overflow tunable too? */
+
+/* Note that this doesn't work with highmem page */
+static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
+				      volatile void *address)
+{
+	return phys_to_dma(hwdev, virt_to_phys(address));
+}
+
+static void swiotlb_print_info(unsigned long bytes)
+{
+	printk(KERN_INFO "Software IO TLB enabled: \n"
+	       " Aperture:     %lu megabytes\n"
+	       " Address size: %u bits\n"
+	       " Kernel range: %p - %p\n",
+	       bytes >> 20, dma_bits,
+	       io_tlb_start, io_tlb_end);
+}
+
+/*
+ * Statically reserve bounce buffer space and initialize bounce buffer data
+ * structures for the software IO TLB used to implement the PCI DMA API.
+ */
+void __init
+swiotlb_init_with_default_size(size_t default_size)
+{
+	unsigned long i, bytes;
+	int rc;
+
+	if (!io_tlb_nslabs) {
+		io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
+		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+	}
+
+	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
+
+	/*
+	 * Get IO TLB memory from the low pages
+	 */
+	io_tlb_start = alloc_bootmem_pages(bytes);
+	if (!io_tlb_start)
+		panic("Cannot allocate SWIOTLB buffer!\n");
+	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
+	for (i = 0; i < io_tlb_nslabs; i += IO_TLB_SEGSIZE) {
+		do {
+			rc = xen_create_contiguous_region(
+				(unsigned long)io_tlb_start + (i << IO_TLB_SHIFT),
+				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+				dma_bits);
+		} while (rc && dma_bits++ < max_dma_bits);
+		if (rc) {
+			if (i == 0)
+				panic("No suitable physical memory available for SWIOTLB buffer!\n"
+				      "Use dom0_mem Xen boot parameter to reserve\n"
+				      "some DMA memory (e.g., dom0_mem=-128M).\n");
+			io_tlb_nslabs = i;
+			i <<= IO_TLB_SHIFT;
+			free_bootmem(__pa(io_tlb_start + i), bytes - i);
+			bytes = i;
+			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
+				unsigned int bits = fls64(virt_to_bus(io_tlb_start + i - 1));
+
+				if (bits > dma_bits)
+					dma_bits = bits;
+			}
+			break;
+		}
+	}
+	io_tlb_end = io_tlb_start + bytes;
+
+	/*
+	 * Allocate and initialize the free list array.  This array is used
+	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE.
+	 */
+	io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
+	for (i = 0; i < io_tlb_nslabs; i++)
+ 		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+	io_tlb_index = 0;
+	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t));
+
+	/*
+	 * Get the overflow emergency buffer
+	 */
+	io_tlb_overflow_buffer = alloc_bootmem(io_tlb_overflow);
+	if (!io_tlb_overflow_buffer)
+		panic("Cannot allocate SWIOTLB overflow buffer!\n");
+
+	do {
+		rc = xen_create_contiguous_region(
+			(unsigned long)io_tlb_overflow_buffer,
+			get_order(io_tlb_overflow),
+			dma_bits);
+	} while (rc && dma_bits++ < max_dma_bits);
+	if (rc)
+		panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
+
+	swiotlb_print_info(bytes);
+}
+
+void __init
+swiotlb_init(void)
+{
+	unsigned long ram_end;
+	size_t defsz = 64 << 20; /* 64MB default size */
+
+	if (swiotlb_force == 1) {
+		swiotlb = 1;
+	} else if ((swiotlb_force != -1) &&
+		   is_running_on_xen() &&
+		   is_initial_xendomain()) {
+		/* Domain 0 always has a swiotlb. */
+		ram_end = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
+		if (ram_end <= 0x1ffff)
+			defsz = 2 << 20; /* 2MB on <512MB systems. */
+		else if (ram_end <= 0x3ffff)
+			defsz = 4 << 20; /* 4MB on <1GB systems. */
+		else if (ram_end <= 0x7ffff)
+			defsz = 8 << 20; /* 8MB on <2GB systems. */
+		swiotlb = 1;
+	}
+
+	if (swiotlb)
+		swiotlb_init_with_default_size(defsz);
+	else
+		printk(KERN_INFO "Software IO TLB disabled\n");
+}
+
+static inline int range_needs_mapping(phys_addr_t pa, size_t size)
+{
+	return range_straddles_page_boundary(pa, size);
+}
+
+static int is_swiotlb_buffer(phys_addr_t paddr)
+{
+	return paddr >= virt_to_phys(io_tlb_start) &&
+		paddr < virt_to_phys(io_tlb_end);
+}
+
+/*
+ * Bounce: copy the swiotlb buffer back to the original dma location
+ *
+ * We use __copy_to_user_inatomic to transfer to the host buffer because the
+ * buffer may be mapped read-only (e.g, in blkback driver) but lower-level
+ * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
+ * unnecessary copy from the aperture to the host buffer, and a page fault.
+ */
+static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+			   enum dma_data_direction dir)
+{
+	unsigned long pfn = PFN_DOWN(phys);
+
+	if (PageHighMem(pfn_to_page(pfn))) {
+		/* The buffer does not have a mapping.  Map it in and copy */
+		unsigned int offset = phys & ~PAGE_MASK;
+		char *buffer;
+		unsigned int sz = 0;
+		unsigned long flags;
+
+		while (size) {
+			sz = min_t(size_t, PAGE_SIZE - offset, size);
+
+			local_irq_save(flags);
+			buffer = kmap_atomic(pfn_to_page(pfn),
+					     KM_BOUNCE_READ);
+			if (dir == DMA_TO_DEVICE)
+				memcpy(dma_addr, buffer + offset, sz);
+			else if (__copy_to_user_inatomic(buffer + offset,
+							 dma_addr, sz))
+				/* inaccessible */;
+			kunmap_atomic(buffer, KM_BOUNCE_READ);
+			local_irq_restore(flags);
+
+			size -= sz;
+			pfn++;
+			dma_addr += sz;
+			offset = 0;
+		}
+	} else {
+		if (dir == DMA_TO_DEVICE)
+			memcpy(dma_addr, phys_to_virt(phys), size);
+		else
+			memcpy(phys_to_virt(phys), dma_addr, size);
+	}
+}
+
+/*
+ * Allocates bounce buffer and returns its kernel virtual address.
+ */
+static void *
+map_single(struct device *hwdev, phys_addr_t phys, size_t size, int dir)
+{
+	unsigned long flags;
+	char *dma_addr;
+	unsigned int nslots, stride, index, wrap;
+	int i;
+	unsigned long mask;
+	unsigned long offset_slots;
+	unsigned long max_slots;
+
+	mask = dma_get_seg_boundary(hwdev);
+	offset_slots = -IO_TLB_SEGSIZE;
+
+	/*
+ 	 * Carefully handle integer overflow which can occur when mask == ~0UL.
+ 	 */
+	max_slots = mask + 1
+		    ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
+		    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+
+	/*
+	 * For mappings greater than a page, we limit the stride (and
+	 * hence alignment) to a page size.
+	 */
+	nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+	if (size > PAGE_SIZE)
+		stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
+	else
+		stride = 1;
+
+	BUG_ON(!nslots);
+
+	/*
+	 * Find suitable number of IO TLB entries size that will fit this
+	 * request and allocate a buffer from that IO TLB pool.
+	 */
+	spin_lock_irqsave(&io_tlb_lock, flags);
+	index = ALIGN(io_tlb_index, stride);
+	if (index >= io_tlb_nslabs)
+		index = 0;
+	wrap = index;
+
+	do {
+		while (iommu_is_span_boundary(index, nslots, offset_slots,
+					      max_slots)) {
+			index += stride;
+			if (index >= io_tlb_nslabs)
+				index = 0;
+			if (index == wrap)
+				goto not_found;
+		}
+
+		/*
+		 * If we find a slot that indicates we have 'nslots' number of
+		 * contiguous buffers, we allocate the buffers from that slot
+		 * and mark the entries as '0' indicating unavailable.
+		 */
+		if (io_tlb_list[index] >= nslots) {
+			int count = 0;
+
+			for (i = index; i < (int) (index + nslots); i++)
+				io_tlb_list[i] = 0;
+			for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
+				io_tlb_list[i] = ++count;
+			dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+
+			/*
+			 * Update the indices to avoid searching in the next
+			 * round.
+			 */
+			io_tlb_index = ((index + nslots) < io_tlb_nslabs
+					? (index + nslots) : 0);
+
+			goto found;
+		}
+		index += stride;
+		if (index >= io_tlb_nslabs)
+			index = 0;
+	} while (index != wrap);
+
+not_found:
+	spin_unlock_irqrestore(&io_tlb_lock, flags);
+	return NULL;
+found:
+	spin_unlock_irqrestore(&io_tlb_lock, flags);
+
+	/*
+	 * Save away the mapping from the original address to the DMA address.
+	 * This is needed when we sync the memory.  Then we sync the buffer if
+	 * needed.
+	 */
+	for (i = 0; i < nslots; i++)
+		io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
+	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
+		swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
+
+	return dma_addr;
+}
+
+/*
+ * dma_addr is the kernel virtual address of the bounce buffer to unmap.
+ */
+static void
+do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+{
+	unsigned long flags;
+	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	phys_addr_t phys = io_tlb_orig_addr[index];
+
+	/*
+	 * First, sync the memory before unmapping the entry
+	 */
+	if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+		swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
+
+	/*
+	 * Return the buffer to the free list by setting the corresponding
+	 * entries to indicate the number of contigous entries available.
+	 * While returning the entries to the free list, we merge the entries
+	 * with slots below and above the pool being returned.
+	 */
+	spin_lock_irqsave(&io_tlb_lock, flags);
+	{
+		count = ((index + nslots) < ALIGN(index + 1, IO_TLB_SEGSIZE) ?
+			 io_tlb_list[index + nslots] : 0);
+		/*
+		 * Step 1: return the slots to the free list, merging the
+		 * slots with superceeding slots
+		 */
+		for (i = index + nslots - 1; i >= index; i--)
+			io_tlb_list[i] = ++count;
+		/*
+		 * Step 2: merge the returned slots with the preceding slots,
+		 * if available (non zero)
+		 */
+		for (i = index - 1;
+		     (OFFSET(i, IO_TLB_SEGSIZE) !=
+		      IO_TLB_SEGSIZE -1) && io_tlb_list[i];
+		     i--)
+			io_tlb_list[i] = ++count;
+	}
+	spin_unlock_irqrestore(&io_tlb_lock, flags);
+}
+
+static void
+sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+{
+	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	phys_addr_t phys = io_tlb_orig_addr[index];
+
+	phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
+
+	BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
+	swiotlb_bounce(phys, dma_addr, size, dir);
+}
+
+static void
+swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+{
+	/*
+	 * Ran out of IOMMU space for this operation. This is very bad.
+	 * Unfortunately the drivers cannot handle this operation properly.
+	 * unless they check for pci_dma_mapping_error (most don't)
+	 * When the mapping is small enough return a static buffer to limit
+	 * the damage, or panic when the transfer is too big.
+	 */
+	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %zu bytes at "
+	       "device %s\n", size, dev ? dev_name(dev) : "?");
+
+	if (size <= io_tlb_overflow || !do_panic)
+		return;
+
+	if (dir == DMA_BIDIRECTIONAL)
+		panic("DMA: Random memory could be DMA accessed\n");
+	if (dir == DMA_FROM_DEVICE)
+		panic("DMA: Random memory could be DMA written\n");
+	if (dir == DMA_TO_DEVICE)
+		panic("DMA: Random memory could be DMA read\n");
+}
+
+/*
+ * Map a single buffer of the indicated size for DMA in streaming mode.  The
+ * PCI address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory until
+ * either swiotlb_unmap_page or swiotlb_dma_sync_single is performed.
+ */
+dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
+			    unsigned long offset, size_t size,
+			    enum dma_data_direction dir,
+			    struct dma_attrs *attrs)
+{
+	phys_addr_t phys = page_to_pseudophys(page) + offset;
+	dma_addr_t dev_addr = gnttab_dma_map_page(page) + offset;
+	void *map;
+
+	BUG_ON(dir == DMA_NONE);
+
+	/*
+	 * If the address happens to be in the device's DMA window,
+	 * we can safely return the device addr and not worry about bounce
+	 * buffering it.
+	 */
+	if (dma_capable(dev, dev_addr, size)/* && !swiotlb_force*/)
+		return dev_addr;
+
+	/*
+	 * Oh well, have to allocate and map a bounce buffer.
+	 */
+	gnttab_dma_unmap_page(dev_addr);
+	map = map_single(dev, phys, size, dir);
+	if (!map) {
+		swiotlb_full(dev, size, dir, 1);
+		map = io_tlb_overflow_buffer;
+	}
+
+	dev_addr = swiotlb_virt_to_bus(dev, map);
+	return dev_addr;
+}
+EXPORT_SYMBOL_GPL(swiotlb_map_page);
+
+/*
+ * Unmap a single streaming mode DMA translation.  The dma_addr and size must
+ * match what was provided for in a previous swiotlb_map_page call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guaranteed to see
+ * whatever the device wrote there.
+ */
+static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+			 size_t size, int dir)
+{
+	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (is_swiotlb_buffer(paddr)) {
+		do_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
+		return;
+	}
+
+	gnttab_dma_unmap_page(dev_addr);
+}
+
+void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
+			size_t size, enum dma_data_direction dir,
+			struct dma_attrs *attrs)
+{
+	unmap_single(hwdev, dev_addr, size, dir);
+}
+EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
+
+/*
+ * Make physical memory consistent for a single streaming mode DMA translation
+ * after a transfer.
+ *
+ * If you perform a swiotlb_map_page() but wish to interrogate the buffer
+ * using the cpu, yet do not wish to teardown the PCI dma mapping, you must
+ * call this function before doing so.  At the next point you give the PCI dma
+ * address back to the card, you must first perform a
+ * swiotlb_dma_sync_for_device, and then the device again owns the buffer
+ */
+void
+swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+			    size_t size, enum dma_data_direction dir)
+{
+	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (is_swiotlb_buffer(paddr))
+		sync_single(hwdev, phys_to_virt(paddr), size, dir);
+}
+EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
+
+void
+swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+			       size_t size, enum dma_data_direction dir)
+{
+	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+
+	BUG_ON(dir == DMA_NONE);
+
+	if (is_swiotlb_buffer(paddr))
+		sync_single(hwdev, phys_to_virt(paddr), size, dir);
+}
+EXPORT_SYMBOL(swiotlb_sync_single_for_device);
+
+void
+swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+				  unsigned long offset, size_t size,
+				  enum dma_data_direction dir)
+{
+	swiotlb_sync_single_for_cpu(hwdev, dev_addr + offset, size, dir);
+}
+EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_cpu);
+
+void
+swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+				     unsigned long offset, size_t size,
+				     enum dma_data_direction dir)
+{
+	swiotlb_sync_single_for_device(hwdev, dev_addr + offset, size, dir);
+}
+EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
+
+/*
+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
+ * This is the scatter-gather version of the above swiotlb_map_page
+ * interface.  Here the scatter gather list elements are each tagged with the
+ * appropriate dma address and length.  They are obtained via
+ * sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for swiotlb_map_page are the
+ * same here.
+ */
+int
+swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
+		     enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	BUG_ON(dir == DMA_NONE);
+
+	for_each_sg(sgl, sg, nelems, i) {
+		dma_addr_t dev_addr = gnttab_dma_map_page(sg_page(sg))
+				      + sg->offset;
+		phys_addr_t paddr = page_to_pseudophys(sg_page(sg))
+				   + sg->offset;
+
+		if (range_needs_mapping(paddr, sg->length) ||
+		    !dma_capable(hwdev, dev_addr, sg->length)) {
+			void *map;
+
+			gnttab_dma_unmap_page(dev_addr);
+			map = map_single(hwdev, paddr,
+					 sg->length, dir);
+			if (!map) {
+				/* Don't panic here, we expect map_sg users
+				   to do proper error handling. */
+				swiotlb_full(hwdev, sg->length, dir, 0);
+				swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
+						       attrs);
+				sgl[0].dma_length = 0;
+				return 0;
+			}
+			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
+		} else
+			sg->dma_address = dev_addr;
+		sg->dma_length = sg->length;
+	}
+	return nelems;
+}
+EXPORT_SYMBOL(swiotlb_map_sg_attrs);
+
+int
+swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+	       int dir)
+{
+	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+}
+EXPORT_SYMBOL(swiotlb_map_sg);
+
+/*
+ * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
+ * concerning calls here are the same as for swiotlb_unmap_page() above.
+ */
+void
+swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
+		       int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	BUG_ON(dir == DMA_NONE);
+
+	for_each_sg(sgl, sg, nelems, i)
+		unmap_single(hwdev, sg->dma_address, sg->dma_length, dir);
+
+}
+EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
+
+void
+swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+		 int dir)
+{
+	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+}
+EXPORT_SYMBOL(swiotlb_unmap_sg);
+
+/*
+ * Make physical memory consistent for a set of streaming mode DMA translations
+ * after a transfer.
+ *
+ * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules
+ * and usage.
+ */
+void
+swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sgl,
+			int nelems, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nelems, i)
+		swiotlb_sync_single_for_cpu(hwdev, sg->dma_address,
+					    sg->dma_length, dir);
+}
+EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
+
+void
+swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sgl,
+			   int nelems, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nelems, i)
+		swiotlb_sync_single_for_device(hwdev, sg->dma_address,
+					       sg->dma_length, dir);
+}
+EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
+
+int
+swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
+{
+	return (dma_addr == swiotlb_virt_to_bus(hwdev, io_tlb_overflow_buffer));
+}
+EXPORT_SYMBOL(swiotlb_dma_mapping_error);
+
+/*
+ * Return whether the given PCI device DMA address mask can be supported
+ * properly.  For example, if your device can only drive the low 24-bits
+ * during PCI bus mastering, then you would pass 0x00ffffff as the mask to
+ * this function.
+ */
+int
+swiotlb_dma_supported (struct device *hwdev, u64 mask)
+{
+	return (mask >= ((1UL << dma_bits) - 1));
+}
+EXPORT_SYMBOL(swiotlb_dma_supported);
--- linux-ec2-2.6.32.orig/lib/flex_array.c
+++ linux-ec2-2.6.32/lib/flex_array.c
@@ -99,7 +99,7 @@
 	ret->element_size = element_size;
 	ret->total_nr_elements = total;
 	if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO))
-		memset(ret->parts[0], FLEX_ARRAY_FREE,
+		memset(&ret->parts[0], FLEX_ARRAY_FREE,
 						FLEX_ARRAY_BASE_BYTES_LEFT);
 	return ret;
 }
--- linux-ec2-2.6.32.orig/lib/Makefile
+++ linux-ec2-2.6.32/lib/Makefile
@@ -21,7 +21,7 @@
 
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
 	 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
-	 string_helpers.o gcd.o
+	 string_helpers.o gcd.o list_sort.o lcm.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
--- linux-ec2-2.6.32.orig/lib/list_sort.c
+++ linux-ec2-2.6.32/lib/list_sort.c
@@ -0,0 +1,102 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list_sort.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+/**
+ * list_sort - sort a list.
+ * @priv: private data, passed to @cmp
+ * @head: the list to sort
+ * @cmp: the elements comparison function
+ *
+ * This function has been implemented by Mark J Roberts <mjr@znex.org>. It
+ * implements "merge sort" which has O(nlog(n)) complexity. The list is sorted
+ * in ascending order.
+ *
+ * The comparison function @cmp is supposed to return a negative value if @a is
+ * less than @b, and a positive value if @a is greater than @b. If @a and @b
+ * are equivalent, then it does not matter what this function returns.
+ */
+void list_sort(void *priv, struct list_head *head,
+	       int (*cmp)(void *priv, struct list_head *a,
+			  struct list_head *b))
+{
+	struct list_head *p, *q, *e, *list, *tail, *oldhead;
+	int insize, nmerges, psize, qsize, i;
+
+	if (list_empty(head))
+		return;
+
+	list = head->next;
+	list_del(head);
+	insize = 1;
+	for (;;) {
+		p = oldhead = list;
+		list = tail = NULL;
+		nmerges = 0;
+
+		while (p) {
+			nmerges++;
+			q = p;
+			psize = 0;
+			for (i = 0; i < insize; i++) {
+				psize++;
+				q = q->next == oldhead ? NULL : q->next;
+				if (!q)
+					break;
+			}
+
+			qsize = insize;
+			while (psize > 0 || (qsize > 0 && q)) {
+				if (!psize) {
+					e = q;
+					q = q->next;
+					qsize--;
+					if (q == oldhead)
+						q = NULL;
+				} else if (!qsize || !q) {
+					e = p;
+					p = p->next;
+					psize--;
+					if (p == oldhead)
+						p = NULL;
+				} else if (cmp(priv, p, q) <= 0) {
+					e = p;
+					p = p->next;
+					psize--;
+					if (p == oldhead)
+						p = NULL;
+				} else {
+					e = q;
+					q = q->next;
+					qsize--;
+					if (q == oldhead)
+						q = NULL;
+				}
+				if (tail)
+					tail->next = e;
+				else
+					list = e;
+				e->prev = tail;
+				tail = e;
+			}
+			p = q;
+		}
+
+		tail->next = list;
+		list->prev = tail;
+
+		if (nmerges <= 1)
+			break;
+
+		insize *= 2;
+	}
+
+	head->next = list;
+	head->prev = list->prev;
+	list->prev->next = head;
+	list->prev = head;
+}
+
+EXPORT_SYMBOL(list_sort);
--- linux-ec2-2.6.32.orig/lib/idr.c
+++ linux-ec2-2.6.32/lib/idr.c
@@ -156,10 +156,12 @@
 			id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
 
 			/* if already at the top layer, we need to grow */
-			if (!(p = pa[l])) {
+			if (id >= 1 << (idp->layers * IDR_BITS)) {
 				*starting_id = id;
 				return IDR_NEED_TO_GROW;
 			}
+			p = pa[l];
+			BUG_ON(!p);
 
 			/* If we need to go up one layer, continue the
 			 * loop; otherwise, restart from the top.
--- linux-ec2-2.6.32.orig/lib/lcm.c
+++ linux-ec2-2.6.32/lib/lcm.c
@@ -0,0 +1,15 @@
+#include <linux/kernel.h>
+#include <linux/gcd.h>
+#include <linux/module.h>
+
+/* Lowest common multiple */
+unsigned long lcm(unsigned long a, unsigned long b)
+{
+	if (a && b)
+		return (a * b) / gcd(a, b);
+	else if (b)
+		return b;
+
+	return a;
+}
+EXPORT_SYMBOL_GPL(lcm);
--- linux-ec2-2.6.32.orig/lib/dma-debug.c
+++ linux-ec2-2.6.32/lib/dma-debug.c
@@ -670,12 +670,13 @@
 	return count;
 }
 
-static int dma_debug_device_change(struct notifier_block *nb,
-				    unsigned long action, void *data)
+static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data)
 {
 	struct device *dev = data;
 	int count;
 
+	if (global_disable)
+		return 0;
 
 	switch (action) {
 	case BUS_NOTIFY_UNBOUND_DRIVER:
@@ -697,6 +698,9 @@
 {
 	struct notifier_block *nb;
 
+	if (global_disable)
+		return;
+
 	nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
 	if (nb == NULL) {
 		pr_err("dma_debug_add_bus: out of memory\n");
@@ -909,6 +913,9 @@
 				ref->size);
 	}
 
+	if (entry->direction == DMA_BIDIRECTIONAL)
+		goto out;
+
 	if (ref->direction != entry->direction) {
 		err_printk(dev, entry, "DMA-API: device driver syncs "
 				"DMA memory with different direction "
@@ -919,9 +926,6 @@
 				dir2name[ref->direction]);
 	}
 
-	if (entry->direction == DMA_BIDIRECTIONAL)
-		goto out;
-
 	if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) &&
 		      !(ref->direction == DMA_TO_DEVICE))
 		err_printk(dev, entry, "DMA-API: device driver syncs "
@@ -944,7 +948,6 @@
 
 out:
 	put_hash_bucket(bucket, &flags);
-
 }
 
 void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
--- linux-ec2-2.6.32.orig/lib/percpu_counter.c
+++ linux-ec2-2.6.32/lib/percpu_counter.c
@@ -76,6 +76,7 @@
 	if (!fbc->counters)
 		return -ENOMEM;
 #ifdef CONFIG_HOTPLUG_CPU
+	INIT_LIST_HEAD(&fbc->list);
 	mutex_lock(&percpu_counters_lock);
 	list_add(&fbc->list, &percpu_counters);
 	mutex_unlock(&percpu_counters_lock);
--- linux-ec2-2.6.32.orig/drivers/Makefile
+++ linux-ec2-2.6.32/drivers/Makefile
@@ -9,7 +9,6 @@
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-$(CONFIG_RAPIDIO)		+= rapidio/
-obj-y				+= video/
 obj-$(CONFIG_ACPI)		+= acpi/
 obj-$(CONFIG_SFI)		+= sfi/
 # PnP must come after ACPI since it will eventually need to check if acpi
@@ -17,7 +16,8 @@
 obj-$(CONFIG_PNP)		+= pnp/
 obj-$(CONFIG_ARM_AMBA)		+= amba/
 
-obj-$(CONFIG_XEN)		+= xen/
+obj-$(CONFIG_VIRTIO)		+= virtio/
+obj-$(CONFIG_PARAVIRT_XEN)	+= xen/
 
 # regulators early, since some subsystems rely on them to initialize
 obj-$(CONFIG_REGULATOR)		+= regulator/
@@ -28,6 +28,8 @@
 
 # gpu/ comes after char for AGP vs DRM startup
 obj-y				+= gpu/
+# video/ needs to come after gpu for framebuffer fallback.
+obj-y				+= video/
 
 obj-$(CONFIG_CONNECTOR)		+= connector/
 
@@ -40,6 +42,7 @@
 obj-y				+= base/ block/ misc/ mfd/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-y				+= macintosh/
+obj-$(CONFIG_XEN)		+= xen/
 obj-$(CONFIG_IDE)		+= ide/
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_ATA)		+= ata/
@@ -106,7 +109,6 @@
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_OF)		+= of/
 obj-$(CONFIG_SSB)		+= ssb/
-obj-$(CONFIG_VIRTIO)		+= virtio/
 obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
--- linux-ec2-2.6.32.orig/drivers/atm/solos-pci.c
+++ linux-ec2-2.6.32/drivers/atm/solos-pci.c
@@ -688,7 +688,7 @@
 					      size);
 			}
 			if (atmdebug) {
-				dev_info(&card->dev->dev, "Received: device %d\n", port);
+				dev_info(&card->dev->dev, "Received: port %d\n", port);
 				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
 					 size, le16_to_cpu(header->vpi),
 					 le16_to_cpu(header->vci));
@@ -774,7 +774,8 @@
 	sk_for_each(s, node, head) {
 		vcc = atm_sk(s);
 		if (vcc->dev == dev && vcc->vci == vci &&
-		    vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE)
+		    vcc->vpi == vpi && vcc->qos.rxtp.traffic_class != ATM_NONE &&
+		    test_bit(ATM_VF_READY, &vcc->flags))
 			goto out;
 	}
 	vcc = NULL;
@@ -900,6 +901,10 @@
 	clear_bit(ATM_VF_ADDR, &vcc->flags);
 	clear_bit(ATM_VF_READY, &vcc->flags);
 
+	/* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
+	   tasklet has finished processing any incoming packets (and, more to
+	   the point, using the vcc pointer). */
+	tasklet_unlock_wait(&card->tlet);
 	return;
 }
 
@@ -1003,8 +1008,15 @@
 
 			/* Clean up and free oldskb now it's gone */
 			if (atmdebug) {
+				struct pkt_hdr *header = (void *)oldskb->data;
+				int size = le16_to_cpu(header->size);
+
+				skb_pull(oldskb, sizeof(*header));
 				dev_info(&card->dev->dev, "Transmitted: port %d\n",
 					 port);
+				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
+					 size, le16_to_cpu(header->vpi),
+					 le16_to_cpu(header->vci));
 				print_buffer(oldskb);
 			}
 
--- linux-ec2-2.6.32.orig/drivers/gpio/wm831x-gpio.c
+++ linux-ec2-2.6.32/drivers/gpio/wm831x-gpio.c
@@ -61,23 +61,31 @@
 		return 0;
 }
 
-static int wm831x_gpio_direction_out(struct gpio_chip *chip,
-				     unsigned offset, int value)
+static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
 	struct wm831x *wm831x = wm831x_gpio->wm831x;
 
-	return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-			       WM831X_GPN_DIR | WM831X_GPN_TRI, 0);
+	wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
+			value << offset);
 }
 
-static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int wm831x_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
 	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int ret;
 
-	wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
-			value << offset);
+	ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+			      WM831X_GPN_DIR | WM831X_GPN_TRI, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Can only set GPIO state once it's in output mode */
+	wm831x_gpio_set(chip, offset, value);
+
+	return 0;
 }
 
 #ifdef CONFIG_DEBUG_FS
--- linux-ec2-2.6.32.orig/drivers/ssb/driver_chipcommon.c
+++ linux-ec2-2.6.32/drivers/ssb/driver_chipcommon.c
@@ -233,6 +233,9 @@
 {
 	if (!cc->dev)
 		return; /* We don't have a ChipCommon */
+	if (cc->dev->id.revision >= 11)
+		cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
+	ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
 	ssb_pmu_init(cc);
 	chipco_powercontrol_init(cc);
 	ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
--- linux-ec2-2.6.32.orig/drivers/ssb/b43_pci_bridge.c
+++ linux-ec2-2.6.32/drivers/ssb/b43_pci_bridge.c
@@ -24,6 +24,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BCM_GVC,  0x4318) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
--- linux-ec2-2.6.32.orig/drivers/ssb/sprom.c
+++ linux-ec2-2.6.32/drivers/ssb/sprom.c
@@ -13,6 +13,8 @@
 
 #include "ssb_private.h"
 
+#include <linux/ctype.h>
+
 
 static const struct ssb_sprom *fallback_sprom;
 
@@ -33,17 +35,27 @@
 static int hex2sprom(u16 *sprom, const char *dump, size_t len,
 		     size_t sprom_size_words)
 {
-	char tmp[5] = { 0 };
-	int cnt = 0;
+	char c, tmp[5] = { 0 };
+	int err, cnt = 0;
 	unsigned long parsed;
 
-	if (len < sprom_size_words * 2)
+	/* Strip whitespace at the end. */
+	while (len) {
+		c = dump[len - 1];
+		if (!isspace(c) && c != '\0')
+			break;
+		len--;
+	}
+	/* Length must match exactly. */
+	if (len != sprom_size_words * 4)
 		return -EINVAL;
 
 	while (cnt < sprom_size_words) {
 		memcpy(tmp, dump, 4);
 		dump += 4;
-		parsed = simple_strtoul(tmp, NULL, 16);
+		err = strict_strtoul(tmp, 16, &parsed);
+		if (err)
+			return err;
 		sprom[cnt++] = swab16((u16)parsed);
 	}
 
@@ -167,3 +179,18 @@
 {
 	return fallback_sprom;
 }
+
+/* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
+bool ssb_is_sprom_available(struct ssb_bus *bus)
+{
+	/* status register only exists on chipcomon rev >= 11 and we need check
+	   for >= 31 only */
+	/* this routine differs from specs as we do not access SPROM directly
+	   on PCMCIA */
+	if (bus->bustype == SSB_BUSTYPE_PCI &&
+	    bus->chipco.dev &&	/* can be unavailible! */
+	    bus->chipco.dev->id.revision >= 31)
+		return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
+
+	return true;
+}
--- linux-ec2-2.6.32.orig/drivers/ssb/pci.c
+++ linux-ec2-2.6.32/drivers/ssb/pci.c
@@ -167,7 +167,7 @@
 }
 
 /* Get the word-offset for a SSB_SPROM_XXX define. */
-#define SPOFF(offset)	(((offset) - SSB_SPROM_BASE) / sizeof(u16))
+#define SPOFF(offset)	(((offset) - SSB_SPROM_BASE1) / sizeof(u16))
 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
 #define SPEX16(_outvar, _offset, _mask, _shift)	\
 	out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
@@ -253,7 +253,7 @@
 	int i;
 
 	for (i = 0; i < bus->sprom_size; i++)
-		sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
+		sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
 
 	return 0;
 }
@@ -284,7 +284,7 @@
 			ssb_printk("75%%");
 		else if (i % 2)
 			ssb_printk(".");
-		writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
+		writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
 		mmiowb();
 		msleep(20);
 	}
@@ -620,6 +620,28 @@
 	int err = -ENOMEM;
 	u16 *buf;
 
+	if (!ssb_is_sprom_available(bus)) {
+		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
+		return -ENODEV;
+	}
+	if (bus->chipco.dev) {	/* can be unavailible! */
+		/*
+		 * get SPROM offset: SSB_SPROM_BASE1 except for
+		 * chipcommon rev >= 31 or chip ID is 0x4312 and
+		 * chipcommon status & 3 == 2
+		 */
+		if (bus->chipco.dev->id.revision >= 31)
+			bus->sprom_offset = SSB_SPROM_BASE31;
+		else if (bus->chip_id == 0x4312 &&
+			 (bus->chipco.status & 0x03) == 2)
+			bus->sprom_offset = SSB_SPROM_BASE31;
+		else
+			bus->sprom_offset = SSB_SPROM_BASE1;
+	} else {
+		bus->sprom_offset = SSB_SPROM_BASE1;
+	}
+	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
+
 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
 		goto out;
--- linux-ec2-2.6.32.orig/drivers/firmware/iscsi_ibft_find.c
+++ linux-ec2-2.6.32/drivers/firmware/iscsi_ibft_find.c
@@ -78,6 +78,8 @@
 			}
 		}
 	}
+#ifndef CONFIG_XEN
 	if (ibft_addr)
 		reserve_bootmem(pos, PAGE_ALIGN(len), BOOTMEM_DEFAULT);
+#endif
 }
--- linux-ec2-2.6.32.orig/drivers/firmware/dmi_scan.c
+++ linux-ec2-2.6.32/drivers/firmware/dmi_scan.c
@@ -424,12 +424,17 @@
 {
 	int i;
 
+#ifdef CONFIG_XEN
+	if (!is_initial_xendomain())
+		return false;
+#endif
+
 	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
 
 	for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
 		int s = dmi->matches[i].slot;
 		if (s == DMI_NONE)
-			continue;
+			break;
 		if (dmi_ident[s]
 		    && strstr(dmi_ident[s], dmi->matches[i].substr))
 			continue;
@@ -440,6 +445,15 @@
 }
 
 /**
+ *	dmi_is_end_of_table - check for end-of-table marker
+ *	@dmi: pointer to the dmi_system_id structure to check
+ */
+static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
+{
+	return dmi->matches[0].slot == DMI_NONE;
+}
+
+/**
  *	dmi_check_system - check system DMI data
  *	@list: array of dmi_system_id structures to match against
  *		All non-null elements of the list must match
@@ -457,7 +471,7 @@
 	int count = 0;
 	const struct dmi_system_id *d;
 
-	for (d = list; d->ident; d++)
+	for (d = list; !dmi_is_end_of_table(d); d++)
 		if (dmi_matches(d)) {
 			count++;
 			if (d->callback && d->callback(d))
@@ -484,7 +498,7 @@
 {
 	const struct dmi_system_id *d;
 
-	for (d = list; d->ident; d++)
+	for (d = list; !dmi_is_end_of_table(d); d++)
 		if (dmi_matches(d))
 			return d;
 
--- linux-ec2-2.6.32.orig/drivers/firmware/dcdbas.c
+++ linux-ec2-2.6.32/drivers/firmware/dcdbas.c
@@ -267,8 +267,10 @@
 	}
 
 	/* generate SMI */
+	/* inb to force posted write through and make SMI happen now */
 	asm volatile (
-		"outb %b0,%w1"
+		"outb %b0,%w1\n"
+		"inb %w1"
 		: /* no output args */
 		: "a" (smi_cmd->command_code),
 		  "d" (smi_cmd->command_address),
--- linux-ec2-2.6.32.orig/drivers/i2c/i2c-core.c
+++ linux-ec2-2.6.32/drivers/i2c/i2c-core.c
@@ -745,6 +745,14 @@
 static int __unregister_client(struct device *dev, void *dummy)
 {
 	struct i2c_client *client = i2c_verify_client(dev);
+	if (client && strcmp(client->name, "dummy"))
+		i2c_unregister_device(client);
+	return 0;
+}
+
+static int __unregister_dummy(struct device *dev, void *dummy)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
 	if (client)
 		i2c_unregister_device(client);
 	return 0;
@@ -793,14 +801,21 @@
 	}
 
 	/* Detach any active clients. This can't fail, thus we do not
-	   checking the returned value. */
+	 * check the returned value. This is a two-pass process, because
+	 * we can't remove the dummy devices during the first pass: they
+	 * could have been instantiated by real devices wishing to clean
+	 * them up properly, so we give them a chance to do that first. */
 	res = device_for_each_child(&adap->dev, NULL, __unregister_client);
+	res = device_for_each_child(&adap->dev, NULL, __unregister_dummy);
 
 #ifdef CONFIG_I2C_COMPAT
 	class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,
 				 adap->dev.parent);
 #endif
 
+	/* device name is gone after device_unregister */
+	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
+
 	/* clean up the sysfs representation */
 	init_completion(&adap->dev_released);
 	device_unregister(&adap->dev);
@@ -813,8 +828,6 @@
 	idr_remove(&i2c_adapter_idr, adap->nr);
 	mutex_unlock(&core_lock);
 
-	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
-
 	/* Clear the device structure in case this adapter is ever going to be
 	   added again */
 	memset(&adap->dev, 0, sizeof(adap->dev));
@@ -1201,14 +1214,24 @@
 
 	/* Make sure there is something at this address, unless forced */
 	if (kind < 0) {
-		if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
-				   I2C_SMBUS_QUICK, NULL) < 0)
-			return 0;
-
-		/* prevent 24RF08 corruption */
-		if ((addr & ~0x0f) == 0x50)
-			i2c_smbus_xfer(adapter, addr, 0, 0, 0,
-				       I2C_SMBUS_QUICK, NULL);
+		if (addr == 0x73 && (adapter->class & I2C_CLASS_HWMON)) {
+			/* Special probe for FSC hwmon chips */
+			union i2c_smbus_data dummy;
+
+			if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
+					   I2C_SMBUS_BYTE_DATA, &dummy) < 0)
+				return 0;
+		} else {
+			if (i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_WRITE, 0,
+					   I2C_SMBUS_QUICK, NULL) < 0)
+				return 0;
+
+			/* Prevent 24RF08 corruption */
+			if ((addr & ~0x0f) == 0x50)
+				i2c_smbus_xfer(adapter, addr, 0,
+					       I2C_SMBUS_WRITE, 0,
+					       I2C_SMBUS_QUICK, NULL);
+		}
 	}
 
 	/* Finally call the custom detection function */
--- linux-ec2-2.6.32.orig/drivers/i2c/busses/i2c-pca-isa.c
+++ linux-ec2-2.6.32/drivers/i2c/busses/i2c-pca-isa.c
@@ -71,21 +71,25 @@
 
 static int pca_isa_waitforcompletion(void *pd)
 {
-	long ret = ~0;
 	unsigned long timeout;
+	long ret;
 
 	if (irq > -1) {
-		ret = wait_event_interruptible_timeout(pca_wait,
+		ret = wait_event_timeout(pca_wait,
 				pca_isa_readbyte(pd, I2C_PCA_CON)
 				& I2C_PCA_CON_SI, pca_isa_ops.timeout);
 	} else {
 		/* Do polling */
 		timeout = jiffies + pca_isa_ops.timeout;
-		while (((pca_isa_readbyte(pd, I2C_PCA_CON)
-				& I2C_PCA_CON_SI) == 0)
-				&& (ret = time_before(jiffies, timeout)))
+		do {
+			ret = time_before(jiffies, timeout);
+			if (pca_isa_readbyte(pd, I2C_PCA_CON)
+					& I2C_PCA_CON_SI)
+				break;
 			udelay(100);
+		} while (ret);
 	}
+
 	return ret > 0;
 }
 
@@ -96,7 +100,7 @@
 }
 
 static irqreturn_t pca_handler(int this_irq, void *dev_id) {
-	wake_up_interruptible(&pca_wait);
+	wake_up(&pca_wait);
 	return IRQ_HANDLED;
 }
 
--- linux-ec2-2.6.32.orig/drivers/i2c/busses/Kconfig
+++ linux-ec2-2.6.32/drivers/i2c/busses/Kconfig
@@ -77,7 +77,7 @@
 	  will be called i2c-amd8111.
 
 config I2C_I801
-	tristate "Intel 82801 (ICH)"
+	tristate "Intel 82801 (ICH/PCH)"
 	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the Intel
@@ -97,7 +97,8 @@
 	    ICH9
 	    Tolapai
 	    ICH10
-	    PCH
+	    3400/5 Series (PCH)
+	    Cougar Point (PCH)
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i801.
--- linux-ec2-2.6.32.orig/drivers/i2c/busses/i2c-i801.c
+++ linux-ec2-2.6.32/drivers/i2c/busses/i2c-i801.c
@@ -41,7 +41,8 @@
   Tolapai               0x5032     32     hard     yes     yes     yes
   ICH10                 0x3a30     32     hard     yes     yes     yes
   ICH10                 0x3a60     32     hard     yes     yes     yes
-  PCH                   0x3b30     32     hard     yes     yes     yes
+  3400/5 Series (PCH)   0x3b30     32     hard     yes     yes     yes
+  Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
@@ -415,9 +416,11 @@
 		data->block[0] = 32;	/* max for SMBus block reads */
 	}
 
+	/* Experience has shown that the block buffer can only be used for
+	   SMBus (not I2C) block transactions, even though the datasheet
+	   doesn't mention this limitation. */
 	if ((i801_features & FEATURE_BLOCK_BUFFER)
-	 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
-	      && read_write == I2C_SMBUS_READ)
+	 && command != I2C_SMBUS_I2C_BLOCK_DATA
 	 && i801_set_block_buffer_mode() == 0)
 		result = i801_block_transaction_by_block(data, read_write,
 							 hwpec);
@@ -578,6 +581,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) },
 	{ 0, }
 };
 
@@ -707,6 +711,7 @@
 	case PCI_DEVICE_ID_INTEL_ICH10_4:
 	case PCI_DEVICE_ID_INTEL_ICH10_5:
 	case PCI_DEVICE_ID_INTEL_PCH_SMBUS:
+	case PCI_DEVICE_ID_INTEL_CPT_SMBUS:
 		i801_features |= FEATURE_I2C_BLOCK_READ;
 		/* fall through */
 	case PCI_DEVICE_ID_INTEL_82801DB_3:
--- linux-ec2-2.6.32.orig/drivers/i2c/busses/i2c-pca-platform.c
+++ linux-ec2-2.6.32/drivers/i2c/busses/i2c-pca-platform.c
@@ -80,20 +80,23 @@
 static int i2c_pca_pf_waitforcompletion(void *pd)
 {
 	struct i2c_pca_pf_data *i2c = pd;
-	long ret = ~0;
 	unsigned long timeout;
+	long ret;
 
 	if (i2c->irq) {
-		ret = wait_event_interruptible_timeout(i2c->wait,
+		ret = wait_event_timeout(i2c->wait,
 			i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
 			& I2C_PCA_CON_SI, i2c->adap.timeout);
 	} else {
 		/* Do polling */
 		timeout = jiffies + i2c->adap.timeout;
-		while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
-				& I2C_PCA_CON_SI) == 0)
-				&& (ret = time_before(jiffies, timeout)))
+		do {
+			ret = time_before(jiffies, timeout);
+			if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
+					& I2C_PCA_CON_SI)
+				break;
 			udelay(100);
+		} while (ret);
 	}
 
 	return ret > 0;
@@ -122,7 +125,7 @@
 	if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
 		return IRQ_NONE;
 
-	wake_up_interruptible(&i2c->wait);
+	wake_up(&i2c->wait);
 
 	return IRQ_HANDLED;
 }
@@ -221,7 +224,7 @@
 
 	if (irq) {
 		ret = request_irq(irq, i2c_pca_pf_handler,
-			IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
+			IRQF_TRIGGER_FALLING, pdev->name, i2c);
 		if (ret)
 			goto e_reqirq;
 	}
--- linux-ec2-2.6.32.orig/drivers/i2c/busses/i2c-tiny-usb.c
+++ linux-ec2-2.6.32/drivers/i2c/busses/i2c-tiny-usb.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/types.h>
 
 /* include interfaces to usb layer */
 #include <linux/usb.h>
@@ -31,8 +32,8 @@
 #define CMD_I2C_IO_END		(1<<1)
 
 /* i2c bit delay, default is 10us -> 100kHz */
-static int delay = 10;
-module_param(delay, int, 0);
+static unsigned short delay = 10;
+module_param(delay, ushort, 0);
 MODULE_PARM_DESC(delay, "bit delay in microseconds, "
 		 "e.g. 10 for 100kHz (default is 100kHz)");
 
@@ -109,7 +110,7 @@
 
 static u32 usb_func(struct i2c_adapter *adapter)
 {
-	u32 func;
+	__le32 func;
 
 	/* get functionality from adapter */
 	if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
@@ -118,7 +119,7 @@
 		return 0;
 	}
 
-	return func;
+	return le32_to_cpu(func);
 }
 
 /* This is the actual algorithm we define */
@@ -216,8 +217,7 @@
 		 "i2c-tiny-usb at bus %03d device %03d",
 		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
 
-	if (usb_write(&dev->adapter, CMD_SET_DELAY,
-		      cpu_to_le16(delay), 0, NULL, 0) != 0) {
+	if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) {
 		dev_err(&dev->adapter.dev,
 			"failure setting delay to %dus\n", delay);
 		retval = -EIO;
--- linux-ec2-2.6.32.orig/drivers/cdrom/Makefile
+++ linux-ec2-2.6.32/drivers/cdrom/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_BLK_DEV_SR)	+=              cdrom.o
 obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
 obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
+obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+=		cdrom.o
 
 obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
 obj-$(CONFIG_GDROM)		+= gdrom.o      cdrom.o
--- linux-ec2-2.6.32.orig/drivers/cdrom/cdrom.c
+++ linux-ec2-2.6.32/drivers/cdrom/cdrom.c
@@ -290,7 +290,7 @@
 /* default compatibility mode */
 static int autoclose=1;
 static int autoeject;
-static int lockdoor = 1;
+static int lockdoor = 0;
 /* will we ever get to use this... sigh. */
 static int check_media_type;
 /* automatically restart mrw format */
--- linux-ec2-2.6.32.orig/drivers/firewire/ohci.c
+++ linux-ec2-2.6.32/drivers/firewire/ohci.c
@@ -628,7 +628,7 @@
 	d = &ab->descriptor;
 
 	if (d->res_count == 0) {
-		size_t size, rest, offset;
+		size_t size, size2, rest, pktsize, size3, offset;
 		dma_addr_t start_bus;
 		void *start;
 
@@ -639,25 +639,61 @@
 		 */
 
 		offset = offsetof(struct ar_buffer, data);
-		start = buffer = ab;
+		start = ab;
 		start_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+		buffer = ab->data;
 
 		ab = ab->next;
 		d = &ab->descriptor;
-		size = buffer + PAGE_SIZE - ctx->pointer;
+		size = start + PAGE_SIZE - ctx->pointer;
+		/* valid buffer data in the next page */
 		rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
+		/* what actually fits in this page */
+		size2 = min(rest, (size_t)PAGE_SIZE - offset - size);
 		memmove(buffer, ctx->pointer, size);
-		memcpy(buffer + size, ab->data, rest);
-		ctx->current_buffer = ab;
-		ctx->pointer = (void *) ab->data + rest;
-		end = buffer + size + rest;
+		memcpy(buffer + size, ab->data, size2);
 
-		while (buffer < end)
-			buffer = handle_ar_packet(ctx, buffer);
+		while (size > 0) {
+			void *next = handle_ar_packet(ctx, buffer);
+			pktsize = next - buffer;
+			if (pktsize >= size) {
+				/*
+				 * We have handled all the data that was
+				 * originally in this page, so we can now
+				 * continue in the next page.
+				 */
+				buffer = next;
+				break;
+			}
+			/* move the next packet to the start of the buffer */
+			memmove(buffer, next, size + size2 - pktsize);
+			size -= pktsize;
+			/* fill up this page again */
+			size3 = min(rest - size2,
+				    (size_t)PAGE_SIZE - offset - size - size2);
+			memcpy(buffer + size + size2,
+			       (void *) ab->data + size2, size3);
+			size2 += size3;
+		}
 
-		dma_free_coherent(ohci->card.device, PAGE_SIZE,
-				  start, start_bus);
-		ar_context_add_page(ctx);
+		if (rest > 0) {
+			/* handle the packets that are fully in the next page */
+			buffer = (void *) ab->data +
+					(buffer - (start + offset + size));
+			end = (void *) ab->data + rest;
+
+			while (buffer < end)
+				buffer = handle_ar_packet(ctx, buffer);
+
+			ctx->current_buffer = ab;
+			ctx->pointer = end;
+
+			dma_free_coherent(ohci->card.device, PAGE_SIZE,
+					  start, start_bus);
+			ar_context_add_page(ctx);
+		} else {
+			ctx->pointer = start + PAGE_SIZE;
+		}
 	} else {
 		buffer = ctx->pointer;
 		ctx->pointer = end =
@@ -2209,6 +2245,13 @@
 	page     = payload >> PAGE_SHIFT;
 	offset   = payload & ~PAGE_MASK;
 	rest     = p->payload_length;
+	/*
+	 * The controllers I've tested have not worked correctly when
+	 * second_req_count is zero.  Rather than do something we know won't
+	 * work, return an error
+	 */
+	if (rest == 0)
+		return -EINVAL;
 
 	/* FIXME: make packet-per-buffer/dual-buffer a context option */
 	while (rest > 0) {
@@ -2262,7 +2305,7 @@
 					unsigned long payload)
 {
 	struct iso_context *ctx = container_of(base, struct iso_context, base);
-	struct descriptor *d = NULL, *pd = NULL;
+	struct descriptor *d, *pd;
 	struct fw_iso_packet *p = packet;
 	dma_addr_t d_bus, page_bus;
 	u32 z, header_z, rest;
@@ -2300,8 +2343,9 @@
 		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
 
 		rest = payload_per_buffer;
+		pd = d;
 		for (j = 1; j < z; j++) {
-			pd = d + j;
+			pd++;
 			pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
 						  DESCRIPTOR_INPUT_MORE);
 
@@ -2404,6 +2448,7 @@
 
 #define PCI_VENDOR_ID_AGERE		PCI_VENDOR_ID_ATT
 #define PCI_DEVICE_ID_AGERE_FW643	0x5901
+#define PCI_DEVICE_ID_TI_TSB43AB23	0x8024
 
 static int __devinit pci_probe(struct pci_dev *dev,
 			       const struct pci_device_id *ent)
@@ -2469,7 +2514,8 @@
 #if !defined(CONFIG_X86_32)
 	/* dual-buffer mode is broken with descriptor addresses above 2G */
 	if (dev->vendor == PCI_VENDOR_ID_TI &&
-	    dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
+	    (dev->device == PCI_DEVICE_ID_TI_TSB43AB22 ||
+	     dev->device == PCI_DEVICE_ID_TI_TSB43AB23))
 		ohci->use_dualbuffer = false;
 #endif
 
--- linux-ec2-2.6.32.orig/drivers/firewire/core-card.c
+++ linux-ec2-2.6.32/drivers/firewire/core-card.c
@@ -57,6 +57,9 @@
 static LIST_HEAD(descriptor_list);
 static int descriptor_count;
 
+/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */
+static size_t config_rom_length = 1 + 4 + 1 + 1;
+
 #define BIB_CRC(v)		((v) <<  0)
 #define BIB_CRC_LENGTH(v)	((v) << 16)
 #define BIB_INFO_LENGTH(v)	((v) << 24)
@@ -72,7 +75,7 @@
 #define BIB_CMC			((1) << 30)
 #define BIB_IMC			((1) << 31)
 
-static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
+static u32 *generate_config_rom(struct fw_card *card)
 {
 	struct fw_descriptor *desc;
 	static u32 config_rom[256];
@@ -131,7 +134,7 @@
 	for (i = 0; i < j; i += length + 1)
 		length = fw_compute_block_crc(config_rom + i);
 
-	*config_rom_length = j;
+	WARN_ON(j != config_rom_length);
 
 	return config_rom;
 }
@@ -140,17 +143,24 @@
 {
 	struct fw_card *card;
 	u32 *config_rom;
-	size_t length;
 
 	list_for_each_entry (card, &card_list, link) {
-		config_rom = generate_config_rom(card, &length);
-		card->driver->set_config_rom(card, config_rom, length);
+		config_rom = generate_config_rom(card);
+		card->driver->set_config_rom(card, config_rom,
+					     config_rom_length);
 	}
 }
 
+static size_t required_space(struct fw_descriptor *desc)
+{
+	/* descriptor + entry into root dir + optional immediate entry */
+	return desc->length + 1 + (desc->immediate > 0 ? 1 : 0);
+}
+
 int fw_core_add_descriptor(struct fw_descriptor *desc)
 {
 	size_t i;
+	int ret;
 
 	/*
 	 * Check descriptor is valid; the length of all blocks in the
@@ -166,15 +176,21 @@
 
 	mutex_lock(&card_mutex);
 
-	list_add_tail(&desc->link, &descriptor_list);
-	descriptor_count++;
-	if (desc->immediate > 0)
+	if (config_rom_length + required_space(desc) > 256) {
+		ret = -EBUSY;
+	} else {
+		list_add_tail(&desc->link, &descriptor_list);
+		config_rom_length += required_space(desc);
 		descriptor_count++;
-	update_config_roms();
+		if (desc->immediate > 0)
+			descriptor_count++;
+		update_config_roms();
+		ret = 0;
+	}
 
 	mutex_unlock(&card_mutex);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(fw_core_add_descriptor);
 
@@ -183,6 +199,7 @@
 	mutex_lock(&card_mutex);
 
 	list_del(&desc->link);
+	config_rom_length -= required_space(desc);
 	descriptor_count--;
 	if (desc->immediate > 0)
 		descriptor_count--;
@@ -222,7 +239,7 @@
 static void fw_card_bm_work(struct work_struct *work)
 {
 	struct fw_card *card = container_of(work, struct fw_card, work.work);
-	struct fw_device *root_device;
+	struct fw_device *root_device, *irm_device;
 	struct fw_node *root_node;
 	unsigned long flags;
 	int root_id, new_root_id, irm_id, local_id;
@@ -230,6 +247,7 @@
 	bool do_reset = false;
 	bool root_device_is_running;
 	bool root_device_is_cmc;
+	bool irm_is_1394_1995_only;
 
 	spin_lock_irqsave(&card->lock, flags);
 
@@ -239,12 +257,18 @@
 	}
 
 	generation = card->generation;
+
 	root_node = card->root_node;
 	fw_node_get(root_node);
 	root_device = root_node->data;
 	root_device_is_running = root_device &&
 			atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
 	root_device_is_cmc = root_device && root_device->cmc;
+
+	irm_device = card->irm_node->data;
+	irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
+			(irm_device->config_rom[2] & 0x000000f0) == 0;
+
 	root_id  = root_node->node_id;
 	irm_id   = card->irm_node->node_id;
 	local_id = card->local_node->node_id;
@@ -267,8 +291,15 @@
 
 		if (!card->irm_node->link_on) {
 			new_root_id = local_id;
-			fw_notify("IRM has link off, making local node (%02x) root.\n",
-				  new_root_id);
+			fw_notify("%s, making local node (%02x) root.\n",
+				  "IRM has link off", new_root_id);
+			goto pick_me;
+		}
+
+		if (irm_is_1394_1995_only) {
+			new_root_id = local_id;
+			fw_notify("%s, making local node (%02x) root.\n",
+				  "IRM is not 1394a compliant", new_root_id);
 			goto pick_me;
 		}
 
@@ -307,8 +338,8 @@
 			 * root, and thus, IRM.
 			 */
 			new_root_id = local_id;
-			fw_notify("BM lock failed, making local node (%02x) root.\n",
-				  new_root_id);
+			fw_notify("%s, making local node (%02x) root.\n",
+				  "BM lock failed", new_root_id);
 			goto pick_me;
 		}
 	} else if (card->bm_generation != generation) {
@@ -436,7 +467,6 @@
 		u32 max_receive, u32 link_speed, u64 guid)
 {
 	u32 *config_rom;
-	size_t length;
 	int ret;
 
 	card->max_receive = max_receive;
@@ -445,8 +475,8 @@
 
 	mutex_lock(&card_mutex);
 
-	config_rom = generate_config_rom(card, &length);
-	ret = card->driver->enable(card, config_rom, length);
+	config_rom = generate_config_rom(card);
+	ret = card->driver->enable(card, config_rom, config_rom_length);
 	if (ret == 0)
 		list_add_tail(&card->link, &card_list);
 
--- linux-ec2-2.6.32.orig/drivers/firewire/core-device.c
+++ linux-ec2-2.6.32/drivers/firewire/core-device.c
@@ -463,6 +463,7 @@
 		return -ENOMEM;
 
 	stack = &rom[READ_BIB_ROM_SIZE];
+	memset(rom, 0, sizeof(*rom) * READ_BIB_ROM_SIZE);
 
 	device->max_speed = SCODE_100;
 
--- linux-ec2-2.6.32.orig/drivers/firewire/core-cdev.c
+++ linux-ec2-2.6.32/drivers/firewire/core-cdev.c
@@ -1299,24 +1299,24 @@
 	int ret;
 
 	if (_IOC_TYPE(cmd) != '#' ||
-	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers))
+	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
+	    _IOC_SIZE(cmd) > sizeof(buffer))
 		return -EINVAL;
 
-	if (_IOC_DIR(cmd) & _IOC_WRITE) {
-		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
-		    copy_from_user(buffer, arg, _IOC_SIZE(cmd)))
+	if (_IOC_DIR(cmd) == _IOC_READ)
+		memset(&buffer, 0, _IOC_SIZE(cmd));
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE)
+		if (copy_from_user(buffer, arg, _IOC_SIZE(cmd)))
 			return -EFAULT;
-	}
 
 	ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
 	if (ret < 0)
 		return ret;
 
-	if (_IOC_DIR(cmd) & _IOC_READ) {
-		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
-		    copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		if (copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
 			return -EFAULT;
-	}
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/power/olpc_battery.c
+++ linux-ec2-2.6.32/drivers/power/olpc_battery.c
@@ -271,14 +271,14 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32;
+		val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_AVG:
 		ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120;
+		val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
 		ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -299,7 +299,7 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
+		val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256;
 		break;
 	case POWER_SUPPLY_PROP_TEMP_AMBIENT:
 		ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
@@ -313,7 +313,7 @@
 		if (ret)
 			return ret;
 
-		val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15;
+		val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15;
 		break;
 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
 		ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
--- linux-ec2-2.6.32.orig/drivers/power/apm_power.c
+++ linux-ec2-2.6.32/drivers/power/apm_power.c
@@ -233,6 +233,7 @@
 		empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
 		now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
 		avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+		break;
 	case SOURCE_VOLTAGE:
 		full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX;
 		empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN;
--- linux-ec2-2.6.32.orig/drivers/power/ds2760_battery.c
+++ linux-ec2-2.6.32/drivers/power/ds2760_battery.c
@@ -211,7 +211,7 @@
 	if (di->rem_capacity > 100)
 		di->rem_capacity = 100;
 
-	if (di->current_uA >= 100L)
+	if (di->current_uA < -100L)
 		di->life_sec = -((di->accum_current_uAh - di->empty_uAh) * 36L)
 					/ (di->current_uA / 100L);
 	else
--- linux-ec2-2.6.32.orig/drivers/mtd/ubi/upd.c
+++ linux-ec2-2.6.32/drivers/mtd/ubi/upd.c
@@ -147,12 +147,15 @@
 	}
 
 	if (bytes == 0) {
+		err = ubi_wl_flush(ubi);
+		if (err)
+			return err;
+
 		err = clear_update_marker(ubi, vol, 0);
 		if (err)
 			return err;
-		err = ubi_wl_flush(ubi);
-		if (!err)
-			vol->updating = 0;
+		vol->updating = 0;
+		return 0;
 	}
 
 	vol->upd_buf = vmalloc(ubi->leb_size);
@@ -362,16 +365,16 @@
 
 	ubi_assert(vol->upd_received <= vol->upd_bytes);
 	if (vol->upd_received == vol->upd_bytes) {
+		err = ubi_wl_flush(ubi);
+		if (err)
+			return err;
 		/* The update is finished, clear the update marker */
 		err = clear_update_marker(ubi, vol, vol->upd_bytes);
 		if (err)
 			return err;
-		err = ubi_wl_flush(ubi);
-		if (err == 0) {
-			vol->updating = 0;
-			err = to_write;
-			vfree(vol->upd_buf);
-		}
+		vol->updating = 0;
+		err = to_write;
+		vfree(vol->upd_buf);
 	}
 
 	return err;
--- linux-ec2-2.6.32.orig/drivers/mtd/ubi/cdev.c
+++ linux-ec2-2.6.32/drivers/mtd/ubi/cdev.c
@@ -853,7 +853,6 @@
 			break;
 		}
 
-		req.name[req.name_len] = '\0';
 		err = verify_mkvol_req(ubi, &req);
 		if (err)
 			break;
--- linux-ec2-2.6.32.orig/drivers/mtd/ubi/vtbl.c
+++ linux-ec2-2.6.32/drivers/mtd/ubi/vtbl.c
@@ -566,6 +566,7 @@
 		vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
 		vol->alignment = be32_to_cpu(vtbl[i].alignment);
 		vol->data_pad = be32_to_cpu(vtbl[i].data_pad);
+		vol->upd_marker = vtbl[i].upd_marker;
 		vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?
 					UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
 		vol->name_len = be16_to_cpu(vtbl[i].name_len);
--- linux-ec2-2.6.32.orig/drivers/mtd/nand/pxa3xx_nand.c
+++ linux-ec2-2.6.32/drivers/mtd/nand/pxa3xx_nand.c
@@ -316,7 +316,7 @@
 #define tAR_NDTR1(r)	(((r) >> 0) & 0xf)
 
 /* convert nano-seconds to nand flash controller clock cycles */
-#define ns2cycle(ns, clk)	(int)(((ns) * (clk / 1000000) / 1000) - 1)
+#define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
 /* convert nand flash controller clock cycles to nano-seconds */
 #define cycle2ns(c, clk)	((((c) + 1) * 1000000 + clk / 500) / (clk / 1000))
--- linux-ec2-2.6.32.orig/drivers/mtd/nand/omap2.c
+++ linux-ec2-2.6.32/drivers/mtd/nand/omap2.c
@@ -1099,6 +1099,6 @@
 module_init(omap_nand_init);
 module_exit(omap_nand_exit);
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");
--- linux-ec2-2.6.32.orig/drivers/mtd/onenand/omap2.c
+++ linux-ec2-2.6.32/drivers/mtd/onenand/omap2.c
@@ -800,7 +800,7 @@
 module_init(omap2_onenand_init);
 module_exit(omap2_onenand_exit);
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
 MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
--- linux-ec2-2.6.32.orig/drivers/mtd/onenand/generic.c
+++ linux-ec2-2.6.32/drivers/mtd/onenand/generic.c
@@ -131,7 +131,7 @@
 	.remove		= __devexit_p(generic_onenand_remove),
 };
 
-MODULE_ALIAS(DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
 
 static int __init generic_onenand_init(void)
 {
--- linux-ec2-2.6.32.orig/drivers/macintosh/windfarm_smu_controls.c
+++ linux-ec2-2.6.32/drivers/macintosh/windfarm_smu_controls.c
@@ -202,6 +202,8 @@
 		fct->ctrl.name = "cpu-front-fan-1";
 	else if (!strcmp(l, "CPU A PUMP"))
 		fct->ctrl.name = "cpu-pump-0";
+	else if (!strcmp(l, "CPU B PUMP"))
+		fct->ctrl.name = "cpu-pump-1";
 	else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") ||
 		 !strcmp(l, "EXPANSION SLOTS INTAKE"))
 		fct->ctrl.name = "slots-fan";
--- linux-ec2-2.6.32.orig/drivers/macintosh/therm_adt746x.c
+++ linux-ec2-2.6.32/drivers/macintosh/therm_adt746x.c
@@ -79,6 +79,7 @@
 	u8			limits[3];
 	int			last_speed[2];
 	int			last_var[2];
+	int			pwm_inv[2];
 };
 
 static enum {ADT7460, ADT7467} therm_type;
@@ -89,6 +90,8 @@
 
 static void write_both_fan_speed(struct thermostat *th, int speed);
 static void write_fan_speed(struct thermostat *th, int speed, int fan);
+static void thermostat_create_files(void);
+static void thermostat_remove_files(void);
 
 static int
 write_reg(struct thermostat* th, int reg, u8 data)
@@ -160,6 +163,8 @@
 	struct thermostat *th = i2c_get_clientdata(client);
 	int i;
 	
+	thermostat_remove_files();
+
 	if (thread_therm != NULL) {
 		kthread_stop(thread_therm);
 	}
@@ -229,19 +234,23 @@
 	
 	if (speed >= 0) {
 		manual = read_reg(th, MANUAL_MODE[fan]);
+		manual &= ~INVERT_MASK;
 		write_reg(th, MANUAL_MODE[fan],
-			(manual|MANUAL_MASK) & (~INVERT_MASK));
+			manual | MANUAL_MASK | th->pwm_inv[fan]);
 		write_reg(th, FAN_SPD_SET[fan], speed);
 	} else {
 		/* back to automatic */
 		if(therm_type == ADT7460) {
 			manual = read_reg(th,
 				MANUAL_MODE[fan]) & (~MANUAL_MASK);
-
+			manual &= ~INVERT_MASK;
+			manual |= th->pwm_inv[fan];
 			write_reg(th,
 				MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
 		} else {
 			manual = read_reg(th, MANUAL_MODE[fan]);
+			manual &= ~INVERT_MASK;
+			manual |= th->pwm_inv[fan];
 			write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK));
 		}
 	}
@@ -418,6 +427,10 @@
 
 	thermostat = th;
 
+	/* record invert bit status because fw can corrupt it after suspend */
+	th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
+	th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
+
 	/* be sure to really write fan speed the first time */
 	th->last_speed[0] = -2;
 	th->last_speed[1] = -2;
@@ -440,6 +453,8 @@
 		return -ENOMEM;
 	}
 
+	thermostat_create_files();
+
 	return 0;
 }
 
@@ -557,7 +572,6 @@
 	struct device_node* np;
 	const u32 *prop;
 	int i = 0, offset = 0;
-	int err;
 
 	np = of_find_node_by_name(NULL, "fan");
 	if (!np)
@@ -624,6 +638,17 @@
 		return -ENODEV;
 	}
 
+#ifndef CONFIG_I2C_POWERMAC
+	request_module("i2c-powermac");
+#endif
+
+	return i2c_add_driver(&thermostat_driver);
+}
+
+static void thermostat_create_files(void)
+{
+	int err;
+
 	err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature);
 	err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature);
 	err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit);
@@ -638,16 +663,9 @@
 	if (err)
 		printk(KERN_WARNING
 			"Failed to create tempertaure attribute file(s).\n");
-
-#ifndef CONFIG_I2C_POWERMAC
-	request_module("i2c-powermac");
-#endif
-
-	return i2c_add_driver(&thermostat_driver);
 }
 
-static void __exit
-thermostat_exit(void)
+static void thermostat_remove_files(void)
 {
 	if (of_dev) {
 		device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature);
@@ -664,9 +682,14 @@
 			device_remove_file(&of_dev->dev,
 					   &dev_attr_sensor2_fan_speed);
 
-		of_device_unregister(of_dev);
 	}
+}
+
+static void __exit
+thermostat_exit(void)
+{
 	i2c_del_driver(&thermostat_driver);
+	of_device_unregister(of_dev);
 }
 
 module_init(thermostat_init);
--- linux-ec2-2.6.32.orig/drivers/block/Makefile
+++ linux-ec2-2.6.32/drivers/block/Makefile
@@ -35,6 +35,6 @@
 obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
 obj-$(CONFIG_BLK_DEV_HD)	+= hd.o
 
-obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen-blkfront.o
+obj-$(CONFIG_XEN_BLKFRONT)	+= xen-blkfront.o
 
 swim_mod-objs	:= swim.o swim_asm.o
--- linux-ec2-2.6.32.orig/drivers/block/nbd.c
+++ linux-ec2-2.6.32/drivers/block/nbd.c
@@ -56,7 +56,7 @@
 
 static unsigned int nbds_max = 16;
 static struct nbd_device *nbd_dev;
-static int max_part;
+static int max_part = 15;
 
 /*
  * Use just one lock (or at most 1 per NIC). Two arguments for this:
--- linux-ec2-2.6.32.orig/drivers/block/cciss.c
+++ linux-ec2-2.6.32/drivers/block/cciss.c
@@ -339,6 +339,9 @@
 	if (*pos > h->highest_lun)
 		return 0;
 
+	if (drv == NULL) /* it's possible for h->drv[] to have holes. */
+		return 0;
+
 	if (drv->heads == 0)
 		return 0;
 
--- linux-ec2-2.6.32.orig/drivers/block/pktcdvd.c
+++ linux-ec2-2.6.32/drivers/block/pktcdvd.c
@@ -322,7 +322,7 @@
 	pkt_kobj_remove(pd->kobj_stat);
 	pkt_kobj_remove(pd->kobj_wqueue);
 	if (class_pktcdvd)
-		device_destroy(class_pktcdvd, pd->pkt_dev);
+		device_unregister(pd->dev);
 }
 
 
@@ -2408,7 +2408,7 @@
 	pkt_shrink_pktlist(pd);
 }
 
-static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
+static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor)
 {
 	if (dev_minor >= MAX_WRITERS)
 		return NULL;
--- linux-ec2-2.6.32.orig/drivers/block/Kconfig
+++ linux-ec2-2.6.32/drivers/block/Kconfig
@@ -458,9 +458,9 @@
 	help
 	  Include support for the Xilinx SystemACE CompactFlash interface
 
-config XEN_BLKDEV_FRONTEND
+config XEN_BLKFRONT
 	tristate "Xen virtual block device support"
-	depends on XEN
+	depends on PARAVIRT_XEN
 	default y
 	help
 	  This driver implements the front-end of the Xen virtual
--- linux-ec2-2.6.32.orig/drivers/block/xen-blkfront.c
+++ linux-ec2-2.6.32/drivers/block/xen-blkfront.c
@@ -1056,7 +1056,6 @@
 
 static struct xenbus_driver blkfront = {
 	.name = "vbd",
-	.owner = THIS_MODULE,
 	.ids = blkfront_ids,
 	.probe = blkfront_probe,
 	.remove = blkfront_remove,
--- linux-ec2-2.6.32.orig/drivers/block/loop.c
+++ linux-ec2-2.6.32/drivers/block/loop.c
@@ -238,6 +238,8 @@
 		if (ret)
 			goto fail;
 
+		file_update_time(file);
+
 		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
 				bvec->bv_page, bv_offs, size, IV);
 		copied = size;
--- linux-ec2-2.6.32.orig/drivers/block/cciss.h
+++ linux-ec2-2.6.32/drivers/block/cciss.h
@@ -165,6 +165,7 @@
 	 printk("Sending %x - down to controller\n", c->busaddr );
 #endif /* CCISS_DEBUG */ 
          writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
 	 h->commands_outstanding++;
 	 if ( h->commands_outstanding > h->max_outstanding)
 		h->max_outstanding = h->commands_outstanding;
--- linux-ec2-2.6.32.orig/drivers/lguest/segments.c
+++ linux-ec2-2.6.32/drivers/lguest/segments.c
@@ -179,8 +179,10 @@
 	 * We assume the Guest has the same number of GDT entries as the
 	 * Host, otherwise we'd have to dynamically allocate the Guest GDT.
 	 */
-	if (num >= ARRAY_SIZE(cpu->arch.gdt))
+	if (num >= ARRAY_SIZE(cpu->arch.gdt)) {
 		kill_guest(cpu, "too many gdt entries %i", num);
+		return;
+	}
 
 	/* Set it up, then fix it. */
 	cpu->arch.gdt[num].a = lo;
--- linux-ec2-2.6.32.orig/drivers/serial/8250.c
+++ linux-ec2-2.6.32/drivers/serial/8250.c
@@ -83,6 +83,9 @@
 
 #define PASS_LIMIT	256
 
+#define BOTH_EMPTY 	(UART_LSR_TEMT | UART_LSR_THRE)
+
+
 /*
  * We default to IRQ0 for the "no irq" hack.   Some
  * machine types want others as well - they're free
@@ -252,7 +255,8 @@
 		.fifo_size	= 128,
 		.tx_loadsz	= 128,
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-		.flags		= UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+		/* UART_CAP_EFR breaks billionon CF bluetooth card. */
+		.flags		= UART_CAP_FIFO | UART_CAP_SLEEP,
 	},
 	[PORT_RSA] = {
 		.name		= "RSA",
@@ -1339,14 +1343,12 @@
 		serial_out(up, UART_IER, up->ier);
 
 		if (up->bugs & UART_BUG_TXEN) {
-			unsigned char lsr, iir;
+			unsigned char lsr;
 			lsr = serial_in(up, UART_LSR);
 			up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
-			iir = serial_in(up, UART_IIR) & 0x0f;
 			if ((up->port.type == PORT_RM9000) ?
-				(lsr & UART_LSR_THRE &&
-				(iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
-				(lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
+				(lsr & UART_LSR_THRE) :
+				(lsr & UART_LSR_TEMT))
 				transmit_chars(up);
 		}
 	}
@@ -1794,7 +1796,7 @@
 	up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
-	return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+	return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
 }
 
 static unsigned int serial8250_get_mctrl(struct uart_port *port)
@@ -1852,8 +1854,6 @@
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
 /*
  *	Wait for transmitter & holding register to empty
  */
--- linux-ec2-2.6.32.orig/drivers/serial/uartlite.c
+++ linux-ec2-2.6.32/drivers/serial/uartlite.c
@@ -394,7 +394,7 @@
 		spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int __init ulite_console_setup(struct console *co, char *options)
+static int __devinit ulite_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
--- linux-ec2-2.6.32.orig/drivers/serial/serial_core.c
+++ linux-ec2-2.6.32/drivers/serial/serial_core.c
@@ -1067,10 +1067,10 @@
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int uart_get_count(struct uart_state *state,
-			  struct serial_icounter_struct __user *icnt)
+static int uart_get_icount(struct tty_struct *tty,
+			  struct serial_icounter_struct *icount)
 {
-	struct serial_icounter_struct icount;
+	struct uart_state *state = tty->driver_data;
 	struct uart_icount cnow;
 	struct uart_port *uport = state->uart_port;
 
@@ -1078,19 +1078,19 @@
 	memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
 	spin_unlock_irq(&uport->lock);
 
-	icount.cts         = cnow.cts;
-	icount.dsr         = cnow.dsr;
-	icount.rng         = cnow.rng;
-	icount.dcd         = cnow.dcd;
-	icount.rx          = cnow.rx;
-	icount.tx          = cnow.tx;
-	icount.frame       = cnow.frame;
-	icount.overrun     = cnow.overrun;
-	icount.parity      = cnow.parity;
-	icount.brk         = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
+	icount->cts         = cnow.cts;
+	icount->dsr         = cnow.dsr;
+	icount->rng         = cnow.rng;
+	icount->dcd         = cnow.dcd;
+	icount->rx          = cnow.rx;
+	icount->tx          = cnow.tx;
+	icount->frame       = cnow.frame;
+	icount->overrun     = cnow.overrun;
+	icount->parity      = cnow.parity;
+	icount->brk         = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
 
-	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+	return 0;
 }
 
 /*
@@ -1143,10 +1143,6 @@
 	case TIOCMIWAIT:
 		ret = uart_wait_modem_status(state, arg);
 		break;
-
-	case TIOCGICOUNT:
-		ret = uart_get_count(state, uarg);
-		break;
 	}
 
 	if (ret != -ENOIOCTLCMD)
@@ -2322,6 +2318,7 @@
 #endif
 	.tiocmget	= uart_tiocmget,
 	.tiocmset	= uart_tiocmset,
+	.get_icount	= uart_get_icount,
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_init	= uart_poll_init,
 	.poll_get_char	= uart_poll_get_char,
--- linux-ec2-2.6.32.orig/drivers/serial/Kconfig
+++ linux-ec2-2.6.32/drivers/serial/Kconfig
@@ -9,6 +9,7 @@
 # The new 8250/16550 serial drivers
 config SERIAL_8250
 	tristate "8250/16550 and compatible serial support"
+	depends on !XEN_DISABLE_SERIAL
 	select SERIAL_CORE
 	---help---
 	  This selects whether you want to include the driver for the standard
--- linux-ec2-2.6.32.orig/drivers/serial/imx.c
+++ linux-ec2-2.6.32/drivers/serial/imx.c
@@ -119,7 +119,8 @@
 #define  MX2_UCR3_RXDMUXSEL	 (1<<2)  /* RXD Muxed Input Select, on mx2/mx3 */
 #define  UCR3_INVT  	 (1<<1)  /* Inverted Infrared transmission */
 #define  UCR3_BPEN  	 (1<<0)  /* Preset registers enable */
-#define  UCR4_CTSTL_32   (32<<10) /* CTS trigger level (32 chars) */
+#define  UCR4_CTSTL_SHF  10      /* CTS trigger level shift */
+#define  UCR4_CTSTL_MASK 0x3F    /* CTS trigger is 6 bits wide */
 #define  UCR4_INVR  	 (1<<9)  /* Inverted infrared reception */
 #define  UCR4_ENIRI 	 (1<<8)  /* Serial infrared interrupt enable */
 #define  UCR4_WKEN  	 (1<<7)  /* Wake interrupt enable */
@@ -381,12 +382,13 @@
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
-	unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
+	unsigned int val;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
 	writel(USR1_RTSD, sport->port.membase + USR1);
+	val = readl(sport->port.membase + USR1) & USR1_RTSS;
 	uart_handle_cts_change(&sport->port, !!val);
 	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 
@@ -590,6 +592,9 @@
 	return 0;
 }
 
+/* half the RX buffer size */
+#define CTSTL 16
+
 static int imx_startup(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
@@ -606,6 +611,10 @@
 	if (USE_IRDA(sport))
 		temp |= UCR4_IRSC;
 
+	/* set the trigger level for CTS */
+	temp &= ~(UCR4_CTSTL_MASK<<  UCR4_CTSTL_SHF);
+	temp |= CTSTL<<  UCR4_CTSTL_SHF;
+
 	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
 	if (USE_IRDA(sport)) {
@@ -1279,7 +1288,7 @@
 		sport->use_irda = 1;
 #endif
 
-	if (pdata->init) {
+	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
 			goto clkput;
@@ -1292,7 +1301,7 @@
 
 	return 0;
 deinit:
-	if (pdata->exit)
+	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 clkput:
 	clk_put(sport->clk);
@@ -1321,7 +1330,7 @@
 
 	clk_disable(sport->clk);
 
-	if (pdata->exit)
+	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 
 	iounmap(sport->port.membase);
--- linux-ec2-2.6.32.orig/drivers/serial/8250_pnp.c
+++ linux-ec2-2.6.32/drivers/serial/8250_pnp.c
@@ -328,15 +328,7 @@
 	/* U.S. Robotics 56K Voice INT PnP*/
 	{	"USR9190",		0	},
 	/* Wacom tablets */
-	{	"WACF004",		0	},
-	{	"WACF005",		0	},
-	{       "WACF006",              0       },
-	{       "WACF007",              0       },
-	{       "WACF008",              0       },
-	{       "WACF009",              0       },
-	{       "WACF00A",              0       },
-	{       "WACF00B",              0       },
-	{       "WACF00C",              0       },
+	{	"WACFXXX",		0	},
 	/* Compaq touchscreen */
 	{       "FPI2002",              0 },
 	/* Fujitsu Stylistic touchscreens */
@@ -354,6 +346,10 @@
 	{	"FUJ02E5",		0	},
 	/* Fujitsu P-series tablet PC device */
 	{	"FUJ02E6",		0	},
+	/* Fujitsu Wacom 2FGT Tablet PC device */
+	{	"FUJ02E7",		0	},
+	/* Fujitsu Wacom 1FGT Tablet PC device */
+	{	"FUJ02E9",		0	},
 	/*
 	 * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
 	 * disguise)
--- linux-ec2-2.6.32.orig/drivers/serial/cpm_uart/cpm_uart_core.c
+++ linux-ec2-2.6.32/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -930,6 +930,83 @@
 	}
 }
 
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_CPM_CONSOLE)
+/*
+ * Write a string to the serial port
+ * Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_early_write(struct uart_cpm_port *pinfo,
+		const char *string, u_int count)
+{
+	unsigned int i;
+	cbd_t __iomem *bdp, *bdbase;
+	unsigned char *cpm_outp_addr;
+
+	/* Get the address of the host memory buffer.
+	 */
+	bdp = pinfo->tx_cur;
+	bdbase = pinfo->tx_bd_base;
+
+	/*
+	 * Now, do each character.  This is not as bad as it looks
+	 * since this is a holding FIFO and not a transmitting FIFO.
+	 * We could add the complexity of filling the entire transmit
+	 * buffer, but we would just wait longer between accesses......
+	 */
+	for (i = 0; i < count; i++, string++) {
+		/* Wait for transmitter fifo to empty.
+		 * Ready indicates output is ready, and xmt is doing
+		 * that, not that it is ready for us to send.
+		 */
+		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+			;
+
+		/* Send the character out.
+		 * If the buffer address is in the CPM DPRAM, don't
+		 * convert it.
+		 */
+		cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+					pinfo);
+		*cpm_outp_addr = *string;
+
+		out_be16(&bdp->cbd_datlen, 1);
+		setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+			bdp = bdbase;
+		else
+			bdp++;
+
+		/* if a LF, also do CR... */
+		if (*string == 10) {
+			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+				;
+
+			cpm_outp_addr = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr),
+						pinfo);
+			*cpm_outp_addr = 13;
+
+			out_be16(&bdp->cbd_datlen, 1);
+			setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
+				bdp = bdbase;
+			else
+				bdp++;
+		}
+	}
+
+	/*
+	 * Finally, Wait for transmitter & holding register to empty
+	 *  and restore the IER
+	 */
+	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
+		;
+
+	pinfo->tx_cur = bdp;
+}
+#endif
+
 #ifdef CONFIG_CONSOLE_POLL
 /* Serial polling routines for writing and reading from the uart while
  * in an interrupt or debug context.
@@ -999,7 +1076,7 @@
 	static char ch[2];
 
 	ch[0] = (char)c;
-	cpm_uart_early_write(pinfo->port.line, ch, 1);
+	cpm_uart_early_write(pinfo, ch, 1);
 }
 #endif /* CONFIG_CONSOLE_POLL */
 
@@ -1130,9 +1207,6 @@
 				   u_int count)
 {
 	struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
-	unsigned int i;
-	cbd_t __iomem *bdp, *bdbase;
-	unsigned char *cp;
 	unsigned long flags;
 	int nolock = oops_in_progress;
 
@@ -1142,66 +1216,7 @@
 		spin_lock_irqsave(&pinfo->port.lock, flags);
 	}
 
-	/* Get the address of the host memory buffer.
-	 */
-	bdp = pinfo->tx_cur;
-	bdbase = pinfo->tx_bd_base;
-
-	/*
-	 * Now, do each character.  This is not as bad as it looks
-	 * since this is a holding FIFO and not a transmitting FIFO.
-	 * We could add the complexity of filling the entire transmit
-	 * buffer, but we would just wait longer between accesses......
-	 */
-	for (i = 0; i < count; i++, s++) {
-		/* Wait for transmitter fifo to empty.
-		 * Ready indicates output is ready, and xmt is doing
-		 * that, not that it is ready for us to send.
-		 */
-		while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-			;
-
-		/* Send the character out.
-		 * If the buffer address is in the CPM DPRAM, don't
-		 * convert it.
-		 */
-		cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-		*cp = *s;
-
-		out_be16(&bdp->cbd_datlen, 1);
-		setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-		if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-			bdp = bdbase;
-		else
-			bdp++;
-
-		/* if a LF, also do CR... */
-		if (*s == 10) {
-			while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-				;
-
-			cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
-			*cp = 13;
-
-			out_be16(&bdp->cbd_datlen, 1);
-			setbits16(&bdp->cbd_sc, BD_SC_READY);
-
-			if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
-				bdp = bdbase;
-			else
-				bdp++;
-		}
-	}
-
-	/*
-	 * Finally, Wait for transmitter & holding register to empty
-	 *  and restore the IER
-	 */
-	while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
-		;
-
-	pinfo->tx_cur = bdp;
+	cpm_uart_early_write(pinfo, s, count);
 
 	if (unlikely(nolock)) {
 		local_irq_restore(flags);
--- linux-ec2-2.6.32.orig/drivers/infiniband/ulp/iser/iser_memory.c
+++ linux-ec2-2.6.32/drivers/infiniband/ulp/iser/iser_memory.c
@@ -209,6 +209,8 @@
 	mem_copy->copy_buf = NULL;
 }
 
+#define IS_4K_ALIGNED(addr)	((((unsigned long)addr) & ~MASK_4K) == 0)
+
 /**
  * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses
  * and returns the length of resulting physical address array (may be less than
@@ -221,62 +223,52 @@
  * where --few fragments of the same page-- are present in the SG as
  * consecutive elements. Also, it handles one entry SG.
  */
+
 static int iser_sg_to_page_vec(struct iser_data_buf *data,
 			       struct iser_page_vec *page_vec,
 			       struct ib_device *ibdev)
 {
-	struct scatterlist *sgl = (struct scatterlist *)data->buf;
-	struct scatterlist *sg;
-	u64 first_addr, last_addr, page;
-	int end_aligned;
-	unsigned int cur_page = 0;
+	struct scatterlist *sg, *sgl = (struct scatterlist *)data->buf;
+	u64 start_addr, end_addr, page, chunk_start = 0;
 	unsigned long total_sz = 0;
-	int i;
+	unsigned int dma_len;
+	int i, new_chunk, cur_page, last_ent = data->dma_nents - 1;
 
 	/* compute the offset of first element */
 	page_vec->offset = (u64) sgl[0].offset & ~MASK_4K;
 
+	new_chunk = 1;
+	cur_page  = 0;
 	for_each_sg(sgl, sg, data->dma_nents, i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
-
+		start_addr = ib_sg_dma_address(ibdev, sg);
+		if (new_chunk)
+			chunk_start = start_addr;
+		dma_len = ib_sg_dma_len(ibdev, sg);
+		end_addr = start_addr + dma_len;
 		total_sz += dma_len;
 
-		first_addr = ib_sg_dma_address(ibdev, sg);
-		last_addr  = first_addr + dma_len;
-
-		end_aligned   = !(last_addr  & ~MASK_4K);
-
-		/* continue to collect page fragments till aligned or SG ends */
-		while (!end_aligned && (i + 1 < data->dma_nents)) {
-			sg = sg_next(sg);
-			i++;
-			dma_len = ib_sg_dma_len(ibdev, sg);
-			total_sz += dma_len;
-			last_addr = ib_sg_dma_address(ibdev, sg) + dma_len;
-			end_aligned = !(last_addr  & ~MASK_4K);
+		/* collect page fragments until aligned or end of SG list */
+		if (!IS_4K_ALIGNED(end_addr) && i < last_ent) {
+			new_chunk = 0;
+			continue;
 		}
+		new_chunk = 1;
 
-		/* handle the 1st page in the 1st DMA element */
-		if (cur_page == 0) {
-			page = first_addr & MASK_4K;
-			page_vec->pages[cur_page] = page;
-			cur_page++;
+		/* address of the first page in the contiguous chunk;
+		   masking relevant for the very first SG entry,
+		   which might be unaligned */
+		page = chunk_start & MASK_4K;
+		do {
+			page_vec->pages[cur_page++] = page;
 			page += SIZE_4K;
-		} else
-			page = first_addr;
-
-		for (; page < last_addr; page += SIZE_4K) {
-			page_vec->pages[cur_page] = page;
-			cur_page++;
-		}
-
+		} while (page < end_addr);
 	}
+
 	page_vec->data_size = total_sz;
 	iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page);
 	return cur_page;
 }
 
-#define IS_4K_ALIGNED(addr)	((((unsigned long)addr) & ~MASK_4K) == 0)
 
 /**
  * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
@@ -284,42 +276,40 @@
  * the number of entries which are aligned correctly. Supports the case where
  * consecutive SG elements are actually fragments of the same physcial page.
  */
-static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
-					      struct ib_device *ibdev)
+static int iser_data_buf_aligned_len(struct iser_data_buf *data,
+				      struct ib_device *ibdev)
 {
-	struct scatterlist *sgl, *sg;
-	u64 end_addr, next_addr;
-	int i, cnt;
-	unsigned int ret_len = 0;
+	struct scatterlist *sgl, *sg, *next_sg = NULL;
+	u64 start_addr, end_addr;
+	int i, ret_len, start_check = 0;
+
+	if (data->dma_nents == 1)
+		return 1;
 
 	sgl = (struct scatterlist *)data->buf;
+	start_addr  = ib_sg_dma_address(ibdev, sgl);
 
-	cnt = 0;
 	for_each_sg(sgl, sg, data->dma_nents, i) {
-		/* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
-		   "offset: %ld sz: %ld\n", i,
-		   (unsigned long)sg_phys(sg),
-		   (unsigned long)sg->offset,
-		   (unsigned long)sg->length); */
-		end_addr = ib_sg_dma_address(ibdev, sg) +
-			   ib_sg_dma_len(ibdev, sg);
-		/* iser_dbg("Checking sg iobuf end address "
-		       "0x%08lX\n", end_addr); */
-		if (i + 1 < data->dma_nents) {
-			next_addr = ib_sg_dma_address(ibdev, sg_next(sg));
-			/* are i, i+1 fragments of the same page? */
-			if (end_addr == next_addr) {
-				cnt++;
-				continue;
-			} else if (!IS_4K_ALIGNED(end_addr)) {
-				ret_len = cnt + 1;
-				break;
-			}
-		}
-		cnt++;
+		if (start_check && !IS_4K_ALIGNED(start_addr))
+			break;
+
+		next_sg = sg_next(sg);
+		if (!next_sg)
+			break;
+
+		end_addr    = start_addr + ib_sg_dma_len(ibdev, sg);
+		start_addr  = ib_sg_dma_address(ibdev, next_sg);
+
+		if (end_addr == start_addr) {
+			start_check = 0;
+			continue;
+		} else
+			start_check = 1;
+
+		if (!IS_4K_ALIGNED(end_addr))
+			break;
 	}
-	if (i == data->dma_nents)
-		ret_len = cnt;	/* loop ended */
+	ret_len = (next_sg) ? i : i+1;
 	iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n",
 		 ret_len, data->dma_nents, data);
 	return ret_len;
--- linux-ec2-2.6.32.orig/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ linux-ec2-2.6.32/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -752,6 +752,8 @@
 		if (++priv->tx_outstanding == ipoib_sendq_size) {
 			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
 				  tx->qp->qp_num);
+			if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
+				ipoib_warn(priv, "request notify on send CQ failed\n");
 			netif_stop_queue(dev);
 		}
 	}
--- linux-ec2-2.6.32.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ linux-ec2-2.6.32/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -884,6 +884,7 @@
 
 	neigh->neighbour = neighbour;
 	neigh->dev = dev;
+	memset(&neigh->dgid.raw, 0, sizeof (union ib_gid));
 	*to_ipoib_neigh(neighbour) = neigh;
 	skb_queue_head_init(&neigh->queue);
 	ipoib_cm_set(neigh, NULL);
@@ -1162,7 +1163,7 @@
 
 	return ret ? ret : count;
 }
-static DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child);
+static DEVICE_ATTR(create_child, S_IWUSR, NULL, create_child);
 
 static ssize_t delete_child(struct device *dev,
 			    struct device_attribute *attr,
@@ -1182,7 +1183,7 @@
 	return ret ? ret : count;
 
 }
-static DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child);
+static DEVICE_ATTR(delete_child, S_IWUSR, NULL, delete_child);
 
 int ipoib_add_pkey_attr(struct net_device *dev)
 {
--- linux-ec2-2.6.32.orig/drivers/infiniband/hw/ipath/ipath_fs.c
+++ linux-ec2-2.6.32/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -346,10 +346,8 @@
 	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
 		spin_unlock_irqrestore(&ipath_devs_lock, flags);
 		ret = create_device_files(sb, dd);
-		if (ret) {
-			deactivate_locked_super(sb);
+		if (ret)
 			goto bail;
-		}
 		spin_lock_irqsave(&ipath_devs_lock, flags);
 	}
 
--- linux-ec2-2.6.32.orig/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ linux-ec2-2.6.32/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -486,7 +486,8 @@
 	    V_MSS_IDX(mtu_idx) |
 	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
 	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+	opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+	       V_CONG_CONTROL_FLAVOR(cong_flavor);
 	skb->priority = CPL_PRIORITY_SETUP;
 	set_arp_failure_handler(skb, act_open_req_arp_failure);
 
@@ -1303,7 +1304,8 @@
 	    V_MSS_IDX(mtu_idx) |
 	    V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx);
 	opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10);
-	opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor);
+	opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) |
+	       V_CONG_CONTROL_FLAVOR(cong_flavor);
 
 	rpl = cplhdr(skb);
 	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
--- linux-ec2-2.6.32.orig/drivers/infiniband/core/uverbs_cmd.c
+++ linux-ec2-2.6.32/drivers/infiniband/core/uverbs_cmd.c
@@ -875,68 +875,81 @@
 	return ret ? ret : in_len;
 }
 
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+	struct ib_uverbs_wc tmp;
+
+	tmp.wr_id		= wc->wr_id;
+	tmp.status		= wc->status;
+	tmp.opcode		= wc->opcode;
+	tmp.vendor_err		= wc->vendor_err;
+	tmp.byte_len		= wc->byte_len;
+	tmp.ex.imm_data		= (__u32 __force) wc->ex.imm_data;
+	tmp.qp_num		= wc->qp->qp_num;
+	tmp.src_qp		= wc->src_qp;
+	tmp.wc_flags		= wc->wc_flags;
+	tmp.pkey_index		= wc->pkey_index;
+	tmp.slid		= wc->slid;
+	tmp.sl			= wc->sl;
+	tmp.dlid_path_bits	= wc->dlid_path_bits;
+	tmp.port_num		= wc->port_num;
+	tmp.reserved		= 0;
+
+	if (copy_to_user(dest, &tmp, sizeof tmp))
+		return -EFAULT;
+
+	return 0;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
 			  const char __user *buf, int in_len,
 			  int out_len)
 {
 	struct ib_uverbs_poll_cq       cmd;
-	struct ib_uverbs_poll_cq_resp *resp;
+	struct ib_uverbs_poll_cq_resp  resp;
+	u8 __user                     *header_ptr;
+	u8 __user                     *data_ptr;
 	struct ib_cq                  *cq;
-	struct ib_wc                  *wc;
-	int                            ret = 0;
-	int                            i;
-	int                            rsize;
+	struct ib_wc                   wc;
+	int                            ret;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
-	if (!wc)
-		return -ENOMEM;
-
-	rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
-	resp = kmalloc(rsize, GFP_KERNEL);
-	if (!resp) {
-		ret = -ENOMEM;
-		goto out_wc;
-	}
-
 	cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-	if (!cq) {
-		ret = -EINVAL;
-		goto out;
-	}
+	if (!cq)
+		return -EINVAL;
 
-	resp->count = ib_poll_cq(cq, cmd.ne, wc);
+	/* we copy a struct ib_uverbs_poll_cq_resp to user space */
+	header_ptr = (void __user *)(unsigned long) cmd.response;
+	data_ptr = header_ptr + sizeof resp;
 
-	put_cq_read(cq);
+	memset(&resp, 0, sizeof resp);
+	while (resp.count < cmd.ne) {
+		ret = ib_poll_cq(cq, 1, &wc);
+		if (ret < 0)
+			goto out_put;
+		if (!ret)
+			break;
+
+		ret = copy_wc_to_user(data_ptr, &wc);
+		if (ret)
+			goto out_put;
 
-	for (i = 0; i < resp->count; i++) {
-		resp->wc[i].wr_id 	   = wc[i].wr_id;
-		resp->wc[i].status 	   = wc[i].status;
-		resp->wc[i].opcode 	   = wc[i].opcode;
-		resp->wc[i].vendor_err 	   = wc[i].vendor_err;
-		resp->wc[i].byte_len 	   = wc[i].byte_len;
-		resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
-		resp->wc[i].qp_num 	   = wc[i].qp->qp_num;
-		resp->wc[i].src_qp 	   = wc[i].src_qp;
-		resp->wc[i].wc_flags 	   = wc[i].wc_flags;
-		resp->wc[i].pkey_index 	   = wc[i].pkey_index;
-		resp->wc[i].slid 	   = wc[i].slid;
-		resp->wc[i].sl 		   = wc[i].sl;
-		resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
-		resp->wc[i].port_num 	   = wc[i].port_num;
+		data_ptr += sizeof(struct ib_uverbs_wc);
+		++resp.count;
 	}
 
-	if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+	if (copy_to_user(header_ptr, &resp, sizeof resp)) {
 		ret = -EFAULT;
+		goto out_put;
+	}
 
-out:
-	kfree(resp);
+	ret = in_len;
 
-out_wc:
-	kfree(wc);
-	return ret ? ret : in_len;
+out_put:
+	put_cq_read(cq);
+	return ret;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
--- linux-ec2-2.6.32.orig/drivers/infiniband/core/cm.c
+++ linux-ec2-2.6.32/drivers/infiniband/core/cm.c
@@ -2986,6 +2986,7 @@
 		goto out; /* No match. */
 	}
 	atomic_inc(&cur_cm_id_priv->refcount);
+	atomic_inc(&cm_id_priv->refcount);
 	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
--- linux-ec2-2.6.32.orig/drivers/infiniband/core/cma.c
+++ linux-ec2-2.6.32/drivers/infiniband/core/cma.c
@@ -1138,6 +1138,11 @@
 	cm_id->context = conn_id;
 	cm_id->cm_handler = cma_ib_handler;
 
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (!ret) {
 		/*
@@ -1150,8 +1155,10 @@
 			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
 		mutex_unlock(&lock);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		goto out;
 	}
+	cma_deref_id(conn_id);
 
 	/* Destroy the CM ID by returning a non-zero value. */
 	conn_id->cm_id.ib = NULL;
@@ -1353,17 +1360,25 @@
 	event.param.conn.private_data_len = iw_event->private_data_len;
 	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
 	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret) {
 		/* User wants to destroy the CM ID */
 		conn_id->cm_id.iw = NULL;
 		cma_exch(conn_id, CMA_DESTROYING);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		rdma_destroy_id(&conn_id->id);
 		goto out;
 	}
 
 	mutex_unlock(&conn_id->handler_mutex);
+	cma_deref_id(conn_id);
 
 out:
 	if (dev)
--- linux-ec2-2.6.32.orig/drivers/parisc/led.c
+++ linux-ec2-2.6.32/drivers/parisc/led.c
@@ -182,16 +182,18 @@
 static int led_proc_write(struct file *file, const char *buf, 
 	unsigned long count, void *data)
 {
-	char *cur, lbuf[count + 1];
+	char *cur, lbuf[32];
 	int d;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	memset(lbuf, 0, count + 1);
+	if (count >= sizeof(lbuf))
+		count = sizeof(lbuf)-1;
 
 	if (copy_from_user(lbuf, buf, count))
 		return -EFAULT;
+	lbuf[count] = 0;
 
 	cur = lbuf;
 
--- linux-ec2-2.6.32.orig/drivers/md/dm.c
+++ linux-ec2-2.6.32/drivers/md/dm.c
@@ -614,8 +614,10 @@
 			if (!md->barrier_error && io_error != -EOPNOTSUPP)
 				md->barrier_error = io_error;
 			end_io_acct(io);
+			free_io(md, io);
 		} else {
 			end_io_acct(io);
+			free_io(md, io);
 
 			if (io_error != DM_ENDIO_REQUEUE) {
 				trace_block_bio_complete(md->queue, bio);
@@ -623,8 +625,6 @@
 				bio_endio(bio, io_error);
 			}
 		}
-
-		free_io(md, io);
 	}
 }
 
@@ -1487,10 +1487,15 @@
 	return BLKPREP_OK;
 }
 
-static void map_request(struct dm_target *ti, struct request *rq,
-			struct mapped_device *md)
+/*
+ * Returns:
+ * 0  : the request has been processed (not requeued)
+ * !0 : the request has been requeued
+ */
+static int map_request(struct dm_target *ti, struct request *rq,
+		       struct mapped_device *md)
 {
-	int r;
+	int r, requeued = 0;
 	struct request *clone = rq->special;
 	struct dm_rq_target_io *tio = clone->end_io_data;
 
@@ -1516,6 +1521,7 @@
 	case DM_MAPIO_REQUEUE:
 		/* The target wants to requeue the I/O */
 		dm_requeue_unmapped_request(clone);
+		requeued = 1;
 		break;
 	default:
 		if (r > 0) {
@@ -1527,6 +1533,8 @@
 		dm_kill_unmapped_request(clone, r);
 		break;
 	}
+
+	return requeued;
 }
 
 /*
@@ -1568,12 +1576,17 @@
 
 		blk_start_request(rq);
 		spin_unlock(q->queue_lock);
-		map_request(ti, rq, md);
+		if (map_request(ti, rq, md))
+			goto requeued;
+
 		spin_lock_irq(q->queue_lock);
 	}
 
 	goto out;
 
+requeued:
+	spin_lock_irq(q->queue_lock);
+
 plug_and_out:
 	if (!elv_queue_empty(q))
 		/* Some requests still remain, retry later */
@@ -1912,13 +1925,14 @@
 	wake_up(&md->eventq);
 }
 
+/*
+ * Protected by md->suspend_lock obtained by dm_swap_table().
+ */
 static void __set_size(struct mapped_device *md, sector_t size)
 {
 	set_capacity(md->disk, size);
 
-	mutex_lock(&md->bdev->bd_inode->i_mutex);
 	i_size_write(md->bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
-	mutex_unlock(&md->bdev->bd_inode->i_mutex);
 }
 
 static int __bind(struct mapped_device *md, struct dm_table *t,
@@ -2573,6 +2587,7 @@
 {
 	return md->disk;
 }
+EXPORT_SYMBOL_GPL(dm_disk);
 
 struct kobject *dm_kobject(struct mapped_device *md)
 {
--- linux-ec2-2.6.32.orig/drivers/md/raid10.c
+++ linux-ec2-2.6.32/drivers/md/raid10.c
@@ -493,7 +493,7 @@
  */
 static int read_balance(conf_t *conf, r10bio_t *r10_bio)
 {
-	const unsigned long this_sector = r10_bio->sector;
+	const sector_t this_sector = r10_bio->sector;
 	int disk, slot, nslot;
 	const int sectors = r10_bio->sectors;
 	sector_t new_distance, current_distance;
@@ -824,11 +824,29 @@
 		 */
 		bp = bio_split(bio,
 			       chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
+
+		/* Each of these 'make_request' calls will call 'wait_barrier'.
+		 * If the first succeeds but the second blocks due to the resync
+		 * thread raising the barrier, we will deadlock because the
+		 * IO to the underlying device will be queued in generic_make_request
+		 * and will never complete, so will never reduce nr_pending.
+		 * So increment nr_waiting here so no new raise_barriers will
+		 * succeed, and so the second wait_barrier cannot block.
+		 */
+		spin_lock_irq(&conf->resync_lock);
+		conf->nr_waiting++;
+		spin_unlock_irq(&conf->resync_lock);
+
 		if (make_request(q, &bp->bio1))
 			generic_make_request(&bp->bio1);
 		if (make_request(q, &bp->bio2))
 			generic_make_request(&bp->bio2);
 
+		spin_lock_irq(&conf->resync_lock);
+		conf->nr_waiting--;
+		wake_up(&conf->wait_barrier);
+		spin_unlock_irq(&conf->resync_lock);
+
 		bio_pair_release(bp);
 		return 0;
 	bad_map:
@@ -1155,13 +1173,17 @@
 
 			disk_stack_limits(mddev->gendisk, rdev->bdev,
 					  rdev->data_offset << 9);
-			/* as we don't honour merge_bvec_fn, we must never risk
-			 * violating it, so limit ->max_sector to one PAGE, as
-			 * a one page request is never in violation.
+			/* as we don't honour merge_bvec_fn, we must
+			 * never risk violating it, so limit
+			 * ->max_phys_segments to one lying with a single
+			 * page, as a one page request is never in
+			 * violation.
 			 */
-			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-			    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
-				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
+			if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
+				blk_queue_max_phys_segments(mddev->queue, 1);
+				blk_queue_segment_boundary(mddev->queue,
+							   PAGE_CACHE_SIZE - 1);
+			}
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
@@ -2155,12 +2177,14 @@
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
 				  rdev->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
-		 * violating it, so limit ->max_sector to one PAGE, as
-		 * a one page request is never in violation.
+		 * violating it, so limit max_phys_segments to 1 lying
+		 * within a single page.
 		 */
-		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
-			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
+			blk_queue_max_phys_segments(mddev->queue, 1);
+			blk_queue_segment_boundary(mddev->queue,
+						   PAGE_CACHE_SIZE - 1);
+		}
 
 		disk->head_position = 0;
 	}
--- linux-ec2-2.6.32.orig/drivers/md/linear.c
+++ linux-ec2-2.6.32/drivers/md/linear.c
@@ -172,12 +172,14 @@
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
 				  rdev->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
-		 * violating it, so limit ->max_sector to one PAGE, as
-		 * a one page request is never in violation.
+		 * violating it, so limit max_phys_segments to 1 lying within
+		 * a single page.
 		 */
-		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
-			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
+			blk_queue_max_phys_segments(mddev->queue, 1);
+			blk_queue_segment_boundary(mddev->queue,
+						   PAGE_CACHE_SIZE - 1);
+		}
 
 		conf->array_sectors += rdev->sectors;
 		cnt++;
--- linux-ec2-2.6.32.orig/drivers/md/dm-snap.c
+++ linux-ec2-2.6.32/drivers/md/dm-snap.c
@@ -553,6 +553,8 @@
 	hash_size = min(origin_dev_size, cow_dev_size) >> s->store->chunk_shift;
 	hash_size = min(hash_size, max_buckets);
 
+	if (hash_size < 64)
+		hash_size = 64;
 	hash_size = rounddown_pow_of_two(hash_size);
 	if (init_exception_table(&s->complete, hash_size,
 				 DM_CHUNK_CONSECUTIVE_BITS))
@@ -1152,10 +1154,11 @@
 	unsigned sz = 0;
 	struct dm_snapshot *snap = ti->private;
 
-	down_write(&snap->lock);
-
 	switch (type) {
 	case STATUSTYPE_INFO:
+
+		down_write(&snap->lock);
+
 		if (!snap->valid)
 			DMEMIT("Invalid");
 		else {
@@ -1171,6 +1174,9 @@
 			else
 				DMEMIT("Unknown");
 		}
+
+		up_write(&snap->lock);
+
 		break;
 
 	case STATUSTYPE_TABLE:
@@ -1185,8 +1191,6 @@
 		break;
 	}
 
-	up_write(&snap->lock);
-
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/md/bitmap.h
+++ linux-ec2-2.6.32/drivers/md/bitmap.h
@@ -254,6 +254,9 @@
 	wait_queue_head_t write_wait;
 	wait_queue_head_t overflow_wait;
 
+#ifndef __GENKSYMS__
+	wait_queue_head_t behind_wait;
+#endif
 };
 
 /* the bitmap API */
@@ -282,7 +285,7 @@
 void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
 
 void bitmap_unplug(struct bitmap *bitmap);
-void bitmap_daemon_work(struct bitmap *bitmap);
+void bitmap_daemon_work(mddev_t *mddev);
 #endif
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/md/dm-log-userspace-transfer.c
+++ linux-ec2-2.6.32/drivers/md/dm-log-userspace-transfer.c
@@ -172,11 +172,15 @@
 {
 	int r = 0;
 	size_t dummy = 0;
-	int overhead_size =
-		sizeof(struct dm_ulog_request *) + sizeof(struct cn_msg);
+	int overhead_size = sizeof(struct dm_ulog_request) + sizeof(struct cn_msg);
 	struct dm_ulog_request *tfr = prealloced_ulog_tfr;
 	struct receiving_pkg pkg;
 
+	/*
+	 * Given the space needed to hold the 'struct cn_msg' and
+	 * 'struct dm_ulog_request' - do we have enough payload
+	 * space remaining?
+	 */
 	if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) {
 		DMINFO("Size of tfr exceeds preallocated size");
 		return -EINVAL;
@@ -191,7 +195,7 @@
 	 */
 	mutex_lock(&dm_ulog_lock);
 
-	memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size);
+	memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - sizeof(struct cn_msg));
 	memcpy(tfr->uuid, uuid, DM_UUID_LEN);
 	tfr->luid = luid;
 	tfr->seq = dm_ulog_seq++;
--- linux-ec2-2.6.32.orig/drivers/md/bitmap.c
+++ linux-ec2-2.6.32/drivers/md/bitmap.c
@@ -1078,23 +1078,31 @@
  *			out to disk
  */
 
-void bitmap_daemon_work(struct bitmap *bitmap)
+void bitmap_daemon_work(mddev_t *mddev)
 {
+	struct bitmap *bitmap;
 	unsigned long j;
 	unsigned long flags;
 	struct page *page = NULL, *lastpage = NULL;
 	int blocks;
 	void *paddr;
 
-	if (bitmap == NULL)
+	/* Use a mutex to guard daemon_work against
+	 * bitmap_destroy.
+	 */
+	mutex_lock(&mddev->bitmap_mutex);
+	bitmap = mddev->bitmap;
+	if (bitmap == NULL) {
+		mutex_unlock(&mddev->bitmap_mutex);
 		return;
+	}
 	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
 		goto done;
 
 	bitmap->daemon_lastrun = jiffies;
 	if (bitmap->allclean) {
 		bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
-		return;
+		goto done;
 	}
 	bitmap->allclean = 1;
 
@@ -1203,6 +1211,7 @@
  done:
 	if (bitmap->allclean == 0)
 		bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+	mutex_unlock(&mddev->bitmap_mutex);
 }
 
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1308,7 +1317,8 @@
 {
 	if (!bitmap) return;
 	if (behind) {
-		atomic_dec(&bitmap->behind_writes);
+		if (atomic_dec_and_test(&bitmap->behind_writes))
+			wake_up(&bitmap->behind_wait);
 		PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
 		  atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
 	}
@@ -1541,9 +1551,9 @@
 	 */
 	sleep = bitmap->daemon_sleep;
 	bitmap->daemon_sleep = 0;
-	bitmap_daemon_work(bitmap);
-	bitmap_daemon_work(bitmap);
-	bitmap_daemon_work(bitmap);
+	bitmap_daemon_work(mddev);
+	bitmap_daemon_work(mddev);
+	bitmap_daemon_work(mddev);
 	bitmap->daemon_sleep = sleep;
 	bitmap_update_sb(bitmap);
 }
@@ -1574,6 +1584,7 @@
 	kfree(bp);
 	kfree(bitmap);
 }
+
 void bitmap_destroy(mddev_t *mddev)
 {
 	struct bitmap *bitmap = mddev->bitmap;
@@ -1581,7 +1592,9 @@
 	if (!bitmap) /* there was no bitmap */
 		return;
 
+	mutex_lock(&mddev->bitmap_mutex);
 	mddev->bitmap = NULL; /* disconnect from the md device */
+	mutex_unlock(&mddev->bitmap_mutex);
 	if (mddev->thread)
 		mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
 
@@ -1617,6 +1630,7 @@
 	atomic_set(&bitmap->pending_writes, 0);
 	init_waitqueue_head(&bitmap->write_wait);
 	init_waitqueue_head(&bitmap->overflow_wait);
+	init_waitqueue_head(&bitmap->behind_wait);
 
 	bitmap->mddev = mddev;
 
--- linux-ec2-2.6.32.orig/drivers/md/dm-exception-store.h
+++ linux-ec2-2.6.32/drivers/md/dm-exception-store.h
@@ -162,7 +162,7 @@
 static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
 				      sector_t sector)
 {
-	return (sector & ~store->chunk_mask) >> store->chunk_shift;
+	return sector >> store->chunk_shift;
 }
 
 int dm_exception_store_type_register(struct dm_exception_store_type *type);
--- linux-ec2-2.6.32.orig/drivers/md/dm-raid1.c
+++ linux-ec2-2.6.32/drivers/md/dm-raid1.c
@@ -659,7 +659,7 @@
 	/*
 	 * Dispatch io.
 	 */
-	if (unlikely(ms->log_failure)) {
+	if (unlikely(ms->log_failure) && errors_handled(ms)) {
 		spin_lock_irq(&ms->lock);
 		bio_list_merge(&ms->failures, &sync);
 		spin_unlock_irq(&ms->lock);
--- linux-ec2-2.6.32.orig/drivers/md/dm-table.c
+++ linux-ec2-2.6.32/drivers/md/dm-table.c
@@ -499,16 +499,15 @@
 		return 0;
 	}
 
-	if (blk_stack_limits(limits, &q->limits, start << 9) < 0)
-		DMWARN("%s: target device %s is misaligned: "
+	if (bdev_stack_limits(limits, bdev, start) < 0)
+		DMWARN("%s: adding target device %s caused an alignment inconsistency: "
 		       "physical_block_size=%u, logical_block_size=%u, "
 		       "alignment_offset=%u, start=%llu",
 		       dm_device_name(ti->table->md), bdevname(bdev, b),
 		       q->limits.physical_block_size,
 		       q->limits.logical_block_size,
 		       q->limits.alignment_offset,
-		       (unsigned long long) start << 9);
-
+		       (unsigned long long) start << SECTOR_SHIFT);
 
 	/*
 	 * Check if merge fn is supported.
@@ -1025,9 +1024,9 @@
 		 * for the table.
 		 */
 		if (blk_stack_limits(limits, &ti_limits, 0) < 0)
-			DMWARN("%s: target device "
+			DMWARN("%s: adding target device "
 			       "(start sect %llu len %llu) "
-			       "is misaligned",
+			       "caused an alignment inconsistency",
 			       dm_device_name(table->md),
 			       (unsigned long long) ti->begin,
 			       (unsigned long long) ti->len);
@@ -1079,24 +1078,10 @@
 			       struct queue_limits *limits)
 {
 	/*
-	 * Each target device in the table has a data area that should normally
-	 * be aligned such that the DM device's alignment_offset is 0.
-	 * FIXME: Propagate alignment_offsets up the stack and warn of
-	 *	  sub-optimal or inconsistent settings.
-	 */
-	limits->alignment_offset = 0;
-	limits->misaligned = 0;
-
-	/*
 	 * Copy table's limits to the DM device's request_queue
 	 */
 	q->limits = *limits;
 
-	if (limits->no_cluster)
-		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
-	else
-		queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-
 	dm_table_set_integrity(t);
 
 	/*
--- linux-ec2-2.6.32.orig/drivers/md/raid5.c
+++ linux-ec2-2.6.32/drivers/md/raid5.c
@@ -1526,7 +1526,7 @@
 
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 		atomic_inc(&rdev->read_errors);
-		if (conf->mddev->degraded)
+		if (conf->mddev->degraded >= conf->max_degraded)
 			printk_rl(KERN_WARNING
 				  "raid5:%s: read error not correctable "
 				  "(sector %llu on %s).\n",
@@ -1649,8 +1649,8 @@
 				     int previous, int *dd_idx,
 				     struct stripe_head *sh)
 {
-	long stripe;
-	unsigned long chunk_number;
+	sector_t stripe, stripe2;
+	sector_t chunk_number;
 	unsigned int chunk_offset;
 	int pd_idx, qd_idx;
 	int ddf_layout = 0;
@@ -1670,18 +1670,13 @@
 	 */
 	chunk_offset = sector_div(r_sector, sectors_per_chunk);
 	chunk_number = r_sector;
-	BUG_ON(r_sector != chunk_number);
 
 	/*
 	 * Compute the stripe number
 	 */
-	stripe = chunk_number / data_disks;
-
-	/*
-	 * Compute the data disk and parity disk indexes inside the stripe
-	 */
-	*dd_idx = chunk_number % data_disks;
-
+	stripe = chunk_number;
+	*dd_idx = sector_div(stripe, data_disks);
+	stripe2 = stripe;
 	/*
 	 * Select the parity disk based on the user selected algorithm.
 	 */
@@ -1693,21 +1688,21 @@
 	case 5:
 		switch (algorithm) {
 		case ALGORITHM_LEFT_ASYMMETRIC:
-			pd_idx = data_disks - stripe % raid_disks;
+			pd_idx = data_disks - sector_div(stripe2, raid_disks);
 			if (*dd_idx >= pd_idx)
 				(*dd_idx)++;
 			break;
 		case ALGORITHM_RIGHT_ASYMMETRIC:
-			pd_idx = stripe % raid_disks;
+			pd_idx = sector_div(stripe2, raid_disks);
 			if (*dd_idx >= pd_idx)
 				(*dd_idx)++;
 			break;
 		case ALGORITHM_LEFT_SYMMETRIC:
-			pd_idx = data_disks - stripe % raid_disks;
+			pd_idx = data_disks - sector_div(stripe2, raid_disks);
 			*dd_idx = (pd_idx + 1 + *dd_idx) % raid_disks;
 			break;
 		case ALGORITHM_RIGHT_SYMMETRIC:
-			pd_idx = stripe % raid_disks;
+			pd_idx = sector_div(stripe2, raid_disks);
 			*dd_idx = (pd_idx + 1 + *dd_idx) % raid_disks;
 			break;
 		case ALGORITHM_PARITY_0:
@@ -1727,7 +1722,7 @@
 
 		switch (algorithm) {
 		case ALGORITHM_LEFT_ASYMMETRIC:
-			pd_idx = raid_disks - 1 - (stripe % raid_disks);
+			pd_idx = raid_disks - 1 - sector_div(stripe2, raid_disks);
 			qd_idx = pd_idx + 1;
 			if (pd_idx == raid_disks-1) {
 				(*dd_idx)++;	/* Q D D D P */
@@ -1736,7 +1731,7 @@
 				(*dd_idx) += 2; /* D D P Q D */
 			break;
 		case ALGORITHM_RIGHT_ASYMMETRIC:
-			pd_idx = stripe % raid_disks;
+			pd_idx = sector_div(stripe2, raid_disks);
 			qd_idx = pd_idx + 1;
 			if (pd_idx == raid_disks-1) {
 				(*dd_idx)++;	/* Q D D D P */
@@ -1745,12 +1740,12 @@
 				(*dd_idx) += 2; /* D D P Q D */
 			break;
 		case ALGORITHM_LEFT_SYMMETRIC:
-			pd_idx = raid_disks - 1 - (stripe % raid_disks);
+			pd_idx = raid_disks - 1 - sector_div(stripe2, raid_disks);
 			qd_idx = (pd_idx + 1) % raid_disks;
 			*dd_idx = (pd_idx + 2 + *dd_idx) % raid_disks;
 			break;
 		case ALGORITHM_RIGHT_SYMMETRIC:
-			pd_idx = stripe % raid_disks;
+			pd_idx = sector_div(stripe2, raid_disks);
 			qd_idx = (pd_idx + 1) % raid_disks;
 			*dd_idx = (pd_idx + 2 + *dd_idx) % raid_disks;
 			break;
@@ -1769,7 +1764,7 @@
 			/* Exactly the same as RIGHT_ASYMMETRIC, but or
 			 * of blocks for computing Q is different.
 			 */
-			pd_idx = stripe % raid_disks;
+			pd_idx = sector_div(stripe2, raid_disks);
 			qd_idx = pd_idx + 1;
 			if (pd_idx == raid_disks-1) {
 				(*dd_idx)++;	/* Q D D D P */
@@ -1784,7 +1779,8 @@
 			 * D D D P Q  rather than
 			 * Q D D D P
 			 */
-			pd_idx = raid_disks - 1 - ((stripe + 1) % raid_disks);
+			stripe2 += 1;
+			pd_idx = raid_disks - 1 - sector_div(stripe2, raid_disks);
 			qd_idx = pd_idx + 1;
 			if (pd_idx == raid_disks-1) {
 				(*dd_idx)++;	/* Q D D D P */
@@ -1796,7 +1792,7 @@
 
 		case ALGORITHM_ROTATING_N_CONTINUE:
 			/* Same as left_symmetric but Q is before P */
-			pd_idx = raid_disks - 1 - (stripe % raid_disks);
+			pd_idx = raid_disks - 1 - sector_div(stripe2, raid_disks);
 			qd_idx = (pd_idx + raid_disks - 1) % raid_disks;
 			*dd_idx = (pd_idx + 1 + *dd_idx) % raid_disks;
 			ddf_layout = 1;
@@ -1804,27 +1800,27 @@
 
 		case ALGORITHM_LEFT_ASYMMETRIC_6:
 			/* RAID5 left_asymmetric, with Q on last device */
-			pd_idx = data_disks - stripe % (raid_disks-1);
+			pd_idx = data_disks - sector_div(stripe2, raid_disks-1);
 			if (*dd_idx >= pd_idx)
 				(*dd_idx)++;
 			qd_idx = raid_disks - 1;
 			break;
 
 		case ALGORITHM_RIGHT_ASYMMETRIC_6:
-			pd_idx = stripe % (raid_disks-1);
+			pd_idx = sector_div(stripe2, raid_disks-1);
 			if (*dd_idx >= pd_idx)
 				(*dd_idx)++;
 			qd_idx = raid_disks - 1;
 			break;
 
 		case ALGORITHM_LEFT_SYMMETRIC_6:
-			pd_idx = data_disks - stripe % (raid_disks-1);
+			pd_idx = data_disks - sector_div(stripe2, raid_disks-1);
 			*dd_idx = (pd_idx + 1 + *dd_idx) % (raid_disks-1);
 			qd_idx = raid_disks - 1;
 			break;
 
 		case ALGORITHM_RIGHT_SYMMETRIC_6:
-			pd_idx = stripe % (raid_disks-1);
+			pd_idx = sector_div(stripe2, raid_disks-1);
 			*dd_idx = (pd_idx + 1 + *dd_idx) % (raid_disks-1);
 			qd_idx = raid_disks - 1;
 			break;
@@ -1869,14 +1865,14 @@
 				 : conf->algorithm;
 	sector_t stripe;
 	int chunk_offset;
-	int chunk_number, dummy1, dd_idx = i;
+	sector_t chunk_number;
+	int dummy1, dd_idx = i;
 	sector_t r_sector;
 	struct stripe_head sh2;
 
 
 	chunk_offset = sector_div(new_sector, sectors_per_chunk);
 	stripe = new_sector;
-	BUG_ON(new_sector != stripe);
 
 	if (i == sh->pd_idx)
 		return 0;
@@ -1969,7 +1965,7 @@
 	}
 
 	chunk_number = stripe * data_disks + i;
-	r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
+	r_sector = chunk_number * sectors_per_chunk + chunk_offset;
 
 	check = raid5_compute_sector(conf, r_sector,
 				     previous, &dummy1, &sh2);
@@ -5432,11 +5428,11 @@
 		    !test_bit(Faulty, &rdev->flags)) {
 			if (raid5_add_disk(mddev, rdev) == 0) {
 				char nm[20];
-				if (rdev->raid_disk >= conf->previous_raid_disks)
+				if (rdev->raid_disk >= conf->previous_raid_disks) {
 					set_bit(In_sync, &rdev->flags);
-				else
+					added_devices++;
+				} else
 					rdev->recovery_offset = 0;
-				added_devices++;
 				sprintf(nm, "rd%d", rdev->raid_disk);
 				if (sysfs_create_link(&mddev->kobj,
 						      &rdev->kobj, nm))
@@ -5448,9 +5444,12 @@
 				break;
 		}
 
+	/* When a reshape changes the number of devices, ->degraded
+	 * is measured against the large of the pre and post number of
+	 * devices.*/
 	if (mddev->delta_disks > 0) {
 		spin_lock_irqsave(&conf->device_lock, flags);
-		mddev->degraded = (conf->raid_disks - conf->previous_raid_disks)
+		mddev->degraded += (conf->raid_disks - conf->previous_raid_disks)
 			- added_devices;
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
--- linux-ec2-2.6.32.orig/drivers/md/md.h
+++ linux-ec2-2.6.32/drivers/md/md.h
@@ -289,6 +289,7 @@
 								* hot-adding a bitmap.  It should
 								* eventually be settable by sysfs.
 								*/
+	struct mutex			bitmap_mutex;
 
 	struct list_head		all_mddevs;
 };
--- linux-ec2-2.6.32.orig/drivers/md/dm-crypt.c
+++ linux-ec2-2.6.32/drivers/md/dm-crypt.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
  * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
- * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the GPL.
  */
@@ -71,10 +71,21 @@
 	int (*ctr)(struct crypt_config *cc, struct dm_target *ti,
 		   const char *opts);
 	void (*dtr)(struct crypt_config *cc);
-	const char *(*status)(struct crypt_config *cc);
+	int (*init)(struct crypt_config *cc);
+	int (*wipe)(struct crypt_config *cc);
 	int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
 };
 
+struct iv_essiv_private {
+	struct crypto_cipher *tfm;
+	struct crypto_hash *hash_tfm;
+	u8 *salt;
+};
+
+struct iv_benbi_private {
+	int shift;
+};
+
 /*
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
@@ -102,8 +113,8 @@
 	struct crypt_iv_operations *iv_gen_ops;
 	char *iv_mode;
 	union {
-		struct crypto_cipher *essiv_tfm;
-		int benbi_shift;
+		struct iv_essiv_private essiv;
+		struct iv_benbi_private benbi;
 	} iv_gen_private;
 	sector_t iv_offset;
 	unsigned int iv_size;
@@ -169,88 +180,114 @@
 	return 0;
 }
 
-static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
-			      const char *opts)
+/* Initialise ESSIV - compute salt but no local memory allocations */
+static int crypt_iv_essiv_init(struct crypt_config *cc)
 {
-	struct crypto_cipher *essiv_tfm;
-	struct crypto_hash *hash_tfm;
+	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
 	struct hash_desc desc;
 	struct scatterlist sg;
-	unsigned int saltsize;
-	u8 *salt;
 	int err;
 
-	if (opts == NULL) {
+	sg_init_one(&sg, cc->key, cc->key_size);
+	desc.tfm = essiv->hash_tfm;
+	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt);
+	if (err)
+		return err;
+
+	return crypto_cipher_setkey(essiv->tfm, essiv->salt,
+				    crypto_hash_digestsize(essiv->hash_tfm));
+}
+
+/* Wipe salt and reset key derived from volume key */
+static int crypt_iv_essiv_wipe(struct crypt_config *cc)
+{
+	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
+	unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
+
+	memset(essiv->salt, 0, salt_size);
+
+	return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size);
+}
+
+static void crypt_iv_essiv_dtr(struct crypt_config *cc)
+{
+	struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
+
+	crypto_free_cipher(essiv->tfm);
+	essiv->tfm = NULL;
+
+	crypto_free_hash(essiv->hash_tfm);
+	essiv->hash_tfm = NULL;
+
+	kzfree(essiv->salt);
+	essiv->salt = NULL;
+}
+
+static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
+			      const char *opts)
+{
+	struct crypto_cipher *essiv_tfm = NULL;
+	struct crypto_hash *hash_tfm = NULL;
+	u8 *salt = NULL;
+	int err;
+
+	if (!opts) {
 		ti->error = "Digest algorithm missing for ESSIV mode";
 		return -EINVAL;
 	}
 
-	/* Hash the cipher key with the given hash algorithm */
+	/* Allocate hash algorithm */
 	hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(hash_tfm)) {
 		ti->error = "Error initializing ESSIV hash";
-		return PTR_ERR(hash_tfm);
+		err = PTR_ERR(hash_tfm);
+		goto bad;
 	}
 
-	saltsize = crypto_hash_digestsize(hash_tfm);
-	salt = kmalloc(saltsize, GFP_KERNEL);
-	if (salt == NULL) {
+	salt = kzalloc(crypto_hash_digestsize(hash_tfm), GFP_KERNEL);
+	if (!salt) {
 		ti->error = "Error kmallocing salt storage in ESSIV";
-		crypto_free_hash(hash_tfm);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto bad;
 	}
 
-	sg_init_one(&sg, cc->key, cc->key_size);
-	desc.tfm = hash_tfm;
-	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-	err = crypto_hash_digest(&desc, &sg, cc->key_size, salt);
-	crypto_free_hash(hash_tfm);
-
-	if (err) {
-		ti->error = "Error calculating hash in ESSIV";
-		kfree(salt);
-		return err;
-	}
-
-	/* Setup the essiv_tfm with the given salt */
+	/* Allocate essiv_tfm */
 	essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(essiv_tfm)) {
 		ti->error = "Error allocating crypto tfm for ESSIV";
-		kfree(salt);
-		return PTR_ERR(essiv_tfm);
+		err = PTR_ERR(essiv_tfm);
+		goto bad;
 	}
 	if (crypto_cipher_blocksize(essiv_tfm) !=
 	    crypto_ablkcipher_ivsize(cc->tfm)) {
 		ti->error = "Block size of ESSIV cipher does "
 			    "not match IV size of block cipher";
-		crypto_free_cipher(essiv_tfm);
-		kfree(salt);
-		return -EINVAL;
-	}
-	err = crypto_cipher_setkey(essiv_tfm, salt, saltsize);
-	if (err) {
-		ti->error = "Failed to set key for ESSIV cipher";
-		crypto_free_cipher(essiv_tfm);
-		kfree(salt);
-		return err;
+		err = -EINVAL;
+		goto bad;
 	}
-	kfree(salt);
 
-	cc->iv_gen_private.essiv_tfm = essiv_tfm;
+	cc->iv_gen_private.essiv.salt = salt;
+	cc->iv_gen_private.essiv.tfm = essiv_tfm;
+	cc->iv_gen_private.essiv.hash_tfm = hash_tfm;
+
 	return 0;
-}
 
-static void crypt_iv_essiv_dtr(struct crypt_config *cc)
-{
-	crypto_free_cipher(cc->iv_gen_private.essiv_tfm);
-	cc->iv_gen_private.essiv_tfm = NULL;
+bad:
+	if (essiv_tfm && !IS_ERR(essiv_tfm))
+		crypto_free_cipher(essiv_tfm);
+	if (hash_tfm && !IS_ERR(hash_tfm))
+		crypto_free_hash(hash_tfm);
+	kfree(salt);
+	return err;
 }
 
 static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
 {
 	memset(iv, 0, cc->iv_size);
 	*(u64 *)iv = cpu_to_le64(sector);
-	crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv);
+	crypto_cipher_encrypt_one(cc->iv_gen_private.essiv.tfm, iv, iv);
 	return 0;
 }
 
@@ -273,7 +310,7 @@
 		return -EINVAL;
 	}
 
-	cc->iv_gen_private.benbi_shift = 9 - log;
+	cc->iv_gen_private.benbi.shift = 9 - log;
 
 	return 0;
 }
@@ -288,7 +325,7 @@
 
 	memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */
 
-	val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1);
+	val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi.shift) + 1);
 	put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64)));
 
 	return 0;
@@ -308,6 +345,8 @@
 static struct crypt_iv_operations crypt_iv_essiv_ops = {
 	.ctr       = crypt_iv_essiv_ctr,
 	.dtr       = crypt_iv_essiv_dtr,
+	.init      = crypt_iv_essiv_init,
+	.wipe      = crypt_iv_essiv_wipe,
 	.generator = crypt_iv_essiv_gen
 };
 
@@ -1039,6 +1078,12 @@
 	    cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0)
 		goto bad_ivmode;
 
+	if (cc->iv_gen_ops && cc->iv_gen_ops->init &&
+	    cc->iv_gen_ops->init(cc) < 0) {
+		ti->error = "Error initialising IV";
+		goto bad_slab_pool;
+	}
+
 	cc->iv_size = crypto_ablkcipher_ivsize(tfm);
 	if (cc->iv_size)
 		/* at least a 64 bit sector number should fit in our buffer */
@@ -1278,6 +1323,7 @@
 static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
 {
 	struct crypt_config *cc = ti->private;
+	int ret = -EINVAL;
 
 	if (argc < 2)
 		goto error;
@@ -1287,10 +1333,22 @@
 			DMWARN("not suspended during key manipulation.");
 			return -EINVAL;
 		}
-		if (argc == 3 && !strnicmp(argv[1], MESG_STR("set")))
-			return crypt_set_key(cc, argv[2]);
-		if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe")))
+		if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
+			ret = crypt_set_key(cc, argv[2]);
+			if (ret)
+				return ret;
+			if (cc->iv_gen_ops && cc->iv_gen_ops->init)
+				ret = cc->iv_gen_ops->init(cc);
+			return ret;
+		}
+		if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
+			if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
+				ret = cc->iv_gen_ops->wipe(cc);
+				if (ret)
+					return ret;
+			}
 			return crypt_wipe_key(cc);
+		}
 	}
 
 error:
--- linux-ec2-2.6.32.orig/drivers/md/dm-exception-store.c
+++ linux-ec2-2.6.32/drivers/md/dm-exception-store.c
@@ -216,7 +216,8 @@
 		type = get_type("N");
 	else {
 		ti->error = "Persistent flag is not P or N";
-		return -EINVAL;
+		r = -EINVAL;
+		goto bad_type;
 	}
 
 	if (!type) {
--- linux-ec2-2.6.32.orig/drivers/md/dm-region-hash.c
+++ linux-ec2-2.6.32/drivers/md/dm-region-hash.c
@@ -643,10 +643,9 @@
 	spin_lock_irq(&rh->region_lock);
 	if (success)
 		list_add(&reg->list, &reg->rh->recovered_regions);
-	else {
-		reg->state = DM_RH_NOSYNC;
+	else
 		list_add(&reg->list, &reg->rh->failed_recovered_regions);
-	}
+
 	spin_unlock_irq(&rh->region_lock);
 
 	rh->wakeup_workers(rh->context);
--- linux-ec2-2.6.32.orig/drivers/md/multipath.c
+++ linux-ec2-2.6.32/drivers/md/multipath.c
@@ -301,14 +301,16 @@
 					  rdev->data_offset << 9);
 
 		/* as we don't honour merge_bvec_fn, we must never risk
-		 * violating it, so limit ->max_sector to one PAGE, as
-		 * a one page request is never in violation.
+		 * violating it, so limit ->max_phys_segments to one, lying
+		 * within a single page.
 		 * (Note: it is very unlikely that a device with
 		 * merge_bvec_fn will be involved in multipath.)
 		 */
-			if (q->merge_bvec_fn &&
-			    queue_max_sectors(q) > (PAGE_SIZE>>9))
-				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
+			if (q->merge_bvec_fn) {
+				blk_queue_max_phys_segments(mddev->queue, 1);
+				blk_queue_segment_boundary(mddev->queue,
+							   PAGE_CACHE_SIZE - 1);
+			}
 
 			conf->working_disks++;
 			mddev->degraded--;
@@ -476,9 +478,11 @@
 		/* as we don't honour merge_bvec_fn, we must never risk
 		 * violating it, not that we ever expect a device with
 		 * a merge_bvec_fn to be involved in multipath */
-		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
-		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
-			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
+		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
+			blk_queue_max_phys_segments(mddev->queue, 1);
+			blk_queue_segment_boundary(mddev->queue,
+						   PAGE_CACHE_SIZE - 1);
+		}
 
 		if (!test_bit(Faulty, &rdev->flags))
 			conf->working_disks++;
--- linux-ec2-2.6.32.orig/drivers/md/dm-mpath.c
+++ linux-ec2-2.6.32/drivers/md/dm-mpath.c
@@ -33,7 +33,6 @@
 	unsigned fail_count;		/* Cumulative failure count */
 
 	struct dm_path path;
-	struct work_struct deactivate_path;
 	struct work_struct activate_path;
 };
 
@@ -113,7 +112,6 @@
 static void process_queued_ios(struct work_struct *work);
 static void trigger_event(struct work_struct *work);
 static void activate_path(struct work_struct *work);
-static void deactivate_path(struct work_struct *work);
 
 
 /*-----------------------------------------------
@@ -126,7 +124,6 @@
 
 	if (pgpath) {
 		pgpath->is_active = 1;
-		INIT_WORK(&pgpath->deactivate_path, deactivate_path);
 		INIT_WORK(&pgpath->activate_path, activate_path);
 	}
 
@@ -138,14 +135,6 @@
 	kfree(pgpath);
 }
 
-static void deactivate_path(struct work_struct *work)
-{
-	struct pgpath *pgpath =
-		container_of(work, struct pgpath, deactivate_path);
-
-	blk_abort_queue(pgpath->path.dev->bdev->bd_disk->queue);
-}
-
 static struct priority_group *alloc_priority_group(void)
 {
 	struct priority_group *pg;
@@ -691,6 +680,7 @@
 
 		if (as->argc < nr_params) {
 			ti->error = "not enough path parameters";
+			r = -EINVAL;
 			goto bad;
 		}
 
@@ -948,7 +938,6 @@
 		      pgpath->path.dev->name, m->nr_valid_paths);
 
 	schedule_work(&m->trigger_event);
-	queue_work(kmultipathd, &pgpath->deactivate_path);
 
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
--- linux-ec2-2.6.32.orig/drivers/md/raid0.c
+++ linux-ec2-2.6.32/drivers/md/raid0.c
@@ -176,14 +176,15 @@
 		disk_stack_limits(mddev->gendisk, rdev1->bdev,
 				  rdev1->data_offset << 9);
 		/* as we don't honour merge_bvec_fn, we must never risk
-		 * violating it, so limit ->max_sector to one PAGE, as
-		 * a one page request is never in violation.
+		 * violating it, so limit ->max_phys_segments to 1, lying within
+		 * a single page.
 		 */
 
-		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
-		    queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
-			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
-
+		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn) {
+			blk_queue_max_phys_segments(mddev->queue, 1);
+			blk_queue_segment_boundary(mddev->queue,
+						   PAGE_CACHE_SIZE - 1);
+		}
 		if (!smallest || (rdev1->sectors < smallest->sectors))
 			smallest = rdev1;
 		cnt++;
--- linux-ec2-2.6.32.orig/drivers/md/dm-uevent.c
+++ linux-ec2-2.6.32/drivers/md/dm-uevent.c
@@ -139,14 +139,13 @@
 		list_del_init(&event->elist);
 
 		/*
-		 * Need to call dm_copy_name_and_uuid from here for now.
-		 * Context of previous var adds and locking used for
-		 * hash_cell not compatable.
+		 * When a device is being removed this copy fails and we
+		 * discard these unsent events.
 		 */
 		if (dm_copy_name_and_uuid(event->md, event->name,
 					  event->uuid)) {
-			DMERR("%s: dm_copy_name_and_uuid() failed",
-			      __func__);
+			DMINFO("%s: skipping sending uevent for lost device",
+			       __func__);
 			goto uevent_free;
 		}
 
--- linux-ec2-2.6.32.orig/drivers/md/raid1.c
+++ linux-ec2-2.6.32/drivers/md/raid1.c
@@ -417,7 +417,7 @@
  */
 static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
-	const unsigned long this_sector = r1_bio->sector;
+	const sector_t this_sector = r1_bio->sector;
 	int new_disk = conf->last_used, disk = new_disk;
 	int wonly_disk = -1;
 	const int sectors = r1_bio->sectors;
@@ -433,7 +433,7 @@
  retry:
 	if (conf->mddev->recovery_cp < MaxSector &&
 	    (this_sector + sectors >= conf->next_resync)) {
-		/* Choose the first operation device, for consistancy */
+		/* Choose the first operational device, for consistancy */
 		new_disk = 0;
 
 		for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
@@ -845,6 +845,15 @@
 		}
 		mirror = conf->mirrors + rdisk;
 
+		if (test_bit(WriteMostly, &mirror->rdev->flags) &&
+		    bitmap) {
+			/* Reading from a write-mostly device must
+			 * take care not to over-take any writes
+			 * that are 'behind'
+			 */
+			wait_event(bitmap->behind_wait,
+				   atomic_read(&bitmap->behind_writes) == 0);
+		}
 		r1_bio->read_disk = rdisk;
 
 		read_bio = bio_clone(bio, GFP_NOIO);
@@ -891,9 +900,10 @@
 			if (test_bit(Faulty, &rdev->flags)) {
 				rdev_dec_pending(rdev, mddev);
 				r1_bio->bios[i] = NULL;
-			} else
+			} else {
 				r1_bio->bios[i] = bio;
-			targets++;
+				targets++;
+			}
 		} else
 			r1_bio->bios[i] = NULL;
 	}
@@ -921,9 +931,13 @@
 		set_bit(R1BIO_Degraded, &r1_bio->state);
 	}
 
-	/* do behind I/O ? */
+	/* do behind I/O ?
+	 * Not if there are too many, or cannot allocate memory,
+	 * or a reader on WriteMostly is waiting for behind writes
+	 * to flush */
 	if (bitmap &&
 	    atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind &&
+	    !waitqueue_active(&bitmap->behind_wait) &&
 	    (behind_pages = alloc_behind_pages(bio)) != NULL)
 		set_bit(R1BIO_BehindIO, &r1_bio->state);
 
@@ -1174,6 +1188,7 @@
 		 * is not possible.
 		 */
 		if (!test_bit(Faulty, &rdev->flags) &&
+		    !mddev->recovery_disabled &&
 		    mddev->degraded < conf->raid_disks) {
 			err = -EBUSY;
 			goto abort;
@@ -2104,15 +2119,13 @@
 {
 	conf_t *conf = mddev->private;
 	struct bitmap *bitmap = mddev->bitmap;
-	int behind_wait = 0;
 
 	/* wait for behind writes to complete */
-	while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
-		behind_wait++;
-		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ); /* wait a second */
+	if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+		printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop.\n", mdname(mddev));
 		/* need to kick something here to make sure I/O goes? */
+		wait_event(bitmap->behind_wait,
+			   atomic_read(&bitmap->behind_writes) == 0);
 	}
 
 	raise_barrier(conf);
--- linux-ec2-2.6.32.orig/drivers/md/md.c
+++ linux-ec2-2.6.32/drivers/md/md.c
@@ -282,7 +282,9 @@
 	if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
 		return;
 	if (!mddev->raid_disks && list_empty(&mddev->disks) &&
-	    !mddev->hold_active) {
+	    mddev->ctime == 0 && !mddev->hold_active) {
+		/* Array is not configured at all, and not held active,
+		 * so destroy it */
 		list_del(&mddev->all_mddevs);
 		if (mddev->gendisk) {
 			/* we did a probe so need to clean up.
@@ -303,6 +305,9 @@
 {
 	mddev_t *mddev, *new = NULL;
 
+	if (unit && MAJOR(unit) != MD_MAJOR)
+		unit &= ~((1<<MdpMinorShift)-1);
+
  retry:
 	spin_lock(&all_mddevs_lock);
 
@@ -367,6 +372,7 @@
 
 	mutex_init(&new->open_mutex);
 	mutex_init(&new->reconfig_mutex);
+	mutex_init(&new->bitmap_mutex);
 	INIT_LIST_HEAD(&new->disks);
 	INIT_LIST_HEAD(&new->all_mddevs);
 	init_timer(&new->safemode_timer);
@@ -1119,7 +1125,7 @@
 	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
 		       rdev->sb_page);
 	md_super_wait(rdev->mddev);
-	return num_sectors / 2; /* kB for sysfs */
+	return num_sectors;
 }
 
 
@@ -1482,7 +1488,7 @@
 	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
 		       rdev->sb_page);
 	md_super_wait(rdev->mddev);
-	return num_sectors / 2; /* kB for sysfs */
+	return num_sectors;
 }
 
 static struct super_type super_types[] = {
@@ -2008,12 +2014,18 @@
 		if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
 			/* .. if the array isn't clean, an 'even' event must also go
 			 * to spares. */
-			if ((mddev->events&1)==0)
+			if ((mddev->events&1)==0) {
 				nospares = 0;
+				sync_req = 2; /* force a second update to get the
+					       * even/odd in sync */
+			}
 		} else {
 			/* otherwise an 'odd' event must go to spares */
-			if ((mddev->events&1))
+			if ((mddev->events&1)) {
 				nospares = 0;
+				sync_req = 2; /* force a second update to get the
+					       * even/odd in sync */
+			}
 		}
 	}
 
@@ -3950,9 +3962,6 @@
 		goto abort;
 	mddev->queue->queuedata = mddev;
 
-	/* Can be unlocked because the queue is new: no concurrency */
-	queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
-
 	blk_queue_make_request(mddev->queue, md_make_request);
 
 	disk = alloc_disk(1 << shift);
@@ -4170,7 +4179,7 @@
 	mddev->barriers_work = 1;
 	mddev->ok_start_degraded = start_dirty_degraded;
 
-	if (start_readonly)
+	if (start_readonly && mddev->ro == 0)
 		mddev->ro = 2; /* read-only, but switch on first write */
 
 	err = mddev->pers->run(mddev);
@@ -4793,17 +4802,21 @@
 				PTR_ERR(rdev));
 			return PTR_ERR(rdev);
 		}
-		/* set save_raid_disk if appropriate */
+		/* set saved_raid_disk if appropriate */
 		if (!mddev->persistent) {
 			if (info->state & (1<<MD_DISK_SYNC)  &&
-			    info->raid_disk < mddev->raid_disks)
+			    info->raid_disk < mddev->raid_disks) {
 				rdev->raid_disk = info->raid_disk;
-			else
+				set_bit(In_sync, &rdev->flags);
+			} else
 				rdev->raid_disk = -1;
 		} else
 			super_types[mddev->major_version].
 				validate_super(mddev, rdev);
-		rdev->saved_raid_disk = rdev->raid_disk;
+		if (test_bit(In_sync, &rdev->flags))
+			rdev->saved_raid_disk = rdev->raid_disk;
+		else
+			rdev->saved_raid_disk = -1;
 
 		clear_bit(In_sync, &rdev->flags); /* just to be sure */
 		if (info->state & (1<<MD_DISK_WRITEMOSTLY))
@@ -5070,6 +5083,10 @@
 		mddev->minor_version = info->minor_version;
 		mddev->patch_version = info->patch_version;
 		mddev->persistent = !info->not_persistent;
+		/* ensure mddev_put doesn't delete this now that there
+		 * is some minimal configuration.
+		 */
+		mddev->ctime         = get_seconds();
 		return 0;
 	}
 	mddev->major_version = MD_MAJOR_VERSION;
@@ -5321,6 +5338,7 @@
 	int err = 0;
 	void __user *argp = (void __user *)arg;
 	mddev_t *mddev = NULL;
+	int ro;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -5456,6 +5474,34 @@
 			err = do_md_stop(mddev, 1, 1);
 			goto done_unlock;
 
+		case BLKROSET:
+			if (get_user(ro, (int __user *)(arg))) {
+				err = -EFAULT;
+				goto done_unlock;
+			}
+			err = -EINVAL;
+
+			/* if the bdev is going readonly the value of mddev->ro
+			 * does not matter, no writes are coming
+			 */
+			if (ro)
+				goto done_unlock;
+
+			/* are we are already prepared for writes? */
+			if (mddev->ro != 1)
+				goto done_unlock;
+
+			/* transitioning to readauto need only happen for
+			 * arrays that call md_write_start
+			 */
+			if (mddev->pers) {
+				err = restart_array(mddev);
+				if (err == 0) {
+					mddev->ro = 2;
+					set_disk_ro(mddev->gendisk, 0);
+				}
+			}
+			goto done_unlock;
 	}
 
 	/*
@@ -6629,7 +6675,7 @@
 
 
 	if (mddev->bitmap)
-		bitmap_daemon_work(mddev->bitmap);
+		bitmap_daemon_work(mddev);
 
 	if (mddev->ro)
 		return;
--- linux-ec2-2.6.32.orig/drivers/md/dm-ioctl.c
+++ linux-ec2-2.6.32/drivers/md/dm-ioctl.c
@@ -56,6 +56,11 @@
  */
 static DECLARE_RWSEM(_hash_lock);
 
+/*
+ * Protects use of mdptr to obtain hash cell name and uuid from mapped device.
+ */
+static DEFINE_MUTEX(dm_hash_cells_mutex);
+
 static void init_buckets(struct list_head *buckets)
 {
 	unsigned int i;
@@ -206,7 +211,9 @@
 		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
 	}
 	dm_get(md);
+	mutex_lock(&dm_hash_cells_mutex);
 	dm_set_mdptr(md, cell);
+	mutex_unlock(&dm_hash_cells_mutex);
 	up_write(&_hash_lock);
 
 	return 0;
@@ -224,7 +231,9 @@
 	/* remove from the dev hash */
 	list_del(&hc->uuid_list);
 	list_del(&hc->name_list);
+	mutex_lock(&dm_hash_cells_mutex);
 	dm_set_mdptr(hc->md, NULL);
+	mutex_unlock(&dm_hash_cells_mutex);
 
 	table = dm_get_table(hc->md);
 	if (table) {
@@ -240,40 +249,46 @@
 
 static void dm_hash_remove_all(int keep_open_devices)
 {
-	int i, dev_skipped, dev_removed;
+	int i, dev_skipped;
 	struct hash_cell *hc;
-	struct list_head *tmp, *n;
+	struct mapped_device *md;
+
+retry:
+	dev_skipped = 0;
 
 	down_write(&_hash_lock);
 
-retry:
-	dev_skipped = dev_removed = 0;
 	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_safe (tmp, n, _name_buckets + i) {
-			hc = list_entry(tmp, struct hash_cell, name_list);
+		list_for_each_entry(hc, _name_buckets + i, name_list) {
+			md = hc->md;
+			dm_get(md);
 
-			if (keep_open_devices &&
-			    dm_lock_for_deletion(hc->md)) {
+			if (keep_open_devices && dm_lock_for_deletion(md)) {
+				dm_put(md);
 				dev_skipped++;
 				continue;
 			}
+
 			__hash_remove(hc);
-			dev_removed = 1;
-		}
-	}
 
-	/*
-	 * Some mapped devices may be using other mapped devices, so if any
-	 * still exist, repeat until we make no further progress.
-	 */
-	if (dev_skipped) {
-		if (dev_removed)
-			goto retry;
+			up_write(&_hash_lock);
 
-		DMWARN("remove_all left %d open device(s)", dev_skipped);
+			dm_put(md);
+
+			/*
+			 * Some mapped devices may be using other mapped
+			 * devices, so repeat until we make no further
+			 * progress.  If a new mapped device is created
+			 * here it will also get removed.
+			 */
+			goto retry;
+		}
 	}
 
 	up_write(&_hash_lock);
+
+	if (dev_skipped)
+		DMWARN("remove_all left %d open device(s)", dev_skipped);
 }
 
 static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
@@ -321,7 +336,9 @@
 	 */
 	list_del(&hc->name_list);
 	old_name = hc->name;
+	mutex_lock(&dm_hash_cells_mutex);
 	hc->name = new_name;
+	mutex_unlock(&dm_hash_cells_mutex);
 	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
 
 	/*
@@ -1582,8 +1599,7 @@
 	if (!md)
 		return -ENXIO;
 
-	dm_get(md);
-	down_read(&_hash_lock);
+	mutex_lock(&dm_hash_cells_mutex);
 	hc = dm_get_mdptr(md);
 	if (!hc || hc->md != md) {
 		r = -ENXIO;
@@ -1596,8 +1612,7 @@
 		strcpy(uuid, hc->uuid ? : "");
 
 out:
-	up_read(&_hash_lock);
-	dm_put(md);
+	mutex_unlock(&dm_hash_cells_mutex);
 
 	return r;
 }
--- linux-ec2-2.6.32.orig/drivers/md/dm-stripe.c
+++ linux-ec2-2.6.32/drivers/md/dm-stripe.c
@@ -110,7 +110,7 @@
 	}
 
 	stripes = simple_strtoul(argv[0], &end, 10);
-	if (*end) {
+	if (!stripes || *end) {
 		ti->error = "Invalid stripe count";
 		return -EINVAL;
 	}
--- linux-ec2-2.6.32.orig/drivers/acpi/processor_idle.c
+++ linux-ec2-2.6.32/drivers/acpi/processor_idle.c
@@ -110,10 +110,19 @@
 	  DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
 	  DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
 	 (void *)2},
+	{ set_max_cstate, "Pavilion zv5000", {
+	  DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")},
+	 (void *)1},
+	{ set_max_cstate, "Asus L8400B", {
+	  DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")},
+	 (void *)1},
 	{},
 };
 
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 /*
  * Callers should disable interrupts before the call and enable
  * interrupts after return.
@@ -132,6 +141,7 @@
 	}
 	current_thread_info()->status |= TS_POLLING;
 }
+#endif
 
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
 
@@ -196,7 +206,7 @@
 static void lapic_timer_check_state(int state, struct acpi_processor *pr,
 				   struct acpi_processor_cx *cstate) { }
 static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
-static void lapic_timer_state_broadcast(struct acpi_processor *pr,
+static inline void lapic_timer_state_broadcast(struct acpi_processor *pr,
 				       struct acpi_processor_cx *cx,
 				       int broadcast)
 {
@@ -244,7 +254,8 @@
 	return 0;
 }
 
-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
+#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) \
+    && !defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
 static void tsc_check_state(int state)
 {
 	switch (boot_cpu_data.x86_vendor) {
@@ -299,6 +310,17 @@
 	pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency;
 	pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency;
 
+	/*
+	 * FADT specified C2 latency must be less than or equal to
+	 * 100 microseconds.
+	 */
+	if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			"C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency));
+		/* invalidate C2 */
+		pr->power.states[ACPI_STATE_C2].address = 0;
+	}
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			  "lvl2[0x%08x] lvl3[0x%08x]\n",
 			  pr->power.states[ACPI_STATE_C2].address,
@@ -419,7 +441,8 @@
 				 */
 				cx.entry_method = ACPI_CSTATE_HALT;
 				snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
-			} else {
+			/* This doesn't apply to external control case */
+			} else if (!processor_pm_external()) {
 				continue;
 			}
 			if (cx.type == ACPI_STATE_C1 &&
@@ -458,6 +481,12 @@
 
 		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));
 
@@ -495,22 +524,16 @@
 		return;
 
 	/*
-	 * C2 latency must be less than or equal to 100
-	 * microseconds.
-	 */
-	else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "latency too large [%d]\n", cx->latency));
-		return;
-	}
-
-	/*
 	 * Otherwise we've met all of our C2 requirements.
 	 * Normalize the C2 latency to expidite policy
 	 */
 	cx->valid = 1;
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 	cx->latency_ticks = cx->latency;
+#else
+	cx->latency_ticks = us_to_pm_timer_ticks(cx->latency);
+#endif
 
 	return;
 }
@@ -593,7 +616,11 @@
 	 */
 	cx->valid = 1;
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 	cx->latency_ticks = cx->latency;
+#else
+	cx->latency_ticks = us_to_pm_timer_ticks(cx->latency);
+#endif
 	/*
 	 * On older chipsets, BM_RLD needs to be set
 	 * in order for Bus Master activity to wake the
@@ -667,6 +694,20 @@
 
 	pr->power.count = acpi_processor_power_verify(pr);
 
+#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+	/*
+	 * Set Default Policy
+	 * ------------------
+	 * Now that we know which states are supported, set the default
+	 * policy.  Note that this policy can be changed dynamically
+	 * (e.g. encourage deeper sleeps to conserve battery life when
+	 * not on AC).
+	 */
+	result = acpi_processor_set_power_policy(pr);
+	if (result)
+		return result;
+#endif
+
 	/*
 	 * if one state of type C2 or C3 is available, mark this
 	 * CPU as being "idle manageable"
@@ -764,6 +805,7 @@
 };
 #endif
 
+#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
 /**
  * acpi_idle_bm_check - checks if bus master activity was detected
  */
@@ -879,12 +921,14 @@
 		return(acpi_idle_enter_c1(dev, state));
 
 	local_irq_disable();
-	current_thread_info()->status &= ~TS_POLLING;
-	/*
-	 * TS_POLLING-cleared state must be visible before we test
-	 * NEED_RESCHED:
-	 */
-	smp_mb();
+	if (cx->entry_method != ACPI_CSTATE_FFH) {
+		current_thread_info()->status &= ~TS_POLLING;
+		/*
+		 * TS_POLLING-cleared state must be visible before we test
+		 * NEED_RESCHED:
+		 */
+		smp_mb();
+	}
 
 	if (unlikely(need_resched())) {
 		current_thread_info()->status |= TS_POLLING;
@@ -951,7 +995,7 @@
 	if (acpi_idle_suspend)
 		return(acpi_idle_enter_c1(dev, state));
 
-	if (acpi_idle_bm_check()) {
+	if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
 		if (dev->safe_state) {
 			dev->last_state = dev->safe_state;
 			return dev->safe_state->enter(dev, dev->safe_state);
@@ -964,12 +1008,14 @@
 	}
 
 	local_irq_disable();
-	current_thread_info()->status &= ~TS_POLLING;
-	/*
-	 * TS_POLLING-cleared state must be visible before we test
-	 * NEED_RESCHED:
-	 */
-	smp_mb();
+	if (cx->entry_method != ACPI_CSTATE_FFH) {
+		current_thread_info()->status &= ~TS_POLLING;
+		/*
+		 * TS_POLLING-cleared state must be visible before we test
+		 * NEED_RESCHED:
+		 */
+		smp_mb();
+	}
 
 	if (unlikely(need_resched())) {
 		current_thread_info()->status |= TS_POLLING;
@@ -1129,6 +1175,13 @@
 	return 0;
 }
 
+#else /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
+static inline int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+{
+	return 0;
+}
+#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
+
 int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 {
 	int ret = 0;
@@ -1146,6 +1199,14 @@
 	if (!pr->flags.power_setup_done)
 		return -ENODEV;
 
+	if (processor_pm_external()) {
+		pr->flags.power = 0;
+		ret = acpi_processor_get_power_info(pr);
+		processor_notify_external(pr,
+			PROCESSOR_PM_CHANGE, PM_TYPE_IDLE);
+		return ret;
+	}
+
 	cpuidle_pause_and_lock();
 	cpuidle_disable_device(&pr->power.dev);
 	acpi_processor_get_power_info(pr);
@@ -1187,6 +1248,10 @@
 			       "ACPI: processor limited to max C-state %d\n",
 			       max_cstate);
 		first_run++;
+#if defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) && defined(CONFIG_SMP)
+		pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
+				    &acpi_processor_latency_notifier);
+#endif
 	}
 
 	if (!pr)
@@ -1223,6 +1288,11 @@
 	if (!entry)
 		return -EIO;
 #endif
+
+	if (processor_pm_external())
+		processor_notify_external(pr,
+			PROCESSOR_PM_INIT, PM_TYPE_IDLE);
+
 	return 0;
 }
 
@@ -1241,5 +1311,12 @@
 				  acpi_device_dir(device));
 #endif
 
+#if defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) && defined(CONFIG_SMP)
+	/* Unregister the idle handler when processor #0 is removed. */
+	if (pr->id == 0)
+		pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
+				       &acpi_processor_latency_notifier);
+#endif
+
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/acpi/processor_extcntl.c
+++ linux-ec2-2.6.32/drivers/acpi/processor_extcntl.c
@@ -0,0 +1,346 @@
+/*
+ * 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_CLASS            "processor"
+#define _COMPONENT              ACPI_PROCESSOR_COMPONENT
+ACPI_MODULE_NAME("processor_extcntl")
+
+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_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control) {
+		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_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+
+	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
+				    acpi_gbl_FADT.pstate_control, 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.
+	 */
+	pdomain = &pr->performance->domain_info;
+	pdomain->num_processors = 0;
+	ret = acpi_processor_get_psd(pr);
+	if (ret < 0) {
+		/*
+		 * _PSD is optional - assume no coordination if absent (or
+		 * broken), matching native kernels' behavior.
+		 */
+		pdomain->num_entries = ACPI_PSD_REV0_ENTRIES;
+		pdomain->revision = ACPI_PSD_REV0_REVISION;
+		pdomain->domain = pr->acpi_id;
+		pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL;
+		pdomain->num_processors = 1;
+	}
+
+	/* Some sanity check */
+	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;
+}
+
+/*
+ * Objects and functions removed in native 2.6.29, and thus moved here.
+ */
+#ifdef CONFIG_SMP
+static void smp_callback(void *v)
+{
+	/* we already woke the CPU up, nothing more to do */
+}
+
+/*
+ * This function gets called when a part of the kernel has a new latency
+ * requirement.  This means we need to get all processors out of their C-state,
+ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
+ * wakes them all right up.
+ */
+static int acpi_processor_latency_notify(struct notifier_block *b,
+					 unsigned long l, void *v)
+{
+	smp_call_function(smp_callback, NULL, 1);
+	return NOTIFY_OK;
+}
+
+struct notifier_block acpi_processor_latency_notifier = {
+	.notifier_call = acpi_processor_latency_notify,
+};
+#endif
+
+/*
+ * bm_history -- bit-mask with a bit per jiffy of bus-master activity
+ * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
+ * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
+ * 100 HZ: 0x0000000F: 4 jiffies = 40ms
+ * reduce history for more aggressive entry into C3
+ */
+static unsigned int bm_history __read_mostly =
+    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
+module_param(bm_history, uint, 0644);
+
+int acpi_processor_set_power_policy(struct acpi_processor *pr)
+{
+	unsigned int i;
+	unsigned int state_is_set = 0;
+	struct acpi_processor_cx *lower = NULL;
+	struct acpi_processor_cx *higher = NULL;
+	struct acpi_processor_cx *cx;
+
+
+	if (!pr)
+		return -EINVAL;
+
+	/*
+	 * This function sets the default Cx state policy (OS idle handler).
+	 * Our scheme is to promote quickly to C2 but more conservatively
+	 * to C3.  We're favoring C2  for its characteristics of low latency
+	 * (quick response), good power savings, and ability to allow bus
+	 * mastering activity.  Note that the Cx state policy is completely
+	 * customizable and can be altered dynamically.
+	 */
+
+	/* startup state */
+	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+		cx = &pr->power.states[i];
+		if (!cx->valid)
+			continue;
+
+		if (!state_is_set)
+			pr->power.state = cx;
+		state_is_set++;
+		break;
+	}
+
+	if (!state_is_set)
+		return -ENODEV;
+
+	/* demotion */
+	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
+		cx = &pr->power.states[i];
+		if (!cx->valid)
+			continue;
+
+		if (lower) {
+			cx->demotion.state = lower;
+			cx->demotion.threshold.ticks = cx->latency_ticks;
+			cx->demotion.threshold.count = 1;
+			if (cx->type == ACPI_STATE_C3)
+				cx->demotion.threshold.bm = bm_history;
+		}
+
+		lower = cx;
+	}
+
+	/* promotion */
+	for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
+		cx = &pr->power.states[i];
+		if (!cx->valid)
+			continue;
+
+		if (higher) {
+			cx->promotion.state = higher;
+			cx->promotion.threshold.ticks = cx->latency_ticks;
+			if (cx->type >= ACPI_STATE_C2)
+				cx->promotion.threshold.count = 4;
+			else
+				cx->promotion.threshold.count = 10;
+			if (higher->type == ACPI_STATE_C3)
+				cx->promotion.threshold.bm = bm_history;
+		}
+
+		higher = cx;
+	}
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/acpi/power_meter.c
+++ linux-ec2-2.6.32/drivers/acpi/power_meter.c
@@ -34,7 +34,7 @@
 #define ACPI_POWER_METER_NAME		"power_meter"
 ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);
 #define ACPI_POWER_METER_DEVICE_NAME	"Power Meter"
-#define ACPI_POWER_METER_CLASS		"power_meter_resource"
+#define ACPI_POWER_METER_CLASS		"pwr_meter_resource"
 
 #define NUM_SENSORS			17
 
--- linux-ec2-2.6.32.orig/drivers/acpi/tables.c
+++ linux-ec2-2.6.32/drivers/acpi/tables.c
@@ -213,7 +213,7 @@
 	unsigned long table_end;
 	acpi_size tbl_size;
 
-	if (acpi_disabled)
+	if (acpi_disabled && !acpi_ht)
 		return -ENODEV;
 
 	if (!handler)
@@ -280,7 +280,7 @@
 	struct acpi_table_header *table = NULL;
 	acpi_size tbl_size;
 
-	if (acpi_disabled)
+	if (acpi_disabled && !acpi_ht)
 		return -ENODEV;
 
 	if (!handler)
--- linux-ec2-2.6.32.orig/drivers/acpi/Makefile
+++ linux-ec2-2.6.32/drivers/acpi/Makefile
@@ -62,5 +62,6 @@
 processor-y			:= processor_core.o processor_throttling.o
 processor-y			+= processor_idle.o processor_thermal.o
 processor-$(CONFIG_CPU_FREQ)	+= processor_perflib.o
+processor-$(CONFIG_PROCESSOR_EXTERNAL_CONTROL) += processor_perflib.o processor_extcntl.o
 
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
--- linux-ec2-2.6.32.orig/drivers/acpi/blacklist.c
+++ linux-ec2-2.6.32/drivers/acpi/blacklist.c
@@ -185,6 +185,12 @@
 	acpi_osi_setup("!Windows 2006");
 	return 0;
 }
+static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
+	acpi_osi_setup("!Windows 2009");
+	return 0;
+}
 
 static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
 	{
@@ -211,6 +217,38 @@
 		     DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"),
 		},
 	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba Satellite L355",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba Satellite L355",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win7,
+	.ident = "ASUS K50IJ",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba P305D",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
+		},
+	},
 
 	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
--- linux-ec2-2.6.32.orig/drivers/acpi/button.c
+++ linux-ec2-2.6.32/drivers/acpi/button.c
@@ -282,6 +282,13 @@
 	if (ret == NOTIFY_DONE)
 		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
 						   device);
+	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
+		/*
+		 * It is also regarded as success if the notifier_chain
+		 * returns NOTIFY_OK or NOTIFY_DONE.
+		 */
+		ret = 0;
+	}
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/drivers/acpi/ec.c
+++ linux-ec2-2.6.32/drivers/acpi/ec.c
@@ -201,14 +201,13 @@
 	spin_unlock_irqrestore(&ec->curr_lock, flags);
 }
 
-static void acpi_ec_gpe_query(void *ec_cxt);
+static int acpi_ec_sync_query(struct acpi_ec *ec);
 
-static int ec_check_sci(struct acpi_ec *ec, u8 state)
+static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
 {
 	if (state & ACPI_EC_FLAG_SCI) {
 		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
-			return acpi_os_execute(OSL_EC_BURST_HANDLER,
-				acpi_ec_gpe_query, ec);
+			return acpi_ec_sync_query(ec);
 	}
 	return 0;
 }
@@ -249,11 +248,6 @@
 {
 	unsigned long tmp;
 	int ret = 0;
-	pr_debug(PREFIX "transaction start\n");
-	/* disable GPE during transaction if storm is detected */
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		acpi_disable_gpe(NULL, ec->gpe);
-	}
 	if (EC_FLAGS_MSI)
 		udelay(ACPI_EC_MSI_UDELAY);
 	/* start transaction */
@@ -265,20 +259,9 @@
 		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
 	spin_unlock_irqrestore(&ec->curr_lock, tmp);
 	ret = ec_poll(ec);
-	pr_debug(PREFIX "transaction end\n");
 	spin_lock_irqsave(&ec->curr_lock, tmp);
 	ec->curr = NULL;
 	spin_unlock_irqrestore(&ec->curr_lock, tmp);
-	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
-		/* check if we received SCI during transaction */
-		ec_check_sci(ec, acpi_ec_read_status(ec));
-		/* it is safe to enable GPE outside of transaction */
-		acpi_enable_gpe(NULL, ec->gpe);
-	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
-		pr_info(PREFIX "GPE storm detected, "
-			"transactions will use polling mode\n");
-		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
-	}
 	return ret;
 }
 
@@ -321,7 +304,26 @@
 		status = -ETIME;
 		goto end;
 	}
+	pr_debug(PREFIX "transaction start\n");
+	/* disable GPE during transaction if storm is detected */
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		acpi_disable_gpe(NULL, ec->gpe);
+	}
+
 	status = acpi_ec_transaction_unlocked(ec, t);
+
+	/* check if we received SCI during transaction */
+	ec_check_sci_sync(ec, acpi_ec_read_status(ec));
+	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+		msleep(1);
+		/* it is safe to enable GPE outside of transaction */
+		acpi_enable_gpe(NULL, ec->gpe);
+	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
+		pr_info(PREFIX "GPE storm detected, "
+			"transactions will use polling mode\n");
+		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
+	}
+	pr_debug(PREFIX "transaction end\n");
 end:
 	if (ec->global_lock)
 		acpi_release_global_lock(glk);
@@ -443,7 +445,7 @@
 
 EXPORT_SYMBOL(ec_transaction);
 
-static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
+static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
 {
 	int result;
 	u8 d;
@@ -452,20 +454,16 @@
 				.wlen = 0, .rlen = 1};
 	if (!ec || !data)
 		return -EINVAL;
-
 	/*
 	 * Query the EC to find out which _Qxx method we need to evaluate.
 	 * Note that successful completion of the query causes the ACPI_EC_SCI
 	 * bit to be cleared (and thus clearing the interrupt source).
 	 */
-
-	result = acpi_ec_transaction(ec, &t);
+	result = acpi_ec_transaction_unlocked(ec, &t);
 	if (result)
 		return result;
-
 	if (!d)
 		return -ENODATA;
-
 	*data = d;
 	return 0;
 }
@@ -509,43 +507,78 @@
 
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static void acpi_ec_gpe_query(void *ec_cxt)
+static void acpi_ec_run(void *cxt)
 {
-	struct acpi_ec *ec = ec_cxt;
-	u8 value = 0;
-	struct acpi_ec_query_handler *handler, copy;
-
-	if (!ec || acpi_ec_query(ec, &value))
+	struct acpi_ec_query_handler *handler = cxt;
+	if (!handler)
 		return;
-	mutex_lock(&ec->lock);
+	pr_debug(PREFIX "start query execution\n");
+	if (handler->func)
+		handler->func(handler->data);
+	else if (handler->handle)
+		acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
+	pr_debug(PREFIX "stop query execution\n");
+	kfree(handler);
+}
+
+static int acpi_ec_sync_query(struct acpi_ec *ec)
+{
+	u8 value = 0;
+	int status;
+	struct acpi_ec_query_handler *handler, *copy;
+	if ((status = acpi_ec_query_unlocked(ec, &value)))
+		return status;
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
 			/* have custom handler for this bit */
-			memcpy(&copy, handler, sizeof(copy));
-			mutex_unlock(&ec->lock);
-			if (copy.func) {
-				copy.func(copy.data);
-			} else if (copy.handle) {
-				acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
-			}
-			return;
+			copy = kmalloc(sizeof(*handler), GFP_KERNEL);
+			if (!copy)
+				return -ENOMEM;
+			memcpy(copy, handler, sizeof(*copy));
+			pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
+			return acpi_os_execute(OSL_GPE_HANDLER,
+				acpi_ec_run, copy);
 		}
 	}
+	return 0;
+}
+
+static void acpi_ec_gpe_query(void *ec_cxt)
+{
+	struct acpi_ec *ec = ec_cxt;
+	if (!ec)
+		return;
+	mutex_lock(&ec->lock);
+	acpi_ec_sync_query(ec);
 	mutex_unlock(&ec->lock);
 }
 
+static void acpi_ec_gpe_query(void *ec_cxt);
+
+static int ec_check_sci(struct acpi_ec *ec, u8 state)
+{
+	if (state & ACPI_EC_FLAG_SCI) {
+		if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
+			pr_debug(PREFIX "push gpe query to the queue\n");
+			return acpi_os_execute(OSL_NOTIFY_HANDLER,
+				acpi_ec_gpe_query, ec);
+		}
+	}
+	return 0;
+}
+
 static u32 acpi_ec_gpe_handler(void *data)
 {
 	struct acpi_ec *ec = data;
-	u8 status;
 
 	pr_debug(PREFIX "~~~> interrupt\n");
-	status = acpi_ec_read_status(ec);
 
-	advance_transaction(ec, status);
-	if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
+	advance_transaction(ec, acpi_ec_read_status(ec));
+	if (ec_transaction_done(ec) &&
+	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
 		wake_up(&ec->wait);
-	ec_check_sci(ec, status);
+		ec_check_sci(ec, acpi_ec_read_status(ec));
+	}
 	return ACPI_INTERRUPT_HANDLED;
 }
 
@@ -568,10 +601,7 @@
 	if (function != ACPI_READ && function != ACPI_WRITE)
 		return AE_BAD_PARAMETER;
 
-	if (bits != 8 && acpi_strict)
-		return AE_BAD_PARAMETER;
-
-	if (EC_FLAGS_MSI)
+	if (EC_FLAGS_MSI || bits > 8)
 		acpi_ec_burst_enable(ec);
 
 	if (function == ACPI_READ) {
@@ -593,7 +623,7 @@
 		}
 	}
 
-	if (EC_FLAGS_MSI)
+	if (EC_FLAGS_MSI || bits > 8)
 		acpi_ec_burst_disable(ec);
 
 	switch (result) {
@@ -916,6 +946,7 @@
 /* MSI EC needs special treatment, enable it */
 static int ec_flag_msi(const struct dmi_system_id *id)
 {
+	printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
 	EC_FLAGS_MSI = 1;
 	EC_FLAGS_VALIDATE_ECDT = 1;
 	return 0;
@@ -928,8 +959,16 @@
 	DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
 	{
 	ec_flag_msi, "MSI hardware", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"),
-	DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL},
+	DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL},
+	{
+	ec_flag_msi, "MSI hardware", {
+	DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL},
+	{
+	ec_flag_msi, "MSI hardware", {
+	DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
+	{
+	ec_flag_msi, "MSI hardware", {
+	DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
 	{
 	ec_validate_ecdt, "ASUS hardware", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
--- linux-ec2-2.6.32.orig/drivers/acpi/sleep.c
+++ linux-ec2-2.6.32/drivers/acpi/sleep.c
@@ -60,6 +60,7 @@
 static int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
+#ifndef CONFIG_ACPI_PV_SLEEP
 	/* do we have a wakeup address for S2 and S3? */
 	if (acpi_state == ACPI_STATE_S3) {
 		if (!acpi_wakeup_address) {
@@ -69,6 +70,7 @@
 				(acpi_physical_address)acpi_wakeup_address);
 
 	}
+#endif
 	ACPI_FLUSH_CPU_CACHE();
 	acpi_enable_wakeup_device_prep(acpi_state);
 #endif
@@ -80,6 +82,7 @@
 
 #ifdef CONFIG_ACPI_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
 /*
  * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
  * user to request that behavior by using the 'acpi_old_suspend_ordering'
@@ -170,18 +173,6 @@
 #endif /* CONFIG_ACPI_SLEEP */
 
 #ifdef CONFIG_SUSPEND
-/*
- * According to the ACPI specification the BIOS should make sure that ACPI is
- * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states.  Still,
- * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
- * on such systems during resume.  Unfortunately that doesn't help in
- * particularly pathological cases in which SCI_EN has to be set directly on
- * resume, although the specification states very clearly that this flag is
- * owned by the hardware.  The set_sci_en_on_resume variable will be set in such
- * cases.
- */
-static bool set_sci_en_on_resume;
-
 extern void do_suspend_lowlevel(void);
 
 static u32 acpi_suspend_states[] = {
@@ -244,15 +235,19 @@
 		break;
 
 	case ACPI_STATE_S3:
+#ifdef CONFIG_ACPI_PV_SLEEP
+		/* Hyperviosr will save and restore CPU context
+		 * and then we can skip low level housekeeping here.
+		 */
+		acpi_enter_sleep_state(acpi_state);
+#else
 		do_suspend_lowlevel();
+#endif
 		break;
 	}
 
-	/* If ACPI is not enabled by the BIOS, we need to enable it here. */
-	if (set_sci_en_on_resume)
-		acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
-	else
-		acpi_enable();
+	/* This violates the spec but is required for bug compatibility. */
+	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
 
 	/* Reprogram control registers and execute _BFS */
 	acpi_leave_sleep_state_prep(acpi_state);
@@ -341,12 +336,6 @@
 	return 0;
 }
 
-static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d)
-{
-	set_sci_en_on_resume = true;
-	return 0;
-}
-
 static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
 	{
 	.callback = init_old_suspend_ordering,
@@ -365,22 +354,6 @@
 		},
 	},
 	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Apple MacBook 1,1",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
-		DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Apple MacMini 1,1",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
-		},
-	},
-	{
 	.callback = init_old_suspend_ordering,
 	.ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
 	.matches = {
@@ -389,62 +362,6 @@
 		},
 	},
 	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Toshiba Satellite L300",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard HP G7000 Notebook PC",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard Pavilion dv4",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard Pavilion dv7",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard Compaq Presario C700 Notebook PC",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"),
-		},
-	},
-	{
-	.callback = init_set_sci_en_on_resume,
-	.ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC",
-	.matches = {
-		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"),
-		},
-	},
-	{
 	.callback = init_old_suspend_ordering,
 	.ident = "Panasonic CF51-2L",
 	.matches = {
--- linux-ec2-2.6.32.orig/drivers/acpi/video_detect.c
+++ linux-ec2-2.6.32/drivers/acpi/video_detect.c
@@ -250,7 +250,7 @@
 				ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR;
 		if (!strcmp("video", str))
 			acpi_video_support |=
-				ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO;
+				ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO;
 	}
 	return 1;
 }
--- linux-ec2-2.6.32.orig/drivers/acpi/Kconfig
+++ linux-ec2-2.6.32/drivers/acpi/Kconfig
@@ -9,7 +9,7 @@
 	depends on PCI
 	depends on PM
 	select PNP
-	select CPU_IDLE
+	select CPU_IDLE if !PROCESSOR_EXTERNAL_CONTROL
 	default y
 	help
 	  Advanced Configuration and Power Interface (ACPI) support for 
@@ -307,6 +307,7 @@
 config X86_PM_TIMER
 	bool "Power Management Timer Support" if EMBEDDED
 	depends on X86
+	depends on !XEN
 	default y
 	help
 	  The Power Management Timer is available on all ACPI-capable,
@@ -360,4 +361,13 @@
 	  To compile this driver as a module, choose M here:
 	  the modules will be called sbs and sbshc.
 
+config ACPI_PV_SLEEP
+	bool
+	depends on X86 && XEN && ACPI_SLEEP
+	default y
+
+config PROCESSOR_EXTERNAL_CONTROL
+	bool
+	depends on (X86 || IA64) && XEN
+	default y
 endif	# ACPI
--- linux-ec2-2.6.32.orig/drivers/acpi/scan.c
+++ linux-ec2-2.6.32/drivers/acpi/scan.c
@@ -168,6 +168,16 @@
 }
 static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
 
+#ifdef CONFIG_PCI_GUESTDEV
+static ssize_t
+acpi_device_uid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+#endif
+
 static ssize_t
 acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -208,6 +218,13 @@
 	if (result)
 		goto end;
 
+#ifdef CONFIG_PCI_GUESTDEV
+	if(dev->pnp.unique_id) {
+		result = device_create_file(&dev->dev, &dev_attr_uid);
+		if(result)
+			goto end;
+	}
+#endif
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
@@ -271,6 +288,9 @@
 		kfree(id->id);
 		kfree(id);
 	}
+#ifdef CONFIG_PCI_GUESTDEV
+	kfree(device->pnp.unique_id);
+#endif
 }
 
 static void acpi_device_release(struct device *dev)
@@ -1047,6 +1067,11 @@
 			for (i = 0; i < cid_list->count; i++)
 				acpi_add_id(device, cid_list->ids[i].string);
 		}
+#ifdef CONFIG_PCI_GUESTDEV
+		if (info->valid & ACPI_VALID_UID)
+			device->pnp.unique_id = kstrdup(info->unique_id.string,
+							GFP_KERNEL);
+#endif
 		if (info->valid & ACPI_VALID_ADR) {
 			device->pnp.bus_address = info->address;
 			device->flags.bus_address = 1;
@@ -1357,6 +1382,9 @@
 {
 	struct acpi_bus_ops ops;
 
+	if (!device)
+		return -EINVAL;
+
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_start = 1;
 
--- linux-ec2-2.6.32.orig/drivers/acpi/pci_root.c
+++ linux-ec2-2.6.32/drivers/acpi/pci_root.c
@@ -465,6 +465,40 @@
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
+#ifdef CONFIG_PCI_GUESTDEV
+#include <linux/sysfs.h>
+
+static ssize_t seg_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &acpi_pci_roots) {
+		struct acpi_pci_root *root;
+		root = list_entry(entry, struct acpi_pci_root, node);
+		if (&root->device->dev == dev)
+			return sprintf(buf, "%04x\n", root->segment);
+	}
+	return 0;
+}
+static DEVICE_ATTR(seg, 0444, seg_show, NULL);
+
+static ssize_t bbn_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &acpi_pci_roots) {
+		struct acpi_pci_root *root;
+		root = list_entry(entry, struct acpi_pci_root, node);
+		if (&root->device->dev == dev)
+			return sprintf(buf, "%02x\n", root->bus_nr);
+	}
+	return 0;
+}
+static DEVICE_ATTR(bbn, 0444, bbn_show, NULL);
+#endif
+
 static int __devinit acpi_pci_root_add(struct acpi_device *device)
 {
 	unsigned long long segment, bus;
@@ -576,6 +610,13 @@
 	if (flags != base_flags)
 		acpi_pci_osc_support(root, flags);
 
+#ifdef CONFIG_PCI_GUESTDEV
+	if (device_create_file(&device->dev, &dev_attr_seg))
+		dev_warn(&device->dev, "could not create seg attr\n");
+	if (device_create_file(&device->dev, &dev_attr_bbn))
+		dev_warn(&device->dev, "could not create bbn attr\n");
+#endif
+
 	return 0;
 
 end:
@@ -613,3 +654,31 @@
 }
 
 subsys_initcall(acpi_pci_root_init);
+
+#ifdef CONFIG_PCI_GUESTDEV
+int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &acpi_pci_roots) {
+		struct acpi_pci_root *root;
+
+		root = list_entry(entry, struct acpi_pci_root, node);
+		if (strcmp(acpi_device_hid(root->device), hid))
+			continue;
+
+		if (!root->device->pnp.unique_id) {
+			if (strlen(uid))
+				continue;
+		} else {
+			if (strcmp(root->device->pnp.unique_id, uid))
+				continue;
+		}
+
+		*seg = (int)root->segment;
+		*bbn = (int)root->bus_nr;
+		return TRUE;
+	}
+	return FALSE;
+}
+#endif
--- linux-ec2-2.6.32.orig/drivers/acpi/bus.c
+++ linux-ec2-2.6.32/drivers/acpi/bus.c
@@ -344,6 +344,167 @@
 
 EXPORT_SYMBOL(acpi_bus_can_wakeup);
 
+static void acpi_print_osc_error(acpi_handle handle,
+	struct acpi_osc_context *context, char *error)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
+	int i;
+
+	if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
+		printk(KERN_DEBUG "%s\n", error);
+	else {
+		printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
+		kfree(buffer.pointer);
+	}
+	printk(KERN_DEBUG"_OSC request data:");
+	for (i = 0; i < context->cap.length; i += sizeof(u32))
+		printk("%x ", *((u32 *)(context->cap.pointer + i)));
+	printk("\n");
+}
+
+static u8 hex_val(unsigned char c)
+{
+	return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;
+}
+
+static acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
+{
+	int i;
+	static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
+		24, 26, 28, 30, 32, 34};
+
+	if (strlen(str) != 36)
+		return AE_BAD_PARAMETER;
+	for (i = 0; i < 36; i++) {
+		if (i == 8 || i == 13 || i == 18 || i == 23) {
+			if (str[i] != '-')
+				return AE_BAD_PARAMETER;
+		} else if (!isxdigit(str[i]))
+			return AE_BAD_PARAMETER;
+	}
+	for (i = 0; i < 16; i++) {
+		uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4;
+		uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]);
+	}
+	return AE_OK;
+}
+
+acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
+{
+	acpi_status status;
+	struct acpi_object_list input;
+	union acpi_object in_params[4];
+	union acpi_object *out_obj;
+	u8 uuid[16];
+	u32 errors;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	if (!context)
+		return AE_ERROR;
+	if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
+		return AE_ERROR;
+	context->ret.length = ACPI_ALLOCATE_BUFFER;
+	context->ret.pointer = NULL;
+
+	/* Setting up input parameters */
+	input.count = 4;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= 16;
+	in_params[0].buffer.pointer	= uuid;
+	in_params[1].type 		= ACPI_TYPE_INTEGER;
+	in_params[1].integer.value 	= context->rev;
+	in_params[2].type 		= ACPI_TYPE_INTEGER;
+	in_params[2].integer.value	= context->cap.length/sizeof(u32);
+	in_params[3].type		= ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length 	= context->cap.length;
+	in_params[3].buffer.pointer 	= context->cap.pointer;
+
+	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	if (!output.length)
+		return AE_NULL_OBJECT;
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER
+		|| out_obj->buffer.length != context->cap.length) {
+		acpi_print_osc_error(handle, context,
+			"_OSC evaluation returned wrong type");
+		status = AE_TYPE;
+		goto out_kfree;
+	}
+	/* Need to ignore the bit0 in result code */
+	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+	if (errors) {
+		if (errors & OSC_REQUEST_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC request failed");
+		if (errors & OSC_INVALID_UUID_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC invalid UUID");
+		if (errors & OSC_INVALID_REVISION_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC invalid revision");
+		if (errors & OSC_CAPABILITIES_MASK_ERROR) {
+			if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
+			    & OSC_QUERY_ENABLE)
+				goto out_success;
+			status = AE_SUPPORT;
+			goto out_kfree;
+		}
+		status = AE_ERROR;
+		goto out_kfree;
+	}
+out_success:
+	context->ret.length = out_obj->buffer.length;
+	context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
+	if (!context->ret.pointer) {
+		status =  AE_NO_MEMORY;
+		goto out_kfree;
+	}
+	memcpy(context->ret.pointer, out_obj->buffer.pointer,
+		context->ret.length);
+	status =  AE_OK;
+
+out_kfree:
+	kfree(output.pointer);
+	if (status != AE_OK)
+		context->ret.pointer = NULL;
+	return status;
+}
+EXPORT_SYMBOL(acpi_run_osc);
+
+static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
+static void acpi_bus_osc_support(void)
+{
+	u32 capbuf[2];
+	struct acpi_osc_context context = {
+		.uuid_str = sb_uuid_str,
+		.rev = 1,
+		.cap.length = 8,
+		.cap.pointer = capbuf,
+	};
+	acpi_handle handle;
+
+	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
+	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
+#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
+			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
+	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
+#endif
+
+#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
+#endif
+	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
+		return;
+	if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
+		kfree(context.ret.pointer);
+	/* do we need to check the returned cap? Sounds no */
+}
+
 /* --------------------------------------------------------------------------
                                 Event Management
    -------------------------------------------------------------------------- */
@@ -734,6 +895,8 @@
 	status = acpi_ec_ecdt_probe();
 	/* Ignore result. Not having an ECDT is not fatal. */
 
+	acpi_bus_osc_support();
+
 	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
--- linux-ec2-2.6.32.orig/drivers/acpi/battery.c
+++ linux-ec2-2.6.32/drivers/acpi/battery.c
@@ -837,6 +837,18 @@
 #endif
 }
 
+static LIST_HEAD(acpi_battery_domain);
+
+static void acpi_battery_update_async(struct acpi_device *device, async_cookie_t cookie)
+{
+	struct acpi_battery *battery = acpi_driver_data(device);
+
+	acpi_battery_update(battery);
+	printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
+		ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+		device->status.battery_present ? "present" : "absent");
+}
+
 static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
@@ -851,14 +863,14 @@
 	strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
 	device->driver_data = battery;
 	mutex_init(&battery->lock);
-	acpi_battery_update(battery);
+	/* Mark the battery for update at first access. */
+	battery->update_time = 0;
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	result = acpi_battery_add_fs(device);
 #endif
 	if (!result) {
-		printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
-			ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
-			device->status.battery_present ? "present" : "absent");
+		async_schedule_domain(acpi_battery_update_async, device, &acpi_battery_domain);
+
 	} else {
 #ifdef CONFIG_ACPI_PROCFS_POWER
 		acpi_battery_remove_fs(device);
@@ -874,6 +886,10 @@
 
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
+
+	/* Ensure all async updates are complete before freeing the battery. */
+	async_synchronize_full_domain(&acpi_battery_domain);
+
 	battery = acpi_driver_data(device);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
@@ -911,27 +927,21 @@
 		},
 };
 
-static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
+static int __init acpi_battery_init(void)
 {
 	if (acpi_disabled)
 		return;
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_dir = acpi_lock_battery_dir();
 	if (!acpi_battery_dir)
-		return;
+		return -1;
 #endif
 	if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
 #ifdef CONFIG_ACPI_PROCFS_POWER
 		acpi_unlock_battery_dir(acpi_battery_dir);
 #endif
-		return;
+		return -1;
 	}
-	return;
-}
-
-static int __init acpi_battery_init(void)
-{
-	async_schedule(acpi_battery_init_async, NULL);
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/acpi/processor_core.c
+++ linux-ec2-2.6.32/drivers/acpi/processor_core.c
@@ -134,12 +134,6 @@
 
 static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
 	{
-	set_no_mwait, "IFL91 board", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-	DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
-	DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
-	DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
-	{
 	set_no_mwait, "Extensa 5220", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -658,7 +652,8 @@
 	 */
 	if (pr->id == -1) {
 		if (ACPI_FAILURE
-		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+		    (acpi_processor_hotadd_init(pr->handle, &pr->id)) &&
+		    !processor_cntl_external()) {
 			return -ENODEV;
 		}
 	}
@@ -671,7 +666,14 @@
 	 * generated as the following format:
 	 * CPU+CPU ID.
 	 */
-	sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+	if (pr->id != -1)
+		sprintf(acpi_device_bid(device), "CPU%X", pr->id);
+	else
+		snprintf(acpi_device_bid(device),
+			 ARRAY_SIZE(acpi_device_bid(device)),
+			 "#%0*X",
+			 (int)ARRAY_SIZE(acpi_device_bid(device)) - 2,
+			 pr->acpi_id);
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
 			  pr->acpi_id));
 
@@ -703,13 +705,17 @@
 	 * of /proc/cpuinfo
 	 */
 	status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
-	if (ACPI_SUCCESS(status))
+	if (ACPI_SUCCESS(status) && pr->id != -1)
 		arch_fix_phys_package_id(pr->id, object.integer.value);
 
 	return 0;
 }
 
+#ifndef CONFIG_XEN
 static DEFINE_PER_CPU(void *, processor_device_array);
+#else
+static void *processor_device_array[NR_ACPI_CPUS];
+#endif
 
 static void acpi_processor_notify(struct acpi_device *device, u32 event)
 {
@@ -790,27 +796,43 @@
 	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
 	device->driver_data = pr;
 
+ 	processor_extcntl_init();
+
 	result = acpi_processor_get_info(device);
-	if (result) {
+	if (result ||
+	    ((pr->id == -1) && !processor_cntl_external())) {
 		/* Processor is physically not present */
 		return 0;
 	}
 
-	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
+	BUG_ON(!processor_cntl_external() &&
+	       ((pr->id >= nr_cpu_ids) || (pr->id < 0)));
 
 	/*
 	 * Buggy BIOS check
 	 * ACPI id of processors can be reported wrongly by the BIOS.
 	 * Don't trust it blindly
 	 */
+#ifndef CONFIG_XEN
 	if (per_cpu(processor_device_array, pr->id) != NULL &&
 	    per_cpu(processor_device_array, pr->id) != device) {
+#else
+	BUG_ON(pr->acpi_id >= NR_ACPI_CPUS);
+	if (processor_device_array[pr->acpi_id] != NULL &&
+	    processor_device_array[pr->acpi_id] != device) {
+#endif
 		printk(KERN_WARNING "BIOS reported wrong ACPI id "
 			"for the processor\n");
 		result = -ENODEV;
 		goto err_free_cpumask;
 	}
+#ifndef CONFIG_XEN
 	per_cpu(processor_device_array, pr->id) = device;
+#else
+	processor_device_array[pr->acpi_id] = device;
+	if (pr->id != -1)
+		per_cpu(processors, pr->id) = pr;
+#endif
 
 	per_cpu(processors, pr->id) = pr;
 
@@ -818,10 +840,12 @@
 	if (result)
 		goto err_free_cpumask;
 
-	sysdev = get_cpu_sysdev(pr->id);
-	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
-		result = -EFAULT;
-		goto err_remove_fs;
+	if (pr->id != -1) {
+		sysdev = get_cpu_sysdev(pr->id);
+		if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+			result = -EFAULT;
+			goto err_remove_fs;
+		}
 	}
 
 	/* _PDC call should be done before doing anything else (if reqd.). */
@@ -829,15 +853,27 @@
 	acpi_processor_set_pdc(pr);
 	arch_acpi_processor_cleanup_pdc(pr);
 
-#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);
-	acpi_processor_get_limit_info(pr);
 
+	/*
+	 * pr->id may equal to -1 while processor_cntl_external enabled.
+	 * throttle and thermal module don't support this case.
+	 * Tx only works when dom0 vcpu == pcpu num by far, as we give
+	 * control to dom0.
+	 */
+	if (pr->id != -1) {
+		acpi_processor_get_throttling_info(pr);
+		acpi_processor_get_limit_info(pr);
+	}
 
 	acpi_processor_power_init(pr, device);
 
+	result = processor_extcntl_prepare(pr);
+	if (result)
+		goto err_power_exit;
+
 	pr->cdev = thermal_cooling_device_register("Processor", device,
 						&processor_cooling_ops);
 	if (IS_ERR(pr->cdev)) {
@@ -889,7 +925,7 @@
 
 	pr = acpi_driver_data(device);
 
-	if (pr->id >= nr_cpu_ids)
+	if (!processor_cntl_external() && pr->id >= nr_cpu_ids)
 		goto free;
 
 	if (type == ACPI_BUS_REMOVAL_EJECT) {
@@ -899,7 +935,8 @@
 
 	acpi_processor_power_exit(pr, device);
 
-	sysfs_remove_link(&device->dev.kobj, "sysdev");
+	if (pr->id != -1)
+		sysfs_remove_link(&device->dev.kobj, "sysdev");
 
 	acpi_processor_remove_fs(device);
 
@@ -910,8 +947,14 @@
 		pr->cdev = NULL;
 	}
 
+#ifndef CONFIG_XEN
 	per_cpu(processors, pr->id) = NULL;
 	per_cpu(processor_device_array, pr->id) = NULL;
+#else
+	if (pr->id != -1)
+		per_cpu(processors, pr->id) = NULL;
+	processor_device_array[pr->acpi_id] = NULL;
+#endif
 
 free:
 	free_cpumask_var(pr->throttling.shared_cpu_map);
@@ -967,6 +1010,10 @@
 		return -ENODEV;
 	}
 
+	if (processor_cntl_external() && acpi_driver_data(*device))
+		processor_notify_external(acpi_driver_data(*device),
+			PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
+
 	return 0;
 }
 
@@ -996,6 +1043,10 @@
 					    "Unable to add the device\n");
 			break;
 		}
+		pr = acpi_driver_data(device);
+		if (processor_cntl_external() && pr)
+			processor_notify_external(pr,
+					PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
 		break;
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -1012,6 +1063,9 @@
 				    "Driver data is NULL, dropping EJECT\n");
 			return;
 		}
+		if (processor_cntl_external())
+			processor_notify_external(pr, PROCESSOR_HOTPLUG,
+						HOTPLUG_TYPE_REMOVE);
 		break;
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -1076,6 +1130,11 @@
 
 static int acpi_processor_handle_eject(struct acpi_processor *pr)
 {
+#ifdef CONFIG_XEN
+	if (pr->id == -1)
+		return (0);
+#endif
+
 	if (cpu_online(pr->id))
 		cpu_down(pr->id);
 
--- linux-ec2-2.6.32.orig/drivers/acpi/processor_perflib.c
+++ linux-ec2-2.6.32/drivers/acpi/processor_perflib.c
@@ -78,6 +78,7 @@
 
 static int acpi_processor_ppc_status;
 
+#ifdef CONFIG_CPU_FREQ
 static int acpi_processor_ppc_notifier(struct notifier_block *nb,
 				       unsigned long event, void *data)
 {
@@ -120,6 +121,7 @@
 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)
 {
@@ -164,9 +166,15 @@
 	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
@@ -185,6 +193,7 @@
 
 	acpi_processor_ppc_status &= ~PPC_REGISTERED;
 }
+#endif	/* CONFIG_CPU_FREQ */
 
 static int acpi_processor_get_performance_control(struct acpi_processor *pr)
 {
@@ -332,7 +341,10 @@
 	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;
@@ -356,7 +368,11 @@
 	if (result)
 		goto update_bios;
 
-	return 0;
+	/* We need to call _PPC once when cpufreq starts */
+	if (ignore_ppc != 1)
+		result = acpi_processor_get_platform_limit(pr);
+
+	return result;
 
 	/*
 	 * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
@@ -373,6 +389,7 @@
 	return result;
 }
 
+#ifdef CONFIG_CPU_FREQ
 int acpi_processor_notify_smm(struct module *calling_module)
 {
 	acpi_status status;
@@ -433,8 +450,12 @@
 }
 
 EXPORT_SYMBOL(acpi_processor_notify_smm);
+#endif	/* CONFIG_CPU_FREQ */
 
-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;
--- linux-ec2-2.6.32.orig/drivers/acpi/osl.c
+++ linux-ec2-2.6.32/drivers/acpi/osl.c
@@ -1151,16 +1151,10 @@
 
 	if (clash) {
 		if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
-			printk("%sACPI: %s resource %s [0x%llx-0x%llx]"
-			       " conflicts with ACPI region %s"
-			       " [0x%llx-0x%llx]\n",
-			       acpi_enforce_resources == ENFORCE_RESOURCES_LAX
-			       ? KERN_WARNING : KERN_ERR,
-			       ioport ? "I/O" : "Memory", res->name,
-			       (long long) res->start, (long long) res->end,
-			       res_list_elem->name,
-			       (long long) res_list_elem->start,
-			       (long long) res_list_elem->end);
+			printk(KERN_INFO "ACPI: resource %s %pR"
+			       " conflicts with ACPI region %s %pR\n",
+			       res->name, res, res_list_elem->name,
+			       res_list_elem);
 			if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
 				printk(KERN_NOTICE "ACPI: This conflict may"
 				       " cause random problems and system"
--- linux-ec2-2.6.32.orig/drivers/acpi/video.c
+++ linux-ec2-2.6.32/drivers/acpi/video.c
@@ -2088,7 +2088,7 @@
 
 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
 {
-	return acpi_video_bus_DOS(video, 0, 0);
+	return acpi_video_bus_DOS(video, 0, 1);
 }
 
 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
--- linux-ec2-2.6.32.orig/drivers/acpi/acpica/hwsleep.c
+++ linux-ec2-2.6.32/drivers/acpi/acpica/hwsleep.c
@@ -236,7 +236,11 @@
 	u32 pm1b_control;
 	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
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
 	acpi_status status;
@@ -347,6 +351,7 @@
 
 	/* Write #2: Write both SLP_TYP + SLP_EN */
 
+#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
 	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -386,6 +391,15 @@
 		/* Spin until we wake */
 
 	} while (!in_value);
+#else
+	/* PV ACPI just need check hypercall return value */
+	err = acpi_notify_hypervisor_state(sleep_state,
+			pm1a_control, pm1b_control);
+	if (err) {
+		printk(KERN_ERR "ACPI: Hypervisor failure [%d]\n", err);
+		return_ACPI_STATUS(AE_ERROR);
+	}
+#endif
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -404,6 +418,7 @@
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
+#ifndef CONFIG_XEN
 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
 {
 	u32 in_value;
@@ -457,6 +472,7 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
+#endif
 
 /*******************************************************************************
  *
--- linux-ec2-2.6.32.orig/drivers/acpi/acpica/exprep.c
+++ linux-ec2-2.6.32/drivers/acpi/acpica/exprep.c
@@ -468,6 +468,23 @@
 
 		acpi_ut_add_reference(obj_desc->field.region_obj);
 
+		/* allow full data read from EC address space */
+		if (obj_desc->field.region_obj->region.space_id ==
+			ACPI_ADR_SPACE_EC) {
+			if (obj_desc->common_field.bit_length > 8) {
+				int access_bit_width = ACPI_ROUND_UP(
+					obj_desc->common_field.bit_length, 8);
+				if (access_bit_width > sizeof(acpi_integer) * 8)
+					access_bit_width =
+						sizeof(acpi_integer) * 8;
+				obj_desc->common_field.access_bit_width =
+					 access_bit_width;
+				obj_desc->common_field.access_byte_width =
+					ACPI_DIV_8(access_bit_width);
+			}
+
+		}
+
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
 				  obj_desc->field.start_field_bit_offset,
--- linux-ec2-2.6.32.orig/drivers/acpi/acpica/aclocal.h
+++ linux-ec2-2.6.32/drivers/acpi/acpica/aclocal.h
@@ -846,6 +846,7 @@
 	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
 	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
 	ACPI_BITMASK_RT_CLOCK_STATUS       | \
+	ACPI_BITMASK_PCIEXP_WAKE_DISABLE   | \
 	ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
--- linux-ec2-2.6.32.orig/drivers/acpi/acpica/dswexec.c
+++ linux-ec2-2.6.32/drivers/acpi/acpica/dswexec.c
@@ -300,10 +300,25 @@
 			 * we must enter this object into the namespace.  The created
 			 * object is temporary and will be deleted upon completion of
 			 * the execution of this method.
+			 *
+			 * Note 10/2010: Except for the Scope() op. This opcode does
+			 * not actually create a new object, it refers to an existing
+			 * object. However, for Scope(), we want to indeed open a
+			 * new scope.
 			 */
-			status = acpi_ds_load2_begin_op(walk_state, NULL);
+			if (op->common.aml_opcode != AML_SCOPE_OP) {
+				status =
+				    acpi_ds_load2_begin_op(walk_state, NULL);
+			} else {
+				status =
+				    acpi_ds_scope_stack_push(op->named.node,
+							     op->named.node->
+							     type, walk_state);
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
 		}
-
 		break;
 
 	case AML_CLASS_EXECUTE:
--- linux-ec2-2.6.32.orig/drivers/platform/x86/eeepc-laptop.c
+++ linux-ec2-2.6.32/drivers/platform/x86/eeepc-laptop.c
@@ -34,6 +34,7 @@
 #include <linux/rfkill.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
+#include <linux/dmi.h>
 
 #define EEEPC_LAPTOP_VERSION	"0.1"
 
@@ -135,6 +136,8 @@
 	acpi_handle handle;		/* the handle of the hotk device */
 	u32 cm_supported;		/* the control methods supported
 					   by this BIOS */
+	bool cpufv_disabled;
+	bool hotplug_disabled;
 	uint init_flag;			/* Init flags */
 	u16 event_count[128];		/* count for each event */
 	struct input_dev *inputdev;
@@ -251,6 +254,14 @@
 MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
 MODULE_LICENSE("GPL");
 
+static bool hotplug_disabled;
+
+module_param(hotplug_disabled, bool, 0644);
+MODULE_PARM_DESC(hotplug_disabled,
+		 "Disable hotplug for wireless device. "
+		 "If your laptop need that, please report to "
+		 "acpi4asus-user@lists.sourceforge.net.");
+
 /*
  * ACPI Helpers
  */
@@ -467,6 +478,8 @@
 	struct eeepc_cpufv c;
 	int rv, value;
 
+	if (ehotk->cpufv_disabled)
+		return -EPERM;
 	if (get_cpufv(&c))
 		return -ENODEV;
 	rv = parse_arg(buf, count, &value);
@@ -478,6 +491,38 @@
 	return rv;
 }
 
+static ssize_t show_cpufv_disabled(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	return sprintf(buf, "%d\n", ehotk->cpufv_disabled);
+}
+
+static ssize_t store_cpufv_disabled(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	int rv, value;
+
+	rv = parse_arg(buf, count, &value);
+	if (rv < 0)
+		return rv;
+
+	switch (value) {
+	case 0:
+		if (ehotk->cpufv_disabled)
+			pr_warning("cpufv enabled (not officially supported "
+				"on this model)\n");
+		ehotk->cpufv_disabled = false;
+		return rv;
+	case 1:
+		return -EPERM;
+	default:
+		return -EINVAL;
+	}
+}
+
+
 static struct device_attribute dev_attr_cpufv = {
 	.attr = {
 		.name = "cpufv",
@@ -493,12 +538,22 @@
 	.show   = show_available_cpufv
 };
 
+static struct device_attribute dev_attr_cpufv_disabled = {
+	.attr = {
+		.name = "cpufv_disabled",
+		.mode = 0644 },
+	.show   = show_cpufv_disabled,
+	.store  = store_cpufv_disabled
+};
+
+
 static struct attribute *platform_attributes[] = {
 	&dev_attr_camera.attr,
 	&dev_attr_cardr.attr,
 	&dev_attr_disp.attr,
 	&dev_attr_cpufv.attr,
 	&dev_attr_available_cpufv.attr,
+	&dev_attr_cpufv_disabled.attr,
 	NULL
 };
 
@@ -564,6 +619,54 @@
 	return -EINVAL;
 }
 
+static void eeepc_dmi_check(void)
+{
+	const char *model;
+
+	model = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!model)
+		return;
+
+	/*
+	 * Blacklist for setting cpufv (cpu speed).
+	 *
+	 * EeePC 4G ("701") implements CFVS, but it is not supported
+	 * by the pre-installed OS, and the original option to change it
+	 * in the BIOS setup screen was removed in later versions.
+	 *
+	 * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
+	 * this applies to all "701" models (4G/4G Surf/2G Surf).
+	 *
+	 * So Asus made a deliberate decision not to support it on this model.
+	 * We have several reports that using it can cause the system to hang
+	 *
+	 * The hang has also been reported on a "702" (Model name "8G"?).
+	 *
+	 * We avoid dmi_check_system() / dmi_match(), because they use
+	 * substring matching.  We don't want to affect the "701SD"
+	 * and "701SDX" models, because they do support S.H.E.
+	 */
+	if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
+		ehotk->cpufv_disabled = true;
+		pr_info("model %s does not officially support setting cpu "
+			"speed\n", model);
+		pr_info("cpufv disabled to avoid instability\n");
+	}
+
+	/*
+	 * Blacklist for wlan hotplug
+	 *
+	 * Eeepc 1005HA doesn't work like others models and don't need the
+	 * hotplug code. In fact, current hotplug code seems to unplug another
+	 * device...
+	 */
+	if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
+	    strcmp(model, "1005PE") == 0) {
+		ehotk->hotplug_disabled = true;
+		pr_info("wlan hotplug disabled\n");
+	}
+}
+
 static void cmsg_quirk(int cm, const char *name)
 {
 	int dummy;
@@ -649,6 +752,8 @@
 	struct pci_dev *dev;
 	struct pci_bus *bus;
 	bool blocked = eeepc_wlan_rfkill_blocked();
+	bool absent;
+	u32 l;
 
 	if (ehotk->wlan_rfkill)
 		rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
@@ -662,6 +767,22 @@
 			goto out_unlock;
 		}
 
+		if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
+			pr_err("Unable to read PCI config space?\n");
+			goto out_unlock;
+		}
+		absent = (l == 0xffffffff);
+
+		if (blocked != absent) {
+			pr_warning("BIOS says wireless lan is %s, "
+					"but the pci device is %s\n",
+				blocked ? "blocked" : "unblocked",
+				absent ? "absent" : "present");
+			pr_warning("skipped wireless hotplug as probably "
+					"inappropriate for this model\n");
+			goto out_unlock;
+		}
+
 		if (!blocked) {
 			dev = pci_get_slot(bus, 0);
 			if (dev) {
@@ -1095,6 +1216,9 @@
 	if (result && result != -ENODEV)
 		goto exit;
 
+	if (ehotk->hotplug_disabled)
+		return 0;
+
 	result = eeepc_setup_pci_hotplug();
 	/*
 	 * If we get -EBUSY then something else is handling the PCI hotplug -
@@ -1208,6 +1332,10 @@
 	device->driver_data = ehotk;
 	ehotk->device = device;
 
+	ehotk->hotplug_disabled = hotplug_disabled;
+
+	eeepc_dmi_check();
+
 	result = eeepc_hotk_check();
 	if (result)
 		goto fail_platform_driver;
--- linux-ec2-2.6.32.orig/drivers/platform/x86/wmi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/wmi.c
@@ -510,8 +510,8 @@
 /**
  * wmi_get_event_data - Get WMI data associated with an event
  *
- * @event - Event to find
- * &out - Buffer to hold event data
+ * @event: Event to find
+ * @out: Buffer to hold event data. out->pointer should be freed with kfree()
  *
  * Returns extra data associated with an event in WMI.
  */
--- linux-ec2-2.6.32.orig/drivers/platform/x86/compal-laptop.c
+++ linux-ec2-2.6.32/drivers/platform/x86/compal-laptop.c
@@ -26,17 +26,8 @@
 /*
  * comapl-laptop.c - Compal laptop support.
  *
- * This driver exports a few files in /sys/devices/platform/compal-laptop/:
- *
- *   wlan - wlan subsystem state: contains 0 or 1 (rw)
- *
- *   bluetooth - Bluetooth subsystem state: contains 0 or 1 (rw)
- *
- *   raw - raw value taken from embedded controller register (ro)
- *
- * In addition to these platform device attributes the driver
- * registers itself in the Linux backlight control subsystem and is
- * available to userspace under /sys/class/backlight/compal-laptop/.
+ * The driver registers itself with the rfkill subsystem and
+ * the Linux backlight control subsystem.
  *
  * This driver might work on other laptops produced by Compal. If you
  * want to try it you can pass force=1 as argument to the module which
@@ -52,6 +43,7 @@
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
 #include <linux/autoconf.h>
+#include <linux/rfkill.h>
 
 #define COMPAL_DRIVER_VERSION "0.2.6"
 
@@ -64,6 +56,10 @@
 #define WLAN_MASK	0x01
 #define BT_MASK 	0x02
 
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bt_rfkill;
+static struct platform_device *compal_device;
+
 static int force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -89,65 +85,75 @@
 	return (int) result;
 }
 
-static int set_wlan_state(int state)
+static int compal_rfkill_set(void *data, bool blocked)
 {
+	unsigned long radio = (unsigned long) data;
 	u8 result, value;
 
 	ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
 
-	if ((result & KILLSWITCH_MASK) == 0)
-		return -EINVAL;
-	else {
-		if (state)
-			value = (u8) (result | WLAN_MASK);
-		else
-			value = (u8) (result & ~WLAN_MASK);
-		ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
-	}
+	if (!blocked)
+		value = (u8) (result | radio);
+	else
+		value = (u8) (result & ~radio);
+	ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
 
 	return 0;
 }
 
-static int set_bluetooth_state(int state)
+static void compal_rfkill_poll(struct rfkill *rfkill, void *data)
 {
-	u8 result, value;
+	u8 result;
+	bool hw_blocked;
 
 	ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
 
-	if ((result & KILLSWITCH_MASK) == 0)
-		return -EINVAL;
-	else {
-		if (state)
-			value = (u8) (result | BT_MASK);
-		else
-			value = (u8) (result & ~BT_MASK);
-		ec_write(COMPAL_EC_COMMAND_WIRELESS, value);
-	}
-
-	return 0;
+	hw_blocked = !(result & KILLSWITCH_MASK);
+	rfkill_set_hw_state(rfkill, hw_blocked);
 }
 
-static int get_wireless_state(int *wlan, int *bluetooth)
+static const struct rfkill_ops compal_rfkill_ops = {
+	.poll = compal_rfkill_poll,
+	.set_block = compal_rfkill_set,
+};
+
+static int setup_rfkill(void)
 {
-	u8 result;
+	int ret;
 
-	ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
+	wifi_rfkill = rfkill_alloc("compal-wifi", &compal_device->dev,
+				RFKILL_TYPE_WLAN, &compal_rfkill_ops,
+				(void *) WLAN_MASK);
+	if (!wifi_rfkill)
+		return -ENOMEM;
 
-	if (wlan) {
-		if ((result & KILLSWITCH_MASK) == 0)
-			*wlan = 0;
-		else
-			*wlan = result & WLAN_MASK;
-	}
+	ret = rfkill_register(wifi_rfkill);
+	if (ret)
+		goto err_wifi;
 
-	if (bluetooth) {
-		if ((result & KILLSWITCH_MASK) == 0)
-			*bluetooth = 0;
-		else
-			*bluetooth = (result & BT_MASK) >> 1;
+	bt_rfkill = rfkill_alloc("compal-bluetooth", &compal_device->dev,
+				RFKILL_TYPE_BLUETOOTH, &compal_rfkill_ops,
+				(void *) BT_MASK);
+	if (!bt_rfkill) {
+		ret = -ENOMEM;
+		goto err_allocate_bt;
 	}
+	ret = rfkill_register(bt_rfkill);
+	if (ret)
+		goto err_register_bt;
 
 	return 0;
+
+err_register_bt:
+	rfkill_destroy(bt_rfkill);
+
+err_allocate_bt:
+	rfkill_unregister(wifi_rfkill);
+
+err_wifi:
+	rfkill_destroy(wifi_rfkill);
+
+	return ret;
 }
 
 /* Backlight device stuff */
@@ -170,86 +176,6 @@
 
 static struct backlight_device *compalbl_device;
 
-/* Platform device */
-
-static ssize_t show_wlan(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	int ret, enabled;
-
-	ret = get_wireless_state(&enabled, NULL);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%i\n", enabled);
-}
-
-static ssize_t show_raw(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	u8 result;
-
-	ec_read(COMPAL_EC_COMMAND_WIRELESS, &result);
-
-	return sprintf(buf, "%i\n", result);
-}
-
-static ssize_t show_bluetooth(struct device *dev,
-	struct device_attribute *attr, char *buf)
-{
-	int ret, enabled;
-
-	ret = get_wireless_state(NULL, &enabled);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%i\n", enabled);
-}
-
-static ssize_t store_wlan_state(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	int state, ret;
-
-	if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
-		return -EINVAL;
-
-	ret = set_wlan_state(state);
-	if (ret < 0)
-		return ret;
-
-	return count;
-}
-
-static ssize_t store_bluetooth_state(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	int state, ret;
-
-	if (sscanf(buf, "%i", &state) != 1 || (state < 0 || state > 1))
-		return -EINVAL;
-
-	ret = set_bluetooth_state(state);
-	if (ret < 0)
-		return ret;
-
-	return count;
-}
-
-static DEVICE_ATTR(bluetooth, 0644, show_bluetooth, store_bluetooth_state);
-static DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan_state);
-static DEVICE_ATTR(raw, 0444, show_raw, NULL);
-
-static struct attribute *compal_attributes[] = {
-	&dev_attr_bluetooth.attr,
-	&dev_attr_wlan.attr,
-	&dev_attr_raw.attr,
-	NULL
-};
-
-static struct attribute_group compal_attribute_group = {
-	.attrs = compal_attributes
-};
 
 static struct platform_driver compal_driver = {
 	.driver = {
@@ -258,8 +184,6 @@
 	}
 };
 
-static struct platform_device *compal_device;
-
 /* Initialization */
 
 static int dmi_check_cb(const struct dmi_system_id *id)
@@ -311,6 +235,47 @@
 		},
 		.callback = dmi_check_cb
 	},
+	{
+		.ident = "Dell Mini 9",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "Dell Mini 10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "Dell Mini 10v",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "Dell Inspiron 11z",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
+		},
+		.callback = dmi_check_cb
+	},
+	{
+		.ident = "Dell Mini 12",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
+		},
+		.callback = dmi_check_cb
+	},
+
 	{ }
 };
 
@@ -349,23 +314,21 @@
 
 	ret = platform_device_add(compal_device);
 	if (ret)
-		goto fail_platform_device1;
+		goto fail_platform_device;
 
-	ret = sysfs_create_group(&compal_device->dev.kobj,
-		&compal_attribute_group);
+	ret = setup_rfkill();
 	if (ret)
-		goto fail_platform_device2;
+		goto fail_rfkill;
 
 	printk(KERN_INFO "compal-laptop: driver "COMPAL_DRIVER_VERSION
 		" successfully loaded.\n");
 
 	return 0;
 
-fail_platform_device2:
-
+fail_rfkill:
 	platform_device_del(compal_device);
 
-fail_platform_device1:
+fail_platform_device:
 
 	platform_device_put(compal_device);
 
@@ -383,10 +346,13 @@
 static void __exit compal_cleanup(void)
 {
 
-	sysfs_remove_group(&compal_device->dev.kobj, &compal_attribute_group);
 	platform_device_unregister(compal_device);
 	platform_driver_unregister(&compal_driver);
 	backlight_device_unregister(compalbl_device);
+	rfkill_unregister(wifi_rfkill);
+	rfkill_destroy(wifi_rfkill);
+	rfkill_unregister(bt_rfkill);
+	rfkill_destroy(bt_rfkill);
 
 	printk(KERN_INFO "compal-laptop: driver unloaded.\n");
 }
@@ -404,3 +370,8 @@
 MODULE_ALIAS("dmi:*:rnIFL91:rvrIFT00:*");
 MODULE_ALIAS("dmi:*:rnJFL92:rvrIFT00:*");
 MODULE_ALIAS("dmi:*:rnIFT00:rvrIFT00:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron910:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1010:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1011:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1110:*");
+MODULE_ALIAS("dmi:*:svnDellInc.:pnInspiron1210:*");
--- linux-ec2-2.6.32.orig/drivers/platform/x86/acerhdf.c
+++ linux-ec2-2.6.32/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
  */
 #undef START_IN_KERNEL_MODE
 
-#define DRV_VER "0.5.18"
+#define DRV_VER "0.5.20"
 
 /*
  * According to the Atom N270 datasheet,
@@ -112,12 +112,14 @@
 MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
 
 /*
- * cmd_off: to switch the fan completely off / to check if the fan is off
+ * cmd_off: to switch the fan completely off
+ * chk_off: to check if the fan is off
  *	cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then
  *		the fan speed depending on the temperature
  */
 struct fancmd {
 	u8 cmd_off;
+	u8 chk_off;
 	u8 cmd_auto;
 };
 
@@ -134,32 +136,41 @@
 /* Register addresses and values for different BIOS versions */
 static const struct bios_settings_t bios_tbl[] = {
 	/* AOA110 */
-	{"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
-	{"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
-	{"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
-	{"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
-	{"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
+	{"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
+	{"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} },
 	/* AOA150 */
-	{"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	/* Acer 1410 */
+	{"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} },
 	/* special BIOS / other */
-	{"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
-	{"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
-	{"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
+	{"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3103 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3201 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3302 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
 	/* pewpew-terminator */
-	{"", "", "", 0, 0, {0, 0} }
+	{"", "", "", 0, 0, {0, 0, 0} }
 };
 
 static const struct bios_settings_t *bios_cfg __read_mostly;
@@ -183,7 +194,7 @@
 	if (ec_read(bios_cfg->fanreg, &fan))
 		return -EINVAL;
 
-	if (fan != bios_cfg->cmd.cmd_off)
+	if (fan != bios_cfg->cmd.chk_off)
 		*state = ACERHDF_FAN_AUTO;
 	else
 		*state = ACERHDF_FAN_OFF;
@@ -629,9 +640,10 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Peter Feuerer");
 MODULE_DESCRIPTION("Aspire One temperature and fan driver");
-MODULE_ALIAS("dmi:*:*Acer*:*:");
-MODULE_ALIAS("dmi:*:*Gateway*:*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
 
 module_init(acerhdf_init);
 module_exit(acerhdf_exit);
--- linux-ec2-2.6.32.orig/drivers/platform/x86/sony-laptop.c
+++ linux-ec2-2.6.32/drivers/platform/x86/sony-laptop.c
@@ -1390,6 +1390,10 @@
 	struct sonypi_event	*events;
 };
 
+struct sony_pic_quirk_entry {
+	u8				set_wwan_power;
+};
+
 struct sony_pic_dev {
 	struct acpi_device		*acpi_dev;
 	struct sony_pic_irq		*cur_irq;
@@ -1400,6 +1404,7 @@
 	struct sonypi_eventtypes	*event_types;
 	int                             (*handle_irq)(const u8, const u8);
 	int				model;
+	struct sony_pic_quirk_entry	*quirks;
 	u16				evport_offset;
 	u8				camera_power;
 	u8				bluetooth_power;
@@ -2828,6 +2833,12 @@
 	if (result)
 		goto err_remove_pf;
 
+	if (spic_dev.quirks && spic_dev.quirks->set_wwan_power) {
+		/*
+		 * Power isn't enabled by default.
+		 */
+		__sony_pic_set_wwanpower(1);
+	}
 	return 0;
 
 err_remove_pf:
@@ -2898,6 +2909,16 @@
 		},
 };
 
+static struct sony_pic_quirk_entry sony_pic_vaio_vgn = {
+	.set_wwan_power = 1,
+};
+
+static int dmi_matched(const struct dmi_system_id *dmi)
+{
+	spic_dev.quirks = dmi->driver_data;
+	return 0;
+}
+
 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
 	{
 		.ident = "Sony Vaio",
@@ -2912,6 +2933,8 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
 		},
+		.callback = dmi_matched,
+		.driver_data = &sony_pic_vaio_vgn,
 	},
 	{ }
 };
--- linux-ec2-2.6.32.orig/drivers/platform/x86/dell-laptop.c
+++ linux-ec2-2.6.32/drivers/platform/x86/dell-laptop.c
@@ -22,9 +22,15 @@
 #include <linux/rfkill.h>
 #include <linux/power_supply.h>
 #include <linux/acpi.h>
+#include <linux/input.h>
 #include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
+#define WLAN_SWITCH_MASK 0
+#define BT_SWITCH_MASK 1
+#define WWAN_SWITCH_MASK 2
+#define HW_SWITCH_SUPPORT 3
+#define HW_SWITCH_MASK 16
 
 /* This structure will be modified by the firmware when we enter
  * system management mode, hence the volatiles */
@@ -63,6 +69,13 @@
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *wwan_rfkill;
 
+/*
+ * RFkill status is maintained in software because the BIOS has an annoying
+ * habit of emitting a KEY_WLAN key press event before the BIOS state is updated, making
+ * dell_send_request() racy.
+ */
+static int   hw_switch_status;
+
 static const struct dmi_system_id __initdata dell_device_table[] = {
 	{
 		.ident = "Dell laptop",
@@ -71,9 +84,70 @@
 			DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
 		},
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/
+		},
+	},
+	{
+		.ident = "Dell Computer Corporation",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
+		},
+	},
 	{ }
 };
 
+static struct dmi_system_id __devinitdata dell_blacklist[] = {
+	/* BIOS always returns HW switch disabled */
+	{
+		.ident = "Dell Vostro 1720",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
+		},
+	},
+	/* Supported by compal-laptop */
+	{
+		.ident = "Dell Mini 9",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
+		},
+	},
+	{
+		.ident = "Dell Mini 10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
+		},
+	},
+	{
+		.ident = "Dell Mini 10v",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
+		},
+	},
+	{
+		.ident = "Dell Inspiron 11z",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
+		},
+	},
+	{
+		.ident = "Dell Mini 12",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
+		},
+	},
+	{}
+};
+
 static void parse_da_table(const struct dmi_header *dm)
 {
 	/* Final token is a terminator, so we don't want to copy it */
@@ -180,10 +254,12 @@
 	int disable = blocked ? 1 : 0;
 	unsigned long radio = (unsigned long)data;
 
-	memset(&buffer, 0, sizeof(struct calling_interface_buffer));
-	buffer.input[0] = (1 | (radio<<8) | (disable << 16));
-	dell_send_request(&buffer, 17, 11);
-
+	if (!(hw_switch_status & BIT(radio-1)) || !(hw_switch_status & BIT(HW_SWITCH_MASK)) || \
+			!(hw_switch_status & BIT(HW_SWITCH_SUPPORT))) {
+		memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+		buffer.input[0] = (1 | (radio<<8) | (disable << 16));
+		dell_send_request(&buffer, 17, 11);
+	}
 	return 0;
 }
 
@@ -191,14 +267,33 @@
 {
 	struct calling_interface_buffer buffer;
 	int status;
-	int bit = (unsigned long)data + 16;
+	int bit = (unsigned long)data - 1;
 
 	memset(&buffer, 0, sizeof(struct calling_interface_buffer));
 	dell_send_request(&buffer, 17, 11);
 	status = buffer.output[1];
 
-	if (status & BIT(bit))
-		rfkill_set_hw_state(rfkill, !!(status & BIT(16)));
+	hw_switch_status |= (status & BIT(0)) << BIT(HW_SWITCH_SUPPORT);
+	hw_switch_status |= (status & BIT(HW_SWITCH_MASK)) ^ BIT(HW_SWITCH_MASK);
+
+	/* HW switch control not supported
+	   explicitly set it to all 3 as they'll change in unison then */
+	if (!(status & BIT(0)))
+		hw_switch_status |= BIT(WLAN_SWITCH_MASK) | BIT(BT_SWITCH_MASK) | (WWAN_SWITCH_MASK);
+	else {
+		/* rerun the query to see what is really supported */
+		memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+		buffer.input[0] = 2;
+		dell_send_request(&buffer, 17, 11);
+		status = buffer.output[1];
+
+		hw_switch_status |= status & BIT(bit);
+	}
+
+	if (hw_switch_status & BIT(bit))
+		rfkill_set_hw_state(rfkill, hw_switch_status & BIT(HW_SWITCH_MASK));
+	else
+		rfkill_set_hw_state(rfkill, 0);
 }
 
 static const struct rfkill_ops dell_rfkill_ops = {
@@ -206,11 +301,38 @@
 	.query = dell_rfkill_query,
 };
 
+/*
+ * Called for each KEY_WLAN key press event. Note that a physical
+ * rf-kill switch change also causes the BIOS to emit a KEY_WLAN.
+ *
+ * dell_rfkill_set may block, so schedule it on a worker thread.
+ */
+static void dell_rfkill_update(struct work_struct *work)
+{
+	hw_switch_status ^= BIT(HW_SWITCH_MASK);
+	if (wifi_rfkill && (hw_switch_status & BIT(WLAN_SWITCH_MASK))) {
+		rfkill_set_hw_state(wifi_rfkill, hw_switch_status & BIT(HW_SWITCH_MASK));
+		dell_rfkill_set((void*)1, rfkill_blocked(wifi_rfkill));
+	}
+
+	if (bluetooth_rfkill && (hw_switch_status & BIT(BT_SWITCH_MASK))) {
+		rfkill_set_hw_state(bluetooth_rfkill, hw_switch_status & BIT(HW_SWITCH_MASK));
+		dell_rfkill_set((void*)2, rfkill_blocked(bluetooth_rfkill));
+	}
+
+	if (wwan_rfkill && (hw_switch_status & BIT(WWAN_SWITCH_MASK))) {
+		rfkill_set_hw_state(wwan_rfkill, hw_switch_status & BIT(HW_SWITCH_MASK));
+		dell_rfkill_set((void*)3, rfkill_blocked(wwan_rfkill));
+	}
+}
+DECLARE_WORK(dell_rfkill_update_work, &dell_rfkill_update);
+
 static int dell_setup_rfkill(void)
 {
 	struct calling_interface_buffer buffer;
 	int status;
 	int ret;
+	hw_switch_status = 0;
 
 	memset(&buffer, 0, sizeof(struct calling_interface_buffer));
 	dell_send_request(&buffer, 17, 11);
@@ -310,6 +432,92 @@
 	.update_status  = dell_send_intensity,
 };
 
+static const struct input_device_id dell_input_ids[] = {
+	{
+		.bustype = 0x11,
+		.vendor = 0x01,
+		.product = 0x01,
+		.version = 0xab41,
+		.flags = INPUT_DEVICE_ID_MATCH_BUS |
+			 INPUT_DEVICE_ID_MATCH_VENDOR |
+			 INPUT_DEVICE_ID_MATCH_PRODUCT |
+			 INPUT_DEVICE_ID_MATCH_VERSION
+	},
+	{ },
+};
+
+static bool dell_input_filter(struct input_handle *handle, unsigned int type,
+			     unsigned int code, int value)
+{
+	if (type == EV_KEY && code == KEY_WLAN && value == 1) {
+		if (!schedule_work(&dell_rfkill_update_work))
+			printk(KERN_NOTICE "rfkill switch handling already "
+					   "scheduled, dropping this event\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static void dell_input_event(struct input_handle *handle, unsigned int type,
+			     unsigned int code, int value)
+{
+}
+
+static int dell_input_connect(struct input_handler *handler,
+			      struct input_dev *dev,
+			      const struct input_device_id *id)
+{
+	struct input_handle *handle;
+	int error;
+
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
+
+	handle->dev = dev;
+	handle->handler = handler;
+	handle->name = "dell-laptop";
+
+	error = input_register_handle(handle);
+	if (error)
+		goto err_free_handle;
+
+	error = input_open_device(handle);
+	if (error)
+		goto err_unregister_handle;
+
+	error = input_filter_device(handle);
+	if (error)
+		goto err_close_handle;
+
+	return 0;
+
+err_close_handle:
+	input_close_device(handle);
+err_unregister_handle:
+	input_unregister_handle(handle);
+err_free_handle:
+	kfree(handle);
+	return error;
+}
+
+static void dell_input_disconnect(struct input_handle *handle)
+{
+	input_close_device(handle);
+	input_unregister_handle(handle);
+	kfree(handle);
+}
+
+static struct input_handler dell_input_handler = {
+	.name = "dell-laptop",
+	.filter = dell_input_filter,
+	.event = dell_input_event,
+	.connect = dell_input_connect,
+	.disconnect = dell_input_disconnect,
+	.id_table = dell_input_ids,
+};
+
 static int __init dell_init(void)
 {
 	struct calling_interface_buffer buffer;
@@ -319,6 +527,12 @@
 	if (!dmi_check_system(dell_device_table))
 		return -ENODEV;
 
+	if (dmi_check_system(dell_blacklist)) {
+		printk(KERN_INFO "dell-laptop: Blacklisted hardware detected - "
+				"not loading\n");
+		return -ENODEV;
+	}
+
 	dmi_walk(find_tokens, NULL);
 
 	if (!da_tokens)  {
@@ -333,6 +547,10 @@
 		goto out;
 	}
 
+	if (input_register_handler(&dell_input_handler))
+		printk(KERN_INFO
+		       "dell-laptop: Could not register input filter\n");
+
 #ifdef CONFIG_ACPI
 	/* In the event of an ACPI backlight being available, don't
 	 * register the platform controller.
@@ -388,6 +606,7 @@
 		rfkill_unregister(bluetooth_rfkill);
 	if (wwan_rfkill)
 		rfkill_unregister(wwan_rfkill);
+	input_unregister_handler(&dell_input_handler);
 }
 
 module_init(dell_init);
@@ -397,3 +616,5 @@
 MODULE_DESCRIPTION("Dell laptop driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
+MODULE_ALIAS("dmi:*svnDellInc.:*:ct9:*");
+MODULE_ALIAS("dmi:*svnDellComputerCorporation.:*:ct8:*");
--- linux-ec2-2.6.32.orig/drivers/platform/x86/asus_acpi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/asus_acpi.c
@@ -1001,14 +1001,8 @@
 	struct proc_dir_entry *proc;
 	mode_t mode;
 
-	/*
-	 * If parameter uid or gid is not changed, keep the default setting for
-	 * our proc entries (-rw-rw-rw-) else, it means we care about security,
-	 * and then set to -rw-rw----
-	 */
-
 	if ((asus_uid == 0) && (asus_gid == 0)) {
-		mode = S_IFREG | S_IRUGO | S_IWUGO;
+		mode = S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP;
 	} else {
 		mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
 		printk(KERN_WARNING "  asus_uid and asus_gid parameters are "
--- linux-ec2-2.6.32.orig/drivers/platform/x86/Kconfig
+++ linux-ec2-2.6.32/drivers/platform/x86/Kconfig
@@ -233,6 +233,29 @@
 
 	  If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
 
+config THINKPAD_ACPI_ALSA_SUPPORT
+	bool "Console audio control ALSA interface"
+	depends on THINKPAD_ACPI
+	depends on SND
+	depends on SND = y || THINKPAD_ACPI = SND
+	default y
+	---help---
+	  Enables monitoring of the built-in console audio output control
+	  (headphone and speakers), which is operated by the mute and (in
+	  some ThinkPad models) volume hotkeys.
+
+	  If this option is enabled, ThinkPad-ACPI will export an ALSA card
+	  with a single read-only mixer control, which should be used for
+	  on-screen-display feedback purposes by the Desktop Environment.
+
+	  Optionally, the driver will also allow software control (the
+	  ALSA mixer will be made read-write).  Please refer to the driver
+	  documentation for details.
+
+	  All IBM models have both volume and mute control.  Newer Lenovo
+	  models only have mute control (the volume hotkeys are just normal
+	  keys and volume control is done through the main HDA mixer).
+
 config THINKPAD_ACPI_DEBUGFACILITIES
 	bool "Maintainer debug facilities"
 	depends on THINKPAD_ACPI
--- linux-ec2-2.6.32.orig/drivers/platform/x86/hp-wmi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/hp-wmi.c
@@ -334,8 +334,13 @@
 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
 	static struct key_entry *key;
 	union acpi_object *obj;
+	acpi_status status;
 
-	wmi_get_event_data(value, &response);
+	status = wmi_get_event_data(value, &response);
+	if (status != AE_OK) {
+		printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status);
+		return;
+	}
 
 	obj = (union acpi_object *)response.pointer;
 
@@ -377,6 +382,8 @@
 			       eventcode);
 	} else
 		printk(KERN_INFO "HP WMI: Unknown response received\n");
+
+	kfree(obj);
 }
 
 static int __init hp_wmi_input_setup(void)
--- linux-ec2-2.6.32.orig/drivers/platform/x86/toshiba_acpi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/toshiba_acpi.c
@@ -28,13 +28,28 @@
  *		engineering the Windows drivers
  *	Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
  *	Rob Miller - TV out and hotkeys help
+ *      Daniel Silverstone - Punting of hotkeys via acpi using a thread    	
  *
+ *  PLEASE NOTE
+ *
+ *  This is an experimental version of toshiba_acpi which includes emulation
+ *  of the original toshiba driver's /proc/toshiba and /dev/toshiba,
+ *  allowing Toshiba userspace utilities to work.  The relevant code was
+ *  based on toshiba.c (copyright 1996-2001 Jonathan A. Buzzard) and
+ *  incorporated into this driver with help from Gintautas Miliauskas,
+ *  Charles Schwieters, and Christoph Burger-Scheidlin.
+ *
+ *  Caveats:
+ *      * hotkey status in /proc/toshiba is not implemented
+ *      * to make accesses to /dev/toshiba load this driver instead of
+ *          the original driver, you will have to modify your module
+ *          auto-loading configuration
  *
  *  TODO
  *
  */
 
-#define TOSHIBA_ACPI_VERSION	"0.19"
+#define TOSHIBA_ACPI_VERSION	"0.19-dev-acpikeys"
 #define PROC_INTERFACE_VERSION	1
 
 #include <linux/kernel.h>
@@ -42,9 +57,15 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/toshiba.h>
+#include <asm/io.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
+#include <linux/input-polldev.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 
@@ -356,6 +377,11 @@
 static int force_fan;
 static int last_key_event;
 static int key_event_valid;
+static int hotkeys_over_acpi = 1;
+static int hotkeys_check_per_sec = 2;
+
+module_param(hotkeys_over_acpi, uint, 0400);
+module_param(hotkeys_check_per_sec, uint, 0400);
 
 typedef struct _ProcItem {
 	const char *name;
@@ -583,27 +609,34 @@
 	u32 hci_result;
 	u32 value;
 
-	if (!key_event_valid) {
-		hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
-		if (hci_result == HCI_SUCCESS) {
-			key_event_valid = 1;
-			last_key_event = value;
-		} else if (hci_result == HCI_EMPTY) {
-			/* better luck next time */
-		} else if (hci_result == HCI_NOT_SUPPORTED) {
-			/* This is a workaround for an unresolved issue on
-			 * some machines where system events sporadically
-			 * become disabled. */
-			hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
-			printk(MY_NOTICE "Re-enabled hotkeys\n");
-		} else {
-			printk(MY_ERR "Error reading hotkey status\n");
-			goto end;
+	if (!hotkeys_over_acpi) {
+		if (!key_event_valid) {
+			hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+			if (hci_result == HCI_SUCCESS) {
+				key_event_valid = 1;
+				last_key_event = value;
+			} else if (hci_result == HCI_EMPTY) {
+				/* better luck next time */
+			} else if (hci_result == HCI_NOT_SUPPORTED) {
+				/* This is a workaround for an
+				 * unresolved issue on some machines
+				 * where system events sporadically
+				 * become disabled. */
+				hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+				printk(MY_NOTICE "Re-enabled hotkeys\n");
+			} else {
+				printk(MY_ERR "Error reading hotkey status\n");
+				goto end;
+			}
 		}
+	} else {
+		key_event_valid = 0;
+		last_key_event = 0;
 	}
 
 	p += sprintf(p, "hotkey_ready:            %d\n", key_event_valid);
 	p += sprintf(p, "hotkey:                  0x%04x\n", last_key_event);
+	p += sprintf(p, "hotkeys_via_acpi:        %d\n", hotkeys_over_acpi);
 
       end:
 	return p;
@@ -630,6 +663,191 @@
 	return p;
 }
 
+/* /dev/toshiba and /proc/toshiba handlers {{{
+ *
+ * ISSUE: lots of magic numbers and mysterious code
+ */
+
+#define TOSH_MINOR_DEV		181
+#define OLD_PROC_TOSHIBA	"toshiba"
+
+static int
+tosh_acpi_bridge(SMMRegisters* regs)
+{
+	acpi_status status;
+
+	/* assert(sizeof(SMMRegisters) == sizeof(u32)*HCI_WORDS); */
+	status = hci_raw((u32*)regs, (u32*)regs);
+	if (status == AE_OK && (regs->eax & 0xff00) == HCI_SUCCESS)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int
+tosh_ioctl(struct inode* ip, struct file* fp, unsigned int cmd,
+	unsigned long arg)
+{
+	SMMRegisters regs;
+	unsigned short ax,bx;
+	int err;
+
+	if ((!arg) || (cmd != TOSH_SMM))
+		return -EINVAL;
+
+	if (copy_from_user(&regs, (SMMRegisters*)arg, sizeof(SMMRegisters)))
+		return -EFAULT;
+
+	ax = regs.eax & 0xff00;
+	bx = regs.ebx & 0xffff;
+
+	/* block HCI calls to read/write memory & PCI devices */
+	if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069))
+		return -EINVAL;
+
+	err = tosh_acpi_bridge(&regs);
+
+	if (copy_to_user((SMMRegisters*)arg, &regs, sizeof(SMMRegisters)))
+		return -EFAULT;
+
+	return err;
+}
+
+static int
+tosh_get_machine_id(void __iomem *bios)
+{
+	int id;
+	unsigned short bx,cx;
+	unsigned long address;
+
+	id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
+
+	/* do we have a SCTTable machine identication number on our hands */
+	if (id==0xfc2f) {
+		bx = 0xe6f5; /* cheat */
+		/* now twiddle with our pointer a bit */
+		address = 0x00000000 + bx;
+		cx = readw(bios + address);
+		address = 0x00000009 + bx + cx;
+		cx = readw(bios + address);
+		address = 0x0000000a + cx;
+		cx = readw(bios + address);
+		/* now construct our machine identification number */
+		id = ((cx & 0xff)<<8)+((cx & 0xff00)>>8);
+	}
+
+	return id;
+}
+
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+
+static struct file_operations tosh_fops = {
+	.owner = THIS_MODULE,
+	.ioctl = tosh_ioctl
+};
+
+static struct miscdevice tosh_device = {
+	TOSH_MINOR_DEV,
+	"toshiba",
+	&tosh_fops
+};
+
+static void
+setup_tosh_info(void __iomem *bios)
+{
+	int major, minor;
+	int day, month, year;
+
+	tosh_id = tosh_get_machine_id(bios);
+
+	/* get the BIOS version */
+	major = readb(bios + 0xe009)-'0';
+	minor = ((readb(bios + 0xe00b)-'0')*10)+(readb(bios + 0xe00c)-'0');
+	tosh_bios = (major*0x100)+minor;
+
+	/* get the BIOS date */
+	day = ((readb(bios + 0xfff5)-'0')*10)+(readb(bios + 0xfff6)-'0');
+	month = ((readb(bios + 0xfff8)-'0')*10)+(readb(bios + 0xfff9)-'0');
+	year = ((readb(bios + 0xfffb)-'0')*10)+(readb(bios + 0xfffc)-'0');
+	tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
+		| ((day & 0x1f)<<1);
+}
+
+/* /proc/toshiba read handler */
+static int
+tosh_proc_show(struct seq_file *m, void *v)
+{
+	/* TODO: tosh_fn_status() */
+	int key = 0;
+
+	/* Format:
+	 *    0) Linux driver version (this will change if format changes)
+	 *    1) Machine ID
+	 *    2) SCI version
+	 *    3) BIOS version (major, minor)
+	 *    4) BIOS date (in SCI date format)
+	 *    5) Fn Key status
+	 */
+
+	seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
+		tosh_id,
+		(tosh_sci & 0xff00)>>8,
+		tosh_sci & 0xff,
+		(tosh_bios & 0xff00)>>8,
+		tosh_bios & 0xff,
+		tosh_date,
+		key);
+
+	return 0;
+}
+
+static int tosh_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tosh_proc_show, NULL);
+}
+
+static const struct file_operations tosh_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tosh_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init
+old_driver_emulation_init(void)
+{
+	int status;
+	void __iomem *bios = ioremap(0xf0000, 0x10000);
+	if (!bios)
+		return -ENOMEM;
+
+	if ((status = misc_register(&tosh_device))) {
+		printk(MY_ERR "failed to register misc device %d (\"%s\")\n",
+			tosh_device.minor, tosh_device.name);
+		return status;
+	}
+
+	setup_tosh_info(bios);
+	proc_create(OLD_PROC_TOSHIBA, 0, NULL, &tosh_proc_fops);
+
+	iounmap(bios);
+
+	return 0;
+}
+
+static void __exit
+old_driver_emulation_exit(void)
+{
+	remove_proc_entry(OLD_PROC_TOSHIBA, NULL);
+	misc_deregister(&tosh_device);
+}
+
+/* }}} end of /dev/toshiba and /proc/toshiba handlers */
+
 /* proc and module init
  */
 
@@ -676,6 +894,133 @@
         .update_status  = set_lcd_status,
 };
 
+static struct semaphore thread_sem;
+static int thread_should_die;
+
+static struct acpi_device *threaded_device = 0;
+
+static void thread_deliver_button_event(u32 value)
+{
+	if (!threaded_device) return;
+	if( value == 0x0100 ) {
+		/* Ignore FN on its own */
+	} else if( value & 0x80 ) {
+		acpi_bus_generate_proc_event( threaded_device, 1, value & ~0x80 );
+	} else {
+		acpi_bus_generate_proc_event( threaded_device, 0, value );
+	}
+}
+
+static int toshiba_acpi_thread(void *data)
+{
+	int dropped = 0;
+	u32 hci_result, value;
+
+	daemonize("ktoshkeyd");
+	set_user_nice(current, 4);
+	thread_should_die = 0;
+
+	up(&thread_sem);
+
+	do {
+		/* In case we get stuck; we can rmmod the module here */
+		if (thread_should_die)
+			break;
+
+		hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+		if (hci_result == HCI_SUCCESS) {
+			dropped++;
+		} else if (hci_result == HCI_EMPTY) {
+                         /* better luck next time */
+		} else if (hci_result == HCI_NOT_SUPPORTED) {
+			/* This is a workaround for an unresolved issue on
+			 * some machines where system events sporadically
+			 * become disabled. */
+			hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+			printk(MY_NOTICE "Re-enabled hotkeys\n");
+		}
+	} while (hci_result != HCI_EMPTY);
+
+	printk(MY_INFO "Dropped %d keys from the queue on startup\n", dropped);
+
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / hotkeys_check_per_sec);
+
+		if (thread_should_die)
+			break;
+
+		if (try_to_freeze())
+			continue;
+
+		do {
+			hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+			if (hci_result == HCI_SUCCESS) {
+				thread_deliver_button_event(value);
+			} else if (hci_result == HCI_EMPTY) {
+				/* better luck next time */
+			} else if (hci_result == HCI_NOT_SUPPORTED) {
+				/* This is a workaround for an
+				 * unresolved issue on some machines
+				 * where system events sporadically
+				 * become disabled. */
+				hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+				printk(MY_NOTICE "Re-enabled hotkeys\n");
+			}
+		} while (hci_result == HCI_SUCCESS);
+	}
+	set_user_nice(current, -20);	/* Become nasty so we are cleaned up
+					 * before the module exits making us oops */
+	up(&thread_sem);
+	return 0;
+}
+
+static int acpi_toshkeys_add (struct acpi_device *device)
+{
+	threaded_device = device;
+	strcpy(acpi_device_name(device), "Toshiba laptop hotkeys");
+	strcpy(acpi_device_class(device), "hkey");
+	return 0;
+}
+
+static int acpi_toshkeys_remove (struct acpi_device *device, int type)
+{
+	if (threaded_device == device)
+		threaded_device = 0;
+	return 0;
+}
+
+static const struct acpi_device_id acpi_toshkeys_ids[] = {
+	{ "TOS6200", 0 },
+	{ "TOS6207", 0 },
+	{ "TOS6208", 0 },
+ 	{"", 0}
+};
+
+static struct acpi_driver acpi_threaded_toshkeys = {
+	.name = "Toshiba laptop hotkeys driver",
+	.class = "hkey",
+	.ids = acpi_toshkeys_ids,
+	.ops = {
+		.add = acpi_toshkeys_add,
+		.remove = acpi_toshkeys_remove,
+	},
+};
+
+static int __init init_threaded_acpi(void)
+{
+        acpi_status result = AE_OK;
+        result = acpi_bus_register_driver(&acpi_threaded_toshkeys);
+        if( result < 0 )
+                printk(MY_ERR "Registration of toshkeys acpi device failed\n");
+        return result;
+}
+
+static void kill_threaded_acpi(void)
+{
+        acpi_bus_unregister_driver(&acpi_threaded_toshkeys);
+}
+
 static void toshiba_acpi_exit(void)
 {
 	if (toshiba_acpi.bt_rfk) {
@@ -686,11 +1031,19 @@
 	if (toshiba_backlight_device)
 		backlight_device_unregister(toshiba_backlight_device);
 
+	if (hotkeys_over_acpi) {
+		thread_should_die = 1;
+		down(&thread_sem);
+		kill_threaded_acpi();
+	}
+
 	remove_device();
 
 	if (toshiba_proc_dir)
 		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 
+	old_driver_emulation_exit();
+
 	platform_device_unregister(toshiba_acpi.p_dev);
 
 	return;
@@ -730,6 +1083,9 @@
 		return ret;
 	}
 
+	if ((ret = old_driver_emulation_init()))
+		return ret;
+
 	force_fan = 0;
 	key_event_valid = 0;
 
@@ -762,6 +1118,26 @@
 	}
         toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 
+	if (hotkeys_over_acpi && ACPI_SUCCESS(status)) {
+		printk(MY_INFO "Toshiba hotkeys are sent as ACPI events\n");
+		if (hotkeys_check_per_sec < 1)
+			hotkeys_check_per_sec = 1;
+		if (hotkeys_check_per_sec > 10)
+			hotkeys_check_per_sec = 10;
+		printk(MY_INFO "ktoshkeyd will check %d time%s per second\n",
+			hotkeys_check_per_sec, hotkeys_check_per_sec==1?"":"s");
+		if (init_threaded_acpi() >= 0) {
+			init_MUTEX_LOCKED(&thread_sem);
+			kernel_thread(toshiba_acpi_thread, NULL, CLONE_KERNEL);
+			down(&thread_sem);
+		} else {
+			remove_device();
+			remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+			status = AE_ERROR;
+			printk(MY_INFO "ktoshkeyd initialisation failed. Refusing to load module\n");
+		}
+	}
+
 	/* Register rfkill switch for Bluetooth */
 	if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
 		toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
--- linux-ec2-2.6.32.orig/drivers/platform/x86/acer-wmi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/acer-wmi.c
@@ -90,7 +90,7 @@
  */
 #define AMW0_GUID1		"67C3371D-95A3-4C37-BB61-DD47B491DAAB"
 #define AMW0_GUID2		"431F16ED-0C2B-444C-B267-27DEB140CF9C"
-#define WMID_GUID1		"6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"
+#define WMID_GUID1		"6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
 #define WMID_GUID2		"95764E09-FB56-4e83-B31A-37761F60994A"
 
 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
@@ -1065,7 +1065,7 @@
 			return -EINVAL;
 	return count;
 }
-static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg,
+static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
 	set_bool_threeg);
 
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
--- linux-ec2-2.6.32.orig/drivers/platform/x86/thinkpad_acpi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/thinkpad_acpi.c
@@ -21,8 +21,8 @@
  *  02110-1301, USA.
  */
 
-#define TPACPI_VERSION "0.23"
-#define TPACPI_SYSFS_VERSION 0x020500
+#define TPACPI_VERSION "0.24"
+#define TPACPI_SYSFS_VERSION 0x020700
 
 /*
  *  Changelog:
@@ -61,6 +61,7 @@
 
 #include <linux/nvram.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/sysfs.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
@@ -76,6 +77,10 @@
 #include <linux/jiffies.h>
 #include <linux/workqueue.h>
 
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
 #include <acpi/acpi_drivers.h>
 
 #include <linux/pci_ids.h>
@@ -231,6 +236,7 @@
 #define TPACPI_DBG_HKEY		0x0008
 #define TPACPI_DBG_FAN		0x0010
 #define TPACPI_DBG_BRGHT	0x0020
+#define TPACPI_DBG_MIXER	0x0040
 
 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
 #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -256,7 +262,7 @@
 struct ibm_struct {
 	char *name;
 
-	int (*read) (char *);
+	int (*read) (struct seq_file *);
 	int (*write) (char *);
 	void (*exit) (void);
 	void (*resume) (void);
@@ -280,6 +286,7 @@
 	char param[32];
 
 	int (*init) (struct ibm_init_struct *);
+	mode_t base_procfs_mode;
 	struct ibm_struct *data;
 };
 
@@ -298,6 +305,7 @@
 	u32 fan_ctrl_status_undef:1;
 	u32 second_fan:1;
 	u32 beep_needs_two_args:1;
+	u32 mixer_no_level_control:1;
 	u32 input_device_registered:1;
 	u32 platform_drv_registered:1;
 	u32 platform_drv_attrs_registered:1;
@@ -309,6 +317,7 @@
 
 static struct {
 	u16 hotkey_mask_ff:1;
+	u16 volume_ctrl_forbidden:1;
 } tp_warned;
 
 struct thinkpad_id_data {
@@ -425,6 +434,12 @@
 	  .ec = TPACPI_MATCH_ANY,		\
 	  .quirks = (__quirk) }
 
+#define TPACPI_QEC_LNV(__id1, __id2, __quirk)	\
+	{ .vendor = PCI_VENDOR_ID_LENOVO,	\
+	  .bios = TPACPI_MATCH_ANY,		\
+	  .ec = TPID(__id1, __id2),		\
+	  .quirks = (__quirk) }
+
 struct tpacpi_quirk {
 	unsigned int vendor;
 	u16 bios;
@@ -776,36 +791,25 @@
  ****************************************************************************
  ****************************************************************************/
 
-static int dispatch_procfs_read(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
+static int dispatch_proc_show(struct seq_file *m, void *v)
 {
-	struct ibm_struct *ibm = data;
-	int len;
+	struct ibm_struct *ibm = m->private;
 
 	if (!ibm || !ibm->read)
 		return -EINVAL;
+	return ibm->read(m);
+}
 
-	len = ibm->read(page);
-	if (len < 0)
-		return len;
-
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
+static int dispatch_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dispatch_proc_show, PDE(inode)->data);
 }
 
-static int dispatch_procfs_write(struct file *file,
+static ssize_t dispatch_proc_write(struct file *file,
 			const char __user *userbuf,
-			unsigned long count, void *data)
+			size_t count, loff_t *pos)
 {
-	struct ibm_struct *ibm = data;
+	struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
 	char *kernbuf;
 	int ret;
 
@@ -834,6 +838,15 @@
 	return ret;
 }
 
+static const struct file_operations dispatch_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dispatch_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= dispatch_proc_write,
+};
+
 static char *next_cmd(char **cmds)
 {
 	char *start = *cmds;
@@ -1264,6 +1277,7 @@
 	struct tpacpi_rfk *atp_rfk;
 	int res;
 	bool sw_state = false;
+	bool hw_state;
 	int sw_status;
 
 	BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
@@ -1298,7 +1312,8 @@
 			rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
 		}
 	}
-	rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
+	hw_state = tpacpi_rfk_check_hwblock_state();
+	rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
 
 	res = rfkill_register(atp_rfk->rfkill);
 	if (res < 0) {
@@ -1311,6 +1326,9 @@
 	}
 
 	tpacpi_rfkill_switches[id] = atp_rfk;
+
+	printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
+		name, (sw_state || hw_state) ? "" : "un");
 	return 0;
 }
 
@@ -1383,12 +1401,10 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
+static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
 {
-	int len = 0;
-
 	if (id >= TPACPI_RFK_SW_MAX)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
 		int status;
 
@@ -1402,13 +1418,13 @@
 				return status;
 		}
 
-		len += sprintf(p + len, "status:\t\t%s\n",
+		seq_printf(m, "status:\t\t%s\n",
 				(status == TPACPI_RFK_RADIO_ON) ?
 					"enabled" : "disabled");
-		len += sprintf(p + len, "commands:\tenable, disable\n");
+		seq_printf(m, "commands:\tenable, disable\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
@@ -1655,7 +1671,7 @@
  * Table of recommended minimum BIOS versions
  *
  * Reasons for listing:
- *    1. Stable BIOS, listed because the unknown ammount of
+ *    1. Stable BIOS, listed because the unknown amount of
  *       bugs and bad ACPI behaviour on older versions
  *
  *    2. BIOS or EC fw with known bugs that trigger on Linux
@@ -1779,7 +1795,7 @@
 
 	TPV_QL1('7', '9',  'E', '3',  '5', '0'), /* T60/p */
 	TPV_QL1('7', 'C',  'D', '2',  '2', '2'), /* R60, R60i */
-	TPV_QL0('7', 'E',  'D', '0'),		 /* R60e, R60i */
+	TPV_QL1('7', 'E',  'D', '0',  '1', '5'), /* R60e, R60i */
 
 	/*      BIOS FW    BIOS VERS  EC FW     EC VERS */
 	TPV_QI2('1', 'W',  '9', '0',  '1', 'V', '2', '8'), /* R50e (1) */
@@ -1795,8 +1811,8 @@
 	TPV_QI1('7', '4',  '6', '4',  '2', '7'), /* X41 (0) */
 	TPV_QI1('7', '5',  '6', '0',  '2', '0'), /* X41t (0) */
 
-	TPV_QL0('7', 'B',  'D', '7'),		 /* X60/s */
-	TPV_QL0('7', 'J',  '3', '0'),		 /* X60t */
+	TPV_QL1('7', 'B',  'D', '7',  '4', '0'), /* X60/s */
+	TPV_QL1('7', 'J',  '3', '0',  '1', '3'), /* X60t */
 
 	/* (0) - older versions lack DMI EC fw string and functionality */
 	/* (1) - older versions known to lack functionality */
@@ -1886,14 +1902,11 @@
 	return 0;
 }
 
-static int thinkpad_acpi_driver_read(char *p)
+static int thinkpad_acpi_driver_read(struct seq_file *m)
 {
-	int len = 0;
-
-	len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC);
-	len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
-
-	return len;
+	seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
+	seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
+	return 0;
 }
 
 static struct ibm_struct thinkpad_acpi_driver_data = {
@@ -2073,6 +2086,7 @@
 
 static void tpacpi_driver_event(const unsigned int hkey_event);
 static void hotkey_driver_event(const unsigned int scancode);
+static void hotkey_poll_setup(const bool may_warn);
 
 /* HKEY.MHKG() return bits */
 #define TP_HOTKEY_TABLET_MASK (1 << 3)
@@ -2189,7 +2203,8 @@
 		       fwmask, hotkey_acpi_mask);
 	}
 
-	hotkey_mask_warn_incomplete_mask();
+	if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
+		hotkey_mask_warn_incomplete_mask();
 
 	return rc;
 }
@@ -2254,6 +2269,8 @@
 
 	rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
 							~hotkey_source_mask);
+	hotkey_poll_setup(true);
+
 	mutex_unlock(&hotkey_mutex);
 
 	return rc;
@@ -2538,7 +2555,7 @@
 }
 
 /* call with hotkey_mutex held */
-static void hotkey_poll_setup(bool may_warn)
+static void hotkey_poll_setup(const bool may_warn)
 {
 	const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
 	const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
@@ -2569,7 +2586,7 @@
 	}
 }
 
-static void hotkey_poll_setup_safe(bool may_warn)
+static void hotkey_poll_setup_safe(const bool may_warn)
 {
 	mutex_lock(&hotkey_mutex);
 	hotkey_poll_setup(may_warn);
@@ -2587,7 +2604,11 @@
 
 #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
 
-static void hotkey_poll_setup_safe(bool __unused)
+static void hotkey_poll_setup(const bool __unused)
+{
+}
+
+static void hotkey_poll_setup_safe(const bool __unused)
 {
 }
 
@@ -2597,16 +2618,11 @@
 {
 	switch (tpacpi_lifecycle) {
 	case TPACPI_LIFE_INIT:
-		/*
-		 * hotkey_init will call hotkey_poll_setup_safe
-		 * at the appropriate moment
-		 */
-		return 0;
-	case TPACPI_LIFE_EXITING:
-		return -EBUSY;
 	case TPACPI_LIFE_RUNNING:
 		hotkey_poll_setup_safe(false);
 		return 0;
+	case TPACPI_LIFE_EXITING:
+		return -EBUSY;
 	}
 
 	/* Should only happen if tpacpi_lifecycle is corrupt */
@@ -2617,7 +2633,7 @@
 static void hotkey_inputdev_close(struct input_dev *dev)
 {
 	/* disable hotkey polling when possible */
-	if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING &&
+	if (tpacpi_lifecycle != TPACPI_LIFE_EXITING &&
 	    !(hotkey_source_mask & hotkey_driver_mask))
 		hotkey_poll_setup_safe(false);
 }
@@ -3185,6 +3201,8 @@
 	int res, i;
 	int status;
 	int hkeyv;
+	bool radiosw_state  = false;
+	bool tabletsw_state = false;
 
 	unsigned long quirks;
 
@@ -3290,6 +3308,7 @@
 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
 	if (dbg_wlswemul) {
 		tp_features.hotkey_wlsw = 1;
+		radiosw_state = !!tpacpi_wlsw_emulstate;
 		printk(TPACPI_INFO
 			"radio switch emulation enabled\n");
 	} else
@@ -3297,6 +3316,7 @@
 	/* Not all thinkpads have a hardware radio switch */
 	if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
 		tp_features.hotkey_wlsw = 1;
+		radiosw_state = !!status;
 		printk(TPACPI_INFO
 			"radio switch found; radios are %s\n",
 			enabled(status, 0));
@@ -3308,11 +3328,11 @@
 	/* For X41t, X60t, X61t Tablets... */
 	if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
 		tp_features.hotkey_tablet = 1;
+		tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
 		printk(TPACPI_INFO
 			"possible tablet mode switch found; "
 			"ThinkPad in %s mode\n",
-			(status & TP_HOTKEY_TABLET_MASK)?
-				"tablet" : "laptop");
+			(tabletsw_state) ? "tablet" : "laptop");
 		res = add_to_attr_set(hotkey_dev_attributes,
 				&dev_attr_hotkey_tablet_mode.attr);
 	}
@@ -3347,16 +3367,14 @@
 			TPACPI_HOTKEY_MAP_SIZE);
 	}
 
-	set_bit(EV_KEY, tpacpi_inputdev->evbit);
-	set_bit(EV_MSC, tpacpi_inputdev->evbit);
-	set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
+	input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
 	tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
 	tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
 	tpacpi_inputdev->keycode = hotkey_keycode_map;
 	for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
 		if (hotkey_keycode_map[i] != KEY_RESERVED) {
-			set_bit(hotkey_keycode_map[i],
-				tpacpi_inputdev->keybit);
+			input_set_capability(tpacpi_inputdev, EV_KEY,
+						hotkey_keycode_map[i]);
 		} else {
 			if (i < sizeof(hotkey_reserved_mask)*8)
 				hotkey_reserved_mask |= 1 << i;
@@ -3364,12 +3382,14 @@
 	}
 
 	if (tp_features.hotkey_wlsw) {
-		set_bit(EV_SW, tpacpi_inputdev->evbit);
-		set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
+		input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
+		input_report_switch(tpacpi_inputdev,
+				    SW_RFKILL_ALL, radiosw_state);
 	}
 	if (tp_features.hotkey_tablet) {
-		set_bit(EV_SW, tpacpi_inputdev->evbit);
-		set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
+		input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
+		input_report_switch(tpacpi_inputdev,
+				    SW_TABLET_MODE, tabletsw_state);
 	}
 
 	/* Do not issue duplicate brightness change events to
@@ -3436,8 +3456,6 @@
 	tpacpi_inputdev->close = &hotkey_inputdev_close;
 
 	hotkey_poll_setup_safe(true);
-	tpacpi_send_radiosw_update();
-	tpacpi_input_send_tabletsw();
 
 	return 0;
 
@@ -3545,49 +3563,57 @@
 	}
 }
 
+static void thermal_dump_all_sensors(void);
+
 static bool hotkey_notify_thermal(const u32 hkey,
 				 bool *send_acpi_ev,
 				 bool *ignore_acpi_ev)
 {
+	bool known = true;
+
 	/* 0x6000-0x6FFF: thermal alarms */
 	*send_acpi_ev = true;
 	*ignore_acpi_ev = false;
 
 	switch (hkey) {
+	case TP_HKEY_EV_THM_TABLE_CHANGED:
+		printk(TPACPI_INFO
+			"EC reports that Thermal Table has changed\n");
+		/* recommended action: do nothing, we don't have
+		 * Lenovo ATM information */
+		return true;
 	case TP_HKEY_EV_ALARM_BAT_HOT:
 		printk(TPACPI_CRIT
 			"THERMAL ALARM: battery is too hot!\n");
 		/* recommended action: warn user through gui */
-		return true;
+		break;
 	case TP_HKEY_EV_ALARM_BAT_XHOT:
 		printk(TPACPI_ALERT
 			"THERMAL EMERGENCY: battery is extremely hot!\n");
 		/* recommended action: immediate sleep/hibernate */
-		return true;
+		break;
 	case TP_HKEY_EV_ALARM_SENSOR_HOT:
 		printk(TPACPI_CRIT
 			"THERMAL ALARM: "
 			"a sensor reports something is too hot!\n");
 		/* recommended action: warn user through gui, that */
 		/* some internal component is too hot */
-		return true;
+		break;
 	case TP_HKEY_EV_ALARM_SENSOR_XHOT:
 		printk(TPACPI_ALERT
 			"THERMAL EMERGENCY: "
 			"a sensor reports something is extremely hot!\n");
 		/* recommended action: immediate sleep/hibernate */
-		return true;
-	case TP_HKEY_EV_THM_TABLE_CHANGED:
-		printk(TPACPI_INFO
-			"EC reports that Thermal Table has changed\n");
-		/* recommended action: do nothing, we don't have
-		 * Lenovo ATM information */
-		return true;
+		break;
 	default:
 		printk(TPACPI_ALERT
 			 "THERMAL ALERT: unknown thermal alarm received\n");
-		return false;
+		known = false;
 	}
+
+	thermal_dump_all_sensors();
+
+	return known;
 }
 
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3635,13 +3661,19 @@
 			break;
 		case 3:
 			/* 0x3000-0x3FFF: bay-related wakeups */
-			if (hkey == TP_HKEY_EV_BAYEJ_ACK) {
+			switch (hkey) {
+			case TP_HKEY_EV_BAYEJ_ACK:
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "bay ejected\n");
 				hotkey_wakeup_hotunplug_complete_notify_change();
 				known_ev = true;
-			} else {
+				break;
+			case TP_HKEY_EV_OPTDRV_EJ:
+				/* FIXME: kick libata if SATA link offline */
+				known_ev = true;
+				break;
+			default:
 				known_ev = false;
 			}
 			break;
@@ -3730,14 +3762,13 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int hotkey_read(char *p)
+static int hotkey_read(struct seq_file *m)
 {
 	int res, status;
-	int len = 0;
 
 	if (!tp_features.hotkey) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
 
 	if (mutex_lock_killable(&hotkey_mutex))
@@ -3749,17 +3780,16 @@
 	if (res)
 		return res;
 
-	len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
+	seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
 	if (hotkey_all_mask) {
-		len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask);
-		len += sprintf(p + len,
-			       "commands:\tenable, disable, reset, <mask>\n");
+		seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
+		seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
 	} else {
-		len += sprintf(p + len, "mask:\t\tnot supported\n");
-		len += sprintf(p + len, "commands:\tenable, disable, reset\n");
+		seq_printf(m, "mask:\t\tnot supported\n");
+		seq_printf(m, "commands:\tenable, disable, reset\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static void hotkey_enabledisable_warn(bool enable)
@@ -3852,7 +3882,7 @@
 	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
 	TP_ACPI_BLUETOOTH_RADIOSSW	= 0x02,	/* Bluetooth radio enabled */
 	TP_ACPI_BLUETOOTH_RESUMECTRL	= 0x04,	/* Bluetooth state at resume:
-						   off / last state */
+						   0 = disable, 1 = enable */
 };
 
 enum {
@@ -3866,15 +3896,6 @@
 
 #define TPACPI_RFK_BLUETOOTH_SW_NAME	"tpacpi_bluetooth_sw"
 
-static void bluetooth_suspend(pm_message_t state)
-{
-	/* Try to make sure radio will resume powered off */
-	if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
-		   TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
-		vdbg_printk(TPACPI_DBG_RFKILL,
-			"bluetooth power down on resume request failed\n");
-}
-
 static int bluetooth_get_status(void)
 {
 	int status;
@@ -3907,9 +3928,9 @@
 	}
 #endif
 
-	/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
 	if (state == TPACPI_RFK_RADIO_ON)
-		status = TP_ACPI_BLUETOOTH_RADIOSSW;
+		status = TP_ACPI_BLUETOOTH_RADIOSSW
+			  | TP_ACPI_BLUETOOTH_RESUMECTRL;
 	else
 		status = 0;
 
@@ -4035,9 +4056,9 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int bluetooth_read(char *p)
+static int bluetooth_read(struct seq_file *m)
 {
-	return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p);
+	return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
 }
 
 static int bluetooth_write(char *buf)
@@ -4050,7 +4071,6 @@
 	.read = bluetooth_read,
 	.write = bluetooth_write,
 	.exit = bluetooth_exit,
-	.suspend = bluetooth_suspend,
 	.shutdown = bluetooth_shutdown,
 };
 
@@ -4063,20 +4083,11 @@
 	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
 	TP_ACPI_WANCARD_RADIOSSW	= 0x02,	/* Wan radio enabled */
 	TP_ACPI_WANCARD_RESUMECTRL	= 0x04,	/* Wan state at resume:
-						   off / last state */
+						   0 = disable, 1 = enable */
 };
 
 #define TPACPI_RFK_WWAN_SW_NAME		"tpacpi_wwan_sw"
 
-static void wan_suspend(pm_message_t state)
-{
-	/* Try to make sure radio will resume powered off */
-	if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
-		   TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
-		vdbg_printk(TPACPI_DBG_RFKILL,
-			"WWAN power down on resume request failed\n");
-}
-
 static int wan_get_status(void)
 {
 	int status;
@@ -4109,9 +4120,9 @@
 	}
 #endif
 
-	/* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
 	if (state == TPACPI_RFK_RADIO_ON)
-		status = TP_ACPI_WANCARD_RADIOSSW;
+		status = TP_ACPI_WANCARD_RADIOSSW
+			 | TP_ACPI_WANCARD_RESUMECTRL;
 	else
 		status = 0;
 
@@ -4236,9 +4247,9 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int wan_read(char *p)
+static int wan_read(struct seq_file *m)
 {
-	return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p);
+	return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
 }
 
 static int wan_write(char *buf)
@@ -4251,7 +4262,6 @@
 	.read = wan_read,
 	.write = wan_write,
 	.exit = wan_exit,
-	.suspend = wan_suspend,
 	.shutdown = wan_shutdown,
 };
 
@@ -4614,16 +4624,19 @@
 	/* not reached */
 }
 
-static int video_read(char *p)
+static int video_read(struct seq_file *m)
 {
 	int status, autosw;
-	int len = 0;
 
 	if (video_supported == TPACPI_VIDEO_NONE) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
 
+	/* Even reads can crash X.org, so... */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	status = video_outputsw_get();
 	if (status < 0)
 		return status;
@@ -4632,20 +4645,20 @@
 	if (autosw < 0)
 		return autosw;
 
-	len += sprintf(p + len, "status:\t\tsupported\n");
-	len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
-	len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
+	seq_printf(m, "status:\t\tsupported\n");
+	seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
+	seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
 	if (video_supported == TPACPI_VIDEO_NEW)
-		len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
-	len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
-	len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
-	len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
+		seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
+	seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
+	seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
+	seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
 	if (video_supported == TPACPI_VIDEO_NEW)
-		len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
-	len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
-	len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
+		seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
+	seq_printf(m, "commands:\tauto_enable, auto_disable\n");
+	seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
 
-	return len;
+	return 0;
 }
 
 static int video_write(char *buf)
@@ -4657,6 +4670,10 @@
 	if (video_supported == TPACPI_VIDEO_NONE)
 		return -ENODEV;
 
+	/* Even reads can crash X.org, let alone writes... */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	enable = 0;
 	disable = 0;
 
@@ -4837,25 +4854,24 @@
 		flush_workqueue(tpacpi_wq);
 }
 
-static int light_read(char *p)
+static int light_read(struct seq_file *m)
 {
-	int len = 0;
 	int status;
 
 	if (!tp_features.light) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	} else if (!tp_features.light_status) {
-		len += sprintf(p + len, "status:\t\tunknown\n");
-		len += sprintf(p + len, "commands:\ton, off\n");
+		seq_printf(m, "status:\t\tunknown\n");
+		seq_printf(m, "commands:\ton, off\n");
 	} else {
 		status = light_get_status();
 		if (status < 0)
 			return status;
-		len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
-		len += sprintf(p + len, "commands:\ton, off\n");
+		seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
+		seq_printf(m, "commands:\ton, off\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int light_write(char *buf)
@@ -4933,20 +4949,18 @@
 	device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
 }
 
-static int cmos_read(char *p)
+static int cmos_read(struct seq_file *m)
 {
-	int len = 0;
-
 	/* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
 	   R30, R31, T20-22, X20-21 */
 	if (!cmos_handle)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
-		len += sprintf(p + len, "status:\t\tsupported\n");
-		len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
+		seq_printf(m, "status:\t\tsupported\n");
+		seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int cmos_write(char *buf)
@@ -5321,15 +5335,13 @@
 	((s) == TPACPI_LED_OFF ? "off" : \
 		((s) == TPACPI_LED_ON ? "on" : "blinking"))
 
-static int led_read(char *p)
+static int led_read(struct seq_file *m)
 {
-	int len = 0;
-
 	if (!led_supported) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
-	len += sprintf(p + len, "status:\t\tsupported\n");
+	seq_printf(m, "status:\t\tsupported\n");
 
 	if (led_supported == TPACPI_LED_570) {
 		/* 570 */
@@ -5338,15 +5350,15 @@
 			status = led_get_status(i);
 			if (status < 0)
 				return -EIO;
-			len += sprintf(p + len, "%d:\t\t%s\n",
+			seq_printf(m, "%d:\t\t%s\n",
 				       i, str_led_status(status));
 		}
 	}
 
-	len += sprintf(p + len, "commands:\t"
+	seq_printf(m, "commands:\t"
 		       "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
 
-	return len;
+	return 0;
 }
 
 static int led_write(char *buf)
@@ -5419,18 +5431,16 @@
 	return (beep_handle)? 0 : 1;
 }
 
-static int beep_read(char *p)
+static int beep_read(struct seq_file *m)
 {
-	int len = 0;
-
 	if (!beep_handle)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
-		len += sprintf(p + len, "status:\t\tsupported\n");
-		len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
+		seq_printf(m, "status:\t\tsupported\n");
+		seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int beep_write(char *buf)
@@ -5483,8 +5493,11 @@
 	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
 	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
 	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
+
+	TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
 };
 
+
 #define TPACPI_MAX_THERMAL_SENSORS 16	/* Max thermal sensors supported */
 struct ibm_thermal_sensors_struct {
 	s32 temp[TPACPI_MAX_THERMAL_SENSORS];
@@ -5574,6 +5587,28 @@
 	return n;
 }
 
+static void thermal_dump_all_sensors(void)
+{
+	int n, i;
+	struct ibm_thermal_sensors_struct t;
+
+	n = thermal_get_sensors(&t);
+	if (n <= 0)
+		return;
+
+	printk(TPACPI_NOTICE
+		"temperatures (Celsius):");
+
+	for (i = 0; i < n; i++) {
+		if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
+			printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
+		else
+			printk(KERN_CONT " N/A");
+	}
+
+	printk(KERN_CONT "\n");
+}
+
 /* sysfs temp##_input -------------------------------------------------- */
 
 static ssize_t thermal_temp_input_show(struct device *dev,
@@ -5589,7 +5624,7 @@
 	res = thermal_get_sensor(idx, &value);
 	if (res)
 		return res;
-	if (value == TP_EC_THERMAL_TMP_NA * 1000)
+	if (value == TPACPI_THERMAL_SENSOR_NA)
 		return -ENXIO;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", value);
@@ -5758,7 +5793,7 @@
 	case TPACPI_THERMAL_ACPI_TMP07:
 	case TPACPI_THERMAL_ACPI_UPDT:
 		sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
-				   &thermal_temp_input16_group);
+				   &thermal_temp_input8_group);
 		break;
 	case TPACPI_THERMAL_NONE:
 	default:
@@ -5766,9 +5801,8 @@
 	}
 }
 
-static int thermal_read(char *p)
+static int thermal_read(struct seq_file *m)
 {
-	int len = 0;
 	int n, i;
 	struct ibm_thermal_sensors_struct t;
 
@@ -5776,16 +5810,16 @@
 	if (unlikely(n < 0))
 		return n;
 
-	len += sprintf(p + len, "temperatures:\t");
+	seq_printf(m, "temperatures:\t");
 
 	if (n > 0) {
 		for (i = 0; i < (n - 1); i++)
-			len += sprintf(p + len, "%d ", t.temp[i] / 1000);
-		len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
+			seq_printf(m, "%d ", t.temp[i] / 1000);
+		seq_printf(m, "%d\n", t.temp[i] / 1000);
 	} else
-		len += sprintf(p + len, "not supported\n");
+		seq_printf(m, "not supported\n");
 
-	return len;
+	return 0;
 }
 
 static struct ibm_struct thermal_driver_data = {
@@ -5800,39 +5834,38 @@
 
 static u8 ecdump_regs[256];
 
-static int ecdump_read(char *p)
+static int ecdump_read(struct seq_file *m)
 {
-	int len = 0;
 	int i, j;
 	u8 v;
 
-	len += sprintf(p + len, "EC      "
+	seq_printf(m, "EC      "
 		       " +00 +01 +02 +03 +04 +05 +06 +07"
 		       " +08 +09 +0a +0b +0c +0d +0e +0f\n");
 	for (i = 0; i < 256; i += 16) {
-		len += sprintf(p + len, "EC 0x%02x:", i);
+		seq_printf(m, "EC 0x%02x:", i);
 		for (j = 0; j < 16; j++) {
 			if (!acpi_ec_read(i + j, &v))
 				break;
 			if (v != ecdump_regs[i + j])
-				len += sprintf(p + len, " *%02x", v);
+				seq_printf(m, " *%02x", v);
 			else
-				len += sprintf(p + len, "  %02x", v);
+				seq_printf(m, "  %02x", v);
 			ecdump_regs[i + j] = v;
 		}
-		len += sprintf(p + len, "\n");
+		seq_putc(m, '\n');
 		if (j != 16)
 			break;
 	}
 
 	/* These are way too dangerous to advertise openly... */
 #if 0
-	len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
+	seq_printf(m, "commands:\t0x<offset> 0x<value>"
 		       " (<offset> is 00-ff, <value> is 00-ff)\n");
-	len += sprintf(p + len, "commands:\t0x<offset> <value>  "
+	seq_printf(m, "commands:\t0x<offset> <value>  "
 		       " (<offset> is 00-ff, <value> is 0-255)\n");
 #endif
-	return len;
+	return 0;
 }
 
 static int ecdump_write(char *buf)
@@ -6095,6 +6128,12 @@
 	return status & TP_EC_BACKLIGHT_LVLMSK;
 }
 
+static void tpacpi_brightness_notify_change(void)
+{
+	backlight_force_update(ibm_backlight_device,
+			       BACKLIGHT_UPDATE_HOTKEY);
+}
+
 static struct backlight_ops ibm_backlight_data = {
 	.get_brightness = brightness_get,
 	.update_status  = brightness_update_status,
@@ -6116,15 +6155,15 @@
 	TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC),	/* T43/p ATI */
 
 	/* Models with ATI GPUs that can use ECNVRAM */
-	TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),	/* R50,51 T40-42 */
 	TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
-	TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC),	/* R52 */
 	TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 
 	/* Models with Intel Extreme Graphics 2 */
-	TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
-	TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
-	TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+	TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),	/* X40 */
+	TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 
 	/* Models with Intel GMA900 */
 	TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC),	/* T43, R52 */
@@ -6223,9 +6262,9 @@
 		printk(TPACPI_INFO
 		       "detected a 16-level brightness capable ThinkPad\n");
 
-	ibm_backlight_device = backlight_device_register(
-					TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL,
-					&ibm_backlight_data);
+	ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
+							 NULL, NULL,
+							 &ibm_backlight_data);
 	if (IS_ERR(ibm_backlight_device)) {
 		int rc = PTR_ERR(ibm_backlight_device);
 		ibm_backlight_device = NULL;
@@ -6244,11 +6283,15 @@
 			"or not on your ThinkPad\n", TPACPI_MAIL);
 	}
 
-	ibm_backlight_device->props.max_brightness =
-				(tp_features.bright_16levels)? 15 : 7;
 	ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
 	backlight_update_status(ibm_backlight_device);
 
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
+			"brightness: registering brightness hotkeys "
+			"as change notification\n");
+	tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
+				| TP_ACPI_HKEY_BRGHTUP_MASK
+				| TP_ACPI_HKEY_BRGHTDWN_MASK);;
 	return 0;
 }
 
@@ -6273,23 +6316,22 @@
 	tpacpi_brightness_checkpoint_nvram();
 }
 
-static int brightness_read(char *p)
+static int brightness_read(struct seq_file *m)
 {
-	int len = 0;
 	int level;
 
 	level = brightness_get(NULL);
 	if (level < 0) {
-		len += sprintf(p + len, "level:\t\tunreadable\n");
+		seq_printf(m, "level:\t\tunreadable\n");
 	} else {
-		len += sprintf(p + len, "level:\t\t%d\n", level);
-		len += sprintf(p + len, "commands:\tup, down\n");
-		len += sprintf(p + len, "commands:\tlevel <level>"
+		seq_printf(m, "level:\t\t%d\n", level);
+		seq_printf(m, "commands:\tup, down\n");
+		seq_printf(m, "commands:\tlevel <level>"
 			       " (<level> is 0-%d)\n",
 			       (tp_features.bright_16levels) ? 15 : 7);
 	}
 
-	return len;
+	return 0;
 }
 
 static int brightness_write(char *buf)
@@ -6325,6 +6367,9 @@
 	 * Doing it this way makes the syscall restartable in case of EINTR
 	 */
 	rc = brightness_set(level);
+	if (!rc && ibm_backlight_device)
+		backlight_force_update(ibm_backlight_device,
+					BACKLIGHT_UPDATE_SYSFS);
 	return (rc == -EINTR)? -ERESTARTSYS : rc;
 }
 
@@ -6341,101 +6386,704 @@
  * Volume subdriver
  */
 
-static int volume_offset = 0x30;
+/*
+ * IBM ThinkPads have a simple volume controller with MUTE gating.
+ * Very early Lenovo ThinkPads follow the IBM ThinkPad spec.
+ *
+ * Since the *61 series (and probably also the later *60 series), Lenovo
+ * ThinkPads only implement the MUTE gate.
+ *
+ * EC register 0x30
+ *   Bit 6: MUTE (1 mutes sound)
+ *   Bit 3-0: Volume
+ *   Other bits should be zero as far as we know.
+ *
+ * This is also stored in CMOS NVRAM, byte 0x60, bit 6 (MUTE), and
+ * bits 3-0 (volume).  Other bits in NVRAM may have other functions,
+ * such as bit 7 which is used to detect repeated presses of MUTE,
+ * and we leave them unchanged.
+ */
+
+#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
+
+#define TPACPI_ALSA_DRVNAME  "ThinkPad EC"
+#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
+#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
+
+static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */
+static char *alsa_id = "ThinkPadEC";
+static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
+
+struct tpacpi_alsa_data {
+	struct snd_card *card;
+	struct snd_ctl_elem_id *ctl_mute_id;
+	struct snd_ctl_elem_id *ctl_vol_id;
+};
+
+static struct snd_card *alsa_card;
+
+enum {
+	TP_EC_AUDIO = 0x30,
+
+	/* TP_EC_AUDIO bits */
+	TP_EC_AUDIO_MUTESW = 6,
+
+	/* TP_EC_AUDIO bitmasks */
+	TP_EC_AUDIO_LVL_MSK = 0x0F,
+	TP_EC_AUDIO_MUTESW_MSK = (1 << TP_EC_AUDIO_MUTESW),
+
+	/* Maximum volume */
+	TP_EC_VOLUME_MAX = 14,
+};
+
+enum tpacpi_volume_access_mode {
+	TPACPI_VOL_MODE_AUTO = 0,	/* Not implemented yet */
+	TPACPI_VOL_MODE_EC,		/* Pure EC control */
+	TPACPI_VOL_MODE_UCMS_STEP,	/* UCMS step-based control: N/A */
+	TPACPI_VOL_MODE_ECNVRAM,	/* EC control w/ NVRAM store */
+	TPACPI_VOL_MODE_MAX
+};
+
+enum tpacpi_volume_capabilities {
+	TPACPI_VOL_CAP_AUTO = 0,	/* Use white/blacklist */
+	TPACPI_VOL_CAP_VOLMUTE,		/* Output vol and mute */
+	TPACPI_VOL_CAP_MUTEONLY,	/* Output mute only */
+	TPACPI_VOL_CAP_MAX
+};
 
-static int volume_read(char *p)
+static enum tpacpi_volume_access_mode volume_mode =
+	TPACPI_VOL_MODE_MAX;
+
+static enum tpacpi_volume_capabilities volume_capabilities;
+static int volume_control_allowed;
+
+/*
+ * Used to syncronize writers to TP_EC_AUDIO and
+ * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write
+ */
+static struct mutex volume_mutex;
+
+static void tpacpi_volume_checkpoint_nvram(void)
 {
-	int len = 0;
-	u8 level;
+	u8 lec = 0;
+	u8 b_nvram;
+	u8 ec_mask;
+
+	if (volume_mode != TPACPI_VOL_MODE_ECNVRAM)
+		return;
+	if (!volume_control_allowed)
+		return;
+
+	vdbg_printk(TPACPI_DBG_MIXER,
+		"trying to checkpoint mixer state to NVRAM...\n");
+
+	if (tp_features.mixer_no_level_control)
+		ec_mask = TP_EC_AUDIO_MUTESW_MSK;
+	else
+		ec_mask = TP_EC_AUDIO_MUTESW_MSK | TP_EC_AUDIO_LVL_MSK;
 
-	if (!acpi_ec_read(volume_offset, &level)) {
-		len += sprintf(p + len, "level:\t\tunreadable\n");
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return;
+
+	if (unlikely(!acpi_ec_read(TP_EC_AUDIO, &lec)))
+		goto unlock;
+	lec &= ec_mask;
+	b_nvram = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
+
+	if (lec != (b_nvram & ec_mask)) {
+		/* NVRAM needs update */
+		b_nvram &= ~ec_mask;
+		b_nvram |= lec;
+		nvram_write_byte(b_nvram, TP_NVRAM_ADDR_MIXER);
+		dbg_printk(TPACPI_DBG_MIXER,
+			   "updated NVRAM mixer status to 0x%02x (0x%02x)\n",
+			   (unsigned int) lec, (unsigned int) b_nvram);
 	} else {
-		len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
-		len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
-		len += sprintf(p + len, "commands:\tup, down, mute\n");
-		len += sprintf(p + len, "commands:\tlevel <level>"
-			       " (<level> is 0-15)\n");
+		vdbg_printk(TPACPI_DBG_MIXER,
+			   "NVRAM mixer status already is 0x%02x (0x%02x)\n",
+			   (unsigned int) lec, (unsigned int) b_nvram);
 	}
 
-	return len;
+unlock:
+	mutex_unlock(&volume_mutex);
 }
 
-static int volume_write(char *buf)
+static int volume_get_status_ec(u8 *status)
 {
-	int cmos_cmd, inc, i;
-	u8 level, mute;
-	int new_level, new_mute;
-	char *cmd;
+	u8 s;
 
-	while ((cmd = next_cmd(&buf))) {
-		if (!acpi_ec_read(volume_offset, &level))
-			return -EIO;
-		new_mute = mute = level & 0x40;
-		new_level = level = level & 0xf;
+	if (!acpi_ec_read(TP_EC_AUDIO, &s))
+		return -EIO;
 
-		if (strlencmp(cmd, "up") == 0) {
-			if (mute)
-				new_mute = 0;
-			else
-				new_level = level == 15 ? 15 : level + 1;
-		} else if (strlencmp(cmd, "down") == 0) {
-			if (mute)
-				new_mute = 0;
-			else
-				new_level = level == 0 ? 0 : level - 1;
-		} else if (sscanf(cmd, "level %d", &new_level) == 1 &&
-			   new_level >= 0 && new_level <= 15) {
-			/* new_level set */
-		} else if (strlencmp(cmd, "mute") == 0) {
-			new_mute = 0x40;
-		} else
-			return -EINVAL;
+	*status = s;
 
-		if (new_level != level) {
-			/* mute doesn't change */
+	dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s);
 
-			cmos_cmd = (new_level > level) ?
-					TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
-			inc = new_level > level ? 1 : -1;
+	return 0;
+}
 
-			if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
-				     !acpi_ec_write(volume_offset, level)))
-				return -EIO;
+static int volume_get_status(u8 *status)
+{
+	return volume_get_status_ec(status);
+}
 
-			for (i = level; i != new_level; i += inc)
-				if (issue_thinkpad_cmos_command(cmos_cmd) ||
-				    !acpi_ec_write(volume_offset, i + inc))
-					return -EIO;
-
-			if (mute &&
-			    (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
-			     !acpi_ec_write(volume_offset, new_level + mute))) {
-				return -EIO;
-			}
+static int volume_set_status_ec(const u8 status)
+{
+	if (!acpi_ec_write(TP_EC_AUDIO, status))
+		return -EIO;
+
+	dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
+
+	return 0;
+}
+
+static int volume_set_status(const u8 status)
+{
+	return volume_set_status_ec(status);
+}
+
+/* returns < 0 on error, 0 on no change, 1 on change */
+static int __volume_set_mute_ec(const bool mute)
+{
+	int rc;
+	u8 s, n;
+
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return -EINTR;
+
+	rc = volume_get_status_ec(&s);
+	if (rc)
+		goto unlock;
+
+	n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
+		     s & ~TP_EC_AUDIO_MUTESW_MSK;
+
+	if (n != s) {
+		rc = volume_set_status_ec(n);
+		if (!rc)
+			rc = 1;
+	}
+
+unlock:
+	mutex_unlock(&volume_mutex);
+	return rc;
+}
+
+static int volume_alsa_set_mute(const bool mute)
+{
+	dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
+		   (mute) ? "" : "un");
+	return __volume_set_mute_ec(mute);
+}
+
+static int volume_set_mute(const bool mute)
+{
+	int rc;
+
+	dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
+		   (mute) ? "" : "un");
+
+	rc = __volume_set_mute_ec(mute);
+	return (rc < 0) ? rc : 0;
+}
+
+/* returns < 0 on error, 0 on no change, 1 on change */
+static int __volume_set_volume_ec(const u8 vol)
+{
+	int rc;
+	u8 s, n;
+
+	if (vol > TP_EC_VOLUME_MAX)
+		return -EINVAL;
+
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return -EINTR;
+
+	rc = volume_get_status_ec(&s);
+	if (rc)
+		goto unlock;
+
+	n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
+
+	if (n != s) {
+		rc = volume_set_status_ec(n);
+		if (!rc)
+			rc = 1;
+	}
+
+unlock:
+	mutex_unlock(&volume_mutex);
+	return rc;
+}
+
+static int volume_alsa_set_volume(const u8 vol)
+{
+	dbg_printk(TPACPI_DBG_MIXER,
+		   "ALSA: trying to set volume level to %hu\n", vol);
+	return __volume_set_volume_ec(vol);
+}
+
+static void volume_alsa_notify_change(void)
+{
+	struct tpacpi_alsa_data *d;
+
+	if (alsa_card && alsa_card->private_data) {
+		d = alsa_card->private_data;
+		if (d->ctl_mute_id)
+			snd_ctl_notify(alsa_card,
+					SNDRV_CTL_EVENT_MASK_VALUE,
+					d->ctl_mute_id);
+		if (d->ctl_vol_id)
+			snd_ctl_notify(alsa_card,
+					SNDRV_CTL_EVENT_MASK_VALUE,
+					d->ctl_vol_id);
+	}
+}
+
+static int volume_alsa_vol_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = TP_EC_VOLUME_MAX;
+	return 0;
+}
+
+static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 s;
+	int rc;
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	ucontrol->value.integer.value[0] = s & TP_EC_AUDIO_LVL_MSK;
+	return 0;
+}
+
+static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
+}
+
+#define volume_alsa_mute_info snd_ctl_boolean_mono_info
+
+static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 s;
+	int rc;
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	ucontrol->value.integer.value[0] =
+				(s & TP_EC_AUDIO_MUTESW_MSK) ? 0 : 1;
+	return 0;
+}
+
+static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
+}
+
+static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Console Playback Volume",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.info = volume_alsa_vol_info,
+	.get = volume_alsa_vol_get,
+};
+
+static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Console Playback Switch",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.info = volume_alsa_mute_info,
+	.get = volume_alsa_mute_get,
+};
+
+static void volume_suspend(pm_message_t state)
+{
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static void volume_resume(void)
+{
+	volume_alsa_notify_change();
+}
+
+static void volume_shutdown(void)
+{
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static void volume_exit(void)
+{
+	if (alsa_card) {
+		snd_card_free(alsa_card);
+		alsa_card = NULL;
+	}
+
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static int __init volume_create_alsa_mixer(void)
+{
+	struct snd_card *card;
+	struct tpacpi_alsa_data *data;
+	struct snd_kcontrol *ctl_vol;
+	struct snd_kcontrol *ctl_mute;
+	int rc;
+
+	rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
+			    sizeof(struct tpacpi_alsa_data), &card);
+	if (rc < 0 || !card) {
+		printk(TPACPI_ERR
+			"Failed to create ALSA card structures: %d\n", rc);
+		return 1;
+	}
+
+	BUG_ON(!card->private_data);
+	data = card->private_data;
+	data->card = card;
+
+	strlcpy(card->driver, TPACPI_ALSA_DRVNAME,
+		sizeof(card->driver));
+	strlcpy(card->shortname, TPACPI_ALSA_SHRTNAME,
+		sizeof(card->shortname));
+	snprintf(card->mixername, sizeof(card->mixername), "ThinkPad EC %s",
+		 (thinkpad_id.ec_version_str) ?
+			thinkpad_id.ec_version_str : "(unknown)");
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s at EC reg 0x%02x, fw %s", card->shortname, TP_EC_AUDIO,
+		 (thinkpad_id.ec_version_str) ?
+			thinkpad_id.ec_version_str : "unknown");
+
+	if (volume_control_allowed) {
+		volume_alsa_control_vol.put = volume_alsa_vol_put;
+		volume_alsa_control_vol.access =
+				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+
+		volume_alsa_control_mute.put = volume_alsa_mute_put;
+		volume_alsa_control_mute.access =
+				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+	}
+
+	if (!tp_features.mixer_no_level_control) {
+		ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
+		rc = snd_ctl_add(card, ctl_vol);
+		if (rc < 0) {
+			printk(TPACPI_ERR
+				"Failed to create ALSA volume control: %d\n",
+				rc);
+			goto err_exit;
 		}
+		data->ctl_vol_id = &ctl_vol->id;
+	}
 
-		if (new_mute != mute) {
-			/* level doesn't change */
+	ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
+	rc = snd_ctl_add(card, ctl_mute);
+	if (rc < 0) {
+		printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n",
+			rc);
+		goto err_exit;
+	}
+	data->ctl_mute_id = &ctl_mute->id;
 
-			cmos_cmd = (new_mute) ?
-				   TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
+	snd_card_set_dev(card, &tpacpi_pdev->dev);
+	rc = snd_card_register(card);
+	if (rc < 0) {
+		printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc);
+		goto err_exit;
+	}
 
-			if (issue_thinkpad_cmos_command(cmos_cmd) ||
-			    !acpi_ec_write(volume_offset, level + new_mute))
-				return -EIO;
+	alsa_card = card;
+	return 0;
+
+err_exit:
+	snd_card_free(card);
+	return 1;
+}
+
+#define TPACPI_VOL_Q_MUTEONLY	0x0001	/* Mute-only control available */
+#define TPACPI_VOL_Q_LEVEL	0x0002  /* Volume control available */
+
+static const struct tpacpi_quirk volume_quirk_table[] __initconst = {
+	/* Whitelist volume level on all IBM by default */
+	{ .vendor = PCI_VENDOR_ID_IBM,
+	  .bios   = TPACPI_MATCH_ANY,
+	  .ec     = TPACPI_MATCH_ANY,
+	  .quirks = TPACPI_VOL_Q_LEVEL },
+
+	/* Lenovo models with volume control (needs confirmation) */
+	TPACPI_QEC_LNV('7', 'C', TPACPI_VOL_Q_LEVEL), /* R60/i */
+	TPACPI_QEC_LNV('7', 'E', TPACPI_VOL_Q_LEVEL), /* R60e/i */
+	TPACPI_QEC_LNV('7', '9', TPACPI_VOL_Q_LEVEL), /* T60/p */
+	TPACPI_QEC_LNV('7', 'B', TPACPI_VOL_Q_LEVEL), /* X60/s */
+	TPACPI_QEC_LNV('7', 'J', TPACPI_VOL_Q_LEVEL), /* X60t */
+	TPACPI_QEC_LNV('7', '7', TPACPI_VOL_Q_LEVEL), /* Z60 */
+	TPACPI_QEC_LNV('7', 'F', TPACPI_VOL_Q_LEVEL), /* Z61 */
+
+	/* Whitelist mute-only on all Lenovo by default */
+	{ .vendor = PCI_VENDOR_ID_LENOVO,
+	  .bios   = TPACPI_MATCH_ANY,
+	  .ec	  = TPACPI_MATCH_ANY,
+	  .quirks = TPACPI_VOL_Q_MUTEONLY }
+};
+
+static int __init volume_init(struct ibm_init_struct *iibm)
+{
+	unsigned long quirks;
+	int rc;
+
+	vdbg_printk(TPACPI_DBG_INIT, "initializing volume subdriver\n");
+
+	mutex_init(&volume_mutex);
+
+	/*
+	 * Check for module parameter bogosity, note that we
+	 * init volume_mode to TPACPI_VOL_MODE_MAX in order to be
+	 * able to detect "unspecified"
+	 */
+	if (volume_mode > TPACPI_VOL_MODE_MAX)
+		return -EINVAL;
+
+	if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
+		printk(TPACPI_ERR
+			"UCMS step volume mode not implemented, "
+			"please contact %s\n", TPACPI_MAIL);
+		return 1;
+	}
+
+	if (volume_capabilities >= TPACPI_VOL_CAP_MAX)
+		return -EINVAL;
+
+	/*
+	 * The ALSA mixer is our primary interface.
+	 * When disabled, don't install the subdriver at all
+	 */
+	if (!alsa_enable) {
+		vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+			    "ALSA mixer disabled by parameter, "
+			    "not loading volume subdriver...\n");
+		return 1;
+	}
+
+	quirks = tpacpi_check_quirks(volume_quirk_table,
+				     ARRAY_SIZE(volume_quirk_table));
+
+	switch (volume_capabilities) {
+	case TPACPI_VOL_CAP_AUTO:
+		if (quirks & TPACPI_VOL_Q_MUTEONLY)
+			tp_features.mixer_no_level_control = 1;
+		else if (quirks & TPACPI_VOL_Q_LEVEL)
+			tp_features.mixer_no_level_control = 0;
+		else
+			return 1; /* no mixer */
+		break;
+	case TPACPI_VOL_CAP_VOLMUTE:
+		tp_features.mixer_no_level_control = 0;
+		break;
+	case TPACPI_VOL_CAP_MUTEONLY:
+		tp_features.mixer_no_level_control = 1;
+		break;
+	default:
+		return 1;
+	}
+
+	if (volume_capabilities != TPACPI_VOL_CAP_AUTO)
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"using user-supplied volume_capabilities=%d\n",
+				volume_capabilities);
+
+	if (volume_mode == TPACPI_VOL_MODE_AUTO ||
+	    volume_mode == TPACPI_VOL_MODE_MAX) {
+		volume_mode = TPACPI_VOL_MODE_ECNVRAM;
+
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"driver auto-selected volume_mode=%d\n",
+				volume_mode);
+	} else {
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"using user-supplied volume_mode=%d\n",
+				volume_mode);
+	}
+
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+			"mute is supported, volume control is %s\n",
+			str_supported(!tp_features.mixer_no_level_control));
+
+	rc = volume_create_alsa_mixer();
+	if (rc) {
+		printk(TPACPI_ERR
+			"Could not create the ALSA mixer interface\n");
+		return rc;
+	}
+
+	printk(TPACPI_INFO
+		"Console audio control enabled, mode: %s\n",
+		(volume_control_allowed) ?
+			"override (read/write)" :
+			"monitor (read only)");
+
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+		"registering volume hotkeys as change notification\n");
+	tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
+			| TP_ACPI_HKEY_VOLUP_MASK
+			| TP_ACPI_HKEY_VOLDWN_MASK
+			| TP_ACPI_HKEY_MUTE_MASK);
+
+	return 0;
+}
+
+static int volume_read(struct seq_file *m)
+{
+	u8 status;
+
+	if (volume_get_status(&status) < 0) {
+		seq_printf(m, "level:\t\tunreadable\n");
+	} else {
+		if (tp_features.mixer_no_level_control)
+			seq_printf(m, "level:\t\tunsupported\n");
+		else
+			seq_printf(m, "level:\t\t%d\n",
+					status & TP_EC_AUDIO_LVL_MSK);
+
+		seq_printf(m, "mute:\t\t%s\n",
+				onoff(status, TP_EC_AUDIO_MUTESW));
+
+		if (volume_control_allowed) {
+			seq_printf(m, "commands:\tunmute, mute\n");
+			if (!tp_features.mixer_no_level_control) {
+				seq_printf(m,
+					       "commands:\tup, down\n");
+				seq_printf(m,
+					       "commands:\tlevel <level>"
+					       " (<level> is 0-%d)\n",
+					       TP_EC_VOLUME_MAX);
+			}
 		}
 	}
 
 	return 0;
 }
 
+static int volume_write(char *buf)
+{
+	u8 s;
+	u8 new_level, new_mute;
+	int l;
+	char *cmd;
+	int rc;
+
+	/*
+	 * We do allow volume control at driver startup, so that the
+	 * user can set initial state through the volume=... parameter hack.
+	 */
+	if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
+		if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
+			tp_warned.volume_ctrl_forbidden = 1;
+			printk(TPACPI_NOTICE
+				"Console audio control in monitor mode, "
+				"changes are not allowed.\n");
+			printk(TPACPI_NOTICE
+				"Use the volume_control=1 module parameter "
+				"to enable volume control\n");
+		}
+		return -EPERM;
+	}
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	new_level = s & TP_EC_AUDIO_LVL_MSK;
+	new_mute  = s & TP_EC_AUDIO_MUTESW_MSK;
+
+	while ((cmd = next_cmd(&buf))) {
+		if (!tp_features.mixer_no_level_control) {
+			if (strlencmp(cmd, "up") == 0) {
+				if (new_mute)
+					new_mute = 0;
+				else if (new_level < TP_EC_VOLUME_MAX)
+					new_level++;
+				continue;
+			} else if (strlencmp(cmd, "down") == 0) {
+				if (new_mute)
+					new_mute = 0;
+				else if (new_level > 0)
+					new_level--;
+				continue;
+			} else if (sscanf(cmd, "level %u", &l) == 1 &&
+				   l >= 0 && l <= TP_EC_VOLUME_MAX) {
+					new_level = l;
+				continue;
+			}
+		}
+		if (strlencmp(cmd, "mute") == 0)
+			new_mute = TP_EC_AUDIO_MUTESW_MSK;
+		else if (strlencmp(cmd, "unmute") == 0)
+			new_mute = 0;
+		else
+			return -EINVAL;
+	}
+
+	if (tp_features.mixer_no_level_control) {
+		tpacpi_disclose_usertask("procfs volume", "%smute\n",
+					new_mute ? "" : "un");
+		rc = volume_set_mute(!!new_mute);
+	} else {
+		tpacpi_disclose_usertask("procfs volume",
+					"%smute and set level to %d\n",
+					new_mute ? "" : "un", new_level);
+		rc = volume_set_status(new_mute | new_level);
+	}
+	volume_alsa_notify_change();
+
+	return (rc == -EINTR) ? -ERESTARTSYS : rc;
+}
+
 static struct ibm_struct volume_driver_data = {
 	.name = "volume",
 	.read = volume_read,
 	.write = volume_write,
+	.exit = volume_exit,
+	.suspend = volume_suspend,
+	.resume = volume_resume,
+	.shutdown = volume_shutdown,
+};
+
+#else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
+
+#define alsa_card NULL
+
+static void inline volume_alsa_notify_change(void)
+{
+}
+
+static int __init volume_init(struct ibm_init_struct *iibm)
+{
+	printk(TPACPI_INFO
+		"volume: disabled as there is no ALSA support in this kernel\n");
+
+	return 1;
+}
+
+static struct ibm_struct volume_driver_data = {
+	.name = "volume",
 };
 
+#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
+
 /*************************************************************************
  * Fan subdriver
  */
@@ -6461,7 +7109,7 @@
  *
  * 	Fan speed changes of any sort (including those caused by the
  * 	disengaged mode) are usually done slowly by the firmware as the
- * 	maximum ammount of fan duty cycle change per second seems to be
+ * 	maximum amount of fan duty cycle change per second seems to be
  * 	limited.
  *
  * 	Reading is not available if GFAN exists.
@@ -6545,7 +7193,7 @@
  * 	The speeds are stored on handles
  * 	(FANA:FAN9), (FANC:FANB), (FANE:FAND).
  *
- * 	There are three default speed sets, acessible as handles:
+ * 	There are three default speed sets, accessible as handles:
  * 	FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H
  *
  * 	ACPI DSDT switches which set is in use depending on various
@@ -7510,9 +8158,8 @@
 	}
 }
 
-static int fan_read(char *p)
+static int fan_read(struct seq_file *m)
 {
-	int len = 0;
 	int rc;
 	u8 status;
 	unsigned int speed = 0;
@@ -7524,7 +8171,7 @@
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "status:\t\t%s\n"
+		seq_printf(m, "status:\t\t%s\n"
 			       "level:\t\t%d\n",
 			       (status != 0) ? "enabled" : "disabled", status);
 		break;
@@ -7535,54 +8182,54 @@
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "status:\t\t%s\n",
+		seq_printf(m, "status:\t\t%s\n",
 			       (status != 0) ? "enabled" : "disabled");
 
 		rc = fan_get_speed(&speed);
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "speed:\t\t%d\n", speed);
+		seq_printf(m, "speed:\t\t%d\n", speed);
 
 		if (status & TP_EC_FAN_FULLSPEED)
 			/* Disengaged mode takes precedence */
-			len += sprintf(p + len, "level:\t\tdisengaged\n");
+			seq_printf(m, "level:\t\tdisengaged\n");
 		else if (status & TP_EC_FAN_AUTO)
-			len += sprintf(p + len, "level:\t\tauto\n");
+			seq_printf(m, "level:\t\tauto\n");
 		else
-			len += sprintf(p + len, "level:\t\t%d\n", status);
+			seq_printf(m, "level:\t\t%d\n", status);
 		break;
 
 	case TPACPI_FAN_NONE:
 	default:
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	}
 
 	if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
-		len += sprintf(p + len, "commands:\tlevel <level>");
+		seq_printf(m, "commands:\tlevel <level>");
 
 		switch (fan_control_access_mode) {
 		case TPACPI_FAN_WR_ACPI_SFAN:
-			len += sprintf(p + len, " (<level> is 0-7)\n");
+			seq_printf(m, " (<level> is 0-7)\n");
 			break;
 
 		default:
-			len += sprintf(p + len, " (<level> is 0-7, "
+			seq_printf(m, " (<level> is 0-7, "
 				       "auto, disengaged, full-speed)\n");
 			break;
 		}
 	}
 
 	if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
-		len += sprintf(p + len, "commands:\tenable, disable\n"
+		seq_printf(m, "commands:\tenable, disable\n"
 			       "commands:\twatchdog <timeout> (<timeout> "
 			       "is 0 (off), 1-120 (seconds))\n");
 
 	if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
-		len += sprintf(p + len, "commands:\tspeed <speed>"
+		seq_printf(m, "commands:\tspeed <speed>"
 			       " (<speed> is 0-65535)\n");
 
-	return len;
+	return 0;
 }
 
 static int fan_write_cmd_level(const char *cmd, int *rc)
@@ -7724,10 +8371,23 @@
  */
 static void tpacpi_driver_event(const unsigned int hkey_event)
 {
+	if (ibm_backlight_device) {
+		switch (hkey_event) {
+		case TP_HKEY_EV_BRGHT_UP:
+		case TP_HKEY_EV_BRGHT_DOWN:
+			tpacpi_brightness_notify_change();
+		}
+	}
+	if (alsa_card) {
+		switch (hkey_event) {
+		case TP_HKEY_EV_VOL_UP:
+		case TP_HKEY_EV_VOL_DOWN:
+		case TP_HKEY_EV_VOL_MUTE:
+			volume_alsa_notify_change();
+		}
+	}
 }
 
-
-
 static void hotkey_driver_event(const unsigned int scancode)
 {
 	tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
@@ -7856,19 +8516,20 @@
 		"%s installed\n", ibm->name);
 
 	if (ibm->read) {
-		entry = create_proc_entry(ibm->name,
-					  S_IFREG | S_IRUGO | S_IWUSR,
-					  proc_dir);
+		mode_t mode = iibm->base_procfs_mode;
+
+		if (!mode)
+			mode = S_IRUGO;
+		if (ibm->write)
+			mode |= S_IWUSR;
+		entry = proc_create_data(ibm->name, mode, proc_dir,
+					 &dispatch_proc_fops, ibm);
 		if (!entry) {
 			printk(TPACPI_ERR "unable to create proc entry %s\n",
 			       ibm->name);
 			ret = -ENODEV;
 			goto err_out;
 		}
-		entry->data = ibm;
-		entry->read_proc = &dispatch_procfs_read;
-		if (ibm->write)
-			entry->write_proc = &dispatch_procfs_write;
 		ibm->flags.proc_created = 1;
 	}
 
@@ -8049,6 +8710,7 @@
 #ifdef CONFIG_THINKPAD_ACPI_VIDEO
 	{
 		.init = video_init,
+		.base_procfs_mode = S_IRUSR,
 		.data = &video_driver_data,
 	},
 #endif
@@ -8080,6 +8742,7 @@
 		.data = &brightness_driver_data,
 	},
 	{
+		.init = volume_init,
 		.data = &volume_driver_data,
 	},
 	{
@@ -8115,36 +8778,61 @@
 	return -EINVAL;
 }
 
-module_param(experimental, int, 0);
+module_param(experimental, int, 0444);
 MODULE_PARM_DESC(experimental,
 		 "Enables experimental features when non-zero");
 
 module_param_named(debug, dbg_level, uint, 0);
 MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
 
-module_param(force_load, bool, 0);
+module_param(force_load, bool, 0444);
 MODULE_PARM_DESC(force_load,
 		 "Attempts to load the driver even on a "
 		 "mis-identified ThinkPad when true");
 
-module_param_named(fan_control, fan_control_allowed, bool, 0);
+module_param_named(fan_control, fan_control_allowed, bool, 0444);
 MODULE_PARM_DESC(fan_control,
 		 "Enables setting fan parameters features when true");
 
-module_param_named(brightness_mode, brightness_mode, uint, 0);
+module_param_named(brightness_mode, brightness_mode, uint, 0444);
 MODULE_PARM_DESC(brightness_mode,
 		 "Selects brightness control strategy: "
 		 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
 
-module_param(brightness_enable, uint, 0);
+module_param(brightness_enable, uint, 0444);
 MODULE_PARM_DESC(brightness_enable,
 		 "Enables backlight control when 1, disables when 0");
 
-module_param(hotkey_report_mode, uint, 0);
+module_param(hotkey_report_mode, uint, 0444);
 MODULE_PARM_DESC(hotkey_report_mode,
 		 "used for backwards compatibility with userspace, "
 		 "see documentation");
 
+#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
+module_param_named(volume_mode, volume_mode, uint, 0444);
+MODULE_PARM_DESC(volume_mode,
+		 "Selects volume control strategy: "
+		 "0=auto, 1=EC, 2=N/A, 3=EC+NVRAM");
+
+module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
+MODULE_PARM_DESC(volume_capabilities,
+		 "Selects the mixer capabilites: "
+		 "0=auto, 1=volume and mute, 2=mute only");
+
+module_param_named(volume_control, volume_control_allowed, bool, 0444);
+MODULE_PARM_DESC(volume_control,
+		 "Enables software override for the console audio "
+		 "control when true");
+
+/* ALSA module API parameters */
+module_param_named(index, alsa_index, int, 0444);
+MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
+module_param_named(id, alsa_id, charp, 0444);
+MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
+module_param_named(enable, alsa_enable, bool, 0444);
+MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
+#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */
+
 #define TPACPI_PARAM(feature) \
 	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
 	MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
@@ -8163,25 +8851,25 @@
 TPACPI_PARAM(fan);
 
 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
-module_param(dbg_wlswemul, uint, 0);
+module_param(dbg_wlswemul, uint, 0444);
 MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
 module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
 MODULE_PARM_DESC(wlsw_state,
 		 "Initial state of the emulated WLSW switch");
 
-module_param(dbg_bluetoothemul, uint, 0);
+module_param(dbg_bluetoothemul, uint, 0444);
 MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
 module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
 MODULE_PARM_DESC(bluetooth_state,
 		 "Initial state of the emulated bluetooth switch");
 
-module_param(dbg_wwanemul, uint, 0);
+module_param(dbg_wwanemul, uint, 0444);
 MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
 module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
 MODULE_PARM_DESC(wwan_state,
 		 "Initial state of the emulated WWAN switch");
 
-module_param(dbg_uwbemul, uint, 0);
+module_param(dbg_uwbemul, uint, 0444);
 MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
 module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
 MODULE_PARM_DESC(uwb_state,
@@ -8374,6 +9062,7 @@
 						PCI_VENDOR_ID_IBM;
 		tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
 		tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
+		tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
 	}
 	for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
 		ret = ibm_init(&ibms_init[i]);
@@ -8384,6 +9073,9 @@
 			return ret;
 		}
 	}
+
+	tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
+
 	ret = input_register_device(tpacpi_inputdev);
 	if (ret < 0) {
 		printk(TPACPI_ERR "unable to register input device\n");
@@ -8393,7 +9085,6 @@
 		tp_features.input_device_registered = 1;
 	}
 
-	tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/platform/x86/dell-wmi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/dell-wmi.c
@@ -40,6 +40,10 @@
 
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
+/* Temporary workaround until the WMI sysfs interface goes in.
+   Borrowed from acer-wmi */
+MODULE_ALIAS("dmi:*:*Dell*:*:");
+
 struct key_entry {
 	char type;		/* See KE_* below */
 	u16 code;
@@ -158,8 +162,13 @@
 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
 	static struct key_entry *key;
 	union acpi_object *obj;
+	acpi_status status;
 
-	wmi_get_event_data(value, &response);
+	status = wmi_get_event_data(value, &response);
+	if (status != AE_OK) {
+		printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status);
+		return;
+	}
 
 	obj = (union acpi_object *)response.pointer;
 
@@ -180,6 +189,7 @@
 			printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
 			       buffer[1] & 0xFFFF);
 	}
+	kfree(obj);
 }
 
 static int __init dell_wmi_input_setup(void)
--- linux-ec2-2.6.32.orig/drivers/platform/x86/asus-laptop.c
+++ linux-ec2-2.6.32/drivers/platform/x86/asus-laptop.c
@@ -221,6 +221,7 @@
  */
 static const struct acpi_device_id asus_device_ids[] = {
 	{"ATK0100", 0},
+	{"ATK0101", 0},
 	{"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, asus_device_ids);
@@ -293,6 +294,11 @@
 enum { KE_KEY, KE_END };
 
 static struct key_entry asus_keymap[] = {
+	{KE_KEY, 0x02, KEY_SCREENLOCK},
+	{KE_KEY, 0x05, KEY_WLAN},
+	{KE_KEY, 0x08, BTN_TOUCH},
+	{KE_KEY, 0x17, KEY_ZOOM},
+	{KE_KEY, 0x1f, KEY_BATTERY},
 	{KE_KEY, 0x30, KEY_VOLUMEUP},
 	{KE_KEY, 0x31, KEY_VOLUMEDOWN},
 	{KE_KEY, 0x32, KEY_MUTE},
@@ -312,6 +318,8 @@
 	{KE_KEY, 0x5F, KEY_WLAN},
 	{KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
 	{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
 	{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
 	{KE_KEY, 0x82, KEY_CAMERA},
 	{KE_KEY, 0x8A, KEY_PROG1},
@@ -1283,8 +1291,8 @@
 	hotk->ledd_status = 0xFFF;
 
 	/* Set initial values of light sensor and level */
-	hotk->light_switch = 1;	/* Default to light sensor disabled */
-	hotk->light_level = 0;	/* level 5 for sensor sensitivity */
+	hotk->light_switch = 0;	/* Default to light sensor disabled */
+	hotk->light_level = 5;	/* level 5 for sensor sensitivity */
 
 	if (ls_switch_handle)
 		set_light_sens_switch(hotk->light_switch);
--- linux-ec2-2.6.32.orig/drivers/platform/x86/tc1100-wmi.c
+++ linux-ec2-2.6.32/drivers/platform/x86/tc1100-wmi.c
@@ -177,7 +177,7 @@
 			return -EINVAL; \
 	return count; \
 } \
-static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \
+static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, \
 	show_bool_##value, set_bool_##value);
 
 show_set_bool(wireless, TC1100_INSTANCE_WIRELESS);
--- linux-ec2-2.6.32.orig/drivers/oprofile/oprof.h
+++ linux-ec2-2.6.32/drivers/oprofile/oprof.h
@@ -39,4 +39,7 @@
 int oprofile_set_backtrace(unsigned long depth);
 int oprofile_set_timeout(unsigned long time);
 
+int oprofile_set_active(int active_domains[], unsigned int adomains);
+int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
+
 #endif /* OPROF_H */
--- linux-ec2-2.6.32.orig/drivers/oprofile/cpu_buffer.c
+++ linux-ec2-2.6.32/drivers/oprofile/cpu_buffer.c
@@ -8,6 +8,10 @@
  * @author Barry Kasindorf <barry.kasindorf@amd.com>
  * @author Robert Richter <robert.richter@amd.com>
  *
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ *
  * Each CPU has a local buffer that stores PC value/event
  * pairs. We also log context switches when we notice them.
  * Eventually each CPU's buffer is processed into the global
@@ -30,23 +34,7 @@
 
 #define OP_BUFFER_FLAGS	0
 
-/*
- * Read and write access is using spin locking. Thus, writing to the
- * buffer by NMI handler (x86) could occur also during critical
- * sections when reading the buffer. To avoid this, there are 2
- * buffers for independent read and write access. Read access is in
- * process context only, write access only in the NMI handler. If the
- * read buffer runs empty, both buffers are swapped atomically. There
- * is potentially a small window during swapping where the buffers are
- * disabled and samples could be lost.
- *
- * Using 2 buffers is a little bit overhead, but the solution is clear
- * and does not require changes in the ring buffer implementation. It
- * can be changed to a single buffer solution when the ring buffer
- * access is implemented as non-locking atomic code.
- */
-static struct ring_buffer *op_ring_buffer_read;
-static struct ring_buffer *op_ring_buffer_write;
+static struct ring_buffer *op_ring_buffer;
 DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
 
 static void wq_sync_buffer(struct work_struct *work);
@@ -54,6 +42,12 @@
 #define DEFAULT_TIMER_EXPIRE (HZ / 10)
 static int work_enabled;
 
+#ifndef CONFIG_XEN
+#define current_domain COORDINATOR_DOMAIN
+#else
+static int32_t current_domain = COORDINATOR_DOMAIN;
+#endif
+
 unsigned long oprofile_get_cpu_buffer_size(void)
 {
 	return oprofile_cpu_buffer_size;
@@ -69,12 +63,9 @@
 
 void free_cpu_buffers(void)
 {
-	if (op_ring_buffer_read)
-		ring_buffer_free(op_ring_buffer_read);
-	op_ring_buffer_read = NULL;
-	if (op_ring_buffer_write)
-		ring_buffer_free(op_ring_buffer_write);
-	op_ring_buffer_write = NULL;
+	if (op_ring_buffer)
+		ring_buffer_free(op_ring_buffer);
+	op_ring_buffer = NULL;
 }
 
 #define RB_EVENT_HDR_SIZE 4
@@ -87,18 +78,15 @@
 	unsigned long byte_size = buffer_size * (sizeof(struct op_sample) +
 						 RB_EVENT_HDR_SIZE);
 
-	op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
-	if (!op_ring_buffer_read)
-		goto fail;
-	op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
-	if (!op_ring_buffer_write)
+	op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
+	if (!op_ring_buffer)
 		goto fail;
 
 	for_each_possible_cpu(i) {
 		struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
 
 		b->last_task = NULL;
-		b->last_is_kernel = -1;
+		b->last_cpu_mode = -1;
 		b->tracing = 0;
 		b->buffer_size = buffer_size;
 		b->sample_received = 0;
@@ -143,8 +131,6 @@
 
 		cancel_delayed_work(&b->work);
 	}
-
-	flush_scheduled_work();
 }
 
 /*
@@ -163,16 +149,11 @@
 *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)
 {
 	entry->event = ring_buffer_lock_reserve
-		(op_ring_buffer_write, sizeof(struct op_sample) +
+		(op_ring_buffer, sizeof(struct op_sample) +
 		 size * sizeof(entry->sample->data[0]));
-	if (entry->event)
-		entry->sample = ring_buffer_event_data(entry->event);
-	else
-		entry->sample = NULL;
-
-	if (!entry->sample)
+	if (!entry->event)
 		return NULL;
-
+	entry->sample = ring_buffer_event_data(entry->event);
 	entry->size = size;
 	entry->data = entry->sample->data;
 
@@ -181,25 +162,16 @@
 
 int op_cpu_buffer_write_commit(struct op_entry *entry)
 {
-	return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event);
+	return ring_buffer_unlock_commit(op_ring_buffer, entry->event);
 }
 
 struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)
 {
 	struct ring_buffer_event *e;
-	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
-	if (e)
-		goto event;
-	if (ring_buffer_swap_cpu(op_ring_buffer_read,
-				 op_ring_buffer_write,
-				 cpu))
+	e = ring_buffer_consume(op_ring_buffer, cpu, NULL);
+	if (!e)
 		return NULL;
-	e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
-	if (e)
-		goto event;
-	return NULL;
 
-event:
 	entry->event = e;
 	entry->sample = ring_buffer_event_data(e);
 	entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))
@@ -210,13 +182,12 @@
 
 unsigned long op_cpu_buffer_entries(int cpu)
 {
-	return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)
-		+ ring_buffer_entries_cpu(op_ring_buffer_write, cpu);
+	return ring_buffer_entries_cpu(op_ring_buffer, cpu);
 }
 
 static int
 op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace,
-	    int is_kernel, struct task_struct *task)
+	    int cpu_mode, struct task_struct *task)
 {
 	struct op_entry entry;
 	struct op_sample *sample;
@@ -229,16 +200,15 @@
 		flags |= TRACE_BEGIN;
 
 	/* notice a switch from user->kernel or vice versa */
-	is_kernel = !!is_kernel;
-	if (cpu_buf->last_is_kernel != is_kernel) {
-		cpu_buf->last_is_kernel = is_kernel;
-		flags |= KERNEL_CTX_SWITCH;
-		if (is_kernel)
-			flags |= IS_KERNEL;
+	if (cpu_buf->last_cpu_mode != cpu_mode) {
+		cpu_buf->last_cpu_mode = cpu_mode;
+		flags |= KERNEL_CTX_SWITCH | cpu_mode;
 	}
 
 	/* notice a task switch */
-	if (cpu_buf->last_task != task) {
+	/* if not processing other domain samples */
+	if (cpu_buf->last_task != task &&
+	    current_domain == COORDINATOR_DOMAIN) {
 		cpu_buf->last_task = task;
 		flags |= USER_CTX_SWITCH;
 	}
@@ -287,14 +257,14 @@
 /*
  * This must be safe from any context.
  *
- * is_kernel is needed because on some architectures you cannot
+ * cpu_mode is needed because on some architectures you cannot
  * tell if you are in kernel or user space simply by looking at
- * pc. We tag this in the buffer by generating kernel enter/exit
- * events whenever is_kernel changes
+ * pc. We tag this in the buffer by generating kernel/user (and
+ * xen) enter events whenever cpu_mode changes
  */
 static int
 log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
-	   unsigned long backtrace, int is_kernel, unsigned long event)
+	   unsigned long backtrace, int cpu_mode, unsigned long event)
 {
 	cpu_buf->sample_received++;
 
@@ -303,7 +273,7 @@
 		return 0;
 	}
 
-	if (op_add_code(cpu_buf, backtrace, is_kernel, current))
+	if (op_add_code(cpu_buf, backtrace, cpu_mode, current))
 		goto fail;
 
 	if (op_add_sample(cpu_buf, pc, event))
@@ -434,6 +404,20 @@
 	log_sample(cpu_buf, pc, 0, is_kernel, event);
 }
 
+#ifdef CONFIG_XEN
+/*
+ * This is basically log_sample(b, ESCAPE_CODE, 1, cpu_mode, CPU_TRACE_BEGIN),
+ * as was previously accessible through oprofile_add_pc().
+ */
+void oprofile_add_mode(int cpu_mode)
+{
+	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+
+	if (op_add_code(cpu_buf, 1, cpu_mode, current))
+		cpu_buf->sample_lost_overflow++;
+}
+#endif
+
 void oprofile_add_trace(unsigned long pc)
 {
 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
@@ -458,6 +442,28 @@
 	return;
 }
 
+#ifdef CONFIG_XEN
+int oprofile_add_domain_switch(int32_t domain_id)
+{
+	struct op_entry entry;
+	struct op_sample *sample;
+
+	sample = op_cpu_buffer_write_reserve(&entry, 1);
+	if (!sample)
+		return 0;
+
+	sample->eip = ESCAPE_CODE;
+	sample->event = DOMAIN_SWITCH;
+
+	op_cpu_buffer_add_data(&entry, domain_id);
+	op_cpu_buffer_write_commit(&entry);
+
+	current_domain = domain_id;
+
+	return 1;
+}
+#endif
+
 /*
  * This serves to avoid cpu buffer overflow, and makes sure
  * the task mortuary progresses
--- linux-ec2-2.6.32.orig/drivers/oprofile/oprof.c
+++ linux-ec2-2.6.32/drivers/oprofile/oprof.c
@@ -5,6 +5,10 @@
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ *
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
  */
 
 #include <linux/kernel.h>
@@ -35,6 +39,34 @@
  */
 static int timer = 0;
 
+#ifdef CONFIG_XEN
+int oprofile_set_active(int active_domains[], unsigned int adomains)
+{
+	int err;
+
+	if (!oprofile_ops.set_active)
+		return -EINVAL;
+
+	mutex_lock(&start_mutex);
+	err = oprofile_ops.set_active(active_domains, adomains);
+	mutex_unlock(&start_mutex);
+	return err;
+}
+
+int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
+{
+	int err;
+
+	if (!oprofile_ops.set_passive)
+		return -EINVAL;
+
+	mutex_lock(&start_mutex);
+	err = oprofile_ops.set_passive(passive_domains, pdomains);
+	mutex_unlock(&start_mutex);
+	return err;
+}
+#endif
+
 int oprofile_setup(void)
 {
 	int err;
--- linux-ec2-2.6.32.orig/drivers/oprofile/event_buffer.h
+++ linux-ec2-2.6.32/drivers/oprofile/event_buffer.h
@@ -30,6 +30,9 @@
 #define INVALID_COOKIE ~0UL
 #define NO_COOKIE 0UL
 
+/* Constant used to refer to coordinator domain (Xen) */
+#define COORDINATOR_DOMAIN -1
+
 extern const struct file_operations event_buffer_fops;
 
 /* mutex between sync_cpu_buffers() and the
--- linux-ec2-2.6.32.orig/drivers/oprofile/oprofile_files.c
+++ linux-ec2-2.6.32/drivers/oprofile/oprofile_files.c
@@ -5,11 +5,17 @@
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ *
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
  */
 
 #include <linux/fs.h>
 #include <linux/oprofile.h>
 #include <linux/jiffies.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
 
 #include "event_buffer.h"
 #include "oprofile_stats.h"
@@ -165,6 +171,200 @@
 	.write		= dump_write,
 };
 
+#ifdef CONFIG_XEN
+#include <linux/slab.h>
+
+#define TMPBUFSIZE 512
+
+static unsigned int adomains = 0;
+static int active_domains[MAX_OPROF_DOMAINS + 1];
+static DEFINE_MUTEX(adom_mutex);
+
+static ssize_t adomain_write(struct file * file, char const __user * buf,
+			     size_t count, loff_t * offset)
+{
+	char *tmpbuf;
+	char *startp, *endp;
+	int i;
+	unsigned long val;
+	ssize_t retval = count;
+
+	if (*offset)
+		return -EINVAL;
+	if (count > TMPBUFSIZE - 1)
+		return -EINVAL;
+
+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (copy_from_user(tmpbuf, buf, count)) {
+		kfree(tmpbuf);
+		return -EFAULT;
+	}
+	tmpbuf[count] = 0;
+
+	mutex_lock(&adom_mutex);
+
+	startp = tmpbuf;
+	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
+	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
+		val = simple_strtoul(startp, &endp, 0);
+		if (endp == startp)
+			break;
+		while (ispunct(*endp) || isspace(*endp))
+			endp++;
+		active_domains[i] = val;
+		if (active_domains[i] != val)
+			/* Overflow, force error below */
+			i = MAX_OPROF_DOMAINS + 1;
+		startp = endp;
+	}
+	/* Force error on trailing junk */
+	adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
+
+	kfree(tmpbuf);
+
+	if (adomains > MAX_OPROF_DOMAINS
+	    || oprofile_set_active(active_domains, adomains)) {
+		adomains = 0;
+		retval = -EINVAL;
+	}
+
+	mutex_unlock(&adom_mutex);
+	return retval;
+}
+
+static ssize_t adomain_read(struct file * file, char __user * buf,
+			    size_t count, loff_t * offset)
+{
+	char * tmpbuf;
+	size_t len;
+	int i;
+	ssize_t retval;
+
+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
+		return -ENOMEM;
+
+	mutex_lock(&adom_mutex);
+
+	len = 0;
+	for (i = 0; i < adomains; i++)
+		len += snprintf(tmpbuf + len,
+				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
+				"%u ", active_domains[i]);
+	WARN_ON(len > TMPBUFSIZE);
+	if (len != 0 && len <= TMPBUFSIZE)
+		tmpbuf[len-1] = '\n';
+
+	mutex_unlock(&adom_mutex);
+
+	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
+
+	kfree(tmpbuf);
+	return retval;
+}
+
+
+static const struct file_operations active_domain_ops = {
+	.read		= adomain_read,
+	.write		= adomain_write,
+};
+
+static unsigned int pdomains = 0;
+static int passive_domains[MAX_OPROF_DOMAINS];
+static DEFINE_MUTEX(pdom_mutex);
+
+static ssize_t pdomain_write(struct file * file, char const __user * buf,
+			     size_t count, loff_t * offset)
+{
+	char *tmpbuf;
+	char *startp, *endp;
+	int i;
+	unsigned long val;
+	ssize_t retval = count;
+
+	if (*offset)
+		return -EINVAL;
+	if (count > TMPBUFSIZE - 1)
+		return -EINVAL;
+
+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (copy_from_user(tmpbuf, buf, count)) {
+		kfree(tmpbuf);
+		return -EFAULT;
+	}
+	tmpbuf[count] = 0;
+
+	mutex_lock(&pdom_mutex);
+
+	startp = tmpbuf;
+	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
+	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
+		val = simple_strtoul(startp, &endp, 0);
+		if (endp == startp)
+			break;
+		while (ispunct(*endp) || isspace(*endp))
+			endp++;
+		passive_domains[i] = val;
+		if (passive_domains[i] != val)
+			/* Overflow, force error below */
+			i = MAX_OPROF_DOMAINS + 1;
+		startp = endp;
+	}
+	/* Force error on trailing junk */
+	pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
+
+	kfree(tmpbuf);
+
+	if (pdomains > MAX_OPROF_DOMAINS
+	    || oprofile_set_passive(passive_domains, pdomains)) {
+		pdomains = 0;
+		retval = -EINVAL;
+	}
+
+	mutex_unlock(&pdom_mutex);
+	return retval;
+}
+
+static ssize_t pdomain_read(struct file * file, char __user * buf,
+			    size_t count, loff_t * offset)
+{
+	char * tmpbuf;
+	size_t len;
+	int i;
+	ssize_t retval;
+
+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
+		return -ENOMEM;
+
+	mutex_lock(&pdom_mutex);
+
+	len = 0;
+	for (i = 0; i < pdomains; i++)
+		len += snprintf(tmpbuf + len,
+				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
+				"%u ", passive_domains[i]);
+	WARN_ON(len > TMPBUFSIZE);
+	if (len != 0 && len <= TMPBUFSIZE)
+		tmpbuf[len-1] = '\n';
+
+	mutex_unlock(&pdom_mutex);
+
+	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
+
+	kfree(tmpbuf);
+	return retval;
+}
+
+static const struct file_operations passive_domain_ops = {
+	.read		= pdomain_read,
+	.write		= pdomain_write,
+};
+
+#endif /* CONFIG_XEN */
+
 void oprofile_create_files(struct super_block *sb, struct dentry *root)
 {
 	/* reinitialize default values */
@@ -175,6 +375,10 @@
 
 	oprofilefs_create_file(sb, root, "enable", &enable_fops);
 	oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
+#ifdef CONFIG_XEN
+	oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
+	oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops);
+#endif
 	oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
 	oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size);
 	oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed);
--- linux-ec2-2.6.32.orig/drivers/oprofile/cpu_buffer.h
+++ linux-ec2-2.6.32/drivers/oprofile/cpu_buffer.h
@@ -40,7 +40,7 @@
 struct oprofile_cpu_buffer {
 	unsigned long buffer_size;
 	struct task_struct *last_task;
-	int last_is_kernel;
+	int last_cpu_mode;
 	int tracing;
 	unsigned long sample_received;
 	unsigned long sample_lost_overflow;
@@ -62,7 +62,7 @@
 {
 	struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
 
-	cpu_buf->last_is_kernel = -1;
+	cpu_buf->last_cpu_mode = -1;
 	cpu_buf->last_task = NULL;
 }
 
@@ -112,9 +112,13 @@
 }
 
 /* extra data flags */
-#define KERNEL_CTX_SWITCH	(1UL << 0)
-#define IS_KERNEL		(1UL << 1)
+#define CPU_MODE_USER		0
+#define CPU_MODE_KERNEL		1
+#define CPU_MODE_XEN		2
+#define CPU_MODE_MASK		3
 #define TRACE_BEGIN		(1UL << 2)
 #define USER_CTX_SWITCH		(1UL << 3)
+#define KERNEL_CTX_SWITCH	(1UL << 4)
+#define DOMAIN_SWITCH		(1UL << 5)
 
 #endif /* OPROFILE_CPU_BUFFER_H */
--- linux-ec2-2.6.32.orig/drivers/oprofile/buffer_sync.c
+++ linux-ec2-2.6.32/drivers/oprofile/buffer_sync.c
@@ -8,6 +8,10 @@
  * @author Barry Kasindorf
  * @author Robert Richter <robert.richter@amd.com>
  *
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ *
  * This is the core of the buffer management. Each
  * CPU buffer is processed and entered into the
  * global event buffer. Such processing is necessary
@@ -42,6 +46,10 @@
 static DEFINE_SPINLOCK(task_mortuary);
 static void process_task_mortuary(void);
 
+#ifdef CONFIG_XEN
+static int cpu_current_domain[NR_CPUS];
+#endif
+
 /* Take ownership of the task struct and place it on the
  * list for processing. Only after two full buffer syncs
  * does the task eventually get freed, because by then
@@ -60,7 +68,6 @@
 	return NOTIFY_OK;
 }
 
-
 /* The task is on its way out. A sync of the buffer means we can catch
  * any remaining samples for this task.
  */
@@ -140,24 +147,21 @@
 	.notifier_call = module_load_notify,
 };
 
-
-static void end_sync(void)
-{
-	end_cpu_work();
-	/* make sure we don't leak task structs */
-	process_task_mortuary();
-	process_task_mortuary();
-}
-
-
 int sync_start(void)
 {
 	int err;
+#ifdef CONFIG_XEN
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		cpu_current_domain[i] = COORDINATOR_DOMAIN;
+	}
+#endif
 
 	if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
 		return -ENOMEM;
 
-	start_cpu_work();
+	mutex_lock(&buffer_mutex);
 
 	err = task_handoff_register(&task_free_nb);
 	if (err)
@@ -172,7 +176,10 @@
 	if (err)
 		goto out4;
 
+	start_cpu_work();
+
 out:
+	mutex_unlock(&buffer_mutex);
 	return err;
 out4:
 	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
@@ -181,7 +188,6 @@
 out2:
 	task_handoff_unregister(&task_free_nb);
 out1:
-	end_sync();
 	free_cpumask_var(marked_cpus);
 	goto out;
 }
@@ -189,11 +195,20 @@
 
 void sync_stop(void)
 {
+	/* flush buffers */
+	mutex_lock(&buffer_mutex);
+	end_cpu_work();
 	unregister_module_notifier(&module_load_nb);
 	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
 	profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
 	task_handoff_unregister(&task_free_nb);
-	end_sync();
+	mutex_unlock(&buffer_mutex);
+	flush_scheduled_work();
+
+	/* make sure we don't leak task structs */
+	process_task_mortuary();
+	process_task_mortuary();
+
 	free_cpumask_var(marked_cpus);
 }
 
@@ -284,15 +299,33 @@
 	last_cookie = INVALID_COOKIE;
 }
 
-static void add_kernel_ctx_switch(unsigned int in_kernel)
+static void add_cpu_mode_switch(unsigned int cpu_mode)
 {
 	add_event_entry(ESCAPE_CODE);
-	if (in_kernel)
+	switch (cpu_mode) {
+	case CPU_MODE_USER:
+		add_event_entry(USER_ENTER_SWITCH_CODE);
+		break;
+	case CPU_MODE_KERNEL:
 		add_event_entry(KERNEL_ENTER_SWITCH_CODE);
-	else
-		add_event_entry(KERNEL_EXIT_SWITCH_CODE);
+		break;
+	case CPU_MODE_XEN:
+		add_event_entry(XEN_ENTER_SWITCH_CODE);
+	  	break;
+	default:
+		break;
+	}
 }
 
+#ifdef CONFIG_XEN
+static void add_domain_switch(unsigned long domain_id)
+{
+	add_event_entry(ESCAPE_CODE);
+	add_event_entry(DOMAIN_SWITCH_CODE);
+	add_event_entry(domain_id);
+}
+#endif
+
 static void
 add_user_ctx_switch(struct task_struct const *task, unsigned long cookie)
 {
@@ -371,12 +404,12 @@
  * for later lookup from userspace. Return 0 on failure.
  */
 static int
-add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
+add_sample(struct mm_struct *mm, struct op_sample *s, int cpu_mode)
 {
 	unsigned long cookie;
 	off_t offset;
 
-	if (in_kernel) {
+	if (cpu_mode >= CPU_MODE_KERNEL) {
 		add_sample_entry(s->eip, s->event);
 		return 1;
 	}
@@ -501,7 +534,7 @@
 	unsigned long val;
 	struct task_struct *new;
 	unsigned long cookie = 0;
-	int in_kernel = 1;
+	int cpu_mode = CPU_MODE_KERNEL;
 	sync_buffer_state state = sb_buffer_start;
 	unsigned int i;
 	unsigned long available;
@@ -513,6 +546,13 @@
 
 	add_cpu_switch(cpu);
 
+#ifdef CONFIG_XEN
+	/* We need to assign the first samples in this CPU buffer to the
+	   same domain that we were processing at the last sync_buffer */
+	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
+		add_domain_switch(cpu_current_domain[cpu]);
+#endif
+
 	op_cpu_buffer_reset(cpu);
 	available = op_cpu_buffer_entries(cpu);
 
@@ -529,10 +569,10 @@
 			}
 			if (flags & KERNEL_CTX_SWITCH) {
 				/* kernel/userspace switch */
-				in_kernel = flags & IS_KERNEL;
+				cpu_mode = flags & CPU_MODE_MASK;
 				if (state == sb_buffer_start)
 					state = sb_sample_start;
-				add_kernel_ctx_switch(flags & IS_KERNEL);
+				add_cpu_mode_switch(cpu_mode);
 			}
 			if (flags & USER_CTX_SWITCH
 			    && op_cpu_buffer_get_data(&entry, &val)) {
@@ -545,16 +585,30 @@
 					cookie = get_exec_dcookie(mm);
 				add_user_ctx_switch(new, cookie);
 			}
+#ifdef CONFIG_XEN
+			if ((flags & DOMAIN_SWITCH)
+			    && op_cpu_buffer_get_data(&entry, &val)) {
+				cpu_current_domain[cpu] = val;
+				add_domain_switch(val);
+			}
+#endif
 			if (op_cpu_buffer_get_size(&entry))
 				add_data(&entry, mm);
 			continue;
 		}
 
+#ifdef CONFIG_XEN
+		if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) {
+			add_sample_entry(sample->eip, sample->event);
+			continue;
+		}
+#endif
+
 		if (state < sb_bt_start)
 			/* ignore sample */
 			continue;
 
-		if (add_sample(mm, sample, in_kernel))
+		if (add_sample(mm, sample, cpu_mode))
 			continue;
 
 		/* ignore backtraces if failed to add a sample */
@@ -565,6 +619,12 @@
 	}
 	release_mm(mm);
 
+#ifdef CONFIG_XEN
+	/* We reset domain to COORDINATOR at each CPU switch */
+	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
+		add_domain_switch(COORDINATOR_DOMAIN);
+#endif
+
 	mark_done(cpu);
 
 	mutex_unlock(&buffer_mutex);
--- linux-ec2-2.6.32.orig/drivers/message/fusion/mptctl.c
+++ linux-ec2-2.6.32/drivers/message/fusion/mptctl.c
@@ -577,6 +577,13 @@
 }
 
 static int
+mptctl_release(struct inode *inode, struct file *filep)
+{
+	fasync_helper(-1, filep, 0, &async_queue);
+	return 0;
+}
+
+static int
 mptctl_fasync(int fd, struct file *filep, int mode)
 {
 	MPT_ADAPTER	*ioc;
@@ -621,11 +628,8 @@
 	 */
 	iocnumX = khdr.iocnum & 0xFF;
 	if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) ||
-	    (iocp == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnumX);
+	    (iocp == NULL))
 		return -ENODEV;
-	}
 
 	if (!iocp->active) {
 		printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n",
@@ -2781,6 +2785,7 @@
 	.llseek =	no_llseek,
 	.fasync = 	mptctl_fasync,
 	.unlocked_ioctl = mptctl_ioctl,
+	.release =	mptctl_release,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = compat_mpctl_ioctl,
 #endif
--- linux-ec2-2.6.32.orig/drivers/message/fusion/mptbase.c
+++ linux-ec2-2.6.32/drivers/message/fusion/mptbase.c
@@ -3232,6 +3232,16 @@
 	pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
 	pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
 	pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
+	/*
+	 * VMware emulation is broken, its PortFact's MaxDevices reports value
+	 * programmed by IOC Init, so if you program IOC Init to 256 (which is 0,
+	 * as that field is only 8 bit), it reports back 0 in port facts, instead
+	 * of 256...  And unfortunately using 256 triggers another bug in the
+	 * code (parallel SCSI can have only 16 devices).
+	 */
+	if (pfacts->MaxDevices == 0) {
+	   pfacts->MaxDevices = 16;
+	}
 	pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
 	pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
 	pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
@@ -4330,6 +4340,8 @@
 
 	if (ioc->bus_type == SPI)
 		num_chain *= MPT_SCSI_CAN_QUEUE;
+	else if (ioc->bus_type == SAS)
+		num_chain *= MPT_SAS_CAN_QUEUE;
 	else
 		num_chain *= MPT_FC_CAN_QUEUE;
 
--- linux-ec2-2.6.32.orig/drivers/message/fusion/mptscsih.c
+++ linux-ec2-2.6.32/drivers/message/fusion/mptscsih.c
@@ -792,11 +792,36 @@
 			 *  precedence!
 			 */
 			sc->result = (DID_OK << 16) | scsi_status;
-			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
-				/* Have already saved the status and sense data
+			if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
+
+				/*
+				 * For an Errata on LSI53C1030
+				 * When the length of request data
+				 * and transfer data are different
+				 * with result of command (READ or VERIFY),
+				 * DID_SOFT_ERROR is set.
 				 */
-				;
-			} else {
+				if (ioc->bus_type == SPI) {
+					if (pScsiReq->CDB[0] == READ_6  ||
+					    pScsiReq->CDB[0] == READ_10 ||
+					    pScsiReq->CDB[0] == READ_12 ||
+					    pScsiReq->CDB[0] == READ_16 ||
+					    pScsiReq->CDB[0] == VERIFY  ||
+					    pScsiReq->CDB[0] == VERIFY_16) {
+						if (scsi_bufflen(sc) !=
+							xfer_cnt) {
+							sc->result =
+							DID_SOFT_ERROR << 16;
+						    printk(KERN_WARNING "Errata"
+						    "on LSI53C1030 occurred."
+						    "sc->req_bufflen=0x%02x,"
+						    "xfer_cnt=0x%02x\n",
+						    scsi_bufflen(sc),
+						    xfer_cnt);
+						}
+					}
+				}
+
 				if (xfer_cnt < sc->underflow) {
 					if (scsi_status == SAM_STAT_BUSY)
 						sc->result = SAM_STAT_BUSY;
@@ -835,7 +860,58 @@
 			sc->result = (DID_OK << 16) | scsi_status;
 			if (scsi_state == 0) {
 				;
-			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+			} else if (scsi_state &
+			    MPI_SCSI_STATE_AUTOSENSE_VALID) {
+
+				/*
+				 * For potential trouble on LSI53C1030.
+				 * (date:2007.xx.)
+				 * It is checked whether the length of
+				 * request data is equal to
+				 * the length of transfer and residual.
+				 * MEDIUM_ERROR is set by incorrect data.
+				 */
+				if ((ioc->bus_type == SPI) &&
+					(sc->sense_buffer[2] & 0x20)) {
+					u32	 difftransfer;
+					difftransfer =
+					sc->sense_buffer[3] << 24 |
+					sc->sense_buffer[4] << 16 |
+					sc->sense_buffer[5] << 8 |
+					sc->sense_buffer[6];
+					if (((sc->sense_buffer[3] & 0x80) ==
+						0x80) && (scsi_bufflen(sc)
+						!= xfer_cnt)) {
+						sc->sense_buffer[2] =
+						    MEDIUM_ERROR;
+						sc->sense_buffer[12] = 0xff;
+						sc->sense_buffer[13] = 0xff;
+						printk(KERN_WARNING"Errata"
+						"on LSI53C1030 occurred."
+						"sc->req_bufflen=0x%02x,"
+						"xfer_cnt=0x%02x\n" ,
+						scsi_bufflen(sc),
+						xfer_cnt);
+					}
+					if (((sc->sense_buffer[3] & 0x80)
+						!= 0x80) &&
+						(scsi_bufflen(sc) !=
+						xfer_cnt + difftransfer)) {
+						sc->sense_buffer[2] =
+							MEDIUM_ERROR;
+						sc->sense_buffer[12] = 0xff;
+						sc->sense_buffer[13] = 0xff;
+						printk(KERN_WARNING
+						"Errata on LSI53C1030 occurred"
+						"sc->req_bufflen=0x%02x,"
+						" xfer_cnt=0x%02x,"
+						"difftransfer=0x%02x\n",
+						scsi_bufflen(sc),
+						xfer_cnt,
+						difftransfer);
+					}
+				}
+
 				/*
 				 * If running against circa 200003dd 909 MPT f/w,
 				 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
@@ -1720,7 +1796,7 @@
 		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
 		   "Command not in the active list! (sc=%p)\n", ioc->name,
 		   SCpnt));
-		retval = 0;
+		retval = SUCCESS;
 		goto out;
 	}
 
@@ -1759,8 +1835,9 @@
 	}
 
  out:
-	printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
-	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt);
+	printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p) (sn=%ld)\n",
+	    ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval,
+	    SCpnt, SCpnt->serial_number);
 
 	return retval;
 }
@@ -1797,7 +1874,7 @@
 
 	vdevice = SCpnt->device->hostdata;
 	if (!vdevice || !vdevice->vtarget) {
-		retval = SUCCESS;
+		retval = 0;
 		goto out;
 	}
 
@@ -2363,6 +2440,8 @@
 		ioc->name,sdev->tagged_supported, sdev->simple_tags,
 		sdev->ordered_tags));
 
+	blk_queue_dma_alignment (sdev->request_queue, 512 - 1);
+
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/pci/probe.c
+++ linux-ec2-2.6.32/drivers/pci/probe.c
@@ -1087,7 +1087,11 @@
 	if (dev && !dev->is_added)	/* new device? */
 		nr++;
 
+#ifndef pcibios_scan_all_fns
 	if (dev && dev->multifunction) {
+#else
+	if (dev ? dev->multifunction : pcibios_scan_all_fns(bus, devfn)) {
+#endif
 		for (fn = 1; fn < 8; fn++) {
 			dev = pci_scan_single_device(bus, devfn + fn);
 			if (dev) {
--- linux-ec2-2.6.32.orig/drivers/pci/guestdev.c
+++ linux-ec2-2.6.32/drivers/pci/guestdev.c
@@ -0,0 +1,887 @@
+/*
+ * Copyright (c) 2008, 2009 NEC Corporation.
+ * Copyright (c) 2009 Isaku Yamahata
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <asm/setup.h>
+
+#define HID_LEN 8
+#define UID_LEN 8
+#define DEV_LEN 2
+#define FUNC_LEN 1
+#define DEV_NUM_MAX 31
+#define FUNC_NUM_MAX 7
+#define INVALID_SEG (-1)
+#define INVALID_BBN (-1)
+#define GUESTDEV_STR_MAX 128
+
+#define GUESTDEV_FLAG_TYPE_MASK 0x3
+#define GUESTDEV_FLAG_DEVICEPATH 0x1
+#define GUESTDEV_FLAG_SBDF 0x2
+
+#define GUESTDEV_OPT_IOMUL	0x1
+
+struct guestdev {
+	int flags;
+	int options;
+	struct list_head root_list;
+	union {
+		struct devicepath {
+			char hid[HID_LEN + 1];
+			char uid[UID_LEN + 1];
+			int seg;
+			int bbn;
+			struct devicepath_node *child;
+		} devicepath;
+		struct sbdf {
+			int seg;
+			int bus;
+			int dev;
+			int func;
+		} sbdf;
+	} u;
+};
+
+struct devicepath_node {
+	int dev;
+	int func;
+	struct devicepath_node *child;
+};
+
+struct pcidev_sbdf {
+	int seg;
+	int bus;
+	struct pcidev_sbdf_node *child;
+};
+
+struct pcidev_sbdf_node {
+	int dev;
+	int func;
+	struct pcidev_sbdf_node *child;
+};
+
+static char guestdev_param[COMMAND_LINE_SIZE];
+static LIST_HEAD(guestdev_list);
+
+/* Get hid and uid */
+static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
+{
+	char *sp, *ep;
+	int len;
+
+	sp = str;
+	ep = strchr(sp, ':');
+	if (!ep) {
+		ep = strchr(sp, '-');
+		if (!ep)
+			goto format_err_end;
+	}
+	/* hid length */
+	len = ep - sp;
+	if (len <= 0 || HID_LEN < len)
+		goto format_err_end;
+
+	strlcpy(hid, sp, len);
+
+	if (*ep == '-') { /* no uid */
+		uid[0] = '\0';
+		return TRUE;
+	}
+
+	sp = ep + 1;
+	ep = strchr(sp, '-');
+	if (!ep)
+		ep = strchr(sp, '\0');
+
+	/* uid length */
+	len = ep - sp;
+	if (len <= 0 || UID_LEN < len)
+		goto format_err_end;
+
+	strlcpy(uid, sp, len);
+	return TRUE;
+
+format_err_end:
+	return FALSE;
+}
+
+/* Get device and function */
+static int __init pci_get_dev_func(char *str, int *dev, int *func)
+{
+	if (sscanf(str, "%02x.%01x", dev, func) != 2)
+		goto format_err_end;
+
+	if (*dev < 0 || DEV_NUM_MAX < *dev)
+		goto format_err_end;
+
+	if (*func < 0 || FUNC_NUM_MAX < *func)
+		goto format_err_end;
+
+	return TRUE;
+
+format_err_end:
+	return FALSE;
+}
+
+/* Check extended guestdev parameter format error */
+static int __init pci_check_extended_guestdev_format(char *str)
+{
+	int flg;
+	char *p;
+
+	/* Check extended format */
+	if (strpbrk(str, "(|)") == NULL)
+		return TRUE;
+
+	flg = 0;
+	p = str;
+	while (*p) {
+		switch (*p) {
+		case '(':
+			/* Check nesting error */
+			if (flg != 0)
+				goto format_err_end;
+			flg = 1;
+			/* Check position of '(' is head or
+			   previos charactor of '(' is not '-'. */
+			if (p == str || *(p - 1) != '-')
+				goto format_err_end;
+			break;
+		case ')':
+			/* Check nesting error */
+			if (flg != 1)
+				goto format_err_end;
+			flg = 0;
+			/* Check next charactor of ')' is not '\0' */
+			if (*(p + 1) != '\0')
+				goto format_err_end;
+			break;
+		case '|':
+			/* Check position of '|' is outside of '(' and ')' */
+			if (flg != 1)
+				goto format_err_end;
+			break;
+		default:
+			break;
+		}
+		p++;
+	}
+	/* Check number of '(' and ')' are not equal */
+	if (flg != 0)
+		goto format_err_end;
+	return TRUE;
+
+format_err_end:
+	printk(KERN_ERR
+		"PCI: The format of the guestdev parameter is illegal. [%s]\n",
+		str);
+	return FALSE;
+}
+
+/* Make guestdev strings */
+static void pci_make_guestdev_str(struct guestdev *gdev,
+					char *gdev_str, int buf_size)
+{
+	struct devicepath_node *node;
+	int count;
+
+	switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+	case GUESTDEV_FLAG_DEVICEPATH:
+		memset(gdev_str, 0, buf_size);
+
+		if (strlen(gdev->u.devicepath.uid))
+			count = snprintf(gdev_str, buf_size, "%s:%s",
+						gdev->u.devicepath.hid,
+						gdev->u.devicepath.uid);
+		else
+			count = snprintf(gdev_str, buf_size, "%s",
+						 gdev->u.devicepath.hid);
+		if (count < 0)
+			return;
+
+		node = gdev->u.devicepath.child;
+		while (node) {
+			gdev_str += count;
+			buf_size -= count;
+			if (buf_size <= 0)
+				return;
+			count = snprintf(gdev_str, buf_size, "-%02x.%01x",
+				node->dev, node->func);
+			if (count < 0)
+				return;
+			node = node->child;
+		}
+		break;
+	case GUESTDEV_FLAG_SBDF:
+		snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
+					gdev->u.sbdf.seg, gdev->u.sbdf.bus,
+					gdev->u.sbdf.dev, gdev->u.sbdf.func);
+		break;
+	default:
+		BUG();
+	}
+}
+
+/* Free guestdev and nodes */
+static void __init pci_free_guestdev(struct guestdev *gdev)
+{
+	struct devicepath_node *node, *next;
+
+	if (!gdev)
+		return;
+	if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
+		node = gdev->u.devicepath.child;
+		while (node) {
+			next = node->child;
+			kfree(node);
+			node = next;
+		}
+	}
+	list_del(&gdev->root_list);
+	kfree(gdev);
+}
+
+/* Copy guestdev and nodes */
+struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
+{
+	struct guestdev *gdev;
+	struct devicepath_node *node, *node_src, *node_upper;
+
+	BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
+
+	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
+	if (!gdev)
+		goto allocate_err_end;
+
+	memset(gdev, 0, sizeof(*gdev));
+	INIT_LIST_HEAD(&gdev->root_list);
+	gdev->flags = gdev_src->flags;
+	gdev->options = gdev_src->options;
+	strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
+	strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
+	gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
+	gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
+
+	node_upper = NULL;
+
+	node_src = gdev_src->u.devicepath.child;
+	while (node_src) {
+		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		if (!node)
+			goto allocate_err_end;
+		memset(node, 0, sizeof(*node));
+		node->dev = node_src->dev;
+		node->func = node_src->func;
+		if (!node_upper)
+			gdev->u.devicepath.child = node;
+		else
+			node_upper->child = node;
+		node_upper = node;
+		node_src = node_src->child;
+	}
+
+	return gdev;
+
+allocate_err_end:
+	if (gdev)
+		pci_free_guestdev(gdev);
+	printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+	return NULL;
+}
+
+/* Make guestdev from path strings */
+static int __init pci_make_devicepath_guestdev(char *path_str, int options)
+{
+	char hid[HID_LEN + 1], uid[UID_LEN + 1];
+	char *sp, *ep;
+	struct guestdev *gdev, *gdev_org;
+	struct devicepath_node *node, *node_tmp;
+	int dev, func, ret_val;
+
+	ret_val = 0;
+	gdev = gdev_org = NULL;
+	sp = path_str;
+	/* Look for end of hid:uid'-' */
+	ep = strchr(sp, '-');
+	/* Only hid, uid. (No dev, func) */
+	if (!ep)
+		goto format_err_end;
+
+	memset(hid, 0 ,sizeof(hid));
+	memset(uid, 0, sizeof(uid));
+	if (!pci_get_hid_uid(sp, hid, uid))
+		goto format_err_end;
+
+	gdev_org = kmalloc(sizeof(*gdev_org), GFP_KERNEL);
+	if (!gdev_org)
+		goto allocate_err_end;
+	memset(gdev_org, 0, sizeof(*gdev_org));
+	INIT_LIST_HEAD(&gdev_org->root_list);
+	gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
+	gdev_org->options = options;
+	strcpy(gdev_org->u.devicepath.hid, hid);
+	strcpy(gdev_org->u.devicepath.uid, uid);
+	gdev_org->u.devicepath.seg = INVALID_SEG;
+	gdev_org->u.devicepath.bbn = INVALID_BBN;
+
+	gdev = gdev_org;
+
+	sp = ep + 1;
+	ep = sp;
+	do {
+		if (*sp == '(') {
+			sp++;
+			if (strchr(sp, '|')) {
+				gdev = pci_copy_guestdev(gdev_org);
+				if (!gdev) {
+					ret_val = -ENOMEM;
+					goto end;
+				}
+			}
+			continue;
+		}
+		if (gdev && pci_get_dev_func(sp, &dev, &func)) {
+			node = kmalloc(sizeof(*node), GFP_KERNEL);
+			if (!node)
+				goto allocate_err_end;
+			memset(node, 0, sizeof(*node));
+			node->dev = dev;
+			node->func = func;
+			/* add node to end of guestdev */
+			if (gdev->u.devicepath.child) {
+				node_tmp = gdev->u.devicepath.child;
+				while (node_tmp->child) {
+					node_tmp = node_tmp->child;
+				}
+				node_tmp->child = node;
+			} else
+				gdev->u.devicepath.child = node;
+		} else if (gdev) {
+			printk(KERN_ERR
+				"PCI: Can't obtain dev# and #func# from %s.\n",
+				sp);
+			ret_val = -EINVAL;
+			if (gdev == gdev_org)
+				goto end;
+			pci_free_guestdev(gdev);
+			gdev = NULL;
+		}
+
+		ep = strpbrk(sp, "-|)");
+		if (!ep)
+			ep = strchr(sp, '\0');
+		/* Is *ep '|' OR ')' OR '\0' ? */
+		if (*ep != '-') {
+			if (gdev)
+				list_add_tail(&gdev->root_list, &guestdev_list);
+			if (*ep == '|') {
+				/* Between '|' and '|' ? */
+				if (strchr(ep + 1, '|')) {
+					gdev = pci_copy_guestdev(gdev_org);
+					if (!gdev) {
+						ret_val = -ENOMEM;
+						goto end;
+					}
+				} else {
+					gdev = gdev_org;
+					gdev_org = NULL;
+				}
+			} else {
+				gdev_org = NULL;
+				gdev = NULL;
+			}
+		}
+		if (*ep == ')')
+			ep++;
+		sp = ep + 1;
+	} while (*ep != '\0');
+
+	goto end;
+
+format_err_end:
+	printk(KERN_ERR
+		"PCI: The format of the guestdev parameter is illegal. [%s]\n",
+		path_str);
+	ret_val = -EINVAL;
+	goto end;
+
+allocate_err_end:
+	printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+	ret_val = -ENOMEM;
+	goto end;
+
+end:
+	if (gdev_org && (gdev_org != gdev))
+		pci_free_guestdev(gdev_org);
+	if (gdev)
+		pci_free_guestdev(gdev);
+	return ret_val;
+}
+
+static int __init pci_make_sbdf_guestdev(char* str, int options)
+{
+	struct guestdev *gdev;
+	int seg, bus, dev, func;
+
+	if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
+		seg = 0;
+		if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
+			return -EINVAL;
+	}
+	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
+	if (!gdev) {
+		printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(&gdev->root_list);
+	gdev->flags = GUESTDEV_FLAG_SBDF;
+	gdev->options = options;
+	gdev->u.sbdf.seg = seg;
+	gdev->u.sbdf.bus = bus;
+	gdev->u.sbdf.dev = dev;
+	gdev->u.sbdf.func = func;
+	list_add_tail(&gdev->root_list, &guestdev_list);
+	return 0;
+}
+
+static int __init pci_parse_options(const char *str)
+{
+	int options = 0;
+	char *ep;
+
+	while (str) {
+		str++;
+		ep = strchr(str, '+');
+		if (ep)
+			ep = '\0';	/* Chop */
+
+		if (!strcmp(str, "iomul"))
+			options |= GUESTDEV_OPT_IOMUL;
+
+		str = ep;
+	}
+	return options;
+}
+
+/* Parse guestdev parameter */
+static int __init pci_parse_guestdev(void)
+{
+	int len;
+	char *sp, *ep, *op;
+	int options;
+	struct list_head *head;
+	struct guestdev *gdev;
+	char path_str[GUESTDEV_STR_MAX];
+	int ret_val = 0;
+
+	len = strlen(guestdev_param);
+	if (len == 0)
+		return 0;
+
+	sp = guestdev_param;
+
+	do {
+		ep = strchr(sp, ',');
+		/* Chop */
+		if (ep)
+			*ep = '\0';
+		options = 0;
+		op = strchr(sp, '+');
+		if (op && (!ep || op < ep)) {
+			options = pci_parse_options(op);
+			*op = '\0';	/* Chop */
+		}
+		ret_val = pci_make_sbdf_guestdev(sp, options);
+		if (ret_val == -EINVAL) {
+			if (pci_check_extended_guestdev_format(sp)) {
+				ret_val = pci_make_devicepath_guestdev(
+					sp, options);
+				if (ret_val && ret_val != -EINVAL)
+					break;
+			}
+		} else if (ret_val)
+			break;
+
+		if (ep)
+			ep++;
+		sp = ep;
+	} while (ep);
+
+	list_for_each(head, &guestdev_list) {
+		gdev = list_entry(head, struct guestdev, root_list);
+		pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
+		printk(KERN_DEBUG
+			"PCI: %s has been reserved for guest domain.\n",
+			path_str);
+	}
+	return 0;
+}
+
+arch_initcall(pci_parse_guestdev);
+
+/* Get command line */
+static int __init pci_guestdev_setup(char *str)
+{
+	if (strlen(str) >= COMMAND_LINE_SIZE)
+		return 0;
+	strlcpy(guestdev_param, str, sizeof(guestdev_param));
+	return 1;
+}
+
+__setup("guestdev=", pci_guestdev_setup);
+
+/* Free sbdf and nodes */
+static void pci_free_sbdf(struct pcidev_sbdf *sbdf)
+{
+	struct pcidev_sbdf_node *node, *next;
+
+	node = sbdf->child;
+	while (node) {
+		next = node->child;
+		kfree(node);
+		node = next;
+	}
+	/* Skip kfree(sbdf) */
+}
+
+/* Does PCI device belong to sub tree specified by guestdev with device path? */
+typedef int (*pci_node_match_t)(const struct devicepath_node *gdev_node,
+				const struct pcidev_sbdf_node *sbdf_node,
+				int options);
+
+static int pci_node_match(const struct devicepath_node *gdev_node,
+			  const struct pcidev_sbdf_node *sbdf_node,
+			  int options_unused)
+{
+	return (gdev_node->dev == sbdf_node->dev &&
+		gdev_node->func == sbdf_node->func);
+}
+
+static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
+					 struct pcidev_sbdf *sbdf,
+					 pci_node_match_t match)
+{
+	int seg, bbn;
+	struct devicepath_node *gdev_node;
+	struct pcidev_sbdf_node *sbdf_node;
+
+	if (!gdev || !sbdf)
+		return FALSE;
+
+	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
+	/* Compare seg and bbn */
+	if (gdev->u.devicepath.seg == INVALID_SEG ||
+	    gdev->u.devicepath.bbn == INVALID_BBN) {
+		if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
+		    gdev->u.devicepath.uid, &seg, &bbn)) {
+			gdev->u.devicepath.seg = seg;
+			gdev->u.devicepath.bbn = bbn;
+		} else
+			return FALSE;
+	}
+
+	if (gdev->u.devicepath.seg != sbdf->seg ||
+	    gdev->u.devicepath.bbn != sbdf->bus)
+		return FALSE;
+
+	gdev_node = gdev->u.devicepath.child;
+	sbdf_node = sbdf->child;
+
+	/* Compare dev and func */
+	while (gdev_node) {
+		if (!sbdf_node)
+			return FALSE;
+		if (!match(gdev_node, sbdf_node, gdev->options))
+			return FALSE;
+		gdev_node = gdev_node->child;
+		sbdf_node = sbdf_node->child;
+	}
+	return TRUE;
+}
+
+/* Get sbdf from device */
+static int pci_get_sbdf_from_pcidev(
+	struct pci_dev *dev, struct pcidev_sbdf *sbdf)
+{
+	struct pcidev_sbdf_node *node;
+
+	if (!dev)
+		return FALSE;
+
+	for(;;) {
+		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		if (!node) {
+			printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+			goto err_end;
+		}
+		memset(node, 0, sizeof(*node));
+		node->dev = PCI_SLOT(dev->devfn);
+		node->func = PCI_FUNC(dev->devfn);
+
+		if (!sbdf->child)
+			sbdf->child = node;
+		else {
+			node->child = sbdf->child;
+			sbdf->child = node;
+		}
+		if (!dev->bus)
+			goto err_end;
+		if (!dev->bus->self)
+			break;
+		dev = dev->bus->self;
+	}
+	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &sbdf->seg, &sbdf->bus) != 2)
+		goto err_end;
+	return TRUE;
+
+err_end:
+	pci_free_sbdf(sbdf);
+	return FALSE;
+}
+
+/* Does PCI device belong to sub tree specified by guestdev with sbdf? */
+typedef int (*pci_sbdf_match_t)(const struct guestdev *gdev,
+				const  struct pci_dev *dev);
+
+static int pci_sbdf_match(const struct guestdev *gdev,
+			  const struct pci_dev *dev)
+{
+	int seg, bus;
+
+	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2)
+		return FALSE;
+
+	return gdev->u.sbdf.seg == seg &&
+		gdev->u.sbdf.bus == bus &&
+		gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
+		gdev->u.sbdf.func == PCI_FUNC(dev->devfn);
+}
+
+static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev,
+				   pci_sbdf_match_t match)
+{
+	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
+	for (;;) {
+		if (match(gdev, dev))
+			return TRUE;
+		if (!dev->bus || !dev->bus->self)
+			break;
+		dev = dev->bus->self;
+	}
+	return FALSE;
+}
+
+/* Does PCI device belong to sub tree specified by guestdev parameter? */
+static int __pci_is_guestdev(struct pci_dev *dev, pci_node_match_t node_match,
+			     pci_sbdf_match_t sbdf_match)
+{
+	struct guestdev *gdev;
+	struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
+	struct list_head *head;
+	int result = FALSE;
+
+	if (!dev)
+		return FALSE;
+
+	list_for_each(head, &guestdev_list) {
+		gdev = list_entry(head, struct guestdev, root_list);
+		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+		case GUESTDEV_FLAG_DEVICEPATH:
+			if (sbdf == NULL) {
+				sbdf = &pcidev_sbdf;
+				memset(sbdf, 0 ,sizeof(*sbdf));
+				if (!pci_get_sbdf_from_pcidev(dev, sbdf))
+					goto out;
+			}
+			if (pci_is_in_devicepath_sub_tree(gdev, sbdf,
+							  node_match)) {
+				result = TRUE;
+				goto out;
+			}
+			break;
+		case GUESTDEV_FLAG_SBDF:
+			if (pci_is_in_sbdf_sub_tree(gdev, dev, sbdf_match)) {
+				result = TRUE;
+				goto out;
+			}
+			break;
+		default:
+			BUG();
+		}
+	}
+out:
+	if (sbdf)
+		pci_free_sbdf(sbdf);
+	return result;
+}
+
+int pci_is_guestdev(struct pci_dev *dev)
+{
+	return __pci_is_guestdev(dev, pci_node_match, pci_sbdf_match);
+}
+EXPORT_SYMBOL_GPL(pci_is_guestdev);
+
+static int reassign_resources;
+
+static int __init pci_set_reassign_resources(char *str)
+{
+	reassign_resources = 1;
+
+	return 1;
+}
+__setup("reassign_resources", pci_set_reassign_resources);
+
+int pci_is_guestdev_to_reassign(struct pci_dev *dev)
+{
+	if (reassign_resources)
+		return pci_is_guestdev(dev);
+	return FALSE;
+}
+
+#ifdef CONFIG_PCI_IOMULTI
+static int pci_iomul_node_match(const struct devicepath_node *gdev_node,
+				const struct pcidev_sbdf_node *sbdf_node,
+				int options)
+{
+	return (options & GUESTDEV_OPT_IOMUL) &&
+		((gdev_node->child != NULL &&
+		  sbdf_node->child != NULL &&
+		  gdev_node->dev == sbdf_node->dev &&
+		  gdev_node->func == sbdf_node->func) ||
+		 (gdev_node->child == NULL &&
+		  sbdf_node->child == NULL &&
+		  gdev_node->dev == sbdf_node->dev));
+}
+
+static int pci_iomul_sbdf_match(const struct guestdev *gdev,
+				const struct pci_dev *dev)
+{
+	int seg, bus;
+
+	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2)
+		return FALSE;
+
+	return (gdev->options & GUESTDEV_OPT_IOMUL) &&
+		gdev->u.sbdf.seg == seg &&
+		gdev->u.sbdf.bus == bus &&
+		gdev->u.sbdf.dev == PCI_SLOT(dev->devfn);
+}
+
+int pci_is_iomuldev(struct pci_dev *dev)
+{
+	return __pci_is_guestdev(dev,
+				 pci_iomul_node_match, pci_iomul_sbdf_match);
+}
+#endif /* CONFIG_PCI_IOMULTI */
+
+/* Check whether the devicepath exists under the pci root bus */
+static int __init pci_check_devicepath_exists(
+		struct guestdev *gdev, struct pci_bus *bus)
+{
+	struct devicepath_node *node;
+	struct pci_dev *dev;
+
+	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
+	node = gdev->u.devicepath.child;
+	while (node) {
+		if (!bus)
+			return FALSE;
+		dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
+		if (!dev)
+			return FALSE;
+		bus = dev->subordinate;
+		node = node->child;
+		pci_dev_put(dev);
+	}
+	return TRUE;
+}
+
+/* Check whether the guestdev exists in the PCI device tree */
+static int __init pci_check_guestdev_exists(void)
+{
+	struct list_head *head;
+	struct guestdev *gdev;
+	int seg, bbn;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	char path_str[GUESTDEV_STR_MAX];
+
+	list_for_each(head, &guestdev_list) {
+		gdev = list_entry(head, struct guestdev, root_list);
+		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+		case GUESTDEV_FLAG_DEVICEPATH:
+			if (gdev->u.devicepath.seg == INVALID_SEG ||
+				gdev->u.devicepath.bbn == INVALID_BBN) {
+				if (acpi_pci_get_root_seg_bbn(
+					gdev->u.devicepath.hid,
+					gdev->u.devicepath.uid, &seg, &bbn)) {
+					gdev->u.devicepath.seg = seg;
+					gdev->u.devicepath.bbn = bbn;
+				} else {
+					pci_make_guestdev_str(gdev,
+						path_str, GUESTDEV_STR_MAX);
+					printk(KERN_INFO
+					"PCI: Device does not exist. %s\n",
+					path_str);
+					continue;
+				}
+			}
+
+			bus = pci_find_bus(gdev->u.devicepath.seg,
+						gdev->u.devicepath.bbn);
+			if (!bus ||
+				!pci_check_devicepath_exists(gdev, bus)) {
+				pci_make_guestdev_str(gdev, path_str,
+					GUESTDEV_STR_MAX);
+				printk(KERN_INFO
+					"PCI: Device does not exist. %s\n",
+					path_str);
+			}
+			break;
+		case GUESTDEV_FLAG_SBDF:
+			bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
+			if (bus) {
+				dev = pci_get_slot(bus,
+					PCI_DEVFN(gdev->u.sbdf.dev,
+							gdev->u.sbdf.func));
+				if (dev) {
+					pci_dev_put(dev);
+					continue;
+				}
+			}
+			pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
+			printk(KERN_INFO "PCI: Device does not exist. %s\n",
+								path_str);
+			break;
+		default:
+			BUG();
+		}
+	}
+	return 0;
+}
+
+fs_initcall(pci_check_guestdev_exists);
+
--- linux-ec2-2.6.32.orig/drivers/pci/pci-stub.c
+++ linux-ec2-2.6.32/drivers/pci/pci-stub.c
@@ -54,6 +54,9 @@
 			subdevice = PCI_ANY_ID, class=0, class_mask=0;
 		int fields;
 
+		if (!strlen(id))
+			continue;
+
 		fields = sscanf(id, "%x:%x:%x:%x:%x:%x",
 				&vendor, &device, &subvendor, &subdevice,
 				&class, &class_mask);
--- linux-ec2-2.6.32.orig/drivers/pci/Makefile
+++ linux-ec2-2.6.32/drivers/pci/Makefile
@@ -7,6 +7,9 @@
 			irq.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
+obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
+obj-$(CONFIG_PCI_IOMULTI) += iomulti.o
+obj-$(CONFIG_PCI_RESERVE) += reserve.o
 
 obj-$(CONFIG_PCI_LEGACY) += legacy.o
 CFLAGS_legacy.o += -Wno-deprecated-declarations
--- linux-ec2-2.6.32.orig/drivers/pci/dmar.c
+++ linux-ec2-2.6.32/drivers/pci/dmar.c
@@ -582,6 +582,8 @@
 	return 0;
 }
 
+static int bios_warned;
+
 int __init check_zero_address(void)
 {
 	struct acpi_table_dmar *dmar;
@@ -601,6 +603,9 @@
 		}
 
 		if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
+			void __iomem *addr;
+			u64 cap, ecap;
+
 			drhd = (void *)entry_header;
 			if (!drhd->address) {
 				/* Promote an attitude of violence to a BIOS engineer today */
@@ -609,17 +614,40 @@
 				     dmi_get_system_info(DMI_BIOS_VENDOR),
 				     dmi_get_system_info(DMI_BIOS_VERSION),
 				     dmi_get_system_info(DMI_PRODUCT_VERSION));
-#ifdef CONFIG_DMAR
-				dmar_disabled = 1;
-#endif
-				return 0;
+				bios_warned = 1;
+				goto failed;
+			}
+
+			addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
+			if (!addr ) {
+				printk("IOMMU: can't validate: %llx\n", drhd->address);
+				goto failed;
+			}
+			cap = dmar_readq(addr + DMAR_CAP_REG);
+			ecap = dmar_readq(addr + DMAR_ECAP_REG);
+			early_iounmap(addr, VTD_PAGE_SIZE);
+			if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
+				/* Promote an attitude of violence to a BIOS engineer today */
+				WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+				     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+				      drhd->address,
+				      dmi_get_system_info(DMI_BIOS_VENDOR),
+				      dmi_get_system_info(DMI_BIOS_VERSION),
+				      dmi_get_system_info(DMI_PRODUCT_VERSION));
+				bios_warned = 1;
+				goto failed;
 			}
-			break;
 		}
 
 		entry_header = ((void *)entry_header + entry_header->length);
 	}
 	return 1;
+
+failed:
+#ifdef CONFIG_DMAR
+	dmar_disabled = 1;
+#endif
+	return 0;
 }
 
 void __init detect_intel_iommu(void)
@@ -664,6 +692,18 @@
 	int agaw = 0;
 	int msagaw = 0;
 
+	if (!drhd->reg_base_addr) {
+		if (!bios_warned) {
+			WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
+			     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			     dmi_get_system_info(DMI_BIOS_VENDOR),
+			     dmi_get_system_info(DMI_BIOS_VERSION),
+			     dmi_get_system_info(DMI_PRODUCT_VERSION));
+			bios_warned = 1;
+		}
+		return -EINVAL;
+	}
+
 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
 	if (!iommu)
 		return -ENOMEM;
@@ -680,13 +720,16 @@
 	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
 	if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-		/* Promote an attitude of violence to a BIOS engineer today */
-		WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
-		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		     drhd->reg_base_addr,
-		     dmi_get_system_info(DMI_BIOS_VENDOR),
-		     dmi_get_system_info(DMI_BIOS_VERSION),
-		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		if (!bios_warned) {
+			/* Promote an attitude of violence to a BIOS engineer today */
+			WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+			     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			     drhd->reg_base_addr,
+			     dmi_get_system_info(DMI_BIOS_VENDOR),
+			     dmi_get_system_info(DMI_BIOS_VERSION),
+			     dmi_get_system_info(DMI_PRODUCT_VERSION));
+			bios_warned = 1;
+		}
 		goto err_unmap;
 	}
 
@@ -1337,6 +1380,11 @@
 			       (unsigned long long)drhd->reg_base_addr, ret);
 			return -1;
 		}
+
+		/*
+		 * Clear any previous faults.
+		 */
+		dmar_fault(iommu->irq, iommu);
 	}
 
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/pci/pci-sysfs.c
+++ linux-ec2-2.6.32/drivers/pci/pci-sysfs.c
@@ -662,17 +662,21 @@
 
 #ifdef HAVE_PCI_MMAP
 
-int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
+		  enum pci_mmap_api mmap_api)
 {
-	unsigned long nr, start, size;
+	unsigned long nr, start, size, pci_start;
 
+	if (pci_resource_len(pdev, resno) == 0)
+		return 0;
 	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	start = vma->vm_pgoff;
 	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-	if (start < size && size - start >= nr)
+	pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
+			pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+	if (start >= pci_start && start < pci_start + size &&
+			start + nr <= pci_start + size)
 		return 1;
-	WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
-		current->comm, start, start+nr, pci_name(pdev), resno, size);
 	return 0;
 }
 
@@ -702,8 +706,14 @@
 	if (i >= PCI_ROM_RESOURCE)
 		return -ENODEV;
 
-	if (!pci_mmap_fits(pdev, i, vma))
+	if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
+		WARN(1, "process \"%s\" tried to map 0x%08lx bytes "
+			"at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
+			current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
+			pci_name(pdev), i,
+			pci_resource_start(pdev, i), pci_resource_len(pdev, i));
 		return -EINVAL;
+	}
 
 	/* pci_mmap_page_range() expects the same kind of entry as coming
 	 * from /proc/bus/pci/ which is a "user visible" value. If this is
@@ -929,7 +939,12 @@
 
 	if (val != 1)
 		return -EINVAL;
-	return pci_reset_function(pdev);
+
+	result = pci_reset_function(pdev);
+	if (result < 0)
+		return result;
+
+	return count;
 }
 
 static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store);
@@ -952,7 +967,7 @@
 		attr->write = write_vpd_attr;
 		retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
 		if (retval) {
-			kfree(dev->vpd->attr);
+			kfree(attr);
 			return retval;
 		}
 		dev->vpd->attr = attr;
--- linux-ec2-2.6.32.orig/drivers/pci/pci.h
+++ linux-ec2-2.6.32/drivers/pci/pci.h
@@ -13,8 +13,13 @@
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef HAVE_PCI_MMAP
+enum pci_mmap_api {
+	PCI_MMAP_SYSFS,	/* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
+	PCI_MMAP_PROCFS	/* mmap on /proc/bus/pci/<BDF> */
+};
 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
-			 struct vm_area_struct *vma);
+			 struct vm_area_struct *vmai,
+			 enum pci_mmap_api mmap_api);
 #endif
 int pci_probe_reset_function(struct pci_dev *dev);
 
@@ -311,4 +316,26 @@
 	return resource_alignment(res);
 }
 
+#ifdef CONFIG_PCI_GUESTDEV
+extern int pci_is_guestdev_to_reassign(struct pci_dev *dev);
+extern int pci_is_iomuldev(struct pci_dev *dev);
+#else
+#define pci_is_iomuldev(dev)	0
+#endif
+
+#ifdef CONFIG_PCI_RESERVE
+unsigned long pci_reserve_size_io(struct pci_bus *bus);
+unsigned long pci_reserve_size_mem(struct pci_bus *bus);
+#else
+static inline unsigned long pci_reserve_size_io(struct pci_bus *bus)
+{
+	return 0;
+}
+
+static inline unsigned long pci_reserve_size_mem(struct pci_bus *bus)
+{
+	return 0;
+}
+#endif /* CONFIG_PCI_RESERVE */
+
 #endif /* DRIVERS_PCI_H */
--- linux-ec2-2.6.32.orig/drivers/pci/quirks.c
+++ linux-ec2-2.6.32/drivers/pci/quirks.c
@@ -155,6 +155,26 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs);
 
 /*
+ * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+ * for some HT machines to use C4 w/o hanging.
+ */
+static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+{
+	u32 pmbase;
+	u16 pm1a;
+
+	pci_read_config_dword(dev, 0x40, &pmbase);
+	pmbase = pmbase & 0xff80;
+	pm1a = inw(pmbase);
+
+	if (pm1a & 0x10) {
+		dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n");
+		outw(0x10, pmbase);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts);
+
+/*
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
@@ -486,6 +506,17 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi);
 
+#define ICH_PMBASE	0x40
+#define ICH_ACPI_CNTL	0x44
+#define  ICH4_ACPI_EN	0x10
+#define  ICH6_ACPI_EN	0x80
+#define ICH4_GPIOBASE	0x58
+#define ICH4_GPIO_CNTL	0x5c
+#define  ICH4_GPIO_EN	0x10
+#define ICH6_GPIOBASE	0x48
+#define ICH6_GPIO_CNTL	0x4c
+#define  ICH6_GPIO_EN	0x10
+
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
@@ -494,12 +525,33 @@
 static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
+	/*
+	 * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict
+	 * with low legacy (and fixed) ports. We don't know the decoding
+	 * priority and can't tell whether the legacy device or the one created
+	 * here is really at that address.  This happens on boards with broken
+	 * BIOSes.
+	*/
+
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH4_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH4 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x58, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
+	pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH4_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
+	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi);
@@ -515,12 +567,25 @@
 static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH6_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH6 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x48, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+	pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH6_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
+	}
 }
 
 static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -1444,7 +1509,8 @@
 	conf5 &= ~(1 << 24);  /* Clear bit 24 */
 
 	switch (pdev->device) {
-	case PCI_DEVICE_ID_JMICRON_JMB360:
+	case PCI_DEVICE_ID_JMICRON_JMB360: /* SATA single port */
+	case PCI_DEVICE_ID_JMICRON_JMB362: /* SATA dual ports */
 		/* The controller should be in single function ahci mode */
 		conf1 |= 0x0002A100; /* Set 8, 13, 15, 17 */
 		break;
@@ -1480,12 +1546,14 @@
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB360, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, quirk_jmicron_ata);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB362, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, quirk_jmicron_ata);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, quirk_jmicron_ata);
@@ -2081,6 +2149,7 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
 
 /* Disable MSI on chipsets that are known to not support it */
 static void __devinit quirk_disable_msi(struct pci_dev *dev)
@@ -2092,6 +2161,8 @@
 	}
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
 
 /* Go through the list of Hypertransport capabilities and
  * return 1 if a HT MSI capability is found and enabled */
@@ -2183,15 +2254,16 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
 			 ht_enable_msi_mapping);
 
-/* The P5N32-SLI Premium motherboard from Asus has a problem with msi
+/* The P5N32-SLI motherboards from Asus have a problem with msi
  * for the MCP55 NIC. It is not yet determined whether the msi problem
  * also affects other devices. As for now, turn off msi for this device.
  */
 static void __devinit nvenet_msi_disable(struct pci_dev *dev)
 {
-	if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) {
+	if (dmi_name_in_vendors("P5N32-SLI PREMIUM") ||
+	    dmi_name_in_vendors("P5N32-E SLI")) {
 		dev_info(&dev->dev,
-			 "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n");
+			 "Disabling msi for MCP55 NIC on P5N32-SLI\n");
 		dev->no_msi = 1;
 	}
 }
@@ -2350,6 +2422,9 @@
 	int pos;
 	int found;
 
+	if (!pci_msi_enabled())
+		return;
+
 	/* check if there is HT MSI cap or enabled on this device */
 	found = ht_check_msi_mapping(dev);
 
@@ -2465,57 +2540,6 @@
 
 #endif /* CONFIG_PCI_MSI */
 
-#ifdef CONFIG_PCI_IOV
-
-/*
- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
- * old Flash Memory Space.
- */
-static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
-{
-	int pos, flags;
-	u32 bar, start, size;
-
-	if (PAGE_SIZE > 0x10000)
-		return;
-
-	flags = pci_resource_flags(dev, 0);
-	if ((flags & PCI_BASE_ADDRESS_SPACE) !=
-			PCI_BASE_ADDRESS_SPACE_MEMORY ||
-	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
-			PCI_BASE_ADDRESS_MEM_TYPE_32)
-		return;
-
-	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
-	if (!pos)
-		return;
-
-	pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
-	if (bar & PCI_BASE_ADDRESS_MEM_MASK)
-		return;
-
-	start = pci_resource_start(dev, 1);
-	size = pci_resource_len(dev, 1);
-	if (!start || size != 0x400000 || start & (size - 1))
-		return;
-
-	pci_resource_flags(dev, 1) = 0;
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
-
-	dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
-
-#endif	/* CONFIG_PCI_IOV */
-
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {
@@ -2544,6 +2568,29 @@
 extern struct pci_fixup __start_pci_fixups_suspend[];
 extern struct pci_fixup __end_pci_fixups_suspend[];
 
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#define VTUNCERRMSK_REG	0x1ac
+#define VTD_MSK_SPEC_ERRORS	(1 << 31)
+/*
+ * This is a quirk for masking vt-d spec defined errors to platform error
+ * handling logic. With out this, platforms using Intel 7500, 5500 chipsets
+ * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based
+ * on the RAS config settings of the platform) when a vt-d fault happens.
+ * The resulting SMI caused the system to hang.
+ *
+ * VT-d spec related errors are already handled by the VT-d OS code, so no
+ * need to report the same error through other channels.
+ */
+static void vtd_mask_spec_errors(struct pci_dev *dev)
+{
+	u32 word;
+
+	pci_read_config_dword(dev, VTUNCERRMSK_REG, &word);
+	pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+#endif
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
 {
--- linux-ec2-2.6.32.orig/drivers/pci/Kconfig
+++ linux-ec2-2.6.32/drivers/pci/Kconfig
@@ -42,6 +42,27 @@
 
 	  When in doubt, say N.
 
+config PCI_GUESTDEV
+	bool "PCI Device Reservation for Passthrough"
+	depends on PCI && ACPI && XEN
+	default y
+	help
+	  Say Y here if you want to reserve PCI device for passthrough.
+
+config PCI_IOMULTI
+	bool "PCI Device IO Multiplex for Passthrough"
+	depends on PCI && ACPI && XEN
+	default y
+	help
+	  Say Y here if you need io multiplexing.
+
+config PCI_RESERVE
+	bool "PCI IO/MEMORY space reserve"
+	depends on PCI && XEN_PRIVILEGED_GUEST
+	default y
+	help
+	  Say Y here if you need PCI IO/MEMORY space reserve
+
 config PCI_STUB
 	tristate "PCI Stub driver"
 	depends on PCI
@@ -54,7 +75,7 @@
 config HT_IRQ
 	bool "Interrupts on hypertransport devices"
 	default y
-	depends on PCI && X86_LOCAL_APIC && X86_IO_APIC
+	depends on PCI && X86_LOCAL_APIC && X86_IO_APIC && !XEN
 	help
 	   This allows native hypertransport devices to use interrupts.
 
--- linux-ec2-2.6.32.orig/drivers/pci/iomulti.c
+++ linux-ec2-2.6.32/drivers/pci/iomulti.c
@@ -0,0 +1,1415 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/sort.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+
+#include "pci.h"
+#include "iomulti.h"
+
+#define PCI_NUM_BARS		6
+#define PCI_BUS_MAX		255
+#define PCI_DEV_MAX		31
+#define PCI_FUNC_MAX		7
+#define PCI_NUM_FUNC		8
+
+/* see pci_resource_len */
+static inline resource_size_t pci_iomul_len(const struct resource* r)
+{
+	if (r->start == 0 && r->start == r->end)
+		return 0;
+	return r->end - r->start + 1;
+}
+
+#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
+/* stolen from pbus_size_io() */
+static unsigned long pdev_size_io(struct pci_dev *pdev)
+{
+	unsigned long size = 0, size1 = 0;
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *r = &pdev->resource[i];
+		unsigned long r_size;
+
+		if (!(r->flags & IORESOURCE_IO))
+			continue;
+
+		r_size = r->end - r->start + 1;
+
+		if (r_size < 0x400)
+			/* Might be re-aligned for ISA */
+			size += r_size;
+		else
+			size1 += r_size;
+	}
+
+/* To be fixed in 2.5: we should have sort of HAVE_ISA
+   flag in the struct pci_bus. */
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+	size = (size & 0xff) + ((size & ~0xffUL) << 2);
+#endif
+	size = ROUND_UP(size + size1, 4096);
+	return size;
+}
+
+/*
+ * primary bus number of PCI-PCI bridge in switch on which
+ * this slots sits.
+ * i.e. the primary bus number of PCI-PCI bridge of downstream port
+ *      or root port in switch.
+ *      the secondary bus number of PCI-PCI bridge of upstream port
+ *      in switch.
+ */
+static inline unsigned char pci_dev_switch_busnr(struct pci_dev *pdev)
+{
+	if (pci_find_capability(pdev, PCI_CAP_ID_EXP))
+		return pdev->bus->primary;
+	return pdev->bus->number;
+}
+
+struct pci_iomul_func {
+	int		segment;
+	uint8_t		bus;
+	uint8_t		devfn;
+
+	/* only start and end are used */
+	unsigned long	io_size;
+	uint8_t		io_bar;
+	struct resource	resource[PCI_NUM_BARS];
+	struct resource dummy_parent;
+};
+
+struct pci_iomul_switch {
+	struct list_head	list;	/* bus_list_lock protects */
+
+	/*
+	 * This lock the following entry and following
+	 * pci_iomul_slot/pci_iomul_func.
+	 */
+	struct mutex		lock;
+	struct kref		kref;
+
+	struct resource		io_resource;
+	struct resource		*io_region;
+	unsigned int		count;
+	struct pci_dev		*current_pdev;
+
+	int			segment;
+	uint8_t			bus;
+
+	uint32_t		io_base;
+	uint32_t		io_limit;
+
+	/* func which has the largeset io size*/
+	struct pci_iomul_func	*func;
+
+	struct list_head	slots;
+};
+
+struct pci_iomul_slot {
+	struct list_head	sibling;
+	struct kref		kref;
+	/*
+	 * busnr
+	 * when pcie, the primary busnr of the PCI-PCI bridge on which
+	 * this devices sits.
+	 */
+	uint8_t			switch_busnr;
+	struct resource		dummy_parent[PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES];
+
+	/* device */
+	int			segment;
+	uint8_t			bus;
+	uint8_t			dev;
+
+	struct pci_iomul_func	*func[PCI_NUM_FUNC];
+};
+
+static LIST_HEAD(switch_list);
+static DEFINE_MUTEX(switch_list_lock);
+
+/*****************************************************************************/
+static int inline pci_iomul_switch_io_allocated(
+	const struct pci_iomul_switch *sw)
+{
+	return !(sw->io_base == 0 || sw->io_base > sw->io_limit);
+}
+
+static struct pci_iomul_switch *pci_iomul_find_switch_locked(int segment,
+							     uint8_t bus)
+{
+	struct pci_iomul_switch *sw;
+
+	BUG_ON(!mutex_is_locked(&switch_list_lock));
+	list_for_each_entry(sw, &switch_list, list) {
+		if (sw->segment == segment && sw->bus == bus)
+			return sw;
+	}
+	return NULL;
+}
+
+static struct pci_iomul_slot *pci_iomul_find_slot_locked(
+	struct pci_iomul_switch *sw, uint8_t busnr, uint8_t dev)
+{
+	struct pci_iomul_slot *slot;
+
+	BUG_ON(!mutex_is_locked(&sw->lock));
+	list_for_each_entry(slot, &sw->slots, sibling) {
+		if (slot->bus == busnr && slot->dev == dev)
+			return slot;
+	}
+	return NULL;
+}
+
+static void pci_iomul_switch_get(struct pci_iomul_switch *sw);
+/* on successfull exit, sw->lock is locked for use slot and
+ * refrence count of sw is incremented.
+ */
+static void pci_iomul_get_lock_switch(struct pci_dev *pdev,
+				      struct pci_iomul_switch **swp,
+				      struct pci_iomul_slot **slot)
+{
+	mutex_lock(&switch_list_lock);
+
+	*swp = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
+					    pci_dev_switch_busnr(pdev));
+	if (*swp == NULL) {
+		*slot = NULL;
+		goto out;
+	}
+
+	mutex_lock(&(*swp)->lock);
+	*slot = pci_iomul_find_slot_locked(*swp, pdev->bus->number,
+					   PCI_SLOT(pdev->devfn));
+	if (*slot == NULL) {
+		mutex_unlock(&(*swp)->lock);
+		*swp = NULL;
+	} else {
+		pci_iomul_switch_get(*swp);
+	}
+out:
+	mutex_unlock(&switch_list_lock);
+}
+
+static struct pci_iomul_switch *pci_iomul_switch_alloc(int segment,
+						       uint8_t bus)
+{
+	struct pci_iomul_switch *sw;
+
+	BUG_ON(!mutex_is_locked(&switch_list_lock));
+
+	sw = kmalloc(sizeof(*sw), GFP_KERNEL);
+
+	mutex_init(&sw->lock);
+	kref_init(&sw->kref);
+	sw->io_region = NULL;
+	sw->count = 0;
+	sw->current_pdev = NULL;
+	sw->segment = segment;
+	sw->bus = bus;
+	sw->io_base = 0;
+	sw->io_limit = 0;
+	sw->func = NULL;
+	INIT_LIST_HEAD(&sw->slots);
+
+	return sw;
+}
+
+static void pci_iomul_switch_add_locked(struct pci_iomul_switch *sw)
+{
+	BUG_ON(!mutex_is_locked(&switch_list_lock));
+	list_add(&sw->list, &switch_list);
+}
+
+#ifdef CONFIG_HOTPLUG_PCI
+static void pci_iomul_switch_del_locked(struct pci_iomul_switch *sw)
+{
+	BUG_ON(!mutex_is_locked(&switch_list_lock));
+	list_del(&sw->list);
+}
+#endif
+
+static void pci_iomul_switch_get(struct pci_iomul_switch *sw)
+{
+	kref_get(&sw->kref);
+}
+
+static void pci_iomul_switch_release(struct kref *kref)
+{
+	struct pci_iomul_switch *sw = container_of(kref,
+						   struct pci_iomul_switch,
+						   kref);
+	kfree(sw);
+}
+
+static void pci_iomul_switch_put(struct pci_iomul_switch *sw)
+{
+	kref_put(&sw->kref, &pci_iomul_switch_release);
+}
+
+static int __devinit pci_iomul_slot_init(struct pci_dev *pdev,
+					 struct pci_iomul_slot *slot)
+{
+	u16 rpcap;
+	u16 cap;
+
+	rpcap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (!rpcap) {
+		/* pci device isn't supported */
+		printk(KERN_INFO
+		       "PCI: sharing io port of non PCIe device %s "
+		       "isn't supported. ignoring.\n",
+		       pci_name(pdev));
+		return -ENOSYS;
+	}
+
+        pci_read_config_word(pdev, rpcap + PCI_CAP_FLAGS, &cap);
+	switch ((cap & PCI_EXP_FLAGS_TYPE) >> 4) {
+	case PCI_EXP_TYPE_RC_END:
+		printk(KERN_INFO
+		       "PCI: io port sharing of root complex integrated "
+		       "endpoint %s isn't supported. ignoring.\n",
+		       pci_name(pdev));
+		return -ENOSYS;
+	case PCI_EXP_TYPE_ENDPOINT:
+	case PCI_EXP_TYPE_LEG_END:
+		break;
+	default:
+		printk(KERN_INFO
+		       "PCI: io port sharing of non endpoint %s "
+		       "doesn't make sense. ignoring.\n",
+		       pci_name(pdev));
+		return -EINVAL;
+	}
+
+	kref_init(&slot->kref);
+	slot->switch_busnr = pci_dev_switch_busnr(pdev);
+	slot->segment = pci_domain_nr(pdev->bus);
+	slot->bus = pdev->bus->number;
+	slot->dev = PCI_SLOT(pdev->devfn);
+
+	return 0;
+}
+
+static struct pci_iomul_slot *__devinit
+pci_iomul_slot_alloc(struct pci_dev *pdev)
+{
+	struct pci_iomul_slot *slot;
+
+	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+	if (slot == NULL)
+		return NULL;
+
+	if (pci_iomul_slot_init(pdev, slot) != 0) {
+		kfree(slot);
+		return NULL;
+	}
+	return slot;
+}
+
+static void pci_iomul_slot_add_locked(struct pci_iomul_switch *sw,
+				      struct pci_iomul_slot *slot)
+{
+	BUG_ON(!mutex_is_locked(&sw->lock));
+	list_add(&slot->sibling, &sw->slots);
+}
+
+#ifdef CONFIG_HOTPLUG_PCI
+static void pci_iomul_slot_del_locked(struct pci_iomul_switch *sw,
+				       struct pci_iomul_slot *slot)
+{
+	BUG_ON(!mutex_is_locked(&sw->lock));
+	list_del(&slot->sibling);
+}
+#endif
+
+static void pci_iomul_slot_get(struct pci_iomul_slot *slot)
+{
+	kref_get(&slot->kref);
+}
+
+static void pci_iomul_slot_release(struct kref *kref)
+{
+	struct pci_iomul_slot *slot = container_of(kref, struct pci_iomul_slot,
+						   kref);
+	kfree(slot);
+}
+
+static void pci_iomul_slot_put(struct pci_iomul_slot *slot)
+{
+	kref_put(&slot->kref, &pci_iomul_slot_release);
+}
+
+/*****************************************************************************/
+static int pci_get_sbd(const char *str,
+		       int *segment__, uint8_t *bus__, uint8_t *dev__)
+{
+	int segment;
+	int bus;
+	int dev;
+
+	if (sscanf(str, "%x:%x:%x", &segment, &bus, &dev) != 3) {
+		if (sscanf(str, "%x:%x", &bus, &dev) == 2)
+			segment = 0;
+		else
+			return -EINVAL;
+	}
+
+	if (segment < 0 || INT_MAX <= segment)
+		return -EINVAL;
+	if (bus < 0 || PCI_BUS_MAX < bus)
+		return -EINVAL;
+	if (dev < 0 || PCI_DEV_MAX < dev)
+		return -EINVAL;
+
+	*segment__ = segment;
+	*bus__ = bus;
+	*dev__ = dev;
+	return 0;
+}
+
+static char iomul_param[COMMAND_LINE_SIZE];
+#define TOKEN_MAX	10	/* SSSS:BB:DD length is 10 */
+static int pci_is_iomul_dev_param(struct pci_dev *pdev)
+{
+        int len;
+        char *p;
+	char *next_str;
+
+	for (p = &iomul_param[0]; *p != '\0'; p = next_str + 1) {
+		next_str = strchr(p, ',');
+		if (next_str != NULL)
+			len = next_str - p;
+		else
+			len = strlen(p);
+
+		if (len > 0 && len <= TOKEN_MAX) {
+			char tmp[TOKEN_MAX+1];
+			int seg;
+			uint8_t bus;
+			uint8_t dev;
+
+			strlcpy(tmp, p, len);
+			if (pci_get_sbd(tmp, &seg, &bus, &dev) == 0 &&
+			    pci_domain_nr(pdev->bus) == seg &&
+			    pdev->bus->number == bus &&
+			    PCI_SLOT(pdev->devfn) == dev)
+				return 1;
+		}
+		if (next_str == NULL)
+			break;
+	}
+
+	/* check guestcev=<device>+iomul option */
+	return pci_is_iomuldev(pdev);
+}
+
+/*
+ * Format: [<segment>:]<bus>:<dev>[,[<segment>:]<bus>:<dev>[,...]
+ */
+static int __init pci_iomul_param_setup(char *str)
+{
+	if (strlen(str) >= COMMAND_LINE_SIZE)
+		return 0;
+
+	/* parse it after pci bus scanning */
+	strlcpy(iomul_param, str, sizeof(iomul_param));
+	return 1;
+}
+__setup("guestiomuldev=", pci_iomul_param_setup);
+
+/*****************************************************************************/
+static void __devinit pci_iomul_set_bridge_io_window(struct pci_dev *bridge,
+						     uint32_t io_base,
+						     uint32_t io_limit)
+{
+	uint16_t l;
+	uint32_t upper16;
+
+	io_base >>= 12;
+	io_base <<= 4;
+	io_limit >>= 12;
+	io_limit <<= 4;
+	l = (io_base & 0xff) | ((io_limit & 0xff) << 8);
+	upper16 = ((io_base & 0xffff00) >> 8) |
+		(((io_limit & 0xffff00) >> 8) << 16);
+
+        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
+        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
+        /* Update lower 16 bits of I/O base/limit. */
+        pci_write_config_word(bridge, PCI_IO_BASE, l);
+        /* Update upper 16 bits of I/O base/limit. */
+        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, upper16);
+}
+
+static void __devinit pci_disable_bridge_io_window(struct pci_dev *bridge)
+{
+	/* set base = 0xffffff limit = 0x0 */
+	pci_iomul_set_bridge_io_window(bridge, 0xffffff, 0);
+}
+
+static int __devinit pci_iomul_func_scan(struct pci_dev *pdev,
+					 struct pci_iomul_slot *slot,
+					 uint8_t func)
+{
+	struct pci_iomul_func *f;
+	unsigned int i;
+
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (f == NULL)
+		return -ENOMEM;
+
+	f->segment = slot->segment;
+	f->bus = slot->bus;
+	f->devfn = PCI_DEVFN(slot->dev, func);
+	f->io_size = pdev_size_io(pdev);
+
+	for (i = 0; i < PCI_NUM_BARS; i++) {
+		if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO))
+			continue;
+		if (pci_resource_len(pdev, i) == 0)
+			continue;
+
+		f->io_bar |= 1 << i;
+		f->resource[i] = pdev->resource[i];
+	}
+
+	if (f->io_bar)
+		slot->func[func] = f;
+	else
+		kfree(f);
+	return 0;
+}
+
+/*
+ * This is tricky part.
+ * fake PCI resource assignment routines by setting flags to 0.
+ * PCI resource allocate routines think the resource should
+ * be allocated by checking flags. 0 means this resource isn't used.
+ * See pbus_size_io() and pdev_sort_resources().
+ *
+ * After allocated resources, flags (IORESOURCE_IO) is exported
+ * to other part including user process.
+ * So we have to set flags to IORESOURCE_IO, but at the same time
+ * we must prevent those resources from reassigning when pci hot plug.
+ * To achieve that, set r->parent to dummy resource.
+ */
+static void __devinit pci_iomul_disable_resource(struct resource *r)
+{
+	/* don't allocate this resource */
+	r->flags = 0;
+}
+
+static void __devinit pci_iomul_reenable_resource(
+	struct resource *dummy_parent, struct resource *r)
+{
+	int ret;
+
+	dummy_parent->start = r->start;
+	dummy_parent->end = r->end;
+	dummy_parent->flags = r->flags;
+	dummy_parent->name = "PCI IOMUL dummy resource";
+
+	ret = request_resource(dummy_parent, r);
+	BUG_ON(ret);
+}
+
+static void __devinit pci_iomul_fixup_ioresource(struct pci_dev *pdev,
+						 struct pci_iomul_func *func,
+						 int reassign, int dealloc)
+{
+	uint8_t i;
+	struct resource *r;
+
+	printk(KERN_INFO "PCI: deallocating io resource[%s]. io size 0x%lx\n",
+	       pci_name(pdev), func->io_size);
+	for (i = 0; i < PCI_NUM_BARS; i++) {
+		r = &pdev->resource[i];
+		if (!(func->io_bar & (1 << i)))
+			continue;
+
+		if (reassign) {
+			r->end -= r->start;
+			r->start = 0;
+			pci_update_resource(pdev, i);
+			func->resource[i] = *r;
+		}
+
+		if (dealloc)
+			/* don't allocate this resource */
+			pci_iomul_disable_resource(r);
+	}
+
+	/* parent PCI-PCI bridge */
+	if (!reassign)
+		return;
+	pdev = pdev->bus->self;
+	if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+		return;
+	pci_disable_bridge_io_window(pdev);
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		r = &pdev->resource[i];
+		if (!(r->flags & IORESOURCE_IO))
+			continue;
+
+		r->end -= r->start;
+		r->start = 0;
+		if (i < PCI_BRIDGE_RESOURCES)
+			pci_update_resource(pdev, i);
+	}
+}
+
+static void __devinit __quirk_iomul_dealloc_ioresource(
+	struct pci_iomul_switch *sw,
+	struct pci_dev *pdev, struct pci_iomul_slot *slot)
+{
+	struct pci_iomul_func *f;
+	struct pci_iomul_func *__f;
+
+	if (pci_iomul_func_scan(pdev, slot, PCI_FUNC(pdev->devfn)) != 0)
+		return;
+
+	f = slot->func[PCI_FUNC(pdev->devfn)];
+	if (f == NULL)
+		return;
+
+	__f = sw->func;
+	/* sw->io_base == 0 means that we are called at boot time.
+	 * != 0 means that we are called by php after boot. */
+	if (sw->io_base == 0 &&
+	    (__f == NULL || __f->io_size < f->io_size)) {
+		if (__f != NULL) {
+			struct pci_bus *__pbus;
+			struct pci_dev *__pdev;
+
+			__pbus = pci_find_bus(__f->segment, __f->bus);
+			BUG_ON(__pbus == NULL);
+			__pdev = pci_get_slot(__pbus, __f->devfn);
+			BUG_ON(__pdev == NULL);
+			pci_iomul_fixup_ioresource(__pdev, __f, 0, 1);
+			pci_dev_put(__pdev);
+		}
+
+		pci_iomul_fixup_ioresource(pdev, f, 1, 0);
+		sw->func = f;
+	} else {
+		pci_iomul_fixup_ioresource(pdev, f, 1, 1);
+	}
+}
+
+static void __devinit quirk_iomul_dealloc_ioresource(struct pci_dev *pdev)
+{
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_slot *slot;
+
+	if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+		return;
+	if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+		return;	/* PCI Host Bridge isn't a target device */
+	if (!pci_is_iomul_dev_param(pdev))
+		return;
+
+	mutex_lock(&switch_list_lock);
+	sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
+					  pci_dev_switch_busnr(pdev));
+	if (sw == NULL) {
+		sw = pci_iomul_switch_alloc(pci_domain_nr(pdev->bus),
+					    pci_dev_switch_busnr(pdev));
+		if (sw == NULL) {
+			mutex_unlock(&switch_list_lock);
+			printk(KERN_WARNING
+			       "PCI: can't allocate memory "
+			       "for sw of IO mulplexing %s", pci_name(pdev));
+			return;
+		}
+		pci_iomul_switch_add_locked(sw);
+	}
+	pci_iomul_switch_get(sw);
+	mutex_unlock(&switch_list_lock);
+
+	mutex_lock(&sw->lock);
+	slot = pci_iomul_find_slot_locked(sw, pdev->bus->number,
+					  PCI_SLOT(pdev->devfn));
+	if (slot == NULL) {
+		slot = pci_iomul_slot_alloc(pdev);
+		if (slot == NULL) {
+			mutex_unlock(&sw->lock);
+			pci_iomul_switch_put(sw);
+			printk(KERN_WARNING "PCI: can't allocate memory "
+			       "for IO mulplexing %s", pci_name(pdev));
+			return;
+		}
+		pci_iomul_slot_add_locked(sw, slot);
+	}
+
+	printk(KERN_INFO "PCI: disable device and release io resource[%s].\n",
+	       pci_name(pdev));
+	pci_disable_device(pdev);
+
+	__quirk_iomul_dealloc_ioresource(sw, pdev, slot);
+
+	mutex_unlock(&sw->lock);
+	pci_iomul_switch_put(sw);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID,
+			 quirk_iomul_dealloc_ioresource);
+
+static void __devinit pci_iomul_read_bridge_io(struct pci_iomul_switch *sw)
+{
+	struct pci_iomul_func *f = sw->func;
+
+	struct pci_bus *pbus;
+	struct pci_dev *pdev;
+	struct pci_dev *bridge;
+
+	uint16_t l;
+	uint16_t base_upper16;
+	uint16_t limit_upper16;
+	uint32_t io_base;
+	uint32_t io_limit;
+
+	pbus = pci_find_bus(f->segment, f->bus);
+	BUG_ON(pbus == NULL);
+
+	pdev = pci_get_slot(pbus, f->devfn);
+	BUG_ON(pdev == NULL);
+
+	bridge = pdev->bus->self;
+	pci_read_config_word(bridge, PCI_IO_BASE, &l);
+	pci_read_config_word(bridge, PCI_IO_BASE_UPPER16, &base_upper16);
+	pci_read_config_word(bridge, PCI_IO_LIMIT_UPPER16, &limit_upper16);
+
+	io_base = (l & 0xf0) | ((uint32_t)base_upper16 << 8);
+	io_base <<= 8;
+	io_limit = (l >> 8) | ((uint32_t)limit_upper16 << 8);
+	io_limit <<= 8;
+	io_limit |= 0xfff;
+
+	sw->io_base = io_base;
+	sw->io_limit = io_limit;
+
+	pci_dev_put(pdev);
+	printk(KERN_INFO "PCI: bridge %s base 0x%x limit 0x%x\n",
+	       pci_name(bridge), sw->io_base, sw->io_limit);
+}
+
+static void __devinit pci_iomul_setup_brige(struct pci_dev *bridge,
+					    uint32_t io_base,
+					    uint32_t io_limit)
+{
+	uint16_t cmd;
+
+	if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+		return;
+
+	pci_iomul_set_bridge_io_window(bridge, io_base, io_limit);
+
+	/* and forcibly enables IO */
+	pci_read_config_word(bridge, PCI_COMMAND, &cmd);
+	if (!(cmd & PCI_COMMAND_IO)) {
+		cmd |= PCI_COMMAND_IO;
+                printk(KERN_INFO "PCI: Forcibly Enabling IO %s\n",
+		       pci_name(bridge));
+                pci_write_config_word(bridge, PCI_COMMAND, cmd);
+	}
+}
+
+struct __bar {
+	unsigned long size;
+	uint8_t bar;
+};
+
+/* decending order */
+static int __devinit pci_iomul_bar_cmp(const void *lhs__, const void *rhs__)
+{
+	const struct __bar *lhs = (struct __bar*)lhs__;
+	const struct __bar *rhs = (struct __bar*)rhs__;
+	return - (lhs->size - rhs->size);
+}
+
+static void __devinit pci_iomul_setup_dev(struct pci_dev *pdev,
+					  struct pci_iomul_func *f,
+					  uint32_t io_base)
+{
+	struct __bar bars[PCI_NUM_BARS];
+	int i;
+	uint8_t num_bars = 0;
+	struct resource *r;
+
+	printk(KERN_INFO "PCI: Forcibly assign IO %s from 0x%x\n",
+	       pci_name(pdev), io_base);
+
+	for (i = 0; i < PCI_NUM_BARS; i++) {
+		if (!(f->io_bar & (1 << i)))
+			continue;
+
+		r = &f->resource[i];
+		bars[num_bars].size = pci_iomul_len(r);
+		bars[num_bars].bar = i;
+
+		num_bars++;
+	}
+
+	sort(bars, num_bars, sizeof(bars[0]), &pci_iomul_bar_cmp, NULL);
+
+	for (i = 0; i < num_bars; i++) {
+		struct resource *fr = &f->resource[bars[i].bar];
+		r = &pdev->resource[bars[i].bar];
+
+		BUG_ON(r->start != 0);
+		r->start += io_base;
+		r->end += io_base;
+
+		fr->start = r->start;
+		fr->end = r->end;
+
+		/* pci_update_resource() check flags. */
+		r->flags = fr->flags;
+		pci_update_resource(pdev, bars[i].bar);
+		pci_iomul_reenable_resource(&f->dummy_parent, r);
+
+		io_base += bars[i].size;
+	}
+}
+
+static void __devinit pci_iomul_release_io_resource(
+	struct pci_dev *pdev, struct pci_iomul_switch *sw,
+	struct pci_iomul_slot *slot, struct pci_iomul_func *f)
+{
+	int i;
+	struct resource *r;
+
+	for (i = 0; i < PCI_NUM_BARS; i++) {
+		if (pci_resource_flags(pdev, i) & IORESOURCE_IO &&
+		    pdev->resource[i].parent != NULL) {
+			r = &pdev->resource[i];
+			f->resource[i] = *r;
+			release_resource(r);
+			pci_iomul_reenable_resource(&f->dummy_parent, r);
+		}
+	}
+
+	/* parent PCI-PCI bridge */
+	pdev = pdev->bus->self;
+	if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_HOST) {
+		for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *parent = pdev->resource[i].parent;
+
+			if (pci_resource_flags(pdev, i) & IORESOURCE_IO &&
+			    parent != NULL) {
+				r = &pdev->resource[i];
+
+				sw->io_resource.flags = r->flags;
+				sw->io_resource.start = sw->io_base;
+				sw->io_resource.end = sw->io_limit;
+				sw->io_resource.name = "PCI IO Multiplexer";
+
+				release_resource(r);
+				pci_iomul_reenable_resource(
+					&slot->dummy_parent[i - PCI_BRIDGE_RESOURCES], r);
+
+				if (request_resource(parent,
+						     &sw->io_resource))
+					printk(KERN_ERR
+					       "PCI IOMul: can't allocate "
+					       "resource. [0x%x, 0x%x]",
+					       sw->io_base, sw->io_limit);
+			}
+		}
+	}
+}
+
+static void __devinit quirk_iomul_reassign_ioresource(struct pci_dev *pdev)
+{
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_slot *slot;
+	struct pci_iomul_func *sf;
+	struct pci_iomul_func *f;
+
+	pci_iomul_get_lock_switch(pdev, &sw, &slot);
+	if (sw == NULL || slot == NULL)
+		return;
+
+	if (sw->io_base == 0)
+		pci_iomul_read_bridge_io(sw);
+	if (!pci_iomul_switch_io_allocated(sw))
+		goto out;
+
+	sf = sw->func;
+	f = slot->func[PCI_FUNC(pdev->devfn)];
+	if (f == NULL)
+		/* (sf == NULL || f == NULL) case
+		 * can happen when all the specified devices
+		 * don't have io space
+		 */
+		goto out;
+
+	if (sf != NULL &&
+	    (pci_domain_nr(pdev->bus) != sf->segment ||
+	     pdev->bus->number != sf->bus ||
+	     PCI_SLOT(pdev->devfn) != PCI_SLOT(sf->devfn)) &&
+	    PCI_FUNC(pdev->devfn) == 0) {
+		pci_iomul_setup_brige(pdev->bus->self,
+				      sw->io_base, sw->io_limit);
+	}
+
+	BUG_ON(f->io_size > sw->io_limit - sw->io_base + 1);
+	if (/* f == sf */
+            sf != NULL &&
+	    pci_domain_nr(pdev->bus) == sf->segment &&
+	    pdev->bus->number == sf->bus &&
+	    pdev->devfn == sf->devfn)
+		pci_iomul_release_io_resource(pdev, sw, slot, f);
+	else
+		pci_iomul_setup_dev(pdev, f, sw->io_base);
+
+out:
+	mutex_unlock(&sw->lock);
+	pci_iomul_switch_put(sw);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID,
+			quirk_iomul_reassign_ioresource);
+
+/*****************************************************************************/
+#ifdef CONFIG_HOTPLUG_PCI
+static int __devinit __pci_iomul_notifier_del_device(struct pci_dev *pdev)
+{
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_slot *slot;
+	int i;
+
+	pci_iomul_get_lock_switch(pdev, &sw, &slot);
+	if (sw == NULL || slot == NULL)
+		return 0;
+
+	if (sw->func == slot->func[PCI_FUNC(pdev->devfn)])
+		sw->func = NULL;
+	kfree(slot->func[PCI_FUNC(pdev->devfn)]);
+	slot->func[PCI_FUNC(pdev->devfn)] = NULL;
+	for (i = 0; i < PCI_NUM_FUNC; i++) {
+		if (slot->func[i] != NULL)
+			goto out;
+	}
+
+	pci_iomul_slot_del_locked(sw, slot);
+	pci_iomul_slot_put(slot);
+
+out:
+	mutex_unlock(&sw->lock);
+	pci_iomul_switch_put(sw);
+	return 0;
+}
+
+static int __devinit __pci_iomul_notifier_del_switch(struct pci_dev *pdev)
+{
+	struct pci_iomul_switch *sw;
+
+	mutex_lock(&switch_list_lock);
+	sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
+					  pdev->bus->number);
+	if (sw == NULL)
+		goto out;
+
+	pci_iomul_switch_del_locked(sw);
+
+	mutex_lock(&sw->lock);
+	if (sw->io_resource.parent)
+		release_resource(&sw->io_resource);
+	sw->io_base = 0;	/* to tell this switch is removed */
+	sw->io_limit = 0;
+	BUG_ON(!list_empty(&sw->slots));
+	mutex_unlock(&sw->lock);
+
+out:
+	mutex_unlock(&switch_list_lock);
+	pci_iomul_switch_put(sw);
+	return 0;
+}
+
+static int __devinit pci_iomul_notifier_del_device(struct pci_dev *pdev)
+{
+	int ret;
+	switch (pdev->hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+		ret = __pci_iomul_notifier_del_device(pdev);
+		break;
+	case PCI_HEADER_TYPE_BRIDGE:
+		ret = __pci_iomul_notifier_del_switch(pdev);
+		break;
+	default:
+                printk(KERN_WARNING "PCI IOMUL: "
+		       "device %s has unknown header type %02x, ignoring.\n",
+		       pci_name(pdev), pdev->hdr_type);
+		ret = -EIO;
+		break;
+	}
+	return ret;
+}
+
+static int __devinit pci_iomul_notifier(struct notifier_block *nb,
+					unsigned long action, void *data)
+{
+        struct device *dev = data;
+        struct pci_dev *pdev = to_pci_dev(dev);
+
+        switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		quirk_iomul_reassign_ioresource(pdev);
+		break;
+	case BUS_NOTIFY_DEL_DEVICE:
+		return pci_iomul_notifier_del_device(pdev);
+	default:
+		/* nothing */
+		break;
+	}
+
+	return 0;
+}
+
+static struct notifier_block pci_iomul_nb = {
+        .notifier_call = pci_iomul_notifier,
+};
+
+static int __init pci_iomul_hotplug_init(void)
+{
+        bus_register_notifier(&pci_bus_type, &pci_iomul_nb);
+	return 0;
+}
+
+late_initcall(pci_iomul_hotplug_init);
+#endif
+
+/*****************************************************************************/
+struct pci_iomul_data {
+	struct mutex lock;
+
+	struct pci_dev *pdev;
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_slot *slot;	/* slot::kref */
+	struct pci_iomul_func **func;	/* when dereferencing,
+					   sw->lock is necessary */
+};
+
+static int pci_iomul_func_ioport(struct pci_iomul_func *func,
+				 uint8_t bar, uint64_t offset, int *port)
+{
+	if (!(func->io_bar & (1 << bar)))
+		return -EINVAL;
+
+	*port = func->resource[bar].start + offset;
+	if (*port < func->resource[bar].start ||
+	    *port > func->resource[bar].end)
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline int pci_iomul_valid(struct pci_iomul_data *iomul)
+{
+	BUG_ON(!mutex_is_locked(&iomul->lock));
+	BUG_ON(!mutex_is_locked(&iomul->sw->lock));
+	return pci_iomul_switch_io_allocated(iomul->sw) &&
+		*iomul->func != NULL;
+}
+
+static void __pci_iomul_enable_io(struct pci_dev *pdev)
+{
+	uint16_t cmd;
+
+	pci_dev_get(pdev);
+	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_IO;
+	pci_write_config_word(pdev, PCI_COMMAND, cmd);
+}
+
+static void __pci_iomul_disable_io(struct pci_iomul_data *iomul,
+				   struct pci_dev *pdev)
+{
+	uint16_t cmd;
+
+	if (!pci_iomul_valid(iomul))
+		return;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+	cmd &= ~PCI_COMMAND_IO;
+	pci_write_config_word(pdev, PCI_COMMAND, cmd);
+	pci_dev_put(pdev);
+}
+
+static int pci_iomul_open(struct inode *inode, struct file *filp)
+{
+	struct pci_iomul_data *iomul;
+	iomul = kmalloc(sizeof(*iomul), GFP_KERNEL);
+	if (iomul == NULL)
+		return -ENOMEM;
+
+	mutex_init(&iomul->lock);
+	iomul->pdev = NULL;
+	iomul->sw = NULL;
+	iomul->slot = NULL;
+	iomul->func = NULL;
+	filp->private_data = (void*)iomul;
+
+	return 0;
+}
+
+static int pci_iomul_release(struct inode *inode, struct file *filp)
+{
+	struct pci_iomul_data *iomul =
+		(struct pci_iomul_data*)filp->private_data;
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_slot *slot = NULL;
+
+	mutex_lock(&iomul->lock);
+	sw = iomul->sw;
+	slot = iomul->slot;
+	if (iomul->pdev != NULL) {
+		if (sw != NULL) {
+			mutex_lock(&sw->lock);
+			if (sw->current_pdev == iomul->pdev) {
+				__pci_iomul_disable_io(iomul,
+						       sw->current_pdev);
+				sw->current_pdev = NULL;
+			}
+			sw->count--;
+			if (sw->count == 0) {
+				release_region(sw->io_region->start, sw->io_region->end - sw->io_region->start + 1);
+				sw->io_region = NULL;
+			}
+			mutex_unlock(&sw->lock);
+		}
+		pci_dev_put(iomul->pdev);
+	}
+	mutex_unlock(&iomul->lock);
+
+	if (slot != NULL)
+		pci_iomul_slot_put(slot);
+	if (sw != NULL)
+		pci_iomul_switch_put(sw);
+	kfree(iomul);
+	return 0;
+}
+
+static long pci_iomul_setup(struct pci_iomul_data *iomul,
+			    struct pci_iomul_setup __user *arg)
+{
+	long error = 0;
+	struct pci_iomul_setup setup;
+	struct pci_iomul_switch *sw = NULL;
+	struct pci_iomul_slot *slot;
+	struct pci_bus *pbus;
+	struct pci_dev *pdev;
+
+	if (copy_from_user(&setup, arg, sizeof(setup)))
+		return -EFAULT;
+
+	pbus = pci_find_bus(setup.segment, setup.bus);
+	if (pbus == NULL)
+		return -ENODEV;
+	pdev = pci_get_slot(pbus, setup.dev);
+	if (pdev == NULL)
+		return -ENODEV;
+
+	mutex_lock(&iomul->lock);
+	if (iomul->sw != NULL) {
+		error = -EBUSY;
+		goto out0;
+	}
+
+	pci_iomul_get_lock_switch(pdev, &sw, &slot);
+	if (sw == NULL || slot == NULL) {
+		error = -ENODEV;
+		goto out0;
+	}
+	if (!pci_iomul_switch_io_allocated(sw)) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	if (slot->func[setup.func] == NULL) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	if (sw->count == 0) {
+		BUG_ON(sw->io_region != NULL);
+		sw->io_region =
+			request_region(sw->io_base,
+				       sw->io_limit - sw->io_base + 1,
+				       "PCI IO Multiplexer driver");
+		if (sw->io_region == NULL) {
+			mutex_unlock(&sw->lock);
+			error = -EBUSY;
+			goto out;
+		}
+	}
+	sw->count++;
+	pci_iomul_slot_get(slot);
+
+	iomul->pdev = pdev;
+	iomul->sw = sw;
+	iomul->slot = slot;
+	iomul->func = &slot->func[setup.func];
+
+out:
+	mutex_unlock(&sw->lock);
+out0:
+	mutex_unlock(&iomul->lock);
+	if (error != 0) {
+		if (sw != NULL)
+			pci_iomul_switch_put(sw);
+		pci_dev_put(pdev);
+	}
+	return error;
+}
+
+static int pci_iomul_lock(struct pci_iomul_data *iomul,
+			  struct pci_iomul_switch **sw,
+			  struct pci_iomul_func **func)
+{
+	mutex_lock(&iomul->lock);
+	*sw = iomul->sw;
+	if (*sw == NULL) {
+		mutex_unlock(&iomul->lock);
+		return -ENODEV;
+	}
+	mutex_lock(&(*sw)->lock);
+	if (!pci_iomul_valid(iomul)) {
+		mutex_unlock(&(*sw)->lock);
+		mutex_unlock(&iomul->lock);
+		return -ENODEV;
+	}
+	*func = *iomul->func;
+
+	return 0;
+}
+
+static long pci_iomul_disable_io(struct pci_iomul_data *iomul)
+{
+	long error = 0;
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_func *dummy_func;
+	struct pci_dev *pdev;
+
+	if (pci_iomul_lock(iomul, &sw, &dummy_func) < 0)
+		return -ENODEV;
+
+	pdev = iomul->pdev;
+	if (pdev == NULL)
+		error = -ENODEV;
+
+	if (pdev != NULL && sw->current_pdev == pdev) {
+		__pci_iomul_disable_io(iomul, pdev);
+		sw->current_pdev = NULL;
+	}
+
+	mutex_unlock(&sw->lock);
+	mutex_unlock(&iomul->lock);
+	return error;
+}
+
+static void pci_iomul_switch_to(
+	struct pci_iomul_data *iomul, struct pci_iomul_switch *sw,
+	struct pci_dev *next_pdev)
+{
+	if (sw->current_pdev == next_pdev)
+		/* nothing to do */
+		return;
+
+	if (sw->current_pdev != NULL)
+		__pci_iomul_disable_io(iomul, sw->current_pdev);
+
+	__pci_iomul_enable_io(next_pdev);
+	sw->current_pdev = next_pdev;
+}
+
+static long pci_iomul_in(struct pci_iomul_data *iomul,
+			 struct pci_iomul_in __user *arg)
+{
+	struct pci_iomul_in in;
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_func *func;
+
+	long error = 0;
+	int port;
+	uint32_t value = 0;
+
+	if (copy_from_user(&in, arg, sizeof(in)))
+		return -EFAULT;
+
+	if (pci_iomul_lock(iomul, &sw, &func) < 0)
+		return -ENODEV;
+
+	error = pci_iomul_func_ioport(func, in.bar, in.offset, &port);
+	if (error)
+		goto out;
+
+	pci_iomul_switch_to(iomul, sw, iomul->pdev);
+	switch (in.size) {
+	case 4:
+		value = inl(port);
+		break;
+	case 2:
+		value = inw(port);
+		break;
+	case 1:
+		value = inb(port);
+		break;
+	default:
+		error = -EINVAL;
+		break;
+	}
+
+out:
+	mutex_unlock(&sw->lock);
+	mutex_unlock(&iomul->lock);
+
+	if (error == 0 && put_user(value, &arg->value))
+		return -EFAULT;
+	return error;
+}
+
+static long pci_iomul_out(struct pci_iomul_data *iomul,
+			  struct pci_iomul_out __user *arg)
+{
+	struct pci_iomul_in out;
+	struct pci_iomul_switch *sw;
+	struct pci_iomul_func *func;
+
+	long error = 0;
+	int port;
+
+	if (copy_from_user(&out, arg, sizeof(out)))
+		return -EFAULT;
+
+	if (pci_iomul_lock(iomul, &sw, &func) < 0)
+		return -ENODEV;
+
+	error = pci_iomul_func_ioport(func, out.bar, out.offset, &port);
+	if (error)
+		goto out;
+
+	pci_iomul_switch_to(iomul, sw, iomul->pdev);
+	switch (out.size) {
+	case 4:
+		outl(out.value, port);
+		break;
+	case 2:
+		outw(out.value, port);
+		break;
+	case 1:
+		outb(out.value, port);
+		break;
+	default:
+		error = -EINVAL;
+		break;
+	}
+
+out:
+	mutex_unlock(&sw->lock);
+	mutex_unlock(&iomul->lock);
+	return error;
+}
+
+static long pci_iomul_ioctl(struct file *filp,
+			    unsigned int cmd, unsigned long arg)
+{
+	long error;
+	struct pci_iomul_data *iomul =
+		(struct pci_iomul_data*)filp->private_data;
+
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	switch (cmd) {
+	case PCI_IOMUL_SETUP:
+		error = pci_iomul_setup(iomul,
+					(struct pci_iomul_setup __user *)arg);
+		break;
+	case PCI_IOMUL_DISABLE_IO:
+		error = pci_iomul_disable_io(iomul);
+		break;
+	case PCI_IOMUL_IN:
+		error = pci_iomul_in(iomul, (struct pci_iomul_in __user *)arg);
+		break;
+	case PCI_IOMUL_OUT:
+		error = pci_iomul_out(iomul,
+				      (struct pci_iomul_out __user *)arg);
+		break;
+	default:
+		error = -ENOSYS;
+		break;
+	}
+
+	return error;
+}
+
+static const struct file_operations pci_iomul_fops = {
+	.owner = THIS_MODULE,
+
+	.open = pci_iomul_open, /* nonseekable_open */
+	.release = pci_iomul_release,
+
+	.unlocked_ioctl = pci_iomul_ioctl,
+};
+
+static struct miscdevice pci_iomul_miscdev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "pci_iomul",
+	.fops = &pci_iomul_fops,
+};
+
+static int pci_iomul_init(void)
+{
+	int error;
+	error = misc_register(&pci_iomul_miscdev);
+	if (error != 0) {
+		printk(KERN_ALERT "Couldn't register /dev/misc/pci_iomul");
+		return error;
+	}
+	printk("PCI IO multiplexer device installed.\n");
+	return 0;
+}
+
+#if 0
+static void pci_iomul_cleanup(void)
+{
+	misc_deregister(&pci_iomul_miscdev);
+}
+#endif
+
+/*
+ * This must be called after pci fixup final which is called by
+ * device_initcall(pci_init).
+ */
+late_initcall(pci_iomul_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Isaku Yamahata <yamahata@valinux.co.jp>");
+MODULE_DESCRIPTION("PCI IO space multiplexing driver");
--- linux-ec2-2.6.32.orig/drivers/pci/msi.c
+++ linux-ec2-2.6.32/drivers/pci/msi.c
@@ -195,6 +195,9 @@
 void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 {
 	struct msi_desc *entry = get_irq_desc_msi(desc);
+
+	BUG_ON(entry->dev->current_state != PCI_D0);
+
 	if (entry->msi_attrib.is_msix) {
 		void __iomem *base = entry->mask_base +
 			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
@@ -228,10 +231,32 @@
 	read_msi_msg_desc(desc, msg);
 }
 
+void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+{
+	struct msi_desc *entry = get_irq_desc_msi(desc);
+
+	/* Assert that the cache is valid, assuming that
+	 * valid messages are not all-zeroes. */
+	BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
+		 entry->msg.data));
+
+	*msg = entry->msg;
+}
+
+void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	get_cached_msi_msg_desc(desc, msg);
+}
+
 void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
 {
 	struct msi_desc *entry = get_irq_desc_msi(desc);
-	if (entry->msi_attrib.is_msix) {
+
+	if (entry->dev->current_state != PCI_D0) {
+		/* Don't touch the hardware now */
+	} else if (entry->msi_attrib.is_msix) {
 		void __iomem *base;
 		base = entry->mask_base +
 			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
--- linux-ec2-2.6.32.orig/drivers/pci/intel-iommu.c
+++ linux-ec2-2.6.32/drivers/pci/intel-iommu.c
@@ -71,6 +71,49 @@
 #define DMA_32BIT_PFN		IOVA_PFN(DMA_BIT_MASK(32))
 #define DMA_64BIT_PFN		IOVA_PFN(DMA_BIT_MASK(64))
 
+/* page table handling */
+#define LEVEL_STRIDE		(9)
+#define LEVEL_MASK		(((u64)1 << LEVEL_STRIDE) - 1)
+
+static inline int agaw_to_level(int agaw)
+{
+	return agaw + 2;
+}
+
+static inline int agaw_to_width(int agaw)
+{
+	return 30 + agaw * LEVEL_STRIDE;
+}
+
+static inline int width_to_agaw(int width)
+{
+	return (width - 30) / LEVEL_STRIDE;
+}
+
+static inline unsigned int level_to_offset_bits(int level)
+{
+	return (level - 1) * LEVEL_STRIDE;
+}
+
+static inline int pfn_level_offset(unsigned long pfn, int level)
+{
+	return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
+}
+
+static inline unsigned long level_mask(int level)
+{
+	return -1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long level_size(int level)
+{
+	return 1UL << level_to_offset_bits(level);
+}
+
+static inline unsigned long align_to_level(unsigned long pfn, int level)
+{
+	return (pfn + level_size(level) - 1) & level_mask(level);
+}
 
 /* VT-d pages must always be _smaller_ than MM pages. Otherwise things
    are never going to work. */
@@ -339,7 +382,7 @@
 int dmar_disabled = 1;
 #endif /*CONFIG_DMAR_DEFAULT_ON*/
 
-static int __initdata dmar_map_gfx = 1;
+static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
 
@@ -449,8 +492,6 @@
 }
 
 
-static inline int width_to_agaw(int width);
-
 static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
 {
 	unsigned long sagaw;
@@ -664,51 +705,6 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-/* page table handling */
-#define LEVEL_STRIDE		(9)
-#define LEVEL_MASK		(((u64)1 << LEVEL_STRIDE) - 1)
-
-static inline int agaw_to_level(int agaw)
-{
-	return agaw + 2;
-}
-
-static inline int agaw_to_width(int agaw)
-{
-	return 30 + agaw * LEVEL_STRIDE;
-
-}
-
-static inline int width_to_agaw(int width)
-{
-	return (width - 30) / LEVEL_STRIDE;
-}
-
-static inline unsigned int level_to_offset_bits(int level)
-{
-	return (level - 1) * LEVEL_STRIDE;
-}
-
-static inline int pfn_level_offset(unsigned long pfn, int level)
-{
-	return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
-}
-
-static inline unsigned long level_mask(int level)
-{
-	return -1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long level_size(int level)
-{
-	return 1UL << level_to_offset_bits(level);
-}
-
-static inline unsigned long align_to_level(unsigned long pfn, int level)
-{
-	return (pfn + level_size(level) - 1) & level_mask(level);
-}
-
 static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
 				      unsigned long pfn)
 {
@@ -1523,12 +1519,15 @@
 
 		/* Skip top levels of page tables for
 		 * iommu which has less agaw than default.
+		 * Unnecessary for PT mode.
 		 */
-		for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
-			pgd = phys_to_virt(dma_pte_addr(pgd));
-			if (!dma_pte_present(pgd)) {
-				spin_unlock_irqrestore(&iommu->lock, flags);
-				return -ENOMEM;
+		if (translation != CONTEXT_TT_PASS_THROUGH) {
+			for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+				pgd = phys_to_virt(dma_pte_addr(pgd));
+				if (!dma_pte_present(pgd)) {
+					spin_unlock_irqrestore(&iommu->lock, flags);
+					return -ENOMEM;
+				}
 			}
 		}
 	}
@@ -1859,7 +1858,7 @@
 
 	ret = iommu_attach_domain(domain, iommu);
 	if (ret) {
-		domain_exit(domain);
+		free_domain_mem(domain);
 		goto error;
 	}
 
@@ -1991,6 +1990,16 @@
 	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
 	       pci_name(pdev), start, end);
 	
+	if (end < start) {
+		WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
+			"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			dmi_get_system_info(DMI_BIOS_VENDOR),
+			dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		ret = -EIO;
+		goto error;
+	}
+
 	if (end >> agaw_to_width(domain->agaw)) {
 		WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
 		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
@@ -3228,13 +3237,22 @@
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
 
+	if (iommu_no_mapping(dev))
+		return 0;
+
 	domain = find_domain(pdev);
 	if (!domain)
 		return 0;
 
-	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
 		domain_remove_one_dev_info(domain, pdev);
 
+		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+		    list_empty(&domain->devices))
+			domain_exit(domain);
+	}
+
 	return 0;
 }
 
@@ -3381,6 +3399,11 @@
 		domain->iommu_count--;
 		domain_update_iommu_cap(domain);
 		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+		spin_lock_irqsave(&iommu->lock, tmp_flags);
+		clear_bit(domain->id, iommu->domain_ids);
+		iommu->domains[domain->id] = NULL;
+		spin_unlock_irqrestore(&iommu->lock, tmp_flags);
 	}
 
 	spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3718,6 +3741,12 @@
 	 */
 	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
 	rwbf_quirk = 1;
+
+	/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
+	if (dev->revision == 0x07) {
+		printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+		dmar_map_gfx = 0;
+	}
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
--- linux-ec2-2.6.32.orig/drivers/pci/msi-xen.c
+++ linux-ec2-2.6.32/drivers/pci/msi-xen.c
@@ -0,0 +1,838 @@
+/*
+ * 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/err.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/msi.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <xen/evtchn.h>
+
+#include "pci.h"
+#include "msi.h"
+
+static int pci_msi_enable = 1;
+
+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;
+	/* Store default pre-assigned irq */
+	unsigned int default_irq;
+};
+
+struct msi_pirq_entry {
+	struct list_head list;
+	int pirq;
+	int entry_nr;
+};
+
+/* Arch hooks */
+
+#ifndef arch_msi_check_device
+int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	return 0;
+}
+#endif
+
+#ifndef arch_setup_msi_irqs
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	struct msi_desc *entry;
+	int ret;
+
+	/*
+	 * If an architecture wants to support multiple MSI, it needs to
+	 * override arch_setup_msi_irqs()
+	 */
+	if (type == PCI_CAP_ID_MSI && nvec > 1)
+		return 1;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		ret = arch_setup_msi_irq(dev, entry);
+		if (ret < 0)
+			return ret;
+		if (ret > 0)
+			return -ENOSPC;
+	}
+
+	return 0;
+}
+#endif
+
+#ifndef arch_teardown_msi_irqs
+void arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+	struct msi_desc *entry;
+
+	list_for_each_entry(entry, &dev->msi_list, list) {
+		int i, nvec;
+		if (entry->irq == 0)
+			continue;
+		nvec = 1 << entry->msi_attrib.multiple;
+		for (i = 0; i < nvec; i++)
+			arch_teardown_msi_irq(entry->irq + i);
+	}
+}
+#endif
+
+static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
+{
+	u16 control;
+
+	BUG_ON(!pos);
+
+	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+	control &= ~PCI_MSI_FLAGS_ENABLE;
+	if (enable)
+		control |= PCI_MSI_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+}
+
+static void msix_set_enable(struct pci_dev *dev, int enable)
+{
+	int pos;
+	u16 control;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (pos) {
+		pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+		control &= ~PCI_MSIX_FLAGS_ENABLE;
+		if (enable)
+			control |= PCI_MSIX_FLAGS_ENABLE;
+		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+	}
+}
+
+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 = kzalloc(sizeof(struct msi_dev_list), GFP_ATOMIC);
+
+	/* Failed to allocate msi_dev structure */
+	if ( !ret ) {
+		spin_unlock_irqrestore(&msi_dev_lock, flags);
+		return NULL;
+	}
+
+	ret->dev = dev;
+	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;
+}
+EXPORT_SYMBOL(register_msi_get_owner);
+
+int unregister_msi_get_owner(int (*func)(struct pci_dev *dev))
+{
+	if (get_owner != func)
+		return -EINVAL;
+	get_owner = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(unregister_msi_get_owner);
+
+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) {
+		dev_info(&dev->dev, "get owner: %x \n", 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);
+	/* See comments in msi_map_vector, input parameter pirq means
+	 * irq number only if the device belongs to dom0 itself.
+	 */
+	unmap.pirq = (unmap.domid != DOMID_SELF)
+		? pirq : evtchn_get_xen_pirq(pirq);
+
+	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
+		dev_warn(&dev->dev, "unmap irq %x failed\n", pirq);
+
+	if (rc < 0)
+		return rc;
+
+	if (unmap.domid == DOMID_SELF)
+		evtchn_map_pirq(pirq, 0);
+
+	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_vector(struct pci_dev *dev, 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 = -1;
+	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)))
+		dev_warn(&dev->dev, "map irq failed\n");
+
+	if (rc < 0)
+		return rc;
+	/* This happens when MSI support is not enabled in older Xen. */
+	if (rc == 0 && map_irq.pirq < 0)
+		return -ENOSYS;
+
+	BUG_ON(map_irq.pirq <= 0);
+
+	/* If mapping of this particular MSI is on behalf of another domain,
+	 * we do not need to get an irq in dom0. This also implies:
+	 * dev->irq in dom0 will be 'Xen pirq' if this device belongs to
+	 * to another domain, and will be 'Linux irq' if it belongs to dom0.
+	 */
+	if (domid == DOMID_SELF) {
+		rc = evtchn_map_pirq(-1, map_irq.pirq);
+		dev_printk(KERN_DEBUG, &dev->dev,
+			   "irq %d (%d) for MSI/MSI-X\n",
+			   rc, map_irq.pirq);
+		return rc;
+	}
+	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for dom%d MSI/MSI-X\n",
+		   map_irq.pirq, domid);
+	return map_irq.pirq;
+}
+
+static void pci_intx_for_msi(struct pci_dev *dev, int enable)
+{
+	if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
+		pci_intx(dev, enable);
+}
+
+void pci_restore_msi_state(struct pci_dev *dev)
+{
+	int rc;
+	struct physdev_restore_msi restore;
+
+	if (!dev->msi_enabled && !dev->msix_enabled)
+		return;
+
+	pci_intx_for_msi(dev, 0);
+	if (dev->msi_enabled) {
+		int pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+
+		msi_set_enable(dev, pos, 0);
+	}
+	if (dev->msix_enabled)
+		msix_set_enable(dev, 0);
+
+	restore.bus = dev->bus->number;
+	restore.devfn = dev->devfn;
+	rc = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
+	WARN(rc && rc != -ENOSYS, "restore_msi -> %d\n", rc);
+}
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
+
+/**
+ * msi_capability_init - configure device's MSI capability structure
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ * @nvec: number of interrupts to allocate
+ *
+ * Setup the MSI capability structure of the device with the requested
+ * number of interrupts.  A return value of zero indicates the successful
+ * setup of an entry with the new MSI irq.  A negative return value indicates
+ * an error, and a positive return value indicates the number of interrupts
+ * which could have been allocated.
+ */
+static int msi_capability_init(struct pci_dev *dev, int nvec)
+{
+	int pos, pirq;
+	u16 control;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	msi_set_enable(dev, pos, 0);	/* Disable MSI during set up */
+
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+
+	WARN_ON(nvec > 1); /* XXX */
+	pirq = msi_map_vector(dev, 0, 0);
+	if (pirq < 0)
+		return -EBUSY;
+
+	/* Set MSI enabled bits	 */
+	pci_intx_for_msi(dev, 0);
+	msi_set_enable(dev, pos, 1);
+	dev->msi_enabled = 1;
+
+	dev->irq = pirq;
+	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 irq. A return of zero indicates the successful setup of
+ * requested MSI-X entries with allocated irqs 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;
+	u16 control;
+	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;
+
+	msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+
+	/* Ensure MSI-X is disabled while it is set up */
+	control &= ~PCI_MSIX_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
+	table_base = find_table_base(dev, pos);
+	if (!table_base)
+		return -ENODEV;
+
+	/*
+	 * Some devices require MSI-X to be enabled before we can touch the
+	 * MSI-X registers.  We need to mask all the vectors to prevent
+	 * interrupts coming in before they're fully set up.
+	 */
+	control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
+	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) {
+				dev_warn(&dev->dev,
+					 "msix entry %d was not freed\n",
+					 entries[i].entry);
+				(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) {
+		int avail = i - 1;
+		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;
+		}
+		/* If we had some success report the number of irqs
+		 * we succeeded in setting up.
+		 */
+		if (avail <= 0)
+			avail = -EBUSY;
+		return avail;
+	}
+
+	/* Set MSI-X enabled bits and unmask the function */
+	pci_intx_for_msi(dev, 0);
+	dev->msix_enabled = 1;
+
+	control &= ~PCI_MSIX_FLAGS_MASKALL;
+	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+
+	return 0;
+}
+
+/**
+ * pci_msi_check_device - check whether MSI may be enabled on a device
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ * @nvec: how many MSIs have been requested ?
+ * @type: are we checking for MSI or MSI-X ?
+ *
+ * Look at global flags, the device itself, and its parent busses
+ * to determine if MSI/-X are supported for the device. If MSI/-X is
+ * supported return 0, else return an error code.
+ **/
+static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+	struct pci_bus *bus;
+	int ret;
+
+	/* MSI must be globally enabled and supported by the device */
+	if (!pci_msi_enable || !dev || dev->no_msi)
+		return -EINVAL;
+
+	/*
+	 * You can't ask to have 0 or less MSIs configured.
+	 *  a) it's stupid ..
+	 *  b) the list manipulation code assumes nvec >= 1.
+	 */
+	if (nvec < 1)
+		return -ERANGE;
+
+	/*
+	 * Any bridge which does NOT route MSI transactions from its
+	 * secondary bus to its primary bus must set NO_MSI flag on
+	 * the secondary pci_bus.
+	 * We expect only arch-specific PCI host bus controller driver
+	 * or quirks for specific PCI bridges to be setting NO_MSI.
+	 */
+	for (bus = dev->bus; bus; bus = bus->parent)
+		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+			return -EINVAL;
+
+	ret = arch_msi_check_device(dev, nvec, type);
+	if (ret)
+		return ret;
+
+	if (!pci_find_capability(dev, type))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * pci_enable_msi_block - configure device's MSI capability structure
+ * @dev: device to configure
+ * @nvec: number of interrupts to configure
+ *
+ * Allocate IRQs for a device with the MSI capability.
+ * This function returns a negative errno if an error occurs.  If it
+ * is unable to allocate the number of interrupts requested, it returns
+ * the number of interrupts it might be able to allocate.  If it successfully
+ * allocates at least the number of interrupts requested, it returns 0 and
+ * updates the @dev's irq member to the lowest new interrupt number; the
+ * other interrupt numbers allocated to this device are consecutive.
+ */
+extern int pci_frontend_enable_msi(struct pci_dev *dev);
+int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
+{
+	int temp, status, pos, maxvec;
+	u16 msgctl;
+	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	if (!pos)
+		return -EINVAL;
+	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+	maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+	if (nvec > maxvec)
+		return maxvec;
+
+	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
+	if (status)
+ 		return status;
+
+#ifdef CONFIG_XEN_PCIDEV_FRONTEND
+	if (!is_initial_xendomain())
+	{
+		int ret;
+
+		temp = dev->irq;
+		WARN_ON(nvec > 1); /* XXX */
+		ret = pci_frontend_enable_msi(dev);
+		if (ret)
+			return ret;
+
+		dev->irq = evtchn_map_pirq(-1, dev->irq);
+		msi_dev_entry->default_irq = temp;
+
+		return ret;
+	}
+#endif
+
+	temp = dev->irq;
+
+	/* Check whether driver already requested MSI-X irqs */
+	if (dev->msix_enabled) {
+		dev_info(&dev->dev, "can't enable MSI "
+			 "(MSI-X already enabled)\n");
+		return -EINVAL;
+	}
+
+	status = msi_capability_init(dev, nvec);
+	if ( !status )
+		msi_dev_entry->default_irq = temp;
+
+	return status;
+}
+EXPORT_SYMBOL(pci_enable_msi_block);
+
+extern void pci_frontend_disable_msi(struct pci_dev* dev);
+void pci_msi_shutdown(struct pci_dev *dev)
+{
+	int pirq, pos;
+	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+
+	if (!pci_msi_enable || !dev)
+		return;
+
+#ifdef CONFIG_XEN_PCIDEV_FRONTEND
+	if (!is_initial_xendomain()) {
+		evtchn_map_pirq(dev->irq, 0);
+		pci_frontend_disable_msi(dev);
+		dev->irq = msi_dev_entry->default_irq;
+		return;
+	}
+#endif
+
+	if (!dev->msi_enabled)
+		return;
+
+	pirq = dev->irq;
+	/* Restore dev->irq to its default pin-assertion vector */
+	dev->irq = msi_dev_entry->default_irq;
+	msi_unmap_pirq(dev, pirq);
+
+	/* Disable MSI mode */
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+	msi_set_enable(dev, pos, 0);
+	pci_intx_for_msi(dev, 1);
+	dev->msi_enabled = 0;
+}
+
+void pci_disable_msi(struct pci_dev *dev)
+{
+	pci_msi_shutdown(dev);
+}
+EXPORT_SYMBOL(pci_disable_msi);
+
+/**
+ * pci_msix_table_size - return the number of device's MSI-X table entries
+ * @dev: pointer to the pci_dev data structure of MSI-X device function
+ */
+int pci_msix_table_size(struct pci_dev *dev)
+{
+	int pos;
+	u16 control;
+
+	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+	if (!pos)
+		return 0;
+
+	pci_read_config_word(dev, msi_control_reg(pos), &control);
+	return multi_msix_capable(control);
+}
+
+/**
+ * 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 irqs requested for allocation by device driver
+ *
+ * Setup the MSI-X capability structure of device function with the number
+ * of requested irqs 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 irqs. A return of < 0 indicates a failure.
+ * Or a return of > 0 indicates that driver request is exceeding the number
+ * of irqs or MSI-X 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)
+{
+	int status, nr_entries;
+	int i, j, temp;
+	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+
+	if (!entries)
+		return -EINVAL;
+
+#ifdef CONFIG_XEN_PCIDEV_FRONTEND
+	if (!is_initial_xendomain()) {
+		struct msi_pirq_entry *pirq_entry;
+		int ret, irq;
+
+		temp = dev->irq;
+		ret = pci_frontend_enable_msix(dev, entries, nvec);
+		if (ret) {
+			dev_warn(&dev->dev,
+				 "got %x from frontend_enable_msix\n", ret);
+			return ret;
+		}
+		msi_dev_entry->default_irq = temp;
+
+		for (i = 0; i < nvec; i++) {
+			int mapped = 0;
+
+			list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
+				if (pirq_entry->entry_nr == entries[i].entry) {
+					irq = pirq_entry->pirq;
+					BUG_ON(entries[i].vector != evtchn_get_xen_pirq(irq));
+					entries[i].vector = irq;
+					mapped = 1;
+					break;
+				}
+			}
+			if (mapped)
+				continue;
+			irq = evtchn_map_pirq(-1, entries[i].vector);
+			attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
+			entries[i].vector = irq;
+		}
+        return 0;
+	}
+#endif
+
+	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
+	if (status)
+		return status;
+
+	nr_entries = pci_msix_table_size(dev);
+	if (nvec > nr_entries)
+		return nr_entries;
+
+	/* 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) {
+		dev_info(&dev->dev, "can't enable MSI-X "
+		       "(MSI IRQ already assigned)\n");
+		return -EINVAL;
+	}
+
+	status = msix_capability_init(dev, entries, nvec);
+
+	if ( !status )
+		msi_dev_entry->default_irq = temp;
+
+	return status;
+}
+EXPORT_SYMBOL(pci_enable_msix);
+
+extern void pci_frontend_disable_msix(struct pci_dev* dev);
+void pci_msix_shutdown(struct pci_dev *dev)
+{
+	if (!pci_msi_enable)
+		return;
+	if (!dev)
+		return;
+
+#ifdef CONFIG_XEN_PCIDEV_FRONTEND
+	if (!is_initial_xendomain()) {
+		struct msi_dev_list *msi_dev_entry;
+		struct msi_pirq_entry *pirq_entry, *tmp;
+
+		pci_frontend_disable_msix(dev);
+
+		msi_dev_entry = get_msi_dev_pirq_list(dev);
+		list_for_each_entry_safe(pirq_entry, tmp,
+		                         &msi_dev_entry->pirq_list_head, list) {
+			evtchn_map_pirq(pirq_entry->pirq, 0);
+			list_del(&pirq_entry->list);
+			kfree(pirq_entry);
+		}
+
+		dev->irq = msi_dev_entry->default_irq;
+		return;
+	}
+#endif
+
+	if (!dev->msix_enabled)
+		return;
+
+	msi_remove_pci_irq_vectors(dev);
+
+	/* Disable MSI mode */
+	msix_set_enable(dev, 0);
+	pci_intx_for_msi(dev, 1);
+	dev->msix_enabled = 0;
+}
+
+void pci_disable_msix(struct pci_dev *dev)
+{
+	pci_msix_shutdown(dev);
+}
+EXPORT_SYMBOL(pci_disable_msix);
+
+/**
+ * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs 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 irqs, 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))
+		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 = msi_dev_entry->default_irq;
+}
+
+void pci_no_msi(void)
+{
+	pci_msi_enable = 0;
+}
+
+/**
+ * pci_msi_enabled - is MSI enabled?
+ *
+ * Returns true if MSI has not been disabled by the command-line option
+ * pci=nomsi.
+ **/
+int pci_msi_enabled(void)
+{
+	return pci_msi_enable;
+}
+EXPORT_SYMBOL(pci_msi_enabled);
+
+void pci_msi_init_pci_dev(struct pci_dev *dev)
+{
+#ifndef CONFIG_XEN
+	INIT_LIST_HEAD(&dev->msi_list);
+#endif
+}
--- linux-ec2-2.6.32.orig/drivers/pci/setup-bus.c
+++ linux-ec2-2.6.32/drivers/pci/setup-bus.c
@@ -142,7 +142,6 @@
 	struct pci_dev *bridge = bus->self;
 	struct pci_bus_region region;
 	u32 l, bu, lu, io_upper16;
-	int pref_mem64;
 
 	if (pci_is_enabled(bridge))
 		return;
@@ -198,7 +197,6 @@
 	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
 
 	/* Set up PREF base/limit. */
-	pref_mem64 = 0;
 	bu = lu = 0;
 	pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
 	if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
@@ -206,7 +204,6 @@
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
 		if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
-			pref_mem64 = 1;
 			bu = upper_32_bits(region.start);
 			lu = upper_32_bits(region.end);
 			width = 16;
@@ -221,11 +218,9 @@
 	}
 	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
-	if (pref_mem64) {
-		/* Set the upper 32 bits of PREF base & limit. */
-		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
-		pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
-	}
+	/* Set the upper 32 bits of PREF base & limit. */
+	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
 
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
@@ -343,7 +338,7 @@
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 	size = (size & 0xff) + ((size & ~0xffUL) << 2);
 #endif
-	size = ALIGN(size + size1, 4096);
+	size = ALIGN(max(size + size1, pci_reserve_size_io(bus)), 4096);
 	if (!size) {
 		b_res->flags = 0;
 		return;
@@ -423,7 +418,8 @@
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size = ALIGN(size, min_align);
+	size = ALIGN(max(size, (resource_size_t)pci_reserve_size_mem(bus)),
+		     min_align);
 	if (!size) {
 		b_res->flags = 0;
 		return 1;
--- linux-ec2-2.6.32.orig/drivers/pci/proc.c
+++ linux-ec2-2.6.32/drivers/pci/proc.c
@@ -259,7 +259,7 @@
 
 	/* Make sure the caller is mapping a real resource for this device */
 	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-		if (pci_mmap_fits(dev, i, vma))
+		if (pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
 			break;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/pci/iomulti.h
+++ linux-ec2-2.6.32/drivers/pci/iomulti.h
@@ -0,0 +1,51 @@
+#ifndef PCI_IOMULTI_H
+#define PCI_IOMULTI_H
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+struct pci_iomul_setup {
+	uint16_t	segment;
+	uint8_t		bus;
+	uint8_t		dev;
+	uint8_t		func;
+};
+
+struct pci_iomul_in {
+	uint8_t		bar;
+	uint64_t	offset;
+
+	uint8_t		size;
+	uint32_t	value;
+};
+
+struct pci_iomul_out {
+	uint8_t		bar;
+	uint64_t	offset;
+
+	uint8_t		size;
+	uint32_t	value;
+};
+
+#define PCI_IOMUL_SETUP		_IOW ('P', 0, struct pci_iomul_setup)
+#define PCI_IOMUL_DISABLE_IO	_IO  ('P', 1)
+#define PCI_IOMUL_IN		_IOWR('P', 2, struct pci_iomul_in)
+#define PCI_IOMUL_OUT		_IOW ('P', 3, struct pci_iomul_out)
+
+#endif /* PCI_IOMULTI_H */
--- linux-ec2-2.6.32.orig/drivers/pci/pci.c
+++ linux-ec2-2.6.32/drivers/pci/pci.c
@@ -373,8 +373,12 @@
 			continue;	/* Wrong type */
 		if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
 			return r;	/* Exact match */
-		if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH))
-			best = r;	/* Approximating prefetchable by non-prefetchable */
+		/* We can't insert a non-prefetch resource inside a prefetchable parent .. */
+		if (r->flags & IORESOURCE_PREFETCH)
+			continue;
+		/* .. but we can put a prefetchable resource inside a non-prefetchable one */
+		if (!best)
+			best = r;
 	}
 	return best;
 }
@@ -386,7 +390,12 @@
  * Restore the BAR values for a given device, so as to make it
  * accessible by its driver.
  */
+#ifndef CONFIG_XEN
 static void
+#else
+EXPORT_SYMBOL_GPL(pci_restore_bars);
+void
+#endif
 pci_restore_bars(struct pci_dev *dev)
 {
 	int i;
@@ -601,7 +610,7 @@
  */
 int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state)
 {
-	return state > PCI_D0 ?
+	return state >= PCI_D0 ?
 			pci_platform_power_transition(dev, state) : -EINVAL;
 }
 EXPORT_SYMBOL_GPL(__pci_complete_power_transition);
@@ -638,10 +647,6 @@
 		 */
 		return 0;
 
-	/* Check if we're already there */
-	if (dev->current_state == state)
-		return 0;
-
 	__pci_start_power_transition(dev, state);
 
 	/* This device is quirked not to be put into D3, so
@@ -2050,6 +2055,7 @@
 		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
 	}
 }
+EXPORT_SYMBOL_GPL(pci_msi_off);
 
 #ifndef HAVE_ARCH_PCI_SET_DMA_MASK
 /*
@@ -2350,18 +2356,17 @@
  */
 int pcix_get_max_mmrbc(struct pci_dev *dev)
 {
-	int err, cap;
+	int cap;
 	u32 stat;
 
 	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	if (!cap)
 		return -EINVAL;
 
-	err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
-	if (err)
+	if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat))
 		return -EINVAL;
 
-	return (stat & PCI_X_STATUS_MAX_READ) >> 12;
+	return 512 << ((stat & PCI_X_STATUS_MAX_READ) >> 21);
 }
 EXPORT_SYMBOL(pcix_get_max_mmrbc);
 
@@ -2374,18 +2379,17 @@
  */
 int pcix_get_mmrbc(struct pci_dev *dev)
 {
-	int ret, cap;
-	u32 cmd;
+	int cap;
+	u16 cmd;
 
 	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	if (!cap)
 		return -EINVAL;
 
-	ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
-	if (!ret)
-		ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
+	if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd))
+		return -EINVAL;
 
-	return ret;
+	return 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
 }
 EXPORT_SYMBOL(pcix_get_mmrbc);
 
@@ -2400,28 +2404,27 @@
  */
 int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
 {
-	int cap, err = -EINVAL;
-	u32 stat, cmd, v, o;
+	int cap;
+	u32 stat, v, o;
+	u16 cmd;
 
 	if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc))
-		goto out;
+		return -EINVAL;
 
 	v = ffs(mmrbc) - 10;
 
 	cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
 	if (!cap)
-		goto out;
+		return -EINVAL;
 
-	err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
-	if (err)
-		goto out;
+	if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat))
+		return -EINVAL;
 
 	if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21)
 		return -E2BIG;
 
-	err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
-	if (err)
-		goto out;
+	if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd))
+		return -EINVAL;
 
 	o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
 	if (o != v) {
@@ -2431,10 +2434,10 @@
 
 		cmd &= ~PCI_X_CMD_MAX_READ;
 		cmd |= v << 2;
-		err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd);
+		if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd))
+			return -EIO;
 	}
-out:
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL(pcix_set_mmrbc);
 
@@ -2544,6 +2547,23 @@
 	return 0;
 }
 
+/* Some architectures require additional programming to enable VGA */
+static arch_set_vga_state_t arch_set_vga_state;
+
+void __init pci_register_set_vga_state(arch_set_vga_state_t func)
+{
+	arch_set_vga_state = func;	/* NULL disables */
+}
+
+static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
+		      unsigned int command_bits, bool change_bridge)
+{
+	if (arch_set_vga_state)
+		return arch_set_vga_state(dev, decode, command_bits,
+						change_bridge);
+	return 0;
+}
+
 /**
  * pci_set_vga_state - set VGA decode state on device and parents if requested
  * @dev: the PCI device
@@ -2557,9 +2577,15 @@
 	struct pci_bus *bus;
 	struct pci_dev *bridge;
 	u16 cmd;
+	int rc;
 
 	WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
 
+	/* ARCH specific VGA enables */
+	rc = pci_set_vga_state_arch(dev, decode, command_bits, change_bridge);
+	if (rc)
+		return rc;
+
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	if (decode == true)
 		cmd |= command_bits;
@@ -2658,6 +2684,13 @@
  */
 int pci_is_reassigndev(struct pci_dev *dev)
 {
+#ifdef CONFIG_PCI_GUESTDEV
+	int result;
+
+	result = pci_is_guestdev_to_reassign(dev);
+	if (result)
+		return result;
+#endif /* CONFIG_PCI_GUESTDEV */
 	return (pci_specified_resource_alignment(dev) != 0);
 }
 
@@ -2723,6 +2756,11 @@
 	return 1;
 }
 
+void __weak pci_fixup_cardbus(struct pci_bus *bus)
+{
+}
+EXPORT_SYMBOL(pci_fixup_cardbus);
+
 static int __init pci_setup(char *str)
 {
 	while (str) {
@@ -2801,4 +2839,3 @@
 EXPORT_SYMBOL(pci_prepare_to_sleep);
 EXPORT_SYMBOL(pci_back_from_sleep);
 EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
-
--- linux-ec2-2.6.32.orig/drivers/pci/reserve.c
+++ linux-ec2-2.6.32/drivers/pci/reserve.c
@@ -0,0 +1,143 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (c) 2009 Isaku Yamahata
+ *                    VA Linux Systems Japan K.K.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include <asm/setup.h>
+
+static char pci_reserve_param[COMMAND_LINE_SIZE];
+
+/* pci_reserve=	[PCI]
+ * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
+ * Format of sbdf: [<segment>:]<bus>:<dev>.<func>
+ */
+static int pci_reserve_parse_size(const char *str,
+				  unsigned long *io_size,
+				  unsigned long *mem_size)
+{
+	if (sscanf(str, "io%lx", io_size) == 1 ||
+	    sscanf(str, "IO%lx", io_size) == 1)
+		return 0;
+
+	if (sscanf(str, "mem%lx", mem_size) == 1 ||
+	    sscanf(str, "MEM%lx", mem_size) == 1)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int pci_reserve_parse_one(const char *str,
+				 int *seg, int *bus, int *dev, int *func,
+				 unsigned long *io_size,
+				 unsigned long *mem_size)
+{
+	char *p;
+
+	*io_size = 0;
+	*mem_size = 0;
+
+	if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) {
+		*seg = 0;
+		if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) {
+			return -EINVAL;
+		}
+	}
+
+	p = strchr(str, '+');
+	if (p == NULL)
+		return -EINVAL;
+	p++;
+	if (pci_reserve_parse_size(p, io_size, mem_size))
+		return -EINVAL;
+
+	p = strchr(str, '+');
+	if (p != NULL) {
+		p++;
+		pci_reserve_parse_size(p, io_size, mem_size);
+	}
+	return 0;
+}
+
+static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags)
+{
+	char *sp;
+	char *ep;
+
+	int seg;
+	int bus;
+	int dev;
+	int func;
+
+	unsigned long io_size;
+	unsigned long mem_size;
+
+	sp = pci_reserve_param;
+
+	do {
+		ep = strchr(sp, ',');
+		if (ep)
+			*ep = '\0';	/* chomp */
+
+		if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func,
+					  &io_size, &mem_size) == 0) {
+			if (pci_domain_nr(pbus) == seg &&
+			    pbus->number == bus &&
+			    PCI_SLOT(pbus->self->devfn) == dev &&
+			    PCI_FUNC(pbus->self->devfn) == func) {
+				switch (flags) {
+				case IORESOURCE_IO:
+					return io_size;
+				case IORESOURCE_MEM:
+					return mem_size;
+				default:
+					break;
+				}
+			}
+		}
+
+		if (ep) {
+			*ep = ',';	/* restore chomp'ed ',' for later */
+			ep++;
+		}
+		sp = ep;
+	} while (ep);
+
+	return 0;
+}
+
+unsigned long pci_reserve_size_io(struct pci_bus *pbus)
+{
+	return pci_reserve_size(pbus, IORESOURCE_IO);
+}
+
+unsigned long pci_reserve_size_mem(struct pci_bus *pbus)
+{
+	return pci_reserve_size(pbus, IORESOURCE_MEM);
+}
+
+static int __init pci_reserve_setup(char *str)
+{
+	if (strlen(str) >= sizeof(pci_reserve_param))
+		return 0;
+	strlcpy(pci_reserve_param, str, sizeof(pci_reserve_param));
+	return 1;
+}
+__setup("pci_reserve=", pci_reserve_setup);
--- linux-ec2-2.6.32.orig/drivers/pci/hotplug/ibmphp_ebda.c
+++ linux-ec2-2.6.32/drivers/pci/hotplug/ibmphp_ebda.c
@@ -245,7 +245,7 @@
 
 int __init ibmphp_access_ebda (void)
 {
-	u8 format, num_ctlrs, rio_complete, hs_complete;
+	u8 format, num_ctlrs, rio_complete, hs_complete, ebda_sz;
 	u16 ebda_seg, num_entries, next_offset, offset, blk_id, sub_addr, re, rc_id, re_id, base;
 	int rc = 0;
 
@@ -260,7 +260,16 @@
 	iounmap (io_mem);
 	debug ("returned ebda segment: %x\n", ebda_seg);
 	
-	io_mem = ioremap(ebda_seg<<4, 1024);
+	io_mem = ioremap(ebda_seg<<4, 1);
+	if (!io_mem)
+		return -ENOMEM;
+	ebda_sz = readb(io_mem);
+	iounmap(io_mem);
+	debug("ebda size: %d(KiB)\n", ebda_sz);
+	if (ebda_sz == 0)
+		return -ENOMEM;
+
+	io_mem = ioremap(ebda_seg<<4, (ebda_sz * 1024));
 	if (!io_mem )
 		return -ENOMEM;
 	next_offset = 0x180;
--- linux-ec2-2.6.32.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-ec2-2.6.32/drivers/pci/hotplug/acpiphp_glue.c
@@ -213,6 +213,7 @@
 
 	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
 	if (pdev) {
+		pdev->current_state = PCI_D0;
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 		pci_dev_put(pdev);
 	}
--- linux-ec2-2.6.32.orig/drivers/pci/pcie/aer/aerdrv_core.c
+++ linux-ec2-2.6.32/drivers/pci/pcie/aer/aerdrv_core.c
@@ -78,19 +78,15 @@
 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
 {
 	int pos;
-	u32 status, mask;
+	u32 status;
 
 	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
 	if (!pos)
 		return -EIO;
 
 	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
-	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
-	if (dev->error_state == pci_channel_io_normal)
-		status &= ~mask; /* Clear corresponding nonfatal bits */
-	else
-		status &= mask; /* Clear corresponding fatal bits */
-	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+	if (status)
+		pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/pci/pcie/aer/aer_inject.c
+++ linux-ec2-2.6.32/drivers/pci/pcie/aer/aer_inject.c
@@ -302,7 +302,7 @@
 	unsigned long flags;
 	unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
 	int pos_cap_err, rp_pos_cap_err;
-	u32 sever;
+	u32 sever, cor_mask, uncor_mask;
 	int ret = 0;
 
 	dev = pci_get_bus_and_slot(einj->bus, devfn);
@@ -320,6 +320,9 @@
 		goto out_put;
 	}
 	pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
+	pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &cor_mask);
+	pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
+			      &uncor_mask);
 
 	rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
 	if (!rp_pos_cap_err) {
@@ -354,6 +357,21 @@
 	err->header_log2 = einj->header_log2;
 	err->header_log3 = einj->header_log3;
 
+	if (einj->cor_status && !(einj->cor_status & ~cor_mask)) {
+		ret = -EINVAL;
+		printk(KERN_WARNING "The correctable error(s) is masked "
+				"by device\n");
+		spin_unlock_irqrestore(&inject_lock, flags);
+		goto out_put;
+	}
+	if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) {
+		ret = -EINVAL;
+		printk(KERN_WARNING "The uncorrectable error(s) is masked "
+				"by device\n");
+		spin_unlock_irqrestore(&inject_lock, flags);
+		goto out_put;
+	}
+
 	rperr = __find_aer_error_by_dev(rpdev);
 	if (!rperr) {
 		rperr = rperr_alloc;
@@ -392,8 +410,14 @@
 	if (ret)
 		goto out_put;
 
-	if (find_aer_device(rpdev, &edev))
+	if (find_aer_device(rpdev, &edev)) {
+		if (!get_service_data(edev)) {
+			printk(KERN_WARNING "AER service is not initialized\n");
+			ret = -EINVAL;
+			goto out_put;
+		}
 		aer_irq(-1, edev);
+	}
 	else
 		ret = -EINVAL;
 out_put:
--- linux-ec2-2.6.32.orig/drivers/ata/ata_generic.c
+++ linux-ec2-2.6.32/drivers/ata/ata_generic.c
@@ -32,6 +32,11 @@
  *	A generic parallel ATA driver using libata
  */
 
+enum {
+	ATA_GEN_CLASS_MATCH		= (1 << 0),
+	ATA_GEN_FORCE_DMA		= (1 << 1),
+};
+
 /**
  *	generic_set_mode	-	mode setting
  *	@link: link to set up
@@ -46,13 +51,17 @@
 static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
 {
 	struct ata_port *ap = link->ap;
+	const struct pci_device_id *id = ap->host->private_data;
 	int dma_enabled = 0;
 	struct ata_device *dev;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
-	/* Bits 5 and 6 indicate if DMA is active on master/slave */
-	if (ap->ioaddr.bmdma_addr)
+	if (id->driver_data & ATA_GEN_FORCE_DMA) {
+		dma_enabled = 0xff;
+	} else if (ap->ioaddr.bmdma_addr) {
+		/* Bits 5 and 6 indicate if DMA is active on master/slave */
 		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	}
 
 	if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
 		dma_enabled = 0xFF;
@@ -126,7 +135,7 @@
 	const struct ata_port_info *ppi[] = { &info, NULL };
 
 	/* Don't use the generic entry unless instructed to do so */
-	if (id->driver_data == 1 && all_generic_ide == 0)
+	if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)
 		return -ENODEV;
 
 	/* Devices that need care */
@@ -155,7 +164,7 @@
 			return rc;
 		pcim_pin_device(dev);
 	}
-	return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
+	return ata_pci_sff_init_one(dev, ppi, &generic_sht, (void *)id);
 }
 
 static struct pci_device_id ata_generic[] = {
@@ -167,12 +176,21 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
-	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
+	  .driver_data = ATA_GEN_FORCE_DMA },
+	/*
+	 * For some reason, MCP89 on MacBook 7,1 doesn't work with
+	 * ahci, use ata_generic instead.
+	 */
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
+	  PCI_VENDOR_ID_APPLE, 0xcb89,
+	  .driver_data = ATA_GEN_FORCE_DMA },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
 	/* Must come last. If you add entries adjust this table appropriately */
-	{ PCI_ANY_ID,		PCI_ANY_ID,			   PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
+	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
+	  .driver_data = ATA_GEN_CLASS_MATCH },
 	{ 0, },
 };
 
--- linux-ec2-2.6.32.orig/drivers/ata/sata_mv.c
+++ linux-ec2-2.6.32/drivers/ata/sata_mv.c
@@ -1879,19 +1879,25 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+static void mv_bmdma_stop_ap(struct ata_port *ap)
 {
-	struct ata_port *ap = qc->ap;
 	void __iomem *port_mmio = mv_ap_base(ap);
 	u32 cmd;
 
 	/* clear start/stop bit */
 	cmd = readl(port_mmio + BMDMA_CMD);
-	cmd &= ~ATA_DMA_START;
-	writelfl(cmd, port_mmio + BMDMA_CMD);
+	if (cmd & ATA_DMA_START) {
+		cmd &= ~ATA_DMA_START;
+		writelfl(cmd, port_mmio + BMDMA_CMD);
 
-	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-	ata_sff_dma_pause(ap);
+		/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+		ata_sff_dma_pause(ap);
+	}
+}
+
+static void mv_bmdma_stop(struct ata_queued_cmd *qc)
+{
+	mv_bmdma_stop_ap(qc->ap);
 }
 
 /**
@@ -1915,8 +1921,21 @@
 	reg = readl(port_mmio + BMDMA_STATUS);
 	if (reg & ATA_DMA_ACTIVE)
 		status = ATA_DMA_ACTIVE;
-	else
+	else if (reg & ATA_DMA_ERR)
 		status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR;
+	else {
+		/*
+		 * Just because DMA_ACTIVE is 0 (DMA completed),
+		 * this does _not_ mean the device is "done".
+		 * So we should not yet be signalling ATA_DMA_INTR
+		 * in some cases.  Eg. DSM/TRIM, and perhaps others.
+		 */
+		mv_bmdma_stop_ap(ap);
+		if (ioread8(ap->ioaddr.altstatus_addr) & ATA_BUSY)
+			status = 0;
+		else
+			status = ATA_DMA_INTR;
+	}
 	return status;
 }
 
@@ -1976,6 +1995,9 @@
 
 	switch (tf->protocol) {
 	case ATA_PROT_DMA:
+		if (tf->command == ATA_CMD_DSM)
+			return;
+		/* fall-thru */
 	case ATA_PROT_NCQ:
 		break;	/* continue below */
 	case ATA_PROT_PIO:
@@ -2075,6 +2097,8 @@
 	if ((tf->protocol != ATA_PROT_DMA) &&
 	    (tf->protocol != ATA_PROT_NCQ))
 		return;
+	if (tf->command == ATA_CMD_DSM)
+		return;  /* use bmdma for this */
 
 	/* Fill in Gen IIE command request block */
 	if (!(tf->flags & ATA_TFLAG_WRITE))
@@ -2270,6 +2294,12 @@
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
+		if (qc->tf.command == ATA_CMD_DSM) {
+			if (!ap->ops->bmdma_setup)  /* no bmdma on GEN_I */
+				return AC_ERR_OTHER;
+			break;  /* use bmdma for this */
+		}
+		/* fall thru */
 	case ATA_PROT_NCQ:
 		mv_start_edma(ap, port_mmio, pp, qc->tf.protocol);
 		pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK;
--- linux-ec2-2.6.32.orig/drivers/ata/pata_cmd64x.c
+++ linux-ec2-2.6.32/drivers/ata/pata_cmd64x.c
@@ -219,7 +219,7 @@
 		regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift;
 		/* Merge the control bits */
 		regU |= 1 << adev->devno; /* UDMA on */
-		if (adev->dma_mode > 2)	/* 15nS timing */
+		if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */
 			regU |= 4 << adev->devno;
 	} else {
 		regU &= ~ (1 << adev->devno);	/* UDMA off */
--- linux-ec2-2.6.32.orig/drivers/ata/libata-scsi.c
+++ linux-ec2-2.6.32/drivers/ata/libata-scsi.c
@@ -1099,13 +1099,13 @@
 	/* configure max sectors */
 	blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
 
+	sdev->sector_size = ATA_SECT_SIZE;
+
 	if (dev->class == ATA_DEV_ATAPI) {
 		struct request_queue *q = sdev->request_queue;
 		void *buf;
 
-		/* set the min alignment and padding */
-		blk_queue_update_dma_alignment(sdev->request_queue,
-					       ATA_DMA_PAD_SZ - 1);
+		/* set DMA padding */
 		blk_queue_update_dma_pad(sdev->request_queue,
 					 ATA_DMA_PAD_SZ - 1);
 
@@ -1119,12 +1119,24 @@
 
 		blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
 	} else {
-		/* ATA devices must be sector aligned */
-		blk_queue_update_dma_alignment(sdev->request_queue,
-					       ATA_SECT_SIZE - 1);
 		sdev->manage_start_stop = 1;
 	}
 
+	/*
+	 * ata_pio_sectors() expects buffer for each sector to not cross
+	 * page boundary.  Enforce it by requiring buffers to be sector
+	 * aligned, which works iff sector_size is not larger than
+	 * PAGE_SIZE.  ATAPI devices also need the alignment as
+	 * IDENTIFY_PACKET is executed as ATA_PROT_PIO.
+	 */
+	if (sdev->sector_size > PAGE_SIZE)
+		ata_dev_printk(dev, KERN_WARNING,
+			"sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
+			sdev->sector_size);
+
+	blk_queue_update_dma_alignment(sdev->request_queue,
+				       sdev->sector_size - 1);
+
 	if (dev->flags & ATA_DFLAG_AN)
 		set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
 
@@ -2497,8 +2509,11 @@
 		 *
 		 * If door lock fails, always clear sdev->locked to
 		 * avoid this infinite loop.
+		 *
+		 * This may happen before SCSI scan is complete.  Make
+		 * sure qc->dev->sdev isn't NULL before dereferencing.
 		 */
-		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
+		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)
 			qc->dev->sdev->locked = 0;
 
 		qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
@@ -2825,7 +2840,7 @@
 	 * write indication (used for PIO/DMA setup), result TF is
 	 * copied back and we don't whine too much about its failure.
 	 */
-	tf->flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	if (scmd->sc_data_direction == DMA_TO_DEVICE)
 		tf->flags |= ATA_TFLAG_WRITE;
 
--- linux-ec2-2.6.32.orig/drivers/ata/pata_ali.c
+++ linux-ec2-2.6.32/drivers/ata/pata_ali.c
@@ -453,7 +453,9 @@
 			/* Clear CD-ROM DMA write bit */
 			tmp &= 0x7F;
 		/* Cable and UDMA */
-		pci_write_config_byte(pdev, 0x4B, tmp | 0x09);
+		if (pdev->revision >= 0xc2)
+			tmp |= 0x01;
+		pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
 		/*
 		 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
 		 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
--- linux-ec2-2.6.32.orig/drivers/ata/pata_pdc202xx_old.c
+++ linux-ec2-2.6.32/drivers/ata/pata_pdc202xx_old.c
@@ -2,7 +2,7 @@
  * pata_pdc202xx_old.c 	- Promise PDC202xx PATA for new ATA layer
  *			  (C) 2005 Red Hat Inc
  *			  Alan Cox <alan@lxorguk.ukuu.org.uk>
- *			  (C) 2007,2009 Bartlomiej Zolnierkiewicz
+ *			  (C) 2007,2009,2010 Bartlomiej Zolnierkiewicz
  *
  * Based in part on linux/drivers/ide/pci/pdc202xx_old.c
  *
@@ -35,6 +35,15 @@
 	return ATA_CBL_PATA80;
 }
 
+static void pdc202xx_exec_command(struct ata_port *ap,
+				  const struct ata_taskfile *tf)
+{
+	DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+
+	iowrite8(tf->command, ap->ioaddr.command_addr);
+	ndelay(400);
+}
+
 /**
  *	pdc202xx_configure_piomode	-	set chip PIO timing
  *	@ap: ATA interface
@@ -271,6 +280,8 @@
 	.cable_detect		= ata_cable_40wire,
 	.set_piomode		= pdc202xx_set_piomode,
 	.set_dmamode		= pdc202xx_set_dmamode,
+
+	.sff_exec_command	= pdc202xx_exec_command,
 };
 
 static struct ata_port_operations pdc2026x_port_ops = {
@@ -284,6 +295,8 @@
 	.dev_config		= pdc2026x_dev_config,
 
 	.port_start		= pdc2026x_port_start,
+
+	.sff_exec_command	= pdc202xx_exec_command,
 };
 
 static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
--- linux-ec2-2.6.32.orig/drivers/ata/ahci.c
+++ linux-ec2-2.6.32/drivers/ata/ahci.c
@@ -113,6 +113,7 @@
 	board_ahci_mcp65	= 6,
 	board_ahci_nopmp	= 7,
 	board_ahci_yesncq	= 8,
+	board_ahci_nosntf	= 9,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -235,6 +236,7 @@
 	AHCI_HFLAG_NO_SUSPEND		= (1 << 10), /* don't suspend */
 	AHCI_HFLAG_SRST_TOUT_IS_OFFLINE	= (1 << 11), /* treat SRST timeout as
 							link offline */
+	AHCI_HFLAG_NO_SNTF		= (1 << 12), /* no sntf */
 
 	/* ap->flags bits */
 
@@ -508,7 +510,7 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
-	/* board_ahci_yesncq */
+	[board_ahci_yesncq] =
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_YES_NCQ),
 		.flags		= AHCI_FLAG_COMMON,
@@ -516,6 +518,14 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
+	[board_ahci_nosntf] =
+	{
+		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
@@ -531,7 +541,7 @@
 	{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
 	{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
 	{ PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
-	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
+	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_nosntf }, /* ICH8 */
 	{ PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
 	{ PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
 	{ PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
@@ -560,6 +570,17 @@
 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
+	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
+	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
+	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
+	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -849,6 +870,12 @@
 		cap &= ~HOST_CAP_PMP;
 	}
 
+	if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "controller can't do SNTF, turning off CAP_SNTF\n");
+		cap &= ~HOST_CAP_SNTF;
+	}
+
 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361 &&
 	    port_map != 1) {
 		dev_printk(KERN_INFO, &pdev->dev,
@@ -2815,6 +2842,14 @@
 		 * On HP dv[4-6] and HDX18 with earlier BIOSen, link
 		 * to the harddisk doesn't become online after
 		 * resuming from STR.  Warn and fail suspend.
+		 *
+		 * http://bugzilla.kernel.org/show_bug.cgi?id=12276
+		 *
+		 * Use dates instead of versions to match as HP is
+		 * apparently recycling both product and version
+		 * strings.
+		 *
+		 * http://bugzilla.kernel.org/show_bug.cgi?id=15462
 		 */
 		{
 			.ident = "dv4",
@@ -2823,7 +2858,7 @@
 				DMI_MATCH(DMI_PRODUCT_NAME,
 					  "HP Pavilion dv4 Notebook PC"),
 			},
-			.driver_data = "F.30", /* cutoff BIOS version */
+			.driver_data = "20090105",	/* F.30 */
 		},
 		{
 			.ident = "dv5",
@@ -2832,7 +2867,7 @@
 				DMI_MATCH(DMI_PRODUCT_NAME,
 					  "HP Pavilion dv5 Notebook PC"),
 			},
-			.driver_data = "F.16", /* cutoff BIOS version */
+			.driver_data = "20090506",	/* F.16 */
 		},
 		{
 			.ident = "dv6",
@@ -2841,7 +2876,7 @@
 				DMI_MATCH(DMI_PRODUCT_NAME,
 					  "HP Pavilion dv6 Notebook PC"),
 			},
-			.driver_data = "F.21",	/* cutoff BIOS version */
+			.driver_data = "20090423",	/* F.21 */
 		},
 		{
 			.ident = "HDX18",
@@ -2850,19 +2885,38 @@
 				DMI_MATCH(DMI_PRODUCT_NAME,
 					  "HP HDX18 Notebook PC"),
 			},
-			.driver_data = "F.23",	/* cutoff BIOS version */
+			.driver_data = "20090430",	/* F.23 */
+		},
+		/*
+		 * Acer eMachines G725 has the same problem.  BIOS
+		 * V1.03 is known to be broken.  V3.04 is known to
+		 * work.  Inbetween, there are V1.06, V2.06 and V3.03
+		 * that we don't have much idea about.  For now,
+		 * blacklist anything older than V3.04.
+		 *
+		 * http://bugzilla.kernel.org/show_bug.cgi?id=15104
+		 */
+		{
+			.ident = "G725",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "eMachines"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "eMachines G725"),
+			},
+			.driver_data = "20091216",	/* V3.04 */
 		},
 		{ }	/* terminate list */
 	};
 	const struct dmi_system_id *dmi = dmi_first_match(sysids);
-	const char *ver;
+	int year, month, date;
+	char buf[9];
 
 	if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2))
 		return false;
 
-	ver = dmi_get_system_info(DMI_BIOS_VERSION);
+	dmi_get_date(DMI_BIOS_DATE, &year, &month, &date);
+	snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date);
 
-	return !ver || strcmp(ver, dmi->driver_data) < 0;
+	return strcmp(buf, dmi->driver_data) < 0;
 }
 
 static bool ahci_broken_online(struct pci_dev *pdev)
@@ -2988,6 +3042,16 @@
 	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
 		return -ENODEV;
 
+	/*
+	 * For some reason, MCP89 on MacBook 7,1 doesn't work with
+	 * ahci, use ata_generic instead.
+	 */
+	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+	    pdev->subsystem_device == 0xcb89)
+		return -ENODEV;
+
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -3043,8 +3107,16 @@
 	ahci_save_initial_config(pdev, hpriv);
 
 	/* prepare host */
-	if (hpriv->cap & HOST_CAP_NCQ)
-		pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA;
+	if (hpriv->cap & HOST_CAP_NCQ) {
+		pi.flags |= ATA_FLAG_NCQ;
+		/* Auto-activate optimization is supposed to be supported on
+		   all AHCI controllers indicating NCQ support, but it seems
+		   to be broken at least on some NVIDIA MCP79 chipsets.
+		   Until we get info on which NVIDIA chipsets don't have this
+		   issue, if any, disable AA on all NVIDIA AHCIs. */
+		if (pdev->vendor != PCI_VENDOR_ID_NVIDIA)
+			pi.flags |= ATA_FLAG_FPDMA_AA;
+	}
 
 	if (hpriv->cap & HOST_CAP_PMP)
 		pi.flags |= ATA_FLAG_PMP;
--- linux-ec2-2.6.32.orig/drivers/ata/pata_mpc52xx.c
+++ linux-ec2-2.6.32/drivers/ata/pata_mpc52xx.c
@@ -610,7 +610,7 @@
 };
 
 static struct ata_port_operations mpc52xx_ata_port_ops = {
-	.inherits		= &ata_sff_port_ops,
+	.inherits		= &ata_bmdma_port_ops,
 	.sff_dev_select		= mpc52xx_ata_dev_select,
 	.set_piomode		= mpc52xx_ata_set_piomode,
 	.set_dmamode		= mpc52xx_ata_set_dmamode,
--- linux-ec2-2.6.32.orig/drivers/ata/libata-eh.c
+++ linux-ec2-2.6.32/drivers/ata/libata-eh.c
@@ -870,6 +870,8 @@
 void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
+	struct request_queue *q = qc->scsicmd->device->request_queue;
+	unsigned long flags;
 
 	WARN_ON(!ap->ops->error_handler);
 
@@ -881,7 +883,9 @@
 	 * Note that ATA_QCFLAG_FAILED is unconditionally set after
 	 * this function completes.
 	 */
+	spin_lock_irqsave(q->queue_lock, flags);
 	blk_abort_request(qc->scsicmd->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -1615,6 +1619,7 @@
 	}
 
 	/* okay, this error is ours */
+	memset(&tf, 0, sizeof(tf));
 	rc = ata_eh_read_log_10h(dev, &tag, &tf);
 	if (rc) {
 		ata_link_printk(link, KERN_ERR, "failed to read log page 10h "
@@ -2019,8 +2024,9 @@
 			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
 
 		/* determine whether the command is worth retrying */
-		if (!(qc->err_mask & AC_ERR_INVALID) &&
-		    ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV))
+		if (qc->flags & ATA_QCFLAG_IO ||
+		    (!(qc->err_mask & AC_ERR_INVALID) &&
+		     qc->err_mask != AC_ERR_DEV))
 			qc->flags |= ATA_QCFLAG_RETRY;
 
 		/* accumulate error info */
@@ -3143,6 +3149,10 @@
 	if (link->flags & ATA_LFLAG_DISABLED)
 		return 1;
 
+	/* skip if explicitly requested */
+	if (ehc->i.flags & ATA_EHI_NO_RECOVERY)
+		return 1;
+
 	/* thaw frozen port and recover failed devices */
 	if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
 		return 0;
--- linux-ec2-2.6.32.orig/drivers/ata/pata_hpt3x2n.c
+++ linux-ec2-2.6.32/drivers/ata/pata_hpt3x2n.c
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
- * Portions Copyright (C) 2005-2007	MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
  *
  *
  * TODO
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x2n"
-#define DRV_VERSION	"0.3.4"
+#define DRV_VERSION	"0.3.9"
 
 enum {
 	HPT_PCI_FAST	=	(1 << 31),
@@ -185,9 +185,8 @@
 
 	pci_read_config_dword(pdev, addr1, &reg);
 	mode = hpt3x2n_find_mode(ap, adev->pio_mode);
-	mode &= ~0x8000000;	/* No FIFO in PIO */
-	mode &= ~0x30070000;	/* Leave config bits alone */
-	reg &= 0x30070000;	/* Strip timing bits */
+	mode &= 0xCFC3FFFF;	/* Leave DMA bits alone */
+	reg &= ~0xCFC3FFFF;	/* Strip timing bits */
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
@@ -204,8 +203,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 addr1, addr2;
-	u32 reg;
-	u32 mode;
+	u32 reg, mode, mask;
 	u8 fast;
 
 	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -216,11 +214,12 @@
 	fast &= ~0x07;
 	pci_write_config_byte(pdev, addr2, fast);
 
+	mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
 	pci_read_config_dword(pdev, addr1, &reg);
 	mode = hpt3x2n_find_mode(ap, adev->dma_mode);
-	mode |= 0x8000000;	/* FIFO in MWDMA or UDMA */
-	mode &= ~0xC0000000;	/* Leave config bits alone */
-	reg &= 0xC0000000;	/* Strip timing bits */
+	mode &= mask;
+	reg &= ~mask;
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
@@ -263,7 +262,7 @@
 
 static void hpt3x2n_set_clock(struct ata_port *ap, int source)
 {
-	void __iomem *bmdma = ap->ioaddr.bmdma_addr;
+	void __iomem *bmdma = ap->ioaddr.bmdma_addr - ap->port_no * 8;
 
 	/* Tristate the bus */
 	iowrite8(0x80, bmdma+0x73);
@@ -273,9 +272,9 @@
 	iowrite8(source, bmdma+0x7B);
 	iowrite8(0xC0, bmdma+0x79);
 
-	/* Reset state machines */
-	iowrite8(0x37, bmdma+0x70);
-	iowrite8(0x37, bmdma+0x74);
+	/* Reset state machines, avoid enabling the disabled channels */
+	iowrite8(ioread8(bmdma+0x70) | 0x32, bmdma+0x70);
+	iowrite8(ioread8(bmdma+0x74) | 0x32, bmdma+0x74);
 
 	/* Complete reset */
 	iowrite8(0x00, bmdma+0x79);
@@ -285,21 +284,10 @@
 	iowrite8(0x00, bmdma+0x77);
 }
 
-/* Check if our partner interface is busy */
-
-static int hpt3x2n_pair_idle(struct ata_port *ap)
-{
-	struct ata_host *host = ap->host;
-	struct ata_port *pair = host->ports[ap->port_no ^ 1];
-
-	if (pair->hsm_task_state == HSM_ST_IDLE)
-		return 1;
-	return 0;
-}
-
 static int hpt3x2n_use_dpll(struct ata_port *ap, int writing)
 {
 	long flags = (long)ap->host->private_data;
+
 	/* See if we should use the DPLL */
 	if (writing)
 		return USE_DPLL;	/* Needed for write */
@@ -308,20 +296,35 @@
 	return 0;
 }
 
+static int hpt3x2n_qc_defer(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_port *alt = ap->host->ports[ap->port_no ^ 1];
+	int rc, flags = (long)ap->host->private_data;
+	int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
+
+	/* First apply the usual rules */
+	rc = ata_std_qc_defer(qc);
+	if (rc != 0)
+		return rc;
+
+	if ((flags & USE_DPLL) != dpll && alt->qc_active)
+		return ATA_DEFER_PORT;
+	return 0;
+}
+
 static unsigned int hpt3x2n_qc_issue(struct ata_queued_cmd *qc)
 {
-	struct ata_taskfile *tf = &qc->tf;
 	struct ata_port *ap = qc->ap;
 	int flags = (long)ap->host->private_data;
+	int dpll = hpt3x2n_use_dpll(ap, qc->tf.flags & ATA_TFLAG_WRITE);
 
-	if (hpt3x2n_pair_idle(ap)) {
-		int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE));
-		if ((flags & USE_DPLL) != dpll) {
-			if (dpll == 1)
-				hpt3x2n_set_clock(ap, 0x21);
-			else
-				hpt3x2n_set_clock(ap, 0x23);
-		}
+	if ((flags & USE_DPLL) != dpll) {
+		flags &= ~USE_DPLL;
+		flags |= dpll;
+		ap->host->private_data = (void *)(long)flags;
+
+		hpt3x2n_set_clock(ap, dpll ? 0x21 : 0x23);
 	}
 	return ata_sff_qc_issue(qc);
 }
@@ -338,6 +341,8 @@
 	.inherits	= &ata_bmdma_port_ops,
 
 	.bmdma_stop	= hpt3x2n_bmdma_stop,
+
+	.qc_defer	= hpt3x2n_qc_defer,
 	.qc_issue	= hpt3x2n_qc_issue,
 
 	.cable_detect	= hpt3x2n_cable_detect,
@@ -455,7 +460,7 @@
 	unsigned int f_low, f_high;
 	int adjust;
 	unsigned long iobase = pci_resource_start(dev, 4);
-	void *hpriv = NULL;
+	void *hpriv = (void *)USE_DPLL;
 	int rc;
 
 	rc = pcim_enable_device(dev);
@@ -542,16 +547,16 @@
 	       pci_mhz);
 	/* Set our private data up. We only need a few flags so we use
 	   it directly */
-	if (pci_mhz > 60) {
-		hpriv = (void *)PCI66;
-		/*
-		 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
-		 * the MISC. register to stretch the UltraDMA Tss timing.
-		 * NOTE: This register is only writeable via I/O space.
-		 */
-		if (dev->device == PCI_DEVICE_ID_TTI_HPT371)
-			outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);
-	}
+	if (pci_mhz > 60)
+		hpriv = (void *)(PCI66 | USE_DPLL);
+
+	/*
+	 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
+	 * the MISC. register to stretch the UltraDMA Tss timing.
+	 * NOTE: This register is only writeable via I/O space.
+	 */
+	if (dev->device == PCI_DEVICE_ID_TTI_HPT371)
+		outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c);
 
 	/* Now kick off ATA set up */
 	return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv);
--- linux-ec2-2.6.32.orig/drivers/ata/libata-core.c
+++ linux-ec2-2.6.32/drivers/ata/libata-core.c
@@ -139,7 +139,7 @@
 module_param_named(fua, libata_fua, int, 0444);
 MODULE_PARM_DESC(fua, "FUA support (0=off [default], 1=on)");
 
-static int ata_ignore_hpa;
+static int ata_ignore_hpa = 1;
 module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
 MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)");
 
@@ -159,6 +159,10 @@
 module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
 MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)");
 
+static int atapi_an;
+module_param(atapi_an, int, 0444);
+MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -2570,7 +2574,8 @@
 		 * to enable ATAPI AN to discern between PHY status
 		 * changed notifications and ATAPI ANs.
 		 */
-		if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
+		if (atapi_an &&
+		    (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
 		    (!sata_pmp_attached(ap) ||
 		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
 			unsigned int err_mask;
@@ -3790,21 +3795,45 @@
 int sata_link_resume(struct ata_link *link, const unsigned long *params,
 		     unsigned long deadline)
 {
+	int tries = ATA_LINK_RESUME_TRIES;
 	u32 scontrol, serror;
 	int rc;
 
 	if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
 		return rc;
 
-	scontrol = (scontrol & 0x0f0) | 0x300;
+	/*
+	 * Writes to SControl sometimes get ignored under certain
+	 * controllers (ata_piix SIDPR).  Make sure DET actually is
+	 * cleared.
+	 */
+	do {
+		scontrol = (scontrol & 0x0f0) | 0x300;
+		if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
+			return rc;
+		/*
+		 * Some PHYs react badly if SStatus is pounded
+		 * immediately after resuming.  Delay 200ms before
+		 * debouncing.
+		 */
+		msleep(200);
 
-	if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol)))
-		return rc;
+		/* is SControl restored correctly? */
+		if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
+			return rc;
+	} while ((scontrol & 0xf0f) != 0x300 && --tries);
 
-	/* Some PHYs react badly if SStatus is pounded immediately
-	 * after resuming.  Delay 200ms before debouncing.
-	 */
-	msleep(200);
+	if ((scontrol & 0xf0f) != 0x300) {
+		ata_link_printk(link, KERN_ERR,
+				"failed to resume link (SControl %X)\n",
+				scontrol);
+		return 0;
+	}
+
+	if (tries < ATA_LINK_RESUME_TRIES)
+		ata_link_printk(link, KERN_WARNING,
+				"link resume succeeded after %d retries\n",
+				ATA_LINK_RESUME_TRIES - tries);
 
 	if ((rc = sata_link_debounce(link, params, deadline)))
 		return rc;
@@ -4323,6 +4352,10 @@
 	{ "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
 	{ "HTS541080G9SA00",    "MB4OC60D",     ATA_HORKAGE_NONCQ, },
 	{ "HTS541010G9SA00",    "MBZOC60D",     ATA_HORKAGE_NONCQ, },
+	{ "FUJITSU MHW2160BH PL", "0084001E",   ATA_HORKAGE_NONCQ, },
+
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
+	{ "C300-CTFDDAC128MAG",	"0001",		ATA_HORKAGE_NONCQ, },
 
 	/* devices which puke on READ_NATIVE_MAX */
 	{ "HDS724040KLSA80",	"KFAOA20N",	ATA_HORKAGE_BROKEN_HPA, },
@@ -4984,9 +5017,6 @@
 {
 	struct ata_device *dev = qc->dev;
 
-	if (ata_tag_internal(qc->tag))
-		return;
-
 	if (ata_is_nodata(qc->tf.protocol))
 		return;
 
@@ -5030,14 +5060,23 @@
 		if (unlikely(qc->err_mask))
 			qc->flags |= ATA_QCFLAG_FAILED;
 
-		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-			/* always fill result TF for failed qc */
+		/*
+		 * Finish internal commands without any further processing
+		 * and always with the result TF filled.
+		 */
+		if (unlikely(ata_tag_internal(qc->tag))) {
 			fill_result_tf(qc);
+			__ata_qc_complete(qc);
+			return;
+		}
 
-			if (!ata_tag_internal(qc->tag))
-				ata_qc_schedule_eh(qc);
-			else
-				__ata_qc_complete(qc);
+		/*
+		 * Non-internal qc has failed.  Fill the result TF and
+		 * summon EH.
+		 */
+		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+			fill_result_tf(qc);
+			ata_qc_schedule_eh(qc);
 			return;
 		}
 
@@ -5472,6 +5511,7 @@
  */
 int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
 {
+	unsigned int ehi_flags = ATA_EHI_QUIET;
 	int rc;
 
 	/*
@@ -5480,7 +5520,18 @@
 	 */
 	ata_lpm_enable(host);
 
-	rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
+	/*
+	 * On some hardware, device fails to respond after spun down
+	 * for suspend.  As the device won't be used before being
+	 * resumed, we don't need to touch the device.  Ask EH to skip
+	 * the usual stuff and proceed directly to suspend.
+	 *
+	 * http://thread.gmane.org/gmane.linux.ide/46764
+	 */
+	if (mesg.event == PM_EVENT_SUSPEND)
+		ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
+
+	rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
 	if (rc == 0)
 		host->dev->power.power_state = mesg;
 	return rc;
--- linux-ec2-2.6.32.orig/drivers/ata/libata-sff.c
+++ linux-ec2-2.6.32/drivers/ata/libata-sff.c
@@ -893,6 +893,9 @@
 				       do_write);
 	}
 
+	if (!do_write && !PageSlab(page))
+		flush_dcache_page(page);
+
 	qc->curbytes += qc->sect_size;
 	qc->cursg_ofs += qc->sect_size;
 
--- linux-ec2-2.6.32.orig/drivers/ata/pata_hpt37x.c
+++ linux-ec2-2.6.32/drivers/ata/pata_hpt37x.c
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt37x"
-#define DRV_VERSION	"0.6.12"
+#define DRV_VERSION	"0.6.14"
 
 struct hpt_clock {
 	u8	xfer_speed;
@@ -404,9 +404,8 @@
 
 	pci_read_config_dword(pdev, addr1, &reg);
 	mode = hpt37x_find_mode(ap, adev->pio_mode);
-	mode &= ~0x8000000;	/* No FIFO in PIO */
-	mode &= ~0x30070000;	/* Leave config bits alone */
-	reg &= 0x30070000;	/* Strip timing bits */
+	mode &= 0xCFC3FFFF;	/* Leave DMA bits alone */
+	reg &= ~0xCFC3FFFF;	/* Strip timing bits */
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
@@ -423,8 +422,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 addr1, addr2;
-	u32 reg;
-	u32 mode;
+	u32 reg, mode, mask;
 	u8 fast;
 
 	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -436,11 +434,12 @@
 	fast |= 0x01;
 	pci_write_config_byte(pdev, addr2, fast);
 
+	mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
 	pci_read_config_dword(pdev, addr1, &reg);
 	mode = hpt37x_find_mode(ap, adev->dma_mode);
-	mode |= 0x8000000;	/* FIFO in MWDMA or UDMA */
-	mode &= ~0xC0000000;	/* Leave config bits alone */
-	reg &= 0xC0000000;	/* Strip timing bits */
+	mode &= mask;
+	reg &= ~mask;
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
@@ -508,9 +507,8 @@
 	mode = hpt37x_find_mode(ap, adev->pio_mode);
 
 	printk("Find mode for %d reports %X\n", adev->pio_mode, mode);
-	mode &= ~0x80000000;	/* No FIFO in PIO */
-	mode &= ~0x30070000;	/* Leave config bits alone */
-	reg &= 0x30070000;	/* Strip timing bits */
+	mode &= 0xCFC3FFFF;	/* Leave DMA bits alone */
+	reg &= ~0xCFC3FFFF;	/* Strip timing bits */
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
@@ -527,8 +525,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	u32 addr1, addr2;
-	u32 reg;
-	u32 mode;
+	u32 reg, mode, mask;
 	u8 fast;
 
 	addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
@@ -539,12 +536,13 @@
 	fast &= ~0x07;
 	pci_write_config_byte(pdev, addr2, fast);
 
+	mask = adev->dma_mode < XFER_UDMA_0 ? 0x31C001FF : 0x303C0000;
+
 	pci_read_config_dword(pdev, addr1, &reg);
 	mode = hpt37x_find_mode(ap, adev->dma_mode);
 	printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode);
-	mode &= ~0xC0000000;	/* Leave config bits alone */
-	mode |= 0x80000000;	/* FIFO in MWDMA or UDMA */
-	reg &= 0xC0000000;	/* Strip timing bits */
+	mode &= mask;
+	reg &= ~mask;
 	pci_write_config_dword(pdev, addr1, reg | mode);
 }
 
--- linux-ec2-2.6.32.orig/drivers/ata/sata_via.c
+++ linux-ec2-2.6.32/drivers/ata/sata_via.c
@@ -40,6 +40,8 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
@@ -80,6 +82,7 @@
 static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
 static void svia_noop_freeze(struct ata_port *ap);
 static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
+static void vt6420_bmdma_start(struct ata_queued_cmd *qc);
 static int vt6421_pata_cable_detect(struct ata_port *ap);
 static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
 static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
@@ -121,6 +124,7 @@
 	.inherits		= &svia_base_ops,
 	.freeze			= svia_noop_freeze,
 	.prereset		= vt6420_prereset,
+	.bmdma_start		= vt6420_bmdma_start,
 };
 
 static struct ata_port_operations vt6421_pata_ops = {
@@ -377,6 +381,17 @@
 	return 0;
 }
 
+static void vt6420_bmdma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	if ((qc->tf.command == ATA_CMD_PACKET) &&
+	    (qc->scsicmd->sc_data_direction == DMA_TO_DEVICE)) {
+		/* Prevents corruption on some ATAPI burners */
+		ata_sff_pause(ap);
+	}
+	ata_bmdma_start(qc);
+}
+
 static int vt6421_pata_cable_detect(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -558,6 +573,19 @@
 		tmp8 |= NATIVE_MODE_ALL;
 		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
 	}
+
+	/*
+	 * vt6421 has problems talking to some drives.  The following
+	 * is the magic fix from Joseph Chan <JosephChan@via.com.tw>.
+	 * Please add proper documentation if possible.
+	 *
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=15173
+	 */
+	if (pdev->device == 0x3249) {
+		pci_read_config_byte(pdev, 0x52, &tmp8);
+		tmp8 |= 1 << 2;
+		pci_write_config_byte(pdev, 0x52, tmp8);
+	}
 }
 
 static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
--- linux-ec2-2.6.32.orig/drivers/ata/sata_nv.c
+++ linux-ec2-2.6.32/drivers/ata/sata_nv.c
@@ -1673,7 +1673,6 @@
 	mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
 	mask &= ~(NV_INT_ALL_MCP55 << shift);
 	writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-	ata_sff_freeze(ap);
 }
 
 static void nv_mcp55_thaw(struct ata_port *ap)
@@ -1687,7 +1686,6 @@
 	mask = readl(mmio_base + NV_INT_ENABLE_MCP55);
 	mask |= (NV_INT_MASK_MCP55 << shift);
 	writel(mask, mmio_base + NV_INT_ENABLE_MCP55);
-	ata_sff_thaw(ap);
 }
 
 static void nv_adma_error_handler(struct ata_port *ap)
@@ -2478,8 +2476,7 @@
 	}
 
 	pci_set_master(pdev);
-	return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
-				 IRQF_SHARED, ipriv->sht);
+	return ata_pci_sff_activate_host(host, ipriv->irq_handler, ipriv->sht);
 }
 
 #ifdef CONFIG_PM
--- linux-ec2-2.6.32.orig/drivers/ata/pata_via.c
+++ linux-ec2-2.6.32/drivers/ata/pata_via.c
@@ -661,6 +661,7 @@
 	{ PCI_VDEVICE(VIA, 0x3164), },
 	{ PCI_VDEVICE(VIA, 0x5324), },
 	{ PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE },
+	{ PCI_VDEVICE(VIA, 0x9001), VIA_IDFLAG_SINGLE },
 
 	{ },
 };
--- linux-ec2-2.6.32.orig/drivers/ata/ata_piix.c
+++ linux-ec2-2.6.32/drivers/ata/ata_piix.c
@@ -157,6 +157,7 @@
 struct piix_host_priv {
 	const int *map;
 	u32 saved_iocfg;
+	spinlock_t sidpr_lock;	/* FIXME: remove once locking in EH is fixed */
 	void __iomem *sidpr;
 };
 
@@ -291,6 +292,14 @@
 	{ 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	/* SATA Controller IDE (PCH) */
 	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	/* SATA Controller IDE (CPT) */
+	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	/* SATA Controller IDE (CPT) */
+	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	/* SATA Controller IDE (CPT) */
+	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (CPT) */
+	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	{ }	/* terminate list */
 };
 
@@ -869,10 +878,10 @@
 				(timings[pio][1] << 8);
 		}
 
-		if (ap->udma_mask) {
+		if (ap->udma_mask)
 			udma_enable &= ~(1 << devid);
-			pci_write_config_word(dev, master_port, master_data);
-		}
+
+		pci_write_config_word(dev, master_port, master_data);
 	}
 	/* Don't scribble on 0x48 if the controller does not support UDMA */
 	if (ap->udma_mask)
@@ -940,12 +949,15 @@
 			       unsigned int reg, u32 *val)
 {
 	struct piix_host_priv *hpriv = link->ap->host->private_data;
+	unsigned long flags;
 
 	if (reg >= ARRAY_SIZE(piix_sidx_map))
 		return -EINVAL;
 
+	spin_lock_irqsave(&hpriv->sidpr_lock, flags);
 	piix_sidpr_sel(link, reg);
 	*val = ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
+	spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
 	return 0;
 }
 
@@ -953,12 +965,15 @@
 				unsigned int reg, u32 val)
 {
 	struct piix_host_priv *hpriv = link->ap->host->private_data;
+	unsigned long flags;
 
 	if (reg >= ARRAY_SIZE(piix_sidx_map))
 		return -EINVAL;
 
+	spin_lock_irqsave(&hpriv->sidpr_lock, flags);
 	piix_sidpr_sel(link, reg);
 	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
+	spin_unlock_irqrestore(&hpriv->sidpr_lock, flags);
 	return 0;
 }
 
@@ -1547,6 +1562,7 @@
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	if (!hpriv)
 		return -ENOMEM;
+	spin_lock_init(&hpriv->sidpr_lock);
 
 	/* Save IOCFG, this will be used for cable detection, quirk
 	 * detection and restoration on detach.  This is necessary
--- linux-ec2-2.6.32.orig/drivers/bluetooth/hci_ldisc.c
+++ linux-ec2-2.6.32/drivers/bluetooth/hci_ldisc.c
@@ -258,9 +258,16 @@
 
 	BT_DBG("tty %p", tty);
 
+	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+	   the pointer */
 	if (hu)
 		return -EEXIST;
 
+	/* Error if the tty has no write op instead of leaving an exploitable
+	   hole */
+	if (tty->ops->write == NULL)
+		return -EOPNOTSUPP;
+
 	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
 		BT_ERR("Can't allocate control structure");
 		return -ENFILE;
--- linux-ec2-2.6.32.orig/drivers/bluetooth/btusb.c
+++ linux-ec2-2.6.32/drivers/bluetooth/btusb.c
@@ -59,6 +59,21 @@
 	/* Generic Bluetooth USB device */
 	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+	/* Apple MacBookPro 7,1 */
+	{ USB_DEVICE(0x05ac, 0x8213) },
+
+	/* Apple iMac11,1 */
+	{ USB_DEVICE(0x05ac, 0x8215) },
+
+	/* Apple MacBookPro6,2 */
+	{ USB_DEVICE(0x05ac, 0x8218) },
+
+	/* Apple MacBookAir3,1, MacBookAir3,2 */
+	{ USB_DEVICE(0x05ac, 0x821b) },
+
+	/* Apple MacBookPro8,2 */
+	{ USB_DEVICE(0x05ac, 0x821a) },
+
 	/* AVM BlueFRITZ! USB v2.0 */
 	{ USB_DEVICE(0x057c, 0x3800) },
 
@@ -307,6 +322,7 @@
 		return;
 
 	usb_anchor_urb(urb, &data->bulk_anchor);
+	usb_mark_last_busy(data->udev);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err < 0) {
--- linux-ec2-2.6.32.orig/drivers/scsi/qla1280.c
+++ linux-ec2-2.6.32/drivers/scsi/qla1280.c
@@ -1640,8 +1640,10 @@
 	uint16_t mb[MAILBOX_REGISTER_COUNT], i;
 	int err;
 
+	spin_unlock_irq(ha->host->host_lock);
 	err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
 			       &ha->pdev->dev);
+	spin_lock_irq(ha->host->host_lock);
 	if (err) {
 		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
 		       ql1280_board_tbl[ha->devnum].fwname, err);
@@ -1699,8 +1701,10 @@
 		return -ENOMEM;
 #endif
 
+	spin_unlock_irq(ha->host->host_lock);
 	err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
 			       &ha->pdev->dev);
+	spin_lock_irq(ha->host->host_lock);
 	if (err) {
 		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
 		       ql1280_board_tbl[ha->devnum].fwname, err);
--- linux-ec2-2.6.32.orig/drivers/scsi/gdth.c
+++ linux-ec2-2.6.32/drivers/scsi/gdth.c
@@ -4174,6 +4174,14 @@
     ha = gdth_find_ha(gen.ionode);
     if (!ha)
         return -EFAULT;
+
+    if (gen.data_len > INT_MAX)
+        return -EINVAL;
+    if (gen.sense_len > INT_MAX)
+        return -EINVAL;
+    if (gen.data_len + gen.sense_len > INT_MAX)
+        return -EINVAL;
+
     if (gen.data_len + gen.sense_len != 0) {
         if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len,
                                      FALSE, &paddr)))
--- linux-ec2-2.6.32.orig/drivers/scsi/hosts.c
+++ linux-ec2-2.6.32/drivers/scsi/hosts.c
@@ -180,14 +180,20 @@
 EXPORT_SYMBOL(scsi_remove_host);
 
 /**
- * scsi_add_host - add a scsi host
+ * scsi_add_host_with_dma - add a scsi host with dma device
  * @shost:	scsi host pointer to add
  * @dev:	a struct device of type scsi class
+ * @dma_dev:	dma device for the host
+ *
+ * Note: You rarely need to worry about this unless you're in a
+ * virtualised host environments, so use the simpler scsi_add_host()
+ * function instead.
  *
  * Return value: 
  * 	0 on success / != 0 for error
  **/
-int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
+int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
+			   struct device *dma_dev)
 {
 	struct scsi_host_template *sht = shost->hostt;
 	int error = -EINVAL;
@@ -207,6 +213,7 @@
 
 	if (!shost->shost_gendev.parent)
 		shost->shost_gendev.parent = dev ? dev : &platform_bus;
+	shost->dma_dev = dma_dev;
 
 	error = device_add(&shost->shost_gendev);
 	if (error)
@@ -262,7 +269,7 @@
  fail:
 	return error;
 }
-EXPORT_SYMBOL(scsi_add_host);
+EXPORT_SYMBOL(scsi_add_host_with_dma);
 
 static void scsi_host_dev_release(struct device *dev)
 {
--- linux-ec2-2.6.32.orig/drivers/scsi/Makefile
+++ linux-ec2-2.6.32/drivers/scsi/Makefile
@@ -133,6 +133,7 @@
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
+obj-$(CONFIG_VMWARE_PVSCSI)	+= vmw_pvscsi.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
--- linux-ec2-2.6.32.orig/drivers/scsi/ipr.c
+++ linux-ec2-2.6.32/drivers/scsi/ipr.c
@@ -6516,6 +6516,7 @@
 	int rc;
 
 	ENTER;
+	ioa_cfg->pdev->state_saved = true;
 	rc = pci_restore_state(ioa_cfg->pdev);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
--- linux-ec2-2.6.32.orig/drivers/scsi/st.h
+++ linux-ec2-2.6.32/drivers/scsi/st.h
@@ -46,6 +46,7 @@
 	struct st_request *last_SRpnt;
 	struct st_cmdstatus cmdstat;
 	struct page **reserved_pages;
+	int reserved_page_order;
 	struct page **mapped_pages;
 	struct rq_map_data map_data;
 	unsigned char *b_data;
--- linux-ec2-2.6.32.orig/drivers/scsi/ses.c
+++ linux-ec2-2.6.32/drivers/scsi/ses.c
@@ -389,9 +389,9 @@
 		len = (desc_ptr[2] << 8) + desc_ptr[3];
 		/* skip past overall descriptor */
 		desc_ptr += len + 4;
-		if (ses_dev->page10)
-			addl_desc_ptr = ses_dev->page10 + 8;
 	}
+	if (ses_dev->page10)
+		addl_desc_ptr = ses_dev->page10 + 8;
 	type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
 	components = 0;
 	for (i = 0; i < types; i++, type_ptr += 4) {
@@ -591,8 +591,6 @@
 		ses_dev->page10_len = len;
 		buf = NULL;
 	}
-	kfree(hdr_buf);
-
 	scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL);
 	if (!scomp)
 		goto err_free;
@@ -604,6 +602,8 @@
 		goto err_free;
 	}
 
+	kfree(hdr_buf);
+
 	edev->scratch = ses_dev;
 	for (i = 0; i < components; i++)
 		edev->component[i].scratch = scomp + i;
--- linux-ec2-2.6.32.orig/drivers/scsi/libiscsi.c
+++ linux-ec2-2.6.32/drivers/scsi/libiscsi.c
@@ -384,12 +384,12 @@
 
 	WARN_ON(hdrlength >= 256);
 	hdr->hlength = hdrlength & 0xFF;
+	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
 
 	if (session->tt->init_task && session->tt->init_task(task))
 		return -EIO;
 
 	task->state = ISCSI_TASK_RUNNING;
-	hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
 	session->cmdsn++;
 
 	conn->scsicmd_pdus_cnt++;
@@ -2823,14 +2823,15 @@
 		session->state = ISCSI_STATE_TERMINATE;
 	else if (conn->stop_stage != STOP_CONN_RECOVER)
 		session->state = ISCSI_STATE_IN_RECOVERY;
+
+	old_stop_stage = conn->stop_stage;
+	conn->stop_stage = flag;
 	spin_unlock_bh(&session->lock);
 
 	del_timer_sync(&conn->transport_timer);
 	iscsi_suspend_tx(conn);
 
 	spin_lock_bh(&session->lock);
-	old_stop_stage = conn->stop_stage;
-	conn->stop_stage = flag;
 	conn->c_stage = ISCSI_CONN_STOPPED;
 	spin_unlock_bh(&session->lock);
 
--- linux-ec2-2.6.32.orig/drivers/scsi/vmw_pvscsi.h
+++ linux-ec2-2.6.32/drivers/scsi/vmw_pvscsi.h
@@ -0,0 +1,397 @@
+/*
+ * VMware PVSCSI header file
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Maintained by: Alok N Kataria <akataria@vmware.com>
+ *
+ */
+
+#ifndef _VMW_PVSCSI_H_
+#define _VMW_PVSCSI_H_
+
+#include <linux/types.h>
+
+#define PVSCSI_DRIVER_VERSION_STRING   "1.0.1.0-k"
+
+#define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128
+
+#define MASK(n)        ((1 << (n)) - 1)        /* make an n-bit mask */
+
+#define PCI_VENDOR_ID_VMWARE		0x15AD
+#define PCI_DEVICE_ID_VMWARE_PVSCSI	0x07C0
+
+/*
+ * host adapter status/error codes
+ */
+enum HostBusAdapterStatus {
+   BTSTAT_SUCCESS       = 0x00,  /* CCB complete normally with no errors */
+   BTSTAT_LINKED_COMMAND_COMPLETED           = 0x0a,
+   BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b,
+   BTSTAT_DATA_UNDERRUN = 0x0c,
+   BTSTAT_SELTIMEO      = 0x11,  /* SCSI selection timeout */
+   BTSTAT_DATARUN       = 0x12,  /* data overrun/underrun */
+   BTSTAT_BUSFREE       = 0x13,  /* unexpected bus free */
+   BTSTAT_INVPHASE      = 0x14,  /* invalid bus phase or sequence requested by target */
+   BTSTAT_LUNMISMATCH   = 0x17,  /* linked CCB has different LUN from first CCB */
+   BTSTAT_SENSFAILED    = 0x1b,  /* auto request sense failed */
+   BTSTAT_TAGREJECT     = 0x1c,  /* SCSI II tagged queueing message rejected by target */
+   BTSTAT_BADMSG        = 0x1d,  /* unsupported message received by the host adapter */
+   BTSTAT_HAHARDWARE    = 0x20,  /* host adapter hardware failed */
+   BTSTAT_NORESPONSE    = 0x21,  /* target did not respond to SCSI ATN, sent a SCSI RST */
+   BTSTAT_SENTRST       = 0x22,  /* host adapter asserted a SCSI RST */
+   BTSTAT_RECVRST       = 0x23,  /* other SCSI devices asserted a SCSI RST */
+   BTSTAT_DISCONNECT    = 0x24,  /* target device reconnected improperly (w/o tag) */
+   BTSTAT_BUSRESET      = 0x25,  /* host adapter issued BUS device reset */
+   BTSTAT_ABORTQUEUE    = 0x26,  /* abort queue generated */
+   BTSTAT_HASOFTWARE    = 0x27,  /* host adapter software error */
+   BTSTAT_HATIMEOUT     = 0x30,  /* host adapter hardware timeout error */
+   BTSTAT_SCSIPARITY    = 0x34,  /* SCSI parity error detected */
+};
+
+/*
+ * Register offsets.
+ *
+ * These registers are accessible both via i/o space and mm i/o.
+ */
+
+enum PVSCSIRegOffset {
+	PVSCSI_REG_OFFSET_COMMAND        =    0x0,
+	PVSCSI_REG_OFFSET_COMMAND_DATA   =    0x4,
+	PVSCSI_REG_OFFSET_COMMAND_STATUS =    0x8,
+	PVSCSI_REG_OFFSET_LAST_STS_0     =  0x100,
+	PVSCSI_REG_OFFSET_LAST_STS_1     =  0x104,
+	PVSCSI_REG_OFFSET_LAST_STS_2     =  0x108,
+	PVSCSI_REG_OFFSET_LAST_STS_3     =  0x10c,
+	PVSCSI_REG_OFFSET_INTR_STATUS    = 0x100c,
+	PVSCSI_REG_OFFSET_INTR_MASK      = 0x2010,
+	PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014,
+	PVSCSI_REG_OFFSET_DEBUG          = 0x3018,
+	PVSCSI_REG_OFFSET_KICK_RW_IO     = 0x4018,
+};
+
+/*
+ * Virtual h/w commands.
+ */
+
+enum PVSCSICommands {
+	PVSCSI_CMD_FIRST             = 0, /* has to be first */
+
+	PVSCSI_CMD_ADAPTER_RESET     = 1,
+	PVSCSI_CMD_ISSUE_SCSI        = 2,
+	PVSCSI_CMD_SETUP_RINGS       = 3,
+	PVSCSI_CMD_RESET_BUS         = 4,
+	PVSCSI_CMD_RESET_DEVICE      = 5,
+	PVSCSI_CMD_ABORT_CMD         = 6,
+	PVSCSI_CMD_CONFIG            = 7,
+	PVSCSI_CMD_SETUP_MSG_RING    = 8,
+	PVSCSI_CMD_DEVICE_UNPLUG     = 9,
+
+	PVSCSI_CMD_LAST              = 10  /* has to be last */
+};
+
+/*
+ * Command descriptor for PVSCSI_CMD_RESET_DEVICE --
+ */
+
+struct PVSCSICmdDescResetDevice {
+	u32	target;
+	u8	lun[8];
+} __packed;
+
+/*
+ * Command descriptor for PVSCSI_CMD_ABORT_CMD --
+ *
+ * - currently does not support specifying the LUN.
+ * - _pad should be 0.
+ */
+
+struct PVSCSICmdDescAbortCmd {
+	u64	context;
+	u32	target;
+	u32	_pad;
+} __packed;
+
+/*
+ * Command descriptor for PVSCSI_CMD_SETUP_RINGS --
+ *
+ * Notes:
+ * - reqRingNumPages and cmpRingNumPages need to be power of two.
+ * - reqRingNumPages and cmpRingNumPages need to be different from 0,
+ * - reqRingNumPages and cmpRingNumPages need to be inferior to
+ *   PVSCSI_SETUP_RINGS_MAX_NUM_PAGES.
+ */
+
+#define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES        32
+struct PVSCSICmdDescSetupRings {
+	u32	reqRingNumPages;
+	u32	cmpRingNumPages;
+	u64	ringsStatePPN;
+	u64	reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
+	u64	cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
+} __packed;
+
+/*
+ * Command descriptor for PVSCSI_CMD_SETUP_MSG_RING --
+ *
+ * Notes:
+ * - this command was not supported in the initial revision of the h/w
+ *   interface. Before using it, you need to check that it is supported by
+ *   writing PVSCSI_CMD_SETUP_MSG_RING to the 'command' register, then
+ *   immediately after read the 'command status' register:
+ *       * a value of -1 means that the cmd is NOT supported,
+ *       * a value != -1 means that the cmd IS supported.
+ *   If it's supported the 'command status' register should return:
+ *      sizeof(PVSCSICmdDescSetupMsgRing) / sizeof(u32).
+ * - this command should be issued _after_ the usual SETUP_RINGS so that the
+ *   RingsState page is already setup. If not, the command is a nop.
+ * - numPages needs to be a power of two,
+ * - numPages needs to be different from 0,
+ * - _pad should be zero.
+ */
+
+#define PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES  16
+
+struct PVSCSICmdDescSetupMsgRing {
+	u32	numPages;
+	u32	_pad;
+	u64	ringPPNs[PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES];
+} __packed;
+
+enum PVSCSIMsgType {
+	PVSCSI_MSG_DEV_ADDED          = 0,
+	PVSCSI_MSG_DEV_REMOVED        = 1,
+	PVSCSI_MSG_LAST               = 2,
+};
+
+/*
+ * Msg descriptor.
+ *
+ * sizeof(struct PVSCSIRingMsgDesc) == 128.
+ *
+ * - type is of type enum PVSCSIMsgType.
+ * - the content of args depend on the type of event being delivered.
+ */
+
+struct PVSCSIRingMsgDesc {
+	u32	type;
+	u32	args[31];
+} __packed;
+
+struct PVSCSIMsgDescDevStatusChanged {
+	u32	type;  /* PVSCSI_MSG_DEV _ADDED / _REMOVED */
+	u32	bus;
+	u32	target;
+	u8	lun[8];
+	u32	pad[27];
+} __packed;
+
+/*
+ * Rings state.
+ *
+ * - the fields:
+ *    . msgProdIdx,
+ *    . msgConsIdx,
+ *    . msgNumEntriesLog2,
+ *   .. are only used once the SETUP_MSG_RING cmd has been issued.
+ * - '_pad' helps to ensure that the msg related fields are on their own
+ *   cache-line.
+ */
+
+struct PVSCSIRingsState {
+	u32	reqProdIdx;
+	u32	reqConsIdx;
+	u32	reqNumEntriesLog2;
+
+	u32	cmpProdIdx;
+	u32	cmpConsIdx;
+	u32	cmpNumEntriesLog2;
+
+	u8	_pad[104];
+
+	u32	msgProdIdx;
+	u32	msgConsIdx;
+	u32	msgNumEntriesLog2;
+} __packed;
+
+/*
+ * Request descriptor.
+ *
+ * sizeof(RingReqDesc) = 128
+ *
+ * - context: is a unique identifier of a command. It could normally be any
+ *   64bit value, however we currently store it in the serialNumber variable
+ *   of struct SCSI_Command, so we have the following restrictions due to the
+ *   way this field is handled in the vmkernel storage stack:
+ *    * this value can't be 0,
+ *    * the upper 32bit need to be 0 since serialNumber is as a u32.
+ *   Currently tracked as PR 292060.
+ * - dataLen: contains the total number of bytes that need to be transferred.
+ * - dataAddr:
+ *   * if PVSCSI_FLAG_CMD_WITH_SG_LIST is set: dataAddr is the PA of the first
+ *     s/g table segment, each s/g segment is entirely contained on a single
+ *     page of physical memory,
+ *   * if PVSCSI_FLAG_CMD_WITH_SG_LIST is NOT set, then dataAddr is the PA of
+ *     the buffer used for the DMA transfer,
+ * - flags:
+ *   * PVSCSI_FLAG_CMD_WITH_SG_LIST: see dataAddr above,
+ *   * PVSCSI_FLAG_CMD_DIR_NONE: no DMA involved,
+ *   * PVSCSI_FLAG_CMD_DIR_TOHOST: transfer from device to main memory,
+ *   * PVSCSI_FLAG_CMD_DIR_TODEVICE: transfer from main memory to device,
+ *   * PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB: reserved to handle CDBs larger than
+ *     16bytes. To be specified.
+ * - vcpuHint: vcpuId of the processor that will be most likely waiting for the
+ *   completion of the i/o. For guest OSes that use lowest priority message
+ *   delivery mode (such as windows), we use this "hint" to deliver the
+ *   completion action to the proper vcpu. For now, we can use the vcpuId of
+ *   the processor that initiated the i/o as a likely candidate for the vcpu
+ *   that will be waiting for the completion..
+ * - bus should be 0: we currently only support bus 0 for now.
+ * - unused should be zero'd.
+ */
+
+#define PVSCSI_FLAG_CMD_WITH_SG_LIST        (1 << 0)
+#define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB     (1 << 1)
+#define PVSCSI_FLAG_CMD_DIR_NONE            (1 << 2)
+#define PVSCSI_FLAG_CMD_DIR_TOHOST          (1 << 3)
+#define PVSCSI_FLAG_CMD_DIR_TODEVICE        (1 << 4)
+
+struct PVSCSIRingReqDesc {
+	u64	context;
+	u64	dataAddr;
+	u64	dataLen;
+	u64	senseAddr;
+	u32	senseLen;
+	u32	flags;
+	u8	cdb[16];
+	u8	cdbLen;
+	u8	lun[8];
+	u8	tag;
+	u8	bus;
+	u8	target;
+	u8	vcpuHint;
+	u8	unused[59];
+} __packed;
+
+/*
+ * Scatter-gather list management.
+ *
+ * As described above, when PVSCSI_FLAG_CMD_WITH_SG_LIST is set in the
+ * RingReqDesc.flags, then RingReqDesc.dataAddr is the PA of the first s/g
+ * table segment.
+ *
+ * - each segment of the s/g table contain a succession of struct
+ *   PVSCSISGElement.
+ * - each segment is entirely contained on a single physical page of memory.
+ * - a "chain" s/g element has the flag PVSCSI_SGE_FLAG_CHAIN_ELEMENT set in
+ *   PVSCSISGElement.flags and in this case:
+ *     * addr is the PA of the next s/g segment,
+ *     * length is undefined, assumed to be 0.
+ */
+
+struct PVSCSISGElement {
+	u64	addr;
+	u32	length;
+	u32	flags;
+} __packed;
+
+/*
+ * Completion descriptor.
+ *
+ * sizeof(RingCmpDesc) = 32
+ *
+ * - context: identifier of the command. The same thing that was specified
+ *   under "context" as part of struct RingReqDesc at initiation time,
+ * - dataLen: number of bytes transferred for the actual i/o operation,
+ * - senseLen: number of bytes written into the sense buffer,
+ * - hostStatus: adapter status,
+ * - scsiStatus: device status,
+ * - _pad should be zero.
+ */
+
+struct PVSCSIRingCmpDesc {
+	u64	context;
+	u64	dataLen;
+	u32	senseLen;
+	u16	hostStatus;
+	u16	scsiStatus;
+	u32	_pad[2];
+} __packed;
+
+/*
+ * Interrupt status / IRQ bits.
+ */
+
+#define PVSCSI_INTR_CMPL_0                 (1 << 0)
+#define PVSCSI_INTR_CMPL_1                 (1 << 1)
+#define PVSCSI_INTR_CMPL_MASK              MASK(2)
+
+#define PVSCSI_INTR_MSG_0                  (1 << 2)
+#define PVSCSI_INTR_MSG_1                  (1 << 3)
+#define PVSCSI_INTR_MSG_MASK               (MASK(2) << 2)
+
+#define PVSCSI_INTR_ALL_SUPPORTED          MASK(4)
+
+/*
+ * Number of MSI-X vectors supported.
+ */
+#define PVSCSI_MAX_INTRS        24
+
+/*
+ * Enumeration of supported MSI-X vectors
+ */
+#define PVSCSI_VECTOR_COMPLETION   0
+
+/*
+ * Misc constants for the rings.
+ */
+
+#define PVSCSI_MAX_NUM_PAGES_REQ_RING   PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
+#define PVSCSI_MAX_NUM_PAGES_CMP_RING   PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
+#define PVSCSI_MAX_NUM_PAGES_MSG_RING   PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES
+
+#define PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE \
+				(PAGE_SIZE / sizeof(struct PVSCSIRingReqDesc))
+
+#define PVSCSI_MAX_REQ_QUEUE_DEPTH \
+	(PVSCSI_MAX_NUM_PAGES_REQ_RING * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE)
+
+#define PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES     1
+#define PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES 1
+#define PVSCSI_MEM_SPACE_MISC_NUM_PAGES        2
+#define PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES     2
+#define PVSCSI_MEM_SPACE_MSIX_NUM_PAGES        2
+
+enum PVSCSIMemSpace {
+	PVSCSI_MEM_SPACE_COMMAND_PAGE		= 0,
+	PVSCSI_MEM_SPACE_INTR_STATUS_PAGE	= 1,
+	PVSCSI_MEM_SPACE_MISC_PAGE		= 2,
+	PVSCSI_MEM_SPACE_KICK_IO_PAGE		= 4,
+	PVSCSI_MEM_SPACE_MSIX_TABLE_PAGE	= 6,
+	PVSCSI_MEM_SPACE_MSIX_PBA_PAGE		= 7,
+};
+
+#define PVSCSI_MEM_SPACE_NUM_PAGES \
+	(PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES +       \
+	 PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES +   \
+	 PVSCSI_MEM_SPACE_MISC_NUM_PAGES +          \
+	 PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES +       \
+	 PVSCSI_MEM_SPACE_MSIX_NUM_PAGES)
+
+#define PVSCSI_MEM_SPACE_SIZE        (PVSCSI_MEM_SPACE_NUM_PAGES * PAGE_SIZE)
+
+#endif /* _VMW_PVSCSI_H_ */
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_transport_iscsi.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_transport_iscsi.c
@@ -627,8 +627,10 @@
 	spin_unlock_irqrestore(&session->lock, flags);
 	scsi_target_block(&session->dev);
 	ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
-	queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
-			   session->recovery_tmo * HZ);
+	if (session->recovery_tmo >= 0)
+		queue_delayed_work(iscsi_eh_timer_workq,
+				   &session->recovery_work,
+				   session->recovery_tmo * HZ);
 }
 
 void iscsi_block_session(struct iscsi_cls_session *session)
@@ -1348,8 +1350,7 @@
 	switch (ev->u.set_param.param) {
 	case ISCSI_PARAM_SESS_RECOVERY_TMO:
 		sscanf(data, "%d", &value);
-		if (value != 0)
-			session->recovery_tmo = value;
+		session->recovery_tmo = value;
 		break;
 	default:
 		err = transport->set_param(conn, ev->u.set_param.param,
--- linux-ec2-2.6.32.orig/drivers/scsi/Kconfig
+++ linux-ec2-2.6.32/drivers/scsi/Kconfig
@@ -621,6 +621,14 @@
 	  substantial, so users of MultiMaster Host Adapters may not
 	  wish to include it.
 
+config VMWARE_PVSCSI
+	tristate "VMware PVSCSI driver support"
+	depends on PCI && SCSI && X86
+	help
+	  This driver supports VMware's para virtualized SCSI HBA.
+	  To compile this driver as a module, choose M here: the
+	  module will be called vmw_pvscsi.
+
 config LIBFC
 	tristate "LibFC module"
 	select SCSI_FC_ATTRS
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_error.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_error.c
@@ -301,7 +301,20 @@
 		if (scmd->device->allow_restart &&
 		    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
 			return FAILED;
-		return SUCCESS;
+
+		if (blk_barrier_rq(scmd->request))
+			/*
+			 * barrier requests should always retry on UA
+			 * otherwise block will get a spurious error
+			 */
+			return NEEDS_RETRY;
+		else
+			/*
+			 * for normal (non barrier) commands, pass the
+			 * UA upwards for a determination in the
+			 * completion functions
+			 */
+			return SUCCESS;
 
 		/* these three are not supported */
 	case COPY_ABORTED:
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_devinfo.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_devinfo.c
@@ -168,11 +168,10 @@
 	{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36},
 	{"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36},
 	{"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN | BLIST_INQUIRY_36},
-	{"HITACHI", "DF400", "*", BLIST_SPARSELUN},
-	{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
-	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
-	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
-	{"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "DF400", "*", BLIST_REPORTLUN2},
+	{"HITACHI", "DF500", "*", BLIST_REPORTLUN2},
+	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2},
+	{"HITACHI", "OPEN-", "*", BLIST_REPORTLUN2},
 	{"HITACHI", "OP-C-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HITACHI", "3380-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HITACHI", "3390-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
--- linux-ec2-2.6.32.orig/drivers/scsi/st.c
+++ linux-ec2-2.6.32/drivers/scsi/st.c
@@ -552,13 +552,15 @@
 	SRpnt->waiting = waiting;
 
 	if (STp->buffer->do_dio) {
+		mdata->page_order = 0;
 		mdata->nr_entries = STp->buffer->sg_segs;
 		mdata->pages = STp->buffer->mapped_pages;
 	} else {
+		mdata->page_order = STp->buffer->reserved_page_order;
 		mdata->nr_entries =
 			DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order);
-		STp->buffer->map_data.pages = STp->buffer->reserved_pages;
-		STp->buffer->map_data.offset = 0;
+		mdata->pages = STp->buffer->reserved_pages;
+		mdata->offset = 0;
 	}
 
 	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
@@ -3718,7 +3720,7 @@
 		priority |= __GFP_ZERO;
 
 	if (STbuffer->frp_segs) {
-		order = STbuffer->map_data.page_order;
+		order = STbuffer->reserved_page_order;
 		b_size = PAGE_SIZE << order;
 	} else {
 		for (b_size = PAGE_SIZE, order = 0;
@@ -3751,7 +3753,7 @@
 		segs++;
 	}
 	STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
-	STbuffer->map_data.page_order = order;
+	STbuffer->reserved_page_order = order;
 
 	return 1;
 }
@@ -3764,7 +3766,7 @@
 
 	for (i=0; i < st_bp->frp_segs; i++)
 		memset(page_address(st_bp->reserved_pages[i]), 0,
-		       PAGE_SIZE << st_bp->map_data.page_order);
+		       PAGE_SIZE << st_bp->reserved_page_order);
 	st_bp->cleared = 1;
 }
 
@@ -3772,7 +3774,7 @@
 /* Release the extra buffer */
 static void normalize_buffer(struct st_buffer * STbuffer)
 {
-	int i, order = STbuffer->map_data.page_order;
+	int i, order = STbuffer->reserved_page_order;
 
 	for (i = 0; i < STbuffer->frp_segs; i++) {
 		__free_pages(STbuffer->reserved_pages[i], order);
@@ -3780,7 +3782,7 @@
 	}
 	STbuffer->frp_segs = 0;
 	STbuffer->sg_segs = 0;
-	STbuffer->map_data.page_order = 0;
+	STbuffer->reserved_page_order = 0;
 	STbuffer->map_data.offset = 0;
 }
 
@@ -3790,7 +3792,7 @@
 static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
 {
 	int i, cnt, res, offset;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	for (i = 0, offset = st_bp->buffer_bytes;
 	     i < st_bp->frp_segs && offset >= length; i++)
@@ -3822,7 +3824,7 @@
 static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
 {
 	int i, cnt, res, offset;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	for (i = 0, offset = st_bp->read_pointer;
 	     i < st_bp->frp_segs && offset >= length; i++)
@@ -3855,7 +3857,7 @@
 {
 	int src_seg, dst_seg, src_offset = 0, dst_offset;
 	int count, total;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	if (offset == 0)
 		return;
@@ -4577,7 +4579,6 @@
         }
 
 	mdata->offset = uaddr & ~PAGE_MASK;
-	mdata->page_order = 0;
 	STbp->mapped_pages = pages;
 
 	return nr_pages;
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_transport_fc.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_transport_fc.c
@@ -648,11 +648,22 @@
 		return error;
 	error = transport_class_register(&fc_vport_class);
 	if (error)
-		return error;
+		goto unreg_host_class;
 	error = transport_class_register(&fc_rport_class);
 	if (error)
-		return error;
-	return transport_class_register(&fc_transport_class);
+		goto unreg_vport_class;
+	error = transport_class_register(&fc_transport_class);
+	if (error)
+		goto unreg_rport_class;
+	return 0;
+
+unreg_rport_class:
+	transport_class_unregister(&fc_rport_class);
+unreg_vport_class:
+	transport_class_unregister(&fc_vport_class);
+unreg_host_class:
+	transport_class_unregister(&fc_host_class);
+	return error;
 }
 
 static void __exit fc_transport_exit(void)
@@ -1204,6 +1215,15 @@
 {
 	struct fc_vport *vport = transport_class_to_vport(dev);
 	struct Scsi_Host *shost = vport_to_shost(vport);
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+	if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {
+		spin_unlock_irqrestore(shost->host_lock, flags);
+		return -EBUSY;
+	}
+	vport->flags |= FC_VPORT_DELETING;
+	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	fc_queue_work(shost, &vport->vport_delete_work);
 	return count;
@@ -1793,6 +1813,9 @@
 	list_for_each_entry(vport, &fc_host->vports, peers) {
 		if ((vport->channel == 0) &&
 		    (vport->port_name == wwpn) && (vport->node_name == wwnn)) {
+			if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING))
+				break;
+			vport->flags |= FC_VPORT_DELETING;
 			match = 1;
 			break;
 		}
@@ -2384,6 +2407,7 @@
 	struct Scsi_Host *shost = rport_to_shost(rport);
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	unsigned long flags;
+	int do_callback = 0;
 
 	/*
 	 * if a scan is pending, flush the SCSI Host work_q so that
@@ -2422,8 +2446,15 @@
 	 * Avoid this call if we already called it when we preserved the
 	 * rport for the binding.
 	 */
+	spin_lock_irqsave(shost->host_lock, flags);
 	if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) &&
-	    (i->f->dev_loss_tmo_callbk))
+	    (i->f->dev_loss_tmo_callbk)) {
+		rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;
+		do_callback = 1;
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+
+	if (do_callback)
 		i->f->dev_loss_tmo_callbk(rport);
 
 	fc_bsg_remove(rport->rqst_q);
@@ -2970,6 +3001,7 @@
 	struct fc_internal *i = to_fc_internal(shost->transportt);
 	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
 	unsigned long flags;
+	int do_callback = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
 
@@ -3035,7 +3067,6 @@
 	rport->roles = FC_PORT_ROLE_UNKNOWN;
 	rport->port_state = FC_PORTSTATE_NOTPRESENT;
 	rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
-	rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;
 
 	/*
 	 * Pre-emptively kill I/O rather than waiting for the work queue
@@ -3045,32 +3076,40 @@
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	fc_terminate_rport_io(rport);
 
-	BUG_ON(rport->port_state != FC_PORTSTATE_NOTPRESENT);
+	spin_lock_irqsave(shost->host_lock, flags);
 
-	/* remove the identifiers that aren't used in the consisting binding */
-	switch (fc_host->tgtid_bind_type) {
-	case FC_TGTID_BIND_BY_WWPN:
-		rport->node_name = -1;
-		rport->port_id = -1;
-		break;
-	case FC_TGTID_BIND_BY_WWNN:
-		rport->port_name = -1;
-		rport->port_id = -1;
-		break;
-	case FC_TGTID_BIND_BY_ID:
-		rport->node_name = -1;
-		rport->port_name = -1;
-		break;
-	case FC_TGTID_BIND_NONE:	/* to keep compiler happy */
-		break;
+	if (rport->port_state == FC_PORTSTATE_NOTPRESENT) {	/* still missing */
+
+		/* remove the identifiers that aren't used in the consisting binding */
+		switch (fc_host->tgtid_bind_type) {
+		case FC_TGTID_BIND_BY_WWPN:
+			rport->node_name = -1;
+			rport->port_id = -1;
+			break;
+		case FC_TGTID_BIND_BY_WWNN:
+			rport->port_name = -1;
+			rport->port_id = -1;
+			break;
+		case FC_TGTID_BIND_BY_ID:
+			rport->node_name = -1;
+			rport->port_name = -1;
+			break;
+		case FC_TGTID_BIND_NONE:	/* to keep compiler happy */
+			break;
+		}
+
+		/*
+		 * As this only occurs if the remote port (scsi target)
+		 * went away and didn't come back - we'll remove
+		 * all attached scsi devices.
+		 */
+		rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;
+		fc_queue_work(shost, &rport->stgt_delete_work);
+
+		do_callback = 1;
 	}
 
-	/*
-	 * As this only occurs if the remote port (scsi target)
-	 * went away and didn't come back - we'll remove
-	 * all attached scsi devices.
-	 */
-	fc_queue_work(shost, &rport->stgt_delete_work);
+	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	/*
 	 * Notify the driver that the rport is now dead. The LLDD will
@@ -3078,7 +3117,7 @@
 	 *
 	 * Note: we set the CALLBK_DONE flag above to correspond
 	 */
-	if (i->f->dev_loss_tmo_callbk)
+	if (do_callback && i->f->dev_loss_tmo_callbk)
 		i->f->dev_loss_tmo_callbk(rport);
 }
 
@@ -3301,18 +3340,6 @@
 	unsigned long flags;
 	int stat;
 
-	spin_lock_irqsave(shost->host_lock, flags);
-	if (vport->flags & FC_VPORT_CREATING) {
-		spin_unlock_irqrestore(shost->host_lock, flags);
-		return -EBUSY;
-	}
-	if (vport->flags & (FC_VPORT_DEL)) {
-		spin_unlock_irqrestore(shost->host_lock, flags);
-		return -EALREADY;
-	}
-	vport->flags |= FC_VPORT_DELETING;
-	spin_unlock_irqrestore(shost->host_lock, flags);
-
 	if (i->f->vport_delete)
 		stat = i->f->vport_delete(vport);
 	else
@@ -3769,8 +3796,9 @@
 		return;
 
 	while (!blk_queue_plugged(q)) {
-		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED))
-				break;
+		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) &&
+		    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
+			break;
 
 		req = blk_fetch_request(q);
 		if (!req)
--- linux-ec2-2.6.32.orig/drivers/scsi/vmw_pvscsi.c
+++ linux-ec2-2.6.32/drivers/scsi/vmw_pvscsi.c
@@ -0,0 +1,1407 @@
+/*
+ * Linux driver for VMware's para-virtualized SCSI HBA.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  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.
+ *
+ * Maintained by: Alok N Kataria <akataria@vmware.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/pci.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "vmw_pvscsi.h"
+
+#define PVSCSI_LINUX_DRIVER_DESC "VMware PVSCSI driver"
+
+MODULE_DESCRIPTION(PVSCSI_LINUX_DRIVER_DESC);
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PVSCSI_DRIVER_VERSION_STRING);
+
+#define PVSCSI_DEFAULT_NUM_PAGES_PER_RING	8
+#define PVSCSI_DEFAULT_NUM_PAGES_MSG_RING	1
+#define PVSCSI_DEFAULT_QUEUE_DEPTH		64
+#define SGL_SIZE				PAGE_SIZE
+
+struct pvscsi_sg_list {
+	struct PVSCSISGElement sge[PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT];
+};
+
+struct pvscsi_ctx {
+	/*
+	 * The index of the context in cmd_map serves as the context ID for a
+	 * 1-to-1 mapping completions back to requests.
+	 */
+	struct scsi_cmnd	*cmd;
+	struct pvscsi_sg_list	*sgl;
+	struct list_head	list;
+	dma_addr_t		dataPA;
+	dma_addr_t		sensePA;
+	dma_addr_t		sglPA;
+};
+
+struct pvscsi_adapter {
+	char				*mmioBase;
+	unsigned int			irq;
+	u8				rev;
+	bool				use_msi;
+	bool				use_msix;
+	bool				use_msg;
+
+	spinlock_t			hw_lock;
+
+	struct workqueue_struct		*workqueue;
+	struct work_struct		work;
+
+	struct PVSCSIRingReqDesc	*req_ring;
+	unsigned			req_pages;
+	unsigned			req_depth;
+	dma_addr_t			reqRingPA;
+
+	struct PVSCSIRingCmpDesc	*cmp_ring;
+	unsigned			cmp_pages;
+	dma_addr_t			cmpRingPA;
+
+	struct PVSCSIRingMsgDesc	*msg_ring;
+	unsigned			msg_pages;
+	dma_addr_t			msgRingPA;
+
+	struct PVSCSIRingsState		*rings_state;
+	dma_addr_t			ringStatePA;
+
+	struct pci_dev			*dev;
+	struct Scsi_Host		*host;
+
+	struct list_head		cmd_pool;
+	struct pvscsi_ctx		*cmd_map;
+};
+
+
+/* Command line parameters */
+static int pvscsi_ring_pages     = PVSCSI_DEFAULT_NUM_PAGES_PER_RING;
+static int pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
+static int pvscsi_cmd_per_lun    = PVSCSI_DEFAULT_QUEUE_DEPTH;
+static bool pvscsi_disable_msi;
+static bool pvscsi_disable_msix;
+static bool pvscsi_use_msg       = true;
+
+#define PVSCSI_RW (S_IRUSR | S_IWUSR)
+
+module_param_named(ring_pages, pvscsi_ring_pages, int, PVSCSI_RW);
+MODULE_PARM_DESC(ring_pages, "Number of pages per req/cmp ring - (default="
+		 __stringify(PVSCSI_DEFAULT_NUM_PAGES_PER_RING) ")");
+
+module_param_named(msg_ring_pages, pvscsi_msg_ring_pages, int, PVSCSI_RW);
+MODULE_PARM_DESC(msg_ring_pages, "Number of pages for the msg ring - (default="
+		 __stringify(PVSCSI_DEFAULT_NUM_PAGES_MSG_RING) ")");
+
+module_param_named(cmd_per_lun, pvscsi_cmd_per_lun, int, PVSCSI_RW);
+MODULE_PARM_DESC(cmd_per_lun, "Maximum commands per lun - (default="
+		 __stringify(PVSCSI_MAX_REQ_QUEUE_DEPTH) ")");
+
+module_param_named(disable_msi, pvscsi_disable_msi, bool, PVSCSI_RW);
+MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
+
+module_param_named(disable_msix, pvscsi_disable_msix, bool, PVSCSI_RW);
+MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
+
+module_param_named(use_msg, pvscsi_use_msg, bool, PVSCSI_RW);
+MODULE_PARM_DESC(use_msg, "Use msg ring when available - (default=1)");
+
+static const struct pci_device_id pvscsi_pci_tbl[] = {
+	{ PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_PVSCSI) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, pvscsi_pci_tbl);
+
+static struct device *
+pvscsi_dev(const struct pvscsi_adapter *adapter)
+{
+	return &(adapter->dev->dev);
+}
+
+static struct pvscsi_ctx *
+pvscsi_find_context(const struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
+{
+	struct pvscsi_ctx *ctx, *end;
+
+	end = &adapter->cmd_map[adapter->req_depth];
+	for (ctx = adapter->cmd_map; ctx < end; ctx++)
+		if (ctx->cmd == cmd)
+			return ctx;
+
+	return NULL;
+}
+
+static struct pvscsi_ctx *
+pvscsi_acquire_context(struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
+{
+	struct pvscsi_ctx *ctx;
+
+	if (list_empty(&adapter->cmd_pool))
+		return NULL;
+
+	ctx = list_first_entry(&adapter->cmd_pool, struct pvscsi_ctx, list);
+	ctx->cmd = cmd;
+	list_del(&ctx->list);
+
+	return ctx;
+}
+
+static void pvscsi_release_context(struct pvscsi_adapter *adapter,
+				   struct pvscsi_ctx *ctx)
+{
+	ctx->cmd = NULL;
+	list_add(&ctx->list, &adapter->cmd_pool);
+}
+
+/*
+ * Map a pvscsi_ctx struct to a context ID field value; we map to a simple
+ * non-zero integer. ctx always points to an entry in cmd_map array, hence
+ * the return value is always >=1.
+ */
+static u64 pvscsi_map_context(const struct pvscsi_adapter *adapter,
+			      const struct pvscsi_ctx *ctx)
+{
+	return ctx - adapter->cmd_map + 1;
+}
+
+static struct pvscsi_ctx *
+pvscsi_get_context(const struct pvscsi_adapter *adapter, u64 context)
+{
+	return &adapter->cmd_map[context - 1];
+}
+
+static void pvscsi_reg_write(const struct pvscsi_adapter *adapter,
+			     u32 offset, u32 val)
+{
+	writel(val, adapter->mmioBase + offset);
+}
+
+static u32 pvscsi_reg_read(const struct pvscsi_adapter *adapter, u32 offset)
+{
+	return readl(adapter->mmioBase + offset);
+}
+
+static u32 pvscsi_read_intr_status(const struct pvscsi_adapter *adapter)
+{
+	return pvscsi_reg_read(adapter, PVSCSI_REG_OFFSET_INTR_STATUS);
+}
+
+static void pvscsi_write_intr_status(const struct pvscsi_adapter *adapter,
+				     u32 val)
+{
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_INTR_STATUS, val);
+}
+
+static void pvscsi_unmask_intr(const struct pvscsi_adapter *adapter)
+{
+	u32 intr_bits;
+
+	intr_bits = PVSCSI_INTR_CMPL_MASK;
+	if (adapter->use_msg)
+		intr_bits |= PVSCSI_INTR_MSG_MASK;
+
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_INTR_MASK, intr_bits);
+}
+
+static void pvscsi_mask_intr(const struct pvscsi_adapter *adapter)
+{
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_INTR_MASK, 0);
+}
+
+static void pvscsi_write_cmd_desc(const struct pvscsi_adapter *adapter,
+				  u32 cmd, const void *desc, size_t len)
+{
+	const u32 *ptr = desc;
+	size_t i;
+
+	len /= sizeof(*ptr);
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND, cmd);
+	for (i = 0; i < len; i++)
+		pvscsi_reg_write(adapter,
+				 PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]);
+}
+
+static void pvscsi_abort_cmd(const struct pvscsi_adapter *adapter,
+			     const struct pvscsi_ctx *ctx)
+{
+	struct PVSCSICmdDescAbortCmd cmd = { 0 };
+
+	cmd.target = ctx->cmd->device->id;
+	cmd.context = pvscsi_map_context(adapter, ctx);
+
+	pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_ABORT_CMD, &cmd, sizeof(cmd));
+}
+
+static void pvscsi_kick_rw_io(const struct pvscsi_adapter *adapter)
+{
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
+}
+
+static void pvscsi_process_request_ring(const struct pvscsi_adapter *adapter)
+{
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_KICK_NON_RW_IO, 0);
+}
+
+static int scsi_is_rw(unsigned char op)
+{
+	return op == READ_6  || op == WRITE_6 ||
+	       op == READ_10 || op == WRITE_10 ||
+	       op == READ_12 || op == WRITE_12 ||
+	       op == READ_16 || op == WRITE_16;
+}
+
+static void pvscsi_kick_io(const struct pvscsi_adapter *adapter,
+			   unsigned char op)
+{
+	if (scsi_is_rw(op))
+		pvscsi_kick_rw_io(adapter);
+	else
+		pvscsi_process_request_ring(adapter);
+}
+
+static void ll_adapter_reset(const struct pvscsi_adapter *adapter)
+{
+	dev_dbg(pvscsi_dev(adapter), "Adapter Reset on %p\n", adapter);
+
+	pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
+}
+
+static void ll_bus_reset(const struct pvscsi_adapter *adapter)
+{
+	dev_dbg(pvscsi_dev(adapter), "Reseting bus on %p\n", adapter);
+
+	pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_RESET_BUS, NULL, 0);
+}
+
+static void ll_device_reset(const struct pvscsi_adapter *adapter, u32 target)
+{
+	struct PVSCSICmdDescResetDevice cmd = { 0 };
+
+	dev_dbg(pvscsi_dev(adapter), "Reseting device: target=%u\n", target);
+
+	cmd.target = target;
+
+	pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_RESET_DEVICE,
+			      &cmd, sizeof(cmd));
+}
+
+static void pvscsi_create_sg(struct pvscsi_ctx *ctx,
+			     struct scatterlist *sg, unsigned count)
+{
+	unsigned i;
+	struct PVSCSISGElement *sge;
+
+	BUG_ON(count > PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT);
+
+	sge = &ctx->sgl->sge[0];
+	for (i = 0; i < count; i++, sg++) {
+		sge[i].addr   = sg_dma_address(sg);
+		sge[i].length = sg_dma_len(sg);
+		sge[i].flags  = 0;
+	}
+}
+
+/*
+ * Map all data buffers for a command into PCI space and
+ * setup the scatter/gather list if needed.
+ */
+static void pvscsi_map_buffers(struct pvscsi_adapter *adapter,
+			       struct pvscsi_ctx *ctx, struct scsi_cmnd *cmd,
+			       struct PVSCSIRingReqDesc *e)
+{
+	unsigned count;
+	unsigned bufflen = scsi_bufflen(cmd);
+	struct scatterlist *sg;
+
+	e->dataLen = bufflen;
+	e->dataAddr = 0;
+	if (bufflen == 0)
+		return;
+
+	sg = scsi_sglist(cmd);
+	count = scsi_sg_count(cmd);
+	if (count != 0) {
+		int segs = scsi_dma_map(cmd);
+		if (segs > 1) {
+			pvscsi_create_sg(ctx, sg, segs);
+
+			e->flags |= PVSCSI_FLAG_CMD_WITH_SG_LIST;
+			ctx->sglPA = pci_map_single(adapter->dev, ctx->sgl,
+						    SGL_SIZE, PCI_DMA_TODEVICE);
+			e->dataAddr = ctx->sglPA;
+		} else
+			e->dataAddr = sg_dma_address(sg);
+	} else {
+		/*
+		 * In case there is no S/G list, scsi_sglist points
+		 * directly to the buffer.
+		 */
+		ctx->dataPA = pci_map_single(adapter->dev, sg, bufflen,
+					     cmd->sc_data_direction);
+		e->dataAddr = ctx->dataPA;
+	}
+}
+
+static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
+				 struct pvscsi_ctx *ctx)
+{
+	struct scsi_cmnd *cmd;
+	unsigned bufflen;
+
+	cmd = ctx->cmd;
+	bufflen = scsi_bufflen(cmd);
+
+	if (bufflen != 0) {
+		unsigned count = scsi_sg_count(cmd);
+
+		if (count != 0) {
+			scsi_dma_unmap(cmd);
+			if (ctx->sglPA) {
+				pci_unmap_single(adapter->dev, ctx->sglPA,
+						 SGL_SIZE, PCI_DMA_TODEVICE);
+				ctx->sglPA = 0;
+			}
+		} else
+			pci_unmap_single(adapter->dev, ctx->dataPA, bufflen,
+					 cmd->sc_data_direction);
+	}
+	if (cmd->sense_buffer)
+		pci_unmap_single(adapter->dev, ctx->sensePA,
+				 SCSI_SENSE_BUFFERSIZE, PCI_DMA_FROMDEVICE);
+}
+
+static int __devinit pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
+{
+	adapter->rings_state = pci_alloc_consistent(adapter->dev, PAGE_SIZE,
+						    &adapter->ringStatePA);
+	if (!adapter->rings_state)
+		return -ENOMEM;
+
+	adapter->req_pages = min(PVSCSI_MAX_NUM_PAGES_REQ_RING,
+				 pvscsi_ring_pages);
+	adapter->req_depth = adapter->req_pages
+					* PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
+	adapter->req_ring = pci_alloc_consistent(adapter->dev,
+						 adapter->req_pages * PAGE_SIZE,
+						 &adapter->reqRingPA);
+	if (!adapter->req_ring)
+		return -ENOMEM;
+
+	adapter->cmp_pages = min(PVSCSI_MAX_NUM_PAGES_CMP_RING,
+				 pvscsi_ring_pages);
+	adapter->cmp_ring = pci_alloc_consistent(adapter->dev,
+						 adapter->cmp_pages * PAGE_SIZE,
+						 &adapter->cmpRingPA);
+	if (!adapter->cmp_ring)
+		return -ENOMEM;
+
+	BUG_ON(!IS_ALIGNED(adapter->ringStatePA, PAGE_SIZE));
+	BUG_ON(!IS_ALIGNED(adapter->reqRingPA, PAGE_SIZE));
+	BUG_ON(!IS_ALIGNED(adapter->cmpRingPA, PAGE_SIZE));
+
+	if (!adapter->use_msg)
+		return 0;
+
+	adapter->msg_pages = min(PVSCSI_MAX_NUM_PAGES_MSG_RING,
+				 pvscsi_msg_ring_pages);
+	adapter->msg_ring = pci_alloc_consistent(adapter->dev,
+						 adapter->msg_pages * PAGE_SIZE,
+						 &adapter->msgRingPA);
+	if (!adapter->msg_ring)
+		return -ENOMEM;
+	BUG_ON(!IS_ALIGNED(adapter->msgRingPA, PAGE_SIZE));
+
+	return 0;
+}
+
+static void pvscsi_setup_all_rings(const struct pvscsi_adapter *adapter)
+{
+	struct PVSCSICmdDescSetupRings cmd = { 0 };
+	dma_addr_t base;
+	unsigned i;
+
+	cmd.ringsStatePPN   = adapter->ringStatePA >> PAGE_SHIFT;
+	cmd.reqRingNumPages = adapter->req_pages;
+	cmd.cmpRingNumPages = adapter->cmp_pages;
+
+	base = adapter->reqRingPA;
+	for (i = 0; i < adapter->req_pages; i++) {
+		cmd.reqRingPPNs[i] = base >> PAGE_SHIFT;
+		base += PAGE_SIZE;
+	}
+
+	base = adapter->cmpRingPA;
+	for (i = 0; i < adapter->cmp_pages; i++) {
+		cmd.cmpRingPPNs[i] = base >> PAGE_SHIFT;
+		base += PAGE_SIZE;
+	}
+
+	memset(adapter->rings_state, 0, PAGE_SIZE);
+	memset(adapter->req_ring, 0, adapter->req_pages * PAGE_SIZE);
+	memset(adapter->cmp_ring, 0, adapter->cmp_pages * PAGE_SIZE);
+
+	pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_SETUP_RINGS,
+			      &cmd, sizeof(cmd));
+
+	if (adapter->use_msg) {
+		struct PVSCSICmdDescSetupMsgRing cmd_msg = { 0 };
+
+		cmd_msg.numPages = adapter->msg_pages;
+
+		base = adapter->msgRingPA;
+		for (i = 0; i < adapter->msg_pages; i++) {
+			cmd_msg.ringPPNs[i] = base >> PAGE_SHIFT;
+			base += PAGE_SIZE;
+		}
+		memset(adapter->msg_ring, 0, adapter->msg_pages * PAGE_SIZE);
+
+		pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_SETUP_MSG_RING,
+				      &cmd_msg, sizeof(cmd_msg));
+	}
+}
+
+/*
+ * Pull a completion descriptor off and pass the completion back
+ * to the SCSI mid layer.
+ */
+static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
+				    const struct PVSCSIRingCmpDesc *e)
+{
+	struct pvscsi_ctx *ctx;
+	struct scsi_cmnd *cmd;
+	u32 btstat = e->hostStatus;
+	u32 sdstat = e->scsiStatus;
+
+	ctx = pvscsi_get_context(adapter, e->context);
+	cmd = ctx->cmd;
+	pvscsi_unmap_buffers(adapter, ctx);
+	pvscsi_release_context(adapter, ctx);
+	cmd->result = 0;
+
+	if (sdstat != SAM_STAT_GOOD &&
+	    (btstat == BTSTAT_SUCCESS ||
+	     btstat == BTSTAT_LINKED_COMMAND_COMPLETED ||
+	     btstat == BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG)) {
+		cmd->result = (DID_OK << 16) | sdstat;
+		if (sdstat == SAM_STAT_CHECK_CONDITION && cmd->sense_buffer)
+			cmd->result |= (DRIVER_SENSE << 24);
+	} else
+		switch (btstat) {
+		case BTSTAT_SUCCESS:
+		case BTSTAT_LINKED_COMMAND_COMPLETED:
+		case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
+			/* If everything went fine, let's move on..  */
+			cmd->result = (DID_OK << 16);
+			break;
+
+		case BTSTAT_DATARUN:
+		case BTSTAT_DATA_UNDERRUN:
+			/* Report residual data in underruns */
+			scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen);
+			cmd->result = (DID_ERROR << 16);
+			break;
+
+		case BTSTAT_SELTIMEO:
+			/* Our emulation returns this for non-connected devs */
+			cmd->result = (DID_BAD_TARGET << 16);
+			break;
+
+		case BTSTAT_LUNMISMATCH:
+		case BTSTAT_TAGREJECT:
+		case BTSTAT_BADMSG:
+			cmd->result = (DRIVER_INVALID << 24);
+			/* fall through */
+
+		case BTSTAT_HAHARDWARE:
+		case BTSTAT_INVPHASE:
+		case BTSTAT_HATIMEOUT:
+		case BTSTAT_NORESPONSE:
+		case BTSTAT_DISCONNECT:
+		case BTSTAT_HASOFTWARE:
+		case BTSTAT_BUSFREE:
+		case BTSTAT_SENSFAILED:
+			cmd->result |= (DID_ERROR << 16);
+			break;
+
+		case BTSTAT_SENTRST:
+		case BTSTAT_RECVRST:
+		case BTSTAT_BUSRESET:
+			cmd->result = (DID_RESET << 16);
+			break;
+
+		case BTSTAT_ABORTQUEUE:
+			cmd->result = (DID_ABORT << 16);
+			break;
+
+		case BTSTAT_SCSIPARITY:
+			cmd->result = (DID_PARITY << 16);
+			break;
+
+		default:
+			cmd->result = (DID_ERROR << 16);
+			scmd_printk(KERN_DEBUG, cmd,
+				    "Unknown completion status: 0x%x\n",
+				    btstat);
+	}
+
+	dev_dbg(&cmd->device->sdev_gendev,
+		"cmd=%p %x ctx=%p result=0x%x status=0x%x,%x\n",
+		cmd, cmd->cmnd[0], ctx, cmd->result, btstat, sdstat);
+
+	cmd->scsi_done(cmd);
+}
+
+/*
+ * barrier usage : Since the PVSCSI device is emulated, there could be cases
+ * where we may want to serialize some accesses between the driver and the
+ * emulation layer. We use compiler barriers instead of the more expensive
+ * memory barriers because PVSCSI is only supported on X86 which has strong
+ * memory access ordering.
+ */
+static void pvscsi_process_completion_ring(struct pvscsi_adapter *adapter)
+{
+	struct PVSCSIRingsState *s = adapter->rings_state;
+	struct PVSCSIRingCmpDesc *ring = adapter->cmp_ring;
+	u32 cmp_entries = s->cmpNumEntriesLog2;
+
+	while (s->cmpConsIdx != s->cmpProdIdx) {
+		struct PVSCSIRingCmpDesc *e = ring + (s->cmpConsIdx &
+						      MASK(cmp_entries));
+		/*
+		 * This barrier() ensures that *e is not dereferenced while
+		 * the device emulation still writes data into the slot.
+		 * Since the device emulation advances s->cmpProdIdx only after
+		 * updating the slot we want to check it first.
+		 */
+		barrier();
+		pvscsi_complete_request(adapter, e);
+		/*
+		 * This barrier() ensures that compiler doesn't reorder write
+		 * to s->cmpConsIdx before the read of (*e) inside
+		 * pvscsi_complete_request. Otherwise, device emulation may
+		 * overwrite *e before we had a chance to read it.
+		 */
+		barrier();
+		s->cmpConsIdx++;
+	}
+}
+
+/*
+ * Translate a Linux SCSI request into a request ring entry.
+ */
+static int pvscsi_queue_ring(struct pvscsi_adapter *adapter,
+			     struct pvscsi_ctx *ctx, struct scsi_cmnd *cmd)
+{
+	struct PVSCSIRingsState *s;
+	struct PVSCSIRingReqDesc *e;
+	struct scsi_device *sdev;
+	u32 req_entries;
+
+	s = adapter->rings_state;
+	sdev = cmd->device;
+	req_entries = s->reqNumEntriesLog2;
+
+	/*
+	 * If this condition holds, we might have room on the request ring, but
+	 * we might not have room on the completion ring for the response.
+	 * However, we have already ruled out this possibility - we would not
+	 * have successfully allocated a context if it were true, since we only
+	 * have one context per request entry.  Check for it anyway, since it
+	 * would be a serious bug.
+	 */
+	if (s->reqProdIdx - s->cmpConsIdx >= 1 << req_entries) {
+		scmd_printk(KERN_ERR, cmd, "vmw_pvscsi: "
+			    "ring full: reqProdIdx=%d cmpConsIdx=%d\n",
+			    s->reqProdIdx, s->cmpConsIdx);
+		return -1;
+	}
+
+	e = adapter->req_ring + (s->reqProdIdx & MASK(req_entries));
+
+	e->bus    = sdev->channel;
+	e->target = sdev->id;
+	memset(e->lun, 0, sizeof(e->lun));
+	e->lun[1] = sdev->lun;
+
+	if (cmd->sense_buffer) {
+		ctx->sensePA = pci_map_single(adapter->dev, cmd->sense_buffer,
+					      SCSI_SENSE_BUFFERSIZE,
+					      PCI_DMA_FROMDEVICE);
+		e->senseAddr = ctx->sensePA;
+		e->senseLen = SCSI_SENSE_BUFFERSIZE;
+	} else {
+		e->senseLen  = 0;
+		e->senseAddr = 0;
+	}
+	e->cdbLen   = cmd->cmd_len;
+	e->vcpuHint = smp_processor_id();
+	memcpy(e->cdb, cmd->cmnd, e->cdbLen);
+
+	e->tag = SIMPLE_QUEUE_TAG;
+	if (sdev->tagged_supported &&
+	    (cmd->tag == HEAD_OF_QUEUE_TAG ||
+	     cmd->tag == ORDERED_QUEUE_TAG))
+		e->tag = cmd->tag;
+
+	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+		e->flags = PVSCSI_FLAG_CMD_DIR_TOHOST;
+	else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		e->flags = PVSCSI_FLAG_CMD_DIR_TODEVICE;
+	else if (cmd->sc_data_direction == DMA_NONE)
+		e->flags = PVSCSI_FLAG_CMD_DIR_NONE;
+	else
+		e->flags = 0;
+
+	pvscsi_map_buffers(adapter, ctx, cmd, e);
+
+	e->context = pvscsi_map_context(adapter, ctx);
+
+	barrier();
+
+	s->reqProdIdx++;
+
+	return 0;
+}
+
+static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct pvscsi_adapter *adapter = shost_priv(host);
+	struct pvscsi_ctx *ctx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+
+	ctx = pvscsi_acquire_context(adapter, cmd);
+	if (!ctx || pvscsi_queue_ring(adapter, ctx, cmd) != 0) {
+		if (ctx)
+			pvscsi_release_context(adapter, ctx);
+		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	cmd->scsi_done = done;
+
+	dev_dbg(&cmd->device->sdev_gendev,
+		"queued cmd %p, ctx %p, op=%x\n", cmd, ctx, cmd->cmnd[0]);
+
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+	pvscsi_kick_io(adapter, cmd->cmnd[0]);
+
+	return 0;
+}
+
+static int pvscsi_abort(struct scsi_cmnd *cmd)
+{
+	struct pvscsi_adapter *adapter = shost_priv(cmd->device->host);
+	struct pvscsi_ctx *ctx;
+	unsigned long flags;
+
+	scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n",
+		    adapter->host->host_no, cmd);
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+
+	/*
+	 * Poll the completion ring first - we might be trying to abort
+	 * a command that is waiting to be dispatched in the completion ring.
+	 */
+	pvscsi_process_completion_ring(adapter);
+
+	/*
+	 * If there is no context for the command, it either already succeeded
+	 * or else was never properly issued.  Not our problem.
+	 */
+	ctx = pvscsi_find_context(adapter, cmd);
+	if (!ctx) {
+		scmd_printk(KERN_DEBUG, cmd, "Failed to abort cmd %p\n", cmd);
+		goto out;
+	}
+
+	pvscsi_abort_cmd(adapter, ctx);
+
+	pvscsi_process_completion_ring(adapter);
+
+out:
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	return SUCCESS;
+}
+
+/*
+ * Abort all outstanding requests.  This is only safe to use if the completion
+ * ring will never be walked again or the device has been reset, because it
+ * destroys the 1-1 mapping between context field passed to emulation and our
+ * request structure.
+ */
+static void pvscsi_reset_all(struct pvscsi_adapter *adapter)
+{
+	unsigned i;
+
+	for (i = 0; i < adapter->req_depth; i++) {
+		struct pvscsi_ctx *ctx = &adapter->cmd_map[i];
+		struct scsi_cmnd *cmd = ctx->cmd;
+		if (cmd) {
+			scmd_printk(KERN_ERR, cmd,
+				    "Forced reset on cmd %p\n", cmd);
+			pvscsi_unmap_buffers(adapter, ctx);
+			pvscsi_release_context(adapter, ctx);
+			cmd->result = (DID_RESET << 16);
+			cmd->scsi_done(cmd);
+		}
+	}
+}
+
+static int pvscsi_host_reset(struct scsi_cmnd *cmd)
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct pvscsi_adapter *adapter = shost_priv(host);
+	unsigned long flags;
+	bool use_msg;
+
+	scmd_printk(KERN_INFO, cmd, "SCSI Host reset\n");
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+
+	use_msg = adapter->use_msg;
+
+	if (use_msg) {
+		adapter->use_msg = 0;
+		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+		/*
+		 * Now that we know that the ISR won't add more work on the
+		 * workqueue we can safely flush any outstanding work.
+		 */
+		flush_workqueue(adapter->workqueue);
+		spin_lock_irqsave(&adapter->hw_lock, flags);
+	}
+
+	/*
+	 * We're going to tear down the entire ring structure and set it back
+	 * up, so stalling new requests until all completions are flushed and
+	 * the rings are back in place.
+	 */
+
+	pvscsi_process_request_ring(adapter);
+
+	ll_adapter_reset(adapter);
+
+	/*
+	 * Now process any completions.  Note we do this AFTER adapter reset,
+	 * which is strange, but stops races where completions get posted
+	 * between processing the ring and issuing the reset.  The backend will
+	 * not touch the ring memory after reset, so the immediately pre-reset
+	 * completion ring state is still valid.
+	 */
+	pvscsi_process_completion_ring(adapter);
+
+	pvscsi_reset_all(adapter);
+	adapter->use_msg = use_msg;
+	pvscsi_setup_all_rings(adapter);
+	pvscsi_unmask_intr(adapter);
+
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+	return SUCCESS;
+}
+
+static int pvscsi_bus_reset(struct scsi_cmnd *cmd)
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct pvscsi_adapter *adapter = shost_priv(host);
+	unsigned long flags;
+
+	scmd_printk(KERN_INFO, cmd, "SCSI Bus reset\n");
+
+	/*
+	 * We don't want to queue new requests for this bus after
+	 * flushing all pending requests to emulation, since new
+	 * requests could then sneak in during this bus reset phase,
+	 * so take the lock now.
+	 */
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+
+	pvscsi_process_request_ring(adapter);
+	ll_bus_reset(adapter);
+	pvscsi_process_completion_ring(adapter);
+
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+	return SUCCESS;
+}
+
+static int pvscsi_device_reset(struct scsi_cmnd *cmd)
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct pvscsi_adapter *adapter = shost_priv(host);
+	unsigned long flags;
+
+	scmd_printk(KERN_INFO, cmd, "SCSI device reset on scsi%u:%u\n",
+		    host->host_no, cmd->device->id);
+
+	/*
+	 * We don't want to queue new requests for this device after flushing
+	 * all pending requests to emulation, since new requests could then
+	 * sneak in during this device reset phase, so take the lock now.
+	 */
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+
+	pvscsi_process_request_ring(adapter);
+	ll_device_reset(adapter, cmd->device->id);
+	pvscsi_process_completion_ring(adapter);
+
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+	return SUCCESS;
+}
+
+static struct scsi_host_template pvscsi_template;
+
+static const char *pvscsi_info(struct Scsi_Host *host)
+{
+	struct pvscsi_adapter *adapter = shost_priv(host);
+	static char buf[256];
+
+	sprintf(buf, "VMware PVSCSI storage adapter rev %d, req/cmp/msg rings: "
+		"%u/%u/%u pages, cmd_per_lun=%u", adapter->rev,
+		adapter->req_pages, adapter->cmp_pages, adapter->msg_pages,
+		pvscsi_template.cmd_per_lun);
+
+	return buf;
+}
+
+static struct scsi_host_template pvscsi_template = {
+	.module				= THIS_MODULE,
+	.name				= "VMware PVSCSI Host Adapter",
+	.proc_name			= "vmw_pvscsi",
+	.info				= pvscsi_info,
+	.queuecommand			= pvscsi_queue,
+	.this_id			= -1,
+	.sg_tablesize			= PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT,
+	.dma_boundary			= UINT_MAX,
+	.max_sectors			= 0xffff,
+	.use_clustering			= ENABLE_CLUSTERING,
+	.eh_abort_handler		= pvscsi_abort,
+	.eh_device_reset_handler	= pvscsi_device_reset,
+	.eh_bus_reset_handler		= pvscsi_bus_reset,
+	.eh_host_reset_handler		= pvscsi_host_reset,
+};
+
+static void pvscsi_process_msg(const struct pvscsi_adapter *adapter,
+			       const struct PVSCSIRingMsgDesc *e)
+{
+	struct PVSCSIRingsState *s = adapter->rings_state;
+	struct Scsi_Host *host = adapter->host;
+	struct scsi_device *sdev;
+
+	printk(KERN_INFO "vmw_pvscsi: msg type: 0x%x - MSG RING: %u/%u (%u) \n",
+	       e->type, s->msgProdIdx, s->msgConsIdx, s->msgNumEntriesLog2);
+
+	BUILD_BUG_ON(PVSCSI_MSG_LAST != 2);
+
+	if (e->type == PVSCSI_MSG_DEV_ADDED) {
+		struct PVSCSIMsgDescDevStatusChanged *desc;
+		desc = (struct PVSCSIMsgDescDevStatusChanged *)e;
+
+		printk(KERN_INFO
+		       "vmw_pvscsi: msg: device added at scsi%u:%u:%u\n",
+		       desc->bus, desc->target, desc->lun[1]);
+
+		if (!scsi_host_get(host))
+			return;
+
+		sdev = scsi_device_lookup(host, desc->bus, desc->target,
+					  desc->lun[1]);
+		if (sdev) {
+			printk(KERN_INFO "vmw_pvscsi: device already exists\n");
+			scsi_device_put(sdev);
+		} else
+			scsi_add_device(adapter->host, desc->bus,
+					desc->target, desc->lun[1]);
+
+		scsi_host_put(host);
+	} else if (e->type == PVSCSI_MSG_DEV_REMOVED) {
+		struct PVSCSIMsgDescDevStatusChanged *desc;
+		desc = (struct PVSCSIMsgDescDevStatusChanged *)e;
+
+		printk(KERN_INFO
+		       "vmw_pvscsi: msg: device removed at scsi%u:%u:%u\n",
+		       desc->bus, desc->target, desc->lun[1]);
+
+		if (!scsi_host_get(host))
+			return;
+
+		sdev = scsi_device_lookup(host, desc->bus, desc->target,
+					  desc->lun[1]);
+		if (sdev) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		} else
+			printk(KERN_INFO
+			       "vmw_pvscsi: failed to lookup scsi%u:%u:%u\n",
+			       desc->bus, desc->target, desc->lun[1]);
+
+		scsi_host_put(host);
+	}
+}
+
+static int pvscsi_msg_pending(const struct pvscsi_adapter *adapter)
+{
+	struct PVSCSIRingsState *s = adapter->rings_state;
+
+	return s->msgProdIdx != s->msgConsIdx;
+}
+
+static void pvscsi_process_msg_ring(const struct pvscsi_adapter *adapter)
+{
+	struct PVSCSIRingsState *s = adapter->rings_state;
+	struct PVSCSIRingMsgDesc *ring = adapter->msg_ring;
+	u32 msg_entries = s->msgNumEntriesLog2;
+
+	while (pvscsi_msg_pending(adapter)) {
+		struct PVSCSIRingMsgDesc *e = ring + (s->msgConsIdx &
+						      MASK(msg_entries));
+
+		barrier();
+		pvscsi_process_msg(adapter, e);
+		barrier();
+		s->msgConsIdx++;
+	}
+}
+
+static void pvscsi_msg_workqueue_handler(struct work_struct *data)
+{
+	struct pvscsi_adapter *adapter;
+
+	adapter = container_of(data, struct pvscsi_adapter, work);
+
+	pvscsi_process_msg_ring(adapter);
+}
+
+static int pvscsi_setup_msg_workqueue(struct pvscsi_adapter *adapter)
+{
+	char name[32];
+
+	if (!pvscsi_use_msg)
+		return 0;
+
+	pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND,
+			 PVSCSI_CMD_SETUP_MSG_RING);
+
+	if (pvscsi_reg_read(adapter, PVSCSI_REG_OFFSET_COMMAND_STATUS) == -1)
+		return 0;
+
+	snprintf(name, sizeof(name),
+		 "vmw_pvscsi_wq_%u", adapter->host->host_no);
+
+	adapter->workqueue = create_singlethread_workqueue(name);
+	if (!adapter->workqueue) {
+		printk(KERN_ERR "vmw_pvscsi: failed to create work queue\n");
+		return 0;
+	}
+	INIT_WORK(&adapter->work, pvscsi_msg_workqueue_handler);
+
+	return 1;
+}
+
+static irqreturn_t pvscsi_isr(int irq, void *devp)
+{
+	struct pvscsi_adapter *adapter = devp;
+	int handled;
+
+	if (adapter->use_msi || adapter->use_msix)
+		handled = true;
+	else {
+		u32 val = pvscsi_read_intr_status(adapter);
+		handled = (val & PVSCSI_INTR_ALL_SUPPORTED) != 0;
+		if (handled)
+			pvscsi_write_intr_status(devp, val);
+	}
+
+	if (handled) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&adapter->hw_lock, flags);
+
+		pvscsi_process_completion_ring(adapter);
+		if (adapter->use_msg && pvscsi_msg_pending(adapter))
+			queue_work(adapter->workqueue, &adapter->work);
+
+		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+static void pvscsi_free_sgls(const struct pvscsi_adapter *adapter)
+{
+	struct pvscsi_ctx *ctx = adapter->cmd_map;
+	unsigned i;
+
+	for (i = 0; i < adapter->req_depth; ++i, ++ctx)
+		free_pages((unsigned long)ctx->sgl, get_order(SGL_SIZE));
+}
+
+static int pvscsi_setup_msix(const struct pvscsi_adapter *adapter, int *irq)
+{
+	struct msix_entry entry = { 0, PVSCSI_VECTOR_COMPLETION };
+	int ret;
+
+	ret = pci_enable_msix(adapter->dev, &entry, 1);
+	if (ret)
+		return ret;
+
+	*irq = entry.vector;
+
+	return 0;
+}
+
+static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
+{
+	if (adapter->irq) {
+		free_irq(adapter->irq, adapter);
+		adapter->irq = 0;
+	}
+	if (adapter->use_msi) {
+		pci_disable_msi(adapter->dev);
+		adapter->use_msi = 0;
+	} else if (adapter->use_msix) {
+		pci_disable_msix(adapter->dev);
+		adapter->use_msix = 0;
+	}
+}
+
+static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
+{
+	pvscsi_shutdown_intr(adapter);
+
+	if (adapter->workqueue)
+		destroy_workqueue(adapter->workqueue);
+
+	if (adapter->mmioBase)
+		pci_iounmap(adapter->dev, adapter->mmioBase);
+
+	pci_release_regions(adapter->dev);
+
+	if (adapter->cmd_map) {
+		pvscsi_free_sgls(adapter);
+		kfree(adapter->cmd_map);
+	}
+
+	if (adapter->rings_state)
+		pci_free_consistent(adapter->dev, PAGE_SIZE,
+				    adapter->rings_state, adapter->ringStatePA);
+
+	if (adapter->req_ring)
+		pci_free_consistent(adapter->dev,
+				    adapter->req_pages * PAGE_SIZE,
+				    adapter->req_ring, adapter->reqRingPA);
+
+	if (adapter->cmp_ring)
+		pci_free_consistent(adapter->dev,
+				    adapter->cmp_pages * PAGE_SIZE,
+				    adapter->cmp_ring, adapter->cmpRingPA);
+
+	if (adapter->msg_ring)
+		pci_free_consistent(adapter->dev,
+				    adapter->msg_pages * PAGE_SIZE,
+				    adapter->msg_ring, adapter->msgRingPA);
+}
+
+/*
+ * Allocate scatter gather lists.
+ *
+ * These are statically allocated.  Trying to be clever was not worth it.
+ *
+ * Dynamic allocation can fail, and we can't go deeep into the memory
+ * allocator, since we're a SCSI driver, and trying too hard to allocate
+ * memory might generate disk I/O.  We also don't want to fail disk I/O
+ * in that case because we can't get an allocation - the I/O could be
+ * trying to swap out data to free memory.  Since that is pathological,
+ * just use a statically allocated scatter list.
+ *
+ */
+static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
+{
+	struct pvscsi_ctx *ctx;
+	int i;
+
+	ctx = adapter->cmd_map;
+	BUILD_BUG_ON(sizeof(struct pvscsi_sg_list) > SGL_SIZE);
+
+	for (i = 0; i < adapter->req_depth; ++i, ++ctx) {
+		ctx->sgl = (void *)__get_free_pages(GFP_KERNEL,
+						    get_order(SGL_SIZE));
+		ctx->sglPA = 0;
+		BUG_ON(!IS_ALIGNED(((unsigned long)ctx->sgl), PAGE_SIZE));
+		if (!ctx->sgl) {
+			for (; i >= 0; --i, --ctx) {
+				free_pages((unsigned long)ctx->sgl,
+					   get_order(SGL_SIZE));
+				ctx->sgl = NULL;
+			}
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static int __devinit pvscsi_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	struct pvscsi_adapter *adapter;
+	struct Scsi_Host *host;
+	unsigned int i;
+	unsigned long flags = 0;
+	int error;
+
+	error = -ENODEV;
+
+	if (pci_enable_device(pdev))
+		return error;
+
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0 &&
+	    pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
+		printk(KERN_INFO "vmw_pvscsi: using 64bit dma\n");
+	} else if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) == 0 &&
+		   pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) == 0) {
+		printk(KERN_INFO "vmw_pvscsi: using 32bit dma\n");
+	} else {
+		printk(KERN_ERR "vmw_pvscsi: failed to set DMA mask\n");
+		goto out_disable_device;
+	}
+
+	pvscsi_template.can_queue =
+		min(PVSCSI_MAX_NUM_PAGES_REQ_RING, pvscsi_ring_pages) *
+		PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
+	pvscsi_template.cmd_per_lun =
+		min(pvscsi_template.can_queue, pvscsi_cmd_per_lun);
+	host = scsi_host_alloc(&pvscsi_template, sizeof(struct pvscsi_adapter));
+	if (!host) {
+		printk(KERN_ERR "vmw_pvscsi: failed to allocate host\n");
+		goto out_disable_device;
+	}
+
+	adapter = shost_priv(host);
+	memset(adapter, 0, sizeof(*adapter));
+	adapter->dev  = pdev;
+	adapter->host = host;
+
+	spin_lock_init(&adapter->hw_lock);
+
+	host->max_channel = 0;
+	host->max_id      = 16;
+	host->max_lun     = 1;
+	host->max_cmd_len = 16;
+
+	adapter->rev = pdev->revision;
+
+	if (pci_request_regions(pdev, "vmw_pvscsi")) {
+		printk(KERN_ERR "vmw_pvscsi: pci memory selection failed\n");
+		goto out_free_host;
+	}
+
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		if ((pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO))
+			continue;
+
+		if (pci_resource_len(pdev, i) < PVSCSI_MEM_SPACE_SIZE)
+			continue;
+
+		break;
+	}
+
+	if (i == DEVICE_COUNT_RESOURCE) {
+		printk(KERN_ERR
+		       "vmw_pvscsi: adapter has no suitable MMIO region\n");
+		goto out_release_resources;
+	}
+
+	adapter->mmioBase = pci_iomap(pdev, i, PVSCSI_MEM_SPACE_SIZE);
+
+	if (!adapter->mmioBase) {
+		printk(KERN_ERR
+		       "vmw_pvscsi: can't iomap for BAR %d memsize %lu\n",
+		       i, PVSCSI_MEM_SPACE_SIZE);
+		goto out_release_resources;
+	}
+
+	pci_set_master(pdev);
+	pci_set_drvdata(pdev, host);
+
+	ll_adapter_reset(adapter);
+
+	adapter->use_msg = pvscsi_setup_msg_workqueue(adapter);
+
+	error = pvscsi_allocate_rings(adapter);
+	if (error) {
+		printk(KERN_ERR "vmw_pvscsi: unable to allocate ring memory\n");
+		goto out_release_resources;
+	}
+
+	/*
+	 * From this point on we should reset the adapter if anything goes
+	 * wrong.
+	 */
+	pvscsi_setup_all_rings(adapter);
+
+	adapter->cmd_map = kcalloc(adapter->req_depth,
+				   sizeof(struct pvscsi_ctx), GFP_KERNEL);
+	if (!adapter->cmd_map) {
+		printk(KERN_ERR "vmw_pvscsi: failed to allocate memory.\n");
+		error = -ENOMEM;
+		goto out_reset_adapter;
+	}
+
+	INIT_LIST_HEAD(&adapter->cmd_pool);
+	for (i = 0; i < adapter->req_depth; i++) {
+		struct pvscsi_ctx *ctx = adapter->cmd_map + i;
+		list_add(&ctx->list, &adapter->cmd_pool);
+	}
+
+	error = pvscsi_allocate_sg(adapter);
+	if (error) {
+		printk(KERN_ERR "vmw_pvscsi: unable to allocate s/g table\n");
+		goto out_reset_adapter;
+	}
+
+	if (!pvscsi_disable_msix &&
+	    pvscsi_setup_msix(adapter, &adapter->irq) == 0) {
+		printk(KERN_INFO "vmw_pvscsi: using MSI-X\n");
+		adapter->use_msix = 1;
+	} else if (!pvscsi_disable_msi && pci_enable_msi(pdev) == 0) {
+		printk(KERN_INFO "vmw_pvscsi: using MSI\n");
+		adapter->use_msi = 1;
+		adapter->irq = pdev->irq;
+	} else {
+		printk(KERN_INFO "vmw_pvscsi: using INTx\n");
+		adapter->irq = pdev->irq;
+		flags = IRQF_SHARED;
+	}
+
+	error = request_irq(adapter->irq, pvscsi_isr, flags,
+			    "vmw_pvscsi", adapter);
+	if (error) {
+		printk(KERN_ERR
+		       "vmw_pvscsi: unable to request IRQ: %d\n", error);
+		adapter->irq = 0;
+		goto out_reset_adapter;
+	}
+
+	error = scsi_add_host(host, &pdev->dev);
+	if (error) {
+		printk(KERN_ERR
+		       "vmw_pvscsi: scsi_add_host failed: %d\n", error);
+		goto out_reset_adapter;
+	}
+
+	dev_info(&pdev->dev, "VMware PVSCSI rev %d host #%u\n",
+		 adapter->rev, host->host_no);
+
+	pvscsi_unmask_intr(adapter);
+
+	scsi_scan_host(host);
+
+	return 0;
+
+out_reset_adapter:
+	ll_adapter_reset(adapter);
+out_release_resources:
+	pvscsi_release_resources(adapter);
+out_free_host:
+	scsi_host_put(host);
+out_disable_device:
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+
+	return error;
+}
+
+static void __pvscsi_shutdown(struct pvscsi_adapter *adapter)
+{
+	pvscsi_mask_intr(adapter);
+
+	if (adapter->workqueue)
+		flush_workqueue(adapter->workqueue);
+
+	pvscsi_shutdown_intr(adapter);
+
+	pvscsi_process_request_ring(adapter);
+	pvscsi_process_completion_ring(adapter);
+	ll_adapter_reset(adapter);
+}
+
+static void pvscsi_shutdown(struct pci_dev *dev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(dev);
+	struct pvscsi_adapter *adapter = shost_priv(host);
+
+	__pvscsi_shutdown(adapter);
+}
+
+static void pvscsi_remove(struct pci_dev *pdev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pdev);
+	struct pvscsi_adapter *adapter = shost_priv(host);
+
+	scsi_remove_host(host);
+
+	__pvscsi_shutdown(adapter);
+	pvscsi_release_resources(adapter);
+
+	scsi_host_put(host);
+
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+}
+
+static struct pci_driver pvscsi_pci_driver = {
+	.name		= "vmw_pvscsi",
+	.id_table	= pvscsi_pci_tbl,
+	.probe		= pvscsi_probe,
+	.remove		= __devexit_p(pvscsi_remove),
+	.shutdown       = pvscsi_shutdown,
+};
+
+static int __init pvscsi_init(void)
+{
+	pr_info("%s - version %s\n",
+		PVSCSI_LINUX_DRIVER_DESC, PVSCSI_DRIVER_VERSION_STRING);
+	return pci_register_driver(&pvscsi_pci_driver);
+}
+
+static void __exit pvscsi_exit(void)
+{
+	pci_unregister_driver(&pvscsi_pci_driver);
+}
+
+module_init(pvscsi_init);
+module_exit(pvscsi_exit);
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_lib_dma.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_lib_dma.c
@@ -23,7 +23,7 @@
 	int nseg = 0;
 
 	if (scsi_sg_count(cmd)) {
-		struct device *dev = cmd->device->host->shost_gendev.parent;
+		struct device *dev = cmd->device->host->dma_dev;
 
 		nseg = dma_map_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
 				  cmd->sc_data_direction);
@@ -41,7 +41,7 @@
 void scsi_dma_unmap(struct scsi_cmnd *cmd)
 {
 	if (scsi_sg_count(cmd)) {
-		struct device *dev = cmd->device->host->shost_gendev.parent;
+		struct device *dev = cmd->device->host->dma_dev;
 
 		dma_unmap_sg(dev, scsi_sglist(cmd), scsi_sg_count(cmd),
 			     cmd->sc_data_direction);
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_sysfs.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_sysfs.c
@@ -318,14 +318,8 @@
 		kfree(evt);
 	}
 
-	if (sdev->request_queue) {
-		sdev->request_queue->queuedata = NULL;
-		/* user context needed to free queue */
-		scsi_free_queue(sdev->request_queue);
-		/* temporary expedient, try to catch use of queue lock
-		 * after free of sdev */
-		sdev->request_queue = NULL;
-	}
+	/* NULL queue means the device can't be used */
+	sdev->request_queue = NULL;
 
 	scsi_target_reap(scsi_target(sdev));
 
@@ -925,6 +919,12 @@
 	if (sdev->host->hostt->slave_destroy)
 		sdev->host->hostt->slave_destroy(sdev);
 	transport_destroy_device(dev);
+
+	/* cause the request function to reject all I/O requests */
+	sdev->request_queue->queuedata = NULL;
+
+	/* Freeing the queue signals to block that we're done */
+	scsi_free_queue(sdev->request_queue);
 	put_device(dev);
 }
 
@@ -954,10 +954,11 @@
 	list_for_each_entry(sdev, &shost->__devices, siblings) {
 		if (sdev->channel != starget->channel ||
 		    sdev->id != starget->id ||
-		    sdev->sdev_state == SDEV_DEL)
+		    scsi_device_get(sdev))
 			continue;
 		spin_unlock_irqrestore(shost->host_lock, flags);
 		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
 		spin_lock_irqsave(shost->host_lock, flags);
 		goto restart;
 	}
--- linux-ec2-2.6.32.orig/drivers/scsi/sd.c
+++ linux-ec2-2.6.32/drivers/scsi/sd.c
@@ -971,6 +971,7 @@
 {
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->timeout = SD_TIMEOUT;
+	rq->retries = SD_MAX_RETRIES;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
 	rq->cmd_len = 10;
 }
@@ -1039,6 +1040,12 @@
 	u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512);
 	u64 bad_lba;
 	int info_valid;
+	/*
+	 * resid is optional but mostly filled in.  When it's unused,
+	 * its value is zero, so we assume the whole buffer transferred
+	 */
+	unsigned int transferred = scsi_bufflen(scmd) - scsi_get_resid(scmd);
+	unsigned int good_bytes;
 
 	if (!blk_fs_request(scmd->request))
 		return 0;
@@ -1072,7 +1079,8 @@
 	/* This computation should always be done in terms of
 	 * the resolution of the device's medium.
 	 */
-	return (bad_lba - start_lba) * scmd->device->sector_size;
+	good_bytes = (bad_lba - start_lba) * scmd->device->sector_size;
+	return min(good_bytes, transferred);
 }
 
 /**
@@ -2048,11 +2056,10 @@
 	index = sdkp->index;
 	dev = &sdp->sdev_gendev;
 
-	if (index < SD_MAX_DISKS) {
-		gd->major = sd_major((index & 0xf0) >> 4);
-		gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
-		gd->minors = SD_MINORS;
-	}
+	gd->major = sd_major((index & 0xf0) >> 4);
+	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+	gd->minors = SD_MINORS;
+
 	gd->fops = &sd_fops;
 	gd->private_data = &sdkp->driver;
 	gd->queue = sdkp->device->request_queue;
@@ -2141,6 +2148,12 @@
 	if (error)
 		goto out_put;
 
+	if (index >= SD_MAX_DISKS) {
+		error = -ENODEV;
+		sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n");
+		goto out_free_index;
+	}
+
 	error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
 	if (error)
 		goto out_free_index;
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_lib.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_lib.c
@@ -400,10 +400,15 @@
 static void scsi_run_queue(struct request_queue *q)
 {
 	struct scsi_device *sdev = q->queuedata;
-	struct Scsi_Host *shost = sdev->host;
+	struct Scsi_Host *shost;
 	LIST_HEAD(starved_list);
 	unsigned long flags;
 
+	/* if the device is dead, sdev will be NULL, so no queue to run */
+	if (!sdev)
+		return;
+
+	shost = sdev->host;
 	if (scsi_target(sdev)->single_lun)
 		scsi_single_lun_run(sdev);
 
@@ -749,9 +754,9 @@
 			 */
 			req->next_rq->resid_len = scsi_in(cmd)->resid;
 
+			scsi_release_buffers(cmd);
 			blk_end_request_all(req, 0);
 
-			scsi_release_buffers(cmd);
 			scsi_next_command(cmd);
 			return;
 		}
@@ -773,8 +778,14 @@
 	 * we already took a copy of the original into rq->errors which
 	 * is what gets returned to the user
 	 */
-	if (sense_valid && sshdr.sense_key == RECOVERED_ERROR) {
-		if (!(req->cmd_flags & REQ_QUIET))
+	if (sense_valid && (sshdr.sense_key == RECOVERED_ERROR)) {
+		/* if ATA PASS-THROUGH INFORMATION AVAILABLE skip
+		 * print since caller wants ATA registers. Only occurs on
+		 * SCSI ATA PASS_THROUGH commands when CK_COND=1
+		 */
+		if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d))
+			;
+		else if (!(req->cmd_flags & REQ_QUIET))
 			scsi_print_sense("", cmd);
 		result = 0;
 		/* BLOCK_PC may have set error */
@@ -1630,9 +1641,8 @@
 
 	blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
 
-	/* New queue, no concurrency on queue_flags */
 	if (!shost->use_clustering)
-		queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+		q->limits.cluster = 0;
 
 	/*
 	 * set a reasonable default alignment on word boundaries: the
@@ -2426,7 +2436,8 @@
 		sdev->sdev_state = SDEV_RUNNING;
 	else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
 		sdev->sdev_state = SDEV_CREATED;
-	else
+	else if (sdev->sdev_state != SDEV_CANCEL &&
+		 sdev->sdev_state != SDEV_OFFLINE)
 		return -EINVAL;
 
 	spin_lock_irqsave(q->queue_lock, flags);
--- linux-ec2-2.6.32.orig/drivers/scsi/pmcraid.c
+++ linux-ec2-2.6.32/drivers/scsi/pmcraid.c
@@ -3508,6 +3508,9 @@
 			rc = -EFAULT;
 			goto out_free_buffer;
 		}
+	} else if (request_size < 0) {
+		rc = -EINVAL;
+		goto out_free_buffer;
 	}
 
 	/* check if we have any additional command parameters */
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_debug.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_debug.c
@@ -914,7 +914,8 @@
 static sector_t get_sdebug_capacity(void)
 {
 	if (scsi_debug_virtual_gb > 0)
-		return 2048 * 1024 * (sector_t)scsi_debug_virtual_gb;
+		return (sector_t)scsi_debug_virtual_gb *
+			(1073741824 / scsi_debug_sector_size);
 	else
 		return sdebug_store_sectors;
 }
--- linux-ec2-2.6.32.orig/drivers/scsi/scsi_ioctl.c
+++ linux-ec2-2.6.32/drivers/scsi/scsi_ioctl.c
@@ -308,6 +308,9 @@
 		case SG_SCSI_RESET_DEVICE:
 			val = SCSI_TRY_RESET_DEVICE;
 			break;
+		case SG_SCSI_RESET_TARGET:
+			val = SCSI_TRY_RESET_TARGET;
+			break;
 		case SG_SCSI_RESET_BUS:
 			val = SCSI_TRY_RESET_BUS;
 			break;
--- linux-ec2-2.6.32.orig/drivers/scsi/aacraid/commctrl.c
+++ linux-ec2-2.6.32/drivers/scsi/aacraid/commctrl.c
@@ -655,9 +655,9 @@
 				/* Does this really need to be GFP_DMA? */
 				p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
 				if(!p) {
-					kfree (usg);
-					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+					dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
 					  usg->sg[i].count,i,usg->count));
+					kfree(usg);
 					rcode = -ENOMEM;
 					goto cleanup;
 				}
--- linux-ec2-2.6.32.orig/drivers/scsi/aic7xxx/aic79xx_core.c
+++ linux-ec2-2.6.32/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -3171,13 +3171,16 @@
 				tinfo->curr.transport_version = 2;
 				tinfo->goal.transport_version = 2;
 				tinfo->goal.ppr_options = 0;
-				/*
-				 * Remove any SCBs in the waiting for selection
-				 * queue that may also be for this target so
-				 * that command ordering is preserved.
-				 */
-				ahd_freeze_devq(ahd, scb);
-				ahd_qinfifo_requeue_tail(ahd, scb);
+				if (scb != NULL) {
+					/*
+					 * Remove any SCBs in the waiting
+					 * for selection queue that may
+					 * also be for this target so that
+					 * command ordering is preserved.
+					 */
+					ahd_freeze_devq(ahd, scb);
+					ahd_qinfifo_requeue_tail(ahd, scb);
+				}
 				printerror = 0;
 			}
 		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
@@ -3194,13 +3197,16 @@
 				      MSG_EXT_WDTR_BUS_8_BIT,
 				      AHD_TRANS_CUR|AHD_TRANS_GOAL,
 				      /*paused*/TRUE);
-			/*
-			 * Remove any SCBs in the waiting for selection
-			 * queue that may also be for this target so that
-			 * command ordering is preserved.
-			 */
-			ahd_freeze_devq(ahd, scb);
-			ahd_qinfifo_requeue_tail(ahd, scb);
+			if (scb != NULL) {
+				/*
+				 * Remove any SCBs in the waiting for
+				 * selection queue that may also be for
+				 * this target so that command ordering
+				 * is preserved.
+				 */
+				ahd_freeze_devq(ahd, scb);
+				ahd_qinfifo_requeue_tail(ahd, scb);
+			}
 			printerror = 0;
 		} else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
 			&& ppr_busfree == 0) {
@@ -3217,13 +3223,16 @@
 					/*ppr_options*/0,
 					AHD_TRANS_CUR|AHD_TRANS_GOAL,
 					/*paused*/TRUE);
-			/*
-			 * Remove any SCBs in the waiting for selection
-			 * queue that may also be for this target so that
-			 * command ordering is preserved.
-			 */
-			ahd_freeze_devq(ahd, scb);
-			ahd_qinfifo_requeue_tail(ahd, scb);
+			if (scb != NULL) {
+				/*
+				 * Remove any SCBs in the waiting for
+				 * selection queue that may also be for
+				 * this target so that command ordering
+				 * is preserved.
+				 */
+				ahd_freeze_devq(ahd, scb);
+				ahd_qinfifo_requeue_tail(ahd, scb);
+			}
 			printerror = 0;
 		} else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
 			&& ahd_sent_msg(ahd, AHDMSG_1B,
@@ -3251,7 +3260,7 @@
 	 * the message phases.  We check it last in case we
 	 * had to send some other message that caused a busfree.
 	 */
-	if (printerror != 0
+	if (scb != NULL && printerror != 0
 	 && (lastphase == P_MESGIN || lastphase == P_MESGOUT)
 	 && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
 
--- linux-ec2-2.6.32.orig/drivers/scsi/mvsas/mv_init.c
+++ linux-ec2-2.6.32/drivers/scsi/mvsas/mv_init.c
@@ -657,6 +657,7 @@
 	{ PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
+	{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
 
 	{ }	/* terminate list */
 };
--- linux-ec2-2.6.32.orig/drivers/scsi/megaraid/megaraid_sas.h
+++ linux-ec2-2.6.32/drivers/scsi/megaraid/megaraid_sas.h
@@ -30,6 +30,8 @@
 #define	PCI_DEVICE_ID_LSI_VERDE_ZCR		0x0413
 #define	PCI_DEVICE_ID_LSI_SAS1078GEN2		0x0078
 #define	PCI_DEVICE_ID_LSI_SAS0079GEN2		0x0079
+#define	PCI_DEVICE_ID_LSI_SAS0073SKINNY		0x0073
+#define	PCI_DEVICE_ID_LSI_SAS0071SKINNY		0x0071
 
 /*
  * =====================================
@@ -570,6 +572,7 @@
  * is shown below
  */
 #define MEGASAS_INT_CMDS			32
+#define MEGASAS_SKINNY_INT_CMDS			5
 
 /*
  * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
@@ -584,6 +587,8 @@
 #define MFI_REPLY_1078_MESSAGE_INTERRUPT	0x80000000
 #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT	0x00000001
 #define MFI_GEN2_ENABLE_INTERRUPT_MASK		(0x00000001 | 0x00000004)
+#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT	0x40000000
+#define MFI_SKINNY_ENABLE_INTERRUPT_MASK	(0x00000001)
 
 /*
 * register set for both 1068 and 1078 controllers
--- linux-ec2-2.6.32.orig/drivers/scsi/megaraid/megaraid_sas.c
+++ linux-ec2-2.6.32/drivers/scsi/megaraid/megaraid_sas.c
@@ -75,6 +75,10 @@
 	/* gen2*/
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
 	/* gen2*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
+	/* skinny*/
+	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
+	/* skinny*/
 	{PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
 	/* xscale IOP, vega */
 	{PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -328,6 +332,99 @@
 };
 
 /**
+ * megasas_enable_intr_skinny -	Enables interrupts
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
+
+	writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
+
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_disable_intr_skinny -	Disables interrupt
+ * @regs:			MFI register set
+ */
+static inline void
+megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	u32 mask = 0xFFFFFFFF;
+	writel(mask, &regs->outbound_intr_mask);
+	/* Dummy readl to force pci flush */
+	readl(&regs->outbound_intr_mask);
+}
+
+/**
+ * megasas_read_fw_status_reg_skinny - returns the current FW status value
+ * @regs:			MFI register set
+ */
+static u32
+megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
+{
+	return readl(&(regs)->outbound_scratch_pad);
+}
+
+/**
+ * megasas_clear_interrupt_skinny -	Check & clear interrupt
+ * @regs:				MFI register set
+ */
+static int
+megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
+{
+	u32 status;
+	/*
+	 * Check if it is our interrupt
+	 */
+	status = readl(&regs->outbound_intr_status);
+
+	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
+		return 1;
+	}
+
+	/*
+	 * Clear the interrupt by writing back the same value
+	 */
+	writel(status, &regs->outbound_intr_status);
+
+	/*
+	* dummy read to flush PCI
+	*/
+	readl(&regs->outbound_intr_status);
+
+	return 0;
+}
+
+/**
+ * megasas_fire_cmd_skinny -	Sends command to the FW
+ * @frame_phys_addr :		Physical address of cmd
+ * @frame_count :		Number of frames for the command
+ * @regs :			MFI register set
+ */
+static inline void
+megasas_fire_cmd_skinny(dma_addr_t frame_phys_addr, u32 frame_count,
+			struct megasas_register_set __iomem *regs)
+{
+	writel(0, &(regs)->inbound_high_queue_port);
+	writel((frame_phys_addr | (frame_count<<1))|1,
+		&(regs)->inbound_low_queue_port);
+}
+
+static struct megasas_instance_template megasas_instance_template_skinny = {
+
+	.fire_cmd = megasas_fire_cmd_skinny,
+	.enable_intr = megasas_enable_intr_skinny,
+	.disable_intr = megasas_disable_intr_skinny,
+	.clear_intr = megasas_clear_intr_skinny,
+	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+};
+
+
+/**
 *	The following functions are defined for gen2 (deviceid : 0x78 0x79)
 *	controllers
 */
@@ -1072,7 +1169,14 @@
 
 		spin_lock_irqsave(instance->host->host_lock, flags);
 		instance->flag &= ~MEGASAS_FW_BUSY;
-		instance->host->can_queue =
+		if ((instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+			PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+			instance->host->can_queue =
+				instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+		} else
+			instance->host->can_queue =
 				instance->max_fw_cmds - MEGASAS_INT_CMDS;
 
 		spin_unlock_irqrestore(instance->host->host_lock, flags);
@@ -1556,16 +1660,34 @@
 			/*
 			 * Set the CLR bit in inbound doorbell
 			 */
-			writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
-				&instance->reg_set->inbound_doorbell);
+			if ((instance->pdev->device == \
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+
+				writel(
+				  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+				  &instance->reg_set->reserved_0[0]);
+			} else {
+				writel(
+				    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
+					&instance->reg_set->inbound_doorbell);
+			}
 
 			max_wait = 2;
 			cur_state = MFI_STATE_WAIT_HANDSHAKE;
 			break;
 
 		case MFI_STATE_BOOT_MESSAGE_PENDING:
-			writel(MFI_INIT_HOTPLUG,
-				&instance->reg_set->inbound_doorbell);
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+			(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+				writel(MFI_INIT_HOTPLUG,
+				&instance->reg_set->reserved_0[0]);
+			} else
+				writel(MFI_INIT_HOTPLUG,
+					&instance->reg_set->inbound_doorbell);
 
 			max_wait = 10;
 			cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
@@ -1576,7 +1698,15 @@
 			 * Bring it to READY state; assuming max wait 10 secs
 			 */
 			instance->instancet->disable_intr(instance->reg_set);
-			writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
+			if ((instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+				(instance->pdev->device ==
+				PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->reserved_0[0]);
+			} else
+				writel(MFI_RESET_FLAGS,
+					&instance->reg_set->inbound_doorbell);
 
 			max_wait = 60;
 			cur_state = MFI_STATE_OPERATIONAL;
@@ -2081,6 +2211,8 @@
 	 * Map the message registers
 	 */
 	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
 		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
 		instance->base_addr = pci_resource_start(instance->pdev, 1);
 	} else {
@@ -2111,6 +2243,10 @@
 		case PCI_DEVICE_ID_LSI_SAS0079GEN2:
 			instance->instancet = &megasas_instance_template_gen2;
 			break;
+		case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
+		case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
+			instance->instancet = &megasas_instance_template_skinny;
+			break;
 		case PCI_DEVICE_ID_LSI_SAS1064R:
 		case PCI_DEVICE_ID_DELL_PERC5:
 		default:
@@ -2465,7 +2601,13 @@
 	 */
 	host->irq = instance->pdev->irq;
 	host->unique_id = instance->unique_id;
-	host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
+	} else
+		host->can_queue =
+			instance->max_fw_cmds - MEGASAS_INT_CMDS;
 	host->this_id = instance->init_id;
 	host->sg_tablesize = instance->max_num_sge;
 	host->max_sectors = instance->max_sectors_per_req;
@@ -2598,7 +2740,6 @@
 	spin_lock_init(&instance->completion_lock);
 
 	mutex_init(&instance->aen_mutex);
-	sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
 
 	/*
 	 * Initialize PCI related and misc parameters
@@ -2608,6 +2749,12 @@
 	instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
 	instance->init_id = MEGASAS_DEFAULT_INIT_ID;
 
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
+	} else
+		sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
+
 	megasas_dbg_lvl = 0;
 	instance->flag = 0;
 	instance->last_time = 0;
@@ -3032,7 +3179,7 @@
 	int error = 0, i;
 	void *sense = NULL;
 	dma_addr_t sense_handle;
-	u32 *sense_ptr;
+	unsigned long *sense_ptr;
 
 	memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -3072,6 +3219,9 @@
 	 * For each user buffer, create a mirror buffer and copy in
 	 */
 	for (i = 0; i < ioc->sge_count; i++) {
+		if (!ioc->sgl[i].iov_len)
+			continue;
+
 		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
 						    ioc->sgl[i].iov_len,
 						    &buf_handle, GFP_KERNEL);
@@ -3109,7 +3259,7 @@
 		}
 
 		sense_ptr =
-		    (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
+		(unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
 		*sense_ptr = sense_handle;
 	}
 
@@ -3140,8 +3290,8 @@
 		 * sense_ptr points to the location that has the user
 		 * sense buffer address
 		 */
-		sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
-				     ioc->sense_off);
+		sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
+				ioc->sense_off);
 
 		if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
 				 sense, ioc->sense_len)) {
@@ -3282,6 +3432,7 @@
 	    compat_alloc_user_space(sizeof(struct megasas_iocpacket));
 	int i;
 	int error = 0;
+	compat_uptr_t ptr;
 
 	if (clear_user(ioc, sizeof(*ioc)))
 		return -EFAULT;
@@ -3294,9 +3445,22 @@
 	    copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
 		return -EFAULT;
 
-	for (i = 0; i < MAX_IOCTL_SGE; i++) {
-		compat_uptr_t ptr;
+	/*
+	 * The sense_ptr is used in megasas_mgmt_fw_ioctl only when
+	 * sense_len is not null, so prepare the 64bit value under
+	 * the same condition.
+	 */
+	if (ioc->sense_len) {
+		void __user **sense_ioc_ptr =
+			(void __user **)(ioc->frame.raw + ioc->sense_off);
+		compat_uptr_t *sense_cioc_ptr =
+			(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
+		if (get_user(ptr, sense_cioc_ptr) ||
+		    put_user(compat_ptr(ptr), sense_ioc_ptr))
+			return -EFAULT;
+	}
 
+	for (i = 0; i < MAX_IOCTL_SGE; i++) {
 		if (get_user(ptr, &cioc->sgl[i].iov_base) ||
 		    put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
 		    copy_in_user(&ioc->sgl[i].iov_len,
@@ -3451,7 +3615,7 @@
 	return retval;
 }
 
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO,
+static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
 		megasas_sysfs_show_poll_mode_io,
 		megasas_sysfs_set_poll_mode_io);
 
--- linux-ec2-2.6.32.orig/drivers/scsi/arm/fas216.c
+++ linux-ec2-2.6.32/drivers/scsi/arm/fas216.c
@@ -2516,7 +2516,7 @@
 		if (info->scsi.phase == PHASE_IDLE)
 			fas216_kick(info);
 
-		mod_timer(&info->eh_timer, 30 * HZ);
+		mod_timer(&info->eh_timer, jiffies + 30 * HZ);
 		spin_unlock_irqrestore(&info->host_lock, flags);
 
 		/*
--- linux-ec2-2.6.32.orig/drivers/scsi/device_handler/scsi_dh_alua.c
+++ linux-ec2-2.6.32/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -701,6 +701,8 @@
 	{"IBM", "2145" },
 	{"Pillar", "Axiom" },
 	{"Intel", "Multi-Flex"},
+	{"NETAPP", "LUN"},
+	{"AIX", "NVDISK"},
 	{NULL, NULL}
 };
 
--- linux-ec2-2.6.32.orig/drivers/scsi/device_handler/scsi_dh.c
+++ linux-ec2-2.6.32/drivers/scsi/device_handler/scsi_dh.c
@@ -304,18 +304,15 @@
 	sdev = to_scsi_device(dev);
 
 	if (action == BUS_NOTIFY_ADD_DEVICE) {
+		err = device_create_file(dev, &scsi_dh_state_attr);
+		/* don't care about err */
 		devinfo = device_handler_match(NULL, sdev);
-		if (!devinfo)
-			goto out;
-
-		err = scsi_dh_handler_attach(sdev, devinfo);
-		if (!err)
-			err = device_create_file(dev, &scsi_dh_state_attr);
+		if (devinfo)
+			err = scsi_dh_handler_attach(sdev, devinfo);
 	} else if (action == BUS_NOTIFY_DEL_DEVICE) {
 		device_remove_file(dev, &scsi_dh_state_attr);
 		scsi_dh_handler_detach(sdev, NULL);
 	}
-out:
 	return err;
 }
 
--- linux-ec2-2.6.32.orig/drivers/scsi/device_handler/scsi_dh_emc.c
+++ linux-ec2-2.6.32/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -272,7 +272,7 @@
 	int len = 0;
 
 	rq = blk_get_request(sdev->request_queue,
-			(cmd == MODE_SELECT) ? WRITE : READ, GFP_NOIO);
+			(cmd != INQUIRY) ? WRITE : READ, GFP_NOIO);
 	if (!rq) {
 		sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
 		return NULL;
@@ -284,16 +284,17 @@
 	switch (cmd) {
 	case MODE_SELECT:
 		len = sizeof(short_trespass);
-		rq->cmd_flags |= REQ_RW;
 		rq->cmd[1] = 0x10;
+		rq->cmd[4] = len;
 		break;
 	case MODE_SELECT_10:
 		len = sizeof(long_trespass);
-		rq->cmd_flags |= REQ_RW;
 		rq->cmd[1] = 0x10;
+		rq->cmd[8] = len;
 		break;
 	case INQUIRY:
 		len = CLARIION_BUFFER_SIZE;
+		rq->cmd[4] = len;
 		memset(buffer, 0, len);
 		break;
 	default:
@@ -301,7 +302,6 @@
 		break;
 	}
 
-	rq->cmd[4] = len;
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
 			 REQ_FAILFAST_DRIVER;
--- linux-ec2-2.6.32.orig/drivers/scsi/ibmvscsi/ibmvfc.h
+++ linux-ec2-2.6.32/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -38,6 +38,7 @@
 #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT	\
 		(IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
 #define IBMVFC_INIT_TIMEOUT		120
+#define IBMVFC_ABORT_WAIT_TIMEOUT	40
 #define IBMVFC_MAX_REQUESTS_DEFAULT	100
 
 #define IBMVFC_DEBUG			0
--- linux-ec2-2.6.32.orig/drivers/scsi/ibmvscsi/ibmvfc.c
+++ linux-ec2-2.6.32/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1969,7 +1969,7 @@
 	DECLARE_COMPLETION_ONSTACK(comp);
 	int wait;
 	unsigned long flags;
-	signed long timeout = init_timeout * HZ;
+	signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
 
 	ENTER;
 	do {
@@ -2720,6 +2720,7 @@
 	if (crq->valid & 0x80) {
 		if (++async_crq->cur == async_crq->size)
 			async_crq->cur = 0;
+		rmb();
 	} else
 		crq = NULL;
 
@@ -2742,6 +2743,7 @@
 	if (crq->valid & 0x80) {
 		if (++queue->cur == queue->size)
 			queue->cur = 0;
+		rmb();
 	} else
 		crq = NULL;
 
@@ -2790,12 +2792,14 @@
 		while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
 			ibmvfc_handle_async(async, vhost);
 			async->valid = 0;
+			wmb();
 		}
 
 		/* Pull all the valid messages off the CRQ */
 		while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
 			ibmvfc_handle_crq(crq, vhost);
 			crq->valid = 0;
+			wmb();
 		}
 
 		vio_enable_interrupts(vdev);
@@ -2803,10 +2807,12 @@
 			vio_disable_interrupts(vdev);
 			ibmvfc_handle_async(async, vhost);
 			async->valid = 0;
+			wmb();
 		} else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
 			vio_disable_interrupts(vdev);
 			ibmvfc_handle_crq(crq, vhost);
 			crq->valid = 0;
+			wmb();
 		} else
 			done = 1;
 	}
--- linux-ec2-2.6.32.orig/drivers/scsi/libfc/fc_lport.c
+++ linux-ec2-2.6.32/drivers/scsi/libfc/fc_lport.c
@@ -329,7 +329,7 @@
  * @sp: current sequence in the RLIR exchange
  * @fp: RLIR request frame
  *
- * Locking Note: The lport lock is exected to be held before calling
+ * Locking Note: The lport lock is expected to be held before calling
  * this function.
  */
 static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
@@ -348,7 +348,7 @@
  * @sp: current sequence in the ECHO exchange
  * @fp: ECHO request frame
  *
- * Locking Note: The lport lock is exected to be held before calling
+ * Locking Note: The lport lock is expected to be held before calling
  * this function.
  */
 static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
@@ -361,7 +361,7 @@
 	void *dp;
 	u32 f_ctl;
 
-	FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n",
+	FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n",
 		     fc_lport_state(lport));
 
 	len = fr_len(in_fp) - sizeof(struct fc_frame_header);
@@ -374,7 +374,7 @@
 	if (fp) {
 		dp = fc_frame_payload_get(fp, len);
 		memcpy(dp, pp, len);
-		*((u32 *)dp) = htonl(ELS_LS_ACC << 24);
+		*((__be32 *)dp) = htonl(ELS_LS_ACC << 24);
 		sp = lport->tt.seq_start_next(sp);
 		f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
 		fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
@@ -385,12 +385,12 @@
 }
 
 /**
- * fc_lport_recv_echo_req() - Handle received Request Node ID data request
- * @lport: Fibre Channel local port recieving the RNID
- * @sp: current sequence in the RNID exchange
- * @fp: RNID request frame
+ * fc_lport_recv_rnid_req() - Handle received Request Node ID data request
+ * @sp:	   The sequence in the RNID exchange
+ * @fp:	   The RNID request frame
+ * @lport: The local port recieving the RNID
  *
- * Locking Note: The lport lock is exected to be held before calling
+ * Locking Note: The lport lock is expected to be held before calling
  * this function.
  */
 static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
@@ -667,7 +667,7 @@
  * Accept it with the common service parameters indicating our N port.
  * Set up to do a PLOGI if we have the higher-number WWPN.
  *
- * Locking Note: The lport lock is exected to be held before calling
+ * Locking Note: The lport lock is expected to be held before calling
  * this function.
  */
 static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
@@ -1115,7 +1115,7 @@
 
 	if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,
 				  fc_lport_scr_resp, lport, lport->e_d_tov))
-		fc_lport_error(lport, fp);
+		fc_lport_error(lport, NULL);
 }
 
 /**
@@ -1186,7 +1186,7 @@
 	if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID,
 				  fc_lport_rpn_id_resp,
 				  lport, lport->e_d_tov))
-		fc_lport_error(lport, fp);
+		fc_lport_error(lport, NULL);
 }
 
 static struct fc_rport_operations fc_lport_rport_ops = {
@@ -1237,10 +1237,13 @@
 
 	switch (lport->state) {
 	case LPORT_ST_DISABLED:
+		WARN_ON(1);
+		break;
 	case LPORT_ST_READY:
-	case LPORT_ST_RESET:
 		WARN_ON(1);
 		break;
+	case LPORT_ST_RESET:
+		break;
 	case LPORT_ST_FLOGI:
 		fc_lport_enter_flogi(lport);
 		break;
@@ -1337,7 +1340,7 @@
 
 	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,
 				  fc_lport_logo_resp, lport, lport->e_d_tov))
-		fc_lport_error(lport, fp);
+		fc_lport_error(lport, NULL);
 }
 
 /**
@@ -1453,7 +1456,7 @@
 
 	if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI,
 				  fc_lport_flogi_resp, lport, lport->e_d_tov))
-		fc_lport_error(lport, fp);
+		fc_lport_error(lport, NULL);
 }
 
 /* Configure a fc_lport */
--- linux-ec2-2.6.32.orig/drivers/scsi/libfc/fc_fcp.c
+++ linux-ec2-2.6.32/drivers/scsi/libfc/fc_fcp.c
@@ -302,10 +302,13 @@
 	if (!fsp)
 		return;
 
+	if (fsp->xfer_ddp == FC_XID_UNKNOWN)
+		return;
+
 	lp = fsp->lp;
-	if (fsp->xfer_ddp && lp->tt.ddp_done) {
+	if (lp->tt.ddp_done) {
 		fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp);
-		fsp->xfer_ddp = 0;
+		fsp->xfer_ddp = FC_XID_UNKNOWN;
 	}
 }
 
@@ -572,7 +575,8 @@
 		tlen -= sg_bytes;
 		remaining -= sg_bytes;
 
-		if (tlen)
+		if ((skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN) &&
+		    (tlen))
 			continue;
 
 		/*
@@ -1048,7 +1052,6 @@
 
 	seq = lp->tt.exch_seq_send(lp, fp, resp, fc_fcp_pkt_destroy, fsp, 0);
 	if (!seq) {
-		fc_frame_free(fp);
 		rc = -1;
 		goto unlock;
 	}
@@ -1313,7 +1316,6 @@
 		fc_fcp_pkt_hold(fsp);		/* hold while REC outstanding */
 		return;
 	}
-	fc_frame_free(fp);
 retry:
 	if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 		fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
@@ -1561,10 +1563,9 @@
 
 	seq = lp->tt.exch_seq_send(lp, fp, fc_fcp_srr_resp, NULL,
 				   fsp, jiffies_to_msecs(FC_SCSI_REC_TOV));
-	if (!seq) {
-		fc_frame_free(fp);
+	if (!seq)
 		goto retry;
-	}
+
 	fsp->recov_seq = seq;
 	fsp->xfer_len = offset;
 	fsp->xfer_contig_end = offset;
@@ -1708,6 +1709,7 @@
 	fsp->cmd = sc_cmd;	/* save the cmd */
 	fsp->lp = lp;		/* save the softc ptr */
 	fsp->rport = rport;	/* set the remote port ptr */
+	fsp->xfer_ddp = FC_XID_UNKNOWN;
 	sc_cmd->scsi_done = done;
 
 	/*
@@ -1846,7 +1848,8 @@
 			 * scsi status is good but transport level
 			 * underrun.
 			 */
-			sc_cmd->result = DID_OK << 16;
+			sc_cmd->result = (fsp->state & FC_SRB_RCV_STATUS ?
+					  DID_OK : DID_ERROR) << 16;
 		} else {
 			/*
 			 * scsi got underrun, this is an error
@@ -2046,18 +2049,16 @@
 int fc_slave_alloc(struct scsi_device *sdev)
 {
 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
-	int queue_depth;
 
 	if (!rport || fc_remote_port_chkready(rport))
 		return -ENXIO;
 
-	if (sdev->tagged_supported) {
-		if (sdev->host->hostt->cmd_per_lun)
-			queue_depth = sdev->host->hostt->cmd_per_lun;
-		else
-			queue_depth = FC_FCP_DFLT_QUEUE_DEPTH;
-		scsi_activate_tcq(sdev, queue_depth);
-	}
+	if (sdev->tagged_supported)
+		scsi_activate_tcq(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
+	else
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
+					FC_FCP_DFLT_QUEUE_DEPTH);
+
 	return 0;
 }
 EXPORT_SYMBOL(fc_slave_alloc);
--- linux-ec2-2.6.32.orig/drivers/scsi/libfc/fc_elsct.c
+++ linux-ec2-2.6.32/drivers/scsi/libfc/fc_elsct.c
@@ -53,8 +53,10 @@
 		did = FC_FID_DIR_SERV;
 	}
 
-	if (rc)
+	if (rc) {
+		fc_frame_free(fp);
 		return NULL;
+	}
 
 	fc_fill_fc_hdr(fp, r_ctl, did, fc_host_port_id(lport->host), fh_type,
 		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
--- linux-ec2-2.6.32.orig/drivers/scsi/libfc/fc_rport.c
+++ linux-ec2-2.6.32/drivers/scsi/libfc/fc_rport.c
@@ -86,6 +86,7 @@
 	[RPORT_ST_LOGO] = "LOGO",
 	[RPORT_ST_ADISC] = "ADISC",
 	[RPORT_ST_DELETE] = "Delete",
+	[RPORT_ST_RESTART] = "Restart",
 };
 
 /**
@@ -99,8 +100,7 @@
 	struct fc_rport_priv *rdata;
 
 	list_for_each_entry(rdata, &lport->disc.rports, peers)
-		if (rdata->ids.port_id == port_id &&
-		    rdata->rp_state != RPORT_ST_DELETE)
+		if (rdata->ids.port_id == port_id)
 			return rdata;
 	return NULL;
 }
@@ -235,6 +235,7 @@
 	struct fc_rport_operations *rport_ops;
 	struct fc_rport_identifiers ids;
 	struct fc_rport *rport;
+	int restart = 0;
 
 	mutex_lock(&rdata->rp_mutex);
 	event = rdata->event;
@@ -287,8 +288,20 @@
 		mutex_unlock(&rdata->rp_mutex);
 
 		if (port_id != FC_FID_DIR_SERV) {
+			/*
+			 * We must drop rp_mutex before taking disc_mutex.
+			 * Re-evaluate state to allow for restart.
+			 * A transition to RESTART state must only happen
+			 * while disc_mutex is held and rdata is on the list.
+			 */
 			mutex_lock(&lport->disc.disc_mutex);
-			list_del(&rdata->peers);
+			mutex_lock(&rdata->rp_mutex);
+			if (rdata->rp_state == RPORT_ST_RESTART)
+				restart = 1;
+			else
+				list_del(&rdata->peers);
+			rdata->event = RPORT_EV_NONE;
+			mutex_unlock(&rdata->rp_mutex);
 			mutex_unlock(&lport->disc.disc_mutex);
 		}
 
@@ -312,7 +325,13 @@
 			mutex_unlock(&rdata->rp_mutex);
 			fc_remote_port_delete(rport);
 		}
-		kref_put(&rdata->kref, lport->tt.rport_destroy);
+		if (restart) {
+			mutex_lock(&rdata->rp_mutex);
+			FC_RPORT_DBG(rdata, "work restart\n");
+			fc_rport_enter_plogi(rdata);
+			mutex_unlock(&rdata->rp_mutex);
+		} else
+			kref_put(&rdata->kref, lport->tt.rport_destroy);
 		break;
 
 	default:
@@ -342,6 +361,12 @@
 		FC_RPORT_DBG(rdata, "ADISC port\n");
 		fc_rport_enter_adisc(rdata);
 		break;
+	case RPORT_ST_RESTART:
+		break;
+	case RPORT_ST_DELETE:
+		FC_RPORT_DBG(rdata, "Restart deleted port\n");
+		fc_rport_state_enter(rdata, RPORT_ST_RESTART);
+		break;
 	default:
 		FC_RPORT_DBG(rdata, "Login to port\n");
 		fc_rport_enter_plogi(rdata);
@@ -397,20 +422,21 @@
 
 	if (rdata->rp_state == RPORT_ST_DELETE) {
 		FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n");
-		mutex_unlock(&rdata->rp_mutex);
 		goto out;
 	}
 
-	fc_rport_enter_logo(rdata);
+	if (rdata->rp_state == RPORT_ST_RESTART)
+		FC_RPORT_DBG(rdata, "Port in Restart state, deleting\n");
+	else
+		fc_rport_enter_logo(rdata);
 
 	/*
 	 * Change the state to Delete so that we discard
 	 * the response.
 	 */
 	fc_rport_enter_delete(rdata, RPORT_EV_STOP);
-	mutex_unlock(&rdata->rp_mutex);
-
 out:
+	mutex_unlock(&rdata->rp_mutex);
 	return 0;
 }
 
@@ -466,6 +492,7 @@
 	case RPORT_ST_READY:
 	case RPORT_ST_INIT:
 	case RPORT_ST_DELETE:
+	case RPORT_ST_RESTART:
 		break;
 	}
 
@@ -499,6 +526,7 @@
 		fc_rport_enter_logo(rdata);
 		break;
 	case RPORT_ST_DELETE:
+	case RPORT_ST_RESTART:
 	case RPORT_ST_READY:
 	case RPORT_ST_INIT:
 		break;
@@ -632,7 +660,7 @@
 
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PLOGI,
 				  fc_rport_plogi_resp, rdata, lport->e_d_tov))
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
 }
@@ -793,7 +821,7 @@
 
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI,
 				  fc_rport_prli_resp, rdata, lport->e_d_tov))
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
 }
@@ -889,7 +917,7 @@
 
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_RTV,
 				     fc_rport_rtv_resp, rdata, lport->e_d_tov))
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
 }
@@ -919,7 +947,7 @@
 
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_LOGO,
 				  fc_rport_logo_resp, rdata, lport->e_d_tov))
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
 }
@@ -1006,7 +1034,7 @@
 	}
 	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_ADISC,
 				  fc_rport_adisc_resp, rdata, lport->e_d_tov))
-		fc_rport_error_retry(rdata, fp);
+		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
 }
@@ -1248,6 +1276,7 @@
 		}
 		break;
 	case RPORT_ST_PRLI:
+	case RPORT_ST_RTV:
 	case RPORT_ST_READY:
 	case RPORT_ST_ADISC:
 		FC_RPORT_DBG(rdata, "Received PLOGI in logged-in state %d "
@@ -1255,11 +1284,14 @@
 		/* XXX TBD - should reset */
 		break;
 	case RPORT_ST_DELETE:
-	default:
-		FC_RPORT_DBG(rdata, "Received PLOGI in unexpected state %d\n",
-			     rdata->rp_state);
-		fc_frame_free(rx_fp);
-		goto out;
+	case RPORT_ST_LOGO:
+	case RPORT_ST_RESTART:
+		FC_RPORT_DBG(rdata, "Received PLOGI in state %s - send busy\n",
+			     fc_rport_state(rdata));
+		mutex_unlock(&rdata->rp_mutex);
+		rjt_data.reason = ELS_RJT_BUSY;
+		rjt_data.explan = ELS_EXPL_NONE;
+		goto reject;
 	}
 
 	/*
@@ -1402,7 +1434,7 @@
 				break;
 			case FC_TYPE_FCP:
 				fcp_parm = ntohl(rspp->spp_params);
-				if (fcp_parm * FCP_SPPF_RETRY)
+				if (fcp_parm & FCP_SPPF_RETRY)
 					rdata->flags |= FC_RP_FLAGS_RETRY;
 				rdata->supported_classes = FC_COS_CLASS3;
 				if (fcp_parm & FCP_SPPF_INIT_FCN)
@@ -1510,14 +1542,14 @@
 		FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n",
 			     fc_rport_state(rdata));
 
+		fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+
 		/*
-		 * If the remote port was created due to discovery,
-		 * log back in.  It may have seen a stale RSCN about us.
+		 * If the remote port was created due to discovery, set state
+		 * to log back in.  It may have seen a stale RSCN about us.
 		 */
-		if (rdata->rp_state != RPORT_ST_DELETE && rdata->disc_id)
-			fc_rport_enter_plogi(rdata);
-		else
-			fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
+		if (rdata->disc_id)
+			fc_rport_state_enter(rdata, RPORT_ST_RESTART);
 		mutex_unlock(&rdata->rp_mutex);
 	} else
 		FC_RPORT_ID_DBG(lport, sid,
--- linux-ec2-2.6.32.orig/drivers/scsi/libfc/fc_disc.c
+++ linux-ec2-2.6.32/drivers/scsi/libfc/fc_disc.c
@@ -371,7 +371,7 @@
 				 disc, lport->e_d_tov))
 		return;
 err:
-	fc_disc_error(disc, fp);
+	fc_disc_error(disc, NULL);
 }
 
 /**
--- linux-ec2-2.6.32.orig/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ linux-ec2-2.6.32/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -636,6 +636,13 @@
 	data_out_sz = karg.data_out_size;
 	data_in_sz = karg.data_in_size;
 
+	/* Check for overflow and wraparound */
+	if (karg.data_sge_offset * 4 > ioc->request_sz ||
+	    karg.data_sge_offset > (UINT_MAX / 4)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* copy in request message frame from user */
 	if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
 		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
@@ -1809,7 +1816,7 @@
 	Mpi2DiagBufferPostReply_t *mpi_reply;
 	int rc, i;
 	u8 buffer_type;
-	unsigned long timeleft;
+	unsigned long timeleft, request_size, copy_size;
 	u16 smid;
 	u16 ioc_status;
 	u8 issue_reset = 0;
@@ -1845,6 +1852,8 @@
 		return -ENOMEM;
 	}
 
+	request_size = ioc->diag_buffer_sz[buffer_type];
+
 	if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
 		printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
 		    "or bytes_to_read are not 4 byte aligned\n", ioc->name,
@@ -1852,13 +1861,23 @@
 		return -EINVAL;
 	}
 
+	if (karg.starting_offset > request_size)
+		return -EINVAL;
+
 	diag_data = (void *)(request_data + karg.starting_offset);
 	dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), "
 	    "offset(%d), sz(%d)\n", ioc->name, __func__,
 	    diag_data, karg.starting_offset, karg.bytes_to_read));
 
+	/* Truncate data on requests that are too large */
+	if ((diag_data + karg.bytes_to_read < diag_data) ||
+	    (diag_data + karg.bytes_to_read > request_data + request_size))
+		copy_size = request_size - karg.starting_offset;
+	else
+		copy_size = karg.bytes_to_read;
+
 	if (copy_to_user((void __user *)uarg->diagnostic_data,
-	    diag_data, karg.bytes_to_read)) {
+	    diag_data, copy_size)) {
 		printk(MPT2SAS_ERR_FMT "%s: Unable to write "
 		    "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
 		    __func__, diag_data);
--- linux-ec2-2.6.32.orig/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ linux-ec2-2.6.32/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -1947,9 +1947,9 @@
 		/* adjust hba_queue_depth, reply_free_queue_depth,
 		 * and queue_size
 		 */
-		ioc->hba_queue_depth -= queue_diff;
-		ioc->reply_free_queue_depth -= queue_diff;
-		queue_size -= queue_diff;
+		ioc->hba_queue_depth -= (queue_diff / 2);
+		ioc->reply_free_queue_depth -= (queue_diff / 2);
+		queue_size = facts->MaxReplyDescriptorPostQueueDepth;
 	}
 	ioc->reply_post_queue_depth = queue_size;
 
@@ -3595,6 +3595,8 @@
 static void
 _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
 {
+	mpt2sas_scsih_reset_handler(ioc, reset_phase);
+	mpt2sas_ctl_reset_handler(ioc, reset_phase);
 	switch (reset_phase) {
 	case MPT2_IOC_PRE_RESET:
 		dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
@@ -3625,8 +3627,6 @@
 		    "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
 		break;
 	}
-	mpt2sas_scsih_reset_handler(ioc, reset_phase);
-	mpt2sas_ctl_reset_handler(ioc, reset_phase);
 }
 
 /**
@@ -3680,6 +3680,7 @@
 {
 	int r;
 	unsigned long flags;
+	u8 pe_complete = ioc->wait_for_port_enable_to_complete;
 
 	dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
 	    __func__));
@@ -3701,6 +3702,14 @@
 	if (r)
 		goto out;
 	_base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
+
+	/* If this hard reset is called while port enable is active, then
+	 * there is no reason to call make_ioc_operational
+	 */
+	if (pe_complete) {
+		r = -EFAULT;
+		goto out;
+	}
 	r = _base_make_ioc_operational(ioc, sleep_flag);
 	if (!r)
 		_base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
--- linux-ec2-2.6.32.orig/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ linux-ec2-2.6.32/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -196,10 +196,28 @@
 		PCI_ANY_ID, PCI_ANY_ID },
 	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
 		PCI_ANY_ID, PCI_ANY_ID },
+	/* Meteor ~ 2116 */
 	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
 		PCI_ANY_ID, PCI_ANY_ID },
 	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
 		PCI_ANY_ID, PCI_ANY_ID },
+	/* Thunderbolt ~ 2208 */
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8,
+		PCI_ANY_ID, PCI_ANY_ID },
 	{0}	/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, scsih_pci_table);
@@ -927,7 +945,7 @@
 	u32 chain_offset;
 	u32 chain_length;
 	u32 chain_flags;
-	u32 sges_left;
+	int sges_left;
 	u32 sges_in_segment;
 	u32 sgl_flags;
 	u32 sgl_flags_last_element;
@@ -948,7 +966,7 @@
 
 	sg_scmd = scsi_sglist(scmd);
 	sges_left = scsi_dma_map(scmd);
-	if (!sges_left) {
+	if (sges_left < 0) {
 		sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
 		" failed: request for %d bytes!\n", scsi_bufflen(scmd));
 		return -ENOMEM;
@@ -2567,9 +2585,6 @@
 	u16 handle;
 
 	for (i = 0 ; i < event_data->NumEntries; i++) {
-		if (event_data->PHY[i].PhyStatus &
-		    MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
-			continue;
 		handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
 		if (!handle)
 			continue;
@@ -5703,6 +5718,8 @@
 	struct _sas_port *mpt2sas_port;
 	struct _sas_device *sas_device;
 	struct _sas_node *expander_sibling;
+	struct _raid_device *raid_device, *next;
+	struct MPT2SAS_TARGET *sas_target_priv_data;
 	struct workqueue_struct	*wq;
 	unsigned long flags;
 
@@ -5716,6 +5733,21 @@
 	if (wq)
 		destroy_workqueue(wq);
 
+	/* release all the volumes */
+	list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
+	    list) {
+		if (raid_device->starget) {
+			sas_target_priv_data =
+			    raid_device->starget->hostdata;
+			sas_target_priv_data->deleted = 1;
+			scsi_remove_target(&raid_device->starget->dev);
+		}
+		printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
+		    "(0x%016llx)\n", ioc->name,  raid_device->handle,
+		    (unsigned long long) raid_device->wwid);
+		_scsih_raid_device_remove(ioc, raid_device);
+	}
+
 	/* free ports attached to the sas_host */
  retry_again:
 	list_for_each_entry(mpt2sas_port,
--- linux-ec2-2.6.32.orig/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ linux-ec2-2.6.32/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -348,6 +348,14 @@
 #define MPI2_MFGPAGE_DEVID_SAS2108_3                (0x0077)
 #define MPI2_MFGPAGE_DEVID_SAS2116_1                (0x0064)
 #define MPI2_MFGPAGE_DEVID_SAS2116_2                (0x0065)
+#define MPI2_MFGPAGE_DEVID_SAS2208_1                (0x0080)
+#define MPI2_MFGPAGE_DEVID_SAS2208_2                (0x0081)
+#define MPI2_MFGPAGE_DEVID_SAS2208_3                (0x0082)
+#define MPI2_MFGPAGE_DEVID_SAS2208_4                (0x0083)
+#define MPI2_MFGPAGE_DEVID_SAS2208_5                (0x0084)
+#define MPI2_MFGPAGE_DEVID_SAS2208_6                (0x0085)
+#define MPI2_MFGPAGE_DEVID_SAS2208_7                (0x0086)
+#define MPI2_MFGPAGE_DEVID_SAS2208_8                (0x0087)
 
 
 /* Manufacturing Page 0 */
--- linux-ec2-2.6.32.orig/drivers/scsi/bfa/bfa_core.c
+++ linux-ec2-2.6.32/drivers/scsi/bfa/bfa_core.c
@@ -84,11 +84,32 @@
 	for (i = 0; hal_mods[i]; i++)
 		hal_mods[i]->meminfo(cfg, &km_len, &dm_len);
 
+	dm_len += bfa_port_meminfo();
 
 	meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len;
 	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
 }
 
+static void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+	struct bfa_port_s       *port = &bfa->modules.port;
+	uint32_t                dm_len;
+	uint8_t                 *dm_kva;
+	uint64_t                dm_pa;
+
+	dm_len = bfa_port_meminfo();
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa  = bfa_meminfo_dma_phys(mi);
+
+	memset(port, 0, sizeof(struct bfa_port_s));
+	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm);
+	bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
+
 /**
  * Use this function to do attach the driver instance with the BFA
  * library. This function will not trigger any HW initialization
@@ -140,6 +161,7 @@
 	for (i = 0; hal_mods[i]; i++)
 		hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev);
 
+	bfa_com_port_attach(bfa, meminfo);
 }
 
 /**
--- linux-ec2-2.6.32.orig/drivers/scsi/fcoe/fcoe.c
+++ linux-ec2-2.6.32/drivers/scsi/fcoe/fcoe.c
@@ -137,7 +137,7 @@
 	.change_queue_depth = fc_change_queue_depth,
 	.change_queue_type = fc_change_queue_type,
 	.this_id = -1,
-	.cmd_per_lun = 32,
+	.cmd_per_lun = 3,
 	.can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
 	.use_clustering = ENABLE_CLUSTERING,
 	.sg_tablesize = SG_ALL,
@@ -160,6 +160,7 @@
 {
 	struct fcoe_ctlr *fip = &fcoe->ctlr;
 	struct netdev_hw_addr *ha;
+	struct net_device *real_dev;
 	u8 flogi_maddr[ETH_ALEN];
 
 	fcoe->netdev = netdev;
@@ -173,10 +174,12 @@
 
 	/* look for SAN MAC address, if multiple SAN MACs exist, only
 	 * use the first one for SPMA */
+	real_dev = (netdev->priv_flags & IFF_802_1Q_VLAN) ?
+		vlan_dev_real_dev(netdev) : netdev;
 	rcu_read_lock();
-	for_each_dev_addr(netdev, ha) {
+	for_each_dev_addr(real_dev, ha) {
 		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
-		    (is_valid_ether_addr(fip->ctl_src_addr))) {
+		    (is_valid_ether_addr(ha->addr))) {
 			memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN);
 			fip->spma = 1;
 			break;
@@ -664,7 +667,7 @@
 {
 	struct net_device *n = fcoe_netdev(lp);
 
-	if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
+	if (n->netdev_ops->ndo_fcoe_ddp_setup)
 		return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
 
 	return 0;
@@ -681,7 +684,7 @@
 {
 	struct net_device *n = fcoe_netdev(lp);
 
-	if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
+	if (n->netdev_ops->ndo_fcoe_ddp_done)
 		return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
 	return 0;
 }
@@ -1631,7 +1634,7 @@
 {
 	struct fcoe_interface *fcoe;
 	struct net_device *netdev;
-	int rc;
+	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
 #ifdef CONFIG_FCOE_MODULE
--- linux-ec2-2.6.32.orig/drivers/scsi/lpfc/lpfc_init.c
+++ linux-ec2-2.6.32/drivers/scsi/lpfc/lpfc_init.c
@@ -2408,7 +2408,7 @@
 	vport->els_tmofunc.function = lpfc_els_timeout;
 	vport->els_tmofunc.data = (unsigned long)vport;
 
-	error = scsi_add_host(shost, dev);
+	error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
 	if (error)
 		goto out_put_shost;
 
@@ -4384,9 +4384,13 @@
 		pdev = phba->pcidev;
 
 	/* Set the device DMA mask size */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+	 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+		 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
 			return error;
+		}
+	}
 
 	/* Get the bus address of Bar0 and Bar2 and the number of bytes
 	 * required by each mapping.
@@ -5940,9 +5944,13 @@
 		pdev = phba->pcidev;
 
 	/* Set the device DMA mask size */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+	 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+		 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
 			return error;
+		}
+	}
 
 	/* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
 	 * number of bytes required by each mapping. They are actually
--- linux-ec2-2.6.32.orig/drivers/scsi/libsas/sas_scsi_host.c
+++ linux-ec2-2.6.32/drivers/scsi/libsas/sas_scsi_host.c
@@ -648,6 +648,7 @@
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	list_splice_init(&shost->eh_cmd_q, &eh_work_q);
+	shost->host_eh_scheduled = 0;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 
 	SAS_DPRINTK("Enter %s\n", __func__);
@@ -1025,6 +1026,8 @@
 void sas_task_abort(struct sas_task *task)
 {
 	struct scsi_cmnd *sc = task->uldd_task;
+	struct request_queue *q = sc->device->request_queue;
+	unsigned long flags;
 
 	/* Escape for libsas internal commands */
 	if (!sc) {
@@ -1039,7 +1042,9 @@
 		return;
 	}
 
+	spin_lock_irqsave(q->queue_lock, flags);
 	blk_abort_request(sc->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 	scsi_schedule_eh(sc->device->host);
 }
 
--- linux-ec2-2.6.32.orig/drivers/scsi/libsas/sas_ata.c
+++ linux-ec2-2.6.32/drivers/scsi/libsas/sas_ata.c
@@ -346,6 +346,7 @@
 static struct ata_port_operations sas_sata_ops = {
 	.phy_reset		= sas_ata_phy_reset,
 	.post_internal_cmd	= sas_ata_post_internal,
+	.qc_defer               = ata_std_qc_defer,
 	.qc_prep		= ata_noop_qc_prep,
 	.qc_issue		= sas_ata_qc_issue,
 	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
@@ -394,11 +395,15 @@
 void sas_ata_task_abort(struct sas_task *task)
 {
 	struct ata_queued_cmd *qc = task->uldd_task;
+	struct request_queue *q = qc->scsicmd->device->request_queue;
 	struct completion *waiting;
+	unsigned long flags;
 
 	/* Bounce SCSI-initiated commands to the SCSI EH */
 	if (qc->scsicmd) {
+		spin_lock_irqsave(q->queue_lock, flags);
 		blk_abort_request(qc->scsicmd->request);
+		spin_unlock_irqrestore(q->queue_lock, flags);
 		scsi_schedule_eh(qc->scsicmd->device->host);
 		return;
 	}
--- linux-ec2-2.6.32.orig/drivers/scsi/qla2xxx/qla_mid.c
+++ linux-ec2-2.6.32/drivers/scsi/qla2xxx/qla_mid.c
@@ -638,11 +638,15 @@
 
 static void qla_do_work(struct work_struct *work)
 {
+	unsigned long flags;
 	struct rsp_que *rsp = container_of(work, struct rsp_que, q_work);
 	struct scsi_qla_host *vha;
+	struct qla_hw_data *ha = rsp->hw;
 
-	vha = qla25xx_get_host(rsp);
+	spin_lock_irqsave(&rsp->hw->hardware_lock, flags);
+	vha = pci_get_drvdata(ha->pdev);
 	qla24xx_process_response_queue(vha, rsp);
+	spin_unlock_irqrestore(&rsp->hw->hardware_lock, flags);
 }
 
 /* create response queue */
--- linux-ec2-2.6.32.orig/drivers/scsi/qla2xxx/qla_os.c
+++ linux-ec2-2.6.32/drivers/scsi/qla2xxx/qla_os.c
@@ -2016,13 +2016,13 @@
 	DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
 	    base_vha->host_no, ha));
 
-	base_vha->flags.init_done = 1;
-	base_vha->flags.online = 1;
-
 	ret = scsi_add_host(host, &pdev->dev);
 	if (ret)
 		goto probe_failed;
 
+	base_vha->flags.init_done = 1;
+	base_vha->flags.online = 1;
+
 	ha->isp_ops->enable_intrs(ha);
 
 	scsi_scan_host(host);
--- linux-ec2-2.6.32.orig/drivers/scsi/qla2xxx/qla_attr.c
+++ linux-ec2-2.6.32/drivers/scsi/qla2xxx/qla_attr.c
@@ -1654,7 +1654,8 @@
 			fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
 	}
 
-	if (scsi_add_host(vha->host, &fc_vport->dev)) {
+	if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
+				   &ha->pdev->dev)) {
 		DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
 			vha->host_no, vha->vp_idx));
 		goto vport_create_failed_2;
--- linux-ec2-2.6.32.orig/drivers/scsi/qla2xxx/qla_isr.c
+++ linux-ec2-2.6.32/drivers/scsi/qla2xxx/qla_isr.c
@@ -1347,16 +1347,22 @@
 
 	sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
 	if (IS_FWI2_CAPABLE(ha)) {
-		sense_len = le32_to_cpu(sts24->sense_len);
-		rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
-		resid_len = le32_to_cpu(sts24->rsp_residual_count);
-		fw_resid_len = le32_to_cpu(sts24->residual_len);
+		if (scsi_status & SS_SENSE_LEN_VALID)
+			sense_len = le32_to_cpu(sts24->sense_len);
+		if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
+			rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
+		if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER))
+			resid_len = le32_to_cpu(sts24->rsp_residual_count);
+		if (comp_status == CS_DATA_UNDERRUN)
+			fw_resid_len = le32_to_cpu(sts24->residual_len);
 		rsp_info = sts24->data;
 		sense_data = sts24->data;
 		host_to_fcp_swap(sts24->data, sizeof(sts24->data));
 	} else {
-		sense_len = le16_to_cpu(sts->req_sense_length);
-		rsp_info_len = le16_to_cpu(sts->rsp_info_len);
+		if (scsi_status & SS_SENSE_LEN_VALID)
+			sense_len = le16_to_cpu(sts->req_sense_length);
+		if (scsi_status & SS_RESPONSE_INFO_LEN_VALID)
+			rsp_info_len = le16_to_cpu(sts->rsp_info_len);
 		resid_len = le32_to_cpu(sts->residual_length);
 		rsp_info = sts->rsp_info;
 		sense_data = sts->req_sense_data;
@@ -1443,38 +1449,62 @@
 		break;
 
 	case CS_DATA_UNDERRUN:
-		resid = resid_len;
+		DEBUG2(printk(KERN_INFO
+		    "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x. "
+		    "resid=0x%x fw_resid=0x%x cdb=0x%x os_underflow=0x%x\n",
+		    vha->host_no, cp->device->id, cp->device->lun, comp_status,
+		    scsi_status, resid_len, fw_resid_len, cp->cmnd[0],
+		    cp->underflow));
+
 		/* Use F/W calculated residual length. */
-		if (IS_FWI2_CAPABLE(ha)) {
-			if (!(scsi_status & SS_RESIDUAL_UNDER)) {
-				lscsi_status = 0;
-			} else if (resid != fw_resid_len) {
-				scsi_status &= ~SS_RESIDUAL_UNDER;
-				lscsi_status = 0;
+		resid = IS_FWI2_CAPABLE(ha) ? fw_resid_len : resid_len;
+		scsi_set_resid(cp, resid);
+		if (scsi_status & SS_RESIDUAL_UNDER) {
+			if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
+				DEBUG2(printk(
+				    "scsi(%ld:%d:%d:%d) Dropped frame(s) "
+				    "detected (%x of %x bytes)...residual "
+				    "length mismatch...retrying command.\n",
+				    vha->host_no, cp->device->channel,
+				    cp->device->id, cp->device->lun, resid,
+				    scsi_bufflen(cp)));
+
+				cp->result = DID_ERROR << 16 | lscsi_status;
+				break;
 			}
-			resid = fw_resid_len;
-		}
 
-		if (scsi_status & SS_RESIDUAL_UNDER) {
-			scsi_set_resid(cp, resid);
-		} else {
-			DEBUG2(printk(KERN_INFO
-			    "scsi(%ld:%d:%d) UNDERRUN status detected "
-			    "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x "
-			    "os_underflow=0x%x\n", vha->host_no,
-			    cp->device->id, cp->device->lun, comp_status,
-			    scsi_status, resid_len, resid, cp->cmnd[0],
-			    cp->underflow));
+			if (!lscsi_status &&
+			    ((unsigned)(scsi_bufflen(cp) - resid) <
+			    cp->underflow)) {
+				qla_printk(KERN_INFO, ha,
+				    "scsi(%ld:%d:%d:%d): Mid-layer underflow "
+				    "detected (%x of %x bytes)...returning "
+				    "error status.\n", vha->host_no,
+				    cp->device->channel, cp->device->id,
+				    cp->device->lun, resid, scsi_bufflen(cp));
+
+				cp->result = DID_ERROR << 16;
+				break;
+			}
+		} else if (!lscsi_status) {
+			DEBUG2(printk(
+			    "scsi(%ld:%d:%d:%d) Dropped frame(s) detected "
+			    "(%x of %x bytes)...firmware reported underrun..."
+			    "retrying command.\n", vha->host_no,
+			    cp->device->channel, cp->device->id,
+			    cp->device->lun, resid, scsi_bufflen(cp)));
 
+			cp->result = DID_ERROR << 16;
+			break;
 		}
 
+		cp->result = DID_OK << 16 | lscsi_status;
+
 		/*
 		 * Check to see if SCSI Status is non zero. If so report SCSI
 		 * Status.
 		 */
 		if (lscsi_status != 0) {
-			cp->result = DID_OK << 16 | lscsi_status;
-
 			if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
 				DEBUG2(printk(KERN_INFO
 				    "scsi(%ld): QUEUE FULL status detected "
@@ -1501,42 +1531,6 @@
 				break;
 
 			qla2x00_handle_sense(sp, sense_data, sense_len, rsp);
-		} else {
-			/*
-			 * If RISC reports underrun and target does not report
-			 * it then we must have a lost frame, so tell upper
-			 * layer to retry it by reporting an error.
-			 */
-			if (!(scsi_status & SS_RESIDUAL_UNDER)) {
-				DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped "
-					      "frame(s) detected (%x of %x bytes)..."
-					      "retrying command.\n",
-					vha->host_no, cp->device->channel,
-					cp->device->id, cp->device->lun, resid,
-					scsi_bufflen(cp)));
-
-				scsi_set_resid(cp, resid);
-				cp->result = DID_ERROR << 16;
-				break;
-			}
-
-			/* Handle mid-layer underflow */
-			if ((unsigned)(scsi_bufflen(cp) - resid) <
-			    cp->underflow) {
-				qla_printk(KERN_INFO, ha,
-					   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-					   "detected (%x of %x bytes)...returning "
-					   "error status.\n", vha->host_no,
-					   cp->device->channel, cp->device->id,
-					   cp->device->lun, resid,
-					   scsi_bufflen(cp));
-
-				cp->result = DID_ERROR << 16;
-				break;
-			}
-
-			/* Everybody online, looking good... */
-			cp->result = DID_OK << 16;
 		}
 		break;
 
@@ -2018,7 +2012,7 @@
 
 	spin_lock_irq(&ha->hardware_lock);
 
-	vha = qla25xx_get_host(rsp);
+	vha = pci_get_drvdata(ha->pdev);
 	qla24xx_process_response_queue(vha, rsp);
 	if (!ha->mqenable) {
 		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
@@ -2246,30 +2240,28 @@
 
 	/* If possible, enable MSI-X. */
 	if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
-	    !IS_QLA8432(ha) && !IS_QLA8001(ha))
-		goto skip_msix;
+		!IS_QLA8432(ha) && !IS_QLA8001(ha))
+		goto skip_msi;
+
+	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
+		(ha->pdev->subsystem_device == 0x7040 ||
+		ha->pdev->subsystem_device == 0x7041 ||
+		ha->pdev->subsystem_device == 0x1705)) {
+		DEBUG2(qla_printk(KERN_WARNING, ha,
+			"MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X,0x%X).\n",
+			ha->pdev->subsystem_vendor,
+			ha->pdev->subsystem_device));
+		goto skip_msi;
+	}
 
 	if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
 		!QLA_MSIX_FW_MODE_1(ha->fw_attributes))) {
 		DEBUG2(qla_printk(KERN_WARNING, ha,
 		"MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
 			ha->pdev->revision, ha->fw_attributes));
-
 		goto skip_msix;
 	}
 
-	if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_HP &&
-	    (ha->pdev->subsystem_device == 0x7040 ||
-		ha->pdev->subsystem_device == 0x7041 ||
-		ha->pdev->subsystem_device == 0x1705)) {
-		DEBUG2(qla_printk(KERN_WARNING, ha,
-		    "MSI-X: Unsupported ISP2432 SSVID/SSDID (0x%X, 0x%X).\n",
-		    ha->pdev->subsystem_vendor,
-		    ha->pdev->subsystem_device));
-
-		goto skip_msi;
-	}
-
 	ret = qla24xx_enable_msix(ha, rsp);
 	if (!ret) {
 		DEBUG2(qla_printk(KERN_INFO, ha,
@@ -2357,30 +2349,3 @@
 	msix->rsp = rsp;
 	return ret;
 }
-
-struct scsi_qla_host *
-qla25xx_get_host(struct rsp_que *rsp)
-{
-	srb_t *sp;
-	struct qla_hw_data *ha = rsp->hw;
-	struct scsi_qla_host *vha = NULL;
-	struct sts_entry_24xx *pkt;
-	struct req_que *req;
-	uint16_t que;
-	uint32_t handle;
-
-	pkt = (struct sts_entry_24xx *) rsp->ring_ptr;
-	que = MSW(pkt->handle);
-	handle = (uint32_t) LSW(pkt->handle);
-	req = ha->req_q_map[que];
-	if (handle < MAX_OUTSTANDING_COMMANDS) {
-		sp = req->outstanding_cmds[handle];
-		if (sp)
-			return  sp->fcport->vha;
-		else
-			goto base_que;
-	}
-base_que:
-	vha = pci_get_drvdata(ha->pdev);
-	return vha;
-}
--- linux-ec2-2.6.32.orig/drivers/scsi/qla2xxx/qla_gbl.h
+++ linux-ec2-2.6.32/drivers/scsi/qla2xxx/qla_gbl.h
@@ -453,6 +453,5 @@
 extern void qla25xx_wrt_req_reg(struct qla_hw_data *, uint16_t, uint16_t);
 extern void qla25xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
 extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
-extern struct scsi_qla_host * qla25xx_get_host(struct rsp_que *);
 
 #endif /* _QLA_GBL_H */
--- linux-ec2-2.6.32.orig/drivers/memstick/core/mspro_block.c
+++ linux-ec2-2.6.32/drivers/memstick/core/mspro_block.c
@@ -1330,13 +1330,14 @@
 	struct mspro_block_data *msb = memstick_get_drvdata(card);
 	unsigned long flags;
 
-	del_gendisk(msb->disk);
-	dev_dbg(&card->dev, "mspro block remove\n");
 	spin_lock_irqsave(&msb->q_lock, flags);
 	msb->eject = 1;
 	blk_start_queue(msb->queue);
 	spin_unlock_irqrestore(&msb->q_lock, flags);
 
+	del_gendisk(msb->disk);
+	dev_dbg(&card->dev, "mspro block remove\n");
+
 	blk_cleanup_queue(msb->queue);
 	msb->queue = NULL;
 
--- linux-ec2-2.6.32.orig/drivers/char/hvc_iucv.c
+++ linux-ec2-2.6.32/drivers/char/hvc_iucv.c
@@ -139,6 +139,8 @@
  *
  * This function allocates a new struct iucv_tty_buffer element and, optionally,
  * allocates an internal data buffer with the specified size @size.
+ * The internal data buffer is always allocated with GFP_DMA which is
+ * required for receiving and sending data with IUCV.
  * Note: The total message size arises from the internal buffer size and the
  *	 members of the iucv_tty_msg structure.
  * The function returns NULL if memory allocation has failed.
@@ -154,7 +156,7 @@
 
 	if (size > 0) {
 		bufp->msg.length = MSG_SIZE(size);
-		bufp->mbuf = kmalloc(bufp->msg.length, flags);
+		bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
 		if (!bufp->mbuf) {
 			mempool_free(bufp, hvc_iucv_mempool);
 			return NULL;
@@ -237,7 +239,7 @@
 	if (!rb->mbuf) { /* message not yet received ... */
 		/* allocate mem to store msg data; if no memory is available
 		 * then leave the buffer on the list and re-try later */
-		rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC);
+		rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
 		if (!rb->mbuf)
 			return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/drivers/char/hpet.c
+++ linux-ec2-2.6.32/drivers/char/hpet.c
@@ -476,6 +476,21 @@
 	if (irq) {
 		unsigned long irq_flags;
 
+		if (devp->hd_flags & HPET_SHARED_IRQ) {
+			/*
+			 * To prevent the interrupt handler from seeing an
+			 * unwanted interrupt status bit, program the timer
+			 * so that it will not fire in the near future ...
+			 */
+			writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK,
+			       &timer->hpet_config);
+			write_counter(read_counter(&hpet->hpet_mc),
+				      &timer->hpet_compare);
+			/* ... and clear any left-over status. */
+			isr = 1 << (devp - devp->hd_hpets->hp_dev);
+			writel(isr, &hpet->hpet_isr);
+		}
+
 		sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
 		irq_flags = devp->hd_flags & HPET_SHARED_IRQ
 						? IRQF_SHARED : IRQF_DISABLED;
@@ -970,6 +985,8 @@
 		return -ENODEV;
 
 	if (!data.hd_address || !data.hd_nirqs) {
+		if (data.hd_address)
+			iounmap(data.hd_address);
 		printk("%s: no address or irqs in _CRS\n", __func__);
 		return -ENODEV;
 	}
--- linux-ec2-2.6.32.orig/drivers/char/nozomi.c
+++ linux-ec2-2.6.32/drivers/char/nozomi.c
@@ -1629,10 +1629,10 @@
 
 	dc->open_ttys--;
 	port->count--;
-	tty_port_tty_set(port, NULL);
 
 	if (port->count == 0) {
 		DBG1("close: %d", nport->token_dl);
+		tty_port_tty_set(port, NULL);
 		spin_lock_irqsave(&dc->spin_mutex, flags);
 		dc->last_ier &= ~(nport->token_dl);
 		writew(dc->last_ier, dc->reg_ier);
--- linux-ec2-2.6.32.orig/drivers/char/tty_buffer.c
+++ linux-ec2-2.6.32/drivers/char/tty_buffer.c
@@ -247,7 +247,8 @@
 {
 	int copied = 0;
 	do {
-		int space = tty_buffer_request_room(tty, size - copied);
+		int goal = min(size - copied, TTY_BUFFER_PAGE);
+		int space = tty_buffer_request_room(tty, goal);
 		struct tty_buffer *tb = tty->buf.tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0))
@@ -283,7 +284,8 @@
 {
 	int copied = 0;
 	do {
-		int space = tty_buffer_request_room(tty, size - copied);
+		int goal = min(size - copied, TTY_BUFFER_PAGE);
+		int space = tty_buffer_request_room(tty, goal);
 		struct tty_buffer *tb = tty->buf.tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0))
@@ -410,7 +412,8 @@
 	spin_lock_irqsave(&tty->buf.lock, flags);
 
 	if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
-		struct tty_buffer *head;
+		struct tty_buffer *head, *tail = tty->buf.tail;
+		int seen_tail = 0;
 		while ((head = tty->buf.head) != NULL) {
 			int count;
 			char *char_buf;
@@ -420,6 +423,15 @@
 			if (!count) {
 				if (head->next == NULL)
 					break;
+				/*
+				  There's a possibility tty might get new buffer
+				  added during the unlock window below. We could
+				  end up spinning in here forever hogging the CPU
+				  completely. To avoid this let's have a rest each
+				  time we processed the tail buffer.
+				*/
+				if (tail == head)
+					seen_tail = 1;
 				tty->buf.head = head->next;
 				tty_buffer_free(tty, head);
 				continue;
@@ -429,7 +441,7 @@
 			   line discipline as we want to empty the queue */
 			if (test_bit(TTY_FLUSHPENDING, &tty->flags))
 				break;
-			if (!tty->receive_room) {
+			if (!tty->receive_room || seen_tail) {
 				schedule_delayed_work(&tty->buf.work, 1);
 				break;
 			}
--- linux-ec2-2.6.32.orig/drivers/char/vt_ioctl.c
+++ linux-ec2-2.6.32/drivers/char/vt_ioctl.c
@@ -38,6 +38,8 @@
 #include <linux/kbd_diacr.h>
 #include <linux/selection.h>
 
+#define max_font_size 65536
+
 char vt_dont_switch;
 extern struct tty_driver *console_driver;
 
@@ -503,6 +505,7 @@
 	struct kbd_struct * kbd;
 	unsigned int console;
 	unsigned char ucval;
+	unsigned int uival;
 	void __user *up = (void __user *)arg;
 	int i, perm;
 	int ret = 0;
@@ -657,7 +660,7 @@
 		break;
 
 	case KDGETMODE:
-		ucval = vc->vc_mode;
+		uival = vc->vc_mode;
 		goto setint;
 
 	case KDMAPDISP:
@@ -695,7 +698,7 @@
 		break;
 
 	case KDGKBMODE:
-		ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
+		uival = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 				 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 				 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 				 K_XLATE);
@@ -717,9 +720,9 @@
 		break;
 
 	case KDGKBMETA:
-		ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
+		uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
 	setint:
-		ret = put_user(ucval, (int __user *)arg);
+		ret = put_user(uival, (int __user *)arg);
 		break;
 
 	case KDGETKEYCODE:
@@ -949,7 +952,7 @@
 		for (i = 0; i < MAX_NR_CONSOLES; ++i)
 			if (! VT_IS_IN_USE(i))
 				break;
-		ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;
+		uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
 		goto setint;		 
 
 	/*
@@ -1589,6 +1592,7 @@
 {
 	unsigned char old_vc_mode;
 	int old = fg_console;
+	struct vc_data *oldvc = vc_cons[fg_console].d;
 
 	last_console = fg_console;
 
@@ -1597,9 +1601,31 @@
 	 * KD_TEXT mode or vice versa, which means we need to blank or
 	 * unblank the screen later.
 	 */
-	old_vc_mode = vc_cons[fg_console].d->vc_mode;
+	old_vc_mode = oldvc->vc_mode;
+
+#if defined(CONFIG_VGA_CONSOLE)
+	if (old_vc_mode == KD_TEXT && oldvc->vc_sw == &vga_con &&
+	    oldvc->vc_sw->con_font_get) {
+		if (!oldvc->vc_font.data)
+			oldvc->vc_font.data = kmalloc(max_font_size, 
+						      GFP_KERNEL);
+		lock_kernel();
+		oldvc->vc_sw->con_font_get(oldvc, &oldvc->vc_font);
+		unlock_kernel();
+	}
+#endif
 	switch_screen(vc);
 
+#if defined(CONFIG_VGA_CONSOLE)
+	if (vc->vc_mode == KD_TEXT && vc->vc_sw == &vga_con &&
+	    vc->vc_sw->con_font_set) {
+		if (vc->vc_font.data) {
+			lock_kernel();
+			vc->vc_sw->con_font_set(vc, &vc->vc_font, 0);
+			unlock_kernel();
+		}
+	}
+#endif
 	/*
 	 * This can't appear below a successful kill_pid().  If it did,
 	 * then the *blank_screen operation could occur while X, having
--- linux-ec2-2.6.32.orig/drivers/char/tty_ldisc.c
+++ linux-ec2-2.6.32/drivers/char/tty_ldisc.c
@@ -45,6 +45,7 @@
 
 static DEFINE_SPINLOCK(tty_ldisc_lock);
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
@@ -81,6 +82,7 @@
 		return;
 	}
 	local_irq_restore(flags);
+	wake_up(&tty_ldisc_idle);
 }
 
 /**
@@ -442,9 +444,15 @@
 
 static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
 {
+	int ret;
+
 	WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
-	if (ld->ops->open)
-		return ld->ops->open(tty);
+	if (ld->ops->open) {
+		ret = ld->ops->open(tty);
+		if (ret)
+			clear_bit(TTY_LDISC_OPEN, &tty->flags);
+		return ret;
+	}
 	return 0;
 }
 
@@ -522,6 +530,23 @@
 }
 
 /**
+ *	tty_ldisc_wait_idle	-	wait for the ldisc to become idle
+ *	@tty: tty to wait for
+ *
+ *	Wait for the line discipline to become idle. The discipline must
+ *	have been halted for this to guarantee it remains idle.
+ */
+static int tty_ldisc_wait_idle(struct tty_struct *tty)
+{
+	int ret;
+	ret = wait_event_interruptible_timeout(tty_ldisc_idle,
+			atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
+	if (ret < 0)
+		return ret;
+	return ret > 0 ? 0 : -EBUSY;
+}
+
+/**
  *	tty_set_ldisc		-	set line discipline
  *	@tty: the terminal to set
  *	@ldisc: the line discipline
@@ -616,7 +641,16 @@
 
 	flush_scheduled_work();
 
+	retval = tty_ldisc_wait_idle(tty);
+
 	mutex_lock(&tty->ldisc_mutex);
+
+	/* handle wait idle failure locked */
+	if (retval) {
+		tty_ldisc_put(new_ldisc);
+		goto enable;
+	}
+
 	if (test_bit(TTY_HUPPED, &tty->flags)) {
 		/* We were raced by the hangup method. It will have stomped
 		   the ldisc data and closed the ldisc down */
@@ -649,6 +683,7 @@
 
 	tty_ldisc_put(o_ldisc);
 
+enable:
 	/*
 	 *	Allow ldisc referencing to occur again
 	 */
@@ -687,14 +722,18 @@
 /**
  *	tty_ldisc_reinit	-	reinitialise the tty ldisc
  *	@tty: tty to reinit
+ *	@ldisc: line discipline to reinitialize
  *
- *	Switch the tty back to N_TTY line discipline and leave the
- *	ldisc state closed
+ *	Switch the tty to a line discipline and leave the ldisc
+ *	state closed
  */
 
-static void tty_ldisc_reinit(struct tty_struct *tty)
+static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 {
-	struct tty_ldisc *ld;
+	struct tty_ldisc *ld = tty_ldisc_get(ldisc);
+
+	if (IS_ERR(ld))
+		return -1;
 
 	tty_ldisc_close(tty, tty->ldisc);
 	tty_ldisc_put(tty->ldisc);
@@ -702,10 +741,10 @@
 	/*
 	 *	Switch the line discipline back
 	 */
-	ld = tty_ldisc_get(N_TTY);
-	BUG_ON(IS_ERR(ld));
 	tty_ldisc_assign(tty, ld);
-	tty_set_termios_ldisc(tty, N_TTY);
+	tty_set_termios_ldisc(tty, ldisc);
+
+	return 0;
 }
 
 /**
@@ -726,6 +765,8 @@
 void tty_ldisc_hangup(struct tty_struct *tty)
 {
 	struct tty_ldisc *ld;
+	int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
+	int err = 0;
 
 	/*
 	 * FIXME! What are the locking issues here? This may me overdoing
@@ -753,25 +794,35 @@
 	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 	/*
 	 * Shutdown the current line discipline, and reset it to
-	 * N_TTY.
+	 * N_TTY if need be.
+	 *
+	 * Avoid racing set_ldisc or tty_ldisc_release
 	 */
-	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-		/* Avoid racing set_ldisc or tty_ldisc_release */
-		mutex_lock(&tty->ldisc_mutex);
-		tty_ldisc_halt(tty);
-		if (tty->ldisc) {	/* Not yet closed */
-			/* Switch back to N_TTY */
-			tty_ldisc_reinit(tty);
-			/* At this point we have a closed ldisc and we want to
-			   reopen it. We could defer this to the next open but
-			   it means auditing a lot of other paths so this is
-			   a FIXME */
+	mutex_lock(&tty->ldisc_mutex);
+	tty_ldisc_halt(tty);
+	/* At this point we have a closed ldisc and we want to
+	   reopen it. We could defer this to the next open but
+	   it means auditing a lot of other paths so this is
+	   a FIXME */
+	if (tty->ldisc) {	/* Not yet closed */
+		if (reset == 0) {
+
+			if (!tty_ldisc_reinit(tty, tty->termios->c_line))
+				err = tty_ldisc_open(tty, tty->ldisc);
+			else
+				err = 1;
+		}
+		/* If the re-open fails or we reset then go to N_TTY. The
+		   N_TTY open cannot fail */
+		if (reset || err) {
+			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
 			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
-			tty_ldisc_enable(tty);
 		}
-		mutex_unlock(&tty->ldisc_mutex);
-		tty_reset_termios(tty);
+		tty_ldisc_enable(tty);
 	}
+	mutex_unlock(&tty->ldisc_mutex);
+	if (reset)
+		tty_reset_termios(tty);
 }
 
 /**
--- linux-ec2-2.6.32.orig/drivers/char/tty_io.c
+++ linux-ec2-2.6.32/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
+#include <linux/serial.h>
 
 #include <linux/uaccess.h>
 #include <asm/system.h>
@@ -136,6 +137,8 @@
 DEFINE_MUTEX(tty_mutex);
 EXPORT_SYMBOL(tty_mutex);
 
+int console_use_vt = 1;
+
 static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
 static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
 ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -1408,6 +1411,8 @@
 	list_del_init(&tty->tty_files);
 	file_list_unlock();
 
+	put_pid(tty->pgrp);
+	put_pid(tty->session);
 	free_tty_struct(tty);
 }
 
@@ -1736,7 +1741,7 @@
 		goto got_driver;
 	}
 #ifdef CONFIG_VT
-	if (device == MKDEV(TTY_MAJOR, 0)) {
+	if (console_use_vt && device == MKDEV(TTY_MAJOR, 0)) {
 		extern struct tty_driver *console_driver;
 		driver = tty_driver_kref_get(console_driver);
 		index = fg_console;
@@ -1930,8 +1935,10 @@
 			pid = task_pid(current);
 			type = PIDTYPE_PID;
 		}
+		get_pid(pid);
 		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 		retval = __f_setown(filp, pid, type, 0);
+		put_pid(pid);
 		if (retval)
 			goto out;
 	} else {
@@ -2432,6 +2439,20 @@
 	return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+	int retval = -EINVAL;
+	struct serial_icounter_struct icount;
+	memset(&icount, 0, sizeof(icount));
+	if (tty->ops->get_icount)
+		retval = tty->ops->get_icount(tty, &icount);
+	if (retval != 0)
+		return retval;
+	if (copy_to_user(arg, &icount, sizeof(icount)))
+		return -EFAULT;
+	return 0;
+}
+
 struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
 {
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2552,6 +2573,12 @@
 	case TIOCMBIC:
 	case TIOCMBIS:
 		return tty_tiocmset(tty, file, cmd, p);
+	case TIOCGICOUNT:
+		retval = tty_tiocgicount(tty, p);
+		/* For the moment allow fall through to the old method */
+        	if (retval != -EINVAL)
+			return retval;
+		break;
 	case TCFLSH:
 		switch (arg) {
 		case TCIFLUSH:
@@ -3121,7 +3148,8 @@
 			      "console");
 
 #ifdef CONFIG_VT
-	vty_init(&console_fops);
+	if (console_use_vt)
+		vty_init(&console_fops);
 #endif
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/char/mem.c
+++ linux-ec2-2.6.32/drivers/char/mem.c
@@ -35,6 +35,19 @@
 # include <linux/efi.h>
 #endif
 
+static inline unsigned long size_inside_page(unsigned long start,
+					     unsigned long size)
+{
+	unsigned long sz;
+
+	if (-start & (PAGE_SIZE - 1))
+		sz = -start & (PAGE_SIZE - 1);
+	else
+		sz = PAGE_SIZE;
+
+	return min_t(unsigned long, sz, size);
+}
+
 /*
  * Architectures vary in how they handle caching for addresses
  * outside of main memory.
@@ -110,6 +123,7 @@
 {
 }
 
+#ifndef ARCH_HAS_DEV_MEM
 /*
  * This funcion reads the *physical* memory. The f_pos points directly to the 
  * memory location. 
@@ -254,6 +268,7 @@
 	*ppos += written;
 	return written;
 }
+#endif
 
 int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
 	unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
@@ -345,6 +360,9 @@
 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;
@@ -359,6 +377,13 @@
 	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);
 }
@@ -408,6 +433,7 @@
 	unsigned long p = *ppos;
 	ssize_t low_count, read, sz;
 	char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+	int err = 0;
 
 	read = 0;
 	if (p < (unsigned long) high_memory) {
@@ -430,15 +456,7 @@
 		}
 #endif
 		while (low_count > 0) {
-			/*
-			 * Handle first page in case it's not aligned
-			 */
-			if (-p & (PAGE_SIZE - 1))
-				sz = -p & (PAGE_SIZE - 1);
-			else
-				sz = PAGE_SIZE;
-
-			sz = min_t(unsigned long, sz, low_count);
+			sz = size_inside_page(p, low_count);
 
 			/*
 			 * On ia64 if a page has been mapped somewhere as
@@ -462,16 +480,18 @@
 		if (!kbuf)
 			return -ENOMEM;
 		while (count > 0) {
-			int len = count;
+			int len = size_inside_page(p, count);
 
-			if (len > PAGE_SIZE)
-				len = PAGE_SIZE;
+			if (!is_vmalloc_or_module_addr((void *)p)) {
+				err = -ENXIO;
+				break;
+			}
 			len = vread(kbuf, (char *)p, len);
 			if (!len)
 				break;
 			if (copy_to_user(buf, kbuf, len)) {
-				free_page((unsigned long)kbuf);
-				return -EFAULT;
+				err = -EFAULT;
+				break;
 			}
 			count -= len;
 			buf += len;
@@ -480,8 +500,8 @@
 		}
 		free_page((unsigned long)kbuf);
 	}
- 	*ppos = p;
- 	return read;
+	*ppos = p;
+	return read ? read : err;
 }
 
 
@@ -510,15 +530,8 @@
 
 	while (count > 0) {
 		char *ptr;
-		/*
-		 * Handle first page in case it's not aligned
-		 */
-		if (-realp & (PAGE_SIZE - 1))
-			sz = -realp & (PAGE_SIZE - 1);
-		else
-			sz = PAGE_SIZE;
 
-		sz = min_t(unsigned long, sz, count);
+		sz = size_inside_page(realp, count);
 
 		/*
 		 * On ia64 if a page has been mapped somewhere as
@@ -557,6 +570,7 @@
 	ssize_t virtr = 0;
 	ssize_t written;
 	char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+	int err = 0;
 
 	if (p < (unsigned long) high_memory) {
 
@@ -578,20 +592,20 @@
 		if (!kbuf)
 			return wrote ? wrote : -ENOMEM;
 		while (count > 0) {
-			int len = count;
+			int len = size_inside_page(p, count);
 
-			if (len > PAGE_SIZE)
-				len = PAGE_SIZE;
+			if (!is_vmalloc_or_module_addr((void *)p)) {
+				err = -ENXIO;
+				break;
+			}
 			if (len) {
 				written = copy_from_user(kbuf, buf, len);
 				if (written) {
-					if (wrote + virtr)
-						break;
-					free_page((unsigned long)kbuf);
-					return -EFAULT;
+					err = -EFAULT;
+					break;
 				}
 			}
-			len = vwrite(kbuf, (char *)p, len);
+			vwrite(kbuf, (char *)p, len);
 			count -= len;
 			buf += len;
 			virtr += len;
@@ -600,8 +614,8 @@
 		free_page((unsigned long)kbuf);
 	}
 
- 	*ppos = p;
- 	return virtr + wrote;
+	*ppos = p;
+	return virtr + wrote ? : err;
 }
 #endif
 
@@ -774,6 +788,7 @@
 #define open_kmem	open_mem
 #define open_oldmem	open_mem
 
+#ifndef ARCH_HAS_DEV_MEM
 static const struct file_operations mem_fops = {
 	.llseek		= memory_lseek,
 	.read		= read_mem,
@@ -782,6 +797,9 @@
 	.open		= open_mem,
 	.get_unmapped_area = get_unmapped_area_mem,
 };
+#else
+extern const struct file_operations mem_fops;
+#endif
 
 #ifdef CONFIG_DEVKMEM
 static const struct file_operations kmem_fops = {
@@ -820,10 +838,11 @@
 /*
  * capabilities for /dev/zero
  * - permits private mappings, "copies" are taken of the source of zeros
+ * - no writeback happens
  */
 static struct backing_dev_info zero_bdi = {
 	.name		= "char/mem",
-	.capabilities	= BDI_CAP_MAP_COPY,
+	.capabilities	= BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static const struct file_operations full_fops = {
--- linux-ec2-2.6.32.orig/drivers/char/Kconfig
+++ linux-ec2-2.6.32/drivers/char/Kconfig
@@ -659,7 +659,7 @@
 
 config HVC_XEN
 	bool "Xen Hypervisor Console support"
-	depends on XEN
+	depends on PARAVIRT_XEN
 	select HVC_DRIVER
 	select HVC_IRQ
 	default y
@@ -1052,7 +1052,7 @@
 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
--- linux-ec2-2.6.32.orig/drivers/char/nvram.c
+++ linux-ec2-2.6.32/drivers/char/nvram.c
@@ -265,10 +265,16 @@
 	unsigned char contents[NVRAM_BYTES];
 	unsigned i = *ppos;
 	unsigned char *tmp;
-	int len;
 
-	len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count;
-	if (copy_from_user(contents, buf, len))
+	if (i >= NVRAM_BYTES)
+		return 0;	/* Past EOF */
+
+	if (count > NVRAM_BYTES - i)
+		count = NVRAM_BYTES - i;
+	if (count > NVRAM_BYTES)
+		return -EFAULT;	/* Can't happen, but prove it to gcc */
+
+	if (copy_from_user(contents, buf, count))
 		return -EFAULT;
 
 	spin_lock_irq(&rtc_lock);
@@ -276,7 +282,7 @@
 	if (!__nvram_check_checksum())
 		goto checksum_err;
 
-	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+	for (tmp = contents; count--; ++i, ++tmp)
 		__nvram_write_byte(*tmp, i);
 
 	__nvram_set_checksum();
--- linux-ec2-2.6.32.orig/drivers/char/keyboard.c
+++ linux-ec2-2.6.32/drivers/char/keyboard.c
@@ -1068,6 +1068,8 @@
 	int code;
 
 	switch (keycode) {
+		case KEY_RESERVED:
+			break;
 		case KEY_PAUSE:
 			put_queue(vc, 0xe1);
 			put_queue(vc, 0x1d | up_flag);
@@ -1125,6 +1127,8 @@
 
 static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
 {
+	if (keycode == KEY_RESERVED)
+		return 0;
 	if (keycode > 127)
 		return -1;
 
--- linux-ec2-2.6.32.orig/drivers/char/i8k.c
+++ linux-ec2-2.6.32/drivers/char/i8k.c
@@ -119,7 +119,7 @@
 	int eax = regs->eax;
 
 #if defined(CONFIG_X86_64)
-	asm("pushq %%rax\n\t"
+	asm volatile("pushq %%rax\n\t"
 		"movl 0(%%rax),%%edx\n\t"
 		"pushq %%rdx\n\t"
 		"movl 4(%%rax),%%ebx\n\t"
@@ -145,7 +145,7 @@
 		:    "a"(regs)
 		:    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 #else
-	asm("pushl %%eax\n\t"
+	asm volatile("pushl %%eax\n\t"
 	    "movl 0(%%eax),%%edx\n\t"
 	    "push %%edx\n\t"
 	    "movl 4(%%eax),%%ebx\n\t"
@@ -166,7 +166,8 @@
 	    "movl %%edx,0(%%eax)\n\t"
 	    "lahf\n\t"
 	    "shrl $8,%%eax\n\t"
-	    "andl $1,%%eax\n":"=a"(rc)
+	    "andl $1,%%eax\n"
+	    :"=a"(rc)
 	    :    "a"(regs)
 	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 #endif
--- linux-ec2-2.6.32.orig/drivers/char/random.c
+++ linux-ec2-2.6.32/drivers/char/random.c
@@ -1051,12 +1051,6 @@
 				/* like a named pipe */
 	}
 
-	/*
-	 * If we gave the user some bytes, update the access time.
-	 */
-	if (count)
-		file_accessed(file);
-
 	return (count ? count : retval);
 }
 
@@ -1107,7 +1101,6 @@
 			    size_t count, loff_t *ppos)
 {
 	size_t ret;
-	struct inode *inode = file->f_path.dentry->d_inode;
 
 	ret = write_pool(&blocking_pool, buffer, count);
 	if (ret)
@@ -1116,8 +1109,6 @@
 	if (ret)
 		return ret;
 
-	inode->i_mtime = current_fs_time(inode->i_sb);
-	mark_inode_dirty(inode);
 	return (ssize_t)count;
 }
 
--- linux-ec2-2.6.32.orig/drivers/char/raw.c
+++ linux-ec2-2.6.32/drivers/char/raw.c
@@ -247,6 +247,7 @@
 	.aio_read = 	generic_file_aio_read,
 	.write	=	do_sync_write,
 	.aio_write =	blkdev_aio_write,
+	.fsync	=	block_fsync,
 	.open	=	raw_open,
 	.release=	raw_release,
 	.ioctl	=	raw_ioctl,
--- linux-ec2-2.6.32.orig/drivers/char/hvc_console.c
+++ linux-ec2-2.6.32/drivers/char/hvc_console.c
@@ -312,6 +312,7 @@
 	spin_lock_irqsave(&hp->lock, flags);
 	/* Check and then increment for fast path open. */
 	if (hp->count++ > 0) {
+		tty_kref_get(tty);
 		spin_unlock_irqrestore(&hp->lock, flags);
 		hvc_kick();
 		return 0;
@@ -319,7 +320,7 @@
 
 	tty->driver_data = hp;
 
-	hp->tty = tty;
+	hp->tty = tty_kref_get(tty);
 
 	spin_unlock_irqrestore(&hp->lock, flags);
 
@@ -336,6 +337,7 @@
 		spin_lock_irqsave(&hp->lock, flags);
 		hp->tty = NULL;
 		spin_unlock_irqrestore(&hp->lock, flags);
+		tty_kref_put(tty);
 		tty->driver_data = NULL;
 		kref_put(&hp->kref, destroy_hvc_struct);
 		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
@@ -363,6 +365,7 @@
 		return;
 
 	hp = tty->driver_data;
+
 	spin_lock_irqsave(&hp->lock, flags);
 
 	if (--hp->count == 0) {
@@ -389,6 +392,7 @@
 		spin_unlock_irqrestore(&hp->lock, flags);
 	}
 
+	tty_kref_put(tty);
 	kref_put(&hp->kref, destroy_hvc_struct);
 }
 
@@ -424,10 +428,11 @@
 	spin_unlock_irqrestore(&hp->lock, flags);
 
 	if (hp->ops->notifier_hangup)
-			hp->ops->notifier_hangup(hp, hp->data);
+		hp->ops->notifier_hangup(hp, hp->data);
 
 	while(temp_open_count) {
 		--temp_open_count;
+		tty_kref_put(tty);
 		kref_put(&hp->kref, destroy_hvc_struct);
 	}
 }
@@ -592,7 +597,7 @@
 	}
 
 	/* No tty attached, just skip */
-	tty = hp->tty;
+	tty = tty_kref_get(hp->tty);
 	if (tty == NULL)
 		goto bail;
 
@@ -672,6 +677,8 @@
 
 		tty_flip_buffer_push(tty);
 	}
+	if (tty)
+		tty_kref_put(tty);
 
 	return poll_mask;
 }
@@ -806,7 +813,7 @@
 	struct tty_struct *tty;
 
 	spin_lock_irqsave(&hp->lock, flags);
-	tty = hp->tty;
+	tty = tty_kref_get(hp->tty);
 
 	if (hp->index < MAX_NR_HVC_CONSOLES)
 		vtermnos[hp->index] = -1;
@@ -818,18 +825,18 @@
 	/*
 	 * We 'put' the instance that was grabbed when the kref instance
 	 * was initialized using kref_init().  Let the last holder of this
-	 * kref cause it to be removed, which will probably be the tty_hangup
+	 * kref cause it to be removed, which will probably be the tty_vhangup
 	 * below.
 	 */
 	kref_put(&hp->kref, destroy_hvc_struct);
 
 	/*
-	 * This function call will auto chain call hvc_hangup.  The tty should
-	 * always be valid at this time unless a simultaneous tty close already
-	 * cleaned up the hvc_struct.
+	 * This function call will auto chain call hvc_hangup.
 	 */
-	if (tty)
-		tty_hangup(tty);
+	if (tty) {
+		tty_vhangup(tty);
+		tty_kref_put(tty);
+	}
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/char/agp/agp.h
+++ linux-ec2-2.6.32/drivers/char/agp/agp.h
@@ -31,6 +31,10 @@
 
 #include <asm/agp.h>	/* for flush_agp_cache() */
 
+#ifndef virt_to_gart
+#define virt_to_gart virt_to_phys
+#endif
+
 #define PFX "agpgart: "
 
 //#define AGP_DEBUG 1
--- linux-ec2-2.6.32.orig/drivers/char/agp/amd-k7-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/amd-k7-agp.c
@@ -44,7 +44,7 @@
 #ifndef CONFIG_X86
 	SetPageReserved(virt_to_page(page_map->real));
 	global_cache_flush();
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+	page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
 		ClearPageReserved(virt_to_page(page_map->real));
@@ -160,7 +160,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -173,7 +173,7 @@
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+		writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
 	}
--- linux-ec2-2.6.32.orig/drivers/char/agp/efficeon-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/efficeon-agp.c
@@ -226,7 +226,7 @@
 
 		efficeon_private.l1_table[index] = page;
 
-		value = virt_to_phys((unsigned long *)page) | pati | present | index;
+		value = virt_to_gart((unsigned long *)page) | pati | present | index;
 
 		pci_write_config_dword(agp_bridge->dev,
 			EFFICEON_ATTPAGE, value);
--- linux-ec2-2.6.32.orig/drivers/char/agp/sworks-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/sworks-agp.c
@@ -155,7 +155,7 @@
 	/* Create a fake scratch directory */
 	for (i = 0; i < 1024; i++) {
 		writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
-		writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+		writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
 	}
 
 	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -167,7 +167,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -179,7 +179,7 @@
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++)
-		writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+		writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/char/agp/intel-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/intel-agp.c
@@ -8,8 +8,12 @@
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
+#include <asm/smp.h>
 #include "agp.h"
 
+int intel_agp_enabled;
+EXPORT_SYMBOL(intel_agp_enabled);
+
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
@@ -48,6 +52,8 @@
 #define PCI_DEVICE_ID_INTEL_Q33_IG          0x29D2
 #define PCI_DEVICE_ID_INTEL_B43_HB          0x2E40
 #define PCI_DEVICE_ID_INTEL_B43_IG          0x2E42
+#define PCI_DEVICE_ID_INTEL_B43_1_HB        0x2E90
+#define PCI_DEVICE_ID_INTEL_B43_1_IG        0x2E92
 #define PCI_DEVICE_ID_INTEL_GM45_HB         0x2A40
 #define PCI_DEVICE_ID_INTEL_GM45_IG         0x2A42
 #define PCI_DEVICE_ID_INTEL_IGD_E_HB        0x2E00
@@ -95,6 +101,7 @@
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_1_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB || \
@@ -178,6 +185,7 @@
 	 * popup and for the GTT.
 	 */
 	int gtt_entries;			/* i830+ */
+	int gtt_total_size;
 	union {
 		void __iomem *i9xx_flush_page;
 		void *i8xx_flush_page;
@@ -399,8 +407,19 @@
 	if (page == NULL)
 		return NULL;
 
+#ifdef CONFIG_XEN
+	if (xen_create_contiguous_region((unsigned long)page_address(page), 2, 32)) {
+		__free_pages(page, 2);
+		return NULL;
+	}
+#endif
+
 	if (set_pages_uc(page, 4) < 0) {
 		set_pages_wb(page, 4);
+#ifdef CONFIG_XEN
+		xen_destroy_contiguous_region((unsigned long)page_address(page),
+					      2);
+#endif
 		__free_pages(page, 2);
 		return NULL;
 	}
@@ -415,6 +434,9 @@
 		return;
 
 	set_pages_wb(page, 4);
+#ifdef CONFIG_XEN
+	xen_destroy_contiguous_region((unsigned long)page_address(page), 2);
+#endif
 	put_page(page);
 	__free_pages(page, 2);
 	atomic_dec(&agp_bridge->current_memory_agp);
@@ -549,7 +571,11 @@
 	new->page_count = pg_count;
 	new->num_scratch_pages = pg_count;
 	new->type = AGP_PHYS_MEMORY;
+#ifndef CONFIG_XEN
 	new->physical = page_to_phys(new->pages[0]);
+#else
+	new->physical = page_to_pseudophys(new->pages[0]);
+#endif
 	return new;
 }
 
@@ -814,12 +840,6 @@
 		intel_i830_fini_flush();
 }
 
-static void
-do_wbinvd(void *null)
-{
-	wbinvd();
-}
-
 /* The chipset_flush interface needs to get data that has already been
  * flushed out of the CPU all the way out to main memory, because the GPU
  * doesn't snoop those buffers.
@@ -836,12 +856,10 @@
 
 	memset(pg, 0, 1024);
 
-	if (cpu_has_clflush) {
+	if (cpu_has_clflush)
 		clflush_cache_range(pg, 1024);
-	} else {
-		if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
-			printk(KERN_ERR "Timed out waiting for cache flush.\n");
-	}
+	else if (wbinvd_on_all_cpus() != 0)
+		printk(KERN_ERR "Timed out waiting for cache flush.\n");
 }
 
 /* The intel i830 automatically initializes the agp aperture during POST.
@@ -1153,7 +1171,7 @@
 	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
 
 	if (agp_bridge->driver->needs_scratch_page) {
-		for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+		for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
 			writel(agp_bridge->scratch_page, intel_private.gtt+i);
 		}
 		readl(intel_private.gtt+i-1);	/* PCI Posting. */
@@ -1308,6 +1326,8 @@
 	if (!intel_private.gtt)
 		return -ENOMEM;
 
+	intel_private.gtt_total_size = gtt_map_size / 4;
+
 	temp &= 0xfff80000;
 
 	intel_private.registers = ioremap(temp, 128 * 4096);
@@ -1357,6 +1377,7 @@
 	case PCI_DEVICE_ID_INTEL_G45_HB:
 	case PCI_DEVICE_ID_INTEL_G41_HB:
 	case PCI_DEVICE_ID_INTEL_B43_HB:
+	case PCI_DEVICE_ID_INTEL_B43_1_HB:
 	case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
 	case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
 	case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB:
@@ -1395,6 +1416,8 @@
 	if (!intel_private.gtt)
 		return -ENOMEM;
 
+	intel_private.gtt_total_size = gtt_size / 4;
+
 	intel_private.registers = ioremap(temp, 128 * 4096);
 	if (!intel_private.registers) {
 		iounmap(intel_private.gtt);
@@ -2354,6 +2377,8 @@
 	    "G45/G43", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
 	    "B43", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG, 0,
+	    "B43", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
 	    "G41", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_IGDNG_D_HB, PCI_DEVICE_ID_INTEL_IGDNG_D_IG, 0,
@@ -2373,7 +2398,7 @@
 	struct agp_bridge_data *bridge;
 	u8 cap_ptr = 0;
 	struct resource *r;
-	int i;
+	int i, err;
 
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 
@@ -2461,7 +2486,10 @@
 				"set gfx device dma mask 36bit failed!\n");
 
 	pci_set_drvdata(pdev, bridge);
-	return agp_add_bridge(bridge);
+	err = agp_add_bridge(bridge);
+	if (!err)
+		intel_agp_enabled = 1;
+	return err;
 }
 
 static void __devexit agp_intel_remove(struct pci_dev *pdev)
@@ -2562,6 +2590,7 @@
 	ID(PCI_DEVICE_ID_INTEL_G45_HB),
 	ID(PCI_DEVICE_ID_INTEL_G41_HB),
 	ID(PCI_DEVICE_ID_INTEL_B43_HB),
+	ID(PCI_DEVICE_ID_INTEL_B43_1_HB),
 	ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
 	ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
 	ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB),
--- linux-ec2-2.6.32.orig/drivers/char/agp/Kconfig
+++ linux-ec2-2.6.32/drivers/char/agp/Kconfig
@@ -57,7 +57,7 @@
 
 config AGP_AMD64
 	tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
-	depends on AGP && X86
+	depends on AGP && X86 && K8_NB
 	default y if GART_IOMMU
 	help
 	  This option gives you AGP support for the GLX component of
--- linux-ec2-2.6.32.orig/drivers/char/agp/hp-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/hp-agp.c
@@ -488,9 +488,8 @@
 	handle = obj;
 	do {
 		status = acpi_get_object_info(handle, &info);
-		if (ACPI_SUCCESS(status)) {
+		if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) {
 			/* TBD check _CID also */
-			info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0';
 			match = (strcmp(info->hardware_id.string, "HWP0001") == 0);
 			kfree(info);
 			if (match) {
--- linux-ec2-2.6.32.orig/drivers/char/agp/ati-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/ati-agp.c
@@ -360,7 +360,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Write out the size register */
 	current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -390,7 +390,7 @@
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,
+		writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
 	}
--- linux-ec2-2.6.32.orig/drivers/char/agp/amd64-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/amd64-agp.c
@@ -178,7 +178,7 @@
 
 static int amd_8151_configure(void)
 {
-	unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+	unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
 	int i;
 
 	/* Configure AGP regs in each x86-64 host bridge. */
@@ -499,6 +499,10 @@
 	u8 cap_ptr;
 	int err;
 
+	/* The Highlander principle */
+	if (agp_bridges_found)
+		return -ENODEV;
+
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 	if (!cap_ptr)
 		return -ENODEV;
@@ -558,10 +562,12 @@
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-	release_mem_region(virt_to_phys(bridge->gatt_table_real),
+	release_mem_region(virt_to_gart(bridge->gatt_table_real),
 			   amd64_aperture_sizes[bridge->aperture_size_idx].size);
 	agp_remove_bridge(bridge);
 	agp_put_bridge(bridge);
+
+	agp_bridges_found--;
 }
 
 #ifdef CONFIG_PM
@@ -709,6 +715,11 @@
 
 MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);
 
+static DEFINE_PCI_DEVICE_TABLE(agp_amd64_pci_promisc_table) = {
+	{ PCI_DEVICE_CLASS(0, 0) },
+	{ }
+};
+
 static struct pci_driver agp_amd64_pci_driver = {
 	.name		= "agpgart-amd64",
 	.id_table	= agp_amd64_pci_table,
@@ -733,7 +744,6 @@
 		return err;
 
 	if (agp_bridges_found == 0) {
-		struct pci_dev *dev;
 		if (!agp_try_unsupported && !agp_try_unsupported_boot) {
 			printk(KERN_INFO PFX "No supported AGP bridge found.\n");
 #ifdef MODULE
@@ -749,17 +759,10 @@
 			return -ENODEV;
 
 		/* Look for any AGP bridge */
-		dev = NULL;
-		err = -ENODEV;
-		for_each_pci_dev(dev) {
-			if (!pci_find_capability(dev, PCI_CAP_ID_AGP))
-				continue;
-			/* Only one bridge supported right now */
-			if (agp_amd64_probe(dev, NULL) == 0) {
-				err = 0;
-				break;
-			}
-		}
+		agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table;
+		err = driver_attach(&agp_amd64_pci_driver.driver);
+		if (err == 0 && agp_bridges_found == 0)
+			err = -ENODEV;
 	}
 	return err;
 }
--- linux-ec2-2.6.32.orig/drivers/char/agp/sis-agp.c
+++ linux-ec2-2.6.32/drivers/char/agp/sis-agp.c
@@ -415,14 +415,6 @@
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 	},
-	{
-		.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-		.class_mask	= ~0,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_760,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-	},
 	{ }
 };
 
--- linux-ec2-2.6.32.orig/drivers/char/agp/generic.c
+++ linux-ec2-2.6.32/drivers/char/agp/generic.c
@@ -123,6 +123,9 @@
 	struct agp_memory *new;
 	unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
 
+	if (INT_MAX/sizeof(struct page *) < num_agp_pages)
+		return NULL;
+
 	new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
 	if (new == NULL)
 		return NULL;
@@ -242,11 +245,14 @@
 	int scratch_pages;
 	struct agp_memory *new;
 	size_t i;
+	int cur_memory;
 
 	if (!bridge)
 		return NULL;
 
-	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
+	cur_memory = atomic_read(&bridge->current_memory_agp);
+	if ((cur_memory + page_count > bridge->max_memory_agp) ||
+	    (cur_memory + page_count < page_count))
 		return NULL;
 
 	if (type >= AGP_USER_TYPES) {
@@ -988,7 +994,7 @@
 	set_memory_uc((unsigned long)table, 1 << page_order);
 	bridge->gatt_table = (void *)table;
 #else
-	bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+	bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
 					(PAGE_SIZE * (1 << page_order)));
 	bridge->driver->cache_flush();
 #endif
@@ -1001,7 +1007,7 @@
 
 		return -ENOMEM;
 	}
-	bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+	bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = 0; i < num_entries; i++) {
@@ -1123,8 +1129,8 @@
 		return -EINVAL;
 	}
 
-	/* AK: could wrap */
-	if ((pg_start + mem->page_count) > num_entries)
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
 		return -EINVAL;
 
 	j = pg_start;
@@ -1158,7 +1164,7 @@
 {
 	size_t i;
 	struct agp_bridge_data *bridge;
-	int mask_type;
+	int mask_type, num_entries;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -1170,6 +1176,11 @@
 	if (type != mem->type)
 		return -EINVAL;
 
+	num_entries = agp_num_entries();
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
+		return -EINVAL;
+
 	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
 	if (mask_type != 0) {
 		/* The generic routines know nothing of memory types */
--- linux-ec2-2.6.32.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-ec2-2.6.32/drivers/char/ipmi/ipmi_si_intf.c
@@ -310,9 +310,14 @@
 {
 	/* Deliver the message to the upper layer with the lock
 	   released. */
-	spin_unlock(&(smi_info->si_lock));
-	ipmi_smi_msg_received(smi_info->intf, msg);
-	spin_lock(&(smi_info->si_lock));
+
+	if (smi_info->run_to_completion) {
+		ipmi_smi_msg_received(smi_info->intf, msg);
+	} else {
+		spin_unlock(&(smi_info->si_lock));
+		ipmi_smi_msg_received(smi_info->intf, msg);
+		spin_lock(&(smi_info->si_lock));
+	}
 }
 
 static void return_hosed_msg(struct smi_info *smi_info, int cCode)
--- linux-ec2-2.6.32.orig/drivers/char/tpm/Makefile
+++ linux-ec2-2.6.32/drivers/char/tpm/Makefile
@@ -9,3 +9,5 @@
 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
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm_infineon.c
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm_infineon.c
@@ -39,12 +39,12 @@
 struct tpm_inf_dev {
 	int iotype;
 
-	void __iomem *mem_base;		/* MMIO ioremap'd addr */
-	unsigned long map_base;		/* phys MMIO base */
-	unsigned long map_size;		/* MMIO region size */
-	unsigned int index_off;		/* index register offset */
+	void __iomem *mem_base;	/* MMIO ioremap'd addr */
+	unsigned long map_base;	/* phys MMIO base */
+	unsigned long map_size;	/* MMIO region size */
+	unsigned int index_off;	/* index register offset */
 
-	unsigned int data_regs;		/* Data registers */
+	unsigned int data_regs;	/* Data registers */
 	unsigned int data_size;
 
 	unsigned int config_port;	/* IO Port config index reg */
@@ -406,14 +406,14 @@
 	.miscdev = {.fops = &inf_ops,},
 };
 
-static const struct pnp_device_id tpm_pnp_tbl[] = {
+static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
 	/* Infineon TPMs */
 	{"IFX0101", 0},
 	{"IFX0102", 0},
 	{"", 0}
 };
 
-MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
+MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
 
 static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
 				       const struct pnp_device_id *dev_id)
@@ -430,7 +430,7 @@
 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
 	    !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) {
 
-	    	tpm_dev.iotype = TPM_INF_IO_PORT;
+		tpm_dev.iotype = TPM_INF_IO_PORT;
 
 		tpm_dev.config_port = pnp_port_start(dev, 0);
 		tpm_dev.config_size = pnp_port_len(dev, 0);
@@ -459,9 +459,9 @@
 			goto err_last;
 		}
 	} else if (pnp_mem_valid(dev, 0) &&
-	           !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
+		   !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) {
 
-	    	tpm_dev.iotype = TPM_INF_IO_MEM;
+		tpm_dev.iotype = TPM_INF_IO_MEM;
 
 		tpm_dev.map_base = pnp_mem_start(dev, 0);
 		tpm_dev.map_size = pnp_mem_len(dev, 0);
@@ -563,11 +563,11 @@
 			 "product id 0x%02x%02x"
 			 "%s\n",
 			 tpm_dev.iotype == TPM_INF_IO_PORT ?
-				tpm_dev.config_port :
-				tpm_dev.map_base + tpm_dev.index_off,
+			 tpm_dev.config_port :
+			 tpm_dev.map_base + tpm_dev.index_off,
 			 tpm_dev.iotype == TPM_INF_IO_PORT ?
-				tpm_dev.data_regs :
-				tpm_dev.map_base + tpm_dev.data_regs,
+			 tpm_dev.data_regs :
+			 tpm_dev.map_base + tpm_dev.data_regs,
 			 version[0], version[1],
 			 vendorid[0], vendorid[1],
 			 productid[0], productid[1], chipname);
@@ -607,20 +607,55 @@
 			iounmap(tpm_dev.mem_base);
 			release_mem_region(tpm_dev.map_base, tpm_dev.map_size);
 		}
+		tpm_dev_vendor_release(chip);
 		tpm_remove_hardware(chip->dev);
 	}
 }
 
+static int tpm_inf_pnp_suspend(struct pnp_dev *dev, pm_message_t pm_state)
+{
+	struct tpm_chip *chip = pnp_get_drvdata(dev);
+	int rc;
+	if (chip) {
+		u8 savestate[] = {
+			0, 193,	/* TPM_TAG_RQU_COMMAND */
+			0, 0, 0, 10,	/* blob length (in bytes) */
+			0, 0, 0, 152	/* TPM_ORD_SaveState */
+		};
+		dev_info(&dev->dev, "saving TPM state\n");
+		rc = tpm_inf_send(chip, savestate, sizeof(savestate));
+		if (rc < 0) {
+			dev_err(&dev->dev, "error while saving TPM state\n");
+			return rc;
+		}
+	}
+	return 0;
+}
+
+static int tpm_inf_pnp_resume(struct pnp_dev *dev)
+{
+	/* Re-configure TPM after suspending */
+	tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
+	tpm_config_out(IOLIMH, TPM_INF_ADDR);
+	tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA);
+	tpm_config_out(IOLIML, TPM_INF_ADDR);
+	tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA);
+	/* activate register */
+	tpm_config_out(TPM_DAR, TPM_INF_ADDR);
+	tpm_config_out(0x01, TPM_INF_DATA);
+	tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
+	/* disable RESET, LP and IRQC */
+	tpm_data_out(RESET_LP_IRQC_DISABLE, CMD);
+	return tpm_pm_resume(&dev->dev);
+}
+
 static struct pnp_driver tpm_inf_pnp_driver = {
 	.name = "tpm_inf_pnp",
-	.driver = {
-		.owner = THIS_MODULE,
-		.suspend = tpm_pm_suspend,
-		.resume = tpm_pm_resume,
-	},
-	.id_table = tpm_pnp_tbl,
+	.id_table = tpm_inf_pnp_tbl,
 	.probe = tpm_inf_pnp_probe,
-	.remove = __devexit_p(tpm_inf_pnp_remove),
+	.suspend = tpm_inf_pnp_suspend,
+	.resume = tpm_inf_pnp_resume,
+	.remove = __devexit_p(tpm_inf_pnp_remove)
 };
 
 static int __init init_inf(void)
@@ -638,5 +673,5 @@
 
 MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
-MODULE_VERSION("1.9");
+MODULE_VERSION("1.9.2");
 MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm_xen.c
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm_xen.c
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@us.ibm.com
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netfront/netfront.c
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 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/errno.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <xen/evtchn.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/tpmif.h>
+#include <xen/gnttab.h>
+#include <xen/xenbus.h>
+#include "tpm.h"
+#include "tpm_vtpm.h"
+
+#undef DEBUG
+
+/* local structures */
+struct tpm_private {
+	struct tpm_chip *chip;
+
+	tpmif_tx_interface_t *tx;
+	atomic_t refcnt;
+	unsigned int irq;
+	u8 is_connected;
+	u8 is_suspended;
+
+	spinlock_t tx_lock;
+
+	struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
+
+	atomic_t tx_busy;
+	void *tx_remember;
+
+	domid_t backend_id;
+	wait_queue_head_t wait_q;
+
+	struct xenbus_device *dev;
+	int ring_ref;
+};
+
+struct tx_buffer {
+	unsigned int size;	// available space in data
+	unsigned int len;	// used space in data
+	unsigned char *data;	// pointer to a page
+};
+
+
+/* locally visible variables */
+static grant_ref_t gref_head;
+static struct tpm_private *my_priv;
+
+/* local function prototypes */
+static irqreturn_t tpmif_int(int irq,
+                             void *tpm_priv);
+static void tpmif_rx_action(unsigned long unused);
+static int tpmif_connect(struct xenbus_device *dev,
+                         struct tpm_private *tp,
+                         domid_t domid);
+static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
+static int tpmif_allocate_tx_buffers(struct tpm_private *tp);
+static void tpmif_free_tx_buffers(struct tpm_private *tp);
+static void tpmif_set_connected_state(struct tpm_private *tp,
+                                      u8 newstate);
+static int tpm_xmit(struct tpm_private *tp,
+                    const u8 * buf, size_t count, int userbuffer,
+                    void *remember);
+static void destroy_tpmring(struct tpm_private *tp);
+void __exit tpmif_exit(void);
+
+#define DPRINTK(fmt, args...) \
+    pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "xen_tpm_fr: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
+
+#define GRANT_INVALID_REF	0
+
+
+static inline int
+tx_buffer_copy(struct tx_buffer *txb, const u8 *src, int len,
+               int isuserbuffer)
+{
+	int copied = len;
+
+	if (len > txb->size)
+		copied = txb->size;
+	if (isuserbuffer) {
+		if (copy_from_user(txb->data, src, copied))
+			return -EFAULT;
+	} else {
+		memcpy(txb->data, src, copied);
+	}
+	txb->len = len;
+	return copied;
+}
+
+static inline struct tx_buffer *tx_buffer_alloc(void)
+{
+	struct tx_buffer *txb;
+
+	txb = kzalloc(sizeof(struct tx_buffer), GFP_KERNEL);
+	if (!txb)
+		return NULL;
+
+	txb->len = 0;
+	txb->size = PAGE_SIZE;
+	txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (txb->data == NULL) {
+		kfree(txb);
+		txb = NULL;
+	}
+
+	return txb;
+}
+
+
+static inline void tx_buffer_free(struct tx_buffer *txb)
+{
+	if (txb) {
+		free_page((long)txb->data);
+		kfree(txb);
+	}
+}
+
+/**************************************************************
+ Utility function for the tpm_private structure
+**************************************************************/
+static void tpm_private_init(struct tpm_private *tp)
+{
+	spin_lock_init(&tp->tx_lock);
+	init_waitqueue_head(&tp->wait_q);
+	atomic_set(&tp->refcnt, 1);
+}
+
+static void tpm_private_put(void)
+{
+	if (!atomic_dec_and_test(&my_priv->refcnt))
+		return;
+
+	tpmif_free_tx_buffers(my_priv);
+	kfree(my_priv);
+	my_priv = NULL;
+}
+
+static struct tpm_private *tpm_private_get(void)
+{
+	int err;
+
+	if (my_priv) {
+		atomic_inc(&my_priv->refcnt);
+		return my_priv;
+	}
+
+	my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL);
+	if (!my_priv)
+		return NULL;
+
+	tpm_private_init(my_priv);
+	err = tpmif_allocate_tx_buffers(my_priv);
+	if (err < 0)
+		tpm_private_put();
+
+	return my_priv;
+}
+
+/**************************************************************
+
+ The interface to let the tpm plugin register its callback
+ function and send data to another partition using this module
+
+**************************************************************/
+
+static DEFINE_MUTEX(suspend_lock);
+/*
+ * Send data via this module by calling this function
+ */
+int vtpm_vd_send(struct tpm_private *tp,
+                 const u8 * buf, size_t count, void *ptr)
+{
+	int sent;
+
+	mutex_lock(&suspend_lock);
+	sent = tpm_xmit(tp, buf, count, 0, ptr);
+	mutex_unlock(&suspend_lock);
+
+	return sent;
+}
+
+/**************************************************************
+ XENBUS support code
+**************************************************************/
+
+static int setup_tpmring(struct xenbus_device *dev,
+                         struct tpm_private *tp)
+{
+	tpmif_tx_interface_t *sring;
+	int err;
+
+	tp->ring_ref = GRANT_INVALID_REF;
+
+	sring = (void *)__get_free_page(GFP_KERNEL);
+	if (!sring) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+		return -ENOMEM;
+	}
+	tp->tx = sring;
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
+	if (err < 0) {
+		free_page((unsigned long)sring);
+		tp->tx = NULL;
+		xenbus_dev_fatal(dev, err, "allocating grant reference");
+		goto fail;
+	}
+	tp->ring_ref = err;
+
+	err = tpmif_connect(dev, tp, dev->otherend_id);
+	if (err)
+		goto fail;
+
+	return 0;
+fail:
+	destroy_tpmring(tp);
+	return err;
+}
+
+
+static void destroy_tpmring(struct tpm_private *tp)
+{
+	tpmif_set_connected_state(tp, 0);
+
+	if (tp->ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(tp->ring_ref, (unsigned long)tp->tx);
+		tp->ring_ref = GRANT_INVALID_REF;
+		tp->tx = NULL;
+	}
+
+	if (tp->irq)
+		unbind_from_irqhandler(tp->irq, tp);
+
+	tp->irq = 0;
+}
+
+
+static int talk_to_backend(struct xenbus_device *dev,
+                           struct tpm_private *tp)
+{
+	const char *message = NULL;
+	int err;
+	struct xenbus_transaction xbt;
+
+	err = setup_tpmring(dev, tp);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "setting up ring");
+		goto out;
+	}
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		goto destroy_tpmring;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename,
+	                    "ring-ref","%u", tp->ring_ref);
+	if (err) {
+		message = "writing ring-ref";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    irq_to_evtchn_port(tp->irq));
+	if (err) {
+		message = "writing event-channel";
+		goto abort_transaction;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err) {
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto destroy_tpmring;
+	}
+
+	xenbus_switch_state(dev, XenbusStateConnected);
+
+	return 0;
+
+abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	if (message)
+		xenbus_dev_error(dev, err, "%s", message);
+destroy_tpmring:
+	destroy_tpmring(tp);
+out:
+	return err;
+}
+
+/**
+ * Callback received when the backend's state changes.
+ */
+static void backend_changed(struct xenbus_device *dev,
+			    enum xenbus_state backend_state)
+{
+	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
+	DPRINTK("\n");
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitWait:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+		break;
+
+	case XenbusStateConnected:
+		tpmif_set_connected_state(tp, 1);
+		break;
+
+	case XenbusStateClosing:
+		tpmif_set_connected_state(tp, 0);
+		xenbus_frontend_closed(dev);
+		break;
+
+	case XenbusStateClosed:
+		tpmif_set_connected_state(tp, 0);
+		if (tp->is_suspended == 0)
+			device_unregister(&dev->dev);
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static int tpmfront_probe(struct xenbus_device *dev,
+                          const struct xenbus_device_id *id)
+{
+	int err;
+	int handle;
+	struct tpm_private *tp = tpm_private_get();
+
+	if (!tp)
+		return -ENOMEM;
+
+	tp->chip = init_vtpm(&dev->dev, tp);
+	if (IS_ERR(tp->chip))
+		return PTR_ERR(tp->chip);
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+	                   "handle", "%i", &handle);
+	if (XENBUS_EXIST_ERR(err))
+		return err;
+
+	if (err < 0) {
+		xenbus_dev_fatal(dev,err,"reading virtual-device");
+		return err;
+	}
+
+	tp->dev = dev;
+
+	err = talk_to_backend(dev, tp);
+	if (err) {
+		tpm_private_put();
+		return err;
+	}
+
+	return 0;
+}
+
+
+static int tpmfront_remove(struct xenbus_device *dev)
+{
+	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
+	destroy_tpmring(tp);
+	cleanup_vtpm(&dev->dev);
+	return 0;
+}
+
+static int tpmfront_suspend(struct xenbus_device *dev)
+{
+	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
+	u32 ctr;
+
+	/* Take the lock, preventing any application from sending. */
+	mutex_lock(&suspend_lock);
+	tp->is_suspended = 1;
+
+	for (ctr = 0; atomic_read(&tp->tx_busy); ctr++) {
+		if ((ctr % 10) == 0)
+			printk("TPM-FE [INFO]: Waiting for outstanding "
+			       "request.\n");
+		/* Wait for a request to be responded to. */
+		interruptible_sleep_on_timeout(&tp->wait_q, 100);
+	}
+
+	return 0;
+}
+
+static int tpmfront_suspend_finish(struct tpm_private *tp)
+{
+	tp->is_suspended = 0;
+	/* Allow applications to send again. */
+	mutex_unlock(&suspend_lock);
+	return 0;
+}
+
+static int tpmfront_suspend_cancel(struct xenbus_device *dev)
+{
+	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
+	return tpmfront_suspend_finish(tp);
+}
+
+static int tpmfront_resume(struct xenbus_device *dev)
+{
+	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
+	destroy_tpmring(tp);
+	return talk_to_backend(dev, tp);
+}
+
+static int tpmif_connect(struct xenbus_device *dev,
+                         struct tpm_private *tp,
+                         domid_t domid)
+{
+	int err;
+
+	tp->backend_id = domid;
+
+	err = bind_listening_port_to_irqhandler(
+		domid, tpmif_int, IRQF_SAMPLE_RANDOM, "tpmif", tp);
+	if (err <= 0) {
+		WPRINTK("bind_listening_port_to_irqhandler failed "
+			"(err=%d)\n", err);
+		return err;
+	}
+	tp->irq = err;
+
+	return 0;
+}
+
+static struct xenbus_device_id tpmfront_ids[] = {
+	{ "vtpm" },
+	{ "" }
+};
+
+static struct xenbus_driver tpmfront = {
+	.name = "vtpm",
+	.ids = tpmfront_ids,
+	.probe = tpmfront_probe,
+	.remove =  tpmfront_remove,
+	.resume = tpmfront_resume,
+	.otherend_changed = backend_changed,
+	.suspend = tpmfront_suspend,
+	.suspend_cancel = tpmfront_suspend_cancel,
+};
+
+static int __init init_tpm_xenbus(void)
+{
+	return xenbus_register_frontend(&tpmfront);
+}
+
+static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
+{
+	unsigned int i;
+
+	for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
+		tp->tx_buffers[i] = tx_buffer_alloc();
+		if (!tp->tx_buffers[i]) {
+			tpmif_free_tx_buffers(tp);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static void tpmif_free_tx_buffers(struct tpm_private *tp)
+{
+	unsigned int i;
+
+	for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
+		tx_buffer_free(tp->tx_buffers[i]);
+}
+
+static void tpmif_rx_action(unsigned long priv)
+{
+	struct tpm_private *tp = (struct tpm_private *)priv;
+	int i = 0;
+	unsigned int received;
+	unsigned int offset = 0;
+	u8 *buffer;
+	tpmif_tx_request_t *tx = &tp->tx->ring[i].req;
+
+	atomic_set(&tp->tx_busy, 0);
+	wake_up_interruptible(&tp->wait_q);
+
+	received = tx->size;
+
+	buffer = kmalloc(received, GFP_ATOMIC);
+	if (!buffer)
+		return;
+
+	for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
+		struct tx_buffer *txb = tp->tx_buffers[i];
+		tpmif_tx_request_t *tx;
+		unsigned int tocopy;
+
+		tx = &tp->tx->ring[i].req;
+		tocopy = tx->size;
+		if (tocopy > PAGE_SIZE)
+			tocopy = PAGE_SIZE;
+
+		memcpy(&buffer[offset], txb->data, tocopy);
+
+		gnttab_release_grant_reference(&gref_head, tx->ref);
+
+		offset += tocopy;
+	}
+
+	vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
+	kfree(buffer);
+}
+
+
+static irqreturn_t tpmif_int(int irq, void *tpm_priv)
+{
+	struct tpm_private *tp = tpm_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->tx_lock, flags);
+	tpmif_rx_tasklet.data = (unsigned long)tp;
+	tasklet_schedule(&tpmif_rx_tasklet);
+	spin_unlock_irqrestore(&tp->tx_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+
+static int tpm_xmit(struct tpm_private *tp,
+                    const u8 * buf, size_t count, int isuserbuffer,
+                    void *remember)
+{
+	tpmif_tx_request_t *tx;
+	TPMIF_RING_IDX i;
+	unsigned int offset = 0;
+
+	spin_lock_irq(&tp->tx_lock);
+
+	if (unlikely(atomic_read(&tp->tx_busy))) {
+		printk("tpm_xmit: There's an outstanding request/response "
+		       "on the way!\n");
+		spin_unlock_irq(&tp->tx_lock);
+		return -EBUSY;
+	}
+
+	if (tp->is_connected != 1) {
+		spin_unlock_irq(&tp->tx_lock);
+		return -EIO;
+	}
+
+	for (i = 0; count > 0 && i < TPMIF_TX_RING_SIZE; i++) {
+		struct tx_buffer *txb = tp->tx_buffers[i];
+		int copied;
+
+		if (!txb) {
+			DPRINTK("txb (i=%d) is NULL. buffers initilized?\n"
+				"Not transmitting anything!\n", i);
+			spin_unlock_irq(&tp->tx_lock);
+			return -EFAULT;
+		}
+
+		copied = tx_buffer_copy(txb, &buf[offset], count,
+		                        isuserbuffer);
+		if (copied < 0) {
+			/* An error occurred */
+			spin_unlock_irq(&tp->tx_lock);
+			return copied;
+		}
+		count -= copied;
+		offset += copied;
+
+		tx = &tp->tx->ring[i].req;
+		tx->addr = virt_to_machine(txb->data);
+		tx->size = txb->len;
+		tx->unused = 0;
+
+		DPRINTK("First 4 characters sent by TPM-FE are "
+			"0x%02x 0x%02x 0x%02x 0x%02x\n",
+		        txb->data[0],txb->data[1],txb->data[2],txb->data[3]);
+
+		/* Get the granttable reference for this page. */
+		tx->ref = gnttab_claim_grant_reference(&gref_head);
+		if (tx->ref == -ENOSPC) {
+			spin_unlock_irq(&tp->tx_lock);
+			DPRINTK("Grant table claim reference failed in "
+				"func:%s line:%d file:%s\n",
+				__FUNCTION__, __LINE__, __FILE__);
+			return -ENOSPC;
+		}
+		gnttab_grant_foreign_access_ref(tx->ref,
+						tp->backend_id,
+						virt_to_mfn(txb->data),
+						0 /*RW*/);
+		wmb();
+	}
+
+	atomic_set(&tp->tx_busy, 1);
+	tp->tx_remember = remember;
+
+	mb();
+
+	notify_remote_via_irq(tp->irq);
+
+	spin_unlock_irq(&tp->tx_lock);
+	return offset;
+}
+
+
+static void tpmif_notify_upperlayer(struct tpm_private *tp)
+{
+	/* Notify upper layer about the state of the connection to the BE. */
+	vtpm_vd_status(tp->chip, (tp->is_connected
+				  ? TPM_VD_STATUS_CONNECTED
+				  : TPM_VD_STATUS_DISCONNECTED));
+}
+
+
+static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
+{
+	/*
+	 * Don't notify upper layer if we are in suspend mode and
+	 * should disconnect - assumption is that we will resume
+	 * The mutex keeps apps from sending.
+	 */
+	if (is_connected == 0 && tp->is_suspended == 1)
+		return;
+
+	/*
+	 * Unlock the mutex if we are connected again
+	 * after being suspended - now resuming.
+	 * This also removes the suspend state.
+	 */
+	if (is_connected == 1 && tp->is_suspended == 1)
+		tpmfront_suspend_finish(tp);
+
+	if (is_connected != tp->is_connected) {
+		tp->is_connected = is_connected;
+		tpmif_notify_upperlayer(tp);
+	}
+}
+
+
+
+/* =================================================================
+ * Initialization function.
+ * =================================================================
+ */
+
+
+static int __init tpmif_init(void)
+{
+	struct tpm_private *tp;
+
+	if (is_initial_xendomain())
+		return -EPERM;
+
+	tp = tpm_private_get();
+	if (!tp)
+		return -ENOMEM;
+
+	IPRINTK("Initialising the vTPM driver.\n");
+	if (gnttab_alloc_grant_references(TPMIF_TX_RING_SIZE,
+					  &gref_head) < 0) {
+		tpm_private_put();
+		return -EFAULT;
+	}
+
+	init_tpm_xenbus();
+	return 0;
+}
+
+
+module_init(tpmif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/char/tpm/Kconfig
+++ linux-ec2-2.6.32/drivers/char/tpm/Kconfig
@@ -58,4 +58,13 @@
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.prosec.rub.de/tpm
 
+config TCG_XEN
+	tristate "XEN TPM Interface"
+	depends on XEN
+	---help---
+	  If you want to make TPM support available to a Xen user domain,
+	  say Yes and it will be accessible from within Linux.
+	  To compile this driver as a module, choose M here; the module
+	  will be called tpm_xenu.
+
 endif # TCG_TPM
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm_vtpm.c
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm_vtpm.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * Authors:
+ * Stefan Berger <stefanb@us.ibm.com>
+ *
+ * Generic device driver part for device drivers in a virtualized
+ * environment.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include "tpm.h"
+#include "tpm_vtpm.h"
+
+/* read status bits */
+enum {
+	STATUS_BUSY = 0x01,
+	STATUS_DATA_AVAIL = 0x02,
+	STATUS_READY = 0x04
+};
+
+struct transmission {
+	struct list_head next;
+
+	unsigned char *request;
+	size_t  request_len;
+	size_t  request_buflen;
+
+	unsigned char *response;
+	size_t  response_len;
+	size_t  response_buflen;
+
+	unsigned int flags;
+};
+
+enum {
+	TRANSMISSION_FLAG_WAS_QUEUED = 0x1
+};
+
+
+enum {
+	DATAEX_FLAG_QUEUED_ONLY = 0x1
+};
+
+
+/* local variables */
+
+/* local function prototypes */
+static int _vtpm_send_queued(struct tpm_chip *chip);
+
+
+/* =============================================================
+ * Some utility functions
+ * =============================================================
+ */
+static void vtpm_state_init(struct vtpm_state *vtpms)
+{
+	vtpms->current_request = NULL;
+	spin_lock_init(&vtpms->req_list_lock);
+	init_waitqueue_head(&vtpms->req_wait_queue);
+	INIT_LIST_HEAD(&vtpms->queued_requests);
+
+	vtpms->current_response = NULL;
+	spin_lock_init(&vtpms->resp_list_lock);
+	init_waitqueue_head(&vtpms->resp_wait_queue);
+
+	vtpms->disconnect_time = jiffies;
+}
+
+
+static inline struct transmission *transmission_alloc(void)
+{
+	return kzalloc(sizeof(struct transmission), GFP_ATOMIC);
+}
+
+static unsigned char *
+transmission_set_req_buffer(struct transmission *t,
+                            unsigned char *buffer, size_t len)
+{
+	if (t->request_buflen < len) {
+		kfree(t->request);
+		t->request = kmalloc(len, GFP_KERNEL);
+		if (!t->request) {
+			t->request_buflen = 0;
+			return NULL;
+		}
+		t->request_buflen = len;
+	}
+
+	memcpy(t->request, buffer, len);
+	t->request_len = len;
+
+	return t->request;
+}
+
+static unsigned char *
+transmission_set_res_buffer(struct transmission *t,
+                            const unsigned char *buffer, size_t len)
+{
+	if (t->response_buflen < len) {
+		kfree(t->response);
+		t->response = kmalloc(len, GFP_ATOMIC);
+		if (!t->response) {
+			t->response_buflen = 0;
+			return NULL;
+		}
+		t->response_buflen = len;
+	}
+
+	memcpy(t->response, buffer, len);
+	t->response_len = len;
+
+	return t->response;
+}
+
+static inline void transmission_free(struct transmission *t)
+{
+	kfree(t->request);
+	kfree(t->response);
+	kfree(t);
+}
+
+/* =============================================================
+ * Interface with the lower layer driver
+ * =============================================================
+ */
+/*
+ * Lower layer uses this function to make a response available.
+ */
+int vtpm_vd_recv(const struct tpm_chip *chip,
+                 const unsigned char *buffer, size_t count,
+                 void *ptr)
+{
+	unsigned long flags;
+	int ret_size = 0;
+	struct transmission *t;
+	struct vtpm_state *vtpms;
+
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	/*
+	 * The list with requests must contain one request
+	 * only and the element there must be the one that
+	 * was passed to me from the front-end.
+	 */
+	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
+	if (vtpms->current_request != ptr) {
+		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+		return 0;
+	}
+
+	if ((t = vtpms->current_request)) {
+		transmission_free(t);
+		vtpms->current_request = NULL;
+	}
+
+	t = transmission_alloc();
+	if (t) {
+		if (!transmission_set_res_buffer(t, buffer, count)) {
+			transmission_free(t);
+			spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+			return -ENOMEM;
+		}
+		ret_size = count;
+		vtpms->current_response = t;
+		wake_up_interruptible(&vtpms->resp_wait_queue);
+	}
+	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+
+	return ret_size;
+}
+
+
+/*
+ * Lower layer indicates its status (connected/disconnected)
+ */
+void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status)
+{
+	struct vtpm_state *vtpms;
+
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	vtpms->vd_status = vd_status;
+	if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
+		vtpms->disconnect_time = jiffies;
+	}
+}
+
+/* =============================================================
+ * Interface with the generic TPM driver
+ * =============================================================
+ */
+static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int rc = 0;
+	unsigned long flags;
+	struct vtpm_state *vtpms;
+
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	/*
+	 * Check if the previous operation only queued the command
+	 * In this case there won't be a response, so I just
+	 * return from here and reset that flag. In any other
+	 * case I should receive a response from the back-end.
+	 */
+	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
+	if ((vtpms->flags & DATAEX_FLAG_QUEUED_ONLY) != 0) {
+		vtpms->flags &= ~DATAEX_FLAG_QUEUED_ONLY;
+		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+		/*
+		 * The first few commands (measurements) must be
+		 * queued since it might not be possible to talk to the
+		 * TPM, yet.
+		 * Return a response of up to 30 '0's.
+		 */
+
+		count = min_t(size_t, count, 30);
+		memset(buf, 0x0, count);
+		return count;
+	}
+	/*
+	 * Check whether something is in the responselist and if
+	 * there's nothing in the list wait for something to appear.
+	 */
+
+	if (!vtpms->current_response) {
+		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+		interruptible_sleep_on_timeout(&vtpms->resp_wait_queue,
+		                               1000);
+		spin_lock_irqsave(&vtpms->resp_list_lock ,flags);
+	}
+
+	if (vtpms->current_response) {
+		struct transmission *t = vtpms->current_response;
+		vtpms->current_response = NULL;
+		rc = min(count, t->response_len);
+		memcpy(buf, t->response, rc);
+		transmission_free(t);
+	}
+
+	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+	return rc;
+}
+
+static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int rc = 0;
+	unsigned long flags;
+	struct transmission *t = transmission_alloc();
+	struct vtpm_state *vtpms;
+
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	if (!t)
+		return -ENOMEM;
+	/*
+	 * If there's a current request, it must be the
+	 * previous request that has timed out.
+	 */
+	spin_lock_irqsave(&vtpms->req_list_lock, flags);
+	if (vtpms->current_request != NULL) {
+		printk("WARNING: Sending although there is a request outstanding.\n"
+		       "         Previous request must have timed out.\n");
+		transmission_free(vtpms->current_request);
+		vtpms->current_request = NULL;
+	}
+	spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
+
+	/*
+	 * Queue the packet if the driver below is not
+	 * ready, yet, or there is any packet already
+	 * in the queue.
+	 * If the driver below is ready, unqueue all
+	 * packets first before sending our current
+	 * packet.
+	 * For each unqueued packet, except for the
+	 * last (=current) packet, call the function
+	 * tpm_xen_recv to wait for the response to come
+	 * back.
+	 */
+	if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
+		if (time_after(jiffies,
+		               vtpms->disconnect_time + HZ * 10)) {
+			rc = -ENOENT;
+		} else {
+			goto queue_it;
+		}
+	} else {
+		/*
+		 * Send all queued packets.
+		 */
+		if (_vtpm_send_queued(chip) == 0) {
+
+			vtpms->current_request = t;
+
+			rc = vtpm_vd_send(vtpms->tpm_private,
+			                  buf,
+			                  count,
+			                  t);
+			/*
+			 * The generic TPM driver will call
+			 * the function to receive the response.
+			 */
+			if (rc < 0) {
+				vtpms->current_request = NULL;
+				goto queue_it;
+			}
+		} else {
+queue_it:
+			if (!transmission_set_req_buffer(t, buf, count)) {
+				transmission_free(t);
+				rc = -ENOMEM;
+				goto exit;
+			}
+			/*
+			 * An error occurred. Don't event try
+			 * to send the current request. Just
+			 * queue it.
+			 */
+			spin_lock_irqsave(&vtpms->req_list_lock, flags);
+			vtpms->flags |= DATAEX_FLAG_QUEUED_ONLY;
+			list_add_tail(&t->next, &vtpms->queued_requests);
+			spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
+		}
+	}
+
+exit:
+	return rc;
+}
+
+
+/*
+ * Send all queued requests.
+ */
+static int _vtpm_send_queued(struct tpm_chip *chip)
+{
+	int rc;
+	int error = 0;
+	unsigned long flags;
+	unsigned char buffer[1];
+	struct vtpm_state *vtpms;
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	spin_lock_irqsave(&vtpms->req_list_lock, flags);
+
+	while (!list_empty(&vtpms->queued_requests)) {
+		/*
+		 * Need to dequeue them.
+		 * Read the result into a dummy buffer.
+		 */
+		struct transmission *qt = (struct transmission *)
+		                          vtpms->queued_requests.next;
+		list_del(&qt->next);
+		vtpms->current_request = qt;
+		spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
+
+		rc = vtpm_vd_send(vtpms->tpm_private,
+		                  qt->request,
+		                  qt->request_len,
+		                  qt);
+
+		if (rc < 0) {
+			spin_lock_irqsave(&vtpms->req_list_lock, flags);
+			if ((qt = vtpms->current_request) != NULL) {
+				/*
+				 * requeue it at the beginning
+				 * of the list
+				 */
+				list_add(&qt->next,
+				         &vtpms->queued_requests);
+			}
+			vtpms->current_request = NULL;
+			error = 1;
+			break;
+		}
+		/*
+		 * After this point qt is not valid anymore!
+		 * It is freed when the front-end is delivering
+		 * the data by calling tpm_recv
+		 */
+		/*
+		 * Receive response into provided dummy buffer
+		 */
+		rc = vtpm_recv(chip, buffer, sizeof(buffer));
+		spin_lock_irqsave(&vtpms->req_list_lock, flags);
+	}
+
+	spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
+
+	return error;
+}
+
+static void vtpm_cancel(struct tpm_chip *chip)
+{
+	unsigned long flags;
+	struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	spin_lock_irqsave(&vtpms->resp_list_lock,flags);
+
+	if (!vtpms->current_response && vtpms->current_request) {
+		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+		interruptible_sleep_on(&vtpms->resp_wait_queue);
+		spin_lock_irqsave(&vtpms->resp_list_lock,flags);
+	}
+
+	if (vtpms->current_response) {
+		struct transmission *t = vtpms->current_response;
+		vtpms->current_response = NULL;
+		transmission_free(t);
+	}
+
+	spin_unlock_irqrestore(&vtpms->resp_list_lock,flags);
+}
+
+static u8 vtpm_status(struct tpm_chip *chip)
+{
+	u8 rc = 0;
+	unsigned long flags;
+	struct vtpm_state *vtpms;
+
+	vtpms = (struct vtpm_state *)chip_get_private(chip);
+
+	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
+	/*
+	 * Data are available if:
+	 *  - there's a current response
+	 *  - the last packet was queued only (this is fake, but necessary to
+	 *      get the generic TPM layer to call the receive function.)
+	 */
+	if (vtpms->current_response ||
+	    0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) {
+		rc = STATUS_DATA_AVAIL;
+	} else if (!vtpms->current_response && !vtpms->current_request) {
+		rc = STATUS_READY;
+	}
+
+	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+	return rc;
+}
+
+static struct file_operations vtpm_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+		   NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *vtpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	NULL,
+};
+
+static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs };
+
+#define TPM_LONG_TIMEOUT   (10 * 60 * HZ)
+
+static struct tpm_vendor_specific tpm_vtpm = {
+	.recv = vtpm_recv,
+	.send = vtpm_send,
+	.cancel = vtpm_cancel,
+	.status = vtpm_status,
+	.req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
+	.req_complete_val  = STATUS_DATA_AVAIL,
+	.req_canceled = STATUS_READY,
+	.attr_group = &vtpm_attr_grp,
+	.miscdev = {
+		.fops = &vtpm_ops,
+	},
+	.duration = {
+		TPM_LONG_TIMEOUT,
+		TPM_LONG_TIMEOUT,
+		TPM_LONG_TIMEOUT,
+	},
+};
+
+struct tpm_chip *init_vtpm(struct device *dev,
+                           struct tpm_private *tp)
+{
+	long rc;
+	struct tpm_chip *chip;
+	struct vtpm_state *vtpms;
+
+	vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL);
+	if (!vtpms)
+		return ERR_PTR(-ENOMEM);
+
+	vtpm_state_init(vtpms);
+	vtpms->tpm_private = tp;
+
+	chip = tpm_register_hardware(dev, &tpm_vtpm);
+	if (!chip) {
+		rc = -ENODEV;
+		goto err_free_mem;
+	}
+
+	chip_set_private(chip, vtpms);
+
+	return chip;
+
+err_free_mem:
+	kfree(vtpms);
+
+	return ERR_PTR(rc);
+}
+
+void cleanup_vtpm(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip);
+	tpm_remove_hardware(dev);
+	kfree(vtpms);
+}
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm_vtpm.h
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm_vtpm.h
@@ -0,0 +1,55 @@
+#ifndef TPM_VTPM_H
+#define TPM_VTPM_H
+
+struct tpm_chip;
+struct tpm_private;
+
+struct vtpm_state {
+	struct transmission *current_request;
+	spinlock_t           req_list_lock;
+	wait_queue_head_t    req_wait_queue;
+
+	struct list_head     queued_requests;
+
+	struct transmission *current_response;
+	spinlock_t           resp_list_lock;
+	wait_queue_head_t    resp_wait_queue;     // processes waiting for responses
+
+	u8                   vd_status;
+	u8                   flags;
+
+	unsigned long        disconnect_time;
+
+	/*
+	 * The following is a private structure of the underlying
+	 * driver. It is passed as parameter in the send function.
+	 */
+	struct tpm_private *tpm_private;
+};
+
+
+enum vdev_status {
+	TPM_VD_STATUS_DISCONNECTED = 0x0,
+	TPM_VD_STATUS_CONNECTED = 0x1
+};
+
+/* this function is called from tpm_vtpm.c */
+int vtpm_vd_send(struct tpm_private * tp,
+                 const u8 * buf, size_t count, void *ptr);
+
+/* these functions are offered by tpm_vtpm.c */
+struct tpm_chip *init_vtpm(struct device *,
+                           struct tpm_private *);
+void cleanup_vtpm(struct device *);
+int vtpm_vd_recv(const struct tpm_chip* chip,
+                 const unsigned char *buffer, size_t count, void *ptr);
+void vtpm_vd_status(const struct tpm_chip *, u8 status);
+
+static inline struct tpm_private *tpm_private_from_dev(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct vtpm_state *vtpms = chip_get_private(chip);
+	return vtpms->tpm_private;
+}
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm_tis.c
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm_tis.c
@@ -257,6 +257,10 @@
 	return size;
 }
 
+static int itpm;
+module_param(itpm, bool, 0444);
+MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
+
 /*
  * If interrupts are used (signaled by an irq set in the vendor structure)
  * tpm.c can skip polling for the data to be available as the interrupt is
@@ -293,7 +297,7 @@
 		wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
 			      &chip->vendor.int_queue);
 		status = tpm_tis_status(chip);
-		if ((status & TPM_STS_DATA_EXPECT) == 0) {
+		if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
 			rc = -EIO;
 			goto out_err;
 		}
@@ -350,6 +354,7 @@
 		   NULL);
 static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
 
 static struct attribute *tis_attrs[] = {
 	&dev_attr_pubek.attr,
@@ -359,7 +364,8 @@
 	&dev_attr_owned.attr,
 	&dev_attr_temp_deactivated.attr,
 	&dev_attr_caps.attr,
-	&dev_attr_cancel.attr, NULL,
+	&dev_attr_cancel.attr,
+	&dev_attr_timeouts.attr, NULL,
 };
 
 static struct attribute_group tis_attr_grp = {
@@ -467,6 +473,10 @@
 		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
 		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 
+	if (itpm)
+		dev_info(dev, "Intel iTPM workaround enabled\n");
+
+
 	/* Figure out the capabilities */
 	intfcaps =
 	    ioread32(chip->vendor.iobase +
@@ -614,7 +624,14 @@
 
 static int tpm_tis_pnp_resume(struct pnp_dev *dev)
 {
-	return tpm_pm_resume(&dev->dev);
+	struct tpm_chip *chip = pnp_get_drvdata(dev);
+	int ret;
+
+	ret = tpm_pm_resume(&dev->dev);
+	if (!ret)
+		tpm_continue_selftest(chip);
+
+	return ret;
 }
 
 static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
@@ -629,6 +646,7 @@
 	{"", 0},		/* User Specified */
 	{"", 0}			/* Terminator */
 };
+MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
 
 static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
 {
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm.h
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm.h
@@ -56,6 +56,8 @@
 				char *);
 extern ssize_t tpm_show_temp_deactivated(struct device *,
 					 struct device_attribute *attr, char *);
+extern ssize_t tpm_show_timeouts(struct device *,
+				 struct device_attribute *attr, char *);
 
 struct tpm_chip;
 
@@ -108,6 +110,9 @@
 	struct dentry **bios_dir;
 
 	struct list_head list;
+#ifdef CONFIG_XEN
+	void *priv;
+#endif
 	void (*release) (struct device *);
 };
 
@@ -224,6 +229,7 @@
 	u8	algorithm[4];
 	u8	encscheme[2];
 	u8	sigscheme[2];
+	__be32	paramsize;
 	u8	parameters[12]; /*assuming RSA*/
 	__be32	keysize;
 	u8	modulus[256];
@@ -266,6 +272,18 @@
 
 ssize_t	tpm_getcap(struct device *, __be32, cap_t *, const char *);
 
+#ifdef CONFIG_XEN
+static inline void *chip_get_private(const struct tpm_chip *chip)
+{
+	return chip->priv;
+}
+
+static inline void chip_set_private(struct tpm_chip *chip, void *priv)
+{
+	chip->priv = priv;
+}
+#endif
+
 extern void tpm_get_timeouts(struct tpm_chip *);
 extern void tpm_gen_interrupt(struct tpm_chip *);
 extern void tpm_continue_selftest(struct tpm_chip *);
--- linux-ec2-2.6.32.orig/drivers/char/tpm/tpm.c
+++ linux-ec2-2.6.32/drivers/char/tpm/tpm.c
@@ -353,12 +353,14 @@
 		    tpm_protected_ordinal_duration[ordinal &
 						   TPM_PROTECTED_ORDINAL_MASK];
 
-	if (duration_idx != TPM_UNDEFINED)
+	if (duration_idx != TPM_UNDEFINED) {
 		duration = chip->vendor.duration[duration_idx];
-	if (duration <= 0)
+		/* if duration is 0, it's because chip->vendor.duration wasn't */
+		/* filled yet, so we set the lowest timeout just to give enough */
+		/* time for tpm_get_timeouts() to succeed */
+		return (duration <= 0 ? HZ : duration);
+	} else
 		return 2 * 60 * HZ;
-	else
-		return duration;
 }
 EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
 
@@ -564,9 +566,11 @@
 	if (rc)
 		return;
 
-	if (be32_to_cpu(tpm_cmd.header.out.return_code)
-	    != 3 * sizeof(u32))
+	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
+	    be32_to_cpu(tpm_cmd.header.out.length)
+	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
 		return;
+
 	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
 	chip->vendor.duration[TPM_SHORT] =
 	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
@@ -910,6 +914,18 @@
 }
 EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
 
+ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d %d %d\n",
+	               jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
+	               jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
+	               jiffies_to_usecs(chip->vendor.duration[TPM_LONG]));
+}
+EXPORT_SYMBOL_GPL(tpm_show_timeouts);
+
 ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
@@ -953,7 +969,7 @@
 		return -EBUSY;
 	}
 
-	chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
 	if (chip->data_buffer == NULL) {
 		clear_bit(0, &chip->is_open);
 		put_device(chip->dev);
--- linux-ec2-2.6.32.orig/drivers/char/pcmcia/synclink_cs.c
+++ linux-ec2-2.6.32/drivers/char/pcmcia/synclink_cs.c
@@ -4164,6 +4164,8 @@
 	if (cmd != SIOCWANDEV)
 		return hdlc_ioctl(dev, ifr, cmd);
 
+	memset(&new_line, 0, size);
+
 	switch(ifr->ifr_settings.type) {
 	case IF_GET_IFACE: /* return current sync_serial_settings */
 
--- linux-ec2-2.6.32.orig/drivers/gpu/vga/vgaarb.c
+++ linux-ec2-2.6.32/drivers/gpu/vga/vgaarb.c
@@ -954,6 +954,7 @@
 		}
 
 	} else if (strncmp(curr_pos, "target ", 7) == 0) {
+		struct pci_bus *pbus;
 		unsigned int domain, bus, devfn;
 		struct vga_device *vgadev;
 
@@ -961,7 +962,7 @@
 		remaining -= 7;
 		pr_devel("client 0x%p called 'target'\n", priv);
 		/* if target is default */
-		if (!strncmp(buf, "default", 7))
+		if (!strncmp(curr_pos, "default", 7))
 			pdev = pci_dev_get(vga_default_device());
 		else {
 			if (!vga_pci_str_to_vars(curr_pos, remaining,
@@ -969,18 +970,31 @@
 				ret_val = -EPROTO;
 				goto done;
 			}
+			pr_devel("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
+				domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
-			pdev = pci_get_bus_and_slot(bus, devfn);
+			pbus = pci_find_bus(domain, bus);
+			pr_devel("vgaarb: pbus %p\n", pbus);
+			if (pbus == NULL) {
+				pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
+					domain, bus);
+				ret_val = -ENODEV;
+				goto done;
+			}
+			pdev = pci_get_slot(pbus, devfn);
+			pr_devel("vgaarb: pdev %p\n", pdev);
 			if (!pdev) {
-				pr_info("vgaarb: invalid PCI address!\n");
+				pr_err("vgaarb: invalid PCI address %x:%x\n",
+					bus, devfn);
 				ret_val = -ENODEV;
 				goto done;
 			}
 		}
 
 		vgadev = vgadev_find(pdev);
+		pr_devel("vgaarb: vgadev %p\n", vgadev);
 		if (vgadev == NULL) {
-			pr_info("vgaarb: this pci device is not a vga device\n");
+			pr_err("vgaarb: this pci device is not a vga device\n");
 			pci_dev_put(pdev);
 			ret_val = -ENODEV;
 			goto done;
@@ -998,7 +1012,8 @@
 			}
 		}
 		if (i == MAX_USER_CARDS) {
-			pr_err("vgaarb: maximum user cards number reached!\n");
+			pr_err("vgaarb: maximum user cards (%d) number reached!\n",
+				MAX_USER_CARDS);
 			pci_dev_put(pdev);
 			/* XXX: which value to return? */
 			ret_val =  -ENOMEM;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_ioc32.c
@@ -104,7 +104,7 @@
 			  &version->desc))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
+	err = drm_ioctl(file,
 			DRM_IOCTL_VERSION, (unsigned long)version);
 	if (err)
 		return err;
@@ -145,8 +145,7 @@
 			  &u->unique))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
+	err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
 	if (err)
 		return err;
 
@@ -174,8 +173,7 @@
 			  &u->unique))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
+	return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
 }
 
 typedef struct drm_map32 {
@@ -205,8 +203,7 @@
 	if (__put_user(idx, &map->offset))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_GET_MAP, (unsigned long)map);
+	err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map);
 	if (err)
 		return err;
 
@@ -246,8 +243,7 @@
 	    || __put_user(m32.flags, &map->flags))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_ADD_MAP, (unsigned long)map);
+	err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
 	if (err)
 		return err;
 
@@ -284,8 +280,7 @@
 	if (__put_user((void *)(unsigned long)handle, &map->handle))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RM_MAP, (unsigned long)map);
+	return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
 }
 
 typedef struct drm_client32 {
@@ -314,8 +309,7 @@
 	if (__put_user(idx, &client->idx))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_GET_CLIENT, (unsigned long)client);
+	err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
 	if (err)
 		return err;
 
@@ -351,8 +345,7 @@
 	if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_GET_STATS, (unsigned long)stats);
+	err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
 	if (err)
 		return err;
 
@@ -395,8 +388,7 @@
 	    || __put_user(agp_start, &buf->agp_start))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
+	err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
 	if (err)
 		return err;
 
@@ -427,8 +419,7 @@
 	    || __put_user(b32.high_mark, &buf->high_mark))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
+	return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
 }
 
 typedef struct drm_buf_info32 {
@@ -469,8 +460,7 @@
 	    || __put_user(list, &request->list))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_INFO_BUFS, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
 	if (err)
 		return err;
 
@@ -531,8 +521,7 @@
 	    || __put_user(list, &request->list))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_MAP_BUFS, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
 	if (err)
 		return err;
 
@@ -578,8 +567,7 @@
 			  &request->list))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_FREE_BUFS, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
 }
 
 typedef struct drm_ctx_priv_map32 {
@@ -605,8 +593,7 @@
 			  &request->handle))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
 }
 
 static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
@@ -628,8 +615,7 @@
 	if (__put_user(ctx_id, &request->ctx_id))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
 	if (err)
 		return err;
 
@@ -664,8 +650,7 @@
 			  &res->contexts))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_RES_CTX, (unsigned long)res);
+	err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
 	if (err)
 		return err;
 
@@ -718,8 +703,7 @@
 			  &d->request_sizes))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_DMA, (unsigned long)d);
+	err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
 	if (err)
 		return err;
 
@@ -751,8 +735,7 @@
 	if (put_user(m32.mode, &mode->mode))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
+	return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
 }
 
 typedef struct drm_agp_info32 {
@@ -781,8 +764,7 @@
 	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_AGP_INFO, (unsigned long)info);
+	err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
 	if (err)
 		return err;
 
@@ -827,16 +809,14 @@
 	    || __put_user(req32.type, &request->type))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
 	if (err)
 		return err;
 
 	if (__get_user(req32.handle, &request->handle)
 	    || __get_user(req32.physical, &request->physical)
 	    || copy_to_user(argp, &req32, sizeof(req32))) {
-		drm_ioctl(file->f_path.dentry->d_inode, file,
-			  DRM_IOCTL_AGP_FREE, (unsigned long)request);
+		drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
 		return -EFAULT;
 	}
 
@@ -856,8 +836,7 @@
 	    || __put_user(handle, &request->handle))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_AGP_FREE, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
 }
 
 typedef struct drm_agp_binding32 {
@@ -881,8 +860,7 @@
 	    || __put_user(req32.offset, &request->offset))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_AGP_BIND, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
 }
 
 static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
@@ -898,8 +876,7 @@
 	    || __put_user(handle, &request->handle))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
 }
 #endif				/* __OS_HAS_AGP */
 
@@ -923,8 +900,7 @@
 	    || __put_user(x, &request->size))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_SG_ALLOC, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
 	if (err)
 		return err;
 
@@ -950,8 +926,7 @@
 	    || __put_user(x << PAGE_SHIFT, &request->handle))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_SG_FREE, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
 }
 
 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
@@ -981,8 +956,7 @@
 	    __put_user(update32.data, &request->data))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
 	return err;
 }
 #endif
@@ -1023,8 +997,7 @@
 	    || __put_user(req32.request.signal, &request->request.signal))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
+	err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
 	if (err)
 		return err;
 
@@ -1094,16 +1067,14 @@
 	 * than always failing.
 	 */
 	if (nr >= ARRAY_SIZE(drm_compat_ioctls))
-		return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+		return drm_ioctl(filp, cmd, arg);
 
 	fn = drm_compat_ioctls[nr];
 
-	lock_kernel();		/* XXX for now */
 	if (fn != NULL)
 		ret = (*fn) (filp, cmd, arg);
 	else
-		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+		ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_stub.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_stub.c
@@ -128,6 +128,7 @@
 	kref_get(&master->refcount);
 	return master;
 }
+EXPORT_SYMBOL(drm_master_get);
 
 static void drm_master_destroy(struct kref *kref)
 {
@@ -170,10 +171,13 @@
 	kref_put(&(*master)->refcount, drm_master_destroy);
 	*master = NULL;
 }
+EXPORT_SYMBOL(drm_master_put);
 
 int drm_setmaster_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv)
 {
+	int ret = 0;
+
 	if (file_priv->is_master)
 		return 0;
 
@@ -188,6 +192,13 @@
 		mutex_lock(&dev->struct_mutex);
 		file_priv->minor->master = drm_master_get(file_priv->master);
 		file_priv->is_master = 1;
+		if (dev->driver->master_set) {
+			ret = dev->driver->master_set(dev, file_priv, false);
+			if (unlikely(ret != 0)) {
+				file_priv->is_master = 0;
+				drm_master_put(&file_priv->minor->master);
+			}
+		}
 		mutex_unlock(&dev->struct_mutex);
 	}
 
@@ -204,6 +215,8 @@
 		return -EINVAL;
 
 	mutex_lock(&dev->struct_mutex);
+	if (dev->driver->master_drop)
+		dev->driver->master_drop(dev, file_priv, false);
 	drm_master_put(&file_priv->minor->master);
 	file_priv->is_master = 0;
 	mutex_unlock(&dev->struct_mutex);
@@ -220,9 +233,11 @@
 	INIT_LIST_HEAD(&dev->ctxlist);
 	INIT_LIST_HEAD(&dev->vmalist);
 	INIT_LIST_HEAD(&dev->maplist);
+	INIT_LIST_HEAD(&dev->vblank_event_list);
 
 	spin_lock_init(&dev->count_lock);
 	spin_lock_init(&dev->drw_lock);
+	spin_lock_init(&dev->event_lock);
 	init_timer(&dev->timer);
 	mutex_init(&dev->struct_mutex);
 	mutex_init(&dev->ctxlist_mutex);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_gem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_gem.c
@@ -142,19 +142,6 @@
 	if (IS_ERR(obj->filp))
 		goto free;
 
-	/* Basically we want to disable the OOM killer and handle ENOMEM
-	 * ourselves by sacrificing pages from cached buffers.
-	 * XXX shmem_file_[gs]et_gfp_mask()
-	 */
-	mapping_set_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping,
-			     GFP_HIGHUSER |
-			     __GFP_COLD |
-			     __GFP_FS |
-			     __GFP_RECLAIMABLE |
-			     __GFP_NORETRY |
-			     __GFP_NOWARN |
-			     __GFP_NOMEMALLOC);
-
 	kref_init(&obj->refcount);
 	kref_init(&obj->handlecount);
 	obj->size = size;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_fops.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_fops.c
@@ -140,14 +140,16 @@
 		spin_unlock(&dev->count_lock);
 	}
 out:
-	mutex_lock(&dev->struct_mutex);
-	if (minor->type == DRM_MINOR_LEGACY) {
-		BUG_ON((dev->dev_mapping != NULL) &&
-			(dev->dev_mapping != inode->i_mapping));
-		if (dev->dev_mapping == NULL)
-			dev->dev_mapping = inode->i_mapping;
+	if (!retcode) {
+		mutex_lock(&dev->struct_mutex);
+		if (minor->type == DRM_MINOR_LEGACY) {
+			if (dev->dev_mapping == NULL)
+				dev->dev_mapping = inode->i_mapping;
+			else if (dev->dev_mapping != inode->i_mapping)
+				retcode = -ENODEV;
+		}
+		mutex_unlock(&dev->struct_mutex);
 	}
-	mutex_unlock(&dev->struct_mutex);
 
 	return retcode;
 }
@@ -257,6 +259,9 @@
 
 	INIT_LIST_HEAD(&priv->lhead);
 	INIT_LIST_HEAD(&priv->fbs);
+	INIT_LIST_HEAD(&priv->event_list);
+	init_waitqueue_head(&priv->event_wait);
+	priv->event_space = 4096; /* set aside 4k for event buffer */
 
 	if (dev->driver->driver_features & DRIVER_GEM)
 		drm_gem_open(dev, priv);
@@ -297,6 +302,18 @@
 				goto out_free;
 			}
 		}
+		mutex_lock(&dev->struct_mutex);
+		if (dev->driver->master_set) {
+			ret = dev->driver->master_set(dev, priv, true);
+			if (ret) {
+				/* drop both references if this fails */
+				drm_master_put(&priv->minor->master);
+				drm_master_put(&priv->master);
+				mutex_unlock(&dev->struct_mutex);
+				goto out_free;
+			}
+		}
+		mutex_unlock(&dev->struct_mutex);
 	} else {
 		/* get a reference to the master */
 		priv->master = drm_master_get(priv->minor->master);
@@ -413,6 +430,30 @@
 	}
 }
 
+static void drm_events_release(struct drm_file *file_priv)
+{
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_pending_event *e, *et;
+	struct drm_pending_vblank_event *v, *vt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	/* Remove pending flips */
+	list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
+		if (v->base.file_priv == file_priv) {
+			list_del(&v->base.link);
+			drm_vblank_put(dev, v->pipe);
+			v->base.destroy(&v->base);
+		}
+
+	/* Remove unconsumed events */
+	list_for_each_entry_safe(e, et, &file_priv->event_list, link)
+		e->destroy(e);
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
 /**
  * Release file.
  *
@@ -451,6 +492,8 @@
 	if (file_priv->minor->master)
 		drm_master_release(dev, filp);
 
+	drm_events_release(file_priv);
+
 	if (dev->driver->driver_features & DRIVER_GEM)
 		drm_gem_release(dev, file_priv);
 
@@ -504,6 +547,8 @@
 
 		if (file_priv->minor->master == file_priv->master) {
 			/* drop the reference held my the minor */
+			if (dev->driver->master_drop)
+				dev->driver->master_drop(dev, file_priv, true);
 			drm_master_put(&file_priv->minor->master);
 		}
 	}
@@ -544,9 +589,74 @@
 }
 EXPORT_SYMBOL(drm_release);
 
-/** No-op. */
+static bool
+drm_dequeue_event(struct drm_file *file_priv,
+		  size_t total, size_t max, struct drm_pending_event **out)
+{
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_pending_event *e;
+	unsigned long flags;
+	bool ret = false;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	*out = NULL;
+	if (list_empty(&file_priv->event_list))
+		goto out;
+	e = list_first_entry(&file_priv->event_list,
+			     struct drm_pending_event, link);
+	if (e->event->length + total > max)
+		goto out;
+
+	file_priv->event_space += e->event->length;
+	list_del(&e->link);
+	*out = e;
+	ret = true;
+
+out:
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	return ret;
+}
+
+ssize_t drm_read(struct file *filp, char __user *buffer,
+		 size_t count, loff_t *offset)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_pending_event *e;
+	size_t total;
+	ssize_t ret;
+
+	ret = wait_event_interruptible(file_priv->event_wait,
+				       !list_empty(&file_priv->event_list));
+	if (ret < 0)
+		return ret;
+
+	total = 0;
+	while (drm_dequeue_event(file_priv, total, count, &e)) {
+		if (copy_to_user(buffer + total,
+				 e->event, e->event->length)) {
+			total = -EFAULT;
+			break;
+		}
+
+		total += e->event->length;
+		e->destroy(e);
+	}
+
+	return total;
+}
+EXPORT_SYMBOL(drm_read);
+
 unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
 {
-	return 0;
+	struct drm_file *file_priv = filp->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(filp, &file_priv->event_wait, wait);
+
+	if (!list_empty(&file_priv->event_list))
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
 }
 EXPORT_SYMBOL(drm_poll);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/Makefile
@@ -15,7 +15,7 @@
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
-drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o
+drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 
@@ -30,4 +30,7 @@
 obj-$(CONFIG_DRM_I915)  += i915/
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
+obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VIA)	+=via/
+obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+obj-y			+= i2c/
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_crtc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_crtc.c
@@ -125,6 +125,15 @@
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
+static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
+	{ DRM_MODE_DIRTY_OFF,      "Off"      },
+	{ DRM_MODE_DIRTY_ON,       "On"       },
+	{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
+};
+
+DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
+		 drm_dirty_info_enum_list)
+
 struct drm_conn_prop_enum_list {
 	int type;
 	char *name;
@@ -144,11 +153,12 @@
 	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
 	{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
 	{ DRM_MODE_CONNECTOR_Component, "Component", 0 },
-	{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
-	{ DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
-	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
-	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
+	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+	{ DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
 	{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
+	{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -247,7 +257,8 @@
 	mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
-void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
+struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
+		uint32_t id, uint32_t type)
 {
 	struct drm_mode_object *obj = NULL;
 
@@ -272,7 +283,7 @@
  * functions & device file and adds it to the master fd list.
  *
  * RETURNS:
- * Zero on success, error code on falure.
+ * Zero on success, error code on failure.
  */
 int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
 			 const struct drm_framebuffer_funcs *funcs)
@@ -802,6 +813,36 @@
 EXPORT_SYMBOL(drm_mode_create_dithering_property);
 
 /**
+ * drm_mode_create_dirty_property - create dirty property
+ * @dev: DRM device
+ *
+ * Called by a driver the first time it's needed, must be attached to desired
+ * connectors.
+ */
+int drm_mode_create_dirty_info_property(struct drm_device *dev)
+{
+	struct drm_property *dirty_info;
+	int i;
+
+	if (dev->mode_config.dirty_info_property)
+		return 0;
+
+	dirty_info =
+		drm_property_create(dev, DRM_MODE_PROP_ENUM |
+				    DRM_MODE_PROP_IMMUTABLE,
+				    "dirty",
+				    ARRAY_SIZE(drm_dirty_info_enum_list));
+	for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
+		drm_property_add_enum(dirty_info, i,
+				      drm_dirty_info_enum_list[i].type,
+				      drm_dirty_info_enum_list[i].name);
+	dev->mode_config.dirty_info_property = dirty_info;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
+
+/**
  * drm_mode_config_init - initialize DRM mode_configuration structure
  * @dev: DRM device
  *
@@ -1753,6 +1794,71 @@
 	return ret;
 }
 
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	struct drm_clip_rect __user *clips_ptr;
+	struct drm_clip_rect *clips = NULL;
+	struct drm_mode_fb_dirty_cmd *r = data;
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb;
+	unsigned flags;
+	int num_clips;
+	int ret = 0;
+
+	mutex_lock(&dev->mode_config.mutex);
+	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj) {
+		DRM_ERROR("invalid framebuffer id\n");
+		ret = -EINVAL;
+		goto out_err1;
+	}
+	fb = obj_to_fb(obj);
+
+	num_clips = r->num_clips;
+	clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
+
+	if (!num_clips != !clips_ptr) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
+
+	/* If userspace annotates copy, clips must come in pairs */
+	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	if (num_clips && clips_ptr) {
+		clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
+		if (!clips) {
+			ret = -ENOMEM;
+			goto out_err1;
+		}
+
+		ret = copy_from_user(clips, clips_ptr,
+				     num_clips * sizeof(*clips));
+		if (ret)
+			goto out_err2;
+	}
+
+	if (fb->funcs->dirty) {
+		ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
+	} else {
+		ret = -ENOSYS;
+		goto out_err2;
+	}
+
+out_err2:
+	kfree(clips);
+out_err1:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+
 /**
  * drm_fb_release - remove and free the FBs on this file
  * @filp: file * from the ioctl
@@ -2328,7 +2434,7 @@
 	} else if (connector->funcs->set_property)
 		ret = connector->funcs->set_property(connector, property, out_resp->value);
 
-	/* store the property value if succesful */
+	/* store the property value if successful */
 	if (!ret)
 		drm_connector_property_set_value(connector, property, out_resp->value);
 out:
@@ -2478,3 +2584,72 @@
 	mutex_unlock(&dev->mode_config.mutex);
 	return ret;
 }
+
+int drm_mode_page_flip_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_crtc_page_flip *page_flip = data;
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	struct drm_framebuffer *fb;
+	struct drm_pending_vblank_event *e = NULL;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
+	    page_flip->reserved != 0)
+		return -EINVAL;
+
+	mutex_lock(&dev->mode_config.mutex);
+	obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
+	if (!obj)
+		goto out;
+	crtc = obj_to_crtc(obj);
+
+	if (crtc->funcs->page_flip == NULL)
+		goto out;
+
+	obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
+	if (!obj)
+		goto out;
+	fb = obj_to_fb(obj);
+
+	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+		ret = -ENOMEM;
+		spin_lock_irqsave(&dev->event_lock, flags);
+		if (file_priv->event_space < sizeof e->event) {
+			spin_unlock_irqrestore(&dev->event_lock, flags);
+			goto out;
+		}
+		file_priv->event_space -= sizeof e->event;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+
+		e = kzalloc(sizeof *e, GFP_KERNEL);
+		if (e == NULL) {
+			spin_lock_irqsave(&dev->event_lock, flags);
+			file_priv->event_space += sizeof e->event;
+			spin_unlock_irqrestore(&dev->event_lock, flags);
+			goto out;
+		}
+
+		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
+		e->event.base.length = sizeof e->event;
+		e->event.user_data = page_flip->user_data;
+		e->base.event = &e->event.base;
+		e->base.file_priv = file_priv;
+		e->base.destroy =
+			(void (*) (struct drm_pending_event *)) kfree;
+	}
+
+	ret = crtc->funcs->page_flip(crtc, fb, e);
+	if (ret) {
+		spin_lock_irqsave(&dev->event_lock, flags);
+		file_priv->event_space += sizeof e->event;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		kfree(e);
+	}
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_irq.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_irq.c
@@ -115,6 +115,7 @@
 
 	dev->num_crtcs = 0;
 }
+EXPORT_SYMBOL(drm_vblank_cleanup);
 
 int drm_vblank_init(struct drm_device *dev, int num_crtcs)
 {
@@ -163,7 +164,6 @@
 	}
 
 	dev->vblank_disable_allowed = 0;
-
 	return 0;
 
 err:
@@ -429,15 +429,21 @@
 
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	/* Going from 0->1 means we have to enable interrupts again */
-	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
-	    !dev->vblank_enabled[crtc]) {
-		ret = dev->driver->enable_vblank(dev, crtc);
-		DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
-		if (ret)
+	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
+		if (!dev->vblank_enabled[crtc]) {
+			ret = dev->driver->enable_vblank(dev, crtc);
+			DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
+			if (ret)
+				atomic_dec(&dev->vblank_refcount[crtc]);
+			else {
+				dev->vblank_enabled[crtc] = 1;
+				drm_update_vblank_count(dev, crtc);
+			}
+		}
+	} else {
+		if (!dev->vblank_enabled[crtc]) {
 			atomic_dec(&dev->vblank_refcount[crtc]);
-		else {
-			dev->vblank_enabled[crtc] = 1;
-			drm_update_vblank_count(dev, crtc);
+			ret = -EINVAL;
 		}
 	}
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -464,6 +470,18 @@
 }
 EXPORT_SYMBOL(drm_vblank_put);
 
+void drm_vblank_off(struct drm_device *dev, int crtc)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev->vbl_lock, irqflags);
+	DRM_WAKEUP(&dev->vbl_queue[crtc]);
+	dev->vblank_enabled[crtc] = 0;
+	dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc);
+	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+}
+EXPORT_SYMBOL(drm_vblank_off);
+
 /**
  * drm_vblank_pre_modeset - account for vblanks across mode sets
  * @dev: DRM device
@@ -475,6 +493,9 @@
  */
 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
 {
+	/* vblank is not initialized (IRQ not installed ?) */
+	if (!dev->num_crtcs)
+		return;
 	/*
 	 * To avoid all the problems that might happen if interrupts
 	 * were enabled/disabled around or between these calls, we just
@@ -522,7 +543,8 @@
 		    struct drm_file *file_priv)
 {
 	struct drm_modeset_ctl *modeset = data;
-	int crtc, ret = 0;
+	int ret = 0;
+	unsigned int crtc;
 
 	/* If drm_vblank_init() hasn't been called yet, just no-op */
 	if (!dev->num_crtcs)
@@ -550,6 +572,63 @@
 	return ret;
 }
 
+static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
+				  union drm_wait_vblank *vblwait,
+				  struct drm_file *file_priv)
+{
+	struct drm_pending_vblank_event *e;
+	struct timeval now;
+	unsigned long flags;
+	unsigned int seq;
+
+	e = kzalloc(sizeof *e, GFP_KERNEL);
+	if (e == NULL)
+		return -ENOMEM;
+
+	e->pipe = pipe;
+	e->event.base.type = DRM_EVENT_VBLANK;
+	e->event.base.length = sizeof e->event;
+	e->event.user_data = vblwait->request.signal;
+	e->base.event = &e->event.base;
+	e->base.file_priv = file_priv;
+	e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
+
+	do_gettimeofday(&now);
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	if (file_priv->event_space < sizeof e->event) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		kfree(e);
+		return -ENOMEM;
+	}
+
+	file_priv->event_space -= sizeof e->event;
+	seq = drm_vblank_count(dev, pipe);
+	if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
+	    (seq - vblwait->request.sequence) <= (1 << 23)) {
+		vblwait->request.sequence = seq + 1;
+		vblwait->reply.sequence = vblwait->request.sequence;
+	}
+
+	DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
+		  vblwait->request.sequence, seq, pipe);
+
+	e->event.sequence = vblwait->request.sequence;
+	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		drm_vblank_put(dev, e->pipe);
+		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	} else {
+		list_add_tail(&e->base.link, &dev->vblank_event_list);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	return 0;
+}
+
 /**
  * Wait for VBLANK.
  *
@@ -609,6 +688,9 @@
 		goto done;
 	}
 
+	if (flags & _DRM_VBLANK_EVENT)
+		return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+
 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
 	    (seq - vblwait->request.sequence) <= (1<<23)) {
 		vblwait->request.sequence = seq + 1;
@@ -641,6 +723,38 @@
 	return ret;
 }
 
+void drm_handle_vblank_events(struct drm_device *dev, int crtc)
+{
+	struct drm_pending_vblank_event *e, *t;
+	struct timeval now;
+	unsigned long flags;
+	unsigned int seq;
+
+	do_gettimeofday(&now);
+	seq = drm_vblank_count(dev, crtc);
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
+		if (e->pipe != crtc)
+			continue;
+		if ((seq - e->event.sequence) > (1<<23))
+			continue;
+
+		DRM_DEBUG("vblank event on %d, current %d\n",
+			  e->event.sequence, seq);
+
+		e->event.sequence = seq;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		drm_vblank_put(dev, e->pipe);
+		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
 /**
  * drm_handle_vblank - handle a vblank event
  * @dev: DRM device
@@ -651,7 +765,11 @@
  */
 void drm_handle_vblank(struct drm_device *dev, int crtc)
 {
+	if (!dev->num_crtcs)
+		return;
+
 	atomic_inc(&dev->_vblank_count[crtc]);
 	DRM_WAKEUP(&dev->vbl_queue[crtc]);
+	drm_handle_vblank_events(dev, crtc);
 }
 EXPORT_SYMBOL(drm_handle_vblank);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_fb_helper.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_fb_helper.c
@@ -156,7 +156,7 @@
 			force = DRM_FORCE_ON;
 			break;
 		case 'D':
-			if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) ||
+			if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
 			    (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
 				force = DRM_FORCE_ON;
 			else
@@ -373,11 +373,9 @@
 					mutex_unlock(&dev->mode_config.mutex);
 				}
 			}
-			if (dpms_mode == DRM_MODE_DPMS_OFF) {
-				mutex_lock(&dev->mode_config.mutex);
-				crtc_funcs->dpms(crtc, dpms_mode);
-				mutex_unlock(&dev->mode_config.mutex);
-			}
+			mutex_lock(&dev->mode_config.mutex);
+			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+			mutex_unlock(&dev->mode_config.mutex);
 		}
 	}
 }
@@ -385,18 +383,23 @@
 int drm_fb_helper_blank(int blank, struct fb_info *info)
 {
 	switch (blank) {
+	/* Display: On; HSync: On, VSync: On */
 	case FB_BLANK_UNBLANK:
 		drm_fb_helper_on(info);
 		break;
+	/* Display: Off; HSync: On, VSync: On */
 	case FB_BLANK_NORMAL:
 		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
 		break;
+	/* Display: Off; HSync: Off, VSync: On */
 	case FB_BLANK_HSYNC_SUSPEND:
 		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
 		break;
+	/* Display: Off; HSync: On, VSync: Off */
 	case FB_BLANK_VSYNC_SUSPEND:
 		drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
 		break;
+	/* Display: Off; HSync: Off, VSync: Off */
 	case FB_BLANK_POWERDOWN:
 		drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
 		break;
@@ -603,11 +606,10 @@
 		return -EINVAL;
 
 	/* Need to resize the fb object !!! */
-	if (var->xres > fb->width || var->yres > fb->height) {
-		DRM_ERROR("Requested width/height is greater than current fb "
-			   "object %dx%d > %dx%d\n", var->xres, var->yres,
-			   fb->width, fb->height);
-		DRM_ERROR("Need resizing code.\n");
+	if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
+			  "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+			  fb->width, fb->height, fb->bits_per_pixel);
 		return -EINVAL;
 	}
 
@@ -905,8 +907,13 @@
 
 	if (new_fb) {
 		info->var.pixclock = 0;
-		if (register_framebuffer(info) < 0)
+		ret = fb_alloc_cmap(&info->cmap, modeset->crtc->gamma_size, 0);
+		if (ret)
+			return ret;
+		if (register_framebuffer(info) < 0) {
+			fb_dealloc_cmap(&info->cmap);
 			return -EINVAL;
+		}
 	} else {
 		drm_fb_helper_set_par(info);
 	}
@@ -936,6 +943,7 @@
 		unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
 	}
 	drm_fb_helper_crtc_free(helper);
+	fb_dealloc_cmap(&helper->fb->fbdev->cmap);
 }
 EXPORT_SYMBOL(drm_fb_helper_free);
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_modes.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_modes.c
@@ -1,9 +1,4 @@
 /*
- * The list_sort function is (presumably) licensed under the GPL (see the
- * top level "COPYING" file for details).
- *
- * The remainder of this file is:
- *
  * Copyright © 1997-2003 by The XFree86 Project, Inc.
  * Copyright © 2007 Dave Airlie
  * Copyright © 2007-2008 Intel Corporation
@@ -36,6 +31,7 @@
  */
 
 #include <linux/list.h>
+#include <linux/list_sort.h>
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
@@ -553,6 +549,32 @@
 }
 EXPORT_SYMBOL(drm_mode_height);
 
+/** drm_mode_hsync - get the hsync of a mode
+ * @mode: mode
+ *
+ * LOCKING:
+ * None.
+ *
+ * Return @modes's hsync rate in kHz, rounded to the nearest int.
+ */
+int drm_mode_hsync(struct drm_display_mode *mode)
+{
+	unsigned int calc_val;
+
+	if (mode->hsync)
+		return mode->hsync;
+
+	if (mode->htotal < 0)
+		return 0;
+
+	calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
+	calc_val += 500;				/* round to 1000Hz */
+	calc_val /= 1000;				/* truncate to kHz */
+
+	return calc_val;
+}
+EXPORT_SYMBOL(drm_mode_hsync);
+
 /**
  * drm_mode_vrefresh - get the vrefresh of a mode
  * @mode: mode
@@ -560,7 +582,7 @@
  * LOCKING:
  * None.
  *
- * Return @mode's vrefresh rate or calculate it if necessary.
+ * Return @mode's vrefresh rate in Hz or calculate it if necessary.
  *
  * FIXME: why is this needed?  shouldn't vrefresh be set already?
  *
@@ -829,6 +851,7 @@
 
 /**
  * drm_mode_compare - compare modes for favorability
+ * @priv: unused
  * @lh_a: list_head for first mode
  * @lh_b: list_head for second mode
  *
@@ -842,7 +865,7 @@
  * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
  * positive if @lh_b is better than @lh_a.
  */
-static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b)
+static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b)
 {
 	struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
 	struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
@@ -859,85 +882,6 @@
 	return diff;
 }
 
-/* FIXME: what we don't have a list sort function? */
-/* list sort from Mark J Roberts (mjr@znex.org) */
-void list_sort(struct list_head *head,
-	       int (*cmp)(struct list_head *a, struct list_head *b))
-{
-	struct list_head *p, *q, *e, *list, *tail, *oldhead;
-	int insize, nmerges, psize, qsize, i;
-
-	list = head->next;
-	list_del(head);
-	insize = 1;
-	for (;;) {
-		p = oldhead = list;
-		list = tail = NULL;
-		nmerges = 0;
-
-		while (p) {
-			nmerges++;
-			q = p;
-			psize = 0;
-			for (i = 0; i < insize; i++) {
-				psize++;
-				q = q->next == oldhead ? NULL : q->next;
-				if (!q)
-					break;
-			}
-
-			qsize = insize;
-			while (psize > 0 || (qsize > 0 && q)) {
-				if (!psize) {
-					e = q;
-					q = q->next;
-					qsize--;
-					if (q == oldhead)
-						q = NULL;
-				} else if (!qsize || !q) {
-					e = p;
-					p = p->next;
-					psize--;
-					if (p == oldhead)
-						p = NULL;
-				} else if (cmp(p, q) <= 0) {
-					e = p;
-					p = p->next;
-					psize--;
-					if (p == oldhead)
-						p = NULL;
-				} else {
-					e = q;
-					q = q->next;
-					qsize--;
-					if (q == oldhead)
-						q = NULL;
-				}
-				if (tail)
-					tail->next = e;
-				else
-					list = e;
-				e->prev = tail;
-				tail = e;
-			}
-			p = q;
-		}
-
-		tail->next = list;
-		list->prev = tail;
-
-		if (nmerges <= 1)
-			break;
-
-		insize *= 2;
-	}
-
-	head->next = list;
-	head->prev = list->prev;
-	list->prev->next = head;
-	list->prev = head;
-}
-
 /**
  * drm_mode_sort - sort mode list
  * @mode_list: list to sort
@@ -949,7 +893,7 @@
  */
 void drm_mode_sort(struct list_head *mode_list)
 {
-	list_sort(mode_list, drm_mode_compare);
+	list_sort(NULL, mode_list, drm_mode_compare);
 }
 EXPORT_SYMBOL(drm_mode_sort);
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/Kconfig
+++ linux-ec2-2.6.32/drivers/gpu/drm/Kconfig
@@ -66,6 +66,8 @@
 
 	  If M is selected, the module will be called radeon.
 
+source "drivers/gpu/drm/radeon/Kconfig"
+
 config DRM_I810
 	tristate "Intel I810"
 	depends on DRM && AGP && AGP_INTEL
@@ -92,7 +94,10 @@
 config DRM_I915
 	tristate "i915 driver"
 	depends on AGP_INTEL
+	# we need shmfs for the swappable backing store, and in particular
+	# the shmem_readpage() which depends upon tmpfs
 	select SHMEM
+	select TMPFS
 	select DRM_KMS_HELPER
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ati_pcigart.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ati_pcigart.c
@@ -39,8 +39,7 @@
 				       struct drm_ati_pcigart_info *gart_info)
 {
 	gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
-						PAGE_SIZE,
-						gart_info->table_mask);
+						PAGE_SIZE);
 	if (gart_info->table_handle == NULL)
 		return -ENOMEM;
 
@@ -112,6 +111,13 @@
 	if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
 		DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
 
+		if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) {
+			DRM_ERROR("fail to set dma mask to 0x%Lx\n",
+				  (unsigned long long)gart_info->table_mask);
+			ret = 1;
+			goto done;
+		}
+
 		ret = drm_ati_alloc_pcigart_table(dev, gart_info);
 		if (ret) {
 			DRM_ERROR("cannot allocate PCI GART page!\n");
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_drv.c
@@ -145,6 +145,8 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
@@ -366,6 +368,29 @@
 module_exit(drm_core_exit);
 
 /**
+ * Copy and IOCTL return string to user space
+ */
+static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
+{
+	int len;
+
+	/* don't overflow userbuf */
+	len = strlen(value);
+	if (len > *buf_len)
+		len = *buf_len;
+
+	/* let userspace know exact length of driver value (which could be
+	 * larger than the userspace-supplied buffer) */
+	*buf_len = strlen(value);
+
+	/* finally, try filling in the userbuf */
+	if (len && buf)
+		if (copy_to_user(buf, value, len))
+			return -EFAULT;
+	return 0;
+}
+
+/**
  * Get version information
  *
  * \param inode device inode.
@@ -380,16 +405,21 @@
 		       struct drm_file *file_priv)
 {
 	struct drm_version *version = data;
-	int len;
+	int err;
 
 	version->version_major = dev->driver->major;
 	version->version_minor = dev->driver->minor;
 	version->version_patchlevel = dev->driver->patchlevel;
-	DRM_COPY(version->name, dev->driver->name);
-	DRM_COPY(version->date, dev->driver->date);
-	DRM_COPY(version->desc, dev->driver->desc);
+	err = drm_copy_field(version->name, &version->name_len,
+			dev->driver->name);
+	if (!err)
+		err = drm_copy_field(version->date, &version->date_len,
+				dev->driver->date);
+	if (!err)
+		err = drm_copy_field(version->desc, &version->desc_len,
+				dev->driver->desc);
 
-	return 0;
+	return err;
 }
 
 /**
@@ -404,11 +434,11 @@
  * Looks up the ioctl function in the ::ioctls table, checking for root
  * previleges if so required, and dispatches to the respective function.
  */
-int drm_ioctl(struct inode *inode, struct file *filp,
+long drm_ioctl(struct file *filp,
 	      unsigned int cmd, unsigned long arg)
 {
 	struct drm_file *file_priv = filp->private_data;
-	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_device *dev;
 	struct drm_ioctl_desc *ioctl;
 	drm_ioctl_t *func;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -416,6 +446,7 @@
 	char stack_kdata[128];
 	char *kdata = NULL;
 
+	dev = file_priv->minor->dev;
 	atomic_inc(&dev->ioctl_count);
 	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
 	++file_priv->ioctl_count;
@@ -470,8 +501,16 @@
 				retcode = -EFAULT;
 				goto err_i1;
 			}
+		} else
+			memset(kdata, 0, _IOC_SIZE(cmd));
+
+		if (ioctl->flags & DRM_UNLOCKED)
+			retcode = func(dev, kdata, file_priv);
+		else {
+			lock_kernel();
+			retcode = func(dev, kdata, file_priv);
+			unlock_kernel();
 		}
-		retcode = func(dev, kdata, file_priv);
 
 		if (cmd & IOC_OUT) {
 			if (copy_to_user((void __user *)arg, kdata,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_bufs.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_bufs.c
@@ -326,7 +326,7 @@
 		 * As we're limiting the address to 2^32-1 (or less),
 		 * casting it down to 32 bits is no problem, but we
 		 * need to point to a 64bit variable first. */
-		dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+		dmah = drm_pci_alloc(dev, map->size, map->size);
 		if (!dmah) {
 			kfree(map);
 			return -ENOMEM;
@@ -885,7 +885,7 @@
 
 	while (entry->buf_count < count) {
 
-		dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
+		dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
 
 		if (!dmah) {
 			/* Set count correctly so we free the proper amount. */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_pci.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_pci.c
@@ -47,8 +47,7 @@
 /**
  * \brief Allocate a PCI consistent memory block, for DMA.
  */
-drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
-				dma_addr_t maxaddr)
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
 {
 	drm_dma_handle_t *dmah;
 #if 1
@@ -63,11 +62,6 @@
 	if (align > size)
 		return NULL;
 
-	if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
-		DRM_ERROR("Setting pci dma mask failed\n");
-		return NULL;
-	}
-
 	dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
 	if (!dmah)
 		return NULL;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_edid.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_edid.c
@@ -85,6 +85,8 @@
 
 	/* Envision Peripherals, Inc. EN-7100e */
 	{ "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH },
+	/* Envision EN2028 */
+	{ "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 },
 
 	/* Funai Electronics PM36B */
 	{ "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
@@ -123,18 +125,20 @@
  */
 static bool edid_is_valid(struct edid *edid)
 {
-	int i;
+	int i, score = 0;
 	u8 csum = 0;
 	u8 *raw_edid = (u8 *)edid;
 
-	if (memcmp(edid->header, edid_header, sizeof(edid_header)))
-		goto bad;
-	if (edid->version != 1) {
-		DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	if (score == 8) ;
+	else if (score >= 6) {
+		DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
+		memcpy(raw_edid, edid_header, sizeof(edid_header));
+	} else
 		goto bad;
-	}
-	if (edid->revision > 4)
-		DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
 
 	for (i = 0; i < EDID_LENGTH; i++)
 		csum += raw_edid[i];
@@ -143,6 +147,14 @@
 		goto bad;
 	}
 
+	if (edid->version != 1) {
+		DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
+		goto bad;
+	}
+
+	if (edid->revision > 4)
+		DRM_DEBUG("EDID minor > 4, assuming backward compatibility\n");
+
 	return 1;
 
 bad:
@@ -322,7 +334,7 @@
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 1024x768@85Hz */
 	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
-		   1072, 1376, 0, 768, 769, 772, 808, 0,
+		   1168, 1376, 0, 768, 769, 772, 808, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 1152x864@75Hz */
 	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
@@ -481,16 +493,17 @@
 		   3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
 };
+static const int drm_num_dmt_modes =
+	sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
 
 static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
 			int hsize, int vsize, int fresh)
 {
-	int i, count;
+	int i;
 	struct drm_display_mode *ptr, *mode;
 
-	count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
 	mode = NULL;
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < drm_num_dmt_modes; i++) {
 		ptr = &drm_dmt_modes[i];
 		if (hsize == ptr->hdisplay &&
 			vsize == ptr->vdisplay &&
@@ -563,8 +576,8 @@
 		mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
 				    false);
 		mode->hdisplay = 1366;
-		mode->vsync_start = mode->vsync_start - 1;
-		mode->vsync_end = mode->vsync_end - 1;
+		mode->hsync_start = mode->hsync_start - 1;
+		mode->hsync_end = mode->hsync_end - 1;
 		return mode;
 	}
 	mode = NULL;
@@ -587,6 +600,50 @@
 	return mode;
 }
 
+/*
+ * EDID is delightfully ambiguous about how interlaced modes are to be
+ * encoded.  Our internal representation is of frame height, but some
+ * HDTV detailed timings are encoded as field height.
+ *
+ * The format list here is from CEA, in frame size.  Technically we
+ * should be checking refresh rate too.  Whatever.
+ */
+static void
+drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
+			    struct detailed_pixel_timing *pt)
+{
+	int i;
+	static const struct {
+		int w, h;
+	} cea_interlaced[] = {
+		{ 1920, 1080 },
+		{  720,  480 },
+		{ 1440,  480 },
+		{ 2880,  480 },
+		{  720,  576 },
+		{ 1440,  576 },
+		{ 2880,  576 },
+	};
+	static const int n_sizes =
+		sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
+
+	if (!(pt->misc & DRM_EDID_PT_INTERLACED))
+		return;
+
+	for (i = 0; i < n_sizes; i++) {
+		if ((mode->hdisplay == cea_interlaced[i].w) &&
+		    (mode->vdisplay == cea_interlaced[i].h / 2)) {
+			mode->vdisplay *= 2;
+			mode->vsync_start *= 2;
+			mode->vsync_end *= 2;
+			mode->vtotal *= 2;
+			mode->vtotal |= 1;
+		}
+	}
+
+	mode->flags |= DRM_MODE_FLAG_INTERLACE;
+}
+
 /**
  * drm_mode_detailed - create a new mode from an EDID detailed timing section
  * @dev: DRM device (needed to create new mode)
@@ -622,8 +679,7 @@
 		return NULL;
 	}
 	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
-		printk(KERN_WARNING "integrated sync not supported\n");
-		return NULL;
+		printk(KERN_WARNING "composite sync not supported\n");
 	}
 
 	/* it is incorrect if hsync/vsync width is zero */
@@ -653,15 +709,6 @@
 	mode->vsync_end = mode->vsync_start + vsync_pulse_width;
 	mode->vtotal = mode->vdisplay + vblank;
 
-	/* perform the basic check for the detailed timing */
-	if (mode->hsync_end > mode->htotal ||
-		mode->vsync_end > mode->vtotal) {
-		drm_mode_destroy(dev, mode);
-		DRM_DEBUG_KMS("Incorrect detailed timing. "
-				"Sync is beyond the blank.\n");
-		return NULL;
-	}
-
 	/* Some EDIDs have bogus h/vtotal values */
 	if (mode->hsync_end > mode->htotal)
 		mode->htotal = mode->hsync_end + 1;
@@ -670,8 +717,7 @@
 
 	drm_mode_set_name(mode);
 
-	if (pt->misc & DRM_EDID_PT_INTERLACED)
-		mode->flags |= DRM_MODE_FLAG_INTERLACE;
+	drm_mode_do_interlace_quirk(mode, pt);
 
 	if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
 		pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
@@ -834,8 +880,169 @@
 	return modes;
 }
 
+/*
+ * XXX fix this for:
+ * - GTF secondary curve formula
+ * - EDID 1.4 range offsets
+ * - CVT extended bits
+ */
+static bool
+mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing)
+{
+	struct detailed_data_monitor_range *range;
+	int hsync, vrefresh;
+
+	range = &timing->data.other_data.data.range;
+
+	hsync = drm_mode_hsync(mode);
+	vrefresh = drm_mode_vrefresh(mode);
+
+	if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz)
+		return false;
+
+	if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq)
+		return false;
+
+	if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) {
+		/* be forgiving since it's in units of 10MHz */
+		int max_clock = range->pixel_clock_mhz * 10 + 9;
+		max_clock *= 1000;
+		if (mode->clock > max_clock)
+			return false;
+	}
+
+	return true;
+}
+
+/*
+ * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
+ * need to account for them.
+ */
+static int drm_gtf_modes_for_range(struct drm_connector *connector,
+				   struct detailed_timing *timing)
+{
+	int i, modes = 0;
+	struct drm_display_mode *newmode;
+	struct drm_device *dev = connector->dev;
+
+	for (i = 0; i < drm_num_dmt_modes; i++) {
+		if (mode_in_range(drm_dmt_modes + i, timing)) {
+			newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
+			if (newmode) {
+				drm_mode_probed_add(connector, newmode);
+				modes++;
+			}
+		}
+	}
+
+	return modes;
+}
+
+static int drm_cvt_modes(struct drm_connector *connector,
+			 struct detailed_timing *timing)
+{
+	int i, j, modes = 0;
+	struct drm_display_mode *newmode;
+	struct drm_device *dev = connector->dev;
+	struct cvt_timing *cvt;
+	const int rates[] = { 60, 85, 75, 60, 50 };
+	const u8 empty[3] = { 0, 0, 0 };
+
+	for (i = 0; i < 4; i++) {
+		int uninitialized_var(width), height;
+		cvt = &(timing->data.other_data.data.cvt[i]);
+
+		if (!memcmp(cvt->code, empty, 3))
+			continue;
+
+		height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
+		switch (cvt->code[1] & 0x0c) {
+		case 0x00:
+			width = height * 4 / 3;
+			break;
+		case 0x04:
+			width = height * 16 / 9;
+			break;
+		case 0x08:
+			width = height * 16 / 10;
+			break;
+		case 0x0c:
+			width = height * 15 / 9;
+			break;
+		}
+
+		for (j = 1; j < 5; j++) {
+			if (cvt->code[2] & (1 << j)) {
+				newmode = drm_cvt_mode(dev, width, height,
+						       rates[j], j == 0,
+						       false, false);
+				if (newmode) {
+					drm_mode_probed_add(connector, newmode);
+					modes++;
+				}
+			}
+		}
+	}
+
+	return modes;
+}
+
+static int add_detailed_modes(struct drm_connector *connector,
+			      struct detailed_timing *timing,
+			      struct edid *edid, u32 quirks, int preferred)
+{
+	int i, modes = 0;
+	struct detailed_non_pixel *data = &timing->data.other_data;
+	int timing_level = standard_timing_level(edid);
+	int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
+	struct drm_display_mode *newmode;
+	struct drm_device *dev = connector->dev;
+
+	if (timing->pixel_clock) {
+		newmode = drm_mode_detailed(dev, edid, timing, quirks);
+		if (!newmode)
+			return 0;
+
+		if (preferred)
+			newmode->type |= DRM_MODE_TYPE_PREFERRED;
+
+		drm_mode_probed_add(connector, newmode);
+		return 1;
+	}
+
+	/* other timing types */
+	switch (data->type) {
+	case EDID_DETAIL_MONITOR_RANGE:
+		if (gtf)
+			modes += drm_gtf_modes_for_range(connector, timing);
+		break;
+	case EDID_DETAIL_STD_MODES:
+		/* Six modes per detailed section */
+		for (i = 0; i < 6; i++) {
+			struct std_timing *std;
+			struct drm_display_mode *newmode;
+
+			std = &data->data.timings[i];
+			newmode = drm_mode_std(dev, std, edid->revision,
+					       timing_level);
+			if (newmode) {
+				drm_mode_probed_add(connector, newmode);
+				modes++;
+			}
+		}
+		break;
+	case EDID_DETAIL_CVT_3BYTE:
+		modes += drm_cvt_modes(connector, timing);
+		break;
+	default:
+		break;
+	}
+
+	return modes;
+}
+
 /**
- * add_detailed_modes - get detailed mode info from EDID data
+ * add_detailed_info - get detailed mode info from EDID data
  * @connector: attached connector
  * @edid: EDID block to scan
  * @quirks: quirks to apply
@@ -846,67 +1053,24 @@
 static int add_detailed_info(struct drm_connector *connector,
 			     struct edid *edid, u32 quirks)
 {
-	struct drm_device *dev = connector->dev;
-	int i, j, modes = 0;
-	int timing_level;
-
-	timing_level = standard_timing_level(edid);
+	int i, modes = 0;
 
 	for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
 		struct detailed_timing *timing = &edid->detailed_timings[i];
-		struct detailed_non_pixel *data = &timing->data.other_data;
-		struct drm_display_mode *newmode;
-
-		/* X server check is version 1.1 or higher */
-		if (edid->version == 1 && edid->revision >= 1 &&
-		    !timing->pixel_clock) {
-			/* Other timing or info */
-			switch (data->type) {
-			case EDID_DETAIL_MONITOR_SERIAL:
-				break;
-			case EDID_DETAIL_MONITOR_STRING:
-				break;
-			case EDID_DETAIL_MONITOR_RANGE:
-				/* Get monitor range data */
-				break;
-			case EDID_DETAIL_MONITOR_NAME:
-				break;
-			case EDID_DETAIL_MONITOR_CPDATA:
-				break;
-			case EDID_DETAIL_STD_MODES:
-				for (j = 0; j < 6; i++) {
-					struct std_timing *std;
-					struct drm_display_mode *newmode;
-
-					std = &data->data.timings[j];
-					newmode = drm_mode_std(dev, std,
-							       edid->revision,
-							       timing_level);
-					if (newmode) {
-						drm_mode_probed_add(connector, newmode);
-						modes++;
-					}
-				}
-				break;
-			default:
-				break;
-			}
-		} else {
-			newmode = drm_mode_detailed(dev, edid, timing, quirks);
-			if (!newmode)
-				continue;
+		int preferred = (i == 0) && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
 
-			/* First detailed mode is preferred */
-			if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
-				newmode->type |= DRM_MODE_TYPE_PREFERRED;
-			drm_mode_probed_add(connector, newmode);
+		/* In 1.0, only timings are allowed */
+		if (!timing->pixel_clock && edid->version == 1 &&
+			edid->revision == 0)
+			continue;
 
-			modes++;
-		}
+		modes += add_detailed_modes(connector, timing, edid, quirks,
+					    preferred);
 	}
 
 	return modes;
 }
+
 /**
  * add_detailed_mode_eedid - get detailed mode info from addtional timing
  * 			EDID block
@@ -920,12 +1084,9 @@
 static int add_detailed_info_eedid(struct drm_connector *connector,
 			     struct edid *edid, u32 quirks)
 {
-	struct drm_device *dev = connector->dev;
-	int i, j, modes = 0;
+	int i, modes = 0;
 	char *edid_ext = NULL;
 	struct detailed_timing *timing;
-	struct detailed_non_pixel *data;
-	struct drm_display_mode *newmode;
 	int edid_ext_num;
 	int start_offset, end_offset;
 	int timing_level;
@@ -976,51 +1137,7 @@
 	for (i = start_offset; i < end_offset;
 			i += sizeof(struct detailed_timing)) {
 		timing = (struct detailed_timing *)(edid_ext + i);
-		data = &timing->data.other_data;
-		/* Detailed mode timing */
-		if (timing->pixel_clock) {
-			newmode = drm_mode_detailed(dev, edid, timing, quirks);
-			if (!newmode)
-				continue;
-
-			drm_mode_probed_add(connector, newmode);
-
-			modes++;
-			continue;
-		}
-
-		/* Other timing or info */
-		switch (data->type) {
-		case EDID_DETAIL_MONITOR_SERIAL:
-			break;
-		case EDID_DETAIL_MONITOR_STRING:
-			break;
-		case EDID_DETAIL_MONITOR_RANGE:
-			/* Get monitor range data */
-			break;
-		case EDID_DETAIL_MONITOR_NAME:
-			break;
-		case EDID_DETAIL_MONITOR_CPDATA:
-			break;
-		case EDID_DETAIL_STD_MODES:
-			/* Five modes per detailed section */
-			for (j = 0; j < 5; i++) {
-				struct std_timing *std;
-				struct drm_display_mode *newmode;
-
-				std = &data->data.timings[j];
-				newmode = drm_mode_std(dev, std,
-						       edid->revision,
-						       timing_level);
-				if (newmode) {
-					drm_mode_probed_add(connector, newmode);
-					modes++;
-				}
-			}
-			break;
-		default:
-			break;
-		}
+		modes += add_detailed_modes(connector, timing, edid, quirks, 0);
 	}
 
 	return modes;
@@ -1066,19 +1183,19 @@
 			     struct i2c_adapter *adapter,
 			     char *buf, int len)
 {
-	int ret;
+	int i;
 
-	ret = drm_do_probe_ddc_edid(adapter, buf, len);
-	if (ret != 0) {
-		goto end;
-	}
-	if (!edid_is_valid((struct edid *)buf)) {
-		dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
-			 drm_get_connector_name(connector));
-		ret = -1;
+	for (i = 0; i < 4; i++) {
+		if (drm_do_probe_ddc_edid(adapter, buf, len))
+			return -1;
+		if (edid_is_valid((struct edid *)buf))
+			return 0;
 	}
-end:
-	return ret;
+
+	/* repeated checksum failures; warn, but carry on */
+	dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
+		 drm_get_connector_name(connector));
+	return -1;
 }
 
 /**
@@ -1296,6 +1413,8 @@
 					ptr->vdisplay > vdisplay)
 				continue;
 		}
+		if (drm_mode_vrefresh(ptr) > 61)
+			continue;
 		mode = drm_mode_duplicate(dev, ptr);
 		if (mode) {
 			drm_mode_probed_add(connector, mode);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_mm.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_mm.c
@@ -226,6 +226,44 @@
 }
 EXPORT_SYMBOL(drm_mm_get_block_generic);
 
+struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int atomic)
+{
+	struct drm_mm_node *align_splitoff = NULL;
+	unsigned tmp = 0;
+	unsigned wasted = 0;
+
+	if (node->start < start)
+		wasted += start - node->start;
+	if (alignment)
+		tmp = ((node->start + wasted) % alignment);
+
+	if (tmp)
+		wasted += alignment - tmp;
+	if (wasted) {
+		align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
+		if (unlikely(align_splitoff == NULL))
+			return NULL;
+	}
+
+	if (node->size == size) {
+		list_del_init(&node->fl_entry);
+		node->free = 0;
+	} else {
+		node = drm_mm_split_at_start(node, size, atomic);
+	}
+
+	if (align_splitoff)
+		drm_mm_put_block(align_splitoff);
+
+	return node;
+}
+EXPORT_SYMBOL(drm_mm_get_block_range_generic);
+
 /*
  * Put a block. Merge with the previous and / or next block if they are free.
  * Otherwise add to the free stack.
@@ -320,7 +358,7 @@
 		if (entry->size >= size + wasted) {
 			if (!best_match)
 				return entry;
-			if (size < best_size) {
+			if (entry->size < best_size) {
 				best = entry;
 				best_size = entry->size;
 			}
@@ -331,6 +369,57 @@
 }
 EXPORT_SYMBOL(drm_mm_search_free);
 
+struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int best_match)
+{
+	struct list_head *list;
+	const struct list_head *free_stack = &mm->fl_entry;
+	struct drm_mm_node *entry;
+	struct drm_mm_node *best;
+	unsigned long best_size;
+	unsigned wasted;
+
+	best = NULL;
+	best_size = ~0UL;
+
+	list_for_each(list, free_stack) {
+		entry = list_entry(list, struct drm_mm_node, fl_entry);
+		wasted = 0;
+
+		if (entry->size < size)
+			continue;
+
+		if (entry->start > end || (entry->start+entry->size) < start)
+			continue;
+
+		if (entry->start < start)
+			wasted += start - entry->start;
+
+		if (alignment) {
+			register unsigned tmp = (entry->start + wasted) % alignment;
+			if (tmp)
+				wasted += alignment - tmp;
+		}
+
+		if (entry->size >= size + wasted &&
+		    (entry->start + wasted + size) <= end) {
+			if (!best_match)
+				return entry;
+			if (entry->size < best_size) {
+				best = entry;
+				best_size = entry->size;
+			}
+		}
+	}
+
+	return best;
+}
+EXPORT_SYMBOL(drm_mm_search_free_in_range);
+
 int drm_mm_clean(struct drm_mm * mm)
 {
 	struct list_head *head = &mm->ml_entry;
@@ -381,6 +470,26 @@
 }
 EXPORT_SYMBOL(drm_mm_takedown);
 
+void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
+{
+	struct drm_mm_node *entry;
+	int total_used = 0, total_free = 0, total = 0;
+
+	list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
+		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
+			prefix, entry->start, entry->start + entry->size,
+			entry->size, entry->free ? "free" : "used");
+		total += entry->size;
+		if (entry->free)
+			total_free += entry->size;
+		else
+			total_used += entry->size;
+	}
+	printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
+		total_used, total_free);
+}
+EXPORT_SYMBOL(drm_mm_debug_table);
+
 #if defined(CONFIG_DEBUG_FS)
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 {
@@ -395,7 +504,7 @@
 		else
 			total_used += entry->size;
 	}
-	seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used);
+	seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_dump_table);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_crtc_helper.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_crtc_helper.c
@@ -104,12 +104,13 @@
 	if (connector->status == connector_status_disconnected) {
 		DRM_DEBUG_KMS("%s is disconnected\n",
 			  drm_get_connector_name(connector));
+		drm_mode_connector_update_edid_property(connector, NULL);
 		goto prune;
 	}
 
 	count = (*connector_funcs->get_modes)(connector);
 	if (!count) {
-		count = drm_add_modes_noedid(connector, 800, 600);
+		count = drm_add_modes_noedid(connector, 1024, 768);
 		if (!count)
 			return 0;
 	}
@@ -216,7 +217,7 @@
 EXPORT_SYMBOL(drm_helper_crtc_in_use);
 
 /**
- * drm_disable_unused_functions - disable unused objects
+ * drm_helper_disable_unused_functions - disable unused objects
  * @dev: DRM device
  *
  * LOCKING:
@@ -702,7 +703,7 @@
 		if (encoder->crtc != crtc)
 			continue;
 
-		DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder),
+		DRM_DEBUG("%s: set mode %s %x\n", drm_get_encoder_name(encoder),
 			 mode->name, mode->base.id);
 		encoder_funcs = encoder->helper_private;
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
@@ -924,13 +925,13 @@
 		mode_changed = true;
 
 	if (mode_changed) {
-		old_fb = set->crtc->fb;
-		set->crtc->fb = set->fb;
 		set->crtc->enabled = (set->mode != NULL);
 		if (set->mode != NULL) {
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
+			old_fb = set->crtc->fb;
+			set->crtc->fb = set->fb;
 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
 						      old_fb)) {
@@ -1020,6 +1021,9 @@
 {
 	int count = 0;
 
+	/* disable all the possible outputs/crtcs before entering KMS mode */
+	drm_helper_disable_unused_functions(dev);
+
 	drm_fb_helper_parse_command_line(dev);
 
 	count = drm_helper_probe_connector_modes(dev,
@@ -1029,7 +1033,8 @@
 	/*
 	 * we shouldn't end up with no modes here.
 	 */
-	WARN(!count, "No connectors reported connected with modes\n");
+	if (count == 0)
+		printk(KERN_INFO "No connectors reported connected with modes\n");
 
 	drm_setup_crtcs(dev);
 
@@ -1159,6 +1164,9 @@
 int drm_helper_resume_force_mode(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_crtc_helper_funcs *crtc_funcs;
 	int ret;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1171,6 +1179,25 @@
 
 		if (ret == false)
 			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
+
+		/* Turn off outputs that were already powered off */
+		if (drm_helper_choose_crtc_dpms(crtc)) {
+			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+				if(encoder->crtc != crtc)
+					continue;
+
+				encoder_funcs = encoder->helper_private;
+				if (encoder_funcs->dpms)
+					(*encoder_funcs->dpms) (encoder,
+								drm_helper_choose_encoder_dpms(encoder));
+
+				crtc_funcs = crtc->helper_private;
+				if (crtc_funcs->dpms)
+					(*crtc_funcs->dpms) (crtc,
+							     drm_helper_choose_crtc_dpms(crtc));
+			}
+		}
 	}
 	/* disable the unused connectors while restoring the modesetting */
 	drm_helper_disable_unused_functions(dev);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/drm_dp_i2c_helper.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/drm_dp_i2c_helper.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include "drm_dp_helper.h"
+#include "drmP.h"
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+			    uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+	
+	ret = (*algo_data->aux_ch)(adapter, mode,
+				   write_byte, read_byte);
+	return ret;
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_START;
+	int ret;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	algo_data->address = address;
+	algo_data->running = true;
+	ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+	return ret;
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int mode = MODE_I2C_STOP;
+
+	if (reading)
+		mode |= MODE_I2C_READ;
+	else
+		mode |= MODE_I2C_WRITE;
+	if (algo_data->running) {
+		(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+		algo_data->running = false;
+	}
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * the I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+	return ret;
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	int ret;
+
+	if (!algo_data->running)
+		return -EIO;
+
+	ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+	return ret;
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+		     struct i2c_msg *msgs,
+		     int num)
+{
+	int ret = 0;
+	bool reading = false;
+	int m;
+	int b;
+
+	for (m = 0; m < num; m++) {
+		u16 len = msgs[m].len;
+		u8 *buf = msgs[m].buf;
+		reading = (msgs[m].flags & I2C_M_RD) != 0;
+		ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+		if (ret < 0)
+			break;
+		if (reading) {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+				if (ret < 0)
+					break;
+			}
+		} else {
+			for (b = 0; b < len; b++) {
+				ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+				if (ret < 0)
+					break;
+			}
+		}
+		if (ret < 0)
+			break;
+	}
+	if (ret >= 0)
+		ret = num;
+	i2c_algo_dp_aux_stop(adapter, reading);
+	DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
+	return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	       I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+	.master_xfer	= i2c_algo_dp_aux_xfer,
+	.functionality	= i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+	(void) i2c_algo_dp_aux_address(adapter, 0, false);
+	(void) i2c_algo_dp_aux_stop(adapter, false);
+					   
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+	adapter->algo = &i2c_dp_aux_algo;
+	adapter->retries = 3;
+	i2c_dp_aux_reset_bus(adapter);
+	return 0;
+}
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+	int error;
+	
+	error = i2c_dp_aux_prepare_bus(adapter);
+	if (error)
+		return error;
+	error = i2c_add_adapter(adapter);
+	return error;
+}
+EXPORT_SYMBOL(i2c_dp_aux_add_bus);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "vmwgfx_drv.h"
+
+int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct vmw_private *dev_priv;
+
+	if (unlikely(vma->vm_pgoff < VMWGFX_FILE_PAGE_OFFSET)) {
+		if (vmw_fifo_mmap(filp, vma) == 0)
+			return 0;
+		return drm_mmap(filp, vma);
+	}
+
+	file_priv = (struct drm_file *)filp->private_data;
+	dev_priv = vmw_priv(file_priv->minor->dev);
+	return ttm_bo_mmap(filp, vma, &dev_priv->bdev);
+}
+
+static int vmw_ttm_mem_global_init(struct ttm_global_reference *ref)
+{
+	DRM_INFO("global init.\n");
+	return ttm_mem_global_init(ref->object);
+}
+
+static void vmw_ttm_mem_global_release(struct ttm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+int vmw_ttm_global_init(struct vmw_private *dev_priv)
+{
+	struct ttm_global_reference *global_ref;
+	int ret;
+
+	global_ref = &dev_priv->mem_global_ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &vmw_ttm_mem_global_init;
+	global_ref->release = &vmw_ttm_mem_global_release;
+
+	ret = ttm_global_item_ref(global_ref);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM memory accounting.\n");
+		return ret;
+	}
+
+	dev_priv->bo_global_ref.mem_glob =
+		dev_priv->mem_global_ref.object;
+	global_ref = &dev_priv->bo_global_ref.ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_BO;
+	global_ref->size = sizeof(struct ttm_bo_global);
+	global_ref->init = &ttm_bo_global_init;
+	global_ref->release = &ttm_bo_global_release;
+		ret = ttm_global_item_ref(global_ref);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM buffer objects.\n");
+		goto out_no_bo;
+	}
+
+	return 0;
+out_no_bo:
+	ttm_global_item_unref(&dev_priv->mem_global_ref);
+	return ret;
+}
+
+void vmw_ttm_global_release(struct vmw_private *dev_priv)
+{
+	ttm_global_item_unref(&dev_priv->bo_global_ref.ref);
+	ttm_global_item_unref(&dev_priv->mem_global_ref);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_reg.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+/**
+ * This file contains virtual hardware defines for kernel space.
+ */
+
+#ifndef _VMWGFX_REG_H_
+#define _VMWGFX_REG_H_
+
+#include <linux/types.h>
+
+#define VMWGFX_INDEX_PORT     0x0
+#define VMWGFX_VALUE_PORT     0x1
+#define VMWGFX_IRQSTATUS_PORT 0x8
+
+struct svga_guest_mem_descriptor {
+	__le32 ppn;
+	__le32 num_pages;
+};
+
+struct svga_fifo_cmd_fence {
+	__le32 fence;
+};
+
+#define SVGA_SYNC_GENERIC         1
+#define SVGA_SYNC_FIFOFULL        2
+
+#include "svga_types.h"
+
+#include "svga3d_reg.h"
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_kms.h"
+
+#define vmw_crtc_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.crtc)
+#define vmw_encoder_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.encoder)
+#define vmw_connector_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.connector)
+
+struct vmw_legacy_display {
+	struct list_head active;
+
+	unsigned num_active;
+
+	struct vmw_framebuffer *fb;
+};
+
+/**
+ * Display unit using the legacy register interface.
+ */
+struct vmw_legacy_display_unit {
+	struct vmw_display_unit base;
+
+	struct list_head active;
+
+	unsigned unit;
+};
+
+static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
+{
+	list_del_init(&ldu->active);
+	vmw_display_unit_cleanup(&ldu->base);
+	kfree(ldu);
+}
+
+
+/*
+ * Legacy Display Unit CRTC functions
+ */
+
+static void vmw_ldu_crtc_save(struct drm_crtc *crtc)
+{
+}
+
+static void vmw_ldu_crtc_restore(struct drm_crtc *crtc)
+{
+}
+
+static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc,
+				   u16 *r, u16 *g, u16 *b,
+				   uint32_t size)
+{
+}
+
+static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc)
+{
+	vmw_ldu_destroy(vmw_crtc_to_ldu(crtc));
+}
+
+static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
+{
+	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
+	struct vmw_legacy_display_unit *entry;
+	struct drm_crtc *crtc;
+	int i = 0;
+
+	/* to stop the screen from changing size on resize */
+	vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+	for (i = 0; i < lds->num_active; i++) {
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	}
+
+	/* Now set the mode */
+	vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+	i = 0;
+	list_for_each_entry(entry, &lds->active, active) {
+		crtc = &entry->base.crtc;
+
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, crtc->x);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, crtc->y);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, crtc->mode.hdisplay);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, crtc->mode.vdisplay);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		i++;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
+			      struct vmw_legacy_display_unit *ldu)
+{
+	struct vmw_legacy_display *ld = vmw_priv->ldu_priv;
+	if (list_empty(&ldu->active))
+		return 0;
+
+	list_del_init(&ldu->active);
+	if (--(ld->num_active) == 0) {
+		BUG_ON(!ld->fb);
+		if (ld->fb->unpin)
+			ld->fb->unpin(ld->fb);
+		ld->fb = NULL;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
+			      struct vmw_legacy_display_unit *ldu,
+			      struct vmw_framebuffer *vfb)
+{
+	struct vmw_legacy_display *ld = vmw_priv->ldu_priv;
+	struct vmw_legacy_display_unit *entry;
+	struct list_head *at;
+
+	if (!list_empty(&ldu->active))
+		return 0;
+
+	at = &ld->active;
+	list_for_each_entry(entry, &ld->active, active) {
+		if (entry->unit > ldu->unit)
+			break;
+
+		at = &entry->active;
+	}
+
+	list_add(&ldu->active, at);
+	if (ld->num_active++ == 0) {
+		BUG_ON(ld->fb);
+		if (vfb->pin)
+			vfb->pin(vfb);
+		ld->fb = vfb;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_legacy_display_unit *ldu;
+	struct drm_connector *connector;
+	struct drm_display_mode *mode;
+	struct drm_encoder *encoder;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+	struct drm_crtc *crtc;
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	/* get the ldu */
+	crtc = set->crtc;
+	ldu = vmw_crtc_to_ldu(crtc);
+	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (set->num_connectors > 1) {
+		DRM_ERROR("to many connectors\n");
+		return -EINVAL;
+	}
+
+	if (set->num_connectors == 1 &&
+	    set->connectors[0] != &ldu->base.connector) {
+		DRM_ERROR("connector doesn't match %p %p\n",
+			set->connectors[0], &ldu->base.connector);
+		return -EINVAL;
+	}
+
+	/* ldu only supports one fb active at the time */
+	if (dev_priv->ldu_priv->fb && vfb &&
+	    dev_priv->ldu_priv->fb != vfb) {
+		DRM_ERROR("Multiple framebuffers not supported\n");
+		return -EINVAL;
+	}
+
+	/* since they always map one to one these are safe */
+	connector = &ldu->base.connector;
+	encoder = &ldu->base.encoder;
+
+	/* should we turn the crtc off? */
+	if (set->num_connectors == 0 || !set->mode || !set->fb) {
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+
+		vmw_ldu_del_active(dev_priv, ldu);
+
+		vmw_ldu_commit_list(dev_priv);
+
+		return 0;
+	}
+
+
+	/* we now know we want to set a mode */
+	mode = set->mode;
+	fb = set->fb;
+
+	if (set->x + mode->hdisplay > fb->width ||
+	    set->y + mode->vdisplay > fb->height) {
+		DRM_ERROR("set outside of framebuffer\n");
+		return -EINVAL;
+	}
+
+	vmw_fb_off(dev_priv);
+
+	crtc->fb = fb;
+	encoder->crtc = crtc;
+	connector->encoder = encoder;
+	crtc->x = set->x;
+	crtc->y = set->y;
+	crtc->mode = *mode;
+
+	vmw_ldu_add_active(dev_priv, ldu, vfb);
+
+	vmw_ldu_commit_list(dev_priv);
+
+	return 0;
+}
+
+static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
+	.save = vmw_ldu_crtc_save,
+	.restore = vmw_ldu_crtc_restore,
+	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_move = vmw_du_crtc_cursor_move,
+	.gamma_set = vmw_ldu_crtc_gamma_set,
+	.destroy = vmw_ldu_crtc_destroy,
+	.set_config = vmw_ldu_crtc_set_config,
+};
+
+/*
+ * Legacy Display Unit encoder functions
+ */
+
+static void vmw_ldu_encoder_destroy(struct drm_encoder *encoder)
+{
+	vmw_ldu_destroy(vmw_encoder_to_ldu(encoder));
+}
+
+static struct drm_encoder_funcs vmw_legacy_encoder_funcs = {
+	.destroy = vmw_ldu_encoder_destroy,
+};
+
+/*
+ * Legacy Display Unit connector functions
+ */
+
+static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode)
+{
+}
+
+static void vmw_ldu_connector_save(struct drm_connector *connector)
+{
+}
+
+static void vmw_ldu_connector_restore(struct drm_connector *connector)
+{
+}
+
+static enum drm_connector_status
+	vmw_ldu_connector_detect(struct drm_connector *connector)
+{
+	/* XXX vmwctrl should control connection status */
+	if (vmw_connector_to_ldu(connector)->base.unit == 0)
+		return connector_status_connected;
+	return connector_status_disconnected;
+}
+
+static struct drm_display_mode vmw_ldu_connector_builtin[] = {
+	/* 640x480@60Hz */
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
+		   752, 800, 0, 480, 489, 492, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 800x600@60Hz */
+	{ DRM_MODE("800x600",
+		   DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		   40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
+		   0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1024x768@60Hz */
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+		   1184, 1344, 0, 768, 771, 777, 806, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1152x864@75Hz */
+	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+		   1344, 1600, 0, 864, 865, 868, 900, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x768@60Hz */
+	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+		   1472, 1664, 0, 768, 771, 778, 798, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x800@60Hz */
+	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+		   1480, 1680, 0, 800, 803, 809, 831, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x960@60Hz */
+	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
+		   1488, 1800, 0, 960, 961, 964, 1000, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x1024@60Hz */
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
+		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1360x768@60Hz */
+	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
+		   1536, 1792, 0, 768, 771, 777, 795, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x1050@60Hz */
+	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x900@60Hz */
+	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
+		   1672, 1904, 0, 900, 903, 909, 934, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1600x1200@60Hz */
+	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
+		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1680x1050@60Hz */
+	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1792x1344@60Hz */
+	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
+		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1853x1392@60Hz */
+	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
+		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1200@60Hz */
+	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1440@60Hz */
+	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
+		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 2560x1600@60Hz */
+	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
+		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* Terminate */
+	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
+};
+
+static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
+					uint32_t max_width, uint32_t max_height)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode = NULL;
+	int i;
+
+	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
+		if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
+		    vmw_ldu_connector_builtin[i].vdisplay > max_height)
+			continue;
+
+		mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]);
+		if (!mode)
+			return 0;
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
+		drm_mode_probed_add(connector, mode);
+	}
+
+	drm_mode_connector_list_update(connector);
+
+	return 1;
+}
+
+static int vmw_ldu_connector_set_property(struct drm_connector *connector,
+					  struct drm_property *property,
+					  uint64_t val)
+{
+	return 0;
+}
+
+static void vmw_ldu_connector_destroy(struct drm_connector *connector)
+{
+	vmw_ldu_destroy(vmw_connector_to_ldu(connector));
+}
+
+static struct drm_connector_funcs vmw_legacy_connector_funcs = {
+	.dpms = vmw_ldu_connector_dpms,
+	.save = vmw_ldu_connector_save,
+	.restore = vmw_ldu_connector_restore,
+	.detect = vmw_ldu_connector_detect,
+	.fill_modes = vmw_ldu_connector_fill_modes,
+	.set_property = vmw_ldu_connector_set_property,
+	.destroy = vmw_ldu_connector_destroy,
+};
+
+static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
+{
+	struct vmw_legacy_display_unit *ldu;
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	ldu = kzalloc(sizeof(*ldu), GFP_KERNEL);
+	if (!ldu)
+		return -ENOMEM;
+
+	ldu->unit = unit;
+	crtc = &ldu->base.crtc;
+	encoder = &ldu->base.encoder;
+	connector = &ldu->base.connector;
+
+	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+			   DRM_MODE_CONNECTOR_LVDS);
+	/* Initial status */
+	if (unit == 0)
+		connector->status = connector_status_connected;
+	else
+		connector->status = connector_status_disconnected;
+
+	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
+			 DRM_MODE_ENCODER_LVDS);
+	drm_mode_connector_attach_encoder(connector, encoder);
+	encoder->possible_crtcs = (1 << unit);
+	encoder->possible_clones = 0;
+
+	INIT_LIST_HEAD(&ldu->active);
+
+	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
+
+	drm_connector_attach_property(connector,
+				      dev->mode_config.dirty_info_property,
+				      1);
+
+	return 0;
+}
+
+int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
+{
+	if (dev_priv->ldu_priv) {
+		DRM_INFO("ldu system already on\n");
+		return -EINVAL;
+	}
+
+	dev_priv->ldu_priv = kmalloc(GFP_KERNEL, sizeof(*dev_priv->ldu_priv));
+
+	if (!dev_priv->ldu_priv)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
+	dev_priv->ldu_priv->num_active = 0;
+	dev_priv->ldu_priv->fb = NULL;
+
+	drm_mode_create_dirty_info_property(dev_priv->dev);
+
+	vmw_ldu_init(dev_priv, 0);
+	vmw_ldu_init(dev_priv, 1);
+	vmw_ldu_init(dev_priv, 2);
+	vmw_ldu_init(dev_priv, 3);
+	vmw_ldu_init(dev_priv, 4);
+	vmw_ldu_init(dev_priv, 5);
+	vmw_ldu_init(dev_priv, 6);
+	vmw_ldu_init(dev_priv, 7);
+
+	return 0;
+}
+
+int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
+{
+	if (!dev_priv->ldu_priv)
+		return -ENOSYS;
+
+	BUG_ON(!list_empty(&dev_priv->ldu_priv->active));
+
+	kfree(dev_priv->ldu_priv);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -0,0 +1,716 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "vmwgfx_reg.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_placement.h"
+
+static int vmw_cmd_invalid(struct vmw_private *dev_priv,
+			   struct vmw_sw_context *sw_context,
+			   SVGA3dCmdHeader *header)
+{
+	return capable(CAP_SYS_ADMIN) ? : -EINVAL;
+}
+
+static int vmw_cmd_ok(struct vmw_private *dev_priv,
+		      struct vmw_sw_context *sw_context,
+		      SVGA3dCmdHeader *header)
+{
+	return 0;
+}
+
+static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     SVGA3dCmdHeader *header)
+{
+	struct vmw_cid_cmd {
+		SVGA3dCmdHeader header;
+		__le32 cid;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_cid_cmd, header);
+	if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
+		return 0;
+
+	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not find or use context %u\n",
+			  (unsigned) cmd->cid);
+		return ret;
+	}
+
+	sw_context->last_cid = cmd->cid;
+	sw_context->cid_valid = true;
+
+	return 0;
+}
+
+static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     uint32_t *sid)
+{
+	if (*sid == SVGA3D_INVALID_ID)
+		return 0;
+
+	if (unlikely((!sw_context->sid_valid  ||
+		      *sid != sw_context->last_sid))) {
+		int real_id;
+		int ret = vmw_surface_check(dev_priv, sw_context->tfile,
+					    *sid, &real_id);
+
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Could ot find or use surface 0x%08x "
+				  "address 0x%08lx\n",
+				  (unsigned int) *sid,
+				  (unsigned long) sid);
+			return ret;
+		}
+
+		sw_context->last_sid = *sid;
+		sw_context->sid_valid = true;
+		*sid = real_id;
+		sw_context->sid_translation = real_id;
+	} else
+		*sid = sw_context->sid_translation;
+
+	return 0;
+}
+
+
+static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
+					   struct vmw_sw_context *sw_context,
+					   SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSetRenderTarget body;
+	} *cmd;
+	int ret;
+
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid);
+	return ret;
+}
+
+static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
+				      struct vmw_sw_context *sw_context,
+				      SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceCopy body;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
+	if (unlikely(ret != 0))
+		return ret;
+	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
+}
+
+static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
+				     struct vmw_sw_context *sw_context,
+				     SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceStretchBlt body;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
+	if (unlikely(ret != 0))
+		return ret;
+	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
+}
+
+static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
+					 struct vmw_sw_context *sw_context,
+					 SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdBlitSurfaceToScreen body;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
+}
+
+static int vmw_cmd_present_check(struct vmw_private *dev_priv,
+				 struct vmw_sw_context *sw_context,
+				 SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
+}
+
+static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
+				   struct vmw_sw_context *sw_context,
+				   SVGAGuestPtr *ptr,
+				   struct vmw_dma_buffer **vmw_bo_p)
+{
+	struct vmw_dma_buffer *vmw_bo = NULL;
+	struct ttm_buffer_object *bo;
+	uint32_t handle = ptr->gmrId;
+	struct vmw_relocation *reloc;
+	uint32_t cur_validate_node;
+	struct ttm_validate_buffer *val_buf;
+	int ret;
+
+	ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not find or use GMR region.\n");
+		return -EINVAL;
+	}
+	bo = &vmw_bo->base;
+
+	if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
+		DRM_ERROR("Max number relocations per submission"
+			  " exceeded\n");
+		ret = -EINVAL;
+		goto out_no_reloc;
+	}
+
+	reloc = &sw_context->relocs[sw_context->cur_reloc++];
+	reloc->location = ptr;
+
+	cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
+	if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
+		DRM_ERROR("Max number of DMA buffers per submission"
+			  " exceeded.\n");
+		ret = -EINVAL;
+		goto out_no_reloc;
+	}
+
+	reloc->index = cur_validate_node;
+	if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
+		val_buf = &sw_context->val_bufs[cur_validate_node];
+		val_buf->bo = ttm_bo_reference(bo);
+		val_buf->new_sync_obj_arg = (void *) dev_priv;
+		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+		++sw_context->cur_val_buf;
+	}
+	*vmw_bo_p = vmw_bo;
+	return 0;
+
+out_no_reloc:
+	vmw_dmabuf_unreference(&vmw_bo);
+	vmw_bo_p = NULL;
+	return ret;
+}
+
+static int vmw_cmd_end_query(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     SVGA3dCmdHeader *header)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	struct vmw_query_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdEndQuery q;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_query_cmd, header);
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+				      &cmd->q.guestResult,
+				      &vmw_bo);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_dmabuf_unreference(&vmw_bo);
+	return 0;
+}
+
+static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
+			      struct vmw_sw_context *sw_context,
+			      SVGA3dCmdHeader *header)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	struct vmw_query_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdWaitForQuery q;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_query_cmd, header);
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+				      &cmd->q.guestResult,
+				      &vmw_bo);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_dmabuf_unreference(&vmw_bo);
+	return 0;
+}
+
+
+static int vmw_cmd_dma(struct vmw_private *dev_priv,
+		       struct vmw_sw_context *sw_context,
+		       SVGA3dCmdHeader *header)
+{
+	struct vmw_dma_buffer *vmw_bo = NULL;
+	struct ttm_buffer_object *bo;
+	struct vmw_surface *srf = NULL;
+	struct vmw_dma_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceDMA dma;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_dma_cmd, header);
+	ret = vmw_translate_guest_ptr(dev_priv, sw_context,
+				      &cmd->dma.guest.ptr,
+				      &vmw_bo);
+	if (unlikely(ret != 0))
+		return ret;
+
+	bo = &vmw_bo->base;
+	ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
+					     cmd->dma.host.sid, &srf);
+	if (ret) {
+		DRM_ERROR("could not find surface\n");
+		goto out_no_reloc;
+	}
+
+	/**
+	 * Patch command stream with device SID.
+	 */
+
+	cmd->dma.host.sid = srf->res.id;
+	vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
+	/**
+	 * FIXME: May deadlock here when called from the
+	 * command parsing code.
+	 */
+	vmw_surface_unreference(&srf);
+
+out_no_reloc:
+	vmw_dmabuf_unreference(&vmw_bo);
+	return ret;
+}
+
+static int vmw_cmd_draw(struct vmw_private *dev_priv,
+			struct vmw_sw_context *sw_context,
+			SVGA3dCmdHeader *header)
+{
+	struct vmw_draw_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDrawPrimitives body;
+	} *cmd;
+	SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)(
+		(unsigned long)header + sizeof(*cmd));
+	SVGA3dPrimitiveRange *range;
+	uint32_t i;
+	uint32_t maxnum;
+	int ret;
+
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	cmd = container_of(header, struct vmw_draw_cmd, header);
+	maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
+
+	if (unlikely(cmd->body.numVertexDecls > maxnum)) {
+		DRM_ERROR("Illegal number of vertex declarations.\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
+		ret = vmw_cmd_sid_check(dev_priv, sw_context,
+					&decl->array.surfaceId);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	maxnum = (header->size - sizeof(cmd->body) -
+		  cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range);
+	if (unlikely(cmd->body.numRanges > maxnum)) {
+		DRM_ERROR("Illegal number of index ranges.\n");
+		return -EINVAL;
+	}
+
+	range = (SVGA3dPrimitiveRange *) decl;
+	for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
+		ret = vmw_cmd_sid_check(dev_priv, sw_context,
+					&range->indexArray.surfaceId);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	return 0;
+}
+
+
+static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     SVGA3dCmdHeader *header)
+{
+	struct vmw_tex_state_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSetTextureState state;
+	};
+
+	SVGA3dTextureState *last_state = (SVGA3dTextureState *)
+	  ((unsigned long) header + header->size + sizeof(header));
+	SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
+		((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
+	int ret;
+
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	for (; cur_state < last_state; ++cur_state) {
+		if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
+			continue;
+
+		ret = vmw_cmd_sid_check(dev_priv, sw_context,
+					&cur_state->value);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	return 0;
+}
+
+
+typedef int (*vmw_cmd_func) (struct vmw_private *,
+			     struct vmw_sw_context *,
+			     SVGA3dCmdHeader *);
+
+#define VMW_CMD_DEF(cmd, func) \
+	[cmd - SVGA_3D_CMD_BASE] = func
+
+static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma),
+	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
+		    &vmw_cmd_set_render_target_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
+	VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
+	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
+	VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
+		    &vmw_cmd_blt_surf_screen_check)
+};
+
+static int vmw_cmd_check(struct vmw_private *dev_priv,
+			 struct vmw_sw_context *sw_context,
+			 void *buf, uint32_t *size)
+{
+	uint32_t cmd_id;
+	uint32_t size_remaining = *size;
+	SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
+	int ret;
+
+	cmd_id = ((uint32_t *)buf)[0];
+	if (cmd_id == SVGA_CMD_UPDATE) {
+		*size = 5 << 2;
+		return 0;
+	}
+
+	cmd_id = le32_to_cpu(header->id);
+	*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
+
+	cmd_id -= SVGA_3D_CMD_BASE;
+	if (unlikely(*size > size_remaining))
+		goto out_err;
+
+	if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
+		goto out_err;
+
+	ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	return 0;
+out_err:
+	DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n",
+		  cmd_id + SVGA_3D_CMD_BASE);
+	return -EINVAL;
+}
+
+static int vmw_cmd_check_all(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     void *buf, uint32_t size)
+{
+	int32_t cur_size = size;
+	int ret;
+
+	while (cur_size > 0) {
+		size = cur_size;
+		ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
+		if (unlikely(ret != 0))
+			return ret;
+		buf = (void *)((unsigned long) buf + size);
+		cur_size -= size;
+	}
+
+	if (unlikely(cur_size != 0)) {
+		DRM_ERROR("Command verifier out of sync.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vmw_free_relocations(struct vmw_sw_context *sw_context)
+{
+	sw_context->cur_reloc = 0;
+}
+
+static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
+{
+	uint32_t i;
+	struct vmw_relocation *reloc;
+	struct ttm_validate_buffer *validate;
+	struct ttm_buffer_object *bo;
+
+	for (i = 0; i < sw_context->cur_reloc; ++i) {
+		reloc = &sw_context->relocs[i];
+		validate = &sw_context->val_bufs[reloc->index];
+		bo = validate->bo;
+		reloc->location->offset += bo->offset;
+		reloc->location->gmrId = vmw_dmabuf_gmr(bo);
+	}
+	vmw_free_relocations(sw_context);
+}
+
+static void vmw_clear_validations(struct vmw_sw_context *sw_context)
+{
+	struct ttm_validate_buffer *entry, *next;
+
+	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
+				 head) {
+		list_del(&entry->head);
+		vmw_dmabuf_validate_clear(entry->bo);
+		ttm_bo_unref(&entry->bo);
+		sw_context->cur_val_buf--;
+	}
+	BUG_ON(sw_context->cur_val_buf != 0);
+}
+
+static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
+				      struct ttm_buffer_object *bo)
+{
+	int ret;
+
+	if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
+		return 0;
+
+	/**
+	 * Put BO in VRAM, only if there is space.
+	 */
+
+	ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false);
+	if (unlikely(ret == -ERESTARTSYS))
+		return ret;
+
+	/**
+	 * Otherwise, set it up as GMR.
+	 */
+
+	if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
+		return 0;
+
+	ret = vmw_gmr_bind(dev_priv, bo);
+	if (likely(ret == 0 || ret == -ERESTARTSYS))
+		return ret;
+
+	/**
+	 * If that failed, try VRAM again, this time evicting
+	 * previous contents.
+	 */
+
+	ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
+	return ret;
+}
+
+
+static int vmw_validate_buffers(struct vmw_private *dev_priv,
+				struct vmw_sw_context *sw_context)
+{
+	struct ttm_validate_buffer *entry;
+	int ret;
+
+	list_for_each_entry(entry, &sw_context->validate_nodes, head) {
+		ret = vmw_validate_single_buffer(dev_priv, entry->bo);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	return 0;
+}
+
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
+	struct drm_vmw_fence_rep fence_rep;
+	struct drm_vmw_fence_rep __user *user_fence_rep;
+	int ret;
+	void *user_cmd;
+	void *cmd;
+	uint32_t sequence;
+	struct vmw_sw_context *sw_context = &dev_priv->ctx;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTARTSYS;
+		goto out_no_cmd_mutex;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving fifo space for commands.\n");
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	user_cmd = (void __user *)(unsigned long)arg->commands;
+	ret = copy_from_user(cmd, user_cmd, arg->command_size);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed copying commands.\n");
+		goto out_commit;
+	}
+
+	sw_context->tfile = vmw_fpriv(file_priv)->tfile;
+	sw_context->cid_valid = false;
+	sw_context->sid_valid = false;
+	sw_context->cur_reloc = 0;
+	sw_context->cur_val_buf = 0;
+
+	INIT_LIST_HEAD(&sw_context->validate_nodes);
+
+	ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
+	if (unlikely(ret != 0))
+		goto out_err;
+	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes,
+				     dev_priv->val_seq++);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	ret = vmw_validate_buffers(dev_priv, sw_context);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	vmw_apply_relocations(sw_context);
+	vmw_fifo_commit(dev_priv, arg->command_size);
+
+	ret = vmw_fifo_send_fence(dev_priv, &sequence);
+
+	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+				    (void *)(unsigned long) sequence);
+	vmw_clear_validations(sw_context);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	/*
+	 * This error is harmless, because if fence submission fails,
+	 * vmw_fifo_send_fence will sync.
+	 */
+
+	if (ret != 0)
+		DRM_ERROR("Fence submission error. Syncing.\n");
+
+	fence_rep.error = ret;
+	fence_rep.fence_seq = (uint64_t) sequence;
+
+	user_fence_rep = (struct drm_vmw_fence_rep __user *)
+	    (unsigned long)arg->fence_rep;
+
+	/*
+	 * copy_to_user errors will be detected by user space not
+	 * seeing fence_rep::error filled in.
+	 */
+
+	ret = copy_to_user(user_fence_rep, &fence_rep, sizeof(fence_rep));
+
+	vmw_kms_cursor_post_execbuf(dev_priv);
+	ttm_read_unlock(&vmaster->lock);
+	return 0;
+out_err:
+	vmw_free_relocations(sw_context);
+	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
+	vmw_clear_validations(sw_context);
+out_commit:
+	vmw_fifo_commit(dev_priv, 0);
+out_unlock:
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+out_no_cmd_mutex:
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/svga_escape.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/svga_escape.h
@@ -0,0 +1,89 @@
+/**********************************************************
+ * Copyright 2007-2009 VMware, Inc.  All rights reserved.
+ *
+ * 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.
+ *
+ **********************************************************/
+
+/*
+ * svga_escape.h --
+ *
+ *    Definitions for our own (vendor-specific) SVGA Escape commands.
+ */
+
+#ifndef _SVGA_ESCAPE_H_
+#define _SVGA_ESCAPE_H_
+
+
+/*
+ * Namespace IDs for the escape command
+ */
+
+#define SVGA_ESCAPE_NSID_VMWARE 0x00000000
+#define SVGA_ESCAPE_NSID_DEVEL  0xFFFFFFFF
+
+
+/*
+ * Within SVGA_ESCAPE_NSID_VMWARE, we multiplex commands according to
+ * the first DWORD of escape data (after the nsID and size). As a
+ * guideline we're using the high word and low word as a major and
+ * minor command number, respectively.
+ *
+ * Major command number allocation:
+ *
+ *   0000: Reserved
+ *   0001: SVGA_ESCAPE_VMWARE_LOG (svga_binary_logger.h)
+ *   0002: SVGA_ESCAPE_VMWARE_VIDEO (svga_overlay.h)
+ *   0003: SVGA_ESCAPE_VMWARE_HINT (svga_escape.h)
+ */
+
+#define SVGA_ESCAPE_VMWARE_MAJOR_MASK  0xFFFF0000
+
+
+/*
+ * SVGA Hint commands.
+ *
+ * These escapes let the SVGA driver provide optional information to
+ * he host about the state of the guest or guest applications. The
+ * host can use these hints to make user interface or performance
+ * decisions.
+ *
+ * Notes:
+ *
+ *   - SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN is deprecated for guests
+ *     that use the SVGA Screen Object extension. Instead of sending
+ *     this escape, use the SVGA_SCREEN_FULLSCREEN_HINT flag on your
+ *     Screen Object.
+ */
+
+#define SVGA_ESCAPE_VMWARE_HINT               0x00030000
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  // Deprecated
+
+typedef
+struct {
+   uint32 command;
+   uint32 fullscreen;
+   struct {
+      int32 x, y;
+   } monitorPosition;
+} SVGAEscapeHintFullscreen;
+
+#endif /* _SVGA_ESCAPE_H_ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -0,0 +1,252 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+
+static uint32_t vram_placement_flags = TTM_PL_FLAG_VRAM |
+	TTM_PL_FLAG_CACHED;
+
+static uint32_t vram_ne_placement_flags = TTM_PL_FLAG_VRAM |
+	TTM_PL_FLAG_CACHED |
+	TTM_PL_FLAG_NO_EVICT;
+
+static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM |
+	TTM_PL_FLAG_CACHED;
+
+struct ttm_placement vmw_vram_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &vram_placement_flags
+};
+
+struct ttm_placement vmw_vram_sys_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
+struct ttm_placement vmw_vram_ne_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_ne_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &vram_ne_placement_flags
+};
+
+struct ttm_placement vmw_sys_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &sys_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
+struct vmw_ttm_backend {
+	struct ttm_backend backend;
+};
+
+static int vmw_ttm_populate(struct ttm_backend *backend,
+			    unsigned long num_pages, struct page **pages,
+			    struct page *dummy_read_page)
+{
+	return 0;
+}
+
+static int vmw_ttm_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
+{
+	return 0;
+}
+
+static int vmw_ttm_unbind(struct ttm_backend *backend)
+{
+	return 0;
+}
+
+static void vmw_ttm_clear(struct ttm_backend *backend)
+{
+}
+
+static void vmw_ttm_destroy(struct ttm_backend *backend)
+{
+	struct vmw_ttm_backend *vmw_be =
+	    container_of(backend, struct vmw_ttm_backend, backend);
+
+	kfree(vmw_be);
+}
+
+static struct ttm_backend_func vmw_ttm_func = {
+	.populate = vmw_ttm_populate,
+	.clear = vmw_ttm_clear,
+	.bind = vmw_ttm_bind,
+	.unbind = vmw_ttm_unbind,
+	.destroy = vmw_ttm_destroy,
+};
+
+struct ttm_backend *vmw_ttm_backend_init(struct ttm_bo_device *bdev)
+{
+	struct vmw_ttm_backend *vmw_be;
+
+	vmw_be = kmalloc(sizeof(*vmw_be), GFP_KERNEL);
+	if (!vmw_be)
+		return NULL;
+
+	vmw_be->backend.func = &vmw_ttm_func;
+
+	return &vmw_be->backend;
+}
+
+int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+{
+	return 0;
+}
+
+int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+		      struct ttm_mem_type_manager *man)
+{
+	struct vmw_private *dev_priv =
+	    container_of(bdev, struct vmw_private, bdev);
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		/* System memory */
+
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_VRAM:
+		/* "On-card" video ram */
+		man->gpu_offset = 0;
+		man->io_offset = dev_priv->vram_start;
+		man->io_size = dev_priv->vram_size;
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+		    TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->io_addr = NULL;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_WC;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void vmw_evict_flags(struct ttm_buffer_object *bo,
+		     struct ttm_placement *placement)
+{
+	*placement = vmw_sys_placement;
+}
+
+/**
+ * FIXME: Proper access checks on buffers.
+ */
+
+static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+	return 0;
+}
+
+static void vmw_move_notify(struct ttm_buffer_object *bo,
+		     struct ttm_mem_reg *new_mem)
+{
+	if (new_mem->mem_type != TTM_PL_SYSTEM)
+		vmw_dmabuf_gmr_unbind(bo);
+}
+
+static void vmw_swap_notify(struct ttm_buffer_object *bo)
+{
+	vmw_dmabuf_gmr_unbind(bo);
+}
+
+/**
+ * FIXME: We're using the old vmware polling method to sync.
+ * Do this with fences instead.
+ */
+
+static void *vmw_sync_obj_ref(void *sync_obj)
+{
+	return sync_obj;
+}
+
+static void vmw_sync_obj_unref(void **sync_obj)
+{
+	*sync_obj = NULL;
+}
+
+static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+	mutex_unlock(&dev_priv->hw_mutex);
+	return 0;
+}
+
+static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+	uint32_t sequence = (unsigned long) sync_obj;
+
+	return vmw_fence_signaled(dev_priv, sequence);
+}
+
+static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
+			     bool lazy, bool interruptible)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+	uint32_t sequence = (unsigned long) sync_obj;
+
+	return vmw_wait_fence(dev_priv, false, sequence, false, 3*HZ);
+}
+
+struct ttm_bo_driver vmw_bo_driver = {
+	.create_ttm_backend_entry = vmw_ttm_backend_init,
+	.invalidate_caches = vmw_invalidate_caches,
+	.init_mem_type = vmw_init_mem_type,
+	.evict_flags = vmw_evict_flags,
+	.move = NULL,
+	.verify_access = vmw_verify_access,
+	.sync_obj_signaled = vmw_sync_obj_signaled,
+	.sync_obj_wait = vmw_sync_obj_wait,
+	.sync_obj_flush = vmw_sync_obj_flush,
+	.sync_obj_unref = vmw_sync_obj_unref,
+	.sync_obj_ref = vmw_sync_obj_ref,
+	.move_notify = vmw_move_notify,
+	.swap_notify = vmw_swap_notify
+};
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
@@ -0,0 +1,213 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "drmP.h"
+#include "ttm/ttm_bo_driver.h"
+
+/**
+ * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
+ * the number of used descriptors.
+ */
+
+static int vmw_gmr_build_descriptors(struct list_head *desc_pages,
+				     struct page *pages[],
+				     unsigned long num_pages)
+{
+	struct page *page, *next;
+	struct svga_guest_mem_descriptor *page_virtual = NULL;
+	struct svga_guest_mem_descriptor *desc_virtual = NULL;
+	unsigned int desc_per_page;
+	unsigned long prev_pfn;
+	unsigned long pfn;
+	int ret;
+
+	desc_per_page = PAGE_SIZE /
+	    sizeof(struct svga_guest_mem_descriptor) - 1;
+
+	while (likely(num_pages != 0)) {
+		page = alloc_page(__GFP_HIGHMEM);
+		if (unlikely(page == NULL)) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
+
+		list_add_tail(&page->lru, desc_pages);
+
+		/*
+		 * Point previous page terminating descriptor to this
+		 * page before unmapping it.
+		 */
+
+		if (likely(page_virtual != NULL)) {
+			desc_virtual->ppn = page_to_pfn(page);
+			kunmap_atomic(page_virtual, KM_USER0);
+		}
+
+		page_virtual = kmap_atomic(page, KM_USER0);
+		desc_virtual = page_virtual - 1;
+		prev_pfn = ~(0UL);
+
+		while (likely(num_pages != 0)) {
+			pfn = page_to_pfn(*pages);
+
+			if (pfn != prev_pfn + 1) {
+
+				if (desc_virtual - page_virtual ==
+				    desc_per_page - 1)
+					break;
+
+				(++desc_virtual)->ppn = cpu_to_le32(pfn);
+				desc_virtual->num_pages = cpu_to_le32(1);
+			} else {
+				uint32_t tmp =
+				    le32_to_cpu(desc_virtual->num_pages);
+				desc_virtual->num_pages = cpu_to_le32(tmp + 1);
+			}
+			prev_pfn = pfn;
+			--num_pages;
+			++pages;
+		}
+
+		(++desc_virtual)->ppn = cpu_to_le32(0);
+		desc_virtual->num_pages = cpu_to_le32(0);
+	}
+
+	if (likely(page_virtual != NULL))
+		kunmap_atomic(page_virtual, KM_USER0);
+
+	return 0;
+out_err:
+	list_for_each_entry_safe(page, next, desc_pages, lru) {
+		list_del_init(&page->lru);
+		__free_page(page);
+	}
+	return ret;
+}
+
+static inline void vmw_gmr_free_descriptors(struct list_head *desc_pages)
+{
+	struct page *page, *next;
+
+	list_for_each_entry_safe(page, next, desc_pages, lru) {
+		list_del_init(&page->lru);
+		__free_page(page);
+	}
+}
+
+static void vmw_gmr_fire_descriptors(struct vmw_private *dev_priv,
+				     int gmr_id, struct list_head *desc_pages)
+{
+	struct page *page;
+
+	if (unlikely(list_empty(desc_pages)))
+		return;
+
+	page = list_entry(desc_pages->next, struct page, lru);
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
+	wmb();
+	vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, page_to_pfn(page));
+	mb();
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+}
+
+/**
+ * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
+ * the number of used descriptors.
+ */
+
+static unsigned long vmw_gmr_count_descriptors(struct page *pages[],
+					       unsigned long num_pages)
+{
+	unsigned long prev_pfn = ~(0UL);
+	unsigned long pfn;
+	unsigned long descriptors = 0;
+
+	while (num_pages--) {
+		pfn = page_to_pfn(*pages++);
+		if (prev_pfn + 1 != pfn)
+			++descriptors;
+		prev_pfn = pfn;
+	}
+
+	return descriptors;
+}
+
+int vmw_gmr_bind(struct vmw_private *dev_priv,
+		 struct ttm_buffer_object *bo)
+{
+	struct ttm_tt *ttm = bo->ttm;
+	unsigned long descriptors;
+	int ret;
+	uint32_t id;
+	struct list_head desc_pages;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_GMR))
+		return -EINVAL;
+
+	ret = ttm_tt_populate(ttm);
+	if (unlikely(ret != 0))
+		return ret;
+
+	descriptors = vmw_gmr_count_descriptors(ttm->pages, ttm->num_pages);
+	if (unlikely(descriptors > dev_priv->max_gmr_descriptors))
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&desc_pages);
+	ret = vmw_gmr_build_descriptors(&desc_pages, ttm->pages,
+					ttm->num_pages);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_gmr_id_alloc(dev_priv, &id);
+	if (unlikely(ret != 0))
+		goto out_no_id;
+
+	vmw_gmr_fire_descriptors(dev_priv, id, &desc_pages);
+	vmw_gmr_free_descriptors(&desc_pages);
+	vmw_dmabuf_set_gmr(bo, id);
+	return 0;
+
+out_no_id:
+	vmw_gmr_free_descriptors(&desc_pages);
+	return ret;
+}
+
+void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
+	wmb();
+	vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0);
+	mb();
+	mutex_unlock(&dev_priv->hw_mutex);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -0,0 +1,538 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "drmP.h"
+#include "ttm/ttm_placement.h"
+
+bool vmw_fifo_have_3d(struct vmw_private *dev_priv)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t fifo_min, hwversion;
+
+	fifo_min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
+	if (fifo_min <= SVGA_FIFO_3D_HWVERSION * sizeof(unsigned int))
+		return false;
+
+	hwversion = ioread32(fifo_mem + SVGA_FIFO_3D_HWVERSION);
+	if (hwversion == 0)
+		return false;
+
+	if (hwversion < SVGA3D_HWVERSION_WS65_B1)
+		return false;
+
+	return true;
+}
+
+int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max;
+	uint32_t min;
+	uint32_t dummy;
+	int ret;
+
+	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
+	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
+	if (unlikely(fifo->static_buffer == NULL))
+		return -ENOMEM;
+
+	fifo->last_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
+	fifo->last_data_size = 0;
+	fifo->last_buffer_add = false;
+	fifo->last_buffer = vmalloc(fifo->last_buffer_size);
+	if (unlikely(fifo->last_buffer == NULL)) {
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	fifo->dynamic_buffer = NULL;
+	fifo->reserved_size = 0;
+	fifo->using_bounce_buffer = false;
+
+	mutex_init(&fifo->fifo_mutex);
+	init_rwsem(&fifo->rwsem);
+
+	/*
+	 * Allow mapping the first page read-only to user-space.
+	 */
+
+	DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
+	DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
+	DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
+
+	mutex_lock(&dev_priv->hw_mutex);
+	dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
+	dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+	vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+
+	min = 4;
+	if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
+		min = vmw_read(dev_priv, SVGA_REG_MEM_REGS);
+	min <<= 2;
+
+	if (min < PAGE_SIZE)
+		min = PAGE_SIZE;
+
+	iowrite32(min, fifo_mem + SVGA_FIFO_MIN);
+	iowrite32(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
+	wmb();
+	iowrite32(min,  fifo_mem + SVGA_FIFO_NEXT_CMD);
+	iowrite32(min,  fifo_mem + SVGA_FIFO_STOP);
+	iowrite32(0, fifo_mem + SVGA_FIFO_BUSY);
+	mb();
+
+	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
+	fifo->capabilities = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+
+	DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
+		 (unsigned int) max,
+		 (unsigned int) min,
+		 (unsigned int) fifo->capabilities);
+
+	atomic_set(&dev_priv->fence_seq, dev_priv->last_read_sequence);
+	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
+
+	return vmw_fifo_send_fence(dev_priv, &dummy);
+out_err:
+	vfree(fifo->static_buffer);
+	fifo->static_buffer = NULL;
+	return ret;
+}
+
+void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) {
+		iowrite32(1, fifo_mem + SVGA_FIFO_BUSY);
+		vmw_write(dev_priv, SVGA_REG_SYNC, reason);
+	}
+
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
+		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+
+	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+
+	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
+		  dev_priv->config_done_state);
+	vmw_write(dev_priv, SVGA_REG_ENABLE,
+		  dev_priv->enable_state);
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (likely(fifo->last_buffer != NULL)) {
+		vfree(fifo->last_buffer);
+		fifo->last_buffer = NULL;
+	}
+
+	if (likely(fifo->static_buffer != NULL)) {
+		vfree(fifo->static_buffer);
+		fifo->static_buffer = NULL;
+	}
+
+	if (likely(fifo->dynamic_buffer != NULL)) {
+		vfree(fifo->dynamic_buffer);
+		fifo->dynamic_buffer = NULL;
+	}
+}
+
+static bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+
+	return ((max - next_cmd) + (stop - min) <= bytes);
+}
+
+static int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
+			       uint32_t bytes, bool interruptible,
+			       unsigned long timeout)
+{
+	int ret = 0;
+	unsigned long end_jiffies = jiffies + timeout;
+	DEFINE_WAIT(__wait);
+
+	DRM_INFO("Fifo wait noirq.\n");
+
+	for (;;) {
+		prepare_to_wait(&dev_priv->fifo_queue, &__wait,
+				(interruptible) ?
+				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		if (!vmw_fifo_is_full(dev_priv, bytes))
+			break;
+		if (time_after_eq(jiffies, end_jiffies)) {
+			ret = -EBUSY;
+			DRM_ERROR("SVGA device lockup.\n");
+			break;
+		}
+		schedule_timeout(1);
+		if (interruptible && signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+	finish_wait(&dev_priv->fifo_queue, &__wait);
+	wake_up_all(&dev_priv->fifo_queue);
+	DRM_INFO("Fifo noirq exit.\n");
+	return ret;
+}
+
+static int vmw_fifo_wait(struct vmw_private *dev_priv,
+			 uint32_t bytes, bool interruptible,
+			 unsigned long timeout)
+{
+	long ret = 1L;
+	unsigned long irq_flags;
+
+	if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
+		return 0;
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return vmw_fifo_wait_noirq(dev_priv, bytes,
+					   interruptible, timeout);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_FIFO_PROGRESS,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
+			  SVGA_IRQFLAG_FIFO_PROGRESS);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+		    (dev_priv->fifo_queue,
+		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+	else
+		ret = wait_event_timeout
+		    (dev_priv->fifo_queue,
+		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+
+	if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
+			  ~SVGA_IRQFLAG_FIFO_PROGRESS);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ret;
+}
+
+void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max;
+	uint32_t min;
+	uint32_t next_cmd;
+	uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
+	int ret;
+
+	mutex_lock(&fifo_state->fifo_mutex);
+	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+
+	if (unlikely(bytes >= (max - min)))
+		goto out_err;
+
+	BUG_ON(fifo_state->reserved_size != 0);
+	BUG_ON(fifo_state->dynamic_buffer != NULL);
+
+	fifo_state->reserved_size = bytes;
+
+	while (1) {
+		uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+		bool need_bounce = false;
+		bool reserve_in_place = false;
+
+		if (next_cmd >= stop) {
+			if (likely((next_cmd + bytes < max ||
+				    (next_cmd + bytes == max && stop > min))))
+				reserve_in_place = true;
+
+			else if (vmw_fifo_is_full(dev_priv, bytes)) {
+				ret = vmw_fifo_wait(dev_priv, bytes,
+						    false, 3 * HZ);
+				if (unlikely(ret != 0))
+					goto out_err;
+			} else
+				need_bounce = true;
+
+		} else {
+
+			if (likely((next_cmd + bytes < stop)))
+				reserve_in_place = true;
+			else {
+				ret = vmw_fifo_wait(dev_priv, bytes,
+						    false, 3 * HZ);
+				if (unlikely(ret != 0))
+					goto out_err;
+			}
+		}
+
+		if (reserve_in_place) {
+			if (reserveable || bytes <= sizeof(uint32_t)) {
+				fifo_state->using_bounce_buffer = false;
+
+				if (reserveable)
+					iowrite32(bytes, fifo_mem +
+						  SVGA_FIFO_RESERVED);
+				return fifo_mem + (next_cmd >> 2);
+			} else {
+				need_bounce = true;
+			}
+		}
+
+		if (need_bounce) {
+			fifo_state->using_bounce_buffer = true;
+			if (bytes < fifo_state->static_buffer_size)
+				return fifo_state->static_buffer;
+			else {
+				fifo_state->dynamic_buffer = vmalloc(bytes);
+				return fifo_state->dynamic_buffer;
+			}
+		}
+	}
+out_err:
+	fifo_state->reserved_size = 0;
+	mutex_unlock(&fifo_state->fifo_mutex);
+	return NULL;
+}
+
+static void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
+			      __le32 __iomem *fifo_mem,
+			      uint32_t next_cmd,
+			      uint32_t max, uint32_t min, uint32_t bytes)
+{
+	uint32_t chunk_size = max - next_cmd;
+	uint32_t rest;
+	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
+	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
+
+	if (bytes < chunk_size)
+		chunk_size = bytes;
+
+	iowrite32(bytes, fifo_mem + SVGA_FIFO_RESERVED);
+	mb();
+	memcpy_toio(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
+	rest = bytes - chunk_size;
+	if (rest)
+		memcpy_toio(fifo_mem + (min >> 2), buffer + (chunk_size >> 2),
+			    rest);
+}
+
+static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
+			       __le32 __iomem *fifo_mem,
+			       uint32_t next_cmd,
+			       uint32_t max, uint32_t min, uint32_t bytes)
+{
+	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
+	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
+
+	while (bytes > 0) {
+		iowrite32(*buffer++, fifo_mem + (next_cmd >> 2));
+		next_cmd += sizeof(uint32_t);
+		if (unlikely(next_cmd == max))
+			next_cmd = min;
+		mb();
+		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+		mb();
+		bytes -= sizeof(uint32_t);
+	}
+}
+
+void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
+
+	BUG_ON((bytes & 3) != 0);
+	BUG_ON(bytes > fifo_state->reserved_size);
+
+	fifo_state->reserved_size = 0;
+
+	if (fifo_state->using_bounce_buffer) {
+		if (reserveable)
+			vmw_fifo_res_copy(fifo_state, fifo_mem,
+					  next_cmd, max, min, bytes);
+		else
+			vmw_fifo_slow_copy(fifo_state, fifo_mem,
+					   next_cmd, max, min, bytes);
+
+		if (fifo_state->dynamic_buffer) {
+			vfree(fifo_state->dynamic_buffer);
+			fifo_state->dynamic_buffer = NULL;
+		}
+
+	}
+
+	down_write(&fifo_state->rwsem);
+	if (fifo_state->using_bounce_buffer || reserveable) {
+		next_cmd += bytes;
+		if (next_cmd >= max)
+			next_cmd -= max - min;
+		mb();
+		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+	}
+
+	if (reserveable)
+		iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED);
+	mb();
+	up_write(&fifo_state->rwsem);
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	mutex_unlock(&fifo_state->fifo_mutex);
+}
+
+int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	struct svga_fifo_cmd_fence *cmd_fence;
+	void *fm;
+	int ret = 0;
+	uint32_t bytes = sizeof(__le32) + sizeof(*cmd_fence);
+
+	fm = vmw_fifo_reserve(dev_priv, bytes);
+	if (unlikely(fm == NULL)) {
+		*sequence = atomic_read(&dev_priv->fence_seq);
+		ret = -ENOMEM;
+		(void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+					false, 3*HZ);
+		goto out_err;
+	}
+
+	do {
+		*sequence = atomic_add_return(1, &dev_priv->fence_seq);
+	} while (*sequence == 0);
+
+	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
+
+		/*
+		 * Don't request hardware to send a fence. The
+		 * waiting code in vmwgfx_irq.c will emulate this.
+		 */
+
+		vmw_fifo_commit(dev_priv, 0);
+		return 0;
+	}
+
+	*(__le32 *) fm = cpu_to_le32(SVGA_CMD_FENCE);
+	cmd_fence = (struct svga_fifo_cmd_fence *)
+	    ((unsigned long)fm + sizeof(__le32));
+
+	iowrite32(*sequence, &cmd_fence->fence);
+	fifo_state->last_buffer_add = true;
+	vmw_fifo_commit(dev_priv, bytes);
+	fifo_state->last_buffer_add = false;
+
+out_err:
+	return ret;
+}
+
+/**
+ * Map the first page of the FIFO read-only to user-space.
+ */
+
+static int vmw_fifo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int ret;
+	unsigned long address = (unsigned long)vmf->virtual_address;
+
+	if (address != vma->vm_start)
+		return VM_FAULT_SIGBUS;
+
+	ret = vm_insert_pfn(vma, address, vma->vm_pgoff);
+	if (likely(ret == -EBUSY || ret == 0))
+		return VM_FAULT_NOPAGE;
+	else if (ret == -ENOMEM)
+		return VM_FAULT_OOM;
+
+	return VM_FAULT_SIGBUS;
+}
+
+static struct vm_operations_struct vmw_fifo_vm_ops = {
+	.fault = vmw_fifo_vm_fault,
+	.open = NULL,
+	.close = NULL
+};
+
+int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct vmw_private *dev_priv;
+
+	file_priv = (struct drm_file *)filp->private_data;
+	dev_priv = vmw_priv(file_priv->minor->dev);
+
+	if (vma->vm_pgoff != (dev_priv->mmio_start >> PAGE_SHIFT) ||
+	    (vma->vm_end - vma->vm_start) != PAGE_SIZE)
+		return -EINVAL;
+
+	vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_SHARED;
+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+	vma->vm_page_prot = ttm_io_prot(TTM_PL_FLAG_UNCACHED,
+					vma->vm_page_prot);
+	vma->vm_ops = &vmw_fifo_vm_ops;
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/Makefile
@@ -0,0 +1,9 @@
+
+ccflags-y := -Iinclude/drm
+
+vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
+	    vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
+	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
+	    vmwgfx_overlay.o
+
+obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -0,0 +1,737 @@
+/**************************************************************************
+ *
+ * Copyright © 2007 David Airlie
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "vmwgfx_drv.h"
+
+#include "ttm/ttm_placement.h"
+
+#define VMW_DIRTY_DELAY (HZ / 30)
+
+struct vmw_fb_par {
+	struct vmw_private *vmw_priv;
+
+	void *vmalloc;
+
+	struct vmw_dma_buffer *vmw_bo;
+	struct ttm_bo_kmap_obj map;
+
+	u32 pseudo_palette[17];
+
+	unsigned depth;
+	unsigned bpp;
+
+	unsigned max_width;
+	unsigned max_height;
+
+	void *bo_ptr;
+	unsigned bo_size;
+	bool bo_iowrite;
+
+	struct {
+		spinlock_t lock;
+		bool active;
+		unsigned x1;
+		unsigned y1;
+		unsigned x2;
+		unsigned y2;
+	} dirty;
+};
+
+static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	struct vmw_fb_par *par = info->par;
+	u32 *pal = par->pseudo_palette;
+
+	if (regno > 15) {
+		DRM_ERROR("Bad regno %u.\n", regno);
+		return 1;
+	}
+
+	switch (par->depth) {
+	case 24:
+	case 32:
+		pal[regno] = ((red & 0xff00) << 8) |
+			      (green & 0xff00) |
+			     ((blue  & 0xff00) >> 8);
+		break;
+	default:
+		DRM_ERROR("Bad depth %u, bpp %u.\n", par->depth, par->bpp);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int vmw_fb_check_var(struct fb_var_screeninfo *var,
+			    struct fb_info *info)
+{
+	int depth = var->bits_per_pixel;
+	struct vmw_fb_par *par = info->par;
+	struct vmw_private *vmw_priv = par->vmw_priv;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+		depth = (var->transp.length > 0) ? 32 : 24;
+		break;
+	default:
+		DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	switch (depth) {
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		break;
+	default:
+		DRM_ERROR("Bad depth %u.\n", depth);
+		return -EINVAL;
+	}
+
+	/* without multimon its hard to resize */
+	if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
+	    (var->xres != par->max_width ||
+	     var->yres != par->max_height)) {
+		DRM_ERROR("Tried to resize, but we don't have multimon\n");
+		return -EINVAL;
+	}
+
+	if (var->xres > par->max_width ||
+	    var->yres > par->max_height) {
+		DRM_ERROR("Requested geom can not fit in framebuffer\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vmw_fb_set_par(struct fb_info *info)
+{
+	struct vmw_fb_par *par = info->par;
+	struct vmw_private *vmw_priv = par->vmw_priv;
+
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
+		vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
+		vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
+		vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
+		vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
+		vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+		vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+		vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+
+		/* TODO check if pitch and offset changes */
+
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, info->var.yoffset);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	} else {
+		vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
+		vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
+
+		/* TODO check if pitch and offset changes */
+	}
+
+	return 0;
+}
+
+static int vmw_fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	return 0;
+}
+
+static int vmw_fb_blank(int blank, struct fb_info *info)
+{
+	return 0;
+}
+
+/*
+ * Dirty code
+ */
+
+static void vmw_fb_dirty_flush(struct vmw_fb_par *par)
+{
+	struct vmw_private *vmw_priv = par->vmw_priv;
+	struct fb_info *info = vmw_priv->fb_info;
+	int stride = (info->fix.line_length / 4);
+	int *src = (int *)info->screen_base;
+	__le32 __iomem *vram_mem = par->bo_ptr;
+	unsigned long flags;
+	unsigned x, y, w, h;
+	int i, k;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdUpdate body;
+	} *cmd;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	if (!par->dirty.active) {
+		spin_unlock_irqrestore(&par->dirty.lock, flags);
+		return;
+	}
+	x = par->dirty.x1;
+	y = par->dirty.y1;
+	w = min(par->dirty.x2, info->var.xres) - x;
+	h = min(par->dirty.y2, info->var.yres) - y;
+	par->dirty.x1 = par->dirty.x2 = 0;
+	par->dirty.y1 = par->dirty.y2 = 0;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+	for (i = y * stride; i < info->fix.smem_len / 4; i += stride) {
+		for (k = i+x; k < i+x+w && k < info->fix.smem_len / 4; k++)
+			iowrite32(src[k], vram_mem + k);
+	}
+
+#if 0
+	DRM_INFO("%s, (%u, %u) (%ux%u)\n", __func__, x, y, w, h);
+#endif
+
+	cmd = vmw_fifo_reserve(vmw_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return;
+	}
+
+	cmd->header = cpu_to_le32(SVGA_CMD_UPDATE);
+	cmd->body.x = cpu_to_le32(x);
+	cmd->body.y = cpu_to_le32(y);
+	cmd->body.width = cpu_to_le32(w);
+	cmd->body.height = cpu_to_le32(h);
+	vmw_fifo_commit(vmw_priv, sizeof(*cmd));
+}
+
+static void vmw_fb_dirty_mark(struct vmw_fb_par *par,
+			      unsigned x1, unsigned y1,
+			      unsigned width, unsigned height)
+{
+	struct fb_info *info = par->vmw_priv->fb_info;
+	unsigned long flags;
+	unsigned x2 = x1 + width;
+	unsigned y2 = y1 + height;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	if (par->dirty.x1 == par->dirty.x2) {
+		par->dirty.x1 = x1;
+		par->dirty.y1 = y1;
+		par->dirty.x2 = x2;
+		par->dirty.y2 = y2;
+		/* if we are active start the dirty work
+		 * we share the work with the defio system */
+		if (par->dirty.active)
+			schedule_delayed_work(&info->deferred_work, VMW_DIRTY_DELAY);
+	} else {
+		if (x1 < par->dirty.x1)
+			par->dirty.x1 = x1;
+		if (y1 < par->dirty.y1)
+			par->dirty.y1 = y1;
+		if (x2 > par->dirty.x2)
+			par->dirty.x2 = x2;
+		if (y2 > par->dirty.y2)
+			par->dirty.y2 = y2;
+	}
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+}
+
+static void vmw_deferred_io(struct fb_info *info,
+			    struct list_head *pagelist)
+{
+	struct vmw_fb_par *par = info->par;
+	unsigned long start, end, min, max;
+	unsigned long flags;
+	struct page *page;
+	int y1, y2;
+
+	min = ULONG_MAX;
+	max = 0;
+	list_for_each_entry(page, pagelist, lru) {
+		start = page->index << PAGE_SHIFT;
+		end = start + PAGE_SIZE - 1;
+		min = min(min, start);
+		max = max(max, end);
+	}
+
+	if (min < max) {
+		y1 = min / info->fix.line_length;
+		y2 = (max / info->fix.line_length) + 1;
+
+		spin_lock_irqsave(&par->dirty.lock, flags);
+		par->dirty.x1 = 0;
+		par->dirty.y1 = y1;
+		par->dirty.x2 = info->var.xres;
+		par->dirty.y2 = y2;
+		spin_unlock_irqrestore(&par->dirty.lock, flags);
+	}
+
+	vmw_fb_dirty_flush(par);
+};
+
+struct fb_deferred_io vmw_defio = {
+	.delay		= VMW_DIRTY_DELAY,
+	.deferred_io	= vmw_deferred_io,
+};
+
+/*
+ * Draw code
+ */
+
+static void vmw_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	cfb_fillrect(info, rect);
+	vmw_fb_dirty_mark(info->par, rect->dx, rect->dy,
+			  rect->width, rect->height);
+}
+
+static void vmw_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	cfb_copyarea(info, region);
+	vmw_fb_dirty_mark(info->par, region->dx, region->dy,
+			  region->width, region->height);
+}
+
+static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	cfb_imageblit(info, image);
+	vmw_fb_dirty_mark(info->par, image->dx, image->dy,
+			  image->width, image->height);
+}
+
+/*
+ * Bring up code
+ */
+
+static struct fb_ops vmw_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = vmw_fb_check_var,
+	.fb_set_par = vmw_fb_set_par,
+	.fb_setcolreg = vmw_fb_setcolreg,
+	.fb_fillrect = vmw_fb_fillrect,
+	.fb_copyarea = vmw_fb_copyarea,
+	.fb_imageblit = vmw_fb_imageblit,
+	.fb_pan_display = vmw_fb_pan_display,
+	.fb_blank = vmw_fb_blank,
+};
+
+static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
+			    size_t size, struct vmw_dma_buffer **out)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	struct ttm_placement ne_placement = vmw_vram_ne_placement;
+	int ret;
+
+	ne_placement.lpfn = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	/* interuptable? */
+	ret = ttm_write_lock(&vmw_priv->fbdev_master.lock, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_bo = kmalloc(sizeof(*vmw_bo), GFP_KERNEL);
+	if (!vmw_bo)
+		goto err_unlock;
+
+	ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size,
+			      &ne_placement,
+			      false,
+			      &vmw_dmabuf_bo_free);
+	if (unlikely(ret != 0))
+		goto err_unlock; /* init frees the buffer on failure */
+
+	*out = vmw_bo;
+
+	ttm_write_unlock(&vmw_priv->fbdev_master.lock);
+
+	return 0;
+
+err_unlock:
+	ttm_write_unlock(&vmw_priv->fbdev_master.lock);
+	return ret;
+}
+
+int vmw_fb_init(struct vmw_private *vmw_priv)
+{
+	struct device *device = &vmw_priv->dev->pdev->dev;
+	struct vmw_fb_par *par;
+	struct fb_info *info;
+	unsigned initial_width, initial_height;
+	unsigned fb_width, fb_height;
+	unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
+	int ret;
+
+	initial_width = 800;
+	initial_height = 600;
+
+	fb_bbp = 32;
+	fb_depth = 24;
+
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+		fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
+	} else {
+		fb_width = min(vmw_priv->fb_max_width, initial_width);
+		fb_height = min(vmw_priv->fb_max_height, initial_height);
+	}
+
+	initial_width = min(fb_width, initial_width);
+	initial_height = min(fb_height, initial_height);
+
+	vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
+	vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
+	vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
+	vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+
+	fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+	fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
+	fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
+
+	DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
+	DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
+	DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
+	DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
+	DRM_DEBUG("bpp    %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
+	DRM_DEBUG("depth  %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
+	DRM_DEBUG("bpl    %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
+	DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
+	DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
+	DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
+	DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
+	DRM_DEBUG("fb_pitch  %u\n", fb_pitch);
+	DRM_DEBUG("fb_size   %u kiB\n", fb_size / 1024);
+
+	info = framebuffer_alloc(sizeof(*par), device);
+	if (!info)
+		return -ENOMEM;
+
+	/*
+	 * Par
+	 */
+	vmw_priv->fb_info = info;
+	par = info->par;
+	par->vmw_priv = vmw_priv;
+	par->depth = fb_depth;
+	par->bpp = fb_bbp;
+	par->vmalloc = NULL;
+	par->max_width = fb_width;
+	par->max_height = fb_height;
+
+	/*
+	 * Create buffers and alloc memory
+	 */
+	par->vmalloc = vmalloc(fb_size);
+	if (unlikely(par->vmalloc == NULL)) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	ret = vmw_fb_create_bo(vmw_priv, fb_size, &par->vmw_bo);
+	if (unlikely(ret != 0))
+		goto err_free;
+
+	ret = ttm_bo_kmap(&par->vmw_bo->base,
+			  0,
+			  par->vmw_bo->base.num_pages,
+			  &par->map);
+	if (unlikely(ret != 0))
+		goto err_unref;
+	par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
+	par->bo_size = fb_size;
+
+	/*
+	 * Fixed and var
+	 */
+	strcpy(info->fix.id, "svgadrmfb");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 1; /* doing it in hw */
+	info->fix.ypanstep = 1; /* doing it in hw */
+	info->fix.ywrapstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fix.line_length = fb_pitch;
+
+	info->fix.smem_start = 0;
+	info->fix.smem_len = fb_size;
+
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+
+	info->pseudo_palette = par->pseudo_palette;
+	info->screen_base = par->vmalloc;
+	info->screen_size = fb_size;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &vmw_fb_ops;
+
+	/* 24 depth per default */
+	info->var.red.offset = 16;
+	info->var.green.offset = 8;
+	info->var.blue.offset = 0;
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+	info->var.transp.offset = 0;
+	info->var.transp.length = 0;
+
+	info->var.xres_virtual = fb_width;
+	info->var.yres_virtual = fb_height;
+	info->var.bits_per_pixel = par->bpp;
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.height = -1;
+	info->var.width = -1;
+
+	info->var.xres = initial_width;
+	info->var.yres = initial_height;
+
+#if 0
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+#else
+	info->pixmap.size = 0;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+#endif
+
+	info->aperture_base = vmw_priv->vram_start;
+	info->aperture_size = vmw_priv->vram_size;
+
+	/*
+	 * Dirty & Deferred IO
+	 */
+	par->dirty.x1 = par->dirty.x2 = 0;
+	par->dirty.y1 = par->dirty.y1 = 0;
+	par->dirty.active = true;
+	spin_lock_init(&par->dirty.lock);
+	info->fbdefio = &vmw_defio;
+	fb_deferred_io_init(info);
+
+	ret = register_framebuffer(info);
+	if (unlikely(ret != 0))
+		goto err_defio;
+
+	return 0;
+
+err_defio:
+	fb_deferred_io_cleanup(info);
+	ttm_bo_kunmap(&par->map);
+err_unref:
+	ttm_bo_unref((struct ttm_buffer_object **)&par->vmw_bo);
+err_free:
+	vfree(par->vmalloc);
+	framebuffer_release(info);
+	vmw_priv->fb_info = NULL;
+
+	return ret;
+}
+
+int vmw_fb_close(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	struct ttm_buffer_object *bo;
+
+	if (!vmw_priv->fb_info)
+		return 0;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+	bo = &par->vmw_bo->base;
+	par->vmw_bo = NULL;
+
+	/* ??? order */
+	fb_deferred_io_cleanup(info);
+	unregister_framebuffer(info);
+
+	ttm_bo_kunmap(&par->map);
+	ttm_bo_unref(&bo);
+
+	vfree(par->vmalloc);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
+			 struct vmw_dma_buffer *vmw_bo)
+{
+	struct ttm_buffer_object *bo = &vmw_bo->base;
+	int ret = 0;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false);
+	ttm_bo_unreserve(bo);
+
+	return ret;
+}
+
+int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				struct vmw_dma_buffer *vmw_bo)
+{
+	struct ttm_buffer_object *bo = &vmw_bo->base;
+	struct ttm_placement ne_placement = vmw_vram_ne_placement;
+	int ret = 0;
+
+	ne_placement.lpfn = bo->num_pages;
+
+	/* interuptable? */
+	ret = ttm_write_lock(&vmw_priv->active_master->lock, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err_unlock;
+
+	ret = ttm_bo_validate(bo, &ne_placement, false, false);
+	ttm_bo_unreserve(bo);
+err_unlock:
+	ttm_write_unlock(&vmw_priv->active_master->lock);
+
+	return ret;
+}
+
+int vmw_fb_off(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	unsigned long flags;
+
+	if (!vmw_priv->fb_info)
+		return -EINVAL;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	par->dirty.active = false;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+	flush_scheduled_work();
+
+	par->bo_ptr = NULL;
+	ttm_bo_kunmap(&par->map);
+
+	vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo);
+
+	return 0;
+}
+
+int vmw_fb_on(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	unsigned long flags;
+	bool dummy;
+	int ret;
+
+	if (!vmw_priv->fb_info)
+		return -EINVAL;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+
+	/* we are already active */
+	if (par->bo_ptr != NULL)
+		return 0;
+
+	/* Make sure that all overlays are stoped when we take over */
+	vmw_overlay_stop_all(vmw_priv);
+
+	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("could not move buffer to start of VRAM\n");
+		goto err_no_buffer;
+	}
+
+	ret = ttm_bo_kmap(&par->vmw_bo->base,
+			  0,
+			  par->vmw_bo->base.num_pages,
+			  &par->map);
+	BUG_ON(ret != 0);
+	par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &dummy);
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	par->dirty.active = true;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+err_no_buffer:
+	vmw_fb_set_par(info);
+
+	vmw_fb_dirty_mark(par, 0, 0, info->var.xres, info->var.yres);
+
+	/* If there already was stuff dirty we wont
+	 * schedule a new work, so lets do it now */
+	schedule_delayed_work(&info->deferred_work, 0);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -0,0 +1,625 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "vmwgfx_drv.h"
+
+#include "ttm/ttm_placement.h"
+
+#include "svga_overlay.h"
+#include "svga_escape.h"
+
+#define VMW_MAX_NUM_STREAMS 1
+
+struct vmw_stream {
+	struct vmw_dma_buffer *buf;
+	bool claimed;
+	bool paused;
+	struct drm_vmw_control_stream_arg saved;
+};
+
+/**
+ * Overlay control
+ */
+struct vmw_overlay {
+	/*
+	 * Each stream is a single overlay. In Xv these are called ports.
+	 */
+	struct mutex mutex;
+	struct vmw_stream stream[VMW_MAX_NUM_STREAMS];
+};
+
+static inline struct vmw_overlay *vmw_overlay(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	return dev_priv ? dev_priv->overlay_priv : NULL;
+}
+
+struct vmw_escape_header {
+	uint32_t cmd;
+	SVGAFifoCmdEscape body;
+};
+
+struct vmw_escape_video_flush {
+	struct vmw_escape_header escape;
+	SVGAEscapeVideoFlush flush;
+};
+
+static inline void fill_escape(struct vmw_escape_header *header,
+			       uint32_t size)
+{
+	header->cmd = SVGA_CMD_ESCAPE;
+	header->body.nsid = SVGA_ESCAPE_NSID_VMWARE;
+	header->body.size = size;
+}
+
+static inline void fill_flush(struct vmw_escape_video_flush *cmd,
+			      uint32_t stream_id)
+{
+	fill_escape(&cmd->escape, sizeof(cmd->flush));
+	cmd->flush.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH;
+	cmd->flush.streamId = stream_id;
+}
+
+/**
+ * Pin or unpin a buffer in vram.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to pin or unpin.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Takes the current masters ttm lock in read.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
+				  struct vmw_dma_buffer *buf,
+				  bool pin, bool interruptible)
+{
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_placement *overlay_placement = &vmw_vram_placement;
+	int ret;
+
+	ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	if (pin)
+		overlay_placement = &vmw_vram_ne_placement;
+
+	ret = ttm_bo_validate(bo, overlay_placement, interruptible, false);
+
+	ttm_bo_unreserve(bo);
+
+err:
+	ttm_read_unlock(&dev_priv->active_master->lock);
+
+	return ret;
+}
+
+/**
+ * Send put command to hw.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_overlay_send_put(struct vmw_private *dev_priv,
+				struct vmw_dma_buffer *buf,
+				struct drm_vmw_control_stream_arg *arg,
+				bool interruptible)
+{
+	struct {
+		struct vmw_escape_header escape;
+		struct {
+			struct {
+				uint32_t cmdType;
+				uint32_t streamId;
+			} header;
+			struct {
+				uint32_t registerId;
+				uint32_t value;
+			} items[SVGA_VIDEO_PITCH_3 + 1];
+		} body;
+		struct vmw_escape_video_flush flush;
+	} *cmds;
+	uint32_t offset;
+	int i, ret;
+
+	for (;;) {
+		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
+		if (cmds)
+			break;
+
+		ret = vmw_fallback_wait(dev_priv, false, true, 0,
+					interruptible, 3*HZ);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	fill_escape(&cmds->escape, sizeof(cmds->body));
+	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->body.header.streamId = arg->stream_id;
+
+	for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
+		cmds->body.items[i].registerId = i;
+
+	offset = buf->base.offset + arg->offset;
+
+	cmds->body.items[SVGA_VIDEO_ENABLED].value     = true;
+	cmds->body.items[SVGA_VIDEO_FLAGS].value       = arg->flags;
+	cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
+	cmds->body.items[SVGA_VIDEO_FORMAT].value      = arg->format;
+	cmds->body.items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
+	cmds->body.items[SVGA_VIDEO_SIZE].value        = arg->size;
+	cmds->body.items[SVGA_VIDEO_WIDTH].value       = arg->width;
+	cmds->body.items[SVGA_VIDEO_HEIGHT].value      = arg->height;
+	cmds->body.items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
+	cmds->body.items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
+	cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
+	cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
+	cmds->body.items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
+	cmds->body.items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
+	cmds->body.items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
+	cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
+	cmds->body.items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
+	cmds->body.items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
+	cmds->body.items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+
+	fill_flush(&cmds->flush, arg->stream_id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+
+	return 0;
+}
+
+/**
+ * Send stop command to hw.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_overlay_send_stop(struct vmw_private *dev_priv,
+				 uint32_t stream_id,
+				 bool interruptible)
+{
+	struct {
+		struct vmw_escape_header escape;
+		SVGAEscapeVideoSetRegs body;
+		struct vmw_escape_video_flush flush;
+	} *cmds;
+	int ret;
+
+	for (;;) {
+		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
+		if (cmds)
+			break;
+
+		ret = vmw_fallback_wait(dev_priv, false, true, 0,
+					interruptible, 3*HZ);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	fill_escape(&cmds->escape, sizeof(cmds->body));
+	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->body.header.streamId = stream_id;
+	cmds->body.items[0].registerId = SVGA_VIDEO_ENABLED;
+	cmds->body.items[0].value = false;
+	fill_flush(&cmds->flush, stream_id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+
+	return 0;
+}
+
+/**
+ * Stop or pause a stream.
+ *
+ * If the stream is paused the no evict flag is removed from the buffer
+ * but left in vram. This allows for instance mode_set to evict it
+ * should it need to.
+ *
+ * The caller must hold the overlay lock.
+ *
+ * @stream_id which stream to stop/pause.
+ * @pause true to pause, false to stop completely.
+ */
+static int vmw_overlay_stop(struct vmw_private *dev_priv,
+			    uint32_t stream_id, bool pause,
+			    bool interruptible)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct vmw_stream *stream = &overlay->stream[stream_id];
+	int ret;
+
+	/* no buffer attached the stream is completely stopped */
+	if (!stream->buf)
+		return 0;
+
+	/* If the stream is paused this is already done */
+	if (!stream->paused) {
+		ret = vmw_overlay_send_stop(dev_priv, stream_id,
+					    interruptible);
+		if (ret)
+			return ret;
+
+		/* We just remove the NO_EVICT flag so no -ENOMEM */
+		ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
+					     interruptible);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	if (!pause) {
+		vmw_dmabuf_unreference(&stream->buf);
+		stream->paused = false;
+	} else {
+		stream->paused = true;
+	}
+
+	return 0;
+}
+
+/**
+ * Update a stream and send any put or stop fifo commands needed.
+ *
+ * The caller must hold the overlay lock.
+ *
+ * Returns
+ * -ENOMEM if buffer doesn't fit in vram.
+ * -ERESTARTSYS if interrupted.
+ */
+static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
+				     struct vmw_dma_buffer *buf,
+				     struct drm_vmw_control_stream_arg *arg,
+				     bool interruptible)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct vmw_stream *stream = &overlay->stream[arg->stream_id];
+	int ret = 0;
+
+	if (!buf)
+		return -EINVAL;
+
+	DRM_DEBUG("   %s: old %p, new %p, %spaused\n", __func__,
+		  stream->buf, buf, stream->paused ? "" : "not ");
+
+	if (stream->buf != buf) {
+		ret = vmw_overlay_stop(dev_priv, arg->stream_id,
+				       false, interruptible);
+		if (ret)
+			return ret;
+	} else if (!stream->paused) {
+		/* If the buffers match and not paused then just send
+		 * the put command, no need to do anything else.
+		 */
+		ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible);
+		if (ret == 0)
+			stream->saved = *arg;
+		else
+			BUG_ON(!interruptible);
+
+		return ret;
+	}
+
+	/* We don't start the old stream if we are interrupted.
+	 * Might return -ENOMEM if it can't fit the buffer in vram.
+	 */
+	ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
+	if (ret)
+		return ret;
+
+	ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible);
+	if (ret) {
+		/* This one needs to happen no matter what. We only remove
+		 * the NO_EVICT flag so this is safe from -ENOMEM.
+		 */
+		BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
+		return ret;
+	}
+
+	if (stream->buf != buf)
+		stream->buf = vmw_dmabuf_reference(buf);
+	stream->saved = *arg;
+
+	return 0;
+}
+
+/**
+ * Stop all streams.
+ *
+ * Used by the fb code when starting.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_stop_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		struct vmw_stream *stream = &overlay->stream[i];
+		if (!stream->buf)
+			continue;
+
+		ret = vmw_overlay_stop(dev_priv, i, false, false);
+		WARN_ON(ret != 0);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+/**
+ * Try to resume all paused streams.
+ *
+ * Used by the kms code after moving a new scanout buffer to vram.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_resume_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		struct vmw_stream *stream = &overlay->stream[i];
+		if (!stream->paused)
+			continue;
+
+		ret = vmw_overlay_update_stream(dev_priv, stream->buf,
+						&stream->saved, false);
+		if (ret != 0)
+			DRM_INFO("%s: *warning* failed to resume stream %i\n",
+				 __func__, i);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+/**
+ * Pauses all active streams.
+ *
+ * Used by the kms code when moving a new scanout buffer to vram.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_pause_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		if (overlay->stream[i].paused)
+			DRM_INFO("%s: *warning* stream %i already paused\n",
+				 __func__, i);
+		ret = vmw_overlay_stop(dev_priv, i, true, false);
+		WARN_ON(ret != 0);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+int vmw_overlay_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct drm_vmw_control_stream_arg *arg =
+	    (struct drm_vmw_control_stream_arg *)data;
+	struct vmw_dma_buffer *buf;
+	struct vmw_resource *res;
+	int ret;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	ret = vmw_user_stream_lookup(dev_priv, tfile, &arg->stream_id, &res);
+	if (ret)
+		return ret;
+
+	mutex_lock(&overlay->mutex);
+
+	if (!arg->enabled) {
+		ret = vmw_overlay_stop(dev_priv, arg->stream_id, false, true);
+		goto out_unlock;
+	}
+
+	ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf);
+	if (ret)
+		goto out_unlock;
+
+	ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
+
+	vmw_dmabuf_unreference(&buf);
+
+out_unlock:
+	mutex_unlock(&overlay->mutex);
+	vmw_resource_unreference(&res);
+
+	return ret;
+}
+
+int vmw_overlay_num_overlays(struct vmw_private *dev_priv)
+{
+	if (!dev_priv->overlay_priv)
+		return 0;
+
+	return VMW_MAX_NUM_STREAMS;
+}
+
+int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, k;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0, k = 0; i < VMW_MAX_NUM_STREAMS; i++)
+		if (!overlay->stream[i].claimed)
+			k++;
+
+	mutex_unlock(&overlay->mutex);
+
+	return k;
+}
+
+int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+
+		if (overlay->stream[i].claimed)
+			continue;
+
+		overlay->stream[i].claimed = true;
+		*out = i;
+		mutex_unlock(&overlay->mutex);
+		return 0;
+	}
+
+	mutex_unlock(&overlay->mutex);
+	return -ESRCH;
+}
+
+int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+
+	BUG_ON(stream_id >= VMW_MAX_NUM_STREAMS);
+
+	if (!overlay)
+		return -ENOSYS;
+
+	mutex_lock(&overlay->mutex);
+
+	WARN_ON(!overlay->stream[stream_id].claimed);
+	vmw_overlay_stop(dev_priv, stream_id, false, false);
+	overlay->stream[stream_id].claimed = false;
+
+	mutex_unlock(&overlay->mutex);
+	return 0;
+}
+
+int vmw_overlay_init(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay;
+	int i;
+
+	if (dev_priv->overlay_priv)
+		return -EINVAL;
+
+	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_VIDEO) &&
+	     (dev_priv->fifo.capabilities & SVGA_FIFO_CAP_ESCAPE)) {
+		DRM_INFO("hardware doesn't support overlays\n");
+		return -ENOSYS;
+	}
+
+	overlay = kmalloc(GFP_KERNEL, sizeof(*overlay));
+	if (!overlay)
+		return -ENOMEM;
+
+	memset(overlay, 0, sizeof(*overlay));
+	mutex_init(&overlay->mutex);
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		overlay->stream[i].buf = NULL;
+		overlay->stream[i].paused = false;
+		overlay->stream[i].claimed = false;
+	}
+
+	dev_priv->overlay_priv = overlay;
+
+	return 0;
+}
+
+int vmw_overlay_close(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	bool forgotten_buffer = false;
+	int i;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		if (overlay->stream[i].buf) {
+			forgotten_buffer = true;
+			vmw_overlay_stop(dev_priv, i, false, false);
+		}
+	}
+
+	WARN_ON(forgotten_buffer);
+
+	dev_priv->overlay_priv = NULL;
+	kfree(overlay);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -0,0 +1,783 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "vmwgfx_drv.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_module.h"
+
+#define VMWGFX_DRIVER_NAME "vmwgfx"
+#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
+#define VMWGFX_CHIP_SVGAII 0
+#define VMW_FB_RESERVATION 0
+
+/**
+ * Fully encoded drm commands. Might move to vmw_drm.h
+ */
+
+#define DRM_IOCTL_VMW_GET_PARAM					\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GET_PARAM,		\
+		 struct drm_vmw_getparam_arg)
+#define DRM_IOCTL_VMW_ALLOC_DMABUF				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_ALLOC_DMABUF,	\
+		union drm_vmw_alloc_dmabuf_arg)
+#define DRM_IOCTL_VMW_UNREF_DMABUF				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_DMABUF,	\
+		struct drm_vmw_unref_dmabuf_arg)
+#define DRM_IOCTL_VMW_CURSOR_BYPASS				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_CURSOR_BYPASS,	\
+		 struct drm_vmw_cursor_bypass_arg)
+
+#define DRM_IOCTL_VMW_CONTROL_STREAM				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_CONTROL_STREAM,	\
+		 struct drm_vmw_control_stream_arg)
+#define DRM_IOCTL_VMW_CLAIM_STREAM				\
+	DRM_IOR(DRM_COMMAND_BASE + DRM_VMW_CLAIM_STREAM,	\
+		 struct drm_vmw_stream_arg)
+#define DRM_IOCTL_VMW_UNREF_STREAM				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_STREAM,	\
+		 struct drm_vmw_stream_arg)
+
+#define DRM_IOCTL_VMW_CREATE_CONTEXT				\
+	DRM_IOR(DRM_COMMAND_BASE + DRM_VMW_CREATE_CONTEXT,	\
+		struct drm_vmw_context_arg)
+#define DRM_IOCTL_VMW_UNREF_CONTEXT				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_CONTEXT,	\
+		struct drm_vmw_context_arg)
+#define DRM_IOCTL_VMW_CREATE_SURFACE				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_SURFACE,	\
+		 union drm_vmw_surface_create_arg)
+#define DRM_IOCTL_VMW_UNREF_SURFACE				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_SURFACE,	\
+		 struct drm_vmw_surface_arg)
+#define DRM_IOCTL_VMW_REF_SURFACE				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_REF_SURFACE,	\
+		 union drm_vmw_surface_reference_arg)
+#define DRM_IOCTL_VMW_EXECBUF					\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_EXECBUF,		\
+		struct drm_vmw_execbuf_arg)
+#define DRM_IOCTL_VMW_FIFO_DEBUG				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FIFO_DEBUG,		\
+		 struct drm_vmw_fifo_debug_arg)
+#define DRM_IOCTL_VMW_FENCE_WAIT				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,		\
+		 struct drm_vmw_fence_wait_arg)
+
+
+/**
+ * The core DRM version of this macro doesn't account for
+ * DRM_COMMAND_BASE.
+ */
+
+#define VMW_IOCTL_DEF(ioctl, func, flags) \
+	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+/**
+ * Ioctl definitions.
+ */
+
+static struct drm_ioctl_desc vmw_ioctls[] = {
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS,
+		      vmw_kms_cursor_bypass_ioctl,
+		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl,
+		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
+		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
+		      DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED),
+
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
+		      DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+		      DRM_AUTH | DRM_UNLOCKED)
+};
+
+static struct pci_device_id vmw_pci_id_list[] = {
+	{0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},
+	{0, 0, 0}
+};
+
+static char *vmw_devname = "vmwgfx";
+
+static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
+static void vmw_master_init(struct vmw_master *);
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+			      void *ptr);
+
+static void vmw_print_capabilities(uint32_t capabilities)
+{
+	DRM_INFO("Capabilities:\n");
+	if (capabilities & SVGA_CAP_RECT_COPY)
+		DRM_INFO("  Rect copy.\n");
+	if (capabilities & SVGA_CAP_CURSOR)
+		DRM_INFO("  Cursor.\n");
+	if (capabilities & SVGA_CAP_CURSOR_BYPASS)
+		DRM_INFO("  Cursor bypass.\n");
+	if (capabilities & SVGA_CAP_CURSOR_BYPASS_2)
+		DRM_INFO("  Cursor bypass 2.\n");
+	if (capabilities & SVGA_CAP_8BIT_EMULATION)
+		DRM_INFO("  8bit emulation.\n");
+	if (capabilities & SVGA_CAP_ALPHA_CURSOR)
+		DRM_INFO("  Alpha cursor.\n");
+	if (capabilities & SVGA_CAP_3D)
+		DRM_INFO("  3D.\n");
+	if (capabilities & SVGA_CAP_EXTENDED_FIFO)
+		DRM_INFO("  Extended Fifo.\n");
+	if (capabilities & SVGA_CAP_MULTIMON)
+		DRM_INFO("  Multimon.\n");
+	if (capabilities & SVGA_CAP_PITCHLOCK)
+		DRM_INFO("  Pitchlock.\n");
+	if (capabilities & SVGA_CAP_IRQMASK)
+		DRM_INFO("  Irq mask.\n");
+	if (capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)
+		DRM_INFO("  Display Topology.\n");
+	if (capabilities & SVGA_CAP_GMR)
+		DRM_INFO("  GMR.\n");
+	if (capabilities & SVGA_CAP_TRACES)
+		DRM_INFO("  Traces.\n");
+}
+
+static int vmw_request_device(struct vmw_private *dev_priv)
+{
+	int ret;
+
+	vmw_kms_save_vga(dev_priv);
+
+	ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Unable to initialize FIFO.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void vmw_release_device(struct vmw_private *dev_priv)
+{
+	vmw_fifo_release(dev_priv, &dev_priv->fifo);
+	vmw_kms_restore_vga(dev_priv);
+}
+
+
+static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+	struct vmw_private *dev_priv;
+	int ret;
+	uint32_t svga_id;
+
+	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+	if (unlikely(dev_priv == NULL)) {
+		DRM_ERROR("Failed allocating a device private struct.\n");
+		return -ENOMEM;
+	}
+	memset(dev_priv, 0, sizeof(*dev_priv));
+
+	dev_priv->dev = dev;
+	dev_priv->vmw_chipset = chipset;
+	dev_priv->last_read_sequence = (uint32_t) -100;
+	mutex_init(&dev_priv->hw_mutex);
+	mutex_init(&dev_priv->cmdbuf_mutex);
+	rwlock_init(&dev_priv->resource_lock);
+	idr_init(&dev_priv->context_idr);
+	idr_init(&dev_priv->surface_idr);
+	idr_init(&dev_priv->stream_idr);
+	ida_init(&dev_priv->gmr_ida);
+	mutex_init(&dev_priv->init_mutex);
+	init_waitqueue_head(&dev_priv->fence_queue);
+	init_waitqueue_head(&dev_priv->fifo_queue);
+	atomic_set(&dev_priv->fence_queue_waiters, 0);
+	atomic_set(&dev_priv->fifo_queue_waiters, 0);
+	INIT_LIST_HEAD(&dev_priv->gmr_lru);
+
+	dev_priv->io_start = pci_resource_start(dev->pdev, 0);
+	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
+	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+	svga_id = vmw_read(dev_priv, SVGA_REG_ID);
+	if (svga_id != SVGA_ID_2) {
+		ret = -ENOSYS;
+		DRM_ERROR("Unsuported SVGA ID 0x%x\n", svga_id);
+		mutex_unlock(&dev_priv->hw_mutex);
+		goto out_err0;
+	}
+
+	dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
+
+	if (dev_priv->capabilities & SVGA_CAP_GMR) {
+		dev_priv->max_gmr_descriptors =
+			vmw_read(dev_priv,
+				 SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
+		dev_priv->max_gmr_ids =
+			vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
+	}
+
+	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
+	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
+	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
+	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	vmw_print_capabilities(dev_priv->capabilities);
+
+	if (dev_priv->capabilities & SVGA_CAP_GMR) {
+		DRM_INFO("Max GMR ids is %u\n",
+			 (unsigned)dev_priv->max_gmr_ids);
+		DRM_INFO("Max GMR descriptors is %u\n",
+			 (unsigned)dev_priv->max_gmr_descriptors);
+	}
+	DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
+		 dev_priv->vram_start, dev_priv->vram_size / 1024);
+	DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
+		 dev_priv->mmio_start, dev_priv->mmio_size / 1024);
+
+	ret = vmw_ttm_global_init(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_err0;
+
+
+	vmw_master_init(&dev_priv->fbdev_master);
+	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
+	dev_priv->active_master = &dev_priv->fbdev_master;
+
+
+	ret = ttm_bo_device_init(&dev_priv->bdev,
+				 dev_priv->bo_global_ref.ref.object,
+				 &vmw_bo_driver, VMWGFX_FILE_PAGE_OFFSET,
+				 false);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed initializing TTM buffer object driver.\n");
+		goto out_err1;
+	}
+
+	ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM,
+			     (dev_priv->vram_size >> PAGE_SHIFT));
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed initializing memory manager for VRAM.\n");
+		goto out_err2;
+	}
+
+	dev_priv->mmio_mtrr = drm_mtrr_add(dev_priv->mmio_start,
+					   dev_priv->mmio_size, DRM_MTRR_WC);
+
+	dev_priv->mmio_virt = ioremap_wc(dev_priv->mmio_start,
+					 dev_priv->mmio_size);
+
+	if (unlikely(dev_priv->mmio_virt == NULL)) {
+		ret = -ENOMEM;
+		DRM_ERROR("Failed mapping MMIO.\n");
+		goto out_err3;
+	}
+
+	dev_priv->tdev = ttm_object_device_init
+	    (dev_priv->mem_global_ref.object, 12);
+
+	if (unlikely(dev_priv->tdev == NULL)) {
+		DRM_ERROR("Unable to initialize TTM object management.\n");
+		ret = -ENOMEM;
+		goto out_err4;
+	}
+
+	dev->dev_private = dev_priv;
+
+	if (!dev->devname)
+		dev->devname = vmw_devname;
+
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+		ret = drm_irq_install(dev);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed installing irq: %d\n", ret);
+			goto out_no_irq;
+		}
+	}
+
+	ret = pci_request_regions(dev->pdev, "vmwgfx probe");
+	dev_priv->stealth = (ret != 0);
+	if (dev_priv->stealth) {
+		/**
+		 * Request at least the mmio PCI resource.
+		 */
+
+		DRM_INFO("It appears like vesafb is loaded. "
+			 "Ignore above error if any.\n");
+		ret = pci_request_region(dev->pdev, 2, "vmwgfx stealth probe");
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed reserving the SVGA MMIO resource.\n");
+			goto out_no_device;
+		}
+	}
+	ret = vmw_request_device(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_no_device;
+	vmw_kms_init(dev_priv);
+	vmw_overlay_init(dev_priv);
+	vmw_fb_init(dev_priv);
+
+	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
+	register_pm_notifier(&dev_priv->pm_nb);
+
+	DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");
+
+	return 0;
+
+out_no_device:
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev->devname == vmw_devname)
+		dev->devname = NULL;
+out_no_irq:
+	ttm_object_device_release(&dev_priv->tdev);
+out_err4:
+	iounmap(dev_priv->mmio_virt);
+out_err3:
+	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
+		     dev_priv->mmio_size, DRM_MTRR_WC);
+	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+out_err2:
+	(void)ttm_bo_device_release(&dev_priv->bdev);
+out_err1:
+	vmw_ttm_global_release(dev_priv);
+out_err0:
+	ida_destroy(&dev_priv->gmr_ida);
+	idr_destroy(&dev_priv->surface_idr);
+	idr_destroy(&dev_priv->context_idr);
+	idr_destroy(&dev_priv->stream_idr);
+	kfree(dev_priv);
+	return ret;
+}
+
+static int vmw_driver_unload(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
+
+	unregister_pm_notifier(&dev_priv->pm_nb);
+
+	vmw_fb_close(dev_priv);
+	vmw_kms_close(dev_priv);
+	vmw_overlay_close(dev_priv);
+	vmw_release_device(dev_priv);
+	if (dev_priv->stealth)
+		pci_release_region(dev->pdev, 2);
+	else
+		pci_release_regions(dev->pdev);
+
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev->devname == vmw_devname)
+		dev->devname = NULL;
+	ttm_object_device_release(&dev_priv->tdev);
+	iounmap(dev_priv->mmio_virt);
+	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
+		     dev_priv->mmio_size, DRM_MTRR_WC);
+	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+	(void)ttm_bo_device_release(&dev_priv->bdev);
+	vmw_ttm_global_release(dev_priv);
+	ida_destroy(&dev_priv->gmr_ida);
+	idr_destroy(&dev_priv->surface_idr);
+	idr_destroy(&dev_priv->context_idr);
+	idr_destroy(&dev_priv->stream_idr);
+
+	kfree(dev_priv);
+
+	return 0;
+}
+
+static void vmw_postclose(struct drm_device *dev,
+			 struct drm_file *file_priv)
+{
+	struct vmw_fpriv *vmw_fp;
+
+	vmw_fp = vmw_fpriv(file_priv);
+	ttm_object_file_release(&vmw_fp->tfile);
+	if (vmw_fp->locked_master)
+		drm_master_put(&vmw_fp->locked_master);
+	kfree(vmw_fp);
+}
+
+static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp;
+	int ret = -ENOMEM;
+
+	vmw_fp = kzalloc(sizeof(*vmw_fp), GFP_KERNEL);
+	if (unlikely(vmw_fp == NULL))
+		return ret;
+
+	vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
+	if (unlikely(vmw_fp->tfile == NULL))
+		goto out_no_tfile;
+
+	file_priv->driver_priv = vmw_fp;
+
+	if (unlikely(dev_priv->bdev.dev_mapping == NULL))
+		dev_priv->bdev.dev_mapping =
+			file_priv->filp->f_path.dentry->d_inode->i_mapping;
+
+	return 0;
+
+out_no_tfile:
+	kfree(vmw_fp);
+	return ret;
+}
+
+static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev = file_priv->minor->dev;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+
+	/*
+	 * Do extra checking on driver private ioctls.
+	 */
+
+	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
+	    && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+		struct drm_ioctl_desc *ioctl =
+		    &vmw_ioctls[nr - DRM_COMMAND_BASE];
+
+		if (unlikely(ioctl->cmd != cmd)) {
+			DRM_ERROR("Invalid command format, ioctl %d\n",
+				  nr - DRM_COMMAND_BASE);
+			return -EINVAL;
+		}
+	}
+
+	return drm_ioctl(filp, cmd, arg);
+}
+
+static int vmw_firstopen(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	dev_priv->is_opened = true;
+
+	return 0;
+}
+
+static void vmw_lastclose(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_crtc *crtc;
+	struct drm_mode_set set;
+	int ret;
+
+	/**
+	 * Do nothing on the lastclose call from drm_unload.
+	 */
+
+	if (!dev_priv->is_opened)
+		return;
+
+	dev_priv->is_opened = false;
+	set.x = 0;
+	set.y = 0;
+	set.fb = NULL;
+	set.mode = NULL;
+	set.connectors = NULL;
+	set.num_connectors = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		set.crtc = crtc;
+		ret = crtc->funcs->set_config(&set);
+		WARN_ON(ret != 0);
+	}
+
+}
+
+static void vmw_master_init(struct vmw_master *vmaster)
+{
+	ttm_lock_init(&vmaster->lock);
+}
+
+static int vmw_master_create(struct drm_device *dev,
+			     struct drm_master *master)
+{
+	struct vmw_master *vmaster;
+
+	DRM_INFO("Master create.\n");
+	vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
+	if (unlikely(vmaster == NULL))
+		return -ENOMEM;
+
+	ttm_lock_init(&vmaster->lock);
+	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+	master->driver_priv = vmaster;
+
+	return 0;
+}
+
+static void vmw_master_destroy(struct drm_device *dev,
+			       struct drm_master *master)
+{
+	struct vmw_master *vmaster = vmw_master(master);
+
+	DRM_INFO("Master destroy.\n");
+	master->driver_priv = NULL;
+	kfree(vmaster);
+}
+
+
+static int vmw_master_set(struct drm_device *dev,
+			  struct drm_file *file_priv,
+			  bool from_open)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct vmw_master *active = dev_priv->active_master;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret = 0;
+
+	DRM_INFO("Master set.\n");
+
+	if (active) {
+		BUG_ON(active != &dev_priv->fbdev_master);
+		ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
+		if (unlikely(ret != 0))
+			goto out_no_active_lock;
+
+		ttm_lock_set_kill(&active->lock, true, SIGTERM);
+		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Unable to clean VRAM on "
+				  "master drop.\n");
+		}
+
+		dev_priv->active_master = NULL;
+	}
+
+	ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
+	if (!from_open) {
+		ttm_vt_unlock(&vmaster->lock);
+		BUG_ON(vmw_fp->locked_master != file_priv->master);
+		drm_master_put(&vmw_fp->locked_master);
+	}
+
+	dev_priv->active_master = vmaster;
+
+	return 0;
+
+out_no_active_lock:
+	vmw_release_device(dev_priv);
+	return ret;
+}
+
+static void vmw_master_drop(struct drm_device *dev,
+			    struct drm_file *file_priv,
+			    bool from_release)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	DRM_INFO("Master drop.\n");
+
+	/**
+	 * Make sure the master doesn't disappear while we have
+	 * it locked.
+	 */
+
+	vmw_fp->locked_master = drm_master_get(file_priv->master);
+	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
+
+	if (unlikely((ret != 0))) {
+		DRM_ERROR("Unable to lock TTM at VT switch.\n");
+		drm_master_put(&vmw_fp->locked_master);
+	}
+
+	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+
+	dev_priv->active_master = &dev_priv->fbdev_master;
+	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
+	ttm_vt_unlock(&dev_priv->fbdev_master.lock);
+
+	vmw_fb_on(dev_priv);
+}
+
+
+static void vmw_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_put_dev(dev);
+}
+
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+			      void *ptr)
+{
+	struct vmw_private *dev_priv =
+		container_of(nb, struct vmw_private, pm_nb);
+	struct vmw_master *vmaster = dev_priv->active_master;
+
+	switch (val) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		ttm_suspend_lock(&vmaster->lock);
+
+		/**
+		 * This empties VRAM and unbinds all GMR bindings.
+		 * Buffer contents is moved to swappable memory.
+		 */
+		ttm_bo_swapout_all(&dev_priv->bdev);
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		ttm_suspend_unlock(&vmaster->lock);
+		break;
+	case PM_RESTORE_PREPARE:
+		break;
+	case PM_POST_RESTORE:
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/**
+ * These might not be needed with the virtual SVGA device.
+ */
+
+int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	return 0;
+}
+
+int vmw_pci_resume(struct pci_dev *pdev)
+{
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	return pci_enable_device(pdev);
+}
+
+static struct drm_driver driver = {
+	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+	DRIVER_MODESET,
+	.load = vmw_driver_load,
+	.unload = vmw_driver_unload,
+	.firstopen = vmw_firstopen,
+	.lastclose = vmw_lastclose,
+	.irq_preinstall = vmw_irq_preinstall,
+	.irq_postinstall = vmw_irq_postinstall,
+	.irq_uninstall = vmw_irq_uninstall,
+	.irq_handler = vmw_irq_handler,
+	.reclaim_buffers_locked = NULL,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = vmw_ioctls,
+	.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
+	.dma_quiescent = NULL,	/*vmw_dma_quiescent, */
+	.master_create = vmw_master_create,
+	.master_destroy = vmw_master_destroy,
+	.master_set = vmw_master_set,
+	.master_drop = vmw_master_drop,
+	.open = vmw_driver_open,
+	.postclose = vmw_postclose,
+	.fops = {
+		 .owner = THIS_MODULE,
+		 .open = drm_open,
+		 .release = drm_release,
+		 .unlocked_ioctl = vmw_unlocked_ioctl,
+		 .mmap = vmw_mmap,
+		 .poll = drm_poll,
+		 .fasync = drm_fasync,
+#if defined(CONFIG_COMPAT)
+		 .compat_ioctl = drm_compat_ioctl,
+#endif
+		 },
+	.pci_driver = {
+		       .name = VMWGFX_DRIVER_NAME,
+		       .id_table = vmw_pci_id_list,
+		       .probe = vmw_probe,
+		       .remove = vmw_remove,
+		       .suspend = vmw_pci_suspend,
+		       .resume = vmw_pci_resume
+		       },
+	.name = VMWGFX_DRIVER_NAME,
+	.desc = VMWGFX_DRIVER_DESC,
+	.date = VMWGFX_DRIVER_DATE,
+	.major = VMWGFX_DRIVER_MAJOR,
+	.minor = VMWGFX_DRIVER_MINOR,
+	.patchlevel = VMWGFX_DRIVER_PATCHLEVEL
+};
+
+static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_dev(pdev, ent, &driver);
+}
+
+static int __init vmwgfx_init(void)
+{
+	int ret;
+	ret = drm_init(&driver);
+	if (ret)
+		DRM_ERROR("Failed initializing DRM.\n");
+	return ret;
+}
+
+static void __exit vmwgfx_exit(void)
+{
+	drm_exit(&driver);
+}
+
+module_init(vmwgfx_init);
+module_exit(vmwgfx_exit);
+
+MODULE_AUTHOR("VMware Inc. and others");
+MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device");
+MODULE_LICENSE("GPL and additional rights");
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/Kconfig
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/Kconfig
@@ -0,0 +1,13 @@
+config DRM_VMWGFX
+	tristate "DRM driver for VMware Virtual GPU"
+	depends on DRM && PCI
+	select FB_DEFERRED_IO
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_TTM
+	help
+	  KMS enabled DRM driver for SVGA2 virtual hardware.
+
+	  If unsure say n. The compiled module will be
+	  called vmwgfx.ko
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/svga_overlay.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/svga_overlay.h
@@ -0,0 +1,201 @@
+/**********************************************************
+ * Copyright 2007-2009 VMware, Inc.  All rights reserved.
+ *
+ * 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.
+ *
+ **********************************************************/
+
+/*
+ * svga_overlay.h --
+ *
+ *    Definitions for video-overlay support.
+ */
+
+#ifndef _SVGA_OVERLAY_H_
+#define _SVGA_OVERLAY_H_
+
+#include "svga_reg.h"
+
+/*
+ * Video formats we support
+ */
+
+#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2'
+#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2'
+#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y'
+
+typedef enum {
+   SVGA_OVERLAY_FORMAT_INVALID = 0,
+   SVGA_OVERLAY_FORMAT_YV12 = VMWARE_FOURCC_YV12,
+   SVGA_OVERLAY_FORMAT_YUY2 = VMWARE_FOURCC_YUY2,
+   SVGA_OVERLAY_FORMAT_UYVY = VMWARE_FOURCC_UYVY,
+} SVGAOverlayFormat;
+
+#define SVGA_VIDEO_COLORKEY_MASK             0x00ffffff
+
+#define SVGA_ESCAPE_VMWARE_VIDEO             0x00020000
+
+#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS    0x00020001
+        /* FIFO escape layout:
+         * Type, Stream Id, (Register Id, Value) pairs */
+
+#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH       0x00020002
+        /* FIFO escape layout:
+         * Type, Stream Id */
+
+typedef
+struct SVGAEscapeVideoSetRegs {
+   struct {
+      uint32 cmdType;
+      uint32 streamId;
+   } header;
+
+   // May include zero or more items.
+   struct {
+      uint32 registerId;
+      uint32 value;
+   } items[1];
+} SVGAEscapeVideoSetRegs;
+
+typedef
+struct SVGAEscapeVideoFlush {
+   uint32 cmdType;
+   uint32 streamId;
+} SVGAEscapeVideoFlush;
+
+
+/*
+ * Struct definitions for the video overlay commands built on
+ * SVGAFifoCmdEscape.
+ */
+typedef
+struct {
+   uint32 command;
+   uint32 overlay;
+} SVGAFifoEscapeCmdVideoBase;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+} SVGAFifoEscapeCmdVideoFlush;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+   struct {
+      uint32 regId;
+      uint32 value;
+   } items[1];
+} SVGAFifoEscapeCmdVideoSetRegs;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+   struct {
+      uint32 regId;
+      uint32 value;
+   } items[SVGA_VIDEO_NUM_REGS];
+} SVGAFifoEscapeCmdVideoSetAllRegs;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMwareVideoGetAttributes --
+ *
+ *      Computes the size, pitches and offsets for YUV frames.
+ *
+ * Results:
+ *      TRUE on success; otherwise FALSE on failure.
+ *
+ * Side effects:
+ *      Pitches and offsets for the given YUV frame are put in 'pitches'
+ *      and 'offsets' respectively. They are both optional though.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline bool
+VMwareVideoGetAttributes(const SVGAOverlayFormat format,    // IN
+                         uint32 *width,                     // IN / OUT
+                         uint32 *height,                    // IN / OUT
+                         uint32 *size,                      // OUT
+                         uint32 *pitches,                   // OUT (optional)
+                         uint32 *offsets)                   // OUT (optional)
+{
+    int tmp;
+
+    *width = (*width + 1) & ~1;
+
+    if (offsets) {
+        offsets[0] = 0;
+    }
+
+    switch (format) {
+    case VMWARE_FOURCC_YV12:
+       *height = (*height + 1) & ~1;
+       *size = (*width + 3) & ~3;
+
+       if (pitches) {
+          pitches[0] = *size;
+       }
+
+       *size *= *height;
+
+       if (offsets) {
+          offsets[1] = *size;
+       }
+
+       tmp = ((*width >> 1) + 3) & ~3;
+
+       if (pitches) {
+          pitches[1] = pitches[2] = tmp;
+       }
+
+       tmp *= (*height >> 1);
+       *size += tmp;
+
+       if (offsets) {
+          offsets[2] = *size;
+       }
+
+       *size += tmp;
+       break;
+
+    case VMWARE_FOURCC_YUY2:
+    case VMWARE_FOURCC_UYVY:
+       *size = *width * 2;
+
+       if (pitches) {
+          pitches[0] = *size;
+       }
+
+       *size *= *height;
+       break;
+
+    default:
+       return false;
+    }
+
+    return true;
+}
+
+#endif // _SVGA_OVERLAY_H_
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 VMWGFX_KMS_H_
+#define VMWGFX_KMS_H_
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+
+#define vmw_framebuffer_to_vfb(x) \
+	container_of(x, struct vmw_framebuffer, base)
+
+/**
+ * Base class for framebuffers
+ *
+ * @pin is called the when ever a crtc uses this framebuffer
+ * @unpin is called
+ */
+struct vmw_framebuffer {
+	struct drm_framebuffer base;
+	int (*pin)(struct vmw_framebuffer *fb);
+	int (*unpin)(struct vmw_framebuffer *fb);
+};
+
+
+#define vmw_crtc_to_du(x) \
+	container_of(x, struct vmw_display_unit, crtc)
+
+/*
+ * Basic cursor manipulation
+ */
+int vmw_cursor_update_image(struct vmw_private *dev_priv,
+			    u32 *image, u32 width, u32 height,
+			    u32 hotspotX, u32 hotspotY);
+void vmw_cursor_update_position(struct vmw_private *dev_priv,
+				bool show, int x, int y);
+
+/**
+ * Base class display unit.
+ *
+ * Since the SVGA hw doesn't have a concept of a crtc, encoder or connector
+ * so the display unit is all of them at the same time. This is true for both
+ * legacy multimon and screen objects.
+ */
+struct vmw_display_unit {
+	struct drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+
+	struct vmw_surface *cursor_surface;
+	struct vmw_dma_buffer *cursor_dmabuf;
+	size_t cursor_age;
+
+	int cursor_x;
+	int cursor_y;
+
+	int hotspot_x;
+	int hotspot_y;
+
+	unsigned unit;
+};
+
+/*
+ * Shared display unit functions - vmwgfx_kms.c
+ */
+void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+			   uint32_t handle, uint32_t width, uint32_t height);
+int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+
+/*
+ * Legacy display unit functions - vmwgfx_ldu.h
+ */
+int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
+int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/svga_types.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/svga_types.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+/**
+ * Silly typedefs for the svga headers. Currently the headers are shared
+ * between all components that talk to svga. And as such the headers are
+ * are in a completely different style and use weird defines.
+ *
+ * This file lets all the ugly be prefixed with svga*.
+ */
+
+#ifndef _SVGA_TYPES_H_
+#define _SVGA_TYPES_H_
+
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint8_t uint8;
+typedef int32_t int32;
+typedef bool Bool;
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -0,0 +1,521 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 _VMWGFX_DRV_H_
+#define _VMWGFX_DRV_H_
+
+#include "vmwgfx_reg.h"
+#include "drmP.h"
+#include "vmwgfx_drm.h"
+#include "drm_hashtab.h"
+#include "linux/suspend.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_lock.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "ttm/ttm_module.h"
+
+#define VMWGFX_DRIVER_DATE "20100209"
+#define VMWGFX_DRIVER_MAJOR 1
+#define VMWGFX_DRIVER_MINOR 0
+#define VMWGFX_DRIVER_PATCHLEVEL 0
+#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
+#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
+#define VMWGFX_MAX_RELOCATIONS 2048
+#define VMWGFX_MAX_GMRS 2048
+
+struct vmw_fpriv {
+	struct drm_master *locked_master;
+	struct ttm_object_file *tfile;
+};
+
+struct vmw_dma_buffer {
+	struct ttm_buffer_object base;
+	struct list_head validate_list;
+	struct list_head gmr_lru;
+	uint32_t gmr_id;
+	bool gmr_bound;
+	uint32_t cur_validate_node;
+	bool on_validate_list;
+};
+
+struct vmw_resource {
+	struct kref kref;
+	struct vmw_private *dev_priv;
+	struct idr *idr;
+	int id;
+	enum ttm_object_type res_type;
+	bool avail;
+	void (*hw_destroy) (struct vmw_resource *res);
+	void (*res_free) (struct vmw_resource *res);
+
+	/* TODO is a generic snooper needed? */
+#if 0
+	void (*snoop)(struct vmw_resource *res,
+		      struct ttm_object_file *tfile,
+		      SVGA3dCmdHeader *header);
+	void *snoop_priv;
+#endif
+};
+
+struct vmw_cursor_snooper {
+	struct drm_crtc *crtc;
+	size_t age;
+	uint32_t *image;
+};
+
+struct vmw_surface {
+	struct vmw_resource res;
+	uint32_t flags;
+	uint32_t format;
+	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
+	struct drm_vmw_size *sizes;
+	uint32_t num_sizes;
+
+	bool scanout;
+
+	/* TODO so far just a extra pointer */
+	struct vmw_cursor_snooper snooper;
+};
+
+struct vmw_fifo_state {
+	unsigned long reserved_size;
+	__le32 *dynamic_buffer;
+	__le32 *static_buffer;
+	__le32 *last_buffer;
+	uint32_t last_data_size;
+	uint32_t last_buffer_size;
+	bool last_buffer_add;
+	unsigned long static_buffer_size;
+	bool using_bounce_buffer;
+	uint32_t capabilities;
+	struct mutex fifo_mutex;
+	struct rw_semaphore rwsem;
+};
+
+struct vmw_relocation {
+	SVGAGuestPtr *location;
+	uint32_t index;
+};
+
+struct vmw_sw_context{
+	struct ida bo_list;
+	uint32_t last_cid;
+	bool cid_valid;
+	uint32_t last_sid;
+	uint32_t sid_translation;
+	bool sid_valid;
+	struct ttm_object_file *tfile;
+	struct list_head validate_nodes;
+	struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
+	uint32_t cur_reloc;
+	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
+	uint32_t cur_val_buf;
+};
+
+struct vmw_legacy_display;
+struct vmw_overlay;
+
+struct vmw_master {
+	struct ttm_lock lock;
+};
+
+struct vmw_private {
+	struct ttm_bo_device bdev;
+	struct ttm_bo_global_ref bo_global_ref;
+	struct ttm_global_reference mem_global_ref;
+
+	struct vmw_fifo_state fifo;
+
+	struct drm_device *dev;
+	unsigned long vmw_chipset;
+	unsigned int io_start;
+	uint32_t vram_start;
+	uint32_t vram_size;
+	uint32_t mmio_start;
+	uint32_t mmio_size;
+	uint32_t fb_max_width;
+	uint32_t fb_max_height;
+	__le32 __iomem *mmio_virt;
+	int mmio_mtrr;
+	uint32_t capabilities;
+	uint32_t max_gmr_descriptors;
+	uint32_t max_gmr_ids;
+	struct mutex hw_mutex;
+
+	/*
+	 * VGA registers.
+	 */
+
+	uint32_t vga_width;
+	uint32_t vga_height;
+	uint32_t vga_depth;
+	uint32_t vga_bpp;
+	uint32_t vga_pseudo;
+	uint32_t vga_red_mask;
+	uint32_t vga_blue_mask;
+	uint32_t vga_green_mask;
+
+	/*
+	 * Framebuffer info.
+	 */
+
+	void *fb_info;
+	struct vmw_legacy_display *ldu_priv;
+	struct vmw_overlay *overlay_priv;
+
+	/*
+	 * Context and surface management.
+	 */
+
+	rwlock_t resource_lock;
+	struct idr context_idr;
+	struct idr surface_idr;
+	struct idr stream_idr;
+
+	/*
+	 * Block lastclose from racing with firstopen.
+	 */
+
+	struct mutex init_mutex;
+
+	/*
+	 * A resource manager for kernel-only surfaces and
+	 * contexts.
+	 */
+
+	struct ttm_object_device *tdev;
+
+	/*
+	 * Fencing and IRQs.
+	 */
+
+	atomic_t fence_seq;
+	wait_queue_head_t fence_queue;
+	wait_queue_head_t fifo_queue;
+	atomic_t fence_queue_waiters;
+	atomic_t fifo_queue_waiters;
+	uint32_t last_read_sequence;
+	spinlock_t irq_lock;
+
+	/*
+	 * Device state
+	 */
+
+	uint32_t traces_state;
+	uint32_t enable_state;
+	uint32_t config_done_state;
+
+	/**
+	 * Execbuf
+	 */
+	/**
+	 * Protected by the cmdbuf mutex.
+	 */
+
+	struct vmw_sw_context ctx;
+	uint32_t val_seq;
+	struct mutex cmdbuf_mutex;
+
+	/**
+	 * GMR management. Protected by the lru spinlock.
+	 */
+
+	struct ida gmr_ida;
+	struct list_head gmr_lru;
+
+
+	/**
+	 * Operating mode.
+	 */
+
+	bool stealth;
+	bool is_opened;
+
+	/**
+	 * Master management.
+	 */
+
+	struct vmw_master *active_master;
+	struct vmw_master fbdev_master;
+	struct notifier_block pm_nb;
+};
+
+static inline struct vmw_private *vmw_priv(struct drm_device *dev)
+{
+	return (struct vmw_private *)dev->dev_private;
+}
+
+static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv)
+{
+	return (struct vmw_fpriv *)file_priv->driver_priv;
+}
+
+static inline struct vmw_master *vmw_master(struct drm_master *master)
+{
+	return (struct vmw_master *) master->driver_priv;
+}
+
+static inline void vmw_write(struct vmw_private *dev_priv,
+			     unsigned int offset, uint32_t value)
+{
+	outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT);
+	outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT);
+}
+
+static inline uint32_t vmw_read(struct vmw_private *dev_priv,
+				unsigned int offset)
+{
+	uint32_t val;
+
+	outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT);
+	val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT);
+	return val;
+}
+
+/**
+ * GMR utilities - vmwgfx_gmr.c
+ */
+
+extern int vmw_gmr_bind(struct vmw_private *dev_priv,
+			struct ttm_buffer_object *bo);
+extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
+
+/**
+ * Resource utilities - vmwgfx_resource.c
+ */
+
+extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
+extern void vmw_resource_unreference(struct vmw_resource **p_res);
+extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
+extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+extern int vmw_context_check(struct vmw_private *dev_priv,
+			     struct ttm_object_file *tfile,
+			     int id);
+extern void vmw_surface_res_free(struct vmw_resource *res);
+extern int vmw_surface_init(struct vmw_private *dev_priv,
+			    struct vmw_surface *srf,
+			    void (*res_free) (struct vmw_resource *res));
+extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
+					  struct ttm_object_file *tfile,
+					  uint32_t handle,
+					  struct vmw_surface **out);
+extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv);
+extern int vmw_surface_check(struct vmw_private *dev_priv,
+			     struct ttm_object_file *tfile,
+			     uint32_t handle, int *id);
+extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
+extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
+			   struct vmw_dma_buffer *vmw_bo,
+			   size_t size, struct ttm_placement *placement,
+			   bool interuptable,
+			   void (*bo_free) (struct ttm_buffer_object *bo));
+extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
+					 uint32_t cur_validate_node);
+extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
+extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
+				  uint32_t id, struct vmw_dma_buffer **out);
+extern uint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo);
+extern void vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id);
+extern int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id);
+extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				       struct vmw_dma_buffer *bo);
+extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
+				struct vmw_dma_buffer *bo);
+extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo);
+extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
+				  struct ttm_object_file *tfile,
+				  uint32_t *inout_id,
+				  struct vmw_resource **out);
+
+
+/**
+ * Misc Ioctl functionality - vmwgfx_ioctl.c
+ */
+
+extern int vmw_getparam_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+extern int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+
+/**
+ * Fifo utilities - vmwgfx_fifo.c
+ */
+
+extern int vmw_fifo_init(struct vmw_private *dev_priv,
+			 struct vmw_fifo_state *fifo);
+extern void vmw_fifo_release(struct vmw_private *dev_priv,
+			     struct vmw_fifo_state *fifo);
+extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes);
+extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes);
+extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
+			       uint32_t *sequence);
+extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
+extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
+extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv);
+
+/**
+ * TTM glue - vmwgfx_ttm_glue.c
+ */
+
+extern int vmw_ttm_global_init(struct vmw_private *dev_priv);
+extern void vmw_ttm_global_release(struct vmw_private *dev_priv);
+extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/**
+ * TTM buffer object driver - vmwgfx_buffer.c
+ */
+
+extern struct ttm_placement vmw_vram_placement;
+extern struct ttm_placement vmw_vram_ne_placement;
+extern struct ttm_placement vmw_vram_sys_placement;
+extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_bo_driver vmw_bo_driver;
+extern int vmw_dma_quiescent(struct drm_device *dev);
+
+/**
+ * Command submission - vmwgfx_execbuf.c
+ */
+
+extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+
+/**
+ * IRQs and wating - vmwgfx_irq.c
+ */
+
+extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
+extern int vmw_wait_fence(struct vmw_private *dev_priv, bool lazy,
+			  uint32_t sequence, bool interruptible,
+			  unsigned long timeout);
+extern void vmw_irq_preinstall(struct drm_device *dev);
+extern int vmw_irq_postinstall(struct drm_device *dev);
+extern void vmw_irq_uninstall(struct drm_device *dev);
+extern bool vmw_fence_signaled(struct vmw_private *dev_priv,
+			       uint32_t sequence);
+extern int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+extern int vmw_fallback_wait(struct vmw_private *dev_priv,
+			     bool lazy,
+			     bool fifo_idle,
+			     uint32_t sequence,
+			     bool interruptible,
+			     unsigned long timeout);
+
+/**
+ * Kernel framebuffer - vmwgfx_fb.c
+ */
+
+int vmw_fb_init(struct vmw_private *vmw_priv);
+int vmw_fb_close(struct vmw_private *dev_priv);
+int vmw_fb_off(struct vmw_private *vmw_priv);
+int vmw_fb_on(struct vmw_private *vmw_priv);
+
+/**
+ * Kernel modesetting - vmwgfx_kms.c
+ */
+
+int vmw_kms_init(struct vmw_private *dev_priv);
+int vmw_kms_close(struct vmw_private *dev_priv);
+int vmw_kms_save_vga(struct vmw_private *vmw_priv);
+int vmw_kms_restore_vga(struct vmw_private *vmw_priv);
+int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv);
+void vmw_kms_cursor_snoop(struct vmw_surface *srf,
+			  struct ttm_object_file *tfile,
+			  struct ttm_buffer_object *bo,
+			  SVGA3dCmdHeader *header);
+
+/**
+ * Overlay control - vmwgfx_overlay.c
+ */
+
+int vmw_overlay_init(struct vmw_private *dev_priv);
+int vmw_overlay_close(struct vmw_private *dev_priv);
+int vmw_overlay_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int vmw_overlay_stop_all(struct vmw_private *dev_priv);
+int vmw_overlay_resume_all(struct vmw_private *dev_priv);
+int vmw_overlay_pause_all(struct vmw_private *dev_priv);
+int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out);
+int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id);
+int vmw_overlay_num_overlays(struct vmw_private *dev_priv);
+int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv);
+
+/**
+ * Inline helper functions
+ */
+
+static inline void vmw_surface_unreference(struct vmw_surface **srf)
+{
+	struct vmw_surface *tmp_srf = *srf;
+	struct vmw_resource *res = &tmp_srf->res;
+	*srf = NULL;
+
+	vmw_resource_unreference(&res);
+}
+
+static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf)
+{
+	(void) vmw_resource_reference(&srf->res);
+	return srf;
+}
+
+static inline void vmw_dmabuf_unreference(struct vmw_dma_buffer **buf)
+{
+	struct vmw_dma_buffer *tmp_buf = *buf;
+	struct ttm_buffer_object *bo = &tmp_buf->base;
+	*buf = NULL;
+
+	ttm_bo_unref(&bo);
+}
+
+static inline struct vmw_dma_buffer *vmw_dmabuf_reference(struct vmw_dma_buffer *buf)
+{
+	if (ttm_bo_reference(&buf->base))
+		return buf;
+	return NULL;
+}
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/svga_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/svga_reg.h
@@ -0,0 +1,1346 @@
+/**********************************************************
+ * Copyright 1998-2009 VMware, Inc.  All rights reserved.
+ *
+ * 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.
+ *
+ **********************************************************/
+
+/*
+ * svga_reg.h --
+ *
+ *    Virtual hardware definitions for the VMware SVGA II device.
+ */
+
+#ifndef _SVGA_REG_H_
+#define _SVGA_REG_H_
+
+/*
+ * PCI device IDs.
+ */
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
+
+/*
+ * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
+ * cursor bypass mode. This is still supported, but no new guest
+ * drivers should use it.
+ */
+#define SVGA_CURSOR_ON_HIDE            0x0   /* Must be 0 to maintain backward compatibility */
+#define SVGA_CURSOR_ON_SHOW            0x1   /* Must be 1 to maintain backward compatibility */
+#define SVGA_CURSOR_ON_REMOVE_FROM_FB  0x2   /* Remove the cursor from the framebuffer because we need to see what's under it */
+#define SVGA_CURSOR_ON_RESTORE_TO_FB   0x3   /* Put the cursor back in the framebuffer so the user can see it */
+
+/*
+ * The maximum framebuffer size that can traced for e.g. guests in VESA mode.
+ * The changeMap in the monitor is proportional to this number. Therefore, we'd
+ * like to keep it as small as possible to reduce monitor overhead (using
+ * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over
+ * 4k!).
+ *
+ * NB: For compatibility reasons, this value must be greater than 0xff0000.
+ *     See bug 335072.
+ */
+#define SVGA_FB_MAX_TRACEABLE_SIZE      0x1000000
+
+#define SVGA_MAX_PSEUDOCOLOR_DEPTH      8
+#define SVGA_MAX_PSEUDOCOLORS           (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
+#define SVGA_NUM_PALETTE_REGS           (3 * SVGA_MAX_PSEUDOCOLORS)
+
+#define SVGA_MAGIC         0x900000UL
+#define SVGA_MAKE_ID(ver)  (SVGA_MAGIC << 8 | (ver))
+
+/* Version 2 let the address of the frame buffer be unsigned on Win32 */
+#define SVGA_VERSION_2     2
+#define SVGA_ID_2          SVGA_MAKE_ID(SVGA_VERSION_2)
+
+/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so
+   PALETTE_BASE has moved */
+#define SVGA_VERSION_1     1
+#define SVGA_ID_1          SVGA_MAKE_ID(SVGA_VERSION_1)
+
+/* Version 0 is the initial version */
+#define SVGA_VERSION_0     0
+#define SVGA_ID_0          SVGA_MAKE_ID(SVGA_VERSION_0)
+
+/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */
+#define SVGA_ID_INVALID    0xFFFFFFFF
+
+/* Port offsets, relative to BAR0 */
+#define SVGA_INDEX_PORT         0x0
+#define SVGA_VALUE_PORT         0x1
+#define SVGA_BIOS_PORT          0x2
+#define SVGA_IRQSTATUS_PORT     0x8
+
+/*
+ * Interrupt source flags for IRQSTATUS_PORT and IRQMASK.
+ *
+ * Interrupts are only supported when the
+ * SVGA_CAP_IRQMASK capability is present.
+ */
+#define SVGA_IRQFLAG_ANY_FENCE            0x1    /* Any fence was passed */
+#define SVGA_IRQFLAG_FIFO_PROGRESS        0x2    /* Made forward progress in the FIFO */
+#define SVGA_IRQFLAG_FENCE_GOAL           0x4    /* SVGA_FIFO_FENCE_GOAL reached */
+
+/*
+ * Registers
+ */
+
+enum {
+   SVGA_REG_ID = 0,
+   SVGA_REG_ENABLE = 1,
+   SVGA_REG_WIDTH = 2,
+   SVGA_REG_HEIGHT = 3,
+   SVGA_REG_MAX_WIDTH = 4,
+   SVGA_REG_MAX_HEIGHT = 5,
+   SVGA_REG_DEPTH = 6,
+   SVGA_REG_BITS_PER_PIXEL = 7,       /* Current bpp in the guest */
+   SVGA_REG_PSEUDOCOLOR = 8,
+   SVGA_REG_RED_MASK = 9,
+   SVGA_REG_GREEN_MASK = 10,
+   SVGA_REG_BLUE_MASK = 11,
+   SVGA_REG_BYTES_PER_LINE = 12,
+   SVGA_REG_FB_START = 13,            /* (Deprecated) */
+   SVGA_REG_FB_OFFSET = 14,
+   SVGA_REG_VRAM_SIZE = 15,
+   SVGA_REG_FB_SIZE = 16,
+
+   /* ID 0 implementation only had the above registers, then the palette */
+
+   SVGA_REG_CAPABILITIES = 17,
+   SVGA_REG_MEM_START = 18,           /* (Deprecated) */
+   SVGA_REG_MEM_SIZE = 19,
+   SVGA_REG_CONFIG_DONE = 20,         /* Set when memory area configured */
+   SVGA_REG_SYNC = 21,                /* See "FIFO Synchronization Registers" */
+   SVGA_REG_BUSY = 22,                /* See "FIFO Synchronization Registers" */
+   SVGA_REG_GUEST_ID = 23,            /* Set guest OS identifier */
+   SVGA_REG_CURSOR_ID = 24,           /* (Deprecated) */
+   SVGA_REG_CURSOR_X = 25,            /* (Deprecated) */
+   SVGA_REG_CURSOR_Y = 26,            /* (Deprecated) */
+   SVGA_REG_CURSOR_ON = 27,           /* (Deprecated) */
+   SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */
+   SVGA_REG_SCRATCH_SIZE = 29,        /* Number of scratch registers */
+   SVGA_REG_MEM_REGS = 30,            /* Number of FIFO registers */
+   SVGA_REG_NUM_DISPLAYS = 31,        /* (Deprecated) */
+   SVGA_REG_PITCHLOCK = 32,           /* Fixed pitch for all modes */
+   SVGA_REG_IRQMASK = 33,             /* Interrupt mask */
+
+   /* Legacy multi-monitor support */
+   SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */
+   SVGA_REG_DISPLAY_ID = 35,        /* Display ID for the following display attributes */
+   SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */
+   SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */
+   SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */
+   SVGA_REG_DISPLAY_WIDTH = 39,     /* The display's width */
+   SVGA_REG_DISPLAY_HEIGHT = 40,    /* The display's height */
+
+   /* See "Guest memory regions" below. */
+   SVGA_REG_GMR_ID = 41,
+   SVGA_REG_GMR_DESCRIPTOR = 42,
+   SVGA_REG_GMR_MAX_IDS = 43,
+   SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
+
+   SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
+   SVGA_REG_TOP = 46,               /* Must be 1 more than the last register */
+
+   SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
+   /* Next 768 (== 256*3) registers exist for colormap */
+
+   SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
+                                    /* Base of scratch registers */
+   /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage:
+      First 4 are reserved for VESA BIOS Extension; any remaining are for
+      the use of the current SVGA driver. */
+};
+
+
+/*
+ * Guest memory regions (GMRs):
+ *
+ * This is a new memory mapping feature available in SVGA devices
+ * which have the SVGA_CAP_GMR bit set. Previously, there were two
+ * fixed memory regions available with which to share data between the
+ * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs
+ * are our name for an extensible way of providing arbitrary DMA
+ * buffers for use between the driver and the SVGA device. They are a
+ * new alternative to framebuffer memory, usable for both 2D and 3D
+ * graphics operations.
+ *
+ * Since GMR mapping must be done synchronously with guest CPU
+ * execution, we use a new pair of SVGA registers:
+ *
+ *   SVGA_REG_GMR_ID --
+ *
+ *     Read/write.
+ *     This register holds the 32-bit ID (a small positive integer)
+ *     of a GMR to create, delete, or redefine. Writing this register
+ *     has no side-effects.
+ *
+ *   SVGA_REG_GMR_DESCRIPTOR --
+ *
+ *     Write-only.
+ *     Writing this register will create, delete, or redefine the GMR
+ *     specified by the above ID register. If this register is zero,
+ *     the GMR is deleted. Any pointers into this GMR (including those
+ *     currently being processed by FIFO commands) will be
+ *     synchronously invalidated.
+ *
+ *     If this register is nonzero, it must be the physical page
+ *     number (PPN) of a data structure which describes the physical
+ *     layout of the memory region this GMR should describe. The
+ *     descriptor structure will be read synchronously by the SVGA
+ *     device when this register is written. The descriptor need not
+ *     remain allocated for the lifetime of the GMR.
+ *
+ *     The guest driver should write SVGA_REG_GMR_ID first, then
+ *     SVGA_REG_GMR_DESCRIPTOR.
+ *
+ *   SVGA_REG_GMR_MAX_IDS --
+ *
+ *     Read-only.
+ *     The SVGA device may choose to support a maximum number of
+ *     user-defined GMR IDs. This register holds the number of supported
+ *     IDs. (The maximum supported ID plus 1)
+ *
+ *   SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH --
+ *
+ *     Read-only.
+ *     The SVGA device may choose to put a limit on the total number
+ *     of SVGAGuestMemDescriptor structures it will read when defining
+ *     a single GMR.
+ *
+ * The descriptor structure is an array of SVGAGuestMemDescriptor
+ * structures. Each structure may do one of three things:
+ *
+ *   - Terminate the GMR descriptor list.
+ *     (ppn==0, numPages==0)
+ *
+ *   - Add a PPN or range of PPNs to the GMR's virtual address space.
+ *     (ppn != 0, numPages != 0)
+ *
+ *   - Provide the PPN of the next SVGAGuestMemDescriptor, in order to
+ *     support multi-page GMR descriptor tables without forcing the
+ *     driver to allocate physically contiguous memory.
+ *     (ppn != 0, numPages == 0)
+ *
+ * Note that each physical page of SVGAGuestMemDescriptor structures
+ * can describe at least 2MB of guest memory. If the driver needs to
+ * use more than one page of descriptor structures, it must use one of
+ * its SVGAGuestMemDescriptors to point to an additional page.  The
+ * device will never automatically cross a page boundary.
+ *
+ * Once the driver has described a GMR, it is immediately available
+ * for use via any FIFO command that uses an SVGAGuestPtr structure.
+ * These pointers include a GMR identifier plus an offset into that
+ * GMR.
+ *
+ * The driver must check the SVGA_CAP_GMR bit before using the GMR
+ * registers.
+ */
+
+/*
+ * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer
+ * memory as well.  In the future, these IDs could even be used to
+ * allow legacy memory regions to be redefined by the guest as GMRs.
+ *
+ * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA
+ * is being phased out. Please try to use user-defined GMRs whenever
+ * possible.
+ */
+#define SVGA_GMR_NULL         ((uint32) -1)
+#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  // Guest Framebuffer (GFB)
+
+typedef
+struct SVGAGuestMemDescriptor {
+   uint32 ppn;
+   uint32 numPages;
+} SVGAGuestMemDescriptor;
+
+typedef
+struct SVGAGuestPtr {
+   uint32 gmrId;
+   uint32 offset;
+} SVGAGuestPtr;
+
+
+/*
+ * SVGAGMRImageFormat --
+ *
+ *    This is a packed representation of the source 2D image format
+ *    for a GMR-to-screen blit. Currently it is defined as an encoding
+ *    of the screen's color depth and bits-per-pixel, however, 16 bits
+ *    are reserved for future use to identify other encodings (such as
+ *    RGBA or higher-precision images).
+ *
+ *    Currently supported formats:
+ *
+ *       bpp depth  Format Name
+ *       --- -----  -----------
+ *        32    24  32-bit BGRX
+ *        24    24  24-bit BGR
+ *        16    16  RGB 5-6-5
+ *        16    15  RGB 5-5-5
+ *
+ */
+
+typedef
+struct SVGAGMRImageFormat {
+   union {
+      struct {
+         uint32 bitsPerPixel : 8;
+         uint32 colorDepth   : 8;
+         uint32 reserved     : 16;  // Must be zero
+      };
+
+      uint32 value;
+   };
+} SVGAGMRImageFormat;
+
+/*
+ * SVGAColorBGRX --
+ *
+ *    A 24-bit color format (BGRX), which does not depend on the
+ *    format of the legacy guest framebuffer (GFB) or the current
+ *    GMRFB state.
+ */
+
+typedef
+struct SVGAColorBGRX {
+   union {
+      struct {
+         uint32 b : 8;
+         uint32 g : 8;
+         uint32 r : 8;
+         uint32 x : 8;  // Unused
+      };
+
+      uint32 value;
+   };
+} SVGAColorBGRX;
+
+
+/*
+ * SVGASignedRect --
+ * SVGASignedPoint --
+ *
+ *    Signed rectangle and point primitives. These are used by the new
+ *    2D primitives for drawing to Screen Objects, which can occupy a
+ *    signed virtual coordinate space.
+ *
+ *    SVGASignedRect specifies a half-open interval: the (left, top)
+ *    pixel is part of the rectangle, but the (right, bottom) pixel is
+ *    not.
+ */
+
+typedef
+struct SVGASignedRect {
+   int32  left;
+   int32  top;
+   int32  right;
+   int32  bottom;
+} SVGASignedRect;
+
+typedef
+struct SVGASignedPoint {
+   int32  x;
+   int32  y;
+} SVGASignedPoint;
+
+
+/*
+ *  Capabilities
+ *
+ *  Note the holes in the bitfield. Missing bits have been deprecated,
+ *  and must not be reused. Those capabilities will never be reported
+ *  by new versions of the SVGA device.
+ */
+
+#define SVGA_CAP_NONE               0x00000000
+#define SVGA_CAP_RECT_COPY          0x00000002
+#define SVGA_CAP_CURSOR             0x00000020
+#define SVGA_CAP_CURSOR_BYPASS      0x00000040   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_8BIT_EMULATION     0x00000100
+#define SVGA_CAP_ALPHA_CURSOR       0x00000200
+#define SVGA_CAP_3D                 0x00004000
+#define SVGA_CAP_EXTENDED_FIFO      0x00008000
+#define SVGA_CAP_MULTIMON           0x00010000   // Legacy multi-monitor support
+#define SVGA_CAP_PITCHLOCK          0x00020000
+#define SVGA_CAP_IRQMASK            0x00040000
+#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   // Legacy multi-monitor support
+#define SVGA_CAP_GMR                0x00100000
+#define SVGA_CAP_TRACES             0x00200000
+
+
+/*
+ * FIFO register indices.
+ *
+ * The FIFO is a chunk of device memory mapped into guest physmem.  It
+ * is always treated as 32-bit words.
+ *
+ * The guest driver gets to decide how to partition it between
+ * - FIFO registers (there are always at least 4, specifying where the
+ *   following data area is and how much data it contains; there may be
+ *   more registers following these, depending on the FIFO protocol
+ *   version in use)
+ * - FIFO data, written by the guest and slurped out by the VMX.
+ * These indices are 32-bit word offsets into the FIFO.
+ */
+
+enum {
+   /*
+    * Block 1 (basic registers): The originally defined FIFO registers.
+    * These exist and are valid for all versions of the FIFO protocol.
+    */
+
+   SVGA_FIFO_MIN = 0,
+   SVGA_FIFO_MAX,       /* The distance from MIN to MAX must be at least 10K */
+   SVGA_FIFO_NEXT_CMD,
+   SVGA_FIFO_STOP,
+
+   /*
+    * Block 2 (extended registers): Mandatory registers for the extended
+    * FIFO.  These exist if the SVGA caps register includes
+    * SVGA_CAP_EXTENDED_FIFO; some of them are valid only if their
+    * associated capability bit is enabled.
+    *
+    * Note that when originally defined, SVGA_CAP_EXTENDED_FIFO implied
+    * support only for (FIFO registers) CAPABILITIES, FLAGS, and FENCE.
+    * This means that the guest has to test individually (in most cases
+    * using FIFO caps) for the presence of registers after this; the VMX
+    * can define "extended FIFO" to mean whatever it wants, and currently
+    * won't enable it unless there's room for that set and much more.
+    */
+
+   SVGA_FIFO_CAPABILITIES = 4,
+   SVGA_FIFO_FLAGS,
+   // Valid with SVGA_FIFO_CAP_FENCE:
+   SVGA_FIFO_FENCE,
+
+   /*
+    * Block 3a (optional extended registers): Additional registers for the
+    * extended FIFO, whose presence isn't actually implied by
+    * SVGA_CAP_EXTENDED_FIFO; these exist if SVGA_FIFO_MIN is high enough to
+    * leave room for them.
+    *
+    * These in block 3a, the VMX currently considers mandatory for the
+    * extended FIFO.
+    */
+
+   // Valid if exists (i.e. if extended FIFO enabled):
+   SVGA_FIFO_3D_HWVERSION,       /* See SVGA3dHardwareVersion in svga3d_reg.h */
+   // Valid with SVGA_FIFO_CAP_PITCHLOCK:
+   SVGA_FIFO_PITCHLOCK,
+
+   // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3:
+   SVGA_FIFO_CURSOR_ON,          /* Cursor bypass 3 show/hide register */
+   SVGA_FIFO_CURSOR_X,           /* Cursor bypass 3 x register */
+   SVGA_FIFO_CURSOR_Y,           /* Cursor bypass 3 y register */
+   SVGA_FIFO_CURSOR_COUNT,       /* Incremented when any of the other 3 change */
+   SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
+
+   // Valid with SVGA_FIFO_CAP_RESERVE:
+   SVGA_FIFO_RESERVED,           /* Bytes past NEXT_CMD with real contents */
+
+   /*
+    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT:
+    *
+    * By default this is SVGA_ID_INVALID, to indicate that the cursor
+    * coordinates are specified relative to the virtual root. If this
+    * is set to a specific screen ID, cursor position is reinterpreted
+    * as a signed offset relative to that screen's origin. This is the
+    * only way to place the cursor on a non-rooted screen.
+    */
+   SVGA_FIFO_CURSOR_SCREEN_ID,
+
+   /*
+    * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
+    * registers, but this must be done carefully and with judicious use of
+    * capability bits, since comparisons based on SVGA_FIFO_MIN aren't
+    * enough to tell you whether the register exists: we've shipped drivers
+    * and products that used SVGA_FIFO_3D_CAPS but didn't know about some of
+    * the earlier ones.  The actual order of introduction was:
+    * - PITCHLOCK
+    * - 3D_CAPS
+    * - CURSOR_* (cursor bypass 3)
+    * - RESERVED
+    * So, code that wants to know whether it can use any of the
+    * aforementioned registers, or anything else added after PITCHLOCK and
+    * before 3D_CAPS, needs to reason about something other than
+    * SVGA_FIFO_MIN.
+    */
+
+   /*
+    * 3D caps block space; valid with 3D hardware version >=
+    * SVGA3D_HWVERSION_WS6_B1.
+    */
+   SVGA_FIFO_3D_CAPS      = 32,
+   SVGA_FIFO_3D_CAPS_LAST = 32 + 255,
+
+   /*
+    * End of VMX's current definition of "extended-FIFO registers".
+    * Registers before here are always enabled/disabled as a block; either
+    * the extended FIFO is enabled and includes all preceding registers, or
+    * it's disabled entirely.
+    *
+    * Block 3b (truly optional extended registers): Additional registers for
+    * the extended FIFO, which the VMX already knows how to enable and
+    * disable with correct granularity.
+    *
+    * Registers after here exist if and only if the guest SVGA driver
+    * sets SVGA_FIFO_MIN high enough to leave room for them.
+    */
+
+   // Valid if register exists:
+   SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
+   SVGA_FIFO_FENCE_GOAL,         /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
+   SVGA_FIFO_BUSY,               /* See "FIFO Synchronization Registers" */
+
+   /*
+    * Always keep this last.  This defines the maximum number of
+    * registers we know about.  At power-on, this value is placed in
+    * the SVGA_REG_MEM_REGS register, and we expect the guest driver
+    * to allocate this much space in FIFO memory for registers.
+    */
+    SVGA_FIFO_NUM_REGS
+};
+
+
+/*
+ * Definition of registers included in extended FIFO support.
+ *
+ * The guest SVGA driver gets to allocate the FIFO between registers
+ * and data.  It must always allocate at least 4 registers, but old
+ * drivers stopped there.
+ *
+ * The VMX will enable extended FIFO support if and only if the guest
+ * left enough room for all registers defined as part of the mandatory
+ * set for the extended FIFO.
+ *
+ * Note that the guest drivers typically allocate the FIFO only at
+ * initialization time, not at mode switches, so it's likely that the
+ * number of FIFO registers won't change without a reboot.
+ *
+ * All registers less than this value are guaranteed to be present if
+ * svgaUser->fifo.extended is set. Any later registers must be tested
+ * individually for compatibility at each use (in the VMX).
+ *
+ * This value is used only by the VMX, so it can change without
+ * affecting driver compatibility; keep it that way?
+ */
+#define SVGA_FIFO_EXTENDED_MANDATORY_REGS  (SVGA_FIFO_3D_CAPS_LAST + 1)
+
+
+/*
+ * FIFO Synchronization Registers
+ *
+ *  This explains the relationship between the various FIFO
+ *  sync-related registers in IOSpace and in FIFO space.
+ *
+ *  SVGA_REG_SYNC --
+ *
+ *       The SYNC register can be used in two different ways by the guest:
+ *
+ *         1. If the guest wishes to fully sync (drain) the FIFO,
+ *            it will write once to SYNC then poll on the BUSY
+ *            register. The FIFO is sync'ed once BUSY is zero.
+ *
+ *         2. If the guest wants to asynchronously wake up the host,
+ *            it will write once to SYNC without polling on BUSY.
+ *            Ideally it will do this after some new commands have
+ *            been placed in the FIFO, and after reading a zero
+ *            from SVGA_FIFO_BUSY.
+ *
+ *       (1) is the original behaviour that SYNC was designed to
+ *       support.  Originally, a write to SYNC would implicitly
+ *       trigger a read from BUSY. This causes us to synchronously
+ *       process the FIFO.
+ *
+ *       This behaviour has since been changed so that writing SYNC
+ *       will *not* implicitly cause a read from BUSY. Instead, it
+ *       makes a channel call which asynchronously wakes up the MKS
+ *       thread.
+ *
+ *       New guests can use this new behaviour to implement (2)
+ *       efficiently. This lets guests get the host's attention
+ *       without waiting for the MKS to poll, which gives us much
+ *       better CPU utilization on SMP hosts and on UP hosts while
+ *       we're blocked on the host GPU.
+ *
+ *       Old guests shouldn't notice the behaviour change. SYNC was
+ *       never guaranteed to process the entire FIFO, since it was
+ *       bounded to a particular number of CPU cycles. Old guests will
+ *       still loop on the BUSY register until the FIFO is empty.
+ *
+ *       Writing to SYNC currently has the following side-effects:
+ *
+ *         - Sets SVGA_REG_BUSY to TRUE (in the monitor)
+ *         - Asynchronously wakes up the MKS thread for FIFO processing
+ *         - The value written to SYNC is recorded as a "reason", for
+ *           stats purposes.
+ *
+ *       If SVGA_FIFO_BUSY is available, drivers are advised to only
+ *       write to SYNC if SVGA_FIFO_BUSY is FALSE. Drivers should set
+ *       SVGA_FIFO_BUSY to TRUE after writing to SYNC. The MKS will
+ *       eventually set SVGA_FIFO_BUSY on its own, but this approach
+ *       lets the driver avoid sending multiple asynchronous wakeup
+ *       messages to the MKS thread.
+ *
+ *  SVGA_REG_BUSY --
+ *
+ *       This register is set to TRUE when SVGA_REG_SYNC is written,
+ *       and it reads as FALSE when the FIFO has been completely
+ *       drained.
+ *
+ *       Every read from this register causes us to synchronously
+ *       process FIFO commands. There is no guarantee as to how many
+ *       commands each read will process.
+ *
+ *       CPU time spent processing FIFO commands will be billed to
+ *       the guest.
+ *
+ *       New drivers should avoid using this register unless they
+ *       need to guarantee that the FIFO is completely drained. It
+ *       is overkill for performing a sync-to-fence. Older drivers
+ *       will use this register for any type of synchronization.
+ *
+ *  SVGA_FIFO_BUSY --
+ *
+ *       This register is a fast way for the guest driver to check
+ *       whether the FIFO is already being processed. It reads and
+ *       writes at normal RAM speeds, with no monitor intervention.
+ *
+ *       If this register reads as TRUE, the host is guaranteeing that
+ *       any new commands written into the FIFO will be noticed before
+ *       the MKS goes back to sleep.
+ *
+ *       If this register reads as FALSE, no such guarantee can be
+ *       made.
+ *
+ *       The guest should use this register to quickly determine
+ *       whether or not it needs to wake up the host. If the guest
+ *       just wrote a command or group of commands that it would like
+ *       the host to begin processing, it should:
+ *
+ *         1. Read SVGA_FIFO_BUSY. If it reads as TRUE, no further
+ *            action is necessary.
+ *
+ *         2. Write TRUE to SVGA_FIFO_BUSY. This informs future guest
+ *            code that we've already sent a SYNC to the host and we
+ *            don't need to send a duplicate.
+ *
+ *         3. Write a reason to SVGA_REG_SYNC. This will send an
+ *            asynchronous wakeup to the MKS thread.
+ */
+
+
+/*
+ * FIFO Capabilities
+ *
+ *      Fence -- Fence register and command are supported
+ *      Accel Front -- Front buffer only commands are supported
+ *      Pitch Lock -- Pitch lock register is supported
+ *      Video -- SVGA Video overlay units are supported
+ *      Escape -- Escape command is supported
+ *
+ * XXX: Add longer descriptions for each capability, including a list
+ *      of the new features that each capability provides.
+ *
+ * SVGA_FIFO_CAP_SCREEN_OBJECT --
+ *
+ *    Provides dynamic multi-screen rendering, for improved Unity and
+ *    multi-monitor modes. With Screen Object, the guest can
+ *    dynamically create and destroy 'screens', which can represent
+ *    Unity windows or virtual monitors. Screen Object also provides
+ *    strong guarantees that DMA operations happen only when
+ *    guest-initiated. Screen Object deprecates the BAR1 guest
+ *    framebuffer (GFB) and all commands that work only with the GFB.
+ *
+ *    New registers:
+ *       FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID
+ *
+ *    New 2D commands:
+ *       DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN,
+ *       BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY
+ *
+ *    New 3D commands:
+ *       BLIT_SURFACE_TO_SCREEN
+ *
+ *    New guarantees:
+ *
+ *       - The host will not read or write guest memory, including the GFB,
+ *         except when explicitly initiated by a DMA command.
+ *
+ *       - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK,
+ *         is guaranteed to complete before any subsequent FENCEs.
+ *
+ *       - All legacy commands which affect a Screen (UPDATE, PRESENT,
+ *         PRESENT_READBACK) as well as new Screen blit commands will
+ *         all behave consistently as blits, and memory will be read
+ *         or written in FIFO order.
+ *
+ *         For example, if you PRESENT from one SVGA3D surface to multiple
+ *         places on the screen, the data copied will always be from the
+ *         SVGA3D surface at the time the PRESENT was issued in the FIFO.
+ *         This was not necessarily true on devices without Screen Object.
+ *
+ *         This means that on devices that support Screen Object, the
+ *         PRESENT_READBACK command should not be necessary unless you
+ *         actually want to read back the results of 3D rendering into
+ *         system memory. (And for that, the BLIT_SCREEN_TO_GMRFB
+ *         command provides a strict superset of functionality.)
+ *
+ *       - When a screen is resized, either using Screen Object commands or
+ *         legacy multimon registers, its contents are preserved.
+ */
+
+#define SVGA_FIFO_CAP_NONE                  0
+#define SVGA_FIFO_CAP_FENCE             (1<<0)
+#define SVGA_FIFO_CAP_ACCELFRONT        (1<<1)
+#define SVGA_FIFO_CAP_PITCHLOCK         (1<<2)
+#define SVGA_FIFO_CAP_VIDEO             (1<<3)
+#define SVGA_FIFO_CAP_CURSOR_BYPASS_3   (1<<4)
+#define SVGA_FIFO_CAP_ESCAPE            (1<<5)
+#define SVGA_FIFO_CAP_RESERVE           (1<<6)
+#define SVGA_FIFO_CAP_SCREEN_OBJECT     (1<<7)
+
+
+/*
+ * FIFO Flags
+ *
+ *      Accel Front -- Driver should use front buffer only commands
+ */
+
+#define SVGA_FIFO_FLAG_NONE                 0
+#define SVGA_FIFO_FLAG_ACCELFRONT       (1<<0)
+#define SVGA_FIFO_FLAG_RESERVED        (1<<31) // Internal use only
+
+/*
+ * FIFO reservation sentinel value
+ */
+
+#define SVGA_FIFO_RESERVED_UNKNOWN      0xffffffff
+
+
+/*
+ * Video overlay support
+ */
+
+#define SVGA_NUM_OVERLAY_UNITS 32
+
+
+/*
+ * Video capabilities that the guest is currently using
+ */
+
+#define SVGA_VIDEO_FLAG_COLORKEY        0x0001
+
+
+/*
+ * Offsets for the video overlay registers
+ */
+
+enum {
+   SVGA_VIDEO_ENABLED = 0,
+   SVGA_VIDEO_FLAGS,
+   SVGA_VIDEO_DATA_OFFSET,
+   SVGA_VIDEO_FORMAT,
+   SVGA_VIDEO_COLORKEY,
+   SVGA_VIDEO_SIZE,          // Deprecated
+   SVGA_VIDEO_WIDTH,
+   SVGA_VIDEO_HEIGHT,
+   SVGA_VIDEO_SRC_X,
+   SVGA_VIDEO_SRC_Y,
+   SVGA_VIDEO_SRC_WIDTH,
+   SVGA_VIDEO_SRC_HEIGHT,
+   SVGA_VIDEO_DST_X,         // Signed int32
+   SVGA_VIDEO_DST_Y,         // Signed int32
+   SVGA_VIDEO_DST_WIDTH,
+   SVGA_VIDEO_DST_HEIGHT,
+   SVGA_VIDEO_PITCH_1,
+   SVGA_VIDEO_PITCH_2,
+   SVGA_VIDEO_PITCH_3,
+   SVGA_VIDEO_DATA_GMRID,    // Optional, defaults to SVGA_GMR_FRAMEBUFFER
+   SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID)
+   SVGA_VIDEO_NUM_REGS
+};
+
+
+/*
+ * SVGA Overlay Units
+ *
+ *      width and height relate to the entire source video frame.
+ *      srcX, srcY, srcWidth and srcHeight represent subset of the source
+ *      video frame to be displayed.
+ */
+
+typedef struct SVGAOverlayUnit {
+   uint32 enabled;
+   uint32 flags;
+   uint32 dataOffset;
+   uint32 format;
+   uint32 colorKey;
+   uint32 size;
+   uint32 width;
+   uint32 height;
+   uint32 srcX;
+   uint32 srcY;
+   uint32 srcWidth;
+   uint32 srcHeight;
+   int32  dstX;
+   int32  dstY;
+   uint32 dstWidth;
+   uint32 dstHeight;
+   uint32 pitches[3];
+   uint32 dataGMRId;
+   uint32 dstScreenId;
+} SVGAOverlayUnit;
+
+
+/*
+ * SVGAScreenObject --
+ *
+ *    This is a new way to represent a guest's multi-monitor screen or
+ *    Unity window. Screen objects are only supported if the
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set.
+ *
+ *    If Screen Objects are supported, they can be used to fully
+ *    replace the functionality provided by the framebuffer registers
+ *    (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY.
+ *
+ *    The screen object is a struct with guaranteed binary
+ *    compatibility. New flags can be added, and the struct may grow,
+ *    but existing fields must retain their meaning.
+ *
+ */
+
+#define SVGA_SCREEN_HAS_ROOT    (1 << 0)  // Screen is present in the virtual coord space
+#define SVGA_SCREEN_IS_PRIMARY  (1 << 1)  // Guest considers this screen to be 'primary'
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)   // Guest is running a fullscreen app here
+
+typedef
+struct SVGAScreenObject {
+   uint32 structSize;   // sizeof(SVGAScreenObject)
+   uint32 id;
+   uint32 flags;
+   struct {
+      uint32 width;
+      uint32 height;
+   } size;
+   struct {
+      int32 x;
+      int32 y;
+   } root;              // Only used if SVGA_SCREEN_HAS_ROOT is set.
+} SVGAScreenObject;
+
+
+/*
+ *  Commands in the command FIFO:
+ *
+ *  Command IDs defined below are used for the traditional 2D FIFO
+ *  communication (not all commands are available for all versions of the
+ *  SVGA FIFO protocol).
+ *
+ *  Note the holes in the command ID numbers: These commands have been
+ *  deprecated, and the old IDs must not be reused.
+ *
+ *  Command IDs from 1000 to 1999 are reserved for use by the SVGA3D
+ *  protocol.
+ *
+ *  Each command's parameters are described by the comments and
+ *  structs below.
+ */
+
+typedef enum {
+   SVGA_CMD_INVALID_CMD           = 0,
+   SVGA_CMD_UPDATE                = 1,
+   SVGA_CMD_RECT_COPY             = 3,
+   SVGA_CMD_DEFINE_CURSOR         = 19,
+   SVGA_CMD_DEFINE_ALPHA_CURSOR   = 22,
+   SVGA_CMD_UPDATE_VERBOSE        = 25,
+   SVGA_CMD_FRONT_ROP_FILL        = 29,
+   SVGA_CMD_FENCE                 = 30,
+   SVGA_CMD_ESCAPE                = 33,
+   SVGA_CMD_DEFINE_SCREEN         = 34,
+   SVGA_CMD_DESTROY_SCREEN        = 35,
+   SVGA_CMD_DEFINE_GMRFB          = 36,
+   SVGA_CMD_BLIT_GMRFB_TO_SCREEN  = 37,
+   SVGA_CMD_BLIT_SCREEN_TO_GMRFB  = 38,
+   SVGA_CMD_ANNOTATION_FILL       = 39,
+   SVGA_CMD_ANNOTATION_COPY       = 40,
+   SVGA_CMD_MAX
+} SVGAFifoCmdId;
+
+#define SVGA_CMD_MAX_ARGS           64
+
+
+/*
+ * SVGA_CMD_UPDATE --
+ *
+ *    This is a DMA transfer which copies from the Guest Framebuffer
+ *    (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which
+ *    intersect with the provided virtual rectangle.
+ *
+ *    This command does not support using arbitrary guest memory as a
+ *    data source- it only works with the pre-defined GFB memory.
+ *    This command also does not support signed virtual coordinates.
+ *    If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with
+ *    negative root x/y coordinates, the negative portion of those
+ *    screens will not be reachable by this command.
+ *
+ *    This command is not necessary when using framebuffer
+ *    traces. Traces are automatically enabled if the SVGA FIFO is
+ *    disabled, and you may explicitly enable/disable traces using
+ *    SVGA_REG_TRACES. With traces enabled, any write to the GFB will
+ *    automatically act as if a subsequent SVGA_CMD_UPDATE was issued.
+ *
+ *    Traces and SVGA_CMD_UPDATE are the only supported ways to render
+ *    pseudocolor screen updates. The newer Screen Object commands
+ *    only support true color formats.
+ *
+ * Availability:
+ *    Always available.
+ */
+
+typedef
+struct {
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+} SVGAFifoCmdUpdate;
+
+
+/*
+ * SVGA_CMD_RECT_COPY --
+ *
+ *    Perform a rectangular DMA transfer from one area of the GFB to
+ *    another, and copy the result to any screens which intersect it.
+ *
+ * Availability:
+ *    SVGA_CAP_RECT_COPY
+ */
+
+typedef
+struct {
+   uint32 srcX;
+   uint32 srcY;
+   uint32 destX;
+   uint32 destY;
+   uint32 width;
+   uint32 height;
+} SVGAFifoCmdRectCopy;
+
+
+/*
+ * SVGA_CMD_DEFINE_CURSOR --
+ *
+ *    Provide a new cursor image, as an AND/XOR mask.
+ *
+ *    The recommended way to position the cursor overlay is by using
+ *    the SVGA_FIFO_CURSOR_* registers, supported by the
+ *    SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
+ *
+ * Availability:
+ *    SVGA_CAP_CURSOR
+ */
+
+typedef
+struct {
+   uint32 id;             // Reserved, must be zero.
+   uint32 hotspotX;
+   uint32 hotspotY;
+   uint32 width;
+   uint32 height;
+   uint32 andMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   uint32 xorMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   /*
+    * Followed by scanline data for AND mask, then XOR mask.
+    * Each scanline is padded to a 32-bit boundary.
+   */
+} SVGAFifoCmdDefineCursor;
+
+
+/*
+ * SVGA_CMD_DEFINE_ALPHA_CURSOR --
+ *
+ *    Provide a new cursor image, in 32-bit BGRA format.
+ *
+ *    The recommended way to position the cursor overlay is by using
+ *    the SVGA_FIFO_CURSOR_* registers, supported by the
+ *    SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
+ *
+ * Availability:
+ *    SVGA_CAP_ALPHA_CURSOR
+ */
+
+typedef
+struct {
+   uint32 id;             // Reserved, must be zero.
+   uint32 hotspotX;
+   uint32 hotspotY;
+   uint32 width;
+   uint32 height;
+   /* Followed by scanline data */
+} SVGAFifoCmdDefineAlphaCursor;
+
+
+/*
+ * SVGA_CMD_UPDATE_VERBOSE --
+ *
+ *    Just like SVGA_CMD_UPDATE, but also provide a per-rectangle
+ *    'reason' value, an opaque cookie which is used by internal
+ *    debugging tools. Third party drivers should not use this
+ *    command.
+ *
+ * Availability:
+ *    SVGA_CAP_EXTENDED_FIFO
+ */
+
+typedef
+struct {
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+   uint32 reason;
+} SVGAFifoCmdUpdateVerbose;
+
+
+/*
+ * SVGA_CMD_FRONT_ROP_FILL --
+ *
+ *    This is a hint which tells the SVGA device that the driver has
+ *    just filled a rectangular region of the GFB with a solid
+ *    color. Instead of reading these pixels from the GFB, the device
+ *    can assume that they all equal 'color'. This is primarily used
+ *    for remote desktop protocols.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_ACCELFRONT
+ */
+
+#define  SVGA_ROP_COPY                    0x03
+
+typedef
+struct {
+   uint32 color;     // In the same format as the GFB
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+   uint32 rop;       // Must be SVGA_ROP_COPY
+} SVGAFifoCmdFrontRopFill;
+
+
+/*
+ * SVGA_CMD_FENCE --
+ *
+ *    Insert a synchronization fence.  When the SVGA device reaches
+ *    this command, it will copy the 'fence' value into the
+ *    SVGA_FIFO_FENCE register. It will also compare the fence against
+ *    SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the
+ *    SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will
+ *    raise this interrupt.
+ *
+ * Availability:
+ *    SVGA_FIFO_FENCE for this command,
+ *    SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL.
+ */
+
+typedef
+struct {
+   uint32 fence;
+} SVGAFifoCmdFence;
+
+
+/*
+ * SVGA_CMD_ESCAPE --
+ *
+ *    Send an extended or vendor-specific variable length command.
+ *    This is used for video overlay, third party plugins, and
+ *    internal debugging tools. See svga_escape.h
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_ESCAPE
+ */
+
+typedef
+struct {
+   uint32 nsid;
+   uint32 size;
+   /* followed by 'size' bytes of data */
+} SVGAFifoCmdEscape;
+
+
+/*
+ * SVGA_CMD_DEFINE_SCREEN --
+ *
+ *    Define or redefine an SVGAScreenObject. See the description of
+ *    SVGAScreenObject above.  The video driver is responsible for
+ *    generating new screen IDs. They should be small positive
+ *    integers. The virtual device will have an implementation
+ *    specific upper limit on the number of screen IDs
+ *    supported. Drivers are responsible for recycling IDs. The first
+ *    valid ID is zero.
+ *
+ *    - Interaction with other registers:
+ *
+ *    For backwards compatibility, when the GFB mode registers (WIDTH,
+ *    HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
+ *    deletes all screens other than screen #0, and redefines screen
+ *    #0 according to the specified mode. Drivers that use
+ *    SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0.
+ *
+ *    If you use screen objects, do not use the legacy multi-mon
+ *    registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAScreenObject screen;   // Variable-length according to version
+} SVGAFifoCmdDefineScreen;
+
+
+/*
+ * SVGA_CMD_DESTROY_SCREEN --
+ *
+ *    Destroy an SVGAScreenObject. Its ID is immediately available for
+ *    re-use.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   uint32 screenId;
+} SVGAFifoCmdDestroyScreen;
+
+
+/*
+ * SVGA_CMD_DEFINE_GMRFB --
+ *
+ *    This command sets a piece of SVGA device state called the
+ *    Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a
+ *    piece of light-weight state which identifies the location and
+ *    format of an image in guest memory or in BAR1. The GMRFB has
+ *    an arbitrary size, and it doesn't need to match the geometry
+ *    of the GFB or any screen object.
+ *
+ *    The GMRFB can be redefined as often as you like. You could
+ *    always use the same GMRFB, you could redefine it before
+ *    rendering from a different guest screen, or you could even
+ *    redefine it before every blit.
+ *
+ *    There are multiple ways to use this command. The simplest way is
+ *    to use it to move the framebuffer either to elsewhere in the GFB
+ *    (BAR1) memory region, or to a user-defined GMR. This lets a
+ *    driver use a framebuffer allocated entirely out of normal system
+ *    memory, which we encourage.
+ *
+ *    Another way to use this command is to set up a ring buffer of
+ *    updates in GFB memory. If a driver wants to ensure that no
+ *    frames are skipped by the SVGA device, it is important that the
+ *    driver not modify the source data for a blit until the device is
+ *    done processing the command. One efficient way to accomplish
+ *    this is to use a ring of small DMA buffers. Each buffer is used
+ *    for one blit, then we move on to the next buffer in the
+ *    ring. The FENCE mechanism is used to protect each buffer from
+ *    re-use until the device is finished with that buffer's
+ *    corresponding blit.
+ *
+ *    This command does not affect the meaning of SVGA_CMD_UPDATE.
+ *    UPDATEs always occur from the legacy GFB memory area. This
+ *    command has no support for pseudocolor GMRFBs. Currently only
+ *    true-color 15, 16, and 24-bit depths are supported. Future
+ *    devices may expose capabilities for additional framebuffer
+ *    formats.
+ *
+ *    The default GMRFB value is undefined. Drivers must always send
+ *    this command at least once before performing any blit from the
+ *    GMRFB.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAGuestPtr        ptr;
+   uint32              bytesPerLine;
+   SVGAGMRImageFormat  format;
+} SVGAFifoCmdDefineGMRFB;
+
+
+/*
+ * SVGA_CMD_BLIT_GMRFB_TO_SCREEN --
+ *
+ *    This is a guest-to-host blit. It performs a DMA operation to
+ *    copy a rectangular region of pixels from the current GMRFB to
+ *    one or more Screen Objects.
+ *
+ *    The destination coordinate may be specified relative to a
+ *    screen's origin (if a screen ID is specified) or relative to the
+ *    virtual coordinate system's origin (if the screen ID is
+ *    SVGA_ID_INVALID). The actual destination may span zero or more
+ *    screens, in the case of a virtual destination rect or a rect
+ *    which extends off the edge of the specified screen.
+ *
+ *    This command writes to the screen's "base layer": the underlying
+ *    framebuffer which exists below any cursor or video overlays. No
+ *    action is necessary to explicitly hide or update any overlays
+ *    which exist on top of the updated region.
+ *
+ *    The SVGA device is guaranteed to finish reading from the GMRFB
+ *    by the time any subsequent FENCE commands are reached.
+ *
+ *    This command consumes an annotation. See the
+ *    SVGA_CMD_ANNOTATION_* commands for details.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  srcOrigin;
+   SVGASignedRect   destRect;
+   uint32           destScreenId;
+} SVGAFifoCmdBlitGMRFBToScreen;
+
+
+/*
+ * SVGA_CMD_BLIT_SCREEN_TO_GMRFB --
+ *
+ *    This is a host-to-guest blit. It performs a DMA operation to
+ *    copy a rectangular region of pixels from a single Screen Object
+ *    back to the current GMRFB.
+ *
+ *    Usage note: This command should be used rarely. It will
+ *    typically be inefficient, but it is necessary for some types of
+ *    synchronization between 3D (GPU) and 2D (CPU) rendering into
+ *    overlapping areas of a screen.
+ *
+ *    The source coordinate is specified relative to a screen's
+ *    origin. The provided screen ID must be valid. If any parameters
+ *    are invalid, the resulting pixel values are undefined.
+ *
+ *    This command reads the screen's "base layer". Overlays like
+ *    video and cursor are not included, but any data which was sent
+ *    using a blit-to-screen primitive will be available, no matter
+ *    whether the data's original source was the GMRFB or the 3D
+ *    acceleration hardware.
+ *
+ *    Note that our guest-to-host blits and host-to-guest blits aren't
+ *    symmetric in their current implementation. While the parameters
+ *    are identical, host-to-guest blits are a lot less featureful.
+ *    They do not support clipping: If the source parameters don't
+ *    fully fit within a screen, the blit fails. They must originate
+ *    from exactly one screen. Virtual coordinates are not directly
+ *    supported.
+ *
+ *    Host-to-guest blits do support the same set of GMRFB formats
+ *    offered by guest-to-host blits.
+ *
+ *    The SVGA device is guaranteed to finish writing to the GMRFB by
+ *    the time any subsequent FENCE commands are reached.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  destOrigin;
+   SVGASignedRect   srcRect;
+   uint32           srcScreenId;
+} SVGAFifoCmdBlitScreenToGMRFB;
+
+
+/*
+ * SVGA_CMD_ANNOTATION_FILL --
+ *
+ *    This is a blit annotation. This command stores a small piece of
+ *    device state which is consumed by the next blit-to-screen
+ *    command. The state is only cleared by commands which are
+ *    specifically documented as consuming an annotation. Other
+ *    commands (such as ESCAPEs for debugging) may intervene between
+ *    the annotation and its associated blit.
+ *
+ *    This annotation is a promise about the contents of the next
+ *    blit: The video driver is guaranteeing that all pixels in that
+ *    blit will have the same value, specified here as a color in
+ *    SVGAColorBGRX format.
+ *
+ *    The SVGA device can still render the blit correctly even if it
+ *    ignores this annotation, but the annotation may allow it to
+ *    perform the blit more efficiently, for example by ignoring the
+ *    source data and performing a fill in hardware.
+ *
+ *    This annotation is most important for performance when the
+ *    user's display is being remoted over a network connection.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAColorBGRX  color;
+} SVGAFifoCmdAnnotationFill;
+
+
+/*
+ * SVGA_CMD_ANNOTATION_COPY --
+ *
+ *    This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more
+ *    information about annotations.
+ *
+ *    This annotation is a promise about the contents of the next
+ *    blit: The video driver is guaranteeing that all pixels in that
+ *    blit will have the same value as those which already exist at an
+ *    identically-sized region on the same or a different screen.
+ *
+ *    Note that the source pixels for the COPY in this annotation are
+ *    sampled before applying the anqnotation's associated blit. They
+ *    are allowed to overlap with the blit's destination pixels.
+ *
+ *    The copy source rectangle is specified the same way as the blit
+ *    destination: it can be a rectangle which spans zero or more
+ *    screens, specified relative to either a screen or to the virtual
+ *    coordinate system's origin. If the source rectangle includes
+ *    pixels which are not from exactly one screen, the results are
+ *    undefined.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  srcOrigin;
+   uint32           srcScreenId;
+} SVGAFifoCmdAnnotationCopy;
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -0,0 +1,1187 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "vmwgfx_drm.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_placement.h"
+#include "drmP.h"
+
+#define VMW_RES_CONTEXT ttm_driver_type0
+#define VMW_RES_SURFACE ttm_driver_type1
+#define VMW_RES_STREAM ttm_driver_type2
+
+struct vmw_user_context {
+	struct ttm_base_object base;
+	struct vmw_resource res;
+};
+
+struct vmw_user_surface {
+	struct ttm_base_object base;
+	struct vmw_surface srf;
+};
+
+struct vmw_user_dma_buffer {
+	struct ttm_base_object base;
+	struct vmw_dma_buffer dma;
+};
+
+struct vmw_bo_user_rep {
+	uint32_t handle;
+	uint64_t map_handle;
+};
+
+struct vmw_stream {
+	struct vmw_resource res;
+	uint32_t stream_id;
+};
+
+struct vmw_user_stream {
+	struct ttm_base_object base;
+	struct vmw_stream stream;
+};
+
+static inline struct vmw_dma_buffer *
+vmw_dma_buffer(struct ttm_buffer_object *bo)
+{
+	return container_of(bo, struct vmw_dma_buffer, base);
+}
+
+static inline struct vmw_user_dma_buffer *
+vmw_user_dma_buffer(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	return container_of(vmw_bo, struct vmw_user_dma_buffer, dma);
+}
+
+struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
+{
+	kref_get(&res->kref);
+	return res;
+}
+
+static void vmw_resource_release(struct kref *kref)
+{
+	struct vmw_resource *res =
+	    container_of(kref, struct vmw_resource, kref);
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	idr_remove(res->idr, res->id);
+	write_unlock(&dev_priv->resource_lock);
+
+	if (likely(res->hw_destroy != NULL))
+		res->hw_destroy(res);
+
+	if (res->res_free != NULL)
+		res->res_free(res);
+	else
+		kfree(res);
+
+	write_lock(&dev_priv->resource_lock);
+}
+
+void vmw_resource_unreference(struct vmw_resource **p_res)
+{
+	struct vmw_resource *res = *p_res;
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	*p_res = NULL;
+	write_lock(&dev_priv->resource_lock);
+	kref_put(&res->kref, vmw_resource_release);
+	write_unlock(&dev_priv->resource_lock);
+}
+
+static int vmw_resource_init(struct vmw_private *dev_priv,
+			     struct vmw_resource *res,
+			     struct idr *idr,
+			     enum ttm_object_type obj_type,
+			     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+
+	kref_init(&res->kref);
+	res->hw_destroy = NULL;
+	res->res_free = res_free;
+	res->res_type = obj_type;
+	res->idr = idr;
+	res->avail = false;
+	res->dev_priv = dev_priv;
+
+	do {
+		if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+			return -ENOMEM;
+
+		write_lock(&dev_priv->resource_lock);
+		ret = idr_get_new_above(idr, res, 1, &res->id);
+		write_unlock(&dev_priv->resource_lock);
+
+	} while (ret == -EAGAIN);
+
+	return ret;
+}
+
+/**
+ * vmw_resource_activate
+ *
+ * @res:        Pointer to the newly created resource
+ * @hw_destroy: Destroy function. NULL if none.
+ *
+ * Activate a resource after the hardware has been made aware of it.
+ * Set tye destroy function to @destroy. Typically this frees the
+ * resource and destroys the hardware resources associated with it.
+ * Activate basically means that the function vmw_resource_lookup will
+ * find it.
+ */
+
+static void vmw_resource_activate(struct vmw_resource *res,
+				  void (*hw_destroy) (struct vmw_resource *))
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	write_lock(&dev_priv->resource_lock);
+	res->avail = true;
+	res->hw_destroy = hw_destroy;
+	write_unlock(&dev_priv->resource_lock);
+}
+
+struct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv,
+					 struct idr *idr, int id)
+{
+	struct vmw_resource *res;
+
+	read_lock(&dev_priv->resource_lock);
+	res = idr_find(idr, id);
+	if (res && res->avail)
+		kref_get(&res->kref);
+	else
+		res = NULL;
+	read_unlock(&dev_priv->resource_lock);
+
+	if (unlikely(res == NULL))
+		return NULL;
+
+	return res;
+}
+
+/**
+ * Context management:
+ */
+
+static void vmw_hw_context_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDestroyContext body;
+	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "destruction.\n");
+		return;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+}
+
+static int vmw_context_init(struct vmw_private *dev_priv,
+			    struct vmw_resource *res,
+			    void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDefineContext body;
+	} *cmd;
+
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
+				VMW_RES_CONTEXT, res_free);
+
+	if (unlikely(ret != 0)) {
+		if (res_free == NULL)
+			kfree(res);
+		else
+			res_free(res);
+		return ret;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_resource_activate(res, vmw_hw_context_destroy);
+	return 0;
+}
+
+struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
+{
+	struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+	int ret;
+
+	if (unlikely(res == NULL))
+		return NULL;
+
+	ret = vmw_context_init(dev_priv, res, NULL);
+	return (ret == 0) ? res : NULL;
+}
+
+/**
+ * User-space context management:
+ */
+
+static void vmw_user_context_free(struct vmw_resource *res)
+{
+	struct vmw_user_context *ctx =
+	    container_of(res, struct vmw_user_context, res);
+
+	kfree(ctx);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_context_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_context *ctx =
+	    container_of(base, struct vmw_user_context, base);
+	struct vmw_resource *res = &ctx->res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_resource *res;
+	struct vmw_user_context *ctx;
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret = 0;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_context_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ctx = container_of(res, struct vmw_user_context, res);
+	if (ctx->base.tfile != tfile && !ctx->base.shareable) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE);
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+
+	if (unlikely(ctx == NULL))
+		return -ENOMEM;
+
+	res = &ctx->res;
+	ctx->base.shareable = false;
+	ctx->base.tfile = NULL;
+
+	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(&ctx->res);
+	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
+				   &vmw_user_context_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		goto out_err;
+	}
+
+	arg->cid = res->id;
+out_err:
+	vmw_resource_unreference(&res);
+	return ret;
+
+}
+
+int vmw_context_check(struct vmw_private *dev_priv,
+		      struct ttm_object_file *tfile,
+		      int id)
+{
+	struct vmw_resource *res;
+	int ret = 0;
+
+	read_lock(&dev_priv->resource_lock);
+	res = idr_find(&dev_priv->context_idr, id);
+	if (res && res->avail) {
+		struct vmw_user_context *ctx =
+			container_of(res, struct vmw_user_context, res);
+		if (ctx->base.tfile != tfile && !ctx->base.shareable)
+			ret = -EPERM;
+	} else
+		ret = -EINVAL;
+	read_unlock(&dev_priv->resource_lock);
+
+	return ret;
+}
+
+
+/**
+ * Surface management.
+ */
+
+static void vmw_hw_surface_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDestroySurface body;
+	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "destruction.\n");
+		return;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.sid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+}
+
+void vmw_surface_res_free(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+
+	kfree(srf->sizes);
+	kfree(srf->snooper.image);
+	kfree(srf);
+}
+
+int vmw_surface_init(struct vmw_private *dev_priv,
+		     struct vmw_surface *srf,
+		     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDefineSurface body;
+	} *cmd;
+	SVGA3dSize *cmd_size;
+	struct vmw_resource *res = &srf->res;
+	struct drm_vmw_size *src_size;
+	size_t submit_size;
+	uint32_t cmd_len;
+	int i;
+
+	BUG_ON(res_free == NULL);
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
+				VMW_RES_SURFACE, res_free);
+
+	if (unlikely(ret != 0)) {
+		res_free(res);
+		return ret;
+	}
+
+	submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
+	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed for create surface.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
+	cmd->header.size = cpu_to_le32(cmd_len);
+	cmd->body.sid = cpu_to_le32(res->id);
+	cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
+	cmd->body.format = cpu_to_le32(srf->format);
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		cmd->body.face[i].numMipLevels =
+		    cpu_to_le32(srf->mip_levels[i]);
+	}
+
+	cmd += 1;
+	cmd_size = (SVGA3dSize *) cmd;
+	src_size = srf->sizes;
+
+	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+		cmd_size->width = cpu_to_le32(src_size->width);
+		cmd_size->height = cpu_to_le32(src_size->height);
+		cmd_size->depth = cpu_to_le32(src_size->depth);
+	}
+
+	vmw_fifo_commit(dev_priv, submit_size);
+	vmw_resource_activate(res, vmw_hw_surface_destroy);
+	return 0;
+}
+
+static void vmw_user_surface_free(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+	struct vmw_user_surface *user_srf =
+	    container_of(srf, struct vmw_user_surface, srf);
+
+	kfree(srf->sizes);
+	kfree(srf->snooper.image);
+	kfree(user_srf);
+}
+
+int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
+				   struct ttm_object_file *tfile,
+				   uint32_t handle, struct vmw_surface **out)
+{
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+	struct ttm_base_object *base;
+	int ret = -EINVAL;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL))
+		return -EINVAL;
+
+	if (unlikely(base->object_type != VMW_RES_SURFACE))
+		goto out_bad_resource;
+
+	user_srf = container_of(base, struct vmw_user_surface, base);
+	srf = &user_srf->srf;
+	res = &srf->res;
+
+	read_lock(&dev_priv->resource_lock);
+
+	if (!res->avail || res->res_free != &vmw_user_surface_free) {
+		read_unlock(&dev_priv->resource_lock);
+		goto out_bad_resource;
+	}
+
+	kref_get(&res->kref);
+	read_unlock(&dev_priv->resource_lock);
+
+	*out = srf;
+	ret = 0;
+
+out_bad_resource:
+	ttm_base_object_unref(&base);
+
+	return ret;
+}
+
+static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_surface *user_srf =
+	    container_of(base, struct vmw_user_surface, base);
+	struct vmw_resource *res = &user_srf->srf.res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+
+	return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
+}
+
+int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_surface *user_srf =
+	    kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	struct vmw_surface *srf;
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	union drm_vmw_surface_create_arg *arg =
+	    (union drm_vmw_surface_create_arg *)data;
+	struct drm_vmw_surface_create_req *req = &arg->req;
+	struct drm_vmw_surface_arg *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct drm_vmw_size __user *user_sizes;
+	int ret;
+	int i;
+
+	if (unlikely(user_srf == NULL))
+		return -ENOMEM;
+
+	srf = &user_srf->srf;
+	res = &srf->res;
+
+	srf->flags = req->flags;
+	srf->format = req->format;
+	srf->scanout = req->scanout;
+	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+	srf->num_sizes = 0;
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		srf->num_sizes += srf->mip_levels[i];
+
+	if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+	    DRM_VMW_MAX_MIP_LEVELS) {
+		ret = -EINVAL;
+		goto out_err0;
+	}
+
+	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_err0;
+	}
+
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    req->size_addr;
+
+	ret = copy_from_user(srf->sizes, user_sizes,
+			     srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	if (srf->scanout &&
+	    srf->num_sizes == 1 &&
+	    srf->sizes[0].width == 64 &&
+	    srf->sizes[0].height == 64 &&
+	    srf->format == SVGA3D_A8R8G8B8) {
+
+		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
+		/* clear the image */
+		if (srf->snooper.image) {
+			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
+		} else {
+			DRM_ERROR("Failed to allocate cursor_image\n");
+			ret = -ENOMEM;
+			goto out_err1;
+		}
+	} else {
+		srf->snooper.image = NULL;
+	}
+	srf->snooper.crtc = NULL;
+
+	user_srf->base.shareable = false;
+	user_srf->base.tfile = NULL;
+
+	/**
+	 * From this point, the generic resource management functions
+	 * destroy the object on failure.
+	 */
+
+	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(&srf->res);
+	ret = ttm_base_object_init(tfile, &user_srf->base,
+				   req->shareable, VMW_RES_SURFACE,
+				   &vmw_user_surface_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		vmw_resource_unreference(&res);
+		return ret;
+	}
+
+	rep->sid = user_srf->base.hash.key;
+	if (rep->sid == SVGA3D_INVALID_ID)
+		DRM_ERROR("Created bad Surface ID.\n");
+
+	vmw_resource_unreference(&res);
+	return 0;
+out_err1:
+	kfree(srf->sizes);
+out_err0:
+	kfree(user_srf);
+	return ret;
+}
+
+int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	union drm_vmw_surface_reference_arg *arg =
+	    (union drm_vmw_surface_reference_arg *)data;
+	struct drm_vmw_surface_arg *req = &arg->req;
+	struct drm_vmw_surface_create_req *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+	struct drm_vmw_size __user *user_sizes;
+	struct ttm_base_object *base;
+	int ret = -EINVAL;
+
+	base = ttm_base_object_lookup(tfile, req->sid);
+	if (unlikely(base == NULL)) {
+		DRM_ERROR("Could not find surface to reference.\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(base->object_type != VMW_RES_SURFACE))
+		goto out_bad_resource;
+
+	user_srf = container_of(base, struct vmw_user_surface, base);
+	srf = &user_srf->srf;
+
+	ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not add a reference to a surface.\n");
+		goto out_no_reference;
+	}
+
+	rep->flags = srf->flags;
+	rep->format = srf->format;
+	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    rep->size_addr;
+
+	if (user_sizes)
+		ret = copy_to_user(user_sizes, srf->sizes,
+				   srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0))
+		DRM_ERROR("copy_to_user failed %p %u\n",
+			  user_sizes, srf->num_sizes);
+out_bad_resource:
+out_no_reference:
+	ttm_base_object_unref(&base);
+
+	return ret;
+}
+
+int vmw_surface_check(struct vmw_private *dev_priv,
+		      struct ttm_object_file *tfile,
+		      uint32_t handle, int *id)
+{
+	struct ttm_base_object *base;
+	struct vmw_user_surface *user_srf;
+
+	int ret = -EPERM;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL))
+		return -EINVAL;
+
+	if (unlikely(base->object_type != VMW_RES_SURFACE))
+		goto out_bad_surface;
+
+	user_srf = container_of(base, struct vmw_user_surface, base);
+	*id = user_srf->srf.res.id;
+	ret = 0;
+
+out_bad_surface:
+	/**
+	 * FIXME: May deadlock here when called from the
+	 * command parsing code.
+	 */
+
+	ttm_base_object_unref(&base);
+	return ret;
+}
+
+/**
+ * Buffer management.
+ */
+
+static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob,
+				  unsigned long num_pages)
+{
+	static size_t bo_user_size = ~0;
+
+	size_t page_array_size =
+	    (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
+
+	if (unlikely(bo_user_size == ~0)) {
+		bo_user_size = glob->ttm_bo_extra_size +
+		    ttm_round_pot(sizeof(struct vmw_dma_buffer));
+	}
+
+	return bo_user_size + page_array_size;
+}
+
+void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	struct ttm_bo_global *glob = bo->glob;
+	struct vmw_private *dev_priv =
+		container_of(bo->bdev, struct vmw_private, bdev);
+
+	if (vmw_bo->gmr_bound) {
+		vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
+		spin_unlock(&glob->lru_lock);
+		vmw_bo->gmr_bound = false;
+	}
+}
+
+void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	struct ttm_bo_global *glob = bo->glob;
+
+	vmw_dmabuf_gmr_unbind(bo);
+	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
+	kfree(vmw_bo);
+}
+
+int vmw_dmabuf_init(struct vmw_private *dev_priv,
+		    struct vmw_dma_buffer *vmw_bo,
+		    size_t size, struct ttm_placement *placement,
+		    bool interruptible,
+		    void (*bo_free) (struct ttm_buffer_object *bo))
+{
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	size_t acc_size;
+	int ret;
+
+	BUG_ON(!bo_free);
+
+	acc_size =
+	    vmw_dmabuf_acc_size(bdev->glob,
+				(size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+	if (unlikely(ret != 0)) {
+		/* we must free the bo here as
+		 * ttm_buffer_object_init does so as well */
+		bo_free(&vmw_bo->base);
+		return ret;
+	}
+
+	memset(vmw_bo, 0, sizeof(*vmw_bo));
+
+	INIT_LIST_HEAD(&vmw_bo->gmr_lru);
+	INIT_LIST_HEAD(&vmw_bo->validate_list);
+	vmw_bo->gmr_id = 0;
+	vmw_bo->gmr_bound = false;
+
+	ret = ttm_bo_init(bdev, &vmw_bo->base, size,
+			  ttm_bo_type_device, placement,
+			  0, 0, interruptible,
+			  NULL, acc_size, bo_free);
+	return ret;
+}
+
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
+	struct ttm_bo_global *glob = bo->glob;
+
+	vmw_dmabuf_gmr_unbind(bo);
+	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
+	kfree(vmw_user_bo);
+}
+
+static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_base_object *base = *p_base;
+	struct ttm_buffer_object *bo;
+
+	*p_base = NULL;
+
+	if (unlikely(base == NULL))
+		return;
+
+	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
+	bo = &vmw_user_bo->dma.base;
+	ttm_bo_unref(&bo);
+}
+
+int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	union drm_vmw_alloc_dmabuf_arg *arg =
+	    (union drm_vmw_alloc_dmabuf_arg *)data;
+	struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
+	struct drm_vmw_dmabuf_rep *rep = &arg->rep;
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_buffer_object *tmp;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
+	if (unlikely(vmw_user_bo == NULL))
+		return -ENOMEM;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0)) {
+		kfree(vmw_user_bo);
+		return ret;
+	}
+
+	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
+			      &vmw_vram_sys_placement, true,
+			      &vmw_user_dmabuf_destroy);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
+	ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
+				   &vmw_user_bo->base,
+				   false,
+				   ttm_buffer_type,
+				   &vmw_user_dmabuf_release, NULL);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unref(&tmp);
+	} else {
+		rep->handle = vmw_user_bo->base.hash.key;
+		rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
+		rep->cur_gmr_id = vmw_user_bo->base.hash.key;
+		rep->cur_gmr_offset = 0;
+	}
+	ttm_bo_unref(&tmp);
+
+	ttm_read_unlock(&vmaster->lock);
+
+	return 0;
+}
+
+int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_vmw_unref_dmabuf_arg *arg =
+	    (struct drm_vmw_unref_dmabuf_arg *)data;
+
+	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					 arg->handle,
+					 TTM_REF_USAGE);
+}
+
+uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
+				  uint32_t cur_validate_node)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+
+	if (likely(vmw_bo->on_validate_list))
+		return vmw_bo->cur_validate_node;
+
+	vmw_bo->cur_validate_node = cur_validate_node;
+	vmw_bo->on_validate_list = true;
+
+	return cur_validate_node;
+}
+
+void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+
+	vmw_bo->on_validate_list = false;
+}
+
+uint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo;
+
+	if (bo->mem.mem_type == TTM_PL_VRAM)
+		return SVGA_GMR_FRAMEBUFFER;
+
+	vmw_bo = vmw_dma_buffer(bo);
+
+	return (vmw_bo->gmr_bound) ? vmw_bo->gmr_id : SVGA_GMR_NULL;
+}
+
+void vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	vmw_bo->gmr_bound = true;
+	vmw_bo->gmr_id = id;
+}
+
+int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
+			   uint32_t handle, struct vmw_dma_buffer **out)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_base_object *base;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return -ESRCH;
+	}
+
+	if (unlikely(base->object_type != ttm_buffer_type)) {
+		ttm_base_object_unref(&base);
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return -EINVAL;
+	}
+
+	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
+	(void)ttm_bo_reference(&vmw_user_bo->dma.base);
+	ttm_base_object_unref(&base);
+	*out = &vmw_user_bo->dma;
+
+	return 0;
+}
+
+/**
+ * TODO: Implement a gmr id eviction mechanism. Currently we just fail
+ * when we're out of ids, causing GMR space to be allocated
+ * out of VRAM.
+ */
+
+int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id)
+{
+	struct ttm_bo_global *glob = dev_priv->bdev.glob;
+	int id;
+	int ret;
+
+	do {
+		if (unlikely(ida_pre_get(&dev_priv->gmr_ida, GFP_KERNEL) == 0))
+			return -ENOMEM;
+
+		spin_lock(&glob->lru_lock);
+		ret = ida_get_new(&dev_priv->gmr_ida, &id);
+		spin_unlock(&glob->lru_lock);
+	} while (ret == -EAGAIN);
+
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (unlikely(id >= dev_priv->max_gmr_ids)) {
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, id);
+		spin_unlock(&glob->lru_lock);
+		return -EBUSY;
+	}
+
+	*p_id = (uint32_t) id;
+	return 0;
+}
+
+/*
+ * Stream managment
+ */
+
+static void vmw_stream_destroy(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct vmw_stream *stream;
+	int ret;
+
+	DRM_INFO("%s: unref\n", __func__);
+	stream = container_of(res, struct vmw_stream, res);
+
+	ret = vmw_overlay_unref(dev_priv, stream->stream_id);
+	WARN_ON(ret != 0);
+}
+
+static int vmw_stream_init(struct vmw_private *dev_priv,
+			   struct vmw_stream *stream,
+			   void (*res_free) (struct vmw_resource *res))
+{
+	struct vmw_resource *res = &stream->res;
+	int ret;
+
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
+				VMW_RES_STREAM, res_free);
+
+	if (unlikely(ret != 0)) {
+		if (res_free == NULL)
+			kfree(stream);
+		else
+			res_free(&stream->res);
+		return ret;
+	}
+
+	ret = vmw_overlay_claim(dev_priv, &stream->stream_id);
+	if (ret) {
+		vmw_resource_unreference(&res);
+		return ret;
+	}
+
+	DRM_INFO("%s: claimed\n", __func__);
+
+	vmw_resource_activate(&stream->res, vmw_stream_destroy);
+	return 0;
+}
+
+/**
+ * User-space context management:
+ */
+
+static void vmw_user_stream_free(struct vmw_resource *res)
+{
+	struct vmw_user_stream *stream =
+	    container_of(res, struct vmw_user_stream, stream.res);
+
+	kfree(stream);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_stream_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_stream *stream =
+	    container_of(base, struct vmw_user_stream, base);
+	struct vmw_resource *res = &stream->stream.res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_resource *res;
+	struct vmw_user_stream *stream;
+	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret = 0;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_stream_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	stream = container_of(res, struct vmw_user_stream, stream.res);
+	if (stream->base.tfile != tfile) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE);
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+
+	if (unlikely(stream == NULL))
+		return -ENOMEM;
+
+	res = &stream->stream.res;
+	stream->base.shareable = false;
+	stream->base.tfile = NULL;
+
+	ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(res);
+	ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
+				   &vmw_user_stream_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		goto out_err;
+	}
+
+	arg->stream_id = res->id;
+out_err:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_user_stream_lookup(struct vmw_private *dev_priv,
+			   struct ttm_object_file *tfile,
+			   uint32_t *inout_id, struct vmw_resource **out)
+{
+	struct vmw_user_stream *stream;
+	struct vmw_resource *res;
+	int ret;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_stream_free) {
+		ret = -EINVAL;
+		goto err_ref;
+	}
+
+	stream = container_of(res, struct vmw_user_stream, stream.res);
+	if (stream->base.tfile != tfile) {
+		ret = -EPERM;
+		goto err_ref;
+	}
+
+	*inout_id = stream->stream.stream_id;
+	*out = res;
+	return 0;
+err_ref:
+	vmw_resource_unreference(&res);
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -0,0 +1,286 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "vmwgfx_drv.h"
+
+#define VMW_FENCE_WRAP (1 << 24)
+
+irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *)arg;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	spin_lock(&dev_priv->irq_lock);
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	spin_unlock(&dev_priv->irq_lock);
+
+	if (status & SVGA_IRQFLAG_ANY_FENCE)
+		wake_up_all(&dev_priv->fence_queue);
+	if (status & SVGA_IRQFLAG_FIFO_PROGRESS)
+		wake_up_all(&dev_priv->fifo_queue);
+
+	if (likely(status)) {
+		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
+{
+	uint32_t busy;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	busy = vmw_read(dev_priv, SVGA_REG_BUSY);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return (busy == 0);
+}
+
+
+bool vmw_fence_signaled(struct vmw_private *dev_priv,
+			uint32_t sequence)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	struct vmw_fifo_state *fifo_state;
+	bool ret;
+
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return true;
+
+	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return true;
+
+	fifo_state = &dev_priv->fifo;
+	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
+	    vmw_fifo_idle(dev_priv, sequence))
+		return true;
+
+	/**
+	 * Then check if the sequence is higher than what we've actually
+	 * emitted. Then the fence is stale and signaled.
+	 */
+
+	ret = ((atomic_read(&dev_priv->fence_seq) - sequence)
+	       > VMW_FENCE_WRAP);
+
+	return ret;
+}
+
+int vmw_fallback_wait(struct vmw_private *dev_priv,
+		      bool lazy,
+		      bool fifo_idle,
+		      uint32_t sequence,
+		      bool interruptible,
+		      unsigned long timeout)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+
+	uint32_t count = 0;
+	uint32_t signal_seq;
+	int ret;
+	unsigned long end_jiffies = jiffies + timeout;
+	bool (*wait_condition)(struct vmw_private *, uint32_t);
+	DEFINE_WAIT(__wait);
+
+	wait_condition = (fifo_idle) ? &vmw_fifo_idle :
+		&vmw_fence_signaled;
+
+	/**
+	 * Block command submission while waiting for idle.
+	 */
+
+	if (fifo_idle)
+		down_read(&fifo_state->rwsem);
+	signal_seq = atomic_read(&dev_priv->fence_seq);
+	ret = 0;
+
+	for (;;) {
+		prepare_to_wait(&dev_priv->fence_queue, &__wait,
+				(interruptible) ?
+				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		if (wait_condition(dev_priv, sequence))
+			break;
+		if (time_after_eq(jiffies, end_jiffies)) {
+			DRM_ERROR("SVGA device lockup.\n");
+			break;
+		}
+		if (lazy)
+			schedule_timeout(1);
+		else if ((++count & 0x0F) == 0) {
+			/**
+			 * FIXME: Use schedule_hr_timeout here for
+			 * newer kernels and lower CPU utilization.
+			 */
+
+			__set_current_state(TASK_RUNNING);
+			schedule();
+			__set_current_state((interruptible) ?
+					    TASK_INTERRUPTIBLE :
+					    TASK_UNINTERRUPTIBLE);
+		}
+		if (interruptible && signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+	finish_wait(&dev_priv->fence_queue, &__wait);
+	if (ret == 0 && fifo_idle) {
+		__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+		iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
+	}
+	wake_up_all(&dev_priv->fence_queue);
+	if (fifo_idle)
+		up_read(&fifo_state->rwsem);
+
+	return ret;
+}
+
+int vmw_wait_fence(struct vmw_private *dev_priv,
+		   bool lazy, uint32_t sequence,
+		   bool interruptible, unsigned long timeout)
+{
+	long ret;
+	unsigned long irq_flags;
+	struct vmw_fifo_state *fifo = &dev_priv->fifo;
+
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return 0;
+
+	if (likely(vmw_fence_signaled(dev_priv, sequence)))
+		return 0;
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+
+	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
+		return vmw_fallback_wait(dev_priv, lazy, true, sequence,
+					 interruptible, timeout);
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return vmw_fallback_wait(dev_priv, lazy, false, sequence,
+					 interruptible, timeout);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_ANY_FENCE,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
+			  SVGA_IRQFLAG_ANY_FENCE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+		    (dev_priv->fence_queue,
+		     vmw_fence_signaled(dev_priv, sequence),
+		     timeout);
+	else
+		ret = wait_event_timeout
+		    (dev_priv->fence_queue,
+		     vmw_fence_signaled(dev_priv, sequence),
+		     timeout);
+
+	if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
+			  ~SVGA_IRQFLAG_ANY_FENCE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ret;
+}
+
+void vmw_irq_preinstall(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return;
+
+	spin_lock_init(&dev_priv->irq_lock);
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+}
+
+int vmw_irq_postinstall(struct drm_device *dev)
+{
+	return 0;
+}
+
+void vmw_irq_uninstall(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_IRQMASK, 0);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+}
+
+#define VMW_FENCE_WAIT_TIMEOUT 3*HZ;
+
+int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_wait_arg *arg =
+	    (struct drm_vmw_fence_wait_arg *)data;
+	unsigned long timeout;
+
+	if (!arg->cookie_valid) {
+		arg->cookie_valid = 1;
+		arg->kernel_cookie = jiffies + VMW_FENCE_WAIT_TIMEOUT;
+	}
+
+	timeout = jiffies;
+	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie))
+		return -EBUSY;
+
+	timeout = (unsigned long)arg->kernel_cookie - timeout;
+	return vmw_wait_fence(vmw_priv(dev), true, arg->sequence, true, timeout);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -0,0 +1,880 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_kms.h"
+
+/* Might need a hrtimer here? */
+#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
+
+
+void vmw_display_unit_cleanup(struct vmw_display_unit *du)
+{
+	if (du->cursor_surface)
+		vmw_surface_unreference(&du->cursor_surface);
+	if (du->cursor_dmabuf)
+		vmw_dmabuf_unreference(&du->cursor_dmabuf);
+	drm_crtc_cleanup(&du->crtc);
+	drm_encoder_cleanup(&du->encoder);
+	drm_connector_cleanup(&du->connector);
+}
+
+/*
+ * Display Unit Cursor functions
+ */
+
+int vmw_cursor_update_image(struct vmw_private *dev_priv,
+			    u32 *image, u32 width, u32 height,
+			    u32 hotspotX, u32 hotspotY)
+{
+	struct {
+		u32 cmd;
+		SVGAFifoCmdDefineAlphaCursor cursor;
+	} *cmd;
+	u32 image_size = width * height * 4;
+	u32 cmd_size = sizeof(*cmd) + image_size;
+
+	if (!image)
+		return -EINVAL;
+
+	cmd = vmw_fifo_reserve(dev_priv, cmd_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+
+	memcpy(&cmd[1], image, image_size);
+
+	cmd->cmd = cpu_to_le32(SVGA_CMD_DEFINE_ALPHA_CURSOR);
+	cmd->cursor.id = cpu_to_le32(0);
+	cmd->cursor.width = cpu_to_le32(width);
+	cmd->cursor.height = cpu_to_le32(height);
+	cmd->cursor.hotspotX = cpu_to_le32(hotspotX);
+	cmd->cursor.hotspotY = cpu_to_le32(hotspotY);
+
+	vmw_fifo_commit(dev_priv, cmd_size);
+
+	return 0;
+}
+
+void vmw_cursor_update_position(struct vmw_private *dev_priv,
+				bool show, int x, int y)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t count;
+
+	iowrite32(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
+	iowrite32(x, fifo_mem + SVGA_FIFO_CURSOR_X);
+	iowrite32(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
+	count = ioread32(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+	iowrite32(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+}
+
+int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+			   uint32_t handle, uint32_t width, uint32_t height)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	struct vmw_surface *surface = NULL;
+	struct vmw_dma_buffer *dmabuf = NULL;
+	int ret;
+
+	if (handle) {
+		ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
+						     handle, &surface);
+		if (!ret) {
+			if (!surface->snooper.image) {
+				DRM_ERROR("surface not suitable for cursor\n");
+				return -EINVAL;
+			}
+		} else {
+			ret = vmw_user_dmabuf_lookup(tfile,
+						     handle, &dmabuf);
+			if (ret) {
+				DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* takedown old cursor */
+	if (du->cursor_surface) {
+		du->cursor_surface->snooper.crtc = NULL;
+		vmw_surface_unreference(&du->cursor_surface);
+	}
+	if (du->cursor_dmabuf)
+		vmw_dmabuf_unreference(&du->cursor_dmabuf);
+
+	/* setup new image */
+	if (surface) {
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_surface = surface;
+
+		du->cursor_surface->snooper.crtc = crtc;
+		du->cursor_age = du->cursor_surface->snooper.age;
+		vmw_cursor_update_image(dev_priv, surface->snooper.image,
+					64, 64, du->hotspot_x, du->hotspot_y);
+	} else if (dmabuf) {
+		struct ttm_bo_kmap_obj map;
+		unsigned long kmap_offset;
+		unsigned long kmap_num;
+		void *virtual;
+		bool dummy;
+
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_dmabuf = dmabuf;
+
+		kmap_offset = 0;
+		kmap_num = (64*64*4) >> PAGE_SHIFT;
+
+		ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("reserve failed\n");
+			return -EINVAL;
+		}
+
+		ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
+		if (unlikely(ret != 0))
+			goto err_unreserve;
+
+		virtual = ttm_kmap_obj_virtual(&map, &dummy);
+		vmw_cursor_update_image(dev_priv, virtual, 64, 64,
+					du->hotspot_x, du->hotspot_y);
+
+		ttm_bo_kunmap(&map);
+err_unreserve:
+		ttm_bo_unreserve(&dmabuf->base);
+
+	} else {
+		vmw_cursor_update_position(dev_priv, false, 0, 0);
+		return 0;
+	}
+
+	vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y);
+
+	return 0;
+}
+
+int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
+
+	du->cursor_x = x + crtc->x;
+	du->cursor_y = y + crtc->y;
+
+	vmw_cursor_update_position(dev_priv, shown,
+				   du->cursor_x, du->cursor_y);
+
+	return 0;
+}
+
+void vmw_kms_cursor_snoop(struct vmw_surface *srf,
+			  struct ttm_object_file *tfile,
+			  struct ttm_buffer_object *bo,
+			  SVGA3dCmdHeader *header)
+{
+	struct ttm_bo_kmap_obj map;
+	unsigned long kmap_offset;
+	unsigned long kmap_num;
+	SVGA3dCopyBox *box;
+	unsigned box_count;
+	void *virtual;
+	bool dummy;
+	struct vmw_dma_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceDMA dma;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_dma_cmd, header);
+
+	/* No snooper installed */
+	if (!srf->snooper.image)
+		return;
+
+	if (cmd->dma.host.face != 0 || cmd->dma.host.mipmap != 0) {
+		DRM_ERROR("face and mipmap for cursors should never != 0\n");
+		return;
+	}
+
+	if (cmd->header.size < 64) {
+		DRM_ERROR("at least one full copy box must be given\n");
+		return;
+	}
+
+	box = (SVGA3dCopyBox *)&cmd[1];
+	box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
+			sizeof(SVGA3dCopyBox);
+
+	if (cmd->dma.guest.pitch != (64 * 4) ||
+	    cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+	    box->x != 0    || box->y != 0    || box->z != 0    ||
+	    box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
+	    box->w != 64   || box->h != 64   || box->d != 1    ||
+	    box_count != 1) {
+		/* TODO handle none page aligned offsets */
+		/* TODO handle partial uploads and pitch != 256 */
+		/* TODO handle more then one copy (size != 64) */
+		DRM_ERROR("lazy programer, cant handle wierd stuff\n");
+		return;
+	}
+
+	kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
+	kmap_num = (64*64*4) >> PAGE_SHIFT;
+
+	ret = ttm_bo_reserve(bo, true, false, false, 0);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("reserve failed\n");
+		return;
+	}
+
+	ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0))
+		goto err_unreserve;
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+
+	memcpy(srf->snooper.image, virtual, 64*64*4);
+	srf->snooper.age++;
+
+	/* we can't call this function from this function since execbuf has
+	 * reserved fifo space.
+	 *
+	 * if (srf->snooper.crtc)
+	 *	vmw_ldu_crtc_cursor_update_image(dev_priv,
+	 *					 srf->snooper.image, 64, 64,
+	 *					 du->hotspot_x, du->hotspot_y);
+	 */
+
+	ttm_bo_kunmap(&map);
+err_unreserve:
+	ttm_bo_unreserve(bo);
+}
+
+void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_display_unit *du;
+	struct drm_crtc *crtc;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		du = vmw_crtc_to_du(crtc);
+		if (!du->cursor_surface ||
+		    du->cursor_age == du->cursor_surface->snooper.age)
+			continue;
+
+		du->cursor_age = du->cursor_surface->snooper.age;
+		vmw_cursor_update_image(dev_priv,
+					du->cursor_surface->snooper.image,
+					64, 64, du->hotspot_x, du->hotspot_y);
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+/*
+ * Generic framebuffer code
+ */
+
+int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
+				  struct drm_file *file_priv,
+				  unsigned int *handle)
+{
+	if (handle)
+		handle = 0;
+
+	return 0;
+}
+
+/*
+ * Surface framebuffer code
+ */
+
+#define vmw_framebuffer_to_vfbs(x) \
+	container_of(x, struct vmw_framebuffer_surface, base.base)
+
+struct vmw_framebuffer_surface {
+	struct vmw_framebuffer base;
+	struct vmw_surface *surface;
+	struct delayed_work d_work;
+	struct mutex work_lock;
+	bool present_fs;
+};
+
+void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
+{
+	struct vmw_framebuffer_surface *vfb =
+		vmw_framebuffer_to_vfbs(framebuffer);
+
+	cancel_delayed_work_sync(&vfb->d_work);
+	drm_framebuffer_cleanup(framebuffer);
+	vmw_surface_unreference(&vfb->surface);
+
+	kfree(framebuffer);
+}
+
+static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
+{
+	struct delayed_work *d_work =
+		container_of(work, struct delayed_work, work);
+	struct vmw_framebuffer_surface *vfbs =
+		container_of(d_work, struct vmw_framebuffer_surface, d_work);
+	struct vmw_surface *surf = vfbs->surface;
+	struct drm_framebuffer *framebuffer = &vfbs->base.base;
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+		SVGA3dCopyRect cr;
+	} *cmd;
+
+	mutex_lock(&vfbs->work_lock);
+	if (!vfbs->present_fs)
+		goto out_unlock;
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL))
+		goto out_resched;
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr));
+	cmd->body.sid = cpu_to_le32(surf->res.id);
+	cmd->cr.x = cpu_to_le32(0);
+	cmd->cr.y = cpu_to_le32(0);
+	cmd->cr.srcx = cmd->cr.x;
+	cmd->cr.srcy = cmd->cr.y;
+	cmd->cr.w = cpu_to_le32(framebuffer->width);
+	cmd->cr.h = cpu_to_le32(framebuffer->height);
+	vfbs->present_fs = false;
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+out_resched:
+	/**
+	 * Will not re-add if already pending.
+	 */
+	schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
+out_unlock:
+	mutex_unlock(&vfbs->work_lock);
+}
+
+
+int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
+				  unsigned flags, unsigned color,
+				  struct drm_clip_rect *clips,
+				  unsigned num_clips)
+{
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_framebuffer_surface *vfbs =
+		vmw_framebuffer_to_vfbs(framebuffer);
+	struct vmw_surface *surf = vfbs->surface;
+	struct drm_clip_rect norect;
+	SVGA3dCopyRect *cr;
+	int i, inc = 1;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+		SVGA3dCopyRect cr;
+	} *cmd;
+
+	if (!num_clips ||
+	    !(dev_priv->fifo.capabilities &
+	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
+		int ret;
+
+		mutex_lock(&vfbs->work_lock);
+		vfbs->present_fs = true;
+		ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
+		mutex_unlock(&vfbs->work_lock);
+		if (ret) {
+			/**
+			 * No work pending, Force immediate present.
+			 */
+			vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
+		}
+		return 0;
+	}
+
+	if (!num_clips) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		inc = 2; /* skip source rects */
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr));
+	cmd->body.sid = cpu_to_le32(surf->res.id);
+
+	for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) {
+		cr->x = cpu_to_le16(clips->x1);
+		cr->y = cpu_to_le16(clips->y1);
+		cr->srcx = cr->x;
+		cr->srcy = cr->y;
+		cr->w = cpu_to_le16(clips->x2 - clips->x1);
+		cr->h = cpu_to_le16(clips->y2 - clips->y1);
+	}
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = {
+	.destroy = vmw_framebuffer_surface_destroy,
+	.dirty = vmw_framebuffer_surface_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
+				    struct vmw_surface *surface,
+				    struct vmw_framebuffer **out,
+				    unsigned width, unsigned height)
+
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_framebuffer_surface *vfbs;
+	int ret;
+
+	vfbs = kzalloc(sizeof(*vfbs), GFP_KERNEL);
+	if (!vfbs) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+
+	ret = drm_framebuffer_init(dev, &vfbs->base.base,
+				   &vmw_framebuffer_surface_funcs);
+	if (ret)
+		goto out_err2;
+
+	if (!vmw_surface_reference(surface)) {
+		DRM_ERROR("failed to reference surface %p\n", surface);
+		goto out_err3;
+	}
+
+	/* XXX get the first 3 from the surface info */
+	vfbs->base.base.bits_per_pixel = 32;
+	vfbs->base.base.pitch = width * 32 / 4;
+	vfbs->base.base.depth = 24;
+	vfbs->base.base.width = width;
+	vfbs->base.base.height = height;
+	vfbs->base.pin = NULL;
+	vfbs->base.unpin = NULL;
+	vfbs->surface = surface;
+	mutex_init(&vfbs->work_lock);
+	INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
+	*out = &vfbs->base;
+
+	return 0;
+
+out_err3:
+	drm_framebuffer_cleanup(&vfbs->base.base);
+out_err2:
+	kfree(vfbs);
+out_err1:
+	return ret;
+}
+
+/*
+ * Dmabuf framebuffer code
+ */
+
+#define vmw_framebuffer_to_vfbd(x) \
+	container_of(x, struct vmw_framebuffer_dmabuf, base.base)
+
+struct vmw_framebuffer_dmabuf {
+	struct vmw_framebuffer base;
+	struct vmw_dma_buffer *buffer;
+};
+
+void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
+{
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(framebuffer);
+
+	drm_framebuffer_cleanup(framebuffer);
+	vmw_dmabuf_unreference(&vfbd->buffer);
+
+	kfree(vfbd);
+}
+
+int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+				 unsigned flags, unsigned color,
+				 struct drm_clip_rect *clips,
+				 unsigned num_clips)
+{
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct drm_clip_rect norect;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdUpdate body;
+	} *cmd;
+	int i, increment = 1;
+
+	if (!num_clips) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		increment = 2;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_clips; i++, clips += increment) {
+		cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
+		cmd[i].body.x = cpu_to_le32(clips->x1);
+		cmd[i].body.y = cpu_to_le32(clips->y1);
+		cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1);
+		cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
+	}
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
+	.destroy = vmw_framebuffer_dmabuf_destroy,
+	.dirty = vmw_framebuffer_dmabuf_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
+{
+	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+	int ret;
+
+	vmw_overlay_pause_all(dev_priv);
+
+	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
+
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+		vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
+		vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
+		vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
+		vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
+		vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+		vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+		vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+	} else
+		WARN_ON(true);
+
+	vmw_overlay_resume_all(dev_priv);
+
+	return 0;
+}
+
+static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb)
+{
+	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+
+	if (!vfbd->buffer) {
+		WARN_ON(!vfbd->buffer);
+		return 0;
+	}
+
+	return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
+}
+
+int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
+				   struct vmw_dma_buffer *dmabuf,
+				   struct vmw_framebuffer **out,
+				   unsigned width, unsigned height)
+
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_framebuffer_dmabuf *vfbd;
+	int ret;
+
+	vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
+	if (!vfbd) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+
+	ret = drm_framebuffer_init(dev, &vfbd->base.base,
+				   &vmw_framebuffer_dmabuf_funcs);
+	if (ret)
+		goto out_err2;
+
+	if (!vmw_dmabuf_reference(dmabuf)) {
+		DRM_ERROR("failed to reference dmabuf %p\n", dmabuf);
+		goto out_err3;
+	}
+
+	/* XXX get the first 3 from the surface info */
+	vfbd->base.base.bits_per_pixel = 32;
+	vfbd->base.base.pitch = width * 32 / 4;
+	vfbd->base.base.depth = 24;
+	vfbd->base.base.width = width;
+	vfbd->base.base.height = height;
+	vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
+	vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	vfbd->buffer = dmabuf;
+	*out = &vfbd->base;
+
+	return 0;
+
+out_err3:
+	drm_framebuffer_cleanup(&vfbd->base.base);
+out_err2:
+	kfree(vfbd);
+out_err1:
+	return ret;
+}
+
+/*
+ * Generic Kernel modesetting functions
+ */
+
+static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
+						 struct drm_file *file_priv,
+						 struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_framebuffer *vfb = NULL;
+	struct vmw_surface *surface = NULL;
+	struct vmw_dma_buffer *bo = NULL;
+	int ret;
+
+	ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
+					     mode_cmd->handle, &surface);
+	if (ret)
+		goto try_dmabuf;
+
+	if (!surface->scanout)
+		goto err_not_scanout;
+
+	ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
+					      mode_cmd->width, mode_cmd->height);
+
+	/* vmw_user_surface_lookup takes one ref so does new_fb */
+	vmw_surface_unreference(&surface);
+
+	if (ret) {
+		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		return NULL;
+	}
+	return &vfb->base;
+
+try_dmabuf:
+	DRM_INFO("%s: trying buffer\n", __func__);
+
+	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
+	if (ret) {
+		DRM_ERROR("failed to find buffer: %i\n", ret);
+		return NULL;
+	}
+
+	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
+					     mode_cmd->width, mode_cmd->height);
+
+	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
+	vmw_dmabuf_unreference(&bo);
+
+	if (ret) {
+		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		return NULL;
+	}
+
+	return &vfb->base;
+
+err_not_scanout:
+	DRM_ERROR("surface not marked as scanout\n");
+	/* vmw_user_surface_lookup takes one ref */
+	vmw_surface_unreference(&surface);
+
+	return NULL;
+}
+
+static int vmw_kms_fb_changed(struct drm_device *dev)
+{
+	return 0;
+}
+
+static struct drm_mode_config_funcs vmw_kms_funcs = {
+	.fb_create = vmw_kms_fb_create,
+	.fb_changed = vmw_kms_fb_changed,
+};
+
+int vmw_kms_init(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int ret;
+
+	drm_mode_config_init(dev);
+	dev->mode_config.funcs = &vmw_kms_funcs;
+	dev->mode_config.min_width = 1;
+	dev->mode_config.min_height = 1;
+	dev->mode_config.max_width = dev_priv->fb_max_width;
+	dev->mode_config.max_height = dev_priv->fb_max_height;
+
+	ret = vmw_kms_init_legacy_display_system(dev_priv);
+
+	return 0;
+}
+
+int vmw_kms_close(struct vmw_private *dev_priv)
+{
+	/*
+	 * Docs says we should take the lock before calling this function
+	 * but since it destroys encoders and our destructor calls
+	 * drm_encoder_cleanup which takes the lock we deadlock.
+	 */
+	drm_mode_config_cleanup(dev_priv->dev);
+	vmw_kms_close_legacy_display_system(dev_priv);
+	return 0;
+}
+
+int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct drm_vmw_cursor_bypass_arg *arg = data;
+	struct vmw_display_unit *du;
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	int ret = 0;
+
+
+	mutex_lock(&dev->mode_config.mutex);
+	if (arg->flags & DRM_VMW_CURSOR_BYPASS_ALL) {
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			du = vmw_crtc_to_du(crtc);
+			du->hotspot_x = arg->xhot;
+			du->hotspot_y = arg->yhot;
+		}
+
+		mutex_unlock(&dev->mode_config.mutex);
+		return 0;
+	}
+
+	obj = drm_mode_object_find(dev, arg->crtc_id, DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	crtc = obj_to_crtc(obj);
+	du = vmw_crtc_to_du(crtc);
+
+	du->hotspot_x = arg->xhot;
+	du->hotspot_y = arg->yhot;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+int vmw_kms_save_vga(struct vmw_private *vmw_priv)
+{
+	/*
+	 * setup a single multimon monitor with the size
+	 * of 0x0, this stops the UI from resizing when we
+	 * change the framebuffer size
+	 */
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	}
+
+	vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
+	vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
+	vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
+	vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+	vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
+	vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
+	vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
+	vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+
+	return 0;
+}
+
+int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
+{
+	vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
+	vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
+	vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+	vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
+	vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
+	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
+	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
+
+	/* TODO check for multimon */
+	vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "vmwgfx_drv.h"
+#include "vmwgfx_drm.h"
+
+int vmw_getparam_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_getparam_arg *param =
+	    (struct drm_vmw_getparam_arg *)data;
+
+	switch (param->param) {
+	case DRM_VMW_PARAM_NUM_STREAMS:
+		param->value = vmw_overlay_num_overlays(dev_priv);
+		break;
+	case DRM_VMW_PARAM_NUM_FREE_STREAMS:
+		param->value = vmw_overlay_num_free_overlays(dev_priv);
+		break;
+	case DRM_VMW_PARAM_3D:
+		param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0;
+		break;
+	case DRM_VMW_PARAM_FIFO_OFFSET:
+		param->value = dev_priv->mmio_start;
+		break;
+	case DRM_VMW_PARAM_HW_CAPS:
+		param->value = dev_priv->capabilities;
+		break;
+	case DRM_VMW_PARAM_FIFO_CAPS:
+		param->value = dev_priv->fifo.capabilities;
+		break;
+	default:
+		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
+			  param->param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	struct drm_vmw_fifo_debug_arg *arg =
+	    (struct drm_vmw_fifo_debug_arg *)data;
+	__le32 __user *buffer = (__le32 __user *)
+	    (unsigned long)arg->debug_buffer;
+
+	if (unlikely(fifo_state->last_buffer == NULL))
+		return -EINVAL;
+
+	if (arg->debug_buffer_size < fifo_state->last_data_size) {
+		arg->used_size = arg->debug_buffer_size;
+		arg->did_not_fit = 1;
+	} else {
+		arg->used_size = fifo_state->last_data_size;
+		arg->did_not_fit = 0;
+	}
+	return copy_to_user(buffer, fifo_state->last_buffer, arg->used_size);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/vmwgfx/svga3d_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/vmwgfx/svga3d_reg.h
@@ -0,0 +1,1793 @@
+/**********************************************************
+ * Copyright 1998-2009 VMware, Inc.  All rights reserved.
+ *
+ * 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.
+ *
+ **********************************************************/
+
+/*
+ * svga3d_reg.h --
+ *
+ *       SVGA 3D hardware definitions
+ */
+
+#ifndef _SVGA3D_REG_H_
+#define _SVGA3D_REG_H_
+
+#include "svga_reg.h"
+
+
+/*
+ * 3D Hardware Version
+ *
+ *   The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo
+ *   register.   Is set by the host and read by the guest.  This lets
+ *   us make new guest drivers which are backwards-compatible with old
+ *   SVGA hardware revisions.  It does not let us support old guest
+ *   drivers.  Good enough for now.
+ *
+ */
+
+#define SVGA3D_MAKE_HWVERSION(major, minor)      (((major) << 16) | ((minor) & 0xFF))
+#define SVGA3D_MAJOR_HWVERSION(version)          ((version) >> 16)
+#define SVGA3D_MINOR_HWVERSION(version)          ((version) & 0xFF)
+
+typedef enum {
+   SVGA3D_HWVERSION_WS5_RC1   = SVGA3D_MAKE_HWVERSION(0, 1),
+   SVGA3D_HWVERSION_WS5_RC2   = SVGA3D_MAKE_HWVERSION(0, 2),
+   SVGA3D_HWVERSION_WS51_RC1  = SVGA3D_MAKE_HWVERSION(0, 3),
+   SVGA3D_HWVERSION_WS6_B1    = SVGA3D_MAKE_HWVERSION(1, 1),
+   SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
+   SVGA3D_HWVERSION_WS65_B1   = SVGA3D_MAKE_HWVERSION(2, 0),
+   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS65_B1,
+} SVGA3dHardwareVersion;
+
+/*
+ * Generic Types
+ */
+
+typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
+#define SVGA3D_NUM_CLIPPLANES                   6
+#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS  8
+
+
+/*
+ * Surface formats.
+ *
+ * If you modify this list, be sure to keep GLUtil.c in sync. It
+ * includes the internal format definition of each surface in
+ * GLUtil_ConvertSurfaceFormat, and it contains a table of
+ * human-readable names in GLUtil_GetFormatName.
+ */
+
+typedef enum SVGA3dSurfaceFormat {
+   SVGA3D_FORMAT_INVALID = 0,
+
+   SVGA3D_X8R8G8B8       = 1,
+   SVGA3D_A8R8G8B8       = 2,
+
+   SVGA3D_R5G6B5         = 3,
+   SVGA3D_X1R5G5B5       = 4,
+   SVGA3D_A1R5G5B5       = 5,
+   SVGA3D_A4R4G4B4       = 6,
+
+   SVGA3D_Z_D32          = 7,
+   SVGA3D_Z_D16          = 8,
+   SVGA3D_Z_D24S8        = 9,
+   SVGA3D_Z_D15S1        = 10,
+
+   SVGA3D_LUMINANCE8            = 11,
+   SVGA3D_LUMINANCE4_ALPHA4     = 12,
+   SVGA3D_LUMINANCE16           = 13,
+   SVGA3D_LUMINANCE8_ALPHA8     = 14,
+
+   SVGA3D_DXT1           = 15,
+   SVGA3D_DXT2           = 16,
+   SVGA3D_DXT3           = 17,
+   SVGA3D_DXT4           = 18,
+   SVGA3D_DXT5           = 19,
+
+   SVGA3D_BUMPU8V8       = 20,
+   SVGA3D_BUMPL6V5U5     = 21,
+   SVGA3D_BUMPX8L8V8U8   = 22,
+   SVGA3D_BUMPL8V8U8     = 23,
+
+   SVGA3D_ARGB_S10E5     = 24,   /* 16-bit floating-point ARGB */
+   SVGA3D_ARGB_S23E8     = 25,   /* 32-bit floating-point ARGB */
+
+   SVGA3D_A2R10G10B10    = 26,
+
+   /* signed formats */
+   SVGA3D_V8U8           = 27,
+   SVGA3D_Q8W8V8U8       = 28,
+   SVGA3D_CxV8U8         = 29,
+
+   /* mixed formats */
+   SVGA3D_X8L8V8U8       = 30,
+   SVGA3D_A2W10V10U10    = 31,
+
+   SVGA3D_ALPHA8         = 32,
+
+   /* Single- and dual-component floating point formats */
+   SVGA3D_R_S10E5        = 33,
+   SVGA3D_R_S23E8        = 34,
+   SVGA3D_RG_S10E5       = 35,
+   SVGA3D_RG_S23E8       = 36,
+
+   /*
+    * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
+    * the most efficient format to use when creating new surfaces
+    * expressly for index or vertex data.
+    */
+   SVGA3D_BUFFER         = 37,
+
+   SVGA3D_Z_D24X8        = 38,
+
+   SVGA3D_V16U16         = 39,
+
+   SVGA3D_G16R16         = 40,
+   SVGA3D_A16B16G16R16   = 41,
+
+   /* Packed Video formats */
+   SVGA3D_UYVY           = 42,
+   SVGA3D_YUY2           = 43,
+
+   SVGA3D_FORMAT_MAX
+} SVGA3dSurfaceFormat;
+
+typedef uint32 SVGA3dColor; /* a, r, g, b */
+
+/*
+ * These match the D3DFORMAT_OP definitions used by Direct3D. We need
+ * them so that we can query the host for what the supported surface
+ * operations are (when we're using the D3D backend, in particular),
+ * and so we can send those operations to the guest.
+ */
+typedef enum {
+   SVGA3DFORMAT_OP_TEXTURE                               = 0x00000001,
+   SVGA3DFORMAT_OP_VOLUMETEXTURE                         = 0x00000002,
+   SVGA3DFORMAT_OP_CUBETEXTURE                           = 0x00000004,
+   SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET                = 0x00000008,
+   SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET              = 0x00000010,
+   SVGA3DFORMAT_OP_ZSTENCIL                              = 0x00000040,
+   SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH   = 0x00000080,
+
+/*
+ * This format can be used as a render target if the current display mode
+ * is the same depth if the alpha channel is ignored. e.g. if the device
+ * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the
+ * format op list entry for A8R8G8B8 should have this cap.
+ */
+   SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET  = 0x00000100,
+
+/*
+ * This format contains DirectDraw support (including Flip).  This flag
+ * should not to be set on alpha formats.
+ */
+   SVGA3DFORMAT_OP_DISPLAYMODE                           = 0x00000400,
+
+/*
+ * The rasterizer can support some level of Direct3D support in this format
+ * and implies that the driver can create a Context in this mode (for some
+ * render target format).  When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE
+ * flag must also be set.
+ */
+   SVGA3DFORMAT_OP_3DACCELERATION                        = 0x00000800,
+
+/*
+ * This is set for a private format when the driver has put the bpp in
+ * the structure.
+ */
+   SVGA3DFORMAT_OP_PIXELSIZE                             = 0x00001000,
+
+/*
+ * Indicates that this format can be converted to any RGB format for which
+ * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified
+ */
+   SVGA3DFORMAT_OP_CONVERT_TO_ARGB                       = 0x00002000,
+
+/*
+ * Indicates that this format can be used to create offscreen plain surfaces.
+ */
+   SVGA3DFORMAT_OP_OFFSCREENPLAIN                        = 0x00004000,
+
+/*
+ * Indicated that this format can be read as an SRGB texture (meaning that the
+ * sampler will linearize the looked up data)
+ */
+   SVGA3DFORMAT_OP_SRGBREAD                              = 0x00008000,
+
+/*
+ * Indicates that this format can be used in the bumpmap instructions
+ */
+   SVGA3DFORMAT_OP_BUMPMAP                               = 0x00010000,
+
+/*
+ * Indicates that this format can be sampled by the displacement map sampler
+ */
+   SVGA3DFORMAT_OP_DMAP                                  = 0x00020000,
+
+/*
+ * Indicates that this format cannot be used with texture filtering
+ */
+   SVGA3DFORMAT_OP_NOFILTER                              = 0x00040000,
+
+/*
+ * Indicates that format conversions are supported to this RGB format if
+ * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format.
+ */
+   SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB                    = 0x00080000,
+
+/*
+ * Indicated that this format can be written as an SRGB target (meaning that the
+ * pixel pipe will DE-linearize data on output to format)
+ */
+   SVGA3DFORMAT_OP_SRGBWRITE                             = 0x00100000,
+
+/*
+ * Indicates that this format cannot be used with alpha blending
+ */
+   SVGA3DFORMAT_OP_NOALPHABLEND                          = 0x00200000,
+
+/*
+ * Indicates that the device can auto-generated sublevels for resources
+ * of this format
+ */
+   SVGA3DFORMAT_OP_AUTOGENMIPMAP                         = 0x00400000,
+
+/*
+ * Indicates that this format can be used by vertex texture sampler
+ */
+   SVGA3DFORMAT_OP_VERTEXTEXTURE                         = 0x00800000,
+
+/*
+ * Indicates that this format supports neither texture coordinate wrap
+ * modes, nor mipmapping
+ */
+   SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP                  = 0x01000000
+} SVGA3dFormatOp;
+
+/*
+ * This structure is a conversion of SVGA3DFORMAT_OP_*.
+ * Entries must be located at the same position.
+ */
+typedef union {
+   uint32 value;
+   struct {
+      uint32 texture : 1;
+      uint32 volumeTexture : 1;
+      uint32 cubeTexture : 1;
+      uint32 offscreenRenderTarget : 1;
+      uint32 sameFormatRenderTarget : 1;
+      uint32 unknown1 : 1;
+      uint32 zStencil : 1;
+      uint32 zStencilArbitraryDepth : 1;
+      uint32 sameFormatUpToAlpha : 1;
+      uint32 unknown2 : 1;
+      uint32 displayMode : 1;
+      uint32 acceleration3d : 1;
+      uint32 pixelSize : 1;
+      uint32 convertToARGB : 1;
+      uint32 offscreenPlain : 1;
+      uint32 sRGBRead : 1;
+      uint32 bumpMap : 1;
+      uint32 dmap : 1;
+      uint32 noFilter : 1;
+      uint32 memberOfGroupARGB : 1;
+      uint32 sRGBWrite : 1;
+      uint32 noAlphaBlend : 1;
+      uint32 autoGenMipMap : 1;
+      uint32 vertexTexture : 1;
+      uint32 noTexCoordWrapNorMip : 1;
+   };
+} SVGA3dSurfaceFormatCaps;
+
+/*
+ * SVGA_3D_CMD_SETRENDERSTATE Types.  All value types
+ * must fit in a uint32.
+ */
+
+typedef enum {
+   SVGA3D_RS_INVALID                   = 0,
+   SVGA3D_RS_ZENABLE                   = 1,     /* SVGA3dBool */
+   SVGA3D_RS_ZWRITEENABLE              = 2,     /* SVGA3dBool */
+   SVGA3D_RS_ALPHATESTENABLE           = 3,     /* SVGA3dBool */
+   SVGA3D_RS_DITHERENABLE              = 4,     /* SVGA3dBool */
+   SVGA3D_RS_BLENDENABLE               = 5,     /* SVGA3dBool */
+   SVGA3D_RS_FOGENABLE                 = 6,     /* SVGA3dBool */
+   SVGA3D_RS_SPECULARENABLE            = 7,     /* SVGA3dBool */
+   SVGA3D_RS_STENCILENABLE             = 8,     /* SVGA3dBool */
+   SVGA3D_RS_LIGHTINGENABLE            = 9,     /* SVGA3dBool */
+   SVGA3D_RS_NORMALIZENORMALS          = 10,    /* SVGA3dBool */
+   SVGA3D_RS_POINTSPRITEENABLE         = 11,    /* SVGA3dBool */
+   SVGA3D_RS_POINTSCALEENABLE          = 12,    /* SVGA3dBool */
+   SVGA3D_RS_STENCILREF                = 13,    /* uint32 */
+   SVGA3D_RS_STENCILMASK               = 14,    /* uint32 */
+   SVGA3D_RS_STENCILWRITEMASK          = 15,    /* uint32 */
+   SVGA3D_RS_FOGSTART                  = 16,    /* float */
+   SVGA3D_RS_FOGEND                    = 17,    /* float */
+   SVGA3D_RS_FOGDENSITY                = 18,    /* float */
+   SVGA3D_RS_POINTSIZE                 = 19,    /* float */
+   SVGA3D_RS_POINTSIZEMIN              = 20,    /* float */
+   SVGA3D_RS_POINTSIZEMAX              = 21,    /* float */
+   SVGA3D_RS_POINTSCALE_A              = 22,    /* float */
+   SVGA3D_RS_POINTSCALE_B              = 23,    /* float */
+   SVGA3D_RS_POINTSCALE_C              = 24,    /* float */
+   SVGA3D_RS_FOGCOLOR                  = 25,    /* SVGA3dColor */
+   SVGA3D_RS_AMBIENT                   = 26,    /* SVGA3dColor */
+   SVGA3D_RS_CLIPPLANEENABLE           = 27,    /* SVGA3dClipPlanes */
+   SVGA3D_RS_FOGMODE                   = 28,    /* SVGA3dFogMode */
+   SVGA3D_RS_FILLMODE                  = 29,    /* SVGA3dFillMode */
+   SVGA3D_RS_SHADEMODE                 = 30,    /* SVGA3dShadeMode */
+   SVGA3D_RS_LINEPATTERN               = 31,    /* SVGA3dLinePattern */
+   SVGA3D_RS_SRCBLEND                  = 32,    /* SVGA3dBlendOp */
+   SVGA3D_RS_DSTBLEND                  = 33,    /* SVGA3dBlendOp */
+   SVGA3D_RS_BLENDEQUATION             = 34,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_CULLMODE                  = 35,    /* SVGA3dFace */
+   SVGA3D_RS_ZFUNC                     = 36,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_ALPHAFUNC                 = 37,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_STENCILFUNC               = 38,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_STENCILFAIL               = 39,    /* SVGA3dStencilOp */
+   SVGA3D_RS_STENCILZFAIL              = 40,    /* SVGA3dStencilOp */
+   SVGA3D_RS_STENCILPASS               = 41,    /* SVGA3dStencilOp */
+   SVGA3D_RS_ALPHAREF                  = 42,    /* float (0.0 .. 1.0) */
+   SVGA3D_RS_FRONTWINDING              = 43,    /* SVGA3dFrontWinding */
+   SVGA3D_RS_COORDINATETYPE            = 44,    /* SVGA3dCoordinateType */
+   SVGA3D_RS_ZBIAS                     = 45,    /* float */
+   SVGA3D_RS_RANGEFOGENABLE            = 46,    /* SVGA3dBool */
+   SVGA3D_RS_COLORWRITEENABLE          = 47,    /* SVGA3dColorMask */
+   SVGA3D_RS_VERTEXMATERIALENABLE      = 48,    /* SVGA3dBool */
+   SVGA3D_RS_DIFFUSEMATERIALSOURCE     = 49,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_SPECULARMATERIALSOURCE    = 50,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_AMBIENTMATERIALSOURCE     = 51,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_EMISSIVEMATERIALSOURCE    = 52,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_TEXTUREFACTOR             = 53,    /* SVGA3dColor */
+   SVGA3D_RS_LOCALVIEWER               = 54,    /* SVGA3dBool */
+   SVGA3D_RS_SCISSORTESTENABLE         = 55,    /* SVGA3dBool */
+   SVGA3D_RS_BLENDCOLOR                = 56,    /* SVGA3dColor */
+   SVGA3D_RS_STENCILENABLE2SIDED       = 57,    /* SVGA3dBool */
+   SVGA3D_RS_CCWSTENCILFUNC            = 58,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_CCWSTENCILFAIL            = 59,    /* SVGA3dStencilOp */
+   SVGA3D_RS_CCWSTENCILZFAIL           = 60,    /* SVGA3dStencilOp */
+   SVGA3D_RS_CCWSTENCILPASS            = 61,    /* SVGA3dStencilOp */
+   SVGA3D_RS_VERTEXBLEND               = 62,    /* SVGA3dVertexBlendFlags */
+   SVGA3D_RS_SLOPESCALEDEPTHBIAS       = 63,    /* float */
+   SVGA3D_RS_DEPTHBIAS                 = 64,    /* float */
+
+
+   /*
+    * Output Gamma Level
+    *
+    * Output gamma effects the gamma curve of colors that are output from the
+    * rendering pipeline.  A value of 1.0 specifies a linear color space. If the
+    * value is <= 0.0, gamma correction is ignored and linear color space is
+    * used.
+    */
+
+   SVGA3D_RS_OUTPUTGAMMA               = 65,    /* float */
+   SVGA3D_RS_ZVISIBLE                  = 66,    /* SVGA3dBool */
+   SVGA3D_RS_LASTPIXEL                 = 67,    /* SVGA3dBool */
+   SVGA3D_RS_CLIPPING                  = 68,    /* SVGA3dBool */
+   SVGA3D_RS_WRAP0                     = 69,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP1                     = 70,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP2                     = 71,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP3                     = 72,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP4                     = 73,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP5                     = 74,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP6                     = 75,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP7                     = 76,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP8                     = 77,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP9                     = 78,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP10                    = 79,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP11                    = 80,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP12                    = 81,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP13                    = 82,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP14                    = 83,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP15                    = 84,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_MULTISAMPLEANTIALIAS      = 85,    /* SVGA3dBool */
+   SVGA3D_RS_MULTISAMPLEMASK           = 86,    /* uint32 */
+   SVGA3D_RS_INDEXEDVERTEXBLENDENABLE  = 87,    /* SVGA3dBool */
+   SVGA3D_RS_TWEENFACTOR               = 88,    /* float */
+   SVGA3D_RS_ANTIALIASEDLINEENABLE     = 89,    /* SVGA3dBool */
+   SVGA3D_RS_COLORWRITEENABLE1         = 90,    /* SVGA3dColorMask */
+   SVGA3D_RS_COLORWRITEENABLE2         = 91,    /* SVGA3dColorMask */
+   SVGA3D_RS_COLORWRITEENABLE3         = 92,    /* SVGA3dColorMask */
+   SVGA3D_RS_SEPARATEALPHABLENDENABLE  = 93,    /* SVGA3dBool */
+   SVGA3D_RS_SRCBLENDALPHA             = 94,    /* SVGA3dBlendOp */
+   SVGA3D_RS_DSTBLENDALPHA             = 95,    /* SVGA3dBlendOp */
+   SVGA3D_RS_BLENDEQUATIONALPHA        = 96,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_MAX
+} SVGA3dRenderStateName;
+
+typedef enum {
+   SVGA3D_VERTEXMATERIAL_NONE     = 0,    /* Use the value in the current material */
+   SVGA3D_VERTEXMATERIAL_DIFFUSE  = 1,    /* Use the value in the diffuse component */
+   SVGA3D_VERTEXMATERIAL_SPECULAR = 2,    /* Use the value in the specular component */
+} SVGA3dVertexMaterial;
+
+typedef enum {
+   SVGA3D_FILLMODE_INVALID = 0,
+   SVGA3D_FILLMODE_POINT   = 1,
+   SVGA3D_FILLMODE_LINE    = 2,
+   SVGA3D_FILLMODE_FILL    = 3,
+   SVGA3D_FILLMODE_MAX
+} SVGA3dFillModeType;
+
+
+typedef
+union {
+   struct {
+      uint16   mode;       /* SVGA3dFillModeType */
+      uint16   face;       /* SVGA3dFace */
+   };
+   uint32 uintValue;
+} SVGA3dFillMode;
+
+typedef enum {
+   SVGA3D_SHADEMODE_INVALID = 0,
+   SVGA3D_SHADEMODE_FLAT    = 1,
+   SVGA3D_SHADEMODE_SMOOTH  = 2,
+   SVGA3D_SHADEMODE_PHONG   = 3,     /* Not supported */
+   SVGA3D_SHADEMODE_MAX
+} SVGA3dShadeMode;
+
+typedef
+union {
+   struct {
+      uint16 repeat;
+      uint16 pattern;
+   };
+   uint32 uintValue;
+} SVGA3dLinePattern;
+
+typedef enum {
+   SVGA3D_BLENDOP_INVALID            = 0,
+   SVGA3D_BLENDOP_ZERO               = 1,
+   SVGA3D_BLENDOP_ONE                = 2,
+   SVGA3D_BLENDOP_SRCCOLOR           = 3,
+   SVGA3D_BLENDOP_INVSRCCOLOR        = 4,
+   SVGA3D_BLENDOP_SRCALPHA           = 5,
+   SVGA3D_BLENDOP_INVSRCALPHA        = 6,
+   SVGA3D_BLENDOP_DESTALPHA          = 7,
+   SVGA3D_BLENDOP_INVDESTALPHA       = 8,
+   SVGA3D_BLENDOP_DESTCOLOR          = 9,
+   SVGA3D_BLENDOP_INVDESTCOLOR       = 10,
+   SVGA3D_BLENDOP_SRCALPHASAT        = 11,
+   SVGA3D_BLENDOP_BLENDFACTOR        = 12,
+   SVGA3D_BLENDOP_INVBLENDFACTOR     = 13,
+   SVGA3D_BLENDOP_MAX
+} SVGA3dBlendOp;
+
+typedef enum {
+   SVGA3D_BLENDEQ_INVALID            = 0,
+   SVGA3D_BLENDEQ_ADD                = 1,
+   SVGA3D_BLENDEQ_SUBTRACT           = 2,
+   SVGA3D_BLENDEQ_REVSUBTRACT        = 3,
+   SVGA3D_BLENDEQ_MINIMUM            = 4,
+   SVGA3D_BLENDEQ_MAXIMUM            = 5,
+   SVGA3D_BLENDEQ_MAX
+} SVGA3dBlendEquation;
+
+typedef enum {
+   SVGA3D_FRONTWINDING_INVALID = 0,
+   SVGA3D_FRONTWINDING_CW      = 1,
+   SVGA3D_FRONTWINDING_CCW     = 2,
+   SVGA3D_FRONTWINDING_MAX
+} SVGA3dFrontWinding;
+
+typedef enum {
+   SVGA3D_FACE_INVALID  = 0,
+   SVGA3D_FACE_NONE     = 1,
+   SVGA3D_FACE_FRONT    = 2,
+   SVGA3D_FACE_BACK     = 3,
+   SVGA3D_FACE_FRONT_BACK = 4,
+   SVGA3D_FACE_MAX
+} SVGA3dFace;
+
+/*
+ * The order and the values should not be changed
+ */
+
+typedef enum {
+   SVGA3D_CMP_INVALID              = 0,
+   SVGA3D_CMP_NEVER                = 1,
+   SVGA3D_CMP_LESS                 = 2,
+   SVGA3D_CMP_EQUAL                = 3,
+   SVGA3D_CMP_LESSEQUAL            = 4,
+   SVGA3D_CMP_GREATER              = 5,
+   SVGA3D_CMP_NOTEQUAL             = 6,
+   SVGA3D_CMP_GREATEREQUAL         = 7,
+   SVGA3D_CMP_ALWAYS               = 8,
+   SVGA3D_CMP_MAX
+} SVGA3dCmpFunc;
+
+/*
+ * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows
+ * the fog factor to be specified in the alpha component of the specular
+ * (a.k.a. secondary) vertex color.
+ */
+typedef enum {
+   SVGA3D_FOGFUNC_INVALID          = 0,
+   SVGA3D_FOGFUNC_EXP              = 1,
+   SVGA3D_FOGFUNC_EXP2             = 2,
+   SVGA3D_FOGFUNC_LINEAR           = 3,
+   SVGA3D_FOGFUNC_PER_VERTEX       = 4
+} SVGA3dFogFunction;
+
+/*
+ * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex
+ * or per-pixel basis.
+ */
+typedef enum {
+   SVGA3D_FOGTYPE_INVALID          = 0,
+   SVGA3D_FOGTYPE_VERTEX           = 1,
+   SVGA3D_FOGTYPE_PIXEL            = 2,
+   SVGA3D_FOGTYPE_MAX              = 3
+} SVGA3dFogType;
+
+/*
+ * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is
+ * computed using the eye Z value of each pixel (or vertex), whereas range-
+ * based fog is computed using the actual distance (range) to the eye.
+ */
+typedef enum {
+   SVGA3D_FOGBASE_INVALID          = 0,
+   SVGA3D_FOGBASE_DEPTHBASED       = 1,
+   SVGA3D_FOGBASE_RANGEBASED       = 2,
+   SVGA3D_FOGBASE_MAX              = 3
+} SVGA3dFogBase;
+
+typedef enum {
+   SVGA3D_STENCILOP_INVALID        = 0,
+   SVGA3D_STENCILOP_KEEP           = 1,
+   SVGA3D_STENCILOP_ZERO           = 2,
+   SVGA3D_STENCILOP_REPLACE        = 3,
+   SVGA3D_STENCILOP_INCRSAT        = 4,
+   SVGA3D_STENCILOP_DECRSAT        = 5,
+   SVGA3D_STENCILOP_INVERT         = 6,
+   SVGA3D_STENCILOP_INCR           = 7,
+   SVGA3D_STENCILOP_DECR           = 8,
+   SVGA3D_STENCILOP_MAX
+} SVGA3dStencilOp;
+
+typedef enum {
+   SVGA3D_CLIPPLANE_0              = (1 << 0),
+   SVGA3D_CLIPPLANE_1              = (1 << 1),
+   SVGA3D_CLIPPLANE_2              = (1 << 2),
+   SVGA3D_CLIPPLANE_3              = (1 << 3),
+   SVGA3D_CLIPPLANE_4              = (1 << 4),
+   SVGA3D_CLIPPLANE_5              = (1 << 5),
+} SVGA3dClipPlanes;
+
+typedef enum {
+   SVGA3D_CLEAR_COLOR              = 0x1,
+   SVGA3D_CLEAR_DEPTH              = 0x2,
+   SVGA3D_CLEAR_STENCIL            = 0x4
+} SVGA3dClearFlag;
+
+typedef enum {
+   SVGA3D_RT_DEPTH                 = 0,
+   SVGA3D_RT_STENCIL               = 1,
+   SVGA3D_RT_COLOR0                = 2,
+   SVGA3D_RT_COLOR1                = 3,
+   SVGA3D_RT_COLOR2                = 4,
+   SVGA3D_RT_COLOR3                = 5,
+   SVGA3D_RT_COLOR4                = 6,
+   SVGA3D_RT_COLOR5                = 7,
+   SVGA3D_RT_COLOR6                = 8,
+   SVGA3D_RT_COLOR7                = 9,
+   SVGA3D_RT_MAX,
+   SVGA3D_RT_INVALID               = ((uint32)-1),
+} SVGA3dRenderTargetType;
+
+#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1)
+
+typedef
+union {
+   struct {
+      uint32  red   : 1;
+      uint32  green : 1;
+      uint32  blue  : 1;
+      uint32  alpha : 1;
+   };
+   uint32 uintValue;
+} SVGA3dColorMask;
+
+typedef enum {
+   SVGA3D_VBLEND_DISABLE            = 0,
+   SVGA3D_VBLEND_1WEIGHT            = 1,
+   SVGA3D_VBLEND_2WEIGHT            = 2,
+   SVGA3D_VBLEND_3WEIGHT            = 3,
+} SVGA3dVertexBlendFlags;
+
+typedef enum {
+   SVGA3D_WRAPCOORD_0   = 1 << 0,
+   SVGA3D_WRAPCOORD_1   = 1 << 1,
+   SVGA3D_WRAPCOORD_2   = 1 << 2,
+   SVGA3D_WRAPCOORD_3   = 1 << 3,
+   SVGA3D_WRAPCOORD_ALL = 0xF,
+} SVGA3dWrapFlags;
+
+/*
+ * SVGA_3D_CMD_TEXTURESTATE Types.  All value types
+ * must fit in a uint32.
+ */
+
+typedef enum {
+   SVGA3D_TS_INVALID                    = 0,
+   SVGA3D_TS_BIND_TEXTURE               = 1,    /* SVGA3dSurfaceId */
+   SVGA3D_TS_COLOROP                    = 2,    /* SVGA3dTextureCombiner */
+   SVGA3D_TS_COLORARG1                  = 3,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_COLORARG2                  = 4,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAOP                    = 5,    /* SVGA3dTextureCombiner */
+   SVGA3D_TS_ALPHAARG1                  = 6,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAARG2                  = 7,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ADDRESSU                   = 8,    /* SVGA3dTextureAddress */
+   SVGA3D_TS_ADDRESSV                   = 9,    /* SVGA3dTextureAddress */
+   SVGA3D_TS_MIPFILTER                  = 10,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_MAGFILTER                  = 11,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_MINFILTER                  = 12,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_BORDERCOLOR                = 13,   /* SVGA3dColor */
+   SVGA3D_TS_TEXCOORDINDEX              = 14,   /* uint32 */
+   SVGA3D_TS_TEXTURETRANSFORMFLAGS      = 15,   /* SVGA3dTexTransformFlags */
+   SVGA3D_TS_TEXCOORDGEN                = 16,   /* SVGA3dTextureCoordGen */
+   SVGA3D_TS_BUMPENVMAT00               = 17,   /* float */
+   SVGA3D_TS_BUMPENVMAT01               = 18,   /* float */
+   SVGA3D_TS_BUMPENVMAT10               = 19,   /* float */
+   SVGA3D_TS_BUMPENVMAT11               = 20,   /* float */
+   SVGA3D_TS_TEXTURE_MIPMAP_LEVEL       = 21,   /* uint32 */
+   SVGA3D_TS_TEXTURE_LOD_BIAS           = 22,   /* float */
+   SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL  = 23,   /* uint32 */
+   SVGA3D_TS_ADDRESSW                   = 24,   /* SVGA3dTextureAddress */
+
+
+   /*
+    * Sampler Gamma Level
+    *
+    * Sampler gamma effects the color of samples taken from the sampler.  A
+    * value of 1.0 will produce linear samples.  If the value is <= 0.0 the
+    * gamma value is ignored and a linear space is used.
+    */
+
+   SVGA3D_TS_GAMMA                      = 25,   /* float */
+   SVGA3D_TS_BUMPENVLSCALE              = 26,   /* float */
+   SVGA3D_TS_BUMPENVLOFFSET             = 27,   /* float */
+   SVGA3D_TS_COLORARG0                  = 28,   /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAARG0                  = 29,   /* SVGA3dTextureArgData */
+   SVGA3D_TS_MAX
+} SVGA3dTextureStateName;
+
+typedef enum {
+   SVGA3D_TC_INVALID                   = 0,
+   SVGA3D_TC_DISABLE                   = 1,
+   SVGA3D_TC_SELECTARG1                = 2,
+   SVGA3D_TC_SELECTARG2                = 3,
+   SVGA3D_TC_MODULATE                  = 4,
+   SVGA3D_TC_ADD                       = 5,
+   SVGA3D_TC_ADDSIGNED                 = 6,
+   SVGA3D_TC_SUBTRACT                  = 7,
+   SVGA3D_TC_BLENDTEXTUREALPHA         = 8,
+   SVGA3D_TC_BLENDDIFFUSEALPHA         = 9,
+   SVGA3D_TC_BLENDCURRENTALPHA         = 10,
+   SVGA3D_TC_BLENDFACTORALPHA          = 11,
+   SVGA3D_TC_MODULATE2X                = 12,
+   SVGA3D_TC_MODULATE4X                = 13,
+   SVGA3D_TC_DSDT                      = 14,
+   SVGA3D_TC_DOTPRODUCT3               = 15,
+   SVGA3D_TC_BLENDTEXTUREALPHAPM       = 16,
+   SVGA3D_TC_ADDSIGNED2X               = 17,
+   SVGA3D_TC_ADDSMOOTH                 = 18,
+   SVGA3D_TC_PREMODULATE               = 19,
+   SVGA3D_TC_MODULATEALPHA_ADDCOLOR    = 20,
+   SVGA3D_TC_MODULATECOLOR_ADDALPHA    = 21,
+   SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
+   SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
+   SVGA3D_TC_BUMPENVMAPLUMINANCE       = 24,
+   SVGA3D_TC_MULTIPLYADD               = 25,
+   SVGA3D_TC_LERP                      = 26,
+   SVGA3D_TC_MAX
+} SVGA3dTextureCombiner;
+
+#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)
+
+typedef enum {
+   SVGA3D_TEX_ADDRESS_INVALID    = 0,
+   SVGA3D_TEX_ADDRESS_WRAP       = 1,
+   SVGA3D_TEX_ADDRESS_MIRROR     = 2,
+   SVGA3D_TEX_ADDRESS_CLAMP      = 3,
+   SVGA3D_TEX_ADDRESS_BORDER     = 4,
+   SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
+   SVGA3D_TEX_ADDRESS_EDGE       = 6,
+   SVGA3D_TEX_ADDRESS_MAX
+} SVGA3dTextureAddress;
+
+/*
+ * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is
+ * disabled, and the rasterizer should use the magnification filter instead.
+ */
+typedef enum {
+   SVGA3D_TEX_FILTER_NONE           = 0,
+   SVGA3D_TEX_FILTER_NEAREST        = 1,
+   SVGA3D_TEX_FILTER_LINEAR         = 2,
+   SVGA3D_TEX_FILTER_ANISOTROPIC    = 3,
+   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, // Deprecated, not implemented
+   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, // Deprecated, not implemented
+   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, // Not currently implemented
+   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, // Not currently implemented
+   SVGA3D_TEX_FILTER_MAX
+} SVGA3dTextureFilter;
+
+typedef enum {
+   SVGA3D_TEX_TRANSFORM_OFF    = 0,
+   SVGA3D_TEX_TRANSFORM_S      = (1 << 0),
+   SVGA3D_TEX_TRANSFORM_T      = (1 << 1),
+   SVGA3D_TEX_TRANSFORM_R      = (1 << 2),
+   SVGA3D_TEX_TRANSFORM_Q      = (1 << 3),
+   SVGA3D_TEX_PROJECTED        = (1 << 15),
+} SVGA3dTexTransformFlags;
+
+typedef enum {
+   SVGA3D_TEXCOORD_GEN_OFF              = 0,
+   SVGA3D_TEXCOORD_GEN_EYE_POSITION     = 1,
+   SVGA3D_TEXCOORD_GEN_EYE_NORMAL       = 2,
+   SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
+   SVGA3D_TEXCOORD_GEN_SPHERE           = 4,
+   SVGA3D_TEXCOORD_GEN_MAX
+} SVGA3dTextureCoordGen;
+
+/*
+ * Texture argument constants for texture combiner
+ */
+typedef enum {
+   SVGA3D_TA_INVALID    = 0,
+   SVGA3D_TA_CONSTANT   = 1,
+   SVGA3D_TA_PREVIOUS   = 2,
+   SVGA3D_TA_DIFFUSE    = 3,
+   SVGA3D_TA_TEXTURE    = 4,
+   SVGA3D_TA_SPECULAR   = 5,
+   SVGA3D_TA_MAX
+} SVGA3dTextureArgData;
+
+#define SVGA3D_TM_MASK_LEN 4
+
+/* Modifiers for texture argument constants defined above. */
+typedef enum {
+   SVGA3D_TM_NONE       = 0,
+   SVGA3D_TM_ALPHA      = (1 << SVGA3D_TM_MASK_LEN),
+   SVGA3D_TM_ONE_MINUS  = (2 << SVGA3D_TM_MASK_LEN),
+} SVGA3dTextureArgModifier;
+
+#define SVGA3D_INVALID_ID         ((uint32)-1)
+#define SVGA3D_MAX_CLIP_PLANES    6
+
+/*
+ * This is the limit to the number of fixed-function texture
+ * transforms and texture coordinates we can support. It does *not*
+ * correspond to the number of texture image units (samplers) we
+ * support!
+ */
+#define SVGA3D_MAX_TEXTURE_COORDS 8
+
+/*
+ * Vertex declarations
+ *
+ * Notes:
+ *
+ * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you
+ * draw with any POSITIONT vertex arrays, the programmable vertex
+ * pipeline will be implicitly disabled. Drawing will take place as if
+ * no vertex shader was bound.
+ */
+
+typedef enum {
+   SVGA3D_DECLUSAGE_POSITION     = 0,
+   SVGA3D_DECLUSAGE_BLENDWEIGHT,       //  1
+   SVGA3D_DECLUSAGE_BLENDINDICES,      //  2
+   SVGA3D_DECLUSAGE_NORMAL,            //  3
+   SVGA3D_DECLUSAGE_PSIZE,             //  4
+   SVGA3D_DECLUSAGE_TEXCOORD,          //  5
+   SVGA3D_DECLUSAGE_TANGENT,           //  6
+   SVGA3D_DECLUSAGE_BINORMAL,          //  7
+   SVGA3D_DECLUSAGE_TESSFACTOR,        //  8
+   SVGA3D_DECLUSAGE_POSITIONT,         //  9
+   SVGA3D_DECLUSAGE_COLOR,             // 10
+   SVGA3D_DECLUSAGE_FOG,               // 11
+   SVGA3D_DECLUSAGE_DEPTH,             // 12
+   SVGA3D_DECLUSAGE_SAMPLE,            // 13
+   SVGA3D_DECLUSAGE_MAX
+} SVGA3dDeclUsage;
+
+typedef enum {
+   SVGA3D_DECLMETHOD_DEFAULT     = 0,
+   SVGA3D_DECLMETHOD_PARTIALU,
+   SVGA3D_DECLMETHOD_PARTIALV,
+   SVGA3D_DECLMETHOD_CROSSUV,          // Normal
+   SVGA3D_DECLMETHOD_UV,
+   SVGA3D_DECLMETHOD_LOOKUP,           // Lookup a displacement map
+   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
+} SVGA3dDeclMethod;
+
+typedef enum {
+   SVGA3D_DECLTYPE_FLOAT1        =  0,
+   SVGA3D_DECLTYPE_FLOAT2        =  1,
+   SVGA3D_DECLTYPE_FLOAT3        =  2,
+   SVGA3D_DECLTYPE_FLOAT4        =  3,
+   SVGA3D_DECLTYPE_D3DCOLOR      =  4,
+   SVGA3D_DECLTYPE_UBYTE4        =  5,
+   SVGA3D_DECLTYPE_SHORT2        =  6,
+   SVGA3D_DECLTYPE_SHORT4        =  7,
+   SVGA3D_DECLTYPE_UBYTE4N       =  8,
+   SVGA3D_DECLTYPE_SHORT2N       =  9,
+   SVGA3D_DECLTYPE_SHORT4N       = 10,
+   SVGA3D_DECLTYPE_USHORT2N      = 11,
+   SVGA3D_DECLTYPE_USHORT4N      = 12,
+   SVGA3D_DECLTYPE_UDEC3         = 13,
+   SVGA3D_DECLTYPE_DEC3N         = 14,
+   SVGA3D_DECLTYPE_FLOAT16_2     = 15,
+   SVGA3D_DECLTYPE_FLOAT16_4     = 16,
+   SVGA3D_DECLTYPE_MAX,
+} SVGA3dDeclType;
+
+/*
+ * This structure is used for the divisor for geometry instancing;
+ * it's a direct translation of the Direct3D equivalent.
+ */
+typedef union {
+   struct {
+      /*
+       * For index data, this number represents the number of instances to draw.
+       * For instance data, this number represents the number of
+       * instances/vertex in this stream
+       */
+      uint32 count : 30;
+
+      /*
+       * This is 1 if this is supposed to be the data that is repeated for
+       * every instance.
+       */
+      uint32 indexedData : 1;
+
+      /*
+       * This is 1 if this is supposed to be the per-instance data.
+       */
+      uint32 instanceData : 1;
+   };
+
+   uint32 value;
+} SVGA3dVertexDivisor;
+
+typedef enum {
+   SVGA3D_PRIMITIVE_INVALID                     = 0,
+   SVGA3D_PRIMITIVE_TRIANGLELIST                = 1,
+   SVGA3D_PRIMITIVE_POINTLIST                   = 2,
+   SVGA3D_PRIMITIVE_LINELIST                    = 3,
+   SVGA3D_PRIMITIVE_LINESTRIP                   = 4,
+   SVGA3D_PRIMITIVE_TRIANGLESTRIP               = 5,
+   SVGA3D_PRIMITIVE_TRIANGLEFAN                 = 6,
+   SVGA3D_PRIMITIVE_MAX
+} SVGA3dPrimitiveType;
+
+typedef enum {
+   SVGA3D_COORDINATE_INVALID                   = 0,
+   SVGA3D_COORDINATE_LEFTHANDED                = 1,
+   SVGA3D_COORDINATE_RIGHTHANDED               = 2,
+   SVGA3D_COORDINATE_MAX
+} SVGA3dCoordinateType;
+
+typedef enum {
+   SVGA3D_TRANSFORM_INVALID                     = 0,
+   SVGA3D_TRANSFORM_WORLD                       = 1,
+   SVGA3D_TRANSFORM_VIEW                        = 2,
+   SVGA3D_TRANSFORM_PROJECTION                  = 3,
+   SVGA3D_TRANSFORM_TEXTURE0                    = 4,
+   SVGA3D_TRANSFORM_TEXTURE1                    = 5,
+   SVGA3D_TRANSFORM_TEXTURE2                    = 6,
+   SVGA3D_TRANSFORM_TEXTURE3                    = 7,
+   SVGA3D_TRANSFORM_TEXTURE4                    = 8,
+   SVGA3D_TRANSFORM_TEXTURE5                    = 9,
+   SVGA3D_TRANSFORM_TEXTURE6                    = 10,
+   SVGA3D_TRANSFORM_TEXTURE7                    = 11,
+   SVGA3D_TRANSFORM_WORLD1                      = 12,
+   SVGA3D_TRANSFORM_WORLD2                      = 13,
+   SVGA3D_TRANSFORM_WORLD3                      = 14,
+   SVGA3D_TRANSFORM_MAX
+} SVGA3dTransformType;
+
+typedef enum {
+   SVGA3D_LIGHTTYPE_INVALID                     = 0,
+   SVGA3D_LIGHTTYPE_POINT                       = 1,
+   SVGA3D_LIGHTTYPE_SPOT1                       = 2, /* 1-cone, in degrees */
+   SVGA3D_LIGHTTYPE_SPOT2                       = 3, /* 2-cone, in radians */
+   SVGA3D_LIGHTTYPE_DIRECTIONAL                 = 4,
+   SVGA3D_LIGHTTYPE_MAX
+} SVGA3dLightType;
+
+typedef enum {
+   SVGA3D_CUBEFACE_POSX                         = 0,
+   SVGA3D_CUBEFACE_NEGX                         = 1,
+   SVGA3D_CUBEFACE_POSY                         = 2,
+   SVGA3D_CUBEFACE_NEGY                         = 3,
+   SVGA3D_CUBEFACE_POSZ                         = 4,
+   SVGA3D_CUBEFACE_NEGZ                         = 5,
+} SVGA3dCubeFace;
+
+typedef enum {
+   SVGA3D_SHADERTYPE_COMPILED_DX8               = 0,
+   SVGA3D_SHADERTYPE_VS                         = 1,
+   SVGA3D_SHADERTYPE_PS                         = 2,
+   SVGA3D_SHADERTYPE_MAX
+} SVGA3dShaderType;
+
+typedef enum {
+   SVGA3D_CONST_TYPE_FLOAT                      = 0,
+   SVGA3D_CONST_TYPE_INT                        = 1,
+   SVGA3D_CONST_TYPE_BOOL                       = 2,
+} SVGA3dShaderConstType;
+
+#define SVGA3D_MAX_SURFACE_FACES                6
+
+typedef enum {
+   SVGA3D_STRETCH_BLT_POINT                     = 0,
+   SVGA3D_STRETCH_BLT_LINEAR                    = 1,
+   SVGA3D_STRETCH_BLT_MAX
+} SVGA3dStretchBltMode;
+
+typedef enum {
+   SVGA3D_QUERYTYPE_OCCLUSION                   = 0,
+   SVGA3D_QUERYTYPE_MAX
+} SVGA3dQueryType;
+
+typedef enum {
+   SVGA3D_QUERYSTATE_PENDING     = 0,      /* Waiting on the host (set by guest) */
+   SVGA3D_QUERYSTATE_SUCCEEDED   = 1,      /* Completed successfully (set by host) */
+   SVGA3D_QUERYSTATE_FAILED      = 2,      /* Completed unsuccessfully (set by host) */
+   SVGA3D_QUERYSTATE_NEW         = 3,      /* Never submitted (For guest use only) */
+} SVGA3dQueryState;
+
+typedef enum {
+   SVGA3D_WRITE_HOST_VRAM        = 1,
+   SVGA3D_READ_HOST_VRAM         = 2,
+} SVGA3dTransferType;
+
+/*
+ * The maximum number vertex arrays we're guaranteed to support in
+ * SVGA_3D_CMD_DRAWPRIMITIVES.
+ */
+#define SVGA3D_MAX_VERTEX_ARRAYS   32
+
+/*
+ * Identifiers for commands in the command FIFO.
+ *
+ * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
+ * the SVGA3D protocol and remain reserved; they should not be used in the
+ * future.
+ *
+ * IDs between 1040 and 1999 (inclusive) are available for use by the
+ * current SVGA3D protocol.
+ *
+ * FIFO clients other than SVGA3D should stay below 1000, or at 2000
+ * and up.
+ */
+
+#define SVGA_3D_CMD_LEGACY_BASE            1000
+#define SVGA_3D_CMD_BASE                   1040
+
+#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
+#define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
+#define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
+#define SVGA_3D_CMD_SURFACE_DMA            SVGA_3D_CMD_BASE + 4
+#define SVGA_3D_CMD_CONTEXT_DEFINE         SVGA_3D_CMD_BASE + 5
+#define SVGA_3D_CMD_CONTEXT_DESTROY        SVGA_3D_CMD_BASE + 6
+#define SVGA_3D_CMD_SETTRANSFORM           SVGA_3D_CMD_BASE + 7
+#define SVGA_3D_CMD_SETZRANGE              SVGA_3D_CMD_BASE + 8
+#define SVGA_3D_CMD_SETRENDERSTATE         SVGA_3D_CMD_BASE + 9
+#define SVGA_3D_CMD_SETRENDERTARGET        SVGA_3D_CMD_BASE + 10
+#define SVGA_3D_CMD_SETTEXTURESTATE        SVGA_3D_CMD_BASE + 11
+#define SVGA_3D_CMD_SETMATERIAL            SVGA_3D_CMD_BASE + 12
+#define SVGA_3D_CMD_SETLIGHTDATA           SVGA_3D_CMD_BASE + 13
+#define SVGA_3D_CMD_SETLIGHTENABLED        SVGA_3D_CMD_BASE + 14
+#define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
+#define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
+#define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
+#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    // Deprecated
+#define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
+#define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
+#define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
+#define SVGA_3D_CMD_SET_SHADER_CONST       SVGA_3D_CMD_BASE + 22
+#define SVGA_3D_CMD_DRAW_PRIMITIVES        SVGA_3D_CMD_BASE + 23
+#define SVGA_3D_CMD_SETSCISSORRECT         SVGA_3D_CMD_BASE + 24
+#define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
+#define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
+#define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
+#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    // Deprecated
+#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
+#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 30
+
+#define SVGA_3D_CMD_FUTURE_MAX             2000
+
+/*
+ * Common substructures used in multiple FIFO commands:
+ */
+
+typedef struct {
+   union {
+      struct {
+         uint16  function;       // SVGA3dFogFunction
+         uint8   type;           // SVGA3dFogType
+         uint8   base;           // SVGA3dFogBase
+      };
+      uint32     uintValue;
+   };
+} SVGA3dFogMode;
+
+/*
+ * Uniquely identify one image (a 1D/2D/3D array) from a surface. This
+ * is a surface ID as well as face/mipmap indices.
+ */
+
+typedef
+struct SVGA3dSurfaceImageId {
+   uint32               sid;
+   uint32               face;
+   uint32               mipmap;
+} SVGA3dSurfaceImageId;
+
+typedef
+struct SVGA3dGuestImage {
+   SVGAGuestPtr         ptr;
+
+   /*
+    * A note on interpretation of pitch: This value of pitch is the
+    * number of bytes between vertically adjacent image
+    * blocks. Normally this is the number of bytes between the first
+    * pixel of two adjacent scanlines. With compressed textures,
+    * however, this may represent the number of bytes between
+    * compression blocks rather than between rows of pixels.
+    *
+    * XXX: Compressed textures currently must be tightly packed in guest memory.
+    *
+    * If the image is 1-dimensional, pitch is ignored.
+    *
+    * If 'pitch' is zero, the SVGA3D device calculates a pitch value
+    * assuming each row of blocks is tightly packed.
+    */
+   uint32 pitch;
+} SVGA3dGuestImage;
+
+
+/*
+ * FIFO command format definitions:
+ */
+
+/*
+ * The data size header following cmdNum for every 3d command
+ */
+typedef
+struct {
+   uint32               id;
+   uint32               size;
+} SVGA3dCmdHeader;
+
+/*
+ * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with
+ * optional mipmaps and cube faces.
+ */
+
+typedef
+struct {
+   uint32               width;
+   uint32               height;
+   uint32               depth;
+} SVGA3dSize;
+
+typedef enum {
+   SVGA3D_SURFACE_CUBEMAP              = (1 << 0),
+   SVGA3D_SURFACE_HINT_STATIC          = (1 << 1),
+   SVGA3D_SURFACE_HINT_DYNAMIC         = (1 << 2),
+   SVGA3D_SURFACE_HINT_INDEXBUFFER     = (1 << 3),
+   SVGA3D_SURFACE_HINT_VERTEXBUFFER    = (1 << 4),
+   SVGA3D_SURFACE_HINT_TEXTURE         = (1 << 5),
+   SVGA3D_SURFACE_HINT_RENDERTARGET    = (1 << 6),
+   SVGA3D_SURFACE_HINT_DEPTHSTENCIL    = (1 << 7),
+   SVGA3D_SURFACE_HINT_WRITEONLY       = (1 << 8),
+} SVGA3dSurfaceFlags;
+
+typedef
+struct {
+   uint32               numMipLevels;
+} SVGA3dSurfaceFace;
+
+typedef
+struct {
+   uint32                      sid;
+   SVGA3dSurfaceFlags          surfaceFlags;
+   SVGA3dSurfaceFormat         format;
+   SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
+   /*
+    * Followed by an SVGA3dSize structure for each mip level in each face.
+    *
+    * A note on surface sizes: Sizes are always specified in pixels,
+    * even if the true surface size is not a multiple of the minimum
+    * block size of the surface's format. For example, a 3x3x1 DXT1
+    * compressed texture would actually be stored as a 4x4x1 image in
+    * memory.
+    */
+} SVGA3dCmdDefineSurface;       /* SVGA_3D_CMD_SURFACE_DEFINE */
+
+typedef
+struct {
+   uint32               sid;
+} SVGA3dCmdDestroySurface;      /* SVGA_3D_CMD_SURFACE_DESTROY */
+
+typedef
+struct {
+   uint32               cid;
+} SVGA3dCmdDefineContext;       /* SVGA_3D_CMD_CONTEXT_DEFINE */
+
+typedef
+struct {
+   uint32               cid;
+} SVGA3dCmdDestroyContext;      /* SVGA_3D_CMD_CONTEXT_DESTROY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dClearFlag      clearFlag;
+   uint32               color;
+   float                depth;
+   uint32               stencil;
+   /* Followed by variable number of SVGA3dRect structures */
+} SVGA3dCmdClear;               /* SVGA_3D_CMD_CLEAR */
+
+typedef
+struct SVGA3dCopyRect {
+   uint32               x;
+   uint32               y;
+   uint32               w;
+   uint32               h;
+   uint32               srcx;
+   uint32               srcy;
+} SVGA3dCopyRect;
+
+typedef
+struct SVGA3dCopyBox {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+   uint32               w;
+   uint32               h;
+   uint32               d;
+   uint32               srcx;
+   uint32               srcy;
+   uint32               srcz;
+} SVGA3dCopyBox;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               w;
+   uint32               h;
+} SVGA3dRect;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+   uint32               w;
+   uint32               h;
+   uint32               d;
+} SVGA3dBox;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+} SVGA3dPoint;
+
+typedef
+struct {
+   SVGA3dLightType      type;
+   SVGA3dBool           inWorldSpace;
+   float                diffuse[4];
+   float                specular[4];
+   float                ambient[4];
+   float                position[4];
+   float                direction[4];
+   float                range;
+   float                falloff;
+   float                attenuation0;
+   float                attenuation1;
+   float                attenuation2;
+   float                theta;
+   float                phi;
+} SVGA3dLightData;
+
+typedef
+struct {
+   uint32               sid;
+   /* Followed by variable number of SVGA3dCopyRect structures */
+} SVGA3dCmdPresent;             /* SVGA_3D_CMD_PRESENT */
+
+typedef
+struct {
+   SVGA3dRenderStateName   state;
+   union {
+      uint32               uintValue;
+      float                floatValue;
+   };
+} SVGA3dRenderState;
+
+typedef
+struct {
+   uint32               cid;
+   /* Followed by variable number of SVGA3dRenderState structures */
+} SVGA3dCmdSetRenderState;      /* SVGA_3D_CMD_SETRENDERSTATE */
+
+typedef
+struct {
+   uint32                 cid;
+   SVGA3dRenderTargetType type;
+   SVGA3dSurfaceImageId   target;
+} SVGA3dCmdSetRenderTarget;     /* SVGA_3D_CMD_SETRENDERTARGET */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId  src;
+   SVGA3dSurfaceImageId  dest;
+   /* Followed by variable number of SVGA3dCopyBox structures */
+} SVGA3dCmdSurfaceCopy;               /* SVGA_3D_CMD_SURFACE_COPY */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId  src;
+   SVGA3dSurfaceImageId  dest;
+   SVGA3dBox             boxSrc;
+   SVGA3dBox             boxDest;
+   SVGA3dStretchBltMode  mode;
+} SVGA3dCmdSurfaceStretchBlt;         /* SVGA_3D_CMD_SURFACE_STRETCHBLT */
+
+typedef
+struct {
+   /*
+    * If the discard flag is present in a surface DMA operation, the host may
+    * discard the contents of the current mipmap level and face of the target
+    * surface before applying the surface DMA contents.
+    */
+   uint32 discard : 1;
+
+   /*
+    * If the unsynchronized flag is present, the host may perform this upload
+    * without syncing to pending reads on this surface.
+    */
+   uint32 unsynchronized : 1;
+
+   /*
+    * Guests *MUST* set the reserved bits to 0 before submitting the command
+    * suffix as future flags may occupy these bits.
+    */
+   uint32 reserved : 30;
+} SVGA3dSurfaceDMAFlags;
+
+typedef
+struct {
+   SVGA3dGuestImage      guest;
+   SVGA3dSurfaceImageId  host;
+   SVGA3dTransferType    transfer;
+   /*
+    * Followed by variable number of SVGA3dCopyBox structures. For consistency
+    * in all clipping logic and coordinate translation, we define the
+    * "source" in each copyBox as the guest image and the
+    * "destination" as the host image, regardless of transfer
+    * direction.
+    *
+    * For efficiency, the SVGA3D device is free to copy more data than
+    * specified. For example, it may round copy boxes outwards such
+    * that they lie on particular alignment boundaries.
+    */
+} SVGA3dCmdSurfaceDMA;                /* SVGA_3D_CMD_SURFACE_DMA */
+
+/*
+ * SVGA3dCmdSurfaceDMASuffix --
+ *
+ *    This is a command suffix that will appear after a SurfaceDMA command in
+ *    the FIFO.  It contains some extra information that hosts may use to
+ *    optimize performance or protect the guest.  This suffix exists to preserve
+ *    backwards compatibility while also allowing for new functionality to be
+ *    implemented.
+ */
+
+typedef
+struct {
+   uint32 suffixSize;
+
+   /*
+    * The maximum offset is used to determine the maximum offset from the
+    * guestPtr base address that will be accessed or written to during this
+    * surfaceDMA.  If the suffix is supported, the host will respect this
+    * boundary while performing surface DMAs.
+    *
+    * Defaults to MAX_UINT32
+    */
+   uint32 maximumOffset;
+
+   /*
+    * A set of flags that describes optimizations that the host may perform
+    * while performing this surface DMA operation.  The guest should never rely
+    * on behaviour that is different when these flags are set for correctness.
+    *
+    * Defaults to 0
+    */
+   SVGA3dSurfaceDMAFlags flags;
+} SVGA3dCmdSurfaceDMASuffix;
+
+/*
+ * SVGA_3D_CMD_DRAW_PRIMITIVES --
+ *
+ *   This command is the SVGA3D device's generic drawing entry point.
+ *   It can draw multiple ranges of primitives, optionally using an
+ *   index buffer, using an arbitrary collection of vertex buffers.
+ *
+ *   Each SVGA3dVertexDecl defines a distinct vertex array to bind
+ *   during this draw call. The declarations specify which surface
+ *   the vertex data lives in, what that vertex data is used for,
+ *   and how to interpret it.
+ *
+ *   Each SVGA3dPrimitiveRange defines a collection of primitives
+ *   to render using the same vertex arrays. An index buffer is
+ *   optional.
+ */
+
+typedef
+struct {
+   /*
+    * A range hint is an optional specification for the range of indices
+    * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed
+    * that the entire array will be used.
+    *
+    * These are only hints. The SVGA3D device may use them for
+    * performance optimization if possible, but it's also allowed to
+    * ignore these values.
+    */
+   uint32               first;
+   uint32               last;
+} SVGA3dArrayRangeHint;
+
+typedef
+struct {
+   /*
+    * Define the origin and shape of a vertex or index array. Both
+    * 'offset' and 'stride' are in bytes. The provided surface will be
+    * reinterpreted as a flat array of bytes in the same format used
+    * by surface DMA operations. To avoid unnecessary conversions, the
+    * surface should be created with the SVGA3D_BUFFER format.
+    *
+    * Index 0 in the array starts 'offset' bytes into the surface.
+    * Index 1 begins at byte 'offset + stride', etc. Array indices may
+    * not be negative.
+    */
+   uint32               surfaceId;
+   uint32               offset;
+   uint32               stride;
+} SVGA3dArray;
+
+typedef
+struct {
+   /*
+    * Describe a vertex array's data type, and define how it is to be
+    * used by the fixed function pipeline or the vertex shader. It
+    * isn't useful to have two VertexDecls with the same
+    * VertexArrayIdentity in one draw call.
+    */
+   SVGA3dDeclType       type;
+   SVGA3dDeclMethod     method;
+   SVGA3dDeclUsage      usage;
+   uint32               usageIndex;
+} SVGA3dVertexArrayIdentity;
+
+typedef
+struct {
+   SVGA3dVertexArrayIdentity  identity;
+   SVGA3dArray                array;
+   SVGA3dArrayRangeHint       rangeHint;
+} SVGA3dVertexDecl;
+
+typedef
+struct {
+   /*
+    * Define a group of primitives to render, from sequential indices.
+    *
+    * The value of 'primitiveType' and 'primitiveCount' imply the
+    * total number of vertices that will be rendered.
+    */
+   SVGA3dPrimitiveType  primType;
+   uint32               primitiveCount;
+
+   /*
+    * Optional index buffer. If indexArray.surfaceId is
+    * SVGA3D_INVALID_ID, we render without an index buffer. Rendering
+    * without an index buffer is identical to rendering with an index
+    * buffer containing the sequence [0, 1, 2, 3, ...].
+    *
+    * If an index buffer is in use, indexWidth specifies the width in
+    * bytes of each index value. It must be less than or equal to
+    * indexArray.stride.
+    *
+    * (Currently, the SVGA3D device requires index buffers to be tightly
+    * packed. In other words, indexWidth == indexArray.stride)
+    */
+   SVGA3dArray          indexArray;
+   uint32               indexWidth;
+
+   /*
+    * Optional index bias. This number is added to all indices from
+    * indexArray before they are used as vertex array indices. This
+    * can be used in multiple ways:
+    *
+    *  - When not using an indexArray, this bias can be used to
+    *    specify where in the vertex arrays to begin rendering.
+    *
+    *  - A positive number here is equivalent to increasing the
+    *    offset in each vertex array.
+    *
+    *  - A negative number can be used to render using a small
+    *    vertex array and an index buffer that contains large
+    *    values. This may be used by some applications that
+    *    crop a vertex buffer without modifying their index
+    *    buffer.
+    *
+    * Note that rendering with a negative bias value may be slower and
+    * use more memory than rendering with a positive or zero bias.
+    */
+   int32                indexBias;
+} SVGA3dPrimitiveRange;
+
+typedef
+struct {
+   uint32               cid;
+   uint32               numVertexDecls;
+   uint32               numRanges;
+
+   /*
+    * There are two variable size arrays after the
+    * SVGA3dCmdDrawPrimitives structure. In order,
+    * they are:
+    *
+    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls'
+    * 2. SVGA3dPrimitiveRange, quantity 'numRanges'
+    * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
+    *    the frequency divisor for this the corresponding vertex decl)
+    */
+} SVGA3dCmdDrawPrimitives;      /* SVGA_3D_CMD_DRAWPRIMITIVES */
+
+typedef
+struct {
+   uint32                   stage;
+   SVGA3dTextureStateName   name;
+   union {
+      uint32                value;
+      float                 floatValue;
+   };
+} SVGA3dTextureState;
+
+typedef
+struct {
+   uint32               cid;
+   /* Followed by variable number of SVGA3dTextureState structures */
+} SVGA3dCmdSetTextureState;      /* SVGA_3D_CMD_SETTEXTURESTATE */
+
+typedef
+struct {
+   uint32                   cid;
+   SVGA3dTransformType      type;
+   float                    matrix[16];
+} SVGA3dCmdSetTransform;          /* SVGA_3D_CMD_SETTRANSFORM */
+
+typedef
+struct {
+   float                min;
+   float                max;
+} SVGA3dZRange;
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dZRange         zRange;
+} SVGA3dCmdSetZRange;             /* SVGA_3D_CMD_SETZRANGE */
+
+typedef
+struct {
+   float                diffuse[4];
+   float                ambient[4];
+   float                specular[4];
+   float                emissive[4];
+   float                shininess;
+} SVGA3dMaterial;
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dFace           face;
+   SVGA3dMaterial       material;
+} SVGA3dCmdSetMaterial;           /* SVGA_3D_CMD_SETMATERIAL */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   SVGA3dLightData      data;
+} SVGA3dCmdSetLightData;           /* SVGA_3D_CMD_SETLIGHTDATA */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   uint32               enabled;
+} SVGA3dCmdSetLightEnabled;      /* SVGA_3D_CMD_SETLIGHTENABLED */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dRect           rect;
+} SVGA3dCmdSetViewport;           /* SVGA_3D_CMD_SETVIEWPORT */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dRect           rect;
+} SVGA3dCmdSetScissorRect;         /* SVGA_3D_CMD_SETSCISSORRECT */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   float                plane[4];
+} SVGA3dCmdSetClipPlane;           /* SVGA_3D_CMD_SETCLIPPLANE */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               shid;
+   SVGA3dShaderType     type;
+   /* Followed by variable number of DWORDs for shader bycode */
+} SVGA3dCmdDefineShader;           /* SVGA_3D_CMD_SHADER_DEFINE */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               shid;
+   SVGA3dShaderType     type;
+} SVGA3dCmdDestroyShader;         /* SVGA_3D_CMD_SHADER_DESTROY */
+
+typedef
+struct {
+   uint32                  cid;
+   uint32                  reg;     /* register number */
+   SVGA3dShaderType        type;
+   SVGA3dShaderConstType   ctype;
+   uint32                  values[4];
+} SVGA3dCmdSetShaderConst;        /* SVGA_3D_CMD_SET_SHADER_CONST */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dShaderType     type;
+   uint32               shid;
+} SVGA3dCmdSetShader;             /* SVGA_3D_CMD_SET_SHADER */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+} SVGA3dCmdBeginQuery;           /* SVGA_3D_CMD_BEGIN_QUERY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAGuestPtr         guestResult;  /* Points to an SVGA3dQueryResult structure */
+} SVGA3dCmdEndQuery;                  /* SVGA_3D_CMD_END_QUERY */
+
+typedef
+struct {
+   uint32               cid;          /* Same parameters passed to END_QUERY */
+   SVGA3dQueryType      type;
+   SVGAGuestPtr         guestResult;
+} SVGA3dCmdWaitForQuery;              /* SVGA_3D_CMD_WAIT_FOR_QUERY */
+
+typedef
+struct {
+   uint32               totalSize;    /* Set by guest before query is ended. */
+   SVGA3dQueryState     state;        /* Set by host or guest. See SVGA3dQueryState. */
+   union {                            /* Set by host on exit from PENDING state */
+      uint32            result32;
+   };
+} SVGA3dQueryResult;
+
+/*
+ * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN --
+ *
+ *    This is a blit from an SVGA3D surface to a Screen Object. Just
+ *    like GMR-to-screen blits, this blit may be directed at a
+ *    specific screen or to the virtual coordinate space.
+ *
+ *    The blit copies from a rectangular region of an SVGA3D surface
+ *    image to a rectangular region of a screen or screens.
+ *
+ *    This command takes an optional variable-length list of clipping
+ *    rectangles after the body of the command. If no rectangles are
+ *    specified, there is no clipping region. The entire destRect is
+ *    drawn to. If one or more rectangles are included, they describe
+ *    a clipping region. The clip rectangle coordinates are measured
+ *    relative to the top-left corner of destRect.
+ *
+ *    This clipping region serves multiple purposes:
+ *
+ *      - It can be used to perform an irregularly shaped blit more
+ *        efficiently than by issuing many separate blit commands.
+ *
+ *      - It is equivalent to allowing blits with non-integer
+ *        source coordinates. You could blit just one half-pixel
+ *        of a source, for example, by specifying a larger
+ *        destination rectangle than you need, then removing
+ *        part of it using a clip rectangle.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *
+ * Limitations:
+ *
+ *    - Currently, no backend supports blits from a mipmap or face
+ *      other than the first one.
+ */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId srcImage;
+   SVGASignedRect       srcRect;
+   uint32               destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */
+   SVGASignedRect       destRect;     /* Supports scaling if src/rest different size */
+   /* Clipping: zero or more SVGASignedRects follow */
+} SVGA3dCmdBlitSurfaceToScreen;         /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
+
+
+/*
+ * Capability query index.
+ *
+ * Notes:
+ *
+ *   1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of
+ *      fixed-function texture units available. Each of these units
+ *      work in both FFP and Shader modes, and they support texture
+ *      transforms and texture coordinates. The host may have additional
+ *      texture image units that are only usable with shaders.
+ *
+ *   2. The BUFFER_FORMAT capabilities are deprecated, and they always
+ *      return TRUE. Even on physical hardware that does not support
+ *      these formats natively, the SVGA3D device will provide an emulation
+ *      which should be invisible to the guest OS.
+ *
+ *      In general, the SVGA3D device should support any operation on
+ *      any surface format, it just may perform some of these
+ *      operations in software depending on the capabilities of the
+ *      available physical hardware.
+ *
+ *      XXX: In the future, we will add capabilities that describe in
+ *      detail what formats are supported in hardware for what kinds
+ *      of operations.
+ */
+
+typedef enum {
+   SVGA3D_DEVCAP_3D                                = 0,
+   SVGA3D_DEVCAP_MAX_LIGHTS                        = 1,
+   SVGA3D_DEVCAP_MAX_TEXTURES                      = 2,  /* See note (1) */
+   SVGA3D_DEVCAP_MAX_CLIP_PLANES                   = 3,
+   SVGA3D_DEVCAP_VERTEX_SHADER_VERSION             = 4,
+   SVGA3D_DEVCAP_VERTEX_SHADER                     = 5,
+   SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION           = 6,
+   SVGA3D_DEVCAP_FRAGMENT_SHADER                   = 7,
+   SVGA3D_DEVCAP_MAX_RENDER_TARGETS                = 8,
+   SVGA3D_DEVCAP_S23E8_TEXTURES                    = 9,
+   SVGA3D_DEVCAP_S10E5_TEXTURES                    = 10,
+   SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND             = 11,
+   SVGA3D_DEVCAP_D16_BUFFER_FORMAT                 = 12, /* See note (2) */
+   SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT               = 13, /* See note (2) */
+   SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT               = 14, /* See note (2) */
+   SVGA3D_DEVCAP_QUERY_TYPES                       = 15,
+   SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING         = 16,
+   SVGA3D_DEVCAP_MAX_POINT_SIZE                    = 17,
+   SVGA3D_DEVCAP_MAX_SHADER_TEXTURES               = 18,
+   SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH                 = 19,
+   SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT                = 20,
+   SVGA3D_DEVCAP_MAX_VOLUME_EXTENT                 = 21,
+   SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT                = 22,
+   SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO          = 23,
+   SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY            = 24,
+   SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT               = 25,
+   SVGA3D_DEVCAP_MAX_VERTEX_INDEX                  = 26,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS    = 27,
+   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS  = 28,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS           = 29,
+   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS         = 30,
+   SVGA3D_DEVCAP_TEXTURE_OPS                       = 31,
+   SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8               = 32,
+   SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8               = 33,
+   SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10            = 34,
+   SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5               = 35,
+   SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5               = 36,
+   SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4               = 37,
+   SVGA3D_DEVCAP_SURFACEFMT_R5G6B5                 = 38,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16            = 39,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8      = 40,
+   SVGA3D_DEVCAP_SURFACEFMT_ALPHA8                 = 41,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8             = 42,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D16                  = 43,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8                = 44,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8                = 45,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT1                   = 46,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT2                   = 47,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT3                   = 48,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT4                   = 49,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT5                   = 50,
+   SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8           = 51,
+   SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10            = 52,
+   SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8               = 53,
+   SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8               = 54,
+   SVGA3D_DEVCAP_SURFACEFMT_CxV8U8                 = 55,
+   SVGA3D_DEVCAP_SURFACEFMT_R_S10E5                = 56,
+   SVGA3D_DEVCAP_SURFACEFMT_R_S23E8                = 57,
+   SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5               = 58,
+   SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8               = 59,
+   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5             = 60,
+   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8             = 61,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES        = 63,
+
+   /*
+    * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color
+    * render targets.  This does no include the depth or stencil targets.
+    */
+   SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS   = 64,
+
+   SVGA3D_DEVCAP_SURFACEFMT_V16U16                 = 65,
+   SVGA3D_DEVCAP_SURFACEFMT_G16R16                 = 66,
+   SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16           = 67,
+   SVGA3D_DEVCAP_SURFACEFMT_UYVY                   = 68,
+   SVGA3D_DEVCAP_SURFACEFMT_YUY2                   = 69,
+
+   /*
+    * Don't add new caps into the previous section; the values in this
+    * enumeration must not change. You can put new values right before
+    * SVGA3D_DEVCAP_MAX.
+    */
+   SVGA3D_DEVCAP_MAX                                  /* This must be the last index. */
+} SVGA3dDevCapIndex;
+
+typedef union {
+   Bool   b;
+   uint32 u;
+   int32  i;
+   float  f;
+} SVGA3dDevCapResult;
+
+#endif /* _SVGA3D_REG_H_ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i2c/ch7006_mode.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i2c/ch7006_mode.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "ch7006_priv.h"
+
+char *ch7006_tv_norm_names[] = {
+	[TV_NORM_PAL] = "PAL",
+	[TV_NORM_PAL_M] = "PAL-M",
+	[TV_NORM_PAL_N] = "PAL-N",
+	[TV_NORM_PAL_NC] = "PAL-Nc",
+	[TV_NORM_PAL_60] = "PAL-60",
+	[TV_NORM_NTSC_M] = "NTSC-M",
+	[TV_NORM_NTSC_J] = "NTSC-J",
+};
+
+#define NTSC_LIKE_TIMINGS .vrefresh = 60 * fixed1/1.001,		\
+		.vdisplay = 480,					\
+		.vtotal = 525,						\
+		.hvirtual = 660
+
+#define PAL_LIKE_TIMINGS .vrefresh = 50 * fixed1,		\
+		.vdisplay = 576,				\
+		.vtotal = 625,					\
+		.hvirtual = 810
+
+struct ch7006_tv_norm_info ch7006_tv_norms[] = {
+	[TV_NORM_NTSC_M] = {
+		NTSC_LIKE_TIMINGS,
+		.black_level = 0.339 * fixed1,
+		.subc_freq = 3579545 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC),
+		.voffset = 0,
+	},
+	[TV_NORM_NTSC_J] = {
+		NTSC_LIKE_TIMINGS,
+		.black_level = 0.286 * fixed1,
+		.subc_freq = 3579545 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, NTSC_J),
+		.voffset = 0,
+	},
+	[TV_NORM_PAL] = {
+		PAL_LIKE_TIMINGS,
+		.black_level = 0.3 * fixed1,
+		.subc_freq = 4433618.75 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL),
+		.voffset = 0,
+	},
+	[TV_NORM_PAL_M] = {
+		NTSC_LIKE_TIMINGS,
+		.black_level = 0.339 * fixed1,
+		.subc_freq = 3575611.433 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M),
+		.voffset = 16,
+	},
+
+	/* The following modes seem to work right but they're
+	 * undocumented */
+
+	[TV_NORM_PAL_N] = {
+		PAL_LIKE_TIMINGS,
+		.black_level = 0.339 * fixed1,
+		.subc_freq = 4433618.75 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL),
+		.voffset = 0,
+	},
+	[TV_NORM_PAL_NC] = {
+		PAL_LIKE_TIMINGS,
+		.black_level = 0.3 * fixed1,
+		.subc_freq = 3582056.25 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL),
+		.voffset = 0,
+	},
+	[TV_NORM_PAL_60] = {
+		NTSC_LIKE_TIMINGS,
+		.black_level = 0.3 * fixed1,
+		.subc_freq = 4433618.75 * fixed1,
+		.dispmode = bitfs(CH7006_DISPMODE_OUTPUT_STD, PAL_M),
+		.voffset = 16,
+	},
+};
+
+#define __MODE(f, hd, vd, ht, vt, hsynp, vsynp,				\
+	       subc, scale, scale_mask, norm_mask, e_hd, e_vd) {	\
+		.mode = {						\
+			.name = #hd "x" #vd,				\
+			.status = 0,					\
+			.type = DRM_MODE_TYPE_DRIVER,			\
+			.clock = f,					\
+			.hdisplay = hd,					\
+			.hsync_start = e_hd + 16,			\
+			.hsync_end = e_hd + 80,				\
+			.htotal = ht,					\
+			.hskew = 0,					\
+			.vdisplay = vd,					\
+			.vsync_start = vd + 10,				\
+			.vsync_end = vd + 26,				\
+			.vtotal = vt,					\
+			.vscan = 0,					\
+			.flags = DRM_MODE_FLAG_##hsynp##HSYNC |		\
+				DRM_MODE_FLAG_##vsynp##VSYNC,		\
+			.vrefresh = 0,					\
+		},							\
+		.enc_hdisp = e_hd,					\
+		.enc_vdisp = e_vd,					\
+		.subc_coeff = subc * fixed1,				\
+		.dispmode = bitfs(CH7006_DISPMODE_SCALING_RATIO, scale) | \
+			    bitfs(CH7006_DISPMODE_INPUT_RES, e_hd##x##e_vd), \
+		.valid_scales = scale_mask,				\
+		.valid_norms = norm_mask				\
+	 }
+
+#define MODE(f, hd, vd, ht, vt, hsynp, vsynp,				\
+	     subc, scale, scale_mask, norm_mask)			\
+	__MODE(f, hd, vd, ht, vt, hsynp, vsynp, subc, scale,		\
+	       scale_mask, norm_mask, hd, vd)
+
+#define NTSC_LIKE (1 << TV_NORM_NTSC_M | 1 << TV_NORM_NTSC_J |		\
+		   1 << TV_NORM_PAL_M | 1 << TV_NORM_PAL_60)
+
+#define PAL_LIKE (1 << TV_NORM_PAL | 1 << TV_NORM_PAL_N | 1 << TV_NORM_PAL_NC)
+
+struct ch7006_mode ch7006_modes[] = {
+	MODE(21000, 512, 384, 840, 500, N, N, 181.797557582, 5_4, 0x6, PAL_LIKE),
+	MODE(26250, 512, 384, 840, 625, N, N, 145.438046066, 1_1, 0x1, PAL_LIKE),
+	MODE(20140, 512, 384, 800, 420, N, N, 213.257083791, 5_4, 0x4, NTSC_LIKE),
+	MODE(24671, 512, 384, 784, 525, N, N, 174.0874153, 1_1, 0x3, NTSC_LIKE),
+	MODE(28125, 720, 400, 1125, 500, N, N, 135.742176298, 5_4, 0x6, PAL_LIKE),
+	MODE(34875, 720, 400, 1116, 625, N, N, 109.469496898, 1_1, 0x1, PAL_LIKE),
+	MODE(23790, 720, 400, 945, 420, N, N, 160.475642016, 5_4, 0x4, NTSC_LIKE),
+	MODE(29455, 720, 400, 936, 525, N, N, 129.614941843, 1_1, 0x3, NTSC_LIKE),
+	MODE(25000, 640, 400, 1000, 500, N, N, 152.709948279, 5_4, 0x6, PAL_LIKE),
+	MODE(31500, 640, 400, 1008, 625, N, N, 121.198371646, 1_1, 0x1, PAL_LIKE),
+	MODE(21147, 640, 400, 840, 420, N, N, 180.535097338, 5_4, 0x4, NTSC_LIKE),
+	MODE(26434, 640, 400, 840, 525, N, N, 144.42807787, 1_1, 0x2, NTSC_LIKE),
+	MODE(30210, 640, 400, 840, 600, N, N, 126.374568276, 7_8, 0x1, NTSC_LIKE),
+	MODE(21000, 640, 480, 840, 500, N, N, 181.797557582, 5_4, 0x4, PAL_LIKE),
+	MODE(26250, 640, 480, 840, 625, N, N, 145.438046066, 1_1, 0x2, PAL_LIKE),
+	MODE(31500, 640, 480, 840, 750, N, N, 121.198371646, 5_6, 0x1, PAL_LIKE),
+	MODE(24671, 640, 480, 784, 525, N, N, 174.0874153, 1_1, 0x4, NTSC_LIKE),
+	MODE(28196, 640, 480, 784, 600, N, N, 152.326488422, 7_8, 0x2, NTSC_LIKE),
+	MODE(30210, 640, 480, 800, 630, N, N, 142.171389101, 5_6, 0x1, NTSC_LIKE),
+	__MODE(29500, 720, 576, 944, 625, P, P, 145.592111636, 1_1, 0x7, PAL_LIKE, 800, 600),
+	MODE(36000, 800, 600, 960, 750, P, P, 119.304647022, 5_6, 0x6, PAL_LIKE),
+	MODE(39000, 800, 600, 936, 836, P, P, 110.127366499, 3_4, 0x1, PAL_LIKE),
+	MODE(39273, 800, 600, 1040, 630, P, P, 145.816809399, 5_6, 0x4, NTSC_LIKE),
+	MODE(43636, 800, 600, 1040, 700, P, P, 131.235128487, 3_4, 0x2, NTSC_LIKE),
+	MODE(47832, 800, 600, 1064, 750, P, P, 119.723275165, 7_10, 0x1, NTSC_LIKE),
+	{}
+};
+
+struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
+				       struct drm_display_mode *drm_mode)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_mode *mode;
+
+	for (mode = ch7006_modes; mode->mode.clock; mode++) {
+
+		if (~mode->valid_norms & 1<<priv->norm)
+			continue;
+
+		if (mode->mode.hdisplay != drm_mode->hdisplay ||
+		    mode->mode.vdisplay != drm_mode->vdisplay ||
+		    mode->mode.vtotal != drm_mode->vtotal ||
+		    mode->mode.htotal != drm_mode->htotal ||
+		    mode->mode.clock != drm_mode->clock)
+			continue;
+
+		return mode;
+	}
+
+	return NULL;
+}
+
+/* Some common HW state calculation code */
+
+void ch7006_setup_levels(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	uint8_t *regs = priv->state.regs;
+	struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+	int gain;
+	int black_level;
+
+	/* Set DAC_GAIN if the voltage drop between white and black is
+	 * high enough. */
+	if (norm->black_level < 339*fixed1/1000) {
+		gain = 76;
+
+		regs[CH7006_INPUT_FORMAT] |= CH7006_INPUT_FORMAT_DAC_GAIN;
+	} else {
+		gain = 71;
+
+		regs[CH7006_INPUT_FORMAT] &= ~CH7006_INPUT_FORMAT_DAC_GAIN;
+	}
+
+	black_level = round_fixed(norm->black_level*26625)/gain;
+
+	/* Correct it with the specified brightness. */
+	black_level = interpolate(90, black_level, 208, priv->brightness);
+
+	regs[CH7006_BLACK_LEVEL] = bitf(CH7006_BLACK_LEVEL_0, black_level);
+
+	ch7006_dbg(client, "black level: %d\n", black_level);
+}
+
+void ch7006_setup_subcarrier(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_state *state = &priv->state;
+	struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+	struct ch7006_mode *mode = priv->mode;
+	uint32_t subc_inc;
+
+	subc_inc = round_fixed((mode->subc_coeff >> 8)
+			       * (norm->subc_freq >> 24));
+
+	setbitf(state, CH7006_SUBC_INC0, 28, subc_inc);
+	setbitf(state, CH7006_SUBC_INC1, 24, subc_inc);
+	setbitf(state, CH7006_SUBC_INC2, 20, subc_inc);
+	setbitf(state, CH7006_SUBC_INC3, 16, subc_inc);
+	setbitf(state, CH7006_SUBC_INC4, 12, subc_inc);
+	setbitf(state, CH7006_SUBC_INC5, 8, subc_inc);
+	setbitf(state, CH7006_SUBC_INC6, 4, subc_inc);
+	setbitf(state, CH7006_SUBC_INC7, 0, subc_inc);
+
+	ch7006_dbg(client, "subcarrier inc: %u\n", subc_inc);
+}
+
+void ch7006_setup_pll(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	uint8_t *regs = priv->state.regs;
+	struct ch7006_mode *mode = priv->mode;
+	int n, best_n = 0;
+	int m, best_m = 0;
+	int freq, best_freq = 0;
+
+	for (n = 0; n < CH7006_MAXN; n++) {
+		for (m = 0; m < CH7006_MAXM; m++) {
+			freq = CH7006_FREQ0*(n+2)/(m+2);
+
+			if (abs(freq - mode->mode.clock) <
+			    abs(best_freq - mode->mode.clock)) {
+				best_freq = freq;
+				best_n = n;
+				best_m = m;
+			}
+		}
+	}
+
+	regs[CH7006_PLLOV] = bitf(CH7006_PLLOV_N_8, best_n) |
+		bitf(CH7006_PLLOV_M_8, best_m);
+
+	regs[CH7006_PLLM] = bitf(CH7006_PLLM_0, best_m);
+	regs[CH7006_PLLN] = bitf(CH7006_PLLN_0, best_n);
+
+	if (best_n < 108)
+		regs[CH7006_PLL_CONTROL] |= CH7006_PLL_CONTROL_CAPACITOR;
+	else
+		regs[CH7006_PLL_CONTROL] &= ~CH7006_PLL_CONTROL_CAPACITOR;
+
+	ch7006_dbg(client, "n=%d m=%d f=%d c=%d\n",
+		   best_n, best_m, best_freq, best_n < 108);
+}
+
+void ch7006_setup_power_state(struct drm_encoder *encoder)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	uint8_t *power = &priv->state.regs[CH7006_POWER];
+	int subconnector;
+
+	subconnector = priv->select_subconnector ? priv->select_subconnector :
+							priv->subconnector;
+
+	*power = CH7006_POWER_RESET;
+
+	if (priv->last_dpms == DRM_MODE_DPMS_ON) {
+		switch (subconnector) {
+		case DRM_MODE_SUBCONNECTOR_SVIDEO:
+			*power |= bitfs(CH7006_POWER_LEVEL, CVBS_OFF);
+			break;
+		case DRM_MODE_SUBCONNECTOR_Composite:
+			*power |= bitfs(CH7006_POWER_LEVEL, SVIDEO_OFF);
+			break;
+		case DRM_MODE_SUBCONNECTOR_SCART:
+			*power |= bitfs(CH7006_POWER_LEVEL, NORMAL) |
+				CH7006_POWER_SCART;
+			break;
+		}
+
+	} else {
+		*power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
+	}
+}
+
+void ch7006_setup_properties(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_state *state = &priv->state;
+	struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+	struct ch7006_mode *ch_mode = priv->mode;
+	struct drm_display_mode *mode = &ch_mode->mode;
+	uint8_t *regs = state->regs;
+	int flicker, contrast, hpos, vpos;
+	uint64_t scale, aspect;
+
+	flicker = interpolate(0, 2, 3, priv->flicker);
+	regs[CH7006_FFILTER] = bitf(CH7006_FFILTER_TEXT, flicker) |
+		bitf(CH7006_FFILTER_LUMA, flicker) |
+		bitf(CH7006_FFILTER_CHROMA, 1);
+
+	contrast = interpolate(0, 5, 7, priv->contrast);
+	regs[CH7006_CONTRAST] = bitf(CH7006_CONTRAST_0, contrast);
+
+	scale = norm->vtotal*fixed1;
+	do_div(scale, mode->vtotal);
+
+	aspect = ch_mode->enc_hdisp*fixed1;
+	do_div(aspect, ch_mode->enc_vdisp);
+
+	hpos = round_fixed((norm->hvirtual * aspect - mode->hdisplay * scale)
+			   * priv->hmargin * mode->vtotal) / norm->vtotal / 100 / 4;
+
+	setbitf(state, CH7006_POV, HPOS_8, hpos);
+	setbitf(state, CH7006_HPOS, 0, hpos);
+
+	vpos = max(0, norm->vdisplay - round_fixed(mode->vdisplay*scale)
+		   + norm->voffset) * priv->vmargin / 100 / 2;
+
+	setbitf(state, CH7006_POV, VPOS_8, vpos);
+	setbitf(state, CH7006_VPOS, 0, vpos);
+
+	ch7006_dbg(client, "hpos: %d, vpos: %d\n", hpos, vpos);
+}
+
+/* HW access functions */
+
+void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val)
+{
+	uint8_t buf[] = {addr, val};
+	int ret;
+
+	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	if (ret < 0)
+		ch7006_err(client, "Error %d writing to subaddress 0x%x\n",
+			   ret, addr);
+}
+
+uint8_t ch7006_read(struct i2c_client *client, uint8_t addr)
+{
+	uint8_t val;
+	int ret;
+
+	ret = i2c_master_send(client, &addr, sizeof(addr));
+	if (ret < 0)
+		goto fail;
+
+	ret = i2c_master_recv(client, &val, sizeof(val));
+	if (ret < 0)
+		goto fail;
+
+	return val;
+
+fail:
+	ch7006_err(client, "Error %d reading from subaddress 0x%x\n",
+		   ret, addr);
+	return 0;
+}
+
+void ch7006_state_load(struct i2c_client *client,
+		       struct ch7006_state *state)
+{
+	ch7006_load_reg(client, state, CH7006_POWER);
+
+	ch7006_load_reg(client, state, CH7006_DISPMODE);
+	ch7006_load_reg(client, state, CH7006_FFILTER);
+	ch7006_load_reg(client, state, CH7006_BWIDTH);
+	ch7006_load_reg(client, state, CH7006_INPUT_FORMAT);
+	ch7006_load_reg(client, state, CH7006_CLKMODE);
+	ch7006_load_reg(client, state, CH7006_START_ACTIVE);
+	ch7006_load_reg(client, state, CH7006_POV);
+	ch7006_load_reg(client, state, CH7006_BLACK_LEVEL);
+	ch7006_load_reg(client, state, CH7006_HPOS);
+	ch7006_load_reg(client, state, CH7006_VPOS);
+	ch7006_load_reg(client, state, CH7006_INPUT_SYNC);
+	ch7006_load_reg(client, state, CH7006_DETECT);
+	ch7006_load_reg(client, state, CH7006_CONTRAST);
+	ch7006_load_reg(client, state, CH7006_PLLOV);
+	ch7006_load_reg(client, state, CH7006_PLLM);
+	ch7006_load_reg(client, state, CH7006_PLLN);
+	ch7006_load_reg(client, state, CH7006_BCLKOUT);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC0);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC1);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC2);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC3);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC4);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC5);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC6);
+	ch7006_load_reg(client, state, CH7006_SUBC_INC7);
+	ch7006_load_reg(client, state, CH7006_PLL_CONTROL);
+	ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0);
+}
+
+void ch7006_state_save(struct i2c_client *client,
+		       struct ch7006_state *state)
+{
+	ch7006_save_reg(client, state, CH7006_POWER);
+
+	ch7006_save_reg(client, state, CH7006_DISPMODE);
+	ch7006_save_reg(client, state, CH7006_FFILTER);
+	ch7006_save_reg(client, state, CH7006_BWIDTH);
+	ch7006_save_reg(client, state, CH7006_INPUT_FORMAT);
+	ch7006_save_reg(client, state, CH7006_CLKMODE);
+	ch7006_save_reg(client, state, CH7006_START_ACTIVE);
+	ch7006_save_reg(client, state, CH7006_POV);
+	ch7006_save_reg(client, state, CH7006_BLACK_LEVEL);
+	ch7006_save_reg(client, state, CH7006_HPOS);
+	ch7006_save_reg(client, state, CH7006_VPOS);
+	ch7006_save_reg(client, state, CH7006_INPUT_SYNC);
+	ch7006_save_reg(client, state, CH7006_DETECT);
+	ch7006_save_reg(client, state, CH7006_CONTRAST);
+	ch7006_save_reg(client, state, CH7006_PLLOV);
+	ch7006_save_reg(client, state, CH7006_PLLM);
+	ch7006_save_reg(client, state, CH7006_PLLN);
+	ch7006_save_reg(client, state, CH7006_BCLKOUT);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC0);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC1);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC2);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC3);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC4);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC5);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC6);
+	ch7006_save_reg(client, state, CH7006_SUBC_INC7);
+	ch7006_save_reg(client, state, CH7006_PLL_CONTROL);
+	ch7006_save_reg(client, state, CH7006_CALC_SUBC_INC0);
+
+	state->regs[CH7006_FFILTER] = (state->regs[CH7006_FFILTER] & 0xf0) |
+		(state->regs[CH7006_FFILTER] & 0x0c) >> 2 |
+		(state->regs[CH7006_FFILTER] & 0x03) << 2;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i2c/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/i2c/Makefile
@@ -0,0 +1,4 @@
+ccflags-y := -Iinclude/drm
+
+ch7006-y := ch7006_drv.o ch7006_mode.o
+obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i2c/ch7006_priv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/i2c/ch7006_priv.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __DRM_I2C_CH7006_PRIV_H__
+#define __DRM_I2C_CH7006_PRIV_H__
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "drm_encoder_slave.h"
+#include "i2c/ch7006.h"
+
+typedef int64_t fixed;
+#define fixed1 (1LL << 32)
+
+enum ch7006_tv_norm {
+	TV_NORM_PAL,
+	TV_NORM_PAL_M,
+	TV_NORM_PAL_N,
+	TV_NORM_PAL_NC,
+	TV_NORM_PAL_60,
+	TV_NORM_NTSC_M,
+	TV_NORM_NTSC_J,
+	NUM_TV_NORMS
+};
+
+struct ch7006_tv_norm_info {
+	fixed vrefresh;
+	int vdisplay;
+	int vtotal;
+	int hvirtual;
+
+	fixed subc_freq;
+	fixed black_level;
+
+	uint32_t dispmode;
+	int voffset;
+};
+
+struct ch7006_mode {
+	struct drm_display_mode mode;
+
+	int enc_hdisp;
+	int enc_vdisp;
+
+	fixed subc_coeff;
+	uint32_t dispmode;
+
+	uint32_t valid_scales;
+	uint32_t valid_norms;
+};
+
+struct ch7006_state {
+	uint8_t regs[0x26];
+};
+
+struct ch7006_priv {
+	struct ch7006_encoder_params *params;
+	struct ch7006_mode *mode;
+
+	struct ch7006_state state;
+	struct ch7006_state saved_state;
+
+	struct drm_property *scale_property;
+
+	int select_subconnector;
+	int subconnector;
+	int hmargin;
+	int vmargin;
+	enum ch7006_tv_norm norm;
+	int brightness;
+	int contrast;
+	int flicker;
+	int scale;
+
+	int last_dpms;
+};
+
+#define to_ch7006_priv(x) \
+	((struct ch7006_priv *)to_encoder_slave(x)->slave_priv)
+
+extern int ch7006_debug;
+extern char *ch7006_tv_norm;
+extern int ch7006_scale;
+
+extern char *ch7006_tv_norm_names[];
+extern struct ch7006_tv_norm_info ch7006_tv_norms[];
+extern struct ch7006_mode ch7006_modes[];
+
+struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder,
+				       struct drm_display_mode *drm_mode);
+
+void ch7006_setup_levels(struct drm_encoder *encoder);
+void ch7006_setup_subcarrier(struct drm_encoder *encoder);
+void ch7006_setup_pll(struct drm_encoder *encoder);
+void ch7006_setup_power_state(struct drm_encoder *encoder);
+void ch7006_setup_properties(struct drm_encoder *encoder);
+
+void ch7006_write(struct i2c_client *client, uint8_t addr, uint8_t val);
+uint8_t ch7006_read(struct i2c_client *client, uint8_t addr);
+
+void ch7006_state_load(struct i2c_client *client,
+		       struct ch7006_state *state);
+void ch7006_state_save(struct i2c_client *client,
+		       struct ch7006_state *state);
+
+/* Some helper macros */
+
+#define ch7006_dbg(client, format, ...) do {				\
+		if (ch7006_debug)					\
+			dev_printk(KERN_DEBUG, &client->dev,		\
+				   "%s: " format, __func__, ## __VA_ARGS__); \
+	} while (0)
+#define ch7006_info(client, format, ...) \
+				dev_info(&client->dev, format, __VA_ARGS__)
+#define ch7006_err(client, format, ...) \
+				dev_err(&client->dev, format, __VA_ARGS__)
+
+#define __mask(src, bitfield) \
+		(((2 << (1 ? bitfield)) - 1) & ~((1 << (0 ? bitfield)) - 1))
+#define mask(bitfield) __mask(bitfield)
+
+#define __bitf(src, bitfield, x) \
+		(((x) >> (src) << (0 ? bitfield)) &  __mask(src, bitfield))
+#define bitf(bitfield, x) __bitf(bitfield, x)
+#define bitfs(bitfield, s) __bitf(bitfield, bitfield##_##s)
+#define setbitf(state, reg, bitfield, x)				\
+	state->regs[reg] = (state->regs[reg] & ~mask(reg##_##bitfield))	\
+		| bitf(reg##_##bitfield, x)
+
+#define __unbitf(src, bitfield, x) \
+		((x & __mask(src, bitfield)) >> (0 ? bitfield) << (src))
+#define unbitf(bitfield, x) __unbitf(bitfield, x)
+
+static inline int interpolate(int y0, int y1, int y2, int x)
+{
+	return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50;
+}
+
+static inline int32_t round_fixed(fixed x)
+{
+	return (x + fixed1/2) >> 32;
+}
+
+#define ch7006_load_reg(client, state, reg) ch7006_write(client, reg, state->regs[reg])
+#define ch7006_save_reg(client, state, reg) state->regs[reg] = ch7006_read(client, reg)
+
+/* Fixed hardware specs */
+
+#define CH7006_FREQ0				14318
+#define CH7006_MAXN				650
+#define CH7006_MAXM				315
+
+/* Register definitions */
+
+#define CH7006_DISPMODE				0x00
+#define CH7006_DISPMODE_INPUT_RES		0, 7:5
+#define CH7006_DISPMODE_INPUT_RES_512x384	0x0
+#define CH7006_DISPMODE_INPUT_RES_720x400	0x1
+#define CH7006_DISPMODE_INPUT_RES_640x400	0x2
+#define CH7006_DISPMODE_INPUT_RES_640x480	0x3
+#define CH7006_DISPMODE_INPUT_RES_800x600	0x4
+#define CH7006_DISPMODE_INPUT_RES_NATIVE	0x5
+#define CH7006_DISPMODE_OUTPUT_STD		0, 4:3
+#define CH7006_DISPMODE_OUTPUT_STD_PAL		0x0
+#define CH7006_DISPMODE_OUTPUT_STD_NTSC		0x1
+#define CH7006_DISPMODE_OUTPUT_STD_PAL_M	0x2
+#define CH7006_DISPMODE_OUTPUT_STD_NTSC_J	0x3
+#define CH7006_DISPMODE_SCALING_RATIO		0, 2:0
+#define CH7006_DISPMODE_SCALING_RATIO_5_4	0x0
+#define CH7006_DISPMODE_SCALING_RATIO_1_1	0x1
+#define CH7006_DISPMODE_SCALING_RATIO_7_8	0x2
+#define CH7006_DISPMODE_SCALING_RATIO_5_6	0x3
+#define CH7006_DISPMODE_SCALING_RATIO_3_4	0x4
+#define CH7006_DISPMODE_SCALING_RATIO_7_10	0x5
+
+#define CH7006_FFILTER				0x01
+#define CH7006_FFILTER_TEXT			0, 5:4
+#define CH7006_FFILTER_LUMA			0, 3:2
+#define CH7006_FFILTER_CHROMA			0, 1:0
+#define CH7006_FFILTER_CHROMA_NO_DCRAWL		0x3
+
+#define CH7006_BWIDTH				0x03
+#define CH7006_BWIDTH_5L_FFILER			(1 << 7)
+#define CH7006_BWIDTH_CVBS_NO_CHROMA		(1 << 6)
+#define CH7006_BWIDTH_CHROMA			0, 5:4
+#define CH7006_BWIDTH_SVIDEO_YPEAK		(1 << 3)
+#define CH7006_BWIDTH_SVIDEO_LUMA		0, 2:1
+#define CH7006_BWIDTH_CVBS_LUMA			0, 0:0
+
+#define CH7006_INPUT_FORMAT			0x04
+#define CH7006_INPUT_FORMAT_DAC_GAIN		(1 << 6)
+#define CH7006_INPUT_FORMAT_RGB_PASS_THROUGH	(1 << 5)
+#define CH7006_INPUT_FORMAT_FORMAT		0, 3:0
+#define CH7006_INPUT_FORMAT_FORMAT_RGB16	0x0
+#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m16	0x1
+#define CH7006_INPUT_FORMAT_FORMAT_RGB24m16	0x2
+#define CH7006_INPUT_FORMAT_FORMAT_RGB15	0x3
+#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12C	0x4
+#define CH7006_INPUT_FORMAT_FORMAT_RGB24m12I	0x5
+#define CH7006_INPUT_FORMAT_FORMAT_RGB24m8	0x6
+#define CH7006_INPUT_FORMAT_FORMAT_RGB16m8	0x7
+#define CH7006_INPUT_FORMAT_FORMAT_RGB15m8	0x8
+#define CH7006_INPUT_FORMAT_FORMAT_YCrCb24m8	0x9
+
+#define CH7006_CLKMODE				0x06
+#define CH7006_CLKMODE_SUBC_LOCK		(1 << 7)
+#define CH7006_CLKMODE_MASTER			(1 << 6)
+#define CH7006_CLKMODE_POS_EDGE			(1 << 4)
+#define CH7006_CLKMODE_XCM			0, 3:2
+#define CH7006_CLKMODE_PCM			0, 1:0
+
+#define CH7006_START_ACTIVE			0x07
+#define CH7006_START_ACTIVE_0			0, 7:0
+
+#define CH7006_POV				0x08
+#define CH7006_POV_START_ACTIVE_8		8, 2:2
+#define CH7006_POV_HPOS_8			8, 1:1
+#define CH7006_POV_VPOS_8			8, 0:0
+
+#define CH7006_BLACK_LEVEL			0x09
+#define CH7006_BLACK_LEVEL_0			0, 7:0
+
+#define CH7006_HPOS				0x0a
+#define CH7006_HPOS_0				0, 7:0
+
+#define CH7006_VPOS				0x0b
+#define CH7006_VPOS_0				0, 7:0
+
+#define CH7006_INPUT_SYNC			0x0d
+#define CH7006_INPUT_SYNC_EMBEDDED		(1 << 3)
+#define CH7006_INPUT_SYNC_OUTPUT		(1 << 2)
+#define CH7006_INPUT_SYNC_PVSYNC		(1 << 1)
+#define CH7006_INPUT_SYNC_PHSYNC		(1 << 0)
+
+#define CH7006_POWER				0x0e
+#define CH7006_POWER_SCART			(1 << 4)
+#define CH7006_POWER_RESET			(1 << 3)
+#define CH7006_POWER_LEVEL			0, 2:0
+#define CH7006_POWER_LEVEL_CVBS_OFF		0x0
+#define CH7006_POWER_LEVEL_POWER_OFF		0x1
+#define CH7006_POWER_LEVEL_SVIDEO_OFF		0x2
+#define CH7006_POWER_LEVEL_NORMAL		0x3
+#define CH7006_POWER_LEVEL_FULL_POWER_OFF	0x4
+
+#define CH7006_DETECT				0x10
+#define CH7006_DETECT_SVIDEO_Y_TEST		(1 << 3)
+#define CH7006_DETECT_SVIDEO_C_TEST		(1 << 2)
+#define CH7006_DETECT_CVBS_TEST			(1 << 1)
+#define CH7006_DETECT_SENSE			(1 << 0)
+
+#define CH7006_CONTRAST				0x11
+#define CH7006_CONTRAST_0			0, 2:0
+
+#define CH7006_PLLOV	 			0x13
+#define CH7006_PLLOV_N_8	 		8, 2:1
+#define CH7006_PLLOV_M_8	 		8, 0:0
+
+#define CH7006_PLLM	 			0x14
+#define CH7006_PLLM_0	 			0, 7:0
+
+#define CH7006_PLLN	 			0x15
+#define CH7006_PLLN_0	 			0, 7:0
+
+#define CH7006_BCLKOUT	 			0x17
+
+#define CH7006_SUBC_INC0			0x18
+#define CH7006_SUBC_INC0_28			28, 3:0
+
+#define CH7006_SUBC_INC1			0x19
+#define CH7006_SUBC_INC1_24			24, 3:0
+
+#define CH7006_SUBC_INC2			0x1a
+#define CH7006_SUBC_INC2_20			20, 3:0
+
+#define CH7006_SUBC_INC3			0x1b
+#define CH7006_SUBC_INC3_GPIO1_VAL		(1 << 7)
+#define CH7006_SUBC_INC3_GPIO0_VAL		(1 << 6)
+#define CH7006_SUBC_INC3_POUT_3_3V		(1 << 5)
+#define CH7006_SUBC_INC3_POUT_INV		(1 << 4)
+#define CH7006_SUBC_INC3_16			16, 3:0
+
+#define CH7006_SUBC_INC4			0x1c
+#define CH7006_SUBC_INC4_GPIO1_IN		(1 << 7)
+#define CH7006_SUBC_INC4_GPIO0_IN		(1 << 6)
+#define CH7006_SUBC_INC4_DS_INPUT		(1 << 4)
+#define CH7006_SUBC_INC4_12			12, 3:0
+
+#define CH7006_SUBC_INC5			0x1d
+#define CH7006_SUBC_INC5_8			8, 3:0
+
+#define CH7006_SUBC_INC6			0x1e
+#define CH7006_SUBC_INC6_4			4, 3:0
+
+#define CH7006_SUBC_INC7			0x1f
+#define CH7006_SUBC_INC7_0			0, 3:0
+
+#define CH7006_PLL_CONTROL			0x20
+#define CH7006_PLL_CONTROL_CPI			(1 << 5)
+#define CH7006_PLL_CONTROL_CAPACITOR		(1 << 4)
+#define CH7006_PLL_CONTROL_7STAGES		(1 << 3)
+#define CH7006_PLL_CONTROL_DIGITAL_5V		(1 << 2)
+#define CH7006_PLL_CONTROL_ANALOG_5V		(1 << 1)
+#define CH7006_PLL_CONTROL_MEMORY_5V		(1 << 0)
+
+#define CH7006_CALC_SUBC_INC0			0x21
+#define CH7006_CALC_SUBC_INC0_24		24, 4:3
+#define CH7006_CALC_SUBC_INC0_HYST		0, 2:1
+#define CH7006_CALC_SUBC_INC0_AUTO		(1 << 0)
+
+#define CH7006_CALC_SUBC_INC1			0x22
+#define CH7006_CALC_SUBC_INC1_16		16, 7:0
+
+#define CH7006_CALC_SUBC_INC2			0x23
+#define CH7006_CALC_SUBC_INC2_8			8, 7:0
+
+#define CH7006_CALC_SUBC_INC3			0x24
+#define CH7006_CALC_SUBC_INC3_0			0, 7:0
+
+#define CH7006_VERSION_ID			0x25
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i2c/ch7006_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "ch7006_priv.h"
+
+/* DRM encoder functions */
+
+static void ch7006_encoder_set_config(struct drm_encoder *encoder,
+				      void *params)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+
+	priv->params = params;
+}
+
+static void ch7006_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+
+	drm_property_destroy(encoder->dev, priv->scale_property);
+
+	kfree(priv);
+	to_encoder_slave(encoder)->slave_priv = NULL;
+
+	drm_i2c_encoder_destroy(encoder);
+}
+
+static void  ch7006_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_state *state = &priv->state;
+
+	ch7006_dbg(client, "\n");
+
+	if (mode == priv->last_dpms)
+		return;
+	priv->last_dpms = mode;
+
+	ch7006_setup_power_state(encoder);
+
+	ch7006_load_reg(client, state, CH7006_POWER);
+}
+
+static void ch7006_encoder_save(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+
+	ch7006_dbg(client, "\n");
+
+	ch7006_state_save(client, &priv->saved_state);
+}
+
+static void ch7006_encoder_restore(struct drm_encoder *encoder)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+
+	ch7006_dbg(client, "\n");
+
+	ch7006_state_load(client, &priv->saved_state);
+}
+
+static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder,
+				      struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+
+	/* The ch7006 is painfully picky with the input timings so no
+	 * custom modes for now... */
+
+	priv->mode = ch7006_lookup_mode(encoder, mode);
+
+	return !!priv->mode;
+}
+
+static int ch7006_encoder_mode_valid(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode)
+{
+	if (ch7006_lookup_mode(encoder, mode))
+		return MODE_OK;
+	else
+		return MODE_BAD;
+}
+
+static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *drm_mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_encoder_params *params = priv->params;
+	struct ch7006_state *state = &priv->state;
+	uint8_t *regs = state->regs;
+	struct ch7006_mode *mode = priv->mode;
+	struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
+	int start_active;
+
+	ch7006_dbg(client, "\n");
+
+	regs[CH7006_DISPMODE] = norm->dispmode | mode->dispmode;
+	regs[CH7006_BWIDTH] = 0;
+	regs[CH7006_INPUT_FORMAT] = bitf(CH7006_INPUT_FORMAT_FORMAT,
+					 params->input_format);
+
+	regs[CH7006_CLKMODE] = CH7006_CLKMODE_SUBC_LOCK
+		| bitf(CH7006_CLKMODE_XCM, params->xcm)
+		| bitf(CH7006_CLKMODE_PCM, params->pcm);
+	if (params->clock_mode)
+		regs[CH7006_CLKMODE] |= CH7006_CLKMODE_MASTER;
+	if (params->clock_edge)
+		regs[CH7006_CLKMODE] |= CH7006_CLKMODE_POS_EDGE;
+
+	start_active = (drm_mode->htotal & ~0x7) - (drm_mode->hsync_start & ~0x7);
+	regs[CH7006_POV] = bitf(CH7006_POV_START_ACTIVE_8, start_active);
+	regs[CH7006_START_ACTIVE] = bitf(CH7006_START_ACTIVE_0, start_active);
+
+	regs[CH7006_INPUT_SYNC] = 0;
+	if (params->sync_direction)
+		regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_OUTPUT;
+	if (params->sync_encoding)
+		regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_EMBEDDED;
+	if (drm_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PVSYNC;
+	if (drm_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		regs[CH7006_INPUT_SYNC] |= CH7006_INPUT_SYNC_PHSYNC;
+
+	regs[CH7006_DETECT] = 0;
+	regs[CH7006_BCLKOUT] = 0;
+
+	regs[CH7006_SUBC_INC3] = 0;
+	if (params->pout_level)
+		regs[CH7006_SUBC_INC3] |= CH7006_SUBC_INC3_POUT_3_3V;
+
+	regs[CH7006_SUBC_INC4] = 0;
+	if (params->active_detect)
+		regs[CH7006_SUBC_INC4] |= CH7006_SUBC_INC4_DS_INPUT;
+
+	regs[CH7006_PLL_CONTROL] = priv->saved_state.regs[CH7006_PLL_CONTROL];
+
+	ch7006_setup_levels(encoder);
+	ch7006_setup_subcarrier(encoder);
+	ch7006_setup_pll(encoder);
+	ch7006_setup_power_state(encoder);
+	ch7006_setup_properties(encoder);
+
+	ch7006_state_load(client, state);
+}
+
+static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encoder,
+						       struct drm_connector *connector)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_state *state = &priv->state;
+	int det;
+
+	ch7006_dbg(client, "\n");
+
+	ch7006_save_reg(client, state, CH7006_DETECT);
+	ch7006_save_reg(client, state, CH7006_POWER);
+	ch7006_save_reg(client, state, CH7006_CLKMODE);
+
+	ch7006_write(client, CH7006_POWER, CH7006_POWER_RESET |
+					   bitfs(CH7006_POWER_LEVEL, NORMAL));
+	ch7006_write(client, CH7006_CLKMODE, CH7006_CLKMODE_MASTER);
+
+	ch7006_write(client, CH7006_DETECT, CH7006_DETECT_SENSE);
+
+	ch7006_write(client, CH7006_DETECT, 0);
+
+	det = ch7006_read(client, CH7006_DETECT);
+
+	ch7006_load_reg(client, state, CH7006_CLKMODE);
+	ch7006_load_reg(client, state, CH7006_POWER);
+	ch7006_load_reg(client, state, CH7006_DETECT);
+
+	if ((det & (CH7006_DETECT_SVIDEO_Y_TEST|
+		    CH7006_DETECT_SVIDEO_C_TEST|
+		    CH7006_DETECT_CVBS_TEST)) == 0)
+		priv->subconnector = DRM_MODE_SUBCONNECTOR_SCART;
+	else if ((det & (CH7006_DETECT_SVIDEO_Y_TEST|
+			 CH7006_DETECT_SVIDEO_C_TEST)) == 0)
+		priv->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO;
+	else if ((det & CH7006_DETECT_CVBS_TEST) == 0)
+		priv->subconnector = DRM_MODE_SUBCONNECTOR_Composite;
+	else
+		priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
+
+	drm_connector_property_set_value(connector,
+			encoder->dev->mode_config.tv_subconnector_property,
+							priv->subconnector);
+
+	return priv->subconnector ? connector_status_connected :
+					connector_status_disconnected;
+}
+
+static int ch7006_encoder_get_modes(struct drm_encoder *encoder,
+				    struct drm_connector *connector)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_mode *mode;
+	int n = 0;
+
+	for (mode = ch7006_modes; mode->mode.clock; mode++) {
+		if (~mode->valid_scales & 1<<priv->scale ||
+		    ~mode->valid_norms & 1<<priv->norm)
+			continue;
+
+		drm_mode_probed_add(connector,
+				drm_mode_duplicate(encoder->dev, &mode->mode));
+
+		n++;
+	}
+
+	return n;
+}
+
+static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
+					   struct drm_connector *connector)
+{
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_mode_config *conf = &dev->mode_config;
+
+	drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
+
+	priv->scale_property = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						   "scale", 2);
+	priv->scale_property->values[0] = 0;
+	priv->scale_property->values[1] = 2;
+
+	drm_connector_attach_property(connector, conf->tv_select_subconnector_property,
+				      priv->select_subconnector);
+	drm_connector_attach_property(connector, conf->tv_subconnector_property,
+				      priv->subconnector);
+	drm_connector_attach_property(connector, conf->tv_left_margin_property,
+				      priv->hmargin);
+	drm_connector_attach_property(connector, conf->tv_bottom_margin_property,
+				      priv->vmargin);
+	drm_connector_attach_property(connector, conf->tv_mode_property,
+				      priv->norm);
+	drm_connector_attach_property(connector, conf->tv_brightness_property,
+				      priv->brightness);
+	drm_connector_attach_property(connector, conf->tv_contrast_property,
+				      priv->contrast);
+	drm_connector_attach_property(connector, conf->tv_flicker_reduction_property,
+				      priv->flicker);
+	drm_connector_attach_property(connector, priv->scale_property,
+				      priv->scale);
+
+	return 0;
+}
+
+static int ch7006_encoder_set_property(struct drm_encoder *encoder,
+				       struct drm_connector *connector,
+				       struct drm_property *property,
+				       uint64_t val)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	struct ch7006_priv *priv = to_ch7006_priv(encoder);
+	struct ch7006_state *state = &priv->state;
+	struct drm_mode_config *conf = &encoder->dev->mode_config;
+	struct drm_crtc *crtc = encoder->crtc;
+	bool modes_changed = false;
+
+	ch7006_dbg(client, "\n");
+
+	if (property == conf->tv_select_subconnector_property) {
+		priv->select_subconnector = val;
+
+		ch7006_setup_power_state(encoder);
+
+		ch7006_load_reg(client, state, CH7006_POWER);
+
+	} else if (property == conf->tv_left_margin_property) {
+		priv->hmargin = val;
+
+		ch7006_setup_properties(encoder);
+
+		ch7006_load_reg(client, state, CH7006_POV);
+		ch7006_load_reg(client, state, CH7006_HPOS);
+
+	} else if (property == conf->tv_bottom_margin_property) {
+		priv->vmargin = val;
+
+		ch7006_setup_properties(encoder);
+
+		ch7006_load_reg(client, state, CH7006_POV);
+		ch7006_load_reg(client, state, CH7006_VPOS);
+
+	} else if (property == conf->tv_mode_property) {
+		if (connector->dpms != DRM_MODE_DPMS_OFF)
+			return -EINVAL;
+
+		priv->norm = val;
+
+		modes_changed = true;
+
+	} else if (property == conf->tv_brightness_property) {
+		priv->brightness = val;
+
+		ch7006_setup_levels(encoder);
+
+		ch7006_load_reg(client, state, CH7006_BLACK_LEVEL);
+
+	} else if (property == conf->tv_contrast_property) {
+		priv->contrast = val;
+
+		ch7006_setup_properties(encoder);
+
+		ch7006_load_reg(client, state, CH7006_CONTRAST);
+
+	} else if (property == conf->tv_flicker_reduction_property) {
+		priv->flicker = val;
+
+		ch7006_setup_properties(encoder);
+
+		ch7006_load_reg(client, state, CH7006_FFILTER);
+
+	} else if (property == priv->scale_property) {
+		if (connector->dpms != DRM_MODE_DPMS_OFF)
+			return -EINVAL;
+
+		priv->scale = val;
+
+		modes_changed = true;
+
+	} else {
+		return -EINVAL;
+	}
+
+	if (modes_changed) {
+		drm_helper_probe_single_connector_modes(connector, 0, 0);
+
+		/* Disable the crtc to ensure a full modeset is
+		 * performed whenever it's turned on again. */
+		if (crtc) {
+			struct drm_mode_set modeset = {
+				.crtc = crtc,
+			};
+
+			crtc->funcs->set_config(&modeset);
+		}
+	}
+
+	return 0;
+}
+
+static struct drm_encoder_slave_funcs ch7006_encoder_funcs = {
+	.set_config = ch7006_encoder_set_config,
+	.destroy = ch7006_encoder_destroy,
+	.dpms = ch7006_encoder_dpms,
+	.save = ch7006_encoder_save,
+	.restore = ch7006_encoder_restore,
+	.mode_fixup = ch7006_encoder_mode_fixup,
+	.mode_valid = ch7006_encoder_mode_valid,
+	.mode_set = ch7006_encoder_mode_set,
+	.detect = ch7006_encoder_detect,
+	.get_modes = ch7006_encoder_get_modes,
+	.create_resources = ch7006_encoder_create_resources,
+	.set_property = ch7006_encoder_set_property,
+};
+
+
+/* I2C driver functions */
+
+static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	uint8_t addr = CH7006_VERSION_ID;
+	uint8_t val;
+	int ret;
+
+	ch7006_dbg(client, "\n");
+
+	ret = i2c_master_send(client, &addr, sizeof(addr));
+	if (ret < 0)
+		goto fail;
+
+	ret = i2c_master_recv(client, &val, sizeof(val));
+	if (ret < 0)
+		goto fail;
+
+	ch7006_info(client, "Detected version ID: %x\n", val);
+
+	/* I don't know what this is for, but otherwise I get no
+	 * signal.
+	 */
+	ch7006_write(client, 0x3d, 0x0);
+
+	return 0;
+
+fail:
+	ch7006_err(client, "Error %d reading version ID\n", ret);
+
+	return -ENODEV;
+}
+
+static int ch7006_remove(struct i2c_client *client)
+{
+	ch7006_dbg(client, "\n");
+
+	return 0;
+}
+
+static int ch7006_encoder_init(struct i2c_client *client,
+			       struct drm_device *dev,
+			       struct drm_encoder_slave *encoder)
+{
+	struct ch7006_priv *priv;
+	int i;
+
+	ch7006_dbg(client, "\n");
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	encoder->slave_priv = priv;
+	encoder->slave_funcs = &ch7006_encoder_funcs;
+
+	priv->norm = TV_NORM_PAL;
+	priv->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic;
+	priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
+	priv->scale = 1;
+	priv->contrast = 50;
+	priv->brightness = 50;
+	priv->flicker = 50;
+	priv->hmargin = 50;
+	priv->vmargin = 50;
+	priv->last_dpms = -1;
+
+	if (ch7006_tv_norm) {
+		for (i = 0; i < NUM_TV_NORMS; i++) {
+			if (!strcmp(ch7006_tv_norm_names[i], ch7006_tv_norm)) {
+				priv->norm = i;
+				break;
+			}
+		}
+
+		if (i == NUM_TV_NORMS)
+			ch7006_err(client, "Invalid TV norm setting \"%s\".\n",
+				   ch7006_tv_norm);
+	}
+
+	if (ch7006_scale >= 0 && ch7006_scale <= 2)
+		priv->scale = ch7006_scale;
+	else
+		ch7006_err(client, "Invalid scale setting \"%d\".\n",
+			   ch7006_scale);
+
+	return 0;
+}
+
+static struct i2c_device_id ch7006_ids[] = {
+	{ "ch7006", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ch7006_ids);
+
+static struct drm_i2c_encoder_driver ch7006_driver = {
+	.i2c_driver = {
+		.probe = ch7006_probe,
+		.remove = ch7006_remove,
+
+		.driver = {
+			.name = "ch7006",
+		},
+
+		.id_table = ch7006_ids,
+	},
+
+	.encoder_init = ch7006_encoder_init,
+};
+
+
+/* Module initialization */
+
+static int __init ch7006_init(void)
+{
+	return drm_i2c_encoder_register(THIS_MODULE, &ch7006_driver);
+}
+
+static void __exit ch7006_exit(void)
+{
+	drm_i2c_encoder_unregister(&ch7006_driver);
+}
+
+int ch7006_debug;
+module_param_named(debug, ch7006_debug, int, 0600);
+MODULE_PARM_DESC(debug, "Enable debug output.");
+
+char *ch7006_tv_norm;
+module_param_named(tv_norm, ch7006_tv_norm, charp, 0600);
+MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
+		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, PAL-60, NTSC-M, NTSC-J.\n"
+		 "\t\tDefault: PAL");
+
+int ch7006_scale = 1;
+module_param_named(scale, ch7006_scale, int, 0600);
+MODULE_PARM_DESC(scale, "Default scale.\n"
+		 "\t\tSupported: 0 -> Select video modes with a higher blanking ratio.\n"
+		 "\t\t\t1 -> Select default video modes.\n"
+		 "\t\t\t2 -> Select video modes with a lower blanking ratio.");
+
+MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
+MODULE_DESCRIPTION("Chrontel ch7006 TV encoder driver");
+MODULE_LICENSE("GPL and additional rights");
+
+module_init(ch7006_init);
+module_exit(ch7006_exit);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_lvds.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_lvds.c
@@ -56,7 +56,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 blc_pwm_ctl, reg;
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		reg = BLC_PWM_CPU_CTL;
 	else
 		reg = BLC_PWM_CTL;
@@ -74,7 +74,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		reg = BLC_PWM_PCH_CTL2;
 	else
 		reg = BLC_PWM_CTL;
@@ -91,7 +91,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_status, ctl_reg, status_reg;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		ctl_reg = PCH_PP_CONTROL;
 		status_reg = PCH_PP_STATUS;
 	} else {
@@ -137,7 +137,7 @@
 	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
 	u32 pwm_ctl_reg;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
 		pp_ctl_reg = PCH_PP_CONTROL;
@@ -174,7 +174,7 @@
 	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
 	u32 pwm_ctl_reg;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
 		pp_ctl_reg = PCH_PP_CONTROL;
@@ -297,7 +297,7 @@
 	}
 
 	/* full screen scale for now */
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		goto out;
 
 	/* 965+ wants fuzzy fitting */
@@ -327,7 +327,7 @@
 	 * to register description and PRM.
 	 * Change the value here to see the borders for debugging
 	 */
-	if (!IS_IGDNG(dev)) {
+	if (!IS_IRONLAKE(dev)) {
 		I915_WRITE(BCLRPAT_A, 0);
 		I915_WRITE(BCLRPAT_B, 0);
 	}
@@ -548,7 +548,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		reg = BLC_PWM_CPU_CTL;
 	else
 		reg = BLC_PWM_CTL;
@@ -587,7 +587,7 @@
 	 * settings.
 	 */
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		return;
 
 	/*
@@ -599,18 +599,6 @@
 	I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
 }
 
-/* Some lid devices report incorrect lid status, assume they're connected */
-static const struct dmi_system_id bad_lid_status[] = {
-	{
-		.ident = "Aspire One",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
-		},
-	},
-	{ }
-};
-
 /**
  * Detect the LVDS connection.
  *
@@ -620,10 +608,14 @@
  */
 static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status = connector_status_connected;
 
-	if (!acpi_lid_open() && !dmi_check_system(bad_lid_status))
-		status = connector_status_disconnected;
+	/* ACPI lid methods were generally unreliable in this generation, so
+	 * don't even bother.
+	 */
+	if (IS_GEN2(dev) || IS_GEN3(dev))
+		return connector_status_connected;
 
 	return status;
 }
@@ -679,7 +671,14 @@
 	struct drm_i915_private *dev_priv =
 		container_of(nb, struct drm_i915_private, lid_notifier);
 	struct drm_device *dev = dev_priv->dev;
+	struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+	/*
+	 * check and update the status of LVDS connector after receiving
+	 * the LID nofication event.
+	 */
+	if (connector)
+		connector->status = connector->funcs->detect(connector);
 	if (!acpi_lid_open()) {
 		dev_priv->modeset_on_lid = 1;
 		return NOTIFY_OK;
@@ -845,73 +844,126 @@
 	},
 	{
 		.callback = intel_no_lvds_dmi_callback,
+		.ident = "AOpen i915GMm-HFS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Aopen i945GTt-VFA",
 		.matches = {
 			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
 		},
 	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Clientron U800",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
+		},
+	},
 
 	{ }	/* terminating entry */
 };
 
-#ifdef CONFIG_ACPI
-/*
- * check_lid_device -- check whether @handle is an ACPI LID device.
- * @handle: ACPI device handle
- * @level : depth in the ACPI namespace tree
- * @context: the number of LID device when we find the device
- * @rv: a return value to fill if desired (Not use)
+/**
+ * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
+ * @dev: drm device
+ * @connector: LVDS connector
+ *
+ * Find the reduced downclock for LVDS in EDID.
  */
-static acpi_status
-check_lid_device(acpi_handle handle, u32 level, void *context,
-			void **return_value)
+static void intel_find_lvds_downclock(struct drm_device *dev,
+				struct drm_connector *connector)
 {
-	struct acpi_device *acpi_dev;
-	int *lid_present = context;
-
-	acpi_dev = NULL;
-	/* Get the acpi device for device handle */
-	if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) {
-		/* If there is no ACPI device for handle, return */
-		return AE_OK;
-	}
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *scan, *panel_fixed_mode;
+	int temp_downclock;
 
-	if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7))
-		*lid_present = 1;
+	panel_fixed_mode = dev_priv->panel_fixed_mode;
+	temp_downclock = panel_fixed_mode->clock;
 
-	return AE_OK;
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(scan, &connector->probed_modes, head) {
+		/*
+		 * If one mode has the same resolution with the fixed_panel
+		 * mode while they have the different refresh rate, it means
+		 * that the reduced downclock is found for the LVDS. In such
+		 * case we can set the different FPx0/1 to dynamically select
+		 * between low and high frequency.
+		 */
+		if (scan->hdisplay == panel_fixed_mode->hdisplay &&
+			scan->hsync_start == panel_fixed_mode->hsync_start &&
+			scan->hsync_end == panel_fixed_mode->hsync_end &&
+			scan->htotal == panel_fixed_mode->htotal &&
+			scan->vdisplay == panel_fixed_mode->vdisplay &&
+			scan->vsync_start == panel_fixed_mode->vsync_start &&
+			scan->vsync_end == panel_fixed_mode->vsync_end &&
+			scan->vtotal == panel_fixed_mode->vtotal) {
+			if (scan->clock < temp_downclock) {
+				/*
+				 * The downclock is already found. But we
+				 * expect to find the lower downclock.
+				 */
+				temp_downclock = scan->clock;
+			}
+		}
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	if (temp_downclock < panel_fixed_mode->clock &&
+	    i915_lvds_downclock) {
+		/* We found the downclock for LVDS. */
+		dev_priv->lvds_downclock_avail = 1;
+		dev_priv->lvds_downclock = temp_downclock;
+		DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
+				"Normal clock %dKhz, downclock %dKhz\n",
+				panel_fixed_mode->clock, temp_downclock);
+	}
+	return;
 }
 
-/**
- * check whether there exists the ACPI LID device by enumerating the ACPI
- * device tree.
+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the LVDS is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the LVDS is present.
+ * Note: The addin_offset should also be checked for LVDS panel.
+ * Only when it is non-zero, it is assumed that it is present.
  */
-static int intel_lid_present(void)
+static int lvds_is_present_in_vbt(struct drm_device *dev)
 {
-	int lid_present = 0;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i, ret;
 
-	if (acpi_disabled) {
-		/* If ACPI is disabled, there is no ACPI device tree to
-		 * check, so assume the LID device would have been present.
-		 */
+	if (!dev_priv->child_dev_num)
 		return 1;
-	}
 
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				ACPI_UINT32_MAX,
-				check_lid_device, &lid_present, NULL);
+	ret = 0;
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+		/*
+		 * If the device type is not LFP, continue.
+		 * If the device type is 0x22, it is also regarded as LFP.
+		 */
+		if (p_child->device_type != DEVICE_TYPE_INT_LFP &&
+			p_child->device_type != DEVICE_TYPE_LFP)
+			continue;
 
-	return lid_present;
-}
-#else
-static int intel_lid_present(void)
-{
-	/* In the absence of ACPI built in, assume that the LID device would
-	 * have been present.
-	 */
-	return 1;
+		/* The addin_offset should be checked. Only when it is
+		 * non-zero, it is regarded as present.
+		 */
+		if (p_child->addin_offset) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
 }
-#endif
 
 /**
  * intel_lvds_init - setup LVDS connectors on this device
@@ -936,21 +988,16 @@
 	if (dmi_check_system(intel_no_lvds))
 		return;
 
-	/* Assume that any device without an ACPI LID device also doesn't
-	 * have an integrated LVDS.  We would be better off parsing the BIOS
-	 * to get a reliable indicator, but that code isn't written yet.
-	 *
-	 * In the case of all-in-one desktops using LVDS that we've seen,
-	 * they're using SDVO LVDS.
-	 */
-	if (!intel_lid_present())
+	if (!lvds_is_present_in_vbt(dev)) {
+		DRM_DEBUG_KMS("LVDS is not present in VBT\n");
 		return;
+	}
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
 			return;
 		if (dev_priv->edp_support) {
-			DRM_DEBUG("disable LVDS for eDP support\n");
+			DRM_DEBUG_KMS("disable LVDS for eDP support\n");
 			return;
 		}
 		gpio = PCH_GPIOC;
@@ -1023,6 +1070,7 @@
 			dev_priv->panel_fixed_mode =
 				drm_mode_duplicate(dev, scan);
 			mutex_unlock(&dev->mode_config.mutex);
+			intel_find_lvds_downclock(dev, connector);
 			goto out;
 		}
 		mutex_unlock(&dev->mode_config.mutex);
@@ -1047,8 +1095,8 @@
 	 * correct mode.
 	 */
 
-	/* IGDNG: FIXME if still fail, not try pipe mode now */
-	if (IS_IGDNG(dev))
+	/* Ironlake: FIXME if still fail, not try pipe mode now */
+	if (IS_IRONLAKE(dev))
 		goto failed;
 
 	lvds = I915_READ(LVDS);
@@ -1069,7 +1117,7 @@
 		goto failed;
 
 out:
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		u32 pwm;
 		/* make sure PWM is enabled */
 		pwm = I915_READ(BLC_PWM_CPU_CTL2);
@@ -1082,9 +1130,11 @@
 	}
 	dev_priv->lid_notifier.notifier_call = intel_lid_notify;
 	if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
-		DRM_DEBUG("lid notifier registration failed\n");
+		DRM_DEBUG_KMS("lid notifier registration failed\n");
 		dev_priv->lid_notifier.notifier_call = NULL;
 	}
+	/* keep the LVDS connector */
+	dev_priv->int_lvds_connector = connector;
 	drm_sysfs_connector_add(connector);
 	return;
 
@@ -1093,5 +1143,6 @@
 	if (intel_output->ddc_bus)
 		intel_i2c_destroy(intel_output->ddc_bus);
 	drm_connector_cleanup(connector);
+	drm_encoder_cleanup(encoder);
 	kfree(intel_output);
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_crt.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_crt.c
@@ -39,7 +39,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 temp, reg;
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		reg = PCH_ADPA;
 	else
 		reg = ADPA;
@@ -64,34 +64,6 @@
 	}
 
 	I915_WRITE(reg, temp);
-
-	if (IS_IGD(dev)) {
-		if (mode == DRM_MODE_DPMS_OFF) {
-			/* turn off DAC */
-			temp = I915_READ(PORT_HOTPLUG_EN);
-			temp &= ~CRT_EOS_INT_EN;
-			I915_WRITE(PORT_HOTPLUG_EN, temp);
-
-			temp = I915_READ(PORT_HOTPLUG_STAT);
-			if (temp & CRT_EOS_INT_STATUS)
-				I915_WRITE(PORT_HOTPLUG_STAT,
-					CRT_EOS_INT_STATUS);
-		} else {
-			/* turn on DAC. EOS interrupt must be enabled after DAC
-			 * is enabled, so it sounds not good to enable it in
-			 * i915_driver_irq_postinstall()
-			 * wait 12.5ms after DAC is enabled
-			 */
-			msleep(13);
-			temp = I915_READ(PORT_HOTPLUG_STAT);
-			if (temp & CRT_EOS_INT_STATUS)
-				I915_WRITE(PORT_HOTPLUG_STAT,
-					CRT_EOS_INT_STATUS);
-			temp = I915_READ(PORT_HOTPLUG_EN);
-			temp |= CRT_EOS_INT_EN;
-			I915_WRITE(PORT_HOTPLUG_EN, temp);
-		}
-	}
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -141,7 +113,7 @@
 	else
 		dpll_md_reg = DPLL_B_MD;
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		adpa_reg = PCH_ADPA;
 	else
 		adpa_reg = ADPA;
@@ -150,7 +122,7 @@
 	 * Disable separate mode multiplier used when cloning SDVO to CRT
 	 * XXX this needs to be adjusted when we really are cloning
 	 */
-	if (IS_I965G(dev) && !IS_IGDNG(dev)) {
+	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
 		dpll_md = I915_READ(dpll_md_reg);
 		I915_WRITE(dpll_md_reg,
 			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
@@ -164,18 +136,18 @@
 
 	if (intel_crtc->pipe == 0) {
 		adpa |= ADPA_PIPE_A_SELECT;
-		if (!IS_IGDNG(dev))
+		if (!HAS_PCH_SPLIT(dev))
 			I915_WRITE(BCLRPAT_A, 0);
 	} else {
 		adpa |= ADPA_PIPE_B_SELECT;
-		if (!IS_IGDNG(dev))
+		if (!HAS_PCH_SPLIT(dev))
 			I915_WRITE(BCLRPAT_B, 0);
 	}
 
 	I915_WRITE(adpa_reg, adpa);
 }
 
-static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
+static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -185,6 +157,9 @@
 	adpa = I915_READ(PCH_ADPA);
 
 	adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+	/* disable HPD first */
+	I915_WRITE(PCH_ADPA, adpa);
+	(void)I915_READ(PCH_ADPA);
 
 	adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
 			ADPA_CRT_HOTPLUG_WARMUP_10MS |
@@ -194,7 +169,7 @@
 			ADPA_CRT_HOTPLUG_ENABLE |
 			ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
 
-	DRM_DEBUG("pch crt adpa 0x%x", adpa);
+	DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa);
 	I915_WRITE(PCH_ADPA, adpa);
 
 	while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
@@ -227,8 +202,8 @@
 	u32 hotplug_en;
 	int i, tries = 0;
 
-	if (IS_IGDNG(dev))
-		return intel_igdng_crt_detect_hotplug(connector);
+	if (HAS_PCH_SPLIT(dev))
+		return intel_ironlake_crt_detect_hotplug(connector);
 
 	/*
 	 * On 4 series desktop, CRT detect sequence need to be done twice
@@ -549,12 +524,12 @@
 					  &intel_output->enc);
 
 	/* Set up the DDC bus. */
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		i2c_reg = PCH_GPIOA;
 	else {
 		i2c_reg = GPIOA;
 		/* Use VBT information for CRT DDC if available */
-		if (dev_priv->crt_ddc_bus != -1)
+		if (dev_priv->crt_ddc_bus != 0)
 			i2c_reg = dev_priv->crt_ddc_bus;
 	}
 	intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
@@ -576,4 +551,6 @@
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
+
+	dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_opregion.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_opregion.c
@@ -118,6 +118,10 @@
 #define ASLE_BACKLIGHT_FAIL    (2<<12)
 #define ASLE_PFIT_FAIL         (2<<14)
 #define ASLE_PWM_FREQ_FAIL     (2<<16)
+#define ASLE_ALS_ILLUM_FAILED	(1<<10)
+#define ASLE_BACKLIGHT_FAILED	(1<<12)
+#define ASLE_PFIT_FAILED	(1<<14)
+#define ASLE_PWM_FREQ_FAILED	(1<<16)
 
 /* ASLE backlight brightness to set */
 #define ASLE_BCLP_VALID                (1<<31)
@@ -163,7 +167,7 @@
 	if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE))
 		pci_write_config_dword(dev->pdev, PCI_LBPC, bclp);
 	else {
-		if (IS_IGD(dev)) {
+		if (IS_PINEVIEW(dev)) {
 			blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
 			max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> 
 					BACKLIGHT_MODULATION_FREQ_SHIFT;
@@ -224,7 +228,7 @@
 	asle_req = asle->aslc & ASLE_REQ_MSK;
 
 	if (!asle_req) {
-		DRM_DEBUG("non asle set request??\n");
+		DRM_DEBUG_DRIVER("non asle set request??\n");
 		return;
 	}
 
@@ -243,6 +247,73 @@
 	asle->aslc = asle_stat;
 }
 
+static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct opregion_asle *asle = dev_priv->opregion.asle;
+	u32 cpu_pwm_ctl, pch_pwm_ctl2;
+	u32 max_backlight, level;
+
+	if (!(bclp & ASLE_BCLP_VALID))
+		return ASLE_BACKLIGHT_FAILED;
+
+	bclp &= ASLE_BCLP_MSK;
+	if (bclp < 0 || bclp > 255)
+		return ASLE_BACKLIGHT_FAILED;
+
+	cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
+	pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+	/* get the max PWM frequency */
+	max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
+	/* calculate the expected PMW frequency */
+	level = (bclp * max_backlight) / 255;
+	/* reserve the high 16 bits */
+	cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
+	/* write the updated PWM frequency */
+	I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
+
+	asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
+
+	return 0;
+}
+
+void ironlake_opregion_gse_intr(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct opregion_asle *asle = dev_priv->opregion.asle;
+	u32 asle_stat = 0;
+	u32 asle_req;
+
+	if (!asle)
+		return;
+
+	asle_req = asle->aslc & ASLE_REQ_MSK;
+
+	if (!asle_req) {
+		DRM_DEBUG_DRIVER("non asle set request??\n");
+		return;
+	}
+
+	if (asle_req & ASLE_SET_ALS_ILLUM) {
+		DRM_DEBUG_DRIVER("Illum is not supported\n");
+		asle_stat |= ASLE_ALS_ILLUM_FAILED;
+	}
+
+	if (asle_req & ASLE_SET_BACKLIGHT)
+		asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
+
+	if (asle_req & ASLE_SET_PFIT) {
+		DRM_DEBUG_DRIVER("Pfit is not supported\n");
+		asle_stat |= ASLE_PFIT_FAILED;
+	}
+
+	if (asle_req & ASLE_SET_PWM_FREQ) {
+		DRM_DEBUG_DRIVER("PWM freq is not supported\n");
+		asle_stat |= ASLE_PWM_FREQ_FAILED;
+	}
+
+	asle->aslc = asle_stat;
+}
 #define ASLE_ALS_EN    (1<<0)
 #define ASLE_BLC_EN    (1<<1)
 #define ASLE_PFIT_EN   (1<<2)
@@ -258,8 +329,7 @@
 			unsigned long irqflags;
 
 			spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-			i915_enable_pipestat(dev_priv, 1,
-					     I915_LEGACY_BLC_EVENT_ENABLE);
+			intel_enable_asle(dev);
 			spin_unlock_irqrestore(&dev_priv->user_irq_lock,
 					       irqflags);
 		}
@@ -312,8 +382,57 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_opregion *opregion = &dev_priv->opregion;
 	struct drm_connector *connector;
+	acpi_handle handle;
+	struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
+	unsigned long long device_id;
+	acpi_status status;
 	int i = 0;
 
+	handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
+	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev)))
+		return;
+
+	if (acpi_is_video_device(acpi_dev))
+		acpi_video_bus = acpi_dev;
+	else {
+		list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
+			if (acpi_is_video_device(acpi_cdev)) {
+				acpi_video_bus = acpi_cdev;
+				break;
+			}
+		}
+	}
+
+	if (!acpi_video_bus) {
+		printk(KERN_WARNING "No ACPI video bus found\n");
+		return;
+	}
+
+	list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
+		if (i >= 8) {
+			dev_printk (KERN_ERR, &dev->pdev->dev,
+				    "More than 8 outputs detected\n");
+			return;
+		}
+		status =
+			acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
+						NULL, &device_id);
+		if (ACPI_SUCCESS(status)) {
+			if (!device_id)
+				goto blind_set;
+			opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
+			i++;
+		}
+	}
+
+end:
+	/* If fewer than 8 outputs, the list must be null terminated */
+	if (i < 8)
+		opregion->acpi->didl[i] = 0;
+	return;
+
+blind_set:
+	i = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		int output_type = ACPI_OTHER_OUTPUT;
 		if (i >= 8) {
@@ -346,10 +465,7 @@
 		opregion->acpi->didl[i] |= (1<<31) | output_type | i;
 		i++;
 	}
-
-	/* If fewer than 8 outputs, the list must be null terminated */
-	if (i < 8)
-		opregion->acpi->didl[i] = 0;
+	goto end;
 }
 
 int intel_opregion_init(struct drm_device *dev, int resume)
@@ -361,9 +477,9 @@
 	int err = 0;
 
 	pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
-	DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls);
+	DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
 	if (asls == 0) {
-		DRM_DEBUG("ACPI OpRegion not supported!\n");
+		DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
 		return -ENOTSUPP;
 	}
 
@@ -373,30 +489,30 @@
 
 	opregion->header = base;
 	if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) {
-		DRM_DEBUG("opregion signature mismatch\n");
+		DRM_DEBUG_DRIVER("opregion signature mismatch\n");
 		err = -EINVAL;
 		goto err_out;
 	}
 
 	mboxes = opregion->header->mboxes;
 	if (mboxes & MBOX_ACPI) {
-		DRM_DEBUG("Public ACPI methods supported\n");
+		DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
 		opregion->acpi = base + OPREGION_ACPI_OFFSET;
 		if (drm_core_check_feature(dev, DRIVER_MODESET))
 			intel_didl_outputs(dev);
 	} else {
-		DRM_DEBUG("Public ACPI methods not supported\n");
+		DRM_DEBUG_DRIVER("Public ACPI methods not supported\n");
 		err = -ENOTSUPP;
 		goto err_out;
 	}
 	opregion->enabled = 1;
 
 	if (mboxes & MBOX_SWSCI) {
-		DRM_DEBUG("SWSCI supported\n");
+		DRM_DEBUG_DRIVER("SWSCI supported\n");
 		opregion->swsci = base + OPREGION_SWSCI_OFFSET;
 	}
 	if (mboxes & MBOX_ASLE) {
-		DRM_DEBUG("ASLE supported\n");
+		DRM_DEBUG_DRIVER("ASLE supported\n");
 		opregion->asle = base + OPREGION_ASLE_OFFSET;
 		opregion_enable_asle(dev);
 	}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/dvo_ivch.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/dvo_ivch.c
@@ -202,7 +202,8 @@
 	};
 
 	if (!priv->quiet) {
-		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
+		DRM_DEBUG_KMS("Unable to read register 0x%02x from "
+				"%s:%02x.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
@@ -230,7 +231,7 @@
 		return true;
 
 	if (!priv->quiet) {
-		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
+		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
@@ -261,7 +262,7 @@
 	 * the address it's responding on.
 	 */
 	if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) {
-		DRM_DEBUG("ivch detect failed due to address mismatch "
+		DRM_DEBUG_KMS("ivch detect failed due to address mismatch "
 			  "(%d vs %d)\n",
 			  (temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr);
 		goto out;
@@ -367,41 +368,41 @@
 	uint16_t val;
 
 	ivch_read(dvo, VR00, &val);
-	DRM_DEBUG("VR00: 0x%04x\n", val);
+	DRM_LOG_KMS("VR00: 0x%04x\n", val);
 	ivch_read(dvo, VR01, &val);
-	DRM_DEBUG("VR01: 0x%04x\n", val);
+	DRM_LOG_KMS("VR01: 0x%04x\n", val);
 	ivch_read(dvo, VR30, &val);
-	DRM_DEBUG("VR30: 0x%04x\n", val);
+	DRM_LOG_KMS("VR30: 0x%04x\n", val);
 	ivch_read(dvo, VR40, &val);
-	DRM_DEBUG("VR40: 0x%04x\n", val);
+	DRM_LOG_KMS("VR40: 0x%04x\n", val);
 
 	/* GPIO registers */
 	ivch_read(dvo, VR80, &val);
-	DRM_DEBUG("VR80: 0x%04x\n", val);
+	DRM_LOG_KMS("VR80: 0x%04x\n", val);
 	ivch_read(dvo, VR81, &val);
-	DRM_DEBUG("VR81: 0x%04x\n", val);
+	DRM_LOG_KMS("VR81: 0x%04x\n", val);
 	ivch_read(dvo, VR82, &val);
-	DRM_DEBUG("VR82: 0x%04x\n", val);
+	DRM_LOG_KMS("VR82: 0x%04x\n", val);
 	ivch_read(dvo, VR83, &val);
-	DRM_DEBUG("VR83: 0x%04x\n", val);
+	DRM_LOG_KMS("VR83: 0x%04x\n", val);
 	ivch_read(dvo, VR84, &val);
-	DRM_DEBUG("VR84: 0x%04x\n", val);
+	DRM_LOG_KMS("VR84: 0x%04x\n", val);
 	ivch_read(dvo, VR85, &val);
-	DRM_DEBUG("VR85: 0x%04x\n", val);
+	DRM_LOG_KMS("VR85: 0x%04x\n", val);
 	ivch_read(dvo, VR86, &val);
-	DRM_DEBUG("VR86: 0x%04x\n", val);
+	DRM_LOG_KMS("VR86: 0x%04x\n", val);
 	ivch_read(dvo, VR87, &val);
-	DRM_DEBUG("VR87: 0x%04x\n", val);
+	DRM_LOG_KMS("VR87: 0x%04x\n", val);
 	ivch_read(dvo, VR88, &val);
-	DRM_DEBUG("VR88: 0x%04x\n", val);
+	DRM_LOG_KMS("VR88: 0x%04x\n", val);
 
 	/* Scratch register 0 - AIM Panel type */
 	ivch_read(dvo, VR8E, &val);
-	DRM_DEBUG("VR8E: 0x%04x\n", val);
+	DRM_LOG_KMS("VR8E: 0x%04x\n", val);
 
 	/* Scratch register 1 - Status register */
 	ivch_read(dvo, VR8F, &val);
-	DRM_DEBUG("VR8F: 0x%04x\n", val);
+	DRM_LOG_KMS("VR8F: 0x%04x\n", val);
 }
 
 static void ivch_save(struct intel_dvo_device *dvo)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_sdvo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_sdvo.c
@@ -35,8 +35,7 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "intel_sdvo_regs.h"
-
-#undef SDVO_DEBUG
+#include <linux/dmi.h>
 
 static char *tv_format_names[] = {
 	"NTSC_M"   , "NTSC_J"  , "NTSC_443",
@@ -356,7 +355,6 @@
 #define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
 #define SDVO_PRIV(output)   ((struct intel_sdvo_priv *) (output)->dev_priv)
 
-#ifdef SDVO_DEBUG
 static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
 				   void *args, int args_len)
 {
@@ -379,9 +377,6 @@
 		DRM_LOG_KMS("(%02X)", cmd);
 	DRM_LOG_KMS("\n");
 }
-#else
-#define intel_sdvo_debug_write(o, c, a, l)
-#endif
 
 static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd,
 				 void *args, int args_len)
@@ -398,7 +393,6 @@
 	intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd);
 }
 
-#ifdef SDVO_DEBUG
 static const char *cmd_status_names[] = {
 	"Power on",
 	"Success",
@@ -427,9 +421,6 @@
 		DRM_LOG_KMS("(??? %d)", status);
 	DRM_LOG_KMS("\n");
 }
-#else
-#define intel_sdvo_debug_response(o, r, l, s)
-#endif
 
 static u8 intel_sdvo_read_response(struct intel_output *intel_output,
 				   void *response, int response_len)
@@ -472,14 +463,63 @@
 }
 
 /**
- * Don't check status code from this as it switches the bus back to the
- * SDVO chips which defeats the purpose of doing a bus switch in the first
- * place.
+ * Try to read the response after issuie the DDC switch command. But it
+ * is noted that we must do the action of reading response and issuing DDC
+ * switch command in one I2C transaction. Otherwise when we try to start
+ * another I2C transaction after issuing the DDC bus switch, it will be
+ * switched to the internal SDVO register.
  */
 static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output,
 					      u8 target)
 {
-	intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	u8 out_buf[2], cmd_buf[2], ret_value[2], ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr = sdvo_priv->slave_addr >> 1,
+			.flags = 0,
+			.len = 2,
+			.buf = out_buf,
+		},
+		/* the following two are to read the response */
+		{
+			.addr = sdvo_priv->slave_addr >> 1,
+			.flags = 0,
+			.len = 1,
+			.buf = cmd_buf,
+		},
+		{
+			.addr = sdvo_priv->slave_addr >> 1,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = ret_value,
+		},
+	};
+
+	intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH,
+					&target, 1);
+	/* write the DDC switch command argument */
+	intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target);
+
+	out_buf[0] = SDVO_I2C_OPCODE;
+	out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
+	cmd_buf[0] = SDVO_I2C_CMD_STATUS;
+	cmd_buf[1] = 0;
+	ret_value[0] = 0;
+	ret_value[1] = 0;
+
+	ret = i2c_transfer(intel_output->i2c_bus, msgs, 3);
+	if (ret != 3) {
+		/* failure in I2C transfer */
+		DRM_DEBUG_KMS("I2c transfer returned %d\n", ret);
+		return;
+	}
+	if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) {
+		DRM_DEBUG_KMS("DDC switch command returns response %d\n",
+					ret_value[0]);
+		return;
+	}
+	return;
 }
 
 static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1)
@@ -1589,6 +1629,32 @@
 	edid = drm_get_edid(&intel_output->base,
 			    intel_output->ddc_bus);
 
+	/* This is only applied to SDVO cards with multiple outputs */
+	if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) {
+		uint8_t saved_ddc, temp_ddc;
+		saved_ddc = sdvo_priv->ddc_bus;
+		temp_ddc = sdvo_priv->ddc_bus >> 1;
+		/*
+		 * Don't use the 1 as the argument of DDC bus switch to get
+		 * the EDID. It is used for SDVO SPD ROM.
+		 */
+		while(temp_ddc > 1) {
+			sdvo_priv->ddc_bus = temp_ddc;
+			edid = drm_get_edid(&intel_output->base,
+				intel_output->ddc_bus);
+			if (edid) {
+				/*
+				 * When we can get the EDID, maybe it is the
+				 * correct DDC bus. Update it.
+				 */
+				sdvo_priv->ddc_bus = temp_ddc;
+				break;
+			}
+			temp_ddc >>= 1;
+		}
+		if (edid == NULL)
+			sdvo_priv->ddc_bus = saved_ddc;
+	}
 	/* when there is no edid and no monitor is connected with VGA
 	 * port, try to use the CRT ddc to read the EDID for DVI-connector
 	 */
@@ -1627,6 +1693,10 @@
 
 	intel_sdvo_write_cmd(intel_output,
 			     SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+	/* add 30ms delay when the output type might be TV */
+	if (sdvo_priv->caps.output_flags &
+	    (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0))
+ 		mdelay(30);
 	status = intel_sdvo_read_response(intel_output, &response, 2);
 
 	DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8);
@@ -2214,6 +2284,25 @@
 		return 0x72;
 }
 
+static int intel_sdvo_bad_tv_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Ignoring bad SDVO TV connector for %s\n", id->ident);
+	return 1;
+}
+
+static struct dmi_system_id intel_sdvo_bad_tv[] = {
+	{
+		.callback = intel_sdvo_bad_tv_callback,
+		.ident = "IntelG45/ICH10R/DME1737",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IBM CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "4800784"),
+		},
+	},
+
+	{ }	/* terminating entry */
+};
+
 static bool
 intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
 {
@@ -2254,7 +2343,8 @@
 					(1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 					(1 << INTEL_ANALOG_CLONE_BIT);
 		}
-	} else if (flags & SDVO_OUTPUT_SVID0) {
+	} else if ((flags & SDVO_OUTPUT_SVID0) &&
+		   !dmi_check_system(intel_sdvo_bad_tv)) {
 
 		sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
 		encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
@@ -2276,6 +2366,14 @@
 		connector->connector_type = DRM_MODE_CONNECTOR_VGA;
 		intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 					(1 << INTEL_ANALOG_CLONE_BIT);
+	} else if (flags & SDVO_OUTPUT_CVBS0) {
+
+		sdvo_priv->controlled_output = SDVO_OUTPUT_CVBS0;
+		encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
+		connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
+		sdvo_priv->is_tv = true;
+		intel_output->needs_tv_clock = true;
+		intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
 	} else if (flags & SDVO_OUTPUT_LVDS0) {
 
 		sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
@@ -2668,6 +2766,7 @@
 
 bool intel_sdvo_init(struct drm_device *dev, int output_device)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
 	struct intel_output *intel_output;
 	struct intel_sdvo_priv *sdvo_priv;
@@ -2714,10 +2813,12 @@
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
 		sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
 						"SDVOB/VGA DDC BUS");
+		dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
 	} else {
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
 		sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
 						"SDVOC/VGA DDC BUS");
+		dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
 	}
 
 	if (intel_output->ddc_bus == NULL)
@@ -2726,7 +2827,7 @@
 	/* Wrap with our custom algo which switches to DDC mode */
 	intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
 
-	/* In defaut case sdvo lvds is false */
+	/* In default case sdvo lvds is false */
 	intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
 
 	if (intel_sdvo_output_setup(intel_output,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/dvo_tfp410.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -130,7 +130,7 @@
 	};
 
 	if (!tfp->quiet) {
-		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
+		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
@@ -156,7 +156,7 @@
 		return true;
 
 	if (!tfp->quiet) {
-		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
+		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
@@ -191,13 +191,15 @@
 	tfp->quiet = true;
 
 	if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
-		DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n",
+		DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s "
+				"Slave %d.\n",
 			  id, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
 	if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
-		DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n",
+		DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s "
+				"Slave %d.\n",
 			  id, adapter->name, dvo->slave_addr);
 		goto out;
 	}
@@ -214,7 +216,7 @@
 	uint8_t ctl2;
 
 	if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
-		if (ctl2 & TFP410_CTL_2_HTPLG)
+		if (ctl2 & TFP410_CTL_2_RSEN)
 			ret = connector_status_connected;
 		else
 			ret = connector_status_disconnected;
@@ -262,33 +264,33 @@
 	uint8_t val, val2;
 
 	tfp410_readb(dvo, TFP410_REV, &val);
-	DRM_DEBUG("TFP410_REV: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_CTL_1, &val);
-	DRM_DEBUG("TFP410_CTL1: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_CTL_2, &val);
-	DRM_DEBUG("TFP410_CTL2: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_CTL_3, &val);
-	DRM_DEBUG("TFP410_CTL3: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_USERCFG, &val);
-	DRM_DEBUG("TFP410_USERCFG: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_DE_DLY, &val);
-	DRM_DEBUG("TFP410_DE_DLY: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_DE_CTL, &val);
-	DRM_DEBUG("TFP410_DE_CTL: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_DE_TOP, &val);
-	DRM_DEBUG("TFP410_DE_TOP: 0x%02X\n", val);
+	DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
 	tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
 	tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
-	DRM_DEBUG("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
+	DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
 	tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
 	tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
-	DRM_DEBUG("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
+	DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
 	tfp410_readb(dvo, TFP410_H_RES_LO, &val);
 	tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
-	DRM_DEBUG("TFP410_H_RES: 0x%02X%02X\n", val2, val);
+	DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
 	tfp410_readb(dvo, TFP410_V_RES_LO, &val);
 	tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
-	DRM_DEBUG("TFP410_V_RES: 0x%02X%02X\n", val2, val);
+	DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
 }
 
 static void tfp410_save(struct intel_dvo_device *dvo)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/Makefile
@@ -15,7 +15,6 @@
 	  intel_lvds.o \
 	  intel_bios.o \
 	  intel_dp.o \
-	  intel_dp_i2c.o \
 	  intel_hdmi.o \
 	  intel_sdvo.o \
 	  intel_modes.o \
@@ -23,6 +22,7 @@
 	  intel_fb.o \
 	  intel_tv.o \
 	  intel_dvo.o \
+	  intel_overlay.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
 	  dvo_ivch.o \
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_debugfs.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_debugfs.c
@@ -27,6 +27,7 @@
  */
 
 #include <linux/seq_file.h>
+#include <linux/debugfs.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
@@ -96,13 +97,14 @@
 	{
 		struct drm_gem_object *obj = obj_priv->obj;
 
-		seq_printf(m, "    %p: %s %8zd %08x %08x %d %s",
+		seq_printf(m, "    %p: %s %8zd %08x %08x %d%s%s",
 			   obj,
 			   get_pin_flag(obj_priv),
 			   obj->size,
 			   obj->read_domains, obj->write_domain,
 			   obj_priv->last_rendering_seqno,
-			   obj_priv->dirty ? "dirty" : "");
+			   obj_priv->dirty ? " dirty" : "",
+			   obj_priv->madv == I915_MADV_DONTNEED ? " purgeable" : "");
 
 		if (obj->name)
 			seq_printf(m, " (name: %d)", obj->name);
@@ -160,7 +162,7 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	if (!IS_IGDNG(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		seq_printf(m, "Interrupt enable:    %08x\n",
 			   I915_READ(IER));
 		seq_printf(m, "Interrupt identity:  %08x\n",
@@ -270,7 +272,7 @@
 		mem = kmap_atomic(pages[page], KM_USER0);
 		for (i = 0; i < PAGE_SIZE; i += 4)
 			seq_printf(m, "%08x :  %08x\n", i, mem[i / 4]);
-		kunmap_atomic(pages[page], KM_USER0);
+		kunmap_atomic(mem, KM_USER0);
 	}
 }
 
@@ -288,7 +290,7 @@
 	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
 		obj = obj_priv->obj;
 		if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) {
-		    ret = i915_gem_object_get_pages(obj);
+		    ret = i915_gem_object_get_pages(obj, 0);
 		    if (ret) {
 			    DRM_ERROR("Failed to get pages: %d\n", ret);
 			    spin_unlock(&dev_priv->mm.active_list_lock);
@@ -384,37 +386,111 @@
 	return 0;
 }
 
-static int i915_registers_info(struct seq_file *m, void *data) {
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
+static int
+i915_wedged_open(struct inode *inode,
+		 struct file *filp)
+{
+	filp->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t
+i915_wedged_read(struct file *filp,
+		 char __user *ubuf,
+		 size_t max,
+		 loff_t *ppos)
+{
+	struct drm_device *dev = filp->private_data;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	char buf[80];
+	int len;
+
+	len = snprintf(buf, sizeof (buf),
+		       "wedged :  %d\n",
+		       atomic_read(&dev_priv->mm.wedged));
+
+	return simple_read_from_buffer(ubuf, max, ppos, buf, len);
+}
+
+static ssize_t
+i915_wedged_write(struct file *filp,
+		  const char __user *ubuf,
+		  size_t cnt,
+		  loff_t *ppos)
+{
+	struct drm_device *dev = filp->private_data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t reg;
+	char buf[20];
+	int val = 1;
+
+	if (cnt > 0) {
+		if (cnt > sizeof (buf) - 1)
+			return -EINVAL;
+
+		if (copy_from_user(buf, ubuf, cnt))
+			return -EFAULT;
+		buf[cnt] = 0;
+
+		val = simple_strtoul(buf, NULL, 0);
+	}
+
+	DRM_INFO("Manually setting wedged to %d\n", val);
 
-#define DUMP_RANGE(start, end) \
-	for (reg=start; reg < end; reg += 4) \
-	seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
-
-	DUMP_RANGE(0x00000, 0x00fff);   /* VGA registers */
-	DUMP_RANGE(0x02000, 0x02fff);   /* instruction, memory, interrupt control registers */
-	DUMP_RANGE(0x03000, 0x031ff);   /* FENCE and PPGTT control registers */
-	DUMP_RANGE(0x03200, 0x03fff);   /* frame buffer compression registers */
-	DUMP_RANGE(0x05000, 0x05fff);   /* I/O control registers */
-	DUMP_RANGE(0x06000, 0x06fff);   /* clock control registers */
-	DUMP_RANGE(0x07000, 0x07fff);   /* 3D internal debug registers */
-	DUMP_RANGE(0x07400, 0x088ff);   /* GPE debug registers */
-	DUMP_RANGE(0x0a000, 0x0afff);   /* display palette registers */
-	DUMP_RANGE(0x10000, 0x13fff);   /* MMIO MCHBAR */
-	DUMP_RANGE(0x30000, 0x3ffff);   /* overlay registers */
-	DUMP_RANGE(0x60000, 0x6ffff);   /* display engine pipeline registers */
-	DUMP_RANGE(0x70000, 0x72fff);   /* display and cursor registers */
-	DUMP_RANGE(0x73000, 0x73fff);   /* performance counters */
+	atomic_set(&dev_priv->mm.wedged, val);
+	if (val) {
+		DRM_WAKEUP(&dev_priv->irq_queue);
+		queue_work(dev_priv->wq, &dev_priv->error_work);
+	}
+
+	return cnt;
+}
+
+static const struct file_operations i915_wedged_fops = {
+	.owner = THIS_MODULE,
+	.open = i915_wedged_open,
+	.read = i915_wedged_read,
+	.write = i915_wedged_write,
+};
+
+/* As the drm_debugfs_init() routines are called before dev->dev_private is
+ * allocated we need to hook into the minor for release. */
+static int
+drm_add_fake_info_node(struct drm_minor *minor,
+		       struct dentry *ent,
+		       const void *key)
+{
+	struct drm_info_node *node;
+
+	node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+	if (node == NULL) {
+		debugfs_remove(ent);
+		return -ENOMEM;
+	}
+
+	node->minor = minor;
+	node->dent = ent;
+	node->info_ent = (void *) key;
+	list_add(&node->list, &minor->debugfs_nodes.list);
 
 	return 0;
 }
 
+static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	struct dentry *ent;
+
+	ent = debugfs_create_file("i915_wedged",
+				  S_IRUGO | S_IWUSR,
+				  root, dev,
+				  &i915_wedged_fops);
+	if (IS_ERR(ent))
+		return PTR_ERR(ent);
+
+	return drm_add_fake_info_node(minor, ent, &i915_wedged_fops);
+}
 
 static struct drm_info_list i915_debugfs_list[] = {
-	{"i915_regs", i915_registers_info, 0},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
 	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
@@ -432,6 +508,12 @@
 
 int i915_debugfs_init(struct drm_minor *minor)
 {
+	int ret;
+
+	ret = i915_wedged_create(minor->debugfs_root, minor);
+	if (ret)
+		return ret;
+
 	return drm_debugfs_create_files(i915_debugfs_list,
 					I915_DEBUGFS_ENTRIES,
 					minor->debugfs_root, minor);
@@ -441,7 +523,8 @@
 {
 	drm_debugfs_remove_files(i915_debugfs_list,
 				 I915_DEBUGFS_ENTRIES, minor);
+	drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops,
+				 1, minor);
 }
 
 #endif /* CONFIG_DEBUG_FS */
-
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_display.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_display.c
@@ -32,7 +32,7 @@
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
-#include "intel_dp.h"
+#include "drm_dp_helper.h"
 
 #include "drm_crtc_helper.h"
 
@@ -41,6 +41,7 @@
 bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
 static void intel_update_watermarks(struct drm_device *dev);
 static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
+static void intel_crtc_update_cursor(struct drm_crtc *crtc);
 
 typedef struct {
     /* given values */
@@ -70,8 +71,6 @@
     intel_p2_t	    p2;
     bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
 		      int, int, intel_clock_t *);
-    bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *,
-			      int, int, intel_clock_t *);
 };
 
 #define I8XX_DOT_MIN		  25000
@@ -102,32 +101,32 @@
 #define I9XX_DOT_MAX		 400000
 #define I9XX_VCO_MIN		1400000
 #define I9XX_VCO_MAX		2800000
-#define IGD_VCO_MIN		1700000
-#define IGD_VCO_MAX		3500000
+#define PINEVIEW_VCO_MIN		1700000
+#define PINEVIEW_VCO_MAX		3500000
 #define I9XX_N_MIN		      1
 #define I9XX_N_MAX		      6
-/* IGD's Ncounter is a ring counter */
-#define IGD_N_MIN		      3
-#define IGD_N_MAX		      6
+/* Pineview's Ncounter is a ring counter */
+#define PINEVIEW_N_MIN		      3
+#define PINEVIEW_N_MAX		      6
 #define I9XX_M_MIN		     70
 #define I9XX_M_MAX		    120
-#define IGD_M_MIN		      2
-#define IGD_M_MAX		    256
+#define PINEVIEW_M_MIN		      2
+#define PINEVIEW_M_MAX		    256
 #define I9XX_M1_MIN		     10
 #define I9XX_M1_MAX		     22
 #define I9XX_M2_MIN		      5
 #define I9XX_M2_MAX		      9
-/* IGD M1 is reserved, and must be 0 */
-#define IGD_M1_MIN		      0
-#define IGD_M1_MAX		      0
-#define IGD_M2_MIN		      0
-#define IGD_M2_MAX		      254
+/* Pineview M1 is reserved, and must be 0 */
+#define PINEVIEW_M1_MIN		      0
+#define PINEVIEW_M1_MAX		      0
+#define PINEVIEW_M2_MIN		      0
+#define PINEVIEW_M2_MAX		      254
 #define I9XX_P_SDVO_DAC_MIN	      5
 #define I9XX_P_SDVO_DAC_MAX	     80
 #define I9XX_P_LVDS_MIN		      7
 #define I9XX_P_LVDS_MAX		     98
-#define IGD_P_LVDS_MIN		      7
-#define IGD_P_LVDS_MAX		     112
+#define PINEVIEW_P_LVDS_MIN		      7
+#define PINEVIEW_P_LVDS_MAX		     112
 #define I9XX_P1_MIN		      1
 #define I9XX_P1_MAX		      8
 #define I9XX_P2_SDVO_DAC_SLOW		     10
@@ -234,53 +233,108 @@
 #define G4X_P2_DISPLAY_PORT_FAST           10
 #define G4X_P2_DISPLAY_PORT_LIMIT          0
 
-/* IGDNG */
+/* Ironlake / Sandybridge */
 /* as we calculate clock using (register_value + 2) for
    N/M1/M2, so here the range value for them is (actual_value-2).
  */
-#define IGDNG_DOT_MIN         25000
-#define IGDNG_DOT_MAX         350000
-#define IGDNG_VCO_MIN         1760000
-#define IGDNG_VCO_MAX         3510000
-#define IGDNG_N_MIN           1
-#define IGDNG_N_MAX           5
-#define IGDNG_M_MIN           79
-#define IGDNG_M_MAX           118
-#define IGDNG_M1_MIN          12
-#define IGDNG_M1_MAX          23
-#define IGDNG_M2_MIN          5
-#define IGDNG_M2_MAX          9
-#define IGDNG_P_SDVO_DAC_MIN  5
-#define IGDNG_P_SDVO_DAC_MAX  80
-#define IGDNG_P_LVDS_MIN      28
-#define IGDNG_P_LVDS_MAX      112
-#define IGDNG_P1_MIN          1
-#define IGDNG_P1_MAX          8
-#define IGDNG_P2_SDVO_DAC_SLOW 10
-#define IGDNG_P2_SDVO_DAC_FAST 5
-#define IGDNG_P2_LVDS_SLOW    14 /* single channel */
-#define IGDNG_P2_LVDS_FAST    7  /* double channel */
-#define IGDNG_P2_DOT_LIMIT    225000 /* 225Mhz */
+#define IRONLAKE_DOT_MIN         25000
+#define IRONLAKE_DOT_MAX         350000
+#define IRONLAKE_VCO_MIN         1760000
+#define IRONLAKE_VCO_MAX         3510000
+#define IRONLAKE_M1_MIN          12
+#define IRONLAKE_M1_MAX          22
+#define IRONLAKE_M2_MIN          5
+#define IRONLAKE_M2_MAX          9
+#define IRONLAKE_P2_DOT_LIMIT    225000 /* 225Mhz */
+
+/* We have parameter ranges for different type of outputs. */
+
+/* DAC & HDMI Refclk 120Mhz */
+#define IRONLAKE_DAC_N_MIN	1
+#define IRONLAKE_DAC_N_MAX	5
+#define IRONLAKE_DAC_M_MIN	79
+#define IRONLAKE_DAC_M_MAX	127
+#define IRONLAKE_DAC_P_MIN	5
+#define IRONLAKE_DAC_P_MAX	80
+#define IRONLAKE_DAC_P1_MIN	1
+#define IRONLAKE_DAC_P1_MAX	8
+#define IRONLAKE_DAC_P2_SLOW	10
+#define IRONLAKE_DAC_P2_FAST	5
+
+/* LVDS single-channel 120Mhz refclk */
+#define IRONLAKE_LVDS_S_N_MIN	1
+#define IRONLAKE_LVDS_S_N_MAX	3
+#define IRONLAKE_LVDS_S_M_MIN	79
+#define IRONLAKE_LVDS_S_M_MAX	118
+#define IRONLAKE_LVDS_S_P_MIN	28
+#define IRONLAKE_LVDS_S_P_MAX	112
+#define IRONLAKE_LVDS_S_P1_MIN	2
+#define IRONLAKE_LVDS_S_P1_MAX	8
+#define IRONLAKE_LVDS_S_P2_SLOW	14
+#define IRONLAKE_LVDS_S_P2_FAST	14
+
+/* LVDS dual-channel 120Mhz refclk */
+#define IRONLAKE_LVDS_D_N_MIN	1
+#define IRONLAKE_LVDS_D_N_MAX	3
+#define IRONLAKE_LVDS_D_M_MIN	79
+#define IRONLAKE_LVDS_D_M_MAX	127
+#define IRONLAKE_LVDS_D_P_MIN	14
+#define IRONLAKE_LVDS_D_P_MAX	56
+#define IRONLAKE_LVDS_D_P1_MIN	2
+#define IRONLAKE_LVDS_D_P1_MAX	8
+#define IRONLAKE_LVDS_D_P2_SLOW	7
+#define IRONLAKE_LVDS_D_P2_FAST	7
+
+/* LVDS single-channel 100Mhz refclk */
+#define IRONLAKE_LVDS_S_SSC_N_MIN	1
+#define IRONLAKE_LVDS_S_SSC_N_MAX	2
+#define IRONLAKE_LVDS_S_SSC_M_MIN	79
+#define IRONLAKE_LVDS_S_SSC_M_MAX	126
+#define IRONLAKE_LVDS_S_SSC_P_MIN	28
+#define IRONLAKE_LVDS_S_SSC_P_MAX	112
+#define IRONLAKE_LVDS_S_SSC_P1_MIN	2
+#define IRONLAKE_LVDS_S_SSC_P1_MAX	8
+#define IRONLAKE_LVDS_S_SSC_P2_SLOW	14
+#define IRONLAKE_LVDS_S_SSC_P2_FAST	14
+
+/* LVDS dual-channel 100Mhz refclk */
+#define IRONLAKE_LVDS_D_SSC_N_MIN	1
+#define IRONLAKE_LVDS_D_SSC_N_MAX	3
+#define IRONLAKE_LVDS_D_SSC_M_MIN	79
+#define IRONLAKE_LVDS_D_SSC_M_MAX	126
+#define IRONLAKE_LVDS_D_SSC_P_MIN	14
+#define IRONLAKE_LVDS_D_SSC_P_MAX	42
+#define IRONLAKE_LVDS_D_SSC_P1_MIN	2
+#define IRONLAKE_LVDS_D_SSC_P1_MAX	6
+#define IRONLAKE_LVDS_D_SSC_P2_SLOW	7
+#define IRONLAKE_LVDS_D_SSC_P2_FAST	7
+
+/* DisplayPort */
+#define IRONLAKE_DP_N_MIN		1
+#define IRONLAKE_DP_N_MAX		2
+#define IRONLAKE_DP_M_MIN		81
+#define IRONLAKE_DP_M_MAX		90
+#define IRONLAKE_DP_P_MIN		10
+#define IRONLAKE_DP_P_MAX		20
+#define IRONLAKE_DP_P2_FAST		10
+#define IRONLAKE_DP_P2_SLOW		10
+#define IRONLAKE_DP_P2_LIMIT		0
+#define IRONLAKE_DP_P1_MIN		1
+#define IRONLAKE_DP_P1_MAX		2
 
 static bool
 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 		    int target, int refclk, intel_clock_t *best_clock);
 static bool
-intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-			    int target, int refclk, intel_clock_t *best_clock);
-static bool
 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 			int target, int refclk, intel_clock_t *best_clock);
-static bool
-intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-			int target, int refclk, intel_clock_t *best_clock);
 
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
 		      int target, int refclk, intel_clock_t *best_clock);
 static bool
-intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc,
-		      int target, int refclk, intel_clock_t *best_clock);
+intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc,
+			   int target, int refclk, intel_clock_t *best_clock);
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
         .dot = { .min = I8XX_DOT_MIN,		.max = I8XX_DOT_MAX },
@@ -294,7 +348,6 @@
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_SLOW,	.p2_fast = I8XX_P2_FAST },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
@@ -309,7 +362,6 @@
 	.p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
 		 .p2_slow = I8XX_P2_LVDS_SLOW,	.p2_fast = I8XX_P2_LVDS_FAST },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 	
 static const intel_limit_t intel_limits_i9xx_sdvo = {
@@ -324,7 +376,6 @@
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_lvds = {
@@ -342,7 +393,6 @@
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_FAST },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 
     /* below parameter and function is for G4X Chipset Family*/
@@ -360,7 +410,6 @@
 		 .p2_fast = G4X_P2_SDVO_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-	.find_reduced_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_hdmi = {
@@ -377,7 +426,6 @@
 		 .p2_fast = G4X_P2_HDMI_DAC_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-	.find_reduced_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
@@ -402,7 +450,6 @@
 		 .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-	.find_reduced_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
@@ -427,7 +474,6 @@
 		 .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
 	},
 	.find_pll = intel_g4x_find_best_PLL,
-	.find_reduced_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_display_port = {
@@ -453,74 +499,162 @@
         .find_pll = intel_find_pll_g4x_dp,
 };
 
-static const intel_limit_t intel_limits_igd_sdvo = {
+static const intel_limit_t intel_limits_pineview_sdvo = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX},
-        .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
-        .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
-        .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
-        .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
-        .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
+        .vco = { .min = PINEVIEW_VCO_MIN,		.max = PINEVIEW_VCO_MAX },
+        .n   = { .min = PINEVIEW_N_MIN,		.max = PINEVIEW_N_MAX },
+        .m   = { .min = PINEVIEW_M_MIN,		.max = PINEVIEW_M_MAX },
+        .m1  = { .min = PINEVIEW_M1_MIN,		.max = PINEVIEW_M1_MAX },
+        .m2  = { .min = PINEVIEW_M2_MIN,		.max = PINEVIEW_M2_MAX },
         .p   = { .min = I9XX_P_SDVO_DAC_MIN,    .max = I9XX_P_SDVO_DAC_MAX },
         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
 	.p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,	.p2_fast = I9XX_P2_SDVO_DAC_FAST },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 
-static const intel_limit_t intel_limits_igd_lvds = {
+static const intel_limit_t intel_limits_pineview_lvds = {
         .dot = { .min = I9XX_DOT_MIN,		.max = I9XX_DOT_MAX },
-        .vco = { .min = IGD_VCO_MIN,		.max = IGD_VCO_MAX },
-        .n   = { .min = IGD_N_MIN,		.max = IGD_N_MAX },
-        .m   = { .min = IGD_M_MIN,		.max = IGD_M_MAX },
-        .m1  = { .min = IGD_M1_MIN,		.max = IGD_M1_MAX },
-        .m2  = { .min = IGD_M2_MIN,		.max = IGD_M2_MAX },
-        .p   = { .min = IGD_P_LVDS_MIN,	.max = IGD_P_LVDS_MAX },
+        .vco = { .min = PINEVIEW_VCO_MIN,		.max = PINEVIEW_VCO_MAX },
+        .n   = { .min = PINEVIEW_N_MIN,		.max = PINEVIEW_N_MAX },
+        .m   = { .min = PINEVIEW_M_MIN,		.max = PINEVIEW_M_MAX },
+        .m1  = { .min = PINEVIEW_M1_MIN,		.max = PINEVIEW_M1_MAX },
+        .m2  = { .min = PINEVIEW_M2_MIN,		.max = PINEVIEW_M2_MAX },
+        .p   = { .min = PINEVIEW_P_LVDS_MIN,	.max = PINEVIEW_P_LVDS_MAX },
         .p1  = { .min = I9XX_P1_MIN,		.max = I9XX_P1_MAX },
-	/* IGD only supports single-channel mode. */
+	/* Pineview only supports single-channel mode. */
 	.p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
 		 .p2_slow = I9XX_P2_LVDS_SLOW,	.p2_fast = I9XX_P2_LVDS_SLOW },
 	.find_pll = intel_find_best_PLL,
-	.find_reduced_pll = intel_find_best_reduced_PLL,
 };
 
-static const intel_limit_t intel_limits_igdng_sdvo = {
-	.dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
-	.vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
-	.n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
-	.m   = { .min = IGDNG_M_MIN,            .max = IGDNG_M_MAX },
-	.m1  = { .min = IGDNG_M1_MIN,           .max = IGDNG_M1_MAX },
-	.m2  = { .min = IGDNG_M2_MIN,           .max = IGDNG_M2_MAX },
-	.p   = { .min = IGDNG_P_SDVO_DAC_MIN,   .max = IGDNG_P_SDVO_DAC_MAX },
-	.p1  = { .min = IGDNG_P1_MIN,           .max = IGDNG_P1_MAX },
-	.p2  = { .dot_limit = IGDNG_P2_DOT_LIMIT,
-		 .p2_slow = IGDNG_P2_SDVO_DAC_SLOW,
-		 .p2_fast = IGDNG_P2_SDVO_DAC_FAST },
-	.find_pll = intel_igdng_find_best_PLL,
+static const intel_limit_t intel_limits_ironlake_dac = {
+	.dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
+	.vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
+	.n   = { .min = IRONLAKE_DAC_N_MIN,        .max = IRONLAKE_DAC_N_MAX },
+	.m   = { .min = IRONLAKE_DAC_M_MIN,        .max = IRONLAKE_DAC_M_MAX },
+	.m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
+	.m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
+	.p   = { .min = IRONLAKE_DAC_P_MIN,	   .max = IRONLAKE_DAC_P_MAX },
+	.p1  = { .min = IRONLAKE_DAC_P1_MIN,       .max = IRONLAKE_DAC_P1_MAX },
+	.p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+		 .p2_slow = IRONLAKE_DAC_P2_SLOW,
+		 .p2_fast = IRONLAKE_DAC_P2_FAST },
+	.find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_single_lvds = {
+	.dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
+	.vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
+	.n   = { .min = IRONLAKE_LVDS_S_N_MIN,     .max = IRONLAKE_LVDS_S_N_MAX },
+	.m   = { .min = IRONLAKE_LVDS_S_M_MIN,     .max = IRONLAKE_LVDS_S_M_MAX },
+	.m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
+	.m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
+	.p   = { .min = IRONLAKE_LVDS_S_P_MIN,     .max = IRONLAKE_LVDS_S_P_MAX },
+	.p1  = { .min = IRONLAKE_LVDS_S_P1_MIN,    .max = IRONLAKE_LVDS_S_P1_MAX },
+	.p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+		 .p2_slow = IRONLAKE_LVDS_S_P2_SLOW,
+		 .p2_fast = IRONLAKE_LVDS_S_P2_FAST },
+	.find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_dual_lvds = {
+	.dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
+	.vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
+	.n   = { .min = IRONLAKE_LVDS_D_N_MIN,     .max = IRONLAKE_LVDS_D_N_MAX },
+	.m   = { .min = IRONLAKE_LVDS_D_M_MIN,     .max = IRONLAKE_LVDS_D_M_MAX },
+	.m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
+	.m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
+	.p   = { .min = IRONLAKE_LVDS_D_P_MIN,     .max = IRONLAKE_LVDS_D_P_MAX },
+	.p1  = { .min = IRONLAKE_LVDS_D_P1_MIN,    .max = IRONLAKE_LVDS_D_P1_MAX },
+	.p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+		 .p2_slow = IRONLAKE_LVDS_D_P2_SLOW,
+		 .p2_fast = IRONLAKE_LVDS_D_P2_FAST },
+	.find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
+	.dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
+	.vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
+	.n   = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX },
+	.m   = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX },
+	.m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
+	.m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
+	.p   = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX },
+	.p1  = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX },
+	.p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+		 .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW,
+		 .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST },
+	.find_pll = intel_g4x_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
+	.dot = { .min = IRONLAKE_DOT_MIN,          .max = IRONLAKE_DOT_MAX },
+	.vco = { .min = IRONLAKE_VCO_MIN,          .max = IRONLAKE_VCO_MAX },
+	.n   = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX },
+	.m   = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX },
+	.m1  = { .min = IRONLAKE_M1_MIN,           .max = IRONLAKE_M1_MAX },
+	.m2  = { .min = IRONLAKE_M2_MIN,           .max = IRONLAKE_M2_MAX },
+	.p   = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX },
+	.p1  = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX },
+	.p2  = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+		 .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW,
+		 .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST },
+	.find_pll = intel_g4x_find_best_PLL,
 };
 
-static const intel_limit_t intel_limits_igdng_lvds = {
-	.dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
-	.vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
-	.n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
-	.m   = { .min = IGDNG_M_MIN,            .max = IGDNG_M_MAX },
-	.m1  = { .min = IGDNG_M1_MIN,           .max = IGDNG_M1_MAX },
-	.m2  = { .min = IGDNG_M2_MIN,           .max = IGDNG_M2_MAX },
-	.p   = { .min = IGDNG_P_LVDS_MIN,       .max = IGDNG_P_LVDS_MAX },
-	.p1  = { .min = IGDNG_P1_MIN,           .max = IGDNG_P1_MAX },
-	.p2  = { .dot_limit = IGDNG_P2_DOT_LIMIT,
-		 .p2_slow = IGDNG_P2_LVDS_SLOW,
-		 .p2_fast = IGDNG_P2_LVDS_FAST },
-	.find_pll = intel_igdng_find_best_PLL,
+static const intel_limit_t intel_limits_ironlake_display_port = {
+        .dot = { .min = IRONLAKE_DOT_MIN,
+                 .max = IRONLAKE_DOT_MAX },
+        .vco = { .min = IRONLAKE_VCO_MIN,
+                 .max = IRONLAKE_VCO_MAX},
+        .n   = { .min = IRONLAKE_DP_N_MIN,
+                 .max = IRONLAKE_DP_N_MAX },
+        .m   = { .min = IRONLAKE_DP_M_MIN,
+                 .max = IRONLAKE_DP_M_MAX },
+        .m1  = { .min = IRONLAKE_M1_MIN,
+                 .max = IRONLAKE_M1_MAX },
+        .m2  = { .min = IRONLAKE_M2_MIN,
+                 .max = IRONLAKE_M2_MAX },
+        .p   = { .min = IRONLAKE_DP_P_MIN,
+                 .max = IRONLAKE_DP_P_MAX },
+        .p1  = { .min = IRONLAKE_DP_P1_MIN,
+                 .max = IRONLAKE_DP_P1_MAX},
+        .p2  = { .dot_limit = IRONLAKE_DP_P2_LIMIT,
+                 .p2_slow = IRONLAKE_DP_P2_SLOW,
+                 .p2_fast = IRONLAKE_DP_P2_FAST },
+        .find_pll = intel_find_pll_ironlake_dp,
 };
 
-static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc)
+static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	const intel_limit_t *limit;
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-		limit = &intel_limits_igdng_lvds;
+	int refclk = 120;
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100)
+			refclk = 100;
+
+		if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
+		    LVDS_CLKB_POWER_UP) {
+			/* LVDS dual channel */
+			if (refclk == 100)
+				limit = &intel_limits_ironlake_dual_lvds_100m;
+			else
+				limit = &intel_limits_ironlake_dual_lvds;
+		} else {
+			if (refclk == 100)
+				limit = &intel_limits_ironlake_single_lvds_100m;
+			else
+				limit = &intel_limits_ironlake_single_lvds;
+		}
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+			HAS_eDP)
+		limit = &intel_limits_ironlake_display_port;
 	else
-		limit = &intel_limits_igdng_sdvo;
+		limit = &intel_limits_ironlake_dac;
 
 	return limit;
 }
@@ -557,20 +691,20 @@
 	struct drm_device *dev = crtc->dev;
 	const intel_limit_t *limit;
 
-	if (IS_IGDNG(dev))
-		limit = intel_igdng_limit(crtc);
+	if (HAS_PCH_SPLIT(dev))
+		limit = intel_ironlake_limit(crtc);
 	else if (IS_G4X(dev)) {
 		limit = intel_g4x_limit(crtc);
-	} else if (IS_I9XX(dev) && !IS_IGD(dev)) {
+	} else if (IS_I9XX(dev) && !IS_PINEVIEW(dev)) {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
 			limit = &intel_limits_i9xx_lvds;
 		else
 			limit = &intel_limits_i9xx_sdvo;
-	} else if (IS_IGD(dev)) {
+	} else if (IS_PINEVIEW(dev)) {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits_igd_lvds;
+			limit = &intel_limits_pineview_lvds;
 		else
-			limit = &intel_limits_igd_sdvo;
+			limit = &intel_limits_pineview_sdvo;
 	} else {
 		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
 			limit = &intel_limits_i8xx_lvds;
@@ -580,8 +714,8 @@
 	return limit;
 }
 
-/* m1 is reserved as 0 in IGD, n is a ring counter */
-static void igd_clock(int refclk, intel_clock_t *clock)
+/* m1 is reserved as 0 in Pineview, n is a ring counter */
+static void pineview_clock(int refclk, intel_clock_t *clock)
 {
 	clock->m = clock->m2 + 2;
 	clock->p = clock->p1 * clock->p2;
@@ -591,8 +725,8 @@
 
 static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
 {
-	if (IS_IGD(dev)) {
-		igd_clock(refclk, clock);
+	if (IS_PINEVIEW(dev)) {
+		pineview_clock(refclk, clock);
 		return;
 	}
 	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
@@ -657,7 +791,7 @@
 		INTELPllInvalid ("m2 out of range\n");
 	if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
 		INTELPllInvalid ("m1 out of range\n");
-	if (clock->m1 <= clock->m2 && !IS_IGD(dev))
+	if (clock->m1 <= clock->m2 && !IS_PINEVIEW(dev))
 		INTELPllInvalid ("m1 <= m2\n");
 	if (clock->m   < limit->m.min   || limit->m.max   < clock->m)
 		INTELPllInvalid ("m out of range\n");
@@ -706,16 +840,17 @@
 
 	memset (best_clock, 0, sizeof (*best_clock));
 
-	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-		for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
-		     clock.m1++) {
-			for (clock.m2 = limit->m2.min;
-			     clock.m2 <= limit->m2.max; clock.m2++) {
-				/* m1 is always 0 in IGD */
-				if (clock.m2 >= clock.m1 && !IS_IGD(dev))
-					break;
-				for (clock.n = limit->n.min;
-				     clock.n <= limit->n.max; clock.n++) {
+	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+	     clock.m1++) {
+		for (clock.m2 = limit->m2.min;
+		     clock.m2 <= limit->m2.max; clock.m2++) {
+			/* m1 is always 0 in Pineview */
+			if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev))
+				break;
+			for (clock.n = limit->n.min;
+			     clock.n <= limit->n.max; clock.n++) {
+				for (clock.p1 = limit->p1.min;
+					clock.p1 <= limit->p1.max; clock.p1++) {
 					int this_err;
 
 					intel_clock(dev, refclk, &clock);
@@ -736,46 +871,6 @@
 	return (err != target);
 }
 
-
-static bool
-intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-			    int target, int refclk, intel_clock_t *best_clock)
-
-{
-	struct drm_device *dev = crtc->dev;
-	intel_clock_t clock;
-	int err = target;
-	bool found = false;
-
-	memcpy(&clock, best_clock, sizeof(intel_clock_t));
-
-	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
-		for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
-			/* m1 is always 0 in IGD */
-			if (clock.m2 >= clock.m1 && !IS_IGD(dev))
-				break;
-			for (clock.n = limit->n.min; clock.n <= limit->n.max;
-			     clock.n++) {
-				int this_err;
-
-				intel_clock(dev, refclk, &clock);
-
-				if (!intel_PLL_is_valid(crtc, &clock))
-					continue;
-
-				this_err = abs(clock.dot - target);
-				if (this_err < err) {
-					*best_clock = clock;
-					err = this_err;
-					found = true;
-				}
-			}
-		}
-	}
-
-	return found;
-}
-
 static bool
 intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 			int target, int refclk, intel_clock_t *best_clock)
@@ -785,12 +880,18 @@
 	intel_clock_t clock;
 	int max_n;
 	bool found;
-	/* approximately equals target * 0.00488 */
-	int err_most = (target >> 8) + (target >> 10);
+	/* approximately equals target * 0.00585 */
+	int err_most = (target >> 8) + (target >> 9);
 	found = false;
 
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+		int lvds_reg;
+
+		if (IS_IRONLAKE(dev))
+			lvds_reg = PCH_LVDS;
+		else
+			lvds_reg = LVDS;
+		if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
 		    LVDS_CLKB_POWER_UP)
 			clock.p2 = limit->p2.p2_fast;
 		else
@@ -833,11 +934,16 @@
 }
 
 static bool
-intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
-		      int target, int refclk, intel_clock_t *best_clock)
+intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+			   int target, int refclk, intel_clock_t *best_clock)
 {
 	struct drm_device *dev = crtc->dev;
 	intel_clock_t clock;
+
+	/* return directly when it is eDP */
+	if (HAS_eDP)
+		return true;
+
 	if (target < 200000) {
 		clock.n = 1;
 		clock.p1 = 2;
@@ -856,68 +962,6 @@
 	return true;
 }
 
-static bool
-intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-			int target, int refclk, intel_clock_t *best_clock)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	intel_clock_t clock;
-	int err_most = 47;
-	int err_min = 10000;
-
-	/* eDP has only 2 clock choice, no n/m/p setting */
-	if (HAS_eDP)
-		return true;
-
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-		return intel_find_pll_igdng_dp(limit, crtc, target,
-					       refclk, best_clock);
-
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
-		    LVDS_CLKB_POWER_UP)
-			clock.p2 = limit->p2.p2_fast;
-		else
-			clock.p2 = limit->p2.p2_slow;
-	} else {
-		if (target < limit->p2.dot_limit)
-			clock.p2 = limit->p2.p2_slow;
-		else
-			clock.p2 = limit->p2.p2_fast;
-	}
-
-	memset(best_clock, 0, sizeof(*best_clock));
-	for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
-		/* based on hardware requriment prefer smaller n to precision */
-		for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
-			/* based on hardware requirment prefere larger m1,m2 */
-			for (clock.m1 = limit->m1.max;
-			     clock.m1 >= limit->m1.min; clock.m1--) {
-				for (clock.m2 = limit->m2.max;
-				     clock.m2 >= limit->m2.min; clock.m2--) {
-					int this_err;
-
-					intel_clock(dev, refclk, &clock);
-					if (!intel_PLL_is_valid(crtc, &clock))
-						continue;
-					this_err = abs((10000 - (target*10000/clock.dot)));
-					if (this_err < err_most) {
-						*best_clock = clock;
-						/* found on first matching */
-						goto out;
-					} else if (this_err < err_min) {
-						*best_clock = clock;
-						err_min = this_err;
-					}
-				}
-			}
-		}
-	}
-out:
-	return true;
-}
-
 /* DisplayPort has only two frequencies, 162MHz and 270MHz */
 static bool
 intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
@@ -949,7 +993,7 @@
 intel_wait_for_vblank(struct drm_device *dev)
 {
 	/* Wait for 20ms, i.e. one cycle at 50hz. */
-	mdelay(20);
+	msleep(20);
 }
 
 /* Parameters have changed, update FBC info */
@@ -988,13 +1032,15 @@
 
 	/* enable it... */
 	fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
+	if (IS_I945GM(dev))
+		fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */
 	fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
 	fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
 	if (obj_priv->tiling_mode != I915_TILING_NONE)
 		fbc_ctl |= dev_priv->cfb_fence;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 
-	DRM_DEBUG("enabled FBC, pitch %ld, yoff %d, plane %d, ",
+	DRM_DEBUG_KMS("enabled FBC, pitch %ld, yoff %d, plane %d, ",
 		  dev_priv->cfb_pitch, crtc->y, dev_priv->cfb_plane);
 }
 
@@ -1017,7 +1063,7 @@
 
 	intel_wait_for_vblank(dev);
 
-	DRM_DEBUG("disabled FBC\n");
+	DRM_DEBUG_KMS("disabled FBC\n");
 }
 
 static bool i8xx_fbc_enabled(struct drm_crtc *crtc)
@@ -1062,7 +1108,7 @@
 	/* enable it... */
 	I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
 
-	DRM_DEBUG("enabled fbc on plane %d\n", intel_crtc->plane);
+	DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
 }
 
 void g4x_disable_fbc(struct drm_device *dev)
@@ -1076,7 +1122,7 @@
 	I915_WRITE(DPFC_CONTROL, dpfc_ctl);
 	intel_wait_for_vblank(dev);
 
-	DRM_DEBUG("disabled FBC\n");
+	DRM_DEBUG_KMS("disabled FBC\n");
 }
 
 static bool g4x_fbc_enabled(struct drm_crtc *crtc)
@@ -1115,8 +1161,12 @@
 	struct drm_framebuffer *fb = crtc->fb;
 	struct intel_framebuffer *intel_fb;
 	struct drm_i915_gem_object *obj_priv;
+	struct drm_crtc *tmp_crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane;
+	int crtcs_enabled = 0;
+
+	DRM_DEBUG_KMS("\n");
 
 	if (!i915_powersave)
 		return;
@@ -1136,30 +1186,42 @@
 	 * If FBC is already on, we just have to verify that we can
 	 * keep it that way...
 	 * Need to disable if:
+	 *   - more than one pipe is active
 	 *   - changing FBC params (stride, fence, mode)
 	 *   - new fb is too large to fit in compressed buffer
 	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
 	 */
+	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+		if (tmp_crtc->enabled)
+			crtcs_enabled++;
+	}
+	DRM_DEBUG_KMS("%d pipes active\n", crtcs_enabled);
+	if (crtcs_enabled > 1) {
+		DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
+		goto out_disable;
+	}
 	if (intel_fb->obj->size > dev_priv->cfb_size) {
-		DRM_DEBUG("framebuffer too large, disabling compression\n");
+		DRM_DEBUG_KMS("framebuffer too large, disabling "
+				"compression\n");
 		goto out_disable;
 	}
 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
 	    (mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
-		DRM_DEBUG("mode incompatible with compression, disabling\n");
+		DRM_DEBUG_KMS("mode incompatible with compression, "
+				"disabling\n");
 		goto out_disable;
 	}
 	if ((mode->hdisplay > 2048) ||
 	    (mode->vdisplay > 1536)) {
-		DRM_DEBUG("mode too large for compression, disabling\n");
+		DRM_DEBUG_KMS("mode too large for compression, disabling\n");
 		goto out_disable;
 	}
 	if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
-		DRM_DEBUG("plane not 0, disabling compression\n");
+		DRM_DEBUG_KMS("plane not 0, disabling compression\n");
 		goto out_disable;
 	}
 	if (obj_priv->tiling_mode != I915_TILING_X) {
-		DRM_DEBUG("framebuffer not tiled, disabling compression\n");
+		DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
 		goto out_disable;
 	}
 
@@ -1181,13 +1243,57 @@
 	return;
 
 out_disable:
-	DRM_DEBUG("unsupported config, disabling FBC\n");
+	DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
 	/* Multiple disables should be harmless */
 	if (dev_priv->display.fbc_enabled(crtc))
 		dev_priv->display.disable_fbc(dev);
 }
 
 static int
+intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
+{
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	u32 alignment;
+	int ret;
+
+	switch (obj_priv->tiling_mode) {
+	case I915_TILING_NONE:
+		alignment = 64 * 1024;
+		break;
+	case I915_TILING_X:
+		/* pin() will align the object as required by fence */
+		alignment = 0;
+		break;
+	case I915_TILING_Y:
+		/* FIXME: Is this true? */
+		DRM_ERROR("Y tiled not allowed for scan out buffers\n");
+		return -EINVAL;
+	default:
+		BUG();
+	}
+
+	ret = i915_gem_object_pin(obj, alignment);
+	if (ret != 0)
+		return ret;
+
+	/* Install a fence for tiled scan-out. Pre-i965 always needs a
+	 * fence, whereas 965+ only requires a fence if using
+	 * framebuffer compression.  For simplicity, we always install
+	 * a fence as the cost is not that onerous.
+	 */
+	if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
+	    obj_priv->tiling_mode != I915_TILING_NONE) {
+		ret = i915_gem_object_get_fence_reg(obj);
+		if (ret != 0) {
+			i915_gem_object_unpin(obj);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		    struct drm_framebuffer *old_fb)
 {
@@ -1206,12 +1312,12 @@
 	int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
 	int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
 	int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
-	u32 dspcntr, alignment;
+	u32 dspcntr;
 	int ret;
 
 	/* no fb bound */
 	if (!crtc->fb) {
-		DRM_DEBUG("No FB bound\n");
+		DRM_DEBUG_KMS("No FB bound\n");
 		return 0;
 	}
 
@@ -1228,50 +1334,20 @@
 	obj = intel_fb->obj;
 	obj_priv = obj->driver_private;
 
-	switch (obj_priv->tiling_mode) {
-	case I915_TILING_NONE:
-		alignment = 64 * 1024;
-		break;
-	case I915_TILING_X:
-		/* pin() will align the object as required by fence */
-		alignment = 0;
-		break;
-	case I915_TILING_Y:
-		/* FIXME: Is this true? */
-		DRM_ERROR("Y tiled not allowed for scan out buffers\n");
-		return -EINVAL;
-	default:
-		BUG();
-	}
-
 	mutex_lock(&dev->struct_mutex);
-	ret = i915_gem_object_pin(obj, alignment);
+	ret = intel_pin_and_fence_fb_obj(dev, obj);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
-	ret = i915_gem_object_set_to_gtt_domain(obj, 1);
+	ret = i915_gem_object_set_to_display_plane(obj);
 	if (ret != 0) {
 		i915_gem_object_unpin(obj);
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
-	/* Install a fence for tiled scan-out. Pre-i965 always needs a fence,
-	 * whereas 965+ only requires a fence if using framebuffer compression.
-	 * For simplicity, we always install a fence as the cost is not that onerous.
-	 */
-	if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-	    obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj);
-		if (ret != 0) {
-			i915_gem_object_unpin(obj);
-			mutex_unlock(&dev->struct_mutex);
-			return ret;
-		}
-	}
-
 	dspcntr = I915_READ(dspcntr_reg);
 	/* Mask out pixel format bits in case we change it */
 	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
@@ -1287,7 +1363,10 @@
 		break;
 	case 24:
 	case 32:
-		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		if (crtc->fb->depth == 30)
+			dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
+		else
+			dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
 		DRM_ERROR("Unknown color depth\n");
@@ -1302,7 +1381,7 @@
 			dspcntr &= ~DISPPLANE_TILED;
 	}
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		/* must disable */
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
@@ -1311,7 +1390,7 @@
 	Start = obj_priv->gtt_offset;
 	Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 
-	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+	DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
 	I915_WRITE(dspstride, crtc->fb->pitch);
 	if (IS_I965G(dev)) {
 		I915_WRITE(dspbase, Offset);
@@ -1363,7 +1442,7 @@
 	u8 sr1;
 	u32 vga_reg;
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		vga_reg = CPU_VGACNTRL;
 	else
 		vga_reg = VGACNTRL;
@@ -1379,19 +1458,19 @@
 	I915_WRITE(vga_reg, VGA_DISP_DISABLE);
 }
 
-static void igdng_disable_pll_edp (struct drm_crtc *crtc)
+static void ironlake_disable_pll_edp (struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 	dpa_ctl = I915_READ(DP_A);
 	dpa_ctl &= ~DP_PLL_ENABLE;
 	I915_WRITE(DP_A, dpa_ctl);
 }
 
-static void igdng_enable_pll_edp (struct drm_crtc *crtc)
+static void ironlake_enable_pll_edp (struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1400,17 +1479,18 @@
 	dpa_ctl = I915_READ(DP_A);
 	dpa_ctl |= DP_PLL_ENABLE;
 	I915_WRITE(DP_A, dpa_ctl);
+	POSTING_READ(DP_A);
 	udelay(200);
 }
 
 
-static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock)
+static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
-	DRM_DEBUG("eDP PLL enable for clock %d\n", clock);
+	DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock);
 	dpa_ctl = I915_READ(DP_A);
 	dpa_ctl &= ~DP_PLL_FREQ_MASK;
 
@@ -1440,7 +1520,7 @@
 	udelay(500);
 }
 
-static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
+static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1473,6 +1553,10 @@
 	int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
 	u32 temp;
 	int tries = 5, j, n;
+	u32 pipe_bpc;
+
+	temp = I915_READ(pipeconf_reg);
+	pipe_bpc = temp & PIPE_BPC_MASK;
 
 	/* XXX: When our outputs are all unaware of DPMS modes other than off
 	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
@@ -1481,10 +1565,19 @@
 	case DRM_MODE_DPMS_ON:
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
-		DRM_DEBUG("crtc %d dpms on\n", pipe);
+		DRM_DEBUG_KMS("crtc %d dpms on\n", pipe);
+
+		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+			temp = I915_READ(PCH_LVDS);
+			if ((temp & LVDS_PORT_EN) == 0) {
+				I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
+				POSTING_READ(PCH_LVDS);
+			}
+		}
+
 		if (HAS_eDP) {
 			/* enable eDP PLL */
-			igdng_enable_pll_edp(crtc);
+			ironlake_enable_pll_edp(crtc);
 		} else {
 			/* enable PCH DPLL */
 			temp = I915_READ(pch_dpll_reg);
@@ -1495,13 +1588,19 @@
 
 			/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
 			temp = I915_READ(fdi_rx_reg);
+			/*
+			 * make the BPC in FDI Rx be consistent with that in
+			 * pipeconf reg.
+			 */
+			temp &= ~(0x7 << 16);
+			temp |= (pipe_bpc << 11);
 			I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
 					FDI_SEL_PCDCLK |
 					FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
 			I915_READ(fdi_rx_reg);
 			udelay(200);
 
-			/* Enable CPU FDI TX PLL, always on for IGDNG */
+			/* Enable CPU FDI TX PLL, always on for Ironlake */
 			temp = I915_READ(fdi_tx_reg);
 			if ((temp & FDI_TX_PLL_ENABLE) == 0) {
 				I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
@@ -1568,12 +1667,13 @@
 			udelay(150);
 
 			temp = I915_READ(fdi_rx_iir_reg);
-			DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+			DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
 
 			if ((temp & FDI_RX_BIT_LOCK) == 0) {
 				for (j = 0; j < tries; j++) {
 					temp = I915_READ(fdi_rx_iir_reg);
-					DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+					DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n",
+								temp);
 					if (temp & FDI_RX_BIT_LOCK)
 						break;
 					udelay(200);
@@ -1582,11 +1682,11 @@
 					I915_WRITE(fdi_rx_iir_reg,
 							temp | FDI_RX_BIT_LOCK);
 				else
-					DRM_DEBUG("train 1 fail\n");
+					DRM_DEBUG_KMS("train 1 fail\n");
 			} else {
 				I915_WRITE(fdi_rx_iir_reg,
 						temp | FDI_RX_BIT_LOCK);
-				DRM_DEBUG("train 1 ok 2!\n");
+				DRM_DEBUG_KMS("train 1 ok 2!\n");
 			}
 			temp = I915_READ(fdi_tx_reg);
 			temp &= ~FDI_LINK_TRAIN_NONE;
@@ -1601,12 +1701,13 @@
 			udelay(150);
 
 			temp = I915_READ(fdi_rx_iir_reg);
-			DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+			DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
 
 			if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
 				for (j = 0; j < tries; j++) {
 					temp = I915_READ(fdi_rx_iir_reg);
-					DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+					DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n",
+								temp);
 					if (temp & FDI_RX_SYMBOL_LOCK)
 						break;
 					udelay(200);
@@ -1614,15 +1715,15 @@
 				if (j != tries) {
 					I915_WRITE(fdi_rx_iir_reg,
 							temp | FDI_RX_SYMBOL_LOCK);
-					DRM_DEBUG("train 2 ok 1!\n");
+					DRM_DEBUG_KMS("train 2 ok 1!\n");
 				} else
-					DRM_DEBUG("train 2 fail\n");
+					DRM_DEBUG_KMS("train 2 fail\n");
 			} else {
 				I915_WRITE(fdi_rx_iir_reg,
 						temp | FDI_RX_SYMBOL_LOCK);
-				DRM_DEBUG("train 2 ok 2!\n");
+				DRM_DEBUG_KMS("train 2 ok 2!\n");
 			}
-			DRM_DEBUG("train done\n");
+			DRM_DEBUG_KMS("train done\n");
 
 			/* set transcoder timing */
 			I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
@@ -1635,6 +1736,12 @@
 
 			/* enable PCH transcoder */
 			temp = I915_READ(transconf_reg);
+			/*
+			 * make the BPC in transcoder be consistent with
+			 * that in pipeconf reg.
+			 */
+			temp &= ~PIPE_BPC_MASK;
+			temp |= pipe_bpc;
 			I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
 			I915_READ(transconf_reg);
 
@@ -1664,10 +1771,9 @@
 
 	break;
 	case DRM_MODE_DPMS_OFF:
-		DRM_DEBUG("crtc %d dpms off\n", pipe);
-
-		i915_disable_vga(dev);
+		DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
 
+		drm_vblank_off(dev, pipe);
 		/* Disable display plane */
 		temp = I915_READ(dspcntr_reg);
 		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
@@ -1677,6 +1783,8 @@
 			I915_READ(dspbase_reg);
 		}
 
+		i915_disable_vga(dev);
+
 		/* disable cpu pipe, disable after all planes disabled */
 		temp = I915_READ(pipeconf_reg);
 		if ((temp & PIPEACONF_ENABLE) != 0) {
@@ -1690,16 +1798,23 @@
 					udelay(500);
 					continue;
 				} else {
-					DRM_DEBUG("pipe %d off delay\n", pipe);
+					DRM_DEBUG_KMS("pipe %d off delay\n",
+								pipe);
 					break;
 				}
 			}
 		} else
-			DRM_DEBUG("crtc %d is disabled\n", pipe);
+			DRM_DEBUG_KMS("crtc %d is disabled\n", pipe);
 
-		if (HAS_eDP) {
-			igdng_disable_pll_edp(crtc);
+		udelay(100);
+
+		/* Disable PF */
+		temp = I915_READ(pf_ctl_reg);
+		if ((temp & PF_ENABLE) != 0) {
+			I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
+			I915_READ(pf_ctl_reg);
 		}
+		I915_WRITE(pf_win_size, 0);
 
 		/* disable CPU FDI tx and PCH FDI rx */
 		temp = I915_READ(fdi_tx_reg);
@@ -1707,6 +1822,9 @@
 		I915_READ(fdi_tx_reg);
 
 		temp = I915_READ(fdi_rx_reg);
+		/* BPC in FDI rx is consistent with that in pipeconf */
+		temp &= ~(0x07 << 16);
+		temp |= (pipe_bpc << 11);
 		I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
 		I915_READ(fdi_rx_reg);
 
@@ -1725,6 +1843,13 @@
 
 		udelay(100);
 
+		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+			temp = I915_READ(PCH_LVDS);
+			I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
+			I915_READ(PCH_LVDS);
+			udelay(100);
+		}
+
 		/* disable PCH transcoder */
 		temp = I915_READ(transconf_reg);
 		if ((temp & TRANS_ENABLE) != 0) {
@@ -1738,11 +1863,19 @@
 					udelay(500);
 					continue;
 				} else {
-					DRM_DEBUG("transcoder %d off delay\n", pipe);
+					DRM_DEBUG_KMS("transcoder %d off "
+							"delay\n", pipe);
 					break;
 				}
 			}
 		}
+		temp = I915_READ(transconf_reg);
+		/* BPC in transcoder is consistent with that in pipeconf */
+		temp &= ~PIPE_BPC_MASK;
+		temp |= pipe_bpc;
+		I915_WRITE(transconf_reg, temp);
+		I915_READ(transconf_reg);
+		udelay(100);
 
 		/* disable PCH DPLL */
 		temp = I915_READ(pch_dpll_reg);
@@ -1751,14 +1884,20 @@
 			I915_READ(pch_dpll_reg);
 		}
 
-		temp = I915_READ(fdi_rx_reg);
-		if ((temp & FDI_RX_PLL_ENABLE) != 0) {
-			temp &= ~FDI_SEL_PCDCLK;
-			temp &= ~FDI_RX_PLL_ENABLE;
-			I915_WRITE(fdi_rx_reg, temp);
-			I915_READ(fdi_rx_reg);
+		if (HAS_eDP) {
+			ironlake_disable_pll_edp(crtc);
 		}
 
+		temp = I915_READ(fdi_rx_reg);
+		temp &= ~FDI_SEL_PCDCLK;
+		I915_WRITE(fdi_rx_reg, temp);
+		I915_READ(fdi_rx_reg);
+
+		temp = I915_READ(fdi_rx_reg);
+		temp &= ~FDI_RX_PLL_ENABLE;
+		I915_WRITE(fdi_rx_reg, temp);
+		I915_READ(fdi_rx_reg);
+
 		/* Disable CPU FDI TX PLL */
 		temp = I915_READ(fdi_tx_reg);
 		if ((temp & FDI_TX_PLL_ENABLE) != 0) {
@@ -1767,20 +1906,43 @@
 			udelay(100);
 		}
 
-		/* Disable PF */
-		temp = I915_READ(pf_ctl_reg);
-		if ((temp & PF_ENABLE) != 0) {
-			I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
-			I915_READ(pf_ctl_reg);
-		}
-		I915_WRITE(pf_win_size, 0);
-
 		/* Wait for the clocks to turn off. */
-		udelay(150);
+		udelay(100);
 		break;
 	}
 }
 
+static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
+{
+	struct intel_overlay *overlay;
+	int ret;
+
+	if (!enable && intel_crtc->overlay) {
+		overlay = intel_crtc->overlay;
+		mutex_lock(&overlay->dev->struct_mutex);
+		for (;;) {
+			ret = intel_overlay_switch_off(overlay);
+			if (ret == 0)
+				break;
+
+			ret = intel_overlay_recover_from_interrupt(overlay, 0);
+			if (ret != 0) {
+				/* overlay doesn't react anymore. Usually
+				 * results in a black screen and an unkillable
+				 * X server. */
+				BUG();
+				overlay->hw_wedged = HW_WEDGED;
+				break;
+			}
+		}
+		mutex_unlock(&overlay->dev->struct_mutex);
+	}
+	/* Let userspace switch the overlay on again. In most cases userspace
+	 * has to recompute where to put it anyway. */
+
+	return;
+}
+
 static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct drm_device *dev = crtc->dev;
@@ -1839,12 +2001,14 @@
 			intel_update_fbc(crtc, &crtc->mode);
 
 		/* Give the overlay scaler a chance to enable if it's on this pipe */
-		//intel_crtc_dpms_video(crtc, true); TODO
+		intel_crtc_dpms_overlay(intel_crtc, true);
 	break;
 	case DRM_MODE_DPMS_OFF:
 		intel_update_watermarks(dev);
+
 		/* Give the overlay scaler a chance to disable if it's on this pipe */
-		//intel_crtc_dpms_video(crtc, FALSE); TODO
+		intel_crtc_dpms_overlay(intel_crtc, false);
+		drm_vblank_off(dev, pipe);
 
 		if (dev_priv->cfb_plane == plane &&
 		    dev_priv->display.disable_fbc)
@@ -1904,6 +2068,9 @@
 	int pipe = intel_crtc->pipe;
 	bool enabled;
 
+	if (intel_crtc->dpms_mode == mode)
+		return;
+
 	dev_priv->display.dpms(crtc, mode);
 
 	intel_crtc->dpms_mode = mode;
@@ -1963,7 +2130,7 @@
 				  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		/* FDI link clock is fixed at 2.7G */
 		if (mode->clock * 3 > 27000 * 4)
 			return MODE_CLOCK_HIGH;
@@ -2039,7 +2206,7 @@
  * Return the pipe currently connected to the panel fitter,
  * or -1 if the panel fitter is not present or not in use
  */
-static int intel_panel_fitter_pipe (struct drm_device *dev)
+int intel_panel_fitter_pipe (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32  pfit_control;
@@ -2083,9 +2250,8 @@
 #define LINK_N 0x80000
 
 static void
-igdng_compute_m_n(int bits_per_pixel, int nlanes,
-		int pixel_clock, int link_clock,
-		struct fdi_m_n *m_n)
+ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
+		     int link_clock, struct fdi_m_n *m_n)
 {
 	u64 temp;
 
@@ -2113,34 +2279,34 @@
 	unsigned long cacheline_size;
 };
 
-/* IGD has different values for various configs */
-static struct intel_watermark_params igd_display_wm = {
-	IGD_DISPLAY_FIFO,
-	IGD_MAX_WM,
-	IGD_DFT_WM,
-	IGD_GUARD_WM,
-	IGD_FIFO_LINE_SIZE
+/* Pineview has different values for various configs */
+static struct intel_watermark_params pineview_display_wm = {
+	PINEVIEW_DISPLAY_FIFO,
+	PINEVIEW_MAX_WM,
+	PINEVIEW_DFT_WM,
+	PINEVIEW_GUARD_WM,
+	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params igd_display_hplloff_wm = {
-	IGD_DISPLAY_FIFO,
-	IGD_MAX_WM,
-	IGD_DFT_HPLLOFF_WM,
-	IGD_GUARD_WM,
-	IGD_FIFO_LINE_SIZE
+static struct intel_watermark_params pineview_display_hplloff_wm = {
+	PINEVIEW_DISPLAY_FIFO,
+	PINEVIEW_MAX_WM,
+	PINEVIEW_DFT_HPLLOFF_WM,
+	PINEVIEW_GUARD_WM,
+	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params igd_cursor_wm = {
-	IGD_CURSOR_FIFO,
-	IGD_CURSOR_MAX_WM,
-	IGD_CURSOR_DFT_WM,
-	IGD_CURSOR_GUARD_WM,
-	IGD_FIFO_LINE_SIZE,
+static struct intel_watermark_params pineview_cursor_wm = {
+	PINEVIEW_CURSOR_FIFO,
+	PINEVIEW_CURSOR_MAX_WM,
+	PINEVIEW_CURSOR_DFT_WM,
+	PINEVIEW_CURSOR_GUARD_WM,
+	PINEVIEW_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params igd_cursor_hplloff_wm = {
-	IGD_CURSOR_FIFO,
-	IGD_CURSOR_MAX_WM,
-	IGD_CURSOR_DFT_WM,
-	IGD_CURSOR_GUARD_WM,
-	IGD_FIFO_LINE_SIZE
+static struct intel_watermark_params pineview_cursor_hplloff_wm = {
+	PINEVIEW_CURSOR_FIFO,
+	PINEVIEW_CURSOR_MAX_WM,
+	PINEVIEW_CURSOR_DFT_WM,
+	PINEVIEW_CURSOR_GUARD_WM,
+	PINEVIEW_FIFO_LINE_SIZE
 };
 static struct intel_watermark_params g4x_wm_info = {
 	G4X_FIFO_SIZE,
@@ -2213,11 +2379,11 @@
 		1000;
 	entries_required /= wm->cacheline_size;
 
-	DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
+	DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required);
 
 	wm_size = wm->fifo_size - (entries_required + wm->guard_size);
 
-	DRM_DEBUG("FIFO watermark level: %d\n", wm_size);
+	DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size);
 
 	/* Don't promote wm_size to unsigned... */
 	if (wm_size > (long)wm->max_wm)
@@ -2279,50 +2445,50 @@
 			return latency;
 	}
 
-	DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
+	DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
 
 	return NULL;
 }
 
-static void igd_disable_cxsr(struct drm_device *dev)
+static void pineview_disable_cxsr(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
 	/* deactivate cxsr */
 	reg = I915_READ(DSPFW3);
-	reg &= ~(IGD_SELF_REFRESH_EN);
+	reg &= ~(PINEVIEW_SELF_REFRESH_EN);
 	I915_WRITE(DSPFW3, reg);
 	DRM_INFO("Big FIFO is disabled\n");
 }
 
-static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
-			    int pixel_size)
+static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock,
+				 int pixel_size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 	unsigned long wm;
 	struct cxsr_latency *latency;
 
-	latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq,
+	latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
 		dev_priv->mem_freq);
 	if (!latency) {
-		DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
-		igd_disable_cxsr(dev);
+		DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
+		pineview_disable_cxsr(dev);
 		return;
 	}
 
 	/* Display SR */
-	wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size,
+	wm = intel_calculate_wm(clock, &pineview_display_wm, pixel_size,
 				latency->display_sr);
 	reg = I915_READ(DSPFW1);
 	reg &= 0x7fffff;
 	reg |= wm << 23;
 	I915_WRITE(DSPFW1, reg);
-	DRM_DEBUG("DSPFW1 register is %x\n", reg);
+	DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
 
 	/* cursor SR */
-	wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size,
+	wm = intel_calculate_wm(clock, &pineview_cursor_wm, pixel_size,
 				latency->cursor_sr);
 	reg = I915_READ(DSPFW3);
 	reg &= ~(0x3f << 24);
@@ -2330,7 +2496,7 @@
 	I915_WRITE(DSPFW3, reg);
 
 	/* Display HPLL off SR */
-	wm = intel_calculate_wm(clock, &igd_display_hplloff_wm,
+	wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
 		latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
 	reg = I915_READ(DSPFW3);
 	reg &= 0xfffffe00;
@@ -2338,17 +2504,17 @@
 	I915_WRITE(DSPFW3, reg);
 
 	/* cursor HPLL off SR */
-	wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size,
+	wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, pixel_size,
 				latency->cursor_hpll_disable);
 	reg = I915_READ(DSPFW3);
 	reg &= ~(0x3f << 16);
 	reg |= (wm & 0x3f) << 16;
 	I915_WRITE(DSPFW3, reg);
-	DRM_DEBUG("DSPFW3 register is %x\n", reg);
+	DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
 
 	/* activate cxsr */
 	reg = I915_READ(DSPFW3);
-	reg |= IGD_SELF_REFRESH_EN;
+	reg |= PINEVIEW_SELF_REFRESH_EN;
 	I915_WRITE(DSPFW3, reg);
 
 	DRM_INFO("Big FIFO is enabled\n");
@@ -2370,7 +2536,7 @@
  * A value of 5us seems to be a good balance; safe for very low end
  * platforms but not overly aggressive on lower latency configs.
  */
-const static int latency_ns = 5000;
+static const int latency_ns = 5000;
 
 static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
 {
@@ -2384,8 +2550,8 @@
 		size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) -
 			(dsparb & 0x7f);
 
-	DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
-		  size);
+	DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+			plane ? "B" : "A", size);
 
 	return size;
 }
@@ -2403,8 +2569,8 @@
 			(dsparb & 0x1ff);
 	size >>= 1; /* Convert to cachelines */
 
-	DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
-		  size);
+	DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+			plane ? "B" : "A", size);
 
 	return size;
 }
@@ -2418,7 +2584,8 @@
 	size = dsparb & 0x7f;
 	size >>= 2; /* Convert to cachelines */
 
-	DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
+	DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+			plane ? "B" : "A",
 		  size);
 
 	return size;
@@ -2433,8 +2600,8 @@
 	size = dsparb & 0x7f;
 	size >>= 1; /* Convert to cachelines */
 
-	DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
-		  size);
+	DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb,
+			plane ? "B" : "A", size);
 
 	return size;
 }
@@ -2480,7 +2647,7 @@
 	/* Calc sr entries for one plane configs */
 	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
 		/* self-refresh has much higher latency */
-		const static int sr_latency_ns = 12000;
+		static const int sr_latency_ns = 12000;
 
 		sr_clock = planea_clock ? planea_clock : planeb_clock;
 		line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2491,6 +2658,10 @@
 		sr_entries = roundup(sr_entries / cacheline_size, 1);
 		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
 		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+					& ~FW_BLC_SELF_EN);
 	}
 
 	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
@@ -2509,15 +2680,45 @@
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i965_update_wm(struct drm_device *dev, int unused, int unused2,
-			   int unused3, int unused4)
+static void i965_update_wm(struct drm_device *dev, int planea_clock,
+			   int planeb_clock, int sr_hdisplay, int pixel_size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long line_time_us;
+	int sr_clock, sr_entries, srwm = 1;
+
+	/* Calc sr entries for one plane configs */
+	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+		/* self-refresh has much higher latency */
+		static const int sr_latency_ns = 12000;
+
+		sr_clock = planea_clock ? planea_clock : planeb_clock;
+		line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+		/* Use ns/us then divide to preserve precision */
+		sr_entries = (((sr_latency_ns / line_time_us) + 1) *
+			      pixel_size * sr_hdisplay) / 1000;
+		sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1);
+		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
+		srwm = I945_FIFO_SIZE - sr_entries;
+		if (srwm < 0)
+			srwm = 1;
+		srwm &= 0x3f;
+		if (IS_I965GM(dev))
+			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		if (IS_I965GM(dev))
+			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+				   & ~FW_BLC_SELF_EN);
+	}
 
-	DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
+		      srwm);
 
 	/* 965 has limitations... */
-	I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
+	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) |
+		   (8 << 0));
 	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
 }
 
@@ -2553,7 +2754,7 @@
 				       pixel_size, latency_ns);
 	planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params,
 				       pixel_size, latency_ns);
-	DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
 	/*
 	 * Overlay gets an aggressive default since video jitter is bad.
@@ -2564,7 +2765,7 @@
 	if (HAS_FW_BLC(dev) && sr_hdisplay &&
 	    (!planea_clock || !planeb_clock)) {
 		/* self-refresh has much higher latency */
-		const static int sr_latency_ns = 6000;
+		static const int sr_latency_ns = 6000;
 
 		sr_clock = planea_clock ? planea_clock : planeb_clock;
 		line_time_us = ((sr_hdisplay * 1000) / sr_clock);
@@ -2573,14 +2774,18 @@
 		sr_entries = (((sr_latency_ns / line_time_us) + 1) *
 			      pixel_size * sr_hdisplay) / 1000;
 		sr_entries = roundup(sr_entries / cacheline_size, 1);
-		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
+		DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries);
 		srwm = total_size - sr_entries;
 		if (srwm < 0)
 			srwm = 1;
 		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
+	} else {
+		/* Turn off self refresh if both pipes are enabled */
+		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+					& ~FW_BLC_SELF_EN);
 	}
 
-	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
 		  planea_wm, planeb_wm, cwm, srwm);
 
 	fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
@@ -2607,7 +2812,7 @@
 				       pixel_size, latency_ns);
 	fwater_lo |= (3<<8) | planea_wm;
 
-	DRM_DEBUG("Setting FIFO watermarks - A: %d\n", planea_wm);
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
 
 	I915_WRITE(FW_BLC, fwater_lo);
 }
@@ -2661,11 +2866,11 @@
 		if (crtc->enabled) {
 			enabled++;
 			if (intel_crtc->plane == 0) {
-				DRM_DEBUG("plane A (pipe %d) clock: %d\n",
+				DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n",
 					  intel_crtc->pipe, crtc->mode.clock);
 				planea_clock = crtc->mode.clock;
 			} else {
-				DRM_DEBUG("plane B (pipe %d) clock: %d\n",
+				DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n",
 					  intel_crtc->pipe, crtc->mode.clock);
 				planeb_clock = crtc->mode.clock;
 			}
@@ -2682,10 +2887,10 @@
 		return;
 
 	/* Single plane configs can enable self refresh */
-	if (enabled == 1 && IS_IGD(dev))
-		igd_enable_cxsr(dev, sr_clock, pixel_size);
-	else if (IS_IGD(dev))
-		igd_disable_cxsr(dev);
+	if (enabled == 1 && IS_PINEVIEW(dev))
+		pineview_enable_cxsr(dev, sr_clock, pixel_size);
+	else if (IS_PINEVIEW(dev))
+		pineview_disable_cxsr(dev);
 
 	dev_priv->display.update_wm(dev, planea_clock, planeb_clock,
 				    sr_hdisplay, pixel_size);
@@ -2779,10 +2984,11 @@
 
 	if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
 		refclk = dev_priv->lvds_ssc_freq * 1000;
-		DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
+		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+					refclk / 1000);
 	} else if (IS_I9XX(dev)) {
 		refclk = 96000;
-		if (IS_IGDNG(dev))
+		if (HAS_PCH_SPLIT(dev))
 			refclk = 120000; /* 120Mhz refclk */
 	} else {
 		refclk = 48000;
@@ -2802,14 +3008,26 @@
 		return -EINVAL;
 	}
 
-	if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) {
-		memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
-		has_reduced_clock = limit->find_reduced_pll(limit, crtc,
-							    (adjusted_mode->clock*3/4),
+	/* Ensure that the cursor is valid for the new mode before changing... */
+	intel_crtc_update_cursor(crtc);
+
+	if (is_lvds && dev_priv->lvds_downclock_avail) {
+		has_reduced_clock = limit->find_pll(limit, crtc,
+							    dev_priv->lvds_downclock,
 							    refclk,
 							    &reduced_clock);
+		if (has_reduced_clock && (clock.p != reduced_clock.p)) {
+			/*
+			 * If the different P is found, it means that we can't
+			 * switch the display clock by using the FP0/FP1.
+			 * In such case we will disable the LVDS downclock
+			 * feature.
+			 */
+			DRM_DEBUG_KMS("Different P is found for "
+						"LVDS clock/downclock\n");
+			has_reduced_clock = 0;
+		}
 	}
-
 	/* SDVO TV has fixed PLL values depend on its clock range,
 	   this mirrors vbios setting. */
 	if (is_sdvo && is_tv) {
@@ -2831,7 +3049,7 @@
 	}
 
 	/* FDI link */
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		int lane, link_bw, bpp;
 		/* eDP doesn't require FDI link, so just set DP M/N
 		   according to current link config */
@@ -2854,6 +3072,33 @@
 
 		/* determine panel color depth */
 		temp = I915_READ(pipeconf_reg);
+		temp &= ~PIPE_BPC_MASK;
+		if (is_lvds) {
+			int lvds_reg = I915_READ(PCH_LVDS);
+			/* the BPC will be 6 if it is 18-bit LVDS panel */
+			if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+				temp |= PIPE_8BPC;
+			else
+				temp |= PIPE_6BPC;
+		} else if (is_edp) {
+			switch (dev_priv->edp_bpp/3) {
+			case 8:
+				temp |= PIPE_8BPC;
+				break;
+			case 10:
+				temp |= PIPE_10BPC;
+				break;
+			case 6:
+				temp |= PIPE_6BPC;
+				break;
+			case 12:
+				temp |= PIPE_12BPC;
+				break;
+			}
+		} else
+			temp |= PIPE_8BPC;
+		I915_WRITE(pipeconf_reg, temp);
+		I915_READ(pipeconf_reg);
 
 		switch (temp & PIPE_BPC_MASK) {
 		case PIPE_8BPC:
@@ -2873,8 +3118,7 @@
 			bpp = 24;
 		}
 
-		igdng_compute_m_n(bpp, lane, target_clock,
-				  link_bw, &m_n);
+		ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
 	}
 
 	/* Ironlake: try to setup display ref clock before DPLL
@@ -2882,7 +3126,7 @@
 	 * PCH B stepping, previous chipset stepping should be
 	 * ignoring this setting.
 	 */
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		temp = I915_READ(PCH_DREF_CONTROL);
 		/* Always enable nonspread source */
 		temp &= ~DREF_NONSPREAD_SOURCE_MASK;
@@ -2917,7 +3161,7 @@
 		}
 	}
 
-	if (IS_IGD(dev)) {
+	if (IS_PINEVIEW(dev)) {
 		fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
 		if (has_reduced_clock)
 			fp2 = (1 << reduced_clock.n) << 16 |
@@ -2929,7 +3173,7 @@
 				reduced_clock.m2;
 	}
 
-	if (!IS_IGDNG(dev))
+	if (!HAS_PCH_SPLIT(dev))
 		dpll = DPLL_VGA_MODE_DIS;
 
 	if (IS_I9XX(dev)) {
@@ -2942,19 +3186,19 @@
 			sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
 			if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 				dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-			else if (IS_IGDNG(dev))
+			else if (HAS_PCH_SPLIT(dev))
 				dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 		}
 		if (is_dp)
 			dpll |= DPLL_DVO_HIGH_SPEED;
 
 		/* compute bitmask from p1 value */
-		if (IS_IGD(dev))
-			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_IGD;
+		if (IS_PINEVIEW(dev))
+			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
 		else {
 			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
 			/* also FPA1 */
-			if (IS_IGDNG(dev))
+			if (HAS_PCH_SPLIT(dev))
 				dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
 			if (IS_G4X(dev) && has_reduced_clock)
 				dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
@@ -2973,7 +3217,7 @@
 			dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 			break;
 		}
-		if (IS_I965G(dev) && !IS_IGDNG(dev))
+		if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
 			dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 	} else {
 		if (is_lvds) {
@@ -3005,9 +3249,9 @@
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
-	/* IGDNG's plane is forced to pipe, bit 24 is to
+	/* Ironlake's plane is forced to pipe, bit 24 is to
 	   enable color space conversion */
-	if (!IS_IGDNG(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		if (pipe == 0)
 			dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
 		else
@@ -3034,20 +3278,20 @@
 
 
 	/* Disable the panel fitter if it was on our pipe */
-	if (!IS_IGDNG(dev) && intel_panel_fitter_pipe(dev) == pipe)
+	if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
 		I915_WRITE(PFIT_CONTROL, 0);
 
-	DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
-	/* assign to IGDNG registers */
-	if (IS_IGDNG(dev)) {
+	/* assign to Ironlake registers */
+	if (HAS_PCH_SPLIT(dev)) {
 		fp_reg = pch_fp_reg;
 		dpll_reg = pch_dpll_reg;
 	}
 
 	if (is_edp) {
-		igdng_disable_pll_edp(crtc);
+		ironlake_disable_pll_edp(crtc);
 	} else if ((dpll & DPLL_VCO_ENABLE)) {
 		I915_WRITE(fp_reg, fp);
 		I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
@@ -3062,7 +3306,7 @@
 	if (is_lvds) {
 		u32 lvds;
 
-		if (IS_IGDNG(dev))
+		if (HAS_PCH_SPLIT(dev))
 			lvds_reg = PCH_LVDS;
 
 		lvds = I915_READ(lvds_reg);
@@ -3081,7 +3325,20 @@
 		 * appropriately here, but we need to look more thoroughly into how
 		 * panels behave in the two modes.
 		 */
-
+		/* set the dithering flag */
+		if (IS_I965G(dev)) {
+			if (dev_priv->lvds_dither) {
+				if (IS_IRONLAKE(dev))
+					pipeconf |= PIPE_ENABLE_DITHER;
+				else
+					lvds |= LVDS_ENABLE_DITHER;
+			} else {
+				if (IS_IRONLAKE(dev))
+					pipeconf &= ~PIPE_ENABLE_DITHER;
+				else
+					lvds &= ~LVDS_ENABLE_DITHER;
+			}
+		}
 		I915_WRITE(lvds_reg, lvds);
 		I915_READ(lvds_reg);
 	}
@@ -3095,7 +3352,7 @@
 		/* Wait for the clocks to stabilize. */
 		udelay(150);
 
-		if (IS_I965G(dev) && !IS_IGDNG(dev)) {
+		if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
 			if (is_sdvo) {
 				sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
 				I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
@@ -3115,14 +3372,14 @@
 		I915_WRITE(fp_reg + 4, fp2);
 		intel_crtc->lowfreq_avail = true;
 		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG("enabling CxSR downclocking\n");
+			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
 			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
 		}
 	} else {
 		I915_WRITE(fp_reg + 4, fp);
 		intel_crtc->lowfreq_avail = false;
 		if (HAS_PIPE_CXSR(dev)) {
-			DRM_DEBUG("disabling CxSR downclocking\n");
+			DRM_DEBUG_KMS("disabling CxSR downclocking\n");
 			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
 		}
 	}
@@ -3142,21 +3399,21 @@
 	/* pipesrc and dspsize control the size that is scaled from, which should
 	 * always be the user's requested size.
 	 */
-	if (!IS_IGDNG(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
 				(mode->hdisplay - 1));
 		I915_WRITE(dsppos_reg, 0);
 	}
 	I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
 		I915_WRITE(link_m1_reg, m_n.link_m);
 		I915_WRITE(link_n1_reg, m_n.link_n);
 
 		if (is_edp) {
-			igdng_set_pll_edp(crtc, adjusted_mode->clock);
+			ironlake_set_pll_edp(crtc, adjusted_mode->clock);
 		} else {
 			/* enable FDI RX PLL too */
 			temp = I915_READ(fdi_rx_reg);
@@ -3170,7 +3427,7 @@
 
 	intel_wait_for_vblank(dev);
 
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		/* enable address swizzle for tiling buffer */
 		temp = I915_READ(DISP_ARB_CTL);
 		I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
@@ -3204,8 +3461,8 @@
 	if (!crtc->enabled)
 		return;
 
-	/* use legacy palette for IGDNG */
-	if (IS_IGDNG(dev))
+	/* use legacy palette for Ironlake */
+	if (HAS_PCH_SPLIT(dev))
 		palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
 						   LGC_PALETTE_B;
 
@@ -3217,6 +3474,85 @@
 	}
 }
 
+/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
+static void intel_crtc_update_cursor(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int x = intel_crtc->cursor_x;
+	int y = intel_crtc->cursor_y;
+	uint32_t base, pos;
+	bool visible;
+
+	pos = 0;
+
+	if (crtc->fb) {
+		base = intel_crtc->cursor_addr;
+		if (x > (int) crtc->fb->width)
+			base = 0;
+
+		if (y > (int) crtc->fb->height)
+			base = 0;
+	} else
+		base = 0;
+
+	if (x < 0) {
+		if (x + intel_crtc->cursor_width < 0)
+			base = 0;
+
+		pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+		x = -x;
+	}
+	pos |= x << CURSOR_X_SHIFT;
+
+	if (y < 0) {
+		if (y + intel_crtc->cursor_height < 0)
+			base = 0;
+
+		pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+		y = -y;
+	}
+	pos |= y << CURSOR_Y_SHIFT;
+
+	visible = base != 0;
+	if (!visible && !intel_crtc->cursor_visble)
+		return;
+
+	I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos);
+	if (intel_crtc->cursor_visble != visible) {
+		uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
+		if (base) {
+			/* Hooray for CUR*CNTR differences */
+			if (IS_MOBILE(dev) || IS_I9XX(dev)) {
+				cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
+				cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+				cntl |= pipe << 28; /* Connect to correct pipe */
+			} else {
+				cntl &= ~(CURSOR_FORMAT_MASK);
+				cntl |= CURSOR_ENABLE;
+				cntl |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
+			}
+		} else {
+			if (IS_MOBILE(dev) || IS_I9XX(dev)) {
+				cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
+				cntl |= CURSOR_MODE_DISABLE;
+			} else {
+				cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
+			}
+		}
+		I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
+
+		intel_crtc->cursor_visble = visible;
+	}
+	/* and commit changes on next vblank */
+	I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+
+	if (visible)
+		intel_mark_busy(dev, to_intel_framebuffer(crtc->fb)->obj);
+}
+
 static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 				 struct drm_file *file_priv,
 				 uint32_t handle,
@@ -3227,24 +3563,14 @@
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_gem_object *bo;
 	struct drm_i915_gem_object *obj_priv;
-	int pipe = intel_crtc->pipe;
-	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
-	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
-	uint32_t temp = I915_READ(control);
-	size_t addr;
+	uint32_t addr;
 	int ret;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 
 	/* if we want to turn off the cursor ignore width and height */
 	if (!handle) {
-		DRM_DEBUG("cursor off\n");
-		if (IS_MOBILE(dev) || IS_I9XX(dev)) {
-			temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
-			temp |= CURSOR_MODE_DISABLE;
-		} else {
-			temp &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
-		}
+		DRM_DEBUG_KMS("cursor off\n");
 		addr = 0;
 		bo = NULL;
 		mutex_lock(&dev->struct_mutex);
@@ -3271,7 +3597,7 @@
 
 	/* we only need to pin inside GTT if cursor is non-phy */
 	mutex_lock(&dev->struct_mutex);
-	if (!dev_priv->cursor_needs_physical) {
+	if (!dev_priv->info->cursor_needs_physical) {
 		ret = i915_gem_object_pin(bo, PAGE_SIZE);
 		if (ret) {
 			DRM_ERROR("failed to pin cursor bo\n");
@@ -3279,7 +3605,9 @@
 		}
 		addr = obj_priv->gtt_offset;
 	} else {
-		ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
+		ret = i915_gem_attach_phys_object(dev, bo,
+						  (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
+
 		if (ret) {
 			DRM_ERROR("failed to attach phys object\n");
 			goto fail_locked;
@@ -3290,23 +3618,9 @@
 	if (!IS_I9XX(dev))
 		I915_WRITE(CURSIZE, (height << 12) | width);
 
-	/* Hooray for CUR*CNTR differences */
-	if (IS_MOBILE(dev) || IS_I9XX(dev)) {
-		temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
-		temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-		temp |= (pipe << 28); /* Connect to correct pipe */
-	} else {
-		temp &= ~(CURSOR_FORMAT_MASK);
-		temp |= CURSOR_ENABLE;
-		temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE;
-	}
-
  finish:
-	I915_WRITE(control, temp);
-	I915_WRITE(base, addr);
-
 	if (intel_crtc->cursor_bo) {
-		if (dev_priv->cursor_needs_physical) {
+		if (dev_priv->info->cursor_needs_physical) {
 			if (intel_crtc->cursor_bo != bo)
 				i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
 		} else
@@ -3318,6 +3632,10 @@
 
 	intel_crtc->cursor_addr = addr;
 	intel_crtc->cursor_bo = bo;
+	intel_crtc->cursor_width = width;
+	intel_crtc->cursor_height = height;
+
+	intel_crtc_update_cursor(crtc);
 
 	return 0;
 fail:
@@ -3330,34 +3648,12 @@
 
 static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_framebuffer *intel_fb;
-	int pipe = intel_crtc->pipe;
-	uint32_t temp = 0;
-	uint32_t adder;
 
-	if (crtc->fb) {
-		intel_fb = to_intel_framebuffer(crtc->fb);
-		intel_mark_busy(dev, intel_fb->obj);
-	}
+	intel_crtc->cursor_x = x;
+	intel_crtc->cursor_y = y;
 
-	if (x < 0) {
-		temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
-		x = -x;
-	}
-	if (y < 0) {
-		temp |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
-		y = -y;
-	}
-
-	temp |= x << CURSOR_X_SHIFT;
-	temp |= y << CURSOR_Y_SHIFT;
-
-	adder = intel_crtc->cursor_addr;
-	I915_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
-	I915_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+	intel_crtc_update_cursor(crtc);
 
 	return 0;
 }
@@ -3509,7 +3805,6 @@
 void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode)
 {
 	struct drm_encoder *encoder = &intel_output->enc;
-	struct drm_device *dev = encoder->dev;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
@@ -3519,7 +3814,6 @@
 		intel_output->base.encoder = NULL;
 		intel_output->load_detect_temp = false;
 		crtc->enabled = drm_helper_crtc_in_use(crtc);
-		drm_helper_disable_unused_functions(dev);
 	}
 
 	/* Switch crtc and output back off if necessary */
@@ -3546,18 +3840,18 @@
 		fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
 
 	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
-	if (IS_IGD(dev)) {
-		clock.n = ffs((fp & FP_N_IGD_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
-		clock.m2 = (fp & FP_M2_IGD_DIV_MASK) >> FP_M2_DIV_SHIFT;
+	if (IS_PINEVIEW(dev)) {
+		clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
+		clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
 	} else {
 		clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
 		clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
 	}
 
 	if (IS_I9XX(dev)) {
-		if (IS_IGD(dev))
-			clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_IGD) >>
-				DPLL_FPA01_P1_POST_DIV_SHIFT_IGD);
+		if (IS_PINEVIEW(dev))
+			clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
+				DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
 		else
 			clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
 			       DPLL_FPA01_P1_POST_DIV_SHIFT);
@@ -3572,7 +3866,7 @@
 				7 : 14;
 			break;
 		default:
-			DRM_DEBUG("Unknown DPLL mode %08x in programmed "
+			DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
 				  "mode\n", (int)(dpll & DPLL_MODE_MASK));
 			return 0;
 		}
@@ -3658,132 +3952,13 @@
 	struct drm_device *dev = (struct drm_device *)arg;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	DRM_DEBUG("idle timer fired, downclocking\n");
+	DRM_DEBUG_DRIVER("idle timer fired, downclocking\n");
 
 	dev_priv->busy = false;
 
 	queue_work(dev_priv->wq, &dev_priv->idle_work);
 }
 
-void intel_increase_renderclock(struct drm_device *dev, bool schedule)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-
-	if (IS_IGDNG(dev))
-		return;
-
-	if (!dev_priv->render_reclock_avail) {
-		DRM_DEBUG("not reclocking render clock\n");
-		return;
-	}
-
-	/* Restore render clock frequency to original value */
-	if (IS_G4X(dev) || IS_I9XX(dev))
-		pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
-	else if (IS_I85X(dev))
-		pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
-	DRM_DEBUG("increasing render clock frequency\n");
-
-	/* Schedule downclock */
-	if (schedule)
-		mod_timer(&dev_priv->idle_timer, jiffies +
-			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-}
-
-void intel_decrease_renderclock(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-
-	if (IS_IGDNG(dev))
-		return;
-
-	if (!dev_priv->render_reclock_avail) {
-		DRM_DEBUG("not reclocking render clock\n");
-		return;
-	}
-
-	if (IS_G4X(dev)) {
-		u16 gcfgc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-		/* Down to minimum... */
-		gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
-		gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
-
-		pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-	} else if (IS_I965G(dev)) {
-		u16 gcfgc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-		/* Down to minimum... */
-		gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
-		gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
-
-		pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-	} else if (IS_I945G(dev) || IS_I945GM(dev)) {
-		u16 gcfgc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-		/* Down to minimum... */
-		gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
-		gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
-
-		pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-	} else if (IS_I915G(dev)) {
-		u16 gcfgc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-		/* Down to minimum... */
-		gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
-		gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
-
-		pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-	} else if (IS_I85X(dev)) {
-		u16 hpllcc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
-
-		/* Up to maximum... */
-		hpllcc &= ~GC_CLOCK_CONTROL_MASK;
-		hpllcc |= GC_CLOCK_133_200;
-
-		pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
-	}
-	DRM_DEBUG("decreasing render clock frequency\n");
-}
-
-/* Note that no increase function is needed for this - increase_renderclock()
- *  will also rewrite these bits
- */
-void intel_decrease_displayclock(struct drm_device *dev)
-{
-	if (IS_IGDNG(dev))
-		return;
-
-	if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
-	    IS_I915GM(dev)) {
-		u16 gcfgc;
-
-		/* Adjust render clock... */
-		pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
-
-		/* Down to minimum... */
-		gcfgc &= ~0xf0;
-		gcfgc |= 0x80;
-
-		pci_write_config_word(dev->pdev, GCFGC, gcfgc);
-	}
-}
-
 #define CRTC_IDLE_TIMEOUT 1000 /* ms */
 
 static void intel_crtc_idle_timer(unsigned long arg)
@@ -3792,7 +3967,7 @@
 	struct drm_crtc *crtc = &intel_crtc->base;
 	drm_i915_private_t *dev_priv = crtc->dev->dev_private;
 
-	DRM_DEBUG("idle timer fired, downclocking\n");
+	DRM_DEBUG_DRIVER("idle timer fired, downclocking\n");
 
 	intel_crtc->busy = false;
 
@@ -3808,17 +3983,18 @@
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 	int dpll = I915_READ(dpll_reg);
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
 		return;
 
 	if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
-		DRM_DEBUG("upclocking LVDS\n");
+		DRM_DEBUG_DRIVER("upclocking LVDS\n");
 
 		/* Unlock panel regs */
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+			   PANEL_UNLOCK_REGS);
 
 		dpll &= ~DISPLAY_RATE_SELECT_FPA1;
 		I915_WRITE(dpll_reg, dpll);
@@ -3826,7 +4002,7 @@
 		intel_wait_for_vblank(dev);
 		dpll = I915_READ(dpll_reg);
 		if (dpll & DISPLAY_RATE_SELECT_FPA1)
-			DRM_DEBUG("failed to upclock LVDS!\n");
+			DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
 
 		/* ...and lock them again */
 		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
@@ -3847,7 +4023,7 @@
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 	int dpll = I915_READ(dpll_reg);
 
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -3858,10 +4034,11 @@
 	 * the manual case.
 	 */
 	if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
-		DRM_DEBUG("downclocking LVDS\n");
+		DRM_DEBUG_DRIVER("downclocking LVDS\n");
 
 		/* Unlock panel regs */
-		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
+		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) |
+			   PANEL_UNLOCK_REGS);
 
 		dpll |= DISPLAY_RATE_SELECT_FPA1;
 		I915_WRITE(dpll_reg, dpll);
@@ -3869,7 +4046,7 @@
 		intel_wait_for_vblank(dev);
 		dpll = I915_READ(dpll_reg);
 		if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
-			DRM_DEBUG("failed to downclock LVDS!\n");
+			DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
 
 		/* ...and lock them again */
 		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
@@ -3897,12 +4074,6 @@
 
 	mutex_lock(&dev->struct_mutex);
 
-	/* GPU isn't processing, downclock it. */
-	if (!dev_priv->busy) {
-		intel_decrease_renderclock(dev);
-		intel_decrease_displayclock(dev);
-	}
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		/* Skip inactive CRTCs */
 		if (!crtc->fb)
@@ -3936,8 +4107,11 @@
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	dev_priv->busy = true;
-	intel_increase_renderclock(dev, true);
+	if (!dev_priv->busy)
+		dev_priv->busy = true;
+	else
+		mod_timer(&dev_priv->idle_timer, jiffies +
+			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (!crtc->fb)
@@ -3967,6 +4141,220 @@
 	kfree(intel_crtc);
 }
 
+struct intel_unpin_work {
+	struct work_struct work;
+	struct drm_device *dev;
+	struct drm_gem_object *old_fb_obj;
+	struct drm_gem_object *pending_flip_obj;
+	struct drm_pending_vblank_event *event;
+	int pending;
+};
+
+static void intel_unpin_work_fn(struct work_struct *__work)
+{
+	struct intel_unpin_work *work =
+		container_of(__work, struct intel_unpin_work, work);
+
+	mutex_lock(&work->dev->struct_mutex);
+	i915_gem_object_unpin(work->old_fb_obj);
+	drm_gem_object_unreference(work->pending_flip_obj);
+	drm_gem_object_unreference(work->old_fb_obj);
+	mutex_unlock(&work->dev->struct_mutex);
+	kfree(work);
+}
+
+static void do_intel_finish_page_flip(struct drm_device *dev,
+				      struct drm_crtc *crtc)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_unpin_work *work;
+	struct drm_i915_gem_object *obj_priv;
+	struct drm_pending_vblank_event *e;
+	struct timeval now;
+	unsigned long flags;
+
+	/* Ignore early vblank irqs */
+	if (intel_crtc == NULL)
+		return;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	work = intel_crtc->unpin_work;
+	if (work == NULL || !work->pending) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		return;
+	}
+
+	intel_crtc->unpin_work = NULL;
+	drm_vblank_put(dev, intel_crtc->pipe);
+
+	if (work->event) {
+		e = work->event;
+		do_gettimeofday(&now);
+		e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe);
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		list_add_tail(&e->base.link,
+			      &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+	}
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	obj_priv = work->pending_flip_obj->driver_private;
+
+	/* Initial scanout buffer will have a 0 pending flip count */
+	if ((atomic_read(&obj_priv->pending_flip) == 0) ||
+	    atomic_dec_and_test(&obj_priv->pending_flip))
+		DRM_WAKEUP(&dev_priv->pending_flip_queue);
+	schedule_work(&work->work);
+}
+
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+	do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
+
+	do_intel_finish_page_flip(dev, crtc);
+}
+
+void intel_prepare_page_flip(struct drm_device *dev, int plane)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc =
+		to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (intel_crtc->unpin_work) {
+		intel_crtc->unpin_work->pending = 1;
+	} else {
+		DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static int intel_crtc_page_flip(struct drm_crtc *crtc,
+				struct drm_framebuffer *fb,
+				struct drm_pending_vblank_event *event)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_framebuffer *intel_fb;
+	struct drm_i915_gem_object *obj_priv;
+	struct drm_gem_object *obj;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_unpin_work *work;
+	unsigned long flags, offset;
+	int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int ret, pipesrc;
+	u32 flip_mask;
+	RING_LOCALS;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (work == NULL)
+		return -ENOMEM;
+
+	work->event = event;
+	work->dev = crtc->dev;
+	intel_fb = to_intel_framebuffer(crtc->fb);
+	work->old_fb_obj = intel_fb->obj;
+	INIT_WORK(&work->work, intel_unpin_work_fn);
+
+	/* We borrow the event spin lock for protecting unpin_work */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (intel_crtc->unpin_work) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		kfree(work);
+
+		DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+		return -EBUSY;
+	}
+	intel_crtc->unpin_work = work;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	intel_fb = to_intel_framebuffer(fb);
+	obj = intel_fb->obj;
+
+	mutex_lock(&dev->struct_mutex);
+	ret = intel_pin_and_fence_fb_obj(dev, obj);
+	if (ret != 0) {
+		mutex_unlock(&dev->struct_mutex);
+
+		spin_lock_irqsave(&dev->event_lock, flags);
+		intel_crtc->unpin_work = NULL;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+
+		kfree(work);
+
+		DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
+			  obj->driver_private);
+		return ret;
+	}
+
+	/* Reference the objects for the scheduled work. */
+	drm_gem_object_reference(work->old_fb_obj);
+	drm_gem_object_reference(obj);
+
+	crtc->fb = fb;
+	i915_gem_object_flush_write_domain(obj);
+	drm_vblank_get(dev, intel_crtc->pipe);
+	obj_priv = obj->driver_private;
+	atomic_inc(&obj_priv->pending_flip);
+	work->pending_flip_obj = obj;
+
+	if (intel_crtc->plane)
+		flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+	else
+		flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+
+	if (IS_GEN3(dev) || IS_GEN2(dev)) {
+		BEGIN_LP_RING(2);
+		OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
+		OUT_RING(0);
+		ADVANCE_LP_RING();
+	}
+
+	/* Offset into the new buffer for cases of shared fbs between CRTCs */
+	offset = obj_priv->gtt_offset;
+	offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
+
+	BEGIN_LP_RING(4);
+	if (IS_I965G(dev)) {
+		OUT_RING(MI_DISPLAY_FLIP |
+			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+		OUT_RING(fb->pitch);
+		OUT_RING(offset | obj_priv->tiling_mode);
+		pipesrc = I915_READ(pipesrc_reg); 
+		OUT_RING(pipesrc & 0x0fff0fff);
+	} else if (IS_GEN3(dev)) {
+		OUT_RING(MI_DISPLAY_FLIP_I915 |
+			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+		OUT_RING(fb->pitch);
+		OUT_RING(offset);
+		OUT_RING(MI_NOOP);
+	} else {
+		OUT_RING(MI_DISPLAY_FLIP |
+			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
+		OUT_RING(fb->pitch);
+		OUT_RING(offset);
+		OUT_RING(MI_NOOP);
+	}
+	ADVANCE_LP_RING();
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
 static const struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.dpms = intel_crtc_dpms,
 	.mode_fixup = intel_crtc_mode_fixup,
@@ -3983,11 +4371,13 @@
 	.gamma_set = intel_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
 	.destroy = intel_crtc_destroy,
+	.page_flip = intel_crtc_page_flip,
 };
 
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc;
 	int i;
 
@@ -4010,12 +4400,17 @@
 	intel_crtc->pipe = pipe;
 	intel_crtc->plane = pipe;
 	if (IS_MOBILE(dev) && (IS_I9XX(dev) && !IS_I965G(dev))) {
-		DRM_DEBUG("swapping pipes & planes for FBC\n");
+		DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
 		intel_crtc->plane = ((pipe == 0) ? 1 : 0);
 	}
 
+	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+	       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
+	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
+	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
+
 	intel_crtc->cursor_addr = 0;
-	intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
+	intel_crtc->dpms_mode = -1;
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
 	intel_crtc->busy = false;
@@ -4090,7 +4485,7 @@
 	if (IS_MOBILE(dev) && !IS_I830(dev))
 		intel_lvds_init(dev);
 
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		int found;
 
 		if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
@@ -4118,37 +4513,51 @@
 		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D);
 
-	} else if (IS_I9XX(dev)) {
+	} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 		bool found = false;
 
 		if (I915_READ(SDVOB) & SDVO_DETECTED) {
+			DRM_DEBUG_KMS("probing SDVOB\n");
 			found = intel_sdvo_init(dev, SDVOB);
-			if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
+				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
 				intel_hdmi_init(dev, SDVOB);
+			}
 
-			if (!found && SUPPORTS_INTEGRATED_DP(dev))
+			if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
+				DRM_DEBUG_KMS("probing DP_B\n");
 				intel_dp_init(dev, DP_B);
+			}
 		}
 
 		/* Before G4X SDVOC doesn't have its own detect register */
 
-		if (I915_READ(SDVOB) & SDVO_DETECTED)
+		if (I915_READ(SDVOB) & SDVO_DETECTED) {
+			DRM_DEBUG_KMS("probing SDVOC\n");
 			found = intel_sdvo_init(dev, SDVOC);
+		}
 
 		if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
 
-			if (SUPPORTS_INTEGRATED_HDMI(dev))
+			if (SUPPORTS_INTEGRATED_HDMI(dev)) {
+				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
 				intel_hdmi_init(dev, SDVOC);
-			if (SUPPORTS_INTEGRATED_DP(dev))
+			}
+			if (SUPPORTS_INTEGRATED_DP(dev)) {
+				DRM_DEBUG_KMS("probing DP_C\n");
 				intel_dp_init(dev, DP_C);
+			}
 		}
 
-		if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+		if (SUPPORTS_INTEGRATED_DP(dev) &&
+		    (I915_READ(DP_D) & DP_DETECTED)) {
+			DRM_DEBUG_KMS("probing DP_D\n");
 			intel_dp_init(dev, DP_D);
-	} else
+		}
+	} else if (IS_GEN2(dev))
 		intel_dvo_init(dev);
 
-	if (IS_I9XX(dev) && IS_MOBILE(dev) && !IS_IGDNG(dev))
+	if (SUPPORTS_TV(dev))
 		intel_tv_init(dev);
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -4249,6 +4658,42 @@
 	.fb_changed = intelfb_probe,
 };
 
+static struct drm_gem_object *
+intel_alloc_power_context(struct drm_device *dev)
+{
+	struct drm_gem_object *pwrctx;
+	int ret;
+
+	pwrctx = drm_gem_object_alloc(dev, 4096);
+	if (!pwrctx) {
+		DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
+		return NULL;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+	ret = i915_gem_object_pin(pwrctx, 4096);
+	if (ret) {
+		DRM_ERROR("failed to pin power context: %d\n", ret);
+		goto err_unref;
+	}
+
+	ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1);
+	if (ret) {
+		DRM_ERROR("failed to set-domain on power context: %d\n", ret);
+		goto err_unpin;
+	}
+	mutex_unlock(&dev->struct_mutex);
+
+	return pwrctx;
+
+err_unpin:
+	i915_gem_object_unpin(pwrctx);
+err_unref:
+	drm_gem_object_unreference(pwrctx);
+	mutex_unlock(&dev->struct_mutex);
+	return NULL;
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4257,7 +4702,7 @@
 	 * Disable clock gating reported to work incorrectly according to the
 	 * specs, but enable as much else as we can.
 	 */
-	if (IS_IGDNG(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		return;
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
@@ -4291,11 +4736,37 @@
 		dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
 			DSTATE_DOT_CLOCK_GATING;
 		I915_WRITE(D_STATE, dstate);
-	} else if (IS_I855(dev) || IS_I865G(dev)) {
+	} else if (IS_I85X(dev) || IS_I865G(dev)) {
 		I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
 	} else if (IS_I830(dev)) {
 		I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
 	}
+
+	/*
+	 * GPU can automatically power down the render unit if given a page
+	 * to save state.
+	 */
+	if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) {
+		struct drm_i915_gem_object *obj_priv = NULL;
+
+		if (dev_priv->pwrctx) {
+			obj_priv = dev_priv->pwrctx->driver_private;
+		} else {
+			struct drm_gem_object *pwrctx;
+
+			pwrctx = intel_alloc_power_context(dev);
+			if (pwrctx) {
+				dev_priv->pwrctx = pwrctx;
+				obj_priv = pwrctx->driver_private;
+			}
+		}
+
+		if (obj_priv) {
+			I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN);
+			I915_WRITE(MCHBAR_RENDER_STANDBY,
+				   I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT);
+		}
+	}
 }
 
 /* Set up chip specific display functions */
@@ -4304,8 +4775,8 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* We always want a DPMS function */
-	if (IS_IGDNG(dev))
-		dev_priv->display.dpms = igdng_crtc_dpms;
+	if (HAS_PCH_SPLIT(dev))
+		dev_priv->display.dpms = ironlake_crtc_dpms;
 	else
 		dev_priv->display.dpms = i9xx_crtc_dpms;
 
@@ -4315,7 +4786,7 @@
 			dev_priv->display.fbc_enabled = g4x_fbc_enabled;
 			dev_priv->display.enable_fbc = g4x_enable_fbc;
 			dev_priv->display.disable_fbc = g4x_disable_fbc;
-		} else if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) {
+		} else if (IS_I965GM(dev)) {
 			dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
 			dev_priv->display.enable_fbc = i8xx_enable_fbc;
 			dev_priv->display.disable_fbc = i8xx_disable_fbc;
@@ -4324,13 +4795,13 @@
 	}
 
 	/* Returns the core display clock speed */
-	if (IS_I945G(dev))
+	if (IS_I945G(dev) || (IS_G33(dev) && ! IS_PINEVIEW_M(dev)))
 		dev_priv->display.get_display_clock_speed =
 			i945_get_display_clock_speed;
 	else if (IS_I915G(dev))
 		dev_priv->display.get_display_clock_speed =
 			i915_get_display_clock_speed;
-	else if (IS_I945GM(dev) || IS_845G(dev) || IS_IGDGM(dev))
+	else if (IS_I945GM(dev) || IS_845G(dev) || IS_PINEVIEW_M(dev))
 		dev_priv->display.get_display_clock_speed =
 			i9xx_misc_get_display_clock_speed;
 	else if (IS_I915GM(dev))
@@ -4339,7 +4810,7 @@
 	else if (IS_I865G(dev))
 		dev_priv->display.get_display_clock_speed =
 			i865_get_display_clock_speed;
-	else if (IS_I855(dev))
+	else if (IS_I85X(dev))
 		dev_priv->display.get_display_clock_speed =
 			i855_get_display_clock_speed;
 	else /* 852, 830 */
@@ -4347,7 +4818,7 @@
 			i830_get_display_clock_speed;
 
 	/* For FIFO watermark updates */
-	if (IS_IGDNG(dev))
+	if (HAS_PCH_SPLIT(dev))
 		dev_priv->display.update_wm = NULL;
 	else if (IS_G4X(dev))
 		dev_priv->display.update_wm = g4x_update_wm;
@@ -4403,7 +4874,7 @@
 		num_pipe = 2;
 	else
 		num_pipe = 1;
-	DRM_DEBUG("%d display pipe%s available.\n",
+	DRM_DEBUG_KMS("%d display pipe%s available.\n",
 		  num_pipe, num_pipe > 1 ? "s" : "");
 
 	if (IS_I85X(dev))
@@ -4422,6 +4893,15 @@
 	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
 		    (unsigned long)dev);
+
+	intel_setup_overlay(dev);
+
+	if (IS_PINEVIEW(dev) && !intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+							dev_priv->fsb_freq,
+							dev_priv->mem_freq))
+		DRM_INFO("failed to find known CxSR latency "
+			 "(found fsb freq %d, mem freq %d), disabling CxSR\n",
+			 dev_priv->fsb_freq, dev_priv->mem_freq);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -4442,14 +4922,23 @@
 		del_timer_sync(&intel_crtc->idle_timer);
 	}
 
-	intel_increase_renderclock(dev, false);
 	del_timer_sync(&dev_priv->idle_timer);
 
-	mutex_unlock(&dev->struct_mutex);
-
 	if (dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
+	if (dev_priv->pwrctx) {
+		struct drm_i915_gem_object *obj_priv;
+
+		obj_priv = dev_priv->pwrctx->driver_private;
+		I915_WRITE(PWRCTXA, obj_priv->gtt_offset &~ PWRCTX_EN);
+		I915_READ(PWRCTXA);
+		i915_gem_object_unpin(dev_priv->pwrctx);
+		drm_gem_object_unreference(dev_priv->pwrctx);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
 	drm_mode_config_cleanup(dev);
 }
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_dma.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_dma.c
@@ -123,7 +123,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	/* Program Hardware Status Page */
 	dev_priv->status_page_dmah =
-		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
 
 	if (!dev_priv->status_page_dmah) {
 		DRM_ERROR("Can not allocate hardware status page\n");
@@ -134,6 +134,10 @@
 
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 
+	if (IS_I965G(dev))
+		dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
+					     0xf0;
+
 	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 	return 0;
@@ -683,8 +687,10 @@
 		ret = copy_from_user(cliprects, batch->cliprects,
 				     batch->num_cliprects *
 				     sizeof(struct drm_clip_rect));
-		if (ret != 0)
+		if (ret != 0) {
+			ret = -EFAULT;
 			goto fail_free;
+		}
 	}
 
 	mutex_lock(&dev->struct_mutex);
@@ -725,20 +731,26 @@
 		return -ENOMEM;
 
 	ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
-	if (ret != 0)
+	if (ret != 0) {
+		ret = -EFAULT;
 		goto fail_batch_free;
+	}
 
 	if (cmdbuf->num_cliprects) {
 		cliprects = kcalloc(cmdbuf->num_cliprects,
 				    sizeof(struct drm_clip_rect), GFP_KERNEL);
-		if (cliprects == NULL)
+		if (cliprects == NULL) {
+			ret = -ENOMEM;
 			goto fail_batch_free;
+		}
 
 		ret = copy_from_user(cliprects, cmdbuf->cliprects,
 				     cmdbuf->num_cliprects *
 				     sizeof(struct drm_clip_rect));
-		if (ret != 0)
+		if (ret != 0) {
+			ret = -EFAULT;
 			goto fail_clip_free;
+		}
 	}
 
 	mutex_lock(&dev->struct_mutex);
@@ -807,9 +819,19 @@
 	case I915_PARAM_NUM_FENCES_AVAIL:
 		value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
 		break;
+	case I915_PARAM_HAS_OVERLAY:
+		value = dev_priv->overlay ? 1 : 0;
+		break;
+	case I915_PARAM_HAS_PAGEFLIPPING:
+		value = 1;
+		break;
+	case I915_PARAM_HAS_EXECBUF2:
+		/* depends on GEM */
+		value = dev_priv->has_gem;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
-					param->param);
+				 param->param);
 		return -EINVAL;
 	}
 
@@ -962,15 +984,21 @@
 	 * Some of the preallocated space is taken by the GTT
 	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
 	 */
-	if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev))
+	if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev))
 		overhead = 4096;
 	else
 		overhead = (*aperture_size / 1024) + 4096;
 
 	switch (tmp & INTEL_GMCH_GMS_MASK) {
 	case INTEL_855_GMCH_GMS_DISABLED:
-		DRM_ERROR("video memory is disabled\n");
-		return -1;
+		/* XXX: This is what my A1 silicon has. */
+		if (IS_GEN6(dev)) {
+			stolen = 64 * 1024 * 1024;
+		} else {
+			DRM_ERROR("video memory is disabled\n");
+			return -1;
+		}
+		break;
 	case INTEL_855_GMCH_GMS_STOLEN_1M:
 		stolen = 1 * 1024 * 1024;
 		break;
@@ -1048,7 +1076,7 @@
 	int gtt_offset, gtt_size;
 
 	if (IS_I965G(dev)) {
-		if (IS_G4X(dev) || IS_IGDNG(dev)) {
+		if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
 			gtt_offset = 2*1024*1024;
 			gtt_size = 2*1024*1024;
 		} else {
@@ -1070,7 +1098,7 @@
 
 	entry = *(volatile u32 *)(gtt + (gtt_addr / 1024));
 
-	DRM_DEBUG("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
+	DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry);
 
 	/* Mask out these reserved bits on this hardware. */
 	if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) ||
@@ -1096,7 +1124,7 @@
 	phys =(entry & PTE_ADDRESS_MASK) |
 		((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4));
 
-	DRM_DEBUG("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys);
+	DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys);
 
 	return phys;
 }
@@ -1111,7 +1139,8 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_mm_node *compressed_fb, *compressed_llb;
-	unsigned long cfb_base, ll_base;
+	unsigned long cfb_base;
+	unsigned long ll_base = 0;
 
 	/* Leave 1M for line length buffer & misc. */
 	compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
@@ -1194,14 +1223,6 @@
 	dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
 		0xff000000;
 
-	if (IS_MOBILE(dev) || IS_I9XX(dev))
-		dev_priv->cursor_needs_physical = true;
-	else
-		dev_priv->cursor_needs_physical = false;
-
-	if (IS_I965G(dev) || IS_G33(dev))
-		dev_priv->cursor_needs_physical = false;
-
 	/* Basic memrange allocator for stolen space (aka vram) */
 	drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 	DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024));
@@ -1251,6 +1272,12 @@
 	if (ret)
 		goto destroy_ringbuffer;
 
+	/* IIR "flip pending" bit means done if this bit is set */
+	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
+		dev_priv->flip_pending_is_done = true;
+
+	intel_modeset_init(dev);
+
 	ret = drm_irq_install(dev);
 	if (ret)
 		goto destroy_ringbuffer;
@@ -1265,8 +1292,6 @@
 
 	I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 
-	intel_modeset_init(dev);
-
 	drm_helper_initial_config(dev);
 
 	return 0;
@@ -1306,7 +1331,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 tmp;
 
-	if (!IS_IGD(dev))
+	if (!IS_PINEVIEW(dev))
 		return;
 
 	tmp = I915_READ(CLKCFG);
@@ -1354,7 +1379,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	resource_size_t base, size;
-	int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+	int ret = 0, mmio_bar;
 	uint32_t agp_size, prealloc_size, prealloc_start;
 
 	/* i915 has 4 more counters */
@@ -1370,8 +1395,10 @@
 
 	dev->dev_private = (void *)dev_priv;
 	dev_priv->dev = dev;
+	dev_priv->info = (struct intel_device_info *) flags;
 
 	/* Add register map (needed for suspend/resume) */
+	mmio_bar = IS_I9XX(dev) ? 0 : 1;
 	base = drm_get_resource_start(dev, mmio_bar);
 	size = drm_get_resource_len(dev, mmio_bar);
 
@@ -1380,6 +1407,21 @@
 		goto free_priv;
 	}
 
+	/* overlay on gen2 is broken and can't address above 1G */
+	if (IS_GEN2(dev))
+		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(30));
+
+	/* 965GM sometimes incorrectly writes to hardware status page (HWS)
+	 * using 32bit addressing, overwriting memory if HWS is located
+	 * above 4GB.
+	 *
+	 * The documentation also mentions an issue with undefined
+	 * behaviour if any general state is accessed within a page above 4GB,
+	 * which also needs to be handled carefully.
+	 */
+	if (IS_I965G(dev) && !IS_G4X(dev) && !IS_IRONLAKE(dev))
+		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32));
+
 	dev_priv->regs = ioremap(base, size);
 	if (!dev_priv->regs) {
 		DRM_ERROR("failed to map registers\n");
@@ -1413,7 +1455,7 @@
 	if (ret)
 		goto out_iomapfree;
 
-	dev_priv->wq = create_workqueue("i915");
+	dev_priv->wq = create_singlethread_workqueue("i915");
 	if (dev_priv->wq == NULL) {
 		DRM_ERROR("Failed to create our workqueue.\n");
 		ret = -ENOMEM;
@@ -1434,7 +1476,7 @@
 
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-	if (IS_G4X(dev) || IS_IGDNG(dev)) {
+	if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
 		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
 		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
 	}
@@ -1489,9 +1531,7 @@
 	}
 
 	/* Must be done after probing outputs */
-	/* FIXME: verify on IGDNG */
-	if (!IS_IGDNG(dev))
-		intel_opregion_init(dev, 0);
+	intel_opregion_init(dev, 0);
 
 	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
 		    (unsigned long) dev);
@@ -1525,6 +1565,15 @@
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		/*
+		 * free the memory space allocated for the child device
+		 * config parsed from VBT
+		 */
+		if (dev_priv->child_dev && dev_priv->child_dev_num) {
+			kfree(dev_priv->child_dev);
+			dev_priv->child_dev = NULL;
+			dev_priv->child_dev_num = 0;
+		}
 		drm_irq_uninstall(dev);
 		vga_client_register(dev->pdev, NULL, NULL, NULL);
 	}
@@ -1535,8 +1584,7 @@
 	if (dev_priv->regs != NULL)
 		iounmap(dev_priv->regs);
 
-	if (!IS_IGDNG(dev))
-		intel_opregion_free(dev, 0);
+	intel_opregion_free(dev, 0);
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		intel_modeset_cleanup(dev);
@@ -1548,6 +1596,11 @@
 		mutex_unlock(&dev->struct_mutex);
 		drm_mm_takedown(&dev_priv->vram);
 		i915_gem_lastclose(dev);
+
+		intel_cleanup_overlay(dev);
+
+		if (!I915_NEED_GFX_HWS(dev))
+			i915_free_hws(dev);
 	}
 
 	pci_dev_put(dev_priv->bridge_dev);
@@ -1638,6 +1691,7 @@
 	DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
@@ -1656,6 +1710,8 @@
 	DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
 	DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
 	DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
+	DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
+	DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/dvo_ch7017.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -249,7 +249,8 @@
 	if (val != CH7017_DEVICE_ID_VALUE &&
 	    val != CH7018_DEVICE_ID_VALUE &&
 	    val != CH7019_DEVICE_ID_VALUE) {
-		DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n",
+		DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
+				"Slave %d.\n",
 			  val, i2cbus->adapter.name,dvo->slave_addr);
 		goto fail;
 	}
@@ -284,7 +285,7 @@
 	uint8_t horizontal_active_pixel_output, vertical_active_line_output;
 	uint8_t active_input_line_output;
 
-	DRM_DEBUG("Registers before mode setting\n");
+	DRM_DEBUG_KMS("Registers before mode setting\n");
 	ch7017_dump_regs(dvo);
 
 	/* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
@@ -346,7 +347,7 @@
 	/* Turn the LVDS back on with new settings. */
 	ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down);
 
-	DRM_DEBUG("Registers after mode setting\n");
+	DRM_DEBUG_KMS("Registers after mode setting\n");
 	ch7017_dump_regs(dvo);
 }
 
@@ -386,7 +387,7 @@
 #define DUMP(reg)					\
 do {							\
 	ch7017_read(dvo, reg, &val);			\
-	DRM_DEBUG(#reg ": %02x\n", val);		\
+	DRM_DEBUG_KMS(#reg ": %02x\n", val);		\
 } while (0)
 
 	DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_bios.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_bios.c
@@ -33,6 +33,8 @@
 #define	SLAVE_ADDR1	0x70
 #define	SLAVE_ADDR2	0x72
 
+static int panel_type;
+
 static void *
 find_section(struct bdb_header *bdb, int section_id)
 {
@@ -114,6 +116,8 @@
 	struct lvds_dvo_timing *dvo_timing;
 	struct drm_display_mode *panel_fixed_mode;
 	int lfp_data_size, dvo_timing_offset;
+	int i, temp_downclock;
+	struct drm_display_mode *temp_mode;
 
 	/* Defaults if we can't find VBT info */
 	dev_priv->lvds_dither = 0;
@@ -126,6 +130,7 @@
 	dev_priv->lvds_dither = lvds_options->pixel_dither;
 	if (lvds_options->panel_type == 0xff)
 		return;
+	panel_type = lvds_options->panel_type;
 
 	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
 	if (!lvds_lfp_data)
@@ -159,9 +164,50 @@
 
 	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
 
-	DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
+	DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
 	drm_mode_debug_printmodeline(panel_fixed_mode);
 
+	temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
+	temp_downclock = panel_fixed_mode->clock;
+	/*
+	 * enumerate the LVDS panel timing info entry in VBT to check whether
+	 * the LVDS downclock is found.
+	 */
+	for (i = 0; i < 16; i++) {
+		entry = (struct bdb_lvds_lfp_data_entry *)
+			((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
+		dvo_timing = (struct lvds_dvo_timing *)
+			((unsigned char *)entry + dvo_timing_offset);
+
+		fill_detail_timing_data(temp_mode, dvo_timing);
+
+		if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
+		temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
+		temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
+		temp_mode->htotal == panel_fixed_mode->htotal &&
+		temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
+		temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
+		temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
+		temp_mode->vtotal == panel_fixed_mode->vtotal &&
+		temp_mode->clock < temp_downclock) {
+			/*
+			 * downclock is already found. But we expect
+			 * to find the lower downclock.
+			 */
+			temp_downclock = temp_mode->clock;
+		}
+		/* clear it to zero */
+		memset(temp_mode, 0, sizeof(*temp_mode));
+	}
+	kfree(temp_mode);
+	if (temp_downclock < panel_fixed_mode->clock &&
+	    i915_lvds_downclock) {
+		dev_priv->lvds_downclock_avail = 1;
+		dev_priv->lvds_downclock = temp_downclock;
+		DRM_DEBUG_KMS("LVDS downclock is found in VBT. ",
+				"Normal Clock %dKHz, downclock %dKHz\n",
+				temp_downclock, panel_fixed_mode->clock);
+	}
 	return;
 }
 
@@ -201,6 +247,7 @@
 parse_general_features(struct drm_i915_private *dev_priv,
 		       struct bdb_header *bdb)
 {
+	struct drm_device *dev = dev_priv->dev;
 	struct bdb_general_features *general;
 
 	/* Set sensible defaults in case we can't find the general block */
@@ -217,7 +264,7 @@
 			if (IS_I85X(dev_priv->dev))
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 66 : 48;
-			else if (IS_IGDNG(dev_priv->dev))
+			else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev))
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 100 : 120;
 			else
@@ -241,22 +288,18 @@
 		GPIOF,
 	};
 
-	/* Set sensible defaults in case we can't find the general block
-	   or it is the wrong chipset */
-	dev_priv->crt_ddc_bus = -1;
-
 	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
 	if (general) {
 		u16 block_size = get_blocksize(general);
 		if (block_size >= sizeof(*general)) {
 			int bus_pin = general->crt_ddc_gmbus_pin;
-			DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
+			DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin);
 			if ((bus_pin >= 1) && (bus_pin <= 6)) {
 				dev_priv->crt_ddc_bus =
 					crt_bus_map_table[bus_pin-1];
 			}
 		} else {
-			DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
+			DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n",
 				  block_size);
 		}
 	}
@@ -274,7 +317,7 @@
 
 	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
 	if (!p_defs) {
-		DRM_DEBUG("No general definition block is found\n");
+		DRM_DEBUG_KMS("No general definition block is found\n");
 		return;
 	}
 	/* judge whether the size of child device meets the requirements.
@@ -284,7 +327,7 @@
 	 */
 	if (p_defs->child_dev_size != sizeof(*p_child)) {
 		/* different child dev size . Ignore it */
-		DRM_DEBUG("different child size is found. Invalid.\n");
+		DRM_DEBUG_KMS("different child size is found. Invalid.\n");
 		return;
 	}
 	/* get the block size of general definitions */
@@ -310,11 +353,11 @@
 		if (p_child->dvo_port != DEVICE_PORT_DVOB &&
 			p_child->dvo_port != DEVICE_PORT_DVOC) {
 			/* skip the incorrect SDVO port */
-			DRM_DEBUG("Incorrect SDVO port. Skip it \n");
+			DRM_DEBUG_KMS("Incorrect SDVO port. Skip it \n");
 			continue;
 		}
-		DRM_DEBUG("the SDVO device with slave addr %2x is found on "
-				"%s port\n",
+		DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
+				" %s port\n",
 				p_child->slave_addr,
 				(p_child->dvo_port == DEVICE_PORT_DVOB) ?
 					"SDVOB" : "SDVOC");
@@ -325,21 +368,21 @@
 			p_mapping->dvo_wiring = p_child->dvo_wiring;
 			p_mapping->initialized = 1;
 		} else {
-			DRM_DEBUG("Maybe one SDVO port is shared by "
+			DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
 					 "two SDVO device.\n");
 		}
 		if (p_child->slave2_addr) {
 			/* Maybe this is a SDVO device with multiple inputs */
 			/* And the mapping info is not added */
-			DRM_DEBUG("there exists the slave2_addr. Maybe this "
-				"is a SDVO device with multiple inputs.\n");
+			DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
+				" is a SDVO device with multiple inputs.\n");
 		}
 		count++;
 	}
 
 	if (!count) {
 		/* No SDVO device info is found */
-		DRM_DEBUG("No SDVO device info is found in VBT\n");
+		DRM_DEBUG_KMS("No SDVO device info is found in VBT\n");
 	}
 	return;
 }
@@ -366,6 +409,98 @@
 		dev_priv->render_reclock_avail = true;
 }
 
+static void
+parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+{
+	struct bdb_edp *edp;
+
+	edp = find_section(bdb, BDB_EDP);
+	if (!edp) {
+		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) {
+			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\
+				       assume 18bpp panel color depth.\n");
+			dev_priv->edp_bpp = 18;
+		}
+		return;
+	}
+
+	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
+	case EDP_18BPP:
+		dev_priv->edp_bpp = 18;
+		break;
+	case EDP_24BPP:
+		dev_priv->edp_bpp = 24;
+		break;
+	case EDP_30BPP:
+		dev_priv->edp_bpp = 30;
+		break;
+	}
+}
+
+static void
+parse_device_mapping(struct drm_i915_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct bdb_general_definitions *p_defs;
+	struct child_device_config *p_child, *child_dev_ptr;
+	int i, child_device_num, count;
+	u16	block_size;
+
+	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	if (!p_defs) {
+		DRM_DEBUG_KMS("No general definition block is found\n");
+		return;
+	}
+	/* judge whether the size of child device meets the requirements.
+	 * If the child device size obtained from general definition block
+	 * is different with sizeof(struct child_device_config), skip the
+	 * parsing of sdvo device info
+	 */
+	if (p_defs->child_dev_size != sizeof(*p_child)) {
+		/* different child dev size . Ignore it */
+		DRM_DEBUG_KMS("different child size is found. Invalid.\n");
+		return;
+	}
+	/* get the block size of general definitions */
+	block_size = get_blocksize(p_defs);
+	/* get the number of child device */
+	child_device_num = (block_size - sizeof(*p_defs)) /
+				sizeof(*p_child);
+	count = 0;
+	/* get the number of child device that is present */
+	for (i = 0; i < child_device_num; i++) {
+		p_child = &(p_defs->devices[i]);
+		if (!p_child->device_type) {
+			/* skip the device block if device type is invalid */
+			continue;
+		}
+		count++;
+	}
+	if (!count) {
+		DRM_DEBUG_KMS("no child dev is parsed from VBT \n");
+		return;
+	}
+	dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
+	if (!dev_priv->child_dev) {
+		DRM_DEBUG_KMS("No memory space for child device\n");
+		return;
+	}
+
+	dev_priv->child_dev_num = count;
+	count = 0;
+	for (i = 0; i < child_device_num; i++) {
+		p_child = &(p_defs->devices[i]);
+		if (!p_child->device_type) {
+			/* skip the device block if device type is invalid */
+			continue;
+		}
+		child_dev_ptr = dev_priv->child_dev + count;
+		count++;
+		memcpy((void *)child_dev_ptr, (void *)p_child,
+					sizeof(*p_child));
+	}
+	return;
+}
 /**
  * intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -417,7 +552,9 @@
 	parse_lfp_panel_data(dev_priv, bdb);
 	parse_sdvo_panel_data(dev_priv, bdb);
 	parse_sdvo_device_mapping(dev_priv, bdb);
+	parse_device_mapping(dev_priv, bdb);
 	parse_driver_features(dev_priv, bdb);
+	parse_edp(dev_priv, bdb);
 
 	pci_unmap_rom(pdev, bios);
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_ioc32.c
@@ -66,8 +66,7 @@
 			  &batchbuffer->cliprects))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_I915_BATCHBUFFER,
+	return drm_ioctl(file, DRM_IOCTL_I915_BATCHBUFFER,
 			 (unsigned long)batchbuffer);
 }
 
@@ -102,8 +101,8 @@
 			  &cmdbuffer->cliprects))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
+	return drm_ioctl(file, DRM_IOCTL_I915_CMDBUFFER,
+			 (unsigned long)cmdbuffer);
 }
 
 typedef struct drm_i915_irq_emit32 {
@@ -125,8 +124,8 @@
 			  &request->irq_seq))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_I915_IRQ_EMIT,
+			 (unsigned long)request);
 }
 typedef struct drm_i915_getparam32 {
 	int param;
@@ -149,8 +148,8 @@
 			  &request->value))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM,
+			 (unsigned long)request);
 }
 
 typedef struct drm_i915_mem_alloc32 {
@@ -178,8 +177,8 @@
 			  &request->region_offset))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_I915_ALLOC, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_I915_ALLOC,
+			 (unsigned long)request);
 }
 
 drm_ioctl_compat_t *i915_compat_ioctls[] = {
@@ -211,12 +210,10 @@
 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
 		fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-	lock_kernel();		/* XXX for now */
 	if (fn != NULL)
 		ret = (*fn) (filp, cmd, arg);
 	else
-		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+		ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_dp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_dp.c
@@ -33,7 +33,8 @@
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
-#include "intel_dp.h"
+#include "drm_dp_helper.h"
+
 
 #define DP_LINK_STATUS_SIZE	6
 #define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
@@ -124,9 +125,21 @@
 
 /* I think this is a fiction */
 static int
-intel_dp_link_required(int pixel_clock)
+intel_dp_link_required(struct drm_device *dev,
+		       struct intel_output *intel_output, int pixel_clock)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_eDP(intel_output))
+		return (pixel_clock * dev_priv->edp_bpp) / 8;
+	else
+		return pixel_clock * 3;
+}
+
+static int
+intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 {
-	return pixel_clock * 3;
+	return (max_link_clock * max_lanes * 8) / 10;
 }
 
 static int
@@ -137,7 +150,11 @@
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
 	int max_lanes = intel_dp_max_lane_count(intel_output);
 
-	if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes)
+	/* only refuse the mode on non eDP since we have seen some wierd eDP panels
+	   which are outside spec tolerances but somehow work by magic */
+	if (!IS_eDP(intel_output) &&
+	    (intel_dp_link_required(connector->dev, intel_output, mode->clock)
+	     > intel_dp_max_data_rate(max_link_clock, max_lanes)))
 		return MODE_CLOCK_HIGH;
 
 	if (mode->clock < 10000)
@@ -223,8 +240,8 @@
 	 */
 	if (IS_eDP(intel_output))
 		aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-	else if (IS_IGDNG(dev))
-		aux_clock_divider = 62; /* IGDNG: input clock fixed at 125Mhz */
+	else if (IS_IRONLAKE(dev))
+		aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
 	else
 		aux_clock_divider = intel_hrawclk(dev) / 2;
 
@@ -282,7 +299,7 @@
 	/* Timeouts occur when the device isn't connected, so they're
 	 * "normal" -- don't fill the kernel log with these */
 	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
-		DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status);
+		DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status);
 		return -ETIMEDOUT;
 	}
 
@@ -382,17 +399,77 @@
 }
 
 static int
-intel_dp_i2c_aux_ch(struct i2c_adapter *adapter,
-		    uint8_t *send, int send_bytes,
-		    uint8_t *recv, int recv_bytes)
+intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
+		    uint8_t write_byte, uint8_t *read_byte)
 {
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
 	struct intel_dp_priv *dp_priv = container_of(adapter,
 						     struct intel_dp_priv,
 						     adapter);
 	struct intel_output *intel_output = dp_priv->intel_output;
+	uint16_t address = algo_data->address;
+	uint8_t msg[5];
+	uint8_t reply[2];
+	int msg_bytes;
+	int reply_bytes;
+	int ret;
+
+	/* Set up the command byte */
+	if (mode & MODE_I2C_READ)
+		msg[0] = AUX_I2C_READ << 4;
+	else
+		msg[0] = AUX_I2C_WRITE << 4;
+
+	if (!(mode & MODE_I2C_STOP))
+		msg[0] |= AUX_I2C_MOT << 4;
+
+	msg[1] = address >> 8;
+	msg[2] = address;
 
-	return intel_dp_aux_ch(intel_output,
-			       send, send_bytes, recv, recv_bytes);
+	switch (mode) {
+	case MODE_I2C_WRITE:
+		msg[3] = 0;
+		msg[4] = write_byte;
+		msg_bytes = 5;
+		reply_bytes = 1;
+		break;
+	case MODE_I2C_READ:
+		msg[3] = 0;
+		msg_bytes = 4;
+		reply_bytes = 2;
+		break;
+	default:
+		msg_bytes = 3;
+		reply_bytes = 1;
+		break;
+	}
+
+	for (;;) {
+	  ret = intel_dp_aux_ch(intel_output,
+				msg, msg_bytes,
+				reply, reply_bytes);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
+			return ret;
+		}
+		switch (reply[0] & AUX_I2C_REPLY_MASK) {
+		case AUX_I2C_REPLY_ACK:
+			if (mode == MODE_I2C_READ) {
+				*read_byte = reply[1];
+			}
+			return reply_bytes - 1;
+		case AUX_I2C_REPLY_NACK:
+			DRM_DEBUG_KMS("aux_ch nack\n");
+			return -EREMOTEIO;
+		case AUX_I2C_REPLY_DEFER:
+			DRM_DEBUG_KMS("aux_ch defer\n");
+			udelay(100);
+			break;
+		default:
+			DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
+			return -EREMOTEIO;
+		}
+	}
 }
 
 static int
@@ -429,19 +506,33 @@
 
 	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 		for (clock = 0; clock <= max_clock; clock++) {
-			int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 
-			if (intel_dp_link_required(mode->clock) <= link_avail) {
+			if (intel_dp_link_required(encoder->dev, intel_output, mode->clock)
+					<= link_avail) {
 				dp_priv->link_bw = bws[clock];
 				dp_priv->lane_count = lane_count;
 				adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
-				DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n",
+				DRM_DEBUG_KMS("Display port link bw %02x lane "
+						"count %d clock %d\n",
 				       dp_priv->link_bw, dp_priv->lane_count,
 				       adjusted_mode->clock);
 				return true;
 			}
 		}
 	}
+
+	if (IS_eDP(intel_output)) {
+		/* okay we failed just pick the highest */
+		dp_priv->lane_count = max_lane_count;
+		dp_priv->link_bw = bws[max_clock];
+		adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+		DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+			      "count %d clock %d\n",
+			      dp_priv->link_bw, dp_priv->lane_count,
+			      adjusted_mode->clock);
+		return true;
+	}
 	return false;
 }
 
@@ -514,7 +605,7 @@
 	intel_dp_compute_m_n(3, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		if (intel_crtc->pipe == 0) {
 			I915_WRITE(TRANSA_DATA_M1,
 				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
@@ -606,23 +697,68 @@
 	}
 }
 
-static void igdng_edp_backlight_on (struct drm_device *dev)
+static void ironlake_edp_panel_on (struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long timeout = jiffies + msecs_to_jiffies(5000);
+	u32 pp, pp_status;
+
+	pp_status = I915_READ(PCH_PP_STATUS);
+	if (pp_status & PP_ON)
+		return;
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp |= PANEL_UNLOCK_REGS | POWER_TARGET_ON;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	do {
+		pp_status = I915_READ(PCH_PP_STATUS);
+	} while (((pp_status & PP_ON) == 0) && !time_after(jiffies, timeout));
+
+	if (time_after(jiffies, timeout))
+		DRM_DEBUG_KMS("panel on wait timed out: 0x%08x\n", pp_status);
+
+	pp &= ~(PANEL_UNLOCK_REGS | EDP_FORCE_VDD);
+	I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void ironlake_edp_panel_off (struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long timeout = jiffies + msecs_to_jiffies(5000);
+	u32 pp, pp_status;
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp &= ~POWER_TARGET_ON;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	do {
+		pp_status = I915_READ(PCH_PP_STATUS);
+	} while ((pp_status & PP_ON) && !time_after(jiffies, timeout));
+
+	if (time_after(jiffies, timeout))
+		DRM_DEBUG_KMS("panel off wait timed out\n");
+
+	/* Make sure VDD is enabled so DP AUX will work */
+	pp |= EDP_FORCE_VDD;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void ironlake_edp_backlight_on (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 	pp = I915_READ(PCH_PP_CONTROL);
 	pp |= EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
 }
 
-static void igdng_edp_backlight_off (struct drm_device *dev)
+static void ironlake_edp_backlight_off (struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 	pp = I915_READ(PCH_PP_CONTROL);
 	pp &= ~EDP_BLC_ENABLE;
 	I915_WRITE(PCH_PP_CONTROL, pp);
@@ -640,14 +776,18 @@
 	if (mode != DRM_MODE_DPMS_ON) {
 		if (dp_reg & DP_PORT_EN) {
 			intel_dp_link_down(intel_output, dp_priv->DP);
-			if (IS_eDP(intel_output))
-				igdng_edp_backlight_off(dev);
+			if (IS_eDP(intel_output)) {
+				ironlake_edp_backlight_off(dev);
+				ironlake_edp_panel_off(dev);
+			}
 		}
 	} else {
 		if (!(dp_reg & DP_PORT_EN)) {
 			intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
-			if (IS_eDP(intel_output))
-				igdng_edp_backlight_on(dev);
+			if (IS_eDP(intel_output)) {
+				ironlake_edp_panel_on(dev);
+				ironlake_edp_backlight_on(dev);
+			}
 		}
 	}
 	dp_priv->dpms_mode = mode;
@@ -1010,7 +1150,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 
 	if (IS_eDP(intel_output)) {
 		DP &= ~DP_PLL_ENABLE;
@@ -1071,7 +1211,7 @@
 }
 
 static enum drm_connector_status
-igdng_dp_detect(struct drm_connector *connector)
+ironlake_dp_detect(struct drm_connector *connector)
 {
 	struct intel_output *intel_output = to_intel_output(connector);
 	struct intel_dp_priv *dp_priv = intel_output->dev_priv;
@@ -1106,18 +1246,8 @@
 
 	dp_priv->has_audio = false;
 
-	if (IS_IGDNG(dev))
-		return igdng_dp_detect(connector);
-
-	temp = I915_READ(PORT_HOTPLUG_EN);
-
-	I915_WRITE(PORT_HOTPLUG_EN,
-	       temp |
-	       DPB_HOTPLUG_INT_EN |
-	       DPC_HOTPLUG_INT_EN |
-	       DPD_HOTPLUG_INT_EN);
-
-	POSTING_READ(PORT_HOTPLUG_EN);
+	if (IS_IRONLAKE(dev))
+		return ironlake_dp_detect(connector);
 
 	switch (dp_priv->output_reg) {
 	case DP_B:
@@ -1254,18 +1384,17 @@
 	else
 		intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
 
-	if (output_reg == DP_B)
+	if (output_reg == DP_B || output_reg == PCH_DP_B)
 		intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-	else if (output_reg == DP_C)
+	else if (output_reg == DP_C || output_reg == PCH_DP_C)
 		intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-	else if (output_reg == DP_D)
+	else if (output_reg == DP_D || output_reg == PCH_DP_D)
 		intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-	if (IS_eDP(intel_output)) {
-		intel_output->crtc_mask = (1 << 1);
+	if (IS_eDP(intel_output))
 		intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-	} else
-		intel_output->crtc_mask = (1 << 0) | (1 << 1);
+
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
@@ -1290,14 +1419,20 @@
 			break;
 		case DP_B:
 		case PCH_DP_B:
+			dev_priv->hotplug_supported_mask |=
+				HDMIB_HOTPLUG_INT_STATUS;
 			name = "DPDDC-B";
 			break;
 		case DP_C:
 		case PCH_DP_C:
+			dev_priv->hotplug_supported_mask |=
+				HDMIC_HOTPLUG_INT_STATUS;
 			name = "DPDDC-C";
 			break;
 		case DP_D:
 		case PCH_DP_D:
+			dev_priv->hotplug_supported_mask |=
+				HDMID_HOTPLUG_INT_STATUS;
 			name = "DPDDC-D";
 			break;
 	}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_tv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_tv.c
@@ -1213,20 +1213,17 @@
 		tv_ctl |= TV_TRILEVEL_SYNC;
 	if (tv_mode->pal_burst)
 		tv_ctl |= TV_PAL_BURST;
+
 	scctl1 = 0;
-	/* dda1 implies valid video levels */
-	if (tv_mode->dda1_inc) {
+	if (tv_mode->dda1_inc)
 		scctl1 |= TV_SC_DDA1_EN;
-	}
-
 	if (tv_mode->dda2_inc)
 		scctl1 |= TV_SC_DDA2_EN;
-
 	if (tv_mode->dda3_inc)
 		scctl1 |= TV_SC_DDA3_EN;
-
 	scctl1 |= tv_mode->sc_reset;
-	scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
+	if (video_levels)
+		scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
 	scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
 
 	scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
@@ -1416,16 +1413,16 @@
 	 *  0 0 0 Component
 	 */
 	if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
-		DRM_DEBUG("Detected Composite TV connection\n");
+		DRM_DEBUG_KMS("Detected Composite TV connection\n");
 		type = DRM_MODE_CONNECTOR_Composite;
 	} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
-		DRM_DEBUG("Detected S-Video TV connection\n");
+		DRM_DEBUG_KMS("Detected S-Video TV connection\n");
 		type = DRM_MODE_CONNECTOR_SVIDEO;
 	} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
-		DRM_DEBUG("Detected Component TV connection\n");
+		DRM_DEBUG_KMS("Detected Component TV connection\n");
 		type = DRM_MODE_CONNECTOR_Component;
 	} else {
-		DRM_DEBUG("No TV connection detected\n");
+		DRM_DEBUG_KMS("No TV connection detected\n");
 		type = -1;
 	}
 
@@ -1702,6 +1699,41 @@
 	.destroy = intel_tv_enc_destroy,
 };
 
+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the integrated TV is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the TV is present.
+ */
+static int tv_is_present_in_vbt(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i, ret;
+
+	if (!dev_priv->child_dev_num)
+		return 1;
+
+	ret = 0;
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+		/*
+		 * If the device type is not TV, continue.
+		 */
+		if (p_child->device_type != DEVICE_TYPE_INT_TV &&
+			p_child->device_type != DEVICE_TYPE_TV)
+			continue;
+		/* Only when the addin_offset is non-zero, it is regarded
+		 * as present.
+		 */
+		if (p_child->addin_offset) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
 
 void
 intel_tv_init(struct drm_device *dev)
@@ -1717,6 +1749,10 @@
 	if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 		return;
 
+	if (!tv_is_present_in_vbt(dev)) {
+		DRM_DEBUG_KMS("Integrated TV is not present.\n");
+		return;
+	}
 	/* Even if we have an encoder we may not have a connector */
 	if (!dev_priv->int_tv_support)
 		return;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_suspend.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_suspend.c
@@ -27,14 +27,14 @@
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
-#include "i915_drv.h"
+#include "intel_drv.h"
 
 static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32	dpll_reg;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
 	} else {
 		dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
@@ -53,7 +53,7 @@
 	if (!i915_pipe_enabled(dev, pipe))
 		return;
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
@@ -75,7 +75,7 @@
 	if (!i915_pipe_enabled(dev, pipe))
 		return;
 
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
@@ -239,7 +239,7 @@
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
 		dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
 	}
@@ -247,7 +247,7 @@
 	/* Pipe & plane A info */
 	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
 	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
 		dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
 		dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
@@ -256,7 +256,7 @@
 		dev_priv->saveFPA1 = I915_READ(FPA1);
 		dev_priv->saveDPLL_A = I915_READ(DPLL_A);
 	}
-	if (IS_I965G(dev) && !IS_IGDNG(dev))
+	if (IS_I965G(dev) && !IS_IRONLAKE(dev))
 		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
 	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
 	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
@@ -264,10 +264,10 @@
 	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
 	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
 	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
-	if (!IS_IGDNG(dev))
+	if (!IS_IRONLAKE(dev))
 		dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
 		dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
 		dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
@@ -304,7 +304,7 @@
 	/* Pipe & plane B info */
 	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
 	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
 		dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
 		dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
@@ -313,7 +313,7 @@
 		dev_priv->saveFPB1 = I915_READ(FPB1);
 		dev_priv->saveDPLL_B = I915_READ(DPLL_B);
 	}
-	if (IS_I965G(dev) && !IS_IGDNG(dev))
+	if (IS_I965G(dev) && !IS_IRONLAKE(dev))
 		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
 	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
 	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
@@ -321,10 +321,10 @@
 	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
 	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
 	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
-	if (!IS_IGDNG(dev))
+	if (!IS_IRONLAKE(dev))
 		dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
 		dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
 		dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
@@ -369,7 +369,7 @@
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dpll_a_reg = PCH_DPLL_A;
 		dpll_b_reg = PCH_DPLL_B;
 		fpa0_reg = PCH_FPA0;
@@ -385,7 +385,7 @@
 		fpb1_reg = FPB1;
 	}
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
 		I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
 	}
@@ -402,7 +402,7 @@
 	/* Actually enable it */
 	I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
 	DRM_UDELAY(150);
-	if (IS_I965G(dev) && !IS_IGDNG(dev))
+	if (IS_I965G(dev) && !IS_IRONLAKE(dev))
 		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
 	DRM_UDELAY(150);
 
@@ -413,10 +413,10 @@
 	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
 	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
 	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-	if (!IS_IGDNG(dev))
+	if (!IS_IRONLAKE(dev))
 		I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
 		I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
 		I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
@@ -467,7 +467,7 @@
 	/* Actually enable it */
 	I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
 	DRM_UDELAY(150);
-	if (IS_I965G(dev) && !IS_IGDNG(dev))
+	if (IS_I965G(dev) && !IS_IRONLAKE(dev))
 		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
 	DRM_UDELAY(150);
 
@@ -478,10 +478,10 @@
 	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
 	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
 	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-	if (!IS_IGDNG(dev))
+	if (!IS_IRONLAKE(dev))
 		I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
 		I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
 		I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
@@ -546,14 +546,14 @@
 		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
 
 	/* CRT state */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->saveADPA = I915_READ(PCH_ADPA);
 	} else {
 		dev_priv->saveADPA = I915_READ(ADPA);
 	}
 
 	/* LVDS state */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
 		dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
 		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
@@ -571,10 +571,10 @@
 			dev_priv->saveLVDS = I915_READ(LVDS);
 	}
 
-	if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev))
+	if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev))
 		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
 		dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
 		dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
@@ -614,7 +614,7 @@
 	dev_priv->saveVGA0 = I915_READ(VGA0);
 	dev_priv->saveVGA1 = I915_READ(VGA1);
 	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
 	else
 		dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
@@ -656,24 +656,24 @@
 		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
 
 	/* CRT state */
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
 	else
 		I915_WRITE(ADPA, dev_priv->saveADPA);
 
 	/* LVDS state */
-	if (IS_I965G(dev) && !IS_IGDNG(dev))
+	if (IS_I965G(dev) && !IS_IRONLAKE(dev))
 		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
 	} else if (IS_MOBILE(dev) && !IS_I830(dev))
 		I915_WRITE(LVDS, dev_priv->saveLVDS);
 
-	if (!IS_I830(dev) && !IS_845G(dev) && !IS_IGDNG(dev))
+	if (!IS_I830(dev) && !IS_845G(dev) && !IS_IRONLAKE(dev))
 		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
 
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
 		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
 		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
@@ -713,7 +713,7 @@
 	}
 
 	/* VGA state */
-	if (IS_IGDNG(dev))
+	if (IS_IRONLAKE(dev))
 		I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
 	else
 		I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
@@ -732,17 +732,13 @@
 
 	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
-	/* Render Standby */
-	if (IS_I965G(dev) && IS_MOBILE(dev))
-		dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
-
 	/* Hardware status page */
 	dev_priv->saveHWS = I915_READ(HWS_PGA);
 
 	i915_save_display(dev);
 
 	/* Interrupt state */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		dev_priv->saveDEIER = I915_READ(DEIER);
 		dev_priv->saveDEIMR = I915_READ(DEIMR);
 		dev_priv->saveGTIER = I915_READ(GTIER);
@@ -754,10 +750,6 @@
 		dev_priv->saveIMR = I915_READ(IMR);
 	}
 
-	/* Clock gating state */
-	dev_priv->saveD_STATE = I915_READ(D_STATE);
-	dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); /* Not sure about this */
-
 	/* Cache mode state */
 	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
 
@@ -795,10 +787,6 @@
 
 	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
-	/* Render Standby */
-	if (IS_I965G(dev) && IS_MOBILE(dev))
-		I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
-
 	/* Hardware status page */
 	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
 
@@ -817,7 +805,7 @@
 	i915_restore_display(dev);
 
 	/* Interrupt state */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(DEIER, dev_priv->saveDEIER);
 		I915_WRITE(DEIMR, dev_priv->saveDEIMR);
 		I915_WRITE(GTIER, dev_priv->saveGTIER);
@@ -830,8 +818,7 @@
 	}
 
 	/* Clock gating state */
-	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
-	I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
+	intel_init_clock_gating(dev);
 
 	/* Cache mode state */
 	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
@@ -846,6 +833,9 @@
 	for (i = 0; i < 3; i++)
 		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
 
+	/* I2C state */
+	intel_i2c_reset_gmbus(dev);
+
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_drv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_drv.h
@@ -170,9 +170,34 @@
 	/* clock gating init */
 };
 
+struct intel_overlay;
+
+struct intel_device_info {
+	u8 is_mobile : 1;
+	u8 is_i8xx : 1;
+	u8 is_i85x : 1;
+	u8 is_i915g : 1;
+	u8 is_i9xx : 1;
+	u8 is_i945gm : 1;
+	u8 is_i965g : 1;
+	u8 is_i965gm : 1;
+	u8 is_g33 : 1;
+	u8 need_gfx_hws : 1;
+	u8 is_g4x : 1;
+	u8 is_pineview : 1;
+	u8 is_ironlake : 1;
+	u8 has_fbc : 1;
+	u8 has_rc6 : 1;
+	u8 has_pipe_cxsr : 1;
+	u8 has_hotplug : 1;
+	u8 cursor_needs_physical : 1;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 
+	const struct intel_device_info *info;
+
 	int has_gem;
 
 	void __iomem *regs;
@@ -182,11 +207,15 @@
 
 	drm_dma_handle_t *status_page_dmah;
 	void *hw_status_page;
+	void *seqno_page;
 	dma_addr_t dma_status_page;
 	uint32_t counter;
 	unsigned int status_gfx_addr;
+	unsigned int seqno_gfx_addr;
 	drm_local_map_t hws_map;
 	struct drm_gem_object *hws_obj;
+	struct drm_gem_object *seqno_obj;
+	struct drm_gem_object *pwrctx;
 
 	struct resource mch_res;
 
@@ -206,11 +235,13 @@
 	/** Cached value of IMR to avoid reads in updating the bitfield */
 	u32 irq_mask_reg;
 	u32 pipestat[2];
-	/** splitted irq regs for graphics and display engine on IGDNG,
+	/** splitted irq regs for graphics and display engine on Ironlake,
 	    irq_mask_reg is still used for display irq. */
 	u32 gt_irq_mask_reg;
 	u32 gt_irq_enable_reg;
 	u32 de_irq_enable_reg;
+	u32 pch_irq_mask_reg;
+	u32 pch_irq_enable_reg;
 
 	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
@@ -227,8 +258,6 @@
 	int hangcheck_count;
 	uint32_t last_acthd;
 
-	bool cursor_needs_physical;
-
 	struct drm_mm vram;
 
 	unsigned long cfb_size;
@@ -240,6 +269,9 @@
 
 	struct intel_opregion opregion;
 
+	/* overlay */
+	struct intel_overlay *overlay;
+
 	/* LVDS info */
 	int backlight_duty_cycle;  /* restore backlight to this value */
 	bool panel_wants_dither;
@@ -255,10 +287,11 @@
 	unsigned int lvds_use_ssc:1;
 	unsigned int edp_support:1;
 	int lvds_ssc_freq;
+	int edp_bpp;
 
 	struct notifier_block lid_notifier;
 
-	int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
+	int crt_ddc_bus; /* 0 = unknown, else GPIO to use for CRT DDC */
 	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@@ -279,7 +312,6 @@
 	u32 saveDSPACNTR;
 	u32 saveDSPBCNTR;
 	u32 saveDSPARB;
-	u32 saveRENDERSTANDBY;
 	u32 saveHWS;
 	u32 savePIPEACONF;
 	u32 savePIPEBCONF;
@@ -374,8 +406,6 @@
 	u32 saveFDI_RXA_IMR;
 	u32 saveFDI_RXB_IMR;
 	u32 saveCACHE_MODE_0;
-	u32 saveD_STATE;
-	u32 saveDSPCLK_GATE_D;
 	u32 saveMI_ARB_STATE;
 	u32 saveSWF0[16];
 	u32 saveSWF1[16];
@@ -467,6 +497,15 @@
 		struct list_head flushing_list;
 
 		/**
+		 * List of objects currently pending a GPU write flush.
+		 *
+		 * All elements on this list will belong to either the
+		 * active_list or flushing_list, last_rendering_seqno can
+		 * be used to differentiate between the two elements.
+		 */
+		struct list_head gpu_write_list;
+
+		/**
 		 * LRU list of objects which are not in the ringbuffer and
 		 * are ready to unbind, but are still in the GTT.
 		 *
@@ -539,13 +578,23 @@
 	/* indicate whether the LVDS_BORDER should be enabled or not */
 	unsigned int lvds_border_bits;
 
+	struct drm_crtc *plane_to_crtc_mapping[2];
+	struct drm_crtc *pipe_to_crtc_mapping[2];
+	wait_queue_head_t pending_flip_queue;
+	bool flip_pending_is_done;
+
 	/* Reclocking support */
 	bool render_reclock_avail;
 	bool lvds_downclock_avail;
+	/* indicates the reduced downclock for LVDS*/
+	int lvds_downclock;
 	struct work_struct idle_work;
 	struct timer_list idle_timer;
 	bool busy;
 	u16 orig_clock;
+	int child_dev_num;
+	struct child_device_config *child_dev;
+	struct drm_connector *int_lvds_connector;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
@@ -557,6 +606,8 @@
 
 	/** This object's place on the active/flushing/inactive lists */
 	struct list_head list;
+	/** This object's place on GPU write list */
+	struct list_head gpu_write_list;
 
 	/** This object's place on the fenced object LRU */
 	struct list_head fence_list;
@@ -638,6 +689,13 @@
 	 * Advice: are the backing pages purgeable?
 	 */
 	int madv;
+
+	/**
+	 * Number of crtcs where this object is currently the fb, but
+	 * will be page flipped away on the next vblank.  When it
+	 * reaches 0, dev_priv->pending_flip_queue will be woken up.
+	 */
+	atomic_t pending_flip;
 };
 
 /**
@@ -681,6 +739,7 @@
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc;
 extern unsigned int i915_powersave;
+extern unsigned int i915_lvds_downclock;
 
 extern void i915_save_display(struct drm_device *dev);
 extern void i915_restore_display(struct drm_device *dev);
@@ -738,6 +797,8 @@
 void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
 
+void intel_enable_asle (struct drm_device *dev);
+
 
 /* i915_mem.c */
 extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -770,6 +831,8 @@
 			     struct drm_file *file_priv);
 int i915_gem_execbuffer(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
+int i915_gem_execbuffer2(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
 int i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
 int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
@@ -813,17 +876,22 @@
 int i915_gem_do_init(struct drm_device *dev, unsigned long start,
 		     unsigned long end);
 int i915_gem_idle(struct drm_device *dev);
+uint32_t i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
+			  uint32_t flush_domains);
+int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
 				      int write);
+int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj);
 int i915_gem_attach_phys_object(struct drm_device *dev,
 				struct drm_gem_object *obj, int id);
 void i915_gem_detach_phys_object(struct drm_device *dev,
 				 struct drm_gem_object *obj);
 void i915_gem_free_all_phys_object(struct drm_device *dev);
-int i915_gem_object_get_pages(struct drm_gem_object *obj);
+int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
 void i915_gem_object_put_pages(struct drm_gem_object *obj);
 void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
+void i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
 
 void i915_gem_shrinker_init(void);
 void i915_gem_shrinker_exit(void);
@@ -832,6 +900,9 @@
 void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
 void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
 void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
+bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
+		    int tiling_mode);
+bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
 
 /* i915_gem_debug.c */
 void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@ -863,11 +934,13 @@
 extern int intel_opregion_init(struct drm_device *dev, int resume);
 extern void intel_opregion_free(struct drm_device *dev, int suspend);
 extern void opregion_asle_intr(struct drm_device *dev);
+extern void ironlake_opregion_gse_intr(struct drm_device *dev);
 extern void opregion_enable_asle(struct drm_device *dev);
 #else
 static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
 static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
 static inline void opregion_asle_intr(struct drm_device *dev) { return; }
+static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
 static inline void opregion_enable_asle(struct drm_device *dev) { return; }
 #endif
 
@@ -952,85 +1025,78 @@
 extern int i915_wrap_ring(struct drm_device * dev);
 extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
-#define IS_I830(dev) ((dev)->pci_device == 0x3577)
-#define IS_845G(dev) ((dev)->pci_device == 0x2562)
-#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
-#define IS_I855(dev) ((dev)->pci_device == 0x3582)
-#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
-
-#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
-#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
-#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
-		        (dev)->pci_device == 0x27AE)
-#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
-		       (dev)->pci_device == 0x2982 || \
-		       (dev)->pci_device == 0x2992 || \
-		       (dev)->pci_device == 0x29A2 || \
-		       (dev)->pci_device == 0x2A02 || \
-		       (dev)->pci_device == 0x2A12 || \
-		       (dev)->pci_device == 0x2A42 || \
-		       (dev)->pci_device == 0x2E02 || \
-		       (dev)->pci_device == 0x2E12 || \
-		       (dev)->pci_device == 0x2E22 || \
-		       (dev)->pci_device == 0x2E32 || \
-		       (dev)->pci_device == 0x2E42 || \
-		       (dev)->pci_device == 0x0042 || \
-		       (dev)->pci_device == 0x0046)
-
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \
-			(dev)->pci_device == 0x2A12)
-
-#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
-
-#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
-		     (dev)->pci_device == 0x2E12 || \
-		     (dev)->pci_device == 0x2E22 || \
-		     (dev)->pci_device == 0x2E32 || \
-		     (dev)->pci_device == 0x2E42 || \
-		     IS_GM45(dev))
-
-#define IS_IGDG(dev) ((dev)->pci_device == 0xa001)
-#define IS_IGDGM(dev) ((dev)->pci_device == 0xa011)
-#define IS_IGD(dev) (IS_IGDG(dev) || IS_IGDGM(dev))
-
-#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 ||	\
-			(dev)->pci_device == 0x29B2 ||	\
-			(dev)->pci_device == 0x29D2 ||  \
-			(IS_IGD(dev)))
-
-#define IS_IGDNG_D(dev)	((dev)->pci_device == 0x0042)
-#define IS_IGDNG_M(dev)	((dev)->pci_device == 0x0046)
-#define IS_IGDNG(dev)	(IS_IGDNG_D(dev) || IS_IGDNG_M(dev))
-
-#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
-		      IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \
-		      IS_IGDNG(dev))
-
-#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-			IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \
-			IS_IGD(dev) || IS_IGDNG_M(dev))
+#define INTEL_INFO(dev)	(((struct drm_i915_private *) (dev)->dev_private)->info)
+
+#define IS_I830(dev)		((dev)->pci_device == 0x3577)
+#define IS_845G(dev)		((dev)->pci_device == 0x2562)
+#define IS_I85X(dev)		(INTEL_INFO(dev)->is_i85x)
+#define IS_I865G(dev)		((dev)->pci_device == 0x2572)
+#define IS_GEN2(dev)		(INTEL_INFO(dev)->is_i8xx)
+#define IS_I915G(dev)		(INTEL_INFO(dev)->is_i915g)
+#define IS_I915GM(dev)		((dev)->pci_device == 0x2592)
+#define IS_I945G(dev)		((dev)->pci_device == 0x2772)
+#define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
+#define IS_I965G(dev)		(INTEL_INFO(dev)->is_i965g)
+#define IS_I965GM(dev)		(INTEL_INFO(dev)->is_i965gm)
+#define IS_GM45(dev)		((dev)->pci_device == 0x2A42)
+#define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
+#define IS_PINEVIEW_G(dev)	((dev)->pci_device == 0xa001)
+#define IS_PINEVIEW_M(dev)	((dev)->pci_device == 0xa011)
+#define IS_PINEVIEW(dev)	(INTEL_INFO(dev)->is_pineview)
+#define IS_G33(dev)		(INTEL_INFO(dev)->is_g33)
+#define IS_IRONLAKE_D(dev)	((dev)->pci_device == 0x0042)
+#define IS_IRONLAKE_M(dev)	((dev)->pci_device == 0x0046)
+#define IS_IRONLAKE(dev)	(INTEL_INFO(dev)->is_ironlake)
+#define IS_I9XX(dev)		(INTEL_INFO(dev)->is_i9xx)
+#define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
+
+#define IS_GEN3(dev)	(IS_I915G(dev) ||			\
+			 IS_I915GM(dev) ||			\
+			 IS_I945G(dev) ||			\
+			 IS_I945GM(dev) ||			\
+			 IS_G33(dev) || \
+			 IS_PINEVIEW(dev))
+#define IS_GEN4(dev)	((dev)->pci_device == 0x2972 ||		\
+			 (dev)->pci_device == 0x2982 ||		\
+			 (dev)->pci_device == 0x2992 ||		\
+			 (dev)->pci_device == 0x29A2 ||		\
+			 (dev)->pci_device == 0x2A02 ||		\
+			 (dev)->pci_device == 0x2A12 ||		\
+			 (dev)->pci_device == 0x2E02 ||		\
+			 (dev)->pci_device == 0x2E12 ||		\
+			 (dev)->pci_device == 0x2E22 ||		\
+			 (dev)->pci_device == 0x2E32 ||		\
+			 (dev)->pci_device == 0x2A42 ||		\
+			 (dev)->pci_device == 0x2E42 ||		\
+			 (dev)->pci_device == 0x2E92)
+
+#define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
+
+#define IS_GEN6(dev)	((dev)->pci_device == 0x0102)
 
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \
-				IS_IGDNG(dev))
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
 #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
 						      IS_I915GM(dev)))
-#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev) || IS_IGDNG(dev))
-#define SUPPORTS_INTEGRATED_DP(dev)	(IS_G4X(dev) || IS_IGDNG(dev))
-#define SUPPORTS_EDP(dev)		(IS_IGDNG_M(dev))
-#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev))
+#define SUPPORTS_DIGITAL_OUTPUTS(dev)	(IS_I9XX(dev) && !IS_PINEVIEW(dev))
+#define SUPPORTS_INTEGRATED_HDMI(dev)	(IS_G4X(dev) || IS_IRONLAKE(dev))
+#define SUPPORTS_INTEGRATED_DP(dev)	(IS_G4X(dev) || IS_IRONLAKE(dev))
+#define SUPPORTS_EDP(dev)		(IS_IRONLAKE_M(dev))
+#define SUPPORTS_TV(dev)		(IS_I9XX(dev) && IS_MOBILE(dev) && \
+					!IS_IRONLAKE(dev) && !IS_PINEVIEW(dev))
+#define I915_HAS_HOTPLUG(dev)		 (INTEL_INFO(dev)->has_hotplug)
 /* dsparb controlled by hw only */
-#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
+#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
 
-#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
-#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
-#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \
-			   (IS_I9XX(dev) || IS_GM45(dev)) && \
-			   !IS_IGD(dev) && \
-			   !IS_IGDNG(dev))
+#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev))
+#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
+#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
+
+#define HAS_PCH_SPLIT(dev) (IS_IRONLAKE(dev) ||	\
+			    IS_GEN6(dev))
+#define HAS_PIPE_CONTROL(dev) (IS_IRONLAKE(dev) || IS_GEN6(dev))
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_gem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_gem.c
@@ -277,7 +277,7 @@
 
 	mutex_lock(&dev->struct_mutex);
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_get_pages(obj, 0);
 	if (ret != 0)
 		goto fail_unlock;
 
@@ -321,40 +321,24 @@
 	return ret;
 }
 
-static inline gfp_t
-i915_gem_object_get_page_gfp_mask (struct drm_gem_object *obj)
-{
-	return mapping_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping);
-}
-
-static inline void
-i915_gem_object_set_page_gfp_mask (struct drm_gem_object *obj, gfp_t gfp)
-{
-	mapping_set_gfp_mask(obj->filp->f_path.dentry->d_inode->i_mapping, gfp);
-}
-
 static int
 i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj)
 {
 	int ret;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN);
 
 	/* If we've insufficient memory to map in the pages, attempt
 	 * to make some space by throwing out some old buffers.
 	 */
 	if (ret == -ENOMEM) {
 		struct drm_device *dev = obj->dev;
-		gfp_t gfp;
 
 		ret = i915_gem_evict_something(dev, obj->size);
 		if (ret)
 			return ret;
 
-		gfp = i915_gem_object_get_page_gfp_mask(obj);
-		i915_gem_object_set_page_gfp_mask(obj, gfp & ~__GFP_NORETRY);
-		ret = i915_gem_object_get_pages(obj);
-		i915_gem_object_set_page_gfp_mask (obj, gfp);
+		ret = i915_gem_object_get_pages(obj, 0);
 	}
 
 	return ret;
@@ -498,14 +482,17 @@
 		return -EBADF;
 	obj_priv = obj->driver_private;
 
-	/* Bounds check source.
-	 *
-	 * XXX: This could use review for overflow issues...
-	 */
-	if (args->offset > obj->size || args->size > obj->size ||
-	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference(obj);
-		return -EINVAL;
+	/* Bounds check source.  */
+	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!access_ok(VERIFY_WRITE,
+		       (char __user *)(uintptr_t)args->data_ptr,
+		       args->size)) {
+		ret = -EFAULT;
+		goto err;
 	}
 
 	if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -517,8 +504,8 @@
 							file_priv);
 	}
 
+err:
 	drm_gem_object_unreference(obj);
-
 	return ret;
 }
 
@@ -608,8 +595,6 @@
 
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	remain = args->size;
-	if (!access_ok(VERIFY_READ, user_data, remain))
-		return -EFAULT;
 
 
 	mutex_lock(&dev->struct_mutex);
@@ -790,7 +775,7 @@
 
 	mutex_lock(&dev->struct_mutex);
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_get_pages(obj, 0);
 	if (ret != 0)
 		goto fail_unlock;
 
@@ -971,14 +956,17 @@
 		return -EBADF;
 	obj_priv = obj->driver_private;
 
-	/* Bounds check destination.
-	 *
-	 * XXX: This could use review for overflow issues...
-	 */
-	if (args->offset > obj->size || args->size > obj->size ||
-	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference(obj);
-		return -EINVAL;
+	/* Bounds check destination. */
+	if (args->offset > obj->size || args->size > obj->size - args->offset) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!access_ok(VERIFY_READ,
+		       (char __user *)(uintptr_t)args->data_ptr,
+		       args->size)) {
+		ret = -EFAULT;
+		goto err;
 	}
 
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -1011,8 +999,8 @@
 		DRM_INFO("pwrite failed %d\n", ret);
 #endif
 
+err:
 	drm_gem_object_unreference(obj);
-
 	return ret;
 }
 
@@ -1288,6 +1276,7 @@
 	list->hash.key = list->file_offset_node->start;
 	if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) {
 		DRM_ERROR("failed to add to map hash\n");
+		ret = -ENOMEM;
 		goto out_free_mm;
 	}
 
@@ -1309,7 +1298,7 @@
  * i915_gem_release_mmap - remove physical page mappings
  * @obj: obj in question
  *
- * Preserve the reservation of the mmaping with the DRM core code, but
+ * Preserve the reservation of the mmapping with the DRM core code, but
  * relinquish ownership of the pages back to the system.
  *
  * It is vital that we remove the page mapping if we have mapped a tiled
@@ -1485,9 +1474,6 @@
 		obj_priv->dirty = 0;
 
 	for (i = 0; i < page_count; i++) {
-		if (obj_priv->pages[i] == NULL)
-			break;
-
 		if (obj_priv->dirty)
 			set_page_dirty(obj_priv->pages[i]);
 
@@ -1567,6 +1553,8 @@
 	else
 		list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
 
+	BUG_ON(!list_empty(&obj_priv->gpu_write_list));
+
 	obj_priv->last_rendering_seqno = 0;
 	if (obj_priv->active) {
 		obj_priv->active = 0;
@@ -1575,6 +1563,13 @@
 	i915_verify_inactive(dev, __FILE__, __LINE__);
 }
 
+#define PIPE_CONTROL_FLUSH(addr)					\
+	OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
+		 PIPE_CONTROL_DEPTH_STALL);				\
+	OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);			\
+	OUT_RING(0);							\
+	OUT_RING(0);							\
+
 /**
  * Creates a new sequence number, emitting a write of it to the status page
  * plus an interrupt, which will trigger i915_user_interrupt_handler.
@@ -1583,7 +1578,7 @@
  *
  * Returned sequence numbers are nonzero on success.
  */
-static uint32_t
+uint32_t
 i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
 		 uint32_t flush_domains)
 {
@@ -1609,15 +1604,49 @@
 	if (dev_priv->mm.next_gem_seqno == 0)
 		dev_priv->mm.next_gem_seqno++;
 
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_STORE_DWORD_INDEX);
-	OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	OUT_RING(seqno);
+	if (HAS_PIPE_CONTROL(dev)) {
+		u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
 
-	OUT_RING(MI_USER_INTERRUPT);
-	ADVANCE_LP_RING();
+		/*
+		 * Workaround qword write incoherence by flushing the
+		 * PIPE_NOTIFY buffers out to memory before requesting
+		 * an interrupt.
+		 */
+		BEGIN_LP_RING(32);
+		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
+		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+		OUT_RING(seqno);
+		OUT_RING(0);
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		scratch_addr += 128; /* write to separate cachelines */
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		scratch_addr += 128;
+		PIPE_CONTROL_FLUSH(scratch_addr);
+		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+			 PIPE_CONTROL_NOTIFY);
+		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+		OUT_RING(seqno);
+		OUT_RING(0);
+		ADVANCE_LP_RING();
+	} else {
+		BEGIN_LP_RING(4);
+		OUT_RING(MI_STORE_DWORD_INDEX);
+		OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+		OUT_RING(seqno);
+
+		OUT_RING(MI_USER_INTERRUPT);
+		ADVANCE_LP_RING();
+	}
 
-	DRM_DEBUG("%d\n", seqno);
+	DRM_DEBUG_DRIVER("%d\n", seqno);
 
 	request->seqno = seqno;
 	request->emitted_jiffies = jiffies;
@@ -1637,7 +1666,8 @@
 		struct drm_i915_gem_object *obj_priv, *next;
 
 		list_for_each_entry_safe(obj_priv, next,
-					 &dev_priv->mm.flushing_list, list) {
+					 &dev_priv->mm.gpu_write_list,
+					 gpu_write_list) {
 			struct drm_gem_object *obj = obj_priv->obj;
 
 			if ((obj->write_domain & flush_domains) ==
@@ -1645,6 +1675,7 @@
 				uint32_t old_write_domain = obj->write_domain;
 
 				obj->write_domain = 0;
+				list_del_init(&obj_priv->gpu_write_list);
 				i915_gem_object_move_to_active(obj, seqno);
 
 				trace_i915_gem_object_change_domain(obj,
@@ -1758,7 +1789,10 @@
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
+	if (HAS_PIPE_CONTROL(dev))
+		return ((volatile u32 *)(dev_priv->seqno_page))[0];
+	else
+		return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
 }
 
 /**
@@ -1820,12 +1854,8 @@
 	mutex_unlock(&dev->struct_mutex);
 }
 
-/**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
-static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno)
+int
+i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 ier;
@@ -1837,7 +1867,7 @@
 		return -EIO;
 
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
-		if (IS_IGDNG(dev))
+		if (HAS_PCH_SPLIT(dev))
 			ier = I915_READ(DEIER) | I915_READ(GTIER);
 		else
 			ier = I915_READ(IER);
@@ -1852,10 +1882,15 @@
 
 		dev_priv->mm.waiting_gem_seqno = seqno;
 		i915_user_irq_get(dev);
-		ret = wait_event_interruptible(dev_priv->irq_queue,
-					       i915_seqno_passed(i915_get_gem_seqno(dev),
-								 seqno) ||
-					       atomic_read(&dev_priv->mm.wedged));
+		if (interruptible)
+			ret = wait_event_interruptible(dev_priv->irq_queue,
+				i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
+				atomic_read(&dev_priv->mm.wedged));
+		else
+			wait_event(dev_priv->irq_queue,
+				i915_seqno_passed(i915_get_gem_seqno(dev), seqno) ||
+				atomic_read(&dev_priv->mm.wedged));
+
 		i915_user_irq_put(dev);
 		dev_priv->mm.waiting_gem_seqno = 0;
 
@@ -1879,6 +1914,16 @@
 	return ret;
 }
 
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+static int
+i915_wait_request(struct drm_device *dev, uint32_t seqno)
+{
+	return i915_do_wait_request(dev, seqno, 1);
+}
+
 static void
 i915_gem_flush(struct drm_device *dev,
 	       uint32_t invalidate_domains,
@@ -1947,7 +1992,7 @@
 #endif
 		BEGIN_LP_RING(2);
 		OUT_RING(cmd);
-		OUT_RING(0); /* noop */
+		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
 	}
 }
@@ -2009,9 +2054,6 @@
 	/* blow away mappings if mapped through GTT */
 	i915_gem_release_mmap(obj);
 
-	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-		i915_gem_clear_fence_reg(obj);
-
 	/* Move the object to the CPU domain to ensure that
 	 * any possible CPU writes while it's not in the GTT
 	 * are flushed when we go to remap it. This will
@@ -2027,6 +2069,10 @@
 
 	BUG_ON(obj_priv->active);
 
+	/* release the fence reg _after_ flushing */
+	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+		i915_gem_clear_fence_reg(obj);
+
 	if (obj_priv->agp_mem != NULL) {
 		drm_unbind_agp(obj_priv->agp_mem);
 		drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE);
@@ -2087,8 +2133,8 @@
 i915_gem_evict_everything(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t seqno;
 	int ret;
+	uint32_t seqno;
 	bool lists_empty;
 
 	spin_lock(&dev_priv->mm.active_list_lock);
@@ -2110,6 +2156,8 @@
 	if (ret)
 		return ret;
 
+	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+
 	ret = i915_gem_evict_from_inactive_list(dev);
 	if (ret)
 		return ret;
@@ -2217,14 +2265,14 @@
 }
 
 int
-i915_gem_object_get_pages(struct drm_gem_object *obj)
+i915_gem_object_get_pages(struct drm_gem_object *obj,
+			  gfp_t gfpmask)
 {
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int page_count, i;
 	struct address_space *mapping;
 	struct inode *inode;
 	struct page *page;
-	int ret;
 
 	if (obj_priv->pages_refcount++ != 0)
 		return 0;
@@ -2243,12 +2291,14 @@
 	inode = obj->filp->f_path.dentry->d_inode;
 	mapping = inode->i_mapping;
 	for (i = 0; i < page_count; i++) {
-		page = read_mapping_page(mapping, i, NULL);
-		if (IS_ERR(page)) {
-			ret = PTR_ERR(page);
-			i915_gem_object_put_pages(obj);
-			return ret;
-		}
+		page = read_cache_page_gfp(mapping, i,
+					   GFP_HIGHUSER |
+					   __GFP_COLD |
+					   __GFP_RECLAIMABLE |
+					   gfpmask);
+		if (IS_ERR(page))
+			goto err_pages;
+
 		obj_priv->pages[i] = page;
 	}
 
@@ -2256,6 +2306,15 @@
 		i915_gem_object_do_bit_17_swizzle(obj);
 
 	return 0;
+
+err_pages:
+	while (i--)
+		page_cache_release(obj_priv->pages[i]);
+
+	drm_free_large(obj_priv->pages);
+	obj_priv->pages = NULL;
+	obj_priv->pages_refcount--;
+	return PTR_ERR(page);
 }
 
 static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
@@ -2306,6 +2365,12 @@
 	pitch_val = obj_priv->stride / tile_width;
 	pitch_val = ffs(pitch_val) - 1;
 
+	if (obj_priv->tiling_mode == I915_TILING_Y &&
+	    HAS_128_BYTE_Y_TILING(dev))
+		WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
+	else
+		WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL);
+
 	val = obj_priv->gtt_offset;
 	if (obj_priv->tiling_mode == I915_TILING_Y)
 		val |= 1 << I830_FENCE_TILING_Y_SHIFT;
@@ -2566,12 +2631,9 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	struct drm_mm_node *free_space;
-	bool retry_alloc = false;
+	gfp_t gfpmask =  __GFP_NORETRY | __GFP_NOWARN;
 	int ret;
 
-	if (dev_priv->mm.suspended)
-		return -EBUSY;
-
 	if (obj_priv->madv != I915_MADV_WILLNEED) {
 		DRM_ERROR("Attempting to bind a purgeable object\n");
 		return -EINVAL;
@@ -2584,6 +2646,14 @@
 		return -EINVAL;
 	}
 
+	/* If the object is bigger than the entire aperture, reject it early
+	 * before evicting everything in a vain attempt to find space.
+	 */
+	if (obj->size > dev->gtt_total) {
+		DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+		return -E2BIG;
+	}
+
  search_free:
 	free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
 					obj->size, alignment, 0);
@@ -2613,15 +2683,7 @@
 	DRM_INFO("Binding object of size %zd at 0x%08x\n",
 		 obj->size, obj_priv->gtt_offset);
 #endif
-	if (retry_alloc) {
-		i915_gem_object_set_page_gfp_mask (obj,
-						   i915_gem_object_get_page_gfp_mask (obj) & ~__GFP_NORETRY);
-	}
-	ret = i915_gem_object_get_pages(obj);
-	if (retry_alloc) {
-		i915_gem_object_set_page_gfp_mask (obj,
-						   i915_gem_object_get_page_gfp_mask (obj) | __GFP_NORETRY);
-	}
+	ret = i915_gem_object_get_pages(obj, gfpmask);
 	if (ret) {
 		drm_mm_put_block(obj_priv->gtt_space);
 		obj_priv->gtt_space = NULL;
@@ -2631,9 +2693,9 @@
 			ret = i915_gem_evict_something(dev, obj->size);
 			if (ret) {
 				/* now try to shrink everyone else */
-				if (! retry_alloc) {
-				    retry_alloc = true;
-				    goto search_free;
+				if (gfpmask) {
+					gfpmask = 0;
+					goto search_free;
 				}
 
 				return ret;
@@ -2711,7 +2773,7 @@
 	old_write_domain = obj->write_domain;
 	i915_gem_flush(dev, 0, obj->write_domain);
 	seqno = i915_add_request(dev, NULL, obj->write_domain);
-	obj->write_domain = 0;
+	BUG_ON(obj->write_domain);
 	i915_gem_object_move_to_active(obj, seqno);
 
 	trace_i915_gem_object_change_domain(obj,
@@ -2760,6 +2822,22 @@
 					    old_write_domain);
 }
 
+void
+i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
+{
+	switch (obj->write_domain) {
+	case I915_GEM_DOMAIN_GTT:
+		i915_gem_object_flush_gtt_write_domain(obj);
+		break;
+	case I915_GEM_DOMAIN_CPU:
+		i915_gem_object_flush_cpu_write_domain(obj);
+		break;
+	default:
+		i915_gem_object_flush_gpu_write_domain(obj);
+		break;
+	}
+}
+
 /**
  * Moves a single object to the GTT read, and possibly write domain.
  *
@@ -2811,6 +2889,57 @@
 	return 0;
 }
 
+/*
+ * Prepare buffer for display plane. Use uninterruptible for possible flush
+ * wait, as in modesetting process we're not supposed to be interrupted.
+ */
+int
+i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	uint32_t old_write_domain, old_read_domains;
+	int ret;
+
+	/* Not valid to be called on unbound objects. */
+	if (obj_priv->gtt_space == NULL)
+		return -EINVAL;
+
+	i915_gem_object_flush_gpu_write_domain(obj);
+
+	/* Wait on any GPU rendering and flushing to occur. */
+	if (obj_priv->active) {
+#if WATCH_BUF
+		DRM_INFO("%s: object %p wait for seqno %08x\n",
+			  __func__, obj, obj_priv->last_rendering_seqno);
+#endif
+		ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0);
+		if (ret != 0)
+			return ret;
+	}
+
+	old_write_domain = obj->write_domain;
+	old_read_domains = obj->read_domains;
+
+	obj->read_domains &= I915_GEM_DOMAIN_GTT;
+
+	i915_gem_object_flush_cpu_write_domain(obj);
+
+	/* It should now be out of any other write domains, and we can update
+	 * the domain values for our changes.
+	 */
+	BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+	obj->read_domains |= I915_GEM_DOMAIN_GTT;
+	obj->write_domain = I915_GEM_DOMAIN_GTT;
+	obj_priv->dirty = 1;
+
+	trace_i915_gem_object_change_domain(obj,
+					    old_read_domains,
+					    old_write_domain);
+
+	return 0;
+}
+
 /**
  * Moves a single object to the CPU read, and possibly write domain.
  *
@@ -3170,7 +3299,7 @@
 static int
 i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
 				 struct drm_file *file_priv,
-				 struct drm_i915_gem_exec_object *entry,
+				 struct drm_i915_gem_exec_object2 *entry,
 				 struct drm_i915_gem_relocation_entry *relocs)
 {
 	struct drm_device *dev = obj->dev;
@@ -3178,12 +3307,35 @@
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int i, ret;
 	void __iomem *reloc_page;
+	bool need_fence;
+
+	need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+	             obj_priv->tiling_mode != I915_TILING_NONE;
+
+	/* Check fence reg constraints and rebind if necessary */
+	if (need_fence && !i915_obj_fenceable(dev, obj))
+		i915_gem_object_unbind(obj);
 
 	/* Choose the GTT offset for our buffer and put it there. */
 	ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
 	if (ret)
 		return ret;
 
+	/*
+	 * Pre-965 chips need a fence register set up in order to
+	 * properly handle blits to/from tiled surfaces.
+	 */
+	if (need_fence) {
+		ret = i915_gem_object_get_fence_reg(obj);
+		if (ret != 0) {
+			if (ret != -EBUSY && ret != -ERESTARTSYS)
+				DRM_ERROR("Failure to install fence: %d\n",
+					  ret);
+			i915_gem_object_unpin(obj);
+			return ret;
+		}
+	}
+
 	entry->offset = obj_priv->gtt_offset;
 
 	/* Apply the relocations, using the GTT aperture to avoid cache
@@ -3345,7 +3497,7 @@
  */
 static int
 i915_dispatch_gem_execbuffer(struct drm_device *dev,
-			      struct drm_i915_gem_execbuffer *exec,
+			      struct drm_i915_gem_execbuffer2 *exec,
 			      struct drm_clip_rect *cliprects,
 			      uint64_t exec_offset)
 {
@@ -3435,7 +3587,7 @@
 }
 
 static int
-i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
+i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list,
 			      uint32_t buffer_count,
 			      struct drm_i915_gem_relocation_entry **relocs)
 {
@@ -3450,8 +3602,10 @@
 	}
 
 	*relocs = drm_calloc_large(reloc_count, sizeof(**relocs));
-	if (*relocs == NULL)
+	if (*relocs == NULL) {
+		DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count);
 		return -ENOMEM;
+	}
 
 	for (i = 0; i < buffer_count; i++) {
 		struct drm_i915_gem_relocation_entry __user *user_relocs;
@@ -3475,13 +3629,16 @@
 }
 
 static int
-i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
+i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list,
 			    uint32_t buffer_count,
 			    struct drm_i915_gem_relocation_entry *relocs)
 {
 	uint32_t reloc_count = 0, i;
 	int ret = 0;
 
+	if (relocs == NULL)
+	    return 0;
+
 	for (i = 0; i < buffer_count; i++) {
 		struct drm_i915_gem_relocation_entry __user *user_relocs;
 		int unwritten;
@@ -3508,7 +3665,7 @@
 }
 
 static int
-i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec,
+i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec,
 			   uint64_t exec_offset)
 {
 	uint32_t exec_start, exec_len;
@@ -3525,22 +3682,57 @@
 	return 0;
 }
 
+static int
+i915_gem_wait_for_pending_flip(struct drm_device *dev,
+			       struct drm_gem_object **object_list,
+			       int count)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv;
+	DEFINE_WAIT(wait);
+	int i, ret = 0;
+
+	for (;;) {
+		prepare_to_wait(&dev_priv->pending_flip_queue,
+				&wait, TASK_INTERRUPTIBLE);
+		for (i = 0; i < count; i++) {
+			obj_priv = object_list[i]->driver_private;
+			if (atomic_read(&obj_priv->pending_flip) > 0)
+				break;
+		}
+		if (i == count)
+			break;
+
+		if (!signal_pending(current)) {
+			mutex_unlock(&dev->struct_mutex);
+			schedule();
+			mutex_lock(&dev->struct_mutex);
+			continue;
+		}
+		ret = -ERESTARTSYS;
+		break;
+	}
+	finish_wait(&dev_priv->pending_flip_queue, &wait);
+
+	return ret;
+}
+
 int
-i915_gem_execbuffer(struct drm_device *dev, void *data,
-		    struct drm_file *file_priv)
+i915_gem_do_execbuffer(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv,
+		       struct drm_i915_gem_execbuffer2 *args,
+		       struct drm_i915_gem_exec_object2 *exec_list)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_gem_execbuffer *args = data;
-	struct drm_i915_gem_exec_object *exec_list = NULL;
 	struct drm_gem_object **object_list = NULL;
 	struct drm_gem_object *batch_obj;
 	struct drm_i915_gem_object *obj_priv;
 	struct drm_clip_rect *cliprects = NULL;
-	struct drm_i915_gem_relocation_entry *relocs;
-	int ret, ret2, i, pinned = 0;
+	struct drm_i915_gem_relocation_entry *relocs = NULL;
+	int ret = 0, ret2, i, pinned = 0;
 	uint64_t exec_offset;
 	uint32_t seqno, flush_domains, reloc_index;
-	int pin_tries;
+	int pin_tries, flips;
 
 #if WATCH_EXEC
 	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
@@ -3551,31 +3743,21 @@
 		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
 		return -EINVAL;
 	}
-	/* Copy in the exec list from userland */
-	exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count);
-	object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count);
-	if (exec_list == NULL || object_list == NULL) {
-		DRM_ERROR("Failed to allocate exec or object list "
-			  "for %d buffers\n",
+	object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count);
+	if (object_list == NULL) {
+		DRM_ERROR("Failed to allocate object list for %d buffers\n",
 			  args->buffer_count);
 		ret = -ENOMEM;
 		goto pre_mutex_err;
 	}
-	ret = copy_from_user(exec_list,
-			     (struct drm_i915_relocation_entry __user *)
-			     (uintptr_t) args->buffers_ptr,
-			     sizeof(*exec_list) * args->buffer_count);
-	if (ret != 0) {
-		DRM_ERROR("copy %d exec entries failed %d\n",
-			  args->buffer_count, ret);
-		goto pre_mutex_err;
-	}
 
 	if (args->num_cliprects != 0) {
 		cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects),
 				    GFP_KERNEL);
-		if (cliprects == NULL)
+		if (cliprects == NULL) {
+			ret = -ENOMEM;
 			goto pre_mutex_err;
+		}
 
 		ret = copy_from_user(cliprects,
 				     (struct drm_clip_rect __user *)
@@ -3584,6 +3766,7 @@
 		if (ret != 0) {
 			DRM_ERROR("copy %d cliprects failed: %d\n",
 				  args->num_cliprects, ret);
+			ret = -EFAULT;
 			goto pre_mutex_err;
 		}
 	}
@@ -3598,26 +3781,27 @@
 	i915_verify_inactive(dev, __FILE__, __LINE__);
 
 	if (atomic_read(&dev_priv->mm.wedged)) {
-		DRM_ERROR("Execbuf while wedged\n");
 		mutex_unlock(&dev->struct_mutex);
 		ret = -EIO;
 		goto pre_mutex_err;
 	}
 
 	if (dev_priv->mm.suspended) {
-		DRM_ERROR("Execbuf while VT-switched.\n");
 		mutex_unlock(&dev->struct_mutex);
 		ret = -EBUSY;
 		goto pre_mutex_err;
 	}
 
 	/* Look up object handles */
+	flips = 0;
 	for (i = 0; i < args->buffer_count; i++) {
 		object_list[i] = drm_gem_object_lookup(dev, file_priv,
 						       exec_list[i].handle);
 		if (object_list[i] == NULL) {
 			DRM_ERROR("Invalid object handle %d at index %d\n",
 				   exec_list[i].handle, i);
+			/* prevent error path from reading uninitialized data */
+			args->buffer_count = i + 1;
 			ret = -EBADF;
 			goto err;
 		}
@@ -3626,10 +3810,20 @@
 		if (obj_priv->in_execbuffer) {
 			DRM_ERROR("Object %p appears more than once in object list\n",
 				   object_list[i]);
+			/* prevent error path from reading uninitialized data */
+			args->buffer_count = i + 1;
 			ret = -EBADF;
 			goto err;
 		}
 		obj_priv->in_execbuffer = true;
+		flips += atomic_read(&obj_priv->pending_flip);
+	}
+
+	if (flips > 0) {
+		ret = i915_gem_wait_for_pending_flip(dev, object_list,
+						     args->buffer_count);
+		if (ret)
+			goto err;
 	}
 
 	/* Pin and relocate */
@@ -3731,16 +3925,23 @@
 		i915_gem_flush(dev,
 			       dev->invalidate_domains,
 			       dev->flush_domains);
-		if (dev->flush_domains)
+		if (dev->flush_domains & I915_GEM_GPU_DOMAINS)
 			(void)i915_add_request(dev, file_priv,
 					       dev->flush_domains);
 	}
 
 	for (i = 0; i < args->buffer_count; i++) {
 		struct drm_gem_object *obj = object_list[i];
+		struct drm_i915_gem_object *obj_priv = obj->driver_private;
 		uint32_t old_write_domain = obj->write_domain;
 
 		obj->write_domain = obj->pending_write_domain;
+		if (obj->write_domain)
+			list_move_tail(&obj_priv->gpu_write_list,
+				       &dev_priv->mm.gpu_write_list);
+		else
+			list_del_init(&obj_priv->gpu_write_list);
+
 		trace_i915_gem_object_change_domain(obj,
 						    obj->read_domains,
 						    old_write_domain);
@@ -3814,8 +4015,101 @@
 
 	mutex_unlock(&dev->struct_mutex);
 
+pre_mutex_err:
+	/* Copy the updated relocations out regardless of current error
+	 * state.  Failure to update the relocs would mean that the next
+	 * time userland calls execbuf, it would do so with presumed offset
+	 * state that didn't match the actual object state.
+	 */
+	ret2 = i915_gem_put_relocs_to_user(exec_list, args->buffer_count,
+					   relocs);
+	if (ret2 != 0) {
+		DRM_ERROR("Failed to copy relocations back out: %d\n", ret2);
+
+		if (ret == 0)
+			ret = ret2;
+	}
+
+	drm_free_large(object_list);
+	kfree(cliprects);
+
+	return ret;
+}
+
+/*
+ * Legacy execbuffer just creates an exec2 list from the original exec object
+ * list array and passes it to the real function.
+ */
+int
+i915_gem_execbuffer(struct drm_device *dev, void *data,
+		    struct drm_file *file_priv)
+{
+	struct drm_i915_gem_execbuffer *args = data;
+	struct drm_i915_gem_execbuffer2 exec2;
+	struct drm_i915_gem_exec_object *exec_list = NULL;
+	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+	int ret, i;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
+		return -EINVAL;
+	}
+
+	/* Copy in the exec list from userland */
+	exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
+	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	if (exec_list == NULL || exec2_list == NULL) {
+		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+			  args->buffer_count);
+		drm_free_large(exec_list);
+		drm_free_large(exec2_list);
+		return -ENOMEM;
+	}
+	ret = copy_from_user(exec_list,
+			     (struct drm_i915_relocation_entry __user *)
+			     (uintptr_t) args->buffers_ptr,
+			     sizeof(*exec_list) * args->buffer_count);
+	if (ret != 0) {
+		DRM_ERROR("copy %d exec entries failed %d\n",
+			  args->buffer_count, ret);
+		drm_free_large(exec_list);
+		drm_free_large(exec2_list);
+		return -EFAULT;
+	}
+
+	for (i = 0; i < args->buffer_count; i++) {
+		exec2_list[i].handle = exec_list[i].handle;
+		exec2_list[i].relocation_count = exec_list[i].relocation_count;
+		exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
+		exec2_list[i].alignment = exec_list[i].alignment;
+		exec2_list[i].offset = exec_list[i].offset;
+		if (!IS_I965G(dev))
+			exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
+		else
+			exec2_list[i].flags = 0;
+	}
+
+	exec2.buffers_ptr = args->buffers_ptr;
+	exec2.buffer_count = args->buffer_count;
+	exec2.batch_start_offset = args->batch_start_offset;
+	exec2.batch_len = args->batch_len;
+	exec2.DR1 = args->DR1;
+	exec2.DR4 = args->DR4;
+	exec2.num_cliprects = args->num_cliprects;
+	exec2.cliprects_ptr = args->cliprects_ptr;
+	exec2.flags = 0;
+
+	ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list);
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
+		for (i = 0; i < args->buffer_count; i++)
+			exec_list[i].offset = exec2_list[i].offset;
+		/* ... and back out to userspace */
 		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
 				   (uintptr_t) args->buffers_ptr,
 				   exec_list,
@@ -3828,25 +4122,62 @@
 		}
 	}
 
-	/* Copy the updated relocations out regardless of current error
-	 * state.  Failure to update the relocs would mean that the next
-	 * time userland calls execbuf, it would do so with presumed offset
-	 * state that didn't match the actual object state.
-	 */
-	ret2 = i915_gem_put_relocs_to_user(exec_list, args->buffer_count,
-					   relocs);
-	if (ret2 != 0) {
-		DRM_ERROR("Failed to copy relocations back out: %d\n", ret2);
+	drm_free_large(exec_list);
+	drm_free_large(exec2_list);
+	return ret;
+}
 
-		if (ret == 0)
-			ret = ret2;
+int
+i915_gem_execbuffer2(struct drm_device *dev, void *data,
+		     struct drm_file *file_priv)
+{
+	struct drm_i915_gem_execbuffer2 *args = data;
+	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
+	int ret;
+
+#if WATCH_EXEC
+	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
+		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
+#endif
+
+	if (args->buffer_count < 1) {
+		DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
+		return -EINVAL;
 	}
 
-pre_mutex_err:
-	drm_free_large(object_list);
-	drm_free_large(exec_list);
-	kfree(cliprects);
+	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	if (exec2_list == NULL) {
+		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
+			  args->buffer_count);
+		return -ENOMEM;
+	}
+	ret = copy_from_user(exec2_list,
+			     (struct drm_i915_relocation_entry __user *)
+			     (uintptr_t) args->buffers_ptr,
+			     sizeof(*exec2_list) * args->buffer_count);
+	if (ret != 0) {
+		DRM_ERROR("copy %d exec entries failed %d\n",
+			  args->buffer_count, ret);
+		drm_free_large(exec2_list);
+		return -EFAULT;
+	}
 
+	ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list);
+	if (!ret) {
+		/* Copy the new buffer offsets back to the user's exec list. */
+		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+				   (uintptr_t) args->buffers_ptr,
+				   exec2_list,
+				   sizeof(*exec2_list) * args->buffer_count);
+		if (ret) {
+			ret = -EFAULT;
+			DRM_ERROR("failed to copy %d exec entries "
+				  "back to user (%d)\n",
+				  args->buffer_count, ret);
+		}
+	}
+
+	drm_free_large(exec2_list);
 	return ret;
 }
 
@@ -3858,24 +4189,23 @@
 	int ret;
 
 	i915_verify_inactive(dev, __FILE__, __LINE__);
+
+	if (obj_priv->gtt_space != NULL) {
+		if (alignment == 0)
+			alignment = i915_gem_get_gtt_alignment(obj);
+		if (obj_priv->gtt_offset & (alignment - 1)) {
+			ret = i915_gem_object_unbind(obj);
+			if (ret)
+				return ret;
+		}
+	}
+
 	if (obj_priv->gtt_space == NULL) {
 		ret = i915_gem_object_bind_to_gtt(obj, alignment);
 		if (ret)
 			return ret;
 	}
-	/*
-	 * Pre-965 chips need a fence register set up in order to
-	 * properly handle tiled surfaces.
-	 */
-	if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj);
-		if (ret != 0) {
-			if (ret != -EBUSY && ret != -ERESTARTSYS)
-				DRM_ERROR("Failure to install fence: %d\n",
-					  ret);
-			return ret;
-		}
-	}
+
 	obj_priv->pin_count++;
 
 	/* If the object is not active and not pending a flush,
@@ -4133,6 +4463,7 @@
 	obj_priv->obj = obj;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	INIT_LIST_HEAD(&obj_priv->list);
+	INIT_LIST_HEAD(&obj_priv->gpu_write_list);
 	INIT_LIST_HEAD(&obj_priv->fence_list);
 	obj_priv->madv = I915_MADV_WILLNEED;
 
@@ -4314,6 +4645,49 @@
 	return 0;
 }
 
+/*
+ * 965+ support PIPE_CONTROL commands, which provide finer grained control
+ * over cache flushing.
+ */
+static int
+i915_gem_init_pipe_control(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+	int ret;
+
+	obj = drm_gem_object_alloc(dev, 4096);
+	if (obj == NULL) {
+		DRM_ERROR("Failed to allocate seqno page\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	obj_priv = obj->driver_private;
+	obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
+
+	ret = i915_gem_object_pin(obj, 4096);
+	if (ret)
+		goto err_unref;
+
+	dev_priv->seqno_gfx_addr = obj_priv->gtt_offset;
+	dev_priv->seqno_page =  kmap(obj_priv->pages[0]);
+	if (dev_priv->seqno_page == NULL)
+		goto err_unpin;
+
+	dev_priv->seqno_obj = obj;
+	memset(dev_priv->seqno_page, 0, PAGE_SIZE);
+
+	return 0;
+
+err_unpin:
+	i915_gem_object_unpin(obj);
+err_unref:
+	drm_gem_object_unreference(obj);
+err:
+	return ret;
+}
+
 static int
 i915_gem_init_hws(struct drm_device *dev)
 {
@@ -4331,7 +4705,8 @@
 	obj = drm_gem_object_alloc(dev, 4096);
 	if (obj == NULL) {
 		DRM_ERROR("Failed to allocate status page\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err;
 	}
 	obj_priv = obj->driver_private;
 	obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
@@ -4339,7 +4714,7 @@
 	ret = i915_gem_object_pin(obj, 4096);
 	if (ret != 0) {
 		drm_gem_object_unreference(obj);
-		return ret;
+		goto err_unref;
 	}
 
 	dev_priv->status_gfx_addr = obj_priv->gtt_offset;
@@ -4348,20 +4723,50 @@
 	if (dev_priv->hw_status_page == NULL) {
 		DRM_ERROR("Failed to map status page.\n");
 		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-		i915_gem_object_unpin(obj);
-		drm_gem_object_unreference(obj);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_unpin;
+	}
+
+	if (HAS_PIPE_CONTROL(dev)) {
+		ret = i915_gem_init_pipe_control(dev);
+		if (ret)
+			goto err_unpin;
 	}
+
 	dev_priv->hws_obj = obj;
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
 	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
 	I915_READ(HWS_PGA); /* posting read */
-	DRM_DEBUG("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
+	DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
+
+	return 0;
 
+err_unpin:
+	i915_gem_object_unpin(obj);
+err_unref:
+	drm_gem_object_unreference(obj);
+err:
 	return 0;
 }
 
 static void
+i915_gem_cleanup_pipe_control(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	struct drm_i915_gem_object *obj_priv;
+
+	obj = dev_priv->seqno_obj;
+	obj_priv = obj->driver_private;
+	kunmap(obj_priv->pages[0]);
+	i915_gem_object_unpin(obj);
+	drm_gem_object_unreference(obj);
+	dev_priv->seqno_obj = NULL;
+
+	dev_priv->seqno_page = NULL;
+}
+
+static void
 i915_gem_cleanup_hws(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -4382,6 +4787,9 @@
 	memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 	dev_priv->hw_status_page = NULL;
 
+	if (HAS_PIPE_CONTROL(dev))
+		i915_gem_cleanup_pipe_control(dev);
+
 	/* Write high address into HWS_PGA when disabling. */
 	I915_WRITE(HWS_PGA, 0x1ffff000);
 }
@@ -4584,6 +4992,7 @@
 	spin_lock_init(&dev_priv->mm.active_list_lock);
 	INIT_LIST_HEAD(&dev_priv->mm.active_list);
 	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
+	INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 	INIT_LIST_HEAD(&dev_priv->mm.request_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
@@ -4595,6 +5004,16 @@
 	list_add(&dev_priv->mm.shrink_list, &shrink_list);
 	spin_unlock(&shrink_list_lock);
 
+	/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
+	if (IS_GEN3(dev)) {
+		u32 tmp = I915_READ(MI_ARB_STATE);
+		if (!(tmp & MI_ARB_C3_LP_WRITE_ENABLE)) {
+			/* arb state is a masked write, so set bit + bit in mask */
+			tmp = MI_ARB_C3_LP_WRITE_ENABLE | (MI_ARB_C3_LP_WRITE_ENABLE << MI_ARB_MASK_SHIFT);
+			I915_WRITE(MI_ARB_STATE, tmp);
+		}
+	}
+
 	/* Old X drivers will take 0-2 for front, back, depth buffers */
 	dev_priv->fence_reg_start = 3;
 
@@ -4614,8 +5033,8 @@
 			for (i = 0; i < 8; i++)
 				I915_WRITE(FENCE_REG_945_8 + (i * 4), 0);
 	}
-
 	i915_gem_detect_bit_6_swizzle(dev);
+	init_waitqueue_head(&dev_priv->pending_flip_queue);
 }
 
 /*
@@ -4638,7 +5057,7 @@
 
 	phys_obj->id = id;
 
-	phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff);
+	phys_obj->handle = drm_pci_alloc(dev, size, 0);
 	if (!phys_obj->handle) {
 		ret = -ENOMEM;
 		goto kfree_obj;
@@ -4696,7 +5115,7 @@
 	if (!obj_priv->phys_obj)
 		return;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_get_pages(obj, 0);
 	if (ret)
 		goto out;
 
@@ -4754,7 +5173,7 @@
 	obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
 	obj_priv->phys_obj->cur_obj = obj;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_get_pages(obj, 0);
 	if (ret) {
 		DRM_ERROR("failed to get page list\n");
 		goto out;
@@ -4790,7 +5209,7 @@
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
 
-	DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size);
+	DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size);
 	ret = copy_from_user(obj_addr, user_data, args->size);
 	if (ret)
 		return -EFAULT;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_reg.h
@@ -140,6 +140,7 @@
 #define MI_NOOP			MI_INSTR(0, 0)
 #define MI_USER_INTERRUPT	MI_INSTR(0x02, 0)
 #define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
+#define   MI_WAIT_FOR_OVERLAY_FLIP	(1<<16)
 #define   MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
 #define   MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
 #define   MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
@@ -151,7 +152,14 @@
 #define   MI_END_SCENE		(1 << 4) /* flush binner and incr scene count */
 #define MI_BATCH_BUFFER_END	MI_INSTR(0x0a, 0)
 #define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
+#define MI_OVERLAY_FLIP		MI_INSTR(0x11,0)
+#define   MI_OVERLAY_CONTINUE	(0x0<<21)
+#define   MI_OVERLAY_ON		(0x1<<21)
+#define   MI_OVERLAY_OFF	(0x2<<21)
 #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)
+#define MI_DISPLAY_FLIP		MI_INSTR(0x14, 2)
+#define MI_DISPLAY_FLIP_I915	MI_INSTR(0x14, 1)
+#define   MI_DISPLAY_FLIP_PLANE(n) ((n) << 20)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
@@ -203,6 +211,16 @@
 #define   ASYNC_FLIP                (1<<22)
 #define   DISPLAY_PLANE_A           (0<<20)
 #define   DISPLAY_PLANE_B           (1<<20)
+#define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
+#define   PIPE_CONTROL_QW_WRITE	(1<<14)
+#define   PIPE_CONTROL_DEPTH_STALL (1<<13)
+#define   PIPE_CONTROL_WC_FLUSH	(1<<12)
+#define   PIPE_CONTROL_IS_FLUSH	(1<<11) /* MBZ on Ironlake */
+#define   PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
+#define   PIPE_CONTROL_ISP_DIS	(1<<9)
+#define   PIPE_CONTROL_NOTIFY	(1<<8)
+#define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
+#define   PIPE_CONTROL_STALL_EN	(1<<1) /* in addr word, Ironlake+ only */
 
 /*
  * Fence registers
@@ -214,7 +232,7 @@
 #define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
 #define   I830_FENCE_PITCH_SHIFT	4
 #define   I830_FENCE_REG_VALID		(1<<0)
-#define   I915_FENCE_MAX_PITCH_VAL	0x10
+#define   I915_FENCE_MAX_PITCH_VAL	4
 #define   I830_FENCE_MAX_PITCH_VAL	6
 #define   I830_FENCE_MAX_SIZE_VAL	(1<<8)
 
@@ -260,6 +278,8 @@
 #define HWS_PGA		0x02080
 #define HWS_ADDRESS_MASK	0xfffff000
 #define HWS_START_ADDRESS_SHIFT	4
+#define PWRCTXA		0x2088 /* 965GM+ only */
+#define   PWRCTX_EN	(1<<0)
 #define IPEIR		0x02088
 #define IPEHR		0x0208c
 #define INSTDONE	0x02090
@@ -307,6 +327,70 @@
 #define LM_BURST_LENGTH     0x00000700
 #define LM_FIFO_WATERMARK   0x0000001F
 #define MI_ARB_STATE	0x020e4 /* 915+ only */
+#define   MI_ARB_MASK_SHIFT	  16	/* shift for enable bits */
+
+/* Make render/texture TLB fetches lower priorty than associated data
+ *   fetches. This is not turned on by default
+ */
+#define   MI_ARB_RENDER_TLB_LOW_PRIORITY	(1 << 15)
+
+/* Isoch request wait on GTT enable (Display A/B/C streams).
+ * Make isoch requests stall on the TLB update. May cause
+ * display underruns (test mode only)
+ */
+#define   MI_ARB_ISOCH_WAIT_GTT			(1 << 14)
+
+/* Block grant count for isoch requests when block count is
+ * set to a finite value.
+ */
+#define   MI_ARB_BLOCK_GRANT_MASK		(3 << 12)
+#define   MI_ARB_BLOCK_GRANT_8			(0 << 12)	/* for 3 display planes */
+#define   MI_ARB_BLOCK_GRANT_4			(1 << 12)	/* for 2 display planes */
+#define   MI_ARB_BLOCK_GRANT_2			(2 << 12)	/* for 1 display plane */
+#define   MI_ARB_BLOCK_GRANT_0			(3 << 12)	/* don't use */
+
+/* Enable render writes to complete in C2/C3/C4 power states.
+ * If this isn't enabled, render writes are prevented in low
+ * power states. That seems bad to me.
+ */
+#define   MI_ARB_C3_LP_WRITE_ENABLE		(1 << 11)
+
+/* This acknowledges an async flip immediately instead
+ * of waiting for 2TLB fetches.
+ */
+#define   MI_ARB_ASYNC_FLIP_ACK_IMMEDIATE	(1 << 10)
+
+/* Enables non-sequential data reads through arbiter
+ */
+#define   MI_ARB_DUAL_DATA_PHASE_DISABLE       	(1 << 9)
+
+/* Disable FSB snooping of cacheable write cycles from binner/render
+ * command stream
+ */
+#define   MI_ARB_CACHE_SNOOP_DISABLE		(1 << 8)
+
+/* Arbiter time slice for non-isoch streams */
+#define   MI_ARB_TIME_SLICE_MASK		(7 << 5)
+#define   MI_ARB_TIME_SLICE_1			(0 << 5)
+#define   MI_ARB_TIME_SLICE_2			(1 << 5)
+#define   MI_ARB_TIME_SLICE_4			(2 << 5)
+#define   MI_ARB_TIME_SLICE_6			(3 << 5)
+#define   MI_ARB_TIME_SLICE_8			(4 << 5)
+#define   MI_ARB_TIME_SLICE_10			(5 << 5)
+#define   MI_ARB_TIME_SLICE_14			(6 << 5)
+#define   MI_ARB_TIME_SLICE_16			(7 << 5)
+
+/* Low priority grace period page size */
+#define   MI_ARB_LOW_PRIORITY_GRACE_4KB		(0 << 4)	/* default */
+#define   MI_ARB_LOW_PRIORITY_GRACE_8KB		(1 << 4)
+
+/* Disable display A/B trickle feed */
+#define   MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE	(1 << 2)
+
+/* Set display plane priority */
+#define   MI_ARB_DISPLAY_PRIORITY_A_B		(0 << 0)	/* display A > display B */
+#define   MI_ARB_DISPLAY_PRIORITY_B_A		(1 << 0)	/* display B > display A */
+
 #define CACHE_MODE_0	0x02120 /* 915+ only */
 #define   CM0_MASK_SHIFT          16
 #define   CM0_IZ_OPT_DISABLE      (1<<6)
@@ -316,6 +400,9 @@
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
 #define GFX_FLSH_CNTL	0x02170 /* 915+ only */
+#define ECOSKPD		0x021d0
+#define   ECO_GATING_CX_ONLY	(1<<3)
+#define   ECO_FLIP_DONE		(1<<0)
 
 
 /*
@@ -329,6 +416,7 @@
 #define   FBC_CTL_PERIODIC	(1<<30)
 #define   FBC_CTL_INTERVAL_SHIFT (16)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define   FBC_C3_IDLE		(1<<13)
 #define   FBC_CTL_STRIDE_SHIFT	(5)
 #define   FBC_CTL_FENCENO	(1<<0)
 #define FBC_COMMAND		0x0320c
@@ -405,6 +493,13 @@
 # define GPIO_DATA_VAL_IN		(1 << 12)
 # define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 
+#define GMBUS0			0x5100
+#define GMBUS1			0x5104
+#define GMBUS2			0x5108
+#define GMBUS3			0x510c
+#define GMBUS4			0x5110
+#define GMBUS5			0x5120
+
 /*
  * Clock control & power management
  */
@@ -435,7 +530,7 @@
 #define   DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24) /* i915 */
 #define   DPLL_P2_CLOCK_DIV_MASK	0x03000000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
-#define   DPLL_FPA01_P1_POST_DIV_MASK_IGD	0x00ff8000 /* IGD */
+#define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
 
 #define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
 #define I915_CRC_ERROR_ENABLE			(1UL<<29)
@@ -512,7 +607,7 @@
  */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
 #define   DPLL_FPA01_P1_POST_DIV_SHIFT	16
-#define   DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15
+#define   DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW 15
 /* i830, required in DVO non-gang */
 #define   PLL_P2_DIVIDE_BY_4		(1 << 23)
 #define   PLL_P1_DIVIDE_BY_TWO		(1 << 21) /* i830 */
@@ -522,7 +617,7 @@
 #define   PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
 #define   PLL_REF_INPUT_MASK		(3 << 13)
 #define   PLL_LOAD_PULSE_PHASE_SHIFT		9
-/* IGDNG */
+/* Ironlake */
 # define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT     9
 # define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK      (7 << 9)
 # define PLL_REF_SDVO_HDMI_MULTIPLIER(x)	(((x)-1) << 9)
@@ -586,12 +681,12 @@
 #define FPB0	0x06048
 #define FPB1	0x0604c
 #define   FP_N_DIV_MASK		0x003f0000
-#define   FP_N_IGD_DIV_MASK	0x00ff0000
+#define   FP_N_PINEVIEW_DIV_MASK	0x00ff0000
 #define   FP_N_DIV_SHIFT		16
 #define   FP_M1_DIV_MASK	0x00003f00
 #define   FP_M1_DIV_SHIFT		 8
 #define   FP_M2_DIV_MASK	0x0000003f
-#define   FP_M2_IGD_DIV_MASK	0x000000ff
+#define   FP_M2_PINEVIEW_DIV_MASK	0x000000ff
 #define   FP_M2_DIV_SHIFT		 0
 #define DPLL_TEST	0x606c
 #define   DPLLB_TEST_SDVO_DIV_1		(0 << 22)
@@ -769,7 +864,8 @@
 
 /** GM965 GM45 render standby register */
 #define MCHBAR_RENDER_STANDBY	0x111B8
-
+#define   RCX_SW_EXIT		(1<<23)
+#define   RSX_STATUS_MASK	0x00700000
 #define PEG_BAND_GAP_DATA	0x14d68
 
 /*
@@ -844,7 +940,6 @@
 #define   SDVOB_HOTPLUG_INT_EN			(1 << 26)
 #define   SDVOC_HOTPLUG_INT_EN			(1 << 25)
 #define   TV_HOTPLUG_INT_EN			(1 << 18)
-#define   CRT_EOS_INT_EN			(1 << 10)
 #define   CRT_HOTPLUG_INT_EN			(1 << 9)
 #define   CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
 #define CRT_HOTPLUG_ACTIVATION_PERIOD_32	(0 << 8)
@@ -863,14 +958,6 @@
 #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
 #define CRT_HOTPLUG_MASK			(0x3fc) /* Bits 9-2 */
 #define CRT_FORCE_HOTPLUG_MASK			0xfffffe1f
-#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \
-			 HDMIC_HOTPLUG_INT_EN |	  \
-			 HDMID_HOTPLUG_INT_EN |	  \
-			 SDVOB_HOTPLUG_INT_EN |	  \
-			 SDVOC_HOTPLUG_INT_EN |	  \
-			 TV_HOTPLUG_INT_EN |	  \
-			 CRT_HOTPLUG_INT_EN)
-
 
 #define PORT_HOTPLUG_STAT	0x61114
 #define   HDMIB_HOTPLUG_INT_STATUS		(1 << 29)
@@ -879,7 +966,6 @@
 #define   DPC_HOTPLUG_INT_STATUS		(1 << 28)
 #define   HDMID_HOTPLUG_INT_STATUS		(1 << 27)
 #define   DPD_HOTPLUG_INT_STATUS		(1 << 27)
-#define   CRT_EOS_INT_STATUS			(1 << 12)
 #define   CRT_HOTPLUG_INT_STATUS		(1 << 11)
 #define   TV_HOTPLUG_INT_STATUS			(1 << 10)
 #define   CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
@@ -968,6 +1054,8 @@
 #define   LVDS_PORT_EN			(1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT		(1 << 30)
+/* LVDS dithering flag on 965/g4x platform */
+#define   LVDS_ENABLE_DITHER		(1 << 25)
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE		(1 << 15)
 /*
@@ -1620,7 +1708,7 @@
 #define   DP_CLOCK_OUTPUT_ENABLE	(1 << 13)
 
 #define   DP_SCRAMBLING_DISABLE		(1 << 12)
-#define   DP_SCRAMBLING_DISABLE_IGDNG	(1 << 7)
+#define   DP_SCRAMBLING_DISABLE_IRONLAKE	(1 << 7)
 
 /** limit RGB values to avoid confusing TVs */
 #define   DP_COLOR_RANGE_16_235		(1 << 8)
@@ -1737,6 +1825,8 @@
 
 /* Display & cursor control */
 
+/* dithering flag on Ironlake */
+#define PIPE_ENABLE_DITHER	(1 << 4)
 /* Pipe A */
 #define PIPEADSL		0x70000
 #define PIPEACONF		0x70008
@@ -1804,11 +1894,11 @@
 #define   DSPFW_PLANEB_SHIFT	8
 #define DSPFW2			0x70038
 #define   DSPFW_CURSORA_MASK	0x00003f00
-#define   DSPFW_CURSORA_SHIFT	16
+#define   DSPFW_CURSORA_SHIFT	8
 #define DSPFW3			0x7003c
 #define   DSPFW_HPLL_SR_EN	(1<<31)
 #define   DSPFW_CURSOR_SR_SHIFT	24
-#define   IGD_SELF_REFRESH_EN	(1<<30)
+#define   PINEVIEW_SELF_REFRESH_EN	(1<<30)
 
 /* FIFO watermark sizes etc */
 #define G4X_FIFO_LINE_SIZE	64
@@ -1824,16 +1914,16 @@
 #define G4X_MAX_WM		0x3f
 #define I915_MAX_WM		0x3f
 
-#define IGD_DISPLAY_FIFO	512 /* in 64byte unit */
-#define IGD_FIFO_LINE_SIZE	64
-#define IGD_MAX_WM		0x1ff
-#define IGD_DFT_WM		0x3f
-#define IGD_DFT_HPLLOFF_WM	0
-#define IGD_GUARD_WM		10
-#define IGD_CURSOR_FIFO		64
-#define IGD_CURSOR_MAX_WM	0x3f
-#define IGD_CURSOR_DFT_WM	0
-#define IGD_CURSOR_GUARD_WM	5
+#define PINEVIEW_DISPLAY_FIFO	512 /* in 64byte unit */
+#define PINEVIEW_FIFO_LINE_SIZE	64
+#define PINEVIEW_MAX_WM		0x1ff
+#define PINEVIEW_DFT_WM		0x3f
+#define PINEVIEW_DFT_HPLLOFF_WM	0
+#define PINEVIEW_GUARD_WM		10
+#define PINEVIEW_CURSOR_FIFO		64
+#define PINEVIEW_CURSOR_MAX_WM	0x3f
+#define PINEVIEW_CURSOR_DFT_WM	0
+#define PINEVIEW_CURSOR_GUARD_WM	5
 
 /*
  * The two pipe frame counter registers are not synchronized, so
@@ -1907,6 +1997,7 @@
 #define   DISPPLANE_16BPP			(0x5<<26)
 #define   DISPPLANE_32BPP_NO_ALPHA		(0x6<<26)
 #define   DISPPLANE_32BPP			(0x7<<26)
+#define   DISPPLANE_32BPP_30BIT_NO_ALPHA	(0xa<<26)
 #define   DISPPLANE_STEREO_ENABLE		(1<<25)
 #define   DISPPLANE_STEREO_DISABLE		0
 #define   DISPPLANE_SEL_PIPE_MASK		(1<<24)
@@ -1918,7 +2009,7 @@
 #define   DISPPLANE_NO_LINE_DOUBLE		0
 #define   DISPPLANE_STEREO_POLARITY_FIRST	0
 #define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
-#define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* IGDNG */
+#define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* Ironlake */
 #define   DISPPLANE_TILED			(1<<10)
 #define DSPAADDR		0x70184
 #define DSPASTRIDE		0x70188
@@ -1971,7 +2062,7 @@
 # define VGA_2X_MODE				(1 << 30)
 # define VGA_PIPE_B_SELECT			(1 << 29)
 
-/* IGDNG */
+/* Ironlake */
 
 #define CPU_VGACNTRL	0x41000
 
@@ -2098,6 +2189,7 @@
 #define DEIER   0x4400c
 
 /* GT interrupt */
+#define GT_PIPE_NOTIFY		(1 << 4)
 #define GT_SYNC_STATUS          (1 << 2)
 #define GT_USER_INTERRUPT       (1 << 0)
 
@@ -2117,6 +2209,7 @@
 #define SDE_PORTC_HOTPLUG       (1 << 9)
 #define SDE_PORTB_HOTPLUG       (1 << 8)
 #define SDE_SDVOB_HOTPLUG       (1 << 6)
+#define SDE_HOTPLUG_MASK	(0xf << 8)
 
 #define SDEISR  0xc4000
 #define SDEIMR  0xc4004
@@ -2157,6 +2250,13 @@
 #define PCH_GPIOE               0xc5020
 #define PCH_GPIOF               0xc5024
 
+#define PCH_GMBUS0		0xc5100
+#define PCH_GMBUS1		0xc5104
+#define PCH_GMBUS2		0xc5108
+#define PCH_GMBUS3		0xc510c
+#define PCH_GMBUS4		0xc5110
+#define PCH_GMBUS5		0xc5120
+
 #define PCH_DPLL_A              0xc6014
 #define PCH_DPLL_B              0xc6018
 
@@ -2292,7 +2392,7 @@
 #define  FDI_DP_PORT_WIDTH_X3           (2<<19)
 #define  FDI_DP_PORT_WIDTH_X4           (3<<19)
 #define  FDI_TX_ENHANCE_FRAME_ENABLE    (1<<18)
-/* IGDNG: hardwired to 1 */
+/* Ironlake: hardwired to 1 */
 #define  FDI_TX_PLL_ENABLE              (1<<14)
 /* both Tx and Rx */
 #define  FDI_SCRAMBLING_ENABLE          (0<<7)
@@ -2413,6 +2513,7 @@
 
 #define PCH_PP_STATUS		0xc7200
 #define PCH_PP_CONTROL		0xc7204
+#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
 #define  EDP_FORCE_VDD		(1 << 3)
 #define  EDP_BLC_ENABLE		(1 << 2)
 #define  PANEL_POWER_RESET	(1 << 1)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_drv.c
@@ -33,7 +33,6 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 
-#include "drm_pciids.h"
 #include <linux/console.h>
 #include "drm_crtc_helper.h"
 
@@ -46,36 +45,152 @@
 unsigned int i915_powersave = 1;
 module_param_named(powersave, i915_powersave, int, 0400);
 
+unsigned int i915_lvds_downclock = 0;
+module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
+
 static struct drm_driver driver;
+extern int intel_agp_enabled;
+
+#define INTEL_VGA_DEVICE(id, info) {		\
+	.class = PCI_CLASS_DISPLAY_VGA << 8,	\
+	.class_mask = 0xffff00,			\
+	.vendor = 0x8086,			\
+	.device = id,				\
+	.subvendor = PCI_ANY_ID,		\
+	.subdevice = PCI_ANY_ID,		\
+	.driver_data = (unsigned long) info }
+
+const static struct intel_device_info intel_i830_info = {
+	.is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_845g_info = {
+	.is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i85x_info = {
+	.is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
+	.cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i865g_info = {
+	.is_i8xx = 1,
+};
+
+const static struct intel_device_info intel_i915g_info = {
+	.is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i915gm_info = {
+	.is_i9xx = 1,  .is_mobile = 1,
+	.cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945g_info = {
+	.is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
+};
+const static struct intel_device_info intel_i945gm_info = {
+	.is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
+	.has_hotplug = 1, .cursor_needs_physical = 1,
+};
+
+const static struct intel_device_info intel_i965g_info = {
+	.is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_i965gm_info = {
+	.is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
+	.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_g33_info = {
+	.is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+	.has_hotplug = 1,
+};
 
-static struct pci_device_id pciidlist[] = {
-	i915_PCI_IDS
+const static struct intel_device_info intel_g45_info = {
+	.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+	.has_pipe_cxsr = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_gm45_info = {
+	.is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
+	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
+	.has_pipe_cxsr = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_pineview_info = {
+	.is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1,
+	.need_gfx_hws = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_d_info = {
+	.is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+	.has_pipe_cxsr = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_ironlake_m_info = {
+	.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
+	.need_gfx_hws = 1, .has_rc6 = 1,
+	.has_hotplug = 1,
+};
+
+const static struct pci_device_id pciidlist[] = {
+	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
+	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
+	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
+	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
+	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
+	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
+	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
+	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
+	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
+	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
+	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
+	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
+	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
+	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
+	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
+	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
+	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
+	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
+	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
+	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
+	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
+	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2e92, &intel_g45_info),
+	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
+	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
+	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
+	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
+	{0, 0, 0}
 };
 
 #if defined(CONFIG_DRM_I915_KMS)
 MODULE_DEVICE_TABLE(pci, pciidlist);
 #endif
 
-static int i915_suspend(struct drm_device *dev, pm_message_t state)
+static int i915_drm_freeze(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!dev || !dev_priv) {
-		DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv);
-		DRM_ERROR("DRM not initialized, aborting suspend.\n");
-		return -ENODEV;
-	}
-
-	if (state.event == PM_EVENT_PRETHAW)
-		return 0;
-
 	pci_save_state(dev->pdev);
 
 	/* If KMS is active, we do the leavevt stuff here */
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		if (i915_gem_idle(dev))
+		int error = i915_gem_idle(dev);
+		if (error) {
 			dev_err(&dev->pdev->dev,
-				"GEM idle failed, resume may fail\n");
+				"GEM idle failed, resume might fail\n");
+			return error;
+		}
 		drm_irq_uninstall(dev);
 	}
 
@@ -83,26 +198,42 @@
 
 	intel_opregion_free(dev, 1);
 
+	/* Modeset on resume, not lid events */
+	dev_priv->modeset_on_lid = 0;
+
+	return 0;
+}
+
+static int i915_suspend(struct drm_device *dev, pm_message_t state)
+{
+	int error;
+
+	if (!dev || !dev->dev_private) {
+		DRM_ERROR("dev: %p\n", dev);
+		DRM_ERROR("DRM not initialized, aborting suspend.\n");
+		return -ENODEV;
+	}
+
+	if (state.event == PM_EVENT_PRETHAW)
+		return 0;
+
+	error = i915_drm_freeze(dev);
+	if (error)
+		return error;
+
 	if (state.event == PM_EVENT_SUSPEND) {
 		/* Shut down the device */
 		pci_disable_device(dev->pdev);
 		pci_set_power_state(dev->pdev, PCI_D3hot);
 	}
 
-	/* Modeset on resume, not lid events */
-	dev_priv->modeset_on_lid = 0;
-
 	return 0;
 }
 
-static int i915_resume(struct drm_device *dev)
+static int i915_drm_thaw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret = 0;
-
-	if (pci_enable_device(dev->pdev))
-		return -1;
-	pci_set_master(dev->pdev);
+	int error = 0;
 
 	i915_restore_state(dev);
 
@@ -113,21 +244,28 @@
 		mutex_lock(&dev->struct_mutex);
 		dev_priv->mm.suspended = 0;
 
-		ret = i915_gem_init_ringbuffer(dev);
-		if (ret != 0)
-			ret = -1;
+		error = i915_gem_init_ringbuffer(dev);
 		mutex_unlock(&dev->struct_mutex);
 
 		drm_irq_install(dev);
-	}
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+
 		/* Resume the modeset for every activated CRTC */
 		drm_helper_resume_force_mode(dev);
 	}
 
 	dev_priv->modeset_on_lid = 0;
 
-	return ret;
+	return error;
+}
+
+static int i915_resume(struct drm_device *dev)
+{
+	if (pci_enable_device(dev->pdev))
+		return -EIO;
+
+	pci_set_master(dev->pdev);
+
+	return i915_drm_thaw(dev);
 }
 
 /**
@@ -192,6 +330,7 @@
 		}
 	} else {
 		DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
+		mutex_unlock(&dev->struct_mutex);
 		return -ENODEV;
 	}
 
@@ -268,22 +407,73 @@
 	drm_put_dev(dev);
 }
 
-static int
-i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int i915_pm_suspend(struct device *dev)
 {
-	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	int error;
+
+	if (!drm_dev || !drm_dev->dev_private) {
+		dev_err(dev, "DRM not initialized, aborting suspend.\n");
+		return -ENODEV;
+	}
 
-	return i915_suspend(dev, state);
+	error = i915_drm_freeze(drm_dev);
+	if (error)
+		return error;
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
 }
 
-static int
-i915_pci_resume(struct pci_dev *pdev)
+static int i915_pm_resume(struct device *dev)
 {
-	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	return i915_resume(drm_dev);
+}
+
+static int i915_pm_freeze(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	if (!drm_dev || !drm_dev->dev_private) {
+		dev_err(dev, "DRM not initialized, aborting suspend.\n");
+		return -ENODEV;
+	}
 
-	return i915_resume(dev);
+	return i915_drm_freeze(drm_dev);
 }
 
+static int i915_pm_thaw(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	return i915_drm_thaw(drm_dev);
+}
+
+static int i915_pm_poweroff(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	return i915_drm_freeze(drm_dev);
+}
+
+const struct dev_pm_ops i915_pm_ops = {
+     .suspend = i915_pm_suspend,
+     .resume = i915_pm_resume,
+     .freeze = i915_pm_freeze,
+     .thaw = i915_pm_thaw,
+     .poweroff = i915_pm_poweroff,
+     .restore = i915_pm_resume,
+};
+
 static struct vm_operations_struct i915_gem_vm_ops = {
 	.fault = i915_gem_fault,
 	.open = drm_gem_vm_open,
@@ -303,8 +493,11 @@
 	.lastclose = i915_driver_lastclose,
 	.preclose = i915_driver_preclose,
 	.postclose = i915_driver_postclose,
+
+	/* Used in place of i915_pm_ops for non-DRIVER_MODESET */
 	.suspend = i915_suspend,
 	.resume = i915_resume,
+
 	.device_is_agp = i915_driver_device_is_agp,
 	.enable_vblank = i915_enable_vblank,
 	.disable_vblank = i915_disable_vblank,
@@ -329,10 +522,11 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_gem_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .read = drm_read,
 #ifdef CONFIG_COMPAT
 		 .compat_ioctl = i915_compat_ioctl,
 #endif
@@ -343,10 +537,7 @@
 		 .id_table = pciidlist,
 		 .probe = i915_pci_probe,
 		 .remove = i915_pci_remove,
-#ifdef CONFIG_PM
-		 .resume = i915_pci_resume,
-		 .suspend = i915_pci_suspend,
-#endif
+		 .driver.pm = &i915_pm_ops,
 	},
 
 	.name = DRIVER_NAME,
@@ -359,6 +550,11 @@
 
 static int __init i915_init(void)
 {
+	if (!intel_agp_enabled) {
+		DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
+		return -ENODEV;
+	}
+
 	driver.num_ioctls = i915_max_ioctl;
 
 	i915_gem_shrinker_init();
@@ -372,6 +568,22 @@
 	 * Allow optional vga_text_mode_force boot option to override
 	 * the default behavior.
 	 */
+	/*
+	 * If the user has not specified modesetting the check for known
+         * bad devices and disable them.
+         */
+	if (i915_modeset == -1) {
+		static struct pci_device_id i915_badmodeset[] = {
+			INTEL_VGA_DEVICE(0x3577, 0),
+			INTEL_VGA_DEVICE(0x2562, 0),
+			INTEL_VGA_DEVICE(0x3582, 0),
+			{ },
+		};
+		if (pci_dev_present(i915_badmodeset)) {
+			DRM_INFO("i915 disabling kernel modesetting for known bad device.\n");
+			i915_modeset = 0;
+		}
+	}
 #if defined(CONFIG_DRM_I915_KMS)
 	if (i915_modeset != 0)
 		driver.driver_features |= DRIVER_MODESET;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_bios.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_bios.h
@@ -98,6 +98,7 @@
 #define BDB_SDVO_LVDS_PNP_IDS	 24
 #define BDB_SDVO_LVDS_POWER_SEQ	 25
 #define BDB_TV_OPTIONS		 26
+#define BDB_EDP			 27
 #define BDB_LVDS_OPTIONS	 40
 #define BDB_LVDS_LFP_DATA_PTRS	 41
 #define BDB_LVDS_LFP_DATA	 42
@@ -426,6 +427,45 @@
 	u8 custom_vbt_version;
 } __attribute__((packed));
 
+#define EDP_18BPP	0
+#define EDP_24BPP	1
+#define EDP_30BPP	2
+#define EDP_RATE_1_62	0
+#define EDP_RATE_2_7	1
+#define EDP_LANE_1	0
+#define EDP_LANE_2	1
+#define EDP_LANE_4	3
+#define EDP_PREEMPHASIS_NONE	0
+#define EDP_PREEMPHASIS_3_5dB	1
+#define EDP_PREEMPHASIS_6dB	2
+#define EDP_PREEMPHASIS_9_5dB	3
+#define EDP_VSWING_0_4V		0
+#define EDP_VSWING_0_6V		1
+#define EDP_VSWING_0_8V		2
+#define EDP_VSWING_1_2V		3
+
+struct edp_power_seq {
+	u16 t3;
+	u16 t7;
+	u16 t9;
+	u16 t10;
+	u16 t12;
+} __attribute__ ((packed));
+
+struct edp_link_params {
+	u8 rate:4;
+	u8 lanes:4;
+	u8 preemphasis:4;
+	u8 vswing:4;
+} __attribute__ ((packed));
+
+struct bdb_edp {
+	struct edp_power_seq power_seqs[16];
+	u32 color_depth;
+	u32 sdrrs_msa_timing_delay;
+	struct edp_link_params link_params[16];
+} __attribute__ ((packed));
+
 bool intel_init_bios(struct drm_device *dev);
 
 /*
@@ -549,4 +589,21 @@
 #define   SWF14_APM_STANDBY	0x1
 #define   SWF14_APM_RESTORE	0x0
 
+/* Add the device class for LFP, TV, HDMI */
+#define	 DEVICE_TYPE_INT_LFP	0x1022
+#define	 DEVICE_TYPE_INT_TV	0x1009
+#define	 DEVICE_TYPE_HDMI	0x60D2
+#define	 DEVICE_TYPE_DP		0x68C6
+#define	 DEVICE_TYPE_eDP	0x78C6
+
+/* define the DVO port for HDMI output type */
+#define		DVO_B		1
+#define		DVO_C		2
+#define		DVO_D		3
+
+/* define the PORT for DP output type */
+#define		PORT_IDPB	7
+#define		PORT_IDPC	8
+#define		PORT_IDPD	9
+
 #endif /* _I830_BIOS_H_ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -121,7 +121,7 @@
 				     0,   pcibios_align_resource,
 				     dev_priv->bridge_dev);
 	if (ret) {
-		DRM_DEBUG("failed bus alloc: %d\n", ret);
+		DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
 		dev_priv->mch_res.start = 0;
 		goto out;
 	}
@@ -209,8 +209,8 @@
 	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 	bool need_disable;
 
-	if (IS_IGDNG(dev)) {
-		/* On IGDNG whatever DRAM config, GPU always do
+	if (IS_IRONLAKE(dev) || IS_GEN6(dev)) {
+		/* On Ironlake whatever DRAM config, GPU always do
 		 * same swizzling setup.
 		 */
 		swizzle_x = I915_BIT_6_SWIZZLE_9_10;
@@ -304,35 +304,39 @@
 
 
 /**
- * Returns the size of the fence for a tiled object of the given size.
+ * Returns whether an object is currently fenceable.  If not, it may need
+ * to be unbound and have its pitch adjusted.
  */
-static int
-i915_get_fence_size(struct drm_device *dev, int size)
+bool
+i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
 {
-	int i;
-	int start;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
 	if (IS_I965G(dev)) {
 		/* The 965 can have fences at any page boundary. */
-		return ALIGN(size, 4096);
+		if (obj->size & 4095)
+			return false;
+		return true;
+	} else if (IS_I9XX(dev)) {
+		if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
+			return false;
 	} else {
-		/* Align the size to a power of two greater than the smallest
-		 * fence size.
-		 */
-		if (IS_I9XX(dev))
-			start = 1024 * 1024;
-		else
-			start = 512 * 1024;
+		if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
+			return false;
+	}
 
-		for (i = start; i < size; i <<= 1)
-			;
+	/* Power of two sized... */
+	if (obj->size & (obj->size - 1))
+		return false;
 
-		return i;
-	}
+	/* Objects must be size aligned as well */
+	if (obj_priv->gtt_offset & (obj->size - 1))
+		return false;
+	return true;
 }
 
 /* Check pitch constriants for all chips & tiling formats */
-static bool
+bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
 {
 	int tile_width;
@@ -353,21 +357,17 @@
 		 * reg, so dont bother to check the size */
 		if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
 			return false;
-	} else if (IS_I9XX(dev)) {
-		uint32_t pitch_val = ffs(stride / tile_width) - 1;
-
-		/* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
-		 * instead of 4 (2KB) on 945s.
-		 */
-		if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
-		    size > (I830_FENCE_MAX_SIZE_VAL << 20))
+	} else if (IS_GEN3(dev) || IS_GEN2(dev)) {
+		if (stride > 8192)
 			return false;
-	} else {
-		uint32_t pitch_val = ffs(stride / tile_width) - 1;
 
-		if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
-		    size > (I830_FENCE_MAX_SIZE_VAL << 19))
-			return false;
+		if (IS_GEN3(dev)) {
+			if (size > I830_FENCE_MAX_SIZE_VAL << 20)
+				return false;
+		} else {
+			if (size > I830_FENCE_MAX_SIZE_VAL << 19)
+				return false;
+		}
 	}
 
 	/* 965+ just needs multiples of tile width */
@@ -384,12 +384,6 @@
 	if (stride & (stride - 1))
 		return false;
 
-	/* We don't 0handle the aperture area covered by the fence being bigger
-	 * than the object size.
-	 */
-	if (i915_get_fence_size(dev, size) != size)
-		return false;
-
 	return true;
 }
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_i2c.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_i2c.c
@@ -39,7 +39,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* When using bit bashing for I2C, this bit needs to be set to 1 */
-	if (!IS_IGD(dev))
+	if (!IS_PINEVIEW(dev))
 		return;
 	if (enable)
 		I915_WRITE(DSPCLK_GATE_D,
@@ -118,6 +118,23 @@
 	udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
 }
 
+/* Clears the GMBUS setup.  Our driver doesn't make use of the GMBUS I2C
+ * engine, but if the BIOS leaves it enabled, then that can break our use
+ * of the bit-banging I2C interfaces.  This is notably the case with the
+ * Mac Mini in EFI mode.
+ */
+void
+intel_i2c_reset_gmbus(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (IS_IRONLAKE(dev)) {
+		I915_WRITE(PCH_GMBUS0, 0);
+	} else {
+		I915_WRITE(GMBUS0, 0);
+	}
+}
+
 /**
  * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
  * @dev: DRM device
@@ -168,6 +185,8 @@
 	if(i2c_bit_add_bus(&chan->adapter))
 		goto out_free;
 
+	intel_i2c_reset_gmbus(dev);
+
 	/* JJJ:  raise SCL and SDA? */
 	intel_i2c_quirk_set(dev, true);
 	set_data(chan, 1);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_drv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_drv.h
@@ -110,17 +110,49 @@
 	int clone_mask;
 };
 
+struct intel_crtc;
+struct intel_overlay {
+	struct drm_device *dev;
+	struct intel_crtc *crtc;
+	struct drm_i915_gem_object *vid_bo;
+	struct drm_i915_gem_object *old_vid_bo;
+	int active;
+	int pfit_active;
+	u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
+	u32 color_key;
+	u32 brightness, contrast, saturation;
+	u32 old_xscale, old_yscale;
+	/* register access */
+	u32 flip_addr;
+	struct drm_i915_gem_object *reg_bo;
+	void *virt_addr;
+	/* flip handling */
+	uint32_t last_flip_req;
+	int hw_wedged;
+#define HW_WEDGED		1
+#define NEEDS_WAIT_FOR_FLIP	2
+#define RELEASE_OLD_VID		3
+#define SWITCH_OFF_STAGE_1	4
+#define SWITCH_OFF_STAGE_2	5
+};
+
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
 	enum plane plane;
-	struct drm_gem_object *cursor_bo;
-	uint32_t cursor_addr;
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	int dpms_mode;
 	bool busy; /* is scanout buffer being updated frequently? */
 	struct timer_list idle_timer;
 	bool lowfreq_avail;
+	struct intel_overlay *overlay;
+	struct intel_unpin_work *unpin_work;
+
+	struct drm_gem_object *cursor_bo;
+	uint32_t cursor_addr;
+	int16_t cursor_x, cursor_y;
+	int16_t cursor_width, cursor_height;
+	bool cursor_visble;
 };
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -134,6 +166,8 @@
 int intel_ddc_get_modes(struct intel_output *intel_output);
 extern bool intel_ddc_probe(struct intel_output *intel_output);
 void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
+void intel_i2c_reset_gmbus(struct drm_device *dev);
+
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
@@ -148,6 +182,7 @@
 extern void intel_edp_link_config (struct intel_output *, int *, int *);
 
 
+extern int intel_panel_fitter_pipe (struct drm_device *dev);
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
 extern void intel_encoder_commit (struct drm_encoder *encoder);
@@ -177,10 +212,24 @@
 				    u16 blue, int regno);
 extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 				    u16 *blue, int regno);
+extern void intel_init_clock_gating(struct drm_device *dev);
 
 extern int intel_framebuffer_create(struct drm_device *dev,
 				    struct drm_mode_fb_cmd *mode_cmd,
 				    struct drm_framebuffer **fb,
 				    struct drm_gem_object *obj);
 
+extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
+extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
+extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
+
+extern void intel_setup_overlay(struct drm_device *dev);
+extern void intel_cleanup_overlay(struct drm_device *dev);
+extern int intel_overlay_switch_off(struct intel_overlay *overlay);
+extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
+						int interruptible);
+extern int intel_overlay_put_image(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+extern int intel_overlay_attrs(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
 #endif /* __INTEL_DRV_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_overlay.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_overlay.c
@@ -0,0 +1,1432 @@
+/*
+ * Copyright © 2009
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *    Daniel Vetter <daniel@ffwll.ch>
+ *
+ * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
+ */
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include "intel_drv.h"
+
+/* Limits for overlay size. According to intel doc, the real limits are:
+ * Y width: 4095, UV width (planar): 2047, Y height: 2047,
+ * UV width (planar): * 1023. But the xorg thinks 2048 for height and width. Use
+ * the mininum of both.  */
+#define IMAGE_MAX_WIDTH		2048
+#define IMAGE_MAX_HEIGHT	2046 /* 2 * 1023 */
+/* on 830 and 845 these large limits result in the card hanging */
+#define IMAGE_MAX_WIDTH_LEGACY	1024
+#define IMAGE_MAX_HEIGHT_LEGACY	1088
+
+/* overlay register definitions */
+/* OCMD register */
+#define OCMD_TILED_SURFACE	(0x1<<19)
+#define OCMD_MIRROR_MASK	(0x3<<17)
+#define OCMD_MIRROR_MODE	(0x3<<17)
+#define OCMD_MIRROR_HORIZONTAL	(0x1<<17)
+#define OCMD_MIRROR_VERTICAL	(0x2<<17)
+#define OCMD_MIRROR_BOTH	(0x3<<17)
+#define OCMD_BYTEORDER_MASK	(0x3<<14) /* zero for YUYV or FOURCC YUY2 */
+#define OCMD_UV_SWAP		(0x1<<14) /* YVYU */
+#define OCMD_Y_SWAP		(0x2<<14) /* UYVY or FOURCC UYVY */
+#define OCMD_Y_AND_UV_SWAP	(0x3<<14) /* VYUY */
+#define OCMD_SOURCE_FORMAT_MASK (0xf<<10)
+#define OCMD_RGB_888		(0x1<<10) /* not in i965 Intel docs */
+#define OCMD_RGB_555		(0x2<<10) /* not in i965 Intel docs */
+#define OCMD_RGB_565		(0x3<<10) /* not in i965 Intel docs */
+#define OCMD_YUV_422_PACKED	(0x8<<10)
+#define OCMD_YUV_411_PACKED	(0x9<<10) /* not in i965 Intel docs */
+#define OCMD_YUV_420_PLANAR	(0xc<<10)
+#define OCMD_YUV_422_PLANAR	(0xd<<10)
+#define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
+#define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
+#define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
+#define OCMD_BUF_TYPE_MASK	(Ox1<<5)
+#define OCMD_BUF_TYPE_FRAME	(0x0<<5)
+#define OCMD_BUF_TYPE_FIELD	(0x1<<5)
+#define OCMD_TEST_MODE		(0x1<<4)
+#define OCMD_BUFFER_SELECT	(0x3<<2)
+#define OCMD_BUFFER0		(0x0<<2)
+#define OCMD_BUFFER1		(0x1<<2)
+#define OCMD_FIELD_SELECT	(0x1<<2)
+#define OCMD_FIELD0		(0x0<<1)
+#define OCMD_FIELD1		(0x1<<1)
+#define OCMD_ENABLE		(0x1<<0)
+
+/* OCONFIG register */
+#define OCONF_PIPE_MASK		(0x1<<18)
+#define OCONF_PIPE_A		(0x0<<18)
+#define OCONF_PIPE_B		(0x1<<18)
+#define OCONF_GAMMA2_ENABLE	(0x1<<16)
+#define OCONF_CSC_MODE_BT601	(0x0<<5)
+#define OCONF_CSC_MODE_BT709	(0x1<<5)
+#define OCONF_CSC_BYPASS	(0x1<<4)
+#define OCONF_CC_OUT_8BIT	(0x1<<3)
+#define OCONF_TEST_MODE		(0x1<<2)
+#define OCONF_THREE_LINE_BUFFER	(0x1<<0)
+#define OCONF_TWO_LINE_BUFFER	(0x0<<0)
+
+/* DCLRKM (dst-key) register */
+#define DST_KEY_ENABLE		(0x1<<31)
+#define CLK_RGB24_MASK		0x0
+#define CLK_RGB16_MASK		0x070307
+#define CLK_RGB15_MASK		0x070707
+#define CLK_RGB8I_MASK		0xffffff
+
+#define RGB16_TO_COLORKEY(c) \
+	(((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3))
+#define RGB15_TO_COLORKEY(c) \
+	(((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3))
+
+/* overlay flip addr flag */
+#define OFC_UPDATE		0x1
+
+/* polyphase filter coefficients */
+#define N_HORIZ_Y_TAPS          5
+#define N_VERT_Y_TAPS           3
+#define N_HORIZ_UV_TAPS         3
+#define N_VERT_UV_TAPS          3
+#define N_PHASES                17
+#define MAX_TAPS                5
+
+/* memory bufferd overlay registers */
+struct overlay_registers {
+    u32 OBUF_0Y;
+    u32 OBUF_1Y;
+    u32 OBUF_0U;
+    u32 OBUF_0V;
+    u32 OBUF_1U;
+    u32 OBUF_1V;
+    u32 OSTRIDE;
+    u32 YRGB_VPH;
+    u32 UV_VPH;
+    u32 HORZ_PH;
+    u32 INIT_PHS;
+    u32 DWINPOS;
+    u32 DWINSZ;
+    u32 SWIDTH;
+    u32 SWIDTHSW;
+    u32 SHEIGHT;
+    u32 YRGBSCALE;
+    u32 UVSCALE;
+    u32 OCLRC0;
+    u32 OCLRC1;
+    u32 DCLRKV;
+    u32 DCLRKM;
+    u32 SCLRKVH;
+    u32 SCLRKVL;
+    u32 SCLRKEN;
+    u32 OCONFIG;
+    u32 OCMD;
+    u32 RESERVED1; /* 0x6C */
+    u32 OSTART_0Y;
+    u32 OSTART_1Y;
+    u32 OSTART_0U;
+    u32 OSTART_0V;
+    u32 OSTART_1U;
+    u32 OSTART_1V;
+    u32 OTILEOFF_0Y;
+    u32 OTILEOFF_1Y;
+    u32 OTILEOFF_0U;
+    u32 OTILEOFF_0V;
+    u32 OTILEOFF_1U;
+    u32 OTILEOFF_1V;
+    u32 FASTHSCALE; /* 0xA0 */
+    u32 UVSCALEV; /* 0xA4 */
+    u32 RESERVEDC[(0x200 - 0xA8) / 4]; /* 0xA8 - 0x1FC */
+    u16 Y_VCOEFS[N_VERT_Y_TAPS * N_PHASES]; /* 0x200 */
+    u16 RESERVEDD[0x100 / 2 - N_VERT_Y_TAPS * N_PHASES];
+    u16 Y_HCOEFS[N_HORIZ_Y_TAPS * N_PHASES]; /* 0x300 */
+    u16 RESERVEDE[0x200 / 2 - N_HORIZ_Y_TAPS * N_PHASES];
+    u16 UV_VCOEFS[N_VERT_UV_TAPS * N_PHASES]; /* 0x500 */
+    u16 RESERVEDF[0x100 / 2 - N_VERT_UV_TAPS * N_PHASES];
+    u16 UV_HCOEFS[N_HORIZ_UV_TAPS * N_PHASES]; /* 0x600 */
+    u16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES];
+};
+
+/* overlay flip addr flag */
+#define OFC_UPDATE		0x1
+
+#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
+#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
+
+
+static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
+{
+        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
+	struct overlay_registers *regs;
+
+	/* no recursive mappings */
+	BUG_ON(overlay->virt_addr);
+
+	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
+		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
+				overlay->reg_bo->gtt_offset);
+
+		if (!regs) {
+			DRM_ERROR("failed to map overlay regs in GTT\n");
+			return NULL;
+		}
+	} else
+		regs = overlay->reg_bo->phys_obj->handle->vaddr;
+
+	return overlay->virt_addr = regs;
+}
+
+static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (OVERLAY_NONPHYSICAL(overlay->dev))
+		io_mapping_unmap_atomic(overlay->virt_addr);
+
+	overlay->virt_addr = NULL;
+
+	I915_READ(OVADD); /* flush wc cashes */
+
+	return;
+}
+
+/* overlay needs to be disable in OCMD reg */
+static int intel_overlay_on(struct intel_overlay *overlay)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+	RING_LOCALS;
+
+	BUG_ON(overlay->active);
+
+	overlay->active = 1;
+	overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(MI_FLUSH);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
+	OUT_RING(overlay->flip_addr | OFC_UPDATE);
+	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+
+	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+	if (overlay->last_flip_req == 0)
+		return -ENOMEM;
+
+	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+	if (ret != 0)
+		return ret;
+
+	overlay->hw_wedged = 0;
+	overlay->last_flip_req = 0;
+	return 0;
+}
+
+/* overlay needs to be enabled in OCMD reg */
+static void intel_overlay_continue(struct intel_overlay *overlay,
+			    bool load_polyphase_filter)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 flip_addr = overlay->flip_addr;
+	u32 tmp;
+	RING_LOCALS;
+
+	BUG_ON(!overlay->active);
+
+	if (load_polyphase_filter)
+		flip_addr |= OFC_UPDATE;
+
+	/* check for underruns */
+	tmp = I915_READ(DOVSTA);
+	if (tmp & (1 << 17))
+		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
+
+	BEGIN_LP_RING(4);
+	OUT_RING(MI_FLUSH);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+	OUT_RING(flip_addr);
+        ADVANCE_LP_RING();
+
+	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+}
+
+static int intel_overlay_wait_flip(struct intel_overlay *overlay)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+	u32 tmp;
+	RING_LOCALS;
+
+	if (overlay->last_flip_req != 0) {
+		ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+		if (ret == 0) {
+			overlay->last_flip_req = 0;
+
+			tmp = I915_READ(ISR);
+
+			if (!(tmp & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT))
+				return 0;
+		}
+	}
+
+	/* synchronous slowpath */
+	overlay->hw_wedged = RELEASE_OLD_VID;
+
+	BEGIN_LP_RING(2);
+        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+        OUT_RING(MI_NOOP);
+        ADVANCE_LP_RING();
+
+	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+	if (overlay->last_flip_req == 0)
+		return -ENOMEM;
+
+	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+	if (ret != 0)
+		return ret;
+
+	overlay->hw_wedged = 0;
+	overlay->last_flip_req = 0;
+	return 0;
+}
+
+/* overlay needs to be disabled in OCMD reg */
+static int intel_overlay_off(struct intel_overlay *overlay)
+{
+	u32 flip_addr = overlay->flip_addr;
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	int ret;
+	RING_LOCALS;
+
+	BUG_ON(!overlay->active);
+
+	/* According to intel docs the overlay hw may hang (when switching
+	 * off) without loading the filter coeffs. It is however unclear whether
+	 * this applies to the disabling of the overlay or to the switching off
+	 * of the hw. Do it in both cases */
+	flip_addr |= OFC_UPDATE;
+
+	/* wait for overlay to go idle */
+	overlay->hw_wedged = SWITCH_OFF_STAGE_1;
+
+	BEGIN_LP_RING(6);
+	OUT_RING(MI_FLUSH);
+	OUT_RING(MI_NOOP);
+	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+	OUT_RING(flip_addr);
+        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+        OUT_RING(MI_NOOP);
+        ADVANCE_LP_RING();
+
+	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+	if (overlay->last_flip_req == 0)
+		return -ENOMEM;
+
+	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+	if (ret != 0)
+		return ret;
+
+	/* turn overlay off */
+	overlay->hw_wedged = SWITCH_OFF_STAGE_2;
+
+	BEGIN_LP_RING(6);
+        OUT_RING(MI_FLUSH);
+        OUT_RING(MI_NOOP);
+        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+	OUT_RING(flip_addr);
+        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+        OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+
+	overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+	if (overlay->last_flip_req == 0)
+		return -ENOMEM;
+
+	ret = i915_do_wait_request(dev, overlay->last_flip_req, 1);
+	if (ret != 0)
+		return ret;
+
+	overlay->hw_wedged = 0;
+	overlay->last_flip_req = 0;
+	return ret;
+}
+
+static void intel_overlay_off_tail(struct intel_overlay *overlay)
+{
+	struct drm_gem_object *obj;
+
+	/* never have the overlay hw on without showing a frame */
+	BUG_ON(!overlay->vid_bo);
+	obj = overlay->vid_bo->obj;
+
+	i915_gem_object_unpin(obj);
+	drm_gem_object_unreference(obj);
+	overlay->vid_bo = NULL;
+
+	overlay->crtc->overlay = NULL;
+	overlay->crtc = NULL;
+	overlay->active = 0;
+}
+
+/* recover from an interruption due to a signal
+ * We have to be careful not to repeat work forever an make forward progess. */
+int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
+					 int interruptible)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj;
+	u32 flip_addr;
+	int ret;
+	RING_LOCALS;
+
+	if (overlay->hw_wedged == HW_WEDGED)
+		return -EIO;
+
+	if (overlay->last_flip_req == 0) {
+		overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+		if (overlay->last_flip_req == 0)
+			return -ENOMEM;
+	}
+
+	ret = i915_do_wait_request(dev, overlay->last_flip_req, interruptible);
+	if (ret != 0)
+		return ret;
+
+	switch (overlay->hw_wedged) {
+		case RELEASE_OLD_VID:
+			obj = overlay->old_vid_bo->obj;
+			i915_gem_object_unpin(obj);
+			drm_gem_object_unreference(obj);
+			overlay->old_vid_bo = NULL;
+			break;
+		case SWITCH_OFF_STAGE_1:
+			flip_addr = overlay->flip_addr;
+			flip_addr |= OFC_UPDATE;
+
+			overlay->hw_wedged = SWITCH_OFF_STAGE_2;
+
+			BEGIN_LP_RING(6);
+			OUT_RING(MI_FLUSH);
+			OUT_RING(MI_NOOP);
+			OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+			OUT_RING(flip_addr);
+			OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+			OUT_RING(MI_NOOP);
+			ADVANCE_LP_RING();
+
+			overlay->last_flip_req = i915_add_request(dev, NULL, 0);
+			if (overlay->last_flip_req == 0)
+				return -ENOMEM;
+
+			ret = i915_do_wait_request(dev, overlay->last_flip_req,
+					interruptible);
+			if (ret != 0)
+				return ret;
+
+		case SWITCH_OFF_STAGE_2:
+			intel_overlay_off_tail(overlay);
+			break;
+		default:
+			BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
+	}
+
+	overlay->hw_wedged = 0;
+	overlay->last_flip_req = 0;
+	return 0;
+}
+
+/* Wait for pending overlay flip and release old frame.
+ * Needs to be called before the overlay register are changed
+ * via intel_overlay_(un)map_regs_atomic */
+static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
+{
+	int ret;
+	struct drm_gem_object *obj;
+
+	/* only wait if there is actually an old frame to release to
+	 * guarantee forward progress */
+	if (!overlay->old_vid_bo)
+		return 0;
+
+	ret = intel_overlay_wait_flip(overlay);
+	if (ret != 0)
+		return ret;
+
+	obj = overlay->old_vid_bo->obj;
+	i915_gem_object_unpin(obj);
+	drm_gem_object_unreference(obj);
+	overlay->old_vid_bo = NULL;
+
+	return 0;
+}
+
+struct put_image_params {
+	int format;
+	short dst_x;
+	short dst_y;
+	short dst_w;
+	short dst_h;
+	short src_w;
+	short src_scan_h;
+	short src_scan_w;
+	short src_h;
+	short stride_Y;
+	short stride_UV;
+	int offset_Y;
+	int offset_U;
+	int offset_V;
+};
+
+static int packed_depth_bytes(u32 format)
+{
+	switch (format & I915_OVERLAY_DEPTH_MASK) {
+		case I915_OVERLAY_YUV422:
+			return 4;
+		case I915_OVERLAY_YUV411:
+			/* return 6; not implemented */
+		default:
+			return -EINVAL;
+	}
+}
+
+static int packed_width_bytes(u32 format, short width)
+{
+	switch (format & I915_OVERLAY_DEPTH_MASK) {
+		case I915_OVERLAY_YUV422:
+			return width << 1;
+		default:
+			return -EINVAL;
+	}
+}
+
+static int uv_hsubsampling(u32 format)
+{
+	switch (format & I915_OVERLAY_DEPTH_MASK) {
+		case I915_OVERLAY_YUV422:
+		case I915_OVERLAY_YUV420:
+			return 2;
+		case I915_OVERLAY_YUV411:
+		case I915_OVERLAY_YUV410:
+			return 4;
+		default:
+			return -EINVAL;
+	}
+}
+
+static int uv_vsubsampling(u32 format)
+{
+	switch (format & I915_OVERLAY_DEPTH_MASK) {
+		case I915_OVERLAY_YUV420:
+		case I915_OVERLAY_YUV410:
+			return 2;
+		case I915_OVERLAY_YUV422:
+		case I915_OVERLAY_YUV411:
+			return 1;
+		default:
+			return -EINVAL;
+	}
+}
+
+static u32 calc_swidthsw(struct drm_device *dev, u32 offset, u32 width)
+{
+	u32 mask, shift, ret;
+	if (IS_I9XX(dev)) {
+		mask = 0x3f;
+		shift = 6;
+	} else {
+		mask = 0x1f;
+		shift = 5;
+	}
+	ret = ((offset + width + mask) >> shift) - (offset >> shift);
+	if (IS_I9XX(dev))
+		ret <<= 1;
+	ret -=1;
+	return ret << 2;
+}
+
+static const u16 y_static_hcoeffs[N_HORIZ_Y_TAPS * N_PHASES] = {
+	0x3000, 0xb4a0, 0x1930, 0x1920, 0xb4a0,
+	0x3000, 0xb500, 0x19d0, 0x1880, 0xb440,
+	0x3000, 0xb540, 0x1a88, 0x2f80, 0xb3e0,
+	0x3000, 0xb580, 0x1b30, 0x2e20, 0xb380,
+	0x3000, 0xb5c0, 0x1bd8, 0x2cc0, 0xb320,
+	0x3020, 0xb5e0, 0x1c60, 0x2b80, 0xb2c0,
+	0x3020, 0xb5e0, 0x1cf8, 0x2a20, 0xb260,
+	0x3020, 0xb5e0, 0x1d80, 0x28e0, 0xb200,
+	0x3020, 0xb5c0, 0x1e08, 0x3f40, 0xb1c0,
+	0x3020, 0xb580, 0x1e78, 0x3ce0, 0xb160,
+	0x3040, 0xb520, 0x1ed8, 0x3aa0, 0xb120,
+	0x3040, 0xb4a0, 0x1f30, 0x3880, 0xb0e0,
+	0x3040, 0xb400, 0x1f78, 0x3680, 0xb0a0,
+	0x3020, 0xb340, 0x1fb8, 0x34a0, 0xb060,
+	0x3020, 0xb240, 0x1fe0, 0x32e0, 0xb040,
+	0x3020, 0xb140, 0x1ff8, 0x3160, 0xb020,
+	0xb000, 0x3000, 0x0800, 0x3000, 0xb000};
+static const u16 uv_static_hcoeffs[N_HORIZ_UV_TAPS * N_PHASES] = {
+	0x3000, 0x1800, 0x1800, 0xb000, 0x18d0, 0x2e60,
+	0xb000, 0x1990, 0x2ce0, 0xb020, 0x1a68, 0x2b40,
+	0xb040, 0x1b20, 0x29e0, 0xb060, 0x1bd8, 0x2880,
+	0xb080, 0x1c88, 0x3e60, 0xb0a0, 0x1d28, 0x3c00,
+	0xb0c0, 0x1db8, 0x39e0, 0xb0e0, 0x1e40, 0x37e0,
+	0xb100, 0x1eb8, 0x3620, 0xb100, 0x1f18, 0x34a0,
+	0xb100, 0x1f68, 0x3360, 0xb0e0, 0x1fa8, 0x3240,
+	0xb0c0, 0x1fe0, 0x3140, 0xb060, 0x1ff0, 0x30a0,
+	0x3000, 0x0800, 0x3000};
+
+static void update_polyphase_filter(struct overlay_registers *regs)
+{
+	memcpy(regs->Y_HCOEFS, y_static_hcoeffs, sizeof(y_static_hcoeffs));
+	memcpy(regs->UV_HCOEFS, uv_static_hcoeffs, sizeof(uv_static_hcoeffs));
+}
+
+static bool update_scaling_factors(struct intel_overlay *overlay,
+				   struct overlay_registers *regs,
+				   struct put_image_params *params)
+{
+	/* fixed point with a 12 bit shift */
+	u32 xscale, yscale, xscale_UV, yscale_UV;
+#define FP_SHIFT 12
+#define FRACT_MASK 0xfff
+	bool scale_changed = false;
+	int uv_hscale = uv_hsubsampling(params->format);
+	int uv_vscale = uv_vsubsampling(params->format);
+
+	if (params->dst_w > 1)
+		xscale = ((params->src_scan_w - 1) << FP_SHIFT)
+			/(params->dst_w);
+	else
+		xscale = 1 << FP_SHIFT;
+
+	if (params->dst_h > 1)
+		yscale = ((params->src_scan_h - 1) << FP_SHIFT)
+			/(params->dst_h);
+	else
+		yscale = 1 << FP_SHIFT;
+
+	/*if (params->format & I915_OVERLAY_YUV_PLANAR) {*/
+		xscale_UV = xscale/uv_hscale;
+		yscale_UV = yscale/uv_vscale;
+		/* make the Y scale to UV scale ratio an exact multiply */
+		xscale = xscale_UV * uv_hscale;
+		yscale = yscale_UV * uv_vscale;
+	/*} else {
+		xscale_UV = 0;
+		yscale_UV = 0;
+	}*/
+
+	if (xscale != overlay->old_xscale || yscale != overlay->old_yscale)
+		scale_changed = true;
+	overlay->old_xscale = xscale;
+	overlay->old_yscale = yscale;
+
+	regs->YRGBSCALE = ((yscale & FRACT_MASK) << 20)
+		| ((xscale >> FP_SHIFT) << 16)
+		| ((xscale & FRACT_MASK) << 3);
+	regs->UVSCALE = ((yscale_UV & FRACT_MASK) << 20)
+		| ((xscale_UV >> FP_SHIFT) << 16)
+		| ((xscale_UV & FRACT_MASK) << 3);
+	regs->UVSCALEV = ((yscale >> FP_SHIFT) << 16)
+		| ((yscale_UV >> FP_SHIFT) << 0);
+
+	if (scale_changed)
+		update_polyphase_filter(regs);
+
+	return scale_changed;
+}
+
+static void update_colorkey(struct intel_overlay *overlay,
+			    struct overlay_registers *regs)
+{
+	u32 key = overlay->color_key;
+	switch (overlay->crtc->base.fb->bits_per_pixel) {
+		case 8:
+			regs->DCLRKV = 0;
+			regs->DCLRKM = CLK_RGB8I_MASK | DST_KEY_ENABLE;
+		case 16:
+			if (overlay->crtc->base.fb->depth == 15) {
+				regs->DCLRKV = RGB15_TO_COLORKEY(key);
+				regs->DCLRKM = CLK_RGB15_MASK | DST_KEY_ENABLE;
+			} else {
+				regs->DCLRKV = RGB16_TO_COLORKEY(key);
+				regs->DCLRKM = CLK_RGB16_MASK | DST_KEY_ENABLE;
+			}
+		case 24:
+		case 32:
+			regs->DCLRKV = key;
+			regs->DCLRKM = CLK_RGB24_MASK | DST_KEY_ENABLE;
+	}
+}
+
+static u32 overlay_cmd_reg(struct put_image_params *params)
+{
+	u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
+
+	if (params->format & I915_OVERLAY_YUV_PLANAR) {
+		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
+			case I915_OVERLAY_YUV422:
+				cmd |= OCMD_YUV_422_PLANAR;
+				break;
+			case I915_OVERLAY_YUV420:
+				cmd |= OCMD_YUV_420_PLANAR;
+				break;
+			case I915_OVERLAY_YUV411:
+			case I915_OVERLAY_YUV410:
+				cmd |= OCMD_YUV_410_PLANAR;
+				break;
+		}
+	} else { /* YUV packed */
+		switch (params->format & I915_OVERLAY_DEPTH_MASK) {
+			case I915_OVERLAY_YUV422:
+				cmd |= OCMD_YUV_422_PACKED;
+				break;
+			case I915_OVERLAY_YUV411:
+				cmd |= OCMD_YUV_411_PACKED;
+				break;
+		}
+
+		switch (params->format & I915_OVERLAY_SWAP_MASK) {
+			case I915_OVERLAY_NO_SWAP:
+				break;
+			case I915_OVERLAY_UV_SWAP:
+				cmd |= OCMD_UV_SWAP;
+				break;
+			case I915_OVERLAY_Y_SWAP:
+				cmd |= OCMD_Y_SWAP;
+				break;
+			case I915_OVERLAY_Y_AND_UV_SWAP:
+				cmd |= OCMD_Y_AND_UV_SWAP;
+				break;
+		}
+	}
+
+	return cmd;
+}
+
+int intel_overlay_do_put_image(struct intel_overlay *overlay,
+			       struct drm_gem_object *new_bo,
+			       struct put_image_params *params)
+{
+	int ret, tmp_width;
+	struct overlay_registers *regs;
+	bool scale_changed = false;
+	struct drm_i915_gem_object *bo_priv = new_bo->driver_private;
+	struct drm_device *dev = overlay->dev;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
+	BUG_ON(!overlay);
+
+	ret = intel_overlay_release_old_vid(overlay);
+	if (ret != 0)
+		return ret;
+
+	ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
+	if (ret != 0)
+		return ret;
+
+	ret = i915_gem_object_set_to_gtt_domain(new_bo, 0);
+	if (ret != 0)
+		goto out_unpin;
+
+	if (!overlay->active) {
+		regs = intel_overlay_map_regs_atomic(overlay);
+		if (!regs) {
+			ret = -ENOMEM;
+			goto out_unpin;
+		}
+		regs->OCONFIG = OCONF_CC_OUT_8BIT;
+		if (IS_I965GM(overlay->dev))
+			regs->OCONFIG |= OCONF_CSC_MODE_BT709;
+		regs->OCONFIG |= overlay->crtc->pipe == 0 ?
+			OCONF_PIPE_A : OCONF_PIPE_B;
+		intel_overlay_unmap_regs_atomic(overlay);
+
+		ret = intel_overlay_on(overlay);
+		if (ret != 0)
+			goto out_unpin;
+	}
+
+	regs = intel_overlay_map_regs_atomic(overlay);
+	if (!regs) {
+		ret = -ENOMEM;
+		goto out_unpin;
+	}
+
+	regs->DWINPOS = (params->dst_y << 16) | params->dst_x;
+	regs->DWINSZ = (params->dst_h << 16) | params->dst_w;
+
+	if (params->format & I915_OVERLAY_YUV_PACKED)
+		tmp_width = packed_width_bytes(params->format, params->src_w);
+	else
+		tmp_width = params->src_w;
+
+	regs->SWIDTH = params->src_w;
+	regs->SWIDTHSW = calc_swidthsw(overlay->dev,
+			params->offset_Y, tmp_width);
+	regs->SHEIGHT = params->src_h;
+	regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
+	regs->OSTRIDE = params->stride_Y;
+
+	if (params->format & I915_OVERLAY_YUV_PLANAR) {
+		int uv_hscale = uv_hsubsampling(params->format);
+		int uv_vscale = uv_vsubsampling(params->format);
+		u32 tmp_U, tmp_V;
+		regs->SWIDTH |= (params->src_w/uv_hscale) << 16;
+		tmp_U = calc_swidthsw(overlay->dev, params->offset_U,
+				params->src_w/uv_hscale);
+		tmp_V = calc_swidthsw(overlay->dev, params->offset_V,
+				params->src_w/uv_hscale);
+		regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
+		regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
+		regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
+		regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
+		regs->OSTRIDE |= params->stride_UV << 16;
+	}
+
+	scale_changed = update_scaling_factors(overlay, regs, params);
+
+	update_colorkey(overlay, regs);
+
+	regs->OCMD = overlay_cmd_reg(params);
+
+	intel_overlay_unmap_regs_atomic(overlay);
+
+	intel_overlay_continue(overlay, scale_changed);
+
+	overlay->old_vid_bo = overlay->vid_bo;
+	overlay->vid_bo = new_bo->driver_private;
+
+	return 0;
+
+out_unpin:
+	i915_gem_object_unpin(new_bo);
+	return ret;
+}
+
+int intel_overlay_switch_off(struct intel_overlay *overlay)
+{
+	int ret;
+	struct overlay_registers *regs;
+	struct drm_device *dev = overlay->dev;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
+	if (overlay->hw_wedged) {
+		ret = intel_overlay_recover_from_interrupt(overlay, 1);
+		if (ret != 0)
+			return ret;
+	}
+
+	if (!overlay->active)
+		return 0;
+
+	ret = intel_overlay_release_old_vid(overlay);
+	if (ret != 0)
+		return ret;
+
+	regs = intel_overlay_map_regs_atomic(overlay);
+	regs->OCMD = 0;
+	intel_overlay_unmap_regs_atomic(overlay);
+
+	ret = intel_overlay_off(overlay);
+	if (ret != 0)
+		return ret;
+
+	intel_overlay_off_tail(overlay);
+
+	return 0;
+}
+
+static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
+					  struct intel_crtc *crtc)
+{
+        drm_i915_private_t *dev_priv = overlay->dev->dev_private;
+	u32 pipeconf;
+	int pipeconf_reg = (crtc->pipe == 0) ? PIPEACONF : PIPEBCONF;
+
+	if (!crtc->base.enabled || crtc->dpms_mode != DRM_MODE_DPMS_ON)
+		return -EINVAL;
+
+	pipeconf = I915_READ(pipeconf_reg);
+
+	/* can't use the overlay with double wide pipe */
+	if (!IS_I965G(overlay->dev) && pipeconf & PIPEACONF_DOUBLE_WIDE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
+{
+	struct drm_device *dev = overlay->dev;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 ratio;
+	u32 pfit_control = I915_READ(PFIT_CONTROL);
+
+	/* XXX: This is not the same logic as in the xorg driver, but more in
+	 * line with the intel documentation for the i965 */
+	if (!IS_I965G(dev) && (pfit_control & VERT_AUTO_SCALE)) {
+		ratio = I915_READ(PFIT_AUTO_RATIOS) >> PFIT_VERT_SCALE_SHIFT;
+	} else { /* on i965 use the PGM reg to read out the autoscaler values */
+		ratio = I915_READ(PFIT_PGM_RATIOS);
+		if (IS_I965G(dev))
+			ratio >>= PFIT_VERT_SCALE_SHIFT_965;
+		else
+			ratio >>= PFIT_VERT_SCALE_SHIFT;
+	}
+
+	overlay->pfit_vscale_ratio = ratio;
+}
+
+static int check_overlay_dst(struct intel_overlay *overlay,
+			     struct drm_intel_overlay_put_image *rec)
+{
+	struct drm_display_mode *mode = &overlay->crtc->base.mode;
+
+	if ((rec->dst_x < mode->crtc_hdisplay)
+	    && (rec->dst_x + rec->dst_width
+		    <= mode->crtc_hdisplay)
+	    && (rec->dst_y < mode->crtc_vdisplay)
+	    && (rec->dst_y + rec->dst_height
+		    <= mode->crtc_vdisplay))
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int check_overlay_scaling(struct put_image_params *rec)
+{
+	u32 tmp;
+
+	/* downscaling limit is 8.0 */
+	tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16;
+	if (tmp > 7)
+		return -EINVAL;
+	tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
+	if (tmp > 7)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int check_overlay_src(struct drm_device *dev,
+			     struct drm_intel_overlay_put_image *rec,
+			     struct drm_gem_object *new_bo)
+{
+	u32 stride_mask;
+	int depth;
+	int uv_hscale = uv_hsubsampling(rec->flags);
+	int uv_vscale = uv_vsubsampling(rec->flags);
+	size_t tmp;
+
+	/* check src dimensions */
+	if (IS_845G(dev) || IS_I830(dev)) {
+		if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY
+		    || rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
+			return -EINVAL;
+	} else {
+		if (rec->src_height > IMAGE_MAX_HEIGHT
+		    || rec->src_width > IMAGE_MAX_WIDTH)
+			return -EINVAL;
+	}
+	/* better safe than sorry, use 4 as the maximal subsampling ratio */
+	if (rec->src_height < N_VERT_Y_TAPS*4
+	    || rec->src_width < N_HORIZ_Y_TAPS*4)
+		return -EINVAL;
+
+	/* check alignment constraints */
+	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
+		case I915_OVERLAY_RGB:
+			/* not implemented */
+			return -EINVAL;
+		case I915_OVERLAY_YUV_PACKED:
+			depth = packed_depth_bytes(rec->flags);
+			if (uv_vscale != 1)
+				return -EINVAL;
+			if (depth < 0)
+				return depth;
+			/* ignore UV planes */
+			rec->stride_UV = 0;
+			rec->offset_U = 0;
+			rec->offset_V = 0;
+			/* check pixel alignment */
+			if (rec->offset_Y % depth)
+				return -EINVAL;
+			break;
+		case I915_OVERLAY_YUV_PLANAR:
+			if (uv_vscale < 0 || uv_hscale < 0)
+				return -EINVAL;
+			/* no offset restrictions for planar formats */
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	if (rec->src_width % uv_hscale)
+		return -EINVAL;
+
+	/* stride checking */
+	if (IS_I830(dev) || IS_845G(dev))
+		stride_mask = 255;
+	else
+		stride_mask = 63;
+
+	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
+		return -EINVAL;
+	if (IS_I965G(dev) && rec->stride_Y < 512)
+		return -EINVAL;
+
+	tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
+		4 : 8;
+	if (rec->stride_Y > tmp*1024 || rec->stride_UV > 2*1024)
+		return -EINVAL;
+
+	/* check buffer dimensions */
+	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
+		case I915_OVERLAY_RGB:
+		case I915_OVERLAY_YUV_PACKED:
+			/* always 4 Y values per depth pixels */
+			if (packed_width_bytes(rec->flags, rec->src_width)
+					> rec->stride_Y)
+				return -EINVAL;
+
+			tmp = rec->stride_Y*rec->src_height;
+			if (rec->offset_Y + tmp > new_bo->size)
+				return -EINVAL;
+			break;
+		case I915_OVERLAY_YUV_PLANAR:
+			if (rec->src_width > rec->stride_Y)
+				return -EINVAL;
+			if (rec->src_width/uv_hscale > rec->stride_UV)
+				return -EINVAL;
+
+			tmp = rec->stride_Y*rec->src_height;
+			if (rec->offset_Y + tmp > new_bo->size)
+				return -EINVAL;
+			tmp = rec->stride_UV*rec->src_height;
+			tmp /= uv_vscale;
+			if (rec->offset_U + tmp > new_bo->size
+			    || rec->offset_V + tmp > new_bo->size)
+				return -EINVAL;
+			break;
+	}
+
+	return 0;
+}
+
+int intel_overlay_put_image(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv)
+{
+	struct drm_intel_overlay_put_image *put_image_rec = data;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_overlay *overlay;
+	struct drm_mode_object *drmmode_obj;
+	struct intel_crtc *crtc;
+	struct drm_gem_object *new_bo;
+	struct put_image_params *params;
+	int ret;
+
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
+	overlay = dev_priv->overlay;
+	if (!overlay) {
+		DRM_DEBUG("userspace bug: no overlay\n");
+		return -ENODEV;
+	}
+
+	if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) {
+		mutex_lock(&dev->mode_config.mutex);
+		mutex_lock(&dev->struct_mutex);
+
+		ret = intel_overlay_switch_off(overlay);
+
+		mutex_unlock(&dev->struct_mutex);
+		mutex_unlock(&dev->mode_config.mutex);
+
+		return ret;
+	}
+
+	params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+
+	drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
+                        DRM_MODE_OBJECT_CRTC);
+	if (!drmmode_obj) {
+		ret = -ENOENT;
+		goto out_free;
+	}
+	crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
+
+	new_bo = drm_gem_object_lookup(dev, file_priv,
+			put_image_rec->bo_handle);
+	if (!new_bo) {
+		ret = -ENOENT;
+		goto out_free;
+	}
+
+	mutex_lock(&dev->mode_config.mutex);
+	mutex_lock(&dev->struct_mutex);
+
+	if (overlay->hw_wedged) {
+		ret = intel_overlay_recover_from_interrupt(overlay, 1);
+		if (ret != 0)
+			goto out_unlock;
+	}
+
+	if (overlay->crtc != crtc) {
+		struct drm_display_mode *mode = &crtc->base.mode;
+		ret = intel_overlay_switch_off(overlay);
+		if (ret != 0)
+			goto out_unlock;
+
+		ret = check_overlay_possible_on_crtc(overlay, crtc);
+		if (ret != 0)
+			goto out_unlock;
+
+		overlay->crtc = crtc;
+		crtc->overlay = overlay;
+
+		if (intel_panel_fitter_pipe(dev) == crtc->pipe
+		    /* and line to wide, i.e. one-line-mode */
+		    && mode->hdisplay > 1024) {
+			overlay->pfit_active = 1;
+			update_pfit_vscale_ratio(overlay);
+		} else
+			overlay->pfit_active = 0;
+	}
+
+	ret = check_overlay_dst(overlay, put_image_rec);
+	if (ret != 0)
+		goto out_unlock;
+
+	if (overlay->pfit_active) {
+		params->dst_y = ((((u32)put_image_rec->dst_y) << 12) /
+			overlay->pfit_vscale_ratio);
+		/* shifting right rounds downwards, so add 1 */
+		params->dst_h = ((((u32)put_image_rec->dst_height) << 12) /
+			overlay->pfit_vscale_ratio) + 1;
+	} else {
+		params->dst_y = put_image_rec->dst_y;
+		params->dst_h = put_image_rec->dst_height;
+	}
+	params->dst_x = put_image_rec->dst_x;
+	params->dst_w = put_image_rec->dst_width;
+
+	params->src_w = put_image_rec->src_width;
+	params->src_h = put_image_rec->src_height;
+	params->src_scan_w = put_image_rec->src_scan_width;
+	params->src_scan_h = put_image_rec->src_scan_height;
+	if (params->src_scan_h > params->src_h
+	    || params->src_scan_w > params->src_w) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = check_overlay_src(dev, put_image_rec, new_bo);
+	if (ret != 0)
+		goto out_unlock;
+	params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
+	params->stride_Y = put_image_rec->stride_Y;
+	params->stride_UV = put_image_rec->stride_UV;
+	params->offset_Y = put_image_rec->offset_Y;
+	params->offset_U = put_image_rec->offset_U;
+	params->offset_V = put_image_rec->offset_V;
+
+	/* Check scaling after src size to prevent a divide-by-zero. */
+	ret = check_overlay_scaling(params);
+	if (ret != 0)
+		goto out_unlock;
+
+	ret = intel_overlay_do_put_image(overlay, new_bo, params);
+	if (ret != 0)
+		goto out_unlock;
+
+	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	kfree(params);
+
+	return 0;
+
+out_unlock:
+	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->mode_config.mutex);
+	drm_gem_object_unreference(new_bo);
+out_free:
+	kfree(params);
+
+	return ret;
+}
+
+static void update_reg_attrs(struct intel_overlay *overlay,
+			     struct overlay_registers *regs)
+{
+	regs->OCLRC0 = (overlay->contrast << 18) | (overlay->brightness & 0xff);
+	regs->OCLRC1 = overlay->saturation;
+}
+
+static bool check_gamma_bounds(u32 gamma1, u32 gamma2)
+{
+	int i;
+
+	if (gamma1 & 0xff000000 || gamma2 & 0xff000000)
+		return false;
+
+	for (i = 0; i < 3; i++) {
+		if (((gamma1 >> i * 8) & 0xff) >= ((gamma2 >> i*8) & 0xff))
+			return false;
+	}
+
+	return true;
+}
+
+static bool check_gamma5_errata(u32 gamma5)
+{
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (((gamma5 >> i*8) & 0xff) == 0x80)
+			return false;
+	}
+
+	return true;
+}
+
+static int check_gamma(struct drm_intel_overlay_attrs *attrs)
+{
+	if (!check_gamma_bounds(0, attrs->gamma0)
+	    || !check_gamma_bounds(attrs->gamma0, attrs->gamma1)
+	    || !check_gamma_bounds(attrs->gamma1, attrs->gamma2)
+	    || !check_gamma_bounds(attrs->gamma2, attrs->gamma3)
+	    || !check_gamma_bounds(attrs->gamma3, attrs->gamma4)
+	    || !check_gamma_bounds(attrs->gamma4, attrs->gamma5)
+	    || !check_gamma_bounds(attrs->gamma5, 0x00ffffff))
+		return -EINVAL;
+	if (!check_gamma5_errata(attrs->gamma5))
+		return -EINVAL;
+	return 0;
+}
+
+int intel_overlay_attrs(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+	struct drm_intel_overlay_attrs *attrs = data;
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_overlay *overlay;
+	struct overlay_registers *regs;
+	int ret;
+
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
+	overlay = dev_priv->overlay;
+	if (!overlay) {
+		DRM_DEBUG("userspace bug: no overlay\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&dev->mode_config.mutex);
+	mutex_lock(&dev->struct_mutex);
+
+	if (!(attrs->flags & I915_OVERLAY_UPDATE_ATTRS)) {
+		attrs->color_key = overlay->color_key;
+		attrs->brightness = overlay->brightness;
+		attrs->contrast = overlay->contrast;
+		attrs->saturation = overlay->saturation;
+
+		if (IS_I9XX(dev)) {
+			attrs->gamma0 = I915_READ(OGAMC0);
+			attrs->gamma1 = I915_READ(OGAMC1);
+			attrs->gamma2 = I915_READ(OGAMC2);
+			attrs->gamma3 = I915_READ(OGAMC3);
+			attrs->gamma4 = I915_READ(OGAMC4);
+			attrs->gamma5 = I915_READ(OGAMC5);
+		}
+		ret = 0;
+	} else {
+		overlay->color_key = attrs->color_key;
+		if (attrs->brightness >= -128 && attrs->brightness <= 127) {
+			overlay->brightness = attrs->brightness;
+		} else {
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		if (attrs->contrast <= 255) {
+			overlay->contrast = attrs->contrast;
+		} else {
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+		if (attrs->saturation <= 1023) {
+			overlay->saturation = attrs->saturation;
+		} else {
+			ret = -EINVAL;
+			goto out_unlock;
+		}
+
+		regs = intel_overlay_map_regs_atomic(overlay);
+		if (!regs) {
+			ret = -ENOMEM;
+			goto out_unlock;
+		}
+
+		update_reg_attrs(overlay, regs);
+
+		intel_overlay_unmap_regs_atomic(overlay);
+
+		if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
+			if (!IS_I9XX(dev)) {
+				ret = -EINVAL;
+				goto out_unlock;
+			}
+
+			if (overlay->active) {
+				ret = -EBUSY;
+				goto out_unlock;
+			}
+
+			ret = check_gamma(attrs);
+			if (ret != 0)
+				goto out_unlock;
+
+			I915_WRITE(OGAMC0, attrs->gamma0);
+			I915_WRITE(OGAMC1, attrs->gamma1);
+			I915_WRITE(OGAMC2, attrs->gamma2);
+			I915_WRITE(OGAMC3, attrs->gamma3);
+			I915_WRITE(OGAMC4, attrs->gamma4);
+			I915_WRITE(OGAMC5, attrs->gamma5);
+		}
+		ret = 0;
+	}
+
+out_unlock:
+	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+void intel_setup_overlay(struct drm_device *dev)
+{
+        drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_overlay *overlay;
+	struct drm_gem_object *reg_bo;
+	struct overlay_registers *regs;
+	int ret;
+
+	if (!OVERLAY_EXISTS(dev))
+		return;
+
+	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
+	if (!overlay)
+		return;
+	overlay->dev = dev;
+
+	reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE);
+	if (!reg_bo)
+		goto out_free;
+	overlay->reg_bo = reg_bo->driver_private;
+
+	if (OVERLAY_NONPHYSICAL(dev)) {
+		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
+		if (ret) {
+                        DRM_ERROR("failed to pin overlay register bo\n");
+                        goto out_free_bo;
+                }
+		overlay->flip_addr = overlay->reg_bo->gtt_offset;
+
+		ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
+		if (ret) {
+                        DRM_ERROR("failed to move overlay register bo into the GTT\n");
+                        goto out_unpin_bo;
+                }
+	} else {
+		ret = i915_gem_attach_phys_object(dev, reg_bo,
+				I915_GEM_PHYS_OVERLAY_REGS);
+                if (ret) {
+                        DRM_ERROR("failed to attach phys overlay regs\n");
+                        goto out_free_bo;
+                }
+		overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
+	}
+
+	/* init all values */
+	overlay->color_key = 0x0101fe;
+	overlay->brightness = -19;
+	overlay->contrast = 75;
+	overlay->saturation = 146;
+
+	regs = intel_overlay_map_regs_atomic(overlay);
+	if (!regs)
+		goto out_free_bo;
+
+	memset(regs, 0, sizeof(struct overlay_registers));
+	update_polyphase_filter(regs);
+
+	update_reg_attrs(overlay, regs);
+
+	intel_overlay_unmap_regs_atomic(overlay);
+
+	dev_priv->overlay = overlay;
+	DRM_INFO("initialized overlay support\n");
+	return;
+
+out_unpin_bo:
+	i915_gem_object_unpin(reg_bo);
+out_free_bo:
+	drm_gem_object_unreference(reg_bo);
+out_free:
+	kfree(overlay);
+	return;
+}
+
+void intel_cleanup_overlay(struct drm_device *dev)
+{
+        drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (dev_priv->overlay) {
+		/* The bo's should be free'd by the generic code already.
+		 * Furthermore modesetting teardown happens beforehand so the
+		 * hardware should be off already */
+		BUG_ON(dev_priv->overlay->active);
+
+		kfree(dev_priv->overlay);
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_fb.c
@@ -70,7 +70,7 @@
 
 
 /**
- * Curretly it is assumed that the old framebuffer is reused.
+ * Currently it is assumed that the old framebuffer is reused.
  *
  * LOCKING
  * caller should hold the mode config lock.
@@ -148,7 +148,7 @@
 
 	mutex_lock(&dev->struct_mutex);
 
-	ret = i915_gem_object_pin(fbo, PAGE_SIZE);
+	ret = i915_gem_object_pin(fbo, 64*1024);
 	if (ret) {
 		DRM_ERROR("failed to pin fb: %d\n", ret);
 		goto out_unref;
@@ -230,8 +230,9 @@
 	par->intel_fb = intel_fb;
 
 	/* To allow resizeing without swapping buffers */
-	DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
-		  intel_fb->base.height, obj_priv->gtt_offset, fbo);
+	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
+			intel_fb->base.width, intel_fb->base.height,
+			obj_priv->gtt_offset, fbo);
 
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
@@ -249,7 +250,7 @@
 {
 	int ret;
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_KMS("\n");
 	ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create);
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/i915_irq.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/i915_irq.c
@@ -43,10 +43,13 @@
  * we leave them always unmasked in IMR and then control enabling them through
  * PIPESTAT alone.
  */
-#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT |		 \
-				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
-				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \
-				   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_FIX			\
+	(I915_ASLE_INTERRUPT |				\
+	 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |		\
+	 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |		\
+	 I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |	\
+	 I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT |	\
+	 I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 
 /** Interrupts that we mask and unmask at runtime. */
 #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
@@ -61,7 +64,7 @@
 					 DRM_I915_VBLANK_PIPE_B)
 
 void
-igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
+ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
 		dev_priv->gt_irq_mask_reg &= ~mask;
@@ -71,7 +74,7 @@
 }
 
 static inline void
-igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
+ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
 		dev_priv->gt_irq_mask_reg |= mask;
@@ -82,7 +85,7 @@
 
 /* For display hotplug interrupt */
 void
-igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
+ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->irq_mask_reg & mask) != 0) {
 		dev_priv->irq_mask_reg &= ~mask;
@@ -92,7 +95,7 @@
 }
 
 static inline void
-igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
+ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
 	if ((dev_priv->irq_mask_reg & mask) != mask) {
 		dev_priv->irq_mask_reg |= mask;
@@ -157,6 +160,20 @@
 }
 
 /**
+ * intel_enable_asle - enable ASLE interrupt for OpRegion
+ */
+void intel_enable_asle (struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+	if (IS_IRONLAKE(dev))
+		ironlake_enable_display_irq(dev_priv, DE_GSE);
+	else
+		i915_enable_pipestat(dev_priv, 1,
+				     I915_LEGACY_BLC_EVENT_ENABLE);
+}
+
+/**
  * i915_pipe_enabled - check if a pipe is enabled
  * @dev: DRM device
  * @pipe: pipe to check
@@ -191,7 +208,8 @@
 	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
+				"pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -220,7 +238,8 @@
 	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
-		DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
+		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
+					"pipe %d\n", pipe);
 		return 0;
 	}
 
@@ -250,12 +269,11 @@
 	drm_sysfs_hotplug_event(dev);
 }
 
-irqreturn_t igdng_irq_handler(struct drm_device *dev)
+irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	int ret = IRQ_NONE;
-	u32 de_iir, gt_iir, de_ier;
-	u32 new_de_iir, new_gt_iir;
+	u32 de_iir, gt_iir, de_ier, pch_iir;
 	struct drm_i915_master_private *master_priv;
 
 	/* disable master interrupt before clearing iir  */
@@ -265,36 +283,60 @@
 
 	de_iir = I915_READ(DEIIR);
 	gt_iir = I915_READ(GTIIR);
+	pch_iir = I915_READ(SDEIIR);
 
-	for (;;) {
-		if (de_iir == 0 && gt_iir == 0)
-			break;
+	if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
+		goto done;
 
-		ret = IRQ_HANDLED;
+	ret = IRQ_HANDLED;
 
-		I915_WRITE(DEIIR, de_iir);
-		new_de_iir = I915_READ(DEIIR);
-		I915_WRITE(GTIIR, gt_iir);
-		new_gt_iir = I915_READ(GTIIR);
+	if (dev->primary->master) {
+		master_priv = dev->primary->master->driver_priv;
+		if (master_priv->sarea_priv)
+			master_priv->sarea_priv->last_dispatch =
+				READ_BREADCRUMB(dev_priv);
+	}
 
-		if (dev->primary->master) {
-			master_priv = dev->primary->master->driver_priv;
-			if (master_priv->sarea_priv)
-				master_priv->sarea_priv->last_dispatch =
-					READ_BREADCRUMB(dev_priv);
-		}
+	if (gt_iir & GT_PIPE_NOTIFY) {
+		u32 seqno = i915_get_gem_seqno(dev);
+		dev_priv->mm.irq_gem_seqno = seqno;
+		trace_i915_gem_request_complete(dev, seqno);
+		DRM_WAKEUP(&dev_priv->irq_queue);
+		dev_priv->hangcheck_count = 0;
+		mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
+	}
 
-		if (gt_iir & GT_USER_INTERRUPT) {
-			u32 seqno = i915_get_gem_seqno(dev);
-			dev_priv->mm.irq_gem_seqno = seqno;
-			trace_i915_gem_request_complete(dev, seqno);
-			DRM_WAKEUP(&dev_priv->irq_queue);
-		}
+	if (de_iir & DE_GSE)
+		ironlake_opregion_gse_intr(dev);
+
+	if (de_iir & DE_PLANEA_FLIP_DONE) {
+		intel_prepare_page_flip(dev, 0);
+		intel_finish_page_flip(dev, 0);
+	}
+
+	if (de_iir & DE_PLANEB_FLIP_DONE) {
+		intel_prepare_page_flip(dev, 1);
+		intel_finish_page_flip(dev, 1);
+	}
+
+	if (de_iir & DE_PIPEA_VBLANK)
+		drm_handle_vblank(dev, 0);
+
+	if (de_iir & DE_PIPEB_VBLANK)
+		drm_handle_vblank(dev, 1);
 
-		de_iir = new_de_iir;
-		gt_iir = new_gt_iir;
+	/* check event from PCH */
+	if ((de_iir & DE_PCH_EVENT) &&
+	    (pch_iir & SDE_HOTPLUG_MASK)) {
+		queue_work(dev_priv->wq, &dev_priv->hotplug_work);
 	}
 
+	/* should clear PCH hotplug event before clear CPU irq */
+	I915_WRITE(SDEIIR, pch_iir);
+	I915_WRITE(GTIIR, gt_iir);
+	I915_WRITE(DEIIR, de_iir);
+
+done:
 	I915_WRITE(DEIER, de_ier);
 	(void)I915_READ(DEIER);
 
@@ -317,19 +359,19 @@
 	char *reset_event[] = { "RESET=1", NULL };
 	char *reset_done_event[] = { "ERROR=0", NULL };
 
-	DRM_DEBUG("generating error event\n");
+	DRM_DEBUG_DRIVER("generating error event\n");
 	kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
 
 	if (atomic_read(&dev_priv->mm.wedged)) {
 		if (IS_I965G(dev)) {
-			DRM_DEBUG("resetting chip\n");
+			DRM_DEBUG_DRIVER("resetting chip\n");
 			kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event);
 			if (!i965_reset(dev, GDRST_RENDER)) {
 				atomic_set(&dev_priv->mm.wedged, 0);
 				kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_done_event);
 			}
 		} else {
-			printk("reboot required\n");
+			DRM_DEBUG_DRIVER("reboot required\n");
 		}
 	}
 }
@@ -355,7 +397,7 @@
 
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
 	if (!error) {
-		DRM_DEBUG("out ot memory, not capturing error state\n");
+		DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n");
 		goto out;
 	}
 
@@ -512,7 +554,6 @@
 		/*
 		 * Wakeup waiting processes so they don't hang
 		 */
-		printk("i915: Waking up sleeping processes\n");
 		DRM_WAKEUP(&dev_priv->irq_queue);
 	}
 
@@ -535,8 +576,8 @@
 
 	atomic_inc(&dev_priv->irq_received);
 
-	if (IS_IGDNG(dev))
-		return igdng_irq_handler(dev);
+	if (HAS_PCH_SPLIT(dev))
+		return ironlake_irq_handler(dev);
 
 	iir = I915_READ(IIR);
 
@@ -568,14 +609,14 @@
 		 */
 		if (pipea_stats & 0x8000ffff) {
 			if (pipea_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG("pipe a underrun\n");
+				DRM_DEBUG_DRIVER("pipe a underrun\n");
 			I915_WRITE(PIPEASTAT, pipea_stats);
 			irq_received = 1;
 		}
 
 		if (pipeb_stats & 0x8000ffff) {
 			if (pipeb_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG("pipe b underrun\n");
+				DRM_DEBUG_DRIVER("pipe b underrun\n");
 			I915_WRITE(PIPEBSTAT, pipeb_stats);
 			irq_received = 1;
 		}
@@ -591,7 +632,7 @@
 		    (iir & I915_DISPLAY_PORT_INTERRUPT)) {
 			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
 
-			DRM_DEBUG("hotplug event received, stat 0x%08x\n",
+			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
 				  hotplug_status);
 			if (hotplug_status & dev_priv->hotplug_supported_mask)
 				queue_work(dev_priv->wq,
@@ -599,27 +640,6 @@
 
 			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
 			I915_READ(PORT_HOTPLUG_STAT);
-
-			/* EOS interrupts occurs */
-			if (IS_IGD(dev) &&
-				(hotplug_status & CRT_EOS_INT_STATUS)) {
-				u32 temp;
-
-				DRM_DEBUG("EOS interrupt occurs\n");
-				/* status is already cleared */
-				temp = I915_READ(ADPA);
-				temp &= ~ADPA_DAC_ENABLE;
-				I915_WRITE(ADPA, temp);
-
-				temp = I915_READ(PORT_HOTPLUG_EN);
-				temp &= ~CRT_EOS_INT_EN;
-				I915_WRITE(PORT_HOTPLUG_EN, temp);
-
-				temp = I915_READ(PORT_HOTPLUG_STAT);
-				if (temp & CRT_EOS_INT_STATUS)
-					I915_WRITE(PORT_HOTPLUG_STAT,
-						CRT_EOS_INT_STATUS);
-			}
 		}
 
 		I915_WRITE(IIR, iir);
@@ -641,14 +661,30 @@
 			mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
 		}
 
+		if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
+			intel_prepare_page_flip(dev, 0);
+			if (dev_priv->flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 0);
+		}
+
+		if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
+			if (dev_priv->flip_pending_is_done)
+				intel_finish_page_flip_plane(dev, 1);
+			intel_prepare_page_flip(dev, 1);
+		}
+
 		if (pipea_stats & vblank_status) {
 			vblank++;
 			drm_handle_vblank(dev, 0);
+			if (!dev_priv->flip_pending_is_done)
+				intel_finish_page_flip(dev, 0);
 		}
 
 		if (pipeb_stats & vblank_status) {
 			vblank++;
 			drm_handle_vblank(dev, 1);
+			if (!dev_priv->flip_pending_is_done)
+				intel_finish_page_flip(dev, 1);
 		}
 
 		if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
@@ -684,7 +720,7 @@
 
 	i915_kernel_lost_context(dev);
 
-	DRM_DEBUG("\n");
+	DRM_DEBUG_DRIVER("\n");
 
 	dev_priv->counter++;
 	if (dev_priv->counter > 0x7FFFFFFFUL)
@@ -709,8 +745,8 @@
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
-		if (IS_IGDNG(dev))
-			igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+		if (HAS_PCH_SPLIT(dev))
+			ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
 		else
 			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
 	}
@@ -725,8 +761,8 @@
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
 	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
-		if (IS_IGDNG(dev))
-			igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
+		if (HAS_PCH_SPLIT(dev))
+			ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY);
 		else
 			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
 	}
@@ -749,7 +785,7 @@
 	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
 	int ret = 0;
 
-	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
+	DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr,
 		  READ_BREADCRUMB(dev_priv));
 
 	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
@@ -832,11 +868,11 @@
 	if (!(pipeconf & PIPEACONF_ENABLE))
 		return -EINVAL;
 
-	if (IS_IGDNG(dev))
-		return 0;
-
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	if (IS_I965G(dev))
+	if (HAS_PCH_SPLIT(dev))
+		ironlake_enable_display_irq(dev_priv, (pipe == 0) ? 
+					    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+	else if (IS_I965G(dev))
 		i915_enable_pipestat(dev_priv, pipe,
 				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
 	else
@@ -854,13 +890,14 @@
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long irqflags;
 
-	if (IS_IGDNG(dev))
-		return;
-
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	i915_disable_pipestat(dev_priv, pipe,
-			      PIPE_VBLANK_INTERRUPT_ENABLE |
-			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
+	if (HAS_PCH_SPLIT(dev))
+		ironlake_disable_display_irq(dev_priv, (pipe == 0) ? 
+					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
+	else
+		i915_disable_pipestat(dev_priv, pipe,
+				      PIPE_VBLANK_INTERRUPT_ENABLE |
+				      PIPE_START_VBLANK_INTERRUPT_ENABLE);
 	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
 }
 
@@ -868,7 +905,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!IS_IGDNG(dev))
+	if (!HAS_PCH_SPLIT(dev))
 		opregion_enable_asle(dev);
 	dev_priv->irq_enabled = 1;
 }
@@ -976,7 +1013,7 @@
 
 /* drm_dma.h hooks
 */
-static void igdng_irq_preinstall(struct drm_device *dev)
+static void ironlake_irq_preinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
@@ -992,17 +1029,25 @@
 	I915_WRITE(GTIMR, 0xffffffff);
 	I915_WRITE(GTIER, 0x0);
 	(void) I915_READ(GTIER);
+
+	/* south display irq */
+	I915_WRITE(SDEIMR, 0xffffffff);
+	I915_WRITE(SDEIER, 0x0);
+	(void) I915_READ(SDEIER);
 }
 
-static int igdng_irq_postinstall(struct drm_device *dev)
+static int ironlake_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	/* enable kind of interrupts always enabled */
-	u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
-	u32 render_mask = GT_USER_INTERRUPT;
+	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
+			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE;
+	u32 render_mask = GT_PIPE_NOTIFY;
+	u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
+			   SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
 
 	dev_priv->irq_mask_reg = ~display_mask;
-	dev_priv->de_irq_enable_reg = display_mask;
+	dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK;
 
 	/* should always can generate irq */
 	I915_WRITE(DEIIR, I915_READ(DEIIR));
@@ -1019,6 +1064,14 @@
 	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
 	(void) I915_READ(GTIER);
 
+	dev_priv->pch_irq_mask_reg = ~hotplug_mask;
+	dev_priv->pch_irq_enable_reg = hotplug_mask;
+
+	I915_WRITE(SDEIIR, I915_READ(SDEIIR));
+	I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
+	I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
+	(void) I915_READ(SDEIER);
+
 	return 0;
 }
 
@@ -1031,8 +1084,8 @@
 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 
-	if (IS_IGDNG(dev)) {
-		igdng_irq_preinstall(dev);
+	if (HAS_PCH_SPLIT(dev)) {
+		ironlake_irq_preinstall(dev);
 		return;
 	}
 
@@ -1049,6 +1102,10 @@
 	(void) I915_READ(IER);
 }
 
+/*
+ * Must be called after intel_modeset_init or hotplug interrupts won't be
+ * enabled correctly.
+ */
 int i915_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1059,8 +1116,8 @@
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
-	if (IS_IGDNG(dev))
-		return igdng_irq_postinstall(dev);
+	if (HAS_PCH_SPLIT(dev))
+		return ironlake_irq_postinstall(dev);
 
 	/* Unmask the interrupts that we always want on. */
 	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
@@ -1071,19 +1128,23 @@
 	if (I915_HAS_HOTPLUG(dev)) {
 		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
 
-		/* Leave other bits alone */
-		hotplug_en |= HOTPLUG_EN_MASK;
+		/* Note HDMI and DP share bits */
+		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMIC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
+			hotplug_en |= HDMID_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOC_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
+			hotplug_en |= SDVOB_HOTPLUG_INT_EN;
+		if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
+			hotplug_en |= CRT_HOTPLUG_INT_EN;
+		/* Ignore TV since it's buggy */
+
 		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 
-		dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS |
-			TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS |
-			SDVOB_HOTPLUG_INT_STATUS;
-		if (IS_G4X(dev)) {
-			dev_priv->hotplug_supported_mask |=
-				HDMIB_HOTPLUG_INT_STATUS |
-				HDMIC_HOTPLUG_INT_STATUS |
-				HDMID_HOTPLUG_INT_STATUS;
-		}
 		/* Enable in IER... */
 		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
 		/* and unmask in IMR */
@@ -1120,7 +1181,7 @@
 	return 0;
 }
 
-static void igdng_irq_uninstall(struct drm_device *dev)
+static void ironlake_irq_uninstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	I915_WRITE(HWSTAM, 0xffffffff);
@@ -1143,8 +1204,8 @@
 
 	dev_priv->vblank_pipe = 0;
 
-	if (IS_IGDNG(dev)) {
-		igdng_irq_uninstall(dev);
+	if (HAS_PCH_SPLIT(dev)) {
+		ironlake_irq_uninstall(dev);
 		return;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/intel_hdmi.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/intel_hdmi.c
@@ -82,7 +82,7 @@
 	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
 	 * we do this anyway which shows more stable in testing.
 	 */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
 		POSTING_READ(hdmi_priv->sdvox_reg);
 	}
@@ -99,7 +99,7 @@
 	/* HW workaround, need to write this twice for issue that may result
 	 * in first write getting masked.
 	 */
-	if (IS_IGDNG(dev)) {
+	if (IS_IRONLAKE(dev)) {
 		I915_WRITE(hdmi_priv->sdvox_reg, temp);
 		POSTING_READ(hdmi_priv->sdvox_reg);
 	}
@@ -225,7 +225,6 @@
 	.destroy = intel_hdmi_enc_destroy,
 };
 
-
 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -254,21 +253,26 @@
 	if (sdvox_reg == SDVOB) {
 		intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
+		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == SDVOC) {
 		intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
+		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIB) {
 		intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
 								"HDMIB");
+		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIC) {
 		intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
 								"HDMIC");
+		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMID) {
 		intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
 		intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
 								"HDMID");
+		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
 	}
 	if (!intel_output->ddc_bus)
 		goto err_connector;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/dvo_sil164.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/dvo_sil164.c
@@ -105,7 +105,7 @@
 	};
 
 	if (!sil->quiet) {
-		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
+		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
@@ -131,7 +131,7 @@
 		return true;
 
 	if (!sil->quiet) {
-		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
+		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
@@ -158,7 +158,7 @@
 		goto out;
 
 	if (ch != (SIL164_VID & 0xff)) {
-		DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
+		DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
 			  ch, adapter->name, dvo->slave_addr);
 		goto out;
 	}
@@ -167,13 +167,13 @@
 		goto out;
 
 	if (ch != (SIL164_DID & 0xff)) {
-		DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
+		DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
 			  ch, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 	sil->quiet = false;
 
-	DRM_DEBUG("init sil164 dvo controller successfully!\n");
+	DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
 	return true;
 
 out:
@@ -241,15 +241,15 @@
 	uint8_t val;
 
 	sil164_readb(dvo, SIL164_FREQ_LO, &val);
-	DRM_DEBUG("SIL164_FREQ_LO: 0x%02x\n", val);
+	DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
 	sil164_readb(dvo, SIL164_FREQ_HI, &val);
-	DRM_DEBUG("SIL164_FREQ_HI: 0x%02x\n", val);
+	DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
 	sil164_readb(dvo, SIL164_REG8, &val);
-	DRM_DEBUG("SIL164_REG8: 0x%02x\n", val);
+	DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val);
 	sil164_readb(dvo, SIL164_REG9, &val);
-	DRM_DEBUG("SIL164_REG9: 0x%02x\n", val);
+	DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val);
 	sil164_readb(dvo, SIL164_REGC, &val);
-	DRM_DEBUG("SIL164_REGC: 0x%02x\n", val);
+	DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);
 }
 
 static void sil164_save(struct intel_dvo_device *dvo)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -152,7 +152,7 @@
 	};
 
 	if (!ch7xxx->quiet) {
-		DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
+		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 	return false;
@@ -179,7 +179,7 @@
 		return true;
 
 	if (!ch7xxx->quiet) {
-		DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
+		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
 			  addr, i2cbus->adapter.name, dvo->slave_addr);
 	}
 
@@ -207,7 +207,8 @@
 
 	name = ch7xxx_get_id(vendor);
 	if (!name) {
-		DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+		DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
+				"slave %d.\n",
 			  vendor, adapter->name, dvo->slave_addr);
 		goto out;
 	}
@@ -217,13 +218,14 @@
 		goto out;
 
 	if (device != CH7xxx_DID) {
-		DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
+		DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
+				"slave %d.\n",
 			  vendor, adapter->name, dvo->slave_addr);
 		goto out;
 	}
 
 	ch7xxx->quiet = false;
-	DRM_DEBUG("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
+	DRM_DEBUG_KMS("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
 		  name, vendor, device);
 	return true;
 out:
@@ -315,8 +317,8 @@
 
 	for (i = 0; i < CH7xxx_NUM_REGS; i++) {
 		if ((i % 8) == 0 )
-			DRM_DEBUG("\n %02X: ", i);
-		DRM_DEBUG("%02X ", ch7xxx->mode_reg.regs[i]);
+			DRM_LOG_KMS("\n %02X: ", i);
+		DRM_LOG_KMS("%02X ", ch7xxx->mode_reg.regs[i]);
 	}
 }
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_lock.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_lock.c
@@ -0,0 +1,313 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#include "ttm/ttm_lock.h"
+#include "ttm/ttm_module.h"
+#include <asm/atomic.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+
+#define TTM_WRITE_LOCK_PENDING    (1 << 0)
+#define TTM_VT_LOCK_PENDING       (1 << 1)
+#define TTM_SUSPEND_LOCK_PENDING  (1 << 2)
+#define TTM_VT_LOCK               (1 << 3)
+#define TTM_SUSPEND_LOCK          (1 << 4)
+
+void ttm_lock_init(struct ttm_lock *lock)
+{
+	spin_lock_init(&lock->lock);
+	init_waitqueue_head(&lock->queue);
+	lock->rw = 0;
+	lock->flags = 0;
+	lock->kill_takers = false;
+	lock->signal = SIGKILL;
+}
+EXPORT_SYMBOL(ttm_lock_init);
+
+void ttm_read_unlock(struct ttm_lock *lock)
+{
+	spin_lock(&lock->lock);
+	if (--lock->rw == 0)
+		wake_up_all(&lock->queue);
+	spin_unlock(&lock->lock);
+}
+EXPORT_SYMBOL(ttm_read_unlock);
+
+static bool __ttm_read_lock(struct ttm_lock *lock)
+{
+	bool locked = false;
+
+	spin_lock(&lock->lock);
+	if (unlikely(lock->kill_takers)) {
+		send_sig(lock->signal, current, 0);
+		spin_unlock(&lock->lock);
+		return false;
+	}
+	if (lock->rw >= 0 && lock->flags == 0) {
+		++lock->rw;
+		locked = true;
+	}
+	spin_unlock(&lock->lock);
+	return locked;
+}
+
+int ttm_read_lock(struct ttm_lock *lock, bool interruptible)
+{
+	int ret = 0;
+
+	if (interruptible)
+		ret = wait_event_interruptible(lock->queue,
+					       __ttm_read_lock(lock));
+	else
+		wait_event(lock->queue, __ttm_read_lock(lock));
+	return ret;
+}
+EXPORT_SYMBOL(ttm_read_lock);
+
+static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked)
+{
+	bool block = true;
+
+	*locked = false;
+
+	spin_lock(&lock->lock);
+	if (unlikely(lock->kill_takers)) {
+		send_sig(lock->signal, current, 0);
+		spin_unlock(&lock->lock);
+		return false;
+	}
+	if (lock->rw >= 0 && lock->flags == 0) {
+		++lock->rw;
+		block = false;
+		*locked = true;
+	} else if (lock->flags == 0) {
+		block = false;
+	}
+	spin_unlock(&lock->lock);
+
+	return !block;
+}
+
+int ttm_read_trylock(struct ttm_lock *lock, bool interruptible)
+{
+	int ret = 0;
+	bool locked;
+
+	if (interruptible)
+		ret = wait_event_interruptible
+			(lock->queue, __ttm_read_trylock(lock, &locked));
+	else
+		wait_event(lock->queue, __ttm_read_trylock(lock, &locked));
+
+	if (unlikely(ret != 0)) {
+		BUG_ON(locked);
+		return ret;
+	}
+
+	return (locked) ? 0 : -EBUSY;
+}
+
+void ttm_write_unlock(struct ttm_lock *lock)
+{
+	spin_lock(&lock->lock);
+	lock->rw = 0;
+	wake_up_all(&lock->queue);
+	spin_unlock(&lock->lock);
+}
+EXPORT_SYMBOL(ttm_write_unlock);
+
+static bool __ttm_write_lock(struct ttm_lock *lock)
+{
+	bool locked = false;
+
+	spin_lock(&lock->lock);
+	if (unlikely(lock->kill_takers)) {
+		send_sig(lock->signal, current, 0);
+		spin_unlock(&lock->lock);
+		return false;
+	}
+	if (lock->rw == 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDING) == 0)) {
+		lock->rw = -1;
+		lock->flags &= ~TTM_WRITE_LOCK_PENDING;
+		locked = true;
+	} else {
+		lock->flags |= TTM_WRITE_LOCK_PENDING;
+	}
+	spin_unlock(&lock->lock);
+	return locked;
+}
+
+int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
+{
+	int ret = 0;
+
+	if (interruptible) {
+		ret = wait_event_interruptible(lock->queue,
+					       __ttm_write_lock(lock));
+		if (unlikely(ret != 0)) {
+			spin_lock(&lock->lock);
+			lock->flags &= ~TTM_WRITE_LOCK_PENDING;
+			wake_up_all(&lock->queue);
+			spin_unlock(&lock->lock);
+		}
+	} else
+		wait_event(lock->queue, __ttm_read_lock(lock));
+
+	return ret;
+}
+EXPORT_SYMBOL(ttm_write_lock);
+
+void ttm_write_lock_downgrade(struct ttm_lock *lock)
+{
+	spin_lock(&lock->lock);
+	lock->rw = 1;
+	wake_up_all(&lock->queue);
+	spin_unlock(&lock->lock);
+}
+
+static int __ttm_vt_unlock(struct ttm_lock *lock)
+{
+	int ret = 0;
+
+	spin_lock(&lock->lock);
+	if (unlikely(!(lock->flags & TTM_VT_LOCK)))
+		ret = -EINVAL;
+	lock->flags &= ~TTM_VT_LOCK;
+	wake_up_all(&lock->queue);
+	spin_unlock(&lock->lock);
+	printk(KERN_INFO TTM_PFX "vt unlock.\n");
+
+	return ret;
+}
+
+static void ttm_vt_lock_remove(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct ttm_lock *lock = container_of(base, struct ttm_lock, base);
+	int ret;
+
+	*p_base = NULL;
+	ret = __ttm_vt_unlock(lock);
+	BUG_ON(ret != 0);
+}
+
+static bool __ttm_vt_lock(struct ttm_lock *lock)
+{
+	bool locked = false;
+
+	spin_lock(&lock->lock);
+	if (lock->rw == 0) {
+		lock->flags &= ~TTM_VT_LOCK_PENDING;
+		lock->flags |= TTM_VT_LOCK;
+		locked = true;
+	} else {
+		lock->flags |= TTM_VT_LOCK_PENDING;
+	}
+	spin_unlock(&lock->lock);
+	return locked;
+}
+
+int ttm_vt_lock(struct ttm_lock *lock,
+		bool interruptible,
+		struct ttm_object_file *tfile)
+{
+	int ret = 0;
+
+	if (interruptible) {
+		ret = wait_event_interruptible(lock->queue,
+					       __ttm_vt_lock(lock));
+		if (unlikely(ret != 0)) {
+			spin_lock(&lock->lock);
+			lock->flags &= ~TTM_VT_LOCK_PENDING;
+			wake_up_all(&lock->queue);
+			spin_unlock(&lock->lock);
+			return ret;
+		}
+	} else
+		wait_event(lock->queue, __ttm_vt_lock(lock));
+
+	/*
+	 * Add a base-object, the destructor of which will
+	 * make sure the lock is released if the client dies
+	 * while holding it.
+	 */
+
+	ret = ttm_base_object_init(tfile, &lock->base, false,
+				   ttm_lock_type, &ttm_vt_lock_remove, NULL);
+	if (ret)
+		(void)__ttm_vt_unlock(lock);
+	else {
+		lock->vt_holder = tfile;
+		printk(KERN_INFO TTM_PFX "vt lock.\n");
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(ttm_vt_lock);
+
+int ttm_vt_unlock(struct ttm_lock *lock)
+{
+	return ttm_ref_object_base_unref(lock->vt_holder,
+					 lock->base.hash.key, TTM_REF_USAGE);
+}
+EXPORT_SYMBOL(ttm_vt_unlock);
+
+void ttm_suspend_unlock(struct ttm_lock *lock)
+{
+	spin_lock(&lock->lock);
+	lock->flags &= ~TTM_SUSPEND_LOCK;
+	wake_up_all(&lock->queue);
+	spin_unlock(&lock->lock);
+}
+EXPORT_SYMBOL(ttm_suspend_unlock);
+
+static bool __ttm_suspend_lock(struct ttm_lock *lock)
+{
+	bool locked = false;
+
+	spin_lock(&lock->lock);
+	if (lock->rw == 0) {
+		lock->flags &= ~TTM_SUSPEND_LOCK_PENDING;
+		lock->flags |= TTM_SUSPEND_LOCK;
+		locked = true;
+	} else {
+		lock->flags |= TTM_SUSPEND_LOCK_PENDING;
+	}
+	spin_unlock(&lock->lock);
+	return locked;
+}
+
+void ttm_suspend_lock(struct ttm_lock *lock)
+{
+	wait_event(lock->queue, __ttm_suspend_lock(lock));
+}
+EXPORT_SYMBOL(ttm_suspend_lock);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/Makefile
@@ -3,6 +3,7 @@
 
 ccflags-y := -Iinclude/drm
 ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \
-	ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o
+	ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o \
+	ttm_object.o ttm_lock.o ttm_execbuf_util.o
 
 obj-$(CONFIG_DRM_TTM) += ttm.o
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -114,7 +114,7 @@
 		ret = ttm_bo_wait(bo, false, true, false);
 		spin_unlock(&bo->lock);
 		if (unlikely(ret != 0)) {
-			retval = (ret != -ERESTART) ?
+			retval = (ret != -ERESTARTSYS) ?
 			    VM_FAULT_SIGBUS : VM_FAULT_NOPAGE;
 			goto out_unlock;
 		}
@@ -320,7 +320,7 @@
 		return -EFAULT;
 
 	driver = bo->bdev->driver;
-	if (unlikely(driver->verify_access)) {
+	if (unlikely(!driver->verify_access)) {
 		ret = -EPERM;
 		goto out_unref;
 	}
@@ -349,9 +349,6 @@
 	switch (ret) {
 	case 0:
 		break;
-	case -ERESTART:
-		ret = -EINTR;
-		goto out_unref;
 	case -EBUSY:
 		ret = -EAGAIN;
 		goto out_unref;
@@ -421,8 +418,6 @@
 	switch (ret) {
 	case 0:
 		break;
-	case -ERESTART:
-		return -EINTR;
 	case -EBUSY:
 		return -EAGAIN;
 	default:
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_memory.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_memory.c
@@ -274,16 +274,17 @@
 static int ttm_mem_init_highmem_zone(struct ttm_mem_global *glob,
 				     const struct sysinfo *si)
 {
-	struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL);
+	struct ttm_mem_zone *zone;
 	uint64_t mem;
 	int ret;
 
-	if (unlikely(!zone))
-		return -ENOMEM;
-
 	if (si->totalhigh == 0)
 		return 0;
 
+	zone = kzalloc(sizeof(*zone), GFP_KERNEL);
+	if (unlikely(!zone))
+		return -ENOMEM;
+
 	mem = si->totalram;
 	mem *= si->mem_unit;
 
@@ -322,8 +323,10 @@
 	 * No special dma32 zone needed.
 	 */
 
-	if (mem <= ((uint64_t) 1ULL << 32))
+	if (mem <= ((uint64_t) 1ULL << 32)) {
+		kfree(zone);
 		return 0;
+	}
 
 	/*
 	 * Limit max dma32 memory to 4GB for now
@@ -460,6 +463,7 @@
 {
 	return ttm_mem_global_free_zone(glob, NULL, amount);
 }
+EXPORT_SYMBOL(ttm_mem_global_free);
 
 static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 				  struct ttm_mem_zone *single_zone,
@@ -533,6 +537,7 @@
 	return ttm_mem_global_alloc_zone(glob, NULL, memory, no_wait,
 					 interruptible);
 }
+EXPORT_SYMBOL(ttm_mem_global_alloc);
 
 int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
 			      struct page *page,
@@ -588,3 +593,4 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(ttm_round_pot);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_bo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_bo.c
@@ -27,6 +27,14 @@
 /*
  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  */
+/* Notes:
+ *
+ * We store bo pointer in drm_mm_node struct so we know which bo own a
+ * specific node. There is no protection on the pointer, thus to make
+ * sure things don't go berserk you have to access this pointer while
+ * holding the global lru lock and make sure anytime you free a node you
+ * reset the pointer to NULL.
+ */
 
 #include "ttm/ttm_module.h"
 #include "ttm/ttm_bo_driver.h"
@@ -51,6 +59,59 @@
 	.mode = S_IRUGO
 };
 
+static inline int ttm_mem_type_from_flags(uint32_t flags, uint32_t *mem_type)
+{
+	int i;
+
+	for (i = 0; i <= TTM_PL_PRIV5; i++)
+		if (flags & (1 << i)) {
+			*mem_type = i;
+			return 0;
+		}
+	return -EINVAL;
+}
+
+static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+
+	printk(KERN_ERR TTM_PFX "    has_type: %d\n", man->has_type);
+	printk(KERN_ERR TTM_PFX "    use_type: %d\n", man->use_type);
+	printk(KERN_ERR TTM_PFX "    flags: 0x%08X\n", man->flags);
+	printk(KERN_ERR TTM_PFX "    gpu_offset: 0x%08lX\n", man->gpu_offset);
+	printk(KERN_ERR TTM_PFX "    io_offset: 0x%08lX\n", man->io_offset);
+	printk(KERN_ERR TTM_PFX "    io_size: %ld\n", man->io_size);
+	printk(KERN_ERR TTM_PFX "    size: %llu\n", man->size);
+	printk(KERN_ERR TTM_PFX "    available_caching: 0x%08X\n",
+		man->available_caching);
+	printk(KERN_ERR TTM_PFX "    default_caching: 0x%08X\n",
+		man->default_caching);
+	if (mem_type != TTM_PL_SYSTEM) {
+		spin_lock(&bdev->glob->lru_lock);
+		drm_mm_debug_table(&man->manager, TTM_PFX);
+		spin_unlock(&bdev->glob->lru_lock);
+	}
+}
+
+static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo,
+					struct ttm_placement *placement)
+{
+	int i, ret, mem_type;
+
+	printk(KERN_ERR TTM_PFX "No space for %p (%lu pages, %luK, %luM)\n",
+		bo, bo->mem.num_pages, bo->mem.size >> 10,
+		bo->mem.size >> 20);
+	for (i = 0; i < placement->num_placement; i++) {
+		ret = ttm_mem_type_from_flags(placement->placement[i],
+						&mem_type);
+		if (ret)
+			return;
+		printk(KERN_ERR TTM_PFX "  placement[%d]=0x%08X (%d)\n",
+			i, placement->placement[i], mem_type);
+		ttm_mem_type_debug(bo->bdev, mem_type);
+	}
+}
+
 static ssize_t ttm_bo_global_show(struct kobject *kobj,
 				  struct attribute *attr,
 				  char *buffer)
@@ -117,12 +178,13 @@
 		ret = wait_event_interruptible(bo->event_queue,
 					       atomic_read(&bo->reserved) == 0);
 		if (unlikely(ret != 0))
-			return -ERESTART;
+			return ret;
 	} else {
 		wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0);
 	}
 	return 0;
 }
+EXPORT_SYMBOL(ttm_bo_wait_unreserved);
 
 static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
 {
@@ -247,7 +309,6 @@
 /*
  * Call bo->mutex locked.
  */
-
 static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
@@ -275,9 +336,10 @@
 		bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
 					page_flags | TTM_PAGE_FLAG_USER,
 					glob->dummy_read_page);
-		if (unlikely(bo->ttm == NULL))
+		if (unlikely(bo->ttm == NULL)) {
 			ret = -ENOMEM;
-		break;
+			break;
+		}
 
 		ret = ttm_tt_set_user(bo->ttm, current,
 				      bo->buffer_start, bo->num_pages);
@@ -328,14 +390,8 @@
 		}
 
 		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
-
-			struct ttm_mem_reg *old_mem = &bo->mem;
-			uint32_t save_flags = old_mem->placement;
-
-			*old_mem = *mem;
+			bo->mem = *mem;
 			mem->mm_node = NULL;
-			ttm_flag_masked(&save_flags, mem->placement,
-					TTM_PL_MASK_MEMTYPE);
 			goto moved;
 		}
 
@@ -370,7 +426,8 @@
 		    bdev->man[bo->mem.mem_type].gpu_offset;
 		bo->cur_placement = bo->mem.placement;
 		spin_unlock(&bo->lock);
-	}
+	} else
+		bo->offset = 0;
 
 	return 0;
 
@@ -386,6 +443,43 @@
 }
 
 /**
+ * Call bo::reserved and with the lru lock held.
+ * Will release GPU memory type usage on destruction.
+ * This is the place to put in driver specific hooks.
+ * Will release the bo::reserved lock and the
+ * lru lock on exit.
+ */
+
+static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_global *glob = bo->glob;
+
+	if (bo->ttm) {
+
+		/**
+		 * Release the lru_lock, since we don't want to have
+		 * an atomic requirement on ttm_tt[unbind|destroy].
+		 */
+
+		spin_unlock(&glob->lru_lock);
+		ttm_tt_unbind(bo->ttm);
+		ttm_tt_destroy(bo->ttm);
+		bo->ttm = NULL;
+		spin_lock(&glob->lru_lock);
+	}
+
+	if (bo->mem.mm_node) {
+		drm_mm_put_block(bo->mem.mm_node);
+		bo->mem.mm_node = NULL;
+	}
+
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+	spin_unlock(&glob->lru_lock);
+}
+
+
+/**
  * If bo idle, remove from delayed- and lru lists, and unref.
  * If not idle, and already on delayed list, do nothing.
  * If not idle, and not on delayed list, put on delayed list,
@@ -400,6 +494,7 @@
 	int ret;
 
 	spin_lock(&bo->lock);
+retry:
 	(void) ttm_bo_wait(bo, false, false, !remove_all);
 
 	if (!bo->sync_obj) {
@@ -408,30 +503,52 @@
 		spin_unlock(&bo->lock);
 
 		spin_lock(&glob->lru_lock);
-		ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
-		BUG_ON(ret);
-		if (bo->ttm)
-			ttm_tt_unbind(bo->ttm);
+		ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
 
-		if (!list_empty(&bo->ddestroy)) {
-			list_del_init(&bo->ddestroy);
-			kref_put(&bo->list_kref, ttm_bo_ref_bug);
+		/**
+		 * Someone else has the object reserved. Bail and retry.
+		 */
+
+		if (unlikely(ret == -EBUSY)) {
+			spin_unlock(&glob->lru_lock);
+			spin_lock(&bo->lock);
+			goto requeue;
 		}
-		if (bo->mem.mm_node) {
-			drm_mm_put_block(bo->mem.mm_node);
-			bo->mem.mm_node = NULL;
+
+		/**
+		 * We can re-check for sync object without taking
+		 * the bo::lock since setting the sync object requires
+		 * also bo::reserved. A busy object at this point may
+		 * be caused by another thread starting an accelerated
+		 * eviction.
+		 */
+
+		if (unlikely(bo->sync_obj)) {
+			atomic_set(&bo->reserved, 0);
+			wake_up_all(&bo->event_queue);
+			spin_unlock(&glob->lru_lock);
+			spin_lock(&bo->lock);
+			if (remove_all)
+				goto retry;
+			else
+				goto requeue;
 		}
+
 		put_count = ttm_bo_del_from_lru(bo);
-		spin_unlock(&glob->lru_lock);
 
-		atomic_set(&bo->reserved, 0);
+		if (!list_empty(&bo->ddestroy)) {
+			list_del_init(&bo->ddestroy);
+			++put_count;
+		}
+
+		ttm_bo_cleanup_memtype_use(bo);
 
 		while (put_count--)
-			kref_put(&bo->list_kref, ttm_bo_release_list);
+			kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
 		return 0;
 	}
-
+requeue:
 	spin_lock(&glob->lru_lock);
 	if (list_empty(&bo->ddestroy)) {
 		void *sync_obj = bo->sync_obj;
@@ -465,52 +582,44 @@
 static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
 {
 	struct ttm_bo_global *glob = bdev->glob;
-	struct ttm_buffer_object *entry, *nentry;
-	struct list_head *list, *next;
-	int ret;
+	struct ttm_buffer_object *entry = NULL;
+	int ret = 0;
 
 	spin_lock(&glob->lru_lock);
-	list_for_each_safe(list, next, &bdev->ddestroy) {
-		entry = list_entry(list, struct ttm_buffer_object, ddestroy);
-		nentry = NULL;
-
-		/*
-		 * Protect the next list entry from destruction while we
-		 * unlock the lru_lock.
-		 */
+	if (list_empty(&bdev->ddestroy))
+		goto out_unlock;
 
-		if (next != &bdev->ddestroy) {
-			nentry = list_entry(next, struct ttm_buffer_object,
-					    ddestroy);
+	entry = list_first_entry(&bdev->ddestroy,
+		struct ttm_buffer_object, ddestroy);
+	kref_get(&entry->list_kref);
+
+	for (;;) {
+		struct ttm_buffer_object *nentry = NULL;
+
+		if (entry->ddestroy.next != &bdev->ddestroy) {
+			nentry = list_first_entry(&entry->ddestroy,
+				struct ttm_buffer_object, ddestroy);
 			kref_get(&nentry->list_kref);
 		}
-		kref_get(&entry->list_kref);
 
 		spin_unlock(&glob->lru_lock);
 		ret = ttm_bo_cleanup_refs(entry, remove_all);
 		kref_put(&entry->list_kref, ttm_bo_release_list);
+		entry = nentry;
 
-		spin_lock(&glob->lru_lock);
-		if (nentry) {
-			bool next_onlist = !list_empty(next);
-			spin_unlock(&glob->lru_lock);
-			kref_put(&nentry->list_kref, ttm_bo_release_list);
-			spin_lock(&glob->lru_lock);
-			/*
-			 * Someone might have raced us and removed the
-			 * next entry from the list. We don't bother restarting
-			 * list traversal.
-			 */
+		if (ret || !entry)
+			goto out;
 
-			if (!next_onlist)
-				break;
-		}
-		if (ret)
+		spin_lock(&glob->lru_lock);
+		if (list_empty(&entry->ddestroy))
 			break;
 	}
-	ret = !list_empty(&bdev->ddestroy);
-	spin_unlock(&glob->lru_lock);
 
+out_unlock:
+	spin_unlock(&glob->lru_lock);
+out:
+	if (entry)
+		kref_put(&entry->list_kref, ttm_bo_release_list);
 	return ret;
 }
 
@@ -554,24 +663,21 @@
 }
 EXPORT_SYMBOL(ttm_bo_unref);
 
-static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type,
-			bool interruptible, bool no_wait)
+static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
+			bool no_wait)
 {
-	int ret = 0;
 	struct ttm_bo_device *bdev = bo->bdev;
 	struct ttm_bo_global *glob = bo->glob;
 	struct ttm_mem_reg evict_mem;
-	uint32_t proposed_placement;
-
-	if (bo->mem.mem_type != mem_type)
-		goto out;
+	struct ttm_placement placement;
+	int ret = 0;
 
 	spin_lock(&bo->lock);
 	ret = ttm_bo_wait(bo, false, interruptible, no_wait);
 	spin_unlock(&bo->lock);
 
 	if (unlikely(ret != 0)) {
-		if (ret != -ERESTART) {
+		if (ret != -ERESTARTSYS) {
 			printk(KERN_ERR TTM_PFX
 			       "Failed to expire sync object before "
 			       "buffer eviction.\n");
@@ -584,116 +690,165 @@
 	evict_mem = bo->mem;
 	evict_mem.mm_node = NULL;
 
-	proposed_placement = bdev->driver->evict_flags(bo);
-
-	ret = ttm_bo_mem_space(bo, proposed_placement,
-			       &evict_mem, interruptible, no_wait);
-	if (unlikely(ret != 0 && ret != -ERESTART))
-		ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM,
-				       &evict_mem, interruptible, no_wait);
-
+	placement.fpfn = 0;
+	placement.lpfn = 0;
+	placement.num_placement = 0;
+	placement.num_busy_placement = 0;
+	bdev->driver->evict_flags(bo, &placement);
+	ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible,
+				no_wait);
 	if (ret) {
-		if (ret != -ERESTART)
+		if (ret != -ERESTARTSYS) {
 			printk(KERN_ERR TTM_PFX
 			       "Failed to find memory space for "
 			       "buffer 0x%p eviction.\n", bo);
+			ttm_bo_mem_space_debug(bo, &placement);
+		}
 		goto out;
 	}
 
 	ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible,
 				     no_wait);
 	if (ret) {
-		if (ret != -ERESTART)
+		if (ret != -ERESTARTSYS)
 			printk(KERN_ERR TTM_PFX "Buffer eviction failed\n");
+		spin_lock(&glob->lru_lock);
+		if (evict_mem.mm_node) {
+			evict_mem.mm_node->private = NULL;
+			drm_mm_put_block(evict_mem.mm_node);
+			evict_mem.mm_node = NULL;
+		}
+		spin_unlock(&glob->lru_lock);
 		goto out;
 	}
-
-	spin_lock(&glob->lru_lock);
-	if (evict_mem.mm_node) {
-		drm_mm_put_block(evict_mem.mm_node);
-		evict_mem.mm_node = NULL;
-	}
-	spin_unlock(&glob->lru_lock);
 	bo->evicted = true;
 out:
 	return ret;
 }
 
-/**
- * Repeatedly evict memory from the LRU for @mem_type until we create enough
- * space, or we've evicted everything and there isn't enough space.
- */
-static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev,
-				  struct ttm_mem_reg *mem,
-				  uint32_t mem_type,
-				  bool interruptible, bool no_wait)
+static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
+				uint32_t mem_type,
+				bool interruptible, bool no_wait)
 {
 	struct ttm_bo_global *glob = bdev->glob;
-	struct drm_mm_node *node;
-	struct ttm_buffer_object *entry;
 	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
-	struct list_head *lru;
-	unsigned long num_pages = mem->num_pages;
-	int put_count = 0;
-	int ret;
-
-retry_pre_get:
-	ret = drm_mm_pre_get(&man->manager);
-	if (unlikely(ret != 0))
-		return ret;
+	struct ttm_buffer_object *bo;
+	int ret, put_count = 0;
 
+retry:
 	spin_lock(&glob->lru_lock);
-	do {
-		node = drm_mm_search_free(&man->manager, num_pages,
-					  mem->page_alignment, 1);
-		if (node)
-			break;
+	if (list_empty(&man->lru)) {
+		spin_unlock(&glob->lru_lock);
+		return -EBUSY;
+	}
 
-		lru = &man->lru;
-		if (list_empty(lru))
-			break;
+	bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru);
+	kref_get(&bo->list_kref);
 
-		entry = list_first_entry(lru, struct ttm_buffer_object, lru);
-		kref_get(&entry->list_kref);
+	ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
-		ret =
-		    ttm_bo_reserve_locked(entry, interruptible, no_wait,
-					  false, 0);
+	if (unlikely(ret == -EBUSY)) {
+		spin_unlock(&glob->lru_lock);
+		if (likely(!no_wait))
+			ret = ttm_bo_wait_unreserved(bo, interruptible);
 
-		if (likely(ret == 0))
-			put_count = ttm_bo_del_from_lru(entry);
+		kref_put(&bo->list_kref, ttm_bo_release_list);
 
-		spin_unlock(&glob->lru_lock);
+		/**
+		 * We *need* to retry after releasing the lru lock.
+		 */
 
 		if (unlikely(ret != 0))
 			return ret;
+		goto retry;
+	}
 
-		while (put_count--)
-			kref_put(&entry->list_kref, ttm_bo_ref_bug);
+	put_count = ttm_bo_del_from_lru(bo);
+	spin_unlock(&glob->lru_lock);
 
-		ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait);
+	BUG_ON(ret != 0);
 
-		ttm_bo_unreserve(entry);
+	while (put_count--)
+		kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
-		kref_put(&entry->list_kref, ttm_bo_release_list);
-		if (ret)
+	ret = ttm_bo_evict(bo, interruptible, no_wait);
+	ttm_bo_unreserve(bo);
+
+	kref_put(&bo->list_kref, ttm_bo_release_list);
+	return ret;
+}
+
+static int ttm_bo_man_get_node(struct ttm_buffer_object *bo,
+				struct ttm_mem_type_manager *man,
+				struct ttm_placement *placement,
+				struct ttm_mem_reg *mem,
+				struct drm_mm_node **node)
+{
+	struct ttm_bo_global *glob = bo->glob;
+	unsigned long lpfn;
+	int ret;
+
+	lpfn = placement->lpfn;
+	if (!lpfn)
+		lpfn = man->size;
+	*node = NULL;
+	do {
+		ret = drm_mm_pre_get(&man->manager);
+		if (unlikely(ret))
 			return ret;
 
 		spin_lock(&glob->lru_lock);
-	} while (1);
-
-	if (!node) {
+		*node = drm_mm_search_free_in_range(&man->manager,
+					mem->num_pages, mem->page_alignment,
+					placement->fpfn, lpfn, 1);
+		if (unlikely(*node == NULL)) {
+			spin_unlock(&glob->lru_lock);
+			return 0;
+		}
+		*node = drm_mm_get_block_atomic_range(*node, mem->num_pages,
+							mem->page_alignment,
+							placement->fpfn,
+							lpfn);
 		spin_unlock(&glob->lru_lock);
-		return -ENOMEM;
-	}
+	} while (*node == NULL);
+	return 0;
+}
 
-	node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment);
-	if (unlikely(!node)) {
-		spin_unlock(&glob->lru_lock);
-		goto retry_pre_get;
-	}
+/**
+ * Repeatedly evict memory from the LRU for @mem_type until we create enough
+ * space, or we've evicted everything and there isn't enough space.
+ */
+static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
+					uint32_t mem_type,
+					struct ttm_placement *placement,
+					struct ttm_mem_reg *mem,
+					bool interruptible, bool no_wait)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_bo_global *glob = bdev->glob;
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+	struct drm_mm_node *node;
+	int ret;
 
-	spin_unlock(&glob->lru_lock);
+	do {
+		ret = ttm_bo_man_get_node(bo, man, placement, mem, &node);
+		if (unlikely(ret != 0))
+			return ret;
+		if (node)
+			break;
+		spin_lock(&glob->lru_lock);
+		if (list_empty(&man->lru)) {
+			spin_unlock(&glob->lru_lock);
+			break;
+		}
+		spin_unlock(&glob->lru_lock);
+		ret = ttm_mem_evict_first(bdev, mem_type, interruptible,
+						no_wait);
+		if (unlikely(ret != 0))
+			return ret;
+	} while (1);
+	if (node == NULL)
+		return -ENOMEM;
 	mem->mm_node = node;
 	mem->mem_type = mem_type;
 	return 0;
@@ -724,7 +879,6 @@
 	return result;
 }
 
-
 static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
 				 bool disallow_fixed,
 				 uint32_t mem_type,
@@ -757,66 +911,55 @@
  * space.
  */
 int ttm_bo_mem_space(struct ttm_buffer_object *bo,
-		     uint32_t proposed_placement,
-		     struct ttm_mem_reg *mem,
-		     bool interruptible, bool no_wait)
+			struct ttm_placement *placement,
+			struct ttm_mem_reg *mem,
+			bool interruptible, bool no_wait)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
-	struct ttm_bo_global *glob = bo->glob;
 	struct ttm_mem_type_manager *man;
-
-	uint32_t num_prios = bdev->driver->num_mem_type_prio;
-	const uint32_t *prios = bdev->driver->mem_type_prio;
-	uint32_t i;
 	uint32_t mem_type = TTM_PL_SYSTEM;
 	uint32_t cur_flags = 0;
 	bool type_found = false;
 	bool type_ok = false;
-	bool has_eagain = false;
+	bool has_erestartsys = false;
 	struct drm_mm_node *node = NULL;
-	int ret;
+	int i, ret;
 
 	mem->mm_node = NULL;
-	for (i = 0; i < num_prios; ++i) {
-		mem_type = prios[i];
+	for (i = 0; i < placement->num_placement; ++i) {
+		ret = ttm_mem_type_from_flags(placement->placement[i],
+						&mem_type);
+		if (ret)
+			return ret;
 		man = &bdev->man[mem_type];
 
 		type_ok = ttm_bo_mt_compatible(man,
-					       bo->type == ttm_bo_type_user,
-					       mem_type, proposed_placement,
-					       &cur_flags);
+						bo->type == ttm_bo_type_user,
+						mem_type,
+						placement->placement[i],
+						&cur_flags);
 
 		if (!type_ok)
 			continue;
 
 		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
 						  cur_flags);
+		/*
+		 * Use the access and other non-mapping-related flag bits from
+		 * the memory placement flags to the current flags
+		 */
+		ttm_flag_masked(&cur_flags, placement->placement[i],
+				~TTM_PL_MASK_MEMTYPE);
 
 		if (mem_type == TTM_PL_SYSTEM)
 			break;
 
 		if (man->has_type && man->use_type) {
 			type_found = true;
-			do {
-				ret = drm_mm_pre_get(&man->manager);
-				if (unlikely(ret))
-					return ret;
-
-				spin_lock(&glob->lru_lock);
-				node = drm_mm_search_free(&man->manager,
-							  mem->num_pages,
-							  mem->page_alignment,
-							  1);
-				if (unlikely(!node)) {
-					spin_unlock(&glob->lru_lock);
-					break;
-				}
-				node = drm_mm_get_block_atomic(node,
-							       mem->num_pages,
-							       mem->
-							       page_alignment);
-				spin_unlock(&glob->lru_lock);
-			} while (!node);
+			ret = ttm_bo_man_get_node(bo, man, placement, mem,
+							&node);
+			if (unlikely(ret))
+				return ret;
 		}
 		if (node)
 			break;
@@ -826,67 +969,74 @@
 		mem->mm_node = node;
 		mem->mem_type = mem_type;
 		mem->placement = cur_flags;
+		if (node)
+			node->private = bo;
 		return 0;
 	}
 
 	if (!type_found)
 		return -EINVAL;
 
-	num_prios = bdev->driver->num_mem_busy_prio;
-	prios = bdev->driver->mem_busy_prio;
-
-	for (i = 0; i < num_prios; ++i) {
-		mem_type = prios[i];
+	for (i = 0; i < placement->num_busy_placement; ++i) {
+		ret = ttm_mem_type_from_flags(placement->busy_placement[i],
+						&mem_type);
+		if (ret)
+			return ret;
 		man = &bdev->man[mem_type];
-
 		if (!man->has_type)
 			continue;
-
 		if (!ttm_bo_mt_compatible(man,
-					  bo->type == ttm_bo_type_user,
-					  mem_type,
-					  proposed_placement, &cur_flags))
+						bo->type == ttm_bo_type_user,
+						mem_type,
+						placement->busy_placement[i],
+						&cur_flags))
 			continue;
 
 		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
 						  cur_flags);
+		/*
+		 * Use the access and other non-mapping-related flag bits from
+		 * the memory placement flags to the current flags
+		 */
+		ttm_flag_masked(&cur_flags, placement->busy_placement[i],
+				~TTM_PL_MASK_MEMTYPE);
 
-		ret = ttm_bo_mem_force_space(bdev, mem, mem_type,
-					     interruptible, no_wait);
 
-		if (ret == 0 && mem->mm_node) {
+		if (mem_type == TTM_PL_SYSTEM) {
+			mem->mem_type = mem_type;
 			mem->placement = cur_flags;
+			mem->mm_node = NULL;
 			return 0;
 		}
 
-		if (ret == -ERESTART)
-			has_eagain = true;
+		ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
+						interruptible, no_wait);
+		if (ret == 0 && mem->mm_node) {
+			mem->placement = cur_flags;
+			mem->mm_node->private = bo;
+			return 0;
+		}
+		if (ret == -ERESTARTSYS)
+			has_erestartsys = true;
 	}
-
-	ret = (has_eagain) ? -ERESTART : -ENOMEM;
+	ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM;
 	return ret;
 }
 EXPORT_SYMBOL(ttm_bo_mem_space);
 
 int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait)
 {
-	int ret = 0;
-
 	if ((atomic_read(&bo->cpu_writers) > 0) && no_wait)
 		return -EBUSY;
 
-	ret = wait_event_interruptible(bo->event_queue,
-				       atomic_read(&bo->cpu_writers) == 0);
-
-	if (ret == -ERESTARTSYS)
-		ret = -ERESTART;
-
-	return ret;
+	return wait_event_interruptible(bo->event_queue,
+					atomic_read(&bo->cpu_writers) == 0);
 }
+EXPORT_SYMBOL(ttm_bo_wait_cpu);
 
 int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
-		       uint32_t proposed_placement,
-		       bool interruptible, bool no_wait)
+			struct ttm_placement *placement,
+			bool interruptible, bool no_wait)
 {
 	struct ttm_bo_global *glob = bo->glob;
 	int ret = 0;
@@ -899,147 +1049,138 @@
 	 * Have the driver move function wait for idle when necessary,
 	 * instead of doing it here.
 	 */
-
 	spin_lock(&bo->lock);
 	ret = ttm_bo_wait(bo, false, interruptible, no_wait);
 	spin_unlock(&bo->lock);
-
 	if (ret)
 		return ret;
-
 	mem.num_pages = bo->num_pages;
 	mem.size = mem.num_pages << PAGE_SHIFT;
 	mem.page_alignment = bo->mem.page_alignment;
-
 	/*
 	 * Determine where to move the buffer.
 	 */
-
-	ret = ttm_bo_mem_space(bo, proposed_placement, &mem,
-			       interruptible, no_wait);
+	ret = ttm_bo_mem_space(bo, placement, &mem, interruptible, no_wait);
 	if (ret)
 		goto out_unlock;
-
 	ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait);
-
 out_unlock:
 	if (ret && mem.mm_node) {
 		spin_lock(&glob->lru_lock);
+		mem.mm_node->private = NULL;
 		drm_mm_put_block(mem.mm_node);
 		spin_unlock(&glob->lru_lock);
 	}
 	return ret;
 }
 
-static int ttm_bo_mem_compat(uint32_t proposed_placement,
+static int ttm_bo_mem_compat(struct ttm_placement *placement,
 			     struct ttm_mem_reg *mem)
 {
-	if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0)
-		return 0;
-	if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0)
-		return 0;
+	int i;
+	struct drm_mm_node *node = mem->mm_node;
 
-	return 1;
+	if (node && placement->lpfn != 0 &&
+	    (node->start < placement->fpfn ||
+	     node->start + node->size > placement->lpfn))
+		return -1;
+
+	for (i = 0; i < placement->num_placement; i++) {
+		if ((placement->placement[i] & mem->placement &
+			TTM_PL_MASK_CACHING) &&
+			(placement->placement[i] & mem->placement &
+			TTM_PL_MASK_MEM))
+			return i;
+	}
+	return -1;
 }
 
-int ttm_buffer_object_validate(struct ttm_buffer_object *bo,
-			       uint32_t proposed_placement,
-			       bool interruptible, bool no_wait)
+int ttm_bo_validate(struct ttm_buffer_object *bo,
+			struct ttm_placement *placement,
+			bool interruptible, bool no_wait)
 {
 	int ret;
 
 	BUG_ON(!atomic_read(&bo->reserved));
-	bo->proposed_placement = proposed_placement;
-
-	TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n",
-		  (unsigned long)proposed_placement,
-		  (unsigned long)bo->mem.placement);
-
+	/* Check that range is valid */
+	if (placement->lpfn || placement->fpfn)
+		if (placement->fpfn > placement->lpfn ||
+			(placement->lpfn - placement->fpfn) < bo->num_pages)
+			return -EINVAL;
 	/*
 	 * Check whether we need to move buffer.
 	 */
-
-	if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) {
-		ret = ttm_bo_move_buffer(bo, bo->proposed_placement,
-					 interruptible, no_wait);
-		if (ret) {
-			if (ret != -ERESTART)
-				printk(KERN_ERR TTM_PFX
-				       "Failed moving buffer. "
-				       "Proposed placement 0x%08x\n",
-				       bo->proposed_placement);
-			if (ret == -ENOMEM)
-				printk(KERN_ERR TTM_PFX
-				       "Out of aperture space or "
-				       "DRM memory quota.\n");
+	ret = ttm_bo_mem_compat(placement, &bo->mem);
+	if (ret < 0) {
+		ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait);
+		if (ret)
 			return ret;
-		}
+	} else {
+		/*
+		 * Use the access and other non-mapping-related flag bits from
+		 * the compatible memory placement flags to the active flags
+		 */
+		ttm_flag_masked(&bo->mem.placement, placement->placement[ret],
+				~TTM_PL_MASK_MEMTYPE);
 	}
-
 	/*
 	 * We might need to add a TTM.
 	 */
-
 	if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
 		ret = ttm_bo_add_ttm(bo, true);
 		if (ret)
 			return ret;
 	}
-	/*
-	 * Validation has succeeded, move the access and other
-	 * non-mapping-related flag bits from the proposed flags to
-	 * the active flags
-	 */
-
-	ttm_flag_masked(&bo->mem.placement, bo->proposed_placement,
-			~TTM_PL_MASK_MEMTYPE);
-
 	return 0;
 }
-EXPORT_SYMBOL(ttm_buffer_object_validate);
+EXPORT_SYMBOL(ttm_bo_validate);
 
-int
-ttm_bo_check_placement(struct ttm_buffer_object *bo,
-		       uint32_t set_flags, uint32_t clr_flags)
+int ttm_bo_check_placement(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement)
 {
-	uint32_t new_mask = set_flags | clr_flags;
-
-	if ((bo->type == ttm_bo_type_user) &&
-	    (clr_flags & TTM_PL_FLAG_CACHED)) {
-		printk(KERN_ERR TTM_PFX
-		       "User buffers require cache-coherent memory.\n");
-		return -EINVAL;
-	}
+	int i;
 
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (new_mask & TTM_PL_FLAG_NO_EVICT) {
-			printk(KERN_ERR TTM_PFX "Need to be root to modify"
-			       " NO_EVICT status.\n");
+	if (placement->fpfn || placement->lpfn) {
+		if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) {
+			printk(KERN_ERR TTM_PFX "Page number range to small "
+				"Need %lu pages, range is [%u, %u]\n",
+				bo->mem.num_pages, placement->fpfn,
+				placement->lpfn);
 			return -EINVAL;
 		}
-
-		if ((clr_flags & bo->mem.placement & TTM_PL_MASK_MEMTYPE) &&
-		    (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
-			printk(KERN_ERR TTM_PFX
-			       "Incompatible memory specification"
-			       " for NO_EVICT buffer.\n");
-			return -EINVAL;
+	}
+	for (i = 0; i < placement->num_placement; i++) {
+		if (!capable(CAP_SYS_ADMIN)) {
+			if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) {
+				printk(KERN_ERR TTM_PFX "Need to be root to "
+					"modify NO_EVICT status.\n");
+				return -EINVAL;
+			}
+		}
+	}
+	for (i = 0; i < placement->num_busy_placement; i++) {
+		if (!capable(CAP_SYS_ADMIN)) {
+			if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) {
+				printk(KERN_ERR TTM_PFX "Need to be root to "
+					"modify NO_EVICT status.\n");
+				return -EINVAL;
+			}
 		}
 	}
 	return 0;
 }
 
-int ttm_buffer_object_init(struct ttm_bo_device *bdev,
-			   struct ttm_buffer_object *bo,
-			   unsigned long size,
-			   enum ttm_bo_type type,
-			   uint32_t flags,
-			   uint32_t page_alignment,
-			   unsigned long buffer_start,
-			   bool interruptible,
-			   struct file *persistant_swap_storage,
-			   size_t acc_size,
-			   void (*destroy) (struct ttm_buffer_object *))
+int ttm_bo_init(struct ttm_bo_device *bdev,
+		struct ttm_buffer_object *bo,
+		unsigned long size,
+		enum ttm_bo_type type,
+		struct ttm_placement *placement,
+		uint32_t page_alignment,
+		unsigned long buffer_start,
+		bool interruptible,
+		struct file *persistant_swap_storage,
+		size_t acc_size,
+		void (*destroy) (struct ttm_buffer_object *))
 {
 	int ret = 0;
 	unsigned long num_pages;
@@ -1065,6 +1206,7 @@
 	bo->glob = bdev->glob;
 	bo->type = type;
 	bo->num_pages = num_pages;
+	bo->mem.size = num_pages << PAGE_SHIFT;
 	bo->mem.mem_type = TTM_PL_SYSTEM;
 	bo->mem.num_pages = bo->num_pages;
 	bo->mem.mm_node = NULL;
@@ -1077,29 +1219,21 @@
 	bo->acc_size = acc_size;
 	atomic_inc(&bo->glob->bo_count);
 
-	ret = ttm_bo_check_placement(bo, flags, 0ULL);
+	ret = ttm_bo_check_placement(bo, placement);
 	if (unlikely(ret != 0))
 		goto out_err;
 
 	/*
-	 * If no caching attributes are set, accept any form of caching.
-	 */
-
-	if ((flags & TTM_PL_MASK_CACHING) == 0)
-		flags |= TTM_PL_MASK_CACHING;
-
-	/*
 	 * For ttm_bo_type_device buffers, allocate
 	 * address space from the device.
 	 */
-
 	if (bo->type == ttm_bo_type_device) {
 		ret = ttm_bo_setup_vm(bo);
 		if (ret)
 			goto out_err;
 	}
 
-	ret = ttm_buffer_object_validate(bo, flags, interruptible, false);
+	ret = ttm_bo_validate(bo, placement, interruptible, false);
 	if (ret)
 		goto out_err;
 
@@ -1112,7 +1246,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(ttm_buffer_object_init);
+EXPORT_SYMBOL(ttm_bo_init);
 
 static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
 				 unsigned long num_pages)
@@ -1123,19 +1257,19 @@
 	return glob->ttm_bo_size + 2 * page_array_size;
 }
 
-int ttm_buffer_object_create(struct ttm_bo_device *bdev,
-			     unsigned long size,
-			     enum ttm_bo_type type,
-			     uint32_t flags,
-			     uint32_t page_alignment,
-			     unsigned long buffer_start,
-			     bool interruptible,
-			     struct file *persistant_swap_storage,
-			     struct ttm_buffer_object **p_bo)
+int ttm_bo_create(struct ttm_bo_device *bdev,
+			unsigned long size,
+			enum ttm_bo_type type,
+			struct ttm_placement *placement,
+			uint32_t page_alignment,
+			unsigned long buffer_start,
+			bool interruptible,
+			struct file *persistant_swap_storage,
+			struct ttm_buffer_object **p_bo)
 {
 	struct ttm_buffer_object *bo;
-	int ret;
 	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	int ret;
 
 	size_t acc_size =
 	    ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
@@ -1150,76 +1284,41 @@
 		return -ENOMEM;
 	}
 
-	ret = ttm_buffer_object_init(bdev, bo, size, type, flags,
-				     page_alignment, buffer_start,
-				     interruptible,
-				     persistant_swap_storage, acc_size, NULL);
+	ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
+				buffer_start, interruptible,
+				persistant_swap_storage, acc_size, NULL);
 	if (likely(ret == 0))
 		*p_bo = bo;
 
 	return ret;
 }
 
-static int ttm_bo_leave_list(struct ttm_buffer_object *bo,
-			     uint32_t mem_type, bool allow_errors)
-{
-	int ret;
-
-	spin_lock(&bo->lock);
-	ret = ttm_bo_wait(bo, false, false, false);
-	spin_unlock(&bo->lock);
-
-	if (ret && allow_errors)
-		goto out;
-
-	if (bo->mem.mem_type == mem_type)
-		ret = ttm_bo_evict(bo, mem_type, false, false);
-
-	if (ret) {
-		if (allow_errors) {
-			goto out;
-		} else {
-			ret = 0;
-			printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n");
-		}
-	}
-
-out:
-	return ret;
-}
-
 static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
-				   struct list_head *head,
-				   unsigned mem_type, bool allow_errors)
+					unsigned mem_type, bool allow_errors)
 {
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
 	struct ttm_bo_global *glob = bdev->glob;
-	struct ttm_buffer_object *entry;
 	int ret;
-	int put_count;
 
 	/*
 	 * Can't use standard list traversal since we're unlocking.
 	 */
 
 	spin_lock(&glob->lru_lock);
-
-	while (!list_empty(head)) {
-		entry = list_first_entry(head, struct ttm_buffer_object, lru);
-		kref_get(&entry->list_kref);
-		ret = ttm_bo_reserve_locked(entry, false, false, false, 0);
-		put_count = ttm_bo_del_from_lru(entry);
+	while (!list_empty(&man->lru)) {
 		spin_unlock(&glob->lru_lock);
-		while (put_count--)
-			kref_put(&entry->list_kref, ttm_bo_ref_bug);
-		BUG_ON(ret);
-		ret = ttm_bo_leave_list(entry, mem_type, allow_errors);
-		ttm_bo_unreserve(entry);
-		kref_put(&entry->list_kref, ttm_bo_release_list);
+		ret = ttm_mem_evict_first(bdev, mem_type, false, false);
+		if (ret) {
+			if (allow_errors) {
+				return ret;
+			} else {
+				printk(KERN_ERR TTM_PFX
+					"Cleanup eviction failed\n");
+			}
+		}
 		spin_lock(&glob->lru_lock);
 	}
-
 	spin_unlock(&glob->lru_lock);
-
 	return 0;
 }
 
@@ -1246,7 +1345,7 @@
 
 	ret = 0;
 	if (mem_type > 0) {
-		ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false);
+		ttm_bo_force_list_clean(bdev, mem_type, false);
 
 		spin_lock(&glob->lru_lock);
 		if (drm_mm_clean(&man->manager))
@@ -1279,12 +1378,12 @@
 		return 0;
 	}
 
-	return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true);
+	return ttm_bo_force_list_clean(bdev, mem_type, true);
 }
 EXPORT_SYMBOL(ttm_bo_evict_mm);
 
 int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
-		   unsigned long p_offset, unsigned long p_size)
+			unsigned long p_size)
 {
 	int ret = -EINVAL;
 	struct ttm_mem_type_manager *man;
@@ -1314,7 +1413,7 @@
 			       type);
 			return ret;
 		}
-		ret = drm_mm_init(&man->manager, p_offset, p_size);
+		ret = drm_mm_init(&man->manager, 0, p_size);
 		if (ret)
 			return ret;
 	}
@@ -1463,7 +1562,7 @@
 	 * Initialize the system memory buffer type.
 	 * Other types need to be driver / IOCTL initialized.
 	 */
-	ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0);
+	ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0);
 	if (unlikely(ret != 0))
 		goto out_no_sys;
 
@@ -1693,7 +1792,7 @@
 			ret = wait_event_interruptible
 			    (bo->event_queue, atomic_read(&bo->reserved) == 0);
 			if (unlikely(ret != 0))
-				return -ERESTART;
+				return ret;
 		} else {
 			wait_event(bo->event_queue,
 				   atomic_read(&bo->reserved) == 0);
@@ -1722,12 +1821,14 @@
 	ttm_bo_unreserve(bo);
 	return ret;
 }
+EXPORT_SYMBOL(ttm_bo_synccpu_write_grab);
 
 void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo)
 {
 	if (atomic_dec_and_test(&bo->cpu_writers))
 		wake_up_all(&bo->event_queue);
 }
+EXPORT_SYMBOL(ttm_bo_synccpu_write_release);
 
 /**
  * A buffer object shrink method that tries to swap out the first
@@ -1808,6 +1909,9 @@
 	 * anyone tries to access a ttm page.
 	 */
 
+	if (bo->bdev->driver->swap_notify)
+		bo->bdev->driver->swap_notify(bo);
+
 	ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
 out:
 
@@ -1828,3 +1932,4 @@
 	while (ttm_bo_swapout(&bdev->glob->shrink) == 0)
 		;
 }
+EXPORT_SYMBOL(ttm_bo_swapout_all);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_object.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_object.c
@@ -0,0 +1,452 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+/** @file ttm_ref_object.c
+ *
+ * Base- and reference object implementation for the various
+ * ttm objects. Implements reference counting, minimal security checks
+ * and release on file close.
+ */
+
+/**
+ * struct ttm_object_file
+ *
+ * @tdev: Pointer to the ttm_object_device.
+ *
+ * @lock: Lock that protects the ref_list list and the
+ * ref_hash hash tables.
+ *
+ * @ref_list: List of ttm_ref_objects to be destroyed at
+ * file release.
+ *
+ * @ref_hash: Hash tables of ref objects, one per ttm_ref_type,
+ * for fast lookup of ref objects given a base object.
+ */
+
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_module.h"
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/atomic.h>
+
+struct ttm_object_file {
+	struct ttm_object_device *tdev;
+	rwlock_t lock;
+	struct list_head ref_list;
+	struct drm_open_hash ref_hash[TTM_REF_NUM];
+	struct kref refcount;
+};
+
+/**
+ * struct ttm_object_device
+ *
+ * @object_lock: lock that protects the object_hash hash table.
+ *
+ * @object_hash: hash table for fast lookup of object global names.
+ *
+ * @object_count: Per device object count.
+ *
+ * This is the per-device data structure needed for ttm object management.
+ */
+
+struct ttm_object_device {
+	rwlock_t object_lock;
+	struct drm_open_hash object_hash;
+	atomic_t object_count;
+	struct ttm_mem_global *mem_glob;
+};
+
+/**
+ * struct ttm_ref_object
+ *
+ * @hash: Hash entry for the per-file object reference hash.
+ *
+ * @head: List entry for the per-file list of ref-objects.
+ *
+ * @kref: Ref count.
+ *
+ * @obj: Base object this ref object is referencing.
+ *
+ * @ref_type: Type of ref object.
+ *
+ * This is similar to an idr object, but it also has a hash table entry
+ * that allows lookup with a pointer to the referenced object as a key. In
+ * that way, one can easily detect whether a base object is referenced by
+ * a particular ttm_object_file. It also carries a ref count to avoid creating
+ * multiple ref objects if a ttm_object_file references the same base
+ * object more than once.
+ */
+
+struct ttm_ref_object {
+	struct drm_hash_item hash;
+	struct list_head head;
+	struct kref kref;
+	enum ttm_ref_type ref_type;
+	struct ttm_base_object *obj;
+	struct ttm_object_file *tfile;
+};
+
+static inline struct ttm_object_file *
+ttm_object_file_ref(struct ttm_object_file *tfile)
+{
+	kref_get(&tfile->refcount);
+	return tfile;
+}
+
+static void ttm_object_file_destroy(struct kref *kref)
+{
+	struct ttm_object_file *tfile =
+		container_of(kref, struct ttm_object_file, refcount);
+
+	kfree(tfile);
+}
+
+
+static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile)
+{
+	struct ttm_object_file *tfile = *p_tfile;
+
+	*p_tfile = NULL;
+	kref_put(&tfile->refcount, ttm_object_file_destroy);
+}
+
+
+int ttm_base_object_init(struct ttm_object_file *tfile,
+			 struct ttm_base_object *base,
+			 bool shareable,
+			 enum ttm_object_type object_type,
+			 void (*refcount_release) (struct ttm_base_object **),
+			 void (*ref_obj_release) (struct ttm_base_object *,
+						  enum ttm_ref_type ref_type))
+{
+	struct ttm_object_device *tdev = tfile->tdev;
+	int ret;
+
+	base->shareable = shareable;
+	base->tfile = ttm_object_file_ref(tfile);
+	base->refcount_release = refcount_release;
+	base->ref_obj_release = ref_obj_release;
+	base->object_type = object_type;
+	write_lock(&tdev->object_lock);
+	kref_init(&base->refcount);
+	ret = drm_ht_just_insert_please(&tdev->object_hash,
+					&base->hash,
+					(unsigned long)base, 31, 0, 0);
+	write_unlock(&tdev->object_lock);
+	if (unlikely(ret != 0))
+		goto out_err0;
+
+	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	ttm_base_object_unref(&base);
+
+	return 0;
+out_err1:
+	(void)drm_ht_remove_item(&tdev->object_hash, &base->hash);
+out_err0:
+	return ret;
+}
+EXPORT_SYMBOL(ttm_base_object_init);
+
+static void ttm_release_base(struct kref *kref)
+{
+	struct ttm_base_object *base =
+	    container_of(kref, struct ttm_base_object, refcount);
+	struct ttm_object_device *tdev = base->tfile->tdev;
+
+	(void)drm_ht_remove_item(&tdev->object_hash, &base->hash);
+	write_unlock(&tdev->object_lock);
+	if (base->refcount_release) {
+		ttm_object_file_unref(&base->tfile);
+		base->refcount_release(&base);
+	}
+	write_lock(&tdev->object_lock);
+}
+
+void ttm_base_object_unref(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct ttm_object_device *tdev = base->tfile->tdev;
+
+	*p_base = NULL;
+
+	/*
+	 * Need to take the lock here to avoid racing with
+	 * users trying to look up the object.
+	 */
+
+	write_lock(&tdev->object_lock);
+	(void)kref_put(&base->refcount, &ttm_release_base);
+	write_unlock(&tdev->object_lock);
+}
+EXPORT_SYMBOL(ttm_base_object_unref);
+
+struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+					       uint32_t key)
+{
+	struct ttm_object_device *tdev = tfile->tdev;
+	struct ttm_base_object *base;
+	struct drm_hash_item *hash;
+	int ret;
+
+	read_lock(&tdev->object_lock);
+	ret = drm_ht_find_item(&tdev->object_hash, key, &hash);
+
+	if (likely(ret == 0)) {
+		base = drm_hash_entry(hash, struct ttm_base_object, hash);
+		kref_get(&base->refcount);
+	}
+	read_unlock(&tdev->object_lock);
+
+	if (unlikely(ret != 0))
+		return NULL;
+
+	if (tfile != base->tfile && !base->shareable) {
+		printk(KERN_ERR TTM_PFX
+		       "Attempted access of non-shareable object.\n");
+		ttm_base_object_unref(&base);
+		return NULL;
+	}
+
+	return base;
+}
+EXPORT_SYMBOL(ttm_base_object_lookup);
+
+int ttm_ref_object_add(struct ttm_object_file *tfile,
+		       struct ttm_base_object *base,
+		       enum ttm_ref_type ref_type, bool *existed)
+{
+	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
+	struct ttm_ref_object *ref;
+	struct drm_hash_item *hash;
+	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
+	int ret = -EINVAL;
+
+	if (existed != NULL)
+		*existed = true;
+
+	while (ret == -EINVAL) {
+		read_lock(&tfile->lock);
+		ret = drm_ht_find_item(ht, base->hash.key, &hash);
+
+		if (ret == 0) {
+			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+			kref_get(&ref->kref);
+			read_unlock(&tfile->lock);
+			break;
+		}
+
+		read_unlock(&tfile->lock);
+		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
+					   false, false);
+		if (unlikely(ret != 0))
+			return ret;
+		ref = kmalloc(sizeof(*ref), GFP_KERNEL);
+		if (unlikely(ref == NULL)) {
+			ttm_mem_global_free(mem_glob, sizeof(*ref));
+			return -ENOMEM;
+		}
+
+		ref->hash.key = base->hash.key;
+		ref->obj = base;
+		ref->tfile = tfile;
+		ref->ref_type = ref_type;
+		kref_init(&ref->kref);
+
+		write_lock(&tfile->lock);
+		ret = drm_ht_insert_item(ht, &ref->hash);
+
+		if (likely(ret == 0)) {
+			list_add_tail(&ref->head, &tfile->ref_list);
+			kref_get(&base->refcount);
+			write_unlock(&tfile->lock);
+			if (existed != NULL)
+				*existed = false;
+			break;
+		}
+
+		write_unlock(&tfile->lock);
+		BUG_ON(ret != -EINVAL);
+
+		ttm_mem_global_free(mem_glob, sizeof(*ref));
+		kfree(ref);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(ttm_ref_object_add);
+
+static void ttm_ref_object_release(struct kref *kref)
+{
+	struct ttm_ref_object *ref =
+	    container_of(kref, struct ttm_ref_object, kref);
+	struct ttm_base_object *base = ref->obj;
+	struct ttm_object_file *tfile = ref->tfile;
+	struct drm_open_hash *ht;
+	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
+
+	ht = &tfile->ref_hash[ref->ref_type];
+	(void)drm_ht_remove_item(ht, &ref->hash);
+	list_del(&ref->head);
+	write_unlock(&tfile->lock);
+
+	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
+		base->ref_obj_release(base, ref->ref_type);
+
+	ttm_base_object_unref(&ref->obj);
+	ttm_mem_global_free(mem_glob, sizeof(*ref));
+	kfree(ref);
+	write_lock(&tfile->lock);
+}
+
+int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+			      unsigned long key, enum ttm_ref_type ref_type)
+{
+	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
+	struct ttm_ref_object *ref;
+	struct drm_hash_item *hash;
+	int ret;
+
+	write_lock(&tfile->lock);
+	ret = drm_ht_find_item(ht, key, &hash);
+	if (unlikely(ret != 0)) {
+		write_unlock(&tfile->lock);
+		return -EINVAL;
+	}
+	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+	kref_put(&ref->kref, ttm_ref_object_release);
+	write_unlock(&tfile->lock);
+	return 0;
+}
+EXPORT_SYMBOL(ttm_ref_object_base_unref);
+
+void ttm_object_file_release(struct ttm_object_file **p_tfile)
+{
+	struct ttm_ref_object *ref;
+	struct list_head *list;
+	unsigned int i;
+	struct ttm_object_file *tfile = *p_tfile;
+
+	*p_tfile = NULL;
+	write_lock(&tfile->lock);
+
+	/*
+	 * Since we release the lock within the loop, we have to
+	 * restart it from the beginning each time.
+	 */
+
+	while (!list_empty(&tfile->ref_list)) {
+		list = tfile->ref_list.next;
+		ref = list_entry(list, struct ttm_ref_object, head);
+		ttm_ref_object_release(&ref->kref);
+	}
+
+	for (i = 0; i < TTM_REF_NUM; ++i)
+		drm_ht_remove(&tfile->ref_hash[i]);
+
+	write_unlock(&tfile->lock);
+	ttm_object_file_unref(&tfile);
+}
+EXPORT_SYMBOL(ttm_object_file_release);
+
+struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
+					     unsigned int hash_order)
+{
+	struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+	unsigned int i;
+	unsigned int j = 0;
+	int ret;
+
+	if (unlikely(tfile == NULL))
+		return NULL;
+
+	rwlock_init(&tfile->lock);
+	tfile->tdev = tdev;
+	kref_init(&tfile->refcount);
+	INIT_LIST_HEAD(&tfile->ref_list);
+
+	for (i = 0; i < TTM_REF_NUM; ++i) {
+		ret = drm_ht_create(&tfile->ref_hash[i], hash_order);
+		if (ret) {
+			j = i;
+			goto out_err;
+		}
+	}
+
+	return tfile;
+out_err:
+	for (i = 0; i < j; ++i)
+		drm_ht_remove(&tfile->ref_hash[i]);
+
+	kfree(tfile);
+
+	return NULL;
+}
+EXPORT_SYMBOL(ttm_object_file_init);
+
+struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global
+						 *mem_glob,
+						 unsigned int hash_order)
+{
+	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
+	int ret;
+
+	if (unlikely(tdev == NULL))
+		return NULL;
+
+	tdev->mem_glob = mem_glob;
+	rwlock_init(&tdev->object_lock);
+	atomic_set(&tdev->object_count, 0);
+	ret = drm_ht_create(&tdev->object_hash, hash_order);
+
+	if (likely(ret == 0))
+		return tdev;
+
+	kfree(tdev);
+	return NULL;
+}
+EXPORT_SYMBOL(ttm_object_device_init);
+
+void ttm_object_device_release(struct ttm_object_device **p_tdev)
+{
+	struct ttm_object_device *tdev = *p_tdev;
+
+	*p_tdev = NULL;
+
+	write_lock(&tdev->object_lock);
+	drm_ht_remove(&tdev->object_hash);
+	write_unlock(&tdev->object_lock);
+
+	kfree(tdev);
+}
+EXPORT_SYMBOL(ttm_object_device_release);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_tt.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_tt.c
@@ -192,26 +192,38 @@
 	ttm->state = tt_unbound;
 	return 0;
 }
+EXPORT_SYMBOL(ttm_tt_populate);
 
 #ifdef CONFIG_X86
 static inline int ttm_tt_set_page_caching(struct page *p,
-					  enum ttm_caching_state c_state)
+					  enum ttm_caching_state c_old,
+					  enum ttm_caching_state c_new)
 {
+	int ret = 0;
+
 	if (PageHighMem(p))
 		return 0;
 
-	switch (c_state) {
-	case tt_cached:
-		return set_pages_wb(p, 1);
-	case tt_wc:
-	    return set_memory_wc((unsigned long) page_address(p), 1);
-	default:
-		return set_pages_uc(p, 1);
+	if (c_old != tt_cached) {
+		/* p isn't in the default caching state, set it to
+		 * writeback first to free its current memtype. */
+
+		ret = set_pages_wb(p, 1);
+		if (ret)
+			return ret;
 	}
+
+	if (c_new == tt_wc)
+		ret = set_memory_wc((unsigned long) page_address(p), 1);
+	else if (c_new == tt_uncached)
+		ret = set_pages_uc(p, 1);
+
+	return ret;
 }
 #else /* CONFIG_X86 */
 static inline int ttm_tt_set_page_caching(struct page *p,
-					  enum ttm_caching_state c_state)
+					  enum ttm_caching_state c_old,
+					  enum ttm_caching_state c_new)
 {
 	return 0;
 }
@@ -244,7 +256,9 @@
 	for (i = 0; i < ttm->num_pages; ++i) {
 		cur_page = ttm->pages[i];
 		if (likely(cur_page != NULL)) {
-			ret = ttm_tt_set_page_caching(cur_page, c_state);
+			ret = ttm_tt_set_page_caching(cur_page,
+						      ttm->caching_state,
+						      c_state);
 			if (unlikely(ret != 0))
 				goto out_err;
 		}
@@ -258,7 +272,7 @@
 	for (j = 0; j < i; ++j) {
 		cur_page = ttm->pages[j];
 		if (likely(cur_page != NULL)) {
-			(void)ttm_tt_set_page_caching(cur_page,
+			(void)ttm_tt_set_page_caching(cur_page, c_state,
 						      ttm->caching_state);
 		}
 	}
@@ -466,7 +480,7 @@
 	void *from_virtual;
 	void *to_virtual;
 	int i;
-	int ret;
+	int ret = -ENOMEM;
 
 	if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
 		ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start,
@@ -485,8 +499,10 @@
 
 	for (i = 0; i < ttm->num_pages; ++i) {
 		from_page = read_mapping_page(swap_space, i, NULL);
-		if (IS_ERR(from_page))
+		if (IS_ERR(from_page)) {
+			ret = PTR_ERR(from_page);
 			goto out_err;
+		}
 		to_page = __ttm_tt_get_page(ttm, i);
 		if (unlikely(to_page == NULL))
 			goto out_err;
@@ -509,7 +525,7 @@
 	return 0;
 out_err:
 	ttm_tt_free_alloced_pages(ttm);
-	return -ENOMEM;
+	return ret;
 }
 
 int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
@@ -521,6 +537,7 @@
 	void *from_virtual;
 	void *to_virtual;
 	int i;
+	int ret = -ENOMEM;
 
 	BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
 	BUG_ON(ttm->caching_state != tt_cached);
@@ -543,7 +560,7 @@
 						0);
 		if (unlikely(IS_ERR(swap_storage))) {
 			printk(KERN_ERR "Failed allocating swap storage.\n");
-			return -ENOMEM;
+			return PTR_ERR(swap_storage);
 		}
 	} else
 		swap_storage = persistant_swap_storage;
@@ -555,9 +572,10 @@
 		if (unlikely(from_page == NULL))
 			continue;
 		to_page = read_mapping_page(swap_space, i, NULL);
-		if (unlikely(to_page == NULL))
+		if (unlikely(IS_ERR(to_page))) {
+			ret = PTR_ERR(to_page);
 			goto out_err;
-
+		}
 		preempt_disable();
 		from_virtual = kmap_atomic(from_page, KM_USER0);
 		to_virtual = kmap_atomic(to_page, KM_USER1);
@@ -581,5 +599,5 @@
 	if (!persistant_swap_storage)
 		fput(swap_storage);
 
-	return -ENOMEM;
+	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -53,7 +53,6 @@
 {
 	struct ttm_tt *ttm = bo->ttm;
 	struct ttm_mem_reg *old_mem = &bo->mem;
-	uint32_t save_flags = old_mem->placement;
 	int ret;
 
 	if (old_mem->mem_type != TTM_PL_SYSTEM) {
@@ -62,7 +61,6 @@
 		ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
 				TTM_PL_MASK_MEM);
 		old_mem->mem_type = TTM_PL_SYSTEM;
-		save_flags = old_mem->placement;
 	}
 
 	ret = ttm_tt_set_placement_caching(ttm, new_mem->placement);
@@ -77,7 +75,7 @@
 
 	*old_mem = *new_mem;
 	new_mem->mm_node = NULL;
-	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
+
 	return 0;
 }
 EXPORT_SYMBOL(ttm_bo_move_ttm);
@@ -219,7 +217,6 @@
 	void *old_iomap;
 	void *new_iomap;
 	int ret;
-	uint32_t save_flags = old_mem->placement;
 	unsigned long i;
 	unsigned long page;
 	unsigned long add = 0;
@@ -270,7 +267,6 @@
 
 	*old_mem = *new_mem;
 	new_mem->mm_node = NULL;
-	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
 
 	if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (ttm != NULL)) {
 		ttm_tt_unbind(ttm);
@@ -330,6 +326,7 @@
 	INIT_LIST_HEAD(&fbo->lru);
 	INIT_LIST_HEAD(&fbo->swap);
 	fbo->vm_node = NULL;
+	atomic_set(&fbo->cpu_writers, 0);
 
 	fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
 	if (fbo->mem.mm_node)
@@ -369,6 +366,7 @@
 #endif
 	return tmp;
 }
+EXPORT_SYMBOL(ttm_io_prot);
 
 static int ttm_bo_ioremap(struct ttm_buffer_object *bo,
 			  unsigned long bus_base,
@@ -427,7 +425,7 @@
 
 		/*
 		 * We need to use vmap to get the desired page protection
-		 * or to make the buffer object look contigous.
+		 * or to make the buffer object look contiguous.
 		 */
 		prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
 			PAGE_KERNEL :
@@ -536,7 +534,6 @@
 	struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
 	struct ttm_mem_reg *old_mem = &bo->mem;
 	int ret;
-	uint32_t save_flags = old_mem->placement;
 	struct ttm_buffer_object *ghost_obj;
 	void *tmp_obj = NULL;
 
@@ -597,7 +594,7 @@
 
 	*old_mem = *new_mem;
 	new_mem->mm_node = NULL;
-	ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
+
 	return 0;
 }
 EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -0,0 +1,117 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "ttm/ttm_execbuf_util.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+
+void ttm_eu_backoff_reservation(struct list_head *list)
+{
+	struct ttm_validate_buffer *entry;
+
+	list_for_each_entry(entry, list, head) {
+		struct ttm_buffer_object *bo = entry->bo;
+		if (!entry->reserved)
+			continue;
+
+		entry->reserved = false;
+		ttm_bo_unreserve(bo);
+	}
+}
+EXPORT_SYMBOL(ttm_eu_backoff_reservation);
+
+/*
+ * Reserve buffers for validation.
+ *
+ * If a buffer in the list is marked for CPU access, we back off and
+ * wait for that buffer to become free for GPU access.
+ *
+ * If a buffer is reserved for another validation, the validator with
+ * the highest validation sequence backs off and waits for that buffer
+ * to become unreserved. This prevents deadlocks when validating multiple
+ * buffers in different orders.
+ */
+
+int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq)
+{
+	struct ttm_validate_buffer *entry;
+	int ret;
+
+retry:
+	list_for_each_entry(entry, list, head) {
+		struct ttm_buffer_object *bo = entry->bo;
+
+		entry->reserved = false;
+		ret = ttm_bo_reserve(bo, true, false, true, val_seq);
+		if (ret != 0) {
+			ttm_eu_backoff_reservation(list);
+			if (ret == -EAGAIN) {
+				ret = ttm_bo_wait_unreserved(bo, true);
+				if (unlikely(ret != 0))
+					return ret;
+				goto retry;
+			} else
+				return ret;
+		}
+
+		entry->reserved = true;
+		if (unlikely(atomic_read(&bo->cpu_writers) > 0)) {
+			ttm_eu_backoff_reservation(list);
+			ret = ttm_bo_wait_cpu(bo, false);
+			if (ret)
+				return ret;
+			goto retry;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ttm_eu_reserve_buffers);
+
+void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
+{
+	struct ttm_validate_buffer *entry;
+
+	list_for_each_entry(entry, list, head) {
+		struct ttm_buffer_object *bo = entry->bo;
+		struct ttm_bo_driver *driver = bo->bdev->driver;
+		void *old_sync_obj;
+
+		spin_lock(&bo->lock);
+		old_sync_obj = bo->sync_obj;
+		bo->sync_obj = driver->sync_obj_ref(sync_obj);
+		bo->sync_obj_arg = entry->new_sync_obj_arg;
+		spin_unlock(&bo->lock);
+		ttm_bo_unreserve(bo);
+		entry->reserved = false;
+		if (old_sync_obj)
+			driver->sync_obj_unref(&old_sync_obj);
+	}
+}
+EXPORT_SYMBOL(ttm_eu_fence_buffer_objects);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/r128/r128_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/r128/r128_drv.c
@@ -64,7 +64,7 @@
 		.owner = THIS_MODULE,
 		.open = drm_open,
 		.release = drm_release,
-		.ioctl = drm_ioctl,
+		.unlocked_ioctl = drm_ioctl,
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/r128/r128_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/r128/r128_ioc32.c
@@ -95,8 +95,7 @@
 			  &init->agp_textures_offset))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_R128_INIT, (unsigned long)init);
+	return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init);
 }
 
 typedef struct drm_r128_depth32 {
@@ -129,8 +128,7 @@
 			  &depth->mask))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+	return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
 
 }
 
@@ -153,8 +151,7 @@
 			  &stipple->mask))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+	return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
 }
 
 typedef struct drm_r128_getparam32 {
@@ -178,8 +175,7 @@
 			  &getparam->value))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+	return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
 }
 
 drm_ioctl_compat_t *r128_compat_ioctls[] = {
@@ -210,12 +206,10 @@
 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
 		fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-	lock_kernel();		/* XXX for now */
 	if (fn != NULL)
 		ret = (*fn) (filp, cmd, arg);
 	else
-		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+		ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i830/i830_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i830/i830_drv.c
@@ -70,7 +70,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i830/i830_dma.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i830/i830_dma.c
@@ -117,7 +117,7 @@
 static const struct file_operations i830_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.ioctl = drm_ioctl,
+	.unlocked_ioctl = drm_ioctl,
 	.mmap = i830_mmap_buffers,
 	.fasync = drm_fasync,
 };
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rs600d.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rs600d.h
@@ -30,27 +30,12 @@
 
 /* Registers */
 #define R_000040_GEN_INT_CNTL                        0x000040
-#define   S_000040_DISPLAY_INT_STATUS(x)               (((x) & 0x1) << 0)
-#define   G_000040_DISPLAY_INT_STATUS(x)               (((x) >> 0) & 0x1)
-#define   C_000040_DISPLAY_INT_STATUS                  0xFFFFFFFE
-#define   S_000040_DMA_VIPH0_INT_EN(x)                 (((x) & 0x1) << 12)
-#define   G_000040_DMA_VIPH0_INT_EN(x)                 (((x) >> 12) & 0x1)
-#define   C_000040_DMA_VIPH0_INT_EN                    0xFFFFEFFF
-#define   S_000040_CRTC2_VSYNC(x)                      (((x) & 0x1) << 6)
-#define   G_000040_CRTC2_VSYNC(x)                      (((x) >> 6) & 0x1)
-#define   C_000040_CRTC2_VSYNC                         0xFFFFFFBF
-#define   S_000040_SNAPSHOT2(x)                        (((x) & 0x1) << 7)
-#define   G_000040_SNAPSHOT2(x)                        (((x) >> 7) & 0x1)
-#define   C_000040_SNAPSHOT2                           0xFFFFFF7F
-#define   S_000040_CRTC2_VBLANK(x)                     (((x) & 0x1) << 9)
-#define   G_000040_CRTC2_VBLANK(x)                     (((x) >> 9) & 0x1)
-#define   C_000040_CRTC2_VBLANK                        0xFFFFFDFF
-#define   S_000040_FP2_DETECT(x)                       (((x) & 0x1) << 10)
-#define   G_000040_FP2_DETECT(x)                       (((x) >> 10) & 0x1)
-#define   C_000040_FP2_DETECT                          0xFFFFFBFF
-#define   S_000040_VSYNC_DIFF_OVER_LIMIT(x)            (((x) & 0x1) << 11)
-#define   G_000040_VSYNC_DIFF_OVER_LIMIT(x)            (((x) >> 11) & 0x1)
-#define   C_000040_VSYNC_DIFF_OVER_LIMIT               0xFFFFF7FF
+#define   S_000040_SCRATCH_INT_MASK(x)                 (((x) & 0x1) << 18)
+#define   G_000040_SCRATCH_INT_MASK(x)                 (((x) >> 18) & 0x1)
+#define   C_000040_SCRATCH_INT_MASK                    0xFFFBFFFF
+#define   S_000040_GUI_IDLE_MASK(x)                    (((x) & 0x1) << 19)
+#define   G_000040_GUI_IDLE_MASK(x)                    (((x) >> 19) & 0x1)
+#define   C_000040_GUI_IDLE_MASK                       0xFFF7FFFF
 #define   S_000040_DMA_VIPH1_INT_EN(x)                 (((x) & 0x1) << 13)
 #define   G_000040_DMA_VIPH1_INT_EN(x)                 (((x) >> 13) & 0x1)
 #define   C_000040_DMA_VIPH1_INT_EN                    0xFFFFDFFF
@@ -370,7 +355,90 @@
 #define   S_007EDC_LB_D2_VBLANK_INTERRUPT(x)           (((x) & 0x1) << 5)
 #define   G_007EDC_LB_D2_VBLANK_INTERRUPT(x)           (((x) >> 5) & 0x1)
 #define   C_007EDC_LB_D2_VBLANK_INTERRUPT              0xFFFFFFDF
-
+#define   S_007EDC_DACA_AUTODETECT_INTERRUPT(x)        (((x) & 0x1) << 16)
+#define   G_007EDC_DACA_AUTODETECT_INTERRUPT(x)        (((x) >> 16) & 0x1)
+#define   C_007EDC_DACA_AUTODETECT_INTERRUPT           0xFFFEFFFF
+#define   S_007EDC_DACB_AUTODETECT_INTERRUPT(x)        (((x) & 0x1) << 17)
+#define   G_007EDC_DACB_AUTODETECT_INTERRUPT(x)        (((x) >> 17) & 0x1)
+#define   C_007EDC_DACB_AUTODETECT_INTERRUPT           0xFFFDFFFF
+#define   S_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x)    (((x) & 0x1) << 18)
+#define   G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(x)    (((x) >> 18) & 0x1)
+#define   C_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT       0xFFFBFFFF
+#define   S_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x)    (((x) & 0x1) << 19)
+#define   G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(x)    (((x) >> 19) & 0x1)
+#define   C_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT       0xFFF7FFFF
+#define R_007828_DACA_AUTODETECT_CONTROL               0x007828
+#define   S_007828_DACA_AUTODETECT_MODE(x)             (((x) & 0x3) << 0)
+#define   G_007828_DACA_AUTODETECT_MODE(x)             (((x) >> 0) & 0x3)
+#define   C_007828_DACA_AUTODETECT_MODE                0xFFFFFFFC
+#define   S_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8)
+#define   G_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff)
+#define   C_007828_DACA_AUTODETECT_FRAME_TIME_COUNTER  0xFFFF00FF
+#define   S_007828_DACA_AUTODETECT_CHECK_MASK(x)       (((x) & 0x3) << 16)
+#define   G_007828_DACA_AUTODETECT_CHECK_MASK(x)       (((x) >> 16) & 0x3)
+#define   C_007828_DACA_AUTODETECT_CHECK_MASK          0xFFFCFFFF
+#define R_007838_DACA_AUTODETECT_INT_CONTROL           0x007838
+#define   S_007838_DACA_AUTODETECT_ACK(x)              (((x) & 0x1) << 0)
+#define   C_007838_DACA_DACA_AUTODETECT_ACK            0xFFFFFFFE
+#define   S_007838_DACA_AUTODETECT_INT_ENABLE(x)       (((x) & 0x1) << 16)
+#define   G_007838_DACA_AUTODETECT_INT_ENABLE(x)       (((x) >> 16) & 0x1)
+#define   C_007838_DACA_AUTODETECT_INT_ENABLE          0xFFFCFFFF
+#define R_007A28_DACB_AUTODETECT_CONTROL               0x007A28
+#define   S_007A28_DACB_AUTODETECT_MODE(x)             (((x) & 0x3) << 0)
+#define   G_007A28_DACB_AUTODETECT_MODE(x)             (((x) >> 0) & 0x3)
+#define   C_007A28_DACB_AUTODETECT_MODE                0xFFFFFFFC
+#define   S_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) & 0xff) << 8)
+#define   G_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER(x) (((x) >> 8) & 0xff)
+#define   C_007A28_DACB_AUTODETECT_FRAME_TIME_COUNTER  0xFFFF00FF
+#define   S_007A28_DACB_AUTODETECT_CHECK_MASK(x)       (((x) & 0x3) << 16)
+#define   G_007A28_DACB_AUTODETECT_CHECK_MASK(x)       (((x) >> 16) & 0x3)
+#define   C_007A28_DACB_AUTODETECT_CHECK_MASK          0xFFFCFFFF
+#define R_007A38_DACB_AUTODETECT_INT_CONTROL           0x007A38
+#define   S_007A38_DACB_AUTODETECT_ACK(x)              (((x) & 0x1) << 0)
+#define   C_007A38_DACB_DACA_AUTODETECT_ACK            0xFFFFFFFE
+#define   S_007A38_DACB_AUTODETECT_INT_ENABLE(x)       (((x) & 0x1) << 16)
+#define   G_007A38_DACB_AUTODETECT_INT_ENABLE(x)       (((x) >> 16) & 0x1)
+#define   C_007A38_DACB_AUTODETECT_INT_ENABLE          0xFFFCFFFF
+#define R_007D00_DC_HOT_PLUG_DETECT1_CONTROL           0x007D00
+#define   S_007D00_DC_HOT_PLUG_DETECT1_EN(x)           (((x) & 0x1) << 0)
+#define   G_007D00_DC_HOT_PLUG_DETECT1_EN(x)           (((x) >> 0) & 0x1)
+#define   C_007D00_DC_HOT_PLUG_DETECT1_EN              0xFFFFFFFE
+#define R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS        0x007D04
+#define   S_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x)   (((x) & 0x1) << 0)
+#define   G_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS(x)   (((x) >> 0) & 0x1)
+#define   C_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS      0xFFFFFFFE
+#define   S_007D04_DC_HOT_PLUG_DETECT1_SENSE(x)        (((x) & 0x1) << 1)
+#define   G_007D04_DC_HOT_PLUG_DETECT1_SENSE(x)        (((x) >> 1) & 0x1)
+#define   C_007D04_DC_HOT_PLUG_DETECT1_SENSE           0xFFFFFFFD
+#define R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL       0x007D08
+#define   S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(x)      (((x) & 0x1) << 0)
+#define   C_007D08_DC_HOT_PLUG_DETECT1_INT_ACK         0xFFFFFFFE
+#define   S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) & 0x1) << 8)
+#define   G_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(x) (((x) >> 8) & 0x1)
+#define   C_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY    0xFFFFFEFF
+#define   S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x)       (((x) & 0x1) << 16)
+#define   G_007D08_DC_HOT_PLUG_DETECT1_INT_EN(x)       (((x) >> 16) & 0x1)
+#define   C_007D08_DC_HOT_PLUG_DETECT1_INT_EN          0xFFFEFFFF
+#define R_007D10_DC_HOT_PLUG_DETECT2_CONTROL           0x007D10
+#define   S_007D10_DC_HOT_PLUG_DETECT2_EN(x)           (((x) & 0x1) << 0)
+#define   G_007D10_DC_HOT_PLUG_DETECT2_EN(x)           (((x) >> 0) & 0x1)
+#define   C_007D10_DC_HOT_PLUG_DETECT2_EN              0xFFFFFFFE
+#define R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS        0x007D14
+#define   S_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x)   (((x) & 0x1) << 0)
+#define   G_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS(x)   (((x) >> 0) & 0x1)
+#define   C_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS      0xFFFFFFFE
+#define   S_007D14_DC_HOT_PLUG_DETECT2_SENSE(x)        (((x) & 0x1) << 1)
+#define   G_007D14_DC_HOT_PLUG_DETECT2_SENSE(x)        (((x) >> 1) & 0x1)
+#define   C_007D14_DC_HOT_PLUG_DETECT2_SENSE           0xFFFFFFFD
+#define R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL       0x007D18
+#define   S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(x)      (((x) & 0x1) << 0)
+#define   C_007D18_DC_HOT_PLUG_DETECT2_INT_ACK         0xFFFFFFFE
+#define   S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) & 0x1) << 8)
+#define   G_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(x) (((x) >> 8) & 0x1)
+#define   C_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY    0xFFFFFEFF
+#define   S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x)       (((x) & 0x1) << 16)
+#define   G_007D18_DC_HOT_PLUG_DETECT2_INT_EN(x)       (((x) >> 16) & 0x1)
+#define   C_007D18_DC_HOT_PLUG_DETECT2_INT_EN          0xFFFEFFFF
 
 /* MC registers */
 #define R_000000_MC_STATUS                           0x000000
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/atombios_crtc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -241,6 +241,7 @@
 {
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
@@ -248,20 +249,19 @@
 		if (ASIC_IS_DCE3(rdev))
 			atombios_enable_crtc_memreq(crtc, 1);
 		atombios_blank_crtc(crtc, 0);
+		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+		radeon_crtc_load_lut(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
 		atombios_blank_crtc(crtc, 1);
 		if (ASIC_IS_DCE3(rdev))
 			atombios_enable_crtc_memreq(crtc, 0);
 		atombios_enable_crtc(crtc, 0);
 		break;
 	}
-
-	if (mode != DRM_MODE_DPMS_OFF) {
-		radeon_crtc_load_lut(crtc);
-	}
 }
 
 static void
@@ -307,7 +307,6 @@
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
 
-	printk("executing set crtc dtd timing\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -347,7 +346,6 @@
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
 
-	printk("executing set crtc timing\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -409,60 +407,75 @@
 	}
 }
 
-void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+union adjust_pixel_clock {
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
+};
+
+static u32 atombios_adjust_pll(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct radeon_pll *pll)
 {
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_encoder *encoder = NULL;
 	struct radeon_encoder *radeon_encoder = NULL;
-	uint8_t frev, crev;
-	int index;
-	SET_PIXEL_CLOCK_PS_ALLOCATION args;
-	PIXEL_CLOCK_PARAMETERS *spc1_ptr;
-	PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
-	PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-	uint32_t pll_clock = mode->clock;
-	uint32_t adjusted_clock;
-	uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
-	struct radeon_pll *pll;
-	int pll_flags = 0;
+	u32 adjusted_clock = mode->clock;
 
-	memset(&args, 0, sizeof(args));
+	/* reset the pll flags */
+	pll->flags = 0;
+
+	/* select the PLL algo */
+	if (ASIC_IS_AVIVO(rdev)) {
+		if (radeon_new_pll == 0)
+			pll->algo = PLL_ALGO_LEGACY;
+		else
+			pll->algo = PLL_ALGO_NEW;
+	} else {
+		if (radeon_new_pll == 1)
+			pll->algo = PLL_ALGO_NEW;
+		else
+			pll->algo = PLL_ALGO_LEGACY;
+	}
 
 	if (ASIC_IS_AVIVO(rdev)) {
 		if ((rdev->family == CHIP_RS600) ||
 		    (rdev->family == CHIP_RS690) ||
 		    (rdev->family == CHIP_RS740))
-			pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
-				      RADEON_PLL_PREFER_CLOSEST_LOWER);
+			pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+				       RADEON_PLL_PREFER_CLOSEST_LOWER);
 
 		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */
-			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
-			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 	} else {
-		pll_flags |= RADEON_PLL_LEGACY;
+		pll->flags |= RADEON_PLL_LEGACY;
 
 		if (mode->clock > 200000)	/* range limits??? */
-			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
-			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
-			if (!ASIC_IS_AVIVO(rdev)) {
-				if (encoder->encoder_type !=
-				    DRM_MODE_ENCODER_DAC)
-					pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
-				if (!ASIC_IS_AVIVO(rdev)
-				    && (encoder->encoder_type ==
-					DRM_MODE_ENCODER_LVDS))
-					pll_flags |= RADEON_PLL_USE_REF_DIV;
-			}
 			radeon_encoder = to_radeon_encoder(encoder);
+			if (ASIC_IS_AVIVO(rdev)) {
+				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
+					adjusted_clock = mode->clock * 2;
+				/* LVDS PLL quirks */
+				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
+					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+					pll->algo = dig->pll_algo;
+				}
+			} else {
+				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+					pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
+				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
+					pll->flags |= RADEON_PLL_USE_REF_DIV;
+			}
 			break;
 		}
 	}
@@ -472,36 +485,91 @@
 	 * special hw requirements.
 	 */
 	if (ASIC_IS_DCE3(rdev)) {
-		ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
+		union adjust_pixel_clock args;
+		struct radeon_encoder_atom_dig *dig;
+		u8 frev, crev;
+		int index;
+
+		if (!radeon_encoder->enc_priv)
+			return adjusted_clock;
+		dig = radeon_encoder->enc_priv;
 
-		if (!encoder)
-			return;
+		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
+		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+				      &crev);
 
-		memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
-		adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
-		adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
-		adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
+		memset(&args, 0, sizeof(args));
 
-		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
-		atom_execute_table(rdev->mode_info.atom_context,
-				   index, (uint32_t *)&adjust_pll_args);
-		adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
-	} else {
-		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
-		if (ASIC_IS_AVIVO(rdev) &&
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
-			adjusted_clock = mode->clock * 2;
-		else
-			adjusted_clock = mode->clock;
+		switch (frev) {
+		case 1:
+			switch (crev) {
+			case 1:
+			case 2:
+				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
+				args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
+
+				atom_execute_table(rdev->mode_info.atom_context,
+						   index, (uint32_t *)&args);
+				adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
+				break;
+			default:
+				DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+				return adjusted_clock;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+			return adjusted_clock;
+		}
+	}
+	return adjusted_clock;
+}
+
+union set_pixel_clock {
+	SET_PIXEL_CLOCK_PS_ALLOCATION base;
+	PIXEL_CLOCK_PARAMETERS v1;
+	PIXEL_CLOCK_PARAMETERS_V2 v2;
+	PIXEL_CLOCK_PARAMETERS_V3 v3;
+};
+
+void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder = NULL;
+	struct radeon_encoder *radeon_encoder = NULL;
+	u8 frev, crev;
+	int index;
+	union set_pixel_clock args;
+	u32 pll_clock = mode->clock;
+	u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
+	struct radeon_pll *pll;
+	u32 adjusted_clock;
+
+	memset(&args, 0, sizeof(args));
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc) {
+			radeon_encoder = to_radeon_encoder(encoder);
+			break;
+		}
 	}
 
+	if (!radeon_encoder)
+		return;
+
 	if (radeon_crtc->crtc_id == 0)
 		pll = &rdev->clock.p1pll;
 	else
 		pll = &rdev->clock.p2pll;
 
+	/* adjust pixel clock as needed */
+	adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
+
 	radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
-			   &ref_div, &post_div, pll_flags);
+			   &ref_div, &post_div);
 
 	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
@@ -511,45 +579,38 @@
 	case 1:
 		switch (crev) {
 		case 1:
-			spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
-			spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc1_ptr->ucFracFbDiv = frac_fb_div;
-			spc1_ptr->ucPostDiv = post_div;
-			spc1_ptr->ucPpll =
+			args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v1.usRefDiv = cpu_to_le16(ref_div);
+			args.v1.usFbDiv = cpu_to_le16(fb_div);
+			args.v1.ucFracFbDiv = frac_fb_div;
+			args.v1.ucPostDiv = post_div;
+			args.v1.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
-			spc1_ptr->ucRefDivSrc = 1;
+			args.v1.ucCRTC = radeon_crtc->crtc_id;
+			args.v1.ucRefDivSrc = 1;
 			break;
 		case 2:
-			spc2_ptr =
-			    (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
-			spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc2_ptr->ucFracFbDiv = frac_fb_div;
-			spc2_ptr->ucPostDiv = post_div;
-			spc2_ptr->ucPpll =
+			args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v2.usRefDiv = cpu_to_le16(ref_div);
+			args.v2.usFbDiv = cpu_to_le16(fb_div);
+			args.v2.ucFracFbDiv = frac_fb_div;
+			args.v2.ucPostDiv = post_div;
+			args.v2.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
-			spc2_ptr->ucRefDivSrc = 1;
+			args.v2.ucCRTC = radeon_crtc->crtc_id;
+			args.v2.ucRefDivSrc = 1;
 			break;
 		case 3:
-			if (!encoder)
-				return;
-			spc3_ptr =
-			    (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
-			spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc3_ptr->ucFracFbDiv = frac_fb_div;
-			spc3_ptr->ucPostDiv = post_div;
-			spc3_ptr->ucPpll =
+			args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v3.usRefDiv = cpu_to_le16(ref_div);
+			args.v3.usFbDiv = cpu_to_le16(fb_div);
+			args.v3.ucFracFbDiv = frac_fb_div;
+			args.v3.ucPostDiv = post_div;
+			args.v3.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
-			spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
-			spc3_ptr->ucEncoderMode =
+			args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
+			args.v3.ucTransmitterId = radeon_encoder->encoder_id;
+			args.v3.ucEncoderMode =
 			    atombios_get_encoder_mode(encoder);
 			break;
 		default:
@@ -562,33 +623,43 @@
 		return;
 	}
 
-	printk("executing set pll\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-			   struct drm_framebuffer *old_fb)
+static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			       struct drm_framebuffer *old_fb)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_framebuffer *radeon_fb;
 	struct drm_gem_object *obj;
-	struct drm_radeon_gem_object *obj_priv;
+	struct radeon_bo *rbo;
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+	int r;
 
-	if (!crtc->fb)
-		return -EINVAL;
+	/* no fb bound */
+	if (!crtc->fb) {
+		DRM_DEBUG("No FB bound\n");
+		return 0;
+	}
 
 	radeon_fb = to_radeon_framebuffer(crtc->fb);
 
+	/* Pin framebuffer & get tilling informations */
 	obj = radeon_fb->obj;
-	obj_priv = obj->driver_private;
-
-	if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
+	rbo = obj->driver_private;
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
+	if (unlikely(r != 0)) {
+		radeon_bo_unreserve(rbo);
 		return -EINVAL;
 	}
+	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+	radeon_bo_unreserve(rbo);
 
 	switch (crtc->fb->bits_per_pixel) {
 	case 8:
@@ -618,8 +689,6 @@
 		return -EINVAL;
 	}
 
-	radeon_object_get_tiling_flags(obj->driver_private,
-				       &tiling_flags, NULL);
 	if (tiling_flags & RADEON_TILING_MACRO)
 		fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
 
@@ -674,7 +743,12 @@
 
 	if (old_fb && old_fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(old_fb);
-		radeon_gem_object_unpin(radeon_fb->obj);
+		rbo = radeon_fb->obj->driver_private;
+		r = radeon_bo_reserve(rbo, false);
+		if (unlikely(r != 0))
+			return r;
+		radeon_bo_unpin(rbo);
+		radeon_bo_unreserve(rbo);
 	}
 
 	/* Bytes per pixel may have changed */
@@ -683,6 +757,42 @@
 	return 0;
 }
 
+int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			   struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (ASIC_IS_AVIVO(rdev))
+		return avivo_crtc_set_base(crtc, x, y, old_fb);
+	else
+		return radeon_crtc_set_base(crtc, x, y, old_fb);
+}
+
+/* properly set additional regs when using atombios */
+static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	u32 disp_merge_cntl;
+
+	switch (radeon_crtc->crtc_id) {
+	case 0:
+		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+		break;
+	case 1:
+		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
+		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
+		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
+		break;
+	}
+}
+
 int atombios_crtc_mode_set(struct drm_crtc *crtc,
 			   struct drm_display_mode *mode,
 			   struct drm_display_mode *adjusted_mode,
@@ -704,8 +814,8 @@
 	else {
 		if (radeon_crtc->crtc_id == 0)
 			atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
-		radeon_crtc_set_base(crtc, x, y, old_fb);
-		radeon_legacy_atom_set_surface(crtc);
+		atombios_crtc_set_base(crtc, x, y, old_fb);
+		radeon_legacy_atom_fixup(crtc);
 	}
 	atombios_overscan_setup(crtc, mode, adjusted_mode);
 	atombios_scaler_setup(crtc);
@@ -723,8 +833,8 @@
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 	atombios_lock_crtc(crtc, 1);
+	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rv770.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rv770.c
@@ -92,7 +92,7 @@
 void rv770_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i;
+	int i, r;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -113,8 +113,12 @@
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
 	if (rdev->gart.table.vram.robj) {
-		radeon_object_kunmap(rdev->gart.table.vram.robj);
-		radeon_object_unpin(rdev->gart.table.vram.robj);
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
 	}
 }
 
@@ -167,7 +171,10 @@
 		WREG32((0x2c20 + j), 0x00000000);
 		WREG32((0x2c24 + j), 0x00000000);
 	}
-	WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+	/* r7xx hw bug.  Read from HDP_DEBUG1 rather
+	 * than writing to HDP_REG_COHERENCY_FLUSH_CNTL
+	 */
+	tmp = RREG32(HDP_DEBUG1);
 
 	rv515_mc_stop(rdev, &save);
 	if (r600_mc_wait_for_idle(rdev)) {
@@ -545,9 +552,12 @@
 
 	gb_tiling_config |= BANK_SWAPS(1);
 
-	backend_map = r700_get_tile_pipe_to_backend_map(rdev->config.rv770.max_tile_pipes,
-							rdev->config.rv770.max_backends,
-							(0xff << rdev->config.rv770.max_backends) & 0xff);
+	if (rdev->family == CHIP_RV740)
+		backend_map = 0x28;
+	else
+		backend_map = r700_get_tile_pipe_to_backend_map(rdev->config.rv770.max_tile_pipes,
+								rdev->config.rv770.max_backends,
+								(0xff << rdev->config.rv770.max_backends) & 0xff);
 	gb_tiling_config |= BACKEND_MAP(backend_map);
 
 	cc_gc_shader_pipe_config =
@@ -770,12 +780,59 @@
 
 }
 
+static int rv770_vram_scratch_init(struct radeon_device *rdev)
+{
+	int r;
+	u64 gpu_addr;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
+					true, RADEON_GEM_DOMAIN_VRAM,
+					&rdev->vram_scratch.robj);
+		if (r) {
+			return r;
+		}
+	}
+
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rdev->vram_scratch.robj,
+			  RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+	if (r) {
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+		return r;
+	}
+	r = radeon_bo_kmap(rdev->vram_scratch.robj,
+				(void **)&rdev->vram_scratch.ptr);
+	if (r)
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+	radeon_bo_unreserve(rdev->vram_scratch.robj);
+
+	return r;
+}
+
+static void rv770_vram_scratch_fini(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->vram_scratch.robj == NULL) {
+		return;
+	}
+	r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
+	if (likely(r == 0)) {
+		radeon_bo_kunmap(rdev->vram_scratch.robj);
+		radeon_bo_unpin(rdev->vram_scratch.robj);
+		radeon_bo_unreserve(rdev->vram_scratch.robj);
+	}
+	radeon_bo_unref(&rdev->vram_scratch.robj);
+}
+
 int rv770_mc_init(struct radeon_device *rdev)
 {
 	fixed20_12 a;
 	u32 tmp;
 	int chansize, numchan;
-	int r;
 
 	/* Get VRAM informations */
 	rdev->mc.vram_is_ddr = true;
@@ -818,9 +875,6 @@
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
 
 	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r)
-			return r;
 		/* gtt_size is setup by radeon_agp_init */
 		rdev->mc.gtt_location = rdev->mc.agp_base;
 		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -829,11 +883,11 @@
 		 * AGP so that GPU can catch out of VRAM/AGP access
 		 */
 		if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
-			/* Enought place before */
+			/* Enough place before */
 			rdev->mc.vram_location = rdev->mc.gtt_location -
 							rdev->mc.mc_vram_size;
 		} else if (tmp > rdev->mc.mc_vram_size) {
-			/* Enought place after */
+			/* Enough place after */
 			rdev->mc.vram_location = rdev->mc.gtt_location +
 							rdev->mc.gtt_size;
 		} else {
@@ -870,6 +924,14 @@
 {
 	int r;
 
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+		r = r600_init_microcode(rdev);
+		if (r) {
+			DRM_ERROR("Failed to load firmware!\n");
+			return r;
+		}
+	}
+
 	rv770_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		rv770_agp_enable(rdev);
@@ -878,14 +940,37 @@
 		if (r)
 			return r;
 	}
+	r = rv770_vram_scratch_init(rdev);
+	if (r)
+		return r;
 	rv770_gpu_init(rdev);
-
-	r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
-			      &rdev->r600_blit.shader_gpu_addr);
+	r = r600_blit_init(rdev);
+	if (r) {
+		r600_blit_fini(rdev);
+		rdev->asic->copy = NULL;
+		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
+	}
+	/* pin copy shader into vram */
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (unlikely(r != 0))
+			return r;
+		r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
+				&rdev->r600_blit.shader_gpu_addr);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		if (r) {
+			DRM_ERROR("failed to pin blit object %d\n", r);
+			return r;
+		}
+	}
+	/* Enable IRQ */
+	r = r600_irq_init(rdev);
 	if (r) {
-		DRM_ERROR("failed to pin blit object %d\n", r);
+		DRM_ERROR("radeon: IH init failed (%d).\n", r);
+		radeon_irq_kms_fini(rdev);
 		return r;
 	}
+	r600_irq_set(rdev);
 
 	r = radeon_ring_init(rdev, rdev->cp.ring_size);
 	if (r)
@@ -934,13 +1019,22 @@
 
 int rv770_suspend(struct radeon_device *rdev)
 {
+	int r;
+
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
 	rdev->cp.ready = false;
+	r600_irq_suspend(rdev);
 	r600_wb_disable(rdev);
 	rv770_pcie_gart_disable(rdev);
 	/* unpin shaders bo */
-        radeon_object_unpin(rdev->r600_blit.shader_obj);
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (likely(r == 0)) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
+	}
 	return 0;
 }
 
@@ -975,7 +1069,11 @@
 	if (r)
 		return r;
 	/* Post card if necessary */
-	if (!r600_card_posted(rdev) && rdev->bios) {
+	if (!r600_card_posted(rdev)) {
+		if (!rdev->bios) {
+			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+			return -EINVAL;
+		}
 		DRM_INFO("GPU not posted. posting now...\n");
 		atom_asic_init(rdev->mode_info.atom_context);
 	}
@@ -994,53 +1092,55 @@
 	r = radeon_fence_driver_init(rdev);
 	if (r)
 		return r;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r)
+			radeon_agp_disable(rdev);
+	}
 	r = rv770_mc_init(rdev);
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
+
+	r = radeon_irq_kms_init(rdev);
+	if (r)
+		return r;
+
 	rdev->cp.ring_obj = NULL;
 	r600_ring_init(rdev, 1024 * 1024);
 
-	if (!rdev->me_fw || !rdev->pfp_fw) {
-		r = r600_cp_init_microcode(rdev);
-		if (r) {
-			DRM_ERROR("Failed to load firmware!\n");
-			return r;
-		}
-	}
+	rdev->ih.ring_obj = NULL;
+	r600_ih_ring_init(rdev, 64 * 1024);
 
 	r = r600_pcie_gart_init(rdev);
 	if (r)
 		return r;
 
 	rdev->accel_working = true;
-	r = r600_blit_init(rdev);
-	if (r) {
-		DRM_ERROR("radeon: failled blitter (%d).\n", r);
-		rdev->accel_working = false;
-	}
-
 	r = rv770_startup(rdev);
 	if (r) {
-		rv770_suspend(rdev);
+		dev_err(rdev->dev, "disabling GPU acceleration\n");
+		r600_cp_fini(rdev);
 		r600_wb_fini(rdev);
-		radeon_ring_fini(rdev);
+		r600_irq_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		rv770_pcie_gart_fini(rdev);
 		rdev->accel_working = false;
 	}
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
-			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
 	return 0;
@@ -1048,18 +1148,18 @@
 
 void rv770_fini(struct radeon_device *rdev)
 {
-	rv770_suspend(rdev);
-
 	r600_blit_fini(rdev);
-	radeon_ring_fini(rdev);
+	r600_cp_fini(rdev);
 	r600_wb_fini(rdev);
+	r600_irq_fini(rdev);
+	radeon_irq_kms_fini(rdev);
 	rv770_pcie_gart_fini(rdev);
+	rv770_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_clocks_fini(rdev);
-	if (rdev->flags & RADEON_IS_AGP)
-		radeon_agp_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_agp_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_ioc32.c
@@ -92,8 +92,7 @@
 			  &init->gart_textures_offset))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
 }
 
 typedef struct drm_radeon_clear32 {
@@ -125,8 +124,7 @@
 			  &clr->depth_boxes))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
 }
 
 typedef struct drm_radeon_stipple32 {
@@ -149,8 +147,7 @@
 			  &request->mask))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
 }
 
 typedef struct drm_radeon_tex_image32 {
@@ -204,8 +201,7 @@
 			  &image->data))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
 }
 
 typedef struct drm_radeon_vertex2_32 {
@@ -238,8 +234,7 @@
 			  &request->prim))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
 }
 
 typedef struct drm_radeon_cmd_buffer32 {
@@ -268,8 +263,7 @@
 			  &request->boxes))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
 }
 
 typedef struct drm_radeon_getparam32 {
@@ -293,8 +287,7 @@
 			  &request->value))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
 }
 
 typedef struct drm_radeon_mem_alloc32 {
@@ -322,8 +315,7 @@
 			  &request->region_offset))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
 }
 
 typedef struct drm_radeon_irq_emit32 {
@@ -345,8 +337,7 @@
 			  &request->irq_seq))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
 }
 
 /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
@@ -372,8 +363,7 @@
 			  &request->value))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_dentry->d_inode, file,
-			 DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+	return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
 }
 #else
 #define compat_radeon_cp_setparam NULL
@@ -413,12 +403,10 @@
 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
 		fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-	lock_kernel();		/* XXX for now */
 	if (fn != NULL)
 		ret = (*fn) (filp, cmd, arg);
 	else
-		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+		ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
@@ -431,9 +419,7 @@
 	if (nr < DRM_COMMAND_BASE)
 		return drm_compat_ioctl(filp, cmd, arg);
 
-	lock_kernel();		/* XXX for now */
-	ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+	ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_agp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_agp.c
@@ -144,9 +144,19 @@
 
 	ret = drm_agp_info(rdev->ddev, &info);
 	if (ret) {
+		drm_agp_release(rdev->ddev);
 		DRM_ERROR("Unable to get AGP info: %d\n", ret);
 		return ret;
 	}
+
+	if (rdev->ddev->agp->agp_info.aper_size < 32) {
+		drm_agp_release(rdev->ddev);
+		dev_warn(rdev->dev, "AGP aperture too small (%zuM) "
+			"need at least 32M, disabling AGP\n",
+			rdev->ddev->agp->agp_info.aper_size);
+		return -EINVAL;
+	}
+
 	mode.mode = info.mode;
 	agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode;
 	is_v3 = !!(agp_status & RADEON_AGPv3_MODE);
@@ -221,6 +231,7 @@
 	ret = drm_agp_enable(rdev->ddev, mode);
 	if (ret) {
 		DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+		drm_agp_release(rdev->ddev);
 		return ret;
 	}
 
@@ -252,10 +263,13 @@
 void radeon_agp_fini(struct radeon_device *rdev)
 {
 #if __OS_HAS_AGP
-	if (rdev->flags & RADEON_IS_AGP) {
-		if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
-			drm_agp_release(rdev->ddev);
-		}
+	if (rdev->ddev->agp && rdev->ddev->agp->acquired) {
+		drm_agp_release(rdev->ddev);
 	}
 #endif
 }
+
+void radeon_agp_suspend(struct radeon_device *rdev)
+{
+	radeon_agp_fini(rdev);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_hdmi.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Christian König.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Christian König
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+/*
+ * HDMI color format
+ */
+enum r600_hdmi_color_format {
+	RGB = 0,
+	YCC_422 = 1,
+	YCC_444 = 2
+};
+
+/*
+ * IEC60958 status bits
+ */
+enum r600_hdmi_iec_status_bits {
+	AUDIO_STATUS_DIG_ENABLE   = 0x01,
+	AUDIO_STATUS_V	    = 0x02,
+	AUDIO_STATUS_VCFG	 = 0x04,
+	AUDIO_STATUS_EMPHASIS     = 0x08,
+	AUDIO_STATUS_COPYRIGHT    = 0x10,
+	AUDIO_STATUS_NONAUDIO     = 0x20,
+	AUDIO_STATUS_PROFESSIONAL = 0x40,
+	AUDIO_STATUS_LEVEL	= 0x80
+};
+
+struct {
+	uint32_t Clock;
+
+	int N_32kHz;
+	int CTS_32kHz;
+
+	int N_44_1kHz;
+	int CTS_44_1kHz;
+
+	int N_48kHz;
+	int CTS_48kHz;
+
+} r600_hdmi_ACR[] = {
+    /*	     32kHz	  44.1kHz	48kHz    */
+    /* Clock      N     CTS      N     CTS      N     CTS */
+    {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
+    {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
+    {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
+    {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
+    {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
+    {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
+    {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
+    {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
+    { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
+    { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
+    {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
+};
+
+/*
+ * calculate CTS value if it's not found in the table
+ */
+static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq)
+{
+	if (*CTS == 0)
+		*CTS = clock*N/(128*freq)*1000;
+	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
+		  N, *CTS, freq);
+}
+
+/*
+ * update the N and CTS parameters for a given pixel clock rate
+ */
+static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+	int CTS;
+	int N;
+	int i;
+
+	for (i = 0; r600_hdmi_ACR[i].Clock != clock && r600_hdmi_ACR[i].Clock != 0; i++);
+
+	CTS = r600_hdmi_ACR[i].CTS_32kHz;
+	N = r600_hdmi_ACR[i].N_32kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 32000);
+	WREG32(offset+R600_HDMI_32kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_32kHz_N, N);
+
+	CTS = r600_hdmi_ACR[i].CTS_44_1kHz;
+	N = r600_hdmi_ACR[i].N_44_1kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 44100);
+	WREG32(offset+R600_HDMI_44_1kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_44_1kHz_N, N);
+
+	CTS = r600_hdmi_ACR[i].CTS_48kHz;
+	N = r600_hdmi_ACR[i].N_48kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 48000);
+	WREG32(offset+R600_HDMI_48kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_48kHz_N, N);
+}
+
+/*
+ * calculate the crc for a given info frame
+ */
+static void r600_hdmi_infoframe_checksum(uint8_t packetType,
+					 uint8_t versionNumber,
+					 uint8_t length,
+					 uint8_t *frame)
+{
+    int i;
+    frame[0] = packetType + versionNumber + length;
+    for (i = 1; i <= length; i++)
+	frame[0] += frame[i];
+    frame[0] = 0x100 - frame[0];
+}
+
+/*
+ * build a HDMI Video Info Frame
+ */
+static void r600_hdmi_videoinfoframe(
+	struct drm_encoder *encoder,
+	enum r600_hdmi_color_format color_format,
+	int active_information_present,
+	uint8_t active_format_aspect_ratio,
+	uint8_t scan_information,
+	uint8_t colorimetry,
+	uint8_t ex_colorimetry,
+	uint8_t quantization,
+	int ITC,
+	uint8_t picture_aspect_ratio,
+	uint8_t video_format_identification,
+	uint8_t pixel_repetition,
+	uint8_t non_uniform_picture_scaling,
+	uint8_t bar_info_data_valid,
+	uint16_t top_bar,
+	uint16_t bottom_bar,
+	uint16_t left_bar,
+	uint16_t right_bar
+)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint8_t frame[14];
+
+	frame[0x0] = 0;
+	frame[0x1] =
+		(scan_information & 0x3) |
+		((bar_info_data_valid & 0x3) << 2) |
+		((active_information_present & 0x1) << 4) |
+		((color_format & 0x3) << 5);
+	frame[0x2] =
+		(active_format_aspect_ratio & 0xF) |
+		((picture_aspect_ratio & 0x3) << 4) |
+		((colorimetry & 0x3) << 6);
+	frame[0x3] =
+		(non_uniform_picture_scaling & 0x3) |
+		((quantization & 0x3) << 2) |
+		((ex_colorimetry & 0x7) << 4) |
+		((ITC & 0x1) << 7);
+	frame[0x4] = (video_format_identification & 0x7F);
+	frame[0x5] = (pixel_repetition & 0xF);
+	frame[0x6] = (top_bar & 0xFF);
+	frame[0x7] = (top_bar >> 8);
+	frame[0x8] = (bottom_bar & 0xFF);
+	frame[0x9] = (bottom_bar >> 8);
+	frame[0xA] = (left_bar & 0xFF);
+	frame[0xB] = (left_bar >> 8);
+	frame[0xC] = (right_bar & 0xFF);
+	frame[0xD] = (right_bar >> 8);
+
+	r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
+
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0,
+		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_1,
+		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_2,
+		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_3,
+		frame[0xC] | (frame[0xD] << 8));
+}
+
+/*
+ * build a Audio Info Frame
+ */
+static void r600_hdmi_audioinfoframe(
+	struct drm_encoder *encoder,
+	uint8_t channel_count,
+	uint8_t coding_type,
+	uint8_t sample_size,
+	uint8_t sample_frequency,
+	uint8_t format,
+	uint8_t channel_allocation,
+	uint8_t level_shift,
+	int downmix_inhibit
+)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint8_t frame[11];
+
+	frame[0x0] = 0;
+	frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4);
+	frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2);
+	frame[0x3] = format;
+	frame[0x4] = channel_allocation;
+	frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7);
+	frame[0x6] = 0;
+	frame[0x7] = 0;
+	frame[0x8] = 0;
+	frame[0x9] = 0;
+	frame[0xA] = 0;
+
+	r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
+
+	WREG32(offset+R600_HDMI_AUDIOINFOFRAME_0,
+		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+	WREG32(offset+R600_HDMI_AUDIOINFOFRAME_1,
+		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
+}
+
+/*
+ * test if audio buffer is filled enough to start playing
+ */
+static int r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	return (RREG32(offset+R600_HDMI_STATUS) & 0x10) != 0;
+}
+
+/*
+ * have buffer status changed since last call?
+ */
+int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int status, result;
+
+	if (!radeon_encoder->hdmi_offset)
+		return 0;
+
+	status = r600_hdmi_is_audio_buffer_filled(encoder);
+	result = radeon_encoder->hdmi_buffer_status != status;
+	radeon_encoder->hdmi_buffer_status = status;
+
+	return result;
+}
+
+/*
+ * write the audio workaround status to the hardware
+ */
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t offset = radeon_encoder->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	if (r600_hdmi_is_audio_buffer_filled(encoder)) {
+		/* disable audio workaround and start delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
+
+	} else if (radeon_encoder->hdmi_audio_workaround) {
+		/* enable audio workaround and start delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
+
+	} else {
+		/* disable audio workaround and stop delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00000000, ~0x00001001);
+	}
+}
+
+
+/*
+ * update the info frames with the data from the current display mode
+ */
+void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	r600_audio_set_clock(encoder, mode->clock);
+
+	WREG32(offset+R600_HDMI_UNKNOWN_0, 0x1000);
+	WREG32(offset+R600_HDMI_UNKNOWN_1, 0x0);
+	WREG32(offset+R600_HDMI_UNKNOWN_2, 0x1000);
+
+	r600_hdmi_update_ACR(encoder, mode->clock);
+
+	WREG32(offset+R600_HDMI_VIDEOCNTL, 0x13);
+
+	WREG32(offset+R600_HDMI_VERSION, 0x202);
+
+	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+	/* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001);
+
+	r600_hdmi_audio_workaround(encoder);
+
+	/* audio packets per line, does anyone know how to calc this ? */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
+
+	/* update? reset? don't realy know */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000);
+}
+
+/*
+ * update settings with current parameters from audio engine
+ */
+void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
+				     int channels,
+				     int rate,
+				     int bps,
+				     uint8_t status_bits,
+				     uint8_t category_code)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint32_t iec;
+
+	if (!offset)
+		return;
+
+	DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
+		 r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped",
+		channels, rate, bps);
+	DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
+		  (int)status_bits, (int)category_code);
+
+	iec = 0;
+	if (status_bits & AUDIO_STATUS_PROFESSIONAL)
+		iec |= 1 << 0;
+	if (status_bits & AUDIO_STATUS_NONAUDIO)
+		iec |= 1 << 1;
+	if (status_bits & AUDIO_STATUS_COPYRIGHT)
+		iec |= 1 << 2;
+	if (status_bits & AUDIO_STATUS_EMPHASIS)
+		iec |= 1 << 3;
+
+	iec |= category_code << 8;
+
+	switch (rate) {
+	case  32000: iec |= 0x3 << 24; break;
+	case  44100: iec |= 0x0 << 24; break;
+	case  88200: iec |= 0x8 << 24; break;
+	case 176400: iec |= 0xc << 24; break;
+	case  48000: iec |= 0x2 << 24; break;
+	case  96000: iec |= 0xa << 24; break;
+	case 192000: iec |= 0xe << 24; break;
+	}
+
+	WREG32(offset+R600_HDMI_IEC60958_1, iec);
+
+	iec = 0;
+	switch (bps) {
+	case 16: iec |= 0x2; break;
+	case 20: iec |= 0x3; break;
+	case 24: iec |= 0xb; break;
+	}
+	if (status_bits & AUDIO_STATUS_V)
+		iec |= 0x5 << 16;
+
+	WREG32_P(offset+R600_HDMI_IEC60958_2, iec, ~0x5000f);
+
+	/* 0x021 or 0x031 sets the audio frame length */
+	WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31);
+	r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
+
+	r600_hdmi_audio_workaround(encoder);
+
+	/* update? reset? don't realy know */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
+}
+
+/*
+ * enable/disable the HDMI engine
+ */
+void r600_hdmi_enable(struct drm_encoder *encoder, int enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset);
+
+	/* some version of atombios ignore the enable HDMI flag
+	 * so enabling/disabling HDMI was moved here for TMDS1+2 */
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4);
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4);
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		/* This part is doubtfull in my opinion */
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0);
+		break;
+
+	default:
+		DRM_ERROR("unknown HDMI output type\n");
+		break;
+	}
+}
+
+/*
+ * determin at which register offset the HDMI encoder is
+ */
+void r600_hdmi_init(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		switch (r600_audio_tmds_index(encoder)) {
+		case 0:
+			radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
+			break;
+		case 1:
+			radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
+			break;
+		default:
+			radeon_encoder->hdmi_offset = 0;
+			break;
+		}
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		radeon_encoder->hdmi_offset = R600_HDMI_DIG;
+		break;
+
+	default:
+		radeon_encoder->hdmi_offset = 0;
+		break;
+	}
+
+	DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n",
+		  radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+
+	/* TODO: make this configureable */
+	radeon_encoder->hdmi_audio_workaround = 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_irq.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_irq.c
@@ -289,16 +289,16 @@
 	drm_radeon_irq_emit_t *emit = data;
 	int result;
 
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
-		return -EINVAL;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
 	if (!dev_priv) {
 		DRM_ERROR("called with no initialization\n");
 		return -EINVAL;
 	}
 
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
+		return -EINVAL;
+
+	LOCK_TEST_WITH_RETURN(dev, file_priv);
+
 	result = radeon_emit_irq(dev);
 
 	if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r200.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r200.c
@@ -368,16 +368,21 @@
 		/* 2D, 3D, CUBE */
 		switch (tmp) {
 		case 0:
+		case 3:
+		case 4:
 		case 5:
 		case 6:
 		case 7:
+			/* 1D/2D */
 			track->textures[i].tex_coord_type = 0;
 			break;
 		case 1:
-			track->textures[i].tex_coord_type = 1;
+			/* CUBE */
+			track->textures[i].tex_coord_type = 2;
 			break;
 		case 2:
-			track->textures[i].tex_coord_type = 2;
+			/* 3D */
+			track->textures[i].tex_coord_type = 1;
 			break;
 		}
 		break;
@@ -395,13 +400,15 @@
 			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
 			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
 		}
+		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
+			track->textures[i].lookup_disable = true;
 		switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
 		case R200_TXFORMAT_I8:
 		case R200_TXFORMAT_RGB332:
 		case R200_TXFORMAT_Y8:
 			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
-		case R200_TXFORMAT_DXT1:
 		case R200_TXFORMAT_AI88:
 		case R200_TXFORMAT_ARGB1555:
 		case R200_TXFORMAT_RGB565:
@@ -412,15 +419,24 @@
 		case R200_TXFORMAT_DVDU88:
 		case R200_TXFORMAT_AVYU4444:
 			track->textures[i].cpp = 2;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R200_TXFORMAT_ARGB8888:
 		case R200_TXFORMAT_RGBA8888:
 		case R200_TXFORMAT_ABGR8888:
 		case R200_TXFORMAT_BGR111110:
 		case R200_TXFORMAT_LDVDU8888:
+			track->textures[i].cpp = 4;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
+			break;
+		case R200_TXFORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
 		case R200_TXFORMAT_DXT23:
 		case R200_TXFORMAT_DXT45:
-			track->textures[i].cpp = 4;
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
 			break;
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600d.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600d.h
@@ -196,6 +196,7 @@
 #define	HDP_NONSURFACE_SIZE				0x2C0C
 #define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
 #define	HDP_TILING_CONFIG				0x2F3C
+#define HDP_DEBUG1                                      0x2F34
 
 #define MC_VM_AGP_TOP					0x2184
 #define MC_VM_AGP_BOT					0x2188
@@ -456,7 +457,215 @@
 #define         WAIT_2D_IDLECLEAN_bit                           (1 << 16)
 #define         WAIT_3D_IDLECLEAN_bit                           (1 << 17)
 
-
+#define IH_RB_CNTL                                        0x3e00
+#       define IH_RB_ENABLE                               (1 << 0)
+#       define IH_IB_SIZE(x)                              ((x) << 1) /* log2 */
+#       define IH_RB_FULL_DRAIN_ENABLE                    (1 << 6)
+#       define IH_WPTR_WRITEBACK_ENABLE                   (1 << 8)
+#       define IH_WPTR_WRITEBACK_TIMER(x)                 ((x) << 9) /* log2 */
+#       define IH_WPTR_OVERFLOW_ENABLE                    (1 << 16)
+#       define IH_WPTR_OVERFLOW_CLEAR                     (1 << 31)
+#define IH_RB_BASE                                        0x3e04
+#define IH_RB_RPTR                                        0x3e08
+#define IH_RB_WPTR                                        0x3e0c
+#       define RB_OVERFLOW                                (1 << 0)
+#       define WPTR_OFFSET_MASK                           0x3fffc
+#define IH_RB_WPTR_ADDR_HI                                0x3e10
+#define IH_RB_WPTR_ADDR_LO                                0x3e14
+#define IH_CNTL                                           0x3e18
+#       define ENABLE_INTR                                (1 << 0)
+#       define IH_MC_SWAP(x)                              ((x) << 2)
+#       define IH_MC_SWAP_NONE                            0
+#       define IH_MC_SWAP_16BIT                           1
+#       define IH_MC_SWAP_32BIT                           2
+#       define IH_MC_SWAP_64BIT                           3
+#       define RPTR_REARM                                 (1 << 4)
+#       define MC_WRREQ_CREDIT(x)                         ((x) << 15)
+#       define MC_WR_CLEAN_CNT(x)                         ((x) << 20)
+
+#define RLC_CNTL                                          0x3f00
+#       define RLC_ENABLE                                 (1 << 0)
+#define RLC_HB_BASE                                       0x3f10
+#define RLC_HB_CNTL                                       0x3f0c
+#define RLC_HB_RPTR                                       0x3f20
+#define RLC_HB_WPTR                                       0x3f1c
+#define RLC_HB_WPTR_LSB_ADDR                              0x3f14
+#define RLC_HB_WPTR_MSB_ADDR                              0x3f18
+#define RLC_MC_CNTL                                       0x3f44
+#define RLC_UCODE_CNTL                                    0x3f48
+#define RLC_UCODE_ADDR                                    0x3f2c
+#define RLC_UCODE_DATA                                    0x3f30
+
+#define SRBM_SOFT_RESET                                   0xe60
+#       define SOFT_RESET_RLC                             (1 << 13)
+
+#define CP_INT_CNTL                                       0xc124
+#       define CNTX_BUSY_INT_ENABLE                       (1 << 19)
+#       define CNTX_EMPTY_INT_ENABLE                      (1 << 20)
+#       define SCRATCH_INT_ENABLE                         (1 << 25)
+#       define TIME_STAMP_INT_ENABLE                      (1 << 26)
+#       define IB2_INT_ENABLE                             (1 << 29)
+#       define IB1_INT_ENABLE                             (1 << 30)
+#       define RB_INT_ENABLE                              (1 << 31)
+#define CP_INT_STATUS                                     0xc128
+#       define SCRATCH_INT_STAT                           (1 << 25)
+#       define TIME_STAMP_INT_STAT                        (1 << 26)
+#       define IB2_INT_STAT                               (1 << 29)
+#       define IB1_INT_STAT                               (1 << 30)
+#       define RB_INT_STAT                                (1 << 31)
+
+#define GRBM_INT_CNTL                                     0x8060
+#       define RDERR_INT_ENABLE                           (1 << 0)
+#       define WAIT_COUNT_TIMEOUT_INT_ENABLE              (1 << 1)
+#       define GUI_IDLE_INT_ENABLE                        (1 << 19)
+
+#define INTERRUPT_CNTL                                    0x5468
+#       define IH_DUMMY_RD_OVERRIDE                       (1 << 0)
+#       define IH_DUMMY_RD_EN                             (1 << 1)
+#       define IH_REQ_NONSNOOP_EN                         (1 << 3)
+#       define GEN_IH_INT_EN                              (1 << 8)
+#define INTERRUPT_CNTL2                                   0x546c
+
+#define D1MODE_VBLANK_STATUS                              0x6534
+#define D2MODE_VBLANK_STATUS                              0x6d34
+#       define DxMODE_VBLANK_OCCURRED                     (1 << 0)
+#       define DxMODE_VBLANK_ACK                          (1 << 4)
+#       define DxMODE_VBLANK_STAT                         (1 << 12)
+#       define DxMODE_VBLANK_INTERRUPT                    (1 << 16)
+#       define DxMODE_VBLANK_INTERRUPT_TYPE               (1 << 17)
+#define D1MODE_VLINE_STATUS                               0x653c
+#define D2MODE_VLINE_STATUS                               0x6d3c
+#       define DxMODE_VLINE_OCCURRED                      (1 << 0)
+#       define DxMODE_VLINE_ACK                           (1 << 4)
+#       define DxMODE_VLINE_STAT                          (1 << 12)
+#       define DxMODE_VLINE_INTERRUPT                     (1 << 16)
+#       define DxMODE_VLINE_INTERRUPT_TYPE                (1 << 17)
+#define DxMODE_INT_MASK                                   0x6540
+#       define D1MODE_VBLANK_INT_MASK                     (1 << 0)
+#       define D1MODE_VLINE_INT_MASK                      (1 << 4)
+#       define D2MODE_VBLANK_INT_MASK                     (1 << 8)
+#       define D2MODE_VLINE_INT_MASK                      (1 << 12)
+#define DCE3_DISP_INTERRUPT_STATUS                        0x7ddc
+#       define DC_HPD1_INTERRUPT                          (1 << 18)
+#       define DC_HPD2_INTERRUPT                          (1 << 19)
+#define DISP_INTERRUPT_STATUS                             0x7edc
+#       define LB_D1_VLINE_INTERRUPT                      (1 << 2)
+#       define LB_D2_VLINE_INTERRUPT                      (1 << 3)
+#       define LB_D1_VBLANK_INTERRUPT                     (1 << 4)
+#       define LB_D2_VBLANK_INTERRUPT                     (1 << 5)
+#       define DACA_AUTODETECT_INTERRUPT                  (1 << 16)
+#       define DACB_AUTODETECT_INTERRUPT                  (1 << 17)
+#       define DC_HOT_PLUG_DETECT1_INTERRUPT              (1 << 18)
+#       define DC_HOT_PLUG_DETECT2_INTERRUPT              (1 << 19)
+#       define DC_I2C_SW_DONE_INTERRUPT                   (1 << 20)
+#       define DC_I2C_HW_DONE_INTERRUPT                   (1 << 21)
+#define DISP_INTERRUPT_STATUS_CONTINUE                    0x7ee8
+#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE               0x7de8
+#       define DC_HPD4_INTERRUPT                          (1 << 14)
+#       define DC_HPD4_RX_INTERRUPT                       (1 << 15)
+#       define DC_HPD3_INTERRUPT                          (1 << 28)
+#       define DC_HPD1_RX_INTERRUPT                       (1 << 29)
+#       define DC_HPD2_RX_INTERRUPT                       (1 << 30)
+#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE2              0x7dec
+#       define DC_HPD3_RX_INTERRUPT                       (1 << 0)
+#       define DIGA_DP_VID_STREAM_DISABLE_INTERRUPT       (1 << 1)
+#       define DIGA_DP_STEER_FIFO_OVERFLOW_INTERRUPT      (1 << 2)
+#       define DIGB_DP_VID_STREAM_DISABLE_INTERRUPT       (1 << 3)
+#       define DIGB_DP_STEER_FIFO_OVERFLOW_INTERRUPT      (1 << 4)
+#       define AUX1_SW_DONE_INTERRUPT                     (1 << 5)
+#       define AUX1_LS_DONE_INTERRUPT                     (1 << 6)
+#       define AUX2_SW_DONE_INTERRUPT                     (1 << 7)
+#       define AUX2_LS_DONE_INTERRUPT                     (1 << 8)
+#       define AUX3_SW_DONE_INTERRUPT                     (1 << 9)
+#       define AUX3_LS_DONE_INTERRUPT                     (1 << 10)
+#       define AUX4_SW_DONE_INTERRUPT                     (1 << 11)
+#       define AUX4_LS_DONE_INTERRUPT                     (1 << 12)
+#       define DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT   (1 << 13)
+#       define DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT   (1 << 14)
+/* DCE 3.2 */
+#       define AUX5_SW_DONE_INTERRUPT                     (1 << 15)
+#       define AUX5_LS_DONE_INTERRUPT                     (1 << 16)
+#       define AUX6_SW_DONE_INTERRUPT                     (1 << 17)
+#       define AUX6_LS_DONE_INTERRUPT                     (1 << 18)
+#       define DC_HPD5_INTERRUPT                          (1 << 19)
+#       define DC_HPD5_RX_INTERRUPT                       (1 << 20)
+#       define DC_HPD6_INTERRUPT                          (1 << 21)
+#       define DC_HPD6_RX_INTERRUPT                       (1 << 22)
+
+#define DACA_AUTO_DETECT_CONTROL                          0x7828
+#define DACB_AUTO_DETECT_CONTROL                          0x7a28
+#define DCE3_DACA_AUTO_DETECT_CONTROL                     0x7028
+#define DCE3_DACB_AUTO_DETECT_CONTROL                     0x7128
+#       define DACx_AUTODETECT_MODE(x)                    ((x) << 0)
+#       define DACx_AUTODETECT_MODE_NONE                  0
+#       define DACx_AUTODETECT_MODE_CONNECT               1
+#       define DACx_AUTODETECT_MODE_DISCONNECT            2
+#       define DACx_AUTODETECT_FRAME_TIME_COUNTER(x)      ((x) << 8)
+/* bit 18 = R/C, 17 = G/Y, 16 = B/Comp */
+#       define DACx_AUTODETECT_CHECK_MASK(x)              ((x) << 16)
+
+#define DCE3_DACA_AUTODETECT_INT_CONTROL                  0x7038
+#define DCE3_DACB_AUTODETECT_INT_CONTROL                  0x7138
+#define DACA_AUTODETECT_INT_CONTROL                       0x7838
+#define DACB_AUTODETECT_INT_CONTROL                       0x7a38
+#       define DACx_AUTODETECT_ACK                        (1 << 0)
+#       define DACx_AUTODETECT_INT_ENABLE                 (1 << 16)
+
+#define DC_HOT_PLUG_DETECT1_CONTROL                       0x7d00
+#define DC_HOT_PLUG_DETECT2_CONTROL                       0x7d10
+#define DC_HOT_PLUG_DETECT3_CONTROL                       0x7d24
+#       define DC_HOT_PLUG_DETECTx_EN                     (1 << 0)
+
+#define DC_HOT_PLUG_DETECT1_INT_STATUS                    0x7d04
+#define DC_HOT_PLUG_DETECT2_INT_STATUS                    0x7d14
+#define DC_HOT_PLUG_DETECT3_INT_STATUS                    0x7d28
+#       define DC_HOT_PLUG_DETECTx_INT_STATUS             (1 << 0)
+#       define DC_HOT_PLUG_DETECTx_SENSE                  (1 << 1)
+
+/* DCE 3.0 */
+#define DC_HPD1_INT_STATUS                                0x7d00
+#define DC_HPD2_INT_STATUS                                0x7d0c
+#define DC_HPD3_INT_STATUS                                0x7d18
+#define DC_HPD4_INT_STATUS                                0x7d24
+/* DCE 3.2 */
+#define DC_HPD5_INT_STATUS                                0x7dc0
+#define DC_HPD6_INT_STATUS                                0x7df4
+#       define DC_HPDx_INT_STATUS                         (1 << 0)
+#       define DC_HPDx_SENSE                              (1 << 1)
+#       define DC_HPDx_RX_INT_STATUS                      (1 << 8)
+
+#define DC_HOT_PLUG_DETECT1_INT_CONTROL                   0x7d08
+#define DC_HOT_PLUG_DETECT2_INT_CONTROL                   0x7d18
+#define DC_HOT_PLUG_DETECT3_INT_CONTROL                   0x7d2c
+#       define DC_HOT_PLUG_DETECTx_INT_ACK                (1 << 0)
+#       define DC_HOT_PLUG_DETECTx_INT_POLARITY           (1 << 8)
+#       define DC_HOT_PLUG_DETECTx_INT_EN                 (1 << 16)
+/* DCE 3.0 */
+#define DC_HPD1_INT_CONTROL                               0x7d04
+#define DC_HPD2_INT_CONTROL                               0x7d10
+#define DC_HPD3_INT_CONTROL                               0x7d1c
+#define DC_HPD4_INT_CONTROL                               0x7d28
+/* DCE 3.2 */
+#define DC_HPD5_INT_CONTROL                               0x7dc4
+#define DC_HPD6_INT_CONTROL                               0x7df8
+#       define DC_HPDx_INT_ACK                            (1 << 0)
+#       define DC_HPDx_INT_POLARITY                       (1 << 8)
+#       define DC_HPDx_INT_EN                             (1 << 16)
+#       define DC_HPDx_RX_INT_ACK                         (1 << 20)
+#       define DC_HPDx_RX_INT_EN                          (1 << 24)
+
+/* DCE 3.0 */
+#define DC_HPD1_CONTROL                                   0x7d08
+#define DC_HPD2_CONTROL                                   0x7d14
+#define DC_HPD3_CONTROL                                   0x7d20
+#define DC_HPD4_CONTROL                                   0x7d2c
+/* DCE 3.2 */
+#define DC_HPD5_CONTROL                                   0x7dc8
+#define DC_HPD6_CONTROL                                   0x7dfc
+#       define DC_HPDx_CONNECTION_TIMER(x)                ((x) << 0)
+#       define DC_HPDx_RX_INT_TIMER(x)                    ((x) << 16)
+/* DCE 3.2 */
+#       define DC_HPDx_EN                                 (1 << 28)
 
 /*
  * PM4
@@ -500,7 +709,6 @@
 #define	PACKET3_WAIT_REG_MEM				0x3C
 #define	PACKET3_MEM_WRITE				0x3D
 #define	PACKET3_INDIRECT_BUFFER				0x32
-#define	PACKET3_CP_INTERRUPT				0x40
 #define	PACKET3_SURFACE_SYNC				0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_TC_ACTION_ENA        (1 << 23)
@@ -674,4 +882,30 @@
 #define		S_000E60_SOFT_RESET_TSC(x)		(((x) & 1) << 16)
 #define		S_000E60_SOFT_RESET_VMC(x)		(((x) & 1) << 17)
 
+#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL		0x5480
+
+#define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
+#define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280E0_BASE_256B                           0x00000000
+#define R_0280E4_CB_COLOR1_FRAG                      0x0280E4
+#define R_0280E8_CB_COLOR2_FRAG                      0x0280E8
+#define R_0280EC_CB_COLOR3_FRAG                      0x0280EC
+#define R_0280F0_CB_COLOR4_FRAG                      0x0280F0
+#define R_0280F4_CB_COLOR5_FRAG                      0x0280F4
+#define R_0280F8_CB_COLOR6_FRAG                      0x0280F8
+#define R_0280FC_CB_COLOR7_FRAG                      0x0280FC
+#define R_0280C0_CB_COLOR0_TILE                      0x0280C0
+#define   S_0280C0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280C0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280C0_BASE_256B                           0x00000000
+#define R_0280C4_CB_COLOR1_TILE                      0x0280C4
+#define R_0280C8_CB_COLOR2_TILE                      0x0280C8
+#define R_0280CC_CB_COLOR3_TILE                      0x0280CC
+#define R_0280D0_CB_COLOR4_TILE                      0x0280D0
+#define R_0280D4_CB_COLOR5_TILE                      0x0280D4
+#define R_0280D8_CB_COLOR6_TILE                      0x0280D8
+#define R_0280DC_CB_COLOR7_TILE                      0x0280DC
+
+
 #endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_connectors.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -40,6 +40,28 @@
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+void radeon_connector_hotplug(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+	if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
+
+	if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+	    (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
+		if ((radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+		    (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_eDP)) {
+			if (radeon_dp_needs_link_train(radeon_connector)) {
+				if (connector->encoder)
+					dp_link_train(connector->encoder, connector);
+			}
+		}
+	}
+
+}
+
 static void radeon_property_change_mode(struct drm_encoder *encoder)
 {
 	struct drm_crtc *crtc = encoder->crtc;
@@ -140,12 +162,14 @@
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_connector *conflict;
+	struct radeon_connector *radeon_conflict;
 	int i;
 
 	list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
 		if (conflict == connector)
 			continue;
 
+		radeon_conflict = to_radeon_connector(conflict);
 		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 			if (conflict->encoder_ids[i] == 0)
 				break;
@@ -155,6 +179,9 @@
 				if (conflict->status != connector_status_connected)
 					continue;
 
+				if (radeon_conflict->use_digital)
+					continue;
+
 				if (priority == true) {
 					DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict));
 					DRM_INFO("in favor of %s\n", drm_get_connector_name(connector));
@@ -188,6 +215,18 @@
 		drm_mode_set_name(mode);
 
 		DRM_DEBUG("Adding native panel mode %s\n", mode->name);
+	} else if (native_mode->hdisplay != 0 &&
+		   native_mode->vdisplay != 0) {
+		/* mac laptops without an edid */
+		/* Note that this is not necessarily the exact panel mode,
+		 * but an approximation based on the cvt formula.  For these
+		 * systems we should ideally read the mode info out of the
+		 * registers or add a mode table, but this works and is much
+		 * simpler.
+		 */
+		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
+		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+		DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name);
 	}
 	return mode;
 }
@@ -281,7 +320,7 @@
 		radeon_encoder = to_radeon_encoder(encoder);
 		if (!radeon_encoder->enc_priv)
 			return 0;
-		if (rdev->is_atom_bios) {
+		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) {
 			struct radeon_encoder_atom_dac *dac_int;
 			dac_int = radeon_encoder->enc_priv;
 			dac_int->tv_std = val;
@@ -445,10 +484,10 @@
 		ret = connector_status_connected;
 	else {
 		if (radeon_connector->ddc_bus) {
-			radeon_i2c_do_lock(radeon_connector, 1);
+			radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
 							      &radeon_connector->ddc_bus->adapter);
-			radeon_i2c_do_lock(radeon_connector, 0);
+			radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 			if (radeon_connector->edid)
 				ret = connector_status_connected;
 		}
@@ -546,24 +585,26 @@
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder;
 	struct drm_encoder_helper_funcs *encoder_funcs;
-	bool dret;
+	bool dret = false;
 	enum drm_connector_status ret = connector_status_disconnected;
 
 	encoder = radeon_best_single_encoder(connector);
 	if (!encoder)
 		ret = connector_status_disconnected;
 
-	radeon_i2c_do_lock(radeon_connector, 1);
-	dret = radeon_ddc_probe(radeon_connector);
-	radeon_i2c_do_lock(radeon_connector, 0);
+	if (radeon_connector->ddc_bus) {
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
+		dret = radeon_ddc_probe(radeon_connector);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
 		}
-		radeon_i2c_do_lock(radeon_connector, 1);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector, 0);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
@@ -583,7 +624,7 @@
 				ret = connector_status_connected;
 		}
 	} else {
-		if (radeon_connector->dac_load_detect) {
+		if (radeon_connector->dac_load_detect && encoder) {
 			encoder_funcs = encoder->helper_private;
 			ret = encoder_funcs->detect(encoder, connector);
 		}
@@ -706,19 +747,21 @@
 	struct drm_mode_object *obj;
 	int i;
 	enum drm_connector_status ret = connector_status_disconnected;
-	bool dret;
+	bool dret = false;
 
-	radeon_i2c_do_lock(radeon_connector, 1);
-	dret = radeon_ddc_probe(radeon_connector);
-	radeon_i2c_do_lock(radeon_connector, 0);
+	if (radeon_connector->ddc_bus) {
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
+		dret = radeon_ddc_probe(radeon_connector);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
 		}
-		radeon_i2c_do_lock(radeon_connector, 1);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector, 0);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
@@ -735,6 +778,36 @@
 				ret = connector_status_disconnected;
 			} else
 				ret = connector_status_connected;
+
+			/* This gets complicated.  We have boards with VGA + HDMI with a
+			 * shared DDC line and we have boards with DVI-D + HDMI with a shared
+			 * DDC line.  The latter is more complex because with DVI<->HDMI adapters
+			 * you don't really know what's connected to which port as both are digital.
+			 */
+			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
+				struct drm_device *dev = connector->dev;
+				struct radeon_device *rdev = dev->dev_private;
+				struct drm_connector *list_connector;
+				struct radeon_connector *list_radeon_connector;
+				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
+					if (connector == list_connector)
+						continue;
+					list_radeon_connector = to_radeon_connector(list_connector);
+					if (list_radeon_connector->shared_ddc &&
+					    (list_radeon_connector->ddc_bus->rec.i2c_id ==
+					     radeon_connector->ddc_bus->rec.i2c_id)) {
+						/* cases where both connectors are digital */
+						if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
+							/* hpd is our only option in this case */
+							if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
+								kfree(radeon_connector->edid);
+								radeon_connector->edid = NULL;
+								ret = connector_status_disconnected;
+							}
+						}
+					}
+				}
+			}
 		}
 	}
 
@@ -833,10 +906,18 @@
 static int radeon_dvi_mode_valid(struct drm_connector *connector,
 				  struct drm_display_mode *mode)
 {
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
 	/* XXX check mode bandwidth */
 
+	/* clocks over 135 MHz have heat issues with DVI on RV100 */
+	if (radeon_connector->use_digital &&
+	    (rdev->family == CHIP_RV100) &&
+	    (mode->clock > 135000))
+		return MODE_CLOCK_HIGH;
+
 	if (radeon_connector->use_digital && (mode->clock > 165000)) {
 		if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
@@ -863,6 +944,93 @@
 	.force = radeon_dvi_force,
 };
 
+static void radeon_dp_connector_destroy(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+
+	if (radeon_connector->ddc_bus)
+		radeon_i2c_destroy(radeon_connector->ddc_bus);
+	if (radeon_connector->edid)
+		kfree(radeon_connector->edid);
+	if (radeon_dig_connector->dp_i2c_bus)
+		radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
+	kfree(radeon_connector->con_priv);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static int radeon_dp_get_modes(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	int ret;
+
+	ret = radeon_ddc_get_modes(radeon_connector);
+	return ret;
+}
+
+static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	enum drm_connector_status ret = connector_status_disconnected;
+	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+	u8 sink_type;
+
+	if (radeon_connector->edid) {
+		kfree(radeon_connector->edid);
+		radeon_connector->edid = NULL;
+	}
+
+	sink_type = radeon_dp_getsinktype(radeon_connector);
+	if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+	    (sink_type == CONNECTOR_OBJECT_ID_eDP)) {
+		if (radeon_dp_getdpcd(radeon_connector)) {
+			radeon_dig_connector->dp_sink_type = sink_type;
+			ret = connector_status_connected;
+		}
+	} else {
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
+		if (radeon_ddc_probe(radeon_connector)) {
+			radeon_dig_connector->dp_sink_type = sink_type;
+			ret = connector_status_connected;
+		}
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
+	}
+
+	return ret;
+}
+
+static int radeon_dp_mode_valid(struct drm_connector *connector,
+				  struct drm_display_mode *mode)
+{
+	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+
+	/* XXX check mode bandwidth */
+
+	if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+	    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+		return radeon_dp_mode_valid_helper(radeon_connector, mode);
+	else
+		return MODE_OK;
+}
+
+struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
+	.get_modes = radeon_dp_get_modes,
+	.mode_valid = radeon_dp_mode_valid,
+	.best_encoder = radeon_dvi_encoder,
+};
+
+struct drm_connector_funcs radeon_dp_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = radeon_dp_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = radeon_connector_set_property,
+	.destroy = radeon_dp_connector_destroy,
+	.force = radeon_dvi_force,
+};
+
 void
 radeon_add_atom_connector(struct drm_device *dev,
 			  uint32_t connector_id,
@@ -871,7 +1039,8 @@
 			  struct radeon_i2c_bus_rec *i2c_bus,
 			  bool linkb,
 			  uint32_t igp_lane_info,
-			  uint16_t connector_object_id)
+			  uint16_t connector_object_id,
+			  struct radeon_hpd *hpd)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
@@ -893,8 +1062,7 @@
 			return;
 		}
 		if (radeon_connector->ddc_bus && i2c_bus->valid) {
-			if (memcmp(&radeon_connector->ddc_bus->rec, i2c_bus,
-				    sizeof(struct radeon_i2c_bus_rec)) == 0) {
+			if (radeon_connector->ddc_bus->rec.i2c_id == i2c_bus->i2c_id) {
 				radeon_connector->shared_ddc = true;
 				shared_ddc = true;
 			}
@@ -911,6 +1079,7 @@
 	radeon_connector->devices = supported_device;
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
+	radeon_connector->hpd = *hpd;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -926,6 +1095,8 @@
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.load_detect_property,
 					      1);
+		connector->interlace_allowed = true;
+		connector->doublescan_allowed = true;
 		break;
 	case DRM_MODE_CONNECTOR_DVIA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -941,6 +1112,8 @@
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.load_detect_property,
 					      1);
+		connector->interlace_allowed = true;
+		connector->doublescan_allowed = true;
 		break;
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_DVID:
@@ -963,10 +1136,17 @@
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.coherent_mode_property,
 					      1);
-		radeon_connector->dac_load_detect = true;
-		drm_connector_attach_property(&radeon_connector->base,
-					      rdev->mode_info.load_detect_property,
-					      1);
+		if (connector_type == DRM_MODE_CONNECTOR_DVII) {
+			radeon_connector->dac_load_detect = true;
+			drm_connector_attach_property(&radeon_connector->base,
+						      rdev->mode_info.load_detect_property,
+						      1);
+		}
+		connector->interlace_allowed = true;
+		if (connector_type == DRM_MODE_CONNECTOR_DVII)
+			connector->doublescan_allowed = true;
+		else
+			connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_HDMIA:
 	case DRM_MODE_CONNECTOR_HDMIB:
@@ -989,24 +1169,46 @@
 					      rdev->mode_info.coherent_mode_property,
 					      1);
 		subpixel_order = SubPixelHorizontalRGB;
+		connector->interlace_allowed = true;
+		if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
+			connector->doublescan_allowed = true;
+		else
+			connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_DisplayPort:
+	case DRM_MODE_CONNECTOR_eDP:
 		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
 		if (!radeon_dig_connector)
 			goto failed;
 		radeon_dig_connector->linkb = linkb;
 		radeon_dig_connector->igp_lane_info = igp_lane_info;
 		radeon_connector->con_priv = radeon_dig_connector;
-		drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
-		ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+		drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
+		ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
 		if (ret)
 			goto failed;
 		if (i2c_bus->valid) {
-			radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
+			/* add DP i2c bus */
+			if (connector_type == DRM_MODE_CONNECTOR_eDP)
+				radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
+			else
+				radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
+			if (!radeon_dig_connector->dp_i2c_bus)
+				goto failed;
+			if (connector_type == DRM_MODE_CONNECTOR_eDP)
+				radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP");
+			else
+				radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
 			if (!radeon_connector->ddc_bus)
 				goto failed;
 		}
 		subpixel_order = SubPixelHorizontalRGB;
+		drm_connector_attach_property(&radeon_connector->base,
+					      rdev->mode_info.coherent_mode_property,
+					      1);
+		connector->interlace_allowed = true;
+		/* in theory with a DP to VGA converter... */
+		connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_SVIDEO:
 	case DRM_MODE_CONNECTOR_Composite:
@@ -1020,7 +1222,12 @@
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.load_detect_property,
 						      1);
+			drm_connector_attach_property(&radeon_connector->base,
+						      rdev->mode_info.tv_std_property,
+						      radeon_atombios_get_tv_info(rdev));
 		}
+		connector->interlace_allowed = false;
+		connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_LVDS:
 		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
@@ -1038,11 +1245,12 @@
 			if (!radeon_connector->ddc_bus)
 				goto failed;
 		}
-		drm_mode_create_scaling_mode_property(dev);
 		drm_connector_attach_property(&radeon_connector->base,
 					      dev->mode_config.scaling_mode_property,
 					      DRM_MODE_SCALE_FULLSCREEN);
 		subpixel_order = SubPixelHorizontalRGB;
+		connector->interlace_allowed = false;
+		connector->doublescan_allowed = false;
 		break;
 	}
 
@@ -1063,7 +1271,8 @@
 			    uint32_t supported_device,
 			    int connector_type,
 			    struct radeon_i2c_bus_rec *i2c_bus,
-			    uint16_t connector_object_id)
+			    uint16_t connector_object_id,
+			    struct radeon_hpd *hpd)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_connector *connector;
@@ -1093,6 +1302,7 @@
 	radeon_connector->connector_id = connector_id;
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
+	radeon_connector->hpd = *hpd;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1108,6 +1318,8 @@
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.load_detect_property,
 					      1);
+		connector->interlace_allowed = true;
+		connector->doublescan_allowed = true;
 		break;
 	case DRM_MODE_CONNECTOR_DVIA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
@@ -1123,6 +1335,8 @@
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.load_detect_property,
 					      1);
+		connector->interlace_allowed = true;
+		connector->doublescan_allowed = true;
 		break;
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_DVID:
@@ -1140,6 +1354,11 @@
 						      1);
 		}
 		subpixel_order = SubPixelHorizontalRGB;
+		connector->interlace_allowed = true;
+		if (connector_type == DRM_MODE_CONNECTOR_DVII)
+			connector->doublescan_allowed = true;
+		else
+			connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_SVIDEO:
 	case DRM_MODE_CONNECTOR_Composite:
@@ -1159,8 +1378,13 @@
 				radeon_connector->dac_load_detect = false;
 			drm_connector_attach_property(&radeon_connector->base,
 						      rdev->mode_info.load_detect_property,
-						      1);
+						      radeon_connector->dac_load_detect);
+			drm_connector_attach_property(&radeon_connector->base,
+						      rdev->mode_info.tv_std_property,
+						      radeon_combios_get_tv_info(rdev));
 		}
+		connector->interlace_allowed = false;
+		connector->doublescan_allowed = false;
 		break;
 	case DRM_MODE_CONNECTOR_LVDS:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
@@ -1176,6 +1400,8 @@
 					      dev->mode_config.scaling_mode_property,
 					      DRM_MODE_SCALE_FULLSCREEN);
 		subpixel_order = SubPixelHorizontalRGB;
+		connector->interlace_allowed = false;
+		connector->doublescan_allowed = false;
 		break;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_cp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_cp.c
@@ -417,8 +417,9 @@
 	return -EBUSY;
 }
 
-static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
+static void radeon_init_pipes(struct drm_device *dev)
 {
+	drm_radeon_private_t *dev_priv = dev->dev_private;
 	uint32_t gb_tile_config, gb_pipe_sel = 0;
 
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
@@ -436,11 +437,12 @@
 		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
 	} else {
 		/* R3xx */
-		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 &&
+		     dev->pdev->device != 0x4144) ||
 		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
 			dev_priv->num_gb_pipes = 2;
 		} else {
-			/* R3Vxx */
+			/* RV3xx/R300 AD */
 			dev_priv->num_gb_pipes = 1;
 		}
 	}
@@ -736,7 +738,7 @@
 
 	/* setup the raster pipes */
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
-	    radeon_init_pipes(dev_priv);
+	    radeon_init_pipes(dev);
 
 	/* Reset the CP ring */
 	radeon_do_cp_reset(dev_priv);
@@ -1644,6 +1646,7 @@
 	radeon_cp_load_microcode(dev_priv);
 	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 
+	dev_priv->have_z_offset = 0;
 	radeon_do_engine_reset(dev);
 	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 
@@ -1941,8 +1944,8 @@
 	for (t = 0; t < dev_priv->usec_timeout; t++) {
 		u32 done_age = GET_SCRATCH(dev_priv, 1);
 		DRM_DEBUG("done_age = %d\n", done_age);
-		for (i = start; i < dma->buf_count; i++) {
-			buf = dma->buflist[i];
+		for (i = 0; i < dma->buf_count; i++) {
+			buf = dma->buflist[start];
 			buf_priv = buf->dev_private;
 			if (buf->file_priv == NULL || (buf->pending &&
 						       buf_priv->age <=
@@ -1951,7 +1954,8 @@
 				buf->pending = 0;
 				return buf;
 			}
-			start = 0;
+			if (++start >= dma->buf_count)
+				start = 0;
 		}
 
 		if (t) {
@@ -1960,46 +1964,8 @@
 		}
 	}
 
-	DRM_DEBUG("returning NULL!\n");
-	return NULL;
-}
-
-#if 0
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_radeon_buf_priv_t *buf_priv;
-	struct drm_buf *buf;
-	int i, t;
-	int start;
-	u32 done_age;
-
-	done_age = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
-	if (++dev_priv->last_buf >= dma->buf_count)
-		dev_priv->last_buf = 0;
-
-	start = dev_priv->last_buf;
-	dev_priv->stats.freelist_loops++;
-
-	for (t = 0; t < 2; t++) {
-		for (i = start; i < dma->buf_count; i++) {
-			buf = dma->buflist[i];
-			buf_priv = buf->dev_private;
-			if (buf->file_priv == 0 || (buf->pending &&
-						    buf_priv->age <=
-						    done_age)) {
-				dev_priv->stats.requested_bufs++;
-				buf->pending = 0;
-				return buf;
-			}
-		}
-		start = 0;
-	}
-
 	return NULL;
 }
-#endif
 
 void radeon_freelist_reset(struct drm_device * dev)
 {
@@ -2182,6 +2148,7 @@
 			 &master_priv->sarea);
 	if (ret) {
 		DRM_ERROR("SAREA setup failed\n");
+		kfree(master_priv);
 		return ret;
 	}
 	master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rv770d.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rv770d.h
@@ -128,6 +128,7 @@
 #define	HDP_NONSURFACE_SIZE				0x2C0C
 #define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
 #define	HDP_TILING_CONFIG				0x2F3C
+#define HDP_DEBUG1                                      0x2F34
 
 #define MC_SHARED_CHMAP						0x2004
 #define		NOOFCHAN_SHIFT					12
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_legacy_tv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_legacy_tv.c
@@ -57,6 +57,10 @@
 #define NTSC_TV_PLL_N_14 693
 #define NTSC_TV_PLL_P_14 7
 
+#define PAL_TV_PLL_M_14 19
+#define PAL_TV_PLL_N_14 353
+#define PAL_TV_PLL_P_14 5
+
 #define VERT_LEAD_IN_LINES 2
 #define FRAC_BITS 0xe
 #define FRAC_MASK 0x3fff
@@ -77,7 +81,7 @@
 	unsigned pix_to_tv;
 };
 
-static const uint16_t hor_timing_NTSC[] = {
+static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = {
 	0x0007,
 	0x003f,
 	0x0263,
@@ -98,7 +102,7 @@
 	0
 };
 
-static const uint16_t vert_timing_NTSC[] = {
+static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = {
 	0x2001,
 	0x200d,
 	0x1006,
@@ -115,7 +119,7 @@
 	0
 };
 
-static const uint16_t hor_timing_PAL[] = {
+static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = {
 	0x0007,
 	0x0058,
 	0x027c,
@@ -136,7 +140,7 @@
 	0
 };
 
-static const uint16_t vert_timing_PAL[] = 	{
+static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = {
 	0x2001,
 	0x200c,
 	0x1005,
@@ -205,9 +209,24 @@
 		630627,             /* defRestart */
 		347,                /* crtcPLL_N */
 		14,                 /* crtcPLL_M */
-			8,                  /* crtcPLL_postDiv */
+		8,                  /* crtcPLL_postDiv */
 		1022,               /* pixToTV */
 	},
+	{ /* PAL timing for 14 Mhz ref clk */
+		800,                /* horResolution */
+		600,                /* verResolution */
+		TV_STD_PAL,         /* standard */
+		1131,               /* horTotal */
+		742,                /* verTotal */
+		813,                /* horStart */
+		840,                /* horSyncStart */
+		633,                /* verSyncStart */
+		708369,             /* defRestart */
+		211,                /* crtcPLL_N */
+		9,                  /* crtcPLL_M */
+		8,                  /* crtcPLL_postDiv */
+		759,                /* pixToTV */
+	},
 };
 
 #define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
@@ -242,7 +261,7 @@
 		if (pll->reference_freq == 2700)
 			const_ptr = &available_tv_modes[1];
 		else
-			const_ptr = &available_tv_modes[1]; /* FIX ME */
+			const_ptr = &available_tv_modes[3];
 	}
 	return const_ptr;
 }
@@ -625,7 +644,7 @@
 
 	if (flicker_removal < 3)
 		flicker_removal = 3;
-	for (i = 0; i < 6; ++i) {
+	for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) {
 		if (flicker_removal == SLOPE_limit[i])
 			break;
 	}
@@ -685,9 +704,9 @@
 			n = PAL_TV_PLL_N_27;
 			p = PAL_TV_PLL_P_27;
 		} else {
-			m = PAL_TV_PLL_M_27;
-			n = PAL_TV_PLL_N_27;
-			p = PAL_TV_PLL_P_27;
+			m = PAL_TV_PLL_M_14;
+			n = PAL_TV_PLL_N_14;
+			p = PAL_TV_PLL_P_14;
 		}
 	}
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_display.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_display.c
@@ -234,7 +234,7 @@
 	"INTERNAL_UNIPHY2",
 };
 
-static const char *connector_names[13] = {
+static const char *connector_names[15] = {
 	"Unknown",
 	"VGA",
 	"DVI-I",
@@ -248,6 +248,18 @@
 	"DisplayPort",
 	"HDMI-A",
 	"HDMI-B",
+	"TV",
+	"eDP",
+};
+
+static const char *hpd_names[7] = {
+	"NONE",
+	"HPD1",
+	"HPD2",
+	"HPD3",
+	"HPD4",
+	"HPD5",
+	"HPD6",
 };
 
 static void radeon_print_display_setup(struct drm_device *dev)
@@ -264,16 +276,27 @@
 		radeon_connector = to_radeon_connector(connector);
 		DRM_INFO("Connector %d:\n", i);
 		DRM_INFO("  %s\n", connector_names[connector->connector_type]);
-		if (radeon_connector->ddc_bus)
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			DRM_INFO("  %s\n", hpd_names[radeon_connector->hpd.hpd]);
+		if (radeon_connector->ddc_bus) {
 			DRM_INFO("  DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
 				 radeon_connector->ddc_bus->rec.mask_clk_reg,
 				 radeon_connector->ddc_bus->rec.mask_data_reg,
 				 radeon_connector->ddc_bus->rec.a_clk_reg,
 				 radeon_connector->ddc_bus->rec.a_data_reg,
-				 radeon_connector->ddc_bus->rec.put_clk_reg,
-				 radeon_connector->ddc_bus->rec.put_data_reg,
-				 radeon_connector->ddc_bus->rec.get_clk_reg,
-				 radeon_connector->ddc_bus->rec.get_data_reg);
+				 radeon_connector->ddc_bus->rec.en_clk_reg,
+				 radeon_connector->ddc_bus->rec.en_data_reg,
+				 radeon_connector->ddc_bus->rec.y_clk_reg,
+				 radeon_connector->ddc_bus->rec.y_data_reg);
+		} else {
+			if (connector->connector_type == DRM_MODE_CONNECTOR_VGA ||
+			    connector->connector_type == DRM_MODE_CONNECTOR_DVII ||
+			    connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+			    connector->connector_type == DRM_MODE_CONNECTOR_DVIA ||
+			    connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+			    connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)
+				DRM_INFO("  DDC: no ddc bus - possible BIOS bug - please report to xorg-driver-ati@lists.x.org\n");
+		}
 		DRM_INFO("  Encoders:\n");
 		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 			radeon_encoder = to_radeon_encoder(encoder);
@@ -317,13 +340,17 @@
 				ret = radeon_get_atom_connector_info_from_object_table(dev);
 			else
 				ret = radeon_get_atom_connector_info_from_supported_devices_table(dev);
-		} else
+		} else {
 			ret = radeon_get_legacy_connector_info_from_bios(dev);
+			if (ret == false)
+				ret = radeon_get_legacy_connector_info_from_table(dev);
+		}
 	} else {
 		if (!ASIC_IS_AVIVO(rdev))
 			ret = radeon_get_legacy_connector_info_from_table(dev);
 	}
 	if (ret) {
+		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
@@ -336,12 +363,19 @@
 {
 	int ret = 0;
 
+	if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+	    (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
+		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
+		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
+		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
+			radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
+	}
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	if (!radeon_connector->edid) {
-		radeon_i2c_do_lock(radeon_connector, 1);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector, 0);
+		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 	}
 
 	if (radeon_connector->edid) {
@@ -361,9 +395,9 @@
 
 	if (!radeon_connector->ddc_bus)
 		return -1;
-	radeon_i2c_do_lock(radeon_connector, 1);
+	radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
-	radeon_i2c_do_lock(radeon_connector, 0);
+	radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 	if (edid) {
 		kfree(edid);
 	}
@@ -380,17 +414,18 @@
 	return n;
 }
 
-void radeon_compute_pll(struct radeon_pll *pll,
-			uint64_t freq,
-			uint32_t *dot_clock_p,
-			uint32_t *fb_div_p,
-			uint32_t *frac_fb_div_p,
-			uint32_t *ref_div_p,
-			uint32_t *post_div_p,
-			int flags)
+static void radeon_compute_pll_legacy(struct radeon_pll *pll,
+				      uint64_t freq,
+				      uint32_t *dot_clock_p,
+				      uint32_t *fb_div_p,
+				      uint32_t *frac_fb_div_p,
+				      uint32_t *ref_div_p,
+				      uint32_t *post_div_p)
 {
 	uint32_t min_ref_div = pll->min_ref_div;
 	uint32_t max_ref_div = pll->max_ref_div;
+	uint32_t min_post_div = pll->min_post_div;
+	uint32_t max_post_div = pll->max_post_div;
 	uint32_t min_fractional_feed_div = 0;
 	uint32_t max_fractional_feed_div = 0;
 	uint32_t best_vco = pll->best_vco;
@@ -406,7 +441,7 @@
 	DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
 	freq = freq * 1000;
 
-	if (flags & RADEON_PLL_USE_REF_DIV)
+	if (pll->flags & RADEON_PLL_USE_REF_DIV)
 		min_ref_div = max_ref_div = pll->reference_div;
 	else {
 		while (min_ref_div < max_ref_div-1) {
@@ -421,19 +456,22 @@
 		}
 	}
 
-	if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+	if (pll->flags & RADEON_PLL_USE_POST_DIV)
+		min_post_div = max_post_div = pll->post_div;
+
+	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
 		min_fractional_feed_div = pll->min_frac_feedback_div;
 		max_fractional_feed_div = pll->max_frac_feedback_div;
 	}
 
-	for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
+	for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
 		uint32_t ref_div;
 
-		if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+		if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
 			continue;
 
 		/* legacy radeons only have a few post_divs */
-		if (flags & RADEON_PLL_LEGACY) {
+		if (pll->flags & RADEON_PLL_LEGACY) {
 			if ((post_div == 5) ||
 			    (post_div == 7) ||
 			    (post_div == 9) ||
@@ -480,7 +518,7 @@
 					tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
 					current_freq = radeon_div(tmp, ref_div * post_div);
 
-					if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+					if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
 						error = freq - current_freq;
 						error = error < 0 ? 0xffffffff : error;
 					} else
@@ -507,12 +545,12 @@
 							best_freq = current_freq;
 							best_error = error;
 							best_vco_diff = vco_diff;
-						} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
-							   ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
-							   ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+						} else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
 							best_post_div = post_div;
 							best_ref_div = ref_div;
 							best_feedback_div = feedback_div;
@@ -540,6 +578,200 @@
 	*frac_fb_div_p = best_frac_feedback_div;
 	*ref_div_p = best_ref_div;
 	*post_div_p = best_post_div;
+	DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
+		      freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div,
+		      best_ref_div, best_post_div);
+
+}
+
+static bool
+calc_fb_div(struct radeon_pll *pll,
+	    uint32_t freq,
+            uint32_t post_div,
+            uint32_t ref_div,
+            uint32_t *fb_div,
+            uint32_t *fb_div_frac)
+{
+	fixed20_12 feedback_divider, a, b;
+	u32 vco_freq;
+
+	vco_freq = freq * post_div;
+	/* feedback_divider = vco_freq * ref_div / pll->reference_freq; */
+	a.full = rfixed_const(pll->reference_freq);
+	feedback_divider.full = rfixed_const(vco_freq);
+	feedback_divider.full = rfixed_div(feedback_divider, a);
+	a.full = rfixed_const(ref_div);
+	feedback_divider.full = rfixed_mul(feedback_divider, a);
+
+	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+		/* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */
+		a.full = rfixed_const(10);
+		feedback_divider.full = rfixed_mul(feedback_divider, a);
+		feedback_divider.full += rfixed_const_half(0);
+		feedback_divider.full = rfixed_floor(feedback_divider);
+		feedback_divider.full = rfixed_div(feedback_divider, a);
+
+		/* *fb_div = floor(feedback_divider); */
+		a.full = rfixed_floor(feedback_divider);
+		*fb_div = rfixed_trunc(a);
+		/* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */
+		a.full = rfixed_const(10);
+		b.full = rfixed_mul(feedback_divider, a);
+
+		feedback_divider.full = rfixed_floor(feedback_divider);
+		feedback_divider.full = rfixed_mul(feedback_divider, a);
+		feedback_divider.full = b.full - feedback_divider.full;
+		*fb_div_frac = rfixed_trunc(feedback_divider);
+	} else {
+		/* *fb_div = floor(feedback_divider + 0.5); */
+		feedback_divider.full += rfixed_const_half(0);
+		feedback_divider.full = rfixed_floor(feedback_divider);
+
+		*fb_div = rfixed_trunc(feedback_divider);
+		*fb_div_frac = 0;
+	}
+
+	if (((*fb_div) < pll->min_feedback_div) || ((*fb_div) > pll->max_feedback_div))
+		return false;
+	else
+		return true;
+}
+
+static bool
+calc_fb_ref_div(struct radeon_pll *pll,
+		uint32_t freq,
+		uint32_t post_div,
+		uint32_t *fb_div,
+                uint32_t *fb_div_frac,
+                uint32_t *ref_div)
+{
+	fixed20_12 ffreq, max_error, error, pll_out, a;
+	u32 vco;
+
+	ffreq.full = rfixed_const(freq);
+	/* max_error = ffreq * 0.0025; */
+	a.full = rfixed_const(400);
+	max_error.full = rfixed_div(ffreq, a);
+
+	for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
+		if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) {
+			vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
+			vco = vco / ((*ref_div) * 10);
+
+			if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
+				continue;
+
+			/* pll_out = vco / post_div; */
+			a.full = rfixed_const(post_div);
+			pll_out.full = rfixed_const(vco);
+			pll_out.full = rfixed_div(pll_out, a);
+
+			if (pll_out.full >= ffreq.full) {
+				error.full = pll_out.full - ffreq.full;
+				if (error.full <= max_error.full)
+					return true;
+			}
+		}
+	}
+	return false;
+}
+
+static void radeon_compute_pll_new(struct radeon_pll *pll,
+				   uint64_t freq,
+				   uint32_t *dot_clock_p,
+				   uint32_t *fb_div_p,
+				   uint32_t *frac_fb_div_p,
+				   uint32_t *ref_div_p,
+				   uint32_t *post_div_p)
+{
+	u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
+	u32 best_freq = 0, vco_frequency;
+
+	/* freq = freq / 10; */
+	do_div(freq, 10);
+
+	if (pll->flags & RADEON_PLL_USE_POST_DIV) {
+		post_div = pll->post_div;
+		if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
+			goto done;
+
+		vco_frequency = freq * post_div;
+		if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+			goto done;
+
+		if (pll->flags & RADEON_PLL_USE_REF_DIV) {
+			ref_div = pll->reference_div;
+			if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+				goto done;
+			if (!calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
+				goto done;
+		}
+	} else {
+		for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
+			if (pll->flags & RADEON_PLL_LEGACY) {
+				if ((post_div == 5) ||
+				    (post_div == 7) ||
+				    (post_div == 9) ||
+				    (post_div == 10) ||
+				    (post_div == 11))
+					continue;
+			}
+
+			if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+				continue;
+
+			vco_frequency = freq * post_div;
+			if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+				continue;
+			if (pll->flags & RADEON_PLL_USE_REF_DIV) {
+				ref_div = pll->reference_div;
+				if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+					goto done;
+				if (calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
+					break;
+			} else {
+				if (calc_fb_ref_div(pll, freq, post_div, &fb_div, &fb_div_frac, &ref_div))
+					break;
+			}
+		}
+	}
+
+	best_freq = pll->reference_freq * 10 * fb_div;
+	best_freq += pll->reference_freq * fb_div_frac;
+	best_freq = best_freq / (ref_div * post_div);
+
+done:
+	if (best_freq == 0)
+		DRM_ERROR("Couldn't find valid PLL dividers\n");
+
+	*dot_clock_p = best_freq / 10;
+	*fb_div_p = fb_div;
+	*frac_fb_div_p = fb_div_frac;
+	*ref_div_p = ref_div;
+	*post_div_p = post_div;
+
+	DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
+}
+
+void radeon_compute_pll(struct radeon_pll *pll,
+			uint64_t freq,
+			uint32_t *dot_clock_p,
+			uint32_t *fb_div_p,
+			uint32_t *frac_fb_div_p,
+			uint32_t *ref_div_p,
+			uint32_t *post_div_p)
+{
+	switch (pll->algo) {
+	case PLL_ALGO_NEW:
+		radeon_compute_pll_new(pll, freq, dot_clock_p, fb_div_p,
+				       frac_fb_div_p, ref_div_p, post_div_p);
+		break;
+	case PLL_ALGO_LEGACY:
+	default:
+		radeon_compute_pll_legacy(pll, freq, dot_clock_p, fb_div_p,
+					  frac_fb_div_p, ref_div_p, post_div_p);
+		break;
+	}
 }
 
 static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -551,7 +783,6 @@
 		radeonfb_remove(dev, fb);
 
 	if (radeon_fb->obj) {
-		radeon_gem_object_unpin(radeon_fb->obj);
 		mutex_lock(&dev->struct_mutex);
 		drm_gem_object_unreference(radeon_fb->obj);
 		mutex_unlock(&dev->struct_mutex);
@@ -599,7 +830,11 @@
 	struct drm_gem_object *obj;
 
 	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
-
+	if (obj ==  NULL) {
+		dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
+			"can't create framebuffer\n", mode_cmd->handle);
+		return NULL;
+	}
 	return radeon_framebuffer_create(dev, mode_cmd, obj);
 }
 
@@ -629,7 +864,7 @@
 	{ TV_STD_SECAM, "secam" },
 };
 
-int radeon_modeset_create_props(struct radeon_device *rdev)
+static int radeon_modeset_create_props(struct radeon_device *rdev)
 {
 	int i, sz;
 
@@ -642,7 +877,7 @@
 			return -ENOMEM;
 
 		rdev->mode_info.coherent_mode_property->values[0] = 0;
-		rdev->mode_info.coherent_mode_property->values[0] = 1;
+		rdev->mode_info.coherent_mode_property->values[1] = 1;
 	}
 
 	if (!ASIC_IS_AVIVO(rdev)) {
@@ -666,7 +901,7 @@
 	if (!rdev->mode_info.load_detect_property)
 		return -ENOMEM;
 	rdev->mode_info.load_detect_property->values[0] = 0;
-	rdev->mode_info.load_detect_property->values[0] = 1;
+	rdev->mode_info.load_detect_property->values[1] = 1;
 
 	drm_mode_create_scaling_mode_property(rdev->ddev);
 
@@ -723,6 +958,8 @@
 	if (!ret) {
 		return ret;
 	}
+	/* initialize hpd */
+	radeon_hpd_init(rdev);
 	drm_helper_initial_config(rdev->ddev);
 	return 0;
 }
@@ -730,6 +967,7 @@
 void radeon_modeset_fini(struct radeon_device *rdev)
 {
 	if (rdev->mode_info.mode_config_initialized) {
+		radeon_hpd_fini(rdev);
 		drm_mode_config_cleanup(rdev->ddev);
 		rdev->mode_info.mode_config_initialized = false;
 	}
@@ -750,9 +988,17 @@
 		if (encoder->crtc != crtc)
 			continue;
 		if (first) {
-			radeon_crtc->rmx_type = radeon_encoder->rmx_type;
+			/* set scaling */
+			if (radeon_encoder->rmx_type == RMX_OFF)
+				radeon_crtc->rmx_type = RMX_OFF;
+			else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay ||
+				 mode->vdisplay < radeon_encoder->native_mode.vdisplay)
+				radeon_crtc->rmx_type = radeon_encoder->rmx_type;
+			else
+				radeon_crtc->rmx_type = RMX_OFF;
+			/* copy native mode */
 			memcpy(&radeon_crtc->native_mode,
-				&radeon_encoder->native_mode,
+			       &radeon_encoder->native_mode,
 				sizeof(struct drm_display_mode));
 			first = false;
 		} else {
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_ring.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_ring.c
@@ -41,68 +41,55 @@
 {
 	struct radeon_fence *fence;
 	struct radeon_ib *nib;
-	unsigned long i;
-	int r = 0;
+	int r = 0, i, c;
 
 	*ib = NULL;
 	r = radeon_fence_create(rdev, &fence);
 	if (r) {
-		DRM_ERROR("failed to create fence for new IB\n");
+		dev_err(rdev->dev, "failed to create fence for new IB\n");
 		return r;
 	}
 	mutex_lock(&rdev->ib_pool.mutex);
-	i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
-	if (i < RADEON_IB_POOL_SIZE) {
-		set_bit(i, rdev->ib_pool.alloc_bm);
-		rdev->ib_pool.ibs[i].length_dw = 0;
-		*ib = &rdev->ib_pool.ibs[i];
-		mutex_unlock(&rdev->ib_pool.mutex);
-		goto out;
+	for (i = rdev->ib_pool.head_id, c = 0, nib = NULL; c < RADEON_IB_POOL_SIZE; c++, i++) {
+		i &= (RADEON_IB_POOL_SIZE - 1);
+		if (rdev->ib_pool.ibs[i].free) {
+			nib = &rdev->ib_pool.ibs[i];
+			break;
+		}
 	}
-	if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
-		/* we go do nothings here */
+	if (nib == NULL) {
+		/* This should never happen, it means we allocated all
+		 * IB and haven't scheduled one yet, return EBUSY to
+		 * userspace hoping that on ioctl recall we get better
+		 * luck
+		 */
+		dev_err(rdev->dev, "no free indirect buffer !\n");
 		mutex_unlock(&rdev->ib_pool.mutex);
-		DRM_ERROR("all IB allocated none scheduled.\n");
-		r = -EINVAL;
-		goto out;
-	}
-	/* get the first ib on the scheduled list */
-	nib = list_entry(rdev->ib_pool.scheduled_ibs.next,
-			 struct radeon_ib, list);
-	if (nib->fence == NULL) {
-		/* we go do nothings here */
-		mutex_unlock(&rdev->ib_pool.mutex);
-		DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
-		r = -EINVAL;
-		goto out;
+		radeon_fence_unref(&fence);
+		return -EBUSY;
 	}
-	mutex_unlock(&rdev->ib_pool.mutex);
-
-	r = radeon_fence_wait(nib->fence, false);
-	if (r) {
-		DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
-			  (unsigned long)nib->gpu_addr, nib->length_dw);
-		DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n");
-		goto out;
+	rdev->ib_pool.head_id = (nib->idx + 1) & (RADEON_IB_POOL_SIZE - 1);
+	nib->free = false;
+	if (nib->fence) {
+		mutex_unlock(&rdev->ib_pool.mutex);
+		r = radeon_fence_wait(nib->fence, false);
+		if (r) {
+			dev_err(rdev->dev, "error waiting fence of IB(%u:0x%016lX:%u)\n",
+				nib->idx, (unsigned long)nib->gpu_addr, nib->length_dw);
+			mutex_lock(&rdev->ib_pool.mutex);
+			nib->free = true;
+			mutex_unlock(&rdev->ib_pool.mutex);
+			radeon_fence_unref(&fence);
+			return r;
+		}
+		mutex_lock(&rdev->ib_pool.mutex);
 	}
 	radeon_fence_unref(&nib->fence);
-
+	nib->fence = fence;
 	nib->length_dw = 0;
-
-	/* scheduled list is accessed here */
-	mutex_lock(&rdev->ib_pool.mutex);
-	list_del(&nib->list);
-	INIT_LIST_HEAD(&nib->list);
 	mutex_unlock(&rdev->ib_pool.mutex);
-
 	*ib = nib;
-out:
-	if (r) {
-		radeon_fence_unref(&fence);
-	} else {
-		(*ib)->fence = fence;
-	}
-	return r;
+	return 0;
 }
 
 void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
@@ -113,19 +100,10 @@
 	if (tmp == NULL) {
 		return;
 	}
-	mutex_lock(&rdev->ib_pool.mutex);
-	if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) {
-		/* IB is scheduled & not signaled don't do anythings */
-		mutex_unlock(&rdev->ib_pool.mutex);
-		return;
-	}
-	list_del(&tmp->list);
-	INIT_LIST_HEAD(&tmp->list);
-	if (tmp->fence)
+	if (!tmp->fence->emited)
 		radeon_fence_unref(&tmp->fence);
-
-	tmp->length_dw = 0;
-	clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
+	mutex_lock(&rdev->ib_pool.mutex);
+	tmp->free = true;
 	mutex_unlock(&rdev->ib_pool.mutex);
 }
 
@@ -135,7 +113,7 @@
 
 	if (!ib->length_dw || !rdev->cp.ready) {
 		/* TODO: Nothings in the ib we should report. */
-		DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
+		DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx);
 		return -EINVAL;
 	}
 
@@ -148,7 +126,8 @@
 	radeon_ring_ib_execute(rdev, ib);
 	radeon_fence_emit(rdev, ib->fence);
 	mutex_lock(&rdev->ib_pool.mutex);
-	list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
+	/* once scheduled IB is considered free and protected by the fence */
+	ib->free = true;
 	mutex_unlock(&rdev->ib_pool.mutex);
 	radeon_ring_unlock_commit(rdev);
 	return 0;
@@ -164,20 +143,24 @@
 	if (rdev->ib_pool.robj)
 		return 0;
 	/* Allocate 1M object buffer */
-	INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
-	r = radeon_object_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
-				 true, RADEON_GEM_DOMAIN_GTT,
-				 false, &rdev->ib_pool.robj);
+	r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
+				true, RADEON_GEM_DOMAIN_GTT,
+				&rdev->ib_pool.robj);
 	if (r) {
 		DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
 		return r;
 	}
-	r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
+	r = radeon_bo_reserve(rdev->ib_pool.robj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
 	if (r) {
+		radeon_bo_unreserve(rdev->ib_pool.robj);
 		DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
 		return r;
 	}
-	r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
+	r = radeon_bo_kmap(rdev->ib_pool.robj, &ptr);
+	radeon_bo_unreserve(rdev->ib_pool.robj);
 	if (r) {
 		DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
 		return r;
@@ -190,9 +173,9 @@
 		rdev->ib_pool.ibs[i].ptr = ptr + offset;
 		rdev->ib_pool.ibs[i].idx = i;
 		rdev->ib_pool.ibs[i].length_dw = 0;
-		INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
+		rdev->ib_pool.ibs[i].free = true;
 	}
-	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
+	rdev->ib_pool.head_id = 0;
 	rdev->ib_pool.ready = true;
 	DRM_INFO("radeon: ib pool ready.\n");
 	if (radeon_debugfs_ib_init(rdev)) {
@@ -203,14 +186,20 @@
 
 void radeon_ib_pool_fini(struct radeon_device *rdev)
 {
+	int r;
+
 	if (!rdev->ib_pool.ready) {
 		return;
 	}
 	mutex_lock(&rdev->ib_pool.mutex);
-	bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
 	if (rdev->ib_pool.robj) {
-		radeon_object_kunmap(rdev->ib_pool.robj);
-		radeon_object_unref(&rdev->ib_pool.robj);
+		r = radeon_bo_reserve(rdev->ib_pool.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->ib_pool.robj);
+			radeon_bo_unpin(rdev->ib_pool.robj);
+			radeon_bo_unreserve(rdev->ib_pool.robj);
+		}
+		radeon_bo_unref(&rdev->ib_pool.robj);
 		rdev->ib_pool.robj = NULL;
 	}
 	mutex_unlock(&rdev->ib_pool.mutex);
@@ -288,29 +277,28 @@
 	rdev->cp.ring_size = ring_size;
 	/* Allocate ring buffer */
 	if (rdev->cp.ring_obj == NULL) {
-		r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
-					 true,
-					 RADEON_GEM_DOMAIN_GTT,
-					 false,
-					 &rdev->cp.ring_obj);
+		r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, true,
+					RADEON_GEM_DOMAIN_GTT,
+					&rdev->cp.ring_obj);
 		if (r) {
-			DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
-			mutex_unlock(&rdev->cp.mutex);
+			dev_err(rdev->dev, "(%d) ring create failed\n", r);
 			return r;
 		}
-		r = radeon_object_pin(rdev->cp.ring_obj,
-				      RADEON_GEM_DOMAIN_GTT,
-				      &rdev->cp.gpu_addr);
+		r = radeon_bo_reserve(rdev->cp.ring_obj, false);
+		if (unlikely(r != 0))
+			return r;
+		r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT,
+					&rdev->cp.gpu_addr);
 		if (r) {
-			DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
-			mutex_unlock(&rdev->cp.mutex);
+			radeon_bo_unreserve(rdev->cp.ring_obj);
+			dev_err(rdev->dev, "(%d) ring pin failed\n", r);
 			return r;
 		}
-		r = radeon_object_kmap(rdev->cp.ring_obj,
+		r = radeon_bo_kmap(rdev->cp.ring_obj,
 				       (void **)&rdev->cp.ring);
+		radeon_bo_unreserve(rdev->cp.ring_obj);
 		if (r) {
-			DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
-			mutex_unlock(&rdev->cp.mutex);
+			dev_err(rdev->dev, "(%d) ring map failed\n", r);
 			return r;
 		}
 	}
@@ -321,11 +309,17 @@
 
 void radeon_ring_fini(struct radeon_device *rdev)
 {
+	int r;
+
 	mutex_lock(&rdev->cp.mutex);
 	if (rdev->cp.ring_obj) {
-		radeon_object_kunmap(rdev->cp.ring_obj);
-		radeon_object_unpin(rdev->cp.ring_obj);
-		radeon_object_unref(&rdev->cp.ring_obj);
+		r = radeon_bo_reserve(rdev->cp.ring_obj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->cp.ring_obj);
+			radeon_bo_unpin(rdev->cp.ring_obj);
+			radeon_bo_unreserve(rdev->cp.ring_obj);
+		}
+		radeon_bo_unref(&rdev->cp.ring_obj);
 		rdev->cp.ring = NULL;
 		rdev->cp.ring_obj = NULL;
 	}
@@ -346,7 +340,7 @@
 	if (ib == NULL) {
 		return 0;
 	}
-	seq_printf(m, "IB %04lu\n", ib->idx);
+	seq_printf(m, "IB %04u\n", ib->idx);
 	seq_printf(m, "IB fence %p\n", ib->fence);
 	seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
 	for (i = 0; i < ib->length_dw; i++) {
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_audio.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_audio.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Christian König.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Christian König
+ */
+#include "drmP.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "atom.h"
+
+#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
+
+/*
+ * check if the chipset is supported
+ */
+static int r600_audio_chipset_supported(struct radeon_device *rdev)
+{
+	return (rdev->family >= CHIP_R600 && rdev->family < CHIP_RV710)
+		|| rdev->family == CHIP_RS600
+		|| rdev->family == CHIP_RS690
+		|| rdev->family == CHIP_RS740;
+}
+
+/*
+ * current number of channels
+ */
+static int r600_audio_channels(struct radeon_device *rdev)
+{
+	return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1;
+}
+
+/*
+ * current bits per sample
+ */
+static int r600_audio_bits_per_sample(struct radeon_device *rdev)
+{
+	uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4;
+	switch (value) {
+	case 0x0: return  8;
+	case 0x1: return 16;
+	case 0x2: return 20;
+	case 0x3: return 24;
+	case 0x4: return 32;
+	}
+
+	DRM_ERROR("Unknown bits per sample 0x%x using 16 instead.\n", (int)value);
+
+	return 16;
+}
+
+/*
+ * current sampling rate in HZ
+ */
+static int r600_audio_rate(struct radeon_device *rdev)
+{
+	uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
+	uint32_t result;
+
+	if (value & 0x4000)
+		result = 44100;
+	else
+		result = 48000;
+
+	result *= ((value >> 11) & 0x7) + 1;
+	result /= ((value >> 8) & 0x7) + 1;
+
+	return result;
+}
+
+/*
+ * iec 60958 status bits
+ */
+static uint8_t r600_audio_status_bits(struct radeon_device *rdev)
+{
+	return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
+}
+
+/*
+ * iec 60958 category code
+ */
+static uint8_t r600_audio_category_code(struct radeon_device *rdev)
+{
+	return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
+}
+
+/*
+ * update all hdmi interfaces with current audio parameters
+ */
+static void r600_audio_update_hdmi(unsigned long param)
+{
+	struct radeon_device *rdev = (struct radeon_device *)param;
+	struct drm_device *dev = rdev->ddev;
+
+	int channels = r600_audio_channels(rdev);
+	int rate = r600_audio_rate(rdev);
+	int bps = r600_audio_bits_per_sample(rdev);
+	uint8_t status_bits = r600_audio_status_bits(rdev);
+	uint8_t category_code = r600_audio_category_code(rdev);
+
+	struct drm_encoder *encoder;
+	int changes = 0;
+
+	changes |= channels != rdev->audio_channels;
+	changes |= rate != rdev->audio_rate;
+	changes |= bps != rdev->audio_bits_per_sample;
+	changes |= status_bits != rdev->audio_status_bits;
+	changes |= category_code != rdev->audio_category_code;
+
+	if (changes) {
+		rdev->audio_channels = channels;
+		rdev->audio_rate = rate;
+		rdev->audio_bits_per_sample = bps;
+		rdev->audio_status_bits = status_bits;
+		rdev->audio_category_code = category_code;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (changes || r600_hdmi_buffer_status_changed(encoder))
+			r600_hdmi_update_audio_settings(
+				encoder, channels,
+				rate, bps, status_bits,
+				category_code);
+	}
+
+	mod_timer(&rdev->audio_timer,
+		jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
+}
+
+/*
+ * initialize the audio vars and register the update timer
+ */
+int r600_audio_init(struct radeon_device *rdev)
+{
+	if (!r600_audio_chipset_supported(rdev))
+		return 0;
+
+	DRM_INFO("%s audio support", radeon_audio ? "Enabling" : "Disabling");
+	WREG32_P(R600_AUDIO_ENABLE, radeon_audio ? 0x81000000 : 0x0, ~0x81000000);
+
+	rdev->audio_channels = -1;
+	rdev->audio_rate = -1;
+	rdev->audio_bits_per_sample = -1;
+	rdev->audio_status_bits = 0;
+	rdev->audio_category_code = 0;
+
+	setup_timer(
+		&rdev->audio_timer,
+		r600_audio_update_hdmi,
+		(unsigned long)rdev);
+
+	mod_timer(&rdev->audio_timer, jiffies + 1);
+
+	return 0;
+}
+
+/*
+ * determin how the encoders and audio interface is wired together
+ */
+int r600_audio_tmds_index(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *other;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		return 0;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		/* special case check if an TMDS1 is present */
+		list_for_each_entry(other, &dev->mode_config.encoder_list, head) {
+			if (to_radeon_encoder(other)->encoder_id ==
+				ENCODER_OBJECT_ID_INTERNAL_TMDS1)
+				return 1;
+		}
+		return 0;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		return 1;
+
+	default:
+		DRM_ERROR("Unsupported encoder type 0x%02X\n",
+			  radeon_encoder->encoder_id);
+		return -1;
+	}
+}
+
+/*
+ * atach the audio codec to the clock source of the encoder
+ */
+void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int base_rate = 48000;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		WREG32_P(R600_AUDIO_TIMING, 0, ~0x301);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301);
+		break;
+
+	default:
+		DRM_ERROR("Unsupported encoder type 0x%02X\n",
+			  radeon_encoder->encoder_id);
+		return;
+	}
+
+	switch (r600_audio_tmds_index(encoder)) {
+	case 0:
+		WREG32(R600_AUDIO_PLL1_MUL, base_rate*50);
+		WREG32(R600_AUDIO_PLL1_DIV, clock*100);
+		WREG32(R600_AUDIO_CLK_SRCSEL, 0);
+		break;
+
+	case 1:
+		WREG32(R600_AUDIO_PLL2_MUL, base_rate*50);
+		WREG32(R600_AUDIO_PLL2_DIV, clock*100);
+		WREG32(R600_AUDIO_CLK_SRCSEL, 1);
+		break;
+	}
+}
+
+/*
+ * release the audio timer
+ * TODO: How to do this correctly on SMP systems?
+ */
+void r600_audio_fini(struct radeon_device *rdev)
+{
+	if (!r600_audio_chipset_supported(rdev))
+		return;
+
+	del_timer(&rdev->audio_timer);
+	WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_cs.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_cs.c
@@ -76,17 +76,17 @@
 			}
 			p->relocs_ptr[i] = &p->relocs[i];
 			p->relocs[i].robj = p->relocs[i].gobj->driver_private;
-			p->relocs[i].lobj.robj = p->relocs[i].robj;
+			p->relocs[i].lobj.bo = p->relocs[i].robj;
 			p->relocs[i].lobj.rdomain = r->read_domains;
 			p->relocs[i].lobj.wdomain = r->write_domain;
 			p->relocs[i].handle = r->handle;
 			p->relocs[i].flags = r->flags;
 			INIT_LIST_HEAD(&p->relocs[i].lobj.list);
-			radeon_object_list_add_object(&p->relocs[i].lobj,
-						      &p->validated);
+			radeon_bo_list_add_object(&p->relocs[i].lobj,
+						&p->validated);
 		}
 	}
-	return radeon_object_list_validate(&p->validated, p->ib->fence);
+	return radeon_bo_list_validate(&p->validated);
 }
 
 int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
@@ -189,16 +189,17 @@
 {
 	unsigned i;
 
-	if (error) {
-		radeon_object_list_unvalidate(&parser->validated);
-	} else {
-		radeon_object_list_clean(&parser->validated);
-	}
-	for (i = 0; i < parser->nrelocs; i++) {
-		if (parser->relocs[i].gobj) {
-			mutex_lock(&parser->rdev->ddev->struct_mutex);
-			drm_gem_object_unreference(parser->relocs[i].gobj);
-			mutex_unlock(&parser->rdev->ddev->struct_mutex);
+	if (!error && parser->ib) {
+		radeon_bo_list_fence(&parser->validated, parser->ib->fence);
+	}
+	radeon_bo_list_unreserve(&parser->validated);
+	if (parser->relocs != NULL) {
+		for (i = 0; i < parser->nrelocs; i++) {
+			if (parser->relocs[i].gobj) {
+				mutex_lock(&parser->rdev->ddev->struct_mutex);
+				drm_gem_object_unreference(parser->relocs[i].gobj);
+				mutex_unlock(&parser->rdev->ddev->struct_mutex);
+			}
 		}
 	}
 	kfree(parser->track);
@@ -230,6 +231,7 @@
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
 	parser.rdev = rdev;
+	parser.dev = rdev->dev;
 	r = radeon_cs_parser_init(&parser, data);
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
@@ -246,7 +248,8 @@
 	}
 	r = radeon_cs_parser_relocs(&parser);
 	if (r) {
-		DRM_ERROR("Failed to parse relocation !\n");
+		if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to parse relocation %d!\n", r);
 		radeon_cs_parser_fini(&parser, r);
 		mutex_unlock(&rdev->cs_mutex);
 		return r;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600.c
@@ -38,8 +38,10 @@
 
 #define PFP_UCODE_SIZE 576
 #define PM4_UCODE_SIZE 1792
+#define RLC_UCODE_SIZE 768
 #define R700_PFP_UCODE_SIZE 848
 #define R700_PM4_UCODE_SIZE 1360
+#define R700_RLC_UCODE_SIZE 1024
 
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/R600_pfp.bin");
@@ -62,6 +64,8 @@
 MODULE_FIRMWARE("radeon/RV730_me.bin");
 MODULE_FIRMWARE("radeon/RV710_pfp.bin");
 MODULE_FIRMWARE("radeon/RV710_me.bin");
+MODULE_FIRMWARE("radeon/R600_rlc.bin");
+MODULE_FIRMWARE("radeon/R700_rlc.bin");
 
 int r600_debugfs_mc_info_init(struct radeon_device *rdev);
 
@@ -70,6 +74,282 @@
 void r600_gpu_init(struct radeon_device *rdev);
 void r600_fini(struct radeon_device *rdev);
 
+/* hpd for digital panel detect/disconnect */
+bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
+{
+	bool connected = false;
+
+	if (ASIC_IS_DCE3(rdev)) {
+		switch (hpd) {
+		case RADEON_HPD_1:
+			if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_2:
+			if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_3:
+			if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_4:
+			if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+			/* DCE 3.2 */
+		case RADEON_HPD_5:
+			if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_6:
+			if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
+				connected = true;
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (hpd) {
+		case RADEON_HPD_1:
+			if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_2:
+			if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
+				connected = true;
+			break;
+		case RADEON_HPD_3:
+			if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE)
+				connected = true;
+			break;
+		default:
+			break;
+		}
+	}
+	return connected;
+}
+
+void r600_hpd_set_polarity(struct radeon_device *rdev,
+			   enum radeon_hpd_id hpd)
+{
+	u32 tmp;
+	bool connected = r600_hpd_sense(rdev, hpd);
+
+	if (ASIC_IS_DCE3(rdev)) {
+		switch (hpd) {
+		case RADEON_HPD_1:
+			tmp = RREG32(DC_HPD1_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD1_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_2:
+			tmp = RREG32(DC_HPD2_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD2_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_3:
+			tmp = RREG32(DC_HPD3_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD3_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_4:
+			tmp = RREG32(DC_HPD4_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD4_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_5:
+			tmp = RREG32(DC_HPD5_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD5_INT_CONTROL, tmp);
+			break;
+			/* DCE 3.2 */
+		case RADEON_HPD_6:
+			tmp = RREG32(DC_HPD6_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HPDx_INT_POLARITY;
+			else
+				tmp |= DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD6_INT_CONTROL, tmp);
+			break;
+		default:
+			break;
+		}
+	} else {
+		switch (hpd) {
+		case RADEON_HPD_1:
+			tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			else
+				tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_2:
+			tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			else
+				tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
+			break;
+		case RADEON_HPD_3:
+			tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL);
+			if (connected)
+				tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			else
+				tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY;
+			WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void r600_hpd_init(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	if (ASIC_IS_DCE3(rdev)) {
+		u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
+		if (ASIC_IS_DCE32(rdev))
+			tmp |= DC_HPDx_EN;
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+			switch (radeon_connector->hpd.hpd) {
+			case RADEON_HPD_1:
+				WREG32(DC_HPD1_CONTROL, tmp);
+				rdev->irq.hpd[0] = true;
+				break;
+			case RADEON_HPD_2:
+				WREG32(DC_HPD2_CONTROL, tmp);
+				rdev->irq.hpd[1] = true;
+				break;
+			case RADEON_HPD_3:
+				WREG32(DC_HPD3_CONTROL, tmp);
+				rdev->irq.hpd[2] = true;
+				break;
+			case RADEON_HPD_4:
+				WREG32(DC_HPD4_CONTROL, tmp);
+				rdev->irq.hpd[3] = true;
+				break;
+				/* DCE 3.2 */
+			case RADEON_HPD_5:
+				WREG32(DC_HPD5_CONTROL, tmp);
+				rdev->irq.hpd[4] = true;
+				break;
+			case RADEON_HPD_6:
+				WREG32(DC_HPD6_CONTROL, tmp);
+				rdev->irq.hpd[5] = true;
+				break;
+			default:
+				break;
+			}
+		}
+	} else {
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+			switch (radeon_connector->hpd.hpd) {
+			case RADEON_HPD_1:
+				WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
+				rdev->irq.hpd[0] = true;
+				break;
+			case RADEON_HPD_2:
+				WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN);
+				rdev->irq.hpd[1] = true;
+				break;
+			case RADEON_HPD_3:
+				WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN);
+				rdev->irq.hpd[2] = true;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+	if (rdev->irq.installed)
+		r600_irq_set(rdev);
+}
+
+void r600_hpd_fini(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	if (ASIC_IS_DCE3(rdev)) {
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+			switch (radeon_connector->hpd.hpd) {
+			case RADEON_HPD_1:
+				WREG32(DC_HPD1_CONTROL, 0);
+				rdev->irq.hpd[0] = false;
+				break;
+			case RADEON_HPD_2:
+				WREG32(DC_HPD2_CONTROL, 0);
+				rdev->irq.hpd[1] = false;
+				break;
+			case RADEON_HPD_3:
+				WREG32(DC_HPD3_CONTROL, 0);
+				rdev->irq.hpd[2] = false;
+				break;
+			case RADEON_HPD_4:
+				WREG32(DC_HPD4_CONTROL, 0);
+				rdev->irq.hpd[3] = false;
+				break;
+				/* DCE 3.2 */
+			case RADEON_HPD_5:
+				WREG32(DC_HPD5_CONTROL, 0);
+				rdev->irq.hpd[4] = false;
+				break;
+			case RADEON_HPD_6:
+				WREG32(DC_HPD6_CONTROL, 0);
+				rdev->irq.hpd[5] = false;
+				break;
+			default:
+				break;
+			}
+		}
+	} else {
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+			switch (radeon_connector->hpd.hpd) {
+			case RADEON_HPD_1:
+				WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0);
+				rdev->irq.hpd[0] = false;
+				break;
+			case RADEON_HPD_2:
+				WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0);
+				rdev->irq.hpd[1] = false;
+				break;
+			case RADEON_HPD_3:
+				WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0);
+				rdev->irq.hpd[2] = false;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+}
+
 /*
  * R600 PCIE GART
  */
@@ -90,6 +370,22 @@
 	unsigned i;
 	u32 tmp;
 
+	/* flush hdp cache so updates hit vram */
+	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+	    !(rdev->flags & RADEON_IS_AGP)) {
+		void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
+		u32 tmp;
+
+		/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
+		 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+		 * This seems to cause problems on some AGP cards. Just use the old
+		 * method for them.
+		 */
+		WREG32(HDP_DEBUG1, 0);
+		tmp = readl((void __iomem *)ptr);
+	} else
+		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
 	WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
 	WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
 	WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
@@ -180,7 +476,7 @@
 void r600_pcie_gart_disable(struct radeon_device *rdev)
 {
 	u32 tmp;
-	int i;
+	int i, r;
 
 	/* Disable all tables */
 	for (i = 0; i < 7; i++)
@@ -208,8 +504,12 @@
 	WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
 	WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
 	if (rdev->gart.table.vram.robj) {
-		radeon_object_kunmap(rdev->gart.table.vram.robj);
-		radeon_object_unpin(rdev->gart.table.vram.robj);
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
 	}
 }
 
@@ -340,7 +640,6 @@
 	fixed20_12 a;
 	u32 tmp;
 	int chansize, numchan;
-	int r;
 
 	/* Get VRAM informations */
 	rdev->mc.vram_is_ddr = true;
@@ -383,9 +682,6 @@
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
 
 	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r)
-			return r;
 		/* gtt_size is setup by radeon_agp_init */
 		rdev->mc.gtt_location = rdev->mc.agp_base;
 		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -394,11 +690,11 @@
 		 * AGP so that GPU can catch out of VRAM/AGP access
 		 */
 		if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
-			/* Enought place before */
+			/* Enough place before */
 			rdev->mc.vram_location = rdev->mc.gtt_location -
 							rdev->mc.mc_vram_size;
 		} else if (tmp > rdev->mc.mc_vram_size) {
-			/* Enought place after */
+			/* Enough place after */
 			rdev->mc.vram_location = rdev->mc.gtt_location +
 							rdev->mc.gtt_size;
 		} else {
@@ -443,6 +739,10 @@
 	a.full = rfixed_const(100);
 	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
 	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+
+	if (rdev->flags & RADEON_IS_IGP)
+		rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+
 	return 0;
 }
 
@@ -1101,7 +1401,6 @@
 	(void)RREG32(PCIE_PORT_DATA);
 }
 
-
 /*
  * CP & Ring
  */
@@ -1110,11 +1409,12 @@
 	WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
 }
 
-int r600_cp_init_microcode(struct radeon_device *rdev)
+int r600_init_microcode(struct radeon_device *rdev)
 {
 	struct platform_device *pdev;
 	const char *chip_name;
-	size_t pfp_req_size, me_req_size;
+	const char *rlc_chip_name;
+	size_t pfp_req_size, me_req_size, rlc_req_size;
 	char fw_name[30];
 	int err;
 
@@ -1128,30 +1428,62 @@
 	}
 
 	switch (rdev->family) {
-	case CHIP_R600: chip_name = "R600"; break;
-	case CHIP_RV610: chip_name = "RV610"; break;
-	case CHIP_RV630: chip_name = "RV630"; break;
-	case CHIP_RV620: chip_name = "RV620"; break;
-	case CHIP_RV635: chip_name = "RV635"; break;
-	case CHIP_RV670: chip_name = "RV670"; break;
+	case CHIP_R600:
+		chip_name = "R600";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV610:
+		chip_name = "RV610";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV630:
+		chip_name = "RV630";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV620:
+		chip_name = "RV620";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV635:
+		chip_name = "RV635";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV670:
+		chip_name = "RV670";
+		rlc_chip_name = "R600";
+		break;
 	case CHIP_RS780:
-	case CHIP_RS880: chip_name = "RS780"; break;
-	case CHIP_RV770: chip_name = "RV770"; break;
+	case CHIP_RS880:
+		chip_name = "RS780";
+		rlc_chip_name = "R600";
+		break;
+	case CHIP_RV770:
+		chip_name = "RV770";
+		rlc_chip_name = "R700";
+		break;
 	case CHIP_RV730:
-	case CHIP_RV740: chip_name = "RV730"; break;
-	case CHIP_RV710: chip_name = "RV710"; break;
+	case CHIP_RV740:
+		chip_name = "RV730";
+		rlc_chip_name = "R700";
+		break;
+	case CHIP_RV710:
+		chip_name = "RV710";
+		rlc_chip_name = "R700";
+		break;
 	default: BUG();
 	}
 
 	if (rdev->family >= CHIP_RV770) {
 		pfp_req_size = R700_PFP_UCODE_SIZE * 4;
 		me_req_size = R700_PM4_UCODE_SIZE * 4;
+		rlc_req_size = R700_RLC_UCODE_SIZE * 4;
 	} else {
 		pfp_req_size = PFP_UCODE_SIZE * 4;
 		me_req_size = PM4_UCODE_SIZE * 12;
+		rlc_req_size = RLC_UCODE_SIZE * 4;
 	}
 
-	DRM_INFO("Loading %s CP Microcode\n", chip_name);
+	DRM_INFO("Loading %s Microcode\n", chip_name);
 
 	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
 	err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev);
@@ -1175,6 +1507,18 @@
 		       rdev->me_fw->size, fw_name);
 		err = -EINVAL;
 	}
+
+	snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name);
+	err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev);
+	if (err)
+		goto out;
+	if (rdev->rlc_fw->size != rlc_req_size) {
+		printk(KERN_ERR
+		       "r600_rlc: Bogus length %zu in firmware \"%s\"\n",
+		       rdev->rlc_fw->size, fw_name);
+		err = -EINVAL;
+	}
+
 out:
 	platform_device_unregister(pdev);
 
@@ -1187,6 +1531,8 @@
 		rdev->pfp_fw = NULL;
 		release_firmware(rdev->me_fw);
 		rdev->me_fw = NULL;
+		release_firmware(rdev->rlc_fw);
+		rdev->rlc_fw = NULL;
 	}
 	return err;
 }
@@ -1324,6 +1670,12 @@
 	rdev->cp.align_mask = 16 - 1;
 }
 
+void r600_cp_fini(struct radeon_device *rdev)
+{
+	r600_cp_stop(rdev);
+	radeon_ring_fini(rdev);
+}
+
 
 /*
  * GPU scratch registers helpers function.
@@ -1381,10 +1733,16 @@
 
 void r600_wb_disable(struct radeon_device *rdev)
 {
+	int r;
+
 	WREG32(SCRATCH_UMSK, 0);
 	if (rdev->wb.wb_obj) {
-		radeon_object_kunmap(rdev->wb.wb_obj);
-		radeon_object_unpin(rdev->wb.wb_obj);
+		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
+		if (unlikely(r != 0))
+			return;
+		radeon_bo_kunmap(rdev->wb.wb_obj);
+		radeon_bo_unpin(rdev->wb.wb_obj);
+		radeon_bo_unreserve(rdev->wb.wb_obj);
 	}
 }
 
@@ -1392,7 +1750,7 @@
 {
 	r600_wb_disable(rdev);
 	if (rdev->wb.wb_obj) {
-		radeon_object_unref(&rdev->wb.wb_obj);
+		radeon_bo_unref(&rdev->wb.wb_obj);
 		rdev->wb.wb = NULL;
 		rdev->wb.wb_obj = NULL;
 	}
@@ -1403,22 +1761,29 @@
 	int r;
 
 	if (rdev->wb.wb_obj == NULL) {
-		r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
-				RADEON_GEM_DOMAIN_GTT, false, &rdev->wb.wb_obj);
+		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
+				RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj);
 		if (r) {
-			dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r);
+			dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
 			return r;
 		}
-		r = radeon_object_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
+		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
+		if (unlikely(r != 0)) {
+			r600_wb_fini(rdev);
+			return r;
+		}
+		r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
 				&rdev->wb.gpu_addr);
 		if (r) {
-			dev_warn(rdev->dev, "failed to pin WB buffer (%d).\n", r);
+			radeon_bo_unreserve(rdev->wb.wb_obj);
+			dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r);
 			r600_wb_fini(rdev);
 			return r;
 		}
-		r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
+		r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
+		radeon_bo_unreserve(rdev->wb.wb_obj);
 		if (r) {
-			dev_warn(rdev->dev, "failed to map WB buffer (%d).\n", r);
+			dev_warn(rdev->dev, "(%d) map WB bo failed\n", r);
 			r600_wb_fini(rdev);
 			return r;
 		}
@@ -1433,41 +1798,36 @@
 void r600_fence_ring_emit(struct radeon_device *rdev,
 			  struct radeon_fence *fence)
 {
+	/* Also consider EVENT_WRITE_EOP.  it handles the interrupts + timestamps + events */
 	/* Emit fence sequence & fire IRQ */
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
 	radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
 	radeon_ring_write(rdev, fence->seq);
-}
-
-int r600_copy_dma(struct radeon_device *rdev,
-		  uint64_t src_offset,
-		  uint64_t dst_offset,
-		  unsigned num_pages,
-		  struct radeon_fence *fence)
-{
-	/* FIXME: implement */
-	return 0;
+	radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
+	radeon_ring_write(rdev, 1);
+	/* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
+	radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
+	radeon_ring_write(rdev, RB_INT_STAT);
 }
 
 int r600_copy_blit(struct radeon_device *rdev,
 		   uint64_t src_offset, uint64_t dst_offset,
 		   unsigned num_pages, struct radeon_fence *fence)
 {
-	r600_blit_prepare_copy(rdev, num_pages * RADEON_GPU_PAGE_SIZE);
+	int r;
+
+	mutex_lock(&rdev->r600_blit.mutex);
+	rdev->r600_blit.vb_ib = NULL;
+	r = r600_blit_prepare_copy(rdev, num_pages * RADEON_GPU_PAGE_SIZE);
+	if (r) {
+		if (rdev->r600_blit.vb_ib)
+			radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
+		mutex_unlock(&rdev->r600_blit.mutex);
+		return r;
+	}
 	r600_kms_blit_copy(rdev, src_offset, dst_offset, num_pages * RADEON_GPU_PAGE_SIZE);
 	r600_blit_done_copy(rdev, fence);
-	return 0;
-}
-
-int r600_irq_process(struct radeon_device *rdev)
-{
-	/* FIXME: implement */
-	return 0;
-}
-
-int r600_irq_set(struct radeon_device *rdev)
-{
-	/* FIXME: implement */
+	mutex_unlock(&rdev->r600_blit.mutex);
 	return 0;
 }
 
@@ -1506,6 +1866,14 @@
 {
 	int r;
 
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+		r = r600_init_microcode(rdev);
+		if (r) {
+			DRM_ERROR("Failed to load firmware!\n");
+			return r;
+		}
+	}
+
 	r600_mc_program(rdev);
 	if (rdev->flags & RADEON_IS_AGP) {
 		r600_agp_enable(rdev);
@@ -1515,13 +1883,33 @@
 			return r;
 	}
 	r600_gpu_init(rdev);
-
-	r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
-			      &rdev->r600_blit.shader_gpu_addr);
+	r = r600_blit_init(rdev);
 	if (r) {
-		DRM_ERROR("failed to pin blit object %d\n", r);
+		r600_blit_fini(rdev);
+		rdev->asic->copy = NULL;
+		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
+	}
+	/* pin copy shader into vram */
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (unlikely(r != 0))
+			return r;
+		r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
+				&rdev->r600_blit.shader_gpu_addr);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		if (r) {
+			dev_err(rdev->dev, "(%d) pin blit object failed\n", r);
+			return r;
+		}
+	}
+	/* Enable IRQ */
+	r = r600_irq_init(rdev);
+	if (r) {
+		DRM_ERROR("radeon: IH init failed (%d).\n", r);
+		radeon_irq_kms_fini(rdev);
 		return r;
 	}
+	r600_irq_set(rdev);
 
 	r = radeon_ring_init(rdev, rdev->cp.ring_size);
 	if (r)
@@ -1578,18 +1966,35 @@
 		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
 		return r;
 	}
+
+	r = r600_audio_init(rdev);
+	if (r) {
+		DRM_ERROR("radeon: audio resume failed\n");
+		return r;
+	}
+
 	return r;
 }
 
 int r600_suspend(struct radeon_device *rdev)
 {
+	int r;
+
+	r600_audio_fini(rdev);
 	/* FIXME: we should wait for ring to be empty */
 	r600_cp_stop(rdev);
 	rdev->cp.ready = false;
+	r600_irq_suspend(rdev);
 	r600_wb_disable(rdev);
 	r600_pcie_gart_disable(rdev);
 	/* unpin shaders bo */
-	radeon_object_unpin(rdev->r600_blit.shader_obj);
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (!r) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
+	}
 	return 0;
 }
 
@@ -1627,7 +2032,11 @@
 	if (r)
 		return r;
 	/* Post card if necessary */
-	if (!r600_card_posted(rdev) && rdev->bios) {
+	if (!r600_card_posted(rdev)) {
+		if (!rdev->bios) {
+			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+			return -EINVAL;
+		}
 		DRM_INFO("GPU not posted. posting now...\n");
 		atom_asic_init(rdev->mode_info.atom_context);
 	}
@@ -1646,73 +2055,78 @@
 	r = radeon_fence_driver_init(rdev);
 	if (r)
 		return r;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r)
+			radeon_agp_disable(rdev);
+	}
 	r = r600_mc_init(rdev);
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
+	if (r)
+		return r;
+
+	r = radeon_irq_kms_init(rdev);
 	if (r)
 		return r;
+
 	rdev->cp.ring_obj = NULL;
 	r600_ring_init(rdev, 1024 * 1024);
 
-	if (!rdev->me_fw || !rdev->pfp_fw) {
-		r = r600_cp_init_microcode(rdev);
-		if (r) {
-			DRM_ERROR("Failed to load firmware!\n");
-			return r;
-		}
-	}
+	rdev->ih.ring_obj = NULL;
+	r600_ih_ring_init(rdev, 64 * 1024);
 
 	r = r600_pcie_gart_init(rdev);
 	if (r)
 		return r;
 
 	rdev->accel_working = true;
-	r = r600_blit_init(rdev);
-	if (r) {
-		DRM_ERROR("radeon: failled blitter (%d).\n", r);
-		return r;
-	}
-
 	r = r600_startup(rdev);
 	if (r) {
-		r600_suspend(rdev);
+		dev_err(rdev->dev, "disabling GPU acceleration\n");
+		r600_cp_fini(rdev);
 		r600_wb_fini(rdev);
-		radeon_ring_fini(rdev);
+		r600_irq_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		r600_pcie_gart_fini(rdev);
 		rdev->accel_working = false;
 	}
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
-			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
+
+	r = r600_audio_init(rdev);
+	if (r)
+		return r; /* TODO error handling */
 	return 0;
 }
 
 void r600_fini(struct radeon_device *rdev)
 {
-	/* Suspend operations */
-	r600_suspend(rdev);
-
+	r600_audio_fini(rdev);
 	r600_blit_fini(rdev);
-	radeon_ring_fini(rdev);
+	r600_cp_fini(rdev);
 	r600_wb_fini(rdev);
+	r600_irq_fini(rdev);
+	radeon_irq_kms_fini(rdev);
 	r600_pcie_gart_fini(rdev);
+	radeon_agp_fini(rdev);
 	radeon_gem_fini(rdev);
 	radeon_fence_driver_fini(rdev);
 	radeon_clocks_fini(rdev);
-	if (rdev->flags & RADEON_IS_AGP)
-		radeon_agp_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -1798,8 +2212,668 @@
 	return r;
 }
 
+/*
+ * Interrupts
+ *
+ * Interrupts use a ring buffer on r6xx/r7xx hardware.  It works pretty
+ * the same as the CP ring buffer, but in reverse.  Rather than the CPU
+ * writing to the ring and the GPU consuming, the GPU writes to the ring
+ * and host consumes.  As the host irq handler processes interrupts, it
+ * increments the rptr.  When the rptr catches up with the wptr, all the
+ * current interrupts have been processed.
+ */
+
+void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
+{
+	u32 rb_bufsz;
+
+	/* Align ring size */
+	rb_bufsz = drm_order(ring_size / 4);
+	ring_size = (1 << rb_bufsz) * 4;
+	rdev->ih.ring_size = ring_size;
+	rdev->ih.ptr_mask = rdev->ih.ring_size - 1;
+	rdev->ih.rptr = 0;
+}
+
+static int r600_ih_ring_alloc(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Allocate ring buffer */
+	if (rdev->ih.ring_obj == NULL) {
+		r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
+				     true,
+				     RADEON_GEM_DOMAIN_GTT,
+				     &rdev->ih.ring_obj);
+		if (r) {
+			DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r);
+			return r;
+		}
+		r = radeon_bo_reserve(rdev->ih.ring_obj, false);
+		if (unlikely(r != 0))
+			return r;
+		r = radeon_bo_pin(rdev->ih.ring_obj,
+				  RADEON_GEM_DOMAIN_GTT,
+				  &rdev->ih.gpu_addr);
+		if (r) {
+			radeon_bo_unreserve(rdev->ih.ring_obj);
+			DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r);
+			return r;
+		}
+		r = radeon_bo_kmap(rdev->ih.ring_obj,
+				   (void **)&rdev->ih.ring);
+		radeon_bo_unreserve(rdev->ih.ring_obj);
+		if (r) {
+			DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r);
+			return r;
+		}
+	}
+	return 0;
+}
+
+static void r600_ih_ring_fini(struct radeon_device *rdev)
+{
+	int r;
+	if (rdev->ih.ring_obj) {
+		r = radeon_bo_reserve(rdev->ih.ring_obj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->ih.ring_obj);
+			radeon_bo_unpin(rdev->ih.ring_obj);
+			radeon_bo_unreserve(rdev->ih.ring_obj);
+		}
+		radeon_bo_unref(&rdev->ih.ring_obj);
+		rdev->ih.ring = NULL;
+		rdev->ih.ring_obj = NULL;
+	}
+}
+
+static void r600_rlc_stop(struct radeon_device *rdev)
+{
+
+	if (rdev->family >= CHIP_RV770) {
+		/* r7xx asics need to soft reset RLC before halting */
+		WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC);
+		RREG32(SRBM_SOFT_RESET);
+		udelay(15000);
+		WREG32(SRBM_SOFT_RESET, 0);
+		RREG32(SRBM_SOFT_RESET);
+	}
+
+	WREG32(RLC_CNTL, 0);
+}
+
+static void r600_rlc_start(struct radeon_device *rdev)
+{
+	WREG32(RLC_CNTL, RLC_ENABLE);
+}
+
+static int r600_rlc_init(struct radeon_device *rdev)
+{
+	u32 i;
+	const __be32 *fw_data;
+
+	if (!rdev->rlc_fw)
+		return -EINVAL;
+
+	r600_rlc_stop(rdev);
+
+	WREG32(RLC_HB_BASE, 0);
+	WREG32(RLC_HB_CNTL, 0);
+	WREG32(RLC_HB_RPTR, 0);
+	WREG32(RLC_HB_WPTR, 0);
+	WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
+	WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
+	WREG32(RLC_MC_CNTL, 0);
+	WREG32(RLC_UCODE_CNTL, 0);
+
+	fw_data = (const __be32 *)rdev->rlc_fw->data;
+	if (rdev->family >= CHIP_RV770) {
+		for (i = 0; i < R700_RLC_UCODE_SIZE; i++) {
+			WREG32(RLC_UCODE_ADDR, i);
+			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+		}
+	} else {
+		for (i = 0; i < RLC_UCODE_SIZE; i++) {
+			WREG32(RLC_UCODE_ADDR, i);
+			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+		}
+	}
+	WREG32(RLC_UCODE_ADDR, 0);
+
+	r600_rlc_start(rdev);
+
+	return 0;
+}
+
+static void r600_enable_interrupts(struct radeon_device *rdev)
+{
+	u32 ih_cntl = RREG32(IH_CNTL);
+	u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
+
+	ih_cntl |= ENABLE_INTR;
+	ih_rb_cntl |= IH_RB_ENABLE;
+	WREG32(IH_CNTL, ih_cntl);
+	WREG32(IH_RB_CNTL, ih_rb_cntl);
+	rdev->ih.enabled = true;
+}
+
+static void r600_disable_interrupts(struct radeon_device *rdev)
+{
+	u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
+	u32 ih_cntl = RREG32(IH_CNTL);
+
+	ih_rb_cntl &= ~IH_RB_ENABLE;
+	ih_cntl &= ~ENABLE_INTR;
+	WREG32(IH_RB_CNTL, ih_rb_cntl);
+	WREG32(IH_CNTL, ih_cntl);
+	/* set rptr, wptr to 0 */
+	WREG32(IH_RB_RPTR, 0);
+	WREG32(IH_RB_WPTR, 0);
+	rdev->ih.enabled = false;
+	rdev->ih.wptr = 0;
+	rdev->ih.rptr = 0;
+}
+
+static void r600_disable_interrupt_state(struct radeon_device *rdev)
+{
+	u32 tmp;
+
+	WREG32(CP_INT_CNTL, 0);
+	WREG32(GRBM_INT_CNTL, 0);
+	WREG32(DxMODE_INT_MASK, 0);
+	if (ASIC_IS_DCE3(rdev)) {
+		WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0);
+		WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0);
+		tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+		WREG32(DC_HPD1_INT_CONTROL, tmp);
+		tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+		WREG32(DC_HPD2_INT_CONTROL, tmp);
+		tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+		WREG32(DC_HPD3_INT_CONTROL, tmp);
+		tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+		WREG32(DC_HPD4_INT_CONTROL, tmp);
+		if (ASIC_IS_DCE32(rdev)) {
+			tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD5_INT_CONTROL, 0);
+			tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
+			WREG32(DC_HPD6_INT_CONTROL, 0);
+		}
+	} else {
+		WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
+		WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
+		tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
+		WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, 0);
+		tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
+		WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, 0);
+		tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY;
+		WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, 0);
+	}
+}
+
+int r600_irq_init(struct radeon_device *rdev)
+{
+	int ret = 0;
+	int rb_bufsz;
+	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
+
+	/* allocate ring */
+	ret = r600_ih_ring_alloc(rdev);
+	if (ret)
+		return ret;
+
+	/* disable irqs */
+	r600_disable_interrupts(rdev);
+
+	/* init rlc */
+	ret = r600_rlc_init(rdev);
+	if (ret) {
+		r600_ih_ring_fini(rdev);
+		return ret;
+	}
+
+	/* setup interrupt control */
+	/* set dummy read address to ring address */
+	WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
+	interrupt_cntl = RREG32(INTERRUPT_CNTL);
+	/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
+	 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
+	 */
+	interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE;
+	/* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */
+	interrupt_cntl &= ~IH_REQ_NONSNOOP_EN;
+	WREG32(INTERRUPT_CNTL, interrupt_cntl);
+
+	WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
+	rb_bufsz = drm_order(rdev->ih.ring_size / 4);
+
+	ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
+		      IH_WPTR_OVERFLOW_CLEAR |
+		      (rb_bufsz << 1));
+	/* WPTR writeback, not yet */
+	/*ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;*/
+	WREG32(IH_RB_WPTR_ADDR_LO, 0);
+	WREG32(IH_RB_WPTR_ADDR_HI, 0);
+
+	WREG32(IH_RB_CNTL, ih_rb_cntl);
+
+	/* set rptr, wptr to 0 */
+	WREG32(IH_RB_RPTR, 0);
+	WREG32(IH_RB_WPTR, 0);
+
+	/* Default settings for IH_CNTL (disabled at first) */
+	ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10);
+	/* RPTR_REARM only works if msi's are enabled */
+	if (rdev->msi_enabled)
+		ih_cntl |= RPTR_REARM;
+
+#ifdef __BIG_ENDIAN
+	ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT);
+#endif
+	WREG32(IH_CNTL, ih_cntl);
+
+	/* force the active interrupt state to all disabled */
+	r600_disable_interrupt_state(rdev);
+
+	/* enable irqs */
+	r600_enable_interrupts(rdev);
+
+	return ret;
+}
+
+void r600_irq_suspend(struct radeon_device *rdev)
+{
+	r600_disable_interrupts(rdev);
+	r600_rlc_stop(rdev);
+}
+
+void r600_irq_fini(struct radeon_device *rdev)
+{
+	r600_irq_suspend(rdev);
+	r600_ih_ring_fini(rdev);
+}
+
+int r600_irq_set(struct radeon_device *rdev)
+{
+	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
+	u32 mode_int = 0;
+	u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
+
+	if (!rdev->irq.installed) {
+		WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+		return -EINVAL;
+	}
+	/* don't enable anything if the ih is disabled */
+	if (!rdev->ih.enabled) {
+		r600_disable_interrupts(rdev);
+		/* force the active interrupt state to all disabled */
+		r600_disable_interrupt_state(rdev);
+		return 0;
+	}
 
+	if (ASIC_IS_DCE3(rdev)) {
+		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		if (ASIC_IS_DCE32(rdev)) {
+			hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
+			hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		}
+	} else {
+		hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN;
+		hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN;
+	}
+
+	if (rdev->irq.sw_int) {
+		DRM_DEBUG("r600_irq_set: sw int\n");
+		cp_int_cntl |= RB_INT_ENABLE;
+	}
+	if (rdev->irq.crtc_vblank_int[0]) {
+		DRM_DEBUG("r600_irq_set: vblank 0\n");
+		mode_int |= D1MODE_VBLANK_INT_MASK;
+	}
+	if (rdev->irq.crtc_vblank_int[1]) {
+		DRM_DEBUG("r600_irq_set: vblank 1\n");
+		mode_int |= D2MODE_VBLANK_INT_MASK;
+	}
+	if (rdev->irq.hpd[0]) {
+		DRM_DEBUG("r600_irq_set: hpd 1\n");
+		hpd1 |= DC_HPDx_INT_EN;
+	}
+	if (rdev->irq.hpd[1]) {
+		DRM_DEBUG("r600_irq_set: hpd 2\n");
+		hpd2 |= DC_HPDx_INT_EN;
+	}
+	if (rdev->irq.hpd[2]) {
+		DRM_DEBUG("r600_irq_set: hpd 3\n");
+		hpd3 |= DC_HPDx_INT_EN;
+	}
+	if (rdev->irq.hpd[3]) {
+		DRM_DEBUG("r600_irq_set: hpd 4\n");
+		hpd4 |= DC_HPDx_INT_EN;
+	}
+	if (rdev->irq.hpd[4]) {
+		DRM_DEBUG("r600_irq_set: hpd 5\n");
+		hpd5 |= DC_HPDx_INT_EN;
+	}
+	if (rdev->irq.hpd[5]) {
+		DRM_DEBUG("r600_irq_set: hpd 6\n");
+		hpd6 |= DC_HPDx_INT_EN;
+	}
+
+	WREG32(CP_INT_CNTL, cp_int_cntl);
+	WREG32(DxMODE_INT_MASK, mode_int);
+	if (ASIC_IS_DCE3(rdev)) {
+		WREG32(DC_HPD1_INT_CONTROL, hpd1);
+		WREG32(DC_HPD2_INT_CONTROL, hpd2);
+		WREG32(DC_HPD3_INT_CONTROL, hpd3);
+		WREG32(DC_HPD4_INT_CONTROL, hpd4);
+		if (ASIC_IS_DCE32(rdev)) {
+			WREG32(DC_HPD5_INT_CONTROL, hpd5);
+			WREG32(DC_HPD6_INT_CONTROL, hpd6);
+		}
+	} else {
+		WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
+		WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
+		WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3);
+	}
 
+	return 0;
+}
+
+static inline void r600_irq_ack(struct radeon_device *rdev,
+				u32 *disp_int,
+				u32 *disp_int_cont,
+				u32 *disp_int_cont2)
+{
+	u32 tmp;
+
+	if (ASIC_IS_DCE3(rdev)) {
+		*disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
+		*disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE);
+		*disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2);
+	} else {
+		*disp_int = RREG32(DISP_INTERRUPT_STATUS);
+		*disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE);
+		*disp_int_cont2 = 0;
+	}
+
+	if (*disp_int & LB_D1_VBLANK_INTERRUPT)
+		WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
+	if (*disp_int & LB_D1_VLINE_INTERRUPT)
+		WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
+	if (*disp_int & LB_D2_VBLANK_INTERRUPT)
+		WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
+	if (*disp_int & LB_D2_VLINE_INTERRUPT)
+		WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
+	if (*disp_int & DC_HPD1_INTERRUPT) {
+		if (ASIC_IS_DCE3(rdev)) {
+			tmp = RREG32(DC_HPD1_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HPD1_INT_CONTROL, tmp);
+		} else {
+			tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
+		}
+	}
+	if (*disp_int & DC_HPD2_INTERRUPT) {
+		if (ASIC_IS_DCE3(rdev)) {
+			tmp = RREG32(DC_HPD2_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HPD2_INT_CONTROL, tmp);
+		} else {
+			tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
+		}
+	}
+	if (*disp_int_cont & DC_HPD3_INTERRUPT) {
+		if (ASIC_IS_DCE3(rdev)) {
+			tmp = RREG32(DC_HPD3_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HPD3_INT_CONTROL, tmp);
+		} else {
+			tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp);
+		}
+	}
+	if (*disp_int_cont & DC_HPD4_INTERRUPT) {
+		tmp = RREG32(DC_HPD4_INT_CONTROL);
+		tmp |= DC_HPDx_INT_ACK;
+		WREG32(DC_HPD4_INT_CONTROL, tmp);
+	}
+	if (ASIC_IS_DCE32(rdev)) {
+		if (*disp_int_cont2 & DC_HPD5_INTERRUPT) {
+			tmp = RREG32(DC_HPD5_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HPD5_INT_CONTROL, tmp);
+		}
+		if (*disp_int_cont2 & DC_HPD6_INTERRUPT) {
+			tmp = RREG32(DC_HPD5_INT_CONTROL);
+			tmp |= DC_HPDx_INT_ACK;
+			WREG32(DC_HPD6_INT_CONTROL, tmp);
+		}
+	}
+}
+
+void r600_irq_disable(struct radeon_device *rdev)
+{
+	u32 disp_int, disp_int_cont, disp_int_cont2;
+
+	r600_disable_interrupts(rdev);
+	/* Wait and acknowledge irq */
+	mdelay(1);
+	r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+	r600_disable_interrupt_state(rdev);
+}
+
+static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
+{
+	u32 wptr, tmp;
+
+	/* XXX use writeback */
+	wptr = RREG32(IH_RB_WPTR);
+
+	if (wptr & RB_OVERFLOW) {
+		/* When a ring buffer overflow happen start parsing interrupt
+		 * from the last not overwritten vector (wptr + 16). Hopefully
+		 * this should allow us to catchup.
+		 */
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
+			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
+		tmp = RREG32(IH_RB_CNTL);
+		tmp |= IH_WPTR_OVERFLOW_CLEAR;
+		WREG32(IH_RB_CNTL, tmp);
+	}
+	return (wptr & rdev->ih.ptr_mask);
+}
+
+/*        r600 IV Ring
+ * Each IV ring entry is 128 bits:
+ * [7:0]    - interrupt source id
+ * [31:8]   - reserved
+ * [59:32]  - interrupt source data
+ * [127:60]  - reserved
+ *
+ * The basic interrupt vector entries
+ * are decoded as follows:
+ * src_id  src_data  description
+ *      1         0  D1 Vblank
+ *      1         1  D1 Vline
+ *      5         0  D2 Vblank
+ *      5         1  D2 Vline
+ *     19         0  FP Hot plug detection A
+ *     19         1  FP Hot plug detection B
+ *     19         2  DAC A auto-detection
+ *     19         3  DAC B auto-detection
+ *    176         -  CP_INT RB
+ *    177         -  CP_INT IB1
+ *    178         -  CP_INT IB2
+ *    181         -  EOP Interrupt
+ *    233         -  GUI Idle
+ *
+ * Note, these are based on r600 and may need to be
+ * adjusted or added to on newer asics
+ */
+
+int r600_irq_process(struct radeon_device *rdev)
+{
+	u32 wptr = r600_get_ih_wptr(rdev);
+	u32 rptr = rdev->ih.rptr;
+	u32 src_id, src_data;
+	u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
+	unsigned long flags;
+	bool queue_hotplug = false;
+
+	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
+	if (!rdev->ih.enabled)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&rdev->ih.lock, flags);
+
+	if (rptr == wptr) {
+		spin_unlock_irqrestore(&rdev->ih.lock, flags);
+		return IRQ_NONE;
+	}
+	if (rdev->shutdown) {
+		spin_unlock_irqrestore(&rdev->ih.lock, flags);
+		return IRQ_NONE;
+	}
+
+restart_ih:
+	/* display interrupts */
+	r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2);
+
+	rdev->ih.wptr = wptr;
+	while (rptr != wptr) {
+		/* wptr/rptr are in bytes! */
+		ring_index = rptr / 4;
+		src_id =  rdev->ih.ring[ring_index] & 0xff;
+		src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff;
+
+		switch (src_id) {
+		case 1: /* D1 vblank/vline */
+			switch (src_data) {
+			case 0: /* D1 vblank */
+				if (disp_int & LB_D1_VBLANK_INTERRUPT) {
+					drm_handle_vblank(rdev->ddev, 0);
+					disp_int &= ~LB_D1_VBLANK_INTERRUPT;
+					DRM_DEBUG("IH: D1 vblank\n");
+				}
+				break;
+			case 1: /* D1 vline */
+				if (disp_int & LB_D1_VLINE_INTERRUPT) {
+					disp_int &= ~LB_D1_VLINE_INTERRUPT;
+					DRM_DEBUG("IH: D1 vline\n");
+				}
+				break;
+			default:
+				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+				break;
+			}
+			break;
+		case 5: /* D2 vblank/vline */
+			switch (src_data) {
+			case 0: /* D2 vblank */
+				if (disp_int & LB_D2_VBLANK_INTERRUPT) {
+					drm_handle_vblank(rdev->ddev, 1);
+					disp_int &= ~LB_D2_VBLANK_INTERRUPT;
+					DRM_DEBUG("IH: D2 vblank\n");
+				}
+				break;
+			case 1: /* D1 vline */
+				if (disp_int & LB_D2_VLINE_INTERRUPT) {
+					disp_int &= ~LB_D2_VLINE_INTERRUPT;
+					DRM_DEBUG("IH: D2 vline\n");
+				}
+				break;
+			default:
+				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+				break;
+			}
+			break;
+		case 19: /* HPD/DAC hotplug */
+			switch (src_data) {
+			case 0:
+				if (disp_int & DC_HPD1_INTERRUPT) {
+					disp_int &= ~DC_HPD1_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD1\n");
+				}
+				break;
+			case 1:
+				if (disp_int & DC_HPD2_INTERRUPT) {
+					disp_int &= ~DC_HPD2_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD2\n");
+				}
+				break;
+			case 4:
+				if (disp_int_cont & DC_HPD3_INTERRUPT) {
+					disp_int_cont &= ~DC_HPD3_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD3\n");
+				}
+				break;
+			case 5:
+				if (disp_int_cont & DC_HPD4_INTERRUPT) {
+					disp_int_cont &= ~DC_HPD4_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD4\n");
+				}
+				break;
+			case 10:
+				if (disp_int_cont2 & DC_HPD5_INTERRUPT) {
+					disp_int_cont &= ~DC_HPD5_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD5\n");
+				}
+				break;
+			case 12:
+				if (disp_int_cont2 & DC_HPD6_INTERRUPT) {
+					disp_int_cont &= ~DC_HPD6_INTERRUPT;
+					queue_hotplug = true;
+					DRM_DEBUG("IH: HPD6\n");
+				}
+				break;
+			default:
+				DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+				break;
+			}
+			break;
+		case 176: /* CP_INT in ring buffer */
+		case 177: /* CP_INT in IB1 */
+		case 178: /* CP_INT in IB2 */
+			DRM_DEBUG("IH: CP int: 0x%08x\n", src_data);
+			radeon_fence_process(rdev);
+			break;
+		case 181: /* CP EOP event */
+			DRM_DEBUG("IH: CP EOP\n");
+			break;
+		default:
+			DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
+			break;
+		}
+
+		/* wptr/rptr are in bytes! */
+		rptr += 16;
+		rptr &= rdev->ih.ptr_mask;
+	}
+	/* make sure wptr hasn't changed while processing */
+	wptr = r600_get_ih_wptr(rdev);
+	if (wptr != rdev->ih.wptr)
+		goto restart_ih;
+	if (queue_hotplug)
+		queue_work(rdev->wq, &rdev->hotplug_work);
+	rdev->ih.rptr = rptr;
+	WREG32(IH_RB_RPTR, rdev->ih.rptr);
+	spin_unlock_irqrestore(&rdev->ih.lock, flags);
+	return IRQ_HANDLED;
+}
 
 /*
  * Debugfs info
@@ -1811,21 +2885,21 @@
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct radeon_device *rdev = dev->dev_private;
-	uint32_t rdp, wdp;
 	unsigned count, i, j;
 
 	radeon_ring_free_size(rdev);
-	rdp = RREG32(CP_RB_RPTR);
-	wdp = RREG32(CP_RB_WPTR);
-	count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask;
+	count = (rdev->cp.ring_size / 4) - rdev->cp.ring_free_dw;
 	seq_printf(m, "CP_STAT 0x%08x\n", RREG32(CP_STAT));
-	seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp);
-	seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);
+	seq_printf(m, "CP_RB_WPTR 0x%08x\n", RREG32(CP_RB_WPTR));
+	seq_printf(m, "CP_RB_RPTR 0x%08x\n", RREG32(CP_RB_RPTR));
+	seq_printf(m, "driver's copy of the CP_RB_WPTR 0x%08x\n", rdev->cp.wptr);
+	seq_printf(m, "driver's copy of the CP_RB_RPTR 0x%08x\n", rdev->cp.rptr);
 	seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw);
 	seq_printf(m, "%u dwords in ring\n", count);
+	i = rdev->cp.rptr;
 	for (j = 0; j <= count; j++) {
-		i = (rdp + j) & rdev->cp.ptr_mask;
 		seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]);
+		i = (i + 1) & rdev->cp.ptr_mask;
 	}
 	return 0;
 }
@@ -1855,3 +2929,31 @@
 	return 0;
 #endif
 }
+
+/**
+ * r600_ioctl_wait_idle - flush host path cache on wait idle ioctl
+ * rdev: radeon device structure
+ * bo: buffer object struct which userspace is waiting for idle
+ *
+ * Some R6XX/R7XX doesn't seems to take into account HDP flush performed
+ * through ring buffer, this leads to corruption in rendering, see
+ * http://bugzilla.kernel.org/show_bug.cgi?id=15186 to avoid this we
+ * directly perform HDP flush by writing register through MMIO.
+ */
+void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
+{
+	/* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
+	 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
+	 * This seems to cause problems on some AGP cards. Just use the old
+	 * method for them.
+	 */
+	if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+	    rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) {
+		void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
+		u32 tmp;
+
+		WREG32(HDP_DEBUG1, 0);
+		tmp = readl((void __iomem *)ptr);
+	} else
+		WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_test.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_test.c
@@ -30,8 +30,8 @@
 /* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
 void radeon_test_moves(struct radeon_device *rdev)
 {
-	struct radeon_object *vram_obj = NULL;
-	struct radeon_object **gtt_obj = NULL;
+	struct radeon_bo *vram_obj = NULL;
+	struct radeon_bo **gtt_obj = NULL;
 	struct radeon_fence *fence = NULL;
 	uint64_t gtt_addr, vram_addr;
 	unsigned i, n, size;
@@ -42,8 +42,8 @@
 	/* Number of tests =
 	 * (Total GTT - IB pool - writeback page - ring buffer) / test size
 	 */
-	n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
-	     rdev->cp.ring_size) / size;
+	n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE -
+	     rdev->cp.ring_size)) / size;
 
 	gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
 	if (!gtt_obj) {
@@ -52,38 +52,42 @@
 		goto out_cleanup;
 	}
 
-	r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
-				 false, &vram_obj);
+	r = radeon_bo_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
+				&vram_obj);
 	if (r) {
 		DRM_ERROR("Failed to create VRAM object\n");
 		goto out_cleanup;
 	}
-
-	r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
+	r = radeon_bo_reserve(vram_obj, false);
+	if (unlikely(r != 0))
+		goto out_cleanup;
+	r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
 	if (r) {
 		DRM_ERROR("Failed to pin VRAM object\n");
 		goto out_cleanup;
 	}
-
 	for (i = 0; i < n; i++) {
 		void *gtt_map, *vram_map;
 		void **gtt_start, **gtt_end;
 		void **vram_start, **vram_end;
 
-		r = radeon_object_create(rdev, NULL, size, true,
-					 RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i);
+		r = radeon_bo_create(rdev, NULL, size, true,
+					 RADEON_GEM_DOMAIN_GTT, gtt_obj + i);
 		if (r) {
 			DRM_ERROR("Failed to create GTT object %d\n", i);
 			goto out_cleanup;
 		}
 
-		r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
+		r = radeon_bo_reserve(gtt_obj[i], false);
+		if (unlikely(r != 0))
+			goto out_cleanup;
+		r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
 		if (r) {
 			DRM_ERROR("Failed to pin GTT object %d\n", i);
 			goto out_cleanup;
 		}
 
-		r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
 		if (r) {
 			DRM_ERROR("Failed to map GTT object %d\n", i);
 			goto out_cleanup;
@@ -94,7 +98,7 @@
 		     gtt_start++)
 			*gtt_start = gtt_start;
 
-		radeon_object_kunmap(gtt_obj[i]);
+		radeon_bo_kunmap(gtt_obj[i]);
 
 		r = radeon_fence_create(rdev, &fence);
 		if (r) {
@@ -116,7 +120,7 @@
 
 		radeon_fence_unref(&fence);
 
-		r = radeon_object_kmap(vram_obj, &vram_map);
+		r = radeon_bo_kmap(vram_obj, &vram_map);
 		if (r) {
 			DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
 			goto out_cleanup;
@@ -131,13 +135,13 @@
 					  "expected 0x%p (GTT map 0x%p-0x%p)\n",
 					  i, *vram_start, gtt_start, gtt_map,
 					  gtt_end);
-				radeon_object_kunmap(vram_obj);
+				radeon_bo_kunmap(vram_obj);
 				goto out_cleanup;
 			}
 			*vram_start = vram_start;
 		}
 
-		radeon_object_kunmap(vram_obj);
+		radeon_bo_kunmap(vram_obj);
 
 		r = radeon_fence_create(rdev, &fence);
 		if (r) {
@@ -159,7 +163,7 @@
 
 		radeon_fence_unref(&fence);
 
-		r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+		r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
 		if (r) {
 			DRM_ERROR("Failed to map GTT object after copy %d\n", i);
 			goto out_cleanup;
@@ -174,12 +178,12 @@
 					  "expected 0x%p (VRAM map 0x%p-0x%p)\n",
 					  i, *gtt_start, vram_start, vram_map,
 					  vram_end);
-				radeon_object_kunmap(gtt_obj[i]);
+				radeon_bo_kunmap(gtt_obj[i]);
 				goto out_cleanup;
 			}
 		}
 
-		radeon_object_kunmap(gtt_obj[i]);
+		radeon_bo_kunmap(gtt_obj[i]);
 
 		DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
 			 gtt_addr - rdev->mc.gtt_location);
@@ -187,14 +191,20 @@
 
 out_cleanup:
 	if (vram_obj) {
-		radeon_object_unpin(vram_obj);
-		radeon_object_unref(&vram_obj);
+		if (radeon_bo_is_reserved(vram_obj)) {
+			radeon_bo_unpin(vram_obj);
+			radeon_bo_unreserve(vram_obj);
+		}
+		radeon_bo_unref(&vram_obj);
 	}
 	if (gtt_obj) {
 		for (i = 0; i < n; i++) {
 			if (gtt_obj[i]) {
-				radeon_object_unpin(gtt_obj[i]);
-				radeon_object_unref(&gtt_obj[i]);
+				if (radeon_bo_is_reserved(gtt_obj[i])) {
+					radeon_bo_unpin(gtt_obj[i]);
+					radeon_bo_unreserve(gtt_obj[i]);
+				}
+				radeon_bo_unref(&gtt_obj[i]);
 			}
 		}
 		kfree(gtt_obj);
@@ -206,4 +216,3 @@
 		printk(KERN_WARNING "Error while testing BO move.\n");
 	}
 }
-
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/Makefile
@@ -24,6 +24,9 @@
 $(obj)/r300_reg_safe.h: $(src)/reg_srcs/r300 $(obj)/mkregtable
 	$(call if_changed,mkregtable)
 
+$(obj)/r420_reg_safe.h: $(src)/reg_srcs/r420 $(obj)/mkregtable
+	$(call if_changed,mkregtable)
+
 $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
 	$(call if_changed,mkregtable)
 
@@ -35,6 +38,8 @@
 
 $(obj)/r300.o: $(obj)/r300_reg_safe.h
 
+$(obj)/r420.o: $(obj)/r420_reg_safe.h
+
 $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
@@ -49,7 +54,7 @@
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
-	r600_blit_kms.o radeon_pm.o
+	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r300.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r300.c
@@ -36,7 +36,15 @@
 #include "rv350d.h"
 #include "r300_reg_safe.h"
 
-/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 */
+/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380
+ *
+ * GPU Errata:
+ * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL
+ *   using MMIO to flush host path read cache, this lead to HARDLOCKUP.
+ *   However, scheduling such write to the ring seems harmless, i suspect
+ *   the CP read collide with the flush somehow, or maybe the MC, hard to
+ *   tell. (Jerome Glisse)
+ */
 
 /*
  * rv370,rv380 PCIE GART
@@ -137,14 +145,19 @@
 
 void rv370_pcie_gart_disable(struct radeon_device *rdev)
 {
-	uint32_t tmp;
+	u32 tmp;
+	int r;
 
 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
 	if (rdev->gart.table.vram.robj) {
-		radeon_object_kunmap(rdev->gart.table.vram.robj);
-		radeon_object_unpin(rdev->gart.table.vram.robj);
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
 	}
 }
 
@@ -173,6 +186,11 @@
 	/* Wait until IDLE & CLEAN */
 	radeon_ring_write(rdev, PACKET0(0x1720, 0));
 	radeon_ring_write(rdev, (1 << 17) | (1 << 16)  | (1 << 9));
+	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(rdev, rdev->config.r300.hdp_cntl |
+				RADEON_HDP_READ_BUFFER_INVALIDATE);
+	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(rdev, rdev->config.r300.hdp_cntl);
 	/* Emit fence sequence & fire IRQ */
 	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
 	radeon_ring_write(rdev, fence->seq);
@@ -346,11 +364,12 @@
 
 	r100_hdp_reset(rdev);
 	/* FIXME: rv380 one pipes ? */
-	if ((rdev->family == CHIP_R300) || (rdev->family == CHIP_R350)) {
+	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
+	    (rdev->family == CHIP_R350)) {
 		/* r300,r350 */
 		rdev->num_gb_pipes = 2;
 	} else {
-		/* rv350,rv370,rv380 */
+		/* rv350,rv370,rv380,r300 AD */
 		rdev->num_gb_pipes = 1;
 	}
 	rdev->num_z_pipes = 1;
@@ -488,11 +507,14 @@
 
 	/* DDR for all card after R300 & IGP */
 	rdev->mc.vram_is_ddr = true;
+
 	tmp = RREG32(RADEON_MEM_CNTL);
-	if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
-		rdev->mc.vram_width = 128;
-	} else {
-		rdev->mc.vram_width = 64;
+	tmp &= R300_MEM_NUM_CHANNELS_MASK;
+	switch (tmp) {
+	case 0: rdev->mc.vram_width = 64; break;
+	case 1: rdev->mc.vram_width = 128; break;
+	case 2: rdev->mc.vram_width = 256; break;
+	default:  rdev->mc.vram_width = 128; break;
 	}
 
 	r100_vram_init_sizes(rdev);
@@ -681,7 +703,15 @@
 			r100_cs_dump_packet(p, pkt);
 			return r;
 		}
-		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
+
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+			tile_flags |= R300_TXO_MACRO_TILE;
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+			tile_flags |= R300_TXO_MICRO_TILE;
+
+		tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+		tmp |= tile_flags;
+		ib[idx] = tmp;
 		track->textures[i].robj = reloc->robj;
 		break;
 	/* Tracked registers */
@@ -840,6 +870,7 @@
 		case R300_TX_FORMAT_Y4X4:
 		case R300_TX_FORMAT_Z3Y3X2:
 			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_X16:
 		case R300_TX_FORMAT_Y8X8:
@@ -847,11 +878,11 @@
 		case R300_TX_FORMAT_Z6Y5X5:
 		case R300_TX_FORMAT_W4Z4Y4X4:
 		case R300_TX_FORMAT_W1Z5Y5X5:
-		case R300_TX_FORMAT_DXT1:
 		case R300_TX_FORMAT_D3DMFT_CxV8U8:
 		case R300_TX_FORMAT_B8G8_B8G8:
 		case R300_TX_FORMAT_G8R8_G8B8:
 			track->textures[i].cpp = 2;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_Y16X16:
 		case R300_TX_FORMAT_Z11Y11X10:
@@ -861,17 +892,35 @@
 		case 0x17:
 		case R300_TX_FORMAT_FL_I32:
 		case 0x1e:
-		case R300_TX_FORMAT_DXT3:
-		case R300_TX_FORMAT_DXT5:
 			track->textures[i].cpp = 4;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_W16Z16Y16X16:
 		case R300_TX_FORMAT_FL_R16G16B16A16:
 		case R300_TX_FORMAT_FL_I32A32:
 			track->textures[i].cpp = 8;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case R300_TX_FORMAT_FL_R32G32B32A32:
 			track->textures[i].cpp = 16;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
+			break;
+		case R300_TX_FORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
+		case R300_TX_FORMAT_ATI2N:
+			if (p->rdev->family < CHIP_R420) {
+				DRM_ERROR("Invalid texture format %u\n",
+					  (idx_value & 0x1F));
+				return -EINVAL;
+			}
+			/* The same rules apply as for DXT3/5. */
+			/* Pass through. */
+		case R300_TX_FORMAT_DXT3:
+		case R300_TX_FORMAT_DXT5:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
 			break;
 		default:
 			DRM_ERROR("Invalid texture format %u\n",
@@ -932,6 +981,16 @@
 			track->textures[i].width_11 = tmp;
 			tmp = ((idx_value >> 16) & 1) << 11;
 			track->textures[i].height_11 = tmp;
+
+			/* ATI1N */
+			if (idx_value & (1 << 14)) {
+				/* The same rules apply as for DXT1. */
+				track->textures[i].compress_format =
+					R100_TRACK_COMP_DXT1;
+			}
+		} else if (idx_value & (1 << 14)) {
+			DRM_ERROR("Forbidden bit TXFORMAT_MSB\n");
+			return -EINVAL;
 		}
 		break;
 	case 0x4480:
@@ -973,6 +1032,39 @@
 		}
 		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
 		break;
+	case 0x4e0c:
+		/* RB3D_COLOR_CHANNEL_MASK */
+		track->color_channel_mask = idx_value;
+		break;
+	case 0x4d1c:
+		/* ZB_BW_CNTL */
+		track->fastfill = !!(idx_value & (1 << 2));
+		break;
+	case 0x4e04:
+		/* RB3D_BLENDCNTL */
+		track->blend_read_enable = !!(idx_value & (1 << 2));
+		break;
+	case R300_RB3D_AARESOLVE_OFFSET:
+		r = r100_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+				  idx, reg);
+			r100_cs_dump_packet(p, pkt);
+			return r;
+		}
+		track->aa.robj = reloc->robj;
+		track->aa.offset = idx_value;
+		track->aa_dirty = true;
+		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
+		break;
+	case R300_RB3D_AARESOLVE_PITCH:
+		track->aa.pitch = idx_value & 0x3FFE;
+		track->aa_dirty = true;
+		break;
+	case R300_RB3D_AARESOLVE_CTL:
+		track->aaresolve = idx_value & 0x1;
+		track->aa_dirty = true;
+		break;
 	case 0x4be8:
 		/* valid register only on RV530 */
 		if (p->rdev->family == CHIP_RV530)
@@ -1181,6 +1273,9 @@
 {
 	int r;
 
+	/* set common regs */
+	r100_set_common_regs(rdev);
+	/* program mc */
 	r300_mc_program(rdev);
 	/* Resume clock */
 	r300_clock_startup(rdev);
@@ -1193,14 +1288,20 @@
 		if (r)
 			return r;
 	}
+
+	if (rdev->family == CHIP_R300 ||
+	    rdev->family == CHIP_R350 ||
+	    rdev->family == CHIP_RV350)
+		r100_enable_bm(rdev);
+
 	if (rdev->flags & RADEON_IS_PCI) {
 		r = r100_pci_gart_enable(rdev);
 		if (r)
 			return r;
 	}
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	r100_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -1237,6 +1338,8 @@
 	radeon_combios_asic_init(rdev->ddev);
 	/* Resume clock after posting */
 	r300_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return r300_startup(rdev);
 }
 
@@ -1254,7 +1357,6 @@
 
 void r300_fini(struct radeon_device *rdev)
 {
-	r300_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
@@ -1263,9 +1365,10 @@
 		rv370_pcie_gart_fini(rdev);
 	if (rdev->flags & RADEON_IS_PCI)
 		r100_pci_gart_fini(rdev);
+	radeon_agp_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -1303,14 +1406,14 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		radeon_combios_asic_init(rdev->ddev);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
 	/* Set asic errata */
 	r300_errata(rdev);
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	r300_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
@@ -1325,7 +1428,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	if (rdev->flags & RADEON_IS_PCIE) {
@@ -1344,15 +1447,15 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		r300_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		if (rdev->flags & RADEON_IS_PCIE)
 			rv370_pcie_gart_fini(rdev);
 		if (rdev->flags & RADEON_IS_PCI)
 			r100_pci_gart_fini(rdev);
-		radeon_irq_kms_fini(rdev);
+		radeon_agp_fini(rdev);
 		rdev->accel_working = false;
 	}
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_gem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_gem.c
@@ -38,22 +38,21 @@
 
 void radeon_gem_object_free(struct drm_gem_object *gobj)
 {
-	struct radeon_object *robj = gobj->driver_private;
+	struct radeon_bo *robj = gobj->driver_private;
 
 	gobj->driver_private = NULL;
 	if (robj) {
-		radeon_object_unref(&robj);
+		radeon_bo_unref(&robj);
 	}
 }
 
 int radeon_gem_object_create(struct radeon_device *rdev, int size,
-			     int alignment, int initial_domain,
-			     bool discardable, bool kernel,
-			     bool interruptible,
-			     struct drm_gem_object **obj)
+				int alignment, int initial_domain,
+				bool discardable, bool kernel,
+				struct drm_gem_object **obj)
 {
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	int r;
 
 	*obj = NULL;
@@ -65,11 +64,11 @@
 	if (alignment < PAGE_SIZE) {
 		alignment = PAGE_SIZE;
 	}
-	r = radeon_object_create(rdev, gobj, size, kernel, initial_domain,
-				 interruptible, &robj);
+	r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj);
 	if (r) {
-		DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
-			  size, initial_domain, alignment);
+		if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
+				  size, initial_domain, alignment, r);
 		mutex_lock(&rdev->ddev->struct_mutex);
 		drm_gem_object_unreference(gobj);
 		mutex_unlock(&rdev->ddev->struct_mutex);
@@ -83,33 +82,33 @@
 int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 			  uint64_t *gpu_addr)
 {
-	struct radeon_object *robj = obj->driver_private;
-	uint32_t flags;
+	struct radeon_bo *robj = obj->driver_private;
+	int r;
 
-	switch (pin_domain) {
-	case RADEON_GEM_DOMAIN_VRAM:
-		flags = TTM_PL_FLAG_VRAM;
-		break;
-	case RADEON_GEM_DOMAIN_GTT:
-		flags = TTM_PL_FLAG_TT;
-		break;
-	default:
-		flags = TTM_PL_FLAG_SYSTEM;
-		break;
-	}
-	return radeon_object_pin(robj, flags, gpu_addr);
+	r = radeon_bo_reserve(robj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(robj, pin_domain, gpu_addr);
+	radeon_bo_unreserve(robj);
+	return r;
 }
 
 void radeon_gem_object_unpin(struct drm_gem_object *obj)
 {
-	struct radeon_object *robj = obj->driver_private;
-	radeon_object_unpin(robj);
+	struct radeon_bo *robj = obj->driver_private;
+	int r;
+
+	r = radeon_bo_reserve(robj, false);
+	if (likely(r == 0)) {
+		radeon_bo_unpin(robj);
+		radeon_bo_unreserve(robj);
+	}
 }
 
 int radeon_gem_set_domain(struct drm_gem_object *gobj,
 			  uint32_t rdomain, uint32_t wdomain)
 {
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	uint32_t domain;
 	int r;
 
@@ -127,7 +126,7 @@
 	}
 	if (domain == RADEON_GEM_DOMAIN_CPU) {
 		/* Asking for cpu access wait for object idle */
-		r = radeon_object_wait(robj);
+		r = radeon_bo_wait(robj, NULL, false);
 		if (r) {
 			printk(KERN_ERR "Failed to wait for object !\n");
 			return r;
@@ -144,7 +143,7 @@
 
 void radeon_gem_fini(struct radeon_device *rdev)
 {
-	radeon_object_force_delete(rdev);
+	radeon_bo_force_delete(rdev);
 }
 
 
@@ -158,9 +157,13 @@
 	struct drm_radeon_gem_info *args = data;
 
 	args->vram_size = rdev->mc.real_vram_size;
-	/* FIXME: report somethings that makes sense */
-	args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
-	args->gart_size = rdev->mc.gtt_size;
+	args->vram_visible = rdev->mc.real_vram_size;
+	if (rdev->stollen_vga_memory)
+		args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
+	if (rdev->fbdev_rbo)
+		args->vram_visible -= radeon_bo_size(rdev->fbdev_rbo);
+	args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 -
+		RADEON_IB_POOL_SIZE*64*1024;
 	return 0;
 }
 
@@ -192,8 +195,8 @@
 	/* create a gem object to contain this object in */
 	args->size = roundup(args->size, PAGE_SIZE);
 	r = radeon_gem_object_create(rdev, args->size, args->alignment,
-				     args->initial_domain, false,
-				     false, true, &gobj);
+					args->initial_domain, false,
+					false, &gobj);
 	if (r) {
 		return r;
 	}
@@ -218,7 +221,7 @@
 	 * just validate the BO into a certain domain */
 	struct drm_radeon_gem_set_domain *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	int r;
 
 	/* for now if someone requests domain CPU -
@@ -244,19 +247,18 @@
 {
 	struct drm_radeon_gem_mmap *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
-	int r;
+	struct radeon_bo *robj;
 
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL) {
 		return -EINVAL;
 	}
 	robj = gobj->driver_private;
-	r = radeon_object_mmap(robj, &args->addr_ptr);
+	args->addr_ptr = radeon_bo_mmap_offset(robj);
 	mutex_lock(&dev->struct_mutex);
 	drm_gem_object_unreference(gobj);
 	mutex_unlock(&dev->struct_mutex);
-	return r;
+	return 0;
 }
 
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
@@ -264,16 +266,16 @@
 {
 	struct drm_radeon_gem_busy *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	int r;
-	uint32_t cur_placement;
+	uint32_t cur_placement = 0;
 
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL) {
 		return -EINVAL;
 	}
 	robj = gobj->driver_private;
-	r = radeon_object_busy_domain(robj, &cur_placement);
+	r = radeon_bo_wait(robj, &cur_placement, true);
 	switch (cur_placement) {
 	case TTM_PL_VRAM:
 		args->domain = RADEON_GEM_DOMAIN_VRAM;
@@ -297,7 +299,7 @@
 {
 	struct drm_radeon_gem_wait_idle *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	int r;
 
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
@@ -305,7 +307,10 @@
 		return -EINVAL;
 	}
 	robj = gobj->driver_private;
-	r = radeon_object_wait(robj);
+	r = radeon_bo_wait(robj, NULL, false);
+	/* callback hw specific functions if any */
+	if (robj->rdev->asic->ioctl_wait_idle)
+		robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
 	mutex_lock(&dev->struct_mutex);
 	drm_gem_object_unreference(gobj);
 	mutex_unlock(&dev->struct_mutex);
@@ -317,7 +322,7 @@
 {
 	struct drm_radeon_gem_set_tiling *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	int r = 0;
 
 	DRM_DEBUG("%d \n", args->handle);
@@ -325,7 +330,7 @@
 	if (gobj == NULL)
 		return -EINVAL;
 	robj = gobj->driver_private;
-	radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
+	r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
 	mutex_lock(&dev->struct_mutex);
 	drm_gem_object_unreference(gobj);
 	mutex_unlock(&dev->struct_mutex);
@@ -337,16 +342,20 @@
 {
 	struct drm_radeon_gem_get_tiling *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_object *robj;
+	struct radeon_bo *rbo;
 	int r = 0;
 
 	DRM_DEBUG("\n");
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL)
 		return -EINVAL;
-	robj = gobj->driver_private;
-	radeon_object_get_tiling_flags(robj, &args->tiling_flags,
-				       &args->pitch);
+	rbo = gobj->driver_private;
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		goto out;
+	radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch);
+	radeon_bo_unreserve(rbo);
+out:
 	mutex_lock(&dev->struct_mutex);
 	drm_gem_object_unreference(gobj);
 	mutex_unlock(&dev->struct_mutex);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_pm.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_pm.c
@@ -27,7 +27,7 @@
 int radeon_pm_init(struct radeon_device *rdev)
 {
 	if (radeon_debugfs_pm_init(rdev)) {
-		DRM_ERROR("Failed to register debugfs file for CP !\n");
+		DRM_ERROR("Failed to register debugfs file for PM!\n");
 	}
 
 	return 0;
@@ -44,8 +44,11 @@
 	struct drm_device *dev = node->minor->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
-	seq_printf(m, "engine clock: %u0 Hz\n", radeon_get_engine_clock(rdev));
-	seq_printf(m, "memory clock: %u0 Hz\n", radeon_get_memory_clock(rdev));
+	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
+	seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
+	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
+	if (rdev->asic->get_memory_clock)
+		seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rs400.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rs400.c
@@ -223,15 +223,31 @@
 	return 0;
 }
 
+int rs400_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	uint32_t tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32(0x0150);
+		if (tmp & (1 << 2)) {
+			return 0;
+		}
+		DRM_UDELAY(1);
+	}
+	return -1;
+}
+
 void rs400_gpu_init(struct radeon_device *rdev)
 {
 	/* FIXME: HDP same place on rs400 ? */
 	r100_hdp_reset(rdev);
 	/* FIXME: is this correct ? */
 	r420_pipes_init(rdev);
-	if (r300_mc_wait_for_idle(rdev)) {
-		printk(KERN_WARNING "Failed to wait MC idle while "
-		       "programming pipes. Bad things might happen.\n");
+	if (rs400_mc_wait_for_idle(rdev)) {
+		printk(KERN_WARNING "rs400: Failed to wait MC idle while "
+		       "programming pipes. Bad things might happen. %08x\n", RREG32(0x150));
 	}
 }
 
@@ -352,10 +368,11 @@
 	u32 tmp;
 
 	/* Setup GPU memory space */
-	tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
+	tmp = RREG32(R_00015C_NB_TOM);
 	rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
 	rdev->mc.gtt_location = 0xFFFFFFFFUL;
 	r = radeon_mc_setup(rdev);
+	rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
 	if (r)
 		return r;
 	return 0;
@@ -369,8 +386,8 @@
 	r100_mc_stop(rdev, &save);
 
 	/* Wait for mc idle */
-	if (r300_mc_wait_for_idle(rdev))
-		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+	if (rs400_mc_wait_for_idle(rdev))
+		dev_warn(rdev->dev, "rs400: Wait MC idle timeout before updating MC.\n");
 	WREG32(R_000148_MC_FB_LOCATION,
 		S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
 		S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
@@ -387,14 +404,15 @@
 	r300_clock_startup(rdev);
 	/* Initialize GPU configuration (# pipes, ...) */
 	rs400_gpu_init(rdev);
+	r100_enable_bm(rdev);
 	/* Initialize GART (initialize after TTM so we can allocate
 	 * memory through TTM but finalize after TTM) */
 	r = rs400_gart_enable(rdev);
 	if (r)
 		return r;
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	r100_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -430,6 +448,8 @@
 	radeon_combios_asic_init(rdev->ddev);
 	/* Resume clock after posting */
 	r300_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return rs400_startup(rdev);
 }
 
@@ -444,7 +464,6 @@
 
 void rs400_fini(struct radeon_device *rdev)
 {
-	rs400_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
@@ -452,7 +471,7 @@
 	rs400_gart_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -490,12 +509,13 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		radeon_combios_asic_init(rdev->ddev);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
+
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	rs400_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
@@ -510,7 +530,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	r = rs400_gart_init(rdev);
@@ -522,7 +542,6 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		rs400_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -449,6 +449,7 @@
 	u32 packet2s[16];
 	int num_packet2s = 0;
 
+	mutex_init(&rdev->r600_blit.mutex);
 	rdev->r600_blit.state_offset = 0;
 
 	if (rdev->family >= CHIP_RV770)
@@ -473,9 +474,8 @@
 	obj_size += r6xx_ps_size * 4;
 	obj_size = ALIGN(obj_size, 256);
 
-	r = radeon_object_create(rdev, NULL, obj_size,
-				 true, RADEON_GEM_DOMAIN_VRAM,
-				 false, &rdev->r600_blit.shader_obj);
+	r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM,
+				&rdev->r600_blit.shader_obj);
 	if (r) {
 		DRM_ERROR("r600 failed to allocate shader\n");
 		return r;
@@ -485,12 +485,14 @@
 		  obj_size,
 		  rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset);
 
-	r = radeon_object_kmap(rdev->r600_blit.shader_obj, &ptr);
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr);
 	if (r) {
 		DRM_ERROR("failed to map blit object %d\n", r);
 		return r;
 	}
-
 	if (rdev->family >= CHIP_RV770)
 		memcpy_toio(ptr + rdev->r600_blit.state_offset,
 			    r7xx_default_state, rdev->r600_blit.state_len * 4);
@@ -500,19 +502,28 @@
 	if (num_packet2s)
 		memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
 			    packet2s, num_packet2s * 4);
-
-
 	memcpy(ptr + rdev->r600_blit.vs_offset, r6xx_vs, r6xx_vs_size * 4);
 	memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
-
-	radeon_object_kunmap(rdev->r600_blit.shader_obj);
+	radeon_bo_kunmap(rdev->r600_blit.shader_obj);
+	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
 	return 0;
 }
 
 void r600_blit_fini(struct radeon_device *rdev)
 {
-	radeon_object_unpin(rdev->r600_blit.shader_obj);
-	radeon_object_unref(&rdev->r600_blit.shader_obj);
+	int r;
+
+	if (rdev->r600_blit.shader_obj == NULL)
+		return;
+	/* If we can't reserve the bo, unref should be enough to destroy
+	 * it when it becomes idle.
+	 */
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (!r) {
+		radeon_bo_unpin(rdev->r600_blit.shader_obj);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	}
+	radeon_bo_unref(&rdev->r600_blit.shader_obj);
 }
 
 int r600_vb_ib_get(struct radeon_device *rdev)
@@ -532,9 +543,6 @@
 void r600_vb_ib_put(struct radeon_device *rdev)
 {
 	radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
-	mutex_lock(&rdev->ib_pool.mutex);
-	list_add_tail(&rdev->r600_blit.vb_ib->list, &rdev->ib_pool.scheduled_ibs);
-	mutex_unlock(&rdev->ib_pool.mutex);
 	radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
 }
 
@@ -547,7 +555,8 @@
 	int dwords_per_loop = 76, num_loops;
 
 	r = r600_vb_ib_get(rdev);
-	WARN_ON(r);
+	if (r)
+		return r;
 
 	/* set_render_target emits 2 extra dwords on rv6xx */
 	if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
@@ -569,11 +578,12 @@
 	ring_size = num_loops * dwords_per_loop;
 	/* set default  + shaders */
 	ring_size += 40; /* shaders + def state */
-	ring_size += 3; /* fence emit for VB IB */
+	ring_size += 7; /* fence emit for VB IB */
 	ring_size += 5; /* done copy */
-	ring_size += 3; /* fence emit for done copy */
+	ring_size += 7; /* fence emit for done copy */
 	r = radeon_ring_lock(rdev, ring_size);
-	WARN_ON(r);
+	if (r)
+		return r;
 
 	set_default_state(rdev); /* 14 */
 	set_shaders(rdev); /* 26 */
@@ -619,8 +629,8 @@
 			int src_x = src_gpu_addr & 255;
 			int dst_x = dst_gpu_addr & 255;
 			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255;
-			dst_gpu_addr = dst_gpu_addr & ~255;
+			src_gpu_addr = src_gpu_addr & ~255ULL;
+			dst_gpu_addr = dst_gpu_addr & ~255ULL;
 
 			if (!src_x && !dst_x) {
 				h = (cur_size / max_bytes);
@@ -713,8 +723,8 @@
 			int src_x = (src_gpu_addr & 255);
 			int dst_x = (dst_gpu_addr & 255);
 			int h = 1;
-			src_gpu_addr = src_gpu_addr & ~255;
-			dst_gpu_addr = dst_gpu_addr & ~255;
+			src_gpu_addr = src_gpu_addr & ~255ULL;
+			dst_gpu_addr = dst_gpu_addr & ~255ULL;
 
 			if (!src_x && !dst_x) {
 				h = (cur_size / max_bytes);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_cp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_cp.c
@@ -1428,9 +1428,12 @@
 
 	gb_tiling_config |= R600_BANK_SWAPS(1);
 
-	backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
-							dev_priv->r600_max_backends,
-							(0xff << dev_priv->r600_max_backends) & 0xff);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
+		backend_map = 0x28;
+	else
+		backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
+								dev_priv->r600_max_backends,
+								(0xff << dev_priv->r600_max_backends) & 0xff);
 	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
 
 	cc_gc_shader_pipe_config =
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_mode.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_mode.h
@@ -33,6 +33,7 @@
 #include <drm_crtc.h>
 #include <drm_mode.h>
 #include <drm_edid.h>
+#include <drm_dp_helper.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
@@ -45,32 +46,6 @@
 #define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base)
 #define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base)
 
-enum radeon_connector_type {
-	CONNECTOR_NONE,
-	CONNECTOR_VGA,
-	CONNECTOR_DVI_I,
-	CONNECTOR_DVI_D,
-	CONNECTOR_DVI_A,
-	CONNECTOR_STV,
-	CONNECTOR_CTV,
-	CONNECTOR_LVDS,
-	CONNECTOR_DIGITAL,
-	CONNECTOR_SCART,
-	CONNECTOR_HDMI_TYPE_A,
-	CONNECTOR_HDMI_TYPE_B,
-	CONNECTOR_0XC,
-	CONNECTOR_0XD,
-	CONNECTOR_DIN,
-	CONNECTOR_DISPLAY_PORT,
-	CONNECTOR_UNSUPPORTED
-};
-
-enum radeon_dvi_type {
-	DVI_AUTO,
-	DVI_DIGITAL,
-	DVI_ANALOG
-};
-
 enum radeon_rmx_type {
 	RMX_OFF,
 	RMX_FULL,
@@ -87,26 +62,48 @@
 	TV_STD_SCART_PAL,
 	TV_STD_SECAM,
 	TV_STD_PAL_CN,
+	TV_STD_PAL_N,
 };
 
+/* radeon gpio-based i2c
+ * 1. "mask" reg and bits
+ *    grabs the gpio pins for software use
+ *    0=not held  1=held
+ * 2. "a" reg and bits
+ *    output pin value
+ *    0=low 1=high
+ * 3. "en" reg and bits
+ *    sets the pin direction
+ *    0=input 1=output
+ * 4. "y" reg and bits
+ *    input pin value
+ *    0=low 1=high
+ */
 struct radeon_i2c_bus_rec {
 	bool valid;
+	/* id used by atom */
+	uint8_t i2c_id;
+	/* can be used with hw i2c engine */
+	bool hw_capable;
+	/* uses multi-media i2c engine */
+	bool mm_i2c;
+	/* regs and bits */
 	uint32_t mask_clk_reg;
 	uint32_t mask_data_reg;
 	uint32_t a_clk_reg;
 	uint32_t a_data_reg;
-	uint32_t put_clk_reg;
-	uint32_t put_data_reg;
-	uint32_t get_clk_reg;
-	uint32_t get_data_reg;
+	uint32_t en_clk_reg;
+	uint32_t en_data_reg;
+	uint32_t y_clk_reg;
+	uint32_t y_data_reg;
 	uint32_t mask_clk_mask;
 	uint32_t mask_data_mask;
-	uint32_t put_clk_mask;
-	uint32_t put_data_mask;
-	uint32_t get_clk_mask;
-	uint32_t get_data_mask;
 	uint32_t a_clk_mask;
 	uint32_t a_data_mask;
+	uint32_t en_clk_mask;
+	uint32_t en_data_mask;
+	uint32_t y_clk_mask;
+	uint32_t y_data_mask;
 };
 
 struct radeon_tmds_pll {
@@ -116,6 +113,7 @@
 
 #define RADEON_MAX_BIOS_CONNECTOR 16
 
+/* pll flags */
 #define RADEON_PLL_USE_BIOS_DIVS        (1 << 0)
 #define RADEON_PLL_NO_ODD_POST_DIV      (1 << 1)
 #define RADEON_PLL_USE_REF_DIV          (1 << 2)
@@ -128,16 +126,30 @@
 #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
+#define RADEON_PLL_USE_POST_DIV         (1 << 12)
+
+/* pll algo */
+enum radeon_pll_algo {
+	PLL_ALGO_LEGACY,
+	PLL_ALGO_NEW
+};
 
 struct radeon_pll {
-	uint16_t reference_freq;
-	uint16_t reference_div;
+	/* reference frequency */
+	uint32_t reference_freq;
+
+	/* fixed dividers */
+	uint32_t reference_div;
+	uint32_t post_div;
+
+	/* pll in/out limits */
 	uint32_t pll_in_min;
 	uint32_t pll_in_max;
 	uint32_t pll_out_min;
 	uint32_t pll_out_max;
-	uint16_t xclk;
+	uint32_t best_vco;
 
+	/* divider limits */
 	uint32_t min_ref_div;
 	uint32_t max_ref_div;
 	uint32_t min_post_div;
@@ -146,13 +158,23 @@
 	uint32_t max_feedback_div;
 	uint32_t min_frac_feedback_div;
 	uint32_t max_frac_feedback_div;
-	uint32_t best_vco;
+
+	/* flags for the current clock */
+	uint32_t flags;
+
+	/* pll id */
+	uint32_t id;
+	/* pll algo */
+	enum radeon_pll_algo algo;
 };
 
 struct radeon_i2c_chan {
-	struct drm_device *dev;
 	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
+	struct drm_device *dev;
+	union {
+		struct i2c_algo_dp_aux_data dp;
+		struct i2c_algo_bit_data bit;
+	} algo;
 	struct radeon_i2c_bus_rec rec;
 };
 
@@ -170,6 +192,11 @@
 	CT_EMAC,
 };
 
+enum radeon_dvo_chip {
+	DVO_SIL164,
+	DVO_SIL1178,
+};
+
 struct radeon_mode_info {
 	struct atom_context *atom_context;
 	struct card_info *atom_card_info;
@@ -261,6 +288,13 @@
 	struct radeon_tmds_pll tmds_pll[4];
 };
 
+struct radeon_encoder_ext_tmds {
+	/* tmds over dvo */
+	struct radeon_i2c_chan *i2c_bus;
+	uint8_t slave_addr;
+	enum radeon_dvo_chip dvo_chip;
+};
+
 /* spread spectrum */
 struct radeon_atom_ss {
 	uint16_t percentage;
@@ -274,10 +308,11 @@
 struct radeon_encoder_atom_dig {
 	/* atom dig */
 	bool coherent_mode;
-	int dig_block;
+	int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB */
 	/* atom lvds */
 	uint32_t lvds_misc;
 	uint16_t panel_pwr_delay;
+	enum radeon_pll_algo pll_algo;
 	struct radeon_atom_ss *ss;
 	/* panel mode */
 	struct drm_display_mode native_mode;
@@ -297,11 +332,43 @@
 	enum radeon_rmx_type rmx_type;
 	struct drm_display_mode native_mode;
 	void *enc_priv;
+	int hdmi_offset;
+	int hdmi_audio_workaround;
+	int hdmi_buffer_status;
 };
 
 struct radeon_connector_atom_dig {
 	uint32_t igp_lane_info;
 	bool linkb;
+	/* displayport */
+	struct radeon_i2c_chan *dp_i2c_bus;
+	u8 dpcd[8];
+	u8 dp_sink_type;
+	int dp_clock;
+	int dp_lane_count;
+};
+
+struct radeon_gpio_rec {
+	bool valid;
+	u8 id;
+	u32 reg;
+	u32 mask;
+};
+
+enum radeon_hpd_id {
+	RADEON_HPD_NONE = 0,
+	RADEON_HPD_1,
+	RADEON_HPD_2,
+	RADEON_HPD_3,
+	RADEON_HPD_4,
+	RADEON_HPD_5,
+	RADEON_HPD_6,
+};
+
+struct radeon_hpd {
+	enum radeon_hpd_id hpd;
+	u8 plugged_state;
+	struct radeon_gpio_rec gpio;
 };
 
 struct radeon_connector {
@@ -318,6 +385,7 @@
 	void *con_priv;
 	bool dac_load_detect;
 	uint16_t connector_object_id;
+	struct radeon_hpd hpd;
 };
 
 struct radeon_framebuffer {
@@ -325,10 +393,42 @@
 	struct drm_gem_object *obj;
 };
 
+extern enum radeon_tv_std
+radeon_combios_get_tv_info(struct radeon_device *rdev);
+extern enum radeon_tv_std
+radeon_atombios_get_tv_info(struct radeon_device *rdev);
+
+extern void radeon_connector_hotplug(struct drm_connector *connector);
+extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
+extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
+				       struct drm_display_mode *mode);
+extern void radeon_dp_set_link_config(struct drm_connector *connector,
+				      struct drm_display_mode *mode);
+extern void dp_link_train(struct drm_encoder *encoder,
+			  struct drm_connector *connector);
+extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
+extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
+extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
+					   int action, uint8_t lane_num,
+					   uint8_t lane_set);
+extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
+				uint8_t write_byte, uint8_t *read_byte);
+
+extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
+						    struct radeon_i2c_bus_rec *rec,
+						    const char *name);
 extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
 						 struct radeon_i2c_bus_rec *rec,
 						 const char *name);
 extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
+extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
+				   u8 slave_addr,
+				   u8 addr,
+				   u8 *val);
+extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c,
+				   u8 slave_addr,
+				   u8 addr,
+				   u8 val);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
@@ -340,8 +440,9 @@
 			       uint32_t *fb_div_p,
 			       uint32_t *frac_fb_div_p,
 			       uint32_t *ref_div_p,
-			       uint32_t *post_div_p,
-			       int flags);
+			       uint32_t *post_div_p);
+
+extern void radeon_setup_encoder_clones(struct drm_device *dev);
 
 struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
 struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv);
@@ -349,6 +450,7 @@
 struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index);
 struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
 extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
+extern void atombios_digital_setup(struct drm_encoder *encoder, int action);
 extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
 extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
 
@@ -364,7 +466,6 @@
 
 extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 				 struct drm_framebuffer *old_fb);
-extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc);
 
 extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
 				  struct drm_file *file_priv,
@@ -378,12 +479,16 @@
 extern bool radeon_combios_get_clock_info(struct drm_device *dev);
 extern struct radeon_encoder_atom_dig *
 radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
-bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
-				   struct radeon_encoder_int_tmds *tmds);
-bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
-					   struct radeon_encoder_int_tmds *tmds);
-bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
-					    struct radeon_encoder_int_tmds *tmds);
+extern bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
+					  struct radeon_encoder_int_tmds *tmds);
+extern bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
+						     struct radeon_encoder_int_tmds *tmds);
+extern bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
+						   struct radeon_encoder_int_tmds *tmds);
+extern bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
+							 struct radeon_encoder_ext_tmds *tmds);
+extern bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
+						       struct radeon_encoder_ext_tmds *tmds);
 extern struct radeon_encoder_primary_dac *
 radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
 extern struct radeon_encoder_tv_dac *
@@ -395,6 +500,8 @@
 radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
 extern struct radeon_encoder_primary_dac *
 radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder);
+extern bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder);
+extern void radeon_external_tmds_setup(struct drm_encoder *encoder);
 extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
 extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
 extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
@@ -426,16 +533,13 @@
 			       struct radeon_crtc *radeon_crtc);
 void radeon_legacy_init_crtc(struct drm_device *dev,
 			     struct radeon_crtc *radeon_crtc);
-void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state);
+extern void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state);
 
 void radeon_get_clock_info(struct drm_device *dev);
 
 extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev);
 extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev);
 
-void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
-			   struct drm_display_mode *mode,
-			   struct drm_display_mode *adjusted_mode);
 void radeon_enc_destroy(struct drm_encoder *encoder);
 void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
 void radeon_combios_asic_init(struct drm_device *dev);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -46,6 +46,7 @@
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
+	bool is_mac = false;
 	DRM_DEBUG("\n");
 
 	if (radeon_encoder->enc_priv) {
@@ -58,6 +59,15 @@
 		}
 	}
 
+	/* macs (and possibly some x86 oem systems?) wire up LVDS strangely
+	 * Taken from radeonfb.
+	 */
+	if ((rdev->mode_info.connector_table == CT_IBOOK) ||
+	    (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) ||
+	    (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) ||
+	    (rdev->mode_info.connector_table == CT_POWERBOOK_VGA))
+		is_mac = true;
+
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN);
@@ -74,6 +84,8 @@
 
 		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		if (is_mac)
+			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
 		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
@@ -85,10 +97,18 @@
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
 		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
-		lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
+		if (is_mac) {
+			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
+			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN);
+		} else {
+			WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
+			lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
+		}
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
+		udelay(panel_pwr_delay * 1000);
 		break;
 	}
 
@@ -136,7 +156,14 @@
 	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
 
 	lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
-	if ((!rdev->is_atom_bios)) {
+	if (rdev->is_atom_bios) {
+		/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
+		 * need to call that on resume to set up the reg properly.
+		 */
+		radeon_encoder->pixel_clock = adjusted_mode->clock;
+		atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
+		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	} else {
 		struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
 		if (lvds) {
 			DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
@@ -147,8 +174,7 @@
 					     (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
 		} else
 			lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-	} else
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	}
 	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
 	lvds_gen_cntl &= ~(RADEON_LVDS_ON |
 			   RADEON_LVDS_BLON |
@@ -184,9 +210,9 @@
 		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
-static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
-					  struct drm_display_mode *mode,
-					  struct drm_display_mode *adjusted_mode)
+static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
@@ -194,15 +220,24 @@
 	radeon_encoder_set_active_device(encoder);
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	if (radeon_encoder->rmx_type != RMX_OFF)
-		radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
+	/* get the native mode for LVDS */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
+		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+		int mode_id = adjusted_mode->base.id;
+		*adjusted_mode = *native_mode;
+		adjusted_mode->hdisplay = mode->hdisplay;
+		adjusted_mode->vdisplay = mode->vdisplay;
+		adjusted_mode->crtc_hdisplay = mode->hdisplay;
+		adjusted_mode->crtc_vdisplay = mode->vdisplay;
+		adjusted_mode->base.id = mode_id;
+	}
 
 	return true;
 }
 
 static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 	.dpms = radeon_legacy_lvds_dpms,
-	.mode_fixup = radeon_legacy_lvds_mode_fixup,
+	.mode_fixup = radeon_legacy_mode_fixup,
 	.prepare = radeon_legacy_lvds_prepare,
 	.mode_set = radeon_legacy_lvds_mode_set,
 	.commit = radeon_legacy_lvds_commit,
@@ -214,17 +249,6 @@
 	.destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder,
-						 struct drm_display_mode *mode,
-						 struct drm_display_mode *adjusted_mode)
-{
-	/* set the active encoder to connector routing */
-	radeon_encoder_set_active_device(encoder);
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	return true;
-}
-
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -410,7 +434,7 @@
 
 static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
 	.dpms = radeon_legacy_primary_dac_dpms,
-	.mode_fixup = radeon_legacy_primary_dac_mode_fixup,
+	.mode_fixup = radeon_legacy_mode_fixup,
 	.prepare = radeon_legacy_primary_dac_prepare,
 	.mode_set = radeon_legacy_primary_dac_mode_set,
 	.commit = radeon_legacy_primary_dac_commit,
@@ -423,16 +447,6 @@
 	.destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder,
-					      struct drm_display_mode *mode,
-					      struct drm_display_mode *adjusted_mode)
-{
-
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	return true;
-}
-
 static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -584,7 +598,7 @@
 
 static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
 	.dpms = radeon_legacy_tmds_int_dpms,
-	.mode_fixup = radeon_legacy_tmds_int_mode_fixup,
+	.mode_fixup = radeon_legacy_mode_fixup,
 	.prepare = radeon_legacy_tmds_int_prepare,
 	.mode_set = radeon_legacy_tmds_int_mode_set,
 	.commit = radeon_legacy_tmds_int_commit,
@@ -596,17 +610,6 @@
 	.destroy = radeon_enc_destroy,
 };
 
-static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder,
-					      struct drm_display_mode *mode,
-					      struct drm_display_mode *adjusted_mode)
-{
-	/* set the active encoder to connector routing */
-	radeon_encoder_set_active_device(encoder);
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	return true;
-}
-
 static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -697,6 +700,8 @@
 			/*if (mode->clock > 165000)
 			  fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
 		}
+		if (!radeon_combios_external_tmds_setup(encoder))
+			radeon_external_tmds_setup(encoder);
 	}
 
 	if (radeon_crtc->crtc_id == 0) {
@@ -724,9 +729,22 @@
 		radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 }
 
+static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
+	if (tmds) {
+		if (tmds->i2c_bus)
+			radeon_i2c_destroy(tmds->i2c_bus);
+	}
+	kfree(radeon_encoder->enc_priv);
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
+
 static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
 	.dpms = radeon_legacy_tmds_ext_dpms,
-	.mode_fixup = radeon_legacy_tmds_ext_mode_fixup,
+	.mode_fixup = radeon_legacy_mode_fixup,
 	.prepare = radeon_legacy_tmds_ext_prepare,
 	.mode_set = radeon_legacy_tmds_ext_mode_set,
 	.commit = radeon_legacy_tmds_ext_commit,
@@ -735,20 +753,9 @@
 
 
 static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_ext_tmds_enc_destroy,
 };
 
-static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
-					    struct drm_display_mode *mode,
-					    struct drm_display_mode *adjusted_mode)
-{
-	/* set the active encoder to connector routing */
-	radeon_encoder_set_active_device(encoder);
-	drm_mode_set_crtcinfo(adjusted_mode, 0);
-
-	return true;
-}
-
 static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -1265,7 +1272,7 @@
 
 static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
 	.dpms = radeon_legacy_tv_dac_dpms,
-	.mode_fixup = radeon_legacy_tv_dac_mode_fixup,
+	.mode_fixup = radeon_legacy_mode_fixup,
 	.prepare = radeon_legacy_tv_dac_prepare,
 	.mode_set = radeon_legacy_tv_dac_mode_set,
 	.commit = radeon_legacy_tv_dac_commit,
@@ -1302,6 +1309,29 @@
 	return tmds;
 }
 
+static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder_ext_tmds *tmds = NULL;
+	bool ret;
+
+	if (rdev->is_atom_bios)
+		return NULL;
+
+	tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
+
+	if (!tmds)
+		return NULL;
+
+	ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
+
+	if (ret == false)
+		radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
+
+	return tmds;
+}
+
 void
 radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
 {
@@ -1329,7 +1359,6 @@
 		encoder->possible_crtcs = 0x1;
 	else
 		encoder->possible_crtcs = 0x3;
-	encoder->possible_clones = 0;
 
 	radeon_encoder->enc_priv = NULL;
 
@@ -1373,7 +1402,7 @@
 		drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
 		drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
 		if (!rdev->is_atom_bios)
-			radeon_combios_get_ext_tmds_info(radeon_encoder);
+			radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
 		break;
 	}
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/atom.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/atom.c
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <asm/unaligned.h>
 
 #define ATOM_DEBUG
 
@@ -58,6 +59,7 @@
 } atom_exec_context;
 
 int atom_debug = 0;
+static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params);
 void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params);
 
 static uint32_t atom_arg_mask[8] =
@@ -126,7 +128,7 @@
 		case ATOM_IIO_MOVE_INDEX:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((index >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -136,7 +138,7 @@
 		case ATOM_IIO_MOVE_DATA:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((data >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -146,7 +148,7 @@
 		case ATOM_IIO_MOVE_ATTR:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((ctx->
 			      io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
@@ -211,7 +213,9 @@
 	case ATOM_ARG_PS:
 		idx = U8(*ptr);
 		(*ptr)++;
-		val = le32_to_cpu(ctx->ps[idx]);
+		/* get_unaligned_le32 avoids unaligned accesses from atombios
+		 * tables, noticed on a DEC Alpha. */
+		val = get_unaligned_le32((u32 *)&ctx->ps[idx]);
 		if (print)
 			DEBUG("PS[0x%02X,0x%04X]", idx, val);
 		break;
@@ -245,6 +249,9 @@
 		case ATOM_WS_ATTRIBUTES:
 			val = gctx->io_attr;
 			break;
+		case ATOM_WS_REGPTR:
+			val = gctx->reg_block;
+			break;
 		default:
 			val = ctx->ws[idx];
 		}
@@ -263,10 +270,10 @@
 	case ATOM_ARG_FB:
 		idx = U8(*ptr);
 		(*ptr)++;
+		val = gctx->scratch[((gctx->fb_base + idx) / 4)];
 		if (print)
 			DEBUG("FB[0x%02X]", idx);
-		printk(KERN_INFO "FB access is not implemented.\n");
-		return 0;
+		break;
 	case ATOM_ARG_IMM:
 		switch (align) {
 		case ATOM_SRC_DWORD:
@@ -384,6 +391,32 @@
 	return atom_get_src_int(ctx, attr, ptr, NULL, 1);
 }
 
+static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
+{
+	uint32_t val = 0xCDCDCDCD;
+
+	switch (align) {
+	case ATOM_SRC_DWORD:
+		val = U32(*ptr);
+		(*ptr) += 4;
+		break;
+	case ATOM_SRC_WORD0:
+	case ATOM_SRC_WORD8:
+	case ATOM_SRC_WORD16:
+		val = U16(*ptr);
+		(*ptr) += 2;
+		break;
+	case ATOM_SRC_BYTE0:
+	case ATOM_SRC_BYTE8:
+	case ATOM_SRC_BYTE16:
+	case ATOM_SRC_BYTE24:
+		val = U8(*ptr);
+		(*ptr)++;
+		break;
+	}
+	return val;
+}
+
 static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
 			     int *ptr, uint32_t *saved, int print)
 {
@@ -481,6 +514,9 @@
 		case ATOM_WS_ATTRIBUTES:
 			gctx->io_attr = val;
 			break;
+		case ATOM_WS_REGPTR:
+			gctx->reg_block = val;
+			break;
 		default:
 			ctx->ws[idx] = val;
 		}
@@ -488,9 +524,9 @@
 	case ATOM_ARG_FB:
 		idx = U8(*ptr);
 		(*ptr)++;
+		gctx->scratch[((gctx->fb_base + idx) / 4)] = val;
 		DEBUG("FB[0x%02X]", idx);
-		printk(KERN_INFO "FB access is not implemented.\n");
-		return;
+		break;
 	case ATOM_ARG_PLL:
 		idx = U8(*ptr);
 		(*ptr)++;
@@ -573,7 +609,7 @@
 	else
 		SDEBUG("   table: %d\n", idx);
 	if (U16(ctx->ctx->cmd_table + 4 + 2 * idx))
-		atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
+		atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift);
 }
 
 static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg)
@@ -607,7 +643,7 @@
 	uint8_t count = U8((*ptr)++);
 	SDEBUG("   count: %d\n", count);
 	if (arg == ATOM_UNIT_MICROSEC)
-		schedule_timeout_uninterruptible(usecs_to_jiffies(count));
+		udelay(count);
 	else
 		schedule_timeout_uninterruptible(msecs_to_jiffies(count));
 }
@@ -676,7 +712,7 @@
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
 	SDEBUG("   src1: ");
-	src1 = atom_get_src(ctx, attr, ptr);
+	src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
 	SDEBUG("   src2: ");
 	src2 = atom_get_src(ctx, attr, ptr);
 	dst &= src1;
@@ -808,7 +844,7 @@
 	SDEBUG("   base: 0x%04X\n", ctx->ctx->reg_block);
 }
 
-static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
+static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
 {
 	uint8_t attr = U8((*ptr)++), shift;
 	uint32_t saved, dst;
@@ -817,14 +853,14 @@
 	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-	shift = U8((*ptr)++);
+	shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
 	SDEBUG("   shift: %d\n", shift);
 	dst <<= shift;
 	SDEBUG("   dst: ");
 	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
 }
 
-static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
+static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
 {
 	uint8_t attr = U8((*ptr)++), shift;
 	uint32_t saved, dst;
@@ -833,9 +869,47 @@
 	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-	shift = U8((*ptr)++);
+	shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
+	SDEBUG("   shift: %d\n", shift);
+	dst >>= shift;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	/* op needs to full dst value */
+	dst = saved;
+	shift = atom_get_src(ctx, attr, ptr);
+	SDEBUG("   shift: %d\n", shift);
+	dst <<= shift;
+	dst &= atom_arg_mask[dst_align];
+	dst >>= atom_arg_shift[dst_align];
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	uint32_t dst_align = atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3];
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	/* op needs to full dst value */
+	dst = saved;
+	shift = atom_get_src(ctx, attr, ptr);
 	SDEBUG("   shift: %d\n", shift);
 	dst >>= shift;
+	dst &= atom_arg_mask[dst_align];
+	dst >>= atom_arg_shift[dst_align];
 	SDEBUG("   dst: ");
 	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
 }
@@ -936,18 +1010,18 @@
 	atom_op_or, ATOM_ARG_FB}, {
 	atom_op_or, ATOM_ARG_PLL}, {
 	atom_op_or, ATOM_ARG_MC}, {
-	atom_op_shl, ATOM_ARG_REG}, {
-	atom_op_shl, ATOM_ARG_PS}, {
-	atom_op_shl, ATOM_ARG_WS}, {
-	atom_op_shl, ATOM_ARG_FB}, {
-	atom_op_shl, ATOM_ARG_PLL}, {
-	atom_op_shl, ATOM_ARG_MC}, {
-	atom_op_shr, ATOM_ARG_REG}, {
-	atom_op_shr, ATOM_ARG_PS}, {
-	atom_op_shr, ATOM_ARG_WS}, {
-	atom_op_shr, ATOM_ARG_FB}, {
-	atom_op_shr, ATOM_ARG_PLL}, {
-	atom_op_shr, ATOM_ARG_MC}, {
+	atom_op_shift_left, ATOM_ARG_REG}, {
+	atom_op_shift_left, ATOM_ARG_PS}, {
+	atom_op_shift_left, ATOM_ARG_WS}, {
+	atom_op_shift_left, ATOM_ARG_FB}, {
+	atom_op_shift_left, ATOM_ARG_PLL}, {
+	atom_op_shift_left, ATOM_ARG_MC}, {
+	atom_op_shift_right, ATOM_ARG_REG}, {
+	atom_op_shift_right, ATOM_ARG_PS}, {
+	atom_op_shift_right, ATOM_ARG_WS}, {
+	atom_op_shift_right, ATOM_ARG_FB}, {
+	atom_op_shift_right, ATOM_ARG_PLL}, {
+	atom_op_shift_right, ATOM_ARG_MC}, {
 	atom_op_mul, ATOM_ARG_REG}, {
 	atom_op_mul, ATOM_ARG_PS}, {
 	atom_op_mul, ATOM_ARG_WS}, {
@@ -1040,7 +1114,7 @@
 	atom_op_shr, ATOM_ARG_MC}, {
 atom_op_debug, 0},};
 
-void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params)
 {
 	int base = CU16(ctx->cmd_table + 4 + 2 * index);
 	int len, ws, ps, ptr;
@@ -1057,8 +1131,6 @@
 
 	SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
 
-	/* reset reg block */
-	ctx->reg_block = 0;
 	ectx.ctx = ctx;
 	ectx.ps_shift = ps / 4;
 	ectx.start = base;
@@ -1092,6 +1164,19 @@
 		kfree(ectx.ws);
 }
 
+void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+{
+	mutex_lock(&ctx->mutex);
+	/* reset reg block */
+	ctx->reg_block = 0;
+	/* reset fb window */
+	ctx->fb_base = 0;
+	/* reset io mode */
+	ctx->io_mode = ATOM_IO_MM;
+	atom_execute_table_locked(ctx, index, params);
+	mutex_unlock(&ctx->mutex);
+}
+
 static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
 
 static void atom_index_iio(struct atom_context *ctx, int base)
@@ -1214,3 +1299,28 @@
 		*crev = CU8(idx + 3);
 	return;
 }
+
+int atom_allocate_fb_scratch(struct atom_context *ctx)
+{
+	int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
+	uint16_t data_offset;
+	int usage_bytes;
+	struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
+
+	atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
+
+	firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
+
+	DRM_DEBUG("atom firmware requested %08x %dkb\n",
+		  firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
+		  firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+
+	usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+	if (usage_bytes == 0)
+		usage_bytes = 20 * 1024;
+	/* allocate some scratch memory */
+	ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
+	if (!ctx->scratch)
+		return -ENOMEM;
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_reg.h
@@ -86,6 +86,7 @@
 #define R600_HDP_NONSURFACE_BASE                                0x2c04
 
 #define R600_BUS_CNTL                                           0x5420
+#       define R600_BIOS_ROM_DIS                                (1 << 1)
 #define R600_CONFIG_CNTL                                        0x5424
 #define R600_CONFIG_MEMSIZE                                     0x5428
 #define R600_CONFIG_F0_BASE                                     0x542C
@@ -110,5 +111,79 @@
 #define R600_BIOS_6_SCRATCH               0x173c
 #define R600_BIOS_7_SCRATCH               0x1740
 
+/* Audio, these regs were reverse enginered,
+ * so the chance is high that the naming is wrong
+ * R6xx+ ??? */
+
+/* Audio clocks */
+#define R600_AUDIO_PLL1_MUL               0x0514
+#define R600_AUDIO_PLL1_DIV               0x0518
+#define R600_AUDIO_PLL2_MUL               0x0524
+#define R600_AUDIO_PLL2_DIV               0x0528
+#define R600_AUDIO_CLK_SRCSEL             0x0534
+
+/* Audio general */
+#define R600_AUDIO_ENABLE                 0x7300
+#define R600_AUDIO_TIMING                 0x7344
+
+/* Audio params */
+#define R600_AUDIO_VENDOR_ID              0x7380
+#define R600_AUDIO_REVISION_ID            0x7384
+#define R600_AUDIO_ROOT_NODE_COUNT        0x7388
+#define R600_AUDIO_NID1_NODE_COUNT        0x738c
+#define R600_AUDIO_NID1_TYPE              0x7390
+#define R600_AUDIO_SUPPORTED_SIZE_RATE    0x7394
+#define R600_AUDIO_SUPPORTED_CODEC        0x7398
+#define R600_AUDIO_SUPPORTED_POWER_STATES 0x739c
+#define R600_AUDIO_NID2_CAPS              0x73a0
+#define R600_AUDIO_NID3_CAPS              0x73a4
+#define R600_AUDIO_NID3_PIN_CAPS          0x73a8
+
+/* Audio conn list */
+#define R600_AUDIO_CONN_LIST_LEN          0x73ac
+#define R600_AUDIO_CONN_LIST              0x73b0
+
+/* Audio verbs */
+#define R600_AUDIO_RATE_BPS_CHANNEL       0x73c0
+#define R600_AUDIO_PLAYING                0x73c4
+#define R600_AUDIO_IMPLEMENTATION_ID      0x73c8
+#define R600_AUDIO_CONFIG_DEFAULT         0x73cc
+#define R600_AUDIO_PIN_SENSE              0x73d0
+#define R600_AUDIO_PIN_WIDGET_CNTL        0x73d4
+#define R600_AUDIO_STATUS_BITS            0x73d8
+
+/* HDMI base register addresses */
+#define R600_HDMI_TMDS1                   0x7400
+#define R600_HDMI_TMDS2                   0x7700
+#define R600_HDMI_DIG                     0x7800
+
+/* HDMI registers */
+#define R600_HDMI_ENABLE           0x00
+#define R600_HDMI_STATUS           0x04
+#define R600_HDMI_CNTL             0x08
+#define R600_HDMI_UNKNOWN_0        0x0C
+#define R600_HDMI_AUDIOCNTL        0x10
+#define R600_HDMI_VIDEOCNTL        0x14
+#define R600_HDMI_VERSION          0x18
+#define R600_HDMI_UNKNOWN_1        0x28
+#define R600_HDMI_VIDEOINFOFRAME_0 0x54
+#define R600_HDMI_VIDEOINFOFRAME_1 0x58
+#define R600_HDMI_VIDEOINFOFRAME_2 0x5c
+#define R600_HDMI_VIDEOINFOFRAME_3 0x60
+#define R600_HDMI_32kHz_CTS        0xac
+#define R600_HDMI_32kHz_N          0xb0
+#define R600_HDMI_44_1kHz_CTS      0xb4
+#define R600_HDMI_44_1kHz_N        0xb8
+#define R600_HDMI_48kHz_CTS        0xbc
+#define R600_HDMI_48kHz_N          0xc0
+#define R600_HDMI_AUDIOINFOFRAME_0 0xcc
+#define R600_HDMI_AUDIOINFOFRAME_1 0xd0
+#define R600_HDMI_IEC60958_1       0xd4
+#define R600_HDMI_IEC60958_2       0xd8
+#define R600_HDMI_UNKNOWN_2        0xdc
+#define R600_HDMI_AUDIO_DEBUG_0    0xe0
+#define R600_HDMI_AUDIO_DEBUG_1    0xe4
+#define R600_HDMI_AUDIO_DEBUG_2    0xe8
+#define R600_HDMI_AUDIO_DEBUG_3    0xec
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/atombios_dp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/atombios_dp.c
@@ -0,0 +1,789 @@
+/*
+ * Copyright 2007-8 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+
+#include "atom.h"
+#include "atom-bits.h"
+#include "drm_dp_helper.h"
+
+/* move these to drm_dp_helper.c/h */
+#define DP_LINK_CONFIGURATION_SIZE 9
+#define DP_LINK_STATUS_SIZE	   6
+#define DP_DPCD_SIZE	           8
+
+static char *voltage_names[] = {
+        "0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char *pre_emph_names[] = {
+        "0dB", "3.5dB", "6dB", "9.5dB"
+};
+
+static const int dp_clocks[] = {
+	54000,  /* 1 lane, 1.62 Ghz */
+	90000,  /* 1 lane, 2.70 Ghz */
+	108000, /* 2 lane, 1.62 Ghz */
+	180000, /* 2 lane, 2.70 Ghz */
+	216000, /* 4 lane, 1.62 Ghz */
+	360000, /* 4 lane, 2.70 Ghz */
+};
+
+static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
+
+/* common helper functions */
+static int dp_lanes_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
+{
+	int i;
+	u8 max_link_bw;
+	u8 max_lane_count;
+
+	if (!dpcd)
+		return 0;
+
+	max_link_bw = dpcd[DP_MAX_LINK_RATE];
+	max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+
+	switch (max_link_bw) {
+	case DP_LINK_BW_1_62:
+	default:
+		for (i = 0; i < num_dp_clocks; i++) {
+			if (i % 2)
+				continue;
+			switch (max_lane_count) {
+			case 1:
+				if (i > 1)
+					return 0;
+				break;
+			case 2:
+				if (i > 3)
+					return 0;
+				break;
+			case 4:
+			default:
+				break;
+			}
+			if (dp_clocks[i] > mode_clock) {
+				if (i < 2)
+					return 1;
+				else if (i < 4)
+					return 2;
+				else
+					return 4;
+			}
+		}
+		break;
+	case DP_LINK_BW_2_7:
+		for (i = 0; i < num_dp_clocks; i++) {
+			switch (max_lane_count) {
+			case 1:
+				if (i > 1)
+					return 0;
+				break;
+			case 2:
+				if (i > 3)
+					return 0;
+				break;
+			case 4:
+			default:
+				break;
+			}
+			if (dp_clocks[i] > mode_clock) {
+				if (i < 2)
+					return 1;
+				else if (i < 4)
+					return 2;
+				else
+					return 4;
+			}
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
+{
+	int i;
+	u8 max_link_bw;
+	u8 max_lane_count;
+
+	if (!dpcd)
+		return 0;
+
+	max_link_bw = dpcd[DP_MAX_LINK_RATE];
+	max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
+
+	switch (max_link_bw) {
+	case DP_LINK_BW_1_62:
+	default:
+		for (i = 0; i < num_dp_clocks; i++) {
+			if (i % 2)
+				continue;
+			switch (max_lane_count) {
+			case 1:
+				if (i > 1)
+					return 0;
+				break;
+			case 2:
+				if (i > 3)
+					return 0;
+				break;
+			case 4:
+			default:
+				break;
+			}
+			if (dp_clocks[i] > mode_clock)
+				return 162000;
+		}
+		break;
+	case DP_LINK_BW_2_7:
+		for (i = 0; i < num_dp_clocks; i++) {
+			switch (max_lane_count) {
+			case 1:
+				if (i > 1)
+					return 0;
+				break;
+			case 2:
+				if (i > 3)
+					return 0;
+				break;
+			case 4:
+			default:
+				break;
+			}
+			if (dp_clocks[i] > mode_clock)
+				return (i % 2) ? 270000 : 162000;
+		}
+	}
+
+	return 0;
+}
+
+int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock)
+{
+	int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock);
+	int bw = dp_lanes_for_mode_clock(dpcd, mode_clock);
+
+	if ((lanes == 0) || (bw == 0))
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r)
+{
+	return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE],
+			     int lane)
+{
+	int i = DP_LANE0_1_STATUS + (lane >> 1);
+	int s = (lane & 1) * 4;
+	u8 l = dp_link_status(link_status, i);
+	return (l >> s) & 0xf;
+}
+
+static bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+				 int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = dp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return false;
+	}
+	return true;
+}
+
+static bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE],
+			     int lane_count)
+{
+	u8 lane_align;
+	u8 lane_status;
+	int lane;
+
+	lane_align = dp_link_status(link_status,
+				    DP_LANE_ALIGN_STATUS_UPDATED);
+	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+		return false;
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = dp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS)
+			return false;
+	}
+	return true;
+}
+
+static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+					int lane)
+
+{
+	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+		 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+	u8 l = dp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+					     int lane)
+{
+	int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int s = ((lane & 1) ?
+		 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+		 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+	u8 l = dp_link_status(link_status, i);
+
+	return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+/* XXX fix me -- chip specific */
+#define DP_VOLTAGE_MAX         DP_TRAIN_VOLTAGE_SWING_1200
+static u8 dp_pre_emphasis_max(u8 voltage_swing)
+{
+	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+	case DP_TRAIN_VOLTAGE_SWING_400:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_600:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_800:
+		return DP_TRAIN_PRE_EMPHASIS_3_5;
+	case DP_TRAIN_VOLTAGE_SWING_1200:
+	default:
+		return DP_TRAIN_PRE_EMPHASIS_0;
+	}
+}
+
+static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
+				int lane_count,
+				u8 train_set[4])
+{
+	u8 v = 0;
+	u8 p = 0;
+	int lane;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		u8 this_v = dp_get_adjust_request_voltage(link_status, lane);
+		u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane);
+
+		DRM_DEBUG("requested signal parameters: lane %d voltage %s pre_emph %s\n",
+			  lane,
+			  voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+			  pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+
+		if (this_v > v)
+			v = this_v;
+		if (this_p > p)
+			p = this_p;
+	}
+
+	if (v >= DP_VOLTAGE_MAX)
+		v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+	if (p >= dp_pre_emphasis_max(v))
+		p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+	DRM_DEBUG("using signal parameters: voltage %s pre_emph %s\n",
+		  voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT],
+		  pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]);
+
+	for (lane = 0; lane < 4; lane++)
+		train_set[lane] = v | p;
+}
+
+
+/* radeon aux chan functions */
+bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
+			   int num_bytes, u8 *read_byte,
+			   u8 read_buf_len, u8 delay)
+{
+	struct drm_device *dev = chan->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
+	unsigned char *base;
+	int retry_count = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	base = (unsigned char *)rdev->mode_info.atom_context->scratch;
+
+retry:
+	memcpy(base, req_bytes, num_bytes);
+
+	args.lpAuxRequest = 0;
+	args.lpDataOut = 16;
+	args.ucDataOutLen = 0;
+	args.ucChannelID = chan->rec.i2c_id;
+	args.ucDelay = delay / 10;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+	if (args.ucReplyStatus && !args.ucDataOutLen) {
+		if (args.ucReplyStatus == 0x20 && retry_count++ < 10)
+			goto retry;
+		DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n",
+			  req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
+			  chan->rec.i2c_id, args.ucReplyStatus, retry_count);
+		return false;
+	}
+
+	if (args.ucDataOutLen && read_byte && read_buf_len) {
+		if (read_buf_len < args.ucDataOutLen) {
+			DRM_ERROR("Buffer to small for return answer %d %d\n",
+				  read_buf_len, args.ucDataOutLen);
+			return false;
+		}
+		{
+			int len = min(read_buf_len, args.ucDataOutLen);
+			memcpy(read_byte, base + 16, len);
+		}
+	}
+	return true;
+}
+
+bool radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, uint16_t address,
+				uint8_t send_bytes, uint8_t *send)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	u8 msg[20];
+	u8 msg_len, dp_msg_len;
+	bool ret;
+
+	dp_msg_len = 4;
+	msg[0] = address;
+	msg[1] = address >> 8;
+	msg[2] = AUX_NATIVE_WRITE << 4;
+	dp_msg_len += send_bytes;
+	msg[3] = (dp_msg_len << 4) | (send_bytes - 1);
+
+	if (send_bytes > 16)
+		return false;
+
+	memcpy(&msg[4], send, send_bytes);
+	msg_len = 4 + send_bytes;
+	ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, NULL, 0, 0);
+	return ret;
+}
+
+bool radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, uint16_t address,
+			       uint8_t delay, uint8_t expected_bytes,
+			       uint8_t *read_p)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	u8 msg[20];
+	u8 msg_len, dp_msg_len;
+	bool ret = false;
+	msg_len = 4;
+	dp_msg_len = 4;
+	msg[0] = address;
+	msg[1] = address >> 8;
+	msg[2] = AUX_NATIVE_READ << 4;
+	msg[3] = (dp_msg_len) << 4;
+	msg[3] |= expected_bytes - 1;
+
+	ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, read_p, expected_bytes, delay);
+	return ret;
+}
+
+/* radeon dp functions */
+static u8 radeon_dp_encoder_service(struct radeon_device *rdev, int action, int dp_clock,
+				    uint8_t ucconfig, uint8_t lane_num)
+{
+	DP_ENCODER_SERVICE_PARAMETERS args;
+	int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
+
+	memset(&args, 0, sizeof(args));
+	args.ucLinkClock = dp_clock / 10;
+	args.ucConfig = ucconfig;
+	args.ucAction = action;
+	args.ucLaneNum = lane_num;
+	args.ucStatus = 0;
+
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+	return args.ucStatus;
+}
+
+u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	struct drm_device *dev = radeon_connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0,
+					 dig_connector->dp_i2c_bus->rec.i2c_id, 0);
+}
+
+bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	u8 msg[25];
+	int ret;
+
+	ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, 0, 8, msg);
+	if (ret) {
+		memcpy(dig_connector->dpcd, msg, 8);
+		{
+			int i;
+			DRM_DEBUG("DPCD: ");
+			for (i = 0; i < 8; i++)
+				DRM_DEBUG("%02x ", msg[i]);
+			DRM_DEBUG("\n");
+		}
+		return true;
+	}
+	dig_connector->dpcd[0] = 0;
+	return false;
+}
+
+void radeon_dp_set_link_config(struct drm_connector *connector,
+			       struct drm_display_mode *mode)
+{
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) &&
+	    (connector->connector_type != DRM_MODE_CONNECTOR_eDP))
+		return;
+
+	radeon_connector = to_radeon_connector(connector);
+	if (!radeon_connector->con_priv)
+		return;
+	dig_connector = radeon_connector->con_priv;
+
+	dig_connector->dp_clock =
+		dp_link_clock_for_mode_clock(dig_connector->dpcd, mode->clock);
+	dig_connector->dp_lane_count =
+		dp_lanes_for_mode_clock(dig_connector->dpcd, mode->clock);
+}
+
+int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
+				struct drm_display_mode *mode)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+
+	return dp_mode_valid(dig_connector->dpcd, mode->clock);
+}
+
+static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector,
+				    u8 link_status[DP_LINK_STATUS_SIZE])
+{
+	int ret;
+	ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 100,
+					DP_LINK_STATUS_SIZE, link_status);
+	if (!ret) {
+		DRM_ERROR("displayport link status failed\n");
+		return false;
+	}
+
+	DRM_DEBUG("link status %02x %02x %02x %02x %02x %02x\n",
+		  link_status[0], link_status[1], link_status[2],
+		  link_status[3], link_status[4], link_status[5]);
+	return true;
+}
+
+bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+
+	if (!atom_dp_get_link_status(radeon_connector, link_status))
+		return false;
+	if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count))
+		return false;
+	return true;
+}
+
+static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state)
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+
+	if (dig_connector->dpcd[0] >= 0x11) {
+		radeon_dp_aux_native_write(radeon_connector, DP_SET_POWER, 1,
+					   &power_state);
+	}
+}
+
+static void dp_set_downspread(struct radeon_connector *radeon_connector, u8 downspread)
+{
+	radeon_dp_aux_native_write(radeon_connector, DP_DOWNSPREAD_CTRL, 1,
+				   &downspread);
+}
+
+static void dp_set_link_bw_lanes(struct radeon_connector *radeon_connector,
+				 u8 link_configuration[DP_LINK_CONFIGURATION_SIZE])
+{
+	radeon_dp_aux_native_write(radeon_connector, DP_LINK_BW_SET, 2,
+				   link_configuration);
+}
+
+static void dp_update_dpvs_emph(struct radeon_connector *radeon_connector,
+				struct drm_encoder *encoder,
+				u8 train_set[4])
+{
+	struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
+	int i;
+
+	for (i = 0; i < dig_connector->dp_lane_count; i++)
+		atombios_dig_transmitter_setup(encoder,
+					       ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH,
+					       i, train_set[i]);
+
+	radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_LANE0_SET,
+				   dig_connector->dp_lane_count, train_set);
+}
+
+static void dp_set_training(struct radeon_connector *radeon_connector,
+			    u8 training)
+{
+	radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_PATTERN_SET,
+				   1, &training);
+}
+
+void dp_link_train(struct drm_encoder *encoder,
+		   struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+	int enc_id = 0;
+	bool clock_recovery, channel_eq;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u8 link_configuration[DP_LINK_CONFIGURATION_SIZE];
+	u8 tries, voltage;
+	u8 train_set[4];
+	int i;
+
+	if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) &&
+	    (connector->connector_type != DRM_MODE_CONNECTOR_eDP))
+		return;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+	dig = radeon_encoder->enc_priv;
+
+	radeon_connector = to_radeon_connector(connector);
+	if (!radeon_connector->con_priv)
+		return;
+	dig_connector = radeon_connector->con_priv;
+
+	if (dig->dig_encoder)
+		enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER;
+	else
+		enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER;
+	if (dig_connector->linkb)
+		enc_id |= ATOM_DP_CONFIG_LINK_B;
+	else
+		enc_id |= ATOM_DP_CONFIG_LINK_A;
+
+	memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+	if (dig_connector->dp_clock == 270000)
+		link_configuration[0] = DP_LINK_BW_2_7;
+	else
+		link_configuration[0] = DP_LINK_BW_1_62;
+	link_configuration[1] = dig_connector->dp_lane_count;
+	if (dig_connector->dpcd[0] >= 0x11)
+		link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+
+	/* power up the sink */
+	dp_set_power(radeon_connector, DP_SET_POWER_D0);
+	/* disable the training pattern on the sink */
+	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
+	/* set link bw and lanes on the sink */
+	dp_set_link_bw_lanes(radeon_connector, link_configuration);
+	/* disable downspread on the sink */
+	dp_set_downspread(radeon_connector, 0);
+	/* start training on the source */
+	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
+				  dig_connector->dp_clock, enc_id, 0);
+	/* set training pattern 1 on the source */
+	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
+				  dig_connector->dp_clock, enc_id, 0);
+
+	/* set initial vs/emph */
+	memset(train_set, 0, 4);
+	udelay(400);
+	/* set training pattern 1 on the sink */
+	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1);
+
+	dp_update_dpvs_emph(radeon_connector, encoder, train_set);
+
+	/* clock recovery loop */
+	clock_recovery = false;
+	tries = 0;
+	voltage = 0xff;
+	for (;;) {
+		udelay(100);
+		if (!atom_dp_get_link_status(radeon_connector, link_status))
+			break;
+
+		if (dp_clock_recovery_ok(link_status, dig_connector->dp_lane_count)) {
+			clock_recovery = true;
+			break;
+		}
+
+		for (i = 0; i < dig_connector->dp_lane_count; i++) {
+			if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+				break;
+		}
+		if (i == dig_connector->dp_lane_count) {
+			DRM_ERROR("clock recovery reached max voltage\n");
+			break;
+		}
+
+		if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+			++tries;
+			if (tries == 5) {
+				DRM_ERROR("clock recovery tried 5 times\n");
+				break;
+			}
+		} else
+			tries = 0;
+
+		voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+		/* Compute new train_set as requested by sink */
+		dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set);
+		dp_update_dpvs_emph(radeon_connector, encoder, train_set);
+	}
+	if (!clock_recovery)
+		DRM_ERROR("clock recovery failed\n");
+	else
+		DRM_DEBUG("clock recovery at voltage %d pre-emphasis %d\n",
+			  train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+			  (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+			  DP_TRAIN_PRE_EMPHASIS_SHIFT);
+
+
+	/* set training pattern 2 on the sink */
+	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2);
+	/* set training pattern 2 on the source */
+	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
+				  dig_connector->dp_clock, enc_id, 1);
+
+	/* channel equalization loop */
+	tries = 0;
+	channel_eq = false;
+	for (;;) {
+		udelay(400);
+		if (!atom_dp_get_link_status(radeon_connector, link_status))
+			break;
+
+		if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) {
+			channel_eq = true;
+			break;
+		}
+
+		/* Try 5 times */
+		if (tries > 5) {
+			DRM_ERROR("channel eq failed: 5 tries\n");
+			break;
+		}
+
+		/* Compute new train_set as requested by sink */
+		dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set);
+		dp_update_dpvs_emph(radeon_connector, encoder, train_set);
+
+		tries++;
+	}
+
+	if (!channel_eq)
+		DRM_ERROR("channel eq failed\n");
+	else
+		DRM_DEBUG("channel eq at voltage %d pre-emphasis %d\n",
+			  train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK,
+			  (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK)
+			  >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
+
+	/* disable the training pattern on the sink */
+	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
+
+	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
+				  dig_connector->dp_clock, enc_id, 0);
+}
+
+int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
+			 uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter;
+	int ret = 0;
+	uint16_t address = algo_data->address;
+	uint8_t msg[5];
+	uint8_t reply[2];
+	int msg_len, dp_msg_len;
+	int reply_bytes;
+
+	/* Set up the command byte */
+	if (mode & MODE_I2C_READ)
+		msg[2] = AUX_I2C_READ << 4;
+	else
+		msg[2] = AUX_I2C_WRITE << 4;
+
+	if (!(mode & MODE_I2C_STOP))
+		msg[2] |= AUX_I2C_MOT << 4;
+
+	msg[0] = address;
+	msg[1] = address >> 8;
+
+	reply_bytes = 1;
+
+	msg_len = 4;
+	dp_msg_len = 3;
+	switch (mode) {
+	case MODE_I2C_WRITE:
+		msg[4] = write_byte;
+		msg_len++;
+		dp_msg_len += 2;
+		break;
+	case MODE_I2C_READ:
+		dp_msg_len += 1;
+		break;
+	default:
+		break;
+	}
+
+	msg[3] = (dp_msg_len) << 4;
+	ret = radeon_process_aux_ch(auxch, msg, msg_len, reply, reply_bytes, 0);
+
+	if (ret) {
+		if (read_byte)
+			*read_byte = reply[0];
+		return reply_bytes;
+	}
+	return -EREMOTEIO;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_atombios.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -47,7 +47,8 @@
 			  int connector_type,
 			  struct radeon_i2c_bus_rec *i2c_bus,
 			  bool linkb, uint32_t igp_lane_info,
-			  uint16_t connector_object_id);
+			  uint16_t connector_object_id,
+			  struct radeon_hpd *hpd);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -60,16 +61,16 @@
 	struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
 };
 
-static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
-							   *dev, uint8_t id)
+static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
+							       uint8_t id)
 {
-	struct radeon_device *rdev = dev->dev_private;
 	struct atom_context *ctx = rdev->mode_info.atom_context;
-	ATOM_GPIO_I2C_ASSIGMENT gpio;
+	ATOM_GPIO_I2C_ASSIGMENT *gpio;
 	struct radeon_i2c_bus_rec i2c;
 	int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
 	struct _ATOM_GPIO_I2C_INFO *i2c_info;
 	uint16_t data_offset;
+	int i;
 
 	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
 	i2c.valid = false;
@@ -78,35 +79,132 @@
 
 	i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
-	gpio = i2c_info->asGPIO_Info[id];
 
-	i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
-	i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
-	i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
-	i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
-	i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
-	i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
-	i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
-	i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
-	i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
-	i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
-	i2c.put_clk_mask = (1 << gpio.ucClkEnShift);
-	i2c.put_data_mask = (1 << gpio.ucDataEnShift);
-	i2c.get_clk_mask = (1 << gpio.ucClkY_Shift);
-	i2c.get_data_mask = (1 << gpio.ucDataY_Shift);
-	i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
-	i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
-	i2c.valid = true;
+	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+		gpio = &i2c_info->asGPIO_Info[i];
+
+			/* some DCE3 boards have bad data for this entry */
+			if (ASIC_IS_DCE3(rdev)) {
+				if ((i == 4) &&
+				    (gpio->usClkMaskRegisterIndex == 0x1fda) &&
+				    (gpio->sucI2cId.ucAccess == 0x94))
+					gpio->sucI2cId.ucAccess = 0x14;
+			}
+
+		if (gpio->sucI2cId.ucAccess == id) {
+			i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+			i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+			i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+			i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+			i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+			i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+			i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+			i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+			i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+			i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+			i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+			i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+			i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+			i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+			i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+			i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+			if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+				i2c.hw_capable = true;
+			else
+				i2c.hw_capable = false;
+
+			if (gpio->sucI2cId.ucAccess == 0xa0)
+				i2c.mm_i2c = true;
+			else
+				i2c.mm_i2c = false;
+
+			i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+			i2c.valid = true;
+			break;
+		}
+	}
 
 	return i2c;
 }
 
+static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
+							u8 id)
+{
+	struct atom_context *ctx = rdev->mode_info.atom_context;
+	struct radeon_gpio_rec gpio;
+	int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
+	struct _ATOM_GPIO_PIN_LUT *gpio_info;
+	ATOM_GPIO_PIN_ASSIGNMENT *pin;
+	u16 data_offset, size;
+	int i, num_indices;
+
+	memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
+	gpio.valid = false;
+
+	atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
+
+	gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
+
+	num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
+
+	for (i = 0; i < num_indices; i++) {
+		pin = &gpio_info->asGPIO_Pin[i];
+		if (id == pin->ucGPIO_ID) {
+			gpio.id = pin->ucGPIO_ID;
+			gpio.reg = pin->usGpioPin_AIndex * 4;
+			gpio.mask = (1 << pin->ucGpioPinBitShift);
+			gpio.valid = true;
+			break;
+		}
+	}
+
+	return gpio;
+}
+
+static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
+							    struct radeon_gpio_rec *gpio)
+{
+	struct radeon_hpd hpd;
+	hpd.gpio = *gpio;
+	if (gpio->reg == AVIVO_DC_GPIO_HPD_A) {
+		switch(gpio->mask) {
+		case (1 << 0):
+			hpd.hpd = RADEON_HPD_1;
+			break;
+		case (1 << 8):
+			hpd.hpd = RADEON_HPD_2;
+			break;
+		case (1 << 16):
+			hpd.hpd = RADEON_HPD_3;
+			break;
+		case (1 << 24):
+			hpd.hpd = RADEON_HPD_4;
+			break;
+		case (1 << 26):
+			hpd.hpd = RADEON_HPD_5;
+			break;
+		case (1 << 28):
+			hpd.hpd = RADEON_HPD_6;
+			break;
+		default:
+			hpd.hpd = RADEON_HPD_NONE;
+			break;
+		}
+	} else
+		hpd.hpd = RADEON_HPD_NONE;
+	return hpd;
+}
+
 static bool radeon_atom_apply_quirks(struct drm_device *dev,
 				     uint32_t supported_device,
 				     int *connector_type,
 				     struct radeon_i2c_bus_rec *i2c_bus,
-				     uint16_t *line_mux)
+				     uint16_t *line_mux,
+				     struct radeon_hpd *hpd)
 {
+	struct radeon_device *rdev = dev->dev_private;
 
 	/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
 	if ((dev->pdev->device == 0x791e) &&
@@ -117,6 +215,15 @@
 			*connector_type = DRM_MODE_CONNECTOR_DVID;
 	}
 
+	/* Asrock RS600 board lists the DVI port as HDMI */
+	if ((dev->pdev->device == 0x7941) &&
+	    (dev->pdev->subsystem_vendor == 0x1849) &&
+	    (dev->pdev->subsystem_device == 0x7941)) {
+		if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP3_SUPPORT))
+			*connector_type = DRM_MODE_CONNECTOR_DVID;
+	}
+
 	/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
 	if ((dev->pdev->device == 0x7941) &&
 	    (dev->pdev->subsystem_vendor == 0x147b) &&
@@ -135,6 +242,23 @@
 		}
 	}
 
+	/* HIS X1300 is DVI+VGA, not DVI+DVI */
+	if ((dev->pdev->device == 0x7146) &&
+	    (dev->pdev->subsystem_vendor == 0x17af) &&
+	    (dev->pdev->subsystem_device == 0x2058)) {
+		if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
+			return false;
+	}
+
+	/* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
+	if ((dev->pdev->device == 0x7142) &&
+	    (dev->pdev->subsystem_vendor == 0x1458) &&
+	    (dev->pdev->subsystem_device == 0x2134)) {
+		if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
+			return false;
+	}
+
+
 	/* Funky macbooks */
 	if ((dev->pdev->device == 0x71C5) &&
 	    (dev->pdev->subsystem_vendor == 0x106b) &&
@@ -142,6 +266,15 @@
 		if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
 		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
 			return false;
+		if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
+			*line_mux = 0x90;
+	}
+
+	/* mac rv630, rv730, others */
+	if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) &&
+	    (*connector_type == DRM_MODE_CONNECTOR_DVII)) {
+		*connector_type = DRM_MODE_CONNECTOR_9PinDIN;
+		*line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1;
 	}
 
 	/* ASUS HD 3600 XT board lists the DVI port as HDMI */
@@ -153,6 +286,15 @@
 		}
 	}
 
+	/* ASUS HD 3600 board lists the DVI port as HDMI */
+	if ((dev->pdev->device == 0x9598) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x01e4)) {
+		if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+			*connector_type = DRM_MODE_CONNECTOR_DVII;
+		}
+	}
+
 	/* ASUS HD 3450 board lists the DVI port as HDMI */
 	if ((dev->pdev->device == 0x95C5) &&
 	    (dev->pdev->subsystem_vendor == 0x1043) &&
@@ -172,6 +314,33 @@
 		}
 	}
 
+	/* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */
+	if ((dev->pdev->device == 0x95c4) &&
+	    (dev->pdev->subsystem_vendor == 0x1025) &&
+	    (dev->pdev->subsystem_device == 0x013c)) {
+		struct radeon_gpio_rec gpio;
+
+		if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
+		    (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
+			gpio = radeon_lookup_gpio(rdev, 6);
+			*hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+			*connector_type = DRM_MODE_CONNECTOR_DVID;
+		} else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+			   (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) {
+			gpio = radeon_lookup_gpio(rdev, 7);
+			*hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+		}
+	}
+
+	/* XFX Pine Group device rv730 reports no VGA DDC lines
+	 * even though they are wired up to record 0x93
+	 */
+	if ((dev->pdev->device == 0x9498) &&
+	    (dev->pdev->subsystem_vendor == 0x1682) &&
+	    (dev->pdev->subsystem_device == 0x2452)) {
+		struct radeon_device *rdev = dev->dev_private;
+		*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
+	}
 	return true;
 }
 
@@ -231,7 +400,9 @@
 	DRM_MODE_CONNECTOR_Unknown,
 	DRM_MODE_CONNECTOR_Unknown,
 	DRM_MODE_CONNECTOR_Unknown,
-	DRM_MODE_CONNECTOR_DisplayPort
+	DRM_MODE_CONNECTOR_DisplayPort,
+	DRM_MODE_CONNECTOR_eDP,
+	DRM_MODE_CONNECTOR_Unknown
 };
 
 bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
@@ -240,16 +411,18 @@
 	struct radeon_mode_info *mode_info = &rdev->mode_info;
 	struct atom_context *ctx = mode_info->atom_context;
 	int index = GetIndexIntoMasterTable(DATA, Object_Header);
-	uint16_t size, data_offset;
-	uint8_t frev, crev, line_mux = 0;
+	u16 size, data_offset;
+	u8 frev, crev;
 	ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
 	ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
 	ATOM_OBJECT_HEADER *obj_header;
 	int i, j, path_size, device_support;
 	int connector_type;
-	uint16_t igp_lane_info, conn_id, connector_object_id;
+	u16 igp_lane_info, conn_id, connector_object_id;
 	bool linkb;
 	struct radeon_i2c_bus_rec ddc_bus;
+	struct radeon_gpio_rec gpio;
+	struct radeon_hpd hpd;
 
 	atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
 
@@ -276,7 +449,6 @@
 		path = (ATOM_DISPLAY_OBJECT_PATH *) addr;
 		path_size += le16_to_cpu(path->usSize);
 		linkb = false;
-
 		if (device_support & le16_to_cpu(path->usDeviceTag)) {
 			uint8_t con_obj_id, con_obj_num, con_obj_type;
 
@@ -377,10 +549,11 @@
 				}
 			}
 
-			/* look up gpio for ddc */
+			/* look up gpio for ddc, hpd */
+			ddc_bus.valid = false;
+			hpd.hpd = RADEON_HPD_NONE;
 			if ((le16_to_cpu(path->usDeviceTag) &
-			     (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-			    == 0) {
+			     (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
 				for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
 					if (le16_to_cpu(path->usConnObjectId) ==
 					    le16_to_cpu(con_obj->asObjects[j].
@@ -394,21 +567,34 @@
 								 asObjects[j].
 								 usRecordOffset));
 						ATOM_I2C_RECORD *i2c_record;
+						ATOM_HPD_INT_RECORD *hpd_record;
+						ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
+						hpd.hpd = RADEON_HPD_NONE;
 
 						while (record->ucRecordType > 0
 						       && record->
 						       ucRecordType <=
 						       ATOM_MAX_OBJECT_RECORD_NUMBER) {
-							switch (record->
-								ucRecordType) {
+							switch (record->ucRecordType) {
 							case ATOM_I2C_RECORD_TYPE:
 								i2c_record =
-								    (ATOM_I2C_RECORD
-								     *) record;
-								line_mux =
-								    i2c_record->
-								    sucI2cId.
-								    bfI2C_LineMux;
+								    (ATOM_I2C_RECORD *)
+									record;
+								i2c_config =
+									(ATOM_I2C_ID_CONFIG_ACCESS *)
+									&i2c_record->sucI2cId;
+								ddc_bus = radeon_lookup_i2c_gpio(rdev,
+												 i2c_config->
+												 ucAccess);
+								break;
+							case ATOM_HPD_INT_RECORD_TYPE:
+								hpd_record =
+									(ATOM_HPD_INT_RECORD *)
+									record;
+								gpio = radeon_lookup_gpio(rdev,
+											  hpd_record->ucHPDIntGPIOID);
+								hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
+								hpd.plugged_state = hpd_record->ucPlugged_PinState;
 								break;
 							}
 							record =
@@ -421,24 +607,13 @@
 						break;
 					}
 				}
-			} else
-				line_mux = 0;
-
-			if ((le16_to_cpu(path->usDeviceTag) ==
-			     ATOM_DEVICE_TV1_SUPPORT)
-			    || (le16_to_cpu(path->usDeviceTag) ==
-				ATOM_DEVICE_TV2_SUPPORT)
-			    || (le16_to_cpu(path->usDeviceTag) ==
-				ATOM_DEVICE_CV_SUPPORT))
-				ddc_bus.valid = false;
-			else
-				ddc_bus = radeon_lookup_gpio(dev, line_mux);
+			}
 
 			conn_id = le16_to_cpu(path->usConnObjectId);
 
 			if (!radeon_atom_apply_quirks
 			    (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
-			     &ddc_bus, &conn_id))
+			     &ddc_bus, &conn_id, &hpd))
 				continue;
 
 			radeon_add_atom_connector(dev,
@@ -447,7 +622,8 @@
 							      usDeviceTag),
 						  connector_type, &ddc_bus,
 						  linkb, igp_lane_info,
-						  connector_object_id);
+						  connector_object_id,
+						  &hpd);
 
 		}
 	}
@@ -502,6 +678,7 @@
 	uint16_t devices;
 	int connector_type;
 	struct radeon_i2c_bus_rec ddc_bus;
+	struct radeon_hpd hpd;
 };
 
 bool radeon_get_atom_connector_info_from_supported_devices_table(struct
@@ -517,7 +694,7 @@
 	uint16_t device_support;
 	uint8_t dac;
 	union atom_supported_devices *supported_devices;
-	int i, j;
+	int i, j, max_device;
 	struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
 
 	atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
@@ -527,7 +704,12 @@
 
 	device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
 
-	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+	if (frev > 1)
+		max_device = ATOM_MAX_SUPPORTED_DEVICE;
+	else
+		max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
+
+	for (i = 0; i < max_device; i++) {
 		ATOM_CONNECTOR_INFO_I2C ci =
 		    supported_devices->info.asConnInfo[i];
 
@@ -553,22 +735,8 @@
 
 		dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
 
-		if ((rdev->family == CHIP_RS690) ||
-		    (rdev->family == CHIP_RS740)) {
-			if ((i == ATOM_DEVICE_DFP2_INDEX)
-			    && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2))
-				bios_connectors[i].line_mux =
-				    ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
-			else if ((i == ATOM_DEVICE_DFP3_INDEX)
-				 && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1))
-				bios_connectors[i].line_mux =
-				    ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1;
-			else
-				bios_connectors[i].line_mux =
-				    ci.sucI2cId.sbfAccess.bfI2C_LineMux;
-		} else
-			bios_connectors[i].line_mux =
-			    ci.sucI2cId.sbfAccess.bfI2C_LineMux;
+		bios_connectors[i].line_mux =
+			ci.sucI2cId.ucAccess;
 
 		/* give tv unique connector ids */
 		if (i == ATOM_DEVICE_TV1_INDEX) {
@@ -582,8 +750,30 @@
 			bios_connectors[i].line_mux = 52;
 		} else
 			bios_connectors[i].ddc_bus =
-			    radeon_lookup_gpio(dev,
-					       bios_connectors[i].line_mux);
+			    radeon_lookup_i2c_gpio(rdev,
+						   bios_connectors[i].line_mux);
+
+		if ((crev > 1) && (frev > 1)) {
+			u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
+			switch (isb) {
+			case 0x4:
+				bios_connectors[i].hpd.hpd = RADEON_HPD_1;
+				break;
+			case 0xa:
+				bios_connectors[i].hpd.hpd = RADEON_HPD_2;
+				break;
+			default:
+				bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
+				break;
+			}
+		} else {
+			if (i == ATOM_DEVICE_DFP1_INDEX)
+				bios_connectors[i].hpd.hpd = RADEON_HPD_1;
+			else if (i == ATOM_DEVICE_DFP2_INDEX)
+				bios_connectors[i].hpd.hpd = RADEON_HPD_2;
+			else
+				bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
+		}
 
 		/* Always set the connector type to VGA for CRT1/CRT2. if they are
 		 * shared with a DVI port, we'll pick up the DVI connector when we
@@ -595,7 +785,8 @@
 
 		if (!radeon_atom_apply_quirks
 		    (dev, (1 << i), &bios_connectors[i].connector_type,
-		     &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
+		     &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
+		     &bios_connectors[i].hpd))
 			continue;
 
 		bios_connectors[i].valid = true;
@@ -610,41 +801,42 @@
 		else
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
-									(1 <<
-									 i),
+									(1 << i),
 									dac),
 						  (1 << i));
 	}
 
 	/* combine shared connectors */
-	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+	for (i = 0; i < max_device; i++) {
 		if (bios_connectors[i].valid) {
-			for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) {
+			for (j = 0; j < max_device; j++) {
 				if (bios_connectors[j].valid && (i != j)) {
 					if (bios_connectors[i].line_mux ==
 					    bios_connectors[j].line_mux) {
-						if (((bios_connectors[i].
-						      devices &
-						      (ATOM_DEVICE_DFP_SUPPORT))
-						     && (bios_connectors[j].
-							 devices &
-							 (ATOM_DEVICE_CRT_SUPPORT)))
-						    ||
-						    ((bios_connectors[j].
-						      devices &
-						      (ATOM_DEVICE_DFP_SUPPORT))
-						     && (bios_connectors[i].
-							 devices &
-							 (ATOM_DEVICE_CRT_SUPPORT)))) {
-							bios_connectors[i].
-							    devices |=
-							    bios_connectors[j].
-							    devices;
-							bios_connectors[i].
-							    connector_type =
-							    DRM_MODE_CONNECTOR_DVII;
-							bios_connectors[j].
-							    valid = false;
+						/* make sure not to combine LVDS */
+						if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+							bios_connectors[i].line_mux = 53;
+							bios_connectors[i].ddc_bus.valid = false;
+							continue;
+						}
+						if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+							bios_connectors[j].line_mux = 53;
+							bios_connectors[j].ddc_bus.valid = false;
+							continue;
+						}
+						/* combine analog and digital for DVI-I */
+						if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
+						     (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) ||
+						    ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) &&
+						     (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) {
+							bios_connectors[i].devices |=
+								bios_connectors[j].devices;
+							bios_connectors[i].connector_type =
+								DRM_MODE_CONNECTOR_DVII;
+							if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT))
+								bios_connectors[i].hpd =
+									bios_connectors[j].hpd;
+							bios_connectors[j].valid = false;
 						}
 					}
 				}
@@ -653,7 +845,7 @@
 	}
 
 	/* add the connectors */
-	for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+	for (i = 0; i < max_device; i++) {
 		if (bios_connectors[i].valid) {
 			uint16_t connector_object_id =
 				atombios_get_connector_object_id(dev,
@@ -666,7 +858,8 @@
 						  connector_type,
 						  &bios_connectors[i].ddc_bus,
 						  false, 0,
-						  connector_object_id);
+						  connector_object_id,
+						  &bios_connectors[i].hpd);
 		}
 	}
 
@@ -731,7 +924,8 @@
 			 * pre-DCE 3.0 r6xx hardware.  This might need to be adjusted per
 			 * family.
 			 */
-			p1pll->pll_out_min = 64800;
+			if (!radeon_new_pll)
+				p1pll->pll_out_min = 64800;
 		}
 
 		p1pll->pll_in_min =
@@ -797,6 +991,47 @@
 	return false;
 }
 
+union igp_info {
+	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
+	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
+};
+
+bool radeon_atombios_sideport_present(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+	union igp_info *igp_info;
+	u8 frev, crev;
+	u16 data_offset;
+
+	/* sideport is AMD only */
+	if (rdev->family == CHIP_RS600)
+		return false;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
+			       &crev, &data_offset);
+
+	igp_info = (union igp_info *)(mode_info->atom_context->bios +
+				      data_offset);
+
+	if (igp_info) {
+		switch (crev) {
+		case 1:
+			if (igp_info->info.ulBootUpMemoryClock)
+				return true;
+			break;
+		case 2:
+			if (igp_info->info_2.ulBootUpSidePortClock)
+				return true;
+			break;
+		default:
+			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
+			break;
+		}
+	}
+	return false;
+}
+
 bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
 				   struct radeon_encoder_int_tmds *tmds)
 {
@@ -861,6 +1096,7 @@
 	struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
 	uint8_t frev, crev;
 	struct radeon_atom_ss *ss = NULL;
+	int i;
 
 	if (id > ATOM_MAX_SS_ENTRY)
 		return NULL;
@@ -878,12 +1114,18 @@
 		if (!ss)
 			return NULL;
 
-		ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage);
-		ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType;
-		ss->step = ss_info->asSS_Info[id].ucSS_Step;
-		ss->delay = ss_info->asSS_Info[id].ucSS_Delay;
-		ss->range = ss_info->asSS_Info[id].ucSS_Range;
-		ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div;
+		for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) {
+			if (ss_info->asSS_Info[i].ucSS_Id == id) {
+				ss->percentage =
+					le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
+				ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType;
+				ss->step = ss_info->asSS_Info[i].ucSS_Step;
+				ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
+				ss->range = ss_info->asSS_Info[i].ucSS_Range;
+				ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
+				break;
+			}
+		}
 	}
 	return ss;
 }
@@ -901,7 +1143,7 @@
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_mode_info *mode_info = &rdev->mode_info;
 	int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
-	uint16_t data_offset;
+	uint16_t data_offset, misc;
 	union lvds_info *lvds_info;
 	uint8_t frev, crev;
 	struct radeon_encoder_atom_dig *lvds = NULL;
@@ -934,17 +1176,42 @@
 		lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
 			le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
 		lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
-			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
 		lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
 			le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
 		lvds->panel_pwr_delay =
 		    le16_to_cpu(lvds_info->info.usOffDelayInMs);
 		lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
+
+		misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
+		if (misc & ATOM_VSYNC_POLARITY)
+			lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+		if (misc & ATOM_HSYNC_POLARITY)
+			lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
+		if (misc & ATOM_COMPOSITESYNC)
+			lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
+		if (misc & ATOM_INTERLACE)
+			lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+		if (misc & ATOM_DOUBLE_CLOCK_MODE)
+			lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
+
 		/* set crtc values */
 		drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
 
 		lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
 
+		if (ASIC_IS_AVIVO(rdev)) {
+			if (radeon_new_pll == 0)
+				lvds->pll_algo = PLL_ALGO_LEGACY;
+			else
+				lvds->pll_algo = PLL_ALGO_NEW;
+		} else {
+			if (radeon_new_pll == 1)
+				lvds->pll_algo = PLL_ALGO_NEW;
+			else
+				lvds->pll_algo = PLL_ALGO_LEGACY;
+		}
+
 		encoder->native_mode = lvds->native_mode;
 	}
 	return lvds;
@@ -1074,6 +1341,61 @@
 	return true;
 }
 
+enum radeon_tv_std
+radeon_atombios_get_tv_info(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
+	uint16_t data_offset;
+	uint8_t frev, crev;
+	struct _ATOM_ANALOG_TV_INFO *tv_info;
+	enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+
+	tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
+
+	switch (tv_info->ucTV_BootUpDefaultStandard) {
+	case ATOM_TV_NTSC:
+		tv_std = TV_STD_NTSC;
+		DRM_INFO("Default TV standard: NTSC\n");
+		break;
+	case ATOM_TV_NTSCJ:
+		tv_std = TV_STD_NTSC_J;
+		DRM_INFO("Default TV standard: NTSC-J\n");
+		break;
+	case ATOM_TV_PAL:
+		tv_std = TV_STD_PAL;
+		DRM_INFO("Default TV standard: PAL\n");
+		break;
+	case ATOM_TV_PALM:
+		tv_std = TV_STD_PAL_M;
+		DRM_INFO("Default TV standard: PAL-M\n");
+		break;
+	case ATOM_TV_PALN:
+		tv_std = TV_STD_PAL_N;
+		DRM_INFO("Default TV standard: PAL-N\n");
+		break;
+	case ATOM_TV_PALCN:
+		tv_std = TV_STD_PAL_CN;
+		DRM_INFO("Default TV standard: PAL-CN\n");
+		break;
+	case ATOM_TV_PAL60:
+		tv_std = TV_STD_PAL_60;
+		DRM_INFO("Default TV standard: PAL-60\n");
+		break;
+	case ATOM_TV_SECAM:
+		tv_std = TV_STD_SECAM;
+		DRM_INFO("Default TV standard: SECAM\n");
+		break;
+	default:
+		tv_std = TV_STD_NTSC;
+		DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+		break;
+	}
+	return tv_std;
+}
+
 struct radeon_encoder_tv_dac *
 radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
 {
@@ -1109,6 +1431,7 @@
 		dac = dac_info->ucDAC2_NTSC_DAC_Adjustment;
 		tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
 
+		tv_dac->tv_std = radeon_atombios_get_tv_info(rdev);
 	}
 	return tv_dac;
 }
@@ -1193,7 +1516,7 @@
 	bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE;
 
 	/* tell the bios not to handle mode switching */
-	bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE);
+	bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
 
 	if (rdev->family >= CHIP_R600) {
 		WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
@@ -1244,10 +1567,13 @@
 	else
 		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
 
-	if (lock)
+	if (lock) {
 		bios_6_scratch |= ATOM_S6_CRITICAL_STATE;
-	else
+		bios_6_scratch &= ~ATOM_S6_ACC_MODE;
+	} else {
 		bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE;
+		bios_6_scratch |= ATOM_S6_ACC_MODE;
+	}
 
 	if (rdev->family >= CHIP_R600)
 		WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r300_cmdbuf.c
@@ -990,7 +990,7 @@
 	int sz;
 	int addr;
 	int type;
-	int clamp;
+	int isclamp;
 	int stride;
 	RING_LOCALS;
 
@@ -999,10 +999,10 @@
 	addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
 
 	type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
-	clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+	isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
 
 	addr |= (type << 16);
-	addr |= (clamp << 17);
+	addr |= (isclamp << 17);
 
 	stride = type ? 4 : 6;
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_object.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_object.h
@@ -28,19 +28,146 @@
 #ifndef __RADEON_OBJECT_H__
 #define __RADEON_OBJECT_H__
 
-#include <ttm/ttm_bo_api.h>
-#include <ttm/ttm_bo_driver.h>
-#include <ttm/ttm_placement.h>
-#include <ttm/ttm_module.h>
+#include <drm/radeon_drm.h>
+#include "radeon.h"
 
-/*
- * TTM.
+/**
+ * radeon_mem_type_to_domain - return domain corresponding to mem_type
+ * @mem_type:	ttm memory type
+ *
+ * Returns corresponding domain of the ttm mem_type
  */
-struct radeon_mman {
-	struct ttm_bo_global_ref        bo_global_ref;
-	struct ttm_global_reference	mem_global_ref;
-	bool				mem_global_referenced;
-	struct ttm_bo_device		bdev;
-};
+static inline unsigned radeon_mem_type_to_domain(u32 mem_type)
+{
+	switch (mem_type) {
+	case TTM_PL_VRAM:
+		return RADEON_GEM_DOMAIN_VRAM;
+	case TTM_PL_TT:
+		return RADEON_GEM_DOMAIN_GTT;
+	case TTM_PL_SYSTEM:
+		return RADEON_GEM_DOMAIN_CPU;
+	default:
+		break;
+	}
+	return 0;
+}
 
+/**
+ * radeon_bo_reserve - reserve bo
+ * @bo:		bo structure
+ * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
+ *
+ * Returns:
+ * -EBUSY: buffer is busy and @no_wait is true
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
+ * a signal. Release all buffer reservations and return to user-space.
+ */
+static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
+		return r;
+	}
+	return 0;
+}
+
+static inline void radeon_bo_unreserve(struct radeon_bo *bo)
+{
+	ttm_bo_unreserve(&bo->tbo);
+}
+
+/**
+ * radeon_bo_gpu_offset - return GPU offset of bo
+ * @bo:	radeon object for which we query the offset
+ *
+ * Returns current GPU offset of the object.
+ *
+ * Note: object should either be pinned or reserved when calling this
+ * function, it might be usefull to add check for this for debugging.
+ */
+static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo)
+{
+	return bo->tbo.offset;
+}
+
+static inline unsigned long radeon_bo_size(struct radeon_bo *bo)
+{
+	return bo->tbo.num_pages << PAGE_SHIFT;
+}
+
+static inline bool radeon_bo_is_reserved(struct radeon_bo *bo)
+{
+	return !!atomic_read(&bo->tbo.reserved);
+}
+
+/**
+ * radeon_bo_mmap_offset - return mmap offset of bo
+ * @bo:	radeon object for which we query the offset
+ *
+ * Returns mmap offset of the object.
+ *
+ * Note: addr_space_offset is constant after ttm bo init thus isn't protected
+ * by any lock.
+ */
+static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo)
+{
+	return bo->tbo.addr_space_offset;
+}
+
+static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
+					bool no_wait)
+{
+	int r;
+
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
+	if (unlikely(r != 0)) {
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
+		return r;
+	}
+	spin_lock(&bo->tbo.lock);
+	if (mem_type)
+		*mem_type = bo->tbo.mem.mem_type;
+	if (bo->tbo.sync_obj)
+		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	spin_unlock(&bo->tbo.lock);
+	ttm_bo_unreserve(&bo->tbo);
+	return r;
+}
+
+extern int radeon_bo_create(struct radeon_device *rdev,
+				struct drm_gem_object *gobj, unsigned long size,
+				bool kernel, u32 domain,
+				struct radeon_bo **bo_ptr);
+extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
+extern void radeon_bo_kunmap(struct radeon_bo *bo);
+extern void radeon_bo_unref(struct radeon_bo **bo);
+extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
+extern int radeon_bo_unpin(struct radeon_bo *bo);
+extern int radeon_bo_evict_vram(struct radeon_device *rdev);
+extern void radeon_bo_force_delete(struct radeon_device *rdev);
+extern int radeon_bo_init(struct radeon_device *rdev);
+extern void radeon_bo_fini(struct radeon_device *rdev);
+extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
+				struct list_head *head);
+extern int radeon_bo_list_reserve(struct list_head *head);
+extern void radeon_bo_list_unreserve(struct list_head *head);
+extern int radeon_bo_list_validate(struct list_head *head);
+extern void radeon_bo_list_fence(struct list_head *head, void *fence);
+extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
+				struct vm_area_struct *vma);
+extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
+				u32 tiling_flags, u32 pitch);
+extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
+				u32 *tiling_flags, u32 *pitch);
+extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
+				bool force_drop);
+extern void radeon_bo_move_notify(struct ttm_buffer_object *bo,
+					struct ttm_mem_reg *mem);
+extern void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
+extern int radeon_bo_get_surface_reg(struct radeon_bo *bo);
 #endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_fixed.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_fixed.h
@@ -38,6 +38,23 @@
 #define fixed_init_half(A) { .full = rfixed_const_half((A)) }
 #define rfixed_trunc(A) ((A).full >> 12)
 
+static inline u32 rfixed_floor(fixed20_12 A)
+{
+	u32 non_frac = rfixed_trunc(A);
+
+	return rfixed_const(non_frac);
+}
+
+static inline u32 rfixed_ceil(fixed20_12 A)
+{
+	u32 non_frac = rfixed_trunc(A);
+
+	if (A.full > rfixed_const(non_frac))
+		return rfixed_const(non_frac + 1);
+	else
+		return rfixed_const(non_frac);
+}
+
 static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B)
 {
 	u64 tmp = ((u64)A.full << 13);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r300_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r300_reg.h
@@ -900,6 +900,7 @@
 #	define R300_TX_FORMAT_FL_I32		    0x1B
 #	define R300_TX_FORMAT_FL_I32A32		    0x1C
 #	define R300_TX_FORMAT_FL_R32G32B32A32	    0x1D
+#	define R300_TX_FORMAT_ATI2N		    0x1F
 	/* alpha modes, convenience mostly */
 	/* if you have alpha, pick constant appropriate to the
 	   number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
@@ -1368,6 +1369,8 @@
 #define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
 #define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
 
+#define R300_RB3D_AARESOLVE_OFFSET          0x4E80
+#define R300_RB3D_AARESOLVE_PITCH           0x4E84
 #define R300_RB3D_AARESOLVE_CTL             0x4E88
 /* gap */
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r100.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r100.c
@@ -65,6 +65,96 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+/* hpd for digital panel detect/disconnect */
+bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
+{
+	bool connected = false;
+
+	switch (hpd) {
+	case RADEON_HPD_1:
+		if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE)
+			connected = true;
+		break;
+	case RADEON_HPD_2:
+		if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE)
+			connected = true;
+		break;
+	default:
+		break;
+	}
+	return connected;
+}
+
+void r100_hpd_set_polarity(struct radeon_device *rdev,
+			   enum radeon_hpd_id hpd)
+{
+	u32 tmp;
+	bool connected = r100_hpd_sense(rdev, hpd);
+
+	switch (hpd) {
+	case RADEON_HPD_1:
+		tmp = RREG32(RADEON_FP_GEN_CNTL);
+		if (connected)
+			tmp &= ~RADEON_FP_DETECT_INT_POL;
+		else
+			tmp |= RADEON_FP_DETECT_INT_POL;
+		WREG32(RADEON_FP_GEN_CNTL, tmp);
+		break;
+	case RADEON_HPD_2:
+		tmp = RREG32(RADEON_FP2_GEN_CNTL);
+		if (connected)
+			tmp &= ~RADEON_FP2_DETECT_INT_POL;
+		else
+			tmp |= RADEON_FP2_DETECT_INT_POL;
+		WREG32(RADEON_FP2_GEN_CNTL, tmp);
+		break;
+	default:
+		break;
+	}
+}
+
+void r100_hpd_init(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		switch (radeon_connector->hpd.hpd) {
+		case RADEON_HPD_1:
+			rdev->irq.hpd[0] = true;
+			break;
+		case RADEON_HPD_2:
+			rdev->irq.hpd[1] = true;
+			break;
+		default:
+			break;
+		}
+	}
+	if (rdev->irq.installed)
+		r100_irq_set(rdev);
+}
+
+void r100_hpd_fini(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		switch (radeon_connector->hpd.hpd) {
+		case RADEON_HPD_1:
+			rdev->irq.hpd[0] = false;
+			break;
+		case RADEON_HPD_2:
+			rdev->irq.hpd[1] = false;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 /*
  * PCI GART
  */
@@ -94,6 +184,15 @@
 	return radeon_gart_table_ram_alloc(rdev);
 }
 
+/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
+void r100_enable_bm(struct radeon_device *rdev)
+{
+	uint32_t tmp;
+	/* Enable bus mastering */
+	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+	WREG32(RADEON_BUS_CNTL, tmp);
+}
+
 int r100_pci_gart_enable(struct radeon_device *rdev)
 {
 	uint32_t tmp;
@@ -105,9 +204,6 @@
 	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
 	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
 	WREG32(RADEON_AIC_HI_ADDR, tmp);
-	/* Enable bus mastering */
-	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-	WREG32(RADEON_BUS_CNTL, tmp);
 	/* set PCI GART page-table base address */
 	WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
@@ -148,6 +244,11 @@
 {
 	uint32_t tmp = 0;
 
+	if (!rdev->irq.installed) {
+		WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+		WREG32(R_000040_GEN_INT_CNTL, 0);
+		return -EINVAL;
+	}
 	if (rdev->irq.sw_int) {
 		tmp |= RADEON_SW_INT_ENABLE;
 	}
@@ -157,6 +258,12 @@
 	if (rdev->irq.crtc_vblank_int[1]) {
 		tmp |= RADEON_CRTC2_VBLANK_MASK;
 	}
+	if (rdev->irq.hpd[0]) {
+		tmp |= RADEON_FP_DETECT_MASK;
+	}
+	if (rdev->irq.hpd[1]) {
+		tmp |= RADEON_FP2_DETECT_MASK;
+	}
 	WREG32(RADEON_GEN_INT_CNTL, tmp);
 	return 0;
 }
@@ -175,8 +282,9 @@
 static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
 {
 	uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
-	uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
-		RADEON_CRTC2_VBLANK_STAT;
+	uint32_t irq_mask = RADEON_SW_INT_TEST |
+		RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT |
+		RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT;
 
 	if (irqs) {
 		WREG32(RADEON_GEN_INT_STATUS, irqs);
@@ -187,6 +295,7 @@
 int r100_irq_process(struct radeon_device *rdev)
 {
 	uint32_t status, msi_rearm;
+	bool queue_hotplug = false;
 
 	status = r100_irq_ack(rdev);
 	if (!status) {
@@ -207,8 +316,18 @@
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			drm_handle_vblank(rdev->ddev, 1);
 		}
+		if (status & RADEON_FP_DETECT_STAT) {
+			queue_hotplug = true;
+			DRM_DEBUG("HPD1\n");
+		}
+		if (status & RADEON_FP2_DETECT_STAT) {
+			queue_hotplug = true;
+			DRM_DEBUG("HPD2\n");
+		}
 		status = r100_irq_ack(rdev);
 	}
+	if (queue_hotplug)
+		queue_work(rdev->wq, &rdev->hotplug_work);
 	if (rdev->msi_enabled) {
 		switch (rdev->family) {
 		case CHIP_RS400:
@@ -235,14 +354,25 @@
 		return RREG32(RADEON_CRTC2_CRNT_FRAME);
 }
 
+/* Who ever call radeon_fence_emit should call ring_lock and ask
+ * for enough space (today caller are ib schedule and buffer move) */
 void r100_fence_ring_emit(struct radeon_device *rdev,
 			  struct radeon_fence *fence)
 {
-	/* Who ever call radeon_fence_emit should call ring_lock and ask
-	 * for enough space (today caller are ib schedule and buffer move) */
+	/* We have to make sure that caches are flushed before
+	 * CPU might read something from VRAM. */
+	radeon_ring_write(rdev, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, RADEON_RB3D_DC_FLUSH_ALL);
+	radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL);
 	/* Wait until IDLE & CLEAN */
 	radeon_ring_write(rdev, PACKET0(0x1720, 0));
 	radeon_ring_write(rdev, (1 << 16) | (1 << 17));
+	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
+				RADEON_HDP_READ_BUFFER_INVALIDATE);
+	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
+	radeon_ring_write(rdev, rdev->config.r100.hdp_cntl);
 	/* Emit fence sequence & fire IRQ */
 	radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0));
 	radeon_ring_write(rdev, fence->seq);
@@ -255,24 +385,27 @@
 	int r;
 
 	if (rdev->wb.wb_obj == NULL) {
-		r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
-					 true,
-					 RADEON_GEM_DOMAIN_GTT,
-					 false, &rdev->wb.wb_obj);
+		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true,
+					RADEON_GEM_DOMAIN_GTT,
+					&rdev->wb.wb_obj);
 		if (r) {
-			DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r);
+			dev_err(rdev->dev, "(%d) create WB buffer failed\n", r);
 			return r;
 		}
-		r = radeon_object_pin(rdev->wb.wb_obj,
-				      RADEON_GEM_DOMAIN_GTT,
-				      &rdev->wb.gpu_addr);
+		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
+		if (unlikely(r != 0))
+			return r;
+		r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
+					&rdev->wb.gpu_addr);
 		if (r) {
-			DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r);
+			dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r);
+			radeon_bo_unreserve(rdev->wb.wb_obj);
 			return r;
 		}
-		r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
+		r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb);
+		radeon_bo_unreserve(rdev->wb.wb_obj);
 		if (r) {
-			DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r);
+			dev_err(rdev->dev, "(%d) map WB buffer failed\n", r);
 			return r;
 		}
 	}
@@ -290,11 +423,19 @@
 
 void r100_wb_fini(struct radeon_device *rdev)
 {
+	int r;
+
 	r100_wb_disable(rdev);
 	if (rdev->wb.wb_obj) {
-		radeon_object_kunmap(rdev->wb.wb_obj);
-		radeon_object_unpin(rdev->wb.wb_obj);
-		radeon_object_unref(&rdev->wb.wb_obj);
+		r = radeon_bo_reserve(rdev->wb.wb_obj, false);
+		if (unlikely(r != 0)) {
+			dev_err(rdev->dev, "(%d) can't finish WB\n", r);
+			return;
+		}
+		radeon_bo_kunmap(rdev->wb.wb_obj);
+		radeon_bo_unpin(rdev->wb.wb_obj);
+		radeon_bo_unreserve(rdev->wb.wb_obj);
+		radeon_bo_unref(&rdev->wb.wb_obj);
 		rdev->wb.wb = NULL;
 		rdev->wb.wb_obj = NULL;
 	}
@@ -1243,6 +1384,7 @@
 		case RADEON_TXFORMAT_RGB332:
 		case RADEON_TXFORMAT_Y8:
 			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case RADEON_TXFORMAT_AI88:
 		case RADEON_TXFORMAT_ARGB1555:
@@ -1250,19 +1392,27 @@
 		case RADEON_TXFORMAT_ARGB4444:
 		case RADEON_TXFORMAT_VYUY422:
 		case RADEON_TXFORMAT_YVYU422:
-		case RADEON_TXFORMAT_DXT1:
 		case RADEON_TXFORMAT_SHADOW16:
 		case RADEON_TXFORMAT_LDUDV655:
 		case RADEON_TXFORMAT_DUDV88:
 			track->textures[i].cpp = 2;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 			break;
 		case RADEON_TXFORMAT_ARGB8888:
 		case RADEON_TXFORMAT_RGBA8888:
-		case RADEON_TXFORMAT_DXT23:
-		case RADEON_TXFORMAT_DXT45:
 		case RADEON_TXFORMAT_SHADOW32:
 		case RADEON_TXFORMAT_LDUDUV8888:
 			track->textures[i].cpp = 4;
+			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
+			break;
+		case RADEON_TXFORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
+		case RADEON_TXFORMAT_DXT23:
+		case RADEON_TXFORMAT_DXT45:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
 			break;
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
@@ -1288,17 +1438,17 @@
 
 int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
 					 struct radeon_cs_packet *pkt,
-					 struct radeon_object *robj)
+					 struct radeon_bo *robj)
 {
 	unsigned idx;
 	u32 value;
 	idx = pkt->idx + 1;
 	value = radeon_get_ib_value(p, idx + 2);
-	if ((value + 1) > radeon_object_size(robj)) {
+	if ((value + 1) > radeon_bo_size(robj)) {
 		DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
 			  "(need %u have %lu) !\n",
 			  value + 1,
-			  radeon_object_size(robj));
+			  radeon_bo_size(robj));
 		return -EINVAL;
 	}
 	return 0;
@@ -1363,6 +1513,7 @@
 			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
 			return -EINVAL;
 		}
+		track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0));
 		track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
 		track->immd_dwords = pkt->count - 1;
 		r = r100_cs_track_check(p->rdev, track);
@@ -1650,6 +1801,17 @@
 	return 0;
 }
 
+void r100_set_common_regs(struct radeon_device *rdev)
+{
+	/* set these so they don't interfere with anything */
+	WREG32(RADEON_OV0_SCALE_CNTL, 0);
+	WREG32(RADEON_SUBPIC_CNTL, 0);
+	WREG32(RADEON_VIPH_CONTROL, 0);
+	WREG32(RADEON_I2C_CNTL_1, 0);
+	WREG32(RADEON_DVI_I2C_CNTL_1, 0);
+	WREG32(RADEON_CAP0_TRIG_CNTL, 0);
+	WREG32(RADEON_CAP1_TRIG_CNTL, 0);
+}
 
 /*
  * VRAM info
@@ -1756,6 +1918,9 @@
 		rdev->mc.vram_location = 0xFFFFFFFFUL;
 		 /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
 		  * Novell bug 204882 + along with lots of ubuntu ones */
+		if (rdev->mc.aper_size > config_aper_size)
+			config_aper_size = rdev->mc.aper_size;
+
 		if (config_aper_size > rdev->mc.real_vram_size)
 			rdev->mc.mc_vram_size = config_aper_size;
 		else
@@ -2588,28 +2753,63 @@
 	DRM_ERROR("coordinate type            %d\n", t->tex_coord_type);
 	DRM_ERROR("width round to power of 2  %d\n", t->roundup_w);
 	DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
+	DRM_ERROR("compress format            %d\n", t->compress_format);
+}
+
+static int r100_track_compress_size(int compress_format, int w, int h)
+{
+	int block_width, block_height, block_bytes;
+	int wblocks, hblocks;
+	int min_wblocks;
+	int sz;
+
+	block_width = 4;
+	block_height = 4;
+
+	switch (compress_format) {
+	case R100_TRACK_COMP_DXT1:
+		block_bytes = 8;
+		min_wblocks = 4;
+		break;
+	default:
+	case R100_TRACK_COMP_DXT35:
+		block_bytes = 16;
+		min_wblocks = 2;
+		break;
+	}
+
+	hblocks = (h + block_height - 1) / block_height;
+	wblocks = (w + block_width - 1) / block_width;
+	if (wblocks < min_wblocks)
+		wblocks = min_wblocks;
+	sz = wblocks * hblocks * block_bytes;
+	return sz;
 }
 
 static int r100_cs_track_cube(struct radeon_device *rdev,
 			      struct r100_cs_track *track, unsigned idx)
 {
 	unsigned face, w, h;
-	struct radeon_object *cube_robj;
+	struct radeon_bo *cube_robj;
 	unsigned long size;
+	unsigned compress_format = track->textures[idx].compress_format;
 
 	for (face = 0; face < 5; face++) {
 		cube_robj = track->textures[idx].cube_info[face].robj;
 		w = track->textures[idx].cube_info[face].width;
 		h = track->textures[idx].cube_info[face].height;
 
-		size = w * h;
+		if (compress_format) {
+			size = r100_track_compress_size(compress_format, w, h);
+		} else
+			size = w * h;
 		size *= track->textures[idx].cpp;
 
 		size += track->textures[idx].cube_info[face].offset;
 
-		if (size > radeon_object_size(cube_robj)) {
+		if (size > radeon_bo_size(cube_robj)) {
 			DRM_ERROR("Cube texture offset greater than object size %lu %lu\n",
-				  size, radeon_object_size(cube_robj));
+				  size, radeon_bo_size(cube_robj));
 			r100_cs_track_texture_print(&track->textures[idx]);
 			return -1;
 		}
@@ -2620,7 +2820,7 @@
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
 				       struct r100_cs_track *track)
 {
-	struct radeon_object *robj;
+	struct radeon_bo *robj;
 	unsigned long size;
 	unsigned u, i, w, h;
 	int ret;
@@ -2628,6 +2828,8 @@
 	for (u = 0; u < track->num_texture; u++) {
 		if (!track->textures[u].enabled)
 			continue;
+		if (track->textures[u].lookup_disable)
+			continue;
 		robj = track->textures[u].robj;
 		if (robj == NULL) {
 			DRM_ERROR("No texture bound to unit %u\n", u);
@@ -2654,9 +2856,15 @@
 			h = h / (1 << i);
 			if (track->textures[u].roundup_h)
 				h = roundup_pow_of_two(h);
-			size += w * h;
+			if (track->textures[u].compress_format) {
+
+				size += r100_track_compress_size(track->textures[u].compress_format, w, h);
+				/* compressed textures are block based */
+			} else
+				size += w * h;
 		}
 		size *= track->textures[u].cpp;
+
 		switch (track->textures[u].tex_coord_type) {
 		case 0:
 			break;
@@ -2676,9 +2884,9 @@
 				  "%u\n", track->textures[u].tex_coord_type, u);
 			return -EINVAL;
 		}
-		if (size > radeon_object_size(robj)) {
+		if (size > radeon_bo_size(robj)) {
 			DRM_ERROR("Texture of unit %u needs %lu bytes but is "
-				  "%lu\n", u, size, radeon_object_size(robj));
+				  "%lu\n", u, size, radeon_bo_size(robj));
 			r100_cs_track_texture_print(&track->textures[u]);
 			return -EINVAL;
 		}
@@ -2695,15 +2903,19 @@
 
 	for (i = 0; i < track->num_cb; i++) {
 		if (track->cb[i].robj == NULL) {
+			if (!(track->fastfill || track->color_channel_mask ||
+			      track->blend_read_enable)) {
+				continue;
+			}
 			DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
 			return -EINVAL;
 		}
 		size = track->cb[i].pitch * track->cb[i].cpp * track->maxy;
 		size += track->cb[i].offset;
-		if (size > radeon_object_size(track->cb[i].robj)) {
+		if (size > radeon_bo_size(track->cb[i].robj)) {
 			DRM_ERROR("[drm] Buffer too small for color buffer %d "
 				  "(need %lu have %lu) !\n", i, size,
-				  radeon_object_size(track->cb[i].robj));
+				  radeon_bo_size(track->cb[i].robj));
 			DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n",
 				  i, track->cb[i].pitch, track->cb[i].cpp,
 				  track->cb[i].offset, track->maxy);
@@ -2717,16 +2929,37 @@
 		}
 		size = track->zb.pitch * track->zb.cpp * track->maxy;
 		size += track->zb.offset;
-		if (size > radeon_object_size(track->zb.robj)) {
+		if (size > radeon_bo_size(track->zb.robj)) {
 			DRM_ERROR("[drm] Buffer too small for z buffer "
 				  "(need %lu have %lu) !\n", size,
-				  radeon_object_size(track->zb.robj));
+				  radeon_bo_size(track->zb.robj));
 			DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n",
 				  track->zb.pitch, track->zb.cpp,
 				  track->zb.offset, track->maxy);
 			return -EINVAL;
 		}
 	}
+
+	if (track->aa_dirty && track->aaresolve) {
+		if (track->aa.robj == NULL) {
+			DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i);
+			return -EINVAL;
+		}
+		/* I believe the format comes from colorbuffer0. */
+		size = track->aa.pitch * track->cb[0].cpp * track->maxy;
+		size += track->aa.offset;
+		if (size > radeon_bo_size(track->aa.robj)) {
+			DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d "
+				  "(need %lu have %lu) !\n", i, size,
+				  radeon_bo_size(track->aa.robj));
+			DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n",
+				  i, track->aa.pitch, track->cb[0].cpp,
+				  track->aa.offset, track->maxy);
+			return -EINVAL;
+		}
+	}
+	track->aa_dirty = false;
+
 	prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
 	nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
 	switch (prim_walk) {
@@ -2738,11 +2971,12 @@
 					  "bound\n", prim_walk, i);
 				return -EINVAL;
 			}
-			if (size > radeon_object_size(track->arrays[i].robj)) {
-				DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
-					   "have %lu dwords\n", prim_walk, i,
-					   size >> 2,
-					   radeon_object_size(track->arrays[i].robj) >> 2);
+			if (size > radeon_bo_size(track->arrays[i].robj)) {
+				dev_err(rdev->dev, "(PW %u) Vertex array %u "
+					"need %lu dwords have %lu dwords\n",
+					prim_walk, i, size >> 2,
+					radeon_bo_size(track->arrays[i].robj)
+					>> 2);
 				DRM_ERROR("Max indices %u\n", track->max_indx);
 				return -EINVAL;
 			}
@@ -2756,10 +2990,12 @@
 					  "bound\n", prim_walk, i);
 				return -EINVAL;
 			}
-			if (size > radeon_object_size(track->arrays[i].robj)) {
-				DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
-					   "have %lu dwords\n", prim_walk, i, size >> 2,
-					   radeon_object_size(track->arrays[i].robj) >> 2);
+			if (size > radeon_bo_size(track->arrays[i].robj)) {
+				dev_err(rdev->dev, "(PW %u) Vertex array %u "
+					"need %lu dwords have %lu dwords\n",
+					prim_walk, i, size >> 2,
+					radeon_bo_size(track->arrays[i].robj)
+					>> 2);
 				return -EINVAL;
 			}
 		}
@@ -2785,6 +3021,7 @@
 void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track)
 {
 	unsigned i, face;
+	track->aa_dirty = true;
 
 	if (rdev->family < CHIP_R300) {
 		track->num_cb = 1;
@@ -2799,6 +3036,8 @@
 		track->num_texture = 16;
 		track->maxy = 4096;
 		track->separate_cube = 0;
+		track->aaresolve = false;
+		track->aa.robj = NULL;
 	}
 
 	for (i = 0; i < track->num_cb; i++) {
@@ -2821,6 +3060,7 @@
 		track->arrays[i].esize = 0x7F;
 	}
 	for (i = 0; i < track->num_texture; i++) {
+		track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 		track->textures[i].pitch = 16536;
 		track->textures[i].width = 16536;
 		track->textures[i].height = 16536;
@@ -2838,6 +3078,7 @@
 		track->textures[i].robj = NULL;
 		/* CS IB emission code makes sure texture unit are disabled */
 		track->textures[i].enabled = false;
+		track->textures[i].lookup_disable = false;
 		track->textures[i].roundup_w = true;
 		track->textures[i].roundup_h = true;
 		if (track->separate_cube)
@@ -3101,6 +3342,9 @@
 {
 	int r;
 
+	/* set common regs */
+	r100_set_common_regs(rdev);
+	/* program mc */
 	r100_mc_program(rdev);
 	/* Resume clock */
 	r100_clock_startup(rdev);
@@ -3108,14 +3352,15 @@
 	r100_gpu_init(rdev);
 	/* Initialize GART (initialize after TTM so we can allocate
 	 * memory through TTM but finalize after TTM) */
+	r100_enable_bm(rdev);
 	if (rdev->flags & RADEON_IS_PCI) {
 		r = r100_pci_gart_enable(rdev);
 		if (r)
 			return r;
 	}
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	r100_irq_set(rdev);
+	rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -3150,6 +3395,8 @@
 	radeon_combios_asic_init(rdev->ddev);
 	/* Resume clock after posting */
 	r100_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return r100_startup(rdev);
 }
 
@@ -3165,16 +3412,16 @@
 
 void r100_fini(struct radeon_device *rdev)
 {
-	r100_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
 	radeon_gem_fini(rdev);
 	if (rdev->flags & RADEON_IS_PCI)
 		r100_pci_gart_fini(rdev);
+	radeon_agp_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -3195,9 +3442,7 @@
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);
 		if (r) {
-			printk(KERN_WARNING "[drm] Disabling AGP\n");
-			rdev->flags &= ~RADEON_IS_AGP;
-			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+			radeon_agp_disable(rdev);
 		} else {
 			rdev->mc.gtt_location = rdev->mc.agp_base;
 		}
@@ -3242,14 +3487,14 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		radeon_combios_asic_init(rdev->ddev);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
 	/* Set asic errata */
 	r100_errata(rdev);
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	r100_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
@@ -3264,7 +3509,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	if (rdev->flags & RADEON_IS_PCI) {
@@ -3278,13 +3523,12 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		r100_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		if (rdev->flags & RADEON_IS_PCI)
 			r100_pci_gart_fini(rdev);
-		radeon_irq_kms_fini(rdev);
 		rdev->accel_working = false;
 	}
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/Kconfig
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/Kconfig
@@ -1,10 +1,14 @@
 config DRM_RADEON_KMS
-	bool "Enable modesetting on radeon by default"
+	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
 	help
-	  Choose this option if you want kernel modesetting enabled by default,
-	  and you have a new enough userspace to support this. Running old
-	  userspaces with this enabled will cause pain.
+	  Choose this option if you want kernel modesetting enabled by default.
+
+	  This is a completely new driver. It's only part of the existing drm
+	  for compatibility reasons. It requires an entirely different graphics
+	  stack above it and works very differently from the old drm stack.
+	  i.e. don't enable this unless you know what you are doing it may
+	  cause issues or bugs compared to the previous userspace driver stack.
 
 	  When kernel modesetting is enabled the IOCTL of radeon/drm
 	  driver are considered as invalid and an error message is printed
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_state.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_state.c
@@ -101,6 +101,7 @@
 			DRM_ERROR("Invalid depth buffer offset\n");
 			return -EINVAL;
 		}
+		dev_priv->have_z_offset = 1;
 		break;
 
 	case RADEON_EMIT_PP_CNTL:
@@ -876,6 +877,12 @@
 		if (tmp & RADEON_BACK)
 			flags |= RADEON_FRONT;
 	}
+	if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
+		if (!dev_priv->have_z_offset) {
+			printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
+			flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
+		}
+	}
 
 	if (flags & (RADEON_FRONT | RADEON_BACK)) {
 
@@ -1950,7 +1957,7 @@
  * Note that refcount can be at most 2, since during a free refcount=3
  * might mean we have to allocate a new surface which might not always
  * be available.
- * For example : we allocate three contigous surfaces ABC. If B is
+ * For example : we allocate three contiguous surfaces ABC. If B is
  * freed, we suddenly need two surfaces to store A and C, which might
  * not always be available.
  */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_drv.c
@@ -86,6 +86,8 @@
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
+int radeon_new_pll = -1;
+int radeon_audio = 1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -120,6 +122,12 @@
 MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 module_param_named(tv, radeon_tv, int, 0444);
 
+MODULE_PARM_DESC(new_pll, "Select new PLL code");
+module_param_named(new_pll, radeon_new_pll, int, 0444);
+
+MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
+module_param_named(audio, radeon_audio, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -188,7 +196,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
@@ -276,7 +284,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = radeon_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
@@ -316,6 +324,18 @@
 		radeon_modeset = 0;
 	}
 #endif
+	/* Check for known bad devices by default. */
+	if (radeon_modeset == -1) {
+		static struct pci_device_id radeon_badmodeset[] = {
+			{ PCI_DEVICE(0x1002, 0x515e) },
+			{ PCI_DEVICE(0x1002, 0x515f) },
+			{ },
+		};
+		if (pci_dev_present(radeon_badmodeset)) {
+			DRM_INFO("radeon disabling kernel modesetting for known bad device.\n");
+			radeon_modeset = 0;
+		}
+	}
 	/* if enabled by default */
 	if (radeon_modeset == -1) {
 #ifdef CONFIG_DRM_RADEON_KMS
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_fb.c
@@ -59,7 +59,7 @@
 };
 
 /**
- * Curretly it is assumed that the old framebuffer is reused.
+ * Currently it is assumed that the old framebuffer is reused.
  *
  * LOCKING
  * caller should hold the mode config lock.
@@ -140,7 +140,7 @@
 	struct radeon_framebuffer *rfb;
 	struct drm_mode_fb_cmd mode_cmd;
 	struct drm_gem_object *gobj = NULL;
-	struct radeon_object *robj = NULL;
+	struct radeon_bo *rbo = NULL;
 	struct device *device = &rdev->pdev->dev;
 	int size, aligned_size, ret;
 	u64 fb_gpuaddr;
@@ -168,14 +168,14 @@
 	ret = radeon_gem_object_create(rdev, aligned_size, 0,
 			RADEON_GEM_DOMAIN_VRAM,
 			false, ttm_bo_type_kernel,
-			false, &gobj);
+			&gobj);
 	if (ret) {
 		printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
 		       surface_width, surface_height);
 		ret = -ENOMEM;
 		goto out;
 	}
-	robj = gobj->driver_private;
+	rbo = gobj->driver_private;
 
 	if (fb_tiled)
 		tiling_flags = RADEON_TILING_MACRO;
@@ -192,8 +192,13 @@
 	}
 #endif
 
-	if (tiling_flags)
-		radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch);
+	if (tiling_flags) {
+		ret = radeon_bo_set_tiling_flags(rbo,
+					tiling_flags | RADEON_TILING_SURFACE,
+					mode_cmd.pitch);
+		if (ret)
+			dev_err(rdev->dev, "FB failed to set tiling flags\n");
+	}
 	mutex_lock(&rdev->ddev->struct_mutex);
 	fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
 	if (fb == NULL) {
@@ -201,10 +206,19 @@
 		ret = -ENOMEM;
 		goto out_unref;
 	}
-	ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+	ret = radeon_bo_reserve(rbo, false);
+	if (unlikely(ret != 0))
+		goto out_unref;
+	ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+	if (ret) {
+		radeon_bo_unreserve(rbo);
+		goto out_unref;
+	}
+	if (fb_tiled)
+		radeon_bo_check_tiling(rbo, 0, 0);
+	ret = radeon_bo_kmap(rbo, &fbptr);
+	radeon_bo_unreserve(rbo);
 	if (ret) {
-		printk(KERN_ERR "failed to pin framebuffer\n");
-		ret = -ENOMEM;
 		goto out_unref;
 	}
 
@@ -213,7 +227,7 @@
 	*fb_p = fb;
 	rfb = to_radeon_framebuffer(fb);
 	rdev->fbdev_rfb = rfb;
-	rdev->fbdev_robj = robj;
+	rdev->fbdev_rbo = rbo;
 
 	info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
 	if (info == NULL) {
@@ -234,15 +248,7 @@
 	if (ret)
 		goto out_unref;
 
-	if (fb_tiled)
-		radeon_object_check_tiling(robj, 0, 0);
-
-	ret = radeon_object_kmap(robj, &fbptr);
-	if (ret) {
-		goto out_unref;
-	}
-
-	memset_io(fbptr, 0, aligned_size);
+	memset_io(fbptr, 0x0, aligned_size);
 
 	strcpy(info->fix.id, "radeondrmfb");
 
@@ -288,8 +294,12 @@
 	return 0;
 
 out_unref:
-	if (robj) {
-		radeon_object_kunmap(robj);
+	if (rbo) {
+		ret = radeon_bo_reserve(rbo, false);
+		if (likely(ret == 0)) {
+			radeon_bo_kunmap(rbo);
+			radeon_bo_unreserve(rbo);
+		}
 	}
 	if (fb && ret) {
 		list_del(&fb->filp_head);
@@ -321,14 +331,22 @@
 
 int radeonfb_probe(struct drm_device *dev)
 {
-	return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
+	struct radeon_device *rdev = dev->dev_private;
+	int bpp_sel = 32;
+
+	/* select 8 bpp console on RN50 or 16MB cards */
+	if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
+		bpp_sel = 8;
+
+	return drm_fb_helper_single_fb_probe(dev, bpp_sel, &radeonfb_create);
 }
 
 int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
 {
 	struct fb_info *info;
 	struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
-	struct radeon_object *robj;
+	struct radeon_bo *rbo;
+	int r;
 
 	if (!fb) {
 		return -EINVAL;
@@ -336,10 +354,14 @@
 	info = fb->fbdev;
 	if (info) {
 		struct radeon_fb_device *rfbdev = info->par;
-		robj = rfb->obj->driver_private;
+		rbo = rfb->obj->driver_private;
 		unregister_framebuffer(info);
-		radeon_object_kunmap(robj);
-		radeon_object_unpin(robj);
+		r = radeon_bo_reserve(rbo, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rbo);
+			radeon_bo_unpin(rbo);
+			radeon_bo_unreserve(rbo);
+		}
 		drm_fb_helper_free(&rfbdev->helper);
 		framebuffer_release(info);
 	}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r100_track.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r100_track.h
@@ -10,26 +10,30 @@
  * CS functions
  */
 struct r100_cs_track_cb {
-	struct radeon_object	*robj;
+	struct radeon_bo	*robj;
 	unsigned		pitch;
 	unsigned		cpp;
 	unsigned		offset;
 };
 
 struct r100_cs_track_array {
-	struct radeon_object	*robj;
+	struct radeon_bo	*robj;
 	unsigned		esize;
 };
 
 struct r100_cs_cube_info {
-	struct radeon_object	*robj;
-	unsigned                offset;
+	struct radeon_bo	*robj;
+	unsigned		offset;
 	unsigned		width;
 	unsigned		height;
 };
 
+#define R100_TRACK_COMP_NONE   0
+#define R100_TRACK_COMP_DXT1   1
+#define R100_TRACK_COMP_DXT35  2
+
 struct r100_cs_track_texture {
-	struct radeon_object	*robj;
+	struct radeon_bo	*robj;
 	struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */
 	unsigned		pitch;
 	unsigned		width;
@@ -42,8 +46,10 @@
 	unsigned		height_11;
 	bool			use_pitch;
 	bool			enabled;
+	bool                    lookup_disable;
 	bool			roundup_w;
 	bool			roundup_h;
+	unsigned                compress_format;
 };
 
 struct r100_cs_track_limits {
@@ -62,13 +68,18 @@
 	unsigned			immd_dwords;
 	unsigned			num_arrays;
 	unsigned			max_indx;
+	unsigned			color_channel_mask;
 	struct r100_cs_track_array	arrays[11];
 	struct r100_cs_track_cb 	cb[R300_MAX_CB];
 	struct r100_cs_track_cb 	zb;
+	struct r100_cs_track_cb 	aa;
 	struct r100_cs_track_texture	textures[R300_TRACK_MAX_TEXTURE];
 	bool				z_enabled;
 	bool                            separate_cube;
-
+	bool				fastfill;
+	bool				blend_read_enable;
+	bool				aa_dirty;
+	bool				aaresolve;
 };
 
 int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r600_cs.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r600_cs.c
@@ -36,6 +36,10 @@
 typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
 static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
 
+struct r600_cs_track {
+	u32	cb_color0_base_last;
+};
+
 /**
  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  * @parser:	parser structure holding parsing context.
@@ -170,13 +174,35 @@
 			  idx, relocs_chunk->length_dw);
 		return -EINVAL;
 	}
-	*cs_reloc = &p->relocs[0];
+	*cs_reloc = p->relocs;
 	(*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
 	(*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
 	return 0;
 }
 
 /**
+ * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser:		parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet p3reloc;
+	int r;
+
+	r = r600_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r) {
+		return 0;
+	}
+	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * r600_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -337,6 +363,7 @@
 				struct radeon_cs_packet *pkt)
 {
 	struct radeon_cs_reloc *reloc;
+	struct r600_cs_track *track;
 	volatile u32 *ib;
 	unsigned idx;
 	unsigned i;
@@ -344,6 +371,7 @@
 	int r;
 	u32 idx_value;
 
+	track = (struct r600_cs_track *)p->track;
 	ib = p->ib->ptr;
 	idx = pkt->idx + 1;
 	idx_value = radeon_get_ib_value(p, idx);
@@ -503,9 +531,60 @@
 		for (i = 0; i < pkt->count; i++) {
 			reg = start_reg + (4 * i);
 			switch (reg) {
+			/* This register were added late, there is userspace
+			 * which does provide relocation for those but set
+			 * 0 offset. In order to avoid breaking old userspace
+			 * we detect this and set address to point to last
+			 * CB_COLOR0_BASE, note that if userspace doesn't set
+			 * CB_COLOR0_BASE before this register we will report
+			 * error. Old userspace always set CB_COLOR0_BASE
+			 * before any of this.
+			 */
+			case R_0280E0_CB_COLOR0_FRAG:
+			case R_0280E4_CB_COLOR1_FRAG:
+			case R_0280E8_CB_COLOR2_FRAG:
+			case R_0280EC_CB_COLOR3_FRAG:
+			case R_0280F0_CB_COLOR4_FRAG:
+			case R_0280F4_CB_COLOR5_FRAG:
+			case R_0280F8_CB_COLOR6_FRAG:
+			case R_0280FC_CB_COLOR7_FRAG:
+			case R_0280C0_CB_COLOR0_TILE:
+			case R_0280C4_CB_COLOR1_TILE:
+			case R_0280C8_CB_COLOR2_TILE:
+			case R_0280CC_CB_COLOR3_TILE:
+			case R_0280D0_CB_COLOR4_TILE:
+			case R_0280D4_CB_COLOR5_TILE:
+			case R_0280D8_CB_COLOR6_TILE:
+			case R_0280DC_CB_COLOR7_TILE:
+				if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+					if (!track->cb_color0_base_last) {
+						dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] = track->cb_color0_base_last;
+					printk_once(KERN_WARNING "radeon: You have old & broken userspace "
+						"please consider updating mesa & xf86-video-ati\n");
+				} else {
+					r = r600_cs_packet_next_reloc(p, &reloc);
+					if (r) {
+						dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				}
+				break;
 			case DB_DEPTH_BASE:
 			case DB_HTILE_DATA_BASE:
 			case CB_COLOR0_BASE:
+				r = r600_cs_packet_next_reloc(p, &reloc);
+				if (r) {
+					DRM_ERROR("bad SET_CONTEXT_REG "
+							"0x%04X\n", reg);
+					return -EINVAL;
+				}
+				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				track->cb_color0_base_last = ib[idx+1+i];
+				break;
 			case CB_COLOR1_BASE:
 			case CB_COLOR2_BASE:
 			case CB_COLOR3_BASE:
@@ -678,8 +757,11 @@
 int r600_cs_parse(struct radeon_cs_parser *p)
 {
 	struct radeon_cs_packet pkt;
+	struct r600_cs_track *track;
 	int r;
 
+	track = kzalloc(sizeof(*track), GFP_KERNEL);
+	p->track = track;
 	do {
 		r = r600_cs_packet_parse(p, &pkt, p->idx);
 		if (r) {
@@ -717,7 +799,7 @@
 	if (p->chunk_relocs_idx == -1) {
 		return 0;
 	}
-	p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+	p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
 	if (p->relocs == NULL) {
 		return -ENOMEM;
 	}
@@ -757,6 +839,7 @@
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
+	parser.dev = &dev->pdev->dev;
 	parser.rdev = NULL;
 	parser.family = family;
 	parser.ib = &fake_ib;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/atom.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/atom.h
@@ -91,6 +91,7 @@
 #define ATOM_WS_AND_MASK	0x45
 #define ATOM_WS_FB_WINDOW	0x46
 #define ATOM_WS_ATTRIBUTES	0x47
+#define ATOM_WS_REGPTR  	0x48
 
 #define ATOM_IIO_NOP		0
 #define ATOM_IIO_START		1
@@ -120,6 +121,7 @@
 
 struct atom_context {
 	struct card_info *card;
+	struct mutex mutex;
 	void *bios;
 	uint32_t cmd_table, data_table;
 	uint16_t *iio;
@@ -132,6 +134,7 @@
 	uint8_t shift;
 	int cs_equal, cs_above;
 	int io_mode;
+	uint32_t *scratch;
 };
 
 extern int atom_debug;
@@ -142,6 +145,7 @@
 void atom_destroy(struct atom_context *);
 void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
 void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
+int atom_allocate_fb_scratch(struct atom_context *ctx);
 #include "atom-types.h"
 #include "atombios.h"
 #include "ObjectID.h"
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_encoders.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -35,6 +35,51 @@
 bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
 				struct drm_display_mode *mode);
 
+static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *clone_encoder;
+	uint32_t index_mask = 0;
+	int count;
+
+	/* DIG routing gets problematic */
+	if (rdev->family >= CHIP_R600)
+		return index_mask;
+	/* LVDS/TV are too wacky */
+	if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
+		return index_mask;
+	/* DVO requires 2x ppll clocks depending on tmds chip */
+	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
+		return index_mask;
+	
+	count = -1;
+	list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
+		count++;
+
+		if (clone_encoder == encoder)
+			continue;
+		if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
+			continue;
+		if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
+			continue;
+		else
+			index_mask |= (1 << count);
+	}
+	return index_mask;
+}
+
+void radeon_setup_encoder_clones(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		encoder->possible_clones = radeon_encoder_clones(encoder);
+	}
+}
+
 uint32_t
 radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
 {
@@ -111,6 +156,26 @@
 	return ret;
 }
 
+static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		return true;
+	default:
+		return false;
+	}
+}
 void
 radeon_link_encoder_connector(struct drm_device *dev)
 {
@@ -157,35 +222,12 @@
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		radeon_connector = to_radeon_connector(connector);
-		if (radeon_encoder->devices & radeon_connector->devices)
+		if (radeon_encoder->active_device & radeon_connector->devices)
 			return connector;
 	}
 	return NULL;
 }
 
-/* used for both atom and legacy */
-void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
-			   struct drm_display_mode *mode,
-			   struct drm_display_mode *adjusted_mode)
-{
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
-
-	if (mode->hdisplay < native_mode->hdisplay ||
-	    mode->vdisplay < native_mode->vdisplay) {
-		int mode_id = adjusted_mode->base.id;
-		*adjusted_mode = *native_mode;
-		if (!ASIC_IS_AVIVO(rdev)) {
-			adjusted_mode->hdisplay = mode->hdisplay;
-			adjusted_mode->vdisplay = mode->vdisplay;
-		}
-		adjusted_mode->base.id = mode_id;
-	}
-}
-
-
 static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
@@ -198,14 +240,26 @@
 	radeon_encoder_set_active_device(encoder);
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-	if (radeon_encoder->rmx_type != RMX_OFF)
-		radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
-
 	/* hw bug */
 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
 	    && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
 		adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
 
+	/* get the native mode for LVDS */
+	if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
+		struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
+		int mode_id = adjusted_mode->base.id;
+		*adjusted_mode = *native_mode;
+		if (!ASIC_IS_AVIVO(rdev)) {
+			adjusted_mode->hdisplay = mode->hdisplay;
+			adjusted_mode->vdisplay = mode->vdisplay;
+			adjusted_mode->crtc_hdisplay = mode->hdisplay;
+			adjusted_mode->crtc_vdisplay = mode->vdisplay;
+		}
+		adjusted_mode->base.id = mode_id;
+	}
+
+	/* get the native mode for TV */
 	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
 		struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
 		if (tv_dac) {
@@ -218,6 +272,12 @@
 		}
 	}
 
+	if (ASIC_IS_DCE3(rdev) &&
+	    (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
+		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+		radeon_dp_set_link_config(connector, mode);
+	}
+
 	return true;
 }
 
@@ -392,7 +452,7 @@
 	LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
 };
 
-static void
+void
 atombios_digital_setup(struct drm_encoder *encoder, int action)
 {
 	struct drm_device *dev = encoder->dev;
@@ -400,6 +460,7 @@
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	union lvds_encoder_control args;
 	int index = 0;
+	int hdmi_detected = 0;
 	uint8_t frev, crev;
 	struct radeon_encoder_atom_dig *dig;
 	struct drm_connector *connector;
@@ -420,6 +481,9 @@
 	if (!radeon_connector->con_priv)
 		return;
 
+	if (drm_detect_hdmi_monitor(radeon_connector->edid))
+		hdmi_detected = 1;
+
 	dig_connector = radeon_connector->con_priv;
 
 	memset(&args, 0, sizeof(args));
@@ -449,13 +513,13 @@
 		case 1:
 			args.v1.ucMisc = 0;
 			args.v1.ucAction = action;
-			if (drm_detect_hdmi_monitor(radeon_connector->edid))
+			if (hdmi_detected)
 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lvds_misc & (1 << 0))
+				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
 					args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lvds_misc & (1 << 1))
+				if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
 					args.v1.ucMisc |= (1 << 1);
 			} else {
 				if (dig_connector->linkb)
@@ -474,7 +538,7 @@
 				if (dig->coherent_mode)
 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
 			}
-			if (drm_detect_hdmi_monitor(radeon_connector->edid))
+			if (hdmi_detected)
 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 			args.v2.ucTruncate = 0;
@@ -482,18 +546,18 @@
 			args.v2.ucTemporal = 0;
 			args.v2.ucFRC = 0;
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-				if (dig->lvds_misc & (1 << 0))
+				if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL)
 					args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
-				if (dig->lvds_misc & (1 << 5)) {
+				if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) {
 					args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN;
-					if (dig->lvds_misc & (1 << 1))
+					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
 						args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH;
 				}
-				if (dig->lvds_misc & (1 << 6)) {
+				if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) {
 					args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN;
-					if (dig->lvds_misc & (1 << 1))
+					if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB)
 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH;
-					if (((dig->lvds_misc >> 2) & 0x3) == 2)
+					if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2)
 						args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4;
 				}
 			} else {
@@ -514,7 +578,7 @@
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
+	r600_hdmi_enable(encoder, hdmi_detected);
 }
 
 int
@@ -522,11 +586,24 @@
 {
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *radeon_dig_connector;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
 	connector = radeon_get_connector_for_encoder(encoder);
-	if (!connector)
-		return 0;
-
+	if (!connector) {
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+			return ATOM_ENCODER_MODE_DVI;
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		default:
+			return ATOM_ENCODER_MODE_CRT;
+		}
+	}
 	radeon_connector = to_radeon_connector(connector);
 
 	switch (connector->connector_type) {
@@ -551,21 +628,23 @@
 		return ATOM_ENCODER_MODE_LVDS;
 		break;
 	case DRM_MODE_CONNECTOR_DisplayPort:
-		/*if (radeon_output->MonType == MT_DP)
-		  return ATOM_ENCODER_MODE_DP;
-		  else*/
-		if (drm_detect_hdmi_monitor(radeon_connector->edid))
+	case DRM_MODE_CONNECTOR_eDP:
+		radeon_dig_connector = radeon_connector->con_priv;
+		if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+			return ATOM_ENCODER_MODE_DP;
+		else if (drm_detect_hdmi_monitor(radeon_connector->edid))
 			return ATOM_ENCODER_MODE_HDMI;
 		else
 			return ATOM_ENCODER_MODE_DVI;
 		break;
-	case CONNECTOR_DVI_A:
-	case CONNECTOR_VGA:
+	case DRM_MODE_CONNECTOR_DVIA:
+	case DRM_MODE_CONNECTOR_VGA:
 		return ATOM_ENCODER_MODE_CRT;
 		break;
-	case CONNECTOR_STV:
-	case CONNECTOR_CTV:
-	case CONNECTOR_DIN:
+	case DRM_MODE_CONNECTOR_Composite:
+	case DRM_MODE_CONNECTOR_SVIDEO:
+	case DRM_MODE_CONNECTOR_9PinDIN:
 		/* fix me */
 		return ATOM_ENCODER_MODE_TV;
 		/*return ATOM_ENCODER_MODE_CV;*/
@@ -573,6 +652,30 @@
 	}
 }
 
+/*
+ * DIG Encoder/Transmitter Setup
+ *
+ * DCE 3.0/3.1
+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA.
+ * Supports up to 3 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1 can drive UNIPHY link A or link B
+ * DIG2 can drive UNIPHY link B or LVTMA
+ *
+ * DCE 3.2
+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B).
+ * Supports up to 5 digital outputs
+ * - 2 DIG encoder blocks.
+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B
+ *
+ * Routing
+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
+ * Examples:
+ * crtc0 -> dig2 -> LVTMA   links A+B -> TMDS/HDMI
+ * crtc1 -> dig1 -> UNIPHY0 link  B   -> DP
+ * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
+ * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
+ */
 static void
 atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
 {
@@ -605,24 +708,11 @@
 
 	memset(&args, 0, sizeof(args));
 
-	if (ASIC_IS_DCE32(rdev)) {
-		if (dig->dig_block)
-			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-		else
-			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-		num = dig->dig_block + 1;
-	} else {
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
-			num = 1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-			num = 2;
-			break;
-		}
-	}
+	if (dig->dig_encoder)
+		index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+	else
+		index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	num = dig->dig_encoder + 1;
 
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
 
@@ -652,18 +742,21 @@
 		}
 	}
 
-	if (radeon_encoder->pixel_clock > 165000) {
-		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
+	args.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+	if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
+		if (dig_connector->dp_clock == 270000)
+			args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+		args.ucLaneNum = dig_connector->dp_lane_count;
+	} else if (radeon_encoder->pixel_clock > 165000)
 		args.ucLaneNum = 8;
-	} else {
-		if (dig_connector->linkb)
-			args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-		else
-			args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
+	else
 		args.ucLaneNum = 4;
-	}
 
-	args.ucEncoderMode = atombios_get_encoder_mode(encoder);
+	if (dig_connector->linkb)
+		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+	else
+		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
@@ -674,8 +767,8 @@
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
 };
 
-static void
-atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
+void
+atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -687,6 +780,7 @@
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	struct radeon_connector_atom_dig *dig_connector;
+	bool is_dp = false;
 
 	connector = radeon_get_connector_for_encoder(encoder);
 	if (!connector)
@@ -704,6 +798,9 @@
 
 	dig_connector = radeon_connector->con_priv;
 
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
+		is_dp = true;
+
 	memset(&args, 0, sizeof(args));
 
 	if (ASIC_IS_DCE32(rdev))
@@ -724,17 +821,23 @@
 	args.v1.ucAction = action;
 	if (action == ATOM_TRANSMITTER_ACTION_INIT) {
 		args.v1.usInitInfo = radeon_connector->connector_object_id;
+	} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+		args.v1.asMode.ucLaneSel = lane_num;
+		args.v1.asMode.ucLaneSet = lane_set;
 	} else {
-		if (radeon_encoder->pixel_clock > 165000)
+		if (is_dp)
+			args.v1.usPixelClock =
+				cpu_to_le16(dig_connector->dp_clock / 10);
+		else if (radeon_encoder->pixel_clock > 165000)
 			args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
 		else
 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 	}
 	if (ASIC_IS_DCE32(rdev)) {
-		if (radeon_encoder->pixel_clock > 165000)
-			args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
-		if (dig->dig_block)
+		if (dig->dig_encoder == 1)
 			args.v2.acConfig.ucEncoderSel = 1;
+		if (dig_connector->linkb)
+			args.v2.acConfig.ucLinkSel = 1;
 
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
@@ -751,26 +854,32 @@
 			break;
 		}
 
-		if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+		if (is_dp)
+			args.v2.acConfig.fCoherentMode = 1;
+		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
 			if (dig->coherent_mode)
 				args.v2.acConfig.fCoherentMode = 1;
+			if (radeon_encoder->pixel_clock > 165000)
+				args.v2.acConfig.fDualLinkConnector = 1;
 		}
 	} else {
+
 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
+		if (dig->dig_encoder)
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
+		else
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
+
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
 			if (rdev->flags & RADEON_IS_IGP) {
 				if (radeon_encoder->pixel_clock > 165000) {
-					args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-							     ATOM_TRANSMITTER_CONFIG_LINKA_B);
 					if (dig_connector->igp_lane_info & 0x3)
 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
 					else if (dig_connector->igp_lane_info & 0xc)
 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
 				} else {
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
 					if (dig_connector->igp_lane_info & 0x1)
 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
 					else if (dig_connector->igp_lane_info & 0x2)
@@ -780,42 +889,27 @@
 					else if (dig_connector->igp_lane_info & 0x8)
 						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
 				}
-			} else {
-				if (radeon_encoder->pixel_clock > 165000)
-					args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-							     ATOM_TRANSMITTER_CONFIG_LINKA_B |
-							     ATOM_TRANSMITTER_CONFIG_LANE_0_7);
-				else {
-					if (dig_connector->linkb)
-						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-					else
-						args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-				}
-			}
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
-			if (radeon_encoder->pixel_clock > 165000)
-				args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK |
-						     ATOM_TRANSMITTER_CONFIG_LINKA_B |
-						     ATOM_TRANSMITTER_CONFIG_LANE_0_7);
-			else {
-				if (dig_connector->linkb)
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
-				else
-					args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3;
 			}
 			break;
 		}
 
-		if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+		if (radeon_encoder->pixel_clock > 165000)
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
+
+		if (dig_connector->linkb)
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
+		else
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
+
+		if (is_dp)
+			args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
 			if (dig->coherent_mode)
 				args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
 		}
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
 }
 
 static void
@@ -918,12 +1012,16 @@
 	if (is_dig) {
 		switch (mode) {
 		case DRM_MODE_DPMS_ON:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+			{
+				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+				dp_link_train(encoder, connector);
+			}
 			break;
 		case DRM_MODE_DPMS_STANDBY:
 		case DRM_MODE_DPMS_SUSPEND:
 		case DRM_MODE_DPMS_OFF:
-			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
 			break;
 		}
 	} else {
@@ -957,6 +1055,7 @@
 	union crtc_sourc_param args;
 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
 	uint8_t frev, crev;
+	struct radeon_encoder_atom_dig *dig;
 
 	memset(&args, 0, sizeof(args));
 
@@ -1020,20 +1119,16 @@
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-				if (ASIC_IS_DCE32(rdev)) {
-					if (radeon_crtc->crtc_id)
-						args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-					else
-						args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
-				} else
+			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+				dig = radeon_encoder->enc_priv;
+				if (dig->dig_encoder)
+					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+				else
 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
 				break;
 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
 				break;
-			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-				args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-				break;
 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
@@ -1060,7 +1155,6 @@
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
 }
 
 static void
@@ -1094,6 +1188,47 @@
 	}
 }
 
+static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *test_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	uint32_t dig_enc_in_use = 0;
+	/* on DCE32 and encoder can driver any block so just crtc id */
+	if (ASIC_IS_DCE32(rdev)) {
+		return radeon_crtc->crtc_id;
+	}
+
+	/* on DCE3 - LVTMA can only be driven by DIGB */
+	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
+		struct radeon_encoder *radeon_test_encoder;
+
+		if (encoder == test_encoder)
+			continue;
+
+		if (!radeon_encoder_is_digital(test_encoder))
+			continue;
+
+		radeon_test_encoder = to_radeon_encoder(test_encoder);
+		dig = radeon_test_encoder->enc_priv;
+
+		if (dig->dig_encoder >= 0)
+			dig_enc_in_use |= (1 << dig->dig_encoder);
+	}
+
+	if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) {
+		if (dig_enc_in_use & 0x2)
+			DRM_ERROR("LVDS required digital encoder 2 but it was in use - stealing\n");
+		return 1;
+	}
+	if (!(dig_enc_in_use & 1))
+		return 0;
+	return 1;
+}
+
 static void
 radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 			     struct drm_display_mode *mode,
@@ -1104,11 +1239,11 @@
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 
-	if (radeon_encoder->enc_priv) {
-		struct radeon_encoder_atom_dig *dig;
-
-		dig = radeon_encoder->enc_priv;
-		dig->dig_block = radeon_crtc->crtc_id;
+	if (radeon_encoder->active_device &
+	    (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
+		struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+		if (dig)
+			dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
 	}
 	radeon_encoder->pixel_clock = adjusted_mode->clock;
 
@@ -1134,14 +1269,14 @@
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 		/* disable the encoder and transmitter */
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
 		atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
 
 		/* setup and enable the encoder and transmitter */
 		atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
 		atombios_ddia_setup(encoder, ATOM_ENABLE);
@@ -1155,11 +1290,17 @@
 	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 		atombios_dac_setup(encoder, ATOM_ENABLE);
-		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
-			atombios_tv_setup(encoder, ATOM_ENABLE);
+		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) {
+			if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
+				atombios_tv_setup(encoder, ATOM_ENABLE);
+			else
+				atombios_tv_setup(encoder, ATOM_DISABLE);
+		}
 		break;
 	}
 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+	r600_hdmi_setmode(encoder, adjusted_mode);
 }
 
 static bool
@@ -1266,7 +1407,13 @@
 static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig;
 	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	if (radeon_encoder_is_digital(encoder)) {
+		dig = radeon_encoder->enc_priv;
+		dig->dig_encoder = -1;
+	}
 	radeon_encoder->active_device = 0;
 }
 
@@ -1323,6 +1470,7 @@
 
 	/* coherent mode by default */
 	dig->coherent_mode = true;
+	dig->dig_encoder = -1;
 
 	return dig;
 }
@@ -1354,7 +1502,6 @@
 		encoder->possible_crtcs = 0x1;
 	else
 		encoder->possible_crtcs = 0x3;
-	encoder->possible_clones = 0;
 
 	radeon_encoder->enc_priv = NULL;
 
@@ -1406,4 +1553,6 @@
 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
 		break;
 	}
+
+	r600_hdmi_init(encoder);
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rs690.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rs690.c
@@ -131,24 +131,26 @@
 
 void rs690_vram_info(struct radeon_device *rdev)
 {
-	uint32_t tmp;
 	fixed20_12 a;
 
 	rs400_gart_adjust_size(rdev);
-	/* DDR for all card after R300 & IGP */
+
 	rdev->mc.vram_is_ddr = true;
-	/* FIXME: is this correct for RS690/RS740 ? */
-	tmp = RREG32(RADEON_MEM_CNTL);
-	if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
-		rdev->mc.vram_width = 128;
-	} else {
-		rdev->mc.vram_width = 64;
-	}
+	rdev->mc.vram_width = 128;
+
 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 
 	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
 	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+		rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+		rdev->mc.real_vram_size = rdev->mc.aper_size;
+
+	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
 	rs690_pm_info(rdev);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
@@ -161,6 +163,21 @@
 	rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
 }
 
+static int rs690_mc_init(struct radeon_device *rdev)
+{
+	int r;
+	u32 tmp;
+
+	/* Setup GPU memory space */
+	tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
+	rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16;
+	rdev->mc.gtt_location = 0xFFFFFFFFUL;
+	r = radeon_mc_setup(rdev);
+	if (r)
+		return r;
+	return 0;
+}
+
 void rs690_line_buffer_adjust(struct radeon_device *rdev,
 			      struct drm_display_mode *mode1,
 			      struct drm_display_mode *mode2)
@@ -244,8 +261,9 @@
 
 	b.full = rfixed_const(mode->crtc_hdisplay);
 	c.full = rfixed_const(256);
-	a.full = rfixed_mul(wm->num_line_pair, b);
-	request_fifo_depth.full = rfixed_div(a, c);
+	a.full = rfixed_div(b, c);
+	request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair);
+	request_fifo_depth.full = rfixed_ceil(request_fifo_depth);
 	if (a.full < rfixed_const(4)) {
 		wm->lb_request_fifo_depth = 4;
 	} else {
@@ -374,6 +392,7 @@
 	a.full = rfixed_const(16);
 	wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
 	wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+	wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max);
 
 	/* Determine estimated width */
 	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
@@ -383,6 +402,7 @@
 	} else {
 		a.full = rfixed_const(16);
 		wm->priority_mark.full = rfixed_div(estimated_width, a);
+		wm->priority_mark.full = rfixed_ceil(wm->priority_mark);
 		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
 	}
 }
@@ -605,8 +625,8 @@
 	if (r)
 		return r;
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	rs600_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -640,6 +660,8 @@
 	atom_asic_init(rdev->mode_info.atom_context);
 	/* Resume clock after posting */
 	rv515_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return rs690_startup(rdev);
 }
 
@@ -654,7 +676,6 @@
 
 void rs690_fini(struct radeon_device *rdev)
 {
-	rs690_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
@@ -662,7 +683,7 @@
 	rs400_gart_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -700,10 +721,9 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		atom_asic_init(rdev->mode_info.atom_context);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
+
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
@@ -711,7 +731,7 @@
 	/* Get vram informations */
 	rs690_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
+	r = rs690_mc_init(rdev);
 	if (r)
 		return r;
 	rv515_debugfs(rdev);
@@ -723,7 +743,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	r = rs400_gart_init(rdev);
@@ -735,7 +755,6 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		rs690_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_kms.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_kms.c
@@ -30,10 +30,19 @@
 #include "radeon.h"
 #include "radeon_drm.h"
 
+int radeon_driver_unload_kms(struct drm_device *dev)
+{
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (rdev == NULL)
+		return 0;
+	radeon_modeset_fini(rdev);
+	radeon_device_fini(rdev);
+	kfree(rdev);
+	dev->dev_private = NULL;
+	return 0;
+}
 
-/*
- * Driver load/unload
- */
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
 {
 	struct radeon_device *rdev;
@@ -62,31 +71,20 @@
 	 */
 	r = radeon_device_init(rdev, dev, dev->pdev, flags);
 	if (r) {
-		DRM_ERROR("Fatal error while trying to initialize radeon.\n");
-		return r;
+		dev_err(&dev->pdev->dev, "Fatal error during GPU init\n");
+		goto out;
 	}
 	/* Again modeset_init should fail only on fatal error
 	 * otherwise it should provide enough functionalities
 	 * for shadowfb to run
 	 */
 	r = radeon_modeset_init(rdev);
-	if (r) {
-		return r;
-	}
-	return 0;
-}
-
-int radeon_driver_unload_kms(struct drm_device *dev)
-{
-	struct radeon_device *rdev = dev->dev_private;
-
-	if (rdev == NULL)
-		return 0;
-	radeon_modeset_fini(rdev);
-	radeon_device_fini(rdev);
-	kfree(rdev);
-	dev->dev_private = NULL;
-	return 0;
+	if (r)
+		dev_err(&dev->pdev->dev, "Fatal error during modeset init\n");
+out:
+	if (r)
+		radeon_driver_unload_kms(dev);
+	return r;
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rv515.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rv515.c
@@ -478,8 +478,8 @@
 			return r;
 	}
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	rs600_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -514,6 +514,8 @@
 	atom_asic_init(rdev->mode_info.atom_context);
 	/* Resume clock after posting */
 	rv515_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return rv515_startup(rdev);
 }
 
@@ -535,16 +537,15 @@
 
 void rv515_fini(struct radeon_device *rdev)
 {
-	rv515_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
 	radeon_gem_fini(rdev);
-    rv370_pcie_gart_fini(rdev);
+	rv370_pcie_gart_fini(rdev);
 	radeon_agp_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -580,10 +581,8 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		atom_asic_init(rdev->mode_info.atom_context);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
@@ -603,7 +602,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	r = rv370_pcie_gart_init(rdev);
@@ -615,13 +614,12 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		rv515_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		rv370_pcie_gart_fini(rdev);
 		radeon_agp_fini(rdev);
-		radeon_irq_kms_fini(rdev);
 		rdev->accel_working = false;
 	}
 	return 0;
@@ -892,8 +890,9 @@
 
 	b.full = rfixed_const(mode->crtc_hdisplay);
 	c.full = rfixed_const(256);
-	a.full = rfixed_mul(wm->num_line_pair, b);
-	request_fifo_depth.full = rfixed_div(a, c);
+	a.full = rfixed_div(b, c);
+	request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair);
+	request_fifo_depth.full = rfixed_ceil(request_fifo_depth);
 	if (a.full < rfixed_const(4)) {
 		wm->lb_request_fifo_depth = 4;
 	} else {
@@ -995,15 +994,17 @@
 	a.full = rfixed_const(16);
 	wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
 	wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+	wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max);
 
 	/* Determine estimated width */
 	estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
 	estimated_width.full = rfixed_div(estimated_width, consumption_time);
 	if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
-		wm->priority_mark.full = rfixed_const(10);
+		wm->priority_mark.full = wm->priority_mark_max.full;
 	} else {
 		a.full = rfixed_const(16);
 		wm->priority_mark.full = rfixed_div(estimated_width, a);
+		wm->priority_mark.full = rfixed_ceil(wm->priority_mark);
 		wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
 	}
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r520.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r520.c
@@ -185,8 +185,8 @@
 			return r;
 	}
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	rs600_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -221,6 +221,8 @@
 	atom_asic_init(rdev->mode_info.atom_context);
 	/* Resume clock after posting */
 	rv515_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return r520_startup(rdev);
 }
 
@@ -254,6 +256,9 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
+
 	if (!radeon_card_posted(rdev) && rdev->bios) {
 		DRM_INFO("GPU not posted. posting now...\n");
 		atom_asic_init(rdev->mode_info.atom_context);
@@ -277,7 +282,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	r = rv370_pcie_gart_init(rdev);
@@ -289,13 +294,12 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		rv515_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		rv370_pcie_gart_fini(rdev);
 		radeon_agp_fini(rdev);
-		radeon_irq_kms_fini(rdev);
 		rdev->accel_working = false;
 	}
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/atombios.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/atombios.h
@@ -1141,7 +1141,7 @@
 /* ucTableFormatRevision=1,ucTableContentRevision=2 */
 typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2 {
 	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucMisc;		/*  see PANEL_ENCODER_MISC_xx defintions below */
+	UCHAR ucMisc;		/*  see PANEL_ENCODER_MISC_xx definitions below */
 	UCHAR ucAction;		/*  0: turn off encoder */
 	/*  1: setup and turn on encoder */
 	UCHAR ucTruncate;	/*  bit0=0: Disable truncate */
@@ -1424,7 +1424,7 @@
 /*  Structures used in FirmwareInfoTable */
 /****************************************************************************/
 
-/*  usBIOSCapability Defintion: */
+/*  usBIOSCapability Definition: */
 /*  Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; */
 /*  Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; */
 /*  Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; */
@@ -2386,7 +2386,7 @@
 } ATOM_ANALOG_TV_INFO_V1_2;
 
 /**************************************************************************/
-/*  VRAM usage and their defintions */
+/*  VRAM usage and their definitions */
 
 /*  One chunk of VRAM used by Bios are for HWICON surfaces,EDID data. */
 /*  Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below. */
@@ -2680,7 +2680,7 @@
 typedef struct _ATOM_HPD_INT_RECORD {
 	ATOM_COMMON_RECORD_HEADER sheader;
 	UCHAR ucHPDIntGPIOID;	/* Corresponding block in GPIO_PIN_INFO table gives the pin info */
-	UCHAR ucPluggged_PinState;
+	UCHAR ucPlugged_PinState;
 } ATOM_HPD_INT_RECORD;
 
 typedef struct _ATOM_OUTPUT_PROTECTION_RECORD {
@@ -3046,7 +3046,7 @@
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC     2
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3
 
-/* Byte aligned defintion for BIOS usage */
+/* Byte aligned definition for BIOS usage */
 #define ATOM_S0_CRT1_MONOb0             0x01
 #define ATOM_S0_CRT1_COLORb0            0x02
 #define ATOM_S0_CRT1_MASKb0             (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0)
@@ -3131,7 +3131,7 @@
 #define ATOM_S2_DISPLAY_ROTATION_DEGREE_SHIFT 30
 #define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK   0xC0000000L
 
-/* Byte aligned defintion for BIOS usage */
+/* Byte aligned definition for BIOS usage */
 #define ATOM_S2_TV1_STANDARD_MASKb0     0x0F
 #define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF
 #define ATOM_S2_CRT1_DPMS_STATEb2       0x01
@@ -3190,7 +3190,7 @@
 #define ATOM_S3_ALLOW_FAST_PWR_SWITCH   0x40000000L
 #define ATOM_S3_RQST_GPU_USE_MIN_PWR    0x80000000L
 
-/* Byte aligned defintion for BIOS usage */
+/* Byte aligned definition for BIOS usage */
 #define ATOM_S3_CRT1_ACTIVEb0           0x01
 #define ATOM_S3_LCD1_ACTIVEb0           0x02
 #define ATOM_S3_TV1_ACTIVEb0            0x04
@@ -3230,7 +3230,7 @@
 #define ATOM_S4_LCD1_REFRESH_MASK       0x0000FF00L
 #define ATOM_S4_LCD1_REFRESH_SHIFT      8
 
-/* Byte aligned defintion for BIOS usage */
+/* Byte aligned definition for BIOS usage */
 #define ATOM_S4_LCD1_PANEL_ID_MASKb0	  0x0FF
 #define ATOM_S4_LCD1_REFRESH_MASKb1		  ATOM_S4_LCD1_PANEL_ID_MASKb0
 #define ATOM_S4_VRAM_INFO_MASKb2        ATOM_S4_LCD1_PANEL_ID_MASKb0
@@ -3310,7 +3310,7 @@
 #define ATOM_S6_VRI_BRIGHTNESS_CHANGE       0x40000000L
 #define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK  0x80000000L
 
-/* Byte aligned defintion for BIOS usage */
+/* Byte aligned definition for BIOS usage */
 #define ATOM_S6_DEVICE_CHANGEb0         0x01
 #define ATOM_S6_SCALER_CHANGEb0         0x02
 #define ATOM_S6_LID_CHANGEb0            0x04
@@ -4690,6 +4690,205 @@
 	ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
 } ATOM_POWERPLAY_INFO_V3;
 
+/* New PPlib */
+/**************************************************************************/
+typedef struct _ATOM_PPLIB_THERMALCONTROLLER
+
+{
+    UCHAR ucType;           // one of ATOM_PP_THERMALCONTROLLER_*
+    UCHAR ucI2cLine;        // as interpreted by DAL I2C
+    UCHAR ucI2cAddress;
+    UCHAR ucFanParameters;  // Fan Control Parameters.
+    UCHAR ucFanMinRPM;      // Fan Minimum RPM (hundreds) -- for display purposes only.
+    UCHAR ucFanMaxRPM;      // Fan Maximum RPM (hundreds) -- for display purposes only.
+    UCHAR ucReserved;       // ----
+    UCHAR ucFlags;          // to be defined
+} ATOM_PPLIB_THERMALCONTROLLER;
+
+#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f
+#define ATOM_PP_FANPARAMETERS_NOFAN                                 0x80    // No fan is connected to this controller.
+
+#define ATOM_PP_THERMALCONTROLLER_NONE      0
+#define ATOM_PP_THERMALCONTROLLER_LM63      1  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_ADM1032   2  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_ADM1030   3  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_MUA6649   4  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_LM64      5
+#define ATOM_PP_THERMALCONTROLLER_F75375    6  // Not used by PPLib
+#define ATOM_PP_THERMALCONTROLLER_RV6xx     7
+#define ATOM_PP_THERMALCONTROLLER_RV770     8
+#define ATOM_PP_THERMALCONTROLLER_ADT7473   9
+
+typedef struct _ATOM_PPLIB_STATE
+{
+    UCHAR ucNonClockStateIndex;
+    UCHAR ucClockStateIndices[1]; // variable-sized
+} ATOM_PPLIB_STATE;
+
+//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps
+#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1
+#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2
+#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4
+#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8
+#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16
+#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32
+#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64
+#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128
+#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256
+#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512
+#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024
+#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048
+
+typedef struct _ATOM_PPLIB_POWERPLAYTABLE
+{
+      ATOM_COMMON_TABLE_HEADER sHeader;
+
+      UCHAR ucDataRevision;
+
+      UCHAR ucNumStates;
+      UCHAR ucStateEntrySize;
+      UCHAR ucClockInfoSize;
+      UCHAR ucNonClockSize;
+
+      // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures
+      USHORT usStateArrayOffset;
+
+      // offset from start of this table to array of ASIC-specific structures,
+      // currently ATOM_PPLIB_CLOCK_INFO.
+      USHORT usClockInfoArrayOffset;
+
+      // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO
+      USHORT usNonClockInfoArrayOffset;
+
+      USHORT usBackbiasTime;    // in microseconds
+      USHORT usVoltageTime;     // in microseconds
+      USHORT usTableSize;       //the size of this structure, or the extended structure
+
+      ULONG ulPlatformCaps;            // See ATOM_PPLIB_CAPS_*
+
+      ATOM_PPLIB_THERMALCONTROLLER    sThermalController;
+
+      USHORT usBootClockInfoOffset;
+      USHORT usBootNonClockInfoOffset;
+
+} ATOM_PPLIB_POWERPLAYTABLE;
+
+//// ATOM_PPLIB_NONCLOCK_INFO::usClassification
+#define ATOM_PPLIB_CLASSIFICATION_UI_MASK          0x0007
+#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT         0
+#define ATOM_PPLIB_CLASSIFICATION_UI_NONE          0
+#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY       1
+#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED      3
+#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE   5
+// 2, 4, 6, 7 are reserved
+
+#define ATOM_PPLIB_CLASSIFICATION_BOOT                   0x0008
+#define ATOM_PPLIB_CLASSIFICATION_THERMAL                0x0010
+#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE     0x0020
+#define ATOM_PPLIB_CLASSIFICATION_REST                   0x0040
+#define ATOM_PPLIB_CLASSIFICATION_FORCED                 0x0080
+#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE          0x0100
+#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE      0x0200
+#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE               0x0400
+#define ATOM_PPLIB_CLASSIFICATION_3DLOW                  0x0800
+#define ATOM_PPLIB_CLASSIFICATION_ACPI                   0x1000
+// remaining 3 bits are reserved
+
+//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings
+#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY           0x00000001
+#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK         0x00000002
+
+// 0 is 2.5Gb/s, 1 is 5Gb/s
+#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK            0x00000004
+#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT           2
+
+// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec
+#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK            0x000000F8
+#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT           3
+
+// lookup into reduced refresh-rate table
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK  0x00000F00
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8
+
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED    0
+#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ         1
+// 2-15 TBD as needed.
+
+#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING        0x00001000
+#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS  0x00002000
+#define ATOM_PPLIB_ENABLE_VARIBRIGHT                     0x00008000
+
+#define ATOM_PPLIB_DISALLOW_ON_DC                       0x00004000
+
+// Contained in an array starting at the offset
+// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset.
+// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex
+typedef struct _ATOM_PPLIB_NONCLOCK_INFO
+{
+      USHORT usClassification;
+      UCHAR  ucMinTemperature;
+      UCHAR  ucMaxTemperature;
+      ULONG  ulCapsAndSettings;
+      UCHAR  ucRequiredPower;
+      UCHAR  ucUnused1[3];
+} ATOM_PPLIB_NONCLOCK_INFO;
+
+// Contained in an array starting at the offset
+// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset.
+// referenced from ATOM_PPLIB_STATE::ucClockStateIndices
+typedef struct _ATOM_PPLIB_R600_CLOCK_INFO
+{
+      USHORT usEngineClockLow;
+      UCHAR ucEngineClockHigh;
+
+      USHORT usMemoryClockLow;
+      UCHAR ucMemoryClockHigh;
+
+      USHORT usVDDC;
+      USHORT usUnused1;
+      USHORT usUnused2;
+
+      ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_*
+
+} ATOM_PPLIB_R600_CLOCK_INFO;
+
+// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO
+#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2          1
+#define ATOM_PPLIB_R600_FLAGS_UVDSAFE           2
+#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE    4
+#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF    8
+#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF    16
+
+typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO
+
+{
+      USHORT usLowEngineClockLow;         // Low Engine clock in MHz (the same way as on the R600).
+      UCHAR  ucLowEngineClockHigh;
+      USHORT usHighEngineClockLow;        // High Engine clock in MHz.
+      UCHAR  ucHighEngineClockHigh;
+      USHORT usMemoryClockLow;            // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants.
+      UCHAR  ucMemoryClockHigh;           // Currentyl unused.
+      UCHAR  ucPadding;                   // For proper alignment and size.
+      USHORT usVDDC;                      // For the 780, use: None, Low, High, Variable
+      UCHAR  ucMaxHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}
+      UCHAR  ucMinHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement.
+      USHORT usHTLinkFreq;                // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200).
+      ULONG  ulFlags;
+} ATOM_PPLIB_RS780_CLOCK_INFO;
+
+#define ATOM_PPLIB_RS780_VOLTAGE_NONE       0
+#define ATOM_PPLIB_RS780_VOLTAGE_LOW        1
+#define ATOM_PPLIB_RS780_VOLTAGE_HIGH       2
+#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE   3
+
+#define ATOM_PPLIB_RS780_SPMCLK_NONE        0   // We cannot change the side port memory clock, leave it as it is.
+#define ATOM_PPLIB_RS780_SPMCLK_LOW         1
+#define ATOM_PPLIB_RS780_SPMCLK_HIGH        2
+
+#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE       0
+#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW        1
+#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH       2
+
 /**************************************************************************/
 
 /*  Following definitions are for compatiblity issue in different SW components. */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_i2c.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -59,35 +59,50 @@
 }
 
 
-void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state)
+void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
 {
-	struct radeon_device *rdev = radeon_connector->base.dev->dev_private;
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t temp;
-	struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec;
 
 	/* RV410 appears to have a bug where the hw i2c in reset
 	 * holds the i2c port in a bad state - switch hw i2c away before
 	 * doing DDC - do this for all r200s/r300s/r400s for safety sake
 	 */
-	if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
-		if (rec->a_clk_reg == RADEON_GPIO_MONID) {
-			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
-						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
-		} else {
-			WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
-						R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
+	if (rec->hw_capable) {
+		if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
+			if (rec->a_clk_reg == RADEON_GPIO_MONID) {
+				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
+			} else {
+				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
+							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
+			}
 		}
 	}
-	if (lock_state) {
-		temp = RREG32(rec->a_clk_reg);
-		temp &= ~(rec->a_clk_mask);
-		WREG32(rec->a_clk_reg, temp);
-
-		temp = RREG32(rec->a_data_reg);
-		temp &= ~(rec->a_data_mask);
-		WREG32(rec->a_data_reg, temp);
+
+	/* switch the pads to ddc mode */
+	if (ASIC_IS_DCE3(rdev) && rec->hw_capable) {
+		temp = RREG32(rec->mask_clk_reg);
+		temp &= ~(1 << 16);
+		WREG32(rec->mask_clk_reg, temp);
 	}
 
+	/* clear the output pin values */
+	temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask;
+	WREG32(rec->a_clk_reg, temp);
+
+	temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
+	WREG32(rec->a_data_reg, temp);
+
+	/* set the pins to input */
+	temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
+	WREG32(rec->en_clk_reg, temp);
+
+	temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
+	WREG32(rec->en_data_reg, temp);
+
+	/* mask the gpio pins for software use */
 	temp = RREG32(rec->mask_clk_reg);
 	if (lock_state)
 		temp |= rec->mask_clk_mask;
@@ -112,8 +127,9 @@
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t val;
 
-	val = RREG32(rec->get_clk_reg);
-	val &= rec->get_clk_mask;
+	/* read the value off the pin */
+	val = RREG32(rec->y_clk_reg);
+	val &= rec->y_clk_mask;
 
 	return (val != 0);
 }
@@ -126,8 +142,10 @@
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t val;
 
-	val = RREG32(rec->get_data_reg);
-	val &= rec->get_data_mask;
+	/* read the value off the pin */
+	val = RREG32(rec->y_data_reg);
+	val &= rec->y_data_mask;
+
 	return (val != 0);
 }
 
@@ -138,9 +156,10 @@
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t val;
 
-	val = RREG32(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask);
-	val |= clock ? 0 : rec->put_clk_mask;
-	WREG32(rec->put_clk_reg, val);
+	/* set pin direction */
+	val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
+	val |= clock ? 0 : rec->en_clk_mask;
+	WREG32(rec->en_clk_reg, val);
 }
 
 static void set_data(void *i2c_priv, int data)
@@ -150,14 +169,15 @@
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
 	uint32_t val;
 
-	val = RREG32(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask);
-	val |= data ? 0 : rec->put_data_mask;
-	WREG32(rec->put_data_reg, val);
+	/* set pin direction */
+	val = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
+	val |= data ? 0 : rec->en_data_mask;
+	WREG32(rec->en_data_reg, val);
 }
 
 struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
-		struct radeon_i2c_bus_rec *rec,
-		const char *name)
+					  struct radeon_i2c_bus_rec *rec,
+					  const char *name)
 {
 	struct radeon_i2c_chan *i2c;
 	int ret;
@@ -167,20 +187,19 @@
 		return NULL;
 
 	i2c->adapter.owner = THIS_MODULE;
-	i2c->adapter.algo_data = &i2c->algo;
 	i2c->dev = dev;
-	i2c->algo.setsda = set_data;
-	i2c->algo.setscl = set_clock;
-	i2c->algo.getsda = get_data;
-	i2c->algo.getscl = get_clock;
-	i2c->algo.udelay = 20;
+	i2c_set_adapdata(&i2c->adapter, i2c);
+	i2c->adapter.algo_data = &i2c->algo.bit;
+	i2c->algo.bit.setsda = set_data;
+	i2c->algo.bit.setscl = set_clock;
+	i2c->algo.bit.getsda = get_data;
+	i2c->algo.bit.getscl = get_clock;
+	i2c->algo.bit.udelay = 20;
 	/* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
 	 * make this, 2 jiffies is a lot more reliable */
-	i2c->algo.timeout = 2;
-	i2c->algo.data = i2c;
+	i2c->algo.bit.timeout = 2;
+	i2c->algo.bit.data = i2c;
 	i2c->rec = *rec;
-	i2c_set_adapdata(&i2c->adapter, i2c);
-
 	ret = i2c_bit_add_bus(&i2c->adapter);
 	if (ret) {
 		DRM_INFO("Failed to register i2c %s\n", name);
@@ -194,6 +213,38 @@
 
 }
 
+struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
+					     struct radeon_i2c_bus_rec *rec,
+					     const char *name)
+{
+	struct radeon_i2c_chan *i2c;
+	int ret;
+
+	i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
+	if (i2c == NULL)
+		return NULL;
+
+	i2c->rec = *rec;
+	i2c->adapter.owner = THIS_MODULE;
+	i2c->dev = dev;
+	i2c_set_adapdata(&i2c->adapter, i2c);
+	i2c->adapter.algo_data = &i2c->algo.dp;
+	i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch;
+	i2c->algo.dp.address = 0;
+	ret = i2c_dp_aux_add_bus(&i2c->adapter);
+	if (ret) {
+		DRM_INFO("Failed to register i2c %s\n", name);
+		goto out_free;
+	}
+
+	return i2c;
+out_free:
+	kfree(i2c);
+	return NULL;
+
+}
+
+
 void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 {
 	if (!i2c)
@@ -207,3 +258,59 @@
 {
 	return NULL;
 }
+
+void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
+			    u8 slave_addr,
+			    u8 addr,
+			    u8 *val)
+{
+	u8 out_buf[2];
+	u8 in_buf[2];
+	struct i2c_msg msgs[] = {
+		{
+			.addr = slave_addr,
+			.flags = 0,
+			.len = 1,
+			.buf = out_buf,
+		},
+		{
+			.addr = slave_addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = in_buf,
+		}
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = 0;
+
+	if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) {
+		*val = in_buf[0];
+		DRM_DEBUG("val = 0x%02x\n", *val);
+	} else {
+		DRM_ERROR("i2c 0x%02x 0x%02x read failed\n",
+			  addr, *val);
+	}
+}
+
+void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus,
+			    u8 slave_addr,
+			    u8 addr,
+			    u8 val)
+{
+	uint8_t out_buf[2];
+	struct i2c_msg msg = {
+		.addr = slave_addr,
+		.flags = 0,
+		.len = 2,
+		.buf = out_buf,
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = val;
+
+	if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1)
+		DRM_ERROR("i2c 0x%02x 0x%02x write failed\n",
+			  addr, val);
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -39,11 +39,32 @@
 	return radeon_irq_process(rdev);
 }
 
+/*
+ * Handle hotplug events outside the interrupt handler proper.
+ */
+static void radeon_hotplug_work_func(struct work_struct *work)
+{
+	struct radeon_device *rdev = container_of(work, struct radeon_device,
+						  hotplug_work);
+	struct drm_device *dev = rdev->ddev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+
+	if (mode_config->num_connector) {
+		list_for_each_entry(connector, &mode_config->connector_list, head)
+			radeon_connector_hotplug(connector);
+	}
+	/* Just fire off a uevent and let userspace tell us what to do */
+	drm_sysfs_hotplug_event(dev);
+}
+
 void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	unsigned i;
 
+	INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
+
 	/* Disable *all* interrupts */
 	rdev->irq.sw_int = false;
 	for (i = 0; i < 2; i++) {
@@ -76,6 +97,7 @@
 	rdev->irq.sw_int = false;
 	for (i = 0; i < 2; i++) {
 		rdev->irq.crtc_vblank_int[i] = false;
+		rdev->irq.hpd[i] = false;
 	}
 	radeon_irq_set(rdev);
 }
@@ -87,30 +109,68 @@
 
 	if (rdev->flags & RADEON_SINGLE_CRTC)
 		num_crtc = 1;
-
+	spin_lock_init(&rdev->irq.sw_lock);
 	r = drm_vblank_init(rdev->ddev, num_crtc);
 	if (r) {
 		return r;
 	}
 	/* enable msi */
 	rdev->msi_enabled = 0;
-	if (rdev->family >= CHIP_RV380) {
+	/* MSIs don't seem to work reliably on all IGP
+	 * chips.  Disable MSI on them for now.
+	 */
+	if ((rdev->family >= CHIP_RV380) &&
+	    (!(rdev->flags & RADEON_IS_IGP)) &&
+	    (!(rdev->flags & RADEON_IS_AGP))) {
 		int ret = pci_enable_msi(rdev->pdev);
-		if (!ret)
+		if (!ret) {
 			rdev->msi_enabled = 1;
+			dev_info(rdev->dev, "radeon: using MSI.\n");
+		}
 	}
-	drm_irq_install(rdev->ddev);
 	rdev->irq.installed = true;
+	r = drm_irq_install(rdev->ddev);
+	if (r) {
+		rdev->irq.installed = false;
+		return r;
+	}
 	DRM_INFO("radeon: irq initialized.\n");
 	return 0;
 }
 
 void radeon_irq_kms_fini(struct radeon_device *rdev)
 {
+	drm_vblank_cleanup(rdev->ddev);
 	if (rdev->irq.installed) {
-		rdev->irq.installed = false;
 		drm_irq_uninstall(rdev->ddev);
+		rdev->irq.installed = false;
 		if (rdev->msi_enabled)
 			pci_disable_msi(rdev->pdev);
 	}
 }
+
+void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
+	if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) {
+		rdev->irq.sw_int = true;
+		radeon_irq_set(rdev);
+	}
+	spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
+}
+
+void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
+	BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0);
+	if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) {
+		rdev->irq.sw_int = false;
+		radeon_irq_set(rdev);
+	}
+	spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -29,8 +29,8 @@
 void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
 			   unsigned sdomain, unsigned ddomain)
 {
-	struct radeon_object *dobj = NULL;
-	struct radeon_object *sobj = NULL;
+	struct radeon_bo *dobj = NULL;
+	struct radeon_bo *sobj = NULL;
 	struct radeon_fence *fence = NULL;
 	uint64_t saddr, daddr;
 	unsigned long start_jiffies;
@@ -41,47 +41,66 @@
 
 	size = bsize;
 	n = 1024;
-	r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj);
+	r = radeon_bo_create(rdev, NULL, size, true, sdomain, &sobj);
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_object_pin(sobj, sdomain, &saddr);
+	r = radeon_bo_reserve(sobj, false);
+	if (unlikely(r != 0))
+		goto out_cleanup;
+	r = radeon_bo_pin(sobj, sdomain, &saddr);
+	radeon_bo_unreserve(sobj);
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj);
+	r = radeon_bo_create(rdev, NULL, size, true, ddomain, &dobj);
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_object_pin(dobj, ddomain, &daddr);
+	r = radeon_bo_reserve(dobj, false);
+	if (unlikely(r != 0))
+		goto out_cleanup;
+	r = radeon_bo_pin(dobj, ddomain, &daddr);
+	radeon_bo_unreserve(dobj);
 	if (r) {
 		goto out_cleanup;
 	}
-	start_jiffies = jiffies;
-	for (i = 0; i < n; i++) {
-		r = radeon_fence_create(rdev, &fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_copy_dma(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, fence);
-		if (r) {
-			goto out_cleanup;
-		}
-		r = radeon_fence_wait(fence, false);
-		if (r) {
-			goto out_cleanup;
+
+	/* r100 doesn't have dma engine so skip the test */
+	if (rdev->asic->copy_dma) {
+
+		start_jiffies = jiffies;
+		for (i = 0; i < n; i++) {
+			r = radeon_fence_create(rdev, &fence);
+			if (r) {
+				goto out_cleanup;
+			}
+
+			r = radeon_copy_dma(rdev, saddr, daddr,
+					size / RADEON_GPU_PAGE_SIZE, fence);
+
+			if (r) {
+				goto out_cleanup;
+			}
+			r = radeon_fence_wait(fence, false);
+			if (r) {
+				goto out_cleanup;
+			}
+			radeon_fence_unref(&fence);
+		}
+		end_jiffies = jiffies;
+		time = end_jiffies - start_jiffies;
+		time = jiffies_to_msecs(time);
+		if (time > 0) {
+			i = ((n * size) >> 10) / time;
+			printk(KERN_INFO "radeon: dma %u bo moves of %ukb from"
+					" %d to %d in %lums (%ukb/ms %ukb/s %uM/s)\n",
+					n, size >> 10,
+					sdomain, ddomain, time,
+					i, i * 1000, (i * 1000) / 1024);
 		}
-		radeon_fence_unref(&fence);
-	}
-	end_jiffies = jiffies;
-	time = end_jiffies - start_jiffies;
-	time = jiffies_to_msecs(time);
-	if (time > 0) {
-		i = ((n * size) >> 10) / time;
-		printk(KERN_INFO "radeon: dma %u bo moves of %ukb from %d to %d"
-		       " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10,
-		       sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024);
 	}
+
 	start_jiffies = jiffies;
 	for (i = 0; i < n; i++) {
 		r = radeon_fence_create(rdev, &fence);
@@ -109,12 +128,20 @@
 	}
 out_cleanup:
 	if (sobj) {
-		radeon_object_unpin(sobj);
-		radeon_object_unref(&sobj);
+		r = radeon_bo_reserve(sobj, false);
+		if (likely(r == 0)) {
+			radeon_bo_unpin(sobj);
+			radeon_bo_unreserve(sobj);
+		}
+		radeon_bo_unref(&sobj);
 	}
 	if (dobj) {
-		radeon_object_unpin(dobj);
-		radeon_object_unref(&dobj);
+		r = radeon_bo_reserve(dobj, false);
+		if (likely(r == 0)) {
+			radeon_bo_unpin(dobj);
+			radeon_bo_unreserve(dobj);
+		}
+		radeon_bo_unref(&dobj);
 	}
 	if (fence) {
 		radeon_fence_unref(&fence);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r500_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r500_reg.h
@@ -716,6 +716,8 @@
 
 #define AVIVO_DVOA_BIT_DEPTH_CONTROL			0x7988
 
+#define AVIVO_DC_GPIO_HPD_A                 0x7e94
+
 #define AVIVO_GPIO_0                        0x7e30
 #define AVIVO_GPIO_1                        0x7e40
 #define AVIVO_GPIO_2                        0x7e50
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/r420.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/r420.c
@@ -30,7 +30,15 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "atom.h"
+#include "r100d.h"
 #include "r420d.h"
+#include "r420_reg_safe.h"
+
+static void r420_set_reg_safe(struct radeon_device *rdev)
+{
+	rdev->config.r300.reg_safe_bm = r420_reg_safe_bm;
+	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
+}
 
 int r420_mc_init(struct radeon_device *rdev)
 {
@@ -42,9 +50,7 @@
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);
 		if (r) {
-			printk(KERN_WARNING "[drm] Disabling AGP\n");
-			rdev->flags &= ~RADEON_IS_AGP;
-			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+			radeon_agp_disable(rdev);
 		} else {
 			rdev->mc.gtt_location = rdev->mc.agp_base;
 		}
@@ -165,10 +171,41 @@
 	WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
 }
 
+static void r420_cp_errata_init(struct radeon_device *rdev)
+{
+	/* RV410 and R420 can lock up if CP DMA to host memory happens
+	 * while the 2D engine is busy.
+	 *
+	 * The proper workaround is to queue a RESYNC at the beginning
+	 * of the CP init, apparently.
+	 */
+	radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch);
+	radeon_ring_lock(rdev, 8);
+	radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1));
+	radeon_ring_write(rdev, rdev->config.r300.resync_scratch);
+	radeon_ring_write(rdev, 0xDEADBEEF);
+	radeon_ring_unlock_commit(rdev);
+}
+
+static void r420_cp_errata_fini(struct radeon_device *rdev)
+{
+	/* Catch the RESYNC we dispatched all the way back,
+	 * at the very beginning of the CP init.
+	 */
+	radeon_ring_lock(rdev, 8);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_RB3D_DC_FINISH);
+	radeon_ring_unlock_commit(rdev);
+	radeon_scratch_free(rdev, rdev->config.r300.resync_scratch);
+}
+
 static int r420_startup(struct radeon_device *rdev)
 {
 	int r;
 
+	/* set common regs */
+	r100_set_common_regs(rdev);
+	/* program mc */
 	r300_mc_program(rdev);
 	/* Resume clock */
 	r420_clock_resume(rdev);
@@ -186,14 +223,15 @@
 	}
 	r420_pipes_init(rdev);
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	r100_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
 		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
 		return r;
 	}
+	r420_cp_errata_init(rdev);
 	r = r100_wb_init(rdev);
 	if (r) {
 		dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
@@ -229,12 +267,14 @@
 	}
 	/* Resume clock after posting */
 	r420_clock_resume(rdev);
-
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return r420_startup(rdev);
 }
 
 int r420_suspend(struct radeon_device *rdev)
 {
+	r420_cp_errata_fini(rdev);
 	r100_cp_disable(rdev);
 	r100_wb_disable(rdev);
 	r100_irq_disable(rdev);
@@ -258,7 +298,7 @@
 	radeon_agp_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	if (rdev->is_atom_bios) {
 		radeon_atombios_fini(rdev);
 	} else {
@@ -301,14 +341,9 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		if (rdev->is_atom_bios) {
-			atom_asic_init(rdev->mode_info.atom_context);
-		} else {
-			radeon_combios_asic_init(rdev->ddev);
-		}
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
+
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
@@ -331,10 +366,13 @@
 		return r;
 	}
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r) {
 		return r;
 	}
+	if (rdev->family == CHIP_R420)
+		r100_enable_bm(rdev);
+
 	if (rdev->flags & RADEON_IS_PCIE) {
 		r = rv370_pcie_gart_init(rdev);
 		if (r)
@@ -345,22 +383,21 @@
 		if (r)
 			return r;
 	}
-	r300_set_reg_safe(rdev);
+	r420_set_reg_safe(rdev);
 	rdev->accel_working = true;
 	r = r420_startup(rdev);
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		r420_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
+		radeon_irq_kms_fini(rdev);
 		if (rdev->flags & RADEON_IS_PCIE)
 			rv370_pcie_gart_fini(rdev);
 		if (rdev->flags & RADEON_IS_PCI)
 			r100_pci_gart_fini(rdev);
 		radeon_agp_fini(rdev);
-		radeon_irq_kms_fini(rdev);
 		rdev->accel_working = false;
 	}
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_fence.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_fence.c
@@ -140,16 +140,15 @@
 
 bool radeon_fence_signaled(struct radeon_fence *fence)
 {
-	struct radeon_device *rdev = fence->rdev;
 	unsigned long irq_flags;
 	bool signaled = false;
 
-	if (rdev->gpu_lockup) {
+	if (!fence)
 		return true;
-	}
-	if (fence == NULL) {
+
+	if (fence->rdev->gpu_lockup)
 		return true;
-	}
+
 	write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags);
 	signaled = fence->signaled;
 	/* if we are shuting down report all fence as signaled */
@@ -168,37 +167,6 @@
 	return signaled;
 }
 
-int r600_fence_wait(struct radeon_fence *fence,  bool intr, bool lazy)
-{
-	struct radeon_device *rdev;
-	int ret = 0;
-
-	rdev = fence->rdev;
-
-	__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-
-	while (1) {
-		if (radeon_fence_signaled(fence))
-			break;
-
-		if (time_after_eq(jiffies, fence->timeout)) {
-			ret = -EBUSY;
-			break;
-		}
-
-		if (lazy)
-			schedule_timeout(1);
-
-		if (intr && signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	__set_current_state(TASK_RUNNING);
-	return ret;
-}
-
-
 int radeon_fence_wait(struct radeon_fence *fence, bool intr)
 {
 	struct radeon_device *rdev;
@@ -216,13 +184,6 @@
 		return 0;
 	}
 
-	if (rdev->family >= CHIP_R600) {
-		r = r600_fence_wait(fence, intr, 0);
-		if (r == -ERESTARTSYS)
-			return -EBUSY;
-		return r;
-	}
-
 retry:
 	cur_jiffies = jiffies;
 	timeout = HZ / 100;
@@ -231,14 +192,17 @@
 	}
 
 	if (intr) {
+		radeon_irq_kms_sw_irq_get(rdev);
 		r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
 				radeon_fence_signaled(fence), timeout);
-		if (unlikely(r == -ERESTARTSYS)) {
-			return -EBUSY;
-		}
+		radeon_irq_kms_sw_irq_put(rdev);
+		if (unlikely(r < 0))
+			return r;
 	} else {
+		radeon_irq_kms_sw_irq_get(rdev);
 		r = wait_event_timeout(rdev->fence_drv.queue,
 			 radeon_fence_signaled(fence), timeout);
+		radeon_irq_kms_sw_irq_put(rdev);
 	}
 	if (unlikely(!radeon_fence_signaled(fence))) {
 		if (unlikely(r == 0)) {
@@ -359,7 +323,7 @@
 	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
 	r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg);
 	if (r) {
-		DRM_ERROR("Fence failed to get a scratch register.");
+		dev_err(rdev->dev, "fence failed to get scratch register\n");
 		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
 		return r;
 	}
@@ -370,9 +334,10 @@
 	INIT_LIST_HEAD(&rdev->fence_drv.signaled);
 	rdev->fence_drv.count_timeout = 0;
 	init_waitqueue_head(&rdev->fence_drv.queue);
+	rdev->fence_drv.initialized = true;
 	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
 	if (radeon_debugfs_fence_init(rdev)) {
-		DRM_ERROR("Failed to register debugfs file for fence !\n");
+		dev_err(rdev->dev, "fence debugfs file creation failed\n");
 	}
 	return 0;
 }
@@ -381,11 +346,13 @@
 {
 	unsigned long irq_flags;
 
+	if (!rdev->fence_drv.initialized)
+		return;
 	wake_up_all(&rdev->fence_drv.queue);
 	write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
 	radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg);
 	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
-	DRM_INFO("radeon: fence finalized\n");
+	rdev->fence_drv.initialized = false;
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/ObjectID.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/ObjectID.h
@@ -1,5 +1,5 @@
 /*
-* Copyright 2006-2007 Advanced Micro Devices, Inc.
+* Copyright 2006-2007 Advanced Micro Devices, Inc.  
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -41,14 +41,14 @@
 /****************************************************/
 /* Encoder Object ID Definition                     */
 /****************************************************/
-#define ENCODER_OBJECT_ID_NONE                    0x00
+#define ENCODER_OBJECT_ID_NONE                    0x00 
 
 /* Radeon Class Display Hardware */
 #define ENCODER_OBJECT_ID_INTERNAL_LVDS           0x01
 #define ENCODER_OBJECT_ID_INTERNAL_TMDS1          0x02
 #define ENCODER_OBJECT_ID_INTERNAL_TMDS2          0x03
 #define ENCODER_OBJECT_ID_INTERNAL_DAC1           0x04
-#define ENCODER_OBJECT_ID_INTERNAL_DAC2           0x05	/* TV/CV DAC */
+#define ENCODER_OBJECT_ID_INTERNAL_DAC2           0x05     /* TV/CV DAC */
 #define ENCODER_OBJECT_ID_INTERNAL_SDVOA          0x06
 #define ENCODER_OBJECT_ID_INTERNAL_SDVOB          0x07
 
@@ -56,11 +56,11 @@
 #define ENCODER_OBJECT_ID_SI170B                  0x08
 #define ENCODER_OBJECT_ID_CH7303                  0x09
 #define ENCODER_OBJECT_ID_CH7301                  0x0A
-#define ENCODER_OBJECT_ID_INTERNAL_DVO1           0x0B	/* This belongs to Radeon Class Display Hardware */
+#define ENCODER_OBJECT_ID_INTERNAL_DVO1           0x0B    /* This belongs to Radeon Class Display Hardware */
 #define ENCODER_OBJECT_ID_EXTERNAL_SDVOA          0x0C
 #define ENCODER_OBJECT_ID_EXTERNAL_SDVOB          0x0D
 #define ENCODER_OBJECT_ID_TITFP513                0x0E
-#define ENCODER_OBJECT_ID_INTERNAL_LVTM1          0x0F	/* not used for Radeon */
+#define ENCODER_OBJECT_ID_INTERNAL_LVTM1          0x0F    /* not used for Radeon */
 #define ENCODER_OBJECT_ID_VT1623                  0x10
 #define ENCODER_OBJECT_ID_HDMI_SI1930             0x11
 #define ENCODER_OBJECT_ID_HDMI_INTERNAL           0x12
@@ -68,9 +68,9 @@
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1   0x13
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1    0x14
 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1    0x15
-#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2    0x16	/* Shared with CV/TV and CRT */
-#define ENCODER_OBJECT_ID_SI178                   0X17	/* External TMDS (dual link, no HDCP.) */
-#define ENCODER_OBJECT_ID_MVPU_FPGA               0x18	/* MVPU FPGA chip */
+#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2    0x16  /* Shared with CV/TV and CRT */
+#define ENCODER_OBJECT_ID_SI178                   0X17  /* External TMDS (dual link, no HDCP.) */
+#define ENCODER_OBJECT_ID_MVPU_FPGA               0x18  /* MVPU FPGA chip */
 #define ENCODER_OBJECT_ID_INTERNAL_DDI            0x19
 #define ENCODER_OBJECT_ID_VT1625                  0x1A
 #define ENCODER_OBJECT_ID_HDMI_SI1932             0x1B
@@ -86,7 +86,7 @@
 /****************************************************/
 /* Connector Object ID Definition                   */
 /****************************************************/
-#define CONNECTOR_OBJECT_ID_NONE                  0x00
+#define CONNECTOR_OBJECT_ID_NONE                  0x00 
 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I     0x01
 #define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I       0x02
 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D     0x03
@@ -96,7 +96,7 @@
 #define CONNECTOR_OBJECT_ID_SVIDEO                0x07
 #define CONNECTOR_OBJECT_ID_YPbPr                 0x08
 #define CONNECTOR_OBJECT_ID_D_CONNECTOR           0x09
-#define CONNECTOR_OBJECT_ID_9PIN_DIN              0x0A	/* Supports both CV & TV */
+#define CONNECTOR_OBJECT_ID_9PIN_DIN              0x0A  /* Supports both CV & TV */
 #define CONNECTOR_OBJECT_ID_SCART                 0x0B
 #define CONNECTOR_OBJECT_ID_HDMI_TYPE_A           0x0C
 #define CONNECTOR_OBJECT_ID_HDMI_TYPE_B           0x0D
@@ -106,6 +106,8 @@
 #define CONNECTOR_OBJECT_ID_CROSSFIRE             0x11
 #define CONNECTOR_OBJECT_ID_HARDCODE_DVI          0x12
 #define CONNECTOR_OBJECT_ID_DISPLAYPORT           0x13
+#define CONNECTOR_OBJECT_ID_eDP                   0x14
+#define CONNECTOR_OBJECT_ID_MXM                   0x15
 
 /* deleted */
 
@@ -116,6 +118,14 @@
 #define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL				0x01
 
 /****************************************************/
+/* Generic Object ID Definition                     */
+/****************************************************/
+#define GENERIC_OBJECT_ID_NONE                    0x00
+#define GENERIC_OBJECT_ID_GLSYNC                  0x01
+#define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE        0x02
+#define GENERIC_OBJECT_ID_MXM_OPM                 0x03
+
+/****************************************************/
 /* Graphics Object ENUM ID Definition               */
 /****************************************************/
 #define GRAPH_OBJECT_ENUM_ID1                     0x01
@@ -124,6 +134,7 @@
 #define GRAPH_OBJECT_ENUM_ID4                     0x04
 #define GRAPH_OBJECT_ENUM_ID5                     0x05
 #define GRAPH_OBJECT_ENUM_ID6                     0x06
+#define GRAPH_OBJECT_ENUM_ID7                     0x07
 
 /****************************************************/
 /* Graphics Object ID Bit definition                */
@@ -133,35 +144,35 @@
 #define RESERVED1_ID_MASK                         0x0800
 #define OBJECT_TYPE_MASK                          0x7000
 #define RESERVED2_ID_MASK                         0x8000
-
+                                                  
 #define OBJECT_ID_SHIFT                           0x00
 #define ENUM_ID_SHIFT                             0x08
 #define OBJECT_TYPE_SHIFT                         0x0C
 
+
 /****************************************************/
 /* Graphics Object family definition                */
 /****************************************************/
-#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) \
-	(GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
-	 GRAPHICS_OBJECT_ID   << OBJECT_ID_SHIFT)
+#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
+                                                                           GRAPHICS_OBJECT_ID   << OBJECT_ID_SHIFT)
 /****************************************************/
 /* GPU Object ID definition - Shared with BIOS      */
 /****************************************************/
-#define GPU_ENUM_ID1	(GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
-			 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
+#define GPU_ENUM_ID1                            ( GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
 
 /****************************************************/
 /* Encoder Object ID definition - Shared with BIOS  */
 /****************************************************/
 /*
-#define ENCODER_INTERNAL_LVDS_ENUM_ID1        0x2101
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1        0x2101      
 #define ENCODER_INTERNAL_TMDS1_ENUM_ID1       0x2102
 #define ENCODER_INTERNAL_TMDS2_ENUM_ID1       0x2103
 #define ENCODER_INTERNAL_DAC1_ENUM_ID1        0x2104
 #define ENCODER_INTERNAL_DAC2_ENUM_ID1        0x2105
 #define ENCODER_INTERNAL_SDVOA_ENUM_ID1       0x2106
 #define ENCODER_INTERNAL_SDVOB_ENUM_ID1       0x2107
-#define ENCODER_SIL170B_ENUM_ID1              0x2108
+#define ENCODER_SIL170B_ENUM_ID1              0x2108  
 #define ENCODER_CH7303_ENUM_ID1               0x2109
 #define ENCODER_CH7301_ENUM_ID1               0x210A
 #define ENCODER_INTERNAL_DVO1_ENUM_ID1        0x210B
@@ -175,8 +186,8 @@
 #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1   0x2113
 #define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1    0x2114
 #define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1    0x2115
-#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    0x2116
-#define ENCODER_SI178_ENUM_ID1                   0x2117
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    0x2116  
+#define ENCODER_SI178_ENUM_ID1                   0x2117 
 #define ENCODER_MVPU_FPGA_ENUM_ID1               0x2118
 #define ENCODER_INTERNAL_DDI_ENUM_ID1            0x2119
 #define ENCODER_VT1625_ENUM_ID1                  0x211A
@@ -185,205 +196,169 @@
 #define ENCODER_DP_DP501_ENUM_ID1                0x211D
 #define ENCODER_INTERNAL_UNIPHY_ENUM_ID1         0x211E
 */
-#define ENCODER_INTERNAL_LVDS_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DAC1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DAC2_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
-
-#define ENCODER_SIL170B_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
-
-#define ENCODER_CH7303_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
-
-#define ENCODER_CH7301_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DVO1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
-
-#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
-
-#define ENCODER_TITFP513_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_VT1623_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_SI1930_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_INTERNAL_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) /* Shared with CV/TV and CRT */
-
-#define ENCODER_SI178_ENUM_ID1  \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)
-
-#define ENCODER_MVPU_FPGA_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_DDI_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT)
-
-#define ENCODER_VT1625_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
-
-#define ENCODER_HDMI_SI1932_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
-
-#define ENCODER_DP_DP501_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
-
-#define ENCODER_DP_AN9801_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
-
-#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
+#define ENCODER_INTERNAL_LVDS_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_TMDS2_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC1_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DAC2_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOA_ENUM_ID2    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_SDVOB_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+#define ENCODER_SIL170B_ENUM_ID1           ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7303_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
+
+#define ENCODER_CH7301_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DVO1_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_TITFP513_ENUM_ID1          ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_LVTM1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_VT1623_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1930_ENUM_ID1       ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_INTERNAL_ENUM_ID1     ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
+
+
+#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT)  // Shared with CV/TV and CRT
+
+#define ENCODER_SI178_ENUM_ID1                    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)  
+
+#define ENCODER_MVPU_FPGA_ENUM_ID1                ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                   ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_DDI_ENUM_ID1     (  GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) 
+
+#define ENCODER_VT1625_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
+
+#define ENCODER_HDMI_SI1932_ENUM_ID1       ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_DP501_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
+
+#define ENCODER_DP_AN9801_ENUM_ID1            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                             GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                             ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1   ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)  
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2         ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
+
+#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1    ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
+                                                  GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                  ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
 
 /****************************************************/
 /* Connector Object ID definition - Shared with BIOS */
@@ -406,167 +381,253 @@
 #define CONNECTOR_7PIN_DIN_ENUM_ID1                 0x310F
 #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1           0x3110
 */
-#define CONNECTOR_LVDS_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_VGA_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_VGA_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_COMPOSITE_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SVIDEO_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_YPbPr_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_D_CONNECTOR_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_9PIN_DIN_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_SCART_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_7PIN_DIN_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_CROSSFIRE_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_CROSSFIRE_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID2 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID3 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
-
-#define CONNECTOR_DISPLAYPORT_ENUM_ID4 \
-	(GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
-	 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+#define CONNECTOR_LVDS_ENUM_ID1                ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_LVDS_ENUM_ID2                ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_eDP_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_eDP_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2   ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID2     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID3     ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_VGA_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_COMPOSITE_ENUM_ID1           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_COMPOSITE_ENUM_ID2           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SVIDEO_ENUM_ID1              ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SVIDEO_ENUM_ID2              ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_YPbPr_ENUM_ID1               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_YPbPr_ENUM_ID2               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_D_CONNECTOR_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_D_CONNECTOR_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_9PIN_DIN_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_9PIN_DIN_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SCART_ENUM_ID1               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_SCART_ENUM_ID2               ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_A_ENUM_ID3         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HDMI_TYPE_B_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_7PIN_DIN_ENUM_ID1            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+#define CONNECTOR_7PIN_DIN_ENUM_ID2            ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1      ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2      ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID1           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_CROSSFIRE_ENUM_ID2           ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
+
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID1        ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_HARDCODE_DVI_ENUM_ID2        ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID1         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID2         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID3         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID4         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID5         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_DISPLAYPORT_ENUM_ID6         ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
+
+#define CONNECTOR_MXM_ENUM_ID1                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_A
+
+#define CONNECTOR_MXM_ENUM_ID2                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_B
+
+#define CONNECTOR_MXM_ENUM_ID3                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_C
+
+#define CONNECTOR_MXM_ENUM_ID4                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DP_D
+
+#define CONNECTOR_MXM_ENUM_ID5                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_LVDS_TXxx
+
+#define CONNECTOR_MXM_ENUM_ID6                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_LVDS_UXxx
+
+#define CONNECTOR_MXM_ENUM_ID7                 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\
+                                                 CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT)          //Mapping to MXM_DAC
 
 /****************************************************/
 /* Router Object ID definition - Shared with BIOS   */
 /****************************************************/
-#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 \
-	(GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
-	 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
-	 ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
+#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1      ( GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
+                                                GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
 
 /* deleted */
 
 /****************************************************/
+/* Generic Object ID definition - Shared with BIOS  */
+/****************************************************/
+#define GENERICOBJECT_GLSYNC_ENUM_ID1           (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_GLSYNC << OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_PX2_NON_DRIVABLE_ID1       (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_PX2_NON_DRIVABLE_ID2       (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT)
+
+#define GENERICOBJECT_MXM_OPM_ENUM_ID1           (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
+                                                 GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
+                                                 GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT)
+
+/****************************************************/
 /* Object Cap definition - Shared with BIOS         */
 /****************************************************/
 #define GRAPHICS_OBJECT_CAP_I2C                 0x00000001L
 #define GRAPHICS_OBJECT_CAP_TABLE_ID            0x00000002L
 
+
 #define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID                   0x01
 #define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID     0x02
 #define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID    0x03
@@ -575,4 +636,8 @@
 #pragma pack()
 #endif
 
-#endif /*GRAPHICTYPE */
+#endif  /*GRAPHICTYPE */
+
+
+
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_combios.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_combios.c
@@ -50,7 +50,8 @@
 			    uint32_t supported_device,
 			    int connector_type,
 			    struct radeon_i2c_bus_rec *i2c_bus,
-			    uint16_t connector_object_id);
+			    uint16_t connector_object_id,
+			    struct radeon_hpd *hpd);
 
 /* from radeon_legacy_encoder.c */
 extern void
@@ -442,39 +443,71 @@
 
 }
 
-struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
+static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
+						       int ddc_line)
 {
 	struct radeon_i2c_bus_rec i2c;
 
-	i2c.mask_clk_mask = RADEON_GPIO_EN_1;
-	i2c.mask_data_mask = RADEON_GPIO_EN_0;
-	i2c.a_clk_mask = RADEON_GPIO_A_1;
-	i2c.a_data_mask = RADEON_GPIO_A_0;
-	i2c.put_clk_mask = RADEON_GPIO_EN_1;
-	i2c.put_data_mask = RADEON_GPIO_EN_0;
-	i2c.get_clk_mask = RADEON_GPIO_Y_1;
-	i2c.get_data_mask = RADEON_GPIO_Y_0;
-	if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
-	    (ddc_line == RADEON_MDGPIO_EN_REG)) {
-		i2c.mask_clk_reg = ddc_line;
-		i2c.mask_data_reg = ddc_line;
-		i2c.a_clk_reg = ddc_line;
-		i2c.a_data_reg = ddc_line;
-		i2c.put_clk_reg = ddc_line;
-		i2c.put_data_reg = ddc_line;
-		i2c.get_clk_reg = ddc_line + 4;
-		i2c.get_data_reg = ddc_line + 4;
+	if (ddc_line == RADEON_GPIOPAD_MASK) {
+		i2c.mask_clk_reg = RADEON_GPIOPAD_MASK;
+		i2c.mask_data_reg = RADEON_GPIOPAD_MASK;
+		i2c.a_clk_reg = RADEON_GPIOPAD_A;
+		i2c.a_data_reg = RADEON_GPIOPAD_A;
+		i2c.en_clk_reg = RADEON_GPIOPAD_EN;
+		i2c.en_data_reg = RADEON_GPIOPAD_EN;
+		i2c.y_clk_reg = RADEON_GPIOPAD_Y;
+		i2c.y_data_reg = RADEON_GPIOPAD_Y;
+	} else if (ddc_line == RADEON_MDGPIO_MASK) {
+		i2c.mask_clk_reg = RADEON_MDGPIO_MASK;
+		i2c.mask_data_reg = RADEON_MDGPIO_MASK;
+		i2c.a_clk_reg = RADEON_MDGPIO_A;
+		i2c.a_data_reg = RADEON_MDGPIO_A;
+		i2c.en_clk_reg = RADEON_MDGPIO_EN;
+		i2c.en_data_reg = RADEON_MDGPIO_EN;
+		i2c.y_clk_reg = RADEON_MDGPIO_Y;
+		i2c.y_data_reg = RADEON_MDGPIO_Y;
 	} else {
+		i2c.mask_clk_mask = RADEON_GPIO_EN_1;
+		i2c.mask_data_mask = RADEON_GPIO_EN_0;
+		i2c.a_clk_mask = RADEON_GPIO_A_1;
+		i2c.a_data_mask = RADEON_GPIO_A_0;
+		i2c.en_clk_mask = RADEON_GPIO_EN_1;
+		i2c.en_data_mask = RADEON_GPIO_EN_0;
+		i2c.y_clk_mask = RADEON_GPIO_Y_1;
+		i2c.y_data_mask = RADEON_GPIO_Y_0;
+
 		i2c.mask_clk_reg = ddc_line;
 		i2c.mask_data_reg = ddc_line;
 		i2c.a_clk_reg = ddc_line;
 		i2c.a_data_reg = ddc_line;
-		i2c.put_clk_reg = ddc_line;
-		i2c.put_data_reg = ddc_line;
-		i2c.get_clk_reg = ddc_line;
-		i2c.get_data_reg = ddc_line;
+		i2c.en_clk_reg = ddc_line;
+		i2c.en_data_reg = ddc_line;
+		i2c.y_clk_reg = ddc_line;
+		i2c.y_data_reg = ddc_line;
 	}
 
+	if (rdev->family < CHIP_R200)
+		i2c.hw_capable = false;
+	else {
+		switch (ddc_line) {
+		case RADEON_GPIO_VGA_DDC:
+		case RADEON_GPIO_DVI_DDC:
+			i2c.hw_capable = true;
+			break;
+		case RADEON_GPIO_MONID:
+			/* hw i2c on RADEON_GPIO_MONID doesn't seem to work
+			 * reliably on some pre-r4xx hardware; not sure why.
+			 */
+			i2c.hw_capable = false;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+	}
+	i2c.mm_i2c = false;
+	i2c.i2c_id = 0;
+
 	if (ddc_line)
 		i2c.valid = true;
 	else
@@ -495,7 +528,7 @@
 	uint16_t sclk, mclk;
 
 	if (rdev->bios == NULL)
-		return NULL;
+		return false;
 
 	pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
 	if (pll_info) {
@@ -562,6 +595,52 @@
 	return false;
 }
 
+bool radeon_combios_sideport_present(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	u16 igp_info;
+
+	/* sideport is AMD only */
+	if (rdev->family == CHIP_RS400)
+		return false;
+
+	igp_info = combios_get_table_offset(dev, COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE);
+
+	if (igp_info) {
+		if (RBIOS16(igp_info + 0x4))
+			return true;
+	}
+	return false;
+}
+
+static const uint32_t default_primarydac_adj[CHIP_LAST] = {
+	0x00000808,		/* r100  */
+	0x00000808,		/* rv100 */
+	0x00000808,		/* rs100 */
+	0x00000808,		/* rv200 */
+	0x00000808,		/* rs200 */
+	0x00000808,		/* r200  */
+	0x00000808,		/* rv250 */
+	0x00000000,		/* rs300 */
+	0x00000808,		/* rv280 */
+	0x00000808,		/* r300  */
+	0x00000808,		/* r350  */
+	0x00000808,		/* rv350 */
+	0x00000808,		/* rv380 */
+	0x00000808,		/* r420  */
+	0x00000808,		/* r423  */
+	0x00000808,		/* rv410 */
+	0x00000000,		/* rs400 */
+	0x00000000,		/* rs480 */
+};
+
+static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev,
+							  struct radeon_encoder_primary_dac *p_dac)
+{
+	p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family];
+	return;
+}
+
 struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
 								       radeon_encoder
 								       *encoder)
@@ -571,20 +650,20 @@
 	uint16_t dac_info;
 	uint8_t rev, bg, dac;
 	struct radeon_encoder_primary_dac *p_dac = NULL;
+	int found = 0;
 
-	if (rdev->bios == NULL)
+	p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac),
+			GFP_KERNEL);
+
+	if (!p_dac)
 		return NULL;
 
+	if (rdev->bios == NULL)
+		goto out;
+
 	/* check CRT table */
 	dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
 	if (dac_info) {
-		p_dac =
-		    kzalloc(sizeof(struct radeon_encoder_primary_dac),
-			    GFP_KERNEL);
-
-		if (!p_dac)
-			return NULL;
-
 		rev = RBIOS8(dac_info) & 0x3;
 		if (rev < 2) {
 			bg = RBIOS8(dac_info + 0x2) & 0xf;
@@ -595,20 +674,28 @@
 			dac = RBIOS8(dac_info + 0x3) & 0xf;
 			p_dac->ps2_pdac_adj = (bg << 8) | (dac);
 		}
-
+		/* if the values are all zeros, use the table */
+		if (p_dac->ps2_pdac_adj)
+			found = 1;
 	}
 
+out:
+	if (!found) /* fallback to defaults */
+		radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
+
 	return p_dac;
 }
 
-static enum radeon_tv_std
-radeon_combios_get_tv_info(struct radeon_encoder *encoder)
+enum radeon_tv_std
+radeon_combios_get_tv_info(struct radeon_device *rdev)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct radeon_device *rdev = dev->dev_private;
+	struct drm_device *dev = rdev->ddev;
 	uint16_t tv_info;
 	enum radeon_tv_std tv_std = TV_STD_NTSC;
 
+	if (rdev->bios == NULL)
+		return tv_std;
+
 	tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
 	if (tv_info) {
 		if (RBIOS8(tv_info + 6) == 'T') {
@@ -731,7 +818,9 @@
 			bg = RBIOS8(dac_info + 0x10) & 0xf;
 			dac = RBIOS8(dac_info + 0x11) & 0xf;
 			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
-			found = 1;
+			/* if the values are all zeros, use the table */
+			if (tv_dac->ps2_tvdac_adj)
+				found = 1;
 		} else if (rev > 1) {
 			bg = RBIOS8(dac_info + 0xc) & 0xf;
 			dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf;
@@ -744,9 +833,11 @@
 			bg = RBIOS8(dac_info + 0xe) & 0xf;
 			dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;
 			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
-			found = 1;
+			/* if the values are all zeros, use the table */
+			if (tv_dac->ps2_tvdac_adj)
+				found = 1;
 		}
-		tv_dac->tv_std = radeon_combios_get_tv_info(encoder);
+		tv_dac->tv_std = radeon_combios_get_tv_info(rdev);
 	}
 	if (!found) {
 		/* then check CRT table */
@@ -761,7 +852,9 @@
 				    (bg << 16) | (dac << 20);
 				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
 				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
-				found = 1;
+				/* if the values are all zeros, use the table */
+				if (tv_dac->ps2_tvdac_adj)
+					found = 1;
 			} else {
 				bg = RBIOS8(dac_info + 0x4) & 0xf;
 				dac = RBIOS8(dac_info + 0x5) & 0xf;
@@ -769,7 +862,9 @@
 				    (bg << 16) | (dac << 20);
 				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
 				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
-				found = 1;
+				/* if the values are all zeros, use the table */
+				if (tv_dac->ps2_tvdac_adj)
+					found = 1;
 			}
 		} else {
 			DRM_INFO("No TV DAC info found in BIOS\n");
@@ -890,8 +985,7 @@
 			 lvds->native_mode.vdisplay);
 
 		lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c);
-		if (lvds->panel_vcc_delay > 2000 || lvds->panel_vcc_delay < 0)
-			lvds->panel_vcc_delay = 2000;
+		lvds->panel_vcc_delay = min_t(u16, lvds->panel_vcc_delay, 2000);
 
 		lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24);
 		lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf;
@@ -993,8 +1087,8 @@
 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R420  */
 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_R423  */
 	{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}},	/* CHIP_RV410 */
-	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RS400 */
-	{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}},	/* CHIP_RS480 */
+	{ {0, 0}, {0, 0}, {0, 0}, {0, 0} },	/* CHIP_RS400 */
+	{ {0, 0}, {0, 0}, {0, 0}, {0, 0} },	/* CHIP_RS480 */
 };
 
 bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
@@ -1028,7 +1122,6 @@
 	tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
 
 	if (tmds_info) {
-
 		ver = RBIOS8(tmds_info);
 		DRM_INFO("DFP table revision: %d\n", ver);
 		if (ver == 3) {
@@ -1063,51 +1156,139 @@
 					  tmds->tmds_pll[i].value);
 			}
 		}
-	} else
+	} else {
 		DRM_INFO("No TMDS info found in BIOS\n");
+		return false;
+	}
 	return true;
 }
 
-struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder)
+bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
+						struct radeon_encoder_ext_tmds *tmds)
 {
-	struct radeon_encoder_int_tmds *tmds = NULL;
-	bool ret;
-
-	tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
+	struct drm_device *dev = encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_i2c_bus_rec i2c_bus;
 
-	if (!tmds)
-		return NULL;
+	/* default for macs */
+	i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
+	tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 
-	ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
-	if (ret == false)
-		radeon_legacy_get_tmds_info_from_table(encoder, tmds);
+	/* XXX some macs have duallink chips */
+	switch (rdev->mode_info.connector_table) {
+	case CT_POWERBOOK_EXTERNAL:
+	case CT_MINI_EXTERNAL:
+	default:
+		tmds->dvo_chip = DVO_SIL164;
+		tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
+		break;
+	}
 
-	return tmds;
+	return true;
 }
 
-void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder)
+bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
+						  struct radeon_encoder_ext_tmds *tmds)
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct radeon_device *rdev = dev->dev_private;
-	uint16_t ext_tmds_info;
-	uint8_t ver;
+	uint16_t offset;
+	uint8_t ver, id, blocks, clk, data;
+	int i;
+	enum radeon_combios_ddc gpio;
+	struct radeon_i2c_bus_rec i2c_bus;
 
 	if (rdev->bios == NULL)
-		return;
+		return false;
 
-	ext_tmds_info =
-	    combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
-	if (ext_tmds_info) {
-		ver = RBIOS8(ext_tmds_info);
-		DRM_INFO("External TMDS Table revision: %d\n", ver);
-		// TODO
+	tmds->i2c_bus = NULL;
+	if (rdev->flags & RADEON_IS_IGP) {
+		offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
+		if (offset) {
+			ver = RBIOS8(offset);
+			DRM_INFO("GPIO Table revision: %d\n", ver);
+			blocks = RBIOS8(offset + 2);
+			for (i = 0; i < blocks; i++) {
+				id = RBIOS8(offset + 3 + (i * 5) + 0);
+				if (id == 136) {
+					clk = RBIOS8(offset + 3 + (i * 5) + 3);
+					data = RBIOS8(offset + 3 + (i * 5) + 4);
+					i2c_bus.valid = true;
+					i2c_bus.mask_clk_mask = (1 << clk);
+					i2c_bus.mask_data_mask = (1 << data);
+					i2c_bus.a_clk_mask = (1 << clk);
+					i2c_bus.a_data_mask = (1 << data);
+					i2c_bus.en_clk_mask = (1 << clk);
+					i2c_bus.en_data_mask = (1 << data);
+					i2c_bus.y_clk_mask = (1 << clk);
+					i2c_bus.y_data_mask = (1 << data);
+					i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK;
+					i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK;
+					i2c_bus.a_clk_reg = RADEON_GPIOPAD_A;
+					i2c_bus.a_data_reg = RADEON_GPIOPAD_A;
+					i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN;
+					i2c_bus.en_data_reg = RADEON_GPIOPAD_EN;
+					i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y;
+					i2c_bus.y_data_reg = RADEON_GPIOPAD_Y;
+					tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+					tmds->dvo_chip = DVO_SIL164;
+					tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
+					break;
+				}
+			}
+		}
+	} else {
+		offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
+		if (offset) {
+			ver = RBIOS8(offset);
+			DRM_INFO("External TMDS Table revision: %d\n", ver);
+			tmds->slave_addr = RBIOS8(offset + 4 + 2);
+			tmds->slave_addr >>= 1; /* 7 bit addressing */
+			gpio = RBIOS8(offset + 4 + 3);
+			switch (gpio) {
+			case DDC_MONID:
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
+				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+				break;
+			case DDC_DVI:
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+				break;
+			case DDC_VGA:
+				i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+				break;
+			case DDC_CRT2:
+				/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
+				if (rdev->family >= CHIP_R300)
+					i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
+				else
+					i2c_bus = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
+				break;
+			case DDC_LCD: /* MM i2c */
+				DRM_ERROR("MM i2c requires hw i2c engine\n");
+				break;
+			default:
+				DRM_ERROR("Unsupported gpio %d\n", gpio);
+				break;
+			}
+		}
+	}
+
+	if (!tmds->i2c_bus) {
+		DRM_INFO("No valid Ext TMDS info found in BIOS\n");
+		return false;
 	}
+
+	return true;
 }
 
 bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_i2c_bus_rec ddc_i2c;
+	struct radeon_hpd hpd;
 
 	rdev->mode_info.connector_table = radeon_connector_table;
 	if (rdev->mode_info.connector_table == CT_NONE) {
@@ -1168,7 +1349,8 @@
 		/* these are the most common settings */
 		if (rdev->flags & RADEON_SINGLE_CRTC) {
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1178,10 +1360,12 @@
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_VGA);
+						    CONNECTOR_OBJECT_ID_VGA,
+						    &hpd);
 		} else if (rdev->flags & RADEON_IS_MOBILITY) {
 			/* LVDS */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK);
+			ddc_i2c = combios_setup_i2c_bus(rdev, 0);
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_LCD1_SUPPORT,
@@ -1191,10 +1375,12 @@
 						    ATOM_DEVICE_LCD1_SUPPORT,
 						    DRM_MODE_CONNECTOR_LVDS,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_LVDS);
+						    CONNECTOR_OBJECT_ID_LVDS,
+						    &hpd);
 
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1204,10 +1390,12 @@
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_VGA);
+						    CONNECTOR_OBJECT_ID_VGA,
+						    &hpd);
 		} else {
 			/* DVI-I - tv dac, int tmds */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+			hpd.hpd = RADEON_HPD_1;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_DFP1_SUPPORT,
@@ -1223,10 +1411,12 @@
 						    ATOM_DEVICE_CRT2_SUPPORT,
 						    DRM_MODE_CONNECTOR_DVII,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
+						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+						    &hpd);
 
 			/* VGA - primary dac */
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_CRT1_SUPPORT,
@@ -1236,11 +1426,14 @@
 						    ATOM_DEVICE_CRT1_SUPPORT,
 						    DRM_MODE_CONNECTOR_VGA,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_VGA);
+						    CONNECTOR_OBJECT_ID_VGA,
+						    &hpd);
 		}
 
 		if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) {
 			/* TV - tv dac */
+			ddc_i2c.valid = false;
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_encoder(dev,
 						  radeon_get_encoder_id(dev,
 									ATOM_DEVICE_TV1_SUPPORT,
@@ -1250,14 +1443,16 @@
 						    ATOM_DEVICE_TV1_SUPPORT,
 						    DRM_MODE_CONNECTOR_SVIDEO,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_SVIDEO);
+						    CONNECTOR_OBJECT_ID_SVIDEO,
+						    &hpd);
 		}
 		break;
 	case CT_IBOOK:
 		DRM_INFO("Connector Table: %d (ibook)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1265,9 +1460,11 @@
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_LVDS);
+					    CONNECTOR_OBJECT_ID_LVDS,
+					    &hpd);
 		/* VGA - TV DAC */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1275,8 +1472,11 @@
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_VGA);
+					    CONNECTOR_OBJECT_ID_VGA,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1285,13 +1485,15 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_POWERBOOK_EXTERNAL:
 		DRM_INFO("Connector Table: %d (powerbook external tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1299,9 +1501,11 @@
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_LVDS);
+					    CONNECTOR_OBJECT_ID_LVDS,
+					    &hpd);
 		/* DVI-I - primary dac, ext tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+		hpd.hpd = RADEON_HPD_2; /* ??? */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP2_SUPPORT,
@@ -1317,8 +1521,11 @@
 					    ATOM_DEVICE_DFP2_SUPPORT |
 					    ATOM_DEVICE_CRT1_SUPPORT,
 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I);
+					    CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1327,13 +1534,15 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_POWERBOOK_INTERNAL:
 		DRM_INFO("Connector Table: %d (powerbook internal tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1341,9 +1550,11 @@
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_LVDS);
+					    CONNECTOR_OBJECT_ID_LVDS,
+					    &hpd);
 		/* DVI-I - primary dac, int tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+		hpd.hpd = RADEON_HPD_1; /* ??? */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1358,8 +1569,11 @@
 					    ATOM_DEVICE_DFP1_SUPPORT |
 					    ATOM_DEVICE_CRT1_SUPPORT,
 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1368,13 +1582,15 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_POWERBOOK_VGA:
 		DRM_INFO("Connector Table: %d (powerbook vga)\n",
 			 rdev->mode_info.connector_table);
 		/* LVDS */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_LCD1_SUPPORT,
@@ -1382,9 +1598,11 @@
 					  ATOM_DEVICE_LCD1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT,
 					    DRM_MODE_CONNECTOR_LVDS, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_LVDS);
+					    CONNECTOR_OBJECT_ID_LVDS,
+					    &hpd);
 		/* VGA - primary dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT1_SUPPORT,
@@ -1392,8 +1610,11 @@
 					  ATOM_DEVICE_CRT1_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT,
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_VGA);
+					    CONNECTOR_OBJECT_ID_VGA,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1402,13 +1623,15 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_MINI_EXTERNAL:
 		DRM_INFO("Connector Table: %d (mini external tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* DVI-I - tv dac, ext tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+		hpd.hpd = RADEON_HPD_2; /* ??? */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP2_SUPPORT,
@@ -1424,8 +1647,11 @@
 					    ATOM_DEVICE_DFP2_SUPPORT |
 					    ATOM_DEVICE_CRT2_SUPPORT,
 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1434,13 +1660,15 @@
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_MINI_INTERNAL:
 		DRM_INFO("Connector Table: %d (mini internal tmds)\n",
 			 rdev->mode_info.connector_table);
 		/* DVI-I - tv dac, int tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+		hpd.hpd = RADEON_HPD_1; /* ??? */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1455,8 +1683,11 @@
 					    ATOM_DEVICE_DFP1_SUPPORT |
 					    ATOM_DEVICE_CRT2_SUPPORT,
 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1465,13 +1696,15 @@
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_IMAC_G5_ISIGHT:
 		DRM_INFO("Connector Table: %d (imac g5 isight)\n",
 			 rdev->mode_info.connector_table);
 		/* DVI-D - int tmds */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
+		hpd.hpd = RADEON_HPD_1; /* ??? */
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_DFP1_SUPPORT,
@@ -1479,9 +1712,11 @@
 					  ATOM_DEVICE_DFP1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT,
 					    DRM_MODE_CONNECTOR_DVID, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
+					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
+					    &hpd);
 		/* VGA - tv dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1489,8 +1724,11 @@
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_VGA);
+					    CONNECTOR_OBJECT_ID_VGA,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1499,13 +1737,15 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	case CT_EMAC:
 		DRM_INFO("Connector Table: %d (emac)\n",
 			 rdev->mode_info.connector_table);
 		/* VGA - primary dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT1_SUPPORT,
@@ -1513,9 +1753,11 @@
 					  ATOM_DEVICE_CRT1_SUPPORT);
 		radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT,
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_VGA);
+					    CONNECTOR_OBJECT_ID_VGA,
+					    &hpd);
 		/* VGA - tv dac */
-		ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+		ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_CRT2_SUPPORT,
@@ -1523,8 +1765,11 @@
 					  ATOM_DEVICE_CRT2_SUPPORT);
 		radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT,
 					    DRM_MODE_CONNECTOR_VGA, &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_VGA);
+					    CONNECTOR_OBJECT_ID_VGA,
+					    &hpd);
 		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
 		radeon_add_legacy_encoder(dev,
 					  radeon_get_encoder_id(dev,
 								ATOM_DEVICE_TV1_SUPPORT,
@@ -1533,7 +1778,8 @@
 		radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT,
 					    DRM_MODE_CONNECTOR_SVIDEO,
 					    &ddc_i2c,
-					    CONNECTOR_OBJECT_ID_SVIDEO);
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	default:
 		DRM_INFO("Connector table: %d (invalid)\n",
@@ -1550,7 +1796,8 @@
 				       int bios_index,
 				       enum radeon_combios_connector
 				       *legacy_connector,
-				       struct radeon_i2c_bus_rec *ddc_i2c)
+				       struct radeon_i2c_bus_rec *ddc_i2c,
+				       struct radeon_hpd *hpd)
 {
 	struct radeon_device *rdev = dev->dev_private;
 
@@ -1558,29 +1805,26 @@
 	if ((rdev->family == CHIP_RS400 ||
 	     rdev->family == CHIP_RS480) &&
 	    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
-		*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
+		*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 	else if ((rdev->family == CHIP_RS400 ||
 		  rdev->family == CHIP_RS480) &&
 		 ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) {
-		ddc_i2c->valid = true;
+		*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIOPAD_MASK);
 		ddc_i2c->mask_clk_mask = (0x20 << 8);
 		ddc_i2c->mask_data_mask = 0x80;
 		ddc_i2c->a_clk_mask = (0x20 << 8);
 		ddc_i2c->a_data_mask = 0x80;
-		ddc_i2c->put_clk_mask = (0x20 << 8);
-		ddc_i2c->put_data_mask = 0x80;
-		ddc_i2c->get_clk_mask = (0x20 << 8);
-		ddc_i2c->get_data_mask = 0x80;
-		ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK;
-		ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK;
-		ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A;
-		ddc_i2c->a_data_reg = RADEON_GPIOPAD_A;
-		ddc_i2c->put_clk_reg = RADEON_GPIOPAD_EN;
-		ddc_i2c->put_data_reg = RADEON_GPIOPAD_EN;
-		ddc_i2c->get_clk_reg = RADEON_LCD_GPIO_Y_REG;
-		ddc_i2c->get_data_reg = RADEON_LCD_GPIO_Y_REG;
+		ddc_i2c->en_clk_mask = (0x20 << 8);
+		ddc_i2c->en_data_mask = 0x80;
+		ddc_i2c->y_clk_mask = (0x20 << 8);
+		ddc_i2c->y_data_mask = 0x80;
 	}
 
+	/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
+	if ((rdev->family >= CHIP_R300) &&
+	    ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
+		*ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+
 	/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
 	   one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
 	if (dev->pdev->device == 0x515e &&
@@ -1624,6 +1868,12 @@
 	    dev->pdev->subsystem_device == 0x280a)
 		return false;
 
+	/* MSI S270 has non-existent TV port */
+	if (dev->pdev->device == 0x5955 &&
+	    dev->pdev->subsystem_vendor == 0x1462 &&
+	    dev->pdev->subsystem_device == 0x0131)
+		return false;
+
 	return true;
 }
 
@@ -1671,6 +1921,7 @@
 	enum radeon_combios_connector connector;
 	int i = 0;
 	struct radeon_i2c_bus_rec ddc_i2c;
+	struct radeon_hpd hpd;
 
 	if (rdev->bios == NULL)
 		return false;
@@ -1691,26 +1942,40 @@
 			switch (ddc_type) {
 			case DDC_MONID:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_MONID);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_MONID);
 				break;
 			case DDC_DVI:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
 				break;
 			case DDC_VGA:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
 				break;
 			case DDC_CRT2:
 				ddc_i2c =
-				    combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
+					combios_setup_i2c_bus(rdev, RADEON_GPIO_CRT2_DDC);
 				break;
 			default:
 				break;
 			}
 
+			switch (connector) {
+			case CONNECTOR_PROPRIETARY_LEGACY:
+			case CONNECTOR_DVI_I_LEGACY:
+			case CONNECTOR_DVI_D_LEGACY:
+				if ((tmp >> 4) & 0x1)
+					hpd.hpd = RADEON_HPD_2;
+				else
+					hpd.hpd = RADEON_HPD_1;
+				break;
+			default:
+				hpd.hpd = RADEON_HPD_NONE;
+				break;
+			}
+
 			if (!radeon_apply_legacy_quirks(dev, i, &connector,
-						       &ddc_i2c))
+							&ddc_i2c, &hpd))
 				continue;
 
 			switch (connector) {
@@ -1727,7 +1992,8 @@
 							    legacy_connector_convert
 							    [connector],
 							    &ddc_i2c,
-							    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D);
+							    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D,
+							    &hpd);
 				break;
 			case CONNECTOR_CRT_LEGACY:
 				if (tmp & 0x1) {
@@ -1753,7 +2019,8 @@
 							    legacy_connector_convert
 							    [connector],
 							    &ddc_i2c,
-							    CONNECTOR_OBJECT_ID_VGA);
+							    CONNECTOR_OBJECT_ID_VGA,
+							    &hpd);
 				break;
 			case CONNECTOR_DVI_I_LEGACY:
 				devices = 0;
@@ -1799,7 +2066,8 @@
 							    legacy_connector_convert
 							    [connector],
 							    &ddc_i2c,
-							    connector_object_id);
+							    connector_object_id,
+							    &hpd);
 				break;
 			case CONNECTOR_DVI_D_LEGACY:
 				if ((tmp >> 4) & 0x1) {
@@ -1817,7 +2085,8 @@
 							    legacy_connector_convert
 							    [connector],
 							    &ddc_i2c,
-							    connector_object_id);
+							    connector_object_id,
+							    &hpd);
 				break;
 			case CONNECTOR_CTV_LEGACY:
 			case CONNECTOR_STV_LEGACY:
@@ -1832,7 +2101,8 @@
 							    legacy_connector_convert
 							    [connector],
 							    &ddc_i2c,
-							    CONNECTOR_OBJECT_ID_SVIDEO);
+							    CONNECTOR_OBJECT_ID_SVIDEO,
+							    &hpd);
 				break;
 			default:
 				DRM_ERROR("Unknown connector type: %d\n",
@@ -1858,14 +2128,16 @@
 									0),
 						  ATOM_DEVICE_DFP1_SUPPORT);
 
-			ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
+			ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_DVI_DDC);
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_connector(dev,
 						    0,
 						    ATOM_DEVICE_CRT1_SUPPORT |
 						    ATOM_DEVICE_DFP1_SUPPORT,
 						    DRM_MODE_CONNECTOR_DVII,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I);
+						    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
+						    &hpd);
 		} else {
 			uint16_t crt_info =
 				combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
@@ -1876,13 +2148,15 @@
 										ATOM_DEVICE_CRT1_SUPPORT,
 										1),
 							  ATOM_DEVICE_CRT1_SUPPORT);
-				ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
+				ddc_i2c = combios_setup_i2c_bus(rdev, RADEON_GPIO_VGA_DDC);
+				hpd.hpd = RADEON_HPD_NONE;
 				radeon_add_legacy_connector(dev,
 							    0,
 							    ATOM_DEVICE_CRT1_SUPPORT,
 							    DRM_MODE_CONNECTOR_VGA,
 							    &ddc_i2c,
-							    CONNECTOR_OBJECT_ID_VGA);
+							    CONNECTOR_OBJECT_ID_VGA,
+							    &hpd);
 			} else {
 				DRM_DEBUG("No connector info found\n");
 				return false;
@@ -1910,27 +2184,27 @@
 				case DDC_MONID:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_MONID);
+						(rdev, RADEON_GPIO_MONID);
 					break;
 				case DDC_DVI:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_DVI_DDC);
+						(rdev, RADEON_GPIO_DVI_DDC);
 					break;
 				case DDC_VGA:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_VGA_DDC);
+						(rdev, RADEON_GPIO_VGA_DDC);
 					break;
 				case DDC_CRT2:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_GPIO_CRT2_DDC);
+						(rdev, RADEON_GPIO_CRT2_DDC);
 					break;
 				case DDC_LCD:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_LCD_GPIO_MASK);
+						(rdev, RADEON_GPIOPAD_MASK);
 					ddc_i2c.mask_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.mask_data_mask =
@@ -1939,19 +2213,19 @@
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.a_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
-					ddc_i2c.put_clk_mask =
+					ddc_i2c.en_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
-					ddc_i2c.put_data_mask =
+					ddc_i2c.en_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
-					ddc_i2c.get_clk_mask =
+					ddc_i2c.y_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
-					ddc_i2c.get_data_mask =
+					ddc_i2c.y_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
 					break;
 				case DDC_GPIO:
 					ddc_i2c =
 					    combios_setup_i2c_bus
-					    (RADEON_MDGPIO_EN_REG);
+						(rdev, RADEON_MDGPIO_MASK);
 					ddc_i2c.mask_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.mask_data_mask =
@@ -1960,13 +2234,13 @@
 					    RBIOS32(lcd_ddc_info + 3);
 					ddc_i2c.a_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
-					ddc_i2c.put_clk_mask =
+					ddc_i2c.en_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
-					ddc_i2c.put_data_mask =
+					ddc_i2c.en_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
-					ddc_i2c.get_clk_mask =
+					ddc_i2c.y_clk_mask =
 					    RBIOS32(lcd_ddc_info + 3);
-					ddc_i2c.get_data_mask =
+					ddc_i2c.y_data_mask =
 					    RBIOS32(lcd_ddc_info + 7);
 					break;
 				default:
@@ -1977,12 +2251,14 @@
 			} else
 				ddc_i2c.valid = false;
 
+			hpd.hpd = RADEON_HPD_NONE;
 			radeon_add_legacy_connector(dev,
 						    5,
 						    ATOM_DEVICE_LCD1_SUPPORT,
 						    DRM_MODE_CONNECTOR_LVDS,
 						    &ddc_i2c,
-						    CONNECTOR_OBJECT_ID_LVDS);
+						    CONNECTOR_OBJECT_ID_LVDS,
+						    &hpd);
 		}
 	}
 
@@ -1993,6 +2269,7 @@
 		if (tv_info) {
 			if (RBIOS8(tv_info + 6) == 'T') {
 				if (radeon_apply_legacy_tv_quirks(dev)) {
+					hpd.hpd = RADEON_HPD_NONE;
 					radeon_add_legacy_encoder(dev,
 								  radeon_get_encoder_id
 								  (dev,
@@ -2003,7 +2280,8 @@
 								    ATOM_DEVICE_TV1_SUPPORT,
 								    DRM_MODE_CONNECTOR_SVIDEO,
 								    &ddc_i2c,
-								    CONNECTOR_OBJECT_ID_SVIDEO);
+								    CONNECTOR_OBJECT_ID_SVIDEO,
+								    &hpd);
 				}
 			}
 		}
@@ -2014,6 +2292,193 @@
 	return true;
 }
 
+void radeon_external_tmds_setup(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
+
+	if (!tmds)
+		return;
+
+	switch (tmds->dvo_chip) {
+	case DVO_SIL164:
+		/* sil 164 */
+		radeon_i2c_do_lock(tmds->i2c_bus, 1);
+		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+				       tmds->slave_addr,
+				       0x08, 0x30);
+		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+				       tmds->slave_addr,
+				       0x09, 0x00);
+		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+				       tmds->slave_addr,
+				       0x0a, 0x90);
+		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+				       tmds->slave_addr,
+				       0x0c, 0x89);
+		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+				       tmds->slave_addr,
+				       0x08, 0x3b);
+		radeon_i2c_do_lock(tmds->i2c_bus, 0);
+		break;
+	case DVO_SIL1178:
+		/* sil 1178 - untested */
+		/*
+		 * 0x0f, 0x44
+		 * 0x0f, 0x4c
+		 * 0x0e, 0x01
+		 * 0x0a, 0x80
+		 * 0x09, 0x30
+		 * 0x0c, 0xc9
+		 * 0x0d, 0x70
+		 * 0x08, 0x32
+		 * 0x08, 0x33
+		 */
+		break;
+	default:
+		break;
+	}
+
+}
+
+bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint16_t offset;
+	uint8_t blocks, slave_addr, rev;
+	uint32_t index, id;
+	uint32_t reg, val, and_mask, or_mask;
+	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
+
+	if (rdev->bios == NULL)
+		return false;
+
+	if (!tmds)
+		return false;
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_ON_TABLE);
+		rev = RBIOS8(offset);
+		if (offset) {
+			rev = RBIOS8(offset);
+			if (rev > 1) {
+				blocks = RBIOS8(offset + 3);
+				index = offset + 4;
+				while (blocks > 0) {
+					id = RBIOS16(index);
+					index += 2;
+					switch (id >> 13) {
+					case 0:
+						reg = (id & 0x1fff) * 4;
+						val = RBIOS32(index);
+						index += 4;
+						WREG32(reg, val);
+						break;
+					case 2:
+						reg = (id & 0x1fff) * 4;
+						and_mask = RBIOS32(index);
+						index += 4;
+						or_mask = RBIOS32(index);
+						index += 4;
+						val = RREG32(reg);
+						val = (val & and_mask) | or_mask;
+						WREG32(reg, val);
+						break;
+					case 3:
+						val = RBIOS16(index);
+						index += 2;
+						udelay(val);
+						break;
+					case 4:
+						val = RBIOS16(index);
+						index += 2;
+						udelay(val * 1000);
+						break;
+					case 6:
+						slave_addr = id & 0xff;
+						slave_addr >>= 1; /* 7 bit addressing */
+						index++;
+						reg = RBIOS8(index);
+						index++;
+						val = RBIOS8(index);
+						index++;
+						radeon_i2c_do_lock(tmds->i2c_bus, 1);
+						radeon_i2c_sw_put_byte(tmds->i2c_bus,
+								       slave_addr,
+								       reg, val);
+						radeon_i2c_do_lock(tmds->i2c_bus, 0);
+						break;
+					default:
+						DRM_ERROR("Unknown id %d\n", id >> 13);
+						break;
+					}
+					blocks--;
+				}
+				return true;
+			}
+		}
+	} else {
+		offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
+		if (offset) {
+			index = offset + 10;
+			id = RBIOS16(index);
+			while (id != 0xffff) {
+				index += 2;
+				switch (id >> 13) {
+				case 0:
+					reg = (id & 0x1fff) * 4;
+					val = RBIOS32(index);
+					WREG32(reg, val);
+					break;
+				case 2:
+					reg = (id & 0x1fff) * 4;
+					and_mask = RBIOS32(index);
+					index += 4;
+					or_mask = RBIOS32(index);
+					index += 4;
+					val = RREG32(reg);
+					val = (val & and_mask) | or_mask;
+					WREG32(reg, val);
+					break;
+				case 4:
+					val = RBIOS16(index);
+					index += 2;
+					udelay(val);
+					break;
+				case 5:
+					reg = id & 0x1fff;
+					and_mask = RBIOS32(index);
+					index += 4;
+					or_mask = RBIOS32(index);
+					index += 4;
+					val = RREG32_PLL(reg);
+					val = (val & and_mask) | or_mask;
+					WREG32_PLL(reg, val);
+					break;
+				case 6:
+					reg = id & 0x1fff;
+					val = RBIOS8(index);
+					index += 1;
+					radeon_i2c_do_lock(tmds->i2c_bus, 1);
+					radeon_i2c_sw_put_byte(tmds->i2c_bus,
+							       tmds->slave_addr,
+							       reg, val);
+					radeon_i2c_do_lock(tmds->i2c_bus, 0);
+					break;
+				default:
+					DRM_ERROR("Unknown id %d\n", id >> 13);
+					break;
+				}
+				id = RBIOS16(index);
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
 static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset)
 {
 	struct radeon_device *rdev = dev->dev_private;
@@ -2384,6 +2849,22 @@
 		combios_write_ram_size(dev);
 	}
 
+	/* quirk for rs4xx HP nx6125 laptop to make it resume
+	 * - it hangs on resume inside the dynclk 1 table.
+	 */
+	if (rdev->family == CHIP_RS480 &&
+	    rdev->pdev->subsystem_vendor == 0x103c &&
+	    rdev->pdev->subsystem_device == 0x308b)
+		return;
+
+	/* quirk for rs4xx HP dv5000 laptop to make it resume
+	 * - it hangs on resume inside the dynclk 1 table.
+	 */
+	if (rdev->family == CHIP_RS480 &&
+	    rdev->pdev->subsystem_vendor == 0x103c &&
+	    rdev->pdev->subsystem_device == 0x30a4)
+		return;
+
 	/* DYN CLK 1 */
 	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
 	if (table)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_gart.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_gart.c
@@ -78,11 +78,9 @@
 	int r;
 
 	if (rdev->gart.table.vram.robj == NULL) {
-		r = radeon_object_create(rdev, NULL,
-					 rdev->gart.table_size,
-					 true,
-					 RADEON_GEM_DOMAIN_VRAM,
-					 false, &rdev->gart.table.vram.robj);
+		r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
+					true, RADEON_GEM_DOMAIN_VRAM,
+					&rdev->gart.table.vram.robj);
 		if (r) {
 			return r;
 		}
@@ -95,32 +93,38 @@
 	uint64_t gpu_addr;
 	int r;
 
-	r = radeon_object_pin(rdev->gart.table.vram.robj,
-			      RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
-	if (r) {
-		radeon_object_unref(&rdev->gart.table.vram.robj);
+	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	if (unlikely(r != 0))
 		return r;
-	}
-	r = radeon_object_kmap(rdev->gart.table.vram.robj,
-			       (void **)&rdev->gart.table.vram.ptr);
+	r = radeon_bo_pin(rdev->gart.table.vram.robj,
+				RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
 	if (r) {
-		radeon_object_unpin(rdev->gart.table.vram.robj);
-		radeon_object_unref(&rdev->gart.table.vram.robj);
-		DRM_ERROR("radeon: failed to map gart vram table.\n");
+		radeon_bo_unreserve(rdev->gart.table.vram.robj);
 		return r;
 	}
+	r = radeon_bo_kmap(rdev->gart.table.vram.robj,
+				(void **)&rdev->gart.table.vram.ptr);
+	if (r)
+		radeon_bo_unpin(rdev->gart.table.vram.robj);
+	radeon_bo_unreserve(rdev->gart.table.vram.robj);
 	rdev->gart.table_addr = gpu_addr;
-	return 0;
+	return r;
 }
 
 void radeon_gart_table_vram_free(struct radeon_device *rdev)
 {
+	int r;
+
 	if (rdev->gart.table.vram.robj == NULL) {
 		return;
 	}
-	radeon_object_kunmap(rdev->gart.table.vram.robj);
-	radeon_object_unpin(rdev->gart.table.vram.robj);
-	radeon_object_unref(&rdev->gart.table.vram.robj);
+	r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+	if (likely(r == 0)) {
+		radeon_bo_kunmap(rdev->gart.table.vram.robj);
+		radeon_bo_unpin(rdev->gart.table.vram.robj);
+		radeon_bo_unreserve(rdev->gart.table.vram.robj);
+	}
+	radeon_bo_unref(&rdev->gart.table.vram.robj);
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_object.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_object.c
@@ -34,100 +34,62 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 
-struct radeon_object {
-	struct ttm_buffer_object	tobj;
-	struct list_head		list;
-	struct radeon_device		*rdev;
-	struct drm_gem_object		*gobj;
-	struct ttm_bo_kmap_obj		kmap;
-	unsigned			pin_count;
-	uint64_t			gpu_addr;
-	void				*kptr;
-	bool				is_iomem;
-	uint32_t			tiling_flags;
-	uint32_t			pitch;
-	int				surface_reg;
-};
 
 int radeon_ttm_init(struct radeon_device *rdev);
 void radeon_ttm_fini(struct radeon_device *rdev);
+static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
 
 /*
  * To exclude mutual BO access we rely on bo_reserve exclusion, as all
  * function are calling it.
  */
 
-static int radeon_object_reserve(struct radeon_object *robj, bool interruptible)
+static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
 {
-	return ttm_bo_reserve(&robj->tobj, interruptible, false, false, 0);
-}
+	struct radeon_bo *bo;
 
-static void radeon_object_unreserve(struct radeon_object *robj)
-{
-	ttm_bo_unreserve(&robj->tobj);
+	bo = container_of(tbo, struct radeon_bo, tbo);
+	mutex_lock(&bo->rdev->gem.mutex);
+	list_del_init(&bo->list);
+	mutex_unlock(&bo->rdev->gem.mutex);
+	radeon_bo_clear_surface_reg(bo);
+	kfree(bo);
 }
 
-static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
+bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
 {
-	struct radeon_object *robj;
-
-	robj = container_of(tobj, struct radeon_object, tobj);
-	list_del_init(&robj->list);
-	radeon_object_clear_surface_reg(robj);
-	kfree(robj);
+	if (bo->destroy == &radeon_ttm_bo_destroy)
+		return true;
+	return false;
 }
 
-static inline void radeon_object_gpu_addr(struct radeon_object *robj)
+void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
 {
-	/* Default gpu address */
-	robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
-	if (robj->tobj.mem.mm_node == NULL) {
-		return;
-	}
-	robj->gpu_addr = ((u64)robj->tobj.mem.mm_node->start) << PAGE_SHIFT;
-	switch (robj->tobj.mem.mem_type) {
-	case TTM_PL_VRAM:
-		robj->gpu_addr += (u64)robj->rdev->mc.vram_location;
-		break;
-	case TTM_PL_TT:
-		robj->gpu_addr += (u64)robj->rdev->mc.gtt_location;
-		break;
-	default:
-		DRM_ERROR("Unknown placement %d\n", robj->tobj.mem.mem_type);
-		robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
-		return;
-	}
-}
+	u32 c = 0;
 
-static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
-{
-	uint32_t flags = 0;
-	if (domain & RADEON_GEM_DOMAIN_VRAM) {
-		flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
-	}
-	if (domain & RADEON_GEM_DOMAIN_GTT) {
-		flags |= TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
-	}
-	if (domain & RADEON_GEM_DOMAIN_CPU) {
-		flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
-	}
-	if (!flags) {
-		flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
-	}
-	return flags;
+	rbo->placement.fpfn = 0;
+	rbo->placement.lpfn = 0;
+	rbo->placement.placement = rbo->placements;
+	rbo->placement.busy_placement = rbo->placements;
+	if (domain & RADEON_GEM_DOMAIN_VRAM)
+		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
+					TTM_PL_FLAG_VRAM;
+	if (domain & RADEON_GEM_DOMAIN_GTT)
+		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
+	if (domain & RADEON_GEM_DOMAIN_CPU)
+		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+	if (!c)
+		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+	rbo->placement.num_placement = c;
+	rbo->placement.num_busy_placement = c;
 }
 
-int radeon_object_create(struct radeon_device *rdev,
-			 struct drm_gem_object *gobj,
-			 unsigned long size,
-			 bool kernel,
-			 uint32_t domain,
-			 bool interruptible,
-			 struct radeon_object **robj_ptr)
+int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
+			unsigned long size, bool kernel, u32 domain,
+			struct radeon_bo **bo_ptr)
 {
-	struct radeon_object *robj;
+	struct radeon_bo *bo;
 	enum ttm_bo_type type;
-	uint32_t flags;
 	int r;
 
 	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
@@ -138,238 +100,167 @@
 	} else {
 		type = ttm_bo_type_device;
 	}
-	*robj_ptr = NULL;
-	robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL);
-	if (robj == NULL) {
+	*bo_ptr = NULL;
+
+retry:
+	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
+	if (bo == NULL)
 		return -ENOMEM;
-	}
-	robj->rdev = rdev;
-	robj->gobj = gobj;
-	robj->surface_reg = -1;
-	INIT_LIST_HEAD(&robj->list);
-
-	flags = radeon_object_flags_from_domain(domain);
-	r = ttm_buffer_object_init(&rdev->mman.bdev, &robj->tobj, size, type, flags,
-				   0, 0, false, NULL, size,
-				   &radeon_ttm_object_object_destroy);
+	bo->rdev = rdev;
+	bo->gobj = gobj;
+	bo->surface_reg = -1;
+	INIT_LIST_HEAD(&bo->list);
+	radeon_ttm_placement_from_domain(bo, domain);
+	/* Kernel allocation are uninterruptible */
+	r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
+			&bo->placement, 0, 0, !kernel, NULL, size,
+			&radeon_ttm_bo_destroy);
 	if (unlikely(r != 0)) {
-		/* ttm call radeon_ttm_object_object_destroy if error happen */
-		DRM_ERROR("Failed to allocate TTM object (%ld, 0x%08X, %u)\n",
-			  size, flags, 0);
+		if (r != -ERESTARTSYS) {
+			if (domain == RADEON_GEM_DOMAIN_VRAM) {
+				domain |= RADEON_GEM_DOMAIN_GTT;
+				goto retry;
+			}
+			dev_err(rdev->dev,
+				"object_init failed for (%lu, 0x%08X)\n",
+				size, domain);
+		}
 		return r;
 	}
-	*robj_ptr = robj;
+	*bo_ptr = bo;
 	if (gobj) {
-		list_add_tail(&robj->list, &rdev->gem.objects);
+		mutex_lock(&bo->rdev->gem.mutex);
+		list_add_tail(&bo->list, &rdev->gem.objects);
+		mutex_unlock(&bo->rdev->gem.mutex);
 	}
 	return 0;
 }
 
-int radeon_object_kmap(struct radeon_object *robj, void **ptr)
+int radeon_bo_kmap(struct radeon_bo *bo, void **ptr)
 {
+	bool is_iomem;
 	int r;
 
-	spin_lock(&robj->tobj.lock);
-	if (robj->kptr) {
+	if (bo->kptr) {
 		if (ptr) {
-			*ptr = robj->kptr;
+			*ptr = bo->kptr;
 		}
-		spin_unlock(&robj->tobj.lock);
 		return 0;
 	}
-	spin_unlock(&robj->tobj.lock);
-	r = ttm_bo_kmap(&robj->tobj, 0, robj->tobj.num_pages, &robj->kmap);
+	r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
 	if (r) {
 		return r;
 	}
-	spin_lock(&robj->tobj.lock);
-	robj->kptr = ttm_kmap_obj_virtual(&robj->kmap, &robj->is_iomem);
-	spin_unlock(&robj->tobj.lock);
+	bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
 	if (ptr) {
-		*ptr = robj->kptr;
+		*ptr = bo->kptr;
 	}
-	radeon_object_check_tiling(robj, 0, 0);
+	radeon_bo_check_tiling(bo, 0, 0);
 	return 0;
 }
 
-void radeon_object_kunmap(struct radeon_object *robj)
+void radeon_bo_kunmap(struct radeon_bo *bo)
 {
-	spin_lock(&robj->tobj.lock);
-	if (robj->kptr == NULL) {
-		spin_unlock(&robj->tobj.lock);
+	if (bo->kptr == NULL)
 		return;
-	}
-	robj->kptr = NULL;
-	spin_unlock(&robj->tobj.lock);
-	radeon_object_check_tiling(robj, 0, 0);
-	ttm_bo_kunmap(&robj->kmap);
+	bo->kptr = NULL;
+	radeon_bo_check_tiling(bo, 0, 0);
+	ttm_bo_kunmap(&bo->kmap);
 }
 
-void radeon_object_unref(struct radeon_object **robj)
+void radeon_bo_unref(struct radeon_bo **bo)
 {
-	struct ttm_buffer_object *tobj;
+	struct ttm_buffer_object *tbo;
 
-	if ((*robj) == NULL) {
+	if ((*bo) == NULL)
 		return;
-	}
-	tobj = &((*robj)->tobj);
-	ttm_bo_unref(&tobj);
-	if (tobj == NULL) {
-		*robj = NULL;
-	}
+	tbo = &((*bo)->tbo);
+	ttm_bo_unref(&tbo);
+	if (tbo == NULL)
+		*bo = NULL;
 }
 
-int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset)
+int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
 {
-	*offset = robj->tobj.addr_space_offset;
-	return 0;
-}
+	int r, i;
 
-int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
-		      uint64_t *gpu_addr)
-{
-	uint32_t flags;
-	uint32_t tmp;
-	int r;
-
-	flags = radeon_object_flags_from_domain(domain);
-	spin_lock(&robj->tobj.lock);
-	if (robj->pin_count) {
-		robj->pin_count++;
-		if (gpu_addr != NULL) {
-			*gpu_addr = robj->gpu_addr;
-		}
-		spin_unlock(&robj->tobj.lock);
+	radeon_ttm_placement_from_domain(bo, domain);
+	if (bo->pin_count) {
+		bo->pin_count++;
+		if (gpu_addr)
+			*gpu_addr = radeon_bo_gpu_offset(bo);
 		return 0;
 	}
-	spin_unlock(&robj->tobj.lock);
-	r = radeon_object_reserve(robj, false);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
-		return r;
+	radeon_ttm_placement_from_domain(bo, domain);
+	for (i = 0; i < bo->placement.num_placement; i++)
+		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+	if (likely(r == 0)) {
+		bo->pin_count = 1;
+		if (gpu_addr != NULL)
+			*gpu_addr = radeon_bo_gpu_offset(bo);
 	}
-	tmp = robj->tobj.mem.placement;
-	ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
-	robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
-	r = ttm_buffer_object_validate(&robj->tobj,
-				       robj->tobj.proposed_placement,
-				       false, false);
-	radeon_object_gpu_addr(robj);
-	if (gpu_addr != NULL) {
-		*gpu_addr = robj->gpu_addr;
-	}
-	robj->pin_count = 1;
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to pin object.\n");
-	}
-	radeon_object_unreserve(robj);
+	if (unlikely(r != 0))
+		dev_err(bo->rdev->dev, "%p pin failed\n", bo);
 	return r;
 }
 
-void radeon_object_unpin(struct radeon_object *robj)
+int radeon_bo_unpin(struct radeon_bo *bo)
 {
-	uint32_t flags;
-	int r;
-
-	spin_lock(&robj->tobj.lock);
-	if (!robj->pin_count) {
-		spin_unlock(&robj->tobj.lock);
-		printk(KERN_WARNING "Unpin not necessary for %p !\n", robj);
-		return;
-	}
-	robj->pin_count--;
-	if (robj->pin_count) {
-		spin_unlock(&robj->tobj.lock);
-		return;
-	}
-	spin_unlock(&robj->tobj.lock);
-	r = radeon_object_reserve(robj, false);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
-		return;
-	}
-	flags = robj->tobj.mem.placement;
-	robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
-	r = ttm_buffer_object_validate(&robj->tobj,
-				       robj->tobj.proposed_placement,
-				       false, false);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to unpin buffer.\n");
-	}
-	radeon_object_unreserve(robj);
-}
+	int r, i;
 
-int radeon_object_wait(struct radeon_object *robj)
-{
-	int r = 0;
-
-	/* FIXME: should use block reservation instead */
-	r = radeon_object_reserve(robj, true);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to reserve object for waiting.\n");
-		return r;
-	}
-	spin_lock(&robj->tobj.lock);
-	if (robj->tobj.sync_obj) {
-		r = ttm_bo_wait(&robj->tobj, true, true, false);
-	}
-	spin_unlock(&robj->tobj.lock);
-	radeon_object_unreserve(robj);
-	return r;
-}
-
-int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement)
-{
-	int r = 0;
-
-	r = radeon_object_reserve(robj, true);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("radeon: failed to reserve object for waiting.\n");
-		return r;
-	}
-	spin_lock(&robj->tobj.lock);
-	*cur_placement = robj->tobj.mem.mem_type;
-	if (robj->tobj.sync_obj) {
-		r = ttm_bo_wait(&robj->tobj, true, true, true);
+	if (!bo->pin_count) {
+		dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo);
+		return 0;
 	}
-	spin_unlock(&robj->tobj.lock);
-	radeon_object_unreserve(robj);
+	bo->pin_count--;
+	if (bo->pin_count)
+		return 0;
+	for (i = 0; i < bo->placement.num_placement; i++)
+		bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
+	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+	if (unlikely(r != 0))
+		dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
 	return r;
 }
 
-int radeon_object_evict_vram(struct radeon_device *rdev)
+int radeon_bo_evict_vram(struct radeon_device *rdev)
 {
-	if (rdev->flags & RADEON_IS_IGP) {
-		/* Useless to evict on IGP chips */
-		return 0;
+	/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
+	if (0 && (rdev->flags & RADEON_IS_IGP)) {
+		if (rdev->mc.igp_sideport_enabled == false)
+			/* Useless to evict on IGP chips */
+			return 0;
 	}
 	return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
 }
 
-void radeon_object_force_delete(struct radeon_device *rdev)
+void radeon_bo_force_delete(struct radeon_device *rdev)
 {
-	struct radeon_object *robj, *n;
+	struct radeon_bo *bo, *n;
 	struct drm_gem_object *gobj;
 
 	if (list_empty(&rdev->gem.objects)) {
 		return;
 	}
-	DRM_ERROR("Userspace still has active objects !\n");
-	list_for_each_entry_safe(robj, n, &rdev->gem.objects, list) {
+	dev_err(rdev->dev, "Userspace still has active objects !\n");
+	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
 		mutex_lock(&rdev->ddev->struct_mutex);
-		gobj = robj->gobj;
-		DRM_ERROR("Force free for (%p,%p,%lu,%lu)\n",
-			  gobj, robj, (unsigned long)gobj->size,
-			  *((unsigned long *)&gobj->refcount));
-		list_del_init(&robj->list);
-		radeon_object_unref(&robj);
+		gobj = bo->gobj;
+		dev_err(rdev->dev, "%p %p %lu %lu force free\n",
+			gobj, bo, (unsigned long)gobj->size,
+			*((unsigned long *)&gobj->refcount));
+		mutex_lock(&bo->rdev->gem.mutex);
+		list_del_init(&bo->list);
+		mutex_unlock(&bo->rdev->gem.mutex);
+		radeon_bo_unref(&bo);
 		gobj->driver_private = NULL;
 		drm_gem_object_unreference(gobj);
 		mutex_unlock(&rdev->ddev->struct_mutex);
 	}
 }
 
-int radeon_object_init(struct radeon_device *rdev)
+int radeon_bo_init(struct radeon_device *rdev)
 {
 	/* Add an MTRR for the VRAM */
 	rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
@@ -382,13 +273,13 @@
 	return radeon_ttm_init(rdev);
 }
 
-void radeon_object_fini(struct radeon_device *rdev)
+void radeon_bo_fini(struct radeon_device *rdev)
 {
 	radeon_ttm_fini(rdev);
 }
 
-void radeon_object_list_add_object(struct radeon_object_list *lobj,
-				   struct list_head *head)
+void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
+				struct list_head *head)
 {
 	if (lobj->wdomain) {
 		list_add(&lobj->list, head);
@@ -397,125 +288,105 @@
 	}
 }
 
-int radeon_object_list_reserve(struct list_head *head)
+int radeon_bo_list_reserve(struct list_head *head)
 {
-	struct radeon_object_list *lobj;
+	struct radeon_bo_list *lobj;
 	int r;
 
 	list_for_each_entry(lobj, head, list){
-		if (!lobj->robj->pin_count) {
-			r = radeon_object_reserve(lobj->robj, true);
-			if (unlikely(r != 0)) {
-				DRM_ERROR("radeon: failed to reserve object.\n");
-				return r;
-			}
-		} else {
-		}
+		r = radeon_bo_reserve(lobj->bo, false);
+		if (unlikely(r != 0))
+			return r;
 	}
 	return 0;
 }
 
-void radeon_object_list_unreserve(struct list_head *head)
+void radeon_bo_list_unreserve(struct list_head *head)
 {
-	struct radeon_object_list *lobj;
+	struct radeon_bo_list *lobj;
 
 	list_for_each_entry(lobj, head, list) {
-		if (!lobj->robj->pin_count) {
-			radeon_object_unreserve(lobj->robj);
-		}
+		/* only unreserve object we successfully reserved */
+		if (radeon_bo_is_reserved(lobj->bo))
+			radeon_bo_unreserve(lobj->bo);
 	}
 }
 
-int radeon_object_list_validate(struct list_head *head, void *fence)
+int radeon_bo_list_validate(struct list_head *head)
 {
-	struct radeon_object_list *lobj;
-	struct radeon_object *robj;
-	struct radeon_fence *old_fence = NULL;
+	struct radeon_bo_list *lobj;
+	struct radeon_bo *bo;
+	u32 domain;
 	int r;
 
-	r = radeon_object_list_reserve(head);
+	r = radeon_bo_list_reserve(head);
 	if (unlikely(r != 0)) {
-		radeon_object_list_unreserve(head);
 		return r;
 	}
 	list_for_each_entry(lobj, head, list) {
-		robj = lobj->robj;
-		if (!robj->pin_count) {
-			if (lobj->wdomain) {
-				robj->tobj.proposed_placement =
-					radeon_object_flags_from_domain(lobj->wdomain);
-			} else {
-				robj->tobj.proposed_placement =
-					radeon_object_flags_from_domain(lobj->rdomain);
-			}
-			r = ttm_buffer_object_validate(&robj->tobj,
-						       robj->tobj.proposed_placement,
-						       true, false);
+		bo = lobj->bo;
+		if (!bo->pin_count) {
+			domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+			
+		retry:
+			radeon_ttm_placement_from_domain(bo, domain);
+			r = ttm_bo_validate(&bo->tbo, &bo->placement,
+						true, false);
 			if (unlikely(r)) {
-				DRM_ERROR("radeon: failed to validate.\n");
+				if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+					domain |= RADEON_GEM_DOMAIN_GTT;
+					goto retry;
+				}
 				return r;
 			}
-			radeon_object_gpu_addr(robj);
-		}
-		lobj->gpu_offset = robj->gpu_addr;
-		lobj->tiling_flags = robj->tiling_flags;
-		if (fence) {
-			old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
-			robj->tobj.sync_obj = radeon_fence_ref(fence);
-			robj->tobj.sync_obj_arg = NULL;
-		}
-		if (old_fence) {
-			radeon_fence_unref(&old_fence);
 		}
+		lobj->gpu_offset = radeon_bo_gpu_offset(bo);
+		lobj->tiling_flags = bo->tiling_flags;
 	}
 	return 0;
 }
 
-void radeon_object_list_unvalidate(struct list_head *head)
+void radeon_bo_list_fence(struct list_head *head, void *fence)
 {
-	struct radeon_object_list *lobj;
+	struct radeon_bo_list *lobj;
+	struct radeon_bo *bo;
 	struct radeon_fence *old_fence = NULL;
 
 	list_for_each_entry(lobj, head, list) {
-		old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj;
-		lobj->robj->tobj.sync_obj = NULL;
+		bo = lobj->bo;
+		spin_lock(&bo->tbo.lock);
+		old_fence = (struct radeon_fence *)bo->tbo.sync_obj;
+		bo->tbo.sync_obj = radeon_fence_ref(fence);
+		bo->tbo.sync_obj_arg = NULL;
+		spin_unlock(&bo->tbo.lock);
 		if (old_fence) {
 			radeon_fence_unref(&old_fence);
 		}
 	}
-	radeon_object_list_unreserve(head);
 }
 
-void radeon_object_list_clean(struct list_head *head)
-{
-	radeon_object_list_unreserve(head);
-}
-
-int radeon_object_fbdev_mmap(struct radeon_object *robj,
+int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
 			     struct vm_area_struct *vma)
 {
-	return ttm_fbdev_mmap(vma, &robj->tobj);
+	return ttm_fbdev_mmap(vma, &bo->tbo);
 }
 
-unsigned long radeon_object_size(struct radeon_object *robj)
+int radeon_bo_get_surface_reg(struct radeon_bo *bo)
 {
-	return robj->tobj.num_pages << PAGE_SHIFT;
-}
-
-int radeon_object_get_surface_reg(struct radeon_object *robj)
-{
-	struct radeon_device *rdev = robj->rdev;
+	struct radeon_device *rdev = bo->rdev;
 	struct radeon_surface_reg *reg;
-	struct radeon_object *old_object;
+	struct radeon_bo *old_object;
 	int steal;
 	int i;
 
-	if (!robj->tiling_flags)
+	BUG_ON(!atomic_read(&bo->tbo.reserved));
+
+	if (!bo->tiling_flags)
 		return 0;
 
-	if (robj->surface_reg >= 0) {
-		reg = &rdev->surface_regs[robj->surface_reg];
-		i = robj->surface_reg;
+	if (bo->surface_reg >= 0) {
+		reg = &rdev->surface_regs[bo->surface_reg];
+		i = bo->surface_reg;
 		goto out;
 	}
 
@@ -523,10 +394,10 @@
 	for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
 
 		reg = &rdev->surface_regs[i];
-		if (!reg->robj)
+		if (!reg->bo)
 			break;
 
-		old_object = reg->robj;
+		old_object = reg->bo;
 		if (old_object->pin_count == 0)
 			steal = i;
 	}
@@ -537,91 +408,107 @@
 			return -ENOMEM;
 		/* find someone with a surface reg and nuke their BO */
 		reg = &rdev->surface_regs[steal];
-		old_object = reg->robj;
+		old_object = reg->bo;
 		/* blow away the mapping */
 		DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
-		ttm_bo_unmap_virtual(&old_object->tobj);
+		ttm_bo_unmap_virtual(&old_object->tbo);
 		old_object->surface_reg = -1;
 		i = steal;
 	}
 
-	robj->surface_reg = i;
-	reg->robj = robj;
+	bo->surface_reg = i;
+	reg->bo = bo;
 
 out:
-	radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
-			       robj->tobj.mem.mm_node->start << PAGE_SHIFT,
-			       robj->tobj.num_pages << PAGE_SHIFT);
+	radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch,
+			       bo->tbo.mem.mm_node->start << PAGE_SHIFT,
+			       bo->tbo.num_pages << PAGE_SHIFT);
 	return 0;
 }
 
-void radeon_object_clear_surface_reg(struct radeon_object *robj)
+static void radeon_bo_clear_surface_reg(struct radeon_bo *bo)
 {
-	struct radeon_device *rdev = robj->rdev;
+	struct radeon_device *rdev = bo->rdev;
 	struct radeon_surface_reg *reg;
 
-	if (robj->surface_reg == -1)
+	if (bo->surface_reg == -1)
 		return;
 
-	reg = &rdev->surface_regs[robj->surface_reg];
-	radeon_clear_surface_reg(rdev, robj->surface_reg);
+	reg = &rdev->surface_regs[bo->surface_reg];
+	radeon_clear_surface_reg(rdev, bo->surface_reg);
 
-	reg->robj = NULL;
-	robj->surface_reg = -1;
+	reg->bo = NULL;
+	bo->surface_reg = -1;
 }
 
-void radeon_object_set_tiling_flags(struct radeon_object *robj,
-				    uint32_t tiling_flags, uint32_t pitch)
+int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
+				uint32_t tiling_flags, uint32_t pitch)
 {
-	robj->tiling_flags = tiling_flags;
-	robj->pitch = pitch;
+	int r;
+
+	r = radeon_bo_reserve(bo, false);
+	if (unlikely(r != 0))
+		return r;
+	bo->tiling_flags = tiling_flags;
+	bo->pitch = pitch;
+	radeon_bo_unreserve(bo);
+	return 0;
 }
 
-void radeon_object_get_tiling_flags(struct radeon_object *robj,
-				    uint32_t *tiling_flags,
-				    uint32_t *pitch)
+void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
+				uint32_t *tiling_flags,
+				uint32_t *pitch)
 {
+	BUG_ON(!atomic_read(&bo->tbo.reserved));
 	if (tiling_flags)
-		*tiling_flags = robj->tiling_flags;
+		*tiling_flags = bo->tiling_flags;
 	if (pitch)
-		*pitch = robj->pitch;
+		*pitch = bo->pitch;
 }
 
-int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
-			       bool force_drop)
+int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
+				bool force_drop)
 {
-	if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
+	BUG_ON(!atomic_read(&bo->tbo.reserved));
+
+	if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
 		return 0;
 
 	if (force_drop) {
-		radeon_object_clear_surface_reg(robj);
+		radeon_bo_clear_surface_reg(bo);
 		return 0;
 	}
 
-	if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
+	if (bo->tbo.mem.mem_type != TTM_PL_VRAM) {
 		if (!has_moved)
 			return 0;
 
-		if (robj->surface_reg >= 0)
-			radeon_object_clear_surface_reg(robj);
+		if (bo->surface_reg >= 0)
+			radeon_bo_clear_surface_reg(bo);
 		return 0;
 	}
 
-	if ((robj->surface_reg >= 0) && !has_moved)
+	if ((bo->surface_reg >= 0) && !has_moved)
 		return 0;
 
-	return radeon_object_get_surface_reg(robj);
+	return radeon_bo_get_surface_reg(bo);
 }
 
 void radeon_bo_move_notify(struct ttm_buffer_object *bo,
-			  struct ttm_mem_reg *mem)
+			   struct ttm_mem_reg *mem)
 {
-	struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
-	radeon_object_check_tiling(robj, 0, 1);
+	struct radeon_bo *rbo;
+	if (!radeon_ttm_bo_is_radeon_bo(bo))
+		return;
+	rbo = container_of(bo, struct radeon_bo, tbo);
+	radeon_bo_check_tiling(rbo, 0, 1);
 }
 
 void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 {
-	struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
-	radeon_object_check_tiling(robj, 0, 0);
+	struct radeon_bo *rbo;
+	if (!radeon_ttm_bo_is_radeon_bo(bo))
+		return;
+	rbo = container_of(bo, struct radeon_bo, tbo);
+	radeon_bo_check_tiling(rbo, 0, 0);
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_clocks.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -44,6 +44,10 @@
 
 	ref_div =
 	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
+
+	if (ref_div == 0)
+		return 0;
+
 	sclk = fb_div / ref_div;
 
 	post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK;
@@ -52,13 +56,13 @@
 	else if (post_div == 3)
 		sclk >>= 2;
 	else if (post_div == 4)
-		sclk >>= 4;
+		sclk >>= 3;
 
 	return sclk;
 }
 
 /* 10 khz */
-static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
+uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
 {
 	struct radeon_pll *mpll = &rdev->clock.mpll;
 	uint32_t fb_div, ref_div, post_div, mclk;
@@ -70,6 +74,10 @@
 
 	ref_div =
 	    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
+
+	if (ref_div == 0)
+		return 0;
+
 	mclk = fb_div / ref_div;
 
 	post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7;
@@ -78,7 +86,7 @@
 	else if (post_div == 3)
 		mclk >>= 2;
 	else if (post_div == 4)
-		mclk >>= 4;
+		mclk >>= 3;
 
 	return mclk;
 }
@@ -98,8 +106,19 @@
 		ret = radeon_combios_get_clock_info(dev);
 
 	if (ret) {
-		if (p1pll->reference_div < 2)
-			p1pll->reference_div = 12;
+		if (p1pll->reference_div < 2) {
+			if (!ASIC_IS_AVIVO(rdev)) {
+				u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV);
+				if (ASIC_IS_R300(rdev))
+					p1pll->reference_div =
+						(tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
+				else
+					p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK;
+				if (p1pll->reference_div < 2)
+					p1pll->reference_div = 12;
+			} else
+				p1pll->reference_div = 12;
+		}
 		if (p2pll->reference_div < 2)
 			p2pll->reference_div = 12;
 		if (rdev->family < CHIP_RS600) {
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/mkregtable.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/mkregtable.c
@@ -661,8 +661,10 @@
 	fseek(file, 0, SEEK_SET);
 
 	/* get header */
-	if (fgets(buf, 1024, file) == NULL)
+	if (fgets(buf, 1024, file) == NULL) {
+		fclose(file);
 		return -1;
+	}
 
 	/* first line will contain the last register
 	 * and gpu name */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_drv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_drv.h
@@ -106,9 +106,10 @@
  * 1.29- R500 3D cmd buffer support
  * 1.30- Add support for occlusion queries
  * 1.31- Add support for num Z pipes from GET_PARAM
+ * 1.32- fixes for rv740 setup
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		31
+#define DRIVER_MINOR		32
 #define DRIVER_PATCHLEVEL	0
 
 enum radeon_cp_microcode_version {
@@ -267,6 +268,8 @@
 
 	u32 scratch_ages[5];
 
+	int have_z_offset;
+
 	/* starting from here on, data is preserved accross an open */
 	uint32_t flags;		/* see radeon_chip_flags */
 	resource_size_t fb_aper_offset;
@@ -1104,7 +1107,6 @@
 #       define R600_IT_WAIT_REG_MEM             0x00003C00
 #       define R600_IT_MEM_WRITE                0x00003D00
 #       define R600_IT_INDIRECT_BUFFER          0x00003200
-#       define R600_IT_CP_INTERRUPT             0x00004000
 #       define R600_IT_SURFACE_SYNC             0x00004300
 #              define R600_CB0_DEST_BASE_ENA    (1 << 6)
 #              define R600_TC_ACTION_ENA        (1 << 23)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -30,9 +30,20 @@
 #include "radeon.h"
 #include "atom.h"
 
+static void radeon_overscan_setup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+
+	WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0);
+	WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0);
+	WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0);
+}
+
 static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
-				       struct drm_display_mode *mode,
-				       struct drm_display_mode *adjusted_mode)
+				       struct drm_display_mode *mode)
 {
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -261,7 +272,7 @@
 	if (!ref_div)
 		return 1;
 
-	vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div;
+	vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div;
 
 	/*
 	 * This is horribly crude: the VCO frequency range is divided into
@@ -292,8 +303,7 @@
 	uint32_t mask;
 
 	if (radeon_crtc->crtc_id)
-		mask = (RADEON_CRTC2_EN |
-			RADEON_CRTC2_DISP_DIS |
+		mask = (RADEON_CRTC2_DISP_DIS |
 			RADEON_CRTC2_VSYNC_DIS |
 			RADEON_CRTC2_HSYNC_DIS |
 			RADEON_CRTC2_DISP_REQ_EN_B);
@@ -305,7 +315,7 @@
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		if (radeon_crtc->crtc_id)
-			WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask);
+			WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
 		else {
 			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
 									 RADEON_CRTC_DISP_REQ_EN_B));
@@ -319,7 +329,7 @@
 	case DRM_MODE_DPMS_OFF:
 		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
 		if (radeon_crtc->crtc_id)
-			WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
+			WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
 		else {
 			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
 										    RADEON_CRTC_DISP_REQ_EN_B));
@@ -329,69 +339,6 @@
 	}
 }
 
-/* properly set crtc bpp when using atombios */
-void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-	int format;
-	uint32_t crtc_gen_cntl;
-	uint32_t disp_merge_cntl;
-	uint32_t crtc_pitch;
-
-	switch (crtc->fb->bits_per_pixel) {
-	case 8:
-		format = 2;
-		break;
-	case 15:      /*  555 */
-		format = 3;
-		break;
-	case 16:      /*  565 */
-		format = 4;
-		break;
-	case 24:      /*  RGB */
-		format = 5;
-		break;
-	case 32:      /* xRGB */
-		format = 6;
-		break;
-	default:
-		return;
-	}
-
-	crtc_pitch  = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
-			((crtc->fb->bits_per_pixel * 8) - 1)) /
-		       (crtc->fb->bits_per_pixel * 8));
-	crtc_pitch |= crtc_pitch << 16;
-
-	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
-
-	switch (radeon_crtc->crtc_id) {
-	case 0:
-		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
-		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
-
-		crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
-		crtc_gen_cntl |= (format << 8);
-		crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
-		WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
-		break;
-	case 1:
-		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
-		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
-		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
-
-		crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
-		crtc_gen_cntl |= (format << 8);
-		WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
-		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
-		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
-		break;
-	}
-}
-
 int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 			 struct drm_framebuffer *old_fb)
 {
@@ -400,14 +347,21 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_framebuffer *radeon_fb;
 	struct drm_gem_object *obj;
+	struct radeon_bo *rbo;
 	uint64_t base;
 	uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
 	uint32_t crtc_pitch, pitch_pixels;
 	uint32_t tiling_flags;
 	int format;
 	uint32_t gen_cntl_reg, gen_cntl_val;
+	int r;
 
 	DRM_DEBUG("\n");
+	/* no fb bound */
+	if (!crtc->fb) {
+		DRM_DEBUG("No FB bound\n");
+		return 0;
+	}
 
 	radeon_fb = to_radeon_framebuffer(crtc->fb);
 
@@ -431,10 +385,22 @@
 		return false;
 	}
 
+	/* Pin framebuffer & get tilling informations */
 	obj = radeon_fb->obj;
-	if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
+	rbo = obj->driver_private;
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base);
+	if (unlikely(r != 0)) {
+		radeon_bo_unreserve(rbo);
 		return -EINVAL;
 	}
+	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+	radeon_bo_unreserve(rbo);
+	if (tiling_flags & RADEON_TILING_MICRO)
+		DRM_ERROR("trying to scanout microtiled buffer\n");
+
 	/* if scanout was in GTT this really wouldn't work */
 	/* crtc offset is from display base addr not FB location */
 	radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
@@ -449,10 +415,6 @@
 		       (crtc->fb->bits_per_pixel * 8));
 	crtc_pitch |= crtc_pitch << 16;
 
-	radeon_object_get_tiling_flags(obj->driver_private,
-				       &tiling_flags, NULL);
-	if (tiling_flags & RADEON_TILING_MICRO)
-		DRM_ERROR("trying to scanout microtiled buffer\n");
 
 	if (tiling_flags & RADEON_TILING_MACRO) {
 		if (ASIC_IS_R300(rdev))
@@ -530,7 +492,12 @@
 
 	if (old_fb && old_fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(old_fb);
-		radeon_gem_object_unpin(radeon_fb->obj);
+		rbo = radeon_fb->obj->driver_private;
+		r = radeon_bo_reserve(rbo, false);
+		if (unlikely(r != 0))
+			return r;
+		radeon_bo_unpin(rbo);
+		radeon_bo_unreserve(rbo);
 	}
 
 	/* Bytes per pixel may have changed */
@@ -642,12 +609,8 @@
 		uint32_t crtc2_gen_cntl;
 		uint32_t disp2_merge_cntl;
 
-		/* check to see if TV DAC is enabled for another crtc and keep it enabled */
-		if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON)
-			crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
-		else
-			crtc2_gen_cntl = 0;
-
+		/* if TV DAC is enabled for another crtc and keep it enabled */
+		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080;
 		crtc2_gen_cntl |= ((format << 8)
 				   | RADEON_CRTC2_VSYNC_DIS
 				   | RADEON_CRTC2_HSYNC_DIS
@@ -676,7 +639,8 @@
 		uint32_t crtc_ext_cntl;
 		uint32_t disp_merge_cntl;
 
-		crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
+		crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000;
+		crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN
 				 | (format << 8)
 				 | RADEON_CRTC_DISP_REQ_EN_B
 				 | ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -728,7 +692,6 @@
 	uint32_t post_divider = 0;
 	uint32_t freq = 0;
 	uint8_t pll_gain;
-	int pll_flags = RADEON_PLL_LEGACY;
 	bool use_bios_divs = false;
 	/* PLL registers */
 	uint32_t pll_ref_div = 0;
@@ -762,10 +725,16 @@
 	else
 		pll = &rdev->clock.p1pll;
 
+	pll->flags = RADEON_PLL_LEGACY;
+	if (radeon_new_pll == 1)
+		pll->algo = PLL_ALGO_NEW;
+	else
+		pll->algo = PLL_ALGO_LEGACY;
+
 	if (mode->clock > 200000) /* range limits??? */
-		pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+		pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 	else
-		pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+		pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
@@ -777,20 +746,22 @@
 			}
 
 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
-				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+				pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
 			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
-				struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-				struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
-				if (lvds) {
-					if (lvds->use_bios_dividers) {
-						pll_ref_div = lvds->panel_ref_divider;
-						pll_fb_post_div   = (lvds->panel_fb_divider |
-								     (lvds->panel_post_divider << 16));
-						htotal_cntl  = 0;
-						use_bios_divs = true;
+				if (!rdev->is_atom_bios) {
+					struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+					struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
+					if (lvds) {
+						if (lvds->use_bios_dividers) {
+							pll_ref_div = lvds->panel_ref_divider;
+							pll_fb_post_div   = (lvds->panel_fb_divider |
+									     (lvds->panel_post_divider << 16));
+							htotal_cntl  = 0;
+							use_bios_divs = true;
+						}
 					}
 				}
-				pll_flags |= RADEON_PLL_USE_REF_DIV;
+				pll->flags |= RADEON_PLL_USE_REF_DIV;
 			}
 		}
 	}
@@ -800,8 +771,7 @@
 	if (!use_bios_divs) {
 		radeon_compute_pll(pll, mode->clock,
 				   &freq, &feedback_div, &frac_fb_div,
-				   &reference_div, &post_divider,
-				   pll_flags);
+				   &reference_div, &post_divider);
 
 		for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 			if (post_div->divider == post_divider)
@@ -1027,8 +997,9 @@
 	radeon_crtc_set_base(crtc, x, y, old_fb);
 	radeon_set_crtc_timing(crtc, adjusted_mode);
 	radeon_set_pll(crtc, adjusted_mode);
+	radeon_overscan_setup(crtc, adjusted_mode);
 	if (radeon_crtc->crtc_id == 0) {
-		radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
+		radeon_legacy_rmx_mode_set(crtc, adjusted_mode);
 	} else {
 		if (radeon_crtc->rmx_type != RMX_OFF) {
 			/* FIXME: only first crtc has rmx what should we
@@ -1042,12 +1013,29 @@
 
 static void radeon_crtc_prepare(struct drm_crtc *crtc)
 {
-	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	struct drm_device *dev = crtc->dev;
+	struct drm_crtc *crtci;
+
+	/*
+	* The hardware wedges sometimes if you reconfigure one CRTC
+	* whilst another is running (see fdo bug #24611).
+	*/
+	list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
+		radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
 }
 
 static void radeon_crtc_commit(struct drm_crtc *crtc)
 {
-	radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+	struct drm_device *dev = crtc->dev;
+	struct drm_crtc *crtci;
+
+	/*
+	* Reenable the CRTCs that should be running.
+	*/
+	list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
+		if (crtci->enabled)
+			radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
+	}
 }
 
 static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/rs600.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/rs600.c
@@ -45,6 +45,123 @@
 void rs600_gpu_init(struct radeon_device *rdev);
 int rs600_mc_wait_for_idle(struct radeon_device *rdev);
 
+int rs600_mc_init(struct radeon_device *rdev)
+{
+	/* read back the MC value from the hw */
+	int r;
+	u32 tmp;
+
+	/* Setup GPU memory space */
+	tmp = RREG32_MC(R_000004_MC_FB_LOCATION);
+	rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16;
+	rdev->mc.gtt_location = 0xffffffffUL;
+	r = radeon_mc_setup(rdev);
+	if (r)
+		return r;
+	return 0;
+}
+
+/* hpd for digital panel detect/disconnect */
+bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
+{
+	u32 tmp;
+	bool connected = false;
+
+	switch (hpd) {
+	case RADEON_HPD_1:
+		tmp = RREG32(R_007D04_DC_HOT_PLUG_DETECT1_INT_STATUS);
+		if (G_007D04_DC_HOT_PLUG_DETECT1_SENSE(tmp))
+			connected = true;
+		break;
+	case RADEON_HPD_2:
+		tmp = RREG32(R_007D14_DC_HOT_PLUG_DETECT2_INT_STATUS);
+		if (G_007D14_DC_HOT_PLUG_DETECT2_SENSE(tmp))
+			connected = true;
+		break;
+	default:
+		break;
+	}
+	return connected;
+}
+
+void rs600_hpd_set_polarity(struct radeon_device *rdev,
+			    enum radeon_hpd_id hpd)
+{
+	u32 tmp;
+	bool connected = rs600_hpd_sense(rdev, hpd);
+
+	switch (hpd) {
+	case RADEON_HPD_1:
+		tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
+		if (connected)
+			tmp &= ~S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
+		else
+			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_POLARITY(1);
+		WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
+		break;
+	case RADEON_HPD_2:
+		tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
+		if (connected)
+			tmp &= ~S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
+		else
+			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_POLARITY(1);
+		WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
+		break;
+	default:
+		break;
+	}
+}
+
+void rs600_hpd_init(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		switch (radeon_connector->hpd.hpd) {
+		case RADEON_HPD_1:
+			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
+			       S_007D00_DC_HOT_PLUG_DETECT1_EN(1));
+			rdev->irq.hpd[0] = true;
+			break;
+		case RADEON_HPD_2:
+			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
+			       S_007D10_DC_HOT_PLUG_DETECT2_EN(1));
+			rdev->irq.hpd[1] = true;
+			break;
+		default:
+			break;
+		}
+	}
+	if (rdev->irq.installed)
+		rs600_irq_set(rdev);
+}
+
+void rs600_hpd_fini(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+		switch (radeon_connector->hpd.hpd) {
+		case RADEON_HPD_1:
+			WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL,
+			       S_007D00_DC_HOT_PLUG_DETECT1_EN(0));
+			rdev->irq.hpd[0] = false;
+			break;
+		case RADEON_HPD_2:
+			WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL,
+			       S_007D10_DC_HOT_PLUG_DETECT2_EN(0));
+			rdev->irq.hpd[1] = false;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 /*
  * GART.
  */
@@ -57,7 +174,7 @@
 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
 
 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
-	tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) & S_000100_INVALIDATE_L2_CACHE(1);
+	tmp |= S_000100_INVALIDATE_ALL_L1_TLBS(1) | S_000100_INVALIDATE_L2_CACHE(1);
 	WREG32_MC(R_000100_MC_PT0_CNTL, tmp);
 
 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
@@ -100,40 +217,40 @@
 	WREG32(R_00004C_BUS_CNTL, tmp);
 	/* FIXME: setup default page */
 	WREG32_MC(R_000100_MC_PT0_CNTL,
-		 (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
-		  S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
+		  (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
+		   S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
+
 	for (i = 0; i < 19; i++) {
 		WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i,
-			S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
-			S_00016C_SYSTEM_ACCESS_MODE_MASK(
-				V_00016C_SYSTEM_ACCESS_MODE_IN_SYS) |
-			S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
-				V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE) |
-			S_00016C_EFFECTIVE_L1_CACHE_SIZE(1) |
-			S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
-			S_00016C_EFFECTIVE_L1_QUEUE_SIZE(1));
+			  S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
+			  S_00016C_SYSTEM_ACCESS_MODE_MASK(
+				  V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) |
+			  S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
+				  V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) |
+			  S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) |
+			  S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
+			  S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3));
 	}
-
-	/* System context map to GART space */
-	WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_start);
-	WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.gtt_end);
-
 	/* enable first context */
-	WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
-	WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
 	WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL,
-			S_000102_ENABLE_PAGE_TABLE(1) |
-			S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
+		  S_000102_ENABLE_PAGE_TABLE(1) |
+		  S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
+
 	/* disable all other contexts */
-	for (i = 1; i < 8; i++) {
+	for (i = 1; i < 8; i++)
 		WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0);
-	}
 
 	/* setup the page table */
 	WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
-			rdev->gart.table_addr);
+		  rdev->gart.table_addr);
+	WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
+	WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
 	WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
 
+	/* System context maps to VRAM space */
+	WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start);
+	WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end);
+
 	/* enable page tables */
 	tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
 	WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1)));
@@ -146,15 +263,20 @@
 
 void rs600_gart_disable(struct radeon_device *rdev)
 {
-	uint32_t tmp;
+	u32 tmp;
+	int r;
 
 	/* FIXME: disable out of gart access */
 	WREG32_MC(R_000100_MC_PT0_CNTL, 0);
 	tmp = RREG32_MC(R_000009_MC_CNTL1);
 	WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
 	if (rdev->gart.table.vram.robj) {
-		radeon_object_kunmap(rdev->gart.table.vram.robj);
-		radeon_object_unpin(rdev->gart.table.vram.robj);
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (r == 0) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
 	}
 }
 
@@ -189,7 +311,16 @@
 {
 	uint32_t tmp = 0;
 	uint32_t mode_int = 0;
-
+	u32 hpd1 = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL) &
+		~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
+	u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) &
+		~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
+
+	if (!rdev->irq.installed) {
+		WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n");
+		WREG32(R_000040_GEN_INT_CNTL, 0);
+		return -EINVAL;
+	}
 	if (rdev->irq.sw_int) {
 		tmp |= S_000040_SW_INT_EN(1);
 	}
@@ -199,8 +330,16 @@
 	if (rdev->irq.crtc_vblank_int[1]) {
 		mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1);
 	}
+	if (rdev->irq.hpd[0]) {
+		hpd1 |= S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1);
+	}
+	if (rdev->irq.hpd[1]) {
+		hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1);
+	}
 	WREG32(R_000040_GEN_INT_CNTL, tmp);
 	WREG32(R_006540_DxMODE_INT_MASK, mode_int);
+	WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1);
+	WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
 	return 0;
 }
 
@@ -208,6 +347,7 @@
 {
 	uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS);
 	uint32_t irq_mask = ~C_000044_SW_INT;
+	u32 tmp;
 
 	if (G_000044_DISPLAY_INT_STAT(irqs)) {
 		*r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS);
@@ -219,6 +359,16 @@
 			WREG32(R_006D34_D2MODE_VBLANK_STATUS,
 				S_006D34_D2MODE_VBLANK_ACK(1));
 		}
+		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) {
+			tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL);
+			tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1);
+			WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp);
+		}
+		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) {
+			tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL);
+			tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1);
+			WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp);
+		}
 	} else {
 		*r500_disp_int = 0;
 	}
@@ -244,6 +394,7 @@
 {
 	uint32_t status, msi_rearm;
 	uint32_t r500_disp_int;
+	bool queue_hotplug = false;
 
 	status = rs600_irq_ack(rdev, &r500_disp_int);
 	if (!status && !r500_disp_int) {
@@ -251,15 +402,25 @@
 	}
 	while (status || r500_disp_int) {
 		/* SW interrupt */
-		if (G_000040_SW_INT_EN(status))
+		if (G_000044_SW_INT(status))
 			radeon_fence_process(rdev);
 		/* Vertical blank interrupts */
 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int))
 			drm_handle_vblank(rdev->ddev, 0);
 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int))
 			drm_handle_vblank(rdev->ddev, 1);
+		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
+			queue_hotplug = true;
+			DRM_DEBUG("HPD1\n");
+		}
+		if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) {
+			queue_hotplug = true;
+			DRM_DEBUG("HPD2\n");
+		}
 		status = rs600_irq_ack(rdev, &r500_disp_int);
 	}
+	if (queue_hotplug)
+		queue_work(rdev->wq, &rdev->hotplug_work);
 	if (rdev->msi_enabled) {
 		switch (rdev->family) {
 		case CHIP_RS600:
@@ -301,9 +462,7 @@
 
 void rs600_gpu_init(struct radeon_device *rdev)
 {
-	/* FIXME: HDP same place on rs600 ? */
 	r100_hdp_reset(rdev);
-	/* FIXME: is this correct ? */
 	r420_pipes_init(rdev);
 	/* Wait for mc idle */
 	if (rs600_mc_wait_for_idle(rdev))
@@ -312,9 +471,20 @@
 
 void rs600_vram_info(struct radeon_device *rdev)
 {
-	/* FIXME: to do or is these values sane ? */
 	rdev->mc.vram_is_ddr = true;
 	rdev->mc.vram_width = 128;
+
+	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+		rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+		rdev->mc.real_vram_size = rdev->mc.aper_size;
 }
 
 void rs600_bandwidth_update(struct radeon_device *rdev)
@@ -388,8 +558,8 @@
 	if (r)
 		return r;
 	/* Enable IRQ */
-	rdev->irq.sw_int = true;
 	rs600_irq_set(rdev);
+	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
@@ -423,6 +593,8 @@
 	atom_asic_init(rdev->mode_info.atom_context);
 	/* Resume clock after posting */
 	rv515_clock_startup(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
 	return rs600_startup(rdev);
 }
 
@@ -437,7 +609,6 @@
 
 void rs600_fini(struct radeon_device *rdev)
 {
-	rs600_suspend(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
@@ -445,7 +616,7 @@
 	rs600_gart_fini(rdev);
 	radeon_irq_kms_fini(rdev);
 	radeon_fence_driver_fini(rdev);
-	radeon_object_fini(rdev);
+	radeon_bo_fini(rdev);
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
@@ -482,10 +653,9 @@
 			RREG32(R_0007C0_CP_STAT));
 	}
 	/* check if cards are posted or not */
-	if (!radeon_card_posted(rdev) && rdev->bios) {
-		DRM_INFO("GPU not posted. posting now...\n");
-		atom_asic_init(rdev->mode_info.atom_context);
-	}
+	if (radeon_boot_test_post_card(rdev) == false)
+		return -EINVAL;
+
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
@@ -493,7 +663,7 @@
 	/* Get vram informations */
 	rs600_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
+	r = rs600_mc_init(rdev);
 	if (r)
 		return r;
 	rs600_debugfs(rdev);
@@ -505,7 +675,7 @@
 	if (r)
 		return r;
 	/* Memory manager */
-	r = radeon_object_init(rdev);
+	r = radeon_bo_init(rdev);
 	if (r)
 		return r;
 	r = rs600_gart_init(rdev);
@@ -517,7 +687,6 @@
 	if (r) {
 		/* Somethings want wront with the accel init stop accel */
 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
-		rs600_suspend(rdev);
 		r100_cp_fini(rdev);
 		r100_wb_fini(rdev);
 		r100_ib_fini(rdev);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_reg.h
@@ -887,6 +887,7 @@
 #       define RADEON_FP_PANEL_FORMAT          (1 <<  3)
 #       define RADEON_FP_EN_TMDS               (1 <<  7)
 #       define RADEON_FP_DETECT_SENSE          (1 <<  8)
+#       define RADEON_FP_DETECT_INT_POL        (1 <<  9)
 #       define R200_FP_SOURCE_SEL_MASK         (3 <<  10)
 #       define R200_FP_SOURCE_SEL_CRTC1        (0 <<  10)
 #       define R200_FP_SOURCE_SEL_CRTC2        (1 <<  10)
@@ -894,6 +895,7 @@
 #       define R200_FP_SOURCE_SEL_TRANS        (3 <<  10)
 #       define RADEON_FP_SEL_CRTC1             (0 << 13)
 #       define RADEON_FP_SEL_CRTC2             (1 << 13)
+#       define R300_HPD_SEL(x)                 ((x) << 13)
 #       define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15)
 #       define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
 #       define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
@@ -909,6 +911,7 @@
 #       define RADEON_FP2_ON                   (1 <<  2)
 #       define RADEON_FP2_PANEL_FORMAT         (1 <<  3)
 #       define RADEON_FP2_DETECT_SENSE         (1 <<  8)
+#       define RADEON_FP2_DETECT_INT_POL       (1 <<  9)
 #       define R200_FP2_SOURCE_SEL_MASK        (3 << 10)
 #       define R200_FP2_SOURCE_SEL_CRTC1       (0 << 10)
 #       define R200_FP2_SOURCE_SEL_CRTC2       (1 << 10)
@@ -988,14 +991,20 @@
 
 #define RADEON_GEN_INT_CNTL                 0x0040
 #	define RADEON_CRTC_VBLANK_MASK		(1 << 0)
+#	define RADEON_FP_DETECT_MASK		(1 << 4)
 #	define RADEON_CRTC2_VBLANK_MASK		(1 << 9)
+#	define RADEON_FP2_DETECT_MASK		(1 << 10)
 #	define RADEON_SW_INT_ENABLE		(1 << 25)
 #define RADEON_GEN_INT_STATUS               0x0044
 #	define AVIVO_DISPLAY_INT_STATUS		(1 << 0)
 #	define RADEON_CRTC_VBLANK_STAT		(1 << 0)
 #	define RADEON_CRTC_VBLANK_STAT_ACK	(1 << 0)
+#	define RADEON_FP_DETECT_STAT		(1 << 4)
+#	define RADEON_FP_DETECT_STAT_ACK	(1 << 4)
 #	define RADEON_CRTC2_VBLANK_STAT		(1 << 9)
 #	define RADEON_CRTC2_VBLANK_STAT_ACK	(1 << 9)
+#	define RADEON_FP2_DETECT_STAT		(1 << 10)
+#	define RADEON_FP2_DETECT_STAT_ACK	(1 << 10)
 #	define RADEON_SW_INT_FIRE		(1 << 26)
 #	define RADEON_SW_INT_TEST		(1 << 25)
 #	define RADEON_SW_INT_TEST_ACK		(1 << 25)
@@ -1051,20 +1060,25 @@
 
        /* Multimedia I2C bus */
 #define RADEON_I2C_CNTL_0		    0x0090
-#define RADEON_I2C_DONE (1<<0)
-#define RADEON_I2C_NACK (1<<1)
-#define RADEON_I2C_HALT (1<<2)
-#define RADEON_I2C_SOFT_RST (1<<5)
-#define RADEON_I2C_DRIVE_EN (1<<6)
-#define RADEON_I2C_DRIVE_SEL (1<<7)
-#define RADEON_I2C_START (1<<8)
-#define RADEON_I2C_STOP (1<<9)
-#define RADEON_I2C_RECEIVE (1<<10)
-#define RADEON_I2C_ABORT (1<<11)
-#define RADEON_I2C_GO (1<<12)
+#define RADEON_I2C_DONE                     (1 << 0)
+#define RADEON_I2C_NACK                     (1 << 1)
+#define RADEON_I2C_HALT                     (1 << 2)
+#define RADEON_I2C_SOFT_RST                 (1 << 5)
+#define RADEON_I2C_DRIVE_EN                 (1 << 6)
+#define RADEON_I2C_DRIVE_SEL                (1 << 7)
+#define RADEON_I2C_START                    (1 << 8)
+#define RADEON_I2C_STOP                     (1 << 9)
+#define RADEON_I2C_RECEIVE                  (1 << 10)
+#define RADEON_I2C_ABORT                    (1 << 11)
+#define RADEON_I2C_GO                       (1 << 12)
+#define RADEON_I2C_PRESCALE_SHIFT           16
 #define RADEON_I2C_CNTL_1                   0x0094
-#define RADEON_I2C_SEL         (1<<16)
-#define RADEON_I2C_EN          (1<<17)
+#define RADEON_I2C_DATA_COUNT_SHIFT         0
+#define RADEON_I2C_ADDR_COUNT_SHIFT         4
+#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT   8
+#define RADEON_I2C_SEL                      (1 << 16)
+#define RADEON_I2C_EN                       (1 << 17)
+#define RADEON_I2C_TIME_LIMIT_SHIFT         24
 #define RADEON_I2C_DATA			    0x0098
 
 #define RADEON_DVI_I2C_CNTL_0		    0x02e0
@@ -1072,7 +1086,7 @@
 #       define R200_SEL_DDC1                0 /* 0x60 - VGA_DDC */
 #       define R200_SEL_DDC2                1 /* 0x64 - DVI_DDC */
 #       define R200_SEL_DDC3                2 /* 0x68 - MONID_DDC */
-#define RADEON_DVI_I2C_CNTL_1               0x02e4 /* ? */
+#define RADEON_DVI_I2C_CNTL_1               0x02e4
 #define RADEON_DVI_I2C_DATA		    0x02e8
 
 #define RADEON_INTERRUPT_LINE               0x0f3c /* PCI */
@@ -1143,15 +1157,16 @@
 #       define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
 #       define RADEON_MC_MCLK_DYN_ENABLE    (1 << 14)
 #       define RADEON_IO_MCLK_DYN_ENABLE    (1 << 15)
-#define RADEON_LCD_GPIO_MASK                0x01a0
-#define RADEON_GPIOPAD_EN                   0x01a0
-#define RADEON_LCD_GPIO_Y_REG               0x01a4
-#define RADEON_MDGPIO_A_REG                 0x01ac
-#define RADEON_MDGPIO_EN_REG                0x01b0
-#define RADEON_MDGPIO_MASK                  0x0198
+
 #define RADEON_GPIOPAD_MASK                 0x0198
 #define RADEON_GPIOPAD_A		    0x019c
-#define RADEON_MDGPIO_Y_REG                 0x01b4
+#define RADEON_GPIOPAD_EN                   0x01a0
+#define RADEON_GPIOPAD_Y                    0x01a4
+#define RADEON_MDGPIO_MASK                  0x01a8
+#define RADEON_MDGPIO_A                     0x01ac
+#define RADEON_MDGPIO_EN                    0x01b0
+#define RADEON_MDGPIO_Y                     0x01b4
+
 #define RADEON_MEM_ADDR_CONFIG              0x0148
 #define RADEON_MEM_BASE                     0x0f10 /* PCI */
 #define RADEON_MEM_CNTL                     0x0140
@@ -1360,6 +1375,9 @@
 #define RADEON_OVR_CLR                      0x0230
 #define RADEON_OVR_WID_LEFT_RIGHT           0x0234
 #define RADEON_OVR_WID_TOP_BOTTOM           0x0238
+#define RADEON_OVR2_CLR                     0x0330
+#define RADEON_OVR2_WID_LEFT_RIGHT          0x0334
+#define RADEON_OVR2_WID_TOP_BOTTOM          0x0338
 
 /* first capture unit */
 
@@ -2809,6 +2827,7 @@
 #       define R200_TXFORMAT_ST_ROUTE_STQ5	(5 << 24)
 #       define R200_TXFORMAT_ST_ROUTE_MASK	(7 << 24)
 #       define R200_TXFORMAT_ST_ROUTE_SHIFT	24
+#       define R200_TXFORMAT_LOOKUP_DISABLE	(1 << 27)
 #       define R200_TXFORMAT_ALPHA_MASK_ENABLE	(1 << 28)
 #       define R200_TXFORMAT_CHROMA_KEY_ENABLE	(1 << 29)
 #       define R200_TXFORMAT_CUBIC_MAP_ENABLE		(1 << 30)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_asic.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_asic.h
@@ -33,6 +33,7 @@
  */
 uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev);
 void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock);
+uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev);
 void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 
 uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev);
@@ -76,6 +77,11 @@
 void r100_bandwidth_update(struct radeon_device *rdev);
 void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r100_ring_test(struct radeon_device *rdev);
+void r100_hpd_init(struct radeon_device *rdev);
+void r100_hpd_fini(struct radeon_device *rdev);
+bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+void r100_hpd_set_polarity(struct radeon_device *rdev,
+			   enum radeon_hpd_id hpd);
 
 static struct radeon_asic r100_asic = {
 	.init = &r100_init,
@@ -100,13 +106,18 @@
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_legacy_get_engine_clock,
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
-	.get_memory_clock = NULL,
+	.get_memory_clock = &radeon_legacy_get_memory_clock,
 	.set_memory_clock = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_legacy_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -155,13 +166,18 @@
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_legacy_get_engine_clock,
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
-	.get_memory_clock = NULL,
+	.get_memory_clock = &radeon_legacy_get_memory_clock,
 	.set_memory_clock = NULL,
 	.set_pcie_lanes = &rv370_set_pcie_lanes,
 	.set_clock_gating = &radeon_legacy_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 /*
@@ -201,6 +217,11 @@
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -238,13 +259,18 @@
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_legacy_get_engine_clock,
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
-	.get_memory_clock = NULL,
+	.get_memory_clock = &radeon_legacy_get_memory_clock,
 	.set_memory_clock = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_legacy_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -263,6 +289,12 @@
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rs600_bandwidth_update(struct radeon_device *rdev);
+void rs600_hpd_init(struct radeon_device *rdev);
+void rs600_hpd_fini(struct radeon_device *rdev);
+bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+void rs600_hpd_set_polarity(struct radeon_device *rdev,
+			    enum radeon_hpd_id hpd);
+
 static struct radeon_asic rs600_asic = {
 	.init = &rs600_init,
 	.fini = &rs600_fini,
@@ -290,7 +322,14 @@
 	.set_memory_clock = &radeon_atom_set_memory_clock,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &rs600_bandwidth_update,
+	.hpd_init = &rs600_hpd_init,
+	.hpd_fini = &rs600_hpd_fini,
+	.hpd_sense = &rs600_hpd_sense,
+	.hpd_set_polarity = &rs600_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -334,6 +373,11 @@
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &rs690_bandwidth_update,
+	.hpd_init = &rs600_hpd_init,
+	.hpd_fini = &rs600_hpd_fini,
+	.hpd_sense = &rs600_hpd_sense,
+	.hpd_set_polarity = &rs600_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -381,6 +425,11 @@
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &rv515_bandwidth_update,
+	.hpd_init = &rs600_hpd_init,
+	.hpd_fini = &rs600_hpd_fini,
+	.hpd_sense = &rs600_hpd_sense,
+	.hpd_set_polarity = &rs600_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 
@@ -419,6 +468,11 @@
 	.set_surface_reg = r100_set_surface_reg,
 	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &rv515_bandwidth_update,
+	.hpd_init = &rs600_hpd_init,
+	.hpd_fini = &rs600_hpd_fini,
+	.hpd_sense = &rs600_hpd_sense,
+	.hpd_set_polarity = &rs600_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
 };
 
 /*
@@ -455,6 +509,12 @@
 int r600_copy_blit(struct radeon_device *rdev,
 		   uint64_t src_offset, uint64_t dst_offset,
 		   unsigned num_pages, struct radeon_fence *fence);
+void r600_hpd_init(struct radeon_device *rdev);
+void r600_hpd_fini(struct radeon_device *rdev);
+bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+void r600_hpd_set_polarity(struct radeon_device *rdev,
+			   enum radeon_hpd_id hpd);
+extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
 
 static struct radeon_asic r600_asic = {
 	.init = &r600_init,
@@ -470,6 +530,7 @@
 	.ring_ib_execute = &r600_ring_ib_execute,
 	.irq_set = &r600_irq_set,
 	.irq_process = &r600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &r600_cs_parse,
 	.copy_blit = &r600_copy_blit,
@@ -484,6 +545,11 @@
 	.set_surface_reg = r600_set_surface_reg,
 	.clear_surface_reg = r600_clear_surface_reg,
 	.bandwidth_update = &rv515_bandwidth_update,
+	.hpd_init = &r600_hpd_init,
+	.hpd_fini = &r600_hpd_fini,
+	.hpd_sense = &r600_hpd_sense,
+	.hpd_set_polarity = &r600_hpd_set_polarity,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
 };
 
 /*
@@ -509,6 +575,7 @@
 	.ring_ib_execute = &r600_ring_ib_execute,
 	.irq_set = &r600_irq_set,
 	.irq_process = &r600_irq_process,
+	.get_vblank_counter = &rs600_get_vblank_counter,
 	.fence_ring_emit = &r600_fence_ring_emit,
 	.cs_parse = &r600_cs_parse,
 	.copy_blit = &r600_copy_blit,
@@ -523,6 +590,11 @@
 	.set_surface_reg = r600_set_surface_reg,
 	.clear_surface_reg = r600_clear_surface_reg,
 	.bandwidth_update = &rv515_bandwidth_update,
+	.hpd_init = &r600_hpd_init,
+	.hpd_fini = &r600_hpd_fini,
+	.hpd_sense = &r600_hpd_sense,
+	.hpd_set_polarity = &r600_hpd_set_polarity,
+	.ioctl_wait_idle = r600_ioctl_wait_idle,
 };
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_bios.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_bios.c
@@ -106,7 +106,7 @@
 	bool r;
 
 	viph_control = RREG32(RADEON_VIPH_CONTROL);
-	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	bus_cntl = RREG32(R600_BUS_CNTL);
 	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
 	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
 	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
@@ -115,7 +115,7 @@
 	/* disable VIP */
 	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
 	/* enable the rom */
-	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+	WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
 	/* Disable VGA mode */
 	WREG32(AVIVO_D1VGA_CONTROL,
 	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
@@ -154,7 +154,7 @@
 			cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
 	}
 	WREG32(RADEON_VIPH_CONTROL, viph_control);
-	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(R600_BUS_CNTL, bus_cntl);
 	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
 	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
 	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
@@ -179,7 +179,7 @@
 	bool r;
 
 	viph_control = RREG32(RADEON_VIPH_CONTROL);
-	bus_cntl = RREG32(RADEON_BUS_CNTL);
+	bus_cntl = RREG32(R600_BUS_CNTL);
 	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
 	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
 	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
@@ -194,7 +194,7 @@
 	/* disable VIP */
 	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
 	/* enable the rom */
-	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+	WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
 	/* Disable VGA mode */
 	WREG32(AVIVO_D1VGA_CONTROL,
 	       (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
@@ -225,7 +225,7 @@
 
 	/* restore regs */
 	WREG32(RADEON_VIPH_CONTROL, viph_control);
-	WREG32(RADEON_BUS_CNTL, bus_cntl);
+	WREG32(R600_BUS_CNTL, bus_cntl);
 	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
 	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
 	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_ttm.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -150,7 +150,7 @@
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		break;
 	case TTM_PL_TT:
-		man->gpu_offset = 0;
+		man->gpu_offset = rdev->mc.gtt_location;
 		man->available_caching = TTM_PL_MASK_CACHING;
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
@@ -180,7 +180,7 @@
 		break;
 	case TTM_PL_VRAM:
 		/* "On-card" video ram */
-		man->gpu_offset = 0;
+		man->gpu_offset = rdev->mc.vram_location;
 		man->flags = TTM_MEMTYPE_FLAG_FIXED |
 			     TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
 			     TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -197,16 +197,34 @@
 	return 0;
 }
 
-static uint32_t radeon_evict_flags(struct ttm_buffer_object *bo)
+static void radeon_evict_flags(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement)
 {
-	uint32_t cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEMTYPE;
+	struct radeon_bo *rbo;
+	static u32 placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
 
+	if (!radeon_ttm_bo_is_radeon_bo(bo)) {
+		placement->fpfn = 0;
+		placement->lpfn = 0;
+		placement->placement = &placements;
+		placement->busy_placement = &placements;
+		placement->num_placement = 1;
+		placement->num_busy_placement = 1;
+		return;
+	}
+	rbo = container_of(bo, struct radeon_bo, tbo);
 	switch (bo->mem.mem_type) {
+	case TTM_PL_VRAM:
+		if (rbo->rdev->cp.ready == false)
+			radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU);
+		else
+			radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT);
+		break;
+	case TTM_PL_TT:
 	default:
-		return (cur_placement & ~TTM_PL_MASK_CACHING) |
-			TTM_PL_FLAG_SYSTEM |
-			TTM_PL_FLAG_CACHED;
+		radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU);
 	}
+	*placement = rbo->placement;
 }
 
 static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp)
@@ -283,14 +301,21 @@
 	struct radeon_device *rdev;
 	struct ttm_mem_reg *old_mem = &bo->mem;
 	struct ttm_mem_reg tmp_mem;
-	uint32_t proposed_placement;
+	u32 placements;
+	struct ttm_placement placement;
 	int r;
 
 	rdev = radeon_get_rdev(bo->bdev);
 	tmp_mem = *new_mem;
 	tmp_mem.mm_node = NULL;
-	proposed_placement = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
-	r = ttm_bo_mem_space(bo, proposed_placement, &tmp_mem,
+	placement.fpfn = 0;
+	placement.lpfn = 0;
+	placement.num_placement = 1;
+	placement.placement = &placements;
+	placement.num_busy_placement = 1;
+	placement.busy_placement = &placements;
+	placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
+	r = ttm_bo_mem_space(bo, &placement, &tmp_mem,
 			     interruptible, no_wait);
 	if (unlikely(r)) {
 		return r;
@@ -329,15 +354,21 @@
 	struct radeon_device *rdev;
 	struct ttm_mem_reg *old_mem = &bo->mem;
 	struct ttm_mem_reg tmp_mem;
-	uint32_t proposed_flags;
+	struct ttm_placement placement;
+	u32 placements;
 	int r;
 
 	rdev = radeon_get_rdev(bo->bdev);
 	tmp_mem = *new_mem;
 	tmp_mem.mm_node = NULL;
-	proposed_flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
-	r = ttm_bo_mem_space(bo, proposed_flags, &tmp_mem,
-			     interruptible, no_wait);
+	placement.fpfn = 0;
+	placement.lpfn = 0;
+	placement.num_placement = 1;
+	placement.placement = &placements;
+	placement.num_busy_placement = 1;
+	placement.busy_placement = &placements;
+	placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
+	r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait);
 	if (unlikely(r)) {
 		return r;
 	}
@@ -378,7 +409,7 @@
 	     new_mem->mem_type == TTM_PL_SYSTEM) ||
 	    (old_mem->mem_type == TTM_PL_SYSTEM &&
 	     new_mem->mem_type == TTM_PL_TT)) {
-		/* bind is enought */
+		/* bind is enough */
 		radeon_move_null(bo, new_mem);
 		return 0;
 	}
@@ -407,18 +438,6 @@
 	return r;
 }
 
-const uint32_t radeon_mem_prios[] = {
-	TTM_PL_VRAM,
-	TTM_PL_TT,
-	TTM_PL_SYSTEM,
-};
-
-const uint32_t radeon_busy_prios[] = {
-	TTM_PL_TT,
-	TTM_PL_VRAM,
-	TTM_PL_SYSTEM,
-};
-
 static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg,
 				bool lazy, bool interruptible)
 {
@@ -446,10 +465,6 @@
 }
 
 static struct ttm_bo_driver radeon_bo_driver = {
-	.mem_type_prio = radeon_mem_prios,
-	.mem_busy_prio = radeon_busy_prios,
-	.num_mem_type_prio = ARRAY_SIZE(radeon_mem_prios),
-	.num_mem_busy_prio = ARRAY_SIZE(radeon_busy_prios),
 	.create_ttm_backend_entry = &radeon_create_ttm_backend_entry,
 	.invalidate_caches = &radeon_invalidate_caches,
 	.init_mem_type = &radeon_init_mem_type,
@@ -482,27 +497,32 @@
 		DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
 		return r;
 	}
-	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
-			   ((rdev->mc.real_vram_size) >> PAGE_SHIFT));
+	rdev->mman.initialized = true;
+	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM,
+				rdev->mc.real_vram_size >> PAGE_SHIFT);
 	if (r) {
 		DRM_ERROR("Failed initializing VRAM heap.\n");
 		return r;
 	}
-	r = radeon_object_create(rdev, NULL, 256 * 1024, true,
-				 RADEON_GEM_DOMAIN_VRAM, false,
-				 &rdev->stollen_vga_memory);
+	r = radeon_bo_create(rdev, NULL, 256 * 1024, true,
+				RADEON_GEM_DOMAIN_VRAM,
+				&rdev->stollen_vga_memory);
 	if (r) {
 		return r;
 	}
-	r = radeon_object_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL);
+	r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
+	if (r)
+		return r;
+	r = radeon_bo_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL);
+	radeon_bo_unreserve(rdev->stollen_vga_memory);
 	if (r) {
-		radeon_object_unref(&rdev->stollen_vga_memory);
+		radeon_bo_unref(&rdev->stollen_vga_memory);
 		return r;
 	}
 	DRM_INFO("radeon: %uM of VRAM memory ready\n",
 		 (unsigned)rdev->mc.real_vram_size / (1024 * 1024));
-	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
-			   ((rdev->mc.gtt_size) >> PAGE_SHIFT));
+	r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT,
+				rdev->mc.gtt_size >> PAGE_SHIFT);
 	if (r) {
 		DRM_ERROR("Failed initializing GTT heap.\n");
 		return r;
@@ -523,15 +543,24 @@
 
 void radeon_ttm_fini(struct radeon_device *rdev)
 {
+	int r;
+
+	if (!rdev->mman.initialized)
+		return;
 	if (rdev->stollen_vga_memory) {
-		radeon_object_unpin(rdev->stollen_vga_memory);
-		radeon_object_unref(&rdev->stollen_vga_memory);
+		r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
+		if (r == 0) {
+			radeon_bo_unpin(rdev->stollen_vga_memory);
+			radeon_bo_unreserve(rdev->stollen_vga_memory);
+		}
+		radeon_bo_unref(&rdev->stollen_vga_memory);
 	}
 	ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM);
 	ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT);
 	ttm_bo_device_release(&rdev->mman.bdev);
 	radeon_gart_fini(rdev);
 	radeon_ttm_global_fini(rdev);
+	rdev->mman.initialized = false;
 	DRM_INFO("radeon: ttm finalized\n");
 }
 
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon_device.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon_device.c
@@ -44,10 +44,11 @@
 	if (rdev->family < CHIP_R600) {
 		int i;
 
-		for (i = 0; i < 8; i++) {
-			WREG32(RADEON_SURFACE0_INFO +
-			       i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
-			       0);
+		for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
+			if (rdev->surface_regs[i].bo)
+				radeon_bo_get_surface_reg(rdev->surface_regs[i].bo);
+			else
+				radeon_clear_surface_reg(rdev, i);
 		}
 		/* enable surfaces */
 		WREG32(RADEON_SURFACE_CNTL, 0);
@@ -208,6 +209,24 @@
 
 }
 
+bool radeon_boot_test_post_card(struct radeon_device *rdev)
+{
+	if (radeon_card_posted(rdev))
+		return true;
+
+	if (rdev->bios) {
+		DRM_INFO("GPU not posted. posting now...\n");
+		if (rdev->is_atom_bios)
+			atom_asic_init(rdev->mode_info.atom_context);
+		else
+			radeon_combios_asic_init(rdev->ddev);
+		return true;
+	} else {
+		dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+		return false;
+	}
+}
+
 int radeon_dummy_page_init(struct radeon_device *rdev)
 {
 	rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
@@ -372,6 +391,12 @@
 		/* FIXME: not supported yet */
 		return -EINVAL;
 	}
+
+	if (rdev->flags & RADEON_IS_IGP) {
+		rdev->asic->get_memory_clock = NULL;
+		rdev->asic->set_memory_clock = NULL;
+	}
+
 	return 0;
 }
 
@@ -462,13 +487,18 @@
 	atom_card_info->pll_write = cail_pll_write;
 
 	rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios);
+	mutex_init(&rdev->mode_info.atom_context->mutex);
 	radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
+	atom_allocate_fb_scratch(rdev->mode_info.atom_context);
 	return 0;
 }
 
 void radeon_atombios_fini(struct radeon_device *rdev)
 {
-	kfree(rdev->mode_info.atom_context);
+	if (rdev->mode_info.atom_context) {
+		kfree(rdev->mode_info.atom_context->scratch);
+		kfree(rdev->mode_info.atom_context);
+	}
 	kfree(rdev->mode_info.atom_card_info);
 }
 
@@ -514,11 +544,75 @@
 		rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
 		rdev->asic->gart_set_page = &r100_pci_gart_set_page;
 	}
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+}
+
+void radeon_check_arguments(struct radeon_device *rdev)
+{
+	/* vramlimit must be a power of two */
+	switch (radeon_vram_limit) {
+	case 0:
+	case 4:
+	case 8:
+	case 16:
+	case 32:
+	case 64:
+	case 128:
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
+				radeon_vram_limit);
+		radeon_vram_limit = 0;
+		break;
+	}
+	radeon_vram_limit = radeon_vram_limit << 20;
+	/* gtt size must be power of two and greater or equal to 32M */
+	switch (radeon_gart_size) {
+	case 4:
+	case 8:
+	case 16:
+		dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
+				radeon_gart_size);
+		radeon_gart_size = 512;
+		break;
+	case 32:
+	case 64:
+	case 128:
+	case 256:
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
+				radeon_gart_size);
+		radeon_gart_size = 512;
+		break;
+	}
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+	/* AGP mode can only be -1, 1, 2, 4, 8 */
+	switch (radeon_agpmode) {
+	case -1:
+	case 0:
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		break;
+	default:
+		dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: "
+				"-1, 0, 1, 2, 4, 8)\n", radeon_agpmode);
+		radeon_agpmode = 0;
+		break;
+	}
 }
 
-/*
- * Radeon device.
- */
 int radeon_device_init(struct radeon_device *rdev,
 		       struct drm_device *ddev,
 		       struct pci_dev *pdev,
@@ -544,16 +638,32 @@
 	mutex_init(&rdev->cs_mutex);
 	mutex_init(&rdev->ib_pool.mutex);
 	mutex_init(&rdev->cp.mutex);
+	if (rdev->family >= CHIP_R600)
+		spin_lock_init(&rdev->ih.lock);
+	mutex_init(&rdev->gem.mutex);
 	rwlock_init(&rdev->fence_drv.lock);
 	INIT_LIST_HEAD(&rdev->gem.objects);
 
+	/* setup workqueue */
+	rdev->wq = create_workqueue("radeon");
+	if (rdev->wq == NULL)
+		return -ENOMEM;
+
 	/* Set asic functions */
 	r = radeon_asic_init(rdev);
-	if (r) {
+	if (r)
 		return r;
+	radeon_check_arguments(rdev);
+
+	/* all of the newer IGP chips have an internal gart
+	 * However some rs4xx report as AGP, so remove that here.
+	 */
+	if ((rdev->family >= CHIP_RS400) &&
+	    (rdev->flags & RADEON_IS_IGP)) {
+		rdev->flags &= ~RADEON_IS_AGP;
 	}
 
-	if (radeon_agpmode == -1) {
+	if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
 		radeon_agp_disable(rdev);
 	}
 
@@ -620,6 +730,7 @@
 	DRM_INFO("radeon: finishing device.\n");
 	rdev->shutdown = true;
 	radeon_fini(rdev);
+	destroy_workqueue(rdev->wq);
 	vga_client_register(rdev->pdev, NULL, NULL, NULL);
 	iounmap(rdev->rmmio);
 	rdev->rmmio = NULL;
@@ -631,38 +742,48 @@
  */
 int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 {
-	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_device *rdev;
 	struct drm_crtc *crtc;
+	int r;
 
-	if (dev == NULL || rdev == NULL) {
+	if (dev == NULL || dev->dev_private == NULL) {
 		return -ENODEV;
 	}
 	if (state.event == PM_EVENT_PRETHAW) {
 		return 0;
 	}
+	rdev = dev->dev_private;
+
 	/* unpin the front buffers */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
-		struct radeon_object *robj;
+		struct radeon_bo *robj;
 
 		if (rfb == NULL || rfb->obj == NULL) {
 			continue;
 		}
 		robj = rfb->obj->driver_private;
-		if (robj != rdev->fbdev_robj) {
-			radeon_object_unpin(robj);
+		if (robj != rdev->fbdev_rbo) {
+			r = radeon_bo_reserve(robj, false);
+			if (unlikely(r == 0)) {
+				radeon_bo_unpin(robj);
+				radeon_bo_unreserve(robj);
+			}
 		}
 	}
 	/* evict vram memory */
-	radeon_object_evict_vram(rdev);
+	radeon_bo_evict_vram(rdev);
 	/* wait for gpu to finish processing current batch */
 	radeon_fence_wait_last(rdev);
 
 	radeon_save_bios_scratch_regs(rdev);
 
 	radeon_suspend(rdev);
+	radeon_hpd_fini(rdev);
 	/* evict remaining vram memory */
-	radeon_object_evict_vram(rdev);
+	radeon_bo_evict_vram(rdev);
+
+	radeon_agp_suspend(rdev);
 
 	pci_save_state(dev->pdev);
 	if (state.event == PM_EVENT_SUSPEND) {
@@ -695,6 +816,8 @@
 	fb_set_suspend(rdev->fbdev_info, 0);
 	release_console_sem();
 
+	/* reset hpd state */
+	radeon_hpd_init(rdev);
 	/* blat the mode back in */
 	drm_helper_resume_force_mode(dev);
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/radeon.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/radeon.h
@@ -28,8 +28,6 @@
 #ifndef __RADEON_H__
 #define __RADEON_H__
 
-#include "radeon_object.h"
-
 /* TODO: Here are things that needs to be done :
  *	- surface allocator & initializer : (bit like scratch reg) should
  *	  initialize HDP_ stuff on RS600, R600, R700 hw, well anythings
@@ -67,6 +65,11 @@
 #include <linux/list.h>
 #include <linux/kref.h>
 
+#include <ttm/ttm_bo_api.h>
+#include <ttm/ttm_bo_driver.h>
+#include <ttm/ttm_placement.h>
+#include <ttm/ttm_module.h>
+
 #include "radeon_family.h"
 #include "radeon_mode.h"
 #include "radeon_reg.h"
@@ -85,12 +88,15 @@
 extern int radeon_testing;
 extern int radeon_connector_table;
 extern int radeon_tv;
+extern int radeon_new_pll;
+extern int radeon_audio;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
  * symbol;
  */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
+/* RADEON_IB_POOL_SIZE must be a power of 2 */
 #define RADEON_IB_POOL_SIZE		16
 #define RADEON_DEBUGFS_MAX_NUM_FILES	32
 #define RADEONFB_CONN_LIMIT		4
@@ -157,6 +163,7 @@
 	struct list_head		created;
 	struct list_head		emited;
 	struct list_head		signaled;
+	bool				initialized;
 };
 
 struct radeon_fence {
@@ -186,76 +193,63 @@
  * Tiling registers
  */
 struct radeon_surface_reg {
-	struct radeon_object *robj;
+	struct radeon_bo *bo;
 };
 
 #define RADEON_GEM_MAX_SURFACES 8
 
 /*
- * Radeon buffer.
+ * TTM.
  */
-struct radeon_object;
+struct radeon_mman {
+	struct ttm_bo_global_ref        bo_global_ref;
+	struct ttm_global_reference	mem_global_ref;
+	struct ttm_bo_device		bdev;
+	bool				mem_global_referenced;
+	bool				initialized;
+};
+
+struct radeon_bo {
+	/* Protected by gem.mutex */
+	struct list_head		list;
+	/* Protected by tbo.reserved */
+	u32				placements[3];
+	struct ttm_placement		placement;
+	struct ttm_buffer_object	tbo;
+	struct ttm_bo_kmap_obj		kmap;
+	unsigned			pin_count;
+	void				*kptr;
+	u32				tiling_flags;
+	u32				pitch;
+	int				surface_reg;
+	/* Constant after initialization */
+	struct radeon_device		*rdev;
+	struct drm_gem_object		*gobj;
+};
 
-struct radeon_object_list {
+struct radeon_bo_list {
 	struct list_head	list;
-	struct radeon_object	*robj;
+	struct radeon_bo	*bo;
 	uint64_t		gpu_offset;
 	unsigned		rdomain;
 	unsigned		wdomain;
-	uint32_t                tiling_flags;
+	u32			tiling_flags;
 };
 
-int radeon_object_init(struct radeon_device *rdev);
-void radeon_object_fini(struct radeon_device *rdev);
-int radeon_object_create(struct radeon_device *rdev,
-			 struct drm_gem_object *gobj,
-			 unsigned long size,
-			 bool kernel,
-			 uint32_t domain,
-			 bool interruptible,
-			 struct radeon_object **robj_ptr);
-int radeon_object_kmap(struct radeon_object *robj, void **ptr);
-void radeon_object_kunmap(struct radeon_object *robj);
-void radeon_object_unref(struct radeon_object **robj);
-int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
-		      uint64_t *gpu_addr);
-void radeon_object_unpin(struct radeon_object *robj);
-int radeon_object_wait(struct radeon_object *robj);
-int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement);
-int radeon_object_evict_vram(struct radeon_device *rdev);
-int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset);
-void radeon_object_force_delete(struct radeon_device *rdev);
-void radeon_object_list_add_object(struct radeon_object_list *lobj,
-				   struct list_head *head);
-int radeon_object_list_validate(struct list_head *head, void *fence);
-void radeon_object_list_unvalidate(struct list_head *head);
-void radeon_object_list_clean(struct list_head *head);
-int radeon_object_fbdev_mmap(struct radeon_object *robj,
-			     struct vm_area_struct *vma);
-unsigned long radeon_object_size(struct radeon_object *robj);
-void radeon_object_clear_surface_reg(struct radeon_object *robj);
-int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
-			       bool force_drop);
-void radeon_object_set_tiling_flags(struct radeon_object *robj,
-				    uint32_t tiling_flags, uint32_t pitch);
-void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch);
-void radeon_bo_move_notify(struct ttm_buffer_object *bo,
-			   struct ttm_mem_reg *mem);
-void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
 /*
  * GEM objects.
  */
 struct radeon_gem {
+	struct mutex		mutex;
 	struct list_head	objects;
 };
 
 int radeon_gem_init(struct radeon_device *rdev);
 void radeon_gem_fini(struct radeon_device *rdev);
 int radeon_gem_object_create(struct radeon_device *rdev, int size,
-			     int alignment, int initial_domain,
-			     bool discardable, bool kernel,
-			     bool interruptible,
-			     struct drm_gem_object **obj);
+				int alignment, int initial_domain,
+				bool discardable, bool kernel,
+				struct drm_gem_object **obj);
 int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 			  uint64_t *gpu_addr);
 void radeon_gem_object_unpin(struct drm_gem_object *obj);
@@ -271,7 +265,7 @@
 };
 
 struct radeon_gart_table_vram {
-	struct radeon_object		*robj;
+	struct radeon_bo		*robj;
 	volatile uint32_t		*ptr;
 };
 
@@ -326,10 +320,12 @@
 	u64			real_vram_size;
 	int			vram_mtrr;
 	bool			vram_is_ddr;
+	bool                    igp_sideport_enabled;
 };
 
 int radeon_mc_setup(struct radeon_device *rdev);
-
+bool radeon_combios_sideport_present(struct radeon_device *rdev);
+bool radeon_atombios_sideport_present(struct radeon_device *rdev);
 
 /*
  * GPU scratch registers structures, functions & helpers
@@ -352,22 +348,28 @@
 	bool		sw_int;
 	/* FIXME: use a define max crtc rather than hardcode it */
 	bool		crtc_vblank_int[2];
+	/* FIXME: use defines for max hpd/dacs */
+	bool            hpd[6];
+	spinlock_t sw_lock;
+	int sw_refcount;
 };
 
 int radeon_irq_kms_init(struct radeon_device *rdev);
 void radeon_irq_kms_fini(struct radeon_device *rdev);
-
+void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev);
+void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
 
 /*
  * CP & ring.
  */
 struct radeon_ib {
 	struct list_head	list;
-	unsigned long		idx;
+	unsigned		idx;
 	uint64_t		gpu_addr;
 	struct radeon_fence	*fence;
-	uint32_t	*ptr;
+	uint32_t		*ptr;
 	uint32_t		length_dw;
+	bool			free;
 };
 
 /*
@@ -376,15 +378,14 @@
  */
 struct radeon_ib_pool {
 	struct mutex		mutex;
-	struct radeon_object	*robj;
-	struct list_head	scheduled_ibs;
+	struct radeon_bo	*robj;
 	struct radeon_ib	ibs[RADEON_IB_POOL_SIZE];
 	bool			ready;
-	DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE);
+	unsigned		head_id;
 };
 
 struct radeon_cp {
-	struct radeon_object	*ring_obj;
+	struct radeon_bo	*ring_obj;
 	volatile uint32_t	*ring;
 	unsigned		rptr;
 	unsigned		wptr;
@@ -399,8 +400,25 @@
 	bool			ready;
 };
 
+/*
+ * R6xx+ IH ring
+ */
+struct r600_ih {
+	struct radeon_bo	*ring_obj;
+	volatile uint32_t	*ring;
+	unsigned		rptr;
+	unsigned		wptr;
+	unsigned		wptr_old;
+	unsigned		ring_size;
+	uint64_t		gpu_addr;
+	uint32_t		ptr_mask;
+	spinlock_t              lock;
+	bool                    enabled;
+};
+
 struct r600_blit {
-	struct radeon_object	*shader_obj;
+	struct mutex		mutex;
+	struct radeon_bo	*shader_obj;
 	u64 shader_gpu_addr;
 	u32 vs_offset, ps_offset;
 	u32 state_offset;
@@ -430,8 +448,8 @@
  */
 struct radeon_cs_reloc {
 	struct drm_gem_object		*gobj;
-	struct radeon_object		*robj;
-	struct radeon_object_list	lobj;
+	struct radeon_bo		*robj;
+	struct radeon_bo_list		lobj;
 	uint32_t			handle;
 	uint32_t			flags;
 };
@@ -448,6 +466,7 @@
 };
 
 struct radeon_cs_parser {
+	struct device		*dev;
 	struct radeon_device	*rdev;
 	struct drm_file		*filp;
 	/* chunks */
@@ -520,6 +539,7 @@
  */
 int radeon_agp_init(struct radeon_device *rdev);
 void radeon_agp_resume(struct radeon_device *rdev);
+void radeon_agp_suspend(struct radeon_device *rdev);
 void radeon_agp_fini(struct radeon_device *rdev);
 
 
@@ -527,7 +547,7 @@
  * Writeback
  */
 struct radeon_wb {
-	struct radeon_object	*wb_obj;
+	struct radeon_bo	*wb_obj;
 	volatile uint32_t	*wb;
 	uint64_t		gpu_addr;
 };
@@ -639,6 +659,17 @@
 			       uint32_t offset, uint32_t obj_size);
 	int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
 	void (*bandwidth_update)(struct radeon_device *rdev);
+	void (*hpd_init)(struct radeon_device *rdev);
+	void (*hpd_fini)(struct radeon_device *rdev);
+	bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+	void (*hpd_set_polarity)(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+	/* ioctl hw specific callback. Some hw might want to perform special
+	 * operation on specific ioctl. For instance on wait idle some hw
+	 * might want to perform and HDP flush through MMIO as it seems that
+	 * some R6XX/R7XX hw doesn't take HDP flush into account if programmed
+	 * through ring.
+	 */
+	void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
 };
 
 /*
@@ -647,11 +678,14 @@
 struct r100_asic {
 	const unsigned	*reg_safe_bm;
 	unsigned	reg_safe_bm_size;
+	u32		hdp_cntl;
 };
 
 struct r300_asic {
 	const unsigned	*reg_safe_bm;
 	unsigned	reg_safe_bm_size;
+	u32		resync_scratch;
+	u32		hdp_cntl;
 };
 
 struct r600_asic {
@@ -727,6 +761,11 @@
 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *filp);
 
+/* VRAM scratch page for HDP bug */
+struct r700_vram_scratch {
+	struct radeon_bo		*robj;
+	volatile uint32_t		*ptr;
+};
 
 /*
  * Core structure, functions and helpers.
@@ -751,9 +790,9 @@
 	uint8_t				*bios;
 	bool				is_atom_bios;
 	uint16_t			bios_header_start;
-	struct radeon_object		*stollen_vga_memory;
+	struct radeon_bo		*stollen_vga_memory;
 	struct fb_info			*fbdev_info;
-	struct radeon_object		*fbdev_robj;
+	struct radeon_bo		*fbdev_rbo;
 	struct radeon_framebuffer	*fbdev_rfb;
 	/* Register mmio */
 	resource_size_t			rmmio_base;
@@ -791,8 +830,21 @@
 	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
 	const struct firmware *me_fw;	/* all family ME firmware */
 	const struct firmware *pfp_fw;	/* r6/700 PFP firmware */
+	const struct firmware *rlc_fw;	/* r6/700 RLC firmware */
 	struct r600_blit r600_blit;
+	struct r700_vram_scratch vram_scratch;
 	int msi_enabled; /* msi enabled */
+	struct r600_ih ih; /* r6/700 interrupt ring */
+	struct workqueue_struct *wq;
+	struct work_struct hotplug_work;
+
+	/* audio stuff */
+	struct timer_list	audio_timer;
+	int			audio_channels;
+	int			audio_rate;
+	int			audio_bits_per_sample;
+	uint8_t			audio_status_bits;
+	uint8_t			audio_category_code;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -811,7 +863,7 @@
 
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
-	if (reg < 0x10000)
+	if (reg < rdev->rmmio_size)
 		return readl(((void __iomem *)rdev->rmmio) + reg);
 	else {
 		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -821,7 +873,7 @@
 
 static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-	if (reg < 0x10000)
+	if (reg < rdev->rmmio_size)
 		writel(v, ((void __iomem *)rdev->rmmio) + reg);
 	else {
 		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -829,6 +881,10 @@
 	}
 }
 
+/*
+ * Cast helper
+ */
+#define to_radeon_fence(p) ((struct radeon_fence *)(p))
 
 /*
  * Registers read & write functions.
@@ -965,18 +1021,25 @@
 #define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev))
 #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
 #define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
-#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
+#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e))
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
 #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
 #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
 #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
 #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
+#define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev))
+#define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev))
+#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
+#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
 
 /* Common functions */
+/* AGP */
+extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
+extern bool radeon_boot_test_post_card(struct radeon_device *rdev);
 extern int radeon_clocks_init(struct radeon_device *rdev);
 extern void radeon_clocks_fini(struct radeon_device *rdev);
 extern void radeon_scratch_init(struct radeon_device *rdev);
@@ -984,6 +1047,8 @@
 extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
 extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
+extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
+extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
 
 /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
 struct r100_mc_save {
@@ -1021,7 +1086,7 @@
 extern void r100_vga_render_disable(struct radeon_device *rdev);
 extern int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
 						struct radeon_cs_packet *pkt,
-						struct radeon_object *robj);
+						struct radeon_bo *robj);
 extern int r100_cs_parse_packet0(struct radeon_cs_parser *p,
 				struct radeon_cs_packet *pkt,
 				const unsigned *auth, unsigned n,
@@ -1029,6 +1094,8 @@
 extern int r100_cs_packet_parse(struct radeon_cs_parser *p,
 				struct radeon_cs_packet *pkt,
 				unsigned idx);
+extern void r100_enable_bm(struct radeon_device *rdev);
+extern void r100_set_common_regs(struct radeon_device *rdev);
 
 /* rv200,rv250,rv280 */
 extern void r200_set_safe_registers(struct radeon_device *rdev);
@@ -1091,6 +1158,7 @@
 extern void r600_cp_stop(struct radeon_device *rdev);
 extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
 extern int r600_cp_resume(struct radeon_device *rdev);
+extern void r600_cp_fini(struct radeon_device *rdev);
 extern int r600_count_pipe_bits(uint32_t val);
 extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
 extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
@@ -1104,7 +1172,30 @@
 extern void r600_scratch_init(struct radeon_device *rdev);
 extern int r600_blit_init(struct radeon_device *rdev);
 extern void r600_blit_fini(struct radeon_device *rdev);
-extern int r600_cp_init_microcode(struct radeon_device *rdev);
+extern int r600_init_microcode(struct radeon_device *rdev);
 extern int r600_gpu_reset(struct radeon_device *rdev);
+/* r600 irq */
+extern int r600_irq_init(struct radeon_device *rdev);
+extern void r600_irq_fini(struct radeon_device *rdev);
+extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
+extern int r600_irq_set(struct radeon_device *rdev);
+extern void r600_irq_suspend(struct radeon_device *rdev);
+/* r600 audio */
+extern int r600_audio_init(struct radeon_device *rdev);
+extern int r600_audio_tmds_index(struct drm_encoder *encoder);
+extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
+extern void r600_audio_fini(struct radeon_device *rdev);
+extern void r600_hdmi_init(struct drm_encoder *encoder);
+extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable);
+extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
+extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
+extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
+					    int channels,
+					    int rate,
+					    int bps,
+					    uint8_t status_bits,
+					    uint8_t category_code);
+
+#include "radeon_object.h"
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/reg_srcs/r300
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/reg_srcs/r300
@@ -705,9 +705,6 @@
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4F04 ZB_ZSTENCILCNTL
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/reg_srcs/r200
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/reg_srcs/r200
@@ -91,6 +91,8 @@
 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL
 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL
 0x22c4 SE_TCL_POINT_SPRITE_CNTL
+0x22d0 SE_PVS_CNTL
+0x22d4 SE_PVS_CONST_CNTL
 0x2648 RE_POINTSIZE
 0x26c0 RE_TOP_LEFT
 0x26c4 RE_MISC
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/reg_srcs/rs600
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/reg_srcs/rs600
@@ -153,7 +153,7 @@
 0x42A4 SU_POLY_OFFSET_FRONT_SCALE
 0x42A8 SU_POLY_OFFSET_FRONT_OFFSET
 0x42AC SU_POLY_OFFSET_BACK_SCALE
-0x42B0 SU_POLY_OFFSET_BACK_OFFSET 
+0x42B0 SU_POLY_OFFSET_BACK_OFFSET
 0x42B4 SU_POLY_OFFSET_ENABLE
 0x42B8 SU_CULL_MODE
 0x42C0 SU_DEPTH_SCALE
@@ -291,6 +291,8 @@
 0x46AC US_OUT_FMT_2
 0x46B0 US_OUT_FMT_3
 0x46B4 US_W_FMT
+0x46B8 US_CODE_BANK
+0x46BC US_CODE_EXT
 0x46C0 US_ALU_RGB_ADDR_0
 0x46C4 US_ALU_RGB_ADDR_1
 0x46C8 US_ALU_RGB_ADDR_2
@@ -547,6 +549,70 @@
 0x4AB4 US_ALU_ALPHA_INST_61
 0x4AB8 US_ALU_ALPHA_INST_62
 0x4ABC US_ALU_ALPHA_INST_63
+0x4AC0 US_ALU_EXT_ADDR_0
+0x4AC4 US_ALU_EXT_ADDR_1
+0x4AC8 US_ALU_EXT_ADDR_2
+0x4ACC US_ALU_EXT_ADDR_3
+0x4AD0 US_ALU_EXT_ADDR_4
+0x4AD4 US_ALU_EXT_ADDR_5
+0x4AD8 US_ALU_EXT_ADDR_6
+0x4ADC US_ALU_EXT_ADDR_7
+0x4AE0 US_ALU_EXT_ADDR_8
+0x4AE4 US_ALU_EXT_ADDR_9
+0x4AE8 US_ALU_EXT_ADDR_10
+0x4AEC US_ALU_EXT_ADDR_11
+0x4AF0 US_ALU_EXT_ADDR_12
+0x4AF4 US_ALU_EXT_ADDR_13
+0x4AF8 US_ALU_EXT_ADDR_14
+0x4AFC US_ALU_EXT_ADDR_15
+0x4B00 US_ALU_EXT_ADDR_16
+0x4B04 US_ALU_EXT_ADDR_17
+0x4B08 US_ALU_EXT_ADDR_18
+0x4B0C US_ALU_EXT_ADDR_19
+0x4B10 US_ALU_EXT_ADDR_20
+0x4B14 US_ALU_EXT_ADDR_21
+0x4B18 US_ALU_EXT_ADDR_22
+0x4B1C US_ALU_EXT_ADDR_23
+0x4B20 US_ALU_EXT_ADDR_24
+0x4B24 US_ALU_EXT_ADDR_25
+0x4B28 US_ALU_EXT_ADDR_26
+0x4B2C US_ALU_EXT_ADDR_27
+0x4B30 US_ALU_EXT_ADDR_28
+0x4B34 US_ALU_EXT_ADDR_29
+0x4B38 US_ALU_EXT_ADDR_30
+0x4B3C US_ALU_EXT_ADDR_31
+0x4B40 US_ALU_EXT_ADDR_32
+0x4B44 US_ALU_EXT_ADDR_33
+0x4B48 US_ALU_EXT_ADDR_34
+0x4B4C US_ALU_EXT_ADDR_35
+0x4B50 US_ALU_EXT_ADDR_36
+0x4B54 US_ALU_EXT_ADDR_37
+0x4B58 US_ALU_EXT_ADDR_38
+0x4B5C US_ALU_EXT_ADDR_39
+0x4B60 US_ALU_EXT_ADDR_40
+0x4B64 US_ALU_EXT_ADDR_41
+0x4B68 US_ALU_EXT_ADDR_42
+0x4B6C US_ALU_EXT_ADDR_43
+0x4B70 US_ALU_EXT_ADDR_44
+0x4B74 US_ALU_EXT_ADDR_45
+0x4B78 US_ALU_EXT_ADDR_46
+0x4B7C US_ALU_EXT_ADDR_47
+0x4B80 US_ALU_EXT_ADDR_48
+0x4B84 US_ALU_EXT_ADDR_49
+0x4B88 US_ALU_EXT_ADDR_50
+0x4B8C US_ALU_EXT_ADDR_51
+0x4B90 US_ALU_EXT_ADDR_52
+0x4B94 US_ALU_EXT_ADDR_53
+0x4B98 US_ALU_EXT_ADDR_54
+0x4B9C US_ALU_EXT_ADDR_55
+0x4BA0 US_ALU_EXT_ADDR_56
+0x4BA4 US_ALU_EXT_ADDR_57
+0x4BA8 US_ALU_EXT_ADDR_58
+0x4BAC US_ALU_EXT_ADDR_59
+0x4BB0 US_ALU_EXT_ADDR_60
+0x4BB4 US_ALU_EXT_ADDR_61
+0x4BB8 US_ALU_EXT_ADDR_62
+0x4BBC US_ALU_EXT_ADDR_63
 0x4BC0 FG_FOG_BLEND
 0x4BC4 FG_FOG_FACTOR
 0x4BC8 FG_FOG_COLOR_R
@@ -705,9 +771,6 @@
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4F04 ZB_ZSTENCILCNTL
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/reg_srcs/r420
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/reg_srcs/r420
@@ -0,0 +1,792 @@
+r420 0x4f60
+0x1434 SRC_Y_X
+0x1438 DST_Y_X
+0x143C DST_HEIGHT_WIDTH
+0x146C DP_GUI_MASTER_CNTL
+0x1474 BRUSH_Y_X
+0x1478 DP_BRUSH_BKGD_CLR
+0x147C DP_BRUSH_FRGD_CLR
+0x1480 BRUSH_DATA0
+0x1484 BRUSH_DATA1
+0x1598 DST_WIDTH_HEIGHT
+0x15C0 CLR_CMP_CNTL
+0x15C4 CLR_CMP_CLR_SRC
+0x15C8 CLR_CMP_CLR_DST
+0x15CC CLR_CMP_MSK
+0x15D8 DP_SRC_FRGD_CLR
+0x15DC DP_SRC_BKGD_CLR
+0x1600 DST_LINE_START
+0x1604 DST_LINE_END
+0x1608 DST_LINE_PATCOUNT
+0x16C0 DP_CNTL
+0x16CC DP_WRITE_MSK
+0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR
+0x16E8 DEFAULT_SC_BOTTOM_RIGHT
+0x16EC SC_TOP_LEFT
+0x16F0 SC_BOTTOM_RIGHT
+0x16F4 SRC_SC_BOTTOM_RIGHT
+0x1714 DSTCACHE_CTLSTAT
+0x1720 WAIT_UNTIL
+0x172C RBBM_GUICNTL
+0x1D98 VAP_VPORT_XSCALE
+0x1D9C VAP_VPORT_XOFFSET
+0x1DA0 VAP_VPORT_YSCALE
+0x1DA4 VAP_VPORT_YOFFSET
+0x1DA8 VAP_VPORT_ZSCALE
+0x1DAC VAP_VPORT_ZOFFSET
+0x2080 VAP_CNTL
+0x2090 VAP_OUT_VTX_FMT_0
+0x2094 VAP_OUT_VTX_FMT_1
+0x20B0 VAP_VTE_CNTL
+0x2138 VAP_VF_MIN_VTX_INDX
+0x2140 VAP_CNTL_STATUS
+0x2150 VAP_PROG_STREAM_CNTL_0
+0x2154 VAP_PROG_STREAM_CNTL_1
+0x2158 VAP_PROG_STREAM_CNTL_2
+0x215C VAP_PROG_STREAM_CNTL_3
+0x2160 VAP_PROG_STREAM_CNTL_4
+0x2164 VAP_PROG_STREAM_CNTL_5
+0x2168 VAP_PROG_STREAM_CNTL_6
+0x216C VAP_PROG_STREAM_CNTL_7
+0x2180 VAP_VTX_STATE_CNTL
+0x2184 VAP_VSM_VTX_ASSM
+0x2188 VAP_VTX_STATE_IND_REG_0
+0x218C VAP_VTX_STATE_IND_REG_1
+0x2190 VAP_VTX_STATE_IND_REG_2
+0x2194 VAP_VTX_STATE_IND_REG_3
+0x2198 VAP_VTX_STATE_IND_REG_4
+0x219C VAP_VTX_STATE_IND_REG_5
+0x21A0 VAP_VTX_STATE_IND_REG_6
+0x21A4 VAP_VTX_STATE_IND_REG_7
+0x21A8 VAP_VTX_STATE_IND_REG_8
+0x21AC VAP_VTX_STATE_IND_REG_9
+0x21B0 VAP_VTX_STATE_IND_REG_10
+0x21B4 VAP_VTX_STATE_IND_REG_11
+0x21B8 VAP_VTX_STATE_IND_REG_12
+0x21BC VAP_VTX_STATE_IND_REG_13
+0x21C0 VAP_VTX_STATE_IND_REG_14
+0x21C4 VAP_VTX_STATE_IND_REG_15
+0x21DC VAP_PSC_SGN_NORM_CNTL
+0x21E0 VAP_PROG_STREAM_CNTL_EXT_0
+0x21E4 VAP_PROG_STREAM_CNTL_EXT_1
+0x21E8 VAP_PROG_STREAM_CNTL_EXT_2
+0x21EC VAP_PROG_STREAM_CNTL_EXT_3
+0x21F0 VAP_PROG_STREAM_CNTL_EXT_4
+0x21F4 VAP_PROG_STREAM_CNTL_EXT_5
+0x21F8 VAP_PROG_STREAM_CNTL_EXT_6
+0x21FC VAP_PROG_STREAM_CNTL_EXT_7
+0x2200 VAP_PVS_VECTOR_INDX_REG
+0x2204 VAP_PVS_VECTOR_DATA_REG
+0x2208 VAP_PVS_VECTOR_DATA_REG_128
+0x221C VAP_CLIP_CNTL
+0x2220 VAP_GB_VERT_CLIP_ADJ
+0x2224 VAP_GB_VERT_DISC_ADJ
+0x2228 VAP_GB_HORZ_CLIP_ADJ
+0x222C VAP_GB_HORZ_DISC_ADJ
+0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0
+0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1
+0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2
+0x223C VAP_PVS_FLOW_CNTL_ADDRS_3
+0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4
+0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5
+0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6
+0x224C VAP_PVS_FLOW_CNTL_ADDRS_7
+0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8
+0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9
+0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10
+0x225C VAP_PVS_FLOW_CNTL_ADDRS_11
+0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12
+0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13
+0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14
+0x226C VAP_PVS_FLOW_CNTL_ADDRS_15
+0x2284 VAP_PVS_STATE_FLUSH_REG
+0x2288 VAP_PVS_VTX_TIMEOUT_REG
+0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0
+0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1
+0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2
+0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3
+0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4
+0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5
+0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6
+0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7
+0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8
+0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9
+0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10
+0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11
+0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12
+0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13
+0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14
+0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15
+0x22D0 VAP_PVS_CODE_CNTL_0
+0x22D4 VAP_PVS_CONST_CNTL
+0x22D8 VAP_PVS_CODE_CNTL_1
+0x22DC VAP_PVS_FLOW_CNTL_OPC
+0x342C RB2D_DSTCACHE_CTLSTAT
+0x4000 GB_VAP_RASTER_VTX_FMT_0
+0x4004 GB_VAP_RASTER_VTX_FMT_1
+0x4008 GB_ENABLE
+0x401C GB_SELECT
+0x4020 GB_AA_CONFIG
+0x4024 GB_FIFO_SIZE
+0x4100 TX_INVALTAGS
+0x4200 GA_POINT_S0
+0x4204 GA_POINT_T0
+0x4208 GA_POINT_S1
+0x420C GA_POINT_T1
+0x4214 GA_TRIANGLE_STIPPLE
+0x421C GA_POINT_SIZE
+0x4230 GA_POINT_MINMAX
+0x4234 GA_LINE_CNTL
+0x4238 GA_LINE_STIPPLE_CONFIG
+0x4260 GA_LINE_STIPPLE_VALUE
+0x4264 GA_LINE_S0
+0x4268 GA_LINE_S1
+0x4278 GA_COLOR_CONTROL
+0x427C GA_SOLID_RG
+0x4280 GA_SOLID_BA
+0x4288 GA_POLY_MODE
+0x428C GA_ROUND_MODE
+0x4290 GA_OFFSET
+0x4294 GA_FOG_SCALE
+0x4298 GA_FOG_OFFSET
+0x42A0 SU_TEX_WRAP
+0x42A4 SU_POLY_OFFSET_FRONT_SCALE
+0x42A8 SU_POLY_OFFSET_FRONT_OFFSET
+0x42AC SU_POLY_OFFSET_BACK_SCALE
+0x42B0 SU_POLY_OFFSET_BACK_OFFSET
+0x42B4 SU_POLY_OFFSET_ENABLE
+0x42B8 SU_CULL_MODE
+0x42C0 SU_DEPTH_SCALE
+0x42C4 SU_DEPTH_OFFSET
+0x42C8 SU_REG_DEST
+0x4300 RS_COUNT
+0x4304 RS_INST_COUNT
+0x4310 RS_IP_0
+0x4314 RS_IP_1
+0x4318 RS_IP_2
+0x431C RS_IP_3
+0x4320 RS_IP_4
+0x4324 RS_IP_5
+0x4328 RS_IP_6
+0x432C RS_IP_7
+0x4330 RS_INST_0
+0x4334 RS_INST_1
+0x4338 RS_INST_2
+0x433C RS_INST_3
+0x4340 RS_INST_4
+0x4344 RS_INST_5
+0x4348 RS_INST_6
+0x434C RS_INST_7
+0x4350 RS_INST_8
+0x4354 RS_INST_9
+0x4358 RS_INST_10
+0x435C RS_INST_11
+0x4360 RS_INST_12
+0x4364 RS_INST_13
+0x4368 RS_INST_14
+0x436C RS_INST_15
+0x43A4 SC_HYPERZ_EN
+0x43A8 SC_EDGERULE
+0x43B0 SC_CLIP_0_A
+0x43B4 SC_CLIP_0_B
+0x43B8 SC_CLIP_1_A
+0x43BC SC_CLIP_1_B
+0x43C0 SC_CLIP_2_A
+0x43C4 SC_CLIP_2_B
+0x43C8 SC_CLIP_3_A
+0x43CC SC_CLIP_3_B
+0x43D0 SC_CLIP_RULE
+0x43E0 SC_SCISSOR0
+0x43E8 SC_SCREENDOOR
+0x4440 TX_FILTER1_0
+0x4444 TX_FILTER1_1
+0x4448 TX_FILTER1_2
+0x444C TX_FILTER1_3
+0x4450 TX_FILTER1_4
+0x4454 TX_FILTER1_5
+0x4458 TX_FILTER1_6
+0x445C TX_FILTER1_7
+0x4460 TX_FILTER1_8
+0x4464 TX_FILTER1_9
+0x4468 TX_FILTER1_10
+0x446C TX_FILTER1_11
+0x4470 TX_FILTER1_12
+0x4474 TX_FILTER1_13
+0x4478 TX_FILTER1_14
+0x447C TX_FILTER1_15
+0x4580 TX_CHROMA_KEY_0
+0x4584 TX_CHROMA_KEY_1
+0x4588 TX_CHROMA_KEY_2
+0x458C TX_CHROMA_KEY_3
+0x4590 TX_CHROMA_KEY_4
+0x4594 TX_CHROMA_KEY_5
+0x4598 TX_CHROMA_KEY_6
+0x459C TX_CHROMA_KEY_7
+0x45A0 TX_CHROMA_KEY_8
+0x45A4 TX_CHROMA_KEY_9
+0x45A8 TX_CHROMA_KEY_10
+0x45AC TX_CHROMA_KEY_11
+0x45B0 TX_CHROMA_KEY_12
+0x45B4 TX_CHROMA_KEY_13
+0x45B8 TX_CHROMA_KEY_14
+0x45BC TX_CHROMA_KEY_15
+0x45C0 TX_BORDER_COLOR_0
+0x45C4 TX_BORDER_COLOR_1
+0x45C8 TX_BORDER_COLOR_2
+0x45CC TX_BORDER_COLOR_3
+0x45D0 TX_BORDER_COLOR_4
+0x45D4 TX_BORDER_COLOR_5
+0x45D8 TX_BORDER_COLOR_6
+0x45DC TX_BORDER_COLOR_7
+0x45E0 TX_BORDER_COLOR_8
+0x45E4 TX_BORDER_COLOR_9
+0x45E8 TX_BORDER_COLOR_10
+0x45EC TX_BORDER_COLOR_11
+0x45F0 TX_BORDER_COLOR_12
+0x45F4 TX_BORDER_COLOR_13
+0x45F8 TX_BORDER_COLOR_14
+0x45FC TX_BORDER_COLOR_15
+0x4600 US_CONFIG
+0x4604 US_PIXSIZE
+0x4608 US_CODE_OFFSET
+0x460C US_RESET
+0x4610 US_CODE_ADDR_0
+0x4614 US_CODE_ADDR_1
+0x4618 US_CODE_ADDR_2
+0x461C US_CODE_ADDR_3
+0x4620 US_TEX_INST_0
+0x4624 US_TEX_INST_1
+0x4628 US_TEX_INST_2
+0x462C US_TEX_INST_3
+0x4630 US_TEX_INST_4
+0x4634 US_TEX_INST_5
+0x4638 US_TEX_INST_6
+0x463C US_TEX_INST_7
+0x4640 US_TEX_INST_8
+0x4644 US_TEX_INST_9
+0x4648 US_TEX_INST_10
+0x464C US_TEX_INST_11
+0x4650 US_TEX_INST_12
+0x4654 US_TEX_INST_13
+0x4658 US_TEX_INST_14
+0x465C US_TEX_INST_15
+0x4660 US_TEX_INST_16
+0x4664 US_TEX_INST_17
+0x4668 US_TEX_INST_18
+0x466C US_TEX_INST_19
+0x4670 US_TEX_INST_20
+0x4674 US_TEX_INST_21
+0x4678 US_TEX_INST_22
+0x467C US_TEX_INST_23
+0x4680 US_TEX_INST_24
+0x4684 US_TEX_INST_25
+0x4688 US_TEX_INST_26
+0x468C US_TEX_INST_27
+0x4690 US_TEX_INST_28
+0x4694 US_TEX_INST_29
+0x4698 US_TEX_INST_30
+0x469C US_TEX_INST_31
+0x46A4 US_OUT_FMT_0
+0x46A8 US_OUT_FMT_1
+0x46AC US_OUT_FMT_2
+0x46B0 US_OUT_FMT_3
+0x46B4 US_W_FMT
+0x46B8 US_CODE_BANK
+0x46BC US_CODE_EXT
+0x46C0 US_ALU_RGB_ADDR_0
+0x46C4 US_ALU_RGB_ADDR_1
+0x46C8 US_ALU_RGB_ADDR_2
+0x46CC US_ALU_RGB_ADDR_3
+0x46D0 US_ALU_RGB_ADDR_4
+0x46D4 US_ALU_RGB_ADDR_5
+0x46D8 US_ALU_RGB_ADDR_6
+0x46DC US_ALU_RGB_ADDR_7
+0x46E0 US_ALU_RGB_ADDR_8
+0x46E4 US_ALU_RGB_ADDR_9
+0x46E8 US_ALU_RGB_ADDR_10
+0x46EC US_ALU_RGB_ADDR_11
+0x46F0 US_ALU_RGB_ADDR_12
+0x46F4 US_ALU_RGB_ADDR_13
+0x46F8 US_ALU_RGB_ADDR_14
+0x46FC US_ALU_RGB_ADDR_15
+0x4700 US_ALU_RGB_ADDR_16
+0x4704 US_ALU_RGB_ADDR_17
+0x4708 US_ALU_RGB_ADDR_18
+0x470C US_ALU_RGB_ADDR_19
+0x4710 US_ALU_RGB_ADDR_20
+0x4714 US_ALU_RGB_ADDR_21
+0x4718 US_ALU_RGB_ADDR_22
+0x471C US_ALU_RGB_ADDR_23
+0x4720 US_ALU_RGB_ADDR_24
+0x4724 US_ALU_RGB_ADDR_25
+0x4728 US_ALU_RGB_ADDR_26
+0x472C US_ALU_RGB_ADDR_27
+0x4730 US_ALU_RGB_ADDR_28
+0x4734 US_ALU_RGB_ADDR_29
+0x4738 US_ALU_RGB_ADDR_30
+0x473C US_ALU_RGB_ADDR_31
+0x4740 US_ALU_RGB_ADDR_32
+0x4744 US_ALU_RGB_ADDR_33
+0x4748 US_ALU_RGB_ADDR_34
+0x474C US_ALU_RGB_ADDR_35
+0x4750 US_ALU_RGB_ADDR_36
+0x4754 US_ALU_RGB_ADDR_37
+0x4758 US_ALU_RGB_ADDR_38
+0x475C US_ALU_RGB_ADDR_39
+0x4760 US_ALU_RGB_ADDR_40
+0x4764 US_ALU_RGB_ADDR_41
+0x4768 US_ALU_RGB_ADDR_42
+0x476C US_ALU_RGB_ADDR_43
+0x4770 US_ALU_RGB_ADDR_44
+0x4774 US_ALU_RGB_ADDR_45
+0x4778 US_ALU_RGB_ADDR_46
+0x477C US_ALU_RGB_ADDR_47
+0x4780 US_ALU_RGB_ADDR_48
+0x4784 US_ALU_RGB_ADDR_49
+0x4788 US_ALU_RGB_ADDR_50
+0x478C US_ALU_RGB_ADDR_51
+0x4790 US_ALU_RGB_ADDR_52
+0x4794 US_ALU_RGB_ADDR_53
+0x4798 US_ALU_RGB_ADDR_54
+0x479C US_ALU_RGB_ADDR_55
+0x47A0 US_ALU_RGB_ADDR_56
+0x47A4 US_ALU_RGB_ADDR_57
+0x47A8 US_ALU_RGB_ADDR_58
+0x47AC US_ALU_RGB_ADDR_59
+0x47B0 US_ALU_RGB_ADDR_60
+0x47B4 US_ALU_RGB_ADDR_61
+0x47B8 US_ALU_RGB_ADDR_62
+0x47BC US_ALU_RGB_ADDR_63
+0x47C0 US_ALU_ALPHA_ADDR_0
+0x47C4 US_ALU_ALPHA_ADDR_1
+0x47C8 US_ALU_ALPHA_ADDR_2
+0x47CC US_ALU_ALPHA_ADDR_3
+0x47D0 US_ALU_ALPHA_ADDR_4
+0x47D4 US_ALU_ALPHA_ADDR_5
+0x47D8 US_ALU_ALPHA_ADDR_6
+0x47DC US_ALU_ALPHA_ADDR_7
+0x47E0 US_ALU_ALPHA_ADDR_8
+0x47E4 US_ALU_ALPHA_ADDR_9
+0x47E8 US_ALU_ALPHA_ADDR_10
+0x47EC US_ALU_ALPHA_ADDR_11
+0x47F0 US_ALU_ALPHA_ADDR_12
+0x47F4 US_ALU_ALPHA_ADDR_13
+0x47F8 US_ALU_ALPHA_ADDR_14
+0x47FC US_ALU_ALPHA_ADDR_15
+0x4800 US_ALU_ALPHA_ADDR_16
+0x4804 US_ALU_ALPHA_ADDR_17
+0x4808 US_ALU_ALPHA_ADDR_18
+0x480C US_ALU_ALPHA_ADDR_19
+0x4810 US_ALU_ALPHA_ADDR_20
+0x4814 US_ALU_ALPHA_ADDR_21
+0x4818 US_ALU_ALPHA_ADDR_22
+0x481C US_ALU_ALPHA_ADDR_23
+0x4820 US_ALU_ALPHA_ADDR_24
+0x4824 US_ALU_ALPHA_ADDR_25
+0x4828 US_ALU_ALPHA_ADDR_26
+0x482C US_ALU_ALPHA_ADDR_27
+0x4830 US_ALU_ALPHA_ADDR_28
+0x4834 US_ALU_ALPHA_ADDR_29
+0x4838 US_ALU_ALPHA_ADDR_30
+0x483C US_ALU_ALPHA_ADDR_31
+0x4840 US_ALU_ALPHA_ADDR_32
+0x4844 US_ALU_ALPHA_ADDR_33
+0x4848 US_ALU_ALPHA_ADDR_34
+0x484C US_ALU_ALPHA_ADDR_35
+0x4850 US_ALU_ALPHA_ADDR_36
+0x4854 US_ALU_ALPHA_ADDR_37
+0x4858 US_ALU_ALPHA_ADDR_38
+0x485C US_ALU_ALPHA_ADDR_39
+0x4860 US_ALU_ALPHA_ADDR_40
+0x4864 US_ALU_ALPHA_ADDR_41
+0x4868 US_ALU_ALPHA_ADDR_42
+0x486C US_ALU_ALPHA_ADDR_43
+0x4870 US_ALU_ALPHA_ADDR_44
+0x4874 US_ALU_ALPHA_ADDR_45
+0x4878 US_ALU_ALPHA_ADDR_46
+0x487C US_ALU_ALPHA_ADDR_47
+0x4880 US_ALU_ALPHA_ADDR_48
+0x4884 US_ALU_ALPHA_ADDR_49
+0x4888 US_ALU_ALPHA_ADDR_50
+0x488C US_ALU_ALPHA_ADDR_51
+0x4890 US_ALU_ALPHA_ADDR_52
+0x4894 US_ALU_ALPHA_ADDR_53
+0x4898 US_ALU_ALPHA_ADDR_54
+0x489C US_ALU_ALPHA_ADDR_55
+0x48A0 US_ALU_ALPHA_ADDR_56
+0x48A4 US_ALU_ALPHA_ADDR_57
+0x48A8 US_ALU_ALPHA_ADDR_58
+0x48AC US_ALU_ALPHA_ADDR_59
+0x48B0 US_ALU_ALPHA_ADDR_60
+0x48B4 US_ALU_ALPHA_ADDR_61
+0x48B8 US_ALU_ALPHA_ADDR_62
+0x48BC US_ALU_ALPHA_ADDR_63
+0x48C0 US_ALU_RGB_INST_0
+0x48C4 US_ALU_RGB_INST_1
+0x48C8 US_ALU_RGB_INST_2
+0x48CC US_ALU_RGB_INST_3
+0x48D0 US_ALU_RGB_INST_4
+0x48D4 US_ALU_RGB_INST_5
+0x48D8 US_ALU_RGB_INST_6
+0x48DC US_ALU_RGB_INST_7
+0x48E0 US_ALU_RGB_INST_8
+0x48E4 US_ALU_RGB_INST_9
+0x48E8 US_ALU_RGB_INST_10
+0x48EC US_ALU_RGB_INST_11
+0x48F0 US_ALU_RGB_INST_12
+0x48F4 US_ALU_RGB_INST_13
+0x48F8 US_ALU_RGB_INST_14
+0x48FC US_ALU_RGB_INST_15
+0x4900 US_ALU_RGB_INST_16
+0x4904 US_ALU_RGB_INST_17
+0x4908 US_ALU_RGB_INST_18
+0x490C US_ALU_RGB_INST_19
+0x4910 US_ALU_RGB_INST_20
+0x4914 US_ALU_RGB_INST_21
+0x4918 US_ALU_RGB_INST_22
+0x491C US_ALU_RGB_INST_23
+0x4920 US_ALU_RGB_INST_24
+0x4924 US_ALU_RGB_INST_25
+0x4928 US_ALU_RGB_INST_26
+0x492C US_ALU_RGB_INST_27
+0x4930 US_ALU_RGB_INST_28
+0x4934 US_ALU_RGB_INST_29
+0x4938 US_ALU_RGB_INST_30
+0x493C US_ALU_RGB_INST_31
+0x4940 US_ALU_RGB_INST_32
+0x4944 US_ALU_RGB_INST_33
+0x4948 US_ALU_RGB_INST_34
+0x494C US_ALU_RGB_INST_35
+0x4950 US_ALU_RGB_INST_36
+0x4954 US_ALU_RGB_INST_37
+0x4958 US_ALU_RGB_INST_38
+0x495C US_ALU_RGB_INST_39
+0x4960 US_ALU_RGB_INST_40
+0x4964 US_ALU_RGB_INST_41
+0x4968 US_ALU_RGB_INST_42
+0x496C US_ALU_RGB_INST_43
+0x4970 US_ALU_RGB_INST_44
+0x4974 US_ALU_RGB_INST_45
+0x4978 US_ALU_RGB_INST_46
+0x497C US_ALU_RGB_INST_47
+0x4980 US_ALU_RGB_INST_48
+0x4984 US_ALU_RGB_INST_49
+0x4988 US_ALU_RGB_INST_50
+0x498C US_ALU_RGB_INST_51
+0x4990 US_ALU_RGB_INST_52
+0x4994 US_ALU_RGB_INST_53
+0x4998 US_ALU_RGB_INST_54
+0x499C US_ALU_RGB_INST_55
+0x49A0 US_ALU_RGB_INST_56
+0x49A4 US_ALU_RGB_INST_57
+0x49A8 US_ALU_RGB_INST_58
+0x49AC US_ALU_RGB_INST_59
+0x49B0 US_ALU_RGB_INST_60
+0x49B4 US_ALU_RGB_INST_61
+0x49B8 US_ALU_RGB_INST_62
+0x49BC US_ALU_RGB_INST_63
+0x49C0 US_ALU_ALPHA_INST_0
+0x49C4 US_ALU_ALPHA_INST_1
+0x49C8 US_ALU_ALPHA_INST_2
+0x49CC US_ALU_ALPHA_INST_3
+0x49D0 US_ALU_ALPHA_INST_4
+0x49D4 US_ALU_ALPHA_INST_5
+0x49D8 US_ALU_ALPHA_INST_6
+0x49DC US_ALU_ALPHA_INST_7
+0x49E0 US_ALU_ALPHA_INST_8
+0x49E4 US_ALU_ALPHA_INST_9
+0x49E8 US_ALU_ALPHA_INST_10
+0x49EC US_ALU_ALPHA_INST_11
+0x49F0 US_ALU_ALPHA_INST_12
+0x49F4 US_ALU_ALPHA_INST_13
+0x49F8 US_ALU_ALPHA_INST_14
+0x49FC US_ALU_ALPHA_INST_15
+0x4A00 US_ALU_ALPHA_INST_16
+0x4A04 US_ALU_ALPHA_INST_17
+0x4A08 US_ALU_ALPHA_INST_18
+0x4A0C US_ALU_ALPHA_INST_19
+0x4A10 US_ALU_ALPHA_INST_20
+0x4A14 US_ALU_ALPHA_INST_21
+0x4A18 US_ALU_ALPHA_INST_22
+0x4A1C US_ALU_ALPHA_INST_23
+0x4A20 US_ALU_ALPHA_INST_24
+0x4A24 US_ALU_ALPHA_INST_25
+0x4A28 US_ALU_ALPHA_INST_26
+0x4A2C US_ALU_ALPHA_INST_27
+0x4A30 US_ALU_ALPHA_INST_28
+0x4A34 US_ALU_ALPHA_INST_29
+0x4A38 US_ALU_ALPHA_INST_30
+0x4A3C US_ALU_ALPHA_INST_31
+0x4A40 US_ALU_ALPHA_INST_32
+0x4A44 US_ALU_ALPHA_INST_33
+0x4A48 US_ALU_ALPHA_INST_34
+0x4A4C US_ALU_ALPHA_INST_35
+0x4A50 US_ALU_ALPHA_INST_36
+0x4A54 US_ALU_ALPHA_INST_37
+0x4A58 US_ALU_ALPHA_INST_38
+0x4A5C US_ALU_ALPHA_INST_39
+0x4A60 US_ALU_ALPHA_INST_40
+0x4A64 US_ALU_ALPHA_INST_41
+0x4A68 US_ALU_ALPHA_INST_42
+0x4A6C US_ALU_ALPHA_INST_43
+0x4A70 US_ALU_ALPHA_INST_44
+0x4A74 US_ALU_ALPHA_INST_45
+0x4A78 US_ALU_ALPHA_INST_46
+0x4A7C US_ALU_ALPHA_INST_47
+0x4A80 US_ALU_ALPHA_INST_48
+0x4A84 US_ALU_ALPHA_INST_49
+0x4A88 US_ALU_ALPHA_INST_50
+0x4A8C US_ALU_ALPHA_INST_51
+0x4A90 US_ALU_ALPHA_INST_52
+0x4A94 US_ALU_ALPHA_INST_53
+0x4A98 US_ALU_ALPHA_INST_54
+0x4A9C US_ALU_ALPHA_INST_55
+0x4AA0 US_ALU_ALPHA_INST_56
+0x4AA4 US_ALU_ALPHA_INST_57
+0x4AA8 US_ALU_ALPHA_INST_58
+0x4AAC US_ALU_ALPHA_INST_59
+0x4AB0 US_ALU_ALPHA_INST_60
+0x4AB4 US_ALU_ALPHA_INST_61
+0x4AB8 US_ALU_ALPHA_INST_62
+0x4ABC US_ALU_ALPHA_INST_63
+0x4AC0 US_ALU_EXT_ADDR_0
+0x4AC4 US_ALU_EXT_ADDR_1
+0x4AC8 US_ALU_EXT_ADDR_2
+0x4ACC US_ALU_EXT_ADDR_3
+0x4AD0 US_ALU_EXT_ADDR_4
+0x4AD4 US_ALU_EXT_ADDR_5
+0x4AD8 US_ALU_EXT_ADDR_6
+0x4ADC US_ALU_EXT_ADDR_7
+0x4AE0 US_ALU_EXT_ADDR_8
+0x4AE4 US_ALU_EXT_ADDR_9
+0x4AE8 US_ALU_EXT_ADDR_10
+0x4AEC US_ALU_EXT_ADDR_11
+0x4AF0 US_ALU_EXT_ADDR_12
+0x4AF4 US_ALU_EXT_ADDR_13
+0x4AF8 US_ALU_EXT_ADDR_14
+0x4AFC US_ALU_EXT_ADDR_15
+0x4B00 US_ALU_EXT_ADDR_16
+0x4B04 US_ALU_EXT_ADDR_17
+0x4B08 US_ALU_EXT_ADDR_18
+0x4B0C US_ALU_EXT_ADDR_19
+0x4B10 US_ALU_EXT_ADDR_20
+0x4B14 US_ALU_EXT_ADDR_21
+0x4B18 US_ALU_EXT_ADDR_22
+0x4B1C US_ALU_EXT_ADDR_23
+0x4B20 US_ALU_EXT_ADDR_24
+0x4B24 US_ALU_EXT_ADDR_25
+0x4B28 US_ALU_EXT_ADDR_26
+0x4B2C US_ALU_EXT_ADDR_27
+0x4B30 US_ALU_EXT_ADDR_28
+0x4B34 US_ALU_EXT_ADDR_29
+0x4B38 US_ALU_EXT_ADDR_30
+0x4B3C US_ALU_EXT_ADDR_31
+0x4B40 US_ALU_EXT_ADDR_32
+0x4B44 US_ALU_EXT_ADDR_33
+0x4B48 US_ALU_EXT_ADDR_34
+0x4B4C US_ALU_EXT_ADDR_35
+0x4B50 US_ALU_EXT_ADDR_36
+0x4B54 US_ALU_EXT_ADDR_37
+0x4B58 US_ALU_EXT_ADDR_38
+0x4B5C US_ALU_EXT_ADDR_39
+0x4B60 US_ALU_EXT_ADDR_40
+0x4B64 US_ALU_EXT_ADDR_41
+0x4B68 US_ALU_EXT_ADDR_42
+0x4B6C US_ALU_EXT_ADDR_43
+0x4B70 US_ALU_EXT_ADDR_44
+0x4B74 US_ALU_EXT_ADDR_45
+0x4B78 US_ALU_EXT_ADDR_46
+0x4B7C US_ALU_EXT_ADDR_47
+0x4B80 US_ALU_EXT_ADDR_48
+0x4B84 US_ALU_EXT_ADDR_49
+0x4B88 US_ALU_EXT_ADDR_50
+0x4B8C US_ALU_EXT_ADDR_51
+0x4B90 US_ALU_EXT_ADDR_52
+0x4B94 US_ALU_EXT_ADDR_53
+0x4B98 US_ALU_EXT_ADDR_54
+0x4B9C US_ALU_EXT_ADDR_55
+0x4BA0 US_ALU_EXT_ADDR_56
+0x4BA4 US_ALU_EXT_ADDR_57
+0x4BA8 US_ALU_EXT_ADDR_58
+0x4BAC US_ALU_EXT_ADDR_59
+0x4BB0 US_ALU_EXT_ADDR_60
+0x4BB4 US_ALU_EXT_ADDR_61
+0x4BB8 US_ALU_EXT_ADDR_62
+0x4BBC US_ALU_EXT_ADDR_63
+0x4BC0 FG_FOG_BLEND
+0x4BC4 FG_FOG_FACTOR
+0x4BC8 FG_FOG_COLOR_R
+0x4BCC FG_FOG_COLOR_G
+0x4BD0 FG_FOG_COLOR_B
+0x4BD4 FG_ALPHA_FUNC
+0x4BD8 FG_DEPTH_SRC
+0x4C00 US_ALU_CONST_R_0
+0x4C04 US_ALU_CONST_G_0
+0x4C08 US_ALU_CONST_B_0
+0x4C0C US_ALU_CONST_A_0
+0x4C10 US_ALU_CONST_R_1
+0x4C14 US_ALU_CONST_G_1
+0x4C18 US_ALU_CONST_B_1
+0x4C1C US_ALU_CONST_A_1
+0x4C20 US_ALU_CONST_R_2
+0x4C24 US_ALU_CONST_G_2
+0x4C28 US_ALU_CONST_B_2
+0x4C2C US_ALU_CONST_A_2
+0x4C30 US_ALU_CONST_R_3
+0x4C34 US_ALU_CONST_G_3
+0x4C38 US_ALU_CONST_B_3
+0x4C3C US_ALU_CONST_A_3
+0x4C40 US_ALU_CONST_R_4
+0x4C44 US_ALU_CONST_G_4
+0x4C48 US_ALU_CONST_B_4
+0x4C4C US_ALU_CONST_A_4
+0x4C50 US_ALU_CONST_R_5
+0x4C54 US_ALU_CONST_G_5
+0x4C58 US_ALU_CONST_B_5
+0x4C5C US_ALU_CONST_A_5
+0x4C60 US_ALU_CONST_R_6
+0x4C64 US_ALU_CONST_G_6
+0x4C68 US_ALU_CONST_B_6
+0x4C6C US_ALU_CONST_A_6
+0x4C70 US_ALU_CONST_R_7
+0x4C74 US_ALU_CONST_G_7
+0x4C78 US_ALU_CONST_B_7
+0x4C7C US_ALU_CONST_A_7
+0x4C80 US_ALU_CONST_R_8
+0x4C84 US_ALU_CONST_G_8
+0x4C88 US_ALU_CONST_B_8
+0x4C8C US_ALU_CONST_A_8
+0x4C90 US_ALU_CONST_R_9
+0x4C94 US_ALU_CONST_G_9
+0x4C98 US_ALU_CONST_B_9
+0x4C9C US_ALU_CONST_A_9
+0x4CA0 US_ALU_CONST_R_10
+0x4CA4 US_ALU_CONST_G_10
+0x4CA8 US_ALU_CONST_B_10
+0x4CAC US_ALU_CONST_A_10
+0x4CB0 US_ALU_CONST_R_11
+0x4CB4 US_ALU_CONST_G_11
+0x4CB8 US_ALU_CONST_B_11
+0x4CBC US_ALU_CONST_A_11
+0x4CC0 US_ALU_CONST_R_12
+0x4CC4 US_ALU_CONST_G_12
+0x4CC8 US_ALU_CONST_B_12
+0x4CCC US_ALU_CONST_A_12
+0x4CD0 US_ALU_CONST_R_13
+0x4CD4 US_ALU_CONST_G_13
+0x4CD8 US_ALU_CONST_B_13
+0x4CDC US_ALU_CONST_A_13
+0x4CE0 US_ALU_CONST_R_14
+0x4CE4 US_ALU_CONST_G_14
+0x4CE8 US_ALU_CONST_B_14
+0x4CEC US_ALU_CONST_A_14
+0x4CF0 US_ALU_CONST_R_15
+0x4CF4 US_ALU_CONST_G_15
+0x4CF8 US_ALU_CONST_B_15
+0x4CFC US_ALU_CONST_A_15
+0x4D00 US_ALU_CONST_R_16
+0x4D04 US_ALU_CONST_G_16
+0x4D08 US_ALU_CONST_B_16
+0x4D0C US_ALU_CONST_A_16
+0x4D10 US_ALU_CONST_R_17
+0x4D14 US_ALU_CONST_G_17
+0x4D18 US_ALU_CONST_B_17
+0x4D1C US_ALU_CONST_A_17
+0x4D20 US_ALU_CONST_R_18
+0x4D24 US_ALU_CONST_G_18
+0x4D28 US_ALU_CONST_B_18
+0x4D2C US_ALU_CONST_A_18
+0x4D30 US_ALU_CONST_R_19
+0x4D34 US_ALU_CONST_G_19
+0x4D38 US_ALU_CONST_B_19
+0x4D3C US_ALU_CONST_A_19
+0x4D40 US_ALU_CONST_R_20
+0x4D44 US_ALU_CONST_G_20
+0x4D48 US_ALU_CONST_B_20
+0x4D4C US_ALU_CONST_A_20
+0x4D50 US_ALU_CONST_R_21
+0x4D54 US_ALU_CONST_G_21
+0x4D58 US_ALU_CONST_B_21
+0x4D5C US_ALU_CONST_A_21
+0x4D60 US_ALU_CONST_R_22
+0x4D64 US_ALU_CONST_G_22
+0x4D68 US_ALU_CONST_B_22
+0x4D6C US_ALU_CONST_A_22
+0x4D70 US_ALU_CONST_R_23
+0x4D74 US_ALU_CONST_G_23
+0x4D78 US_ALU_CONST_B_23
+0x4D7C US_ALU_CONST_A_23
+0x4D80 US_ALU_CONST_R_24
+0x4D84 US_ALU_CONST_G_24
+0x4D88 US_ALU_CONST_B_24
+0x4D8C US_ALU_CONST_A_24
+0x4D90 US_ALU_CONST_R_25
+0x4D94 US_ALU_CONST_G_25
+0x4D98 US_ALU_CONST_B_25
+0x4D9C US_ALU_CONST_A_25
+0x4DA0 US_ALU_CONST_R_26
+0x4DA4 US_ALU_CONST_G_26
+0x4DA8 US_ALU_CONST_B_26
+0x4DAC US_ALU_CONST_A_26
+0x4DB0 US_ALU_CONST_R_27
+0x4DB4 US_ALU_CONST_G_27
+0x4DB8 US_ALU_CONST_B_27
+0x4DBC US_ALU_CONST_A_27
+0x4DC0 US_ALU_CONST_R_28
+0x4DC4 US_ALU_CONST_G_28
+0x4DC8 US_ALU_CONST_B_28
+0x4DCC US_ALU_CONST_A_28
+0x4DD0 US_ALU_CONST_R_29
+0x4DD4 US_ALU_CONST_G_29
+0x4DD8 US_ALU_CONST_B_29
+0x4DDC US_ALU_CONST_A_29
+0x4DE0 US_ALU_CONST_R_30
+0x4DE4 US_ALU_CONST_G_30
+0x4DE8 US_ALU_CONST_B_30
+0x4DEC US_ALU_CONST_A_30
+0x4DF0 US_ALU_CONST_R_31
+0x4DF4 US_ALU_CONST_G_31
+0x4DF8 US_ALU_CONST_B_31
+0x4DFC US_ALU_CONST_A_31
+0x4E04 RB3D_BLENDCNTL_R3
+0x4E08 RB3D_ABLENDCNTL_R3
+0x4E0C RB3D_COLOR_CHANNEL_MASK
+0x4E10 RB3D_CONSTANT_COLOR
+0x4E14 RB3D_COLOR_CLEAR_VALUE
+0x4E18 RB3D_ROPCNTL_R3
+0x4E1C RB3D_CLRCMP_FLIPE_R3
+0x4E20 RB3D_CLRCMP_CLR_R3
+0x4E24 RB3D_CLRCMP_MSK_R3
+0x4E48 RB3D_DEBUG_CTL
+0x4E4C RB3D_DSTCACHE_CTLSTAT_R3
+0x4E50 RB3D_DITHER_CTL
+0x4E54 RB3D_CMASK_OFFSET0
+0x4E58 RB3D_CMASK_OFFSET1
+0x4E5C RB3D_CMASK_OFFSET2
+0x4E60 RB3D_CMASK_OFFSET3
+0x4E64 RB3D_CMASK_PITCH0
+0x4E68 RB3D_CMASK_PITCH1
+0x4E6C RB3D_CMASK_PITCH2
+0x4E70 RB3D_CMASK_PITCH3
+0x4E74 RB3D_CMASK_WRINDEX
+0x4E78 RB3D_CMASK_DWORD
+0x4E7C RB3D_CMASK_RDINDEX
+0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
+0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
+0x4F04 ZB_ZSTENCILCNTL
+0x4F08 ZB_STENCILREFMASK
+0x4F14 ZB_ZTOP
+0x4F18 ZB_ZCACHE_CTLSTAT
+0x4F1C ZB_BW_CNTL
+0x4F28 ZB_DEPTHCLEARVALUE
+0x4F30 ZB_ZMASK_OFFSET
+0x4F34 ZB_ZMASK_PITCH
+0x4F38 ZB_ZMASK_WRINDEX
+0x4F3C ZB_ZMASK_DWORD
+0x4F40 ZB_ZMASK_RDINDEX
+0x4F44 ZB_HIZ_OFFSET
+0x4F48 ZB_HIZ_WRINDEX
+0x4F4C ZB_HIZ_DWORD
+0x4F50 ZB_HIZ_RDINDEX
+0x4F54 ZB_HIZ_PITCH
+0x4F58 ZB_ZPASS_DATA
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/radeon/reg_srcs/rv515
+++ linux-ec2-2.6.32/drivers/gpu/drm/radeon/reg_srcs/rv515
@@ -161,7 +161,12 @@
 0x401C GB_SELECT
 0x4020 GB_AA_CONFIG
 0x4024 GB_FIFO_SIZE
+0x4028 GB_Z_PEQ_CONFIG
 0x4100 TX_INVALTAGS
+0x4114 SU_TEX_WRAP_PS3
+0x4118 PS3_ENABLE
+0x411c PS3_VTX_FMT
+0x4120 PS3_TEX_SOURCE
 0x4200 GA_POINT_S0
 0x4204 GA_POINT_T0
 0x4208 GA_POINT_S1
@@ -171,6 +176,7 @@
 0x4230 GA_POINT_MINMAX
 0x4234 GA_LINE_CNTL
 0x4238 GA_LINE_STIPPLE_CONFIG
+0x4258 GA_COLOR_CONTROL_PS3
 0x4260 GA_LINE_STIPPLE_VALUE
 0x4264 GA_LINE_S0
 0x4268 GA_LINE_S1
@@ -459,9 +465,6 @@
 0x4E74 RB3D_CMASK_WRINDEX
 0x4E78 RB3D_CMASK_DWORD
 0x4E7C RB3D_CMASK_RDINDEX
-0x4E80 RB3D_AARESOLVE_OFFSET
-0x4E84 RB3D_AARESOLVE_PITCH
-0x4E88 RB3D_AARESOLVE_CTL
 0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD
 0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD
 0x4EF8 RB3D_CONSTANT_COLOR_AR
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/savage/savage_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/savage/savage_drv.c
@@ -50,7 +50,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/sis/sis_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/sis/sis_drv.c
@@ -80,7 +80,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -48,7 +48,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/via/via_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/via/via_drv.c
@@ -58,7 +58,7 @@
 		.owner = THIS_MODULE,
 		.open = drm_open,
 		.release = drm_release,
-		.ioctl = drm_ioctl,
+		.unlocked_ioctl = drm_ioctl,
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i810/i810_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i810/i810_drv.c
@@ -59,7 +59,7 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .ioctl = drm_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/i810/i810_dma.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/i810/i810_dma.c
@@ -115,7 +115,7 @@
 static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.ioctl = drm_ioctl,
+	.unlocked_ioctl = drm_ioctl,
 	.mmap = i810_mmap_buffers,
 	.fasync = drm_fasync,
 };
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_graph.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright 2007 Stephane Marchesin
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+
+static uint32_t nv04_graph_ctx_regs[] = {
+	0x0040053c,
+	0x00400544,
+	0x00400540,
+	0x00400548,
+	NV04_PGRAPH_CTX_SWITCH1,
+	NV04_PGRAPH_CTX_SWITCH2,
+	NV04_PGRAPH_CTX_SWITCH3,
+	NV04_PGRAPH_CTX_SWITCH4,
+	NV04_PGRAPH_CTX_CACHE1,
+	NV04_PGRAPH_CTX_CACHE2,
+	NV04_PGRAPH_CTX_CACHE3,
+	NV04_PGRAPH_CTX_CACHE4,
+	0x00400184,
+	0x004001a4,
+	0x004001c4,
+	0x004001e4,
+	0x00400188,
+	0x004001a8,
+	0x004001c8,
+	0x004001e8,
+	0x0040018c,
+	0x004001ac,
+	0x004001cc,
+	0x004001ec,
+	0x00400190,
+	0x004001b0,
+	0x004001d0,
+	0x004001f0,
+	0x00400194,
+	0x004001b4,
+	0x004001d4,
+	0x004001f4,
+	0x00400198,
+	0x004001b8,
+	0x004001d8,
+	0x004001f8,
+	0x0040019c,
+	0x004001bc,
+	0x004001dc,
+	0x004001fc,
+	0x00400174,
+	NV04_PGRAPH_DMA_START_0,
+	NV04_PGRAPH_DMA_START_1,
+	NV04_PGRAPH_DMA_LENGTH,
+	NV04_PGRAPH_DMA_MISC,
+	NV04_PGRAPH_DMA_PITCH,
+	NV04_PGRAPH_BOFFSET0,
+	NV04_PGRAPH_BBASE0,
+	NV04_PGRAPH_BLIMIT0,
+	NV04_PGRAPH_BOFFSET1,
+	NV04_PGRAPH_BBASE1,
+	NV04_PGRAPH_BLIMIT1,
+	NV04_PGRAPH_BOFFSET2,
+	NV04_PGRAPH_BBASE2,
+	NV04_PGRAPH_BLIMIT2,
+	NV04_PGRAPH_BOFFSET3,
+	NV04_PGRAPH_BBASE3,
+	NV04_PGRAPH_BLIMIT3,
+	NV04_PGRAPH_BOFFSET4,
+	NV04_PGRAPH_BBASE4,
+	NV04_PGRAPH_BLIMIT4,
+	NV04_PGRAPH_BOFFSET5,
+	NV04_PGRAPH_BBASE5,
+	NV04_PGRAPH_BLIMIT5,
+	NV04_PGRAPH_BPITCH0,
+	NV04_PGRAPH_BPITCH1,
+	NV04_PGRAPH_BPITCH2,
+	NV04_PGRAPH_BPITCH3,
+	NV04_PGRAPH_BPITCH4,
+	NV04_PGRAPH_SURFACE,
+	NV04_PGRAPH_STATE,
+	NV04_PGRAPH_BSWIZZLE2,
+	NV04_PGRAPH_BSWIZZLE5,
+	NV04_PGRAPH_BPIXEL,
+	NV04_PGRAPH_NOTIFY,
+	NV04_PGRAPH_PATT_COLOR0,
+	NV04_PGRAPH_PATT_COLOR1,
+	NV04_PGRAPH_PATT_COLORRAM+0x00,
+	NV04_PGRAPH_PATT_COLORRAM+0x04,
+	NV04_PGRAPH_PATT_COLORRAM+0x08,
+	NV04_PGRAPH_PATT_COLORRAM+0x0c,
+	NV04_PGRAPH_PATT_COLORRAM+0x10,
+	NV04_PGRAPH_PATT_COLORRAM+0x14,
+	NV04_PGRAPH_PATT_COLORRAM+0x18,
+	NV04_PGRAPH_PATT_COLORRAM+0x1c,
+	NV04_PGRAPH_PATT_COLORRAM+0x20,
+	NV04_PGRAPH_PATT_COLORRAM+0x24,
+	NV04_PGRAPH_PATT_COLORRAM+0x28,
+	NV04_PGRAPH_PATT_COLORRAM+0x2c,
+	NV04_PGRAPH_PATT_COLORRAM+0x30,
+	NV04_PGRAPH_PATT_COLORRAM+0x34,
+	NV04_PGRAPH_PATT_COLORRAM+0x38,
+	NV04_PGRAPH_PATT_COLORRAM+0x3c,
+	NV04_PGRAPH_PATT_COLORRAM+0x40,
+	NV04_PGRAPH_PATT_COLORRAM+0x44,
+	NV04_PGRAPH_PATT_COLORRAM+0x48,
+	NV04_PGRAPH_PATT_COLORRAM+0x4c,
+	NV04_PGRAPH_PATT_COLORRAM+0x50,
+	NV04_PGRAPH_PATT_COLORRAM+0x54,
+	NV04_PGRAPH_PATT_COLORRAM+0x58,
+	NV04_PGRAPH_PATT_COLORRAM+0x5c,
+	NV04_PGRAPH_PATT_COLORRAM+0x60,
+	NV04_PGRAPH_PATT_COLORRAM+0x64,
+	NV04_PGRAPH_PATT_COLORRAM+0x68,
+	NV04_PGRAPH_PATT_COLORRAM+0x6c,
+	NV04_PGRAPH_PATT_COLORRAM+0x70,
+	NV04_PGRAPH_PATT_COLORRAM+0x74,
+	NV04_PGRAPH_PATT_COLORRAM+0x78,
+	NV04_PGRAPH_PATT_COLORRAM+0x7c,
+	NV04_PGRAPH_PATT_COLORRAM+0x80,
+	NV04_PGRAPH_PATT_COLORRAM+0x84,
+	NV04_PGRAPH_PATT_COLORRAM+0x88,
+	NV04_PGRAPH_PATT_COLORRAM+0x8c,
+	NV04_PGRAPH_PATT_COLORRAM+0x90,
+	NV04_PGRAPH_PATT_COLORRAM+0x94,
+	NV04_PGRAPH_PATT_COLORRAM+0x98,
+	NV04_PGRAPH_PATT_COLORRAM+0x9c,
+	NV04_PGRAPH_PATT_COLORRAM+0xa0,
+	NV04_PGRAPH_PATT_COLORRAM+0xa4,
+	NV04_PGRAPH_PATT_COLORRAM+0xa8,
+	NV04_PGRAPH_PATT_COLORRAM+0xac,
+	NV04_PGRAPH_PATT_COLORRAM+0xb0,
+	NV04_PGRAPH_PATT_COLORRAM+0xb4,
+	NV04_PGRAPH_PATT_COLORRAM+0xb8,
+	NV04_PGRAPH_PATT_COLORRAM+0xbc,
+	NV04_PGRAPH_PATT_COLORRAM+0xc0,
+	NV04_PGRAPH_PATT_COLORRAM+0xc4,
+	NV04_PGRAPH_PATT_COLORRAM+0xc8,
+	NV04_PGRAPH_PATT_COLORRAM+0xcc,
+	NV04_PGRAPH_PATT_COLORRAM+0xd0,
+	NV04_PGRAPH_PATT_COLORRAM+0xd4,
+	NV04_PGRAPH_PATT_COLORRAM+0xd8,
+	NV04_PGRAPH_PATT_COLORRAM+0xdc,
+	NV04_PGRAPH_PATT_COLORRAM+0xe0,
+	NV04_PGRAPH_PATT_COLORRAM+0xe4,
+	NV04_PGRAPH_PATT_COLORRAM+0xe8,
+	NV04_PGRAPH_PATT_COLORRAM+0xec,
+	NV04_PGRAPH_PATT_COLORRAM+0xf0,
+	NV04_PGRAPH_PATT_COLORRAM+0xf4,
+	NV04_PGRAPH_PATT_COLORRAM+0xf8,
+	NV04_PGRAPH_PATT_COLORRAM+0xfc,
+	NV04_PGRAPH_PATTERN,
+	0x0040080c,
+	NV04_PGRAPH_PATTERN_SHAPE,
+	0x00400600,
+	NV04_PGRAPH_ROP3,
+	NV04_PGRAPH_CHROMA,
+	NV04_PGRAPH_BETA_AND,
+	NV04_PGRAPH_BETA_PREMULT,
+	NV04_PGRAPH_CONTROL0,
+	NV04_PGRAPH_CONTROL1,
+	NV04_PGRAPH_CONTROL2,
+	NV04_PGRAPH_BLEND,
+	NV04_PGRAPH_STORED_FMT,
+	NV04_PGRAPH_SOURCE_COLOR,
+	0x00400560,
+	0x00400568,
+	0x00400564,
+	0x0040056c,
+	0x00400400,
+	0x00400480,
+	0x00400404,
+	0x00400484,
+	0x00400408,
+	0x00400488,
+	0x0040040c,
+	0x0040048c,
+	0x00400410,
+	0x00400490,
+	0x00400414,
+	0x00400494,
+	0x00400418,
+	0x00400498,
+	0x0040041c,
+	0x0040049c,
+	0x00400420,
+	0x004004a0,
+	0x00400424,
+	0x004004a4,
+	0x00400428,
+	0x004004a8,
+	0x0040042c,
+	0x004004ac,
+	0x00400430,
+	0x004004b0,
+	0x00400434,
+	0x004004b4,
+	0x00400438,
+	0x004004b8,
+	0x0040043c,
+	0x004004bc,
+	0x00400440,
+	0x004004c0,
+	0x00400444,
+	0x004004c4,
+	0x00400448,
+	0x004004c8,
+	0x0040044c,
+	0x004004cc,
+	0x00400450,
+	0x004004d0,
+	0x00400454,
+	0x004004d4,
+	0x00400458,
+	0x004004d8,
+	0x0040045c,
+	0x004004dc,
+	0x00400460,
+	0x004004e0,
+	0x00400464,
+	0x004004e4,
+	0x00400468,
+	0x004004e8,
+	0x0040046c,
+	0x004004ec,
+	0x00400470,
+	0x004004f0,
+	0x00400474,
+	0x004004f4,
+	0x00400478,
+	0x004004f8,
+	0x0040047c,
+	0x004004fc,
+	0x00400534,
+	0x00400538,
+	0x00400514,
+	0x00400518,
+	0x0040051c,
+	0x00400520,
+	0x00400524,
+	0x00400528,
+	0x0040052c,
+	0x00400530,
+	0x00400d00,
+	0x00400d40,
+	0x00400d80,
+	0x00400d04,
+	0x00400d44,
+	0x00400d84,
+	0x00400d08,
+	0x00400d48,
+	0x00400d88,
+	0x00400d0c,
+	0x00400d4c,
+	0x00400d8c,
+	0x00400d10,
+	0x00400d50,
+	0x00400d90,
+	0x00400d14,
+	0x00400d54,
+	0x00400d94,
+	0x00400d18,
+	0x00400d58,
+	0x00400d98,
+	0x00400d1c,
+	0x00400d5c,
+	0x00400d9c,
+	0x00400d20,
+	0x00400d60,
+	0x00400da0,
+	0x00400d24,
+	0x00400d64,
+	0x00400da4,
+	0x00400d28,
+	0x00400d68,
+	0x00400da8,
+	0x00400d2c,
+	0x00400d6c,
+	0x00400dac,
+	0x00400d30,
+	0x00400d70,
+	0x00400db0,
+	0x00400d34,
+	0x00400d74,
+	0x00400db4,
+	0x00400d38,
+	0x00400d78,
+	0x00400db8,
+	0x00400d3c,
+	0x00400d7c,
+	0x00400dbc,
+	0x00400590,
+	0x00400594,
+	0x00400598,
+	0x0040059c,
+	0x004005a8,
+	0x004005ac,
+	0x004005b0,
+	0x004005b4,
+	0x004005c0,
+	0x004005c4,
+	0x004005c8,
+	0x004005cc,
+	0x004005d0,
+	0x004005d4,
+	0x004005d8,
+	0x004005dc,
+	0x004005e0,
+	NV04_PGRAPH_PASSTHRU_0,
+	NV04_PGRAPH_PASSTHRU_1,
+	NV04_PGRAPH_PASSTHRU_2,
+	NV04_PGRAPH_DVD_COLORFMT,
+	NV04_PGRAPH_SCALED_FORMAT,
+	NV04_PGRAPH_MISC24_0,
+	NV04_PGRAPH_MISC24_1,
+	NV04_PGRAPH_MISC24_2,
+	0x00400500,
+	0x00400504,
+	NV04_PGRAPH_VALID1,
+	NV04_PGRAPH_VALID2,
+	NV04_PGRAPH_DEBUG_3
+};
+
+struct graph_state {
+	int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
+};
+
+struct nouveau_channel *
+nv04_graph_channel(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chid = dev_priv->engine.fifo.channels;
+
+	if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000)
+		chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24;
+
+	if (chid >= dev_priv->engine.fifo.channels)
+		return NULL;
+
+	return dev_priv->fifos[chid];
+}
+
+void
+nv04_graph_context_switch(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_channel *chan = NULL;
+	int chid;
+
+	pgraph->fifo_access(dev, false);
+	nouveau_wait_for_idle(dev);
+
+	/* If previous context is valid, we need to save it */
+	pgraph->unload_context(dev);
+
+	/* Load context for next channel */
+	chid = dev_priv->engine.fifo.channel_id(dev);
+	chan = dev_priv->fifos[chid];
+	if (chan)
+		nv04_graph_load_context(chan);
+
+	pgraph->fifo_access(dev, true);
+}
+
+static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) {
+		if (nv04_graph_ctx_regs[i] == reg)
+			return &ctx->nv04[i];
+	}
+
+	return NULL;
+}
+
+int nv04_graph_create_context(struct nouveau_channel *chan)
+{
+	struct graph_state *pgraph_ctx;
+	NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id);
+
+	chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
+						GFP_KERNEL);
+	if (pgraph_ctx == NULL)
+		return -ENOMEM;
+
+	*ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
+
+	return 0;
+}
+
+void nv04_graph_destroy_context(struct nouveau_channel *chan)
+{
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+
+	kfree(pgraph_ctx);
+	chan->pgraph_ctx = NULL;
+}
+
+int nv04_graph_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	uint32_t tmp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
+		nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
+
+	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
+
+	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
+	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24);
+
+	tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2);
+	nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff);
+
+	return 0;
+}
+
+int
+nv04_graph_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_channel *chan = NULL;
+	struct graph_state *ctx;
+	uint32_t tmp;
+	int i;
+
+	chan = pgraph->channel(dev);
+	if (!chan)
+		return 0;
+	ctx = chan->pgraph_ctx;
+
+	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
+		ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]);
+
+	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000);
+	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
+	tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
+	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
+	return 0;
+}
+
+int nv04_graph_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
+			~NV_PMC_ENABLE_PGRAPH);
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
+			 NV_PMC_ENABLE_PGRAPH);
+
+	/* Enable PGRAPH interrupts */
+	nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV04_PGRAPH_VALID1, 0);
+	nv_wr32(dev, NV04_PGRAPH_VALID2, 0);
+	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000);
+	/*1231C000 blob, 001 haiku*/
+	//*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100);
+	/*0x72111100 blob , 01 haiku*/
+	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071);
+	/*haiku same*/
+
+	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
+	/*haiku and blob 10d4*/
+
+	nv_wr32(dev, NV04_PGRAPH_STATE        , 0xFFFFFFFF);
+	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL  , 0x10000100);
+	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
+	tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
+	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
+
+	/* These don't belong here, they're part of a per-channel context */
+	nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
+	nv_wr32(dev, NV04_PGRAPH_BETA_AND     , 0xFFFFFFFF);
+
+	return 0;
+}
+
+void nv04_graph_takedown(struct drm_device *dev)
+{
+}
+
+void
+nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
+{
+	if (enabled)
+		nv_wr32(dev, NV04_PGRAPH_FIFO,
+					nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
+	else
+		nv_wr32(dev, NV04_PGRAPH_FIFO,
+					nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
+}
+
+static int
+nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
+			int mthd, uint32_t data)
+{
+	chan->fence.last_sequence_irq = data;
+	nouveau_fence_handler(chan->dev, chan->id);
+	return 0;
+}
+
+static int
+nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
+			      int mthd, uint32_t data)
+{
+	struct drm_device *dev = chan->dev;
+	uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
+	int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
+	uint32_t tmp;
+
+	tmp  = nv_ri32(dev, instance);
+	tmp &= ~0x00038000;
+	tmp |= ((data & 7) << 15);
+
+	nv_wi32(dev, instance, tmp);
+	nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp);
+	nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp);
+	return 0;
+}
+
+static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
+	{ 0x0150, nv04_graph_mthd_set_ref },
+	{}
+};
+
+static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = {
+	{ 0x02fc, nv04_graph_mthd_set_operation },
+	{},
+};
+
+struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
+	{ 0x0039, false, NULL },
+	{ 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */
+	{ 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */
+	{ 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */
+	{ 0x0077, false, nv04_graph_mthds_set_operation }, /* sifm */
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x0042, false, NULL }, /* surf2d */
+	{ 0x0043, false, NULL }, /* rop */
+	{ 0x0012, false, NULL }, /* beta1 */
+	{ 0x0072, false, NULL }, /* beta4 */
+	{ 0x0019, false, NULL }, /* cliprect */
+	{ 0x0044, false, NULL }, /* pattern */
+	{ 0x0052, false, NULL }, /* swzsurf */
+	{ 0x0053, false, NULL }, /* surf3d */
+	{ 0x0054, false, NULL }, /* tex_tri */
+	{ 0x0055, false, NULL }, /* multitex_tri */
+	{ 0x506e, true, nv04_graph_mthds_sw },
+	{}
+};
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_object.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/*
+ * Authors:
+ *   Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+/* NVidia uses context objects to drive drawing operations.
+
+   Context objects can be selected into 8 subchannels in the FIFO,
+   and then used via DMA command buffers.
+
+   A context object is referenced by a user defined handle (CARD32). The HW
+   looks up graphics objects in a hash table in the instance RAM.
+
+   An entry in the hash table consists of 2 CARD32. The first CARD32 contains
+   the handle, the second one a bitfield, that contains the address of the
+   object in instance RAM.
+
+   The format of the second CARD32 seems to be:
+
+   NV4 to NV30:
+
+   15: 0  instance_addr >> 4
+   17:16  engine (here uses 1 = graphics)
+   28:24  channel id (here uses 0)
+   31	  valid (use 1)
+
+   NV40:
+
+   15: 0  instance_addr >> 4   (maybe 19-0)
+   21:20  engine (here uses 1 = graphics)
+   I'm unsure about the other bits, but using 0 seems to work.
+
+   The key into the hash table depends on the object handle and channel id and
+   is given as:
+*/
+static uint32_t
+nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t hash = 0;
+	int i;
+
+	NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle);
+
+	for (i = 32; i > 0; i -= dev_priv->ramht_bits) {
+		hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
+		handle >>= dev_priv->ramht_bits;
+	}
+
+	if (dev_priv->card_type < NV_50)
+		hash ^= channel << (dev_priv->ramht_bits - 4);
+	hash <<= 3;
+
+	NV_DEBUG(dev, "hash=0x%08x\n", hash);
+	return hash;
+}
+
+static int
+nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht,
+			  uint32_t offset)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t ctx = nv_ro32(dev, ramht, (offset + 4)/4);
+
+	if (dev_priv->card_type < NV_40)
+		return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
+	return (ctx != 0);
+}
+
+static int
+nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
+	struct nouveau_channel *chan = ref->channel;
+	struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
+	uint32_t ctx, co, ho;
+
+	if (!ramht) {
+		NV_ERROR(dev, "No hash table!\n");
+		return -EINVAL;
+	}
+
+	if (dev_priv->card_type < NV_40) {
+		ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) |
+		      (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+		      (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
+	} else
+	if (dev_priv->card_type < NV_50) {
+		ctx = (ref->instance >> 4) |
+		      (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+		      (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
+	} else {
+		if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
+			ctx = (ref->instance << 10) | 2;
+		} else {
+			ctx = (ref->instance >> 4) |
+			      ((ref->gpuobj->engine <<
+				NV40_RAMHT_CONTEXT_ENGINE_SHIFT));
+		}
+	}
+
+	instmem->prepare_access(dev, true);
+	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
+	do {
+		if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
+			NV_DEBUG(dev,
+				 "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+				 chan->id, co, ref->handle, ctx);
+			nv_wo32(dev, ramht, (co + 0)/4, ref->handle);
+			nv_wo32(dev, ramht, (co + 4)/4, ctx);
+
+			list_add_tail(&ref->list, &chan->ramht_refs);
+			instmem->finish_access(dev);
+			return 0;
+		}
+		NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
+			 chan->id, co, nv_ro32(dev, ramht, co/4));
+
+		co += 8;
+		if (co >= dev_priv->ramht_size)
+			co = 0;
+	} while (co != ho);
+	instmem->finish_access(dev);
+
+	NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
+	return -ENOMEM;
+}
+
+static void
+nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
+	struct nouveau_channel *chan = ref->channel;
+	struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
+	uint32_t co, ho;
+
+	if (!ramht) {
+		NV_ERROR(dev, "No hash table!\n");
+		return;
+	}
+
+	instmem->prepare_access(dev, true);
+	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
+	do {
+		if (nouveau_ramht_entry_valid(dev, ramht, co) &&
+		    (ref->handle == nv_ro32(dev, ramht, (co/4)))) {
+			NV_DEBUG(dev,
+				 "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+				 chan->id, co, ref->handle,
+				 nv_ro32(dev, ramht, (co + 4)));
+			nv_wo32(dev, ramht, (co + 0)/4, 0x00000000);
+			nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);
+
+			list_del(&ref->list);
+			instmem->finish_access(dev);
+			return;
+		}
+
+		co += 8;
+		if (co >= dev_priv->ramht_size)
+			co = 0;
+	} while (co != ho);
+	list_del(&ref->list);
+	instmem->finish_access(dev);
+
+	NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
+		 chan->id, ref->handle);
+}
+
+int
+nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
+		   uint32_t size, int align, uint32_t flags,
+		   struct nouveau_gpuobj **gpuobj_ret)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	struct nouveau_gpuobj *gpuobj;
+	struct mem_block *pramin = NULL;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
+		 chan ? chan->id : -1, size, align, flags);
+
+	if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL)
+		return -EINVAL;
+
+	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
+	if (!gpuobj)
+		return -ENOMEM;
+	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
+	gpuobj->flags = flags;
+	gpuobj->im_channel = chan;
+
+	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
+
+	/* Choose between global instmem heap, and per-channel private
+	 * instmem heap.  On <NV50 allow requests for private instmem
+	 * to be satisfied from global heap if no per-channel area
+	 * available.
+	 */
+	if (chan) {
+		if (chan->ramin_heap) {
+			NV_DEBUG(dev, "private heap\n");
+			pramin = chan->ramin_heap;
+		} else
+		if (dev_priv->card_type < NV_50) {
+			NV_DEBUG(dev, "global heap fallback\n");
+			pramin = dev_priv->ramin_heap;
+		}
+	} else {
+		NV_DEBUG(dev, "global heap\n");
+		pramin = dev_priv->ramin_heap;
+	}
+
+	if (!pramin) {
+		NV_ERROR(dev, "No PRAMIN heap!\n");
+		return -EINVAL;
+	}
+
+	if (!chan) {
+		ret = engine->instmem.populate(dev, gpuobj, &size);
+		if (ret) {
+			nouveau_gpuobj_del(dev, &gpuobj);
+			return ret;
+		}
+	}
+
+	/* Allocate a chunk of the PRAMIN aperture */
+	gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
+						    drm_order(align),
+						    (struct drm_file *)-2, 0);
+	if (!gpuobj->im_pramin) {
+		nouveau_gpuobj_del(dev, &gpuobj);
+		return -ENOMEM;
+	}
+
+	if (!chan) {
+		ret = engine->instmem.bind(dev, gpuobj);
+		if (ret) {
+			nouveau_gpuobj_del(dev, &gpuobj);
+			return ret;
+		}
+	}
+
+	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
+		int i;
+
+		engine->instmem.prepare_access(dev, true);
+		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
+			nv_wo32(dev, gpuobj, i/4, 0);
+		engine->instmem.finish_access(dev);
+	}
+
+	*gpuobj_ret = gpuobj;
+	return 0;
+}
+
+int
+nouveau_gpuobj_early_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	NV_DEBUG(dev, "\n");
+
+	INIT_LIST_HEAD(&dev_priv->gpuobj_list);
+
+	return 0;
+}
+
+int
+nouveau_gpuobj_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	NV_DEBUG(dev, "\n");
+
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_gpuobj_new_fake(dev,
+			dev_priv->ramht_offset, ~0, dev_priv->ramht_size,
+			NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ALLOW_NO_REFS,
+						&dev_priv->ramht, NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void
+nouveau_gpuobj_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	NV_DEBUG(dev, "\n");
+
+	nouveau_gpuobj_del(dev, &dev_priv->ramht);
+}
+
+void
+nouveau_gpuobj_late_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = NULL;
+	struct list_head *entry, *tmp;
+
+	NV_DEBUG(dev, "\n");
+
+	list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
+		gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
+
+		NV_ERROR(dev, "gpuobj %p still exists at takedown, refs=%d\n",
+			 gpuobj, gpuobj->refcount);
+		gpuobj->refcount = 0;
+		nouveau_gpuobj_del(dev, &gpuobj);
+	}
+}
+
+int
+nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	struct nouveau_gpuobj *gpuobj;
+	int i;
+
+	NV_DEBUG(dev, "gpuobj %p\n", pgpuobj ? *pgpuobj : NULL);
+
+	if (!dev_priv || !pgpuobj || !(*pgpuobj))
+		return -EINVAL;
+	gpuobj = *pgpuobj;
+
+	if (gpuobj->refcount != 0) {
+		NV_ERROR(dev, "gpuobj refcount is %d\n", gpuobj->refcount);
+		return -EINVAL;
+	}
+
+	if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
+		engine->instmem.prepare_access(dev, true);
+		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
+			nv_wo32(dev, gpuobj, i/4, 0);
+		engine->instmem.finish_access(dev);
+	}
+
+	if (gpuobj->dtor)
+		gpuobj->dtor(dev, gpuobj);
+
+	if (gpuobj->im_backing && !(gpuobj->flags & NVOBJ_FLAG_FAKE))
+		engine->instmem.clear(dev, gpuobj);
+
+	if (gpuobj->im_pramin) {
+		if (gpuobj->flags & NVOBJ_FLAG_FAKE)
+			kfree(gpuobj->im_pramin);
+		else
+			nouveau_mem_free_block(gpuobj->im_pramin);
+	}
+
+	list_del(&gpuobj->list);
+
+	*pgpuobj = NULL;
+	kfree(gpuobj);
+	return 0;
+}
+
+static int
+nouveau_gpuobj_instance_get(struct drm_device *dev,
+			    struct nouveau_channel *chan,
+			    struct nouveau_gpuobj *gpuobj, uint32_t *inst)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *cpramin;
+
+	/* <NV50 use PRAMIN address everywhere */
+	if (dev_priv->card_type < NV_50) {
+		*inst = gpuobj->im_pramin->start;
+		return 0;
+	}
+
+	if (chan && gpuobj->im_channel != chan) {
+		NV_ERROR(dev, "Channel mismatch: obj %d, ref %d\n",
+			 gpuobj->im_channel->id, chan->id);
+		return -EINVAL;
+	}
+
+	/* NV50 channel-local instance */
+	if (chan) {
+		cpramin = chan->ramin->gpuobj;
+		*inst = gpuobj->im_pramin->start - cpramin->im_pramin->start;
+		return 0;
+	}
+
+	/* NV50 global (VRAM) instance */
+	if (!gpuobj->im_channel) {
+		/* ...from global heap */
+		if (!gpuobj->im_backing) {
+			NV_ERROR(dev, "AII, no VRAM backing gpuobj\n");
+			return -EINVAL;
+		}
+		*inst = gpuobj->im_backing_start;
+		return 0;
+	} else {
+		/* ...from local heap */
+		cpramin = gpuobj->im_channel->ramin->gpuobj;
+		*inst = cpramin->im_backing_start +
+			(gpuobj->im_pramin->start - cpramin->im_pramin->start);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+int
+nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan,
+		       uint32_t handle, struct nouveau_gpuobj *gpuobj,
+		       struct nouveau_gpuobj_ref **ref_ret)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj_ref *ref;
+	uint32_t instance;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d h=0x%08x gpuobj=%p\n",
+		 chan ? chan->id : -1, handle, gpuobj);
+
+	if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL))
+		return -EINVAL;
+
+	if (!chan && !ref_ret)
+		return -EINVAL;
+
+	if (gpuobj->engine == NVOBJ_ENGINE_SW && !gpuobj->im_pramin) {
+		/* sw object */
+		instance = 0x40;
+	} else {
+		ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance);
+		if (ret)
+			return ret;
+	}
+
+	ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+	if (!ref)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&ref->list);
+	ref->gpuobj   = gpuobj;
+	ref->channel  = chan;
+	ref->instance = instance;
+
+	if (!ref_ret) {
+		ref->handle = handle;
+
+		ret = nouveau_ramht_insert(dev, ref);
+		if (ret) {
+			kfree(ref);
+			return ret;
+		}
+	} else {
+		ref->handle = ~0;
+		*ref_ret = ref;
+	}
+
+	ref->gpuobj->refcount++;
+	return 0;
+}
+
+int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **pref)
+{
+	struct nouveau_gpuobj_ref *ref;
+
+	NV_DEBUG(dev, "ref %p\n", pref ? *pref : NULL);
+
+	if (!dev || !pref || *pref == NULL)
+		return -EINVAL;
+	ref = *pref;
+
+	if (ref->handle != ~0)
+		nouveau_ramht_remove(dev, ref);
+
+	if (ref->gpuobj) {
+		ref->gpuobj->refcount--;
+
+		if (ref->gpuobj->refcount == 0) {
+			if (!(ref->gpuobj->flags & NVOBJ_FLAG_ALLOW_NO_REFS))
+				nouveau_gpuobj_del(dev, &ref->gpuobj);
+		}
+	}
+
+	*pref = NULL;
+	kfree(ref);
+	return 0;
+}
+
+int
+nouveau_gpuobj_new_ref(struct drm_device *dev,
+		       struct nouveau_channel *oc, struct nouveau_channel *rc,
+		       uint32_t handle, uint32_t size, int align,
+		       uint32_t flags, struct nouveau_gpuobj_ref **ref)
+{
+	struct nouveau_gpuobj *gpuobj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, oc, size, align, flags, &gpuobj);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_ref_add(dev, rc, handle, gpuobj, ref);
+	if (ret) {
+		nouveau_gpuobj_del(dev, &gpuobj);
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle,
+			struct nouveau_gpuobj_ref **ref_ret)
+{
+	struct nouveau_gpuobj_ref *ref;
+	struct list_head *entry, *tmp;
+
+	list_for_each_safe(entry, tmp, &chan->ramht_refs) {
+		ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
+
+		if (ref->handle == handle) {
+			if (ref_ret)
+				*ref_ret = ref;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+int
+nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
+			uint32_t b_offset, uint32_t size,
+			uint32_t flags, struct nouveau_gpuobj **pgpuobj,
+			struct nouveau_gpuobj_ref **pref)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = NULL;
+	int i;
+
+	NV_DEBUG(dev,
+		 "p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n",
+		 p_offset, b_offset, size, flags);
+
+	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
+	if (!gpuobj)
+		return -ENOMEM;
+	NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
+	gpuobj->im_channel = NULL;
+	gpuobj->flags      = flags | NVOBJ_FLAG_FAKE;
+
+	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
+
+	if (p_offset != ~0) {
+		gpuobj->im_pramin = kzalloc(sizeof(struct mem_block),
+					    GFP_KERNEL);
+		if (!gpuobj->im_pramin) {
+			nouveau_gpuobj_del(dev, &gpuobj);
+			return -ENOMEM;
+		}
+		gpuobj->im_pramin->start = p_offset;
+		gpuobj->im_pramin->size  = size;
+	}
+
+	if (b_offset != ~0) {
+		gpuobj->im_backing = (struct nouveau_bo *)-1;
+		gpuobj->im_backing_start = b_offset;
+	}
+
+	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
+		dev_priv->engine.instmem.prepare_access(dev, true);
+		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
+			nv_wo32(dev, gpuobj, i/4, 0);
+		dev_priv->engine.instmem.finish_access(dev);
+	}
+
+	if (pref) {
+		i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref);
+		if (i) {
+			nouveau_gpuobj_del(dev, &gpuobj);
+			return i;
+		}
+	}
+
+	if (pgpuobj)
+		*pgpuobj = gpuobj;
+	return 0;
+}
+
+
+static uint32_t
+nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/*XXX: dodgy hack for now */
+	if (dev_priv->card_type >= NV_50)
+		return 24;
+	if (dev_priv->card_type >= NV_40)
+		return 32;
+	return 16;
+}
+
+/*
+   DMA objects are used to reference a piece of memory in the
+   framebuffer, PCI or AGP address space. Each object is 16 bytes big
+   and looks as follows:
+
+   entry[0]
+   11:0  class (seems like I can always use 0 here)
+   12    page table present?
+   13    page entry linear?
+   15:14 access: 0 rw, 1 ro, 2 wo
+   17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP
+   31:20 dma adjust (bits 0-11 of the address)
+   entry[1]
+   dma limit (size of transfer)
+   entry[X]
+   1     0 readonly, 1 readwrite
+   31:12 dma frame address of the page (bits 12-31 of the address)
+   entry[N]
+   page table terminator, same value as the first pte, as does nvidia
+   rivatv uses 0xffffffff
+
+   Non linear page tables need a list of frame addresses afterwards,
+   the rivatv project has some info on this.
+
+   The method below creates a DMA object in instance RAM and returns a handle
+   to it that can be used to set up context objects.
+*/
+int
+nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
+		       uint64_t offset, uint64_t size, int access,
+		       int target, struct nouveau_gpuobj **gpuobj)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d class=0x%04x offset=0x%llx size=0x%llx\n",
+		 chan->id, class, offset, size);
+	NV_DEBUG(dev, "access=%d target=%d\n", access, target);
+
+	switch (target) {
+	case NV_DMA_TARGET_AGP:
+		offset += dev_priv->gart_info.aper_base;
+		break;
+	default:
+		break;
+	}
+
+	ret = nouveau_gpuobj_new(dev, chan,
+				 nouveau_gpuobj_class_instmem_size(dev, class),
+				 16, NVOBJ_FLAG_ZERO_ALLOC |
+				 NVOBJ_FLAG_ZERO_FREE, gpuobj);
+	if (ret) {
+		NV_ERROR(dev, "Error creating gpuobj: %d\n", ret);
+		return ret;
+	}
+
+	instmem->prepare_access(dev, true);
+
+	if (dev_priv->card_type < NV_50) {
+		uint32_t frame, adjust, pte_flags = 0;
+
+		if (access != NV_DMA_ACCESS_RO)
+			pte_flags |= (1<<1);
+		adjust = offset &  0x00000fff;
+		frame  = offset & ~0x00000fff;
+
+		nv_wo32(dev, *gpuobj, 0, ((1<<12) | (1<<13) |
+				(adjust << 20) |
+				 (access << 14) |
+				 (target << 16) |
+				  class));
+		nv_wo32(dev, *gpuobj, 1, size - 1);
+		nv_wo32(dev, *gpuobj, 2, frame | pte_flags);
+		nv_wo32(dev, *gpuobj, 3, frame | pte_flags);
+	} else {
+		uint64_t limit = offset + size - 1;
+		uint32_t flags0, flags5;
+
+		if (target == NV_DMA_TARGET_VIDMEM) {
+			flags0 = 0x00190000;
+			flags5 = 0x00010000;
+		} else {
+			flags0 = 0x7fc00000;
+			flags5 = 0x00080000;
+		}
+
+		nv_wo32(dev, *gpuobj, 0, flags0 | class);
+		nv_wo32(dev, *gpuobj, 1, lower_32_bits(limit));
+		nv_wo32(dev, *gpuobj, 2, lower_32_bits(offset));
+		nv_wo32(dev, *gpuobj, 3, ((upper_32_bits(limit) & 0xff) << 24) |
+					(upper_32_bits(offset) & 0xff));
+		nv_wo32(dev, *gpuobj, 5, flags5);
+	}
+
+	instmem->finish_access(dev);
+
+	(*gpuobj)->engine = NVOBJ_ENGINE_SW;
+	(*gpuobj)->class  = class;
+	return 0;
+}
+
+int
+nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan,
+			    uint64_t offset, uint64_t size, int access,
+			    struct nouveau_gpuobj **gpuobj,
+			    uint32_t *o_ret)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (dev_priv->gart_info.type == NOUVEAU_GART_AGP ||
+	    (dev_priv->card_type >= NV_50 &&
+	     dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) {
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+					     offset + dev_priv->vm_gart_base,
+					     size, access, NV_DMA_TARGET_AGP,
+					     gpuobj);
+		if (o_ret)
+			*o_ret = 0;
+	} else
+	if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) {
+		*gpuobj = dev_priv->gart_info.sg_ctxdma;
+		if (offset & ~0xffffffffULL) {
+			NV_ERROR(dev, "obj offset exceeds 32-bits\n");
+			return -EINVAL;
+		}
+		if (o_ret)
+			*o_ret = (uint32_t)offset;
+		ret = (*gpuobj != NULL) ? 0 : -EINVAL;
+	} else {
+		NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/* Context objects in the instance RAM have the following structure.
+ * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes.
+
+   NV4 - NV30:
+
+   entry[0]
+   11:0 class
+   12   chroma key enable
+   13   user clip enable
+   14   swizzle enable
+   17:15 patch config:
+       scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre
+   18   synchronize enable
+   19   endian: 1 big, 0 little
+   21:20 dither mode
+   23    single step enable
+   24    patch status: 0 invalid, 1 valid
+   25    context_surface 0: 1 valid
+   26    context surface 1: 1 valid
+   27    context pattern: 1 valid
+   28    context rop: 1 valid
+   29,30 context beta, beta4
+   entry[1]
+   7:0   mono format
+   15:8  color format
+   31:16 notify instance address
+   entry[2]
+   15:0  dma 0 instance address
+   31:16 dma 1 instance address
+   entry[3]
+   dma method traps
+
+   NV40:
+   No idea what the exact format is. Here's what can be deducted:
+
+   entry[0]:
+   11:0  class  (maybe uses more bits here?)
+   17    user clip enable
+   21:19 patch config
+   25    patch status valid ?
+   entry[1]:
+   15:0  DMA notifier  (maybe 20:0)
+   entry[2]:
+   15:0  DMA 0 instance (maybe 20:0)
+   24    big endian
+   entry[3]:
+   15:0  DMA 1 instance (maybe 20:0)
+   entry[4]:
+   entry[5]:
+   set to 0?
+*/
+int
+nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
+		      struct nouveau_gpuobj **gpuobj)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
+
+	ret = nouveau_gpuobj_new(dev, chan,
+				 nouveau_gpuobj_class_instmem_size(dev, class),
+				 16,
+				 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
+				 gpuobj);
+	if (ret) {
+		NV_ERROR(dev, "Error creating gpuobj: %d\n", ret);
+		return ret;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	if (dev_priv->card_type >= NV_50) {
+		nv_wo32(dev, *gpuobj, 0, class);
+		nv_wo32(dev, *gpuobj, 5, 0x00010000);
+	} else {
+		switch (class) {
+		case NV_CLASS_NULL:
+			nv_wo32(dev, *gpuobj, 0, 0x00001030);
+			nv_wo32(dev, *gpuobj, 1, 0xFFFFFFFF);
+			break;
+		default:
+			if (dev_priv->card_type >= NV_40) {
+				nv_wo32(dev, *gpuobj, 0, class);
+#ifdef __BIG_ENDIAN
+				nv_wo32(dev, *gpuobj, 2, 0x01000000);
+#endif
+			} else {
+#ifdef __BIG_ENDIAN
+				nv_wo32(dev, *gpuobj, 0, class | 0x00080000);
+#else
+				nv_wo32(dev, *gpuobj, 0, class);
+#endif
+			}
+		}
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	(*gpuobj)->engine = NVOBJ_ENGINE_GR;
+	(*gpuobj)->class  = class;
+	return 0;
+}
+
+int
+nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
+		      struct nouveau_gpuobj **gpuobj_ret)
+{
+	struct drm_nouveau_private *dev_priv;
+	struct nouveau_gpuobj *gpuobj;
+
+	if (!chan || !gpuobj_ret || *gpuobj_ret != NULL)
+		return -EINVAL;
+	dev_priv = chan->dev->dev_private;
+
+	gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
+	if (!gpuobj)
+		return -ENOMEM;
+	gpuobj->engine = NVOBJ_ENGINE_SW;
+	gpuobj->class = class;
+
+	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
+	*gpuobj_ret = gpuobj;
+	return 0;
+}
+
+static int
+nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *pramin = NULL;
+	uint32_t size;
+	uint32_t base;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	/* Base amount for object storage (4KiB enough?) */
+	size = 0x1000;
+	base = 0;
+
+	/* PGRAPH context */
+
+	if (dev_priv->card_type == NV_50) {
+		/* Various fixed table thingos */
+		size += 0x1400; /* mostly unknown stuff */
+		size += 0x4000; /* vm pd */
+		base  = 0x6000;
+		/* RAMHT, not sure about setting size yet, 32KiB to be safe */
+		size += 0x8000;
+		/* RAMFC */
+		size += 0x1000;
+		/* PGRAPH context */
+		size += 0x70000;
+	}
+
+	NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
+		 chan->id, size, base);
+	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
+				     &chan->ramin);
+	if (ret) {
+		NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret);
+		return ret;
+	}
+	pramin = chan->ramin->gpuobj;
+
+	ret = nouveau_mem_init_heap(&chan->ramin_heap,
+				    pramin->im_pramin->start + base, size);
+	if (ret) {
+		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
+		nouveau_gpuobj_ref_del(dev, &chan->ramin);
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
+			    uint32_t vram_h, uint32_t tt_h)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
+	struct nouveau_gpuobj *vram = NULL, *tt = NULL;
+	int ret, i;
+
+	INIT_LIST_HEAD(&chan->ramht_refs);
+
+	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
+
+	/* Reserve a block of PRAMIN for the channel
+	 *XXX: maybe on <NV50 too at some point
+	 */
+	if (0 || dev_priv->card_type == NV_50) {
+		ret = nouveau_gpuobj_channel_init_pramin(chan);
+		if (ret) {
+			NV_ERROR(dev, "init pramin\n");
+			return ret;
+		}
+	}
+
+	/* NV50 VM
+	 *  - Allocate per-channel page-directory
+	 *  - Map GART and VRAM into the channel's address space at the
+	 *    locations determined during init.
+	 */
+	if (dev_priv->card_type >= NV_50) {
+		uint32_t vm_offset, pde;
+
+		instmem->prepare_access(dev, true);
+
+		vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
+		vm_offset += chan->ramin->gpuobj->im_pramin->start;
+
+		ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
+							0, &chan->vm_pd, NULL);
+		if (ret) {
+			instmem->finish_access(dev);
+			return ret;
+		}
+		for (i = 0; i < 0x4000; i += 8) {
+			nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);
+			nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe);
+		}
+
+		pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 2;
+		ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
+					     dev_priv->gart_info.sg_ctxdma,
+					     &chan->vm_gart_pt);
+		if (ret) {
+			instmem->finish_access(dev);
+			return ret;
+		}
+		nv_wo32(dev, chan->vm_pd, pde++,
+			    chan->vm_gart_pt->instance | 0x03);
+		nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
+
+		pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2;
+		for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
+			ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
+						     dev_priv->vm_vram_pt[i],
+						     &chan->vm_vram_pt[i]);
+			if (ret) {
+				instmem->finish_access(dev);
+				return ret;
+			}
+
+			nv_wo32(dev, chan->vm_pd, pde++,
+				    chan->vm_vram_pt[i]->instance | 0x61);
+			nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
+		}
+
+		instmem->finish_access(dev);
+	}
+
+	/* RAMHT */
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht,
+					     &chan->ramht);
+		if (ret)
+			return ret;
+	} else {
+		ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0,
+					     0x8000, 16,
+					     NVOBJ_FLAG_ZERO_ALLOC,
+					     &chan->ramht);
+		if (ret)
+			return ret;
+	}
+
+	/* VRAM ctxdma */
+	if (dev_priv->card_type >= NV_50) {
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+					     0, dev_priv->vm_end,
+					     NV_DMA_ACCESS_RW,
+					     NV_DMA_TARGET_AGP, &vram);
+		if (ret) {
+			NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
+			return ret;
+		}
+	} else {
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+						0, dev_priv->fb_available_size,
+						NV_DMA_ACCESS_RW,
+						NV_DMA_TARGET_VIDMEM, &vram);
+		if (ret) {
+			NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL);
+	if (ret) {
+		NV_ERROR(dev, "Error referencing VRAM ctxdma: %d\n", ret);
+		return ret;
+	}
+
+	/* TT memory ctxdma */
+	if (dev_priv->card_type >= NV_50) {
+		tt = vram;
+	} else
+	if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) {
+		ret = nouveau_gpuobj_gart_dma_new(chan, 0,
+						  dev_priv->gart_info.aper_size,
+						  NV_DMA_ACCESS_RW, &tt, NULL);
+	} else {
+		NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type);
+		ret = -EINVAL;
+	}
+
+	if (ret) {
+		NV_ERROR(dev, "Error creating TT ctxdma: %d\n", ret);
+		return ret;
+	}
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL);
+	if (ret) {
+		NV_ERROR(dev, "Error referencing TT ctxdma: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void
+nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct drm_device *dev = chan->dev;
+	struct list_head *entry, *tmp;
+	struct nouveau_gpuobj_ref *ref;
+	int i;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	if (!chan->ramht_refs.next)
+		return;
+
+	list_for_each_safe(entry, tmp, &chan->ramht_refs) {
+		ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
+
+		nouveau_gpuobj_ref_del(dev, &ref);
+	}
+
+	nouveau_gpuobj_ref_del(dev, &chan->ramht);
+
+	nouveau_gpuobj_del(dev, &chan->vm_pd);
+	nouveau_gpuobj_ref_del(dev, &chan->vm_gart_pt);
+	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
+		nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
+
+	if (chan->ramin_heap)
+		nouveau_mem_takedown(&chan->ramin_heap);
+	if (chan->ramin)
+		nouveau_gpuobj_ref_del(dev, &chan->ramin);
+
+}
+
+int
+nouveau_gpuobj_suspend(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj;
+	int i;
+
+	if (dev_priv->card_type < NV_50) {
+		dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram);
+		if (!dev_priv->susres.ramin_copy)
+			return -ENOMEM;
+
+		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
+			dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i);
+		return 0;
+	}
+
+	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
+		if (!gpuobj->im_backing || (gpuobj->flags & NVOBJ_FLAG_FAKE))
+			continue;
+
+		gpuobj->im_backing_suspend = vmalloc(gpuobj->im_pramin->size);
+		if (!gpuobj->im_backing_suspend) {
+			nouveau_gpuobj_resume(dev);
+			return -ENOMEM;
+		}
+
+		dev_priv->engine.instmem.prepare_access(dev, false);
+		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
+			gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i);
+		dev_priv->engine.instmem.finish_access(dev);
+	}
+
+	return 0;
+}
+
+void
+nouveau_gpuobj_suspend_cleanup(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj;
+
+	if (dev_priv->card_type < NV_50) {
+		vfree(dev_priv->susres.ramin_copy);
+		dev_priv->susres.ramin_copy = NULL;
+		return;
+	}
+
+	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
+		if (!gpuobj->im_backing_suspend)
+			continue;
+
+		vfree(gpuobj->im_backing_suspend);
+		gpuobj->im_backing_suspend = NULL;
+	}
+}
+
+void
+nouveau_gpuobj_resume(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj;
+	int i;
+
+	if (dev_priv->card_type < NV_50) {
+		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
+			nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]);
+		nouveau_gpuobj_suspend_cleanup(dev);
+		return;
+	}
+
+	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
+		if (!gpuobj->im_backing_suspend)
+			continue;
+
+		dev_priv->engine.instmem.prepare_access(dev, true);
+		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
+			nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]);
+		dev_priv->engine.instmem.finish_access(dev);
+	}
+
+	nouveau_gpuobj_suspend_cleanup(dev);
+}
+
+int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_grobj_alloc *init = data;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_pgraph_object_class *grc;
+	struct nouveau_gpuobj *gr = NULL;
+	struct nouveau_channel *chan;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
+
+	if (init->handle == ~0)
+		return -EINVAL;
+
+	grc = pgraph->grclass;
+	while (grc->id) {
+		if (grc->id == init->class)
+			break;
+		grc++;
+	}
+
+	if (!grc->id) {
+		NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class);
+		return -EPERM;
+	}
+
+	if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0)
+		return -EEXIST;
+
+	if (!grc->software)
+		ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr);
+	else
+		ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr);
+
+	if (ret) {
+		NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n",
+			 ret, init->channel, init->handle);
+		return ret;
+	}
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL);
+	if (ret) {
+		NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n",
+			 ret, init->channel, init->handle);
+		nouveau_gpuobj_del(dev, &gr);
+		return ret;
+	}
+
+	return 0;
+}
+
+int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_nouveau_gpuobj_free *objfree = data;
+	struct nouveau_gpuobj_ref *ref;
+	struct nouveau_channel *chan;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
+
+	ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);
+	if (ret)
+		return ret;
+	nouveau_gpuobj_ref_del(dev, &ref);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv20_graph.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -0,0 +1,775 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+/*
+ * NV20
+ * -----
+ * There are 3 families :
+ * NV20 is 0x10de:0x020*
+ * NV25/28 is 0x10de:0x025* / 0x10de:0x028*
+ * NV2A is 0x10de:0x02A0
+ *
+ * NV30
+ * -----
+ * There are 3 families :
+ * NV30/31 is 0x10de:0x030* / 0x10de:0x031*
+ * NV34 is 0x10de:0x032*
+ * NV35/36 is 0x10de:0x033* / 0x10de:0x034*
+ *
+ * Not seen in the wild, no dumps (probably NV35) :
+ * NV37 is 0x10de:0x00fc, 0x10de:0x00fd
+ * NV38 is 0x10de:0x0333, 0x10de:0x00fe
+ *
+ */
+
+#define NV20_GRCTX_SIZE (3580*4)
+#define NV25_GRCTX_SIZE (3529*4)
+#define NV2A_GRCTX_SIZE (3500*4)
+
+#define NV30_31_GRCTX_SIZE (24392)
+#define NV34_GRCTX_SIZE    (18140)
+#define NV35_36_GRCTX_SIZE (22396)
+
+static void
+nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x033c/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x047c/4, 0x00000101);
+	nv_wo32(dev, ctx, 0x0490/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x04a8/4, 0x44400000);
+	for (i = 0x04d4; i <= 0x04e0; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x04f4; i <= 0x0500; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080000);
+	for (i = 0x050c; i <= 0x0518; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x051c; i <= 0x0528; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x000105b8);
+	for (i = 0x052c; i <= 0x0538; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	for (i = 0x055c; i <= 0x0598; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x05fc/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0604/4, 0x00004000);
+	nv_wo32(dev, ctx, 0x0610/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0618/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x061c/4, 0x00010000);
+	for (i = 0x1c1c; i <= 0x248c; i += 16) {
+		nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9);
+		nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c);
+		nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b);
+	}
+	nv_wo32(dev, ctx, 0x281c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2830/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x285c/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2860/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2864/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x286c/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2870/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2878/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x2880/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x34a4/4, 0x000fe000);
+	nv_wo32(dev, ctx, 0x3530/4, 0x000003f8);
+	nv_wo32(dev, ctx, 0x3540/4, 0x002fe000);
+	for (i = 0x355c; i <= 0x3578; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x001c527c);
+}
+
+static void
+nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x035c/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x03c0/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x03c4/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x049c/4, 0x00000101);
+	nv_wo32(dev, ctx, 0x04b0/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x04c8/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x04cc/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x04d0/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x04e4/4, 0x44400000);
+	nv_wo32(dev, ctx, 0x04fc/4, 0x4b800000);
+	for (i = 0x0510; i <= 0x051c; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x0530; i <= 0x053c; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080000);
+	for (i = 0x0548; i <= 0x0554; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x0558; i <= 0x0564; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x000105b8);
+	for (i = 0x0568; i <= 0x0574; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	for (i = 0x0598; i <= 0x05d4; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x05e0/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x0620/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0624/4, 0x30201000);
+	nv_wo32(dev, ctx, 0x0628/4, 0x70605040);
+	nv_wo32(dev, ctx, 0x062c/4, 0xb0a09080);
+	nv_wo32(dev, ctx, 0x0630/4, 0xf0e0d0c0);
+	nv_wo32(dev, ctx, 0x0664/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x066c/4, 0x00004000);
+	nv_wo32(dev, ctx, 0x0678/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0680/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x0684/4, 0x00010000);
+	for (i = 0x1b04; i <= 0x2374; i += 16) {
+		nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9);
+		nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c);
+		nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b);
+	}
+	nv_wo32(dev, ctx, 0x2704/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2718/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2744/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2748/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x274c/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x2754/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2758/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2760/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x2768/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x308c/4, 0x000fe000);
+	nv_wo32(dev, ctx, 0x3108/4, 0x000003f8);
+	nv_wo32(dev, ctx, 0x3468/4, 0x002fe000);
+	for (i = 0x3484; i <= 0x34a0; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x001c527c);
+}
+
+static void
+nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x033c/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x047c/4, 0x00000101);
+	nv_wo32(dev, ctx, 0x0490/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x04a8/4, 0x44400000);
+	for (i = 0x04d4; i <= 0x04e0; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x04f4; i <= 0x0500; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080000);
+	for (i = 0x050c; i <= 0x0518; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x051c; i <= 0x0528; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x000105b8);
+	for (i = 0x052c; i <= 0x0538; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	for (i = 0x055c; i <= 0x0598; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x05fc/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0604/4, 0x00004000);
+	nv_wo32(dev, ctx, 0x0610/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0618/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x061c/4, 0x00010000);
+	for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */
+		nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9);
+		nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c);
+		nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b);
+	}
+	nv_wo32(dev, ctx, 0x269c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x26b0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x26dc/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x26e0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x26e4/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x26ec/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x26f0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x26f8/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x2700/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x3024/4, 0x000fe000);
+	nv_wo32(dev, ctx, 0x30a0/4, 0x000003f8);
+	nv_wo32(dev, ctx, 0x33fc/4, 0x002fe000);
+	for (i = 0x341c; i <= 0x3438; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x001c527c);
+}
+
+static void
+nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x0410/4, 0x00000101);
+	nv_wo32(dev, ctx, 0x0424/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x0428/4, 0x00000060);
+	nv_wo32(dev, ctx, 0x0444/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0448/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x044c/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x0460/4, 0x44400000);
+	nv_wo32(dev, ctx, 0x048c/4, 0xffff0000);
+	for (i = 0x04e0; i < 0x04e8; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x04ec/4, 0x00011100);
+	for (i = 0x0508; i < 0x0548; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x0550/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x058c/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0590/4, 0x30201000);
+	nv_wo32(dev, ctx, 0x0594/4, 0x70605040);
+	nv_wo32(dev, ctx, 0x0598/4, 0xb8a89888);
+	nv_wo32(dev, ctx, 0x059c/4, 0xf8e8d8c8);
+	nv_wo32(dev, ctx, 0x05b0/4, 0xb0000000);
+	for (i = 0x0600; i < 0x0640; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00010588);
+	for (i = 0x0640; i < 0x0680; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x06c0; i < 0x0700; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0008aae4);
+	for (i = 0x0700; i < 0x0740; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x0740; i < 0x0780; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	nv_wo32(dev, ctx, 0x085c/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x0860/4, 0x00010000);
+	for (i = 0x0864; i < 0x0874; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00040004);
+	for (i = 0x1f18; i <= 0x3088 ; i += 16) {
+		nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9);
+		nv_wo32(dev, ctx, i/4 + 1, 0x0436086c);
+		nv_wo32(dev, ctx, i/4 + 2, 0x000c001b);
+	}
+	for (i = 0x30b8; i < 0x30c8; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0000ffff);
+	nv_wo32(dev, ctx, 0x344c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3808/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x381c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3848/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x384c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3850/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x3858/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x385c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3864/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x386c/4, 0xbf800000);
+}
+
+static void
+nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x040c/4, 0x01000101);
+	nv_wo32(dev, ctx, 0x0420/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x0424/4, 0x00000060);
+	nv_wo32(dev, ctx, 0x0440/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0444/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x0448/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x045c/4, 0x44400000);
+	nv_wo32(dev, ctx, 0x0480/4, 0xffff0000);
+	for (i = 0x04d4; i < 0x04dc; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x04e0/4, 0x00011100);
+	for (i = 0x04fc; i < 0x053c; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x0544/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x057c/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0580/4, 0x30201000);
+	nv_wo32(dev, ctx, 0x0584/4, 0x70605040);
+	nv_wo32(dev, ctx, 0x0588/4, 0xb8a89888);
+	nv_wo32(dev, ctx, 0x058c/4, 0xf8e8d8c8);
+	nv_wo32(dev, ctx, 0x05a0/4, 0xb0000000);
+	for (i = 0x05f0; i < 0x0630; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00010588);
+	for (i = 0x0630; i < 0x0670; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x06b0; i < 0x06f0; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0008aae4);
+	for (i = 0x06f0; i < 0x0730; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x0730; i < 0x0770; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	nv_wo32(dev, ctx, 0x0850/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x0854/4, 0x00010000);
+	for (i = 0x0858; i < 0x0868; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00040004);
+	for (i = 0x15ac; i <= 0x271c ; i += 16) {
+		nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9);
+		nv_wo32(dev, ctx, i/4 + 1, 0x0436086c);
+		nv_wo32(dev, ctx, i/4 + 2, 0x000c001b);
+	}
+	for (i = 0x274c; i < 0x275c; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0000ffff);
+	nv_wo32(dev, ctx, 0x2ae0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2e9c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2eb0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2edc/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2ee0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2ee4/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x2eec/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x2ef0/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x2ef8/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x2f00/4, 0xbf800000);
+}
+
+static void
+nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	int i;
+
+	nv_wo32(dev, ctx, 0x040c/4, 0x00000101);
+	nv_wo32(dev, ctx, 0x0420/4, 0x00000111);
+	nv_wo32(dev, ctx, 0x0424/4, 0x00000060);
+	nv_wo32(dev, ctx, 0x0440/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x0444/4, 0xffff0000);
+	nv_wo32(dev, ctx, 0x0448/4, 0x00000001);
+	nv_wo32(dev, ctx, 0x045c/4, 0x44400000);
+	nv_wo32(dev, ctx, 0x0488/4, 0xffff0000);
+	for (i = 0x04dc; i < 0x04e4; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0fff0000);
+	nv_wo32(dev, ctx, 0x04e8/4, 0x00011100);
+	for (i = 0x0504; i < 0x0544; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x07ff0000);
+	nv_wo32(dev, ctx, 0x054c/4, 0x4b7fffff);
+	nv_wo32(dev, ctx, 0x0588/4, 0x00000080);
+	nv_wo32(dev, ctx, 0x058c/4, 0x30201000);
+	nv_wo32(dev, ctx, 0x0590/4, 0x70605040);
+	nv_wo32(dev, ctx, 0x0594/4, 0xb8a89888);
+	nv_wo32(dev, ctx, 0x0598/4, 0xf8e8d8c8);
+	nv_wo32(dev, ctx, 0x05ac/4, 0xb0000000);
+	for (i = 0x0604; i < 0x0644; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00010588);
+	for (i = 0x0644; i < 0x0684; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00030303);
+	for (i = 0x06c4; i < 0x0704; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0008aae4);
+	for (i = 0x0704; i < 0x0744; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x01012000);
+	for (i = 0x0744; i < 0x0784; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00080008);
+	nv_wo32(dev, ctx, 0x0860/4, 0x00040000);
+	nv_wo32(dev, ctx, 0x0864/4, 0x00010000);
+	for (i = 0x0868; i < 0x0878; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x00040004);
+	for (i = 0x1f1c; i <= 0x308c ; i += 16) {
+		nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9);
+		nv_wo32(dev, ctx, i/4 + 1, 0x0436086c);
+		nv_wo32(dev, ctx, i/4 + 2, 0x000c001b);
+	}
+	for (i = 0x30bc; i < 0x30cc; i += 4)
+		nv_wo32(dev, ctx, i/4, 0x0000ffff);
+	nv_wo32(dev, ctx, 0x3450/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x380c/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3820/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x384c/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x3850/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3854/4, 0x3f000000);
+	nv_wo32(dev, ctx, 0x385c/4, 0x40000000);
+	nv_wo32(dev, ctx, 0x3860/4, 0x3f800000);
+	nv_wo32(dev, ctx, 0x3868/4, 0xbf800000);
+	nv_wo32(dev, ctx, 0x3870/4, 0xbf800000);
+}
+
+int
+nv20_graph_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
+	unsigned int ctx_size;
+	unsigned int idoffs = 0x28/4;
+	int ret;
+
+	switch (dev_priv->chipset) {
+	case 0x20:
+		ctx_size = NV20_GRCTX_SIZE;
+		ctx_init = nv20_graph_context_init;
+		idoffs = 0;
+		break;
+	case 0x25:
+	case 0x28:
+		ctx_size = NV25_GRCTX_SIZE;
+		ctx_init = nv25_graph_context_init;
+		break;
+	case 0x2a:
+		ctx_size = NV2A_GRCTX_SIZE;
+		ctx_init = nv2a_graph_context_init;
+		idoffs = 0;
+		break;
+	case 0x30:
+	case 0x31:
+		ctx_size = NV30_31_GRCTX_SIZE;
+		ctx_init = nv30_31_graph_context_init;
+		break;
+	case 0x34:
+		ctx_size = NV34_GRCTX_SIZE;
+		ctx_init = nv34_graph_context_init;
+		break;
+	case 0x35:
+	case 0x36:
+		ctx_size = NV35_36_GRCTX_SIZE;
+		ctx_init = nv35_36_graph_context_init;
+		break;
+	default:
+		ctx_size = 0;
+		ctx_init = nv35_36_graph_context_init;
+		NV_ERROR(dev, "Please contact the devs if you want your NV%x"
+			      " card to work\n", dev_priv->chipset);
+		return -ENOSYS;
+		break;
+	}
+
+	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
+					  NVOBJ_FLAG_ZERO_ALLOC,
+					  &chan->ramin_grctx);
+	if (ret)
+		return ret;
+
+	/* Initialise default context values */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	ctx_init(dev, chan->ramin_grctx->gpuobj);
+
+	/* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */
+	nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs,
+					(chan->id << 24) | 0x1); /* CTX_USER */
+
+	nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id,
+			chan->ramin_grctx->instance >> 4);
+
+	dev_priv->engine.instmem.finish_access(dev);
+	return 0;
+}
+
+void
+nv20_graph_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (chan->ramin_grctx)
+		nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, 0);
+	dev_priv->engine.instmem.finish_access(dev);
+}
+
+int
+nv20_graph_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	uint32_t inst;
+
+	if (!chan->ramin_grctx)
+		return -EINVAL;
+	inst = chan->ramin_grctx->instance >> 4;
+
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
+		     NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD);
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
+
+	nouveau_wait_for_idle(dev);
+	return 0;
+}
+
+int
+nv20_graph_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_channel *chan;
+	uint32_t inst, tmp;
+
+	chan = pgraph->channel(dev);
+	if (!chan)
+		return 0;
+	inst = chan->ramin_grctx->instance >> 4;
+
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
+		     NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
+
+	nouveau_wait_for_idle(dev);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
+	tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
+	tmp |= (pfifo->channels - 1) << 24;
+	nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
+	return 0;
+}
+
+static void
+nv20_graph_rdi(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i, writecount = 32;
+	uint32_t rdi_index = 0x2c80000;
+
+	if (dev_priv->chipset == 0x20) {
+		rdi_index = 0x3d0000;
+		writecount = 15;
+	}
+
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index);
+	for (i = 0; i < writecount; i++)
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0);
+
+	nouveau_wait_for_idle(dev);
+}
+
+void
+nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			     uint32_t size, uint32_t pitch)
+{
+	uint32_t limit = max(1u, addr + size) - 1;
+
+	if (pitch)
+		addr |= 1;
+
+	nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+	nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+	nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit);
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch);
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr);
+}
+
+int
+nv20_graph_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv =
+		(struct drm_nouveau_private *)dev->dev_private;
+	uint32_t tmp, vramsz;
+	int ret, i;
+
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) |  NV_PMC_ENABLE_PGRAPH);
+
+	if (!dev_priv->ctx_table) {
+		/* Create Context Pointer Table */
+		dev_priv->ctx_table_size = 32 * 4;
+		ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
+						  dev_priv->ctx_table_size, 16,
+						  NVOBJ_FLAG_ZERO_ALLOC,
+						  &dev_priv->ctx_table);
+		if (ret)
+			return ret;
+	}
+
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
+		 dev_priv->ctx_table->instance >> 4);
+
+	nv20_graph_rdi(dev);
+
+	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xF3CE0475); /* 0x4 = auto ctx switch */
+	nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
+	nv_wr32(dev, 0x40009C           , 0x00000040);
+
+	if (dev_priv->chipset >= 0x25) {
+		nv_wr32(dev, 0x400890, 0x00080000);
+		nv_wr32(dev, 0x400610, 0x304B1FB6);
+		nv_wr32(dev, 0x400B80, 0x18B82880);
+		nv_wr32(dev, 0x400B84, 0x44000000);
+		nv_wr32(dev, 0x400098, 0x40000080);
+		nv_wr32(dev, 0x400B88, 0x000000ff);
+	} else {
+		nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */
+		nv_wr32(dev, 0x400094, 0x00000005);
+		nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */
+		nv_wr32(dev, 0x400B84, 0x24000000);
+		nv_wr32(dev, 0x400098, 0x00000040);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E10038);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030);
+	}
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+		nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
+
+	for (i = 0; i < 8; i++) {
+		nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4));
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA,
+					nv_rd32(dev, 0x100300 + i * 4));
+	}
+	nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324));
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324));
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
+	nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
+
+	tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) & 0x0007ff00;
+	nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp);
+	tmp = nv_rd32(dev, NV10_PGRAPH_SURFACE) | 0x00020100;
+	nv_wr32(dev, NV10_PGRAPH_SURFACE, tmp);
+
+	/* begin RAM config */
+	vramsz = drm_get_resource_len(dev, 0) - 1;
+	nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
+	nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG0));
+	nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004);
+	nv_wr32(dev, NV10_PGRAPH_RDI_DATA , nv_rd32(dev, NV04_PFB_CFG1));
+	nv_wr32(dev, 0x400820, 0);
+	nv_wr32(dev, 0x400824, 0);
+	nv_wr32(dev, 0x400864, vramsz - 1);
+	nv_wr32(dev, 0x400868, vramsz - 1);
+
+	/* interesting.. the below overwrites some of the tile setup above.. */
+	nv_wr32(dev, 0x400B20, 0x00000000);
+	nv_wr32(dev, 0x400B04, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
+	nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
+	nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
+	nv_wr32(dev, NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
+
+	return 0;
+}
+
+void
+nv20_graph_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nouveau_gpuobj_ref_del(dev, &dev_priv->ctx_table);
+}
+
+int
+nv30_graph_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret, i;
+
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) |  NV_PMC_ENABLE_PGRAPH);
+
+	if (!dev_priv->ctx_table) {
+		/* Create Context Pointer Table */
+		dev_priv->ctx_table_size = 32 * 4;
+		ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
+						  dev_priv->ctx_table_size, 16,
+						  NVOBJ_FLAG_ZERO_ALLOC,
+						  &dev_priv->ctx_table);
+		if (ret)
+			return ret;
+	}
+
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
+			dev_priv->ctx_table->instance >> 4);
+
+	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0);
+	nv_wr32(dev, 0x400890, 0x01b463ff);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf2de0475);
+	nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000);
+	nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0xf04bdff6);
+	nv_wr32(dev, 0x400B80, 0x1003d888);
+	nv_wr32(dev, 0x400B84, 0x0c000000);
+	nv_wr32(dev, 0x400098, 0x00000000);
+	nv_wr32(dev, 0x40009C, 0x0005ad00);
+	nv_wr32(dev, 0x400B88, 0x62ff00ff); /* suspiciously like PGRAPH_DEBUG_2 */
+	nv_wr32(dev, 0x4000a0, 0x00000000);
+	nv_wr32(dev, 0x4000a4, 0x00000008);
+	nv_wr32(dev, 0x4008a8, 0xb784a400);
+	nv_wr32(dev, 0x400ba0, 0x002f8685);
+	nv_wr32(dev, 0x400ba4, 0x00231f3f);
+	nv_wr32(dev, 0x4008a4, 0x40000020);
+
+	if (dev_priv->chipset == 0x34) {
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0004);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00200201);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0008);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000008);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0000);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000032);
+		nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00004);
+		nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000002);
+	}
+
+	nv_wr32(dev, 0x4000c0, 0x00000016);
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+		nv20_graph_set_region_tiling(dev, i, 0, 0, 0);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
+	nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
+	nv_wr32(dev, 0x0040075c             , 0x00000001);
+
+	/* begin RAM config */
+	/* vramsz = drm_get_resource_len(dev, 0) - 1; */
+	nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
+	nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
+	if (dev_priv->chipset != 0x34) {
+		nv_wr32(dev, 0x400750, 0x00EA0000);
+		nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG0));
+		nv_wr32(dev, 0x400750, 0x00EA0004);
+		nv_wr32(dev, 0x400754, nv_rd32(dev, NV04_PFB_CFG1));
+	}
+
+	return 0;
+}
+
+struct nouveau_pgraph_object_class nv20_graph_grclass[] = {
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x0039, false, NULL }, /* m2mf */
+	{ 0x004a, false, NULL }, /* gdirect */
+	{ 0x009f, false, NULL }, /* imageblit (nv12) */
+	{ 0x008a, false, NULL }, /* ifc */
+	{ 0x0089, false, NULL }, /* sifm */
+	{ 0x0062, false, NULL }, /* surf2d */
+	{ 0x0043, false, NULL }, /* rop */
+	{ 0x0012, false, NULL }, /* beta1 */
+	{ 0x0072, false, NULL }, /* beta4 */
+	{ 0x0019, false, NULL }, /* cliprect */
+	{ 0x0044, false, NULL }, /* pattern */
+	{ 0x009e, false, NULL }, /* swzsurf */
+	{ 0x0096, false, NULL }, /* celcius */
+	{ 0x0097, false, NULL }, /* kelvin (nv20) */
+	{ 0x0597, false, NULL }, /* kelvin (nv25) */
+	{}
+};
+
+struct nouveau_pgraph_object_class nv30_graph_grclass[] = {
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x0039, false, NULL }, /* m2mf */
+	{ 0x004a, false, NULL }, /* gdirect */
+	{ 0x009f, false, NULL }, /* imageblit (nv12) */
+	{ 0x008a, false, NULL }, /* ifc */
+	{ 0x038a, false, NULL }, /* ifc (nv30) */
+	{ 0x0089, false, NULL }, /* sifm */
+	{ 0x0389, false, NULL }, /* sifm (nv30) */
+	{ 0x0062, false, NULL }, /* surf2d */
+	{ 0x0362, false, NULL }, /* surf2d (nv30) */
+	{ 0x0043, false, NULL }, /* rop */
+	{ 0x0012, false, NULL }, /* beta1 */
+	{ 0x0072, false, NULL }, /* beta4 */
+	{ 0x0019, false, NULL }, /* cliprect */
+	{ 0x0044, false, NULL }, /* pattern */
+	{ 0x039e, false, NULL }, /* swzsurf */
+	{ 0x0397, false, NULL }, /* rankine (nv30) */
+	{ 0x0497, false, NULL }, /* rankine (nv35) */
+	{ 0x0697, false, NULL }, /* rankine (nv34) */
+	{}
+};
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv40_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv40_fb.c
@@ -0,0 +1,75 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+void
+nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			  uint32_t size, uint32_t pitch)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t limit = max(1u, addr + size) - 1;
+
+	if (pitch)
+		addr |= 1;
+
+	switch (dev_priv->chipset) {
+	case 0x40:
+		nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
+		nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
+		nv_wr32(dev, NV10_PFB_TILE(i), addr);
+		break;
+
+	default:
+		nv_wr32(dev, NV40_PFB_TLIMIT(i), limit);
+		nv_wr32(dev, NV40_PFB_TSIZE(i), pitch);
+		nv_wr32(dev, NV40_PFB_TILE(i), addr);
+		break;
+	}
+}
+
+int
+nv40_fb_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	uint32_t tmp;
+	int i;
+
+	/* This is strictly a NV4x register (don't know about NV5x). */
+	/* The blob sets these to all kinds of values, and they mess up our setup. */
+	/* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */
+	/* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */
+	/* Any idea what this is? */
+	nv_wr32(dev, NV40_PFB_UNK_800, 0x1);
+
+	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x45:
+		tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2);
+		nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15));
+		pfb->num_tiles = NV10_PFB_TILE__SIZE;
+		break;
+	case 0x46: /* G72 */
+	case 0x47: /* G70 */
+	case 0x49: /* G71 */
+	case 0x4b: /* G73 */
+	case 0x4c: /* C51 (G7X version) */
+		pfb->num_tiles = NV40_PFB_TILE__SIZE_1;
+		break;
+	default:
+		pfb->num_tiles = NV40_PFB_TILE__SIZE_0;
+		break;
+	}
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < pfb->num_tiles; i++)
+		pfb->set_region_tiling(dev, i, 0, 0, 0);
+
+	return 0;
+}
+
+void
+nv40_fb_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_hw.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_hw.h
@@ -0,0 +1,455 @@
+/*
+ * Copyright 2008 Stuart Bennett
+ *
+ * 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 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 __NOUVEAU_HW_H__
+#define __NOUVEAU_HW_H__
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+
+#define MASK(field) ( \
+	(0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field))
+
+#define XLATE(src, srclowbit, outfield) ( \
+	(((src) >> (srclowbit)) << (0 ? outfield)) & MASK(outfield))
+
+void NVWriteVgaSeq(struct drm_device *, int head, uint8_t index, uint8_t value);
+uint8_t NVReadVgaSeq(struct drm_device *, int head, uint8_t index);
+void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value);
+uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index);
+void NVSetOwner(struct drm_device *, int owner);
+void NVBlankScreen(struct drm_device *, int head, bool blank);
+void nouveau_hw_setpll(struct drm_device *, uint32_t reg1,
+		       struct nouveau_pll_vals *pv);
+int nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype,
+			   struct nouveau_pll_vals *pllvals);
+int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals);
+int nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype);
+void nouveau_hw_save_vga_fonts(struct drm_device *, bool save);
+void nouveau_hw_save_state(struct drm_device *, int head,
+			   struct nv04_mode_state *state);
+void nouveau_hw_load_state(struct drm_device *, int head,
+			   struct nv04_mode_state *state);
+void nouveau_hw_load_state_palette(struct drm_device *, int head,
+				   struct nv04_mode_state *state);
+
+/* nouveau_calc.c */
+extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
+			     int *burst, int *lwm);
+extern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim,
+				int clk, struct nouveau_pll_vals *pv);
+
+static inline uint32_t
+nvReadMC(struct drm_device *dev, uint32_t reg)
+{
+	uint32_t val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val);
+	return val;
+}
+
+static inline void
+nvWriteMC(struct drm_device *dev, uint32_t reg, uint32_t val)
+{
+	NV_REG_DEBUG(MC, dev, "reg %08x val %08x\n", reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t
+nvReadVIDEO(struct drm_device *dev, uint32_t reg)
+{
+	uint32_t val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val);
+	return val;
+}
+
+static inline void
+nvWriteVIDEO(struct drm_device *dev, uint32_t reg, uint32_t val)
+{
+	NV_REG_DEBUG(VIDEO, dev, "reg %08x val %08x\n", reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t
+nvReadFB(struct drm_device *dev, uint32_t reg)
+{
+	uint32_t val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val);
+	return val;
+}
+
+static inline void
+nvWriteFB(struct drm_device *dev, uint32_t reg, uint32_t val)
+{
+	NV_REG_DEBUG(FB, dev, "reg %08x val %08x\n", reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t
+nvReadEXTDEV(struct drm_device *dev, uint32_t reg)
+{
+	uint32_t val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val);
+	return val;
+}
+
+static inline void
+nvWriteEXTDEV(struct drm_device *dev, uint32_t reg, uint32_t val)
+{
+	NV_REG_DEBUG(EXTDEV, dev, "reg %08x val %08x\n", reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t NVReadCRTC(struct drm_device *dev,
+					int head, uint32_t reg)
+{
+	uint32_t val;
+	if (head)
+		reg += NV_PCRTC0_SIZE;
+	val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val);
+	return val;
+}
+
+static inline void NVWriteCRTC(struct drm_device *dev,
+					int head, uint32_t reg, uint32_t val)
+{
+	if (head)
+		reg += NV_PCRTC0_SIZE;
+	NV_REG_DEBUG(CRTC, dev, "head %d reg %08x val %08x\n", head, reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
+					int head, uint32_t reg)
+{
+	uint32_t val;
+	if (head)
+		reg += NV_PRAMDAC0_SIZE;
+	val = nv_rd32(dev, reg);
+	NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n",
+							head, reg, val);
+	return val;
+}
+
+static inline void NVWriteRAMDAC(struct drm_device *dev,
+					int head, uint32_t reg, uint32_t val)
+{
+	if (head)
+		reg += NV_PRAMDAC0_SIZE;
+	NV_REG_DEBUG(RAMDAC, dev, "head %d reg %08x val %08x\n",
+							head, reg, val);
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint8_t nv_read_tmds(struct drm_device *dev,
+					int or, int dl, uint8_t address)
+{
+	int ramdac = (or & OUTPUT_C) >> 2;
+
+	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8,
+	NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
+	return NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8);
+}
+
+static inline void nv_write_tmds(struct drm_device *dev,
+					int or, int dl, uint8_t address,
+					uint8_t data)
+{
+	int ramdac = (or & OUTPUT_C) >> 2;
+
+	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data);
+	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address);
+}
+
+static inline void NVWriteVgaCrtc(struct drm_device *dev,
+					int head, uint8_t index, uint8_t value)
+{
+	NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n",
+							head, index, value);
+	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+	nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
+}
+
+static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
+					int head, uint8_t index)
+{
+	uint8_t val;
+	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
+	val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
+	NV_REG_DEBUG(VGACRTC, dev, "head %d index 0x%02x data 0x%02x\n",
+							head, index, val);
+	return val;
+}
+
+/* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
+ * I suspect they in fact do nothing, but are merely a way to carry useful
+ * per-head variables around
+ *
+ * Known uses:
+ * CR57		CR58
+ * 0x00		index to the appropriate dcb entry (or 7f for inactive)
+ * 0x02		dcb entry's "or" value (or 00 for inactive)
+ * 0x03		bit0 set for dual link (LVDS, possibly elsewhere too)
+ * 0x08 or 0x09	pxclk in MHz
+ * 0x0f		laptop panel info -	low nibble for PEXTDEV_BOOT_0 strap
+ * 					high nibble for xlat strap value
+ */
+
+static inline void
+NVWriteVgaCrtc5758(struct drm_device *dev, int head, uint8_t index, uint8_t value)
+{
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_58, value);
+}
+
+static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_t index)
+{
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_57, index);
+	return NVReadVgaCrtc(dev, head, NV_CIO_CRE_58);
+}
+
+static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
+					int head, uint32_t reg)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint8_t val;
+
+	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
+	 * NVSetOwner for the relevant head to be programmed */
+	if (head && dev_priv->card_type == NV_40)
+		reg += NV_PRMVIO_SIZE;
+
+	val = nv_rd08(dev, reg);
+	NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n", head, reg, val);
+	return val;
+}
+
+static inline void NVWritePRMVIO(struct drm_device *dev,
+					int head, uint32_t reg, uint8_t value)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
+	 * NVSetOwner for the relevant head to be programmed */
+	if (head && dev_priv->card_type == NV_40)
+		reg += NV_PRMVIO_SIZE;
+
+	NV_REG_DEBUG(RMVIO, dev, "head %d reg %08x val %02x\n",
+						head, reg, value);
+	nv_wr08(dev, reg, value);
+}
+
+static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
+{
+	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
+}
+
+static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
+{
+	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
+}
+
+static inline void NVWriteVgaAttr(struct drm_device *dev,
+					int head, uint8_t index, uint8_t value)
+{
+	if (NVGetEnablePalette(dev, head))
+		index &= ~0x20;
+	else
+		index |= 0x20;
+
+	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n",
+							head, index, value);
+	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+	nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
+}
+
+static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
+					int head, uint8_t index)
+{
+	uint8_t val;
+	if (NVGetEnablePalette(dev, head))
+		index &= ~0x20;
+	else
+		index |= 0x20;
+
+	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
+	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
+	val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
+	NV_REG_DEBUG(VGAATTR, dev, "head %d index 0x%02x data 0x%02x\n",
+							head, index, val);
+	return val;
+}
+
+static inline void NVVgaSeqReset(struct drm_device *dev, int head, bool start)
+{
+	NVWriteVgaSeq(dev, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3);
+}
+
+static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
+{
+	uint8_t seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX);
+
+	if (protect) {
+		NVVgaSeqReset(dev, head, true);
+		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
+	} else {
+		/* Reenable sequencer, then turn on screen */
+		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);   /* reenable display */
+		NVVgaSeqReset(dev, head, false);
+	}
+	NVSetEnablePalette(dev, head, protect);
+}
+
+static inline bool
+nv_heads_tied(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset == 0x11)
+		return !!(nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28));
+
+	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
+}
+
+/* makes cr0-7 on the specified head read-only */
+static inline bool
+nv_lock_vga_crtc_base(struct drm_device *dev, int head, bool lock)
+{
+	uint8_t cr11 = NVReadVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX);
+	bool waslocked = cr11 & 0x80;
+
+	if (lock)
+		cr11 |= 0x80;
+	else
+		cr11 &= ~0x80;
+	NVWriteVgaCrtc(dev, head, NV_CIO_CR_VRE_INDEX, cr11);
+
+	return waslocked;
+}
+
+static inline void
+nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock)
+{
+	/* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
+	 * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
+	 * bit6: seems to have some effect on CR09 (double scan, VBS_9)
+	 * bit5: unlocks HDE
+	 * bit4: unlocks VDE
+	 * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
+	 * bit2: same as bit 1 of 0x60?804
+	 * bit0: same as bit 0 of 0x60?804
+	 */
+
+	uint8_t cr21 = lock;
+
+	if (lock < 0)
+		/* 0xfa is generic "unlock all" mask */
+		cr21 = NVReadVgaCrtc(dev, head, NV_CIO_CRE_21) | 0xfa;
+
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_21, cr21);
+}
+
+/* renders the extended crtc regs (cr19+) on all crtcs impervious:
+ * immutable and unreadable
+ */
+static inline bool
+NVLockVgaCrtcs(struct drm_device *dev, bool lock)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
+
+	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
+		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
+	/* NV11 has independently lockable extended crtcs, except when tied */
+	if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev))
+		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
+			       lock ? NV_CIO_SR_LOCK_VALUE :
+				      NV_CIO_SR_UNLOCK_RW_VALUE);
+
+	return waslocked;
+}
+
+/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
+#define NV04_CURSOR_SIZE 32
+/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
+#define NV10_CURSOR_SIZE 64
+
+static inline int nv_cursor_width(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
+}
+
+static inline void
+nv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
+{
+	/* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
+	 * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
+	 * for changes to the CRTC CURCTL regs to take effect, whether changing
+	 * the pixmap location, or just showing/hiding the cursor
+	 */
+	uint32_t curpos = NVReadRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_CU_START_POS, curpos);
+}
+
+static inline void
+nv_show_cursor(struct drm_device *dev, int head, bool show)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint8_t *curctl1 =
+		&dev_priv->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
+
+	if (show)
+		*curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
+	else
+		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
+
+	if (dev_priv->card_type == NV_40)
+		nv_fix_nv40_hw_cursor(dev, head);
+}
+
+static inline uint32_t
+nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int mask;
+
+	if (bpp == 15)
+		bpp = 16;
+	if (bpp == 24)
+		bpp = 8;
+
+	/* Alignment requirements taken from the Haiku driver */
+	if (dev_priv->card_type == NV_04)
+		mask = 128 / bpp - 1;
+	else
+		mask = 512 / bpp - 1;
+
+	return (width + mask) & ~mask;
+}
+
+#endif	/* __NOUVEAU_HW_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_reg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_reg.h
@@ -0,0 +1,837 @@
+
+
+#define NV03_BOOT_0                                        0x00100000
+#    define NV03_BOOT_0_RAM_AMOUNT                         0x00000003
+#    define NV03_BOOT_0_RAM_AMOUNT_8MB                     0x00000000
+#    define NV03_BOOT_0_RAM_AMOUNT_2MB                     0x00000001
+#    define NV03_BOOT_0_RAM_AMOUNT_4MB                     0x00000002
+#    define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM               0x00000003
+#    define NV04_BOOT_0_RAM_AMOUNT_32MB                    0x00000000
+#    define NV04_BOOT_0_RAM_AMOUNT_4MB                     0x00000001
+#    define NV04_BOOT_0_RAM_AMOUNT_8MB                     0x00000002
+#    define NV04_BOOT_0_RAM_AMOUNT_16MB                    0x00000003
+
+#define NV04_FIFO_DATA                                     0x0010020c
+#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK              0xfff00000
+#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT             20
+
+#define NV_RAMIN                                           0x00700000
+
+#define NV_RAMHT_HANDLE_OFFSET                             0
+#define NV_RAMHT_CONTEXT_OFFSET                            4
+#    define NV_RAMHT_CONTEXT_VALID                         (1<<31)
+#    define NV_RAMHT_CONTEXT_CHANNEL_SHIFT                 24
+#    define NV_RAMHT_CONTEXT_ENGINE_SHIFT                  16
+#        define NV_RAMHT_CONTEXT_ENGINE_SOFTWARE           0
+#        define NV_RAMHT_CONTEXT_ENGINE_GRAPHICS           1
+#    define NV_RAMHT_CONTEXT_INSTANCE_SHIFT                0
+#    define NV40_RAMHT_CONTEXT_CHANNEL_SHIFT               23
+#    define NV40_RAMHT_CONTEXT_ENGINE_SHIFT                20
+#    define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT              0
+
+/* DMA object defines */
+#define NV_DMA_ACCESS_RW 0
+#define NV_DMA_ACCESS_RO 1
+#define NV_DMA_ACCESS_WO 2
+#define NV_DMA_TARGET_VIDMEM 0
+#define NV_DMA_TARGET_PCI    2
+#define NV_DMA_TARGET_AGP    3
+/* The following is not a real value used by the card, it's changed by
+ * nouveau_object_dma_create */
+#define NV_DMA_TARGET_PCI_NONLINEAR 8
+
+/* Some object classes we care about in the drm */
+#define NV_CLASS_DMA_FROM_MEMORY                           0x00000002
+#define NV_CLASS_DMA_TO_MEMORY                             0x00000003
+#define NV_CLASS_NULL                                      0x00000030
+#define NV_CLASS_DMA_IN_MEMORY                             0x0000003D
+
+#define NV03_USER(i)                             (0x00800000+(i*NV03_USER_SIZE))
+#define NV03_USER__SIZE                                                       16
+#define NV10_USER__SIZE                                                       32
+#define NV03_USER_SIZE                                                0x00010000
+#define NV03_USER_DMA_PUT(i)                     (0x00800040+(i*NV03_USER_SIZE))
+#define NV03_USER_DMA_PUT__SIZE                                               16
+#define NV10_USER_DMA_PUT__SIZE                                               32
+#define NV03_USER_DMA_GET(i)                     (0x00800044+(i*NV03_USER_SIZE))
+#define NV03_USER_DMA_GET__SIZE                                               16
+#define NV10_USER_DMA_GET__SIZE                                               32
+#define NV03_USER_REF_CNT(i)                     (0x00800048+(i*NV03_USER_SIZE))
+#define NV03_USER_REF_CNT__SIZE                                               16
+#define NV10_USER_REF_CNT__SIZE                                               32
+
+#define NV40_USER(i)                             (0x00c00000+(i*NV40_USER_SIZE))
+#define NV40_USER_SIZE                                                0x00001000
+#define NV40_USER_DMA_PUT(i)                     (0x00c00040+(i*NV40_USER_SIZE))
+#define NV40_USER_DMA_PUT__SIZE                                               32
+#define NV40_USER_DMA_GET(i)                     (0x00c00044+(i*NV40_USER_SIZE))
+#define NV40_USER_DMA_GET__SIZE                                               32
+#define NV40_USER_REF_CNT(i)                     (0x00c00048+(i*NV40_USER_SIZE))
+#define NV40_USER_REF_CNT__SIZE                                               32
+
+#define NV50_USER(i)                             (0x00c00000+(i*NV50_USER_SIZE))
+#define NV50_USER_SIZE                                                0x00002000
+#define NV50_USER_DMA_PUT(i)                     (0x00c00040+(i*NV50_USER_SIZE))
+#define NV50_USER_DMA_PUT__SIZE                                              128
+#define NV50_USER_DMA_GET(i)                     (0x00c00044+(i*NV50_USER_SIZE))
+#define NV50_USER_DMA_GET__SIZE                                              128
+#define NV50_USER_REF_CNT(i)                     (0x00c00048+(i*NV50_USER_SIZE))
+#define NV50_USER_REF_CNT__SIZE                                              128
+
+#define NV03_FIFO_SIZE                                     0x8000UL
+
+#define NV03_PMC_BOOT_0                                    0x00000000
+#define NV03_PMC_BOOT_1                                    0x00000004
+#define NV03_PMC_INTR_0                                    0x00000100
+#    define NV_PMC_INTR_0_PFIFO_PENDING                        (1<<8)
+#    define NV_PMC_INTR_0_PGRAPH_PENDING                      (1<<12)
+#    define NV_PMC_INTR_0_NV50_I2C_PENDING                    (1<<21)
+#    define NV_PMC_INTR_0_CRTC0_PENDING                       (1<<24)
+#    define NV_PMC_INTR_0_CRTC1_PENDING                       (1<<25)
+#    define NV_PMC_INTR_0_NV50_DISPLAY_PENDING                (1<<26)
+#    define NV_PMC_INTR_0_CRTCn_PENDING                       (3<<24)
+#define NV03_PMC_INTR_EN_0                                 0x00000140
+#    define NV_PMC_INTR_EN_0_MASTER_ENABLE                     (1<<0)
+#define NV03_PMC_ENABLE                                    0x00000200
+#    define NV_PMC_ENABLE_PFIFO                                (1<<8)
+#    define NV_PMC_ENABLE_PGRAPH                              (1<<12)
+/* Disabling the below bit breaks newer (G7X only?) mobile chipsets,
+ * the card will hang early on in the X init process.
+ */
+#    define NV_PMC_ENABLE_UNK13                               (1<<13)
+#define NV40_PMC_GRAPH_UNITS				   0x00001540
+#define NV40_PMC_BACKLIGHT				   0x000015f0
+#	define NV40_PMC_BACKLIGHT_MASK			   0x001f0000
+#define NV40_PMC_1700                                      0x00001700
+#define NV40_PMC_1704                                      0x00001704
+#define NV40_PMC_1708                                      0x00001708
+#define NV40_PMC_170C                                      0x0000170C
+
+/* probably PMC ? */
+#define NV50_PUNK_BAR0_PRAMIN                              0x00001700
+#define NV50_PUNK_BAR_CFG_BASE                             0x00001704
+#define NV50_PUNK_BAR_CFG_BASE_VALID                          (1<<30)
+#define NV50_PUNK_BAR1_CTXDMA                              0x00001708
+#define NV50_PUNK_BAR1_CTXDMA_VALID                           (1<<31)
+#define NV50_PUNK_BAR3_CTXDMA                              0x0000170C
+#define NV50_PUNK_BAR3_CTXDMA_VALID                           (1<<31)
+#define NV50_PUNK_UNK1710                                  0x00001710
+
+#define NV04_PBUS_PCI_NV_1                                 0x00001804
+#define NV04_PBUS_PCI_NV_19                                0x0000184C
+#define NV04_PBUS_PCI_NV_20				0x00001850
+#	define NV04_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED		(0 << 0)
+#	define NV04_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED		(1 << 0)
+
+#define NV04_PTIMER_INTR_0                                 0x00009100
+#define NV04_PTIMER_INTR_EN_0                              0x00009140
+#define NV04_PTIMER_NUMERATOR                              0x00009200
+#define NV04_PTIMER_DENOMINATOR                            0x00009210
+#define NV04_PTIMER_TIME_0                                 0x00009400
+#define NV04_PTIMER_TIME_1                                 0x00009410
+#define NV04_PTIMER_ALARM_0                                0x00009420
+
+#define NV04_PFB_CFG0                                      0x00100200
+#define NV04_PFB_CFG1                                      0x00100204
+#define NV40_PFB_020C                                      0x0010020C
+#define NV10_PFB_TILE(i)                                   (0x00100240 + (i*16))
+#define NV10_PFB_TILE__SIZE                                8
+#define NV10_PFB_TLIMIT(i)                                 (0x00100244 + (i*16))
+#define NV10_PFB_TSIZE(i)                                  (0x00100248 + (i*16))
+#define NV10_PFB_TSTATUS(i)                                (0x0010024C + (i*16))
+#define NV10_PFB_CLOSE_PAGE2                               0x0010033C
+#define NV40_PFB_TILE(i)                                   (0x00100600 + (i*16))
+#define NV40_PFB_TILE__SIZE_0                              12
+#define NV40_PFB_TILE__SIZE_1                              15
+#define NV40_PFB_TLIMIT(i)                                 (0x00100604 + (i*16))
+#define NV40_PFB_TSIZE(i)                                  (0x00100608 + (i*16))
+#define NV40_PFB_TSTATUS(i)                                (0x0010060C + (i*16))
+#define NV40_PFB_UNK_800					0x00100800
+
+#define NV04_PGRAPH_DEBUG_0                                0x00400080
+#define NV04_PGRAPH_DEBUG_1                                0x00400084
+#define NV04_PGRAPH_DEBUG_2                                0x00400088
+#define NV04_PGRAPH_DEBUG_3                                0x0040008c
+#define NV10_PGRAPH_DEBUG_4                                0x00400090
+#define NV03_PGRAPH_INTR                                   0x00400100
+#define NV03_PGRAPH_NSTATUS                                0x00400104
+#    define NV04_PGRAPH_NSTATUS_STATE_IN_USE                  (1<<11)
+#    define NV04_PGRAPH_NSTATUS_INVALID_STATE                 (1<<12)
+#    define NV04_PGRAPH_NSTATUS_BAD_ARGUMENT                  (1<<13)
+#    define NV04_PGRAPH_NSTATUS_PROTECTION_FAULT              (1<<14)
+#    define NV10_PGRAPH_NSTATUS_STATE_IN_USE                  (1<<23)
+#    define NV10_PGRAPH_NSTATUS_INVALID_STATE                 (1<<24)
+#    define NV10_PGRAPH_NSTATUS_BAD_ARGUMENT                  (1<<25)
+#    define NV10_PGRAPH_NSTATUS_PROTECTION_FAULT              (1<<26)
+#define NV03_PGRAPH_NSOURCE                                0x00400108
+#    define NV03_PGRAPH_NSOURCE_NOTIFICATION                   (1<<0)
+#    define NV03_PGRAPH_NSOURCE_DATA_ERROR                     (1<<1)
+#    define NV03_PGRAPH_NSOURCE_PROTECTION_ERROR               (1<<2)
+#    define NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION                (1<<3)
+#    define NV03_PGRAPH_NSOURCE_LIMIT_COLOR                    (1<<4)
+#    define NV03_PGRAPH_NSOURCE_LIMIT_ZETA                     (1<<5)
+#    define NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD                   (1<<6)
+#    define NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION               (1<<7)
+#    define NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION               (1<<8)
+#    define NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION               (1<<9)
+#    define NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION               (1<<10)
+#    define NV03_PGRAPH_NSOURCE_STATE_INVALID                 (1<<11)
+#    define NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY                 (1<<12)
+#    define NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE                 (1<<13)
+#    define NV03_PGRAPH_NSOURCE_METHOD_CNT                    (1<<14)
+#    define NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION              (1<<15)
+#    define NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION            (1<<16)
+#    define NV03_PGRAPH_NSOURCE_DMA_WIDTH_A                   (1<<17)
+#    define NV03_PGRAPH_NSOURCE_DMA_WIDTH_B                   (1<<18)
+#define NV03_PGRAPH_INTR_EN                                0x00400140
+#define NV40_PGRAPH_INTR_EN                                0x0040013C
+#    define NV_PGRAPH_INTR_NOTIFY                              (1<<0)
+#    define NV_PGRAPH_INTR_MISSING_HW                          (1<<4)
+#    define NV_PGRAPH_INTR_CONTEXT_SWITCH                     (1<<12)
+#    define NV_PGRAPH_INTR_BUFFER_NOTIFY                      (1<<16)
+#    define NV_PGRAPH_INTR_ERROR                              (1<<20)
+#define NV10_PGRAPH_CTX_CONTROL                            0x00400144
+#define NV10_PGRAPH_CTX_USER                               0x00400148
+#define NV10_PGRAPH_CTX_SWITCH1                            0x0040014C
+#define NV10_PGRAPH_CTX_SWITCH2                            0x00400150
+#define NV10_PGRAPH_CTX_SWITCH3                            0x00400154
+#define NV10_PGRAPH_CTX_SWITCH4                            0x00400158
+#define NV10_PGRAPH_CTX_SWITCH5                            0x0040015C
+#define NV04_PGRAPH_CTX_SWITCH1                            0x00400160
+#define NV10_PGRAPH_CTX_CACHE1                             0x00400160
+#define NV04_PGRAPH_CTX_SWITCH2                            0x00400164
+#define NV04_PGRAPH_CTX_SWITCH3                            0x00400168
+#define NV04_PGRAPH_CTX_SWITCH4                            0x0040016C
+#define NV04_PGRAPH_CTX_CONTROL                            0x00400170
+#define NV04_PGRAPH_CTX_USER                               0x00400174
+#define NV04_PGRAPH_CTX_CACHE1                             0x00400180
+#define NV10_PGRAPH_CTX_CACHE2                             0x00400180
+#define NV03_PGRAPH_CTX_CONTROL                            0x00400190
+#define NV03_PGRAPH_CTX_USER                               0x00400194
+#define NV04_PGRAPH_CTX_CACHE2                             0x004001A0
+#define NV10_PGRAPH_CTX_CACHE3                             0x004001A0
+#define NV04_PGRAPH_CTX_CACHE3                             0x004001C0
+#define NV10_PGRAPH_CTX_CACHE4                             0x004001C0
+#define NV04_PGRAPH_CTX_CACHE4                             0x004001E0
+#define NV10_PGRAPH_CTX_CACHE5                             0x004001E0
+#define NV40_PGRAPH_CTXCTL_0304                            0x00400304
+#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX                   0x00000001
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT                      0x00400308
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_MASK              0xff000000
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT                     24
+#define NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK              0x00ffffff
+#define NV40_PGRAPH_CTXCTL_0310                            0x00400310
+#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE                  0x00000020
+#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD                  0x00000040
+#define NV40_PGRAPH_CTXCTL_030C                            0x0040030c
+#define NV40_PGRAPH_CTXCTL_UCODE_INDEX                     0x00400324
+#define NV40_PGRAPH_CTXCTL_UCODE_DATA                      0x00400328
+#define NV40_PGRAPH_CTXCTL_CUR                             0x0040032c
+#define NV40_PGRAPH_CTXCTL_CUR_LOADED                      0x01000000
+#define NV40_PGRAPH_CTXCTL_CUR_INSTANCE                    0x000FFFFF
+#define NV40_PGRAPH_CTXCTL_NEXT                            0x00400330
+#define NV40_PGRAPH_CTXCTL_NEXT_INSTANCE                   0x000fffff
+#define NV50_PGRAPH_CTXCTL_CUR                             0x0040032c
+#define NV50_PGRAPH_CTXCTL_CUR_LOADED                      0x80000000
+#define NV50_PGRAPH_CTXCTL_CUR_INSTANCE                    0x00ffffff
+#define NV50_PGRAPH_CTXCTL_NEXT                            0x00400330
+#define NV50_PGRAPH_CTXCTL_NEXT_INSTANCE                   0x00ffffff
+#define NV03_PGRAPH_ABS_X_RAM                              0x00400400
+#define NV03_PGRAPH_ABS_Y_RAM                              0x00400480
+#define NV03_PGRAPH_X_MISC                                 0x00400500
+#define NV03_PGRAPH_Y_MISC                                 0x00400504
+#define NV04_PGRAPH_VALID1                                 0x00400508
+#define NV04_PGRAPH_SOURCE_COLOR                           0x0040050C
+#define NV04_PGRAPH_MISC24_0                               0x00400510
+#define NV03_PGRAPH_XY_LOGIC_MISC0                         0x00400514
+#define NV03_PGRAPH_XY_LOGIC_MISC1                         0x00400518
+#define NV03_PGRAPH_XY_LOGIC_MISC2                         0x0040051C
+#define NV03_PGRAPH_XY_LOGIC_MISC3                         0x00400520
+#define NV03_PGRAPH_CLIPX_0                                0x00400524
+#define NV03_PGRAPH_CLIPX_1                                0x00400528
+#define NV03_PGRAPH_CLIPY_0                                0x0040052C
+#define NV03_PGRAPH_CLIPY_1                                0x00400530
+#define NV03_PGRAPH_ABS_ICLIP_XMAX                         0x00400534
+#define NV03_PGRAPH_ABS_ICLIP_YMAX                         0x00400538
+#define NV03_PGRAPH_ABS_UCLIP_XMIN                         0x0040053C
+#define NV03_PGRAPH_ABS_UCLIP_YMIN                         0x00400540
+#define NV03_PGRAPH_ABS_UCLIP_XMAX                         0x00400544
+#define NV03_PGRAPH_ABS_UCLIP_YMAX                         0x00400548
+#define NV03_PGRAPH_ABS_UCLIPA_XMIN                        0x00400560
+#define NV03_PGRAPH_ABS_UCLIPA_YMIN                        0x00400564
+#define NV03_PGRAPH_ABS_UCLIPA_XMAX                        0x00400568
+#define NV03_PGRAPH_ABS_UCLIPA_YMAX                        0x0040056C
+#define NV04_PGRAPH_MISC24_1                               0x00400570
+#define NV04_PGRAPH_MISC24_2                               0x00400574
+#define NV04_PGRAPH_VALID2                                 0x00400578
+#define NV04_PGRAPH_PASSTHRU_0                             0x0040057C
+#define NV04_PGRAPH_PASSTHRU_1                             0x00400580
+#define NV04_PGRAPH_PASSTHRU_2                             0x00400584
+#define NV10_PGRAPH_DIMX_TEXTURE                           0x00400588
+#define NV10_PGRAPH_WDIMX_TEXTURE                          0x0040058C
+#define NV04_PGRAPH_COMBINE_0_ALPHA                        0x00400590
+#define NV04_PGRAPH_COMBINE_0_COLOR                        0x00400594
+#define NV04_PGRAPH_COMBINE_1_ALPHA                        0x00400598
+#define NV04_PGRAPH_COMBINE_1_COLOR                        0x0040059C
+#define NV04_PGRAPH_FORMAT_0                               0x004005A8
+#define NV04_PGRAPH_FORMAT_1                               0x004005AC
+#define NV04_PGRAPH_FILTER_0                               0x004005B0
+#define NV04_PGRAPH_FILTER_1                               0x004005B4
+#define NV03_PGRAPH_MONO_COLOR0                            0x00400600
+#define NV04_PGRAPH_ROP3                                   0x00400604
+#define NV04_PGRAPH_BETA_AND                               0x00400608
+#define NV04_PGRAPH_BETA_PREMULT                           0x0040060C
+#define NV04_PGRAPH_LIMIT_VIOL_PIX                         0x00400610
+#define NV04_PGRAPH_FORMATS                                0x00400618
+#define NV10_PGRAPH_DEBUG_2                                0x00400620
+#define NV04_PGRAPH_BOFFSET0                               0x00400640
+#define NV04_PGRAPH_BOFFSET1                               0x00400644
+#define NV04_PGRAPH_BOFFSET2                               0x00400648
+#define NV04_PGRAPH_BOFFSET3                               0x0040064C
+#define NV04_PGRAPH_BOFFSET4                               0x00400650
+#define NV04_PGRAPH_BOFFSET5                               0x00400654
+#define NV04_PGRAPH_BBASE0                                 0x00400658
+#define NV04_PGRAPH_BBASE1                                 0x0040065C
+#define NV04_PGRAPH_BBASE2                                 0x00400660
+#define NV04_PGRAPH_BBASE3                                 0x00400664
+#define NV04_PGRAPH_BBASE4                                 0x00400668
+#define NV04_PGRAPH_BBASE5                                 0x0040066C
+#define NV04_PGRAPH_BPITCH0                                0x00400670
+#define NV04_PGRAPH_BPITCH1                                0x00400674
+#define NV04_PGRAPH_BPITCH2                                0x00400678
+#define NV04_PGRAPH_BPITCH3                                0x0040067C
+#define NV04_PGRAPH_BPITCH4                                0x00400680
+#define NV04_PGRAPH_BLIMIT0                                0x00400684
+#define NV04_PGRAPH_BLIMIT1                                0x00400688
+#define NV04_PGRAPH_BLIMIT2                                0x0040068C
+#define NV04_PGRAPH_BLIMIT3                                0x00400690
+#define NV04_PGRAPH_BLIMIT4                                0x00400694
+#define NV04_PGRAPH_BLIMIT5                                0x00400698
+#define NV04_PGRAPH_BSWIZZLE2                              0x0040069C
+#define NV04_PGRAPH_BSWIZZLE5                              0x004006A0
+#define NV03_PGRAPH_STATUS                                 0x004006B0
+#define NV04_PGRAPH_STATUS                                 0x00400700
+#define NV04_PGRAPH_TRAPPED_ADDR                           0x00400704
+#define NV04_PGRAPH_TRAPPED_DATA                           0x00400708
+#define NV04_PGRAPH_SURFACE                                0x0040070C
+#define NV10_PGRAPH_TRAPPED_DATA_HIGH                      0x0040070C
+#define NV04_PGRAPH_STATE                                  0x00400710
+#define NV10_PGRAPH_SURFACE                                0x00400710
+#define NV04_PGRAPH_NOTIFY                                 0x00400714
+#define NV10_PGRAPH_STATE                                  0x00400714
+#define NV10_PGRAPH_NOTIFY                                 0x00400718
+
+#define NV04_PGRAPH_FIFO                                   0x00400720
+
+#define NV04_PGRAPH_BPIXEL                                 0x00400724
+#define NV10_PGRAPH_RDI_INDEX                              0x00400750
+#define NV04_PGRAPH_FFINTFC_ST2                            0x00400754
+#define NV10_PGRAPH_RDI_DATA                               0x00400754
+#define NV04_PGRAPH_DMA_PITCH                              0x00400760
+#define NV10_PGRAPH_FFINTFC_ST2                            0x00400764
+#define NV04_PGRAPH_DVD_COLORFMT                           0x00400764
+#define NV04_PGRAPH_SCALED_FORMAT                          0x00400768
+#define NV10_PGRAPH_DMA_PITCH                              0x00400770
+#define NV10_PGRAPH_DVD_COLORFMT                           0x00400774
+#define NV10_PGRAPH_SCALED_FORMAT                          0x00400778
+#define NV20_PGRAPH_CHANNEL_CTX_TABLE                      0x00400780
+#define NV20_PGRAPH_CHANNEL_CTX_POINTER                    0x00400784
+#define NV20_PGRAPH_CHANNEL_CTX_XFER                       0x00400788
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD                  0x00000001
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE                  0x00000002
+#define NV04_PGRAPH_PATT_COLOR0                            0x00400800
+#define NV04_PGRAPH_PATT_COLOR1                            0x00400804
+#define NV04_PGRAPH_PATTERN                                0x00400808
+#define NV04_PGRAPH_PATTERN_SHAPE                          0x00400810
+#define NV04_PGRAPH_CHROMA                                 0x00400814
+#define NV04_PGRAPH_CONTROL0                               0x00400818
+#define NV04_PGRAPH_CONTROL1                               0x0040081C
+#define NV04_PGRAPH_CONTROL2                               0x00400820
+#define NV04_PGRAPH_BLEND                                  0x00400824
+#define NV04_PGRAPH_STORED_FMT                             0x00400830
+#define NV04_PGRAPH_PATT_COLORRAM                          0x00400900
+#define NV20_PGRAPH_TILE(i)                                (0x00400900 + (i*16))
+#define NV20_PGRAPH_TLIMIT(i)                              (0x00400904 + (i*16))
+#define NV20_PGRAPH_TSIZE(i)                               (0x00400908 + (i*16))
+#define NV20_PGRAPH_TSTATUS(i)                             (0x0040090C + (i*16))
+#define NV10_PGRAPH_TILE(i)                                (0x00400B00 + (i*16))
+#define NV10_PGRAPH_TLIMIT(i)                              (0x00400B04 + (i*16))
+#define NV10_PGRAPH_TSIZE(i)                               (0x00400B08 + (i*16))
+#define NV10_PGRAPH_TSTATUS(i)                             (0x00400B0C + (i*16))
+#define NV04_PGRAPH_U_RAM                                  0x00400D00
+#define NV47_PGRAPH_TILE(i)                                (0x00400D00 + (i*16))
+#define NV47_PGRAPH_TLIMIT(i)                              (0x00400D04 + (i*16))
+#define NV47_PGRAPH_TSIZE(i)                               (0x00400D08 + (i*16))
+#define NV47_PGRAPH_TSTATUS(i)                             (0x00400D0C + (i*16))
+#define NV04_PGRAPH_V_RAM                                  0x00400D40
+#define NV04_PGRAPH_W_RAM                                  0x00400D80
+#define NV10_PGRAPH_COMBINER0_IN_ALPHA                     0x00400E40
+#define NV10_PGRAPH_COMBINER1_IN_ALPHA                     0x00400E44
+#define NV10_PGRAPH_COMBINER0_IN_RGB                       0x00400E48
+#define NV10_PGRAPH_COMBINER1_IN_RGB                       0x00400E4C
+#define NV10_PGRAPH_COMBINER_COLOR0                        0x00400E50
+#define NV10_PGRAPH_COMBINER_COLOR1                        0x00400E54
+#define NV10_PGRAPH_COMBINER0_OUT_ALPHA                    0x00400E58
+#define NV10_PGRAPH_COMBINER1_OUT_ALPHA                    0x00400E5C
+#define NV10_PGRAPH_COMBINER0_OUT_RGB                      0x00400E60
+#define NV10_PGRAPH_COMBINER1_OUT_RGB                      0x00400E64
+#define NV10_PGRAPH_COMBINER_FINAL0                        0x00400E68
+#define NV10_PGRAPH_COMBINER_FINAL1                        0x00400E6C
+#define NV10_PGRAPH_WINDOWCLIP_HORIZONTAL                  0x00400F00
+#define NV10_PGRAPH_WINDOWCLIP_VERTICAL                    0x00400F20
+#define NV10_PGRAPH_XFMODE0                                0x00400F40
+#define NV10_PGRAPH_XFMODE1                                0x00400F44
+#define NV10_PGRAPH_GLOBALSTATE0                           0x00400F48
+#define NV10_PGRAPH_GLOBALSTATE1                           0x00400F4C
+#define NV10_PGRAPH_PIPE_ADDRESS                           0x00400F50
+#define NV10_PGRAPH_PIPE_DATA                              0x00400F54
+#define NV04_PGRAPH_DMA_START_0                            0x00401000
+#define NV04_PGRAPH_DMA_START_1                            0x00401004
+#define NV04_PGRAPH_DMA_LENGTH                             0x00401008
+#define NV04_PGRAPH_DMA_MISC                               0x0040100C
+#define NV04_PGRAPH_DMA_DATA_0                             0x00401020
+#define NV04_PGRAPH_DMA_DATA_1                             0x00401024
+#define NV04_PGRAPH_DMA_RM                                 0x00401030
+#define NV04_PGRAPH_DMA_A_XLATE_INST                       0x00401040
+#define NV04_PGRAPH_DMA_A_CONTROL                          0x00401044
+#define NV04_PGRAPH_DMA_A_LIMIT                            0x00401048
+#define NV04_PGRAPH_DMA_A_TLB_PTE                          0x0040104C
+#define NV04_PGRAPH_DMA_A_TLB_TAG                          0x00401050
+#define NV04_PGRAPH_DMA_A_ADJ_OFFSET                       0x00401054
+#define NV04_PGRAPH_DMA_A_OFFSET                           0x00401058
+#define NV04_PGRAPH_DMA_A_SIZE                             0x0040105C
+#define NV04_PGRAPH_DMA_A_Y_SIZE                           0x00401060
+#define NV04_PGRAPH_DMA_B_XLATE_INST                       0x00401080
+#define NV04_PGRAPH_DMA_B_CONTROL                          0x00401084
+#define NV04_PGRAPH_DMA_B_LIMIT                            0x00401088
+#define NV04_PGRAPH_DMA_B_TLB_PTE                          0x0040108C
+#define NV04_PGRAPH_DMA_B_TLB_TAG                          0x00401090
+#define NV04_PGRAPH_DMA_B_ADJ_OFFSET                       0x00401094
+#define NV04_PGRAPH_DMA_B_OFFSET                           0x00401098
+#define NV04_PGRAPH_DMA_B_SIZE                             0x0040109C
+#define NV04_PGRAPH_DMA_B_Y_SIZE                           0x004010A0
+#define NV40_PGRAPH_TILE1(i)                               (0x00406900 + (i*16))
+#define NV40_PGRAPH_TLIMIT1(i)                             (0x00406904 + (i*16))
+#define NV40_PGRAPH_TSIZE1(i)                              (0x00406908 + (i*16))
+#define NV40_PGRAPH_TSTATUS1(i)                            (0x0040690C + (i*16))
+
+
+/* It's a guess that this works on NV03. Confirmed on NV04, though */
+#define NV04_PFIFO_DELAY_0                                 0x00002040
+#define NV04_PFIFO_DMA_TIMESLICE                           0x00002044
+#define NV04_PFIFO_NEXT_CHANNEL                            0x00002050
+#define NV03_PFIFO_INTR_0                                  0x00002100
+#define NV03_PFIFO_INTR_EN_0                               0x00002140
+#    define NV_PFIFO_INTR_CACHE_ERROR                          (1<<0)
+#    define NV_PFIFO_INTR_RUNOUT                               (1<<4)
+#    define NV_PFIFO_INTR_RUNOUT_OVERFLOW                      (1<<8)
+#    define NV_PFIFO_INTR_DMA_PUSHER                          (1<<12)
+#    define NV_PFIFO_INTR_DMA_PT                              (1<<16)
+#    define NV_PFIFO_INTR_SEMAPHORE                           (1<<20)
+#    define NV_PFIFO_INTR_ACQUIRE_TIMEOUT                     (1<<24)
+#define NV03_PFIFO_RAMHT                                   0x00002210
+#define NV03_PFIFO_RAMFC                                   0x00002214
+#define NV03_PFIFO_RAMRO                                   0x00002218
+#define NV40_PFIFO_RAMFC                                   0x00002220
+#define NV03_PFIFO_CACHES                                  0x00002500
+#define NV04_PFIFO_MODE                                    0x00002504
+#define NV04_PFIFO_DMA                                     0x00002508
+#define NV04_PFIFO_SIZE                                    0x0000250c
+#define NV50_PFIFO_CTX_TABLE(c)                        (0x2600+(c)*4)
+#define NV50_PFIFO_CTX_TABLE__SIZE                                128
+#define NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED                  (1<<31)
+#define NV50_PFIFO_CTX_TABLE_UNK30_BAD                        (1<<30)
+#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80             0x0FFFFFFF
+#define NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84             0x00FFFFFF
+#define NV03_PFIFO_CACHE0_PUSH0                            0x00003000
+#define NV03_PFIFO_CACHE0_PULL0                            0x00003040
+#define NV04_PFIFO_CACHE0_PULL0                            0x00003050
+#define NV04_PFIFO_CACHE0_PULL1                            0x00003054
+#define NV03_PFIFO_CACHE1_PUSH0                            0x00003200
+#define NV03_PFIFO_CACHE1_PUSH1                            0x00003204
+#define NV03_PFIFO_CACHE1_PUSH1_DMA                            (1<<8)
+#define NV40_PFIFO_CACHE1_PUSH1_DMA                           (1<<16)
+#define NV03_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000000f
+#define NV10_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000001f
+#define NV50_PFIFO_CACHE1_PUSH1_CHID_MASK                  0x0000007f
+#define NV03_PFIFO_CACHE1_PUT                              0x00003210
+#define NV04_PFIFO_CACHE1_DMA_PUSH                         0x00003220
+#define NV04_PFIFO_CACHE1_DMA_FETCH                        0x00003224
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_8_BYTES         0x00000000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_16_BYTES        0x00000008
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_24_BYTES        0x00000010
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_32_BYTES        0x00000018
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_40_BYTES        0x00000020
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_48_BYTES        0x00000028
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_56_BYTES        0x00000030
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_64_BYTES        0x00000038
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_72_BYTES        0x00000040
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_80_BYTES        0x00000048
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_88_BYTES        0x00000050
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_96_BYTES        0x00000058
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_104_BYTES       0x00000060
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES       0x00000068
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_120_BYTES       0x00000070
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES       0x00000078
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_136_BYTES       0x00000080
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_144_BYTES       0x00000088
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_152_BYTES       0x00000090
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_160_BYTES       0x00000098
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_168_BYTES       0x000000A0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_176_BYTES       0x000000A8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_184_BYTES       0x000000B0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_192_BYTES       0x000000B8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_200_BYTES       0x000000C0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_208_BYTES       0x000000C8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_216_BYTES       0x000000D0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_224_BYTES       0x000000D8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_232_BYTES       0x000000E0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_240_BYTES       0x000000E8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_248_BYTES       0x000000F0
+#    define NV_PFIFO_CACHE1_DMA_FETCH_TRIG_256_BYTES       0x000000F8
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE                 0x0000E000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_32_BYTES        0x00000000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_64_BYTES        0x00002000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_96_BYTES        0x00004000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES       0x00006000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_160_BYTES       0x00008000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_192_BYTES       0x0000A000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_224_BYTES       0x0000C000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_SIZE_256_BYTES       0x0000E000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS             0x001F0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_0           0x00000000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_1           0x00010000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_2           0x00020000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_3           0x00030000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4           0x00040000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_5           0x00050000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_6           0x00060000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_7           0x00070000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8           0x00080000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_9           0x00090000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_10          0x000A0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_11          0x000B0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_12          0x000C0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_13          0x000D0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_14          0x000E0000
+#    define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15          0x000F0000
+#    define NV_PFIFO_CACHE1_ENDIAN                         0x80000000
+#    define NV_PFIFO_CACHE1_LITTLE_ENDIAN                  0x7FFFFFFF
+#    define NV_PFIFO_CACHE1_BIG_ENDIAN                     0x80000000
+#define NV04_PFIFO_CACHE1_DMA_STATE                        0x00003228
+#define NV04_PFIFO_CACHE1_DMA_INSTANCE                     0x0000322c
+#define NV04_PFIFO_CACHE1_DMA_CTL                          0x00003230
+#define NV04_PFIFO_CACHE1_DMA_PUT                          0x00003240
+#define NV04_PFIFO_CACHE1_DMA_GET                          0x00003244
+#define NV10_PFIFO_CACHE1_REF_CNT                          0x00003248
+#define NV10_PFIFO_CACHE1_DMA_SUBROUTINE                   0x0000324C
+#define NV03_PFIFO_CACHE1_PULL0                            0x00003240
+#define NV04_PFIFO_CACHE1_PULL0                            0x00003250
+#define NV03_PFIFO_CACHE1_PULL1                            0x00003250
+#define NV04_PFIFO_CACHE1_PULL1                            0x00003254
+#define NV04_PFIFO_CACHE1_HASH                             0x00003258
+#define NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT                  0x00003260
+#define NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP                0x00003264
+#define NV10_PFIFO_CACHE1_ACQUIRE_VALUE                    0x00003268
+#define NV10_PFIFO_CACHE1_SEMAPHORE                        0x0000326C
+#define NV03_PFIFO_CACHE1_GET                              0x00003270
+#define NV04_PFIFO_CACHE1_ENGINE                           0x00003280
+#define NV04_PFIFO_CACHE1_DMA_DCOUNT                       0x000032A0
+#define NV40_PFIFO_GRCTX_INSTANCE                          0x000032E0
+#define NV40_PFIFO_UNK32E4                                 0x000032E4
+#define NV04_PFIFO_CACHE1_METHOD(i)                (0x00003800+(i*8))
+#define NV04_PFIFO_CACHE1_DATA(i)                  (0x00003804+(i*8))
+#define NV40_PFIFO_CACHE1_METHOD(i)                (0x00090000+(i*8))
+#define NV40_PFIFO_CACHE1_DATA(i)                  (0x00090004+(i*8))
+
+#define NV_CRTC0_INTSTAT                                   0x00600100
+#define NV_CRTC0_INTEN                                     0x00600140
+#define NV_CRTC1_INTSTAT                                   0x00602100
+#define NV_CRTC1_INTEN                                     0x00602140
+#    define NV_CRTC_INTR_VBLANK                                (1<<0)
+
+#define NV04_PRAMIN						0x00700000
+
+/* Fifo commands. These are not regs, neither masks */
+#define NV03_FIFO_CMD_JUMP                                 0x20000000
+#define NV03_FIFO_CMD_JUMP_OFFSET_MASK                     0x1ffffffc
+#define NV03_FIFO_CMD_REWIND                               (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK))
+
+/* This is a partial import from rules-ng, a few things may be duplicated.
+ * Eventually we should completely import everything from rules-ng.
+ * For the moment check rules-ng for docs.
+  */
+
+#define NV50_PMC                                            0x00000000
+#define NV50_PMC__LEN                                              0x1
+#define NV50_PMC__ESIZE                                         0x2000
+#    define NV50_PMC_BOOT_0                                 0x00000000
+#        define NV50_PMC_BOOT_0_REVISION                    0x000000ff
+#        define NV50_PMC_BOOT_0_REVISION__SHIFT                      0
+#        define NV50_PMC_BOOT_0_ARCH                        0x0ff00000
+#        define NV50_PMC_BOOT_0_ARCH__SHIFT                         20
+#    define NV50_PMC_INTR_0                                 0x00000100
+#        define NV50_PMC_INTR_0_PFIFO                           (1<<8)
+#        define NV50_PMC_INTR_0_PGRAPH                         (1<<12)
+#        define NV50_PMC_INTR_0_PTIMER                         (1<<20)
+#        define NV50_PMC_INTR_0_HOTPLUG                        (1<<21)
+#        define NV50_PMC_INTR_0_DISPLAY                        (1<<26)
+#    define NV50_PMC_INTR_EN_0                              0x00000140
+#        define NV50_PMC_INTR_EN_0_MASTER                       (1<<0)
+#            define NV50_PMC_INTR_EN_0_MASTER_DISABLED          (0<<0)
+#            define NV50_PMC_INTR_EN_0_MASTER_ENABLED           (1<<0)
+#    define NV50_PMC_ENABLE                                 0x00000200
+#        define NV50_PMC_ENABLE_PFIFO                           (1<<8)
+#        define NV50_PMC_ENABLE_PGRAPH                         (1<<12)
+
+#define NV50_PCONNECTOR                                     0x0000e000
+#define NV50_PCONNECTOR__LEN                                       0x1
+#define NV50_PCONNECTOR__ESIZE                                  0x1000
+#    define NV50_PCONNECTOR_HOTPLUG_INTR                    0x0000e050
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C0          (1<<0)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C1          (1<<1)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C2          (1<<2)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C3          (1<<3)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C0       (1<<16)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C1       (1<<17)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C2       (1<<18)
+#        define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C3       (1<<19)
+#    define NV50_PCONNECTOR_HOTPLUG_CTRL                    0x0000e054
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C0          (1<<0)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C1          (1<<1)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C2          (1<<2)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C3          (1<<3)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C0       (1<<16)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C1       (1<<17)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C2       (1<<18)
+#        define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C3       (1<<19)
+#    define NV50_PCONNECTOR_HOTPLUG_STATE                   0x0000e104
+#        define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C0 (1<<2)
+#        define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C1 (1<<6)
+#        define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C2 (1<<10)
+#        define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C3 (1<<14)
+#    define NV50_PCONNECTOR_I2C_PORT_0                      0x0000e138
+#    define NV50_PCONNECTOR_I2C_PORT_1                      0x0000e150
+#    define NV50_PCONNECTOR_I2C_PORT_2                      0x0000e168
+#    define NV50_PCONNECTOR_I2C_PORT_3                      0x0000e180
+#    define NV50_PCONNECTOR_I2C_PORT_4                      0x0000e240
+#    define NV50_PCONNECTOR_I2C_PORT_5                      0x0000e258
+
+#define NV50_AUXCH_DATA_OUT(i,n)             ((n) * 4 + (i) * 0x50 + 0x0000e4c0)
+#define NV50_AUXCH_DATA_OUT__SIZE                                             4
+#define NV50_AUXCH_DATA_IN(i,n)              ((n) * 4 + (i) * 0x50 + 0x0000e4d0)
+#define NV50_AUXCH_DATA_IN__SIZE                                              4
+#define NV50_AUXCH_ADDR(i)                             ((i) * 0x50 + 0x0000e4e0)
+#define NV50_AUXCH_CTRL(i)                             ((i) * 0x50 + 0x0000e4e4)
+#define NV50_AUXCH_CTRL_LINKSTAT                                     0x01000000
+#define NV50_AUXCH_CTRL_LINKSTAT_NOT_READY                           0x00000000
+#define NV50_AUXCH_CTRL_LINKSTAT_READY                               0x01000000
+#define NV50_AUXCH_CTRL_LINKEN                                       0x00100000
+#define NV50_AUXCH_CTRL_LINKEN_DISABLED                              0x00000000
+#define NV50_AUXCH_CTRL_LINKEN_ENABLED                               0x00100000
+#define NV50_AUXCH_CTRL_EXEC                                         0x00010000
+#define NV50_AUXCH_CTRL_EXEC_COMPLETE                                0x00000000
+#define NV50_AUXCH_CTRL_EXEC_IN_PROCESS                              0x00010000
+#define NV50_AUXCH_CTRL_CMD                                          0x0000f000
+#define NV50_AUXCH_CTRL_CMD_SHIFT                                            12
+#define NV50_AUXCH_CTRL_LEN                                          0x0000000f
+#define NV50_AUXCH_CTRL_LEN_SHIFT                                             0
+#define NV50_AUXCH_STAT(i)                             ((i) * 0x50 + 0x0000e4e8)
+#define NV50_AUXCH_STAT_STATE                                        0x10000000
+#define NV50_AUXCH_STAT_STATE_NOT_READY                              0x00000000
+#define NV50_AUXCH_STAT_STATE_READY                                  0x10000000
+#define NV50_AUXCH_STAT_REPLY                                        0x000f0000
+#define NV50_AUXCH_STAT_REPLY_AUX                                    0x00030000
+#define NV50_AUXCH_STAT_REPLY_AUX_ACK                                0x00000000
+#define NV50_AUXCH_STAT_REPLY_AUX_NACK                               0x00010000
+#define NV50_AUXCH_STAT_REPLY_AUX_DEFER                              0x00020000
+#define NV50_AUXCH_STAT_REPLY_I2C                                    0x000c0000
+#define NV50_AUXCH_STAT_REPLY_I2C_ACK                                0x00000000
+#define NV50_AUXCH_STAT_REPLY_I2C_NACK                               0x00040000
+#define NV50_AUXCH_STAT_REPLY_I2C_DEFER                              0x00080000
+#define NV50_AUXCH_STAT_COUNT                                        0x0000001f
+
+#define NV50_PBUS                                           0x00088000
+#define NV50_PBUS__LEN                                             0x1
+#define NV50_PBUS__ESIZE                                        0x1000
+#    define NV50_PBUS_PCI_ID                                0x00088000
+#        define NV50_PBUS_PCI_ID_VENDOR_ID                  0x0000ffff
+#        define NV50_PBUS_PCI_ID_VENDOR_ID__SHIFT                    0
+#        define NV50_PBUS_PCI_ID_DEVICE_ID                  0xffff0000
+#        define NV50_PBUS_PCI_ID_DEVICE_ID__SHIFT                   16
+
+#define NV50_PFB                                            0x00100000
+#define NV50_PFB__LEN                                              0x1
+#define NV50_PFB__ESIZE                                         0x1000
+
+#define NV50_PEXTDEV                                        0x00101000
+#define NV50_PEXTDEV__LEN                                          0x1
+#define NV50_PEXTDEV__ESIZE                                     0x1000
+
+#define NV50_PROM                                           0x00300000
+#define NV50_PROM__LEN                                             0x1
+#define NV50_PROM__ESIZE                                       0x10000
+
+#define NV50_PGRAPH                                         0x00400000
+#define NV50_PGRAPH__LEN                                           0x1
+#define NV50_PGRAPH__ESIZE                                     0x10000
+
+#define NV50_PDISPLAY                                                0x00610000
+#define NV50_PDISPLAY_OBJECTS                                        0x00610010
+#define NV50_PDISPLAY_INTR_0                                         0x00610020
+#define NV50_PDISPLAY_INTR_1                                         0x00610024
+#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC                             0x0000000c
+#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_SHIFT                                2
+#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(n)                   (1 << ((n) + 2))
+#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0                           0x00000004
+#define NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1                           0x00000008
+#define NV50_PDISPLAY_INTR_1_CLK_UNK10                               0x00000010
+#define NV50_PDISPLAY_INTR_1_CLK_UNK20                               0x00000020
+#define NV50_PDISPLAY_INTR_1_CLK_UNK40                               0x00000040
+#define NV50_PDISPLAY_INTR_EN                                        0x0061002c
+#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC                            0x0000000c
+#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n)                   (1 << ((n) + 2))
+#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0                          0x00000004
+#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1                          0x00000008
+#define NV50_PDISPLAY_INTR_EN_CLK_UNK10                              0x00000010
+#define NV50_PDISPLAY_INTR_EN_CLK_UNK20                              0x00000020
+#define NV50_PDISPLAY_INTR_EN_CLK_UNK40                              0x00000040
+#define NV50_PDISPLAY_UNK30_CTRL                                     0x00610030
+#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0                        0x00000200
+#define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1                        0x00000400
+#define NV50_PDISPLAY_UNK30_CTRL_PENDING                             0x80000000
+#define NV50_PDISPLAY_TRAPPED_ADDR                                   0x00610080
+#define NV50_PDISPLAY_TRAPPED_DATA                                   0x00610084
+#define NV50_PDISPLAY_CHANNEL_STAT(i)                  ((i) * 0x10 + 0x00610200)
+#define NV50_PDISPLAY_CHANNEL_STAT_DMA                               0x00000010
+#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED                      0x00000000
+#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED                       0x00000010
+#define NV50_PDISPLAY_CHANNEL_DMA_CB(i)                ((i) * 0x10 + 0x00610204)
+#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION                        0x00000002
+#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM                   0x00000000
+#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM                 0x00000002
+#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID                           0x00000001
+#define NV50_PDISPLAY_CHANNEL_UNK2(i)                  ((i) * 0x10 + 0x00610208)
+#define NV50_PDISPLAY_CHANNEL_UNK3(i)                  ((i) * 0x10 + 0x0061020c)
+
+#define NV50_PDISPLAY_CURSOR                                         0x00610270
+#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)           ((i) * 0x10 + 0x00610270)
+#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON                         0x00000001
+#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS                     0x00030000
+#define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE              0x00010000
+
+#define NV50_PDISPLAY_CTRL_STATE                                     0x00610300
+#define NV50_PDISPLAY_CTRL_STATE_PENDING                             0x80000000
+#define NV50_PDISPLAY_CTRL_STATE_METHOD                              0x00001ffc
+#define NV50_PDISPLAY_CTRL_STATE_ENABLE                              0x00000001
+#define NV50_PDISPLAY_CTRL_VAL                                       0x00610304
+#define NV50_PDISPLAY_UNK_380                                        0x00610380
+#define NV50_PDISPLAY_RAM_AMOUNT                                     0x00610384
+#define NV50_PDISPLAY_UNK_388                                        0x00610388
+#define NV50_PDISPLAY_UNK_38C                                        0x0061038c
+
+#define NV50_PDISPLAY_CRTC_P(i, r)        ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
+#define NV50_PDISPLAY_CRTC_C(i, r)    (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r)
+#define NV50_PDISPLAY_CRTC_UNK_0A18 /* mthd 0x0900 */                0x00610a18
+#define NV50_PDISPLAY_CRTC_CLUT_MODE                                 0x00610a24
+#define NV50_PDISPLAY_CRTC_INTERLACE                                 0x00610a48
+#define NV50_PDISPLAY_CRTC_SCALE_CTRL                                0x00610a50
+#define NV50_PDISPLAY_CRTC_CURSOR_CTRL                               0x00610a58
+#define NV50_PDISPLAY_CRTC_UNK0A78 /* mthd 0x0904 */                 0x00610a78
+#define NV50_PDISPLAY_CRTC_UNK0AB8                                   0x00610ab8
+#define NV50_PDISPLAY_CRTC_DEPTH                                     0x00610ac8
+#define NV50_PDISPLAY_CRTC_CLOCK                                     0x00610ad0
+#define NV50_PDISPLAY_CRTC_COLOR_CTRL                                0x00610ae0
+#define NV50_PDISPLAY_CRTC_SYNC_START_TO_BLANK_END                   0x00610ae8
+#define NV50_PDISPLAY_CRTC_MODE_UNK1                                 0x00610af0
+#define NV50_PDISPLAY_CRTC_DISPLAY_TOTAL                             0x00610af8
+#define NV50_PDISPLAY_CRTC_SYNC_DURATION                             0x00610b00
+#define NV50_PDISPLAY_CRTC_MODE_UNK2                                 0x00610b08
+#define NV50_PDISPLAY_CRTC_UNK_0B10 /* mthd 0x0828 */                0x00610b10
+#define NV50_PDISPLAY_CRTC_FB_SIZE                                   0x00610b18
+#define NV50_PDISPLAY_CRTC_FB_PITCH                                  0x00610b20
+#define NV50_PDISPLAY_CRTC_FB_PITCH_LINEAR                           0x00100000
+#define NV50_PDISPLAY_CRTC_FB_POS                                    0x00610b28
+#define NV50_PDISPLAY_CRTC_SCALE_CENTER_OFFSET                       0x00610b38
+#define NV50_PDISPLAY_CRTC_REAL_RES                                  0x00610b40
+#define NV50_PDISPLAY_CRTC_SCALE_RES1                                0x00610b48
+#define NV50_PDISPLAY_CRTC_SCALE_RES2                                0x00610b50
+
+#define NV50_PDISPLAY_DAC_MODE_CTRL_P(i)                (0x00610b58 + (i) * 0x8)
+#define NV50_PDISPLAY_DAC_MODE_CTRL_C(i)                (0x00610b5c + (i) * 0x8)
+#define NV50_PDISPLAY_SOR_MODE_CTRL_P(i)                (0x00610b70 + (i) * 0x8)
+#define NV50_PDISPLAY_SOR_MODE_CTRL_C(i)                (0x00610b74 + (i) * 0x8)
+#define NV50_PDISPLAY_DAC_MODE_CTRL2_P(i)               (0x00610bdc + (i) * 0x8)
+#define NV50_PDISPLAY_DAC_MODE_CTRL2_C(i)               (0x00610be0 + (i) * 0x8)
+
+#define NV90_PDISPLAY_SOR_MODE_CTRL_P(i)                (0x00610794 + (i) * 0x8)
+#define NV90_PDISPLAY_SOR_MODE_CTRL_C(i)                (0x00610798 + (i) * 0x8)
+#define NV90_PDISPLAY_DAC_MODE_CTRL_P(i)                (0x00610b58 + (i) * 0x8)
+#define NV90_PDISPLAY_DAC_MODE_CTRL_C(i)                (0x00610b5c + (i) * 0x8)
+#define NV90_PDISPLAY_DAC_MODE_CTRL2_P(i)               (0x00610b80 + (i) * 0x8)
+#define NV90_PDISPLAY_DAC_MODE_CTRL2_C(i)               (0x00610b84 + (i) * 0x8)
+
+#define NV50_PDISPLAY_CRTC_CLK                                       0x00614000
+#define NV50_PDISPLAY_CRTC_CLK_CTRL1(i)                 ((i) * 0x800 + 0x614100)
+#define NV50_PDISPLAY_CRTC_CLK_CTRL1_CONNECTED                       0x00000600
+#define NV50_PDISPLAY_CRTC_CLK_VPLL_A(i)                ((i) * 0x800 + 0x614104)
+#define NV50_PDISPLAY_CRTC_CLK_VPLL_B(i)                ((i) * 0x800 + 0x614108)
+#define NV50_PDISPLAY_CRTC_CLK_CTRL2(i)                 ((i) * 0x800 + 0x614200)
+
+#define NV50_PDISPLAY_DAC_CLK                                        0x00614000
+#define NV50_PDISPLAY_DAC_CLK_CTRL2(i)                  ((i) * 0x800 + 0x614280)
+
+#define NV50_PDISPLAY_SOR_CLK                                        0x00614000
+#define NV50_PDISPLAY_SOR_CLK_CTRL2(i)                  ((i) * 0x800 + 0x614300)
+
+#define NV50_PDISPLAY_VGACRTC(r)                                ((r) + 0x619400)
+
+#define NV50_PDISPLAY_DAC                                            0x0061a000
+#define NV50_PDISPLAY_DAC_DPMS_CTRL(i)                (0x0061a004 + (i) * 0x800)
+#define NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF                        0x00000001
+#define NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF                        0x00000004
+#define NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED                          0x00000010
+#define NV50_PDISPLAY_DAC_DPMS_CTRL_OFF                              0x00000040
+#define NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING                          0x80000000
+#define NV50_PDISPLAY_DAC_LOAD_CTRL(i)                (0x0061a00c + (i) * 0x800)
+#define NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE                           0x00100000
+#define NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT                          0x38000000
+#define NV50_PDISPLAY_DAC_LOAD_CTRL_DONE                             0x80000000
+#define NV50_PDISPLAY_DAC_CLK_CTRL1(i)                (0x0061a010 + (i) * 0x800)
+#define NV50_PDISPLAY_DAC_CLK_CTRL1_CONNECTED                        0x00000600
+
+#define NV50_PDISPLAY_SOR                                            0x0061c000
+#define NV50_PDISPLAY_SOR_DPMS_CTRL(i)                (0x0061c004 + (i) * 0x800)
+#define NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING                          0x80000000
+#define NV50_PDISPLAY_SOR_DPMS_CTRL_ON                               0x00000001
+#define NV50_PDISPLAY_SOR_CLK_CTRL1(i)                (0x0061c008 + (i) * 0x800)
+#define NV50_PDISPLAY_SOR_CLK_CTRL1_CONNECTED                        0x00000600
+#define NV50_PDISPLAY_SOR_DPMS_STATE(i)               (0x0061c030 + (i) * 0x800)
+#define NV50_PDISPLAY_SOR_DPMS_STATE_ACTIVE                          0x00030000
+#define NV50_PDISPLAY_SOR_DPMS_STATE_BLANKED                         0x00080000
+#define NV50_PDISPLAY_SOR_DPMS_STATE_WAIT                            0x10000000
+#define NV50_PDISPLAY_SOR_BACKLIGHT                                  0x0061c084
+#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE                           0x80000000
+#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL                            0x00000fff
+#define NV50_SOR_DP_CTRL(i,l)            (0x0061c10c + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED                      0x00004000
+#define NV50_SOR_DP_CTRL_LANE_MASK                                   0x001f0000
+#define NV50_SOR_DP_CTRL_LANE_0_ENABLED                              0x00010000
+#define NV50_SOR_DP_CTRL_LANE_1_ENABLED                              0x00020000
+#define NV50_SOR_DP_CTRL_LANE_2_ENABLED                              0x00040000
+#define NV50_SOR_DP_CTRL_LANE_3_ENABLED                              0x00080000
+#define NV50_SOR_DP_CTRL_TRAINING_PATTERN                            0x0f000000
+#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED                   0x00000000
+#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1                          0x01000000
+#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2                          0x02000000
+#define NV50_SOR_DP_UNK118(i,l)          (0x0061c118 + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_UNK120(i,l)          (0x0061c120 + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_UNK130(i,l)          (0x0061c130 + (i) * 0x800 + (l) * 0x80)
+
+#define NV50_PDISPLAY_USER(i)                        ((i) * 0x1000 + 0x00640000)
+#define NV50_PDISPLAY_USER_PUT(i)                    ((i) * 0x1000 + 0x00640000)
+#define NV50_PDISPLAY_USER_GET(i)                    ((i) * 0x1000 + 0x00640004)
+
+#define NV50_PDISPLAY_CURSOR_USER                                    0x00647000
+#define NV50_PDISPLAY_CURSOR_USER_POS_CTRL(i)        ((i) * 0x1000 + 0x00647080)
+#define NV50_PDISPLAY_CURSOR_USER_POS(i)             ((i) * 0x1000 + 0x00647084)
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2005-2006 Stephane Marchesin
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nouveau_dma.h"
+
+static int
+nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_bo *pb = chan->pushbuf_bo;
+	struct nouveau_gpuobj *pushbuf = NULL;
+	uint32_t start = pb->bo.mem.mm_node->start << PAGE_SHIFT;
+	int ret;
+
+	if (pb->bo.mem.mem_type == TTM_PL_TT) {
+		ret = nouveau_gpuobj_gart_dma_new(chan, 0,
+						  dev_priv->gart_info.aper_size,
+						  NV_DMA_ACCESS_RO, &pushbuf,
+						  NULL);
+		chan->pushbuf_base = start;
+	} else
+	if (dev_priv->card_type != NV_04) {
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
+					     dev_priv->fb_available_size,
+					     NV_DMA_ACCESS_RO,
+					     NV_DMA_TARGET_VIDMEM, &pushbuf);
+		chan->pushbuf_base = start;
+	} else {
+		/* NV04 cmdbuf hack, from original ddx.. not sure of it's
+		 * exact reason for existing :)  PCI access to cmdbuf in
+		 * VRAM.
+		 */
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+					     drm_get_resource_start(dev, 1),
+					     dev_priv->fb_available_size,
+					     NV_DMA_ACCESS_RO,
+					     NV_DMA_TARGET_PCI, &pushbuf);
+		chan->pushbuf_base = start;
+	}
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf);
+	if (ret) {
+		NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret);
+		if (pushbuf != dev_priv->gart_info.sg_ctxdma)
+			nouveau_gpuobj_del(dev, &pushbuf);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct nouveau_bo *
+nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
+{
+	struct nouveau_bo *pushbuf = NULL;
+	int location, ret;
+
+	if (nouveau_vram_pushbuf)
+		location = TTM_PL_FLAG_VRAM;
+	else
+		location = TTM_PL_FLAG_TT;
+
+	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false,
+			     true, &pushbuf);
+	if (ret) {
+		NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
+		return NULL;
+	}
+
+	ret = nouveau_bo_pin(pushbuf, location);
+	if (ret) {
+		NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret);
+		nouveau_bo_ref(NULL, &pushbuf);
+		return NULL;
+	}
+
+	return pushbuf;
+}
+
+/* allocates and initializes a fifo for user space consumption */
+int
+nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
+		      struct drm_file *file_priv,
+		      uint32_t vram_handle, uint32_t tt_handle)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_channel *chan;
+	int channel, user;
+	int ret;
+
+	/*
+	 * Alright, here is the full story
+	 * Nvidia cards have multiple hw fifo contexts (praise them for that,
+	 * no complicated crash-prone context switches)
+	 * We allocate a new context for each app and let it write to it
+	 * directly (woo, full userspace command submission !)
+	 * When there are no more contexts, you lost
+	 */
+	for (channel = 0; channel < pfifo->channels; channel++) {
+		if (dev_priv->fifos[channel] == NULL)
+			break;
+	}
+
+	/* no more fifos. you lost. */
+	if (channel == pfifo->channels)
+		return -EINVAL;
+
+	dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel),
+					   GFP_KERNEL);
+	if (!dev_priv->fifos[channel])
+		return -ENOMEM;
+	dev_priv->fifo_alloc_count++;
+	chan = dev_priv->fifos[channel];
+	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
+	INIT_LIST_HEAD(&chan->fence.pending);
+	chan->dev = dev;
+	chan->id = channel;
+	chan->file_priv = file_priv;
+	chan->vram_handle = vram_handle;
+	chan->gart_handle = tt_handle;
+
+	NV_INFO(dev, "Allocating FIFO number %d\n", channel);
+
+	/* Allocate DMA push buffer */
+	chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev);
+	if (!chan->pushbuf_bo) {
+		ret = -ENOMEM;
+		NV_ERROR(dev, "pushbuf %d\n", ret);
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	nouveau_dma_pre_init(chan);
+
+	/* Locate channel's user control regs */
+	if (dev_priv->card_type < NV_40)
+		user = NV03_USER(channel);
+	else
+	if (dev_priv->card_type < NV_50)
+		user = NV40_USER(channel);
+	else
+		user = NV50_USER(channel);
+
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user,
+								PAGE_SIZE);
+	if (!chan->user) {
+		NV_ERROR(dev, "ioremap of regs failed.\n");
+		nouveau_channel_free(chan);
+		return -ENOMEM;
+	}
+	chan->user_put = 0x40;
+	chan->user_get = 0x44;
+
+	/* Allocate space for per-channel fixed notifier memory */
+	ret = nouveau_notifier_init_channel(chan);
+	if (ret) {
+		NV_ERROR(dev, "ntfy %d\n", ret);
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	/* Setup channel's default objects */
+	ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle);
+	if (ret) {
+		NV_ERROR(dev, "gpuobj %d\n", ret);
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	/* Create a dma object for the push buffer */
+	ret = nouveau_channel_pushbuf_ctxdma_init(chan);
+	if (ret) {
+		NV_ERROR(dev, "pbctxdma %d\n", ret);
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	/* disable the fifo caches */
+	pfifo->reassign(dev, false);
+
+	/* Create a graphics context for new channel */
+	ret = pgraph->create_context(chan);
+	if (ret) {
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	/* Construct inital RAMFC for new channel */
+	ret = pfifo->create_context(chan);
+	if (ret) {
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	pfifo->reassign(dev, true);
+
+	ret = nouveau_dma_init(chan);
+	if (!ret)
+		ret = nouveau_fence_init(chan);
+	if (ret) {
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	nouveau_debugfs_channel_init(chan);
+
+	NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel);
+	*chan_ret = chan;
+	return 0;
+}
+
+/* stops a fifo */
+void
+nouveau_channel_free(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	unsigned long flags;
+	int ret;
+
+	NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id);
+
+	nouveau_debugfs_channel_fini(chan);
+
+	/* Give outstanding push buffers a chance to complete */
+	spin_lock_irqsave(&chan->fence.lock, flags);
+	nouveau_fence_update(chan);
+	spin_unlock_irqrestore(&chan->fence.lock, flags);
+	if (chan->fence.sequence != chan->fence.sequence_ack) {
+		struct nouveau_fence *fence = NULL;
+
+		ret = nouveau_fence_new(chan, &fence, true);
+		if (ret == 0) {
+			ret = nouveau_fence_wait(fence, NULL, false, false);
+			nouveau_fence_unref((void *)&fence);
+		}
+
+		if (ret)
+			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
+	}
+
+	/* Ensure all outstanding fences are signaled.  They should be if the
+	 * above attempts at idling were OK, but if we failed this'll tell TTM
+	 * we're done with the buffers.
+	 */
+	nouveau_fence_fini(chan);
+
+	/* Ensure the channel is no longer active on the GPU */
+	pfifo->reassign(dev, false);
+
+	pgraph->fifo_access(dev, false);
+	if (pgraph->channel(dev) == chan)
+		pgraph->unload_context(dev);
+	pgraph->destroy_context(chan);
+	pgraph->fifo_access(dev, true);
+
+	if (pfifo->channel_id(dev) == chan->id) {
+		pfifo->disable(dev);
+		pfifo->unload_context(dev);
+		pfifo->enable(dev);
+	}
+	pfifo->destroy_context(chan);
+
+	pfifo->reassign(dev, true);
+
+	/* Release the channel's resources */
+	nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
+	if (chan->pushbuf_bo) {
+		nouveau_bo_unpin(chan->pushbuf_bo);
+		nouveau_bo_ref(NULL, &chan->pushbuf_bo);
+	}
+	nouveau_gpuobj_channel_takedown(chan);
+	nouveau_notifier_takedown_channel(chan);
+	if (chan->user)
+		iounmap(chan->user);
+
+	dev_priv->fifos[chan->id] = NULL;
+	dev_priv->fifo_alloc_count--;
+	kfree(chan);
+}
+
+/* cleans up all the fifos from file_priv */
+void
+nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	int i;
+
+	NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
+	for (i = 0; i < engine->fifo.channels; i++) {
+		struct nouveau_channel *chan = dev_priv->fifos[i];
+
+		if (chan && chan->file_priv == file_priv)
+			nouveau_channel_free(chan);
+	}
+}
+
+int
+nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv,
+		      int channel)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+
+	if (channel >= engine->fifo.channels)
+		return 0;
+	if (dev_priv->fifos[channel] == NULL)
+		return 0;
+
+	return (dev_priv->fifos[channel]->file_priv == file_priv);
+}
+
+/***********************************
+ * ioctls wrapping the functions
+ ***********************************/
+
+static int
+nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_channel_alloc *init = data;
+	struct nouveau_channel *chan;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	if (dev_priv->engine.graph.accel_blocked)
+		return -ENODEV;
+
+	if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
+		return -EINVAL;
+
+	ret = nouveau_channel_alloc(dev, &chan, file_priv,
+				    init->fb_ctxdma_handle,
+				    init->tt_ctxdma_handle);
+	if (ret)
+		return ret;
+	init->channel  = chan->id;
+
+	init->subchan[0].handle = NvM2MF;
+	if (dev_priv->card_type < NV_50)
+		init->subchan[0].grclass = 0x0039;
+	else
+		init->subchan[0].grclass = 0x5039;
+	init->subchan[1].handle = NvSw;
+	init->subchan[1].grclass = NV_SW;
+	init->nr_subchan = 2;
+
+	/* Named memory object area */
+	ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem,
+				    &init->notifier_handle);
+	if (ret) {
+		nouveau_channel_free(chan);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_nouveau_channel_free *cfree = data;
+	struct nouveau_channel *chan;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
+
+	nouveau_channel_free(chan);
+	return 0;
+}
+
+/***********************************
+ * finally, the ioctl table
+ ***********************************/
+
+struct drm_ioctl_desc nouveau_ioctls[] = {
+	DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL, nouveau_gem_ioctl_pushbuf_call, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PIN, nouveau_gem_ioctl_pin, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_UNPIN, nouveau_gem_ioctl_unpin, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL2, nouveau_gem_ioctl_pushbuf_call2, DRM_AUTH),
+};
+
+int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_CONNECTOR_H__
+#define __NOUVEAU_CONNECTOR_H__
+
+#include "drm_edid.h"
+#include "nouveau_i2c.h"
+
+struct nouveau_connector {
+	struct drm_connector base;
+
+	struct dcb_connector_table_entry *dcb;
+
+	int scaling_mode;
+	bool use_dithering;
+
+	struct nouveau_encoder *detected_encoder;
+	struct edid *edid;
+	struct drm_display_mode *native_mode;
+};
+
+static inline struct nouveau_connector *nouveau_connector(
+						struct drm_connector *con)
+{
+	return container_of(con, struct nouveau_connector, base);
+}
+
+int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type);
+
+#endif /* __NOUVEAU_CONNECTOR_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_display.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_crtc_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_fb.h"
+#include "nouveau_fbcon.h"
+
+static void
+nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
+{
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+	struct drm_device *dev = drm_fb->dev;
+
+	if (drm_fb->fbdev)
+		nouveau_fbcon_remove(dev, drm_fb);
+
+	if (fb->nvbo) {
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(fb->nvbo->gem);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	drm_framebuffer_cleanup(drm_fb);
+	kfree(fb);
+}
+
+static int
+nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,
+				       struct drm_file *file_priv,
+				       unsigned int *handle)
+{
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+
+	return drm_gem_handle_create(file_priv, fb->nvbo->gem, handle);
+}
+
+static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
+	.destroy = nouveau_user_framebuffer_destroy,
+	.create_handle = nouveau_user_framebuffer_create_handle,
+};
+
+struct drm_framebuffer *
+nouveau_framebuffer_create(struct drm_device *dev, struct nouveau_bo *nvbo,
+			   struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct nouveau_framebuffer *fb;
+	int ret;
+
+	fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
+	if (!fb)
+		return NULL;
+
+	ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
+	if (ret) {
+		kfree(fb);
+		return NULL;
+	}
+
+	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+
+	fb->nvbo = nvbo;
+	return &fb->base;
+}
+
+static struct drm_framebuffer *
+nouveau_user_framebuffer_create(struct drm_device *dev,
+				struct drm_file *file_priv,
+				struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct drm_framebuffer *fb;
+	struct drm_gem_object *gem;
+
+	gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
+	if (!gem)
+		return NULL;
+
+	fb = nouveau_framebuffer_create(dev, nouveau_gem_object(gem), mode_cmd);
+	if (!fb) {
+		drm_gem_object_unreference(gem);
+		return NULL;
+	}
+
+	return fb;
+}
+
+const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
+	.fb_create = nouveau_user_framebuffer_create,
+	.fb_changed = nouveau_fbcon_probe,
+};
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -0,0 +1,125 @@
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include <acpi/acpi_bus.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "drm_crtc_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nv50_display.h"
+
+#define NOUVEAU_DSM_SUPPORTED 0x00
+#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00
+
+#define NOUVEAU_DSM_ACTIVE 0x01
+#define NOUVEAU_DSM_ACTIVE_QUERY 0x00
+
+#define NOUVEAU_DSM_LED 0x02
+#define NOUVEAU_DSM_LED_STATE 0x00
+#define NOUVEAU_DSM_LED_OFF 0x10
+#define NOUVEAU_DSM_LED_STAMINA 0x11
+#define NOUVEAU_DSM_LED_SPEED 0x12
+
+#define NOUVEAU_DSM_POWER 0x03
+#define NOUVEAU_DSM_POWER_STATE 0x00
+#define NOUVEAU_DSM_POWER_SPEED 0x01
+#define NOUVEAU_DSM_POWER_STAMINA 0x02
+
+static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
+{
+	static char muid[] = {
+		0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
+		0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
+	};
+
+	struct pci_dev *pdev = dev->pdev;
+	struct acpi_handle *handle;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_object_list input;
+	union acpi_object params[4];
+	union acpi_object *obj;
+	int err;
+
+	handle = DEVICE_ACPI_HANDLE(&pdev->dev);
+
+	if (!handle)
+		return -ENODEV;
+
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(muid);
+	params[0].buffer.pointer = (char *)muid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = 0x00000102;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_INTEGER;
+	params[3].integer.value = arg;
+
+	err = acpi_evaluate_object(handle, "_DSM", &input, &output);
+	if (err) {
+		NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
+		return err;
+	}
+
+	obj = (union acpi_object *)output.pointer;
+
+	if (obj->type == ACPI_TYPE_INTEGER)
+		if (obj->integer.value == 0x80000002)
+			return -ENODEV;
+
+	if (obj->type == ACPI_TYPE_BUFFER) {
+		if (obj->buffer.length == 4 && result) {
+			*result = 0;
+			*result |= obj->buffer.pointer[0];
+			*result |= (obj->buffer.pointer[1] << 8);
+			*result |= (obj->buffer.pointer[2] << 16);
+			*result |= (obj->buffer.pointer[3] << 24);
+		}
+	}
+
+	kfree(output.pointer);
+	return 0;
+}
+
+int nouveau_hybrid_setup(struct drm_device *dev)
+{
+	int result;
+
+	if (nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STATE,
+								&result))
+		return -ENODEV;
+
+	NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result);
+
+	if (result) { /* Ensure that the external GPU is enabled */
+		nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL);
+		nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED,
+									NULL);
+	} else { /* Stamina mode - disable the external GPU */
+		nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA,
+									NULL);
+		nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA,
+									NULL);
+	}
+
+	return 0;
+}
+
+bool nouveau_dsm_probe(struct drm_device *dev)
+{
+	int support = 0;
+
+	if (nouveau_dsm(dev, NOUVEAU_DSM_SUPPORTED,
+				NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &support))
+		return false;
+
+	if (!support)
+		return false;
+
+	return true;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA,
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA,
+ * All Rights Reserved.
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 "drmP.h"
+
+#include "nouveau_drv.h"
+
+int
+nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_nouveau_private *dev_priv =
+		file_priv->minor->dev->dev_private;
+
+	if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+		return drm_mmap(filp, vma);
+
+	return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev);
+}
+
+static int
+nouveau_ttm_mem_global_init(struct ttm_global_reference *ref)
+{
+	return ttm_mem_global_init(ref->object);
+}
+
+static void
+nouveau_ttm_mem_global_release(struct ttm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+int
+nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
+{
+	struct ttm_global_reference *global_ref;
+	int ret;
+
+	global_ref = &dev_priv->ttm.mem_global_ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &nouveau_ttm_mem_global_init;
+	global_ref->release = &nouveau_ttm_mem_global_release;
+
+	ret = ttm_global_item_ref(global_ref);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM memory accounting\n");
+		dev_priv->ttm.mem_global_ref.release = NULL;
+		return ret;
+	}
+
+	dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object;
+	global_ref = &dev_priv->ttm.bo_global_ref.ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_BO;
+	global_ref->size = sizeof(struct ttm_bo_global);
+	global_ref->init = &ttm_bo_global_init;
+	global_ref->release = &ttm_bo_global_release;
+
+	ret = ttm_global_item_ref(global_ref);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM BO subsystem\n");
+		ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
+		dev_priv->ttm.mem_global_ref.release = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
+void
+nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv)
+{
+	if (dev_priv->ttm.mem_global_ref.release == NULL)
+		return;
+
+	ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref);
+	ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
+	dev_priv->ttm.mem_global_ref.release = NULL;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+void
+nouveau_dma_pre_init(struct nouveau_channel *chan)
+{
+	chan->dma.max  = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
+	chan->dma.put  = 0;
+	chan->dma.cur  = chan->dma.put;
+	chan->dma.free = chan->dma.max - chan->dma.cur;
+}
+
+int
+nouveau_dma_init(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *m2mf = NULL;
+	struct nouveau_gpuobj *nvsw = NULL;
+	int ret, i;
+
+	/* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
+	ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ?
+				    0x0039 : 0x5039, &m2mf);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL);
+	if (ret)
+		return ret;
+
+	/* Create an NV_SW object for various sync purposes */
+	ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL);
+	if (ret)
+		return ret;
+
+	/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
+	ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
+	if (ret)
+		return ret;
+
+	/* Map push buffer */
+	ret = nouveau_bo_map(chan->pushbuf_bo);
+	if (ret)
+		return ret;
+
+	/* Map M2MF notifier object - fbcon. */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = nouveau_bo_map(chan->notifier_bo);
+		if (ret)
+			return ret;
+	}
+
+	/* Insert NOPS for NOUVEAU_DMA_SKIPS */
+	ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
+		OUT_RING(chan, 0);
+
+	/* Initialise NV_MEMORY_TO_MEMORY_FORMAT */
+	ret = RING_SPACE(chan, 4);
+	if (ret)
+		return ret;
+	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
+	OUT_RING(chan, NvM2MF);
+	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+	OUT_RING(chan, NvNotify0);
+
+	/* Initialise NV_SW */
+	ret = RING_SPACE(chan, 2);
+	if (ret)
+		return ret;
+	BEGIN_RING(chan, NvSubSw, 0, 1);
+	OUT_RING(chan, NvSw);
+
+	/* Sit back and pray the channel works.. */
+	FIRE_RING(chan);
+
+	return 0;
+}
+
+void
+OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
+{
+	bool is_iomem;
+	u32 *mem = ttm_kmap_obj_virtual(&chan->pushbuf_bo->kmap, &is_iomem);
+	mem = &mem[chan->dma.cur];
+	if (is_iomem)
+		memcpy_toio((void __force __iomem *)mem, data, nr_dwords * 4);
+	else
+		memcpy(mem, data, nr_dwords * 4);
+	chan->dma.cur += nr_dwords;
+}
+
+/* Fetch and adjust GPU GET pointer
+ *
+ * Returns:
+ *  value >= 0, the adjusted GET pointer
+ *  -EINVAL if GET pointer currently outside main push buffer
+ *  -EBUSY if timeout exceeded
+ */
+static inline int
+READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
+{
+	uint32_t val;
+
+	val = nvchan_rd32(chan, chan->user_get);
+
+	/* reset counter as long as GET is still advancing, this is
+	 * to avoid misdetecting a GPU lockup if the GPU happens to
+	 * just be processing an operation that takes a long time
+	 */
+	if (val != *prev_get) {
+		*prev_get = val;
+		*timeout = 0;
+	}
+
+	if ((++*timeout & 0xff) == 0) {
+		DRM_UDELAY(1);
+		if (*timeout > 100000)
+			return -EBUSY;
+	}
+
+	if (val < chan->pushbuf_base ||
+	    val > chan->pushbuf_base + (chan->dma.max << 2))
+		return -EINVAL;
+
+	return (val - chan->pushbuf_base) >> 2;
+}
+
+int
+nouveau_dma_wait(struct nouveau_channel *chan, int size)
+{
+	uint32_t prev_get = 0, cnt = 0;
+	int get;
+
+	while (chan->dma.free < size) {
+		get = READ_GET(chan, &prev_get, &cnt);
+		if (unlikely(get == -EBUSY))
+			return -EBUSY;
+
+		/* loop until we have a usable GET pointer.  the value
+		 * we read from the GPU may be outside the main ring if
+		 * PFIFO is processing a buffer called from the main ring,
+		 * discard these values until something sensible is seen.
+		 *
+		 * the other case we discard GET is while the GPU is fetching
+		 * from the SKIPS area, so the code below doesn't have to deal
+		 * with some fun corner cases.
+		 */
+		if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS)
+			continue;
+
+		if (get <= chan->dma.cur) {
+			/* engine is fetching behind us, or is completely
+			 * idle (GET == PUT) so we have free space up until
+			 * the end of the push buffer
+			 *
+			 * we can only hit that path once per call due to
+			 * looping back to the beginning of the push buffer,
+			 * we'll hit the fetching-ahead-of-us path from that
+			 * point on.
+			 *
+			 * the *one* exception to that rule is if we read
+			 * GET==PUT, in which case the below conditional will
+			 * always succeed and break us out of the wait loop.
+			 */
+			chan->dma.free = chan->dma.max - chan->dma.cur;
+			if (chan->dma.free >= size)
+				break;
+
+			/* not enough space left at the end of the push buffer,
+			 * instruct the GPU to jump back to the start right
+			 * after processing the currently pending commands.
+			 */
+			OUT_RING(chan, chan->pushbuf_base | 0x20000000);
+
+			/* wait for GET to depart from the skips area.
+			 * prevents writing GET==PUT and causing a race
+			 * condition that causes us to think the GPU is
+			 * idle when it's not.
+			 */
+			do {
+				get = READ_GET(chan, &prev_get, &cnt);
+				if (unlikely(get == -EBUSY))
+					return -EBUSY;
+				if (unlikely(get == -EINVAL))
+					continue;
+			} while (get <= NOUVEAU_DMA_SKIPS);
+			WRITE_PUT(NOUVEAU_DMA_SKIPS);
+
+			/* we're now submitting commands at the start of
+			 * the push buffer.
+			 */
+			chan->dma.cur  =
+			chan->dma.put  = NOUVEAU_DMA_SKIPS;
+		}
+
+		/* engine fetching ahead of us, we have space up until the
+		 * current GET pointer.  the "- 1" is to ensure there's
+		 * space left to emit a jump back to the beginning of the
+		 * push buffer if we require it.  we can never get GET == PUT
+		 * here, so this is safe.
+		 */
+		chan->dma.free = get - chan->dma.cur - 1;
+	}
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_display.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_display.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Author: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_fb.h"
+#include "nouveau_hw.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+
+#define MULTIPLE_ENCODERS(e) (e & (e - 1))
+
+static void
+nv04_display_store_initial_head_owner(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset != 0x11) {
+		dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
+		goto ownerknown;
+	}
+
+	/* reading CR44 is broken on nv11, so we attempt to infer it */
+	if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28))	/* heads tied, restore both */
+		dev_priv->crtc_owner = 0x4;
+	else {
+		uint8_t slaved_on_A, slaved_on_B;
+		bool tvA = false;
+		bool tvB = false;
+
+		NVLockVgaCrtcs(dev, false);
+
+		slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
+									0x80;
+		if (slaved_on_B)
+			tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) &
+					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
+
+		slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) &
+									0x80;
+		if (slaved_on_A)
+			tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
+					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
+
+		NVLockVgaCrtcs(dev, true);
+
+		if (slaved_on_A && !tvA)
+			dev_priv->crtc_owner = 0x0;
+		else if (slaved_on_B && !tvB)
+			dev_priv->crtc_owner = 0x3;
+		else if (slaved_on_A)
+			dev_priv->crtc_owner = 0x0;
+		else if (slaved_on_B)
+			dev_priv->crtc_owner = 0x3;
+		else
+			dev_priv->crtc_owner = 0x0;
+	}
+
+ownerknown:
+	NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner);
+
+	/* we need to ensure the heads are not tied henceforth, or reading any
+	 * 8 bit reg on head B will fail
+	 * setting a single arbitrary head solves that */
+	NVSetOwner(dev, 0);
+}
+
+int
+nv04_display_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+	uint16_t connector[16] = { 0 };
+	int i, ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	if (nv_two_heads(dev))
+		nv04_display_store_initial_head_owner(dev);
+	nouveau_hw_save_vga_fonts(dev, 1);
+
+	drm_mode_config_init(dev);
+	drm_mode_create_scaling_mode_property(dev);
+	drm_mode_create_dithering_property(dev);
+
+	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+	switch (dev_priv->card_type) {
+	case NV_04:
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+		break;
+	default:
+		dev->mode_config.max_width = 4096;
+		dev->mode_config.max_height = 4096;
+		break;
+	}
+
+	dev->mode_config.fb_base = dev_priv->fb_phys;
+
+	nv04_crtc_create(dev, 0);
+	if (nv_two_heads(dev))
+		nv04_crtc_create(dev, 1);
+
+	for (i = 0; i < dcb->entries; i++) {
+		struct dcb_entry *dcbent = &dcb->entry[i];
+
+		switch (dcbent->type) {
+		case OUTPUT_ANALOG:
+			ret = nv04_dac_create(dev, dcbent);
+			break;
+		case OUTPUT_LVDS:
+		case OUTPUT_TMDS:
+			ret = nv04_dfp_create(dev, dcbent);
+			break;
+		case OUTPUT_TV:
+			if (dcbent->location == DCB_LOC_ON_CHIP)
+				ret = nv17_tv_create(dev, dcbent);
+			else
+				ret = nv04_tv_create(dev, dcbent);
+			break;
+		default:
+			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
+			continue;
+		}
+
+		if (ret)
+			continue;
+
+		connector[dcbent->connector] |= (1 << dcbent->type);
+	}
+
+	for (i = 0; i < dcb->entries; i++) {
+		struct dcb_entry *dcbent = &dcb->entry[i];
+		uint16_t encoders;
+		int type;
+
+		encoders = connector[dcbent->connector];
+		if (!(encoders & (1 << dcbent->type)))
+			continue;
+		connector[dcbent->connector] = 0;
+
+		switch (dcbent->type) {
+		case OUTPUT_ANALOG:
+			if (!MULTIPLE_ENCODERS(encoders))
+				type = DRM_MODE_CONNECTOR_VGA;
+			else
+				type = DRM_MODE_CONNECTOR_DVII;
+			break;
+		case OUTPUT_TMDS:
+			if (!MULTIPLE_ENCODERS(encoders))
+				type = DRM_MODE_CONNECTOR_DVID;
+			else
+				type = DRM_MODE_CONNECTOR_DVII;
+			break;
+		case OUTPUT_LVDS:
+			type = DRM_MODE_CONNECTOR_LVDS;
+#if 0
+			/* don't create i2c adapter when lvds ddc not allowed */
+			if (dcbent->lvdsconf.use_straps_for_mode ||
+			    dev_priv->vbios->fp_no_ddc)
+				i2c_index = 0xf;
+#endif
+			break;
+		case OUTPUT_TV:
+			type = DRM_MODE_CONNECTOR_TV;
+			break;
+		default:
+			type = DRM_MODE_CONNECTOR_Unknown;
+			continue;
+		}
+
+		nouveau_connector_create(dev, dcbent->connector, type);
+	}
+
+	/* Save previous state */
+	NVLockVgaCrtcs(dev, false);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		crtc->funcs->save(crtc);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct drm_encoder_helper_funcs *func = encoder->helper_private;
+
+		func->save(encoder);
+	}
+
+	return 0;
+}
+
+void
+nv04_display_destroy(struct drm_device *dev)
+{
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	/* Turn every CRTC off. */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct drm_mode_set modeset = {
+			.crtc = crtc,
+		};
+
+		crtc->funcs->set_config(&modeset);
+	}
+
+	/* Restore state */
+	NVLockVgaCrtcs(dev, false);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct drm_encoder_helper_funcs *func = encoder->helper_private;
+
+		func->restore(encoder);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		crtc->funcs->restore(crtc);
+
+	drm_mode_config_cleanup(dev);
+
+	nouveau_hw_save_vga_fonts(dev, 0);
+}
+
+void
+nv04_display_restore(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	NVLockVgaCrtcs(dev, false);
+
+	/* meh.. modeset apparently doesn't setup all the regs and depends
+	 * on pre-existing state, for now load the state of the card *before*
+	 * nouveau was loaded, and then do a modeset.
+	 *
+	 * best thing to do probably is to make save/restore routines not
+	 * save/restore "pre-load" state, but more general so we can save
+	 * on suspend too.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct drm_encoder_helper_funcs *func = encoder->helper_private;
+
+		func->restore(encoder);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		crtc->funcs->restore(crtc);
+
+	if (nv_two_heads(dev)) {
+		NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n",
+			dev_priv->crtc_owner);
+		NVSetOwner(dev, dev_priv->crtc_owner);
+	}
+
+	NVLockVgaCrtcs(dev, true);
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -0,0 +1,792 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_mode.h"
+#include "drm_crtc_helper.h"
+
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_fb.h"
+#include "nouveau_connector.h"
+#include "nv50_display.h"
+
+static void
+nv50_crtc_lut_load(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
+	int i;
+
+	NV_DEBUG_KMS(crtc->dev, "\n");
+
+	for (i = 0; i < 256; i++) {
+		writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0);
+		writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2);
+		writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4);
+	}
+
+	if (nv_crtc->lut.depth == 30) {
+		writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0);
+		writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2);
+		writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4);
+	}
+}
+
+int
+nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	int index = nv_crtc->index, ret;
+
+	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+	NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked");
+
+	if (blanked) {
+		nv_crtc->cursor.hide(nv_crtc, false);
+
+		ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 7 : 5);
+		if (ret) {
+			NV_ERROR(dev, "no space while blanking crtc\n");
+			return ret;
+		}
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
+		OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK);
+		OUT_RING(evo, 0);
+		if (dev_priv->chipset != 0x50) {
+			BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
+			OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE);
+		}
+
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
+		OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
+	} else {
+		if (nv_crtc->cursor.visible)
+			nv_crtc->cursor.show(nv_crtc, false);
+		else
+			nv_crtc->cursor.hide(nv_crtc, false);
+
+		ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 10 : 8);
+		if (ret) {
+			NV_ERROR(dev, "no space while unblanking crtc\n");
+			return ret;
+		}
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2);
+		OUT_RING(evo, nv_crtc->lut.depth == 8 ?
+				NV50_EVO_CRTC_CLUT_MODE_OFF :
+				NV50_EVO_CRTC_CLUT_MODE_ON);
+		OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.mm_node->start <<
+				 PAGE_SHIFT) >> 8);
+		if (dev_priv->chipset != 0x50) {
+			BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1);
+			OUT_RING(evo, NvEvoVRAM);
+		}
+
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_OFFSET), 2);
+		OUT_RING(evo, nv_crtc->fb.offset >> 8);
+		OUT_RING(evo, 0);
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1);
+		if (dev_priv->chipset != 0x50)
+			if (nv_crtc->fb.tile_flags == 0x7a00)
+				OUT_RING(evo, NvEvoFB32);
+			else
+			if (nv_crtc->fb.tile_flags == 0x7000)
+				OUT_RING(evo, NvEvoFB16);
+			else
+				OUT_RING(evo, NvEvoVRAM);
+		else
+			OUT_RING(evo, NvEvoVRAM);
+	}
+
+	nv_crtc->fb.blanked = blanked;
+	return 0;
+}
+
+static int
+nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
+	if (ret) {
+		NV_ERROR(dev, "no space while setting dither\n");
+		return ret;
+	}
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DITHER_CTRL), 1);
+	if (on)
+		OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_ON);
+	else
+		OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_OFF);
+
+	if (update) {
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
+		FIRE_RING(evo);
+	}
+
+	return 0;
+}
+
+struct nouveau_connector *
+nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc = to_drm_crtc(nv_crtc);
+
+	/* The safest approach is to find an encoder with the right crtc, that
+	 * is also linked to a connector. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (connector->encoder)
+			if (connector->encoder->crtc == crtc)
+				return nouveau_connector(connector);
+	}
+
+	return NULL;
+}
+
+static int
+nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update)
+{
+	struct nouveau_connector *nv_connector =
+		nouveau_crtc_connector_get(nv_crtc);
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct drm_display_mode *native_mode = NULL;
+	struct drm_display_mode *mode = &nv_crtc->base.mode;
+	uint32_t outX, outY, horiz, vert;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	switch (scaling_mode) {
+	case DRM_MODE_SCALE_NONE:
+		break;
+	default:
+		if (!nv_connector || !nv_connector->native_mode) {
+			NV_ERROR(dev, "No native mode, forcing panel scaling\n");
+			scaling_mode = DRM_MODE_SCALE_NONE;
+		} else {
+			native_mode = nv_connector->native_mode;
+		}
+		break;
+	}
+
+	switch (scaling_mode) {
+	case DRM_MODE_SCALE_ASPECT:
+		horiz = (native_mode->hdisplay << 19) / mode->hdisplay;
+		vert = (native_mode->vdisplay << 19) / mode->vdisplay;
+
+		if (vert > horiz) {
+			outX = (mode->hdisplay * horiz) >> 19;
+			outY = (mode->vdisplay * horiz) >> 19;
+		} else {
+			outX = (mode->hdisplay * vert) >> 19;
+			outY = (mode->vdisplay * vert) >> 19;
+		}
+		break;
+	case DRM_MODE_SCALE_FULLSCREEN:
+		outX = native_mode->hdisplay;
+		outY = native_mode->vdisplay;
+		break;
+	case DRM_MODE_SCALE_CENTER:
+	case DRM_MODE_SCALE_NONE:
+	default:
+		outX = mode->hdisplay;
+		outY = mode->vdisplay;
+		break;
+	}
+
+	ret = RING_SPACE(evo, update ? 7 : 5);
+	if (ret)
+		return ret;
+
+	/* Got a better name for SCALER_ACTIVE? */
+	/* One day i've got to really figure out why this is needed. */
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1);
+	if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) ||
+	    (mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+	    mode->hdisplay != outX || mode->vdisplay != outY) {
+		OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_ACTIVE);
+	} else {
+		OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_INACTIVE);
+	}
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2);
+	OUT_RING(evo, outY << 16 | outX);
+	OUT_RING(evo, outY << 16 | outX);
+
+	if (update) {
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
+		FIRE_RING(evo);
+	}
+
+	return 0;
+}
+
+int
+nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
+{
+	uint32_t pll_reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head);
+	struct nouveau_pll_vals pll;
+	struct pll_lims limits;
+	uint32_t reg1, reg2;
+	int ret;
+
+	ret = get_pll_limits(dev, pll_reg, &limits);
+	if (ret)
+		return ret;
+
+	ret = nouveau_calc_pll_mnp(dev, &limits, pclk, &pll);
+	if (ret <= 0)
+		return ret;
+
+	if (limits.vco2.maxfreq) {
+		reg1 = nv_rd32(dev, pll_reg + 4) & 0xff00ff00;
+		reg2 = nv_rd32(dev, pll_reg + 8) & 0x8000ff00;
+		nv_wr32(dev, pll_reg, 0x10000611);
+		nv_wr32(dev, pll_reg + 4, reg1 | (pll.M1 << 16) | pll.N1);
+		nv_wr32(dev, pll_reg + 8,
+			reg2 | (pll.log2P << 28) | (pll.M2 << 16) | pll.N2);
+	} else {
+		reg1 = nv_rd32(dev, pll_reg + 4) & 0xffc00000;
+		nv_wr32(dev, pll_reg, 0x50000610);
+		nv_wr32(dev, pll_reg + 4, reg1 |
+			(pll.log2P << 16) | (pll.M1 << 8) | pll.N1);
+	}
+
+	return 0;
+}
+
+static void
+nv50_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct drm_device *dev;
+	struct nouveau_crtc *nv_crtc;
+
+	if (!crtc)
+		return;
+
+	dev = crtc->dev;
+	nv_crtc = nouveau_crtc(crtc);
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	drm_crtc_cleanup(&nv_crtc->base);
+
+	nv50_cursor_fini(nv_crtc);
+
+	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	kfree(nv_crtc->mode);
+	kfree(nv_crtc);
+}
+
+int
+nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+		     uint32_t buffer_handle, uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nouveau_bo *cursor = NULL;
+	struct drm_gem_object *gem;
+	int ret = 0, i;
+
+	if (width != 64 || height != 64)
+		return -EINVAL;
+
+	if (!buffer_handle) {
+		nv_crtc->cursor.hide(nv_crtc, true);
+		return 0;
+	}
+
+	gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
+	if (!gem)
+		return -EINVAL;
+	cursor = nouveau_gem_object(gem);
+
+	ret = nouveau_bo_map(cursor);
+	if (ret)
+		goto out;
+
+	/* The simple will do for now. */
+	for (i = 0; i < 64 * 64; i++)
+		nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, nouveau_bo_rd32(cursor, i));
+
+	nouveau_bo_unmap(cursor);
+
+	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset -
+					    dev_priv->vm_vram_base);
+	nv_crtc->cursor.show(nv_crtc, true);
+
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+int
+nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	nv_crtc->cursor.set_pos(nv_crtc, x, y);
+	return 0;
+}
+
+static void
+nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+		    uint32_t size)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	int i;
+
+	if (size != 256)
+		return;
+
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = r[i];
+		nv_crtc->lut.g[i] = g[i];
+		nv_crtc->lut.b[i] = b[i];
+	}
+
+	/* We need to know the depth before we upload, but it's possible to
+	 * get called before a framebuffer is bound.  If this is the case,
+	 * mark the lut values as dirty by setting depth==0, and it'll be
+	 * uploaded on the first mode_set_base()
+	 */
+	if (!nv_crtc->base.fb) {
+		nv_crtc->lut.depth = 0;
+		return;
+	}
+
+	nv50_crtc_lut_load(crtc);
+}
+
+static void
+nv50_crtc_save(struct drm_crtc *crtc)
+{
+	NV_ERROR(crtc->dev, "!!\n");
+}
+
+static void
+nv50_crtc_restore(struct drm_crtc *crtc)
+{
+	NV_ERROR(crtc->dev, "!!\n");
+}
+
+static const struct drm_crtc_funcs nv50_crtc_funcs = {
+	.save = nv50_crtc_save,
+	.restore = nv50_crtc_restore,
+	.cursor_set = nv50_crtc_cursor_set,
+	.cursor_move = nv50_crtc_cursor_move,
+	.gamma_set = nv50_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = nv50_crtc_destroy,
+};
+
+static void
+nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+}
+
+static void
+nv50_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_encoder *encoder;
+	uint32_t dac = 0, sor = 0;
+
+	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+
+	/* Disconnect all unused encoders. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (!drm_helper_encoder_in_use(encoder))
+			continue;
+
+		if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+		    nv_encoder->dcb->type == OUTPUT_TV)
+			dac |= (1 << nv_encoder->or);
+		else
+			sor |= (1 << nv_encoder->or);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+		    nv_encoder->dcb->type == OUTPUT_TV) {
+			if (dac & (1 << nv_encoder->or))
+				continue;
+		} else {
+			if (sor & (1 << nv_encoder->or))
+				continue;
+		}
+
+		nv_encoder->disconnect(nv_encoder);
+	}
+
+	nv50_crtc_blank(nv_crtc, true);
+}
+
+static void
+nv50_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc *crtc2;
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	int ret;
+
+	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+
+	nv50_crtc_blank(nv_crtc, false);
+
+	/* Explicitly blank all unused crtc's. */
+	list_for_each_entry(crtc2, &dev->mode_config.crtc_list, head) {
+		if (!drm_helper_crtc_in_use(crtc2))
+			nv50_crtc_blank(nouveau_crtc(crtc2), true);
+	}
+
+	ret = RING_SPACE(evo, 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while committing crtc\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+	OUT_RING(evo, 0);
+	FIRE_RING(evo);
+}
+
+static bool
+nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		     struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static int
+nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			   struct drm_framebuffer *old_fb, bool update)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+	int ret, format;
+
+	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+
+	switch (drm_fb->depth) {
+	case  8:
+		format = NV50_EVO_CRTC_FB_DEPTH_8;
+		break;
+	case 15:
+		format = NV50_EVO_CRTC_FB_DEPTH_15;
+		break;
+	case 16:
+		format = NV50_EVO_CRTC_FB_DEPTH_16;
+		break;
+	case 24:
+	case 32:
+		format = NV50_EVO_CRTC_FB_DEPTH_24;
+		break;
+	case 30:
+		format = NV50_EVO_CRTC_FB_DEPTH_30;
+		break;
+	default:
+		 NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth);
+		 return -EINVAL;
+	}
+
+	ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	if (old_fb) {
+		struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb);
+		nouveau_bo_unpin(ofb->nvbo);
+	}
+
+	nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base;
+	nv_crtc->fb.tile_flags = fb->nvbo->tile_flags;
+	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
+	if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
+		ret = RING_SPACE(evo, 2);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
+		if (nv_crtc->fb.tile_flags == 0x7a00)
+			OUT_RING(evo, NvEvoFB32);
+		else
+		if (nv_crtc->fb.tile_flags == 0x7000)
+			OUT_RING(evo, NvEvoFB16);
+		else
+			OUT_RING(evo, NvEvoVRAM);
+	}
+
+	ret = RING_SPACE(evo, 12);
+	if (ret)
+		return ret;
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5);
+	OUT_RING(evo, nv_crtc->fb.offset >> 8);
+	OUT_RING(evo, 0);
+	OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width);
+	if (!nv_crtc->fb.tile_flags) {
+		OUT_RING(evo, drm_fb->pitch | (1 << 20));
+	} else {
+		OUT_RING(evo, ((drm_fb->pitch / 4) << 4) |
+				  fb->nvbo->tile_mode);
+	}
+	if (dev_priv->chipset == 0x50)
+		OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format);
+	else
+		OUT_RING(evo, format);
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1);
+	OUT_RING(evo, fb->base.depth == 8 ?
+		 NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
+	OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
+	OUT_RING(evo, (y << 16) | x);
+
+	if (nv_crtc->lut.depth != fb->base.depth) {
+		nv_crtc->lut.depth = fb->base.depth;
+		nv50_crtc_lut_load(crtc);
+	}
+
+	if (update) {
+		ret = RING_SPACE(evo, 2);
+		if (ret)
+			return ret;
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
+		FIRE_RING(evo);
+	}
+
+	return 0;
+}
+
+static int
+nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		   struct drm_display_mode *adjusted_mode, int x, int y,
+		   struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nouveau_connector *nv_connector = NULL;
+	uint32_t hsync_dur,  vsync_dur, hsync_start_to_end, vsync_start_to_end;
+	uint32_t hunk1, vunk1, vunk2a, vunk2b;
+	int ret;
+
+	/* Find the connector attached to this CRTC */
+	nv_connector = nouveau_crtc_connector_get(nv_crtc);
+
+	*nv_crtc->mode = *adjusted_mode;
+
+	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
+
+	hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
+	vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start;
+	hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start;
+	vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start;
+	/* I can't give this a proper name, anyone else can? */
+	hunk1 = adjusted_mode->htotal -
+		adjusted_mode->hsync_start + adjusted_mode->hdisplay;
+	vunk1 = adjusted_mode->vtotal -
+		adjusted_mode->vsync_start + adjusted_mode->vdisplay;
+	/* Another strange value, this time only for interlaced adjusted_modes. */
+	vunk2a = 2 * adjusted_mode->vtotal -
+		 adjusted_mode->vsync_start + adjusted_mode->vdisplay;
+	vunk2b = adjusted_mode->vtotal -
+		 adjusted_mode->vsync_start + adjusted_mode->vtotal;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		vsync_dur /= 2;
+		vsync_start_to_end  /= 2;
+		vunk1 /= 2;
+		vunk2a /= 2;
+		vunk2b /= 2;
+		/* magic */
+		if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+			vsync_start_to_end -= 1;
+			vunk1 -= 1;
+			vunk2a -= 1;
+			vunk2b -= 1;
+		}
+	}
+
+	ret = RING_SPACE(evo, 17);
+	if (ret)
+		return ret;
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLOCK), 2);
+	OUT_RING(evo, adjusted_mode->clock | 0x800000);
+	OUT_RING(evo, (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0);
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DISPLAY_START), 5);
+	OUT_RING(evo, 0);
+	OUT_RING(evo, (adjusted_mode->vtotal << 16) | adjusted_mode->htotal);
+	OUT_RING(evo, (vsync_dur - 1) << 16 | (hsync_dur - 1));
+	OUT_RING(evo, (vsync_start_to_end - 1) << 16 |
+			(hsync_start_to_end - 1));
+	OUT_RING(evo, (vunk1 - 1) << 16 | (hunk1 - 1));
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK0824), 1);
+		OUT_RING(evo, (vunk2b - 1) << 16 | (vunk2a - 1));
+	} else {
+		OUT_RING(evo, 0);
+		OUT_RING(evo, 0);
+	}
+
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK082C), 1);
+	OUT_RING(evo, 0);
+
+	/* This is the actual resolution of the mode. */
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, REAL_RES), 1);
+	OUT_RING(evo, (mode->vdisplay << 16) | mode->hdisplay);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CENTER_OFFSET), 1);
+	OUT_RING(evo, NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(0, 0));
+
+	nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
+	nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
+
+	return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, false);
+}
+
+static int
+nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			struct drm_framebuffer *old_fb)
+{
+	return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, true);
+}
+
+static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
+	.dpms = nv50_crtc_dpms,
+	.prepare = nv50_crtc_prepare,
+	.commit = nv50_crtc_commit,
+	.mode_fixup = nv50_crtc_mode_fixup,
+	.mode_set = nv50_crtc_mode_set,
+	.mode_set_base = nv50_crtc_mode_set_base,
+	.load_lut = nv50_crtc_lut_load,
+};
+
+int
+nv50_crtc_create(struct drm_device *dev, int index)
+{
+	struct nouveau_crtc *nv_crtc = NULL;
+	int ret, i;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
+	if (!nv_crtc)
+		return -ENOMEM;
+
+	nv_crtc->mode = kzalloc(sizeof(*nv_crtc->mode), GFP_KERNEL);
+	if (!nv_crtc->mode) {
+		kfree(nv_crtc);
+		return -ENOMEM;
+	}
+
+	/* Default CLUT parameters, will be activated on the hw upon
+	 * first mode set.
+	 */
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = i << 8;
+		nv_crtc->lut.g[i] = i << 8;
+		nv_crtc->lut.b[i] = i << 8;
+	}
+	nv_crtc->lut.depth = 0;
+
+	ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, false, true, &nv_crtc->lut.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->lut.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo);
+	}
+
+	if (ret) {
+		kfree(nv_crtc->mode);
+		kfree(nv_crtc);
+		return ret;
+	}
+
+	nv_crtc->index = index;
+
+	/* set function pointers */
+	nv_crtc->set_dither = nv50_crtc_set_dither;
+	nv_crtc->set_scale = nv50_crtc_set_scale;
+
+	drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs);
+	drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
+	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
+
+	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	}
+
+	nv50_cursor_init(nv_crtc);
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright © 2007 David Airlie
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *     David Airlie
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/screen_info.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nouveau_crtc.h"
+#include "nouveau_fb.h"
+#include "nouveau_fbcon.h"
+#include "nouveau_dma.h"
+
+static int
+nouveau_fbcon_sync(struct fb_info *info)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	int ret, i;
+
+	if (!chan || !chan->accel_done ||
+	    info->state != FBINFO_STATE_RUNNING ||
+	    info->flags & FBINFO_HWACCEL_DISABLED)
+		return 0;
+
+	if (RING_SPACE(chan, 4)) {
+		nouveau_fbcon_gpu_lockup(info);
+		return 0;
+	}
+
+	BEGIN_RING(chan, 0, 0x0104, 1);
+	OUT_RING(chan, 0);
+	BEGIN_RING(chan, 0, 0x0100, 1);
+	OUT_RING(chan, 0);
+	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
+	FIRE_RING(chan);
+
+	ret = -EBUSY;
+	for (i = 0; i < 100000; i++) {
+		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) {
+			ret = 0;
+			break;
+		}
+		DRM_UDELAY(1);
+	}
+
+	if (ret) {
+		nouveau_fbcon_gpu_lockup(info);
+		return 0;
+	}
+
+	chan->accel_done = false;
+	return 0;
+}
+
+static struct fb_ops nouveau_fbcon_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_setcolreg = drm_fb_helper_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_sync = nouveau_fbcon_sync,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static struct fb_ops nv04_fbcon_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_setcolreg = drm_fb_helper_setcolreg,
+	.fb_fillrect = nv04_fbcon_fillrect,
+	.fb_copyarea = nv04_fbcon_copyarea,
+	.fb_imageblit = nv04_fbcon_imageblit,
+	.fb_sync = nouveau_fbcon_sync,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static struct fb_ops nv50_fbcon_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_setcolreg = drm_fb_helper_setcolreg,
+	.fb_fillrect = nv50_fbcon_fillrect,
+	.fb_copyarea = nv50_fbcon_copyarea,
+	.fb_imageblit = nv50_fbcon_imageblit,
+	.fb_sync = nouveau_fbcon_sync,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+				    u16 blue, int regno)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	nv_crtc->lut.r[regno] = red;
+	nv_crtc->lut.g[regno] = green;
+	nv_crtc->lut.b[regno] = blue;
+}
+
+static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+				    u16 *blue, int regno)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	*red = nv_crtc->lut.r[regno];
+	*green = nv_crtc->lut.g[regno];
+	*blue = nv_crtc->lut.b[regno];
+}
+
+static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
+	.gamma_set = nouveau_fbcon_gamma_set,
+	.gamma_get = nouveau_fbcon_gamma_get
+};
+
+#if defined(__i386__) || defined(__x86_64__)
+static bool
+nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev)
+{
+	struct pci_dev *pdev = dev->pdev;
+	int ramin;
+
+	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB &&
+	    screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+		return false;
+
+	if (screen_info.lfb_base < pci_resource_start(pdev, 1))
+		goto not_fb;
+
+	if (screen_info.lfb_base + screen_info.lfb_size >=
+	    pci_resource_start(pdev, 1) + pci_resource_len(pdev, 1))
+		goto not_fb;
+
+	return true;
+not_fb:
+	ramin = 2;
+	if (pci_resource_len(pdev, ramin) == 0) {
+		ramin = 3;
+		if (pci_resource_len(pdev, ramin) == 0)
+			return false;
+	}
+
+	if (screen_info.lfb_base < pci_resource_start(pdev, ramin))
+		return false;
+
+	if (screen_info.lfb_base + screen_info.lfb_size >=
+	    pci_resource_start(pdev, ramin) + pci_resource_len(pdev, ramin))
+		return false;
+
+	return true;
+}
+#endif
+
+void
+nouveau_fbcon_zfill(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct fb_info *info = dev_priv->fbdev_info;
+	struct fb_fillrect rect;
+
+	/* Clear the entire fbcon.  The drm will program every connector
+	 * with it's preferred mode.  If the sizes differ, one display will
+	 * quite likely have garbage around the console.
+	 */
+	rect.dx = rect.dy = 0;
+	rect.width = info->var.xres_virtual;
+	rect.height = info->var.yres_virtual;
+	rect.color = 0;
+	rect.rop = ROP_COPY;
+	info->fbops->fb_fillrect(info, &rect);
+}
+
+static int
+nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
+		     uint32_t fb_height, uint32_t surface_width,
+		     uint32_t surface_height, uint32_t surface_depth,
+		     uint32_t surface_bpp, struct drm_framebuffer **pfb)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct fb_info *info;
+	struct nouveau_fbcon_par *par;
+	struct drm_framebuffer *fb;
+	struct nouveau_framebuffer *nouveau_fb;
+	struct nouveau_bo *nvbo;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct device *device = &dev->pdev->dev;
+	int size, ret;
+
+	mode_cmd.width = surface_width;
+	mode_cmd.height = surface_height;
+
+	mode_cmd.bpp = surface_bpp;
+	mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
+	mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
+	mode_cmd.depth = surface_depth;
+
+	size = mode_cmd.pitch * mode_cmd.height;
+	size = roundup(size, PAGE_SIZE);
+
+	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
+			      0, 0x0000, false, true, &nvbo);
+	if (ret) {
+		NV_ERROR(dev, "failed to allocate framebuffer\n");
+		goto out;
+	}
+
+	ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_ERROR(dev, "failed to pin fb: %d\n", ret);
+		nouveau_bo_ref(NULL, &nvbo);
+		goto out;
+	}
+
+	ret = nouveau_bo_map(nvbo);
+	if (ret) {
+		NV_ERROR(dev, "failed to map fb: %d\n", ret);
+		nouveau_bo_unpin(nvbo);
+		nouveau_bo_ref(NULL, &nvbo);
+		goto out;
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	fb = nouveau_framebuffer_create(dev, nvbo, &mode_cmd);
+	if (!fb) {
+		ret = -ENOMEM;
+		NV_ERROR(dev, "failed to allocate fb.\n");
+		goto out_unref;
+	}
+
+	list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
+
+	nouveau_fb = nouveau_framebuffer(fb);
+	*pfb = fb;
+
+	info = framebuffer_alloc(sizeof(struct nouveau_fbcon_par), device);
+	if (!info) {
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+
+	par = info->par;
+	par->helper.funcs = &nouveau_fbcon_helper_funcs;
+	par->helper.dev = dev;
+	ret = drm_fb_helper_init_crtc_count(&par->helper, 2, 4);
+	if (ret)
+		goto out_unref;
+	dev_priv->fbdev_info = info;
+
+	strcpy(info->fix.id, "nouveaufb");
+	if (nouveau_nofbaccel)
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED;
+	else
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+			      FBINFO_HWACCEL_FILLRECT |
+			      FBINFO_HWACCEL_IMAGEBLIT;
+	info->fbops = &nouveau_fbcon_ops;
+	info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
+			       dev_priv->vm_vram_base;
+	info->fix.smem_len = size;
+
+	info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
+	info->screen_size = size;
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
+
+	/* FIXME: we really shouldn't expose mmio space at all */
+	info->fix.mmio_start = pci_resource_start(dev->pdev, 1);
+	info->fix.mmio_len = pci_resource_len(dev->pdev, 1);
+
+	/* Set aperture base/size for vesafb takeover */
+#if defined(__i386__) || defined(__x86_64__)
+	if (nouveau_fbcon_has_vesafb_or_efifb(dev)) {
+		/* Some NVIDIA VBIOS' are stupid and decide to put the
+		 * framebuffer in the middle of the PRAMIN BAR for
+		 * whatever reason.  We need to know the exact lfb_base
+		 * to get vesafb kicked off, and the only reliable way
+		 * we have left is to find out lfb_base the same way
+		 * vesafb did.
+		 */
+		info->aperture_base = screen_info.lfb_base;
+		info->aperture_size = screen_info.lfb_size;
+		if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
+			info->aperture_size *= 65536;
+	} else
+#endif
+	{
+		info->aperture_base = info->fix.mmio_start;
+		info->aperture_size = info->fix.mmio_len;
+	}
+
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+
+	fb->fbdev = info;
+
+	par->nouveau_fb = nouveau_fb;
+	par->dev = dev;
+
+	if (dev_priv->channel && !nouveau_nofbaccel) {
+		switch (dev_priv->card_type) {
+		case NV_50:
+			nv50_fbcon_accel_init(info);
+			info->fbops = &nv50_fbcon_ops;
+			break;
+		default:
+			nv04_fbcon_accel_init(info);
+			info->fbops = &nv04_fbcon_ops;
+			break;
+		};
+	}
+
+	nouveau_fbcon_zfill(dev);
+
+	/* To allow resizeing without swapping buffers */
+	NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n",
+						nouveau_fb->base.width,
+						nouveau_fb->base.height,
+						nvbo->bo.offset, nvbo);
+
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+
+out_unref:
+	mutex_unlock(&dev->struct_mutex);
+out:
+	return ret;
+}
+
+int
+nouveau_fbcon_probe(struct drm_device *dev)
+{
+	NV_DEBUG_KMS(dev, "\n");
+
+	return drm_fb_helper_single_fb_probe(dev, 32, nouveau_fbcon_create);
+}
+
+int
+nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+	struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fb);
+	struct fb_info *info;
+
+	if (!fb)
+		return -EINVAL;
+
+	info = fb->fbdev;
+	if (info) {
+		struct nouveau_fbcon_par *par = info->par;
+
+		unregister_framebuffer(info);
+		nouveau_bo_unmap(nouveau_fb->nvbo);
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(nouveau_fb->nvbo->gem);
+		nouveau_fb->nvbo = NULL;
+		mutex_unlock(&dev->struct_mutex);
+		if (par)
+			drm_fb_helper_free(&par->helper);
+		framebuffer_release(info);
+	}
+
+	return 0;
+}
+
+void nouveau_fbcon_gpu_lockup(struct fb_info *info)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+
+	NV_ERROR(dev, "GPU lockup - switching to software fbcon\n");
+	info->flags |= FBINFO_HWACCEL_DISABLED;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -0,0 +1,1002 @@
+/*
+ * Copyright 1993-2003 NVIDIA, Corporation
+ * Copyright 2006 Dave Airlie
+ * Copyright 2007 Maarten Maathuis
+ *
+ * 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 (including the next
+ * paragraph) 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 "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nouveau_fb.h"
+#include "nouveau_hw.h"
+#include "nvreg.h"
+
+static int
+nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			struct drm_framebuffer *old_fb);
+
+static void
+crtc_wr_cio_state(struct drm_crtc *crtc, struct nv04_crtc_reg *crtcstate, int index)
+{
+	NVWriteVgaCrtc(crtc->dev, nouveau_crtc(crtc)->index, index,
+		       crtcstate->CRTC[index]);
+}
+
+static void nv_crtc_set_digital_vibrance(struct drm_crtc *crtc, int level)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+
+	regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level;
+	if (nv_crtc->saturation && nv_gf4_disp_arch(crtc->dev)) {
+		regp->CRTC[NV_CIO_CRE_CSB] = 0x80;
+		regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2;
+		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_5B);
+	}
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_CSB);
+}
+
+static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+
+	nv_crtc->sharpness = level;
+	if (level < 0)	/* blur is in hw range 0x3f -> 0x20 */
+		level += 0x40;
+	regp->ramdac_634 = level;
+	NVWriteRAMDAC(crtc->dev, nv_crtc->index, NV_PRAMDAC_634, regp->ramdac_634);
+}
+
+#define PLLSEL_VPLL1_MASK				\
+	(NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL	\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2)
+#define PLLSEL_VPLL2_MASK				\
+	(NV_PRAMDAC_PLL_COEFF_SELECT_PLL_SOURCE_VPLL2		\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_VCLK2_RATIO_DB2)
+#define PLLSEL_TV_MASK					\
+	(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1		\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1		\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2	\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2)
+
+/* NV4x 0x40.. pll notes:
+ * gpu pll: 0x4000 + 0x4004
+ * ?gpu? pll: 0x4008 + 0x400c
+ * vpll1: 0x4010 + 0x4014
+ * vpll2: 0x4018 + 0x401c
+ * mpll: 0x4020 + 0x4024
+ * mpll: 0x4038 + 0x403c
+ *
+ * the first register of each pair has some unknown details:
+ * bits 0-7: redirected values from elsewhere? (similar to PLL_SETUP_CONTROL?)
+ * bits 20-23: (mpll) something to do with post divider?
+ * bits 28-31: related to single stage mode? (bit 8/12)
+ */
+
+static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv04_mode_state *state = &dev_priv->mode_reg;
+	struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index];
+	struct nouveau_pll_vals *pv = &regp->pllvals;
+	struct pll_lims pll_lim;
+
+	if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim))
+		return;
+
+	/* NM2 == 0 is used to determine single stage mode on two stage plls */
+	pv->NM2 = 0;
+
+	/* for newer nv4x the blob uses only the first stage of the vpll below a
+	 * certain clock.  for a certain nv4b this is 150MHz.  since the max
+	 * output frequency of the first stage for this card is 300MHz, it is
+	 * assumed the threshold is given by vco1 maxfreq/2
+	 */
+	/* for early nv4x, specifically nv40 and *some* nv43 (devids 0 and 6,
+	 * not 8, others unknown), the blob always uses both plls.  no problem
+	 * has yet been observed in allowing the use a single stage pll on all
+	 * nv43 however.  the behaviour of single stage use is untested on nv40
+	 */
+	if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2))
+		memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2));
+
+	if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv))
+		return;
+
+	state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK;
+
+	/* The blob uses this always, so let's do the same */
+	if (dev_priv->card_type == NV_40)
+		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE;
+	/* again nv40 and some nv43 act more like nv3x as described above */
+	if (dev_priv->chipset < 0x41)
+		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL |
+				 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL;
+	state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK;
+
+	if (pv->NM2)
+		NV_DEBUG_KMS(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n",
+			 pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P);
+	else
+		NV_DEBUG_KMS(dev, "vpll: n %d m %d log2p %d\n",
+			 pv->N1, pv->M1, pv->log2P);
+
+	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
+}
+
+static void
+nv_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	unsigned char seq1 = 0, crtc17 = 0;
+	unsigned char crtc1A;
+
+	NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode,
+							nv_crtc->index);
+
+	if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */
+		return;
+
+	nv_crtc->last_dpms = mode;
+
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, nv_crtc->index);
+
+	/* nv4ref indicates these two RPC1 bits inhibit h/v sync */
+	crtc1A = NVReadVgaCrtc(dev, nv_crtc->index,
+					NV_CIO_CRE_RPC1_INDEX) & ~0xC0;
+	switch (mode) {
+	case DRM_MODE_DPMS_STANDBY:
+		/* Screen: Off; HSync: Off, VSync: On -- Not Supported */
+		seq1 = 0x20;
+		crtc17 = 0x80;
+		crtc1A |= 0x80;
+		break;
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Screen: Off; HSync: On, VSync: Off -- Not Supported */
+		seq1 = 0x20;
+		crtc17 = 0x80;
+		crtc1A |= 0x40;
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Screen: Off; HSync: Off, VSync: Off */
+		seq1 = 0x20;
+		crtc17 = 0x00;
+		crtc1A |= 0xC0;
+		break;
+	case DRM_MODE_DPMS_ON:
+	default:
+		/* Screen: On; HSync: On, VSync: On */
+		seq1 = 0x00;
+		crtc17 = 0x80;
+		break;
+	}
+
+	NVVgaSeqReset(dev, nv_crtc->index, true);
+	/* Each head has it's own sequencer, so we can turn it off when we want */
+	seq1 |= (NVReadVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX) & ~0x20);
+	NVWriteVgaSeq(dev, nv_crtc->index, NV_VIO_SR_CLOCK_INDEX, seq1);
+	crtc17 |= (NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX) & ~0x80);
+	mdelay(10);
+	NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CR_MODE_INDEX, crtc17);
+	NVVgaSeqReset(dev, nv_crtc->index, false);
+
+	NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
+}
+
+static bool
+nv_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		   struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void
+nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+	struct drm_framebuffer *fb = crtc->fb;
+
+	/* Calculate our timings */
+	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1;
+	int horizStart		= (mode->crtc_hsync_start >> 3) 	+ 1;
+	int horizEnd		= (mode->crtc_hsync_end >> 3)		+ 1;
+	int horizTotal		= (mode->crtc_htotal >> 3)		- 5;
+	int horizBlankStart	= (mode->crtc_hdisplay >> 3)		- 1;
+	int horizBlankEnd	= (mode->crtc_htotal >> 3)		- 1;
+	int vertDisplay		= mode->crtc_vdisplay			- 1;
+	int vertStart		= mode->crtc_vsync_start 		- 1;
+	int vertEnd		= mode->crtc_vsync_end			- 1;
+	int vertTotal		= mode->crtc_vtotal 			- 2;
+	int vertBlankStart	= mode->crtc_vdisplay 			- 1;
+	int vertBlankEnd	= mode->crtc_vtotal			- 1;
+
+	struct drm_encoder *encoder;
+	bool fp_output = false;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (encoder->crtc == crtc &&
+		    (nv_encoder->dcb->type == OUTPUT_LVDS ||
+		     nv_encoder->dcb->type == OUTPUT_TMDS))
+			fp_output = true;
+	}
+
+	if (fp_output) {
+		vertStart = vertTotal - 3;
+		vertEnd = vertTotal - 2;
+		vertBlankStart = vertStart;
+		horizStart = horizTotal - 5;
+		horizEnd = horizTotal - 2;
+		horizBlankEnd = horizTotal + 4;
+#if 0
+		if (dev->overlayAdaptor && dev_priv->card_type >= NV_10)
+			/* This reportedly works around some video overlay bandwidth problems */
+			horizTotal += 2;
+#endif
+	}
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vertTotal |= 1;
+
+#if 0
+	ErrorF("horizDisplay: 0x%X \n", horizDisplay);
+	ErrorF("horizStart: 0x%X \n", horizStart);
+	ErrorF("horizEnd: 0x%X \n", horizEnd);
+	ErrorF("horizTotal: 0x%X \n", horizTotal);
+	ErrorF("horizBlankStart: 0x%X \n", horizBlankStart);
+	ErrorF("horizBlankEnd: 0x%X \n", horizBlankEnd);
+	ErrorF("vertDisplay: 0x%X \n", vertDisplay);
+	ErrorF("vertStart: 0x%X \n", vertStart);
+	ErrorF("vertEnd: 0x%X \n", vertEnd);
+	ErrorF("vertTotal: 0x%X \n", vertTotal);
+	ErrorF("vertBlankStart: 0x%X \n", vertBlankStart);
+	ErrorF("vertBlankEnd: 0x%X \n", vertBlankEnd);
+#endif
+
+	/*
+	* compute correct Hsync & Vsync polarity
+	*/
+	if ((mode->flags & (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))
+		&& (mode->flags & (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) {
+
+		regp->MiscOutReg = 0x23;
+		if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+			regp->MiscOutReg |= 0x40;
+		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+			regp->MiscOutReg |= 0x80;
+	} else {
+		int vdisplay = mode->vdisplay;
+		if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+			vdisplay *= 2;
+		if (mode->vscan > 1)
+			vdisplay *= mode->vscan;
+		if (vdisplay < 400)
+			regp->MiscOutReg = 0xA3;	/* +hsync -vsync */
+		else if (vdisplay < 480)
+			regp->MiscOutReg = 0x63;	/* -hsync +vsync */
+		else if (vdisplay < 768)
+			regp->MiscOutReg = 0xE3;	/* -hsync -vsync */
+		else
+			regp->MiscOutReg = 0x23;	/* +hsync +vsync */
+	}
+
+	regp->MiscOutReg |= (mode->clock_index & 0x03) << 2;
+
+	/*
+	 * Time Sequencer
+	 */
+	regp->Sequencer[NV_VIO_SR_RESET_INDEX] = 0x00;
+	/* 0x20 disables the sequencer */
+	if (mode->flags & DRM_MODE_FLAG_CLKDIV2)
+		regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x29;
+	else
+		regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x21;
+	regp->Sequencer[NV_VIO_SR_PLANE_MASK_INDEX] = 0x0F;
+	regp->Sequencer[NV_VIO_SR_CHAR_MAP_INDEX] = 0x00;
+	regp->Sequencer[NV_VIO_SR_MEM_MODE_INDEX] = 0x0E;
+
+	/*
+	 * CRTC
+	 */
+	regp->CRTC[NV_CIO_CR_HDT_INDEX] = horizTotal;
+	regp->CRTC[NV_CIO_CR_HDE_INDEX] = horizDisplay;
+	regp->CRTC[NV_CIO_CR_HBS_INDEX] = horizBlankStart;
+	regp->CRTC[NV_CIO_CR_HBE_INDEX] = (1 << 7) |
+					  XLATE(horizBlankEnd, 0, NV_CIO_CR_HBE_4_0);
+	regp->CRTC[NV_CIO_CR_HRS_INDEX] = horizStart;
+	regp->CRTC[NV_CIO_CR_HRE_INDEX] = XLATE(horizBlankEnd, 5, NV_CIO_CR_HRE_HBE_5) |
+					  XLATE(horizEnd, 0, NV_CIO_CR_HRE_4_0);
+	regp->CRTC[NV_CIO_CR_VDT_INDEX] = vertTotal;
+	regp->CRTC[NV_CIO_CR_OVL_INDEX] = XLATE(vertStart, 9, NV_CIO_CR_OVL_VRS_9) |
+					  XLATE(vertDisplay, 9, NV_CIO_CR_OVL_VDE_9) |
+					  XLATE(vertTotal, 9, NV_CIO_CR_OVL_VDT_9) |
+					  (1 << 4) |
+					  XLATE(vertBlankStart, 8, NV_CIO_CR_OVL_VBS_8) |
+					  XLATE(vertStart, 8, NV_CIO_CR_OVL_VRS_8) |
+					  XLATE(vertDisplay, 8, NV_CIO_CR_OVL_VDE_8) |
+					  XLATE(vertTotal, 8, NV_CIO_CR_OVL_VDT_8);
+	regp->CRTC[NV_CIO_CR_RSAL_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_CELL_HT_INDEX] = ((mode->flags & DRM_MODE_FLAG_DBLSCAN) ? MASK(NV_CIO_CR_CELL_HT_SCANDBL) : 0) |
+					      1 << 6 |
+					      XLATE(vertBlankStart, 9, NV_CIO_CR_CELL_HT_VBS_9);
+	regp->CRTC[NV_CIO_CR_CURS_ST_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_CURS_END_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_SA_HI_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_SA_LO_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_TCOFF_HI_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_TCOFF_LO_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_VRS_INDEX] = vertStart;
+	regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0);
+	regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay;
+	/* framebuffer can be larger than crtc scanout area. */
+	regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = fb->pitch / 8;
+	regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00;
+	regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart;
+	regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd;
+	regp->CRTC[NV_CIO_CR_MODE_INDEX] = 0x43;
+	regp->CRTC[NV_CIO_CR_LCOMP_INDEX] = 0xff;
+
+	/*
+	 * Some extended CRTC registers (they are not saved with the rest of the vga regs).
+	 */
+
+	/* framebuffer can be larger than crtc scanout area. */
+	regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
+	regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ?
+					    MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00;
+	regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) |
+					   XLATE(vertBlankStart, 10, NV_CIO_CRE_LSR_VBS_10) |
+					   XLATE(vertStart, 10, NV_CIO_CRE_LSR_VRS_10) |
+					   XLATE(vertDisplay, 10, NV_CIO_CRE_LSR_VDE_10) |
+					   XLATE(vertTotal, 10, NV_CIO_CRE_LSR_VDT_10);
+	regp->CRTC[NV_CIO_CRE_HEB__INDEX] = XLATE(horizStart, 8, NV_CIO_CRE_HEB_HRS_8) |
+					    XLATE(horizBlankStart, 8, NV_CIO_CRE_HEB_HBS_8) |
+					    XLATE(horizDisplay, 8, NV_CIO_CRE_HEB_HDE_8) |
+					    XLATE(horizTotal, 8, NV_CIO_CRE_HEB_HDT_8);
+	regp->CRTC[NV_CIO_CRE_EBR_INDEX] = XLATE(vertBlankStart, 11, NV_CIO_CRE_EBR_VBS_11) |
+					   XLATE(vertStart, 11, NV_CIO_CRE_EBR_VRS_11) |
+					   XLATE(vertDisplay, 11, NV_CIO_CRE_EBR_VDE_11) |
+					   XLATE(vertTotal, 11, NV_CIO_CRE_EBR_VDT_11);
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		horizTotal = (horizTotal >> 1) & ~1;
+		regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = horizTotal;
+		regp->CRTC[NV_CIO_CRE_HEB__INDEX] |= XLATE(horizTotal, 8, NV_CIO_CRE_HEB_ILC_8);
+	} else
+		regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = 0xff;  /* interlace off */
+
+	/*
+	* Graphics Display Controller
+	*/
+	regp->Graphics[NV_VIO_GX_SR_INDEX] = 0x00;
+	regp->Graphics[NV_VIO_GX_SREN_INDEX] = 0x00;
+	regp->Graphics[NV_VIO_GX_CCOMP_INDEX] = 0x00;
+	regp->Graphics[NV_VIO_GX_ROP_INDEX] = 0x00;
+	regp->Graphics[NV_VIO_GX_READ_MAP_INDEX] = 0x00;
+	regp->Graphics[NV_VIO_GX_MODE_INDEX] = 0x40; /* 256 color mode */
+	regp->Graphics[NV_VIO_GX_MISC_INDEX] = 0x05; /* map 64k mem + graphic mode */
+	regp->Graphics[NV_VIO_GX_DONT_CARE_INDEX] = 0x0F;
+	regp->Graphics[NV_VIO_GX_BIT_MASK_INDEX] = 0xFF;
+
+	regp->Attribute[0]  = 0x00; /* standard colormap translation */
+	regp->Attribute[1]  = 0x01;
+	regp->Attribute[2]  = 0x02;
+	regp->Attribute[3]  = 0x03;
+	regp->Attribute[4]  = 0x04;
+	regp->Attribute[5]  = 0x05;
+	regp->Attribute[6]  = 0x06;
+	regp->Attribute[7]  = 0x07;
+	regp->Attribute[8]  = 0x08;
+	regp->Attribute[9]  = 0x09;
+	regp->Attribute[10] = 0x0A;
+	regp->Attribute[11] = 0x0B;
+	regp->Attribute[12] = 0x0C;
+	regp->Attribute[13] = 0x0D;
+	regp->Attribute[14] = 0x0E;
+	regp->Attribute[15] = 0x0F;
+	regp->Attribute[NV_CIO_AR_MODE_INDEX] = 0x01; /* Enable graphic mode */
+	/* Non-vga */
+	regp->Attribute[NV_CIO_AR_OSCAN_INDEX] = 0x00;
+	regp->Attribute[NV_CIO_AR_PLANE_INDEX] = 0x0F; /* enable all color planes */
+	regp->Attribute[NV_CIO_AR_HPP_INDEX] = 0x00;
+	regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00;
+}
+
+/**
+ * Sets up registers for the given mode/adjusted_mode pair.
+ *
+ * The clocks, CRTCs and outputs attached to this CRTC must be off.
+ *
+ * This shouldn't enable any clocks, CRTCs, or outputs, but they should
+ * be easily turned on/off after this.
+ */
+static void
+nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+	struct nv04_crtc_reg *savep = &dev_priv->saved_reg.crtc_reg[nv_crtc->index];
+	struct drm_encoder *encoder;
+	bool lvds_output = false, tmds_output = false, tv_output = false,
+		off_chip_digital = false;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+		bool digital = false;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		if (nv_encoder->dcb->type == OUTPUT_LVDS)
+			digital = lvds_output = true;
+		if (nv_encoder->dcb->type == OUTPUT_TV)
+			tv_output = true;
+		if (nv_encoder->dcb->type == OUTPUT_TMDS)
+			digital = tmds_output = true;
+		if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital)
+			off_chip_digital = true;
+	}
+
+	/* Registers not directly related to the (s)vga mode */
+
+	/* What is the meaning of this register? */
+	/* A few popular values are 0x18, 0x1c, 0x38, 0x3c */
+	regp->CRTC[NV_CIO_CRE_ENH_INDEX] = savep->CRTC[NV_CIO_CRE_ENH_INDEX] & ~(1<<5);
+
+	regp->crtc_eng_ctrl = 0;
+	/* Except for rare conditions I2C is enabled on the primary crtc */
+	if (nv_crtc->index == 0)
+		regp->crtc_eng_ctrl |= NV_CRTC_FSEL_I2C;
+#if 0
+	/* Set overlay to desired crtc. */
+	if (dev->overlayAdaptor) {
+		NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(dev);
+		if (pPriv->overlayCRTC == nv_crtc->index)
+			regp->crtc_eng_ctrl |= NV_CRTC_FSEL_OVERLAY;
+	}
+#endif
+
+	/* ADDRESS_SPACE_PNVM is the same as setting HCUR_ASI */
+	regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 |
+			     NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 |
+			     NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM;
+	if (dev_priv->chipset >= 0x11)
+		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32;
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE;
+
+	/* Unblock some timings */
+	regp->CRTC[NV_CIO_CRE_53] = 0;
+	regp->CRTC[NV_CIO_CRE_54] = 0;
+
+	/* 0x00 is disabled, 0x11 is lvds, 0x22 crt and 0x88 tmds */
+	if (lvds_output)
+		regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x11;
+	else if (tmds_output)
+		regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x88;
+	else
+		regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x22;
+
+	/* These values seem to vary */
+	/* This register seems to be used by the bios to make certain decisions on some G70 cards? */
+	regp->CRTC[NV_CIO_CRE_SCRATCH4__INDEX] = savep->CRTC[NV_CIO_CRE_SCRATCH4__INDEX];
+
+	nv_crtc_set_digital_vibrance(crtc, nv_crtc->saturation);
+
+	/* probably a scratch reg, but kept for cargo-cult purposes:
+	 * bit0: crtc0?, head A
+	 * bit6: lvds, head A
+	 * bit7: (only in X), head A
+	 */
+	if (nv_crtc->index == 0)
+		regp->CRTC[NV_CIO_CRE_4B] = savep->CRTC[NV_CIO_CRE_4B] | 0x80;
+
+	/* The blob seems to take the current value from crtc 0, add 4 to that
+	 * and reuse the old value for crtc 1 */
+	regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] = dev_priv->saved_reg.crtc_reg[0].CRTC[NV_CIO_CRE_TVOUT_LATENCY];
+	if (!nv_crtc->index)
+		regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] += 4;
+
+	/* the blob sometimes sets |= 0x10 (which is the same as setting |=
+	 * 1 << 30 on 0x60.830), for no apparent reason */
+	regp->CRTC[NV_CIO_CRE_59] = off_chip_digital;
+
+	regp->crtc_830 = mode->crtc_vdisplay - 3;
+	regp->crtc_834 = mode->crtc_vdisplay - 1;
+
+	if (dev_priv->card_type == NV_40)
+		/* This is what the blob does */
+		regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850);
+
+	if (dev_priv->card_type >= NV_30)
+		regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT);
+
+	regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC;
+
+	/* Some misc regs */
+	if (dev_priv->card_type == NV_40) {
+		regp->CRTC[NV_CIO_CRE_85] = 0xFF;
+		regp->CRTC[NV_CIO_CRE_86] = 0x1;
+	}
+
+	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8;
+	/* Enable slaved mode (called MODE_TV in nv4ref.h) */
+	if (lvds_output || tmds_output || tv_output)
+		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
+
+	/* Generic PRAMDAC regs */
+
+	if (dev_priv->card_type >= NV_10)
+		/* Only bit that bios and blob set. */
+		regp->nv10_cursync = (1 << 25);
+
+	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
+				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
+				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
+	if (crtc->fb->depth == 16)
+		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
+	if (dev_priv->chipset >= 0x11)
+		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
+
+	regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */
+	regp->tv_setup = 0;
+
+	nv_crtc_set_image_sharpening(crtc, nv_crtc->sharpness);
+
+	/* Some values the blob sets */
+	regp->ramdac_8c0 = 0x100;
+	regp->ramdac_a20 = 0x0;
+	regp->ramdac_a24 = 0xfffff;
+	regp->ramdac_a34 = 0x1;
+}
+
+/**
+ * Sets up registers for the given mode/adjusted_mode pair.
+ *
+ * The clocks, CRTCs and outputs attached to this CRTC must be off.
+ *
+ * This shouldn't enable any clocks, CRTCs, or outputs, but they should
+ * be easily turned on/off after this.
+ */
+static int
+nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		 struct drm_display_mode *adjusted_mode,
+		 int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	NV_DEBUG_KMS(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index);
+	drm_mode_debug_printmodeline(adjusted_mode);
+
+	/* unlock must come after turning off FP_TG_CONTROL in output_prepare */
+	nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
+
+	nv_crtc_mode_set_vga(crtc, adjusted_mode);
+	/* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */
+	if (dev_priv->card_type == NV_40)
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, dev_priv->mode_reg.sel_clk);
+	nv_crtc_mode_set_regs(crtc, adjusted_mode);
+	nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock);
+	return 0;
+}
+
+static void nv_crtc_save(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nv04_mode_state *state = &dev_priv->mode_reg;
+	struct nv04_crtc_reg *crtc_state = &state->crtc_reg[nv_crtc->index];
+	struct nv04_mode_state *saved = &dev_priv->saved_reg;
+	struct nv04_crtc_reg *crtc_saved = &saved->crtc_reg[nv_crtc->index];
+
+	if (nv_two_heads(crtc->dev))
+		NVSetOwner(crtc->dev, nv_crtc->index);
+
+	nouveau_hw_save_state(crtc->dev, nv_crtc->index, saved);
+
+	/* init some state to saved value */
+	state->sel_clk = saved->sel_clk & ~(0x5 << 16);
+	crtc_state->CRTC[NV_CIO_CRE_LCD__INDEX] = crtc_saved->CRTC[NV_CIO_CRE_LCD__INDEX];
+	state->pllsel = saved->pllsel & ~(PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK);
+	crtc_state->gpio_ext = crtc_saved->gpio_ext;
+}
+
+static void nv_crtc_restore(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	int head = nv_crtc->index;
+	uint8_t saved_cr21 = dev_priv->saved_reg.crtc_reg[head].CRTC[NV_CIO_CRE_21];
+
+	if (nv_two_heads(crtc->dev))
+		NVSetOwner(crtc->dev, head);
+
+	nouveau_hw_load_state(crtc->dev, head, &dev_priv->saved_reg);
+	nv_lock_vga_crtc_shadow(crtc->dev, head, saved_cr21);
+
+	nv_crtc->last_dpms = NV_DPMS_CLEARED;
+}
+
+static void nv_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
+
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, nv_crtc->index);
+
+	funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+	NVBlankScreen(dev, nv_crtc->index, true);
+
+	/* Some more preperation. */
+	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
+	if (dev_priv->card_type == NV_40) {
+		uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900);
+		NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000);
+	}
+}
+
+static void nv_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_crtc_helper_funcs *funcs = crtc->helper_private;
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	nouveau_hw_load_state(dev, nv_crtc->index, &dev_priv->mode_reg);
+	nv04_crtc_mode_set_base(crtc, crtc->x, crtc->y, NULL);
+
+#ifdef __BIG_ENDIAN
+	/* turn on LFB swapping */
+	{
+		uint8_t tmp = NVReadVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR);
+		tmp |= MASK(NV_CIO_CRE_RCR_ENDIAN_BIG);
+		NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RCR, tmp);
+	}
+#endif
+
+	funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static void nv_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	NV_DEBUG_KMS(crtc->dev, "\n");
+
+	if (!nv_crtc)
+		return;
+
+	drm_crtc_cleanup(crtc);
+
+	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	kfree(nv_crtc);
+}
+
+static void
+nv_crtc_gamma_load(struct drm_crtc *crtc)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs;
+	int i;
+
+	rgbs = (struct rgb *)dev_priv->mode_reg.crtc_reg[nv_crtc->index].DAC;
+	for (i = 0; i < 256; i++) {
+		rgbs[i].r = nv_crtc->lut.r[i] >> 8;
+		rgbs[i].g = nv_crtc->lut.g[i] >> 8;
+		rgbs[i].b = nv_crtc->lut.b[i] >> 8;
+	}
+
+	nouveau_hw_load_state_palette(dev, nv_crtc->index, &dev_priv->mode_reg);
+}
+
+static void
+nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	int i;
+
+	if (size != 256)
+		return;
+
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = r[i];
+		nv_crtc->lut.g[i] = g[i];
+		nv_crtc->lut.b[i] = b[i];
+	}
+
+	/* We need to know the depth before we upload, but it's possible to
+	 * get called before a framebuffer is bound.  If this is the case,
+	 * mark the lut values as dirty by setting depth==0, and it'll be
+	 * uploaded on the first mode_set_base()
+	 */
+	if (!nv_crtc->base.fb) {
+		nv_crtc->lut.depth = 0;
+		return;
+	}
+
+	nv_crtc_gamma_load(crtc);
+}
+
+static int
+nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+			struct drm_framebuffer *old_fb)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+	struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
+	int arb_burst, arb_lwm;
+	int ret;
+
+	ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
+	if (ret)
+		return ret;
+
+	if (old_fb) {
+		struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb);
+		nouveau_bo_unpin(ofb->nvbo);
+	}
+
+	nv_crtc->fb.offset = fb->nvbo->bo.offset;
+
+	if (nv_crtc->lut.depth != drm_fb->depth) {
+		nv_crtc->lut.depth = drm_fb->depth;
+		nv_crtc_gamma_load(crtc);
+	}
+
+	/* Update the framebuffer format. */
+	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3;
+	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8;
+	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
+	if (crtc->fb->depth == 16)
+		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);
+	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL,
+		      regp->ramdac_gen_ctrl);
+
+	regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3;
+	regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
+		XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX);
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX);
+
+	/* Update the framebuffer location. */
+	regp->fb_start = nv_crtc->fb.offset & ~3;
+	regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8);
+	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start);
+
+	/* Update the arbitration parameters. */
+	nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel,
+			 &arb_burst, &arb_lwm);
+
+	regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst;
+	regp->CRTC[NV_CIO_CRE_FFLWM__INDEX] = arb_lwm & 0xff;
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
+
+	if (dev_priv->card_type >= NV_30) {
+		regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
+		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
+	}
+
+	return 0;
+}
+
+static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
+			       struct nouveau_bo *dst)
+{
+	int width = nv_cursor_width(dev);
+	uint32_t pixel;
+	int i, j;
+
+	for (i = 0; i < width; i++) {
+		for (j = 0; j < width; j++) {
+			pixel = nouveau_bo_rd32(src, i*64 + j);
+
+			nouveau_bo_wr16(dst, i*width + j, (pixel & 0x80000000) >> 16
+				     | (pixel & 0xf80000) >> 9
+				     | (pixel & 0xf800) >> 6
+				     | (pixel & 0xf8) >> 3);
+		}
+	}
+}
+
+static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
+			       struct nouveau_bo *dst)
+{
+	uint32_t pixel;
+	int alpha, i;
+
+	/* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha
+	 * cursors (though NPM in combination with fp dithering may not work on
+	 * nv11, from "nv" driver history)
+	 * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the
+	 * blob uses, however we get given PM cursors so we use PM mode
+	 */
+	for (i = 0; i < 64 * 64; i++) {
+		pixel = nouveau_bo_rd32(src, i);
+
+		/* hw gets unhappy if alpha <= rgb values.  for a PM image "less
+		 * than" shouldn't happen; fix "equal to" case by adding one to
+		 * alpha channel (slightly inaccurate, but so is attempting to
+		 * get back to NPM images, due to limits of integer precision)
+		 */
+		alpha = pixel >> 24;
+		if (alpha > 0 && alpha < 255)
+			pixel = (pixel & 0x00ffffff) | ((alpha + 1) << 24);
+
+#ifdef __BIG_ENDIAN
+		{
+			struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+			if (dev_priv->chipset == 0x11) {
+				pixel = ((pixel & 0x000000ff) << 24) |
+					((pixel & 0x0000ff00) << 8) |
+					((pixel & 0x00ff0000) >> 8) |
+					((pixel & 0xff000000) >> 24);
+			}
+		}
+#endif
+
+		nouveau_bo_wr32(dst, i, pixel);
+	}
+}
+
+static int
+nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+		     uint32_t buffer_handle, uint32_t width, uint32_t height)
+{
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct drm_device *dev = dev_priv->dev;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nouveau_bo *cursor = NULL;
+	struct drm_gem_object *gem;
+	int ret = 0;
+
+	if (width != 64 || height != 64)
+		return -EINVAL;
+
+	if (!buffer_handle) {
+		nv_crtc->cursor.hide(nv_crtc, true);
+		return 0;
+	}
+
+	gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
+	if (!gem)
+		return -EINVAL;
+	cursor = nouveau_gem_object(gem);
+
+	ret = nouveau_bo_map(cursor);
+	if (ret)
+		goto out;
+
+	if (dev_priv->chipset >= 0x11)
+		nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
+	else
+		nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
+
+	nouveau_bo_unmap(cursor);
+	nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->bo.offset;
+	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
+	nv_crtc->cursor.show(nv_crtc, true);
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static int
+nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+	nv_crtc->cursor.set_pos(nv_crtc, x, y);
+	return 0;
+}
+
+static const struct drm_crtc_funcs nv04_crtc_funcs = {
+	.save = nv_crtc_save,
+	.restore = nv_crtc_restore,
+	.cursor_set = nv04_crtc_cursor_set,
+	.cursor_move = nv04_crtc_cursor_move,
+	.gamma_set = nv_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = nv_crtc_destroy,
+};
+
+static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
+	.dpms = nv_crtc_dpms,
+	.prepare = nv_crtc_prepare,
+	.commit = nv_crtc_commit,
+	.mode_fixup = nv_crtc_mode_fixup,
+	.mode_set = nv_crtc_mode_set,
+	.mode_set_base = nv04_crtc_mode_set_base,
+	.load_lut = nv_crtc_gamma_load,
+};
+
+int
+nv04_crtc_create(struct drm_device *dev, int crtc_num)
+{
+	struct nouveau_crtc *nv_crtc;
+	int ret, i;
+
+	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL);
+	if (!nv_crtc)
+		return -ENOMEM;
+
+	for (i = 0; i < 256; i++) {
+		nv_crtc->lut.r[i] = i << 8;
+		nv_crtc->lut.g[i] = i << 8;
+		nv_crtc->lut.b[i] = i << 8;
+	}
+	nv_crtc->lut.depth = 0;
+
+	nv_crtc->index = crtc_num;
+	nv_crtc->last_dpms = NV_DPMS_CLEARED;
+
+	drm_crtc_init(dev, &nv_crtc->base, &nv04_crtc_funcs);
+	drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs);
+	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
+
+	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
+			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+	if (!ret) {
+		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
+		if (!ret)
+			ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
+		if (ret)
+			nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
+	}
+
+	nv04_cursor_init(nv_crtc);
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nvreg.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nvreg.h
@@ -0,0 +1,535 @@
+/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */
+/*
+ * Copyright 1996-1997  David J. McKay
+ *
+ * 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
+ * DAVID J. MCKAY 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nvreg.h,v 1.6 2002/01/25 21:56:06 tsi Exp $ */
+
+#ifndef __NVREG_H_
+#define __NVREG_H_
+
+#define NV_PMC_OFFSET               0x00000000
+#define NV_PMC_SIZE                 0x00001000
+
+#define NV_PBUS_OFFSET              0x00001000
+#define NV_PBUS_SIZE                0x00001000
+
+#define NV_PFIFO_OFFSET             0x00002000
+#define NV_PFIFO_SIZE               0x00002000
+
+#define NV_HDIAG_OFFSET             0x00005000
+#define NV_HDIAG_SIZE               0x00001000
+
+#define NV_PRAM_OFFSET              0x00006000
+#define NV_PRAM_SIZE                0x00001000
+
+#define NV_PVIDEO_OFFSET            0x00008000
+#define NV_PVIDEO_SIZE              0x00001000
+
+#define NV_PTIMER_OFFSET            0x00009000
+#define NV_PTIMER_SIZE              0x00001000
+
+#define NV_PPM_OFFSET               0x0000A000
+#define NV_PPM_SIZE                 0x00001000
+
+#define NV_PTV_OFFSET               0x0000D000
+#define NV_PTV_SIZE                 0x00001000
+
+#define NV_PRMVGA_OFFSET            0x000A0000
+#define NV_PRMVGA_SIZE              0x00020000
+
+#define NV_PRMVIO0_OFFSET           0x000C0000
+#define NV_PRMVIO_SIZE              0x00002000
+#define NV_PRMVIO1_OFFSET           0x000C2000
+
+#define NV_PFB_OFFSET               0x00100000
+#define NV_PFB_SIZE                 0x00001000
+
+#define NV_PEXTDEV_OFFSET           0x00101000
+#define NV_PEXTDEV_SIZE             0x00001000
+
+#define NV_PME_OFFSET               0x00200000
+#define NV_PME_SIZE                 0x00001000
+
+#define NV_PROM_OFFSET              0x00300000
+#define NV_PROM_SIZE                0x00010000
+
+#define NV_PGRAPH_OFFSET            0x00400000
+#define NV_PGRAPH_SIZE              0x00010000
+
+#define NV_PCRTC0_OFFSET            0x00600000
+#define NV_PCRTC0_SIZE              0x00002000 /* empirical */
+
+#define NV_PRMCIO0_OFFSET           0x00601000
+#define NV_PRMCIO_SIZE              0x00002000
+#define NV_PRMCIO1_OFFSET           0x00603000
+
+#define NV50_DISPLAY_OFFSET           0x00610000
+#define NV50_DISPLAY_SIZE             0x0000FFFF
+
+#define NV_PRAMDAC0_OFFSET          0x00680000
+#define NV_PRAMDAC0_SIZE            0x00002000
+
+#define NV_PRMDIO0_OFFSET           0x00681000
+#define NV_PRMDIO_SIZE              0x00002000
+#define NV_PRMDIO1_OFFSET           0x00683000
+
+#define NV_PRAMIN_OFFSET            0x00700000
+#define NV_PRAMIN_SIZE              0x00100000
+
+#define NV_FIFO_OFFSET              0x00800000
+#define NV_FIFO_SIZE                0x00800000
+
+#define NV_PMC_BOOT_0			0x00000000
+#define NV_PMC_ENABLE			0x00000200
+
+#define NV_VIO_VSE2			0x000003c3
+#define NV_VIO_SRX			0x000003c4
+
+#define NV_CIO_CRX__COLOR		0x000003d4
+#define NV_CIO_CR__COLOR		0x000003d5
+
+#define NV_PBUS_DEBUG_1			0x00001084
+#define NV_PBUS_DEBUG_4			0x00001098
+#define NV_PBUS_DEBUG_DUALHEAD_CTL	0x000010f0
+#define NV_PBUS_POWERCTRL_1		0x00001584
+#define NV_PBUS_POWERCTRL_2		0x00001588
+#define NV_PBUS_POWERCTRL_4		0x00001590
+#define NV_PBUS_PCI_NV_19		0x0000184C
+#define NV_PBUS_PCI_NV_20		0x00001850
+#	define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED	(0 << 0)
+#	define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED	(1 << 0)
+
+#define NV_PFIFO_RAMHT			0x00002210
+
+#define NV_PTV_TV_INDEX			0x0000d220
+#define NV_PTV_TV_DATA			0x0000d224
+#define NV_PTV_HFILTER			0x0000d310
+#define NV_PTV_HFILTER2			0x0000d390
+#define NV_PTV_VFILTER			0x0000d510
+
+#define NV_PRMVIO_MISC__WRITE		0x000c03c2
+#define NV_PRMVIO_SRX			0x000c03c4
+#define NV_PRMVIO_SR			0x000c03c5
+#	define NV_VIO_SR_RESET_INDEX		0x00
+#	define NV_VIO_SR_CLOCK_INDEX		0x01
+#	define NV_VIO_SR_PLANE_MASK_INDEX	0x02
+#	define NV_VIO_SR_CHAR_MAP_INDEX		0x03
+#	define NV_VIO_SR_MEM_MODE_INDEX		0x04
+#define NV_PRMVIO_MISC__READ		0x000c03cc
+#define NV_PRMVIO_GRX			0x000c03ce
+#define NV_PRMVIO_GX			0x000c03cf
+#	define NV_VIO_GX_SR_INDEX		0x00
+#	define NV_VIO_GX_SREN_INDEX		0x01
+#	define NV_VIO_GX_CCOMP_INDEX		0x02
+#	define NV_VIO_GX_ROP_INDEX		0x03
+#	define NV_VIO_GX_READ_MAP_INDEX		0x04
+#	define NV_VIO_GX_MODE_INDEX		0x05
+#	define NV_VIO_GX_MISC_INDEX		0x06
+#	define NV_VIO_GX_DONT_CARE_INDEX	0x07
+#	define NV_VIO_GX_BIT_MASK_INDEX		0x08
+
+#define NV_PFB_BOOT_0			0x00100000
+#define NV_PFB_CFG0			0x00100200
+#define NV_PFB_CFG1			0x00100204
+#define NV_PFB_CSTATUS			0x0010020C
+#define NV_PFB_REFCTRL			0x00100210
+#	define NV_PFB_REFCTRL_VALID_1			(1 << 31)
+#define NV_PFB_PAD			0x0010021C
+#	define NV_PFB_PAD_CKE_NORMAL			(1 << 0)
+#define NV_PFB_TILE_NV10		0x00100240
+#define NV_PFB_TILE_SIZE_NV10		0x00100244
+#define NV_PFB_REF			0x001002D0
+#	define NV_PFB_REF_CMD_REFRESH			(1 << 0)
+#define NV_PFB_PRE			0x001002D4
+#	define NV_PFB_PRE_CMD_PRECHARGE			(1 << 0)
+#define NV_PFB_CLOSE_PAGE2		0x0010033C
+#define NV_PFB_TILE_NV40		0x00100600
+#define NV_PFB_TILE_SIZE_NV40		0x00100604
+
+#define NV_PEXTDEV_BOOT_0		0x00101000
+#	define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT	(8 << 12)
+#define NV_PEXTDEV_BOOT_3		0x0010100c
+
+#define NV_PCRTC_INTR_0					0x00600100
+#	define NV_PCRTC_INTR_0_VBLANK				(1 << 0)
+#define NV_PCRTC_INTR_EN_0				0x00600140
+#define NV_PCRTC_START					0x00600800
+#define NV_PCRTC_CONFIG					0x00600804
+#	define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA		(1 << 0)
+#	define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC		(2 << 0)
+#define NV_PCRTC_CURSOR_CONFIG				0x00600810
+#	define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE		(1 << 0)
+#	define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE	(1 << 4)
+#	define NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM	(1 << 8)
+#	define NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32		(1 << 12)
+#	define NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64		(1 << 16)
+#	define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_32		(2 << 24)
+#	define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64		(4 << 24)
+#	define NV_PCRTC_CURSOR_CONFIG_CUR_BLEND_ALPHA		(1 << 28)
+
+/* note: PCRTC_GPIO is not available on nv10, and in fact aliases 0x600810 */
+#define NV_PCRTC_GPIO					0x00600818
+#define NV_PCRTC_GPIO_EXT				0x0060081c
+#define NV_PCRTC_830					0x00600830
+#define NV_PCRTC_834					0x00600834
+#define NV_PCRTC_850					0x00600850
+#define NV_PCRTC_ENGINE_CTRL				0x00600860
+#	define NV_CRTC_FSEL_I2C					(1 << 4)
+#	define NV_CRTC_FSEL_OVERLAY				(1 << 12)
+
+#define NV_PRMCIO_ARX			0x006013c0
+#define NV_PRMCIO_AR__WRITE		0x006013c0
+#define NV_PRMCIO_AR__READ		0x006013c1
+#	define NV_CIO_AR_MODE_INDEX		0x10
+#	define NV_CIO_AR_OSCAN_INDEX		0x11
+#	define NV_CIO_AR_PLANE_INDEX		0x12
+#	define NV_CIO_AR_HPP_INDEX		0x13
+#	define NV_CIO_AR_CSEL_INDEX		0x14
+#define NV_PRMCIO_INP0			0x006013c2
+#define NV_PRMCIO_CRX__COLOR		0x006013d4
+#define NV_PRMCIO_CR__COLOR		0x006013d5
+	/* Standard VGA CRTC registers */
+#	define NV_CIO_CR_HDT_INDEX		0x00	/* horizontal display total */
+#	define NV_CIO_CR_HDE_INDEX		0x01	/* horizontal display end */
+#	define NV_CIO_CR_HBS_INDEX		0x02	/* horizontal blanking start */
+#	define NV_CIO_CR_HBE_INDEX		0x03	/* horizontal blanking end */
+#		define NV_CIO_CR_HBE_4_0		4:0
+#	define NV_CIO_CR_HRS_INDEX		0x04	/* horizontal retrace start */
+#	define NV_CIO_CR_HRE_INDEX		0x05	/* horizontal retrace end */
+#		define NV_CIO_CR_HRE_4_0		4:0
+#		define NV_CIO_CR_HRE_HBE_5		7:7
+#	define NV_CIO_CR_VDT_INDEX		0x06	/* vertical display total */
+#	define NV_CIO_CR_OVL_INDEX		0x07	/* overflow bits */
+#		define NV_CIO_CR_OVL_VDT_8		0:0
+#		define NV_CIO_CR_OVL_VDE_8		1:1
+#		define NV_CIO_CR_OVL_VRS_8		2:2
+#		define NV_CIO_CR_OVL_VBS_8		3:3
+#		define NV_CIO_CR_OVL_VDT_9		5:5
+#		define NV_CIO_CR_OVL_VDE_9		6:6
+#		define NV_CIO_CR_OVL_VRS_9		7:7
+#	define NV_CIO_CR_RSAL_INDEX		0x08	/* normally "preset row scan" */
+#	define NV_CIO_CR_CELL_HT_INDEX		0x09	/* cell height?! normally "max scan line" */
+#		define NV_CIO_CR_CELL_HT_VBS_9		5:5
+#		define NV_CIO_CR_CELL_HT_SCANDBL	7:7
+#	define NV_CIO_CR_CURS_ST_INDEX		0x0a	/* cursor start */
+#	define NV_CIO_CR_CURS_END_INDEX		0x0b	/* cursor end */
+#	define NV_CIO_CR_SA_HI_INDEX		0x0c	/* screen start address high */
+#	define NV_CIO_CR_SA_LO_INDEX		0x0d	/* screen start address low */
+#	define NV_CIO_CR_TCOFF_HI_INDEX		0x0e	/* cursor offset high */
+#	define NV_CIO_CR_TCOFF_LO_INDEX		0x0f	/* cursor offset low */
+#	define NV_CIO_CR_VRS_INDEX		0x10	/* vertical retrace start */
+#	define NV_CIO_CR_VRE_INDEX		0x11	/* vertical retrace end */
+#		define NV_CIO_CR_VRE_3_0		3:0
+#	define NV_CIO_CR_VDE_INDEX		0x12	/* vertical display end */
+#	define NV_CIO_CR_OFFSET_INDEX		0x13	/* sets screen pitch */
+#	define NV_CIO_CR_ULINE_INDEX		0x14	/* underline location */
+#	define NV_CIO_CR_VBS_INDEX		0x15	/* vertical blank start */
+#	define NV_CIO_CR_VBE_INDEX		0x16	/* vertical blank end */
+#	define NV_CIO_CR_MODE_INDEX		0x17	/* crtc mode control */
+#	define NV_CIO_CR_LCOMP_INDEX		0x18	/* line compare */
+	/* Extended VGA CRTC registers */
+#	define NV_CIO_CRE_RPC0_INDEX		0x19	/* repaint control 0 */
+#		define NV_CIO_CRE_RPC0_OFFSET_10_8	7:5
+#	define NV_CIO_CRE_RPC1_INDEX		0x1a	/* repaint control 1 */
+#		define NV_CIO_CRE_RPC1_LARGE		2:2
+#	define NV_CIO_CRE_FF_INDEX		0x1b	/* fifo control */
+#	define NV_CIO_CRE_ENH_INDEX		0x1c	/* enhanced? */
+#	define NV_CIO_SR_LOCK_INDEX		0x1f	/* crtc lock */
+#		define NV_CIO_SR_UNLOCK_RW_VALUE	0x57
+#		define NV_CIO_SR_LOCK_VALUE		0x99
+#	define NV_CIO_CRE_FFLWM__INDEX		0x20	/* fifo low water mark */
+#	define NV_CIO_CRE_21			0x21	/* vga shadow crtc lock */
+#	define NV_CIO_CRE_LSR_INDEX		0x25	/* ? */
+#		define NV_CIO_CRE_LSR_VDT_10		0:0
+#		define NV_CIO_CRE_LSR_VDE_10		1:1
+#		define NV_CIO_CRE_LSR_VRS_10		2:2
+#		define NV_CIO_CRE_LSR_VBS_10		3:3
+#		define NV_CIO_CRE_LSR_HBE_6		4:4
+#	define NV_CIO_CR_ARX_INDEX		0x26	/* attribute index -- ro copy of 0x60.3c0 */
+#	define NV_CIO_CRE_CHIP_ID_INDEX		0x27	/* chip revision */
+#	define NV_CIO_CRE_PIXEL_INDEX		0x28
+#		define NV_CIO_CRE_PIXEL_FORMAT		1:0
+#	define NV_CIO_CRE_HEB__INDEX		0x2d	/* horizontal extra bits? */
+#		define NV_CIO_CRE_HEB_HDT_8		0:0
+#		define NV_CIO_CRE_HEB_HDE_8		1:1
+#		define NV_CIO_CRE_HEB_HBS_8		2:2
+#		define NV_CIO_CRE_HEB_HRS_8		3:3
+#		define NV_CIO_CRE_HEB_ILC_8		4:4
+#	define NV_CIO_CRE_2E			0x2e	/* some scratch or dummy reg to force writes to sink in */
+#	define NV_CIO_CRE_HCUR_ADDR2_INDEX	0x2f	/* cursor */
+#	define NV_CIO_CRE_HCUR_ADDR0_INDEX	0x30		/* pixmap */
+#		define NV_CIO_CRE_HCUR_ADDR0_ADR	6:0
+#		define NV_CIO_CRE_HCUR_ASI		7:7
+#	define NV_CIO_CRE_HCUR_ADDR1_INDEX	0x31			/* address */
+#		define NV_CIO_CRE_HCUR_ADDR1_ENABLE	0:0
+#		define NV_CIO_CRE_HCUR_ADDR1_CUR_DBL	1:1
+#		define NV_CIO_CRE_HCUR_ADDR1_ADR	7:2
+#	define NV_CIO_CRE_LCD__INDEX		0x33
+#		define NV_CIO_CRE_LCD_LCD_SELECT	0:0
+#	define NV_CIO_CRE_DDC0_STATUS__INDEX	0x36
+#	define NV_CIO_CRE_DDC0_WR__INDEX	0x37
+#	define NV_CIO_CRE_ILACE__INDEX		0x39	/* interlace */
+#	define NV_CIO_CRE_SCRATCH3__INDEX	0x3b
+#	define NV_CIO_CRE_SCRATCH4__INDEX	0x3c
+#	define NV_CIO_CRE_DDC_STATUS__INDEX	0x3e
+#	define NV_CIO_CRE_DDC_WR__INDEX		0x3f
+#	define NV_CIO_CRE_EBR_INDEX		0x41	/* extra bits ? (vertical) */
+#		define NV_CIO_CRE_EBR_VDT_11		0:0
+#		define NV_CIO_CRE_EBR_VDE_11		2:2
+#		define NV_CIO_CRE_EBR_VRS_11		4:4
+#		define NV_CIO_CRE_EBR_VBS_11		6:6
+#	define NV_CIO_CRE_43			0x43
+#	define NV_CIO_CRE_44			0x44	/* head control */
+#	define NV_CIO_CRE_CSB			0x45	/* colour saturation boost */
+#	define NV_CIO_CRE_RCR			0x46
+#		define NV_CIO_CRE_RCR_ENDIAN_BIG	7:7
+#	define NV_CIO_CRE_47			0x47	/* extended fifo lwm, used on nv30+ */
+#	define NV_CIO_CRE_49			0x49
+#	define NV_CIO_CRE_4B			0x4b	/* given patterns in 0x[2-3][a-c] regs, probably scratch 6 */
+#	define NV_CIO_CRE_TVOUT_LATENCY		0x52
+#	define NV_CIO_CRE_53			0x53	/* `fp_htiming' according to Haiku */
+#	define NV_CIO_CRE_54			0x54	/* `fp_vtiming' according to Haiku */
+#	define NV_CIO_CRE_57			0x57	/* index reg for cr58 */
+#	define NV_CIO_CRE_58			0x58	/* data reg for cr57 */
+#	define NV_CIO_CRE_59			0x59	/* related to on/off-chip-ness of digital outputs */
+#	define NV_CIO_CRE_5B			0x5B	/* newer colour saturation reg */
+#	define NV_CIO_CRE_85			0x85
+#	define NV_CIO_CRE_86			0x86
+#define NV_PRMCIO_INP0__COLOR		0x006013da
+
+#define NV_PRAMDAC_CU_START_POS				0x00680300
+#	define NV_PRAMDAC_CU_START_POS_X			15:0
+#	define NV_PRAMDAC_CU_START_POS_Y			31:16
+#define NV_RAMDAC_NV10_CURSYNC				0x00680404
+
+#define NV_PRAMDAC_NVPLL_COEFF				0x00680500
+#define NV_PRAMDAC_MPLL_COEFF				0x00680504
+#define NV_PRAMDAC_VPLL_COEFF				0x00680508
+#	define NV30_RAMDAC_ENABLE_VCO2				(8 << 4)
+
+#define NV_PRAMDAC_PLL_COEFF_SELECT			0x0068050c
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE	(4 << 0)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL	(1 << 8)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL	(2 << 8)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL	(4 << 8)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_PLL_SOURCE_VPLL2	(8 << 8)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1		(1 << 16)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1		(2 << 16)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2		(4 << 16)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2		(8 << 16)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_TV_CLK_SOURCE_VIP	(1 << 20)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2	(1 << 28)
+#	define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK2_RATIO_DB2	(2 << 28)
+
+#define NV_PRAMDAC_PLL_SETUP_CONTROL			0x00680510
+#define NV_RAMDAC_VPLL2					0x00680520
+#define NV_PRAMDAC_SEL_CLK				0x00680524
+#define NV_RAMDAC_DITHER_NV11				0x00680528
+#define NV_PRAMDAC_DACCLK				0x0068052c
+#	define NV_PRAMDAC_DACCLK_SEL_DACCLK			(1 << 0)
+
+#define NV_RAMDAC_NVPLL_B				0x00680570
+#define NV_RAMDAC_MPLL_B				0x00680574
+#define NV_RAMDAC_VPLL_B				0x00680578
+#define NV_RAMDAC_VPLL2_B				0x0068057c
+#	define NV31_RAMDAC_ENABLE_VCO2				(8 << 28)
+#define NV_PRAMDAC_580					0x00680580
+#	define NV_RAMDAC_580_VPLL1_ACTIVE			(1 << 8)
+#	define NV_RAMDAC_580_VPLL2_ACTIVE			(1 << 28)
+
+#define NV_PRAMDAC_GENERAL_CONTROL			0x00680600
+#	define NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON		(3 << 4)
+#	define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL		(1 << 8)
+#	define NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL		(1 << 12)
+#	define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM	(2 << 16)
+#	define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS		(1 << 20)
+#	define NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG		(2 << 28)
+#define NV_PRAMDAC_TEST_CONTROL				0x00680608
+#	define NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED	(1 << 12)
+#	define NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF		(1 << 16)
+#	define NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI		(1 << 28)
+#define NV_PRAMDAC_TESTPOINT_DATA			0x00680610
+#	define NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK		(8 << 28)
+#define NV_PRAMDAC_630					0x00680630
+#define NV_PRAMDAC_634					0x00680634
+
+#define NV_PRAMDAC_TV_SETUP				0x00680700
+#define NV_PRAMDAC_TV_VTOTAL				0x00680720
+#define NV_PRAMDAC_TV_VSKEW				0x00680724
+#define NV_PRAMDAC_TV_VSYNC_DELAY			0x00680728
+#define NV_PRAMDAC_TV_HTOTAL				0x0068072c
+#define NV_PRAMDAC_TV_HSKEW				0x00680730
+#define NV_PRAMDAC_TV_HSYNC_DELAY			0x00680734
+#define NV_PRAMDAC_TV_HSYNC_DELAY2			0x00680738
+
+#define NV_PRAMDAC_TV_SETUP                             0x00680700
+
+#define NV_PRAMDAC_FP_VDISPLAY_END			0x00680800
+#define NV_PRAMDAC_FP_VTOTAL				0x00680804
+#define NV_PRAMDAC_FP_VCRTC				0x00680808
+#define NV_PRAMDAC_FP_VSYNC_START			0x0068080c
+#define NV_PRAMDAC_FP_VSYNC_END				0x00680810
+#define NV_PRAMDAC_FP_VVALID_START			0x00680814
+#define NV_PRAMDAC_FP_VVALID_END			0x00680818
+#define NV_PRAMDAC_FP_HDISPLAY_END			0x00680820
+#define NV_PRAMDAC_FP_HTOTAL				0x00680824
+#define NV_PRAMDAC_FP_HCRTC				0x00680828
+#define NV_PRAMDAC_FP_HSYNC_START			0x0068082c
+#define NV_PRAMDAC_FP_HSYNC_END				0x00680830
+#define NV_PRAMDAC_FP_HVALID_START			0x00680834
+#define NV_PRAMDAC_FP_HVALID_END			0x00680838
+
+#define NV_RAMDAC_FP_DITHER				0x0068083c
+#define NV_PRAMDAC_FP_TG_CONTROL			0x00680848
+#	define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS		(1 << 0)
+#	define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE		(2 << 0)
+#	define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS		(1 << 4)
+#	define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE		(2 << 4)
+#	define NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE		(0 << 8)
+#	define NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER		(1 << 8)
+#	define NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE		(2 << 8)
+#	define NV_PRAMDAC_FP_TG_CONTROL_READ_PROG		(1 << 20)
+#	define NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12		(1 << 24)
+#	define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS		(1 << 28)
+#	define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE		(2 << 28)
+#define NV_PRAMDAC_FP_MARGIN_COLOR			0x0068084c
+#define NV_PRAMDAC_850					0x00680850
+#define NV_PRAMDAC_85C					0x0068085c
+#define NV_PRAMDAC_FP_DEBUG_0				0x00680880
+#	define NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE		(1 << 0)
+#	define NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE		(1 << 4)
+/* This doesn't seem to be essential for tmds, but still often set */
+#	define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED		(8 << 4)
+#	define NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR		(1 << 8)
+#	define NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR		(1 << 12)
+#	define NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND		(1 << 20)
+#	define NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND		(1 << 24)
+#       define NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK              (1 << 28)
+#define NV_PRAMDAC_FP_DEBUG_1				0x00680884
+#	define NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE		11:0
+#	define NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE	(1 << 12)
+#	define NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE		27:16
+#	define NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE	(1 << 28)
+#define NV_PRAMDAC_FP_DEBUG_2				0x00680888
+#define NV_PRAMDAC_FP_DEBUG_3				0x0068088C
+
+/* see NV_PRAMDAC_INDIR_TMDS in rules.xml */
+#define NV_PRAMDAC_FP_TMDS_CONTROL			0x006808b0
+#	define NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE		(1 << 16)
+#define NV_PRAMDAC_FP_TMDS_DATA				0x006808b4
+
+#define NV_PRAMDAC_8C0                                  0x006808c0
+
+/* Some kind of switch */
+#define NV_PRAMDAC_900					0x00680900
+#define NV_PRAMDAC_A20					0x00680A20
+#define NV_PRAMDAC_A24					0x00680A24
+#define NV_PRAMDAC_A34					0x00680A34
+
+#define NV_PRAMDAC_CTV					0x00680c00
+
+/* names fabricated from NV_USER_DAC info */
+#define NV_PRMDIO_PIXEL_MASK		0x006813c6
+#	define NV_PRMDIO_PIXEL_MASK_MASK	0xff
+#define NV_PRMDIO_READ_MODE_ADDRESS	0x006813c7
+#define NV_PRMDIO_WRITE_MODE_ADDRESS	0x006813c8
+#define NV_PRMDIO_PALETTE_DATA		0x006813c9
+
+#define NV_PGRAPH_DEBUG_0		0x00400080
+#define NV_PGRAPH_DEBUG_1		0x00400084
+#define NV_PGRAPH_DEBUG_2_NV04		0x00400088
+#define NV_PGRAPH_DEBUG_2		0x00400620
+#define NV_PGRAPH_DEBUG_3		0x0040008c
+#define NV_PGRAPH_DEBUG_4		0x00400090
+#define NV_PGRAPH_INTR			0x00400100
+#define NV_PGRAPH_INTR_EN		0x00400140
+#define NV_PGRAPH_CTX_CONTROL		0x00400144
+#define NV_PGRAPH_CTX_CONTROL_NV04	0x00400170
+#define NV_PGRAPH_ABS_UCLIP_XMIN	0x0040053C
+#define NV_PGRAPH_ABS_UCLIP_YMIN	0x00400540
+#define NV_PGRAPH_ABS_UCLIP_XMAX	0x00400544
+#define NV_PGRAPH_ABS_UCLIP_YMAX	0x00400548
+#define NV_PGRAPH_BETA_AND		0x00400608
+#define NV_PGRAPH_LIMIT_VIOL_PIX	0x00400610
+#define NV_PGRAPH_BOFFSET0		0x00400640
+#define NV_PGRAPH_BOFFSET1		0x00400644
+#define NV_PGRAPH_BOFFSET2		0x00400648
+#define NV_PGRAPH_BLIMIT0		0x00400684
+#define NV_PGRAPH_BLIMIT1		0x00400688
+#define NV_PGRAPH_BLIMIT2		0x0040068c
+#define NV_PGRAPH_STATUS		0x00400700
+#define NV_PGRAPH_SURFACE		0x00400710
+#define NV_PGRAPH_STATE			0x00400714
+#define NV_PGRAPH_FIFO			0x00400720
+#define NV_PGRAPH_PATTERN_SHAPE		0x00400810
+#define NV_PGRAPH_TILE			0x00400b00
+
+#define NV_PVIDEO_INTR_EN		0x00008140
+#define NV_PVIDEO_BUFFER		0x00008700
+#define NV_PVIDEO_STOP			0x00008704
+#define NV_PVIDEO_UVPLANE_BASE(buff)	(0x00008800+(buff)*4)
+#define NV_PVIDEO_UVPLANE_LIMIT(buff)	(0x00008808+(buff)*4)
+#define NV_PVIDEO_UVPLANE_OFFSET_BUFF(buff)	(0x00008820+(buff)*4)
+#define NV_PVIDEO_BASE(buff)		(0x00008900+(buff)*4)
+#define NV_PVIDEO_LIMIT(buff)		(0x00008908+(buff)*4)
+#define NV_PVIDEO_LUMINANCE(buff)	(0x00008910+(buff)*4)
+#define NV_PVIDEO_CHROMINANCE(buff)	(0x00008918+(buff)*4)
+#define NV_PVIDEO_OFFSET_BUFF(buff)	(0x00008920+(buff)*4)
+#define NV_PVIDEO_SIZE_IN(buff)		(0x00008928+(buff)*4)
+#define NV_PVIDEO_POINT_IN(buff)	(0x00008930+(buff)*4)
+#define NV_PVIDEO_DS_DX(buff)		(0x00008938+(buff)*4)
+#define NV_PVIDEO_DT_DY(buff)		(0x00008940+(buff)*4)
+#define NV_PVIDEO_POINT_OUT(buff)	(0x00008948+(buff)*4)
+#define NV_PVIDEO_SIZE_OUT(buff)	(0x00008950+(buff)*4)
+#define NV_PVIDEO_FORMAT(buff)		(0x00008958+(buff)*4)
+#	define NV_PVIDEO_FORMAT_PLANAR			(1 << 0)
+#	define NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8	(1 << 16)
+#	define NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY	(1 << 20)
+#	define NV_PVIDEO_FORMAT_MATRIX_ITURBT709	(1 << 24)
+#define NV_PVIDEO_COLOR_KEY		0x00008B00
+
+/* NV04 overlay defines from VIDIX & Haiku */
+#define NV_PVIDEO_INTR_EN_0		0x00680140
+#define NV_PVIDEO_STEP_SIZE		0x00680200
+#define NV_PVIDEO_CONTROL_Y		0x00680204
+#define NV_PVIDEO_CONTROL_X		0x00680208
+#define NV_PVIDEO_BUFF0_START_ADDRESS	0x0068020c
+#define NV_PVIDEO_BUFF0_PITCH_LENGTH	0x00680214
+#define NV_PVIDEO_BUFF0_OFFSET		0x0068021c
+#define NV_PVIDEO_BUFF1_START_ADDRESS	0x00680210
+#define NV_PVIDEO_BUFF1_PITCH_LENGTH	0x00680218
+#define NV_PVIDEO_BUFF1_OFFSET		0x00680220
+#define NV_PVIDEO_OE_STATE		0x00680224
+#define NV_PVIDEO_SU_STATE		0x00680228
+#define NV_PVIDEO_RM_STATE		0x0068022c
+#define NV_PVIDEO_WINDOW_START		0x00680230
+#define NV_PVIDEO_WINDOW_SIZE		0x00680234
+#define NV_PVIDEO_FIFO_THRES_SIZE	0x00680238
+#define NV_PVIDEO_FIFO_BURST_LENGTH	0x0068023c
+#define NV_PVIDEO_KEY			0x00680240
+#define NV_PVIDEO_OVERLAY		0x00680244
+#define NV_PVIDEO_RED_CSC_OFFSET	0x00680280
+#define NV_PVIDEO_GREEN_CSC_OFFSET	0x00680284
+#define NV_PVIDEO_BLUE_CSC_OFFSET	0x00680288
+#define NV_PVIDEO_CSC_ADJUST		0x0068028c
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv10_fifo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv10_fifo.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE))
+#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
+
+int
+nv10_fifo_channel_id(struct drm_device *dev)
+{
+	return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
+			NV10_PFIFO_CACHE1_PUSH1_CHID_MASK;
+}
+
+int
+nv10_fifo_create_context(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct drm_device *dev = chan->dev;
+	uint32_t fc = NV10_RAMFC(chan->id);
+	int ret;
+
+	ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0,
+				      NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC |
+				      NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc);
+	if (ret)
+		return ret;
+
+	/* Fill entries that are seen filled in dumps of nvidia driver just
+	 * after channel's is put into DMA mode
+	 */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wi32(dev, fc +  0, chan->pushbuf_base);
+	nv_wi32(dev, fc +  4, chan->pushbuf_base);
+	nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
+	nv_wi32(dev, fc + 20, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+			      NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+			      NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+			      NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+			      0);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	/* enable the fifo dma operation */
+	nv_wr32(dev, NV04_PFIFO_MODE,
+		nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
+	return 0;
+}
+
+void
+nv10_fifo_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+
+	nv_wr32(dev, NV04_PFIFO_MODE,
+			nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
+
+	nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+static void
+nv10_fifo_do_load_context(struct drm_device *dev, int chid)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t fc = NV10_RAMFC(chid), tmp;
+
+	dev_priv->engine.instmem.prepare_access(dev, false);
+
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
+
+	tmp = nv_ri32(dev, fc + 12);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
+
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 16));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 20));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 24));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 28));
+
+	if (dev_priv->chipset < 0x17)
+		goto out;
+
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 32));
+	tmp = nv_ri32(dev, fc + 36);
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp);
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 40));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 44));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
+
+out:
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
+}
+
+int
+nv10_fifo_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	uint32_t tmp;
+
+	nv10_fifo_do_load_context(dev, chan->id);
+
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
+		     NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
+
+	/* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+	tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+	return 0;
+}
+
+int
+nv10_fifo_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	uint32_t fc, tmp;
+	int chid;
+
+	chid = pfifo->channel_id(dev);
+	if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
+		return 0;
+	fc = NV10_RAMFC(chid);
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+
+	nv_wi32(dev, fc +  0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
+	nv_wi32(dev, fc +  4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
+	nv_wi32(dev, fc +  8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
+	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF;
+	tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16);
+	nv_wi32(dev, fc + 12, tmp);
+	nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
+	nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
+	nv_wi32(dev, fc + 24, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
+	nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
+
+	if (dev_priv->chipset < 0x17)
+		goto out;
+
+	nv_wi32(dev, fc + 32, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+	tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
+	nv_wi32(dev, fc + 36, tmp);
+	nv_wi32(dev, fc + 40, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+	nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE));
+	nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
+
+out:
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv10_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
+	return 0;
+}
+
+static void
+nv10_fifo_init_reset(struct drm_device *dev)
+{
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) |  NV_PMC_ENABLE_PFIFO);
+
+	nv_wr32(dev, 0x003224, 0x000f0078);
+	nv_wr32(dev, 0x002044, 0x0101ffff);
+	nv_wr32(dev, 0x002040, 0x000000ff);
+	nv_wr32(dev, 0x002500, 0x00000000);
+	nv_wr32(dev, 0x003000, 0x00000000);
+	nv_wr32(dev, 0x003050, 0x00000000);
+
+	nv_wr32(dev, 0x003258, 0x00000000);
+	nv_wr32(dev, 0x003210, 0x00000000);
+	nv_wr32(dev, 0x003270, 0x00000000);
+}
+
+static void
+nv10_fifo_init_ramxx(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
+				       ((dev_priv->ramht_bits - 9) << 16) |
+				       (dev_priv->ramht_offset >> 8));
+	nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8);
+
+	if (dev_priv->chipset < 0x17) {
+		nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8);
+	} else {
+		nv_wr32(dev, NV03_PFIFO_RAMFC, (dev_priv->ramfc_offset >> 8) |
+					       (1 << 16) /* 64 Bytes entry*/);
+		/* XXX nvidia blob set bit 18, 21,23 for nv20 & nv30 */
+	}
+}
+
+static void
+nv10_fifo_init_intr(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x002100, 0xffffffff);
+	nv_wr32(dev, 0x002140, 0xffffffff);
+}
+
+int
+nv10_fifo_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	int i;
+
+	nv10_fifo_init_reset(dev);
+	nv10_fifo_init_ramxx(dev);
+
+	nv10_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
+
+	nv10_fifo_init_intr(dev);
+	pfifo->enable(dev);
+	pfifo->reassign(dev, true);
+
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		if (dev_priv->fifos[i]) {
+			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
+			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
+		}
+	}
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_fifo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE))
+#define NV04_RAMFC__SIZE 32
+#define NV04_RAMFC_DMA_PUT                                       0x00
+#define NV04_RAMFC_DMA_GET                                       0x04
+#define NV04_RAMFC_DMA_INSTANCE                                  0x08
+#define NV04_RAMFC_DMA_STATE                                     0x0C
+#define NV04_RAMFC_DMA_FETCH                                     0x10
+#define NV04_RAMFC_ENGINE                                        0x14
+#define NV04_RAMFC_PULL1_ENGINE                                  0x18
+
+#define RAMFC_WR(offset, val) nv_wo32(dev, chan->ramfc->gpuobj, \
+					 NV04_RAMFC_##offset/4, (val))
+#define RAMFC_RD(offset)      nv_ro32(dev, chan->ramfc->gpuobj, \
+					 NV04_RAMFC_##offset/4)
+
+void
+nv04_fifo_disable(struct drm_device *dev)
+{
+	uint32_t tmp;
+
+	tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, tmp & ~1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 0);
+	tmp = nv_rd32(dev, NV03_PFIFO_CACHE1_PULL1);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, tmp & ~1);
+}
+
+void
+nv04_fifo_enable(struct drm_device *dev)
+{
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, 1);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
+}
+
+bool
+nv04_fifo_reassign(struct drm_device *dev, bool enable)
+{
+	uint32_t reassign = nv_rd32(dev, NV03_PFIFO_CACHES);
+
+	nv_wr32(dev, NV03_PFIFO_CACHES, enable ? 1 : 0);
+	return (reassign == 1);
+}
+
+bool
+nv04_fifo_cache_flush(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	uint64_t start = ptimer->read(dev);
+
+	do {
+		if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) ==
+		    nv_rd32(dev, NV03_PFIFO_CACHE1_PUT))
+			return true;
+
+	} while (ptimer->read(dev) - start < 100000000);
+
+	NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n");
+
+	return false;
+}
+
+bool
+nv04_fifo_cache_pull(struct drm_device *dev, bool enable)
+{
+	uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0);
+
+	if (enable) {
+		nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1);
+	} else {
+		nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1);
+		nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
+	}
+
+	return !!(pull & 1);
+}
+
+int
+nv04_fifo_channel_id(struct drm_device *dev)
+{
+	return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
+			NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
+}
+
+int
+nv04_fifo_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int ret;
+
+	ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
+						NV04_RAMFC__SIZE,
+						NVOBJ_FLAG_ZERO_ALLOC |
+						NVOBJ_FLAG_ZERO_FREE,
+						NULL, &chan->ramfc);
+	if (ret)
+		return ret;
+
+	/* Setup initial state */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	RAMFC_WR(DMA_PUT, chan->pushbuf_base);
+	RAMFC_WR(DMA_GET, chan->pushbuf_base);
+	RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
+	RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+			     NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+			     NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+			     NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+			     0));
+	dev_priv->engine.instmem.finish_access(dev);
+
+	/* enable the fifo dma operation */
+	nv_wr32(dev, NV04_PFIFO_MODE,
+		nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
+	return 0;
+}
+
+void
+nv04_fifo_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+
+	nv_wr32(dev, NV04_PFIFO_MODE,
+		nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
+
+	nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+static void
+nv04_fifo_do_load_context(struct drm_device *dev, int chid)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t fc = NV04_RAMFC(chid), tmp;
+
+	dev_priv->engine.instmem.prepare_access(dev, false);
+
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
+	tmp = nv_ri32(dev, fc + 8);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 12));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, nv_ri32(dev, fc + 16));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
+
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
+}
+
+int
+nv04_fifo_load_context(struct nouveau_channel *chan)
+{
+	uint32_t tmp;
+
+	nv_wr32(chan->dev, NV03_PFIFO_CACHE1_PUSH1,
+			   NV03_PFIFO_CACHE1_PUSH1_DMA | chan->id);
+	nv04_fifo_do_load_context(chan->dev, chan->id);
+	nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
+
+	/* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+	tmp = nv_rd32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
+	nv_wr32(chan->dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+	return 0;
+}
+
+int
+nv04_fifo_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_channel *chan = NULL;
+	uint32_t tmp;
+	int chid;
+
+	chid = pfifo->channel_id(dev);
+	if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
+		return 0;
+
+	chan = dev_priv->fifos[chid];
+	if (!chan) {
+		NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
+		return -EINVAL;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
+	RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
+	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
+	tmp |= nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE);
+	RAMFC_WR(DMA_INSTANCE, tmp);
+	RAMFC_WR(DMA_STATE, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
+	RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
+	RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
+	RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv04_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
+	return 0;
+}
+
+static void
+nv04_fifo_init_reset(struct drm_device *dev)
+{
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) |  NV_PMC_ENABLE_PFIFO);
+
+	nv_wr32(dev, 0x003224, 0x000f0078);
+	nv_wr32(dev, 0x002044, 0x0101ffff);
+	nv_wr32(dev, 0x002040, 0x000000ff);
+	nv_wr32(dev, 0x002500, 0x00000000);
+	nv_wr32(dev, 0x003000, 0x00000000);
+	nv_wr32(dev, 0x003050, 0x00000000);
+	nv_wr32(dev, 0x003200, 0x00000000);
+	nv_wr32(dev, 0x003250, 0x00000000);
+	nv_wr32(dev, 0x003220, 0x00000000);
+
+	nv_wr32(dev, 0x003250, 0x00000000);
+	nv_wr32(dev, 0x003270, 0x00000000);
+	nv_wr32(dev, 0x003210, 0x00000000);
+}
+
+static void
+nv04_fifo_init_ramxx(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
+				       ((dev_priv->ramht_bits - 9) << 16) |
+				       (dev_priv->ramht_offset >> 8));
+	nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8);
+	nv_wr32(dev, NV03_PFIFO_RAMFC, dev_priv->ramfc_offset >> 8);
+}
+
+static void
+nv04_fifo_init_intr(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x002100, 0xffffffff);
+	nv_wr32(dev, 0x002140, 0xffffffff);
+}
+
+int
+nv04_fifo_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	int i;
+
+	nv04_fifo_init_reset(dev);
+	nv04_fifo_init_ramxx(dev);
+
+	nv04_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
+
+	nv04_fifo_init_intr(dev);
+	pfifo->enable(dev);
+
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		if (dev_priv->fifos[i]) {
+			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
+			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
+		}
+	}
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_dac.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_crtc_helper.h"
+
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nv50_display.h"
+
+static void
+nv50_dac_disconnect(struct nouveau_encoder *nv_encoder)
+{
+	struct drm_device *dev = to_drm_encoder(nv_encoder)->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);
+
+	ret = RING_SPACE(evo, 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while disconnecting DAC\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
+	OUT_RING(evo, 0);
+}
+
+static enum drm_connector_status
+nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	enum drm_connector_status status = connector_status_disconnected;
+	uint32_t dpms_state, load_pattern, load_state;
+	int or = nv_encoder->or;
+
+	nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
+	dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or));
+
+	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
+		0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
+	if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or),
+		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
+		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
+		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
+			  nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
+		return status;
+	}
+
+	/* Use bios provided value if possible. */
+	if (dev_priv->vbios->dactestval) {
+		load_pattern = dev_priv->vbios->dactestval;
+		NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
+			  load_pattern);
+	} else {
+		load_pattern = 340;
+		NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n",
+			 load_pattern);
+	}
+
+	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or),
+		NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern);
+	mdelay(45); /* give it some time to process */
+	load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or));
+
+	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0);
+	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state |
+		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
+
+	if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) ==
+			  NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT)
+		status = connector_status_connected;
+
+	if (status == connector_status_connected)
+		NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or);
+	else
+		NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or);
+
+	return status;
+}
+
+static void
+nv50_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	uint32_t val;
+	int or = nv_encoder->or;
+
+	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
+
+	/* wait for it to be done */
+	if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or),
+		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
+		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
+		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
+			 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
+		return;
+	}
+
+	val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F;
+
+	if (mode != DRM_MODE_DPMS_ON)
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_STANDBY:
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
+		break;
+	case DRM_MODE_DPMS_SUSPEND:
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
+		break;
+	case DRM_MODE_DPMS_OFF:
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF;
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
+		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
+		break;
+	default:
+		break;
+	}
+
+	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val |
+		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
+}
+
+static void
+nv50_dac_save(struct drm_encoder *encoder)
+{
+	NV_ERROR(encoder->dev, "!!\n");
+}
+
+static void
+nv50_dac_restore(struct drm_encoder *encoder)
+{
+	NV_ERROR(encoder->dev, "!!\n");
+}
+
+static bool
+nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *connector;
+
+	NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
+
+	connector = nouveau_encoder_connector_get(nv_encoder);
+	if (!connector) {
+		NV_ERROR(encoder->dev, "Encoder has no connector\n");
+		return false;
+	}
+
+	if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
+	     connector->native_mode) {
+		int id = adjusted_mode->base.id;
+		*adjusted_mode = *connector->native_mode;
+		adjusted_mode->base.id = id;
+	}
+
+	return true;
+}
+
+static void
+nv50_dac_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nv50_dac_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
+	uint32_t mode_ctl = 0, mode_ctl2 = 0;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or);
+
+	nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	if (crtc->index == 1)
+		mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1;
+	else
+		mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0;
+
+	/* Lacking a working tv-out, this is not a 100% sure. */
+	if (nv_encoder->dcb->type == OUTPUT_ANALOG)
+		mode_ctl |= 0x40;
+	else
+	if (nv_encoder->dcb->type == OUTPUT_TV)
+		mode_ctl |= 0x100;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+		mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+		mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC;
+
+	ret = RING_SPACE(evo, 3);
+	if (ret) {
+		NV_ERROR(dev, "no space while connecting DAC\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
+	OUT_RING(evo, mode_ctl);
+	OUT_RING(evo, mode_ctl2);
+}
+
+static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = {
+	.dpms = nv50_dac_dpms,
+	.save = nv50_dac_save,
+	.restore = nv50_dac_restore,
+	.mode_fixup = nv50_dac_mode_fixup,
+	.prepare = nv50_dac_prepare,
+	.commit = nv50_dac_commit,
+	.mode_set = nv50_dac_mode_set,
+	.detect = nv50_dac_detect
+};
+
+static void
+nv50_dac_destroy(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	if (!encoder)
+		return;
+
+	NV_DEBUG_KMS(encoder->dev, "\n");
+
+	drm_encoder_cleanup(encoder);
+	kfree(nv_encoder);
+}
+
+static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
+	.destroy = nv50_dac_destroy,
+};
+
+int
+nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+
+	NV_DEBUG_KMS(dev, "\n");
+	NV_INFO(dev, "Detected a DAC output\n");
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	encoder = to_drm_encoder(nv_encoder);
+
+	nv_encoder->dcb = entry;
+	nv_encoder->or = ffs(entry->or) - 1;
+
+	nv_encoder->disconnect = nv50_dac_disconnect;
+
+	drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs,
+			 DRM_MODE_ENCODER_DAC);
+	drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2007-2008 Nouveau Project
+ *
+ * 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 (including the next
+ * paragraph) 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 __NOUVEAU_BIOS_H__
+#define __NOUVEAU_BIOS_H__
+
+#include "nvreg.h"
+#include "nouveau_i2c.h"
+
+#define DCB_MAX_NUM_ENTRIES 16
+#define DCB_MAX_NUM_I2C_ENTRIES 16
+#define DCB_MAX_NUM_GPIO_ENTRIES 32
+#define DCB_MAX_NUM_CONNECTOR_ENTRIES 16
+
+#define DCB_LOC_ON_CHIP 0
+
+struct dcb_entry {
+	int index;	/* may not be raw dcb index if merging has happened */
+	uint8_t type;
+	uint8_t i2c_index;
+	uint8_t heads;
+	uint8_t connector;
+	uint8_t bus;
+	uint8_t location;
+	uint8_t or;
+	bool duallink_possible;
+	union {
+		struct sor_conf {
+			int link;
+		} sorconf;
+		struct {
+			int maxfreq;
+		} crtconf;
+		struct {
+			struct sor_conf sor;
+			bool use_straps_for_mode;
+			bool use_power_scripts;
+		} lvdsconf;
+		struct {
+			bool has_component_output;
+		} tvconf;
+		struct {
+			struct sor_conf sor;
+			int link_nr;
+			int link_bw;
+		} dpconf;
+		struct {
+			struct sor_conf sor;
+		} tmdsconf;
+	};
+	bool i2c_upper_default;
+};
+
+struct dcb_i2c_entry {
+	uint8_t port_type;
+	uint8_t read, write;
+	struct nouveau_i2c_chan *chan;
+};
+
+struct parsed_dcb {
+	int entries;
+	struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
+	struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
+};
+
+enum dcb_gpio_tag {
+	DCB_GPIO_TVDAC0 = 0xc,
+	DCB_GPIO_TVDAC1 = 0x2d,
+};
+
+struct dcb_gpio_entry {
+	enum dcb_gpio_tag tag;
+	int line;
+	bool invert;
+};
+
+struct parsed_dcb_gpio {
+	int entries;
+	struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
+};
+
+struct dcb_connector_table_entry {
+	uint32_t entry;
+	uint8_t type;
+	uint8_t index;
+	uint8_t gpio_tag;
+};
+
+struct dcb_connector_table {
+	int entries;
+	struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
+};
+
+struct bios_parsed_dcb {
+	uint8_t version;
+
+	struct parsed_dcb dcb;
+
+	uint8_t *i2c_table;
+	uint8_t i2c_default_indices;
+
+	uint16_t gpio_table_ptr;
+	struct parsed_dcb_gpio gpio;
+	uint16_t connector_table_ptr;
+	struct dcb_connector_table connector;
+};
+
+enum nouveau_encoder_type {
+	OUTPUT_ANALOG = 0,
+	OUTPUT_TV = 1,
+	OUTPUT_TMDS = 2,
+	OUTPUT_LVDS = 3,
+	OUTPUT_DP = 6,
+	OUTPUT_ANY = -1
+};
+
+enum nouveau_or {
+	OUTPUT_A = (1 << 0),
+	OUTPUT_B = (1 << 1),
+	OUTPUT_C = (1 << 2)
+};
+
+enum LVDS_script {
+	/* Order *does* matter here */
+	LVDS_INIT = 1,
+	LVDS_RESET,
+	LVDS_BACKLIGHT_ON,
+	LVDS_BACKLIGHT_OFF,
+	LVDS_PANEL_ON,
+	LVDS_PANEL_OFF
+};
+
+/* changing these requires matching changes to reg tables in nv_get_clock */
+#define MAX_PLL_TYPES	4
+enum pll_types {
+	NVPLL,
+	MPLL,
+	VPLL1,
+	VPLL2
+};
+
+struct pll_lims {
+	struct {
+		int minfreq;
+		int maxfreq;
+		int min_inputfreq;
+		int max_inputfreq;
+
+		uint8_t min_m;
+		uint8_t max_m;
+		uint8_t min_n;
+		uint8_t max_n;
+	} vco1, vco2;
+
+	uint8_t max_log2p;
+	/*
+	 * for most pre nv50 cards setting a log2P of 7 (the common max_log2p
+	 * value) is no different to 6 (at least for vplls) so allowing the MNP
+	 * calc to use 7 causes the generated clock to be out by a factor of 2.
+	 * however, max_log2p cannot be fixed-up during parsing as the
+	 * unmodified max_log2p value is still needed for setting mplls, hence
+	 * an additional max_usable_log2p member
+	 */
+	uint8_t max_usable_log2p;
+	uint8_t log2p_bias;
+
+	uint8_t min_p;
+	uint8_t max_p;
+
+	int refclk;
+};
+
+struct nouveau_bios_info {
+	struct parsed_dcb *dcb;
+
+	uint8_t chip_version;
+
+	uint32_t dactestval;
+	uint32_t tvdactestval;
+	uint8_t digital_min_front_porch;
+	bool fp_no_ddc;
+};
+
+struct nvbios {
+	struct drm_device *dev;
+	struct nouveau_bios_info pub;
+
+	struct mutex lock;
+
+	uint8_t data[NV_PROM_SIZE];
+	unsigned int length;
+	bool execute;
+
+	uint8_t major_version;
+	uint8_t feature_byte;
+	bool is_mobile;
+
+	uint32_t fmaxvco, fminvco;
+
+	bool old_style_init;
+	uint16_t init_script_tbls_ptr;
+	uint16_t extra_init_script_tbl_ptr;
+	uint16_t macro_index_tbl_ptr;
+	uint16_t macro_tbl_ptr;
+	uint16_t condition_tbl_ptr;
+	uint16_t io_condition_tbl_ptr;
+	uint16_t io_flag_condition_tbl_ptr;
+	uint16_t init_function_tbl_ptr;
+
+	uint16_t pll_limit_tbl_ptr;
+	uint16_t ram_restrict_tbl_ptr;
+	uint8_t ram_restrict_group_count;
+
+	uint16_t some_script_ptr; /* BIT I + 14 */
+	uint16_t init96_tbl_ptr; /* BIT I + 16 */
+
+	struct bios_parsed_dcb bdcb;
+
+	struct {
+		int crtchead;
+		/* these need remembering across suspend */
+		uint32_t saved_nv_pfb_cfg0;
+	} state;
+
+	struct {
+		struct dcb_entry *output;
+		uint16_t script_table_ptr;
+		uint16_t dp_table_ptr;
+	} display;
+
+	struct {
+		uint16_t fptablepointer;	/* also used by tmds */
+		uint16_t fpxlatetableptr;
+		int xlatwidth;
+		uint16_t lvdsmanufacturerpointer;
+		uint16_t fpxlatemanufacturertableptr;
+		uint16_t mode_ptr;
+		uint16_t xlated_entry;
+		bool power_off_for_reset;
+		bool reset_after_pclk_change;
+		bool dual_link;
+		bool link_c_increment;
+		bool BITbit1;
+		bool if_is_24bit;
+		int duallink_transition_clk;
+		uint8_t strapless_is_24bit;
+		uint8_t *edid;
+
+		/* will need resetting after suspend */
+		int last_script_invoc;
+		bool lvds_init_run;
+	} fp;
+
+	struct {
+		uint16_t output0_script_ptr;
+		uint16_t output1_script_ptr;
+	} tmds;
+
+	struct {
+		uint16_t mem_init_tbl_ptr;
+		uint16_t sdr_seq_tbl_ptr;
+		uint16_t ddr_seq_tbl_ptr;
+
+		struct {
+			uint8_t crt, tv, panel;
+		} i2c_indices;
+
+		uint16_t lvds_single_a_script_ptr;
+	} legacy;
+};
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv17_gpio.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv17_gpio.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+
+static bool
+get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
+		  uint32_t *mask)
+{
+	if (ent->line < 2) {
+		*reg = NV_PCRTC_GPIO;
+		*shift = ent->line * 16;
+		*mask = 0x11;
+
+	} else if (ent->line < 10) {
+		*reg = NV_PCRTC_GPIO_EXT;
+		*shift = (ent->line - 2) * 4;
+		*mask = 0x3;
+
+	} else if (ent->line < 14) {
+		*reg = NV_PCRTC_850;
+		*shift = (ent->line - 10) * 4;
+		*mask = 0x3;
+
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+int
+nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
+{
+	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
+	uint32_t reg, shift, mask, value;
+
+	if (!ent)
+		return -ENODEV;
+
+	if (!get_gpio_location(ent, &reg, &shift, &mask))
+		return -ENODEV;
+
+	value = NVReadCRTC(dev, 0, reg) >> shift;
+
+	return (ent->invert ? 1 : 0) ^ (value & 1);
+}
+
+int
+nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
+{
+	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
+	uint32_t reg, shift, mask, value;
+
+	if (!ent)
+		return -ENODEV;
+
+	if (!get_gpio_location(ent, &reg, &shift, &mask))
+		return -ENODEV;
+
+	value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift;
+	mask = ~(mask << shift);
+
+	NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask));
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/Makefile
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
+             nouveau_object.o nouveau_irq.o nouveau_notifier.o \
+             nouveau_sgdma.o nouveau_dma.o \
+             nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
+             nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
+             nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
+             nouveau_dp.o nouveau_grctx.o \
+             nv04_timer.o \
+             nv04_mc.o nv40_mc.o nv50_mc.o \
+             nv04_fb.o nv10_fb.o nv40_fb.o \
+             nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
+             nv04_graph.o nv10_graph.o nv20_graph.o \
+             nv40_graph.o nv50_graph.o \
+             nv40_grctx.o nv50_grctx.o \
+             nv04_instmem.o nv50_instmem.o \
+             nv50_crtc.o nv50_dac.o nv50_sor.o \
+             nv50_cursor.o nv50_display.o nv50_fbcon.o \
+             nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
+             nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
+             nv17_gpio.o
+
+nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
+nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
+nouveau-$(CONFIG_ACPI) += nouveau_acpi.o
+
+obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_dac.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_dac.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2003 NVIDIA, Corporation
+ * Copyright 2006 Dave Airlie
+ * Copyright 2007 Maarten Maathuis
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * 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 (including the next
+ * paragraph) 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 "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+#include "nvreg.h"
+
+int nv04_dac_output_offset(struct drm_encoder *encoder)
+{
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+	int offset = 0;
+
+	if (dcb->or & (8 | OUTPUT_C))
+		offset += 0x68;
+	if (dcb->or & (8 | OUTPUT_B))
+		offset += 0x2000;
+
+	return offset;
+}
+
+/*
+ * arbitrary limit to number of sense oscillations tolerated in one sample
+ * period (observed to be at least 13 in "nvidia")
+ */
+#define MAX_HBLANK_OSC 20
+
+/*
+ * arbitrary limit to number of conflicting sample pairs to tolerate at a
+ * voltage step (observed to be at least 5 in "nvidia")
+ */
+#define MAX_SAMPLE_PAIRS 10
+
+static int sample_load_twice(struct drm_device *dev, bool sense[2])
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		bool sense_a, sense_b, sense_b_prime;
+		int j = 0;
+
+		/*
+		 * wait for bit 0 clear -- out of hblank -- (say reg value 0x4),
+		 * then wait for transition 0x4->0x5->0x4: enter hblank, leave
+		 * hblank again
+		 * use a 10ms timeout (guards against crtc being inactive, in
+		 * which case blank state would never change)
+		 */
+		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+					0x00000001, 0x00000000))
+			return -EBUSY;
+		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+					0x00000001, 0x00000001))
+			return -EBUSY;
+		if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR,
+					0x00000001, 0x00000000))
+			return -EBUSY;
+
+		udelay(100);
+		/* when level triggers, sense is _LO_ */
+		sense_a = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
+
+		/* take another reading until it agrees with sense_a... */
+		do {
+			udelay(100);
+			sense_b = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
+			if (sense_a != sense_b) {
+				sense_b_prime =
+					nv_rd08(dev, NV_PRMCIO_INP0) & 0x10;
+				if (sense_b == sense_b_prime) {
+					/* ... unless two consecutive subsequent
+					 * samples agree; sense_a is replaced */
+					sense_a = sense_b;
+					/* force mis-match so we loop */
+					sense_b = !sense_a;
+				}
+			}
+		} while ((sense_a != sense_b) && ++j < MAX_HBLANK_OSC);
+
+		if (j == MAX_HBLANK_OSC)
+			/* with so much oscillation, default to sense:LO */
+			sense[i] = false;
+		else
+			sense[i] = sense_a;
+	}
+
+	return 0;
+}
+
+static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder,
+						 struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode;
+	uint8_t saved_palette0[3], saved_palette_mask;
+	uint32_t saved_rtest_ctrl, saved_rgen_ctrl;
+	int i;
+	uint8_t blue;
+	bool sense = true;
+
+	/*
+	 * for this detection to work, there needs to be a mode set up on the
+	 * CRTC.  this is presumed to be the case
+	 */
+
+	if (nv_two_heads(dev))
+		/* only implemented for head A for now */
+		NVSetOwner(dev, 0);
+
+	saved_cr_mode = NVReadVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode | 0x80);
+
+	saved_seq1 = NVReadVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX);
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20);
+
+	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL,
+		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
+
+	msleep(10);
+
+	saved_pi = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX,
+		       saved_pi & ~(0x80 | MASK(NV_CIO_CRE_PIXEL_FORMAT)));
+	saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0);
+
+	nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
+	for (i = 0; i < 3; i++)
+		saved_palette0[i] = nv_rd08(dev, NV_PRMDIO_PALETTE_DATA);
+	saved_palette_mask = nv_rd08(dev, NV_PRMDIO_PIXEL_MASK);
+	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, 0);
+
+	saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL,
+		      (saved_rgen_ctrl & ~(NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
+					   NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM)) |
+		      NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON);
+
+	blue = 8;	/* start of test range */
+
+	do {
+		bool sense_pair[2];
+
+		nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0);
+		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0);
+		/* testing blue won't find monochrome monitors.  I don't care */
+		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, blue);
+
+		i = 0;
+		/* take sample pairs until both samples in the pair agree */
+		do {
+			if (sample_load_twice(dev, sense_pair))
+				goto out;
+		} while ((sense_pair[0] != sense_pair[1]) &&
+							++i < MAX_SAMPLE_PAIRS);
+
+		if (i == MAX_SAMPLE_PAIRS)
+			/* too much oscillation defaults to LO */
+			sense = false;
+		else
+			sense = sense_pair[0];
+
+	/*
+	 * if sense goes LO before blue ramps to 0x18, monitor is not connected.
+	 * ergo, if blue gets to 0x18, monitor must be connected
+	 */
+	} while (++blue < 0x18 && sense);
+
+out:
+	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl);
+	nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
+	for (i = 0; i < 3; i++)
+		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1);
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1);
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
+
+	if (blue == 0x18) {
+		NV_INFO(dev, "Load detected on head A\n");
+		return connector_status_connected;
+	}
+
+	return connector_status_disconnected;
+}
+
+uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
+	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
+		saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput;
+	int head;
+
+#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
+	if (dcb->type == OUTPUT_TV) {
+		testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0);
+
+		if (dev_priv->vbios->tvdactestval)
+			testval = dev_priv->vbios->tvdactestval;
+	} else {
+		testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
+
+		if (dev_priv->vbios->dactestval)
+			testval = dev_priv->vbios->dactestval;
+	}
+
+	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
+		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
+
+	saved_powerctrl_2 = nvReadMC(dev, NV_PBUS_POWERCTRL_2);
+
+	nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
+	if (regoffset == 0x68) {
+		saved_powerctrl_4 = nvReadMC(dev, NV_PBUS_POWERCTRL_4);
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
+	}
+
+	saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
+	saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
+
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
+
+	msleep(4);
+
+	saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
+	head = (saved_routput & 0x100) >> 8;
+#if 0
+	/* if there's a spare crtc, using it will minimise flicker for the case
+	 * where the in-use crtc is in use by an off-chip tmds encoder */
+	if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled)
+		head ^= 1;
+#endif
+	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
+	routput = (saved_routput & 0xfffffece) | head << 8;
+
+	if (dev_priv->card_type >= NV_40) {
+		if (dcb->type == OUTPUT_TV)
+			routput |= 0x1a << 16;
+		else
+			routput &= ~(0x1a << 16);
+	}
+
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, routput);
+	msleep(1);
+
+	temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA,
+		      NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK | testval);
+	temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
+		      temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
+	msleep(5);
+
+	sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
+
+	temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL,
+		      temp & ~NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TESTPOINT_DATA, 0);
+
+	/* bios does something more complex for restoring, but I think this is good enough */
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
+	if (regoffset == 0x68)
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
+	nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
+
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
+
+	return sample;
+}
+
+static enum drm_connector_status
+nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+	uint32_t sample = nv17_dac_sample_load(encoder);
+
+	if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
+		NV_INFO(dev, "Load detected on output %c\n",
+			'@' + ffs(dcb->or));
+		return connector_status_connected;
+	} else {
+		return connector_status_disconnected;
+	}
+}
+
+static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void nv04_dac_prepare(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int head = nouveau_crtc(encoder->crtc)->index;
+	struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg;
+
+	helper->dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	nv04_dfp_disable(dev, head);
+
+	/* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f)
+	 * at LCD__INDEX which we don't alter
+	 */
+	if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44))
+		crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
+}
+
+
+static void nv04_dac_mode_set(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode,
+			      struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int head = nouveau_crtc(encoder->crtc)->index;
+
+	if (nv_gf4_disp_arch(dev)) {
+		struct drm_encoder *rebind;
+		uint32_t dac_offset = nv04_dac_output_offset(encoder);
+		uint32_t otherdac;
+
+		/* bit 16-19 are bits that are set on some G70 cards,
+		 * but don't seem to have much effect */
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset,
+			      head << 8 | NV_PRAMDAC_DACCLK_SEL_DACCLK);
+		/* force any other vga encoders to bind to the other crtc */
+		list_for_each_entry(rebind, &dev->mode_config.encoder_list, head) {
+			if (rebind == encoder
+			    || nouveau_encoder(rebind)->dcb->type != OUTPUT_ANALOG)
+				continue;
+
+			dac_offset = nv04_dac_output_offset(rebind);
+			otherdac = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset);
+			NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + dac_offset,
+				      (otherdac & ~0x0100) | (head ^ 1) << 8);
+		}
+	}
+
+	/* This could use refinement for flatpanels, but it should work this way */
+	if (dev_priv->chipset < 0x44)
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
+	else
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
+}
+
+static void nv04_dac_commit(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+
+	helper->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+}
+
+void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+
+	if (nv_gf4_disp_arch(dev)) {
+		uint32_t *dac_users = &dev_priv->dac_users[ffs(dcb->or) - 1];
+		int dacclk_off = NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder);
+		uint32_t dacclk = NVReadRAMDAC(dev, 0, dacclk_off);
+
+		if (enable) {
+			*dac_users |= 1 << dcb->index;
+			NVWriteRAMDAC(dev, 0, dacclk_off, dacclk | NV_PRAMDAC_DACCLK_SEL_DACCLK);
+
+		} else {
+			*dac_users &= ~(1 << dcb->index);
+			if (!*dac_users)
+				NVWriteRAMDAC(dev, 0, dacclk_off,
+					dacclk & ~NV_PRAMDAC_DACCLK_SEL_DACCLK);
+		}
+	}
+}
+
+static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	if (nv_encoder->last_dpms == mode)
+		return;
+	nv_encoder->last_dpms = mode;
+
+	NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n",
+		     mode, nv_encoder->dcb->index);
+
+	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
+}
+
+static void nv04_dac_save(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+
+	if (nv_gf4_disp_arch(dev))
+		nv_encoder->restore.output = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK +
+							  nv04_dac_output_offset(encoder));
+}
+
+static void nv04_dac_restore(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+
+	if (nv_gf4_disp_arch(dev))
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + nv04_dac_output_offset(encoder),
+			      nv_encoder->restore.output);
+
+	nv_encoder->last_dpms = NV_DPMS_CLEARED;
+}
+
+static void nv04_dac_destroy(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	NV_DEBUG_KMS(encoder->dev, "\n");
+
+	drm_encoder_cleanup(encoder);
+	kfree(nv_encoder);
+}
+
+static const struct drm_encoder_helper_funcs nv04_dac_helper_funcs = {
+	.dpms = nv04_dac_dpms,
+	.save = nv04_dac_save,
+	.restore = nv04_dac_restore,
+	.mode_fixup = nv04_dac_mode_fixup,
+	.prepare = nv04_dac_prepare,
+	.commit = nv04_dac_commit,
+	.mode_set = nv04_dac_mode_set,
+	.detect = nv04_dac_detect
+};
+
+static const struct drm_encoder_helper_funcs nv17_dac_helper_funcs = {
+	.dpms = nv04_dac_dpms,
+	.save = nv04_dac_save,
+	.restore = nv04_dac_restore,
+	.mode_fixup = nv04_dac_mode_fixup,
+	.prepare = nv04_dac_prepare,
+	.commit = nv04_dac_commit,
+	.mode_set = nv04_dac_mode_set,
+	.detect = nv17_dac_detect
+};
+
+static const struct drm_encoder_funcs nv04_dac_funcs = {
+	.destroy = nv04_dac_destroy,
+};
+
+int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	const struct drm_encoder_helper_funcs *helper;
+	struct drm_encoder *encoder;
+	struct nouveau_encoder *nv_encoder = NULL;
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+
+	encoder = to_drm_encoder(nv_encoder);
+
+	nv_encoder->dcb = entry;
+	nv_encoder->or = ffs(entry->or) - 1;
+
+	if (nv_gf4_disp_arch(dev))
+		helper = &nv17_dac_helper_funcs;
+	else
+		helper = &nv04_dac_helper_funcs;
+
+	drm_encoder_init(dev, encoder, &nv04_dac_funcs, DRM_MODE_ENCODER_DAC);
+	drm_encoder_helper_add(encoder, helper);
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_FBCON_H__
+#define __NOUVEAU_FBCON_H__
+
+#include "drm_fb_helper.h"
+
+struct nouveau_fbcon_par {
+	struct drm_fb_helper helper;
+	struct drm_device *dev;
+	struct nouveau_framebuffer *nouveau_fb;
+};
+
+int nouveau_fbcon_probe(struct drm_device *dev);
+int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb);
+void nouveau_fbcon_restore(void);
+void nouveau_fbcon_zfill(struct drm_device *dev);
+
+void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
+void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
+int nv04_fbcon_accel_init(struct fb_info *info);
+void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
+void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
+int nv50_fbcon_accel_init(struct fb_info *info);
+
+void nouveau_fbcon_gpu_lockup(struct fb_info *info);
+#endif /* __NV50_FBCON_H__ */
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+#define USE_REFCNT (dev_priv->card_type >= NV_10)
+
+struct nouveau_fence {
+	struct nouveau_channel *channel;
+	struct kref refcount;
+	struct list_head entry;
+
+	uint32_t sequence;
+	bool signalled;
+};
+
+static inline struct nouveau_fence *
+nouveau_fence(void *sync_obj)
+{
+	return (struct nouveau_fence *)sync_obj;
+}
+
+static void
+nouveau_fence_del(struct kref *ref)
+{
+	struct nouveau_fence *fence =
+		container_of(ref, struct nouveau_fence, refcount);
+
+	kfree(fence);
+}
+
+void
+nouveau_fence_update(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct list_head *entry, *tmp;
+	struct nouveau_fence *fence;
+	uint32_t sequence;
+
+	if (USE_REFCNT)
+		sequence = nvchan_rd32(chan, 0x48);
+	else
+		sequence = chan->fence.last_sequence_irq;
+
+	if (chan->fence.sequence_ack == sequence)
+		return;
+	chan->fence.sequence_ack = sequence;
+
+	list_for_each_safe(entry, tmp, &chan->fence.pending) {
+		fence = list_entry(entry, struct nouveau_fence, entry);
+
+		sequence = fence->sequence;
+		fence->signalled = true;
+		list_del(&fence->entry);
+		kref_put(&fence->refcount, nouveau_fence_del);
+
+		if (sequence == chan->fence.sequence_ack)
+			break;
+	}
+}
+
+int
+nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence,
+		  bool emit)
+{
+	struct nouveau_fence *fence;
+	int ret = 0;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		return -ENOMEM;
+	kref_init(&fence->refcount);
+	fence->channel = chan;
+
+	if (emit)
+		ret = nouveau_fence_emit(fence);
+
+	if (ret)
+		nouveau_fence_unref((void *)&fence);
+	*pfence = fence;
+	return ret;
+}
+
+struct nouveau_channel *
+nouveau_fence_channel(struct nouveau_fence *fence)
+{
+	return fence ? fence->channel : NULL;
+}
+
+int
+nouveau_fence_emit(struct nouveau_fence *fence)
+{
+	struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private;
+	struct nouveau_channel *chan = fence->channel;
+	unsigned long flags;
+	int ret;
+
+	ret = RING_SPACE(chan, 2);
+	if (ret)
+		return ret;
+
+	if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) {
+		spin_lock_irqsave(&chan->fence.lock, flags);
+		nouveau_fence_update(chan);
+		spin_unlock_irqrestore(&chan->fence.lock, flags);
+
+		BUG_ON(chan->fence.sequence ==
+		       chan->fence.sequence_ack - 1);
+	}
+
+	fence->sequence = ++chan->fence.sequence;
+
+	kref_get(&fence->refcount);
+	spin_lock_irqsave(&chan->fence.lock, flags);
+	list_add_tail(&fence->entry, &chan->fence.pending);
+	spin_unlock_irqrestore(&chan->fence.lock, flags);
+
+	BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
+	OUT_RING(chan, fence->sequence);
+	FIRE_RING(chan);
+
+	return 0;
+}
+
+void
+nouveau_fence_unref(void **sync_obj)
+{
+	struct nouveau_fence *fence = nouveau_fence(*sync_obj);
+
+	if (fence)
+		kref_put(&fence->refcount, nouveau_fence_del);
+	*sync_obj = NULL;
+}
+
+void *
+nouveau_fence_ref(void *sync_obj)
+{
+	struct nouveau_fence *fence = nouveau_fence(sync_obj);
+
+	kref_get(&fence->refcount);
+	return sync_obj;
+}
+
+bool
+nouveau_fence_signalled(void *sync_obj, void *sync_arg)
+{
+	struct nouveau_fence *fence = nouveau_fence(sync_obj);
+	struct nouveau_channel *chan = fence->channel;
+	unsigned long flags;
+
+	if (fence->signalled)
+		return true;
+
+	spin_lock_irqsave(&chan->fence.lock, flags);
+	nouveau_fence_update(chan);
+	spin_unlock_irqrestore(&chan->fence.lock, flags);
+	return fence->signalled;
+}
+
+int
+nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
+{
+	unsigned long timeout = jiffies + (3 * DRM_HZ);
+	int ret = 0;
+
+	__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+
+	while (1) {
+		if (nouveau_fence_signalled(sync_obj, sync_arg))
+			break;
+
+		if (time_after_eq(jiffies, timeout)) {
+			ret = -EBUSY;
+			break;
+		}
+
+		if (lazy)
+			schedule_timeout(1);
+
+		if (intr && signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+	}
+
+	__set_current_state(TASK_RUNNING);
+
+	return ret;
+}
+
+int
+nouveau_fence_flush(void *sync_obj, void *sync_arg)
+{
+	return 0;
+}
+
+void
+nouveau_fence_handler(struct drm_device *dev, int channel)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = NULL;
+
+	if (channel >= 0 && channel < dev_priv->engine.fifo.channels)
+		chan = dev_priv->fifos[channel];
+
+	if (chan) {
+		spin_lock_irq(&chan->fence.lock);
+		nouveau_fence_update(chan);
+		spin_unlock_irq(&chan->fence.lock);
+	}
+}
+
+int
+nouveau_fence_init(struct nouveau_channel *chan)
+{
+	INIT_LIST_HEAD(&chan->fence.pending);
+	spin_lock_init(&chan->fence.lock);
+	return 0;
+}
+
+void
+nouveau_fence_fini(struct nouveau_channel *chan)
+{
+	struct list_head *entry, *tmp;
+	struct nouveau_fence *fence;
+
+	list_for_each_safe(entry, tmp, &chan->fence.pending) {
+		fence = list_entry(entry, struct nouveau_fence, entry);
+
+		fence->signalled = true;
+		list_del(&fence->entry);
+		kref_put(&fence->refcount, nouveau_fence_del);
+	}
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_ioc32.c
@@ -0,0 +1,70 @@
+/**
+ * \file mga_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the MGA DRM.
+ *
+ * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Egbert Eich 2003,2004
+ * Copyright (C) Dave Airlie 2005
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHOR 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/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+
+#include "nouveau_drv.h"
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
+			 unsigned long arg)
+{
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	drm_ioctl_compat_t *fn = NULL;
+	int ret;
+
+	if (nr < DRM_COMMAND_BASE)
+		return drm_compat_ioctl(filp, cmd, arg);
+
+#if 0
+	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
+		fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE];
+#endif
+	if (fn != NULL)
+		ret = (*fn)(filp, cmd, arg);
+	else
+		ret = drm_ioctl(filp, cmd, arg);
+
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2006 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/*
+ * Authors:
+ *   Ben Skeggs <darktama@iinet.net.au>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_reg.h"
+#include <linux/ratelimit.h>
+
+/* needed for hotplug irq */
+#include "nouveau_connector.h"
+#include "nv50_display.h"
+
+void
+nouveau_irq_preinstall(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/* Master disable */
+	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
+
+	if (dev_priv->card_type == NV_50) {
+		INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
+		INIT_LIST_HEAD(&dev_priv->vbl_waiting);
+	}
+}
+
+int
+nouveau_irq_postinstall(struct drm_device *dev)
+{
+	/* Master enable */
+	nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
+	return 0;
+}
+
+void
+nouveau_irq_uninstall(struct drm_device *dev)
+{
+	/* Master disable */
+	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
+}
+
+static int
+nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_pgraph_object_method *grm;
+	struct nouveau_pgraph_object_class *grc;
+
+	grc = dev_priv->engine.graph.grclass;
+	while (grc->id) {
+		if (grc->id == class)
+			break;
+		grc++;
+	}
+
+	if (grc->id != class || !grc->methods)
+		return -ENOENT;
+
+	grm = grc->methods;
+	while (grm->id) {
+		if (grm->id == mthd)
+			return grm->exec(chan, class, mthd, data);
+		grm++;
+	}
+
+	return -ENOENT;
+}
+
+static bool
+nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data)
+{
+	struct drm_device *dev = chan->dev;
+	const int subc = (addr >> 13) & 0x7;
+	const int mthd = addr & 0x1ffc;
+
+	if (mthd == 0x0000) {
+		struct nouveau_gpuobj_ref *ref = NULL;
+
+		if (nouveau_gpuobj_ref_find(chan, data, &ref))
+			return false;
+
+		if (ref->gpuobj->engine != NVOBJ_ENGINE_SW)
+			return false;
+
+		chan->sw_subchannel[subc] = ref->gpuobj->class;
+		nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev,
+			NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4));
+		return true;
+	}
+
+	/* hw object */
+	if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4)))
+		return false;
+
+	if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data))
+		return false;
+
+	return true;
+}
+
+static void
+nouveau_fifo_irq_handler(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	uint32_t status, reassign;
+	int cnt = 0;
+
+	reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
+	while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
+		struct nouveau_channel *chan = NULL;
+		uint32_t chid, get;
+
+		nv_wr32(dev, NV03_PFIFO_CACHES, 0);
+
+		chid = engine->fifo.channel_id(dev);
+		if (chid >= 0 && chid < engine->fifo.channels)
+			chan = dev_priv->fifos[chid];
+		get  = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
+
+		if (status & NV_PFIFO_INTR_CACHE_ERROR) {
+			uint32_t mthd, data;
+			int ptr;
+
+			/* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
+			 * wrapping on my G80 chips, but CACHE1 isn't big
+			 * enough for this much data.. Tests show that it
+			 * wraps around to the start at GET=0x800.. No clue
+			 * as to why..
+			 */
+			ptr = (get & 0x7ff) >> 2;
+
+			if (dev_priv->card_type < NV_40) {
+				mthd = nv_rd32(dev,
+					NV04_PFIFO_CACHE1_METHOD(ptr));
+				data = nv_rd32(dev,
+					NV04_PFIFO_CACHE1_DATA(ptr));
+			} else {
+				mthd = nv_rd32(dev,
+					NV40_PFIFO_CACHE1_METHOD(ptr));
+				data = nv_rd32(dev,
+					NV40_PFIFO_CACHE1_DATA(ptr));
+			}
+
+			if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) {
+				NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
+					     "Mthd 0x%04x Data 0x%08x\n",
+					chid, (mthd >> 13) & 7, mthd & 0x1ffc,
+					data);
+			}
+
+			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
+			nv_wr32(dev, NV03_PFIFO_INTR_0,
+						NV_PFIFO_INTR_CACHE_ERROR);
+
+			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
+				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
+			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
+			nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
+				nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
+
+			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
+				nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
+
+			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
+		}
+
+		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
+			NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid);
+
+			status &= ~NV_PFIFO_INTR_DMA_PUSHER;
+			nv_wr32(dev, NV03_PFIFO_INTR_0,
+						NV_PFIFO_INTR_DMA_PUSHER);
+
+			nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
+			if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get)
+				nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET,
+								get + 4);
+		}
+
+		if (status & NV_PFIFO_INTR_SEMAPHORE) {
+			uint32_t sem;
+
+			status &= ~NV_PFIFO_INTR_SEMAPHORE;
+			nv_wr32(dev, NV03_PFIFO_INTR_0,
+				NV_PFIFO_INTR_SEMAPHORE);
+
+			sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
+			nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
+
+			nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
+			nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
+		}
+
+		if (status) {
+			NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
+				status, chid);
+			nv_wr32(dev, NV03_PFIFO_INTR_0, status);
+			status = 0;
+		}
+
+		nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
+	}
+
+	if (status) {
+		NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
+		nv_wr32(dev, 0x2140, 0);
+		nv_wr32(dev, 0x140, 0);
+	}
+
+	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
+}
+
+struct nouveau_bitfield_names {
+	uint32_t mask;
+	const char *name;
+};
+
+static struct nouveau_bitfield_names nstatus_names[] =
+{
+	{ NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+	{ NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+	{ NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+	{ NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
+};
+
+static struct nouveau_bitfield_names nstatus_names_nv10[] =
+{
+	{ NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
+	{ NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
+	{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
+	{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
+};
+
+static struct nouveau_bitfield_names nsource_names[] =
+{
+	{ NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
+	{ NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
+	{ NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
+	{ NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
+	{ NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
+	{ NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
+	{ NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
+	{ NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
+	{ NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
+	{ NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
+	{ NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
+	{ NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
+	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
+	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
+};
+
+static void
+nouveau_print_bitfield_names_(uint32_t value,
+				const struct nouveau_bitfield_names *namelist,
+				const int namelist_len)
+{
+	/*
+	 * Caller must have already printed the KERN_* log level for us.
+	 * Also the caller is responsible for adding the newline.
+	 */
+	int i;
+	for (i = 0; i < namelist_len; ++i) {
+		uint32_t mask = namelist[i].mask;
+		if (value & mask) {
+			printk(" %s", namelist[i].name);
+			value &= ~mask;
+		}
+	}
+	if (value)
+		printk(" (unknown bits 0x%08x)", value);
+}
+#define nouveau_print_bitfield_names(val, namelist) \
+	nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
+
+
+static int
+nouveau_graph_chid_from_grctx(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t inst;
+	int i;
+
+	if (dev_priv->card_type < NV_40)
+		return dev_priv->engine.fifo.channels;
+	else
+	if (dev_priv->card_type < NV_50) {
+		inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4;
+
+		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+			struct nouveau_channel *chan = dev_priv->fifos[i];
+
+			if (!chan || !chan->ramin_grctx)
+				continue;
+
+			if (inst == chan->ramin_grctx->instance)
+				break;
+		}
+	} else {
+		inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12;
+
+		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+			struct nouveau_channel *chan = dev_priv->fifos[i];
+
+			if (!chan || !chan->ramin)
+				continue;
+
+			if (inst == chan->ramin->instance)
+				break;
+		}
+	}
+
+
+	return i;
+}
+
+static int
+nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	int channel;
+
+	if (dev_priv->card_type < NV_10)
+		channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
+	else
+	if (dev_priv->card_type < NV_40)
+		channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
+	else
+		channel = nouveau_graph_chid_from_grctx(dev);
+
+	if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
+		NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel);
+		return -EINVAL;
+	}
+
+	*channel_ret = channel;
+	return 0;
+}
+
+struct nouveau_pgraph_trap {
+	int channel;
+	int class;
+	int subc, mthd, size;
+	uint32_t data, data2;
+	uint32_t nsource, nstatus;
+};
+
+static void
+nouveau_graph_trap_info(struct drm_device *dev,
+			struct nouveau_pgraph_trap *trap)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t address;
+
+	trap->nsource = trap->nstatus = 0;
+	if (dev_priv->card_type < NV_50) {
+		trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+		trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+	}
+
+	if (nouveau_graph_trapped_channel(dev, &trap->channel))
+		trap->channel = -1;
+	address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+
+	trap->mthd = address & 0x1FFC;
+	trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+	if (dev_priv->card_type < NV_10) {
+		trap->subc  = (address >> 13) & 0x7;
+	} else {
+		trap->subc  = (address >> 16) & 0x7;
+		trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH);
+	}
+
+	if (dev_priv->card_type < NV_10)
+		trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF;
+	else if (dev_priv->card_type < NV_40)
+		trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF;
+	else if (dev_priv->card_type < NV_50)
+		trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF;
+	else
+		trap->class = nv_rd32(dev, 0x400814);
+}
+
+static void
+nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
+			     struct nouveau_pgraph_trap *trap)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
+
+	NV_INFO(dev, "%s - nSource:", id);
+	nouveau_print_bitfield_names(nsource, nsource_names);
+	printk(", nStatus:");
+	if (dev_priv->card_type < NV_10)
+		nouveau_print_bitfield_names(nstatus, nstatus_names);
+	else
+		nouveau_print_bitfield_names(nstatus, nstatus_names_nv10);
+	printk("\n");
+
+	NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
+					"Data 0x%08x:0x%08x\n",
+					id, trap->channel, trap->subc,
+					trap->class, trap->mthd,
+					trap->data2, trap->data);
+}
+
+static int
+nouveau_pgraph_intr_swmthd(struct drm_device *dev,
+			   struct nouveau_pgraph_trap *trap)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (trap->channel < 0 ||
+	    trap->channel >= dev_priv->engine.fifo.channels ||
+	    !dev_priv->fifos[trap->channel])
+		return -ENODEV;
+
+	return nouveau_call_method(dev_priv->fifos[trap->channel],
+				   trap->class, trap->mthd, trap->data);
+}
+
+static inline void
+nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
+{
+	struct nouveau_pgraph_trap trap;
+	int unhandled = 0;
+
+	nouveau_graph_trap_info(dev, &trap);
+
+	if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+		if (nouveau_pgraph_intr_swmthd(dev, &trap))
+			unhandled = 1;
+	} else {
+		unhandled = 1;
+	}
+
+	if (unhandled)
+		nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
+}
+
+static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
+
+static int nouveau_ratelimit(void)
+{
+	return __ratelimit(&nouveau_ratelimit_state);
+}
+
+
+static inline void
+nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
+{
+	struct nouveau_pgraph_trap trap;
+	int unhandled = 0;
+
+	nouveau_graph_trap_info(dev, &trap);
+	trap.nsource = nsource;
+
+	if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+		if (nouveau_pgraph_intr_swmthd(dev, &trap))
+			unhandled = 1;
+	} else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
+		uint32_t v = nv_rd32(dev, 0x402000);
+		nv_wr32(dev, 0x402000, v);
+
+		/* dump the error anyway for now: it's useful for
+		   Gallium development */
+		unhandled = 1;
+	} else {
+		unhandled = 1;
+	}
+
+	if (unhandled && nouveau_ratelimit())
+		nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
+}
+
+static inline void
+nouveau_pgraph_intr_context_switch(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	uint32_t chid;
+
+	chid = engine->fifo.channel_id(dev);
+	NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid);
+
+	switch (dev_priv->card_type) {
+	case NV_04:
+		nv04_graph_context_switch(dev);
+		break;
+	case NV_10:
+		nv10_graph_context_switch(dev);
+		break;
+	default:
+		NV_ERROR(dev, "Context switch not implemented\n");
+		break;
+	}
+}
+
+static void
+nouveau_pgraph_irq_handler(struct drm_device *dev)
+{
+	uint32_t status;
+
+	while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+
+		if (status & NV_PGRAPH_INTR_NOTIFY) {
+			nouveau_pgraph_intr_notify(dev, nsource);
+
+			status &= ~NV_PGRAPH_INTR_NOTIFY;
+			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
+		}
+
+		if (status & NV_PGRAPH_INTR_ERROR) {
+			nouveau_pgraph_intr_error(dev, nsource);
+
+			status &= ~NV_PGRAPH_INTR_ERROR;
+			nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
+		}
+
+		if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
+			nouveau_pgraph_intr_context_switch(dev);
+
+			status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+			nv_wr32(dev, NV03_PGRAPH_INTR,
+				 NV_PGRAPH_INTR_CONTEXT_SWITCH);
+		}
+
+		if (status) {
+			NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status);
+			nv_wr32(dev, NV03_PGRAPH_INTR, status);
+		}
+
+		if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
+			nv_wr32(dev, NV04_PGRAPH_FIFO, 1);
+	}
+
+	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
+}
+
+static void
+nv50_pgraph_irq_handler(struct drm_device *dev)
+{
+	uint32_t status;
+
+	while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+		uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+
+		if (status & 0x00000001) {
+			nouveau_pgraph_intr_notify(dev, nsource);
+			status &= ~0x00000001;
+			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
+		}
+
+		if (status & 0x00000010) {
+			nouveau_pgraph_intr_error(dev, nsource |
+					NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
+
+			status &= ~0x00000010;
+			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
+		}
+
+		if (status & 0x00001000) {
+			nv_wr32(dev, 0x400500, 0x00000000);
+			nv_wr32(dev, NV03_PGRAPH_INTR,
+				NV_PGRAPH_INTR_CONTEXT_SWITCH);
+			nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
+				NV40_PGRAPH_INTR_EN) &
+				~NV_PGRAPH_INTR_CONTEXT_SWITCH);
+			nv_wr32(dev, 0x400500, 0x00010001);
+
+			nv50_graph_context_switch(dev);
+
+			status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
+		}
+
+		if (status & 0x00100000) {
+			nouveau_pgraph_intr_error(dev, nsource |
+					NV03_PGRAPH_NSOURCE_DATA_ERROR);
+
+			status &= ~0x00100000;
+			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
+		}
+
+		if (status & 0x00200000) {
+			int r;
+
+			nouveau_pgraph_intr_error(dev, nsource |
+					NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
+
+			NV_ERROR(dev, "magic set 1:\n");
+			for (r = 0x408900; r <= 0x408910; r += 4)
+				NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+					nv_rd32(dev, r));
+			nv_wr32(dev, 0x408900,
+				nv_rd32(dev, 0x408904) | 0xc0000000);
+			for (r = 0x408e08; r <= 0x408e24; r += 4)
+				NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+							nv_rd32(dev, r));
+			nv_wr32(dev, 0x408e08,
+				nv_rd32(dev, 0x408e08) | 0xc0000000);
+
+			NV_ERROR(dev, "magic set 2:\n");
+			for (r = 0x409900; r <= 0x409910; r += 4)
+				NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+					nv_rd32(dev, r));
+			nv_wr32(dev, 0x409900,
+				nv_rd32(dev, 0x409904) | 0xc0000000);
+			for (r = 0x409e08; r <= 0x409e24; r += 4)
+				NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
+					nv_rd32(dev, r));
+			nv_wr32(dev, 0x409e08,
+				nv_rd32(dev, 0x409e08) | 0xc0000000);
+
+			status &= ~0x00200000;
+			nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource);
+			nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
+		}
+
+		if (status) {
+			NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
+				status);
+			nv_wr32(dev, NV03_PGRAPH_INTR, status);
+		}
+
+		{
+			const int isb = (1 << 16) | (1 << 0);
+
+			if ((nv_rd32(dev, 0x400500) & isb) != isb)
+				nv_wr32(dev, 0x400500,
+					nv_rd32(dev, 0x400500) | isb);
+		}
+	}
+
+	nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
+	nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
+}
+
+static void
+nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
+{
+	if (crtc & 1)
+		nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
+
+	if (crtc & 2)
+		nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
+}
+
+irqreturn_t
+nouveau_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *)arg;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t status, fbdev_flags = 0;
+
+	status = nv_rd32(dev, NV03_PMC_INTR_0);
+	if (!status)
+		return IRQ_NONE;
+
+	if (dev_priv->fbdev_info) {
+		fbdev_flags = dev_priv->fbdev_info->flags;
+		dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
+	if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
+		nouveau_fifo_irq_handler(dev);
+		status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
+	}
+
+	if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
+		if (dev_priv->card_type >= NV_50)
+			nv50_pgraph_irq_handler(dev);
+		else
+			nouveau_pgraph_irq_handler(dev);
+
+		status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
+	}
+
+	if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
+		nouveau_crtc_irq_handler(dev, (status>>24)&3);
+		status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
+	}
+
+	if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
+		      NV_PMC_INTR_0_NV50_I2C_PENDING)) {
+		nv50_display_irq_handler(dev);
+		status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
+			    NV_PMC_INTR_0_NV50_I2C_PENDING);
+	}
+
+	if (status)
+		NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status);
+
+	if (dev_priv->fbdev_info)
+		dev_priv->fbdev_info->flags = fbdev_flags;
+
+	return IRQ_HANDLED;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 Red Hat <mjg@redhat.com>
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/*
+ * Authors:
+ *  Matthew Garrett <mjg@redhat.com>
+ *
+ * Register locations derived from NVClock by Roderick Colenbrander
+ */
+
+#include <linux/backlight.h>
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nouveau_reg.h"
+
+static int nv40_get_intensity(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)
+									>> 16;
+
+	return val;
+}
+
+static int nv40_set_intensity(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	int val = bd->props.brightness;
+	int reg = nv_rd32(dev, NV40_PMC_BACKLIGHT);
+
+	nv_wr32(dev, NV40_PMC_BACKLIGHT,
+		 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
+
+	return 0;
+}
+
+static struct backlight_ops nv40_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nv40_get_intensity,
+	.update_status = nv40_set_intensity,
+};
+
+static int nv50_get_intensity(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+
+	return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT);
+}
+
+static int nv50_set_intensity(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(bd);
+	int val = bd->props.brightness;
+
+	nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT,
+		val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);
+	return 0;
+}
+
+static struct backlight_ops nv50_bl_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.get_brightness = nv50_get_intensity,
+	.update_status = nv50_set_intensity,
+};
+
+static int nouveau_nv40_backlight_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_device *bd;
+
+	if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
+		return 0;
+
+	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+				       &nv40_bl_ops);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	dev_priv->backlight = bd;
+	bd->props.max_brightness = 31;
+	bd->props.brightness = nv40_get_intensity(bd);
+	backlight_update_status(bd);
+
+	return 0;
+}
+
+static int nouveau_nv50_backlight_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_device *bd;
+
+	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
+		return 0;
+
+	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+				       &nv50_bl_ops);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	dev_priv->backlight = bd;
+	bd->props.max_brightness = 1025;
+	bd->props.brightness = nv50_get_intensity(bd);
+	backlight_update_status(bd);
+	return 0;
+}
+
+int nouveau_backlight_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->card_type) {
+	case NV_40:
+		return nouveau_nv40_backlight_init(dev);
+	case NV_50:
+		return nouveau_nv50_backlight_init(dev);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+void nouveau_backlight_exit(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->backlight) {
+		backlight_device_unregister(dev_priv->backlight);
+		dev_priv->backlight = NULL;
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2003 NVIDIA, Corporation
+ * Copyright 2006 Dave Airlie
+ * Copyright 2007 Maarten Maathuis
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * 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 (including the next
+ * paragraph) 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 "drmP.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+#include "nvreg.h"
+
+#define FP_TG_CONTROL_ON  (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |	\
+			   NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |		\
+			   NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS)
+#define FP_TG_CONTROL_OFF (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE |	\
+			   NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE |	\
+			   NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE)
+
+static inline bool is_fpc_off(uint32_t fpc)
+{
+	return ((fpc & (FP_TG_CONTROL_ON | FP_TG_CONTROL_OFF)) ==
+			FP_TG_CONTROL_OFF);
+}
+
+int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent)
+{
+	/* special case of nv_read_tmds to find crtc associated with an output.
+	 * this does not give a correct answer for off-chip dvi, but there's no
+	 * use for such an answer anyway
+	 */
+	int ramdac = (dcbent->or & OUTPUT_C) >> 2;
+
+	NVWriteRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL,
+	NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4);
+	return ((NVReadRAMDAC(dev, ramdac, NV_PRAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac;
+}
+
+void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
+			int head, bool dl)
+{
+	/* The BIOS scripts don't do this for us, sadly
+	 * Luckily we do know the values ;-)
+	 *
+	 * head < 0 indicates we wish to force a setting with the overrideval
+	 * (for VT restore etc.)
+	 */
+
+	int ramdac = (dcbent->or & OUTPUT_C) >> 2;
+	uint8_t tmds04 = 0x80;
+
+	if (head != ramdac)
+		tmds04 = 0x88;
+
+	if (dcbent->type == OUTPUT_LVDS)
+		tmds04 |= 0x01;
+
+	nv_write_tmds(dev, dcbent->or, 0, 0x04, tmds04);
+
+	if (dl)	/* dual link */
+		nv_write_tmds(dev, dcbent->or, 1, 0x04, tmds04 ^ 0x08);
+}
+
+void nv04_dfp_disable(struct drm_device *dev, int head)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg;
+
+	if (NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL) &
+	    FP_TG_CONTROL_ON) {
+		/* digital remnants must be cleaned before new crtc
+		 * values programmed.  delay is time for the vga stuff
+		 * to realise it's in control again
+		 */
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
+			      FP_TG_CONTROL_OFF);
+		msleep(50);
+	}
+	/* don't inadvertently turn it on when state written later */
+	crtcstate[head].fp_control = FP_TG_CONTROL_OFF;
+}
+
+void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct nouveau_crtc *nv_crtc;
+	uint32_t *fpc;
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		nv_crtc = nouveau_crtc(encoder->crtc);
+		fpc = &dev_priv->mode_reg.crtc_reg[nv_crtc->index].fp_control;
+
+		if (is_fpc_off(*fpc)) {
+			/* using saved value is ok, as (is_digital && dpms_on &&
+			 * fp_control==OFF) is (at present) *only* true when
+			 * fpc's most recent change was by below "off" code
+			 */
+			*fpc = nv_crtc->dpms_saved_fp_control;
+		}
+
+		nv_crtc->fp_users |= 1 << nouveau_encoder(encoder)->dcb->index;
+		NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_FP_TG_CONTROL, *fpc);
+	} else {
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			nv_crtc = nouveau_crtc(crtc);
+			fpc = &dev_priv->mode_reg.crtc_reg[nv_crtc->index].fp_control;
+
+			nv_crtc->fp_users &= ~(1 << nouveau_encoder(encoder)->dcb->index);
+			if (!is_fpc_off(*fpc) && !nv_crtc->fp_users) {
+				nv_crtc->dpms_saved_fp_control = *fpc;
+				/* cut the FP output */
+				*fpc &= ~FP_TG_CONTROL_ON;
+				*fpc |= FP_TG_CONTROL_OFF;
+				NVWriteRAMDAC(dev, nv_crtc->index,
+					      NV_PRAMDAC_FP_TG_CONTROL, *fpc);
+			}
+		}
+	}
+}
+
+static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder);
+
+	/* For internal panels and gpu scaling on DVI we need the native mode */
+	if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) {
+		if (!nv_connector->native_mode)
+			return false;
+		nv_encoder->mode = *nv_connector->native_mode;
+		adjusted_mode->clock = nv_connector->native_mode->clock;
+	} else {
+		nv_encoder->mode = *adjusted_mode;
+	}
+
+	return true;
+}
+
+static void nv04_dfp_prepare_sel_clk(struct drm_device *dev,
+				     struct nouveau_encoder *nv_encoder, int head)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_mode_state *state = &dev_priv->mode_reg;
+	uint32_t bits1618 = nv_encoder->dcb->or & OUTPUT_A ? 0x10000 : 0x40000;
+
+	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP)
+		return;
+
+	/* SEL_CLK is only used on the primary ramdac
+	 * It toggles spread spectrum PLL output and sets the bindings of PLLs
+	 * to heads on digital outputs
+	 */
+	if (head)
+		state->sel_clk |= bits1618;
+	else
+		state->sel_clk &= ~bits1618;
+
+	/* nv30:
+	 *	bit 0		NVClk spread spectrum on/off
+	 *	bit 2		MemClk spread spectrum on/off
+	 * 	bit 4		PixClk1 spread spectrum on/off toggle
+	 * 	bit 6		PixClk2 spread spectrum on/off toggle
+	 *
+	 * nv40 (observations from bios behaviour and mmio traces):
+	 * 	bits 4&6	as for nv30
+	 * 	bits 5&7	head dependent as for bits 4&6, but do not appear with 4&6;
+	 * 			maybe a different spread mode
+	 * 	bits 8&10	seen on dual-link dvi outputs, purpose unknown (set by POST scripts)
+	 * 	The logic behind turning spread spectrum on/off in the first place,
+	 * 	and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table
+	 * 	entry has the necessary info)
+	 */
+	if (nv_encoder->dcb->type == OUTPUT_LVDS && dev_priv->saved_reg.sel_clk & 0xf0) {
+		int shift = (dev_priv->saved_reg.sel_clk & 0x50) ? 0 : 1;
+
+		state->sel_clk &= ~0xf0;
+		state->sel_clk |= (head ? 0x40 : 0x10) << shift;
+	}
+}
+
+static void nv04_dfp_prepare(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int head = nouveau_crtc(encoder->crtc)->index;
+	struct nv04_crtc_reg *crtcstate = dev_priv->mode_reg.crtc_reg;
+	uint8_t *cr_lcd = &crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX];
+	uint8_t *cr_lcd_oth = &crtcstate[head ^ 1].CRTC[NV_CIO_CRE_LCD__INDEX];
+
+	helper->dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	nv04_dfp_prepare_sel_clk(dev, nv_encoder, head);
+
+	/* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f)
+	 * at LCD__INDEX which we don't alter
+	 */
+	if (!(*cr_lcd & 0x44)) {
+		*cr_lcd = 0x3;
+
+		if (nv_two_heads(dev)) {
+			if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP)
+				*cr_lcd |= head ? 0x0 : 0x8;
+			else {
+				*cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30;
+				if (nv_encoder->dcb->type == OUTPUT_LVDS)
+					*cr_lcd |= 0x30;
+				if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) {
+					/* avoid being connected to both crtcs */
+					*cr_lcd_oth &= ~0x30;
+					NVWriteVgaCrtc(dev, head ^ 1,
+						       NV_CIO_CRE_LCD__INDEX,
+						       *cr_lcd_oth);
+				}
+			}
+		}
+	}
+}
+
+
+static void nv04_dfp_mode_set(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode,
+			      struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+	struct nv04_crtc_reg *savep = &dev_priv->saved_reg.crtc_reg[nv_crtc->index];
+	struct nouveau_connector *nv_connector = nouveau_crtc_connector_get(nv_crtc);
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_display_mode *output_mode = &nv_encoder->mode;
+	uint32_t mode_ratio, panel_ratio;
+
+	NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index);
+	drm_mode_debug_printmodeline(output_mode);
+
+	/* Initialize the FP registers in this CRTC. */
+	regp->fp_horiz_regs[FP_DISPLAY_END] = output_mode->hdisplay - 1;
+	regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1;
+	if (!nv_gf4_disp_arch(dev) ||
+	    (output_mode->hsync_start - output_mode->hdisplay) >=
+					dev_priv->vbios->digital_min_front_porch)
+		regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay;
+	else
+		regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios->digital_min_front_porch - 1;
+	regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1;
+	regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1;
+	regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew;
+	regp->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - 1;
+
+	regp->fp_vert_regs[FP_DISPLAY_END] = output_mode->vdisplay - 1;
+	regp->fp_vert_regs[FP_TOTAL] = output_mode->vtotal - 1;
+	regp->fp_vert_regs[FP_CRTC] = output_mode->vtotal - 5 - 1;
+	regp->fp_vert_regs[FP_SYNC_START] = output_mode->vsync_start - 1;
+	regp->fp_vert_regs[FP_SYNC_END] = output_mode->vsync_end - 1;
+	regp->fp_vert_regs[FP_VALID_START] = 0;
+	regp->fp_vert_regs[FP_VALID_END] = output_mode->vdisplay - 1;
+
+	/* bit26: a bit seen on some g7x, no as yet discernable purpose */
+	regp->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
+			   (savep->fp_control & (1 << 26 | NV_PRAMDAC_FP_TG_CONTROL_READ_PROG));
+	/* Deal with vsync/hsync polarity */
+	/* LVDS screens do set this, but modes with +ve syncs are very rare */
+	if (output_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS;
+	if (output_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS;
+	/* panel scaling first, as native would get set otherwise */
+	if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE ||
+	    nv_connector->scaling_mode == DRM_MODE_SCALE_CENTER)	/* panel handles it */
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER;
+	else if (adjusted_mode->hdisplay == output_mode->hdisplay &&
+		 adjusted_mode->vdisplay == output_mode->vdisplay) /* native mode */
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE;
+	else /* gpu needs to scale */
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE;
+	if (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
+		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
+	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP &&
+	    output_mode->clock > 165000)
+		regp->fp_control |= (2 << 24);
+	if (nv_encoder->dcb->type == OUTPUT_LVDS) {
+		bool duallink, dummy;
+
+		nouveau_bios_parse_lvds_table(dev, nv_connector->native_mode->
+					      clock, &duallink, &dummy);
+		if (duallink)
+			regp->fp_control |= (8 << 28);
+	} else
+	if (output_mode->clock > 165000)
+		regp->fp_control |= (8 << 28);
+
+	regp->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND |
+			   NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND |
+			   NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR |
+			   NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR |
+			   NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED |
+			   NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE |
+			   NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE;
+
+	/* We want automatic scaling */
+	regp->fp_debug_1 = 0;
+	/* This can override HTOTAL and VTOTAL */
+	regp->fp_debug_2 = 0;
+
+	/* Use 20.12 fixed point format to avoid floats */
+	mode_ratio = (1 << 12) * adjusted_mode->hdisplay / adjusted_mode->vdisplay;
+	panel_ratio = (1 << 12) * output_mode->hdisplay / output_mode->vdisplay;
+	/* if ratios are equal, SCALE_ASPECT will automatically (and correctly)
+	 * get treated the same as SCALE_FULLSCREEN */
+	if (nv_connector->scaling_mode == DRM_MODE_SCALE_ASPECT &&
+	    mode_ratio != panel_ratio) {
+		uint32_t diff, scale;
+		bool divide_by_2 = nv_gf4_disp_arch(dev);
+
+		if (mode_ratio < panel_ratio) {
+			/* vertical needs to expand to glass size (automatic)
+			 * horizontal needs to be scaled at vertical scale factor
+			 * to maintain aspect */
+
+			scale = (1 << 12) * adjusted_mode->vdisplay / output_mode->vdisplay;
+			regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE |
+					   XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
+
+			/* restrict area of screen used, horizontally */
+			diff = output_mode->hdisplay -
+			       output_mode->vdisplay * mode_ratio / (1 << 12);
+			regp->fp_horiz_regs[FP_VALID_START] += diff / 2;
+			regp->fp_horiz_regs[FP_VALID_END] -= diff / 2;
+		}
+
+		if (mode_ratio > panel_ratio) {
+			/* horizontal needs to expand to glass size (automatic)
+			 * vertical needs to be scaled at horizontal scale factor
+			 * to maintain aspect */
+
+			scale = (1 << 12) * adjusted_mode->hdisplay / output_mode->hdisplay;
+			regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE |
+					   XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE);
+
+			/* restrict area of screen used, vertically */
+			diff = output_mode->vdisplay -
+			       (1 << 12) * output_mode->hdisplay / mode_ratio;
+			regp->fp_vert_regs[FP_VALID_START] += diff / 2;
+			regp->fp_vert_regs[FP_VALID_END] -= diff / 2;
+		}
+	}
+
+	/* Output property. */
+	if (nv_connector->use_dithering) {
+		if (dev_priv->chipset == 0x11)
+			regp->dither = savep->dither | 0x00010000;
+		else {
+			int i;
+			regp->dither = savep->dither | 0x00000001;
+			for (i = 0; i < 3; i++) {
+				regp->dither_regs[i] = 0xe4e4e4e4;
+				regp->dither_regs[i + 3] = 0x44444444;
+			}
+		}
+	} else {
+		if (dev_priv->chipset != 0x11) {
+			/* reset them */
+			int i;
+			for (i = 0; i < 3; i++) {
+				regp->dither_regs[i] = savep->dither_regs[i];
+				regp->dither_regs[i + 3] = savep->dither_regs[i + 3];
+			}
+		}
+		regp->dither = savep->dither;
+	}
+
+	regp->fp_margin_color = 0;
+}
+
+static void nv04_dfp_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct dcb_entry *dcbe = nv_encoder->dcb;
+	int head = nouveau_crtc(encoder->crtc)->index;
+
+	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+
+	if (dcbe->type == OUTPUT_TMDS)
+		run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
+	else if (dcbe->type == OUTPUT_LVDS)
+		call_lvds_script(dev, dcbe, head, LVDS_RESET, nv_encoder->mode.clock);
+
+	/* update fp_control state for any changes made by scripts,
+	 * so correct value is written at DPMS on */
+	dev_priv->mode_reg.crtc_reg[head].fp_control =
+		NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
+
+	/* This could use refinement for flatpanels, but it should work this way */
+	if (dev_priv->chipset < 0x44)
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000);
+	else
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
+
+	helper->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+}
+
+static inline bool is_powersaving_dpms(int mode)
+{
+	return (mode != DRM_MODE_DPMS_ON);
+}
+
+static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms);
+
+	if (nv_encoder->last_dpms == mode)
+		return;
+	nv_encoder->last_dpms = mode;
+
+	NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n",
+		     mode, nv_encoder->dcb->index);
+
+	if (was_powersaving && is_powersaving_dpms(mode))
+		return;
+
+	if (nv_encoder->dcb->lvdsconf.use_power_scripts) {
+		struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder);
+
+		/* when removing an output, crtc may not be set, but PANEL_OFF
+		 * must still be run
+		 */
+		int head = crtc ? nouveau_crtc(crtc)->index :
+			   nv04_dfp_get_bound_head(dev, nv_encoder->dcb);
+
+		if (mode == DRM_MODE_DPMS_ON) {
+			if (!nv_connector->native_mode) {
+				NV_ERROR(dev, "Not turning on LVDS without native mode\n");
+				return;
+			}
+			call_lvds_script(dev, nv_encoder->dcb, head,
+					 LVDS_PANEL_ON, nv_connector->native_mode->clock);
+		} else
+			/* pxclk of 0 is fine for PANEL_OFF, and for a
+			 * disconnected LVDS encoder there is no native_mode
+			 */
+			call_lvds_script(dev, nv_encoder->dcb, head,
+					 LVDS_PANEL_OFF, 0);
+	}
+
+	nv04_dfp_update_fp_control(encoder, mode);
+
+	if (mode == DRM_MODE_DPMS_ON)
+		nv04_dfp_prepare_sel_clk(dev, nv_encoder, nouveau_crtc(crtc)->index);
+	else {
+		dev_priv->mode_reg.sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK);
+		dev_priv->mode_reg.sel_clk &= ~0xf0;
+	}
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, dev_priv->mode_reg.sel_clk);
+}
+
+static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	if (nv_encoder->last_dpms == mode)
+		return;
+	nv_encoder->last_dpms = mode;
+
+	NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n",
+		     mode, nv_encoder->dcb->index);
+
+	nv04_dfp_update_fp_control(encoder, mode);
+}
+
+static void nv04_dfp_save(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+
+	if (nv_two_heads(dev))
+		nv_encoder->restore.head =
+			nv04_dfp_get_bound_head(dev, nv_encoder->dcb);
+}
+
+static void nv04_dfp_restore(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int head = nv_encoder->restore.head;
+
+	if (nv_encoder->dcb->type == OUTPUT_LVDS) {
+		struct drm_display_mode *native_mode = nouveau_encoder_connector_get(nv_encoder)->native_mode;
+		if (native_mode)
+			call_lvds_script(dev, nv_encoder->dcb, head, LVDS_PANEL_ON,
+					 native_mode->clock);
+		else
+			NV_ERROR(dev, "Not restoring LVDS without native mode\n");
+
+	} else if (nv_encoder->dcb->type == OUTPUT_TMDS) {
+		int clock = nouveau_hw_pllvals_to_clk
+					(&dev_priv->saved_reg.crtc_reg[head].pllvals);
+
+		run_tmds_table(dev, nv_encoder->dcb, head, clock);
+	}
+
+	nv_encoder->last_dpms = NV_DPMS_CLEARED;
+}
+
+static void nv04_dfp_destroy(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	NV_DEBUG_KMS(encoder->dev, "\n");
+
+	drm_encoder_cleanup(encoder);
+	kfree(nv_encoder);
+}
+
+static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
+	.dpms = nv04_lvds_dpms,
+	.save = nv04_dfp_save,
+	.restore = nv04_dfp_restore,
+	.mode_fixup = nv04_dfp_mode_fixup,
+	.prepare = nv04_dfp_prepare,
+	.commit = nv04_dfp_commit,
+	.mode_set = nv04_dfp_mode_set,
+	.detect = NULL,
+};
+
+static const struct drm_encoder_helper_funcs nv04_tmds_helper_funcs = {
+	.dpms = nv04_tmds_dpms,
+	.save = nv04_dfp_save,
+	.restore = nv04_dfp_restore,
+	.mode_fixup = nv04_dfp_mode_fixup,
+	.prepare = nv04_dfp_prepare,
+	.commit = nv04_dfp_commit,
+	.mode_set = nv04_dfp_mode_set,
+	.detect = NULL,
+};
+
+static const struct drm_encoder_funcs nv04_dfp_funcs = {
+	.destroy = nv04_dfp_destroy,
+};
+
+int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	const struct drm_encoder_helper_funcs *helper;
+	struct drm_encoder *encoder;
+	struct nouveau_encoder *nv_encoder = NULL;
+	int type;
+
+	switch (entry->type) {
+	case OUTPUT_TMDS:
+		type = DRM_MODE_ENCODER_TMDS;
+		helper = &nv04_tmds_helper_funcs;
+		break;
+	case OUTPUT_LVDS:
+		type = DRM_MODE_ENCODER_LVDS;
+		helper = &nv04_lvds_helper_funcs;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+
+	encoder = to_drm_encoder(nv_encoder);
+
+	nv_encoder->dcb = entry;
+	nv_encoder->or = ffs(entry->or) - 1;
+
+	drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type);
+	drm_encoder_helper_add(encoder, helper);
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_graph.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+#include "nouveau_grctx.h"
+
+#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
+
+static void
+nv50_graph_init_reset(struct drm_device *dev)
+{
+	uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
+
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |  pmc_e);
+}
+
+static void
+nv50_graph_init_intr(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
+	nv_wr32(dev, 0x400138, 0xffffffff);
+	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
+}
+
+static void
+nv50_graph_init_regs__nv(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, 0x400804, 0xc0000000);
+	nv_wr32(dev, 0x406800, 0xc0000000);
+	nv_wr32(dev, 0x400c04, 0xc0000000);
+	nv_wr32(dev, 0x401800, 0xc0000000);
+	nv_wr32(dev, 0x405018, 0xc0000000);
+	nv_wr32(dev, 0x402000, 0xc0000000);
+
+	nv_wr32(dev, 0x400108, 0xffffffff);
+
+	nv_wr32(dev, 0x400824, 0x00004000);
+	nv_wr32(dev, 0x400500, 0x00010001);
+}
+
+static void
+nv50_graph_init_regs(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3,
+				(1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
+	nv_wr32(dev, 0x402ca8, 0x800);
+}
+
+static int
+nv50_graph_init_ctxctl(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	NV_DEBUG(dev, "\n");
+
+	if (nouveau_ctxfw) {
+		nouveau_grctx_prog_load(dev);
+		dev_priv->engine.graph.grctx_size = 0x70000;
+	}
+	if (!dev_priv->engine.graph.ctxprog) {
+		struct nouveau_grctx ctx = {};
+		uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL);
+		int i;
+		if (!cp) {
+			NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n");
+			dev_priv->engine.graph.accel_blocked = true;
+			return 0;
+		}
+		ctx.dev = dev;
+		ctx.mode = NOUVEAU_GRCTX_PROG;
+		ctx.data = cp;
+		ctx.ctxprog_max = 512;
+		if (!nv50_grctx_init(&ctx)) {
+			dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
+
+			nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+			for (i = 0; i < ctx.ctxprog_len; i++)
+				nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
+		} else {
+			dev_priv->engine.graph.accel_blocked = true;
+		}
+		kfree(cp);
+	}
+
+	nv_wr32(dev, 0x400320, 4);
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
+	return 0;
+}
+
+int
+nv50_graph_init(struct drm_device *dev)
+{
+	int ret;
+
+	NV_DEBUG(dev, "\n");
+
+	nv50_graph_init_reset(dev);
+	nv50_graph_init_regs__nv(dev);
+	nv50_graph_init_regs(dev);
+	nv50_graph_init_intr(dev);
+
+	ret = nv50_graph_init_ctxctl(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void
+nv50_graph_takedown(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+	nouveau_grctx_fini(dev);
+}
+
+void
+nv50_graph_fifo_access(struct drm_device *dev, bool enabled)
+{
+	const uint32_t mask = 0x00010001;
+
+	if (enabled)
+		nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask);
+	else
+		nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask);
+}
+
+struct nouveau_channel *
+nv50_graph_channel(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t inst;
+	int i;
+
+	/* Be sure we're not in the middle of a context switch or bad things
+	 * will happen, such as unloading the wrong pgraph context.
+	 */
+	if (!nv_wait(0x400300, 0x00000001, 0x00000000))
+		NV_ERROR(dev, "Ctxprog is still running\n");
+
+	inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
+	if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
+		return NULL;
+	inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
+
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		struct nouveau_channel *chan = dev_priv->fifos[i];
+
+		if (chan && chan->ramin && chan->ramin->instance == inst)
+			return chan;
+	}
+
+	return NULL;
+}
+
+int
+nv50_graph_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
+	struct nouveau_gpuobj *ctx;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	int hdr, ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
+				     0x1000, NVOBJ_FLAG_ZERO_ALLOC |
+				     NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
+	if (ret)
+		return ret;
+	ctx = chan->ramin_grctx->gpuobj;
+
+	hdr = IS_G80 ? 0x200 : 0x20;
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002);
+	nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
+					   pgraph->grctx_size - 1);
+	nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
+	nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0);
+	nv_wo32(dev, ramin, (hdr + 0x10)/4, 0);
+	nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	if (!pgraph->ctxprog) {
+		struct nouveau_grctx ctx = {};
+		ctx.dev = chan->dev;
+		ctx.mode = NOUVEAU_GRCTX_VALS;
+		ctx.data = chan->ramin_grctx->gpuobj;
+		nv50_grctx_init(&ctx);
+	} else {
+		nouveau_grctx_vals_load(dev, ctx);
+	}
+	nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	return 0;
+}
+
+void
+nv50_graph_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i, hdr = IS_G80 ? 0x200 : 0x20;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	if (!chan->ramin || !chan->ramin->gpuobj)
+		return;
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	for (i = hdr; i < hdr + 24; i += 4)
+		nv_wo32(dev, chan->ramin->gpuobj, i/4, 0);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
+}
+
+static int
+nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst)
+{
+	uint32_t fifo = nv_rd32(dev, 0x400500);
+
+	nv_wr32(dev, 0x400500, fifo & ~1);
+	nv_wr32(dev, 0x400784, inst);
+	nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x40);
+	nv_wr32(dev, 0x400320, nv_rd32(dev, 0x400320) | 0x11);
+	nv_wr32(dev, 0x400040, 0xffffffff);
+	(void)nv_rd32(dev, 0x400040);
+	nv_wr32(dev, 0x400040, 0x00000000);
+	nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 1);
+
+	if (nouveau_wait_for_idle(dev))
+		nv_wr32(dev, 0x40032c, inst | (1<<31));
+	nv_wr32(dev, 0x400500, fifo);
+
+	return 0;
+}
+
+int
+nv50_graph_load_context(struct nouveau_channel *chan)
+{
+	uint32_t inst = chan->ramin->instance >> 12;
+
+	NV_DEBUG(chan->dev, "ch%d\n", chan->id);
+	return nv50_graph_do_load_context(chan->dev, inst);
+}
+
+int
+nv50_graph_unload_context(struct drm_device *dev)
+{
+	uint32_t inst;
+
+	inst  = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
+	if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
+		return 0;
+	inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
+
+	nouveau_wait_for_idle(dev);
+	nv_wr32(dev, 0x400784, inst);
+	nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
+	nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01);
+	nouveau_wait_for_idle(dev);
+
+	nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst);
+	return 0;
+}
+
+void
+nv50_graph_context_switch(struct drm_device *dev)
+{
+	uint32_t inst;
+
+	nv50_graph_unload_context(dev);
+
+	inst  = nv_rd32(dev, NV50_PGRAPH_CTXCTL_NEXT);
+	inst &= NV50_PGRAPH_CTXCTL_NEXT_INSTANCE;
+	nv50_graph_do_load_context(dev, inst);
+
+	nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
+		NV40_PGRAPH_INTR_EN) | NV_PGRAPH_INTR_CONTEXT_SWITCH);
+}
+
+static int
+nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass,
+			   int mthd, uint32_t data)
+{
+	struct nouveau_gpuobj_ref *ref = NULL;
+
+	if (nouveau_gpuobj_ref_find(chan, data, &ref))
+		return -ENOENT;
+
+	if (nouveau_notifier_offset(ref->gpuobj, NULL))
+		return -EINVAL;
+
+	chan->nvsw.vblsem = ref->gpuobj;
+	chan->nvsw.vblsem_offset = ~0;
+	return 0;
+}
+
+static int
+nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass,
+			      int mthd, uint32_t data)
+{
+	if (nouveau_notifier_offset(chan->nvsw.vblsem, &data))
+		return -ERANGE;
+
+	chan->nvsw.vblsem_offset = data >> 2;
+	return 0;
+}
+
+static int
+nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass,
+				   int mthd, uint32_t data)
+{
+	chan->nvsw.vblsem_rval = data;
+	return 0;
+}
+
+static int
+nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass,
+			       int mthd, uint32_t data)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1)
+		return -EINVAL;
+
+	if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) &
+		      NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) {
+		nv_wr32(dev, NV50_PDISPLAY_INTR_1,
+			NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data));
+		nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
+			NV50_PDISPLAY_INTR_EN) |
+			NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data));
+	}
+
+	list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
+	return 0;
+}
+
+static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = {
+	{ 0x018c, nv50_graph_nvsw_dma_vblsem },
+	{ 0x0400, nv50_graph_nvsw_vblsem_offset },
+	{ 0x0404, nv50_graph_nvsw_vblsem_release_val },
+	{ 0x0408, nv50_graph_nvsw_vblsem_release },
+	{}
+};
+
+struct nouveau_pgraph_object_class nv50_graph_grclass[] = {
+	{ 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x5039, false, NULL }, /* m2mf */
+	{ 0x502d, false, NULL }, /* 2d */
+	{ 0x50c0, false, NULL }, /* compute */
+	{ 0x5097, false, NULL }, /* tesla (nv50) */
+	{ 0x8297, false, NULL }, /* tesla (nv80/nv90) */
+	{ 0x8397, false, NULL }, /* tesla (nva0) */
+	{ 0x8597, false, NULL }, /* tesla (nva8) */
+	{}
+};
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_i2c.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_i2c.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 __NOUVEAU_I2C_H__
+#define __NOUVEAU_I2C_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+#include "drm_dp_helper.h"
+
+struct dcb_i2c_entry;
+
+struct nouveau_i2c_chan {
+	struct i2c_adapter adapter;
+	struct drm_device *dev;
+	union {
+		struct i2c_algo_bit_data bit;
+		struct i2c_algo_dp_aux_data dp;
+	} algo;
+	unsigned rd;
+	unsigned wr;
+	unsigned data;
+};
+
+int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
+void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
+struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
+
+int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte,
+			  uint8_t *read_byte);
+
+#endif /* __NOUVEAU_I2C_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_tv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+#include "drm_crtc_helper.h"
+
+#include "i2c/ch7006.h"
+
+static struct {
+	struct i2c_board_info board_info;
+	struct drm_encoder_funcs funcs;
+	struct drm_encoder_helper_funcs hfuncs;
+	void *params;
+
+} nv04_tv_encoder_info[] = {
+	{
+		.board_info = { I2C_BOARD_INFO("ch7006", 0x75) },
+		.params = &(struct ch7006_encoder_params) {
+			CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
+			0, 0, 0,
+			CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
+			CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
+		},
+	},
+};
+
+static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
+{
+	struct i2c_msg msg = {
+		.addr = addr,
+		.len = 0,
+	};
+
+	return i2c_transfer(adapter, &msg, 1) == 1;
+}
+
+int nv04_tv_identify(struct drm_device *dev, int i2c_index)
+{
+	struct nouveau_i2c_chan *i2c;
+	bool was_locked;
+	int i, ret;
+
+	NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
+
+	i2c = nouveau_i2c_find(dev, i2c_index);
+	if (!i2c)
+		return -ENODEV;
+
+	was_locked = NVLockVgaCrtcs(dev, false);
+
+	for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
+		if (probe_i2c_addr(&i2c->adapter,
+				   nv04_tv_encoder_info[i].board_info.addr)) {
+			ret = i;
+			break;
+		}
+	}
+
+	if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
+		NV_TRACE(dev, "Detected TV encoder: %s\n",
+			 nv04_tv_encoder_info[i].board_info.type);
+
+	} else {
+		NV_TRACE(dev, "No TV encoders found.\n");
+		i = -ENODEV;
+	}
+
+	NVLockVgaCrtcs(dev, was_locked);
+	return i;
+}
+
+#define PLLSEL_TV_CRTC1_MASK				\
+	(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1		\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
+#define PLLSEL_TV_CRTC2_MASK				\
+	(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2		\
+	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2)
+
+static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_mode_state *state = &dev_priv->mode_reg;
+	uint8_t crtc1A;
+
+	NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n",
+		mode, nv_encoder->dcb->index);
+
+	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		int head = nouveau_crtc(encoder->crtc)->index;
+		crtc1A = NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX);
+
+		state->pllsel |= head ? PLLSEL_TV_CRTC2_MASK :
+					PLLSEL_TV_CRTC1_MASK;
+
+		/* Inhibit hsync */
+		crtc1A |= 0x80;
+
+		NVWriteVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX, crtc1A);
+	}
+
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
+
+	to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode);
+}
+
+static void nv04_tv_bind(struct drm_device *dev, int head, bool bind)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *state = &dev_priv->mode_reg.crtc_reg[head];
+
+	state->tv_setup = 0;
+
+	if (bind) {
+		state->CRTC[NV_CIO_CRE_LCD__INDEX] = 0;
+		state->CRTC[NV_CIO_CRE_49] |= 0x10;
+	} else {
+		state->CRTC[NV_CIO_CRE_49] &= ~0x10;
+	}
+
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_LCD__INDEX,
+		       state->CRTC[NV_CIO_CRE_LCD__INDEX]);
+	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_49,
+		       state->CRTC[NV_CIO_CRE_49]);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP,
+		      state->tv_setup);
+}
+
+static void nv04_tv_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	int head = nouveau_crtc(encoder->crtc)->index;
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+
+	helper->dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	nv04_dfp_disable(dev, head);
+
+	if (nv_two_heads(dev))
+		nv04_tv_bind(dev, head ^ 1, false);
+
+	nv04_tv_bind(dev, head, true);
+}
+
+static void nv04_tv_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+
+	regp->tv_htotal = adjusted_mode->htotal;
+	regp->tv_vtotal = adjusted_mode->vtotal;
+
+	/* These delay the TV signals with respect to the VGA port,
+	 * they might be useful if we ever allow a CRTC to drive
+	 * multiple outputs.
+	 */
+	regp->tv_hskew = 1;
+	regp->tv_hsync_delay = 1;
+	regp->tv_hsync_delay2 = 64;
+	regp->tv_vskew = 1;
+	regp->tv_vsync_delay = 1;
+
+	to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode);
+}
+
+static void nv04_tv_commit(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+
+	helper->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
+		      '@' + ffs(nv_encoder->dcb->or));
+}
+
+static void nv04_tv_destroy(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
+
+	drm_encoder_cleanup(encoder);
+
+	kfree(nv_encoder);
+}
+
+int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct i2c_adapter *adap;
+	struct drm_encoder_funcs *funcs = NULL;
+	struct drm_encoder_helper_funcs *hfuncs = NULL;
+	struct drm_encoder_slave_funcs *sfuncs = NULL;
+	int i2c_index = entry->i2c_index;
+	int type, ret;
+	bool was_locked;
+
+	/* Ensure that we can talk to this encoder */
+	type = nv04_tv_identify(dev, i2c_index);
+	if (type < 0)
+		return type;
+
+	/* Allocate the necessary memory */
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+
+	/* Initialize the common members */
+	encoder = to_drm_encoder(nv_encoder);
+
+	funcs = &nv04_tv_encoder_info[type].funcs;
+	hfuncs = &nv04_tv_encoder_info[type].hfuncs;
+
+	drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
+	drm_encoder_helper_add(encoder, hfuncs);
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+
+	nv_encoder->dcb = entry;
+	nv_encoder->or = ffs(entry->or) - 1;
+
+	/* Run the slave-specific initialization */
+	adap = &dev_priv->vbios->dcb->i2c[i2c_index].chan->adapter;
+
+	was_locked = NVLockVgaCrtcs(dev, false);
+
+	ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
+				   &nv04_tv_encoder_info[type].board_info);
+
+	NVLockVgaCrtcs(dev, was_locked);
+
+	if (ret < 0)
+		goto fail;
+
+	/* Fill the function pointers */
+	sfuncs = to_encoder_slave(encoder)->slave_funcs;
+
+	*funcs = (struct drm_encoder_funcs) {
+		.destroy = nv04_tv_destroy,
+	};
+
+	*hfuncs = (struct drm_encoder_helper_funcs) {
+		.dpms = nv04_tv_dpms,
+		.save = sfuncs->save,
+		.restore = sfuncs->restore,
+		.mode_fixup = sfuncs->mode_fixup,
+		.prepare = nv04_tv_prepare,
+		.commit = nv04_tv_commit,
+		.mode_set = nv04_tv_mode_set,
+		.detect = sfuncs->detect,
+	};
+
+	/* Set the slave encoder configuration */
+	sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
+
+	return 0;
+
+fail:
+	drm_encoder_cleanup(encoder);
+
+	kfree(nv_encoder);
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_DMA_H__
+#define __NOUVEAU_DMA_H__
+
+#ifndef NOUVEAU_DMA_DEBUG
+#define NOUVEAU_DMA_DEBUG 0
+#endif
+
+/*
+ * There's a hw race condition where you can't jump to your PUT offset,
+ * to avoid this we jump to offset + SKIPS and fill the difference with
+ * NOPs.
+ *
+ * xf86-video-nv configures the DMA fetch size to 32 bytes, and uses
+ * a SKIPS value of 8.  Lets assume that the race condition is to do
+ * with writing into the fetch area, we configure a fetch size of 128
+ * bytes so we need a larger SKIPS value.
+ */
+#define NOUVEAU_DMA_SKIPS (128 / 4)
+
+/* Hardcoded object assignments to subchannels (subchannel id). */
+enum {
+	NvSubM2MF	= 0,
+	NvSubSw		= 1,
+	NvSub2D		= 2,
+	NvSubCtxSurf2D  = 2,
+	NvSubGdiRect    = 3,
+	NvSubImageBlit  = 4
+};
+
+/* Object handles. */
+enum {
+	NvM2MF		= 0x80000001,
+	NvDmaFB		= 0x80000002,
+	NvDmaTT		= 0x80000003,
+	NvDmaVRAM	= 0x80000004,
+	NvDmaGART	= 0x80000005,
+	NvNotify0       = 0x80000006,
+	Nv2D		= 0x80000007,
+	NvCtxSurf2D	= 0x80000008,
+	NvRop		= 0x80000009,
+	NvImagePatt	= 0x8000000a,
+	NvClipRect	= 0x8000000b,
+	NvGdiRect	= 0x8000000c,
+	NvImageBlit	= 0x8000000d,
+	NvSw		= 0x8000000e,
+
+	/* G80+ display objects */
+	NvEvoVRAM	= 0x01000000,
+	NvEvoFB16	= 0x01000001,
+	NvEvoFB32	= 0x01000002
+};
+
+#define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
+#define NV_MEMORY_TO_MEMORY_FORMAT_NAME                               0x00000000
+#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF                            0x00000050
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOP                                0x00000100
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY                             0x00000104
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE                 0x00000000
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN       0x00000001
+#define NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY                         0x00000180
+#define NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE                         0x00000184
+#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN                          0x0000030c
+
+#define NV50_MEMORY_TO_MEMORY_FORMAT                                  0x00005039
+#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200                           0x00000200
+#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C                           0x0000021c
+#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH                   0x00000238
+#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH                  0x0000023c
+
+static __must_check inline int
+RING_SPACE(struct nouveau_channel *chan, int size)
+{
+	if (chan->dma.free < size) {
+		int ret;
+
+		ret = nouveau_dma_wait(chan, size);
+		if (ret)
+			return ret;
+	}
+
+	chan->dma.free -= size;
+	return 0;
+}
+
+static inline void
+OUT_RING(struct nouveau_channel *chan, int data)
+{
+	if (NOUVEAU_DMA_DEBUG) {
+		NV_INFO(chan->dev, "Ch%d/0x%08x: 0x%08x\n",
+			chan->id, chan->dma.cur << 2, data);
+	}
+
+	nouveau_bo_wr32(chan->pushbuf_bo, chan->dma.cur++, data);
+}
+
+extern void
+OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords);
+
+static inline void
+BEGIN_RING(struct nouveau_channel *chan, int subc, int mthd, int size)
+{
+	OUT_RING(chan, (subc << 13) | (size << 18) | mthd);
+}
+
+#define WRITE_PUT(val) do {                                                    \
+	DRM_MEMORYBARRIER();                                                   \
+	nouveau_bo_rd32(chan->pushbuf_bo, 0);                                  \
+	nvchan_wr32(chan, chan->user_put, ((val) << 2) + chan->pushbuf_base);  \
+} while (0)
+
+static inline void
+FIRE_RING(struct nouveau_channel *chan)
+{
+	if (NOUVEAU_DMA_DEBUG) {
+		NV_INFO(chan->dev, "Ch%d/0x%08x: PUSH!\n",
+			chan->id, chan->dma.cur << 2);
+	}
+
+	if (chan->dma.cur == chan->dma.put)
+		return;
+	chan->accel_done = true;
+
+	WRITE_PUT(chan->dma.cur);
+	chan->dma.put = chan->dma.cur;
+}
+
+static inline void
+WIND_RING(struct nouveau_channel *chan)
+{
+	chan->dma.cur = chan->dma.put;
+}
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ * Copyright 2005 Stephane Marchesin
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * 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 (including the next
+ * paragraph) 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 AND/OR THEIR SUPPLIERS 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "nouveau_drv.h"
+
+static struct mem_block *
+split_block(struct mem_block *p, uint64_t start, uint64_t size,
+	    struct drm_file *file_priv)
+{
+	/* Maybe cut off the start of an existing block */
+	if (start > p->start) {
+		struct mem_block *newblock =
+			kmalloc(sizeof(*newblock), GFP_KERNEL);
+		if (!newblock)
+			goto out;
+		newblock->start = start;
+		newblock->size = p->size - (start - p->start);
+		newblock->file_priv = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size -= newblock->size;
+		p = newblock;
+	}
+
+	/* Maybe cut off the end of an existing block */
+	if (size < p->size) {
+		struct mem_block *newblock =
+			kmalloc(sizeof(*newblock), GFP_KERNEL);
+		if (!newblock)
+			goto out;
+		newblock->start = start + size;
+		newblock->size = p->size - size;
+		newblock->file_priv = NULL;
+		newblock->next = p->next;
+		newblock->prev = p;
+		p->next->prev = newblock;
+		p->next = newblock;
+		p->size = size;
+	}
+
+out:
+	/* Our block is in the middle */
+	p->file_priv = file_priv;
+	return p;
+}
+
+struct mem_block *
+nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size,
+			int align2, struct drm_file *file_priv, int tail)
+{
+	struct mem_block *p;
+	uint64_t mask = (1 << align2) - 1;
+
+	if (!heap)
+		return NULL;
+
+	if (tail) {
+		list_for_each_prev(p, heap) {
+			uint64_t start = ((p->start + p->size) - size) & ~mask;
+
+			if (p->file_priv == NULL && start >= p->start &&
+			    start + size <= p->start + p->size)
+				return split_block(p, start, size, file_priv);
+		}
+	} else {
+		list_for_each(p, heap) {
+			uint64_t start = (p->start + mask) & ~mask;
+
+			if (p->file_priv == NULL &&
+			    start + size <= p->start + p->size)
+				return split_block(p, start, size, file_priv);
+		}
+	}
+
+	return NULL;
+}
+
+void nouveau_mem_free_block(struct mem_block *p)
+{
+	p->file_priv = NULL;
+
+	/* Assumes a single contiguous range.  Needs a special file_priv in
+	 * 'heap' to stop it being subsumed.
+	 */
+	if (p->next->file_priv == NULL) {
+		struct mem_block *q = p->next;
+		p->size += q->size;
+		p->next = q->next;
+		p->next->prev = p;
+		kfree(q);
+	}
+
+	if (p->prev->file_priv == NULL) {
+		struct mem_block *q = p->prev;
+		q->size += p->size;
+		q->next = p->next;
+		q->next->prev = q;
+		kfree(p);
+	}
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
+			  uint64_t size)
+{
+	struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
+
+	if (!blocks)
+		return -ENOMEM;
+
+	*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
+	if (!*heap) {
+		kfree(blocks);
+		return -ENOMEM;
+	}
+
+	blocks->start = start;
+	blocks->size = size;
+	blocks->file_priv = NULL;
+	blocks->next = blocks->prev = *heap;
+
+	memset(*heap, 0, sizeof(**heap));
+	(*heap)->file_priv = (struct drm_file *) -1;
+	(*heap)->next = (*heap)->prev = blocks;
+	return 0;
+}
+
+/*
+ * Free all blocks associated with the releasing file_priv
+ */
+void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
+{
+	struct mem_block *p;
+
+	if (!heap || !heap->next)
+		return;
+
+	list_for_each(p, heap) {
+		if (p->file_priv == file_priv)
+			p->file_priv = NULL;
+	}
+
+	/* Assumes a single contiguous range.  Needs a special file_priv in
+	 * 'heap' to stop it being subsumed.
+	 */
+	list_for_each(p, heap) {
+		while ((p->file_priv == NULL) &&
+					(p->next->file_priv == NULL) &&
+					(p->next != heap)) {
+			struct mem_block *q = p->next;
+			p->size += q->size;
+			p->next = q->next;
+			p->next->prev = p;
+			kfree(q);
+		}
+	}
+}
+
+/*
+ * NV10-NV40 tiling helpers
+ */
+
+static void
+nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			   uint32_t size, uint32_t pitch)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
+
+	tile->addr = addr;
+	tile->size = size;
+	tile->used = !!pitch;
+	nouveau_fence_unref((void **)&tile->fence);
+
+	if (!pfifo->cache_flush(dev))
+		return;
+
+	pfifo->reassign(dev, false);
+	pfifo->cache_flush(dev);
+	pfifo->cache_pull(dev, false);
+
+	nouveau_wait_for_idle(dev);
+
+	pgraph->set_region_tiling(dev, i, addr, size, pitch);
+	pfb->set_region_tiling(dev, i, addr, size, pitch);
+
+	pfifo->cache_pull(dev, true);
+	pfifo->reassign(dev, true);
+}
+
+struct nouveau_tile_reg *
+nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
+		    uint32_t pitch)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL;
+	int i;
+
+	spin_lock(&dev_priv->tile.lock);
+
+	for (i = 0; i < pfb->num_tiles; i++) {
+		if (tile[i].used)
+			/* Tile region in use. */
+			continue;
+
+		if (tile[i].fence &&
+		    !nouveau_fence_signalled(tile[i].fence, NULL))
+			/* Pending tile region. */
+			continue;
+
+		if (max(tile[i].addr, addr) <
+		    min(tile[i].addr + tile[i].size, addr + size))
+			/* Kill an intersecting tile region. */
+			nv10_mem_set_region_tiling(dev, i, 0, 0, 0);
+
+		if (pitch && !found) {
+			/* Free tile region. */
+			nv10_mem_set_region_tiling(dev, i, addr, size, pitch);
+			found = &tile[i];
+		}
+	}
+
+	spin_unlock(&dev_priv->tile.lock);
+
+	return found;
+}
+
+void
+nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile,
+		       struct nouveau_fence *fence)
+{
+	if (fence) {
+		/* Mark it as pending. */
+		tile->fence = fence;
+		nouveau_fence_ref(fence);
+	}
+
+	tile->used = false;
+}
+
+/*
+ * NV50 VM helpers
+ */
+int
+nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
+			uint32_t flags, uint64_t phys)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *pgt;
+	unsigned block;
+	int i;
+
+	virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
+	size = (size >> 16) << 1;
+
+	phys |= ((uint64_t)flags << 32);
+	phys |= 1;
+	if (dev_priv->vram_sys_base) {
+		phys += dev_priv->vram_sys_base;
+		phys |= 0x30;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	while (size) {
+		unsigned offset_h = upper_32_bits(phys);
+		unsigned offset_l = lower_32_bits(phys);
+		unsigned pte, end;
+
+		for (i = 7; i >= 0; i--) {
+			block = 1 << (i + 1);
+			if (size >= block && !(virt & (block - 1)))
+				break;
+		}
+		offset_l |= (i << 7);
+
+		phys += block << 15;
+		size -= block;
+
+		while (block) {
+			pgt = dev_priv->vm_vram_pt[virt >> 14];
+			pte = virt & 0x3ffe;
+
+			end = pte + block;
+			if (end > 16384)
+				end = 16384;
+			block -= (end - pte);
+			virt  += (end - pte);
+
+			while (pte < end) {
+				nv_wo32(dev, pgt, pte++, offset_l);
+				nv_wo32(dev, pgt, pte++, offset_h);
+			}
+		}
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, 0x100c80, 0x00050001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+		return -EBUSY;
+	}
+
+	nv_wr32(dev, 0x100c80, 0x00000001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+void
+nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *pgt;
+	unsigned pages, pte, end;
+
+	virt -= dev_priv->vm_vram_base;
+	pages = (size >> 16) << 1;
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	while (pages) {
+		pgt = dev_priv->vm_vram_pt[virt >> 29];
+		pte = (virt & 0x1ffe0000ULL) >> 15;
+
+		end = pte + pages;
+		if (end > 16384)
+			end = 16384;
+		pages -= (end - pte);
+		virt  += (end - pte) << 15;
+
+		while (pte < end)
+			nv_wo32(dev, pgt, pte++, 0);
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, 0x100c80, 0x00050001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+		return;
+	}
+
+	nv_wr32(dev, 0x100c80, 0x00000001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+	}
+}
+
+/*
+ * Cleanup everything
+ */
+void nouveau_mem_takedown(struct mem_block **heap)
+{
+	struct mem_block *p;
+
+	if (!*heap)
+		return;
+
+	for (p = (*heap)->next; p != *heap;) {
+		struct mem_block *q = p;
+		p = p->next;
+		kfree(q);
+	}
+
+	kfree(*heap);
+	*heap = NULL;
+}
+
+void nouveau_mem_close(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nouveau_bo_unpin(dev_priv->vga_ram);
+	nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+
+	ttm_bo_device_release(&dev_priv->ttm.bdev);
+
+	nouveau_ttm_global_release(dev_priv);
+
+	if (drm_core_has_AGP(dev) && dev->agp &&
+	    drm_core_check_feature(dev, DRIVER_MODESET)) {
+		struct drm_agp_mem *entry, *tempe;
+
+		/* Remove AGP resources, but leave dev->agp
+		   intact until drv_cleanup is called. */
+		list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
+			if (entry->bound)
+				drm_unbind_agp(entry->memory);
+			drm_free_agp(entry->memory, entry->pages);
+			kfree(entry);
+		}
+		INIT_LIST_HEAD(&dev->agp->memory);
+
+		if (dev->agp->acquired)
+			drm_agp_release(dev);
+
+		dev->agp->acquired = 0;
+		dev->agp->enabled = 0;
+	}
+
+	if (dev_priv->fb_mtrr) {
+		drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),
+			     drm_get_resource_len(dev, 1), DRM_MTRR_WC);
+		dev_priv->fb_mtrr = 0;
+	}
+}
+
+/*XXX won't work on BSD because of pci_read_config_dword */
+static uint32_t
+nouveau_mem_fb_amount_igp(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct pci_dev *bridge;
+	uint32_t mem;
+
+	bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
+	if (!bridge) {
+		NV_ERROR(dev, "no bridge device\n");
+		return 0;
+	}
+
+	if (dev_priv->flags&NV_NFORCE) {
+		pci_read_config_dword(bridge, 0x7C, &mem);
+		return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;
+	} else
+	if (dev_priv->flags&NV_NFORCE2) {
+		pci_read_config_dword(bridge, 0x84, &mem);
+		return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;
+	}
+
+	NV_ERROR(dev, "impossible!\n");
+	return 0;
+}
+
+/* returns the amount of FB ram in bytes */
+uint64_t nouveau_mem_fb_amount(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t boot0;
+
+	switch (dev_priv->card_type) {
+	case NV_04:
+		boot0 = nv_rd32(dev, NV03_BOOT_0);
+		if (boot0 & 0x00000100)
+			return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
+
+		switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) {
+		case NV04_BOOT_0_RAM_AMOUNT_32MB:
+			return 32 * 1024 * 1024;
+		case NV04_BOOT_0_RAM_AMOUNT_16MB:
+			return 16 * 1024 * 1024;
+		case NV04_BOOT_0_RAM_AMOUNT_8MB:
+			return 8 * 1024 * 1024;
+		case NV04_BOOT_0_RAM_AMOUNT_4MB:
+			return 4 * 1024 * 1024;
+		}
+		break;
+	case NV_10:
+	case NV_20:
+	case NV_30:
+	case NV_40:
+	case NV_50:
+	default:
+		if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
+			return nouveau_mem_fb_amount_igp(dev);
+		} else {
+			uint64_t mem;
+			mem = (nv_rd32(dev, NV04_FIFO_DATA) &
+					NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >>
+					NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT;
+			return mem * 1024 * 1024;
+		}
+		break;
+	}
+
+	NV_ERROR(dev,
+		"Unable to detect video ram size. Please report your setup to "
+							DRIVER_EMAIL "\n");
+	return 0;
+}
+
+#if __OS_HAS_AGP
+static void nouveau_mem_reset_agp(struct drm_device *dev)
+{
+	uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
+
+	saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1);
+	saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19);
+
+	/* clear busmaster bit */
+	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
+	/* clear SBA and AGP bits */
+	nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
+
+	/* power cycle pgraph, if enabled */
+	pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
+	if (pmc_enable & NV_PMC_ENABLE_PGRAPH) {
+		nv_wr32(dev, NV03_PMC_ENABLE,
+				pmc_enable & ~NV_PMC_ENABLE_PGRAPH);
+		nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
+				NV_PMC_ENABLE_PGRAPH);
+	}
+
+	/* and restore (gives effect of resetting AGP) */
+	nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
+	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
+}
+#endif
+
+int
+nouveau_mem_init_agp(struct drm_device *dev)
+{
+#if __OS_HAS_AGP
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_agp_info info;
+	struct drm_agp_mode mode;
+	int ret;
+
+	if (nouveau_noagp)
+		return 0;
+
+	nouveau_mem_reset_agp(dev);
+
+	if (!dev->agp->acquired) {
+		ret = drm_agp_acquire(dev);
+		if (ret) {
+			NV_ERROR(dev, "Unable to acquire AGP: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = drm_agp_info(dev, &info);
+	if (ret) {
+		NV_ERROR(dev, "Unable to get AGP info: %d\n", ret);
+		return ret;
+	}
+
+	/* see agp.h for the AGPSTAT_* modes available */
+	mode.mode = info.mode;
+	ret = drm_agp_enable(dev, mode);
+	if (ret) {
+		NV_ERROR(dev, "Unable to enable AGP: %d\n", ret);
+		return ret;
+	}
+
+	dev_priv->gart_info.type	= NOUVEAU_GART_AGP;
+	dev_priv->gart_info.aper_base	= info.aperture_base;
+	dev_priv->gart_info.aper_size	= info.aperture_size;
+#endif
+	return 0;
+}
+
+int
+nouveau_mem_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
+	int ret, dma_bits = 32;
+
+	dev_priv->fb_phys = drm_get_resource_start(dev, 1);
+	dev_priv->gart_info.type = NOUVEAU_GART_NONE;
+
+	if (dev_priv->card_type >= NV_50 &&
+	    pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
+		dma_bits = 40;
+
+	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits));
+	if (ret) {
+		NV_ERROR(dev, "Error setting DMA mask: %d\n", ret);
+		return ret;
+	}
+
+	ret = nouveau_ttm_global_init(dev_priv);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_device_init(&dev_priv->ttm.bdev,
+				 dev_priv->ttm.bo_global_ref.ref.object,
+				 &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET,
+				 dma_bits <= 32 ? true : false);
+	if (ret) {
+		NV_ERROR(dev, "Error initialising bo driver: %d\n", ret);
+		return ret;
+	}
+
+	INIT_LIST_HEAD(&dev_priv->ttm.bo_list);
+	spin_lock_init(&dev_priv->ttm.bo_list_lock);
+	spin_lock_init(&dev_priv->tile.lock);
+
+	dev_priv->fb_available_size = nouveau_mem_fb_amount(dev);
+
+	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
+	if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))
+		dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);
+	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
+
+	NV_INFO(dev, "%d MiB VRAM\n", (int)(dev_priv->fb_available_size >> 20));
+
+	/* remove reserved space at end of vram from available amount */
+	dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;
+	dev_priv->fb_aper_free = dev_priv->fb_available_size;
+
+	/* mappable vram */
+	ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+			     dev_priv->fb_available_size >> PAGE_SHIFT);
+	if (ret) {
+		NV_ERROR(dev, "Failed VRAM mm init: %d\n", ret);
+		return ret;
+	}
+
+	ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+			     0, 0, true, true, &dev_priv->vga_ram);
+	if (ret == 0)
+		ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_WARN(dev, "failed to reserve VGA memory\n");
+		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+	}
+
+	/* GART */
+#if !defined(__powerpc__) && !defined(__ia64__)
+	if (drm_device_is_agp(dev) && dev->agp) {
+		ret = nouveau_mem_init_agp(dev);
+		if (ret)
+			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
+	}
+#endif
+
+	if (dev_priv->gart_info.type == NOUVEAU_GART_NONE) {
+		ret = nouveau_sgdma_init(dev);
+		if (ret) {
+			NV_ERROR(dev, "Error initialising PCI(E): %d\n", ret);
+			return ret;
+		}
+	}
+
+	NV_INFO(dev, "%d MiB GART (aperture)\n",
+		(int)(dev_priv->gart_info.aper_size >> 20));
+	dev_priv->gart_info.aper_free = dev_priv->gart_info.aper_size;
+
+	ret = ttm_bo_init_mm(bdev, TTM_PL_TT,
+			     dev_priv->gart_info.aper_size >> PAGE_SHIFT);
+	if (ret) {
+		NV_ERROR(dev, "Failed TT mm init: %d\n", ret);
+		return ret;
+	}
+
+	dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
+					 drm_get_resource_len(dev, 1),
+					 DRM_MTRR_WC);
+
+	return 0;
+}
+
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_i2c.h"
+#include "nouveau_hw.h"
+
+static void
+nv04_i2c_setscl(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+	uint8_t val;
+
+	val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
+	NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
+}
+
+static void
+nv04_i2c_setsda(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+	uint8_t val;
+
+	val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
+	NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
+}
+
+static int
+nv04_i2c_getscl(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4);
+}
+
+static int
+nv04_i2c_getsda(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8);
+}
+
+static void
+nv4e_i2c_setscl(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+	uint8_t val;
+
+	val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
+	nv_wr32(dev, i2c->wr, val | 0x01);
+}
+
+static void
+nv4e_i2c_setsda(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+	uint8_t val;
+
+	val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
+	nv_wr32(dev, i2c->wr, val | 0x01);
+}
+
+static int
+nv4e_i2c_getscl(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!((nv_rd32(dev, i2c->rd) >> 16) & 4);
+}
+
+static int
+nv4e_i2c_getsda(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
+}
+
+static int
+nv50_i2c_getscl(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!(nv_rd32(dev, i2c->rd) & 1);
+}
+
+
+static int
+nv50_i2c_getsda(void *data)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	return !!(nv_rd32(dev, i2c->rd) & 2);
+}
+
+static void
+nv50_i2c_setscl(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
+}
+
+static void
+nv50_i2c_setsda(void *data, int state)
+{
+	struct nouveau_i2c_chan *i2c = data;
+	struct drm_device *dev = i2c->dev;
+
+	nv_wr32(dev, i2c->wr,
+			(nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0));
+	i2c->data = state;
+}
+
+static const uint32_t nv50_i2c_port[] = {
+	0x00e138, 0x00e150, 0x00e168, 0x00e180,
+	0x00e254, 0x00e274, 0x00e764, 0x00e780,
+	0x00e79c, 0x00e7b8
+};
+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
+
+int
+nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_i2c_chan *i2c;
+	int ret;
+
+	if (entry->chan)
+		return -EEXIST;
+
+	if (dev_priv->card_type == NV_50 && entry->read >= NV50_I2C_PORTS) {
+		NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
+		return -EINVAL;
+	}
+
+	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+	if (i2c == NULL)
+		return -ENOMEM;
+
+	switch (entry->port_type) {
+	case 0:
+		i2c->algo.bit.setsda = nv04_i2c_setsda;
+		i2c->algo.bit.setscl = nv04_i2c_setscl;
+		i2c->algo.bit.getsda = nv04_i2c_getsda;
+		i2c->algo.bit.getscl = nv04_i2c_getscl;
+		i2c->rd = entry->read;
+		i2c->wr = entry->write;
+		break;
+	case 4:
+		i2c->algo.bit.setsda = nv4e_i2c_setsda;
+		i2c->algo.bit.setscl = nv4e_i2c_setscl;
+		i2c->algo.bit.getsda = nv4e_i2c_getsda;
+		i2c->algo.bit.getscl = nv4e_i2c_getscl;
+		i2c->rd = 0x600800 + entry->read;
+		i2c->wr = 0x600800 + entry->write;
+		break;
+	case 5:
+		i2c->algo.bit.setsda = nv50_i2c_setsda;
+		i2c->algo.bit.setscl = nv50_i2c_setscl;
+		i2c->algo.bit.getsda = nv50_i2c_getsda;
+		i2c->algo.bit.getscl = nv50_i2c_getscl;
+		i2c->rd = nv50_i2c_port[entry->read];
+		i2c->wr = i2c->rd;
+		break;
+	case 6:
+		i2c->rd = entry->read;
+		i2c->wr = entry->write;
+		break;
+	default:
+		NV_ERROR(dev, "DCB I2C port type %d unknown\n",
+			 entry->port_type);
+		kfree(i2c);
+		return -EINVAL;
+	}
+
+	snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
+		 "nouveau-%s-%d", pci_name(dev->pdev), index);
+	i2c->adapter.owner = THIS_MODULE;
+	i2c->adapter.dev.parent = &dev->pdev->dev;
+	i2c->dev = dev;
+	i2c_set_adapdata(&i2c->adapter, i2c);
+
+	if (entry->port_type < 6) {
+		i2c->adapter.algo_data = &i2c->algo.bit;
+		i2c->algo.bit.udelay = 40;
+		i2c->algo.bit.timeout = usecs_to_jiffies(5000);
+		i2c->algo.bit.data = i2c;
+		ret = i2c_bit_add_bus(&i2c->adapter);
+	} else {
+		i2c->adapter.algo_data = &i2c->algo.dp;
+		i2c->algo.dp.running = false;
+		i2c->algo.dp.address = 0;
+		i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch;
+		ret = i2c_dp_aux_add_bus(&i2c->adapter);
+	}
+
+	if (ret) {
+		NV_ERROR(dev, "Failed to register i2c %d\n", index);
+		kfree(i2c);
+		return ret;
+	}
+
+	entry->chan = i2c;
+	return 0;
+}
+
+void
+nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry)
+{
+	if (!entry->chan)
+		return;
+
+	i2c_del_adapter(&entry->chan->adapter);
+	kfree(entry->chan);
+	entry->chan = NULL;
+}
+
+struct nouveau_i2c_chan *
+nouveau_i2c_find(struct drm_device *dev, int index)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+
+	if (index > DCB_MAX_NUM_I2C_ENTRIES)
+		return NULL;
+
+	if (!bios->bdcb.dcb.i2c[index].chan) {
+		if (nouveau_i2c_init(dev, &bios->bdcb.dcb.i2c[index], index))
+			return NULL;
+	}
+
+	return bios->bdcb.dcb.i2c[index].chan;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_display.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_display.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NV50_DISPLAY_H__
+#define __NV50_DISPLAY_H__
+
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include "nouveau_reg.h"
+#include "nouveau_crtc.h"
+#include "nv50_evo.h"
+
+void nv50_display_irq_handler(struct drm_device *dev);
+void nv50_display_irq_handler_bh(struct work_struct *work);
+int nv50_display_init(struct drm_device *dev);
+int nv50_display_create(struct drm_device *dev);
+int nv50_display_destroy(struct drm_device *dev);
+int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
+int nv50_crtc_set_clock(struct drm_device *, int head, int pclk);
+
+#endif /* __NV50_DISPLAY_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv40_grctx.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv40_grctx.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+/* NVIDIA context programs handle a number of other conditions which are
+ * not implemented in our versions.  It's not clear why NVIDIA context
+ * programs have this code, nor whether it's strictly necessary for
+ * correct operation.  We'll implement additional handling if/when we
+ * discover it's necessary.
+ *
+ * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state"
+ *   flag is set, this gets saved into the context.
+ * - On context save, the context program for all cards load nsource
+ *   into a flag register and check for ILLEGAL_MTHD.  If it's set,
+ *   opcode 0x60000d is called before resuming normal operation.
+ * - Some context programs check more conditions than the above.  NV44
+ *   checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001))
+ *   and calls 0x60000d before resuming normal operation.
+ * - At the very beginning of NVIDIA's context programs, flag 9 is checked
+ *   and if true 0x800001 is called with count=0, pos=0, the flag is cleared
+ *   and then the ctxprog is aborted.  It looks like a complicated NOP,
+ *   its purpose is unknown.
+ * - In the section of code that loads the per-vs state, NVIDIA check
+ *   flag 10.  If it's set, they only transfer the small 0x300 byte block
+ *   of state + the state for a single vs as opposed to the state for
+ *   all vs units.  It doesn't seem likely that it'll occur in normal
+ *   operation, especially seeing as it appears NVIDIA may have screwed
+ *   up the ctxprogs for some cards and have an invalid instruction
+ *   rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction.
+ * - There's a number of places where context offset 0 (where we place
+ *   the PRAMIN offset of the context) is loaded into either 0x408000,
+ *   0x408004 or 0x408008.  Not sure what's up there either.
+ * - The ctxprogs for some cards save 0x400a00 again during the cleanup
+ *   path for auto-loadctx.
+ */
+
+#define CP_FLAG_CLEAR                 0
+#define CP_FLAG_SET                   1
+#define CP_FLAG_SWAP_DIRECTION        ((0 * 32) + 0)
+#define CP_FLAG_SWAP_DIRECTION_LOAD   0
+#define CP_FLAG_SWAP_DIRECTION_SAVE   1
+#define CP_FLAG_USER_SAVE             ((0 * 32) + 5)
+#define CP_FLAG_USER_SAVE_NOT_PENDING 0
+#define CP_FLAG_USER_SAVE_PENDING     1
+#define CP_FLAG_USER_LOAD             ((0 * 32) + 6)
+#define CP_FLAG_USER_LOAD_NOT_PENDING 0
+#define CP_FLAG_USER_LOAD_PENDING     1
+#define CP_FLAG_STATUS                ((3 * 32) + 0)
+#define CP_FLAG_STATUS_IDLE           0
+#define CP_FLAG_STATUS_BUSY           1
+#define CP_FLAG_AUTO_SAVE             ((3 * 32) + 4)
+#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
+#define CP_FLAG_AUTO_SAVE_PENDING     1
+#define CP_FLAG_AUTO_LOAD             ((3 * 32) + 5)
+#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
+#define CP_FLAG_AUTO_LOAD_PENDING     1
+#define CP_FLAG_UNK54                 ((3 * 32) + 6)
+#define CP_FLAG_UNK54_CLEAR           0
+#define CP_FLAG_UNK54_SET             1
+#define CP_FLAG_ALWAYS                ((3 * 32) + 8)
+#define CP_FLAG_ALWAYS_FALSE          0
+#define CP_FLAG_ALWAYS_TRUE           1
+#define CP_FLAG_UNK57                 ((3 * 32) + 9)
+#define CP_FLAG_UNK57_CLEAR           0
+#define CP_FLAG_UNK57_SET             1
+
+#define CP_CTX                   0x00100000
+#define CP_CTX_COUNT             0x000fc000
+#define CP_CTX_COUNT_SHIFT               14
+#define CP_CTX_REG               0x00003fff
+#define CP_LOAD_SR               0x00200000
+#define CP_LOAD_SR_VALUE         0x000fffff
+#define CP_BRA                   0x00400000
+#define CP_BRA_IP                0x0000ff00
+#define CP_BRA_IP_SHIFT                   8
+#define CP_BRA_IF_CLEAR          0x00000080
+#define CP_BRA_FLAG              0x0000007f
+#define CP_WAIT                  0x00500000
+#define CP_WAIT_SET              0x00000080
+#define CP_WAIT_FLAG             0x0000007f
+#define CP_SET                   0x00700000
+#define CP_SET_1                 0x00000080
+#define CP_SET_FLAG              0x0000007f
+#define CP_NEXT_TO_SWAP          0x00600007
+#define CP_NEXT_TO_CURRENT       0x00600009
+#define CP_SET_CONTEXT_POINTER   0x0060000a
+#define CP_END                   0x0060000e
+#define CP_LOAD_MAGIC_UNK01      0x00800001 /* unknown */
+#define CP_LOAD_MAGIC_NV44TCL    0x00800029 /* per-vs state (0x4497) */
+#define CP_LOAD_MAGIC_NV40TCL    0x00800041 /* per-vs state (0x4097) */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_grctx.h"
+
+/* TODO:
+ *  - get vs count from 0x1540
+ *  - document unimplemented bits compared to nvidia
+ *    - nsource handling
+ *    - R0 & 0x0200 handling
+ *    - single-vs handling
+ *    - 400314 bit 0
+ */
+
+static int
+nv40_graph_4097(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if ((dev_priv->chipset & 0xf0) == 0x60)
+		return 0;
+
+	return !!(0x0baf & (1 << dev_priv->chipset));
+}
+
+static int
+nv40_graph_vs_count(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->chipset) {
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		return 8;
+	case 0x40:
+		return 6;
+	case 0x41:
+	case 0x42:
+		return 5;
+	case 0x43:
+	case 0x44:
+	case 0x46:
+	case 0x4a:
+		return 3;
+	case 0x4c:
+	case 0x4e:
+	case 0x67:
+	default:
+		return 1;
+	}
+}
+
+
+enum cp_label {
+	cp_check_load = 1,
+	cp_setup_auto_load,
+	cp_setup_load,
+	cp_setup_save,
+	cp_swap_state,
+	cp_swap_state3d_3_is_save,
+	cp_prepare_exit,
+	cp_exit,
+};
+
+static void
+nv40_graph_construct_general(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+
+	cp_ctx(ctx, 0x4000a4, 1);
+	gr_def(ctx, 0x4000a4, 0x00000008);
+	cp_ctx(ctx, 0x400144, 58);
+	gr_def(ctx, 0x400144, 0x00000001);
+	cp_ctx(ctx, 0x400314, 1);
+	gr_def(ctx, 0x400314, 0x00000000);
+	cp_ctx(ctx, 0x400400, 10);
+	cp_ctx(ctx, 0x400480, 10);
+	cp_ctx(ctx, 0x400500, 19);
+	gr_def(ctx, 0x400514, 0x00040000);
+	gr_def(ctx, 0x400524, 0x55555555);
+	gr_def(ctx, 0x400528, 0x55555555);
+	gr_def(ctx, 0x40052c, 0x55555555);
+	gr_def(ctx, 0x400530, 0x55555555);
+	cp_ctx(ctx, 0x400560, 6);
+	gr_def(ctx, 0x400568, 0x0000ffff);
+	gr_def(ctx, 0x40056c, 0x0000ffff);
+	cp_ctx(ctx, 0x40057c, 5);
+	cp_ctx(ctx, 0x400710, 3);
+	gr_def(ctx, 0x400710, 0x20010001);
+	gr_def(ctx, 0x400714, 0x0f73ef00);
+	cp_ctx(ctx, 0x400724, 1);
+	gr_def(ctx, 0x400724, 0x02008821);
+	cp_ctx(ctx, 0x400770, 3);
+	if (dev_priv->chipset == 0x40) {
+		cp_ctx(ctx, 0x400814, 4);
+		cp_ctx(ctx, 0x400828, 5);
+		cp_ctx(ctx, 0x400840, 5);
+		gr_def(ctx, 0x400850, 0x00000040);
+		cp_ctx(ctx, 0x400858, 4);
+		gr_def(ctx, 0x400858, 0x00000040);
+		gr_def(ctx, 0x40085c, 0x00000040);
+		gr_def(ctx, 0x400864, 0x80000000);
+		cp_ctx(ctx, 0x40086c, 9);
+		gr_def(ctx, 0x40086c, 0x80000000);
+		gr_def(ctx, 0x400870, 0x80000000);
+		gr_def(ctx, 0x400874, 0x80000000);
+		gr_def(ctx, 0x400878, 0x80000000);
+		gr_def(ctx, 0x400888, 0x00000040);
+		gr_def(ctx, 0x40088c, 0x80000000);
+		cp_ctx(ctx, 0x4009c0, 8);
+		gr_def(ctx, 0x4009cc, 0x80000000);
+		gr_def(ctx, 0x4009dc, 0x80000000);
+	} else {
+		cp_ctx(ctx, 0x400840, 20);
+		if (!nv40_graph_4097(ctx->dev)) {
+			for (i = 0; i < 8; i++)
+				gr_def(ctx, 0x400860 + (i * 4), 0x00000001);
+		}
+		gr_def(ctx, 0x400880, 0x00000040);
+		gr_def(ctx, 0x400884, 0x00000040);
+		gr_def(ctx, 0x400888, 0x00000040);
+		cp_ctx(ctx, 0x400894, 11);
+		gr_def(ctx, 0x400894, 0x00000040);
+		if (nv40_graph_4097(ctx->dev)) {
+			for (i = 0; i < 8; i++)
+				gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000);
+		}
+		cp_ctx(ctx, 0x4008e0, 2);
+		cp_ctx(ctx, 0x4008f8, 2);
+		if (dev_priv->chipset == 0x4c ||
+		    (dev_priv->chipset & 0xf0) == 0x60)
+			cp_ctx(ctx, 0x4009f8, 1);
+	}
+	cp_ctx(ctx, 0x400a00, 73);
+	gr_def(ctx, 0x400b0c, 0x0b0b0b0c);
+	cp_ctx(ctx, 0x401000, 4);
+	cp_ctx(ctx, 0x405004, 1);
+	switch (dev_priv->chipset) {
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		cp_ctx(ctx, 0x403448, 1);
+		gr_def(ctx, 0x403448, 0x00001010);
+		break;
+	default:
+		cp_ctx(ctx, 0x403440, 1);
+		switch (dev_priv->chipset) {
+		case 0x40:
+			gr_def(ctx, 0x403440, 0x00000010);
+			break;
+		case 0x44:
+		case 0x46:
+		case 0x4a:
+			gr_def(ctx, 0x403440, 0x00003010);
+			break;
+		case 0x41:
+		case 0x42:
+		case 0x43:
+		case 0x4c:
+		case 0x4e:
+		case 0x67:
+		default:
+			gr_def(ctx, 0x403440, 0x00001010);
+			break;
+		}
+		break;
+	}
+}
+
+static void
+nv40_graph_construct_state3d(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+
+	if (dev_priv->chipset == 0x40) {
+		cp_ctx(ctx, 0x401880, 51);
+		gr_def(ctx, 0x401940, 0x00000100);
+	} else
+	if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 ||
+	    dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
+		cp_ctx(ctx, 0x401880, 32);
+		for (i = 0; i < 16; i++)
+			gr_def(ctx, 0x401880 + (i * 4), 0x00000111);
+		if (dev_priv->chipset == 0x46)
+			cp_ctx(ctx, 0x401900, 16);
+		cp_ctx(ctx, 0x401940, 3);
+	}
+	cp_ctx(ctx, 0x40194c, 18);
+	gr_def(ctx, 0x401954, 0x00000111);
+	gr_def(ctx, 0x401958, 0x00080060);
+	gr_def(ctx, 0x401974, 0x00000080);
+	gr_def(ctx, 0x401978, 0xffff0000);
+	gr_def(ctx, 0x40197c, 0x00000001);
+	gr_def(ctx, 0x401990, 0x46400000);
+	if (dev_priv->chipset == 0x40) {
+		cp_ctx(ctx, 0x4019a0, 2);
+		cp_ctx(ctx, 0x4019ac, 5);
+	} else {
+		cp_ctx(ctx, 0x4019a0, 1);
+		cp_ctx(ctx, 0x4019b4, 3);
+	}
+	gr_def(ctx, 0x4019bc, 0xffff0000);
+	switch (dev_priv->chipset) {
+	case 0x46:
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		cp_ctx(ctx, 0x4019c0, 18);
+		for (i = 0; i < 16; i++)
+			gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888);
+		break;
+	}
+	cp_ctx(ctx, 0x401a08, 8);
+	gr_def(ctx, 0x401a10, 0x0fff0000);
+	gr_def(ctx, 0x401a14, 0x0fff0000);
+	gr_def(ctx, 0x401a1c, 0x00011100);
+	cp_ctx(ctx, 0x401a2c, 4);
+	cp_ctx(ctx, 0x401a44, 26);
+	for (i = 0; i < 16; i++)
+		gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000);
+	gr_def(ctx, 0x401a8c, 0x4b7fffff);
+	if (dev_priv->chipset == 0x40) {
+		cp_ctx(ctx, 0x401ab8, 3);
+	} else {
+		cp_ctx(ctx, 0x401ab8, 1);
+		cp_ctx(ctx, 0x401ac0, 1);
+	}
+	cp_ctx(ctx, 0x401ad0, 8);
+	gr_def(ctx, 0x401ad0, 0x30201000);
+	gr_def(ctx, 0x401ad4, 0x70605040);
+	gr_def(ctx, 0x401ad8, 0xb8a89888);
+	gr_def(ctx, 0x401adc, 0xf8e8d8c8);
+	cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1);
+	gr_def(ctx, 0x401b10, 0x40100000);
+	cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5);
+	gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ?
+			      0x00000004 : 0x00000000);
+	cp_ctx(ctx, 0x401b30, 25);
+	gr_def(ctx, 0x401b34, 0x0000ffff);
+	gr_def(ctx, 0x401b68, 0x435185d6);
+	gr_def(ctx, 0x401b6c, 0x2155b699);
+	gr_def(ctx, 0x401b70, 0xfedcba98);
+	gr_def(ctx, 0x401b74, 0x00000098);
+	gr_def(ctx, 0x401b84, 0xffffffff);
+	gr_def(ctx, 0x401b88, 0x00ff7000);
+	gr_def(ctx, 0x401b8c, 0x0000ffff);
+	if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a &&
+	    dev_priv->chipset != 0x4e)
+		cp_ctx(ctx, 0x401b94, 1);
+	cp_ctx(ctx, 0x401b98, 8);
+	gr_def(ctx, 0x401b9c, 0x00ff0000);
+	cp_ctx(ctx, 0x401bc0, 9);
+	gr_def(ctx, 0x401be0, 0x00ffff00);
+	cp_ctx(ctx, 0x401c00, 192);
+	for (i = 0; i < 16; i++) { /* fragment texture units */
+		gr_def(ctx, 0x401c40 + (i * 4), 0x00018488);
+		gr_def(ctx, 0x401c80 + (i * 4), 0x00028202);
+		gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4);
+		gr_def(ctx, 0x401d40 + (i * 4), 0x01012000);
+		gr_def(ctx, 0x401d80 + (i * 4), 0x00080008);
+		gr_def(ctx, 0x401e00 + (i * 4), 0x00100008);
+	}
+	for (i = 0; i < 4; i++) { /* vertex texture units */
+		gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80);
+		gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202);
+		gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008);
+		gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008);
+	}
+	cp_ctx(ctx, 0x400f5c, 3);
+	gr_def(ctx, 0x400f5c, 0x00000002);
+	cp_ctx(ctx, 0x400f84, 1);
+}
+
+static void
+nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+
+	cp_ctx(ctx, 0x402000, 1);
+	cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2);
+	switch (dev_priv->chipset) {
+	case 0x40:
+		gr_def(ctx, 0x402404, 0x00000001);
+		break;
+	case 0x4c:
+	case 0x4e:
+	case 0x67:
+		gr_def(ctx, 0x402404, 0x00000020);
+		break;
+	case 0x46:
+	case 0x49:
+	case 0x4b:
+		gr_def(ctx, 0x402404, 0x00000421);
+		break;
+	default:
+		gr_def(ctx, 0x402404, 0x00000021);
+	}
+	if (dev_priv->chipset != 0x40)
+		gr_def(ctx, 0x402408, 0x030c30c3);
+	switch (dev_priv->chipset) {
+	case 0x44:
+	case 0x46:
+	case 0x4a:
+	case 0x4c:
+	case 0x4e:
+	case 0x67:
+		cp_ctx(ctx, 0x402440, 1);
+		gr_def(ctx, 0x402440, 0x00011001);
+		break;
+	default:
+		break;
+	}
+	cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9);
+	gr_def(ctx, 0x402488, 0x3e020200);
+	gr_def(ctx, 0x40248c, 0x00ffffff);
+	switch (dev_priv->chipset) {
+	case 0x40:
+		gr_def(ctx, 0x402490, 0x60103f00);
+		break;
+	case 0x47:
+		gr_def(ctx, 0x402490, 0x40103f00);
+		break;
+	case 0x41:
+	case 0x42:
+	case 0x49:
+	case 0x4b:
+		gr_def(ctx, 0x402490, 0x20103f00);
+		break;
+	default:
+		gr_def(ctx, 0x402490, 0x0c103f00);
+		break;
+	}
+	gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ?
+			      0x00020000 : 0x00040000);
+	cp_ctx(ctx, 0x402500, 31);
+	gr_def(ctx, 0x402530, 0x00008100);
+	if (dev_priv->chipset == 0x40)
+		cp_ctx(ctx, 0x40257c, 6);
+	cp_ctx(ctx, 0x402594, 16);
+	cp_ctx(ctx, 0x402800, 17);
+	gr_def(ctx, 0x402800, 0x00000001);
+	switch (dev_priv->chipset) {
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		cp_ctx(ctx, 0x402864, 1);
+		gr_def(ctx, 0x402864, 0x00001001);
+		cp_ctx(ctx, 0x402870, 3);
+		gr_def(ctx, 0x402878, 0x00000003);
+		if (dev_priv->chipset != 0x47) { /* belong at end!! */
+			cp_ctx(ctx, 0x402900, 1);
+			cp_ctx(ctx, 0x402940, 1);
+			cp_ctx(ctx, 0x402980, 1);
+			cp_ctx(ctx, 0x4029c0, 1);
+			cp_ctx(ctx, 0x402a00, 1);
+			cp_ctx(ctx, 0x402a40, 1);
+			cp_ctx(ctx, 0x402a80, 1);
+			cp_ctx(ctx, 0x402ac0, 1);
+		}
+		break;
+	case 0x40:
+		cp_ctx(ctx, 0x402844, 1);
+		gr_def(ctx, 0x402844, 0x00000001);
+		cp_ctx(ctx, 0x402850, 1);
+		break;
+	default:
+		cp_ctx(ctx, 0x402844, 1);
+		gr_def(ctx, 0x402844, 0x00001001);
+		cp_ctx(ctx, 0x402850, 2);
+		gr_def(ctx, 0x402854, 0x00000003);
+		break;
+	}
+
+	cp_ctx(ctx, 0x402c00, 4);
+	gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ?
+			      0x80800001 : 0x00888001);
+	switch (dev_priv->chipset) {
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		cp_ctx(ctx, 0x402c20, 40);
+		for (i = 0; i < 32; i++)
+			gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff);
+		cp_ctx(ctx, 0x4030b8, 13);
+		gr_def(ctx, 0x4030dc, 0x00000005);
+		gr_def(ctx, 0x4030e8, 0x0000ffff);
+		break;
+	default:
+		cp_ctx(ctx, 0x402c10, 4);
+		if (dev_priv->chipset == 0x40)
+			cp_ctx(ctx, 0x402c20, 36);
+		else
+		if (dev_priv->chipset <= 0x42)
+			cp_ctx(ctx, 0x402c20, 24);
+		else
+		if (dev_priv->chipset <= 0x4a)
+			cp_ctx(ctx, 0x402c20, 16);
+		else
+			cp_ctx(ctx, 0x402c20, 8);
+		cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13);
+		gr_def(ctx, 0x402cd4, 0x00000005);
+		if (dev_priv->chipset != 0x40)
+			gr_def(ctx, 0x402ce0, 0x0000ffff);
+		break;
+	}
+
+	cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3);
+	cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3);
+	cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev));
+	for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++)
+		gr_def(ctx, 0x403420 + (i * 4), 0x00005555);
+
+	if (dev_priv->chipset != 0x40) {
+		cp_ctx(ctx, 0x403600, 1);
+		gr_def(ctx, 0x403600, 0x00000001);
+	}
+	cp_ctx(ctx, 0x403800, 1);
+
+	cp_ctx(ctx, 0x403c18, 1);
+	gr_def(ctx, 0x403c18, 0x00000001);
+	switch (dev_priv->chipset) {
+	case 0x46:
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		cp_ctx(ctx, 0x405018, 1);
+		gr_def(ctx, 0x405018, 0x08e00001);
+		cp_ctx(ctx, 0x405c24, 1);
+		gr_def(ctx, 0x405c24, 0x000e3000);
+		break;
+	}
+	if (dev_priv->chipset != 0x4e)
+		cp_ctx(ctx, 0x405800, 11);
+	cp_ctx(ctx, 0x407000, 1);
+}
+
+static void
+nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx)
+{
+	int len = nv40_graph_4097(ctx->dev) ? 0x0684 : 0x0084;
+
+	cp_out (ctx, 0x300000);
+	cp_lsr (ctx, len - 4);
+	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save);
+	cp_lsr (ctx, len);
+	cp_name(ctx, cp_swap_state3d_3_is_save);
+	cp_out (ctx, 0x800001);
+
+	ctx->ctxvals_pos += len;
+}
+
+static void
+nv40_graph_construct_shader(struct nouveau_grctx *ctx)
+{
+	struct drm_device *dev = ctx->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *obj = ctx->data;
+	int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset;
+	int offset, i;
+
+	vs_nr    = nv40_graph_vs_count(ctx->dev);
+	vs_nr_b0 = 363;
+	vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64;
+	if (dev_priv->chipset == 0x40) {
+		b0_offset = 0x2200/4; /* 33a0 */
+		b1_offset = 0x55a0/4; /* 1500 */
+		vs_len = 0x6aa0/4;
+	} else
+	if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) {
+		b0_offset = 0x2200/4; /* 2200 */
+		b1_offset = 0x4400/4; /* 0b00 */
+		vs_len = 0x4f00/4;
+	} else {
+		b0_offset = 0x1d40/4; /* 2200 */
+		b1_offset = 0x3f40/4; /* 0b00 : 0a40 */
+		vs_len = nv40_graph_4097(dev) ? 0x4a40/4 : 0x4980/4;
+	}
+
+	cp_lsr(ctx, vs_len * vs_nr + 0x300/4);
+	cp_out(ctx, nv40_graph_4097(dev) ? 0x800041 : 0x800029);
+
+	offset = ctx->ctxvals_pos;
+	ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len));
+
+	if (ctx->mode != NOUVEAU_GRCTX_VALS)
+		return;
+
+	offset += 0x0280/4;
+	for (i = 0; i < 16; i++, offset += 2)
+		nv_wo32(dev, obj, offset, 0x3f800000);
+
+	for (vs = 0; vs < vs_nr; vs++, offset += vs_len) {
+		for (i = 0; i < vs_nr_b0 * 6; i += 6)
+			nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001);
+		for (i = 0; i < vs_nr_b1 * 4; i += 4)
+			nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000);
+	}
+}
+
+void
+nv40_grctx_init(struct nouveau_grctx *ctx)
+{
+	/* decide whether we're loading/unloading the context */
+	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
+	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
+
+	cp_name(ctx, cp_check_load);
+	cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
+	cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
+	cp_bra (ctx, ALWAYS, TRUE, cp_exit);
+
+	/* setup for context load */
+	cp_name(ctx, cp_setup_auto_load);
+	cp_wait(ctx, STATUS, IDLE);
+	cp_out (ctx, CP_NEXT_TO_SWAP);
+	cp_name(ctx, cp_setup_load);
+	cp_wait(ctx, STATUS, IDLE);
+	cp_set (ctx, SWAP_DIRECTION, LOAD);
+	cp_out (ctx, 0x00910880); /* ?? */
+	cp_out (ctx, 0x00901ffe); /* ?? */
+	cp_out (ctx, 0x01940000); /* ?? */
+	cp_lsr (ctx, 0x20);
+	cp_out (ctx, 0x0060000b); /* ?? */
+	cp_wait(ctx, UNK57, CLEAR);
+	cp_out (ctx, 0x0060000c); /* ?? */
+	cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
+
+	/* setup for context save */
+	cp_name(ctx, cp_setup_save);
+	cp_set (ctx, SWAP_DIRECTION, SAVE);
+
+	/* general PGRAPH state */
+	cp_name(ctx, cp_swap_state);
+	cp_pos (ctx, 0x00020/4);
+	nv40_graph_construct_general(ctx);
+	cp_wait(ctx, STATUS, IDLE);
+
+	/* 3D state, block 1 */
+	cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit);
+	nv40_graph_construct_state3d(ctx);
+	cp_wait(ctx, STATUS, IDLE);
+
+	/* 3D state, block 2 */
+	nv40_graph_construct_state3d_2(ctx);
+
+	/* Some other block of "random" state */
+	nv40_graph_construct_state3d_3(ctx);
+
+	/* Per-vertex shader state */
+	cp_pos (ctx, ctx->ctxvals_pos);
+	nv40_graph_construct_shader(ctx);
+
+	/* pre-exit state updates */
+	cp_name(ctx, cp_prepare_exit);
+	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
+	cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
+	cp_out (ctx, CP_NEXT_TO_CURRENT);
+
+	cp_name(ctx, cp_exit);
+	cp_set (ctx, USER_SAVE, NOT_PENDING);
+	cp_set (ctx, USER_LOAD, NOT_PENDING);
+	cp_out (ctx, CP_END);
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -0,0 +1,6066 @@
+/*
+ * Copyright 2005-2006 Erik Waling
+ * Copyright 2006 Stephane Marchesin
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * 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 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 "drmP.h"
+#define NV_DEBUG_NOTRACE
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+
+/* these defines are made up */
+#define NV_CIO_CRE_44_HEADA 0x0
+#define NV_CIO_CRE_44_HEADB 0x3
+#define FEATURE_MOBILE 0x10	/* also FEATURE_QUADRO for BMP */
+#define LEGACY_I2C_CRT 0x80
+#define LEGACY_I2C_PANEL 0x81
+#define LEGACY_I2C_TV 0x82
+
+#define EDID1_LEN 128
+
+#define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg)
+#define LOG_OLD_VALUE(x)
+
+#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x))
+#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x))
+
+struct init_exec {
+	bool execute;
+	bool repeat;
+};
+
+static bool nv_cksum(const uint8_t *data, unsigned int length)
+{
+	/*
+	 * There's a few checksums in the BIOS, so here's a generic checking
+	 * function.
+	 */
+	int i;
+	uint8_t sum = 0;
+
+	for (i = 0; i < length; i++)
+		sum += data[i];
+
+	if (sum)
+		return true;
+
+	return false;
+}
+
+static int
+score_vbios(struct drm_device *dev, const uint8_t *data, const bool writeable)
+{
+	if (!(data[0] == 0x55 && data[1] == 0xAA)) {
+		NV_TRACEWARN(dev, "... BIOS signature not found\n");
+		return 0;
+	}
+
+	if (nv_cksum(data, data[2] * 512)) {
+		NV_TRACEWARN(dev, "... BIOS checksum invalid\n");
+		/* if a ro image is somewhat bad, it's probably all rubbish */
+		return writeable ? 2 : 1;
+	} else
+		NV_TRACE(dev, "... appears to be valid\n");
+
+	return 3;
+}
+
+static void load_vbios_prom(struct drm_device *dev, uint8_t *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t pci_nv_20, save_pci_nv_20;
+	int pcir_ptr;
+	int i;
+
+	if (dev_priv->card_type >= NV_50)
+		pci_nv_20 = 0x88050;
+	else
+		pci_nv_20 = NV_PBUS_PCI_NV_20;
+
+	/* enable ROM access */
+	save_pci_nv_20 = nvReadMC(dev, pci_nv_20);
+	nvWriteMC(dev, pci_nv_20,
+		  save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
+
+	/* bail if no rom signature */
+	if (nv_rd08(dev, NV_PROM_OFFSET) != 0x55 ||
+	    nv_rd08(dev, NV_PROM_OFFSET + 1) != 0xaa)
+		goto out;
+
+	/* additional check (see note below) - read PCI record header */
+	pcir_ptr = nv_rd08(dev, NV_PROM_OFFSET + 0x18) |
+		   nv_rd08(dev, NV_PROM_OFFSET + 0x19) << 8;
+	if (nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr) != 'P' ||
+	    nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 1) != 'C' ||
+	    nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 2) != 'I' ||
+	    nv_rd08(dev, NV_PROM_OFFSET + pcir_ptr + 3) != 'R')
+		goto out;
+
+	/* on some 6600GT/6800LE prom reads are messed up.  nvclock alleges a
+	 * a good read may be obtained by waiting or re-reading (cargocult: 5x)
+	 * each byte.  we'll hope pramin has something usable instead
+	 */
+	for (i = 0; i < NV_PROM_SIZE; i++)
+		data[i] = nv_rd08(dev, NV_PROM_OFFSET + i);
+
+out:
+	/* disable ROM access */
+	nvWriteMC(dev, pci_nv_20,
+		  save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
+}
+
+static void load_vbios_pramin(struct drm_device *dev, uint8_t *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t old_bar0_pramin = 0;
+	int i;
+
+	if (dev_priv->card_type >= NV_50) {
+		uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8;
+
+		if (!vbios_vram)
+			vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000;
+
+		old_bar0_pramin = nv_rd32(dev, 0x1700);
+		nv_wr32(dev, 0x1700, vbios_vram >> 16);
+	}
+
+	/* bail if no rom signature */
+	if (nv_rd08(dev, NV_PRAMIN_OFFSET) != 0x55 ||
+	    nv_rd08(dev, NV_PRAMIN_OFFSET + 1) != 0xaa)
+		goto out;
+
+	for (i = 0; i < NV_PROM_SIZE; i++)
+		data[i] = nv_rd08(dev, NV_PRAMIN_OFFSET + i);
+
+out:
+	if (dev_priv->card_type >= NV_50)
+		nv_wr32(dev, 0x1700, old_bar0_pramin);
+}
+
+static void load_vbios_pci(struct drm_device *dev, uint8_t *data)
+{
+	void __iomem *rom = NULL;
+	size_t rom_len;
+	int ret;
+
+	ret = pci_enable_rom(dev->pdev);
+	if (ret)
+		return;
+
+	rom = pci_map_rom(dev->pdev, &rom_len);
+	if (!rom)
+		goto out;
+	memcpy_fromio(data, rom, rom_len);
+	pci_unmap_rom(dev->pdev, rom);
+
+out:
+	pci_disable_rom(dev->pdev);
+}
+
+struct methods {
+	const char desc[8];
+	void (*loadbios)(struct drm_device *, uint8_t *);
+	const bool rw;
+};
+
+static struct methods nv04_methods[] = {
+	{ "PROM", load_vbios_prom, false },
+	{ "PRAMIN", load_vbios_pramin, true },
+	{ "PCIROM", load_vbios_pci, true },
+};
+
+static struct methods nv50_methods[] = {
+	{ "PRAMIN", load_vbios_pramin, true },
+	{ "PROM", load_vbios_prom, false },
+	{ "PCIROM", load_vbios_pci, true },
+};
+
+#define METHODCNT 3
+
+static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct methods *methods;
+	int i;
+	int testscore = 3;
+	int scores[METHODCNT];
+
+	if (nouveau_vbios) {
+		methods = nv04_methods;
+		for (i = 0; i < METHODCNT; i++)
+			if (!strcasecmp(nouveau_vbios, methods[i].desc))
+				break;
+
+		if (i < METHODCNT) {
+			NV_INFO(dev, "Attempting to use BIOS image from %s\n",
+				methods[i].desc);
+
+			methods[i].loadbios(dev, data);
+			if (score_vbios(dev, data, methods[i].rw))
+				return true;
+		}
+
+		NV_ERROR(dev, "VBIOS source \'%s\' invalid\n", nouveau_vbios);
+	}
+
+	if (dev_priv->card_type < NV_50)
+		methods = nv04_methods;
+	else
+		methods = nv50_methods;
+
+	for (i = 0; i < METHODCNT; i++) {
+		NV_TRACE(dev, "Attempting to load BIOS image from %s\n",
+			 methods[i].desc);
+		data[0] = data[1] = 0;	/* avoid reuse of previous image */
+		methods[i].loadbios(dev, data);
+		scores[i] = score_vbios(dev, data, methods[i].rw);
+		if (scores[i] == testscore)
+			return true;
+	}
+
+	while (--testscore > 0) {
+		for (i = 0; i < METHODCNT; i++) {
+			if (scores[i] == testscore) {
+				NV_TRACE(dev, "Using BIOS image from %s\n",
+					 methods[i].desc);
+				methods[i].loadbios(dev, data);
+				return true;
+			}
+		}
+	}
+
+	NV_ERROR(dev, "No valid BIOS image found\n");
+	return false;
+}
+
+struct init_tbl_entry {
+	char *name;
+	uint8_t id;
+	int (*handler)(struct nvbios *, uint16_t, struct init_exec *);
+};
+
+struct bit_entry {
+	uint8_t id[2];
+	uint16_t length;
+	uint16_t offset;
+};
+
+static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *);
+
+#define MACRO_INDEX_SIZE	2
+#define MACRO_SIZE		8
+#define CONDITION_SIZE		12
+#define IO_FLAG_CONDITION_SIZE	9
+#define IO_CONDITION_SIZE	5
+#define MEM_INIT_SIZE		66
+
+static void still_alive(void)
+{
+#if 0
+	sync();
+	msleep(2);
+#endif
+}
+
+static uint32_t
+munge_reg(struct nvbios *bios, uint32_t reg)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	struct dcb_entry *dcbent = bios->display.output;
+
+	if (dev_priv->card_type < NV_50)
+		return reg;
+
+	if (reg & 0x40000000) {
+		BUG_ON(!dcbent);
+
+		reg += (ffs(dcbent->or) - 1) * 0x800;
+		if ((reg & 0x20000000) && !(dcbent->sorconf.link & 1))
+			reg += 0x00000080;
+	}
+
+	reg &= ~0x60000000;
+	return reg;
+}
+
+static int
+valid_reg(struct nvbios *bios, uint32_t reg)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	struct drm_device *dev = bios->dev;
+
+	/* C51 has misaligned regs on purpose. Marvellous */
+	if (reg & 0x2 ||
+	    (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
+		NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
+
+	/* warn on C51 regs that haven't been verified accessible in tracing */
+	if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
+	    reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
+		NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
+			reg);
+
+	if (reg >= (8*1024*1024)) {
+		NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
+		return 0;
+	}
+
+	return 1;
+}
+
+static bool
+valid_idx_port(struct nvbios *bios, uint16_t port)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	struct drm_device *dev = bios->dev;
+
+	/*
+	 * If adding more ports here, the read/write functions below will need
+	 * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is
+	 * used for the port in question
+	 */
+	if (dev_priv->card_type < NV_50) {
+		if (port == NV_CIO_CRX__COLOR)
+			return true;
+		if (port == NV_VIO_SRX)
+			return true;
+	} else {
+		if (port == NV_CIO_CRX__COLOR)
+			return true;
+	}
+
+	NV_ERROR(dev, "========== unknown indexed io port 0x%04X ==========\n",
+		 port);
+
+	return false;
+}
+
+static bool
+valid_port(struct nvbios *bios, uint16_t port)
+{
+	struct drm_device *dev = bios->dev;
+
+	/*
+	 * If adding more ports here, the read/write functions below will need
+	 * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is
+	 * used for the port in question
+	 */
+	if (port == NV_VIO_VSE2)
+		return true;
+
+	NV_ERROR(dev, "========== unknown io port 0x%04X ==========\n", port);
+
+	return false;
+}
+
+static uint32_t
+bios_rd32(struct nvbios *bios, uint32_t reg)
+{
+	uint32_t data;
+
+	reg = munge_reg(bios, reg);
+	if (!valid_reg(bios, reg))
+		return 0;
+
+	/*
+	 * C51 sometimes uses regs with bit0 set in the address. For these
+	 * cases there should exist a translation in a BIOS table to an IO
+	 * port address which the BIOS uses for accessing the reg
+	 *
+	 * These only seem to appear for the power control regs to a flat panel,
+	 * and the GPIO regs at 0x60081*.  In C51 mmio traces the normal regs
+	 * for 0x1308 and 0x1310 are used - hence the mask below.  An S3
+	 * suspend-resume mmio trace from a C51 will be required to see if this
+	 * is true for the power microcode in 0x14.., or whether the direct IO
+	 * port access method is needed
+	 */
+	if (reg & 0x1)
+		reg &= ~0x1;
+
+	data = nv_rd32(bios->dev, reg);
+
+	BIOSLOG(bios, "	Read:  Reg: 0x%08X, Data: 0x%08X\n", reg, data);
+
+	return data;
+}
+
+static void
+bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+
+	reg = munge_reg(bios, reg);
+	if (!valid_reg(bios, reg))
+		return;
+
+	/* see note in bios_rd32 */
+	if (reg & 0x1)
+		reg &= 0xfffffffe;
+
+	LOG_OLD_VALUE(bios_rd32(bios, reg));
+	BIOSLOG(bios, "	Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
+
+	if (dev_priv->VBIOS.execute) {
+		still_alive();
+		nv_wr32(bios->dev, reg, data);
+	}
+}
+
+static uint8_t
+bios_idxprt_rd(struct nvbios *bios, uint16_t port, uint8_t index)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	struct drm_device *dev = bios->dev;
+	uint8_t data;
+
+	if (!valid_idx_port(bios, port))
+		return 0;
+
+	if (dev_priv->card_type < NV_50) {
+		if (port == NV_VIO_SRX)
+			data = NVReadVgaSeq(dev, bios->state.crtchead, index);
+		else	/* assume NV_CIO_CRX__COLOR */
+			data = NVReadVgaCrtc(dev, bios->state.crtchead, index);
+	} else {
+		uint32_t data32;
+
+		data32 = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3));
+		data = (data32 >> ((index & 3) << 3)) & 0xff;
+	}
+
+	BIOSLOG(bios, "	Indexed IO read:  Port: 0x%04X, Index: 0x%02X, "
+		      "Head: 0x%02X, Data: 0x%02X\n",
+		port, index, bios->state.crtchead, data);
+	return data;
+}
+
+static void
+bios_idxprt_wr(struct nvbios *bios, uint16_t port, uint8_t index, uint8_t data)
+{
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	struct drm_device *dev = bios->dev;
+
+	if (!valid_idx_port(bios, port))
+		return;
+
+	/*
+	 * The current head is maintained in the nvbios member  state.crtchead.
+	 * We trap changes to CR44 and update the head variable and hence the
+	 * register set written.
+	 * As CR44 only exists on CRTC0, we update crtchead to head0 in advance
+	 * of the write, and to head1 after the write
+	 */
+	if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 &&
+	    data != NV_CIO_CRE_44_HEADB)
+		bios->state.crtchead = 0;
+
+	LOG_OLD_VALUE(bios_idxprt_rd(bios, port, index));
+	BIOSLOG(bios, "	Indexed IO write: Port: 0x%04X, Index: 0x%02X, "
+		      "Head: 0x%02X, Data: 0x%02X\n",
+		port, index, bios->state.crtchead, data);
+
+	if (bios->execute && dev_priv->card_type < NV_50) {
+		still_alive();
+		if (port == NV_VIO_SRX)
+			NVWriteVgaSeq(dev, bios->state.crtchead, index, data);
+		else	/* assume NV_CIO_CRX__COLOR */
+			NVWriteVgaCrtc(dev, bios->state.crtchead, index, data);
+	} else
+	if (bios->execute) {
+		uint32_t data32, shift = (index & 3) << 3;
+
+		still_alive();
+
+		data32  = bios_rd32(bios, NV50_PDISPLAY_VGACRTC(index & ~3));
+		data32 &= ~(0xff << shift);
+		data32 |= (data << shift);
+		bios_wr32(bios, NV50_PDISPLAY_VGACRTC(index & ~3), data32);
+	}
+
+	if (port == NV_CIO_CRX__COLOR &&
+	    index == NV_CIO_CRE_44 && data == NV_CIO_CRE_44_HEADB)
+		bios->state.crtchead = 1;
+}
+
+static uint8_t
+bios_port_rd(struct nvbios *bios, uint16_t port)
+{
+	uint8_t data, head = bios->state.crtchead;
+
+	if (!valid_port(bios, port))
+		return 0;
+
+	data = NVReadPRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port);
+
+	BIOSLOG(bios, "	IO read:  Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n",
+		port, head, data);
+
+	return data;
+}
+
+static void
+bios_port_wr(struct nvbios *bios, uint16_t port, uint8_t data)
+{
+	int head = bios->state.crtchead;
+
+	if (!valid_port(bios, port))
+		return;
+
+	LOG_OLD_VALUE(bios_port_rd(bios, port));
+	BIOSLOG(bios, "	IO write: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n",
+		port, head, data);
+
+	if (!bios->execute)
+		return;
+
+	still_alive();
+	NVWritePRMVIO(bios->dev, head, NV_PRMVIO0_OFFSET + port, data);
+}
+
+static bool
+io_flag_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond)
+{
+	/*
+	 * The IO flag condition entry has 2 bytes for the CRTC port; 1 byte
+	 * for the CRTC index; 1 byte for the mask to apply to the value
+	 * retrieved from the CRTC; 1 byte for the shift right to apply to the
+	 * masked CRTC value; 2 bytes for the offset to the flag array, to
+	 * which the shifted value is added; 1 byte for the mask applied to the
+	 * value read from the flag array; and 1 byte for the value to compare
+	 * against the masked byte from the flag table.
+	 */
+
+	uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE;
+	uint16_t crtcport = ROM16(bios->data[condptr]);
+	uint8_t crtcindex = bios->data[condptr + 2];
+	uint8_t mask = bios->data[condptr + 3];
+	uint8_t shift = bios->data[condptr + 4];
+	uint16_t flagarray = ROM16(bios->data[condptr + 5]);
+	uint8_t flagarraymask = bios->data[condptr + 7];
+	uint8_t cmpval = bios->data[condptr + 8];
+	uint8_t data;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
+		      "Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, "
+		      "Cmpval: 0x%02X\n",
+		offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval);
+
+	data = bios_idxprt_rd(bios, crtcport, crtcindex);
+
+	data = bios->data[flagarray + ((data & mask) >> shift)];
+	data &= flagarraymask;
+
+	BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n",
+		offset, data, cmpval);
+
+	return (data == cmpval);
+}
+
+static bool
+bios_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond)
+{
+	/*
+	 * The condition table entry has 4 bytes for the address of the
+	 * register to check, 4 bytes for a mask to apply to the register and
+	 * 4 for a test comparison value
+	 */
+
+	uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
+	uint32_t reg = ROM32(bios->data[condptr]);
+	uint32_t mask = ROM32(bios->data[condptr + 4]);
+	uint32_t cmpval = ROM32(bios->data[condptr + 8]);
+	uint32_t data;
+
+	BIOSLOG(bios, "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X\n",
+		offset, cond, reg, mask);
+
+	data = bios_rd32(bios, reg) & mask;
+
+	BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n",
+		offset, data, cmpval);
+
+	return (data == cmpval);
+}
+
+static bool
+io_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond)
+{
+	/*
+	 * The IO condition entry has 2 bytes for the IO port address; 1 byte
+	 * for the index to write to io_port; 1 byte for the mask to apply to
+	 * the byte read from io_port+1; and 1 byte for the value to compare
+	 * against the masked byte.
+	 */
+
+	uint16_t condptr = bios->io_condition_tbl_ptr + cond * IO_CONDITION_SIZE;
+	uint16_t io_port = ROM16(bios->data[condptr]);
+	uint8_t port_index = bios->data[condptr + 2];
+	uint8_t mask = bios->data[condptr + 3];
+	uint8_t cmpval = bios->data[condptr + 4];
+
+	uint8_t data = bios_idxprt_rd(bios, io_port, port_index) & mask;
+
+	BIOSLOG(bios, "0x%04X: Checking if 0x%02X equals 0x%02X\n",
+		offset, data, cmpval);
+
+	return (data == cmpval);
+}
+
+static int
+nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t reg0 = nv_rd32(dev, reg + 0);
+	uint32_t reg1 = nv_rd32(dev, reg + 4);
+	struct nouveau_pll_vals pll;
+	struct pll_lims pll_limits;
+	int ret;
+
+	ret = get_pll_limits(dev, reg, &pll_limits);
+	if (ret)
+		return ret;
+
+	clk = nouveau_calc_pll_mnp(dev, &pll_limits, clk, &pll);
+	if (!clk)
+		return -ERANGE;
+
+	reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
+	reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
+
+	if (dev_priv->VBIOS.execute) {
+		still_alive();
+		nv_wr32(dev, reg + 4, reg1);
+		nv_wr32(dev, reg + 0, reg0);
+	}
+
+	return 0;
+}
+
+static int
+setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk)
+{
+	struct drm_device *dev = bios->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	/* clk in kHz */
+	struct pll_lims pll_lim;
+	struct nouveau_pll_vals pllvals;
+	int ret;
+
+	if (dev_priv->card_type >= NV_50)
+		return nv50_pll_set(dev, reg, clk);
+
+	/* high regs (such as in the mac g5 table) are not -= 4 */
+	ret = get_pll_limits(dev, reg > 0x405c ? reg : reg - 4, &pll_lim);
+	if (ret)
+		return ret;
+
+	clk = nouveau_calc_pll_mnp(dev, &pll_lim, clk, &pllvals);
+	if (!clk)
+		return -ERANGE;
+
+	if (bios->execute) {
+		still_alive();
+		nouveau_hw_setpll(dev, reg, &pllvals);
+	}
+
+	return 0;
+}
+
+static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+
+	/*
+	 * For the results of this function to be correct, CR44 must have been
+	 * set (using bios_idxprt_wr to set crtchead), CR58 set for CR57 = 0,
+	 * and the DCB table parsed, before the script calling the function is
+	 * run.  run_digital_op_script is example of how to do such setup
+	 */
+
+	uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0);
+
+	if (dcb_entry > bios->bdcb.dcb.entries) {
+		NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently "
+				"(%02X)\n", dcb_entry);
+		dcb_entry = 0x7f;	/* unused / invalid marker */
+	}
+
+	return dcb_entry;
+}
+
+static struct nouveau_i2c_chan *
+init_i2c_device_find(struct drm_device *dev, int i2c_index)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct bios_parsed_dcb *bdcb = &dev_priv->VBIOS.bdcb;
+
+	if (i2c_index == 0xff) {
+		/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
+		int idx = dcb_entry_idx_from_crtchead(dev), shift = 0;
+		int default_indices = bdcb->i2c_default_indices;
+
+		if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default)
+			shift = 4;
+
+		i2c_index = (default_indices >> shift) & 0xf;
+	}
+	if (i2c_index == 0x80)	/* g80+ */
+		i2c_index = bdcb->i2c_default_indices & 0xf;
+
+	return nouveau_i2c_find(dev, i2c_index);
+}
+
+static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
+{
+	/*
+	 * For mlv < 0x80, it is an index into a table of TMDS base addresses.
+	 * For mlv == 0x80 use the "or" value of the dcb_entry indexed by
+	 * CR58 for CR57 = 0 to index a table of offsets to the basic
+	 * 0x6808b0 address.
+	 * For mlv == 0x81 use the "or" value of the dcb_entry indexed by
+	 * CR58 for CR57 = 0 to index a table of offsets to the basic
+	 * 0x6808b0 address, and then flip the offset by 8.
+	 */
+
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const int pramdac_offset[13] = {
+		0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 };
+	const uint32_t pramdac_table[4] = {
+		0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8 };
+
+	if (mlv >= 0x80) {
+		int dcb_entry, dacoffset;
+
+		/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
+		dcb_entry = dcb_entry_idx_from_crtchead(dev);
+		if (dcb_entry == 0x7f)
+			return 0;
+		dacoffset = pramdac_offset[
+				dev_priv->VBIOS.bdcb.dcb.entry[dcb_entry].or];
+		if (mlv == 0x81)
+			dacoffset ^= 8;
+		return 0x6808b0 + dacoffset;
+	} else {
+		if (mlv > ARRAY_SIZE(pramdac_table)) {
+			NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n",
+									mlv);
+			return 0;
+		}
+		return pramdac_table[mlv];
+	}
+}
+
+static int
+init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
+		      struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO_RESTRICT_PROG   opcode: 0x32 ('2')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): CRTC index
+	 * offset + 4  (8  bit): mask
+	 * offset + 5  (8  bit): shift
+	 * offset + 6  (8  bit): count
+	 * offset + 7  (32 bit): register
+	 * offset + 11 (32 bit): configuration 1
+	 * ...
+	 *
+	 * Starting at offset + 11 there are "count" 32 bit values.
+	 * To find out which value to use read index "CRTC index" on "CRTC
+	 * port", AND this value with "mask" and then bit shift right "shift"
+	 * bits.  Read the appropriate value using this index and write to
+	 * "register"
+	 */
+
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t crtcindex = bios->data[offset + 3];
+	uint8_t mask = bios->data[offset + 4];
+	uint8_t shift = bios->data[offset + 5];
+	uint8_t count = bios->data[offset + 6];
+	uint32_t reg = ROM32(bios->data[offset + 7]);
+	uint8_t config;
+	uint32_t configval;
+	int len = 11 + count * 4;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
+		      "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
+		offset, crtcport, crtcindex, mask, shift, count, reg);
+
+	config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift;
+	if (config > count) {
+		NV_ERROR(bios->dev,
+			 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
+			 offset, config, count);
+		return 0;
+	}
+
+	configval = ROM32(bios->data[offset + 11 + config * 4]);
+
+	BIOSLOG(bios, "0x%04X: Writing config %02X\n", offset, config);
+
+	bios_wr32(bios, reg, configval);
+
+	return len;
+}
+
+static int
+init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_REPEAT   opcode: 0x33 ('3')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): count
+	 *
+	 * Execute script following this opcode up to INIT_REPEAT_END
+	 * "count" times
+	 */
+
+	uint8_t count = bios->data[offset + 1];
+	uint8_t i;
+
+	/* no iexec->execute check by design */
+
+	BIOSLOG(bios, "0x%04X: Repeating following segment %d times\n",
+		offset, count);
+
+	iexec->repeat = true;
+
+	/*
+	 * count - 1, as the script block will execute once when we leave this
+	 * opcode -- this is compatible with bios behaviour as:
+	 * a) the block is always executed at least once, even if count == 0
+	 * b) the bios interpreter skips to the op following INIT_END_REPEAT,
+	 * while we don't
+	 */
+	for (i = 0; i < count - 1; i++)
+		parse_init_table(bios, offset + 2, iexec);
+
+	iexec->repeat = false;
+
+	return 2;
+}
+
+static int
+init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
+		     struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO_RESTRICT_PLL   opcode: 0x34 ('4')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): CRTC index
+	 * offset + 4  (8  bit): mask
+	 * offset + 5  (8  bit): shift
+	 * offset + 6  (8  bit): IO flag condition index
+	 * offset + 7  (8  bit): count
+	 * offset + 8  (32 bit): register
+	 * offset + 12 (16 bit): frequency 1
+	 * ...
+	 *
+	 * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz).
+	 * Set PLL register "register" to coefficients for frequency n,
+	 * selected by reading index "CRTC index" of "CRTC port" ANDed with
+	 * "mask" and shifted right by "shift".
+	 *
+	 * If "IO flag condition index" > 0, and condition met, double
+	 * frequency before setting it.
+	 */
+
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t crtcindex = bios->data[offset + 3];
+	uint8_t mask = bios->data[offset + 4];
+	uint8_t shift = bios->data[offset + 5];
+	int8_t io_flag_condition_idx = bios->data[offset + 6];
+	uint8_t count = bios->data[offset + 7];
+	uint32_t reg = ROM32(bios->data[offset + 8]);
+	uint8_t config;
+	uint16_t freq;
+	int len = 12 + count * 2;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
+		      "Shift: 0x%02X, IO Flag Condition: 0x%02X, "
+		      "Count: 0x%02X, Reg: 0x%08X\n",
+		offset, crtcport, crtcindex, mask, shift,
+		io_flag_condition_idx, count, reg);
+
+	config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift;
+	if (config > count) {
+		NV_ERROR(bios->dev,
+			 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
+			 offset, config, count);
+		return 0;
+	}
+
+	freq = ROM16(bios->data[offset + 12 + config * 2]);
+
+	if (io_flag_condition_idx > 0) {
+		if (io_flag_condition_met(bios, offset, io_flag_condition_idx)) {
+			BIOSLOG(bios, "0x%04X: Condition fulfilled -- "
+				      "frequency doubled\n", offset);
+			freq *= 2;
+		} else
+			BIOSLOG(bios, "0x%04X: Condition not fulfilled -- "
+				      "frequency unchanged\n", offset);
+	}
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n",
+		offset, reg, config, freq);
+
+	setPLL(bios, reg, freq * 10);
+
+	return len;
+}
+
+static int
+init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_END_REPEAT   opcode: 0x36 ('6')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Marks the end of the block for INIT_REPEAT to repeat
+	 */
+
+	/* no iexec->execute check by design */
+
+	/*
+	 * iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when
+	 * we're not in repeat mode
+	 */
+	if (iexec->repeat)
+		return 0;
+
+	return 1;
+}
+
+static int
+init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_COPY   opcode: 0x37 ('7')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (8  bit): shift
+	 * offset + 6  (8  bit): srcmask
+	 * offset + 7  (16 bit): CRTC port
+	 * offset + 9  (8 bit): CRTC index
+	 * offset + 10  (8 bit): mask
+	 *
+	 * Read index "CRTC index" on "CRTC port", AND with "mask", OR with
+	 * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC
+	 * port
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint8_t shift = bios->data[offset + 5];
+	uint8_t srcmask = bios->data[offset + 6];
+	uint16_t crtcport = ROM16(bios->data[offset + 7]);
+	uint8_t crtcindex = bios->data[offset + 9];
+	uint8_t mask = bios->data[offset + 10];
+	uint32_t data;
+	uint8_t crtcdata;
+
+	if (!iexec->execute)
+		return 11;
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, "
+		      "Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n",
+		offset, reg, shift, srcmask, crtcport, crtcindex, mask);
+
+	data = bios_rd32(bios, reg);
+
+	if (shift < 0x80)
+		data >>= shift;
+	else
+		data <<= (0x100 - shift);
+
+	data &= srcmask;
+
+	crtcdata  = bios_idxprt_rd(bios, crtcport, crtcindex) & mask;
+	crtcdata |= (uint8_t)data;
+	bios_idxprt_wr(bios, crtcport, crtcindex, crtcdata);
+
+	return 11;
+}
+
+static int
+init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_NOT   opcode: 0x38 ('8')
+	 *
+	 * offset      (8  bit): opcode
+	 *
+	 * Invert the current execute / no-execute condition (i.e. "else")
+	 */
+	if (iexec->execute)
+		BIOSLOG(bios, "0x%04X: ------ Skipping following commands  ------\n", offset);
+	else
+		BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", offset);
+
+	iexec->execute = !iexec->execute;
+	return 1;
+}
+
+static int
+init_io_flag_condition(struct nvbios *bios, uint16_t offset,
+		       struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO_FLAG_CONDITION   opcode: 0x39 ('9')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): condition number
+	 *
+	 * Check condition "condition number" in the IO flag condition table.
+	 * If condition not met skip subsequent opcodes until condition is
+	 * inverted (INIT_NOT), or we hit INIT_RESUME
+	 */
+
+	uint8_t cond = bios->data[offset + 1];
+
+	if (!iexec->execute)
+		return 2;
+
+	if (io_flag_condition_met(bios, offset, cond))
+		BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
+	else {
+		BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
+		iexec->execute = false;
+	}
+
+	return 2;
+}
+
+static int
+init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
+		      struct init_exec *iexec)
+{
+	/*
+	 * INIT_INDEX_ADDRESS_LATCHED   opcode: 0x49 ('I')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): control register
+	 * offset + 5  (32 bit): data register
+	 * offset + 9  (32 bit): mask
+	 * offset + 13 (32 bit): data
+	 * offset + 17 (8  bit): count
+	 * offset + 18 (8  bit): address 1
+	 * offset + 19 (8  bit): data 1
+	 * ...
+	 *
+	 * For each of "count" address and data pairs, write "data n" to
+	 * "data register", read the current value of "control register",
+	 * and write it back once ANDed with "mask", ORed with "data",
+	 * and ORed with "address n"
+	 */
+
+	uint32_t controlreg = ROM32(bios->data[offset + 1]);
+	uint32_t datareg = ROM32(bios->data[offset + 5]);
+	uint32_t mask = ROM32(bios->data[offset + 9]);
+	uint32_t data = ROM32(bios->data[offset + 13]);
+	uint8_t count = bios->data[offset + 17];
+	int len = 18 + count * 2;
+	uint32_t value;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, "
+		      "Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n",
+		offset, controlreg, datareg, mask, data, count);
+
+	for (i = 0; i < count; i++) {
+		uint8_t instaddress = bios->data[offset + 18 + i * 2];
+		uint8_t instdata = bios->data[offset + 19 + i * 2];
+
+		BIOSLOG(bios, "0x%04X: Address: 0x%02X, Data: 0x%02X\n",
+			offset, instaddress, instdata);
+
+		bios_wr32(bios, datareg, instdata);
+		value  = bios_rd32(bios, controlreg) & mask;
+		value |= data;
+		value |= instaddress;
+		bios_wr32(bios, controlreg, value);
+	}
+
+	return len;
+}
+
+static int
+init_io_restrict_pll2(struct nvbios *bios, uint16_t offset,
+		      struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO_RESTRICT_PLL2   opcode: 0x4A ('J')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): CRTC index
+	 * offset + 4  (8  bit): mask
+	 * offset + 5  (8  bit): shift
+	 * offset + 6  (8  bit): count
+	 * offset + 7  (32 bit): register
+	 * offset + 11 (32 bit): frequency 1
+	 * ...
+	 *
+	 * Starting at offset + 11 there are "count" 32 bit frequencies (kHz).
+	 * Set PLL register "register" to coefficients for frequency n,
+	 * selected by reading index "CRTC index" of "CRTC port" ANDed with
+	 * "mask" and shifted right by "shift".
+	 */
+
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t crtcindex = bios->data[offset + 3];
+	uint8_t mask = bios->data[offset + 4];
+	uint8_t shift = bios->data[offset + 5];
+	uint8_t count = bios->data[offset + 6];
+	uint32_t reg = ROM32(bios->data[offset + 7]);
+	int len = 11 + count * 4;
+	uint8_t config;
+	uint32_t freq;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
+		      "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
+		offset, crtcport, crtcindex, mask, shift, count, reg);
+
+	if (!reg)
+		return len;
+
+	config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift;
+	if (config > count) {
+		NV_ERROR(bios->dev,
+			 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
+			 offset, config, count);
+		return 0;
+	}
+
+	freq = ROM32(bios->data[offset + 11 + config * 4]);
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n",
+		offset, reg, config, freq);
+
+	setPLL(bios, reg, freq);
+
+	return len;
+}
+
+static int
+init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_PLL2   opcode: 0x4B ('K')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (32 bit): freq
+	 *
+	 * Set PLL register "register" to coefficients for frequency "freq"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint32_t freq = ROM32(bios->data[offset + 5]);
+
+	if (!iexec->execute)
+		return 9;
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n",
+		offset, reg, freq);
+
+	setPLL(bios, reg, freq);
+	return 9;
+}
+
+static int
+init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_I2C_BYTE   opcode: 0x4C ('L')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): DCB I2C table entry index
+	 * offset + 2  (8 bit): I2C slave address
+	 * offset + 3  (8 bit): count
+	 * offset + 4  (8 bit): I2C register 1
+	 * offset + 5  (8 bit): mask 1
+	 * offset + 6  (8 bit): data 1
+	 * ...
+	 *
+	 * For each of "count" registers given by "I2C register n" on the device
+	 * addressed by "I2C slave address" on the I2C bus given by
+	 * "DCB I2C table entry index", read the register, AND the result with
+	 * "mask n" and OR it with "data n" before writing it back to the device
+	 */
+
+	uint8_t i2c_index = bios->data[offset + 1];
+	uint8_t i2c_address = bios->data[offset + 2];
+	uint8_t count = bios->data[offset + 3];
+	int len = 4 + count * 3;
+	struct nouveau_i2c_chan *chan;
+	struct i2c_msg msg;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
+		      "Count: 0x%02X\n",
+		offset, i2c_index, i2c_address, count);
+
+	chan = init_i2c_device_find(bios->dev, i2c_index);
+	if (!chan)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		uint8_t i2c_reg = bios->data[offset + 4 + i * 3];
+		uint8_t mask = bios->data[offset + 5 + i * 3];
+		uint8_t data = bios->data[offset + 6 + i * 3];
+		uint8_t value;
+
+		msg.addr = i2c_address;
+		msg.flags = I2C_M_RD;
+		msg.len = 1;
+		msg.buf = &value;
+		if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
+			return 0;
+
+		BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
+			      "Mask: 0x%02X, Data: 0x%02X\n",
+			offset, i2c_reg, value, mask, data);
+
+		value = (value & mask) | data;
+
+		if (bios->execute) {
+			msg.addr = i2c_address;
+			msg.flags = 0;
+			msg.len = 1;
+			msg.buf = &value;
+			if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
+				return 0;
+		}
+	}
+
+	return len;
+}
+
+static int
+init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_I2C_BYTE   opcode: 0x4D ('M')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): DCB I2C table entry index
+	 * offset + 2  (8 bit): I2C slave address
+	 * offset + 3  (8 bit): count
+	 * offset + 4  (8 bit): I2C register 1
+	 * offset + 5  (8 bit): data 1
+	 * ...
+	 *
+	 * For each of "count" registers given by "I2C register n" on the device
+	 * addressed by "I2C slave address" on the I2C bus given by
+	 * "DCB I2C table entry index", set the register to "data n"
+	 */
+
+	uint8_t i2c_index = bios->data[offset + 1];
+	uint8_t i2c_address = bios->data[offset + 2];
+	uint8_t count = bios->data[offset + 3];
+	int len = 4 + count * 2;
+	struct nouveau_i2c_chan *chan;
+	struct i2c_msg msg;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
+		      "Count: 0x%02X\n",
+		offset, i2c_index, i2c_address, count);
+
+	chan = init_i2c_device_find(bios->dev, i2c_index);
+	if (!chan)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		uint8_t i2c_reg = bios->data[offset + 4 + i * 2];
+		uint8_t data = bios->data[offset + 5 + i * 2];
+
+		BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n",
+			offset, i2c_reg, data);
+
+		if (bios->execute) {
+			msg.addr = i2c_address;
+			msg.flags = 0;
+			msg.len = 1;
+			msg.buf = &data;
+			if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
+				return 0;
+		}
+	}
+
+	return len;
+}
+
+static int
+init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_I2C   opcode: 0x4E ('N')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): DCB I2C table entry index
+	 * offset + 2  (8 bit): I2C slave address
+	 * offset + 3  (8 bit): count
+	 * offset + 4  (8 bit): data 1
+	 * ...
+	 *
+	 * Send "count" bytes ("data n") to the device addressed by "I2C slave
+	 * address" on the I2C bus given by "DCB I2C table entry index"
+	 */
+
+	uint8_t i2c_index = bios->data[offset + 1];
+	uint8_t i2c_address = bios->data[offset + 2];
+	uint8_t count = bios->data[offset + 3];
+	int len = 4 + count;
+	struct nouveau_i2c_chan *chan;
+	struct i2c_msg msg;
+	uint8_t data[256];
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, "
+		      "Count: 0x%02X\n",
+		offset, i2c_index, i2c_address, count);
+
+	chan = init_i2c_device_find(bios->dev, i2c_index);
+	if (!chan)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		data[i] = bios->data[offset + 4 + i];
+
+		BIOSLOG(bios, "0x%04X: Data: 0x%02X\n", offset, data[i]);
+	}
+
+	if (bios->execute) {
+		msg.addr = i2c_address;
+		msg.flags = 0;
+		msg.len = count;
+		msg.buf = data;
+		if (i2c_transfer(&chan->adapter, &msg, 1) != 1)
+			return 0;
+	}
+
+	return len;
+}
+
+static int
+init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_TMDS   opcode: 0x4F ('O')	(non-canon name)
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): magic lookup value
+	 * offset + 2  (8 bit): TMDS address
+	 * offset + 3  (8 bit): mask
+	 * offset + 4  (8 bit): data
+	 *
+	 * Read the data reg for TMDS address "TMDS address", AND it with mask
+	 * and OR it with data, then write it back
+	 * "magic lookup value" determines which TMDS base address register is
+	 * used -- see get_tmds_index_reg()
+	 */
+
+	uint8_t mlv = bios->data[offset + 1];
+	uint32_t tmdsaddr = bios->data[offset + 2];
+	uint8_t mask = bios->data[offset + 3];
+	uint8_t data = bios->data[offset + 4];
+	uint32_t reg, value;
+
+	if (!iexec->execute)
+		return 5;
+
+	BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, "
+		      "Mask: 0x%02X, Data: 0x%02X\n",
+		offset, mlv, tmdsaddr, mask, data);
+
+	reg = get_tmds_index_reg(bios->dev, mlv);
+	if (!reg)
+		return 0;
+
+	bios_wr32(bios, reg,
+		  tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
+	value = (bios_rd32(bios, reg + 4) & mask) | data;
+	bios_wr32(bios, reg + 4, value);
+	bios_wr32(bios, reg, tmdsaddr);
+
+	return 5;
+}
+
+static int
+init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
+		   struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_TMDS_GROUP   opcode: 0x50 ('P')	(non-canon name)
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): magic lookup value
+	 * offset + 2  (8 bit): count
+	 * offset + 3  (8 bit): addr 1
+	 * offset + 4  (8 bit): data 1
+	 * ...
+	 *
+	 * For each of "count" TMDS address and data pairs write "data n" to
+	 * "addr n".  "magic lookup value" determines which TMDS base address
+	 * register is used -- see get_tmds_index_reg()
+	 */
+
+	uint8_t mlv = bios->data[offset + 1];
+	uint8_t count = bios->data[offset + 2];
+	int len = 3 + count * 2;
+	uint32_t reg;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n",
+		offset, mlv, count);
+
+	reg = get_tmds_index_reg(bios->dev, mlv);
+	if (!reg)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+		uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
+		uint8_t tmdsdata = bios->data[offset + 4 + i * 2];
+
+		bios_wr32(bios, reg + 4, tmdsdata);
+		bios_wr32(bios, reg, tmdsaddr);
+	}
+
+	return len;
+}
+
+static int
+init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset,
+		      struct init_exec *iexec)
+{
+	/*
+	 * INIT_CR_INDEX_ADDRESS_LATCHED   opcode: 0x51 ('Q')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): CRTC index1
+	 * offset + 2  (8 bit): CRTC index2
+	 * offset + 3  (8 bit): baseaddr
+	 * offset + 4  (8 bit): count
+	 * offset + 5  (8 bit): data 1
+	 * ...
+	 *
+	 * For each of "count" address and data pairs, write "baseaddr + n" to
+	 * "CRTC index1" and "data n" to "CRTC index2"
+	 * Once complete, restore initial value read from "CRTC index1"
+	 */
+	uint8_t crtcindex1 = bios->data[offset + 1];
+	uint8_t crtcindex2 = bios->data[offset + 2];
+	uint8_t baseaddr = bios->data[offset + 3];
+	uint8_t count = bios->data[offset + 4];
+	int len = 5 + count;
+	uint8_t oldaddr, data;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, "
+		      "BaseAddr: 0x%02X, Count: 0x%02X\n",
+		offset, crtcindex1, crtcindex2, baseaddr, count);
+
+	oldaddr = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex1);
+
+	for (i = 0; i < count; i++) {
+		bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1,
+				     baseaddr + i);
+		data = bios->data[offset + 5 + i];
+		bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex2, data);
+	}
+
+	bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, oldaddr);
+
+	return len;
+}
+
+static int
+init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_CR   opcode: 0x52 ('R')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (8  bit): CRTC index
+	 * offset + 2  (8  bit): mask
+	 * offset + 3  (8  bit): data
+	 *
+	 * Assign the value of at "CRTC index" ANDed with mask and ORed with
+	 * data back to "CRTC index"
+	 */
+
+	uint8_t crtcindex = bios->data[offset + 1];
+	uint8_t mask = bios->data[offset + 2];
+	uint8_t data = bios->data[offset + 3];
+	uint8_t value;
+
+	if (!iexec->execute)
+		return 4;
+
+	BIOSLOG(bios, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
+		offset, crtcindex, mask, data);
+
+	value  = bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, crtcindex) & mask;
+	value |= data;
+	bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, value);
+
+	return 4;
+}
+
+static int
+init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_CR   opcode: 0x53 ('S')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): CRTC index
+	 * offset + 2  (8 bit): value
+	 *
+	 * Assign "value" to CRTC register with index "CRTC index".
+	 */
+
+	uint8_t crtcindex = ROM32(bios->data[offset + 1]);
+	uint8_t data = bios->data[offset + 2];
+
+	if (!iexec->execute)
+		return 3;
+
+	bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, data);
+
+	return 3;
+}
+
+static int
+init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_CR_GROUP   opcode: 0x54 ('T')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): count
+	 * offset + 2  (8 bit): CRTC index 1
+	 * offset + 3  (8 bit): value 1
+	 * ...
+	 *
+	 * For "count", assign "value n" to CRTC register with index
+	 * "CRTC index n".
+	 */
+
+	uint8_t count = bios->data[offset + 1];
+	int len = 2 + count * 2;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	for (i = 0; i < count; i++)
+		init_zm_cr(bios, offset + 2 + 2 * i - 1, iexec);
+
+	return len;
+}
+
+static int
+init_condition_time(struct nvbios *bios, uint16_t offset,
+		    struct init_exec *iexec)
+{
+	/*
+	 * INIT_CONDITION_TIME   opcode: 0x56 ('V')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): condition number
+	 * offset + 2  (8 bit): retries / 50
+	 *
+	 * Check condition "condition number" in the condition table.
+	 * Bios code then sleeps for 2ms if the condition is not met, and
+	 * repeats up to "retries" times, but on one C51 this has proved
+	 * insufficient.  In mmiotraces the driver sleeps for 20ms, so we do
+	 * this, and bail after "retries" times, or 2s, whichever is less.
+	 * If still not met after retries, clear execution flag for this table.
+	 */
+
+	uint8_t cond = bios->data[offset + 1];
+	uint16_t retries = bios->data[offset + 2] * 50;
+	unsigned cnt;
+
+	if (!iexec->execute)
+		return 3;
+
+	if (retries > 100)
+		retries = 100;
+
+	BIOSLOG(bios, "0x%04X: Condition: 0x%02X, Retries: 0x%02X\n",
+		offset, cond, retries);
+
+	if (!bios->execute) /* avoid 2s delays when "faking" execution */
+		retries = 1;
+
+	for (cnt = 0; cnt < retries; cnt++) {
+		if (bios_condition_met(bios, offset, cond)) {
+			BIOSLOG(bios, "0x%04X: Condition met, continuing\n",
+								offset);
+			break;
+		} else {
+			BIOSLOG(bios, "0x%04X: "
+				"Condition not met, sleeping for 20ms\n",
+								offset);
+			msleep(20);
+		}
+	}
+
+	if (!bios_condition_met(bios, offset, cond)) {
+		NV_WARN(bios->dev,
+			"0x%04X: Condition still not met after %dms, "
+			"skipping following opcodes\n", offset, 20 * retries);
+		iexec->execute = false;
+	}
+
+	return 3;
+}
+
+static int
+init_zm_reg_sequence(struct nvbios *bios, uint16_t offset,
+		     struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_REG_SEQUENCE   opcode: 0x58 ('X')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): base register
+	 * offset + 5  (8  bit): count
+	 * offset + 6  (32 bit): value 1
+	 * ...
+	 *
+	 * Starting at offset + 6 there are "count" 32 bit values.
+	 * For "count" iterations set "base register" + 4 * current_iteration
+	 * to "value current_iteration"
+	 */
+
+	uint32_t basereg = ROM32(bios->data[offset + 1]);
+	uint32_t count = bios->data[offset + 5];
+	int len = 6 + count * 4;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	BIOSLOG(bios, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n",
+		offset, basereg, count);
+
+	for (i = 0; i < count; i++) {
+		uint32_t reg = basereg + i * 4;
+		uint32_t data = ROM32(bios->data[offset + 6 + i * 4]);
+
+		bios_wr32(bios, reg, data);
+	}
+
+	return len;
+}
+
+static int
+init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_SUB_DIRECT   opcode: 0x5B ('[')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): subroutine offset (in bios)
+	 *
+	 * Calls a subroutine that will execute commands until INIT_DONE
+	 * is found.
+	 */
+
+	uint16_t sub_offset = ROM16(bios->data[offset + 1]);
+
+	if (!iexec->execute)
+		return 3;
+
+	BIOSLOG(bios, "0x%04X: Executing subroutine at 0x%04X\n",
+		offset, sub_offset);
+
+	parse_init_table(bios, sub_offset, iexec);
+
+	BIOSLOG(bios, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset);
+
+	return 3;
+}
+
+static int
+init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_COPY_NV_REG   opcode: 0x5F ('_')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): src reg
+	 * offset + 5  (8  bit): shift
+	 * offset + 6  (32 bit): src mask
+	 * offset + 10 (32 bit): xor
+	 * offset + 14 (32 bit): dst reg
+	 * offset + 18 (32 bit): dst mask
+	 *
+	 * Shift REGVAL("src reg") right by (signed) "shift", AND result with
+	 * "src mask", then XOR with "xor". Write this OR'd with
+	 * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg"
+	 */
+
+	uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1]));
+	uint8_t shift = bios->data[offset + 5];
+	uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6]));
+	uint32_t xor = *((uint32_t *)(&bios->data[offset + 10]));
+	uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14]));
+	uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18]));
+	uint32_t srcvalue, dstvalue;
+
+	if (!iexec->execute)
+		return 22;
+
+	BIOSLOG(bios, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, "
+		      "Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n",
+		offset, srcreg, shift, srcmask, xor, dstreg, dstmask);
+
+	srcvalue = bios_rd32(bios, srcreg);
+
+	if (shift < 0x80)
+		srcvalue >>= shift;
+	else
+		srcvalue <<= (0x100 - shift);
+
+	srcvalue = (srcvalue & srcmask) ^ xor;
+
+	dstvalue = bios_rd32(bios, dstreg) & dstmask;
+
+	bios_wr32(bios, dstreg, dstvalue | srcvalue);
+
+	return 22;
+}
+
+static int
+init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_INDEX_IO   opcode: 0x62 ('b')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): CRTC index
+	 * offset + 4  (8  bit): data
+	 *
+	 * Write "data" to index "CRTC index" of "CRTC port"
+	 */
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t crtcindex = bios->data[offset + 3];
+	uint8_t data = bios->data[offset + 4];
+
+	if (!iexec->execute)
+		return 5;
+
+	bios_idxprt_wr(bios, crtcport, crtcindex, data);
+
+	return 5;
+}
+
+static int
+init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_COMPUTE_MEM   opcode: 0x63 ('c')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so
+	 * that the hardware can correctly calculate how much VRAM it has
+	 * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C))
+	 *
+	 * The implementation of this opcode in general consists of two parts:
+	 * 1) determination of the memory bus width
+	 * 2) determination of how many of the card's RAM pads have ICs attached
+	 *
+	 * 1) is done by a cunning combination of writes to offsets 0x1c and
+	 * 0x3c in the framebuffer, and seeing whether the written values are
+	 * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0
+	 *
+	 * 2) is done by a cunning combination of writes to an offset slightly
+	 * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing
+	 * if the test pattern can be read back. This then affects bits 12-15 of
+	 * NV_PFB_CFG0
+	 *
+	 * In this context a "cunning combination" may include multiple reads
+	 * and writes to varying locations, often alternating the test pattern
+	 * and 0, doubtless to make sure buffers are filled, residual charges
+	 * on tracks are removed etc.
+	 *
+	 * Unfortunately, the "cunning combination"s mentioned above, and the
+	 * changes to the bits in NV_PFB_CFG0 differ with nearly every bios
+	 * trace I have.
+	 *
+	 * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which
+	 * we started was correct, and use that instead
+	 */
+
+	/* no iexec->execute check by design */
+
+	/*
+	 * This appears to be a NOP on G8x chipsets, both io logs of the VBIOS
+	 * and kmmio traces of the binary driver POSTing the card show nothing
+	 * being done for this opcode.  why is it still listed in the table?!
+	 */
+
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+
+	if (dev_priv->card_type >= NV_40)
+		return 1;
+
+	/*
+	 * On every card I've seen, this step gets done for us earlier in
+	 * the init scripts
+	uint8_t crdata = bios_idxprt_rd(dev, NV_VIO_SRX, 0x01);
+	bios_idxprt_wr(dev, NV_VIO_SRX, 0x01, crdata | 0x20);
+	 */
+
+	/*
+	 * This also has probably been done in the scripts, but an mmio trace of
+	 * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write)
+	 */
+	bios_wr32(bios, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1);
+
+	/* write back the saved configuration value */
+	bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0);
+
+	return 1;
+}
+
+static int
+init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_RESET   opcode: 0x65 ('e')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (32 bit): value1
+	 * offset + 9  (32 bit): value2
+	 *
+	 * Assign "value1" to "register", then assign "value2" to "register"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint32_t value1 = ROM32(bios->data[offset + 5]);
+	uint32_t value2 = ROM32(bios->data[offset + 9]);
+	uint32_t pci_nv_19, pci_nv_20;
+
+	/* no iexec->execute check by design */
+
+	pci_nv_19 = bios_rd32(bios, NV_PBUS_PCI_NV_19);
+	bios_wr32(bios, NV_PBUS_PCI_NV_19, 0);
+	bios_wr32(bios, reg, value1);
+
+	udelay(10);
+
+	bios_wr32(bios, reg, value2);
+	bios_wr32(bios, NV_PBUS_PCI_NV_19, pci_nv_19);
+
+	pci_nv_20 = bios_rd32(bios, NV_PBUS_PCI_NV_20);
+	pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;	/* 0xfffffffe */
+	bios_wr32(bios, NV_PBUS_PCI_NV_20, pci_nv_20);
+
+	return 13;
+}
+
+static int
+init_configure_mem(struct nvbios *bios, uint16_t offset,
+		   struct init_exec *iexec)
+{
+	/*
+	 * INIT_CONFIGURE_MEM   opcode: 0x66 ('f')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Equivalent to INIT_DONE on bios version 3 or greater.
+	 * For early bios versions, sets up the memory registers, using values
+	 * taken from the memory init table
+	 */
+
+	/* no iexec->execute check by design */
+
+	uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4);
+	uint16_t seqtbloffs = bios->legacy.sdr_seq_tbl_ptr, meminitdata = meminitoffs + 6;
+	uint32_t reg, data;
+
+	if (bios->major_version > 2)
+		return 0;
+
+	bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd(
+		       bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20);
+
+	if (bios->data[meminitoffs] & 1)
+		seqtbloffs = bios->legacy.ddr_seq_tbl_ptr;
+
+	for (reg = ROM32(bios->data[seqtbloffs]);
+	     reg != 0xffffffff;
+	     reg = ROM32(bios->data[seqtbloffs += 4])) {
+
+		switch (reg) {
+		case NV_PFB_PRE:
+			data = NV_PFB_PRE_CMD_PRECHARGE;
+			break;
+		case NV_PFB_PAD:
+			data = NV_PFB_PAD_CKE_NORMAL;
+			break;
+		case NV_PFB_REF:
+			data = NV_PFB_REF_CMD_REFRESH;
+			break;
+		default:
+			data = ROM32(bios->data[meminitdata]);
+			meminitdata += 4;
+			if (data == 0xffffffff)
+				continue;
+		}
+
+		bios_wr32(bios, reg, data);
+	}
+
+	return 1;
+}
+
+static int
+init_configure_clk(struct nvbios *bios, uint16_t offset,
+		   struct init_exec *iexec)
+{
+	/*
+	 * INIT_CONFIGURE_CLK   opcode: 0x67 ('g')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Equivalent to INIT_DONE on bios version 3 or greater.
+	 * For early bios versions, sets up the NVClk and MClk PLLs, using
+	 * values taken from the memory init table
+	 */
+
+	/* no iexec->execute check by design */
+
+	uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4);
+	int clock;
+
+	if (bios->major_version > 2)
+		return 0;
+
+	clock = ROM16(bios->data[meminitoffs + 4]) * 10;
+	setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock);
+
+	clock = ROM16(bios->data[meminitoffs + 2]) * 10;
+	if (bios->data[meminitoffs] & 1) /* DDR */
+		clock *= 2;
+	setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock);
+
+	return 1;
+}
+
+static int
+init_configure_preinit(struct nvbios *bios, uint16_t offset,
+		       struct init_exec *iexec)
+{
+	/*
+	 * INIT_CONFIGURE_PREINIT   opcode: 0x68 ('h')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Equivalent to INIT_DONE on bios version 3 or greater.
+	 * For early bios versions, does early init, loading ram and crystal
+	 * configuration from straps into CR3C
+	 */
+
+	/* no iexec->execute check by design */
+
+	uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0);
+	uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6));
+
+	if (bios->major_version > 2)
+		return 0;
+
+	bios_idxprt_wr(bios, NV_CIO_CRX__COLOR,
+			     NV_CIO_CRE_SCRATCH4__INDEX, cr3c);
+
+	return 1;
+}
+
+static int
+init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO   opcode: 0x69 ('i')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): mask
+	 * offset + 4  (8  bit): data
+	 *
+	 * Assign ((IOVAL("crtc port") & "mask") | "data") to "crtc port"
+	 */
+
+	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t mask = bios->data[offset + 3];
+	uint8_t data = bios->data[offset + 4];
+
+	if (!iexec->execute)
+		return 5;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n",
+		offset, crtcport, mask, data);
+
+	/*
+	 * I have no idea what this does, but NVIDIA do this magic sequence
+	 * in the places where this INIT_IO happens..
+	 */
+	if (dev_priv->card_type >= NV_50 && crtcport == 0x3c3 && data == 1) {
+		int i;
+
+		bios_wr32(bios, 0x614100, (bios_rd32(
+			  bios, 0x614100) & 0x0fffffff) | 0x00800000);
+
+		bios_wr32(bios, 0x00e18c, bios_rd32(
+			  bios, 0x00e18c) | 0x00020000);
+
+		bios_wr32(bios, 0x614900, (bios_rd32(
+			  bios, 0x614900) & 0x0fffffff) | 0x00800000);
+
+		bios_wr32(bios, 0x000200, bios_rd32(
+			  bios, 0x000200) & ~0x40000000);
+
+		mdelay(10);
+
+		bios_wr32(bios, 0x00e18c, bios_rd32(
+			  bios, 0x00e18c) & ~0x00020000);
+
+		bios_wr32(bios, 0x000200, bios_rd32(
+			  bios, 0x000200) | 0x40000000);
+
+		bios_wr32(bios, 0x614100, 0x00800018);
+		bios_wr32(bios, 0x614900, 0x00800018);
+
+		mdelay(10);
+
+		bios_wr32(bios, 0x614100, 0x10000018);
+		bios_wr32(bios, 0x614900, 0x10000018);
+
+		for (i = 0; i < 3; i++)
+			bios_wr32(bios, 0x614280 + (i*0x800), bios_rd32(
+				  bios, 0x614280 + (i*0x800)) & 0xf0f0f0f0);
+
+		for (i = 0; i < 2; i++)
+			bios_wr32(bios, 0x614300 + (i*0x800), bios_rd32(
+				  bios, 0x614300 + (i*0x800)) & 0xfffff0f0);
+
+		for (i = 0; i < 3; i++)
+			bios_wr32(bios, 0x614380 + (i*0x800), bios_rd32(
+				  bios, 0x614380 + (i*0x800)) & 0xfffff0f0);
+
+		for (i = 0; i < 2; i++)
+			bios_wr32(bios, 0x614200 + (i*0x800), bios_rd32(
+				  bios, 0x614200 + (i*0x800)) & 0xfffffff0);
+
+		for (i = 0; i < 2; i++)
+			bios_wr32(bios, 0x614108 + (i*0x800), bios_rd32(
+				  bios, 0x614108 + (i*0x800)) & 0x0fffffff);
+		return 5;
+	}
+
+	bios_port_wr(bios, crtcport, (bios_port_rd(bios, crtcport) & mask) |
+									data);
+	return 5;
+}
+
+static int
+init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_SUB   opcode: 0x6B ('k')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): script number
+	 *
+	 * Execute script number "script number", as a subroutine
+	 */
+
+	uint8_t sub = bios->data[offset + 1];
+
+	if (!iexec->execute)
+		return 2;
+
+	BIOSLOG(bios, "0x%04X: Calling script %d\n", offset, sub);
+
+	parse_init_table(bios,
+			 ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]),
+			 iexec);
+
+	BIOSLOG(bios, "0x%04X: End of script %d\n", offset, sub);
+
+	return 2;
+}
+
+static int
+init_ram_condition(struct nvbios *bios, uint16_t offset,
+		   struct init_exec *iexec)
+{
+	/*
+	 * INIT_RAM_CONDITION   opcode: 0x6D ('m')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): mask
+	 * offset + 2  (8 bit): cmpval
+	 *
+	 * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval".
+	 * If condition not met skip subsequent opcodes until condition is
+	 * inverted (INIT_NOT), or we hit INIT_RESUME
+	 */
+
+	uint8_t mask = bios->data[offset + 1];
+	uint8_t cmpval = bios->data[offset + 2];
+	uint8_t data;
+
+	if (!iexec->execute)
+		return 3;
+
+	data = bios_rd32(bios, NV_PFB_BOOT_0) & mask;
+
+	BIOSLOG(bios, "0x%04X: Checking if 0x%08X equals 0x%08X\n",
+		offset, data, cmpval);
+
+	if (data == cmpval)
+		BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
+	else {
+		BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
+		iexec->execute = false;
+	}
+
+	return 3;
+}
+
+static int
+init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_NV_REG   opcode: 0x6E ('n')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (32 bit): mask
+	 * offset + 9  (32 bit): data
+	 *
+	 * Assign ((REGVAL("register") & "mask") | "data") to "register"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint32_t mask = ROM32(bios->data[offset + 5]);
+	uint32_t data = ROM32(bios->data[offset + 9]);
+
+	if (!iexec->execute)
+		return 13;
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n",
+		offset, reg, mask, data);
+
+	bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | data);
+
+	return 13;
+}
+
+static int
+init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_MACRO   opcode: 0x6F ('o')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): macro number
+	 *
+	 * Look up macro index "macro number" in the macro index table.
+	 * The macro index table entry has 1 byte for the index in the macro
+	 * table, and 1 byte for the number of times to repeat the macro.
+	 * The macro table entry has 4 bytes for the register address and
+	 * 4 bytes for the value to write to that register
+	 */
+
+	uint8_t macro_index_tbl_idx = bios->data[offset + 1];
+	uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE);
+	uint8_t macro_tbl_idx = bios->data[tmp];
+	uint8_t count = bios->data[tmp + 1];
+	uint32_t reg, data;
+	int i;
+
+	if (!iexec->execute)
+		return 2;
+
+	BIOSLOG(bios, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, "
+		      "Count: 0x%02X\n",
+		offset, macro_index_tbl_idx, macro_tbl_idx, count);
+
+	for (i = 0; i < count; i++) {
+		uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE;
+
+		reg = ROM32(bios->data[macroentryptr]);
+		data = ROM32(bios->data[macroentryptr + 4]);
+
+		bios_wr32(bios, reg, data);
+	}
+
+	return 2;
+}
+
+static int
+init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_DONE   opcode: 0x71 ('q')
+	 *
+	 * offset      (8  bit): opcode
+	 *
+	 * End the current script
+	 */
+
+	/* mild retval abuse to stop parsing this table */
+	return 0;
+}
+
+static int
+init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_RESUME   opcode: 0x72 ('r')
+	 *
+	 * offset      (8  bit): opcode
+	 *
+	 * End the current execute / no-execute condition
+	 */
+
+	if (iexec->execute)
+		return 1;
+
+	iexec->execute = true;
+	BIOSLOG(bios, "0x%04X: ---- Executing following commands ----\n", offset);
+
+	return 1;
+}
+
+static int
+init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_TIME   opcode: 0x74 ('t')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): time
+	 *
+	 * Sleep for "time" microseconds.
+	 */
+
+	unsigned time = ROM16(bios->data[offset + 1]);
+
+	if (!iexec->execute)
+		return 3;
+
+	BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X microseconds\n",
+		offset, time);
+
+	if (time < 1000)
+		udelay(time);
+	else
+		msleep((time + 900) / 1000);
+
+	return 3;
+}
+
+static int
+init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_CONDITION   opcode: 0x75 ('u')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): condition number
+	 *
+	 * Check condition "condition number" in the condition table.
+	 * If condition not met skip subsequent opcodes until condition is
+	 * inverted (INIT_NOT), or we hit INIT_RESUME
+	 */
+
+	uint8_t cond = bios->data[offset + 1];
+
+	if (!iexec->execute)
+		return 2;
+
+	BIOSLOG(bios, "0x%04X: Condition: 0x%02X\n", offset, cond);
+
+	if (bios_condition_met(bios, offset, cond))
+		BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
+	else {
+		BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
+		iexec->execute = false;
+	}
+
+	return 2;
+}
+
+static int
+init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_IO_CONDITION  opcode: 0x76
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): condition number
+	 *
+	 * Check condition "condition number" in the io condition table.
+	 * If condition not met skip subsequent opcodes until condition is
+	 * inverted (INIT_NOT), or we hit INIT_RESUME
+	 */
+
+	uint8_t cond = bios->data[offset + 1];
+
+	if (!iexec->execute)
+		return 2;
+
+	BIOSLOG(bios, "0x%04X: IO condition: 0x%02X\n", offset, cond);
+
+	if (io_condition_met(bios, offset, cond))
+		BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
+	else {
+		BIOSLOG(bios, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
+		iexec->execute = false;
+	}
+
+	return 2;
+}
+
+static int
+init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_INDEX_IO   opcode: 0x78 ('x')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): CRTC port
+	 * offset + 3  (8  bit): CRTC index
+	 * offset + 4  (8  bit): mask
+	 * offset + 5  (8  bit): data
+	 *
+	 * Read value at index "CRTC index" on "CRTC port", AND with "mask",
+	 * OR with "data", write-back
+	 */
+
+	uint16_t crtcport = ROM16(bios->data[offset + 1]);
+	uint8_t crtcindex = bios->data[offset + 3];
+	uint8_t mask = bios->data[offset + 4];
+	uint8_t data = bios->data[offset + 5];
+	uint8_t value;
+
+	if (!iexec->execute)
+		return 6;
+
+	BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, "
+		      "Data: 0x%02X\n",
+		offset, crtcport, crtcindex, mask, data);
+
+	value = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) | data;
+	bios_idxprt_wr(bios, crtcport, crtcindex, value);
+
+	return 6;
+}
+
+static int
+init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_PLL   opcode: 0x79 ('y')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (16 bit): freq
+	 *
+	 * Set PLL register "register" to coefficients for frequency (10kHz)
+	 * "freq"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint16_t freq = ROM16(bios->data[offset + 5]);
+
+	if (!iexec->execute)
+		return 7;
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq);
+
+	setPLL(bios, reg, freq * 10);
+
+	return 7;
+}
+
+static int
+init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_REG   opcode: 0x7A ('z')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (32 bit): value
+	 *
+	 * Assign "value" to "register"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint32_t value = ROM32(bios->data[offset + 5]);
+
+	if (!iexec->execute)
+		return 9;
+
+	if (reg == 0x000200)
+		value |= 1;
+
+	bios_wr32(bios, reg, value);
+
+	return 9;
+}
+
+static int
+init_ram_restrict_pll(struct nvbios *bios, uint16_t offset,
+		      struct init_exec *iexec)
+{
+	/*
+	 * INIT_RAM_RESTRICT_PLL   opcode: 0x87 ('')
+	 *
+	 * offset      (8 bit): opcode
+	 * offset + 1  (8 bit): PLL type
+	 * offset + 2 (32 bit): frequency 0
+	 *
+	 * Uses the RAMCFG strap of PEXTDEV_BOOT as an index into the table at
+	 * ram_restrict_table_ptr.  The value read from there is used to select
+	 * a frequency from the table starting at 'frequency 0' to be
+	 * programmed into the PLL corresponding to 'type'.
+	 *
+	 * The PLL limits table on cards using this opcode has a mapping of
+	 * 'type' to the relevant registers.
+	 */
+
+	struct drm_device *dev = bios->dev;
+	uint32_t strap = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2;
+	uint8_t index = bios->data[bios->ram_restrict_tbl_ptr + strap];
+	uint8_t type = bios->data[offset + 1];
+	uint32_t freq = ROM32(bios->data[offset + 2 + (index * 4)]);
+	uint8_t *pll_limits = &bios->data[bios->pll_limit_tbl_ptr], *entry;
+	int len = 2 + bios->ram_restrict_group_count * 4;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	if (!bios->pll_limit_tbl_ptr || (pll_limits[0] & 0xf0) != 0x30) {
+		NV_ERROR(dev, "PLL limits table not version 3.x\n");
+		return len; /* deliberate, allow default clocks to remain */
+	}
+
+	entry = pll_limits + pll_limits[1];
+	for (i = 0; i < pll_limits[3]; i++, entry += pll_limits[2]) {
+		if (entry[0] == type) {
+			uint32_t reg = ROM32(entry[3]);
+
+			BIOSLOG(bios, "0x%04X: "
+				      "Type %02x Reg 0x%08x Freq %dKHz\n",
+				offset, type, reg, freq);
+
+			setPLL(bios, reg, freq);
+			return len;
+		}
+	}
+
+	NV_ERROR(dev, "PLL type 0x%02x not found in PLL limits table", type);
+	return len;
+}
+
+static int
+init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_8C   opcode: 0x8C ('')
+	 *
+	 * NOP so far....
+	 *
+	 */
+
+	return 1;
+}
+
+static int
+init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_8D   opcode: 0x8D ('')
+	 *
+	 * NOP so far....
+	 *
+	 */
+
+	return 1;
+}
+
+static int
+init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_GPIO   opcode: 0x8E ('')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Loop over all entries in the DCB GPIO table, and initialise
+	 * each GPIO according to various values listed in each entry
+	 */
+
+	const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
+	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
+	const uint8_t *gpio_table = &bios->data[bios->bdcb.gpio_table_ptr];
+	const uint8_t *gpio_entry;
+	int i;
+
+	if (!iexec->execute)
+		return 1;
+
+	if (bios->bdcb.version != 0x40) {
+		NV_ERROR(bios->dev, "DCB table not version 4.0\n");
+		return 0;
+	}
+
+	if (!bios->bdcb.gpio_table_ptr) {
+		NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
+		return 0;
+	}
+
+	gpio_entry = gpio_table + gpio_table[1];
+	for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) {
+		uint32_t entry = ROM32(gpio_entry[0]), r, s, v;
+		int line = (entry & 0x0000001f);
+
+		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
+
+		if ((entry & 0x0000ff00) == 0x0000ff00)
+			continue;
+
+		r = nv50_gpio_reg[line >> 3];
+		s = (line & 0x07) << 2;
+		v = bios_rd32(bios, r) & ~(0x00000003 << s);
+		if (entry & 0x01000000)
+			v |= (((entry & 0x60000000) >> 29) ^ 2) << s;
+		else
+			v |= (((entry & 0x18000000) >> 27) ^ 2) << s;
+		bios_wr32(bios, r, v);
+
+		r = nv50_gpio_ctl[line >> 4];
+		s = (line & 0x0f);
+		v = bios_rd32(bios, r) & ~(0x00010001 << s);
+		switch ((entry & 0x06000000) >> 25) {
+		case 1:
+			v |= (0x00000001 << s);
+			break;
+		case 2:
+			v |= (0x00010000 << s);
+			break;
+		default:
+			break;
+		}
+		bios_wr32(bios, r, v);
+	}
+
+	return 1;
+}
+
+static int
+init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
+			       struct init_exec *iexec)
+{
+	/*
+	 * INIT_RAM_RESTRICT_ZM_REG_GROUP   opcode: 0x8F ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): reg
+	 * offset + 5  (8  bit): regincrement
+	 * offset + 6  (8  bit): count
+	 * offset + 7  (32 bit): value 1,1
+	 * ...
+	 *
+	 * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at
+	 * ram_restrict_table_ptr. The value read from here is 'n', and
+	 * "value 1,n" gets written to "reg". This repeats "count" times and on
+	 * each iteration 'm', "reg" increases by "regincrement" and
+	 * "value m,n" is used. The extent of n is limited by a number read
+	 * from the 'M' BIT table, herein called "blocklen"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint8_t regincrement = bios->data[offset + 5];
+	uint8_t count = bios->data[offset + 6];
+	uint32_t strap_ramcfg, data;
+	/* previously set by 'M' BIT table */
+	uint16_t blocklen = bios->ram_restrict_group_count * 4;
+	int len = 7 + count * blocklen;
+	uint8_t index;
+	int i;
+
+
+	if (!iexec->execute)
+		return len;
+
+	if (!blocklen) {
+		NV_ERROR(bios->dev,
+			 "0x%04X: Zero block length - has the M table "
+			 "been parsed?\n", offset);
+		return 0;
+	}
+
+	strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf;
+	index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg];
+
+	BIOSLOG(bios, "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, "
+		      "Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n",
+		offset, reg, regincrement, count, strap_ramcfg, index);
+
+	for (i = 0; i < count; i++) {
+		data = ROM32(bios->data[offset + 7 + index * 4 + blocklen * i]);
+
+		bios_wr32(bios, reg, data);
+
+		reg += regincrement;
+	}
+
+	return len;
+}
+
+static int
+init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_COPY_ZM_REG   opcode: 0x90 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): src reg
+	 * offset + 5  (32 bit): dst reg
+	 *
+	 * Put contents of "src reg" into "dst reg"
+	 */
+
+	uint32_t srcreg = ROM32(bios->data[offset + 1]);
+	uint32_t dstreg = ROM32(bios->data[offset + 5]);
+
+	if (!iexec->execute)
+		return 9;
+
+	bios_wr32(bios, dstreg, bios_rd32(bios, srcreg));
+
+	return 9;
+}
+
+static int
+init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset,
+			       struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_REG_GROUP_ADDRESS_LATCHED   opcode: 0x91 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): dst reg
+	 * offset + 5  (8  bit): count
+	 * offset + 6  (32 bit): data 1
+	 * ...
+	 *
+	 * For each of "count" values write "data n" to "dst reg"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint8_t count = bios->data[offset + 5];
+	int len = 6 + count * 4;
+	int i;
+
+	if (!iexec->execute)
+		return len;
+
+	for (i = 0; i < count; i++) {
+		uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]);
+		bios_wr32(bios, reg, data);
+	}
+
+	return len;
+}
+
+static int
+init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_RESERVED   opcode: 0x92 ('')
+	 *
+	 * offset      (8 bit): opcode
+	 *
+	 * Seemingly does nothing
+	 */
+
+	return 1;
+}
+
+static int
+init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_96   opcode: 0x96 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): sreg
+	 * offset + 5  (8  bit): sshift
+	 * offset + 6  (8  bit): smask
+	 * offset + 7  (8  bit): index
+	 * offset + 8  (32 bit): reg
+	 * offset + 12 (32 bit): mask
+	 * offset + 16 (8  bit): shift
+	 *
+	 */
+
+	uint16_t xlatptr = bios->init96_tbl_ptr + (bios->data[offset + 7] * 2);
+	uint32_t reg = ROM32(bios->data[offset + 8]);
+	uint32_t mask = ROM32(bios->data[offset + 12]);
+	uint32_t val;
+
+	val = bios_rd32(bios, ROM32(bios->data[offset + 1]));
+	if (bios->data[offset + 5] < 0x80)
+		val >>= bios->data[offset + 5];
+	else
+		val <<= (0x100 - bios->data[offset + 5]);
+	val &= bios->data[offset + 6];
+
+	val   = bios->data[ROM16(bios->data[xlatptr]) + val];
+	val <<= bios->data[offset + 16];
+
+	if (!iexec->execute)
+		return 17;
+
+	bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | val);
+	return 17;
+}
+
+static int
+init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_97   opcode: 0x97 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): register
+	 * offset + 5  (32 bit): mask
+	 * offset + 9  (32 bit): value
+	 *
+	 * Adds "value" to "register" preserving the fields specified
+	 * by "mask"
+	 */
+
+	uint32_t reg = ROM32(bios->data[offset + 1]);
+	uint32_t mask = ROM32(bios->data[offset + 5]);
+	uint32_t add = ROM32(bios->data[offset + 9]);
+	uint32_t val;
+
+	val = bios_rd32(bios, reg);
+	val = (val & mask) | ((val + add) & ~mask);
+
+	if (!iexec->execute)
+		return 13;
+
+	bios_wr32(bios, reg, val);
+	return 13;
+}
+
+static int
+init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_AUXCH   opcode: 0x98 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): address
+	 * offset + 5  (8  bit): count
+	 * offset + 6  (8  bit): mask 0
+	 * offset + 7  (8  bit): data 0
+	 *  ...
+	 *
+	 */
+
+	struct drm_device *dev = bios->dev;
+	struct nouveau_i2c_chan *auxch;
+	uint32_t addr = ROM32(bios->data[offset + 1]);
+	uint8_t count = bios->data[offset + 5];
+	int len = 6 + count * 2;
+	int ret, i;
+
+	if (!bios->display.output) {
+		NV_ERROR(dev, "INIT_AUXCH: no active output\n");
+		return 0;
+	}
+
+	auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
+	if (!auxch) {
+		NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n",
+			 bios->display.output->i2c_index);
+		return 0;
+	}
+
+	if (!iexec->execute)
+		return len;
+
+	offset += 6;
+	for (i = 0; i < count; i++, offset += 2) {
+		uint8_t data;
+
+		ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1);
+		if (ret) {
+			NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret);
+			return 0;
+		}
+
+		data &= bios->data[offset + 0];
+		data |= bios->data[offset + 1];
+
+		ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1);
+		if (ret) {
+			NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret);
+			return 0;
+		}
+	}
+
+	return len;
+}
+
+static int
+init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_ZM_AUXCH   opcode: 0x99 ('')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (32 bit): address
+	 * offset + 5  (8  bit): count
+	 * offset + 6  (8  bit): data 0
+	 *  ...
+	 *
+	 */
+
+	struct drm_device *dev = bios->dev;
+	struct nouveau_i2c_chan *auxch;
+	uint32_t addr = ROM32(bios->data[offset + 1]);
+	uint8_t count = bios->data[offset + 5];
+	int len = 6 + count;
+	int ret, i;
+
+	if (!bios->display.output) {
+		NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n");
+		return 0;
+	}
+
+	auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
+	if (!auxch) {
+		NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n",
+			 bios->display.output->i2c_index);
+		return 0;
+	}
+
+	if (!iexec->execute)
+		return len;
+
+	offset += 6;
+	for (i = 0; i < count; i++, offset++) {
+		ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1);
+		if (ret) {
+			NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret);
+			return 0;
+		}
+	}
+
+	return len;
+}
+
+static struct init_tbl_entry itbl_entry[] = {
+	/* command name                       , id  , length  , offset  , mult    , command handler                 */
+	/* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
+	{ "INIT_IO_RESTRICT_PROG"             , 0x32, init_io_restrict_prog           },
+	{ "INIT_REPEAT"                       , 0x33, init_repeat                     },
+	{ "INIT_IO_RESTRICT_PLL"              , 0x34, init_io_restrict_pll            },
+	{ "INIT_END_REPEAT"                   , 0x36, init_end_repeat                 },
+	{ "INIT_COPY"                         , 0x37, init_copy                       },
+	{ "INIT_NOT"                          , 0x38, init_not                        },
+	{ "INIT_IO_FLAG_CONDITION"            , 0x39, init_io_flag_condition          },
+	{ "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, init_idx_addr_latched           },
+	{ "INIT_IO_RESTRICT_PLL2"             , 0x4A, init_io_restrict_pll2           },
+	{ "INIT_PLL2"                         , 0x4B, init_pll2                       },
+	{ "INIT_I2C_BYTE"                     , 0x4C, init_i2c_byte                   },
+	{ "INIT_ZM_I2C_BYTE"                  , 0x4D, init_zm_i2c_byte                },
+	{ "INIT_ZM_I2C"                       , 0x4E, init_zm_i2c                     },
+	{ "INIT_TMDS"                         , 0x4F, init_tmds                       },
+	{ "INIT_ZM_TMDS_GROUP"                , 0x50, init_zm_tmds_group              },
+	{ "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, init_cr_idx_adr_latch           },
+	{ "INIT_CR"                           , 0x52, init_cr                         },
+	{ "INIT_ZM_CR"                        , 0x53, init_zm_cr                      },
+	{ "INIT_ZM_CR_GROUP"                  , 0x54, init_zm_cr_group                },
+	{ "INIT_CONDITION_TIME"               , 0x56, init_condition_time             },
+	{ "INIT_ZM_REG_SEQUENCE"              , 0x58, init_zm_reg_sequence            },
+	/* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
+	{ "INIT_SUB_DIRECT"                   , 0x5B, init_sub_direct                 },
+	{ "INIT_COPY_NV_REG"                  , 0x5F, init_copy_nv_reg                },
+	{ "INIT_ZM_INDEX_IO"                  , 0x62, init_zm_index_io                },
+	{ "INIT_COMPUTE_MEM"                  , 0x63, init_compute_mem                },
+	{ "INIT_RESET"                        , 0x65, init_reset                      },
+	{ "INIT_CONFIGURE_MEM"                , 0x66, init_configure_mem              },
+	{ "INIT_CONFIGURE_CLK"                , 0x67, init_configure_clk              },
+	{ "INIT_CONFIGURE_PREINIT"            , 0x68, init_configure_preinit          },
+	{ "INIT_IO"                           , 0x69, init_io                         },
+	{ "INIT_SUB"                          , 0x6B, init_sub                        },
+	{ "INIT_RAM_CONDITION"                , 0x6D, init_ram_condition              },
+	{ "INIT_NV_REG"                       , 0x6E, init_nv_reg                     },
+	{ "INIT_MACRO"                        , 0x6F, init_macro                      },
+	{ "INIT_DONE"                         , 0x71, init_done                       },
+	{ "INIT_RESUME"                       , 0x72, init_resume                     },
+	/* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */
+	{ "INIT_TIME"                         , 0x74, init_time                       },
+	{ "INIT_CONDITION"                    , 0x75, init_condition                  },
+	{ "INIT_IO_CONDITION"                 , 0x76, init_io_condition               },
+	{ "INIT_INDEX_IO"                     , 0x78, init_index_io                   },
+	{ "INIT_PLL"                          , 0x79, init_pll                        },
+	{ "INIT_ZM_REG"                       , 0x7A, init_zm_reg                     },
+	{ "INIT_RAM_RESTRICT_PLL"             , 0x87, init_ram_restrict_pll           },
+	{ "INIT_8C"                           , 0x8C, init_8c                         },
+	{ "INIT_8D"                           , 0x8D, init_8d                         },
+	{ "INIT_GPIO"                         , 0x8E, init_gpio                       },
+	{ "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, init_ram_restrict_zm_reg_group  },
+	{ "INIT_COPY_ZM_REG"                  , 0x90, init_copy_zm_reg                },
+	{ "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, init_zm_reg_group_addr_latched  },
+	{ "INIT_RESERVED"                     , 0x92, init_reserved                   },
+	{ "INIT_96"                           , 0x96, init_96                         },
+	{ "INIT_97"                           , 0x97, init_97                         },
+	{ "INIT_AUXCH"                        , 0x98, init_auxch                      },
+	{ "INIT_ZM_AUXCH"                     , 0x99, init_zm_auxch                   },
+	{ NULL                                , 0   , NULL                            }
+};
+
+#define MAX_TABLE_OPS 1000
+
+static int
+parse_init_table(struct nvbios *bios, unsigned int offset,
+		 struct init_exec *iexec)
+{
+	/*
+	 * Parses all commands in an init table.
+	 *
+	 * We start out executing all commands found in the init table. Some
+	 * opcodes may change the status of iexec->execute to SKIP, which will
+	 * cause the following opcodes to perform no operation until the value
+	 * is changed back to EXECUTE.
+	 */
+
+	int count = 0, i, res;
+	uint8_t id;
+
+	/*
+	 * Loop until INIT_DONE causes us to break out of the loop
+	 * (or until offset > bios length just in case... )
+	 * (and no more than MAX_TABLE_OPS iterations, just in case... )
+	 */
+	while ((offset < bios->length) && (count++ < MAX_TABLE_OPS)) {
+		id = bios->data[offset];
+
+		/* Find matching id in itbl_entry */
+		for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
+			;
+
+		if (itbl_entry[i].name) {
+			BIOSLOG(bios, "0x%04X: [ (0x%02X) - %s ]\n",
+				offset, itbl_entry[i].id, itbl_entry[i].name);
+
+			/* execute eventual command handler */
+			res = (*itbl_entry[i].handler)(bios, offset, iexec);
+			if (!res)
+				break;
+			/*
+			 * Add the offset of the current command including all data
+			 * of that command. The offset will then be pointing on the
+			 * next op code.
+			 */
+			offset += res;
+		} else {
+			NV_ERROR(bios->dev,
+				 "0x%04X: Init table command not found: "
+				 "0x%02X\n", offset, id);
+			return -ENOENT;
+		}
+	}
+
+	if (offset >= bios->length)
+		NV_WARN(bios->dev,
+			"Offset 0x%04X greater than known bios image length.  "
+			"Corrupt image?\n", offset);
+	if (count >= MAX_TABLE_OPS)
+		NV_WARN(bios->dev,
+			"More than %d opcodes to a table is unlikely, "
+			"is the bios image corrupt?\n", MAX_TABLE_OPS);
+
+	return 0;
+}
+
+static void
+parse_init_tables(struct nvbios *bios)
+{
+	/* Loops and calls parse_init_table() for each present table. */
+
+	int i = 0;
+	uint16_t table;
+	struct init_exec iexec = {true, false};
+
+	if (bios->old_style_init) {
+		if (bios->init_script_tbls_ptr)
+			parse_init_table(bios, bios->init_script_tbls_ptr, &iexec);
+		if (bios->extra_init_script_tbl_ptr)
+			parse_init_table(bios, bios->extra_init_script_tbl_ptr, &iexec);
+
+		return;
+	}
+
+	while ((table = ROM16(bios->data[bios->init_script_tbls_ptr + i]))) {
+		NV_INFO(bios->dev,
+			"Parsing VBIOS init table %d at offset 0x%04X\n",
+			i / 2, table);
+		BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", table);
+
+		parse_init_table(bios, table, &iexec);
+		i += 2;
+	}
+}
+
+static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk)
+{
+	int compare_record_len, i = 0;
+	uint16_t compareclk, scriptptr = 0;
+
+	if (bios->major_version < 5) /* pre BIT */
+		compare_record_len = 3;
+	else
+		compare_record_len = 4;
+
+	do {
+		compareclk = ROM16(bios->data[clktable + compare_record_len * i]);
+		if (pxclk >= compareclk * 10) {
+			if (bios->major_version < 5) {
+				uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i];
+				scriptptr = ROM16(bios->data[bios->init_script_tbls_ptr + tmdssub * 2]);
+			} else
+				scriptptr = ROM16(bios->data[clktable + 2 + compare_record_len * i]);
+			break;
+		}
+		i++;
+	} while (compareclk);
+
+	return scriptptr;
+}
+
+static void
+run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
+		      struct dcb_entry *dcbent, int head, bool dl)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	struct init_exec iexec = {true, false};
+
+	NV_TRACE(dev, "0x%04X: Parsing digital output script table\n",
+		 scriptptr);
+	bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_44,
+		       head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA);
+	/* note: if dcb entries have been merged, index may be misleading */
+	NVWriteVgaCrtc5758(dev, head, 0, dcbent->index);
+	parse_init_table(bios, scriptptr, &iexec);
+
+	nv04_dfp_bind_head(dev, dcbent, head, dl);
+}
+
+static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0);
+	uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
+
+	if (!bios->fp.xlated_entry || !sub || !scriptofs)
+		return -EINVAL;
+
+	run_digital_op_script(dev, scriptofs, dcbent, head, bios->fp.dual_link);
+
+	if (script == LVDS_PANEL_OFF) {
+		/* off-on delay in ms */
+		msleep(ROM16(bios->data[bios->fp.xlated_entry + 7]));
+	}
+#ifdef __powerpc__
+	/* Powerbook specific quirks */
+	if ((dev->pci_device & 0xffff) == 0x0179 ||
+	    (dev->pci_device & 0xffff) == 0x0189 ||
+	    (dev->pci_device & 0xffff) == 0x0329) {
+		if (script == LVDS_RESET) {
+			nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
+
+		} else if (script == LVDS_PANEL_ON) {
+			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+				  | (1 << 31));
+			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
+
+		} else if (script == LVDS_PANEL_OFF) {
+			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+				  & ~(1 << 31));
+			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
+		}
+	}
+#endif
+
+	return 0;
+}
+
+static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk)
+{
+	/*
+	 * The BIT LVDS table's header has the information to setup the
+	 * necessary registers. Following the standard 4 byte header are:
+	 * A bitmask byte and a dual-link transition pxclk value for use in
+	 * selecting the init script when not using straps; 4 script pointers
+	 * for panel power, selected by output and on/off; and 8 table pointers
+	 * for panel init, the needed one determined by output, and bits in the
+	 * conf byte. These tables are similar to the TMDS tables, consisting
+	 * of a list of pxclks and script pointers.
+	 */
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
+	uint16_t scriptptr = 0, clktable;
+	uint8_t clktableptr = 0;
+
+	/*
+	 * For now we assume version 3.0 table - g80 support will need some
+	 * changes
+	 */
+
+	switch (script) {
+	case LVDS_INIT:
+		return -ENOSYS;
+	case LVDS_BACKLIGHT_ON:
+	case LVDS_PANEL_ON:
+		scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]);
+		break;
+	case LVDS_BACKLIGHT_OFF:
+	case LVDS_PANEL_OFF:
+		scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
+		break;
+	case LVDS_RESET:
+		if (dcbent->lvdsconf.use_straps_for_mode) {
+			if (bios->fp.dual_link)
+				clktableptr += 2;
+			if (bios->fp.BITbit1)
+				clktableptr++;
+		} else {
+			/* using EDID */
+			uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
+			int fallbackcmpval = (dcbent->or == 4) ? 4 : 1;
+
+			if (bios->fp.dual_link) {
+				clktableptr += 2;
+				fallbackcmpval *= 2;
+			}
+			if (fallbackcmpval & fallback)
+				clktableptr++;
+		}
+
+		/* adding outputset * 8 may not be correct */
+		clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]);
+		if (!clktable) {
+			NV_ERROR(dev, "Pixel clock comparison table not found\n");
+			return -ENOENT;
+		}
+		scriptptr = clkcmptable(bios, clktable, pxclk);
+	}
+
+	if (!scriptptr) {
+		NV_ERROR(dev, "LVDS output init script not found\n");
+		return -ENOENT;
+	}
+	run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link);
+
+	return 0;
+}
+
+int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk)
+{
+	/*
+	 * LVDS operations are multiplexed in an effort to present a single API
+	 * which works with two vastly differing underlying structures.
+	 * This acts as the demux
+	 */
+
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
+	uint32_t sel_clk_binding, sel_clk;
+	int ret;
+
+	if (bios->fp.last_script_invoc == (script << 1 | head) || !lvds_ver ||
+	    (lvds_ver >= 0x30 && script == LVDS_INIT))
+		return 0;
+
+	if (!bios->fp.lvds_init_run) {
+		bios->fp.lvds_init_run = true;
+		call_lvds_script(dev, dcbent, head, LVDS_INIT, pxclk);
+	}
+
+	if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change)
+		call_lvds_script(dev, dcbent, head, LVDS_RESET, pxclk);
+	if (script == LVDS_RESET && bios->fp.power_off_for_reset)
+		call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk);
+
+	NV_TRACE(dev, "Calling LVDS script %d:\n", script);
+
+	/* don't let script change pll->head binding */
+	sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000;
+
+	if (lvds_ver < 0x30)
+		ret = call_lvds_manufacturer_script(dev, dcbent, head, script);
+	else
+		ret = run_lvds_table(dev, dcbent, head, script, pxclk);
+
+	bios->fp.last_script_invoc = (script << 1 | head);
+
+	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
+	/* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
+	nvWriteMC(dev, NV_PBUS_POWERCTRL_2, 0);
+
+	return ret;
+}
+
+struct lvdstableheader {
+	uint8_t lvds_ver, headerlen, recordlen;
+};
+
+static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct nvbios *bios, struct lvdstableheader *lth)
+{
+	/*
+	 * BMP version (0xa) LVDS table has a simple header of version and
+	 * record length. The BIT LVDS table has the typical BIT table header:
+	 * version byte, header length byte, record length byte, and a byte for
+	 * the maximum number of records that can be held in the table.
+	 */
+
+	uint8_t lvds_ver, headerlen, recordlen;
+
+	memset(lth, 0, sizeof(struct lvdstableheader));
+
+	if (bios->fp.lvdsmanufacturerpointer == 0x0) {
+		NV_ERROR(dev, "Pointer to LVDS manufacturer table invalid\n");
+		return -EINVAL;
+	}
+
+	lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
+
+	switch (lvds_ver) {
+	case 0x0a:	/* pre NV40 */
+		headerlen = 2;
+		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
+		break;
+	case 0x30:	/* NV4x */
+		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
+		if (headerlen < 0x1f) {
+			NV_ERROR(dev, "LVDS table header not understood\n");
+			return -EINVAL;
+		}
+		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
+		break;
+	case 0x40:	/* G80/G90 */
+		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
+		if (headerlen < 0x7) {
+			NV_ERROR(dev, "LVDS table header not understood\n");
+			return -EINVAL;
+		}
+		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
+		break;
+	default:
+		NV_ERROR(dev,
+			 "LVDS table revision %d.%d not currently supported\n",
+			 lvds_ver >> 4, lvds_ver & 0xf);
+		return -ENOSYS;
+	}
+
+	lth->lvds_ver = lvds_ver;
+	lth->headerlen = headerlen;
+	lth->recordlen = recordlen;
+
+	return 0;
+}
+
+static int
+get_fp_strap(struct drm_device *dev, struct nvbios *bios)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/*
+	 * The fp strap is normally dictated by the "User Strap" in
+	 * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the
+	 * Internal_Flags struct at 0x48 is set, the user strap gets overriden
+	 * by the PCI subsystem ID during POST, but not before the previous user
+	 * strap has been committed to CR58 for CR57=0xf on head A, which may be
+	 * read and used instead
+	 */
+
+	if (bios->major_version < 5 && bios->data[0x48] & 0x4)
+		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
+
+	if (dev_priv->card_type >= NV_50)
+		return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
+	else
+		return (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
+}
+
+static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
+{
+	uint8_t *fptable;
+	uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex;
+	int ret, ofs, fpstrapping;
+	struct lvdstableheader lth;
+
+	if (bios->fp.fptablepointer == 0x0) {
+		/* Apple cards don't have the fp table; the laptops use DDC */
+		/* The table is also missing on some x86 IGPs */
+#ifndef __powerpc__
+		NV_ERROR(dev, "Pointer to flat panel table invalid\n");
+#endif
+		bios->pub.digital_min_front_porch = 0x4b;
+		return 0;
+	}
+
+	fptable = &bios->data[bios->fp.fptablepointer];
+	fptable_ver = fptable[0];
+
+	switch (fptable_ver) {
+	/*
+	 * BMP version 0x5.0x11 BIOSen have version 1 like tables, but no
+	 * version field, and miss one of the spread spectrum/PWM bytes.
+	 * This could affect early GF2Go parts (not seen any appropriate ROMs
+	 * though). Here we assume that a version of 0x05 matches this case
+	 * (combining with a BMP version check would be better), as the
+	 * common case for the panel type field is 0x0005, and that is in
+	 * fact what we are reading the first byte of.
+	 */
+	case 0x05:	/* some NV10, 11, 15, 16 */
+		recordlen = 42;
+		ofs = -1;
+		break;
+	case 0x10:	/* some NV15/16, and NV11+ */
+		recordlen = 44;
+		ofs = 0;
+		break;
+	case 0x20:	/* NV40+ */
+		headerlen = fptable[1];
+		recordlen = fptable[2];
+		fpentries = fptable[3];
+		/*
+		 * fptable[4] is the minimum
+		 * RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
+		 */
+		bios->pub.digital_min_front_porch = fptable[4];
+		ofs = -7;
+		break;
+	default:
+		NV_ERROR(dev,
+			 "FP table revision %d.%d not currently supported\n",
+			 fptable_ver >> 4, fptable_ver & 0xf);
+		return -ENOSYS;
+	}
+
+	if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */
+		return 0;
+
+	ret = parse_lvds_manufacturer_table_header(dev, bios, &lth);
+	if (ret)
+		return ret;
+
+	if (lth.lvds_ver == 0x30 || lth.lvds_ver == 0x40) {
+		bios->fp.fpxlatetableptr = bios->fp.lvdsmanufacturerpointer +
+							lth.headerlen + 1;
+		bios->fp.xlatwidth = lth.recordlen;
+	}
+	if (bios->fp.fpxlatetableptr == 0x0) {
+		NV_ERROR(dev, "Pointer to flat panel xlat table invalid\n");
+		return -EINVAL;
+	}
+
+	fpstrapping = get_fp_strap(dev, bios);
+
+	fpindex = bios->data[bios->fp.fpxlatetableptr +
+					fpstrapping * bios->fp.xlatwidth];
+
+	if (fpindex > fpentries) {
+		NV_ERROR(dev, "Bad flat panel table index\n");
+		return -ENOENT;
+	}
+
+	/* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
+	if (lth.lvds_ver > 0x10)
+		bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
+
+	/*
+	 * If either the strap or xlated fpindex value are 0xf there is no
+	 * panel using a strap-derived bios mode present.  this condition
+	 * includes, but is different from, the DDC panel indicator above
+	 */
+	if (fpstrapping == 0xf || fpindex == 0xf)
+		return 0;
+
+	bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen +
+			    recordlen * fpindex + ofs;
+
+	NV_TRACE(dev, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n",
+		 ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1,
+		 ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1,
+		 ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10);
+
+	return 0;
+}
+
+bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
+
+	if (!mode)	/* just checking whether we can produce a mode */
+		return bios->fp.mode_ptr;
+
+	memset(mode, 0, sizeof(struct drm_display_mode));
+	/*
+	 * For version 1.0 (version in byte 0):
+	 * bytes 1-2 are "panel type", including bits on whether Colour/mono,
+	 * single/dual link, and type (TFT etc.)
+	 * bytes 3-6 are bits per colour in RGBX
+	 */
+	mode->clock = ROM16(mode_entry[7]) * 10;
+	/* bytes 9-10 is HActive */
+	mode->hdisplay = ROM16(mode_entry[11]) + 1;
+	/*
+	 * bytes 13-14 is HValid Start
+	 * bytes 15-16 is HValid End
+	 */
+	mode->hsync_start = ROM16(mode_entry[17]) + 1;
+	mode->hsync_end = ROM16(mode_entry[19]) + 1;
+	mode->htotal = ROM16(mode_entry[21]) + 1;
+	/* bytes 23-24, 27-30 similarly, but vertical */
+	mode->vdisplay = ROM16(mode_entry[25]) + 1;
+	mode->vsync_start = ROM16(mode_entry[31]) + 1;
+	mode->vsync_end = ROM16(mode_entry[33]) + 1;
+	mode->vtotal = ROM16(mode_entry[35]) + 1;
+	mode->flags |= (mode_entry[37] & 0x10) ?
+			DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+	mode->flags |= (mode_entry[37] & 0x1) ?
+			DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+	/*
+	 * bytes 38-39 relate to spread spectrum settings
+	 * bytes 40-43 are something to do with PWM
+	 */
+
+	mode->status = MODE_OK;
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	drm_mode_set_name(mode);
+	return bios->fp.mode_ptr;
+}
+
+int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, bool *if_is_24bit)
+{
+	/*
+	 * The LVDS table header is (mostly) described in
+	 * parse_lvds_manufacturer_table_header(): the BIT header additionally
+	 * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if
+	 * straps are not being used for the panel, this specifies the frequency
+	 * at which modes should be set up in the dual link style.
+	 *
+	 * Following the header, the BMP (ver 0xa) table has several records,
+	 * indexed by a seperate xlat table, indexed in turn by the fp strap in
+	 * EXTDEV_BOOT. Each record had a config byte, followed by 6 script
+	 * numbers for use by INIT_SUB which controlled panel init and power,
+	 * and finally a dword of ms to sleep between power off and on
+	 * operations.
+	 *
+	 * In the BIT versions, the table following the header serves as an
+	 * integrated config and xlat table: the records in the table are
+	 * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has
+	 * two bytes - the first as a config byte, the second for indexing the
+	 * fp mode table pointed to by the BIT 'D' table
+	 *
+	 * DDC is not used until after card init, so selecting the correct table
+	 * entry and setting the dual link flag for EDID equipped panels,
+	 * requiring tests against the native-mode pixel clock, cannot be done
+	 * until later, when this function should be called with non-zero pxclk
+	 */
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0;
+	struct lvdstableheader lth;
+	uint16_t lvdsofs;
+	int ret, chip_version = bios->pub.chip_version;
+
+	ret = parse_lvds_manufacturer_table_header(dev, bios, &lth);
+	if (ret)
+		return ret;
+
+	switch (lth.lvds_ver) {
+	case 0x0a:	/* pre NV40 */
+		lvdsmanufacturerindex = bios->data[
+					bios->fp.fpxlatemanufacturertableptr +
+					fpstrapping];
+
+		/* we're done if this isn't the EDID panel case */
+		if (!pxclk)
+			break;
+
+		if (chip_version < 0x25) {
+			/* nv17 behaviour
+			 *
+			 * It seems the old style lvds script pointer is reused
+			 * to select 18/24 bit colour depth for EDID panels.
+			 */
+			lvdsmanufacturerindex =
+				(bios->legacy.lvds_single_a_script_ptr & 1) ?
+									2 : 0;
+			if (pxclk >= bios->fp.duallink_transition_clk)
+				lvdsmanufacturerindex++;
+		} else if (chip_version < 0x30) {
+			/* nv28 behaviour (off-chip encoder)
+			 *
+			 * nv28 does a complex dance of first using byte 121 of
+			 * the EDID to choose the lvdsmanufacturerindex, then
+			 * later attempting to match the EDID manufacturer and
+			 * product IDs in a table (signature 'pidt' (panel id
+			 * table?)), setting an lvdsmanufacturerindex of 0 and
+			 * an fp strap of the match index (or 0xf if none)
+			 */
+			lvdsmanufacturerindex = 0;
+		} else {
+			/* nv31, nv34 behaviour */
+			lvdsmanufacturerindex = 0;
+			if (pxclk >= bios->fp.duallink_transition_clk)
+				lvdsmanufacturerindex = 2;
+			if (pxclk >= 140000)
+				lvdsmanufacturerindex = 3;
+		}
+
+		/*
+		 * nvidia set the high nibble of (cr57=f, cr58) to
+		 * lvdsmanufacturerindex in this case; we don't
+		 */
+		break;
+	case 0x30:	/* NV4x */
+	case 0x40:	/* G80/G90 */
+		lvdsmanufacturerindex = fpstrapping;
+		break;
+	default:
+		NV_ERROR(dev, "LVDS table revision not currently supported\n");
+		return -ENOSYS;
+	}
+
+	lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex;
+	switch (lth.lvds_ver) {
+	case 0x0a:
+		bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1;
+		bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2;
+		bios->fp.dual_link = bios->data[lvdsofs] & 4;
+		bios->fp.link_c_increment = bios->data[lvdsofs] & 8;
+		*if_is_24bit = bios->data[lvdsofs] & 16;
+		break;
+	case 0x30:
+		/*
+		 * My money would be on there being a 24 bit interface bit in
+		 * this table, but I have no example of a laptop bios with a
+		 * 24 bit panel to confirm that. Hence we shout loudly if any
+		 * bit other than bit 0 is set (I've not even seen bit 1)
+		 */
+		if (bios->data[lvdsofs] > 1)
+			NV_ERROR(dev,
+				 "You have a very unusual laptop display; please report it\n");
+		/*
+		 * No sign of the "power off for reset" or "reset for panel
+		 * on" bits, but it's safer to assume we should
+		 */
+		bios->fp.power_off_for_reset = true;
+		bios->fp.reset_after_pclk_change = true;
+		/*
+		 * It's ok lvdsofs is wrong for nv4x edid case; dual_link is
+		 * over-written, and BITbit1 isn't used
+		 */
+		bios->fp.dual_link = bios->data[lvdsofs] & 1;
+		bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
+		bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
+		break;
+	case 0x40:
+		bios->fp.dual_link = bios->data[lvdsofs] & 1;
+		bios->fp.if_is_24bit = bios->data[lvdsofs] & 2;
+		bios->fp.strapless_is_24bit = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
+		bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
+		break;
+	}
+
+	/* Dell Latitude D620 reports a too-high value for the dual-link
+	 * transition freq, causing us to program the panel incorrectly.
+	 *
+	 * It doesn't appear the VBIOS actually uses its transition freq
+	 * (90000kHz), instead it uses the "Number of LVDS channels" field
+	 * out of the panel ID structure (http://www.spwg.org/).
+	 *
+	 * For the moment, a quirk will do :)
+	 */
+	if ((dev->pdev->device == 0x01d7) &&
+	    (dev->pdev->subsystem_vendor == 0x1028) &&
+	    (dev->pdev->subsystem_device == 0x01c2)) {
+		bios->fp.duallink_transition_clk = 80000;
+	}
+
+	/* set dual_link flag for EDID case */
+	if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
+		bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
+
+	*dl = bios->fp.dual_link;
+
+	return 0;
+}
+
+static uint8_t *
+bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
+			 uint16_t record, int record_len, int record_nr)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint32_t entry;
+	uint16_t table;
+	int i, v;
+
+	for (i = 0; i < record_nr; i++, record += record_len) {
+		table = ROM16(bios->data[record]);
+		if (!table)
+			continue;
+		entry = ROM32(bios->data[table]);
+
+		v = (entry & 0x000f0000) >> 16;
+		if (!(v & dcbent->or))
+			continue;
+
+		v = (entry & 0x000000f0) >> 4;
+		if (v != dcbent->location)
+			continue;
+
+		v = (entry & 0x0000000f);
+		if (v != dcbent->type)
+			continue;
+
+		return &bios->data[table];
+	}
+
+	return NULL;
+}
+
+void *
+nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
+		      int *length)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint8_t *table;
+
+	if (!bios->display.dp_table_ptr) {
+		NV_ERROR(dev, "No pointer to DisplayPort table\n");
+		return NULL;
+	}
+	table = &bios->data[bios->display.dp_table_ptr];
+
+	if (table[0] != 0x21) {
+		NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
+			 table[0]);
+		return NULL;
+	}
+
+	*length = table[4];
+	return bios_output_config_match(dev, dcbent,
+					bios->display.dp_table_ptr + table[1],
+					table[2], table[3]);
+}
+
+int
+nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
+			       uint32_t sub, int pxclk)
+{
+	/*
+	 * The display script table is located by the BIT 'U' table.
+	 *
+	 * It contains an array of pointers to various tables describing
+	 * a particular output type.  The first 32-bits of the output
+	 * tables contains similar information to a DCB entry, and is
+	 * used to decide whether that particular table is suitable for
+	 * the output you want to access.
+	 *
+	 * The "record header length" field here seems to indicate the
+	 * offset of the first configuration entry in the output tables.
+	 * This is 10 on most cards I've seen, but 12 has been witnessed
+	 * on DP cards, and there's another script pointer within the
+	 * header.
+	 *
+	 * offset + 0   ( 8 bits): version
+	 * offset + 1   ( 8 bits): header length
+	 * offset + 2   ( 8 bits): record length
+	 * offset + 3   ( 8 bits): number of records
+	 * offset + 4   ( 8 bits): record header length
+	 * offset + 5   (16 bits): pointer to first output script table
+	 */
+
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint8_t *table = &bios->data[bios->display.script_table_ptr];
+	uint8_t *otable = NULL;
+	uint16_t script;
+	int i = 0;
+
+	if (!bios->display.script_table_ptr) {
+		NV_ERROR(dev, "No pointer to output script table\n");
+		return 1;
+	}
+
+	/*
+	 * Nothing useful has been in any of the pre-2.0 tables I've seen,
+	 * so until they are, we really don't need to care.
+	 */
+	if (table[0] < 0x20)
+		return 1;
+
+	if (table[0] != 0x20 && table[0] != 0x21) {
+		NV_ERROR(dev, "Output script table version 0x%02x unknown\n",
+			 table[0]);
+		return 1;
+	}
+
+	/*
+	 * The output script tables describing a particular output type
+	 * look as follows:
+	 *
+	 * offset + 0   (32 bits): output this table matches (hash of DCB)
+	 * offset + 4   ( 8 bits): unknown
+	 * offset + 5   ( 8 bits): number of configurations
+	 * offset + 6   (16 bits): pointer to some script
+	 * offset + 8   (16 bits): pointer to some script
+	 *
+	 * headerlen == 10
+	 * offset + 10           : configuration 0
+	 *
+	 * headerlen == 12
+	 * offset + 10           : pointer to some script
+	 * offset + 12           : configuration 0
+	 *
+	 * Each config entry is as follows:
+	 *
+	 * offset + 0   (16 bits): unknown, assumed to be a match value
+	 * offset + 2   (16 bits): pointer to script table (clock set?)
+	 * offset + 4   (16 bits): pointer to script table (reset?)
+	 *
+	 * There doesn't appear to be a count value to say how many
+	 * entries exist in each script table, instead, a 0 value in
+	 * the first 16-bit word seems to indicate both the end of the
+	 * list and the default entry.  The second 16-bit word in the
+	 * script tables is a pointer to the script to execute.
+	 */
+
+	NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n",
+			dcbent->type, dcbent->location, dcbent->or);
+	otable = bios_output_config_match(dev, dcbent, table[1] +
+					  bios->display.script_table_ptr,
+					  table[2], table[3]);
+	if (!otable) {
+		NV_ERROR(dev, "Couldn't find matching output script table\n");
+		return 1;
+	}
+
+	if (pxclk < -2 || pxclk > 0) {
+		/* Try to find matching script table entry */
+		for (i = 0; i < otable[5]; i++) {
+			if (ROM16(otable[table[4] + i*6]) == sub)
+				break;
+		}
+
+		if (i == otable[5]) {
+			NV_ERROR(dev, "Table 0x%04x not found for %d/%d, "
+				      "using first\n",
+				 sub, dcbent->type, dcbent->or);
+			i = 0;
+		}
+	}
+
+	if (pxclk == 0) {
+		script = ROM16(otable[6]);
+		if (!script) {
+			NV_DEBUG_KMS(dev, "output script 0 not found\n");
+			return 1;
+		}
+
+		NV_TRACE(dev, "0x%04X: parsing output script 0\n", script);
+		nouveau_bios_run_init_table(dev, script, dcbent);
+	} else
+	if (pxclk == -1) {
+		script = ROM16(otable[8]);
+		if (!script) {
+			NV_DEBUG_KMS(dev, "output script 1 not found\n");
+			return 1;
+		}
+
+		NV_TRACE(dev, "0x%04X: parsing output script 1\n", script);
+		nouveau_bios_run_init_table(dev, script, dcbent);
+	} else
+	if (pxclk == -2) {
+		if (table[4] >= 12)
+			script = ROM16(otable[10]);
+		else
+			script = 0;
+		if (!script) {
+			NV_DEBUG_KMS(dev, "output script 2 not found\n");
+			return 1;
+		}
+
+		NV_TRACE(dev, "0x%04X: parsing output script 2\n", script);
+		nouveau_bios_run_init_table(dev, script, dcbent);
+	} else
+	if (pxclk > 0) {
+		script = ROM16(otable[table[4] + i*6 + 2]);
+		if (script)
+			script = clkcmptable(bios, script, pxclk);
+		if (!script) {
+			NV_ERROR(dev, "clock script 0 not found\n");
+			return 1;
+		}
+
+		NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script);
+		nouveau_bios_run_init_table(dev, script, dcbent);
+	} else
+	if (pxclk < 0) {
+		script = ROM16(otable[table[4] + i*6 + 4]);
+		if (script)
+			script = clkcmptable(bios, script, -pxclk);
+		if (!script) {
+			NV_DEBUG_KMS(dev, "clock script 1 not found\n");
+			return 1;
+		}
+
+		NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script);
+		nouveau_bios_run_init_table(dev, script, dcbent);
+	}
+
+	return 0;
+}
+
+
+int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, int pxclk)
+{
+	/*
+	 * the pxclk parameter is in kHz
+	 *
+	 * This runs the TMDS regs setting code found on BIT bios cards
+	 *
+	 * For ffs(or) == 1 use the first table, for ffs(or) == 2 and
+	 * ffs(or) == 3, use the second.
+	 */
+
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	int cv = bios->pub.chip_version;
+	uint16_t clktable = 0, scriptptr;
+	uint32_t sel_clk_binding, sel_clk;
+
+	/* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */
+	if (cv >= 0x17 && cv != 0x1a && cv != 0x20 &&
+	    dcbent->location != DCB_LOC_ON_CHIP)
+		return 0;
+
+	switch (ffs(dcbent->or)) {
+	case 1:
+		clktable = bios->tmds.output0_script_ptr;
+		break;
+	case 2:
+	case 3:
+		clktable = bios->tmds.output1_script_ptr;
+		break;
+	}
+
+	if (!clktable) {
+		NV_ERROR(dev, "Pixel clock comparison table not found\n");
+		return -EINVAL;
+	}
+
+	scriptptr = clkcmptable(bios, clktable, pxclk);
+
+	if (!scriptptr) {
+		NV_ERROR(dev, "TMDS output init script not found\n");
+		return -ENOENT;
+	}
+
+	/* don't let script change pll->head binding */
+	sel_clk_binding = bios_rd32(bios, NV_PRAMDAC_SEL_CLK) & 0x50000;
+	run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000);
+	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
+
+	return 0;
+}
+
+int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim)
+{
+	/*
+	 * PLL limits table
+	 *
+	 * Version 0x10: NV30, NV31
+	 * One byte header (version), one record of 24 bytes
+	 * Version 0x11: NV36 - Not implemented
+	 * Seems to have same record style as 0x10, but 3 records rather than 1
+	 * Version 0x20: Found on Geforce 6 cards
+	 * Trivial 4 byte BIT header. 31 (0x1f) byte record length
+	 * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards
+	 * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record
+	 * length in general, some (integrated) have an extra configuration byte
+	 * Version 0x30: Found on Geforce 8, separates the register mapping
+	 * from the limits tables.
+	 */
+
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	int cv = bios->pub.chip_version, pllindex = 0;
+	uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0;
+	uint32_t crystal_strap_mask, crystal_straps;
+
+	if (!bios->pll_limit_tbl_ptr) {
+		if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
+		    cv >= 0x40) {
+			NV_ERROR(dev, "Pointer to PLL limits table invalid\n");
+			return -EINVAL;
+		}
+	} else
+		pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr];
+
+	crystal_strap_mask = 1 << 6;
+	/* open coded dev->twoHeads test */
+	if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20)
+		crystal_strap_mask |= 1 << 22;
+	crystal_straps = nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) &
+							crystal_strap_mask;
+
+	switch (pll_lim_ver) {
+	/*
+	 * We use version 0 to indicate a pre limit table bios (single stage
+	 * pll) and load the hard coded limits instead.
+	 */
+	case 0:
+		break;
+	case 0x10:
+	case 0x11:
+		/*
+		 * Strictly v0x11 has 3 entries, but the last two don't seem
+		 * to get used.
+		 */
+		headerlen = 1;
+		recordlen = 0x18;
+		entries = 1;
+		pllindex = 0;
+		break;
+	case 0x20:
+	case 0x21:
+	case 0x30:
+	case 0x40:
+		headerlen = bios->data[bios->pll_limit_tbl_ptr + 1];
+		recordlen = bios->data[bios->pll_limit_tbl_ptr + 2];
+		entries = bios->data[bios->pll_limit_tbl_ptr + 3];
+		break;
+	default:
+		NV_ERROR(dev, "PLL limits table revision 0x%X not currently "
+				"supported\n", pll_lim_ver);
+		return -ENOSYS;
+	}
+
+	/* initialize all members to zero */
+	memset(pll_lim, 0, sizeof(struct pll_lims));
+
+	if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) {
+		uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex];
+
+		pll_lim->vco1.minfreq = ROM32(pll_rec[0]);
+		pll_lim->vco1.maxfreq = ROM32(pll_rec[4]);
+		pll_lim->vco2.minfreq = ROM32(pll_rec[8]);
+		pll_lim->vco2.maxfreq = ROM32(pll_rec[12]);
+		pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]);
+		pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]);
+		pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX;
+
+		/* these values taken from nv30/31/36 */
+		pll_lim->vco1.min_n = 0x1;
+		if (cv == 0x36)
+			pll_lim->vco1.min_n = 0x5;
+		pll_lim->vco1.max_n = 0xff;
+		pll_lim->vco1.min_m = 0x1;
+		pll_lim->vco1.max_m = 0xd;
+		pll_lim->vco2.min_n = 0x4;
+		/*
+		 * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this
+		 * table version (apart from nv35)), N2 is compared to
+		 * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and
+		 * save a comparison
+		 */
+		pll_lim->vco2.max_n = 0x28;
+		if (cv == 0x30 || cv == 0x35)
+			/* only 5 bits available for N2 on nv30/35 */
+			pll_lim->vco2.max_n = 0x1f;
+		pll_lim->vco2.min_m = 0x1;
+		pll_lim->vco2.max_m = 0x4;
+		pll_lim->max_log2p = 0x7;
+		pll_lim->max_usable_log2p = 0x6;
+	} else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) {
+		uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen;
+		uint32_t reg = 0; /* default match */
+		uint8_t *pll_rec;
+		int i;
+
+		/*
+		 * First entry is default match, if nothing better. warn if
+		 * reg field nonzero
+		 */
+		if (ROM32(bios->data[plloffs]))
+			NV_WARN(dev, "Default PLL limit entry has non-zero "
+				       "register field\n");
+
+		if (limit_match > MAX_PLL_TYPES)
+			/* we've been passed a reg as the match */
+			reg = limit_match;
+		else /* limit match is a pll type */
+			for (i = 1; i < entries && !reg; i++) {
+				uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]);
+
+				if (limit_match == NVPLL &&
+				    (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000))
+					reg = cmpreg;
+				if (limit_match == MPLL &&
+				    (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020))
+					reg = cmpreg;
+				if (limit_match == VPLL1 &&
+				    (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010))
+					reg = cmpreg;
+				if (limit_match == VPLL2 &&
+				    (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018))
+					reg = cmpreg;
+			}
+
+		for (i = 1; i < entries; i++)
+			if (ROM32(bios->data[plloffs + recordlen * i]) == reg) {
+				pllindex = i;
+				break;
+			}
+
+		pll_rec = &bios->data[plloffs + recordlen * pllindex];
+
+		BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n",
+			pllindex ? reg : 0);
+
+		/*
+		 * Frequencies are stored in tables in MHz, kHz are more
+		 * useful, so we convert.
+		 */
+
+		/* What output frequencies can each VCO generate? */
+		pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000;
+		pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000;
+		pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000;
+		pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000;
+
+		/* What input frequencies they accept (past the m-divider)? */
+		pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000;
+		pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000;
+		pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000;
+		pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000;
+
+		/* What values are accepted as multiplier and divider? */
+		pll_lim->vco1.min_n = pll_rec[20];
+		pll_lim->vco1.max_n = pll_rec[21];
+		pll_lim->vco1.min_m = pll_rec[22];
+		pll_lim->vco1.max_m = pll_rec[23];
+		pll_lim->vco2.min_n = pll_rec[24];
+		pll_lim->vco2.max_n = pll_rec[25];
+		pll_lim->vco2.min_m = pll_rec[26];
+		pll_lim->vco2.max_m = pll_rec[27];
+
+		pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29];
+		if (pll_lim->max_log2p > 0x7)
+			/* pll decoding in nv_hw.c assumes never > 7 */
+			NV_WARN(dev, "Max log2 P value greater than 7 (%d)\n",
+				pll_lim->max_log2p);
+		if (cv < 0x60)
+			pll_lim->max_usable_log2p = 0x6;
+		pll_lim->log2p_bias = pll_rec[30];
+
+		if (recordlen > 0x22)
+			pll_lim->refclk = ROM32(pll_rec[31]);
+
+		if (recordlen > 0x23 && pll_rec[35])
+			NV_WARN(dev,
+				"Bits set in PLL configuration byte (%x)\n",
+				pll_rec[35]);
+
+		/* C51 special not seen elsewhere */
+		if (cv == 0x51 && !pll_lim->refclk) {
+			uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK);
+
+			if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) ||
+			    ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) {
+				if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3)
+					pll_lim->refclk = 200000;
+				else
+					pll_lim->refclk = 25000;
+			}
+		}
+	} else if (pll_lim_ver == 0x30) { /* ver 0x30 */
+		uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen];
+		uint8_t *record = NULL;
+		int i;
+
+		BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n",
+			limit_match);
+
+		for (i = 0; i < entries; i++, entry += recordlen) {
+			if (ROM32(entry[3]) == limit_match) {
+				record = &bios->data[ROM16(entry[1])];
+				break;
+			}
+		}
+
+		if (!record) {
+			NV_ERROR(dev, "Register 0x%08x not found in PLL "
+				 "limits table", limit_match);
+			return -ENOENT;
+		}
+
+		pll_lim->vco1.minfreq = ROM16(record[0]) * 1000;
+		pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000;
+		pll_lim->vco2.minfreq = ROM16(record[4]) * 1000;
+		pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000;
+		pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000;
+		pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000;
+		pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000;
+		pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000;
+		pll_lim->vco1.min_n = record[16];
+		pll_lim->vco1.max_n = record[17];
+		pll_lim->vco1.min_m = record[18];
+		pll_lim->vco1.max_m = record[19];
+		pll_lim->vco2.min_n = record[20];
+		pll_lim->vco2.max_n = record[21];
+		pll_lim->vco2.min_m = record[22];
+		pll_lim->vco2.max_m = record[23];
+		pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25];
+		pll_lim->log2p_bias = record[27];
+		pll_lim->refclk = ROM32(record[28]);
+	} else if (pll_lim_ver) { /* ver 0x40 */
+		uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen];
+		uint8_t *record = NULL;
+		int i;
+
+		BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n",
+			limit_match);
+
+		for (i = 0; i < entries; i++, entry += recordlen) {
+			if (ROM32(entry[3]) == limit_match) {
+				record = &bios->data[ROM16(entry[1])];
+				break;
+			}
+		}
+
+		if (!record) {
+			NV_ERROR(dev, "Register 0x%08x not found in PLL "
+				 "limits table", limit_match);
+			return -ENOENT;
+		}
+
+		pll_lim->vco1.minfreq = ROM16(record[0]) * 1000;
+		pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000;
+		pll_lim->vco1.min_inputfreq = ROM16(record[4]) * 1000;
+		pll_lim->vco1.max_inputfreq = ROM16(record[6]) * 1000;
+		pll_lim->vco1.min_m = record[8];
+		pll_lim->vco1.max_m = record[9];
+		pll_lim->vco1.min_n = record[10];
+		pll_lim->vco1.max_n = record[11];
+		pll_lim->min_p = record[12];
+		pll_lim->max_p = record[13];
+		/* where did this go to?? */
+		if (limit_match == 0x00614100 || limit_match == 0x00614900)
+			pll_lim->refclk = 27000;
+		else
+			pll_lim->refclk = 100000;
+	}
+
+	/*
+	 * By now any valid limit table ought to have set a max frequency for
+	 * vco1, so if it's zero it's either a pre limit table bios, or one
+	 * with an empty limit table (seen on nv18)
+	 */
+	if (!pll_lim->vco1.maxfreq) {
+		pll_lim->vco1.minfreq = bios->fminvco;
+		pll_lim->vco1.maxfreq = bios->fmaxvco;
+		pll_lim->vco1.min_inputfreq = 0;
+		pll_lim->vco1.max_inputfreq = INT_MAX;
+		pll_lim->vco1.min_n = 0x1;
+		pll_lim->vco1.max_n = 0xff;
+		pll_lim->vco1.min_m = 0x1;
+		if (crystal_straps == 0) {
+			/* nv05 does this, nv11 doesn't, nv10 unknown */
+			if (cv < 0x11)
+				pll_lim->vco1.min_m = 0x7;
+			pll_lim->vco1.max_m = 0xd;
+		} else {
+			if (cv < 0x11)
+				pll_lim->vco1.min_m = 0x8;
+			pll_lim->vco1.max_m = 0xe;
+		}
+		if (cv < 0x17 || cv == 0x1a || cv == 0x20)
+			pll_lim->max_log2p = 4;
+		else
+			pll_lim->max_log2p = 5;
+		pll_lim->max_usable_log2p = pll_lim->max_log2p;
+	}
+
+	if (!pll_lim->refclk)
+		switch (crystal_straps) {
+		case 0:
+			pll_lim->refclk = 13500;
+			break;
+		case (1 << 6):
+			pll_lim->refclk = 14318;
+			break;
+		case (1 << 22):
+			pll_lim->refclk = 27000;
+			break;
+		case (1 << 22 | 1 << 6):
+			pll_lim->refclk = 25000;
+			break;
+		}
+
+#if 0 /* for easy debugging */
+	ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
+	ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
+	ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
+	ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
+
+	ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
+	ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
+	ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
+	ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
+
+	ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
+	ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
+	ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
+	ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
+	ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
+	ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
+	ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
+	ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
+
+	ErrorF("pll.max_log2p: %d\n", pll_lim->max_log2p);
+	ErrorF("pll.log2p_bias: %d\n", pll_lim->log2p_bias);
+
+	ErrorF("pll.refclk: %d\n", pll_lim->refclk);
+#endif
+
+	return 0;
+}
+
+static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset)
+{
+	/*
+	 * offset + 0  (8 bits): Micro version
+	 * offset + 1  (8 bits): Minor version
+	 * offset + 2  (8 bits): Chip version
+	 * offset + 3  (8 bits): Major version
+	 */
+
+	bios->major_version = bios->data[offset + 3];
+	bios->pub.chip_version = bios->data[offset + 2];
+	NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n",
+		 bios->data[offset + 3], bios->data[offset + 2],
+		 bios->data[offset + 1], bios->data[offset]);
+}
+
+static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset)
+{
+	/*
+	 * Parses the init table segment for pointers used in script execution.
+	 *
+	 * offset + 0  (16 bits): init script tables pointer
+	 * offset + 2  (16 bits): macro index table pointer
+	 * offset + 4  (16 bits): macro table pointer
+	 * offset + 6  (16 bits): condition table pointer
+	 * offset + 8  (16 bits): io condition table pointer
+	 * offset + 10 (16 bits): io flag condition table pointer
+	 * offset + 12 (16 bits): init function table pointer
+	 */
+
+	bios->init_script_tbls_ptr = ROM16(bios->data[offset]);
+	bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]);
+	bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]);
+	bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]);
+	bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]);
+	bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]);
+	bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]);
+}
+
+static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the load detect values for g80 cards.
+	 *
+	 * offset + 0 (16 bits): loadval table pointer
+	 */
+
+	uint16_t load_table_ptr;
+	uint8_t version, headerlen, entrylen, num_entries;
+
+	if (bitentry->length != 3) {
+		NV_ERROR(dev, "Do not understand BIT A table\n");
+		return -EINVAL;
+	}
+
+	load_table_ptr = ROM16(bios->data[bitentry->offset]);
+
+	if (load_table_ptr == 0x0) {
+		NV_ERROR(dev, "Pointer to BIT loadval table invalid\n");
+		return -EINVAL;
+	}
+
+	version = bios->data[load_table_ptr];
+
+	if (version != 0x10) {
+		NV_ERROR(dev, "BIT loadval table version %d.%d not supported\n",
+			 version >> 4, version & 0xF);
+		return -ENOSYS;
+	}
+
+	headerlen = bios->data[load_table_ptr + 1];
+	entrylen = bios->data[load_table_ptr + 2];
+	num_entries = bios->data[load_table_ptr + 3];
+
+	if (headerlen != 4 || entrylen != 4 || num_entries != 2) {
+		NV_ERROR(dev, "Do not understand BIT loadval table\n");
+		return -EINVAL;
+	}
+
+	/* First entry is normal dac, 2nd tv-out perhaps? */
+	bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
+
+	return 0;
+}
+
+static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * offset + 8  (16 bits): PLL limits table pointer
+	 *
+	 * There's more in here, but that's unknown.
+	 */
+
+	if (bitentry->length < 10) {
+		NV_ERROR(dev, "Do not understand BIT C table\n");
+		return -EINVAL;
+	}
+
+	bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]);
+
+	return 0;
+}
+
+static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the flat panel table segment that the bit entry points to.
+	 * Starting at bitentry->offset:
+	 *
+	 * offset + 0  (16 bits): ??? table pointer - seems to have 18 byte
+	 * records beginning with a freq.
+	 * offset + 2  (16 bits): mode table pointer
+	 */
+
+	if (bitentry->length != 4) {
+		NV_ERROR(dev, "Do not understand BIT display table\n");
+		return -EINVAL;
+	}
+
+	bios->fp.fptablepointer = ROM16(bios->data[bitentry->offset + 2]);
+
+	return 0;
+}
+
+static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the init table segment that the bit entry points to.
+	 *
+	 * See parse_script_table_pointers for layout
+	 */
+
+	if (bitentry->length < 14) {
+		NV_ERROR(dev, "Do not understand init table\n");
+		return -EINVAL;
+	}
+
+	parse_script_table_pointers(bios, bitentry->offset);
+
+	if (bitentry->length >= 16)
+		bios->some_script_ptr = ROM16(bios->data[bitentry->offset + 14]);
+	if (bitentry->length >= 18)
+		bios->init96_tbl_ptr = ROM16(bios->data[bitentry->offset + 16]);
+
+	return 0;
+}
+
+static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * BIT 'i' (info?) table
+	 *
+	 * offset + 0  (32 bits): BIOS version dword (as in B table)
+	 * offset + 5  (8  bits): BIOS feature byte (same as for BMP?)
+	 * offset + 13 (16 bits): pointer to table containing DAC load
+	 * detection comparison values
+	 *
+	 * There's other things in the table, purpose unknown
+	 */
+
+	uint16_t daccmpoffset;
+	uint8_t dacver, dacheaderlen;
+
+	if (bitentry->length < 6) {
+		NV_ERROR(dev, "BIT i table too short for needed information\n");
+		return -EINVAL;
+	}
+
+	parse_bios_version(dev, bios, bitentry->offset);
+
+	/*
+	 * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's
+	 * Quadro identity crisis), other bits possibly as for BMP feature byte
+	 */
+	bios->feature_byte = bios->data[bitentry->offset + 5];
+	bios->is_mobile = bios->feature_byte & FEATURE_MOBILE;
+
+	if (bitentry->length < 15) {
+		NV_WARN(dev, "BIT i table not long enough for DAC load "
+			       "detection comparison table\n");
+		return -EINVAL;
+	}
+
+	daccmpoffset = ROM16(bios->data[bitentry->offset + 13]);
+
+	/* doesn't exist on g80 */
+	if (!daccmpoffset)
+		return 0;
+
+	/*
+	 * The first value in the table, following the header, is the
+	 * comparison value, the second entry is a comparison value for
+	 * TV load detection.
+	 */
+
+	dacver = bios->data[daccmpoffset];
+	dacheaderlen = bios->data[daccmpoffset + 1];
+
+	if (dacver != 0x00 && dacver != 0x10) {
+		NV_WARN(dev, "DAC load detection comparison table version "
+			       "%d.%d not known\n", dacver >> 4, dacver & 0xf);
+		return -ENOSYS;
+	}
+
+	bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
+	bios->pub.tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
+
+	return 0;
+}
+
+static int parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the LVDS table segment that the bit entry points to.
+	 * Starting at bitentry->offset:
+	 *
+	 * offset + 0  (16 bits): LVDS strap xlate table pointer
+	 */
+
+	if (bitentry->length != 2) {
+		NV_ERROR(dev, "Do not understand BIT LVDS table\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * No idea if it's still called the LVDS manufacturer table, but
+	 * the concept's close enough.
+	 */
+	bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]);
+
+	return 0;
+}
+
+static int
+parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios,
+		      struct bit_entry *bitentry)
+{
+	/*
+	 * offset + 2  (8  bits): number of options in an
+	 * 	INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set
+	 * offset + 3  (16 bits): pointer to strap xlate table for RAM
+	 * 	restrict option selection
+	 *
+	 * There's a bunch of bits in this table other than the RAM restrict
+	 * stuff that we don't use - their use currently unknown
+	 */
+
+	/*
+	 * Older bios versions don't have a sufficiently long table for
+	 * what we want
+	 */
+	if (bitentry->length < 0x5)
+		return 0;
+
+	if (bitentry->id[1] < 2) {
+		bios->ram_restrict_group_count = bios->data[bitentry->offset + 2];
+		bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]);
+	} else {
+		bios->ram_restrict_group_count = bios->data[bitentry->offset + 0];
+		bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 1]);
+	}
+
+	return 0;
+}
+
+static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the pointer to the TMDS table
+	 *
+	 * Starting at bitentry->offset:
+	 *
+	 * offset + 0  (16 bits): TMDS table pointer
+	 *
+	 * The TMDS table is typically found just before the DCB table, with a
+	 * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being
+	 * length?)
+	 *
+	 * At offset +7 is a pointer to a script, which I don't know how to
+	 * run yet.
+	 * At offset +9 is a pointer to another script, likewise
+	 * Offset +11 has a pointer to a table where the first word is a pxclk
+	 * frequency and the second word a pointer to a script, which should be
+	 * run if the comparison pxclk frequency is less than the pxclk desired.
+	 * This repeats for decreasing comparison frequencies
+	 * Offset +13 has a pointer to a similar table
+	 * The selection of table (and possibly +7/+9 script) is dictated by
+	 * "or" from the DCB.
+	 */
+
+	uint16_t tmdstableptr, script1, script2;
+
+	if (bitentry->length != 2) {
+		NV_ERROR(dev, "Do not understand BIT TMDS table\n");
+		return -EINVAL;
+	}
+
+	tmdstableptr = ROM16(bios->data[bitentry->offset]);
+
+	if (tmdstableptr == 0x0) {
+		NV_ERROR(dev, "Pointer to TMDS table invalid\n");
+		return -EINVAL;
+	}
+
+	/* nv50+ has v2.0, but we don't parse it atm */
+	if (bios->data[tmdstableptr] != 0x11) {
+		NV_WARN(dev,
+			"TMDS table revision %d.%d not currently supported\n",
+			bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
+		return -ENOSYS;
+	}
+
+	/*
+	 * These two scripts are odd: they don't seem to get run even when
+	 * they are not stubbed.
+	 */
+	script1 = ROM16(bios->data[tmdstableptr + 7]);
+	script2 = ROM16(bios->data[tmdstableptr + 9]);
+	if (bios->data[script1] != 'q' || bios->data[script2] != 'q')
+		NV_WARN(dev, "TMDS table script pointers not stubbed\n");
+
+	bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]);
+	bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]);
+
+	return 0;
+}
+
+static int
+parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios,
+		      struct bit_entry *bitentry)
+{
+	/*
+	 * Parses the pointer to the G80 output script tables
+	 *
+	 * Starting at bitentry->offset:
+	 *
+	 * offset + 0  (16 bits): output script table pointer
+	 */
+
+	uint16_t outputscripttableptr;
+
+	if (bitentry->length != 3) {
+		NV_ERROR(dev, "Do not understand BIT U table\n");
+		return -EINVAL;
+	}
+
+	outputscripttableptr = ROM16(bios->data[bitentry->offset]);
+	bios->display.script_table_ptr = outputscripttableptr;
+	return 0;
+}
+
+static int
+parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios,
+				struct bit_entry *bitentry)
+{
+	bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]);
+	return 0;
+}
+
+struct bit_table {
+	const char id;
+	int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *);
+};
+
+#define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry })
+
+static int
+parse_bit_table(struct nvbios *bios, const uint16_t bitoffset,
+		struct bit_table *table)
+{
+	struct drm_device *dev = bios->dev;
+	uint8_t maxentries = bios->data[bitoffset + 4];
+	int i, offset;
+	struct bit_entry bitentry;
+
+	for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) {
+		bitentry.id[0] = bios->data[offset];
+
+		if (bitentry.id[0] != table->id)
+			continue;
+
+		bitentry.id[1] = bios->data[offset + 1];
+		bitentry.length = ROM16(bios->data[offset + 2]);
+		bitentry.offset = ROM16(bios->data[offset + 4]);
+
+		return table->parse_fn(dev, bios, &bitentry);
+	}
+
+	NV_INFO(dev, "BIT table '%c' not found\n", table->id);
+	return -ENOSYS;
+}
+
+static int
+parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset)
+{
+	int ret;
+
+	/*
+	 * The only restriction on parsing order currently is having 'i' first
+	 * for use of bios->*_version or bios->feature_byte while parsing;
+	 * functions shouldn't be actually *doing* anything apart from pulling
+	 * data from the image into the bios struct, thus no interdependencies
+	 */
+	ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('i', i));
+	if (ret) /* info? */
+		return ret;
+	if (bios->major_version >= 0x60) /* g80+ */
+		parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A));
+	ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('C', C));
+	if (ret)
+		return ret;
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display));
+	ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init));
+	if (ret)
+		return ret;
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U));
+	parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport));
+
+	return 0;
+}
+
+static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsigned int offset)
+{
+	/*
+	 * Parses the BMP structure for useful things, but does not act on them
+	 *
+	 * offset +   5: BMP major version
+	 * offset +   6: BMP minor version
+	 * offset +   9: BMP feature byte
+	 * offset +  10: BCD encoded BIOS version
+	 *
+	 * offset +  18: init script table pointer (for bios versions < 5.10h)
+	 * offset +  20: extra init script table pointer (for bios
+	 * versions < 5.10h)
+	 *
+	 * offset +  24: memory init table pointer (used on early bios versions)
+	 * offset +  26: SDR memory sequencing setup data table
+	 * offset +  28: DDR memory sequencing setup data table
+	 *
+	 * offset +  54: index of I2C CRTC pair to use for CRT output
+	 * offset +  55: index of I2C CRTC pair to use for TV output
+	 * offset +  56: index of I2C CRTC pair to use for flat panel output
+	 * offset +  58: write CRTC index for I2C pair 0
+	 * offset +  59: read CRTC index for I2C pair 0
+	 * offset +  60: write CRTC index for I2C pair 1
+	 * offset +  61: read CRTC index for I2C pair 1
+	 *
+	 * offset +  67: maximum internal PLL frequency (single stage PLL)
+	 * offset +  71: minimum internal PLL frequency (single stage PLL)
+	 *
+	 * offset +  75: script table pointers, as described in
+	 * parse_script_table_pointers
+	 *
+	 * offset +  89: TMDS single link output A table pointer
+	 * offset +  91: TMDS single link output B table pointer
+	 * offset +  95: LVDS single link output A table pointer
+	 * offset + 105: flat panel timings table pointer
+	 * offset + 107: flat panel strapping translation table pointer
+	 * offset + 117: LVDS manufacturer panel config table pointer
+	 * offset + 119: LVDS manufacturer strapping translation table pointer
+	 *
+	 * offset + 142: PLL limits table pointer
+	 *
+	 * offset + 156: minimum pixel clock for LVDS dual link
+	 */
+
+	uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor;
+	uint16_t bmplength;
+	uint16_t legacy_scripts_offset, legacy_i2c_offset;
+
+	/* load needed defaults in case we can't parse this info */
+	bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
+	bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
+	bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
+	bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
+	bios->pub.digital_min_front_porch = 0x4b;
+	bios->fmaxvco = 256000;
+	bios->fminvco = 128000;
+	bios->fp.duallink_transition_clk = 90000;
+
+	bmp_version_major = bmp[5];
+	bmp_version_minor = bmp[6];
+
+	NV_TRACE(dev, "BMP version %d.%d\n",
+		 bmp_version_major, bmp_version_minor);
+
+	/*
+	 * Make sure that 0x36 is blank and can't be mistaken for a DCB
+	 * pointer on early versions
+	 */
+	if (bmp_version_major < 5)
+		*(uint16_t *)&bios->data[0x36] = 0;
+
+	/*
+	 * Seems that the minor version was 1 for all major versions prior
+	 * to 5. Version 6 could theoretically exist, but I suspect BIT
+	 * happened instead.
+	 */
+	if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) {
+		NV_ERROR(dev, "You have an unsupported BMP version. "
+				"Please send in your bios\n");
+		return -ENOSYS;
+	}
+
+	if (bmp_version_major == 0)
+		/* nothing that's currently useful in this version */
+		return 0;
+	else if (bmp_version_major == 1)
+		bmplength = 44; /* exact for 1.01 */
+	else if (bmp_version_major == 2)
+		bmplength = 48; /* exact for 2.01 */
+	else if (bmp_version_major == 3)
+		bmplength = 54;
+		/* guessed - mem init tables added in this version */
+	else if (bmp_version_major == 4 || bmp_version_minor < 0x1)
+		/* don't know if 5.0 exists... */
+		bmplength = 62;
+		/* guessed - BMP I2C indices added in version 4*/
+	else if (bmp_version_minor < 0x6)
+		bmplength = 67; /* exact for 5.01 */
+	else if (bmp_version_minor < 0x10)
+		bmplength = 75; /* exact for 5.06 */
+	else if (bmp_version_minor == 0x10)
+		bmplength = 89; /* exact for 5.10h */
+	else if (bmp_version_minor < 0x14)
+		bmplength = 118; /* exact for 5.11h */
+	else if (bmp_version_minor < 0x24)
+		/*
+		 * Not sure of version where pll limits came in;
+		 * certainly exist by 0x24 though.
+		 */
+		/* length not exact: this is long enough to get lvds members */
+		bmplength = 123;
+	else if (bmp_version_minor < 0x27)
+		/*
+		 * Length not exact: this is long enough to get pll limit
+		 * member
+		 */
+		bmplength = 144;
+	else
+		/*
+		 * Length not exact: this is long enough to get dual link
+		 * transition clock.
+		 */
+		bmplength = 158;
+
+	/* checksum */
+	if (nv_cksum(bmp, 8)) {
+		NV_ERROR(dev, "Bad BMP checksum\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Bit 4 seems to indicate either a mobile bios or a quadro card --
+	 * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl
+	 * (not nv10gl), bit 5 that the flat panel tables are present, and
+	 * bit 6 a tv bios.
+	 */
+	bios->feature_byte = bmp[9];
+
+	parse_bios_version(dev, bios, offset + 10);
+
+	if (bmp_version_major < 5 || bmp_version_minor < 0x10)
+		bios->old_style_init = true;
+	legacy_scripts_offset = 18;
+	if (bmp_version_major < 2)
+		legacy_scripts_offset -= 4;
+	bios->init_script_tbls_ptr = ROM16(bmp[legacy_scripts_offset]);
+	bios->extra_init_script_tbl_ptr = ROM16(bmp[legacy_scripts_offset + 2]);
+
+	if (bmp_version_major > 2) {	/* appears in BMP 3 */
+		bios->legacy.mem_init_tbl_ptr = ROM16(bmp[24]);
+		bios->legacy.sdr_seq_tbl_ptr = ROM16(bmp[26]);
+		bios->legacy.ddr_seq_tbl_ptr = ROM16(bmp[28]);
+	}
+
+	legacy_i2c_offset = 0x48;	/* BMP version 2 & 3 */
+	if (bmplength > 61)
+		legacy_i2c_offset = offset + 54;
+	bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
+	bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
+	bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
+	bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
+	bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
+	bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
+	bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
+
+	if (bmplength > 74) {
+		bios->fmaxvco = ROM32(bmp[67]);
+		bios->fminvco = ROM32(bmp[71]);
+	}
+	if (bmplength > 88)
+		parse_script_table_pointers(bios, offset + 75);
+	if (bmplength > 94) {
+		bios->tmds.output0_script_ptr = ROM16(bmp[89]);
+		bios->tmds.output1_script_ptr = ROM16(bmp[91]);
+		/*
+		 * Never observed in use with lvds scripts, but is reused for
+		 * 18/24 bit panel interface default for EDID equipped panels
+		 * (if_is_24bit not set directly to avoid any oscillation).
+		 */
+		bios->legacy.lvds_single_a_script_ptr = ROM16(bmp[95]);
+	}
+	if (bmplength > 108) {
+		bios->fp.fptablepointer = ROM16(bmp[105]);
+		bios->fp.fpxlatetableptr = ROM16(bmp[107]);
+		bios->fp.xlatwidth = 1;
+	}
+	if (bmplength > 120) {
+		bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]);
+		bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]);
+	}
+	if (bmplength > 143)
+		bios->pll_limit_tbl_ptr = ROM16(bmp[142]);
+
+	if (bmplength > 157)
+		bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10;
+
+	return 0;
+}
+
+static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
+{
+	int i, j;
+
+	for (i = 0; i <= (n - len); i++) {
+		for (j = 0; j < len; j++)
+			if (data[i + j] != str[j])
+				break;
+		if (j == len)
+			return i;
+	}
+
+	return 0;
+}
+
+static int
+read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
+{
+	uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
+	int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
+	int recordoffset = 0, rdofs = 1, wrofs = 0;
+	uint8_t port_type = 0;
+
+	if (!i2ctable)
+		return -EINVAL;
+
+	if (dcb_version >= 0x30) {
+		if (i2ctable[0] != dcb_version) /* necessary? */
+			NV_WARN(dev,
+				"DCB I2C table version mismatch (%02X vs %02X)\n",
+				i2ctable[0], dcb_version);
+		dcb_i2c_ver = i2ctable[0];
+		headerlen = i2ctable[1];
+		if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
+			i2c_entries = i2ctable[2];
+		else
+			NV_WARN(dev,
+				"DCB I2C table has more entries than indexable "
+				"(%d entries, max index 15)\n", i2ctable[2]);
+		entry_len = i2ctable[3];
+		/* [4] is i2c_default_indices, read in parse_dcb_table() */
+	}
+	/*
+	 * It's your own fault if you call this function on a DCB 1.1 BIOS --
+	 * the test below is for DCB 1.2
+	 */
+	if (dcb_version < 0x14) {
+		recordoffset = 2;
+		rdofs = 0;
+		wrofs = 1;
+	}
+
+	if (index == 0xf)
+		return 0;
+	if (index > i2c_entries) {
+		NV_ERROR(dev, "DCB I2C index too big (%d > %d)\n",
+			 index, i2ctable[2]);
+		return -ENOENT;
+	}
+	if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
+		NV_ERROR(dev, "DCB I2C entry invalid\n");
+		return -EINVAL;
+	}
+
+	if (dcb_i2c_ver >= 0x30) {
+		port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];
+
+		/*
+		 * Fixup for chips using same address offset for read and
+		 * write.
+		 */
+		if (port_type == 4)	/* seen on C51 */
+			rdofs = wrofs = 1;
+		if (port_type >= 5)	/* G80+ */
+			rdofs = wrofs = 0;
+	}
+
+	if (dcb_i2c_ver >= 0x40 && port_type != 5 && port_type != 6)
+		NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);
+
+	i2c->port_type = port_type;
+	i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
+	i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];
+
+	return 0;
+}
+
+static struct dcb_gpio_entry *
+new_gpio_entry(struct nvbios *bios)
+{
+	struct parsed_dcb_gpio *gpio = &bios->bdcb.gpio;
+
+	return &gpio->entry[gpio->entries++];
+}
+
+struct dcb_gpio_entry *
+nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	int i;
+
+	for (i = 0; i < bios->bdcb.gpio.entries; i++) {
+		if (bios->bdcb.gpio.entry[i].tag != tag)
+			continue;
+
+		return &bios->bdcb.gpio.entry[i];
+	}
+
+	return NULL;
+}
+
+static void
+parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
+{
+	struct dcb_gpio_entry *gpio;
+	uint16_t ent = ROM16(bios->data[offset]);
+	uint8_t line = ent & 0x1f,
+		tag = ent >> 5 & 0x3f,
+		flags = ent >> 11 & 0x1f;
+
+	if (tag == 0x3f)
+		return;
+
+	gpio = new_gpio_entry(bios);
+
+	gpio->tag = tag;
+	gpio->line = line;
+	gpio->invert = flags != 4;
+}
+
+static void
+parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset)
+{
+	struct dcb_gpio_entry *gpio;
+	uint32_t ent = ROM32(bios->data[offset]);
+	uint8_t line = ent & 0x1f,
+		tag = ent >> 8 & 0xff;
+
+	if (tag == 0xff)
+		return;
+
+	gpio = new_gpio_entry(bios);
+
+	/* Currently unused, we may need more fields parsed at some
+	 * point. */
+	gpio->tag = tag;
+	gpio->line = line;
+}
+
+static void
+parse_dcb_gpio_table(struct nvbios *bios)
+{
+	struct drm_device *dev = bios->dev;
+	uint16_t gpio_table_ptr = bios->bdcb.gpio_table_ptr;
+	uint8_t *gpio_table = &bios->data[gpio_table_ptr];
+	int header_len = gpio_table[1],
+	    entries = gpio_table[2],
+	    entry_len = gpio_table[3];
+	void (*parse_entry)(struct nvbios *, uint16_t) = NULL;
+	int i;
+
+	if (bios->bdcb.version >= 0x40) {
+		if (gpio_table_ptr && entry_len != 4) {
+			NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
+			return;
+		}
+
+		parse_entry = parse_dcb40_gpio_entry;
+
+	} else if (bios->bdcb.version >= 0x30) {
+		if (gpio_table_ptr && entry_len != 2) {
+			NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
+			return;
+		}
+
+		parse_entry = parse_dcb30_gpio_entry;
+
+	} else if (bios->bdcb.version >= 0x22) {
+		/*
+		 * DCBs older than v3.0 don't really have a GPIO
+		 * table, instead they keep some GPIO info at fixed
+		 * locations.
+		 */
+		uint16_t dcbptr = ROM16(bios->data[0x36]);
+		uint8_t *tvdac_gpio = &bios->data[dcbptr - 5];
+
+		if (tvdac_gpio[0] & 1) {
+			struct dcb_gpio_entry *gpio = new_gpio_entry(bios);
+
+			gpio->tag = DCB_GPIO_TVDAC0;
+			gpio->line = tvdac_gpio[1] >> 4;
+			gpio->invert = tvdac_gpio[0] & 2;
+		}
+	}
+
+	if (!gpio_table_ptr)
+		return;
+
+	if (entries > DCB_MAX_NUM_GPIO_ENTRIES) {
+		NV_WARN(dev, "Too many entries in the DCB GPIO table.\n");
+		entries = DCB_MAX_NUM_GPIO_ENTRIES;
+	}
+
+	for (i = 0; i < entries; i++)
+		parse_entry(bios, gpio_table_ptr + header_len + entry_len * i);
+}
+
+struct dcb_connector_table_entry *
+nouveau_bios_connector_entry(struct drm_device *dev, int index)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	struct dcb_connector_table_entry *cte;
+
+	if (index >= bios->bdcb.connector.entries)
+		return NULL;
+
+	cte = &bios->bdcb.connector.entry[index];
+	if (cte->type == 0xff)
+		return NULL;
+
+	return cte;
+}
+
+static void
+parse_dcb_connector_table(struct nvbios *bios)
+{
+	struct drm_device *dev = bios->dev;
+	struct dcb_connector_table *ct = &bios->bdcb.connector;
+	struct dcb_connector_table_entry *cte;
+	uint8_t *conntab = &bios->data[bios->bdcb.connector_table_ptr];
+	uint8_t *entry;
+	int i;
+
+	if (!bios->bdcb.connector_table_ptr) {
+		NV_DEBUG_KMS(dev, "No DCB connector table present\n");
+		return;
+	}
+
+	NV_INFO(dev, "DCB connector table: VHER 0x%02x %d %d %d\n",
+		conntab[0], conntab[1], conntab[2], conntab[3]);
+	if ((conntab[0] != 0x30 && conntab[0] != 0x40) ||
+	    (conntab[3] != 2 && conntab[3] != 4)) {
+		NV_ERROR(dev, "  Unknown!  Please report.\n");
+		return;
+	}
+
+	ct->entries = conntab[2];
+
+	entry = conntab + conntab[1];
+	cte = &ct->entry[0];
+	for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) {
+		if (conntab[3] == 2)
+			cte->entry = ROM16(entry[0]);
+		else
+			cte->entry = ROM32(entry[0]);
+		cte->type  = (cte->entry & 0x000000ff) >> 0;
+		cte->index = (cte->entry & 0x00000f00) >> 8;
+		switch (cte->entry & 0x00033000) {
+		case 0x00001000:
+			cte->gpio_tag = 0x07;
+			break;
+		case 0x00002000:
+			cte->gpio_tag = 0x08;
+			break;
+		case 0x00010000:
+			cte->gpio_tag = 0x51;
+			break;
+		case 0x00020000:
+			cte->gpio_tag = 0x52;
+			break;
+		default:
+			cte->gpio_tag = 0xff;
+			break;
+		}
+
+		if (cte->type == 0xff)
+			continue;
+
+		NV_INFO(dev, "  %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n",
+			i, cte->entry, cte->type, cte->index, cte->gpio_tag);
+	}
+}
+
+static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
+{
+	struct dcb_entry *entry = &dcb->entry[dcb->entries];
+
+	memset(entry, 0, sizeof(struct dcb_entry));
+	entry->index = dcb->entries++;
+
+	return entry;
+}
+
+static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
+{
+	struct dcb_entry *entry = new_dcb_entry(dcb);
+
+	entry->type = 0;
+	entry->i2c_index = i2c;
+	entry->heads = heads;
+	entry->location = DCB_LOC_ON_CHIP;
+	/* "or" mostly unused in early gen crt modesetting, 0 is fine */
+}
+
+static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
+{
+	struct dcb_entry *entry = new_dcb_entry(dcb);
+
+	entry->type = 2;
+	entry->i2c_index = LEGACY_I2C_PANEL;
+	entry->heads = twoHeads ? 3 : 1;
+	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
+	entry->or = 1;	/* means |0x10 gets set on CRE_LCD__INDEX */
+	entry->duallink_possible = false; /* SiI164 and co. are single link */
+
+#if 0
+	/*
+	 * For dvi-a either crtc probably works, but my card appears to only
+	 * support dvi-d.  "nvidia" still attempts to program it for dvi-a,
+	 * doing the full fp output setup (program 0x6808.. fp dimension regs,
+	 * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
+	 * the monitor picks up the mode res ok and lights up, but no pixel
+	 * data appears, so the board manufacturer probably connected up the
+	 * sync lines, but missed the video traces / components
+	 *
+	 * with this introduction, dvi-a left as an exercise for the reader.
+	 */
+	fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads);
+#endif
+}
+
+static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
+{
+	struct dcb_entry *entry = new_dcb_entry(dcb);
+
+	entry->type = 1;
+	entry->i2c_index = LEGACY_I2C_TV;
+	entry->heads = twoHeads ? 3 : 1;
+	entry->location = !DCB_LOC_ON_CHIP;	/* ie OFF CHIP */
+}
+
+static bool
+parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
+{
+	entry->type = conn & 0xf;
+	entry->i2c_index = (conn >> 4) & 0xf;
+	entry->heads = (conn >> 8) & 0xf;
+	if (bdcb->version >= 0x40)
+		entry->connector = (conn >> 12) & 0xf;
+	entry->bus = (conn >> 16) & 0xf;
+	entry->location = (conn >> 20) & 0x3;
+	entry->or = (conn >> 24) & 0xf;
+	/*
+	 * Normal entries consist of a single bit, but dual link has the
+	 * next most significant bit set too
+	 */
+	entry->duallink_possible =
+			((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
+
+	switch (entry->type) {
+	case OUTPUT_ANALOG:
+		/*
+		 * Although the rest of a CRT conf dword is usually
+		 * zeros, mac biosen have stuff there so we must mask
+		 */
+		entry->crtconf.maxfreq = (bdcb->version < 0x30) ?
+					 (conf & 0xffff) * 10 :
+					 (conf & 0xff) * 10000;
+		break;
+	case OUTPUT_LVDS:
+		{
+		uint32_t mask;
+		if (conf & 0x1)
+			entry->lvdsconf.use_straps_for_mode = true;
+		if (bdcb->version < 0x22) {
+			mask = ~0xd;
+			/*
+			 * The laptop in bug 14567 lies and claims to not use
+			 * straps when it does, so assume all DCB 2.0 laptops
+			 * use straps, until a broken EDID using one is produced
+			 */
+			entry->lvdsconf.use_straps_for_mode = true;
+			/*
+			 * Both 0x4 and 0x8 show up in v2.0 tables; assume they
+			 * mean the same thing (probably wrong, but might work)
+			 */
+			if (conf & 0x4 || conf & 0x8)
+				entry->lvdsconf.use_power_scripts = true;
+		} else {
+			mask = ~0x5;
+			if (conf & 0x4)
+				entry->lvdsconf.use_power_scripts = true;
+		}
+		if (conf & mask) {
+			/*
+			 * Until we even try to use these on G8x, it's
+			 * useless reporting unknown bits.  They all are.
+			 */
+			if (bdcb->version >= 0x40)
+				break;
+
+			NV_ERROR(dev, "Unknown LVDS configuration bits, "
+				      "please report\n");
+		}
+		break;
+		}
+	case OUTPUT_TV:
+	{
+		if (bdcb->version >= 0x30)
+			entry->tvconf.has_component_output = conf & (0x8 << 4);
+		else
+			entry->tvconf.has_component_output = false;
+
+		break;
+	}
+	case OUTPUT_DP:
+		entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
+		entry->dpconf.link_bw = (conf & 0x00e00000) >> 21;
+		switch ((conf & 0x0f000000) >> 24) {
+		case 0xf:
+			entry->dpconf.link_nr = 4;
+			break;
+		case 0x3:
+			entry->dpconf.link_nr = 2;
+			break;
+		default:
+			entry->dpconf.link_nr = 1;
+			break;
+		}
+		break;
+	case OUTPUT_TMDS:
+		entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
+		break;
+	case 0xe:
+		/* weird g80 mobile type that "nv" treats as a terminator */
+		bdcb->dcb.entries--;
+		return false;
+	}
+
+	/* unsure what DCB version introduces this, 3.0? */
+	if (conf & 0x100000)
+		entry->i2c_upper_default = true;
+
+	return true;
+}
+
+static bool
+parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
+		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
+{
+	switch (conn & 0x0000000f) {
+	case 0:
+		entry->type = OUTPUT_ANALOG;
+		break;
+	case 1:
+		entry->type = OUTPUT_TV;
+		break;
+	case 2:
+	case 3:
+		entry->type = OUTPUT_LVDS;
+		break;
+	case 4:
+		switch ((conn & 0x000000f0) >> 4) {
+		case 0:
+			entry->type = OUTPUT_TMDS;
+			break;
+		case 1:
+			entry->type = OUTPUT_LVDS;
+			break;
+		default:
+			NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
+				 (conn & 0x000000f0) >> 4);
+			return false;
+		}
+		break;
+	default:
+		NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
+		return false;
+	}
+
+	entry->i2c_index = (conn & 0x0003c000) >> 14;
+	entry->heads = ((conn & 0x001c0000) >> 18) + 1;
+	entry->or = entry->heads; /* same as heads, hopefully safe enough */
+	entry->location = (conn & 0x01e00000) >> 21;
+	entry->bus = (conn & 0x0e000000) >> 25;
+	entry->duallink_possible = false;
+
+	switch (entry->type) {
+	case OUTPUT_ANALOG:
+		entry->crtconf.maxfreq = (conf & 0xffff) * 10;
+		break;
+	case OUTPUT_TV:
+		entry->tvconf.has_component_output = false;
+		break;
+	case OUTPUT_TMDS:
+		/*
+		 * Invent a DVI-A output, by copying the fields of the DVI-D
+		 * output; reported to work by math_b on an NV20(!).
+		 */
+		fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
+		break;
+	case OUTPUT_LVDS:
+		if ((conn & 0x00003f00) != 0x10)
+			entry->lvdsconf.use_straps_for_mode = true;
+		entry->lvdsconf.use_power_scripts = true;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static bool parse_dcb_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+			    uint32_t conn, uint32_t conf)
+{
+	struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb);
+	bool ret;
+
+	if (bdcb->version >= 0x20)
+		ret = parse_dcb20_entry(dev, bdcb, conn, conf, entry);
+	else
+		ret = parse_dcb15_entry(dev, &bdcb->dcb, conn, conf, entry);
+	if (!ret)
+		return ret;
+
+	read_dcb_i2c_entry(dev, bdcb->version, bdcb->i2c_table,
+			   entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]);
+
+	return true;
+}
+
+static
+void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
+{
+	/*
+	 * DCB v2.0 lists each output combination separately.
+	 * Here we merge compatible entries to have fewer outputs, with
+	 * more options
+	 */
+
+	int i, newentries = 0;
+
+	for (i = 0; i < dcb->entries; i++) {
+		struct dcb_entry *ient = &dcb->entry[i];
+		int j;
+
+		for (j = i + 1; j < dcb->entries; j++) {
+			struct dcb_entry *jent = &dcb->entry[j];
+
+			if (jent->type == 100) /* already merged entry */
+				continue;
+
+			/* merge heads field when all other fields the same */
+			if (jent->i2c_index == ient->i2c_index &&
+			    jent->type == ient->type &&
+			    jent->location == ient->location &&
+			    jent->or == ient->or) {
+				NV_TRACE(dev, "Merging DCB entries %d and %d\n",
+					 i, j);
+				ient->heads |= jent->heads;
+				jent->type = 100; /* dummy value */
+			}
+		}
+	}
+
+	/* Compact entries merged into others out of dcb */
+	for (i = 0; i < dcb->entries; i++) {
+		if (dcb->entry[i].type == 100)
+			continue;
+
+		if (newentries != i) {
+			dcb->entry[newentries] = dcb->entry[i];
+			dcb->entry[newentries].index = newentries;
+		}
+		newentries++;
+	}
+
+	dcb->entries = newentries;
+}
+
+static int
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct bios_parsed_dcb *bdcb = &bios->bdcb;
+	struct parsed_dcb *dcb;
+	uint16_t dcbptr = 0, i2ctabptr = 0;
+	uint8_t *dcbtable;
+	uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
+	bool configblock = true;
+	int recordlength = 8, confofs = 4;
+	int i;
+
+	dcb = bios->pub.dcb = &bdcb->dcb;
+	dcb->entries = 0;
+
+	/* get the offset from 0x36 */
+	if (dev_priv->card_type > NV_04) {
+		dcbptr = ROM16(bios->data[0x36]);
+		if (dcbptr == 0x0000)
+			NV_WARN(dev, "No output data (DCB) found in BIOS\n");
+	}
+
+	/* this situation likely means a really old card, pre DCB */
+	if (dcbptr == 0x0) {
+		NV_INFO(dev, "Assuming a CRT output exists\n");
+		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
+
+		if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
+			fabricate_tv_output(dcb, twoHeads);
+
+		return 0;
+	}
+
+	dcbtable = &bios->data[dcbptr];
+
+	/* get DCB version */
+	bdcb->version = dcbtable[0];
+	NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n",
+		 bdcb->version >> 4, bdcb->version & 0xf);
+
+	if (bdcb->version >= 0x20) { /* NV17+ */
+		uint32_t sig;
+
+		if (bdcb->version >= 0x30) { /* NV40+ */
+			headerlen = dcbtable[1];
+			entries = dcbtable[2];
+			recordlength = dcbtable[3];
+			i2ctabptr = ROM16(dcbtable[4]);
+			sig = ROM32(dcbtable[6]);
+			bdcb->gpio_table_ptr = ROM16(dcbtable[10]);
+			bdcb->connector_table_ptr = ROM16(dcbtable[20]);
+		} else {
+			i2ctabptr = ROM16(dcbtable[2]);
+			sig = ROM32(dcbtable[4]);
+			headerlen = 8;
+		}
+
+		if (sig != 0x4edcbdcb) {
+			NV_ERROR(dev, "Bad Display Configuration Block "
+					"signature (%08X)\n", sig);
+			return -EINVAL;
+		}
+	} else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */
+		char sig[8] = { 0 };
+
+		strncpy(sig, (char *)&dcbtable[-7], 7);
+		i2ctabptr = ROM16(dcbtable[2]);
+		recordlength = 10;
+		confofs = 6;
+
+		if (strcmp(sig, "DEV_REC")) {
+			NV_ERROR(dev, "Bad Display Configuration Block "
+					"signature (%s)\n", sig);
+			return -EINVAL;
+		}
+	} else {
+		/*
+		 * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always
+		 * has the same single (crt) entry, even when tv-out present, so
+		 * the conclusion is this version cannot really be used.
+		 * v1.2 tables (some NV6/10, and NV15+) normally have the same
+		 * 5 entries, which are not specific to the card and so no use.
+		 * v1.2 does have an I2C table that read_dcb_i2c_table can
+		 * handle, but cards exist (nv11 in #14821) with a bad i2c table
+		 * pointer, so use the indices parsed in parse_bmp_structure.
+		 * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
+		 */
+		NV_TRACEWARN(dev, "No useful information in BIOS output table; "
+				  "adding all possible outputs\n");
+		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
+
+		/*
+		 * Attempt to detect TV before DVI because the test
+		 * for the former is more accurate and it rules the
+		 * latter out.
+		 */
+		if (nv04_tv_identify(dev,
+				     bios->legacy.i2c_indices.tv) >= 0)
+			fabricate_tv_output(dcb, twoHeads);
+
+		else if (bios->tmds.output0_script_ptr ||
+			 bios->tmds.output1_script_ptr)
+			fabricate_dvi_i_output(dcb, twoHeads);
+
+		return 0;
+	}
+
+	if (!i2ctabptr)
+		NV_WARN(dev, "No pointer to DCB I2C port table\n");
+	else {
+		bdcb->i2c_table = &bios->data[i2ctabptr];
+		if (bdcb->version >= 0x30)
+			bdcb->i2c_default_indices = bdcb->i2c_table[4];
+	}
+
+	parse_dcb_gpio_table(bios);
+	parse_dcb_connector_table(bios);
+
+	if (entries > DCB_MAX_NUM_ENTRIES)
+		entries = DCB_MAX_NUM_ENTRIES;
+
+	for (i = 0; i < entries; i++) {
+		uint32_t connection, config = 0;
+
+		connection = ROM32(dcbtable[headerlen + recordlength * i]);
+		if (configblock)
+			config = ROM32(dcbtable[headerlen + confofs + recordlength * i]);
+
+		/* seen on an NV11 with DCB v1.5 */
+		if (connection == 0x00000000)
+			break;
+
+		/* seen on an NV17 with DCB v2.0 */
+		if (connection == 0xffffffff)
+			break;
+
+		if ((connection & 0x0000000f) == 0x0000000f)
+			continue;
+
+		NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n",
+			     dcb->entries, connection, config);
+
+		if (!parse_dcb_entry(dev, bdcb, connection, config))
+			break;
+	}
+
+	/*
+	 * apart for v2.1+ not being known for requiring merging, this
+	 * guarantees dcbent->index is the index of the entry in the rom image
+	 */
+	if (bdcb->version < 0x21)
+		merge_like_dcb_entries(dev, dcb);
+
+	return dcb->entries ? 0 : -ENXIO;
+}
+
+static void
+fixup_legacy_connector(struct nvbios *bios)
+{
+	struct bios_parsed_dcb *bdcb = &bios->bdcb;
+	struct parsed_dcb *dcb = &bdcb->dcb;
+	int high = 0, i;
+
+	/*
+	 * DCB 3.0 also has the table in most cases, but there are some cards
+	 * where the table is filled with stub entries, and the DCB entriy
+	 * indices are all 0.  We don't need the connector indices on pre-G80
+	 * chips (yet?) so limit the use to DCB 4.0 and above.
+	 */
+	if (bdcb->version >= 0x40)
+		return;
+
+	/*
+	 * No known connector info before v3.0, so make it up.  the rule here
+	 * is: anything on the same i2c bus is considered to be on the same
+	 * connector.  any output without an associated i2c bus is assigned
+	 * its own unique connector index.
+	 */
+	for (i = 0; i < dcb->entries; i++) {
+		if (dcb->entry[i].i2c_index == 0xf)
+			continue;
+
+		/*
+		 * Ignore the I2C index for on-chip TV-out, as there
+		 * are cards with bogus values (nv31m in bug 23212),
+		 * and it's otherwise useless.
+		 */
+		if (dcb->entry[i].type == OUTPUT_TV &&
+		    dcb->entry[i].location == DCB_LOC_ON_CHIP) {
+			dcb->entry[i].i2c_index = 0xf;
+			continue;
+		}
+
+		dcb->entry[i].connector = dcb->entry[i].i2c_index;
+		if (dcb->entry[i].connector > high)
+			high = dcb->entry[i].connector;
+	}
+
+	for (i = 0; i < dcb->entries; i++) {
+		if (dcb->entry[i].i2c_index != 0xf)
+			continue;
+
+		dcb->entry[i].connector = ++high;
+	}
+}
+
+static void
+fixup_legacy_i2c(struct nvbios *bios)
+{
+	struct parsed_dcb *dcb = &bios->bdcb.dcb;
+	int i;
+
+	for (i = 0; i < dcb->entries; i++) {
+		if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT)
+			dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt;
+		if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL)
+			dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel;
+		if (dcb->entry[i].i2c_index == LEGACY_I2C_TV)
+			dcb->entry[i].i2c_index = bios->legacy.i2c_indices.tv;
+	}
+}
+
+static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry)
+{
+	/*
+	 * The header following the "HWSQ" signature has the number of entries,
+	 * and the entry size
+	 *
+	 * An entry consists of a dword to write to the sequencer control reg
+	 * (0x00001304), followed by the ucode bytes, written sequentially,
+	 * starting at reg 0x00001400
+	 */
+
+	uint8_t bytes_to_write;
+	uint16_t hwsq_entry_offset;
+	int i;
+
+	if (bios->data[hwsq_offset] <= entry) {
+		NV_ERROR(dev, "Too few entries in HW sequencer table for "
+				"requested entry\n");
+		return -ENOENT;
+	}
+
+	bytes_to_write = bios->data[hwsq_offset + 1];
+
+	if (bytes_to_write != 36) {
+		NV_ERROR(dev, "Unknown HW sequencer entry size\n");
+		return -EINVAL;
+	}
+
+	NV_TRACE(dev, "Loading NV17 power sequencing microcode\n");
+
+	hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
+
+	/* set sequencer control */
+	bios_wr32(bios, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
+	bytes_to_write -= 4;
+
+	/* write ucode */
+	for (i = 0; i < bytes_to_write; i += 4)
+		bios_wr32(bios, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
+
+	/* twiddle NV_PBUS_DEBUG_4 */
+	bios_wr32(bios, NV_PBUS_DEBUG_4, bios_rd32(bios, NV_PBUS_DEBUG_4) | 0x18);
+
+	return 0;
+}
+
+static int load_nv17_hw_sequencer_ucode(struct drm_device *dev,
+					struct nvbios *bios)
+{
+	/*
+	 * BMP based cards, from NV17, need a microcode loading to correctly
+	 * control the GPIO etc for LVDS panels
+	 *
+	 * BIT based cards seem to do this directly in the init scripts
+	 *
+	 * The microcode entries are found by the "HWSQ" signature.
+	 */
+
+	const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' };
+	const int sz = sizeof(hwsq_signature);
+	int hwsq_offset;
+
+	hwsq_offset = findstr(bios->data, bios->length, hwsq_signature, sz);
+	if (!hwsq_offset)
+		return 0;
+
+	/* always use entry 0? */
+	return load_nv17_hwsq_ucode_entry(dev, bios, hwsq_offset + sz, 0);
+}
+
+uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	const uint8_t edid_sig[] = {
+			0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
+	uint16_t offset = 0;
+	uint16_t newoffset;
+	int searchlen = NV_PROM_SIZE;
+
+	if (bios->fp.edid)
+		return bios->fp.edid;
+
+	while (searchlen) {
+		newoffset = findstr(&bios->data[offset], searchlen,
+								edid_sig, 8);
+		if (!newoffset)
+			return NULL;
+		offset += newoffset;
+		if (!nv_cksum(&bios->data[offset], EDID1_LEN))
+			break;
+
+		searchlen -= offset;
+		offset++;
+	}
+
+	NV_TRACE(dev, "Found EDID in BIOS\n");
+
+	return bios->fp.edid = &bios->data[offset];
+}
+
+void
+nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
+			    struct dcb_entry *dcbent)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	struct init_exec iexec = { true, false };
+
+	mutex_lock(&bios->lock);
+	bios->display.output = dcbent;
+	parse_init_table(bios, table, &iexec);
+	bios->display.output = NULL;
+	mutex_unlock(&bios->lock);
+}
+
+static bool NVInitVBIOS(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+
+	memset(bios, 0, sizeof(struct nvbios));
+	mutex_init(&bios->lock);
+	bios->dev = dev;
+
+	if (!NVShadowVBIOS(dev, bios->data))
+		return false;
+
+	bios->length = NV_PROM_SIZE;
+	return true;
+}
+
+static int nouveau_parse_vbios_struct(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
+	const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
+	int offset;
+
+	offset = findstr(bios->data, bios->length,
+					bit_signature, sizeof(bit_signature));
+	if (offset) {
+		NV_TRACE(dev, "BIT BIOS found\n");
+		return parse_bit_structure(bios, offset + 6);
+	}
+
+	offset = findstr(bios->data, bios->length,
+					bmp_signature, sizeof(bmp_signature));
+	if (offset) {
+		NV_TRACE(dev, "BMP BIOS found\n");
+		return parse_bmp_structure(dev, bios, offset);
+	}
+
+	NV_ERROR(dev, "No known BIOS signature found\n");
+	return -ENODEV;
+}
+
+int
+nouveau_run_vbios_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	int i, ret = 0;
+
+	NVLockVgaCrtcs(dev, false);
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, bios->state.crtchead);
+
+	if (bios->major_version < 5)	/* BMP only */
+		load_nv17_hw_sequencer_ucode(dev, bios);
+
+	if (bios->execute) {
+		bios->fp.last_script_invoc = 0;
+		bios->fp.lvds_init_run = false;
+	}
+
+	parse_init_tables(bios);
+
+	/*
+	 * Runs some additional script seen on G8x VBIOSen.  The VBIOS'
+	 * parser will run this right after the init tables, the binary
+	 * driver appears to run it at some point later.
+	 */
+	if (bios->some_script_ptr) {
+		struct init_exec iexec = {true, false};
+
+		NV_INFO(dev, "Parsing VBIOS init table at offset 0x%04X\n",
+			bios->some_script_ptr);
+		parse_init_table(bios, bios->some_script_ptr, &iexec);
+	}
+
+	if (dev_priv->card_type >= NV_50) {
+		for (i = 0; i < bios->bdcb.dcb.entries; i++) {
+			nouveau_bios_run_display_table(dev,
+						       &bios->bdcb.dcb.entry[i],
+						       0, 0);
+		}
+	}
+
+	NVLockVgaCrtcs(dev, true);
+
+	return ret;
+}
+
+static void
+nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	struct dcb_i2c_entry *entry;
+	int i;
+
+	entry = &bios->bdcb.dcb.i2c[0];
+	for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
+		nouveau_i2c_fini(dev, entry);
+}
+
+int
+nouveau_bios_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint32_t saved_nv_pextdev_boot_0;
+	bool was_locked;
+	int ret;
+
+	dev_priv->vbios = &bios->pub;
+
+	if (!NVInitVBIOS(dev))
+		return -ENODEV;
+
+	ret = nouveau_parse_vbios_struct(dev);
+	if (ret)
+		return ret;
+
+	ret = parse_dcb_table(dev, bios, nv_two_heads(dev));
+	if (ret)
+		return ret;
+
+	fixup_legacy_i2c(bios);
+	fixup_legacy_connector(bios);
+
+	if (!bios->major_version)	/* we don't run version 0 bios */
+		return 0;
+
+	/* these will need remembering across a suspend */
+	saved_nv_pextdev_boot_0 = bios_rd32(bios, NV_PEXTDEV_BOOT_0);
+	bios->state.saved_nv_pfb_cfg0 = bios_rd32(bios, NV_PFB_CFG0);
+
+	/* init script execution disabled */
+	bios->execute = false;
+
+	/* ... unless card isn't POSTed already */
+	if (dev_priv->card_type >= NV_10 &&
+	    NVReadVgaCrtc(dev, 0, 0x00) == 0 &&
+	    NVReadVgaCrtc(dev, 0, 0x1a) == 0) {
+		NV_INFO(dev, "Adaptor not initialised\n");
+		if (dev_priv->card_type < NV_50) {
+			NV_ERROR(dev, "Unable to POST this chipset\n");
+			return -ENODEV;
+		}
+
+		NV_INFO(dev, "Running VBIOS init tables\n");
+		bios->execute = true;
+	}
+
+	bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
+
+	ret = nouveau_run_vbios_init(dev);
+	if (ret) {
+		dev_priv->vbios = NULL;
+		return ret;
+	}
+
+	/* feature_byte on BMP is poor, but init always sets CR4B */
+	was_locked = NVLockVgaCrtcs(dev, false);
+	if (bios->major_version < 5)
+		bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40;
+
+	/* all BIT systems need p_f_m_t for digital_min_front_porch */
+	if (bios->is_mobile || bios->major_version >= 5)
+		ret = parse_fp_mode_table(dev, bios);
+	NVLockVgaCrtcs(dev, was_locked);
+
+	/* allow subsequent scripts to execute */
+	bios->execute = true;
+
+	return 0;
+}
+
+void
+nouveau_bios_takedown(struct drm_device *dev)
+{
+	nouveau_bios_i2c_devices_takedown(dev);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2009 Ben Skeggs
+ * Copyright 2008 Stuart Bennett
+ *
+ * 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 (including the next
+ * paragraph) 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include "nouveau_fbcon.h"
+
+void
+nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3);
+	OUT_RING(chan, (region->sy << 16) | region->sx);
+	OUT_RING(chan, (region->dy << 16) | region->dx);
+	OUT_RING(chan, (region->height << 16) | region->width);
+	FIRE_RING(chan);
+}
+
+void
+nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
+	OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3);
+	BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1);
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
+	else
+		OUT_RING(chan, rect->color);
+	BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2);
+	OUT_RING(chan, (rect->dx << 16) | rect->dy);
+	OUT_RING(chan, (rect->width << 16) | rect->height);
+	FIRE_RING(chan);
+}
+
+void
+nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	uint32_t fg;
+	uint32_t bg;
+	uint32_t dsize;
+	uint32_t width;
+	uint32_t *data = (uint32_t *)image->data;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	width = ALIGN(image->width, 8);
+	dsize = ALIGN(width * image->height, 32) >> 5;
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
+		bg = ((uint32_t *) info->pseudo_palette)[image->bg_color];
+	} else {
+		fg = image->fg_color;
+		bg = image->bg_color;
+	}
+
+	BEGIN_RING(chan, NvSubGdiRect, 0x0be4, 7);
+	OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
+	OUT_RING(chan, ((image->dy + image->height) << 16) |
+			 ((image->dx + image->width) & 0xffff));
+	OUT_RING(chan, bg);
+	OUT_RING(chan, fg);
+	OUT_RING(chan, (image->height << 16) | width);
+	OUT_RING(chan, (image->height << 16) | image->width);
+	OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
+
+	while (dsize) {
+		int iter_len = dsize > 128 ? 128 : dsize;
+
+		if (RING_SPACE(chan, iter_len + 1)) {
+			nouveau_fbcon_gpu_lockup(info);
+			cfb_imageblit(info, image);
+			return;
+		}
+
+		BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len);
+		OUT_RINGp(chan, data, iter_len);
+		data += iter_len;
+		dsize -= iter_len;
+	}
+
+	FIRE_RING(chan);
+}
+
+static int
+nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *obj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, handle, obj, NULL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int
+nv04_fbcon_accel_init(struct fb_info *info)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	const int sub = NvSubCtxSurf2D;
+	int surface_fmt, pattern_fmt, rect_fmt;
+	int ret;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		surface_fmt = 1;
+		pattern_fmt = 3;
+		rect_fmt = 3;
+		break;
+	case 16:
+		surface_fmt = 4;
+		pattern_fmt = 1;
+		rect_fmt = 1;
+		break;
+	case 32:
+		switch (info->var.transp.length) {
+		case 0: /* depth 24 */
+		case 8: /* depth 32 */
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		surface_fmt = 6;
+		pattern_fmt = 3;
+		rect_fmt = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ?
+				   0x0062 : 0x0042, NvCtxSurf2D);
+	if (ret)
+		return ret;
+
+	ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect);
+	if (ret)
+		return ret;
+
+	ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop);
+	if (ret)
+		return ret;
+
+	ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt);
+	if (ret)
+		return ret;
+
+	ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect);
+	if (ret)
+		return ret;
+
+	ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ?
+				   0x009f : 0x005f, NvImageBlit);
+	if (ret)
+		return ret;
+
+	if (RING_SPACE(chan, 49)) {
+		nouveau_fbcon_gpu_lockup(info);
+		return 0;
+	}
+
+	BEGIN_RING(chan, sub, 0x0000, 1);
+	OUT_RING(chan, NvCtxSurf2D);
+	BEGIN_RING(chan, sub, 0x0184, 2);
+	OUT_RING(chan, NvDmaFB);
+	OUT_RING(chan, NvDmaFB);
+	BEGIN_RING(chan, sub, 0x0300, 4);
+	OUT_RING(chan, surface_fmt);
+	OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16));
+	OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
+	OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base);
+
+	BEGIN_RING(chan, sub, 0x0000, 1);
+	OUT_RING(chan, NvRop);
+	BEGIN_RING(chan, sub, 0x0300, 1);
+	OUT_RING(chan, 0x55);
+
+	BEGIN_RING(chan, sub, 0x0000, 1);
+	OUT_RING(chan, NvImagePatt);
+	BEGIN_RING(chan, sub, 0x0300, 8);
+	OUT_RING(chan, pattern_fmt);
+#ifdef __BIG_ENDIAN
+	OUT_RING(chan, 2);
+#else
+	OUT_RING(chan, 1);
+#endif
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	OUT_RING(chan, ~0);
+	OUT_RING(chan, ~0);
+	OUT_RING(chan, ~0);
+	OUT_RING(chan, ~0);
+
+	BEGIN_RING(chan, sub, 0x0000, 1);
+	OUT_RING(chan, NvClipRect);
+	BEGIN_RING(chan, sub, 0x0300, 2);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual);
+
+	BEGIN_RING(chan, NvSubImageBlit, 0x0000, 1);
+	OUT_RING(chan, NvImageBlit);
+	BEGIN_RING(chan, NvSubImageBlit, 0x019c, 1);
+	OUT_RING(chan, NvCtxSurf2D);
+	BEGIN_RING(chan, NvSubImageBlit, 0x02fc, 1);
+	OUT_RING(chan, 3);
+
+	BEGIN_RING(chan, NvSubGdiRect, 0x0000, 1);
+	OUT_RING(chan, NvGdiRect);
+	BEGIN_RING(chan, NvSubGdiRect, 0x0198, 1);
+	OUT_RING(chan, NvCtxSurf2D);
+	BEGIN_RING(chan, NvSubGdiRect, 0x0188, 2);
+	OUT_RING(chan, NvImagePatt);
+	OUT_RING(chan, NvRop);
+	BEGIN_RING(chan, NvSubGdiRect, 0x0304, 1);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSubGdiRect, 0x0300, 1);
+	OUT_RING(chan, rect_fmt);
+	BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1);
+	OUT_RING(chan, 3);
+
+	FIRE_RING(chan);
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+struct nv50_instmem_priv {
+	uint32_t save1700[5]; /* 0x1700->0x1710 */
+
+	struct nouveau_gpuobj_ref *pramin_pt;
+	struct nouveau_gpuobj_ref *pramin_bar;
+	struct nouveau_gpuobj_ref *fb_bar;
+
+	bool last_access_wr;
+};
+
+#define NV50_INSTMEM_PAGE_SHIFT 12
+#define NV50_INSTMEM_PAGE_SIZE  (1 << NV50_INSTMEM_PAGE_SHIFT)
+#define NV50_INSTMEM_PT_SIZE(a)	(((a) >> 12) << 3)
+
+/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN
+ */
+#define BAR0_WI32(g, o, v) do {                                   \
+	uint32_t offset;                                          \
+	if ((g)->im_backing) {                                    \
+		offset = (g)->im_backing_start;                   \
+	} else {                                                  \
+		offset  = chan->ramin->gpuobj->im_backing_start;  \
+		offset += (g)->im_pramin->start;                  \
+	}                                                         \
+	offset += (o);                                            \
+	nv_wr32(dev, NV_RAMIN + (offset & 0xfffff), (v));              \
+} while (0)
+
+int
+nv50_instmem_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size;
+	struct nv50_instmem_priv *priv;
+	int ret, i;
+	uint32_t v, save_nv001700;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_priv->engine.instmem.priv = priv;
+
+	/* Save state, will restore at takedown. */
+	for (i = 0x1700; i <= 0x1710; i += 4)
+		priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i);
+
+	if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
+		dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;
+	else
+		dev_priv->vram_sys_base = 0;
+
+	/* Reserve the last MiB of VRAM, we should probably try to avoid
+	 * setting up the below tables over the top of the VBIOS image at
+	 * some point.
+	 */
+	dev_priv->ramin_rsvd_vram = 1 << 20;
+	c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram;
+	c_size   = 128 << 10;
+	c_vmpd   = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200;
+	c_ramfc  = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20;
+	c_base   = c_vmpd + 0x4000;
+	pt_size  = NV50_INSTMEM_PT_SIZE(dev_priv->ramin_size);
+
+	NV_DEBUG(dev, " Rsvd VRAM base: 0x%08x\n", c_offset);
+	NV_DEBUG(dev, "    VBIOS image: 0x%08x\n",
+				(nv_rd32(dev, 0x619f04) & ~0xff) << 8);
+	NV_DEBUG(dev, "  Aperture size: %d MiB\n", dev_priv->ramin_size >> 20);
+	NV_DEBUG(dev, "        PT size: %d KiB\n", pt_size >> 10);
+
+	/* Determine VM layout, we need to do this first to make sure
+	 * we allocate enough memory for all the page tables.
+	 */
+	dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK);
+	dev_priv->vm_gart_size = NV50_VM_BLOCK;
+
+	dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size;
+	dev_priv->vm_vram_size = nouveau_mem_fb_amount(dev);
+	if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM)
+		dev_priv->vm_vram_size = NV50_VM_MAX_VRAM;
+	dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK);
+	dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK;
+
+	dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size;
+
+	NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n",
+		 dev_priv->vm_gart_base,
+		 dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1);
+	NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n",
+		 dev_priv->vm_vram_base,
+		 dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1);
+
+	c_size += dev_priv->vm_vram_pt_nr * (NV50_VM_BLOCK / 65536 * 8);
+
+	/* Map BAR0 PRAMIN aperture over the memory we want to use */
+	save_nv001700 = nv_rd32(dev, NV50_PUNK_BAR0_PRAMIN);
+	nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16));
+
+	/* Create a fake channel, and use it as our "dummy" channels 0/127.
+	 * The main reason for creating a channel is so we can use the gpuobj
+	 * code.  However, it's probably worth noting that NVIDIA also setup
+	 * their channels 0/127 with the same values they configure here.
+	 * So, there may be some other reason for doing this.
+	 *
+	 * Have to create the entire channel manually, as the real channel
+	 * creation code assumes we have PRAMIN access, and we don't until
+	 * we're done here.
+	 */
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	chan->id = 0;
+	chan->dev = dev;
+	chan->file_priv = (struct drm_file *)-2;
+	dev_priv->fifos[0] = dev_priv->fifos[127] = chan;
+
+	/* Channel's PRAMIN object + heap */
+	ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0,
+							NULL, &chan->ramin);
+	if (ret)
+		return ret;
+
+	if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base))
+		return -ENOMEM;
+
+	/* RAMFC + zero channel's PRAMIN up to start of VM pagedir */
+	ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc,
+						0x4000, 0, NULL, &chan->ramfc);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < c_vmpd; i += 4)
+		BAR0_WI32(chan->ramin->gpuobj, i, 0);
+
+	/* VM page directory */
+	ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd,
+					   0x4000, 0, &chan->vm_pd, NULL);
+	if (ret)
+		return ret;
+	for (i = 0; i < 0x4000; i += 8) {
+		BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000);
+		BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000);
+	}
+
+	/* PRAMIN page table, cheat and map into VM at 0x0000000000.
+	 * We map the entire fake channel into the start of the PRAMIN BAR
+	 */
+	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000,
+				     0, &priv->pramin_pt);
+	if (ret)
+		return ret;
+
+	v = c_offset | 1;
+	if (dev_priv->vram_sys_base) {
+		v += dev_priv->vram_sys_base;
+		v |= 0x30;
+	}
+
+	i = 0;
+	while (v < dev_priv->vram_sys_base + c_offset + c_size) {
+		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v);
+		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000);
+		v += 0x1000;
+		i += 8;
+	}
+
+	while (i < pt_size) {
+		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000000);
+		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000);
+		i += 8;
+	}
+
+	BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63);
+	BAR0_WI32(chan->vm_pd, 0x04, 0x00000000);
+
+	/* VRAM page table(s), mapped into VM at +1GiB  */
+	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
+		ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0,
+					     NV50_VM_BLOCK/65536*8, 0, 0,
+					     &chan->vm_vram_pt[i]);
+		if (ret) {
+			NV_ERROR(dev, "Error creating VRAM page tables: %d\n",
+									ret);
+			dev_priv->vm_vram_pt_nr = i;
+			return ret;
+		}
+		dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]->gpuobj;
+
+		for (v = 0; v < dev_priv->vm_vram_pt[i]->im_pramin->size;
+								v += 4)
+			BAR0_WI32(dev_priv->vm_vram_pt[i], v, 0);
+
+		BAR0_WI32(chan->vm_pd, 0x10 + (i*8),
+			  chan->vm_vram_pt[i]->instance | 0x61);
+		BAR0_WI32(chan->vm_pd, 0x14 + (i*8), 0);
+	}
+
+	/* DMA object for PRAMIN BAR */
+	ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0,
+							&priv->pramin_bar);
+	if (ret)
+		return ret;
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000);
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin_size - 1);
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000);
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000);
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000);
+	BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000);
+
+	/* DMA object for FB BAR */
+	ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0,
+							&priv->fb_bar);
+	if (ret)
+		return ret;
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000);
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 +
+					      drm_get_resource_len(dev, 1) - 1);
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000);
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000);
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000);
+	BAR0_WI32(priv->fb_bar->gpuobj, 0x14, 0x00000000);
+
+	/* Poke the relevant regs, and pray it works :) */
+	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12));
+	nv_wr32(dev, NV50_PUNK_UNK1710, 0);
+	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) |
+					 NV50_PUNK_BAR_CFG_BASE_VALID);
+	nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) |
+					NV50_PUNK_BAR1_CTXDMA_VALID);
+	nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) |
+					NV50_PUNK_BAR3_CTXDMA_VALID);
+
+	for (i = 0; i < 8; i++)
+		nv_wr32(dev, 0x1900 + (i*4), 0);
+
+	/* Assume that praying isn't enough, check that we can re-read the
+	 * entire fake channel back from the PRAMIN BAR */
+	dev_priv->engine.instmem.prepare_access(dev, false);
+	for (i = 0; i < c_size; i += 4) {
+		if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) {
+			NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n",
+									i);
+			dev_priv->engine.instmem.finish_access(dev);
+			return -EINVAL;
+		}
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700);
+
+	/* Global PRAMIN heap */
+	if (nouveau_mem_init_heap(&dev_priv->ramin_heap,
+				  c_size, dev_priv->ramin_size - c_size)) {
+		dev_priv->ramin_heap = NULL;
+		NV_ERROR(dev, "Failed to init RAMIN heap\n");
+	}
+
+	/*XXX: incorrect, but needed to make hash func "work" */
+	dev_priv->ramht_offset = 0x10000;
+	dev_priv->ramht_bits   = 9;
+	dev_priv->ramht_size   = (1 << dev_priv->ramht_bits);
+	return 0;
+}
+
+void
+nv50_instmem_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+	struct nouveau_channel *chan = dev_priv->fifos[0];
+	int i;
+
+	NV_DEBUG(dev, "\n");
+
+	if (!priv)
+		return;
+
+	/* Restore state from before init */
+	for (i = 0x1700; i <= 0x1710; i += 4)
+		nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]);
+
+	nouveau_gpuobj_ref_del(dev, &priv->fb_bar);
+	nouveau_gpuobj_ref_del(dev, &priv->pramin_bar);
+	nouveau_gpuobj_ref_del(dev, &priv->pramin_pt);
+
+	/* Destroy dummy channel */
+	if (chan) {
+		for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
+			nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
+			dev_priv->vm_vram_pt[i] = NULL;
+		}
+		dev_priv->vm_vram_pt_nr = 0;
+
+		nouveau_gpuobj_del(dev, &chan->vm_pd);
+		nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+		nouveau_gpuobj_ref_del(dev, &chan->ramin);
+		nouveau_mem_takedown(&chan->ramin_heap);
+
+		dev_priv->fifos[0] = dev_priv->fifos[127] = NULL;
+		kfree(chan);
+	}
+
+	dev_priv->engine.instmem.priv = NULL;
+	kfree(priv);
+}
+
+int
+nv50_instmem_suspend(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->fifos[0];
+	struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
+	int i;
+
+	ramin->im_backing_suspend = vmalloc(ramin->im_pramin->size);
+	if (!ramin->im_backing_suspend)
+		return -ENOMEM;
+
+	for (i = 0; i < ramin->im_pramin->size; i += 4)
+		ramin->im_backing_suspend[i/4] = nv_ri32(dev, i);
+	return 0;
+}
+
+void
+nv50_instmem_resume(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+	struct nouveau_channel *chan = dev_priv->fifos[0];
+	struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
+	int i;
+
+	nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, (ramin->im_backing_start >> 16));
+	for (i = 0; i < ramin->im_pramin->size; i += 4)
+		BAR0_WI32(ramin, i, ramin->im_backing_suspend[i/4]);
+	vfree(ramin->im_backing_suspend);
+	ramin->im_backing_suspend = NULL;
+
+	/* Poke the relevant regs, and pray it works :) */
+	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12));
+	nv_wr32(dev, NV50_PUNK_UNK1710, 0);
+	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) |
+					 NV50_PUNK_BAR_CFG_BASE_VALID);
+	nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->instance >> 4) |
+					NV50_PUNK_BAR1_CTXDMA_VALID);
+	nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) |
+					NV50_PUNK_BAR3_CTXDMA_VALID);
+
+	for (i = 0; i < 8; i++)
+		nv_wr32(dev, 0x1900 + (i*4), 0);
+}
+
+int
+nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
+		      uint32_t *sz)
+{
+	int ret;
+
+	if (gpuobj->im_backing)
+		return -EINVAL;
+
+	*sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE);
+	if (*sz == 0)
+		return -EINVAL;
+
+	ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000,
+			     true, false, &gpuobj->im_backing);
+	if (ret) {
+		NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret);
+		return ret;
+	}
+
+	ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret);
+		nouveau_bo_ref(NULL, &gpuobj->im_backing);
+		return ret;
+	}
+
+	gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start;
+	gpuobj->im_backing_start <<= PAGE_SHIFT;
+
+	return 0;
+}
+
+void
+nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (gpuobj && gpuobj->im_backing) {
+		if (gpuobj->im_bound)
+			dev_priv->engine.instmem.unbind(dev, gpuobj);
+		nouveau_bo_unpin(gpuobj->im_backing);
+		nouveau_bo_ref(NULL, &gpuobj->im_backing);
+		gpuobj->im_backing = NULL;
+	}
+}
+
+int
+nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+	struct nouveau_gpuobj *pramin_pt = priv->pramin_pt->gpuobj;
+	uint32_t pte, pte_end;
+	uint64_t vram;
+
+	if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
+		return -EINVAL;
+
+	NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n",
+		 gpuobj->im_pramin->start, gpuobj->im_pramin->size);
+
+	pte     = (gpuobj->im_pramin->start >> 12) << 1;
+	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
+	vram    = gpuobj->im_backing_start;
+
+	NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n",
+		 gpuobj->im_pramin->start, pte, pte_end);
+	NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start);
+
+	vram |= 1;
+	if (dev_priv->vram_sys_base) {
+		vram += dev_priv->vram_sys_base;
+		vram |= 0x30;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	while (pte < pte_end) {
+		nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram));
+		nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram));
+		vram += NV50_INSTMEM_PAGE_SIZE;
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, 0x100c80, 0x00040001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+		return -EBUSY;
+	}
+
+	nv_wr32(dev, 0x100c80, 0x00060001);
+	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
+		return -EBUSY;
+	}
+
+	gpuobj->im_bound = 1;
+	return 0;
+}
+
+int
+nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+	uint32_t pte, pte_end;
+
+	if (gpuobj->im_bound == 0)
+		return -EINVAL;
+
+	pte     = (gpuobj->im_pramin->start >> 12) << 1;
+	pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	while (pte < pte_end) {
+		nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000);
+		nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000);
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	gpuobj->im_bound = 0;
+	return 0;
+}
+
+void
+nv50_instmem_prepare_access(struct drm_device *dev, bool write)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+
+	priv->last_access_wr = write;
+}
+
+void
+nv50_instmem_finish_access(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+
+	if (priv->last_access_wr) {
+		nv_wr32(dev, 0x070000, 0x00000001);
+		if (!nv_wait(0x070000, 0x00000001, 0x00000000))
+			NV_ERROR(dev, "PRAMIN flush timeout\n");
+	}
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -0,0 +1,322 @@
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include <linux/pagemap.h>
+
+#define NV_CTXDMA_PAGE_SHIFT 12
+#define NV_CTXDMA_PAGE_SIZE  (1 << NV_CTXDMA_PAGE_SHIFT)
+#define NV_CTXDMA_PAGE_MASK  (NV_CTXDMA_PAGE_SIZE - 1)
+
+struct nouveau_sgdma_be {
+	struct ttm_backend backend;
+	struct drm_device *dev;
+
+	dma_addr_t *pages;
+	unsigned nr_pages;
+
+	unsigned pte_start;
+	bool bound;
+};
+
+static int
+nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
+		       struct page **pages, struct page *dummy_read_page)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_device *dev = nvbe->dev;
+
+	NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages);
+
+	if (nvbe->pages)
+		return -EINVAL;
+
+	nvbe->pages = kmalloc(sizeof(dma_addr_t) * num_pages, GFP_KERNEL);
+	if (!nvbe->pages)
+		return -ENOMEM;
+
+	nvbe->nr_pages = 0;
+	while (num_pages--) {
+		nvbe->pages[nvbe->nr_pages] =
+			pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
+				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(dev->pdev,
+					  nvbe->pages[nvbe->nr_pages])) {
+			be->func->clear(be);
+			return -EFAULT;
+		}
+
+		nvbe->nr_pages++;
+	}
+
+	return 0;
+}
+
+static void
+nouveau_sgdma_clear(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_device *dev;
+
+	if (nvbe && nvbe->pages) {
+		dev = nvbe->dev;
+		NV_DEBUG(dev, "\n");
+
+		if (nvbe->bound)
+			be->func->unbind(be);
+
+		while (nvbe->nr_pages--) {
+			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		}
+		kfree(nvbe->pages);
+		nvbe->pages = NULL;
+		nvbe->nr_pages = 0;
+	}
+}
+
+static inline unsigned
+nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
+
+	if (dev_priv->card_type < NV_50)
+		return pte + 2;
+
+	return pte << 1;
+}
+
+static int
+nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_device *dev = nvbe->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+	unsigned i, j, pte;
+
+	NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start);
+
+	dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
+	pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT);
+	nvbe->pte_start = pte;
+	for (i = 0; i < nvbe->nr_pages; i++) {
+		dma_addr_t dma_offset = nvbe->pages[i];
+		uint32_t offset_l = lower_32_bits(dma_offset);
+		uint32_t offset_h = upper_32_bits(dma_offset);
+
+		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
+			if (dev_priv->card_type < NV_50)
+				nv_wo32(dev, gpuobj, pte++, offset_l | 3);
+			else {
+				nv_wo32(dev, gpuobj, pte++, offset_l | 0x21);
+				nv_wo32(dev, gpuobj, pte++, offset_h & 0xff);
+			}
+
+			dma_offset += NV_CTXDMA_PAGE_SIZE;
+		}
+	}
+	dev_priv->engine.instmem.finish_access(nvbe->dev);
+
+	if (dev_priv->card_type == NV_50) {
+		nv_wr32(dev, 0x100c80, 0x00050001);
+		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
+						nv_rd32(dev, 0x100c80));
+			return -EBUSY;
+		}
+
+		nv_wr32(dev, 0x100c80, 0x00000001);
+		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
+			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
+			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
+						nv_rd32(dev, 0x100c80));
+			return -EBUSY;
+		}
+	}
+
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nouveau_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_device *dev = nvbe->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+	unsigned i, j, pte;
+
+	NV_DEBUG(dev, "\n");
+
+	if (!nvbe->bound)
+		return 0;
+
+	dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
+	pte = nvbe->pte_start;
+	for (i = 0; i < nvbe->nr_pages; i++) {
+		dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
+
+		for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) {
+			if (dev_priv->card_type < NV_50)
+				nv_wo32(dev, gpuobj, pte++, dma_offset | 3);
+			else {
+				nv_wo32(dev, gpuobj, pte++, dma_offset | 0x21);
+				nv_wo32(dev, gpuobj, pte++, 0x00000000);
+			}
+
+			dma_offset += NV_CTXDMA_PAGE_SIZE;
+		}
+	}
+	dev_priv->engine.instmem.finish_access(nvbe->dev);
+
+	nvbe->bound = false;
+	return 0;
+}
+
+static void
+nouveau_sgdma_destroy(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+
+	if (be) {
+		NV_DEBUG(nvbe->dev, "\n");
+
+		if (nvbe) {
+			if (nvbe->pages)
+				be->func->clear(be);
+			kfree(nvbe);
+		}
+	}
+}
+
+static struct ttm_backend_func nouveau_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nouveau_sgdma_bind,
+	.unbind			= nouveau_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
+struct ttm_backend *
+nouveau_sgdma_init_ttm(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_sgdma_be *nvbe;
+
+	if (!dev_priv->gart_info.sg_ctxdma)
+		return NULL;
+
+	nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
+	if (!nvbe)
+		return NULL;
+
+	nvbe->dev = dev;
+
+	nvbe->backend.func	= &nouveau_sgdma_backend;
+
+	return &nvbe->backend;
+}
+
+int
+nouveau_sgdma_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = NULL;
+	uint32_t aper_size, obj_size;
+	int i, ret;
+
+	if (dev_priv->card_type < NV_50) {
+		aper_size = (64 * 1024 * 1024);
+		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
+		obj_size += 8; /* ctxdma header */
+	} else {
+		/* 1 entire VM page table */
+		aper_size = (512 * 1024 * 1024);
+		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
+	}
+
+	ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
+				      NVOBJ_FLAG_ALLOW_NO_REFS |
+				      NVOBJ_FLAG_ZERO_ALLOC |
+				      NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+	if (ret) {
+		NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
+		return ret;
+	}
+
+	dev_priv->gart_info.sg_dummy_page =
+		alloc_page(GFP_KERNEL|__GFP_DMA32);
+	set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags);
+	dev_priv->gart_info.sg_dummy_bus =
+		pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
+			     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	if (dev_priv->card_type < NV_50) {
+		/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
+		 * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
+		 * on those cards? */
+		nv_wo32(dev, gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
+				       (1 << 12) /* PT present */ |
+				       (0 << 13) /* PT *not* linear */ |
+				       (NV_DMA_ACCESS_RW  << 14) |
+				       (NV_DMA_TARGET_PCI << 16));
+		nv_wo32(dev, gpuobj, 1, aper_size - 1);
+		for (i = 2; i < 2 + (aper_size >> 12); i++) {
+			nv_wo32(dev, gpuobj, i,
+				    dev_priv->gart_info.sg_dummy_bus | 3);
+		}
+	} else {
+		for (i = 0; i < obj_size; i += 8) {
+			nv_wo32(dev, gpuobj, (i+0)/4,
+				    dev_priv->gart_info.sg_dummy_bus | 0x21);
+			nv_wo32(dev, gpuobj, (i+4)/4, 0);
+		}
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
+	dev_priv->gart_info.aper_base = 0;
+	dev_priv->gart_info.aper_size = aper_size;
+	dev_priv->gart_info.sg_ctxdma = gpuobj;
+	return 0;
+}
+
+void
+nouveau_sgdma_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->gart_info.sg_dummy_page) {
+		pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
+			       NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		unlock_page(dev_priv->gart_info.sg_dummy_page);
+		__free_page(dev_priv->gart_info.sg_dummy_page);
+		dev_priv->gart_info.sg_dummy_page = NULL;
+		dev_priv->gart_info.sg_dummy_bus = 0;
+	}
+
+	nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma);
+}
+
+int
+nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
+	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
+	int pte;
+
+	pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
+	if (dev_priv->card_type < NV_50) {
+		instmem->prepare_access(dev, false);
+		*page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
+		instmem->finish_access(dev);
+		return 0;
+	}
+
+	NV_ERROR(dev, "Unimplemented on NV50\n");
+	return -EINVAL;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_fifo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+struct nv50_fifo_priv {
+	struct nouveau_gpuobj_ref *thingo[2];
+	int cur_thingo;
+};
+
+#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
+
+static void
+nv50_fifo_init_thingo(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv;
+	struct nouveau_gpuobj_ref *cur;
+	int i, nr;
+
+	NV_DEBUG(dev, "\n");
+
+	cur = priv->thingo[priv->cur_thingo];
+	priv->cur_thingo = !priv->cur_thingo;
+
+	/* We never schedule channel 0 or 127 */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	for (i = 1, nr = 0; i < 127; i++) {
+		if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc)
+			nv_wo32(dev, cur->gpuobj, nr++, i);
+	}
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, 0x32f4, cur->instance >> 12);
+	nv_wr32(dev, 0x32ec, nr);
+	nv_wr32(dev, 0x2500, 0x101);
+}
+
+static int
+nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->fifos[channel];
+	uint32_t inst;
+
+	NV_DEBUG(dev, "ch%d\n", channel);
+
+	if (!chan->ramfc)
+		return -EINVAL;
+
+	if (IS_G80)
+		inst = chan->ramfc->instance >> 12;
+	else
+		inst = chan->ramfc->instance >> 8;
+	nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel),
+		 inst | NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
+
+	if (!nt)
+		nv50_fifo_init_thingo(dev);
+	return 0;
+}
+
+static void
+nv50_fifo_channel_disable(struct drm_device *dev, int channel, bool nt)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t inst;
+
+	NV_DEBUG(dev, "ch%d, nt=%d\n", channel, nt);
+
+	if (IS_G80)
+		inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80;
+	else
+		inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84;
+	nv_wr32(dev, NV50_PFIFO_CTX_TABLE(channel), inst);
+
+	if (!nt)
+		nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_reset(struct drm_device *dev)
+{
+	uint32_t pmc_e = NV_PMC_ENABLE_PFIFO;
+
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |  pmc_e);
+}
+
+static void
+nv50_fifo_init_intr(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF);
+	nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
+}
+
+static void
+nv50_fifo_init_context_table(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i;
+
+	NV_DEBUG(dev, "\n");
+
+	for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) {
+		if (dev_priv->fifos[i])
+			nv50_fifo_channel_enable(dev, i, true);
+		else
+			nv50_fifo_channel_disable(dev, i, true);
+	}
+
+	nv50_fifo_init_thingo(dev);
+}
+
+static void
+nv50_fifo_init_regs__nv(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, 0x250c, 0x6f3cfc34);
+}
+
+static void
+nv50_fifo_init_regs(struct drm_device *dev)
+{
+	NV_DEBUG(dev, "\n");
+
+	nv_wr32(dev, 0x2500, 0);
+	nv_wr32(dev, 0x3250, 0);
+	nv_wr32(dev, 0x3220, 0);
+	nv_wr32(dev, 0x3204, 0);
+	nv_wr32(dev, 0x3210, 0);
+	nv_wr32(dev, 0x3270, 0);
+
+	/* Enable dummy channels setup by nv50_instmem.c */
+	nv50_fifo_channel_enable(dev, 0, true);
+	nv50_fifo_channel_enable(dev, 127, true);
+}
+
+int
+nv50_fifo_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fifo_priv *priv;
+	int ret;
+
+	NV_DEBUG(dev, "\n");
+
+	priv = dev_priv->engine.fifo.priv;
+	if (priv) {
+		priv->cur_thingo = !priv->cur_thingo;
+		goto just_reset;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_priv->engine.fifo.priv = priv;
+
+	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
+				     NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[0]);
+	if (ret) {
+		NV_ERROR(dev, "error creating thingo0: %d\n", ret);
+		return ret;
+	}
+
+	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 128*4, 0x1000,
+				     NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo[1]);
+	if (ret) {
+		NV_ERROR(dev, "error creating thingo1: %d\n", ret);
+		return ret;
+	}
+
+just_reset:
+	nv50_fifo_init_reset(dev);
+	nv50_fifo_init_intr(dev);
+	nv50_fifo_init_context_table(dev);
+	nv50_fifo_init_regs__nv(dev);
+	nv50_fifo_init_regs(dev);
+	dev_priv->engine.fifo.enable(dev);
+	dev_priv->engine.fifo.reassign(dev, true);
+
+	return 0;
+}
+
+void
+nv50_fifo_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_fifo_priv *priv = dev_priv->engine.fifo.priv;
+
+	NV_DEBUG(dev, "\n");
+
+	if (!priv)
+		return;
+
+	nouveau_gpuobj_ref_del(dev, &priv->thingo[0]);
+	nouveau_gpuobj_ref_del(dev, &priv->thingo[1]);
+
+	dev_priv->engine.fifo.priv = NULL;
+	kfree(priv);
+}
+
+int
+nv50_fifo_channel_id(struct drm_device *dev)
+{
+	return nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH1) &
+			NV50_PFIFO_CACHE1_PUSH1_CHID_MASK;
+}
+
+int
+nv50_fifo_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramfc = NULL;
+	int ret;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	if (IS_G80) {
+		uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start;
+		uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start;
+
+		ret = nouveau_gpuobj_new_fake(dev, ramin_poffset, ramin_voffset,
+					      0x100, NVOBJ_FLAG_ZERO_ALLOC |
+					      NVOBJ_FLAG_ZERO_FREE, &ramfc,
+					      &chan->ramfc);
+		if (ret)
+			return ret;
+
+		ret = nouveau_gpuobj_new_fake(dev, ramin_poffset + 0x0400,
+					      ramin_voffset + 0x0400, 4096,
+					      0, NULL, &chan->cache);
+		if (ret)
+			return ret;
+	} else {
+		ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256,
+					     NVOBJ_FLAG_ZERO_ALLOC |
+					     NVOBJ_FLAG_ZERO_FREE,
+					     &chan->ramfc);
+		if (ret)
+			return ret;
+		ramfc = chan->ramfc->gpuobj;
+
+		ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024,
+					     0, &chan->cache);
+		if (ret)
+			return ret;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+
+	nv_wo32(dev, ramfc, 0x08/4, chan->pushbuf_base);
+	nv_wo32(dev, ramfc, 0x10/4, chan->pushbuf_base);
+	nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4);
+	nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
+	nv_wo32(dev, ramfc, 0x3c/4, 0x00086078);
+	nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff);
+	nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff);
+	nv_wo32(dev, ramfc, 0x40/4, 0x00000000);
+	nv_wo32(dev, ramfc, 0x7c/4, 0x30000001);
+	nv_wo32(dev, ramfc, 0x78/4, 0x00000000);
+	nv_wo32(dev, ramfc, 0x4c/4, 0xffffffff);
+
+	if (!IS_G80) {
+		nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id);
+		nv_wo32(dev, chan->ramin->gpuobj, 1,
+						chan->ramfc->instance >> 8);
+
+		nv_wo32(dev, ramfc, 0x88/4, chan->cache->instance >> 10);
+		nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12);
+	}
+
+	dev_priv->engine.instmem.finish_access(dev);
+
+	ret = nv50_fifo_channel_enable(dev, chan->id, false);
+	if (ret) {
+		NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret);
+		nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+		return ret;
+	}
+
+	return 0;
+}
+
+void
+nv50_fifo_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_gpuobj_ref *ramfc = chan->ramfc;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	/* This will ensure the channel is seen as disabled. */
+	chan->ramfc = NULL;
+	nv50_fifo_channel_disable(dev, chan->id, false);
+
+	/* Dummy channel, also used on ch 127 */
+	if (chan->id == 0)
+		nv50_fifo_channel_disable(dev, 127, false);
+
+	nouveau_gpuobj_ref_del(dev, &ramfc);
+	nouveau_gpuobj_ref_del(dev, &chan->cache);
+}
+
+int
+nv50_fifo_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
+	struct nouveau_gpuobj *cache = chan->cache->gpuobj;
+	int ptr, cnt;
+
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+
+	dev_priv->engine.instmem.prepare_access(dev, false);
+
+	nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4));
+	nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4));
+	nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4));
+	nv_wr32(dev, 0x3320, nv_ro32(dev, ramfc, 0x0c/4));
+	nv_wr32(dev, 0x3244, nv_ro32(dev, ramfc, 0x10/4));
+	nv_wr32(dev, 0x3328, nv_ro32(dev, ramfc, 0x14/4));
+	nv_wr32(dev, 0x3368, nv_ro32(dev, ramfc, 0x18/4));
+	nv_wr32(dev, 0x336c, nv_ro32(dev, ramfc, 0x1c/4));
+	nv_wr32(dev, 0x3370, nv_ro32(dev, ramfc, 0x20/4));
+	nv_wr32(dev, 0x3374, nv_ro32(dev, ramfc, 0x24/4));
+	nv_wr32(dev, 0x3378, nv_ro32(dev, ramfc, 0x28/4));
+	nv_wr32(dev, 0x337c, nv_ro32(dev, ramfc, 0x2c/4));
+	nv_wr32(dev, 0x3228, nv_ro32(dev, ramfc, 0x30/4));
+	nv_wr32(dev, 0x3364, nv_ro32(dev, ramfc, 0x34/4));
+	nv_wr32(dev, 0x32a0, nv_ro32(dev, ramfc, 0x38/4));
+	nv_wr32(dev, 0x3224, nv_ro32(dev, ramfc, 0x3c/4));
+	nv_wr32(dev, 0x324c, nv_ro32(dev, ramfc, 0x40/4));
+	nv_wr32(dev, 0x2044, nv_ro32(dev, ramfc, 0x44/4));
+	nv_wr32(dev, 0x322c, nv_ro32(dev, ramfc, 0x48/4));
+	nv_wr32(dev, 0x3234, nv_ro32(dev, ramfc, 0x4c/4));
+	nv_wr32(dev, 0x3340, nv_ro32(dev, ramfc, 0x50/4));
+	nv_wr32(dev, 0x3344, nv_ro32(dev, ramfc, 0x54/4));
+	nv_wr32(dev, 0x3280, nv_ro32(dev, ramfc, 0x58/4));
+	nv_wr32(dev, 0x3254, nv_ro32(dev, ramfc, 0x5c/4));
+	nv_wr32(dev, 0x3260, nv_ro32(dev, ramfc, 0x60/4));
+	nv_wr32(dev, 0x3264, nv_ro32(dev, ramfc, 0x64/4));
+	nv_wr32(dev, 0x3268, nv_ro32(dev, ramfc, 0x68/4));
+	nv_wr32(dev, 0x326c, nv_ro32(dev, ramfc, 0x6c/4));
+	nv_wr32(dev, 0x32e4, nv_ro32(dev, ramfc, 0x70/4));
+	nv_wr32(dev, 0x3248, nv_ro32(dev, ramfc, 0x74/4));
+	nv_wr32(dev, 0x2088, nv_ro32(dev, ramfc, 0x78/4));
+	nv_wr32(dev, 0x2058, nv_ro32(dev, ramfc, 0x7c/4));
+	nv_wr32(dev, 0x2210, nv_ro32(dev, ramfc, 0x80/4));
+
+	cnt = nv_ro32(dev, ramfc, 0x84/4);
+	for (ptr = 0; ptr < cnt; ptr++) {
+		nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr),
+			nv_ro32(dev, cache, (ptr * 2) + 0));
+		nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr),
+			nv_ro32(dev, cache, (ptr * 2) + 1));
+	}
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
+
+	/* guessing that all the 0x34xx regs aren't on NV50 */
+	if (!IS_G80) {
+		nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4));
+		nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4));
+		nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4));
+		nv_wr32(dev, 0x3408, nv_ro32(dev, ramfc, 0x94/4));
+		nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4));
+	}
+
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
+	return 0;
+}
+
+int
+nv50_fifo_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_gpuobj *ramfc, *cache;
+	struct nouveau_channel *chan = NULL;
+	int chid, get, put, ptr;
+
+	NV_DEBUG(dev, "\n");
+
+	chid = pfifo->channel_id(dev);
+	if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1)
+		return 0;
+
+	chan = dev_priv->fifos[chid];
+	if (!chan) {
+		NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
+		return -EINVAL;
+	}
+	NV_DEBUG(dev, "ch%d\n", chan->id);
+	ramfc = chan->ramfc->gpuobj;
+	cache = chan->cache->gpuobj;
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+
+	nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330));
+	nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334));
+	nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240));
+	nv_wo32(dev, ramfc, 0x0c/4, nv_rd32(dev, 0x3320));
+	nv_wo32(dev, ramfc, 0x10/4, nv_rd32(dev, 0x3244));
+	nv_wo32(dev, ramfc, 0x14/4, nv_rd32(dev, 0x3328));
+	nv_wo32(dev, ramfc, 0x18/4, nv_rd32(dev, 0x3368));
+	nv_wo32(dev, ramfc, 0x1c/4, nv_rd32(dev, 0x336c));
+	nv_wo32(dev, ramfc, 0x20/4, nv_rd32(dev, 0x3370));
+	nv_wo32(dev, ramfc, 0x24/4, nv_rd32(dev, 0x3374));
+	nv_wo32(dev, ramfc, 0x28/4, nv_rd32(dev, 0x3378));
+	nv_wo32(dev, ramfc, 0x2c/4, nv_rd32(dev, 0x337c));
+	nv_wo32(dev, ramfc, 0x30/4, nv_rd32(dev, 0x3228));
+	nv_wo32(dev, ramfc, 0x34/4, nv_rd32(dev, 0x3364));
+	nv_wo32(dev, ramfc, 0x38/4, nv_rd32(dev, 0x32a0));
+	nv_wo32(dev, ramfc, 0x3c/4, nv_rd32(dev, 0x3224));
+	nv_wo32(dev, ramfc, 0x40/4, nv_rd32(dev, 0x324c));
+	nv_wo32(dev, ramfc, 0x44/4, nv_rd32(dev, 0x2044));
+	nv_wo32(dev, ramfc, 0x48/4, nv_rd32(dev, 0x322c));
+	nv_wo32(dev, ramfc, 0x4c/4, nv_rd32(dev, 0x3234));
+	nv_wo32(dev, ramfc, 0x50/4, nv_rd32(dev, 0x3340));
+	nv_wo32(dev, ramfc, 0x54/4, nv_rd32(dev, 0x3344));
+	nv_wo32(dev, ramfc, 0x58/4, nv_rd32(dev, 0x3280));
+	nv_wo32(dev, ramfc, 0x5c/4, nv_rd32(dev, 0x3254));
+	nv_wo32(dev, ramfc, 0x60/4, nv_rd32(dev, 0x3260));
+	nv_wo32(dev, ramfc, 0x64/4, nv_rd32(dev, 0x3264));
+	nv_wo32(dev, ramfc, 0x68/4, nv_rd32(dev, 0x3268));
+	nv_wo32(dev, ramfc, 0x6c/4, nv_rd32(dev, 0x326c));
+	nv_wo32(dev, ramfc, 0x70/4, nv_rd32(dev, 0x32e4));
+	nv_wo32(dev, ramfc, 0x74/4, nv_rd32(dev, 0x3248));
+	nv_wo32(dev, ramfc, 0x78/4, nv_rd32(dev, 0x2088));
+	nv_wo32(dev, ramfc, 0x7c/4, nv_rd32(dev, 0x2058));
+	nv_wo32(dev, ramfc, 0x80/4, nv_rd32(dev, 0x2210));
+
+	put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2;
+	get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2;
+	ptr = 0;
+	while (put != get) {
+		nv_wo32(dev, cache, ptr++,
+			    nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get)));
+		nv_wo32(dev, cache, ptr++,
+			    nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get)));
+		get = (get + 1) & 0x1ff;
+	}
+
+	/* guessing that all the 0x34xx regs aren't on NV50 */
+	if (!IS_G80) {
+		nv_wo32(dev, ramfc, 0x84/4, ptr >> 1);
+		nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c));
+		nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400));
+		nv_wo32(dev, ramfc, 0x90/4, nv_rd32(dev, 0x3404));
+		nv_wo32(dev, ramfc, 0x94/4, nv_rd32(dev, 0x3408));
+		nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410));
+	}
+
+	dev_priv->engine.instmem.finish_access(dev);
+
+	/*XXX: probably reload ch127 (NULL) state back too */
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 127);
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv10_graph.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv10_graph.c
@@ -0,0 +1,1009 @@
+/*
+ * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr>
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+
+#define NV10_FIFO_NUMBER 32
+
+struct pipe_state {
+	uint32_t pipe_0x0000[0x040/4];
+	uint32_t pipe_0x0040[0x010/4];
+	uint32_t pipe_0x0200[0x0c0/4];
+	uint32_t pipe_0x4400[0x080/4];
+	uint32_t pipe_0x6400[0x3b0/4];
+	uint32_t pipe_0x6800[0x2f0/4];
+	uint32_t pipe_0x6c00[0x030/4];
+	uint32_t pipe_0x7000[0x130/4];
+	uint32_t pipe_0x7400[0x0c0/4];
+	uint32_t pipe_0x7800[0x0c0/4];
+};
+
+static int nv10_graph_ctx_regs[] = {
+	NV10_PGRAPH_CTX_SWITCH1,
+	NV10_PGRAPH_CTX_SWITCH2,
+	NV10_PGRAPH_CTX_SWITCH3,
+	NV10_PGRAPH_CTX_SWITCH4,
+	NV10_PGRAPH_CTX_SWITCH5,
+	NV10_PGRAPH_CTX_CACHE1,	/* 8 values from 0x400160 to 0x40017c */
+	NV10_PGRAPH_CTX_CACHE2,	/* 8 values from 0x400180 to 0x40019c */
+	NV10_PGRAPH_CTX_CACHE3,	/* 8 values from 0x4001a0 to 0x4001bc */
+	NV10_PGRAPH_CTX_CACHE4,	/* 8 values from 0x4001c0 to 0x4001dc */
+	NV10_PGRAPH_CTX_CACHE5,	/* 8 values from 0x4001e0 to 0x4001fc */
+	0x00400164,
+	0x00400184,
+	0x004001a4,
+	0x004001c4,
+	0x004001e4,
+	0x00400168,
+	0x00400188,
+	0x004001a8,
+	0x004001c8,
+	0x004001e8,
+	0x0040016c,
+	0x0040018c,
+	0x004001ac,
+	0x004001cc,
+	0x004001ec,
+	0x00400170,
+	0x00400190,
+	0x004001b0,
+	0x004001d0,
+	0x004001f0,
+	0x00400174,
+	0x00400194,
+	0x004001b4,
+	0x004001d4,
+	0x004001f4,
+	0x00400178,
+	0x00400198,
+	0x004001b8,
+	0x004001d8,
+	0x004001f8,
+	0x0040017c,
+	0x0040019c,
+	0x004001bc,
+	0x004001dc,
+	0x004001fc,
+	NV10_PGRAPH_CTX_USER,
+	NV04_PGRAPH_DMA_START_0,
+	NV04_PGRAPH_DMA_START_1,
+	NV04_PGRAPH_DMA_LENGTH,
+	NV04_PGRAPH_DMA_MISC,
+	NV10_PGRAPH_DMA_PITCH,
+	NV04_PGRAPH_BOFFSET0,
+	NV04_PGRAPH_BBASE0,
+	NV04_PGRAPH_BLIMIT0,
+	NV04_PGRAPH_BOFFSET1,
+	NV04_PGRAPH_BBASE1,
+	NV04_PGRAPH_BLIMIT1,
+	NV04_PGRAPH_BOFFSET2,
+	NV04_PGRAPH_BBASE2,
+	NV04_PGRAPH_BLIMIT2,
+	NV04_PGRAPH_BOFFSET3,
+	NV04_PGRAPH_BBASE3,
+	NV04_PGRAPH_BLIMIT3,
+	NV04_PGRAPH_BOFFSET4,
+	NV04_PGRAPH_BBASE4,
+	NV04_PGRAPH_BLIMIT4,
+	NV04_PGRAPH_BOFFSET5,
+	NV04_PGRAPH_BBASE5,
+	NV04_PGRAPH_BLIMIT5,
+	NV04_PGRAPH_BPITCH0,
+	NV04_PGRAPH_BPITCH1,
+	NV04_PGRAPH_BPITCH2,
+	NV04_PGRAPH_BPITCH3,
+	NV04_PGRAPH_BPITCH4,
+	NV10_PGRAPH_SURFACE,
+	NV10_PGRAPH_STATE,
+	NV04_PGRAPH_BSWIZZLE2,
+	NV04_PGRAPH_BSWIZZLE5,
+	NV04_PGRAPH_BPIXEL,
+	NV10_PGRAPH_NOTIFY,
+	NV04_PGRAPH_PATT_COLOR0,
+	NV04_PGRAPH_PATT_COLOR1,
+	NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
+	0x00400904,
+	0x00400908,
+	0x0040090c,
+	0x00400910,
+	0x00400914,
+	0x00400918,
+	0x0040091c,
+	0x00400920,
+	0x00400924,
+	0x00400928,
+	0x0040092c,
+	0x00400930,
+	0x00400934,
+	0x00400938,
+	0x0040093c,
+	0x00400940,
+	0x00400944,
+	0x00400948,
+	0x0040094c,
+	0x00400950,
+	0x00400954,
+	0x00400958,
+	0x0040095c,
+	0x00400960,
+	0x00400964,
+	0x00400968,
+	0x0040096c,
+	0x00400970,
+	0x00400974,
+	0x00400978,
+	0x0040097c,
+	0x00400980,
+	0x00400984,
+	0x00400988,
+	0x0040098c,
+	0x00400990,
+	0x00400994,
+	0x00400998,
+	0x0040099c,
+	0x004009a0,
+	0x004009a4,
+	0x004009a8,
+	0x004009ac,
+	0x004009b0,
+	0x004009b4,
+	0x004009b8,
+	0x004009bc,
+	0x004009c0,
+	0x004009c4,
+	0x004009c8,
+	0x004009cc,
+	0x004009d0,
+	0x004009d4,
+	0x004009d8,
+	0x004009dc,
+	0x004009e0,
+	0x004009e4,
+	0x004009e8,
+	0x004009ec,
+	0x004009f0,
+	0x004009f4,
+	0x004009f8,
+	0x004009fc,
+	NV04_PGRAPH_PATTERN,	/* 2 values from 0x400808 to 0x40080c */
+	0x0040080c,
+	NV04_PGRAPH_PATTERN_SHAPE,
+	NV03_PGRAPH_MONO_COLOR0,
+	NV04_PGRAPH_ROP3,
+	NV04_PGRAPH_CHROMA,
+	NV04_PGRAPH_BETA_AND,
+	NV04_PGRAPH_BETA_PREMULT,
+	0x00400e70,
+	0x00400e74,
+	0x00400e78,
+	0x00400e7c,
+	0x00400e80,
+	0x00400e84,
+	0x00400e88,
+	0x00400e8c,
+	0x00400ea0,
+	0x00400ea4,
+	0x00400ea8,
+	0x00400e90,
+	0x00400e94,
+	0x00400e98,
+	0x00400e9c,
+	NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */
+	NV10_PGRAPH_WINDOWCLIP_VERTICAL,   /* 8 values from 0x400f20-0x400f3c */
+	0x00400f04,
+	0x00400f24,
+	0x00400f08,
+	0x00400f28,
+	0x00400f0c,
+	0x00400f2c,
+	0x00400f10,
+	0x00400f30,
+	0x00400f14,
+	0x00400f34,
+	0x00400f18,
+	0x00400f38,
+	0x00400f1c,
+	0x00400f3c,
+	NV10_PGRAPH_XFMODE0,
+	NV10_PGRAPH_XFMODE1,
+	NV10_PGRAPH_GLOBALSTATE0,
+	NV10_PGRAPH_GLOBALSTATE1,
+	NV04_PGRAPH_STORED_FMT,
+	NV04_PGRAPH_SOURCE_COLOR,
+	NV03_PGRAPH_ABS_X_RAM,	/* 32 values from 0x400400 to 0x40047c */
+	NV03_PGRAPH_ABS_Y_RAM,	/* 32 values from 0x400480 to 0x4004fc */
+	0x00400404,
+	0x00400484,
+	0x00400408,
+	0x00400488,
+	0x0040040c,
+	0x0040048c,
+	0x00400410,
+	0x00400490,
+	0x00400414,
+	0x00400494,
+	0x00400418,
+	0x00400498,
+	0x0040041c,
+	0x0040049c,
+	0x00400420,
+	0x004004a0,
+	0x00400424,
+	0x004004a4,
+	0x00400428,
+	0x004004a8,
+	0x0040042c,
+	0x004004ac,
+	0x00400430,
+	0x004004b0,
+	0x00400434,
+	0x004004b4,
+	0x00400438,
+	0x004004b8,
+	0x0040043c,
+	0x004004bc,
+	0x00400440,
+	0x004004c0,
+	0x00400444,
+	0x004004c4,
+	0x00400448,
+	0x004004c8,
+	0x0040044c,
+	0x004004cc,
+	0x00400450,
+	0x004004d0,
+	0x00400454,
+	0x004004d4,
+	0x00400458,
+	0x004004d8,
+	0x0040045c,
+	0x004004dc,
+	0x00400460,
+	0x004004e0,
+	0x00400464,
+	0x004004e4,
+	0x00400468,
+	0x004004e8,
+	0x0040046c,
+	0x004004ec,
+	0x00400470,
+	0x004004f0,
+	0x00400474,
+	0x004004f4,
+	0x00400478,
+	0x004004f8,
+	0x0040047c,
+	0x004004fc,
+	NV03_PGRAPH_ABS_UCLIP_XMIN,
+	NV03_PGRAPH_ABS_UCLIP_XMAX,
+	NV03_PGRAPH_ABS_UCLIP_YMIN,
+	NV03_PGRAPH_ABS_UCLIP_YMAX,
+	0x00400550,
+	0x00400558,
+	0x00400554,
+	0x0040055c,
+	NV03_PGRAPH_ABS_UCLIPA_XMIN,
+	NV03_PGRAPH_ABS_UCLIPA_XMAX,
+	NV03_PGRAPH_ABS_UCLIPA_YMIN,
+	NV03_PGRAPH_ABS_UCLIPA_YMAX,
+	NV03_PGRAPH_ABS_ICLIP_XMAX,
+	NV03_PGRAPH_ABS_ICLIP_YMAX,
+	NV03_PGRAPH_XY_LOGIC_MISC0,
+	NV03_PGRAPH_XY_LOGIC_MISC1,
+	NV03_PGRAPH_XY_LOGIC_MISC2,
+	NV03_PGRAPH_XY_LOGIC_MISC3,
+	NV03_PGRAPH_CLIPX_0,
+	NV03_PGRAPH_CLIPX_1,
+	NV03_PGRAPH_CLIPY_0,
+	NV03_PGRAPH_CLIPY_1,
+	NV10_PGRAPH_COMBINER0_IN_ALPHA,
+	NV10_PGRAPH_COMBINER1_IN_ALPHA,
+	NV10_PGRAPH_COMBINER0_IN_RGB,
+	NV10_PGRAPH_COMBINER1_IN_RGB,
+	NV10_PGRAPH_COMBINER_COLOR0,
+	NV10_PGRAPH_COMBINER_COLOR1,
+	NV10_PGRAPH_COMBINER0_OUT_ALPHA,
+	NV10_PGRAPH_COMBINER1_OUT_ALPHA,
+	NV10_PGRAPH_COMBINER0_OUT_RGB,
+	NV10_PGRAPH_COMBINER1_OUT_RGB,
+	NV10_PGRAPH_COMBINER_FINAL0,
+	NV10_PGRAPH_COMBINER_FINAL1,
+	0x00400e00,
+	0x00400e04,
+	0x00400e08,
+	0x00400e0c,
+	0x00400e10,
+	0x00400e14,
+	0x00400e18,
+	0x00400e1c,
+	0x00400e20,
+	0x00400e24,
+	0x00400e28,
+	0x00400e2c,
+	0x00400e30,
+	0x00400e34,
+	0x00400e38,
+	0x00400e3c,
+	NV04_PGRAPH_PASSTHRU_0,
+	NV04_PGRAPH_PASSTHRU_1,
+	NV04_PGRAPH_PASSTHRU_2,
+	NV10_PGRAPH_DIMX_TEXTURE,
+	NV10_PGRAPH_WDIMX_TEXTURE,
+	NV10_PGRAPH_DVD_COLORFMT,
+	NV10_PGRAPH_SCALED_FORMAT,
+	NV04_PGRAPH_MISC24_0,
+	NV04_PGRAPH_MISC24_1,
+	NV04_PGRAPH_MISC24_2,
+	NV03_PGRAPH_X_MISC,
+	NV03_PGRAPH_Y_MISC,
+	NV04_PGRAPH_VALID1,
+	NV04_PGRAPH_VALID2,
+};
+
+static int nv17_graph_ctx_regs[] = {
+	NV10_PGRAPH_DEBUG_4,
+	0x004006b0,
+	0x00400eac,
+	0x00400eb0,
+	0x00400eb4,
+	0x00400eb8,
+	0x00400ebc,
+	0x00400ec0,
+	0x00400ec4,
+	0x00400ec8,
+	0x00400ecc,
+	0x00400ed0,
+	0x00400ed4,
+	0x00400ed8,
+	0x00400edc,
+	0x00400ee0,
+	0x00400a00,
+	0x00400a04,
+};
+
+struct graph_state {
+	int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
+	int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
+	struct pipe_state pipe_state;
+	uint32_t lma_window[4];
+};
+
+#define PIPE_SAVE(dev, state, addr)					\
+	do {								\
+		int __i;						\
+		nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
+		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
+			state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
+	} while (0)
+
+#define PIPE_RESTORE(dev, state, addr)					\
+	do {								\
+		int __i;						\
+		nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
+		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
+			nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \
+	} while (0)
+
+static void nv10_graph_save_pipe(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	struct pipe_state *pipe = &pgraph_ctx->pipe_state;
+
+	PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
+	PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
+	PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400);
+	PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800);
+	PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00);
+	PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000);
+	PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400);
+	PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800);
+	PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040);
+	PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000);
+}
+
+static void nv10_graph_load_pipe(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	struct pipe_state *pipe = &pgraph_ctx->pipe_state;
+	uint32_t xfmode0, xfmode1;
+	int i;
+
+	nouveau_wait_for_idle(dev);
+	/* XXX check haiku comments */
+	xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
+	xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
+	nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
+	nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
+	for (i = 0; i < 4; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+	for (i = 0; i < 4; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
+	for (i = 0; i < 3; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
+	for (i = 0; i < 3; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
+	nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
+
+
+	PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
+	nouveau_wait_for_idle(dev);
+
+	/* restore XFMODE */
+	nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
+	nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
+	PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400);
+	PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800);
+	PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00);
+	PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000);
+	PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400);
+	PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800);
+	PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
+	PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000);
+	PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040);
+	nouveau_wait_for_idle(dev);
+}
+
+static void nv10_graph_create_pipe(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
+	uint32_t *fifo_pipe_state_addr;
+	int i;
+#define PIPE_INIT(addr) \
+	do { \
+		fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
+	} while (0)
+#define PIPE_INIT_END(addr) \
+	do { \
+		uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \
+				ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \
+		if (fifo_pipe_state_addr != __end_addr) \
+			NV_ERROR(dev, "incomplete pipe init for 0x%x :  %p/%p\n", \
+				addr, fifo_pipe_state_addr, __end_addr); \
+	} while (0)
+#define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
+
+	PIPE_INIT(0x0200);
+	for (i = 0; i < 48; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x0200);
+
+	PIPE_INIT(0x6400);
+	for (i = 0; i < 211; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x40000000);
+	NV_WRITE_PIPE_INIT(0x40000000);
+	NV_WRITE_PIPE_INIT(0x40000000);
+	NV_WRITE_PIPE_INIT(0x40000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f000000);
+	NV_WRITE_PIPE_INIT(0x3f000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	PIPE_INIT_END(0x6400);
+
+	PIPE_INIT(0x6800);
+	for (i = 0; i < 162; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x3f800000);
+	for (i = 0; i < 25; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x6800);
+
+	PIPE_INIT(0x6c00);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0xbf800000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x6c00);
+
+	PIPE_INIT(0x7000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x00000000);
+	NV_WRITE_PIPE_INIT(0x7149f2ca);
+	for (i = 0; i < 35; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x7000);
+
+	PIPE_INIT(0x7400);
+	for (i = 0; i < 48; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x7400);
+
+	PIPE_INIT(0x7800);
+	for (i = 0; i < 48; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x7800);
+
+	PIPE_INIT(0x4400);
+	for (i = 0; i < 32; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x4400);
+
+	PIPE_INIT(0x0000);
+	for (i = 0; i < 16; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x0000);
+
+	PIPE_INIT(0x0040);
+	for (i = 0; i < 4; i++)
+		NV_WRITE_PIPE_INIT(0x00000000);
+	PIPE_INIT_END(0x0040);
+
+#undef PIPE_INIT
+#undef PIPE_INIT_END
+#undef NV_WRITE_PIPE_INIT
+}
+
+static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) {
+		if (nv10_graph_ctx_regs[i] == reg)
+			return i;
+	}
+	NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg);
+	return -1;
+}
+
+static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) {
+		if (nv17_graph_ctx_regs[i] == reg)
+			return i;
+	}
+	NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg);
+	return -1;
+}
+
+int nv10_graph_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+	uint32_t tmp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
+		nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
+	if (dev_priv->chipset >= 0x17) {
+		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
+			nv_wr32(dev, nv17_graph_ctx_regs[i],
+						pgraph_ctx->nv17[i]);
+	}
+
+	nv10_graph_load_pipe(chan);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
+	tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
+	nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24);
+	tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
+	nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff);
+	return 0;
+}
+
+int
+nv10_graph_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_channel *chan;
+	struct graph_state *ctx;
+	uint32_t tmp;
+	int i;
+
+	chan = pgraph->channel(dev);
+	if (!chan)
+		return 0;
+	ctx = chan->pgraph_ctx;
+
+	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
+		ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]);
+
+	if (dev_priv->chipset >= 0x17) {
+		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
+			ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]);
+	}
+
+	nv10_graph_save_pipe(chan);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
+	tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
+	tmp |= (pfifo->channels - 1) << 24;
+	nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
+	return 0;
+}
+
+void
+nv10_graph_context_switch(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_channel *chan = NULL;
+	int chid;
+
+	pgraph->fifo_access(dev, false);
+	nouveau_wait_for_idle(dev);
+
+	/* If previous context is valid, we need to save it */
+	nv10_graph_unload_context(dev);
+
+	/* Load context for next channel */
+	chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
+	chan = dev_priv->fifos[chid];
+	if (chan)
+		nv10_graph_load_context(chan);
+
+	pgraph->fifo_access(dev, true);
+}
+
+#define NV_WRITE_CTX(reg, val) do { \
+	int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
+	if (offset > 0) \
+		pgraph_ctx->nv10[offset] = val; \
+	} while (0)
+
+#define NV17_WRITE_CTX(reg, val) do { \
+	int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
+	if (offset > 0) \
+		pgraph_ctx->nv17[offset] = val; \
+	} while (0)
+
+struct nouveau_channel *
+nv10_graph_channel(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chid = dev_priv->engine.fifo.channels;
+
+	if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000)
+		chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24;
+
+	if (chid >= dev_priv->engine.fifo.channels)
+		return NULL;
+
+	return dev_priv->fifos[chid];
+}
+
+int nv10_graph_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct graph_state *pgraph_ctx;
+
+	NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id);
+
+	chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
+						GFP_KERNEL);
+	if (pgraph_ctx == NULL)
+		return -ENOMEM;
+
+
+	NV_WRITE_CTX(0x00400e88, 0x08000000);
+	NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
+	NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
+	NV_WRITE_CTX(0x00400e10, 0x00001000);
+	NV_WRITE_CTX(0x00400e14, 0x00001000);
+	NV_WRITE_CTX(0x00400e30, 0x00080008);
+	NV_WRITE_CTX(0x00400e34, 0x00080008);
+	if (dev_priv->chipset >= 0x17) {
+		/* is it really needed ??? */
+		NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
+					nv_rd32(dev, NV10_PGRAPH_DEBUG_4));
+		NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0));
+		NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
+		NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
+		NV17_WRITE_CTX(0x00400ec0, 0x00000080);
+		NV17_WRITE_CTX(0x00400ed0, 0x00000080);
+	}
+	NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
+
+	nv10_graph_create_pipe(chan);
+	return 0;
+}
+
+void nv10_graph_destroy_context(struct nouveau_channel *chan)
+{
+	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
+
+	kfree(pgraph_ctx);
+	chan->pgraph_ctx = NULL;
+}
+
+void
+nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			     uint32_t size, uint32_t pitch)
+{
+	uint32_t limit = max(1u, addr + size) - 1;
+
+	if (pitch)
+		addr |= 1 << 31;
+
+	nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit);
+	nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch);
+	nv_wr32(dev, NV10_PGRAPH_TILE(i), addr);
+}
+
+int nv10_graph_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+	int i;
+
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
+			~NV_PMC_ENABLE_PGRAPH);
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
+			 NV_PMC_ENABLE_PGRAPH);
+
+	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
+	/* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
+				      (1<<29) |
+				      (1<<31));
+	if (dev_priv->chipset >= 0x17) {
+		nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000);
+		nv_wr32(dev, 0x400a10, 0x3ff3fb6);
+		nv_wr32(dev, 0x400838, 0x2f8684);
+		nv_wr32(dev, 0x40083c, 0x115f3f);
+		nv_wr32(dev, 0x004006b0, 0x40000020);
+	} else
+		nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
+		nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
+
+	tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
+	tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
+	nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
+	nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
+
+	return 0;
+}
+
+void nv10_graph_takedown(struct drm_device *dev)
+{
+}
+
+static int
+nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
+			   int mthd, uint32_t data)
+{
+	struct drm_device *dev = chan->dev;
+	struct graph_state *ctx = chan->pgraph_ctx;
+	struct pipe_state *pipe = &ctx->pipe_state;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
+	uint32_t xfmode0, xfmode1;
+	int i;
+
+	ctx->lma_window[(mthd - 0x1638) / 4] = data;
+
+	if (mthd != 0x1644)
+		return 0;
+
+	nouveau_wait_for_idle(dev);
+
+	PIPE_SAVE(dev, pipe_0x0040, 0x0040);
+	PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
+
+	PIPE_RESTORE(dev, ctx->lma_window, 0x6790);
+
+	nouveau_wait_for_idle(dev);
+
+	xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
+	xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
+
+	PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
+	PIPE_SAVE(dev, pipe_0x64c0, 0x64c0);
+	PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0);
+	PIPE_SAVE(dev, pipe_0x6a80, 0x6a80);
+
+	nouveau_wait_for_idle(dev);
+
+	nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
+	nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
+	for (i = 0; i < 4; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+	for (i = 0; i < 4; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
+	for (i = 0; i < 3; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
+	for (i = 0; i < 3; i++)
+		nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
+	nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
+
+	PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
+
+	nouveau_wait_for_idle(dev);
+
+	PIPE_RESTORE(dev, pipe_0x0040, 0x0040);
+
+	nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
+	nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
+
+	PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0);
+	PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0);
+	PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80);
+	PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
+
+	nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
+	nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
+
+	nouveau_wait_for_idle(dev);
+
+	pgraph->fifo_access(dev, true);
+
+	return 0;
+}
+
+static int
+nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
+			   int mthd, uint32_t data)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+
+	nouveau_wait_for_idle(dev);
+
+	nv_wr32(dev, NV10_PGRAPH_DEBUG_4,
+		nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8);
+	nv_wr32(dev, 0x004006b0,
+		nv_rd32(dev, 0x004006b0) | 0x8 << 24);
+
+	pgraph->fifo_access(dev, true);
+
+	return 0;
+}
+
+static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = {
+	{ 0x1638, nv17_graph_mthd_lma_window },
+	{ 0x163c, nv17_graph_mthd_lma_window },
+	{ 0x1640, nv17_graph_mthd_lma_window },
+	{ 0x1644, nv17_graph_mthd_lma_window },
+	{ 0x1658, nv17_graph_mthd_lma_enable },
+	{}
+};
+
+struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x0039, false, NULL }, /* m2mf */
+	{ 0x004a, false, NULL }, /* gdirect */
+	{ 0x005f, false, NULL }, /* imageblit */
+	{ 0x009f, false, NULL }, /* imageblit (nv12) */
+	{ 0x008a, false, NULL }, /* ifc */
+	{ 0x0089, false, NULL }, /* sifm */
+	{ 0x0062, false, NULL }, /* surf2d */
+	{ 0x0043, false, NULL }, /* rop */
+	{ 0x0012, false, NULL }, /* beta1 */
+	{ 0x0072, false, NULL }, /* beta4 */
+	{ 0x0019, false, NULL }, /* cliprect */
+	{ 0x0044, false, NULL }, /* pattern */
+	{ 0x0052, false, NULL }, /* swzsurf */
+	{ 0x0093, false, NULL }, /* surf3d */
+	{ 0x0094, false, NULL }, /* tex_tri */
+	{ 0x0095, false, NULL }, /* multitex_tri */
+	{ 0x0056, false, NULL }, /* celcius (nv10) */
+	{ 0x0096, false, NULL }, /* celcius (nv11) */
+	{ 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */
+	{}
+};
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/Kconfig
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/Kconfig
@@ -0,0 +1,44 @@
+config DRM_NOUVEAU
+	tristate "Nouveau (nVidia) cards"
+	depends on DRM
+        select FW_LOADER
+	select DRM_KMS_HELPER
+	select DRM_TTM
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB
+	select FRAMEBUFFER_CONSOLE if !EMBEDDED
+	select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT
+	help
+	  Choose this option for open-source nVidia support.
+
+config DRM_NOUVEAU_BACKLIGHT
+	bool "Support for backlight control"
+	depends on DRM_NOUVEAU
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display
+	  (e.g. a laptop panel).
+
+config DRM_NOUVEAU_DEBUG
+	bool "Build in Nouveau's debugfs support"
+	depends on DRM_NOUVEAU && DEBUG_FS
+	default y
+	help
+	  Say Y here if you want Nouveau to output debugging information
+	  via debugfs.
+
+menu "I2C encoder or helper chips"
+     depends on DRM && DRM_KMS_HELPER && I2C
+
+config DRM_I2C_CH7006
+	tristate "Chrontel ch7006 TV encoder"
+	default m if DRM_NOUVEAU
+	help
+	  Support for Chrontel ch7006 and similar TV encoders, found
+	  on some nVidia video cards.
+
+	  This driver is currently only useful if you're also using
+	  the nouveau driver.
+endmenu
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_evo.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_evo.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 NV50_EVO_UPDATE                                              0x00000080
+#define NV50_EVO_UNK84                                               0x00000084
+#define NV50_EVO_UNK84_NOTIFY                                        0x40000000
+#define NV50_EVO_UNK84_NOTIFY_DISABLED                               0x00000000
+#define NV50_EVO_UNK84_NOTIFY_ENABLED                                0x40000000
+#define NV50_EVO_DMA_NOTIFY                                          0x00000088
+#define NV50_EVO_DMA_NOTIFY_HANDLE                                   0xffffffff
+#define NV50_EVO_DMA_NOTIFY_HANDLE_NONE                              0x00000000
+#define NV50_EVO_UNK8C                                               0x0000008C
+
+#define NV50_EVO_DAC(n, r)                       ((n) * 0x80 + NV50_EVO_DAC_##r)
+#define NV50_EVO_DAC_MODE_CTRL                                       0x00000400
+#define NV50_EVO_DAC_MODE_CTRL_CRTC0                                 0x00000001
+#define NV50_EVO_DAC_MODE_CTRL_CRTC1                                 0x00000002
+#define NV50_EVO_DAC_MODE_CTRL2                                      0x00000404
+#define NV50_EVO_DAC_MODE_CTRL2_NHSYNC                               0x00000001
+#define NV50_EVO_DAC_MODE_CTRL2_NVSYNC                               0x00000002
+
+#define NV50_EVO_SOR(n, r)                       ((n) * 0x40 + NV50_EVO_SOR_##r)
+#define NV50_EVO_SOR_MODE_CTRL                                       0x00000600
+#define NV50_EVO_SOR_MODE_CTRL_CRTC0                                 0x00000001
+#define NV50_EVO_SOR_MODE_CTRL_CRTC1                                 0x00000002
+#define NV50_EVO_SOR_MODE_CTRL_TMDS                                  0x00000100
+#define NV50_EVO_SOR_MODE_CTRL_TMDS_DUAL_LINK                        0x00000400
+#define NV50_EVO_SOR_MODE_CTRL_NHSYNC                                0x00001000
+#define NV50_EVO_SOR_MODE_CTRL_NVSYNC                                0x00002000
+
+#define NV50_EVO_CRTC(n, r)                    ((n) * 0x400 + NV50_EVO_CRTC_##r)
+#define NV84_EVO_CRTC(n, r)                    ((n) * 0x400 + NV84_EVO_CRTC_##r)
+#define NV50_EVO_CRTC_UNK0800                                        0x00000800
+#define NV50_EVO_CRTC_CLOCK                                          0x00000804
+#define NV50_EVO_CRTC_INTERLACE                                      0x00000808
+#define NV50_EVO_CRTC_DISPLAY_START                                  0x00000810
+#define NV50_EVO_CRTC_DISPLAY_TOTAL                                  0x00000814
+#define NV50_EVO_CRTC_SYNC_DURATION                                  0x00000818
+#define NV50_EVO_CRTC_SYNC_START_TO_BLANK_END                        0x0000081c
+#define NV50_EVO_CRTC_UNK0820                                        0x00000820
+#define NV50_EVO_CRTC_UNK0824                                        0x00000824
+#define NV50_EVO_CRTC_UNK082C                                        0x0000082c
+#define NV50_EVO_CRTC_CLUT_MODE                                      0x00000840
+/* You can't have a palette in 8 bit mode (=OFF) */
+#define NV50_EVO_CRTC_CLUT_MODE_BLANK                                0x00000000
+#define NV50_EVO_CRTC_CLUT_MODE_OFF                                  0x80000000
+#define NV50_EVO_CRTC_CLUT_MODE_ON                                   0xC0000000
+#define NV50_EVO_CRTC_CLUT_OFFSET                                    0x00000844
+#define NV84_EVO_CRTC_CLUT_DMA                                       0x0000085C
+#define NV84_EVO_CRTC_CLUT_DMA_HANDLE                                0xffffffff
+#define NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE                           0x00000000
+#define NV50_EVO_CRTC_FB_OFFSET                                      0x00000860
+#define NV50_EVO_CRTC_FB_SIZE                                        0x00000868
+#define NV50_EVO_CRTC_FB_CONFIG                                      0x0000086c
+#define NV50_EVO_CRTC_FB_CONFIG_MODE                                 0x00100000
+#define NV50_EVO_CRTC_FB_CONFIG_MODE_TILE                            0x00000000
+#define NV50_EVO_CRTC_FB_CONFIG_MODE_PITCH                           0x00100000
+#define NV50_EVO_CRTC_FB_DEPTH                                       0x00000870
+#define NV50_EVO_CRTC_FB_DEPTH_8                                     0x00001e00
+#define NV50_EVO_CRTC_FB_DEPTH_15                                    0x0000e900
+#define NV50_EVO_CRTC_FB_DEPTH_16                                    0x0000e800
+#define NV50_EVO_CRTC_FB_DEPTH_24                                    0x0000cf00
+#define NV50_EVO_CRTC_FB_DEPTH_30                                    0x0000d100
+#define NV50_EVO_CRTC_FB_DMA                                         0x00000874
+#define NV50_EVO_CRTC_FB_DMA_HANDLE                                  0xffffffff
+#define NV50_EVO_CRTC_FB_DMA_HANDLE_NONE                             0x00000000
+#define NV50_EVO_CRTC_CURSOR_CTRL                                    0x00000880
+#define NV50_EVO_CRTC_CURSOR_CTRL_HIDE                               0x05000000
+#define NV50_EVO_CRTC_CURSOR_CTRL_SHOW                               0x85000000
+#define NV50_EVO_CRTC_CURSOR_OFFSET                                  0x00000884
+#define NV84_EVO_CRTC_CURSOR_DMA                                     0x0000089c
+#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE                              0xffffffff
+#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE                         0x00000000
+#define NV50_EVO_CRTC_DITHER_CTRL                                    0x000008a0
+#define NV50_EVO_CRTC_DITHER_CTRL_OFF                                0x00000000
+#define NV50_EVO_CRTC_DITHER_CTRL_ON                                 0x00000011
+#define NV50_EVO_CRTC_SCALE_CTRL                                     0x000008a4
+#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE                            0x00000000
+#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE                              0x00000009
+#define NV50_EVO_CRTC_COLOR_CTRL                                     0x000008a8
+#define NV50_EVO_CRTC_COLOR_CTRL_COLOR                               0x00040000
+#define NV50_EVO_CRTC_FB_POS                                         0x000008c0
+#define NV50_EVO_CRTC_REAL_RES                                       0x000008c8
+#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET                            0x000008d4
+#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) \
+	((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF))
+/* Both of these are needed, otherwise nothing happens. */
+#define NV50_EVO_CRTC_SCALE_RES1                                     0x000008d8
+#define NV50_EVO_CRTC_SCALE_RES2                                     0x000008dc
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_i2c.h"
+#include "nouveau_encoder.h"
+
+static int
+auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_i2c_chan *auxch;
+	int ret;
+
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
+		return -ENODEV;
+
+	ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int
+auxch_wr(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_i2c_chan *auxch;
+	int ret;
+
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
+		return -ENODEV;
+
+	ret = nouveau_dp_auxch(auxch, 8, address, buf, size);
+	return ret;
+}
+
+static int
+nouveau_dp_lane_count_set(struct drm_encoder *encoder, uint8_t cmd)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	uint32_t tmp;
+	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
+
+	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
+	tmp &= ~(NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED |
+		 NV50_SOR_DP_CTRL_LANE_MASK);
+	tmp |= ((1 << (cmd & DP_LANE_COUNT_MASK)) - 1) << 16;
+	if (cmd & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+		tmp |= NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED;
+	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+
+	return auxch_wr(encoder, DP_LANE_COUNT_SET, &cmd, 1);
+}
+
+static int
+nouveau_dp_link_bw_set(struct drm_encoder *encoder, uint8_t cmd)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	uint32_t tmp;
+	int reg = 0x614300 + (nv_encoder->or * 0x800);
+
+	tmp  = nv_rd32(dev, reg);
+	tmp &= 0xfff3ffff;
+	if (cmd == DP_LINK_BW_2_7)
+		tmp |= 0x00040000;
+	nv_wr32(dev, reg, tmp);
+
+	return auxch_wr(encoder, DP_LINK_BW_SET, &cmd, 1);
+}
+
+static int
+nouveau_dp_link_train_set(struct drm_encoder *encoder, int pattern)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	uint32_t tmp;
+	uint8_t cmd;
+	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
+	int ret;
+
+	tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link));
+	tmp &= ~NV50_SOR_DP_CTRL_TRAINING_PATTERN;
+	tmp |= (pattern << 24);
+	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp);
+
+	ret = auxch_rd(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
+	if (ret)
+		return ret;
+	cmd &= ~DP_TRAINING_PATTERN_MASK;
+	cmd |= (pattern & DP_TRAINING_PATTERN_MASK);
+	return auxch_wr(encoder, DP_TRAINING_PATTERN_SET, &cmd, 1);
+}
+
+static int
+nouveau_dp_max_voltage_swing(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct bit_displayport_encoder_table_entry *dpse;
+	struct bit_displayport_encoder_table *dpe;
+	int i, dpe_headerlen, max_vs = 0;
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe)
+		return false;
+	dpse = (void *)((char *)dpe + dpe_headerlen);
+
+	for (i = 0; i < dpe_headerlen; i++, dpse++) {
+		if (dpse->vs_level > max_vs)
+			max_vs = dpse->vs_level;
+	}
+
+	return max_vs;
+}
+
+static int
+nouveau_dp_max_pre_emphasis(struct drm_encoder *encoder, int vs)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct bit_displayport_encoder_table_entry *dpse;
+	struct bit_displayport_encoder_table *dpe;
+	int i, dpe_headerlen, max_pre = 0;
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe)
+		return false;
+	dpse = (void *)((char *)dpe + dpe_headerlen);
+
+	for (i = 0; i < dpe_headerlen; i++, dpse++) {
+		if (dpse->vs_level != vs)
+			continue;
+
+		if (dpse->pre_level > max_pre)
+			max_pre = dpse->pre_level;
+	}
+
+	return max_pre;
+}
+
+static bool
+nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct bit_displayport_encoder_table_entry *dpse;
+	struct bit_displayport_encoder_table *dpe;
+	int ret, i, dpe_headerlen, vs = 0, pre = 0;
+	uint8_t request[2];
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe)
+		return false;
+	dpse = (void *)((char *)dpe + dpe_headerlen);
+
+	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
+	if (ret)
+		return false;
+
+	NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]);
+
+	/* Keep all lanes at the same level.. */
+	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
+		int lane_req = (request[i >> 1] >> ((i & 1) << 2)) & 0xf;
+		int lane_vs = lane_req & 3;
+		int lane_pre = (lane_req >> 2) & 3;
+
+		if (lane_vs > vs)
+			vs = lane_vs;
+		if (lane_pre > pre)
+			pre = lane_pre;
+	}
+
+	if (vs >= nouveau_dp_max_voltage_swing(encoder)) {
+		vs  = nouveau_dp_max_voltage_swing(encoder);
+		vs |= 4;
+	}
+
+	if (pre >= nouveau_dp_max_pre_emphasis(encoder, vs & 3)) {
+		pre  = nouveau_dp_max_pre_emphasis(encoder, vs & 3);
+		pre |= 4;
+	}
+
+	/* Update the configuration for all lanes.. */
+	for (i = 0; i < nv_encoder->dp.link_nr; i++)
+		config[i] = (pre << 3) | vs;
+
+	return true;
+}
+
+static bool
+nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct bit_displayport_encoder_table_entry *dpse;
+	struct bit_displayport_encoder_table *dpe;
+	int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1);
+	int dpe_headerlen, ret, i;
+
+	NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n",
+		 config[0], config[1], config[2], config[3]);
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe)
+		return false;
+	dpse = (void *)((char *)dpe + dpe_headerlen);
+
+	for (i = 0; i < dpe->record_nr; i++, dpse++) {
+		if (dpse->vs_level == (config[0] & 3) &&
+		    dpse->pre_level == ((config[0] >> 3) & 3))
+			break;
+	}
+	BUG_ON(i == dpe->record_nr);
+
+	for (i = 0; i < nv_encoder->dp.link_nr; i++) {
+		const int shift[4] = { 16, 8, 0, 24 };
+		uint32_t mask = 0xff << shift[i];
+		uint32_t reg0, reg1, reg2;
+
+		reg0  = nv_rd32(dev, NV50_SOR_DP_UNK118(or, link)) & ~mask;
+		reg0 |= (dpse->reg0 << shift[i]);
+		reg1  = nv_rd32(dev, NV50_SOR_DP_UNK120(or, link)) & ~mask;
+		reg1 |= (dpse->reg1 << shift[i]);
+		reg2  = nv_rd32(dev, NV50_SOR_DP_UNK130(or, link)) & 0xffff00ff;
+		reg2 |= (dpse->reg2 << 8);
+		nv_wr32(dev, NV50_SOR_DP_UNK118(or, link), reg0);
+		nv_wr32(dev, NV50_SOR_DP_UNK120(or, link), reg1);
+		nv_wr32(dev, NV50_SOR_DP_UNK130(or, link), reg2);
+	}
+
+	ret = auxch_wr(encoder, DP_TRAINING_LANE0_SET, config, 4);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+bool
+nouveau_dp_link_train(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	uint8_t config[4];
+	uint8_t status[3];
+	bool cr_done, cr_max_vs, eq_done;
+	int ret = 0, i, tries, voltage;
+
+	NV_DEBUG_KMS(dev, "link training!!\n");
+train:
+	cr_done = eq_done = false;
+
+	/* set link configuration */
+	NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n",
+		 nv_encoder->dp.link_bw, nv_encoder->dp.link_nr);
+
+	ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw);
+	if (ret)
+		return false;
+
+	config[0] = nv_encoder->dp.link_nr;
+	if (nv_encoder->dp.dpcd_version >= 0x11)
+		config[0] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+
+	ret = nouveau_dp_lane_count_set(encoder, config[0]);
+	if (ret)
+		return false;
+
+	/* clock recovery */
+	NV_DEBUG_KMS(dev, "\tbegin cr\n");
+	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1);
+	if (ret)
+		goto stop;
+
+	tries = 0;
+	voltage = -1;
+	memset(config, 0x00, sizeof(config));
+	for (;;) {
+		if (!nouveau_dp_link_train_commit(encoder, config))
+			break;
+
+		udelay(100);
+
+		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2);
+		if (ret)
+			break;
+		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
+			 status[0], status[1]);
+
+		cr_done = true;
+		cr_max_vs = false;
+		for (i = 0; i < nv_encoder->dp.link_nr; i++) {
+			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+
+			if (!(lane & DP_LANE_CR_DONE)) {
+				cr_done = false;
+				if (config[i] & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED)
+					cr_max_vs = true;
+				break;
+			}
+		}
+
+		if ((config[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
+			voltage = config[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+			tries = 0;
+		}
+
+		if (cr_done || cr_max_vs || (++tries == 5))
+			break;
+
+		if (!nouveau_dp_link_train_adjust(encoder, config))
+			break;
+	}
+
+	if (!cr_done)
+		goto stop;
+
+	/* channel equalisation */
+	NV_DEBUG_KMS(dev, "\tbegin eq\n");
+	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2);
+	if (ret)
+		goto stop;
+
+	for (tries = 0; tries <= 5; tries++) {
+		udelay(400);
+
+		ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3);
+		if (ret)
+			break;
+		NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n",
+			 status[0], status[1]);
+
+		eq_done = true;
+		if (!(status[2] & DP_INTERLANE_ALIGN_DONE))
+			eq_done = false;
+
+		for (i = 0; eq_done && i < nv_encoder->dp.link_nr; i++) {
+			int lane = (status[i >> 1] >> ((i & 1) * 4)) & 0xf;
+
+			if (!(lane & DP_LANE_CR_DONE)) {
+				cr_done = false;
+				break;
+			}
+
+			if (!(lane & DP_LANE_CHANNEL_EQ_DONE) ||
+			    !(lane & DP_LANE_SYMBOL_LOCKED)) {
+				eq_done = false;
+				break;
+			}
+		}
+
+		if (eq_done || !cr_done)
+			break;
+
+		if (!nouveau_dp_link_train_adjust(encoder, config) ||
+		    !nouveau_dp_link_train_commit(encoder, config))
+			break;
+	}
+
+stop:
+	/* end link training */
+	ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_DISABLE);
+	if (ret)
+		return false;
+
+	/* retry at a lower setting, if possible */
+	if (!ret && !(eq_done && cr_done)) {
+		NV_DEBUG_KMS(dev, "\twe failed\n");
+		if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) {
+			NV_DEBUG_KMS(dev, "retry link training at low rate\n");
+			nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+			goto train;
+		}
+	}
+
+	return eq_done;
+}
+
+bool
+nouveau_dp_detect(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	uint8_t dpcd[4];
+	int ret;
+
+	ret = auxch_rd(encoder, 0x0000, dpcd, 4);
+	if (ret)
+		return false;
+
+	NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n"
+		      "display: link_bw %d, link_nr %d version 0x%02x\n",
+		 nv_encoder->dcb->dpconf.link_bw,
+		 nv_encoder->dcb->dpconf.link_nr,
+		 dpcd[1], dpcd[2] & 0x0f, dpcd[0]);
+
+	nv_encoder->dp.dpcd_version = dpcd[0];
+
+	nv_encoder->dp.link_bw = dpcd[1];
+	if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62 &&
+	    !nv_encoder->dcb->dpconf.link_bw)
+		nv_encoder->dp.link_bw = DP_LINK_BW_1_62;
+
+	nv_encoder->dp.link_nr = dpcd[2] & 0xf;
+	if (nv_encoder->dp.link_nr > nv_encoder->dcb->dpconf.link_nr)
+		nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr;
+
+	return true;
+}
+
+int
+nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
+		 uint8_t *data, int data_nr)
+{
+	struct drm_device *dev = auxch->dev;
+	uint32_t tmp, ctrl, stat = 0, data32[4] = {};
+	int ret = 0, i, index = auxch->rd;
+
+	NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr);
+
+	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
+	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000);
+	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
+	if (!(tmp & 0x01000000)) {
+		NV_ERROR(dev, "expected bit 24 == 1, got 0x%08x\n", tmp);
+		ret = -EIO;
+		goto out;
+	}
+
+	for (i = 0; i < 3; i++) {
+		tmp = nv_rd32(dev, NV50_AUXCH_STAT(auxch->rd));
+		if (tmp & NV50_AUXCH_STAT_STATE_READY)
+			break;
+		udelay(100);
+	}
+
+	if (i == 3) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!(cmd & 1)) {
+		memcpy(data32, data, data_nr);
+		for (i = 0; i < 4; i++) {
+			NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]);
+			nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]);
+		}
+	}
+
+	nv_wr32(dev, NV50_AUXCH_ADDR(index), addr);
+	ctrl  = nv_rd32(dev, NV50_AUXCH_CTRL(index));
+	ctrl &= ~(NV50_AUXCH_CTRL_CMD | NV50_AUXCH_CTRL_LEN);
+	ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT);
+	ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT);
+
+	for (;;) {
+		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);
+		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);
+		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000);
+		if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) {
+			NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
+				 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
+			ret = -EBUSY;
+			goto out;
+		}
+
+		udelay(400);
+
+		stat = nv_rd32(dev, NV50_AUXCH_STAT(index));
+		if ((stat & NV50_AUXCH_STAT_REPLY_AUX) !=
+			    NV50_AUXCH_STAT_REPLY_AUX_DEFER)
+			break;
+	}
+
+	if (cmd & 1) {
+		if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
+			ret = -EREMOTEIO;
+			goto out;
+		}
+
+		for (i = 0; i < 4; i++) {
+			data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
+			NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
+		}
+		memcpy(data, data32, data_nr);
+	}
+
+out:
+	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
+	nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp & ~0x00100000);
+	tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd));
+	if (tmp & 0x01000000) {
+		NV_ERROR(dev, "expected bit 24 == 0, got 0x%08x\n", tmp);
+		ret = -EIO;
+	}
+
+	udelay(400);
+
+	return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY);
+}
+
+int
+nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
+		      uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter;
+	struct drm_device *dev = auxch->dev;
+	int ret = 0, cmd, addr = algo_data->address;
+	uint8_t *buf;
+
+	if (mode == MODE_I2C_READ) {
+		cmd = AUX_I2C_READ;
+		buf = read_byte;
+	} else {
+		cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE;
+		buf = &write_byte;
+	}
+
+	if (!(mode & MODE_I2C_STOP))
+		cmd |= AUX_I2C_MOT;
+
+	if (mode & MODE_I2C_START)
+		return 1;
+
+	for (;;) {
+		ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1);
+		if (ret < 0)
+			return ret;
+
+		switch (ret & NV50_AUXCH_STAT_REPLY_I2C) {
+		case NV50_AUXCH_STAT_REPLY_I2C_ACK:
+			return 1;
+		case NV50_AUXCH_STAT_REPLY_I2C_NACK:
+			return -EREMOTEIO;
+		case NV50_AUXCH_STAT_REPLY_I2C_DEFER:
+			udelay(100);
+			break;
+		default:
+			NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret);
+			return -EREMOTEIO;
+		}
+	}
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_notifier.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ *
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+int
+nouveau_notifier_init_channel(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct nouveau_bo *ntfy = NULL;
+	uint32_t flags;
+	int ret;
+
+	if (nouveau_vram_notify)
+		flags = TTM_PL_FLAG_VRAM;
+	else
+		flags = TTM_PL_FLAG_TT;
+
+	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags,
+			      0, 0x0000, false, true, &ntfy);
+	if (ret)
+		return ret;
+
+	ret = nouveau_bo_pin(ntfy, flags);
+	if (ret)
+		goto out_err;
+
+	ret = nouveau_bo_map(ntfy);
+	if (ret)
+		goto out_err;
+
+	ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size);
+	if (ret)
+		goto out_err;
+
+	chan->notifier_bo = ntfy;
+out_err:
+	if (ret) {
+		mutex_lock(&dev->struct_mutex);
+		drm_gem_object_unreference(ntfy->gem);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	return ret;
+}
+
+void
+nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+
+	if (!chan->notifier_bo)
+		return;
+
+	nouveau_bo_unmap(chan->notifier_bo);
+	mutex_lock(&dev->struct_mutex);
+	nouveau_bo_unpin(chan->notifier_bo);
+	drm_gem_object_unreference(chan->notifier_bo->gem);
+	mutex_unlock(&dev->struct_mutex);
+	nouveau_mem_takedown(&chan->notifier_heap);
+}
+
+static void
+nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
+			     struct nouveau_gpuobj *gpuobj)
+{
+	NV_DEBUG(dev, "\n");
+
+	if (gpuobj->priv)
+		nouveau_mem_free_block(gpuobj->priv);
+}
+
+int
+nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
+		       int size, uint32_t *b_offset)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *nobj = NULL;
+	struct mem_block *mem;
+	uint32_t offset;
+	int target, ret;
+
+	if (!chan->notifier_heap) {
+		NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n",
+			 chan->id);
+		return -EINVAL;
+	}
+
+	mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0,
+				      (struct drm_file *)-2, 0);
+	if (!mem) {
+		NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
+		return -ENOMEM;
+	}
+
+	offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT;
+	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) {
+		target = NV_DMA_TARGET_VIDMEM;
+	} else
+	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) {
+		if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA &&
+		    dev_priv->card_type < NV_50) {
+			ret = nouveau_sgdma_get_page(dev, offset, &offset);
+			if (ret)
+				return ret;
+			target = NV_DMA_TARGET_PCI;
+		} else {
+			target = NV_DMA_TARGET_AGP;
+			if (dev_priv->card_type >= NV_50)
+				offset += dev_priv->vm_gart_base;
+		}
+	} else {
+		NV_ERROR(dev, "Bad DMA target, mem_type %d!\n",
+			 chan->notifier_bo->bo.mem.mem_type);
+		return -EINVAL;
+	}
+	offset += mem->start;
+
+	ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset,
+				     mem->size, NV_DMA_ACCESS_RW, target,
+				     &nobj);
+	if (ret) {
+		nouveau_mem_free_block(mem);
+		NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
+		return ret;
+	}
+	nobj->dtor   = nouveau_notifier_gpuobj_dtor;
+	nobj->priv   = mem;
+
+	ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL);
+	if (ret) {
+		nouveau_gpuobj_del(dev, &nobj);
+		nouveau_mem_free_block(mem);
+		NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret);
+		return ret;
+	}
+
+	*b_offset = mem->start;
+	return 0;
+}
+
+int
+nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
+{
+	if (!nobj || nobj->dtor != nouveau_notifier_gpuobj_dtor)
+		return -EINVAL;
+
+	if (poffset) {
+		struct mem_block *mem = nobj->priv;
+
+		if (*poffset >= mem->size)
+			return false;
+
+		*poffset += mem->start;
+	}
+
+	return 0;
+}
+
+int
+nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct drm_nouveau_notifierobj_alloc *na = data;
+	struct nouveau_channel *chan;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
+
+	ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);
+	if (ret)
+		return ret;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv40_fifo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV40_RAMFC__SIZE))
+#define NV40_RAMFC__SIZE 128
+
+int
+nv40_fifo_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t fc = NV40_RAMFC(chan->id);
+	int ret;
+
+	ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
+				      NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC |
+				      NVOBJ_FLAG_ZERO_FREE, NULL, &chan->ramfc);
+	if (ret)
+		return ret;
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wi32(dev, fc +  0, chan->pushbuf_base);
+	nv_wi32(dev, fc +  4, chan->pushbuf_base);
+	nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
+	nv_wi32(dev, fc + 24, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+			      NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+			      NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+			      NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+			      0x30000000 /* no idea.. */);
+	nv_wi32(dev, fc + 56, chan->ramin_grctx->instance >> 4);
+	nv_wi32(dev, fc + 60, 0x0001FFFF);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	/* enable the fifo dma operation */
+	nv_wr32(dev, NV04_PFIFO_MODE,
+		nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
+	return 0;
+}
+
+void
+nv40_fifo_destroy_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+
+	nv_wr32(dev, NV04_PFIFO_MODE,
+		nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id));
+
+	if (chan->ramfc)
+		nouveau_gpuobj_ref_del(dev, &chan->ramfc);
+}
+
+static void
+nv40_fifo_do_load_context(struct drm_device *dev, int chid)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t fc = NV40_RAMFC(chid), tmp, tmp2;
+
+	dev_priv->engine.instmem.prepare_access(dev, false);
+
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE, nv_ri32(dev, fc + 12));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT, nv_ri32(dev, fc + 16));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, nv_ri32(dev, fc + 20));
+
+	/* No idea what 0x2058 is.. */
+	tmp   = nv_ri32(dev, fc + 24);
+	tmp2  = nv_rd32(dev, 0x2058) & 0xFFF;
+	tmp2 |= (tmp & 0x30000000);
+	nv_wr32(dev, 0x2058, tmp2);
+	tmp  &= ~0x30000000;
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_FETCH, tmp);
+
+	nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 28));
+	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 32));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE, nv_ri32(dev, fc + 36));
+	tmp = nv_ri32(dev, fc + 40);
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, tmp);
+	nv_wr32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT, nv_ri32(dev, fc + 44));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, nv_ri32(dev, fc + 48));
+	nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 52));
+	nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, nv_ri32(dev, fc + 56));
+
+	/* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */
+	tmp  = nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF;
+	tmp |= nv_ri32(dev, fc + 60) & 0x1FFFF;
+	nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, tmp);
+
+	nv_wr32(dev, 0x32e4, nv_ri32(dev, fc + 64));
+	/* NVIDIA does this next line twice... */
+	nv_wr32(dev, 0x32e8, nv_ri32(dev, fc + 68));
+	nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76));
+	nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80));
+
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
+}
+
+int
+nv40_fifo_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	uint32_t tmp;
+
+	nv40_fifo_do_load_context(dev, chan->id);
+
+	/* Set channel active, and in DMA mode */
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
+		     NV40_PFIFO_CACHE1_PUSH1_DMA | chan->id);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 1);
+
+	/* Reset DMA_CTL_AT_INFO to INVALID */
+	tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_CTL) & ~(1 << 31);
+	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+	return 0;
+}
+
+int
+nv40_fifo_unload_context(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	uint32_t fc, tmp;
+	int chid;
+
+	chid = pfifo->channel_id(dev);
+	if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
+		return 0;
+	fc = NV40_RAMFC(chid);
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
+	nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
+	nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
+	nv_wi32(dev, fc + 12, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_INSTANCE));
+	nv_wi32(dev, fc + 16, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT));
+	nv_wi32(dev, fc + 20, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_STATE));
+	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH);
+	tmp |= nv_rd32(dev, 0x2058) & 0x30000000;
+	nv_wi32(dev, fc + 24, tmp);
+	nv_wi32(dev, fc + 28, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
+	nv_wi32(dev, fc + 32, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
+	nv_wi32(dev, fc + 36, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+	tmp = nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
+	nv_wi32(dev, fc + 40, tmp);
+	nv_wi32(dev, fc + 44, nv_rd32(dev, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+	nv_wi32(dev, fc + 48, nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE));
+	/* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something
+	 * more involved depending on the value of 0x3228?
+	 */
+	nv_wi32(dev, fc + 52, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
+	nv_wi32(dev, fc + 56, nv_rd32(dev, NV40_PFIFO_GRCTX_INSTANCE));
+	nv_wi32(dev, fc + 60, nv_rd32(dev, NV04_PFIFO_DMA_TIMESLICE) & 0x1ffff);
+	/* No idea what the below is for exactly, ripped from a mmio-trace */
+	nv_wi32(dev, fc + 64, nv_rd32(dev, NV40_PFIFO_UNK32E4));
+	/* NVIDIA do this next line twice.. bug? */
+	nv_wi32(dev, fc + 68, nv_rd32(dev, 0x32e8));
+	nv_wi32(dev, fc + 76, nv_rd32(dev, 0x2088));
+	nv_wi32(dev, fc + 80, nv_rd32(dev, 0x3300));
+#if 0 /* no real idea which is PUT/GET in UNK_48.. */
+	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_GET);
+	tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16);
+	nv_wi32(dev, fc + 72, tmp);
+#endif
+	dev_priv->engine.instmem.finish_access(dev);
+
+	nv40_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1,
+		     NV40_PFIFO_CACHE1_PUSH1_DMA | (pfifo->channels - 1));
+	return 0;
+}
+
+static void
+nv40_fifo_init_reset(struct drm_device *dev)
+{
+	int i;
+
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PFIFO);
+	nv_wr32(dev, NV03_PMC_ENABLE,
+		nv_rd32(dev, NV03_PMC_ENABLE) |  NV_PMC_ENABLE_PFIFO);
+
+	nv_wr32(dev, 0x003224, 0x000f0078);
+	nv_wr32(dev, 0x003210, 0x00000000);
+	nv_wr32(dev, 0x003270, 0x00000000);
+	nv_wr32(dev, 0x003240, 0x00000000);
+	nv_wr32(dev, 0x003244, 0x00000000);
+	nv_wr32(dev, 0x003258, 0x00000000);
+	nv_wr32(dev, 0x002504, 0x00000000);
+	for (i = 0; i < 16; i++)
+		nv_wr32(dev, 0x002510 + (i * 4), 0x00000000);
+	nv_wr32(dev, 0x00250c, 0x0000ffff);
+	nv_wr32(dev, 0x002048, 0x00000000);
+	nv_wr32(dev, 0x003228, 0x00000000);
+	nv_wr32(dev, 0x0032e8, 0x00000000);
+	nv_wr32(dev, 0x002410, 0x00000000);
+	nv_wr32(dev, 0x002420, 0x00000000);
+	nv_wr32(dev, 0x002058, 0x00000001);
+	nv_wr32(dev, 0x00221c, 0x00000000);
+	/* something with 0x2084, read/modify/write, no change */
+	nv_wr32(dev, 0x002040, 0x000000ff);
+	nv_wr32(dev, 0x002500, 0x00000000);
+	nv_wr32(dev, 0x003200, 0x00000000);
+
+	nv_wr32(dev, NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff);
+}
+
+static void
+nv40_fifo_init_ramxx(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nv_wr32(dev, NV03_PFIFO_RAMHT, (0x03 << 24) /* search 128 */ |
+				       ((dev_priv->ramht_bits - 9) << 16) |
+				       (dev_priv->ramht_offset >> 8));
+	nv_wr32(dev, NV03_PFIFO_RAMRO, dev_priv->ramro_offset>>8);
+
+	switch (dev_priv->chipset) {
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		nv_wr32(dev, 0x2230, 1);
+		break;
+	default:
+		break;
+	}
+
+	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x41:
+	case 0x42:
+	case 0x43:
+	case 0x45:
+	case 0x47:
+	case 0x48:
+	case 0x49:
+	case 0x4b:
+		nv_wr32(dev, NV40_PFIFO_RAMFC, 0x30002);
+		break;
+	default:
+		nv_wr32(dev, 0x2230, 0);
+		nv_wr32(dev, NV40_PFIFO_RAMFC,
+			((nouveau_mem_fb_amount(dev) - 512 * 1024 +
+			  dev_priv->ramfc_offset) >> 16) | (3 << 16));
+		break;
+	}
+}
+
+static void
+nv40_fifo_init_intr(struct drm_device *dev)
+{
+	nv_wr32(dev, 0x002100, 0xffffffff);
+	nv_wr32(dev, 0x002140, 0xffffffff);
+}
+
+int
+nv40_fifo_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	int i;
+
+	nv40_fifo_init_reset(dev);
+	nv40_fifo_init_ramxx(dev);
+
+	nv40_fifo_do_load_context(dev, pfifo->channels - 1);
+	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
+
+	nv40_fifo_init_intr(dev);
+	pfifo->enable(dev);
+	pfifo->reassign(dev, true);
+
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		if (dev_priv->fifos[i]) {
+			uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
+			nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
+		}
+	}
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_sor.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_crtc_helper.h"
+
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nv50_display.h"
+
+static void
+nv50_sor_disconnect(struct nouveau_encoder *nv_encoder)
+{
+	struct drm_device *dev = to_drm_encoder(nv_encoder)->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or);
+
+	ret = RING_SPACE(evo, 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while disconnecting SOR\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
+	OUT_RING(evo, 0);
+}
+
+static void
+nv50_sor_dp_link_train(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct bit_displayport_encoder_table *dpe;
+	int dpe_headerlen;
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe) {
+		NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
+		return;
+	}
+
+	if (dpe->script0) {
+		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
+		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
+					    nv_encoder->dcb);
+	}
+
+	if (!nouveau_dp_link_train(encoder))
+		NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or);
+
+	if (dpe->script1) {
+		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
+		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
+					    nv_encoder->dcb);
+	}
+}
+
+static void
+nv50_sor_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_encoder *enc;
+	uint32_t val;
+	int or = nv_encoder->or;
+
+	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
+
+	nv_encoder->last_dpms = mode;
+	list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nvenc = nouveau_encoder(enc);
+
+		if (nvenc == nv_encoder ||
+		    nvenc->disconnect != nv50_sor_disconnect ||
+		    nvenc->dcb->or != nv_encoder->dcb->or)
+			continue;
+
+		if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
+			return;
+	}
+
+	/* wait for it to be done */
+	if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
+		     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
+		NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or);
+		NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or,
+			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)));
+	}
+
+	val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or));
+
+	if (mode == DRM_MODE_DPMS_ON)
+		val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON;
+	else
+		val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON;
+
+	nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val |
+		NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING);
+	if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or),
+		     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) {
+		NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or);
+		NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or,
+			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or)));
+	}
+
+	if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON)
+		nv50_sor_dp_link_train(encoder);
+}
+
+static void
+nv50_sor_save(struct drm_encoder *encoder)
+{
+	NV_ERROR(encoder->dev, "!!\n");
+}
+
+static void
+nv50_sor_restore(struct drm_encoder *encoder)
+{
+	NV_ERROR(encoder->dev, "!!\n");
+}
+
+static bool
+nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nouveau_connector *connector;
+
+	NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);
+
+	connector = nouveau_encoder_connector_get(nv_encoder);
+	if (!connector) {
+		NV_ERROR(encoder->dev, "Encoder has no connector\n");
+		return false;
+	}
+
+	if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
+	     connector->native_mode) {
+		int id = adjusted_mode->base.id;
+		*adjusted_mode = *connector->native_mode;
+		adjusted_mode->base.id = id;
+	}
+
+	return true;
+}
+
+static void
+nv50_sor_prepare(struct drm_encoder *encoder)
+{
+}
+
+static void
+nv50_sor_commit(struct drm_encoder *encoder)
+{
+}
+
+static void
+nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
+	uint32_t mode_ctl = 0;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or);
+
+	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
+
+	switch (nv_encoder->dcb->type) {
+	case OUTPUT_TMDS:
+		if (nv_encoder->dcb->sorconf.link & 1) {
+			if (adjusted_mode->clock < 165000)
+				mode_ctl = 0x0100;
+			else
+				mode_ctl = 0x0500;
+		} else
+			mode_ctl = 0x0200;
+		break;
+	case OUTPUT_DP:
+		mode_ctl |= 0x00050000;
+		if (nv_encoder->dcb->sorconf.link & 1)
+			mode_ctl |= 0x00000800;
+		else
+			mode_ctl |= 0x00000900;
+		break;
+	default:
+		break;
+	}
+
+	if (crtc->index == 1)
+		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1;
+	else
+		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
+
+	ret = RING_SPACE(evo, 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while connecting SOR\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
+	OUT_RING(evo, mode_ctl);
+}
+
+static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = {
+	.dpms = nv50_sor_dpms,
+	.save = nv50_sor_save,
+	.restore = nv50_sor_restore,
+	.mode_fixup = nv50_sor_mode_fixup,
+	.prepare = nv50_sor_prepare,
+	.commit = nv50_sor_commit,
+	.mode_set = nv50_sor_mode_set,
+	.detect = NULL
+};
+
+static void
+nv50_sor_destroy(struct drm_encoder *encoder)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+	if (!encoder)
+		return;
+
+	NV_DEBUG_KMS(encoder->dev, "\n");
+
+	drm_encoder_cleanup(encoder);
+
+	kfree(nv_encoder);
+}
+
+static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
+	.destroy = nv50_sor_destroy,
+};
+
+int
+nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	struct nouveau_encoder *nv_encoder = NULL;
+	struct drm_encoder *encoder;
+	bool dum;
+	int type;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	switch (entry->type) {
+	case OUTPUT_TMDS:
+		NV_INFO(dev, "Detected a TMDS output\n");
+		type = DRM_MODE_ENCODER_TMDS;
+		break;
+	case OUTPUT_LVDS:
+		NV_INFO(dev, "Detected a LVDS output\n");
+		type = DRM_MODE_ENCODER_LVDS;
+
+		if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) {
+			NV_ERROR(dev, "Failed parsing LVDS table\n");
+			return -EINVAL;
+		}
+		break;
+	case OUTPUT_DP:
+		NV_INFO(dev, "Detected a DP output\n");
+		type = DRM_MODE_ENCODER_TMDS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
+	if (!nv_encoder)
+		return -ENOMEM;
+	encoder = to_drm_encoder(nv_encoder);
+
+	nv_encoder->dcb = entry;
+	nv_encoder->or = ffs(entry->or) - 1;
+
+	nv_encoder->disconnect = nv50_sor_disconnect;
+
+	drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
+	drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_display.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_display.c
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "nv50_display.h"
+#include "nouveau_crtc.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_fb.h"
+#include "drm_crtc_helper.h"
+
+static void
+nv50_evo_channel_del(struct nouveau_channel **pchan)
+{
+	struct nouveau_channel *chan = *pchan;
+
+	if (!chan)
+		return;
+	*pchan = NULL;
+
+	nouveau_gpuobj_channel_takedown(chan);
+	nouveau_bo_ref(NULL, &chan->pushbuf_bo);
+
+	if (chan->user)
+		iounmap(chan->user);
+
+	kfree(chan);
+}
+
+static int
+nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name,
+		    uint32_t tile_flags, uint32_t magic_flags,
+		    uint32_t offset, uint32_t limit)
+{
+	struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
+	struct drm_device *dev = evo->dev;
+	struct nouveau_gpuobj *obj = NULL;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj);
+	if (ret)
+		return ret;
+	obj->engine = NVOBJ_ENGINE_DISPLAY;
+
+	ret = nouveau_gpuobj_ref_add(dev, evo, name, obj, NULL);
+	if (ret) {
+		nouveau_gpuobj_del(dev, &obj);
+		return ret;
+	}
+
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class);
+	nv_wo32(dev, obj, 1, limit);
+	nv_wo32(dev, obj, 2, offset);
+	nv_wo32(dev, obj, 3, 0x00000000);
+	nv_wo32(dev, obj, 4, 0x00000000);
+	nv_wo32(dev, obj, 5, 0x00010000);
+	dev_priv->engine.instmem.finish_access(dev);
+
+	return 0;
+}
+
+static int
+nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	int ret;
+
+	chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	*pchan = chan;
+
+	chan->id = -1;
+	chan->dev = dev;
+	chan->user_get = 4;
+	chan->user_put = 0;
+
+	INIT_LIST_HEAD(&chan->ramht_refs);
+
+	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 32768, 0x1000,
+				     NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin);
+	if (ret) {
+		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	ret = nouveau_mem_init_heap(&chan->ramin_heap, chan->ramin->gpuobj->
+				    im_pramin->start, 32768);
+	if (ret) {
+		NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 4096, 16,
+				     0, &chan->ramht);
+	if (ret) {
+		NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	if (dev_priv->chipset != 0x50) {
+		ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19,
+					  0, 0xffffffff);
+		if (ret) {
+			nv50_evo_channel_del(pchan);
+			return ret;
+		}
+
+
+		ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19,
+					  0, 0xffffffff);
+		if (ret) {
+			nv50_evo_channel_del(pchan);
+			return ret;
+		}
+	}
+
+	ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19,
+				  0, nouveau_mem_fb_amount(dev));
+	if (ret) {
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
+			     false, true, &chan->pushbuf_bo);
+	if (ret == 0)
+		ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret);
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	ret = nouveau_bo_map(chan->pushbuf_bo);
+	if (ret) {
+		NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret);
+		nv50_evo_channel_del(pchan);
+		return ret;
+	}
+
+	chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
+					NV50_PDISPLAY_USER(0), PAGE_SIZE);
+	if (!chan->user) {
+		NV_ERROR(dev, "Error mapping EVO control regs.\n");
+		nv50_evo_channel_del(pchan);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+int
+nv50_display_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct drm_connector *connector;
+	uint32_t val, ram_amount, hpd_en[2];
+	uint64_t start;
+	int ret, i;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004));
+	/*
+	 * I think the 0x006101XX range is some kind of main control area
+	 * that enables things.
+	 */
+	/* CRTC? */
+	for (i = 0; i < 2; i++) {
+		val = nv_rd32(dev, 0x00616100 + (i * 0x800));
+		nv_wr32(dev, 0x00610190 + (i * 0x10), val);
+		val = nv_rd32(dev, 0x00616104 + (i * 0x800));
+		nv_wr32(dev, 0x00610194 + (i * 0x10), val);
+		val = nv_rd32(dev, 0x00616108 + (i * 0x800));
+		nv_wr32(dev, 0x00610198 + (i * 0x10), val);
+		val = nv_rd32(dev, 0x0061610c + (i * 0x800));
+		nv_wr32(dev, 0x0061019c + (i * 0x10), val);
+	}
+	/* DAC */
+	for (i = 0; i < 3; i++) {
+		val = nv_rd32(dev, 0x0061a000 + (i * 0x800));
+		nv_wr32(dev, 0x006101d0 + (i * 0x04), val);
+	}
+	/* SOR */
+	for (i = 0; i < 4; i++) {
+		val = nv_rd32(dev, 0x0061c000 + (i * 0x800));
+		nv_wr32(dev, 0x006101e0 + (i * 0x04), val);
+	}
+	/* Something not yet in use, tv-out maybe. */
+	for (i = 0; i < 3; i++) {
+		val = nv_rd32(dev, 0x0061e000 + (i * 0x800));
+		nv_wr32(dev, 0x006101f0 + (i * 0x04), val);
+	}
+
+	for (i = 0; i < 3; i++) {
+		nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 |
+			NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
+		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001);
+	}
+
+	/* This used to be in crtc unblank, but seems out of place there. */
+	nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0);
+	/* RAM is clamped to 256 MiB. */
+	ram_amount = nouveau_mem_fb_amount(dev);
+	NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount);
+	if (ram_amount > 256*1024*1024)
+		ram_amount = 256*1024*1024;
+	nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1);
+	nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000);
+	nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0);
+
+	/* The precise purpose is unknown, i suspect it has something to do
+	 * with text mode.
+	 */
+	if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) {
+		nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100);
+		nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1);
+		if (!nv_wait(0x006194e8, 2, 0)) {
+			NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n");
+			NV_ERROR(dev, "0x6194e8 = 0x%08x\n",
+						nv_rd32(dev, 0x6194e8));
+			return -EBUSY;
+		}
+	}
+
+	/* taken from nv bug #12637, attempts to un-wedge the hw if it's
+	 * stuck in some unspecified state
+	 */
+	start = ptimer->read(dev);
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00);
+	while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) {
+		if ((val & 0x9f0000) == 0x20000)
+			nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
+							val | 0x800000);
+
+		if ((val & 0x3f0000) == 0x30000)
+			nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
+							val | 0x200000);
+
+		if (ptimer->read(dev) - start > 1000000000ULL) {
+			NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n");
+			NV_ERROR(dev, "0x610200 = 0x%08x\n", val);
+			return -EBUSY;
+		}
+	}
+
+	nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE);
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03);
+	if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x40000000, 0x40000000)) {
+		NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n");
+		NV_ERROR(dev, "0x610200 = 0x%08x\n",
+			  nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)));
+		return -EBUSY;
+	}
+
+	for (i = 0; i < 2; i++) {
+		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000);
+		if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
+			NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
+			NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
+				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)));
+			return -EBUSY;
+		}
+
+		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+			NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON);
+		if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i),
+			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS,
+			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) {
+			NV_ERROR(dev, "timeout: "
+				      "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i);
+			NV_ERROR(dev, "CURSOR_CTRL2(%d) = 0x%08x\n", i,
+				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i)));
+			return -EBUSY;
+		}
+	}
+
+	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->instance >> 8) | 9);
+
+	/* initialise fifo */
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0),
+		((evo->pushbuf_bo->bo.mem.mm_node->start << PAGE_SHIFT) >> 8) |
+		NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM |
+		NV50_PDISPLAY_CHANNEL_DMA_CB_VALID);
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000);
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002);
+	if (!nv_wait(0x610200, 0x80000000, 0x00000000)) {
+		NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n");
+		NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200));
+		return -EBUSY;
+	}
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0),
+		(nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) |
+		 NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED);
+	nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0);
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 |
+		NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED);
+	nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1);
+
+	evo->dma.max = (4096/4) - 2;
+	evo->dma.put = 0;
+	evo->dma.cur = evo->dma.put;
+	evo->dma.free = evo->dma.max - evo->dma.cur;
+
+	ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
+		OUT_RING(evo, 0);
+
+	ret = RING_SPACE(evo, 11);
+	if (ret)
+		return ret;
+	BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2);
+	OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED);
+	OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1);
+	OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1);
+	OUT_RING(evo, 0);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, DISPLAY_START), 1);
+	OUT_RING(evo, 0);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1);
+	OUT_RING(evo, 0);
+	FIRE_RING(evo);
+	if (!nv_wait(0x640004, 0xffffffff, evo->dma.put << 2))
+		NV_ERROR(dev, "evo pushbuf stalled\n");
+
+	/* enable clock change interrupts. */
+	nv_wr32(dev, 0x610028, 0x00010001);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 |
+					     NV50_PDISPLAY_INTR_EN_CLK_UNK20 |
+					     NV50_PDISPLAY_INTR_EN_CLK_UNK40));
+
+	/* enable hotplug interrupts */
+	hpd_en[0] = hpd_en[1] = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct nouveau_connector *conn = nouveau_connector(connector);
+		struct dcb_gpio_entry *gpio;
+
+		if (connector->connector_type != DRM_MODE_CONNECTOR_DVII &&
+		    connector->connector_type != DRM_MODE_CONNECTOR_DVID &&
+		    connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+			continue;
+
+		gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag);
+		if (!gpio)
+			continue;
+
+		hpd_en[gpio->line >> 4] |= (0x00010001 << (gpio->line & 0xf));
+	}
+
+	nv_wr32(dev, 0xe054, 0xffffffff);
+	nv_wr32(dev, 0xe050, hpd_en[0]);
+	if (dev_priv->chipset >= 0x90) {
+		nv_wr32(dev, 0xe074, 0xffffffff);
+		nv_wr32(dev, 0xe070, hpd_en[1]);
+	}
+
+	return 0;
+}
+
+static int nv50_display_disable(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_crtc *drm_crtc;
+	int ret, i;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc);
+
+		nv50_crtc_blank(crtc, true);
+	}
+
+	ret = RING_SPACE(dev_priv->evo, 2);
+	if (ret == 0) {
+		BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(dev_priv->evo, 0);
+	}
+	FIRE_RING(dev_priv->evo);
+
+	/* Almost like ack'ing a vblank interrupt, maybe in the spirit of
+	 * cleaning up?
+	 */
+	list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc);
+		uint32_t mask = NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(crtc->index);
+
+		if (!crtc->base.enabled)
+			continue;
+
+		nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask);
+		if (!nv_wait(NV50_PDISPLAY_INTR_1, mask, mask)) {
+			NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == "
+				      "0x%08x\n", mask, mask);
+			NV_ERROR(dev, "0x610024 = 0x%08x\n",
+				 nv_rd32(dev, NV50_PDISPLAY_INTR_1));
+		}
+	}
+
+	nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0);
+	nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0);
+	if (!nv_wait(NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) {
+		NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n");
+		NV_ERROR(dev, "0x610200 = 0x%08x\n",
+			  nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)));
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(i),
+			     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) {
+			NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i);
+			NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i,
+				  nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i)));
+		}
+	}
+
+	/* disable interrupts. */
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000);
+
+	/* disable hotplug interrupts */
+	nv_wr32(dev, 0xe054, 0xffffffff);
+	nv_wr32(dev, 0xe050, 0x00000000);
+	if (dev_priv->chipset >= 0x90) {
+		nv_wr32(dev, 0xe074, 0xffffffff);
+		nv_wr32(dev, 0xe070, 0x00000000);
+	}
+	return 0;
+}
+
+int nv50_display_create(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
+	uint32_t connector[16] = {};
+	int ret, i;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	/* init basic kernel modesetting */
+	drm_mode_config_init(dev);
+
+	/* Initialise some optional connector properties. */
+	drm_mode_create_scaling_mode_property(dev);
+	drm_mode_create_dithering_property(dev);
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
+
+	dev->mode_config.max_width = 8192;
+	dev->mode_config.max_height = 8192;
+
+	dev->mode_config.fb_base = dev_priv->fb_phys;
+
+	/* Create EVO channel */
+	ret = nv50_evo_channel_new(dev, &dev_priv->evo);
+	if (ret) {
+		NV_ERROR(dev, "Error creating EVO channel: %d\n", ret);
+		return ret;
+	}
+
+	/* Create CRTC objects */
+	for (i = 0; i < 2; i++)
+		nv50_crtc_create(dev, i);
+
+	/* We setup the encoders from the BIOS table */
+	for (i = 0 ; i < dcb->entries; i++) {
+		struct dcb_entry *entry = &dcb->entry[i];
+
+		if (entry->location != DCB_LOC_ON_CHIP) {
+			NV_WARN(dev, "Off-chip encoder %d/%d unsupported\n",
+				entry->type, ffs(entry->or) - 1);
+			continue;
+		}
+
+		switch (entry->type) {
+		case OUTPUT_TMDS:
+		case OUTPUT_LVDS:
+		case OUTPUT_DP:
+			nv50_sor_create(dev, entry);
+			break;
+		case OUTPUT_ANALOG:
+			nv50_dac_create(dev, entry);
+			break;
+		default:
+			NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
+			continue;
+		}
+
+		connector[entry->connector] |= (1 << entry->type);
+	}
+
+	/* It appears that DCB 3.0+ VBIOS has a connector table, however,
+	 * I'm not 100% certain how to decode it correctly yet so just
+	 * look at what encoders are present on each connector index and
+	 * attempt to derive the connector type from that.
+	 */
+	for (i = 0 ; i < dcb->entries; i++) {
+		struct dcb_entry *entry = &dcb->entry[i];
+		uint16_t encoders;
+		int type;
+
+		encoders = connector[entry->connector];
+		if (!(encoders & (1 << entry->type)))
+			continue;
+		connector[entry->connector] = 0;
+
+		if (encoders & (1 << OUTPUT_DP)) {
+			type = DRM_MODE_CONNECTOR_DisplayPort;
+		} else if (encoders & (1 << OUTPUT_TMDS)) {
+			if (encoders & (1 << OUTPUT_ANALOG))
+				type = DRM_MODE_CONNECTOR_DVII;
+			else
+				type = DRM_MODE_CONNECTOR_DVID;
+		} else if (encoders & (1 << OUTPUT_ANALOG)) {
+			type = DRM_MODE_CONNECTOR_VGA;
+		} else if (encoders & (1 << OUTPUT_LVDS)) {
+			type = DRM_MODE_CONNECTOR_LVDS;
+		} else {
+			type = DRM_MODE_CONNECTOR_Unknown;
+		}
+
+		if (type == DRM_MODE_CONNECTOR_Unknown)
+			continue;
+
+		nouveau_connector_create(dev, entry->connector, type);
+	}
+
+	ret = nv50_display_init(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int nv50_display_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	drm_mode_config_cleanup(dev);
+
+	nv50_display_disable(dev);
+	nv50_evo_channel_del(&dev_priv->evo);
+
+	return 0;
+}
+
+static inline uint32_t
+nv50_display_mode_ctrl(struct drm_device *dev, bool sor, int or)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t mc;
+
+	if (sor) {
+		if (dev_priv->chipset < 0x90 ||
+		    dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0)
+			mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(or));
+		else
+			mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(or));
+	} else {
+		mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(or));
+	}
+
+	return mc;
+}
+
+static int
+nv50_display_irq_head(struct drm_device *dev, int *phead,
+		      struct dcb_entry **pdcbent)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t unk30 = nv_rd32(dev, NV50_PDISPLAY_UNK30_CTRL);
+	uint32_t dac = 0, sor = 0;
+	int head, i, or = 0, type = OUTPUT_ANY;
+
+	/* We're assuming that head 0 *or* head 1 will be active here,
+	 * and not both.  I'm not sure if the hw will even signal both
+	 * ever, but it definitely shouldn't for us as we commit each
+	 * CRTC separately, and submission will be blocked by the GPU
+	 * until we handle each in turn.
+	 */
+	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
+	head = ffs((unk30 >> 9) & 3) - 1;
+	if (head < 0)
+		return -EINVAL;
+
+	/* This assumes CRTCs are never bound to multiple encoders, which
+	 * should be the case.
+	 */
+	for (i = 0; i < 3 && type == OUTPUT_ANY; i++) {
+		uint32_t mc = nv50_display_mode_ctrl(dev, false, i);
+		if (!(mc & (1 << head)))
+			continue;
+
+		switch ((mc >> 8) & 0xf) {
+		case 0: type = OUTPUT_ANALOG; break;
+		case 1: type = OUTPUT_TV; break;
+		default:
+			NV_ERROR(dev, "unknown dac mode_ctrl: 0x%08x\n", dac);
+			return -1;
+		}
+
+		or = i;
+	}
+
+	for (i = 0; i < 4 && type == OUTPUT_ANY; i++) {
+		uint32_t mc = nv50_display_mode_ctrl(dev, true, i);
+		if (!(mc & (1 << head)))
+			continue;
+
+		switch ((mc >> 8) & 0xf) {
+		case 0: type = OUTPUT_LVDS; break;
+		case 1: type = OUTPUT_TMDS; break;
+		case 2: type = OUTPUT_TMDS; break;
+		case 5: type = OUTPUT_TMDS; break;
+		case 8: type = OUTPUT_DP; break;
+		case 9: type = OUTPUT_DP; break;
+		default:
+			NV_ERROR(dev, "unknown sor mode_ctrl: 0x%08x\n", sor);
+			return -1;
+		}
+
+		or = i;
+	}
+
+	NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or);
+	if (type == OUTPUT_ANY) {
+		NV_ERROR(dev, "unknown encoder!!\n");
+		return -1;
+	}
+
+	for (i = 0; i < dev_priv->vbios->dcb->entries; i++) {
+		struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i];
+
+		if (dcbent->type != type)
+			continue;
+
+		if (!(dcbent->or & (1 << or)))
+			continue;
+
+		*phead = head;
+		*pdcbent = dcbent;
+		return 0;
+	}
+
+	NV_ERROR(dev, "no DCB entry for %d %d\n", dac != 0, or);
+	return 0;
+}
+
+static uint32_t
+nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
+			   int pxclk)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_connector *nv_connector = NULL;
+	struct drm_encoder *encoder;
+	struct nvbios *bios = &dev_priv->VBIOS;
+	uint32_t mc, script = 0, or;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (nv_encoder->dcb != dcbent)
+			continue;
+
+		nv_connector = nouveau_encoder_connector_get(nv_encoder);
+		break;
+	}
+
+	or = ffs(dcbent->or) - 1;
+	mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or);
+	switch (dcbent->type) {
+	case OUTPUT_LVDS:
+		script = (mc >> 8) & 0xf;
+		if (bios->pub.fp_no_ddc) {
+			if (bios->fp.dual_link)
+				script |= 0x0100;
+			if (bios->fp.if_is_24bit)
+				script |= 0x0200;
+		} else {
+			if (pxclk >= bios->fp.duallink_transition_clk) {
+				script |= 0x0100;
+				if (bios->fp.strapless_is_24bit & 2)
+					script |= 0x0200;
+			} else
+			if (bios->fp.strapless_is_24bit & 1)
+				script |= 0x0200;
+
+			if (nv_connector && nv_connector->edid &&
+			    (nv_connector->edid->revision >= 4) &&
+			    (nv_connector->edid->input & 0x70) >= 0x20)
+				script |= 0x0200;
+		}
+
+		if (nouveau_uscript_lvds >= 0) {
+			NV_INFO(dev, "override script 0x%04x with 0x%04x "
+				     "for output LVDS-%d\n", script,
+				     nouveau_uscript_lvds, or);
+			script = nouveau_uscript_lvds;
+		}
+		break;
+	case OUTPUT_TMDS:
+		script = (mc >> 8) & 0xf;
+		if (pxclk >= 165000)
+			script |= 0x0100;
+
+		if (nouveau_uscript_tmds >= 0) {
+			NV_INFO(dev, "override script 0x%04x with 0x%04x "
+				     "for output TMDS-%d\n", script,
+				     nouveau_uscript_tmds, or);
+			script = nouveau_uscript_tmds;
+		}
+		break;
+	case OUTPUT_DP:
+		script = (mc >> 8) & 0xf;
+		break;
+	case OUTPUT_ANALOG:
+		script = 0xff;
+		break;
+	default:
+		NV_ERROR(dev, "modeset on unsupported output type!\n");
+		break;
+	}
+
+	return script;
+}
+
+static void
+nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan;
+	struct list_head *entry, *tmp;
+
+	list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) {
+		chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait);
+
+		nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset,
+						chan->nvsw.vblsem_rval);
+		list_del(&chan->nvsw.vbl_wait);
+	}
+}
+
+static void
+nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
+{
+	intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC;
+
+	if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0)
+		nv50_display_vblank_crtc_handler(dev, 0);
+
+	if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1)
+		nv50_display_vblank_crtc_handler(dev, 1);
+
+	nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev,
+		     NV50_PDISPLAY_INTR_EN) & ~intr);
+	nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr);
+}
+
+static void
+nv50_display_unk10_handler(struct drm_device *dev)
+{
+	struct dcb_entry *dcbent;
+	int head, ret;
+
+	ret = nv50_display_irq_head(dev, &head, &dcbent);
+	if (ret)
+		goto ack;
+
+	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8);
+
+	nouveau_bios_run_display_table(dev, dcbent, 0, -1);
+
+ack:
+	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10);
+	nv_wr32(dev, 0x610030, 0x80000000);
+}
+
+static void
+nv50_display_unk20_handler(struct drm_device *dev)
+{
+	struct dcb_entry *dcbent;
+	uint32_t tmp, pclk, script;
+	int head, or, ret;
+
+	ret = nv50_display_irq_head(dev, &head, &dcbent);
+	if (ret)
+		goto ack;
+	or = ffs(dcbent->or) - 1;
+	pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
+	script = nv50_display_script_select(dev, dcbent, pclk);
+
+	NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk);
+
+	if (dcbent->type != OUTPUT_DP)
+		nouveau_bios_run_display_table(dev, dcbent, 0, -2);
+
+	nv50_crtc_set_clock(dev, head, pclk);
+
+	nouveau_bios_run_display_table(dev, dcbent, script, pclk);
+
+	tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head));
+	tmp &= ~0x000000f;
+	nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(head), tmp);
+
+	if (dcbent->type != OUTPUT_ANALOG) {
+		tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or));
+		tmp &= ~0x00000f0f;
+		if (script & 0x0100)
+			tmp |= 0x00000101;
+		nv_wr32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp);
+	} else {
+		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0);
+	}
+
+ack:
+	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20);
+	nv_wr32(dev, 0x610030, 0x80000000);
+}
+
+static void
+nv50_display_unk40_handler(struct drm_device *dev)
+{
+	struct dcb_entry *dcbent;
+	int head, pclk, script, ret;
+
+	ret = nv50_display_irq_head(dev, &head, &dcbent);
+	if (ret)
+		goto ack;
+	pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff;
+	script = nv50_display_script_select(dev, dcbent, pclk);
+
+	nouveau_bios_run_display_table(dev, dcbent, script, -pclk);
+
+ack:
+	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40);
+	nv_wr32(dev, 0x610030, 0x80000000);
+	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8);
+}
+
+void
+nv50_display_irq_handler_bh(struct work_struct *work)
+{
+	struct drm_nouveau_private *dev_priv =
+		container_of(work, struct drm_nouveau_private, irq_work);
+	struct drm_device *dev = dev_priv->dev;
+
+	for (;;) {
+		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
+		uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1);
+
+		NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1);
+
+		if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10)
+			nv50_display_unk10_handler(dev);
+		else
+		if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK20)
+			nv50_display_unk20_handler(dev);
+		else
+		if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK40)
+			nv50_display_unk40_handler(dev);
+		else
+			break;
+	}
+
+	nv_wr32(dev, NV03_PMC_INTR_EN_0, 1);
+}
+
+static void
+nv50_display_error_handler(struct drm_device *dev)
+{
+	uint32_t addr, data;
+
+	nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000);
+	addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR);
+	data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA);
+
+	NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n",
+		 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf);
+
+	nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);
+}
+
+static void
+nv50_display_irq_hotplug(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
+	const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
+	uint32_t unplug_mask, plug_mask, change_mask;
+	uint32_t hpd0, hpd1 = 0;
+
+	hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050);
+	if (dev_priv->chipset >= 0x90)
+		hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070);
+
+	plug_mask   = (hpd0 & 0x0000ffff) | (hpd1 << 16);
+	unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000);
+	change_mask = plug_mask | unplug_mask;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct drm_encoder_helper_funcs *helper;
+		struct nouveau_connector *nv_connector =
+			nouveau_connector(connector);
+		struct nouveau_encoder *nv_encoder;
+		struct dcb_gpio_entry *gpio;
+		uint32_t reg;
+		bool plugged;
+
+		if (!nv_connector->dcb)
+			continue;
+
+		gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag);
+		if (!gpio || !(change_mask & (1 << gpio->line)))
+			continue;
+
+		reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]);
+		plugged = !!(reg & (4 << ((gpio->line & 7) << 2)));
+		NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
+			drm_get_connector_name(connector)) ;
+
+		if (!connector->encoder || !connector->encoder->crtc ||
+		    !connector->encoder->crtc->enabled)
+			continue;
+		nv_encoder = nouveau_encoder(connector->encoder);
+		helper = connector->encoder->helper_private;
+
+		if (nv_encoder->dcb->type != OUTPUT_DP)
+			continue;
+
+		if (plugged)
+			helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
+		else
+			helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
+	}
+
+	nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054));
+	if (dev_priv->chipset >= 0x90)
+		nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074));
+}
+
+void
+nv50_display_irq_handler(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t delayed = 0;
+
+	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG)
+		nv50_display_irq_hotplug(dev);
+
+	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
+		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
+		uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1);
+		uint32_t clock;
+
+		NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1);
+
+		if (!intr0 && !(intr1 & ~delayed))
+			break;
+
+		if (intr0 & 0x00010000) {
+			nv50_display_error_handler(dev);
+			intr0 &= ~0x00010000;
+		}
+
+		if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) {
+			nv50_display_vblank_handler(dev, intr1);
+			intr1 &= ~NV50_PDISPLAY_INTR_1_VBLANK_CRTC;
+		}
+
+		clock = (intr1 & (NV50_PDISPLAY_INTR_1_CLK_UNK10 |
+				  NV50_PDISPLAY_INTR_1_CLK_UNK20 |
+				  NV50_PDISPLAY_INTR_1_CLK_UNK40));
+		if (clock) {
+			nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
+			if (!work_pending(&dev_priv->irq_work))
+				queue_work(dev_priv->wq, &dev_priv->irq_work);
+			delayed |= clock;
+			intr1 &= ~clock;
+		}
+
+		if (intr0) {
+			NV_ERROR(dev, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0);
+			nv_wr32(dev, NV50_PDISPLAY_INTR_0, intr0);
+		}
+
+		if (intr1) {
+			NV_ERROR(dev,
+				 "unknown PDISPLAY_INTR_1: 0x%08x\n", intr1);
+			nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr1);
+		}
+	}
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -0,0 +1,848 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 <acpi/button.h>
+
+#include "drmP.h"
+#include "drm_edid.h"
+#include "drm_crtc_helper.h"
+
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_connector.h"
+#include "nouveau_hw.h"
+
+static inline struct drm_encoder_slave_funcs *
+get_slave_funcs(struct nouveau_encoder *enc)
+{
+	return to_encoder_slave(to_drm_encoder(enc))->slave_funcs;
+}
+
+static struct nouveau_encoder *
+find_encoder_by_type(struct drm_connector *connector, int type)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_mode_object *obj;
+	int i, id;
+
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		id = connector->encoder_ids[i];
+		if (!id)
+			break;
+
+		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			continue;
+		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+
+		if (type == OUTPUT_ANY || nv_encoder->dcb->type == type)
+			return nv_encoder;
+	}
+
+	return NULL;
+}
+
+struct nouveau_connector *
+nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
+{
+	struct drm_device *dev = to_drm_encoder(encoder)->dev;
+	struct drm_connector *drm_connector;
+
+	list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
+		if (drm_connector->encoder == to_drm_encoder(encoder))
+			return nouveau_connector(drm_connector);
+	}
+
+	return NULL;
+}
+
+
+static void
+nouveau_connector_destroy(struct drm_connector *drm_connector)
+{
+	struct nouveau_connector *nv_connector =
+		nouveau_connector(drm_connector);
+	struct drm_device *dev;
+
+	if (!nv_connector)
+		return;
+
+	dev = nv_connector->base.dev;
+	NV_DEBUG_KMS(dev, "\n");
+
+	kfree(nv_connector->edid);
+	drm_sysfs_connector_remove(drm_connector);
+	drm_connector_cleanup(drm_connector);
+	kfree(drm_connector);
+}
+
+static void
+nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags)
+{
+	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
+
+	if (dev_priv->card_type >= NV_50)
+		return;
+
+	*flags = 0;
+	if (NVLockVgaCrtcs(dev_priv->dev, false))
+		*flags |= 1;
+	if (nv_heads_tied(dev_priv->dev))
+		*flags |= 2;
+
+	if (*flags & 2)
+		NVSetOwner(dev_priv->dev, 0); /* necessary? */
+}
+
+static void
+nouveau_connector_ddc_finish(struct drm_connector *connector, int flags)
+{
+	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
+
+	if (dev_priv->card_type >= NV_50)
+		return;
+
+	if (flags & 2)
+		NVSetOwner(dev_priv->dev, 4);
+	if (flags & 1)
+		NVLockVgaCrtcs(dev_priv->dev, true);
+}
+
+static struct nouveau_i2c_chan *
+nouveau_connector_ddc_detect(struct drm_connector *connector,
+			     struct nouveau_encoder **pnv_encoder)
+{
+	struct drm_device *dev = connector->dev;
+	uint8_t out_buf[] = { 0x0, 0x0}, buf[2];
+	int ret, flags, i;
+
+	struct i2c_msg msgs[] = {
+		{
+			.addr = 0x50,
+			.flags = 0,
+			.len = 1,
+			.buf = out_buf,
+		},
+		{
+			.addr = 0x50,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
+	};
+
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		struct nouveau_i2c_chan *i2c = NULL;
+		struct nouveau_encoder *nv_encoder;
+		struct drm_mode_object *obj;
+		int id;
+
+		id = connector->encoder_ids[i];
+		if (!id)
+			break;
+
+		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj)
+			continue;
+		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+
+		if (nv_encoder->dcb->i2c_index < 0xf)
+			i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+		if (!i2c)
+			continue;
+
+		nouveau_connector_ddc_prepare(connector, &flags);
+		ret = i2c_transfer(&i2c->adapter, msgs, 2);
+		nouveau_connector_ddc_finish(connector, flags);
+
+		if (ret == 2) {
+			*pnv_encoder = nv_encoder;
+			return i2c;
+		}
+	}
+
+	return NULL;
+}
+
+static void
+nouveau_connector_set_encoder(struct drm_connector *connector,
+			      struct nouveau_encoder *nv_encoder)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
+	struct drm_device *dev = connector->dev;
+
+	if (nv_connector->detected_encoder == nv_encoder)
+		return;
+	nv_connector->detected_encoder = nv_encoder;
+
+	if (nv_encoder->dcb->type == OUTPUT_LVDS ||
+	    nv_encoder->dcb->type == OUTPUT_TMDS) {
+		connector->doublescan_allowed = false;
+		connector->interlace_allowed = false;
+	} else {
+		connector->doublescan_allowed = true;
+		if (dev_priv->card_type == NV_20 ||
+		   (dev_priv->card_type == NV_10 &&
+		    (dev->pci_device & 0x0ff0) != 0x0100 &&
+		    (dev->pci_device & 0x0ff0) != 0x0150))
+			/* HW is broken */
+			connector->interlace_allowed = false;
+		else
+			connector->interlace_allowed = true;
+	}
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+		drm_connector_property_set_value(connector,
+			dev->mode_config.dvi_i_subconnector_property,
+			nv_encoder->dcb->type == OUTPUT_TMDS ?
+			DRM_MODE_SUBCONNECTOR_DVID :
+			DRM_MODE_SUBCONNECTOR_DVIA);
+	}
+}
+
+static enum drm_connector_status
+nouveau_connector_detect(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_encoder *nv_encoder = NULL;
+	struct nouveau_i2c_chan *i2c;
+	int type, flags;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+	if (nv_encoder && nv_connector->native_mode) {
+		unsigned status = connector_status_connected;
+
+#ifdef CONFIG_ACPI
+		if (!nouveau_ignorelid && !acpi_lid_open())
+			status = connector_status_unknown;
+#endif
+		nouveau_connector_set_encoder(connector, nv_encoder);
+		return status;
+	}
+
+	/* Cleanup the previous EDID block. */
+	if (nv_connector->edid) {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		kfree(nv_connector->edid);
+		nv_connector->edid = NULL;
+	}
+
+	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
+	if (i2c) {
+		nouveau_connector_ddc_prepare(connector, &flags);
+		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
+		nouveau_connector_ddc_finish(connector, flags);
+		drm_mode_connector_update_edid_property(connector,
+							nv_connector->edid);
+		if (!nv_connector->edid) {
+			NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
+				 drm_get_connector_name(connector));
+			goto detect_analog;
+		}
+
+		if (nv_encoder->dcb->type == OUTPUT_DP &&
+		    !nouveau_dp_detect(to_drm_encoder(nv_encoder))) {
+			NV_ERROR(dev, "Detected %s, but failed init\n",
+				 drm_get_connector_name(connector));
+			return connector_status_disconnected;
+		}
+
+		/* Override encoder type for DVI-I based on whether EDID
+		 * says the display is digital or analog, both use the
+		 * same i2c channel so the value returned from ddc_detect
+		 * isn't necessarily correct.
+		 */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+			if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
+				type = OUTPUT_TMDS;
+			else
+				type = OUTPUT_ANALOG;
+
+			nv_encoder = find_encoder_by_type(connector, type);
+			if (!nv_encoder) {
+				NV_ERROR(dev, "Detected %d encoder on %s, "
+					      "but no object!\n", type,
+					 drm_get_connector_name(connector));
+				return connector_status_disconnected;
+			}
+		}
+
+		nouveau_connector_set_encoder(connector, nv_encoder);
+		return connector_status_connected;
+	}
+
+detect_analog:
+	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
+	if (!nv_encoder)
+		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
+	if (nv_encoder) {
+		struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
+		struct drm_encoder_helper_funcs *helper =
+						encoder->helper_private;
+
+		if (helper->detect(encoder, connector) ==
+						connector_status_connected) {
+			nouveau_connector_set_encoder(connector, nv_encoder);
+			return connector_status_connected;
+		}
+
+	}
+
+	return connector_status_disconnected;
+}
+
+static void
+nouveau_connector_force(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_encoder *nv_encoder;
+	int type;
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+		if (connector->force == DRM_FORCE_ON_DIGITAL)
+			type = OUTPUT_TMDS;
+		else
+			type = OUTPUT_ANALOG;
+	} else
+		type = OUTPUT_ANY;
+
+	nv_encoder = find_encoder_by_type(connector, type);
+	if (!nv_encoder) {
+		NV_ERROR(dev, "can't find encoder to force %s on!\n",
+			 drm_get_connector_name(connector));
+		connector->status = connector_status_disconnected;
+		return;
+	}
+
+	nouveau_connector_set_encoder(connector, nv_encoder);
+}
+
+static int
+nouveau_connector_set_property(struct drm_connector *connector,
+			       struct drm_property *property, uint64_t value)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+	struct drm_device *dev = connector->dev;
+	int ret;
+
+	/* Scaling mode */
+	if (property == dev->mode_config.scaling_mode_property) {
+		struct nouveau_crtc *nv_crtc = NULL;
+		bool modeset = false;
+
+		switch (value) {
+		case DRM_MODE_SCALE_NONE:
+		case DRM_MODE_SCALE_FULLSCREEN:
+		case DRM_MODE_SCALE_CENTER:
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		/* LVDS always needs gpu scaling */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
+		    value == DRM_MODE_SCALE_NONE)
+			return -EINVAL;
+
+		/* Changing between GPU and panel scaling requires a full
+		 * modeset
+		 */
+		if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) ||
+		    (value == DRM_MODE_SCALE_NONE))
+			modeset = true;
+		nv_connector->scaling_mode = value;
+
+		if (connector->encoder && connector->encoder->crtc)
+			nv_crtc = nouveau_crtc(connector->encoder->crtc);
+		if (!nv_crtc)
+			return 0;
+
+		if (modeset || !nv_crtc->set_scale) {
+			ret = drm_crtc_helper_set_mode(&nv_crtc->base,
+							&nv_crtc->base.mode,
+							nv_crtc->base.x,
+							nv_crtc->base.y, NULL);
+			if (!ret)
+				return -EINVAL;
+		} else {
+			ret = nv_crtc->set_scale(nv_crtc, value, true);
+			if (ret)
+				return ret;
+		}
+
+		return 0;
+	}
+
+	/* Dithering */
+	if (property == dev->mode_config.dithering_mode_property) {
+		struct nouveau_crtc *nv_crtc = NULL;
+
+		if (value == DRM_MODE_DITHERING_ON)
+			nv_connector->use_dithering = true;
+		else
+			nv_connector->use_dithering = false;
+
+		if (connector->encoder && connector->encoder->crtc)
+			nv_crtc = nouveau_crtc(connector->encoder->crtc);
+
+		if (!nv_crtc || !nv_crtc->set_dither)
+			return 0;
+
+		return nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering,
+					   true);
+	}
+
+	if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
+		return get_slave_funcs(nv_encoder)->
+			set_property(to_drm_encoder(nv_encoder), connector, property, value);
+
+	return -EINVAL;
+}
+
+static struct drm_display_mode *
+nouveau_connector_native_mode(struct nouveau_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct drm_display_mode *mode, *largest = NULL;
+	int high_w = 0, high_h = 0, high_v = 0;
+
+	/* Use preferred mode if there is one.. */
+	list_for_each_entry(mode, &connector->base.probed_modes, head) {
+		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+			NV_DEBUG_KMS(dev, "native mode from preferred\n");
+			return drm_mode_duplicate(dev, mode);
+		}
+	}
+
+	/* Otherwise, take the resolution with the largest width, then height,
+	 * then vertical refresh
+	 */
+	list_for_each_entry(mode, &connector->base.probed_modes, head) {
+		if (mode->hdisplay < high_w)
+			continue;
+
+		if (mode->hdisplay == high_w && mode->vdisplay < high_h)
+			continue;
+
+		if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
+		    mode->vrefresh < high_v)
+			continue;
+
+		high_w = mode->hdisplay;
+		high_h = mode->vdisplay;
+		high_v = mode->vrefresh;
+		largest = mode;
+	}
+
+	NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n",
+		      high_w, high_h, high_v);
+	return largest ? drm_mode_duplicate(dev, largest) : NULL;
+}
+
+struct moderec {
+	int hdisplay;
+	int vdisplay;
+};
+
+static struct moderec scaler_modes[] = {
+	{ 1920, 1200 },
+	{ 1920, 1080 },
+	{ 1680, 1050 },
+	{ 1600, 1200 },
+	{ 1400, 1050 },
+	{ 1280, 1024 },
+	{ 1280, 960 },
+	{ 1152, 864 },
+	{ 1024, 768 },
+	{ 800, 600 },
+	{ 720, 400 },
+	{ 640, 480 },
+	{ 640, 400 },
+	{ 640, 350 },
+	{}
+};
+
+static int
+nouveau_connector_scaler_modes_add(struct drm_connector *connector)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct drm_display_mode *native = nv_connector->native_mode, *m;
+	struct drm_device *dev = connector->dev;
+	struct moderec *mode = &scaler_modes[0];
+	int modes = 0;
+
+	if (!native)
+		return 0;
+
+	while (mode->hdisplay) {
+		if (mode->hdisplay <= native->hdisplay &&
+		    mode->vdisplay <= native->vdisplay) {
+			m = drm_cvt_mode(dev, mode->hdisplay, mode->vdisplay,
+					 drm_mode_vrefresh(native), false,
+					 false, false);
+			if (!m)
+				continue;
+
+			m->type |= DRM_MODE_TYPE_DRIVER;
+
+			drm_mode_probed_add(connector, m);
+			modes++;
+		}
+
+		mode++;
+	}
+
+	return modes;
+}
+
+static int
+nouveau_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+	int ret = 0;
+
+	/* If we're not LVDS, destroy the previous native mode, the attached
+	 * monitor could have changed.
+	 */
+	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+	    nv_connector->native_mode) {
+		drm_mode_destroy(dev, nv_connector->native_mode);
+		nv_connector->native_mode = NULL;
+	}
+
+	if (nv_connector->edid)
+		ret = drm_add_edid_modes(connector, nv_connector->edid);
+
+	/* Find the native mode if this is a digital panel, if we didn't
+	 * find any modes through DDC previously add the native mode to
+	 * the list of modes.
+	 */
+	if (!nv_connector->native_mode)
+		nv_connector->native_mode =
+			nouveau_connector_native_mode(nv_connector);
+	if (ret == 0 && nv_connector->native_mode) {
+		struct drm_display_mode *mode;
+
+		mode = drm_mode_duplicate(dev, nv_connector->native_mode);
+		drm_mode_probed_add(connector, mode);
+		ret = 1;
+	}
+
+	if (nv_encoder->dcb->type == OUTPUT_TV)
+		ret = get_slave_funcs(nv_encoder)->
+			get_modes(to_drm_encoder(nv_encoder), connector);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+		ret += nouveau_connector_scaler_modes_add(connector);
+
+	return ret;
+}
+
+static int
+nouveau_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
+{
+	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+	unsigned min_clock = 25000, max_clock = min_clock;
+	unsigned clock = mode->clock;
+
+	switch (nv_encoder->dcb->type) {
+	case OUTPUT_LVDS:
+		BUG_ON(!nv_connector->native_mode);
+		if (mode->hdisplay > nv_connector->native_mode->hdisplay ||
+		    mode->vdisplay > nv_connector->native_mode->vdisplay)
+			return MODE_PANEL;
+
+		min_clock = 0;
+		max_clock = 400000;
+		break;
+	case OUTPUT_TMDS:
+		if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) ||
+		    (dev_priv->card_type < NV_50 &&
+		     !nv_encoder->dcb->duallink_possible))
+			max_clock = 165000;
+		else
+			max_clock = 330000;
+		break;
+	case OUTPUT_ANALOG:
+		max_clock = nv_encoder->dcb->crtconf.maxfreq;
+		if (!max_clock)
+			max_clock = 350000;
+		break;
+	case OUTPUT_TV:
+		return get_slave_funcs(nv_encoder)->
+			mode_valid(to_drm_encoder(nv_encoder), mode);
+	case OUTPUT_DP:
+		if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
+			max_clock = nv_encoder->dp.link_nr * 270000;
+		else
+			max_clock = nv_encoder->dp.link_nr * 162000;
+
+		clock *= 3;
+		break;
+	}
+
+	if (clock < min_clock)
+		return MODE_CLOCK_LOW;
+
+	if (clock > max_clock)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+nouveau_connector_best_encoder(struct drm_connector *connector)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+
+	if (nv_connector->detected_encoder)
+		return to_drm_encoder(nv_connector->detected_encoder);
+
+	return NULL;
+}
+
+static const struct drm_connector_helper_funcs
+nouveau_connector_helper_funcs = {
+	.get_modes = nouveau_connector_get_modes,
+	.mode_valid = nouveau_connector_mode_valid,
+	.best_encoder = nouveau_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs
+nouveau_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = NULL,
+	.restore = NULL,
+	.detect = nouveau_connector_detect,
+	.destroy = nouveau_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = nouveau_connector_set_property,
+	.force = nouveau_connector_force
+};
+
+static int
+nouveau_connector_create_lvds(struct drm_device *dev,
+			      struct drm_connector *connector)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_i2c_chan *i2c = NULL;
+	struct nouveau_encoder *nv_encoder;
+	struct drm_display_mode native, *mode, *temp;
+	bool dummy, if_is_24bit = false;
+	int ret, flags;
+
+	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+	if (!nv_encoder)
+		return -ENODEV;
+
+	ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit);
+	if (ret) {
+		NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n");
+		return ret;
+	}
+	nv_connector->use_dithering = !if_is_24bit;
+
+	/* Firstly try getting EDID over DDC, if allowed and I2C channel
+	 * is available.
+	 */
+	if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
+		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+
+	if (i2c) {
+		nouveau_connector_ddc_prepare(connector, &flags);
+		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
+		nouveau_connector_ddc_finish(connector, flags);
+	}
+
+	/* If no EDID found above, and the VBIOS indicates a hardcoded
+	 * modeline is avalilable for the panel, set it as the panel's
+	 * native mode and exit.
+	 */
+	if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
+	     (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
+	      dev_priv->VBIOS.pub.fp_no_ddc)) {
+		nv_connector->native_mode = drm_mode_duplicate(dev, &native);
+		goto out;
+	}
+
+	/* Still nothing, some VBIOS images have a hardcoded EDID block
+	 * stored for the panel stored in them.
+	 */
+	if (!nv_connector->edid && !nv_connector->native_mode &&
+	    !dev_priv->VBIOS.pub.fp_no_ddc) {
+		struct edid *edid =
+			(struct edid *)nouveau_bios_embedded_edid(dev);
+		if (edid) {
+			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+			*(nv_connector->edid) = *edid;
+		}
+	}
+
+	if (!nv_connector->edid)
+		goto out;
+
+	/* We didn't find/use a panel mode from the VBIOS, so parse the EDID
+	 * block and look for the preferred mode there.
+	 */
+	ret = drm_add_edid_modes(connector, nv_connector->edid);
+	if (ret == 0)
+		goto out;
+	nv_connector->detected_encoder = nv_encoder;
+	nv_connector->native_mode = nouveau_connector_native_mode(nv_connector);
+	list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
+		drm_mode_remove(connector, mode);
+
+out:
+	if (!nv_connector->native_mode) {
+		NV_ERROR(dev, "LVDS present in DCB table, but couldn't "
+			      "determine its native mode.  Disabling.\n");
+		return -ENODEV;
+	}
+
+	drm_mode_connector_update_edid_property(connector, nv_connector->edid);
+	return 0;
+}
+
+int
+nouveau_connector_create(struct drm_device *dev, int index, int type)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_connector *nv_connector = NULL;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
+	if (!nv_connector)
+		return -ENOMEM;
+	nv_connector->dcb = nouveau_bios_connector_entry(dev, index);
+	connector = &nv_connector->base;
+
+	switch (type) {
+	case DRM_MODE_CONNECTOR_VGA:
+		NV_INFO(dev, "Detected a VGA connector\n");
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+		NV_INFO(dev, "Detected a DVI-D connector\n");
+		break;
+	case DRM_MODE_CONNECTOR_DVII:
+		NV_INFO(dev, "Detected a DVI-I connector\n");
+		break;
+	case DRM_MODE_CONNECTOR_LVDS:
+		NV_INFO(dev, "Detected a LVDS connector\n");
+		break;
+	case DRM_MODE_CONNECTOR_TV:
+		NV_INFO(dev, "Detected a TV connector\n");
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		NV_INFO(dev, "Detected a DisplayPort connector\n");
+		break;
+	default:
+		NV_ERROR(dev, "Unknown connector, this is not good.\n");
+		break;
+	}
+
+	/* defaults, will get overridden in detect() */
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
+	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
+
+	/* Init DVI-I specific properties */
+	if (type == DRM_MODE_CONNECTOR_DVII) {
+		drm_mode_create_dvi_i_properties(dev);
+		drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
+		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
+	}
+
+	if (type != DRM_MODE_CONNECTOR_LVDS)
+		nv_connector->use_dithering = false;
+
+	if (type == DRM_MODE_CONNECTOR_DVID ||
+	    type == DRM_MODE_CONNECTOR_DVII ||
+	    type == DRM_MODE_CONNECTOR_LVDS ||
+	    type == DRM_MODE_CONNECTOR_DisplayPort) {
+		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
+
+		drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property,
+					      nv_connector->scaling_mode);
+		drm_connector_attach_property(connector, dev->mode_config.dithering_mode_property,
+					      nv_connector->use_dithering ? DRM_MODE_DITHERING_ON
+					      : DRM_MODE_DITHERING_OFF);
+
+	} else {
+		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
+
+		if (type == DRM_MODE_CONNECTOR_VGA  &&
+				dev_priv->card_type >= NV_50) {
+			drm_connector_attach_property(connector,
+					dev->mode_config.scaling_mode_property,
+					nv_connector->scaling_mode);
+		}
+	}
+
+	/* attach encoders */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (nv_encoder->dcb->connector != index)
+			continue;
+
+		if (get_slave_funcs(nv_encoder))
+			get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
+
+		drm_mode_connector_attach_encoder(connector, encoder);
+	}
+
+	drm_sysfs_connector_add(connector);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		ret = nouveau_connector_create_lvds(dev, connector);
+		if (ret) {
+			connector->funcs->destroy(connector);
+			return ret;
+		}
+	}
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_CRTC_H__
+#define __NOUVEAU_CRTC_H__
+
+struct nouveau_crtc {
+	struct drm_crtc base;
+
+	int index;
+
+	struct drm_display_mode *mode;
+
+	uint32_t dpms_saved_fp_control;
+	uint32_t fp_users;
+	int saturation;
+	int sharpness;
+	int last_dpms;
+
+	struct {
+		int cpp;
+		bool blanked;
+		uint32_t offset;
+		uint32_t tile_flags;
+	} fb;
+
+	struct {
+		struct nouveau_bo *nvbo;
+		bool visible;
+		uint32_t offset;
+		void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
+		void (*set_pos)(struct nouveau_crtc *, int x, int y);
+		void (*hide)(struct nouveau_crtc *, bool update);
+		void (*show)(struct nouveau_crtc *, bool update);
+	} cursor;
+
+	struct {
+		struct nouveau_bo *nvbo;
+		uint16_t r[256];
+		uint16_t g[256];
+		uint16_t b[256];
+		int depth;
+	} lut;
+
+	int (*set_dither)(struct nouveau_crtc *crtc, bool on, bool update);
+	int (*set_scale)(struct nouveau_crtc *crtc, int mode, bool update);
+};
+
+static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct nouveau_crtc, base);
+}
+
+static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc)
+{
+	return &crtc->base;
+}
+
+int nv50_crtc_create(struct drm_device *dev, int index);
+int nv50_cursor_init(struct nouveau_crtc *);
+void nv50_cursor_fini(struct nouveau_crtc *);
+int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv,
+			 uint32_t buffer_handle, uint32_t width,
+			 uint32_t height);
+int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
+
+int nv04_cursor_init(struct nouveau_crtc *);
+
+struct nouveau_connector *
+nouveau_crtc_connector_get(struct nouveau_crtc *crtc);
+
+#endif /* __NOUVEAU_CRTC_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_hw.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_hw.c
@@ -0,0 +1,1080 @@
+/*
+ * Copyright 2006 Dave Airlie
+ * Copyright 2007 Maarten Maathuis
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * 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 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+
+#define CHIPSET_NFORCE 0x01a0
+#define CHIPSET_NFORCE2 0x01f0
+
+/*
+ * misc hw access wrappers/control functions
+ */
+
+void
+NVWriteVgaSeq(struct drm_device *dev, int head, uint8_t index, uint8_t value)
+{
+	NVWritePRMVIO(dev, head, NV_PRMVIO_SRX, index);
+	NVWritePRMVIO(dev, head, NV_PRMVIO_SR, value);
+}
+
+uint8_t
+NVReadVgaSeq(struct drm_device *dev, int head, uint8_t index)
+{
+	NVWritePRMVIO(dev, head, NV_PRMVIO_SRX, index);
+	return NVReadPRMVIO(dev, head, NV_PRMVIO_SR);
+}
+
+void
+NVWriteVgaGr(struct drm_device *dev, int head, uint8_t index, uint8_t value)
+{
+	NVWritePRMVIO(dev, head, NV_PRMVIO_GRX, index);
+	NVWritePRMVIO(dev, head, NV_PRMVIO_GX, value);
+}
+
+uint8_t
+NVReadVgaGr(struct drm_device *dev, int head, uint8_t index)
+{
+	NVWritePRMVIO(dev, head, NV_PRMVIO_GRX, index);
+	return NVReadPRMVIO(dev, head, NV_PRMVIO_GX);
+}
+
+/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied)
+ * it affects only the 8 bit vga io regs, which we access using mmio at
+ * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d*
+ * in general, the set value of cr44 does not matter: reg access works as
+ * expected and values can be set for the appropriate head by using a 0x2000
+ * offset as required
+ * however:
+ * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and
+ *    cr44 must be set to 0 or 3 for accessing values on the correct head
+ *    through the common 0xc03c* addresses
+ * b) in tied mode (4) head B is programmed to the values set on head A, and
+ *    access using the head B addresses can have strange results, ergo we leave
+ *    tied mode in init once we know to what cr44 should be restored on exit
+ *
+ * the owner parameter is slightly abused:
+ * 0 and 1 are treated as head values and so the set value is (owner * 3)
+ * other values are treated as literal values to set
+ */
+void
+NVSetOwner(struct drm_device *dev, int owner)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (owner == 1)
+		owner *= 3;
+
+	if (dev_priv->chipset == 0x11) {
+		/* This might seem stupid, but the blob does it and
+		 * omitting it often locks the system up.
+		 */
+		NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
+		NVReadVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX);
+	}
+
+	/* CR44 is always changed on CRTC0 */
+	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner);
+
+	if (dev_priv->chipset == 0x11) {	/* set me harder */
+		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
+		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner);
+	}
+}
+
+void
+NVBlankScreen(struct drm_device *dev, int head, bool blank)
+{
+	unsigned char seq1;
+
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, head);
+
+	seq1 = NVReadVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX);
+
+	NVVgaSeqReset(dev, head, true);
+	if (blank)
+		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
+	else
+		NVWriteVgaSeq(dev, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);
+	NVVgaSeqReset(dev, head, false);
+}
+
+/*
+ * PLL setting
+ */
+
+static int
+powerctrl_1_shift(int chip_version, int reg)
+{
+	int shift = -4;
+
+	if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20)
+		return shift;
+
+	switch (reg) {
+	case NV_RAMDAC_VPLL2:
+		shift += 4;
+	case NV_PRAMDAC_VPLL_COEFF:
+		shift += 4;
+	case NV_PRAMDAC_MPLL_COEFF:
+		shift += 4;
+	case NV_PRAMDAC_NVPLL_COEFF:
+		shift += 4;
+	}
+
+	/*
+	 * the shift for vpll regs is only used for nv3x chips with a single
+	 * stage pll
+	 */
+	if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 ||
+			  chip_version == 0x36 || chip_version >= 0x40))
+		shift = -4;
+
+	return shift;
+}
+
+static void
+setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chip_version = dev_priv->vbios->chip_version;
+	uint32_t oldpll = NVReadRAMDAC(dev, 0, reg);
+	int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff;
+	uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1;
+	uint32_t saved_powerctrl_1 = 0;
+	int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg);
+
+	if (oldpll == pll)
+		return;	/* already set */
+
+	if (shift_powerctrl_1 >= 0) {
+		saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1);
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_1,
+			(saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) |
+			1 << shift_powerctrl_1);
+	}
+
+	if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1))
+		/* upclock -- write new post divider first */
+		NVWriteRAMDAC(dev, 0, reg, pv->log2P << 16 | (oldpll & 0xffff));
+	else
+		/* downclock -- write new NM first */
+		NVWriteRAMDAC(dev, 0, reg, (oldpll & 0xffff0000) | pv->NM1);
+
+	if (chip_version < 0x17 && chip_version != 0x11)
+		/* wait a bit on older chips */
+		msleep(64);
+	NVReadRAMDAC(dev, 0, reg);
+
+	/* then write the other half as well */
+	NVWriteRAMDAC(dev, 0, reg, pll);
+
+	if (shift_powerctrl_1 >= 0)
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1);
+}
+
+static uint32_t
+new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580)
+{
+	bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF);
+
+	if (ss)	/* single stage pll mode */
+		ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE :
+				      NV_RAMDAC_580_VPLL2_ACTIVE;
+	else
+		ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE :
+				      ~NV_RAMDAC_580_VPLL2_ACTIVE;
+
+	return ramdac580;
+}
+
+static void
+setPLL_double_highregs(struct drm_device *dev, uint32_t reg1,
+		       struct nouveau_pll_vals *pv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chip_version = dev_priv->vbios->chip_version;
+	bool nv3035 = chip_version == 0x30 || chip_version == 0x35;
+	uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70);
+	uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1);
+	uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(dev, 0, reg2) : 0;
+	uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1;
+	uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2;
+	uint32_t oldramdac580 = 0, ramdac580 = 0;
+	bool single_stage = !pv->NM2 || pv->N2 == pv->M2;	/* nv41+ only */
+	uint32_t saved_powerctrl_1 = 0, savedc040 = 0;
+	int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1);
+
+	/* model specific additions to generic pll1 and pll2 set up above */
+	if (nv3035) {
+		pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 |
+		       (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4;
+		pll2 = 0;
+	}
+	if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */
+		oldramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580);
+		ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580);
+		if (oldramdac580 != ramdac580)
+			oldpll1 = ~0;	/* force mismatch */
+		if (single_stage)
+			/* magic value used by nvidia in single stage mode */
+			pll2 |= 0x011f;
+	}
+	if (chip_version > 0x70)
+		/* magic bits set by the blob (but not the bios) on g71-73 */
+		pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28;
+
+	if (oldpll1 == pll1 && oldpll2 == pll2)
+		return;	/* already set */
+
+	if (shift_powerctrl_1 >= 0) {
+		saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1);
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_1,
+			(saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) |
+			1 << shift_powerctrl_1);
+	}
+
+	if (chip_version >= 0x40) {
+		int shift_c040 = 14;
+
+		switch (reg1) {
+		case NV_PRAMDAC_MPLL_COEFF:
+			shift_c040 += 2;
+		case NV_PRAMDAC_NVPLL_COEFF:
+			shift_c040 += 2;
+		case NV_RAMDAC_VPLL2:
+			shift_c040 += 2;
+		case NV_PRAMDAC_VPLL_COEFF:
+			shift_c040 += 2;
+		}
+
+		savedc040 = nvReadMC(dev, 0xc040);
+		if (shift_c040 != 14)
+			nvWriteMC(dev, 0xc040, savedc040 & ~(3 << shift_c040));
+	}
+
+	if (oldramdac580 != ramdac580)
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_580, ramdac580);
+
+	if (!nv3035)
+		NVWriteRAMDAC(dev, 0, reg2, pll2);
+	NVWriteRAMDAC(dev, 0, reg1, pll1);
+
+	if (shift_powerctrl_1 >= 0)
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1);
+	if (chip_version >= 0x40)
+		nvWriteMC(dev, 0xc040, savedc040);
+}
+
+static void
+setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg,
+		      struct nouveau_pll_vals *pv)
+{
+	/* When setting PLLs, there is a merry game of disabling and enabling
+	 * various bits of hardware during the process. This function is a
+	 * synthesis of six nv4x traces, nearly each card doing a subtly
+	 * different thing. With luck all the necessary bits for each card are
+	 * combined herein. Without luck it deviates from each card's formula
+	 * so as to not work on any :)
+	 */
+
+	uint32_t Preg = NMNMreg - 4;
+	bool mpll = Preg == 0x4020;
+	uint32_t oldPval = nvReadMC(dev, Preg);
+	uint32_t NMNM = pv->NM2 << 16 | pv->NM1;
+	uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) |
+			0xc << 28 | pv->log2P << 16;
+	uint32_t saved4600 = 0;
+	/* some cards have different maskc040s */
+	uint32_t maskc040 = ~(3 << 14), savedc040;
+	bool single_stage = !pv->NM2 || pv->N2 == pv->M2;
+
+	if (nvReadMC(dev, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval)
+		return;
+
+	if (Preg == 0x4000)
+		maskc040 = ~0x333;
+	if (Preg == 0x4058)
+		maskc040 = ~(0xc << 24);
+
+	if (mpll) {
+		struct pll_lims pll_lim;
+		uint8_t Pval2;
+
+		if (get_pll_limits(dev, Preg, &pll_lim))
+			return;
+
+		Pval2 = pv->log2P + pll_lim.log2p_bias;
+		if (Pval2 > pll_lim.max_log2p)
+			Pval2 = pll_lim.max_log2p;
+		Pval |= 1 << 28 | Pval2 << 20;
+
+		saved4600 = nvReadMC(dev, 0x4600);
+		nvWriteMC(dev, 0x4600, saved4600 | 8 << 28);
+	}
+	if (single_stage)
+		Pval |= mpll ? 1 << 12 : 1 << 8;
+
+	nvWriteMC(dev, Preg, oldPval | 1 << 28);
+	nvWriteMC(dev, Preg, Pval & ~(4 << 28));
+	if (mpll) {
+		Pval |= 8 << 20;
+		nvWriteMC(dev, 0x4020, Pval & ~(0xc << 28));
+		nvWriteMC(dev, 0x4038, Pval & ~(0xc << 28));
+	}
+
+	savedc040 = nvReadMC(dev, 0xc040);
+	nvWriteMC(dev, 0xc040, savedc040 & maskc040);
+
+	nvWriteMC(dev, NMNMreg, NMNM);
+	if (NMNMreg == 0x4024)
+		nvWriteMC(dev, 0x403c, NMNM);
+
+	nvWriteMC(dev, Preg, Pval);
+	if (mpll) {
+		Pval &= ~(8 << 20);
+		nvWriteMC(dev, 0x4020, Pval);
+		nvWriteMC(dev, 0x4038, Pval);
+		nvWriteMC(dev, 0x4600, saved4600);
+	}
+
+	nvWriteMC(dev, 0xc040, savedc040);
+
+	if (mpll) {
+		nvWriteMC(dev, 0x4020, Pval & ~(1 << 28));
+		nvWriteMC(dev, 0x4038, Pval & ~(1 << 28));
+	}
+}
+
+void
+nouveau_hw_setpll(struct drm_device *dev, uint32_t reg1,
+		  struct nouveau_pll_vals *pv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int cv = dev_priv->vbios->chip_version;
+
+	if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
+	    cv >= 0x40) {
+		if (reg1 > 0x405c)
+			setPLL_double_highregs(dev, reg1, pv);
+		else
+			setPLL_double_lowregs(dev, reg1, pv);
+	} else
+		setPLL_single(dev, reg1, pv);
+}
+
+/*
+ * PLL getting
+ */
+
+static void
+nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1,
+		      uint32_t pll2, struct nouveau_pll_vals *pllvals)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */
+
+	/* log2P is & 0x7 as never more than 7, and nv30/35 only uses 3 bits */
+	pllvals->log2P = (pll1 >> 16) & 0x7;
+	pllvals->N2 = pllvals->M2 = 1;
+
+	if (reg1 <= 0x405c) {
+		pllvals->NM1 = pll2 & 0xffff;
+		/* single stage NVPLL and VPLLs use 1 << 8, MPLL uses 1 << 12 */
+		if (!(pll1 & 0x1100))
+			pllvals->NM2 = pll2 >> 16;
+	} else {
+		pllvals->NM1 = pll1 & 0xffff;
+		if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2)
+			pllvals->NM2 = pll2 & 0xffff;
+		else if (dev_priv->chipset == 0x30 || dev_priv->chipset == 0x35) {
+			pllvals->M1 &= 0xf; /* only 4 bits */
+			if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
+				pllvals->M2 = (pll1 >> 4) & 0x7;
+				pllvals->N2 = ((pll1 >> 21) & 0x18) |
+					      ((pll1 >> 19) & 0x7);
+			}
+		}
+	}
+}
+
+int
+nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype,
+		       struct nouveau_pll_vals *pllvals)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF,
+						    NV_PRAMDAC_MPLL_COEFF,
+						    NV_PRAMDAC_VPLL_COEFF,
+						    NV_RAMDAC_VPLL2 };
+	const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000,
+						    0x4020,
+						    NV_PRAMDAC_VPLL_COEFF,
+						    NV_RAMDAC_VPLL2 };
+	uint32_t reg1, pll1, pll2 = 0;
+	struct pll_lims pll_lim;
+	int ret;
+
+	if (dev_priv->card_type < NV_40)
+		reg1 = nv04_regs[plltype];
+	else
+		reg1 = nv40_regs[plltype];
+
+	pll1 = nvReadMC(dev, reg1);
+
+	if (reg1 <= 0x405c)
+		pll2 = nvReadMC(dev, reg1 + 4);
+	else if (nv_two_reg_pll(dev)) {
+		uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70);
+
+		pll2 = nvReadMC(dev, reg2);
+	}
+
+	if (dev_priv->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
+		uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580);
+
+		/* check whether vpll has been forced into single stage mode */
+		if (reg1 == NV_PRAMDAC_VPLL_COEFF) {
+			if (ramdac580 & NV_RAMDAC_580_VPLL1_ACTIVE)
+				pll2 = 0;
+		} else
+			if (ramdac580 & NV_RAMDAC_580_VPLL2_ACTIVE)
+				pll2 = 0;
+	}
+
+	nouveau_hw_decode_pll(dev, reg1, pll1, pll2, pllvals);
+
+	ret = get_pll_limits(dev, plltype, &pll_lim);
+	if (ret)
+		return ret;
+
+	pllvals->refclk = pll_lim.refclk;
+
+	return 0;
+}
+
+int
+nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv)
+{
+	/* Avoid divide by zero if called at an inappropriate time */
+	if (!pv->M1 || !pv->M2)
+		return 0;
+
+	return pv->N1 * pv->N2 * pv->refclk / (pv->M1 * pv->M2) >> pv->log2P;
+}
+
+int
+nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype)
+{
+	struct nouveau_pll_vals pllvals;
+
+	if (plltype == MPLL && (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) {
+		uint32_t mpllP;
+
+		pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
+		if (!mpllP)
+			mpllP = 4;
+
+		return 400000 / mpllP;
+	} else
+	if (plltype == MPLL && (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) {
+		uint32_t clock;
+
+		pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
+		return clock;
+	}
+
+	nouveau_hw_get_pllvals(dev, plltype, &pllvals);
+
+	return nouveau_hw_pllvals_to_clk(&pllvals);
+}
+
+static void
+nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head)
+{
+	/* the vpll on an unused head can come up with a random value, way
+	 * beyond the pll limits.  for some reason this causes the chip to
+	 * lock up when reading the dac palette regs, so set a valid pll here
+	 * when such a condition detected.  only seen on nv11 to date
+	 */
+
+	struct pll_lims pll_lim;
+	struct nouveau_pll_vals pv;
+	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
+
+	if (get_pll_limits(dev, head ? VPLL2 : VPLL1, &pll_lim))
+		return;
+	nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &pv);
+
+	if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m &&
+	    pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n &&
+	    pv.log2P <= pll_lim.max_log2p)
+		return;
+
+	NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1);
+
+	/* set lowest clock within static limits */
+	pv.M1 = pll_lim.vco1.max_m;
+	pv.N1 = pll_lim.vco1.min_n;
+	pv.log2P = pll_lim.max_usable_log2p;
+	nouveau_hw_setpll(dev, pllreg, &pv);
+}
+
+/*
+ * vga font save/restore
+ */
+
+static void nouveau_vga_font_io(struct drm_device *dev,
+				void __iomem *iovram,
+				bool save, unsigned plane)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned i;
+
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX, 1 << plane);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX, plane);
+	for (i = 0; i < 16384; i++) {
+		if (save) {
+			dev_priv->saved_vga_font[plane][i] =
+					ioread32_native(iovram + i * 4);
+		} else {
+			iowrite32_native(dev_priv->saved_vga_font[plane][i],
+							iovram + i * 4);
+		}
+	}
+}
+
+void
+nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save)
+{
+	uint8_t misc, gr4, gr5, gr6, seq2, seq4;
+	bool graphicsmode;
+	unsigned plane;
+	void __iomem *iovram;
+
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, 0);
+
+	NVSetEnablePalette(dev, 0, true);
+	graphicsmode = NVReadVgaAttr(dev, 0, NV_CIO_AR_MODE_INDEX) & 1;
+	NVSetEnablePalette(dev, 0, false);
+
+	if (graphicsmode) /* graphics mode => framebuffer => no need to save */
+		return;
+
+	NV_INFO(dev, "%sing VGA fonts\n", save ? "Sav" : "Restor");
+
+	/* map first 64KiB of VRAM, holds VGA fonts etc */
+	iovram = ioremap(pci_resource_start(dev->pdev, 1), 65536);
+	if (!iovram) {
+		NV_ERROR(dev, "Failed to map VRAM, "
+					"cannot save/restore VGA fonts.\n");
+		return;
+	}
+
+	if (nv_two_heads(dev))
+		NVBlankScreen(dev, 1, true);
+	NVBlankScreen(dev, 0, true);
+
+	/* save control regs */
+	misc = NVReadPRMVIO(dev, 0, NV_PRMVIO_MISC__READ);
+	seq2 = NVReadVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX);
+	seq4 = NVReadVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX);
+	gr4 = NVReadVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX);
+	gr5 = NVReadVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX);
+	gr6 = NVReadVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX);
+
+	NVWritePRMVIO(dev, 0, NV_PRMVIO_MISC__WRITE, 0x67);
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX, 0x6);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX, 0x0);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX, 0x5);
+
+	/* store font in planes 0..3 */
+	for (plane = 0; plane < 4; plane++)
+		nouveau_vga_font_io(dev, iovram, save, plane);
+
+	/* restore control regs */
+	NVWritePRMVIO(dev, 0, NV_PRMVIO_MISC__WRITE, misc);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_READ_MAP_INDEX, gr4);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_MODE_INDEX, gr5);
+	NVWriteVgaGr(dev, 0, NV_VIO_GX_MISC_INDEX, gr6);
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_PLANE_MASK_INDEX, seq2);
+	NVWriteVgaSeq(dev, 0, NV_VIO_SR_MEM_MODE_INDEX, seq4);
+
+	if (nv_two_heads(dev))
+		NVBlankScreen(dev, 1, false);
+	NVBlankScreen(dev, 0, false);
+
+	iounmap(iovram);
+}
+
+/*
+ * mode state save/load
+ */
+
+static void
+rd_cio_state(struct drm_device *dev, int head,
+	     struct nv04_crtc_reg *crtcstate, int index)
+{
+	crtcstate->CRTC[index] = NVReadVgaCrtc(dev, head, index);
+}
+
+static void
+wr_cio_state(struct drm_device *dev, int head,
+	     struct nv04_crtc_reg *crtcstate, int index)
+{
+	NVWriteVgaCrtc(dev, head, index, crtcstate->CRTC[index]);
+}
+
+static void
+nv_save_state_ramdac(struct drm_device *dev, int head,
+		     struct nv04_mode_state *state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	int i;
+
+	if (dev_priv->card_type >= NV_10)
+		regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC);
+
+	nouveau_hw_get_pllvals(dev, head ? VPLL2 : VPLL1, &regp->pllvals);
+	state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
+	if (nv_two_heads(dev))
+		state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK);
+	if (dev_priv->chipset == 0x11)
+		regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11);
+
+	regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL);
+
+	if (nv_gf4_disp_arch(dev))
+		regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630);
+	if (dev_priv->chipset >= 0x30)
+		regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634);
+
+	regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP);
+	regp->tv_vtotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VTOTAL);
+	regp->tv_vskew = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VSKEW);
+	regp->tv_vsync_delay = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_VSYNC_DELAY);
+	regp->tv_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HTOTAL);
+	regp->tv_hskew = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSKEW);
+	regp->tv_hsync_delay = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY);
+	regp->tv_hsync_delay2 = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY2);
+
+	for (i = 0; i < 7; i++) {
+		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
+		regp->fp_vert_regs[i] = NVReadRAMDAC(dev, head, ramdac_reg);
+		regp->fp_horiz_regs[i] = NVReadRAMDAC(dev, head, ramdac_reg + 0x20);
+	}
+
+	if (nv_gf4_disp_arch(dev)) {
+		regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_FP_DITHER);
+		for (i = 0; i < 3; i++) {
+			regp->dither_regs[i] = NVReadRAMDAC(dev, head, NV_PRAMDAC_850 + i * 4);
+			regp->dither_regs[i + 3] = NVReadRAMDAC(dev, head, NV_PRAMDAC_85C + i * 4);
+		}
+	}
+
+	regp->fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
+	regp->fp_debug_0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_0);
+	if (!nv_gf4_disp_arch(dev) && head == 0) {
+		/* early chips don't allow access to PRAMDAC_TMDS_* without
+		 * the head A FPCLK on (nv11 even locks up) */
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0 &
+			      ~NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK);
+	}
+	regp->fp_debug_1 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1);
+	regp->fp_debug_2 = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_2);
+
+	regp->fp_margin_color = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_MARGIN_COLOR);
+
+	if (nv_gf4_disp_arch(dev))
+		regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0);
+
+	if (dev_priv->card_type == NV_40) {
+		regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20);
+		regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24);
+		regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34);
+
+		for (i = 0; i < 38; i++)
+			regp->ctv_regs[i] = NVReadRAMDAC(dev, head,
+							 NV_PRAMDAC_CTV + 4*i);
+	}
+}
+
+static void
+nv_load_state_ramdac(struct drm_device *dev, int head,
+		     struct nv04_mode_state *state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
+	int i;
+
+	if (dev_priv->card_type >= NV_10)
+		NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
+
+	nouveau_hw_setpll(dev, pllreg, &regp->pllvals);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
+	if (nv_two_heads(dev))
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
+	if (dev_priv->chipset == 0x11)
+		NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
+
+	if (nv_gf4_disp_arch(dev))
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630);
+	if (dev_priv->chipset >= 0x30)
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VTOTAL, regp->tv_vtotal);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VSKEW, regp->tv_vskew);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_VSYNC_DELAY, regp->tv_vsync_delay);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HTOTAL, regp->tv_htotal);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSKEW, regp->tv_hskew);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY, regp->tv_hsync_delay);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_HSYNC_DELAY2, regp->tv_hsync_delay2);
+
+	for (i = 0; i < 7; i++) {
+		uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
+
+		NVWriteRAMDAC(dev, head, ramdac_reg, regp->fp_vert_regs[i]);
+		NVWriteRAMDAC(dev, head, ramdac_reg + 0x20, regp->fp_horiz_regs[i]);
+	}
+
+	if (nv_gf4_disp_arch(dev)) {
+		NVWriteRAMDAC(dev, head, NV_RAMDAC_FP_DITHER, regp->dither);
+		for (i = 0; i < 3; i++) {
+			NVWriteRAMDAC(dev, head, NV_PRAMDAC_850 + i * 4, regp->dither_regs[i]);
+			NVWriteRAMDAC(dev, head, NV_PRAMDAC_85C + i * 4, regp->dither_regs[i + 3]);
+		}
+	}
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_MARGIN_COLOR, regp->fp_margin_color);
+
+	if (nv_gf4_disp_arch(dev))
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0);
+
+	if (dev_priv->card_type == NV_40) {
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20);
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24);
+		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34);
+
+		for (i = 0; i < 38; i++)
+			NVWriteRAMDAC(dev, head,
+				      NV_PRAMDAC_CTV + 4*i, regp->ctv_regs[i]);
+	}
+}
+
+static void
+nv_save_state_vga(struct drm_device *dev, int head,
+		  struct nv04_mode_state *state)
+{
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	int i;
+
+	regp->MiscOutReg = NVReadPRMVIO(dev, head, NV_PRMVIO_MISC__READ);
+
+	for (i = 0; i < 25; i++)
+		rd_cio_state(dev, head, regp, i);
+
+	NVSetEnablePalette(dev, head, true);
+	for (i = 0; i < 21; i++)
+		regp->Attribute[i] = NVReadVgaAttr(dev, head, i);
+	NVSetEnablePalette(dev, head, false);
+
+	for (i = 0; i < 9; i++)
+		regp->Graphics[i] = NVReadVgaGr(dev, head, i);
+
+	for (i = 0; i < 5; i++)
+		regp->Sequencer[i] = NVReadVgaSeq(dev, head, i);
+}
+
+static void
+nv_load_state_vga(struct drm_device *dev, int head,
+		  struct nv04_mode_state *state)
+{
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	int i;
+
+	NVWritePRMVIO(dev, head, NV_PRMVIO_MISC__WRITE, regp->MiscOutReg);
+
+	for (i = 0; i < 5; i++)
+		NVWriteVgaSeq(dev, head, i, regp->Sequencer[i]);
+
+	nv_lock_vga_crtc_base(dev, head, false);
+	for (i = 0; i < 25; i++)
+		wr_cio_state(dev, head, regp, i);
+	nv_lock_vga_crtc_base(dev, head, true);
+
+	for (i = 0; i < 9; i++)
+		NVWriteVgaGr(dev, head, i, regp->Graphics[i]);
+
+	NVSetEnablePalette(dev, head, true);
+	for (i = 0; i < 21; i++)
+		NVWriteVgaAttr(dev, head, i, regp->Attribute[i]);
+	NVSetEnablePalette(dev, head, false);
+}
+
+static void
+nv_save_state_ext(struct drm_device *dev, int head,
+		  struct nv04_mode_state *state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	int i;
+
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_LCD__INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_RPC0_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_RPC1_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_LSR_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_PIXEL_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_HEB__INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX);
+
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_21);
+	if (dev_priv->card_type >= NV_30)
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_47);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_49);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
+
+	if (dev_priv->card_type >= NV_10) {
+		regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830);
+		regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834);
+
+		if (dev_priv->card_type >= NV_30)
+			regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT);
+
+		if (dev_priv->card_type == NV_40)
+			regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850);
+
+		if (nv_two_heads(dev))
+			regp->crtc_eng_ctrl = NVReadCRTC(dev, head, NV_PCRTC_ENGINE_CTRL);
+		regp->cursor_cfg = NVReadCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG);
+	}
+
+	regp->crtc_cfg = NVReadCRTC(dev, head, NV_PCRTC_CONFIG);
+
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
+	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
+	if (dev_priv->card_type >= NV_10) {
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_4B);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
+	}
+	/* NV11 and NV20 don't have this, they stop at 0x52. */
+	if (nv_gf4_disp_arch(dev)) {
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_53);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_54);
+
+		for (i = 0; i < 0x10; i++)
+			regp->CR58[i] = NVReadVgaCrtc5758(dev, head, i);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_59);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_5B);
+
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_85);
+		rd_cio_state(dev, head, regp, NV_CIO_CRE_86);
+	}
+
+	regp->fb_start = NVReadCRTC(dev, head, NV_PCRTC_START);
+}
+
+static void
+nv_load_state_ext(struct drm_device *dev, int head,
+		  struct nv04_mode_state *state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &state->crtc_reg[head];
+	uint32_t reg900;
+	int i;
+
+	if (dev_priv->card_type >= NV_10) {
+		if (nv_two_heads(dev))
+			/* setting ENGINE_CTRL (EC) *must* come before
+			 * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in
+			 * EC that should not be overwritten by writing stale EC
+			 */
+			NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl);
+
+		nvWriteVIDEO(dev, NV_PVIDEO_STOP, 1);
+		nvWriteVIDEO(dev, NV_PVIDEO_INTR_EN, 0);
+		nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(0), 0);
+		nvWriteVIDEO(dev, NV_PVIDEO_OFFSET_BUFF(1), 0);
+		nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(0), dev_priv->fb_available_size - 1);
+		nvWriteVIDEO(dev, NV_PVIDEO_LIMIT(1), dev_priv->fb_available_size - 1);
+		nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(0), dev_priv->fb_available_size - 1);
+		nvWriteVIDEO(dev, NV_PVIDEO_UVPLANE_LIMIT(1), dev_priv->fb_available_size - 1);
+		nvWriteMC(dev, NV_PBUS_POWERCTRL_2, 0);
+
+		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
+		NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830);
+		NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834);
+
+		if (dev_priv->card_type >= NV_30)
+			NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext);
+
+		if (dev_priv->card_type == NV_40) {
+			NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850);
+
+			reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900);
+			if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC)
+				NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000);
+			else
+				NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000);
+		}
+	}
+
+	NVWriteCRTC(dev, head, NV_PCRTC_CONFIG, regp->crtc_cfg);
+
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_RPC0_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_RPC1_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_LSR_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_PIXEL_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_LCD__INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_HEB__INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX);
+	if (dev_priv->card_type >= NV_30)
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_47);
+
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_49);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
+	if (dev_priv->card_type == NV_40)
+		nv_fix_nv40_hw_cursor(dev, head);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX);
+
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
+	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
+	if (dev_priv->card_type >= NV_10) {
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_4B);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
+	}
+	/* NV11 and NV20 stop at 0x52. */
+	if (nv_gf4_disp_arch(dev)) {
+		if (dev_priv->card_type == NV_10) {
+			/* Not waiting for vertical retrace before modifying
+			   CRE_53/CRE_54 causes lockups. */
+			nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8);
+			nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0);
+		}
+
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_53);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_54);
+
+		for (i = 0; i < 0x10; i++)
+			NVWriteVgaCrtc5758(dev, head, i, regp->CR58[i]);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_59);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_5B);
+
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_85);
+		wr_cio_state(dev, head, regp, NV_CIO_CRE_86);
+	}
+
+	NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start);
+
+	/* Setting 1 on this value gives you interrupts for every vblank period. */
+	NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0);
+	NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK);
+}
+
+static void
+nv_save_state_palette(struct drm_device *dev, int head,
+		      struct nv04_mode_state *state)
+{
+	int head_offset = head * NV_PRMDIO_SIZE, i;
+
+	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset,
+				NV_PRMDIO_PIXEL_MASK_MASK);
+	nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
+
+	for (i = 0; i < 768; i++) {
+		state->crtc_reg[head].DAC[i] = nv_rd08(dev,
+				NV_PRMDIO_PALETTE_DATA + head_offset);
+	}
+
+	NVSetEnablePalette(dev, head, false);
+}
+
+void
+nouveau_hw_load_state_palette(struct drm_device *dev, int head,
+			      struct nv04_mode_state *state)
+{
+	int head_offset = head * NV_PRMDIO_SIZE, i;
+
+	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset,
+				NV_PRMDIO_PIXEL_MASK_MASK);
+	nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
+
+	for (i = 0; i < 768; i++) {
+		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA + head_offset,
+				state->crtc_reg[head].DAC[i]);
+	}
+
+	NVSetEnablePalette(dev, head, false);
+}
+
+void nouveau_hw_save_state(struct drm_device *dev, int head,
+			   struct nv04_mode_state *state)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset == 0x11)
+		/* NB: no attempt is made to restore the bad pll later on */
+		nouveau_hw_fix_bad_vpll(dev, head);
+	nv_save_state_ramdac(dev, head, state);
+	nv_save_state_vga(dev, head, state);
+	nv_save_state_palette(dev, head, state);
+	nv_save_state_ext(dev, head, state);
+}
+
+void nouveau_hw_load_state(struct drm_device *dev, int head,
+			   struct nv04_mode_state *state)
+{
+	NVVgaProtect(dev, head, true);
+	nv_load_state_ramdac(dev, head, state);
+	nv_load_state_ext(dev, head, state);
+	nouveau_hw_load_state_palette(dev, head, state);
+	nv_load_state_vga(dev, head, state);
+	NVVgaProtect(dev, head, false);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv40_graph.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_grctx.h"
+
+struct nouveau_channel *
+nv40_graph_channel(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t inst;
+	int i;
+
+	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
+	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
+		return NULL;
+	inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
+
+	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+		struct nouveau_channel *chan = dev_priv->fifos[i];
+
+		if (chan && chan->ramin_grctx &&
+		    chan->ramin_grctx->instance == inst)
+			return chan;
+	}
+
+	return NULL;
+}
+
+int
+nv40_graph_create_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	int ret;
+
+	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
+				     16, NVOBJ_FLAG_ZERO_ALLOC,
+				     &chan->ramin_grctx);
+	if (ret)
+		return ret;
+
+	/* Initialise default context values */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	if (!pgraph->ctxprog) {
+		struct nouveau_grctx ctx = {};
+
+		ctx.dev = chan->dev;
+		ctx.mode = NOUVEAU_GRCTX_VALS;
+		ctx.data = chan->ramin_grctx->gpuobj;
+		nv40_grctx_init(&ctx);
+	} else {
+		nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj);
+	}
+	nv_wo32(dev, chan->ramin_grctx->gpuobj, 0,
+		     chan->ramin_grctx->gpuobj->im_pramin->start);
+	dev_priv->engine.instmem.finish_access(dev);
+	return 0;
+}
+
+void
+nv40_graph_destroy_context(struct nouveau_channel *chan)
+{
+	nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx);
+}
+
+static int
+nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
+{
+	uint32_t old_cp, tv = 1000, tmp;
+	int i;
+
+	old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER);
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+
+	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310);
+	tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
+		      NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp);
+
+	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304);
+	tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp);
+
+	nouveau_wait_for_idle(dev);
+
+	for (i = 0; i < tv; i++) {
+		if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0)
+			break;
+	}
+
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
+
+	if (i == tv) {
+		uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT);
+		NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save);
+		NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n",
+			 ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
+			 ucstat  & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
+		NV_ERROR(dev, "0x40030C = 0x%08x\n",
+			 nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/* Restore the context for a specific channel into PGRAPH */
+int
+nv40_graph_load_context(struct nouveau_channel *chan)
+{
+	struct drm_device *dev = chan->dev;
+	uint32_t inst;
+	int ret;
+
+	if (!chan->ramin_grctx)
+		return -EINVAL;
+	inst = chan->ramin_grctx->instance >> 4;
+
+	ret = nv40_graph_transfer_context(dev, inst, 0);
+	if (ret)
+		return ret;
+
+	/* 0x40032C, no idea of it's exact function.  Could simply be a
+	 * record of the currently active PGRAPH context.  It's currently
+	 * unknown as to what bit 24 does.  The nv ddx has it set, so we will
+	 * set it here too.
+	 */
+	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR,
+		 (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) |
+		  NV40_PGRAPH_CTXCTL_CUR_LOADED);
+	/* 0x32E0 records the instance address of the active FIFO's PGRAPH
+	 * context.  If at any time this doesn't match 0x40032C, you will
+	 * recieve PGRAPH_INTR_CONTEXT_SWITCH
+	 */
+	nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst);
+	return 0;
+}
+
+int
+nv40_graph_unload_context(struct drm_device *dev)
+{
+	uint32_t inst;
+	int ret;
+
+	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
+	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
+		return 0;
+	inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
+
+	ret = nv40_graph_transfer_context(dev, inst, 1);
+
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
+	return ret;
+}
+
+void
+nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			     uint32_t size, uint32_t pitch)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t limit = max(1u, addr + size) - 1;
+
+	if (pitch)
+		addr |= 1;
+
+	switch (dev_priv->chipset) {
+	case 0x44:
+	case 0x4a:
+	case 0x4e:
+		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+		nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+		break;
+
+	case 0x46:
+	case 0x47:
+	case 0x49:
+	case 0x4b:
+		nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch);
+		nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit);
+		nv_wr32(dev, NV47_PGRAPH_TILE(i), addr);
+		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
+		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
+		nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
+		break;
+
+	default:
+		nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch);
+		nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit);
+		nv_wr32(dev, NV20_PGRAPH_TILE(i), addr);
+		nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch);
+		nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit);
+		nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr);
+		break;
+	}
+}
+
+/*
+ * G70		0x47
+ * G71		0x49
+ * NV45		0x48
+ * G72[M]	0x46
+ * G73		0x4b
+ * C51_G7X	0x4c
+ * C51		0x4e
+ */
+int
+nv40_graph_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv =
+		(struct drm_nouveau_private *)dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	uint32_t vramsz;
+	int i, j;
+
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
+			~NV_PMC_ENABLE_PGRAPH);
+	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
+			 NV_PMC_ENABLE_PGRAPH);
+
+	if (nouveau_ctxfw) {
+		nouveau_grctx_prog_load(dev);
+		dev_priv->engine.graph.grctx_size = 175 * 1024;
+	}
+
+	if (!dev_priv->engine.graph.ctxprog) {
+		struct nouveau_grctx ctx = {};
+		uint32_t cp[256];
+
+		ctx.dev = dev;
+		ctx.mode = NOUVEAU_GRCTX_PROG;
+		ctx.data = cp;
+		ctx.ctxprog_max = 256;
+		nv40_grctx_init(&ctx);
+		dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
+
+		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+		for (i = 0; i < ctx.ctxprog_len; i++)
+			nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
+	}
+
+	/* No context present currently */
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
+
+	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
+	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
+
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x401287c0);
+	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xe0de8055);
+	nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00008000);
+	nv_wr32(dev, NV04_PGRAPH_LIMIT_VIOL_PIX, 0x00be3c5f);
+
+	nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
+	nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
+
+	j = nv_rd32(dev, 0x1540) & 0xff;
+	if (j) {
+		for (i = 0; !(j & 1); j >>= 1, i++)
+			;
+		nv_wr32(dev, 0x405000, i);
+	}
+
+	if (dev_priv->chipset == 0x40) {
+		nv_wr32(dev, 0x4009b0, 0x83280fff);
+		nv_wr32(dev, 0x4009b4, 0x000000a0);
+	} else {
+		nv_wr32(dev, 0x400820, 0x83280eff);
+		nv_wr32(dev, 0x400824, 0x000000a0);
+	}
+
+	switch (dev_priv->chipset) {
+	case 0x40:
+	case 0x45:
+		nv_wr32(dev, 0x4009b8, 0x0078e366);
+		nv_wr32(dev, 0x4009bc, 0x0000014c);
+		break;
+	case 0x41:
+	case 0x42: /* pciid also 0x00Cx */
+	/* case 0x0120: XXX (pciid) */
+		nv_wr32(dev, 0x400828, 0x007596ff);
+		nv_wr32(dev, 0x40082c, 0x00000108);
+		break;
+	case 0x43:
+		nv_wr32(dev, 0x400828, 0x0072cb77);
+		nv_wr32(dev, 0x40082c, 0x00000108);
+		break;
+	case 0x44:
+	case 0x46: /* G72 */
+	case 0x4a:
+	case 0x4c: /* G7x-based C51 */
+	case 0x4e:
+		nv_wr32(dev, 0x400860, 0);
+		nv_wr32(dev, 0x400864, 0);
+		break;
+	case 0x47: /* G70 */
+	case 0x49: /* G71 */
+	case 0x4b: /* G73 */
+		nv_wr32(dev, 0x400828, 0x07830610);
+		nv_wr32(dev, 0x40082c, 0x0000016A);
+		break;
+	default:
+		break;
+	}
+
+	nv_wr32(dev, 0x400b38, 0x2ffff800);
+	nv_wr32(dev, 0x400b3c, 0x00006000);
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < pfb->num_tiles; i++)
+		nv40_graph_set_region_tiling(dev, i, 0, 0, 0);
+
+	/* begin RAM config */
+	vramsz = drm_get_resource_len(dev, 0) - 1;
+	switch (dev_priv->chipset) {
+	case 0x40:
+		nv_wr32(dev, 0x4009A4, nv_rd32(dev, NV04_PFB_CFG0));
+		nv_wr32(dev, 0x4009A8, nv_rd32(dev, NV04_PFB_CFG1));
+		nv_wr32(dev, 0x4069A4, nv_rd32(dev, NV04_PFB_CFG0));
+		nv_wr32(dev, 0x4069A8, nv_rd32(dev, NV04_PFB_CFG1));
+		nv_wr32(dev, 0x400820, 0);
+		nv_wr32(dev, 0x400824, 0);
+		nv_wr32(dev, 0x400864, vramsz);
+		nv_wr32(dev, 0x400868, vramsz);
+		break;
+	default:
+		switch (dev_priv->chipset) {
+		case 0x46:
+		case 0x47:
+		case 0x49:
+		case 0x4b:
+			nv_wr32(dev, 0x400DF0, nv_rd32(dev, NV04_PFB_CFG0));
+			nv_wr32(dev, 0x400DF4, nv_rd32(dev, NV04_PFB_CFG1));
+			break;
+		default:
+			nv_wr32(dev, 0x4009F0, nv_rd32(dev, NV04_PFB_CFG0));
+			nv_wr32(dev, 0x4009F4, nv_rd32(dev, NV04_PFB_CFG1));
+			break;
+		}
+		nv_wr32(dev, 0x4069F0, nv_rd32(dev, NV04_PFB_CFG0));
+		nv_wr32(dev, 0x4069F4, nv_rd32(dev, NV04_PFB_CFG1));
+		nv_wr32(dev, 0x400840, 0);
+		nv_wr32(dev, 0x400844, 0);
+		nv_wr32(dev, 0x4008A0, vramsz);
+		nv_wr32(dev, 0x4008A4, vramsz);
+		break;
+	}
+
+	return 0;
+}
+
+void nv40_graph_takedown(struct drm_device *dev)
+{
+	nouveau_grctx_fini(dev);
+}
+
+struct nouveau_pgraph_object_class nv40_graph_grclass[] = {
+	{ 0x0030, false, NULL }, /* null */
+	{ 0x0039, false, NULL }, /* m2mf */
+	{ 0x004a, false, NULL }, /* gdirect */
+	{ 0x009f, false, NULL }, /* imageblit (nv12) */
+	{ 0x008a, false, NULL }, /* ifc */
+	{ 0x0089, false, NULL }, /* sifm */
+	{ 0x3089, false, NULL }, /* sifm (nv40) */
+	{ 0x0062, false, NULL }, /* surf2d */
+	{ 0x3062, false, NULL }, /* surf2d (nv40) */
+	{ 0x0043, false, NULL }, /* rop */
+	{ 0x0012, false, NULL }, /* beta1 */
+	{ 0x0072, false, NULL }, /* beta4 */
+	{ 0x0019, false, NULL }, /* cliprect */
+	{ 0x0044, false, NULL }, /* pattern */
+	{ 0x309e, false, NULL }, /* swzsurf */
+	{ 0x4097, false, NULL }, /* curie (nv40) */
+	{ 0x4497, false, NULL }, /* curie (nv44) */
+	{}
+};
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_state.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright 2005 Stephane Marchesin
+ * Copyright 2008 Stuart Bennett
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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/swab.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "drm_crtc_helper.h"
+#include <linux/vgaarb.h>
+
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nv50_display.h"
+
+static int nouveau_stub_init(struct drm_device *dev) { return 0; }
+static void nouveau_stub_takedown(struct drm_device *dev) {}
+
+static int nouveau_init_engine_ptrs(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+
+	switch (dev_priv->chipset & 0xf0) {
+	case 0x00:
+		engine->instmem.init		= nv04_instmem_init;
+		engine->instmem.takedown	= nv04_instmem_takedown;
+		engine->instmem.suspend		= nv04_instmem_suspend;
+		engine->instmem.resume		= nv04_instmem_resume;
+		engine->instmem.populate	= nv04_instmem_populate;
+		engine->instmem.clear		= nv04_instmem_clear;
+		engine->instmem.bind		= nv04_instmem_bind;
+		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
+		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->mc.init			= nv04_mc_init;
+		engine->mc.takedown		= nv04_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nv04_fb_init;
+		engine->fb.takedown		= nv04_fb_takedown;
+		engine->graph.grclass		= nv04_graph_grclass;
+		engine->graph.init		= nv04_graph_init;
+		engine->graph.takedown		= nv04_graph_takedown;
+		engine->graph.fifo_access	= nv04_graph_fifo_access;
+		engine->graph.channel		= nv04_graph_channel;
+		engine->graph.create_context	= nv04_graph_create_context;
+		engine->graph.destroy_context	= nv04_graph_destroy_context;
+		engine->graph.load_context	= nv04_graph_load_context;
+		engine->graph.unload_context	= nv04_graph_unload_context;
+		engine->fifo.channels		= 16;
+		engine->fifo.init		= nv04_fifo_init;
+		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.cache_flush	= nv04_fifo_cache_flush;
+		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
+		engine->fifo.channel_id		= nv04_fifo_channel_id;
+		engine->fifo.create_context	= nv04_fifo_create_context;
+		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
+		engine->fifo.load_context	= nv04_fifo_load_context;
+		engine->fifo.unload_context	= nv04_fifo_unload_context;
+		break;
+	case 0x10:
+		engine->instmem.init		= nv04_instmem_init;
+		engine->instmem.takedown	= nv04_instmem_takedown;
+		engine->instmem.suspend		= nv04_instmem_suspend;
+		engine->instmem.resume		= nv04_instmem_resume;
+		engine->instmem.populate	= nv04_instmem_populate;
+		engine->instmem.clear		= nv04_instmem_clear;
+		engine->instmem.bind		= nv04_instmem_bind;
+		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
+		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->mc.init			= nv04_mc_init;
+		engine->mc.takedown		= nv04_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nv10_fb_init;
+		engine->fb.takedown		= nv10_fb_takedown;
+		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
+		engine->graph.grclass		= nv10_graph_grclass;
+		engine->graph.init		= nv10_graph_init;
+		engine->graph.takedown		= nv10_graph_takedown;
+		engine->graph.channel		= nv10_graph_channel;
+		engine->graph.create_context	= nv10_graph_create_context;
+		engine->graph.destroy_context	= nv10_graph_destroy_context;
+		engine->graph.fifo_access	= nv04_graph_fifo_access;
+		engine->graph.load_context	= nv10_graph_load_context;
+		engine->graph.unload_context	= nv10_graph_unload_context;
+		engine->graph.set_region_tiling	= nv10_graph_set_region_tiling;
+		engine->fifo.channels		= 32;
+		engine->fifo.init		= nv10_fifo_init;
+		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.cache_flush	= nv04_fifo_cache_flush;
+		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
+		engine->fifo.create_context	= nv10_fifo_create_context;
+		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.load_context	= nv10_fifo_load_context;
+		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		break;
+	case 0x20:
+		engine->instmem.init		= nv04_instmem_init;
+		engine->instmem.takedown	= nv04_instmem_takedown;
+		engine->instmem.suspend		= nv04_instmem_suspend;
+		engine->instmem.resume		= nv04_instmem_resume;
+		engine->instmem.populate	= nv04_instmem_populate;
+		engine->instmem.clear		= nv04_instmem_clear;
+		engine->instmem.bind		= nv04_instmem_bind;
+		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
+		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->mc.init			= nv04_mc_init;
+		engine->mc.takedown		= nv04_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nv10_fb_init;
+		engine->fb.takedown		= nv10_fb_takedown;
+		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
+		engine->graph.grclass		= nv20_graph_grclass;
+		engine->graph.init		= nv20_graph_init;
+		engine->graph.takedown		= nv20_graph_takedown;
+		engine->graph.channel		= nv10_graph_channel;
+		engine->graph.create_context	= nv20_graph_create_context;
+		engine->graph.destroy_context	= nv20_graph_destroy_context;
+		engine->graph.fifo_access	= nv04_graph_fifo_access;
+		engine->graph.load_context	= nv20_graph_load_context;
+		engine->graph.unload_context	= nv20_graph_unload_context;
+		engine->graph.set_region_tiling	= nv20_graph_set_region_tiling;
+		engine->fifo.channels		= 32;
+		engine->fifo.init		= nv10_fifo_init;
+		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.cache_flush	= nv04_fifo_cache_flush;
+		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
+		engine->fifo.create_context	= nv10_fifo_create_context;
+		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.load_context	= nv10_fifo_load_context;
+		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		break;
+	case 0x30:
+		engine->instmem.init		= nv04_instmem_init;
+		engine->instmem.takedown	= nv04_instmem_takedown;
+		engine->instmem.suspend		= nv04_instmem_suspend;
+		engine->instmem.resume		= nv04_instmem_resume;
+		engine->instmem.populate	= nv04_instmem_populate;
+		engine->instmem.clear		= nv04_instmem_clear;
+		engine->instmem.bind		= nv04_instmem_bind;
+		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
+		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->mc.init			= nv04_mc_init;
+		engine->mc.takedown		= nv04_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nv10_fb_init;
+		engine->fb.takedown		= nv10_fb_takedown;
+		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
+		engine->graph.grclass		= nv30_graph_grclass;
+		engine->graph.init		= nv30_graph_init;
+		engine->graph.takedown		= nv20_graph_takedown;
+		engine->graph.fifo_access	= nv04_graph_fifo_access;
+		engine->graph.channel		= nv10_graph_channel;
+		engine->graph.create_context	= nv20_graph_create_context;
+		engine->graph.destroy_context	= nv20_graph_destroy_context;
+		engine->graph.load_context	= nv20_graph_load_context;
+		engine->graph.unload_context	= nv20_graph_unload_context;
+		engine->graph.set_region_tiling	= nv20_graph_set_region_tiling;
+		engine->fifo.channels		= 32;
+		engine->fifo.init		= nv10_fifo_init;
+		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.cache_flush	= nv04_fifo_cache_flush;
+		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
+		engine->fifo.create_context	= nv10_fifo_create_context;
+		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
+		engine->fifo.load_context	= nv10_fifo_load_context;
+		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		break;
+	case 0x40:
+	case 0x60:
+		engine->instmem.init		= nv04_instmem_init;
+		engine->instmem.takedown	= nv04_instmem_takedown;
+		engine->instmem.suspend		= nv04_instmem_suspend;
+		engine->instmem.resume		= nv04_instmem_resume;
+		engine->instmem.populate	= nv04_instmem_populate;
+		engine->instmem.clear		= nv04_instmem_clear;
+		engine->instmem.bind		= nv04_instmem_bind;
+		engine->instmem.unbind		= nv04_instmem_unbind;
+		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
+		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->mc.init			= nv40_mc_init;
+		engine->mc.takedown		= nv40_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nv40_fb_init;
+		engine->fb.takedown		= nv40_fb_takedown;
+		engine->fb.set_region_tiling	= nv40_fb_set_region_tiling;
+		engine->graph.grclass		= nv40_graph_grclass;
+		engine->graph.init		= nv40_graph_init;
+		engine->graph.takedown		= nv40_graph_takedown;
+		engine->graph.fifo_access	= nv04_graph_fifo_access;
+		engine->graph.channel		= nv40_graph_channel;
+		engine->graph.create_context	= nv40_graph_create_context;
+		engine->graph.destroy_context	= nv40_graph_destroy_context;
+		engine->graph.load_context	= nv40_graph_load_context;
+		engine->graph.unload_context	= nv40_graph_unload_context;
+		engine->graph.set_region_tiling	= nv40_graph_set_region_tiling;
+		engine->fifo.channels		= 32;
+		engine->fifo.init		= nv40_fifo_init;
+		engine->fifo.takedown		= nouveau_stub_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.cache_flush	= nv04_fifo_cache_flush;
+		engine->fifo.cache_pull		= nv04_fifo_cache_pull;
+		engine->fifo.channel_id		= nv10_fifo_channel_id;
+		engine->fifo.create_context	= nv40_fifo_create_context;
+		engine->fifo.destroy_context	= nv40_fifo_destroy_context;
+		engine->fifo.load_context	= nv40_fifo_load_context;
+		engine->fifo.unload_context	= nv40_fifo_unload_context;
+		break;
+	case 0x50:
+	case 0x80: /* gotta love NVIDIA's consistency.. */
+	case 0x90:
+	case 0xA0:
+		engine->instmem.init		= nv50_instmem_init;
+		engine->instmem.takedown	= nv50_instmem_takedown;
+		engine->instmem.suspend		= nv50_instmem_suspend;
+		engine->instmem.resume		= nv50_instmem_resume;
+		engine->instmem.populate	= nv50_instmem_populate;
+		engine->instmem.clear		= nv50_instmem_clear;
+		engine->instmem.bind		= nv50_instmem_bind;
+		engine->instmem.unbind		= nv50_instmem_unbind;
+		engine->instmem.prepare_access	= nv50_instmem_prepare_access;
+		engine->instmem.finish_access	= nv50_instmem_finish_access;
+		engine->mc.init			= nv50_mc_init;
+		engine->mc.takedown		= nv50_mc_takedown;
+		engine->timer.init		= nv04_timer_init;
+		engine->timer.read		= nv04_timer_read;
+		engine->timer.takedown		= nv04_timer_takedown;
+		engine->fb.init			= nouveau_stub_init;
+		engine->fb.takedown		= nouveau_stub_takedown;
+		engine->graph.grclass		= nv50_graph_grclass;
+		engine->graph.init		= nv50_graph_init;
+		engine->graph.takedown		= nv50_graph_takedown;
+		engine->graph.fifo_access	= nv50_graph_fifo_access;
+		engine->graph.channel		= nv50_graph_channel;
+		engine->graph.create_context	= nv50_graph_create_context;
+		engine->graph.destroy_context	= nv50_graph_destroy_context;
+		engine->graph.load_context	= nv50_graph_load_context;
+		engine->graph.unload_context	= nv50_graph_unload_context;
+		engine->fifo.channels		= 128;
+		engine->fifo.init		= nv50_fifo_init;
+		engine->fifo.takedown		= nv50_fifo_takedown;
+		engine->fifo.disable		= nv04_fifo_disable;
+		engine->fifo.enable		= nv04_fifo_enable;
+		engine->fifo.reassign		= nv04_fifo_reassign;
+		engine->fifo.channel_id		= nv50_fifo_channel_id;
+		engine->fifo.create_context	= nv50_fifo_create_context;
+		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
+		engine->fifo.load_context	= nv50_fifo_load_context;
+		engine->fifo.unload_context	= nv50_fifo_unload_context;
+		break;
+	default:
+		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
+		return 1;
+	}
+
+	return 0;
+}
+
+static unsigned int
+nouveau_vga_set_decode(void *priv, bool state)
+{
+	struct drm_device *dev = priv;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset >= 0x40)
+		nv_wr32(dev, 0x88054, state);
+	else
+		nv_wr32(dev, 0x1854, state);
+
+	if (state)
+		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
+		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+	else
+		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
+}
+
+static int
+nouveau_card_init_channel(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gpuobj;
+	int ret;
+
+	ret = nouveau_channel_alloc(dev, &dev_priv->channel,
+				    (struct drm_file *)-2,
+				    NvDmaFB, NvDmaTT);
+	if (ret)
+		return ret;
+
+	gpuobj = NULL;
+	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
+				     0, nouveau_mem_fb_amount(dev),
+				     NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,
+				     &gpuobj);
+	if (ret)
+		goto out_err;
+
+	ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM,
+				     gpuobj, NULL);
+	if (ret)
+		goto out_err;
+
+	gpuobj = NULL;
+	ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0,
+					  dev_priv->gart_info.aper_size,
+					  NV_DMA_ACCESS_RW, &gpuobj, NULL);
+	if (ret)
+		goto out_err;
+
+	ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART,
+				     gpuobj, NULL);
+	if (ret)
+		goto out_err;
+
+	return 0;
+out_err:
+	nouveau_gpuobj_del(dev, &gpuobj);
+	nouveau_channel_free(dev_priv->channel);
+	dev_priv->channel = NULL;
+	return ret;
+}
+
+int
+nouveau_card_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine;
+	int ret;
+
+	NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
+
+	if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
+		return 0;
+
+	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
+
+	/* Initialise internal driver API hooks */
+	ret = nouveau_init_engine_ptrs(dev);
+	if (ret)
+		goto out;
+	engine = &dev_priv->engine;
+	dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
+
+	/* Parse BIOS tables / Run init tables if card not POSTed */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = nouveau_bios_init(dev);
+		if (ret)
+			goto out;
+	}
+
+	ret = nouveau_gpuobj_early_init(dev);
+	if (ret)
+		goto out_bios;
+
+	/* Initialise instance memory, must happen before mem_init so we
+	 * know exactly how much VRAM we're able to use for "normal"
+	 * purposes.
+	 */
+	ret = engine->instmem.init(dev);
+	if (ret)
+		goto out_gpuobj_early;
+
+	/* Setup the memory manager */
+	ret = nouveau_mem_init(dev);
+	if (ret)
+		goto out_instmem;
+
+	ret = nouveau_gpuobj_init(dev);
+	if (ret)
+		goto out_mem;
+
+	/* PMC */
+	ret = engine->mc.init(dev);
+	if (ret)
+		goto out_gpuobj;
+
+	/* PTIMER */
+	ret = engine->timer.init(dev);
+	if (ret)
+		goto out_mc;
+
+	/* PFB */
+	ret = engine->fb.init(dev);
+	if (ret)
+		goto out_timer;
+
+	if (nouveau_noaccel)
+		engine->graph.accel_blocked = true;
+	else {
+		/* PGRAPH */
+		ret = engine->graph.init(dev);
+		if (ret)
+			goto out_fb;
+
+		/* PFIFO */
+		ret = engine->fifo.init(dev);
+		if (ret)
+			goto out_graph;
+	}
+
+	/* this call irq_preinstall, register irq handler and
+	 * call irq_postinstall
+	 */
+	ret = drm_irq_install(dev);
+	if (ret)
+		goto out_fifo;
+
+	ret = drm_vblank_init(dev, 0);
+	if (ret)
+		goto out_irq;
+
+	/* what about PVIDEO/PCRTC/PRAMDAC etc? */
+
+	if (!engine->graph.accel_blocked) {
+		ret = nouveau_card_init_channel(dev);
+		if (ret)
+			goto out_irq;
+	}
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		if (dev_priv->card_type >= NV_50)
+			ret = nv50_display_create(dev);
+		else
+			ret = nv04_display_create(dev);
+		if (ret)
+			goto out_irq;
+	}
+
+	ret = nouveau_backlight_init(dev);
+	if (ret)
+		NV_ERROR(dev, "Error %d registering backlight\n", ret);
+
+	dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_helper_initial_config(dev);
+
+	return 0;
+
+out_irq:
+	drm_irq_uninstall(dev);
+out_fifo:
+	if (!nouveau_noaccel)
+		engine->fifo.takedown(dev);
+out_graph:
+	if (!nouveau_noaccel)
+		engine->graph.takedown(dev);
+out_fb:
+	engine->fb.takedown(dev);
+out_timer:
+	engine->timer.takedown(dev);
+out_mc:
+	engine->mc.takedown(dev);
+out_gpuobj:
+	nouveau_gpuobj_takedown(dev);
+out_mem:
+	nouveau_mem_close(dev);
+out_instmem:
+	engine->instmem.takedown(dev);
+out_gpuobj_early:
+	nouveau_gpuobj_late_takedown(dev);
+out_bios:
+	nouveau_bios_takedown(dev);
+out:
+	vga_client_register(dev->pdev, NULL, NULL, NULL);
+	return ret;
+}
+
+static void nouveau_card_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+
+	NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
+
+	if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
+		nouveau_backlight_exit(dev);
+
+		if (dev_priv->channel) {
+			nouveau_channel_free(dev_priv->channel);
+			dev_priv->channel = NULL;
+		}
+
+		if (!nouveau_noaccel) {
+			engine->fifo.takedown(dev);
+			engine->graph.takedown(dev);
+		}
+		engine->fb.takedown(dev);
+		engine->timer.takedown(dev);
+		engine->mc.takedown(dev);
+
+		mutex_lock(&dev->struct_mutex);
+		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
+		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
+		mutex_unlock(&dev->struct_mutex);
+		nouveau_sgdma_takedown(dev);
+
+		nouveau_gpuobj_takedown(dev);
+		nouveau_mem_close(dev);
+		engine->instmem.takedown(dev);
+
+		if (drm_core_check_feature(dev, DRIVER_MODESET))
+			drm_irq_uninstall(dev);
+
+		nouveau_gpuobj_late_takedown(dev);
+		nouveau_bios_takedown(dev);
+
+		vga_client_register(dev->pdev, NULL, NULL, NULL);
+
+		dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
+	}
+}
+
+/* here a client dies, release the stuff that was allocated for its
+ * file_priv */
+void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+	nouveau_channel_cleanup(dev, file_priv);
+}
+
+/* first module load, setup the mmio/fb mapping */
+/* KMS: we need mmio at load time, not when the first drm client opens. */
+int nouveau_firstopen(struct drm_device *dev)
+{
+	return 0;
+}
+
+/* if we have an OF card, copy vbios to RAMIN */
+static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev)
+{
+#if defined(__powerpc__)
+	int size, i;
+	const uint32_t *bios;
+	struct device_node *dn = pci_device_to_OF_node(dev->pdev);
+	if (!dn) {
+		NV_INFO(dev, "Unable to get the OF node\n");
+		return;
+	}
+
+	bios = of_get_property(dn, "NVDA,BMP", &size);
+	if (bios) {
+		for (i = 0; i < size; i += 4)
+			nv_wi32(dev, i, bios[i/4]);
+		NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size);
+	} else {
+		NV_INFO(dev, "Unable to get the OF bios\n");
+	}
+#endif
+}
+
+static void nouveau_apply_noaccel_quirks (struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	if (nouveau_noaccel == -1) {
+		/* If not specified, noaccel should default off */
+		nouveau_noaccel = 0;
+
+		/* MacBook Pro laptops with 9600GT cards hang with acceleration */
+		/* See https://bugs.launchpad.net/bugs/546393 */
+		if ((dev->pdev->device == 0x0647) &&
+		    (dev->pdev->subsystem_vendor == 0x106b)) {
+			nouveau_noaccel = 1;
+			NV_INFO(dev, "Detected MacBook Pro 9600GT chip. "
+				 "Disabling acceleration\n");
+		}
+		/* At least two of the three nv20 cards hang with acceleration */
+		/* See https://bugs.launchpad.net/bugs/544088 */
+		if (dev_priv->chipset == 0x20) {
+			nouveau_noaccel = 1;
+			NV_INFO(dev, "Detected NV20 (GeForce 3) chip. "
+				 "Disabling acceleration\n");
+		}
+		/* GeForce 6100 cards also hang with acceleration */
+		/* See https://bugs.launchpad.net/bugs/542950 */
+		if (dev->pdev->device == 0x0242) {
+			nouveau_noaccel = 1;
+			NV_INFO(dev, "Detected GeForce 6100 chip. "
+				 "Disabling acceleration\n");
+		}
+	}
+}
+
+int nouveau_load(struct drm_device *dev, unsigned long flags)
+{
+	struct drm_nouveau_private *dev_priv;
+	uint32_t reg0;
+	resource_size_t mmio_start_offs;
+
+	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+	if (!dev_priv)
+		return -ENOMEM;
+	dev->dev_private = dev_priv;
+	dev_priv->dev = dev;
+
+	dev_priv->flags = flags & NOUVEAU_FLAGS;
+	dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
+
+	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
+		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
+
+	dev_priv->acpi_dsm = nouveau_dsm_probe(dev);
+
+	if (dev_priv->acpi_dsm)
+		nouveau_hybrid_setup(dev);
+
+	dev_priv->wq = create_workqueue("nouveau");
+	if (!dev_priv->wq)
+		return -EINVAL;
+
+	/* resource 0 is mmio regs */
+	/* resource 1 is linear FB */
+	/* resource 2 is RAMIN (mmio regs + 0x1000000) */
+	/* resource 6 is bios */
+
+	/* map the mmio regs */
+	mmio_start_offs = pci_resource_start(dev->pdev, 0);
+	dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000);
+	if (!dev_priv->mmio) {
+		NV_ERROR(dev, "Unable to initialize the mmio mapping. "
+			 "Please report your setup to " DRIVER_EMAIL "\n");
+		return -EINVAL;
+	}
+	NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
+					(unsigned long long)mmio_start_offs);
+
+#ifdef __BIG_ENDIAN
+	/* Put the card in BE mode if it's not */
+	if (nv_rd32(dev, NV03_PMC_BOOT_1))
+		nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001);
+
+	DRM_MEMORYBARRIER();
+#endif
+
+	/* Time to determine the card architecture */
+	reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
+
+	/* We're dealing with >=NV10 */
+	if ((reg0 & 0x0f000000) > 0) {
+		/* Bit 27-20 contain the architecture in hex */
+		dev_priv->chipset = (reg0 & 0xff00000) >> 20;
+	/* NV04 or NV05 */
+	} else if ((reg0 & 0xff00fff0) == 0x20004000) {
+		if (reg0 & 0x00f00000)
+			dev_priv->chipset = 0x05;
+		else
+			dev_priv->chipset = 0x04;
+	} else
+		dev_priv->chipset = 0xff;
+
+	switch (dev_priv->chipset & 0xf0) {
+	case 0x00:
+	case 0x10:
+	case 0x20:
+	case 0x30:
+		dev_priv->card_type = dev_priv->chipset & 0xf0;
+		break;
+	case 0x40:
+	case 0x60:
+		dev_priv->card_type = NV_40;
+		break;
+	case 0x50:
+	case 0x80:
+	case 0x90:
+	case 0xa0:
+		dev_priv->card_type = NV_50;
+		break;
+	default:
+		NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0);
+		return -EINVAL;
+	}
+
+	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
+		dev_priv->card_type, reg0);
+
+	/* map larger RAMIN aperture on NV40 cards */
+	dev_priv->ramin  = NULL;
+	if (dev_priv->card_type >= NV_40) {
+		int ramin_bar = 2;
+		if (pci_resource_len(dev->pdev, ramin_bar) == 0)
+			ramin_bar = 3;
+
+		dev_priv->ramin_size = pci_resource_len(dev->pdev, ramin_bar);
+		dev_priv->ramin = ioremap(
+				pci_resource_start(dev->pdev, ramin_bar),
+				dev_priv->ramin_size);
+		if (!dev_priv->ramin) {
+			NV_ERROR(dev, "Failed to init RAMIN mapping, "
+				      "limited instance memory available\n");
+		}
+	}
+
+	/* On older cards (or if the above failed), create a map covering
+	 * the BAR0 PRAMIN aperture */
+	if (!dev_priv->ramin) {
+		dev_priv->ramin_size = 1 * 1024 * 1024;
+		dev_priv->ramin = ioremap(mmio_start_offs + NV_RAMIN,
+							dev_priv->ramin_size);
+		if (!dev_priv->ramin) {
+			NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n");
+			return -ENOMEM;
+		}
+	}
+
+	nouveau_OF_copy_vbios_to_ramin(dev);
+
+	/* Special flags */
+	if (dev->pci_device == 0x01a0)
+		dev_priv->flags |= NV_NFORCE;
+	else if (dev->pci_device == 0x01f0)
+		dev_priv->flags |= NV_NFORCE2;
+
+	/* Apply noaccel quirks */
+	nouveau_apply_noaccel_quirks(dev);
+
+	/* For kernel modesetting, init card now and bring up fbcon */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		int ret = nouveau_card_init(dev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void nouveau_close(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/* In the case of an error dev_priv may not be allocated yet */
+	if (dev_priv)
+		nouveau_card_takedown(dev);
+}
+
+/* KMS: we need mmio at load time, not when the first drm client opens. */
+void nouveau_lastclose(struct drm_device *dev)
+{
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	nouveau_close(dev);
+}
+
+int nouveau_unload(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		if (dev_priv->card_type >= NV_50)
+			nv50_display_destroy(dev);
+		else
+			nv04_display_destroy(dev);
+		nouveau_close(dev);
+	}
+
+	iounmap(dev_priv->mmio);
+	iounmap(dev_priv->ramin);
+
+	kfree(dev_priv);
+	dev->dev_private = NULL;
+	return 0;
+}
+
+int
+nouveau_ioctl_card_init(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	return nouveau_card_init(dev);
+}
+
+int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
+						struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_getparam *getparam = data;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	switch (getparam->param) {
+	case NOUVEAU_GETPARAM_CHIPSET_ID:
+		getparam->value = dev_priv->chipset;
+		break;
+	case NOUVEAU_GETPARAM_PCI_VENDOR:
+		getparam->value = dev->pci_vendor;
+		break;
+	case NOUVEAU_GETPARAM_PCI_DEVICE:
+		getparam->value = dev->pci_device;
+		break;
+	case NOUVEAU_GETPARAM_BUS_TYPE:
+		if (drm_device_is_agp(dev))
+			getparam->value = NV_AGP;
+		else if (drm_device_is_pcie(dev))
+			getparam->value = NV_PCIE;
+		else
+			getparam->value = NV_PCI;
+		break;
+	case NOUVEAU_GETPARAM_FB_PHYSICAL:
+		getparam->value = dev_priv->fb_phys;
+		break;
+	case NOUVEAU_GETPARAM_AGP_PHYSICAL:
+		getparam->value = dev_priv->gart_info.aper_base;
+		break;
+	case NOUVEAU_GETPARAM_PCI_PHYSICAL:
+		if (dev->sg) {
+			getparam->value = (unsigned long)dev->sg->virtual;
+		} else {
+			NV_ERROR(dev, "Requested PCIGART address, "
+					"while no PCIGART was created\n");
+			return -EINVAL;
+		}
+		break;
+	case NOUVEAU_GETPARAM_FB_SIZE:
+		getparam->value = dev_priv->fb_available_size;
+		break;
+	case NOUVEAU_GETPARAM_AGP_SIZE:
+		getparam->value = dev_priv->gart_info.aper_size;
+		break;
+	case NOUVEAU_GETPARAM_VM_VRAM_BASE:
+		getparam->value = dev_priv->vm_vram_base;
+		break;
+	case NOUVEAU_GETPARAM_GRAPH_UNITS:
+		/* NV40 and NV50 versions are quite different, but register
+		 * address is the same. User is supposed to know the card
+		 * family anyway... */
+		if (dev_priv->chipset >= 0x40) {
+			getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS);
+			break;
+		}
+		/* FALLTHRU */
+	default:
+		NV_ERROR(dev, "unknown parameter %lld\n", getparam->param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+nouveau_ioctl_setparam(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct drm_nouveau_setparam *setparam = data;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	switch (setparam->param) {
+	default:
+		NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Wait until (value(reg) & mask) == val, up until timeout has hit */
+bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout,
+			uint32_t reg, uint32_t mask, uint32_t val)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	uint64_t start = ptimer->read(dev);
+
+	do {
+		if ((nv_rd32(dev, reg) & mask) == val)
+			return true;
+	} while (ptimer->read(dev) - start < timeout);
+
+	return false;
+}
+
+/* Waits for PGRAPH to go completely idle */
+bool nouveau_wait_for_idle(struct drm_device *dev)
+{
+	if (!nv_wait(NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) {
+		NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n",
+			 nv_rd32(dev, NV04_PGRAPH_STATUS));
+		return false;
+	}
+
+	return true;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2005 Stephane Marchesin.
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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/console.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+#include "nouveau_fb.h"
+#include "nouveau_fbcon.h"
+#include "nv50_display.h"
+
+#include "drm_pciids.h"
+
+MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)");
+int nouveau_ctxfw = 0;
+module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
+
+MODULE_PARM_DESC(noagp, "Disable AGP");
+int nouveau_noagp;
+module_param_named(noagp, nouveau_noagp, int, 0400);
+
+MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
+static int nouveau_modeset = -1; /* kms */
+module_param_named(modeset, nouveau_modeset, int, 0400);
+
+MODULE_PARM_DESC(vbios, "Override default VBIOS location");
+char *nouveau_vbios;
+module_param_named(vbios, nouveau_vbios, charp, 0400);
+
+MODULE_PARM_DESC(vram_pushbuf, "Force DMA push buffers to be in VRAM");
+int nouveau_vram_pushbuf;
+module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
+
+MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
+int nouveau_vram_notify = 1;
+module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
+
+MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
+int nouveau_duallink = 1;
+module_param_named(duallink, nouveau_duallink, int, 0400);
+
+MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)");
+int nouveau_uscript_lvds = -1;
+module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400);
+
+MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)");
+int nouveau_uscript_tmds = -1;
+module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
+
+MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
+int nouveau_ignorelid = 0;
+module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
+
+MODULE_PARM_DESC(noagp, "Disable all acceleration");
+int nouveau_noaccel = -1;
+module_param_named(noaccel, nouveau_noaccel, int, 0400);
+
+MODULE_PARM_DESC(noagp, "Disable fbcon acceleration");
+int nouveau_nofbaccel = 0;
+module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
+
+MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
+		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
+		 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
+		 "\t\tDefault: PAL\n"
+		 "\t\t*NOTE* Ignored for cards with external TV encoders.");
+char *nouveau_tv_norm;
+module_param_named(tv_norm, nouveau_tv_norm, charp, 0400);
+
+MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n"
+		"\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n"
+		"\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n"
+		"\t\t0x100 vgaattr, 0x200 EVO (G80+). ");
+int nouveau_reg_debug;
+module_param_named(reg_debug, nouveau_reg_debug, int, 0600);
+
+int nouveau_fbpercrtc;
+#if 0
+module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
+#endif
+
+static struct pci_device_id pciidlist[] = {
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+		.class = PCI_BASE_CLASS_DISPLAY << 16,
+		.class_mask  = 0xff << 16,
+	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA_SGS, PCI_ANY_ID),
+		.class = PCI_BASE_CLASS_DISPLAY << 16,
+		.class_mask  = 0xff << 16,
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(pci, pciidlist);
+
+static struct drm_driver driver;
+
+static int __devinit
+nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_dev(pdev, ent, &driver);
+}
+
+static void
+nouveau_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_put_dev(dev);
+}
+
+static int
+nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+	struct nouveau_channel *chan;
+	struct drm_crtc *crtc;
+	uint32_t fbdev_flags;
+	int ret, i;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -ENODEV;
+
+	if (pm_state.event == PM_EVENT_PRETHAW)
+		return 0;
+
+	fbdev_flags = dev_priv->fbdev_info->flags;
+	dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_framebuffer *nouveau_fb;
+
+		nouveau_fb = nouveau_framebuffer(crtc->fb);
+		if (!nouveau_fb || !nouveau_fb->nvbo)
+			continue;
+
+		nouveau_bo_unpin(nouveau_fb->nvbo);
+	}
+
+	NV_INFO(dev, "Evicting buffers...\n");
+	ttm_bo_evict_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
+
+	NV_INFO(dev, "Idling channels...\n");
+	for (i = 0; i < pfifo->channels; i++) {
+		struct nouveau_fence *fence = NULL;
+
+		chan = dev_priv->fifos[i];
+		if (!chan || (dev_priv->card_type >= NV_50 &&
+			      chan == dev_priv->fifos[0]))
+			continue;
+
+		ret = nouveau_fence_new(chan, &fence, true);
+		if (ret == 0) {
+			ret = nouveau_fence_wait(fence, NULL, false, false);
+			nouveau_fence_unref((void *)&fence);
+		}
+
+		if (ret) {
+			NV_ERROR(dev, "Failed to idle channel %d for suspend\n",
+				 chan->id);
+		}
+	}
+
+	pgraph->fifo_access(dev, false);
+	nouveau_wait_for_idle(dev);
+	pfifo->reassign(dev, false);
+	pfifo->disable(dev);
+	pfifo->unload_context(dev);
+	pgraph->unload_context(dev);
+
+	NV_INFO(dev, "Suspending GPU objects...\n");
+	ret = nouveau_gpuobj_suspend(dev);
+	if (ret) {
+		NV_ERROR(dev, "... failed: %d\n", ret);
+		goto out_abort;
+	}
+
+	ret = pinstmem->suspend(dev);
+	if (ret) {
+		NV_ERROR(dev, "... failed: %d\n", ret);
+		nouveau_gpuobj_suspend_cleanup(dev);
+		goto out_abort;
+	}
+
+	NV_INFO(dev, "And we're gone!\n");
+	pci_save_state(pdev);
+	if (pm_state.event == PM_EVENT_SUSPEND) {
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, PCI_D3hot);
+	}
+
+	acquire_console_sem();
+	fb_set_suspend(dev_priv->fbdev_info, 1);
+	release_console_sem();
+	dev_priv->fbdev_info->flags = fbdev_flags;
+	return 0;
+
+out_abort:
+	NV_INFO(dev, "Re-enabling acceleration..\n");
+	pfifo->enable(dev);
+	pfifo->reassign(dev, true);
+	pgraph->fifo_access(dev, true);
+	return ret;
+}
+
+static int
+nouveau_pci_resume(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+	struct drm_crtc *crtc;
+	uint32_t fbdev_flags;
+	int ret, i;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -ENODEV;
+
+	fbdev_flags = dev_priv->fbdev_info->flags;
+	dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
+
+	NV_INFO(dev, "We're back, enabling device...\n");
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	if (pci_enable_device(pdev))
+		return -1;
+	pci_set_master(dev->pdev);
+
+	NV_INFO(dev, "POSTing device...\n");
+	ret = nouveau_run_vbios_init(dev);
+	if (ret)
+		return ret;
+
+	if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
+		ret = nouveau_mem_init_agp(dev);
+		if (ret) {
+			NV_ERROR(dev, "error reinitialising AGP: %d\n", ret);
+			return ret;
+		}
+	}
+
+	NV_INFO(dev, "Reinitialising engines...\n");
+	engine->instmem.resume(dev);
+	engine->mc.init(dev);
+	engine->timer.init(dev);
+	engine->fb.init(dev);
+	engine->graph.init(dev);
+	engine->fifo.init(dev);
+
+	NV_INFO(dev, "Restoring GPU objects...\n");
+	nouveau_gpuobj_resume(dev);
+
+	nouveau_irq_postinstall(dev);
+
+	/* Re-write SKIPS, they'll have been lost over the suspend */
+	if (nouveau_vram_pushbuf) {
+		struct nouveau_channel *chan;
+		int j;
+
+		for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+			chan = dev_priv->fifos[i];
+			if (!chan || !chan->pushbuf_bo)
+				continue;
+
+			for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
+				nouveau_bo_wr32(chan->pushbuf_bo, i, 0);
+		}
+	}
+
+	NV_INFO(dev, "Restoring mode...\n");
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_framebuffer *nouveau_fb;
+
+		nouveau_fb = nouveau_framebuffer(crtc->fb);
+		if (!nouveau_fb || !nouveau_fb->nvbo)
+			continue;
+
+		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
+	}
+
+	if (dev_priv->card_type < NV_50) {
+		nv04_display_restore(dev);
+		NVLockVgaCrtcs(dev, false);
+	} else
+		nv50_display_init(dev);
+
+	/* Force CLUT to get re-loaded during modeset */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+		nv_crtc->lut.depth = 0;
+	}
+
+	acquire_console_sem();
+	fb_set_suspend(dev_priv->fbdev_info, 0);
+	release_console_sem();
+
+	nouveau_fbcon_zfill(dev);
+
+	drm_helper_resume_force_mode(dev);
+	dev_priv->fbdev_info->flags = fbdev_flags;
+	return 0;
+}
+
+static struct drm_driver driver = {
+	.driver_features =
+		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
+		DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
+	.load = nouveau_load,
+	.firstopen = nouveau_firstopen,
+	.lastclose = nouveau_lastclose,
+	.unload = nouveau_unload,
+	.preclose = nouveau_preclose,
+#if defined(CONFIG_DRM_NOUVEAU_DEBUG)
+	.debugfs_init = nouveau_debugfs_init,
+	.debugfs_cleanup = nouveau_debugfs_takedown,
+#endif
+	.irq_preinstall = nouveau_irq_preinstall,
+	.irq_postinstall = nouveau_irq_postinstall,
+	.irq_uninstall = nouveau_irq_uninstall,
+	.irq_handler = nouveau_irq_handler,
+	.reclaim_buffers = drm_core_reclaim_buffers,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = nouveau_ioctls,
+	.fops = {
+		.owner = THIS_MODULE,
+		.open = drm_open,
+		.release = drm_release,
+		.unlocked_ioctl = drm_ioctl,
+		.mmap = nouveau_ttm_mmap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
+#if defined(CONFIG_COMPAT)
+		.compat_ioctl = nouveau_compat_ioctl,
+#endif
+	},
+	.pci_driver = {
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
+		.probe = nouveau_pci_probe,
+		.remove = nouveau_pci_remove,
+		.suspend = nouveau_pci_suspend,
+		.resume = nouveau_pci_resume
+	},
+
+	.gem_init_object = nouveau_gem_object_new,
+	.gem_free_object = nouveau_gem_object_del,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+#ifdef GIT_REVISION
+	.date = GIT_REVISION,
+#else
+	.date = DRIVER_DATE,
+#endif
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+	.patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init nouveau_init(void)
+{
+	driver.num_ioctls = nouveau_max_ioctl;
+
+	if (nouveau_modeset == -1) {
+#ifdef CONFIG_VGA_CONSOLE
+		if (vgacon_text_force())
+			nouveau_modeset = 0;
+		else
+#endif
+			nouveau_modeset = 1;
+	}
+
+	if (nouveau_modeset == 1)
+		driver.driver_features |= DRIVER_MODESET;
+
+	return drm_init(&driver);
+}
+
+static void __exit nouveau_exit(void)
+{
+	drm_exit(&driver);
+}
+
+module_init(nouveau_init);
+module_exit(nouveau_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv17_tv_modes.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv17_tv_modes.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_crtc_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+#include "nv17_tv.h"
+
+char *nv17_tv_norm_names[NUM_TV_NORMS] = {
+	[TV_NORM_PAL] = "PAL",
+	[TV_NORM_PAL_M] = "PAL-M",
+	[TV_NORM_PAL_N] = "PAL-N",
+	[TV_NORM_PAL_NC] = "PAL-Nc",
+	[TV_NORM_NTSC_M] = "NTSC-M",
+	[TV_NORM_NTSC_J] = "NTSC-J",
+	[TV_NORM_HD480I] = "hd480i",
+	[TV_NORM_HD480P] = "hd480p",
+	[TV_NORM_HD576I] = "hd576i",
+	[TV_NORM_HD576P] = "hd576p",
+	[TV_NORM_HD720P] = "hd720p",
+	[TV_NORM_HD1080I] = "hd1080i"
+};
+
+/* TV standard specific parameters */
+
+struct nv17_tv_norm_params nv17_tv_norms[NUM_TV_NORMS] = {
+	[TV_NORM_PAL] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 576, 50000, {
+					0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
+					0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
+					0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
+					0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_PAL_M] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 480, 59940, {
+					0x21, 0xe6, 0xef, 0xe3, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x44, 0x76, 0x32, 0x25, 0x0, 0x3c, 0x0,
+					0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
+					0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x18, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x40, 0x10, 0x0, 0x9c,
+					0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_PAL_N] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 576, 50000, {
+					0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x40, 0x8a, 0x32, 0x25, 0x0, 0x3c, 0x0,
+					0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
+					0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
+					0xbd, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_PAL_NC] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 576, 50000, {
+					0x21, 0xf6, 0x94, 0x46, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x44, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
+					0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
+					0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
+					0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_NTSC_M] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 480, 59940, {
+					0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x3c, 0x0,
+					0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
+					0xc5, 0x4, 0xc5, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0x9c,
+					0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_NTSC_J] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 480, 59940, {
+					0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0,
+					0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
+					0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4,
+					0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_HD480I] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 480, 59940, {
+					0x21, 0xf0, 0x7c, 0x1f, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x44, 0x76, 0x48, 0x0, 0x0, 0x32, 0x0,
+					0x3c, 0x0, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x83,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x1,
+					0xcf, 0x4, 0xcf, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x16, 0xff, 0x3, 0x20, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x4, 0x10, 0x0, 0xa4,
+					0xc8, 0x15, 0x5, 0x15, 0x3c, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_HD576I] = { TV_ENC_MODE, {
+			.tv_enc_mode = { 720, 576, 50000, {
+					0x2a, 0x9, 0x8a, 0xcb, 0x0, 0x0, 0xb, 0x18,
+					0x7e, 0x40, 0x8a, 0x35, 0x27, 0x0, 0x34, 0x3,
+					0x3e, 0x3, 0x17, 0x21, 0x1b, 0x1b, 0x24, 0x9c,
+					0x1, 0x0, 0xf, 0xf, 0x60, 0x5, 0xd3, 0x3,
+					0xd3, 0x4, 0xd4, 0x1, 0x2, 0x0, 0xa, 0x5,
+					0x0, 0x1a, 0xff, 0x3, 0x18, 0xf, 0x78, 0x0,
+					0x0, 0xb4, 0x0, 0x15, 0x49, 0x10, 0x0, 0x9b,
+					0xbd, 0x15, 0x5, 0x15, 0x3e, 0x3, 0x0, 0x0
+				} } } },
+
+
+	[TV_NORM_HD480P] = { CTV_ENC_MODE, {
+			.ctv_enc_mode = {
+				.mode = { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000,
+						   720, 735, 743, 858, 0, 480, 490, 494, 525, 0,
+						   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+				.ctv_regs = { 0x3540000, 0x0, 0x0, 0x314,
+					      0x354003a, 0x40000, 0x6f0344, 0x18100000,
+					      0x10160004, 0x10060005, 0x1006000c, 0x10060020,
+					      0x10060021, 0x140e0022, 0x10060202, 0x1802020a,
+					      0x1810020b, 0x10000fff, 0x10000fff, 0x10000fff,
+					      0x10000fff, 0x10000fff, 0x10000fff, 0x70,
+					      0x3ff0000, 0x57, 0x2e001e, 0x258012c,
+					      0xa0aa04ec, 0x30, 0x80960019, 0x12c0300,
+					      0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400
+				} } } },
+
+	[TV_NORM_HD576P] = { CTV_ENC_MODE, {
+			.ctv_enc_mode = {
+				.mode = { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000,
+						   720, 730, 738, 864, 0, 576, 581, 585, 625, 0,
+						   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+				.ctv_regs = { 0x3540000, 0x0, 0x0, 0x314,
+					      0x354003a, 0x40000, 0x6f0344, 0x18100000,
+					      0x10060001, 0x10060009, 0x10060026, 0x10060027,
+					      0x140e0028, 0x10060268, 0x1810026d, 0x10000fff,
+					      0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff,
+					      0x10000fff, 0x10000fff, 0x10000fff, 0x69,
+					      0x3ff0000, 0x57, 0x2e001e, 0x258012c,
+					      0xa0aa04ec, 0x30, 0x80960019, 0x12c0300,
+					      0x2019, 0x600, 0x32060019, 0x0, 0x0, 0x400
+				} } } },
+
+	[TV_NORM_HD720P] = { CTV_ENC_MODE, {
+			.ctv_enc_mode = {
+				.mode = { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250,
+						   1280, 1349, 1357, 1650, 0, 720, 725, 730, 750, 0,
+						   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+				.ctv_regs = { 0x1260394, 0x0, 0x0, 0x622,
+					      0x66b0021, 0x6004a, 0x1210626, 0x8170000,
+					      0x70004, 0x70016, 0x70017, 0x40f0018,
+					      0x702e8, 0x81702ed, 0xfff, 0xfff,
+					      0xfff, 0xfff, 0xfff, 0xfff,
+					      0xfff, 0xfff, 0xfff, 0x0,
+					      0x2e40001, 0x58, 0x2e001e, 0x258012c,
+					      0xa0aa04ec, 0x30, 0x810c0039, 0x12c0300,
+					      0xc0002039, 0x600, 0x32060039, 0x0, 0x0, 0x0
+				} } } },
+
+	[TV_NORM_HD1080I] = { CTV_ENC_MODE, {
+			.ctv_enc_mode = {
+				.mode = { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250,
+						   1920, 1961, 2049, 2200, 0, 1080, 1084, 1088, 1125, 0,
+						   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC
+						   | DRM_MODE_FLAG_INTERLACE) },
+				.ctv_regs = { 0xac0420, 0x44c0478, 0x4a4, 0x4fc0868,
+					      0x8940028, 0x60054, 0xe80870, 0xbf70000,
+					      0xbc70004, 0x70005, 0x70012, 0x70013,
+					      0x40f0014, 0x70230, 0xbf70232, 0xbf70233,
+					      0x1c70237, 0x70238, 0x70244, 0x70245,
+					      0x40f0246, 0x70462, 0x1f70464, 0x0,
+					      0x2e40001, 0x58, 0x2e001e, 0x258012c,
+					      0xa0aa04ec, 0x30, 0x815f004c, 0x12c0300,
+					      0xc000204c, 0x600, 0x3206004c, 0x0, 0x0, 0x0
+				} } } }
+};
+
+/*
+ * The following is some guesswork on how the TV encoder flicker
+ * filter/rescaler works:
+ *
+ * It seems to use some sort of resampling filter, it is controlled
+ * through the registers at NV_PTV_HFILTER and NV_PTV_VFILTER, they
+ * control the horizontal and vertical stage respectively, there is
+ * also NV_PTV_HFILTER2 the blob fills identically to NV_PTV_HFILTER,
+ * but they seem to do nothing. A rough guess might be that they could
+ * be used to independently control the filtering of each interlaced
+ * field, but I don't know how they are enabled. The whole filtering
+ * process seems to be disabled with bits 26:27 of PTV_200, but we
+ * aren't doing that.
+ *
+ * The layout of both register sets is the same:
+ *
+ * A: [BASE+0x18]...[BASE+0x0] [BASE+0x58]..[BASE+0x40]
+ * B: [BASE+0x34]...[BASE+0x1c] [BASE+0x74]..[BASE+0x5c]
+ *
+ * Each coefficient is stored in bits [31],[15:9] in two's complement
+ * format. They seem to be some kind of weights used in a low-pass
+ * filter. Both A and B coefficients are applied to the 14 nearest
+ * samples on each side (Listed from nearest to furthermost.  They
+ * roughly cover 2 framebuffer pixels on each side).  They are
+ * probably multiplied with some more hardwired weights before being
+ * used: B-coefficients are applied the same on both sides,
+ * A-coefficients are inverted before being applied to the opposite
+ * side.
+ *
+ * After all the hassle, I got the following formula by empirical
+ * means...
+ */
+
+#define calc_overscan(o) interpolate(0x100, 0xe1, 0xc1, o)
+
+#define id1 (1LL << 8)
+#define id2 (1LL << 16)
+#define id3 (1LL << 24)
+#define id4 (1LL << 32)
+#define id5 (1LL << 48)
+
+static struct filter_params{
+	int64_t k1;
+	int64_t ki;
+	int64_t ki2;
+	int64_t ki3;
+	int64_t kr;
+	int64_t kir;
+	int64_t ki2r;
+	int64_t ki3r;
+	int64_t kf;
+	int64_t kif;
+	int64_t ki2f;
+	int64_t ki3f;
+	int64_t krf;
+	int64_t kirf;
+	int64_t ki2rf;
+	int64_t ki3rf;
+} fparams[2][4] = {
+	/* Horizontal filter parameters */
+	{
+		{64.311690 * id5, -39.516924 * id5, 6.586143 * id5, 0.000002 * id5,
+		 0.051285 * id4, 26.168746 * id4, -4.361449 * id4, -0.000001 * id4,
+		 9.308169 * id3, 78.180965 * id3, -13.030158 * id3, -0.000001 * id3,
+		 -8.801540 * id1, -46.572890 * id1, 7.762145 * id1, -0.000000 * id1},
+		{-44.565569 * id5, -68.081246 * id5, 39.812074 * id5, -4.009316 * id5,
+		 29.832207 * id4, 50.047322 * id4, -25.380017 * id4, 2.546422 * id4,
+		 104.605622 * id3, 141.908641 * id3, -74.322319 * id3, 7.484316 * id3,
+		 -37.081621 * id1, -90.397510 * id1, 42.784229 * id1, -4.289952 * id1},
+		{-56.793244 * id5, 31.153584 * id5, -5.192247 * id5, -0.000003 * id5,
+		 33.541131 * id4, -34.149302 * id4, 5.691537 * id4, 0.000002 * id4,
+		 87.196610 * id3, -88.995169 * id3, 14.832456 * id3, 0.000012 * id3,
+		 17.288138 * id1, 71.864786 * id1, -11.977408 * id1, -0.000009 * id1},
+		{51.787796 * id5, 21.211771 * id5, -18.993730 * id5, 1.853310 * id5,
+		 -41.470726 * id4, -17.775823 * id4, 13.057821 * id4, -1.15823 * id4,
+		 -154.235673 * id3, -44.878641 * id3, 40.656077 * id3, -3.695595 * id3,
+		 112.201065 * id1, 39.992155 * id1, -25.155714 * id1, 2.113984 * id1},
+	},
+
+	/* Vertical filter parameters */
+	{
+		{67.601979 * id5, 0.428319 * id5, -0.071318 * id5, -0.000012 * id5,
+		 -3.402339 * id4, 0.000209 * id4, -0.000092 * id4, 0.000010 * id4,
+		 -9.180996 * id3, 6.111270 * id3, -1.024457 * id3, 0.001043 * id3,
+		 6.060315 * id1, -0.017425 * id1, 0.007830 * id1, -0.000869 * id1},
+		{6.755647 * id5, 5.841348 * id5, 1.469734 * id5, -0.149656 * id5,
+		 8.293120 * id4, -1.192888 * id4, -0.947652 * id4, 0.094507 * id4,
+		 37.526655 * id3, 10.257875 * id3, -10.823275 * id3, 1.081497 * id3,
+		 -2.361928 * id1, -2.059432 * id1, 1.840671 * id1, -0.168100 * id1},
+		{-14.780391 * id5, -16.042148 * id5, 2.673692 * id5, -0.000000 * id5,
+		 39.541978 * id4, 5.680053 * id4, -0.946676 * id4, 0.000000 * id4,
+		 152.994486 * id3, 12.625439 * id3, -2.119579 * id3, 0.002708 * id3,
+		 -38.125089 * id1, -0.855880 * id1, 0.155359 * id1, -0.002245 * id1},
+		{-27.476193 * id5, -1.454976 * id5, 1.286557 * id5, 0.025346 * id5,
+		 20.687300 * id4, 3.014003 * id4, -0.557786 * id4, -0.01311 * id4,
+		 60.008737 * id3, -0.738273 * id3, 5.408217 * id3, -0.796798 * id3,
+		 -17.296835 * id1, 4.438577 * id1, -2.809420 * id1, 0.385491 * id1},
+	}
+};
+
+static void tv_setup_filter(struct drm_encoder *encoder)
+{
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	struct drm_display_mode *mode = &encoder->crtc->mode;
+	uint32_t (*filters[])[4][7] = {&tv_enc->state.hfilter,
+				       &tv_enc->state.vfilter};
+	int i, j, k;
+	int32_t overscan = calc_overscan(tv_enc->overscan);
+	int64_t flicker = (tv_enc->flicker - 50) * (id3 / 100);
+	uint64_t rs[] = {mode->hdisplay * id3,
+			 mode->vdisplay * id3};
+
+	do_div(rs[0], overscan * tv_norm->tv_enc_mode.hdisplay);
+	do_div(rs[1], overscan * tv_norm->tv_enc_mode.vdisplay);
+
+	for (k = 0; k < 2; k++) {
+		rs[k] = max((int64_t)rs[k], id2);
+
+		for (j = 0; j < 4; j++) {
+			struct filter_params *p = &fparams[k][j];
+
+			for (i = 0; i < 7; i++) {
+				int64_t c = (p->k1 + p->ki*i + p->ki2*i*i + p->ki3*i*i*i)
+					+ (p->kr + p->kir*i + p->ki2r*i*i + p->ki3r*i*i*i)*rs[k]
+					+ (p->kf + p->kif*i + p->ki2f*i*i + p->ki3f*i*i*i)*flicker
+					+ (p->krf + p->kirf*i + p->ki2rf*i*i + p->ki3rf*i*i*i)*flicker*rs[k];
+
+				(*filters[k])[j][i] = (c + id5/2) >> 39 & (0x1 << 31 | 0x7f << 9);
+			}
+		}
+	}
+}
+
+/* Hardware state saving/restoring */
+
+static void tv_save_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7])
+{
+	int i, j;
+	uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c };
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < 7; j++)
+			regs[i][j] = nv_read_ptv(dev, offsets[i]+4*j);
+	}
+}
+
+static void tv_load_filter(struct drm_device *dev, uint32_t base, uint32_t regs[4][7])
+{
+	int i, j;
+	uint32_t offsets[] = { base, base + 0x1c, base + 0x40, base + 0x5c };
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < 7; j++)
+			nv_write_ptv(dev, offsets[i]+4*j, regs[i][j]);
+	}
+}
+
+void nv17_tv_state_save(struct drm_device *dev, struct nv17_tv_state *state)
+{
+	int i;
+
+	for (i = 0; i < 0x40; i++)
+		state->tv_enc[i] = nv_read_tv_enc(dev, i);
+
+	tv_save_filter(dev, NV_PTV_HFILTER, state->hfilter);
+	tv_save_filter(dev, NV_PTV_HFILTER2, state->hfilter2);
+	tv_save_filter(dev, NV_PTV_VFILTER, state->vfilter);
+
+	nv_save_ptv(dev, state, 200);
+	nv_save_ptv(dev, state, 204);
+	nv_save_ptv(dev, state, 208);
+	nv_save_ptv(dev, state, 20c);
+	nv_save_ptv(dev, state, 304);
+	nv_save_ptv(dev, state, 500);
+	nv_save_ptv(dev, state, 504);
+	nv_save_ptv(dev, state, 508);
+	nv_save_ptv(dev, state, 600);
+	nv_save_ptv(dev, state, 604);
+	nv_save_ptv(dev, state, 608);
+	nv_save_ptv(dev, state, 60c);
+	nv_save_ptv(dev, state, 610);
+	nv_save_ptv(dev, state, 614);
+}
+
+void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state)
+{
+	int i;
+
+	for (i = 0; i < 0x40; i++)
+		nv_write_tv_enc(dev, i, state->tv_enc[i]);
+
+	tv_load_filter(dev, NV_PTV_HFILTER, state->hfilter);
+	tv_load_filter(dev, NV_PTV_HFILTER2, state->hfilter2);
+	tv_load_filter(dev, NV_PTV_VFILTER, state->vfilter);
+
+	nv_load_ptv(dev, state, 200);
+	nv_load_ptv(dev, state, 204);
+	nv_load_ptv(dev, state, 208);
+	nv_load_ptv(dev, state, 20c);
+	nv_load_ptv(dev, state, 304);
+	nv_load_ptv(dev, state, 500);
+	nv_load_ptv(dev, state, 504);
+	nv_load_ptv(dev, state, 508);
+	nv_load_ptv(dev, state, 600);
+	nv_load_ptv(dev, state, 604);
+	nv_load_ptv(dev, state, 608);
+	nv_load_ptv(dev, state, 60c);
+	nv_load_ptv(dev, state, 610);
+	nv_load_ptv(dev, state, 614);
+
+	/* This is required for some settings to kick in. */
+	nv_write_tv_enc(dev, 0x3e, 1);
+	nv_write_tv_enc(dev, 0x3e, 0);
+}
+
+/* Timings similar to the ones the blob sets */
+
+struct drm_display_mode nv17_tv_modes[] = {
+	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0,
+		   320, 344, 392, 560, 0, 200, 200, 202, 220, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
+		   | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
+	{ DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 0,
+		   320, 344, 392, 560, 0, 240, 240, 246, 263, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
+		   | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
+	{ DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 0,
+		   400, 432, 496, 640, 0, 300, 300, 303, 314, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC
+		   | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CLKDIV2) },
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 0,
+		   640, 672, 768, 880, 0, 480, 480, 492, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 0,
+		   720, 752, 872, 960, 0, 480, 480, 493, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 0,
+		   720, 776, 856, 960, 0, 576, 576, 588, 597, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 0,
+		   800, 840, 920, 1040, 0, 600, 600, 604, 618, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 0,
+		   1024, 1064, 1200, 1344, 0, 768, 768, 777, 806, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	{}
+};
+
+void nv17_tv_update_properties(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct nv17_tv_state *regs = &tv_enc->state;
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	int subconnector = tv_enc->select_subconnector ?
+						tv_enc->select_subconnector :
+						tv_enc->subconnector;
+
+	switch (subconnector) {
+	case DRM_MODE_SUBCONNECTOR_Composite:
+	{
+		regs->ptv_204 = 0x2;
+
+		/* The composite connector may be found on either pin. */
+		if (tv_enc->pin_mask & 0x4)
+			regs->ptv_204 |= 0x010000;
+		else if (tv_enc->pin_mask & 0x2)
+			regs->ptv_204 |= 0x100000;
+		else
+			regs->ptv_204 |= 0x110000;
+
+		regs->tv_enc[0x7] = 0x10;
+		break;
+	}
+	case DRM_MODE_SUBCONNECTOR_SVIDEO:
+		regs->ptv_204 = 0x11012;
+		regs->tv_enc[0x7] = 0x18;
+		break;
+
+	case DRM_MODE_SUBCONNECTOR_Component:
+		regs->ptv_204 = 0x111333;
+		regs->tv_enc[0x7] = 0x14;
+		break;
+
+	case DRM_MODE_SUBCONNECTOR_SCART:
+		regs->ptv_204 = 0x111012;
+		regs->tv_enc[0x7] = 0x18;
+		break;
+	}
+
+	regs->tv_enc[0x20] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x20], 255,
+					 tv_enc->saturation);
+	regs->tv_enc[0x22] = interpolate(0, tv_norm->tv_enc_mode.tv_enc[0x22], 255,
+					 tv_enc->saturation);
+	regs->tv_enc[0x25] = tv_enc->hue * 255 / 100;
+
+	nv_load_ptv(dev, regs, 204);
+	nv_load_tv_enc(dev, regs, 7);
+	nv_load_tv_enc(dev, regs, 20);
+	nv_load_tv_enc(dev, regs, 22);
+	nv_load_tv_enc(dev, regs, 25);
+}
+
+void nv17_tv_update_rescaler(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct nv17_tv_state *regs = &tv_enc->state;
+
+	regs->ptv_208 = 0x40 | (calc_overscan(tv_enc->overscan) << 8);
+
+	tv_setup_filter(encoder);
+
+	nv_load_ptv(dev, regs, 208);
+	tv_load_filter(dev, NV_PTV_HFILTER, regs->hfilter);
+	tv_load_filter(dev, NV_PTV_HFILTER2, regs->hfilter2);
+	tv_load_filter(dev, NV_PTV_VFILTER, regs->vfilter);
+}
+
+void nv17_ctv_update_rescaler(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	int head = nouveau_crtc(encoder->crtc)->index;
+	struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head];
+	struct drm_display_mode *crtc_mode = &encoder->crtc->mode;
+	struct drm_display_mode *output_mode = &get_tv_norm(encoder)->ctv_enc_mode.mode;
+	int overscan, hmargin, vmargin, hratio, vratio;
+
+	/* The rescaler doesn't do the right thing for interlaced modes. */
+	if (output_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		overscan = 100;
+	else
+		overscan = tv_enc->overscan;
+
+	hmargin = (output_mode->hdisplay - crtc_mode->hdisplay) / 2;
+	vmargin = (output_mode->vdisplay - crtc_mode->vdisplay) / 2;
+
+	hmargin = interpolate(0, min(hmargin, output_mode->hdisplay/20), hmargin,
+			      overscan);
+	vmargin = interpolate(0, min(vmargin, output_mode->vdisplay/20), vmargin,
+			      overscan);
+
+	hratio = crtc_mode->hdisplay * 0x800 / (output_mode->hdisplay - 2*hmargin);
+	vratio = crtc_mode->vdisplay * 0x800 / (output_mode->vdisplay - 2*vmargin) & ~3;
+
+	regs->fp_horiz_regs[FP_VALID_START] = hmargin;
+	regs->fp_horiz_regs[FP_VALID_END] = output_mode->hdisplay - hmargin - 1;
+	regs->fp_vert_regs[FP_VALID_START] = vmargin;
+	regs->fp_vert_regs[FP_VALID_END] = output_mode->vdisplay - vmargin - 1;
+
+	regs->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE |
+		XLATE(vratio, 0, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE) |
+		NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE |
+		XLATE(hratio, 0, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_START,
+		      regs->fp_horiz_regs[FP_VALID_START]);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HVALID_END,
+		      regs->fp_horiz_regs[FP_VALID_END]);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_START,
+		      regs->fp_vert_regs[FP_VALID_START]);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_VVALID_END,
+		      regs->fp_vert_regs[FP_VALID_END]);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_DEBUG_1, regs->fp_debug_1);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_fb.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_FB_H__
+#define __NOUVEAU_FB_H__
+
+struct nouveau_framebuffer {
+	struct drm_framebuffer base;
+	struct nouveau_bo *nvbo;
+};
+
+static inline struct nouveau_framebuffer *
+nouveau_framebuffer(struct drm_framebuffer *fb)
+{
+	return container_of(fb, struct nouveau_framebuffer, base);
+}
+
+extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
+
+struct drm_framebuffer *
+nouveau_framebuffer_create(struct drm_device *, struct nouveau_bo *,
+			   struct drm_mode_fb_cmd *);
+
+#endif /* __NOUVEAU_FB_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -0,0 +1,994 @@
+/*
+ * Copyright (C) 2008 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+#include "nouveau_dma.h"
+
+#define nouveau_gem_pushbuf_sync(chan) 0
+
+int
+nouveau_gem_object_new(struct drm_gem_object *gem)
+{
+	return 0;
+}
+
+void
+nouveau_gem_object_del(struct drm_gem_object *gem)
+{
+	struct nouveau_bo *nvbo = gem->driver_private;
+	struct ttm_buffer_object *bo = &nvbo->bo;
+
+	if (!nvbo)
+		return;
+	nvbo->gem = NULL;
+
+	if (unlikely(nvbo->cpu_filp))
+		ttm_bo_synccpu_write_release(bo);
+
+	if (unlikely(nvbo->pin_refcnt)) {
+		nvbo->pin_refcnt = 1;
+		nouveau_bo_unpin(nvbo);
+	}
+
+	ttm_bo_unref(&bo);
+}
+
+int
+nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
+		int size, int align, uint32_t flags, uint32_t tile_mode,
+		uint32_t tile_flags, bool no_vm, bool mappable,
+		struct nouveau_bo **pnvbo)
+{
+	struct nouveau_bo *nvbo;
+	int ret;
+
+	ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
+			     tile_flags, no_vm, mappable, pnvbo);
+	if (ret)
+		return ret;
+	nvbo = *pnvbo;
+
+	nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size);
+	if (!nvbo->gem) {
+		nouveau_bo_ref(NULL, pnvbo);
+		return -ENOMEM;
+	}
+
+	nvbo->bo.persistant_swap_storage = nvbo->gem->filp;
+	nvbo->gem->driver_private = nvbo;
+	return 0;
+}
+
+static int
+nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
+{
+	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
+
+	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
+	else
+		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
+
+	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
+	rep->offset = nvbo->bo.offset;
+	rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0;
+	rep->tile_mode = nvbo->tile_mode;
+	rep->tile_flags = nvbo->tile_flags;
+	return 0;
+}
+
+static bool
+nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) {
+	switch (tile_flags) {
+	case 0x0000:
+	case 0x1800:
+	case 0x2800:
+	case 0x4800:
+	case 0x7000:
+	case 0x7400:
+	case 0x7a00:
+	case 0xe000:
+		break;
+	default:
+		NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
+		return false;
+	}
+
+	return true;
+}
+
+int
+nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_gem_new *req = data;
+	struct nouveau_bo *nvbo = NULL;
+	struct nouveau_channel *chan = NULL;
+	uint32_t flags = 0;
+	int ret = 0;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
+		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
+
+	if (req->channel_hint) {
+		NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint,
+						     file_priv, chan);
+	}
+
+	if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM)
+		flags |= TTM_PL_FLAG_VRAM;
+	if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART)
+		flags |= TTM_PL_FLAG_TT;
+	if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
+		flags |= TTM_PL_FLAG_SYSTEM;
+
+	if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags))
+		return -EINVAL;
+
+	ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags,
+			      req->info.tile_mode, req->info.tile_flags, false,
+			      (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE),
+			      &nvbo);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gem_info(nvbo->gem, &req->info);
+	if (ret)
+		goto out;
+
+	ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference(nvbo->gem);
+	mutex_unlock(&dev->struct_mutex);
+
+	if (ret)
+		drm_gem_object_unreference(nvbo->gem);
+	return ret;
+}
+
+static int
+nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
+		       uint32_t write_domains, uint32_t valid_domains)
+{
+	struct nouveau_bo *nvbo = gem->driver_private;
+	struct ttm_buffer_object *bo = &nvbo->bo;
+	uint64_t flags;
+
+	if (!valid_domains || (!read_domains && !write_domains))
+		return -EINVAL;
+
+	if (write_domains) {
+		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+		    (write_domains & NOUVEAU_GEM_DOMAIN_VRAM))
+			flags = TTM_PL_FLAG_VRAM;
+		else
+		if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) &&
+		    (write_domains & NOUVEAU_GEM_DOMAIN_GART))
+			flags = TTM_PL_FLAG_TT;
+		else
+			return -EINVAL;
+	} else {
+		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+		    (read_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+		    bo->mem.mem_type == TTM_PL_VRAM)
+			flags = TTM_PL_FLAG_VRAM;
+		else
+		if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) &&
+		    (read_domains & NOUVEAU_GEM_DOMAIN_GART) &&
+		    bo->mem.mem_type == TTM_PL_TT)
+			flags = TTM_PL_FLAG_TT;
+		else
+		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+		    (read_domains & NOUVEAU_GEM_DOMAIN_VRAM))
+			flags = TTM_PL_FLAG_VRAM;
+		else
+			flags = TTM_PL_FLAG_TT;
+	}
+
+	nouveau_bo_placement_set(nvbo, flags);
+	return 0;
+}
+
+struct validate_op {
+	struct list_head vram_list;
+	struct list_head gart_list;
+	struct list_head both_list;
+};
+
+static void
+validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
+{
+	struct list_head *entry, *tmp;
+	struct nouveau_bo *nvbo;
+
+	list_for_each_safe(entry, tmp, list) {
+		nvbo = list_entry(entry, struct nouveau_bo, entry);
+		if (likely(fence)) {
+			struct nouveau_fence *prev_fence;
+
+			spin_lock(&nvbo->bo.lock);
+			prev_fence = nvbo->bo.sync_obj;
+			nvbo->bo.sync_obj = nouveau_fence_ref(fence);
+			spin_unlock(&nvbo->bo.lock);
+			nouveau_fence_unref((void *)&prev_fence);
+		}
+
+		list_del(&nvbo->entry);
+		nvbo->reserved_by = NULL;
+		ttm_bo_unreserve(&nvbo->bo);
+		drm_gem_object_unreference(nvbo->gem);
+	}
+}
+
+static void
+validate_fini(struct validate_op *op, struct nouveau_fence* fence)
+{
+	validate_fini_list(&op->vram_list, fence);
+	validate_fini_list(&op->gart_list, fence);
+	validate_fini_list(&op->both_list, fence);
+}
+
+static int
+validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
+	      struct drm_nouveau_gem_pushbuf_bo *pbbo,
+	      int nr_buffers, struct validate_op *op)
+{
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t sequence;
+	int trycnt = 0;
+	int ret, i;
+
+	sequence = atomic_add_return(1, &dev_priv->ttm.validate_sequence);
+retry:
+	if (++trycnt > 100000) {
+		NV_ERROR(dev, "%s failed and gave up.\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nr_buffers; i++) {
+		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[i];
+		struct drm_gem_object *gem;
+		struct nouveau_bo *nvbo;
+
+		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
+		if (!gem) {
+			NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle);
+			validate_fini(op, NULL);
+			return -EINVAL;
+		}
+		nvbo = gem->driver_private;
+
+		if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
+			NV_ERROR(dev, "multiple instances of buffer %d on "
+				      "validation list\n", b->handle);
+			validate_fini(op, NULL);
+			return -EINVAL;
+		}
+
+		ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence);
+		if (ret) {
+			validate_fini(op, NULL);
+			if (ret == -EAGAIN)
+				ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
+			drm_gem_object_unreference(gem);
+			if (ret)
+				return ret;
+			goto retry;
+		}
+
+		nvbo->reserved_by = file_priv;
+		nvbo->pbbo_index = i;
+		if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+		    (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART))
+			list_add_tail(&nvbo->entry, &op->both_list);
+		else
+		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM)
+			list_add_tail(&nvbo->entry, &op->vram_list);
+		else
+		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
+			list_add_tail(&nvbo->entry, &op->gart_list);
+		else {
+			NV_ERROR(dev, "invalid valid domains: 0x%08x\n",
+				 b->valid_domains);
+			list_add_tail(&nvbo->entry, &op->both_list);
+			validate_fini(op, NULL);
+			return -EINVAL;
+		}
+
+		if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) {
+			validate_fini(op, NULL);
+
+			if (nvbo->cpu_filp == file_priv) {
+				NV_ERROR(dev, "bo %p mapped by process trying "
+					      "to validate it!\n", nvbo);
+				return -EINVAL;
+			}
+
+			ret = ttm_bo_wait_cpu(&nvbo->bo, false);
+			if (ret)
+				return ret;
+			goto retry;
+		}
+	}
+
+	return 0;
+}
+
+static int
+validate_list(struct nouveau_channel *chan, struct list_head *list,
+	      struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
+{
+	struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
+				(void __force __user *)(uintptr_t)user_pbbo_ptr;
+	struct nouveau_bo *nvbo;
+	int ret, relocs = 0;
+
+	list_for_each_entry(nvbo, list, entry) {
+		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
+		struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
+
+		if (prev_fence && nouveau_fence_channel(prev_fence) != chan) {
+			spin_lock(&nvbo->bo.lock);
+			ret = ttm_bo_wait(&nvbo->bo, false, false, false);
+			spin_unlock(&nvbo->bo.lock);
+			if (unlikely(ret))
+				return ret;
+		}
+
+		ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
+					     b->write_domains,
+					     b->valid_domains);
+		if (unlikely(ret))
+			return ret;
+
+		nvbo->channel = chan;
+		ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
+				      false, false);
+		nvbo->channel = NULL;
+		if (unlikely(ret))
+			return ret;
+
+		if (nvbo->bo.offset == b->presumed_offset &&
+		    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
+		      b->presumed_domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
+		     (nvbo->bo.mem.mem_type == TTM_PL_TT &&
+		      b->presumed_domain & NOUVEAU_GEM_DOMAIN_GART)))
+			continue;
+
+		if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+			b->presumed_domain = NOUVEAU_GEM_DOMAIN_GART;
+		else
+			b->presumed_domain = NOUVEAU_GEM_DOMAIN_VRAM;
+		b->presumed_offset = nvbo->bo.offset;
+		b->presumed_ok = 0;
+		relocs++;
+
+		if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index], b, sizeof(*b)))
+			return -EFAULT;
+	}
+
+	return relocs;
+}
+
+static int
+nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
+			     struct drm_file *file_priv,
+			     struct drm_nouveau_gem_pushbuf_bo *pbbo,
+			     uint64_t user_buffers, int nr_buffers,
+			     struct validate_op *op, int *apply_relocs)
+{
+	int ret, relocs = 0;
+
+	INIT_LIST_HEAD(&op->vram_list);
+	INIT_LIST_HEAD(&op->gart_list);
+	INIT_LIST_HEAD(&op->both_list);
+
+	if (nr_buffers == 0)
+		return 0;
+
+	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
+	if (unlikely(ret))
+		return ret;
+
+	ret = validate_list(chan, &op->vram_list, pbbo, user_buffers);
+	if (unlikely(ret < 0)) {
+		validate_fini(op, NULL);
+		return ret;
+	}
+	relocs += ret;
+
+	ret = validate_list(chan, &op->gart_list, pbbo, user_buffers);
+	if (unlikely(ret < 0)) {
+		validate_fini(op, NULL);
+		return ret;
+	}
+	relocs += ret;
+
+	ret = validate_list(chan, &op->both_list, pbbo, user_buffers);
+	if (unlikely(ret < 0)) {
+		validate_fini(op, NULL);
+		return ret;
+	}
+	relocs += ret;
+
+	*apply_relocs = relocs;
+	return 0;
+}
+
+static inline void *
+u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
+{
+	void *mem;
+	void __user *userptr = (void __force __user *)(uintptr_t)user;
+
+	mem = kmalloc(nmemb * size, GFP_KERNEL);
+	if (!mem)
+		return ERR_PTR(-ENOMEM);
+
+	if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) {
+		kfree(mem);
+		return ERR_PTR(-EFAULT);
+	}
+
+	return mem;
+}
+
+static int
+nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
+				struct drm_nouveau_gem_pushbuf_bo *bo,
+				unsigned nr_relocs, uint64_t ptr_relocs,
+				unsigned nr_dwords, unsigned first_dword,
+				uint32_t *pushbuf, bool is_iomem)
+{
+	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
+	struct drm_device *dev = chan->dev;
+	int ret = 0;
+	unsigned i;
+
+	reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
+	if (IS_ERR(reloc))
+		return PTR_ERR(reloc);
+
+	for (i = 0; i < nr_relocs; i++) {
+		struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i];
+		struct drm_nouveau_gem_pushbuf_bo *b;
+		uint32_t data;
+
+		if (r->bo_index >= nr_bo || r->reloc_index < first_dword ||
+		    r->reloc_index >= first_dword + nr_dwords) {
+			NV_ERROR(dev, "Bad relocation %d\n", i);
+			NV_ERROR(dev, "  bo: %d max %d\n", r->bo_index, nr_bo);
+			NV_ERROR(dev, "  id: %d max %d\n", r->reloc_index, nr_dwords);
+			ret = -EINVAL;
+			break;
+		}
+
+		b = &bo[r->bo_index];
+		if (b->presumed_ok)
+			continue;
+
+		if (r->flags & NOUVEAU_GEM_RELOC_LOW)
+			data = b->presumed_offset + r->data;
+		else
+		if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
+			data = (b->presumed_offset + r->data) >> 32;
+		else
+			data = r->data;
+
+		if (r->flags & NOUVEAU_GEM_RELOC_OR) {
+			if (b->presumed_domain == NOUVEAU_GEM_DOMAIN_GART)
+				data |= r->tor;
+			else
+				data |= r->vor;
+		}
+
+		if (is_iomem)
+			iowrite32_native(data, (void __force __iomem *)
+						&pushbuf[r->reloc_index]);
+		else
+			pushbuf[r->reloc_index] = data;
+	}
+
+	kfree(reloc);
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_pushbuf *req = data;
+	struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
+	struct nouveau_channel *chan;
+	struct validate_op op;
+	struct nouveau_fence* fence = 0;
+	uint32_t *pushbuf = NULL;
+	int ret = 0, do_reloc = 0, i;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
+
+	if (req->nr_dwords >= chan->dma.max ||
+	    req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
+	    req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
+		NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
+		NV_ERROR(dev, "  dwords : %d max %d\n", req->nr_dwords,
+			 chan->dma.max - 1);
+		NV_ERROR(dev, "  buffers: %d max %d\n", req->nr_buffers,
+			 NOUVEAU_GEM_MAX_BUFFERS);
+		NV_ERROR(dev, "  relocs : %d max %d\n", req->nr_relocs,
+			 NOUVEAU_GEM_MAX_RELOCS);
+		return -EINVAL;
+	}
+
+	pushbuf = u_memcpya(req->dwords, req->nr_dwords, sizeof(uint32_t));
+	if (IS_ERR(pushbuf))
+		return PTR_ERR(pushbuf);
+
+	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
+	if (IS_ERR(bo)) {
+		kfree(pushbuf);
+		return PTR_ERR(bo);
+	}
+
+	mutex_lock(&dev->struct_mutex);
+
+	/* Validate buffer list */
+	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
+					   req->nr_buffers, &op, &do_reloc);
+	if (ret)
+		goto out;
+
+	/* Apply any relocations that are required */
+	if (do_reloc) {
+		ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers,
+						      bo, req->nr_relocs,
+						      req->relocs,
+						      req->nr_dwords, 0,
+						      pushbuf, false);
+		if (ret)
+			goto out;
+	}
+
+	/* Emit push buffer to the hw
+	 */
+	ret = RING_SPACE(chan, req->nr_dwords);
+	if (ret)
+		goto out;
+
+	OUT_RINGp(chan, pushbuf, req->nr_dwords);
+
+	ret = nouveau_fence_new(chan, &fence, true);
+	if (ret) {
+		NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
+		WIND_RING(chan);
+		goto out;
+	}
+
+	if (nouveau_gem_pushbuf_sync(chan)) {
+		ret = nouveau_fence_wait(fence, NULL, false, false);
+		if (ret) {
+			for (i = 0; i < req->nr_dwords; i++)
+				NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
+			NV_ERROR(dev, "^^ above push buffer is fail :(\n");
+		}
+	}
+
+out:
+	validate_fini(&op, fence);
+	nouveau_fence_unref((void**)&fence);
+	mutex_unlock(&dev->struct_mutex);
+	kfree(pushbuf);
+	kfree(bo);
+	return ret;
+}
+
+#define PUSHBUF_CAL (dev_priv->card_type >= NV_20)
+
+int
+nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_gem_pushbuf_call *req = data;
+	struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
+	struct nouveau_channel *chan;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *pbbo;
+	struct validate_op op;
+	struct nouveau_fence* fence = 0;
+	int i, ret = 0, do_reloc = 0;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
+
+	if (unlikely(req->handle == 0))
+		goto out_next;
+
+	if (req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
+	    req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
+		NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
+		NV_ERROR(dev, "  buffers: %d max %d\n", req->nr_buffers,
+			 NOUVEAU_GEM_MAX_BUFFERS);
+		NV_ERROR(dev, "  relocs : %d max %d\n", req->nr_relocs,
+			 NOUVEAU_GEM_MAX_RELOCS);
+		return -EINVAL;
+	}
+
+	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
+	if (IS_ERR(bo))
+		return PTR_ERR(bo);
+
+	mutex_lock(&dev->struct_mutex);
+
+	/* Validate buffer list */
+	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
+					   req->nr_buffers, &op, &do_reloc);
+	if (ret) {
+		NV_ERROR(dev, "validate: %d\n", ret);
+		goto out;
+	}
+
+	/* Validate DMA push buffer */
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem) {
+		NV_ERROR(dev, "Unknown pb handle 0x%08x\n", req->handle);
+		ret = -EINVAL;
+		goto out;
+	}
+	pbbo = nouveau_gem_object(gem);
+
+	if ((req->offset & 3) || req->nr_dwords < 2 ||
+	    (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
+	    (unsigned long)req->nr_dwords >
+	     ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
+		NV_ERROR(dev, "pb call misaligned or out of bounds: "
+			      "%d + %d * 4 > %ld\n",
+			 req->offset, req->nr_dwords, pbbo->bo.mem.size);
+		ret = -EINVAL;
+		drm_gem_object_unreference(gem);
+		goto out;
+	}
+
+	ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
+			     chan->fence.sequence);
+	if (ret) {
+		NV_ERROR(dev, "resv pb: %d\n", ret);
+		drm_gem_object_unreference(gem);
+		goto out;
+	}
+
+	nouveau_bo_placement_set(pbbo, 1 << chan->pushbuf_bo->bo.mem.mem_type);
+	ret = ttm_bo_validate(&pbbo->bo, &pbbo->placement, false, false);
+	if (ret) {
+		NV_ERROR(dev, "validate pb: %d\n", ret);
+		ttm_bo_unreserve(&pbbo->bo);
+		drm_gem_object_unreference(gem);
+		goto out;
+	}
+
+	list_add_tail(&pbbo->entry, &op.both_list);
+
+	/* If presumed return address doesn't match, we need to map the
+	 * push buffer and fix it..
+	 */
+	if (!PUSHBUF_CAL) {
+		uint32_t retaddy;
+
+		if (chan->dma.free < 4 + NOUVEAU_DMA_SKIPS) {
+			ret = nouveau_dma_wait(chan, 4 + NOUVEAU_DMA_SKIPS);
+			if (ret) {
+				NV_ERROR(dev, "jmp_space: %d\n", ret);
+				goto out;
+			}
+		}
+
+		retaddy  = chan->pushbuf_base + ((chan->dma.cur + 2) << 2);
+		retaddy |= 0x20000000;
+		if (retaddy != req->suffix0) {
+			req->suffix0 = retaddy;
+			do_reloc = 1;
+		}
+	}
+
+	/* Apply any relocations that are required */
+	if (do_reloc) {
+		void *pbvirt;
+		bool is_iomem;
+		ret = ttm_bo_kmap(&pbbo->bo, 0, pbbo->bo.mem.num_pages,
+				  &pbbo->kmap);
+		if (ret) {
+			NV_ERROR(dev, "kmap pb: %d\n", ret);
+			goto out;
+		}
+
+		pbvirt = ttm_kmap_obj_virtual(&pbbo->kmap, &is_iomem);
+		ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers, bo,
+						      req->nr_relocs,
+						      req->relocs,
+						      req->nr_dwords,
+						      req->offset / 4,
+						      pbvirt, is_iomem);
+
+		if (!PUSHBUF_CAL) {
+			nouveau_bo_wr32(pbbo,
+					req->offset / 4 + req->nr_dwords - 2,
+					req->suffix0);
+		}
+
+		ttm_bo_kunmap(&pbbo->kmap);
+		if (ret) {
+			NV_ERROR(dev, "reloc apply: %d\n", ret);
+			goto out;
+		}
+	}
+
+	if (PUSHBUF_CAL) {
+		ret = RING_SPACE(chan, 2);
+		if (ret) {
+			NV_ERROR(dev, "cal_space: %d\n", ret);
+			goto out;
+		}
+		OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
+				  req->offset) | 2);
+		OUT_RING(chan, 0);
+	} else {
+		ret = RING_SPACE(chan, 2 + NOUVEAU_DMA_SKIPS);
+		if (ret) {
+			NV_ERROR(dev, "jmp_space: %d\n", ret);
+			goto out;
+		}
+		OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
+				  req->offset) | 0x20000000);
+		OUT_RING(chan, 0);
+
+		/* Space the jumps apart with NOPs. */
+		for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
+			OUT_RING(chan, 0);
+	}
+
+	ret = nouveau_fence_new(chan, &fence, true);
+	if (ret) {
+		NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
+		WIND_RING(chan);
+		goto out;
+	}
+
+out:
+	validate_fini(&op, fence);
+	nouveau_fence_unref((void**)&fence);
+	mutex_unlock(&dev->struct_mutex);
+	kfree(bo);
+
+out_next:
+	if (PUSHBUF_CAL) {
+		req->suffix0 = 0x00020000;
+		req->suffix1 = 0x00000000;
+	} else {
+		req->suffix0 = 0x20000000 |
+			      (chan->pushbuf_base + ((chan->dma.cur + 2) << 2));
+		req->suffix1 = 0x00000000;
+	}
+
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_pushbuf_call2(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_nouveau_gem_pushbuf_call *req = data;
+
+	req->vram_available = dev_priv->fb_aper_free;
+	req->gart_available = dev_priv->gart_info.aper_free;
+
+	return nouveau_gem_ioctl_pushbuf_call(dev, data, file_priv);
+}
+
+static inline uint32_t
+domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
+{
+	uint32_t flags = 0;
+
+	if (domain & NOUVEAU_GEM_DOMAIN_VRAM)
+		flags |= TTM_PL_FLAG_VRAM;
+	if (domain & NOUVEAU_GEM_DOMAIN_GART)
+		flags |= TTM_PL_FLAG_TT;
+
+	return flags;
+}
+
+int
+nouveau_gem_ioctl_pin(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_pin *req = data;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *nvbo;
+	int ret = 0;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		NV_ERROR(dev, "pin only allowed without kernel modesetting\n");
+		return -EINVAL;
+	}
+
+	if (!DRM_SUSER(DRM_CURPROC))
+		return -EPERM;
+
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem)
+		return -EINVAL;
+	nvbo = nouveau_gem_object(gem);
+
+	ret = nouveau_bo_pin(nvbo, domain_to_ttm(nvbo, req->domain));
+	if (ret)
+		goto out;
+
+	req->offset = nvbo->bo.offset;
+	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+		req->domain = NOUVEAU_GEM_DOMAIN_GART;
+	else
+		req->domain = NOUVEAU_GEM_DOMAIN_VRAM;
+
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_unpin(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_pin *req = data;
+	struct drm_gem_object *gem;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem)
+		return -EINVAL;
+
+	ret = nouveau_bo_unpin(nouveau_gem_object(gem));
+
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_cpu_prep *req = data;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *nvbo;
+	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
+	int ret = -EINVAL;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem)
+		return ret;
+	nvbo = nouveau_gem_object(gem);
+
+	if (nvbo->cpu_filp) {
+		if (nvbo->cpu_filp == file_priv)
+			goto out;
+
+		ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait);
+		if (ret)
+			goto out;
+	}
+
+	if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
+		spin_lock(&nvbo->bo.lock);
+		ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
+		spin_unlock(&nvbo->bo.lock);
+	} else {
+		ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
+		if (ret == 0)
+			nvbo->cpu_filp = file_priv;
+	}
+
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_cpu_prep *req = data;
+	struct drm_gem_object *gem;
+	struct nouveau_bo *nvbo;
+	int ret = -EINVAL;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem)
+		return ret;
+	nvbo = nouveau_gem_object(gem);
+
+	if (nvbo->cpu_filp != file_priv)
+		goto out;
+	nvbo->cpu_filp = NULL;
+
+	ttm_bo_synccpu_write_release(&nvbo->bo);
+	ret = 0;
+
+out:
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+int
+nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct drm_nouveau_gem_info *req = data;
+	struct drm_gem_object *gem;
+	int ret;
+
+	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
+
+	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	if (!gem)
+		return -EINVAL;
+
+	ret = nouveau_gem_info(gem, req);
+	mutex_lock(&dev->struct_mutex);
+	drm_gem_object_unreference(gem);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv10_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv10_fb.c
@@ -0,0 +1,44 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+void
+nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
+			  uint32_t size, uint32_t pitch)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t limit = max(1u, addr + size) - 1;
+
+	if (pitch) {
+		if (dev_priv->card_type >= NV_20)
+			addr |= 1;
+		else
+			addr |= 1 << 31;
+	}
+
+	nv_wr32(dev, NV10_PFB_TLIMIT(i), limit);
+	nv_wr32(dev, NV10_PFB_TSIZE(i), pitch);
+	nv_wr32(dev, NV10_PFB_TILE(i), addr);
+}
+
+int
+nv10_fb_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	int i;
+
+	pfb->num_tiles = NV10_PFB_TILE__SIZE;
+
+	/* Turn all the tiling regions off. */
+	for (i = 0; i < pfb->num_tiles; i++)
+		pfb->set_region_tiling(dev, i, 0, 0, 0);
+
+	return 0;
+}
+
+void
+nv10_fb_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_calc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_calc.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright 1993-2003 NVIDIA, Corporation
+ * Copyright 2007-2009 Stuart Bennett
+ *
+ * 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 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 "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_hw.h"
+
+/****************************************************************************\
+*                                                                            *
+* The video arbitration routines calculate some "magic" numbers.  Fixes      *
+* the snow seen when accessing the framebuffer without it.                   *
+* It just works (I hope).                                                    *
+*                                                                            *
+\****************************************************************************/
+
+struct nv_fifo_info {
+	int lwm;
+	int burst;
+};
+
+struct nv_sim_state {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	int bpp;
+	int mem_page_miss;
+	int mem_latency;
+	int memory_type;
+	int memory_width;
+	int two_heads;
+};
+
+static void
+nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
+{
+	int pagemiss, cas, width, bpp;
+	int nvclks, mclks, pclks, crtpagemiss;
+	int found, mclk_extra, mclk_loop, cbs, m1, p1;
+	int mclk_freq, pclk_freq, nvclk_freq;
+	int us_m, us_n, us_p, crtc_drain_rate;
+	int cpm_us, us_crt, clwm;
+
+	pclk_freq = arb->pclk_khz;
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	cas = arb->mem_latency;
+	width = arb->memory_width >> 6;
+	bpp = arb->bpp;
+	cbs = 128;
+
+	pclks = 2;
+	nvclks = 10;
+	mclks = 13 + cas;
+	mclk_extra = 3;
+	found = 0;
+
+	while (!found) {
+		found = 1;
+
+		mclk_loop = mclks + mclk_extra;
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		us_p = nvclks * 1000 * 1000 / pclk_freq;
+
+		crtc_drain_rate = pclk_freq * bpp / 8;
+		crtpagemiss = 2;
+		crtpagemiss += 1;
+		cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+		us_crt = cpm_us + us_m + us_n + us_p;
+		clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+		clwm++;
+
+		m1 = clwm + cbs - 512;
+		p1 = m1 * pclk_freq / mclk_freq;
+		p1 = p1 * bpp / 8;
+		if ((p1 < m1 && m1 > 0) || clwm > 519) {
+			found = !mclk_extra;
+			mclk_extra--;
+		}
+		if (clwm < 384)
+			clwm = 384;
+
+		fifo->lwm = clwm;
+		fifo->burst = cbs;
+	}
+}
+
+static void
+nv10_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
+{
+	int fill_rate, drain_rate;
+	int pclks, nvclks, mclks, xclks;
+	int pclk_freq, nvclk_freq, mclk_freq;
+	int fill_lat, extra_lat;
+	int max_burst_o, max_burst_l;
+	int fifo_len, min_lwm, max_lwm;
+	const int burst_lat = 80; /* Maximum allowable latency due
+				   * to the CRTC FIFO burst. (ns) */
+
+	pclk_freq = arb->pclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	mclk_freq = arb->mclk_khz;
+
+	fill_rate = mclk_freq * arb->memory_width / 8; /* kB/s */
+	drain_rate = pclk_freq * arb->bpp / 8; /* kB/s */
+
+	fifo_len = arb->two_heads ? 1536 : 1024; /* B */
+
+	/* Fixed FIFO refill latency. */
+
+	pclks = 4;	/* lwm detect. */
+
+	nvclks = 3	/* lwm -> sync. */
+		+ 2	/* fbi bus cycles (1 req + 1 busy) */
+		+ 1	/* 2 edge sync.  may be very close to edge so
+			 * just put one. */
+		+ 1	/* fbi_d_rdv_n */
+		+ 1	/* Fbi_d_rdata */
+		+ 1;	/* crtfifo load */
+
+	mclks = 1	/* 2 edge sync.  may be very close to edge so
+			 * just put one. */
+		+ 1	/* arb_hp_req */
+		+ 5	/* tiling pipeline */
+		+ 2	/* latency fifo */
+		+ 2	/* memory request to fbio block */
+		+ 7;	/* data returned from fbio block */
+
+	/* Need to accumulate 256 bits for read */
+	mclks += (arb->memory_type == 0 ? 2 : 1)
+		* arb->memory_width / 32;
+
+	fill_lat = mclks * 1000 * 1000 / mclk_freq   /* minimum mclk latency */
+		+ nvclks * 1000 * 1000 / nvclk_freq  /* nvclk latency */
+		+ pclks * 1000 * 1000 / pclk_freq;   /* pclk latency */
+
+	/* Conditional FIFO refill latency. */
+
+	xclks = 2 * arb->mem_page_miss + mclks /* Extra latency due to
+						* the overlay. */
+		+ 2 * arb->mem_page_miss       /* Extra pagemiss latency. */
+		+ (arb->bpp == 32 ? 8 : 4);    /* Margin of error. */
+
+	extra_lat = xclks * 1000 * 1000 / mclk_freq;
+
+	if (arb->two_heads)
+		/* Account for another CRTC. */
+		extra_lat += fill_lat + extra_lat + burst_lat;
+
+	/* FIFO burst */
+
+	/* Max burst not leading to overflows. */
+	max_burst_o = (1 + fifo_len - extra_lat * drain_rate / (1000 * 1000))
+		* (fill_rate / 1000) / ((fill_rate - drain_rate) / 1000);
+	fifo->burst = min(max_burst_o, 1024);
+
+	/* Max burst value with an acceptable latency. */
+	max_burst_l = burst_lat * fill_rate / (1000 * 1000);
+	fifo->burst = min(max_burst_l, fifo->burst);
+
+	fifo->burst = rounddown_pow_of_two(fifo->burst);
+
+	/* FIFO low watermark */
+
+	min_lwm = (fill_lat + extra_lat) * drain_rate / (1000 * 1000) + 1;
+	max_lwm = fifo_len - fifo->burst
+		+ fill_lat * drain_rate / (1000 * 1000)
+		+ fifo->burst * drain_rate / fill_rate;
+
+	fifo->lwm = min_lwm + 10 * (max_lwm - min_lwm) / 100; /* Empirical. */
+}
+
+static void
+nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
+		int *burst, int *lwm)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv_fifo_info fifo_data;
+	struct nv_sim_state sim_data;
+	int MClk = nouveau_hw_get_clock(dev, MPLL);
+	int NVClk = nouveau_hw_get_clock(dev, NVPLL);
+	uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1);
+
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	sim_data.bpp = bpp;
+	sim_data.two_heads = nv_two_heads(dev);
+	if ((dev->pci_device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ ||
+	    (dev->pci_device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) {
+		uint32_t type;
+
+		pci_read_config_dword(pci_get_bus_and_slot(0, 1), 0x7c, &type);
+
+		sim_data.memory_type = (type >> 12) & 1;
+		sim_data.memory_width = 64;
+		sim_data.mem_latency = 3;
+		sim_data.mem_page_miss = 10;
+	} else {
+		sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1;
+		sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
+		sim_data.mem_latency = cfg1 & 0xf;
+		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
+	}
+
+	if (dev_priv->card_type == NV_04)
+		nv04_calc_arb(&fifo_data, &sim_data);
+	else
+		nv10_calc_arb(&fifo_data, &sim_data);
+
+	*burst = ilog2(fifo_data.burst >> 4);
+	*lwm = fifo_data.lwm >> 3;
+}
+
+static void
+nv30_update_arb(int *burst, int *lwm)
+{
+	unsigned int fifo_size, burst_size, graphics_lwm;
+
+	fifo_size = 2048;
+	burst_size = 512;
+	graphics_lwm = fifo_size - burst_size;
+
+	*burst = ilog2(burst_size >> 5);
+	*lwm = graphics_lwm >> 3;
+}
+
+void
+nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->card_type < NV_30)
+		nv04_update_arb(dev, vclk, bpp, burst, lwm);
+	else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ ||
+		 (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {
+		*burst = 128;
+		*lwm = 0x0480;
+	} else
+		nv30_update_arb(burst, lwm);
+}
+
+static int
+getMNP_single(struct drm_device *dev, struct pll_lims *pll_lim, int clk,
+	      struct nouveau_pll_vals *bestpv)
+{
+	/* Find M, N and P for a single stage PLL
+	 *
+	 * Note that some bioses (NV3x) have lookup tables of precomputed MNP
+	 * values, but we're too lazy to use those atm
+	 *
+	 * "clk" parameter in kHz
+	 * returns calculated clock
+	 */
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int cv = dev_priv->vbios->chip_version;
+	int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq;
+	int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m;
+	int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n;
+	int minU = pll_lim->vco1.min_inputfreq;
+	int maxU = pll_lim->vco1.max_inputfreq;
+	int minP = pll_lim->max_p ? pll_lim->min_p : 0;
+	int maxP = pll_lim->max_p ? pll_lim->max_p : pll_lim->max_usable_log2p;
+	int crystal = pll_lim->refclk;
+	int M, N, thisP, P;
+	int clkP, calcclk;
+	int delta, bestdelta = INT_MAX;
+	int bestclk = 0;
+
+	/* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */
+	/* possibly correlated with introduction of 27MHz crystal */
+	if (dev_priv->card_type < NV_50) {
+		if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
+			if (clk > 250000)
+				maxM = 6;
+			if (clk > 340000)
+				maxM = 2;
+		} else if (cv < 0x40) {
+			if (clk > 150000)
+				maxM = 6;
+			if (clk > 200000)
+				maxM = 4;
+			if (clk > 340000)
+				maxM = 2;
+		}
+	}
+
+	P = pll_lim->max_p ? maxP : (1 << maxP);
+	if ((clk * P) < minvco) {
+		minvco = clk * maxP;
+		maxvco = minvco * 2;
+	}
+
+	if (clk + clk/200 > maxvco)	/* +0.5% */
+		maxvco = clk + clk/200;
+
+	/* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
+	for (thisP = minP; thisP <= maxP; thisP++) {
+		P = pll_lim->max_p ? thisP : (1 << thisP);
+		clkP = clk * P;
+
+		if (clkP < minvco)
+			continue;
+		if (clkP > maxvco)
+			return bestclk;
+
+		for (M = minM; M <= maxM; M++) {
+			if (crystal/M < minU)
+				return bestclk;
+			if (crystal/M > maxU)
+				continue;
+
+			/* add crystal/2 to round better */
+			N = (clkP * M + crystal/2) / crystal;
+
+			if (N < minN)
+				continue;
+			if (N > maxN)
+				break;
+
+			/* more rounding additions */
+			calcclk = ((N * crystal + P/2) / P + M/2) / M;
+			delta = abs(calcclk - clk);
+			/* we do an exhaustive search rather than terminating
+			 * on an optimality condition...
+			 */
+			if (delta < bestdelta) {
+				bestdelta = delta;
+				bestclk = calcclk;
+				bestpv->N1 = N;
+				bestpv->M1 = M;
+				bestpv->log2P = thisP;
+				if (delta == 0)	/* except this one */
+					return bestclk;
+			}
+		}
+	}
+
+	return bestclk;
+}
+
+static int
+getMNP_double(struct drm_device *dev, struct pll_lims *pll_lim, int clk,
+	      struct nouveau_pll_vals *bestpv)
+{
+	/* Find M, N and P for a two stage PLL
+	 *
+	 * Note that some bioses (NV30+) have lookup tables of precomputed MNP
+	 * values, but we're too lazy to use those atm
+	 *
+	 * "clk" parameter in kHz
+	 * returns calculated clock
+	 */
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int chip_version = dev_priv->vbios->chip_version;
+	int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
+	int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq;
+	int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
+	int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq;
+	int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m;
+	int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n;
+	int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m;
+	int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n;
+	int maxlog2P = pll_lim->max_usable_log2p;
+	int crystal = pll_lim->refclk;
+	bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2);
+	int M1, N1, M2, N2, log2P;
+	int clkP, calcclk1, calcclk2, calcclkout;
+	int delta, bestdelta = INT_MAX;
+	int bestclk = 0;
+
+	int vco2 = (maxvco2 - maxvco2/200) / 2;
+	for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++)
+		;
+	clkP = clk << log2P;
+
+	if (maxvco2 < clk + clk/200)	/* +0.5% */
+		maxvco2 = clk + clk/200;
+
+	for (M1 = minM1; M1 <= maxM1; M1++) {
+		if (crystal/M1 < minU1)
+			return bestclk;
+		if (crystal/M1 > maxU1)
+			continue;
+
+		for (N1 = minN1; N1 <= maxN1; N1++) {
+			calcclk1 = crystal * N1 / M1;
+			if (calcclk1 < minvco1)
+				continue;
+			if (calcclk1 > maxvco1)
+				break;
+
+			for (M2 = minM2; M2 <= maxM2; M2++) {
+				if (calcclk1/M2 < minU2)
+					break;
+				if (calcclk1/M2 > maxU2)
+					continue;
+
+				/* add calcclk1/2 to round better */
+				N2 = (clkP * M2 + calcclk1/2) / calcclk1;
+				if (N2 < minN2)
+					continue;
+				if (N2 > maxN2)
+					break;
+
+				if (!fixedgain2) {
+					if (chip_version < 0x60)
+						if (N2/M2 < 4 || N2/M2 > 10)
+							continue;
+
+					calcclk2 = calcclk1 * N2 / M2;
+					if (calcclk2 < minvco2)
+						break;
+					if (calcclk2 > maxvco2)
+						continue;
+				} else
+					calcclk2 = calcclk1;
+
+				calcclkout = calcclk2 >> log2P;
+				delta = abs(calcclkout - clk);
+				/* we do an exhaustive search rather than terminating
+				 * on an optimality condition...
+				 */
+				if (delta < bestdelta) {
+					bestdelta = delta;
+					bestclk = calcclkout;
+					bestpv->N1 = N1;
+					bestpv->M1 = M1;
+					bestpv->N2 = N2;
+					bestpv->M2 = M2;
+					bestpv->log2P = log2P;
+					if (delta == 0)	/* except this one */
+						return bestclk;
+				}
+			}
+		}
+	}
+
+	return bestclk;
+}
+
+int
+nouveau_calc_pll_mnp(struct drm_device *dev, struct pll_lims *pll_lim, int clk,
+		     struct nouveau_pll_vals *pv)
+{
+	int outclk;
+
+	if (!pll_lim->vco2.maxfreq)
+		outclk = getMNP_single(dev, pll_lim, clk, pv);
+	else
+		outclk = getMNP_double(dev, pll_lim, clk, pv);
+
+	if (!outclk)
+		NV_ERROR(dev, "Could not find a compatible set of PLL values\n");
+
+	return outclk;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -0,0 +1,267 @@
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include "nouveau_fbcon.h"
+
+void
+nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) &&
+	     RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
+	if (rect->rop != ROP_COPY) {
+		BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
+		OUT_RING(chan, 1);
+	}
+	BEGIN_RING(chan, NvSub2D, 0x0588, 1);
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]);
+	else
+		OUT_RING(chan, rect->color);
+	BEGIN_RING(chan, NvSub2D, 0x0600, 4);
+	OUT_RING(chan, rect->dx);
+	OUT_RING(chan, rect->dy);
+	OUT_RING(chan, rect->dx + rect->width);
+	OUT_RING(chan, rect->dy + rect->height);
+	if (rect->rop != ROP_COPY) {
+		BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
+		OUT_RING(chan, 3);
+	}
+	FIRE_RING(chan);
+}
+
+void
+nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
+	BEGIN_RING(chan, NvSub2D, 0x0110, 1);
+	OUT_RING(chan, 0);
+	BEGIN_RING(chan, NvSub2D, 0x08b0, 4);
+	OUT_RING(chan, region->dx);
+	OUT_RING(chan, region->dy);
+	OUT_RING(chan, region->width);
+	OUT_RING(chan, region->height);
+	BEGIN_RING(chan, NvSub2D, 0x08d0, 4);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, region->sx);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, region->sy);
+	FIRE_RING(chan);
+}
+
+void
+nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+	uint32_t *palette = info->pseudo_palette;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) {
+		nouveau_fbcon_gpu_lockup(info);
+	}
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	width = ALIGN(image->width, 32);
+	dwords = (width * image->height) >> 5;
+
+	BEGIN_RING(chan, NvSub2D, 0x0814, 2);
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		OUT_RING(chan, palette[image->bg_color] | mask);
+		OUT_RING(chan, palette[image->fg_color] | mask);
+	} else {
+		OUT_RING(chan, image->bg_color);
+		OUT_RING(chan, image->fg_color);
+	}
+	BEGIN_RING(chan, NvSub2D, 0x0838, 2);
+	OUT_RING(chan, image->width);
+	OUT_RING(chan, image->height);
+	BEGIN_RING(chan, NvSub2D, 0x0850, 4);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, image->dx);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, image->dy);
+
+	while (dwords) {
+		int push = dwords > 2047 ? 2047 : dwords;
+
+		if (RING_SPACE(chan, push + 1)) {
+			nouveau_fbcon_gpu_lockup(info);
+			cfb_imageblit(info, image);
+			return;
+		}
+
+		dwords -= push;
+
+		BEGIN_RING(chan, NvSub2D, 0x40000860, push);
+		OUT_RINGp(chan, data, push);
+		data += push;
+	}
+
+	FIRE_RING(chan);
+}
+
+int
+nv50_fbcon_accel_init(struct fb_info *info)
+{
+	struct nouveau_fbcon_par *par = info->par;
+	struct drm_device *dev = par->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *chan = dev_priv->channel;
+	struct nouveau_gpuobj *eng2d = NULL;
+	int ret, format;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		format = 0xf3;
+		break;
+	case 15:
+		format = 0xf8;
+		break;
+	case 16:
+		format = 0xe8;
+		break;
+	case 32:
+		switch (info->var.transp.length) {
+		case 0: /* depth 24 */
+		case 8: /* depth 32, just use 24.. */
+			format = 0xe6;
+			break;
+		case 2: /* depth 30 */
+			format = 0xd1;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = nouveau_gpuobj_gr_new(dev_priv->channel, 0x502d, &eng2d);
+	if (ret)
+		return ret;
+
+	ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, Nv2D, eng2d, NULL);
+	if (ret)
+		return ret;
+
+	ret = RING_SPACE(chan, 59);
+	if (ret) {
+		nouveau_fbcon_gpu_lockup(info);
+		return ret;
+	}
+
+	BEGIN_RING(chan, NvSub2D, 0x0000, 1);
+	OUT_RING(chan, Nv2D);
+	BEGIN_RING(chan, NvSub2D, 0x0180, 4);
+	OUT_RING(chan, NvNotify0);
+	OUT_RING(chan, chan->vram_handle);
+	OUT_RING(chan, chan->vram_handle);
+	OUT_RING(chan, chan->vram_handle);
+	BEGIN_RING(chan, NvSub2D, 0x0290, 1);
+	OUT_RING(chan, 0);
+	BEGIN_RING(chan, NvSub2D, 0x0888, 1);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x02ac, 1);
+	OUT_RING(chan, 3);
+	BEGIN_RING(chan, NvSub2D, 0x02a0, 1);
+	OUT_RING(chan, 0x55);
+	BEGIN_RING(chan, NvSub2D, 0x08c0, 4);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0580, 2);
+	OUT_RING(chan, 4);
+	OUT_RING(chan, format);
+	BEGIN_RING(chan, NvSub2D, 0x02e8, 2);
+	OUT_RING(chan, 2);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0804, 1);
+	OUT_RING(chan, format);
+	BEGIN_RING(chan, NvSub2D, 0x0800, 1);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0808, 3);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x081c, 1);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0840, 4);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0200, 2);
+	OUT_RING(chan, format);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0214, 5);
+	OUT_RING(chan, info->fix.line_length);
+	OUT_RING(chan, info->var.xres_virtual);
+	OUT_RING(chan, info->var.yres_virtual);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys +
+			 dev_priv->vm_vram_base);
+	BEGIN_RING(chan, NvSub2D, 0x0230, 2);
+	OUT_RING(chan, format);
+	OUT_RING(chan, 1);
+	BEGIN_RING(chan, NvSub2D, 0x0244, 5);
+	OUT_RING(chan, info->fix.line_length);
+	OUT_RING(chan, info->var.xres_virtual);
+	OUT_RING(chan, info->var.yres_virtual);
+	OUT_RING(chan, 0);
+	OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys +
+			 dev_priv->vm_vram_base);
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv17_tv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv17_tv.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_crtc_helper.h"
+#include "nouveau_drv.h"
+#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+#include "nv17_tv.h"
+
+static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
+	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
+		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
+	uint32_t sample = 0;
+	int head;
+
+#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
+	testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
+	if (dev_priv->vbios->tvdactestval)
+		testval = dev_priv->vbios->tvdactestval;
+
+	dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
+	head = (dacclk & 0x100) >> 8;
+
+	/* Save the previous state. */
+	gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
+	gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
+	fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
+	fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
+	fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
+	fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL);
+	test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
+	ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c);
+	ctv_14 = NVReadRAMDAC(dev, head, 0x680c14);
+	ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
+
+	/* Prepare the DAC for load detection.  */
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
+
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL,
+		      NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
+		      NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 |
+		      NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
+		      NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |
+		      NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS);
+
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0);
+
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
+		      (dacclk & ~0xff) | 0x22);
+	msleep(1);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset,
+		      (dacclk & ~0xff) | 0x21);
+
+	NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20);
+	NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16);
+
+	/* Sample pin 0x4 (usually S-video luma). */
+	NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff);
+	msleep(20);
+	sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
+		& 0x4 << 28;
+
+	/* Sample the remaining pins. */
+	NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff);
+	msleep(20);
+	sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset)
+		& 0xa << 28;
+
+	/* Restore the previous state. */
+	NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c);
+	NVWriteRAMDAC(dev, head, 0x680c14, ctv_14);
+	NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk);
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
+	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
+
+	return sample;
+}
+
+static enum drm_connector_status
+nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_mode_config *conf = &dev->mode_config;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct dcb_entry *dcb = tv_enc->base.dcb;
+
+	if (dev_priv->chipset == 0x42 ||
+	    dev_priv->chipset == 0x43)
+		tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
+	else
+		tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
+
+	switch (tv_enc->pin_mask) {
+	case 0x2:
+	case 0x4:
+		tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Composite;
+		break;
+	case 0xc:
+		tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO;
+		break;
+	case 0xe:
+		if (dcb->tvconf.has_component_output)
+			tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component;
+		else
+			tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART;
+		break;
+	default:
+		tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
+		break;
+	}
+
+	drm_connector_property_set_value(connector,
+					 conf->tv_subconnector_property,
+					 tv_enc->subconnector);
+
+	if (tv_enc->subconnector) {
+		NV_INFO(dev, "Load detected on output %c\n",
+			'@' + ffs(dcb->or));
+		return connector_status_connected;
+	} else {
+		return connector_status_disconnected;
+	}
+}
+
+static const struct {
+	int hdisplay;
+	int vdisplay;
+} modes[] = {
+	{ 640, 400 },
+	{ 640, 480 },
+	{ 720, 480 },
+	{ 720, 576 },
+	{ 800, 600 },
+	{ 1024, 768 },
+	{ 1280, 720 },
+	{ 1280, 1024 },
+	{ 1920, 1080 }
+};
+
+static int nv17_tv_get_modes(struct drm_encoder *encoder,
+			     struct drm_connector *connector)
+{
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	struct drm_display_mode *mode;
+	struct drm_display_mode *output_mode;
+	int n = 0;
+	int i;
+
+	if (tv_norm->kind != CTV_ENC_MODE) {
+		struct drm_display_mode *tv_mode;
+
+		for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) {
+			mode = drm_mode_duplicate(encoder->dev, tv_mode);
+
+			mode->clock = tv_norm->tv_enc_mode.vrefresh *
+						mode->htotal / 1000 *
+						mode->vtotal / 1000;
+
+			if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+				mode->clock *= 2;
+
+			if (mode->hdisplay == tv_norm->tv_enc_mode.hdisplay &&
+			    mode->vdisplay == tv_norm->tv_enc_mode.vdisplay)
+				mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+			drm_mode_probed_add(connector, mode);
+			n++;
+		}
+		return n;
+	}
+
+	/* tv_norm->kind == CTV_ENC_MODE */
+	output_mode = &tv_norm->ctv_enc_mode.mode;
+	for (i = 0; i < ARRAY_SIZE(modes); i++) {
+		if (modes[i].hdisplay > output_mode->hdisplay ||
+		    modes[i].vdisplay > output_mode->vdisplay)
+			continue;
+
+		if (modes[i].hdisplay == output_mode->hdisplay &&
+		    modes[i].vdisplay == output_mode->vdisplay) {
+			mode = drm_mode_duplicate(encoder->dev, output_mode);
+			mode->type |= DRM_MODE_TYPE_PREFERRED;
+		} else {
+			mode = drm_cvt_mode(encoder->dev, modes[i].hdisplay,
+				modes[i].vdisplay, 60, false,
+				output_mode->flags & DRM_MODE_FLAG_INTERLACE,
+				false);
+		}
+
+		/* CVT modes are sometimes unsuitable... */
+		if (output_mode->hdisplay <= 720
+		    || output_mode->hdisplay >= 1920) {
+			mode->htotal = output_mode->htotal;
+			mode->hsync_start = (mode->hdisplay + (mode->htotal
+					     - mode->hdisplay) * 9 / 10) & ~7;
+			mode->hsync_end = mode->hsync_start + 8;
+		}
+		if (output_mode->vdisplay >= 1024) {
+			mode->vtotal = output_mode->vtotal;
+			mode->vsync_start = output_mode->vsync_start;
+			mode->vsync_end = output_mode->vsync_end;
+		}
+
+		mode->type |= DRM_MODE_TYPE_DRIVER;
+		drm_mode_probed_add(connector, mode);
+		n++;
+	}
+	return n;
+}
+
+static int nv17_tv_mode_valid(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode)
+{
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+
+	if (tv_norm->kind == CTV_ENC_MODE) {
+		struct drm_display_mode *output_mode =
+						&tv_norm->ctv_enc_mode.mode;
+
+		if (mode->clock > 400000)
+			return MODE_CLOCK_HIGH;
+
+		if (mode->hdisplay > output_mode->hdisplay ||
+		    mode->vdisplay > output_mode->vdisplay)
+			return MODE_BAD;
+
+		if ((mode->flags & DRM_MODE_FLAG_INTERLACE) !=
+		    (output_mode->flags & DRM_MODE_FLAG_INTERLACE))
+			return MODE_NO_INTERLACE;
+
+		if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+			return MODE_NO_DBLESCAN;
+
+	} else {
+		const int vsync_tolerance = 600;
+
+		if (mode->clock > 70000)
+			return MODE_CLOCK_HIGH;
+
+		if (abs(drm_mode_vrefresh(mode) * 1000 -
+			tv_norm->tv_enc_mode.vrefresh) > vsync_tolerance)
+			return MODE_VSYNC;
+
+		/* The encoder takes care of the actual interlacing */
+		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+			return MODE_NO_INTERLACE;
+	}
+
+	return MODE_OK;
+}
+
+static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+
+	if (tv_norm->kind == CTV_ENC_MODE)
+		adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
+	else
+		adjusted_mode->clock = 90000;
+
+	return true;
+}
+
+static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+
+	if (nouveau_encoder(encoder)->last_dpms == mode)
+		return;
+	nouveau_encoder(encoder)->last_dpms = mode;
+
+	NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n",
+		 mode, nouveau_encoder(encoder)->dcb->index);
+
+	regs->ptv_200 &= ~1;
+
+	if (tv_norm->kind == CTV_ENC_MODE) {
+		nv04_dfp_update_fp_control(encoder, mode);
+
+	} else {
+		nv04_dfp_update_fp_control(encoder, DRM_MODE_DPMS_OFF);
+
+		if (mode == DRM_MODE_DPMS_ON)
+			regs->ptv_200 |= 1;
+	}
+
+	nv_load_ptv(dev, regs, 200);
+
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
+	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
+
+	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
+}
+
+static void nv17_tv_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	int head = nouveau_crtc(encoder->crtc)->index;
+	uint8_t *cr_lcd = &dev_priv->mode_reg.crtc_reg[head].CRTC[
+							NV_CIO_CRE_LCD__INDEX];
+	uint32_t dacclk_off = NV_PRAMDAC_DACCLK +
+					nv04_dac_output_offset(encoder);
+	uint32_t dacclk;
+
+	helper->dpms(encoder, DRM_MODE_DPMS_OFF);
+
+	nv04_dfp_disable(dev, head);
+
+	/* Unbind any FP encoders from this head if we need the FP
+	 * stuff enabled. */
+	if (tv_norm->kind == CTV_ENC_MODE) {
+		struct drm_encoder *enc;
+
+		list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
+			struct dcb_entry *dcb = nouveau_encoder(enc)->dcb;
+
+			if ((dcb->type == OUTPUT_TMDS ||
+			     dcb->type == OUTPUT_LVDS) &&
+			     !enc->crtc &&
+			     nv04_dfp_get_bound_head(dev, dcb) == head) {
+				nv04_dfp_bind_head(dev, dcb, head ^ 1,
+						dev_priv->VBIOS.fp.dual_link);
+			}
+		}
+
+	}
+
+	/* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f)
+	 * at LCD__INDEX which we don't alter
+	 */
+	if (!(*cr_lcd & 0x44)) {
+		if (tv_norm->kind == CTV_ENC_MODE)
+			*cr_lcd = 0x1 | (head ? 0x0 : 0x8);
+		else
+			*cr_lcd = 0;
+	}
+
+	/* Set the DACCLK register */
+	dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1;
+
+	if (dev_priv->card_type == NV_40)
+		dacclk |= 0x1a << 16;
+
+	if (tv_norm->kind == CTV_ENC_MODE) {
+		dacclk |=  0x20;
+
+		if (head)
+			dacclk |= 0x100;
+		else
+			dacclk &= ~0x100;
+
+	} else {
+		dacclk |= 0x10;
+
+	}
+
+	NVWriteRAMDAC(dev, 0, dacclk_off, dacclk);
+}
+
+static void nv17_tv_mode_set(struct drm_encoder *encoder,
+			     struct drm_display_mode *drm_mode,
+			     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int head = nouveau_crtc(encoder->crtc)->index;
+	struct nv04_crtc_reg *regs = &dev_priv->mode_reg.crtc_reg[head];
+	struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state;
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	int i;
+
+	regs->CRTC[NV_CIO_CRE_53] = 0x40; /* FP_HTIMING */
+	regs->CRTC[NV_CIO_CRE_54] = 0; /* FP_VTIMING */
+	regs->ramdac_630 = 0x2; /* turn off green mode (tv test pattern?) */
+	regs->tv_setup = 1;
+	regs->ramdac_8c0 = 0x0;
+
+	if (tv_norm->kind == TV_ENC_MODE) {
+		tv_regs->ptv_200 = 0x13111100;
+		if (head)
+			tv_regs->ptv_200 |= 0x10;
+
+		tv_regs->ptv_20c = 0x808010;
+		tv_regs->ptv_304 = 0x2d00000;
+		tv_regs->ptv_600 = 0x0;
+		tv_regs->ptv_60c = 0x0;
+		tv_regs->ptv_610 = 0x1e00000;
+
+		if (tv_norm->tv_enc_mode.vdisplay == 576) {
+			tv_regs->ptv_508 = 0x1200000;
+			tv_regs->ptv_614 = 0x33;
+
+		} else if (tv_norm->tv_enc_mode.vdisplay == 480) {
+			tv_regs->ptv_508 = 0xf00000;
+			tv_regs->ptv_614 = 0x13;
+		}
+
+		if (dev_priv->card_type >= NV_30) {
+			tv_regs->ptv_500 = 0xe8e0;
+			tv_regs->ptv_504 = 0x1710;
+			tv_regs->ptv_604 = 0x0;
+			tv_regs->ptv_608 = 0x0;
+		} else {
+			if (tv_norm->tv_enc_mode.vdisplay == 576) {
+				tv_regs->ptv_604 = 0x20;
+				tv_regs->ptv_608 = 0x10;
+				tv_regs->ptv_500 = 0x19710;
+				tv_regs->ptv_504 = 0x68f0;
+
+			} else if (tv_norm->tv_enc_mode.vdisplay == 480) {
+				tv_regs->ptv_604 = 0x10;
+				tv_regs->ptv_608 = 0x20;
+				tv_regs->ptv_500 = 0x4b90;
+				tv_regs->ptv_504 = 0x1b480;
+			}
+		}
+
+		for (i = 0; i < 0x40; i++)
+			tv_regs->tv_enc[i] = tv_norm->tv_enc_mode.tv_enc[i];
+
+	} else {
+		struct drm_display_mode *output_mode =
+						&tv_norm->ctv_enc_mode.mode;
+
+		/* The registers in PRAMDAC+0xc00 control some timings and CSC
+		 * parameters for the CTV encoder (It's only used for "HD" TV
+		 * modes, I don't think I have enough working to guess what
+		 * they exactly mean...), it's probably connected at the
+		 * output of the FP encoder, but it also needs the analog
+		 * encoder in its OR enabled and routed to the head it's
+		 * using. It's enabled with the DACCLK register, bits [5:4].
+		 */
+		for (i = 0; i < 38; i++)
+			regs->ctv_regs[i] = tv_norm->ctv_enc_mode.ctv_regs[i];
+
+		regs->fp_horiz_regs[FP_DISPLAY_END] = output_mode->hdisplay - 1;
+		regs->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1;
+		regs->fp_horiz_regs[FP_SYNC_START] =
+						output_mode->hsync_start - 1;
+		regs->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1;
+		regs->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay +
+			max((output_mode->hdisplay-600)/40 - 1, 1);
+
+		regs->fp_vert_regs[FP_DISPLAY_END] = output_mode->vdisplay - 1;
+		regs->fp_vert_regs[FP_TOTAL] = output_mode->vtotal - 1;
+		regs->fp_vert_regs[FP_SYNC_START] =
+						output_mode->vsync_start - 1;
+		regs->fp_vert_regs[FP_SYNC_END] = output_mode->vsync_end - 1;
+		regs->fp_vert_regs[FP_CRTC] = output_mode->vdisplay - 1;
+
+		regs->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
+			NV_PRAMDAC_FP_TG_CONTROL_READ_PROG |
+			NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
+
+		if (output_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS;
+		if (output_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			regs->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS;
+
+		regs->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND |
+			NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND |
+			NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR |
+			NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR |
+			NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED |
+			NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE |
+			NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE;
+
+		regs->fp_debug_2 = 0;
+
+		regs->fp_margin_color = 0x801080;
+
+	}
+}
+
+static void nv17_tv_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_encoder_helper_funcs *helper = encoder->helper_private;
+
+	if (get_tv_norm(encoder)->kind == TV_ENC_MODE) {
+		nv17_tv_update_rescaler(encoder);
+		nv17_tv_update_properties(encoder);
+	} else {
+		nv17_ctv_update_rescaler(encoder);
+	}
+
+	nv17_tv_state_load(dev, &to_tv_enc(encoder)->state);
+
+	/* This could use refinement for flatpanels, but it should work */
+	if (dev_priv->chipset < 0x44)
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
+					nv04_dac_output_offset(encoder),
+					0xf0000000);
+	else
+		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL +
+					nv04_dac_output_offset(encoder),
+					0x00100000);
+
+	helper->dpms(encoder, DRM_MODE_DPMS_ON);
+
+	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
+		drm_get_connector_name(
+			&nouveau_encoder_connector_get(nv_encoder)->base),
+		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+}
+
+static void nv17_tv_save(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+
+	nouveau_encoder(encoder)->restore.output =
+					NVReadRAMDAC(dev, 0,
+					NV_PRAMDAC_DACCLK +
+					nv04_dac_output_offset(encoder));
+
+	nv17_tv_state_save(dev, &tv_enc->saved_state);
+
+	tv_enc->state.ptv_200 = tv_enc->saved_state.ptv_200;
+}
+
+static void nv17_tv_restore(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+
+	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK +
+				nv04_dac_output_offset(encoder),
+				nouveau_encoder(encoder)->restore.output);
+
+	nv17_tv_state_load(dev, &to_tv_enc(encoder)->saved_state);
+
+	nouveau_encoder(encoder)->last_dpms = NV_DPMS_CLEARED;
+}
+
+static int nv17_tv_create_resources(struct drm_encoder *encoder,
+				    struct drm_connector *connector)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_mode_config *conf = &dev->mode_config;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+	int num_tv_norms = dcb->tvconf.has_component_output ? NUM_TV_NORMS :
+							NUM_LD_TV_NORMS;
+	int i;
+
+	if (nouveau_tv_norm) {
+		for (i = 0; i < num_tv_norms; i++) {
+			if (!strcmp(nv17_tv_norm_names[i], nouveau_tv_norm)) {
+				tv_enc->tv_norm = i;
+				break;
+			}
+		}
+
+		if (i == num_tv_norms)
+			NV_WARN(dev, "Invalid TV norm setting \"%s\"\n",
+				nouveau_tv_norm);
+	}
+
+	drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names);
+
+	drm_connector_attach_property(connector,
+					conf->tv_select_subconnector_property,
+					tv_enc->select_subconnector);
+	drm_connector_attach_property(connector,
+					conf->tv_subconnector_property,
+					tv_enc->subconnector);
+	drm_connector_attach_property(connector,
+					conf->tv_mode_property,
+					tv_enc->tv_norm);
+	drm_connector_attach_property(connector,
+					conf->tv_flicker_reduction_property,
+					tv_enc->flicker);
+	drm_connector_attach_property(connector,
+					conf->tv_saturation_property,
+					tv_enc->saturation);
+	drm_connector_attach_property(connector,
+					conf->tv_hue_property,
+					tv_enc->hue);
+	drm_connector_attach_property(connector,
+					conf->tv_overscan_property,
+					tv_enc->overscan);
+
+	return 0;
+}
+
+static int nv17_tv_set_property(struct drm_encoder *encoder,
+				struct drm_connector *connector,
+				struct drm_property *property,
+				uint64_t val)
+{
+	struct drm_mode_config *conf = &encoder->dev->mode_config;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
+	bool modes_changed = false;
+
+	if (property == conf->tv_overscan_property) {
+		tv_enc->overscan = val;
+		if (encoder->crtc) {
+			if (tv_norm->kind == CTV_ENC_MODE)
+				nv17_ctv_update_rescaler(encoder);
+			else
+				nv17_tv_update_rescaler(encoder);
+		}
+
+	} else if (property == conf->tv_saturation_property) {
+		if (tv_norm->kind != TV_ENC_MODE)
+			return -EINVAL;
+
+		tv_enc->saturation = val;
+		nv17_tv_update_properties(encoder);
+
+	} else if (property == conf->tv_hue_property) {
+		if (tv_norm->kind != TV_ENC_MODE)
+			return -EINVAL;
+
+		tv_enc->hue = val;
+		nv17_tv_update_properties(encoder);
+
+	} else if (property == conf->tv_flicker_reduction_property) {
+		if (tv_norm->kind != TV_ENC_MODE)
+			return -EINVAL;
+
+		tv_enc->flicker = val;
+		if (encoder->crtc)
+			nv17_tv_update_rescaler(encoder);
+
+	} else if (property == conf->tv_mode_property) {
+		if (connector->dpms != DRM_MODE_DPMS_OFF)
+			return -EINVAL;
+
+		tv_enc->tv_norm = val;
+
+		modes_changed = true;
+
+	} else if (property == conf->tv_select_subconnector_property) {
+		if (tv_norm->kind != TV_ENC_MODE)
+			return -EINVAL;
+
+		tv_enc->select_subconnector = val;
+		nv17_tv_update_properties(encoder);
+
+	} else {
+		return -EINVAL;
+	}
+
+	if (modes_changed) {
+		drm_helper_probe_single_connector_modes(connector, 0, 0);
+
+		/* Disable the crtc to ensure a full modeset is
+		 * performed whenever it's turned on again. */
+		if (crtc) {
+			struct drm_mode_set modeset = {
+				.crtc = crtc,
+			};
+
+			crtc->funcs->set_config(&modeset);
+		}
+	}
+
+	return 0;
+}
+
+static void nv17_tv_destroy(struct drm_encoder *encoder)
+{
+	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
+
+	NV_DEBUG_KMS(encoder->dev, "\n");
+
+	drm_encoder_cleanup(encoder);
+	kfree(tv_enc);
+}
+
+static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = {
+	.dpms = nv17_tv_dpms,
+	.save = nv17_tv_save,
+	.restore = nv17_tv_restore,
+	.mode_fixup = nv17_tv_mode_fixup,
+	.prepare = nv17_tv_prepare,
+	.commit = nv17_tv_commit,
+	.mode_set = nv17_tv_mode_set,
+	.detect = nv17_tv_detect,
+};
+
+static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = {
+	.get_modes = nv17_tv_get_modes,
+	.mode_valid = nv17_tv_mode_valid,
+	.create_resources = nv17_tv_create_resources,
+	.set_property = nv17_tv_set_property,
+};
+
+static struct drm_encoder_funcs nv17_tv_funcs = {
+	.destroy = nv17_tv_destroy,
+};
+
+int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+{
+	struct drm_encoder *encoder;
+	struct nv17_tv_encoder *tv_enc = NULL;
+
+	tv_enc = kzalloc(sizeof(*tv_enc), GFP_KERNEL);
+	if (!tv_enc)
+		return -ENOMEM;
+
+	tv_enc->overscan = 50;
+	tv_enc->flicker = 50;
+	tv_enc->saturation = 50;
+	tv_enc->hue = 0;
+	tv_enc->tv_norm = TV_NORM_PAL;
+	tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
+	tv_enc->select_subconnector = DRM_MODE_SUBCONNECTOR_Automatic;
+	tv_enc->pin_mask = 0;
+
+	encoder = to_drm_encoder(&tv_enc->base);
+
+	tv_enc->base.dcb = entry;
+	tv_enc->base.or = ffs(entry->or) - 1;
+
+	drm_encoder_init(dev, encoder, &nv17_tv_funcs, DRM_MODE_ENCODER_TVDAC);
+	drm_encoder_helper_add(encoder, &nv17_tv_helper_funcs);
+	to_encoder_slave(encoder)->slave_funcs = &nv17_tv_slave_funcs;
+
+	encoder->possible_crtcs = entry->heads;
+	encoder->possible_clones = 0;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv40_mc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv40_mc.c
@@ -0,0 +1,38 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+int
+nv40_mc_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t tmp;
+
+	/* Power up everything, resetting each individual unit will
+	 * be done later if needed.
+	 */
+	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
+
+	switch (dev_priv->chipset) {
+	case 0x44:
+	case 0x46: /* G72 */
+	case 0x4e:
+	case 0x4c: /* C51_G7X */
+		tmp = nv_rd32(dev, NV40_PFB_020C);
+		nv_wr32(dev, NV40_PMC_1700, tmp);
+		nv_wr32(dev, NV40_PMC_1704, 0);
+		nv_wr32(dev, NV40_PMC_1708, 0);
+		nv_wr32(dev, NV40_PMC_170C, tmp);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+void
+nv40_mc_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_cursor.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm_mode.h"
+
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_crtc.h"
+#include "nv50_display.h"
+
+static void
+nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
+{
+	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct drm_device *dev = nv_crtc->base.dev;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	if (update && nv_crtc->cursor.visible)
+		return;
+
+	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while unhiding cursor\n");
+		return;
+	}
+
+	if (dev_priv->chipset != 0x50) {
+		BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
+		OUT_RING(evo, NvEvoVRAM);
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
+	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_SHOW);
+	OUT_RING(evo, nv_crtc->cursor.offset >> 8);
+
+	if (update) {
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
+		FIRE_RING(evo);
+		nv_crtc->cursor.visible = true;
+	}
+}
+
+static void
+nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
+{
+	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
+	struct nouveau_channel *evo = dev_priv->evo;
+	struct drm_device *dev = nv_crtc->base.dev;
+	int ret;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	if (update && !nv_crtc->cursor.visible)
+		return;
+
+	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
+	if (ret) {
+		NV_ERROR(dev, "no space while hiding cursor\n");
+		return;
+	}
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
+	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE);
+	OUT_RING(evo, 0);
+	if (dev_priv->chipset != 0x50) {
+		BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
+		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE);
+	}
+
+	if (update) {
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
+		FIRE_RING(evo);
+		nv_crtc->cursor.visible = false;
+	}
+}
+
+static void
+nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+
+	nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index),
+		((y & 0xFFFF) << 16) | (x & 0xFFFF));
+	/* Needed to make the cursor move. */
+	nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0);
+}
+
+static void
+nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
+{
+	NV_DEBUG_KMS(nv_crtc->base.dev, "\n");
+	if (offset == nv_crtc->cursor.offset)
+		return;
+
+	nv_crtc->cursor.offset = offset;
+	if (nv_crtc->cursor.visible) {
+		nv_crtc->cursor.visible = false;
+		nv_crtc->cursor.show(nv_crtc, true);
+	}
+}
+
+int
+nv50_cursor_init(struct nouveau_crtc *nv_crtc)
+{
+	nv_crtc->cursor.set_offset = nv50_cursor_set_offset;
+	nv_crtc->cursor.set_pos = nv50_cursor_set_pos;
+	nv_crtc->cursor.hide = nv50_cursor_hide;
+	nv_crtc->cursor.show = nv50_cursor_show;
+	return 0;
+}
+
+void
+nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	int idx = nv_crtc->index;
+
+	NV_DEBUG_KMS(dev, "\n");
+
+	nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
+	if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
+		     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
+		NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
+		NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
+			 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
+	}
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_grctx.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_grctx.c
@@ -0,0 +1,2367 @@
+/*
+ * Copyright 2009 Marcin Kościelnicki
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 CP_FLAG_CLEAR                 0
+#define CP_FLAG_SET                   1
+#define CP_FLAG_SWAP_DIRECTION        ((0 * 32) + 0)
+#define CP_FLAG_SWAP_DIRECTION_LOAD   0
+#define CP_FLAG_SWAP_DIRECTION_SAVE   1
+#define CP_FLAG_UNK01                 ((0 * 32) + 1)
+#define CP_FLAG_UNK01_CLEAR           0
+#define CP_FLAG_UNK01_SET             1
+#define CP_FLAG_UNK03                 ((0 * 32) + 3)
+#define CP_FLAG_UNK03_CLEAR           0
+#define CP_FLAG_UNK03_SET             1
+#define CP_FLAG_USER_SAVE             ((0 * 32) + 5)
+#define CP_FLAG_USER_SAVE_NOT_PENDING 0
+#define CP_FLAG_USER_SAVE_PENDING     1
+#define CP_FLAG_USER_LOAD             ((0 * 32) + 6)
+#define CP_FLAG_USER_LOAD_NOT_PENDING 0
+#define CP_FLAG_USER_LOAD_PENDING     1
+#define CP_FLAG_UNK0B                 ((0 * 32) + 0xb)
+#define CP_FLAG_UNK0B_CLEAR           0
+#define CP_FLAG_UNK0B_SET             1
+#define CP_FLAG_UNK1D                 ((0 * 32) + 0x1d)
+#define CP_FLAG_UNK1D_CLEAR           0
+#define CP_FLAG_UNK1D_SET             1
+#define CP_FLAG_UNK20                 ((1 * 32) + 0)
+#define CP_FLAG_UNK20_CLEAR           0
+#define CP_FLAG_UNK20_SET             1
+#define CP_FLAG_STATUS                ((2 * 32) + 0)
+#define CP_FLAG_STATUS_BUSY           0
+#define CP_FLAG_STATUS_IDLE           1
+#define CP_FLAG_AUTO_SAVE             ((2 * 32) + 4)
+#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
+#define CP_FLAG_AUTO_SAVE_PENDING     1
+#define CP_FLAG_AUTO_LOAD             ((2 * 32) + 5)
+#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
+#define CP_FLAG_AUTO_LOAD_PENDING     1
+#define CP_FLAG_XFER                  ((2 * 32) + 11)
+#define CP_FLAG_XFER_IDLE             0
+#define CP_FLAG_XFER_BUSY             1
+#define CP_FLAG_NEWCTX                ((2 * 32) + 12)
+#define CP_FLAG_NEWCTX_BUSY           0
+#define CP_FLAG_NEWCTX_DONE           1
+#define CP_FLAG_ALWAYS                ((2 * 32) + 13)
+#define CP_FLAG_ALWAYS_FALSE          0
+#define CP_FLAG_ALWAYS_TRUE           1
+
+#define CP_CTX                   0x00100000
+#define CP_CTX_COUNT             0x000f0000
+#define CP_CTX_COUNT_SHIFT               16
+#define CP_CTX_REG               0x00003fff
+#define CP_LOAD_SR               0x00200000
+#define CP_LOAD_SR_VALUE         0x000fffff
+#define CP_BRA                   0x00400000
+#define CP_BRA_IP                0x0001ff00
+#define CP_BRA_IP_SHIFT                   8
+#define CP_BRA_IF_CLEAR          0x00000080
+#define CP_BRA_FLAG              0x0000007f
+#define CP_WAIT                  0x00500000
+#define CP_WAIT_SET              0x00000080
+#define CP_WAIT_FLAG             0x0000007f
+#define CP_SET                   0x00700000
+#define CP_SET_1                 0x00000080
+#define CP_SET_FLAG              0x0000007f
+#define CP_NEWCTX                0x00600004
+#define CP_NEXT_TO_SWAP          0x00600005
+#define CP_SET_CONTEXT_POINTER   0x00600006
+#define CP_SET_XFER_POINTER      0x00600007
+#define CP_ENABLE                0x00600009
+#define CP_END                   0x0060000c
+#define CP_NEXT_TO_CURRENT       0x0060000d
+#define CP_DISABLE1              0x0090ffff
+#define CP_DISABLE2              0x0091ffff
+#define CP_XFER_1      0x008000ff
+#define CP_XFER_2      0x008800ff
+#define CP_SEEK_1      0x00c000ff
+#define CP_SEEK_2      0x00c800ff
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_grctx.h"
+
+/*
+ * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's
+ * the GPU itself that does context-switching, but it needs a special
+ * microcode to do it. And it's the driver's task to supply this microcode,
+ * further known as ctxprog, as well as the initial context values, known
+ * as ctxvals.
+ *
+ * Without ctxprog, you cannot switch contexts. Not even in software, since
+ * the majority of context [xfer strands] isn't accessible directly. You're
+ * stuck with a single channel, and you also suffer all the problems resulting
+ * from missing ctxvals, since you cannot load them.
+ *
+ * Without ctxvals, you're stuck with PGRAPH's default context. It's enough to
+ * run 2d operations, but trying to utilise 3d or CUDA will just lock you up,
+ * since you don't have... some sort of needed setup.
+ *
+ * Nouveau will just disable acceleration if not given ctxprog + ctxvals, since
+ * it's too much hassle to handle no-ctxprog as a special case.
+ */
+
+/*
+ * How ctxprogs work.
+ *
+ * The ctxprog is written in its own kind of microcode, with very small and
+ * crappy set of available commands. You upload it to a small [512 insns]
+ * area of memory on PGRAPH, and it'll be run when PFIFO wants PGRAPH to
+ * switch channel. or when the driver explicitely requests it. Stuff visible
+ * to ctxprog consists of: PGRAPH MMIO registers, PGRAPH context strands,
+ * the per-channel context save area in VRAM [known as ctxvals or grctx],
+ * 4 flags registers, a scratch register, two grctx pointers, plus many
+ * random poorly-understood details.
+ *
+ * When ctxprog runs, it's supposed to check what operations are asked of it,
+ * save old context if requested, optionally reset PGRAPH and switch to the
+ * new channel, and load the new context. Context consists of three major
+ * parts: subset of MMIO registers and two "xfer areas".
+ */
+
+/* TODO:
+ *  - document unimplemented bits compared to nvidia
+ *  - NVAx: make a TP subroutine, use it.
+ *  - use 0x4008fc instead of 0x1540?
+ */
+
+enum cp_label {
+	cp_check_load = 1,
+	cp_setup_auto_load,
+	cp_setup_load,
+	cp_setup_save,
+	cp_swap_state,
+	cp_prepare_exit,
+	cp_exit,
+};
+
+static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx);
+
+/* Main function: construct the ctxprog skeleton, call the other functions. */
+
+int
+nv50_grctx_init(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+
+	switch (dev_priv->chipset) {
+	case 0x50:
+	case 0x84:
+	case 0x86:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+	case 0x98:
+	case 0xa0:
+	case 0xa5:
+	case 0xa8:
+	case 0xaa:
+	case 0xac:
+		break;
+	default:
+		NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for "
+				   "your NV%x card.\n", dev_priv->chipset);
+		NV_ERROR(ctx->dev, "Disabling acceleration. Please contact "
+				   "the devs.\n");
+		return -ENOSYS;
+	}
+	/* decide whether we're loading/unloading the context */
+	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
+	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
+
+	cp_name(ctx, cp_check_load);
+	cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
+	cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
+	cp_bra (ctx, ALWAYS, TRUE, cp_exit);
+
+	/* setup for context load */
+	cp_name(ctx, cp_setup_auto_load);
+	cp_out (ctx, CP_DISABLE1);
+	cp_out (ctx, CP_DISABLE2);
+	cp_out (ctx, CP_ENABLE);
+	cp_out (ctx, CP_NEXT_TO_SWAP);
+	cp_set (ctx, UNK01, SET);
+	cp_name(ctx, cp_setup_load);
+	cp_out (ctx, CP_NEWCTX);
+	cp_wait(ctx, NEWCTX, BUSY);
+	cp_set (ctx, UNK1D, CLEAR);
+	cp_set (ctx, SWAP_DIRECTION, LOAD);
+	cp_bra (ctx, UNK0B, SET, cp_prepare_exit);
+	cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
+
+	/* setup for context save */
+	cp_name(ctx, cp_setup_save);
+	cp_set (ctx, UNK1D, SET);
+	cp_wait(ctx, STATUS, BUSY);
+	cp_set (ctx, UNK01, SET);
+	cp_set (ctx, SWAP_DIRECTION, SAVE);
+
+	/* general PGRAPH state */
+	cp_name(ctx, cp_swap_state);
+	cp_set (ctx, UNK03, SET);
+	cp_pos (ctx, 0x00004/4);
+	cp_ctx (ctx, 0x400828, 1); /* needed. otherwise, flickering happens. */
+	cp_pos (ctx, 0x00100/4);
+	nv50_graph_construct_mmio(ctx);
+	nv50_graph_construct_xfer1(ctx);
+	nv50_graph_construct_xfer2(ctx);
+
+	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
+
+	cp_set (ctx, UNK20, SET);
+	cp_set (ctx, SWAP_DIRECTION, SAVE); /* no idea why this is needed, but fixes at least one lockup. */
+	cp_lsr (ctx, ctx->ctxvals_base);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, 4);
+	cp_out (ctx, CP_SEEK_1);
+	cp_out (ctx, CP_XFER_1);
+	cp_wait(ctx, XFER, BUSY);
+
+	/* pre-exit state updates */
+	cp_name(ctx, cp_prepare_exit);
+	cp_set (ctx, UNK01, CLEAR);
+	cp_set (ctx, UNK03, CLEAR);
+	cp_set (ctx, UNK1D, CLEAR);
+
+	cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
+	cp_out (ctx, CP_NEXT_TO_CURRENT);
+
+	cp_name(ctx, cp_exit);
+	cp_set (ctx, USER_SAVE, NOT_PENDING);
+	cp_set (ctx, USER_LOAD, NOT_PENDING);
+	cp_out (ctx, CP_END);
+	ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
+
+	return 0;
+}
+
+/*
+ * Constructs MMIO part of ctxprog and ctxvals. Just a matter of knowing which
+ * registers to save/restore and the default values for them.
+ */
+
+static void
+nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i, j;
+	int offset, base;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+
+	/* 0800 */
+	cp_ctx(ctx, 0x400808, 7);
+	gr_def(ctx, 0x400814, 0x00000030);
+	cp_ctx(ctx, 0x400834, 0x32);
+	if (dev_priv->chipset == 0x50) {
+		gr_def(ctx, 0x400834, 0xff400040);
+		gr_def(ctx, 0x400838, 0xfff00080);
+		gr_def(ctx, 0x40083c, 0xfff70090);
+		gr_def(ctx, 0x400840, 0xffe806a8);
+	}
+	gr_def(ctx, 0x400844, 0x00000002);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		gr_def(ctx, 0x400894, 0x00001000);
+	gr_def(ctx, 0x4008e8, 0x00000003);
+	gr_def(ctx, 0x4008ec, 0x00001000);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x400908, 0xb);
+	else if (dev_priv->chipset < 0xa0)
+		cp_ctx(ctx, 0x400908, 0xc);
+	else
+		cp_ctx(ctx, 0x400908, 0xe);
+
+	if (dev_priv->chipset >= 0xa0)
+		cp_ctx(ctx, 0x400b00, 0x1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		cp_ctx(ctx, 0x400b10, 0x1);
+		gr_def(ctx, 0x400b10, 0x0001629d);
+		cp_ctx(ctx, 0x400b20, 0x1);
+		gr_def(ctx, 0x400b20, 0x0001629d);
+	}
+
+	/* 0C00 */
+	cp_ctx(ctx, 0x400c08, 0x2);
+	gr_def(ctx, 0x400c08, 0x0000fe0c);
+
+	/* 1000 */
+	if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x401008, 0x4);
+		gr_def(ctx, 0x401014, 0x00001000);
+	} else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) {
+		cp_ctx(ctx, 0x401008, 0x5);
+		gr_def(ctx, 0x401018, 0x00001000);
+	} else {
+		cp_ctx(ctx, 0x401008, 0x5);
+		gr_def(ctx, 0x401018, 0x00004000);
+	}
+
+	/* 1400 */
+	cp_ctx(ctx, 0x401400, 0x8);
+	cp_ctx(ctx, 0x401424, 0x3);
+	if (dev_priv->chipset == 0x50)
+		gr_def(ctx, 0x40142c, 0x0001fd87);
+	else
+		gr_def(ctx, 0x40142c, 0x00000187);
+	cp_ctx(ctx, 0x401540, 0x5);
+	gr_def(ctx, 0x401550, 0x00001018);
+
+	/* 1800 */
+	cp_ctx(ctx, 0x401814, 0x1);
+	gr_def(ctx, 0x401814, 0x000000ff);
+	if (dev_priv->chipset == 0x50) {
+		cp_ctx(ctx, 0x40181c, 0xe);
+		gr_def(ctx, 0x401850, 0x00000004);
+	} else if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x40181c, 0xf);
+		gr_def(ctx, 0x401854, 0x00000004);
+	} else {
+		cp_ctx(ctx, 0x40181c, 0x13);
+		gr_def(ctx, 0x401864, 0x00000004);
+	}
+
+	/* 1C00 */
+	cp_ctx(ctx, 0x401c00, 0x1);
+	switch (dev_priv->chipset) {
+	case 0x50:
+		gr_def(ctx, 0x401c00, 0x0001005f);
+		break;
+	case 0x84:
+	case 0x86:
+	case 0x94:
+		gr_def(ctx, 0x401c00, 0x044d00df);
+		break;
+	case 0x92:
+	case 0x96:
+	case 0x98:
+	case 0xa0:
+	case 0xaa:
+	case 0xac:
+		gr_def(ctx, 0x401c00, 0x042500df);
+		break;
+	case 0xa5:
+	case 0xa8:
+		gr_def(ctx, 0x401c00, 0x142500df);
+		break;
+	}
+
+	/* 2400 */
+	cp_ctx(ctx, 0x402400, 0x1);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x402408, 0x1);
+	else
+		cp_ctx(ctx, 0x402408, 0x2);
+	gr_def(ctx, 0x402408, 0x00000600);
+
+	/* 2800 */
+	cp_ctx(ctx, 0x402800, 0x1);
+	if (dev_priv->chipset == 0x50)
+		gr_def(ctx, 0x402800, 0x00000006);
+
+	/* 2C00 */
+	cp_ctx(ctx, 0x402c08, 0x6);
+	if (dev_priv->chipset != 0x50)
+		gr_def(ctx, 0x402c14, 0x01000000);
+	gr_def(ctx, 0x402c18, 0x000000ff);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x402ca0, 0x1);
+	else
+		cp_ctx(ctx, 0x402ca0, 0x2);
+	if (dev_priv->chipset < 0xa0)
+		gr_def(ctx, 0x402ca0, 0x00000400);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		gr_def(ctx, 0x402ca0, 0x00000800);
+	else
+		gr_def(ctx, 0x402ca0, 0x00000400);
+	cp_ctx(ctx, 0x402cac, 0x4);
+
+	/* 3000 */
+	cp_ctx(ctx, 0x403004, 0x1);
+	gr_def(ctx, 0x403004, 0x00000001);
+
+	/* 3404 */
+	if (dev_priv->chipset >= 0xa0) {
+		cp_ctx(ctx, 0x403404, 0x1);
+		gr_def(ctx, 0x403404, 0x00000001);
+	}
+
+	/* 5000 */
+	cp_ctx(ctx, 0x405000, 0x1);
+	switch (dev_priv->chipset) {
+	case 0x50:
+		gr_def(ctx, 0x405000, 0x00300080);
+		break;
+	case 0x84:
+	case 0xa0:
+	case 0xa5:
+	case 0xa8:
+	case 0xaa:
+	case 0xac:
+		gr_def(ctx, 0x405000, 0x000e0080);
+		break;
+	case 0x86:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+	case 0x98:
+		gr_def(ctx, 0x405000, 0x00000080);
+		break;
+	}
+	cp_ctx(ctx, 0x405014, 0x1);
+	gr_def(ctx, 0x405014, 0x00000004);
+	cp_ctx(ctx, 0x40501c, 0x1);
+	cp_ctx(ctx, 0x405024, 0x1);
+	cp_ctx(ctx, 0x40502c, 0x1);
+
+	/* 5400 or maybe 4800 */
+	if (dev_priv->chipset == 0x50) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xea);
+	} else if (dev_priv->chipset < 0x94) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xcb);
+	} else if (dev_priv->chipset < 0xa0) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xcc);
+	} else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		offset = 0x404800;
+		cp_ctx(ctx, 0x404800, 0xda);
+	} else {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xd4);
+	}
+	gr_def(ctx, offset + 0x0c, 0x00000002);
+	gr_def(ctx, offset + 0x10, 0x00000001);
+	if (dev_priv->chipset >= 0x94)
+		offset += 4;
+	gr_def(ctx, offset + 0x1c, 0x00000001);
+	gr_def(ctx, offset + 0x20, 0x00000100);
+	gr_def(ctx, offset + 0x38, 0x00000002);
+	gr_def(ctx, offset + 0x3c, 0x00000001);
+	gr_def(ctx, offset + 0x40, 0x00000001);
+	gr_def(ctx, offset + 0x50, 0x00000001);
+	gr_def(ctx, offset + 0x54, 0x003fffff);
+	gr_def(ctx, offset + 0x58, 0x00001fff);
+	gr_def(ctx, offset + 0x60, 0x00000001);
+	gr_def(ctx, offset + 0x64, 0x00000001);
+	gr_def(ctx, offset + 0x6c, 0x00000001);
+	gr_def(ctx, offset + 0x70, 0x00000001);
+	gr_def(ctx, offset + 0x74, 0x00000001);
+	gr_def(ctx, offset + 0x78, 0x00000004);
+	gr_def(ctx, offset + 0x7c, 0x00000001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x80, 0x00000001);
+	gr_def(ctx, offset + 0x84, 0x00000001);
+	gr_def(ctx, offset + 0x88, 0x00000007);
+	gr_def(ctx, offset + 0x8c, 0x00000001);
+	gr_def(ctx, offset + 0x90, 0x00000007);
+	gr_def(ctx, offset + 0x94, 0x00000001);
+	gr_def(ctx, offset + 0x98, 0x00000001);
+	gr_def(ctx, offset + 0x9c, 0x00000001);
+	if (dev_priv->chipset == 0x50) {
+		 gr_def(ctx, offset + 0xb0, 0x00000001);
+		 gr_def(ctx, offset + 0xb4, 0x00000001);
+		 gr_def(ctx, offset + 0xbc, 0x00000001);
+		 gr_def(ctx, offset + 0xc0, 0x0000000a);
+		 gr_def(ctx, offset + 0xd0, 0x00000040);
+		 gr_def(ctx, offset + 0xd8, 0x00000002);
+		 gr_def(ctx, offset + 0xdc, 0x00000100);
+		 gr_def(ctx, offset + 0xe0, 0x00000001);
+		 gr_def(ctx, offset + 0xe4, 0x00000100);
+		 gr_def(ctx, offset + 0x100, 0x00000001);
+		 gr_def(ctx, offset + 0x124, 0x00000004);
+		 gr_def(ctx, offset + 0x13c, 0x00000001);
+		 gr_def(ctx, offset + 0x140, 0x00000100);
+		 gr_def(ctx, offset + 0x148, 0x00000001);
+		 gr_def(ctx, offset + 0x154, 0x00000100);
+		 gr_def(ctx, offset + 0x158, 0x00000001);
+		 gr_def(ctx, offset + 0x15c, 0x00000100);
+		 gr_def(ctx, offset + 0x164, 0x00000001);
+		 gr_def(ctx, offset + 0x170, 0x00000100);
+		 gr_def(ctx, offset + 0x174, 0x00000001);
+		 gr_def(ctx, offset + 0x17c, 0x00000001);
+		 gr_def(ctx, offset + 0x188, 0x00000002);
+		 gr_def(ctx, offset + 0x190, 0x00000001);
+		 gr_def(ctx, offset + 0x198, 0x00000001);
+		 gr_def(ctx, offset + 0x1ac, 0x00000003);
+		 offset += 0xd0;
+	} else {
+		gr_def(ctx, offset + 0xb0, 0x00000001);
+		gr_def(ctx, offset + 0xb4, 0x00000100);
+		gr_def(ctx, offset + 0xbc, 0x00000001);
+		gr_def(ctx, offset + 0xc8, 0x00000100);
+		gr_def(ctx, offset + 0xcc, 0x00000001);
+		gr_def(ctx, offset + 0xd0, 0x00000100);
+		gr_def(ctx, offset + 0xd8, 0x00000001);
+		gr_def(ctx, offset + 0xe4, 0x00000100);
+	}
+	gr_def(ctx, offset + 0xf8, 0x00000004);
+	gr_def(ctx, offset + 0xfc, 0x00000070);
+	gr_def(ctx, offset + 0x100, 0x00000080);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x114, 0x0000000c);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x11c, 0x00000008);
+	gr_def(ctx, offset + 0x120, 0x00000014);
+	if (dev_priv->chipset == 0x50) {
+		gr_def(ctx, offset + 0x124, 0x00000026);
+		offset -= 0x18;
+	} else {
+		gr_def(ctx, offset + 0x128, 0x00000029);
+		gr_def(ctx, offset + 0x12c, 0x00000027);
+		gr_def(ctx, offset + 0x130, 0x00000026);
+		gr_def(ctx, offset + 0x134, 0x00000008);
+		gr_def(ctx, offset + 0x138, 0x00000004);
+		gr_def(ctx, offset + 0x13c, 0x00000027);
+	}
+	gr_def(ctx, offset + 0x148, 0x00000001);
+	gr_def(ctx, offset + 0x14c, 0x00000002);
+	gr_def(ctx, offset + 0x150, 0x00000003);
+	gr_def(ctx, offset + 0x154, 0x00000004);
+	gr_def(ctx, offset + 0x158, 0x00000005);
+	gr_def(ctx, offset + 0x15c, 0x00000006);
+	gr_def(ctx, offset + 0x160, 0x00000007);
+	gr_def(ctx, offset + 0x164, 0x00000001);
+	gr_def(ctx, offset + 0x1a8, 0x000000cf);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x1d8, 0x00000080);
+	gr_def(ctx, offset + 0x1dc, 0x00000004);
+	gr_def(ctx, offset + 0x1e0, 0x00000004);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	else
+		gr_def(ctx, offset + 0x1e4, 0x00000003);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		gr_def(ctx, offset + 0x1ec, 0x00000003);
+		offset += 8;
+	}
+	gr_def(ctx, offset + 0x1e8, 0x00000001);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x1f4, 0x00000012);
+	gr_def(ctx, offset + 0x1f8, 0x00000010);
+	gr_def(ctx, offset + 0x1fc, 0x0000000c);
+	gr_def(ctx, offset + 0x200, 0x00000001);
+	gr_def(ctx, offset + 0x210, 0x00000004);
+	gr_def(ctx, offset + 0x214, 0x00000002);
+	gr_def(ctx, offset + 0x218, 0x00000004);
+	if (dev_priv->chipset >= 0xa0)
+		offset += 4;
+	gr_def(ctx, offset + 0x224, 0x003fffff);
+	gr_def(ctx, offset + 0x228, 0x00001fff);
+	if (dev_priv->chipset == 0x50)
+		offset -= 0x20;
+	else if (dev_priv->chipset >= 0xa0) {
+		gr_def(ctx, offset + 0x250, 0x00000001);
+		gr_def(ctx, offset + 0x254, 0x00000001);
+		gr_def(ctx, offset + 0x258, 0x00000002);
+		offset += 0x10;
+	}
+	gr_def(ctx, offset + 0x250, 0x00000004);
+	gr_def(ctx, offset + 0x254, 0x00000014);
+	gr_def(ctx, offset + 0x258, 0x00000001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x264, 0x00000002);
+	if (dev_priv->chipset >= 0xa0)
+		offset += 8;
+	gr_def(ctx, offset + 0x270, 0x00000001);
+	gr_def(ctx, offset + 0x278, 0x00000002);
+	gr_def(ctx, offset + 0x27c, 0x00001000);
+	if (dev_priv->chipset == 0x50)
+		offset -= 0xc;
+	else {
+		gr_def(ctx, offset + 0x280, 0x00000e00);
+		gr_def(ctx, offset + 0x284, 0x00001000);
+		gr_def(ctx, offset + 0x288, 0x00001e00);
+	}
+	gr_def(ctx, offset + 0x290, 0x00000001);
+	gr_def(ctx, offset + 0x294, 0x00000001);
+	gr_def(ctx, offset + 0x298, 0x00000001);
+	gr_def(ctx, offset + 0x29c, 0x00000001);
+	gr_def(ctx, offset + 0x2a0, 0x00000001);
+	gr_def(ctx, offset + 0x2b0, 0x00000200);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		gr_def(ctx, offset + 0x2b4, 0x00000200);
+		offset += 4;
+	}
+	if (dev_priv->chipset < 0xa0) {
+		gr_def(ctx, offset + 0x2b8, 0x00000001);
+		gr_def(ctx, offset + 0x2bc, 0x00000070);
+		gr_def(ctx, offset + 0x2c0, 0x00000080);
+		gr_def(ctx, offset + 0x2cc, 0x00000001);
+		gr_def(ctx, offset + 0x2d0, 0x00000070);
+		gr_def(ctx, offset + 0x2d4, 0x00000080);
+	} else {
+		gr_def(ctx, offset + 0x2b8, 0x00000001);
+		gr_def(ctx, offset + 0x2bc, 0x000000f0);
+		gr_def(ctx, offset + 0x2c0, 0x000000ff);
+		gr_def(ctx, offset + 0x2cc, 0x00000001);
+		gr_def(ctx, offset + 0x2d0, 0x000000f0);
+		gr_def(ctx, offset + 0x2d4, 0x000000ff);
+		gr_def(ctx, offset + 0x2dc, 0x00000009);
+		offset += 4;
+	}
+	gr_def(ctx, offset + 0x2e4, 0x00000001);
+	gr_def(ctx, offset + 0x2e8, 0x000000cf);
+	gr_def(ctx, offset + 0x2f0, 0x00000001);
+	gr_def(ctx, offset + 0x300, 0x000000cf);
+	gr_def(ctx, offset + 0x308, 0x00000002);
+	gr_def(ctx, offset + 0x310, 0x00000001);
+	gr_def(ctx, offset + 0x318, 0x00000001);
+	gr_def(ctx, offset + 0x320, 0x000000cf);
+	gr_def(ctx, offset + 0x324, 0x000000cf);
+	gr_def(ctx, offset + 0x328, 0x00000001);
+
+	/* 6000? */
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x4063e0, 0x1);
+
+	/* 6800 */
+	if (dev_priv->chipset < 0x90) {
+		cp_ctx(ctx, 0x406814, 0x2b);
+		gr_def(ctx, 0x406818, 0x00000f80);
+		gr_def(ctx, 0x406860, 0x007f0080);
+		gr_def(ctx, 0x40689c, 0x007f0080);
+	} else {
+		cp_ctx(ctx, 0x406814, 0x4);
+		if (dev_priv->chipset == 0x98)
+			gr_def(ctx, 0x406818, 0x00000f80);
+		else
+			gr_def(ctx, 0x406818, 0x00001f80);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			gr_def(ctx, 0x40681c, 0x00000030);
+		cp_ctx(ctx, 0x406830, 0x3);
+	}
+
+	/* 7000: per-ROP group state */
+	for (i = 0; i < 8; i++) {
+		if (units & (1<<(i+16))) {
+			cp_ctx(ctx, 0x407000 + (i<<8), 3);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820);
+			else if (dev_priv->chipset != 0xa5)
+				gr_def(ctx, 0x407000 + (i<<8), 0x3b74f821);
+			else
+				gr_def(ctx, 0x407000 + (i<<8), 0x7b74f821);
+			gr_def(ctx, 0x407004 + (i<<8), 0x89058001);
+
+			if (dev_priv->chipset == 0x50) {
+				cp_ctx(ctx, 0x407010 + (i<<8), 1);
+			} else if (dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, 0x407010 + (i<<8), 2);
+				gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
+				gr_def(ctx, 0x407014 + (i<<8), 0x0000001f);
+			} else {
+				cp_ctx(ctx, 0x407010 + (i<<8), 3);
+				gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
+				if (dev_priv->chipset != 0xa5)
+					gr_def(ctx, 0x407014 + (i<<8), 0x000000ff);
+				else
+					gr_def(ctx, 0x407014 + (i<<8), 0x000001ff);
+			}
+
+			cp_ctx(ctx, 0x407080 + (i<<8), 4);
+			if (dev_priv->chipset != 0xa5)
+				gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa);
+			else
+				gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, 0x407084 + (i<<8), 0x000000c0);
+			else
+				gr_def(ctx, 0x407084 + (i<<8), 0x400000c0);
+			gr_def(ctx, 0x407088 + (i<<8), 0xb7892080);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, 0x407094 + (i<<8), 1);
+			else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+				cp_ctx(ctx, 0x407094 + (i<<8), 3);
+			else {
+				cp_ctx(ctx, 0x407094 + (i<<8), 4);
+				gr_def(ctx, 0x4070a0 + (i<<8), 1);
+			}
+		}
+	}
+
+	cp_ctx(ctx, 0x407c00, 0x3);
+	if (dev_priv->chipset < 0x90)
+		gr_def(ctx, 0x407c00, 0x00010040);
+	else if (dev_priv->chipset < 0xa0)
+		gr_def(ctx, 0x407c00, 0x00390040);
+	else
+		gr_def(ctx, 0x407c00, 0x003d0040);
+	gr_def(ctx, 0x407c08, 0x00000022);
+	if (dev_priv->chipset >= 0xa0) {
+		cp_ctx(ctx, 0x407c10, 0x3);
+		cp_ctx(ctx, 0x407c20, 0x1);
+		cp_ctx(ctx, 0x407c2c, 0x1);
+	}
+
+	if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x407d00, 0x9);
+	} else {
+		cp_ctx(ctx, 0x407d00, 0x15);
+	}
+	if (dev_priv->chipset == 0x98)
+		gr_def(ctx, 0x407d08, 0x00380040);
+	else {
+		if (dev_priv->chipset < 0x90)
+			gr_def(ctx, 0x407d08, 0x00010040);
+		else if (dev_priv->chipset < 0xa0)
+			gr_def(ctx, 0x407d08, 0x00390040);
+		else
+			gr_def(ctx, 0x407d08, 0x003d0040);
+		gr_def(ctx, 0x407d0c, 0x00000022);
+	}
+
+	/* 8000+: per-TP state */
+	for (i = 0; i < 10; i++) {
+		if (units & (1<<i)) {
+			if (dev_priv->chipset < 0xa0)
+				base = 0x408000 + (i<<12);
+			else
+				base = 0x408000 + (i<<11);
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xc00;
+			else
+				offset = base + 0x80;
+			cp_ctx(ctx, offset + 0x00, 1);
+			gr_def(ctx, offset + 0x00, 0x0000ff0a);
+			cp_ctx(ctx, offset + 0x08, 1);
+
+			/* per-MP state */
+			for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) {
+				if (!(units & (1 << (j+24)))) continue;
+				if (dev_priv->chipset < 0xa0)
+					offset = base + 0x200 + (j<<7);
+				else
+					offset = base + 0x100 + (j<<7);
+				cp_ctx(ctx, offset, 0x20);
+				gr_def(ctx, offset + 0x00, 0x01800000);
+				gr_def(ctx, offset + 0x04, 0x00160000);
+				gr_def(ctx, offset + 0x08, 0x01800000);
+				gr_def(ctx, offset + 0x18, 0x0003ffff);
+				switch (dev_priv->chipset) {
+				case 0x50:
+					gr_def(ctx, offset + 0x1c, 0x00080000);
+					break;
+				case 0x84:
+					gr_def(ctx, offset + 0x1c, 0x00880000);
+					break;
+				case 0x86:
+					gr_def(ctx, offset + 0x1c, 0x008c0000);
+					break;
+				case 0x92:
+				case 0x96:
+				case 0x98:
+					gr_def(ctx, offset + 0x1c, 0x118c0000);
+					break;
+				case 0x94:
+					gr_def(ctx, offset + 0x1c, 0x10880000);
+					break;
+				case 0xa0:
+				case 0xa5:
+					gr_def(ctx, offset + 0x1c, 0x310c0000);
+					break;
+				case 0xa8:
+				case 0xaa:
+				case 0xac:
+					gr_def(ctx, offset + 0x1c, 0x300c0000);
+					break;
+				}
+				gr_def(ctx, offset + 0x40, 0x00010401);
+				if (dev_priv->chipset == 0x50)
+					gr_def(ctx, offset + 0x48, 0x00000040);
+				else
+					gr_def(ctx, offset + 0x48, 0x00000078);
+				gr_def(ctx, offset + 0x50, 0x000000bf);
+				gr_def(ctx, offset + 0x58, 0x00001210);
+				if (dev_priv->chipset == 0x50)
+					gr_def(ctx, offset + 0x5c, 0x00000080);
+				else
+					gr_def(ctx, offset + 0x5c, 0x08000080);
+				if (dev_priv->chipset >= 0xa0)
+					gr_def(ctx, offset + 0x68, 0x0000003e);
+			}
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x300, 0x4);
+			else
+				cp_ctx(ctx, base + 0x300, 0x5);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, base + 0x304, 0x00007070);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, base + 0x304, 0x00027070);
+			else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+				gr_def(ctx, base + 0x304, 0x01127070);
+			else
+				gr_def(ctx, base + 0x304, 0x05127070);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x318, 1);
+			else
+				cp_ctx(ctx, base + 0x320, 1);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, base + 0x318, 0x0003ffff);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, base + 0x318, 0x03ffffff);
+			else
+				gr_def(ctx, base + 0x320, 0x07ffffff);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x324, 5);
+			else
+				cp_ctx(ctx, base + 0x328, 4);
+
+			if (dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, base + 0x340, 9);
+				offset = base + 0x340;
+			} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+				cp_ctx(ctx, base + 0x33c, 0xb);
+				offset = base + 0x344;
+			} else {
+				cp_ctx(ctx, base + 0x33c, 0xd);
+				offset = base + 0x344;
+			}
+			gr_def(ctx, offset + 0x0, 0x00120407);
+			gr_def(ctx, offset + 0x4, 0x05091507);
+			if (dev_priv->chipset == 0x84)
+				gr_def(ctx, offset + 0x8, 0x05100202);
+			else
+				gr_def(ctx, offset + 0x8, 0x05010202);
+			gr_def(ctx, offset + 0xc, 0x00030201);
+
+			cp_ctx(ctx, base + 0x400, 2);
+			gr_def(ctx, base + 0x404, 0x00000040);
+			cp_ctx(ctx, base + 0x40c, 2);
+			gr_def(ctx, base + 0x40c, 0x0d0c0b0a);
+			gr_def(ctx, base + 0x410, 0x00141210);
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0x800;
+			else
+				offset = base + 0x500;
+			cp_ctx(ctx, offset, 6);
+			gr_def(ctx, offset + 0x0, 0x000001f0);
+			gr_def(ctx, offset + 0x4, 0x00000001);
+			gr_def(ctx, offset + 0x8, 0x00000003);
+			if (dev_priv->chipset == 0x50 || dev_priv->chipset >= 0xaa)
+				gr_def(ctx, offset + 0xc, 0x00008000);
+			gr_def(ctx, offset + 0x14, 0x00039e00);
+			cp_ctx(ctx, offset + 0x1c, 2);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, offset + 0x1c, 0x00000040);
+			else
+				gr_def(ctx, offset + 0x1c, 0x00000100);
+			gr_def(ctx, offset + 0x20, 0x00003800);
+
+			if (dev_priv->chipset >= 0xa0) {
+				cp_ctx(ctx, base + 0x54c, 2);
+				if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+					gr_def(ctx, base + 0x54c, 0x003fe006);
+				else
+					gr_def(ctx, base + 0x54c, 0x003fe007);
+				gr_def(ctx, base + 0x550, 0x003fe000);
+			}
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xa00;
+			else
+				offset = base + 0x680;
+			cp_ctx(ctx, offset, 1);
+			gr_def(ctx, offset, 0x00404040);
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xe00;
+			else
+				offset = base + 0x700;
+			cp_ctx(ctx, offset, 2);
+			if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, offset, 0x0077f005);
+			else if (dev_priv->chipset == 0xa5)
+				gr_def(ctx, offset, 0x6cf7f007);
+			else if (dev_priv->chipset == 0xa8)
+				gr_def(ctx, offset, 0x6cfff007);
+			else if (dev_priv->chipset == 0xac)
+				gr_def(ctx, offset, 0x0cfff007);
+			else
+				gr_def(ctx, offset, 0x0cf7f007);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, offset + 0x4, 0x00007fff);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, offset + 0x4, 0x003f7fff);
+			else
+				gr_def(ctx, offset + 0x4, 0x02bf7fff);
+			cp_ctx(ctx, offset + 0x2c, 1);
+			if (dev_priv->chipset == 0x50) {
+				cp_ctx(ctx, offset + 0x50, 9);
+				gr_def(ctx, offset + 0x54, 0x000003ff);
+				gr_def(ctx, offset + 0x58, 0x00000003);
+				gr_def(ctx, offset + 0x5c, 0x00000003);
+				gr_def(ctx, offset + 0x60, 0x000001ff);
+				gr_def(ctx, offset + 0x64, 0x0000001f);
+				gr_def(ctx, offset + 0x68, 0x0000000f);
+				gr_def(ctx, offset + 0x6c, 0x0000000f);
+			} else if(dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, offset + 0x50, 1);
+				cp_ctx(ctx, offset + 0x70, 1);
+			} else {
+				cp_ctx(ctx, offset + 0x50, 1);
+				cp_ctx(ctx, offset + 0x60, 5);
+			}
+		}
+	}
+}
+
+/*
+ * xfer areas. These are a pain.
+ *
+ * There are 2 xfer areas: the first one is big and contains all sorts of
+ * stuff, the second is small and contains some per-TP context.
+ *
+ * Each area is split into 8 "strands". The areas, when saved to grctx,
+ * are made of 8-word blocks. Each block contains a single word from
+ * each strand. The strands are independent of each other, their
+ * addresses are unrelated to each other, and data in them is closely
+ * packed together. The strand layout varies a bit between cards: here
+ * and there, a single word is thrown out in the middle and the whole
+ * strand is offset by a bit from corresponding one on another chipset.
+ * For this reason, addresses of stuff in strands are almost useless.
+ * Knowing sequence of stuff and size of gaps between them is much more
+ * useful, and that's how we build the strands in our generator.
+ *
+ * NVA0 takes this mess to a whole new level by cutting the old strands
+ * into a few dozen pieces [known as genes], rearranging them randomly,
+ * and putting them back together to make new strands. Hopefully these
+ * genes correspond more or less directly to the same PGRAPH subunits
+ * as in 400040 register.
+ *
+ * The most common value in default context is 0, and when the genes
+ * are separated by 0's, gene bounduaries are quite speculative...
+ * some of them can be clearly deduced, others can be guessed, and yet
+ * others won't be resolved without figuring out the real meaning of
+ * given ctxval. For the same reason, ending point of each strand
+ * is unknown. Except for strand 0, which is the longest strand and
+ * its end corresponds to end of the whole xfer.
+ *
+ * An unsolved mystery is the seek instruction: it takes an argument
+ * in bits 8-18, and that argument is clearly the place in strands to
+ * seek to... but the offsets don't seem to correspond to offsets as
+ * seen in grctx. Perhaps there's another, real, not randomly-changing
+ * addressing in strands, and the xfer insn just happens to skip over
+ * the unused bits? NV10-NV30 PIPE comes to mind...
+ *
+ * As far as I know, there's no way to access the xfer areas directly
+ * without the help of ctxprog.
+ */
+
+static inline void
+xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) {
+	int i;
+	if (val && ctx->mode == NOUVEAU_GRCTX_VALS)
+		for (i = 0; i < num; i++)
+			nv_wo32(ctx->dev, ctx->data, ctx->ctxvals_pos + (i << 3), val);
+	ctx->ctxvals_pos += num << 3;
+}
+
+/* Gene declarations... */
+
+static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx);
+
+static void
+nv50_graph_construct_xfer1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+	int offset;
+	int size = 0;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+
+	offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	ctx->ctxvals_base = offset;
+
+	if (dev_priv->chipset < 0xa0) {
+		/* Strand 0 */
+		ctx->ctxvals_pos = offset;
+		switch (dev_priv->chipset) {
+		case 0x50:
+			xf_emit(ctx, 0x99, 0);
+			break;
+		case 0x84:
+		case 0x86:
+			xf_emit(ctx, 0x384, 0);
+			break;
+		case 0x92:
+		case 0x94:
+		case 0x96:
+		case 0x98:
+			xf_emit(ctx, 0x380, 0);
+			break;
+		}
+		nv50_graph_construct_gene_m2mf (ctx);
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x84:
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0x4c4, 0);
+			break;
+		case 0x92:
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0x984, 0);
+			break;
+		}
+		nv50_graph_construct_gene_unk5(ctx);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 0xa, 0);
+		else
+			xf_emit(ctx, 0xb, 0);
+		nv50_graph_construct_gene_unk4(ctx);
+		nv50_graph_construct_gene_unk3(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 1 */
+		ctx->ctxvals_pos = offset + 0x1;
+		nv50_graph_construct_gene_unk6(ctx);
+		nv50_graph_construct_gene_unk7(ctx);
+		nv50_graph_construct_gene_unk8(ctx);
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x92:
+			xf_emit(ctx, 0xfb, 0);
+			break;
+		case 0x84:
+			xf_emit(ctx, 0xd3, 0);
+			break;
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0xab, 0);
+			break;
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0x6b, 0);
+			break;
+		}
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 4, 0);
+		xf_emit(ctx, 1, 0x0fac6881);
+		xf_emit(ctx, 0xb, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 2 */
+		ctx->ctxvals_pos = offset + 0x2;
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x92:
+			xf_emit(ctx, 0xa80, 0);
+			break;
+		case 0x84:
+			xf_emit(ctx, 0xa7e, 0);
+			break;
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0xa7c, 0);
+			break;
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0xa7a, 0);
+			break;
+		}
+		xf_emit(ctx, 1, 0x3fffff);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1fff);
+		xf_emit(ctx, 0xe, 0);
+		nv50_graph_construct_gene_unk9(ctx);
+		nv50_graph_construct_gene_unk2(ctx);
+		nv50_graph_construct_gene_unk1(ctx);
+		nv50_graph_construct_gene_unk10(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 3: per-ROP group state */
+		ctx->ctxvals_pos = offset + 3;
+		for (i = 0; i < 6; i++)
+			if (units & (1 << (i + 16)))
+				nv50_graph_construct_gene_ropc(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strands 4-7: per-TP state */
+		for (i = 0; i < 4; i++) {
+			ctx->ctxvals_pos = offset + 4 + i;
+			if (units & (1 << (2 * i)))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << (2 * i + 1)))
+				nv50_graph_construct_xfer_tp(ctx);
+			if ((ctx->ctxvals_pos-offset)/8 > size)
+				size = (ctx->ctxvals_pos-offset)/8;
+		}
+	} else {
+		/* Strand 0 */
+		ctx->ctxvals_pos = offset;
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0x385, 0);
+		else
+			xf_emit(ctx, 0x384, 0);
+		nv50_graph_construct_gene_m2mf(ctx);
+		xf_emit(ctx, 0x950, 0);
+		nv50_graph_construct_gene_unk10(ctx);
+		xf_emit(ctx, 1, 0x0fac6881);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+			xf_emit(ctx, 1, 1);
+			xf_emit(ctx, 3, 0);
+		}
+		nv50_graph_construct_gene_unk8(ctx);
+		if (dev_priv->chipset == 0xa0)
+			xf_emit(ctx, 0x189, 0);
+		else if (dev_priv->chipset < 0xa8)
+			xf_emit(ctx, 0x99, 0);
+		else if (dev_priv->chipset == 0xaa)
+			xf_emit(ctx, 0x65, 0);
+		else
+			xf_emit(ctx, 0x6d, 0);
+		nv50_graph_construct_gene_unk9(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 1 */
+		ctx->ctxvals_pos = offset + 1;
+		nv50_graph_construct_gene_unk1(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 2 */
+		ctx->ctxvals_pos = offset + 2;
+		if (dev_priv->chipset == 0xa0) {
+			nv50_graph_construct_gene_unk2(ctx);
+		}
+		xf_emit(ctx, 0x36, 0);
+		nv50_graph_construct_gene_unk5(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 3 */
+		ctx->ctxvals_pos = offset + 3;
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 1);
+		nv50_graph_construct_gene_unk6(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 4 */
+		ctx->ctxvals_pos = offset + 4;
+		if (dev_priv->chipset == 0xa0)
+			xf_emit(ctx, 0xa80, 0);
+		else
+			xf_emit(ctx, 0xa7a, 0);
+		xf_emit(ctx, 1, 0x3fffff);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1fff);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 5 */
+		ctx->ctxvals_pos = offset + 5;
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 0x0fac6881);
+		xf_emit(ctx, 0xb, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 3, 0);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 1, 0x11);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 1, 0x11);
+		xf_emit(ctx, 1, 0);
+		for (i = 0; i < 8; i++)
+			if (units & (1<<(i+16)))
+				nv50_graph_construct_gene_ropc(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 6 */
+		ctx->ctxvals_pos = offset + 6;
+		nv50_graph_construct_gene_unk3(ctx);
+		xf_emit(ctx, 0xb, 0);
+		nv50_graph_construct_gene_unk4(ctx);
+		nv50_graph_construct_gene_unk7(ctx);
+		if (units & (1 << 0))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 1))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 2))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 3))
+			nv50_graph_construct_xfer_tp(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 7 */
+		ctx->ctxvals_pos = offset + 7;
+		if (dev_priv->chipset == 0xa0) {
+			if (units & (1 << 4))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 5))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 6))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 7))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 8))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 9))
+				nv50_graph_construct_xfer_tp(ctx);
+		} else {
+			nv50_graph_construct_gene_unk2(ctx);
+		}
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+	}
+
+	ctx->ctxvals_pos = offset + size * 8;
+	ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	cp_lsr (ctx, offset);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, size);
+	cp_out (ctx, CP_SEEK_1);
+	cp_out (ctx, CP_XFER_1);
+	cp_wait(ctx, XFER, BUSY);
+}
+
+/*
+ * non-trivial demagiced parts of ctx init go here
+ */
+
+static void
+nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx)
+{
+	/* m2mf state */
+	xf_emit (ctx, 1, 0);		/* DMA_NOTIFY instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* DMA_BUFFER_IN instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* DMA_BUFFER_OUT instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* OFFSET_IN */
+	xf_emit (ctx, 1, 0);		/* OFFSET_OUT */
+	xf_emit (ctx, 1, 0);		/* PITCH_IN */
+	xf_emit (ctx, 1, 0);		/* PITCH_OUT */
+	xf_emit (ctx, 1, 0);		/* LINE_LENGTH */
+	xf_emit (ctx, 1, 0);		/* LINE_COUNT */
+	xf_emit (ctx, 1, 0x21);		/* FORMAT: bits 0-4 INPUT_INC, bits 5-9 OUTPUT_INC */
+	xf_emit (ctx, 1, 1);		/* LINEAR_IN */
+	xf_emit (ctx, 1, 0x2);		/* TILING_MODE_IN: bits 0-2 y tiling, bits 3-5 z tiling */
+	xf_emit (ctx, 1, 0x100);	/* TILING_PITCH_IN */
+	xf_emit (ctx, 1, 0x100);	/* TILING_HEIGHT_IN */
+	xf_emit (ctx, 1, 1);		/* TILING_DEPTH_IN */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_IN_Z */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_IN */
+	xf_emit (ctx, 1, 1);		/* LINEAR_OUT */
+	xf_emit (ctx, 1, 0x2);		/* TILING_MODE_OUT: bits 0-2 y tiling, bits 3-5 z tiling */
+	xf_emit (ctx, 1, 0x100);	/* TILING_PITCH_OUT */
+	xf_emit (ctx, 1, 0x100);	/* TILING_HEIGHT_OUT */
+	xf_emit (ctx, 1, 1);		/* TILING_DEPTH_OUT */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_OUT_Z */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_OUT */
+	xf_emit (ctx, 1, 0);		/* OFFSET_IN_HIGH */
+	xf_emit (ctx, 1, 0);		/* OFFSET_OUT_HIGH */
+}
+
+static void
+nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* end of area 2 on pre-NVA0, area 1 on NVAx */
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	switch (dev_priv->chipset) {
+	case 0x50:
+	case 0x86:
+	case 0x98:
+	case 0xaa:
+	case 0xac:
+		xf_emit(ctx, 0x542, 0);
+		break;
+	case 0x84:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+		xf_emit(ctx, 0x942, 0);
+		break;
+	case 0xa0:
+		xf_emit(ctx, 0x2042, 0);
+		break;
+	case 0xa5:
+	case 0xa8:
+		xf_emit(ctx, 0x842, 0);
+		break;
+	}
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x27);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 3, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx)
+{
+	/* end of area 2 on pre-NVA0, area 1 on NVAx */
+	xf_emit(ctx, 0x10, 0x04000000);
+	xf_emit(ctx, 0x24, 0);
+	xf_emit(ctx, 2, 0x04e3bfdf);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x1fe21);
+}
+
+static void
+nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */
+	if (dev_priv->chipset != 0x50) {
+		xf_emit(ctx, 5, 0);
+		xf_emit(ctx, 1, 0x80c14);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x804);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 2, 4);
+		xf_emit(ctx, 1, 0x8100c12);
+	}
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 3, 0);
+	else
+		xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x804);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x1a);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 0x7f);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 6, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 0x38, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x38, 0);
+	xf_emit(ctx, 2, 0x88);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 0x16, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x3f800000);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 0x28, 0);
+	else
+		xf_emit(ctx, 0x25, 0);
+	xf_emit(ctx, 1, 0x52);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* end of area 0 on pre-NVA0, beginning of area 6 on NVAx */
+	xf_emit(ctx, 1, 0x3f);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x10, 0);
+	else
+		xf_emit(ctx, 0x11, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x1001);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 0x20, 0);
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0);
+	else
+		xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 2, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx)
+{
+	/* middle of area 0 on pre-NVA0, middle of area 6 on NVAx */
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 0 on pre-NVA0 [after m2mf], end of area 2 on NVAx */
+	xf_emit(ctx, 2, 4);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x1c4d, 0);
+	else
+		xf_emit(ctx, 0x1c4b, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x8100c12);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0x27);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x3c1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x16, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* beginning of area 1 on pre-NVA0 [after m2mf], area 3 on NVAx */
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 8, 0);
+	else
+		xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x20);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x11, 0);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 0xf, 0);
+	else
+		xf_emit(ctx, 0xe, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 0xd, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 8);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	if (dev_priv->chipset == 0xa8)
+		xf_emit(ctx, 1, 0x1e00);
+	xf_emit(ctx, 0xc, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x125, 0);
+	else if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x126, 0);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		xf_emit(ctx, 0x124, 0);
+	else
+		xf_emit(ctx, 0x1f7, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 3, 0);
+	else
+		xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xa1, 0);
+	else
+		xf_emit(ctx, 0x5a, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x834, 0);
+	else if (dev_priv->chipset == 0xa0)
+		xf_emit(ctx, 0x1873, 0);
+	else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x8ba, 0);
+	else
+		xf_emit(ctx, 0x833, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 0xf, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 1 on pre-NVA0 [after m2mf], middle of area 6 on NVAx */
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0x100);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 8);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 0xcf);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x15);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x4444480);
+	xf_emit(ctx, 0x37, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx)
+{
+	/* middle of area 1 on pre-NVA0 [after m2mf], middle of area 0 on NVAx */
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 2);
+}
+
+static void
+nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 2 on pre-NVA0 [after m2mf], end of area 0 on NVAx */
+	xf_emit(ctx, 1, 0x3f800000);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x12, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 0xf, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 3);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 5);
+	xf_emit(ctx, 1, 0x52);
+	if (dev_priv->chipset == 0x50) {
+		xf_emit(ctx, 0x13, 0);
+	} else {
+		xf_emit(ctx, 4, 0);
+		xf_emit(ctx, 1, 1);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0x11, 0);
+		else
+			xf_emit(ctx, 0x10, 0);
+	}
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x26, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 5);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 4, 0xffff);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 3);
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x1f, 0);
+	else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xc, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 1, 0x1a);
+	if (dev_priv->chipset != 0x50) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 3);
+	}
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x26, 0);
+	else
+		xf_emit(ctx, 0x3c, 0);
+	xf_emit(ctx, 1, 0x102);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 4, 4);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x102);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 4, 4);
+	xf_emit(ctx, 0x2c, 0);
+}
+
+static void
+nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic2;
+	if (dev_priv->chipset == 0x50) {
+		magic2 = 0x00003e60;
+	} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+		magic2 = 0x001ffe67;
+	} else {
+		magic2 = 0x00087e67;
+	}
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 7, 0);
+	if (dev_priv->chipset >= 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 0x15);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 1, 4);
+		xf_emit(ctx, 1, 0x400);
+		xf_emit(ctx, 1, 0x300);
+		xf_emit(ctx, 1, 0x1001);
+		if (dev_priv->chipset != 0xa0) {
+			if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+				xf_emit(ctx, 1, 0);
+			else
+				xf_emit(ctx, 1, 0x15);
+		}
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x13, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x10, 0);
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 0x19, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x3f);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1001);
+		xf_emit(ctx, 0xb, 0);
+	} else {
+		xf_emit(ctx, 0xc, 0);
+	}
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x11);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 3, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 5, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 0x16, 0);
+	} else {
+		if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 0x1b, 0);
+		else
+			xf_emit(ctx, 0x15, 0);
+	}
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x5b, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic3;
+	if (dev_priv->chipset == 0x50)
+		magic3 = 0x1000;
+	else if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8)
+		magic3 = 0x1e00;
+	else
+		magic3 = 0;
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x24, 0);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 0x14, 0);
+	else
+		xf_emit(ctx, 0x15, 0);
+	xf_emit(ctx, 2, 4);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 0x03020100);
+	else
+		xf_emit(ctx, 1, 0x00608080);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x80);
+	if (magic3)
+		xf_emit(ctx, 1, magic3);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 0x24, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x03020100);
+	xf_emit(ctx, 1, 3);
+	if (magic3)
+		xf_emit(ctx, 1, magic3);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96)
+		xf_emit(ctx, 0x1024, 0);
+	else if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0xa24, 0);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		xf_emit(ctx, 0x214, 0);
+	else
+		xf_emit(ctx, 0x414, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 2, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic1, magic2;
+	if (dev_priv->chipset == 0x50) {
+		magic1 = 0x3ff;
+		magic2 = 0x00003e60;
+	} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+		magic1 = 0x7ff;
+		magic2 = 0x001ffe67;
+	} else {
+		magic1 = 0x7ff;
+		magic2 = 0x00087e67;
+	}
+	xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xc, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 0xb, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 3);
+		xf_emit(ctx, 1, 0);
+	} else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 1, 0);
+	}
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 0xcf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 8, 1);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x11);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	if(dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x28, 0);
+	xf_emit(ctx, 8, 8);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 8, 0x400);
+	xf_emit(ctx, 8, 0x300);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x20);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x40);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x400);
+	xf_emit(ctx, 1, 0x300);
+	xf_emit(ctx, 1, 0x1001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 0x15, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 3, 0);
+	} else
+		xf_emit(ctx, 0x17, 0);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 0);
+	else if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x3(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 2, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x2a712488);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x4085c000);
+	xf_emit(ctx, 1, 0x40);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0x10100);
+	xf_emit(ctx, 1, 0x02800000);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x4(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 2, 0x04e3bfdf);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x30201000);
+	xf_emit(ctx, 1, 0x70605040);
+	xf_emit(ctx, 1, 0xb8a89888);
+	xf_emit(ctx, 1, 0xf8e8d8c8);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1a);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x5(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xb, 0);
+	else
+		xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 8, 1);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 6, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 6, 0);
+	} else {
+		xf_emit(ctx, 0xb, 0);
+	}
+}
+
+static void
+nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	if (dev_priv->chipset < 0xa0) {
+		nv50_graph_construct_xfer_tp_x1(ctx);
+		nv50_graph_construct_xfer_tp_x2(ctx);
+		nv50_graph_construct_xfer_tp_x3(ctx);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 0xf, 0);
+		else
+			xf_emit(ctx, 0x12, 0);
+		nv50_graph_construct_xfer_tp_x4(ctx);
+	} else {
+		nv50_graph_construct_xfer_tp_x3(ctx);
+		if (dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0xc, 0);
+		else
+			xf_emit(ctx, 0xa, 0);
+		nv50_graph_construct_xfer_tp_x2(ctx);
+		nv50_graph_construct_xfer_tp_x5(ctx);
+		nv50_graph_construct_xfer_tp_x4(ctx);
+		nv50_graph_construct_xfer_tp_x1(ctx);
+	}
+}
+
+static void
+nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i, mpcnt;
+	if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa)
+		mpcnt = 1;
+	else if (dev_priv->chipset < 0xa0 || dev_priv->chipset >= 0xa8)
+		mpcnt = 2;
+	else
+		mpcnt = 3;
+	for (i = 0; i < mpcnt; i++) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 0x80);
+		xf_emit(ctx, 1, 0x80007004);
+		xf_emit(ctx, 1, 0x04000400);
+		if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 1, 0xc0);
+		xf_emit(ctx, 1, 0x1000);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) {
+			xf_emit(ctx, 1, 0xe00);
+			xf_emit(ctx, 1, 0x1e00);
+		}
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 2, 0x1000);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 4);
+		xf_emit(ctx, 1, 2);
+		if (dev_priv->chipset >= 0xaa)
+			xf_emit(ctx, 0xb, 0);
+		else if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 0xc, 0);
+		else
+			xf_emit(ctx, 0xa, 0);
+	}
+	xf_emit(ctx, 1, 0x08100c12);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 1, 0x1fe21);
+	}
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1fe21);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x08100c12);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x3a0, 0);
+	else if (dev_priv->chipset < 0x94)
+		xf_emit(ctx, 0x3a2, 0);
+	else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa)
+		xf_emit(ctx, 0x39f, 0);
+	else
+		xf_emit(ctx, 0x3a3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x2d, 0);
+}
+
+static void
+nv50_graph_construct_xfer2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+	uint32_t offset;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+	int size = 0;
+
+	offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
+
+	if (dev_priv->chipset < 0xa0) {
+		for (i = 0; i < 8; i++) {
+			ctx->ctxvals_pos = offset + i;
+			if (i == 0)
+				xf_emit(ctx, 1, 0x08100c12);
+			if (units & (1 << i))
+				nv50_graph_construct_xfer_tp2(ctx);
+			if ((ctx->ctxvals_pos-offset)/8 > size)
+				size = (ctx->ctxvals_pos-offset)/8;
+		}
+	} else {
+		/* Strand 0: TPs 0, 1 */
+		ctx->ctxvals_pos = offset;
+		xf_emit(ctx, 1, 0x08100c12);
+		if (units & (1 << 0))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 1))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 2, 3 */
+		ctx->ctxvals_pos = offset + 1;
+		if (units & (1 << 2))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 3))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 4, 5, 6 */
+		ctx->ctxvals_pos = offset + 2;
+		if (units & (1 << 4))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 5))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 6))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 7, 8, 9 */
+		ctx->ctxvals_pos = offset + 3;
+		if (units & (1 << 7))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 8))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 9))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+	}
+	ctx->ctxvals_pos = offset + size * 8;
+	ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	cp_lsr (ctx, offset);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, size);
+	cp_out (ctx, CP_SEEK_2);
+	cp_out (ctx, CP_XFER_2);
+	cp_wait(ctx, XFER, BUSY);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 Red Hat <bskeggs@redhat.com>
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/*
+ * Authors:
+ *  Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <linux/debugfs.h>
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+
+static int
+nouveau_debugfs_channel_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct nouveau_channel *chan = node->info_ent->data;
+
+	seq_printf(m, "channel id    : %d\n", chan->id);
+
+	seq_printf(m, "cpu fifo state:\n");
+	seq_printf(m, "          base: 0x%08x\n", chan->pushbuf_base);
+	seq_printf(m, "           max: 0x%08x\n", chan->dma.max << 2);
+	seq_printf(m, "           cur: 0x%08x\n", chan->dma.cur << 2);
+	seq_printf(m, "           put: 0x%08x\n", chan->dma.put << 2);
+	seq_printf(m, "          free: 0x%08x\n", chan->dma.free << 2);
+
+	seq_printf(m, "gpu fifo state:\n");
+	seq_printf(m, "           get: 0x%08x\n",
+					nvchan_rd32(chan, chan->user_get));
+	seq_printf(m, "           put: 0x%08x\n",
+					nvchan_rd32(chan, chan->user_put));
+
+	seq_printf(m, "last fence    : %d\n", chan->fence.sequence);
+	seq_printf(m, "last signalled: %d\n", chan->fence.sequence_ack);
+	return 0;
+}
+
+int
+nouveau_debugfs_channel_init(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct drm_minor *minor = chan->dev->primary;
+	int ret;
+
+	if (!dev_priv->debugfs.channel_root) {
+		dev_priv->debugfs.channel_root =
+			debugfs_create_dir("channel", minor->debugfs_root);
+		if (!dev_priv->debugfs.channel_root)
+			return -ENOENT;
+	}
+
+	snprintf(chan->debugfs.name, 32, "%d", chan->id);
+	chan->debugfs.info.name = chan->debugfs.name;
+	chan->debugfs.info.show = nouveau_debugfs_channel_info;
+	chan->debugfs.info.driver_features = 0;
+	chan->debugfs.info.data = chan;
+
+	ret = drm_debugfs_create_files(&chan->debugfs.info, 1,
+				       dev_priv->debugfs.channel_root,
+				       chan->dev->primary);
+	if (ret == 0)
+		chan->debugfs.active = true;
+	return ret;
+}
+
+void
+nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+
+	if (!chan->debugfs.active)
+		return;
+
+	drm_debugfs_remove_files(&chan->debugfs.info, 1, chan->dev->primary);
+	chan->debugfs.active = false;
+
+	if (chan == dev_priv->channel) {
+		debugfs_remove(dev_priv->debugfs.channel_root);
+		dev_priv->debugfs.channel_root = NULL;
+	}
+}
+
+static int
+nouveau_debugfs_chipset_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_minor *minor = node->minor;
+	struct drm_device *dev = minor->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t ppci_0;
+
+	ppci_0 = nv_rd32(dev, dev_priv->chipset >= 0x40 ? 0x88000 : 0x1800);
+
+	seq_printf(m, "PMC_BOOT_0: 0x%08x\n", nv_rd32(dev, NV03_PMC_BOOT_0));
+	seq_printf(m, "PCI ID    : 0x%04x:0x%04x\n",
+		   ppci_0 & 0xffff, ppci_0 >> 16);
+	return 0;
+}
+
+static int
+nouveau_debugfs_memory_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_minor *minor = node->minor;
+	struct drm_device *dev = minor->dev;
+
+	seq_printf(m, "VRAM total: %dKiB\n",
+		   (int)(nouveau_mem_fb_amount(dev) >> 10));
+	return 0;
+}
+
+static struct drm_info_list nouveau_debugfs_list[] = {
+	{ "chipset", nouveau_debugfs_chipset_info, 0, NULL },
+	{ "memory", nouveau_debugfs_memory_info, 0, NULL },
+};
+#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
+
+int
+nouveau_debugfs_init(struct drm_minor *minor)
+{
+	drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
+				 minor->debugfs_root, minor);
+	return 0;
+}
+
+void
+nouveau_debugfs_takedown(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES,
+				 minor);
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright 2007 Dave Airlied
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
+ */
+/*
+ * Authors: Dave Airlied <airlied@linux.ie>
+ *	    Ben Skeggs   <darktama@iinet.net.au>
+ *	    Jeremy Kolb  <jkolb@brandeis.edu>
+ */
+
+#include "drmP.h"
+
+#include "nouveau_drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+
+#include <linux/log2.h>
+
+static void
+nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct drm_device *dev = dev_priv->dev;
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+
+	ttm_bo_kunmap(&nvbo->kmap);
+
+	if (unlikely(nvbo->gem))
+		DRM_ERROR("bo %p still attached to GEM object\n", bo);
+
+	if (nvbo->tile)
+		nv10_mem_expire_tiling(dev, nvbo->tile, NULL);
+
+	spin_lock(&dev_priv->ttm.bo_list_lock);
+	list_del(&nvbo->head);
+	spin_unlock(&dev_priv->ttm.bo_list_lock);
+	kfree(nvbo);
+}
+
+static void
+nouveau_bo_fixup_align(struct drm_device *dev,
+		       uint32_t tile_mode, uint32_t tile_flags,
+		       int *align, int *size)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	/*
+	 * Some of the tile_flags have a periodic structure of N*4096 bytes,
+	 * align to to that as well as the page size. Align the size to the
+	 * appropriate boundaries. This does imply that sizes are rounded up
+	 * 3-7 pages, so be aware of this and do not waste memory by allocating
+	 * many small buffers.
+	 */
+	if (dev_priv->card_type == NV_50) {
+		uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15;
+		int i;
+
+		switch (tile_flags) {
+		case 0x1800:
+		case 0x2800:
+		case 0x4800:
+		case 0x7a00:
+			if (is_power_of_2(block_size)) {
+				for (i = 1; i < 10; i++) {
+					*align = 12 * i * block_size;
+					if (!(*align % 65536))
+						break;
+				}
+			} else {
+				for (i = 1; i < 10; i++) {
+					*align = 8 * i * block_size;
+					if (!(*align % 65536))
+						break;
+				}
+			}
+			*size = roundup(*size, *align);
+			break;
+		default:
+			break;
+		}
+
+	} else {
+		if (tile_mode) {
+			if (dev_priv->chipset >= 0x40) {
+				*align = 65536;
+				*size = roundup(*size, 64 * tile_mode);
+
+			} else if (dev_priv->chipset >= 0x30) {
+				*align = 32768;
+				*size = roundup(*size, 64 * tile_mode);
+
+			} else if (dev_priv->chipset >= 0x20) {
+				*align = 16384;
+				*size = roundup(*size, 64 * tile_mode);
+
+			} else if (dev_priv->chipset >= 0x10) {
+				*align = 16384;
+				*size = roundup(*size, 32 * tile_mode);
+			}
+		}
+	}
+
+	/* ALIGN works only on powers of two. */
+	*size = roundup(*size, PAGE_SIZE);
+
+	if (dev_priv->card_type == NV_50) {
+		*size = roundup(*size, 65536);
+		*align = max(65536, *align);
+	}
+}
+
+int
+nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
+	       int size, int align, uint32_t flags, uint32_t tile_mode,
+	       uint32_t tile_flags, bool no_vm, bool mappable,
+	       struct nouveau_bo **pnvbo)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_bo *nvbo;
+	int ret = 0;
+
+	nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
+	if (!nvbo)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&nvbo->head);
+	INIT_LIST_HEAD(&nvbo->entry);
+	nvbo->mappable = mappable;
+	nvbo->no_vm = no_vm;
+	nvbo->tile_mode = tile_mode;
+	nvbo->tile_flags = tile_flags;
+
+	nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size);
+	align >>= PAGE_SHIFT;
+
+	nvbo->placement.fpfn = 0;
+	nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0;
+	nouveau_bo_placement_set(nvbo, flags);
+
+	nvbo->channel = chan;
+	ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
+			  ttm_bo_type_device, &nvbo->placement, align, 0,
+			  false, NULL, size, nouveau_bo_del_ttm);
+	nvbo->channel = NULL;
+	if (ret) {
+		/* ttm will call nouveau_bo_del_ttm if it fails.. */
+		return ret;
+	}
+
+	spin_lock(&dev_priv->ttm.bo_list_lock);
+	list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list);
+	spin_unlock(&dev_priv->ttm.bo_list_lock);
+	*pnvbo = nvbo;
+	return 0;
+}
+
+void
+nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t memtype)
+{
+	int n = 0;
+
+	if (memtype & TTM_PL_FLAG_VRAM)
+		nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING;
+	if (memtype & TTM_PL_FLAG_TT)
+		nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	if (memtype & TTM_PL_FLAG_SYSTEM)
+		nvbo->placements[n++] = TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
+	nvbo->placement.placement = nvbo->placements;
+	nvbo->placement.busy_placement = nvbo->placements;
+	nvbo->placement.num_placement = n;
+	nvbo->placement.num_busy_placement = n;
+
+	if (nvbo->pin_refcnt) {
+		while (n--)
+			nvbo->placements[n] |= TTM_PL_FLAG_NO_EVICT;
+	}
+}
+
+int
+nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
+	struct ttm_buffer_object *bo = &nvbo->bo;
+	int ret, i;
+
+	if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) {
+		NV_ERROR(nouveau_bdev(bo->bdev)->dev,
+			 "bo %p pinned elsewhere: 0x%08x vs 0x%08x\n", bo,
+			 1 << bo->mem.mem_type, memtype);
+		return -EINVAL;
+	}
+
+	if (nvbo->pin_refcnt++)
+		return 0;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (ret)
+		goto out;
+
+	nouveau_bo_placement_set(nvbo, memtype);
+	for (i = 0; i < nvbo->placement.num_placement; i++)
+		nvbo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+
+	ret = ttm_bo_validate(bo, &nvbo->placement, false, false);
+	if (ret == 0) {
+		switch (bo->mem.mem_type) {
+		case TTM_PL_VRAM:
+			dev_priv->fb_aper_free -= bo->mem.size;
+			break;
+		case TTM_PL_TT:
+			dev_priv->gart_info.aper_free -= bo->mem.size;
+			break;
+		default:
+			break;
+		}
+	}
+	ttm_bo_unreserve(bo);
+out:
+	if (unlikely(ret))
+		nvbo->pin_refcnt--;
+	return ret;
+}
+
+int
+nouveau_bo_unpin(struct nouveau_bo *nvbo)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
+	struct ttm_buffer_object *bo = &nvbo->bo;
+	int ret, i;
+
+	if (--nvbo->pin_refcnt)
+		return 0;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nvbo->placement.num_placement; i++)
+		nvbo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
+
+	ret = ttm_bo_validate(bo, &nvbo->placement, false, false);
+	if (ret == 0) {
+		switch (bo->mem.mem_type) {
+		case TTM_PL_VRAM:
+			dev_priv->fb_aper_free += bo->mem.size;
+			break;
+		case TTM_PL_TT:
+			dev_priv->gart_info.aper_free += bo->mem.size;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ttm_bo_unreserve(bo);
+	return ret;
+}
+
+int
+nouveau_bo_map(struct nouveau_bo *nvbo)
+{
+	int ret;
+
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap);
+	ttm_bo_unreserve(&nvbo->bo);
+	return ret;
+}
+
+void
+nouveau_bo_unmap(struct nouveau_bo *nvbo)
+{
+	ttm_bo_kunmap(&nvbo->kmap);
+}
+
+u16
+nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index)
+{
+	bool is_iomem;
+	u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
+	mem = &mem[index];
+	if (is_iomem)
+		return ioread16_native((void __force __iomem *)mem);
+	else
+		return *mem;
+}
+
+void
+nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val)
+{
+	bool is_iomem;
+	u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
+	mem = &mem[index];
+	if (is_iomem)
+		iowrite16_native(val, (void __force __iomem *)mem);
+	else
+		*mem = val;
+}
+
+u32
+nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index)
+{
+	bool is_iomem;
+	u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
+	mem = &mem[index];
+	if (is_iomem)
+		return ioread32_native((void __force __iomem *)mem);
+	else
+		return *mem;
+}
+
+void
+nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val)
+{
+	bool is_iomem;
+	u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
+	mem = &mem[index];
+	if (is_iomem)
+		iowrite32_native(val, (void __force __iomem *)mem);
+	else
+		*mem = val;
+}
+
+static struct ttm_backend *
+nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
+	struct drm_device *dev = dev_priv->dev;
+
+	switch (dev_priv->gart_info.type) {
+#if __OS_HAS_AGP
+	case NOUVEAU_GART_AGP:
+		return ttm_agp_backend_init(bdev, dev->agp->bridge);
+#endif
+	case NOUVEAU_GART_SGDMA:
+		return nouveau_sgdma_init_ttm(dev);
+	default:
+		NV_ERROR(dev, "Unknown GART type %d\n",
+			 dev_priv->gart_info.type);
+		break;
+	}
+
+	return NULL;
+}
+
+static int
+nouveau_bo_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+{
+	/* We'll do this from user space. */
+	return 0;
+}
+
+static int
+nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+			 struct ttm_mem_type_manager *man)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
+	struct drm_device *dev = dev_priv->dev;
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_VRAM:
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+			     TTM_MEMTYPE_FLAG_MAPPABLE |
+			     TTM_MEMTYPE_FLAG_NEEDS_IOREMAP;
+		man->available_caching = TTM_PL_FLAG_UNCACHED |
+					 TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+
+		man->io_addr = NULL;
+		man->io_offset = drm_get_resource_start(dev, 1);
+		man->io_size = drm_get_resource_len(dev, 1);
+		if (man->io_size > nouveau_mem_fb_amount(dev))
+			man->io_size = nouveau_mem_fb_amount(dev);
+
+		man->gpu_offset = dev_priv->vm_vram_base;
+		break;
+	case TTM_PL_TT:
+		switch (dev_priv->gart_info.type) {
+		case NOUVEAU_GART_AGP:
+			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+				     TTM_MEMTYPE_FLAG_NEEDS_IOREMAP;
+			man->available_caching = TTM_PL_FLAG_UNCACHED;
+			man->default_caching = TTM_PL_FLAG_UNCACHED;
+			break;
+		case NOUVEAU_GART_SGDMA:
+			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+				     TTM_MEMTYPE_FLAG_CMA;
+			man->available_caching = TTM_PL_MASK_CACHING;
+			man->default_caching = TTM_PL_FLAG_CACHED;
+			break;
+		default:
+			NV_ERROR(dev, "Unknown GART type: %d\n",
+				 dev_priv->gart_info.type);
+			return -EINVAL;
+		}
+
+		man->io_offset  = dev_priv->gart_info.aper_base;
+		man->io_size    = dev_priv->gart_info.aper_size;
+		man->io_addr   = NULL;
+		man->gpu_offset = dev_priv->vm_gart_base;
+		break;
+	default:
+		NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void
+nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+
+	switch (bo->mem.mem_type) {
+	case TTM_PL_VRAM:
+		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT |
+					 TTM_PL_FLAG_SYSTEM);
+		break;
+	default:
+		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM);
+		break;
+	}
+
+	*pl = nvbo->placement;
+}
+
+
+/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access
+ * TTM_PL_{VRAM,TT} directly.
+ */
+
+static int
+nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
+			      struct nouveau_bo *nvbo, bool evict, bool no_wait,
+			      struct ttm_mem_reg *new_mem)
+{
+	struct nouveau_fence *fence = NULL;
+	int ret;
+
+	ret = nouveau_fence_new(chan, &fence, true);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
+					evict, no_wait, new_mem);
+	if (nvbo->channel && nvbo->channel != chan)
+		ret = nouveau_fence_wait(fence, NULL, false, false);
+	nouveau_fence_unref((void *)&fence);
+	return ret;
+}
+
+static inline uint32_t
+nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
+		      struct ttm_mem_reg *mem)
+{
+	if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) {
+		if (mem->mem_type == TTM_PL_TT)
+			return NvDmaGART;
+		return NvDmaVRAM;
+	}
+
+	if (mem->mem_type == TTM_PL_TT)
+		return chan->gart_handle;
+	return chan->vram_handle;
+}
+
+static int
+nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
+		     int no_wait, struct ttm_mem_reg *new_mem)
+{
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct nouveau_channel *chan;
+	uint64_t src_offset, dst_offset;
+	uint32_t page_count;
+	int ret;
+
+	chan = nvbo->channel;
+	if (!chan || nvbo->tile_flags || nvbo->no_vm)
+		chan = dev_priv->channel;
+
+	src_offset = old_mem->mm_node->start << PAGE_SHIFT;
+	dst_offset = new_mem->mm_node->start << PAGE_SHIFT;
+	if (chan != dev_priv->channel) {
+		if (old_mem->mem_type == TTM_PL_TT)
+			src_offset += dev_priv->vm_gart_base;
+		else
+			src_offset += dev_priv->vm_vram_base;
+
+		if (new_mem->mem_type == TTM_PL_TT)
+			dst_offset += dev_priv->vm_gart_base;
+		else
+			dst_offset += dev_priv->vm_vram_base;
+	}
+
+	ret = RING_SPACE(chan, 3);
+	if (ret)
+		return ret;
+	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2);
+	OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem));
+	OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem));
+
+	if (dev_priv->card_type >= NV_50) {
+		ret = RING_SPACE(chan, 4);
+		if (ret)
+			return ret;
+		BEGIN_RING(chan, NvSubM2MF, 0x0200, 1);
+		OUT_RING(chan, 1);
+		BEGIN_RING(chan, NvSubM2MF, 0x021c, 1);
+		OUT_RING(chan, 1);
+	}
+
+	page_count = new_mem->num_pages;
+	while (page_count) {
+		int line_count = (page_count > 2047) ? 2047 : page_count;
+
+		if (dev_priv->card_type >= NV_50) {
+			ret = RING_SPACE(chan, 3);
+			if (ret)
+				return ret;
+			BEGIN_RING(chan, NvSubM2MF, 0x0238, 2);
+			OUT_RING(chan, upper_32_bits(src_offset));
+			OUT_RING(chan, upper_32_bits(dst_offset));
+		}
+		ret = RING_SPACE(chan, 11);
+		if (ret)
+			return ret;
+		BEGIN_RING(chan, NvSubM2MF,
+				 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+		OUT_RING(chan, lower_32_bits(src_offset));
+		OUT_RING(chan, lower_32_bits(dst_offset));
+		OUT_RING(chan, PAGE_SIZE); /* src_pitch */
+		OUT_RING(chan, PAGE_SIZE); /* dst_pitch */
+		OUT_RING(chan, PAGE_SIZE); /* line_length */
+		OUT_RING(chan, line_count);
+		OUT_RING(chan, (1<<8)|(1<<0));
+		OUT_RING(chan, 0);
+		BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
+		OUT_RING(chan, 0);
+
+		page_count -= line_count;
+		src_offset += (PAGE_SIZE * line_count);
+		dst_offset += (PAGE_SIZE * line_count);
+	}
+
+	return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait, new_mem);
+}
+
+static int
+nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
+		      bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	struct ttm_placement placement;
+	struct ttm_mem_reg tmp_mem;
+	int ret;
+
+	placement.fpfn = placement.lpfn = 0;
+	placement.num_placement = placement.num_busy_placement = 1;
+	placement.placement = placement.busy_placement = &placement_memtype;
+
+	tmp_mem = *new_mem;
+	tmp_mem.mm_node = NULL;
+	ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait);
+	if (ret)
+		return ret;
+
+	ret = ttm_tt_bind(bo->ttm, &tmp_mem);
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, &tmp_mem);
+	if (ret)
+		goto out;
+
+	ret = ttm_bo_move_ttm(bo, evict, no_wait, new_mem);
+out:
+	if (tmp_mem.mm_node) {
+		spin_lock(&bo->bdev->glob->lru_lock);
+		drm_mm_put_block(tmp_mem.mm_node);
+		spin_unlock(&bo->bdev->glob->lru_lock);
+	}
+
+	return ret;
+}
+
+static int
+nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
+		      bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
+	struct ttm_placement placement;
+	struct ttm_mem_reg tmp_mem;
+	int ret;
+
+	placement.fpfn = placement.lpfn = 0;
+	placement.num_placement = placement.num_busy_placement = 1;
+	placement.placement = placement.busy_placement = &placement_memtype;
+
+	tmp_mem = *new_mem;
+	tmp_mem.mm_node = NULL;
+	ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, intr, no_wait);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_move_ttm(bo, evict, no_wait, &tmp_mem);
+	if (ret)
+		goto out;
+
+	ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem);
+	if (ret)
+		goto out;
+
+out:
+	if (tmp_mem.mm_node) {
+		spin_lock(&bo->bdev->glob->lru_lock);
+		drm_mm_put_block(tmp_mem.mm_node);
+		spin_unlock(&bo->bdev->glob->lru_lock);
+	}
+
+	return ret;
+}
+
+static int
+nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
+		   struct nouveau_tile_reg **new_tile)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct drm_device *dev = dev_priv->dev;
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	uint64_t offset;
+	int ret;
+
+	if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
+		/* Nothing to do. */
+		*new_tile = NULL;
+		return 0;
+	}
+
+	offset = new_mem->mm_node->start << PAGE_SHIFT;
+
+	if (dev_priv->card_type == NV_50) {
+		ret = nv50_mem_vm_bind_linear(dev,
+					      offset + dev_priv->vm_vram_base,
+					      new_mem->size, nvbo->tile_flags,
+					      offset);
+		if (ret)
+			return ret;
+
+	} else if (dev_priv->card_type >= NV_10) {
+		*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
+						nvbo->tile_mode);
+	}
+
+	return 0;
+}
+
+static void
+nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
+		      struct nouveau_tile_reg *new_tile,
+		      struct nouveau_tile_reg **old_tile)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct drm_device *dev = dev_priv->dev;
+
+	if (dev_priv->card_type >= NV_10 &&
+	    dev_priv->card_type < NV_50) {
+		if (*old_tile)
+			nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj);
+
+		*old_tile = new_tile;
+	}
+}
+
+static int
+nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
+		bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct nouveau_tile_reg *new_tile = NULL;
+	int ret = 0;
+
+	ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
+	if (ret)
+		return ret;
+
+	/* Software copy if the card isn't up and running yet. */
+	if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
+	    !dev_priv->channel) {
+		ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+		goto out;
+	}
+
+	/* Fake bo copy. */
+	if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
+		BUG_ON(bo->mem.mm_node != NULL);
+		bo->mem = *new_mem;
+		new_mem->mm_node = NULL;
+		goto out;
+	}
+
+	/* Hardware assisted copy. */
+	if (new_mem->mem_type == TTM_PL_SYSTEM)
+		ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem);
+	else if (old_mem->mem_type == TTM_PL_SYSTEM)
+		ret = nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem);
+	else
+		ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem);
+
+	if (!ret)
+		goto out;
+
+	/* Fallback to software copy. */
+	ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+
+out:
+	if (ret)
+		nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
+	else
+		nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+
+	return ret;
+}
+
+static int
+nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+	return 0;
+}
+
+struct ttm_bo_driver nouveau_bo_driver = {
+	.create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry,
+	.invalidate_caches = nouveau_bo_invalidate_caches,
+	.init_mem_type = nouveau_bo_init_mem_type,
+	.evict_flags = nouveau_bo_evict_flags,
+	.move = nouveau_bo_move,
+	.verify_access = nouveau_bo_verify_access,
+	.sync_obj_signaled = nouveau_fence_signalled,
+	.sync_obj_wait = nouveau_fence_wait,
+	.sync_obj_flush = nouveau_fence_flush,
+	.sync_obj_unref = nouveau_fence_unref,
+	.sync_obj_ref = nouveau_fence_ref,
+};
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_instmem.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -0,0 +1,208 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+/* returns the size of fifo context */
+static int
+nouveau_fifo_ctx_size(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->chipset >= 0x40)
+		return 128;
+	else
+	if (dev_priv->chipset >= 0x17)
+		return 64;
+
+	return 32;
+}
+
+static void
+nv04_instmem_determine_amount(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* Figure out how much instance memory we need */
+	if (dev_priv->card_type >= NV_40) {
+		/* We'll want more instance memory than this on some NV4x cards.
+		 * There's a 16MB aperture to play with that maps onto the end
+		 * of vram.  For now, only reserve a small piece until we know
+		 * more about what each chipset requires.
+		 */
+		switch (dev_priv->chipset) {
+		case 0x40:
+		case 0x47:
+		case 0x49:
+		case 0x4b:
+			dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024);
+			break;
+		default:
+			dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024);
+			break;
+		}
+	} else {
+		/*XXX: what *are* the limits on <NV40 cards?
+		 */
+		dev_priv->ramin_rsvd_vram = (512 * 1024);
+	}
+	NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10);
+
+	/* Clear all of it, except the BIOS image that's in the first 64KiB */
+	dev_priv->engine.instmem.prepare_access(dev, true);
+	for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4)
+		nv_wi32(dev, i, 0x00000000);
+	dev_priv->engine.instmem.finish_access(dev);
+}
+
+static void
+nv04_instmem_configure_fixed_tables(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
+
+	/* FIFO hash table (RAMHT)
+	 *   use 4k hash table at RAMIN+0x10000
+	 *   TODO: extend the hash table
+	 */
+	dev_priv->ramht_offset = 0x10000;
+	dev_priv->ramht_bits   = 9;
+	dev_priv->ramht_size   = (1 << dev_priv->ramht_bits); /* nr entries */
+	dev_priv->ramht_size  *= 8; /* 2 32-bit values per entry in RAMHT */
+	NV_DEBUG(dev, "RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset,
+						      dev_priv->ramht_size);
+
+	/* FIFO runout table (RAMRO) - 512k at 0x11200 */
+	dev_priv->ramro_offset = 0x11200;
+	dev_priv->ramro_size   = 512;
+	NV_DEBUG(dev, "RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset,
+						      dev_priv->ramro_size);
+
+	/* FIFO context table (RAMFC)
+	 *   NV40  : Not sure exactly how to position RAMFC on some cards,
+	 *           0x30002 seems to position it at RAMIN+0x20000 on these
+	 *           cards.  RAMFC is 4kb (32 fifos, 128byte entries).
+	 *   Others: Position RAMFC at RAMIN+0x11400
+	 */
+	dev_priv->ramfc_size = engine->fifo.channels *
+						nouveau_fifo_ctx_size(dev);
+	switch (dev_priv->card_type) {
+	case NV_40:
+		dev_priv->ramfc_offset = 0x20000;
+		break;
+	case NV_30:
+	case NV_20:
+	case NV_10:
+	case NV_04:
+	default:
+		dev_priv->ramfc_offset = 0x11400;
+		break;
+	}
+	NV_DEBUG(dev, "RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset,
+						      dev_priv->ramfc_size);
+}
+
+int nv04_instmem_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	uint32_t offset;
+	int ret = 0;
+
+	nv04_instmem_determine_amount(dev);
+	nv04_instmem_configure_fixed_tables(dev);
+
+	/* Create a heap to manage RAMIN allocations, we don't allocate
+	 * the space that was reserved for RAMHT/FC/RO.
+	 */
+	offset = dev_priv->ramfc_offset + dev_priv->ramfc_size;
+
+	/* It appears RAMRO (or something?) is controlled by 0x2220/0x2230
+	 * on certain NV4x chipsets as well as RAMFC.  When 0x2230 == 0
+	 * ("new style" control) the upper 16-bits of 0x2220 points at this
+	 * other mysterious table that's clobbering important things.
+	 *
+	 * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting
+	 * smashed to pieces on us, so reserve 0x30000-0x40000 too..
+	 */
+	if (dev_priv->card_type >= NV_40) {
+		if (offset < 0x40000)
+			offset = 0x40000;
+	}
+
+	ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
+				    offset, dev_priv->ramin_rsvd_vram - offset);
+	if (ret) {
+		dev_priv->ramin_heap = NULL;
+		NV_ERROR(dev, "Failed to init RAMIN heap\n");
+	}
+
+	return ret;
+}
+
+void
+nv04_instmem_takedown(struct drm_device *dev)
+{
+}
+
+int
+nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, uint32_t *sz)
+{
+	if (gpuobj->im_backing)
+		return -EINVAL;
+
+	return 0;
+}
+
+void
+nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (gpuobj && gpuobj->im_backing) {
+		if (gpuobj->im_bound)
+			dev_priv->engine.instmem.unbind(dev, gpuobj);
+		gpuobj->im_backing = NULL;
+	}
+}
+
+int
+nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	if (!gpuobj->im_pramin || gpuobj->im_bound)
+		return -EINVAL;
+
+	gpuobj->im_bound = 1;
+	return 0;
+}
+
+int
+nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
+{
+	if (gpuobj->im_bound == 0)
+		return -EINVAL;
+
+	gpuobj->im_bound = 0;
+	return 0;
+}
+
+void
+nv04_instmem_prepare_access(struct drm_device *dev, bool write)
+{
+}
+
+void
+nv04_instmem_finish_access(struct drm_device *dev)
+{
+}
+
+int
+nv04_instmem_suspend(struct drm_device *dev)
+{
+	return 0;
+}
+
+void
+nv04_instmem_resume(struct drm_device *dev)
+{
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_grctx.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_grctx.h
@@ -0,0 +1,133 @@
+#ifndef __NOUVEAU_GRCTX_H__
+#define __NOUVEAU_GRCTX_H__
+
+struct nouveau_grctx {
+	struct drm_device *dev;
+
+	enum {
+		NOUVEAU_GRCTX_PROG,
+		NOUVEAU_GRCTX_VALS
+	} mode;
+	void *data;
+
+	uint32_t ctxprog_max;
+	uint32_t ctxprog_len;
+	uint32_t ctxprog_reg;
+	int      ctxprog_label[32];
+	uint32_t ctxvals_pos;
+	uint32_t ctxvals_base;
+};
+
+#ifdef CP_CTX
+static inline void
+cp_out(struct nouveau_grctx *ctx, uint32_t inst)
+{
+	uint32_t *ctxprog = ctx->data;
+
+	if (ctx->mode != NOUVEAU_GRCTX_PROG)
+		return;
+
+	BUG_ON(ctx->ctxprog_len == ctx->ctxprog_max);
+	ctxprog[ctx->ctxprog_len++] = inst;
+}
+
+static inline void
+cp_lsr(struct nouveau_grctx *ctx, uint32_t val)
+{
+	cp_out(ctx, CP_LOAD_SR | val);
+}
+
+static inline void
+cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length)
+{
+	ctx->ctxprog_reg = (reg - 0x00400000) >> 2;
+
+	ctx->ctxvals_base = ctx->ctxvals_pos;
+	ctx->ctxvals_pos = ctx->ctxvals_base + length;
+
+	if (length > (CP_CTX_COUNT >> CP_CTX_COUNT_SHIFT)) {
+		cp_lsr(ctx, length);
+		length = 0;
+	}
+
+	cp_out(ctx, CP_CTX | (length << CP_CTX_COUNT_SHIFT) | ctx->ctxprog_reg);
+}
+
+static inline void
+cp_name(struct nouveau_grctx *ctx, int name)
+{
+	uint32_t *ctxprog = ctx->data;
+	int i;
+
+	if (ctx->mode != NOUVEAU_GRCTX_PROG)
+		return;
+
+	ctx->ctxprog_label[name] = ctx->ctxprog_len;
+	for (i = 0; i < ctx->ctxprog_len; i++) {
+		if ((ctxprog[i] & 0xfff00000) != 0xff400000)
+			continue;
+		if ((ctxprog[i] & CP_BRA_IP) != ((name) << CP_BRA_IP_SHIFT))
+			continue;
+		ctxprog[i] = (ctxprog[i] & 0x00ff00ff) |
+			     (ctx->ctxprog_len << CP_BRA_IP_SHIFT);
+	}
+}
+
+static inline void
+_cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name)
+{
+	int ip = 0;
+
+	if (mod != 2) {
+		ip = ctx->ctxprog_label[name] << CP_BRA_IP_SHIFT;
+		if (ip == 0)
+			ip = 0xff000000 | (name << CP_BRA_IP_SHIFT);
+	}
+
+	cp_out(ctx, CP_BRA | (mod << 18) | ip | flag |
+		    (state ? 0 : CP_BRA_IF_CLEAR));
+}
+#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
+#ifdef CP_BRA_MOD
+#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
+#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0)
+#endif
+
+static inline void
+_cp_wait(struct nouveau_grctx *ctx, int flag, int state)
+{
+	cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0));
+}
+#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
+
+static inline void
+_cp_set(struct nouveau_grctx *ctx, int flag, int state)
+{
+	cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0));
+}
+#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
+
+static inline void
+cp_pos(struct nouveau_grctx *ctx, int offset)
+{
+	ctx->ctxvals_pos = offset;
+	ctx->ctxvals_base = ctx->ctxvals_pos;
+
+	cp_lsr(ctx, ctx->ctxvals_pos);
+	cp_out(ctx, CP_SET_CONTEXT_POINTER);
+}
+
+static inline void
+gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val)
+{
+	if (ctx->mode != NOUVEAU_GRCTX_VALS)
+		return;
+
+	reg = (reg - 0x00400000) / 4;
+	reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base;
+
+	nv_wo32(ctx->dev, ctx->data, reg, val);
+}
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_cursor.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_cursor.c
@@ -0,0 +1,70 @@
+#include "drmP.h"
+#include "drm_mode.h"
+#include "nouveau_reg.h"
+#include "nouveau_drv.h"
+#include "nouveau_crtc.h"
+#include "nouveau_hw.h"
+
+static void
+nv04_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
+{
+	nv_show_cursor(nv_crtc->base.dev, nv_crtc->index, true);
+}
+
+static void
+nv04_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
+{
+	nv_show_cursor(nv_crtc->base.dev, nv_crtc->index, false);
+}
+
+static void
+nv04_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y)
+{
+	NVWriteRAMDAC(nv_crtc->base.dev, nv_crtc->index,
+		      NV_PRAMDAC_CU_START_POS,
+		      XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
+		      XLATE(x, 0, NV_PRAMDAC_CU_START_POS_X));
+}
+
+static void
+crtc_wr_cio_state(struct drm_crtc *crtc, struct nv04_crtc_reg *crtcstate, int index)
+{
+	NVWriteVgaCrtc(crtc->dev, nouveau_crtc(crtc)->index, index,
+		       crtcstate->CRTC[index]);
+}
+
+static void
+nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
+{
+	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv04_crtc_reg *regp = &dev_priv->mode_reg.crtc_reg[nv_crtc->index];
+	struct drm_crtc *crtc = &nv_crtc->base;
+
+	regp->CRTC[NV_CIO_CRE_HCUR_ADDR0_INDEX] =
+		MASK(NV_CIO_CRE_HCUR_ASI) |
+		XLATE(offset, 17, NV_CIO_CRE_HCUR_ADDR0_ADR);
+	regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] =
+		XLATE(offset, 11, NV_CIO_CRE_HCUR_ADDR1_ADR);
+	if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
+		regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] |=
+			MASK(NV_CIO_CRE_HCUR_ADDR1_CUR_DBL);
+	regp->CRTC[NV_CIO_CRE_HCUR_ADDR2_INDEX] = offset >> 24;
+
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
+	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
+	if (dev_priv->card_type == NV_40)
+		nv_fix_nv40_hw_cursor(dev, nv_crtc->index);
+}
+
+int
+nv04_cursor_init(struct nouveau_crtc *crtc)
+{
+	crtc->cursor.set_offset = nv04_cursor_set_offset;
+	crtc->cursor.set_pos = nv04_cursor_set_pos;
+	crtc->cursor.hide = nv04_cursor_hide;
+	crtc->cursor.show = nv04_cursor_show;
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_fb.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_fb.c
@@ -0,0 +1,21 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+int
+nv04_fb_init(struct drm_device *dev)
+{
+	/* This is what the DDX did for NV_ARCH_04, but a mmio-trace shows
+	 * nvidia reading PFB_CFG_0, then writing back its original value.
+	 * (which was 0x701114 in this case)
+	 */
+
+	nv_wr32(dev, NV04_PFB_CFG0, 0x1114);
+	return 0;
+}
+
+void
+nv04_fb_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv50_mc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv50_mc.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007 Ben Skeggs.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+int
+nv50_mc_init(struct drm_device *dev)
+{
+	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
+	return 0;
+}
+
+void nv50_mc_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_timer.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_timer.c
@@ -0,0 +1,51 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+int
+nv04_timer_init(struct drm_device *dev)
+{
+	nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000);
+	nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF);
+
+	/* Just use the pre-existing values when possible for now; these regs
+	 * are not written in nv (driver writer missed a /4 on the address), and
+	 * writing 8 and 3 to the correct regs breaks the timings on the LVDS
+	 * hardware sequencing microcode.
+	 * A correct solution (involving calculations with the GPU PLL) can
+	 * be done when kernel modesetting lands
+	 */
+	if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) ||
+				!nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) {
+		nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008);
+		nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003);
+	}
+
+	return 0;
+}
+
+uint64_t
+nv04_timer_read(struct drm_device *dev)
+{
+	uint32_t low;
+	/* From kmmio dumps on nv28 this looks like how the blob does this.
+	 * It reads the high dword twice, before and after.
+	 * The only explanation seems to be that the 64-bit timer counter
+	 * advances between high and low dword reads and may corrupt the
+	 * result. Not confirmed.
+	 */
+	uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
+	uint32_t high1;
+	do {
+		high1 = high2;
+		low = nv_rd32(dev, NV04_PTIMER_TIME_0);
+		high2 = nv_rd32(dev, NV04_PTIMER_TIME_1);
+	} while (high1 != high2);
+	return (((uint64_t)high2) << 32) | (uint64_t)low;
+}
+
+void
+nv04_timer_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv04_mc.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv04_mc.c
@@ -0,0 +1,20 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+int
+nv04_mc_init(struct drm_device *dev)
+{
+	/* Power up everything, resetting each individual unit will
+	 * be done later if needed.
+	 */
+
+	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
+	return 0;
+}
+
+void
+nv04_mc_takedown(struct drm_device *dev)
+{
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nv17_tv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nv17_tv.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NV17_TV_H__
+#define __NV17_TV_H__
+
+struct nv17_tv_state {
+	uint8_t tv_enc[0x40];
+
+	uint32_t hfilter[4][7];
+	uint32_t hfilter2[4][7];
+	uint32_t vfilter[4][7];
+
+	uint32_t ptv_200;
+	uint32_t ptv_204;
+	uint32_t ptv_208;
+	uint32_t ptv_20c;
+	uint32_t ptv_304;
+	uint32_t ptv_500;
+	uint32_t ptv_504;
+	uint32_t ptv_508;
+	uint32_t ptv_600;
+	uint32_t ptv_604;
+	uint32_t ptv_608;
+	uint32_t ptv_60c;
+	uint32_t ptv_610;
+	uint32_t ptv_614;
+};
+
+enum nv17_tv_norm{
+	TV_NORM_PAL,
+	TV_NORM_PAL_M,
+	TV_NORM_PAL_N,
+	TV_NORM_PAL_NC,
+	TV_NORM_NTSC_M,
+	TV_NORM_NTSC_J,
+	NUM_LD_TV_NORMS,
+	TV_NORM_HD480I = NUM_LD_TV_NORMS,
+	TV_NORM_HD480P,
+	TV_NORM_HD576I,
+	TV_NORM_HD576P,
+	TV_NORM_HD720P,
+	TV_NORM_HD1080I,
+	NUM_TV_NORMS
+};
+
+struct nv17_tv_encoder {
+	struct nouveau_encoder base;
+
+	struct nv17_tv_state state;
+	struct nv17_tv_state saved_state;
+
+	int overscan;
+	int flicker;
+	int saturation;
+	int hue;
+	enum nv17_tv_norm tv_norm;
+	int subconnector;
+	int select_subconnector;
+	uint32_t pin_mask;
+};
+#define to_tv_enc(x) container_of(nouveau_encoder(x),		\
+				  struct nv17_tv_encoder, base)
+
+extern char *nv17_tv_norm_names[NUM_TV_NORMS];
+
+extern struct nv17_tv_norm_params {
+	enum {
+		TV_ENC_MODE,
+		CTV_ENC_MODE,
+	} kind;
+
+	union {
+		struct {
+			int hdisplay;
+			int vdisplay;
+			int vrefresh; /* mHz */
+
+			uint8_t tv_enc[0x40];
+		} tv_enc_mode;
+
+		struct {
+			struct drm_display_mode mode;
+
+			uint32_t ctv_regs[38];
+		} ctv_enc_mode;
+	};
+
+} nv17_tv_norms[NUM_TV_NORMS];
+#define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm])
+
+extern struct drm_display_mode nv17_tv_modes[];
+
+static inline int interpolate(int y0, int y1, int y2, int x)
+{
+	return y1 + (x < 50 ? y1 - y0 : y2 - y1) * (x - 50) / 50;
+}
+
+void nv17_tv_state_save(struct drm_device *dev, struct nv17_tv_state *state);
+void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state);
+void nv17_tv_update_properties(struct drm_encoder *encoder);
+void nv17_tv_update_rescaler(struct drm_encoder *encoder);
+void nv17_ctv_update_rescaler(struct drm_encoder *encoder);
+
+/* TV hardware access functions */
+
+static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, uint32_t val)
+{
+	nv_wr32(dev, reg, val);
+}
+
+static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg)
+{
+	return nv_rd32(dev, reg);
+}
+
+static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, uint8_t val)
+{
+	nv_write_ptv(dev, NV_PTV_TV_INDEX, reg);
+	nv_write_ptv(dev, NV_PTV_TV_DATA, val);
+}
+
+static inline uint8_t nv_read_tv_enc(struct drm_device *dev, uint8_t reg)
+{
+	nv_write_ptv(dev, NV_PTV_TV_INDEX, reg);
+	return nv_read_ptv(dev, NV_PTV_TV_DATA);
+}
+
+#define nv_load_ptv(dev, state, reg) nv_write_ptv(dev, NV_PTV_OFFSET + 0x##reg, state->ptv_##reg)
+#define nv_save_ptv(dev, state, reg) state->ptv_##reg = nv_read_ptv(dev, NV_PTV_OFFSET + 0x##reg)
+#define nv_load_tv_enc(dev, state, reg) nv_write_tv_enc(dev, 0x##reg, state->tv_enc[0x##reg])
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008 Maarten Maathuis.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_ENCODER_H__
+#define __NOUVEAU_ENCODER_H__
+
+#include "drm_encoder_slave.h"
+#include "nouveau_drv.h"
+
+#define NV_DPMS_CLEARED 0x80
+
+struct nouveau_encoder {
+	struct drm_encoder_slave base;
+
+	struct dcb_entry *dcb;
+	int or;
+
+	struct drm_display_mode mode;
+	int last_dpms;
+
+	struct nv04_output_reg restore;
+
+	void (*disconnect)(struct nouveau_encoder *encoder);
+
+	union {
+		struct {
+			int dpcd_version;
+			int link_nr;
+			int link_bw;
+		} dp;
+	};
+};
+
+static inline struct nouveau_encoder *nouveau_encoder(struct drm_encoder *enc)
+{
+	struct drm_encoder_slave *slave = to_encoder_slave(enc);
+
+	return container_of(slave, struct nouveau_encoder, base);
+}
+
+static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
+{
+	return &enc->base.base;
+}
+
+struct nouveau_connector *
+nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
+int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry);
+int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry);
+
+struct bit_displayport_encoder_table {
+	uint32_t match;
+	uint8_t  record_nr;
+	uint8_t  unknown;
+	uint16_t script0;
+	uint16_t script1;
+	uint16_t unknown_table;
+} __attribute__ ((packed));
+
+struct bit_displayport_encoder_table_entry {
+	uint8_t vs_level;
+	uint8_t pre_level;
+	uint8_t reg0;
+	uint8_t reg1;
+	uint8_t reg2;
+} __attribute__ ((packed));
+
+#endif /* __NOUVEAU_ENCODER_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -0,0 +1,1352 @@
+/*
+ * Copyright 2005 Stephane Marchesin.
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 __NOUVEAU_DRV_H__
+#define __NOUVEAU_DRV_H__
+
+#define DRIVER_AUTHOR		"Stephane Marchesin"
+#define DRIVER_EMAIL		"dri-devel@lists.sourceforge.net"
+
+#define DRIVER_NAME		"nouveau"
+#define DRIVER_DESC		"nVidia Riva/TNT/GeForce"
+#define DRIVER_DATE		"20090420"
+
+#define DRIVER_MAJOR		0
+#define DRIVER_MINOR		0
+#define DRIVER_PATCHLEVEL	15
+
+#define NOUVEAU_FAMILY   0x0000FFFF
+#define NOUVEAU_FLAGS    0xFFFF0000
+
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_memory.h"
+#include "ttm/ttm_module.h"
+
+struct nouveau_fpriv {
+	struct ttm_object_file *tfile;
+};
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#include "nouveau_drm.h"
+#include "nouveau_reg.h"
+#include "nouveau_bios.h"
+struct nouveau_grctx;
+
+#define MAX_NUM_DCB_ENTRIES 16
+
+#define NOUVEAU_MAX_CHANNEL_NR 128
+#define NOUVEAU_MAX_TILE_NR 15
+
+#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
+#define NV50_VM_BLOCK    (512*1024*1024ULL)
+#define NV50_VM_VRAM_NR  (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)
+
+struct nouveau_tile_reg {
+	struct nouveau_fence *fence;
+	uint32_t addr;
+	uint32_t size;
+	bool used;
+};
+
+struct nouveau_bo {
+	struct ttm_buffer_object bo;
+	struct ttm_placement placement;
+	u32 placements[3];
+	struct ttm_bo_kmap_obj kmap;
+	struct list_head head;
+
+	/* protected by ttm_bo_reserve() */
+	struct drm_file *reserved_by;
+	struct list_head entry;
+	int pbbo_index;
+
+	struct nouveau_channel *channel;
+
+	bool mappable;
+	bool no_vm;
+
+	uint32_t tile_mode;
+	uint32_t tile_flags;
+	struct nouveau_tile_reg *tile;
+
+	struct drm_gem_object *gem;
+	struct drm_file *cpu_filp;
+	int pin_refcnt;
+};
+
+static inline struct nouveau_bo *
+nouveau_bo(struct ttm_buffer_object *bo)
+{
+	return container_of(bo, struct nouveau_bo, bo);
+}
+
+static inline struct nouveau_bo *
+nouveau_gem_object(struct drm_gem_object *gem)
+{
+	return gem ? gem->driver_private : NULL;
+}
+
+/* TODO: submit equivalent to TTM generic API upstream? */
+static inline void __iomem *
+nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
+{
+	bool is_iomem;
+	void __iomem *ioptr = (void __force __iomem *)ttm_kmap_obj_virtual(
+						&nvbo->kmap, &is_iomem);
+	WARN_ON_ONCE(ioptr && !is_iomem);
+	return ioptr;
+}
+
+struct mem_block {
+	struct mem_block *next;
+	struct mem_block *prev;
+	uint64_t start;
+	uint64_t size;
+	struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
+};
+
+enum nouveau_flags {
+	NV_NFORCE   = 0x10000000,
+	NV_NFORCE2  = 0x20000000
+};
+
+#define NVOBJ_ENGINE_SW		0
+#define NVOBJ_ENGINE_GR		1
+#define NVOBJ_ENGINE_DISPLAY	2
+#define NVOBJ_ENGINE_INT	0xdeadbeef
+
+#define NVOBJ_FLAG_ALLOW_NO_REFS	(1 << 0)
+#define NVOBJ_FLAG_ZERO_ALLOC		(1 << 1)
+#define NVOBJ_FLAG_ZERO_FREE		(1 << 2)
+#define NVOBJ_FLAG_FAKE			(1 << 3)
+struct nouveau_gpuobj {
+	struct list_head list;
+
+	struct nouveau_channel *im_channel;
+	struct mem_block *im_pramin;
+	struct nouveau_bo *im_backing;
+	uint32_t im_backing_start;
+	uint32_t *im_backing_suspend;
+	int im_bound;
+
+	uint32_t flags;
+	int refcount;
+
+	uint32_t engine;
+	uint32_t class;
+
+	void (*dtor)(struct drm_device *, struct nouveau_gpuobj *);
+	void *priv;
+};
+
+struct nouveau_gpuobj_ref {
+	struct list_head list;
+
+	struct nouveau_gpuobj *gpuobj;
+	uint32_t instance;
+
+	struct nouveau_channel *channel;
+	int handle;
+};
+
+struct nouveau_channel {
+	struct drm_device *dev;
+	int id;
+
+	/* owner of this fifo */
+	struct drm_file *file_priv;
+	/* mapping of the fifo itself */
+	struct drm_local_map *map;
+
+	/* mapping of the regs controling the fifo */
+	void __iomem *user;
+	uint32_t user_get;
+	uint32_t user_put;
+
+	/* Fencing */
+	struct {
+		/* lock protects the pending list only */
+		spinlock_t lock;
+		struct list_head pending;
+		uint32_t sequence;
+		uint32_t sequence_ack;
+		uint32_t last_sequence_irq;
+	} fence;
+
+	/* DMA push buffer */
+	struct nouveau_gpuobj_ref *pushbuf;
+	struct nouveau_bo         *pushbuf_bo;
+	uint32_t                   pushbuf_base;
+
+	/* Notifier memory */
+	struct nouveau_bo *notifier_bo;
+	struct mem_block *notifier_heap;
+
+	/* PFIFO context */
+	struct nouveau_gpuobj_ref *ramfc;
+	struct nouveau_gpuobj_ref *cache;
+
+	/* PGRAPH context */
+	/* XXX may be merge 2 pointers as private data ??? */
+	struct nouveau_gpuobj_ref *ramin_grctx;
+	void *pgraph_ctx;
+
+	/* NV50 VM */
+	struct nouveau_gpuobj     *vm_pd;
+	struct nouveau_gpuobj_ref *vm_gart_pt;
+	struct nouveau_gpuobj_ref *vm_vram_pt[NV50_VM_VRAM_NR];
+
+	/* Objects */
+	struct nouveau_gpuobj_ref *ramin; /* Private instmem */
+	struct mem_block          *ramin_heap; /* Private PRAMIN heap */
+	struct nouveau_gpuobj_ref *ramht; /* Hash table */
+	struct list_head           ramht_refs; /* Objects referenced by RAMHT */
+
+	/* GPU object info for stuff used in-kernel (mm_enabled) */
+	uint32_t m2mf_ntfy;
+	uint32_t vram_handle;
+	uint32_t gart_handle;
+	bool accel_done;
+
+	/* Push buffer state (only for drm's channel on !mm_enabled) */
+	struct {
+		int max;
+		int free;
+		int cur;
+		int put;
+		/* access via pushbuf_bo */
+	} dma;
+
+	uint32_t sw_subchannel[8];
+
+	struct {
+		struct nouveau_gpuobj *vblsem;
+		uint32_t vblsem_offset;
+		uint32_t vblsem_rval;
+		struct list_head vbl_wait;
+	} nvsw;
+
+	struct {
+		bool active;
+		char name[32];
+		struct drm_info_list info;
+	} debugfs;
+};
+
+struct nouveau_instmem_engine {
+	void	*priv;
+
+	int	(*init)(struct drm_device *dev);
+	void	(*takedown)(struct drm_device *dev);
+	int	(*suspend)(struct drm_device *dev);
+	void	(*resume)(struct drm_device *dev);
+
+	int	(*populate)(struct drm_device *, struct nouveau_gpuobj *,
+			    uint32_t *size);
+	void	(*clear)(struct drm_device *, struct nouveau_gpuobj *);
+	int	(*bind)(struct drm_device *, struct nouveau_gpuobj *);
+	int	(*unbind)(struct drm_device *, struct nouveau_gpuobj *);
+	void	(*prepare_access)(struct drm_device *, bool write);
+	void	(*finish_access)(struct drm_device *);
+};
+
+struct nouveau_mc_engine {
+	int  (*init)(struct drm_device *dev);
+	void (*takedown)(struct drm_device *dev);
+};
+
+struct nouveau_timer_engine {
+	int      (*init)(struct drm_device *dev);
+	void     (*takedown)(struct drm_device *dev);
+	uint64_t (*read)(struct drm_device *dev);
+};
+
+struct nouveau_fb_engine {
+	int num_tiles;
+
+	int  (*init)(struct drm_device *dev);
+	void (*takedown)(struct drm_device *dev);
+
+	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
+				 uint32_t size, uint32_t pitch);
+};
+
+struct nouveau_fifo_engine {
+	void *priv;
+
+	int  channels;
+
+	int  (*init)(struct drm_device *);
+	void (*takedown)(struct drm_device *);
+
+	void (*disable)(struct drm_device *);
+	void (*enable)(struct drm_device *);
+	bool (*reassign)(struct drm_device *, bool enable);
+	bool (*cache_flush)(struct drm_device *dev);
+	bool (*cache_pull)(struct drm_device *dev, bool enable);
+
+	int  (*channel_id)(struct drm_device *);
+
+	int  (*create_context)(struct nouveau_channel *);
+	void (*destroy_context)(struct nouveau_channel *);
+	int  (*load_context)(struct nouveau_channel *);
+	int  (*unload_context)(struct drm_device *);
+};
+
+struct nouveau_pgraph_object_method {
+	int id;
+	int (*exec)(struct nouveau_channel *chan, int grclass, int mthd,
+		      uint32_t data);
+};
+
+struct nouveau_pgraph_object_class {
+	int id;
+	bool software;
+	struct nouveau_pgraph_object_method *methods;
+};
+
+struct nouveau_pgraph_engine {
+	struct nouveau_pgraph_object_class *grclass;
+	bool accel_blocked;
+	void *ctxprog;
+	void *ctxvals;
+	int grctx_size;
+
+	int  (*init)(struct drm_device *);
+	void (*takedown)(struct drm_device *);
+
+	void (*fifo_access)(struct drm_device *, bool);
+
+	struct nouveau_channel *(*channel)(struct drm_device *);
+	int  (*create_context)(struct nouveau_channel *);
+	void (*destroy_context)(struct nouveau_channel *);
+	int  (*load_context)(struct nouveau_channel *);
+	int  (*unload_context)(struct drm_device *);
+
+	void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr,
+				  uint32_t size, uint32_t pitch);
+};
+
+struct nouveau_engine {
+	struct nouveau_instmem_engine instmem;
+	struct nouveau_mc_engine      mc;
+	struct nouveau_timer_engine   timer;
+	struct nouveau_fb_engine      fb;
+	struct nouveau_pgraph_engine  graph;
+	struct nouveau_fifo_engine    fifo;
+};
+
+struct nouveau_pll_vals {
+	union {
+		struct {
+#ifdef __BIG_ENDIAN
+			uint8_t N1, M1, N2, M2;
+#else
+			uint8_t M1, N1, M2, N2;
+#endif
+		};
+		struct {
+			uint16_t NM1, NM2;
+		} __attribute__((packed));
+	};
+	int log2P;
+
+	int refclk;
+};
+
+enum nv04_fp_display_regs {
+	FP_DISPLAY_END,
+	FP_TOTAL,
+	FP_CRTC,
+	FP_SYNC_START,
+	FP_SYNC_END,
+	FP_VALID_START,
+	FP_VALID_END
+};
+
+struct nv04_crtc_reg {
+	unsigned char MiscOutReg;     /* */
+	uint8_t CRTC[0x9f];
+	uint8_t CR58[0x10];
+	uint8_t Sequencer[5];
+	uint8_t Graphics[9];
+	uint8_t Attribute[21];
+	unsigned char DAC[768];       /* Internal Colorlookuptable */
+
+	/* PCRTC regs */
+	uint32_t fb_start;
+	uint32_t crtc_cfg;
+	uint32_t cursor_cfg;
+	uint32_t gpio_ext;
+	uint32_t crtc_830;
+	uint32_t crtc_834;
+	uint32_t crtc_850;
+	uint32_t crtc_eng_ctrl;
+
+	/* PRAMDAC regs */
+	uint32_t nv10_cursync;
+	struct nouveau_pll_vals pllvals;
+	uint32_t ramdac_gen_ctrl;
+	uint32_t ramdac_630;
+	uint32_t ramdac_634;
+	uint32_t tv_setup;
+	uint32_t tv_vtotal;
+	uint32_t tv_vskew;
+	uint32_t tv_vsync_delay;
+	uint32_t tv_htotal;
+	uint32_t tv_hskew;
+	uint32_t tv_hsync_delay;
+	uint32_t tv_hsync_delay2;
+	uint32_t fp_horiz_regs[7];
+	uint32_t fp_vert_regs[7];
+	uint32_t dither;
+	uint32_t fp_control;
+	uint32_t dither_regs[6];
+	uint32_t fp_debug_0;
+	uint32_t fp_debug_1;
+	uint32_t fp_debug_2;
+	uint32_t fp_margin_color;
+	uint32_t ramdac_8c0;
+	uint32_t ramdac_a20;
+	uint32_t ramdac_a24;
+	uint32_t ramdac_a34;
+	uint32_t ctv_regs[38];
+};
+
+struct nv04_output_reg {
+	uint32_t output;
+	int head;
+};
+
+struct nv04_mode_state {
+	uint32_t bpp;
+	uint32_t width;
+	uint32_t height;
+	uint32_t interlace;
+	uint32_t repaint0;
+	uint32_t repaint1;
+	uint32_t screen;
+	uint32_t scale;
+	uint32_t dither;
+	uint32_t extra;
+	uint32_t fifo;
+	uint32_t pixel;
+	uint32_t horiz;
+	int arbitration0;
+	int arbitration1;
+	uint32_t pll;
+	uint32_t pllB;
+	uint32_t vpll;
+	uint32_t vpll2;
+	uint32_t vpllB;
+	uint32_t vpll2B;
+	uint32_t pllsel;
+	uint32_t sel_clk;
+	uint32_t general;
+	uint32_t crtcOwner;
+	uint32_t head;
+	uint32_t head2;
+	uint32_t cursorConfig;
+	uint32_t cursor0;
+	uint32_t cursor1;
+	uint32_t cursor2;
+	uint32_t timingH;
+	uint32_t timingV;
+	uint32_t displayV;
+	uint32_t crtcSync;
+
+	struct nv04_crtc_reg crtc_reg[2];
+};
+
+enum nouveau_card_type {
+	NV_04      = 0x00,
+	NV_10      = 0x10,
+	NV_20      = 0x20,
+	NV_30      = 0x30,
+	NV_40      = 0x40,
+	NV_50      = 0x50,
+};
+
+struct drm_nouveau_private {
+	struct drm_device *dev;
+	enum {
+		NOUVEAU_CARD_INIT_DOWN,
+		NOUVEAU_CARD_INIT_DONE,
+		NOUVEAU_CARD_INIT_FAILED
+	} init_state;
+
+	/* the card type, takes NV_* as values */
+	enum nouveau_card_type card_type;
+	/* exact chipset, derived from NV_PMC_BOOT_0 */
+	int chipset;
+	int flags;
+
+	void __iomem *mmio;
+	void __iomem *ramin;
+	uint32_t ramin_size;
+
+	struct nouveau_bo *vga_ram;
+
+	struct workqueue_struct *wq;
+	struct work_struct irq_work;
+
+	struct list_head vbl_waiting;
+
+	struct {
+		struct ttm_global_reference mem_global_ref;
+		struct ttm_bo_global_ref bo_global_ref;
+		struct ttm_bo_device bdev;
+		spinlock_t bo_list_lock;
+		struct list_head bo_list;
+		atomic_t validate_sequence;
+	} ttm;
+
+	struct fb_info *fbdev_info;
+
+	int fifo_alloc_count;
+	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
+
+	struct nouveau_engine engine;
+	struct nouveau_channel *channel;
+
+	/* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
+	struct nouveau_gpuobj *ramht;
+	uint32_t ramin_rsvd_vram;
+	uint32_t ramht_offset;
+	uint32_t ramht_size;
+	uint32_t ramht_bits;
+	uint32_t ramfc_offset;
+	uint32_t ramfc_size;
+	uint32_t ramro_offset;
+	uint32_t ramro_size;
+
+	/* base physical adresses */
+	uint64_t fb_phys;
+	uint64_t fb_available_size;
+	uint64_t fb_mappable_pages;
+	uint64_t fb_aper_free;
+
+	struct {
+		enum {
+			NOUVEAU_GART_NONE = 0,
+			NOUVEAU_GART_AGP,
+			NOUVEAU_GART_SGDMA
+		} type;
+		uint64_t aper_base;
+		uint64_t aper_size;
+		uint64_t aper_free;
+
+		struct nouveau_gpuobj *sg_ctxdma;
+		struct page *sg_dummy_page;
+		dma_addr_t sg_dummy_bus;
+
+		/* nottm hack */
+		struct drm_ttm_backend *sg_be;
+		unsigned long sg_handle;
+	} gart_info;
+
+	/* nv10-nv40 tiling regions */
+	struct {
+		struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR];
+		spinlock_t lock;
+	} tile;
+
+	/* G8x/G9x virtual address space */
+	uint64_t vm_gart_base;
+	uint64_t vm_gart_size;
+	uint64_t vm_vram_base;
+	uint64_t vm_vram_size;
+	uint64_t vm_end;
+	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
+	int vm_vram_pt_nr;
+	uint64_t vram_sys_base;
+
+	/* the mtrr covering the FB */
+	int fb_mtrr;
+
+	struct mem_block *ramin_heap;
+
+	/* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */
+	uint32_t ctx_table_size;
+	struct nouveau_gpuobj_ref *ctx_table;
+
+	struct list_head gpuobj_list;
+
+	struct nvbios VBIOS;
+	struct nouveau_bios_info *vbios;
+
+	struct nv04_mode_state mode_reg;
+	struct nv04_mode_state saved_reg;
+	uint32_t saved_vga_font[4][16384];
+	uint32_t crtc_owner;
+	uint32_t dac_users[4];
+
+	struct nouveau_suspend_resume {
+		uint32_t fifo_mode;
+		uint32_t graph_ctx_control;
+		uint32_t graph_state;
+		uint32_t *ramin_copy;
+		uint64_t ramin_size;
+	} susres;
+
+	struct backlight_device *backlight;
+	bool acpi_dsm;
+
+	struct nouveau_channel *evo;
+
+	struct {
+		struct dentry *channel_root;
+	} debugfs;
+};
+
+static inline struct drm_nouveau_private *
+nouveau_bdev(struct ttm_bo_device *bd)
+{
+	return container_of(bd, struct drm_nouveau_private, ttm.bdev);
+}
+
+static inline int
+nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
+{
+	struct nouveau_bo *prev;
+
+	if (!pnvbo)
+		return -EINVAL;
+	prev = *pnvbo;
+
+	*pnvbo = ref ? nouveau_bo(ttm_bo_reference(&ref->bo)) : NULL;
+	if (prev) {
+		struct ttm_buffer_object *bo = &prev->bo;
+
+		ttm_bo_unref(&bo);
+	}
+
+	return 0;
+}
+
+#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do {            \
+	struct drm_nouveau_private *nv = dev->dev_private;    \
+	if (nv->init_state != NOUVEAU_CARD_INIT_DONE) {       \
+		NV_ERROR(dev, "called without init\n");       \
+		return -EINVAL;                               \
+	}                                                     \
+} while (0)
+
+#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do {    \
+	struct drm_nouveau_private *nv = dev->dev_private;       \
+	if (!nouveau_channel_owner(dev, (cl), (id))) {           \
+		NV_ERROR(dev, "pid %d doesn't own channel %d\n", \
+			 DRM_CURRENTPID, (id));                  \
+		return -EPERM;                                   \
+	}                                                        \
+	(ch) = nv->fifos[(id)];                                  \
+} while (0)
+
+/* nouveau_drv.c */
+extern int nouveau_noagp;
+extern int nouveau_duallink;
+extern int nouveau_uscript_lvds;
+extern int nouveau_uscript_tmds;
+extern int nouveau_vram_pushbuf;
+extern int nouveau_vram_notify;
+extern int nouveau_fbpercrtc;
+extern char *nouveau_tv_norm;
+extern int nouveau_reg_debug;
+extern char *nouveau_vbios;
+extern int nouveau_ctxfw;
+extern int nouveau_ignorelid;
+extern int nouveau_nofbaccel;
+extern int nouveau_noaccel;
+
+/* nouveau_state.c */
+extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
+extern int  nouveau_load(struct drm_device *, unsigned long flags);
+extern int  nouveau_firstopen(struct drm_device *);
+extern void nouveau_lastclose(struct drm_device *);
+extern int  nouveau_unload(struct drm_device *);
+extern int  nouveau_ioctl_getparam(struct drm_device *, void *data,
+				   struct drm_file *);
+extern int  nouveau_ioctl_setparam(struct drm_device *, void *data,
+				   struct drm_file *);
+extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout,
+			       uint32_t reg, uint32_t mask, uint32_t val);
+extern bool nouveau_wait_for_idle(struct drm_device *);
+extern int  nouveau_card_init(struct drm_device *);
+extern int  nouveau_ioctl_card_init(struct drm_device *, void *data,
+				    struct drm_file *);
+extern int  nouveau_ioctl_suspend(struct drm_device *, void *data,
+				  struct drm_file *);
+extern int  nouveau_ioctl_resume(struct drm_device *, void *data,
+				 struct drm_file *);
+
+/* nouveau_mem.c */
+extern int  nouveau_mem_init_heap(struct mem_block **, uint64_t start,
+				 uint64_t size);
+extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
+						 uint64_t size, int align2,
+						 struct drm_file *, int tail);
+extern void nouveau_mem_takedown(struct mem_block **heap);
+extern void nouveau_mem_free_block(struct mem_block *);
+extern uint64_t nouveau_mem_fb_amount(struct drm_device *);
+extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
+extern int  nouveau_mem_init(struct drm_device *);
+extern int  nouveau_mem_init_agp(struct drm_device *);
+extern void nouveau_mem_close(struct drm_device *);
+extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
+						    uint32_t addr,
+						    uint32_t size,
+						    uint32_t pitch);
+extern void nv10_mem_expire_tiling(struct drm_device *dev,
+				   struct nouveau_tile_reg *tile,
+				   struct nouveau_fence *fence);
+extern int  nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
+				    uint32_t size, uint32_t flags,
+				    uint64_t phys);
+extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt,
+			       uint32_t size);
+
+/* nouveau_notifier.c */
+extern int  nouveau_notifier_init_channel(struct nouveau_channel *);
+extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
+extern int  nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
+				   int cout, uint32_t *offset);
+extern int  nouveau_notifier_offset(struct nouveau_gpuobj *, uint32_t *);
+extern int  nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
+					 struct drm_file *);
+extern int  nouveau_ioctl_notifier_free(struct drm_device *, void *data,
+					struct drm_file *);
+
+/* nouveau_channel.c */
+extern struct drm_ioctl_desc nouveau_ioctls[];
+extern int nouveau_max_ioctl;
+extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *);
+extern int  nouveau_channel_owner(struct drm_device *, struct drm_file *,
+				  int channel);
+extern int  nouveau_channel_alloc(struct drm_device *dev,
+				  struct nouveau_channel **chan,
+				  struct drm_file *file_priv,
+				  uint32_t fb_ctxdma, uint32_t tt_ctxdma);
+extern void nouveau_channel_free(struct nouveau_channel *);
+
+/* nouveau_object.c */
+extern int  nouveau_gpuobj_early_init(struct drm_device *);
+extern int  nouveau_gpuobj_init(struct drm_device *);
+extern void nouveau_gpuobj_takedown(struct drm_device *);
+extern void nouveau_gpuobj_late_takedown(struct drm_device *);
+extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
+extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
+extern void nouveau_gpuobj_resume(struct drm_device *dev);
+extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
+				       uint32_t vram_h, uint32_t tt_h);
+extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
+extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *,
+			      uint32_t size, int align, uint32_t flags,
+			      struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *,
+				  uint32_t handle, struct nouveau_gpuobj *,
+				  struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_ref_del(struct drm_device *,
+				  struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle,
+				   struct nouveau_gpuobj_ref **ref_ret);
+extern int nouveau_gpuobj_new_ref(struct drm_device *,
+				  struct nouveau_channel *alloc_chan,
+				  struct nouveau_channel *ref_chan,
+				  uint32_t handle, uint32_t size, int align,
+				  uint32_t flags, struct nouveau_gpuobj_ref **);
+extern int nouveau_gpuobj_new_fake(struct drm_device *,
+				   uint32_t p_offset, uint32_t b_offset,
+				   uint32_t size, uint32_t flags,
+				   struct nouveau_gpuobj **,
+				   struct nouveau_gpuobj_ref**);
+extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
+				  uint64_t offset, uint64_t size, int access,
+				  int target, struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
+				       uint64_t offset, uint64_t size,
+				       int access, struct nouveau_gpuobj **,
+				       uint32_t *o_ret);
+extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
+				 struct nouveau_gpuobj **);
+extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class,
+				 struct nouveau_gpuobj **);
+extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
+				     struct drm_file *);
+extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
+				     struct drm_file *);
+
+/* nouveau_irq.c */
+extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
+extern void        nouveau_irq_preinstall(struct drm_device *);
+extern int         nouveau_irq_postinstall(struct drm_device *);
+extern void        nouveau_irq_uninstall(struct drm_device *);
+
+/* nouveau_sgdma.c */
+extern int nouveau_sgdma_init(struct drm_device *);
+extern void nouveau_sgdma_takedown(struct drm_device *);
+extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset,
+				  uint32_t *page);
+extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
+
+/* nouveau_debugfs.c */
+#if defined(CONFIG_DRM_NOUVEAU_DEBUG)
+extern int  nouveau_debugfs_init(struct drm_minor *);
+extern void nouveau_debugfs_takedown(struct drm_minor *);
+extern int  nouveau_debugfs_channel_init(struct nouveau_channel *);
+extern void nouveau_debugfs_channel_fini(struct nouveau_channel *);
+#else
+static inline int
+nouveau_debugfs_init(struct drm_minor *minor)
+{
+	return 0;
+}
+
+static inline void nouveau_debugfs_takedown(struct drm_minor *minor)
+{
+}
+
+static inline int
+nouveau_debugfs_channel_init(struct nouveau_channel *chan)
+{
+	return 0;
+}
+
+static inline void
+nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
+{
+}
+#endif
+
+/* nouveau_dma.c */
+extern void nouveau_dma_pre_init(struct nouveau_channel *);
+extern int  nouveau_dma_init(struct nouveau_channel *);
+extern int  nouveau_dma_wait(struct nouveau_channel *, int size);
+
+/* nouveau_acpi.c */
+#ifdef CONFIG_ACPI
+extern int nouveau_hybrid_setup(struct drm_device *dev);
+extern bool nouveau_dsm_probe(struct drm_device *dev);
+#else
+static inline int nouveau_hybrid_setup(struct drm_device *dev)
+{
+	return 0;
+}
+static inline bool nouveau_dsm_probe(struct drm_device *dev)
+{
+	return false;
+}
+#endif
+
+/* nouveau_backlight.c */
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+extern int nouveau_backlight_init(struct drm_device *);
+extern void nouveau_backlight_exit(struct drm_device *);
+#else
+static inline int nouveau_backlight_init(struct drm_device *dev)
+{
+	return 0;
+}
+
+static inline void nouveau_backlight_exit(struct drm_device *dev) { }
+#endif
+
+/* nouveau_bios.c */
+extern int nouveau_bios_init(struct drm_device *);
+extern void nouveau_bios_takedown(struct drm_device *dev);
+extern int nouveau_run_vbios_init(struct drm_device *);
+extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table,
+					struct dcb_entry *);
+extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *,
+						      enum dcb_gpio_tag);
+extern struct dcb_connector_table_entry *
+nouveau_bios_connector_entry(struct drm_device *, int index);
+extern int get_pll_limits(struct drm_device *, uint32_t limit_match,
+			  struct pll_lims *);
+extern int nouveau_bios_run_display_table(struct drm_device *,
+					  struct dcb_entry *,
+					  uint32_t script, int pxclk);
+extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *,
+				   int *length);
+extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
+extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
+extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
+					 bool *dl, bool *if_is_24bit);
+extern int run_tmds_table(struct drm_device *, struct dcb_entry *,
+			  int head, int pxclk);
+extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head,
+			    enum LVDS_script, int pxclk);
+
+/* nouveau_ttm.c */
+int nouveau_ttm_global_init(struct drm_nouveau_private *);
+void nouveau_ttm_global_release(struct drm_nouveau_private *);
+int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
+
+/* nouveau_dp.c */
+int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
+		     uint8_t *data, int data_nr);
+bool nouveau_dp_detect(struct drm_encoder *);
+bool nouveau_dp_link_train(struct drm_encoder *);
+
+/* nv04_fb.c */
+extern int  nv04_fb_init(struct drm_device *);
+extern void nv04_fb_takedown(struct drm_device *);
+
+/* nv10_fb.c */
+extern int  nv10_fb_init(struct drm_device *);
+extern void nv10_fb_takedown(struct drm_device *);
+extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
+				      uint32_t, uint32_t);
+
+/* nv40_fb.c */
+extern int  nv40_fb_init(struct drm_device *);
+extern void nv40_fb_takedown(struct drm_device *);
+extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t,
+				      uint32_t, uint32_t);
+
+/* nv04_fifo.c */
+extern int  nv04_fifo_init(struct drm_device *);
+extern void nv04_fifo_disable(struct drm_device *);
+extern void nv04_fifo_enable(struct drm_device *);
+extern bool nv04_fifo_reassign(struct drm_device *, bool);
+extern bool nv04_fifo_cache_flush(struct drm_device *);
+extern bool nv04_fifo_cache_pull(struct drm_device *, bool);
+extern int  nv04_fifo_channel_id(struct drm_device *);
+extern int  nv04_fifo_create_context(struct nouveau_channel *);
+extern void nv04_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv04_fifo_load_context(struct nouveau_channel *);
+extern int  nv04_fifo_unload_context(struct drm_device *);
+
+/* nv10_fifo.c */
+extern int  nv10_fifo_init(struct drm_device *);
+extern int  nv10_fifo_channel_id(struct drm_device *);
+extern int  nv10_fifo_create_context(struct nouveau_channel *);
+extern void nv10_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv10_fifo_load_context(struct nouveau_channel *);
+extern int  nv10_fifo_unload_context(struct drm_device *);
+
+/* nv40_fifo.c */
+extern int  nv40_fifo_init(struct drm_device *);
+extern int  nv40_fifo_create_context(struct nouveau_channel *);
+extern void nv40_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv40_fifo_load_context(struct nouveau_channel *);
+extern int  nv40_fifo_unload_context(struct drm_device *);
+
+/* nv50_fifo.c */
+extern int  nv50_fifo_init(struct drm_device *);
+extern void nv50_fifo_takedown(struct drm_device *);
+extern int  nv50_fifo_channel_id(struct drm_device *);
+extern int  nv50_fifo_create_context(struct nouveau_channel *);
+extern void nv50_fifo_destroy_context(struct nouveau_channel *);
+extern int  nv50_fifo_load_context(struct nouveau_channel *);
+extern int  nv50_fifo_unload_context(struct drm_device *);
+
+/* nv04_graph.c */
+extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
+extern int  nv04_graph_init(struct drm_device *);
+extern void nv04_graph_takedown(struct drm_device *);
+extern void nv04_graph_fifo_access(struct drm_device *, bool);
+extern struct nouveau_channel *nv04_graph_channel(struct drm_device *);
+extern int  nv04_graph_create_context(struct nouveau_channel *);
+extern void nv04_graph_destroy_context(struct nouveau_channel *);
+extern int  nv04_graph_load_context(struct nouveau_channel *);
+extern int  nv04_graph_unload_context(struct drm_device *);
+extern void nv04_graph_context_switch(struct drm_device *);
+
+/* nv10_graph.c */
+extern struct nouveau_pgraph_object_class nv10_graph_grclass[];
+extern int  nv10_graph_init(struct drm_device *);
+extern void nv10_graph_takedown(struct drm_device *);
+extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
+extern int  nv10_graph_create_context(struct nouveau_channel *);
+extern void nv10_graph_destroy_context(struct nouveau_channel *);
+extern int  nv10_graph_load_context(struct nouveau_channel *);
+extern int  nv10_graph_unload_context(struct drm_device *);
+extern void nv10_graph_context_switch(struct drm_device *);
+extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+					 uint32_t, uint32_t);
+
+/* nv20_graph.c */
+extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
+extern struct nouveau_pgraph_object_class nv30_graph_grclass[];
+extern int  nv20_graph_create_context(struct nouveau_channel *);
+extern void nv20_graph_destroy_context(struct nouveau_channel *);
+extern int  nv20_graph_load_context(struct nouveau_channel *);
+extern int  nv20_graph_unload_context(struct drm_device *);
+extern int  nv20_graph_init(struct drm_device *);
+extern void nv20_graph_takedown(struct drm_device *);
+extern int  nv30_graph_init(struct drm_device *);
+extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+					 uint32_t, uint32_t);
+
+/* nv40_graph.c */
+extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
+extern int  nv40_graph_init(struct drm_device *);
+extern void nv40_graph_takedown(struct drm_device *);
+extern struct nouveau_channel *nv40_graph_channel(struct drm_device *);
+extern int  nv40_graph_create_context(struct nouveau_channel *);
+extern void nv40_graph_destroy_context(struct nouveau_channel *);
+extern int  nv40_graph_load_context(struct nouveau_channel *);
+extern int  nv40_graph_unload_context(struct drm_device *);
+extern void nv40_grctx_init(struct nouveau_grctx *);
+extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
+					 uint32_t, uint32_t);
+
+/* nv50_graph.c */
+extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
+extern int  nv50_graph_init(struct drm_device *);
+extern void nv50_graph_takedown(struct drm_device *);
+extern void nv50_graph_fifo_access(struct drm_device *, bool);
+extern struct nouveau_channel *nv50_graph_channel(struct drm_device *);
+extern int  nv50_graph_create_context(struct nouveau_channel *);
+extern void nv50_graph_destroy_context(struct nouveau_channel *);
+extern int  nv50_graph_load_context(struct nouveau_channel *);
+extern int  nv50_graph_unload_context(struct drm_device *);
+extern void nv50_graph_context_switch(struct drm_device *);
+extern int  nv50_grctx_init(struct nouveau_grctx *);
+
+/* nouveau_grctx.c */
+extern int  nouveau_grctx_prog_load(struct drm_device *);
+extern void nouveau_grctx_vals_load(struct drm_device *,
+				    struct nouveau_gpuobj *);
+extern void nouveau_grctx_fini(struct drm_device *);
+
+/* nv04_instmem.c */
+extern int  nv04_instmem_init(struct drm_device *);
+extern void nv04_instmem_takedown(struct drm_device *);
+extern int  nv04_instmem_suspend(struct drm_device *);
+extern void nv04_instmem_resume(struct drm_device *);
+extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+				  uint32_t *size);
+extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern void nv04_instmem_prepare_access(struct drm_device *, bool write);
+extern void nv04_instmem_finish_access(struct drm_device *);
+
+/* nv50_instmem.c */
+extern int  nv50_instmem_init(struct drm_device *);
+extern void nv50_instmem_takedown(struct drm_device *);
+extern int  nv50_instmem_suspend(struct drm_device *);
+extern void nv50_instmem_resume(struct drm_device *);
+extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
+				  uint32_t *size);
+extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
+extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
+extern void nv50_instmem_prepare_access(struct drm_device *, bool write);
+extern void nv50_instmem_finish_access(struct drm_device *);
+
+/* nv04_mc.c */
+extern int  nv04_mc_init(struct drm_device *);
+extern void nv04_mc_takedown(struct drm_device *);
+
+/* nv40_mc.c */
+extern int  nv40_mc_init(struct drm_device *);
+extern void nv40_mc_takedown(struct drm_device *);
+
+/* nv50_mc.c */
+extern int  nv50_mc_init(struct drm_device *);
+extern void nv50_mc_takedown(struct drm_device *);
+
+/* nv04_timer.c */
+extern int  nv04_timer_init(struct drm_device *);
+extern uint64_t nv04_timer_read(struct drm_device *);
+extern void nv04_timer_takedown(struct drm_device *);
+
+extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
+				 unsigned long arg);
+
+/* nv04_dac.c */
+extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
+extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
+extern int nv04_dac_output_offset(struct drm_encoder *encoder);
+extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
+
+/* nv04_dfp.c */
+extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry);
+extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
+extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
+			       int head, bool dl);
+extern void nv04_dfp_disable(struct drm_device *dev, int head);
+extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
+
+/* nv04_tv.c */
+extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
+extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
+
+/* nv17_tv.c */
+extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
+
+/* nv04_display.c */
+extern int nv04_display_create(struct drm_device *);
+extern void nv04_display_destroy(struct drm_device *);
+extern void nv04_display_restore(struct drm_device *);
+
+/* nv04_crtc.c */
+extern int nv04_crtc_create(struct drm_device *, int index);
+
+/* nouveau_bo.c */
+extern struct ttm_bo_driver nouveau_bo_driver;
+extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
+			  int size, int align, uint32_t flags,
+			  uint32_t tile_mode, uint32_t tile_flags,
+			  bool no_vm, bool mappable, struct nouveau_bo **);
+extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
+extern int nouveau_bo_unpin(struct nouveau_bo *);
+extern int nouveau_bo_map(struct nouveau_bo *);
+extern void nouveau_bo_unmap(struct nouveau_bo *);
+extern void nouveau_bo_placement_set(struct nouveau_bo *, uint32_t memtype);
+extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);
+extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);
+extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index);
+extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val);
+
+/* nouveau_fence.c */
+struct nouveau_fence;
+extern int nouveau_fence_init(struct nouveau_channel *);
+extern void nouveau_fence_fini(struct nouveau_channel *);
+extern void nouveau_fence_update(struct nouveau_channel *);
+extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **,
+			     bool emit);
+extern int nouveau_fence_emit(struct nouveau_fence *);
+struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *);
+extern bool nouveau_fence_signalled(void *obj, void *arg);
+extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
+extern int nouveau_fence_flush(void *obj, void *arg);
+extern void nouveau_fence_unref(void **obj);
+extern void *nouveau_fence_ref(void *obj);
+extern void nouveau_fence_handler(struct drm_device *dev, int channel);
+
+/* nouveau_gem.c */
+extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
+			   int size, int align, uint32_t flags,
+			   uint32_t tile_mode, uint32_t tile_flags,
+			   bool no_vm, bool mappable, struct nouveau_bo **);
+extern int nouveau_gem_object_new(struct drm_gem_object *);
+extern void nouveau_gem_object_del(struct drm_gem_object *);
+extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
+				 struct drm_file *);
+extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
+				     struct drm_file *);
+extern int nouveau_gem_ioctl_pushbuf_call(struct drm_device *, void *,
+					  struct drm_file *);
+extern int nouveau_gem_ioctl_pushbuf_call2(struct drm_device *, void *,
+					   struct drm_file *);
+extern int nouveau_gem_ioctl_pin(struct drm_device *, void *,
+				 struct drm_file *);
+extern int nouveau_gem_ioctl_unpin(struct drm_device *, void *,
+				   struct drm_file *);
+extern int nouveau_gem_ioctl_tile(struct drm_device *, void *,
+				  struct drm_file *);
+extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *,
+				      struct drm_file *);
+extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
+				      struct drm_file *);
+extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
+				  struct drm_file *);
+
+/* nv17_gpio.c */
+int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+
+#ifndef ioread32_native
+#ifdef __BIG_ENDIAN
+#define ioread16_native ioread16be
+#define iowrite16_native iowrite16be
+#define ioread32_native  ioread32be
+#define iowrite32_native iowrite32be
+#else /* def __BIG_ENDIAN */
+#define ioread16_native ioread16
+#define iowrite16_native iowrite16
+#define ioread32_native  ioread32
+#define iowrite32_native iowrite32
+#endif /* def __BIG_ENDIAN else */
+#endif /* !ioread32_native */
+
+/* channel control reg access */
+static inline u32 nvchan_rd32(struct nouveau_channel *chan, unsigned reg)
+{
+	return ioread32_native(chan->user + reg);
+}
+
+static inline void nvchan_wr32(struct nouveau_channel *chan,
+							unsigned reg, u32 val)
+{
+	iowrite32_native(val, chan->user + reg);
+}
+
+/* register access */
+static inline u32 nv_rd32(struct drm_device *dev, unsigned reg)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return ioread32_native(dev_priv->mmio + reg);
+}
+
+static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	iowrite32_native(val, dev_priv->mmio + reg);
+}
+
+static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return ioread8(dev_priv->mmio + reg);
+}
+
+static inline void nv_wr08(struct drm_device *dev, unsigned reg, u8 val)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	iowrite8(val, dev_priv->mmio + reg);
+}
+
+#define nv_wait(reg, mask, val) \
+	nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val))
+
+/* PRAMIN access */
+static inline u32 nv_ri32(struct drm_device *dev, unsigned offset)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return ioread32_native(dev_priv->ramin + offset);
+}
+
+static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	iowrite32_native(val, dev_priv->ramin + offset);
+}
+
+/* object access */
+static inline u32 nv_ro32(struct drm_device *dev, struct nouveau_gpuobj *obj,
+				unsigned index)
+{
+	return nv_ri32(dev, obj->im_pramin->start + index * 4);
+}
+
+static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj,
+				unsigned index, u32 val)
+{
+	nv_wi32(dev, obj->im_pramin->start + index * 4, val);
+}
+
+/*
+ * Logging
+ * Argument d is (struct drm_device *).
+ */
+#define NV_PRINTK(level, d, fmt, arg...) \
+	printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \
+					pci_name(d->pdev), ##arg)
+#ifndef NV_DEBUG_NOTRACE
+#define NV_DEBUG(d, fmt, arg...) do {                                          \
+	if (drm_debug & DRM_UT_DRIVER) {                                       \
+		NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \
+			  __LINE__, ##arg);                                    \
+	}                                                                      \
+} while (0)
+#define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \
+	if (drm_debug & DRM_UT_KMS) {                                          \
+		NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \
+			  __LINE__, ##arg);                                    \
+	}                                                                      \
+} while (0)
+#else
+#define NV_DEBUG(d, fmt, arg...) do {                                          \
+	if (drm_debug & DRM_UT_DRIVER)                                         \
+		NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \
+} while (0)
+#define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \
+	if (drm_debug & DRM_UT_KMS)                                            \
+		NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \
+} while (0)
+#endif
+#define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg)
+#define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
+#define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg)
+#define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
+#define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg)
+
+/* nouveau_reg_debug bitmask */
+enum {
+	NOUVEAU_REG_DEBUG_MC             = 0x1,
+	NOUVEAU_REG_DEBUG_VIDEO          = 0x2,
+	NOUVEAU_REG_DEBUG_FB             = 0x4,
+	NOUVEAU_REG_DEBUG_EXTDEV         = 0x8,
+	NOUVEAU_REG_DEBUG_CRTC           = 0x10,
+	NOUVEAU_REG_DEBUG_RAMDAC         = 0x20,
+	NOUVEAU_REG_DEBUG_VGACRTC        = 0x40,
+	NOUVEAU_REG_DEBUG_RMVIO          = 0x80,
+	NOUVEAU_REG_DEBUG_VGAATTR        = 0x100,
+	NOUVEAU_REG_DEBUG_EVO            = 0x200,
+};
+
+#define NV_REG_DEBUG(type, dev, fmt, arg...) do { \
+	if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_##type) \
+		NV_PRINTK(KERN_DEBUG, dev, "%s: " fmt, __func__, ##arg); \
+} while (0)
+
+static inline bool
+nv_two_heads(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const int impl = dev->pci_device & 0x0ff0;
+
+	if (dev_priv->card_type >= NV_10 && impl != 0x0100 &&
+	    impl != 0x0150 && impl != 0x01a0 && impl != 0x0200)
+		return true;
+
+	return false;
+}
+
+static inline bool
+nv_gf4_disp_arch(struct drm_device *dev)
+{
+	return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110;
+}
+
+static inline bool
+nv_two_reg_pll(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const int impl = dev->pci_device & 0x0ff0;
+
+	if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40)
+		return true;
+	return false;
+}
+
+#define NV_SW                                                        0x0000506e
+#define NV_SW_DMA_SEMAPHORE                                          0x00000060
+#define NV_SW_SEMAPHORE_OFFSET                                       0x00000064
+#define NV_SW_SEMAPHORE_ACQUIRE                                      0x00000068
+#define NV_SW_SEMAPHORE_RELEASE                                      0x0000006c
+#define NV_SW_DMA_VBLSEM                                             0x0000018c
+#define NV_SW_VBLSEM_OFFSET                                          0x00000400
+#define NV_SW_VBLSEM_RELEASE_VALUE                                   0x00000404
+#define NV_SW_VBLSEM_RELEASE                                         0x00000408
+
+#endif /* __NOUVEAU_DRV_H__ */
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/nouveau/nouveau_grctx.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/nouveau/nouveau_grctx.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <linux/firmware.h>
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+
+struct nouveau_ctxprog {
+	uint32_t signature;
+	uint8_t  version;
+	uint16_t length;
+	uint32_t data[];
+} __attribute__ ((packed));
+
+struct nouveau_ctxvals {
+	uint32_t signature;
+	uint8_t  version;
+	uint32_t length;
+	struct {
+		uint32_t offset;
+		uint32_t value;
+	} data[];
+} __attribute__ ((packed));
+
+int
+nouveau_grctx_prog_load(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	const int chipset = dev_priv->chipset;
+	const struct firmware *fw;
+	const struct nouveau_ctxprog *cp;
+	const struct nouveau_ctxvals *cv;
+	char name[32];
+	int ret, i;
+
+	if (pgraph->accel_blocked)
+		return -ENODEV;
+
+	if (!pgraph->ctxprog) {
+		sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
+		ret = request_firmware(&fw, name, &dev->pdev->dev);
+		if (ret) {
+			NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
+			return ret;
+		}
+
+		pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL);
+		if (!pgraph->ctxprog) {
+			NV_ERROR(dev, "OOM copying ctxprog\n");
+			release_firmware(fw);
+			return -ENOMEM;
+		}
+		memcpy(pgraph->ctxprog, fw->data, fw->size);
+
+		cp = pgraph->ctxprog;
+		if (le32_to_cpu(cp->signature) != 0x5043564e ||
+		    cp->version != 0 ||
+		    le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
+			NV_ERROR(dev, "ctxprog invalid\n");
+			release_firmware(fw);
+			nouveau_grctx_fini(dev);
+			return -EINVAL;
+		}
+		release_firmware(fw);
+	}
+
+	if (!pgraph->ctxvals) {
+		sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
+		ret = request_firmware(&fw, name, &dev->pdev->dev);
+		if (ret) {
+			NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
+			nouveau_grctx_fini(dev);
+			return ret;
+		}
+
+		pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL);
+		if (!pgraph->ctxvals) {
+			NV_ERROR(dev, "OOM copying ctxvals\n");
+			release_firmware(fw);
+			nouveau_grctx_fini(dev);
+			return -ENOMEM;
+		}
+		memcpy(pgraph->ctxvals, fw->data, fw->size);
+
+		cv = (void *)pgraph->ctxvals;
+		if (le32_to_cpu(cv->signature) != 0x5643564e ||
+		    cv->version != 0 ||
+		    le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
+			NV_ERROR(dev, "ctxvals invalid\n");
+			release_firmware(fw);
+			nouveau_grctx_fini(dev);
+			return -EINVAL;
+		}
+		release_firmware(fw);
+	}
+
+	cp = pgraph->ctxprog;
+
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+	for (i = 0; i < le16_to_cpu(cp->length); i++)
+		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
+			le32_to_cpu(cp->data[i]));
+
+	return 0;
+}
+
+void
+nouveau_grctx_fini(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+
+	if (pgraph->ctxprog) {
+		kfree(pgraph->ctxprog);
+		pgraph->ctxprog = NULL;
+	}
+
+	if (pgraph->ctxvals) {
+		kfree(pgraph->ctxprog);
+		pgraph->ctxvals = NULL;
+	}
+}
+
+void
+nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+	struct nouveau_ctxvals *cv = pgraph->ctxvals;
+	int i;
+
+	if (!cv)
+		return;
+
+	for (i = 0; i < le32_to_cpu(cv->length); i++)
+		nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
+			le32_to_cpu(cv->data[i].value));
+}
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/mga/mga_ioc32.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/mga/mga_ioc32.c
@@ -100,8 +100,7 @@
 	if (err)
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_MGA_INIT, (unsigned long)init);
+	return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init);
 }
 
 typedef struct drm_mga_getparam32 {
@@ -125,8 +124,7 @@
 			  &getparam->value))
 		return -EFAULT;
 
-	return drm_ioctl(file->f_path.dentry->d_inode, file,
-			 DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+	return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
 }
 
 typedef struct drm_mga_drm_bootstrap32 {
@@ -166,8 +164,7 @@
 	    || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
 		return -EFAULT;
 
-	err = drm_ioctl(file->f_path.dentry->d_inode, file,
-			DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+	err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP,
 			(unsigned long)dma_bootstrap);
 	if (err)
 		return err;
@@ -220,12 +217,10 @@
 	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
 		fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
 
-	lock_kernel();		/* XXX for now */
 	if (fn != NULL)
 		ret = (*fn) (filp, cmd, arg);
 	else
-		ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-	unlock_kernel();
+		ret = drm_ioctl(filp, cmd, arg);
 
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/gpu/drm/mga/mga_drv.c
+++ linux-ec2-2.6.32/drivers/gpu/drm/mga/mga_drv.c
@@ -68,7 +68,7 @@
 		.owner = THIS_MODULE,
 		.open = drm_open,
 		.release = drm_release,
-		.ioctl = drm_ioctl,
+		.unlocked_ioctl = drm_ioctl,
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
--- linux-ec2-2.6.32.orig/drivers/mfd/ab3100-core.c
+++ linux-ec2-2.6.32/drivers/mfd/ab3100-core.c
@@ -591,7 +591,7 @@
 	ab3100_get_priv.ab3100 = ab3100;
 	ab3100_get_priv.mode = false;
 	ab3100_get_reg_file = debugfs_create_file("get_reg",
-				S_IWUGO, ab3100_dir, &ab3100_get_priv,
+				S_IWUSR, ab3100_dir, &ab3100_get_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_get_reg_file) {
 		err = -ENOMEM;
@@ -601,7 +601,7 @@
 	ab3100_set_priv.ab3100 = ab3100;
 	ab3100_set_priv.mode = true;
 	ab3100_set_reg_file = debugfs_create_file("set_reg",
-				S_IWUGO, ab3100_dir, &ab3100_set_priv,
+				S_IWUSR, ab3100_dir, &ab3100_set_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_set_reg_file) {
 		err = -ENOMEM;
--- linux-ec2-2.6.32.orig/drivers/mfd/ucb1x00-ts.c
+++ linux-ec2-2.6.32/drivers/mfd/ucb1x00-ts.c
@@ -385,12 +385,18 @@
 	idev->close      = ucb1x00_ts_close;
 
 	__set_bit(EV_ABS, idev->evbit);
-	__set_bit(ABS_X, idev->absbit);
-	__set_bit(ABS_Y, idev->absbit);
-	__set_bit(ABS_PRESSURE, idev->absbit);
 
 	input_set_drvdata(idev, ts);
 
+	ucb1x00_adc_enable(ts->ucb);
+	ts->x_res = ucb1x00_ts_read_xres(ts);
+	ts->y_res = ucb1x00_ts_read_yres(ts);
+	ucb1x00_adc_disable(ts->ucb);
+
+	input_set_abs_params(idev, ABS_X, 0, ts->x_res, 0, 0);
+	input_set_abs_params(idev, ABS_Y, 0, ts->y_res, 0, 0);
+	input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
+
 	err = input_register_device(idev);
 	if (err)
 		goto fail;
--- linux-ec2-2.6.32.orig/drivers/mfd/wm8350-core.c
+++ linux-ec2-2.6.32/drivers/mfd/wm8350-core.c
@@ -134,8 +134,7 @@
 	    wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
 		return 0;
 
-	if ((reg == WM8350_GPIO_CONFIGURATION_I_O) ||
-	    (reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
+	if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
 	     reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
 	    (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
 	     reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
--- linux-ec2-2.6.32.orig/drivers/clocksource/sh_cmt.c
+++ linux-ec2-2.6.32/drivers/clocksource/sh_cmt.c
@@ -413,18 +413,10 @@
 static int sh_cmt_clocksource_enable(struct clocksource *cs)
 {
 	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
-	int ret;
 
 	p->total_cycles = 0;
 
-	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
-	if (ret)
-		return ret;
-
-	/* TODO: calculate good shift from rate and counter bit width */
-	cs->shift = 0;
-	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
-	return 0;
+	return sh_cmt_start(p, FLAG_CLOCKSOURCE);
 }
 
 static void sh_cmt_clocksource_disable(struct clocksource *cs)
@@ -444,7 +436,18 @@
 	cs->disable = sh_cmt_clocksource_disable;
 	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	/* clk_get_rate() needs an enabled clock */
+	clk_enable(p->clk);
+	p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
+	clk_disable(p->clk);
+
+	/* TODO: calculate good shift from rate and counter bit width */
+	cs->shift = 10;
+	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
 	pr_info("sh_cmt: %s used as clock source\n", cs->name);
+
 	clocksource_register(cs);
 	return 0;
 }
@@ -603,18 +606,13 @@
 	p->irqaction.handler = sh_cmt_interrupt;
 	p->irqaction.dev_id = p;
 	p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
-	ret = setup_irq(irq, &p->irqaction);
-	if (ret) {
-		pr_err("sh_cmt: failed to request irq %d\n", irq);
-		goto err1;
-	}
 
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, cfg->clk);
 	if (IS_ERR(p->clk)) {
 		pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk);
 		ret = PTR_ERR(p->clk);
-		goto err2;
+		goto err1;
 	}
 
 	if (resource_size(res) == 6) {
@@ -627,14 +625,25 @@
 		p->clear_bits = ~0xc000;
 	}
 
-	return sh_cmt_register(p, cfg->name,
-			       cfg->clockevent_rating,
-			       cfg->clocksource_rating);
- err2:
-	remove_irq(irq, &p->irqaction);
- err1:
+	ret = sh_cmt_register(p, cfg->name,
+			      cfg->clockevent_rating,
+			      cfg->clocksource_rating);
+	if (ret) {
+		pr_err("sh_cmt: registration failed\n");
+		goto err1;
+	}
+
+	ret = setup_irq(irq, &p->irqaction);
+	if (ret) {
+		pr_err("sh_cmt: failed to request irq %d\n", irq);
+		goto err1;
+	}
+
+	return 0;
+
+err1:
 	iounmap(p->mapbase);
- err0:
+err0:
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/drivers/clocksource/sh_tmu.c
+++ linux-ec2-2.6.32/drivers/clocksource/sh_tmu.c
@@ -199,16 +199,8 @@
 static int sh_tmu_clocksource_enable(struct clocksource *cs)
 {
 	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
-	int ret;
-
-	ret = sh_tmu_enable(p);
-	if (ret)
-		return ret;
 
-	/* TODO: calculate good shift from rate and counter bit width */
-	cs->shift = 10;
-	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
-	return 0;
+	return sh_tmu_enable(p);
 }
 
 static void sh_tmu_clocksource_disable(struct clocksource *cs)
@@ -228,6 +220,16 @@
 	cs->disable = sh_tmu_clocksource_disable;
 	cs->mask = CLOCKSOURCE_MASK(32);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	/* clk_get_rate() needs an enabled clock */
+	clk_enable(p->clk);
+	/* channel will be configured at parent clock / 4 */
+	p->rate = clk_get_rate(p->clk) / 4;
+	clk_disable(p->clk);
+	/* TODO: calculate good shift from rate and counter bit width */
+	cs->shift = 10;
+	cs->mult = clocksource_hz2mult(p->rate, cs->shift);
+
 	pr_info("sh_tmu: %s used as clock source\n", cs->name);
 	clocksource_register(cs);
 	return 0;
@@ -323,15 +325,15 @@
 	ced->set_next_event = sh_tmu_clock_event_next;
 	ced->set_mode = sh_tmu_clock_event_mode;
 
+	pr_info("sh_tmu: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+
 	ret = setup_irq(p->irqaction.irq, &p->irqaction);
 	if (ret) {
 		pr_err("sh_tmu: failed to request irq %d\n",
 		       p->irqaction.irq);
 		return;
 	}
-
-	pr_info("sh_tmu: %s used for clock events\n", ced->name);
-	clockevents_register_device(ced);
 }
 
 static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
--- linux-ec2-2.6.32.orig/drivers/clocksource/sh_mtu2.c
+++ linux-ec2-2.6.32/drivers/clocksource/sh_mtu2.c
@@ -221,15 +221,15 @@
 	ced->cpumask = cpumask_of(0);
 	ced->set_mode = sh_mtu2_clock_event_mode;
 
+	pr_info("sh_mtu2: %s used for clock events\n", ced->name);
+	clockevents_register_device(ced);
+
 	ret = setup_irq(p->irqaction.irq, &p->irqaction);
 	if (ret) {
 		pr_err("sh_mtu2: failed to request irq %d\n",
 		       p->irqaction.irq);
 		return;
 	}
-
-	pr_info("sh_mtu2: %s used for clock events\n", ced->name);
-	clockevents_register_device(ced);
 }
 
 static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
--- linux-ec2-2.6.32.orig/drivers/w1/slaves/w1_therm.c
+++ linux-ec2-2.6.32/drivers/w1/slaves/w1_therm.c
@@ -115,9 +115,8 @@
 
 static inline int w1_DS18B20_convert_temp(u8 rom[9])
 {
-	int t = ((s16)rom[1] << 8) | rom[0];
-	t = t*1000/16;
-	return t;
+	s16 t = le16_to_cpup((__le16 *)rom);
+	return t*1000/16;
 }
 
 static inline int w1_DS18S20_convert_temp(u8 rom[9])
--- linux-ec2-2.6.32.orig/drivers/rtc/class.c
+++ linux-ec2-2.6.32/drivers/rtc/class.c
@@ -226,6 +226,7 @@
 {
 	rtc_dev_exit();
 	class_destroy(rtc_class);
+	idr_destroy(&rtc_idr);
 }
 
 subsys_initcall(rtc_init);
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-ds1307.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-ds1307.c
@@ -775,7 +775,7 @@
 
 read_rtc:
 	/* read RTC registers */
-	tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf);
+	tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
 	if (tmp != 8) {
 		pr_debug("read error %d\n", tmp);
 		err = -EIO;
@@ -860,7 +860,7 @@
 		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
 			tmp += 12;
 		i2c_smbus_write_byte_data(client,
-				DS1307_REG_HOUR,
+				ds1307->offset + DS1307_REG_HOUR,
 				bin2bcd(tmp));
 	}
 
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-cmos.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-cmos.c
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
+#include <linux/pm.h>
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
@@ -723,6 +724,9 @@
 		}
 	}
 
+	cmos_rtc.dev = dev;
+	dev_set_drvdata(dev, &cmos_rtc);
+
 	cmos_rtc.rtc = rtc_device_register(driver_name, dev,
 				&cmos_rtc_ops, THIS_MODULE);
 	if (IS_ERR(cmos_rtc.rtc)) {
@@ -730,8 +734,6 @@
 		goto cleanup0;
 	}
 
-	cmos_rtc.dev = dev;
-	dev_set_drvdata(dev, &cmos_rtc);
 	rename_region(ports, dev_name(&cmos_rtc.rtc->dev));
 
 	spin_lock_irq(&rtc_lock);
@@ -854,7 +856,7 @@
 
 #ifdef	CONFIG_PM
 
-static int cmos_suspend(struct device *dev, pm_message_t mesg)
+static int cmos_suspend(struct device *dev)
 {
 	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
 	unsigned char	tmp;
@@ -901,7 +903,7 @@
  */
 static inline int cmos_poweroff(struct device *dev)
 {
-	return cmos_suspend(dev, PMSG_HIBERNATE);
+	return cmos_suspend(dev);
 }
 
 static int cmos_resume(struct device *dev)
@@ -948,9 +950,9 @@
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
+
 #else
-#define	cmos_suspend	NULL
-#define	cmos_resume	NULL
 
 static inline int cmos_poweroff(struct device *dev)
 {
@@ -1086,7 +1088,7 @@
 
 static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg)
 {
-	return cmos_suspend(&pnp->dev, mesg);
+	return cmos_suspend(&pnp->dev);
 }
 
 static int cmos_pnp_resume(struct pnp_dev *pnp)
@@ -1099,9 +1101,9 @@
 #define	cmos_pnp_resume		NULL
 #endif
 
-static void cmos_pnp_shutdown(struct device *pdev)
+static void cmos_pnp_shutdown(struct pnp_dev *pnp)
 {
-	if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev))
+	if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
 		return;
 
 	cmos_do_shutdown();
@@ -1120,15 +1122,12 @@
 	.id_table	= rtc_ids,
 	.probe		= cmos_pnp_probe,
 	.remove		= __exit_p(cmos_pnp_remove),
+	.shutdown	= cmos_pnp_shutdown,
 
 	/* flag ensures resume() gets called, and stops syslog spam */
 	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
 	.suspend	= cmos_pnp_suspend,
 	.resume		= cmos_pnp_resume,
-	.driver		= {
-		.name	  = (char *)driver_name,
-		.shutdown = cmos_pnp_shutdown,
-	}
 };
 
 #endif	/* CONFIG_PNP */
@@ -1169,8 +1168,9 @@
 	.shutdown	= cmos_platform_shutdown,
 	.driver = {
 		.name		= (char *) driver_name,
-		.suspend	= cmos_suspend,
-		.resume		= cmos_resume,
+#ifdef CONFIG_PM
+		.pm		= &cmos_pm_ops,
+#endif
 	}
 };
 
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-coh901331.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-coh901331.c
@@ -271,12 +271,13 @@
 {
 	struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev);
 
-	if (device_may_wakeup(&pdev->dev))
+	if (device_may_wakeup(&pdev->dev)) {
 		disable_irq_wake(rtap->irq);
-	else
+	} else {
 		clk_enable(rtap->clk);
 		writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK);
 		clk_disable(rtap->clk);
+	}
 	return 0;
 }
 #else
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-ds1511.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-ds1511.c
@@ -480,7 +480,7 @@
 static struct bin_attribute ds1511_nvram_attr = {
 	.attr = {
 		.name = "nvram",
-		.mode = S_IRUGO | S_IWUGO,
+		.mode = S_IRUGO | S_IWUSR,
 	},
 	.size = DS1511_RAM_MAX,
 	.read = ds1511_nvram_read,
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-fm3130.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-fm3130.c
@@ -376,20 +376,22 @@
 	}
 
 	/* Disabling calibration mode */
-	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL)
+	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
 		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
 			fm3130->regs[FM3130_RTC_CONTROL] &
 				~(FM3130_RTC_CONTROL_BIT_CAL));
 		dev_warn(&client->dev, "Disabling calibration mode!\n");
+	}
 
 	/* Disabling read and write modes */
 	if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
-	    fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ)
+	    fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
 		i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
 			fm3130->regs[FM3130_RTC_CONTROL] &
 				~(FM3130_RTC_CONTROL_BIT_READ |
 					FM3130_RTC_CONTROL_BIT_WRITE));
 		dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
+	}
 
 	/* oscillator off?  turn it on, so clock can tick. */
 	if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
--- linux-ec2-2.6.32.orig/drivers/rtc/rtc-s3c.c
+++ linux-ec2-2.6.32/drivers/rtc/rtc-s3c.c
@@ -456,8 +456,6 @@
  	pr_debug("s3c2410_rtc: RTCCON=%02x\n",
 		 readb(s3c_rtc_base + S3C2410_RTCCON));
 
-	s3c_rtc_setfreq(&pdev->dev, 1);
-
 	device_init_wakeup(&pdev->dev, 1);
 
 	/* register RTC and exit */
@@ -474,6 +472,9 @@
 	rtc->max_user_freq = 128;
 
 	platform_set_drvdata(pdev, rtc);
+
+	s3c_rtc_setfreq(&pdev->dev, 1);
+
 	return 0;
 
  err_nortc:
--- linux-ec2-2.6.32.orig/drivers/hwmon/f75375s.c
+++ linux-ec2-2.6.32/drivers/hwmon/f75375s.c
@@ -79,7 +79,7 @@
 #define F75375_REG_PWM2_DROP_DUTY	0x6C
 
 #define FAN_CTRL_LINEAR(nr)		(4 + nr)
-#define FAN_CTRL_MODE(nr)		(5 + ((nr) * 2))
+#define FAN_CTRL_MODE(nr)		(4 + ((nr) * 2))
 
 /*
  * Data structures and manipulation thereof
@@ -298,7 +298,7 @@
 		return -EINVAL;
 
 	fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
-	fanmode = ~(3 << FAN_CTRL_MODE(nr));
+	fanmode &= ~(3 << FAN_CTRL_MODE(nr));
 
 	switch (val) {
 	case 0: /* Full speed */
@@ -350,7 +350,7 @@
 
 	mutex_lock(&data->update_lock);
 	conf = f75375_read8(client, F75375_REG_CONFIG1);
-	conf = ~(1 << FAN_CTRL_LINEAR(nr));
+	conf &= ~(1 << FAN_CTRL_LINEAR(nr));
 
 	if (val == 0)
 		conf |= (1 << FAN_CTRL_LINEAR(nr)) ;
--- linux-ec2-2.6.32.orig/drivers/hwmon/via686a.c
+++ linux-ec2-2.6.32/drivers/hwmon/via686a.c
@@ -687,6 +687,13 @@
 	return 0;
 }
 
+static void via686a_update_fan_div(struct via686a_data *data)
+{
+	int reg = via686a_read_value(data, VIA686A_REG_FANDIV);
+	data->fan_div[0] = (reg >> 4) & 0x03;
+	data->fan_div[1] = reg >> 6;
+}
+
 static void __devinit via686a_init_device(struct via686a_data *data)
 {
 	u8 reg;
@@ -700,6 +707,9 @@
 	via686a_write_value(data, VIA686A_REG_TEMP_MODE,
 			    (reg & ~VIA686A_TEMP_MODE_MASK)
 			    | VIA686A_TEMP_MODE_CONTINUOUS);
+
+	/* Pre-read fan clock divisor values */
+	via686a_update_fan_div(data);
 }
 
 static struct via686a_data *via686a_update_device(struct device *dev)
@@ -751,9 +761,7 @@
 		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 		     0xc0) >> 6;
 
-		i = via686a_read_value(data, VIA686A_REG_FANDIV);
-		data->fan_div[0] = (i >> 4) & 0x03;
-		data->fan_div[1] = i >> 6;
+		via686a_update_fan_div(data);
 		data->alarms =
 		    via686a_read_value(data,
 				       VIA686A_REG_ALARM1) |
--- linux-ec2-2.6.32.orig/drivers/hwmon/lm85.c
+++ linux-ec2-2.6.32/drivers/hwmon/lm85.c
@@ -1286,6 +1286,7 @@
 	switch (data->type) {
 	case adm1027:
 	case adt7463:
+	case adt7468:
 	case emc6d100:
 	case emc6d102:
 		data->freq_map = adm1027_freq_map;
--- linux-ec2-2.6.32.orig/drivers/hwmon/fschmd.c
+++ linux-ec2-2.6.32/drivers/hwmon/fschmd.c
@@ -767,6 +767,7 @@
 static int watchdog_open(struct inode *inode, struct file *filp)
 {
 	struct fschmd_data *pos, *data = NULL;
+	int watchdog_is_open;
 
 	/* We get called from drivers/char/misc.c with misc_mtx hold, and we
 	   call misc_register() from fschmd_probe() with watchdog_data_mutex
@@ -781,10 +782,12 @@
 		}
 	}
 	/* Note we can never not have found data, so we don't check for this */
-	kref_get(&data->kref);
+	watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
+	if (!watchdog_is_open)
+		kref_get(&data->kref);
 	mutex_unlock(&watchdog_data_mutex);
 
-	if (test_and_set_bit(0, &data->watchdog_is_open))
+	if (watchdog_is_open)
 		return -EBUSY;
 
 	/* Start the watchdog */
--- linux-ec2-2.6.32.orig/drivers/hwmon/lis3lv02d.c
+++ linux-ec2-2.6.32/drivers/hwmon/lis3lv02d.c
@@ -127,12 +127,14 @@
 
 	/*
 	 * Common configuration
-	 * BDU: LSB and MSB values are not updated until both have been read.
-	 *      So the value read will always be correct.
+	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
+	 *      both have been read. So the value read will always be correct.
 	 */
-	lis3->read(lis3, CTRL_REG2, &reg);
-	reg |= CTRL2_BDU;
-	lis3->write(lis3, CTRL_REG2, reg);
+	if (lis3->whoami == LIS_DOUBLE_ID) {
+		lis3->read(lis3, CTRL_REG2, &reg);
+		reg |= CTRL2_BDU;
+		lis3->write(lis3, CTRL_REG2, reg);
+	}
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
@@ -361,7 +363,8 @@
 }
 
 /* conversion btw sampling rate and the register values */
-static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560};
+static int lis3_12_rates[4] = {40, 160, 640, 2560};
+static int lis3_8_rates[2] = {100, 400};
 static ssize_t lis3lv02d_rate_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
@@ -369,8 +372,13 @@
 	int val;
 
 	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4;
-	return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]);
+
+	if (lis3_dev.whoami == LIS_DOUBLE_ID)
+		val = lis3_12_rates[(ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4];
+	else
+		val = lis3_8_rates[(ctrl & CTRL1_DR) >> 7];
+
+	return sprintf(buf, "%d\n", val);
 }
 
 static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
--- linux-ec2-2.6.32.orig/drivers/hwmon/ltc4245.c
+++ linux-ec2-2.6.32/drivers/hwmon/ltc4245.c
@@ -45,9 +45,7 @@
 	LTC4245_VEEIN			= 0x19,
 	LTC4245_VEESENSE		= 0x1a,
 	LTC4245_VEEOUT			= 0x1b,
-	LTC4245_GPIOADC1		= 0x1c,
-	LTC4245_GPIOADC2		= 0x1d,
-	LTC4245_GPIOADC3		= 0x1e,
+	LTC4245_GPIOADC			= 0x1c,
 };
 
 struct ltc4245_data {
@@ -61,7 +59,7 @@
 	u8 cregs[0x08];
 
 	/* Voltage registers */
-	u8 vregs[0x0f];
+	u8 vregs[0x0d];
 };
 
 static struct ltc4245_data *ltc4245_update_device(struct device *dev)
@@ -86,7 +84,7 @@
 				data->cregs[i] = val;
 		}
 
-		/* Read voltage registers -- 0x10 to 0x1f */
+		/* Read voltage registers -- 0x10 to 0x1c */
 		for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
 			val = i2c_smbus_read_byte_data(client, i+0x10);
 			if (unlikely(val < 0))
@@ -128,9 +126,7 @@
 	case LTC4245_VEEOUT:
 		voltage = regval * -55;
 		break;
-	case LTC4245_GPIOADC1:
-	case LTC4245_GPIOADC2:
-	case LTC4245_GPIOADC3:
+	case LTC4245_GPIOADC:
 		voltage = regval * 10;
 		break;
 	default:
@@ -297,9 +293,7 @@
 LTC4245_ALARM(in8_min_alarm,	(1 << 3),	LTC4245_FAULT2);
 
 /* GPIO voltages */
-LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC1);
-LTC4245_VOLTAGE(in10_input,			LTC4245_GPIOADC2);
-LTC4245_VOLTAGE(in11_input,			LTC4245_GPIOADC3);
+LTC4245_VOLTAGE(in9_input,			LTC4245_GPIOADC);
 
 /* Power Consumption (virtual) */
 LTC4245_POWER(power1_input,			LTC4245_12VSENSE);
@@ -342,8 +336,6 @@
 	&sensor_dev_attr_in8_min_alarm.dev_attr.attr,
 
 	&sensor_dev_attr_in9_input.dev_attr.attr,
-	&sensor_dev_attr_in10_input.dev_attr.attr,
-	&sensor_dev_attr_in11_input.dev_attr.attr,
 
 	&sensor_dev_attr_power1_input.dev_attr.attr,
 	&sensor_dev_attr_power2_input.dev_attr.attr,
--- linux-ec2-2.6.32.orig/drivers/hwmon/lis3lv02d.h
+++ linux-ec2-2.6.32/drivers/hwmon/lis3lv02d.h
@@ -103,6 +103,7 @@
 	CTRL1_DF1	= 0x20,
 	CTRL1_PD0	= 0x40,
 	CTRL1_PD1	= 0x80,
+	CTRL1_DR	= 0x80, /* Data rate on 8 bits */
 };
 enum lis3lv02d_ctrl2 {
 	CTRL2_DAS	= 0x01,
--- linux-ec2-2.6.32.orig/drivers/hwmon/adt7462.c
+++ linux-ec2-2.6.32/drivers/hwmon/adt7462.c
@@ -97,7 +97,7 @@
 #define		ADT7462_PIN24_SHIFT		6
 #define		ADT7462_PIN26_VOLT_INPUT	0x08
 #define		ADT7462_PIN25_VOLT_INPUT	0x20
-#define		ADT7462_PIN28_SHIFT		6	/* cfg3 */
+#define		ADT7462_PIN28_SHIFT		4	/* cfg3 */
 #define		ADT7462_PIN28_VOLT		0x5
 
 #define ADT7462_REG_ALARM1			0xB8
@@ -182,7 +182,7 @@
  *
  * Some, but not all, of these voltages have low/high limits.
  */
-#define ADT7462_VOLT_COUNT	12
+#define ADT7462_VOLT_COUNT	13
 
 #define ADT7462_VENDOR		0x41
 #define ADT7462_DEVICE		0x62
--- linux-ec2-2.6.32.orig/drivers/hwmon/Kconfig
+++ linux-ec2-2.6.32/drivers/hwmon/Kconfig
@@ -374,7 +374,7 @@
 
 config SENSORS_CORETEMP
 	tristate "Intel Core/Core2/Atom temperature sensor"
-	depends on X86 && EXPERIMENTAL
+	depends on X86 && PCI && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the temperature
 	  sensor inside your CPU. Most of the family 6 CPUs
--- linux-ec2-2.6.32.orig/drivers/hwmon/applesmc.c
+++ linux-ec2-2.6.32/drivers/hwmon/applesmc.c
@@ -142,6 +142,30 @@
 	  "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S",
 	  "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S",
 	  NULL },
+/* Set 17: iMac 9,1 */
+	{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TH0P", "TL0P",
+	  "TN0D", "TN0H", "TN0P", "TO0P", "Tm0P", "Tp0P", NULL },
+/* Set 18: MacBook Pro 2,2 */
+	{ "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0",
+	  "Th0H", "Th1H", "Tm0P", "Ts0P", NULL },
+/* Set 19: Macbook Pro 5,3 */
+	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
+	  "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H",
+	  "Tm0P", "Ts0P", "Ts0S", NULL },
+/* Set 20: MacBook Pro 5,4 */
+	{ "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D",
+	  "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL },
+/* Set 21: MacBook Pro 6,2 */
+	{ "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D",
+	  "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P",
+	  "Ts0P", "Ts0S", NULL },
+/* Set 22: MacBook Pro 7,1 */
+	{ "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S",
+	  "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL },
+/* Set 23: MacBook Air 3,1 */
+	{ "TB0T", "TB1T", "TB2T", "TC0D", "TC0E", "TC0P", "TC1E", "TCZ3",
+	  "TCZ4", "TCZ5", "TG0E", "TG1E", "TG2E", "TGZ3", "TGZ4", "TGZ5",
+	  "TH0F", "TH0O", "TM0P" },
 };
 
 /* List of keys used to read/write fan speeds */
@@ -1350,11 +1374,29 @@
 	{ .accelerometer = 1, .light = 1, .temperature_set = 15 },
 /* MacPro3,1: temperature set 16 */
 	{ .accelerometer = 0, .light = 0, .temperature_set = 16 },
+/* iMac 9,1: light sensor only, temperature set 17 */
+	{ .accelerometer = 0, .light = 0, .temperature_set = 17 },
+/* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */
+	{ .accelerometer = 1, .light = 1, .temperature_set = 18 },
+/* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */
+	{ .accelerometer = 1, .light = 1, .temperature_set = 19 },
+/* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */
+	{ .accelerometer = 1, .light = 1, .temperature_set = 20 },
+/* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */
+	{ .accelerometer = 1, .light = 1, .temperature_set = 21 },
+/* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */
+	{ .accelerometer = 1, .light = 1, .temperature_set = 22 },
+/* MacBook Air 3,1: accelerometer, backlight and temperature set 23 */
+	{ .accelerometer = 0, .light = 0, .temperature_set = 23 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
  * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
 static __initdata struct dmi_system_id applesmc_whitelist[] = {
+	{ applesmc_dmi_match, "Apple MacBook Air 3", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3") },
+		&applesmc_dmi_data[23]},
 	{ applesmc_dmi_match, "Apple MacBook Air 2", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
@@ -1363,6 +1405,22 @@
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
 		&applesmc_dmi_data[7]},
+	{ applesmc_dmi_match, "Apple MacBook Pro 7", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") },
+		&applesmc_dmi_data[22]},
+	{ applesmc_dmi_match, "Apple MacBook Pro 5,4", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") },
+		&applesmc_dmi_data[20]},
+	{ applesmc_dmi_match, "Apple MacBook Pro 5,3", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") },
+		&applesmc_dmi_data[19]},
+	{ applesmc_dmi_match, "Apple MacBook Pro 6", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") },
+		&applesmc_dmi_data[21]},
 	{ applesmc_dmi_match, "Apple MacBook Pro 5", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
@@ -1375,6 +1433,10 @@
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
 		&applesmc_dmi_data[9]},
+	{ applesmc_dmi_match, "Apple MacBook Pro 2,2", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple Computer, Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2") },
+		&applesmc_dmi_data[18]},
 	{ applesmc_dmi_match, "Apple MacBook Pro", {
 	  DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
@@ -1415,6 +1477,10 @@
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
 		&applesmc_dmi_data[4]},
+	{ applesmc_dmi_match, "Apple iMac 9,1", {
+	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1") },
+		&applesmc_dmi_data[17]},
 	{ applesmc_dmi_match, "Apple iMac 8", {
 	  DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
 	  DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
--- linux-ec2-2.6.32.orig/drivers/hwmon/lm78.c
+++ linux-ec2-2.6.32/drivers/hwmon/lm78.c
@@ -870,17 +870,16 @@
 static int __init lm78_isa_found(unsigned short address)
 {
 	int val, save, found = 0;
+	int port;
 
-	/* We have to request the region in two parts because some
-	   boards declare base+4 to base+7 as a PNP device */
-	if (!request_region(address, 4, "lm78")) {
-		pr_debug("lm78: Failed to request low part of region\n");
-		return 0;
-	}
-	if (!request_region(address + 4, 4, "lm78")) {
-		pr_debug("lm78: Failed to request high part of region\n");
-		release_region(address, 4);
-		return 0;
+	/* Some boards declare base+0 to base+7 as a PNP device, some base+4
+	 * to base+7 and some base+5 to base+6. So we better request each port
+	 * individually for the probing phase. */
+	for (port = address; port < address + LM78_EXTENT; port++) {
+		if (!request_region(port, 1, "lm78")) {
+			pr_debug("lm78: Failed to request port 0x%x\n", port);
+			goto release;
+		}
 	}
 
 #define REALLY_SLOW_IO
@@ -944,8 +943,8 @@
 			val & 0x80 ? "LM79" : "LM78", (int)address);
 
  release:
-	release_region(address + 4, 4);
-	release_region(address, 4);
+	for (port--; port >= address; port--)
+		release_region(port, 1);
 	return found;
 }
 
--- linux-ec2-2.6.32.orig/drivers/hwmon/k8temp.c
+++ linux-ec2-2.6.32/drivers/hwmon/k8temp.c
@@ -120,7 +120,7 @@
 	int temp;
 	struct k8temp_data *data = k8temp_update_device(dev);
 
-	if (data->swap_core_select)
+	if (data->swap_core_select && (data->sensorsp & SEL_CORE))
 		core = core ? 0 : 1;
 
 	temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
@@ -143,6 +143,37 @@
 
 MODULE_DEVICE_TABLE(pci, k8temp_ids);
 
+static int __devinit is_rev_g_desktop(u8 model)
+{
+	u32 brandidx;
+
+	if (model < 0x69)
+		return 0;
+
+	if (model == 0xc1 || model == 0x6c || model == 0x7c)
+		return 0;
+
+	/*
+	 * Differentiate between AM2 and ASB1.
+	 * See "Constructing the processor Name String" in "Revision
+	 * Guide for AMD NPT Family 0Fh Processors" (33610).
+	 */
+	brandidx = cpuid_ebx(0x80000001);
+	brandidx = (brandidx >> 9) & 0x1f;
+
+	/* Single core */
+	if ((model == 0x6f || model == 0x7f) &&
+	    (brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc))
+		return 0;
+
+	/* Dual core */
+	if (model == 0x6b &&
+	    (brandidx == 0xb || brandidx == 0xc))
+		return 0;
+
+	return 1;
+}
+
 static int __devinit k8temp_probe(struct pci_dev *pdev,
 				  const struct pci_device_id *id)
 {
@@ -179,12 +210,12 @@
 				 "wrong - check erratum #141\n");
 		}
 
-		if ((model >= 0x69) &&
-		    !(model == 0xc1 || model == 0x6c || model == 0x7c)) {
+		if (is_rev_g_desktop(model)) {
 			/*
-			 * RevG desktop CPUs (i.e. no socket S1G1 parts)
-			 * need additional offset, otherwise reported
-			 * temperature is below ambient temperature
+			 * RevG desktop CPUs (i.e. no socket S1G1 or
+			 * ASB1 parts) need additional offset,
+			 * otherwise reported temperature is below
+			 * ambient temperature
 			 */
 			data->temp_offset = 21000;
 		}
--- linux-ec2-2.6.32.orig/drivers/hwmon/adm1026.c
+++ linux-ec2-2.6.32/drivers/hwmon/adm1026.c
@@ -919,27 +919,27 @@
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val, orig_div, new_div, shift;
+	int val, orig_div, new_div;
 
 	val = simple_strtol(buf, NULL, 10);
 	new_div = DIV_TO_REG(val);
-	if (new_div == 0) {
-		return -EINVAL;
-	}
+
 	mutex_lock(&data->update_lock);
 	orig_div = data->fan_div[nr];
 	data->fan_div[nr] = DIV_FROM_REG(new_div);
 
 	if (nr < 4) { /* 0 <= nr < 4 */
-		shift = 2 * nr;
 		adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
-			((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
-			(new_div << shift)));
+				    (DIV_TO_REG(data->fan_div[0]) << 0) |
+				    (DIV_TO_REG(data->fan_div[1]) << 2) |
+				    (DIV_TO_REG(data->fan_div[2]) << 4) |
+				    (DIV_TO_REG(data->fan_div[3]) << 6));
 	} else { /* 3 < nr < 8 */
-		shift = 2 * (nr - 4);
 		adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
-			((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
-			(new_div << shift)));
+				    (DIV_TO_REG(data->fan_div[4]) << 0) |
+				    (DIV_TO_REG(data->fan_div[5]) << 2) |
+				    (DIV_TO_REG(data->fan_div[6]) << 4) |
+				    (DIV_TO_REG(data->fan_div[7]) << 6));
 	}
 
 	if (data->fan_div[nr] != orig_div) {
--- linux-ec2-2.6.32.orig/drivers/hwmon/pc87360.c
+++ linux-ec2-2.6.32/drivers/hwmon/pc87360.c
@@ -1610,11 +1610,8 @@
 
 static int __init pc87360_device_add(unsigned short address)
 {
-	struct resource res = {
-		.name	= "pc87360",
-		.flags	= IORESOURCE_IO,
-	};
-	int err, i;
+	struct resource res[3];
+	int err, i, res_count;
 
 	pdev = platform_device_alloc("pc87360", address);
 	if (!pdev) {
@@ -1623,22 +1620,28 @@
 		goto exit;
 	}
 
+	memset(res, 0, 3 * sizeof(struct resource));
+	res_count = 0;
 	for (i = 0; i < 3; i++) {
 		if (!extra_isa[i])
 			continue;
-		res.start = extra_isa[i];
-		res.end = extra_isa[i] + PC87360_EXTENT - 1;
+		res[res_count].start = extra_isa[i];
+		res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1;
+		res[res_count].name = "pc87360",
+		res[res_count].flags = IORESOURCE_IO,
 
-		err = acpi_check_resource_conflict(&res);
+		err = acpi_check_resource_conflict(&res[res_count]);
 		if (err)
 			goto exit_device_put;
 
-		err = platform_device_add_resources(pdev, &res, 1);
-		if (err) {
-			printk(KERN_ERR "pc87360: Device resource[%d] "
-			       "addition failed (%d)\n", i, err);
-			goto exit_device_put;
-		}
+		res_count++;
+	}
+
+	err = platform_device_add_resources(pdev, res, res_count);
+	if (err) {
+		printk(KERN_ERR "pc87360: Device resources addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
 	}
 
 	err = platform_device_add(pdev);
--- linux-ec2-2.6.32.orig/drivers/hwmon/sht15.c
+++ linux-ec2-2.6.32/drivers/hwmon/sht15.c
@@ -302,13 +302,13 @@
  **/
 static inline int sht15_calc_temp(struct sht15_data *data)
 {
-	int d1 = 0;
+	int d1 = temppoints[0].d1;
 	int i;
 
-	for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++)
+	for (i = ARRAY_SIZE(temppoints) - 1; i > 0; i--)
 		/* Find pointer to interpolate */
 		if (data->supply_uV > temppoints[i - 1].vdd) {
-			d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd)
+			d1 = (data->supply_uV - temppoints[i - 1].vdd)
 				* (temppoints[i].d1 - temppoints[i - 1].d1)
 				/ (temppoints[i].vdd - temppoints[i - 1].vdd)
 				+ temppoints[i - 1].d1;
@@ -332,12 +332,12 @@
 
 	const int c1 = -4;
 	const int c2 = 40500; /* x 10 ^ -6 */
-	const int c3 = 2800; /* x10 ^ -9 */
+	const int c3 = -28; /* x 10 ^ -7 */
 
 	RHlinear = c1*1000
 		+ c2 * data->val_humid/1000
-		+ (data->val_humid * data->val_humid * c3)/1000000;
-	return (temp - 25000) * (10000 + 800 * data->val_humid)
+		+ (data->val_humid * data->val_humid * c3) / 10000;
+	return (temp - 25000) * (10000 + 80 * data->val_humid)
 		/ 1000000 + RHlinear;
 }
 
@@ -541,7 +541,12 @@
 /* If a regulator is available, query what the supply voltage actually is!*/
 	data->reg = regulator_get(data->dev, "vcc");
 	if (!IS_ERR(data->reg)) {
-		data->supply_uV = regulator_get_voltage(data->reg);
+		int voltage;
+
+		voltage = regulator_get_voltage(data->reg);
+		if (voltage)
+			data->supply_uV = voltage;
+
 		regulator_enable(data->reg);
 		/* setup a notifier block to update this if another device
 		 *  causes the voltage to change */
--- linux-ec2-2.6.32.orig/drivers/hwmon/coretemp.c
+++ linux-ec2-2.6.32/drivers/hwmon/coretemp.c
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
+#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -52,6 +53,7 @@
 	struct mutex update_lock;
 	const char *name;
 	u32 id;
+	u16 core_id;
 	char valid;		/* zero until following fields are valid */
 	unsigned long last_updated;	/* in jiffies */
 	int temp;
@@ -74,7 +76,7 @@
 	if (attr->index == SHOW_NAME)
 		ret = sprintf(buf, "%s\n", data->name);
 	else	/* show label */
-		ret = sprintf(buf, "Core %d\n", data->id);
+		ret = sprintf(buf, "Core %d\n", data->core_id);
 	return ret;
 }
 
@@ -161,6 +163,7 @@
 	int usemsr_ee = 1;
 	int err;
 	u32 eax, edx;
+	struct pci_dev *host_bridge;
 
 	/* Early chips have no MSR for TjMax */
 
@@ -168,11 +171,21 @@
 		usemsr_ee = 0;
 	}
 
-	/* Atoms seems to have TjMax at 90C */
+	/* Atom CPUs */
 
 	if (c->x86_model == 0x1c) {
 		usemsr_ee = 0;
-		tjmax = 90000;
+
+		host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+
+		if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
+		    && (host_bridge->device == 0xa000	/* NM10 based nettop */
+		    || host_bridge->device == 0xa010))	/* NM10 based netbook */
+			tjmax = 100000;
+		else
+			tjmax = 90000;
+
+		pci_dev_put(host_bridge);
 	}
 
 	if ((c->x86_model > 0xe) && (usemsr_ee)) {
@@ -216,7 +229,7 @@
 		if (err) {
 			dev_warn(dev,
 				 "Unable to access MSR 0xEE, for Tjmax, left"
-				 " at default");
+				 " at default\n");
 		} else if (eax & 0x40000000) {
 			tjmax = tjmax_ee;
 		}
@@ -243,6 +256,9 @@
 	}
 
 	data->id = pdev->id;
+#ifdef CONFIG_SMP
+	data->core_id = c->cpu_core_id;
+#endif
 	data->name = "coretemp";
 	mutex_init(&data->update_lock);
 
@@ -340,6 +356,10 @@
 	struct list_head list;
 	struct platform_device *pdev;
 	unsigned int cpu;
+#ifdef CONFIG_SMP
+	u16 phys_proc_id;
+	u16 cpu_core_id;
+#endif
 };
 
 static LIST_HEAD(pdev_list);
@@ -350,6 +370,22 @@
 	int err;
 	struct platform_device *pdev;
 	struct pdev_entry *pdev_entry;
+#ifdef CONFIG_SMP
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+#endif
+
+	mutex_lock(&pdev_list_mutex);
+
+#ifdef CONFIG_SMP
+	/* Skip second HT entry of each core */
+	list_for_each_entry(pdev_entry, &pdev_list, list) {
+		if (c->phys_proc_id == pdev_entry->phys_proc_id &&
+		    c->cpu_core_id == pdev_entry->cpu_core_id) {
+			err = 0;	/* Not an error */
+			goto exit;
+		}
+	}
+#endif
 
 	pdev = platform_device_alloc(DRVNAME, cpu);
 	if (!pdev) {
@@ -373,7 +409,10 @@
 
 	pdev_entry->pdev = pdev;
 	pdev_entry->cpu = cpu;
-	mutex_lock(&pdev_list_mutex);
+#ifdef CONFIG_SMP
+	pdev_entry->phys_proc_id = c->phys_proc_id;
+	pdev_entry->cpu_core_id = c->cpu_core_id;
+#endif
 	list_add_tail(&pdev_entry->list, &pdev_list);
 	mutex_unlock(&pdev_list_mutex);
 
@@ -384,6 +423,7 @@
 exit_device_put:
 	platform_device_put(pdev);
 exit:
+	mutex_unlock(&pdev_list_mutex);
 	return err;
 }
 
--- linux-ec2-2.6.32.orig/drivers/hwmon/w83781d.c
+++ linux-ec2-2.6.32/drivers/hwmon/w83781d.c
@@ -1818,17 +1818,17 @@
 w83781d_isa_found(unsigned short address)
 {
 	int val, save, found = 0;
+	int port;
 
-	/* We have to request the region in two parts because some
-	   boards declare base+4 to base+7 as a PNP device */
-	if (!request_region(address, 4, "w83781d")) {
-		pr_debug("w83781d: Failed to request low part of region\n");
-		return 0;
-	}
-	if (!request_region(address + 4, 4, "w83781d")) {
-		pr_debug("w83781d: Failed to request high part of region\n");
-		release_region(address, 4);
-		return 0;
+	/* Some boards declare base+0 to base+7 as a PNP device, some base+4
+	 * to base+7 and some base+5 to base+6. So we better request each port
+	 * individually for the probing phase. */
+	for (port = address; port < address + W83781D_EXTENT; port++) {
+		if (!request_region(port, 1, "w83781d")) {
+			pr_debug("w83781d: Failed to request port 0x%x\n",
+				 port);
+			goto release;
+		}
 	}
 
 #define REALLY_SLOW_IO
@@ -1902,8 +1902,8 @@
 			val == 0x30 ? "W83782D" : "W83781D", (int)address);
 
  release:
-	release_region(address + 4, 4);
-	release_region(address, 4);
+	for (port--; port >= address; port--)
+		release_region(port, 1);
 	return found;
 }
 
--- linux-ec2-2.6.32.orig/drivers/hwmon/f71882fg.c
+++ linux-ec2-2.6.32/drivers/hwmon/f71882fg.c
@@ -1957,7 +1957,6 @@
 	int i;
 	struct f71882fg_data *data = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
 	if (data->hwmon_dev)
 		hwmon_device_unregister(data->hwmon_dev);
 
@@ -1982,6 +1981,7 @@
 	for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++)
 		device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr);
 
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/hwmon/it87.c
+++ linux-ec2-2.6.32/drivers/hwmon/it87.c
@@ -80,6 +80,13 @@
 	return inb(VAL);
 }
 
+static inline void
+superio_outb(int reg, int val)
+{
+	outb(reg, REG);
+	outb(val, VAL);
+}
+
 static int superio_inw(int reg)
 {
 	int val;
@@ -1036,6 +1043,21 @@
 			sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
 
 		reg = superio_inb(IT87_SIO_PINX2_REG);
+		/*
+		 * The IT8720F has no VIN7 pin, so VCCH should always be
+		 * routed internally to VIN7 with an internal divider.
+		 * Curiously, there still is a configuration bit to control
+		 * this, which means it can be set incorrectly. And even
+		 * more curiously, many boards out there are improperly
+		 * configured, even though the IT8720F datasheet claims
+		 * that the internal routing of VCCH to VIN7 is the default
+		 * setting. So we force the internal routing in this case.
+		 */
+		if (sio_data->type == it8720 && !(reg & (1 << 1))) {
+			reg |= (1 << 1);
+			superio_outb(IT87_SIO_PINX2_REG, reg);
+			pr_notice("it87: Routing internal VCCH to in7\n");
+		}
 		if (reg & (1 << 0))
 			pr_info("it87: in3 is VCC (+5V)\n");
 		if (reg & (1 << 1))
--- linux-ec2-2.6.32.orig/drivers/hwmon/tmp421.c
+++ linux-ec2-2.6.32/drivers/hwmon/tmp421.c
@@ -62,9 +62,9 @@
 #define TMP423_DEVICE_ID			0x23
 
 static const struct i2c_device_id tmp421_id[] = {
-	{ "tmp421", tmp421 },
-	{ "tmp422", tmp422 },
-	{ "tmp423", tmp423 },
+	{ "tmp421", 2 },
+	{ "tmp422", 3 },
+	{ "tmp423", 4 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tmp421_id);
@@ -74,21 +74,23 @@
 	struct mutex update_lock;
 	char valid;
 	unsigned long last_updated;
-	int kind;
+	int channels;
 	u8 config;
 	s16 temp[4];
 };
 
 static int temp_from_s16(s16 reg)
 {
-	int temp = reg;
+	/* Mask out status bits */
+	int temp = reg & ~0xf;
 
 	return (temp * 1000 + 128) / 256;
 }
 
 static int temp_from_u16(u16 reg)
 {
-	int temp = reg;
+	/* Mask out status bits */
+	int temp = reg & ~0xf;
 
 	/* Add offset for extended temperature range. */
 	temp -= 64 * 256;
@@ -108,7 +110,7 @@
 		data->config = i2c_smbus_read_byte_data(client,
 			TMP421_CONFIG_REG_1);
 
-		for (i = 0; i <= data->kind; i++) {
+		for (i = 0; i < data->channels; i++) {
 			data->temp[i] = i2c_smbus_read_byte_data(client,
 				TMP421_TEMP_MSB[i]) << 8;
 			data->temp[i] |= i2c_smbus_read_byte_data(client,
@@ -167,7 +169,7 @@
 	devattr = container_of(a, struct device_attribute, attr);
 	index = to_sensor_dev_attr(devattr)->index;
 
-	if (data->kind > index)
+	if (index < data->channels)
 		return a->mode;
 
 	return 0;
@@ -275,7 +277,7 @@
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
-	data->kind = id->driver_data;
+	data->channels = id->driver_data;
 
 	err = tmp421_init_client(client);
 	if (err)
--- linux-ec2-2.6.32.orig/drivers/hwmon/hp_accel.c
+++ linux-ec2-2.6.32/drivers/hwmon/hp_accel.c
@@ -324,8 +324,8 @@
 	lis3lv02d_joystick_disable();
 	lis3lv02d_poweroff(&lis3_dev);
 
-	flush_work(&hpled_led.work);
 	led_classdev_unregister(&hpled_led.led_classdev);
+	flush_work(&hpled_led.work);
 
 	return lis3lv02d_remove_fs(&lis3_dev);
 }
--- linux-ec2-2.6.32.orig/drivers/hwmon/ams/ams.h
+++ linux-ec2-2.6.32/drivers/hwmon/ams/ams.h
@@ -61,6 +61,7 @@
 
 extern void ams_sensors(s8 *x, s8 *y, s8 *z);
 extern int ams_sensor_attach(void);
+extern void ams_sensor_detach(void);
 
 extern int ams_pmu_init(struct device_node *np);
 extern int ams_i2c_init(struct device_node *np);
--- linux-ec2-2.6.32.orig/drivers/hwmon/ams/ams-i2c.c
+++ linux-ec2-2.6.32/drivers/hwmon/ams/ams-i2c.c
@@ -238,6 +238,8 @@
 static int ams_i2c_remove(struct i2c_client *client)
 {
 	if (ams_info.has_device) {
+		ams_sensor_detach();
+
 		/* Disable interrupts */
 		ams_i2c_set_irq(AMS_IRQ_ALL, 0);
 
--- linux-ec2-2.6.32.orig/drivers/hwmon/ams/ams-pmu.c
+++ linux-ec2-2.6.32/drivers/hwmon/ams/ams-pmu.c
@@ -133,6 +133,8 @@
 
 static void ams_pmu_exit(void)
 {
+	ams_sensor_detach();
+
 	/* Disable interrupts */
 	ams_pmu_set_irq(AMS_IRQ_ALL, 0);
 
--- linux-ec2-2.6.32.orig/drivers/hwmon/ams/ams-core.c
+++ linux-ec2-2.6.32/drivers/hwmon/ams/ams-core.c
@@ -213,7 +213,7 @@
 	return -ENODEV;
 }
 
-void ams_exit(void)
+void ams_sensor_detach(void)
 {
 	/* Remove input device */
 	ams_input_exit();
@@ -221,9 +221,6 @@
 	/* Remove attributes */
 	device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
 
-	/* Shut down implementation */
-	ams_info.exit();
-
 	/* Flush interrupt worker
 	 *
 	 * We do this after ams_info.exit(), because an interrupt might
@@ -239,6 +236,12 @@
 	pmf_unregister_irq_client(&ams_freefall_client);
 }
 
+static void __exit ams_exit(void)
+{
+	/* Shut down implementation */
+	ams_info.exit();
+}
+
 MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple Motion Sensor driver");
 MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/usb/atm/ueagle-atm.c
+++ linux-ec2-2.6.32/drivers/usb/atm/ueagle-atm.c
@@ -2259,7 +2259,7 @@
 	return ret;
 }
 
-static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+static DEVICE_ATTR(stat_status, S_IWUSR | S_IRUGO, read_status, reboot);
 
 static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -2322,7 +2322,7 @@
 	return ret;
 }
 
-static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
+static DEVICE_ATTR(stat_human_status, S_IRUGO, read_human_status, NULL);
 
 static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -2354,7 +2354,7 @@
 	return ret;
 }
 
-static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+static DEVICE_ATTR(stat_delin, S_IRUGO, read_delin, NULL);
 
 #define UEA_ATTR(name, reset) 					\
 								\
--- linux-ec2-2.6.32.orig/drivers/usb/serial/keyspan_pda.c
+++ linux-ec2-2.6.32/drivers/usb/serial/keyspan_pda.c
@@ -663,22 +663,6 @@
 	}
 }
 
-static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-	unsigned char modembits;
-
-	/* If we can read the modem status and the DCD is low then
-	   carrier is not raised yet */
-	if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
-		if (!(modembits & (1>>6)))
-			return 0;
-	}
-	/* Carrier raised, or we failed (eg disconnected) so
-	   progress accordingly */
-	return 1;
-}
-
 
 static int keyspan_pda_open(struct tty_struct *tty,
 					struct usb_serial_port *port)
@@ -854,7 +838,6 @@
 	.id_table =		id_table_std,
 	.num_ports =		1,
 	.dtr_rts =		keyspan_pda_dtr_rts,
-	.carrier_raised	=	keyspan_pda_carrier_raised,
 	.open =			keyspan_pda_open,
 	.close =		keyspan_pda_close,
 	.write =		keyspan_pda_write,
--- linux-ec2-2.6.32.orig/drivers/usb/serial/qcserial.c
+++ linux-ec2-2.6.32/drivers/usb/serial/qcserial.c
@@ -47,6 +47,35 @@
 	{USB_DEVICE(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
 	{USB_DEVICE(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
 	{USB_DEVICE(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
+	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
+	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
+	{USB_DEVICE(0x05c6, 0x9224)},	/* Sony Gobi 2000 QDL device (N0279, VU730) */
+	{USB_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */
+	{USB_DEVICE(0x05c6, 0x9244)},	/* Samsung Gobi 2000 QDL device (VL176) */
+	{USB_DEVICE(0x05c6, 0x9245)},	/* Samsung Gobi 2000 Modem device (VL176) */
+	{USB_DEVICE(0x03f0, 0x241d)},	/* HP Gobi 2000 QDL device (VP412) */
+	{USB_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */
+	{USB_DEVICE(0x05c6, 0x9214)},	/* Acer Gobi 2000 QDL device (VP413) */
+	{USB_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */
+	{USB_DEVICE(0x05c6, 0x9264)},	/* Asus Gobi 2000 QDL device (VR305) */
+	{USB_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */
+	{USB_DEVICE(0x05c6, 0x9234)},	/* Top Global Gobi 2000 QDL device (VR306) */
+	{USB_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */
+	{USB_DEVICE(0x05c6, 0x9274)},	/* iRex Technologies Gobi 2000 QDL device (VR307) */
+	{USB_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */
+	{USB_DEVICE(0x1199, 0x9000)},	/* Sierra Wireless Gobi 2000 QDL device (VT773) */
+	{USB_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9004)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9005)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9006)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9007)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9008)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
+	{USB_DEVICE(0x16d8, 0x8001)},	/* CMDTech Gobi 2000 QDL device (VU922) */
+	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */
 	{ }				/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
--- linux-ec2-2.6.32.orig/drivers/usb/serial/kl5kusb105.c
+++ linux-ec2-2.6.32/drivers/usb/serial/kl5kusb105.c
@@ -310,6 +310,7 @@
 				usb_free_urb(priv->write_urb_pool[j]);
 			}
 		}
+		kfree(priv);
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
 	return -ENOMEM;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/spcp8x5.c
+++ linux-ec2-2.6.32/drivers/usb/serial/spcp8x5.c
@@ -137,7 +137,7 @@
 
 /* how come ??? */
 #define UART_STATE			0x08
-#define UART_STATE_TRANSIENT_MASK	0x74
+#define UART_STATE_TRANSIENT_MASK	0x75
 #define UART_DCD			0x01
 #define UART_DSR			0x02
 #define UART_BREAK_ERROR		0x04
@@ -734,6 +734,10 @@
 			tty_insert_flip_char(tty, data[i], tty_flag);
 		tty_flip_buffer_push(tty);
 	}
+
+	if (status & UART_DCD)
+		usb_serial_handle_dcd_change(port, tty,
+			   priv->line_status & MSR_STATUS_LINE_DCD);
 	tty_kref_put(tty);
 
 	/* Schedule the next read _if_ we are still open */
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ftdi_sio.h
+++ linux-ec2-2.6.32/drivers/usb/serial/ftdi_sio.h
@@ -1,7 +1,10 @@
 /*
- * Definitions for the FTDI USB Single Port Serial Converter -
+ * Driver definitions for the FTDI USB Single Port Serial Converter -
  * known as FTDI_SIO (Serial Input/Output application of the chipset)
  *
+ * For USB vendor/product IDs (VID/PID), please see ftdi_sio_ids.h
+ *
+ *
  * The example I have is known as the USC-1000 which is available from
  * http://www.dse.co.nz - cat no XH4214 It looks similar to this:
  * http://www.dansdata.com/usbser.htm but I can't be sure There are other
@@ -17,866 +20,7 @@
  * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
  * FTDI_SIO implementation.
  *
- * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
- * from Rudolf Gugler
- *
- */
-
-#define FTDI_VID	0x0403	/* Vendor Id */
-#define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
-#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
-#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
-#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
-#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
-#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
-#define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
-#define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
-#define FTDI_NF_RIC_PID	0x0001	/* Product Id */
-#define FTDI_USBX_707_PID 0xF857	/* ADSTech IR Blaster USBX-707 */
-
-/* Larsen and Brusgaard AltiTrack/USBtrack  */
-#define LARSENBRUSGAARD_VID		0x0FD8
-#define LB_ALTITRACK_PID		0x0001
-
-/* www.canusb.com Lawicel CANUSB device */
-#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
-
-/* AlphaMicro Components AMC-232USB01 device */
-#define FTDI_AMC232_PID 0xFF00 /* Product Id */
-
-/* www.candapter.com Ewert Energy Systems CANdapter device */
-#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
-
-/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
-/* the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
-#define FTDI_SCS_DEVICE_1_PID 0xD011    /* SCS Tracker / DSP TNC */
-#define FTDI_SCS_DEVICE_2_PID 0xD012
-#define FTDI_SCS_DEVICE_3_PID 0xD013
-#define FTDI_SCS_DEVICE_4_PID 0xD014
-#define FTDI_SCS_DEVICE_5_PID 0xD015
-#define FTDI_SCS_DEVICE_6_PID 0xD016
-#define FTDI_SCS_DEVICE_7_PID 0xD017
-
-/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
-#define FTDI_ACTZWAVE_PID	0xF2D0
-
-
-/* www.starting-point-systems.com µChameleon device */
-#define FTDI_MICRO_CHAMELEON_PID	0xCAA0	/* Product Id */
-
-/* www.irtrans.de device */
-#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
-
-
-/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
-#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
-
-/* iPlus device */
-#define FTDI_IPLUS_PID 0xD070 /* Product Id */
-#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
-
-/* DMX4ALL DMX Interfaces */
-#define FTDI_DMX4ALL 0xC850
-
-/* OpenDCC (www.opendcc.de) product id */
-#define FTDI_OPENDCC_PID	0xBFD8
-#define FTDI_OPENDCC_SNIFFER_PID	0xBFD9
-#define FTDI_OPENDCC_THROTTLE_PID	0xBFDA
-#define FTDI_OPENDCC_GATEWAY_PID	0xBFDB
-
-/* Sprog II (Andrew Crosland's SprogII DCC interface) */
-#define FTDI_SPROG_II		0xF0C8
-
-/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
-/* they use the ftdi chipset for the USB interface and the vendor id is the same */
-#define FTDI_XF_632_PID 0xFC08	/* 632: 16x2 Character Display */
-#define FTDI_XF_634_PID 0xFC09	/* 634: 20x4 Character Display */
-#define FTDI_XF_547_PID 0xFC0A	/* 547: Two line Display */
-#define FTDI_XF_633_PID 0xFC0B	/* 633: 16x2 Character Display with Keys */
-#define FTDI_XF_631_PID 0xFC0C	/* 631: 20x2 Character Display */
-#define FTDI_XF_635_PID 0xFC0D	/* 635: 20x4 Character Display */
-#define FTDI_XF_640_PID 0xFC0E	/* 640: Two line Display */
-#define FTDI_XF_642_PID 0xFC0F	/* 642: Two line Display */
-
-/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */
-/* broadband internet service.  The following PID is exhibited by the usb device supplied */
-/* (the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
-
-/*
- * PCDJ use ftdi based dj-controllers.  The following PID is for their DAC-2 device
- * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen)
- * (the VID is the standard ftdi vid (FTDI_VID) */
-#define FTDI_PCDJ_DAC2_PID 0xFA88
-
-/*
- * The following are the values for the Matrix Orbital LCD displays,
- * which are the FT232BM ( similar to the 8U232AM )
- */
-#define FTDI_MTXORB_0_PID      0xFA00  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_1_PID      0xFA01  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_2_PID      0xFA02  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_3_PID      0xFA03  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_4_PID      0xFA04  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
-#define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
-
-/* OOCDlink by Joern Kaipf <joernk@web.de>
- * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
-#define FTDI_OOCDLINK_PID	0xbaf8	/* Amontec JTAGkey */
-
-/*
- * The following are the values for the Matrix Orbital FTDI Range
- * Anything in this range will use an FT232RL.
- */
-#define MTXORB_VID			0x1B3D
-#define MTXORB_FTDI_RANGE_0100_PID	0x0100
-#define MTXORB_FTDI_RANGE_0101_PID	0x0101
-#define MTXORB_FTDI_RANGE_0102_PID	0x0102
-#define MTXORB_FTDI_RANGE_0103_PID	0x0103
-#define MTXORB_FTDI_RANGE_0104_PID	0x0104
-#define MTXORB_FTDI_RANGE_0105_PID	0x0105
-#define MTXORB_FTDI_RANGE_0106_PID	0x0106
-#define MTXORB_FTDI_RANGE_0107_PID	0x0107
-#define MTXORB_FTDI_RANGE_0108_PID	0x0108
-#define MTXORB_FTDI_RANGE_0109_PID	0x0109
-#define MTXORB_FTDI_RANGE_010A_PID	0x010A
-#define MTXORB_FTDI_RANGE_010B_PID	0x010B
-#define MTXORB_FTDI_RANGE_010C_PID	0x010C
-#define MTXORB_FTDI_RANGE_010D_PID	0x010D
-#define MTXORB_FTDI_RANGE_010E_PID	0x010E
-#define MTXORB_FTDI_RANGE_010F_PID	0x010F
-#define MTXORB_FTDI_RANGE_0110_PID	0x0110
-#define MTXORB_FTDI_RANGE_0111_PID	0x0111
-#define MTXORB_FTDI_RANGE_0112_PID	0x0112
-#define MTXORB_FTDI_RANGE_0113_PID	0x0113
-#define MTXORB_FTDI_RANGE_0114_PID	0x0114
-#define MTXORB_FTDI_RANGE_0115_PID	0x0115
-#define MTXORB_FTDI_RANGE_0116_PID	0x0116
-#define MTXORB_FTDI_RANGE_0117_PID	0x0117
-#define MTXORB_FTDI_RANGE_0118_PID	0x0118
-#define MTXORB_FTDI_RANGE_0119_PID	0x0119
-#define MTXORB_FTDI_RANGE_011A_PID	0x011A
-#define MTXORB_FTDI_RANGE_011B_PID	0x011B
-#define MTXORB_FTDI_RANGE_011C_PID	0x011C
-#define MTXORB_FTDI_RANGE_011D_PID	0x011D
-#define MTXORB_FTDI_RANGE_011E_PID	0x011E
-#define MTXORB_FTDI_RANGE_011F_PID	0x011F
-#define MTXORB_FTDI_RANGE_0120_PID	0x0120
-#define MTXORB_FTDI_RANGE_0121_PID	0x0121
-#define MTXORB_FTDI_RANGE_0122_PID	0x0122
-#define MTXORB_FTDI_RANGE_0123_PID	0x0123
-#define MTXORB_FTDI_RANGE_0124_PID	0x0124
-#define MTXORB_FTDI_RANGE_0125_PID	0x0125
-#define MTXORB_FTDI_RANGE_0126_PID	0x0126
-#define MTXORB_FTDI_RANGE_0127_PID	0x0127
-#define MTXORB_FTDI_RANGE_0128_PID	0x0128
-#define MTXORB_FTDI_RANGE_0129_PID	0x0129
-#define MTXORB_FTDI_RANGE_012A_PID	0x012A
-#define MTXORB_FTDI_RANGE_012B_PID	0x012B
-#define MTXORB_FTDI_RANGE_012C_PID	0x012C
-#define MTXORB_FTDI_RANGE_012D_PID	0x012D
-#define MTXORB_FTDI_RANGE_012E_PID	0x012E
-#define MTXORB_FTDI_RANGE_012F_PID	0x012F
-#define MTXORB_FTDI_RANGE_0130_PID	0x0130
-#define MTXORB_FTDI_RANGE_0131_PID	0x0131
-#define MTXORB_FTDI_RANGE_0132_PID	0x0132
-#define MTXORB_FTDI_RANGE_0133_PID	0x0133
-#define MTXORB_FTDI_RANGE_0134_PID	0x0134
-#define MTXORB_FTDI_RANGE_0135_PID	0x0135
-#define MTXORB_FTDI_RANGE_0136_PID	0x0136
-#define MTXORB_FTDI_RANGE_0137_PID	0x0137
-#define MTXORB_FTDI_RANGE_0138_PID	0x0138
-#define MTXORB_FTDI_RANGE_0139_PID	0x0139
-#define MTXORB_FTDI_RANGE_013A_PID	0x013A
-#define MTXORB_FTDI_RANGE_013B_PID	0x013B
-#define MTXORB_FTDI_RANGE_013C_PID	0x013C
-#define MTXORB_FTDI_RANGE_013D_PID	0x013D
-#define MTXORB_FTDI_RANGE_013E_PID	0x013E
-#define MTXORB_FTDI_RANGE_013F_PID	0x013F
-#define MTXORB_FTDI_RANGE_0140_PID	0x0140
-#define MTXORB_FTDI_RANGE_0141_PID	0x0141
-#define MTXORB_FTDI_RANGE_0142_PID	0x0142
-#define MTXORB_FTDI_RANGE_0143_PID	0x0143
-#define MTXORB_FTDI_RANGE_0144_PID	0x0144
-#define MTXORB_FTDI_RANGE_0145_PID	0x0145
-#define MTXORB_FTDI_RANGE_0146_PID	0x0146
-#define MTXORB_FTDI_RANGE_0147_PID	0x0147
-#define MTXORB_FTDI_RANGE_0148_PID	0x0148
-#define MTXORB_FTDI_RANGE_0149_PID	0x0149
-#define MTXORB_FTDI_RANGE_014A_PID	0x014A
-#define MTXORB_FTDI_RANGE_014B_PID	0x014B
-#define MTXORB_FTDI_RANGE_014C_PID	0x014C
-#define MTXORB_FTDI_RANGE_014D_PID	0x014D
-#define MTXORB_FTDI_RANGE_014E_PID	0x014E
-#define MTXORB_FTDI_RANGE_014F_PID	0x014F
-#define MTXORB_FTDI_RANGE_0150_PID	0x0150
-#define MTXORB_FTDI_RANGE_0151_PID	0x0151
-#define MTXORB_FTDI_RANGE_0152_PID	0x0152
-#define MTXORB_FTDI_RANGE_0153_PID	0x0153
-#define MTXORB_FTDI_RANGE_0154_PID	0x0154
-#define MTXORB_FTDI_RANGE_0155_PID	0x0155
-#define MTXORB_FTDI_RANGE_0156_PID	0x0156
-#define MTXORB_FTDI_RANGE_0157_PID	0x0157
-#define MTXORB_FTDI_RANGE_0158_PID	0x0158
-#define MTXORB_FTDI_RANGE_0159_PID	0x0159
-#define MTXORB_FTDI_RANGE_015A_PID	0x015A
-#define MTXORB_FTDI_RANGE_015B_PID	0x015B
-#define MTXORB_FTDI_RANGE_015C_PID	0x015C
-#define MTXORB_FTDI_RANGE_015D_PID	0x015D
-#define MTXORB_FTDI_RANGE_015E_PID	0x015E
-#define MTXORB_FTDI_RANGE_015F_PID	0x015F
-#define MTXORB_FTDI_RANGE_0160_PID	0x0160
-#define MTXORB_FTDI_RANGE_0161_PID	0x0161
-#define MTXORB_FTDI_RANGE_0162_PID	0x0162
-#define MTXORB_FTDI_RANGE_0163_PID	0x0163
-#define MTXORB_FTDI_RANGE_0164_PID	0x0164
-#define MTXORB_FTDI_RANGE_0165_PID	0x0165
-#define MTXORB_FTDI_RANGE_0166_PID	0x0166
-#define MTXORB_FTDI_RANGE_0167_PID	0x0167
-#define MTXORB_FTDI_RANGE_0168_PID	0x0168
-#define MTXORB_FTDI_RANGE_0169_PID	0x0169
-#define MTXORB_FTDI_RANGE_016A_PID	0x016A
-#define MTXORB_FTDI_RANGE_016B_PID	0x016B
-#define MTXORB_FTDI_RANGE_016C_PID	0x016C
-#define MTXORB_FTDI_RANGE_016D_PID	0x016D
-#define MTXORB_FTDI_RANGE_016E_PID	0x016E
-#define MTXORB_FTDI_RANGE_016F_PID	0x016F
-#define MTXORB_FTDI_RANGE_0170_PID	0x0170
-#define MTXORB_FTDI_RANGE_0171_PID	0x0171
-#define MTXORB_FTDI_RANGE_0172_PID	0x0172
-#define MTXORB_FTDI_RANGE_0173_PID	0x0173
-#define MTXORB_FTDI_RANGE_0174_PID	0x0174
-#define MTXORB_FTDI_RANGE_0175_PID	0x0175
-#define MTXORB_FTDI_RANGE_0176_PID	0x0176
-#define MTXORB_FTDI_RANGE_0177_PID	0x0177
-#define MTXORB_FTDI_RANGE_0178_PID	0x0178
-#define MTXORB_FTDI_RANGE_0179_PID	0x0179
-#define MTXORB_FTDI_RANGE_017A_PID	0x017A
-#define MTXORB_FTDI_RANGE_017B_PID	0x017B
-#define MTXORB_FTDI_RANGE_017C_PID	0x017C
-#define MTXORB_FTDI_RANGE_017D_PID	0x017D
-#define MTXORB_FTDI_RANGE_017E_PID	0x017E
-#define MTXORB_FTDI_RANGE_017F_PID	0x017F
-#define MTXORB_FTDI_RANGE_0180_PID	0x0180
-#define MTXORB_FTDI_RANGE_0181_PID	0x0181
-#define MTXORB_FTDI_RANGE_0182_PID	0x0182
-#define MTXORB_FTDI_RANGE_0183_PID	0x0183
-#define MTXORB_FTDI_RANGE_0184_PID	0x0184
-#define MTXORB_FTDI_RANGE_0185_PID	0x0185
-#define MTXORB_FTDI_RANGE_0186_PID	0x0186
-#define MTXORB_FTDI_RANGE_0187_PID	0x0187
-#define MTXORB_FTDI_RANGE_0188_PID	0x0188
-#define MTXORB_FTDI_RANGE_0189_PID	0x0189
-#define MTXORB_FTDI_RANGE_018A_PID	0x018A
-#define MTXORB_FTDI_RANGE_018B_PID	0x018B
-#define MTXORB_FTDI_RANGE_018C_PID	0x018C
-#define MTXORB_FTDI_RANGE_018D_PID	0x018D
-#define MTXORB_FTDI_RANGE_018E_PID	0x018E
-#define MTXORB_FTDI_RANGE_018F_PID	0x018F
-#define MTXORB_FTDI_RANGE_0190_PID	0x0190
-#define MTXORB_FTDI_RANGE_0191_PID	0x0191
-#define MTXORB_FTDI_RANGE_0192_PID	0x0192
-#define MTXORB_FTDI_RANGE_0193_PID	0x0193
-#define MTXORB_FTDI_RANGE_0194_PID	0x0194
-#define MTXORB_FTDI_RANGE_0195_PID	0x0195
-#define MTXORB_FTDI_RANGE_0196_PID	0x0196
-#define MTXORB_FTDI_RANGE_0197_PID	0x0197
-#define MTXORB_FTDI_RANGE_0198_PID	0x0198
-#define MTXORB_FTDI_RANGE_0199_PID	0x0199
-#define MTXORB_FTDI_RANGE_019A_PID	0x019A
-#define MTXORB_FTDI_RANGE_019B_PID	0x019B
-#define MTXORB_FTDI_RANGE_019C_PID	0x019C
-#define MTXORB_FTDI_RANGE_019D_PID	0x019D
-#define MTXORB_FTDI_RANGE_019E_PID	0x019E
-#define MTXORB_FTDI_RANGE_019F_PID	0x019F
-#define MTXORB_FTDI_RANGE_01A0_PID	0x01A0
-#define MTXORB_FTDI_RANGE_01A1_PID	0x01A1
-#define MTXORB_FTDI_RANGE_01A2_PID	0x01A2
-#define MTXORB_FTDI_RANGE_01A3_PID	0x01A3
-#define MTXORB_FTDI_RANGE_01A4_PID	0x01A4
-#define MTXORB_FTDI_RANGE_01A5_PID	0x01A5
-#define MTXORB_FTDI_RANGE_01A6_PID	0x01A6
-#define MTXORB_FTDI_RANGE_01A7_PID	0x01A7
-#define MTXORB_FTDI_RANGE_01A8_PID	0x01A8
-#define MTXORB_FTDI_RANGE_01A9_PID	0x01A9
-#define MTXORB_FTDI_RANGE_01AA_PID	0x01AA
-#define MTXORB_FTDI_RANGE_01AB_PID	0x01AB
-#define MTXORB_FTDI_RANGE_01AC_PID	0x01AC
-#define MTXORB_FTDI_RANGE_01AD_PID	0x01AD
-#define MTXORB_FTDI_RANGE_01AE_PID	0x01AE
-#define MTXORB_FTDI_RANGE_01AF_PID	0x01AF
-#define MTXORB_FTDI_RANGE_01B0_PID	0x01B0
-#define MTXORB_FTDI_RANGE_01B1_PID	0x01B1
-#define MTXORB_FTDI_RANGE_01B2_PID	0x01B2
-#define MTXORB_FTDI_RANGE_01B3_PID	0x01B3
-#define MTXORB_FTDI_RANGE_01B4_PID	0x01B4
-#define MTXORB_FTDI_RANGE_01B5_PID	0x01B5
-#define MTXORB_FTDI_RANGE_01B6_PID	0x01B6
-#define MTXORB_FTDI_RANGE_01B7_PID	0x01B7
-#define MTXORB_FTDI_RANGE_01B8_PID	0x01B8
-#define MTXORB_FTDI_RANGE_01B9_PID	0x01B9
-#define MTXORB_FTDI_RANGE_01BA_PID	0x01BA
-#define MTXORB_FTDI_RANGE_01BB_PID	0x01BB
-#define MTXORB_FTDI_RANGE_01BC_PID	0x01BC
-#define MTXORB_FTDI_RANGE_01BD_PID	0x01BD
-#define MTXORB_FTDI_RANGE_01BE_PID	0x01BE
-#define MTXORB_FTDI_RANGE_01BF_PID	0x01BF
-#define MTXORB_FTDI_RANGE_01C0_PID	0x01C0
-#define MTXORB_FTDI_RANGE_01C1_PID	0x01C1
-#define MTXORB_FTDI_RANGE_01C2_PID	0x01C2
-#define MTXORB_FTDI_RANGE_01C3_PID	0x01C3
-#define MTXORB_FTDI_RANGE_01C4_PID	0x01C4
-#define MTXORB_FTDI_RANGE_01C5_PID	0x01C5
-#define MTXORB_FTDI_RANGE_01C6_PID	0x01C6
-#define MTXORB_FTDI_RANGE_01C7_PID	0x01C7
-#define MTXORB_FTDI_RANGE_01C8_PID	0x01C8
-#define MTXORB_FTDI_RANGE_01C9_PID	0x01C9
-#define MTXORB_FTDI_RANGE_01CA_PID	0x01CA
-#define MTXORB_FTDI_RANGE_01CB_PID	0x01CB
-#define MTXORB_FTDI_RANGE_01CC_PID	0x01CC
-#define MTXORB_FTDI_RANGE_01CD_PID	0x01CD
-#define MTXORB_FTDI_RANGE_01CE_PID	0x01CE
-#define MTXORB_FTDI_RANGE_01CF_PID	0x01CF
-#define MTXORB_FTDI_RANGE_01D0_PID	0x01D0
-#define MTXORB_FTDI_RANGE_01D1_PID	0x01D1
-#define MTXORB_FTDI_RANGE_01D2_PID	0x01D2
-#define MTXORB_FTDI_RANGE_01D3_PID	0x01D3
-#define MTXORB_FTDI_RANGE_01D4_PID	0x01D4
-#define MTXORB_FTDI_RANGE_01D5_PID	0x01D5
-#define MTXORB_FTDI_RANGE_01D6_PID	0x01D6
-#define MTXORB_FTDI_RANGE_01D7_PID	0x01D7
-#define MTXORB_FTDI_RANGE_01D8_PID	0x01D8
-#define MTXORB_FTDI_RANGE_01D9_PID	0x01D9
-#define MTXORB_FTDI_RANGE_01DA_PID	0x01DA
-#define MTXORB_FTDI_RANGE_01DB_PID	0x01DB
-#define MTXORB_FTDI_RANGE_01DC_PID	0x01DC
-#define MTXORB_FTDI_RANGE_01DD_PID	0x01DD
-#define MTXORB_FTDI_RANGE_01DE_PID	0x01DE
-#define MTXORB_FTDI_RANGE_01DF_PID	0x01DF
-#define MTXORB_FTDI_RANGE_01E0_PID	0x01E0
-#define MTXORB_FTDI_RANGE_01E1_PID	0x01E1
-#define MTXORB_FTDI_RANGE_01E2_PID	0x01E2
-#define MTXORB_FTDI_RANGE_01E3_PID	0x01E3
-#define MTXORB_FTDI_RANGE_01E4_PID	0x01E4
-#define MTXORB_FTDI_RANGE_01E5_PID	0x01E5
-#define MTXORB_FTDI_RANGE_01E6_PID	0x01E6
-#define MTXORB_FTDI_RANGE_01E7_PID	0x01E7
-#define MTXORB_FTDI_RANGE_01E8_PID	0x01E8
-#define MTXORB_FTDI_RANGE_01E9_PID	0x01E9
-#define MTXORB_FTDI_RANGE_01EA_PID	0x01EA
-#define MTXORB_FTDI_RANGE_01EB_PID	0x01EB
-#define MTXORB_FTDI_RANGE_01EC_PID	0x01EC
-#define MTXORB_FTDI_RANGE_01ED_PID	0x01ED
-#define MTXORB_FTDI_RANGE_01EE_PID	0x01EE
-#define MTXORB_FTDI_RANGE_01EF_PID	0x01EF
-#define MTXORB_FTDI_RANGE_01F0_PID	0x01F0
-#define MTXORB_FTDI_RANGE_01F1_PID	0x01F1
-#define MTXORB_FTDI_RANGE_01F2_PID	0x01F2
-#define MTXORB_FTDI_RANGE_01F3_PID	0x01F3
-#define MTXORB_FTDI_RANGE_01F4_PID	0x01F4
-#define MTXORB_FTDI_RANGE_01F5_PID	0x01F5
-#define MTXORB_FTDI_RANGE_01F6_PID	0x01F6
-#define MTXORB_FTDI_RANGE_01F7_PID	0x01F7
-#define MTXORB_FTDI_RANGE_01F8_PID	0x01F8
-#define MTXORB_FTDI_RANGE_01F9_PID	0x01F9
-#define MTXORB_FTDI_RANGE_01FA_PID	0x01FA
-#define MTXORB_FTDI_RANGE_01FB_PID	0x01FB
-#define MTXORB_FTDI_RANGE_01FC_PID	0x01FC
-#define MTXORB_FTDI_RANGE_01FD_PID	0x01FD
-#define MTXORB_FTDI_RANGE_01FE_PID	0x01FE
-#define MTXORB_FTDI_RANGE_01FF_PID	0x01FF
-
-
-
-/* Interbiometrics USB I/O Board */
-/* Developed for Interbiometrics by Rudolf Gugler */
-#define INTERBIOMETRICS_VID              0x1209
-#define INTERBIOMETRICS_IOBOARD_PID      0x1002
-#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006
-
-/*
- * The following are the values for the Perle Systems
- * UltraPort USB serial converters
- */
-#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0	/* Perle UltraPort Product Id */
-
-/*
- * The following are the values for the Sealevel SeaLINK+ adapters.
- * (Original list sent by Tuan Hoang.  Ian Abbott renamed the macros and
- * removed some PIDs that don't seem to match any existing products.)
- */
-#define SEALEVEL_VID		0x0c52	/* Sealevel Vendor ID */
-#define SEALEVEL_2101_PID	0x2101	/* SeaLINK+232 (2101/2105) */
-#define SEALEVEL_2102_PID	0x2102	/* SeaLINK+485 (2102) */
-#define SEALEVEL_2103_PID	0x2103	/* SeaLINK+232I (2103) */
-#define SEALEVEL_2104_PID	0x2104	/* SeaLINK+485I (2104) */
-#define SEALEVEL_2106_PID	0x9020	/* SeaLINK+422 (2106) */
-#define SEALEVEL_2201_1_PID	0x2211	/* SeaPORT+2/232 (2201) Port 1 */
-#define SEALEVEL_2201_2_PID	0x2221	/* SeaPORT+2/232 (2201) Port 2 */
-#define SEALEVEL_2202_1_PID	0x2212	/* SeaPORT+2/485 (2202) Port 1 */
-#define SEALEVEL_2202_2_PID	0x2222	/* SeaPORT+2/485 (2202) Port 2 */
-#define SEALEVEL_2203_1_PID	0x2213	/* SeaPORT+2 (2203) Port 1 */
-#define SEALEVEL_2203_2_PID	0x2223	/* SeaPORT+2 (2203) Port 2 */
-#define SEALEVEL_2401_1_PID	0x2411	/* SeaPORT+4/232 (2401) Port 1 */
-#define SEALEVEL_2401_2_PID	0x2421	/* SeaPORT+4/232 (2401) Port 2 */
-#define SEALEVEL_2401_3_PID	0x2431	/* SeaPORT+4/232 (2401) Port 3 */
-#define SEALEVEL_2401_4_PID	0x2441	/* SeaPORT+4/232 (2401) Port 4 */
-#define SEALEVEL_2402_1_PID	0x2412	/* SeaPORT+4/485 (2402) Port 1 */
-#define SEALEVEL_2402_2_PID	0x2422	/* SeaPORT+4/485 (2402) Port 2 */
-#define SEALEVEL_2402_3_PID	0x2432	/* SeaPORT+4/485 (2402) Port 3 */
-#define SEALEVEL_2402_4_PID	0x2442	/* SeaPORT+4/485 (2402) Port 4 */
-#define SEALEVEL_2403_1_PID	0x2413	/* SeaPORT+4 (2403) Port 1 */
-#define SEALEVEL_2403_2_PID	0x2423	/* SeaPORT+4 (2403) Port 2 */
-#define SEALEVEL_2403_3_PID	0x2433	/* SeaPORT+4 (2403) Port 3 */
-#define SEALEVEL_2403_4_PID	0x2443	/* SeaPORT+4 (2403) Port 4 */
-#define SEALEVEL_2801_1_PID	0X2811	/* SeaLINK+8/232 (2801) Port 1 */
-#define SEALEVEL_2801_2_PID	0X2821	/* SeaLINK+8/232 (2801) Port 2 */
-#define SEALEVEL_2801_3_PID	0X2831	/* SeaLINK+8/232 (2801) Port 3 */
-#define SEALEVEL_2801_4_PID	0X2841	/* SeaLINK+8/232 (2801) Port 4 */
-#define SEALEVEL_2801_5_PID	0X2851	/* SeaLINK+8/232 (2801) Port 5 */
-#define SEALEVEL_2801_6_PID	0X2861	/* SeaLINK+8/232 (2801) Port 6 */
-#define SEALEVEL_2801_7_PID	0X2871	/* SeaLINK+8/232 (2801) Port 7 */
-#define SEALEVEL_2801_8_PID	0X2881	/* SeaLINK+8/232 (2801) Port 8 */
-#define SEALEVEL_2802_1_PID	0X2812	/* SeaLINK+8/485 (2802) Port 1 */
-#define SEALEVEL_2802_2_PID	0X2822	/* SeaLINK+8/485 (2802) Port 2 */
-#define SEALEVEL_2802_3_PID	0X2832	/* SeaLINK+8/485 (2802) Port 3 */
-#define SEALEVEL_2802_4_PID	0X2842	/* SeaLINK+8/485 (2802) Port 4 */
-#define SEALEVEL_2802_5_PID	0X2852	/* SeaLINK+8/485 (2802) Port 5 */
-#define SEALEVEL_2802_6_PID	0X2862	/* SeaLINK+8/485 (2802) Port 6 */
-#define SEALEVEL_2802_7_PID	0X2872	/* SeaLINK+8/485 (2802) Port 7 */
-#define SEALEVEL_2802_8_PID	0X2882	/* SeaLINK+8/485 (2802) Port 8 */
-#define SEALEVEL_2803_1_PID	0X2813	/* SeaLINK+8 (2803) Port 1 */
-#define SEALEVEL_2803_2_PID	0X2823 	/* SeaLINK+8 (2803) Port 2 */
-#define SEALEVEL_2803_3_PID	0X2833 	/* SeaLINK+8 (2803) Port 3 */
-#define SEALEVEL_2803_4_PID	0X2843 	/* SeaLINK+8 (2803) Port 4 */
-#define SEALEVEL_2803_5_PID	0X2853 	/* SeaLINK+8 (2803) Port 5 */
-#define SEALEVEL_2803_6_PID	0X2863 	/* SeaLINK+8 (2803) Port 6 */
-#define SEALEVEL_2803_7_PID	0X2873 	/* SeaLINK+8 (2803) Port 7 */
-#define SEALEVEL_2803_8_PID	0X2883 	/* SeaLINK+8 (2803) Port 8 */
-
-/*
- * The following are the values for two KOBIL chipcard terminals.
- */
-#define KOBIL_VID		0x0d46	/* KOBIL Vendor ID */
-#define KOBIL_CONV_B1_PID	0x2020	/* KOBIL Konverter for B1 */
-#define KOBIL_CONV_KAAN_PID	0x2021	/* KOBIL_Konverter for KAAN */
-
-/*
- * Icom ID-1 digital transceiver
- */
-
-#define ICOM_ID1_VID            0x0C26
-#define ICOM_ID1_PID            0x0004
-
-/*
- * ASK.fr devices
- */
-#define FTDI_ASK_RDR400_PID	0xC991	/* ASK RDR 400 series card reader */
-
-/*
- * FTDI USB UART chips used in construction projects from the
- * Elektor Electronics magazine (http://elektor-electronics.co.uk)
- */
-#define ELEKTOR_VID		0x0C7D
-#define ELEKTOR_FT323R_PID	0x0005	/* RFID-Reader, issue 09-2006 */
-
-/*
- * DSS-20 Sync Station for Sony Ericsson P800
- */
-#define FTDI_DSS20_PID          0xFC82
-
-/*
- * Home Electronics (www.home-electro.com) USB gadgets
- */
-#define FTDI_HE_TIRA1_PID	0xFA78	/* Tira-1 IR transceiver */
-
-/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
-/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
-#define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
-
-/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
-
-#define FTDI_TNC_X_PID		0xEBE0
-
-/*
- * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
- *
- * The previously included PID for the UO 100 module was incorrect.
- * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
- *
- * Armin Laeuger originally sent the PID for the UM 100 module.
- */
-#define FTDI_R2000KU_TRUE_RNG	0xFB80  /* R2000KU TRUE RNG */
-#define FTDI_ELV_UR100_PID	0xFB58	/* USB-RS232-Umsetzer (UR 100) */
-#define FTDI_ELV_UM100_PID	0xFB5A	/* USB-Modul UM 100 */
-#define FTDI_ELV_UO100_PID	0xFB5B	/* USB-Modul UO 100 */
-#define FTDI_ELV_ALC8500_PID	0xF06E	/* ALC 8500 Expert */
-/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
- * MS Windows, rather than the FTDI Virtual Com Port drivers.
- * Maybe these will be easier to use with the libftdi/libusb user-space
- * drivers, or possibly the Comedi drivers in some cases. */
-#define FTDI_ELV_CLI7000_PID	0xFB59	/* Computer-Light-Interface (CLI 7000) */
-#define FTDI_ELV_PPS7330_PID	0xFB5C	/* Processor-Power-Supply (PPS 7330) */
-#define FTDI_ELV_TFM100_PID	0xFB5D	/* Temperartur-Feuchte Messgeraet (TFM 100) */
-#define FTDI_ELV_UDF77_PID	0xFB5E	/* USB DCF Funkurh (UDF 77) */
-#define FTDI_ELV_UIO88_PID	0xFB5F	/* USB-I/O Interface (UIO 88) */
-#define FTDI_ELV_UAD8_PID	0xF068	/* USB-AD-Wandler (UAD 8) */
-#define FTDI_ELV_UDA7_PID	0xF069	/* USB-DA-Wandler (UDA 7) */
-#define FTDI_ELV_USI2_PID	0xF06A	/* USB-Schrittmotoren-Interface (USI 2) */
-#define FTDI_ELV_T1100_PID	0xF06B	/* Thermometer (T 1100) */
-#define FTDI_ELV_PCD200_PID	0xF06C	/* PC-Datenlogger (PCD 200) */
-#define FTDI_ELV_ULA200_PID	0xF06D	/* USB-LCD-Ansteuerung (ULA 200) */
-#define FTDI_ELV_FHZ1000PC_PID	0xF06F	/* FHZ 1000 PC */
-#define FTDI_ELV_CSI8_PID	0xE0F0	/* Computer-Schalt-Interface (CSI 8) */
-#define FTDI_ELV_EM1000DL_PID	0xE0F1	/* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
-#define FTDI_ELV_PCK100_PID	0xE0F2	/* PC-Kabeltester (PCK 100) */
-#define FTDI_ELV_RFP500_PID	0xE0F3	/* HF-Leistungsmesser (RFP 500) */
-#define FTDI_ELV_FS20SIG_PID	0xE0F4	/* Signalgeber (FS 20 SIG) */
-#define FTDI_ELV_WS300PC_PID	0xE0F6	/* PC-Wetterstation (WS 300 PC) */
-#define FTDI_ELV_FHZ1300PC_PID	0xE0E8	/* FHZ 1300 PC */
-#define FTDI_ELV_WS500_PID	0xE0E9	/* PC-Wetterstation (WS 500) */
-#define FTDI_ELV_HS485_PID	0xE0EA	/* USB to RS-485 adapter */
-#define FTDI_ELV_EM1010PC_PID	0xE0EF	/* Engery monitor EM 1010 PC */
-#define FTDI_PHI_FISCO_PID      0xE40B  /* PHI Fisco USB to Serial cable */
-
-/*
- * Definitions for ID TECH (www.idt-net.com) devices
- */
-#define IDTECH_VID		0x0ACD	/* ID TECH Vendor ID */
-#define IDTECH_IDT1221U_PID	0x0300	/* IDT1221U USB to RS-232 adapter */
-
-/*
- * Definitions for Omnidirectional Control Technology, Inc. devices
- */
-#define OCT_VID			0x0B39	/* OCT vendor ID */
-/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
-/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
-/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
-#define OCT_US101_PID		0x0421	/* OCT US101 USB to RS-232 */
-
-/* an infrared receiver for user access control with IR tags */
-#define FTDI_PIEGROUP_PID	0xF208	/* Product Id */
-
-/*
- * Definitions for Artemis astronomical USB based cameras
- * Check it at http://www.artemisccd.co.uk/
- */
-#define FTDI_ARTEMIS_PID	0xDF28	/* All Artemis Cameras */
-
-/*
- * Definitions for ATIK Instruments astronomical USB based cameras
- * Check it at http://www.atik-instruments.com/
- */
-#define FTDI_ATIK_ATK16_PID	0xDF30	/* ATIK ATK-16 Grayscale Camera */
-#define FTDI_ATIK_ATK16C_PID	0xDF32	/* ATIK ATK-16C Colour Camera */
-#define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Grayscale Camera */
-#define FTDI_ATIK_ATK16HRC_PID	0xDF33	/* ATIK ATK-16HRC Colour Camera */
-#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
-
-/*
- * Protego product ids
- */
-#define PROTEGO_SPECIAL_1	0xFC70	/* special/unknown device */
-#define PROTEGO_R2X0		0xFC71	/* R200-USB TRNG unit (R210, R220, and R230) */
-#define PROTEGO_SPECIAL_3	0xFC72	/* special/unknown device */
-#define PROTEGO_SPECIAL_4	0xFC73	/* special/unknown device */
-
-/*
- * Gude Analog- und Digitalsysteme GmbH
- */
-#define FTDI_GUDEADS_E808_PID    0xE808
-#define FTDI_GUDEADS_E809_PID    0xE809
-#define FTDI_GUDEADS_E80A_PID    0xE80A
-#define FTDI_GUDEADS_E80B_PID    0xE80B
-#define FTDI_GUDEADS_E80C_PID    0xE80C
-#define FTDI_GUDEADS_E80D_PID    0xE80D
-#define FTDI_GUDEADS_E80E_PID    0xE80E
-#define FTDI_GUDEADS_E80F_PID    0xE80F
-#define FTDI_GUDEADS_E888_PID    0xE888  /* Expert ISDN Control USB */
-#define FTDI_GUDEADS_E889_PID    0xE889  /* USB RS-232 OptoBridge */
-#define FTDI_GUDEADS_E88A_PID    0xE88A
-#define FTDI_GUDEADS_E88B_PID    0xE88B
-#define FTDI_GUDEADS_E88C_PID    0xE88C
-#define FTDI_GUDEADS_E88D_PID    0xE88D
-#define FTDI_GUDEADS_E88E_PID    0xE88E
-#define FTDI_GUDEADS_E88F_PID    0xE88F
-
-/*
- * Linx Technologies product ids
- */
-#define LINX_SDMUSBQSS_PID	0xF448	/* Linx SDM-USB-QS-S */
-#define LINX_MASTERDEVEL2_PID   0xF449   /* Linx Master Development 2.0 */
-#define LINX_FUTURE_0_PID   0xF44A   /* Linx future device */
-#define LINX_FUTURE_1_PID   0xF44B   /* Linx future device */
-#define LINX_FUTURE_2_PID   0xF44C   /* Linx future device */
-
-/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
-/* unit for PIC16's/PIC18's */
-#define FTDI_CCSICDU20_0_PID    0xF9D0
-#define FTDI_CCSICDU40_1_PID    0xF9D1
-#define FTDI_CCSMACHX_2_PID     0xF9D2
-#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
-#define FTDI_CCSICDU64_4_PID    0xF9D4
-#define FTDI_CCSPRIME8_5_PID    0xF9D5
-
-/* Inside Accesso contactless reader (http://www.insidefr.com) */
-#define INSIDE_ACCESSO		0xFAD0
-
-/*
- * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI
- */
-#define INTREPID_VID		0x093C
-#define INTREPID_VALUECAN_PID	0x0601
-#define INTREPID_NEOVI_PID	0x0701
-
-/*
- * Falcom Wireless Communications GmbH
- */
-#define FALCOM_VID		0x0F94	/* Vendor Id */
-#define FALCOM_TWIST_PID	0x0001	/* Falcom Twist USB GPRS modem */
-#define FALCOM_SAMBA_PID	0x0005	/* Falcom Samba USB GPRS modem */
-
-/*
- * SUUNTO product ids
- */
-#define FTDI_SUUNTO_SPORTS_PID	0xF680	/* Suunto Sports instrument */
-
-/*
- * Oceanic product ids
- */
-#define FTDI_OCEANIC_PID	0xF460  /* Oceanic dive instrument */
-
-/*
- * TTi (Thurlby Thandar Instruments)
- */
-#define TTI_VID			0x103E	/* Vendor Id */
-#define TTI_QL355P_PID		0x03E8	/* TTi QL355P power supply */
-
-/*
- * Definitions for B&B Electronics products.
- */
-#define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
-#define BANDB_USOTL4_PID	0xAC01	/* USOTL4 Isolated RS-485 Converter */
-#define BANDB_USTL4_PID		0xAC02	/* USTL4 RS-485 Converter */
-#define BANDB_USO9ML2_PID	0xAC03	/* USO9ML2 Isolated RS-232 Converter */
-
-/*
- * RM Michaelides CANview USB (http://www.rmcan.com)
- * CAN fieldbus interface adapter, added by port GmbH www.port.de)
- * Ian Abbott changed the macro names for consistency.
- */
-#define FTDI_RM_CANVIEW_PID	0xfd60	/* Product Id */
-
-/*
- * EVER Eco Pro UPS (http://www.ever.com.pl/)
- */
-
-#define	EVER_ECO_PRO_CDS	0xe520	/* RS-232 converter */
-
-/*
- * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
- * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
- * and I'm not entirely sure which are used by which.
- */
-#define FTDI_4N_GALAXY_DE_1_PID	0xF3C0
-#define FTDI_4N_GALAXY_DE_2_PID	0xF3C1
-
-/*
- * Mobility Electronics products.
- */
-#define MOBILITY_VID			0x1342
-#define MOBILITY_USB_SERIAL_PID		0x0202	/* EasiDock USB 200 serial */
-
-/*
- * microHAM product IDs (http://www.microham.com).
- * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>
- * and Mike Studer (K6EEP) <k6eep@hamsoftware.org>.
- * Ian Abbott <abbotti@mev.co.uk> added a few more from the driver INF file.
- */
-#define FTDI_MHAM_KW_PID 0xEEE8		/* USB-KW interface */
-#define FTDI_MHAM_YS_PID 0xEEE9		/* USB-YS interface */
-#define FTDI_MHAM_Y6_PID 0xEEEA		/* USB-Y6 interface */
-#define FTDI_MHAM_Y8_PID 0xEEEB		/* USB-Y8 interface */
-#define FTDI_MHAM_IC_PID 0xEEEC		/* USB-IC interface */
-#define FTDI_MHAM_DB9_PID 0xEEED	/* USB-DB9 interface */
-#define FTDI_MHAM_RS232_PID 0xEEEE	/* USB-RS232 interface */
-#define FTDI_MHAM_Y9_PID 0xEEEF		/* USB-Y9 interface */
-
-/*
- * Active Robots product ids.
- */
-#define FTDI_ACTIVE_ROBOTS_PID	0xE548	/* USB comms board */
-
-/*
- * Xsens Technologies BV products (http://www.xsens.com).
- */
-#define XSENS_CONVERTER_0_PID	0xD388
-#define XSENS_CONVERTER_1_PID	0xD389
-#define XSENS_CONVERTER_2_PID	0xD38A
-#define XSENS_CONVERTER_3_PID	0xD38B
-#define XSENS_CONVERTER_4_PID	0xD38C
-#define XSENS_CONVERTER_5_PID	0xD38D
-#define XSENS_CONVERTER_6_PID	0xD38E
-#define XSENS_CONVERTER_7_PID	0xD38F
-
-/*
- * Teratronik product ids.
- * Submitted by O. Wölfelschneider.
- */
-#define FTDI_TERATRONIK_VCP_PID	 0xEC88	/* Teratronik device (preferring VCP driver on windows) */
-#define FTDI_TERATRONIK_D2XX_PID 0xEC89	/* Teratronik device (preferring D2XX driver on windows) */
-
-/*
- * Evolution Robotics products (http://www.evolution.com/).
- * Submitted by Shawn M. Lavelle.
- */
-#define EVOLUTION_VID		0xDEEE	/* Vendor ID */
-#define EVOLUTION_ER1_PID	0x0300	/* ER1 Control Module */
-#define EVO_8U232AM_PID	0x02FF	/* Evolution robotics RCM2 (FT232AM)*/
-#define EVO_HYBRID_PID		0x0302	/* Evolution robotics RCM4 PID (FT232BM)*/
-#define EVO_RCM4_PID		0x0303	/* Evolution robotics RCM4 PID */
-
-/* Pyramid Computer GmbH */
-#define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
-
-/*
- * NDI (www.ndigital.com) product ids
- */
-#define FTDI_NDI_HUC_PID		0xDA70	/* NDI Host USB Converter */
-#define FTDI_NDI_SPECTRA_SCU_PID	0xDA71	/* NDI Spectra SCU */
-#define FTDI_NDI_FUTURE_2_PID		0xDA72	/* NDI future device #2 */
-#define FTDI_NDI_FUTURE_3_PID		0xDA73	/* NDI future device #3 */
-#define FTDI_NDI_AURORA_SCU_PID		0xDA74	/* NDI Aurora SCU */
-
-/*
- * Posiflex inc retail equipment (http://www.posiflex.com.tw)
- */
-#define POSIFLEX_VID		0x0d3a  /* Vendor ID */
-#define POSIFLEX_PP7000_PID	0x0300  /* PP-7000II thermal printer */
-
-/*
- * Westrex International devices submitted by Cory Lee
- */
-#define FTDI_WESTREX_MODEL_777_PID	0xDC00	/* Model 777 */
-#define FTDI_WESTREX_MODEL_8900F_PID	0xDC01	/* Model 8900F */
-
-/*
- * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
- */
-#define FTDI_RRCIRKITS_LOCOBUFFER_PID	0xc7d0	/* LocoBuffer USB */
-
-/*
- * Eclo (http://www.eclo.pt/) product IDs.
- * PID 0xEA90 submitted by Martin Grill.
- */
-#define FTDI_ECLO_COM_1WIRE_PID	0xEA90	/* COM to 1-Wire USB adaptor */
-
-/*
- * Papouch products (http://www.papouch.com/)
- * Submitted by Folkert van Heusden
- */
-
-#define PAPOUCH_VID			0x5050	/* Vendor ID */
-#define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
-#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Quido 4/4 Module */
-
-/*
- * ACG Identification Technologies GmbH products (http://www.acg.de/).
- * Submitted by anton -at- goto10 -dot- org.
- */
-#define FTDI_ACG_HFDUAL_PID		0xDD20	/* HF Dual ISO Reader (RFID) */
-
-/*
- * Yost Engineering, Inc. products (www.yostengineering.com).
- * PID 0xE050 submitted by Aaron Prose.
- */
-#define FTDI_YEI_SERVOCENTER31_PID	0xE050	/* YEI ServoCenter3.1 USB */
-
-/*
- * ThorLabs USB motor drivers
- */
-#define FTDI_THORLABS_PID		0xfaf0 /* ThorLabs USB motor drivers */
-
-/*
- * Testo products (http://www.testo.com/)
- * Submitted by Colin Leroy
- */
-#define TESTO_VID			0x128D
-#define TESTO_USB_INTERFACE_PID		0x0001
-
-/*
- * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com.
- */
-#define FTDI_GAMMA_SCOUT_PID		0xD678	/* Gamma Scout online */
-
-/*
- * Tactrix OpenPort (ECU) devices.
- * OpenPort 1.3M submitted by Donour Sizemore.
- * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
- */
-#define FTDI_TACTRIX_OPENPORT_13M_PID	0xCC48	/* OpenPort 1.3 Mitsubishi */
-#define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
-#define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
-
-/*
- * Telldus Technologies
  */
-#define TELLDUS_VID			0x1781	/* Vendor ID */
-#define TELLDUS_TELLSTICK_PID		0x0C30	/* RF control dongle 433 MHz using FT232RL */
-
-/*
- * IBS elektronik product ids
- * Submitted by Thomas Schleusener
- */
-#define FTDI_IBS_US485_PID	0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
-#define FTDI_IBS_PICPRO_PID	0xff39  /* IBS PIC-Programmer */
-#define FTDI_IBS_PCMCIA_PID	0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
-#define FTDI_IBS_PK1_PID	0xff3b  /* IBS PK1 - Particel counter */
-#define FTDI_IBS_RS232MON_PID	0xff3c  /* IBS RS232 - Monitor */
-#define FTDI_IBS_APP70_PID	0xff3d  /* APP 70 (dust monitoring system) */
-#define FTDI_IBS_PEDO_PID	0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
-#define FTDI_IBS_PROD_PID	0xff3f  /* future device */
-
-/*
- *  MaxStream devices	www.maxstream.net
- */
-#define FTDI_MAXSTREAM_PID	0xEE18	/* Xbee PKG-U Module */
-
-/* Olimex */
-#define OLIMEX_VID			0x15BA
-#define OLIMEX_ARM_USB_OCD_PID		0x0003
-
-/* Luminary Micro Stellaris Boards, VID = FTDI_VID */
-/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
-#define LMI_LM3S_DEVEL_BOARD_PID	0xbcd8
-#define LMI_LM3S_EVAL_BOARD_PID		0xbcd9
-
-/* www.elsterelectricity.com Elster Unicom III Optical Probe */
-#define FTDI_ELSTER_UNICOM_PID		0xE700 /* Product Id */
-
-/*
- * The Mobility Lab (TML)
- * Submitted by Pierre Castella
- */
-#define TML_VID			0x1B91	/* Vendor ID */
-#define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
-
-/* Propox devices */
-#define FTDI_PROPOX_JTAGCABLEII_PID	0xD738
-
-/* Rig Expert Ukraine devices */
-#define FTDI_REU_TINY_PID		0xED22	/* RigExpert Tiny */
-
-/* Domintell products  http://www.domintell.com */
-#define FTDI_DOMINTELL_DGQG_PID	0xEF50	/* Master */
-#define FTDI_DOMINTELL_DUSB_PID	0xEF51	/* DUSB01 module */
-
-/* Alti-2 products  http://www.alti-2.com */
-#define ALTI2_VID	0x1BC9
-#define ALTI2_N3_PID	0x6001	/* Neptune 3 */
 
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
@@ -896,86 +40,6 @@
 #define INTERFACE_C		3
 #define INTERFACE_D		4
 
-/*
- * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
- * Submitted by Harald Welte <laforge@openmoko.org>
- */
-#define	FIC_VID			0x1457
-#define	FIC_NEO1973_DEBUG_PID	0x5118
-
-/*
- * RATOC REX-USB60F
- */
-#define RATOC_VENDOR_ID		0x0584
-#define RATOC_PRODUCT_ID_USB60F	0xb020
-
-/*
- * DIEBOLD BCS SE923
- */
-#define DIEBOLD_BCS_SE923_PID	0xfb99
-
-/*
- * Atmel STK541
- */
-#define ATMEL_VID		0x03eb /* Vendor ID */
-#define STK541_PID		0x2109 /* Zigbee Controller */
-
-/*
- * Dresden Elektronic Sensor Terminal Board
- */
-#define DE_VID			0x1cf1 /* Vendor ID */
-#define STB_PID			0x0001 /* Sensor Terminal Board */
-#define WHT_PID			0x0004 /* Wireless Handheld Terminal */
-
-/*
- * Blackfin gnICE JTAG
- * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
- */
-#define ADI_VID 		0x0456
-#define ADI_GNICE_PID 		0xF000
-#define ADI_GNICEPLUS_PID 	0xF001
-
-/*
- * JETI SPECTROMETER SPECBOS 1201
- * http://www.jeti.com/products/sys/scb/scb1201.php
- */
-#define JETI_VID		0x0c6c
-#define JETI_SPC1201_PID	0x04b2
-
-/*
- * Marvell SheevaPlug
- */
-#define MARVELL_VID		0x9e88
-#define MARVELL_SHEEVAPLUG_PID	0x9e8f
-
-#define FTDI_TURTELIZER_PID	0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
-
-/*
- * GN Otometrics (http://www.otometrics.com)
- * Submitted by Ville Sundberg.
- */
-#define GN_OTOMETRICS_VID	0x0c33	/* Vendor ID */
-#define AURICAL_USB_PID		0x0010	/* Aurical USB Audiometer */
-
-/*
- * Bayer Ascensia Contour blood glucose meter USB-converter cable.
- * http://winglucofacts.com/cables/
- */
-#define BAYER_VID                      0x1A79
-#define BAYER_CONTOUR_CABLE_PID        0x6001
-
-/*
- * Marvell OpenRD Base, Client
- * http://www.open-rd.org
- * OpenRD Base, Client use VID 0x0403
- */
-#define MARVELL_OPENRD_PID	0x9e90
-
-/*
- * Hameg HO820 and HO870 interface (using VID 0x0403)
- */
-#define        HAMEG_HO820_PID         0xed74
-#define        HAMEG_HO870_PID         0xed71
 
 /*
  *   BmRequestType:  1100 0000b
@@ -1490,4 +554,3 @@
  * B2..7	Length of message - (not including Byte 0)
  *
  */
-
--- linux-ec2-2.6.32.orig/drivers/usb/serial/pl2303.h
+++ linux-ec2-2.6.32/drivers/usb/serial/pl2303.h
@@ -20,6 +20,8 @@
 #define PL2303_PRODUCT_ID_ALDIGA	0x0611
 #define PL2303_PRODUCT_ID_MMX		0x0612
 #define PL2303_PRODUCT_ID_GPRS		0x0609
+#define PL2303_PRODUCT_ID_HCR331	0x331a
+#define PL2303_PRODUCT_ID_MOTOROLA	0x0307
 
 #define ATEN_VENDOR_ID		0x0557
 #define ATEN_VENDOR_ID2		0x0547
@@ -127,6 +129,10 @@
 #define CRESSI_VENDOR_ID	0x04b8
 #define CRESSI_EDY_PRODUCT_ID	0x0521
 
+/* Zeagle dive computer interface */
+#define ZEAGLE_VENDOR_ID	0x04b8
+#define ZEAGLE_N2ITION3_PRODUCT_ID	0x0522
+
 /* Sony, USB data cable for CMD-Jxx mobile phones */
 #define SONY_VENDOR_ID		0x054c
 #define SONY_QN3USB_PRODUCT_ID	0x0437
--- linux-ec2-2.6.32.orig/drivers/usb/serial/io_ti.c
+++ linux-ec2-2.6.32/drivers/usb/serial/io_ti.c
@@ -1157,7 +1157,7 @@
 
 			/* Check if we have an old version in the I2C and
 			   update if necessary */
-			if (download_cur_ver != download_new_ver) {
+			if (download_cur_ver < download_new_ver) {
 				dbg("%s - Update I2C dld from %d.%d to %d.%d",
 				    __func__,
 				    firmware_version->Ver_Major,
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ir-usb.c
+++ linux-ec2-2.6.32/drivers/usb/serial/ir-usb.c
@@ -312,6 +312,7 @@
 		kfree(port->read_urb->transfer_buffer);
 		port->read_urb->transfer_buffer = buffer;
 		port->read_urb->transfer_buffer_length = buffer_size;
+		port->bulk_in_buffer = buffer;
 
 		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
@@ -321,6 +322,7 @@
 		kfree(port->write_urb->transfer_buffer);
 		port->write_urb->transfer_buffer = buffer;
 		port->write_urb->transfer_buffer_length = buffer_size;
+		port->bulk_out_buffer = buffer;
 		port->bulk_out_size = buffer_size;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/usb/serial/kobil_sct.c
+++ linux-ec2-2.6.32/drivers/usb/serial/kobil_sct.c
@@ -345,7 +345,8 @@
 
 	/* FIXME: Add rts/dtr methods */
 	if (port->write_urb) {
-		usb_kill_urb(port->write_urb);
+		usb_poison_urb(port->write_urb);
+		kfree(port->write_urb->transfer_buffer);
 		usb_free_urb(port->write_urb);
 		port->write_urb = NULL;
 	}
@@ -371,7 +372,7 @@
 	}
 
 	tty = tty_port_tty_get(&port->port);
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 
 		/* BEGIN DEBUG */
 		/*
--- linux-ec2-2.6.32.orig/drivers/usb/serial/sierra.c
+++ linux-ec2-2.6.32/drivers/usb/serial/sierra.c
@@ -195,6 +195,7 @@
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
 	{ USB_DEVICE(0x03F0, 0x1B1D) },	/* HP ev2200 a.k.a MC5720 */
+	{ USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
 	{ USB_DEVICE(0x03F0, 0x1E1D) },	/* HP hs2300 a.k.a MC8775 */
 
 	{ USB_DEVICE(0x1199, 0x0017) },	/* Sierra Wireless EM5625 */
@@ -209,6 +210,7 @@
 	{ USB_DEVICE(0x1199, 0x0021) },	/* Sierra Wireless AirCard 597E */
 	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
 	{ USB_DEVICE(0x1199, 0x0120) },	/* Sierra Wireless USB Dongle 595U */
+	{ USB_DEVICE(0x1199, 0x0301) },	/* Sierra Wireless USB Dongle 250U */
 	/* Sierra Wireless C597 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
 	/* Sierra Wireless T598 */
@@ -264,6 +266,9 @@
 	{ USB_DEVICE(0x1199, 0x68A3), 	/* Sierra Wireless Direct IP modems */
 	  .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
 	},
+	{ USB_DEVICE(0x0f3d, 0x68A3), 	/* Airprime/Sierra Wireless Direct IP modems */
+	  .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+	},
 
 	{ }
 };
@@ -567,14 +572,17 @@
 	} else {
 		if (urb->actual_length) {
 			tty = tty_port_tty_get(&port->port);
-
-			tty_buffer_request_room(tty, urb->actual_length);
-			tty_insert_flip_string(tty, data, urb->actual_length);
-			tty_flip_buffer_push(tty);
-
-			tty_kref_put(tty);
-			usb_serial_debug_data(debug, &port->dev, __func__,
-				urb->actual_length, data);
+			if (tty) {
+				tty_buffer_request_room(tty,
+					urb->actual_length);
+				tty_insert_flip_string(tty, data,
+					urb->actual_length);
+				tty_flip_buffer_push(tty);
+
+				tty_kref_put(tty);
+				usb_serial_debug_data(debug, &port->dev,
+					__func__, urb->actual_length, data);
+			}
 		} else {
 			dev_dbg(&port->dev, "%s: empty read urb"
 				" received\n", __func__);
--- linux-ec2-2.6.32.orig/drivers/usb/serial/usb-serial.c
+++ linux-ec2-2.6.32/drivers/usb/serial/usb-serial.c
@@ -562,6 +562,18 @@
 	return -EINVAL;
 }
 
+static int serial_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	if (port->serial->type->get_icount)
+		return port->serial->type->get_icount(tty, icount);
+	return -EINVAL;
+}
+
 /*
  * We would be calling tty_wakeup here, but unfortunately some line
  * disciplines have an annoying habit of calling tty->write from
@@ -1214,6 +1226,7 @@
 	.chars_in_buffer =	serial_chars_in_buffer,
 	.tiocmget =		serial_tiocmget,
 	.tiocmset =		serial_tiocmset,
+	.get_icount = 		serial_get_icount,
 	.cleanup = 		serial_cleanup,
 	.install = 		serial_install,
 	.proc_fops =		&serial_proc_fops,
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ti_usb_3410_5052.c
+++ linux-ec2-2.6.32/drivers/usb/serial/ti_usb_3410_5052.c
@@ -366,9 +366,9 @@
 
 static void __exit ti_exit(void)
 {
+	usb_deregister(&ti_usb_driver);
 	usb_serial_deregister(&ti_1port_device);
 	usb_serial_deregister(&ti_2port_device);
-	usb_deregister(&ti_usb_driver);
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/usb/serial/io_edgeport.c
+++ linux-ec2-2.6.32/drivers/usb/serial/io_edgeport.c
@@ -2935,8 +2935,8 @@
 
 	dbg("%s %d.%d.%d", fw_info, rec->data[0], rec->data[1], build);
 
-	edge_serial->product_info.FirmwareMajorVersion = fw->data[0];
-	edge_serial->product_info.FirmwareMinorVersion = fw->data[1];
+	edge_serial->product_info.FirmwareMajorVersion = rec->data[0];
+	edge_serial->product_info.FirmwareMinorVersion = rec->data[1];
 	edge_serial->product_info.FirmwareBuildNumber = cpu_to_le16(build);
 
 	for (rec = ihex_next_binrec(rec); rec;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/digi_acceleport.c
+++ linux-ec2-2.6.32/drivers/usb/serial/digi_acceleport.c
@@ -455,7 +455,6 @@
 static int digi_chars_in_buffer(struct tty_struct *tty);
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void digi_close(struct usb_serial_port *port);
-static int digi_carrier_raised(struct usb_serial_port *port);
 static void digi_dtr_rts(struct usb_serial_port *port, int on);
 static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
@@ -511,7 +510,6 @@
 	.open =				digi_open,
 	.close =			digi_close,
 	.dtr_rts =			digi_dtr_rts,
-	.carrier_raised =		digi_carrier_raised,
 	.write =			digi_write,
 	.write_room =			digi_write_room,
 	.write_bulk_callback = 		digi_write_bulk_callback,
@@ -1338,14 +1336,6 @@
 	digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
 }
 
-static int digi_carrier_raised(struct usb_serial_port *port)
-{
-	struct digi_port *priv = usb_get_serial_port_data(port);
-	if (priv->dp_modem_signals & TIOCM_CD)
-		return 1;
-	return 0;
-}
-
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	int ret;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ftdi_sio.c
+++ linux-ec2-2.6.32/drivers/usb/serial/ftdi_sio.c
@@ -44,12 +44,13 @@
 #include <linux/serial.h>
 #include <linux/usb/serial.h>
 #include "ftdi_sio.h"
+#include "ftdi_sio_ids.h"
 
 /*
  * Version Information
  */
 #define DRIVER_VERSION "v1.5.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>, Andreas Mohr"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
 static int debug;
@@ -103,6 +104,7 @@
 static int   ftdi_jtag_probe(struct usb_serial *serial);
 static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
 static int   ftdi_NDI_device_setup(struct usb_serial *serial);
+static int   ftdi_stmclite_probe(struct usb_serial *serial);
 static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 
@@ -126,6 +128,10 @@
 	.port_probe = ftdi_HE_TIRA1_setup,
 };
 
+static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
+	.probe	= ftdi_stmclite_probe,
+};
+
 /*
  * The 8U232AM has the same API as the sio except for:
  * - it can support MUCH higher baudrates; up to:
@@ -144,10 +150,17 @@
 
 
 
+/*
+ * Device ID not listed? Test via module params product/vendor or
+ * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
+ */
 static struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
@@ -156,6 +169,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
@@ -173,9 +189,11 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
+	{ USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
@@ -195,6 +213,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
+	{ USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
 	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
@@ -512,6 +531,7 @@
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
 	{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
 	{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
+	{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
@@ -551,9 +571,16 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
 	/*
-	 * Due to many user requests for multiple ELV devices we enable
-	 * them by default.
+	 * ELV devices:
 	 */
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS550_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_EC3000_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS888_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_TWS550_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FEM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) },
@@ -570,11 +597,17 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UTP8_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS444PC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UMS100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
 	{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -595,9 +628,25 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) },
 	{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
+	{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
+	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) },
+	{ USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) },
 	{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
@@ -624,6 +673,7 @@
 	{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
 	{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
+	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
@@ -640,8 +690,17 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
-	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
-	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) },
+	{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
@@ -662,6 +721,8 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
 	{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
+	{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
+	{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
 	{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
@@ -681,7 +742,37 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+
+	/* Papouch devices based on FTDI chip */
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) },
+
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
@@ -702,7 +793,41 @@
 	{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+	{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
+	{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) },
+	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
+	{ USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) },
+	{ USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
+	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1357,7 +1482,7 @@
 	}
 
 	/* set max packet size based on descriptor */
-	priv->max_packet_size = ep_desc->wMaxPacketSize;
+	priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize);
 
 	dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
 }
@@ -1636,6 +1761,25 @@
 }
 
 /*
+ * First and second port on STMCLiteadaptors is reserved for JTAG interface
+ * and the forth port for pio
+ */
+static int ftdi_stmclite_probe(struct usb_serial *serial)
+{
+	struct usb_device *udev = serial->dev;
+	struct usb_interface *interface = serial->interface;
+
+	dbg("%s", __func__);
+
+	if (interface == udev->actconfig->interface[2])
+		return 0;
+
+	dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+
+	return -ENODEV;
+}
+
+/*
  * The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
  * We have to correct it if we want to read from it.
  */
--- linux-ec2-2.6.32.orig/drivers/usb/serial/cp210x.c
+++ linux-ec2-2.6.32/drivers/usb/serial/cp210x.c
@@ -51,16 +51,18 @@
 static int cp210x_startup(struct usb_serial *);
 static void cp210x_disconnect(struct usb_serial *);
 static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
-static int cp210x_carrier_raised(struct usb_serial_port *p);
 
 static int debug;
 
 static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
 	{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
 	{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
 	{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
 	{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
 	{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
+	{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
+	{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
 	{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
 	{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
 	{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
@@ -72,9 +74,12 @@
 	{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
 	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
+	{ USB_DEVICE(0x10C4, 0x8044) }, /* Cygnal Debug Adapter */
+	{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
+	{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
 	{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
 	{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
 	{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
@@ -84,26 +89,34 @@
 	{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
 	{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
 	{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+	{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
 	{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+	{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
 	{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
 	{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
 	{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+	{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
 	{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+	{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
 	{ USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
 	{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */
-	{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
+	{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesys ETRX2USB */
 	{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
 	{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
 	{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
+	{ USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
 	{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
+	{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
+	{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
 	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
 	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
 	{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
@@ -114,7 +127,14 @@
 	{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
 	{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
+	{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
+	{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+	{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+	{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
 	{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
 	{ } /* Terminating Entry */
 };
@@ -145,8 +165,7 @@
 	.tiocmset		= cp210x_tiocmset,
 	.attach			= cp210x_startup,
 	.disconnect		= cp210x_disconnect,
-	.dtr_rts		= cp210x_dtr_rts,
-	.carrier_raised		= cp210x_carrier_raised
+	.dtr_rts		= cp210x_dtr_rts
 };
 
 /* Config request types */
@@ -207,8 +226,8 @@
 #define BITS_STOP_2		0x0002
 
 /* CP210X_SET_BREAK */
-#define BREAK_ON		0x0000
-#define BREAK_OFF		0x0001
+#define BREAK_ON		0x0001
+#define BREAK_OFF		0x0000
 
 /* CP210X_(SET_MHS|GET_MDMSTS) */
 #define CONTROL_DTR		0x0001
@@ -780,15 +799,6 @@
 	return result;
 }
 
-static int cp210x_carrier_raised(struct usb_serial_port *p)
-{
-	unsigned int control;
-	cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1);
-	if (control & CONTROL_DCD)
-		return 1;
-	return 0;
-}
-
 static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
 {
 	struct usb_serial_port *port = tty->driver_data;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ftdi_sio_ids.h
+++ linux-ec2-2.6.32/drivers/usb/serial/ftdi_sio_ids.h
@@ -0,0 +1,1161 @@
+/*
+ * vendor/product IDs (VID/PID) of devices using FTDI USB serial converters.
+ * Please keep numerically sorted within individual areas, thanks!
+ *
+ * Philipp G�hring - pg@futureware.at - added the Device ID of the USB relais
+ * from Rudolf Gugler
+ *
+ */
+
+
+/**********************************/
+/***** devices using FTDI VID *****/
+/**********************************/
+
+
+#define FTDI_VID	0x0403	/* Vendor Id */
+
+
+/*** "original" FTDI device PIDs ***/
+
+#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
+#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
+#define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
+#define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
+
+
+/*** third-party PIDs (using FTDI_VID) ***/
+
+/*
+ * Marvell OpenRD Base, Client
+ * http://www.open-rd.org
+ * OpenRD Base, Client use VID 0x0403
+ */
+#define MARVELL_OPENRD_PID	0x9e90
+
+/* www.candapter.com Ewert Energy Systems CANdapter device */
+#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+
+#define FTDI_NXTCAM_PID		0xABB8 /* NXTCam for Mindstorms NXT */
+
+/* US Interface Navigator (http://www.usinterface.com/) */
+#define FTDI_USINT_CAT_PID	0xb810	/* Navigator CAT and 2nd PTT lines */
+#define FTDI_USINT_WKEY_PID	0xb811	/* Navigator WKEY and FSK lines */
+#define FTDI_USINT_RS232_PID	0xb812	/* Navigator RS232 and CONFIG lines */
+
+/* OOCDlink by Joern Kaipf <joernk@web.de>
+ * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
+#define FTDI_OOCDLINK_PID	0xbaf8	/* Amontec JTAGkey */
+
+/* Luminary Micro Stellaris Boards, VID = FTDI_VID */
+/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
+#define LMI_LM3S_DEVEL_BOARD_PID	0xbcd8
+#define LMI_LM3S_EVAL_BOARD_PID		0xbcd9
+
+#define FTDI_TURTELIZER_PID	0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
+
+/* OpenDCC (www.opendcc.de) product id */
+#define FTDI_OPENDCC_PID	0xBFD8
+#define FTDI_OPENDCC_SNIFFER_PID	0xBFD9
+#define FTDI_OPENDCC_THROTTLE_PID	0xBFDA
+#define FTDI_OPENDCC_GATEWAY_PID	0xBFDB
+#define FTDI_OPENDCC_GBM_PID	0xBFDC
+
+/*
+ * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
+ */
+#define FTDI_RRCIRKITS_LOCOBUFFER_PID	0xc7d0	/* LocoBuffer USB */
+
+/* DMX4ALL DMX Interfaces */
+#define FTDI_DMX4ALL 0xC850
+
+/*
+ * ASK.fr devices
+ */
+#define FTDI_ASK_RDR400_PID	0xC991	/* ASK RDR 400 series card reader */
+
+/* www.starting-point-systems.com �Chameleon device */
+#define FTDI_MICRO_CHAMELEON_PID	0xCAA0	/* Product Id */
+
+/*
+ * Tactrix OpenPort (ECU) devices.
+ * OpenPort 1.3M submitted by Donour Sizemore.
+ * OpenPort 1.3S and 1.3U submitted by Ian Abbott.
+ */
+#define FTDI_TACTRIX_OPENPORT_13M_PID	0xCC48	/* OpenPort 1.3 Mitsubishi */
+#define FTDI_TACTRIX_OPENPORT_13S_PID	0xCC49	/* OpenPort 1.3 Subaru */
+#define FTDI_TACTRIX_OPENPORT_13U_PID	0xCC4A	/* OpenPort 1.3 Universal */
+
+/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
+/* the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_SCS_DEVICE_0_PID 0xD010    /* SCS PTC-IIusb */
+#define FTDI_SCS_DEVICE_1_PID 0xD011    /* SCS Tracker / DSP TNC */
+#define FTDI_SCS_DEVICE_2_PID 0xD012
+#define FTDI_SCS_DEVICE_3_PID 0xD013
+#define FTDI_SCS_DEVICE_4_PID 0xD014
+#define FTDI_SCS_DEVICE_5_PID 0xD015
+#define FTDI_SCS_DEVICE_6_PID 0xD016
+#define FTDI_SCS_DEVICE_7_PID 0xD017
+
+/* iPlus device */
+#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
+
+/*
+ * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com.
+ */
+#define FTDI_GAMMA_SCOUT_PID		0xD678	/* Gamma Scout online */
+
+/* Propox devices */
+#define FTDI_PROPOX_JTAGCABLEII_PID	0xD738
+
+/* Lenz LI-USB Computer Interface. */
+#define FTDI_LENZ_LIUSB_PID	0xD780
+
+/* Vardaan Enterprises Serial Interface VEUSB422R3 */
+#define FTDI_VARDAAN_PID	0xF070
+
+/*
+ * Xsens Technologies BV products (http://www.xsens.com).
+ */
+#define XSENS_CONVERTER_0_PID	0xD388
+#define XSENS_CONVERTER_1_PID	0xD389
+#define XSENS_CONVERTER_2_PID	0xD38A
+#define XSENS_CONVERTER_3_PID	0xD38B
+#define XSENS_CONVERTER_4_PID	0xD38C
+#define XSENS_CONVERTER_5_PID	0xD38D
+#define XSENS_CONVERTER_6_PID	0xD38E
+#define XSENS_CONVERTER_7_PID	0xD38F
+
+/*
+ * NDI (www.ndigital.com) product ids
+ */
+#define FTDI_NDI_HUC_PID		0xDA70	/* NDI Host USB Converter */
+#define FTDI_NDI_SPECTRA_SCU_PID	0xDA71	/* NDI Spectra SCU */
+#define FTDI_NDI_FUTURE_2_PID		0xDA72	/* NDI future device #2 */
+#define FTDI_NDI_FUTURE_3_PID		0xDA73	/* NDI future device #3 */
+#define FTDI_NDI_AURORA_SCU_PID		0xDA74	/* NDI Aurora SCU */
+
+/*
+ * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs
+ */
+#define FTDI_CHAMSYS_24_MASTER_WING_PID        0xDAF8
+#define FTDI_CHAMSYS_PC_WING_PID       0xDAF9
+#define FTDI_CHAMSYS_USB_DMX_PID       0xDAFA
+#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB
+#define FTDI_CHAMSYS_MINI_WING_PID     0xDAFC
+#define FTDI_CHAMSYS_MAXI_WING_PID     0xDAFD
+#define FTDI_CHAMSYS_MEDIA_WING_PID    0xDAFE
+#define FTDI_CHAMSYS_WING_PID  0xDAFF
+
+/*
+ * Westrex International devices submitted by Cory Lee
+ */
+#define FTDI_WESTREX_MODEL_777_PID	0xDC00	/* Model 777 */
+#define FTDI_WESTREX_MODEL_8900F_PID	0xDC01	/* Model 8900F */
+
+/*
+ * ACG Identification Technologies GmbH products (http://www.acg.de/).
+ * Submitted by anton -at- goto10 -dot- org.
+ */
+#define FTDI_ACG_HFDUAL_PID		0xDD20	/* HF Dual ISO Reader (RFID) */
+
+/*
+ * Definitions for Artemis astronomical USB based cameras
+ * Check it at http://www.artemisccd.co.uk/
+ */
+#define FTDI_ARTEMIS_PID	0xDF28	/* All Artemis Cameras */
+
+/*
+ * Definitions for ATIK Instruments astronomical USB based cameras
+ * Check it at http://www.atik-instruments.com/
+ */
+#define FTDI_ATIK_ATK16_PID	0xDF30	/* ATIK ATK-16 Grayscale Camera */
+#define FTDI_ATIK_ATK16C_PID	0xDF32	/* ATIK ATK-16C Colour Camera */
+#define FTDI_ATIK_ATK16HR_PID	0xDF31	/* ATIK ATK-16HR Grayscale Camera */
+#define FTDI_ATIK_ATK16HRC_PID	0xDF33	/* ATIK ATK-16HRC Colour Camera */
+#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
+
+/*
+ * Yost Engineering, Inc. products (www.yostengineering.com).
+ * PID 0xE050 submitted by Aaron Prose.
+ */
+#define FTDI_YEI_SERVOCENTER31_PID	0xE050	/* YEI ServoCenter3.1 USB */
+
+/*
+ * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
+ * All of these devices use FTDI's vendor ID (0x0403).
+ * Further IDs taken from ELV Windows .inf file.
+ *
+ * The previously included PID for the UO 100 module was incorrect.
+ * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58).
+ *
+ * Armin Laeuger originally sent the PID for the UM 100 module.
+ */
+#define FTDI_ELV_USR_PID	0xE000	/* ELV Universal-Sound-Recorder */
+#define FTDI_ELV_MSM1_PID	0xE001	/* ELV Mini-Sound-Modul */
+#define FTDI_ELV_KL100_PID	0xE002	/* ELV Kfz-Leistungsmesser KL 100 */
+#define FTDI_ELV_WS550_PID	0xE004	/* WS 550 */
+#define FTDI_ELV_EC3000_PID	0xE006	/* ENERGY CONTROL 3000 USB */
+#define FTDI_ELV_WS888_PID	0xE008	/* WS 888 */
+#define FTDI_ELV_TWS550_PID	0xE009	/* Technoline WS 550 */
+#define FTDI_ELV_FEM_PID	0xE00A	/* Funk Energie Monitor */
+#define FTDI_ELV_FHZ1300PC_PID	0xE0E8	/* FHZ 1300 PC */
+#define FTDI_ELV_WS500_PID	0xE0E9	/* PC-Wetterstation (WS 500) */
+#define FTDI_ELV_HS485_PID	0xE0EA	/* USB to RS-485 adapter */
+#define FTDI_ELV_UMS100_PID	0xE0EB	/* ELV USB Master-Slave Schaltsteckdose UMS 100 */
+#define FTDI_ELV_TFD128_PID	0xE0EC	/* ELV Temperatur-Feuchte-Datenlogger TFD 128 */
+#define FTDI_ELV_FM3RX_PID	0xE0ED	/* ELV Messwertuebertragung FM3 RX */
+#define FTDI_ELV_WS777_PID	0xE0EE	/* Conrad WS 777 */
+#define FTDI_ELV_EM1010PC_PID	0xE0EF	/* Engery monitor EM 1010 PC */
+#define FTDI_ELV_CSI8_PID	0xE0F0	/* Computer-Schalt-Interface (CSI 8) */
+#define FTDI_ELV_EM1000DL_PID	0xE0F1	/* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
+#define FTDI_ELV_PCK100_PID	0xE0F2	/* PC-Kabeltester (PCK 100) */
+#define FTDI_ELV_RFP500_PID	0xE0F3	/* HF-Leistungsmesser (RFP 500) */
+#define FTDI_ELV_FS20SIG_PID	0xE0F4	/* Signalgeber (FS 20 SIG) */
+#define FTDI_ELV_UTP8_PID	0xE0F5	/* ELV UTP 8 */
+#define FTDI_ELV_WS300PC_PID	0xE0F6	/* PC-Wetterstation (WS 300 PC) */
+#define FTDI_ELV_WS444PC_PID	0xE0F7	/* Conrad WS 444 PC */
+#define FTDI_PHI_FISCO_PID      0xE40B  /* PHI Fisco USB to Serial cable */
+#define FTDI_ELV_UAD8_PID	0xF068	/* USB-AD-Wandler (UAD 8) */
+#define FTDI_ELV_UDA7_PID	0xF069	/* USB-DA-Wandler (UDA 7) */
+#define FTDI_ELV_USI2_PID	0xF06A	/* USB-Schrittmotoren-Interface (USI 2) */
+#define FTDI_ELV_T1100_PID	0xF06B	/* Thermometer (T 1100) */
+#define FTDI_ELV_PCD200_PID	0xF06C	/* PC-Datenlogger (PCD 200) */
+#define FTDI_ELV_ULA200_PID	0xF06D	/* USB-LCD-Ansteuerung (ULA 200) */
+#define FTDI_ELV_ALC8500_PID	0xF06E	/* ALC 8500 Expert */
+#define FTDI_ELV_FHZ1000PC_PID	0xF06F	/* FHZ 1000 PC */
+#define FTDI_ELV_UR100_PID	0xFB58	/* USB-RS232-Umsetzer (UR 100) */
+#define FTDI_ELV_UM100_PID	0xFB5A	/* USB-Modul UM 100 */
+#define FTDI_ELV_UO100_PID	0xFB5B	/* USB-Modul UO 100 */
+/* Additional ELV PIDs that default to using the FTDI D2XX drivers on
+ * MS Windows, rather than the FTDI Virtual Com Port drivers.
+ * Maybe these will be easier to use with the libftdi/libusb user-space
+ * drivers, or possibly the Comedi drivers in some cases. */
+#define FTDI_ELV_CLI7000_PID	0xFB59	/* Computer-Light-Interface (CLI 7000) */
+#define FTDI_ELV_PPS7330_PID	0xFB5C	/* Processor-Power-Supply (PPS 7330) */
+#define FTDI_ELV_TFM100_PID	0xFB5D	/* Temperartur-Feuchte Messgeraet (TFM 100) */
+#define FTDI_ELV_UDF77_PID	0xFB5E	/* USB DCF Funkurh (UDF 77) */
+#define FTDI_ELV_UIO88_PID	0xFB5F	/* USB-I/O Interface (UIO 88) */
+
+/*
+ * EVER Eco Pro UPS (http://www.ever.com.pl/)
+ */
+
+#define	EVER_ECO_PRO_CDS	0xe520	/* RS-232 converter */
+
+/*
+ * Active Robots product ids.
+ */
+#define FTDI_ACTIVE_ROBOTS_PID	0xE548	/* USB comms board */
+
+/* Pyramid Computer GmbH */
+#define FTDI_PYRAMID_PID	0xE6C8	/* Pyramid Appliance Display */
+
+/* www.elsterelectricity.com Elster Unicom III Optical Probe */
+#define FTDI_ELSTER_UNICOM_PID		0xE700 /* Product Id */
+
+/*
+ * Gude Analog- und Digitalsysteme GmbH
+ */
+#define FTDI_GUDEADS_E808_PID    0xE808
+#define FTDI_GUDEADS_E809_PID    0xE809
+#define FTDI_GUDEADS_E80A_PID    0xE80A
+#define FTDI_GUDEADS_E80B_PID    0xE80B
+#define FTDI_GUDEADS_E80C_PID    0xE80C
+#define FTDI_GUDEADS_E80D_PID    0xE80D
+#define FTDI_GUDEADS_E80E_PID    0xE80E
+#define FTDI_GUDEADS_E80F_PID    0xE80F
+#define FTDI_GUDEADS_E888_PID    0xE888  /* Expert ISDN Control USB */
+#define FTDI_GUDEADS_E889_PID    0xE889  /* USB RS-232 OptoBridge */
+#define FTDI_GUDEADS_E88A_PID    0xE88A
+#define FTDI_GUDEADS_E88B_PID    0xE88B
+#define FTDI_GUDEADS_E88C_PID    0xE88C
+#define FTDI_GUDEADS_E88D_PID    0xE88D
+#define FTDI_GUDEADS_E88E_PID    0xE88E
+#define FTDI_GUDEADS_E88F_PID    0xE88F
+
+/*
+ * Eclo (http://www.eclo.pt/) product IDs.
+ * PID 0xEA90 submitted by Martin Grill.
+ */
+#define FTDI_ECLO_COM_1WIRE_PID	0xEA90	/* COM to 1-Wire USB adaptor */
+
+/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
+#define FTDI_TNC_X_PID		0xEBE0
+
+/*
+ * Teratronik product ids.
+ * Submitted by O. W�lfelschneider.
+ */
+#define FTDI_TERATRONIK_VCP_PID	 0xEC88	/* Teratronik device (preferring VCP driver on windows) */
+#define FTDI_TERATRONIK_D2XX_PID 0xEC89	/* Teratronik device (preferring D2XX driver on windows) */
+
+/* Rig Expert Ukraine devices */
+#define FTDI_REU_TINY_PID		0xED22	/* RigExpert Tiny */
+
+/*
+ * Hameg HO820 and HO870 interface (using VID 0x0403)
+ */
+#define        HAMEG_HO820_PID         0xed74
+#define HAMEG_HO730_PID			0xed73
+#define HAMEG_HO720_PID			0xed72
+#define        HAMEG_HO870_PID         0xed71
+
+/*
+ *  MaxStream devices	www.maxstream.net
+ */
+#define FTDI_MAXSTREAM_PID	0xEE18	/* Xbee PKG-U Module */
+
+/*
+ * microHAM product IDs (http://www.microham.com).
+ * Submitted by Justin Burket (KL1RL) <zorton@jtan.com>
+ * and Mike Studer (K6EEP) <k6eep@hamsoftware.org>.
+ * Ian Abbott <abbotti@mev.co.uk> added a few more from the driver INF file.
+ */
+#define FTDI_MHAM_KW_PID 0xEEE8		/* USB-KW interface */
+#define FTDI_MHAM_YS_PID 0xEEE9		/* USB-YS interface */
+#define FTDI_MHAM_Y6_PID 0xEEEA		/* USB-Y6 interface */
+#define FTDI_MHAM_Y8_PID 0xEEEB		/* USB-Y8 interface */
+#define FTDI_MHAM_IC_PID 0xEEEC		/* USB-IC interface */
+#define FTDI_MHAM_DB9_PID 0xEEED	/* USB-DB9 interface */
+#define FTDI_MHAM_RS232_PID 0xEEEE	/* USB-RS232 interface */
+#define FTDI_MHAM_Y9_PID 0xEEEF		/* USB-Y9 interface */
+
+/* Domintell products  http://www.domintell.com */
+#define FTDI_DOMINTELL_DGQG_PID	0xEF50	/* Master */
+#define FTDI_DOMINTELL_DUSB_PID	0xEF51	/* DUSB01 module */
+
+/*
+ * The following are the values for the Perle Systems
+ * UltraPort USB serial converters
+ */
+#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0	/* Perle UltraPort Product Id */
+
+/* Sprog II (Andrew Crosland's SprogII DCC interface) */
+#define FTDI_SPROG_II		0xF0C8
+
+/* an infrared receiver for user access control with IR tags */
+#define FTDI_PIEGROUP_PID	0xF208	/* Product Id */
+
+/* ACT Solutions HomePro ZWave interface
+   (http://www.act-solutions.com/HomePro.htm) */
+#define FTDI_ACTZWAVE_PID	0xF2D0
+
+/*
+ * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
+ * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
+ * and I'm not entirely sure which are used by which.
+ */
+#define FTDI_4N_GALAXY_DE_1_PID	0xF3C0
+#define FTDI_4N_GALAXY_DE_2_PID	0xF3C1
+
+/*
+ * Linx Technologies product ids
+ */
+#define LINX_SDMUSBQSS_PID	0xF448	/* Linx SDM-USB-QS-S */
+#define LINX_MASTERDEVEL2_PID   0xF449   /* Linx Master Development 2.0 */
+#define LINX_FUTURE_0_PID   0xF44A   /* Linx future device */
+#define LINX_FUTURE_1_PID   0xF44B   /* Linx future device */
+#define LINX_FUTURE_2_PID   0xF44C   /* Linx future device */
+
+/*
+ * Oceanic product ids
+ */
+#define FTDI_OCEANIC_PID	0xF460  /* Oceanic dive instrument */
+
+/*
+ * SUUNTO product ids
+ */
+#define FTDI_SUUNTO_SPORTS_PID	0xF680	/* Suunto Sports instrument */
+
+/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
+/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
+#define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
+
+/* CCS Inc. ICDU/ICDU40 product ID -
+ * the FT232BM is used in an in-circuit-debugger unit for PIC16's/PIC18's */
+#define FTDI_CCSICDU20_0_PID    0xF9D0
+#define FTDI_CCSICDU40_1_PID    0xF9D1
+#define FTDI_CCSMACHX_2_PID     0xF9D2
+#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
+#define FTDI_CCSICDU64_4_PID    0xF9D4
+#define FTDI_CCSPRIME8_5_PID    0xF9D5
+
+/*
+ * The following are the values for the Matrix Orbital LCD displays,
+ * which are the FT232BM ( similar to the 8U232AM )
+ */
+#define FTDI_MTXORB_0_PID      0xFA00  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_1_PID      0xFA01  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_2_PID      0xFA02  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_3_PID      0xFA03  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_4_PID      0xFA04  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
+
+/*
+ * Home Electronics (www.home-electro.com) USB gadgets
+ */
+#define FTDI_HE_TIRA1_PID	0xFA78	/* Tira-1 IR transceiver */
+
+/* Inside Accesso contactless reader (http://www.insidefr.com) */
+#define INSIDE_ACCESSO		0xFAD0
+
+/*
+ * ThorLabs USB motor drivers
+ */
+#define FTDI_THORLABS_PID		0xfaf0 /* ThorLabs USB motor drivers */
+
+/*
+ * Protego product ids
+ */
+#define PROTEGO_SPECIAL_1	0xFC70	/* special/unknown device */
+#define PROTEGO_R2X0		0xFC71	/* R200-USB TRNG unit (R210, R220, and R230) */
+#define PROTEGO_SPECIAL_3	0xFC72	/* special/unknown device */
+#define PROTEGO_SPECIAL_4	0xFC73	/* special/unknown device */
+
+/*
+ * DSS-20 Sync Station for Sony Ericsson P800
+ */
+#define FTDI_DSS20_PID          0xFC82
+
+/* www.irtrans.de device */
+#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
+
+/*
+ * RM Michaelides CANview USB (http://www.rmcan.com) (FTDI_VID)
+ * CAN fieldbus interface adapter, added by port GmbH www.port.de)
+ * Ian Abbott changed the macro names for consistency.
+ */
+#define FTDI_RM_CANVIEW_PID	0xfd60	/* Product Id */
+/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */
+#define FTDI_TTUSB_PID 0xFF20 /* Product Id */
+
+#define FTDI_USBX_707_PID 0xF857	/* ADSTech IR Blaster USBX-707 (FTDI_VID) */
+
+#define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
+
+/*
+ * PCDJ use ftdi based dj-controllers. The following PID is
+ * for their DAC-2 device http://www.pcdjhardware.com/DAC2.asp
+ * (the VID is the standard ftdi vid (FTDI_VID), PID sent by Wouter Paesen)
+ */
+#define FTDI_PCDJ_DAC2_PID 0xFA88
+
+#define FTDI_R2000KU_TRUE_RNG	0xFB80  /* R2000KU TRUE RNG (FTDI_VID) */
+
+/*
+ * DIEBOLD BCS SE923 (FTDI_VID)
+ */
+#define DIEBOLD_BCS_SE923_PID	0xfb99
+
+/* www.crystalfontz.com devices
+ * - thanx for providing free devices for evaluation !
+ * they use the ftdi chipset for the USB interface
+ * and the vendor id is the same
+ */
+#define FTDI_XF_632_PID 0xFC08	/* 632: 16x2 Character Display */
+#define FTDI_XF_634_PID 0xFC09	/* 634: 20x4 Character Display */
+#define FTDI_XF_547_PID 0xFC0A	/* 547: Two line Display */
+#define FTDI_XF_633_PID 0xFC0B	/* 633: 16x2 Character Display with Keys */
+#define FTDI_XF_631_PID 0xFC0C	/* 631: 20x2 Character Display */
+#define FTDI_XF_635_PID 0xFC0D	/* 635: 20x4 Character Display */
+#define FTDI_XF_640_PID 0xFC0E	/* 640: Two line Display */
+#define FTDI_XF_642_PID 0xFC0F	/* 642: Two line Display */
+
+/*
+ * Video Networks Limited / Homechoice in the UK use an ftdi-based device
+ * for their 1Mb broadband internet service.  The following PID is exhibited
+ * by the usb device supplied (the VID is the standard ftdi vid (FTDI_VID)
+ */
+#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
+
+/* AlphaMicro Components AMC-232USB01 device (FTDI_VID) */
+#define FTDI_AMC232_PID 0xFF00 /* Product Id */
+
+/*
+ * IBS elektronik product ids (FTDI_VID)
+ * Submitted by Thomas Schleusener
+ */
+#define FTDI_IBS_US485_PID	0xff38  /* IBS US485 (USB<-->RS422/485 interface) */
+#define FTDI_IBS_PICPRO_PID	0xff39  /* IBS PIC-Programmer */
+#define FTDI_IBS_PCMCIA_PID	0xff3a  /* IBS Card reader for PCMCIA SRAM-cards */
+#define FTDI_IBS_PK1_PID	0xff3b  /* IBS PK1 - Particel counter */
+#define FTDI_IBS_RS232MON_PID	0xff3c  /* IBS RS232 - Monitor */
+#define FTDI_IBS_APP70_PID	0xff3d  /* APP 70 (dust monitoring system) */
+#define FTDI_IBS_PEDO_PID	0xff3e  /* IBS PEDO-Modem (RF modem 868.35 MHz) */
+#define FTDI_IBS_PROD_PID	0xff3f  /* future device */
+/* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
+#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
+
+
+/********************************/
+/** third-party VID/PID combos **/
+/********************************/
+
+
+
+/*
+ * Atmel STK541
+ */
+#define ATMEL_VID		0x03eb /* Vendor ID */
+#define STK541_PID		0x2109 /* Zigbee Controller */
+
+/*
+ * Blackfin gnICE JTAG
+ * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice
+ */
+#define ADI_VID 		0x0456
+#define ADI_GNICE_PID 		0xF000
+#define ADI_GNICEPLUS_PID 	0xF001
+
+/*
+ * RATOC REX-USB60F
+ */
+#define RATOC_VENDOR_ID		0x0584
+#define RATOC_PRODUCT_ID_USB60F	0xb020
+
+/*
+ * Acton Research Corp.
+ */
+#define ACTON_VID		0x0647	/* Vendor ID */
+#define ACTON_SPECTRAPRO_PID	0x0100
+
+/*
+ * Contec products (http://www.contec.com)
+ * Submitted by Daniel Sangorrin
+ */
+#define CONTEC_VID		0x06CE	/* Vendor ID */
+#define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */
+
+/*
+ * Contec products (http://www.contec.com)
+ * Submitted by Daniel Sangorrin
+ */
+#define CONTEC_VID		0x06CE	/* Vendor ID */
+#define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */
+
+/*
+ * Definitions for B&B Electronics products.
+ */
+#define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
+#define BANDB_USOTL4_PID	0xAC01	/* USOTL4 Isolated RS-485 Converter */
+#define BANDB_USTL4_PID		0xAC02	/* USTL4 RS-485 Converter */
+#define BANDB_USO9ML2_PID	0xAC03	/* USO9ML2 Isolated RS-232 Converter */
+#define BANDB_USOPTL4_PID	0xAC11
+#define BANDB_USPTL4_PID	0xAC12
+#define BANDB_USO9ML2DR_2_PID	0xAC16
+#define BANDB_USO9ML2DR_PID	0xAC17
+#define BANDB_USOPTL4DR2_PID	0xAC18	/* USOPTL4R-2 2-port Isolated RS-232 Converter */
+#define BANDB_USOPTL4DR_PID	0xAC19
+#define BANDB_485USB9F_2W_PID	0xAC25
+#define BANDB_485USB9F_4W_PID	0xAC26
+#define BANDB_232USB9M_PID	0xAC27
+#define BANDB_485USBTB_2W_PID	0xAC33
+#define BANDB_485USBTB_4W_PID	0xAC34
+#define BANDB_TTL5USB9M_PID	0xAC49
+#define BANDB_TTL3USB9M_PID	0xAC50
+#define BANDB_ZZ_PROG1_USB_PID	0xBA02
+
+/*
+ * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI
+ */
+#define INTREPID_VID		0x093C
+#define INTREPID_VALUECAN_PID	0x0601
+#define INTREPID_NEOVI_PID	0x0701
+
+/*
+ * Definitions for ID TECH (www.idt-net.com) devices
+ */
+#define IDTECH_VID		0x0ACD	/* ID TECH Vendor ID */
+#define IDTECH_IDT1221U_PID	0x0300	/* IDT1221U USB to RS-232 adapter */
+
+/*
+ * Definitions for Omnidirectional Control Technology, Inc. devices
+ */
+#define OCT_VID			0x0B39	/* OCT vendor ID */
+/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
+/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
+/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
+#define OCT_DK201_PID		0x0103	/* OCT DK201 USB docking station */
+#define OCT_US101_PID		0x0421	/* OCT US101 USB to RS-232 */
+
+/*
+ * Definitions for Icom Inc. devices
+ */
+#define ICOM_VID		0x0C26 /* Icom vendor ID */
+/* Note: ID-1 is a communications tranceiver for HAM-radio operators */
+#define ICOM_ID_1_PID		0x0004 /* ID-1 USB to RS-232 */
+/* Note: OPC is an Optional cable to connect an Icom Tranceiver */
+#define ICOM_OPC_U_UC_PID	0x0018 /* OPC-478UC, OPC-1122U cloning cable */
+/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */
+#define ICOM_ID_RP2C1_PID	0x0009 /* ID-RP2C Asset 1 to RS-232 */
+#define ICOM_ID_RP2C2_PID	0x000A /* ID-RP2C Asset 2 to RS-232 */
+#define ICOM_ID_RP2D_PID	0x000B /* ID-RP2D configuration port*/
+#define ICOM_ID_RP2VT_PID	0x000C /* ID-RP2V Transmit config port */
+#define ICOM_ID_RP2VR_PID	0x000D /* ID-RP2V Receive config port */
+#define ICOM_ID_RP4KVT_PID	0x0010 /* ID-RP4000V Transmit config port */
+#define ICOM_ID_RP4KVR_PID	0x0011 /* ID-RP4000V Receive config port */
+#define ICOM_ID_RP2KVT_PID	0x0012 /* ID-RP2000V Transmit config port */
+#define ICOM_ID_RP2KVR_PID	0x0013 /* ID-RP2000V Receive config port */
+
+/*
+ * GN Otometrics (http://www.otometrics.com)
+ * Submitted by Ville Sundberg.
+ */
+#define GN_OTOMETRICS_VID	0x0c33	/* Vendor ID */
+#define AURICAL_USB_PID		0x0010	/* Aurical USB Audiometer */
+
+/*
+ * The following are the values for the Sealevel SeaLINK+ adapters.
+ * (Original list sent by Tuan Hoang.  Ian Abbott renamed the macros and
+ * removed some PIDs that don't seem to match any existing products.)
+ */
+#define SEALEVEL_VID		0x0c52	/* Sealevel Vendor ID */
+#define SEALEVEL_2101_PID	0x2101	/* SeaLINK+232 (2101/2105) */
+#define SEALEVEL_2102_PID	0x2102	/* SeaLINK+485 (2102) */
+#define SEALEVEL_2103_PID	0x2103	/* SeaLINK+232I (2103) */
+#define SEALEVEL_2104_PID	0x2104	/* SeaLINK+485I (2104) */
+#define SEALEVEL_2106_PID	0x9020	/* SeaLINK+422 (2106) */
+#define SEALEVEL_2201_1_PID	0x2211	/* SeaPORT+2/232 (2201) Port 1 */
+#define SEALEVEL_2201_2_PID	0x2221	/* SeaPORT+2/232 (2201) Port 2 */
+#define SEALEVEL_2202_1_PID	0x2212	/* SeaPORT+2/485 (2202) Port 1 */
+#define SEALEVEL_2202_2_PID	0x2222	/* SeaPORT+2/485 (2202) Port 2 */
+#define SEALEVEL_2203_1_PID	0x2213	/* SeaPORT+2 (2203) Port 1 */
+#define SEALEVEL_2203_2_PID	0x2223	/* SeaPORT+2 (2203) Port 2 */
+#define SEALEVEL_2401_1_PID	0x2411	/* SeaPORT+4/232 (2401) Port 1 */
+#define SEALEVEL_2401_2_PID	0x2421	/* SeaPORT+4/232 (2401) Port 2 */
+#define SEALEVEL_2401_3_PID	0x2431	/* SeaPORT+4/232 (2401) Port 3 */
+#define SEALEVEL_2401_4_PID	0x2441	/* SeaPORT+4/232 (2401) Port 4 */
+#define SEALEVEL_2402_1_PID	0x2412	/* SeaPORT+4/485 (2402) Port 1 */
+#define SEALEVEL_2402_2_PID	0x2422	/* SeaPORT+4/485 (2402) Port 2 */
+#define SEALEVEL_2402_3_PID	0x2432	/* SeaPORT+4/485 (2402) Port 3 */
+#define SEALEVEL_2402_4_PID	0x2442	/* SeaPORT+4/485 (2402) Port 4 */
+#define SEALEVEL_2403_1_PID	0x2413	/* SeaPORT+4 (2403) Port 1 */
+#define SEALEVEL_2403_2_PID	0x2423	/* SeaPORT+4 (2403) Port 2 */
+#define SEALEVEL_2403_3_PID	0x2433	/* SeaPORT+4 (2403) Port 3 */
+#define SEALEVEL_2403_4_PID	0x2443	/* SeaPORT+4 (2403) Port 4 */
+#define SEALEVEL_2801_1_PID	0X2811	/* SeaLINK+8/232 (2801) Port 1 */
+#define SEALEVEL_2801_2_PID	0X2821	/* SeaLINK+8/232 (2801) Port 2 */
+#define SEALEVEL_2801_3_PID	0X2831	/* SeaLINK+8/232 (2801) Port 3 */
+#define SEALEVEL_2801_4_PID	0X2841	/* SeaLINK+8/232 (2801) Port 4 */
+#define SEALEVEL_2801_5_PID	0X2851	/* SeaLINK+8/232 (2801) Port 5 */
+#define SEALEVEL_2801_6_PID	0X2861	/* SeaLINK+8/232 (2801) Port 6 */
+#define SEALEVEL_2801_7_PID	0X2871	/* SeaLINK+8/232 (2801) Port 7 */
+#define SEALEVEL_2801_8_PID	0X2881	/* SeaLINK+8/232 (2801) Port 8 */
+#define SEALEVEL_2802_1_PID	0X2812	/* SeaLINK+8/485 (2802) Port 1 */
+#define SEALEVEL_2802_2_PID	0X2822	/* SeaLINK+8/485 (2802) Port 2 */
+#define SEALEVEL_2802_3_PID	0X2832	/* SeaLINK+8/485 (2802) Port 3 */
+#define SEALEVEL_2802_4_PID	0X2842	/* SeaLINK+8/485 (2802) Port 4 */
+#define SEALEVEL_2802_5_PID	0X2852	/* SeaLINK+8/485 (2802) Port 5 */
+#define SEALEVEL_2802_6_PID	0X2862	/* SeaLINK+8/485 (2802) Port 6 */
+#define SEALEVEL_2802_7_PID	0X2872	/* SeaLINK+8/485 (2802) Port 7 */
+#define SEALEVEL_2802_8_PID	0X2882	/* SeaLINK+8/485 (2802) Port 8 */
+#define SEALEVEL_2803_1_PID	0X2813	/* SeaLINK+8 (2803) Port 1 */
+#define SEALEVEL_2803_2_PID	0X2823 	/* SeaLINK+8 (2803) Port 2 */
+#define SEALEVEL_2803_3_PID	0X2833 	/* SeaLINK+8 (2803) Port 3 */
+#define SEALEVEL_2803_4_PID	0X2843 	/* SeaLINK+8 (2803) Port 4 */
+#define SEALEVEL_2803_5_PID	0X2853 	/* SeaLINK+8 (2803) Port 5 */
+#define SEALEVEL_2803_6_PID	0X2863 	/* SeaLINK+8 (2803) Port 6 */
+#define SEALEVEL_2803_7_PID	0X2873 	/* SeaLINK+8 (2803) Port 7 */
+#define SEALEVEL_2803_8_PID	0X2883 	/* SeaLINK+8 (2803) Port 8 */
+
+/*
+ * JETI SPECTROMETER SPECBOS 1201
+ * http://www.jeti.com/products/sys/scb/scb1201.php
+ */
+#define JETI_VID		0x0c6c
+#define JETI_SPC1201_PID	0x04b2
+
+/*
+ * FTDI USB UART chips used in construction projects from the
+ * Elektor Electronics magazine (http://elektor-electronics.co.uk)
+ */
+#define ELEKTOR_VID		0x0C7D
+#define ELEKTOR_FT323R_PID	0x0005	/* RFID-Reader, issue 09-2006 */
+
+/*
+ * Posiflex inc retail equipment (http://www.posiflex.com.tw)
+ */
+#define POSIFLEX_VID		0x0d3a  /* Vendor ID */
+#define POSIFLEX_PP7000_PID	0x0300  /* PP-7000II thermal printer */
+
+/*
+ * The following are the values for two KOBIL chipcard terminals.
+ */
+#define KOBIL_VID		0x0d46	/* KOBIL Vendor ID */
+#define KOBIL_CONV_B1_PID	0x2020	/* KOBIL Konverter for B1 */
+#define KOBIL_CONV_KAAN_PID	0x2021	/* KOBIL_Konverter for KAAN */
+
+#define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
+#define FTDI_NF_RIC_PID	0x0001	/* Product Id */
+
+/*
+ * Falcom Wireless Communications GmbH
+ */
+#define FALCOM_VID		0x0F94	/* Vendor Id */
+#define FALCOM_TWIST_PID	0x0001	/* Falcom Twist USB GPRS modem */
+#define FALCOM_SAMBA_PID	0x0005	/* Falcom Samba USB GPRS modem */
+
+/* Larsen and Brusgaard AltiTrack/USBtrack  */
+#define LARSENBRUSGAARD_VID		0x0FD8
+#define LB_ALTITRACK_PID		0x0001
+
+/*
+ * TTi (Thurlby Thandar Instruments)
+ */
+#define TTI_VID			0x103E	/* Vendor Id */
+#define TTI_QL355P_PID		0x03E8	/* TTi QL355P power supply */
+
+/* Interbiometrics USB I/O Board */
+/* Developed for Interbiometrics by Rudolf Gugler */
+#define INTERBIOMETRICS_VID              0x1209
+#define INTERBIOMETRICS_IOBOARD_PID      0x1002
+#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006
+
+/*
+ * Testo products (http://www.testo.com/)
+ * Submitted by Colin Leroy
+ */
+#define TESTO_VID			0x128D
+#define TESTO_USB_INTERFACE_PID		0x0001
+
+/*
+ * Mobility Electronics products.
+ */
+#define MOBILITY_VID			0x1342
+#define MOBILITY_USB_SERIAL_PID		0x0202	/* EasiDock USB 200 serial */
+
+/*
+ * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
+ * Submitted by Harald Welte <laforge@openmoko.org>
+ */
+#define	FIC_VID			0x1457
+#define	FIC_NEO1973_DEBUG_PID	0x5118
+
+/* Olimex */
+#define OLIMEX_VID			0x15BA
+#define OLIMEX_ARM_USB_OCD_PID		0x0003
+
+/*
+ * Telldus Technologies
+ */
+#define TELLDUS_VID			0x1781	/* Vendor ID */
+#define TELLDUS_TELLSTICK_PID		0x0C30	/* RF control dongle 433 MHz using FT232RL */
+
+/*
+ * RT Systems programming cables for various ham radios
+ */
+#define RTSYSTEMS_VID			0x2100	/* Vendor ID */
+#define RTSYSTEMS_SERIAL_VX7_PID	0x9e52	/* Serial converter for VX-7 Radios using FT232RL */
+#define RTSYSTEMS_CT29B_PID		0x9e54	/* CT29B Radio Cable */
+
+/*
+ * Bayer Ascensia Contour blood glucose meter USB-converter cable.
+ * http://winglucofacts.com/cables/
+ */
+#define BAYER_VID                      0x1A79
+#define BAYER_CONTOUR_CABLE_PID        0x6001
+
+/*
+ * The following are the values for the Matrix Orbital FTDI Range
+ * Anything in this range will use an FT232RL.
+ */
+#define MTXORB_VID			0x1B3D
+#define MTXORB_FTDI_RANGE_0100_PID	0x0100
+#define MTXORB_FTDI_RANGE_0101_PID	0x0101
+#define MTXORB_FTDI_RANGE_0102_PID	0x0102
+#define MTXORB_FTDI_RANGE_0103_PID	0x0103
+#define MTXORB_FTDI_RANGE_0104_PID	0x0104
+#define MTXORB_FTDI_RANGE_0105_PID	0x0105
+#define MTXORB_FTDI_RANGE_0106_PID	0x0106
+#define MTXORB_FTDI_RANGE_0107_PID	0x0107
+#define MTXORB_FTDI_RANGE_0108_PID	0x0108
+#define MTXORB_FTDI_RANGE_0109_PID	0x0109
+#define MTXORB_FTDI_RANGE_010A_PID	0x010A
+#define MTXORB_FTDI_RANGE_010B_PID	0x010B
+#define MTXORB_FTDI_RANGE_010C_PID	0x010C
+#define MTXORB_FTDI_RANGE_010D_PID	0x010D
+#define MTXORB_FTDI_RANGE_010E_PID	0x010E
+#define MTXORB_FTDI_RANGE_010F_PID	0x010F
+#define MTXORB_FTDI_RANGE_0110_PID	0x0110
+#define MTXORB_FTDI_RANGE_0111_PID	0x0111
+#define MTXORB_FTDI_RANGE_0112_PID	0x0112
+#define MTXORB_FTDI_RANGE_0113_PID	0x0113
+#define MTXORB_FTDI_RANGE_0114_PID	0x0114
+#define MTXORB_FTDI_RANGE_0115_PID	0x0115
+#define MTXORB_FTDI_RANGE_0116_PID	0x0116
+#define MTXORB_FTDI_RANGE_0117_PID	0x0117
+#define MTXORB_FTDI_RANGE_0118_PID	0x0118
+#define MTXORB_FTDI_RANGE_0119_PID	0x0119
+#define MTXORB_FTDI_RANGE_011A_PID	0x011A
+#define MTXORB_FTDI_RANGE_011B_PID	0x011B
+#define MTXORB_FTDI_RANGE_011C_PID	0x011C
+#define MTXORB_FTDI_RANGE_011D_PID	0x011D
+#define MTXORB_FTDI_RANGE_011E_PID	0x011E
+#define MTXORB_FTDI_RANGE_011F_PID	0x011F
+#define MTXORB_FTDI_RANGE_0120_PID	0x0120
+#define MTXORB_FTDI_RANGE_0121_PID	0x0121
+#define MTXORB_FTDI_RANGE_0122_PID	0x0122
+#define MTXORB_FTDI_RANGE_0123_PID	0x0123
+#define MTXORB_FTDI_RANGE_0124_PID	0x0124
+#define MTXORB_FTDI_RANGE_0125_PID	0x0125
+#define MTXORB_FTDI_RANGE_0126_PID	0x0126
+#define MTXORB_FTDI_RANGE_0127_PID	0x0127
+#define MTXORB_FTDI_RANGE_0128_PID	0x0128
+#define MTXORB_FTDI_RANGE_0129_PID	0x0129
+#define MTXORB_FTDI_RANGE_012A_PID	0x012A
+#define MTXORB_FTDI_RANGE_012B_PID	0x012B
+#define MTXORB_FTDI_RANGE_012C_PID	0x012C
+#define MTXORB_FTDI_RANGE_012D_PID	0x012D
+#define MTXORB_FTDI_RANGE_012E_PID	0x012E
+#define MTXORB_FTDI_RANGE_012F_PID	0x012F
+#define MTXORB_FTDI_RANGE_0130_PID	0x0130
+#define MTXORB_FTDI_RANGE_0131_PID	0x0131
+#define MTXORB_FTDI_RANGE_0132_PID	0x0132
+#define MTXORB_FTDI_RANGE_0133_PID	0x0133
+#define MTXORB_FTDI_RANGE_0134_PID	0x0134
+#define MTXORB_FTDI_RANGE_0135_PID	0x0135
+#define MTXORB_FTDI_RANGE_0136_PID	0x0136
+#define MTXORB_FTDI_RANGE_0137_PID	0x0137
+#define MTXORB_FTDI_RANGE_0138_PID	0x0138
+#define MTXORB_FTDI_RANGE_0139_PID	0x0139
+#define MTXORB_FTDI_RANGE_013A_PID	0x013A
+#define MTXORB_FTDI_RANGE_013B_PID	0x013B
+#define MTXORB_FTDI_RANGE_013C_PID	0x013C
+#define MTXORB_FTDI_RANGE_013D_PID	0x013D
+#define MTXORB_FTDI_RANGE_013E_PID	0x013E
+#define MTXORB_FTDI_RANGE_013F_PID	0x013F
+#define MTXORB_FTDI_RANGE_0140_PID	0x0140
+#define MTXORB_FTDI_RANGE_0141_PID	0x0141
+#define MTXORB_FTDI_RANGE_0142_PID	0x0142
+#define MTXORB_FTDI_RANGE_0143_PID	0x0143
+#define MTXORB_FTDI_RANGE_0144_PID	0x0144
+#define MTXORB_FTDI_RANGE_0145_PID	0x0145
+#define MTXORB_FTDI_RANGE_0146_PID	0x0146
+#define MTXORB_FTDI_RANGE_0147_PID	0x0147
+#define MTXORB_FTDI_RANGE_0148_PID	0x0148
+#define MTXORB_FTDI_RANGE_0149_PID	0x0149
+#define MTXORB_FTDI_RANGE_014A_PID	0x014A
+#define MTXORB_FTDI_RANGE_014B_PID	0x014B
+#define MTXORB_FTDI_RANGE_014C_PID	0x014C
+#define MTXORB_FTDI_RANGE_014D_PID	0x014D
+#define MTXORB_FTDI_RANGE_014E_PID	0x014E
+#define MTXORB_FTDI_RANGE_014F_PID	0x014F
+#define MTXORB_FTDI_RANGE_0150_PID	0x0150
+#define MTXORB_FTDI_RANGE_0151_PID	0x0151
+#define MTXORB_FTDI_RANGE_0152_PID	0x0152
+#define MTXORB_FTDI_RANGE_0153_PID	0x0153
+#define MTXORB_FTDI_RANGE_0154_PID	0x0154
+#define MTXORB_FTDI_RANGE_0155_PID	0x0155
+#define MTXORB_FTDI_RANGE_0156_PID	0x0156
+#define MTXORB_FTDI_RANGE_0157_PID	0x0157
+#define MTXORB_FTDI_RANGE_0158_PID	0x0158
+#define MTXORB_FTDI_RANGE_0159_PID	0x0159
+#define MTXORB_FTDI_RANGE_015A_PID	0x015A
+#define MTXORB_FTDI_RANGE_015B_PID	0x015B
+#define MTXORB_FTDI_RANGE_015C_PID	0x015C
+#define MTXORB_FTDI_RANGE_015D_PID	0x015D
+#define MTXORB_FTDI_RANGE_015E_PID	0x015E
+#define MTXORB_FTDI_RANGE_015F_PID	0x015F
+#define MTXORB_FTDI_RANGE_0160_PID	0x0160
+#define MTXORB_FTDI_RANGE_0161_PID	0x0161
+#define MTXORB_FTDI_RANGE_0162_PID	0x0162
+#define MTXORB_FTDI_RANGE_0163_PID	0x0163
+#define MTXORB_FTDI_RANGE_0164_PID	0x0164
+#define MTXORB_FTDI_RANGE_0165_PID	0x0165
+#define MTXORB_FTDI_RANGE_0166_PID	0x0166
+#define MTXORB_FTDI_RANGE_0167_PID	0x0167
+#define MTXORB_FTDI_RANGE_0168_PID	0x0168
+#define MTXORB_FTDI_RANGE_0169_PID	0x0169
+#define MTXORB_FTDI_RANGE_016A_PID	0x016A
+#define MTXORB_FTDI_RANGE_016B_PID	0x016B
+#define MTXORB_FTDI_RANGE_016C_PID	0x016C
+#define MTXORB_FTDI_RANGE_016D_PID	0x016D
+#define MTXORB_FTDI_RANGE_016E_PID	0x016E
+#define MTXORB_FTDI_RANGE_016F_PID	0x016F
+#define MTXORB_FTDI_RANGE_0170_PID	0x0170
+#define MTXORB_FTDI_RANGE_0171_PID	0x0171
+#define MTXORB_FTDI_RANGE_0172_PID	0x0172
+#define MTXORB_FTDI_RANGE_0173_PID	0x0173
+#define MTXORB_FTDI_RANGE_0174_PID	0x0174
+#define MTXORB_FTDI_RANGE_0175_PID	0x0175
+#define MTXORB_FTDI_RANGE_0176_PID	0x0176
+#define MTXORB_FTDI_RANGE_0177_PID	0x0177
+#define MTXORB_FTDI_RANGE_0178_PID	0x0178
+#define MTXORB_FTDI_RANGE_0179_PID	0x0179
+#define MTXORB_FTDI_RANGE_017A_PID	0x017A
+#define MTXORB_FTDI_RANGE_017B_PID	0x017B
+#define MTXORB_FTDI_RANGE_017C_PID	0x017C
+#define MTXORB_FTDI_RANGE_017D_PID	0x017D
+#define MTXORB_FTDI_RANGE_017E_PID	0x017E
+#define MTXORB_FTDI_RANGE_017F_PID	0x017F
+#define MTXORB_FTDI_RANGE_0180_PID	0x0180
+#define MTXORB_FTDI_RANGE_0181_PID	0x0181
+#define MTXORB_FTDI_RANGE_0182_PID	0x0182
+#define MTXORB_FTDI_RANGE_0183_PID	0x0183
+#define MTXORB_FTDI_RANGE_0184_PID	0x0184
+#define MTXORB_FTDI_RANGE_0185_PID	0x0185
+#define MTXORB_FTDI_RANGE_0186_PID	0x0186
+#define MTXORB_FTDI_RANGE_0187_PID	0x0187
+#define MTXORB_FTDI_RANGE_0188_PID	0x0188
+#define MTXORB_FTDI_RANGE_0189_PID	0x0189
+#define MTXORB_FTDI_RANGE_018A_PID	0x018A
+#define MTXORB_FTDI_RANGE_018B_PID	0x018B
+#define MTXORB_FTDI_RANGE_018C_PID	0x018C
+#define MTXORB_FTDI_RANGE_018D_PID	0x018D
+#define MTXORB_FTDI_RANGE_018E_PID	0x018E
+#define MTXORB_FTDI_RANGE_018F_PID	0x018F
+#define MTXORB_FTDI_RANGE_0190_PID	0x0190
+#define MTXORB_FTDI_RANGE_0191_PID	0x0191
+#define MTXORB_FTDI_RANGE_0192_PID	0x0192
+#define MTXORB_FTDI_RANGE_0193_PID	0x0193
+#define MTXORB_FTDI_RANGE_0194_PID	0x0194
+#define MTXORB_FTDI_RANGE_0195_PID	0x0195
+#define MTXORB_FTDI_RANGE_0196_PID	0x0196
+#define MTXORB_FTDI_RANGE_0197_PID	0x0197
+#define MTXORB_FTDI_RANGE_0198_PID	0x0198
+#define MTXORB_FTDI_RANGE_0199_PID	0x0199
+#define MTXORB_FTDI_RANGE_019A_PID	0x019A
+#define MTXORB_FTDI_RANGE_019B_PID	0x019B
+#define MTXORB_FTDI_RANGE_019C_PID	0x019C
+#define MTXORB_FTDI_RANGE_019D_PID	0x019D
+#define MTXORB_FTDI_RANGE_019E_PID	0x019E
+#define MTXORB_FTDI_RANGE_019F_PID	0x019F
+#define MTXORB_FTDI_RANGE_01A0_PID	0x01A0
+#define MTXORB_FTDI_RANGE_01A1_PID	0x01A1
+#define MTXORB_FTDI_RANGE_01A2_PID	0x01A2
+#define MTXORB_FTDI_RANGE_01A3_PID	0x01A3
+#define MTXORB_FTDI_RANGE_01A4_PID	0x01A4
+#define MTXORB_FTDI_RANGE_01A5_PID	0x01A5
+#define MTXORB_FTDI_RANGE_01A6_PID	0x01A6
+#define MTXORB_FTDI_RANGE_01A7_PID	0x01A7
+#define MTXORB_FTDI_RANGE_01A8_PID	0x01A8
+#define MTXORB_FTDI_RANGE_01A9_PID	0x01A9
+#define MTXORB_FTDI_RANGE_01AA_PID	0x01AA
+#define MTXORB_FTDI_RANGE_01AB_PID	0x01AB
+#define MTXORB_FTDI_RANGE_01AC_PID	0x01AC
+#define MTXORB_FTDI_RANGE_01AD_PID	0x01AD
+#define MTXORB_FTDI_RANGE_01AE_PID	0x01AE
+#define MTXORB_FTDI_RANGE_01AF_PID	0x01AF
+#define MTXORB_FTDI_RANGE_01B0_PID	0x01B0
+#define MTXORB_FTDI_RANGE_01B1_PID	0x01B1
+#define MTXORB_FTDI_RANGE_01B2_PID	0x01B2
+#define MTXORB_FTDI_RANGE_01B3_PID	0x01B3
+#define MTXORB_FTDI_RANGE_01B4_PID	0x01B4
+#define MTXORB_FTDI_RANGE_01B5_PID	0x01B5
+#define MTXORB_FTDI_RANGE_01B6_PID	0x01B6
+#define MTXORB_FTDI_RANGE_01B7_PID	0x01B7
+#define MTXORB_FTDI_RANGE_01B8_PID	0x01B8
+#define MTXORB_FTDI_RANGE_01B9_PID	0x01B9
+#define MTXORB_FTDI_RANGE_01BA_PID	0x01BA
+#define MTXORB_FTDI_RANGE_01BB_PID	0x01BB
+#define MTXORB_FTDI_RANGE_01BC_PID	0x01BC
+#define MTXORB_FTDI_RANGE_01BD_PID	0x01BD
+#define MTXORB_FTDI_RANGE_01BE_PID	0x01BE
+#define MTXORB_FTDI_RANGE_01BF_PID	0x01BF
+#define MTXORB_FTDI_RANGE_01C0_PID	0x01C0
+#define MTXORB_FTDI_RANGE_01C1_PID	0x01C1
+#define MTXORB_FTDI_RANGE_01C2_PID	0x01C2
+#define MTXORB_FTDI_RANGE_01C3_PID	0x01C3
+#define MTXORB_FTDI_RANGE_01C4_PID	0x01C4
+#define MTXORB_FTDI_RANGE_01C5_PID	0x01C5
+#define MTXORB_FTDI_RANGE_01C6_PID	0x01C6
+#define MTXORB_FTDI_RANGE_01C7_PID	0x01C7
+#define MTXORB_FTDI_RANGE_01C8_PID	0x01C8
+#define MTXORB_FTDI_RANGE_01C9_PID	0x01C9
+#define MTXORB_FTDI_RANGE_01CA_PID	0x01CA
+#define MTXORB_FTDI_RANGE_01CB_PID	0x01CB
+#define MTXORB_FTDI_RANGE_01CC_PID	0x01CC
+#define MTXORB_FTDI_RANGE_01CD_PID	0x01CD
+#define MTXORB_FTDI_RANGE_01CE_PID	0x01CE
+#define MTXORB_FTDI_RANGE_01CF_PID	0x01CF
+#define MTXORB_FTDI_RANGE_01D0_PID	0x01D0
+#define MTXORB_FTDI_RANGE_01D1_PID	0x01D1
+#define MTXORB_FTDI_RANGE_01D2_PID	0x01D2
+#define MTXORB_FTDI_RANGE_01D3_PID	0x01D3
+#define MTXORB_FTDI_RANGE_01D4_PID	0x01D4
+#define MTXORB_FTDI_RANGE_01D5_PID	0x01D5
+#define MTXORB_FTDI_RANGE_01D6_PID	0x01D6
+#define MTXORB_FTDI_RANGE_01D7_PID	0x01D7
+#define MTXORB_FTDI_RANGE_01D8_PID	0x01D8
+#define MTXORB_FTDI_RANGE_01D9_PID	0x01D9
+#define MTXORB_FTDI_RANGE_01DA_PID	0x01DA
+#define MTXORB_FTDI_RANGE_01DB_PID	0x01DB
+#define MTXORB_FTDI_RANGE_01DC_PID	0x01DC
+#define MTXORB_FTDI_RANGE_01DD_PID	0x01DD
+#define MTXORB_FTDI_RANGE_01DE_PID	0x01DE
+#define MTXORB_FTDI_RANGE_01DF_PID	0x01DF
+#define MTXORB_FTDI_RANGE_01E0_PID	0x01E0
+#define MTXORB_FTDI_RANGE_01E1_PID	0x01E1
+#define MTXORB_FTDI_RANGE_01E2_PID	0x01E2
+#define MTXORB_FTDI_RANGE_01E3_PID	0x01E3
+#define MTXORB_FTDI_RANGE_01E4_PID	0x01E4
+#define MTXORB_FTDI_RANGE_01E5_PID	0x01E5
+#define MTXORB_FTDI_RANGE_01E6_PID	0x01E6
+#define MTXORB_FTDI_RANGE_01E7_PID	0x01E7
+#define MTXORB_FTDI_RANGE_01E8_PID	0x01E8
+#define MTXORB_FTDI_RANGE_01E9_PID	0x01E9
+#define MTXORB_FTDI_RANGE_01EA_PID	0x01EA
+#define MTXORB_FTDI_RANGE_01EB_PID	0x01EB
+#define MTXORB_FTDI_RANGE_01EC_PID	0x01EC
+#define MTXORB_FTDI_RANGE_01ED_PID	0x01ED
+#define MTXORB_FTDI_RANGE_01EE_PID	0x01EE
+#define MTXORB_FTDI_RANGE_01EF_PID	0x01EF
+#define MTXORB_FTDI_RANGE_01F0_PID	0x01F0
+#define MTXORB_FTDI_RANGE_01F1_PID	0x01F1
+#define MTXORB_FTDI_RANGE_01F2_PID	0x01F2
+#define MTXORB_FTDI_RANGE_01F3_PID	0x01F3
+#define MTXORB_FTDI_RANGE_01F4_PID	0x01F4
+#define MTXORB_FTDI_RANGE_01F5_PID	0x01F5
+#define MTXORB_FTDI_RANGE_01F6_PID	0x01F6
+#define MTXORB_FTDI_RANGE_01F7_PID	0x01F7
+#define MTXORB_FTDI_RANGE_01F8_PID	0x01F8
+#define MTXORB_FTDI_RANGE_01F9_PID	0x01F9
+#define MTXORB_FTDI_RANGE_01FA_PID	0x01FA
+#define MTXORB_FTDI_RANGE_01FB_PID	0x01FB
+#define MTXORB_FTDI_RANGE_01FC_PID	0x01FC
+#define MTXORB_FTDI_RANGE_01FD_PID	0x01FD
+#define MTXORB_FTDI_RANGE_01FE_PID	0x01FE
+#define MTXORB_FTDI_RANGE_01FF_PID	0x01FF
+
+
+
+/*
+ * The Mobility Lab (TML)
+ * Submitted by Pierre Castella
+ */
+#define TML_VID			0x1B91	/* Vendor ID */
+#define TML_USB_SERIAL_PID	0x0064	/* USB - Serial Converter */
+
+/* Alti-2 products  http://www.alti-2.com */
+#define ALTI2_VID	0x1BC9
+#define ALTI2_N3_PID	0x6001	/* Neptune 3 */
+
+/*
+ * Ionics PlugComputer
+ */
+#define IONICS_VID			0x1c0c
+#define IONICS_PLUGCOMPUTER_PID		0x0102
+
+/*
+ * Dresden Elektronic Sensor Terminal Board
+ */
+#define DE_VID			0x1cf1 /* Vendor ID */
+#define STB_PID			0x0001 /* Sensor Terminal Board */
+#define WHT_PID			0x0004 /* Wireless Handheld Terminal */
+
+/*
+ * STMicroelectonics
+ */
+#define ST_VID			0x0483
+#define ST_STMCLT1030_PID	0x3747 /* ST Micro Connect Lite STMCLT1030 */
+
+/*
+ * Papouch products (http://www.papouch.com/)
+ * Submitted by Folkert van Heusden
+ */
+
+#define PAPOUCH_VID			0x5050	/* Vendor ID */
+#define PAPOUCH_SB485_PID		0x0100	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_PID		0x0101	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_PID		0x0102	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485_2_PID		0x0103	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_2_PID		0x0104	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_2_PID		0x0105	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485S_PID		0x0106	/* Papouch SB485S USB-485/422 Converter */
+#define PAPOUCH_SB485C_PID		0x0107	/* Papouch SB485C USB-485/422 Converter */
+#define PAPOUCH_LEC_PID			0x0300	/* LEC USB Converter */
+#define PAPOUCH_SB232_PID		0x0301	/* Papouch SB232 USB-RS232 Converter */
+#define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
+#define PAPOUCH_IRAMP_PID		0x0500	/* Papouch IRAmp Duplex */
+#define PAPOUCH_DRAK5_PID		0x0700	/* Papouch DRAK5 */
+#define PAPOUCH_QUIDO8x8_PID		0x0800	/* Papouch Quido 8/8 Module */
+#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Papouch Quido 4/4 Module */
+#define PAPOUCH_QUIDO2x2_PID		0x0a00	/* Papouch Quido 2/2 Module */
+#define PAPOUCH_QUIDO10x1_PID		0x0b00	/* Papouch Quido 10/1 Module */
+#define PAPOUCH_QUIDO30x3_PID		0x0c00	/* Papouch Quido 30/3 Module */
+#define PAPOUCH_QUIDO60x3_PID		0x0d00	/* Papouch Quido 60(100)/3 Module */
+#define PAPOUCH_QUIDO2x16_PID		0x0e00	/* Papouch Quido 2/16 Module */
+#define PAPOUCH_QUIDO3x32_PID		0x0f00	/* Papouch Quido 3/32 Module */
+#define PAPOUCH_DRAK6_PID		0x1000	/* Papouch DRAK6 */
+#define PAPOUCH_UPSUSB_PID		0x8000	/* Papouch UPS-USB adapter */
+#define PAPOUCH_MU_PID			0x8001	/* MU controller */
+#define PAPOUCH_SIMUKEY_PID		0x8002	/* Papouch SimuKey */
+#define PAPOUCH_AD4USB_PID		0x8003	/* AD4USB Measurement Module */
+#define PAPOUCH_GMUX_PID		0x8004	/* Papouch GOLIATH MUX */
+#define PAPOUCH_GMSR_PID		0x8005	/* Papouch GOLIATH MSR */
+
+/*
+ * Marvell SheevaPlug
+ */
+#define MARVELL_VID		0x9e88
+#define MARVELL_SHEEVAPLUG_PID	0x9e8f
+
+/*
+ * Evolution Robotics products (http://www.evolution.com/).
+ * Submitted by Shawn M. Lavelle.
+ */
+#define EVOLUTION_VID		0xDEEE	/* Vendor ID */
+#define EVOLUTION_ER1_PID	0x0300	/* ER1 Control Module */
+#define EVO_8U232AM_PID	0x02FF	/* Evolution robotics RCM2 (FT232AM)*/
+#define EVO_HYBRID_PID		0x0302	/* Evolution robotics RCM4 PID (FT232BM)*/
+#define EVO_RCM4_PID		0x0303	/* Evolution robotics RCM4 PID */
+
+/*
+ * MJS Gadgets HD Radio / XM Radio / Sirius Radio interfaces (using VID 0x0403)
+ */
+#define MJSG_GENERIC_PID	0x9378
+#define MJSG_SR_RADIO_PID	0x9379
+#define MJSG_XM_RADIO_PID	0x937A
+#define MJSG_HD_RADIO_PID	0x937C
+
+/*
+ * D.O.Tec products (http://www.directout.eu)
+ */
+#define FTDI_DOTEC_PID 0x9868
+
+/*
+ * Xverve Signalyzer tools (http://www.signalyzer.com/)
+ */
+#define XVERVE_SIGNALYZER_ST_PID	0xBCA0
+#define XVERVE_SIGNALYZER_SLITE_PID	0xBCA1
+#define XVERVE_SIGNALYZER_SH2_PID	0xBCA2
+#define XVERVE_SIGNALYZER_SH4_PID	0xBCA4
+
+/*
+ * Segway Robotic Mobility Platform USB interface (using VID 0x0403)
+ * Submitted by John G. Rogers
+ */
+#define SEGWAY_RMP200_PID	0xe729
+
+
+/*
+ * Accesio USB Data Acquisition products (http://www.accesio.com/)
+ */
+#define ACCESIO_COM4SM_PID 	0xD578
+
+/* www.sciencescope.co.uk educational dataloggers */
+#define FTDI_SCIENCESCOPE_LOGBOOKML_PID		0xFF18
+#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID	0xFF1C
+#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID	0xFF1D
+
+/*
+ * Milkymist One JTAG/Serial
+ */
+#define QIHARDWARE_VID			0x20B7
+#define MILKYMISTONE_JTAGSERIAL_PID	0x0713
+
+/*
+ * CTI GmbH RS485 Converter http://www.cti-lean.com/
+ */
+/* USB-485-Mini*/
+#define FTDI_CTI_MINI_PID	0xF608
+/* USB-Nano-485*/
+#define FTDI_CTI_NANO_PID	0xF60B
+
+
--- linux-ec2-2.6.32.orig/drivers/usb/serial/navman.c
+++ linux-ec2-2.6.32/drivers/usb/serial/navman.c
@@ -24,6 +24,7 @@
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0a99, 0x0001) },	/* Talon Technology device */
+	{ USB_DEVICE(0x0df7, 0x0900) },	/* Mobile Action i-gotU */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
--- linux-ec2-2.6.32.orig/drivers/usb/serial/option.c
+++ linux-ec2-2.6.32/drivers/usb/serial/option.c
@@ -165,7 +165,10 @@
 #define HUAWEI_PRODUCT_E143D			0x143D
 #define HUAWEI_PRODUCT_E143E			0x143E
 #define HUAWEI_PRODUCT_E143F			0x143F
+#define HUAWEI_PRODUCT_K4505			0x1464
+#define HUAWEI_PRODUCT_K3765			0x1465
 #define HUAWEI_PRODUCT_E14AC			0x14AC
+#define HUAWEI_PRODUCT_ETS1220			0x1803
 
 #define QUANTA_VENDOR_ID			0x0408
 #define QUANTA_PRODUCT_Q101			0xEA02
@@ -225,7 +228,9 @@
 #define AMOI_VENDOR_ID				0x1614
 #define AMOI_PRODUCT_H01			0x0800
 #define AMOI_PRODUCT_H01A			0x7002
+#define AMOI_PRODUCT_9508			0x0800
 #define AMOI_PRODUCT_H02			0x0802
+#define AMOI_PRODUCT_SKYPEPHONE_S2		0x0407
 
 #define DELL_VENDOR_ID				0x413C
 
@@ -283,12 +288,11 @@
 #define BANDRICH_PRODUCT_1011			0x1011
 #define BANDRICH_PRODUCT_1012			0x1012
 
-#define AMOI_VENDOR_ID			0x1614
-#define AMOI_PRODUCT_9508			0x0800
-
 #define QUALCOMM_VENDOR_ID			0x05C6
 
-#define MAXON_VENDOR_ID				0x16d8
+#define CMOTECH_VENDOR_ID			0x16d8
+#define CMOTECH_PRODUCT_6008			0x6008
+#define CMOTECH_PRODUCT_6280			0x6280
 
 #define TELIT_VENDOR_ID				0x1bc7
 #define TELIT_PRODUCT_UC864E			0x1003
@@ -314,6 +318,7 @@
 #define QISDA_PRODUCT_H21_4512			0x4512
 #define QISDA_PRODUCT_H21_4523			0x4523
 #define QISDA_PRODUCT_H20_4515			0x4515
+#define QISDA_PRODUCT_H20_4518			0x4518
 #define QISDA_PRODUCT_H20_4519			0x4519
 
 /* TLAYTECH PRODUCTS */
@@ -332,6 +337,24 @@
 #define ALCATEL_VENDOR_ID			0x1bbb
 #define ALCATEL_PRODUCT_X060S			0x0000
 
+#define PIRELLI_VENDOR_ID			0x1266
+#define PIRELLI_PRODUCT_C100_1			0x1002
+#define PIRELLI_PRODUCT_C100_2			0x1003
+#define PIRELLI_PRODUCT_1004			0x1004
+#define PIRELLI_PRODUCT_1005			0x1005
+#define PIRELLI_PRODUCT_1006			0x1006
+#define PIRELLI_PRODUCT_1007			0x1007
+#define PIRELLI_PRODUCT_1008			0x1008
+#define PIRELLI_PRODUCT_1009			0x1009
+#define PIRELLI_PRODUCT_100A			0x100a
+#define PIRELLI_PRODUCT_100B			0x100b
+#define PIRELLI_PRODUCT_100C			0x100c
+#define PIRELLI_PRODUCT_100D			0x100d
+#define PIRELLI_PRODUCT_100E			0x100e
+#define PIRELLI_PRODUCT_100F			0x100f
+#define PIRELLI_PRODUCT_1011			0x1011
+#define PIRELLI_PRODUCT_1012			0x1012
+
 /* Airplus products */
 #define AIRPLUS_VENDOR_ID			0x1011
 #define AIRPLUS_PRODUCT_MCD650			0x3198
@@ -340,6 +363,39 @@
 #define FOUR_G_SYSTEMS_VENDOR_ID		0x1c9e
 #define FOUR_G_SYSTEMS_PRODUCT_W14		0x9603
 
+/* Haier products */
+#define HAIER_VENDOR_ID				0x201e
+#define HAIER_PRODUCT_CE100			0x2009
+
+/* Cinterion (formerly Siemens) products */
+#define SIEMENS_VENDOR_ID				0x0681
+#define CINTERION_VENDOR_ID				0x1e2d
+#define CINTERION_PRODUCT_HC25_MDM		0x0047
+#define CINTERION_PRODUCT_HC25_MDMNET	0x0040
+#define CINTERION_PRODUCT_HC28_MDM		0x004C
+#define CINTERION_PRODUCT_HC28_MDMNET	0x004A /* same for HC28J */
+#define CINTERION_PRODUCT_EU3_E			0x0051
+#define CINTERION_PRODUCT_EU3_P			0x0052
+#define CINTERION_PRODUCT_PH8			0x0053
+
+/* Olivetti products */
+#define OLIVETTI_VENDOR_ID			0x0b3c
+#define OLIVETTI_PRODUCT_OLICARD100		0xc000
+
+/* Celot products */
+#define CELOT_VENDOR_ID				0x211f
+#define CELOT_PRODUCT_CT680M			0x6801
+
+/* ONDA Communication vendor id */
+#define ONDA_VENDOR_ID       0x1ee8
+
+/* ONDA MT825UP HSDPA 14.2 modem */
+#define ONDA_MT825UP         0x000b
+
+/* Samsung products */
+#define SAMSUNG_VENDOR_ID                       0x04e8
+#define SAMSUNG_PRODUCT_GT_B3730                0x6889
+
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -437,7 +493,10 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
@@ -473,6 +532,7 @@
 	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
 	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
 	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
+	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_SKYPEPHONE_S2) },
 
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD) },		/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
 	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5500_MINICARD) },		/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
@@ -516,7 +576,8 @@
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
-	{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
+	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
+	{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
@@ -538,6 +599,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
@@ -549,43 +611,269 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0079, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1060, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1061, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1062, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1063, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1064, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1065, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1066, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1067, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1068, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1069, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1070, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1071, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1072, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1073, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1074, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1075, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1076, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1077, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1078, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1079, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1080, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1081, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1082, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1083, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1084, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1085, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1086, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1087, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1088, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1089, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1090, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1091, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1092, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1093, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1094, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1095, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1096, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1097, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1098, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1099, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1100, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1101, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1102, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1103, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1104, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1105, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1106, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1107, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1108, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1109, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1110, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1111, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1112, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1113, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1114, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1115, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1116, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1117, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1118, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1119, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1120, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1121, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1122, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1123, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1124, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1125, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1126, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1127, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1128, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1129, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1130, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1131, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1132, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1133, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1134, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1135, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1136, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1137, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1138, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1139, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1140, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1142, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1143, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1144, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1145, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1146, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1147, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1148, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1149, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1150, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1151, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1152, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1153, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1154, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1155, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1156, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1157, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1158, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1159, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1160, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1161, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1162, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1163, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1164, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1165, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1166, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1167, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1168, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1260, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1261, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1262, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1263, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1264, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1265, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1266, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1274, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1275, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1276, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1277, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1278, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1279, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1280, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1281, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1282, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1283, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1284, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1285, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1286, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1287, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1288, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1289, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1290, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1291, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1292, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1293, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1294, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1295, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1296, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1297, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -595,15 +883,50 @@
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
+	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4518) },
 	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
 	{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+	{ USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
 	{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
 	{ USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
+	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
+	/* Pirelli  */
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
+	{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
+	/* Cinterion */
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
+	{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
+	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) },
+	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */
+	{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+
+	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -726,12 +1049,26 @@
 			const struct usb_device_id *id)
 {
 	struct option_intf_private *data;
+
 	/* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
 	if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
 		serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
 		serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)
 		return -ENODEV;
 
+	/* Bandrich modem and AT command interface is 0xff */
+	if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID ||
+		serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) &&
+		serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
+		return -ENODEV;
+
+	/* Don't bind network interfaces on Huawei K3765 & K4505 */
+	if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&
+		(serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 ||
+			serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) &&
+		serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+		return -ENODEV;
+
 	data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/pl2303.c
+++ linux-ec2-2.6.32/drivers/usb/serial/pl2303.c
@@ -59,6 +59,8 @@
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
+	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
+	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
 	{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
 	{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
@@ -95,6 +97,7 @@
 	{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
 	{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
 	{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
+	{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
 	{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
 	{ }					/* Terminating entry */
@@ -954,9 +957,11 @@
 {
 
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	struct tty_struct *tty;
 	unsigned long flags;
 	u8 status_idx = UART_STATE;
 	u8 length = UART_STATE + 1;
+	u8 prev_line_status;
 	u16 idv, idp;
 
 	idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
@@ -978,11 +983,20 @@
 
 	/* Save off the uart status for others to look at */
 	spin_lock_irqsave(&priv->lock, flags);
+	prev_line_status = priv->line_status;
 	priv->line_status = data[status_idx];
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (priv->line_status & UART_BREAK_ERROR)
 		usb_serial_handle_break(port);
 	wake_up_interruptible(&priv->delta_msr_wait);
+
+	tty = tty_port_tty_get(&port->port);
+	if (!tty)
+		return;
+	if ((priv->line_status ^ prev_line_status) & UART_DCD)
+		usb_serial_handle_dcd_change(port, tty,
+				priv->line_status & UART_DCD);
+	tty_kref_put(tty);
 }
 
 static void pl2303_read_int_callback(struct urb *urb)
--- linux-ec2-2.6.32.orig/drivers/usb/serial/mos7720.c
+++ linux-ec2-2.6.32/drivers/usb/serial/mos7720.c
@@ -1466,6 +1466,9 @@
 
 	case TIOCGICOUNT:
 		cnow = mos7720_port->icount;
+
+		memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
 		icount.cts = cnow.cts;
 		icount.dsr = cnow.dsr;
 		icount.rng = cnow.rng;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ch341.c
+++ linux-ec2-2.6.32/drivers/usb/serial/ch341.c
@@ -73,6 +73,7 @@
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x4348, 0x5523) },
 	{ USB_DEVICE(0x1a86, 0x7523) },
+	{ USB_DEVICE(0x1a86, 0x5523) },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -479,12 +480,22 @@
 	if (actual_length >= 4) {
 		struct ch341_private *priv = usb_get_serial_port_data(port);
 		unsigned long flags;
+		u8 prev_line_status = priv->line_status;
 
 		spin_lock_irqsave(&priv->lock, flags);
 		priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
 		if ((data[1] & CH341_MULT_STAT))
 			priv->multi_status_change = 1;
 		spin_unlock_irqrestore(&priv->lock, flags);
+
+		if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) {
+			struct tty_struct *tty = tty_port_tty_get(&port->port);
+			if (tty)
+				usb_serial_handle_dcd_change(port, tty,
+					    priv->line_status & CH341_BIT_DCD);
+			tty_kref_put(tty);
+		}
+
 		wake_up_interruptible(&priv->delta_msr_wait);
 	}
 
--- linux-ec2-2.6.32.orig/drivers/usb/serial/generic.c
+++ linux-ec2-2.6.32/drivers/usb/serial/generic.c
@@ -489,6 +489,8 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	if (port->serial->type->max_in_flight_urbs) {
+		kfree(urb->transfer_buffer);
+
 		spin_lock_irqsave(&port->lock, flags);
 		--port->urbs_in_flight;
 		port->tx_bytes_flight -= urb->transfer_buffer_length;
@@ -576,6 +578,26 @@
 }
 EXPORT_SYMBOL_GPL(usb_serial_handle_break);
 
+/**
+ *	usb_serial_handle_dcd_change - handle a change of carrier detect state
+ *	@port: usb_serial_port structure for the open port
+ *	@tty: tty_struct structure for the port
+ *	@status: new carrier detect status, nonzero if active
+ */
+void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
+				struct tty_struct *tty, unsigned int status)
+{
+	struct tty_port *port = &usb_port->port;
+
+	dbg("%s - port %d, status %d", __func__, usb_port->number, status);
+
+	if (status)
+		wake_up_interruptible(&port->open_wait);
+	else if (tty && !C_CLOCAL(tty))
+		tty_hangup(tty);
+}
+EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change);
+
 int usb_serial_generic_resume(struct usb_serial *serial)
 {
 	struct usb_serial_port *port;
--- linux-ec2-2.6.32.orig/drivers/usb/serial/ipaq.c
+++ linux-ec2-2.6.32/drivers/usb/serial/ipaq.c
@@ -547,7 +547,6 @@
 	{ USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */
 	{ USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */
 	{ USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */
-	{ USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */
 	{ }                             /* Terminating entry */
 };
 
--- linux-ec2-2.6.32.orig/drivers/usb/serial/visor.c
+++ linux-ec2-2.6.32/drivers/usb/serial/visor.c
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/usb/cdc.h>
 #include "visor.h"
 
 /*
@@ -249,6 +250,7 @@
 	.throttle =		visor_throttle,
 	.unthrottle =		visor_unthrottle,
 	.attach =		clie_3_5_startup,
+	.release =		visor_release,
 	.write =		visor_write,
 	.write_room =		visor_write_room,
 	.write_bulk_callback =	visor_write_bulk_callback,
@@ -757,6 +759,17 @@
 
 	dbg("%s", __func__);
 
+	/*
+	 * some Samsung Android phones in modem mode have the same ID
+	 * as SPH-I500, but they are ACM devices, so dont bind to them
+	 */
+	if (id->idVendor == SAMSUNG_VENDOR_ID &&
+		id->idProduct == SAMSUNG_SPH_I500_ID &&
+		serial->dev->descriptor.bDeviceClass == USB_CLASS_COMM &&
+		serial->dev->descriptor.bDeviceSubClass ==
+			USB_CDC_SUBCLASS_ACM)
+		return -ENODEV;
+
 	if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
 		dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
 			serial->dev->actconfig->desc.bConfigurationValue);
--- linux-ec2-2.6.32.orig/drivers/usb/serial/opticon.c
+++ linux-ec2-2.6.32/drivers/usb/serial/opticon.c
@@ -99,8 +99,8 @@
 				available_room = tty_buffer_request_room(tty,
 								data_length);
 				if (available_room) {
-					tty_insert_flip_string(tty, data,
-							       available_room);
+					tty_insert_flip_string(tty, data + 2,
+							       data_length);
 					tty_flip_buffer_push(tty);
 				}
 				tty_kref_put(tty);
@@ -134,7 +134,7 @@
 						  priv->bulk_address),
 				  priv->bulk_in_buffer, priv->buffer_size,
 				  opticon_bulk_callback, priv);
-		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&port->dev,
 			    "%s - failed resubmitting read urb, error %d\n",
--- linux-ec2-2.6.32.orig/drivers/usb/serial/mos7840.c
+++ linux-ec2-2.6.32/drivers/usb/serial/mos7840.c
@@ -120,9 +120,20 @@
  * by making a change here, in moschip_port_id_table, and in
  * moschip_id_table_combined
  */
-#define USB_VENDOR_ID_BANDB             0x0856
-#define BANDB_DEVICE_ID_USOPTL4_4       0xAC44
-#define BANDB_DEVICE_ID_USOPTL4_2       0xAC42
+#define USB_VENDOR_ID_BANDB              0x0856
+#define BANDB_DEVICE_ID_USO9ML2_2        0xAC22
+#define BANDB_DEVICE_ID_USO9ML2_2P       0xBC00
+#define BANDB_DEVICE_ID_USO9ML2_4        0xAC24
+#define BANDB_DEVICE_ID_USO9ML2_4P       0xBC01
+#define BANDB_DEVICE_ID_US9ML2_2         0xAC29
+#define BANDB_DEVICE_ID_US9ML2_4         0xAC30
+#define BANDB_DEVICE_ID_USPTL4_2         0xAC31
+#define BANDB_DEVICE_ID_USPTL4_4         0xAC32
+#define BANDB_DEVICE_ID_USOPTL4_2        0xAC42
+#define BANDB_DEVICE_ID_USOPTL4_2P       0xBC02
+#define BANDB_DEVICE_ID_USOPTL4_4        0xAC44
+#define BANDB_DEVICE_ID_USOPTL4_4P       0xBC03
+#define BANDB_DEVICE_ID_USOPTL2_4        0xAC24
 
 /* This driver also supports
  * ATEN UC2324 device using Moschip MCS7840
@@ -177,8 +188,19 @@
 static struct usb_device_id moschip_port_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
 	{}			/* terminating entry */
@@ -187,8 +209,19 @@
 static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
-	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
+	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
 	{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
 	{}			/* terminating entry */
@@ -262,12 +295,19 @@
 {
 	struct usb_device *dev = port->serial->dev;
 	int ret = 0;
+	u8 *buf;
+
+	buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
-			      MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
+			      MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH,
 			      MOS_WDR_TIMEOUT);
+	*val = buf[0];
 	dbg("mos7840_get_reg_sync offset is %x, return val %x", reg, *val);
-	*val = (*val) & 0x00ff;
+
+	kfree(buf);
 	return ret;
 }
 
@@ -320,6 +360,11 @@
 	struct usb_device *dev = port->serial->dev;
 	int ret = 0;
 	__u16 Wval;
+	u8 *buf;
+
+	buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	/* dbg("application number is %4x",
 	    (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
@@ -343,9 +388,11 @@
 		}
 	}
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
-			      MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
+			      MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH,
 			      MOS_WDR_TIMEOUT);
-	*val = (*val) & 0x00ff;
+	*val = buf[0];
+
+	kfree(buf);
 	return ret;
 }
 
@@ -696,7 +743,6 @@
 	mos7840_port = urb->context;
 	if (!mos7840_port) {
 		dbg("%s", "NULL mos7840_port pointer");
-		mos7840_port->read_urb_busy = false;
 		return;
 	}
 
@@ -2241,6 +2287,9 @@
 	case TIOCGICOUNT:
 		cnow = mos7840_port->icount;
 		smp_rmb();
+
+		memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
 		icount.cts = cnow.cts;
 		icount.dsr = cnow.dsr;
 		icount.rng = cnow.rng;
--- linux-ec2-2.6.32.orig/drivers/usb/storage/sierra_ms.c
+++ linux-ec2-2.6.32/drivers/usb/storage/sierra_ms.c
@@ -120,7 +120,7 @@
 	}
 	return result;
 }
-static DEVICE_ATTR(truinst, S_IWUGO | S_IRUGO, show_truinst, NULL);
+static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);
 
 int sierra_ms_init(struct us_data *us)
 {
--- linux-ec2-2.6.32.orig/drivers/usb/storage/transport.c
+++ linux-ec2-2.6.32/drivers/usb/storage/transport.c
@@ -666,10 +666,11 @@
 	 * to wait for at least one CHECK_CONDITION to determine
 	 * SANE_SENSE support
 	 */
-	if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
+	if (unlikely((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) &&
 	    result == USB_STOR_TRANSPORT_GOOD &&
 	    !(us->fflags & US_FL_SANE_SENSE) &&
-	    !(srb->cmnd[2] & 0x20)) {
+	    !(us->fflags & US_FL_BAD_SENSE) &&
+	    !(srb->cmnd[2] & 0x20))) {
 		US_DEBUGP("-- SAT supported, increasing auto-sense\n");
 		us->fflags |= US_FL_SANE_SENSE;
 	}
@@ -718,6 +719,12 @@
 		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 			US_DEBUGP("-- auto-sense aborted\n");
 			srb->result = DID_ABORT << 16;
+
+			/* If SANE_SENSE caused this problem, disable it */
+			if (sense_size != US_SENSE_SIZE) {
+				us->fflags &= ~US_FL_SANE_SENSE;
+				us->fflags |= US_FL_BAD_SENSE;
+			}
 			goto Handle_Errors;
 		}
 
@@ -727,10 +734,11 @@
 		 * (small) sense request. This fixes some USB GSM modems
 		 */
 		if (temp_result == USB_STOR_TRANSPORT_FAILED &&
-		    (us->fflags & US_FL_SANE_SENSE) &&
-		    sense_size != US_SENSE_SIZE) {
+				sense_size != US_SENSE_SIZE) {
 			US_DEBUGP("-- auto-sense failure, retry small sense\n");
 			sense_size = US_SENSE_SIZE;
+			us->fflags &= ~US_FL_SANE_SENSE;
+			us->fflags |= US_FL_BAD_SENSE;
 			goto Retry_Sense;
 		}
 
@@ -754,6 +762,7 @@
 		 */
 		if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) &&
 		    !(us->fflags & US_FL_SANE_SENSE) &&
+		    !(us->fflags & US_FL_BAD_SENSE) &&
 		    (srb->sense_buffer[0] & 0x7C) == 0x70) {
 			US_DEBUGP("-- SANE_SENSE support enabled\n");
 			us->fflags |= US_FL_SANE_SENSE;
--- linux-ec2-2.6.32.orig/drivers/usb/storage/usb.c
+++ linux-ec2-2.6.32/drivers/usb/storage/usb.c
@@ -228,6 +228,7 @@
 	if (data_len<36) // You lose.
 		return;
 
+	memset(data+8, ' ', 28);
 	if(data[0]&0x20) { /* USB device currently not connected. Return
 			      peripheral qualifier 001b ("...however, the
 			      physical device is not currently connected
@@ -237,15 +238,15 @@
 			      device, it may return zeros or ASCII spaces 
 			      (20h) in those fields until the data is
 			      available from the device."). */
-		memset(data+8,0,28);
 	} else {
 		u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
-		memcpy(data+8, us->unusual_dev->vendorName, 
-			strlen(us->unusual_dev->vendorName) > 8 ? 8 :
-			strlen(us->unusual_dev->vendorName));
-		memcpy(data+16, us->unusual_dev->productName, 
-			strlen(us->unusual_dev->productName) > 16 ? 16 :
-			strlen(us->unusual_dev->productName));
+		int n;
+
+		n = strlen(us->unusual_dev->vendorName);
+		memcpy(data+8, us->unusual_dev->vendorName, min(8, n));
+		n = strlen(us->unusual_dev->productName);
+		memcpy(data+16, us->unusual_dev->productName, min(16, n));
+
 		data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
 		data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
 		data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
@@ -429,7 +430,8 @@
 	u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
 	u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
 	unsigned f = 0;
-	unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY |
+	unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
+			US_FL_FIX_CAPACITY |
 			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
 			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
 			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
@@ -459,6 +461,9 @@
 		case 'a':
 			f |= US_FL_SANE_SENSE;
 			break;
+		case 'b':
+			f |= US_FL_BAD_SENSE;
+			break;
 		case 'c':
 			f |= US_FL_FIX_CAPACITY;
 			break;
--- linux-ec2-2.6.32.orig/drivers/usb/storage/unusual_devs.h
+++ linux-ec2-2.6.32/drivers/usb/storage/unusual_devs.h
@@ -481,6 +481,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64),
 
+/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,
+		"Samsung",
+		"YP-CP3",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
@@ -818,6 +825,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
+/* Reported by Daniel Kukula <daniel.kuku@gmail.com> */
+UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100,
+		"Prolific Technology, Inc.",
+		"Prolific Storage Gadget",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+
 /* Reported by Rogerio Brito <rbrito@ime.usp.br> */
 UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
 		"Prolific Technology, Inc.",
@@ -1029,6 +1043,15 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
+/* Reported by <ttkspam@free.fr>
+ * The device reports a vendor-specific device class, requiring an
+ * explicit vendor/product match.
+ */
+UNUSUAL_DEV(  0x0851, 0x1542, 0x0002, 0x0002,
+		"MagicPixel",
+		"FW_Omega2",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+
 /* Andrew Lunn <andrew@lunn.ch>
  * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
  * on LUN 4.
@@ -1129,6 +1152,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
 		0),
 
+/* Reported by Timo Aaltonen <tjaalton@ubuntu.com> */
+UNUSUAL_DEV( 0x0af0, 0x7011, 0x0000, 0x9999,
+		"Option",
+		"Mass Storage",
+		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+		0 ),
+
 /* Reported by F. Aben <f.aben@option.com>
  * This device (wrongly) has a vendor-specific device descriptor.
  * The entry is needed so usb-storage can bind to it's mass-storage
@@ -1140,8 +1170,8 @@
 		0 ),
 
 /* Reported by Jan Dumon <j.dumon@option.com>
- * This device (wrongly) has a vendor-specific device descriptor.
- * The entry is needed so usb-storage can bind to it's mass-storage
+ * These devices (wrongly) have a vendor-specific device descriptor.
+ * These entries are needed so usb-storage can bind to their mass-storage
  * interface as an interface driver */
 UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000,
 		"Option",
@@ -1149,6 +1179,90 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		0 ),
 
+UNUSUAL_DEV( 0x0af0, 0x7701, 0x0000, 0x0000,
+		"Option",
+		"GI 0451 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7706, 0x0000, 0x0000,
+		"Option",
+		"GI 0451 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7901, 0x0000, 0x0000,
+		"Option",
+		"GI 0452 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7A01, 0x0000, 0x0000,
+		"Option",
+		"GI 0461 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7A05, 0x0000, 0x0000,
+		"Option",
+		"GI 0461 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8300, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8302, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
+		"Option",
+		"GI 070x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd057, 0x0000, 0x0000,
+		"Option",
+		"GI 1505 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd058, 0x0000, 0x0000,
+		"Option",
+		"GI 1509 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd157, 0x0000, 0x0000,
+		"Option",
+		"GI 1515 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd257, 0x0000, 0x0000,
+		"Option",
+		"GI 1215 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000,
+		"Option",
+		"GI 1505 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
 		"Seagate",
@@ -1303,6 +1417,13 @@
 		US_FL_IGNORE_DEVICE ),
 #endif
 
+/* Submitted by Nick Holloway */
+UNUSUAL_DEV( 0x0f88, 0x042e, 0x0100, 0x0100,
+		"VTech",
+		"Kidizoom",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
 		"Sony Ericsson",
@@ -1767,6 +1888,37 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Hans de Goede <hdegoede@redhat.com>
+ * These Appotech controllers are found in Picture Frames, they provide a
+ * (buggy) emulation of a cdrom drive which contains the windows software
+ * Uploading of pictures happens over the corresponding /dev/sg device. */
+UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000,
+		"BUILDWIN",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000,
+		"BUILDWIN",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BAD_SENSE ),
+
+/* Patch by Richard Sch�tz <r.schtz@t-online.de>
+ * This external hard drive enclosure uses a JMicron chip which
+ * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
+UNUSUAL_DEV(  0x1e68, 0x001b, 0x0000, 0x0000,
+		"TrekStor GmbH & Co. KG",
+		"DataStation maxi g.u",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
+
+/* Reported by Jasper Mackenzie <scarletpimpernal@hotmail.com> */
+UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000,
+		"Coby Electronics",
+		"MP3 Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
 UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
 		"ST",
 		"2A",
@@ -1800,13 +1952,6 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
-/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
-UNUSUAL_DEV(  0x2770, 0x915d, 0x0010, 0x0010,
-		"INTOVA",
-		"Pixtreme",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
-
 /* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
  * Mio Moov 330
  */
--- linux-ec2-2.6.32.orig/drivers/usb/storage/unusual_cypress.h
+++ linux-ec2-2.6.32/drivers/usb/storage/unusual_cypress.h
@@ -31,4 +31,9 @@
 		"Cypress ISD-300LP",
 		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
 
+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999,
+		"Super Top",
+		"USB 2.0  SATA BRIDGE",
+		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+
 #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
--- linux-ec2-2.6.32.orig/drivers/usb/gadget/u_serial.c
+++ linux-ec2-2.6.32/drivers/usb/gadget/u_serial.c
@@ -535,17 +535,11 @@
 		list_move(&req->list, &port->read_pool);
 	}
 
-	/* Push from tty to ldisc; this is immediate with low_latency, and
-	 * may trigger callbacks to this driver ... so drop the spinlock.
+	/* Push from tty to ldisc; without low_latency set this is handled by
+	 * a workqueue, so we won't get callbacks and can hold port_lock
 	 */
 	if (tty && do_push) {
-		spin_unlock_irq(&port->port_lock);
 		tty_flip_buffer_push(tty);
-		wake_up_interruptible(&tty->read_wait);
-		spin_lock_irq(&port->port_lock);
-
-		/* tty may have been closed */
-		tty = port->port_tty;
 	}
 
 
@@ -783,11 +777,6 @@
 	port->open_count = 1;
 	port->openclose = false;
 
-	/* low_latency means ldiscs work in tasklet context, without
-	 * needing a workqueue schedule ... easier to keep up.
-	 */
-	tty->low_latency = 1;
-
 	/* if connected, start the I/O stream */
 	if (port->port_usb) {
 		struct gserial	*gser = port->port_usb;
@@ -1194,6 +1183,7 @@
 	n_ports = 0;
 
 	tty_unregister_driver(gs_tty_driver);
+	put_tty_driver(gs_tty_driver);
 	gs_tty_driver = NULL;
 
 	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
--- linux-ec2-2.6.32.orig/drivers/usb/gadget/rndis.c
+++ linux-ec2-2.6.32/drivers/usb/gadget/rndis.c
@@ -291,9 +291,13 @@
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
 		pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
-		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
-		memcpy (outbuf,
-			rndis_per_dev_params [configNr].vendorDescr, length);
+		if ( rndis_per_dev_params [configNr].vendorDescr ) {
+			length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+			memcpy (outbuf,
+				rndis_per_dev_params [configNr].vendorDescr, length);
+		} else {
+			outbuf[0] = 0;
+		}
 		retval = 0;
 		break;
 
--- linux-ec2-2.6.32.orig/drivers/usb/gadget/atmel_usba_udc.c
+++ linux-ec2-2.6.32/drivers/usb/gadget/atmel_usba_udc.c
@@ -2013,6 +2013,9 @@
 			} else {
 				disable_irq(gpio_to_irq(udc->vbus_pin));
 			}
+		} else {
+			/* gpio_request fail so use -EINVAL for gpio_is_valid */
+			udc->vbus_pin = -EINVAL;
 		}
 	}
 
--- linux-ec2-2.6.32.orig/drivers/usb/gadget/fsl_udc_core.c
+++ linux-ec2-2.6.32/drivers/usb/gadget/fsl_udc_core.c
@@ -489,7 +489,7 @@
 	case USB_ENDPOINT_XFER_ISOC:
 		/* Calculate transactions needed for high bandwidth iso */
 		mult = (unsigned char)(1 + ((max >> 11) & 0x03));
-		max = max & 0x8ff;	/* bit 0~10 */
+		max = max & 0x7ff;	/* bit 0~10 */
 		/* 3 transactions at most */
 		if (mult > 3)
 			goto en_done;
--- linux-ec2-2.6.32.orig/drivers/usb/gadget/printer.c
+++ linux-ec2-2.6.32/drivers/usb/gadget/printer.c
@@ -130,31 +130,31 @@
  * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
  */
 
-static ushort __initdata idVendor;
+static ushort idVendor;
 module_param(idVendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(idVendor, "USB Vendor ID");
 
-static ushort __initdata idProduct;
+static ushort idProduct;
 module_param(idProduct, ushort, S_IRUGO);
 MODULE_PARM_DESC(idProduct, "USB Product ID");
 
-static ushort __initdata bcdDevice;
+static ushort bcdDevice;
 module_param(bcdDevice, ushort, S_IRUGO);
 MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
 
-static char *__initdata iManufacturer;
+static char *iManufacturer;
 module_param(iManufacturer, charp, S_IRUGO);
 MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
 
-static char *__initdata iProduct;
+static char *iProduct;
 module_param(iProduct, charp, S_IRUGO);
 MODULE_PARM_DESC(iProduct, "USB Product string");
 
-static char *__initdata iSerialNum;
+static char *iSerialNum;
 module_param(iSerialNum, charp, S_IRUGO);
 MODULE_PARM_DESC(iSerialNum, "1");
 
-static char *__initdata iPNPstring;
+static char *iPNPstring;
 module_param(iPNPstring, charp, S_IRUGO);
 MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
 
--- linux-ec2-2.6.32.orig/drivers/usb/core/sysfs.c
+++ linux-ec2-2.6.32/drivers/usb/core/sysfs.c
@@ -82,9 +82,13 @@
 		struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_device *udev;					\
+	int retval;							\
 									\
 	udev = to_usb_device(dev);					\
-	return sprintf(buf, "%s\n", udev->name);			\
+	rcu_read_lock();						\
+	retval = sprintf(buf, "%s\n", rcu_dereference(udev->name));	\
+	rcu_read_unlock();						\
+	return retval;							\
 }									\
 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
@@ -111,6 +115,12 @@
 	case USB_SPEED_HIGH:
 		speed = "480";
 		break;
+	case USB_SPEED_VARIABLE:
+		speed = "480";
+		break;
+	case USB_SPEED_SUPER:
+		speed = "5000";
+		break;
 	default:
 		speed = "unknown";
 	}
--- linux-ec2-2.6.32.orig/drivers/usb/core/hcd.c
+++ linux-ec2-2.6.32/drivers/usb/core/hcd.c
@@ -140,7 +140,7 @@
 	0x09,       /*  __u8  bMaxPacketSize0; 2^9 = 512 Bytes */
 
 	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
-	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
+	0x03, 0x00, /*  __le16 idProduct; device 0x0003 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
--- linux-ec2-2.6.32.orig/drivers/usb/core/driver.c
+++ linux-ec2-2.6.32/drivers/usb/core/driver.c
@@ -625,9 +625,6 @@
 {
 	struct usb_device *usb_dev;
 
-	/* driver is often null here; dev_dbg() would oops */
-	pr_debug("usb %s: uevent\n", dev_name(dev));
-
 	if (is_usb_device(dev)) {
 		usb_dev = to_usb_device(dev);
 	} else if (is_usb_interface(dev)) {
@@ -639,6 +636,7 @@
 	}
 
 	if (usb_dev->devnum < 0) {
+		/* driver is often null here; dev_dbg() would oops */
 		pr_debug("usb %s: already deleted?\n", dev_name(dev));
 		return -ENODEV;
 	}
@@ -1177,9 +1175,8 @@
 			udev->state == USB_STATE_SUSPENDED)
 		goto done;
 
-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
-
 	if (msg.event & PM_EVENT_AUTO) {
+		udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
 		status = autosuspend_check(udev, 0);
 		if (status < 0)
 			goto done;
@@ -1744,6 +1741,23 @@
 	return status;
 }
 
+static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
+{
+	/* Remote wakeup is needed only when we actually go to sleep.
+	 * For things like FREEZE and QUIESCE, if the device is already
+	 * autosuspended then its current wakeup setting is okay.
+	 */
+	if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_QUIESCE) {
+		udev->do_remote_wakeup = 0;
+		return;
+	}
+
+	/* Allow remote wakeup if it is enabled, even if no interface drivers
+	 * actually want it.
+	 */
+	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+}
+
 int usb_suspend(struct device *dev, pm_message_t msg)
 {
 	struct usb_device	*udev;
@@ -1763,6 +1777,7 @@
 	}
 
 	udev->skip_sys_resume = 0;
+	choose_wakeup(udev, msg);
 	return usb_external_suspend_device(udev, msg);
 }
 
--- linux-ec2-2.6.32.orig/drivers/usb/core/quirks.c
+++ linux-ec2-2.6.32/drivers/usb/core/quirks.c
@@ -38,9 +38,20 @@
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Logitech Harmony 700-series */
+	{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
+
 	/* Philips PSC805 audio device */
 	{ USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Artisman Watchdog Dongle */
+	{ USB_DEVICE(0x04b4, 0x0526), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
+	/* Samsung Android phone modem - ID conflict with SPH-I500 */
+	{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* Roland SC-8820 */
 	{ USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -61,9 +72,16 @@
 	/* M-Systems Flash Disk Pioneers */
 	{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Keytouch QWERTY Panel keyboard */
+	{ USB_DEVICE(0x0926, 0x3333), .driver_info =
+			USB_QUIRK_CONFIG_INTF_STRINGS },
+
 	/* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */
 	{ USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
 
+	/* Broadcom BCM92035DGROM BT dongle */
+	{ USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* Action Semiconductor flash disk */
 	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
 			USB_QUIRK_STRING_FETCH_255 },
--- linux-ec2-2.6.32.orig/drivers/usb/core/urb.c
+++ linux-ec2-2.6.32/drivers/usb/core/urb.c
@@ -137,6 +137,16 @@
 }
 EXPORT_SYMBOL_GPL(usb_anchor_urb);
 
+/* Callers must hold anchor->lock */
+static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
+{
+	urb->anchor = NULL;
+	list_del(&urb->anchor_list);
+	usb_put_urb(urb);
+	if (list_empty(&anchor->urb_list))
+		wake_up(&anchor->wait);
+}
+
 /**
  * usb_unanchor_urb - unanchors an URB
  * @urb: pointer to the urb to anchor
@@ -156,17 +166,14 @@
 		return;
 
 	spin_lock_irqsave(&anchor->lock, flags);
-	if (unlikely(anchor != urb->anchor)) {
-		/* we've lost the race to another thread */
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		return;
-	}
-	urb->anchor = NULL;
-	list_del(&urb->anchor_list);
+	/*
+	 * At this point, we could be competing with another thread which
+	 * has the same intention. To protect the urb from being unanchored
+	 * twice, only the winner of the race gets the job.
+	 */
+	if (likely(anchor == urb->anchor))
+		__usb_unanchor_urb(urb, anchor);
 	spin_unlock_irqrestore(&anchor->lock, flags);
-	usb_put_urb(urb);
-	if (list_empty(&anchor->urb_list))
-		wake_up(&anchor->wait);
 }
 EXPORT_SYMBOL_GPL(usb_unanchor_urb);
 
@@ -725,20 +732,11 @@
 void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
 {
 	struct urb *victim;
-	unsigned long flags;
 
-	spin_lock_irqsave(&anchor->lock, flags);
-	while (!list_empty(&anchor->urb_list)) {
-		victim = list_entry(anchor->urb_list.prev, struct urb,
-				    anchor_list);
-		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		/* this will unanchor the URB */
+	while ((victim = usb_get_from_anchor(anchor)) != NULL) {
 		usb_unlink_urb(victim);
 		usb_put_urb(victim);
-		spin_lock_irqsave(&anchor->lock, flags);
 	}
-	spin_unlock_irqrestore(&anchor->lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
 
@@ -775,12 +773,11 @@
 		victim = list_entry(anchor->urb_list.next, struct urb,
 				    anchor_list);
 		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		usb_unanchor_urb(victim);
+		__usb_unanchor_urb(victim, anchor);
 	} else {
-		spin_unlock_irqrestore(&anchor->lock, flags);
 		victim = NULL;
 	}
+	spin_unlock_irqrestore(&anchor->lock, flags);
 
 	return victim;
 }
@@ -802,12 +799,7 @@
 	while (!list_empty(&anchor->urb_list)) {
 		victim = list_entry(anchor->urb_list.prev, struct urb,
 				    anchor_list);
-		usb_get_urb(victim);
-		spin_unlock_irqrestore(&anchor->lock, flags);
-		/* this may free the URB */
-		usb_unanchor_urb(victim);
-		usb_put_urb(victim);
-		spin_lock_irqsave(&anchor->lock, flags);
+		__usb_unanchor_urb(victim, anchor);
 	}
 	spin_unlock_irqrestore(&anchor->lock, flags);
 }
--- linux-ec2-2.6.32.orig/drivers/usb/core/devices.c
+++ linux-ec2-2.6.32/drivers/usb/core/devices.c
@@ -65,8 +65,8 @@
 #define ALLOW_SERIAL_NUMBER
 
 static const char *format_topo =
-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
-"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
+"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
 
 static const char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
@@ -211,7 +211,7 @@
 		break;
 	case USB_ENDPOINT_XFER_INT:
 		type = "Int.";
-		if (speed == USB_SPEED_HIGH)
+		if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
 			interval = 1 << (desc->bInterval - 1);
 		else
 			interval = desc->bInterval;
@@ -219,7 +219,8 @@
 	default:	/* "can't happen" */
 		return start;
 	}
-	interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+	interval *= (speed == USB_SPEED_HIGH ||
+		     speed == USB_SPEED_SUPER) ? 125 : 1000;
 	if (interval % 1000)
 		unit = 'u';
 	else {
@@ -494,7 +495,7 @@
 		return 0;
 	/* allocate 2^1 pages = 8K (on i386);
 	 * should be more than enough for one device */
-	pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
+	pages_start = (char *)__get_free_pages(GFP_NOIO, 1);
 	if (!pages_start)
 		return -ENOMEM;
 
@@ -509,11 +510,13 @@
 		speed = "1.5"; break;
 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
 	case USB_SPEED_FULL:
-		speed = "12 "; break;
+		speed = "12"; break;
 	case USB_SPEED_HIGH:
 		speed = "480"; break;
+	case USB_SPEED_SUPER:
+		speed = "5000"; break;
 	default:
-		speed = "?? ";
+		speed = "??";
 	}
 	data_end = pages_start + sprintf(pages_start, format_topo,
 			bus->busnum, level, parent_devnum,
@@ -529,8 +532,9 @@
 	if (level == 0) {
 		int	max;
 
-		/* high speed reserves 80%, full/low reserves 90% */
-		if (usbdev->speed == USB_SPEED_HIGH)
+		/* super/high speed reserves 80%, full/low reserves 90% */
+		if (usbdev->speed == USB_SPEED_HIGH ||
+		    usbdev->speed == USB_SPEED_SUPER)
 			max = 800;
 		else
 			max = FRAME_TIME_MAX_USECS_ALLOC;
--- linux-ec2-2.6.32.orig/drivers/usb/core/hub.c
+++ linux-ec2-2.6.32/drivers/usb/core/hub.c
@@ -22,6 +22,8 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
+#include <linux/usb/quirks.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -647,6 +649,8 @@
 static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 {
 	struct usb_device *hdev = hub->hdev;
+	struct usb_hcd *hcd;
+	int ret;
 	int port1;
 	int status;
 	bool need_debounce_delay = false;
@@ -685,6 +689,25 @@
 			atomic_set(&to_usb_interface(hub->intfdev)->
 					pm_usage_cnt, 1);
 			return;		/* Continues at init2: below */
+		} else if (type == HUB_RESET_RESUME) {
+			/* The internal host controller state for the hub device
+			 * may be gone after a host power loss on system resume.
+			 * Update the device's info so the HW knows it's a hub.
+			 */
+			hcd = bus_to_hcd(hdev->bus);
+			if (hcd->driver->update_hub_device) {
+				ret = hcd->driver->update_hub_device(hcd, hdev,
+						&hub->tt, GFP_NOIO);
+				if (ret < 0) {
+					dev_err(hub->intfdev, "Host not "
+							"accepting hub info "
+							"update.\n");
+					dev_err(hub->intfdev, "LS/FS devices "
+							"and hubs may not work "
+							"under this hub\n.");
+				}
+			}
+			hub_power_on(hub, true);
 		} else {
 			hub_power_on(hub, true);
 		}
@@ -1402,11 +1425,11 @@
 					|| new_state == USB_STATE_SUSPENDED)
 				;	/* No change to wakeup settings */
 			else if (new_state == USB_STATE_CONFIGURED)
-				device_init_wakeup(&udev->dev,
+				device_set_wakeup_capable(&udev->dev,
 					(udev->actconfig->desc.bmAttributes
 					 & USB_CONFIG_ATT_WAKEUP));
 			else
-				device_init_wakeup(&udev->dev, 0);
+				device_set_wakeup_capable(&udev->dev, 0);
 		}
 		if (udev->state == USB_STATE_SUSPENDED &&
 			new_state != USB_STATE_SUSPENDED)
@@ -1508,6 +1531,15 @@
 
 #endif
 
+static void hub_free_dev(struct usb_device *udev)
+{
+	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+	/* Root hubs aren't real devices, so don't free HCD resources */
+	if (hcd->driver->free_dev && udev->parent)
+		hcd->driver->free_dev(hcd, udev);
+}
+
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
  * @pdev: pointer to device being disconnected
@@ -1578,6 +1610,8 @@
 
 	usb_stop_pm(udev);
 
+	hub_free_dev(udev);
+
 	put_device(&udev->dev);
 }
 
@@ -1612,12 +1646,12 @@
 #endif
 
 /**
- * usb_configure_device_otg - FIXME (usbcore-internal)
+ * usb_enumerate_device_otg - FIXME (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
- * Do configuration for On-The-Go devices
+ * Finish enumeration for On-The-Go devices
  */
-static int usb_configure_device_otg(struct usb_device *udev)
+static int usb_enumerate_device_otg(struct usb_device *udev)
 {
 	int err = 0;
 
@@ -1688,7 +1722,7 @@
 
 
 /**
- * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal)
+ * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
  * This is only called by usb_new_device() and usb_authorize_device()
@@ -1699,7 +1733,7 @@
  * the string descriptors, as they will be errored out by the device
  * until it has been authorized.
  */
-static int usb_configure_device(struct usb_device *udev)
+static int usb_enumerate_device(struct usb_device *udev)
 {
 	int err;
 
@@ -1723,7 +1757,7 @@
 						      udev->descriptor.iManufacturer);
 		udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
 	}
-	err = usb_configure_device_otg(udev);
+	err = usb_enumerate_device_otg(udev);
 fail:
 	return err;
 }
@@ -1733,8 +1767,8 @@
  * usb_new_device - perform initial device setup (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
  *
- * This is called with devices which have been enumerated, but not yet
- * configured.  The device descriptor is available, but not descriptors
+ * This is called with devices which have been detected but not fully
+ * enumerated.  The device descriptor is available, but not descriptors
  * for any device configuration.  The caller must have locked either
  * the parent hub (if udev is a normal device) or else the
  * usb_bus_list_lock (if udev is a root hub).  The parent's pointer to
@@ -1753,12 +1787,18 @@
 {
 	int err;
 
-	/* Increment the parent's count of unsuspended children */
-	if (udev->parent)
+	if (udev->parent) {
+		/* Increment the parent's count of unsuspended children */
 		usb_autoresume_device(udev->parent);
 
-	usb_detect_quirks(udev);		/* Determine quirks */
-	err = usb_configure_device(udev);	/* detect & probe dev/intfs */
+		/* Initialize non-root-hub device wakeup to disabled;
+		 * device (un)configuration controls wakeup capable
+		 * sysfs power/wakeup controls wakeup enabled/disabled
+		 */
+		device_init_wakeup(&udev->dev, 0);
+	}
+
+	err = usb_enumerate_device(udev);	/* Read descriptors */
 	if (err < 0)
 		goto fail;
 	dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n",
@@ -1803,23 +1843,36 @@
  */
 int usb_deauthorize_device(struct usb_device *usb_dev)
 {
-	unsigned cnt;
+	char *product = NULL;
+	char *manufacturer = NULL;
+	char *serial = NULL;
+
 	usb_lock_device(usb_dev);
 	if (usb_dev->authorized == 0)
 		goto out_unauthorized;
+
 	usb_dev->authorized = 0;
 	usb_set_configuration(usb_dev, -1);
+
+	product = usb_dev->product;
+	manufacturer = usb_dev->manufacturer;
+	serial = usb_dev->serial;
+
 	usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
 	usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
 	usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-	kfree(usb_dev->config);
-	usb_dev->config = NULL;
-	for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++)
-		kfree(usb_dev->rawdescriptors[cnt]);
+
+	usb_destroy_configuration(usb_dev);
 	usb_dev->descriptor.bNumConfigurations = 0;
-	kfree(usb_dev->rawdescriptors);
+
 out_unauthorized:
 	usb_unlock_device(usb_dev);
+	if (product || manufacturer || serial) {
+		synchronize_rcu();
+		kfree(product);
+		kfree(manufacturer);
+		kfree(serial);
+	}
 	return 0;
 }
 
@@ -1827,15 +1880,14 @@
 int usb_authorize_device(struct usb_device *usb_dev)
 {
 	int result = 0, c;
+	char *product = NULL;
+	char *manufacturer = NULL;
+	char *serial = NULL;
+
 	usb_lock_device(usb_dev);
 	if (usb_dev->authorized == 1)
 		goto out_authorized;
-	kfree(usb_dev->product);
-	usb_dev->product = NULL;
-	kfree(usb_dev->manufacturer);
-	usb_dev->manufacturer = NULL;
-	kfree(usb_dev->serial);
-	usb_dev->serial = NULL;
+
 	result = usb_autoresume_device(usb_dev);
 	if (result < 0) {
 		dev_err(&usb_dev->dev,
@@ -1848,10 +1900,19 @@
 			"authorization: %d\n", result);
 		goto error_device_descriptor;
 	}
+
+	product = usb_dev->product;
+	manufacturer = usb_dev->manufacturer;
+	serial = usb_dev->serial;
+	
+	usb_dev->product = NULL;
+	usb_dev->manufacturer = NULL;
+	usb_dev->serial = NULL;
+
 	usb_dev->authorized = 1;
-	result = usb_configure_device(usb_dev);
+	result = usb_enumerate_device(usb_dev);
 	if (result < 0)
-		goto error_configure;
+		goto error_enumerate;
 	/* Choose and set the configuration.  This registers the interfaces
 	 * with the driver core and lets interface drivers bind to them.
 	 */
@@ -1866,11 +1927,19 @@
 		}
 	}
 	dev_info(&usb_dev->dev, "authorized to connect\n");
-error_configure:
+
+error_enumerate:
 error_device_descriptor:
+	usb_autosuspend_device(usb_dev);
 error_autoresume:
 out_authorized:
 	usb_unlock_device(usb_dev);	// complements locktree
+	if (product || manufacturer || serial) {
+		synchronize_rcu();
+		kfree(product);
+		kfree(manufacturer);
+		kfree(serial);
+	}
 	return result;
 }
 
@@ -2664,6 +2733,11 @@
 		udev->ttport = hdev->ttport;
 	} else if (udev->speed != USB_SPEED_HIGH
 			&& hdev->speed == USB_SPEED_HIGH) {
+		if (!hub->tt.hub) {
+			dev_err(&udev->dev, "parent hub has no TT\n");
+			retval = -EINVAL;
+			goto fail;
+		}
 		udev->tt = &hub->tt;
 		udev->ttport = port1;
 	}
@@ -2802,13 +2876,16 @@
 	else
 		i = udev->descriptor.bMaxPacketSize0;
 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
-		if (udev->speed != USB_SPEED_FULL ||
+		if (udev->speed == USB_SPEED_LOW ||
 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
-			dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
+			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
 			retval = -EMSGSIZE;
 			goto fail;
 		}
-		dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		if (udev->speed == USB_SPEED_FULL)
+			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		else
+			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
 		usb_ep0_reinit(udev);
 	}
@@ -3044,6 +3121,10 @@
 		if (status < 0)
 			goto loop;
 
+		usb_detect_quirks(udev);
+		if (udev->quirks & USB_QUIRK_DELAY_INIT)
+			msleep(1000);
+
 		/* consecutive bus-powered hubs aren't reliable; they can
 		 * violate the voltage drop budget.  if the new child has
 		 * a "powered" LED, users should notice we didn't enable it
@@ -3122,6 +3203,7 @@
 loop:
 		usb_ep0_reinit(udev);
 		release_address(udev);
+		hub_free_dev(udev);
 		usb_put_dev(udev);
 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
 			break;
@@ -3278,6 +3360,9 @@
 					USB_PORT_FEAT_C_SUSPEND);
 				udev = hdev->children[i-1];
 				if (udev) {
+					/* TRSMRCY = 10 msec */
+					msleep(10);
+
 					usb_lock_device(udev);
 					ret = remote_wakeup(hdev->
 							children[i-1]);
--- linux-ec2-2.6.32.orig/drivers/usb/core/inode.c
+++ linux-ec2-2.6.32/drivers/usb/core/inode.c
@@ -515,13 +515,13 @@
 	*dentry = NULL;
 	mutex_lock(&parent->d_inode->i_mutex);
 	*dentry = lookup_one_len(name, parent, strlen(name));
-	if (!IS_ERR(dentry)) {
+	if (!IS_ERR(*dentry)) {
 		if ((mode & S_IFMT) == S_IFDIR)
 			error = usbfs_mkdir (parent->d_inode, *dentry, mode);
 		else 
 			error = usbfs_create (parent->d_inode, *dentry, mode);
 	} else
-		error = PTR_ERR(dentry);
+		error = PTR_ERR(*dentry);
 	mutex_unlock(&parent->d_inode->i_mutex);
 
 	return error;
--- linux-ec2-2.6.32.orig/drivers/usb/core/usb.c
+++ linux-ec2-2.6.32/drivers/usb/core/usb.c
@@ -132,7 +132,7 @@
 
 struct find_interface_arg {
 	int minor;
-	struct usb_interface *interface;
+	struct device_driver *drv;
 };
 
 static int __find_interface(struct device *dev, void *data)
@@ -143,12 +143,10 @@
 	if (!is_usb_interface(dev))
 		return 0;
 
+	if (dev->driver != arg->drv)
+		return 0;
 	intf = to_usb_interface(dev);
-	if (intf->minor != -1 && intf->minor == arg->minor) {
-		arg->interface = intf;
-		return 1;
-	}
-	return 0;
+	return intf->minor == arg->minor;
 }
 
 /**
@@ -156,21 +154,24 @@
  * @drv: the driver whose current configuration is considered
  * @minor: the minor number of the desired device
  *
- * This walks the driver device list and returns a pointer to the interface
- * with the matching minor.  Note, this only works for devices that share the
- * USB major number.
+ * This walks the bus device list and returns a pointer to the interface
+ * with the matching minor and driver.  Note, this only works for devices
+ * that share the USB major number.
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
 	struct find_interface_arg argb;
-	int retval;
+	struct device *dev;
 
 	argb.minor = minor;
-	argb.interface = NULL;
-	/* eat the error, it will be in argb.interface */
-	retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
-					__find_interface);
-	return argb.interface;
+	argb.drv = &drv->drvwrap.driver;
+
+	dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface);
+
+	/* Drop reference count from bus_find_device */
+	put_device(dev);
+
+	return dev ? to_usb_interface(dev) : NULL;
 }
 EXPORT_SYMBOL_GPL(usb_find_interface);
 
@@ -190,9 +191,6 @@
 	hcd = bus_to_hcd(udev->bus);
 
 	usb_destroy_configuration(udev);
-	/* Root hubs aren't real devices, so don't free HCD resources */
-	if (hcd->driver->free_dev && udev->parent)
-		hcd->driver->free_dev(hcd, udev);
 	usb_put_hcd(hcd);
 	kfree(udev->product);
 	kfree(udev->manufacturer);
--- linux-ec2-2.6.32.orig/drivers/usb/core/hcd.h
+++ linux-ec2-2.6.32/drivers/usb/core/hcd.h
@@ -234,7 +234,7 @@
 	/* xHCI specific functions */
 		/* Called by usb_alloc_dev to alloc HC device structures */
 	int	(*alloc_dev)(struct usb_hcd *, struct usb_device *);
-		/* Called by usb_release_dev to free HC device structures */
+		/* Called by usb_disconnect to free HC device structures */
 	void	(*free_dev)(struct usb_hcd *, struct usb_device *);
 
 	/* Bandwidth computation functions */
--- linux-ec2-2.6.32.orig/drivers/usb/core/devio.c
+++ linux-ec2-2.6.32/drivers/usb/core/devio.c
@@ -946,10 +946,11 @@
 
 static int proc_connectinfo(struct dev_state *ps, void __user *arg)
 {
-	struct usbdevfs_connectinfo ci;
+	struct usbdevfs_connectinfo ci = {
+		.devnum = ps->dev->devnum,
+		.slow = ps->dev->speed == USB_SPEED_LOW
+	};
 
-	ci.devnum = ps->dev->devnum;
-	ci.slow = ps->dev->speed == USB_SPEED_LOW;
 	if (copy_to_user(arg, &ci, sizeof(ci)))
 		return -EFAULT;
 	return 0;
@@ -1176,6 +1177,13 @@
 			free_async(as);
 			return -ENOMEM;
 		}
+		/* Isochronous input data may end up being discontiguous
+		 * if some of the packets are short.  Clear the buffer so
+		 * that the gaps don't leak kernel data to userspace.
+		 */
+		if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
+			memset(as->urb->transfer_buffer, 0,
+					uurb->buffer_length);
 	}
 	as->urb->dev = ps->dev;
 	as->urb->pipe = (uurb->type << 30) |
@@ -1312,10 +1320,14 @@
 	void __user *addr = as->userurb;
 	unsigned int i;
 
-	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
-				 urb->transfer_buffer_length))
+	if (as->userbuffer && urb->actual_length) {
+		if (urb->number_of_packets > 0)		/* Isochronous */
+			i = urb->transfer_buffer_length;
+		else					/* Non-Isoc */
+			i = urb->actual_length;
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
 			goto err_out;
+	}
 	if (put_user(as->status, &userurb->status))
 		goto err_out;
 	if (put_user(urb->actual_length, &userurb->actual_length))
@@ -1334,14 +1346,11 @@
 		}
 	}
 
-	free_async(as);
-
 	if (put_user(addr, (void __user * __user *)arg))
 		return -EFAULT;
 	return 0;
 
 err_out:
-	free_async(as);
 	return -EFAULT;
 }
 
@@ -1371,8 +1380,11 @@
 static int proc_reapurb(struct dev_state *ps, void __user *arg)
 {
 	struct async *as = reap_as(ps);
-	if (as)
-		return processcompl(as, (void __user * __user *)arg);
+	if (as) {
+		int retval = processcompl(as, (void __user * __user *)arg);
+		free_async(as);
+		return retval;
+	}
 	if (signal_pending(current))
 		return -EINTR;
 	return -EIO;
@@ -1380,11 +1392,16 @@
 
 static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
 {
+	int retval;
 	struct async *as;
 
-	if (!(as = async_getcompleted(ps)))
-		return -EAGAIN;
-	return processcompl(as, (void __user * __user *)arg);
+	as = async_getcompleted(ps);
+	retval = -EAGAIN;
+	if (as) {
+		retval = processcompl(as, (void __user * __user *)arg);
+		free_async(as);
+	}
+	return retval;
 }
 
 #ifdef CONFIG_COMPAT
@@ -1435,9 +1452,9 @@
 	void __user *addr = as->userurb;
 	unsigned int i;
 
-	if (as->userbuffer)
+	if (as->userbuffer && urb->actual_length)
 		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
-				 urb->transfer_buffer_length))
+				 urb->actual_length))
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
@@ -1457,7 +1474,6 @@
 		}
 	}
 
-	free_async(as);
 	if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
 		return -EFAULT;
 	return 0;
@@ -1466,8 +1482,11 @@
 static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
 {
 	struct async *as = reap_as(ps);
-	if (as)
-		return processcompl_compat(as, (void __user * __user *)arg);
+	if (as) {
+		int retval = processcompl_compat(as, (void __user * __user *)arg);
+		free_async(as);
+		return retval;
+	}
 	if (signal_pending(current))
 		return -EINTR;
 	return -EIO;
@@ -1475,11 +1494,16 @@
 
 static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
 {
+	int retval;
 	struct async *as;
 
-	if (!(as = async_getcompleted(ps)))
-		return -EAGAIN;
-	return processcompl_compat(as, (void __user * __user *)arg);
+	retval = -EAGAIN;
+	as = async_getcompleted(ps);
+	if (as) {
+		retval = processcompl_compat(as, (void __user * __user *)arg);
+		free_async(as);
+	}
+	return retval;
 }
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/usb/core/hcd-pci.c
+++ linux-ec2-2.6.32/drivers/usb/core/hcd-pci.c
@@ -197,8 +197,10 @@
 	if (!hcd)
 		return;
 
-	if (hcd->driver->shutdown)
+	if (hcd->driver->shutdown) {
 		hcd->driver->shutdown(hcd);
+		pci_disable_device(dev);
+	}
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
--- linux-ec2-2.6.32.orig/drivers/usb/core/generic.c
+++ linux-ec2-2.6.32/drivers/usb/core/generic.c
@@ -120,7 +120,7 @@
 		 * than a vendor-specific driver. */
 		else if (udev->descriptor.bDeviceClass !=
 						USB_CLASS_VENDOR_SPEC &&
-				(!desc || desc->bInterfaceClass !=
+				(desc && desc->bInterfaceClass !=
 						USB_CLASS_VENDOR_SPEC)) {
 			best = c;
 			break;
--- linux-ec2-2.6.32.orig/drivers/usb/core/file.c
+++ linux-ec2-2.6.32/drivers/usb/core/file.c
@@ -159,9 +159,9 @@
 int usb_register_dev(struct usb_interface *intf,
 		     struct usb_class_driver *class_driver)
 {
-	int retval = -EINVAL;
+	int retval;
 	int minor_base = class_driver->minor_base;
-	int minor = 0;
+	int minor;
 	char name[20];
 	char *temp;
 
@@ -173,12 +173,17 @@
 	 */
 	minor_base = 0;
 #endif
-	intf->minor = -1;
-
-	dbg ("looking for a minor, starting at %d", minor_base);
 
 	if (class_driver->fops == NULL)
-		goto exit;
+		return -EINVAL;
+	if (intf->minor >= 0)
+		return -EADDRINUSE;
+
+	retval = init_usb_class();
+	if (retval)
+		return retval;
+
+	dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base);
 
 	down_write(&minor_rwsem);
 	for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
@@ -186,20 +191,12 @@
 			continue;
 
 		usb_minors[minor] = class_driver->fops;
-
-		retval = 0;
+		intf->minor = minor;
 		break;
 	}
 	up_write(&minor_rwsem);
-
-	if (retval)
-		goto exit;
-
-	retval = init_usb_class();
-	if (retval)
-		goto exit;
-
-	intf->minor = minor;
+	if (intf->minor < 0)
+		return -EXFULL;
 
 	/* create a usb class device for this usb interface */
 	snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
@@ -213,11 +210,11 @@
 				      "%s", temp);
 	if (IS_ERR(intf->usb_dev)) {
 		down_write(&minor_rwsem);
-		usb_minors[intf->minor] = NULL;
+		usb_minors[minor] = NULL;
+		intf->minor = -1;
 		up_write(&minor_rwsem);
 		retval = PTR_ERR(intf->usb_dev);
 	}
-exit:
 	return retval;
 }
 EXPORT_SYMBOL_GPL(usb_register_dev);
--- linux-ec2-2.6.32.orig/drivers/usb/core/message.c
+++ linux-ec2-2.6.32/drivers/usb/core/message.c
@@ -911,11 +911,11 @@
 	if (index <= 0)
 		return NULL;
 
-	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL);
+	buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
 	if (buf) {
 		len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
 		if (len > 0) {
-			smallbuf = kmalloc(++len, GFP_KERNEL);
+			smallbuf = kmalloc(++len, GFP_NOIO);
 			if (!smallbuf)
 				return buf;
 			memcpy(smallbuf, buf, len);
@@ -1185,13 +1185,6 @@
 {
 	int i;
 
-	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
-		skip_ep0 ? "non-ep0" : "all");
-	for (i = skip_ep0; i < 16; ++i) {
-		usb_disable_endpoint(dev, i, true);
-		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
-	}
-
 	/* getting rid of interfaces will disconnect
 	 * any drivers bound to them (a key side effect)
 	 */
@@ -1221,6 +1214,13 @@
 		if (dev->state == USB_STATE_CONFIGURED)
 			usb_set_device_state(dev, USB_STATE_ADDRESS);
 	}
+
+	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+		skip_ep0 ? "non-ep0" : "all");
+	for (i = skip_ep0; i < 16; ++i) {
+		usb_disable_endpoint(dev, i, true);
+		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+	}
 }
 
 /**
@@ -1682,7 +1682,7 @@
 	if (cp) {
 		nintf = cp->desc.bNumInterfaces;
 		new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
-				GFP_KERNEL);
+				GFP_NOIO);
 		if (!new_interfaces) {
 			dev_err(&dev->dev, "Out of memory\n");
 			return -ENOMEM;
@@ -1691,7 +1691,7 @@
 		for (; n < nintf; ++n) {
 			new_interfaces[n] = kzalloc(
 					sizeof(struct usb_interface),
-					GFP_KERNEL);
+					GFP_NOIO);
 			if (!new_interfaces[n]) {
 				dev_err(&dev->dev, "Out of memory\n");
 				ret = -ENOMEM;
@@ -1792,6 +1792,7 @@
 		intf->dev.groups = usb_interface_groups;
 		intf->dev.dma_mask = dev->dev.dma_mask;
 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
+		intf->minor = -1;
 		device_initialize(&intf->dev);
 		mark_quiesced(intf);
 		dev_set_name(&intf->dev, "%d-%s:%d.%d",
--- linux-ec2-2.6.32.orig/drivers/usb/mon/mon_bin.c
+++ linux-ec2-2.6.32/drivers/usb/mon/mon_bin.c
@@ -971,7 +971,7 @@
 
 		mutex_lock(&rp->fetch_lock);
 		spin_lock_irqsave(&rp->b_lock, flags);
-		mon_free_buff(rp->b_vec, size/CHUNK_SIZE);
+		mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
 		kfree(rp->b_vec);
 		rp->b_vec  = vec;
 		rp->b_size = size;
--- linux-ec2-2.6.32.orig/drivers/usb/class/cdc-acm.c
+++ linux-ec2-2.6.32/drivers/usb/class/cdc-acm.c
@@ -170,6 +170,7 @@
 {
 	wb->use = 0;
 	acm->transmitting--;
+	usb_autopm_put_interface_async(acm->control);
 }
 
 /*
@@ -211,9 +212,12 @@
 	}
 
 	dbg("%s susp_count: %d", __func__, acm->susp_count);
+	usb_autopm_get_interface_async(acm->control);
 	if (acm->susp_count) {
-		acm->delayed_wb = wb;
-		schedule_work(&acm->waker);
+		if (!acm->delayed_wb)
+			acm->delayed_wb = wb;
+		else
+			usb_autopm_put_interface_async(acm->control);
 		spin_unlock_irqrestore(&acm->write_lock, flags);
 		return 0;	/* A white lie */
 	}
@@ -293,6 +297,8 @@
 	if (!ACM_READY(acm))
 		goto exit;
 
+	usb_mark_last_busy(acm->dev);
+
 	data = (unsigned char *)(dr + 1);
 	switch (dr->bNotificationType) {
 	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -332,7 +338,6 @@
 		break;
 	}
 exit:
-	usb_mark_last_busy(acm->dev);
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with "
@@ -530,27 +535,12 @@
 	if (!ACM_READY(acm))
 		return;
 	tty = tty_port_tty_get(&acm->port);
+	if (!tty)
+		return;
 	tty_wakeup(tty);
 	tty_kref_put(tty);
 }
 
-static void acm_waker(struct work_struct *waker)
-{
-	struct acm *acm = container_of(waker, struct acm, waker);
-	int rv;
-
-	rv = usb_autopm_get_interface(acm->control);
-	if (rv < 0) {
-		dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
-		return;
-	}
-	if (acm->delayed_wb) {
-		acm_start_wb(acm, acm->delayed_wb);
-		acm->delayed_wb = NULL;
-	}
-	usb_autopm_put_interface(acm->control);
-}
-
 /*
  * TTY handlers
  */
@@ -665,8 +655,10 @@
 		usb_kill_urb(acm->ctrlurb);
 		for (i = 0; i < ACM_NW; i++)
 			usb_kill_urb(acm->wb[i].urb);
+		tasklet_disable(&acm->urb_task);
 		for (i = 0; i < nr; i++)
 			usb_kill_urb(acm->ru[i].urb);
+		tasklet_enable(&acm->urb_task);
 		acm->control->needs_remote_wakeup = 0;
 		usb_autopm_put_interface(acm->control);
 	}
@@ -984,7 +976,8 @@
 	}
 
 	if (!buflen) {
-		if (intf->cur_altsetting->endpoint->extralen &&
+		if (intf->cur_altsetting->endpoint &&
+				intf->cur_altsetting->endpoint->extralen &&
 				intf->cur_altsetting->endpoint->extra) {
 			dev_dbg(&intf->dev,
 				"Seeking extra descriptors on endpoint\n");
@@ -1178,7 +1171,6 @@
 	acm->urb_task.func = acm_rx_tasklet;
 	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint);
-	INIT_WORK(&acm->waker, acm_waker);
 	init_waitqueue_head(&acm->drain_wait);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
@@ -1215,7 +1207,7 @@
 		if (rcv->urb == NULL) {
 			dev_dbg(&intf->dev,
 				"out of memory (read urbs usb_alloc_urb)\n");
-			goto alloc_fail7;
+			goto alloc_fail6;
 		}
 
 		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1239,7 +1231,7 @@
 		if (snd->urb == NULL) {
 			dev_dbg(&intf->dev,
 				"out of memory (write urbs usb_alloc_urb)");
-			goto alloc_fail7;
+			goto alloc_fail8;
 		}
 
 		if (usb_endpoint_xfer_int(epwrite))
@@ -1278,6 +1270,7 @@
 		i = device_create_file(&intf->dev,
 						&dev_attr_iCountryCodeRelDate);
 		if (i < 0) {
+			device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
 			kfree(acm->country_codes);
 			goto skip_countries;
 		}
@@ -1314,6 +1307,7 @@
 		usb_free_urb(acm->wb[i].urb);
 alloc_fail7:
 	acm_read_buffers_free(acm);
+alloc_fail6:
 	for (i = 0; i < num_rx_buf; i++)
 		usb_free_urb(acm->ru[i].urb);
 	usb_free_urb(acm->ctrlurb);
@@ -1343,7 +1337,6 @@
 	tasklet_enable(&acm->urb_task);
 
 	cancel_work_sync(&acm->work);
-	cancel_work_sync(&acm->waker);
 }
 
 static void acm_disconnect(struct usb_interface *intf)
@@ -1435,6 +1428,7 @@
 static int acm_resume(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata(intf);
+	struct acm_wb *wb;
 	int rv = 0;
 	int cnt;
 
@@ -1449,6 +1443,21 @@
 	mutex_lock(&acm->mutex);
 	if (acm->port.count) {
 		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+
+		spin_lock_irq(&acm->write_lock);
+		if (acm->delayed_wb) {
+			wb = acm->delayed_wb;
+			acm->delayed_wb = NULL;
+			spin_unlock_irq(&acm->write_lock);
+			acm_start_wb(acm, wb);
+		} else {
+			spin_unlock_irq(&acm->write_lock);
+		}
+
+		/*
+		 * delayed error checking because we must
+		 * do the write path at all cost
+		 */
 		if (rv < 0)
 			goto err_out;
 
@@ -1461,6 +1470,17 @@
 }
 
 #endif /* CONFIG_PM */
+
+#define NOKIA_PCSUITE_ACM_INFO(x) \
+		USB_DEVICE_AND_INTERFACE_INFO(0x0421, x, \
+		USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \
+		USB_CDC_ACM_PROTO_VENDOR)
+
+#define SAMSUNG_PCSUITE_ACM_INFO(x) \
+		USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \
+		USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \
+		USB_CDC_ACM_PROTO_VENDOR)
+
 /*
  * USB driver structure.
  */
@@ -1518,6 +1538,77 @@
 	{ USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
 	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
 	},
+	{ USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */
+	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+	},
+
+	/* Nokia S60 phones expose two ACM channels. The first is
+	 * a modem and is picked up by the standard AT-command
+	 * information below. The second is 'vendor-specific' but
+	 * is treated as a serial device at the S60 end, so we want
+	 * to expose it on Linux too. */
+	{ NOKIA_PCSUITE_ACM_INFO(0x042D), }, /* Nokia 3250 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04D8), }, /* Nokia 5500 Sport */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04C9), }, /* Nokia E50 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0419), }, /* Nokia E60 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x044D), }, /* Nokia E61 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0001), }, /* Nokia E61i */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0475), }, /* Nokia E62 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0508), }, /* Nokia E65 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0418), }, /* Nokia E70 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0425), }, /* Nokia N71 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0486), }, /* Nokia N73 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04DF), }, /* Nokia N75 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x000e), }, /* Nokia N77 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0445), }, /* Nokia N80 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x042F), }, /* Nokia N91 & N91 8GB */
+	{ NOKIA_PCSUITE_ACM_INFO(0x048E), }, /* Nokia N92 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0420), }, /* Nokia N93 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04E6), }, /* Nokia N93i  */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04B2), }, /* Nokia 5700 XpressMusic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0134), }, /* Nokia 6110 Navigator (China) */
+	{ NOKIA_PCSUITE_ACM_INFO(0x046E), }, /* Nokia 6110 Navigator */
+	{ NOKIA_PCSUITE_ACM_INFO(0x002f), }, /* Nokia 6120 classic &  */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0088), }, /* Nokia 6121 classic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00fc), }, /* Nokia 6124 classic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0042), }, /* Nokia E51 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00b0), }, /* Nokia E66 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00ab), }, /* Nokia E71 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0481), }, /* Nokia N76 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0007), }, /* Nokia N81 & N81 8GB */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0071), }, /* Nokia N82 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04F0), }, /* Nokia N95 & N95-3 NAM */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0070), }, /* Nokia N95 8GB  */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0099), }, /* Nokia 6210 Navigator, RM-367 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0128), }, /* Nokia 6210 Navigator, RM-419 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x008f), }, /* Nokia 6220 Classic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00a0), }, /* Nokia 6650 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x007b), }, /* Nokia N78 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0094), }, /* Nokia N85 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x003a), }, /* Nokia N96 & N96-3  */
+	{ NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */
+	{ NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */
+	{ NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */
+	{ NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */
+	{ NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */
+	{ SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
+
+	/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
+
+	/* control interfaces without any protocol set */
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_PROTO_NONE) },
 
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
@@ -1533,7 +1624,6 @@
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_CDMA) },
 
-	/* NOTE:  COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
 	{ }
 };
 
--- linux-ec2-2.6.32.orig/drivers/usb/class/cdc-acm.h
+++ linux-ec2-2.6.32/drivers/usb/class/cdc-acm.h
@@ -112,7 +112,6 @@
 	struct mutex mutex;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
-	struct work_struct waker;
 	wait_queue_head_t drain_wait;			/* close processing */
 	struct tasklet_struct urb_task;                 /* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
--- linux-ec2-2.6.32.orig/drivers/usb/class/usbtmc.c
+++ linux-ec2-2.6.32/drivers/usb/class/usbtmc.c
@@ -562,10 +562,16 @@
 		n_bytes = roundup(12 + this_part, 4);
 		memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part));
 
-		retval = usb_bulk_msg(data->usb_dev,
-				      usb_sndbulkpipe(data->usb_dev,
-						      data->bulk_out),
-				      buffer, n_bytes, &actual, USBTMC_TIMEOUT);
+		do {
+			retval = usb_bulk_msg(data->usb_dev,
+					      usb_sndbulkpipe(data->usb_dev,
+							      data->bulk_out),
+					      buffer, n_bytes,
+					      &actual, USBTMC_TIMEOUT);
+			if (retval != 0)
+				break;
+			n_bytes -= actual;
+		} while (n_bytes);
 
 		data->bTag_last_write = data->bTag;
 		data->bTag++;
--- linux-ec2-2.6.32.orig/drivers/usb/musb/omap2430.c
+++ linux-ec2-2.6.32/drivers/usb/musb/omap2430.c
@@ -309,6 +309,7 @@
 
 int musb_platform_exit(struct musb *musb)
 {
+	del_timer_sync(&musb_idle_timer);
 
 	omap_vbus_power(musb, 0 /*off*/, 1);
 
--- linux-ec2-2.6.32.orig/drivers/usb/musb/blackfin.c
+++ linux-ec2-2.6.32/drivers/usb/musb/blackfin.c
@@ -248,8 +248,10 @@
 
 	usb_nop_xceiv_register();
 	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv)
+	if (!musb->xceiv) {
+		gpio_free(musb->config->gpio_vrsel);
 		return -ENODEV;
+	}
 
 	if (ANOMALY_05000346) {
 		bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
--- linux-ec2-2.6.32.orig/drivers/usb/musb/musb_gadget.c
+++ linux-ec2-2.6.32/drivers/usb/musb/musb_gadget.c
@@ -577,11 +577,19 @@
 {
 	const u8		epnum = req->epnum;
 	struct usb_request	*request = &req->request;
-	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
+	struct musb_ep		*musb_ep;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	unsigned		fifo_count = 0;
-	u16			len = musb_ep->packet_sz;
+	u16			len;
 	u16			csr = musb_readw(epio, MUSB_RXCSR);
+	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];
+
+	if (hw_ep->is_shared_fifo)
+		musb_ep = &hw_ep->ep_in;
+	else
+		musb_ep = &hw_ep->ep_out;
+
+	len = musb_ep->packet_sz;
 
 	/* We shouldn't get here while DMA is active, but we do... */
 	if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
@@ -749,9 +757,15 @@
 	u16			csr;
 	struct usb_request	*request;
 	void __iomem		*mbase = musb->mregs;
-	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
+	struct musb_ep		*musb_ep;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
 	struct dma_channel	*dma;
+	struct musb_hw_ep	*hw_ep = &musb->endpoints[epnum];
+
+	if (hw_ep->is_shared_fifo)
+		musb_ep = &hw_ep->ep_in;
+	else
+		musb_ep = &hw_ep->ep_out;
 
 	musb_ep_select(mbase, epnum);
 
@@ -1074,7 +1088,7 @@
 /*
  * Context: controller locked, IRQs blocked.
  */
-static void musb_ep_restart(struct musb *musb, struct musb_request *req)
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
 {
 	DBG(3, "<== %s request %p len %u on hw_ep%d\n",
 		req->tx ? "TX/IN" : "RX/OUT",
--- linux-ec2-2.6.32.orig/drivers/usb/musb/musb_gadget_ep0.c
+++ linux-ec2-2.6.32/drivers/usb/musb/musb_gadget_ep0.c
@@ -199,7 +199,6 @@
 static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req)
 {
 	musb_g_giveback(&musb->endpoints[0].ep_in, req, 0);
-	musb->ep0_state = MUSB_EP0_STAGE_SETUP;
 }
 
 /*
@@ -370,6 +369,7 @@
 					ctrlrequest->wIndex & 0x0f;
 				struct musb_ep		*musb_ep;
 				struct musb_hw_ep	*ep;
+				struct musb_request	*request;
 				void __iomem		*regs;
 				int			is_in;
 				u16			csr;
@@ -412,6 +412,14 @@
 							csr);
 				}
 
+				/* Maybe start the first request in the queue */
+				request = to_musb_request(
+						next_request(musb_ep));
+				if (!musb_ep->busy && request) {
+					DBG(3, "restarting the request\n");
+					musb_ep_restart(musb, request);
+				}
+
 				/* select ep0 again */
 				musb_ep_select(mbase, 0);
 				handled = 1;
@@ -648,7 +656,7 @@
 			musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
 			break;
 		default:
-			ERR("SetupEnd came in a wrong ep0stage %s",
+			ERR("SetupEnd came in a wrong ep0stage %s\n",
 			    decode_ep0stage(musb->ep0_state));
 		}
 		csr = musb_readw(regs, MUSB_CSR0);
@@ -771,12 +779,18 @@
 				handled = service_zero_data_request(
 						musb, &setup);
 
+				/*
+				 * We're expecting no data in any case, so
+				 * always set the DATAEND bit -- doing this
+				 * here helps avoid SetupEnd interrupt coming
+				 * in the idle stage when we're stalling...
+				 */
+				musb->ackpend |= MUSB_CSR0_P_DATAEND;
+
 				/* status stage might be immediate */
-				if (handled > 0) {
-					musb->ackpend |= MUSB_CSR0_P_DATAEND;
+				if (handled > 0)
 					musb->ep0_state =
 						MUSB_EP0_STAGE_STATUSIN;
-				}
 				break;
 
 			/* sequence #1 (IN to host), includes GET_STATUS
--- linux-ec2-2.6.32.orig/drivers/usb/musb/musb_gadget.h
+++ linux-ec2-2.6.32/drivers/usb/musb/musb_gadget.h
@@ -105,4 +105,6 @@
 
 extern int musb_gadget_set_halt(struct usb_ep *ep, int value);
 
+extern void musb_ep_restart(struct musb *, struct musb_request *);
+
 #endif		/* __MUSB_GADGET_H */
--- linux-ec2-2.6.32.orig/drivers/usb/musb/musb_core.c
+++ linux-ec2-2.6.32/drivers/usb/musb/musb_core.c
@@ -1792,6 +1792,7 @@
 	INIT_LIST_HEAD(&musb->out_bulk);
 
 	hcd->uses_new_polling = 1;
+	hcd->has_tt = 1;
 
 	musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
 	musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
--- linux-ec2-2.6.32.orig/drivers/usb/misc/appledisplay.c
+++ linux-ec2-2.6.32/drivers/usb/misc/appledisplay.c
@@ -72,8 +72,8 @@
 	struct usb_device *udev;	/* usb device */
 	struct urb *urb;		/* usb request block */
 	struct backlight_device *bd;	/* backlight device */
-	char *urbdata;			/* interrupt URB data buffer */
-	char *msgdata;			/* control message data buffer */
+	u8 *urbdata;			/* interrupt URB data buffer */
+	u8 *msgdata;			/* control message data buffer */
 
 	struct delayed_work work;
 	int button_pressed;
--- linux-ec2-2.6.32.orig/drivers/usb/misc/usbtest.c
+++ linux-ec2-2.6.32/drivers/usb/misc/usbtest.c
@@ -1382,7 +1382,6 @@
 			break;
 		}
 	}
-	simple_free_urb (urb);
 
 	ctx->pending--;
 	if (ctx->pending == 0) {
@@ -1499,6 +1498,7 @@
 			}
 
 			simple_free_urb (urbs [i]);
+			urbs[i] = NULL;
 			context.pending--;
 			context.submit_error = 1;
 			break;
@@ -1508,6 +1508,10 @@
 
 	wait_for_completion (&context.done);
 
+	for (i = 0; i < param->sglen; i++) {
+		if (urbs[i])
+			simple_free_urb(urbs[i]);
+	}
 	/*
 	 * Isochronous transfers are expected to fail sometimes.  As an
 	 * arbitrary limit, we will report an error if any submissions
--- linux-ec2-2.6.32.orig/drivers/usb/misc/emi62.c
+++ linux-ec2-2.6.32/drivers/usb/misc/emi62.c
@@ -167,7 +167,7 @@
 			err("%s - error loading firmware: error = %d", __func__, err);
 			goto wraperr;
 		}
-	} while (i > 0);
+	} while (rec);
 
 	/* Assert reset (stop the CPU in the EMI) */
 	err = emi62_set_reset(dev,1);
--- linux-ec2-2.6.32.orig/drivers/usb/misc/iowarrior.c
+++ linux-ec2-2.6.32/drivers/usb/misc/iowarrior.c
@@ -373,7 +373,7 @@
 	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
 	case USB_DEVICE_ID_CODEMERCS_IOW40:
 		/* IOW24 and IOW40 use a synchronous call */
-		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
+		buf = kmalloc(count, GFP_KERNEL);
 		if (!buf) {
 			retval = -ENOMEM;
 			goto exit;
@@ -552,6 +552,7 @@
 			/* needed for power consumption */
 			struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;
 
+			memset(&info, 0, sizeof(info));
 			/* directly from the descriptor */
 			info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
 			info.product = dev->product_id;
--- linux-ec2-2.6.32.orig/drivers/usb/misc/usbsevseg.c
+++ linux-ec2-2.6.32/drivers/usb/misc/usbsevseg.c
@@ -185,7 +185,7 @@
 								\
 	return count;						\
 }								\
-static DEVICE_ATTR(name, S_IWUGO | S_IRUGO, show_attr_##name, set_attr_##name);
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_attr_##name, set_attr_##name);
 
 static ssize_t show_attr_text(struct device *dev,
 	struct device_attribute *attr, char *buf)
@@ -216,7 +216,7 @@
 	return count;
 }
 
-static DEVICE_ATTR(text, S_IWUGO | S_IRUGO, show_attr_text, set_attr_text);
+static DEVICE_ATTR(text, S_IRUGO | S_IWUSR, show_attr_text, set_attr_text);
 
 static ssize_t show_attr_decimals(struct device *dev,
 	struct device_attribute *attr, char *buf)
@@ -265,8 +265,7 @@
 	return count;
 }
 
-static DEVICE_ATTR(decimals, S_IWUGO | S_IRUGO,
-	show_attr_decimals, set_attr_decimals);
+static DEVICE_ATTR(decimals, S_IRUGO | S_IWUSR, show_attr_decimals, set_attr_decimals);
 
 static ssize_t show_attr_textmode(struct device *dev,
 	struct device_attribute *attr, char *buf)
@@ -312,8 +311,7 @@
 	return -EINVAL;
 }
 
-static DEVICE_ATTR(textmode, S_IWUGO | S_IRUGO,
-	show_attr_textmode, set_attr_textmode);
+static DEVICE_ATTR(textmode, S_IRUGO | S_IWUSR, show_attr_textmode, set_attr_textmode);
 
 
 MYDEV_ATTR_SIMPLE_UNSIGNED(powered, update_display_powered);
--- linux-ec2-2.6.32.orig/drivers/usb/misc/cypress_cy7c63.c
+++ linux-ec2-2.6.32/drivers/usb/misc/cypress_cy7c63.c
@@ -195,11 +195,9 @@
 	return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
 }
 
-static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO,
-		   get_port0_handler, set_port0_handler);
+static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR, get_port0_handler, set_port0_handler);
 
-static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO,
-		   get_port1_handler, set_port1_handler);
+static DEVICE_ATTR(port1, S_IRUGO | S_IWUSR, get_port1_handler, set_port1_handler);
 
 
 static int cypress_probe(struct usb_interface *interface,
--- linux-ec2-2.6.32.orig/drivers/usb/misc/usbled.c
+++ linux-ec2-2.6.32/drivers/usb/misc/usbled.c
@@ -94,7 +94,7 @@
 	change_color(led);						\
 	return count;							\
 }									\
-static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, show_##value, set_##value);
 show_set(blue);
 show_set(red);
 show_set(green);
--- linux-ec2-2.6.32.orig/drivers/usb/misc/trancevibrator.c
+++ linux-ec2-2.6.32/drivers/usb/misc/trancevibrator.c
@@ -85,7 +85,7 @@
 	return count;
 }
 
-static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed);
+static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR, show_speed, set_speed);
 
 static int tv_probe(struct usb_interface *interface,
 		    const struct usb_device_id *id)
--- linux-ec2-2.6.32.orig/drivers/usb/misc/uss720.c
+++ linux-ec2-2.6.32/drivers/usb/misc/uss720.c
@@ -3,7 +3,7 @@
 /*
  *	uss720.c  --  USS720 USB Parport Cable.
  *
- *	Copyright (C) 1999, 2005
+ *	Copyright (C) 1999, 2005, 2010
  *	    Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -176,12 +176,11 @@
 	spin_lock_irqsave(&priv->asynclock, flags);
 	list_add_tail(&rq->asynclist, &priv->asynclist);
 	spin_unlock_irqrestore(&priv->asynclock, flags);
+	kref_get(&rq->ref_count);
 	ret = usb_submit_urb(rq->urb, mem_flags);
-	if (!ret) {
-		kref_get(&rq->ref_count);
+	if (!ret)
 		return rq;
-	}
-	kref_put(&rq->ref_count, destroy_async);
+	destroy_async(&rq->ref_count);
 	err("submit_async_request submit_urb failed with %d", ret);
 	return NULL;
 }
@@ -775,6 +774,8 @@
 	{ USB_DEVICE(0x0557, 0x2001) },
 	{ USB_DEVICE(0x0729, 0x1284) },
 	{ USB_DEVICE(0x1293, 0x0002) },
+	{ USB_DEVICE(0x1293, 0x0002) },
+	{ USB_DEVICE(0x050d, 0x0002) },
 	{ }						/* Terminating entry */
 };
 
--- linux-ec2-2.6.32.orig/drivers/usb/misc/sisusbvga/sisusb.c
+++ linux-ec2-2.6.32/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2435,7 +2435,8 @@
 	}
 
 	if (!sisusb->devinit) {
-		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH ||
+		    sisusb->sisusb_dev->speed == USB_SPEED_SUPER) {
 			if (sisusb_init_gfxdevice(sisusb, 0)) {
 				mutex_unlock(&sisusb->lock);
 				dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
@@ -3007,6 +3008,7 @@
 #else
 			x.sisusb_conactive  = 0;
 #endif
+			memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
 
 			if (copy_to_user((void __user *)arg, &x, sizeof(x)))
 				retval = -EFAULT;
@@ -3167,7 +3169,7 @@
 
 	sisusb->present = 1;
 
-	if (dev->speed == USB_SPEED_HIGH) {
+	if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) {
 		int initscreen = 1;
 #ifdef INCL_SISUSB_CON
 		if (sisusb_first_vc > 0 &&
@@ -3245,6 +3247,7 @@
 	{ USB_DEVICE(0x0711, 0x0902) },
 	{ USB_DEVICE(0x0711, 0x0903) },
 	{ USB_DEVICE(0x0711, 0x0918) },
+	{ USB_DEVICE(0x0711, 0x0920) },
 	{ USB_DEVICE(0x182d, 0x021c) },
 	{ USB_DEVICE(0x182d, 0x0269) },
 	{ }
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-mem.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-mem.c
@@ -136,7 +136,7 @@
 
 static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 {
-	free_cached_itd_list(ehci);
+	free_cached_lists(ehci);
 	if (ehci->async)
 		qh_put (ehci->async);
 	ehci->async = NULL;
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-hcd.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-hcd.c
@@ -103,6 +103,9 @@
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
+/* for ASPM quirk of ISOC on AMD SB800 */
+static struct pci_dev *amd_nb_dev;
+
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
@@ -502,6 +505,11 @@
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
+	if (amd_nb_dev) {
+		pci_dev_put(amd_nb_dev);
+		amd_nb_dev = NULL;
+	}
+
 #ifdef	EHCI_STATS
 	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
 		ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
@@ -537,17 +545,29 @@
 	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
 	ehci->iaa_watchdog.data = (unsigned long) ehci;
 
+	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+
 	/*
 	 * hw default: 1K periodic list heads, one per frame.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
 	ehci->periodic_size = DEFAULT_I_TDPS;
 	INIT_LIST_HEAD(&ehci->cached_itd_list);
+	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+
+	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
+		/* periodic schedule size can be smaller than default */
+		switch (EHCI_TUNE_FLS) {
+		case 0: ehci->periodic_size = 1024; break;
+		case 1: ehci->periodic_size = 512; break;
+		case 2: ehci->periodic_size = 256; break;
+		default:	BUG();
+		}
+	}
 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
 		return retval;
 
 	/* controllers may cache some of the periodic schedule ... */
-	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
 	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
 		ehci->i_thresh = 8;
 	else					// N microframes cached
@@ -596,12 +616,6 @@
 		/* periodic schedule size can be smaller than default */
 		temp &= ~(3 << 2);
 		temp |= (EHCI_TUNE_FLS << 2);
-		switch (EHCI_TUNE_FLS) {
-		case 0: ehci->periodic_size = 1024; break;
-		case 1: ehci->periodic_size = 512; break;
-		case 2: ehci->periodic_size = 256; break;
-		default:	BUG();
-		}
 	}
 	ehci->command = temp;
 
@@ -785,9 +799,10 @@
 
 			/* start 20 msec resume signaling from this port,
 			 * and make khubd collect PORT_STAT_C_SUSPEND to
-			 * stop that signaling.
+			 * stop that signaling.  Use 5 ms extra for safety,
+			 * like usb_port_resume() does.
 			 */
-			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
+			ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
 			ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
 			mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
 		}
@@ -992,7 +1007,7 @@
 	/* endpoints can be iso streams.  for now, we don't
 	 * accelerate iso completions ... so spin a while.
 	 */
-	if (qh->hw->hw_info1 == 0) {
+	if (qh->hw == NULL) {
 		ehci_vdbg (ehci, "iso delay\n");
 		goto idle_timeout;
 	}
@@ -1006,10 +1021,11 @@
 				tmp && tmp != qh;
 				tmp = tmp->qh_next.qh)
 			continue;
-		/* periodic qh self-unlinks on empty */
-		if (!tmp)
-			goto nogood;
-		unlink_async (ehci, qh);
+		/* periodic qh self-unlinks on empty, and a COMPLETING qh
+		 * may already be unlinked.
+		 */
+		if (tmp)
+			unlink_async(ehci, qh);
 		/* FALL THROUGH */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
 	case QH_STATE_UNLINK_WAIT:
@@ -1026,7 +1042,6 @@
 		}
 		/* else FALL THROUGH */
 	default:
-nogood:
 		/* caller was supposed to have unlinked any requests;
 		 * that's not our job.  just leak this memory.
 		 */
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-hub.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-hub.c
@@ -120,9 +120,26 @@
 	del_timer_sync(&ehci->watchdog);
 	del_timer_sync(&ehci->iaa_watchdog);
 
-	port = HCS_N_PORTS (ehci->hcs_params);
 	spin_lock_irq (&ehci->lock);
 
+	/* Once the controller is stopped, port resumes that are already
+	 * in progress won't complete.  Hence if remote wakeup is enabled
+	 * for the root hub and any ports are in the middle of a resume or
+	 * remote wakeup, we must fail the suspend.
+	 */
+	if (hcd->self.root_hub->do_remote_wakeup) {
+		port = HCS_N_PORTS(ehci->hcs_params);
+		while (port--) {
+			if (ehci->reset_done[port] != 0) {
+				spin_unlock_irq(&ehci->lock);
+				ehci_dbg(ehci, "suspend failed because "
+						"port %d is resuming\n",
+						port + 1);
+				return -EBUSY;
+			}
+		}
+	}
+
 	/* stop schedules, clean any completed work */
 	if (HC_IS_RUNNING(hcd->state)) {
 		ehci_quiesce (ehci);
@@ -138,6 +155,7 @@
 	 */
 	ehci->bus_suspended = 0;
 	ehci->owned_ports = 0;
+	port = HCS_N_PORTS(ehci->hcs_params);
 	while (port--) {
 		u32 __iomem	*reg = &ehci->regs->port_status [port];
 		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
@@ -274,6 +292,16 @@
 	/* manually resume the ports we suspended during bus_suspend() */
 	i = HCS_N_PORTS (ehci->hcs_params);
 	while (i--) {
+		/* clear phy low power mode before resume */
+		if (ehci->has_hostpc) {
+			u32 __iomem	*hostpc_reg =
+				(u32 __iomem *)((u8 *)ehci->regs
+				+ HOSTPC0 + 4 * (i & 0xff));
+			temp = ehci_readl(ehci, hostpc_reg);
+			ehci_writel(ehci, temp & ~HOSTPC_PHCD,
+				hostpc_reg);
+			mdelay(5);
+		}
 		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
 		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
 		if (test_bit(i, &ehci->bus_suspended) &&
@@ -658,6 +686,13 @@
 			if (temp & PORT_SUSPEND) {
 				if ((temp & PORT_PE) == 0)
 					goto error;
+				/* clear phy low power mode before resume */
+				if (hostpc_reg) {
+					temp1 = ehci_readl(ehci, hostpc_reg);
+					ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
+						hostpc_reg);
+					mdelay(5);
+				}
 				/* resume signaling for 20 msec */
 				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
 				ehci_writel(ehci, temp | PORT_RESUME,
--- linux-ec2-2.6.32.orig/drivers/usb/host/ohci-pci.c
+++ linux-ec2-2.6.32/drivers/usb/host/ohci-pci.c
@@ -201,6 +201,20 @@
 	return 0;
 }
 
+/* nVidia controllers continue to drive Reset signalling on the bus
+ * even after system shutdown, wasting power.  This flag tells the
+ * shutdown routine to leave the controller OPERATIONAL instead of RESET.
+ */
+static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+
+	return 0;
+}
+
 /*
  * The hardware normally enables the A-link power management feature, which
  * lets the system lower the power consumption in idle states.
@@ -332,6 +346,10 @@
 		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
 		.driver_data = (unsigned long)ohci_quirk_amd700,
 	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
+	},
 
 	/* FIXME for some of the early AMD 760 southbridges, OHCI
 	 * won't work at all.  blacklist them.
--- linux-ec2-2.6.32.orig/drivers/usb/host/uhci-hub.c
+++ linux-ec2-2.6.32/drivers/usb/host/uhci-hub.c
@@ -167,7 +167,7 @@
 				/* Port received a wakeup request */
 				set_bit(port, &uhci->resuming_ports);
 				uhci->ports_timeout = jiffies +
-						msecs_to_jiffies(20);
+						msecs_to_jiffies(25);
 
 				/* Make sure we see the port again
 				 * after the resuming period is over. */
--- linux-ec2-2.6.32.orig/drivers/usb/host/xhci.h
+++ linux-ec2-2.6.32/drivers/usb/host/xhci.h
@@ -609,6 +609,10 @@
 #define MAX_PACKET_MASK		(0xffff << 16)
 #define MAX_PACKET_DECODED(p)	(((p) >> 16) & 0xffff)
 
+/* tx_info bitmasks */
+#define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
+#define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
+
 
 /**
  * struct xhci_input_control_context
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-ppc-of.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-ppc-of.c
@@ -192,17 +192,19 @@
 	}
 
 	rv = usb_add_hcd(hcd, irq, 0);
-	if (rv == 0)
-		return 0;
+	if (rv)
+		goto err_ehci;
 
+	return 0;
+
+err_ehci:
+	if (ehci->has_amcc_usb23)
+		iounmap(ehci->ohci_hcctrl_reg);
 	iounmap(hcd->regs);
 err_ioremap:
 	irq_dispose_mapping(irq);
 err_irq:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
-	if (ehci->has_amcc_usb23)
-		iounmap(ehci->ohci_hcctrl_reg);
 err_rmr:
 	usb_put_hcd(hcd);
 
--- linux-ec2-2.6.32.orig/drivers/usb/host/xhci-mem.c
+++ linux-ec2-2.6.32/drivers/usb/host/xhci-mem.c
@@ -496,6 +496,19 @@
 	return EP_INTERVAL(interval);
 }
 
+/* The "Mult" field in the endpoint context is only set for SuperSpeed devices.
+ * High speed endpoint descriptors can define "the number of additional
+ * transaction opportunities per microframe", but that goes in the Max Burst
+ * endpoint context field.
+ */
+static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
+		struct usb_host_endpoint *ep)
+{
+	if (udev->speed != USB_SPEED_SUPER || !ep->ss_ep_comp)
+		return 0;
+	return ep->ss_ep_comp->desc.bmAttributes;
+}
+
 static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
 		struct usb_host_endpoint *ep)
 {
@@ -526,6 +539,36 @@
 	return type;
 }
 
+/* Return the maximum endpoint service interval time (ESIT) payload.
+ * Basically, this is the maxpacket size, multiplied by the burst size
+ * and mult size.
+ */
+static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
+		struct usb_device *udev,
+		struct usb_host_endpoint *ep)
+{
+	int max_burst;
+	int max_packet;
+
+	/* Only applies for interrupt or isochronous endpoints */
+	if (usb_endpoint_xfer_control(&ep->desc) ||
+			usb_endpoint_xfer_bulk(&ep->desc))
+		return 0;
+
+	if (udev->speed == USB_SPEED_SUPER) {
+		if (ep->ss_ep_comp)
+			return ep->ss_ep_comp->desc.wBytesPerInterval;
+		xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
+		/* Assume no bursts, no multiple opportunities to send. */
+		return ep->desc.wMaxPacketSize;
+	}
+
+	max_packet = ep->desc.wMaxPacketSize & 0x3ff;
+	max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
+	/* A 0 in max burst means 1 transfer per ESIT */
+	return max_packet * (max_burst + 1);
+}
+
 int xhci_endpoint_init(struct xhci_hcd *xhci,
 		struct xhci_virt_device *virt_dev,
 		struct usb_device *udev,
@@ -537,6 +580,7 @@
 	struct xhci_ring *ep_ring;
 	unsigned int max_packet;
 	unsigned int max_burst;
+	u32 max_esit_payload;
 
 	ep_index = xhci_get_endpoint_index(&ep->desc);
 	ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
@@ -550,6 +594,7 @@
 	ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
 
 	ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
+	ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep));
 
 	/* FIXME dig Mult and streams info out of ep companion desc */
 
@@ -595,6 +640,26 @@
 	default:
 		BUG();
 	}
+	max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep);
+	ep_ctx->tx_info = MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload);
+
+	/*
+	 * XXX no idea how to calculate the average TRB buffer length for bulk
+	 * endpoints, as the driver gives us no clue how big each scatter gather
+	 * list entry (or buffer) is going to be.
+	 *
+	 * For isochronous and interrupt endpoints, we set it to the max
+	 * available, until we have new API in the USB core to allow drivers to
+	 * declare how much bandwidth they actually need.
+	 *
+	 * Normally, it would be calculated by taking the total of the buffer
+	 * lengths in the TD and then dividing by the number of TRBs in a TD,
+	 * including link TRBs, No-op TRBs, and Event data TRBs.  Since we don't
+	 * use Event Data TRBs, and we don't chain in a link TRB on short
+	 * transfers, we're basically dividing by 1.
+	 */
+	ep_ctx->tx_info |= AVG_TRB_LENGTH_FOR_EP(max_esit_payload);
+
 	/* FIXME Debug endpoint context */
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/usb/host/ohci.h
+++ linux-ec2-2.6.32/drivers/usb/host/ohci.h
@@ -403,6 +403,7 @@
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
 #define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
 #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
+#define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
 	// there are also chip quirks/bugs in init logic
 
 	struct work_struct	nec_work;	/* Worker for NEC quirk */
--- linux-ec2-2.6.32.orig/drivers/usb/host/ohci-pnx4008.c
+++ linux-ec2-2.6.32/drivers/usb/host/ohci-pnx4008.c
@@ -327,7 +327,7 @@
 	}
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c);
 	i2c_put_adapter(i2c_adap);
@@ -411,7 +411,7 @@
 out2:
 	clk_put(usb_clk);
 out1:
-	i2c_unregister_client(isp1301_i2c_client);
+	i2c_unregister_device(isp1301_i2c_client);
 	isp1301_i2c_client = NULL;
 out_i2c_driver:
 	i2c_del_driver(&isp1301_driver);
@@ -430,7 +430,7 @@
 	pnx4008_unset_usb_bits();
 	clk_disable(usb_clk);
 	clk_put(usb_clk);
-	i2c_unregister_client(isp1301_i2c_client);
+	i2c_unregister_device(isp1301_i2c_client);
 	isp1301_i2c_client = NULL;
 	i2c_del_driver(&isp1301_driver);
 
--- linux-ec2-2.6.32.orig/drivers/usb/host/ohci-hub.c
+++ linux-ec2-2.6.32/drivers/usb/host/ohci-hub.c
@@ -697,7 +697,7 @@
 	u16		wLength
 ) {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports = hcd_to_bus (hcd)->root_hub->maxchild;
+	int		ports = ohci->num_ports;
 	u32		temp;
 	int		retval = 0;
 
--- linux-ec2-2.6.32.orig/drivers/usb/host/xhci-ring.c
+++ linux-ec2-2.6.32/drivers/usb/host/xhci-ring.c
@@ -124,7 +124,7 @@
 		*seg = (*seg)->next;
 		*trb = ((*seg)->trbs);
 	} else {
-		*trb = (*trb)++;
+		(*trb)++;
 	}
 }
 
@@ -241,10 +241,27 @@
 	int i;
 	union xhci_trb *enq = ring->enqueue;
 	struct xhci_segment *enq_seg = ring->enq_seg;
+	struct xhci_segment *cur_seg;
+	unsigned int left_on_ring;
 
 	/* Check if ring is empty */
-	if (enq == ring->dequeue)
+	if (enq == ring->dequeue) {
+		/* Can't use link trbs */
+		left_on_ring = TRBS_PER_SEGMENT - 1;
+		for (cur_seg = enq_seg->next; cur_seg != enq_seg;
+				cur_seg = cur_seg->next)
+			left_on_ring += TRBS_PER_SEGMENT - 1;
+
+		/* Always need one TRB free in the ring. */
+		left_on_ring -= 1;
+		if (num_trbs > left_on_ring) {
+			xhci_warn(xhci, "Not enough room on ring; "
+					"need %u TRBs, %u TRBs left\n",
+					num_trbs, left_on_ring);
+			return 0;
+		}
 		return 1;
+	}
 	/* Make sure there's an extra empty TRB available */
 	for (i = 0; i <= num_trbs; ++i) {
 		if (enq == ring->dequeue)
@@ -333,7 +350,8 @@
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if (TRB_TYPE(generic_trb->field[3]) == TRB_LINK &&
+		if ((generic_trb->field[3] & TRB_TYPE_BITMASK) ==
+				TRB_TYPE(TRB_LINK) &&
 				(generic_trb->field[3] & LINK_TOGGLE))
 			*cycle_state = ~(*cycle_state) & 0x1;
 		cur_seg = cur_seg->next;
@@ -373,8 +391,11 @@
 	state->new_deq_seg = find_trb_seg(cur_td->start_seg,
 			dev->eps[ep_index].stopped_trb,
 			&state->new_cycle_state);
-	if (!state->new_deq_seg)
-		BUG();
+	if (!state->new_deq_seg) {
+		WARN_ON(1);
+		return;
+	}
+
 	/* Dig out the cycle state saved by the xHC during the stop ep cmd */
 	xhci_dbg(xhci, "Finding endpoint context\n");
 	ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
@@ -385,15 +406,31 @@
 	state->new_deq_seg = find_trb_seg(state->new_deq_seg,
 			state->new_deq_ptr,
 			&state->new_cycle_state);
-	if (!state->new_deq_seg)
-		BUG();
+	if (!state->new_deq_seg) {
+		WARN_ON(1);
+		return;
+	}
 
 	trb = &state->new_deq_ptr->generic;
-	if (TRB_TYPE(trb->field[3]) == TRB_LINK &&
+	if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
 				(trb->field[3] & LINK_TOGGLE))
 		state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
+	/*
+	 * If there is only one segment in a ring, find_trb_seg()'s while loop
+	 * will not run, and it will return before it has a chance to see if it
+	 * needs to toggle the cycle bit.  It can't tell if the stalled transfer
+	 * ended just before the link TRB on a one-segment ring, or if the TD
+	 * wrapped around the top of the ring, because it doesn't have the TD in
+	 * question.  Look for the one-segment case where stalled TRB's address
+	 * is greater than the new dequeue pointer address.
+	 */
+	if (ep_ring->first_seg == ep_ring->first_seg->next &&
+			state->new_deq_ptr < dev->eps[ep_index].stopped_trb)
+		state->new_cycle_state ^= 0x1;
+	xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state);
+
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
 			state->new_deq_seg);
@@ -548,6 +585,8 @@
 		/* Otherwise just ring the doorbell to restart the ring */
 		ring_ep_doorbell(xhci, slot_id, ep_index);
 	}
+	ep->stopped_td = NULL;
+	ep->stopped_trb = NULL;
 
 	/*
 	 * Drop the lock and complete the URBs in the cancelled TD list.
@@ -1065,8 +1104,13 @@
 
 			ep->stopped_td = td;
 			ep->stopped_trb = event_trb;
+
 			xhci_queue_reset_ep(xhci, slot_id, ep_index);
 			xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
+
+			ep->stopped_td = NULL;
+			ep->stopped_trb = NULL;
+
 			xhci_ring_cmd_db(xhci);
 			goto td_cleanup;
 		default:
@@ -1186,8 +1230,10 @@
 			for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
 					cur_trb != event_trb;
 					next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
-				if (TRB_TYPE(cur_trb->generic.field[3]) != TRB_TR_NOOP &&
-						TRB_TYPE(cur_trb->generic.field[3]) != TRB_LINK)
+				if ((cur_trb->generic.field[3] &
+				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
+				    (cur_trb->generic.field[3] &
+				 TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
 					td->urb->actual_length +=
 						TRB_LEN(cur_trb->generic.field[2]);
 			}
@@ -1458,12 +1504,13 @@
 
 		/* Scatter gather list entries may cross 64KB boundaries */
 		running_total = TRB_MAX_BUFF_SIZE -
-			(sg_dma_address(sg) & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+			(sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1));
+		running_total &= TRB_MAX_BUFF_SIZE - 1;
 		if (running_total != 0)
 			num_trbs++;
 
 		/* How many more 64KB chunks to transfer, how many more TRBs? */
-		while (running_total < sg_dma_len(sg)) {
+		while (running_total < sg_dma_len(sg) && running_total < temp) {
 			num_trbs++;
 			running_total += TRB_MAX_BUFF_SIZE;
 		}
@@ -1488,11 +1535,11 @@
 static void check_trb_math(struct urb *urb, int num_trbs, int running_total)
 {
 	if (num_trbs != 0)
-		dev_dbg(&urb->dev->dev, "%s - ep %#x - Miscalculated number of "
+		dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated number of "
 				"TRBs, %d left\n", __func__,
 				urb->ep->desc.bEndpointAddress, num_trbs);
 	if (running_total != urb->transfer_buffer_length)
-		dev_dbg(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, "
+		dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, "
 				"queued %#x (%d), asked for %#x (%d)\n",
 				__func__,
 				urb->ep->desc.bEndpointAddress,
@@ -1599,8 +1646,7 @@
 	sg = urb->sg->sg;
 	addr = (u64) sg_dma_address(sg);
 	this_sg_len = sg_dma_len(sg);
-	trb_buff_len = TRB_MAX_BUFF_SIZE -
-		(addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+	trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1));
 	trb_buff_len = min_t(int, trb_buff_len, this_sg_len);
 	if (trb_buff_len > urb->transfer_buffer_length)
 		trb_buff_len = urb->transfer_buffer_length;
@@ -1635,7 +1681,7 @@
 				(unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
 				(unsigned int) addr + trb_buff_len);
 		if (TRB_MAX_BUFF_SIZE -
-				(addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)) < trb_buff_len) {
+				(addr & (TRB_MAX_BUFF_SIZE - 1)) < trb_buff_len) {
 			xhci_warn(xhci, "WARN: sg dma xfer crosses 64KB boundaries!\n");
 			xhci_dbg(xhci, "Next boundary at %#x, end dma = %#x\n",
 					(unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
@@ -1673,7 +1719,7 @@
 		}
 
 		trb_buff_len = TRB_MAX_BUFF_SIZE -
-			(addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+			(addr & (TRB_MAX_BUFF_SIZE - 1));
 		trb_buff_len = min_t(int, trb_buff_len, this_sg_len);
 		if (running_total + trb_buff_len > urb->transfer_buffer_length)
 			trb_buff_len =
@@ -1708,7 +1754,8 @@
 	num_trbs = 0;
 	/* How much data is (potentially) left before the 64KB boundary? */
 	running_total = TRB_MAX_BUFF_SIZE -
-		(urb->transfer_dma & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
+		(urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1));
+	running_total &= TRB_MAX_BUFF_SIZE - 1;
 
 	/* If there's some data on this 64KB chunk, or we have to send a
 	 * zero-length transfer, we need at least one TRB
@@ -1747,8 +1794,8 @@
 	/* How much data is in the first TRB? */
 	addr = (u64) urb->transfer_dma;
 	trb_buff_len = TRB_MAX_BUFF_SIZE -
-		(urb->transfer_dma & ((1 << TRB_MAX_BUFF_SHIFT) - 1));
-	if (urb->transfer_buffer_length < trb_buff_len)
+		(urb->transfer_dma & (TRB_MAX_BUFF_SIZE - 1));
+	if (trb_buff_len > urb->transfer_buffer_length)
 		trb_buff_len = urb->transfer_buffer_length;
 
 	first_trb = true;
--- linux-ec2-2.6.32.orig/drivers/usb/host/uhci-hcd.c
+++ linux-ec2-2.6.32/drivers/usb/host/uhci-hcd.c
@@ -735,6 +735,7 @@
 		uhci_hc_died(uhci);
 	uhci_scan_schedule(uhci);
 	spin_unlock_irq(&uhci->lock);
+	synchronize_irq(hcd->irq);
 
 	del_timer_sync(&uhci->fsbr_timer);
 	release_uhci(uhci);
@@ -749,7 +750,20 @@
 	spin_lock_irq(&uhci->lock);
 	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
 		rc = -ESHUTDOWN;
-	else if (!uhci->dead)
+	else if (uhci->dead)
+		;		/* Dead controllers tell no tales */
+
+	/* Once the controller is stopped, port resumes that are already
+	 * in progress won't complete.  Hence if remote wakeup is enabled
+	 * for the root hub and any ports are in the middle of a resume or
+	 * remote wakeup, we must fail the suspend.
+	 */
+	else if (hcd->self.root_hub->do_remote_wakeup &&
+			uhci->resuming_ports) {
+		dev_dbg(uhci_dev(uhci), "suspend failed because a port "
+				"is resuming\n");
+		rc = -EBUSY;
+	} else
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
 	spin_unlock_irq(&uhci->lock);
 	return rc;
--- linux-ec2-2.6.32.orig/drivers/usb/host/xhci-ext-caps.h
+++ linux-ec2-2.6.32/drivers/usb/host/xhci-ext-caps.h
@@ -101,12 +101,15 @@
 
 	next = readl(base + ext_offset);
 
-	if (ext_offset == XHCI_HCC_PARAMS_OFFSET)
+	if (ext_offset == XHCI_HCC_PARAMS_OFFSET) {
 		/* Find the first extended capability */
 		next = XHCI_HCC_EXT_CAPS(next);
-	else
+		ext_offset = 0;
+	} else {
 		/* Find the next extended capability */
 		next = XHCI_EXT_CAPS_NEXT(next);
+	}
+
 	if (!next)
 		return 0;
 	/*
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-q.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-q.c
@@ -315,7 +315,6 @@
 	int			stopped;
 	unsigned		count = 0;
 	u8			state;
-	const __le32		halt = HALT_BIT(ehci);
 	struct ehci_qh_hw	*hw = qh->hw;
 
 	if (unlikely (list_empty (&qh->qtd_list)))
@@ -422,7 +421,6 @@
 					&& !(qtd->hw_alt_next
 						& EHCI_LIST_END(ehci))) {
 				stopped = 1;
-				goto halt;
 			}
 
 		/* stop scanning when we reach qtds the hc is using */
@@ -456,16 +454,6 @@
 				 */
 				ehci_clear_tt_buffer(ehci, qh, urb, token);
 			}
-
-			/* force halt for unlinked or blocked qh, so we'll
-			 * patch the qh later and so that completions can't
-			 * activate it while we "know" it's stopped.
-			 */
-			if ((halt & hw->hw_token) == 0) {
-halt:
-				hw->hw_token |= halt;
-				wmb ();
-			}
 		}
 
 		/* unless we already know the urb's status, collect qtd status
@@ -827,9 +815,10 @@
 				 * But interval 1 scheduling is simpler, and
 				 * includes high bandwidth.
 				 */
-				dbg ("intr period %d uframes, NYET!",
-						urb->interval);
-				goto done;
+				urb->interval = 1;
+			} else if (qh->period > ehci->periodic_size) {
+				qh->period = ehci->periodic_size;
+				urb->interval = qh->period << 3;
 			}
 		} else {
 			int		think_time;
@@ -852,6 +841,10 @@
 					usb_calc_bus_time (urb->dev->speed,
 					is_input, 0, max_packet (maxp)));
 			qh->period = urb->interval;
+			if (qh->period > ehci->periodic_size) {
+				qh->period = ehci->periodic_size;
+				urb->interval = qh->period;
+			}
 		}
 	}
 
@@ -1231,24 +1224,27 @@
 
 static void scan_async (struct ehci_hcd *ehci)
 {
+	bool			stopped;
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
 	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
+	stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
 	qh = ehci->async->qh_next.qh;
 	if (likely (qh != NULL)) {
 		do {
 			/* clean any finished work for this qh */
-			if (!list_empty (&qh->qtd_list)
-					&& qh->stamp != ehci->stamp) {
+			if (!list_empty(&qh->qtd_list) && (stopped ||
+					qh->stamp != ehci->stamp)) {
 				int temp;
 
 				/* unlinks could happen here; completion
 				 * reporting drops the lock.  rescan using
 				 * the latest schedule, but don't rescan
-				 * qhs we already finished (no looping).
+				 * qhs we already finished (no looping)
+				 * unless the controller is stopped.
 				 */
 				qh = qh_get (qh);
 				qh->stamp = ehci->stamp;
@@ -1269,9 +1265,9 @@
 			 */
 			if (list_empty(&qh->qtd_list)
 					&& qh->qh_state == QH_STATE_LINKED) {
-				if (!ehci->reclaim
-					&& ((ehci->stamp - qh->stamp) & 0x1fff)
-						>= (EHCI_SHRINK_FRAMES * 8))
+				if (!ehci->reclaim && (stopped ||
+					((ehci->stamp - qh->stamp) & 0x1fff)
+						>= EHCI_SHRINK_FRAMES * 8))
 					start_unlink_async(ehci, qh);
 				else
 					action = TIMER_ASYNC_SHRINK;
--- linux-ec2-2.6.32.orig/drivers/usb/host/xhci-hcd.c
+++ linux-ec2-2.6.32/drivers/usb/host/xhci-hcd.c
@@ -97,6 +97,33 @@
 }
 
 /*
+ * Set the run bit and wait for the host to be running.
+ */
+int xhci_start(struct xhci_hcd *xhci)
+{
+	u32 temp;
+	int ret;
+
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	temp |= (CMD_RUN);
+	xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+			temp);
+	xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+	/*
+	 * Wait for the HCHalted Status bit to be 0 to indicate the host is
+	 * running.
+	 */
+	ret = handshake(xhci, &xhci->op_regs->status,
+			STS_HALT, 0, XHCI_MAX_HALT_USEC);
+	if (ret == -ETIMEDOUT)
+		xhci_err(xhci, "Host took too long to start, "
+				"waited %u microseconds.\n",
+				XHCI_MAX_HALT_USEC);
+	return ret;
+}
+
+/*
  * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
  *
  * This resets pipelines, timers, counters, state machines, etc.
@@ -107,6 +134,7 @@
 {
 	u32 command;
 	u32 state;
+	int ret;
 
 	state = xhci_readl(xhci, &xhci->op_regs->status);
 	if ((state & STS_HALT) == 0) {
@@ -121,7 +149,17 @@
 	/* XXX: Why does EHCI set this here?  Shouldn't other code do this? */
 	xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 
-	return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000);
+	ret = handshake(xhci, &xhci->op_regs->command,
+			CMD_RESET, 0, 250 * 1000);
+	if (ret)
+		return ret;
+
+	xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
+	/*
+	 * xHCI cannot write to any doorbells or operational registers other
+	 * than status until the "Controller Not Ready" flag is cleared.
+	 */
+	return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
 }
 
 /*
@@ -460,13 +498,11 @@
 	if (NUM_TEST_NOOPS > 0)
 		doorbell = xhci_setup_one_noop(xhci);
 
-	temp = xhci_readl(xhci, &xhci->op_regs->command);
-	temp |= (CMD_RUN);
-	xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
-			temp);
-	xhci_writel(xhci, temp, &xhci->op_regs->command);
-	/* Flush PCI posted writes */
-	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	if (xhci_start(xhci)) {
+		xhci_halt(xhci);
+		return -ENODEV;
+	}
+
 	xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
 	if (doorbell)
 		(*doorbell)(xhci);
@@ -1157,6 +1193,7 @@
 		cmd_completion = &virt_dev->cmd_completion;
 		cmd_status = &virt_dev->cmd_status;
 	}
+	init_completion(cmd_completion);
 
 	if (!ctx_change)
 		ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
@@ -1413,6 +1450,8 @@
 		kfree(virt_ep->stopped_td);
 		xhci_ring_cmd_db(xhci);
 	}
+	virt_ep->stopped_td = NULL;
+	virt_ep->stopped_trb = NULL;
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	if (ret)
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci.h
+++ linux-ec2-2.6.32/drivers/usb/host/ehci.h
@@ -87,8 +87,9 @@
 	int			next_uframe;	/* scan periodic, start here */
 	unsigned		periodic_sched;	/* periodic activity count */
 
-	/* list of itds completed while clock_frame was still active */
+	/* list of itds & sitds completed while clock_frame was still active */
 	struct list_head	cached_itd_list;
+	struct list_head	cached_sitd_list;
 	unsigned		clock_frame;
 
 	/* per root hub port */
@@ -129,6 +130,7 @@
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		broken_periodic:1;
+	unsigned		amd_l1_fix:1;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
@@ -195,7 +197,7 @@
 	clear_bit (action, &ehci->actions);
 }
 
-static void free_cached_itd_list(struct ehci_hcd *ehci);
+static void free_cached_lists(struct ehci_hcd *ehci);
 
 /*-------------------------------------------------------------------------*/
 
@@ -394,9 +396,8 @@
  * acts like a qh would, if EHCI had them for ISO.
  */
 struct ehci_iso_stream {
-	/* first two fields match QH, but info1 == 0 */
-	__hc32			hw_next;
-	__hc32			hw_info1;
+	/* first field matches ehci_hq, but is NULL */
+	struct ehci_qh_hw	*hw;
 
 	u32			refcount;
 	u8			bEndpointAddress;
--- linux-ec2-2.6.32.orig/drivers/usb/host/pci-quirks.c
+++ linux-ec2-2.6.32/drivers/usb/host/pci-quirks.c
@@ -169,6 +169,7 @@
 static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
 	void __iomem *base;
+	u32 control;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -177,10 +178,14 @@
 	if (base == NULL)
 		return;
 
+	control = readl(base + OHCI_CONTROL);
+
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
-#ifndef __hppa__
-{
-	u32 control = readl(base + OHCI_CONTROL);
+#ifdef __hppa__
+#define	OHCI_CTRL_MASK		(OHCI_CTRL_RWC | OHCI_CTRL_IR)
+#else
+#define	OHCI_CTRL_MASK		OHCI_CTRL_RWC
+
 	if (control & OHCI_CTRL_IR) {
 		int wait_time = 500; /* arbitrary; 5 seconds */
 		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
@@ -194,13 +199,12 @@
 			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
 					" (BIOS bug?) %08x\n",
 					readl(base + OHCI_CONTROL));
-
-		/* reset controller, preserving RWC */
-		writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
 	}
-}
 #endif
 
+	/* reset controller, preserving RWC (and possibly IR) */
+	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+
 	/*
 	 * disable interrupts
 	 */
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-sched.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-sched.c
@@ -1121,8 +1121,8 @@
 					urb->interval);
 		}
 
-	/* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */
-	} else if (unlikely (stream->hw_info1 != 0)) {
+	/* if dev->ep [epnum] is a QH, hw is set */
+	} else if (unlikely (stream->hw != NULL)) {
 		ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
 			urb->dev->devpath, epnum,
 			usb_pipein(urb->pipe) ? "in" : "out");
@@ -1553,13 +1553,84 @@
 static inline void
 itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
 {
-	/* always prepend ITD/SITD ... only QH tree is order-sensitive */
-	itd->itd_next = ehci->pshadow [frame];
-	itd->hw_next = ehci->periodic [frame];
-	ehci->pshadow [frame].itd = itd;
+	union ehci_shadow	*prev = &ehci->pshadow[frame];
+	__hc32			*hw_p = &ehci->periodic[frame];
+	union ehci_shadow	here = *prev;
+	__hc32			type = 0;
+
+	/* skip any iso nodes which might belong to previous microframes */
+	while (here.ptr) {
+		type = Q_NEXT_TYPE(ehci, *hw_p);
+		if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
+			break;
+		prev = periodic_next_shadow(ehci, prev, type);
+		hw_p = shadow_next_periodic(ehci, &here, type);
+		here = *prev;
+	}
+
+	itd->itd_next = here;
+	itd->hw_next = *hw_p;
+	prev->itd = itd;
 	itd->frame = frame;
 	wmb ();
-	ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
+	*hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
+}
+
+#define AB_REG_BAR_LOW 0xe0
+#define AB_REG_BAR_HIGH 0xe1
+#define AB_INDX(addr) ((addr) + 0x00)
+#define AB_DATA(addr) ((addr) + 0x04)
+#define NB_PCIE_INDX_ADDR 0xe0
+#define NB_PCIE_INDX_DATA 0xe4
+#define NB_PIF0_PWRDOWN_0 0x01100012
+#define NB_PIF0_PWRDOWN_1 0x01100013
+
+static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
+{
+	u32 addr, addr_low, addr_high, val;
+
+	outb_p(AB_REG_BAR_LOW, 0xcd6);
+	addr_low = inb_p(0xcd7);
+	outb_p(AB_REG_BAR_HIGH, 0xcd6);
+	addr_high = inb_p(0xcd7);
+	addr = addr_high << 8 | addr_low;
+	outl_p(0x30, AB_INDX(addr));
+	outl_p(0x40, AB_DATA(addr));
+	outl_p(0x34, AB_INDX(addr));
+	val = inl_p(AB_DATA(addr));
+
+	if (disable) {
+		val &= ~0x8;
+		val |= (1 << 4) | (1 << 9);
+	} else {
+		val |= 0x8;
+		val &= ~((1 << 4) | (1 << 9));
+	}
+	outl_p(val, AB_DATA(addr));
+
+	if (amd_nb_dev) {
+		addr = NB_PIF0_PWRDOWN_0;
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
+
+		addr = NB_PIF0_PWRDOWN_1;
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
+	}
+
+	return;
 }
 
 /* fit urb's itds into the selected schedule slot; activate as needed */
@@ -1589,6 +1660,12 @@
 			next_uframe >> 3, next_uframe & 0x7);
 		stream->start = jiffies;
 	}
+
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 1);
+	}
+
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill iTDs uframe by uframe */
@@ -1715,6 +1792,11 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 0);
+	}
+
 	if (unlikely(list_is_singular(&stream->td_list))) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
@@ -2002,6 +2084,12 @@
 			stream->interval, hc32_to_cpu(ehci, stream->splits));
 		stream->start = jiffies;
 	}
+
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 1);
+	}
+
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill sITDs frame by frame */
@@ -2104,6 +2192,11 @@
 	(void) disable_periodic(ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
+	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
+		if (ehci->amd_l1_fix == 1)
+			ehci_quirk_amd_L1(ehci, 0);
+	}
+
 	if (list_is_singular(&stream->td_list)) {
 		ehci_to_hcd(ehci)->self.bandwidth_allocated
 				-= stream->bandwidth;
@@ -2113,13 +2206,27 @@
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	iso_stream_put (ehci, stream);
-	/* OK to recycle this SITD now that its completion callback ran. */
+
 done:
 	sitd->urb = NULL;
-	sitd->stream = NULL;
-	list_move(&sitd->sitd_list, &stream->free_list);
-	iso_stream_put(ehci, stream);
-
+	if (ehci->clock_frame != sitd->frame) {
+		/* OK to recycle this SITD now. */
+		sitd->stream = NULL;
+		list_move(&sitd->sitd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	} else {
+		/* HW might remember this SITD, so we can't recycle it yet.
+		 * Move it to a safe place until a new frame starts.
+		 */
+		list_move(&sitd->sitd_list, &ehci->cached_sitd_list);
+		if (stream->refcount == 2) {
+			/* If iso_stream_put() were called here, stream
+			 * would be freed.  Instead, just prevent reuse.
+			 */
+			stream->ep->hcpriv = NULL;
+			stream->ep = NULL;
+		}
+	}
 	return retval;
 }
 
@@ -2185,9 +2292,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void free_cached_itd_list(struct ehci_hcd *ehci)
+static void free_cached_lists(struct ehci_hcd *ehci)
 {
 	struct ehci_itd *itd, *n;
+	struct ehci_sitd *sitd, *sn;
 
 	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
 		struct ehci_iso_stream	*stream = itd->stream;
@@ -2195,6 +2303,13 @@
 		list_move(&itd->itd_list, &stream->free_list);
 		iso_stream_put(ehci, stream);
 	}
+
+	list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
+		struct ehci_iso_stream	*stream = sitd->stream;
+		sitd->stream = NULL;
+		list_move(&sitd->sitd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	}
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2221,7 +2336,7 @@
 		clock_frame = -1;
 	}
 	if (ehci->clock_frame != clock_frame) {
-		free_cached_itd_list(ehci);
+		free_cached_lists(ehci);
 		ehci->clock_frame = clock_frame;
 	}
 	clock %= mod;
@@ -2384,7 +2499,7 @@
 			clock = now;
 			clock_frame = clock >> 3;
 			if (ehci->clock_frame != clock_frame) {
-				free_cached_itd_list(ehci);
+				free_cached_lists(ehci);
 				ehci->clock_frame = clock_frame;
 			}
 		} else {
--- linux-ec2-2.6.32.orig/drivers/usb/host/ehci-pci.c
+++ linux-ec2-2.6.32/drivers/usb/host/ehci-pci.c
@@ -41,6 +41,42 @@
 	return 0;
 }
 
+static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci)
+{
+	struct pci_dev *amd_smbus_dev;
+	u8 rev = 0;
+
+	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+	if (amd_smbus_dev) {
+		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+		if (rev < 0x40) {
+			pci_dev_put(amd_smbus_dev);
+			amd_smbus_dev = NULL;
+			return 0;
+		}
+	} else {
+		amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL);
+		if (!amd_smbus_dev)
+			return 0;
+		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+		if (rev < 0x11 || rev > 0x18) {
+			pci_dev_put(amd_smbus_dev);
+			amd_smbus_dev = NULL;
+			return 0;
+		}
+	}
+
+	if (!amd_nb_dev)
+		amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
+
+	ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n");
+
+	pci_dev_put(amd_smbus_dev);
+	amd_smbus_dev = NULL;
+
+	return 1;
+}
+
 /* called during probe() after chip reset completes */
 static int ehci_pci_setup(struct usb_hcd *hcd)
 {
@@ -99,6 +135,9 @@
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
+	if (ehci_quirk_amd_hudson(ehci))
+		ehci->amd_l1_fix = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
--- linux-ec2-2.6.32.orig/drivers/usb/host/r8a66597-hcd.c
+++ linux-ec2-2.6.32/drivers/usb/host/r8a66597-hcd.c
@@ -35,7 +35,9 @@
 #include <linux/usb.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/mm.h>
 #include <linux/irq.h>
+#include <asm/cacheflush.h>
 
 #include "../core/hcd.h"
 #include "r8a66597.h"
@@ -216,8 +218,17 @@
 {
 	int port;
 
+	/* disable interrupts */
 	r8a66597_write(r8a66597, 0, INTENB0);
-	r8a66597_write(r8a66597, 0, INTSTS0);
+	r8a66597_write(r8a66597, 0, INTENB1);
+	r8a66597_write(r8a66597, 0, BRDYENB);
+	r8a66597_write(r8a66597, 0, BEMPENB);
+	r8a66597_write(r8a66597, 0, NRDYENB);
+
+	/* clear status */
+	r8a66597_write(r8a66597, 0, BRDYSTS);
+	r8a66597_write(r8a66597, 0, NRDYSTS);
+	r8a66597_write(r8a66597, 0, BEMPSTS);
 
 	for (port = 0; port < r8a66597->max_root_hub; port++)
 		r8a66597_disable_port(r8a66597, port);
@@ -407,7 +418,7 @@
 
 /* this function must be called with interrupt disabled */
 static void free_usb_address(struct r8a66597 *r8a66597,
-			     struct r8a66597_device *dev)
+			     struct r8a66597_device *dev, int reset)
 {
 	int port;
 
@@ -419,7 +430,13 @@
 	dev->state = USB_STATE_DEFAULT;
 	r8a66597->address_map &= ~(1 << dev->address);
 	dev->address = 0;
-	dev_set_drvdata(&dev->udev->dev, NULL);
+	/*
+	 * Only when resetting USB, it is necessary to erase drvdata. When
+	 * a usb device with usb hub is disconnect, "dev->udev" is already
+	 * freed on usb_desconnect(). So we cannot access the data.
+	 */
+	if (reset)
+		dev_set_drvdata(&dev->udev->dev, NULL);
 	list_del(&dev->device_list);
 	kfree(dev);
 
@@ -811,6 +828,26 @@
 	enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
 }
 
+static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb,
+			      int status)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+	if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
+		void *ptr;
+
+		for (ptr = urb->transfer_buffer;
+		     ptr < urb->transfer_buffer + urb->transfer_buffer_length;
+		     ptr += PAGE_SIZE)
+			flush_dcache_page(virt_to_page(ptr));
+	}
+
+	usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+	spin_unlock(&r8a66597->lock);
+	usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status);
+	spin_lock(&r8a66597->lock);
+}
+
 /* this function must be called with interrupt disabled */
 static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
 {
@@ -831,15 +868,9 @@
 		list_del(&td->queue);
 		kfree(td);
 
-		if (urb) {
-			usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
-					urb);
-
-			spin_unlock(&r8a66597->lock);
-			usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb,
-					-ENODEV);
-			spin_lock(&r8a66597->lock);
-		}
+		if (urb)
+			r8a66597_urb_done(r8a66597, urb, -ENODEV);
+
 		break;
 	}
 }
@@ -1042,7 +1073,7 @@
 	struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
 
 	disable_r8a66597_pipe_all(r8a66597, dev);
-	free_usb_address(r8a66597, dev);
+	free_usb_address(r8a66597, dev, 0);
 
 	start_root_hub_sampling(r8a66597, port, 0);
 }
@@ -1276,10 +1307,7 @@
 		if (usb_pipeisoc(urb->pipe))
 			urb->start_frame = r8a66597_get_frame(hcd);
 
-		usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
-		spin_unlock(&r8a66597->lock);
-		usb_hcd_giveback_urb(hcd, urb, status);
-		spin_lock(&r8a66597->lock);
+		r8a66597_urb_done(r8a66597, urb, status);
 	}
 
 	if (restart) {
@@ -2063,7 +2091,7 @@
 				spin_lock_irqsave(&r8a66597->lock, flags);
 				dev = get_r8a66597_device(r8a66597, addr);
 				disable_r8a66597_pipe_all(r8a66597, dev);
-				free_usb_address(r8a66597, dev);
+				free_usb_address(r8a66597, dev, 0);
 				put_child_connect_map(r8a66597, addr);
 				spin_unlock_irqrestore(&r8a66597->lock, flags);
 			}
@@ -2206,7 +2234,7 @@
 			rh->port |= (1 << USB_PORT_FEAT_RESET);
 
 			disable_r8a66597_pipe_all(r8a66597, dev);
-			free_usb_address(r8a66597, dev);
+			free_usb_address(r8a66597, dev, 1);
 
 			r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
 				      get_dvstctr_reg(port));
@@ -2470,6 +2498,12 @@
 	r8a66597->rh_timer.data = (unsigned long)r8a66597;
 	r8a66597->reg = (unsigned long)reg;
 
+	/* make sure no interrupts are pending */
+	ret = r8a66597_clock_enable(r8a66597);
+	if (ret < 0)
+		goto clean_up3;
+	disable_controller(r8a66597);
+
 	for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
 		INIT_LIST_HEAD(&r8a66597->pipe_queue[i]);
 		init_timer(&r8a66597->td_timer[i]);
--- linux-ec2-2.6.32.orig/drivers/usb/host/ohci-hcd.c
+++ linux-ec2-2.6.32/drivers/usb/host/ohci-hcd.c
@@ -398,7 +398,14 @@
 
 	ohci = hcd_to_ohci (hcd);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	ohci_usb_reset (ohci);
+	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+
+	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
+	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
+			OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
+			OHCI_CTRL_RWC);
+	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+
 	/* flush the writes */
 	(void) ohci_readl (ohci, &ohci->regs->control);
 }
--- linux-ec2-2.6.32.orig/drivers/watchdog/iTCO_wdt.c
+++ linux-ec2-2.6.32/drivers/watchdog/iTCO_wdt.c
@@ -1,5 +1,5 @@
 /*
- *	intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets)
+ *	intel TCO Watchdog Driver
  *
  *	(c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
  *
@@ -14,47 +14,24 @@
  *
  *	The TCO watchdog is implemented in the following I/O controller hubs:
  *	(See the intel documentation on http://developer.intel.com.)
- *	82801AA  (ICH)       : document number 290655-003, 290677-014,
- *	82801AB  (ICHO)      : document number 290655-003, 290677-014,
- *	82801BA  (ICH2)      : document number 290687-002, 298242-027,
- *	82801BAM (ICH2-M)    : document number 290687-002, 298242-027,
- *	82801CA  (ICH3-S)    : document number 290733-003, 290739-013,
- *	82801CAM (ICH3-M)    : document number 290716-001, 290718-007,
- *	82801DB  (ICH4)      : document number 290744-001, 290745-025,
- *	82801DBM (ICH4-M)    : document number 252337-001, 252663-008,
- *	82801E   (C-ICH)     : document number 273599-001, 273645-002,
- *	82801EB  (ICH5)      : document number 252516-001, 252517-028,
- *	82801ER  (ICH5R)     : document number 252516-001, 252517-028,
- *	6300ESB  (6300ESB)   : document number 300641-004, 300884-013,
- *	82801FB  (ICH6)      : document number 301473-002, 301474-026,
- *	82801FR  (ICH6R)     : document number 301473-002, 301474-026,
- *	82801FBM (ICH6-M)    : document number 301473-002, 301474-026,
- *	82801FW  (ICH6W)     : document number 301473-001, 301474-026,
- *	82801FRW (ICH6RW)    : document number 301473-001, 301474-026,
- *	631xESB  (631xESB)   : document number 313082-001, 313075-006,
- *	632xESB  (632xESB)   : document number 313082-001, 313075-006,
- *	82801GB  (ICH7)      : document number 307013-003, 307014-024,
- *	82801GR  (ICH7R)     : document number 307013-003, 307014-024,
- *	82801GDH (ICH7DH)    : document number 307013-003, 307014-024,
- *	82801GBM (ICH7-M)    : document number 307013-003, 307014-024,
- *	82801GHM (ICH7-M DH) : document number 307013-003, 307014-024,
- *	82801GU  (ICH7-U)    : document number 307013-003, 307014-024,
- *	82801HB  (ICH8)      : document number 313056-003, 313057-017,
- *	82801HR  (ICH8R)     : document number 313056-003, 313057-017,
- *	82801HBM (ICH8M)     : document number 313056-003, 313057-017,
- *	82801HH  (ICH8DH)    : document number 313056-003, 313057-017,
- *	82801HO  (ICH8DO)    : document number 313056-003, 313057-017,
- *	82801HEM (ICH8M-E)   : document number 313056-003, 313057-017,
- *	82801IB  (ICH9)      : document number 316972-004, 316973-012,
- *	82801IR  (ICH9R)     : document number 316972-004, 316973-012,
- *	82801IH  (ICH9DH)    : document number 316972-004, 316973-012,
- *	82801IO  (ICH9DO)    : document number 316972-004, 316973-012,
- *	82801IBM (ICH9M)     : document number 316972-004, 316973-012,
- *	82801IEM (ICH9M-E)   : document number 316972-004, 316973-012,
- *	82801JIB (ICH10)     : document number 319973-002, 319974-002,
- *	82801JIR (ICH10R)    : document number 319973-002, 319974-002,
- *	82801JD  (ICH10D)    : document number 319973-002, 319974-002,
- *	82801JDO (ICH10DO)   : document number 319973-002, 319974-002
+ *	document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
+ *	document number 290687-002, 298242-027: 82801BA (ICH2)
+ *	document number 290733-003, 290739-013: 82801CA (ICH3-S)
+ *	document number 290716-001, 290718-007: 82801CAM (ICH3-M)
+ *	document number 290744-001, 290745-025: 82801DB (ICH4)
+ *	document number 252337-001, 252663-008: 82801DBM (ICH4-M)
+ *	document number 273599-001, 273645-002: 82801E (C-ICH)
+ *	document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R)
+ *	document number 300641-004, 300884-013: 6300ESB
+ *	document number 301473-002, 301474-026: 82801F (ICH6)
+ *	document number 313082-001, 313075-006: 631xESB, 632xESB
+ *	document number 307013-003, 307014-024: 82801G (ICH7)
+ *	document number 313056-003, 313057-017: 82801H (ICH8)
+ *	document number 316972-004, 316973-012: 82801I (ICH9)
+ *	document number 319973-002, 319974-002: 82801J (ICH10)
+ *	document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
+ *	document number 320066-003, 320257-008: EP80597 (IICH)
+ *	document number TBD                   : Cougar Point (CPT)
  */
 
 /*
@@ -122,6 +99,53 @@
 	TCO_ICH10R,	/* ICH10R */
 	TCO_ICH10D,	/* ICH10D */
 	TCO_ICH10DO,	/* ICH10DO */
+	TCO_PCH,	/* PCH Desktop Full Featured */
+	TCO_PCHM,	/* PCH Mobile Full Featured */
+	TCO_P55,	/* P55 */
+	TCO_PM55,	/* PM55 */
+	TCO_H55,	/* H55 */
+	TCO_QM57,	/* QM57 */
+	TCO_H57,	/* H57 */
+	TCO_HM55,	/* HM55 */
+	TCO_Q57,	/* Q57 */
+	TCO_HM57,	/* HM57 */
+	TCO_PCHMSFF,	/* PCH Mobile SFF Full Featured */
+	TCO_QS57,	/* QS57 */
+	TCO_3400,	/* 3400 */
+	TCO_3420,	/* 3420 */
+	TCO_3450,	/* 3450 */
+	TCO_EP80579,	/* EP80579 */
+	TCO_CPT1,	/* Cougar Point */
+	TCO_CPT2,	/* Cougar Point Desktop */
+	TCO_CPT3,	/* Cougar Point Mobile */
+	TCO_CPT4,	/* Cougar Point */
+	TCO_CPT5,	/* Cougar Point */
+	TCO_CPT6,	/* Cougar Point */
+	TCO_CPT7,	/* Cougar Point */
+	TCO_CPT8,	/* Cougar Point */
+	TCO_CPT9,	/* Cougar Point */
+	TCO_CPT10,	/* Cougar Point */
+	TCO_CPT11,	/* Cougar Point */
+	TCO_CPT12,	/* Cougar Point */
+	TCO_CPT13,	/* Cougar Point */
+	TCO_CPT14,	/* Cougar Point */
+	TCO_CPT15,	/* Cougar Point */
+	TCO_CPT16,	/* Cougar Point */
+	TCO_CPT17,	/* Cougar Point */
+	TCO_CPT18,	/* Cougar Point */
+	TCO_CPT19,	/* Cougar Point */
+	TCO_CPT20,	/* Cougar Point */
+	TCO_CPT21,	/* Cougar Point */
+	TCO_CPT22,	/* Cougar Point */
+	TCO_CPT23,	/* Cougar Point */
+	TCO_CPT24,	/* Cougar Point */
+	TCO_CPT25,	/* Cougar Point */
+	TCO_CPT26,	/* Cougar Point */
+	TCO_CPT27,	/* Cougar Point */
+	TCO_CPT28,	/* Cougar Point */
+	TCO_CPT29,	/* Cougar Point */
+	TCO_CPT30,	/* Cougar Point */
+	TCO_CPT31,	/* Cougar Point */
 };
 
 static struct {
@@ -162,6 +186,53 @@
 	{"ICH10R", 2},
 	{"ICH10D", 2},
 	{"ICH10DO", 2},
+	{"PCH Desktop Full Featured", 2},
+	{"PCH Mobile Full Featured", 2},
+	{"P55", 2},
+	{"PM55", 2},
+	{"H55", 2},
+	{"QM57", 2},
+	{"H57", 2},
+	{"HM55", 2},
+	{"Q57", 2},
+	{"HM57", 2},
+	{"PCH Mobile SFF Full Featured", 2},
+	{"QS57", 2},
+	{"3400", 2},
+	{"3420", 2},
+	{"3450", 2},
+	{"EP80579", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
+	{"Cougar Point", 2},
 	{NULL, 0}
 };
 
@@ -230,6 +301,53 @@
 	{ ITCO_PCI_DEVICE(0x3a16,				TCO_ICH10R)},
 	{ ITCO_PCI_DEVICE(0x3a1a,				TCO_ICH10D)},
 	{ ITCO_PCI_DEVICE(0x3a14,				TCO_ICH10DO)},
+	{ ITCO_PCI_DEVICE(0x3b00,				TCO_PCH)},
+	{ ITCO_PCI_DEVICE(0x3b01,				TCO_PCHM)},
+	{ ITCO_PCI_DEVICE(0x3b02,				TCO_P55)},
+	{ ITCO_PCI_DEVICE(0x3b03,				TCO_PM55)},
+	{ ITCO_PCI_DEVICE(0x3b06,				TCO_H55)},
+	{ ITCO_PCI_DEVICE(0x3b07,				TCO_QM57)},
+	{ ITCO_PCI_DEVICE(0x3b08,				TCO_H57)},
+	{ ITCO_PCI_DEVICE(0x3b09,				TCO_HM55)},
+	{ ITCO_PCI_DEVICE(0x3b0a,				TCO_Q57)},
+	{ ITCO_PCI_DEVICE(0x3b0b,				TCO_HM57)},
+	{ ITCO_PCI_DEVICE(0x3b0d,				TCO_PCHMSFF)},
+	{ ITCO_PCI_DEVICE(0x3b0f,				TCO_QS57)},
+	{ ITCO_PCI_DEVICE(0x3b12,				TCO_3400)},
+	{ ITCO_PCI_DEVICE(0x3b14,				TCO_3420)},
+	{ ITCO_PCI_DEVICE(0x3b16,				TCO_3450)},
+	{ ITCO_PCI_DEVICE(0x5031,				TCO_EP80579)},
+	{ ITCO_PCI_DEVICE(0x1c41,				TCO_CPT1)},
+	{ ITCO_PCI_DEVICE(0x1c42,				TCO_CPT2)},
+	{ ITCO_PCI_DEVICE(0x1c43,				TCO_CPT3)},
+	{ ITCO_PCI_DEVICE(0x1c44,				TCO_CPT4)},
+	{ ITCO_PCI_DEVICE(0x1c45,				TCO_CPT5)},
+	{ ITCO_PCI_DEVICE(0x1c46,				TCO_CPT6)},
+	{ ITCO_PCI_DEVICE(0x1c47,				TCO_CPT7)},
+	{ ITCO_PCI_DEVICE(0x1c48,				TCO_CPT8)},
+	{ ITCO_PCI_DEVICE(0x1c49,				TCO_CPT9)},
+	{ ITCO_PCI_DEVICE(0x1c4a,				TCO_CPT10)},
+	{ ITCO_PCI_DEVICE(0x1c4b,				TCO_CPT11)},
+	{ ITCO_PCI_DEVICE(0x1c4c,				TCO_CPT12)},
+	{ ITCO_PCI_DEVICE(0x1c4d,				TCO_CPT13)},
+	{ ITCO_PCI_DEVICE(0x1c4e,				TCO_CPT14)},
+	{ ITCO_PCI_DEVICE(0x1c4f,				TCO_CPT15)},
+	{ ITCO_PCI_DEVICE(0x1c50,				TCO_CPT16)},
+	{ ITCO_PCI_DEVICE(0x1c51,				TCO_CPT17)},
+	{ ITCO_PCI_DEVICE(0x1c52,				TCO_CPT18)},
+	{ ITCO_PCI_DEVICE(0x1c53,				TCO_CPT19)},
+	{ ITCO_PCI_DEVICE(0x1c54,				TCO_CPT20)},
+	{ ITCO_PCI_DEVICE(0x1c55,				TCO_CPT21)},
+	{ ITCO_PCI_DEVICE(0x1c56,				TCO_CPT22)},
+	{ ITCO_PCI_DEVICE(0x1c57,				TCO_CPT23)},
+	{ ITCO_PCI_DEVICE(0x1c58,				TCO_CPT24)},
+	{ ITCO_PCI_DEVICE(0x1c59,				TCO_CPT25)},
+	{ ITCO_PCI_DEVICE(0x1c5a,				TCO_CPT26)},
+	{ ITCO_PCI_DEVICE(0x1c5b,				TCO_CPT27)},
+	{ ITCO_PCI_DEVICE(0x1c5c,				TCO_CPT28)},
+	{ ITCO_PCI_DEVICE(0x1c5d,				TCO_CPT29)},
+	{ ITCO_PCI_DEVICE(0x1c5e,				TCO_CPT30)},
+	{ ITCO_PCI_DEVICE(0x1c5f,				TCO_CPT31)},
 	{ 0, },			/* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
--- linux-ec2-2.6.32.orig/drivers/watchdog/hpwdt.c
+++ linux-ec2-2.6.32/drivers/watchdog/hpwdt.c
@@ -443,7 +443,7 @@
 static int hpwdt_change_timer(int new_margin)
 {
 	/* Arbitrary, can't find the card's limits */
-	if (new_margin < 30 || new_margin > 600) {
+	if (new_margin < 5 || new_margin > 600) {
 		printk(KERN_WARNING
 			"hpwdt: New value passed in is invalid: %d seconds.\n",
 			new_margin);
--- linux-ec2-2.6.32.orig/drivers/watchdog/bfin_wdt.c
+++ linux-ec2-2.6.32/drivers/watchdog/bfin_wdt.c
@@ -1,9 +1,8 @@
 /*
  * Blackfin On-Chip Watchdog Driver
- *  Supports BF53[123]/BF53[467]/BF54[2489]/BF561
  *
  * Originally based on softdog.c
- * Copyright 2006-2007 Analog Devices Inc.
+ * Copyright 2006-2010 Analog Devices Inc.
  * Copyright 2006-2007 Michele d'Amico
  * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
@@ -137,13 +136,15 @@
  */
 static int bfin_wdt_set_timeout(unsigned long t)
 {
-	u32 cnt;
+	u32 cnt, max_t, sclk;
 	unsigned long flags;
 
-	stampit();
+	sclk = get_sclk();
+	max_t = -1 / sclk;
+	cnt = t * sclk;
+	stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt);
 
-	cnt = t * get_sclk();
-	if (cnt < get_sclk()) {
+	if (t > max_t) {
 		printk(KERN_WARNING PFX "timeout value is too large\n");
 		return -EINVAL;
 	}
--- linux-ec2-2.6.32.orig/drivers/xen/features.c
+++ linux-ec2-2.6.32/drivers/xen/features.c
@@ -9,7 +9,14 @@
 #include <linux/cache.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_PARAVIRT_XEN
 #include <asm/xen/hypercall.h>
+#else
+#include <asm/hypervisor.h>
+#endif
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
 
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
--- linux-ec2-2.6.32.orig/drivers/xen/manage.c
+++ linux-ec2-2.6.32/drivers/xen/manage.c
@@ -43,7 +43,6 @@
 	if (err) {
 		printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
 			err);
-		dpm_resume_noirq(PMSG_RESUME);
 		return err;
 	}
 
@@ -69,7 +68,6 @@
 	}
 
 	sysdev_resume();
-	dpm_resume_noirq(PMSG_RESUME);
 
 	return 0;
 }
@@ -81,6 +79,12 @@
 
 	shutting_down = SHUTDOWN_SUSPEND;
 
+	err = stop_machine_create();
+	if (err) {
+		printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err);
+		goto out;
+	}
+
 #ifdef CONFIG_PREEMPT
 	/* If the kernel is preemptible, we need to freeze all the processes
 	   to prevent them from being in the middle of a pagetable update
@@ -88,14 +92,14 @@
 	err = freeze_processes();
 	if (err) {
 		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
-		return;
+		goto out_destroy_sm;
 	}
 #endif
 
 	err = dpm_suspend_start(PMSG_SUSPEND);
 	if (err) {
 		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
-		goto out;
+		goto out_thaw;
 	}
 
 	printk(KERN_DEBUG "suspending xenstore...\n");
@@ -104,32 +108,39 @@
 	err = dpm_suspend_noirq(PMSG_SUSPEND);
 	if (err) {
 		printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
-		goto resume_devices;
+		goto out_resume;
 	}
 
 	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
+
+	dpm_resume_noirq(PMSG_RESUME);
+
 	if (err) {
 		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
-		goto out;
+		cancelled = 1;
 	}
 
+out_resume:
 	if (!cancelled) {
 		xen_arch_resume();
 		xs_resume();
 	} else
 		xs_suspend_cancel();
 
-	dpm_resume_noirq(PMSG_RESUME);
-
-resume_devices:
 	dpm_resume_end(PMSG_RESUME);
 
 	/* Make sure timer events get retriggered on all CPUs */
 	clock_was_set();
-out:
+
+out_thaw:
 #ifdef CONFIG_PREEMPT
 	thaw_processes();
+
+out_destroy_sm:
 #endif
+	stop_machine_destroy();
+
+out:
 	shutting_down = SHUTDOWN_INVALID;
 }
 #endif	/* CONFIG_PM_SLEEP */
--- linux-ec2-2.6.32.orig/drivers/xen/Makefile
+++ linux-ec2-2.6.32/drivers/xen/Makefile
@@ -1,12 +1,44 @@
-obj-y	+= grant-table.o features.o events.o manage.o
-obj-y	+= xenbus/
+obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o features.o events.o manage.o
+xen-hotplug-$(CONFIG_PARAVIRT_XEN) := cpu_hotplug.o
+xen-xencomm-$(CONFIG_PARAVIRT_XEN) := xencomm.o
+xen-balloon-$(CONFIG_PARAVIRT_XEN) := balloon.o
+
+xen-balloon-$(CONFIG_XEN)	:= balloon/
+obj-$(CONFIG_XEN)		+= core/
+obj-$(CONFIG_XEN)		+= console/
+obj-$(CONFIG_XEN)		+= evtchn/
+obj-y				+= xenbus/
+obj-$(CONFIG_XEN)		+= char/
 
 nostackp := $(call cc-option, -fno-stack-protector)
+ifeq ($(CONFIG_PARAVIRT_XEN),y)
 CFLAGS_features.o			:= $(nostackp)
+endif
 
-obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
-obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
-obj-$(CONFIG_XEN_BALLOON)	+= balloon.o
+obj-$(CONFIG_XEN)		+= features.o util.o
+obj-$(CONFIG_HOTPLUG_CPU)	+= $(xen-hotplug-y)
+obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
+obj-$(CONFIG_XEN_BALLOON)	+= $(xen-balloon-y)
 obj-$(CONFIG_XEN_DEV_EVTCHN)	+= evtchn.o
 obj-$(CONFIG_XENFS)		+= xenfs/
-obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
\ No newline at end of file
+obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
+obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
+obj-$(CONFIG_XEN_BLKDEV_TAP2)           += blktap2/
+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_USB_BACKEND)		+= usbback/
+obj-$(CONFIG_XEN_USB_FRONTEND)		+= usbfront/
+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/
--- linux-ec2-2.6.32.orig/drivers/xen/balloon.c
+++ linux-ec2-2.6.32/drivers/xen/balloon.c
@@ -66,8 +66,6 @@
 	/* We aim for 'current allocation' == 'target allocation'. */
 	unsigned long current_pages;
 	unsigned long target_pages;
-	/* We may hit the hard limit in Xen. If we do then we remember it. */
-	unsigned long hard_limit;
 	/*
 	 * Drivers may alter the memory reservation independently, but they
 	 * must inform the balloon driver so we avoid hitting the hard limit.
@@ -136,6 +134,8 @@
 		list_add(&page->lru, &ballooned_pages);
 		balloon_stats.balloon_low++;
 	}
+
+	totalram_pages--;
 }
 
 /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
@@ -156,6 +156,8 @@
 	else
 		balloon_stats.balloon_low--;
 
+	totalram_pages++;
+
 	return page;
 }
 
@@ -181,7 +183,7 @@
 
 static unsigned long current_target(void)
 {
-	unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit);
+	unsigned long target = balloon_stats.target_pages;
 
 	target = min(target,
 		     balloon_stats.current_pages +
@@ -217,23 +219,10 @@
 	set_xen_guest_handle(reservation.extent_start, frame_list);
 	reservation.nr_extents = nr_pages;
 	rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
-	if (rc < nr_pages) {
-		if (rc > 0) {
-			int ret;
-
-			/* We hit the Xen hard limit: reprobe. */
-			reservation.nr_extents = rc;
-			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
-						   &reservation);
-			BUG_ON(ret != rc);
-		}
-		if (rc >= 0)
-			balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
-						    balloon_stats.driver_pages);
+	if (rc < 0)
 		goto out;
-	}
 
-	for (i = 0; i < nr_pages; i++) {
+	for (i = 0; i < rc; i++) {
 		page = balloon_retrieve();
 		BUG_ON(page == NULL);
 
@@ -259,13 +248,12 @@
 		__free_page(page);
 	}
 
-	balloon_stats.current_pages += nr_pages;
-	totalram_pages = balloon_stats.current_pages;
+	balloon_stats.current_pages += rc;
 
  out:
 	spin_unlock_irqrestore(&balloon_lock, flags);
 
-	return 0;
+	return rc < 0 ? rc : rc != nr_pages;
 }
 
 static int decrease_reservation(unsigned long nr_pages)
@@ -323,7 +311,6 @@
 	BUG_ON(ret != nr_pages);
 
 	balloon_stats.current_pages -= nr_pages;
-	totalram_pages = balloon_stats.current_pages;
 
 	spin_unlock_irqrestore(&balloon_lock, flags);
 
@@ -367,7 +354,6 @@
 static void balloon_set_new_target(unsigned long target)
 {
 	/* No need for lock. Not read-modify-write updates. */
-	balloon_stats.hard_limit   = ~0UL;
 	balloon_stats.target_pages = target;
 	schedule_work(&balloon_worker);
 }
@@ -422,12 +408,10 @@
 	pr_info("xen_balloon: Initialising balloon driver.\n");
 
 	balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
-	totalram_pages   = balloon_stats.current_pages;
 	balloon_stats.target_pages  = balloon_stats.current_pages;
 	balloon_stats.balloon_low   = 0;
 	balloon_stats.balloon_high  = 0;
 	balloon_stats.driver_pages  = 0UL;
-	balloon_stats.hard_limit    = ~0UL;
 
 	init_timer(&balloon_timer);
 	balloon_timer.data = 0;
@@ -472,9 +456,6 @@
 BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
 BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
 BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
-BALLOON_SHOW(hard_limit_kb,
-	     (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
-	     (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
 BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
 
 static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
@@ -544,7 +525,6 @@
 	&attr_current_kb.attr,
 	&attr_low_kb.attr,
 	&attr_high_kb.attr,
-	&attr_hard_limit_kb.attr,
 	&attr_driver_kb.attr,
 	NULL
 };
--- linux-ec2-2.6.32.orig/drivers/xen/Kconfig
+++ linux-ec2-2.6.32/drivers/xen/Kconfig
@@ -1,6 +1,406 @@
+#
+# This Kconfig describe xen options
+#
+
+config XEN
+	bool
+	select IRQ_PER_CPU if SMP
+
+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
+	select PM
+	select PM_SLEEP
+	select PM_SLEEP_SMP if SMP
+
+config XEN_PRIVCMD
+	def_bool y
+	depends on PROC_FS
+
+config XEN_DOMCTL
+	tristate
+
+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
+	select XEN_DOMCTL
+	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
+	select XEN_DOMCTL
+	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_BLKDEV_TAP2
+	tristate "Block-device tap backend driver 2"
+	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_BLKBACK_PAGEMAP
+	tristate
+	depends on XEN_BLKDEV_BACKEND != n && XEN_BLKDEV_TAP2 != n
+	default XEN_BLKDEV_BACKEND || XEN_BLKDEV_TAP2
+
+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_TX_SHIFT
+	int "Maximum simultaneous transmit requests (as a power of 2)"
+	depends on XEN_NETDEV_BACKEND
+	range 5 16
+	default 8
+	help
+	  The maximum number transmits the driver can hold pending, expressed
+	  as the exponent of a power of 2.
+
+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_PRIVILEGED_GUEST && 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_CONTROLLER if IA64
+	default XEN_PCIDEV_BACKEND_VPCI
+
+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_USB_BACKEND
+	tristate "USB backend driver"
+	depends on USB && XEN_BACKEND
+	default m
+	help
+	  The USB backend driver allows the kernel to export its USB Devices
+	  to other guests.
+
+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_USB_FRONTEND
+	tristate "USB frontend driver"
+	depends on USB
+	default m
+	help
+	  The USB frontend driver allows the kernel to access USB Devices
+	  within another guest OS.
+
+config XEN_USB_FRONTEND_HCD_STATS
+	bool "Taking the HCD statistics (for debug)"
+	depends on XEN_USB_FRONTEND
+	default y
+	help
+	  Count the transferred urb status and the RING_FULL occurrence.
+
+config XEN_USB_FRONTEND_HCD_PM
+	bool "HCD suspend/resume support (DO NOT USE)"
+	depends on XEN_USB_FRONTEND
+	default n
+	help
+	  Experimental bus suspend/resume feature support.
+
+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_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/.
+
+config XEN_NR_GUEST_DEVICES
+	int "Number of guest devices"
+	range 0 4032 if 64BIT
+	range 0 960
+	default 256 if XEN_BACKEND
+	default 16
+	help
+	  Specify the total number of virtual devices (i.e. both frontend
+	  and backend) that you want the kernel to be able to service.
+
+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_030200_AND_LATER
+		bool "3.2.0 and later"
+
+	config XEN_COMPAT_030300_AND_LATER
+		bool "3.3.0 and later"
+
+	config XEN_COMPAT_030400_AND_LATER
+		bool "3.4.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 0x030400 if XEN_COMPAT_030400_AND_LATER
+	default 0x030300 if XEN_COMPAT_030300_AND_LATER
+	default 0x030200 if XEN_COMPAT_030200_AND_LATER
+	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
+
+config XEN_VCPU_INFO_PLACEMENT
+	bool "Place shared vCPU info in per-CPU storage"
+#	depends on X86 && (XEN_COMPAT >= 0x00030101)
+	depends on X86
+	depends on !XEN_COMPAT_030002_AND_LATER
+	depends on !XEN_COMPAT_030004_AND_LATER
+	depends on !XEN_COMPAT_030100_AND_LATER
+	default SMP
+	---help---
+	  This allows faster access to the per-vCPU shared info
+	  structure.
+
+endmenu
+
+config HAVE_IRQ_IGNORE_UNHANDLED
+	def_bool y
+
+config IRQ_PER_CPU
+	bool
+
+config NO_IDLE_HZ
+	def_bool y
+
+config XEN_SMPBOOT
+	def_bool y
+	depends on SMP && !PPC_XEN
+
+config XEN_XENCOMM
+	bool
+
+config XEN_DEVMEM
+	def_bool y
+
+endif
+
 config XEN_BALLOON
-	bool "Xen memory balloon driver"
-	depends on XEN
+	bool "Xen memory balloon driver" if PARAVIRT_XEN
+	depends on (XEN && !PPC_XEN) || PARAVIRT_XEN
 	default y
 	help
 	  The balloon driver allows the Xen domain to request more memory from
@@ -8,19 +408,21 @@
 	  return unneeded memory to the system.
 
 config XEN_SCRUB_PAGES
-	bool "Scrub pages before returning them to system"
-	depends on XEN_BALLOON
+	bool "Scrub memory before freeing it to Xen"
+	depends on XEN || XEN_BALLOON
 	default y
 	help
-	  Scrub pages before returning them to the system for reuse by
-	  other domains.  This makes sure that any confidential data
-	  is not accidentally visible to other domains.  Is it more
-	  secure, but slightly less efficient.
+	  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.
 	  If in doubt, say yes.
 
 config XEN_DEV_EVTCHN
 	tristate "Xen /dev/xen/evtchn device"
-	depends on XEN
+	depends on PARAVIRT_XEN
 	default y
 	help
 	  The evtchn driver allows a userspace process to triger event
@@ -30,7 +432,7 @@
 
 config XENFS
 	tristate "Xen filesystem"
-	depends on XEN
+	depends on PARAVIRT_XEN
 	default y
 	help
 	  The xen filesystem provides a way for domains to share
@@ -53,7 +455,7 @@
 
 config XEN_SYS_HYPERVISOR
        bool "Create xen entries under /sys/hypervisor"
-       depends on XEN && SYSFS
+       depends on PARAVIRT_XEN && SYSFS
        select SYS_HYPERVISOR
        default y
        help
--- linux-ec2-2.6.32.orig/drivers/xen/sys-hypervisor.c
+++ linux-ec2-2.6.32/drivers/xen/sys-hypervisor.c
@@ -18,6 +18,8 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>
 
+#include "xenbus/xenbus_comms.h"
+
 #define HYPERVISOR_ATTR_RO(_name) \
 static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
 
@@ -116,9 +118,8 @@
 {
 	char *vm, *val;
 	int ret;
-	extern int xenstored_ready;
 
-	if (!xenstored_ready)
+	if (!is_xenstored_ready())
 		return -EBUSY;
 
 	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
--- linux-ec2-2.6.32.orig/drivers/xen/events.c
+++ linux-ec2-2.6.32/drivers/xen/events.c
@@ -106,6 +106,7 @@
 #define VALID_EVTCHN(chn)	((chn) != 0)
 
 static struct irq_chip xen_dynamic_chip;
+static struct irq_chip xen_percpu_chip;
 
 /* Constructor for packed IRQ information. */
 static struct irq_info mk_unbound_info(void)
@@ -254,7 +255,7 @@
 	}
 #endif
 
-	memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0)));
+	memset(cpu_evtchn_mask(0), ~0, sizeof(struct cpu_evtchn_s));
 }
 
 static inline void clear_evtchn(int port)
@@ -362,7 +363,7 @@
 		irq = find_unbound_irq();
 
 		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-					      handle_level_irq, "event");
+					      handle_edge_irq, "event");
 
 		evtchn_to_irq[evtchn] = irq;
 		irq_info[irq] = mk_evtchn_info(evtchn);
@@ -388,8 +389,8 @@
 		if (irq < 0)
 			goto out;
 
-		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-					      handle_level_irq, "ipi");
+		set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
+					      handle_percpu_irq, "ipi");
 
 		bind_ipi.vcpu = cpu;
 		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
@@ -429,8 +430,8 @@
 
 		irq = find_unbound_irq();
 
-		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
-					      handle_level_irq, "virq");
+		set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
+					      handle_percpu_irq, "virq");
 
 		evtchn_to_irq[evtchn] = irq;
 		irq_info[irq] = mk_virq_info(evtchn, virq);
@@ -474,6 +475,9 @@
 		bind_evtchn_to_cpu(evtchn, 0);
 
 		evtchn_to_irq[evtchn] = -1;
+	}
+
+	if (irq_info[irq].type != IRQT_UNBOUND) {
 		irq_info[irq] = mk_unbound_info();
 
 		dynamic_irq_cleanup(irq);
@@ -532,6 +536,7 @@
 	if (irq < 0)
 		return irq;
 
+	irqflags |= IRQF_NO_SUSPEND;
 	retval = request_irq(irq, handler, irqflags, devname, dev_id);
 	if (retval != 0) {
 		unbind_from_irq(irq);
@@ -809,9 +814,6 @@
 		evtchn_to_irq[evtchn] = irq;
 		irq_info[irq] = mk_virq_info(evtchn, virq);
 		bind_evtchn_to_cpu(evtchn, cpu);
-
-		/* Ready for use. */
-		unmask_evtchn(evtchn);
 	}
 }
 
@@ -837,10 +839,6 @@
 		evtchn_to_irq[evtchn] = irq;
 		irq_info[irq] = mk_ipi_info(evtchn, ipi);
 		bind_evtchn_to_cpu(evtchn, cpu);
-
-		/* Ready for use. */
-		unmask_evtchn(evtchn);
-
 	}
 }
 
@@ -893,6 +891,7 @@
 void xen_irq_resume(void)
 {
 	unsigned int cpu, irq, evtchn;
+	struct irq_desc *desc;
 
 	init_evtchn_cpu_bindings();
 
@@ -911,6 +910,23 @@
 		restore_cpu_virqs(cpu);
 		restore_cpu_ipis(cpu);
 	}
+
+	/*
+	 * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These
+	 * are not handled by the IRQ core.
+	 */
+	for_each_irq_desc(irq, desc) {
+		if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND))
+			continue;
+		if (desc->status & IRQ_DISABLED)
+			continue;
+
+		evtchn = evtchn_from_irq(irq);
+		if (evtchn == -1)
+			continue;
+
+		unmask_evtchn(evtchn);
+	}
 }
 
 static struct irq_chip xen_dynamic_chip __read_mostly = {
@@ -925,6 +941,16 @@
 	.retrigger	= retrigger_dynirq,
 };
 
+static struct irq_chip xen_percpu_chip __read_mostly = {
+	.name		= "xen-percpu",
+
+	.disable	= disable_dynirq,
+	.mask		= disable_dynirq,
+	.unmask		= enable_dynirq,
+
+	.ack		= ack_dynirq,
+};
+
 void __init xen_init_IRQ(void)
 {
 	int i;
--- linux-ec2-2.6.32.orig/drivers/xen/util.c
+++ linux-ec2-2.6.32/drivers/xen/util.c
@@ -0,0 +1,20 @@
+#include <linux/err.h>
+#include <linux/module.h>
+#include <xen/driver_util.h>
+
+struct class *get_xen_class(void)
+{
+	static struct class *xen_class;
+
+	if (xen_class)
+		return xen_class;
+
+	xen_class = class_create(THIS_MODULE, "xen");
+	if (IS_ERR(xen_class)) {
+		printk("Failed to create xen sysfs class.\n");
+		xen_class = NULL;
+	}
+
+	return xen_class;
+}
+EXPORT_SYMBOL_GPL(get_xen_class);
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_msg.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_msg.c
@@ -0,0 +1,391 @@
+/****************************************************************************
+ * 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: %pM\n", 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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_debugfs.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_debugfs.c
@@ -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;
+}
+
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_fwd.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_fwd.c
@@ -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 %pM\n", 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 %pM already accelerated.\n", 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 %pM\n", 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) 
+		&& arp_hdr(skb)->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_header(skb))
+	    && packet_is_arp_reply(skb)) {
+		/*
+		 * update our fast path forwarding to reflect this
+		 * gratuitous ARP
+		 */ 
+		mac = skb_mac_header(skb)+ETH_ALEN;
+
+		DPRINTK("%s: found gratuitous ARP for %pM\n",
+			__FUNCTION__, 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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/Makefile
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel.h
@@ -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
+ ****************************************************************************
+ */
+
+#ifndef NETBACK_ACCEL_H
+#define NETBACK_ACCEL_H
+
+#include <linux/version.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;
+	/*! 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 */
+
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ * 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) ||
+	    (event == NETDEV_CHANGE)) {
+		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) {
+				int ok;
+				if (event == NETDEV_CHANGE)
+					ok = (netif_carrier_ok(net_dev) && 
+					      (net_dev->flags & IFF_UP));
+				else
+					ok = (netif_carrier_ok(net_dev) && 
+					      (event == NETDEV_UP));
+				netback_accel_set_interface_state(bend, ok);
+			}
+
+		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)
+		goto fail0;
+
+	netback_accel_debugfs_init();
+
+	rc = netback_accel_sf_init();
+	if (rc != 0)
+		goto fail1;
+
+	rc = register_netdevice_notifier
+		(&netback_accel_netdev_notifier);
+	if (rc != 0)
+		goto fail2;
+
+	return 0;
+
+ fail2:
+	netback_accel_sf_shutdown();
+ fail1:
+	netback_accel_debugfs_fini();
+	netback_accel_shutdown_fwd();
+ fail0:
+#ifdef EFX_GCOV
+	gcov_provider_fini(THIS_MODULE);
+#endif
+	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");
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_xenbus.c
@@ -0,0 +1,830 @@
+/****************************************************************************
+ * 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_get_drvdata(&(_dev)->dev))->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 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)
+{
+	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) && 
+				(netif_carrier_ok(bend->net_dev)));
+
+	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 = dev_get_drvdata(&dev->dev);
+	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 = dev_get_drvdata(&dev->dev);
+	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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_solarflare.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_solarflare.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/accel_solarflare.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/accel_solarflare.c
@@ -0,0 +1,1236 @@
+/****************************************************************************
+ * 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;
+	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_header_was_set(skb))
+		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
+};
+
+
+/* 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->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;
+			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->net_dev->ifindex);
+	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;
+	}
+
+	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);
+	rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(txdmaq_pfn), 0);
+	if (rc < 0)
+		goto fail0;
+	accel_hw_priv->txdmaq_gnt = hwinfo->txdmaq_gnt = rc;
+
+	VPRINTK("Passing rxdmaq page pfn %lx\n", rxdmaq_pfn);
+	rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(rxdmaq_pfn), 0);
+	if (rc < 0)
+		goto fail1;
+	accel_hw_priv->rxdmaq_gnt = hwinfo->rxdmaq_gnt = rc;
+
+	VPRINTK("Passing doorbell page mfn %x\n", hwinfo->doorbell_mfn);
+	/* Make the relevant H/W pages mappable by the far end */
+	rc = net_accel_grant_page(bend->hdev_data, hwinfo->doorbell_mfn, 1);
+	if (rc < 0)
+		goto fail2;
+	accel_hw_priv->doorbell_gnt = hwinfo->doorbell_gnt = rc;
+	
+	/* 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++) {
+		rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(pfn), 0);
+		if (rc < 0)
+			goto fail3;
+		accel_hw_priv->evq_mem_gnts[i] = hwinfo->evq_mem_gnts[i] = rc;
+
+		VPRINTK("Got grant %u for evq pfn %x\n", hwinfo->evq_mem_gnts[i], 
+			pfn);
+		pfn++;
+	}
+
+	return 0;
+
+ fail3:
+	for (i = i - 1; i >= 0; i--) {
+		ungrant_or_crash(accel_hw_priv->evq_mem_gnts[i], bend->far_end);
+	}
+	ungrant_or_crash(accel_hw_priv->doorbell_gnt, bend->far_end);
+ fail2:
+	ungrant_or_crash(accel_hw_priv->rxdmaq_gnt, bend->far_end);
+ fail1:
+	ungrant_or_crash(accel_hw_priv->txdmaq_gnt, bend->far_end);	
+ fail0:
+	return rc;
+}
+
+
+static int ef_bend_hwinfo_falcon_a(struct netback_accel *bend, 
+				   struct net_accel_hw_falcon_a *hwinfo)
+{
+	int rc, i;
+	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) {
+		/* Undo ef_bend_hwinfo_falcon_common() */
+		ungrant_or_crash(accel_hw_priv->txdmaq_gnt, bend->far_end);
+		ungrant_or_crash(accel_hw_priv->rxdmaq_gnt, bend->far_end);
+		ungrant_or_crash(accel_hw_priv->doorbell_gnt, bend->far_end);
+		for (i = 0; i < accel_hw_priv->evq_npages; i++) {
+			ungrant_or_crash(accel_hw_priv->evq_mem_gnts[i],
+					 bend->far_end);
+		}
+		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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/driver/resource/efx_vi.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+ * 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 ifindex Index of the network interface desired
+ * \return Zero on success (and vih_out set), non-zero on failure.
+ */
+extern int
+efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex);
+
+/*!
+ * 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_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 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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efrm/sysdep_linux.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * 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/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>
+#include <linux/log2.h>
+#include <linux/kfifo.h>
+
+
+/********************************************************************
+ *
+ * List API
+ *
+ ********************************************************************/
+
+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;
+}
+
+/********************************************************************
+ *
+ * Kfifo API
+ *
+ ********************************************************************/
+
+static inline void kfifo_vfree(struct kfifo *fifo)
+{
+	vfree(fifo->buffer);
+	kfree(fifo);
+}
+
+#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efrm/sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efrm/sysdep.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * 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>
+
+#include <ci/efrm/sysdep_linux.h>
+
+#endif /* __CI_EFRM_SYSDEP_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efrm/nic_table.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efrm/nic_table.h
@@ -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_tablep;
+
+static inline void efrm_nic_table_hold(void)
+{
+	atomic_inc(&efrm_nic_tablep->ref_count);
+}
+
+static inline void efrm_nic_table_rele(void)
+{
+	atomic_dec(&efrm_nic_tablep->ref_count);
+}
+
+static inline int efrm_nic_table_held(void)
+{
+	return atomic_read(&efrm_nic_tablep->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_tablep->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_tablep->nic[_i]) &&		\
+		    efrm_nic_set_read((_set), (_i)))
+
+#endif /* __CI_EFRM_NIC_TABLE_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/sysdep.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/log.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/log.h
@@ -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  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.
+  */
+
+#if defined(__unix__) && ! defined(__KERNEL__)
+extern int ci_format_select_set(char* s, int len_s, int nfds, const fd_set*);
+extern int ci_format_select(char* s, int len_s,
+			    int nfds, const fd_set* rds, const fd_set* wrs,
+			    const fd_set* exs, struct timeval* timeout);
+#endif
+
+
+/**********************************************************************
+ * 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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/config.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/config.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/debug.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/debug.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h
@@ -0,0 +1,370 @@
+/****************************************************************************
+ * 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)); }
+
+ci_inline void ci_atomic32_inc(volatile ci_uint32* p)
+{ __asm__ __volatile__("lock; incl %0" : "+m" (*p)); }
+
+ci_inline int ci_atomic32_dec_and_test(volatile ci_uint32* p) {
+  char r;
+  __asm__ __volatile__("lock; decl %0; sete %1" : "+m" (*p), "=qm" (r));
+  return r;
+}
+
+#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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/utils.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/utils.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/sysdep.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/x86_64.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/x86_64.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/gcc.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/gcc.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/x86.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/x86.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/gcc_x86.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/gcc_x86.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/compat/primitive.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/compat/primitive.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/efhw_types.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/efhw_types.h
@@ -0,0 +1,382 @@
+/****************************************************************************
+ * 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>
+
+/*--------------------------------------------------------------------
+ *
+ * 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 */
+	struct efhw_iopages 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 {
+	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;
+};
+
+/*--------------------------------------------------------------------
+ *
+ * filters
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_filter_spec {
+	uint dmaq_id;
+	uint32_t saddr_le32;
+	uint32_t daddr_le32;
+	uint16_t sport_le16;
+	uint16_t dport_le16;
+	unsigned tcp     : 1;
+	unsigned full    : 1;
+	unsigned rss     : 1;  /* not supported on A1 */
+	unsigned scatter : 1;  /* not supported on A1 */
+};
+
+struct efhw_filter_depth {
+	unsigned needed;
+	unsigned max;
+};
+
+struct efhw_filter_search_limits {
+	unsigned tcp_full;
+	unsigned tcp_wild;
+	unsigned udp_full;
+	unsigned udp_wild;
+};
+
+
+/**********************************************************************
+ * 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, int non_irq_evq);
+
+  /*-------------- 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 the interrupt */
+	void (*interrupt_enable) (struct efhw_nic *nic);
+
+	/*! Disable the interrupt */
+	void (*interrupt_disable) (struct efhw_nic *nic);
+
+	/*! Set interrupt moderation strategy for the given IRQ unit
+	 ** val is in usec
+	 */
+	void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq,
+					 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,
+				    int interrupting);
+
+	/*! 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);
+
+  /*-------------- IP Filter API  ------------ */
+
+	/*! 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);
+
+	/*! 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);
+
+  /*-------------- New filter API ------------ */
+
+	/*! Set a given filter */
+	int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec,
+			   int *filter_idx_out);
+
+	/*! Clear a given filter */
+	void (*filter_clear) (struct efhw_nic *nic, int filter_idx);
+};
+
+
+/*----------------------------------------------------------------------------
+ *
+ * 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_tablep->nic array */
+	int index;
+	int ifindex;		/*!< OS level nic index */
+	struct net *nd_net;
+
+	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
+
+	unsigned mtu;		/*!< MAC MTU (includes MAC hdr) */
+
+	/* hardware resources */
+
+	/*! I/O address of the start of the bar */
+	volatile char __iomem *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;
+
+	/*! 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 interrupting_evq;
+
+/* 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 for the interrupting event queue  */
+	unsigned int irq_unit;
+
+	struct efhw_keventq non_interrupting_evq;
+
+	struct efhw_iopage 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. */
+	unsigned ip_filter_tbl_size;
+
+	/* Number of filters currently used */
+	unsigned ip_filter_tbl_used;
+
+	/* Dynamically allocated filter state. */
+	uint8_t *filter_in_use;
+	struct efhw_filter_spec *filter_spec_cache;
+
+	/* Currently required and maximum filter table search depths. */
+	struct efhw_filter_depth tcp_full_srch;
+	struct efhw_filter_depth tcp_wild_srch;
+	struct efhw_filter_depth udp_full_srch;
+	struct efhw_filter_depth udp_wild_srch;
+
+	/* Number of event queues, DMA queues and timers. */
+	unsigned num_evqs;
+	unsigned num_dmaqs;
+	unsigned num_timers;
+};
+
+
+#define EFHW_KVA(nic)       ((nic)->bar_ioaddr)
+
+
+#endif /* __CI_EFHW_EFHW_TYPES_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/common.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/common.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * 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,
+};
+
+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;
+} 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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/sysdep.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * 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/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/if_ether.h>
+
+#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
+#include <linux/etherdevice.h>
+
+typedef unsigned long irq_flags_t;
+
+#define spin_lock_destroy(l_)  do {} while (0)
+
+#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/efhw_config.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/efhw_config.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/hardware_sysdep.h
@@ -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 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 <linux/io.h>
+
+#if defined(__LITTLE_ENDIAN)
+#define EFHW_IS_LITTLE_ENDIAN
+#elif defined(__BIG_ENDIAN)
+#define EFHW_IS_BIG_ENDIAN
+#else
+#error Unknown endianness
+#endif
+
+#ifndef readq
+static inline uint64_t __readq(volatile void __iomem *addr)
+{
+	return *(volatile uint64_t *)addr;
+}
+#define readq(x) __readq(x)
+#endif
+
+#ifndef writeq
+static inline void __writeq(uint64_t v, volatile void __iomem *addr)
+{
+	*(volatile uint64_t *)addr = v;
+}
+#define writeq(val, addr) __writeq((val), (addr))
+#endif
+
+#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/public.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/public.h
@@ -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 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);
+
+/*! Get RX filter search limits from RX_FILTER_CTL_REG.
+ *  use_raw_values = 0 to get actual depth of search, or 1 to get raw values
+ *  from register.
+ */
+extern void
+falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values);
+
+/*! Set RX filter search limits in RX_FILTER_CTL_REG.
+ *  use_raw_values = 0 if specifying actual depth of search, or 1 if specifying
+ *  raw values to write to the register.
+ */
+extern void
+falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values);
+
+
+/*! Legacy RX IP filter search depth control interface */
+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);
+
+/*! Legacy RX IP filter search depth control interface */
+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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/debug.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/debug.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/common_sysdep.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * 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>
+
+/* 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
+
+#endif /* __CI_EFHW_COMMON_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netback/ci/efhw/iopage_types.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netback/ci/efhw/iopage_types.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers -
+ *          resource management for Xen backend, OpenOnload, etc
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * This file provides struct efhw_page and struct efhw_iopage 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 <linux/errno.h>
+#include <ci/efhw/debug.h>
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_page: A single page of memory.  Directly mapped in the
+ * driver, and can be mapped to userlevel.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_page {
+	unsigned long kva;
+};
+
+static inline int efhw_page_alloc(struct efhw_page *p)
+{
+	p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+	return p->kva ? 0 : -ENOMEM;
+}
+
+static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
+{
+	p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+	return p->kva ? 0 : -ENOMEM;
+}
+
+static inline void efhw_page_free(struct efhw_page *p)
+{
+	free_page(p->kva);
+	EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
+}
+
+static inline char *efhw_page_ptr(struct efhw_page *p)
+{
+	return (char *)p->kva;
+}
+
+static inline unsigned efhw_page_pfn(struct efhw_page *p)
+{
+	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
+}
+
+static inline void efhw_page_mark_invalid(struct efhw_page *p)
+{
+	p->kva = 0;
+}
+
+static inline int efhw_page_is_valid(struct efhw_page *p)
+{
+	return p->kva != 0;
+}
+
+static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
+{
+	p->kva = (unsigned long)va;
+}
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_iopage: A single page of memory.  Directly mapped in the driver,
+ * and can be mapped to userlevel.  Can also be accessed by the NIC.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_iopage {
+	struct efhw_page p;
+	dma_addr_t dma_addr;
+};
+
+static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *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)
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_iopages: 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.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_iopages {
+	caddr_t kva;
+	unsigned order;
+	dma_addr_t dma_addr;
+};
+
+static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
+{
+	return p->kva;
+}
+
+static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
+{
+	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
+}
+
+static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
+{
+	return p->dma_addr;
+}
+
+static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
+{
+	return 1u << (p->order + PAGE_SHIFT);
+}
+
+/* struct efhw_iopage <-> struct efhw_iopages 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 struct efhw_iopage 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(struct efhw_iopage *iopage,
+			      struct efhw_iopages *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(struct efhw_iopages *iopages,
+			      struct efhw_iopage *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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/tpmback/common.h
+++ linux-ec2-2.6.32/drivers/xen/tpmback/common.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * drivers/xen/tpmback/common.h
+ */
+
+#ifndef __TPM__BACKEND__COMMON_H__
+#define __TPM__BACKEND__COMMON_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <xen/evtchn.h>
+#include <xen/driver_util.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/tpmif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+#define DPRINTK(_f, _a...)			\
+	pr_debug("(file=%s, line=%d) " _f,	\
+		 __FILE__ , __LINE__ , ## _a )
+
+struct backend_info;
+
+typedef struct tpmif_st {
+	struct list_head tpmif_list;
+	/* Unique identifier for this interface. */
+	domid_t domid;
+	unsigned int handle;
+
+	/* Physical parameters of the comms window. */
+	unsigned int irq;
+
+	/* The shared rings and indexes. */
+	tpmif_tx_interface_t *tx;
+	struct vm_struct *tx_area;
+
+	/* Miscellaneous private stuff. */
+	enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+	int active;
+
+	struct tpmif_st *hash_next;
+	struct list_head list;	/* scheduling list */
+	atomic_t refcnt;
+
+	struct backend_info *bi;
+
+	grant_handle_t shmem_handle;
+	grant_ref_t shmem_ref;
+	struct page **mmap_pages;
+
+	char devname[20];
+} tpmif_t;
+
+void tpmif_disconnect_complete(tpmif_t * tpmif);
+tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi);
+int tpmif_interface_init(void);
+void tpmif_interface_exit(void);
+void tpmif_schedule_work(tpmif_t * tpmif);
+void tpmif_deschedule_work(tpmif_t * tpmif);
+int tpmif_xenbus_init(void);
+void tpmif_xenbus_exit(void);
+int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+irqreturn_t tpmif_be_int(int irq, void *dev_id);
+
+long int tpmback_get_instance(struct backend_info *bi);
+
+int vtpm_release_packets(tpmif_t * tpmif, int send_msgs);
+
+
+#define tpmif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define tpmif_put(_b)					\
+	do {						\
+		if (atomic_dec_and_test(&(_b)->refcnt))	\
+			tpmif_disconnect_complete(_b);	\
+	} while (0)
+
+extern int num_frontends;
+
+static inline unsigned long idx_to_kaddr(tpmif_t *t, unsigned int idx)
+{
+	return (unsigned long)pfn_to_kaddr(page_to_pfn(t->mmap_pages[idx]));
+}
+
+#endif /* __TPMIF__BACKEND__COMMON_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/tpmback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/tpmback/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_XEN_TPMDEV_BACKEND)	+= tpmbk.o
+
+tpmbk-y += tpmback.o interface.o xenbus.o
--- linux-ec2-2.6.32.orig/drivers/xen/tpmback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/tpmback/xenbus.c
@@ -0,0 +1,288 @@
+/*  Xenbus code for tpmif backend
+    Copyright (C) 2005 IBM Corporation
+    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+
+    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 <stdarg.h>
+#include <linux/module.h>
+#include <xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+	struct xenbus_device *dev;
+
+	/* our communications channel */
+	tpmif_t *tpmif;
+
+	long int frontend_id;
+	long int instance; // instance of TPM
+	u8 is_instance_set;// whether instance number has been set
+
+	/* watch front end for changes */
+	struct xenbus_watch backend_watch;
+};
+
+static void maybe_connect(struct backend_info *be);
+static void connect(struct backend_info *be);
+static int connect_ring(struct backend_info *be);
+static void backend_changed(struct xenbus_watch *watch,
+			    const char **vec, unsigned int len);
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state);
+
+long int tpmback_get_instance(struct backend_info *bi)
+{
+	long int res = -1;
+	if (bi && bi->is_instance_set)
+		res = bi->instance;
+	return res;
+}
+
+static int tpmback_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	if (!be) return 0;
+
+	if (be->backend_watch.node) {
+		unregister_xenbus_watch(&be->backend_watch);
+		kfree(be->backend_watch.node);
+		be->backend_watch.node = NULL;
+	}
+	if (be->tpmif) {
+		be->tpmif->bi = NULL;
+		vtpm_release_packets(be->tpmif, 0);
+		tpmif_put(be->tpmif);
+		be->tpmif = NULL;
+	}
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+static int tpmback_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	int err;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+
+	be->is_instance_set = 0;
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+
+	err = xenbus_watch_path2(dev, dev->nodename,
+				 "instance", &be->backend_watch,
+				 backend_changed);
+	if (err) {
+		goto fail;
+	}
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err) {
+		goto fail;
+	}
+	return 0;
+fail:
+	tpmback_remove(dev);
+	return err;
+}
+
+
+static void backend_changed(struct xenbus_watch *watch,
+			    const char **vec, unsigned int len)
+{
+	int err;
+	long instance;
+	struct backend_info *be
+		= container_of(watch, struct backend_info, backend_watch);
+	struct xenbus_device *dev = be->dev;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+			   "instance","%li", &instance);
+	if (XENBUS_EXIST_ERR(err)) {
+		return;
+	}
+
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading instance");
+		return;
+	}
+
+	if (be->is_instance_set == 0) {
+		be->instance = instance;
+		be->is_instance_set = 1;
+	}
+}
+
+
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+	int err;
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+		break;
+
+	case XenbusStateConnected:
+		err = connect_ring(be);
+		if (err) {
+			return;
+		}
+		maybe_connect(be);
+		break;
+
+	case XenbusStateClosing:
+		be->instance = -1;
+		xenbus_switch_state(dev, XenbusStateClosing);
+		break;
+
+	case XenbusStateUnknown: /* keep it here */
+	case XenbusStateClosed:
+		xenbus_switch_state(dev, XenbusStateClosed);
+		device_unregister(&be->dev->dev);
+		tpmback_remove(dev);
+		break;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL,
+				 "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+
+static void maybe_connect(struct backend_info *be)
+{
+	if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
+		return;
+
+	connect(be);
+}
+
+
+static void connect(struct backend_info *be)
+{
+	struct xenbus_transaction xbt;
+	int err;
+	struct xenbus_device *dev = be->dev;
+	unsigned long ready = 1;
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(be->dev, err, "starting transaction");
+		return;
+	}
+
+	err = xenbus_printf(xbt, be->dev->nodename,
+			    "ready", "%lu", ready);
+	if (err) {
+		xenbus_dev_fatal(be->dev, err, "writing 'ready'");
+		goto abort;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err)
+		xenbus_dev_fatal(be->dev, err, "end of transaction");
+
+	err = xenbus_switch_state(dev, XenbusStateConnected);
+	if (!err)
+		be->tpmif->status = CONNECTED;
+	return;
+abort:
+	xenbus_transaction_end(xbt, 1);
+}
+
+
+static int connect_ring(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long ring_ref;
+	unsigned int evtchn;
+	int err;
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "ring-ref", "%lu", &ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_error(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	if (!be->tpmif) {
+		be->tpmif = tpmif_find(dev->otherend_id, be);
+		if (IS_ERR(be->tpmif)) {
+			err = PTR_ERR(be->tpmif);
+			be->tpmif = NULL;
+			xenbus_dev_fatal(dev,err,"creating vtpm interface");
+			return err;
+		}
+	}
+
+	if (be->tpmif != NULL) {
+		err = tpmif_map(be->tpmif, ring_ref, evtchn);
+		if (err) {
+			xenbus_dev_error(dev, err,
+					 "mapping shared-frame %lu port %u",
+					 ring_ref, evtchn);
+			return err;
+		}
+	}
+	return 0;
+}
+
+
+static const struct xenbus_device_id tpmback_ids[] = {
+	{ "vtpm" },
+	{ "" }
+};
+
+
+static struct xenbus_driver tpmback = {
+	.name = "vtpm",
+	.ids = tpmback_ids,
+	.probe = tpmback_probe,
+	.remove = tpmback_remove,
+	.otherend_changed = frontend_changed,
+};
+
+
+int tpmif_xenbus_init(void)
+{
+	return xenbus_register_backend(&tpmback);
+}
+
+void tpmif_xenbus_exit(void)
+{
+	xenbus_unregister_driver(&tpmback);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/tpmback/tpmback.c
+++ linux-ec2-2.6.32/drivers/xen/tpmback/tpmback.c
@@ -0,0 +1,952 @@
+/******************************************************************************
+ * drivers/xen/tpmback/tpmback.c
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@us.ibm.com
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from drivers/xen/netback/netback.c
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ */
+
+#include "common.h"
+#include <xen/evtchn.h>
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+#include <xen/xenbus.h>
+#include <xen/interface/grant_table.h>
+#include <xen/gnttab.h>
+
+/* local data structures */
+struct data_exchange {
+	struct list_head pending_pak;
+	struct list_head current_pak;
+	unsigned int copied_so_far;
+	u8 has_opener:1;
+	u8 aborted:1;
+	rwlock_t pak_lock;	// protects all of the previous fields
+	wait_queue_head_t wait_queue;
+};
+
+struct vtpm_resp_hdr {
+	uint32_t instance_no;
+	uint16_t tag_no;
+	uint32_t len_no;
+	uint32_t ordinal_no;
+} __attribute__ ((packed));
+
+struct packet {
+	struct list_head next;
+	unsigned int data_len;
+	u8 *data_buffer;
+	tpmif_t *tpmif;
+	u32 tpm_instance;
+	u8 req_tag;
+	u32 last_read;
+	u8 flags;
+	struct timer_list processing_timer;
+};
+
+enum {
+	PACKET_FLAG_DISCARD_RESPONSE = 1,
+};
+
+/* local variables */
+static struct data_exchange dataex;
+
+/* local function prototypes */
+static int _packet_write(struct packet *pak,
+			 const char *data, size_t size, int userbuffer);
+static void processing_timeout(unsigned long ptr);
+static int packet_read_shmem(struct packet *pak,
+			     tpmif_t * tpmif,
+			     u32 offset,
+			     char *buffer, int isuserbuffer, u32 left);
+static int vtpm_queue_packet(struct packet *pak);
+
+/***************************************************************
+ Buffer copying fo user and kernel space buffes.
+***************************************************************/
+static inline int copy_from_buffer(void *to,
+				   const void *from, unsigned long size,
+				   int isuserbuffer)
+{
+	if (isuserbuffer) {
+		if (copy_from_user(to, (void __user *)from, size))
+			return -EFAULT;
+	} else {
+		memcpy(to, from, size);
+	}
+	return 0;
+}
+
+static inline int copy_to_buffer(void *to,
+				 const void *from, unsigned long size,
+				 int isuserbuffer)
+{
+	if (isuserbuffer) {
+		if (copy_to_user((void __user *)to, from, size))
+			return -EFAULT;
+	} else {
+		memcpy(to, from, size);
+	}
+	return 0;
+}
+
+
+static void dataex_init(struct data_exchange *dataex)
+{
+	INIT_LIST_HEAD(&dataex->pending_pak);
+	INIT_LIST_HEAD(&dataex->current_pak);
+	dataex->has_opener = 0;
+	rwlock_init(&dataex->pak_lock);
+	init_waitqueue_head(&dataex->wait_queue);
+}
+
+/***************************************************************
+ Packet-related functions
+***************************************************************/
+
+static struct packet *packet_find_instance(struct list_head *head,
+					   u32 tpm_instance)
+{
+	struct packet *pak;
+	struct list_head *p;
+
+	/*
+	 * traverse the list of packets and return the first
+	 * one with the given instance number
+	 */
+	list_for_each(p, head) {
+		pak = list_entry(p, struct packet, next);
+
+		if (pak->tpm_instance == tpm_instance) {
+			return pak;
+		}
+	}
+	return NULL;
+}
+
+static struct packet *packet_find_packet(struct list_head *head, void *packet)
+{
+	struct packet *pak;
+	struct list_head *p;
+
+	/*
+	 * traverse the list of packets and return the first
+	 * one with the given instance number
+	 */
+	list_for_each(p, head) {
+		pak = list_entry(p, struct packet, next);
+
+		if (pak == packet) {
+			return pak;
+		}
+	}
+	return NULL;
+}
+
+static struct packet *packet_alloc(tpmif_t * tpmif,
+				   u32 size, u8 req_tag, u8 flags)
+{
+	struct packet *pak = NULL;
+	pak = kzalloc(sizeof (struct packet), GFP_ATOMIC);
+	if (NULL != pak) {
+		if (tpmif) {
+			pak->tpmif = tpmif;
+			pak->tpm_instance = tpmback_get_instance(tpmif->bi);
+			tpmif_get(tpmif);
+		}
+		pak->data_len = size;
+		pak->req_tag = req_tag;
+		pak->last_read = 0;
+		pak->flags = flags;
+
+		/*
+		 * cannot do tpmif_get(tpmif); bad things happen
+		 * on the last tpmif_put()
+		 */
+		init_timer(&pak->processing_timer);
+		pak->processing_timer.function = processing_timeout;
+		pak->processing_timer.data = (unsigned long)pak;
+	}
+	return pak;
+}
+
+static void inline packet_reset(struct packet *pak)
+{
+	pak->last_read = 0;
+}
+
+static void packet_free(struct packet *pak)
+{
+	if (timer_pending(&pak->processing_timer)) {
+		BUG();
+	}
+
+	if (pak->tpmif)
+		tpmif_put(pak->tpmif);
+	kfree(pak->data_buffer);
+	/*
+	 * cannot do tpmif_put(pak->tpmif); bad things happen
+	 * on the last tpmif_put()
+	 */
+	kfree(pak);
+}
+
+
+/*
+ * Write data to the shared memory and send it to the FE.
+ */
+static int packet_write(struct packet *pak,
+			const char *data, size_t size, int isuserbuffer)
+{
+	int rc = 0;
+
+	if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
+		/* Don't send a respone to this packet. Just acknowledge it. */
+		rc = size;
+	} else {
+		rc = _packet_write(pak, data, size, isuserbuffer);
+	}
+
+	return rc;
+}
+
+int _packet_write(struct packet *pak,
+		  const char *data, size_t size, int isuserbuffer)
+{
+	/*
+	 * Write into the shared memory pages directly
+	 * and send it to the front end.
+	 */
+	tpmif_t *tpmif = pak->tpmif;
+	grant_handle_t handle;
+	int rc = 0;
+	unsigned int i = 0;
+	unsigned int offset = 0;
+
+	if (tpmif == NULL) {
+		return -EFAULT;
+	}
+
+	if (tpmif->status == DISCONNECTED) {
+		return size;
+	}
+
+	while (offset < size && i < TPMIF_TX_RING_SIZE) {
+		unsigned int tocopy;
+		struct gnttab_map_grant_ref map_op;
+		struct gnttab_unmap_grant_ref unmap_op;
+		tpmif_tx_request_t *tx;
+
+		tx = &tpmif->tx->ring[i].req;
+
+		if (0 == tx->addr) {
+			DPRINTK("ERROR: Buffer for outgoing packet NULL?! i=%d\n", i);
+			return 0;
+		}
+
+		gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
+				  GNTMAP_host_map, tx->ref, tpmif->domid);
+
+		if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+						       &map_op, 1))) {
+			BUG();
+		}
+
+		handle = map_op.handle;
+
+		if (map_op.status) {
+			DPRINTK(" Grant table operation failure !\n");
+			return 0;
+		}
+
+		tocopy = min_t(size_t, size - offset, PAGE_SIZE);
+
+		if (copy_from_buffer((void *)(idx_to_kaddr(tpmif, i) |
+					      (tx->addr & ~PAGE_MASK)),
+				     &data[offset], tocopy, isuserbuffer)) {
+			tpmif_put(tpmif);
+			return -EFAULT;
+		}
+		tx->size = tocopy;
+
+		gnttab_set_unmap_op(&unmap_op, idx_to_kaddr(tpmif, i),
+				    GNTMAP_host_map, handle);
+
+		if (unlikely
+		    (HYPERVISOR_grant_table_op
+		     (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
+			BUG();
+		}
+
+		offset += tocopy;
+		i++;
+	}
+
+	rc = offset;
+	DPRINTK("Notifying frontend via irq %d\n", tpmif->irq);
+	notify_remote_via_irq(tpmif->irq);
+
+	return rc;
+}
+
+/*
+ * Read data from the shared memory and copy it directly into the
+ * provided buffer. Advance the read_last indicator which tells
+ * how many bytes have already been read.
+ */
+static int packet_read(struct packet *pak, size_t numbytes,
+		       char *buffer, size_t buffersize, int isuserbuffer)
+{
+	tpmif_t *tpmif = pak->tpmif;
+
+	/*
+	 * Read 'numbytes' of data from the buffer. The first 4
+	 * bytes are the instance number in network byte order,
+	 * after that come the data from the shared memory buffer.
+	 */
+	u32 to_copy;
+	u32 offset = 0;
+	u32 room_left = buffersize;
+
+	if (pak->last_read < 4) {
+		/*
+		 * copy the instance number into the buffer
+		 */
+		u32 instance_no = htonl(pak->tpm_instance);
+		u32 last_read = pak->last_read;
+
+		to_copy = min_t(size_t, 4 - last_read, numbytes);
+
+		if (copy_to_buffer(&buffer[0],
+				   &(((u8 *) & instance_no)[last_read]),
+				   to_copy, isuserbuffer)) {
+			return -EFAULT;
+		}
+
+		pak->last_read += to_copy;
+		offset += to_copy;
+		room_left -= to_copy;
+	}
+
+	/*
+	 * If the packet has a data buffer appended, read from it...
+	 */
+
+	if (room_left > 0) {
+		if (pak->data_buffer) {
+			u32 to_copy = min_t(u32, pak->data_len - offset, room_left);
+			u32 last_read = pak->last_read - 4;
+
+			if (copy_to_buffer(&buffer[offset],
+					   &pak->data_buffer[last_read],
+					   to_copy, isuserbuffer)) {
+				return -EFAULT;
+			}
+			pak->last_read += to_copy;
+			offset += to_copy;
+		} else {
+			offset = packet_read_shmem(pak,
+						   tpmif,
+						   offset,
+						   buffer,
+						   isuserbuffer, room_left);
+		}
+	}
+	return offset;
+}
+
+static int packet_read_shmem(struct packet *pak,
+			     tpmif_t * tpmif,
+			     u32 offset, char *buffer, int isuserbuffer,
+			     u32 room_left)
+{
+	u32 last_read = pak->last_read - 4;
+	u32 i = (last_read / PAGE_SIZE);
+	u32 pg_offset = last_read & (PAGE_SIZE - 1);
+	u32 to_copy;
+	grant_handle_t handle;
+
+	tpmif_tx_request_t *tx;
+
+	tx = &tpmif->tx->ring[0].req;
+	/*
+	 * Start copying data at the page with index 'index'
+	 * and within that page at offset 'offset'.
+	 * Copy a maximum of 'room_left' bytes.
+	 */
+	to_copy = min_t(u32, PAGE_SIZE - pg_offset, room_left);
+	while (to_copy > 0) {
+		void *src;
+		struct gnttab_map_grant_ref map_op;
+		struct gnttab_unmap_grant_ref unmap_op;
+
+		tx = &tpmif->tx->ring[i].req;
+
+		gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
+				  GNTMAP_host_map, tx->ref, tpmif->domid);
+
+		if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+						       &map_op, 1))) {
+			BUG();
+		}
+
+		if (map_op.status) {
+			DPRINTK(" Grant table operation failure !\n");
+			return -EFAULT;
+		}
+
+		handle = map_op.handle;
+
+		if (to_copy > tx->size) {
+			/*
+			 * User requests more than what's available
+			 */
+			to_copy = min_t(u32, tx->size, to_copy);
+		}
+
+		DPRINTK("Copying from mapped memory at %08lx\n",
+			(unsigned long)(idx_to_kaddr(tpmif, i) |
+					(tx->addr & ~PAGE_MASK)));
+
+		src = (void *)(idx_to_kaddr(tpmif, i) |
+			       ((tx->addr & ~PAGE_MASK) + pg_offset));
+		if (copy_to_buffer(&buffer[offset],
+				   src, to_copy, isuserbuffer)) {
+			return -EFAULT;
+		}
+
+		DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n",
+			tpmif->domid, buffer[offset], buffer[offset + 1],
+			buffer[offset + 2], buffer[offset + 3]);
+
+		gnttab_set_unmap_op(&unmap_op, idx_to_kaddr(tpmif, i),
+				    GNTMAP_host_map, handle);
+
+		if (unlikely
+		    (HYPERVISOR_grant_table_op
+		     (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
+			BUG();
+		}
+
+		offset += to_copy;
+		pg_offset = 0;
+		last_read += to_copy;
+		room_left -= to_copy;
+
+		to_copy = min_t(u32, PAGE_SIZE, room_left);
+		i++;
+	}			/* while (to_copy > 0) */
+	/*
+	 * Adjust the last_read pointer
+	 */
+	pak->last_read = last_read + 4;
+	return offset;
+}
+
+/* ============================================================
+ * The file layer for reading data from this device
+ * ============================================================
+ */
+static int vtpm_op_open(struct inode *inode, struct file *f)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	write_lock_irqsave(&dataex.pak_lock, flags);
+	if (dataex.has_opener == 0) {
+		dataex.has_opener = 1;
+	} else {
+		rc = -EPERM;
+	}
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+	return rc;
+}
+
+static ssize_t vtpm_op_read(struct file *file,
+			    char __user * data, size_t size, loff_t * offset)
+{
+	int ret_size = -ENODATA;
+	struct packet *pak = NULL;
+	unsigned long flags;
+
+	write_lock_irqsave(&dataex.pak_lock, flags);
+	if (dataex.aborted) {
+		dataex.aborted = 0;
+		dataex.copied_so_far = 0;
+		write_unlock_irqrestore(&dataex.pak_lock, flags);
+		return -EIO;
+	}
+
+	if (list_empty(&dataex.pending_pak)) {
+		write_unlock_irqrestore(&dataex.pak_lock, flags);
+		wait_event_interruptible(dataex.wait_queue,
+					 !list_empty(&dataex.pending_pak));
+		write_lock_irqsave(&dataex.pak_lock, flags);
+		dataex.copied_so_far = 0;
+	}
+
+	if (!list_empty(&dataex.pending_pak)) {
+		unsigned int left;
+
+		pak = list_entry(dataex.pending_pak.next, struct packet, next);
+		left = pak->data_len - dataex.copied_so_far;
+		list_del(&pak->next);
+		write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+		DPRINTK("size given by app: %zu, available: %u\n", size, left);
+
+		ret_size = min_t(size_t, size, left);
+
+		ret_size = packet_read(pak, ret_size, data, size, 1);
+
+		write_lock_irqsave(&dataex.pak_lock, flags);
+
+		if (ret_size < 0) {
+			del_singleshot_timer_sync(&pak->processing_timer);
+			packet_free(pak);
+			dataex.copied_so_far = 0;
+		} else {
+			DPRINTK("Copied %d bytes to user buffer\n", ret_size);
+
+			dataex.copied_so_far += ret_size;
+			if (dataex.copied_so_far >= pak->data_len + 4) {
+				DPRINTK("All data from this packet given to app.\n");
+				/* All data given to app */
+
+				del_singleshot_timer_sync(&pak->
+							  processing_timer);
+				list_add_tail(&pak->next, &dataex.current_pak);
+				/*
+				 * The more fontends that are handled at the same time,
+				 * the more time we give the TPM to process the request.
+				 */
+				mod_timer(&pak->processing_timer,
+					  jiffies + (num_frontends * 60 * HZ));
+				dataex.copied_so_far = 0;
+			} else {
+				list_add(&pak->next, &dataex.pending_pak);
+			}
+		}
+	}
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+	DPRINTK("Returning result from read to app: %d\n", ret_size);
+
+	return ret_size;
+}
+
+/*
+ * Write operation - only works after a previous read operation!
+ */
+static ssize_t vtpm_op_write(struct file *file,
+			     const char __user * data, size_t size,
+			     loff_t * offset)
+{
+	struct packet *pak;
+	int rc = 0;
+	unsigned int off = 4;
+	unsigned long flags;
+	struct vtpm_resp_hdr vrh;
+
+	/*
+	 * Minimum required packet size is:
+	 * 4 bytes for instance number
+	 * 2 bytes for tag
+	 * 4 bytes for paramSize
+	 * 4 bytes for the ordinal
+	 * sum: 14 bytes
+	 */
+	if (size < sizeof (vrh))
+		return -EFAULT;
+
+	if (copy_from_user(&vrh, data, sizeof (vrh)))
+		return -EFAULT;
+
+	/* malformed packet? */
+	if ((off + ntohl(vrh.len_no)) != size)
+		return -EFAULT;
+
+	write_lock_irqsave(&dataex.pak_lock, flags);
+	pak = packet_find_instance(&dataex.current_pak,
+				   ntohl(vrh.instance_no));
+
+	if (pak == NULL) {
+		write_unlock_irqrestore(&dataex.pak_lock, flags);
+		DPRINTK(KERN_ALERT "No associated packet! (inst=%d)\n",
+		        ntohl(vrh.instance_no));
+		return -EFAULT;
+	}
+
+	del_singleshot_timer_sync(&pak->processing_timer);
+	list_del(&pak->next);
+
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+	/*
+	 * The first 'offset' bytes must be the instance number - skip them.
+	 */
+	size -= off;
+
+	rc = packet_write(pak, &data[off], size, 1);
+
+	if (rc > 0) {
+		/* I neglected the first 4 bytes */
+		rc += off;
+	}
+	packet_free(pak);
+	return rc;
+}
+
+static int vtpm_op_release(struct inode *inode, struct file *file)
+{
+	unsigned long flags;
+
+	vtpm_release_packets(NULL, 1);
+	write_lock_irqsave(&dataex.pak_lock, flags);
+	dataex.has_opener = 0;
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+	return 0;
+}
+
+static unsigned int vtpm_op_poll(struct file *file,
+				 struct poll_table_struct *pts)
+{
+	unsigned int flags = POLLOUT | POLLWRNORM;
+
+	poll_wait(file, &dataex.wait_queue, pts);
+	if (!list_empty(&dataex.pending_pak)) {
+		flags |= POLLIN | POLLRDNORM;
+	}
+	return flags;
+}
+
+static const struct file_operations vtpm_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = vtpm_op_open,
+	.read = vtpm_op_read,
+	.write = vtpm_op_write,
+	.release = vtpm_op_release,
+	.poll = vtpm_op_poll,
+};
+
+static struct miscdevice vtpms_miscdevice = {
+	.minor = 225,
+	.name = "vtpm",
+	.fops = &vtpm_ops,
+};
+
+/***************************************************************
+ Utility functions
+***************************************************************/
+
+static int tpm_send_fail_message(struct packet *pak, u8 req_tag)
+{
+	int rc;
+	static const unsigned char tpm_error_message_fail[] = {
+		0x00, 0x00,
+		0x00, 0x00, 0x00, 0x0a,
+		0x00, 0x00, 0x00, 0x09	/* TPM_FAIL */
+	};
+	unsigned char buffer[sizeof (tpm_error_message_fail)];
+
+	memcpy(buffer, tpm_error_message_fail,
+	       sizeof (tpm_error_message_fail));
+	/*
+	 * Insert the right response tag depending on the given tag
+	 * All response tags are '+3' to the request tag.
+	 */
+	buffer[1] = req_tag + 3;
+
+	/*
+	 * Write the data to shared memory and notify the front-end
+	 */
+	rc = packet_write(pak, buffer, sizeof (buffer), 0);
+
+	return rc;
+}
+
+static int _vtpm_release_packets(struct list_head *head,
+				 tpmif_t * tpmif, int send_msgs)
+{
+	int aborted = 0;
+	int c = 0;
+	struct packet *pak;
+	struct list_head *pos, *tmp;
+
+	list_for_each_safe(pos, tmp, head) {
+		pak = list_entry(pos, struct packet, next);
+		c += 1;
+
+		if (tpmif == NULL || pak->tpmif == tpmif) {
+			int can_send = 0;
+
+			del_singleshot_timer_sync(&pak->processing_timer);
+			list_del(&pak->next);
+
+			if (pak->tpmif && pak->tpmif->status == CONNECTED) {
+				can_send = 1;
+			}
+
+			if (send_msgs && can_send) {
+				tpm_send_fail_message(pak, pak->req_tag);
+			}
+			packet_free(pak);
+			if (c == 1)
+				aborted = 1;
+		}
+	}
+	return aborted;
+}
+
+int vtpm_release_packets(tpmif_t * tpmif, int send_msgs)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&dataex.pak_lock, flags);
+
+	dataex.aborted = _vtpm_release_packets(&dataex.pending_pak,
+					       tpmif,
+					       send_msgs);
+	_vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
+
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+	return 0;
+}
+
+static int vtpm_queue_packet(struct packet *pak)
+{
+	int rc = 0;
+
+	if (dataex.has_opener) {
+		unsigned long flags;
+
+		write_lock_irqsave(&dataex.pak_lock, flags);
+		list_add_tail(&pak->next, &dataex.pending_pak);
+		/* give the TPM some time to pick up the request */
+		mod_timer(&pak->processing_timer, jiffies + (30 * HZ));
+		write_unlock_irqrestore(&dataex.pak_lock, flags);
+
+		wake_up_interruptible(&dataex.wait_queue);
+	} else {
+		rc = -EFAULT;
+	}
+	return rc;
+}
+
+static int vtpm_receive(tpmif_t * tpmif, u32 size)
+{
+	int rc = 0;
+	unsigned char buffer[10];
+	__be32 *native_size;
+	struct packet *pak = packet_alloc(tpmif, size, 0, 0);
+
+	if (!pak)
+		return -ENOMEM;
+	/*
+	 * Read 10 bytes from the received buffer to test its
+	 * content for validity.
+	 */
+	if (sizeof (buffer) != packet_read(pak,
+					   sizeof (buffer), buffer,
+					   sizeof (buffer), 0)) {
+		goto failexit;
+	}
+	/*
+	 * Reset the packet read pointer so we can read all its
+	 * contents again.
+	 */
+	packet_reset(pak);
+
+	native_size = (__force __be32 *) (&buffer[4 + 2]);
+	/*
+	 * Verify that the size of the packet is correct
+	 * as indicated and that there's actually someone reading packets.
+	 * The minimum size of the packet is '10' for tag, size indicator
+	 * and ordinal.
+	 */
+	if (size < 10 ||
+	    be32_to_cpu(*native_size) != size ||
+	    0 == dataex.has_opener || tpmif->status != CONNECTED) {
+		rc = -EINVAL;
+		goto failexit;
+	} else {
+		rc = vtpm_queue_packet(pak);
+		if (rc < 0)
+			goto failexit;
+	}
+	return 0;
+
+      failexit:
+	if (pak) {
+		tpm_send_fail_message(pak, buffer[4 + 1]);
+		packet_free(pak);
+	}
+	return rc;
+}
+
+/*
+ * Timeout function that gets invoked when a packet has not been processed
+ * during the timeout period.
+ * The packet must be on a list when this function is invoked. This
+ * also means that once its taken off a list, the timer must be
+ * destroyed as well.
+ */
+static void processing_timeout(unsigned long ptr)
+{
+	struct packet *pak = (struct packet *)ptr;
+	unsigned long flags;
+
+	write_lock_irqsave(&dataex.pak_lock, flags);
+	/*
+	 * The packet needs to be searched whether it
+	 * is still on the list.
+	 */
+	if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
+	    pak == packet_find_packet(&dataex.current_pak, pak)) {
+		if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) {
+			tpm_send_fail_message(pak, pak->req_tag);
+		}
+		/* discard future responses */
+		pak->flags |= PACKET_FLAG_DISCARD_RESPONSE;
+	}
+
+	write_unlock_irqrestore(&dataex.pak_lock, flags);
+}
+
+static void tpm_tx_action(unsigned long unused);
+static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0);
+
+static struct list_head tpm_schedule_list;
+static spinlock_t tpm_schedule_list_lock;
+
+static inline void maybe_schedule_tx_action(void)
+{
+	smp_mb();
+	tasklet_schedule(&tpm_tx_tasklet);
+}
+
+static inline int __on_tpm_schedule_list(tpmif_t * tpmif)
+{
+	return tpmif->list.next != NULL;
+}
+
+static void remove_from_tpm_schedule_list(tpmif_t * tpmif)
+{
+	spin_lock_irq(&tpm_schedule_list_lock);
+	if (likely(__on_tpm_schedule_list(tpmif))) {
+		list_del(&tpmif->list);
+		tpmif->list.next = NULL;
+		tpmif_put(tpmif);
+	}
+	spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+static void add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
+{
+	if (__on_tpm_schedule_list(tpmif))
+		return;
+
+	spin_lock_irq(&tpm_schedule_list_lock);
+	if (!__on_tpm_schedule_list(tpmif) && tpmif->active) {
+		list_add_tail(&tpmif->list, &tpm_schedule_list);
+		tpmif_get(tpmif);
+	}
+	spin_unlock_irq(&tpm_schedule_list_lock);
+}
+
+void tpmif_schedule_work(tpmif_t * tpmif)
+{
+	add_to_tpm_schedule_list_tail(tpmif);
+	maybe_schedule_tx_action();
+}
+
+void tpmif_deschedule_work(tpmif_t * tpmif)
+{
+	remove_from_tpm_schedule_list(tpmif);
+}
+
+static void tpm_tx_action(unsigned long unused)
+{
+	struct list_head *ent;
+	tpmif_t *tpmif;
+	tpmif_tx_request_t *tx;
+
+	DPRINTK("%s: Getting data from front-end(s)!\n", __FUNCTION__);
+
+	while (!list_empty(&tpm_schedule_list)) {
+		/* Get a tpmif from the list with work to do. */
+		ent = tpm_schedule_list.next;
+		tpmif = list_entry(ent, tpmif_t, list);
+		tpmif_get(tpmif);
+		remove_from_tpm_schedule_list(tpmif);
+
+		tx = &tpmif->tx->ring[0].req;
+
+		/* pass it up */
+		vtpm_receive(tpmif, tx->size);
+
+		tpmif_put(tpmif);
+	}
+}
+
+irqreturn_t tpmif_be_int(int irq, void *dev_id)
+{
+	tpmif_t *tpmif = (tpmif_t *) dev_id;
+
+	add_to_tpm_schedule_list_tail(tpmif);
+	maybe_schedule_tx_action();
+	return IRQ_HANDLED;
+}
+
+static int __init tpmback_init(void)
+{
+	int rc;
+
+	if ((rc = misc_register(&vtpms_miscdevice)) != 0) {
+		printk(KERN_ALERT
+		       "Could not register misc device for TPM BE.\n");
+		return rc;
+	}
+
+	dataex_init(&dataex);
+
+	spin_lock_init(&tpm_schedule_list_lock);
+	INIT_LIST_HEAD(&tpm_schedule_list);
+
+	rc = tpmif_interface_init();
+	if (!rc) {
+		rc = tpmif_xenbus_init();
+		if (rc)
+			tpmif_interface_exit();
+	}
+	if (rc) {
+		misc_deregister(&vtpms_miscdevice);
+		return rc;
+	}
+
+	printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
+
+	return 0;
+}
+module_init(tpmback_init);
+
+static void __exit tpmback_exit(void)
+{
+	vtpm_release_packets(NULL, 0);
+	tpmif_xenbus_exit();
+	tpmif_interface_exit();
+	misc_deregister(&vtpms_miscdevice);
+}
+module_exit(tpmback_exit)
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/tpmback/interface.c
+++ linux-ec2-2.6.32/drivers/xen/tpmback/interface.c
@@ -0,0 +1,170 @@
+ /*****************************************************************************
+ * drivers/xen/tpmback/interface.c
+ *
+ * Vritual TPM interface management.
+ *
+ * Copyright (c) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@us.ibm.com
+ *
+ * This code has been derived from drivers/xen/netback/interface.c
+ * Copyright (c) 2004, Keir Fraser
+ */
+
+#include "common.h"
+#include <linux/err.h>
+#include <xen/balloon.h>
+#include <xen/gnttab.h>
+
+static struct kmem_cache *tpmif_cachep;
+int num_frontends = 0;
+
+LIST_HEAD(tpmif_list);
+
+static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
+{
+	tpmif_t *tpmif;
+
+	tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
+	if (tpmif == NULL)
+		goto out_of_memory;
+
+	memset(tpmif, 0, sizeof (*tpmif));
+	tpmif->domid = domid;
+	tpmif->status = DISCONNECTED;
+	tpmif->bi = bi;
+	snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
+	atomic_set(&tpmif->refcnt, 1);
+
+	tpmif->mmap_pages = alloc_empty_pages_and_pagevec(TPMIF_TX_RING_SIZE);
+	if (tpmif->mmap_pages == NULL)
+		goto out_of_memory;
+
+	list_add(&tpmif->tpmif_list, &tpmif_list);
+	num_frontends++;
+
+	return tpmif;
+
+ out_of_memory:
+	if (tpmif != NULL)
+		kmem_cache_free(tpmif_cachep, tpmif);
+	printk("%s: out of memory\n", __FUNCTION__);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void free_tpmif(tpmif_t * tpmif)
+{
+	num_frontends--;
+	list_del(&tpmif->tpmif_list);
+	free_empty_pages_and_pagevec(tpmif->mmap_pages, TPMIF_TX_RING_SIZE);
+	kmem_cache_free(tpmif_cachep, tpmif);
+}
+
+tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi)
+{
+	tpmif_t *tpmif;
+
+	list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
+		if (tpmif->bi == bi) {
+			if (tpmif->domid == domid) {
+				tpmif_get(tpmif);
+				return tpmif;
+			} else {
+				return ERR_PTR(-EEXIST);
+			}
+		}
+	}
+
+	return alloc_tpmif(domid, bi);
+}
+
+static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
+{
+	struct gnttab_map_grant_ref op;
+
+	gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
+			  GNTMAP_host_map, shared_page, tpmif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		DPRINTK(" Grant table operation failure !\n");
+		return op.status;
+	}
+
+	tpmif->shmem_ref = shared_page;
+	tpmif->shmem_handle = op.handle;
+
+	return 0;
+}
+
+static void unmap_frontend_page(tpmif_t *tpmif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr,
+			    GNTMAP_host_map, tpmif->shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+}
+
+int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
+{
+	int err;
+
+	if (tpmif->irq)
+		return 0;
+
+	if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
+		return -ENOMEM;
+
+	err = map_frontend_page(tpmif, shared_page);
+	if (err) {
+		free_vm_area(tpmif->tx_area);
+		return err;
+	}
+
+	tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
+	memset(tpmif->tx, 0, PAGE_SIZE);
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		tpmif->domid, evtchn, tpmif_be_int, 0, tpmif->devname, tpmif);
+	if (err < 0) {
+		unmap_frontend_page(tpmif);
+		free_vm_area(tpmif->tx_area);
+		return err;
+	}
+	tpmif->irq = err;
+
+	tpmif->shmem_ref = shared_page;
+	tpmif->active = 1;
+
+	return 0;
+}
+
+void tpmif_disconnect_complete(tpmif_t *tpmif)
+{
+	if (tpmif->irq)
+		unbind_from_irqhandler(tpmif->irq, tpmif);
+
+	if (tpmif->tx) {
+		unmap_frontend_page(tpmif);
+		free_vm_area(tpmif->tx_area);
+	}
+
+	free_tpmif(tpmif);
+}
+
+int __init tpmif_interface_init(void)
+{
+	tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
+					 0, 0, NULL);
+	return tpmif_cachep ? 0 : -ENOMEM;
+}
+
+void tpmif_interface_exit(void)
+{
+	kmem_cache_destroy(tpmif_cachep);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/control.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/control.c
@@ -0,0 +1,278 @@
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+
+#include "blktap.h"
+
+static DEFINE_SPINLOCK(blktap_control_lock);
+struct blktap *blktaps[MAX_BLKTAP_DEVICE];
+
+static int ring_major;
+static int device_major;
+static int blktap_control_registered;
+
+static void
+blktap_control_initialize_tap(struct blktap *tap)
+{
+	int minor = tap->minor;
+
+	memset(tap, 0, sizeof(*tap));
+	set_bit(BLKTAP_CONTROL, &tap->dev_inuse);
+	init_rwsem(&tap->tap_sem);
+	sg_init_table(tap->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	init_waitqueue_head(&tap->wq);
+	atomic_set(&tap->refcnt, 0);
+
+	tap->minor = minor;
+}
+
+static struct blktap *
+blktap_control_create_tap(void)
+{
+	int minor;
+	struct blktap *tap;
+
+	tap = kmalloc(sizeof(*tap), GFP_KERNEL);
+	if (unlikely(!tap))
+		return NULL;
+
+	blktap_control_initialize_tap(tap);
+
+	spin_lock_irq(&blktap_control_lock);
+	for (minor = 0; minor < MAX_BLKTAP_DEVICE; minor++)
+		if (!blktaps[minor])
+			break;
+
+	if (minor == MAX_BLKTAP_DEVICE) {
+		kfree(tap);
+		tap = NULL;
+		goto out;
+	}
+
+	tap->minor = minor;
+	blktaps[minor] = tap;
+
+out:
+	spin_unlock_irq(&blktap_control_lock);
+	return tap;
+}
+
+static struct blktap *
+blktap_control_allocate_tap(void)
+{
+	int err, minor;
+	struct blktap *tap;
+
+	/*
+	 * This is called only from the ioctl, which
+	 * means we should always have interrupts enabled.
+	 */
+	BUG_ON(irqs_disabled());
+
+	spin_lock_irq(&blktap_control_lock);
+
+	for (minor = 0; minor < MAX_BLKTAP_DEVICE; minor++) {
+		tap = blktaps[minor];
+		if (!tap)
+			goto found;
+
+		if (!tap->dev_inuse) {
+			blktap_control_initialize_tap(tap);
+			goto found;
+		}
+	}
+
+	tap = NULL;
+
+found:
+	spin_unlock_irq(&blktap_control_lock);
+
+	if (!tap) {
+		tap = blktap_control_create_tap();
+		if (!tap)
+			return NULL;
+	}
+
+	err = blktap_ring_create(tap);
+	if (err) {
+		BTERR("ring creation failed: %d\n", err);
+		clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
+		return NULL;
+	}
+
+	BTINFO("allocated tap %p\n", tap);
+	return tap;
+}
+
+static int
+blktap_control_ioctl(struct inode *inode, struct file *filp,
+		     unsigned int cmd, unsigned long arg)
+{
+	unsigned long dev;
+	struct blktap *tap;
+
+	switch (cmd) {
+	case BLKTAP2_IOCTL_ALLOC_TAP: {
+		struct blktap_handle h;
+
+		tap = blktap_control_allocate_tap();
+		if (!tap) {
+			BTERR("error allocating device\n");
+			return -ENOMEM;
+		}
+
+		h.ring   = ring_major;
+		h.device = device_major;
+		h.minor  = tap->minor;
+
+		if (copy_to_user((struct blktap_handle __user *)arg,
+				 &h, sizeof(h))) {
+			blktap_control_destroy_device(tap);
+			return -EFAULT;
+		}
+
+		return 0;
+	}
+
+	case BLKTAP2_IOCTL_FREE_TAP:
+		dev = arg;
+
+		if (dev > MAX_BLKTAP_DEVICE || !blktaps[dev])
+			return -EINVAL;
+
+		blktap_control_destroy_device(blktaps[dev]);
+		return 0;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static struct file_operations blktap_control_file_operations = {
+	.owner    = THIS_MODULE,
+	.ioctl    = blktap_control_ioctl,
+};
+
+static struct miscdevice blktap_misc = {
+	.minor    = MISC_DYNAMIC_MINOR,
+	.name     = "blktap-control",
+	.fops     = &blktap_control_file_operations,
+};
+
+int
+blktap_control_destroy_device(struct blktap *tap)
+{
+	int err;
+	unsigned long inuse;
+
+	if (!tap)
+		return 0;
+
+	set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
+
+	for (;;) {
+		inuse = tap->dev_inuse;
+		err   = blktap_device_destroy(tap);
+		if (err)
+			goto wait;
+
+		inuse = tap->dev_inuse;
+		err   = blktap_ring_destroy(tap);
+		if (err)
+			goto wait;
+
+		inuse = tap->dev_inuse;
+		err   = blktap_sysfs_destroy(tap);
+		if (err)
+			goto wait;
+
+		break;
+
+	wait:
+		BTDBG("inuse: 0x%lx, dev_inuse: 0x%lx\n",
+		      inuse, tap->dev_inuse);
+		if (wait_event_interruptible(tap->wq, tap->dev_inuse != inuse))
+			break;
+	}
+
+	clear_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
+
+	if (tap->dev_inuse == (1UL << BLKTAP_CONTROL)) {
+		err = 0;
+		clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
+	}
+
+	return err;
+}
+
+static int
+blktap_control_init(void)
+{
+	int err;
+
+	err = misc_register(&blktap_misc);
+	if (err) {
+		BTERR("misc_register failed for control device");
+		return err;
+	}
+
+	blktap_control_registered = 1;
+	return 0;
+}
+
+static void
+blktap_control_free(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_BLKTAP_DEVICE; i++)
+		blktap_control_destroy_device(blktaps[i]);
+
+	if (blktap_control_registered)
+		if (misc_deregister(&blktap_misc) < 0)
+			BTERR("misc_deregister failed for control device");
+}
+
+static void
+blktap_exit(void)
+{
+	blktap_control_free();
+	blktap_ring_free();
+	blktap_sysfs_free();
+	blktap_device_free();
+	blktap_request_pool_free();
+}
+
+static int __init
+blktap_init(void)
+{
+	int err;
+
+	err = blktap_request_pool_init();
+	if (err)
+		return err;
+
+	err = blktap_device_init(&device_major);
+	if (err)
+		goto fail;
+
+	err = blktap_ring_init(&ring_major);
+	if (err)
+		goto fail;
+
+	err = blktap_sysfs_init();
+	if (err)
+		goto fail;
+
+	err = blktap_control_init();
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	blktap_exit();
+	return err;
+}
+
+module_init(blktap_init);
+module_exit(blktap_exit);
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/Makefile
+++ linux-ec2-2.6.32/drivers/xen/blktap2/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap2.o
+
+blktap2-y := control.o ring.o wait_queue.o device.o request.o
+blktap2-$(CONFIG_SYSFS) += sysfs.o
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/sysfs.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/sysfs.c
@@ -0,0 +1,437 @@
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include "blktap.h"
+
+int blktap_debug_level = 1;
+
+static struct class *class;
+static DECLARE_WAIT_QUEUE_HEAD(sysfs_wq);
+
+static inline void
+blktap_sysfs_get(struct blktap *tap)
+{
+	atomic_inc(&tap->ring.sysfs_refcnt);
+}
+
+static inline void
+blktap_sysfs_put(struct blktap *tap)
+{
+	if (atomic_dec_and_test(&tap->ring.sysfs_refcnt))
+		wake_up(&sysfs_wq);
+}
+
+static inline void
+blktap_sysfs_enter(struct blktap *tap)
+{
+	blktap_sysfs_get(tap);               /* pin sysfs device */
+	mutex_lock(&tap->ring.sysfs_mutex);  /* serialize sysfs operations */
+}
+
+static inline void
+blktap_sysfs_exit(struct blktap *tap)
+{
+	mutex_unlock(&tap->ring.sysfs_mutex);
+	blktap_sysfs_put(tap);
+}
+
+static ssize_t blktap_sysfs_pause_device(struct device *,
+					 struct device_attribute *,
+					 const char *, size_t);
+DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
+static ssize_t blktap_sysfs_resume_device(struct device *,
+					  struct device_attribute *,
+					  const char *, size_t);
+DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
+
+static ssize_t
+blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t size)
+{
+	int err;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	blktap_sysfs_enter(tap);
+
+	if (!tap->ring.dev ||
+	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
+		err = -EPERM;
+		goto out;
+	}
+
+	if (size > BLKTAP2_MAX_MESSAGE_LEN) {
+		err = -ENAMETOOLONG;
+		goto out;
+	}
+
+	if (strnlen(buf, BLKTAP2_MAX_MESSAGE_LEN) >= BLKTAP2_MAX_MESSAGE_LEN) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	snprintf(tap->params.name, sizeof(tap->params.name) - 1, "%s", buf);
+	err = size;
+
+out:
+	blktap_sysfs_exit(tap);	
+	return err;
+}
+
+static ssize_t
+blktap_sysfs_get_name(struct device *dev, struct device_attribute *attr,
+		      char *buf)
+{
+	ssize_t size;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	blktap_sysfs_enter(tap);
+
+	if (!tap->ring.dev)
+		size = -ENODEV;
+	else if (tap->params.name[0])
+		size = sprintf(buf, "%s\n", tap->params.name);
+	else
+		size = sprintf(buf, "%d\n", tap->minor);
+
+	blktap_sysfs_exit(tap);
+
+	return size;
+}
+DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
+		  blktap_sysfs_get_name, blktap_sysfs_set_name);
+
+static ssize_t
+blktap_sysfs_remove_device(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	int err;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	if (!tap->ring.dev)
+		return size;
+
+	if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
+		return -EBUSY;
+
+	err = blktap_control_destroy_device(tap);
+
+	return (err ? : size);
+}
+DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
+
+static ssize_t
+blktap_sysfs_pause_device(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t size)
+{
+	int err;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	blktap_sysfs_enter(tap);
+
+	BTDBG("pausing %u:%u: dev_inuse: %lu\n",
+	      MAJOR(tap->ring.devno), MINOR(tap->ring.devno), tap->dev_inuse);
+
+	if (!tap->ring.dev ||
+	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
+		err = 0;
+		goto out;
+	}
+
+	err = blktap_device_pause(tap);
+	if (!err) {
+		device_remove_file(dev, &dev_attr_pause);
+		err = device_create_file(dev, &dev_attr_resume);
+	}
+
+out:
+	blktap_sysfs_exit(tap);
+
+	return (err ? err : size);
+}
+
+static ssize_t
+blktap_sysfs_resume_device(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	int err;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	blktap_sysfs_enter(tap);
+
+	if (!tap->ring.dev ||
+	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = blktap_device_resume(tap);
+	if (!err) {
+		device_remove_file(dev, &dev_attr_resume);
+		err = device_create_file(dev, &dev_attr_pause);
+	}
+
+out:
+	blktap_sysfs_exit(tap);
+
+	BTDBG("returning %zd\n", (err ? err : size));
+	return (err ? err : size);
+}
+
+#ifdef ENABLE_PASSTHROUGH
+static ssize_t
+blktap_sysfs_enable_passthrough(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	int err;
+	unsigned major, minor;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	BTINFO("passthrough request enabled\n");
+
+	blktap_sysfs_enter(tap);
+
+	if (!tap->ring.dev ||
+	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = sscanf(buf, "%x:%x", &major, &minor);
+	if (err != 2) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = blktap_device_enable_passthrough(tap, major, minor);
+
+out:
+	blktap_sysfs_exit(tap);
+	BTDBG("returning %d\n", (err ? err : size));
+	return (err ? err : size);
+}
+#endif
+
+static ssize_t
+blktap_sysfs_debug_device(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	char *tmp;
+	int i, ret;
+	struct blktap *tap = dev_get_drvdata(dev);
+
+	tmp = buf;
+	blktap_sysfs_get(tap);
+
+	if (!tap->ring.dev) {
+		ret = sprintf(tmp, "no device\n");
+		goto out;
+	}
+
+	tmp += sprintf(tmp, "%s (%u:%u), refcnt: %d, dev_inuse: 0x%08lx\n",
+		       tap->params.name, MAJOR(tap->ring.devno),
+		       MINOR(tap->ring.devno), atomic_read(&tap->refcnt),
+		       tap->dev_inuse);
+	tmp += sprintf(tmp, "capacity: 0x%llx, sector size: 0x%lx, "
+		       "device users: %d\n", tap->params.capacity,
+		       tap->params.sector_size, tap->device.users);
+
+	down_read(&tap->tap_sem);
+
+	tmp += sprintf(tmp, "pending requests: %d\n", tap->pending_cnt);
+	for (i = 0; i < MAX_PENDING_REQS; i++) {
+		struct blktap_request *req = tap->pending_requests[i];
+		if (!req)
+			continue;
+
+		tmp += sprintf(tmp, "req %d: id: %llu, usr_idx: %d, "
+			       "status: 0x%02x, pendcnt: %d, "
+			       "nr_pages: %u, op: %d, time: %lu:%lu\n",
+			       i, (unsigned long long)req->id, req->usr_idx,
+			       req->status, atomic_read(&req->pendcnt),
+			       req->nr_pages, req->operation, req->time.tv_sec,
+			       req->time.tv_usec);
+	}
+
+	up_read(&tap->tap_sem);
+	ret = (tmp - buf) + 1;
+
+out:
+	blktap_sysfs_put(tap);
+	BTDBG("%s\n", buf);
+
+	return ret;
+}
+DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
+
+int
+blktap_sysfs_create(struct blktap *tap)
+{
+	struct blktap_ring *ring;
+	struct device *dev;
+
+	if (!class)
+		return -ENODEV;
+
+	ring = &tap->ring;
+
+	dev = device_create(class, NULL, ring->devno, tap,
+			    "blktap%d", tap->minor);
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+
+	ring->dev = dev;
+
+	mutex_init(&ring->sysfs_mutex);
+	atomic_set(&ring->sysfs_refcnt, 0);
+	set_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+
+	if (device_create_file(dev, &dev_attr_name) ||
+	    device_create_file(dev, &dev_attr_remove) ||
+	    device_create_file(dev, &dev_attr_pause) ||
+	    device_create_file(dev, &dev_attr_debug))
+		printk(KERN_WARNING
+		       "One or more attibute files not created for blktap%d\n",
+		       tap->minor);
+
+	return 0;
+}
+
+int
+blktap_sysfs_destroy(struct blktap *tap)
+{
+	struct blktap_ring *ring;
+	struct device *dev;
+
+	ring = &tap->ring;
+	dev  = ring->dev;
+	if (!class || !dev)
+		return 0;
+
+	ring->dev = NULL;
+	if (wait_event_interruptible(sysfs_wq,
+				     !atomic_read(&tap->ring.sysfs_refcnt)))
+		return -EAGAIN;
+
+	/* XXX: is it safe to remove the class from a sysfs attribute? */
+	device_remove_file(dev, &dev_attr_name);
+	device_remove_file(dev, &dev_attr_remove);
+	device_remove_file(dev, &dev_attr_pause);
+	device_remove_file(dev, &dev_attr_resume);
+	device_remove_file(dev, &dev_attr_debug);
+	device_destroy(class, ring->devno);
+
+	clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+
+	return 0;
+}
+
+static ssize_t
+blktap_sysfs_show_verbosity(struct class *class, char *buf)
+{
+	return sprintf(buf, "%d\n", blktap_debug_level);
+}
+
+static ssize_t
+blktap_sysfs_set_verbosity(struct class *class, const char *buf, size_t size)
+{
+	int level;
+
+	if (sscanf(buf, "%d", &level) == 1) {
+		blktap_debug_level = level;
+		return size;
+	}
+
+	return -EINVAL;
+}
+CLASS_ATTR(verbosity, S_IRUSR | S_IWUSR,
+	   blktap_sysfs_show_verbosity, blktap_sysfs_set_verbosity);
+
+static ssize_t
+blktap_sysfs_show_devices(struct class *class, char *buf)
+{
+	int i, ret;
+	struct blktap *tap;
+
+	ret = 0;
+	for (i = 0; i < MAX_BLKTAP_DEVICE; i++) {
+		tap = blktaps[i];
+		if (!tap)
+			continue;
+
+		if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
+			continue;
+
+		ret += sprintf(buf + ret, "%d ", tap->minor);
+		ret += snprintf(buf + ret, sizeof(tap->params.name) - 1,
+				tap->params.name);
+		ret += sprintf(buf + ret, "\n");
+	}
+
+	return ret;
+}
+CLASS_ATTR(devices, S_IRUSR, blktap_sysfs_show_devices, NULL);
+
+void
+blktap_sysfs_free(void)
+{
+	if (!class)
+		return;
+
+	class_remove_file(class, &class_attr_verbosity);
+	class_remove_file(class, &class_attr_devices);
+
+	class_destroy(class);
+}
+
+int
+blktap_sysfs_init(void)
+{
+	struct class *cls;
+
+	if (class)
+		return -EEXIST;
+
+	cls = class_create(THIS_MODULE, "blktap2");
+	if (IS_ERR(cls))
+		return PTR_ERR(cls);
+
+	if (class_create_file(cls, &class_attr_verbosity) ||
+	    class_create_file(cls, &class_attr_devices))
+		printk(KERN_WARNING "blktap2: One or more "
+		       "class attribute files could not be created.\n");
+
+	class = cls;
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/blktap.h
+++ linux-ec2-2.6.32/drivers/xen/blktap2/blktap.h
@@ -0,0 +1,247 @@
+#ifndef _BLKTAP_H_
+#define _BLKTAP_H_
+
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/scatterlist.h>
+#include <xen/blkif.h>
+#include <xen/gnttab.h>
+
+//#define ENABLE_PASSTHROUGH
+
+extern int blktap_debug_level;
+
+#define BTPRINTK(level, tag, force, _f, _a...)				\
+	do {								\
+		if (blktap_debug_level > level &&			\
+		    (force || printk_ratelimit()))			\
+			printk(tag "%s: " _f, __func__, ##_a);		\
+	} while (0)
+
+#define BTDBG(_f, _a...)             BTPRINTK(8, KERN_DEBUG, 1, _f, ##_a)
+#define BTINFO(_f, _a...)            BTPRINTK(0, KERN_INFO, 0, _f, ##_a)
+#define BTWARN(_f, _a...)            BTPRINTK(0, KERN_WARNING, 0, _f, ##_a)
+#define BTERR(_f, _a...)             BTPRINTK(0, KERN_ERR, 0, _f, ##_a)
+
+#define MAX_BLKTAP_DEVICE            256
+
+#define BLKTAP_CONTROL               1
+#define BLKTAP_RING_FD               2
+#define BLKTAP_RING_VMA              3
+#define BLKTAP_DEVICE                4
+#define BLKTAP_SYSFS                 5
+#define BLKTAP_PAUSE_REQUESTED       6
+#define BLKTAP_PAUSED                7
+#define BLKTAP_SHUTDOWN_REQUESTED    8
+#define BLKTAP_PASSTHROUGH           9
+#define BLKTAP_DEFERRED              10
+
+/* blktap IOCTLs: */
+#define BLKTAP2_IOCTL_KICK_FE        1
+#define BLKTAP2_IOCTL_ALLOC_TAP	     200
+#define BLKTAP2_IOCTL_FREE_TAP       201
+#define BLKTAP2_IOCTL_CREATE_DEVICE  202
+#define BLKTAP2_IOCTL_SET_PARAMS     203
+#define BLKTAP2_IOCTL_PAUSE          204
+#define BLKTAP2_IOCTL_REOPEN         205
+#define BLKTAP2_IOCTL_RESUME         206
+
+#define BLKTAP2_MAX_MESSAGE_LEN      256
+
+#define BLKTAP2_RING_MESSAGE_PAUSE   1
+#define BLKTAP2_RING_MESSAGE_RESUME  2
+#define BLKTAP2_RING_MESSAGE_CLOSE   3
+
+#define BLKTAP_REQUEST_FREE          0
+#define BLKTAP_REQUEST_PENDING       1
+
+/*
+ * The maximum number of requests that can be outstanding at any time
+ * is determined by
+ *
+ *   [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] 
+ *
+ * where mmap_alloc < MAX_DYNAMIC_MEM.
+ *
+ * TODO:
+ * mmap_alloc is initialised to 2 and should be adjustable on the fly via
+ * sysfs.
+ */
+#define BLK_RING_SIZE		__RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+#define MAX_DYNAMIC_MEM		BLK_RING_SIZE
+#define MAX_PENDING_REQS	BLK_RING_SIZE
+#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req, _seg)					\
+        (_start +                                                       \
+         ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +        \
+         ((_seg) * PAGE_SIZE))
+
+#define blktap_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blktap_put(_b)					\
+	do {						\
+		if (atomic_dec_and_test(&(_b)->refcnt))	\
+			wake_up(&(_b)->wq);		\
+	} while (0)
+
+struct blktap;
+
+struct grant_handle_pair {
+	grant_handle_t                 kernel;
+	grant_handle_t                 user;
+};
+#define INVALID_GRANT_HANDLE           0xFFFF
+
+struct blktap_handle {
+	unsigned int                   ring;
+	unsigned int                   device;
+	unsigned int                   minor;
+};
+
+struct blktap_params {
+	char                           name[BLKTAP2_MAX_MESSAGE_LEN];
+	unsigned long long             capacity;
+	unsigned long                  sector_size;
+};
+
+struct blktap_device {
+	int                            users;
+	spinlock_t                     lock;
+	struct gendisk                *gd;
+
+#ifdef ENABLE_PASSTHROUGH
+	struct block_device           *bdev;
+#endif
+};
+
+struct blktap_ring {
+	struct vm_area_struct         *vma;
+	blkif_front_ring_t             ring;
+	struct vm_foreign_map          foreign_map;
+	unsigned long                  ring_vstart;
+	unsigned long                  user_vstart;
+
+	int                            response;
+
+	wait_queue_head_t              poll_wait;
+
+	dev_t                          devno;
+	struct device                 *dev;
+	atomic_t                       sysfs_refcnt;
+	struct mutex                   sysfs_mutex;
+};
+
+struct blktap_statistics {
+	unsigned long                  st_print;
+	int                            st_rd_req;
+	int                            st_wr_req;
+	int                            st_oo_req;
+	int                            st_pk_req;
+	int                            st_rd_sect;
+	int                            st_wr_sect;
+	s64                            st_rd_cnt;
+	s64                            st_rd_sum_usecs;
+	s64                            st_rd_max_usecs;
+	s64                            st_wr_cnt;
+	s64                            st_wr_sum_usecs;
+	s64                            st_wr_max_usecs;	
+};
+
+struct blktap_request {
+	uint64_t                       id;
+	uint16_t                       usr_idx;
+
+	uint8_t                        status;
+	atomic_t                       pendcnt;
+	uint8_t                        nr_pages;
+	unsigned short                 operation;
+
+	struct timeval                 time;
+	struct grant_handle_pair       handles[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	struct list_head               free_list;
+};
+
+struct blktap {
+	int                            minor;
+	pid_t                          pid;
+	atomic_t                       refcnt;
+	unsigned long                  dev_inuse;
+
+	struct blktap_params           params;
+
+	struct rw_semaphore            tap_sem;
+
+	struct blktap_ring             ring;
+	struct blktap_device           device;
+
+	int                            pending_cnt;
+	struct blktap_request         *pending_requests[MAX_PENDING_REQS];
+	struct scatterlist             sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+
+	wait_queue_head_t              wq;
+	struct list_head               deferred_queue;
+
+	struct blktap_statistics       stats;
+};
+
+extern struct blktap *blktaps[MAX_BLKTAP_DEVICE];
+
+static inline int
+blktap_active(struct blktap *tap)
+{
+	return test_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
+}
+
+static inline int
+blktap_validate_params(struct blktap *tap, struct blktap_params *params)
+{
+	/* TODO: sanity check */
+	params->name[sizeof(params->name) - 1] = '\0';
+	BTINFO("%s: capacity: %llu, sector-size: %lu\n",
+	       params->name, params->capacity, params->sector_size);
+	return 0;
+}
+
+int blktap_control_destroy_device(struct blktap *);
+
+int blktap_ring_init(int *);
+int blktap_ring_free(void);
+int blktap_ring_create(struct blktap *);
+int blktap_ring_destroy(struct blktap *);
+int blktap_ring_pause(struct blktap *);
+int blktap_ring_resume(struct blktap *);
+void blktap_ring_kick_user(struct blktap *);
+
+int blktap_sysfs_init(void);
+void blktap_sysfs_free(void);
+int blktap_sysfs_create(struct blktap *);
+int blktap_sysfs_destroy(struct blktap *);
+
+int blktap_device_init(int *);
+void blktap_device_free(void);
+int blktap_device_create(struct blktap *);
+int blktap_device_destroy(struct blktap *);
+int blktap_device_pause(struct blktap *);
+int blktap_device_resume(struct blktap *);
+void blktap_device_restart(struct blktap *);
+void blktap_device_finish_request(struct blktap *,
+				  blkif_response_t *,
+				  struct blktap_request *);
+void blktap_device_fail_pending_requests(struct blktap *);
+#ifdef ENABLE_PASSTHROUGH
+int blktap_device_enable_passthrough(struct blktap *,
+				     unsigned, unsigned);
+#endif
+
+void blktap_defer(struct blktap *);
+void blktap_run_deferred(void);
+
+int blktap_request_pool_init(void);
+void blktap_request_pool_free(void);
+int blktap_request_pool_grow(void);
+int blktap_request_pool_shrink(void);
+struct blktap_request *blktap_request_allocate(struct blktap *);
+void blktap_request_free(struct blktap *, struct blktap_request *);
+unsigned long request_to_kaddr(struct blktap_request *, int);
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/device.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/device.c
@@ -0,0 +1,1188 @@
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/cdrom.h>
+#include <linux/hdreg.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <asm/tlbflush.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <xen/xenbus.h>
+#include <xen/interface/io/blkif.h>
+
+#include "blktap.h"
+
+#include "../blkback/blkback-pagemap.h"
+
+#if 0
+#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a)
+#else
+#define DPRINTK_IOCTL(_f, _a...) ((void)0)
+#endif
+
+struct blktap_grant_table {
+	int cnt;
+	struct gnttab_map_grant_ref grants[BLKIF_MAX_SEGMENTS_PER_REQUEST * 2];
+};
+
+static int blktap_device_major;
+
+static inline struct blktap *
+dev_to_blktap(struct blktap_device *dev)
+{
+	return container_of(dev, struct blktap, device);
+}
+
+static int
+blktap_device_open(struct block_device *bd, fmode_t mode)
+{
+	struct blktap *tap;
+	struct blktap_device *dev = bd->bd_disk->private_data;
+
+	if (!dev)
+		return -ENOENT;
+
+	tap = dev_to_blktap(dev);
+	if (!blktap_active(tap) ||
+	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
+		return -ENOENT;
+
+	dev->users++;
+
+	return 0;
+}
+
+static int
+blktap_device_release(struct gendisk *disk, fmode_t mode)
+{
+	struct blktap_device *dev = disk->private_data;
+	struct blktap *tap = dev_to_blktap(dev);
+
+	dev->users--;
+	if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
+		blktap_device_destroy(tap);
+
+	return 0;
+}
+
+static int
+blktap_device_getgeo(struct block_device *bd, struct hd_geometry *hg)
+{
+	/* We don't have real geometry info, but let's at least return
+	   values consistent with the size of the device */
+	sector_t nsect = get_capacity(bd->bd_disk);
+	sector_t cylinders = nsect;
+
+	hg->heads = 0xff;
+	hg->sectors = 0x3f;
+	sector_div(cylinders, hg->heads * hg->sectors);
+	hg->cylinders = cylinders;
+	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
+		hg->cylinders = 0xffff;
+	return 0;
+}
+
+static int
+blktap_device_ioctl(struct block_device *bd, fmode_t mode,
+		    unsigned command, unsigned long argument)
+{
+	int i;
+
+	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx\n",
+		      command, (long)argument);
+
+	switch (command) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+	case HDIO_GETGEO: {
+		struct hd_geometry geo;
+		int ret;
+
+                if (!argument)
+                        return -EINVAL;
+
+		geo.start = get_start_sect(bd);
+		ret = blktap_device_getgeo(bd, &geo);
+		if (ret)
+			return ret;
+
+		if (copy_to_user((struct hd_geometry __user *)argument, &geo,
+				 sizeof(geo)))
+                        return -EFAULT;
+
+                return 0;
+	}
+#endif
+	case CDROMMULTISESSION:
+		BTDBG("FIXME: support multisession CDs later\n");
+		for (i = 0; i < sizeof(struct cdrom_multisession); i++)
+			if (put_user(0, (char __user *)(argument + i)))
+				return -EFAULT;
+		return 0;
+
+	case SCSI_IOCTL_GET_IDLUN:
+		if (!access_ok(VERIFY_WRITE, argument, 
+			sizeof(struct scsi_idlun)))
+			return -EFAULT;
+
+		/* return 0 for now. */
+		__put_user(0, &((struct scsi_idlun __user *)argument)->dev_id);
+		__put_user(0, 
+			&((struct scsi_idlun __user *)argument)->host_unique_id);
+		return 0;
+
+	default:
+		/*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+		  command);*/
+		return -EINVAL; /* same return as native Linux */
+	}
+
+	return 0;
+}
+
+static const struct block_device_operations blktap_device_file_operations = {
+	.owner     = THIS_MODULE,
+	.open      = blktap_device_open,
+	.release   = blktap_device_release,
+	.ioctl     = blktap_device_ioctl,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+	.getgeo    = blktap_device_getgeo
+#endif
+};
+
+static int
+blktap_map_uaddr_fn(pte_t *ptep, struct page *pmd_page,
+		    unsigned long addr, void *data)
+{
+	pte_t *pte = (pte_t *)data;
+
+	BTDBG("ptep %p -> %012llx\n", ptep, (unsigned long long)pte_val(*pte));
+	set_pte(ptep, *pte);
+	return 0;
+}
+
+static int
+blktap_map_uaddr(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+	return apply_to_page_range(vma ? vma->vm_mm : NULL, address,
+				   PAGE_SIZE, blktap_map_uaddr_fn, &pte);
+}
+
+static int
+blktap_umap_uaddr_fn(pte_t *ptep, struct page *pmd_page,
+		     unsigned long addr, void *data)
+{
+	struct vm_area_struct *vma = data;
+
+	BTDBG("ptep %p\n", ptep);
+	xen_ptep_get_and_clear_full(vma, addr, ptep, 1);
+	return 0;
+}
+
+static int
+blktap_umap_uaddr(struct vm_area_struct *vma, unsigned long address)
+{
+	struct mm_struct *mm = NULL;
+
+	if (!vma) {
+#ifdef CONFIG_X86
+		if (HYPERVISOR_update_va_mapping(address, __pte(0),
+						 UVMF_INVLPG|UVMF_ALL))
+			BUG();
+		return 1;
+#endif
+	} else
+		mm = vma->vm_mm;
+	return apply_to_page_range(mm, address,
+				   PAGE_SIZE, blktap_umap_uaddr_fn, vma);
+}
+
+static inline void
+flush_tlb_kernel_page(unsigned long kvaddr)
+{
+#ifdef CONFIG_X86
+	xen_invlpg_all(kvaddr);
+#else
+	flush_tlb_kernel_range(kvaddr, kvaddr + PAGE_SIZE);
+#endif
+}
+
+/*
+ * tap->tap_sem held on entry
+ */
+static void
+blktap_device_fast_flush(struct blktap *tap, struct blktap_request *request)
+{
+	uint64_t ptep;
+	int ret, usr_idx;
+	unsigned int i, cnt;
+	struct page **map, *page;
+	struct blktap_ring *ring;
+	struct grant_handle_pair *khandle;
+	unsigned long kvaddr, uvaddr, offset;
+	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST * 2];
+	grant_handle_t self_gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	int self_gref_nr = 0;
+
+	cnt     = 0;
+	ring    = &tap->ring;
+	usr_idx = request->usr_idx;
+	map     = ring->foreign_map.map;
+
+	if (!ring->vma)
+		return;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		zap_page_range(ring->vma, 
+			       MMAP_VADDR(ring->user_vstart, usr_idx, 0),
+			       request->nr_pages << PAGE_SHIFT, NULL);
+
+	for (i = 0; i < request->nr_pages; i++) {
+		kvaddr = request_to_kaddr(request, i);
+		uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
+
+		khandle = request->handles + i;
+
+		if (khandle->kernel != INVALID_GRANT_HANDLE) {
+			gnttab_set_unmap_op(&unmap[cnt], kvaddr,
+					    GNTMAP_host_map, khandle->kernel);
+			cnt++;
+			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+					    INVALID_P2M_ENTRY);
+		}
+
+		if (khandle->user != INVALID_GRANT_HANDLE) {
+			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+			if (create_lookup_pte_addr(ring->vma->vm_mm,
+						   uvaddr, &ptep) != 0) {
+				BTERR("Couldn't get a pte addr!\n");
+				return;
+			}
+
+			gnttab_set_unmap_op(&unmap[cnt], ptep,
+					    GNTMAP_host_map
+					    | GNTMAP_application_map
+					    | GNTMAP_contains_pte,
+					    khandle->user);
+			cnt++;
+		}
+
+		offset = (uvaddr - ring->vma->vm_start) >> PAGE_SHIFT;
+
+		BTDBG("offset: 0x%08lx, page: %p, request: %p, usr_idx: %d, "
+		      "seg: %d, kvaddr: 0x%08lx, khandle: %u, uvaddr: "
+		      "0x%08lx, handle: %u\n", offset, map[offset], request,
+		      usr_idx, i, kvaddr, khandle->kernel, uvaddr,
+		      khandle->user);
+
+		page = map[offset];
+		if (page) {
+			ClearPageReserved(map[offset]);
+			if (PageBlkback(page)) {
+				ClearPageBlkback(page);
+				set_page_private(page, 0);
+			} else if (
+				xen_feature(XENFEAT_auto_translated_physmap)) {
+				self_gref[self_gref_nr] = khandle->kernel;
+				self_gref_nr++;
+			}
+		}
+		map[offset] = NULL;
+
+		khandle->kernel = INVALID_GRANT_HANDLE;
+		khandle->user   = INVALID_GRANT_HANDLE;
+	}
+
+	if (cnt) {
+		ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+						unmap, cnt);
+		BUG_ON(ret);
+	}
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		zap_page_range(ring->vma, 
+			       MMAP_VADDR(ring->user_vstart, usr_idx, 0), 
+			       request->nr_pages << PAGE_SHIFT, NULL);
+	else {
+		for (i = 0; i < self_gref_nr; i++) {
+			gnttab_end_foreign_access_ref(self_gref[i]);
+		}
+	}
+}
+
+/*
+ * tap->tap_sem held on entry
+ */
+static void
+blktap_unmap(struct blktap *tap, struct blktap_request *request)
+{
+	int i, usr_idx;
+	unsigned long kvaddr;
+
+	usr_idx = request->usr_idx;
+	down_write(&tap->ring.vma->vm_mm->mmap_sem);
+
+	for (i = 0; i < request->nr_pages; i++) {
+		BTDBG("request: %p, seg: %d, kvaddr: 0x%08lx, khandle: %u, "
+		      "uvaddr: 0x%08lx, uhandle: %u\n", request, i,
+		      request_to_kaddr(request, i),
+		      request->handles[i].kernel,
+		      MMAP_VADDR(tap->ring.user_vstart, usr_idx, i),
+		      request->handles[i].user);
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap) &&
+		    request->handles[i].kernel == INVALID_GRANT_HANDLE) {
+			kvaddr = request_to_kaddr(request, i);
+			if (blktap_umap_uaddr(NULL, kvaddr) == 0)
+				flush_tlb_kernel_page(kvaddr);
+			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+					    INVALID_P2M_ENTRY);
+		}
+	}
+
+	blktap_device_fast_flush(tap, request);
+	up_write(&tap->ring.vma->vm_mm->mmap_sem);
+}
+
+/*
+ * called if the tapdisk process dies unexpectedly.
+ * fail and release any pending requests and disable queue.
+ */
+void
+blktap_device_fail_pending_requests(struct blktap *tap)
+{
+	int usr_idx;
+	struct request *req;
+	struct blktap_device *dev;
+	struct blktap_request *request;
+
+	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
+		return;
+
+	down_write(&tap->tap_sem);
+
+	dev = &tap->device;
+	for (usr_idx = 0; usr_idx < MAX_PENDING_REQS; usr_idx++) {
+		request = tap->pending_requests[usr_idx];
+		if (!request || request->status != BLKTAP_REQUEST_PENDING)
+			continue;
+
+		BTERR("%u:%u: failing pending %s of %d pages\n",
+		      blktap_device_major, tap->minor,
+		      (request->operation == BLKIF_OP_PACKET ?
+		       "packet" : request->operation == BLKIF_OP_READ ?
+		       "read" : "write"), request->nr_pages);
+
+		blktap_unmap(tap, request);
+		req = (struct request *)(unsigned long)request->id;
+		blk_end_request_all(req, -ENODEV);
+		blktap_request_free(tap, request);
+	}
+
+	up_write(&tap->tap_sem);
+
+	spin_lock_irq(&dev->lock);
+
+	/* fail any future requests */
+	dev->gd->queue->queuedata = NULL;
+	blk_start_queue(dev->gd->queue);
+
+	spin_unlock_irq(&dev->lock);
+}
+
+/*
+ * tap->tap_sem held on entry
+ */
+void
+blktap_device_finish_request(struct blktap *tap,
+			     blkif_response_t *res,
+			     struct blktap_request *request)
+{
+	struct request *req;
+
+	blktap_unmap(tap, request);
+
+	req = (struct request *)(unsigned long)request->id;
+
+	BTDBG("req %p res status %d operation %d/%d id %lld\n", req,
+	      res->status, res->operation, request->operation,
+	      (unsigned long long)res->id);
+
+	switch (request->operation) {
+	case BLKIF_OP_READ:
+	case BLKIF_OP_WRITE:
+	case BLKIF_OP_PACKET:
+		if (unlikely(res->status != BLKIF_RSP_OKAY))
+			BTERR("Bad return from device data "
+				"request: %x\n", res->status);
+		blk_end_request_all(req,
+			res->status == BLKIF_RSP_OKAY ? 0 : -EIO);
+		break;
+	default:
+		BUG();
+	}
+
+	blktap_request_free(tap, request);
+}
+
+static int
+blktap_prep_foreign(struct blktap *tap,
+		    struct blktap_request *request,
+		    blkif_request_t *blkif_req,
+		    unsigned int seg, struct page *page,
+		    struct blktap_grant_table *table)
+{
+	uint64_t ptep;
+	uint32_t flags;
+	struct page *tap_page;
+	struct blktap_ring *ring;
+	struct blkback_pagemap map;
+	unsigned long uvaddr, kvaddr;
+
+	ring = &tap->ring;
+	map  = blkback_pagemap_read(page);
+	blkif_req->seg[seg].gref = map.gref;
+
+	uvaddr = MMAP_VADDR(ring->user_vstart, request->usr_idx, seg);
+	kvaddr = request_to_kaddr(request, seg);
+	flags  = GNTMAP_host_map |
+		(request->operation == BLKIF_OP_WRITE ? GNTMAP_readonly : 0);
+
+	gnttab_set_map_op(&table->grants[table->cnt],
+			  kvaddr, flags, map.gref, map.domid);
+	table->cnt++;
+
+	/* enable chained tap devices */
+	tap_page = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+	set_page_private(tap_page, page_private(page));
+	SetPageBlkback(tap_page);
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return 0;
+
+	if (create_lookup_pte_addr(ring->vma->vm_mm, uvaddr, &ptep)) {
+		BTERR("couldn't get a pte addr!\n");
+		return -1;
+	}
+
+	flags |= GNTMAP_application_map | GNTMAP_contains_pte;
+	gnttab_set_map_op(&table->grants[table->cnt],
+			  ptep, flags, map.gref, map.domid);
+	table->cnt++;
+
+	return 0;
+}
+
+static int
+blktap_map_foreign(struct blktap *tap,
+		   struct blktap_request *request,
+		   blkif_request_t *blkif_req,
+		   struct blktap_grant_table *table)
+{
+	struct page *page;
+	int i, grant, err, usr_idx;
+	struct blktap_ring *ring;
+	unsigned long uvaddr, kvaddr, foreign_mfn;
+
+	if (!table->cnt)
+		return 0;
+
+	err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+					table->grants, table->cnt);
+	BUG_ON(err);
+
+	grant   = 0;
+	usr_idx = request->usr_idx;
+	ring    = &tap->ring;
+
+	for (i = 0; i < request->nr_pages; i++) {
+		if (!blkif_req->seg[i].gref)
+			continue;
+
+		uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
+		kvaddr = request_to_kaddr(request, i);
+
+		if (unlikely(table->grants[grant].status)) {
+			BTERR("invalid kernel buffer: could not remap it\n");
+			err |= 1;
+			table->grants[grant].handle = INVALID_GRANT_HANDLE;
+		}
+
+		request->handles[i].kernel = table->grants[grant].handle;
+		foreign_mfn = table->grants[grant].dev_bus_addr >> PAGE_SHIFT;
+		grant++;
+
+		if (xen_feature(XENFEAT_auto_translated_physmap))
+			goto done;
+
+		if (unlikely(table->grants[grant].status)) {
+			BTERR("invalid user buffer: could not remap it\n");
+			err |= 1;
+			table->grants[grant].handle = INVALID_GRANT_HANDLE;
+		}
+
+		request->handles[i].user = table->grants[grant].handle;
+		grant++;
+
+	done:
+		if (err)
+			continue;
+
+		page = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap))
+			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+					    FOREIGN_FRAME(foreign_mfn));
+		else if (vm_insert_page(ring->vma, uvaddr, page))
+			err |= 1;
+
+		BTDBG("pending_req: %p, seg: %d, page: %p, "
+		      "kvaddr: 0x%08lx, khandle: %u, uvaddr: 0x%08lx, "
+		      "uhandle: %u\n", request, i, page,
+		      kvaddr, request->handles[i].kernel,		       
+		      uvaddr, request->handles[i].user);
+	}
+
+	return err;
+}
+
+static int
+blktap_map(struct blktap *tap,
+	   struct blktap_request *request,
+	   unsigned int seg, struct page *page)
+{
+	pte_t pte;
+	int usr_idx;
+	struct blktap_ring *ring;
+	unsigned long uvaddr, kvaddr;
+	int err = 0;
+
+	ring    = &tap->ring;
+	usr_idx = request->usr_idx;
+	uvaddr  = MMAP_VADDR(ring->user_vstart, usr_idx, seg);
+	kvaddr  = request_to_kaddr(request, seg);
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+		pte = mk_pte(page, ring->vma->vm_page_prot);
+		blktap_map_uaddr(ring->vma, uvaddr, pte_mkwrite(pte));
+		flush_tlb_page(ring->vma, uvaddr);
+		blktap_map_uaddr(NULL, kvaddr, mk_pte(page, PAGE_KERNEL));
+		flush_tlb_kernel_page(kvaddr);
+
+		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, pte_mfn(pte));
+		request->handles[seg].kernel = INVALID_GRANT_HANDLE;
+	} else {
+		/* grant this page access to self domain and map it. */
+		domid_t domid = 0; /* XXX my domian id: grant table hypercall
+				      doesn't understand DOMID_SELF */
+		int gref;
+		uint32_t flags;
+		struct gnttab_map_grant_ref map;
+		struct page *tap_page;
+
+		gref = gnttab_grant_foreign_access(
+			domid, page_to_pfn(page),
+			(request->operation == BLKIF_OP_WRITE)?
+			GTF_readonly: 0);
+
+		flags  = GNTMAP_host_map |
+			(request->operation == BLKIF_OP_WRITE ?
+			 GNTMAP_readonly : 0);
+
+		gnttab_set_map_op(&map, kvaddr, flags, gref, domid);
+
+		/* enable chained tap devices */
+		tap_page = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+		set_page_private(tap_page, page_private(page));
+		SetPageBlkback(tap_page);
+
+		err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+						&map, 1);
+		BUG_ON(err);
+
+		err = vm_insert_page(ring->vma, uvaddr, tap_page);
+		if (err) {
+			struct gnttab_unmap_grant_ref unmap;
+			gnttab_set_unmap_op(&unmap, kvaddr,
+					    GNTMAP_host_map, gref);
+			VOID(HYPERVISOR_grant_table_op(
+				GNTTABOP_unmap_grant_ref, &unmap, 1));
+		} else
+			request->handles[seg].kernel = gref;
+	}
+	request->handles[seg].user = INVALID_GRANT_HANDLE;
+
+	BTDBG("pending_req: %p, seg: %d, page: %p, kvaddr: 0x%08lx, "
+	      "uvaddr: 0x%08lx\n", request, seg, page, kvaddr,
+	      uvaddr);
+
+	return err;
+}
+
+static int
+blktap_device_process_request(struct blktap *tap,
+			      struct blktap_request *request,
+			      struct request *req)
+{
+	struct page *page;
+	int i, usr_idx, err;
+	struct blktap_ring *ring;
+	struct scatterlist *sg;
+	struct blktap_grant_table table;
+	unsigned int fsect, lsect, nr_sects;
+	unsigned long offset, uvaddr, kvaddr;
+	struct blkif_request blkif_req, *target;
+
+	err = -1;
+	memset(&table, 0, sizeof(table));
+
+	if (!blktap_active(tap))
+		goto out;
+
+	ring    = &tap->ring;
+	usr_idx = request->usr_idx;
+	blkif_req.id = usr_idx;
+	blkif_req.sector_number = (blkif_sector_t)blk_rq_pos(req);
+	blkif_req.handle = 0;
+	blkif_req.operation = rq_data_dir(req) ?
+		BLKIF_OP_WRITE : BLKIF_OP_READ;
+	if (unlikely(blk_pc_request(req)))
+		blkif_req.operation = BLKIF_OP_PACKET;
+
+	request->id        = (unsigned long)req;
+	request->operation = blkif_req.operation;
+	request->status    = BLKTAP_REQUEST_PENDING;
+	do_gettimeofday(&request->time);
+
+	nr_sects = 0;
+	request->nr_pages = 0;
+	blkif_req.nr_segments = blk_rq_map_sg(req->q, req, tap->sg);
+	BUG_ON(blkif_req.nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	for_each_sg(tap->sg, sg, blkif_req.nr_segments, i) {
+			fsect = sg->offset >> 9;
+			lsect = fsect + (sg->length >> 9) - 1;
+			nr_sects += sg->length >> 9;
+
+			blkif_req.seg[i] =
+				(struct blkif_request_segment) {
+				.gref       = 0,
+				.first_sect = fsect,
+				.last_sect  = lsect };
+
+			if (PageBlkback(sg_page(sg))) {
+				/* foreign page -- use xen */
+				if (blktap_prep_foreign(tap,
+							request,
+							&blkif_req,
+							i,
+							sg_page(sg),
+							&table))
+					goto out;
+			} else {
+				/* do it the old fashioned way */
+				if (blktap_map(tap,
+					       request,
+					       i,
+					       sg_page(sg)))
+					goto out;
+			}
+
+			uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
+			kvaddr = request_to_kaddr(request, i);
+			offset = (uvaddr - ring->vma->vm_start) >> PAGE_SHIFT;
+			page   = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+			ring->foreign_map.map[offset] = page;
+			SetPageReserved(page);
+
+			BTDBG("mapped uaddr %08lx to page %p pfn 0x%lx\n",
+			      uvaddr, page, __pa(kvaddr) >> PAGE_SHIFT);
+			BTDBG("offset: 0x%08lx, pending_req: %p, seg: %d, "
+			      "page: %p, kvaddr: 0x%08lx, uvaddr: 0x%08lx\n",
+			      offset, request, i,
+			      page, kvaddr, uvaddr);
+
+			request->nr_pages++;
+	}
+
+	if (blktap_map_foreign(tap, request, &blkif_req, &table))
+		goto out;
+
+	/* Finally, write the request message to the user ring. */
+	target = RING_GET_REQUEST(&ring->ring, ring->ring.req_prod_pvt);
+	memcpy(target, &blkif_req, sizeof(blkif_req));
+	target->id = request->usr_idx;
+	wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
+	ring->ring.req_prod_pvt++;
+
+	if (unlikely(blk_pc_request(req)))
+		tap->stats.st_pk_req++;
+	else if (rq_data_dir(req)) {
+		tap->stats.st_wr_sect += nr_sects;
+		tap->stats.st_wr_req++;
+	} else {
+		tap->stats.st_rd_sect += nr_sects;
+		tap->stats.st_rd_req++;
+	}
+
+	err = 0;
+
+out:
+	if (err)
+		blktap_device_fast_flush(tap, request);
+	return err;
+}
+
+#ifdef ENABLE_PASSTHROUGH
+#define rq_for_each_bio_safe(_bio, _tmp, _req)				\
+	if ((_req)->bio)						\
+		for (_bio = (_req)->bio;				\
+		     _bio && ((_tmp = _bio->bi_next) || 1);		\
+		     _bio = _tmp)
+
+static void
+blktap_device_forward_request(struct blktap *tap, struct request *req)
+{
+	struct bio *bio, *tmp;
+	struct blktap_device *dev;
+
+	dev = &tap->device;
+
+	rq_for_each_bio_safe(bio, tmp, req) {
+		bio->bi_bdev = dev->bdev;
+		submit_bio(bio->bi_rw, bio);
+	}
+}
+
+static void
+blktap_device_close_bdev(struct blktap *tap)
+{
+	struct blktap_device *dev;
+
+	dev = &tap->device;
+
+	if (dev->bdev)
+		blkdev_put(dev->bdev);
+
+	dev->bdev = NULL;
+	clear_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse);
+}
+
+static int
+blktap_device_open_bdev(struct blktap *tap, u32 pdev)
+{
+	struct block_device *bdev;
+	struct blktap_device *dev;
+
+	dev = &tap->device;
+
+	bdev = open_by_devnum(pdev, FMODE_WRITE);
+	if (IS_ERR(bdev)) {
+		BTERR("opening device %x:%x failed: %ld\n",
+		      MAJOR(pdev), MINOR(pdev), PTR_ERR(bdev));
+		return PTR_ERR(bdev);
+	}
+
+	if (!bdev->bd_disk) {
+		BTERR("device %x:%x doesn't exist\n",
+		      MAJOR(pdev), MINOR(pdev));
+		blkdev_put(dev->bdev);
+		return -ENOENT;
+	}
+
+	dev->bdev = bdev;
+	set_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse);
+
+	/* TODO: readjust queue parameters */
+
+	BTINFO("set device %d to passthrough on %x:%x\n",
+	       tap->minor, MAJOR(pdev), MINOR(pdev));
+
+	return 0;
+}
+
+int
+blktap_device_enable_passthrough(struct blktap *tap,
+				 unsigned major, unsigned minor)
+{
+	u32 pdev;
+	struct blktap_device *dev;
+
+	dev  = &tap->device;
+	pdev = MKDEV(major, minor);
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return -EINVAL;
+
+	if (dev->bdev) {
+		if (pdev)
+			return -EINVAL;
+		blktap_device_close_bdev(tap);
+		return 0;
+	}
+
+	return blktap_device_open_bdev(tap, pdev);
+}
+#endif
+
+/*
+ * dev->lock held on entry
+ */
+static void
+blktap_device_run_queue(struct blktap *tap)
+{
+	int queued, err;
+	struct request_queue *rq;
+	struct request *req;
+	struct blktap_ring *ring;
+	struct blktap_device *dev;
+	struct blktap_request *request;
+
+	queued = 0;
+	ring   = &tap->ring;
+	dev    = &tap->device;
+	rq     = dev->gd->queue;
+
+	BTDBG("running queue for %d\n", tap->minor);
+
+	while ((req = blk_peek_request(rq)) != NULL) {
+		if (RING_FULL(&ring->ring)) {
+		wait:
+			/* Avoid pointless unplugs. */
+			blk_stop_queue(rq);
+			blktap_defer(tap);
+			break;
+		}
+
+		blk_start_request(req);
+
+		if (!blk_fs_request(req)) {
+			__blk_end_request_all(req, -EIO);
+			continue;
+		}
+
+		if (blk_barrier_rq(req)) {
+			__blk_end_request_all(req, -EOPNOTSUPP);
+			continue;
+		}
+
+#ifdef ENABLE_PASSTHROUGH
+		if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
+			blktap_device_forward_request(tap, req);
+			continue;
+		}
+#endif
+
+		request = blktap_request_allocate(tap);
+		if (!request) {
+			tap->stats.st_oo_req++;
+			goto wait;
+		}
+
+		BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%x) "
+		      "buffer:%p [%s], pending: %p\n", req, tap->minor,
+		      req->cmd, (unsigned long long)blk_rq_pos(req),
+		      blk_rq_cur_sectors(req), blk_rq_sectors(req), req->buffer,
+		      rq_data_dir(req) ? "write" : "read", request);
+
+		spin_unlock_irq(&dev->lock);
+		down_read(&tap->tap_sem);
+
+		err = blktap_device_process_request(tap, request, req);
+		if (!err)
+			queued++;
+		else {
+			blk_end_request_all(req, err);
+			blktap_request_free(tap, request);
+		}
+
+		up_read(&tap->tap_sem);
+		spin_lock_irq(&dev->lock);
+	}
+
+	if (queued)
+		blktap_ring_kick_user(tap);
+}
+
+/*
+ * dev->lock held on entry
+ */
+static void
+blktap_device_do_request(struct request_queue *rq)
+{
+	struct request *req;
+	struct blktap *tap;
+	struct blktap_device *dev;
+
+	dev = rq->queuedata;
+	if (!dev)
+		goto fail;
+
+	tap = dev_to_blktap(dev);
+	if (!blktap_active(tap))
+		goto fail;
+
+	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse) ||
+	    test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
+		blktap_defer(tap);
+		return;
+	}
+
+	blktap_device_run_queue(tap);
+	return;
+
+fail:
+	while ((req = blk_peek_request(rq))) {
+		BTERR("device closed: failing secs %llu - %llu\n",
+		      (unsigned long long)blk_rq_pos(req),
+		      (unsigned long long)blk_rq_pos(req)
+		      + blk_rq_cur_sectors(req));
+		blk_start_request(req);
+		__blk_end_request_all(req, -EIO);
+	}
+}
+
+void
+blktap_device_restart(struct blktap *tap)
+{
+	struct blktap_device *dev;
+
+	dev = &tap->device;
+	if (!dev->gd || !dev->gd->queue)
+		return;
+
+	if (blktap_active(tap) && RING_FULL(&tap->ring.ring)) {
+		blktap_defer(tap);
+		return;
+	}
+
+	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse) ||
+	    test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
+		blktap_defer(tap);
+		return;
+	}
+
+	spin_lock_irq(&dev->lock);
+
+	/* Re-enable calldowns. */
+	if (blk_queue_stopped(dev->gd->queue))
+		blk_start_queue(dev->gd->queue);
+
+	/* Kick things off immediately. */
+	blktap_device_do_request(dev->gd->queue);
+
+	spin_unlock_irq(&dev->lock);
+}
+
+static void
+blktap_device_configure(struct blktap *tap)
+{
+	struct request_queue *rq;
+	struct blktap_device *dev = &tap->device;
+
+	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !dev->gd)
+		return;
+
+	dev = &tap->device;
+	rq  = dev->gd->queue;
+
+	spin_lock_irq(&dev->lock);
+
+	set_capacity(dev->gd, tap->params.capacity);
+
+	/* Hard sector size and max sectors impersonate the equiv. hardware. */
+	blk_queue_logical_block_size(rq, tap->params.sector_size);
+	blk_queue_max_sectors(rq, 512);
+
+	/* Each segment in a request is up to an aligned page in size. */
+	blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
+	blk_queue_max_segment_size(rq, PAGE_SIZE);
+
+	/* Ensure a merged request will fit in a single I/O ring slot. */
+	blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+	/* Make sure buffer addresses are sector-aligned. */
+	blk_queue_dma_alignment(rq, 511);
+
+	spin_unlock_irq(&dev->lock);
+}
+
+int
+blktap_device_resume(struct blktap *tap)
+{
+	int err;
+
+	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !blktap_active(tap))
+		return -ENODEV;
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return 0;
+
+	err = blktap_ring_resume(tap);
+	if (err)
+		return err;
+
+	/* device size may have changed */
+	blktap_device_configure(tap);
+
+	BTDBG("restarting device\n");
+	blktap_device_restart(tap);
+
+	return 0;
+}
+
+int
+blktap_device_pause(struct blktap *tap)
+{
+	unsigned long flags;
+	struct blktap_device *dev = &tap->device;
+
+	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !blktap_active(tap))
+		return -ENODEV;
+
+	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return 0;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	blk_stop_queue(dev->gd->queue);
+	set_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return blktap_ring_pause(tap);
+}
+
+int
+blktap_device_destroy(struct blktap *tap)
+{
+	struct blktap_device *dev = &tap->device;
+
+	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
+		return 0;
+
+	BTINFO("destroy device %d users %d\n", tap->minor, dev->users);
+
+	if (dev->users)
+		return -EBUSY;
+
+	spin_lock_irq(&dev->lock);
+	/* No more blktap_device_do_request(). */
+	blk_stop_queue(dev->gd->queue);
+	clear_bit(BLKTAP_DEVICE, &tap->dev_inuse);
+	spin_unlock_irq(&dev->lock);
+
+#ifdef ENABLE_PASSTHROUGH
+	if (dev->bdev)
+		blktap_device_close_bdev(tap);
+#endif
+
+	del_gendisk(dev->gd);
+	put_disk(dev->gd);
+	blk_cleanup_queue(dev->gd->queue);
+
+	dev->gd = NULL;
+
+	wake_up(&tap->wq);
+
+	return 0;
+}
+
+int
+blktap_device_create(struct blktap *tap)
+{
+	int minor, err;
+	struct gendisk *gd;
+	struct request_queue *rq;
+	struct blktap_device *dev;
+
+	gd    = NULL;
+	rq    = NULL;
+	dev   = &tap->device;
+	minor = tap->minor;
+
+	if (test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
+		return -EEXIST;
+
+	if (blktap_validate_params(tap, &tap->params))
+		return -EINVAL;
+
+	BTINFO("minor %d sectors %Lu sector-size %lu\n",
+	       minor, tap->params.capacity, tap->params.sector_size);
+
+	err = -ENODEV;
+
+	gd = alloc_disk(1);
+	if (!gd)
+		goto error;
+
+	if (minor < 26)
+		sprintf(gd->disk_name, "tapdev%c", 'a' + minor);
+	else
+		sprintf(gd->disk_name, "tapdev%c%c",
+			'a' + ((minor / 26) - 1), 'a' + (minor % 26));
+
+	gd->major = blktap_device_major;
+	gd->first_minor = minor;
+	gd->fops = &blktap_device_file_operations;
+	gd->private_data = dev;
+
+	spin_lock_init(&dev->lock);
+	rq = blk_init_queue(blktap_device_do_request, &dev->lock);
+	if (!rq)
+		goto error;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+	elevator_init(rq, "noop");
+#else
+	elevator_init(rq, &elevator_noop);
+#endif
+
+	gd->queue     = rq;
+	rq->queuedata = dev;
+	dev->gd       = gd;
+
+	set_bit(BLKTAP_DEVICE, &tap->dev_inuse);
+	blktap_device_configure(tap);
+
+	add_disk(gd);
+
+	err = 0;
+	goto out;
+
+ error:
+	if (gd)
+		del_gendisk(gd);
+	if (rq)
+		blk_cleanup_queue(rq);
+
+ out:
+	BTINFO("creation of %u:%u: %d\n", blktap_device_major, tap->minor, err);
+	return err;
+}
+
+int
+blktap_device_init(int *maj)
+{
+	int major;
+
+	/* Dynamically allocate a major for this device */
+	major = register_blkdev(0, "tapdev");
+	if (major < 0) {
+		BTERR("Couldn't register blktap device\n");
+		return -ENOMEM;
+	}	
+
+	blktap_device_major = *maj = major;
+	BTINFO("blktap device major %d\n", major);
+
+	return 0;
+}
+
+void
+blktap_device_free(void)
+{
+	if (blktap_device_major)
+		unregister_blkdev(blktap_device_major, "tapdev");
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/wait_queue.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/wait_queue.c
@@ -0,0 +1,40 @@
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "blktap.h"
+
+static LIST_HEAD(deferred_work_queue);
+static DEFINE_SPINLOCK(deferred_work_lock);
+
+void
+blktap_run_deferred(void)
+{
+	LIST_HEAD(queue);
+	struct blktap *tap;
+	unsigned long flags;
+
+	spin_lock_irqsave(&deferred_work_lock, flags);
+	list_splice_init(&deferred_work_queue, &queue);
+	list_for_each_entry(tap, &queue, deferred_queue)
+		clear_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
+	spin_unlock_irqrestore(&deferred_work_lock, flags);
+
+	while (!list_empty(&queue)) {
+		tap = list_entry(queue.next, struct blktap, deferred_queue);
+		list_del_init(&tap->deferred_queue);
+		blktap_device_restart(tap);
+	}
+}
+
+void
+blktap_defer(struct blktap *tap)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&deferred_work_lock, flags);
+	if (!test_bit(BLKTAP_DEFERRED, &tap->dev_inuse)) {
+		set_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
+		list_add_tail(&tap->deferred_queue, &deferred_work_queue);
+	}
+	spin_unlock_irqrestore(&deferred_work_lock, flags);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/request.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/request.c
@@ -0,0 +1,297 @@
+#include <linux/spinlock.h>
+#include <xen/balloon.h>
+
+#include "blktap.h"
+
+#define MAX_BUCKETS                      8
+#define BUCKET_SIZE                      MAX_PENDING_REQS
+
+#define BLKTAP_POOL_CLOSING              1
+
+struct blktap_request_bucket;
+
+struct blktap_request_handle {
+	int                              slot;
+	uint8_t                          inuse;
+	struct blktap_request            request;
+	struct blktap_request_bucket    *bucket;
+};
+
+struct blktap_request_bucket {
+	atomic_t                         reqs_in_use;
+	struct blktap_request_handle     handles[BUCKET_SIZE];
+	struct page                    **foreign_pages;
+};
+
+struct blktap_request_pool {
+	spinlock_t                       lock;
+	uint8_t                          status;
+	struct list_head                 free_list;
+	atomic_t                         reqs_in_use;
+	wait_queue_head_t                wait_queue;
+	struct blktap_request_bucket    *buckets[MAX_BUCKETS];
+};
+
+static struct blktap_request_pool pool;
+
+static inline struct blktap_request_handle *
+blktap_request_to_handle(struct blktap_request *req)
+{
+	return container_of(req, struct blktap_request_handle, request);
+}
+
+static void
+blktap_request_pool_init_request(struct blktap_request *request)
+{
+	int i;
+
+	request->usr_idx  = -1;
+	request->nr_pages = 0;
+	request->status   = BLKTAP_REQUEST_FREE;
+	INIT_LIST_HEAD(&request->free_list);
+	for (i = 0; i < ARRAY_SIZE(request->handles); i++) {
+		request->handles[i].user   = INVALID_GRANT_HANDLE;
+		request->handles[i].kernel = INVALID_GRANT_HANDLE;
+	}
+}
+
+static int
+blktap_request_pool_allocate_bucket(void)
+{
+	int i, idx;
+	unsigned long flags;
+	struct blktap_request *request;
+	struct blktap_request_handle *handle;
+	struct blktap_request_bucket *bucket;
+
+	bucket = kzalloc(sizeof(struct blktap_request_bucket), GFP_KERNEL);
+	if (!bucket)
+		goto fail;
+
+	bucket->foreign_pages = alloc_empty_pages_and_pagevec(MMAP_PAGES);
+	if (!bucket->foreign_pages)
+		goto fail;
+
+	spin_lock_irqsave(&pool.lock, flags);
+
+	idx = -1;
+	for (i = 0; i < MAX_BUCKETS; i++) {
+		if (!pool.buckets[i]) {
+			idx = i;
+			pool.buckets[idx] = bucket;
+			break;
+		}
+	}
+
+	if (idx == -1) {
+		spin_unlock_irqrestore(&pool.lock, flags);
+		goto fail;
+	}
+
+	for (i = 0; i < BUCKET_SIZE; i++) {
+		handle  = bucket->handles + i;
+		request = &handle->request;
+
+		handle->slot   = i;
+		handle->inuse  = 0;
+		handle->bucket = bucket;
+
+		blktap_request_pool_init_request(request);
+		list_add_tail(&request->free_list, &pool.free_list);
+	}
+
+	spin_unlock_irqrestore(&pool.lock, flags);
+
+	return 0;
+
+fail:
+	if (bucket && bucket->foreign_pages)
+		free_empty_pages_and_pagevec(bucket->foreign_pages, MMAP_PAGES);
+	kfree(bucket);
+	return -ENOMEM;
+}
+
+static void
+blktap_request_pool_free_bucket(struct blktap_request_bucket *bucket)
+{
+	if (!bucket)
+		return;
+
+	BTDBG("freeing bucket %p\n", bucket);
+
+	free_empty_pages_and_pagevec(bucket->foreign_pages, MMAP_PAGES);
+	kfree(bucket);
+}
+
+unsigned long
+request_to_kaddr(struct blktap_request *req, int seg)
+{
+	struct blktap_request_handle *handle = blktap_request_to_handle(req);
+	int idx = handle->slot * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
+	unsigned long pfn = page_to_pfn(handle->bucket->foreign_pages[idx]);
+	return (unsigned long)pfn_to_kaddr(pfn);
+}
+
+int
+blktap_request_pool_shrink(void)
+{
+	int i, err;
+	unsigned long flags;
+	struct blktap_request_bucket *bucket;
+
+	err = -EAGAIN;
+
+	spin_lock_irqsave(&pool.lock, flags);
+
+	/* always keep at least one bucket */
+	for (i = 1; i < MAX_BUCKETS; i++) {
+		bucket = pool.buckets[i];
+		if (!bucket)
+			continue;
+
+		if (atomic_read(&bucket->reqs_in_use))
+			continue;
+
+		blktap_request_pool_free_bucket(bucket);
+		pool.buckets[i] = NULL;
+		err = 0;
+		break;
+	}
+
+	spin_unlock_irqrestore(&pool.lock, flags);
+
+	return err;
+}
+
+int
+blktap_request_pool_grow(void)
+{
+	return blktap_request_pool_allocate_bucket();
+}
+
+struct blktap_request *
+blktap_request_allocate(struct blktap *tap)
+{
+	int i;
+	uint16_t usr_idx;
+	unsigned long flags;
+	struct blktap_request *request;
+
+	usr_idx = -1;
+	request = NULL;
+
+	spin_lock_irqsave(&pool.lock, flags);
+
+	if (pool.status == BLKTAP_POOL_CLOSING)
+		goto out;
+
+	for (i = 0; i < ARRAY_SIZE(tap->pending_requests); i++)
+		if (!tap->pending_requests[i]) {
+			usr_idx = i;
+			break;
+		}
+
+	if (usr_idx == (uint16_t)-1)
+		goto out;
+
+	if (!list_empty(&pool.free_list)) {
+		request = list_entry(pool.free_list.next,
+				     struct blktap_request, free_list);
+		list_del(&request->free_list);
+	}
+
+	if (request) {
+		struct blktap_request_handle *handle;
+
+		atomic_inc(&pool.reqs_in_use);
+
+		handle = blktap_request_to_handle(request);
+		atomic_inc(&handle->bucket->reqs_in_use);
+		handle->inuse = 1;
+
+		request->usr_idx = usr_idx;
+
+		tap->pending_requests[usr_idx] = request;
+		tap->pending_cnt++;
+	}
+
+out:
+	spin_unlock_irqrestore(&pool.lock, flags);
+	return request;
+}
+
+void
+blktap_request_free(struct blktap *tap, struct blktap_request *request)
+{
+	int free;
+	unsigned long flags;
+	struct blktap_request_handle *handle;
+
+	BUG_ON(request->usr_idx >= ARRAY_SIZE(tap->pending_requests));
+	handle = blktap_request_to_handle(request);
+
+	spin_lock_irqsave(&pool.lock, flags);
+
+	handle->inuse = 0;
+	tap->pending_requests[request->usr_idx] = NULL;
+	blktap_request_pool_init_request(request);
+	list_add(&request->free_list, &pool.free_list);
+	atomic_dec(&handle->bucket->reqs_in_use);
+	free = atomic_dec_and_test(&pool.reqs_in_use);
+
+	spin_unlock_irqrestore(&pool.lock, flags);
+
+	if (--tap->pending_cnt == 0)
+		wake_up_interruptible(&tap->wq);
+
+	if (free)
+		wake_up(&pool.wait_queue);
+}
+
+void
+blktap_request_pool_free(void)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pool.lock, flags);
+
+	pool.status = BLKTAP_POOL_CLOSING;
+	while (atomic_read(&pool.reqs_in_use)) {
+		spin_unlock_irqrestore(&pool.lock, flags);
+		wait_event(pool.wait_queue, !atomic_read(&pool.reqs_in_use));
+		spin_lock_irqsave(&pool.lock, flags);
+	}
+
+	for (i = 0; i < MAX_BUCKETS; i++) {
+		blktap_request_pool_free_bucket(pool.buckets[i]);
+		pool.buckets[i] = NULL;
+	}
+
+	spin_unlock_irqrestore(&pool.lock, flags);
+}
+
+int
+blktap_request_pool_init(void)
+{
+	int i, err;
+
+	memset(&pool, 0, sizeof(pool));
+
+	spin_lock_init(&pool.lock);
+	INIT_LIST_HEAD(&pool.free_list);
+	atomic_set(&pool.reqs_in_use, 0);
+	init_waitqueue_head(&pool.wait_queue);
+
+	for (i = 0; i < 2; i++) {
+		err = blktap_request_pool_allocate_bucket();
+		if (err)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	blktap_request_pool_free();
+	return err;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap2/ring.c
+++ linux-ec2-2.6.32/drivers/xen/blktap2/ring.c
@@ -0,0 +1,612 @@
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include "blktap.h"
+
+static int blktap_ring_major;
+
+static inline struct blktap *
+vma_to_blktap(struct vm_area_struct *vma)
+{
+	struct vm_foreign_map *m = vma->vm_private_data;
+	struct blktap_ring *r = container_of(m, struct blktap_ring, foreign_map);
+	return container_of(r, struct blktap, ring);
+}
+
+ /* 
+  * BLKTAP - immediately before the mmap area,
+  * we have a bunch of pages reserved for shared memory rings.
+  */
+#define RING_PAGES 1
+
+static int
+blktap_read_ring(struct blktap *tap)
+{
+	/* This is called to read responses from the ring. */
+	int usr_idx;
+	RING_IDX rc, rp;
+	blkif_response_t res;
+	struct blktap_ring *ring;
+	struct blktap_request *request;
+
+	down_read(&tap->tap_sem);
+
+	ring = &tap->ring;
+	if (!ring->vma) {
+		up_read(&tap->tap_sem);
+		return 0;
+	}
+
+	/* for each outstanding message on the ring  */
+	rp = ring->ring.sring->rsp_prod;
+	rmb();
+
+	for (rc = ring->ring.rsp_cons; rc != rp; rc++) {
+		memcpy(&res, RING_GET_RESPONSE(&ring->ring, rc), sizeof(res));
+		mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */
+		++ring->ring.rsp_cons;
+
+		usr_idx = (int)res.id;
+		if (usr_idx >= MAX_PENDING_REQS ||
+		    !tap->pending_requests[usr_idx]) {
+			BTWARN("Request %d/%d invalid [%x], tapdisk %d%p\n",
+			       rc, rp, usr_idx, tap->pid, ring->vma);
+			continue;
+		}
+
+		request = tap->pending_requests[usr_idx];
+		BTDBG("request %p response #%d id %x\n", request, rc, usr_idx);
+		blktap_device_finish_request(tap, &res, request);
+	}
+
+	up_read(&tap->tap_sem);
+
+	blktap_run_deferred();
+
+	return 0;
+}
+
+static int
+blktap_ring_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	/*
+	 * if the page has not been mapped in by the driver then return
+	 * VM_FAULT_SIGBUS to the domain.
+	 */
+
+	return VM_FAULT_SIGBUS;
+}
+
+static pte_t
+blktap_ring_clear_pte(struct vm_area_struct *vma,
+		      unsigned long uvaddr,
+		      pte_t *ptep, int is_fullmm)
+{
+	pte_t copy;
+	struct blktap *tap;
+	unsigned long kvaddr;
+	struct page **map, *page;
+	struct blktap_ring *ring;
+	struct blktap_request *request;
+	struct grant_handle_pair *khandle;
+	struct gnttab_unmap_grant_ref unmap[2];
+	int offset, seg, usr_idx, count = 0;
+
+	tap  = vma_to_blktap(vma);
+	ring = &tap->ring;
+	map  = ring->foreign_map.map;
+	BUG_ON(!map);	/* TODO Should this be changed to if statement? */
+
+	/*
+	 * Zap entry if the address is before the start of the grant
+	 * mapped region.
+	 */
+	if (uvaddr < ring->user_vstart)
+		return xen_ptep_get_and_clear_full(vma, uvaddr,
+						   ptep, is_fullmm);
+
+	offset  = (int)((uvaddr - ring->user_vstart) >> PAGE_SHIFT);
+	usr_idx = offset / BLKIF_MAX_SEGMENTS_PER_REQUEST;
+	seg     = offset % BLKIF_MAX_SEGMENTS_PER_REQUEST;
+
+	offset  = (int)((uvaddr - vma->vm_start) >> PAGE_SHIFT);
+	page    = map[offset];
+	if (page) {
+		ClearPageReserved(page);
+		if (PageBlkback(page)) {
+			ClearPageBlkback(page);
+			set_page_private(page, 0);
+		}
+	}
+	map[offset] = NULL;
+
+	request = tap->pending_requests[usr_idx];
+	kvaddr  = request_to_kaddr(request, seg);
+	khandle = request->handles + seg;
+
+	if (khandle->kernel != INVALID_GRANT_HANDLE) {
+		gnttab_set_unmap_op(&unmap[count], kvaddr, 
+				    GNTMAP_host_map, khandle->kernel);
+		count++;
+
+		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, 
+				    INVALID_P2M_ENTRY);
+	}
+
+
+	if (khandle->user != INVALID_GRANT_HANDLE) {
+		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+
+		copy = *ptep;
+		gnttab_set_unmap_op(&unmap[count], virt_to_machine(ptep), 
+				    GNTMAP_host_map 
+				    | GNTMAP_application_map 
+				    | GNTMAP_contains_pte,
+				    khandle->user);
+		count++;
+	} else
+		copy = xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
+						   is_fullmm);
+
+	if (count)
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+					      unmap, count))
+			BUG();
+
+	khandle->kernel = INVALID_GRANT_HANDLE;
+	khandle->user   = INVALID_GRANT_HANDLE;
+
+	return copy;
+}
+
+static void
+blktap_ring_vm_unmap(struct vm_area_struct *vma)
+{
+	struct blktap *tap = vma_to_blktap(vma);
+
+	down_write(&tap->tap_sem);
+	clear_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
+	clear_bit(BLKTAP_PAUSED, &tap->dev_inuse);
+	clear_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
+	up_write(&tap->tap_sem);
+}
+
+static void
+blktap_ring_vm_close(struct vm_area_struct *vma)
+{
+	struct blktap *tap = vma_to_blktap(vma);
+	struct blktap_ring *ring = &tap->ring;
+
+	blktap_ring_vm_unmap(vma);                 /* fail future requests */
+	blktap_device_fail_pending_requests(tap);  /* fail pending requests */
+	blktap_device_restart(tap);                /* fail deferred requests */
+
+	down_write(&tap->tap_sem);
+
+	zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
+
+	kfree(ring->foreign_map.map);
+	ring->foreign_map.map = NULL;
+
+	/* Free the ring page. */
+	ClearPageReserved(virt_to_page(ring->ring.sring));
+	free_page((unsigned long)ring->ring.sring);
+
+	BTINFO("unmapping ring %d\n", tap->minor);
+	ring->ring.sring = NULL;
+	ring->vma = NULL;
+
+	up_write(&tap->tap_sem);
+
+	wake_up(&tap->wq);
+}
+
+static struct vm_operations_struct blktap_ring_vm_operations = {
+	.close    = blktap_ring_vm_close,
+	.unmap    = blktap_ring_vm_unmap,
+	.fault    = blktap_ring_fault,
+	.zap_pte  = blktap_ring_clear_pte,
+};
+
+static int
+blktap_ring_open(struct inode *inode, struct file *filp)
+{
+	int idx;
+	struct blktap *tap;
+
+	idx = iminor(inode);
+	if (idx < 0 || idx > MAX_BLKTAP_DEVICE || blktaps[idx] == NULL) {
+		BTERR("unable to open device blktap%d\n", idx);
+		return -ENODEV;
+	}
+
+	tap = blktaps[idx];
+
+	BTINFO("opening device blktap%d\n", idx);
+
+	if (!test_bit(BLKTAP_CONTROL, &tap->dev_inuse))
+		return -ENODEV;
+
+	/* Only one process can access ring at a time */
+	if (test_and_set_bit(BLKTAP_RING_FD, &tap->dev_inuse))
+		return -EBUSY;
+
+	filp->private_data = tap;
+	BTINFO("opened device %d\n", tap->minor);
+
+	return 0;
+}
+
+static int
+blktap_ring_release(struct inode *inode, struct file *filp)
+{
+	struct blktap *tap = filp->private_data;
+
+	BTINFO("freeing device %d\n", tap->minor);
+	clear_bit(BLKTAP_RING_FD, &tap->dev_inuse);
+	filp->private_data = NULL;
+	wake_up(&tap->wq);	
+	return 0;
+}
+
+/* Note on mmap:
+ * We need to map pages to user space in a way that will allow the block
+ * subsystem set up direct IO to them.  This couldn't be done before, because
+ * there isn't really a sane way to translate a user virtual address down to a 
+ * physical address when the page belongs to another domain.
+ *
+ * My first approach was to map the page in to kernel memory, add an entry
+ * for it in the physical frame list (using alloc_lomem_region as in blkback)
+ * and then attempt to map that page up to user space.  This is disallowed
+ * by xen though, which realizes that we don't really own the machine frame
+ * underlying the physical page.
+ *
+ * The new approach is to provide explicit support for this in xen linux.
+ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
+ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
+ * from pages to actual page structs.  There is a new clause in get_user_pages
+ * that does the right thing for this sort of mapping.
+ */
+static int
+blktap_ring_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int size, err;
+	struct page **map;
+	struct blktap *tap;
+	blkif_sring_t *sring;
+	struct blktap_ring *ring;
+
+	tap   = filp->private_data;
+	ring  = &tap->ring;
+	map   = NULL;
+	sring = NULL;
+
+	if (!tap || test_and_set_bit(BLKTAP_RING_VMA, &tap->dev_inuse))
+		return -ENOMEM;
+
+	size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	if (size != (MMAP_PAGES + RING_PAGES)) {
+		BTERR("you _must_ map exactly %lu pages!\n",
+		      MMAP_PAGES + RING_PAGES);
+		return -EAGAIN;
+	}
+
+	/* Allocate the fe ring. */
+	sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+	if (!sring) {
+		BTERR("Couldn't alloc sring.\n");
+		goto fail_mem;
+	}
+
+	map = kzalloc(size * sizeof(struct page *), GFP_KERNEL);
+	if (!map) {
+		BTERR("Couldn't alloc VM_FOREIGN map.\n");
+		goto fail_mem;
+	}
+
+	SetPageReserved(virt_to_page(sring));
+    
+	SHARED_RING_INIT(sring);
+	FRONT_RING_INIT(&ring->ring, sring, PAGE_SIZE);
+
+	ring->ring_vstart = vma->vm_start;
+	ring->user_vstart = ring->ring_vstart + (RING_PAGES << PAGE_SHIFT);
+
+	/* Map the ring pages to the start of the region and reserve it. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		err = vm_insert_page(vma, vma->vm_start,
+				     virt_to_page(ring->ring.sring));
+	else
+		err = remap_pfn_range(vma, vma->vm_start,
+				      __pa(ring->ring.sring) >> PAGE_SHIFT,
+				      PAGE_SIZE, vma->vm_page_prot);
+	if (err) {
+		BTERR("Mapping user ring failed: %d\n", err);
+		goto fail;
+	}
+
+	/* Mark this VM as containing foreign pages, and set up mappings. */
+	ring->foreign_map.map = map;
+	vma->vm_private_data = &ring->foreign_map;
+	vma->vm_flags |= VM_FOREIGN;
+	vma->vm_flags |= VM_DONTCOPY;
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_ops = &blktap_ring_vm_operations;
+
+#ifdef CONFIG_X86
+	vma->vm_mm->context.has_foreign_mappings = 1;
+#endif
+
+	tap->pid = current->pid;
+	BTINFO("blktap: mapping pid is %d\n", tap->pid);
+
+	ring->vma = vma;
+	return 0;
+
+ fail:
+	/* Clear any active mappings. */
+	zap_page_range(vma, vma->vm_start, 
+		       vma->vm_end - vma->vm_start, NULL);
+	ClearPageReserved(virt_to_page(sring));
+ fail_mem:
+	free_page((unsigned long)sring);
+	kfree(map);
+
+	return -ENOMEM;
+}
+
+static inline void
+blktap_ring_set_message(struct blktap *tap, int msg)
+{
+	struct blktap_ring *ring = &tap->ring;
+
+	down_read(&tap->tap_sem);
+	if (ring->ring.sring)
+		ring->ring.sring->pad[0] = msg;
+	up_read(&tap->tap_sem);
+}
+
+static int
+blktap_ring_ioctl(struct inode *inode, struct file *filp,
+		  unsigned int cmd, unsigned long arg)
+{
+	struct blktap_params params;
+	struct blktap *tap = filp->private_data;
+
+	BTDBG("%d: cmd: %u, arg: %lu\n", tap->minor, cmd, arg);
+
+	switch(cmd) {
+	case BLKTAP2_IOCTL_KICK_FE:
+		/* There are fe messages to process. */
+		return blktap_read_ring(tap);
+
+	case BLKTAP2_IOCTL_CREATE_DEVICE:
+		if (!arg)
+			return -EINVAL;
+
+		if (copy_from_user(&params, (struct blktap_params __user *)arg,
+				   sizeof(params))) {
+			BTERR("failed to get params\n");
+			return -EFAULT;
+		}
+
+		if (blktap_validate_params(tap, &params)) {
+			BTERR("invalid params\n");
+			return -EINVAL;
+		}
+
+		tap->params = params;
+		return blktap_device_create(tap);
+
+	case BLKTAP2_IOCTL_SET_PARAMS:
+		if (!arg)
+			return -EINVAL;
+
+		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+			return -EINVAL;
+
+		if (copy_from_user(&params, (struct blktap_params __user *)arg,
+				   sizeof(params))) {
+			BTERR("failed to get params\n");
+			return -EFAULT;
+		}
+
+		if (blktap_validate_params(tap, &params)) {
+			BTERR("invalid params\n");
+			return -EINVAL;
+		}
+
+		tap->params = params;
+		return 0;
+
+	case BLKTAP2_IOCTL_PAUSE:
+		if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse))
+			return -EINVAL;
+
+		set_bit(BLKTAP_PAUSED, &tap->dev_inuse);
+		clear_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
+
+		blktap_ring_set_message(tap, 0);
+		wake_up_interruptible(&tap->wq);
+
+		return 0;
+
+
+	case BLKTAP2_IOCTL_REOPEN:
+		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+			return -EINVAL;
+
+		if (!arg)
+			return -EINVAL;
+
+		if (copy_to_user((char __user *)arg,
+				 tap->params.name,
+				 strlen(tap->params.name) + 1))
+			return -EFAULT;
+
+		blktap_ring_set_message(tap, 0);
+		wake_up_interruptible(&tap->wq);
+
+		return 0;
+
+	case BLKTAP2_IOCTL_RESUME:
+		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+			return -EINVAL;
+
+		tap->ring.response = (int)arg;
+		if (!tap->ring.response)
+			clear_bit(BLKTAP_PAUSED, &tap->dev_inuse);
+
+		blktap_ring_set_message(tap, 0);
+		wake_up_interruptible(&tap->wq);
+
+		return 0;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static unsigned int blktap_ring_poll(struct file *filp, poll_table *wait)
+{
+	struct blktap *tap = filp->private_data;
+	struct blktap_ring *ring = &tap->ring;
+
+	poll_wait(filp, &ring->poll_wait, wait);
+	if (ring->ring.sring->pad[0] != 0 ||
+	    ring->ring.req_prod_pvt != ring->ring.sring->req_prod) {
+		RING_PUSH_REQUESTS(&ring->ring);
+		return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
+static struct file_operations blktap_ring_file_operations = {
+	.owner    = THIS_MODULE,
+	.open     = blktap_ring_open,
+	.release  = blktap_ring_release,
+	.ioctl    = blktap_ring_ioctl,
+	.mmap     = blktap_ring_mmap,
+	.poll     = blktap_ring_poll,
+};
+
+void
+blktap_ring_kick_user(struct blktap *tap)
+{
+	wake_up_interruptible(&tap->ring.poll_wait);
+}
+
+int
+blktap_ring_resume(struct blktap *tap)
+{
+	int err;
+	struct blktap_ring *ring = &tap->ring;
+
+	if (!blktap_active(tap))
+		return -ENODEV;
+
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return -EINVAL;
+
+	/* set shared flag for resume */
+	ring->response = 0;
+
+	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_RESUME);
+	blktap_ring_kick_user(tap);
+
+	wait_event_interruptible(tap->wq, ring->response ||
+				 !test_bit(BLKTAP_PAUSED, &tap->dev_inuse));
+
+	err = ring->response;
+	ring->response = 0;
+
+	BTDBG("err: %d\n", err);
+
+	if (err)
+		return err;
+
+	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return -EAGAIN;
+
+	return 0;
+}
+
+int
+blktap_ring_pause(struct blktap *tap)
+{
+	if (!blktap_active(tap))
+		return -ENODEV;
+
+	if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse))
+		return -EINVAL;
+
+	BTDBG("draining queue\n");
+	wait_event_interruptible(tap->wq, !tap->pending_cnt);
+	if (tap->pending_cnt)
+		return -EAGAIN;
+
+	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_PAUSE);
+	blktap_ring_kick_user(tap);
+
+	BTDBG("waiting for tapdisk response\n");
+	wait_event_interruptible(tap->wq, test_bit(BLKTAP_PAUSED, &tap->dev_inuse));
+	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
+		return -EAGAIN;
+
+	return 0;
+}
+
+int
+blktap_ring_destroy(struct blktap *tap)
+{
+	if (!test_bit(BLKTAP_RING_FD, &tap->dev_inuse) &&
+	    !test_bit(BLKTAP_RING_VMA, &tap->dev_inuse))
+		return 0;
+
+	BTDBG("sending tapdisk close message\n");
+	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_CLOSE);
+	blktap_ring_kick_user(tap);
+
+	return -EAGAIN;
+}
+
+static void
+blktap_ring_initialize(struct blktap_ring *ring, int minor)
+{
+	memset(ring, 0, sizeof(*ring));
+	init_waitqueue_head(&ring->poll_wait);
+	ring->devno = MKDEV(blktap_ring_major, minor);
+}
+
+int
+blktap_ring_create(struct blktap *tap)
+{
+	struct blktap_ring *ring = &tap->ring;
+	blktap_ring_initialize(ring, tap->minor);
+	return blktap_sysfs_create(tap);
+}
+
+int
+blktap_ring_init(int *major)
+{
+	int err;
+
+	err = register_chrdev(0, "blktap2", &blktap_ring_file_operations);
+	if (err < 0) {
+		BTERR("error registering blktap ring device: %d\n", err);
+		return err;
+	}
+
+	blktap_ring_major = *major = err;
+	BTINFO("blktap ring major: %d\n", blktap_ring_major);
+	return 0;
+}
+
+int
+blktap_ring_free(void)
+{
+	if (blktap_ring_major)
+		unregister_chrdev(blktap_ring_major, "blktap2");
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/evtchn/Makefile
+++ linux-ec2-2.6.32/drivers/xen/evtchn/Makefile
@@ -0,0 +1,2 @@
+
+obj-y	:= evtchn.o
--- linux-ec2-2.6.32.orig/drivers/xen/evtchn/evtchn.c
+++ linux-ec2-2.6.32/drivers/xen/evtchn/evtchn.c
@@ -0,0 +1,563 @@
+/******************************************************************************
+ * evtchn.c
+ * 
+ * Driver for receiving and demuxing event-channel signals.
+ * 
+ * Copyright (c) 2004-2005, K A Fraser
+ * Multi-process extensions Copyright (c) 2004, Steven Smith
+ * 
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/major.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/poll.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <xen/evtchn.h>
+#include <xen/public/evtchn.h>
+
+struct per_user_data {
+	/* Notification ring, accessed via /dev/xen/evtchn. */
+#define EVTCHN_RING_SIZE     (PAGE_SIZE / sizeof(evtchn_port_t))
+#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+	evtchn_port_t *ring;
+	unsigned int ring_cons, ring_prod, ring_overflow;
+	struct mutex ring_cons_mutex; /* protect against concurrent readers */
+
+	/* Processes wait on this queue when ring is empty. */
+	wait_queue_head_t evtchn_wait;
+	struct fasync_struct *evtchn_async_queue;
+
+	int bind_cpu;
+	int nr_event_wrong_delivery;
+};
+
+/* Who's bound to each port? */
+static struct per_user_data *port_user[NR_EVENT_CHANNELS];
+static spinlock_t port_user_lock;
+
+void evtchn_device_upcall(int port)
+{
+	struct per_user_data *u;
+
+	spin_lock(&port_user_lock);
+
+	mask_evtchn(port);
+	clear_evtchn(port);
+
+	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,
+					    SIGIO, POLL_IN);
+			}
+		} else {
+			u->ring_overflow = 1;
+		}
+	}
+
+	spin_unlock(&port_user_lock);
+}
+
+static void evtchn_check_wrong_delivery(struct per_user_data *u)
+{
+	evtchn_port_t port;
+	unsigned int current_cpu = smp_processor_id();
+
+	/* Delivered to correct CPU? All is good. */
+	if (u->bind_cpu == current_cpu) {
+		u->nr_event_wrong_delivery = 0;
+		return;
+	}
+
+	/* Tolerate up to 100 consecutive misdeliveries. */
+	if (++u->nr_event_wrong_delivery < 100)
+		return;
+
+	spin_lock_irq(&port_user_lock);
+
+	for (port = 0; port < NR_EVENT_CHANNELS; port++)
+		if (port_user[port] == u)
+			rebind_evtchn_to_cpu(port, current_cpu);
+
+	u->bind_cpu = current_cpu;
+	u->nr_event_wrong_delivery = 0;
+
+	spin_unlock_irq(&port_user_lock);
+}
+
+static ssize_t evtchn_read(struct file *file, char __user *buf,
+			   size_t count, loff_t *ppos)
+{
+	int rc;
+	unsigned int c, p, bytes1 = 0, bytes2 = 0;
+	struct per_user_data *u = file->private_data;
+
+	/* Whole number of ports. */
+	count &= ~(sizeof(evtchn_port_t)-1);
+
+	if (count == 0)
+		return 0;
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+
+	for (;;) {
+		mutex_lock(&u->ring_cons_mutex);
+
+		rc = -EFBIG;
+		if (u->ring_overflow)
+			goto unlock_out;
+
+		if ((c = u->ring_cons) != (p = u->ring_prod))
+			break;
+
+		mutex_unlock(&u->ring_cons_mutex);
+
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		rc = wait_event_interruptible(
+			u->evtchn_wait, u->ring_cons != u->ring_prod);
+		if (rc)
+			return rc;
+	}
+
+	/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+	if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
+		bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
+			sizeof(evtchn_port_t);
+		bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
+	} else {
+		bytes1 = (p - c) * sizeof(evtchn_port_t);
+		bytes2 = 0;
+	}
+
+	/* Truncate chunks according to caller's maximum byte count. */
+	if (bytes1 > count) {
+		bytes1 = count;
+		bytes2 = 0;
+	} else if ((bytes1 + bytes2) > count) {
+		bytes2 = count - bytes1;
+	}
+
+	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)))
+		goto unlock_out;
+	
+	evtchn_check_wrong_delivery(u);
+
+	u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
+	rc = bytes1 + bytes2;
+
+ unlock_out:
+	mutex_unlock(&u->ring_cons_mutex);
+	return rc;
+}
+
+static ssize_t evtchn_write(struct file *file, const char __user *buf,
+			    size_t count, loff_t *ppos)
+{
+	int rc, i;
+	evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
+	struct per_user_data *u = file->private_data;
+
+	if (kbuf == NULL)
+		return -ENOMEM;
+
+	/* Whole number of ports. */
+	count &= ~(sizeof(evtchn_port_t)-1);
+
+	rc = 0;
+	if (count == 0)
+		goto out;
+
+	if (count > PAGE_SIZE)
+		count = PAGE_SIZE;
+
+	rc = -EFAULT;
+	if (copy_from_user(kbuf, buf, count) != 0)
+		goto out;
+
+	spin_lock_irq(&port_user_lock);
+	for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
+		if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
+			unmask_evtchn(kbuf[i]);
+	spin_unlock_irq(&port_user_lock);
+
+	rc = count;
+
+ out:
+	free_page((unsigned long)kbuf);
+	return rc;
+}
+
+static unsigned int next_bind_cpu(cpumask_t map)
+{
+	static unsigned int bind_cpu;
+	bind_cpu = next_cpu(bind_cpu, map);
+	if (bind_cpu >= NR_CPUS)
+		bind_cpu = first_cpu(map);
+	return bind_cpu;
+}
+
+static void evtchn_bind_to_user(struct per_user_data *u, int port)
+{
+	spin_lock_irq(&port_user_lock);
+
+	BUG_ON(port_user[port] != NULL);
+	port_user[port] = u;
+
+	if (u->bind_cpu == -1)
+		u->bind_cpu = next_bind_cpu(cpu_online_map);
+
+	rebind_evtchn_to_cpu(port, u->bind_cpu);
+
+	unmask_evtchn(port);
+
+	spin_unlock_irq(&port_user_lock);
+}
+
+static long evtchn_ioctl(struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int rc;
+	struct per_user_data *u = file->private_data;
+	void __user *uarg = (void __user *) arg;
+
+	switch (cmd) {
+	case IOCTL_EVTCHN_BIND_VIRQ: {
+		struct ioctl_evtchn_bind_virq bind;
+		struct evtchn_bind_virq bind_virq;
+
+		rc = -EFAULT;
+		if (copy_from_user(&bind, uarg, sizeof(bind)))
+			break;
+
+		bind_virq.virq = bind.virq;
+		bind_virq.vcpu = 0;
+		rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+						 &bind_virq);
+		if (rc != 0)
+			break;
+
+		rc = bind_virq.port;
+		evtchn_bind_to_user(u, rc);
+		break;
+	}
+
+	case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
+		struct ioctl_evtchn_bind_interdomain bind;
+		struct evtchn_bind_interdomain bind_interdomain;
+
+		rc = -EFAULT;
+		if (copy_from_user(&bind, uarg, sizeof(bind)))
+			break;
+
+		bind_interdomain.remote_dom  = bind.remote_domain;
+		bind_interdomain.remote_port = bind.remote_port;
+		rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+						 &bind_interdomain);
+		if (rc != 0)
+			break;
+
+		rc = bind_interdomain.local_port;
+		evtchn_bind_to_user(u, rc);
+		break;
+	}
+
+	case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
+		struct ioctl_evtchn_bind_unbound_port bind;
+		struct evtchn_alloc_unbound alloc_unbound;
+
+		rc = -EFAULT;
+		if (copy_from_user(&bind, uarg, sizeof(bind)))
+			break;
+
+		alloc_unbound.dom        = DOMID_SELF;
+		alloc_unbound.remote_dom = bind.remote_domain;
+		rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+						 &alloc_unbound);
+		if (rc != 0)
+			break;
+
+		rc = alloc_unbound.port;
+		evtchn_bind_to_user(u, rc);
+		break;
+	}
+
+	case IOCTL_EVTCHN_UNBIND: {
+		struct ioctl_evtchn_unbind unbind;
+		struct evtchn_close close;
+		int ret;
+
+		rc = -EFAULT;
+		if (copy_from_user(&unbind, uarg, sizeof(unbind)))
+			break;
+
+		rc = -EINVAL;
+		if (unbind.port >= NR_EVENT_CHANNELS)
+			break;
+
+		spin_lock_irq(&port_user_lock);
+    
+		rc = -ENOTCONN;
+		if (port_user[unbind.port] != u) {
+			spin_unlock_irq(&port_user_lock);
+			break;
+		}
+
+		port_user[unbind.port] = NULL;
+		mask_evtchn(unbind.port);
+		rebind_evtchn_to_cpu(unbind.port, 0);
+
+		spin_unlock_irq(&port_user_lock);
+
+		close.port = unbind.port;
+		ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+		BUG_ON(ret);
+
+		rc = 0;
+		break;
+	}
+
+	case IOCTL_EVTCHN_NOTIFY: {
+		struct ioctl_evtchn_notify notify;
+
+		rc = -EFAULT;
+		if (copy_from_user(&notify, uarg, sizeof(notify)))
+			break;
+
+		if (notify.port >= NR_EVENT_CHANNELS) {
+			rc = -EINVAL;
+		} else if (port_user[notify.port] != u) {
+			rc = -ENOTCONN;
+		} else {
+			notify_remote_via_evtchn(notify.port);
+			rc = 0;
+		}
+		break;
+	}
+
+	case IOCTL_EVTCHN_RESET: {
+		/* Initialise the ring to empty. Clear errors. */
+		mutex_lock(&u->ring_cons_mutex);
+		spin_lock_irq(&port_user_lock);
+		u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+		spin_unlock_irq(&port_user_lock);
+		mutex_unlock(&u->ring_cons_mutex);
+		rc = 0;
+		break;
+	}
+
+	default:
+		rc = -ENOSYS;
+		break;
+	}
+
+	return rc;
+}
+
+static unsigned int evtchn_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask = POLLOUT | POLLWRNORM;
+	struct per_user_data *u = file->private_data;
+
+	poll_wait(file, &u->evtchn_wait, wait);
+	if (u->ring_cons != u->ring_prod)
+		mask |= POLLIN | POLLRDNORM;
+	if (u->ring_overflow)
+		mask = POLLERR;
+	return mask;
+}
+
+static int evtchn_fasync(int fd, struct file *filp, int on)
+{
+	struct per_user_data *u = filp->private_data;
+	return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+}
+
+static int evtchn_open(struct inode *inode, struct file *filp)
+{
+	struct per_user_data *u;
+
+	if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	memset(u, 0, sizeof(*u));
+	init_waitqueue_head(&u->evtchn_wait);
+
+	u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
+	if (u->ring == NULL) {
+		kfree(u);
+		return -ENOMEM;
+	}
+
+	mutex_init(&u->ring_cons_mutex);
+
+	filp->private_data = u;
+
+	u->bind_cpu = -1;
+
+	return 0;
+}
+
+static int evtchn_release(struct inode *inode, struct file *filp)
+{
+	int i;
+	struct per_user_data *u = filp->private_data;
+	struct evtchn_close close;
+
+	spin_lock_irq(&port_user_lock);
+
+	free_page((unsigned long)u->ring);
+
+	for (i = 0; i < NR_EVENT_CHANNELS; i++) {
+		int ret;
+		if (port_user[i] != u)
+			continue;
+
+		port_user[i] = NULL;
+		mask_evtchn(i);
+		rebind_evtchn_to_cpu(i, 0);
+
+		close.port = i;
+		ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+		BUG_ON(ret);
+	}
+
+	spin_unlock_irq(&port_user_lock);
+
+	kfree(u);
+
+	return 0;
+}
+
+static const struct file_operations evtchn_fops = {
+	.owner   = THIS_MODULE,
+	.read    = evtchn_read,
+	.write   = evtchn_write,
+	.unlocked_ioctl = evtchn_ioctl,
+	.poll    = evtchn_poll,
+	.fasync  = evtchn_fasync,
+	.open    = evtchn_open,
+	.release = evtchn_release,
+};
+
+static struct miscdevice evtchn_miscdev = {
+	.minor        = MISC_DYNAMIC_MINOR,
+	.name         = "evtchn",
+	.fops         = &evtchn_fops,
+};
+
+static int __cpuinit evtchn_cpu_notify(struct notifier_block *nfb,
+			unsigned long action, void *hcpu)
+{
+	int hotcpu = (unsigned long)hcpu;
+	cpumask_t map = cpu_online_map;
+	int i, j, newcpu;
+	struct per_user_data *u;
+
+	switch (action) {
+	case CPU_DOWN_PREPARE:
+		cpu_clear(hotcpu, map);
+		spin_lock_irq(&port_user_lock);
+		for (i = 0; i < NR_EVENT_CHANNELS; i++) {
+			u = port_user[i];
+			if ((u == NULL) || (u->bind_cpu != hotcpu))
+				continue;
+			newcpu = next_bind_cpu(map);
+			for (j = i; j < NR_EVENT_CHANNELS; j++)
+				if (port_user[j] == u)
+					rebind_evtchn_to_cpu(j, newcpu);
+			u->bind_cpu = newcpu;
+		}
+		spin_unlock_irq(&port_user_lock);
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata evtchn_cpu_nfb = {
+	.notifier_call = evtchn_cpu_notify
+};
+
+static int __init evtchn_init(void)
+{
+	int err;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	spin_lock_init(&port_user_lock);
+	memset(port_user, 0, sizeof(port_user));
+
+	/* Create '/dev/misc/evtchn'. */
+	err = misc_register(&evtchn_miscdev);
+	if (err != 0) {
+		printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+		return err;
+	}
+
+	register_cpu_notifier(&evtchn_cpu_nfb);
+
+	printk("Event-channel device installed.\n");
+
+	return 0;
+}
+module_init(evtchn_init);
+
+#ifdef CONFIG_MODULE
+static void __exit evtchn_cleanup(void)
+{
+	misc_deregister(&evtchn_miscdev);
+	unregister_cpu_notifier(&evtchn_cpu_nfb);
+}
+module_exit(evtchn_cleanup);
+#endif
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/console/Makefile
+++ linux-ec2-2.6.32/drivers/xen/console/Makefile
@@ -0,0 +1,2 @@
+
+obj-y	:= console.o xencons_ring.o
--- linux-ec2-2.6.32.orig/drivers/xen/console/console.c
+++ linux-ec2-2.6.32/drivers/xen/console/console.c
@@ -0,0 +1,755 @@
+/******************************************************************************
+ * console.c
+ * 
+ * Virtual console driver.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser.
+ * 
+ * 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 <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/screen_info.h>
+#include <linux/vt.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/event_channel.h>
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/xenbus.h>
+#include <xen/xencons.h>
+
+/*
+ * Modes:
+ *  'xencons=off'  [XC_OFF]:     Console is disabled.
+ *  'xencons=tty'  [XC_TTY]:     Console attached to '/dev/tty[0-9]+'.
+ *  'xencons=ttyS' [XC_SERIAL]:  Console attached to '/dev/ttyS[0-9]+'.
+ *  'xencons=xvc'  [XC_XVC]:     Console attached to '/dev/xvc0'.
+ *  'xencons=hvc'  [XC_HVC]:     Console attached to '/dev/hvc0'.
+ *  default:                     XC_XVC
+ * 
+ * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
+ * warnings from standard distro startup scripts.
+ */
+static enum {
+	XC_OFF, XC_TTY, XC_SERIAL, XC_XVC, XC_HVC
+} xc_mode;
+static int xc_num = -1;
+
+/* /dev/xvc0 device number allocated by lanana.org. */
+#define XEN_XVC_MAJOR 204
+#define XEN_XVC_MINOR 191
+
+/* /dev/hvc0 device number */
+#define XEN_HVC_MAJOR 229
+#define XEN_HVC_MINOR 0
+
+void xencons_early_setup(void)
+{
+    if (is_initial_xendomain()) {
+        xc_mode = XC_SERIAL;
+    } else {
+        xc_mode = XC_TTY;
+        console_use_vt = 0;
+    }
+}
+
+static int __init xencons_setup(char *str)
+{
+	char *q;
+	int n;
+
+	console_use_vt = 1;
+	if (!strncmp(str, "ttyS", 4)) {
+		xc_mode = XC_SERIAL;
+		str += 4;
+	} else if (!strncmp(str, "tty", 3)) {
+		xc_mode = XC_TTY;
+		str += 3;
+		console_use_vt = 0;
+	} else if (!strncmp(str, "xvc", 3)) {
+		xc_mode = XC_XVC;
+		str += 3;
+	} else if (!strncmp(str, "hvc", 3)) {
+		xc_mode = XC_HVC;
+		str += 3;
+	} else if (!strncmp(str, "off", 3)) {
+		xc_mode = XC_OFF;
+		str += 3;
+	}
+
+	n = simple_strtol(str, &q, 10);
+	if (q != str)
+		xc_num = n;
+
+	return 1;
+}
+__setup("xencons=", xencons_setup);
+
+/* The kernel and user-land drivers share a common transmit buffer. */
+static unsigned int wbuf_size = 4096;
+#define WBUF_MASK(_i) ((_i)&(wbuf_size-1))
+static char *wbuf;
+static unsigned int wc, wp; /* write_cons, write_prod */
+
+static int __init xencons_bufsz_setup(char *str)
+{
+	unsigned int goal;
+	goal = simple_strtoul(str, NULL, 0);
+	if (goal) {
+		goal = roundup_pow_of_two(goal);
+		if (wbuf_size < goal)
+			wbuf_size = goal;
+	}
+	return 1;
+}
+__setup("xencons_bufsz=", xencons_bufsz_setup);
+
+/* This lock protects accesses to the common transmit buffer. */
+static DEFINE_SPINLOCK(xencons_lock);
+
+/* Common transmit-kick routine. */
+static void __xencons_tx_flush(void);
+
+static struct tty_driver *xencons_driver;
+
+/******************** Kernel console driver ********************************/
+
+static void kcons_write(struct console *c, const char *s, unsigned int count)
+{
+	int           i = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+
+	while (i < count) {
+		for (; i < count; i++) {
+			if ((wp - wc) >= (wbuf_size - 1))
+				break;
+			if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n')
+				wbuf[WBUF_MASK(wp++)] = '\r';
+		}
+
+		__xencons_tx_flush();
+	}
+
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void kcons_write_dom0(struct console *c, const char *s, unsigned int count)
+{
+
+	while (count > 0) {
+		int rc;
+		rc = HYPERVISOR_console_io( CONSOLEIO_write, count, (char *)s);
+		if (rc <= 0)
+			break;
+		count -= rc;
+		s += rc;
+	}
+}
+
+static struct tty_driver *kcons_device(struct console *c, int *index)
+{
+	*index = 0;
+	return xencons_driver;
+}
+
+static struct console kcons_info = {
+	.device	= kcons_device,
+	.flags	= CON_PRINTBUFFER | CON_ENABLED,
+	.index	= -1,
+};
+
+static int __init xen_console_init(void)
+{
+	if (!is_running_on_xen())
+		goto out;
+
+	if (is_initial_xendomain()) {
+		kcons_info.write = kcons_write_dom0;
+	} else {
+		if (!xen_start_info->console.domU.evtchn)
+			goto out;
+		kcons_info.write = kcons_write;
+	}
+
+	switch (xc_mode) {
+	case XC_XVC:
+		strcpy(kcons_info.name, "xvc");
+		if (xc_num == -1)
+			xc_num = 0;
+		break;
+
+	case XC_HVC:
+		strcpy(kcons_info.name, "hvc");
+		if (xc_num == -1)
+			xc_num = 0;
+		if (!is_initial_xendomain())
+			add_preferred_console(kcons_info.name, xc_num, NULL);
+		break;
+
+	case XC_SERIAL:
+		strcpy(kcons_info.name, "ttyS");
+		if (xc_num == -1)
+			xc_num = 0;
+		break;
+
+	case XC_TTY:
+		strcpy(kcons_info.name, "tty");
+		if (xc_num == -1)
+			xc_num = 1;
+		break;
+
+	default:
+		goto out;
+	}
+
+	wbuf = kmalloc(wbuf_size, GFP_KERNEL);
+
+	register_console(&kcons_info);
+
+ out:
+	return 0;
+}
+console_initcall(xen_console_init);
+
+/*** Useful function for console debugging -- goes straight to Xen. ***/
+asmlinkage int xprintk(const char *fmt, ...)
+{
+	va_list args;
+	int printk_len;
+	static char printk_buf[1024];
+
+	/* Emit the output into the temporary buffer */
+	va_start(args, fmt);
+	printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+	va_end(args);
+
+	/* Send the processed output directly to Xen. */
+	kcons_write_dom0(NULL, printk_buf, printk_len);
+
+	return 0;
+}
+
+/*** Forcibly flush console data before dying. ***/
+void xencons_force_flush(void)
+{
+	int sz;
+
+	/* Emergency console is synchronous, so there's nothing to flush. */
+	if (!is_running_on_xen() ||
+	    is_initial_xendomain() ||
+	    !xen_start_info->console.domU.evtchn)
+		return;
+
+	/* Spin until console data is flushed through to the daemon. */
+	while (wc != wp) {
+		int sent = 0;
+		if ((sz = wp - wc) == 0)
+			continue;
+		sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+		if (sent > 0)
+			wc += sent;
+	}
+}
+
+
+void __init dom0_init_screen_info(const struct dom0_vga_console_info *info, size_t size)
+{
+	/* This is drawn from a dump from vgacon:startup in
+	 * standard Linux. */
+	screen_info.orig_video_mode = 3;
+	screen_info.orig_video_isVGA = 1;
+	screen_info.orig_video_lines = 25;
+	screen_info.orig_video_cols = 80;
+	screen_info.orig_video_ega_bx = 3;
+	screen_info.orig_video_points = 16;
+	screen_info.orig_y = screen_info.orig_video_lines - 1;
+
+	switch (info->video_type) {
+	case XEN_VGATYPE_TEXT_MODE_3:
+		if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
+		           + sizeof(info->u.text_mode_3))
+			break;
+		screen_info.orig_video_lines = info->u.text_mode_3.rows;
+		screen_info.orig_video_cols = info->u.text_mode_3.columns;
+		screen_info.orig_x = info->u.text_mode_3.cursor_x;
+		screen_info.orig_y = info->u.text_mode_3.cursor_y;
+		screen_info.orig_video_points =
+			info->u.text_mode_3.font_height;
+		break;
+
+	case XEN_VGATYPE_VESA_LFB:
+		if (size < offsetof(struct dom0_vga_console_info,
+		                    u.vesa_lfb.gbl_caps))
+			break;
+		screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
+		screen_info.lfb_width = info->u.vesa_lfb.width;
+		screen_info.lfb_height = info->u.vesa_lfb.height;
+		screen_info.lfb_depth = info->u.vesa_lfb.bits_per_pixel;
+		screen_info.lfb_base = info->u.vesa_lfb.lfb_base;
+		screen_info.lfb_size = info->u.vesa_lfb.lfb_size;
+		screen_info.lfb_linelength = info->u.vesa_lfb.bytes_per_line;
+		screen_info.red_size = info->u.vesa_lfb.red_size;
+		screen_info.red_pos = info->u.vesa_lfb.red_pos;
+		screen_info.green_size = info->u.vesa_lfb.green_size;
+		screen_info.green_pos = info->u.vesa_lfb.green_pos;
+		screen_info.blue_size = info->u.vesa_lfb.blue_size;
+		screen_info.blue_pos = info->u.vesa_lfb.blue_pos;
+		screen_info.rsvd_size = info->u.vesa_lfb.rsvd_size;
+		screen_info.rsvd_pos = info->u.vesa_lfb.rsvd_pos;
+		if (size >= offsetof(struct dom0_vga_console_info,
+		                     u.vesa_lfb.gbl_caps)
+		            + sizeof(info->u.vesa_lfb.gbl_caps))
+			screen_info.capabilities = info->u.vesa_lfb.gbl_caps;
+		if (size >= offsetof(struct dom0_vga_console_info,
+		                     u.vesa_lfb.mode_attrs)
+		            + sizeof(info->u.vesa_lfb.mode_attrs))
+			screen_info.vesa_attributes = info->u.vesa_lfb.mode_attrs;
+		break;
+	}
+}
+
+
+/******************** User-space console driver (/dev/console) ************/
+
+#define DRV(_d)         (_d)
+#define DUMMY_TTY(_tty) ((xc_mode == XC_TTY) &&		\
+			 ((_tty)->index != (xc_num - 1)))
+
+static struct ktermios *xencons_termios[MAX_NR_CONSOLES];
+static struct ktermios *xencons_termios_locked[MAX_NR_CONSOLES];
+static struct tty_struct *xencons_tty;
+static int xencons_priv_irq;
+static char x_char;
+
+void xencons_rx(char *buf, unsigned len)
+{
+	int           i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	if (xencons_tty == NULL)
+		goto out;
+
+	for (i = 0; i < len; i++) {
+#ifdef CONFIG_MAGIC_SYSRQ
+		if (sysrq_on()) {
+			static unsigned long sysrq_requested;
+
+			if (buf[i] == '\x0f') { /* ^O */
+				if (!sysrq_requested) {
+					sysrq_requested = jiffies;
+					continue; /* don't print sysrq key */
+				}
+				sysrq_requested = 0;
+			} else if (sysrq_requested) {
+				unsigned long sysrq_timeout =
+					sysrq_requested + HZ*2;
+				sysrq_requested = 0;
+				if (time_before(jiffies, sysrq_timeout)) {
+					spin_unlock_irqrestore(
+						&xencons_lock, flags);
+					handle_sysrq(buf[i], xencons_tty);
+					spin_lock_irqsave(
+						&xencons_lock, flags);
+					continue;
+				}
+			}
+		}
+#endif
+		tty_insert_flip_char(xencons_tty, buf[i], 0);
+	}
+	tty_flip_buffer_push(xencons_tty);
+
+ out:
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void __xencons_tx_flush(void)
+{
+	int sent, sz, work_done = 0;
+
+	if (x_char) {
+		if (is_initial_xendomain())
+			kcons_write_dom0(NULL, &x_char, 1);
+		else
+			while (x_char)
+				if (xencons_ring_send(&x_char, 1) == 1)
+					break;
+		x_char = 0;
+		work_done = 1;
+	}
+
+	while (wc != wp) {
+		sz = wp - wc;
+		if (sz > (wbuf_size - WBUF_MASK(wc)))
+			sz = wbuf_size - WBUF_MASK(wc);
+		if (is_initial_xendomain()) {
+			kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+			wc += sz;
+		} else {
+			sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+			if (sent == 0)
+				break;
+			wc += sent;
+		}
+		work_done = 1;
+	}
+
+	if (work_done && (xencons_tty != NULL)) {
+		wake_up_interruptible(&xencons_tty->write_wait);
+		tty_wakeup(xencons_tty);
+	}
+}
+
+void xencons_tx(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	__xencons_tx_flush();
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+/* Privileged receive callback and transmit kicker. */
+static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id)
+{
+	static char rbuf[16];
+	int         l;
+
+	while ((l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0)
+		xencons_rx(rbuf, l);
+
+	xencons_tx();
+
+	return IRQ_HANDLED;
+}
+
+static int xencons_write_room(struct tty_struct *tty)
+{
+	return wbuf_size - (wp - wc);
+}
+
+static int xencons_chars_in_buffer(struct tty_struct *tty)
+{
+	return wp - wc;
+}
+
+static void xencons_send_xchar(struct tty_struct *tty, char ch)
+{
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	x_char = ch;
+	__xencons_tx_flush();
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void xencons_throttle(struct tty_struct *tty)
+{
+	if (DUMMY_TTY(tty))
+		return;
+
+	if (I_IXOFF(tty))
+		xencons_send_xchar(tty, STOP_CHAR(tty));
+}
+
+static void xencons_unthrottle(struct tty_struct *tty)
+{
+	if (DUMMY_TTY(tty))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (x_char != 0)
+			x_char = 0;
+		else
+			xencons_send_xchar(tty, START_CHAR(tty));
+	}
+}
+
+static void xencons_flush_buffer(struct tty_struct *tty)
+{
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	wc = wp = 0;
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static inline int __xencons_put_char(int ch)
+{
+	char _ch = (char)ch;
+	if ((wp - wc) == wbuf_size)
+		return 0;
+	wbuf[WBUF_MASK(wp++)] = _ch;
+	return 1;
+}
+
+static int xencons_write(
+	struct tty_struct *tty,
+	const unsigned char *buf,
+	int count)
+{
+	int i;
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return count;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+
+	for (i = 0; i < count; i++)
+		if (!__xencons_put_char(buf[i]))
+			break;
+
+	if (i != 0)
+		__xencons_tx_flush();
+
+	spin_unlock_irqrestore(&xencons_lock, flags);
+
+	return i;
+}
+
+static int xencons_put_char(struct tty_struct *tty, u_char ch)
+{
+	unsigned long flags;
+	int ret;
+
+	if (DUMMY_TTY(tty))
+		return 0;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	ret = __xencons_put_char(ch);
+	spin_unlock_irqrestore(&xencons_lock, flags);
+	return ret;
+}
+
+static void xencons_flush_chars(struct tty_struct *tty)
+{
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	__xencons_tx_flush();
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	unsigned long orig_jiffies = jiffies;
+
+	if (DUMMY_TTY(tty))
+		return;
+
+	while (tty_chars_in_buffer(tty)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+
+	set_current_state(TASK_RUNNING);
+}
+
+static int xencons_open(struct tty_struct *tty, struct file *filp)
+{
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return 0;
+
+	spin_lock_irqsave(&xencons_lock, flags);
+	tty->driver_data = NULL;
+	if (xencons_tty == NULL)
+		xencons_tty = tty;
+	__xencons_tx_flush();
+	spin_unlock_irqrestore(&xencons_lock, flags);
+
+	return 0;
+}
+
+static void xencons_close(struct tty_struct *tty, struct file *filp)
+{
+	unsigned long flags;
+
+	if (DUMMY_TTY(tty))
+		return;
+
+	mutex_lock(&tty_mutex);
+
+	if (tty->count != 1) {
+		mutex_unlock(&tty_mutex);
+		return;
+	}
+
+	/* Prevent other threads from re-opening this tty. */
+	set_bit(TTY_CLOSING, &tty->flags);
+	mutex_unlock(&tty_mutex);
+
+	tty->closing = 1;
+	tty_wait_until_sent(tty, 0);
+	tty_driver_flush_buffer(tty);
+	if (tty->ldisc->ops->flush_buffer)
+		tty->ldisc->ops->flush_buffer(tty);
+	tty->closing = 0;
+	spin_lock_irqsave(&xencons_lock, flags);
+	xencons_tty = NULL;
+	spin_unlock_irqrestore(&xencons_lock, flags);
+}
+
+static const struct tty_operations xencons_ops = {
+	.open = xencons_open,
+	.close = xencons_close,
+	.write = xencons_write,
+	.write_room = xencons_write_room,
+	.put_char = xencons_put_char,
+	.flush_chars = xencons_flush_chars,
+	.chars_in_buffer = xencons_chars_in_buffer,
+	.send_xchar = xencons_send_xchar,
+	.flush_buffer = xencons_flush_buffer,
+	.throttle = xencons_throttle,
+	.unthrottle = xencons_unthrottle,
+	.wait_until_sent = xencons_wait_until_sent,
+};
+
+static int __init xencons_init(void)
+{
+	int rc;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	if (xc_mode == XC_OFF)
+		return 0;
+
+	if (!is_initial_xendomain()) {
+		rc = xencons_ring_init();
+		if (rc)
+			return rc;
+	}
+
+	xencons_driver = alloc_tty_driver((xc_mode == XC_TTY) ?
+					  MAX_NR_CONSOLES : 1);
+	if (xencons_driver == NULL)
+		return -ENOMEM;
+
+	DRV(xencons_driver)->name            = "xencons";
+	DRV(xencons_driver)->major           = TTY_MAJOR;
+	DRV(xencons_driver)->type            = TTY_DRIVER_TYPE_SERIAL;
+	DRV(xencons_driver)->subtype         = SERIAL_TYPE_NORMAL;
+	DRV(xencons_driver)->init_termios    = tty_std_termios;
+	DRV(xencons_driver)->flags           =
+		TTY_DRIVER_REAL_RAW |
+		TTY_DRIVER_RESET_TERMIOS;
+	DRV(xencons_driver)->termios         = xencons_termios;
+	DRV(xencons_driver)->termios_locked  = xencons_termios_locked;
+
+	switch (xc_mode) {
+	case XC_XVC:
+		DRV(xencons_driver)->name        = "xvc";
+		DRV(xencons_driver)->major       = XEN_XVC_MAJOR;
+		DRV(xencons_driver)->minor_start = XEN_XVC_MINOR;
+		DRV(xencons_driver)->name_base   = xc_num;
+		break;
+	case XC_HVC:
+		DRV(xencons_driver)->name        = "hvc";
+		DRV(xencons_driver)->major       = XEN_HVC_MAJOR;
+		DRV(xencons_driver)->minor_start = XEN_HVC_MINOR;
+		DRV(xencons_driver)->name_base   = xc_num;
+		break;
+	case XC_SERIAL:
+		DRV(xencons_driver)->name        = "ttyS";
+		DRV(xencons_driver)->minor_start = 64 + xc_num;
+		DRV(xencons_driver)->name_base   = xc_num;
+		break;
+	default:
+		DRV(xencons_driver)->name        = "tty";
+		DRV(xencons_driver)->minor_start = 1;
+		DRV(xencons_driver)->name_base   = 1;
+		break;
+	}
+
+	tty_set_operations(xencons_driver, &xencons_ops);
+
+	if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) {
+		printk("WARNING: Failed to register Xen virtual "
+		       "console driver as '%s%d'\n",
+		       DRV(xencons_driver)->name,
+		       DRV(xencons_driver)->name_base);
+		put_tty_driver(xencons_driver);
+		xencons_driver = NULL;
+		return rc;
+	}
+
+	if (is_initial_xendomain()) {
+		xencons_priv_irq = bind_virq_to_irqhandler(
+			VIRQ_CONSOLE,
+			0,
+			xencons_priv_interrupt,
+			0,
+			"console",
+			NULL);
+		BUG_ON(xencons_priv_irq < 0);
+	}
+
+	printk("Xen virtual console successfully installed as %s%d\n",
+	       DRV(xencons_driver)->name, xc_num);
+
+	return 0;
+}
+
+module_init(xencons_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/console/xencons_ring.c
+++ linux-ec2-2.6.32/drivers/xen/console/xencons_ring.c
@@ -0,0 +1,143 @@
+/* 
+ * 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 <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/xencons.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <xen/interface/io/console.h>
+
+static int xencons_irq;
+
+static inline struct xencons_interface *xencons_interface(void)
+{
+	return mfn_to_virt(xen_start_info->console.domU.mfn);
+}
+
+static inline void notify_daemon(void)
+{
+	/* Use evtchn: this is called early, before irq is set up. */
+	notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
+}
+
+int xencons_ring_send(const char *data, unsigned len)
+{
+	int sent = 0;
+	struct xencons_interface *intf = xencons_interface();
+	XENCONS_RING_IDX cons, prod;
+
+	cons = intf->out_cons;
+	prod = intf->out_prod;
+	mb();
+	BUG_ON((prod - cons) > sizeof(intf->out));
+
+	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+	wmb();
+	intf->out_prod = prod;
+
+	notify_daemon();
+
+	return sent;
+}
+
+static irqreturn_t handle_input(int irq, void *unused)
+{
+	struct xencons_interface *intf = xencons_interface();
+	XENCONS_RING_IDX cons, prod;
+
+	cons = intf->in_cons;
+	prod = intf->in_prod;
+	mb();
+	BUG_ON((prod - cons) > sizeof(intf->in));
+
+	while (cons != prod) {
+		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1);
+		cons++;
+	}
+
+	mb();
+	intf->in_cons = cons;
+
+	notify_daemon();
+
+	xencons_tx();
+
+	return IRQ_HANDLED;
+}
+
+int xencons_ring_init(void)
+{
+	int irq;
+
+	if (xencons_irq)
+		unbind_from_irqhandler(xencons_irq, NULL);
+	xencons_irq = 0;
+
+	if (!is_running_on_xen() ||
+	    is_initial_xendomain() ||
+	    !xen_start_info->console.domU.evtchn)
+		return -ENODEV;
+
+	irq = bind_caller_port_to_irqhandler(
+		xen_start_info->console.domU.evtchn,
+		handle_input, 0, "xencons", NULL);
+	if (irq < 0) {
+		printk(KERN_ERR "XEN console request irq failed %i\n", irq);
+		return irq;
+	}
+
+	xencons_irq = irq;
+
+	/* In case we have in-flight data after save/restore... */
+	notify_daemon();
+
+	return 0;
+}
+
+void xencons_resume(void)
+{
+	(void)xencons_ring_init();
+}
--- linux-ec2-2.6.32.orig/drivers/xen/privcmd/Makefile
+++ linux-ec2-2.6.32/drivers/xen/privcmd/Makefile
@@ -0,0 +1,2 @@
+priv-$(CONFIG_COMPAT) := compat_privcmd.o
+obj-y := privcmd.o $(priv-y)
--- linux-ec2-2.6.32.orig/drivers/xen/privcmd/privcmd.c
+++ linux-ec2-2.6.32/drivers/xen/privcmd/privcmd.c
@@ -0,0 +1,336 @@
+/******************************************************************************
+ * privcmd.c
+ * 
+ * Interface to privileged domain-0 commands.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser, B Dragovic
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/smp_lock.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <asm/hypervisor.h>
+
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/hypervisor.h>
+#include <xen/public/privcmd.h>
+#include <xen/interface/xen.h>
+#include <xen/xen_proc.h>
+#include <xen/features.h>
+
+static struct proc_dir_entry *privcmd_intf;
+static struct proc_dir_entry *capabilities_intf;
+
+#ifndef CONFIG_XEN_PRIVILEGED_GUEST
+#define HAVE_ARCH_PRIVCMD_MMAP
+#endif
+#ifndef HAVE_ARCH_PRIVCMD_MMAP
+static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
+#endif
+
+static long privcmd_ioctl(struct file *file,
+			  unsigned int cmd, unsigned long data)
+{
+	long ret = -ENOSYS;
+	void __user *udata = (void __user *) data;
+
+	switch (cmd) {
+	case IOCTL_PRIVCMD_HYPERCALL: {
+		privcmd_hypercall_t hypercall;
+  
+		if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
+			return -EFAULT;
+
+#ifdef CONFIG_X86
+		if (hypercall.op >= (PAGE_SIZE >> 5))
+			break;
+		ret = _hypercall(long, (unsigned int)hypercall.op,
+				 (unsigned long)hypercall.arg[0],
+				 (unsigned long)hypercall.arg[1],
+				 (unsigned long)hypercall.arg[2],
+				 (unsigned long)hypercall.arg[3],
+				 (unsigned long)hypercall.arg[4]);
+#else
+		ret = privcmd_hypercall(&hypercall);
+#endif
+	}
+	break;
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+
+	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 __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;
+
+		if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
+			return -EFAULT;
+
+		p = mmapcmd.entry;
+		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);
+		rc = -EINVAL;
+		if (!vma || (msg->va != vma->vm_start) ||
+		    !privcmd_enforce_singleshot_mapping(vma))
+			goto mmap_out;
+
+		va = vma->vm_start;
+
+		i = 0;
+		list_for_each(l, &pagelist) {
+			int nr = i + min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
+
+			msg = (privcmd_mmap_entry_t*)(l + 1);
+			while (i<nr) {
+
+				/* 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;
+		int i;
+		LIST_HEAD(pagelist);
+		struct list_head *l, *l2;
+
+		if (!is_initial_xendomain())
+			return -EPERM;
+
+		if (copy_from_user(&m, udata, sizeof(m)))
+			return -EFAULT;
+
+		nr_pages = m.num;
+		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);
+			goto mmapbatch_out;
+		}
+
+		p = m.arr;
+		addr = m.addr;
+		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;
+			}
+		}
+
+		up_write(&mm->mmap_sem);
+		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;
+
+#endif /* CONFIG_XEN_PRIVILEGED_GUEST */
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+#ifndef HAVE_ARCH_PRIVCMD_MMAP
+static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	return VM_FAULT_SIGBUS;
+}
+
+static struct vm_operations_struct privcmd_vm_ops = {
+	.fault = privcmd_fault
+};
+
+static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
+{
+	/* Unsupported for auto-translate guests. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return -ENOSYS;
+
+	/* DONTCOPY is essential for Xen as copy_page_range is broken. */
+	vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTCOPY;
+	vma->vm_ops = &privcmd_vm_ops;
+	vma->vm_private_data = NULL;
+
+	return 0;
+}
+
+static int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma)
+{
+	return (xchg(&vma->vm_private_data, (void *)1) == NULL);
+}
+#endif
+
+static const struct file_operations privcmd_file_ops = {
+	.unlocked_ioctl = privcmd_ioctl,
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+	.mmap = privcmd_mmap,
+#endif
+};
+
+static int capabilities_read(char *page, char **start, off_t off,
+			     int count, int *eof, void *data)
+{
+	int len = 0;
+	*page = 0;
+
+	if (is_initial_xendomain())
+		len = sprintf( page, "control_d\n" );
+
+	*eof = 1;
+	return len;
+}
+
+static int __init privcmd_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	privcmd_intf = create_xen_proc_entry("privcmd", 0400);
+	if (privcmd_intf != NULL)
+		privcmd_intf->proc_fops = &privcmd_file_ops;
+
+	capabilities_intf = create_xen_proc_entry("capabilities", 0400 );
+	if (capabilities_intf != NULL)
+		capabilities_intf->read_proc = capabilities_read;
+
+	return 0;
+}
+
+__initcall(privcmd_init);
--- linux-ec2-2.6.32.orig/drivers/xen/privcmd/compat_privcmd.c
+++ linux-ec2-2.6.32/drivers/xen/privcmd/compat_privcmd.c
@@ -0,0 +1,72 @@
+/*
+ * 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>
+ */
+
+#include <linux/compat.h>
+#include <linux/ioctl.h>
+#include <linux/syscalls.h>
+#include <asm/hypervisor.h>
+#include <asm/uaccess.h>
+#include <xen/public/privcmd.h>
+#include <xen/compat_ioctl.h>
+
+int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case IOCTL_PRIVCMD_MMAP_32: {
+		struct privcmd_mmap *p;
+		struct privcmd_mmap_32 *p32;
+		struct privcmd_mmap_32 n32;
+
+		p32 = compat_ptr(arg);
+		p = compat_alloc_user_space(sizeof(*p));
+		if (copy_from_user(&n32, p32, sizeof(n32)) ||
+		    put_user(n32.num, &p->num) ||
+		    put_user(n32.dom, &p->dom) ||
+		    put_user(compat_ptr(n32.entry), &p->entry))
+			return -EFAULT;
+		
+		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAP, (unsigned long)p);
+	}
+		break;
+	case IOCTL_PRIVCMD_MMAPBATCH_32: {
+		struct privcmd_mmapbatch *p;
+		struct privcmd_mmapbatch_32 *p32;
+		struct privcmd_mmapbatch_32 n32;
+
+		p32 = compat_ptr(arg);
+		p = compat_alloc_user_space(sizeof(*p));
+		if (copy_from_user(&n32, p32, sizeof(n32)) ||
+		    put_user(n32.num, &p->num) ||
+		    put_user(n32.dom, &p->dom) ||
+		    put_user(n32.addr, &p->addr) ||
+		    put_user(compat_ptr(n32.arr), &p->arr))
+			return -EFAULT;
+		
+		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, (unsigned long)p);
+	}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/pciback.h
+++ linux-ec2-2.6.32/drivers/xen/pciback/pciback.h
@@ -0,0 +1,126 @@
+/*
+ * 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))
+#define _PCIB_op_pending	(1)
+#define PCIB_op_pending		(1<<(_PCIB_op_pending))
+
+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);
+
+/** 
+* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in pciback
+* before sending aer request to pcifront, so that guest could identify 
+* device, coopearte with pciback to finish aer recovery job if device driver
+* has the capability
+*/
+
+int pciback_get_pcifront_dev(struct pci_dev *pcidev, 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);
+void pciback_do_op(struct work_struct *work);
+
+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;
+
+void test_and_schedule_op(struct pciback_device *pdev);
+#endif
+
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_capability_msi.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_capability_msi.c
@@ -0,0 +1,79 @@
+/*
+ * PCI Backend -- Configuration overlay for MSI capability
+ */
+#include <linux/pci.h>
+#include <linux/slab.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 i, result;
+	struct msix_entry *entries;
+
+	if (op->value > SH_INFO_MAX_VEC)
+		return -EINVAL;
+
+	entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
+	if (entries == NULL)
+		return -ENOMEM;
+
+	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);
+
+	for (i = 0; i < op->value; i++) {
+		op->msix_entries[i].entry = entries[i].entry;
+		op->msix_entries[i].vector = entries[i].vector;
+	}
+
+	kfree(entries);
+
+	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;
+}
+
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/pciback/Makefile
@@ -0,0 +1,15 @@
+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
+
+ccflags-$(CONFIG_XEN_PCIDEV_BE_DEBUG) += -DDEBUG
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/slot.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/slot.c
@@ -0,0 +1,187 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ *               to the frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
+ *   Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+/* There are at most 32 slots in a pci bus.  */
+#define PCI_SLOT_MAX 32
+
+#define PCI_BUS_NBR 2
+
+struct slot_dev_data {
+	/* Access to dev_list must be protected by lock */
+	struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
+	spinlock_t lock;
+};
+
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
+				    unsigned int domain, unsigned int bus,
+				    unsigned int devfn)
+{
+	struct pci_dev *dev = NULL;
+	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
+	unsigned long flags;
+
+	if (domain != 0 || PCI_FUNC(devfn) != 0)
+		return NULL;
+
+	if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
+		return NULL;
+
+	spin_lock_irqsave(&slot_dev->lock, flags);
+	dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
+	spin_unlock_irqrestore(&slot_dev->lock, flags);
+
+	return 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;
+	unsigned long flags;
+
+	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
+		err = -EFAULT;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Can't export bridges on the virtual PCI bus");
+		goto out;
+	}
+
+	spin_lock_irqsave(&slot_dev->lock, flags);
+
+	/* Assign to a new slot on the virtual PCI bus */
+	for (bus = 0; bus < PCI_BUS_NBR; bus++)
+		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+			if (slot_dev->slots[bus][slot] == NULL) {
+				printk(KERN_INFO
+				       "pciback: slot: %s: assign to virtual slot %d, bus %d\n",
+				       pci_name(dev), slot, bus);
+				slot_dev->slots[bus][slot] = dev;
+				goto unlock;
+			}
+		}
+
+	err = -ENOMEM;
+	xenbus_dev_fatal(pdev->xdev, err,
+			 "No more space on root virtual PCI bus");
+
+      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;
+}
+
+void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
+{
+	int slot, bus;
+	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&slot_dev->lock, flags);
+
+	for (bus = 0; bus < PCI_BUS_NBR; bus++)
+		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+			if (slot_dev->slots[bus][slot] == dev) {
+				slot_dev->slots[bus][slot] = NULL;
+				found_dev = dev;
+				goto out;
+			}
+		}
+
+      out:
+	spin_unlock_irqrestore(&slot_dev->lock, flags);
+
+	if (found_dev)
+		pcistub_put_pci_dev(found_dev);
+}
+
+int pciback_init_devices(struct pciback_device *pdev)
+{
+	int slot, bus;
+	struct slot_dev_data *slot_dev;
+
+	slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
+	if (!slot_dev)
+		return -ENOMEM;
+
+	spin_lock_init(&slot_dev->lock);
+
+	for (bus = 0; bus < PCI_BUS_NBR; bus++)
+		for (slot = 0; slot < PCI_SLOT_MAX; slot++)
+			slot_dev->slots[bus][slot] = NULL;
+
+	pdev->pci_dev_data = slot_dev;
+
+	return 0;
+}
+
+int pciback_publish_pci_roots(struct pciback_device *pdev,
+			      publish_pci_root_cb publish_cb)
+{
+	/* The Virtual PCI bus has only one root */
+	return publish_cb(pdev, 0, 0);
+}
+
+void pciback_release_devices(struct pciback_device *pdev)
+{
+	int slot, bus;
+	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
+	struct pci_dev *dev;
+
+	for (bus = 0; bus < PCI_BUS_NBR; bus++)
+		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+			dev = slot_dev->slots[bus][slot];
+			if (dev != NULL)
+				pcistub_put_pci_dev(dev);
+		}
+
+	kfree(slot_dev);
+	pdev->pci_dev_data = NULL;
+}
+
+int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
+		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
+{
+	int slot, busnr;
+	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
+	struct pci_dev *dev;
+	int found = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&slot_dev->lock, flags);
+
+	for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
+		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+			dev = slot_dev->slots[busnr][slot];
+			if (dev && dev->bus->number == pcidev->bus->number
+				&& dev->devfn == pcidev->devfn
+				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)) {
+				found = 1;
+				*domain = 0;
+				*bus = busnr;
+				*devfn = PCI_DEVFN(slot,0);
+				goto out;
+			}
+		}
+out:
+	spin_unlock_irqrestore(&slot_dev->lock, flags);
+	return found;
+
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_quirks.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_quirks.c
@@ -0,0 +1,138 @@
+/*
+ * PCI Backend - Handle special overlays for broken devices.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+LIST_HEAD(pciback_quirks);
+
+static inline const struct pci_device_id *
+match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
+{
+	if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
+	    (id->device == PCI_ANY_ID || id->device == dev->device) &&
+	    (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
+	    (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
+	    !((id->class ^ dev->class) & id->class_mask))
+		return id;
+	return NULL;
+}
+
+struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev)
+{
+	struct pciback_config_quirk *tmp_quirk;
+
+	list_for_each_entry(tmp_quirk, &pciback_quirks, quirks_list)
+		if (match_one_device(&tmp_quirk->devid, dev) != NULL)
+			goto out;
+	tmp_quirk = NULL;
+	printk(KERN_DEBUG
+	       "quirk didn't match any device pciback knows about\n");
+      out:
+	return tmp_quirk;
+}
+
+static inline void register_quirk(struct pciback_config_quirk *quirk)
+{
+	list_add_tail(&quirk->quirks_list, &pciback_quirks);
+}
+
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
+{
+	int ret = 0;
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		if ( OFFSET(cfg_entry) == reg) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
+				    *field)
+{
+	int err = 0;
+
+	switch (field->size) {
+	case 1:
+		field->u.b.read = pciback_read_config_byte;
+		field->u.b.write = pciback_write_config_byte;
+		break;
+	case 2:
+		field->u.w.read = pciback_read_config_word;
+		field->u.w.write = pciback_write_config_word;
+		break;
+	case 4:
+		field->u.dw.read = pciback_read_config_dword;
+		field->u.dw.write = pciback_write_config_dword;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+
+	pciback_config_add_field(dev, field);
+
+      out:
+	return err;
+}
+
+int pciback_config_quirks_init(struct pci_dev *dev)
+{
+	struct pciback_config_quirk *quirk;
+	int ret = 0;
+
+	quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
+	if (!quirk) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	quirk->devid.vendor = dev->vendor;
+	quirk->devid.device = dev->device;
+	quirk->devid.subvendor = dev->subsystem_vendor;
+	quirk->devid.subdevice = dev->subsystem_device;
+	quirk->devid.class = 0;
+	quirk->devid.class_mask = 0;
+	quirk->devid.driver_data = 0UL;
+
+	quirk->pdev = dev;
+
+	register_quirk(quirk);
+      out:
+	return ret;
+}
+
+void pciback_config_field_free(struct config_field *field)
+{
+	kfree(field);
+}
+
+int pciback_config_quirk_release(struct pci_dev *dev)
+{
+	struct pciback_config_quirk *quirk;
+	int ret = 0;
+
+	quirk = pciback_find_quirk(dev);
+	if (!quirk) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	list_del(&quirk->quirks_list);
+	kfree(quirk);
+
+      out:
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space.h
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space.h
@@ -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;
+	const 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,
+				    const struct config_field *field,
+				    unsigned int offset);
+
+static inline int pciback_config_add_field(struct pci_dev *dev,
+					   const struct config_field *field)
+{
+	return pciback_config_add_field_offset(dev, field, 0);
+}
+
+static inline int pciback_config_add_fields(struct pci_dev *dev,
+					    const 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,
+						   const 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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space.c
@@ -0,0 +1,435 @@
+/*
+ * PCI Backend - Functions for creating a virtual configuration space for
+ *               exported PCI Devices.
+ *               It's dangerous to allow PCI Driver Domains to change their
+ *               device's resources (memory, i/o ports, interrupts). We need to
+ *               restrict changes to certain PCI Configuration registers:
+ *               BARs, INTERRUPT_PIN, most registers in the header...
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+static int permissive;
+module_param(permissive, bool, 0644);
+
+#define DEFINE_PCI_CONFIG(op,size,type) 			\
+int pciback_##op##_config_##size 				\
+(struct pci_dev *dev, int offset, type value, void *data)	\
+{								\
+	return pci_##op##_config_##size (dev, offset, value);	\
+}
+
+DEFINE_PCI_CONFIG(read, byte, u8 *)
+DEFINE_PCI_CONFIG(read, word, u16 *)
+DEFINE_PCI_CONFIG(read, dword, u32 *)
+
+DEFINE_PCI_CONFIG(write, byte, u8)
+DEFINE_PCI_CONFIG(write, word, u16)
+DEFINE_PCI_CONFIG(write, dword, u32)
+
+static int conf_space_read(struct pci_dev *dev,
+			   const struct config_field_entry *entry,
+			   int offset, u32 *value)
+{
+	int ret = 0;
+	const struct config_field *field = entry->field;
+
+	*value = 0;
+
+	switch (field->size) {
+	case 1:
+		if (field->u.b.read)
+			ret = field->u.b.read(dev, offset, (u8 *) value,
+					      entry->data);
+		break;
+	case 2:
+		if (field->u.w.read)
+			ret = field->u.w.read(dev, offset, (u16 *) value,
+					      entry->data);
+		break;
+	case 4:
+		if (field->u.dw.read)
+			ret = field->u.dw.read(dev, offset, value, entry->data);
+		break;
+	}
+	return ret;
+}
+
+static int conf_space_write(struct pci_dev *dev,
+			    const struct config_field_entry *entry,
+			    int offset, u32 value)
+{
+	int ret = 0;
+	const struct config_field *field = entry->field;
+
+	switch (field->size) {
+	case 1:
+		if (field->u.b.write)
+			ret = field->u.b.write(dev, offset, (u8) value,
+					       entry->data);
+		break;
+	case 2:
+		if (field->u.w.write)
+			ret = field->u.w.write(dev, offset, (u16) value,
+					       entry->data);
+		break;
+	case 4:
+		if (field->u.dw.write)
+			ret = field->u.dw.write(dev, offset, value,
+						entry->data);
+		break;
+	}
+	return ret;
+}
+
+static inline u32 get_mask(int size)
+{
+	if (size == 1)
+		return 0xff;
+	else if (size == 2)
+		return 0xffff;
+	else
+		return 0xffffffff;
+}
+
+static inline int valid_request(int offset, int size)
+{
+	/* Validate request (no un-aligned requests) */
+	if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
+		return 1;
+	return 0;
+}
+
+static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
+			      int offset)
+{
+	if (offset >= 0) {
+		new_val_mask <<= (offset * 8);
+		new_val <<= (offset * 8);
+	} else {
+		new_val_mask >>= (offset * -8);
+		new_val >>= (offset * -8);
+	}
+	val = (val & ~new_val_mask) | (new_val & new_val_mask);
+
+	return val;
+}
+
+static int pcibios_err_to_errno(int err)
+{
+	switch (err) {
+	case PCIBIOS_SUCCESSFUL:
+		return XEN_PCI_ERR_success;
+	case PCIBIOS_DEVICE_NOT_FOUND:
+		return XEN_PCI_ERR_dev_not_found;
+	case PCIBIOS_BAD_REGISTER_NUMBER:
+		return XEN_PCI_ERR_invalid_offset;
+	case PCIBIOS_FUNC_NOT_SUPPORTED:
+		return XEN_PCI_ERR_not_implemented;
+	case PCIBIOS_SET_FAILED:
+		return XEN_PCI_ERR_access_denied;
+	}
+	return err;
+}
+
+int pciback_config_read(struct pci_dev *dev, int offset, int size,
+			u32 * ret_val)
+{
+	int err = 0;
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+	int req_start, req_end, field_start, field_end;
+	/* if read fails for any reason, return 0 (as if device didn't respond) */
+	u32 value = 0, tmp_val;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x\n",
+		       pci_name(dev), size, offset);
+
+	if (!valid_request(offset, size)) {
+		err = XEN_PCI_ERR_invalid_offset;
+		goto out;
+	}
+
+	/* Get the real value first, then modify as appropriate */
+	switch (size) {
+	case 1:
+		err = pci_read_config_byte(dev, offset, (u8 *) & value);
+		break;
+	case 2:
+		err = pci_read_config_word(dev, offset, (u16 *) & value);
+		break;
+	case 4:
+		err = pci_read_config_dword(dev, offset, &value);
+		break;
+	}
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		req_start = offset;
+		req_end = offset + size;
+		field_start = OFFSET(cfg_entry);
+		field_end = OFFSET(cfg_entry) + field->size;
+
+		if ((req_start >= field_start && req_start < field_end)
+		    || (req_end > field_start && req_end <= field_end)) {
+			err = conf_space_read(dev, cfg_entry, field_start,
+					      &tmp_val);
+			if (err)
+				goto out;
+
+			value = merge_value(value, tmp_val,
+					    get_mask(field->size),
+					    field_start - req_start);
+		}
+	}
+
+      out:
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x = %x\n",
+		       pci_name(dev), size, offset, value);
+
+	*ret_val = value;
+	return pcibios_err_to_errno(err);
+}
+
+int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
+{
+	int err = 0, handled = 0;
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+	u32 tmp_val;
+	int req_start, req_end, field_start, field_end;
+
+	if (unlikely(verbose_request))
+		printk(KERN_DEBUG
+		       "pciback: %s: write request %d bytes at 0x%x = %x\n",
+		       pci_name(dev), size, offset, value);
+
+	if (!valid_request(offset, size))
+		return XEN_PCI_ERR_invalid_offset;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		req_start = offset;
+		req_end = offset + size;
+		field_start = OFFSET(cfg_entry);
+		field_end = OFFSET(cfg_entry) + field->size;
+
+		if ((req_start >= field_start && req_start < field_end)
+		    || (req_end > field_start && req_end <= field_end)) {
+			tmp_val = 0;
+
+			err = pciback_config_read(dev, field_start,
+						  field->size, &tmp_val);
+			if (err)
+				break;
+
+			tmp_val = merge_value(tmp_val, value, get_mask(size),
+					      req_start - field_start);
+
+			err = conf_space_write(dev, cfg_entry, field_start,
+					       tmp_val);
+
+			/* handled is set true here, but not every byte
+			 * may have been written! Properly detecting if
+			 * every byte is handled is unnecessary as the
+			 * flag is used to detect devices that need
+			 * special helpers to work correctly.
+			 */
+			handled = 1;
+		}
+	}
+
+	if (!handled && !err) {
+		/* By default, anything not specificially handled above is
+		 * read-only. The permissive flag changes this behavior so
+		 * that anything not specifically handled above is writable.
+		 * This means that some fields may still be read-only because
+		 * they have entries in the config_field list that intercept
+		 * the write and do nothing. */
+		if (dev_data->permissive || permissive) {
+			switch (size) {
+			case 1:
+				err = pci_write_config_byte(dev, offset,
+							    (u8) value);
+				break;
+			case 2:
+				err = pci_write_config_word(dev, offset,
+							    (u16) value);
+				break;
+			case 4:
+				err = pci_write_config_dword(dev, offset,
+							     (u32) value);
+				break;
+			}
+		} else if (!dev_data->warned_on_write) {
+			dev_data->warned_on_write = 1;
+			dev_warn(&dev->dev, "Driver tried to write to a "
+				 "read-only configuration space field at offset "
+				 "0x%x, size %d. This may be harmless, but if "
+				 "you have problems with your device:\n"
+				 "1) see permissive attribute in sysfs\n"
+				 "2) report problems to the xen-devel "
+				 "mailing list along with details of your "
+				 "device obtained from lspci.\n", offset, size);
+		}
+	}
+
+	return pcibios_err_to_errno(err);
+}
+
+void pciback_config_free_dyn_fields(struct pci_dev *dev)
+{
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry, *t;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev,
+		"free-ing dynamically allocated virtual configuration space fields\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		if (field->clean) {
+			field->clean((struct config_field *)field);
+
+			if (cfg_entry->data)
+				kfree(cfg_entry->data);
+
+			list_del(&cfg_entry->list);
+			kfree(cfg_entry);
+		}
+
+	}
+}
+
+void pciback_config_reset_dev(struct pci_dev *dev)
+{
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	const struct config_field_entry *cfg_entry;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev, "resetting virtual configuration space\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+		field = cfg_entry->field;
+
+		if (field->reset)
+			field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
+	}
+}
+
+void pciback_config_free_dev(struct pci_dev *dev)
+{
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry, *t;
+	const struct config_field *field;
+
+	dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
+	if (!dev_data)
+		return;
+
+	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
+		list_del(&cfg_entry->list);
+
+		field = cfg_entry->field;
+
+		if (field->release)
+			field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
+
+		kfree(cfg_entry);
+	}
+}
+
+int pciback_config_add_field_offset(struct pci_dev *dev,
+				    const struct config_field *field,
+				    unsigned int base_offset)
+{
+	int err = 0;
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+	struct config_field_entry *cfg_entry;
+	void *tmp;
+
+	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
+	if (!cfg_entry) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	cfg_entry->data = NULL;
+	cfg_entry->field = field;
+	cfg_entry->base_offset = base_offset;
+
+	/* silently ignore duplicate fields */
+	err = pciback_field_is_dup(dev,OFFSET(cfg_entry));
+	if (err)
+		goto out;
+
+	if (field->init) {
+		tmp = field->init(dev, OFFSET(cfg_entry));
+
+		if (IS_ERR(tmp)) {
+			err = PTR_ERR(tmp);
+			goto out;
+		}
+
+		cfg_entry->data = tmp;
+	}
+
+	dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
+		OFFSET(cfg_entry));
+	list_add_tail(&cfg_entry->list, &dev_data->config_fields);
+
+      out:
+	if (err)
+		kfree(cfg_entry);
+
+	return err;
+}
+
+/* This sets up the device's virtual configuration space to keep track of 
+ * certain registers (like the base address registers (BARs) so that we can
+ * keep the client from manipulating them directly.
+ */
+int pciback_config_init_dev(struct pci_dev *dev)
+{
+	int err = 0;
+	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
+
+	dev_dbg(&dev->dev, "initializing virtual configuration space\n");
+
+	INIT_LIST_HEAD(&dev_data->config_fields);
+
+	err = pciback_config_header_add_fields(dev);
+	if (err)
+		goto out;
+
+	err = pciback_config_capability_add_fields(dev);
+	if (err)
+		goto out;
+
+	err = pciback_config_quirks_init(dev);
+
+      out:
+	return err;
+}
+
+int pciback_config_init(void)
+{
+	return pciback_config_capability_init();
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/xenbus.c
@@ -0,0 +1,709 @@
+/*
+ * PCI Backend Xenbus Setup - handles setup with frontend and xend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <xen/xenbus.h>
+#include <xen/evtchn.h>
+#include "pciback.h"
+
+#define INVALID_EVTCHN_IRQ  (-1)
+struct workqueue_struct *pciback_wq;
+
+static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
+{
+	struct pciback_device *pdev;
+
+	pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
+	if (pdev == NULL)
+		goto out;
+	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
+
+	pdev->xdev = xdev;
+	dev_set_drvdata(&xdev->dev, pdev);
+
+	spin_lock_init(&pdev->dev_lock);
+
+	pdev->sh_area = NULL;
+	pdev->sh_info = NULL;
+	pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
+	pdev->be_watching = 0;
+
+	INIT_WORK(&pdev->op_work, pciback_do_op);
+
+	if (pciback_init_devices(pdev)) {
+		kfree(pdev);
+		pdev = NULL;
+	}
+      out:
+	return pdev;
+}
+
+static void pciback_disconnect(struct pciback_device *pdev)
+{
+	spin_lock(&pdev->dev_lock);
+
+	/* Ensure the guest can't trigger our handler before removing devices */
+	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
+	 * before releasing the shared memory */
+	flush_workqueue(pciback_wq);
+
+	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);
+
+	dev_set_drvdata(&pdev->xdev->dev, NULL);
+	pdev->xdev = NULL;
+
+	kfree(pdev);
+}
+
+static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
+			     int remote_evtchn)
+{
+	int err = 0;
+	struct vm_struct *area;
+
+	dev_dbg(&pdev->xdev->dev,
+		"Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
+		gnt_ref, remote_evtchn);
+
+	area = xenbus_map_ring_valloc(pdev->xdev, gnt_ref);
+	if (IS_ERR(area)) {
+		err = PTR_ERR(area);
+		goto out;
+	}
+	pdev->sh_area = area;
+	pdev->sh_info = area->addr;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
+		IRQF_SAMPLE_RANDOM, "pciback", pdev);
+	if (err < 0) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error binding event channel to IRQ");
+		goto out;
+	}
+	pdev->evtchn_irq = err;
+	err = 0;
+
+	dev_dbg(&pdev->xdev->dev, "Attached!\n");
+      out:
+	return err;
+}
+
+static int pciback_attach(struct pciback_device *pdev)
+{
+	int err = 0;
+	int gnt_ref, remote_evtchn;
+	char *magic = NULL;
+
+	spin_lock(&pdev->dev_lock);
+
+	/* Make sure we only do this setup once */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	/* Wait for frontend to state that it has published the configuration */
+	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
+
+	err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
+			    "pci-op-ref", "%u", &gnt_ref,
+			    "event-channel", "%u", &remote_evtchn,
+			    "magic", NULL, &magic, NULL);
+	if (err) {
+		/* If configuration didn't get read correctly, wait longer */
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error reading configuration from frontend");
+		goto out;
+	}
+
+	if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
+		xenbus_dev_fatal(pdev->xdev, -EFAULT,
+				 "version mismatch (%s/%s) with pcifront - "
+				 "halting pciback",
+				 magic, XEN_PCI_MAGIC);
+		goto out;
+	}
+
+	err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
+	if (err)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "Connecting...\n");
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+	if (err)
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error switching to connected state!");
+
+	dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
+      out:
+	spin_unlock(&pdev->dev_lock);
+
+	if (magic)
+		kfree(magic);
+
+	return err;
+}
+
+static int pciback_publish_pci_dev(struct pciback_device *pdev,
+				   unsigned int domain, unsigned int bus,
+				   unsigned int devfn, unsigned int devid)
+{
+	int err;
+	int len;
+	char str[64];
+
+	len = snprintf(str, sizeof(str), "vdev-%d", devid);
+	if (unlikely(len >= (sizeof(str) - 1))) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+			    "%04x:%02x:%02x.%02x", domain, bus,
+			    PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+      out:
+	return err;
+}
+
+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;
+
+	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,
+				    unsigned int domain, unsigned int bus)
+{
+	unsigned int d, b;
+	int i, root_num, len, err;
+	char str[64];
+
+	dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+			   "root_num", "%d", &root_num);
+	if (err == 0 || err == -ENOENT)
+		root_num = 0;
+	else if (err < 0)
+		goto out;
+
+	/* Verify that we haven't already published this pci root */
+	for (i = 0; i < root_num; 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->nodename,
+				   str, "%x:%x", &d, &b);
+		if (err < 0)
+			goto out;
+		if (err != 2) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		if (d == domain && b == bus) {
+			err = 0;
+			goto out;
+		}
+	}
+
+	len = snprintf(str, sizeof(str), "root-%d", root_num);
+	if (unlikely(len >= (sizeof(str) - 1))) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
+		root_num, domain, bus);
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+			    "%04x:%02x", domain, bus);
+	if (err)
+		goto out;
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
+			    "root_num", "%d", (root_num + 1));
+
+      out:
+	return err;
+}
+
+static int pciback_reconfigure(struct pciback_device *pdev)
+{
+	int err = 0;
+	int num_devs;
+	int domain, bus, slot, func;
+	int substate;
+	int i, len;
+	char state_str[64];
+	char dev_str[64];
+
+	spin_lock(&pdev->dev_lock);
+
+	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,
+				 "Error reading number of devices");
+		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;
+
+		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:
+	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 = dev_get_drvdata(&xdev->dev);
+
+	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)
+{
+	/* Get configuration from xend (if available now) */
+	int domain, bus, slot, func;
+	int err = 0;
+	int i, num_devs;
+	char dev_str[64];
+	char state_str[64];
+
+	spin_lock(&pdev->dev_lock);
+
+	/* It's possible we could get the call to setup twice, so make sure
+	 * we're not already connected.
+	 */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitWait)
+		goto out;
+
+	dev_dbg(&pdev->xdev->dev, "getting be setup\n");
+
+	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,
+				 "Error reading number of devices");
+		goto out;
+	}
+
+	for (i = 0; i < num_devs; i++) {
+		int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
+		if (unlikely(l >= (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;
+
+		/* 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);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error while publish PCI root buses "
+				 "for frontend");
+		goto out;
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
+	if (err)
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error switching to initialised state!");
+
+      out:
+	spin_unlock(&pdev->dev_lock);
+
+	if (!err)
+		/* see if pcifront is already configured (if not, we'll wait) */
+		pciback_attach(pdev);
+
+	return err;
+}
+
+static void pciback_be_watch(struct xenbus_watch *watch,
+			     const char **vec, unsigned int len)
+{
+	struct pciback_device *pdev =
+	    container_of(watch, struct pciback_device, be_watch);
+
+	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
+	case XenbusStateInitWait:
+		pciback_setup_backend(pdev);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int pciback_xenbus_probe(struct xenbus_device *dev,
+				const struct xenbus_device_id *id)
+{
+	int err = 0;
+	struct pciback_device *pdev = alloc_pdev(dev);
+
+	if (pdev == NULL) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(dev, err,
+				 "Error allocating pciback_device struct");
+		goto out;
+	}
+
+	/* wait for xend to configure us */
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto out;
+
+	/* watch the backend node for backend configuration information */
+	err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
+				pciback_be_watch);
+	if (err)
+		goto out;
+	pdev->be_watching = 1;
+
+	/* We need to force a call to our callback here in case
+	 * xend already configured us!
+	 */
+	pciback_be_watch(&pdev->be_watch, NULL, 0);
+
+      out:
+	return err;
+}
+
+static int pciback_xenbus_remove(struct xenbus_device *dev)
+{
+	struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
+
+	if (pdev != NULL)
+		free_pdev(pdev);
+
+	return 0;
+}
+
+static const struct xenbus_device_id xenpci_ids[] = {
+	{"pci"},
+	{{0}},
+};
+
+static struct xenbus_driver xenbus_pciback_driver = {
+	.name 			= "pciback",
+	.ids 			= xenpci_ids,
+	.probe 			= pciback_xenbus_probe,
+	.remove 		= pciback_xenbus_remove,
+	.otherend_changed 	= pciback_frontend_changed,
+};
+
+int __init pciback_xenbus_register(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+	pciback_wq = create_workqueue("pciback_workqueue");
+	if (!pciback_wq) {
+		printk(KERN_ERR "pciback_xenbus_register: create"
+			"pciback_workqueue failed\n");
+		return -EFAULT;
+	}
+	return xenbus_register_backend(&xenbus_pciback_driver);
+}
+
+void __exit pciback_xenbus_unregister(void)
+{
+	destroy_workqueue(pciback_wq);
+	xenbus_unregister_driver(&xenbus_pciback_driver);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_capability_vpd.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_capability_vpd.c
@@ -0,0 +1,40 @@
+/*
+ * PCI Backend - Configuration space overlay for Vital Product Data
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/pci.h>
+#include "conf_space.h"
+#include "conf_space_capability.h"
+
+static int vpd_address_write(struct pci_dev *dev, int offset, u16 value,
+			     void *data)
+{
+	/* Disallow writes to the vital product data */
+	if (value & PCI_VPD_ADDR_F)
+		return PCIBIOS_SET_FAILED;
+	else
+		return pci_write_config_word(dev, offset, value);
+}
+
+static const struct config_field caplist_vpd[] = {
+	{
+	 .offset    = PCI_VPD_ADDR,
+	 .size      = 2,
+	 .u.w.read  = pciback_read_config_word,
+	 .u.w.write = vpd_address_write,
+	 },
+	{
+	 .offset     = PCI_VPD_DATA,
+	 .size       = 4,
+	 .u.dw.read  = pciback_read_config_dword,
+	 .u.dw.write = NULL,
+	 },
+	{}
+};
+ 
+struct pciback_config_capability pciback_config_capability_vpd = {
+	.capability = PCI_CAP_ID_VPD,
+	.fields = caplist_vpd,
+};
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_capability_pm.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_capability_pm.c
@@ -0,0 +1,126 @@
+/*
+ * PCI Backend - Configuration space overlay for power management
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/pci.h>
+#include "conf_space.h"
+#include "conf_space_capability.h"
+
+static int pm_caps_read(struct pci_dev *dev, int offset, u16 *value,
+			void *data)
+{
+	int err;
+	u16 real_value;
+
+	err = pci_read_config_word(dev, offset, &real_value);
+	if (err)
+		goto out;
+
+	*value = real_value & ~PCI_PM_CAP_PME_MASK;
+
+      out:
+	return err;
+}
+
+/* PM_OK_BITS specifies the bits that the driver domain is allowed to change.
+ * Can't allow driver domain to enable PMEs - they're shared */
+#define PM_OK_BITS (PCI_PM_CTRL_PME_STATUS|PCI_PM_CTRL_DATA_SEL_MASK)
+
+static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
+			 void *data)
+{
+	int err;
+	u16 old_value;
+	pci_power_t new_state, old_state;
+
+	err = pci_read_config_word(dev, offset, &old_value);
+	if (err)
+		goto out;
+
+	old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
+	new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
+
+	new_value &= PM_OK_BITS;
+	if ((old_value & PM_OK_BITS) != new_value) {
+		new_value = (old_value & ~PM_OK_BITS) | new_value;
+		err = pci_write_config_word(dev, offset, new_value);
+		if (err)
+			goto out;
+	}
+
+	/* Let pci core handle the power management change */
+	dev_dbg(&dev->dev, "set power state to %x\n", new_state);
+	err = pci_set_power_state(dev, new_state);
+	if (err) {
+		err = PCIBIOS_SET_FAILED;
+		goto out;
+	}
+
+	/*
+	 * Device may lose PCI config info on D3->D0 transition. This
+	 * is a problem for some guests which will not reset BARs. Even
+	 * those that have a go will be foiled by our BAR-write handler
+	 * which will discard the write! Since Linux won't re-init
+	 * the config space automatically in all cases, we do it here.
+	 * Future: Should we re-initialise all first 64 bytes of config space?
+	 */
+	if (new_state == PCI_D0 &&
+	    (old_state == PCI_D3hot || old_state == PCI_D3cold) &&
+	    !(old_value & PCI_PM_CTRL_NO_SOFT_RESET))
+		pci_restore_bars(dev);
+
+ out:
+	return err;
+}
+
+/* Ensure PMEs are disabled */
+static void *pm_ctrl_init(struct pci_dev *dev, int offset)
+{
+	int err;
+	u16 value;
+
+	err = pci_read_config_word(dev, offset, &value);
+	if (err)
+		goto out;
+
+	if (value & PCI_PM_CTRL_PME_ENABLE) {
+		value &= ~PCI_PM_CTRL_PME_ENABLE;
+		err = pci_write_config_word(dev, offset, value);
+	}
+
+      out:
+	return ERR_PTR(err);
+}
+
+static const struct config_field caplist_pm[] = {
+	{
+		.offset     = PCI_PM_PMC,
+		.size       = 2,
+		.u.w.read   = pm_caps_read,
+	},
+	{
+		.offset     = PCI_PM_CTRL,
+		.size       = 2,
+		.init       = pm_ctrl_init,
+		.u.w.read   = pciback_read_config_word,
+		.u.w.write  = pm_ctrl_write,
+	},
+	{
+		.offset     = PCI_PM_PPB_EXTENSIONS,
+		.size       = 1,
+		.u.b.read   = pciback_read_config_byte,
+	},
+	{
+		.offset     = PCI_PM_DATA_REGISTER,
+		.size       = 1,
+		.u.b.read   = pciback_read_config_byte,
+	},
+	{}
+};
+
+struct pciback_config_capability pciback_config_capability_pm = {
+	.capability = PCI_CAP_ID_PM,
+	.fields = caplist_pm,
+};
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_quirks.h
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_quirks.h
@@ -0,0 +1,35 @@
+/*
+ * PCI Backend - Data structures for special overlays for broken devices.
+ *
+ * Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+
+#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
+
+#include <linux/pci.h>
+#include <linux/list.h>
+
+struct pciback_config_quirk {
+	struct list_head quirks_list;
+	struct pci_device_id devid;
+	struct pci_dev *pdev;
+};
+
+struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev);
+
+int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
+				    *field);
+
+int pciback_config_quirks_remove_field(struct pci_dev *dev, int reg);
+
+int pciback_config_quirks_init(struct pci_dev *dev);
+
+void pciback_config_field_free(struct config_field *field);
+
+int pciback_config_quirk_release(struct pci_dev *dev);
+
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_capability.h
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_capability.h
@@ -0,0 +1,23 @@
+/*
+ * PCI Backend - Data structures for special overlays for structures on
+ *               the capability list.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#ifndef __PCIBACK_CONFIG_CAPABILITY_H__
+#define __PCIBACK_CONFIG_CAPABILITY_H__
+
+#include <linux/pci.h>
+#include <linux/list.h>
+
+struct pciback_config_capability {
+	struct list_head cap_list;
+
+	int capability;
+
+	/* If the device has the capability found above, add these fields */
+	const struct config_field *fields;
+};
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/passthrough.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/passthrough.c
@@ -0,0 +1,176 @@
+/*
+ * PCI Backend - Provides restricted access to the real PCI bus topology
+ *               to the frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+struct passthrough_dev_data {
+	/* Access to dev_list must be protected by lock */
+	struct list_head dev_list;
+	spinlock_t lock;
+};
+
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
+				    unsigned int domain, unsigned int bus,
+				    unsigned int devfn)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry;
+	struct pci_dev *dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
+		if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
+		    && bus == (unsigned int)dev_entry->dev->bus->number
+		    && devfn == dev_entry->dev->devfn) {
+			dev = dev_entry->dev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	return 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)
+		return -ENOMEM;
+	dev_entry->dev = dev;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+	list_add_tail(&dev_entry->list, &dev_data->dev_list);
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	/* 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)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *t;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
+		if (dev_entry->dev == dev) {
+			list_del(&dev_entry->list);
+			found_dev = dev_entry->dev;
+			kfree(dev_entry);
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	if (found_dev)
+		pcistub_put_pci_dev(found_dev);
+}
+
+int pciback_init_devices(struct pciback_device *pdev)
+{
+	struct passthrough_dev_data *dev_data;
+
+	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	spin_lock_init(&dev_data->lock);
+
+	INIT_LIST_HEAD(&dev_data->dev_list);
+
+	pdev->pci_dev_data = dev_data;
+
+	return 0;
+}
+
+int pciback_publish_pci_roots(struct pciback_device *pdev,
+			      publish_pci_root_cb publish_root_cb)
+{
+	int err = 0;
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *e;
+	struct pci_dev *dev;
+	int found;
+	unsigned int domain, bus;
+
+	spin_lock(&dev_data->lock);
+
+	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
+		/* Only publish this device as a root if none of its
+		 * parent bridges are exported
+		 */
+		found = 0;
+		dev = dev_entry->dev->bus->self;
+		for (; !found && dev != NULL; dev = dev->bus->self) {
+			list_for_each_entry(e, &dev_data->dev_list, list) {
+				if (dev == e->dev) {
+					found = 1;
+					break;
+				}
+			}
+		}
+
+		domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus);
+		bus = (unsigned int)dev_entry->dev->bus->number;
+
+		if (!found) {
+			err = publish_root_cb(pdev, domain, bus);
+			if (err)
+				break;
+		}
+	}
+
+	spin_unlock(&dev_data->lock);
+
+	return err;
+}
+
+void pciback_release_devices(struct pciback_device *pdev)
+{
+	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
+	struct pci_dev_entry *dev_entry, *t;
+
+	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
+		list_del(&dev_entry->list);
+		pcistub_put_pci_dev(dev_entry->dev);
+		kfree(dev_entry);
+	}
+
+	kfree(dev_data);
+	pdev->pci_dev_data = NULL;
+}
+
+int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
+		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
+
+{
+	*domain = pci_domain_nr(pcidev->bus);
+	*bus = pcidev->bus->number;
+	*devfn = pcidev->devfn;
+	return 1;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/controller.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/controller.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *      Alex Williamson <alex.williamson@hp.com>
+ *
+ * PCI "Controller" Backend - virtualize PCI bus topology based on PCI
+ * controllers.  Devices under the same PCI controller are exposed on the
+ * same virtual domain:bus.  Within a bus, device slots are virtualized
+ * to compact the bus.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * 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/acpi.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+#define PCI_MAX_BUSSES	255
+#define PCI_MAX_SLOTS	32
+
+struct controller_dev_entry {
+	struct list_head list;
+	struct pci_dev *dev;
+	unsigned int devfn;
+};
+
+struct controller_list_entry {
+	struct list_head list;
+	struct pci_controller *controller;
+	unsigned int domain;
+	unsigned int bus;
+	unsigned int next_devfn;
+	struct list_head dev_list;
+};
+
+struct controller_dev_data {
+	struct list_head list;
+	unsigned int next_domain;
+	unsigned int next_bus;
+	spinlock_t lock;
+};
+
+struct walk_info {
+	struct pciback_device *pdev;
+	int resource_count;
+	int root_num;
+};
+
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
+				    unsigned int domain, unsigned int bus,
+				    unsigned int devfn)
+{
+	struct controller_dev_data *dev_data = pdev->pci_dev_data;
+	struct controller_dev_entry *dev_entry;
+	struct controller_list_entry *cntrl_entry;
+	struct pci_dev *dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
+		if (cntrl_entry->domain != domain ||
+		    cntrl_entry->bus != bus)
+			continue;
+
+		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
+			if (devfn == dev_entry->devfn) {
+				dev = dev_entry->dev;
+				goto found;
+			}
+		}
+	}
+found:
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	return 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;
+	struct controller_list_entry *cntrl_entry;
+	struct pci_controller *dev_controller = PCI_CONTROLLER(dev);
+	unsigned long flags;
+	int ret = 0, found = 0;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	/* Look to see if we already have a domain:bus for this controller */
+	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
+		if (cntrl_entry->controller == dev_controller) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		cntrl_entry = kmalloc(sizeof(*cntrl_entry), GFP_ATOMIC);
+		if (!cntrl_entry) {
+			ret =  -ENOMEM;
+			goto out;
+		}
+
+		cntrl_entry->controller = dev_controller;
+		cntrl_entry->next_devfn = PCI_DEVFN(0, 0);
+
+		cntrl_entry->domain = dev_data->next_domain;
+		cntrl_entry->bus = dev_data->next_bus++;
+		if (dev_data->next_bus > PCI_MAX_BUSSES) {
+			dev_data->next_domain++;
+			dev_data->next_bus = 0;
+		}
+
+		INIT_LIST_HEAD(&cntrl_entry->dev_list);
+
+		list_add_tail(&cntrl_entry->list, &dev_data->list);
+	}
+
+	if (PCI_SLOT(cntrl_entry->next_devfn) > PCI_MAX_SLOTS) {
+		/*
+		 * While it seems unlikely, this can actually happen if
+		 * a controller has P2P bridges under it.
+		 */
+		xenbus_dev_fatal(pdev->xdev, -ENOSPC, "Virtual bus %04x:%02x "
+				 "is full, no room to export %04x:%02x:%02x.%x",
+				 cntrl_entry->domain, cntrl_entry->bus,
+				 pci_domain_nr(dev->bus), dev->bus->number,
+				 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	dev_entry = kmalloc(sizeof(*dev_entry), GFP_ATOMIC);
+	if (!dev_entry) {
+		if (list_empty(&cntrl_entry->dev_list)) {
+			list_del(&cntrl_entry->list);
+			kfree(cntrl_entry);
+		}
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	dev_entry->dev = dev;
+	dev_entry->devfn = cntrl_entry->next_devfn;
+
+	list_add_tail(&dev_entry->list, &cntrl_entry->dev_list);
+
+	cntrl_entry->next_devfn += PCI_DEVFN(1, 0);
+
+out:
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+
+	/* TODO: Publish virtual domain:bus:slot.func here. */
+
+	return ret;
+}
+
+void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
+{
+	struct controller_dev_data *dev_data = pdev->pci_dev_data;
+	struct controller_list_entry *cntrl_entry;
+	struct controller_dev_entry *dev_entry = NULL;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
+		if (cntrl_entry->controller != PCI_CONTROLLER(dev))
+			continue;
+
+		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
+			if (dev_entry->dev == dev) {
+				found_dev = dev_entry->dev;
+				break;
+			}
+		}
+	}
+
+	if (!found_dev) {
+		spin_unlock_irqrestore(&dev_data->lock, flags);
+		return;
+	}
+
+	list_del(&dev_entry->list);
+	kfree(dev_entry);
+
+	if (list_empty(&cntrl_entry->dev_list)) {
+		list_del(&cntrl_entry->list);
+		kfree(cntrl_entry);
+	}
+
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+	pcistub_put_pci_dev(found_dev);
+}
+
+int pciback_init_devices(struct pciback_device *pdev)
+{
+	struct controller_dev_data *dev_data;
+
+	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	spin_lock_init(&dev_data->lock);
+
+	INIT_LIST_HEAD(&dev_data->list);
+
+	/* Starting domain:bus numbers */
+	dev_data->next_domain = 0;
+	dev_data->next_bus = 0;
+
+	pdev->pci_dev_data = dev_data;
+
+	return 0;
+}
+
+static acpi_status write_xenbus_resource(struct acpi_resource *res, void *data)
+{
+	struct walk_info *info = data;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+	int i, len, err;
+	char str[32], tmp[3];
+	unsigned char *ptr, *buf;
+
+	status = acpi_resource_to_address64(res, &addr);
+
+	/* Do we care about this range?  Let's check. */
+	if (!ACPI_SUCCESS(status) ||
+	    !(addr.resource_type == ACPI_MEMORY_RANGE ||
+	      addr.resource_type == ACPI_IO_RANGE) ||
+	    !addr.address_length || addr.producer_consumer != ACPI_PRODUCER)
+		return AE_OK;
+
+	/*
+	 * Furthermore, we really only care to tell the guest about
+	 * address ranges that require address translation of some sort.
+	 */
+	if (!(addr.resource_type == ACPI_MEMORY_RANGE &&
+	      addr.info.mem.translation) &&
+	    !(addr.resource_type == ACPI_IO_RANGE &&
+	      addr.info.io.translation))
+		return AE_OK;
+	   
+	/* Store the resource in xenbus for the guest */
+	len = snprintf(str, sizeof(str), "root-%d-resource-%d",
+		       info->root_num, info->resource_count);
+	if (unlikely(len >= (sizeof(str) - 1)))
+		return AE_OK;
+
+	buf = kzalloc((sizeof(*res) * 2) + 1, GFP_KERNEL);
+	if (!buf)
+		return AE_OK;
+
+	/* Clean out resource_source */
+	res->data.address64.resource_source.index = 0xFF;
+	res->data.address64.resource_source.string_length = 0;
+	res->data.address64.resource_source.string_ptr = NULL;
+
+	ptr = (unsigned char *)res;
+
+	/* Turn the acpi_resource into an ASCII byte stream */
+	for (i = 0; i < sizeof(*res); i++) {
+		snprintf(tmp, sizeof(tmp), "%02x", ptr[i]);
+		strncat(buf, tmp, 2);
+	}
+
+	err = xenbus_printf(XBT_NIL, info->pdev->xdev->nodename,
+			    str, "%s", buf);
+
+	if (!err)
+		info->resource_count++;
+
+	kfree(buf);
+
+	return AE_OK;
+}
+
+int pciback_publish_pci_roots(struct pciback_device *pdev,
+			      publish_pci_root_cb publish_root_cb)
+{
+	struct controller_dev_data *dev_data = pdev->pci_dev_data;
+	struct controller_list_entry *cntrl_entry;
+	int i, root_num, len, err = 0;
+	unsigned int domain, bus;
+	char str[64];
+	struct walk_info info;
+
+	spin_lock(&dev_data->lock);
+
+	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
+		/* First publish all the domain:bus info */
+		err = publish_root_cb(pdev, cntrl_entry->domain,
+				      cntrl_entry->bus);
+		if (err)
+			goto out;
+
+		/*
+ 		 * Now figure out which root-%d this belongs to
+		 * so we can associate resources with it.
+		 */
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
+				   "root_num", "%d", &root_num);
+
+		if (err != 1)
+			goto out;
+
+		for (i = 0; i < root_num; 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->nodename,
+					   str, "%x:%x", &domain, &bus);
+			if (err != 2)
+				goto out;
+
+			/* Is this the one we just published? */
+			if (domain == cntrl_entry->domain &&
+			    bus == cntrl_entry->bus)
+				break;
+		}
+
+		if (i == root_num)
+			goto out;
+
+		info.pdev = pdev;
+		info.resource_count = 0;
+		info.root_num = i;
+
+		/* Let ACPI do the heavy lifting on decoding resources */
+		acpi_walk_resources(cntrl_entry->controller->acpi_handle,
+				    METHOD_NAME__CRS, write_xenbus_resource,
+				    &info);
+
+		/* No resouces.  OK.  On to the next one */
+		if (!info.resource_count)
+			continue;
+
+		/* Store the number of resources we wrote for this root-%d */
+		len = snprintf(str, sizeof(str), "root-%d-resources", i);
+		if (unlikely(len >= (sizeof(str) - 1))) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+				    "%d", info.resource_count);
+		if (err)
+			goto out;
+	}
+
+	/* Finally, write some magic to synchronize with the guest. */
+	len = snprintf(str, sizeof(str), "root-resource-magic");
+	if (unlikely(len >= (sizeof(str) - 1))) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
+			    "%lx", (sizeof(struct acpi_resource) * 2) + 1);
+
+out:
+	spin_unlock(&dev_data->lock);
+
+	return err;
+}
+
+void pciback_release_devices(struct pciback_device *pdev)
+{
+	struct controller_dev_data *dev_data = pdev->pci_dev_data;
+	struct controller_list_entry *cntrl_entry, *c;
+	struct controller_dev_entry *dev_entry, *d;
+
+	list_for_each_entry_safe(cntrl_entry, c, &dev_data->list, list) {
+		list_for_each_entry_safe(dev_entry, d,
+					 &cntrl_entry->dev_list, list) {
+			list_del(&dev_entry->list);
+			pcistub_put_pci_dev(dev_entry->dev);
+			kfree(dev_entry);
+		}
+		list_del(&cntrl_entry->list);
+		kfree(cntrl_entry);
+	}
+
+	kfree(dev_data);
+	pdev->pci_dev_data = NULL;
+}
+
+int pciback_get_pcifront_dev(struct pci_dev *pcidev, 
+		struct pciback_device *pdev, 
+		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
+{
+	struct controller_dev_data *dev_data = pdev->pci_dev_data;
+	struct controller_dev_entry *dev_entry;
+	struct controller_list_entry *cntrl_entry;
+	unsigned long flags;
+	int found = 0;
+	spin_lock_irqsave(&dev_data->lock, flags);
+
+	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
+		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
+			if ( (dev_entry->dev->bus->number == 
+					pcidev->bus->number) &&
+			  	(dev_entry->dev->devfn ==
+					pcidev->devfn) &&
+				(pci_domain_nr(dev_entry->dev->bus) ==
+					pci_domain_nr(pcidev->bus)))
+			{
+				found = 1;
+				*domain = cntrl_entry->domain;
+				*bus = cntrl_entry->bus;
+				*devfn = dev_entry->devfn;
+				goto out;
+			}
+		}
+	}
+out:
+	spin_unlock_irqrestore(&dev_data->lock, flags);
+	return found;
+
+}
+
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/vpci.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/vpci.c
@@ -0,0 +1,242 @@
+/*
+ * PCI Backend - Provides a Virtual PCI bus (with real devices)
+ *               to the frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pciback.h"
+
+#define PCI_SLOT_MAX 32
+
+struct vpci_dev_data {
+	/* Access to dev_list must be protected by lock */
+	struct list_head dev_list[PCI_SLOT_MAX];
+	spinlock_t lock;
+};
+
+static inline struct list_head *list_first(struct list_head *head)
+{
+	return head->next;
+}
+
+struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
+				    unsigned int domain, unsigned int bus,
+				    unsigned int devfn)
+{
+	struct pci_dev_entry *entry;
+	struct pci_dev *dev = NULL;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+
+	if (domain != 0 || bus != 0)
+		return NULL;
+
+	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
+		spin_lock_irqsave(&vpci_dev->lock, flags);
+
+		list_for_each_entry(entry,
+				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
+				    list) {
+			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
+				dev = entry->dev;
+				break;
+			}
+		}
+
+		spin_unlock_irqrestore(&vpci_dev->lock, flags);
+	}
+	return dev;
+}
+
+static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
+{
+	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
+	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
+		return 1;
+
+	return 0;
+}
+
+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, func;
+	struct pci_dev_entry *t, *dev_entry;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+
+	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
+		err = -EFAULT;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Can't export bridges on the virtual PCI bus");
+		goto out;
+	}
+
+	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
+	if (!dev_entry) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error adding entry to virtual PCI bus");
+		goto out;
+	}
+
+	dev_entry->dev = dev;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+
+	/* Keep multi-function devices together on the virtual PCI bus */
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		if (!list_empty(&vpci_dev->dev_list[slot])) {
+			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
+				       struct pci_dev_entry, list);
+
+			if (match_slot(dev, t->dev)) {
+				pr_info("pciback: vpci: %s: "
+					"assign to virtual slot %d func %d\n",
+					pci_name(dev), slot,
+					PCI_FUNC(dev->devfn));
+				list_add_tail(&dev_entry->list,
+					      &vpci_dev->dev_list[slot]);
+				func = PCI_FUNC(dev->devfn);
+				goto unlock;
+			}
+		}
+	}
+
+	/* Assign to a new slot on the virtual PCI bus */
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		if (list_empty(&vpci_dev->dev_list[slot])) {
+			printk(KERN_INFO
+			       "pciback: vpci: %s: assign to virtual slot %d\n",
+			       pci_name(dev), slot);
+			list_add_tail(&dev_entry->list,
+				      &vpci_dev->dev_list[slot]);
+			func = PCI_FUNC(dev->devfn);
+			goto unlock;
+		}
+	}
+
+	err = -ENOMEM;
+	xenbus_dev_fatal(pdev->xdev, err,
+			 "No more space on root virtual PCI bus");
+
+      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;
+}
+
+void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		struct pci_dev_entry *e, *tmp;
+		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
+					 list) {
+			if (e->dev == dev) {
+				list_del(&e->list);
+				found_dev = e->dev;
+				kfree(e);
+				goto out;
+			}
+		}
+	}
+
+      out:
+	spin_unlock_irqrestore(&vpci_dev->lock, flags);
+
+	if (found_dev)
+		pcistub_put_pci_dev(found_dev);
+}
+
+int pciback_init_devices(struct pciback_device *pdev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev;
+
+	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
+	if (!vpci_dev)
+		return -ENOMEM;
+
+	spin_lock_init(&vpci_dev->lock);
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
+	}
+
+	pdev->pci_dev_data = vpci_dev;
+
+	return 0;
+}
+
+int pciback_publish_pci_roots(struct pciback_device *pdev,
+			      publish_pci_root_cb publish_cb)
+{
+	/* The Virtual PCI bus has only one root */
+	return publish_cb(pdev, 0, 0);
+}
+
+void pciback_release_devices(struct pciback_device *pdev)
+{
+	int slot;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		struct pci_dev_entry *e, *tmp;
+		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
+					 list) {
+			list_del(&e->list);
+			pcistub_put_pci_dev(e->dev);
+			kfree(e);
+		}
+	}
+
+	kfree(vpci_dev);
+	pdev->pci_dev_data = NULL;
+}
+
+int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
+		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
+{
+	struct pci_dev_entry *entry;
+	struct pci_dev *dev = NULL;
+	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
+	unsigned long flags;
+	int found = 0, slot;
+
+	spin_lock_irqsave(&vpci_dev->lock, flags);
+	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+		list_for_each_entry(entry,
+			    &vpci_dev->dev_list[slot],
+			    list) {
+			dev = entry->dev;
+			if (dev && dev->bus->number == pcidev->bus->number
+				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)
+				&& dev->devfn == pcidev->devfn)
+			{
+				found = 1;
+				*domain = 0;
+				*bus = 0;
+				*devfn = PCI_DEVFN(slot, PCI_FUNC(pcidev->devfn));
+			}
+		}		
+	}
+	spin_unlock_irqrestore(&vpci_dev->lock, flags);
+	return found;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/pci_stub.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/pci_stub.c
@@ -0,0 +1,1316 @@
+/*
+ * PCI Stub Driver - Grabs devices in backend to be exported later
+ *
+ * Ryan Wilson <hap9@epoch.ncsc.mil>
+ * Chris Bookholt <hap10@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rwsem.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <xen/evtchn.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_quirks.h"
+
+static char *pci_devs_to_hide = NULL;
+wait_queue_head_t aer_wait_queue;
+/*Add sem for sync AER handling and pciback remove/reconfigue ops,
+* We want to avoid in middle of AER ops, pciback devices is being removed
+*/
+static DECLARE_RWSEM(pcistub_sem);
+module_param_named(hide, pci_devs_to_hide, charp, 0444);
+
+struct pcistub_device_id {
+	struct list_head slot_list;
+	int domain;
+	unsigned char bus;
+	unsigned int devfn;
+};
+static LIST_HEAD(pcistub_device_ids);
+static DEFINE_SPINLOCK(device_ids_lock);
+
+struct pcistub_device {
+	struct kref kref;
+	struct list_head dev_list;
+	spinlock_t lock;
+
+	struct pci_dev *dev;
+	struct pciback_device *pdev;	/* non-NULL if struct pci_dev is in use */
+};
+
+/* Access to pcistub_devices & seized_devices lists and the initialize_devices
+ * flag must be locked with pcistub_devices_lock
+ */
+static DEFINE_SPINLOCK(pcistub_devices_lock);
+static LIST_HEAD(pcistub_devices);
+
+/* wait for device_initcall before initializing our devices
+ * (see pcistub_init_devices_late)
+ */
+static int initialize_devices = 0;
+static LIST_HEAD(seized_devices);
+
+static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+
+	dev_dbg(&dev->dev, "pcistub_device_alloc\n");
+
+	psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
+	if (!psdev)
+		return NULL;
+
+	psdev->dev = pci_dev_get(dev);
+	if (!psdev->dev) {
+		kfree(psdev);
+		return NULL;
+	}
+
+	kref_init(&psdev->kref);
+	spin_lock_init(&psdev->lock);
+
+	return psdev;
+}
+
+/* Don't call this directly as it's called by pcistub_device_put */
+static void pcistub_device_release(struct kref *kref)
+{
+	struct pcistub_device *psdev;
+
+	psdev = container_of(kref, struct pcistub_device, kref);
+
+	dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
+
+	/* Clean-up the device */
+	pciback_reset_device(psdev->dev);
+	pciback_config_free_dyn_fields(psdev->dev);
+	pciback_config_free_dev(psdev->dev);
+	kfree(pci_get_drvdata(psdev->dev));
+	pci_set_drvdata(psdev->dev, NULL);
+
+	pci_dev_put(psdev->dev);
+
+	kfree(psdev);
+}
+
+static inline void pcistub_device_get(struct pcistub_device *psdev)
+{
+	kref_get(&psdev->kref);
+}
+
+static inline void pcistub_device_put(struct pcistub_device *psdev)
+{
+	kref_put(&psdev->kref, pcistub_device_release);
+}
+
+static struct pcistub_device *pcistub_device_find(int domain, int bus,
+						  int slot, int func)
+{
+	struct pcistub_device *psdev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev != NULL
+		    && domain == pci_domain_nr(psdev->dev->bus)
+		    && bus == psdev->dev->bus->number
+		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+			pcistub_device_get(psdev);
+			goto out;
+		}
+	}
+
+	/* didn't find it */
+	psdev = NULL;
+
+      out:
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return psdev;
+}
+
+static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
+						  struct pcistub_device *psdev)
+{
+	struct pci_dev *pci_dev = NULL;
+	unsigned long flags;
+
+	pcistub_device_get(psdev);
+
+	spin_lock_irqsave(&psdev->lock, flags);
+	if (!psdev->pdev) {
+		psdev->pdev = pdev;
+		pci_dev = psdev->dev;
+	}
+	spin_unlock_irqrestore(&psdev->lock, flags);
+
+	if (!pci_dev)
+		pcistub_device_put(psdev);
+
+	return pci_dev;
+}
+
+struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
+					    int domain, int bus,
+					    int slot, int func)
+{
+	struct pcistub_device *psdev;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev != NULL
+		    && domain == pci_domain_nr(psdev->dev->bus)
+		    && bus == psdev->dev->bus->number
+		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
+			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return found_dev;
+}
+
+struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
+				    struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	struct pci_dev *found_dev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return found_dev;
+}
+
+void pcistub_put_pci_dev(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev, *found_psdev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_psdev = psdev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	/*hold this lock for avoiding breaking link between
+	* pcistub and pciback when AER is in processing
+	*/
+	down_write(&pcistub_sem);
+	/* Cleanup our device
+	 * (so it's ready for the next domain)
+	 */
+	pciback_reset_device(found_psdev->dev);
+	pciback_config_free_dyn_fields(found_psdev->dev);
+	pciback_config_reset_dev(found_psdev->dev);
+
+	spin_lock_irqsave(&found_psdev->lock, flags);
+	found_psdev->pdev = NULL;
+	spin_unlock_irqrestore(&found_psdev->lock, flags);
+
+	pcistub_device_put(found_psdev);
+	up_write(&pcistub_sem);
+}
+
+static int __devinit pcistub_match_one(struct pci_dev *dev,
+				       struct pcistub_device_id *pdev_id)
+{
+	/* Match the specified device by domain, bus, slot, func and also if
+	 * any of the device's parent bridges match.
+	 */
+	for (; dev != NULL; dev = dev->bus->self) {
+		if (pci_domain_nr(dev->bus) == pdev_id->domain
+		    && dev->bus->number == pdev_id->bus
+		    && dev->devfn == pdev_id->devfn)
+			return 1;
+
+		/* Sometimes topmost bridge links to itself. */
+		if (dev == dev->bus->self)
+			break;
+	}
+
+	return 0;
+}
+
+static int __devinit pcistub_match(struct pci_dev *dev)
+{
+	struct pcistub_device_id *pdev_id;
+	unsigned long flags;
+	int found = 0;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
+		if (pcistub_match_one(dev, pdev_id)) {
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return found;
+}
+
+static int __devinit pcistub_init_device(struct pci_dev *dev)
+{
+	struct pciback_dev_data *dev_data;
+	int err = 0;
+
+	dev_dbg(&dev->dev, "initializing...\n");
+
+	/* The PCI backend is not intended to be a module (or to work with
+	 * removable PCI devices (yet). If it were, pciback_config_free()
+	 * would need to be called somewhere to free the memory allocated
+	 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
+	 */
+	dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
+	if (!dev_data) {
+		err = -ENOMEM;
+		goto out;
+	}
+	pci_set_drvdata(dev, dev_data);
+
+	dev_dbg(&dev->dev, "initializing config\n");
+
+	init_waitqueue_head(&aer_wait_queue);
+	err = pciback_config_init_dev(dev);
+	if (err)
+		goto out;
+
+	/* HACK: Force device (& ACPI) to determine what IRQ it's on - we
+	 * must do this here because pcibios_enable_device may specify
+	 * the pci device's true irq (and possibly its other resources)
+	 * if they differ from what's in the configuration space.
+	 * This makes the assumption that the device's resources won't
+	 * change after this point (otherwise this code may break!)
+	 */
+	dev_dbg(&dev->dev, "enabling device\n");
+	err = pci_enable_device(dev);
+	if (err)
+		goto config_release;
+
+	/* Now disable the device (this also ensures some private device
+	 * data is setup before we export)
+	 */
+	dev_dbg(&dev->dev, "reset device\n");
+	pciback_reset_device(dev);
+
+	return 0;
+
+      config_release:
+	pciback_config_free_dev(dev);
+
+      out:
+	pci_set_drvdata(dev, NULL);
+	kfree(dev_data);
+	return err;
+}
+
+/*
+ * Because some initialization still happens on
+ * devices during fs_initcall, we need to defer
+ * full initialization of our devices until
+ * device_initcall.
+ */
+static int __init pcistub_init_devices_late(void)
+{
+	struct pcistub_device *psdev;
+	unsigned long flags;
+	int err = 0;
+
+	pr_debug("pciback: pcistub_init_devices_late\n");
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	while (!list_empty(&seized_devices)) {
+		psdev = container_of(seized_devices.next,
+				     struct pcistub_device, dev_list);
+		list_del(&psdev->dev_list);
+
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		err = pcistub_init_device(psdev->dev);
+		if (err) {
+			dev_err(&psdev->dev->dev,
+				"error %d initializing device\n", err);
+			kfree(psdev);
+			psdev = NULL;
+		}
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+		if (psdev)
+			list_add_tail(&psdev->dev_list, &pcistub_devices);
+	}
+
+	initialize_devices = 1;
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	return 0;
+}
+
+static int __devinit pcistub_seize(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	unsigned long flags;
+	int err = 0;
+
+	psdev = pcistub_device_alloc(dev);
+	if (!psdev)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	if (initialize_devices) {
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		/* don't want irqs disabled when calling pcistub_init_device */
+		err = pcistub_init_device(psdev->dev);
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+		if (!err)
+			list_add(&psdev->dev_list, &pcistub_devices);
+	} else {
+		dev_dbg(&dev->dev, "deferring initialization\n");
+		list_add(&psdev->dev_list, &seized_devices);
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	if (err)
+		pcistub_device_put(psdev);
+
+	return err;
+}
+
+static int __devinit pcistub_probe(struct pci_dev *dev,
+				   const struct pci_device_id *id)
+{
+	int err = 0;
+
+	dev_dbg(&dev->dev, "probing...\n");
+
+	if (pcistub_match(dev)) {
+
+		if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
+		    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+			dev_err(&dev->dev, "can't export pci devices that "
+				"don't have a normal (0) or bridge (1) "
+				"header type!\n");
+			err = -ENODEV;
+			goto out;
+		}
+
+		dev_info(&dev->dev, "seizing device\n");
+		err = pcistub_seize(dev);
+#ifdef CONFIG_PCI_GUESTDEV
+	} else if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+		if (!pci_is_guestdev(dev)) {
+			err = -ENODEV;
+			goto out;
+		}
+
+		dev_info(&dev->dev, "seizing device\n");
+		err = pcistub_seize(dev);
+#endif /* CONFIG_PCI_GUESTDEV */
+	} else
+		/* Didn't find the device */
+		err = -ENODEV;
+
+      out:
+	return err;
+}
+
+static void pcistub_remove(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev, *found_psdev = NULL;
+	unsigned long flags;
+
+	dev_dbg(&dev->dev, "removing\n");
+
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+
+	pciback_config_quirk_release(dev);
+
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (psdev->dev == dev) {
+			found_psdev = psdev;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+	if (found_psdev) {
+		dev_dbg(&dev->dev, "found device to remove - in use? %p\n",
+			found_psdev->pdev);
+
+		if (found_psdev->pdev) {
+			printk(KERN_WARNING "pciback: ****** removing device "
+			       "%s while still in-use! ******\n",
+			       pci_name(found_psdev->dev));
+			printk(KERN_WARNING "pciback: ****** driver domain may "
+			       "still access this device's i/o resources!\n");
+			printk(KERN_WARNING "pciback: ****** shutdown driver "
+			       "domain before binding device\n");
+			printk(KERN_WARNING "pciback: ****** to other drivers "
+			       "or domains\n");
+
+			pciback_release_pci_dev(found_psdev->pdev,
+						found_psdev->dev);
+		}
+
+		spin_lock_irqsave(&pcistub_devices_lock, flags);
+		list_del(&found_psdev->dev_list);
+		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+
+		/* the final put for releasing from the list */
+		pcistub_device_put(found_psdev);
+	}
+}
+
+static const struct pci_device_id pcistub_ids[] = {
+	{
+	 .vendor = PCI_ANY_ID,
+	 .device = PCI_ANY_ID,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 },
+	{0,},
+};
+
+static void kill_domain_by_device(struct pcistub_device *psdev)
+{
+	struct xenbus_transaction xbt;
+	int err;
+	char nodename[1024];
+
+	if (!psdev) 
+		dev_err(&psdev->dev->dev,
+			"device is NULL when do AER recovery/kill_domain\n");
+	sprintf(nodename, "/local/domain/0/backend/pci/%d/0", 
+		psdev->pdev->xdev->otherend_id);
+	nodename[strlen(nodename)] = '\0';
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err)
+	{
+		dev_err(&psdev->dev->dev,
+			"error %d when start xenbus transaction\n", err);
+		return;
+	}
+	/*PV AER handlers will set this flag*/
+	xenbus_printf(xbt, nodename, "aerState" , "aerfail" );
+	err = xenbus_transaction_end(xbt, 0);
+	if (err)
+	{
+		if (err == -EAGAIN)
+			goto again;
+		dev_err(&psdev->dev->dev,
+			"error %d when end xenbus transaction\n", err);
+		return;
+	}
+}
+
+/* For each aer recovery step error_detected, mmio_enabled, etc, front_end and
+ * backend need to have cooperation. In pciback, those steps will do similar
+ * jobs: send service request and waiting for front_end response. 
+*/
+static pci_ers_result_t common_process(struct pcistub_device *psdev, 
+		pci_channel_state_t state, int aer_cmd, pci_ers_result_t result)
+{
+	pci_ers_result_t res = result;
+	struct xen_pcie_aer_op *aer_op;
+	int ret;
+
+	/*with PV AER drivers*/
+	aer_op = &(psdev->pdev->sh_info->aer_op);
+	aer_op->cmd = aer_cmd ;
+	/*useful for error_detected callback*/
+	aer_op->err = state;
+	/*pcifront_end BDF*/
+	ret = pciback_get_pcifront_dev(psdev->dev, psdev->pdev,
+		&aer_op->domain, &aer_op->bus, &aer_op->devfn);
+	if (!ret) {
+		dev_err(&psdev->dev->dev,
+			"pciback: failed to get pcifront device\n");
+		return PCI_ERS_RESULT_NONE; 
+	}
+	wmb();
+
+	dev_dbg(&psdev->dev->dev, 
+			"pciback: aer_op %x dom %x bus %x devfn %x\n",  
+			aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
+	/*local flag to mark there's aer request, pciback callback will use this
+	* flag to judge whether we need to check pci-front give aer service
+	* ack signal
+	*/
+	set_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
+
+	/*It is possible that a pcifront conf_read_write ops request invokes
+	* the callback which cause the spurious execution of wake_up. 
+	* Yet it is harmless and better than a spinlock here
+	*/
+	set_bit(_XEN_PCIB_active, 
+		(unsigned long *)&psdev->pdev->sh_info->flags);
+	wmb();
+	notify_remote_via_irq(psdev->pdev->evtchn_irq);
+
+	ret = wait_event_timeout(aer_wait_queue, !(test_bit(_XEN_PCIB_active,
+                (unsigned long *)&psdev->pdev->sh_info->flags)), 300*HZ);
+
+	if (!ret) {
+		if (test_bit(_XEN_PCIB_active, 
+			(unsigned long *)&psdev->pdev->sh_info->flags)) {
+			dev_err(&psdev->dev->dev, 
+				"pcifront aer process not responding!\n");
+			clear_bit(_XEN_PCIB_active,
+			  (unsigned long *)&psdev->pdev->sh_info->flags);
+			aer_op->err = PCI_ERS_RESULT_NONE;
+			return res;
+		}
+	}
+	clear_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
+
+	if ( test_bit( _XEN_PCIF_active,
+		(unsigned long*)&psdev->pdev->sh_info->flags)) {
+		dev_dbg(&psdev->dev->dev, 
+			"schedule pci_conf service in pciback \n");
+		test_and_schedule_op(psdev->pdev);
+	}
+
+	res = (pci_ers_result_t)aer_op->err;
+	return res;
+} 
+
+/*
+* pciback_slot_reset: it will send the slot_reset request to  pcifront in case
+* of the device driver could provide this service, and then wait for pcifront
+* ack.
+* @dev: pointer to PCI devices
+* return value is used by aer_core do_recovery policy
+*/
+static pci_ers_result_t pciback_slot_reset(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_RECOVERED;
+	dev_dbg(&dev->dev, "pciback_slot_reset(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if ( !psdev || !psdev->pdev )
+	{
+		dev_err(&dev->dev, 
+			"pciback device is not found/assigned\n");
+		goto end;
+	}
+
+	if ( !psdev->pdev->sh_info )
+	{
+		dev_err(&dev->dev, "pciback device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
+		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
+		dev_err(&dev->dev, 
+			"guest with no AER driver should have been killed\n");
+		goto release;
+	}
+	result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev, 
+			"No AER slot_reset service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+
+}
+
+
+/*pciback_mmio_enabled: it will send the mmio_enabled request to  pcifront 
+* in case of the device driver could provide this service, and then wait 
+* for pcifront ack.
+* @dev: pointer to PCI devices
+* return value is used by aer_core do_recovery policy
+*/
+
+static pci_ers_result_t pciback_mmio_enabled(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_RECOVERED;
+	dev_dbg(&dev->dev, "pciback_mmio_enabled(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if ( !psdev || !psdev->pdev )
+	{
+		dev_err(&dev->dev, 
+			"pciback device is not found/assigned\n");
+		goto end;
+	}
+
+	if ( !psdev->pdev->sh_info )
+	{
+		dev_err(&dev->dev, "pciback device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
+		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
+		dev_err(&dev->dev, 
+			"guest with no AER driver should have been killed\n");
+		goto release;
+	}
+	result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev, 
+			"No AER mmio_enabled service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+}
+
+/*pciback_error_detected: it will send the error_detected request to  pcifront 
+* in case of the device driver could provide this service, and then wait 
+* for pcifront ack.
+* @dev: pointer to PCI devices
+* @error: the current PCI connection state
+* return value is used by aer_core do_recovery policy
+*/
+
+static pci_ers_result_t pciback_error_detected(struct pci_dev *dev,
+	pci_channel_state_t error)
+{
+	struct pcistub_device *psdev;
+	pci_ers_result_t result;
+
+	result = PCI_ERS_RESULT_CAN_RECOVER;
+	dev_dbg(&dev->dev, "pciback_error_detected(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if ( !psdev || !psdev->pdev )
+	{
+		dev_err(&dev->dev, 
+			"pciback device is not found/assigned\n");
+		goto end;
+	}
+
+	if ( !psdev->pdev->sh_info )
+	{
+		dev_err(&dev->dev, "pciback device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	/*Guest owns the device yet no aer handler regiested, kill guest*/
+	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
+		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
+		dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+	result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
+
+	if (result == PCI_ERS_RESULT_NONE ||
+		result == PCI_ERS_RESULT_DISCONNECT) {
+		dev_dbg(&dev->dev, 
+			"No AER error_detected service or disconnected!\n");
+		kill_domain_by_device(psdev);
+	}
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return result;
+}
+
+/*pciback_error_resume: it will send the error_resume request to  pcifront 
+* in case of the device driver could provide this service, and then wait 
+* for pcifront ack.
+* @dev: pointer to PCI devices
+*/
+
+static void pciback_error_resume(struct pci_dev *dev)
+{
+	struct pcistub_device *psdev;
+
+	dev_dbg(&dev->dev, "pciback_error_resume(bus:%x,devfn:%x)\n",
+		dev->bus->number, dev->devfn);
+
+	down_write(&pcistub_sem);
+	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
+				dev->bus->number,
+				PCI_SLOT(dev->devfn),
+				PCI_FUNC(dev->devfn));
+
+	if ( !psdev || !psdev->pdev )
+	{
+		dev_err(&dev->dev, 
+			"pciback device is not found/assigned\n");
+		goto end;
+	}
+
+	if ( !psdev->pdev->sh_info )
+	{
+		dev_err(&dev->dev, "pciback device is not connected or owned"
+			" by HVM, kill it\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+
+	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
+		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
+		dev_err(&dev->dev, 
+			"guest with no AER driver should have been killed\n");
+		kill_domain_by_device(psdev);
+		goto release;
+	}
+	common_process(psdev, 1, XEN_PCI_OP_aer_resume, PCI_ERS_RESULT_RECOVERED);
+release:
+	pcistub_device_put(psdev);
+end:
+	up_write(&pcistub_sem);
+	return;
+}
+
+/*add pciback AER handling*/
+static struct pci_error_handlers pciback_error_handler = {
+	.error_detected = pciback_error_detected,
+	.mmio_enabled = pciback_mmio_enabled,
+	.slot_reset = pciback_slot_reset,
+	.resume = pciback_error_resume,
+};
+
+/*
+ * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
+ * for a normal device. I don't want it to be loaded automatically.
+ */
+
+static struct pci_driver pciback_pci_driver = {
+	.name = "pciback",
+	.id_table = pcistub_ids,
+	.probe = pcistub_probe,
+	.remove = pcistub_remove,
+	.err_handler = &pciback_error_handler,
+};
+
+static inline int str_to_slot(const char *buf, int *domain, int *bus,
+			      int *slot, int *func)
+{
+	int err;
+
+	err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
+	if (err == 4)
+		return 0;
+	else if (err < 0)
+		return -EINVAL;
+
+	/* try again without domain */
+	*domain = 0;
+	err = sscanf(buf, " %x:%x.%x", bus, slot, func);
+	if (err == 3)
+		return 0;
+
+	return -EINVAL;
+}
+
+static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
+			       *slot, int *func, int *reg, int *size, int *mask)
+{
+	int err;
+
+	err =
+	    sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
+		   func, reg, size, mask);
+	if (err == 7)
+		return 0;
+	return -EINVAL;
+}
+
+static int pcistub_device_id_add(int domain, int bus, int slot, int func)
+{
+	struct pcistub_device_id *pci_dev_id;
+	unsigned long flags;
+
+	pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
+	if (!pci_dev_id)
+		return -ENOMEM;
+
+	pci_dev_id->domain = domain;
+	pci_dev_id->bus = bus;
+	pci_dev_id->devfn = PCI_DEVFN(slot, func);
+
+	pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
+		 domain, bus, slot, func);
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return 0;
+}
+
+static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
+{
+	struct pcistub_device_id *pci_dev_id, *t;
+	int devfn = PCI_DEVFN(slot, func);
+	int err = -ENOENT;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, slot_list) {
+
+		if (pci_dev_id->domain == domain
+		    && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) {
+			/* Don't break; here because it's possible the same
+			 * slot could be in the list more than once
+			 */
+			list_del(&pci_dev_id->slot_list);
+			kfree(pci_dev_id);
+
+			err = 0;
+
+			pr_debug("pciback: removed %04x:%02x:%02x.%01x from "
+				 "seize list\n", domain, bus, slot, func);
+		}
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return err;
+}
+
+static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
+			   int size, int mask)
+{
+	int err = 0;
+	struct pcistub_device *psdev;
+	struct pci_dev *dev;
+	struct config_field *field;
+
+	psdev = pcistub_device_find(domain, bus, slot, func);
+	if (!psdev || !psdev->dev) {
+		err = -ENODEV;
+		goto out;
+	}
+	dev = psdev->dev;
+
+	field = kzalloc(sizeof(*field), GFP_ATOMIC);
+	if (!field) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	field->offset = reg;
+	field->size = size;
+	field->mask = mask;
+	field->init = NULL;
+	field->reset = NULL;
+	field->release = NULL;
+	field->clean = pciback_config_field_free;
+
+	err = pciback_config_quirks_add_field(dev, field);
+	if (err)
+		kfree(field);
+      out:
+	return err;
+}
+
+static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
+				size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+
+	err = pcistub_device_id_add(domain, bus, slot, func);
+
+      out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
+
+static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
+				   size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+
+	err = pcistub_device_id_remove(domain, bus, slot, func);
+
+      out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
+
+static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
+{
+	struct pcistub_device_id *pci_dev_id;
+	size_t count = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
+		if (count >= PAGE_SIZE)
+			break;
+
+		count += scnprintf(buf + count, PAGE_SIZE - count,
+				   "%04x:%02x:%02x.%01x\n",
+				   pci_dev_id->domain, pci_dev_id->bus,
+				   PCI_SLOT(pci_dev_id->devfn),
+				   PCI_FUNC(pci_dev_id->devfn));
+	}
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return count;
+}
+
+DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+
+static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
+				 size_t count)
+{
+	int domain, bus, slot, func, reg, size, mask;
+	int err;
+
+	err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
+			   &mask);
+	if (err)
+		goto out;
+
+	err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
+
+      out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+{
+	int count = 0;
+	unsigned long flags;
+	extern struct list_head pciback_quirks;
+	struct pciback_config_quirk *quirk;
+	struct pciback_dev_data *dev_data;
+	const struct config_field *field;
+	const struct config_field_entry *cfg_entry;
+
+	spin_lock_irqsave(&device_ids_lock, flags);
+	list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
+		if (count >= PAGE_SIZE)
+			goto out;
+
+		count += scnprintf(buf + count, PAGE_SIZE - count,
+				   "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
+				   quirk->pdev->bus->number,
+				   PCI_SLOT(quirk->pdev->devfn),
+				   PCI_FUNC(quirk->pdev->devfn),
+				   quirk->devid.vendor, quirk->devid.device,
+				   quirk->devid.subvendor,
+				   quirk->devid.subdevice);
+
+		dev_data = pci_get_drvdata(quirk->pdev);
+
+		list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
+			field = cfg_entry->field;
+			if (count >= PAGE_SIZE)
+				goto out;
+
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					   "\t\t%08x:%01x:%08x\n",
+					   cfg_entry->base_offset + field->offset, 
+					   field->size, field->mask);
+		}
+	}
+
+      out:
+	spin_unlock_irqrestore(&device_ids_lock, flags);
+
+	return count;
+}
+
+DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
+
+static ssize_t permissive_add(struct device_driver *drv, const char *buf,
+			      size_t count)
+{
+	int domain, bus, slot, func;
+	int err;
+	struct pcistub_device *psdev;
+	struct pciback_dev_data *dev_data;
+	err = str_to_slot(buf, &domain, &bus, &slot, &func);
+	if (err)
+		goto out;
+	psdev = pcistub_device_find(domain, bus, slot, func);
+	if (!psdev) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (!psdev->dev) {
+		err = -ENODEV;
+		goto release;
+	}
+	dev_data = pci_get_drvdata(psdev->dev);
+	/* the driver data for a device should never be null at this point */
+	if (!dev_data) {
+		err = -ENXIO;
+		goto release;
+	}
+	if (!dev_data->permissive) {
+		dev_data->permissive = 1;
+		/* Let user know that what they're doing could be unsafe */
+		dev_warn(&psdev->dev->dev,
+			 "enabling permissive mode configuration space accesses!\n");
+		dev_warn(&psdev->dev->dev,
+			 "permissive mode is potentially unsafe!\n");
+	}
+      release:
+	pcistub_device_put(psdev);
+      out:
+	if (!err)
+		err = count;
+	return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+	struct pcistub_device *psdev;
+	struct pciback_dev_data *dev_data;
+	size_t count = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&pcistub_devices_lock, flags);
+	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+		if (count >= PAGE_SIZE)
+			break;
+		if (!psdev->dev)
+			continue;
+		dev_data = pci_get_drvdata(psdev->dev);
+		if (!dev_data || !dev_data->permissive)
+			continue;
+		count +=
+		    scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+			      pci_name(psdev->dev));
+	}
+	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+	return count;
+}
+
+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);
+	driver_remove_file(&pciback_pci_driver.driver,
+			   &driver_attr_remove_slot);
+	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
+	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+	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)
+{
+	int pos = 0;
+	int err = 0;
+	int domain, bus, slot, func;
+	int parsed;
+
+	if (pci_devs_to_hide && *pci_devs_to_hide) {
+		do {
+			parsed = 0;
+
+			err = sscanf(pci_devs_to_hide + pos,
+				     " (%x:%x:%x.%x) %n",
+				     &domain, &bus, &slot, &func, &parsed);
+			if (err != 4) {
+				domain = 0;
+				err = sscanf(pci_devs_to_hide + pos,
+					     " (%x:%x.%x) %n",
+					     &bus, &slot, &func, &parsed);
+				if (err != 3)
+					goto parse_error;
+			}
+
+			err = pcistub_device_id_add(domain, bus, slot, func);
+			if (err)
+				goto out;
+
+			/* if parsed<=0, we've reached the end of the string */
+			pos += parsed;
+		} while (parsed > 0 && pci_devs_to_hide[pos]);
+	}
+
+	/* If we're the first PCI Device Driver to register, we're the
+	 * first one to get offered PCI devices as they become
+	 * available (and thus we can be the first to grab them)
+	 */
+	err = pci_register_driver(&pciback_pci_driver);
+	if (err < 0)
+		goto out;
+
+	err = driver_create_file(&pciback_pci_driver.driver,
+				 &driver_attr_new_slot);
+	if (!err)
+		err = driver_create_file(&pciback_pci_driver.driver,
+					 &driver_attr_remove_slot);
+	if (!err)
+		err = driver_create_file(&pciback_pci_driver.driver,
+					 &driver_attr_slots);
+	if (!err)
+		err = driver_create_file(&pciback_pci_driver.driver,
+					 &driver_attr_quirks);
+	if (!err)
+		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();
+
+      out:
+	return err;
+
+      parse_error:
+	printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at \"%s\"\n",
+	       pci_devs_to_hide + pos);
+	return -EINVAL;
+}
+
+#ifndef MODULE
+/*
+ * fs_initcall happens before device_initcall
+ * so pciback *should* get called first (b/c we 
+ * want to suck up any device before other drivers
+ * get a chance by being the first pci device
+ * driver to register)
+ */
+fs_initcall(pcistub_init);
+#endif
+
+static int __init pciback_init(void)
+{
+	int err;
+
+	err = pciback_config_init();
+	if (err)
+		return err;
+
+#ifdef MODULE
+	err = pcistub_init();
+	if (err < 0)
+		return err;
+#endif
+
+	pcistub_init_devices_late();
+	err = pciback_xenbus_register();
+	if (err)
+		pcistub_exit();
+
+	return err;
+}
+
+static void __exit pciback_cleanup(void)
+{
+	pciback_xenbus_unregister();
+	pcistub_exit();
+}
+
+module_init(pciback_init);
+module_exit(pciback_cleanup);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/pciback_ops.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/pciback_ops.c
@@ -0,0 +1,134 @@
+/*
+ * PCI Backend Operations - respond to PCI requests from Frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/wait.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);
+
+		atomic_set(&dev->enable_cnt, 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;
+		}
+	}
+}
+extern wait_queue_head_t aer_wait_queue;
+extern struct workqueue_struct *pciback_wq;
+/*
+* Now the same evtchn is used for both pcifront conf_read_write request
+* as well as pcie aer front end ack. We use a new work_queue to schedule
+* pciback conf_read_write service for avoiding confict with aer_core 
+* do_recovery job which also use the system default work_queue
+*/
+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))
+	{
+		queue_work(pciback_wq, &pdev->op_work);
+	}
+	/*_XEN_PCIB_active should have been cleared by pcifront. And also make
+	sure pciback is waiting for ack by checking _PCIB_op_pending*/
+	if (!test_bit(_XEN_PCIB_active,(unsigned long *)&pdev->sh_info->flags)
+	    &&test_bit(_PCIB_op_pending, &pdev->flags)) {
+		wake_up(&aer_wait_queue);
+	}
+}
+
+/* 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(struct work_struct *work)
+{
+	struct pciback_device *pdev = container_of(work, struct pciback_device, op_work);
+	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 pciback_device *pdev = dev_id;
+
+	test_and_schedule_op(pdev);
+
+	return IRQ_HANDLED;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_header.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_header.c
@@ -0,0 +1,317 @@
+/*
+ * PCI Backend - Handles the virtual fields in the configuration space headers.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+
+struct pci_bar_info {
+	u32 val;
+	u32 len_val;
+	int which;
+};
+
+#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
+#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
+
+static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+{
+	int err;
+
+	if (!atomic_read(&dev->enable_cnt) && is_enable_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG "pciback: %s: enable\n",
+			       pci_name(dev));
+		err = pci_enable_device(dev);
+		if (err)
+			return err;
+	} else if (atomic_read(&dev->enable_cnt) && !is_enable_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG "pciback: %s: disable\n",
+			       pci_name(dev));
+		pci_disable_device(dev);
+	}
+
+	if (!dev->is_busmaster && is_master_cmd(value)) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG "pciback: %s: set bus master\n",
+			       pci_name(dev));
+		pci_set_master(dev);
+	}
+
+	if (value & PCI_COMMAND_INVALIDATE) {
+		if (unlikely(verbose_request))
+			printk(KERN_DEBUG
+			       "pciback: %s: enable memory-write-invalidate\n",
+			       pci_name(dev));
+		err = pci_set_mwi(dev);
+		if (err) {
+			printk(KERN_WARNING
+			       "pciback: %s: cannot enable memory-write-invalidate (%d)\n",
+			       pci_name(dev), err);
+			value &= ~PCI_COMMAND_INVALIDATE;
+		}
+	}
+
+	return pci_write_config_word(dev, offset, value);
+}
+
+static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING "pciback: driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	/* A write to obtain the length must happen as a 32-bit write.
+	 * This does not (yet) support writing individual bytes
+	 */
+	if (value == ~PCI_ROM_ADDRESS_ENABLE)
+		bar->which = 1;
+	else {
+		u32 tmpval;
+		pci_read_config_dword(dev, offset, &tmpval);
+		if (tmpval != bar->val && value == bar->val) {
+			/* Allow restoration of bar value. */
+			pci_write_config_dword(dev, offset, bar->val);
+		}
+		bar->which = 0;
+	}
+
+	/* Do we need to support enabling/disabling the rom address here? */
+
+	return 0;
+}
+
+/* For the BARs, only allow writes which write ~0 or
+ * the correct resource information
+ * (Needed for when the driver probes the resource usage)
+ */
+static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING "pciback: driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	/* A write to obtain the length must happen as a 32-bit write.
+	 * This does not (yet) support writing individual bytes
+	 */
+	if (value == ~0)
+		bar->which = 1;
+	else {
+		u32 tmpval;
+		pci_read_config_dword(dev, offset, &tmpval);
+		if (tmpval != bar->val && value == bar->val) {
+			/* Allow restoration of bar value. */
+			pci_write_config_dword(dev, offset, bar->val);
+		}
+		bar->which = 0;
+	}
+
+	return 0;
+}
+
+static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	if (unlikely(!bar)) {
+		printk(KERN_WARNING "pciback: driver data not found for %s\n",
+		       pci_name(dev));
+		return XEN_PCI_ERR_op_failed;
+	}
+
+	*value = bar->which ? bar->len_val : bar->val;
+
+	return 0;
+}
+
+static inline void read_dev_bar(struct pci_dev *dev,
+				struct pci_bar_info *bar_info, int offset,
+				u32 len_mask)
+{
+	pci_read_config_dword(dev, offset, &bar_info->val);
+	pci_write_config_dword(dev, offset, len_mask);
+	pci_read_config_dword(dev, offset, &bar_info->len_val);
+	pci_write_config_dword(dev, offset, bar_info->val);
+}
+
+static void *bar_init(struct pci_dev *dev, int offset)
+{
+	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+
+	if (!bar)
+		return ERR_PTR(-ENOMEM);
+
+	read_dev_bar(dev, bar, offset, ~0);
+	bar->which = 0;
+
+	return bar;
+}
+
+static void *rom_init(struct pci_dev *dev, int offset)
+{
+	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+
+	if (!bar)
+		return ERR_PTR(-ENOMEM);
+
+	read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
+	bar->which = 0;
+
+	return bar;
+}
+
+static void bar_reset(struct pci_dev *dev, int offset, void *data)
+{
+	struct pci_bar_info *bar = data;
+
+	bar->which = 0;
+}
+
+static void bar_release(struct pci_dev *dev, int offset, void *data)
+{
+	kfree(data);
+}
+
+static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
+			  void *data)
+{
+	*value = (u8) dev->irq;
+
+	return 0;
+}
+
+static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
+{
+	u8 cur_value;
+	int err;
+
+	err = pci_read_config_byte(dev, offset, &cur_value);
+	if (err)
+		goto out;
+
+	if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
+	    || value == PCI_BIST_START)
+		err = pci_write_config_byte(dev, offset, value);
+
+      out:
+	return err;
+}
+
+static const struct config_field header_common[] = {
+	{
+	 .offset    = PCI_COMMAND,
+	 .size      = 2,
+	 .u.w.read  = pciback_read_config_word,
+	 .u.w.write = command_write,
+	},
+	{
+	 .offset    = PCI_INTERRUPT_LINE,
+	 .size      = 1,
+	 .u.b.read  = interrupt_read,
+	},
+	{
+	 .offset    = PCI_INTERRUPT_PIN,
+	 .size      = 1,
+	 .u.b.read  = pciback_read_config_byte,
+	},
+	{
+	 /* Any side effects of letting driver domain control cache line? */
+	 .offset    = PCI_CACHE_LINE_SIZE,
+	 .size      = 1,
+	 .u.b.read  = pciback_read_config_byte,
+	 .u.b.write = pciback_write_config_byte,
+	},
+	{
+	 .offset    = PCI_LATENCY_TIMER,
+	 .size      = 1,
+	 .u.b.read  = pciback_read_config_byte,
+	},
+	{
+	 .offset    = PCI_BIST,
+	 .size      = 1,
+	 .u.b.read  = pciback_read_config_byte,
+	 .u.b.write = bist_write,
+	},
+	{}
+};
+
+#define CFG_FIELD_BAR(reg_offset) 			\
+	{ 						\
+	 .offset     = reg_offset, 			\
+	 .size       = 4, 				\
+	 .init       = bar_init, 			\
+	 .reset      = bar_reset, 			\
+	 .release    = bar_release, 			\
+	 .u.dw.read  = bar_read, 			\
+	 .u.dw.write = bar_write, 			\
+	 }
+
+#define CFG_FIELD_ROM(reg_offset) 			\
+	{ 						\
+	 .offset     = reg_offset, 			\
+	 .size       = 4, 				\
+	 .init       = rom_init, 			\
+	 .reset      = bar_reset, 			\
+	 .release    = bar_release, 			\
+	 .u.dw.read  = bar_read, 			\
+	 .u.dw.write = rom_write, 			\
+	 }
+
+static const struct config_field header_0[] = {
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
+	CFG_FIELD_ROM(PCI_ROM_ADDRESS),
+	{}
+};
+
+static const struct config_field header_1[] = {
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
+	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
+	CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
+	{}
+};
+
+int pciback_config_header_add_fields(struct pci_dev *dev)
+{
+	int err;
+
+	err = pciback_config_add_fields(dev, header_common);
+	if (err)
+		goto out;
+
+	switch (dev->hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+		err = pciback_config_add_fields(dev, header_0);
+		break;
+
+	case PCI_HEADER_TYPE_BRIDGE:
+		err = pciback_config_add_fields(dev, header_1);
+		break;
+
+	default:
+		err = -EINVAL;
+		printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n",
+		       pci_name(dev), dev->hdr_type);
+		break;
+	}
+
+      out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pciback/conf_space_capability.c
+++ linux-ec2-2.6.32/drivers/xen/pciback/conf_space_capability.c
@@ -0,0 +1,69 @@
+/*
+ * PCI Backend - Handles the virtual fields found on the capability lists
+ *               in the configuration space.
+ *
+ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "pciback.h"
+#include "conf_space.h"
+#include "conf_space_capability.h"
+
+static LIST_HEAD(capabilities);
+
+static const struct config_field caplist_header[] = {
+	{
+	 .offset    = PCI_CAP_LIST_ID,
+	 .size      = 2, /* encompass PCI_CAP_LIST_ID & PCI_CAP_LIST_NEXT */
+	 .u.w.read  = pciback_read_config_word,
+	 .u.w.write = NULL,
+	},
+	{}
+};
+
+static inline void register_capability(struct pciback_config_capability *cap)
+{
+	list_add_tail(&cap->cap_list, &capabilities);
+}
+
+int pciback_config_capability_add_fields(struct pci_dev *dev)
+{
+	int err = 0;
+	struct pciback_config_capability *cap;
+	int cap_offset;
+
+	list_for_each_entry(cap, &capabilities, cap_list) {
+		cap_offset = pci_find_capability(dev, cap->capability);
+		if (cap_offset) {
+			dev_dbg(&dev->dev, "Found capability 0x%x at 0x%x\n",
+				cap->capability, cap_offset);
+
+			err = pciback_config_add_fields_offset(dev,
+							       caplist_header,
+							       cap_offset);
+			if (err)
+				goto out;
+			err = pciback_config_add_fields_offset(dev,
+							       cap->fields,
+							       cap_offset);
+			if (err)
+				goto out;
+		}
+	}
+
+      out:
+	return err;
+}
+
+extern struct pciback_config_capability pciback_config_capability_vpd;
+extern struct pciback_config_capability pciback_config_capability_pm;
+
+int pciback_config_capability_init(void)
+{
+	register_capability(&pciback_config_capability_vpd);
+	register_capability(&pciback_config_capability_pm);
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/fbfront/xenfb.c
+++ linux-ec2-2.6.32/drivers/xen/fbfront/xenfb.c
@@ -0,0 +1,910 @@
+/*
+ * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device
+ *
+ * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/video/q40fb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/*
+ * TODO:
+ *
+ * Switch to grant tables when they become capable of dealing with the
+ * frame buffer.
+ */
+
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/freezer.h>
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/protocols.h>
+#include <xen/xenbus.h>
+#include <linux/kthread.h>
+
+struct xenfb_mapping
+{
+	struct list_head	link;
+	struct vm_area_struct	*vma;
+	atomic_t		map_refs;
+	int			faults;
+	struct xenfb_info	*info;
+};
+
+struct xenfb_info
+{
+	struct task_struct	*kthread;
+	wait_queue_head_t	wq;
+
+	unsigned char		*fb;
+	struct fb_info		*fb_info;
+	struct timer_list	refresh;
+	int			dirty;
+	int			x1, y1, x2, y2;	/* dirty rectangle,
+						   protected by dirty_lock */
+	spinlock_t		dirty_lock;
+	struct mutex		mm_lock;
+	int			nr_pages;
+	struct page		**pages;
+	struct list_head	mappings; /* protected by mm_lock */
+
+	int			irq;
+	struct xenfb_page	*page;
+	unsigned long 		*mfns;
+	int			feature_resize; /* Backend has resize feature */
+	struct xenfb_resize	resize;
+	int			resize_dpy;
+	spinlock_t		resize_lock;
+
+	struct xenbus_device	*xbdev;
+};
+
+/*
+ * There are three locks:
+ *    spinlock resize_lock protecting resize_dpy and resize
+ *    spinlock dirty_lock protecting the dirty rectangle
+ *    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
+ * mappings.  We need to prove that our locking maintains this
+ * invariant.
+ *
+ * There are several kinds of critical regions:
+ *
+ * 1. Holding only dirty_lock: xenfb_refresh().  May run in
+ *    interrupts.  Extends the dirty rectangle.  Trivially preserves
+ *    invariant.
+ *
+ * 2. Holding only mm_lock: xenfb_mmap() and xenfb_vm_close().  Touch
+ *    only mappings.  The former creates unfaulted pages.  Preserves
+ *    invariant.  The latter removes pages.  Preserves invariant.
+ *
+ * 3. Holding both locks: xenfb_vm_fault().  Extends the dirty
+ *    rectangle and updates mappings consistently.  Preserves
+ *    invariant.
+ *
+ * 4. The ugliest one: xenfb_update_screen().  Clear the dirty
+ *    rectangle and update mappings consistently.
+ *
+ *    We can't simply hold both locks, because zap_page_range() cannot
+ *    be called with a spinlock held.
+ *
+ *    Therefore, we first clear the dirty rectangle with both locks
+ *    held.  Then we unlock dirty_lock and update the mappings.
+ *    Critical regions that hold only dirty_lock may interfere with
+ *    that.  This can only be region 1: xenfb_refresh().  But that
+ *    just extends the dirty rectangle, which can't harm the
+ *    invariant.
+ *
+ * But FIXME: the invariant is too weak.  It misses that the fault
+ * record in mappings must be consistent with the mapping of pages in
+ * the associated address space!  __do_fault() updates the PTE after
+ * xenfb_vm_fault() returns, i.e. outside the critical region.  This
+ * allows the following race:
+ *
+ * X writes to some address in the Xen frame buffer
+ * Fault - call __do_fault()
+ *     call xenfb_vm_fault()
+ *         grab mm_lock
+ *         map->faults++;
+ *         release mm_lock
+ *     return back to do_no_page()
+ * (preempted, or SMP)
+ * Xen worker thread runs.
+ *      grab mm_lock
+ *      look at mappings
+ *          find this mapping, zaps its pages (but page not in pte yet)
+ *          clear map->faults
+ *      releases mm_lock
+ * (back to X process)
+ *     put page in X's pte
+ *
+ * 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 int xenfb_remove(struct xenbus_device *);
+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;
+
+	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;
+
+	/* caller ensures !xenfb_queue_full() */
+	xenfb_send_event(info, &event);
+}
+
+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)
+{
+	__u32 cons, prod;
+
+	prod = info->page->out_prod;
+	cons = info->page->out_cons;
+	return prod - cons == XENFB_OUT_RING_LEN;
+}
+
+static void xenfb_update_screen(struct xenfb_info *info)
+{
+	unsigned long flags;
+	int y1, y2, x1, x2;
+	struct xenfb_mapping *map;
+
+	if (xenfb_queue_full(info))
+		return;
+
+	mutex_lock(&info->mm_lock);
+
+	spin_lock_irqsave(&info->dirty_lock, flags);
+	if (info->dirty){
+		info->dirty = 0;
+		y1 = info->y1;
+		y2 = info->y2;
+		x1 = info->x1;
+		x2 = info->x2;
+		info->x1 = info->y1 = INT_MAX;
+		info->x2 = info->y2 = 0;
+	} else {
+		spin_unlock_irqrestore(&info->dirty_lock, flags);
+		mutex_unlock(&info->mm_lock);
+		return;
+	}
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
+
+	list_for_each_entry(map, &info->mappings, link) {
+		if (!map->faults)
+			continue;
+		zap_page_range(map->vma, map->vma->vm_start,
+			       map->vma->vm_end - map->vma->vm_start, NULL);
+		map->faults = 0;
+	}
+
+	mutex_unlock(&info->mm_lock);
+
+	if (x2 < x1 || y2 < y1) {
+		printk("xenfb_update_screen bogus rect %d %d %d %d\n",
+		       x1, x2, y1, y2);
+		WARN_ON(1);
+	}
+	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);
+		xenfb_update_screen(info);
+		wait_event_interruptible(info->wq,
+			kthread_should_stop() || info->dirty);
+		try_to_freeze();
+	}
+	return 0;
+}
+
+static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	u32 v;
+
+	if (regno > info->cmap.len)
+		return 1;
+
+	red   >>= (16 - info->var.red.length);
+	green >>= (16 - info->var.green.length);
+	blue  >>= (16 - info->var.blue.length);
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset);
+
+	/* FIXME is this sane?  check against xxxfb_setcolreg()!  */
+	switch (info->var.bits_per_pixel) {
+	case 16:
+	case 24:
+	case 32:
+		((u32 *)info->pseudo_palette)[regno] = v;
+		break;
+	}
+	
+	return 0;
+}
+
+static void xenfb_timer(unsigned long data)
+{
+	struct xenfb_info *info = (struct xenfb_info *)data;
+	wake_up(&info->wq);
+}
+
+static void __xenfb_refresh(struct xenfb_info *info,
+			    int x1, int y1, int w, int h)
+{
+	int y2, x2;
+
+	y2 = y1 + h;
+	x2 = x1 + w;
+
+	if (info->y1 > y1)
+		info->y1 = y1;
+	if (info->y2 < y2)
+		info->y2 = y2;
+	if (info->x1 > x1)
+		info->x1 = x1;
+	if (info->x2 < x2)
+		info->x2 = x2;
+	info->dirty = 1;
+
+	if (timer_pending(&info->refresh))
+		return;
+
+	mod_timer(&info->refresh, jiffies + HZ/xenfb_fps);
+}
+
+static void xenfb_refresh(struct xenfb_info *info,
+			  int x1, int y1, int w, int h)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->dirty_lock, flags);
+	__xenfb_refresh(info, x1, y1, w, h);
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
+}
+
+static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	struct xenfb_info *info = p->par;
+
+	cfb_fillrect(p, rect);
+	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+	struct xenfb_info *info = p->par;
+
+	cfb_imageblit(p, image);
+	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
+}
+
+static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	struct xenfb_info *info = p->par;
+
+	cfb_copyarea(p, area);
+	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
+}
+
+static void xenfb_vm_open(struct vm_area_struct *vma)
+{
+	struct xenfb_mapping *map = vma->vm_private_data;
+	atomic_inc(&map->map_refs);
+}
+
+static void xenfb_vm_close(struct vm_area_struct *vma)
+{
+	struct xenfb_mapping *map = vma->vm_private_data;
+	struct xenfb_info *info = map->info;
+
+	mutex_lock(&info->mm_lock);
+	if (atomic_dec_and_test(&map->map_refs)) {
+		list_del(&map->link);
+		kfree(map);
+	}
+	mutex_unlock(&info->mm_lock);
+}
+
+static int xenfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct xenfb_mapping *map = vma->vm_private_data;
+	struct xenfb_info *info = map->info;
+	int pgnr = ((long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT;
+	unsigned long flags;
+	struct page *page;
+	int y1, y2;
+
+	if (pgnr >= info->nr_pages)
+		return VM_FAULT_SIGBUS;
+
+	mutex_lock(&info->mm_lock);
+	spin_lock_irqsave(&info->dirty_lock, flags);
+	page = info->pages[pgnr];
+	get_page(page);
+	map->faults++;
+
+	y1 = pgnr * PAGE_SIZE / info->fb_info->fix.line_length;
+	y2 = (pgnr * PAGE_SIZE + PAGE_SIZE - 1) / info->fb_info->fix.line_length;
+	if (y2 > info->fb_info->var.yres)
+		y2 = info->fb_info->var.yres;
+	__xenfb_refresh(info, 0, y1, info->fb_info->var.xres, y2 - y1);
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
+	mutex_unlock(&info->mm_lock);
+
+	vmf->page = page;
+
+	return VM_FAULT_MINOR;
+}
+
+static struct vm_operations_struct xenfb_vm_ops = {
+	.open	= xenfb_vm_open,
+	.close	= xenfb_vm_close,
+	.fault	= xenfb_vm_fault,
+};
+
+static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
+{
+	struct xenfb_info *info = fb_info->par;
+	struct xenfb_mapping *map;
+	int map_pages;
+
+	if (!(vma->vm_flags & VM_WRITE))
+		return -EINVAL;
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+
+	map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT;
+	if (map_pages > info->nr_pages)
+		return -EINVAL;
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (map == NULL)
+		return -ENOMEM;
+
+	map->vma = vma;
+	map->faults = 0;
+	map->info = info;
+	atomic_set(&map->map_refs, 1);
+
+	mutex_lock(&info->mm_lock);
+	list_add(&map->link, &info->mappings);
+	mutex_unlock(&info->mm_lock);
+
+	vma->vm_ops = &xenfb_vm_ops;
+	vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
+	vma->vm_private_data = map;
+
+	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,
+	.fb_fillrect	= xenfb_fillrect,
+	.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)
+{
+	/*
+	 * No in events recognized, simply ignore them all.
+	 * If you need to recognize some, see xenbkd's input_handler()
+	 * for how to do that.
+	 */
+	struct xenfb_info *info = dev_id;
+	struct xenfb_page *page = info->page;
+
+	if (page->in_cons != page->in_prod) {
+		info->page->in_cons = info->page->in_prod;
+		notify_remote_via_irq(info->irq);
+	}
+	return IRQ_HANDLED;
+}
+
+static unsigned long vmalloc_to_mfn(void *address)
+{
+	return pfn_to_mfn(vmalloc_to_pfn(address));
+}
+
+static __devinit void
+xenfb_make_preferred_console(void)
+{
+	struct console *c;
+
+	if (console_set_on_cmdline)
+		return;
+
+	acquire_console_sem();
+	for (c = console_drivers; c; c = c->next) {
+		if (!strcmp(c->name, "tty") && c->index == 0)
+			break;
+	}
+	release_console_sem();
+	if (c) {
+		unregister_console(c);
+		c->flags |= CON_CONSDEV;
+		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
+		register_console(c);
+	}
+}
+
+static int __devinit xenfb_probe(struct xenbus_device *dev,
+				 const struct xenbus_device_id *id)
+{
+	struct xenfb_info *info;
+	struct fb_info *fb_info;
+	int fb_size;
+	int val;
+	int ret;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		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_set_drvdata(&dev->dev, 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);
+	info->refresh.function = xenfb_timer;
+	info->refresh.data = (unsigned long)info;
+	INIT_LIST_HEAD(&info->mappings);
+
+	info->fb = vmalloc(fb_size);
+	if (info->fb == NULL)
+		goto error_nomem;
+	memset(info->fb, 0, fb_size);
+
+	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	info->pages = kmalloc(sizeof(struct page *) * info->nr_pages,
+			      GFP_KERNEL);
+	if (info->pages == NULL)
+		goto error_nomem;
+
+	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+	if (!info->mfns)
+		goto error_nomem;
+
+	/* set up shared page */
+	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!info->page)
+		goto error_nomem;
+
+	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
+				/* see fishy hackery below */
+	if (fb_info == NULL)
+		goto error_nomem;
+
+	/* FIXME fishy hackery */
+	fb_info->pseudo_palette = fb_info->par;
+	fb_info->par = info;
+	/* /FIXME */
+	fb_info->screen_base = info->fb;
+
+	fb_info->fbops = &xenfb_fb_ops;
+	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};
+	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
+
+	fb_info->var.activate = FB_ACTIVATE_NOW;
+	fb_info->var.height = -1;
+	fb_info->var.width = -1;
+	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
+	fb_info->fix.line_length = fb_info->var.xres * (XENFB_DEPTH / 8);
+	fb_info->fix.smem_start = 0;
+	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;
+
+	fb_info->flags = FBINFO_FLAG_DEFAULT;
+
+	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
+	if (ret < 0) {
+		framebuffer_release(fb_info);
+		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
+		goto error;
+	}
+
+	xenfb_init_shared_page(info, fb_info);
+
+	ret = register_framebuffer(fb_info);
+	if (ret) {
+		fb_dealloc_cmap(&info->fb_info->cmap);
+		framebuffer_release(fb_info);
+		xenbus_dev_fatal(dev, ret, "register_framebuffer");
+		goto error;
+	}
+	info->fb_info = fb_info;
+
+	ret = xenfb_connect_backend(dev, info);
+	if (ret < 0)
+		goto error;
+
+	xenfb_make_preferred_console();
+	return 0;
+
+ error_nomem:
+	ret = -ENOMEM;
+	xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+	xenfb_remove(dev);
+	return ret;
+}
+
+static int xenfb_resume(struct xenbus_device *dev)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+
+	xenfb_disconnect_backend(info);
+	xenfb_init_shared_page(info, info->fb_info);
+	return xenfb_connect_backend(dev, info);
+}
+
+static int xenfb_remove(struct xenbus_device *dev)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+
+	del_timer(&info->refresh);
+	if (info->kthread)
+		kthread_stop(info->kthread);
+	xenfb_disconnect_backend(info);
+	if (info->fb_info) {
+		unregister_framebuffer(info->fb_info);
+		fb_dealloc_cmap(&info->fb_info->cmap);
+		framebuffer_release(info->fb_info);
+	}
+	free_page((unsigned long)info->page);
+	vfree(info->mfns);
+	kfree(info->pages);
+	vfree(info->fb);
+	kfree(info);
+
+	return 0;
+}
+
+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);
+
+	for (i = 0; i < info->nr_pages; i++)
+		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+
+	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;
+}
+
+static int xenfb_connect_backend(struct xenbus_device *dev,
+				 struct xenfb_info *info)
+{
+	int ret;
+	struct xenbus_transaction xbt;
+
+	ret = bind_listening_port_to_irqhandler(
+		dev->otherend_id, xenfb_event_handler, 0, "xenfb", info);
+	if (ret < 0) {
+		xenbus_dev_fatal(dev, ret,
+				 "bind_listening_port_to_irqhandler");
+		return ret;
+	}
+	info->irq = ret;
+
+ again:
+	ret = xenbus_transaction_start(&xbt);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "starting transaction");
+		return ret;
+	}
+	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+			    virt_to_mfn(info->page));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    irq_to_evtchn_port(info->irq));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
+			    XEN_IO_PROTO_ABI_NATIVE);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_transaction_end(xbt, 0);
+	if (ret) {
+		if (ret == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, ret, "completing transaction");
+		return ret;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+	return 0;
+
+ error_xenbus:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, ret, "writing xenstore");
+	return ret;
+}
+
+static void xenfb_disconnect_backend(struct xenfb_info *info)
+{
+	if (info->irq >= 0)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+}
+
+static void xenfb_backend_changed(struct xenbus_device *dev,
+				  enum xenbus_state backend_state)
+{
+	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+	int val;
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+	InitWait:
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateConnected:
+		/*
+		 * Work around xenbus race condition: If backend goes
+		 * through InitWait to Connected fast enough, we can
+		 * get Connected twice here.
+		 */
+		if (dev->state != XenbusStateConnected)
+			goto InitWait; /* no InitWait seen yet, fudge it */
+
+
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+					"feature-resize", "%d", &val) < 0)
+			val = 0;
+		info->feature_resize = val;
+
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "request-update", "%d", &val) < 0)
+			val = 0;
+
+		if (val){
+			info->kthread = kthread_run(xenfb_thread, info,
+						    "xenfb thread");
+			if (IS_ERR(info->kthread)) {
+				info->kthread = NULL;
+				xenbus_dev_fatal(dev, PTR_ERR(info->kthread),
+						"xenfb_thread");
+			}
+		}
+		break;
+
+	case XenbusStateClosing:
+		// FIXME is this safe in any dev->state?
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static const struct xenbus_device_id xenfb_ids[] = {
+	{ "vfb" },
+	{ "" }
+};
+MODULE_ALIAS("xen:vfb");
+
+static struct xenbus_driver xenfb_driver = {
+	.name = "vfb",
+	.ids = xenfb_ids,
+	.probe = xenfb_probe,
+	.remove = xenfb_remove,
+	.resume = xenfb_resume,
+	.otherend_changed = xenfb_backend_changed,
+};
+
+static int __init xenfb_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	/* Nothing to do if running in dom0. */
+	if (is_initial_xendomain())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenfb_driver);
+}
+
+static void __exit xenfb_cleanup(void)
+{
+	return xenbus_unregister_driver(&xenfb_driver);
+}
+
+module_init(xenfb_init);
+module_exit(xenfb_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/fbfront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/fbfront/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_XEN_FRAMEBUFFER)	:= xenfb.o
+obj-$(CONFIG_XEN_KEYBOARD)	+= xenkbd.o
--- linux-ec2-2.6.32.orig/drivers/xen/fbfront/xenkbd.c
+++ linux-ec2-2.6.32/drivers/xen/fbfront/xenkbd.c
@@ -0,0 +1,354 @@
+/*
+ * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+/*
+ * TODO:
+ *
+ * Switch to grant tables together with xenfb.c.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <asm/hypervisor.h>
+#include <xen/evtchn.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/kbdif.h>
+#include <xen/xenbus.h>
+
+struct xenkbd_info
+{
+	struct input_dev *kbd;
+	struct input_dev *ptr;
+	struct xenkbd_page *page;
+	int irq;
+	struct xenbus_device *xbdev;
+	char phys[32];
+};
+
+static int xenkbd_remove(struct xenbus_device *);
+static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+/*
+ * Note: if you need to send out events, see xenfb_do_update() for how
+ * to do that.
+ */
+
+static irqreturn_t input_handler(int rq, void *dev_id)
+{
+	struct xenkbd_info *info = dev_id;
+	struct xenkbd_page *page = info->page;
+	__u32 cons, prod;
+
+	prod = page->in_prod;
+	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++) {
+		union xenkbd_in_event *event;
+		struct input_dev *dev;
+		event = &XENKBD_IN_RING_REF(page, cons);
+
+		dev = info->ptr;
+		switch (event->type) {
+		case XENKBD_TYPE_MOTION:
+			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;
+			if (test_bit(event->key.keycode, info->kbd->keybit))
+				dev = info->kbd;
+			if (test_bit(event->key.keycode, info->ptr->keybit))
+				dev = info->ptr;
+			if (dev)
+				input_report_key(dev, event->key.keycode,
+						 event->key.pressed);
+			else
+				printk("xenkbd: unhandled keycode 0x%x\n",
+				       event->key.keycode);
+			break;
+		case XENKBD_TYPE_POS:
+			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)
+			input_sync(dev);
+	}
+	mb();			/* ensure we got ring contents */
+	page->in_cons = cons;
+	notify_remote_via_irq(info->irq);
+
+	return IRQ_HANDLED;
+}
+
+int __devinit xenkbd_probe(struct xenbus_device *dev,
+			   const struct xenbus_device_id *id)
+{
+	int ret, i;
+	struct xenkbd_info *info;
+	struct input_dev *kbd, *ptr;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+		return -ENOMEM;
+	}
+	dev_set_drvdata(&dev->dev, info);
+	info->xbdev = dev;
+	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+
+	info->page = (void *)__get_free_page(GFP_KERNEL);
+	if (!info->page)
+		goto error_nomem;
+	info->page->in_cons = info->page->in_prod = 0;
+	info->page->out_cons = info->page->out_prod = 0;
+
+	/* keyboard */
+	kbd = input_allocate_device();
+	if (!kbd)
+		goto error_nomem;
+	kbd->name = "Xen Virtual Keyboard";
+	kbd->phys = info->phys;
+	kbd->id.bustype = BUS_PCI;
+	kbd->id.vendor = 0x5853;
+	kbd->id.product = 0xffff;
+	kbd->evbit[0] = BIT(EV_KEY);
+	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
+		set_bit(i, kbd->keybit);
+	for (i = KEY_OK; i < KEY_MAX; i++)
+		set_bit(i, kbd->keybit);
+
+	ret = input_register_device(kbd);
+	if (ret) {
+		input_free_device(kbd);
+		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
+		goto error;
+	}
+	info->kbd = kbd;
+
+	/* pointing device */
+	ptr = input_allocate_device();
+	if (!ptr)
+		goto error_nomem;
+	ptr->name = "Xen Virtual Pointer";
+	ptr->phys = info->phys;
+	ptr->id.bustype = BUS_PCI;
+	ptr->id.vendor = 0x5853;
+	ptr->id.product = 0xfffe;
+	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+	for (i = BTN_LEFT; i <= BTN_TASK; i++)
+		set_bit(i, ptr->keybit);
+	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
+	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+
+	ret = input_register_device(ptr);
+	if (ret) {
+		input_free_device(ptr);
+		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
+		goto error;
+	}
+	info->ptr = ptr;
+
+	ret = xenkbd_connect_backend(dev, info);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+ error_nomem:
+	ret = -ENOMEM;
+	xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+	xenkbd_remove(dev);
+	return ret;
+}
+
+static int xenkbd_resume(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	info->page->in_cons = info->page->in_prod = 0;
+	info->page->out_cons = info->page->out_prod = 0;
+	return xenkbd_connect_backend(dev, info);
+}
+
+static int xenkbd_remove(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	input_unregister_device(info->kbd);
+	input_unregister_device(info->ptr);
+	free_page((unsigned long)info->page);
+	kfree(info);
+	return 0;
+}
+
+static int xenkbd_connect_backend(struct xenbus_device *dev,
+				  struct xenkbd_info *info)
+{
+	int ret;
+	struct xenbus_transaction xbt;
+
+	ret = bind_listening_port_to_irqhandler(
+		dev->otherend_id, input_handler, 0, "xenkbd", info);
+	if (ret < 0) {
+		xenbus_dev_fatal(dev, ret,
+				 "bind_listening_port_to_irqhandler");
+		return ret;
+	}
+	info->irq = ret;
+
+ again:
+	ret = xenbus_transaction_start(&xbt);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "starting transaction");
+		return ret;
+	}
+	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+			    virt_to_mfn(info->page));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    irq_to_evtchn_port(info->irq));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_transaction_end(xbt, 0);
+	if (ret) {
+		if (ret == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, ret, "completing transaction");
+		return ret;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+	return 0;
+
+ error_xenbus:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, ret, "writing xenstore");
+	return ret;
+}
+
+static void xenkbd_disconnect_backend(struct xenkbd_info *info)
+{
+	if (info->irq >= 0)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+}
+
+static void xenkbd_backend_changed(struct xenbus_device *dev,
+				   enum xenbus_state backend_state)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+	int ret, val;
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+	InitWait:
+		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				   "feature-abs-pointer", "%d", &val);
+		if (ret < 0)
+			val = 0;
+		if (val) {
+			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
+					    "request-abs-pointer", "1");
+			if (ret)
+				; /* FIXME */
+		}
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateConnected:
+		/*
+		 * Work around xenbus race condition: If backend goes
+		 * through InitWait to Connected fast enough, we can
+		 * get Connected twice here.
+		 */
+		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:
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static const struct xenbus_device_id xenkbd_ids[] = {
+	{ "vkbd" },
+	{ "" }
+};
+MODULE_ALIAS("xen:vkbd");
+
+static struct xenbus_driver xenkbd_driver = {
+	.name = "vkbd",
+	.ids = xenkbd_ids,
+	.probe = xenkbd_probe,
+	.remove = xenkbd_remove,
+	.resume = xenkbd_resume,
+	.otherend_changed = xenkbd_backend_changed,
+};
+
+static int __init xenkbd_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	/* Nothing to do if running in dom0. */
+	if (is_initial_xendomain())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenkbd_driver);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+	return xenbus_unregister_driver(&xenkbd_driver);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_dev.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_dev.c
@@ -0,0 +1,461 @@
+/*
+ * xenbus_dev.c
+ * 
+ * Driver giving user-space access to the kernel's xenbus connection
+ * to xenstore.
+ * 
+ * Copyright (c) 2005, Christian Limpach
+ * Copyright (c) 2005, Rusty Russell, IBM Corporation
+ * 
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/uio.h>
+#include <linux/notifier.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/mutex.h>
+
+#include "xenbus_comms.h"
+
+#include <asm/uaccess.h>
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+#include <xen/xen_proc.h>
+#include <asm/hypervisor.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#include <xen/public/xenbus.h>
+
+struct xenbus_dev_transaction {
+	struct list_head list;
+	struct xenbus_transaction handle;
+};
+
+struct read_buffer {
+	struct list_head list;
+	unsigned int cons;
+	unsigned int len;
+	char msg[];
+};
+
+struct xenbus_dev_data {
+	/* In-progress transaction. */
+	struct list_head transactions;
+
+	/* Active watches. */
+	struct list_head watches;
+
+	/* Partial request. */
+	unsigned int len;
+	union {
+		struct xsd_sockmsg msg;
+		char buffer[PAGE_SIZE];
+	} u;
+
+	/* Response queue. */
+	struct list_head read_buffers;
+	wait_queue_head_t read_waitq;
+
+	struct mutex reply_mutex;
+};
+
+static struct proc_dir_entry *xenbus_dev_intf;
+
+static ssize_t xenbus_dev_read(struct file *filp,
+			       char __user *ubuf,
+			       size_t len, loff_t *ppos)
+{
+	struct xenbus_dev_data *u = filp->private_data;
+	struct read_buffer *rb;
+	int i, ret;
+
+	if (!is_xenstored_ready())
+		return -ENODEV;
+
+	mutex_lock(&u->reply_mutex);
+	while (list_empty(&u->read_buffers)) {
+		mutex_unlock(&u->reply_mutex);
+		ret = wait_event_interruptible(u->read_waitq,
+					       !list_empty(&u->read_buffers));
+		if (ret)
+			return ret;
+		mutex_lock(&u->reply_mutex);
+	}
+
+	rb = list_entry(u->read_buffers.next, struct read_buffer, list);
+	for (i = 0; i < len;) {
+		put_user(rb->msg[rb->cons], ubuf + i);
+		i++;
+		rb->cons++;
+		if (rb->cons == rb->len) {
+			list_del(&rb->list);
+			kfree(rb);
+			if (list_empty(&u->read_buffers))
+				break;
+			rb = list_entry(u->read_buffers.next,
+					struct read_buffer, list);
+		}
+	}
+	mutex_unlock(&u->reply_mutex);
+
+	return i;
+}
+
+static void queue_reply(struct xenbus_dev_data *u,
+			char *data, unsigned int len)
+{
+	struct read_buffer *rb;
+
+	if (len == 0)
+		return;
+
+	rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
+	BUG_ON(rb == NULL);
+
+	rb->cons = 0;
+	rb->len = len;
+
+	memcpy(rb->msg, data, len);
+
+	list_add_tail(&rb->list, &u->read_buffers);
+
+	wake_up(&u->read_waitq);
+}
+
+struct watch_adapter
+{
+	struct list_head list;
+	struct xenbus_watch watch;
+	struct xenbus_dev_data *dev_data;
+	char *token;
+};
+
+static void free_watch_adapter (struct watch_adapter *watch)
+{
+	kfree(watch->watch.node);
+	kfree(watch->token);
+	kfree(watch);
+}
+
+static void watch_fired(struct xenbus_watch *watch,
+			const char **vec,
+			unsigned int len)
+{
+	struct watch_adapter *adap =
+            container_of(watch, struct watch_adapter, watch);
+	struct xsd_sockmsg hdr;
+	const char *path, *token;
+	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;
+	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;
+
+	mutex_lock(&adap->dev_data->reply_mutex);
+	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);
+}
+
+static LIST_HEAD(watch_list);
+
+static ssize_t xenbus_dev_write(struct file *filp,
+				const char __user *ubuf,
+				size_t len, loff_t *ppos)
+{
+	struct xenbus_dev_data *u = filp->private_data;
+	struct xenbus_dev_transaction *trans = NULL;
+	uint32_t msg_type;
+	void *reply;
+	char *path, *token;
+	struct watch_adapter *watch, *tmp_watch;
+	int err, rc = len;
+
+	if (!is_xenstored_ready())
+		return -ENODEV;
+
+	if ((len + u->len) > sizeof(u->u.buffer)) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	u->len += len;
+	if ((u->len < sizeof(u->u.msg)) ||
+	    (u->len < (sizeof(u->u.msg) + u->u.msg.len)))
+		return rc;
+
+	msg_type = u->u.msg.type;
+
+	switch (msg_type) {
+	case XS_WATCH:
+	case XS_UNWATCH: {
+		static const char *XS_RESP = "OK";
+		struct xsd_sockmsg hdr;
+
+		path = u->u.buffer + sizeof(u->u.msg);
+		token = memchr(path, 0, u->u.msg.len);
+		if (token == NULL) {
+			rc = -EILSEQ;
+			goto out;
+		}
+		token++;
+
+		if (msg_type == XS_WATCH) {
+			watch = kzalloc(sizeof(*watch), GFP_KERNEL);
+			watch->watch.node = kmalloc(strlen(path)+1,
+                                                    GFP_KERNEL);
+			strcpy((char *)watch->watch.node, path);
+			watch->watch.callback = watch_fired;
+			watch->token = kmalloc(strlen(token)+1, GFP_KERNEL);
+			strcpy(watch->token, token);
+			watch->dev_data = u;
+
+			err = register_xenbus_watch(&watch->watch);
+			if (err) {
+				free_watch_adapter(watch);
+				rc = err;
+				goto out;
+			}
+			
+			list_add(&watch->list, &u->watches);
+		} else {
+			list_for_each_entry_safe(watch, tmp_watch,
+                                                 &u->watches, list) {
+				if (!strcmp(watch->token, token) &&
+				    !strcmp(watch->watch.node, path))
+				{
+					unregister_xenbus_watch(&watch->watch);
+					list_del(&watch->list);
+					free_watch_adapter(watch);
+					break;
+				}
+			}
+		}
+
+		hdr.type = msg_type;
+		hdr.len = strlen(XS_RESP) + 1;
+		mutex_lock(&u->reply_mutex);
+		queue_reply(u, (char *)&hdr, sizeof(hdr));
+		queue_reply(u, (char *)XS_RESP, hdr.len);
+		mutex_unlock(&u->reply_mutex);
+		break;
+	}
+
+	default:
+		if (msg_type == XS_TRANSACTION_START) {
+			trans = kmalloc(sizeof(*trans), GFP_KERNEL);
+			if (!trans) {
+				rc = -ENOMEM;
+				goto out;
+			}
+		}
+
+		reply = xenbus_dev_request_and_reply(&u->u.msg);
+		if (IS_ERR(reply)) {
+			kfree(trans);
+			rc = PTR_ERR(reply);
+			goto out;
+		}
+
+		if (msg_type == XS_TRANSACTION_START) {
+			trans->handle.id = simple_strtoul(reply, NULL, 0);
+			list_add(&trans->list, &u->transactions);
+		} else if (msg_type == XS_TRANSACTION_END) {
+			list_for_each_entry(trans, &u->transactions, list)
+				if (trans->handle.id == u->u.msg.tx_id)
+					break;
+			BUG_ON(&trans->list == &u->transactions);
+			list_del(&trans->list);
+			kfree(trans);
+		}
+		mutex_lock(&u->reply_mutex);
+		queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
+		queue_reply(u, (char *)reply, u->u.msg.len);
+		mutex_unlock(&u->reply_mutex);
+		kfree(reply);
+		break;
+	}
+
+ out:
+	u->len = 0;
+	return rc;
+}
+
+static int xenbus_dev_open(struct inode *inode, struct file *filp)
+{
+	struct xenbus_dev_data *u;
+
+	if (xen_store_evtchn == 0)
+		return -ENOENT;
+
+	nonseekable_open(inode, filp);
+
+	u = kzalloc(sizeof(*u), GFP_KERNEL);
+	if (u == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&u->transactions);
+	INIT_LIST_HEAD(&u->watches);
+	INIT_LIST_HEAD(&u->read_buffers);
+	init_waitqueue_head(&u->read_waitq);
+
+	mutex_init(&u->reply_mutex);
+
+	filp->private_data = u;
+
+	return 0;
+}
+
+static int xenbus_dev_release(struct inode *inode, struct file *filp)
+{
+	struct xenbus_dev_data *u = filp->private_data;
+	struct xenbus_dev_transaction *trans, *tmp;
+	struct watch_adapter *watch, *tmp_watch;
+
+	list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
+		xenbus_transaction_end(trans->handle, 1);
+		list_del(&trans->list);
+		kfree(trans);
+	}
+
+	list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
+		unregister_xenbus_watch(&watch->watch);
+		list_del(&watch->list);
+		free_watch_adapter(watch);
+	}
+
+	kfree(u);
+
+	return 0;
+}
+
+static unsigned int xenbus_dev_poll(struct file *file, poll_table *wait)
+{
+	struct xenbus_dev_data *u = file->private_data;
+
+	if (!is_xenstored_ready())
+		return -ENODEV;
+
+	poll_wait(file, &u->read_waitq, wait);
+	if (!list_empty(&u->read_buffers))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+#ifdef HAVE_UNLOCKED_IOCTL
+static long xenbus_dev_ioctl(struct file *file,
+                             unsigned int cmd, unsigned long data)
+{
+	extern int xenbus_conn(domid_t remote_dom, int *grant_ref,
+	                       evtchn_port_t *local_port);
+	void __user *udata = (void __user *) data;
+	int ret = -ENOTTY;
+	
+	if (!is_initial_xendomain())
+		return -ENODEV;
+
+
+	switch (cmd) {
+	case IOCTL_XENBUS_ALLOC: {
+		xenbus_alloc_t xa;
+		int old;
+
+		old = atomic_cmpxchg(&xenbus_xsd_state,
+		                     XENBUS_XSD_UNCOMMITTED,
+		                     XENBUS_XSD_FOREIGN_INIT);
+		if (old != XENBUS_XSD_UNCOMMITTED)
+			return -EBUSY;
+
+		if (copy_from_user(&xa, udata, sizeof(xa))) {
+			ret = -EFAULT;
+			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
+			break;
+		}
+
+		ret = xenbus_conn(xa.dom, &xa.grant_ref, &xa.port);
+		if (ret != 0) {
+			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
+			break;
+		}
+
+		if (copy_to_user(udata, &xa, sizeof(xa))) {
+			ret = -EFAULT;
+			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
+			break;
+		}
+	}
+	break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+#endif
+
+static const struct file_operations xenbus_dev_file_ops = {
+	.read = xenbus_dev_read,
+	.write = xenbus_dev_write,
+	.open = xenbus_dev_open,
+	.release = xenbus_dev_release,
+	.poll = xenbus_dev_poll,
+#ifdef HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = xenbus_dev_ioctl
+#endif
+};
+
+int xenbus_dev_init(void)
+{
+	xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
+	if (xenbus_dev_intf)
+		xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/Makefile
+++ linux-ec2-2.6.32/drivers/xen/xenbus/Makefile
@@ -1,7 +1,9 @@
-obj-y	+= xenbus.o
+obj-y += xenbus_client.o xenbus_comms.o xenbus_xs.o xenbus_probe.o
+obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o
 
-xenbus-objs =
-xenbus-objs += xenbus_client.o
-xenbus-objs += xenbus_comms.o
-xenbus-objs += xenbus_xs.o
-xenbus-objs += xenbus_probe.o
+xenbus_be-objs =
+xenbus_be-objs += xenbus_backend_client.o
+
+xenbus-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o
+obj-y += $(xenbus-y) $(xenbus-m)
+obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_probe.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_probe.c
@@ -4,6 +4,7 @@
  * 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
@@ -32,37 +33,57 @@
 
 #define DPRINTK(fmt, args...)				\
 	pr_debug("xenbus_probe (%s:%d) " fmt ".\n",	\
-		 __func__, __LINE__, ##args)
+		 __FUNCTION__, __LINE__, ##args)
 
 #include <linux/kernel.h>
+#include <linux/version.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/notifier.h>
-#include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#if defined(CONFIG_XEN) || defined(MODULE)
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+#include <xen/xen_proc.h>
+#include <xen/evtchn.h>
+#include <xen/features.h>
+#include <xen/gnttab.h>
+#ifdef MODULE
+#include <xen/hvm.h>
+#endif
+#else
 #include <asm/xen/hypervisor.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
 #include <xen/page.h>
+#endif
 
 #include "xenbus_comms.h"
 #include "xenbus_probe.h"
 
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
 
 int xen_store_evtchn;
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 EXPORT_SYMBOL(xen_store_evtchn);
+#endif
 
 struct xenstore_domain_interface *xen_store_interface;
 static unsigned long xen_store_mfn;
 
+extern struct mutex xenwatch_mutex;
+
 static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
 
 static void wait_for_devices(struct xenbus_driver *xendrv);
@@ -71,8 +92,10 @@
 
 static void xenbus_dev_shutdown(struct device *_dev);
 
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 static int xenbus_dev_suspend(struct device *dev, pm_message_t state);
 static int xenbus_dev_resume(struct device *dev);
+#endif
 
 /* If something in array of ids matches this device, return it. */
 static const struct xenbus_device_id *
@@ -95,16 +118,6 @@
 	return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
 }
 
-static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
-{
-	struct xenbus_device *dev = to_xenbus_device(_dev);
-
-	if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
-		return -ENOMEM;
-
-	return 0;
-}
-
 /* device/<type>/<id> => <type>-<id> */
 static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
 {
@@ -173,9 +186,33 @@
 	return read_otherend_details(xendev, "backend-id", "backend");
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+static int xenbus_uevent_frontend(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct xenbus_device *xdev;
+
+	if (dev == NULL)
+		return -ENODEV;
+	xdev = to_xenbus_device(dev);
+	if (xdev == NULL)
+		return -ENODEV;
+
+	/* stuff we want to pass to /sbin/hotplug */
+#if defined(CONFIG_XEN) || defined(MODULE)
+	add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype);
+	add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename);
+#endif
+	add_uevent_var(env, "MODALIAS=xen:%s", xdev->devicetype);
+
+	return 0;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
 static struct device_attribute xenbus_dev_attrs[] = {
 	__ATTR_NULL
 };
+#endif
 
 /* Bus type for frontend drivers. */
 static struct xen_bus_type xenbus_frontend = {
@@ -183,18 +220,29 @@
 	.levels = 2, 		/* device/type/<id> */
 	.get_bus_id = frontend_bus_id,
 	.probe = xenbus_probe_frontend,
+	.error = -ENODEV,
 	.bus = {
 		.name      = "xen",
 		.match     = xenbus_match,
-		.uevent    = xenbus_uevent,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
 		.probe     = xenbus_dev_probe,
 		.remove    = xenbus_dev_remove,
 		.shutdown  = xenbus_dev_shutdown,
+		.uevent    = xenbus_uevent_frontend,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
 		.dev_attrs = xenbus_dev_attrs,
-
+#endif
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 		.suspend   = xenbus_dev_suspend,
 		.resume    = xenbus_dev_resume,
+#endif
+	},
+#if defined(CONFIG_XEN) || defined(MODULE)
+	.dev = {
+		.init_name = "xen",
 	},
+#endif
 };
 
 static void otherend_changed(struct xenbus_watch *watch,
@@ -210,17 +258,17 @@
 	if (!dev->otherend ||
 	    strncmp(dev->otherend, vec[XS_WATCH_PATH],
 		    strlen(dev->otherend))) {
-		dev_dbg(&dev->dev, "Ignoring watch at %s\n",
-			vec[XS_WATCH_PATH]);
+		dev_dbg(&dev->dev, "Ignoring watch at %s", vec[XS_WATCH_PATH]);
 		return;
 	}
 
 	state = xenbus_read_driver_state(dev->otherend);
 
-	dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
+	dev_dbg(&dev->dev, "state is %d (%s), %s, %s",
 		state, xenbus_strstate(state), dev->otherend_watch.node,
 		vec[XS_WATCH_PATH]);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
 	/*
 	 * Ignore xenbus transitions during shutdown. This prevents us doing
 	 * work that can fail e.g., when the rootfs is gone.
@@ -234,6 +282,7 @@
 			xenbus_frontend_closed(dev);
 		return;
 	}
+#endif
 
 	if (drv->otherend_changed)
 		drv->otherend_changed(dev, state);
@@ -253,8 +302,13 @@
 
 static int watch_otherend(struct xenbus_device *dev)
 {
+#if defined(CONFIG_XEN) || defined(MODULE)
+	return xenbus_watch_path2(dev, dev->otherend, "state",
+				  &dev->otherend_watch, otherend_changed);
+#else
 	return xenbus_watch_pathfmt(dev, &dev->otherend_watch, otherend_changed,
 				    "%s/%s", dev->otherend, "state");
+#endif
 }
 
 
@@ -280,8 +334,9 @@
 
 	err = talk_to_otherend(dev);
 	if (err) {
-		dev_warn(&dev->dev, "talk_to_otherend on %s failed.\n",
-			 dev->nodename);
+		dev_warn(&dev->dev,
+		         "xenbus_probe: talk_to_otherend on %s failed.\n",
+		         dev->nodename);
 		return err;
 	}
 
@@ -291,8 +346,9 @@
 
 	err = watch_otherend(dev);
 	if (err) {
-		dev_warn(&dev->dev, "watch_otherend on %s failed.\n",
-		       dev->nodename);
+		dev_warn(&dev->dev,
+		         "xenbus_probe: watch_otherend on %s failed.\n",
+		         dev->nodename);
 		return err;
 	}
 
@@ -327,17 +383,25 @@
 
 	DPRINTK("%s", dev->nodename);
 
+/* Commented out since xenstored stubdom is now minios based not linux based
+#define XENSTORE_DOMAIN_SHARES_THIS_KERNEL
+*/
+#ifndef XENSTORE_DOMAIN_SHARES_THIS_KERNEL
+	if (is_initial_xendomain())
+#endif
+		return;
+
 	get_device(&dev->dev);
 	if (dev->state != XenbusStateConnected) {
-		printk(KERN_INFO "%s: %s: %s != Connected, skipping\n", __func__,
-		       dev->nodename, xenbus_strstate(dev->state));
+		dev_info(&dev->dev, "%s: %s: %s != Connected, skipping\n", __FUNCTION__,
+		         dev->nodename, xenbus_strstate(dev->state));
 		goto out;
 	}
 	xenbus_switch_state(dev, XenbusStateClosing);
 	timeout = wait_for_completion_timeout(&dev->down, timeout);
 	if (!timeout)
-		printk(KERN_INFO "%s: %s timeout closing device\n",
-		       __func__, dev->nodename);
+		dev_info(&dev->dev, "%s: %s timeout closing device\n",
+		         __FUNCTION__, dev->nodename);
  out:
 	put_device(&dev->dev);
 }
@@ -347,12 +411,29 @@
 				  struct module *owner,
 				  const char *mod_name)
 {
+	int ret;
+
+	if (bus->error)
+		return bus->error;
+
 	drv->driver.name = drv->name;
 	drv->driver.bus = &bus->bus;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
 	drv->driver.owner = owner;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
 	drv->driver.mod_name = mod_name;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+	drv->driver.probe = xenbus_dev_probe;
+	drv->driver.remove = xenbus_dev_remove;
+	drv->driver.shutdown = xenbus_dev_shutdown;
+#endif
 
-	return driver_register(&drv->driver);
+	mutex_lock(&xenwatch_mutex);
+	ret = driver_register(&drv->driver);
+	mutex_unlock(&xenwatch_mutex);
+	return ret;
 }
 
 int __xenbus_register_frontend(struct xenbus_driver *drv,
@@ -450,21 +531,30 @@
 }
 
 static ssize_t xendev_show_nodename(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
+				    struct device_attribute *attr,
+#endif
+				    char *buf)
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
 }
-DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
+static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
 
 static ssize_t xendev_show_devtype(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
+				   struct device_attribute *attr,
+#endif
+				   char *buf)
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
 }
 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
 
 static ssize_t xendev_show_modalias(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
+				    struct device_attribute *attr,
+#endif
+				    char *buf)
 {
 	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
 }
@@ -474,7 +564,6 @@
 		      const char *type,
 		      const char *nodename)
 {
-	char devname[XEN_BUS_ID_SIZE];
 	int err;
 	struct xenbus_device *xendev;
 	size_t stringlen;
@@ -482,6 +571,9 @@
 
 	enum xenbus_state state = xenbus_read_driver_state(nodename);
 
+	if (bus->error)
+		return bus->error;
+
 	if (state != XenbusStateInitialising) {
 		/* Device is not new, so ignore it.  This can happen if a
 		   device is going away after switching to Closed.  */
@@ -506,15 +598,26 @@
 	xendev->devicetype = tmpstring;
 	init_completion(&xendev->down);
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+	xendev->dev.parent = &bus->dev;
+#endif
 	xendev->dev.bus = &bus->bus;
 	xendev->dev.release = xenbus_dev_release;
 
-	err = bus->get_bus_id(devname, xendev->nodename);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+	{
+		char devname[XEN_BUS_ID_SIZE];
+
+		err = bus->get_bus_id(devname, xendev->nodename);
+		if (!err)
+			dev_set_name(&xendev->dev, devname);
+	}
+#else
+	err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
+#endif
 	if (err)
 		goto fail;
 
-	dev_set_name(&xendev->dev, devname);
-
 	/* Register with generic device framework. */
 	err = device_register(&xendev->dev);
 	if (err)
@@ -588,6 +691,9 @@
 	char **dir;
 	unsigned int i, dir_n;
 
+	if (bus->error)
+		return bus->error;
+
 	dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n);
 	if (IS_ERR(dir))
 		return PTR_ERR(dir);
@@ -631,7 +737,7 @@
 	char type[XEN_BUS_ID_SIZE];
 	const char *p, *root;
 
-	if (char_count(node, '/') < 2)
+	if (bus->error || char_count(node, '/') < 2)
 		return;
 
 	exists = xenbus_exists(XBT_NIL, node, "");
@@ -660,7 +766,9 @@
 
 	kfree(root);
 }
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 EXPORT_SYMBOL_GPL(xenbus_dev_changed);
+#endif
 
 static void frontend_changed(struct xenbus_watch *watch,
 			     const char **vec, unsigned int len)
@@ -676,7 +784,11 @@
 	.callback = frontend_changed,
 };
 
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
+#else
+static int suspend_dev(struct device *dev, void *data)
+#endif
 {
 	int err = 0;
 	struct xenbus_driver *drv;
@@ -689,14 +801,45 @@
 	drv = to_xenbus_driver(dev->driver);
 	xdev = container_of(dev, struct xenbus_device, dev);
 	if (drv->suspend)
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 		err = drv->suspend(xdev, state);
+#else
+		err = drv->suspend(xdev);
+#endif
 	if (err)
 		printk(KERN_WARNING
 		       "xenbus: suspend %s failed: %i\n", dev_name(dev), err);
 	return 0;
 }
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+static int suspend_cancel_dev(struct device *dev, void *data)
+{
+	int err = 0;
+	struct xenbus_driver *drv;
+	struct xenbus_device *xdev;
+
+	DPRINTK("");
+
+	if (dev->driver == NULL)
+		return 0;
+	drv = to_xenbus_driver(dev->driver);
+	xdev = container_of(dev, struct xenbus_device, dev);
+	if (drv->suspend_cancel)
+		err = drv->suspend_cancel(xdev);
+	if (err)
+		printk(KERN_WARNING
+		       "xenbus: suspend_cancel %s failed: %i\n",
+		       dev_name(dev), err);
+	return 0;
+}
+#endif
+
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 static int xenbus_dev_resume(struct device *dev)
+#else
+static int resume_dev(struct device *dev, void *data)
+#endif
 {
 	int err;
 	struct xenbus_driver *drv;
@@ -741,15 +884,47 @@
 	return 0;
 }
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+void xenbus_suspend(void)
+{
+	DPRINTK("");
+
+	if (!xenbus_frontend.error)
+		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
+	xenbus_backend_suspend(suspend_dev);
+	xs_suspend();
+}
+EXPORT_SYMBOL_GPL(xenbus_suspend);
+
+void xenbus_resume(void)
+{
+	xb_init_comms();
+	xs_resume();
+	if (!xenbus_frontend.error)
+		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
+	xenbus_backend_resume(resume_dev);
+}
+EXPORT_SYMBOL_GPL(xenbus_resume);
+
+void xenbus_suspend_cancel(void)
+{
+	xs_suspend_cancel();
+	if (!xenbus_frontend.error)
+		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev);
+	xenbus_backend_resume(suspend_cancel_dev);
+}
+EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
+#endif
+
 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
-int xenstored_ready = 0;
+atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED);
 
 
 int register_xenstore_notifier(struct notifier_block *nb)
 {
 	int ret = 0;
 
-	if (xenstored_ready > 0)
+	if (is_xenstored_ready())
 		ret = nb->notifier_call(nb, 0, NULL);
 	else
 		blocking_notifier_chain_register(&xenstore_chain, nb);
@@ -764,9 +939,10 @@
 }
 EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
 
+
 void xenbus_probe(struct work_struct *unused)
 {
-	BUG_ON((xenstored_ready <= 0));
+	BUG_ON(!is_xenstored_ready());
 
 	/* Enumerate devices in xenstore and watch for changes. */
 	xenbus_probe_devices(&xenbus_frontend);
@@ -777,49 +953,245 @@
 	blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
 }
 
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
+static struct file_operations xsd_kva_fops;
+static struct proc_dir_entry *xsd_kva_intf;
+static struct proc_dir_entry *xsd_port_intf;
+
+static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	size_t size = vma->vm_end - vma->vm_start;
+	int old;
+	int rc;
+
+	old = atomic_cmpxchg(&xenbus_xsd_state,
+	                   XENBUS_XSD_UNCOMMITTED,
+	                   XENBUS_XSD_LOCAL_INIT);
+	switch (old) {
+		case XENBUS_XSD_UNCOMMITTED:
+			rc = xb_init_comms();
+			if (rc != 0)
+				return rc;
+			break;
+
+		case XENBUS_XSD_FOREIGN_INIT:
+		case XENBUS_XSD_FOREIGN_READY:
+			return -EBUSY;
+
+		case XENBUS_XSD_LOCAL_INIT:
+		case XENBUS_XSD_LOCAL_READY:
+		default:
+			break;
+	}
+
+	if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
+		return -EINVAL;
+
+	if (remap_pfn_range(vma, vma->vm_start, mfn_to_pfn(xen_store_mfn),
+			    size, vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int xsd_kva_read(char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int len;
+
+	len  = sprintf(page, "0x%p", xen_store_interface);
+	*eof = 1;
+	return len;
+}
+
+static int xsd_port_read(char *page, char **start, off_t off,
+			 int count, int *eof, void *data)
+{
+	int len;
+
+	len  = sprintf(page, "%d", xen_store_evtchn);
+	*eof = 1;
+	return len;
+}
+#endif
+
+#if defined(CONFIG_XEN) || defined(MODULE)
+static int xb_free_port(evtchn_port_t port)
+{
+	struct evtchn_close close;
+	close.port = port;
+	return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
+}
+
+int xenbus_conn(domid_t remote_dom, unsigned long *grant_ref, evtchn_port_t *local_port)
+{
+	struct evtchn_alloc_unbound alloc_unbound;
+	int rc, rc2;
+
+	BUG_ON(atomic_read(&xenbus_xsd_state) != XENBUS_XSD_FOREIGN_INIT);
+	BUG_ON(!is_initial_xendomain());
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
+	remove_xen_proc_entry("xsd_kva");
+	remove_xen_proc_entry("xsd_port");
+#endif
+
+	rc = xb_free_port(xen_store_evtchn);
+	if (rc != 0)
+		goto fail0;
+
+	alloc_unbound.dom = DOMID_SELF;
+	alloc_unbound.remote_dom = remote_dom;
+	rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+	                                 &alloc_unbound);
+	if (rc != 0)
+		goto fail0;
+	*local_port = xen_store_evtchn = alloc_unbound.port;
+
+	/* keep the old page (xen_store_mfn, xen_store_interface) */
+	rc = gnttab_grant_foreign_access(remote_dom, xen_store_mfn,
+	                                 GTF_permit_access);
+	if (rc < 0)
+		goto fail1;
+	*grant_ref = rc;
+
+	rc = xb_init_comms();
+	if (rc != 0)
+		goto fail1;
+
+	return 0;
+
+fail1:
+	rc2 = xb_free_port(xen_store_evtchn);
+	if (rc2 != 0)
+		printk(KERN_WARNING
+		       "XENBUS: Error freeing xenstore event channel: %d\n",
+		       rc2);
+fail0:
+	xen_store_evtchn = -1;
+	return rc;
+}
+#endif
+
+#ifndef MODULE
 static int __init xenbus_probe_init(void)
+#else
+static int __devinit xenbus_probe_init(void)
+#endif
 {
 	int err = 0;
+#if defined(CONFIG_XEN) || defined(MODULE)
+	unsigned long page = 0;
+#endif
 
 	DPRINTK("");
 
-	err = -ENODEV;
-	if (!xen_domain())
-		goto out_error;
+	if (!is_running_on_xen())
+		return -ENODEV;
 
 	/* Register ourselves with the kernel bus subsystem */
-	err = bus_register(&xenbus_frontend.bus);
-	if (err)
-		goto out_error;
-
-	err = xenbus_backend_bus_register();
-	if (err)
-		goto out_unreg_front;
+	xenbus_frontend.error = bus_register(&xenbus_frontend.bus);
+	if (xenbus_frontend.error)
+		printk(KERN_WARNING
+		       "XENBUS: Error registering frontend bus: %i\n",
+		       xenbus_frontend.error);
+	xenbus_backend_bus_register();
 
 	/*
 	 * Domain0 doesn't have a store_evtchn or store_mfn yet.
 	 */
-	if (xen_initial_domain()) {
+	if (is_initial_xendomain()) {
+#if defined(CONFIG_XEN) || defined(MODULE)
+		struct evtchn_alloc_unbound alloc_unbound;
+
+		/* Allocate page. */
+		page = get_zeroed_page(GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+
+		xen_store_mfn = xen_start_info->store_mfn =
+			pfn_to_mfn(virt_to_phys((void *)page) >>
+				   PAGE_SHIFT);
+
+		/* Next allocate a local port which xenstored can bind to */
+		alloc_unbound.dom        = DOMID_SELF;
+		alloc_unbound.remote_dom = DOMID_SELF;
+
+		err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+						  &alloc_unbound);
+		if (err == -ENOSYS)
+			goto err;
+		BUG_ON(err);
+		xen_store_evtchn = xen_start_info->store_evtchn =
+			alloc_unbound.port;
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
+		/* And finally publish the above info in /proc/xen */
+		xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0600);
+		if (xsd_kva_intf) {
+			memcpy(&xsd_kva_fops, xsd_kva_intf->proc_fops,
+			       sizeof(xsd_kva_fops));
+			xsd_kva_fops.mmap = xsd_kva_mmap;
+			xsd_kva_intf->proc_fops = &xsd_kva_fops;
+			xsd_kva_intf->read_proc = xsd_kva_read;
+		}
+		xsd_port_intf = create_xen_proc_entry("xsd_port", 0400);
+		if (xsd_port_intf)
+			xsd_port_intf->read_proc = xsd_port_read;
+#endif
+#else
 		/* dom0 not yet supported */
+#endif
+		xen_store_interface = mfn_to_virt(xen_store_mfn);
 	} else {
-		xenstored_ready = 1;
+		atomic_set(&xenbus_xsd_state, XENBUS_XSD_FOREIGN_READY);
+#ifndef MODULE
 		xen_store_evtchn = xen_start_info->store_evtchn;
 		xen_store_mfn = xen_start_info->store_mfn;
+		xen_store_interface = mfn_to_virt(xen_store_mfn);
+#else
+		xen_store_evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
+		xen_store_mfn = hvm_get_parameter(HVM_PARAM_STORE_PFN);
+		xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT,
+					      PAGE_SIZE);
+#endif
+		/* Initialize the shared memory rings to talk to xenstored */
+		err = xb_init_comms();
+		if (err)
+			goto err;
 	}
-	xen_store_interface = mfn_to_virt(xen_store_mfn);
+
+#if defined(CONFIG_XEN) || defined(MODULE)
+	xenbus_dev_init();
+#endif
 
 	/* Initialize the interface to xenstore. */
 	err = xs_init();
 	if (err) {
 		printk(KERN_WARNING
 		       "XENBUS: Error initializing xenstore comms: %i\n", err);
-		goto out_unreg_back;
+		goto err;
+	}
+
+#if defined(CONFIG_XEN) || defined(MODULE)
+	/* Register ourselves with the kernel device subsystem */
+	if (!xenbus_frontend.error) {
+		xenbus_frontend.error = device_register(&xenbus_frontend.dev);
+		if (xenbus_frontend.error) {
+			bus_unregister(&xenbus_frontend.bus);
+			printk(KERN_WARNING
+			       "XENBUS: Error registering frontend device: %i\n",
+			       xenbus_frontend.error);
+		}
 	}
+#endif
+	xenbus_backend_device_register();
 
-	if (!xen_initial_domain())
+	if (!is_initial_xendomain())
 		xenbus_probe(NULL);
 
-#ifdef CONFIG_XEN_COMPAT_XENFS
+#if defined(CONFIG_XEN_COMPAT_XENFS) && !defined(MODULE)
 	/*
 	 * Create xenfs mountpoint in /proc for compatibility with
 	 * utilities that expect to find "xenbus" under "/proc/xen".
@@ -829,21 +1201,36 @@
 
 	return 0;
 
-  out_unreg_back:
-	xenbus_backend_bus_unregister();
+ err:
+#if defined(CONFIG_XEN) || defined(MODULE)
+	if (page)
+		free_page(page);
+#endif
 
-  out_unreg_front:
-	bus_unregister(&xenbus_frontend.bus);
+	/*
+	 * Do not unregister the xenbus front/backend buses here. The buses
+	 * must exist because front/backend drivers will use them when they are
+	 * registered.
+	 */
 
-  out_error:
 	return err;
 }
 
+#ifndef MODULE
 postcore_initcall(xenbus_probe_init);
-
+#ifdef CONFIG_XEN
+MODULE_LICENSE("Dual BSD/GPL");
+#else
 MODULE_LICENSE("GPL");
+#endif
+#else
+int __devinit xenbus_init(void)
+{
+	return xenbus_probe_init();
+}
+#endif
 
-static int is_disconnected_device(struct device *dev, void *data)
+static int is_device_connecting(struct device *dev, void *data)
 {
 	struct xenbus_device *xendev = to_xenbus_device(dev);
 	struct device_driver *drv = data;
@@ -861,20 +1248,24 @@
 		return 0;
 
 	xendrv = to_xenbus_driver(dev->driver);
-	return (xendev->state != XenbusStateConnected ||
-		(xendrv->is_ready && !xendrv->is_ready(xendev)));
+	return (xendev->state < XenbusStateConnected ||
+		(xendev->state == XenbusStateConnected &&
+		 xendrv->is_ready && !xendrv->is_ready(xendev)));
 }
 
-static int exists_disconnected_device(struct device_driver *drv)
+static int exists_connecting_device(struct device_driver *drv)
 {
+	if (xenbus_frontend.error)
+		return xenbus_frontend.error;
 	return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
-				is_disconnected_device);
+				is_device_connecting);
 }
 
 static int print_device_status(struct device *dev, void *data)
 {
 	struct xenbus_device *xendev = to_xenbus_device(dev);
 	struct device_driver *drv = data;
+	struct xenbus_driver *xendrv;
 
 	/* Is this operation limited to a particular driver? */
 	if (drv && (dev->driver != drv))
@@ -884,12 +1275,23 @@
 		/* Information only: is this too noisy? */
 		printk(KERN_INFO "XENBUS: Device with no driver: %s\n",
 		       xendev->nodename);
-	} else if (xendev->state != XenbusStateConnected) {
+		return 0;
+	}
+
+	if (xendev->state < XenbusStateConnected) {
+		enum xenbus_state rstate = XenbusStateUnknown;
+		if (xendev->otherend)
+			rstate = xenbus_read_driver_state(xendev->otherend);
 		printk(KERN_WARNING "XENBUS: Timeout connecting "
-		       "to device: %s (state %d)\n",
-		       xendev->nodename, xendev->state);
+		       "to device: %s (local state %d, remote state %d)\n",
+		       xendev->nodename, xendev->state, rstate);
 	}
 
+	xendrv = to_xenbus_driver(dev->driver);
+	if (xendrv->is_ready && !xendrv->is_ready(xendev))
+		printk(KERN_WARNING "XENBUS: Device not ready: %s\n",
+		       xendev->nodename);
+
 	return 0;
 }
 
@@ -897,7 +1299,7 @@
 static int ready_to_wait_for_devices;
 
 /*
- * On a 10 second timeout, wait for all devices currently configured.  We need
+ * On a 5-minute timeout, wait for all devices currently configured.  We need
  * to do this to guarantee that the filesystems and / or network devices
  * needed for boot are available, before we can allow the boot to proceed.
  *
@@ -912,18 +1314,30 @@
  */
 static void wait_for_devices(struct xenbus_driver *xendrv)
 {
-	unsigned long timeout = jiffies + 10*HZ;
+	unsigned long start = jiffies;
 	struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
+	unsigned int seconds_waited = 0;
 
-	if (!ready_to_wait_for_devices || !xen_domain())
+	if (!ready_to_wait_for_devices || !is_running_on_xen())
 		return;
 
-	while (exists_disconnected_device(drv)) {
-		if (time_after(jiffies, timeout))
-			break;
+	while (exists_connecting_device(drv)) {
+		if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
+			if (!seconds_waited)
+				printk(KERN_WARNING "XENBUS: Waiting for "
+				       "devices to initialise: ");
+			seconds_waited += 5;
+			printk("%us...", 300 - seconds_waited);
+			if (seconds_waited == 300)
+				break;
+		}
+
 		schedule_timeout_interruptible(HZ/10);
 	}
 
+	if (seconds_waited)
+		printk("\n");
+
 	bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
 			 print_device_status);
 }
@@ -931,10 +1345,18 @@
 #ifndef MODULE
 static int __init boot_wait_for_devices(void)
 {
-	ready_to_wait_for_devices = 1;
-	wait_for_devices(NULL);
+	if (!xenbus_frontend.error) {
+		ready_to_wait_for_devices = 1;
+		wait_for_devices(NULL);
+	}
 	return 0;
 }
 
 late_initcall(boot_wait_for_devices);
 #endif
+
+int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *))
+{
+	return bus_for_each_dev(&xenbus_frontend.bus, NULL, arg, fn);
+}
+EXPORT_SYMBOL_GPL(xenbus_for_each_frontend);
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_probe.h
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_probe.h
@@ -34,29 +34,46 @@
 #ifndef _XENBUS_PROBE_H
 #define _XENBUS_PROBE_H
 
+#ifndef BUS_ID_SIZE
 #define XEN_BUS_ID_SIZE			20
+#else
+#define XEN_BUS_ID_SIZE			BUS_ID_SIZE
+#endif
+
+#ifdef CONFIG_PARAVIRT_XEN
+#define is_running_on_xen() xen_domain()
+#define is_initial_xendomain() xen_initial_domain()
+#endif
 
-#ifdef CONFIG_XEN_BACKEND
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+#define dev_name(dev) ((dev)->bus_id)
+#endif
+
+#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
 extern void xenbus_backend_suspend(int (*fn)(struct device *, void *));
 extern void xenbus_backend_resume(int (*fn)(struct device *, void *));
 extern void xenbus_backend_probe_and_watch(void);
-extern int xenbus_backend_bus_register(void);
-extern void xenbus_backend_bus_unregister(void);
+extern void xenbus_backend_bus_register(void);
+extern void xenbus_backend_device_register(void);
 #else
 static inline void xenbus_backend_suspend(int (*fn)(struct device *, void *)) {}
 static inline void xenbus_backend_resume(int (*fn)(struct device *, void *)) {}
 static inline void xenbus_backend_probe_and_watch(void) {}
-static inline int xenbus_backend_bus_register(void) { return 0; }
-static inline void xenbus_backend_bus_unregister(void) {}
+static inline void xenbus_backend_bus_register(void) {}
+static inline void xenbus_backend_device_register(void) {}
 #endif
 
 struct xen_bus_type
 {
 	char *root;
+	int error;
 	unsigned int levels;
 	int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
 	int (*probe)(const char *type, const char *dir);
 	struct bus_type bus;
+#if defined(CONFIG_XEN) || defined(MODULE)
+	struct device dev;
+#endif
 };
 
 extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_comms.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_comms.c
@@ -35,24 +35,57 @@
 #include <linux/sched.h>
 #include <linux/err.h>
 #include <xen/xenbus.h>
+#if defined(CONFIG_XEN) || defined(MODULE)
+#include <xen/evtchn.h>
+#include <asm/hypervisor.h>
+#else
 #include <asm/xen/hypervisor.h>
 #include <xen/events.h>
 #include <xen/page.h>
+#endif
+
 #include "xenbus_comms.h"
 
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
 static int xenbus_irq;
 
+extern void xenbus_probe(struct work_struct *);
 static DECLARE_WORK(probe_work, xenbus_probe);
 
 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 
 static irqreturn_t wake_waiting(int irq, void *unused)
 {
-	if (unlikely(xenstored_ready == 0)) {
-		xenstored_ready = 1;
-		schedule_work(&probe_work);
+	int old, new;
+
+	old = atomic_read(&xenbus_xsd_state);
+	switch (old) {
+		case XENBUS_XSD_UNCOMMITTED:
+			BUG();
+			return IRQ_HANDLED;
+
+		case XENBUS_XSD_FOREIGN_INIT:
+			new = XENBUS_XSD_FOREIGN_READY;
+			break;
+
+		case XENBUS_XSD_LOCAL_INIT:
+			new = XENBUS_XSD_LOCAL_READY;
+			break;
+
+		case XENBUS_XSD_FOREIGN_READY:
+		case XENBUS_XSD_LOCAL_READY:
+		default:
+			goto wake;
 	}
 
+	old = atomic_cmpxchg(&xenbus_xsd_state, old, new);
+	if (old != new)
+		schedule_work(&probe_work);
+
+wake:
 	wake_up(&xb_waitq);
 	return IRQ_HANDLED;
 }
@@ -203,6 +236,7 @@
 int xb_init_comms(void)
 {
 	struct xenstore_domain_interface *intf = xen_store_interface;
+	int err;
 
 	if (intf->req_prod != intf->req_cons)
 		printk(KERN_ERR "XENBUS request ring is not quiescent "
@@ -215,20 +249,33 @@
 		intf->rsp_cons = intf->rsp_prod;
 	}
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+	if (xenbus_irq)
+		unbind_from_irqhandler(xenbus_irq, &xb_waitq);
+
+	err = bind_caller_port_to_irqhandler(
+		xen_store_evtchn, wake_waiting,
+		0, "xenbus", &xb_waitq);
+	if (err <= 0) {
+		printk(KERN_ERR "XENBUS request irq failed %i\n", err);
+		return err;
+	}
+
+	xenbus_irq = err;
+#else
 	if (xenbus_irq) {
 		/* Already have an irq; assume we're resuming */
 		rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
 	} else {
-		int err;
 		err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
 						0, "xenbus", &xb_waitq);
 		if (err <= 0) {
 			printk(KERN_ERR "XENBUS request irq failed %i\n", err);
 			return err;
 		}
-
 		xenbus_irq = err;
 	}
+#endif
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_xs.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_xs.c
@@ -47,6 +47,14 @@
 #include <xen/xenbus.h>
 #include "xenbus_comms.h"
 
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#ifndef PF_NOFREEZE /* Old kernel (pre-2.6.6). */
+#define PF_NOFREEZE	0
+#endif
+
 struct xs_stored_msg {
 	struct list_head list;
 
@@ -76,6 +84,14 @@
 	/*
 	 * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex.
 	 * response_mutex is never taken simultaneously with the other three.
+	 *
+	 * transaction_mutex must be held before incrementing
+	 * transaction_count. The mutex is held when a suspend is in
+	 * progress to prevent new transactions starting.
+	 *
+	 * When decrementing transaction_count to zero the wait queue
+	 * should be woken up, the suspend code waits for count to
+	 * reach zero.
 	 */
 
 	/* One request at a time. */
@@ -85,7 +101,9 @@
 	struct mutex response_mutex;
 
 	/* Protect transactions against save/restore. */
-	struct rw_semaphore transaction_mutex;
+	struct mutex transaction_mutex;
+	atomic_t transaction_count;
+	wait_queue_head_t transaction_wq;
 
 	/* Protect watch (de)register against save/restore. */
 	struct rw_semaphore watch_mutex;
@@ -108,7 +126,7 @@
  * carrying out work.
  */
 static pid_t xenwatch_pid;
-static DEFINE_MUTEX(xenwatch_mutex);
+/* static */ DEFINE_MUTEX(xenwatch_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
 
 static int get_error(const char *errorstring)
@@ -157,6 +175,31 @@
 	return body;
 }
 
+static void transaction_start(void)
+{
+	mutex_lock(&xs_state.transaction_mutex);
+	atomic_inc(&xs_state.transaction_count);
+	mutex_unlock(&xs_state.transaction_mutex);
+}
+
+static void transaction_end(void)
+{
+	if (atomic_dec_and_test(&xs_state.transaction_count))
+		wake_up(&xs_state.transaction_wq);
+}
+
+static void transaction_suspend(void)
+{
+	mutex_lock(&xs_state.transaction_mutex);
+	wait_event(xs_state.transaction_wq,
+		   atomic_read(&xs_state.transaction_count) == 0);
+}
+
+static void transaction_resume(void)
+{
+	mutex_unlock(&xs_state.transaction_mutex);
+}
+
 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
 {
 	void *ret;
@@ -164,7 +207,7 @@
 	int err;
 
 	if (req_msg.type == XS_TRANSACTION_START)
-		down_read(&xs_state.transaction_mutex);
+		transaction_start();
 
 	mutex_lock(&xs_state.request_mutex);
 
@@ -177,14 +220,16 @@
 
 	mutex_unlock(&xs_state.request_mutex);
 
-	if ((msg->type == XS_TRANSACTION_END) ||
+	if ((req_msg.type == XS_TRANSACTION_END) ||
 	    ((req_msg.type == XS_TRANSACTION_START) &&
 	     (msg->type == XS_ERROR)))
-		up_read(&xs_state.transaction_mutex);
+		transaction_end();
 
 	return ret;
 }
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 EXPORT_SYMBOL(xenbus_dev_request_and_reply);
+#endif
 
 /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
 static void *xs_talkv(struct xenbus_transaction t,
@@ -295,7 +340,7 @@
 	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_NOIO | __GFP_HIGH);
@@ -309,6 +354,7 @@
 	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;
 }
@@ -432,11 +478,11 @@
 {
 	char *id_str;
 
-	down_read(&xs_state.transaction_mutex);
+	transaction_start();
 
 	id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
 	if (IS_ERR(id_str)) {
-		up_read(&xs_state.transaction_mutex);
+		transaction_end();
 		return PTR_ERR(id_str);
 	}
 
@@ -461,7 +507,7 @@
 
 	err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
 
-	up_read(&xs_state.transaction_mutex);
+	transaction_end();
 
 	return err;
 }
@@ -499,7 +545,7 @@
 #define PRINTF_BUFFER_SIZE 4096
 	char *printf_buffer;
 
-	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
 	if (printf_buffer == NULL)
 		return -ENOMEM;
 
@@ -622,6 +668,10 @@
 	char token[sizeof(watch) * 2 + 1];
 	int err;
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+	BUG_ON(watch->flags & XBWF_new_thread);
+#endif
+
 	sprintf(token, "%lX", (long)watch);
 
 	down_read(&xs_state.watch_mutex);
@@ -662,7 +712,7 @@
 
 void xs_suspend(void)
 {
-	down_write(&xs_state.transaction_mutex);
+	transaction_suspend();
 	down_write(&xs_state.watch_mutex);
 	mutex_lock(&xs_state.request_mutex);
 	mutex_lock(&xs_state.response_mutex);
@@ -673,11 +723,13 @@
 	struct xenbus_watch *watch;
 	char token[sizeof(watch) * 2 + 1];
 
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 	xb_init_comms();
+#endif
 
 	mutex_unlock(&xs_state.response_mutex);
 	mutex_unlock(&xs_state.request_mutex);
-	up_write(&xs_state.transaction_mutex);
+	transaction_resume();
 
 	/* No need for watches_lock: the watch_mutex is sufficient. */
 	list_for_each_entry(watch, &watches, list) {
@@ -693,14 +745,35 @@
 	mutex_unlock(&xs_state.response_mutex);
 	mutex_unlock(&xs_state.request_mutex);
 	up_write(&xs_state.watch_mutex);
-	up_write(&xs_state.transaction_mutex);
+	mutex_unlock(&xs_state.transaction_mutex);
 }
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+static int xenwatch_handle_callback(void *data)
+{
+	struct xs_stored_msg *msg = data;
+
+	msg->u.watch.handle->callback(msg->u.watch.handle,
+				      (const char **)msg->u.watch.vec,
+				      msg->u.watch.vec_size);
+
+	kfree(msg->u.watch.vec);
+	kfree(msg);
+
+	/* Kill this kthread if we were spawned just for this callback. */
+	if (current->pid != xenwatch_pid)
+		do_exit(0);
+
+	return 0;
+}
+#endif
+
 static int xenwatch_thread(void *unused)
 {
 	struct list_head *ent;
 	struct xs_stored_msg *msg;
 
+	current->flags |= PF_NOFREEZE;
 	for (;;) {
 		wait_event_interruptible(watch_events_waitq,
 					 !list_empty(&watch_events));
@@ -716,17 +789,39 @@
 			list_del(ent);
 		spin_unlock(&watch_events_lock);
 
-		if (ent != &watch_events) {
-			msg = list_entry(ent, struct xs_stored_msg, list);
-			msg->u.watch.handle->callback(
-				msg->u.watch.handle,
-				(const char **)msg->u.watch.vec,
-				msg->u.watch.vec_size);
-			kfree(msg->u.watch.vec);
-			kfree(msg);
+		if (ent == &watch_events) {
+			mutex_unlock(&xenwatch_mutex);
+			continue;
 		}
 
+		msg = list_entry(ent, struct xs_stored_msg, list);
+
+#if defined(CONFIG_XEN) || defined(MODULE)
+		/*
+		 * 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);
+		}
+#else
+		msg->u.watch.handle->callback(
+			msg->u.watch.handle,
+			(const char **)msg->u.watch.vec,
+			msg->u.watch.vec_size);
 		mutex_unlock(&xenwatch_mutex);
+		kfree(msg->u.watch.vec);
+		kfree(msg);
+#endif
 	}
 
 	return 0;
@@ -820,6 +915,7 @@
 {
 	int err;
 
+	current->flags |= PF_NOFREEZE;
 	for (;;) {
 		err = process_msg();
 		if (err)
@@ -834,7 +930,6 @@
 
 int xs_init(void)
 {
-	int err;
 	struct task_struct *task;
 
 	INIT_LIST_HEAD(&xs_state.reply_list);
@@ -843,13 +938,10 @@
 
 	mutex_init(&xs_state.request_mutex);
 	mutex_init(&xs_state.response_mutex);
-	init_rwsem(&xs_state.transaction_mutex);
+	mutex_init(&xs_state.transaction_mutex);
 	init_rwsem(&xs_state.watch_mutex);
-
-	/* Initialize the shared memory rings to talk to xenstored */
-	err = xb_init_comms();
-	if (err)
-		return err;
+	atomic_set(&xs_state.transaction_count, 0);
+	init_waitqueue_head(&xs_state.transaction_wq);
 
 	task = kthread_run(xenwatch_thread, NULL, "xenwatch");
 	if (IS_ERR(task))
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_backend_client.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_backend_client.c
@@ -0,0 +1,147 @@
+/******************************************************************************
+ * Backend-client-facing interface for the Xenbus driver.  In other words, the
+ * interface between the Xenbus and the device-specific code in the backend
+ * driver.
+ *
+ * Copyright (C) 2005-2006 XenSource Ltd
+ * 
+ * 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/err.h>
+#include <xen/gnttab.h>
+#include <xen/xenbus.h>
+#include <xen/driver_util.h>
+
+/* Based on Rusty Russell's skeleton driver's map_page */
+struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref)
+{
+	struct gnttab_map_grant_ref op;
+	struct vm_struct *area;
+
+	area = alloc_vm_area(PAGE_SIZE);
+	if (!area)
+		return ERR_PTR(-ENOMEM);
+
+	gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
+			  gnt_ref, dev->otherend_id);
+	
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status != GNTST_okay) {
+		free_vm_area(area);
+		xenbus_dev_fatal(dev, op.status,
+				 "mapping in shared page %d from domain %d",
+				 gnt_ref, dev->otherend_id);
+		BUG_ON(!IS_ERR(ERR_PTR(op.status)));
+		return ERR_PTR(op.status);
+	}
+
+	/* Stuff the handle in an unused field */
+	area->phys_addr = (unsigned long)op.handle;
+
+	return area;
+}
+EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
+
+
+int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
+		   grant_handle_t *handle, void *vaddr)
+{
+	struct gnttab_map_grant_ref op;
+	
+	gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
+			  gnt_ref, dev->otherend_id);
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status != GNTST_okay) {
+		xenbus_dev_fatal(dev, op.status,
+				 "mapping in shared page %d from domain %d",
+				 gnt_ref, dev->otherend_id);
+	} else
+		*handle = op.handle;
+
+	return op.status;
+}
+EXPORT_SYMBOL_GPL(xenbus_map_ring);
+
+
+/* Based on Rusty Russell's skeleton driver's unmap_page */
+int xenbus_unmap_ring_vfree(struct xenbus_device *dev, struct vm_struct *area)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
+			    (grant_handle_t)area->phys_addr);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status == GNTST_okay)
+		free_vm_area(area);
+	else
+		xenbus_dev_error(dev, op.status,
+				 "unmapping page at handle %d error %d",
+				 (int16_t)area->phys_addr, op.status);
+
+	return op.status;
+}
+EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
+
+
+int xenbus_unmap_ring(struct xenbus_device *dev,
+		     grant_handle_t handle, void *vaddr)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
+			    handle);
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status != GNTST_okay)
+		xenbus_dev_error(dev, op.status,
+				 "unmapping page at handle %d error %d",
+				 handle, op.status);
+
+	return op.status;
+}
+EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
+
+int xenbus_dev_is_online(struct xenbus_device *dev)
+{
+	int rc, val;
+
+	rc = xenbus_scanf(XBT_NIL, dev->nodename, "online", "%d", &val);
+	if (rc != 1)
+		val = 0; /* no online node present */
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_comms.h
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_comms.h
@@ -43,4 +43,20 @@
 extern struct xenstore_domain_interface *xen_store_interface;
 extern int xen_store_evtchn;
 
+/* For xenbus internal use. */
+enum {
+	XENBUS_XSD_UNCOMMITTED = 0,
+	XENBUS_XSD_FOREIGN_INIT,
+	XENBUS_XSD_FOREIGN_READY,
+	XENBUS_XSD_LOCAL_INIT,
+	XENBUS_XSD_LOCAL_READY,
+};
+extern atomic_t xenbus_xsd_state;
+
+static inline int is_xenstored_ready(void)
+{
+	int s = atomic_read(&xenbus_xsd_state);
+	return s == XENBUS_XSD_FOREIGN_READY || s == XENBUS_XSD_LOCAL_READY;
+}
+
 #endif /* _XENBUS_COMMS_H */
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_probe_backend.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_probe_backend.c
@@ -0,0 +1,285 @@
+/******************************************************************************
+ * 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/version.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, struct kobj_uevent_env *env);
+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[XEN_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, XEN_BUS_ID_SIZE, "%.*s-%i-%s",
+		     typelen, type, domid, devid) >= XEN_BUS_ID_SIZE)
+		return -ENOSPC;
+	return 0;
+}
+
+static struct device_attribute xenbus_backend_attrs[] = {
+	__ATTR_NULL
+};
+
+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_attrs = xenbus_backend_attrs,
+	},
+	.dev = {
+		.init_name = "xen-backend",
+	},
+};
+
+static int xenbus_uevent_backend(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct xenbus_device *xdev;
+	struct xenbus_driver *drv;
+
+	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(env, "XENBUS_TYPE=%s", xdev->devicetype);
+
+	add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename);
+
+	add_uevent_var(env, "XENBUS_BASE_PATH=%s", xenbus_backend.root);
+
+	if (dev->driver) {
+		drv = to_xenbus_driver(dev->driver);
+		if (drv && drv->uevent)
+			return drv->uevent(xdev, env);
+	}
+
+	return 0;
+}
+
+int __xenbus_register_backend(struct xenbus_driver *drv,
+			       struct module *owner, const char *mod_name)
+{
+	drv->read_otherend_details = read_frontend_details;
+
+	return xenbus_register_driver_common(drv, &xenbus_backend,
+					     owner, mod_name);
+}
+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("");
+
+	xenbus_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);
--- linux-ec2-2.6.32.orig/drivers/xen/xenbus/xenbus_client.c
+++ linux-ec2-2.6.32/drivers/xen/xenbus/xenbus_client.c
@@ -30,6 +30,12 @@
  * IN THE SOFTWARE.
  */
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+#include <linux/slab.h>
+#include <xen/evtchn.h>
+#include <xen/gnttab.h>
+#include <xen/driver_util.h>
+#else
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <asm/xen/hypervisor.h>
@@ -37,8 +43,13 @@
 #include <xen/interface/event_channel.h>
 #include <xen/events.h>
 #include <xen/grant_table.h>
+#endif
 #include <xen/xenbus.h>
 
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
 const char *xenbus_strstate(enum xenbus_state state)
 {
 	static const char *const name[] = {
@@ -49,6 +60,8 @@
 		[ XenbusStateConnected    ] = "Connected",
 		[ XenbusStateClosing      ] = "Closing",
 		[ XenbusStateClosed	  ] = "Closed",
+		[ XenbusStateReconfiguring ] = "Reconfiguring",
+		[ XenbusStateReconfigured ] = "Reconfigured",
 	};
 	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
 }
@@ -91,6 +104,26 @@
 EXPORT_SYMBOL_GPL(xenbus_watch_path);
 
 
+#if defined(CONFIG_XEN) || defined(MODULE)
+int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+		       const char *path2, struct xenbus_watch *watch,
+		       void (*callback)(struct xenbus_watch *,
+					const char **, unsigned int))
+{
+	int err;
+	char *state = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/%s", path, path2);
+	if (!state) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
+		return -ENOMEM;
+	}
+	err = xenbus_watch_path(dev, state, watch, callback);
+
+	if (err)
+		kfree(state);
+	return err;
+}
+EXPORT_SYMBOL_GPL(xenbus_watch_path2);
+#else
 /**
  * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path
  * @dev: xenbus device
@@ -131,6 +164,7 @@
 	return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
+#endif
 
 
 /**
@@ -200,13 +234,12 @@
 }
 
 
-static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
-				const char *fmt, va_list ap)
+static void _dev_error(struct xenbus_device *dev, int err,
+			const char *fmt, va_list ap)
 {
 	int ret;
 	unsigned int len;
-	char *printf_buffer = NULL;
-	char *path_buffer = NULL;
+	char *printf_buffer = NULL, *path_buffer = NULL;
 
 #define PRINTF_BUFFER_SIZE 4096
 	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
@@ -223,14 +256,16 @@
 	path_buffer = error_path(dev);
 
 	if (path_buffer == NULL) {
-		dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
-		       dev->nodename, printf_buffer);
+		dev_err(&dev->dev,
+		        "xenbus: failed to write error node for %s (%s)\n",
+		        dev->nodename, printf_buffer);
 		goto fail;
 	}
 
 	if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
-		dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
-		       dev->nodename, printf_buffer);
+		dev_err(&dev->dev,
+		        "xenbus: failed to write error node for %s (%s)\n",
+		        dev->nodename, printf_buffer);
 		goto fail;
 	}
 
@@ -249,16 +284,18 @@
  * Report the given negative errno into the store, along with the given
  * formatted message.
  */
-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
+void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
+		      ...)
 {
 	va_list ap;
 
 	va_start(ap, fmt);
-	xenbus_va_dev_error(dev, err, fmt, ap);
+	_dev_error(dev, err, fmt, ap);
 	va_end(ap);
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_error);
 
+
 /**
  * xenbus_dev_fatal
  * @dev: xenbus device
@@ -269,24 +306,25 @@
  * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly
  * closedown of this driver and its peer.
  */
-
-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
+void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+		      ...)
 {
 	va_list ap;
 
 	va_start(ap, fmt);
-	xenbus_va_dev_error(dev, err, fmt, ap);
+	_dev_error(dev, err, fmt, ap);
 	va_end(ap);
 
 	xenbus_switch_state(dev, XenbusStateClosing);
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
 
+
 /**
  * xenbus_grant_ring
  * @dev: xenbus device
  * @ring_mfn: mfn of ring to grant
-
+ *
  * Grant access to the given @ring_mfn to the peer of the given device.  Return
  * 0 on success, or -errno on error.  On error, the device will switch to
  * XenbusStateClosing, and the error will be saved in the store.
@@ -312,7 +350,7 @@
 	struct evtchn_alloc_unbound alloc_unbound;
 	int err;
 
-	alloc_unbound.dom = DOMID_SELF;
+	alloc_unbound.dom        = DOMID_SELF;
 	alloc_unbound.remote_dom = dev->otherend_id;
 
 	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
@@ -327,6 +365,7 @@
 EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
 
 
+#if 0 /* !defined(CONFIG_XEN) && !defined(MODULE) */
 /**
  * Bind to an existing interdomain event channel in another domain. Returns 0
  * on success and stores the local port in *port. On error, returns -errno,
@@ -352,6 +391,7 @@
 	return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
+#endif
 
 
 /**
@@ -373,6 +413,7 @@
 EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
 
 
+#if 0 /* !defined(CONFIG_XEN) && !defined(MODULE) */
 /**
  * xenbus_map_ring_valloc
  * @dev: xenbus device
@@ -547,6 +588,7 @@
 	return op.status;
 }
 EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
+#endif
 
 
 /**
--- linux-ec2-2.6.32.orig/drivers/xen/netback/loopback.c
+++ linux-ec2-2.6.32/drivers/xen/netback/loopback.c
@@ -0,0 +1,327 @@
+/******************************************************************************
+ * netback/loopback.c
+ * 
+ * A two-interface loopback device to emulate a local netfront-netback
+ * connection. This ensures that local packet delivery looks identical
+ * to inter-domain delivery. Most importantly, packets delivered locally
+ * originating from other domains will get *copied* when they traverse this
+ * driver. This prevents unbounded delays in socket-buffer queues from
+ * causing the netback driver to "seize up".
+ * 
+ * This driver creates a symmetric pair of loopback interfaces with names
+ * vif0.0 and veth0. The intention is that 'vif0.0' is bound to an Ethernet
+ * bridge, just like a proper netback interface, while a local IP interface
+ * is configured on 'veth0'.
+ * 
+ * As with a real netback interface, vif0.0 is configured with a suitable
+ * dummy MAC address. No default is provided for veth0: a reasonable strategy
+ * is to transfer eth0's MAC address to veth0, and give eth0 a dummy address
+ * (to avoid confusing the Etherbridge).
+ * 
+ * Copyright (c) 2005 K A Fraser
+ * 
+ * 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/module.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <net/dst.h>
+#include <net/xfrm.h>		/* secpath_reset() */
+#include <asm/hypervisor.h>	/* is_initial_xendomain() */
+#include <../net/core/kmap_skb.h> /* k{,un}map_skb_frag() */
+
+static int nloopbacks = -1;
+module_param(nloopbacks, int, 0);
+MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
+
+struct net_private {
+	struct net_device *loopback_dev;
+	struct net_device_stats stats;
+};
+
+static int loopback_open(struct net_device *dev)
+{
+	struct net_private *np = netdev_priv(dev);
+	memset(&np->stats, 0, sizeof(np->stats));
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int loopback_close(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+#ifdef CONFIG_X86
+static int is_foreign(unsigned long pfn)
+{
+	/* NB. Play it safe for auto-translation mode. */
+	return (xen_feature(XENFEAT_auto_translated_physmap) ||
+		(phys_to_machine_mapping[pfn] & FOREIGN_FRAME_BIT));
+}
+#else
+/* How to detect a foreign mapping? Play it safe. */
+#define is_foreign(pfn)	(1)
+#endif
+
+static int skb_remove_foreign_references(struct sk_buff *skb)
+{
+	struct page *page;
+	unsigned long pfn;
+	int i, off;
+	char *vaddr;
+
+	BUG_ON(skb_shinfo(skb)->frag_list);
+
+	if (skb_cloned(skb) &&
+	    unlikely(pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		return 0;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		pfn = page_to_pfn(skb_shinfo(skb)->frags[i].page);
+		if (!is_foreign(pfn))
+			continue;
+		
+		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+		if (unlikely(!page))
+			return 0;
+
+		vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
+		off = skb_shinfo(skb)->frags[i].page_offset;
+		memcpy(page_address(page) + off,
+		       vaddr + off,
+		       skb_shinfo(skb)->frags[i].size);
+		kunmap_skb_frag(vaddr);
+
+		put_page(skb_shinfo(skb)->frags[i].page);
+		skb_shinfo(skb)->frags[i].page = page;
+	}
+
+	return 1;
+}
+
+static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_private *np = netdev_priv(dev);
+
+	if (!skb_remove_foreign_references(skb)) {
+		np->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	dst_release(skb_dst(skb));
+	skb_dst_set(skb, NULL);
+
+	skb_orphan(skb);
+
+	np->stats.tx_bytes += skb->len;
+	np->stats.tx_packets++;
+
+	/* Switch to loopback context. */
+	dev = np->loopback_dev;
+	np  = netdev_priv(dev);
+
+	np->stats.rx_bytes += skb->len;
+	np->stats.rx_packets++;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		/* Defer checksum calculation. */
+		skb->proto_csum_blank = 1;
+		/* Must be a local packet: assert its integrity. */
+		skb->proto_data_valid = 1;
+	}
+
+	skb->ip_summed = skb->proto_data_valid ?
+		CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+
+	skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->dev      = dev;
+	dev->last_rx  = jiffies;
+
+	/* Flush netfilter context: rx'ed skbuffs not expected to have any. */
+	nf_reset(skb);
+	secpath_reset(skb);
+
+	netif_rx(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *loopback_get_stats(struct net_device *dev)
+{
+	struct net_private *np = netdev_priv(dev);
+	return &np->stats;
+}
+
+static const struct ethtool_ops network_ethtool_ops =
+{
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ethtool_op_set_tso,
+	.get_link = ethtool_op_get_link,
+};
+
+/*
+ * Nothing to do here. Virtual interface is point-to-point and the
+ * physical interface is probably promiscuous anyway.
+ */
+static void loopback_set_multicast_list(struct net_device *dev)
+{
+}
+
+static const struct net_device_ops loopback_netdev_ops = {
+	.ndo_open               = loopback_open,
+	.ndo_stop               = loopback_close,
+	.ndo_start_xmit         = loopback_start_xmit,
+	.ndo_set_multicast_list = loopback_set_multicast_list,
+	.ndo_change_mtu	        = NULL, /* allow arbitrary mtu */
+	.ndo_get_stats          = loopback_get_stats,
+};
+
+static void loopback_construct(struct net_device *dev, struct net_device *lo)
+{
+	struct net_private *np = netdev_priv(dev);
+
+	np->loopback_dev     = lo;
+	dev->netdev_ops      = &loopback_netdev_ops;
+	dev->tx_queue_len    = 0;
+
+	dev->features        = (NETIF_F_HIGHDMA |
+				NETIF_F_LLTX |
+				NETIF_F_TSO |
+				NETIF_F_SG |
+				NETIF_F_IP_CSUM);
+
+	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
+
+	/*
+	 * We do not set a jumbo MTU on the interface. Otherwise the network
+	 * stack will try to send large packets that will get dropped by the
+	 * Ethernet bridge (unless the physical Ethernet interface is
+	 * configured to transfer jumbo packets). If a larger MTU is desired
+	 * then the system administrator can specify it using the 'ifconfig'
+	 * command.
+	 */
+	/*dev->mtu             = 16*1024;*/
+}
+
+static int __init make_loopback(int i)
+{
+	struct net_device *dev1, *dev2;
+	char dev_name[IFNAMSIZ];
+	int err = -ENOMEM;
+
+	sprintf(dev_name, "vif0.%d", i);
+	dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+	if (!dev1)
+		return err;
+
+	sprintf(dev_name, "veth%d", i);
+	dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
+	if (!dev2)
+		goto fail_netdev2;
+
+	loopback_construct(dev1, dev2);
+	loopback_construct(dev2, dev1);
+
+	/*
+	 * Initialise a dummy MAC address for the 'dummy backend' interface. We
+	 * choose the numerically largest non-broadcast address to prevent the
+	 * address getting stolen by an Ethernet bridge for STP purposes.
+	 */
+	memset(dev1->dev_addr, 0xFF, ETH_ALEN);
+	dev1->dev_addr[0] &= ~0x01;
+
+	if ((err = register_netdev(dev1)) != 0)
+		goto fail;
+
+	if ((err = register_netdev(dev2)) != 0) {
+		unregister_netdev(dev1);
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	free_netdev(dev2);
+ fail_netdev2:
+	free_netdev(dev1);
+	return err;
+}
+
+static void __exit clean_loopback(int i)
+{
+	struct net_device *dev1, *dev2;
+	char dev_name[IFNAMSIZ];
+
+	sprintf(dev_name, "vif0.%d", i);
+	dev1 = dev_get_by_name(&init_net, dev_name);
+	sprintf(dev_name, "veth%d", i);
+	dev2 = dev_get_by_name(&init_net, dev_name);
+	if (dev1 && dev2) {
+		unregister_netdev(dev2);
+		unregister_netdev(dev1);
+		free_netdev(dev2);
+		free_netdev(dev1);
+	}
+}
+
+static int __init loopback_init(void)
+{
+	int i, err = 0;
+
+	if (nloopbacks == -1)
+		nloopbacks = is_initial_xendomain() ? 4 : 0;
+
+	for (i = 0; i < nloopbacks; i++)
+		if ((err = make_loopback(i)) != 0)
+			break;
+
+	return err;
+}
+
+module_init(loopback_init);
+
+static void __exit loopback_exit(void)
+{
+	int i;
+
+	for (i = nloopbacks; i-- > 0; )
+		clean_loopback(i);
+}
+
+module_exit(loopback_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/netback/common.h
+++ linux-ec2-2.6.32/drivers/xen/netback/common.h
@@ -0,0 +1,220 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/common.h
+ * 
+ * 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 __NETIF__BACKEND__COMMON_H__
+#define __NETIF__BACKEND__COMMON_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wait.h>
+#include <xen/evtchn.h>
+#include <xen/interface/io/netif.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <xen/interface/grant_table.h>
+#include <xen/gnttab.h>
+#include <xen/driver_util.h>
+#include <xen/xenbus.h>
+
+#define DPRINTK(_f, _a...)			\
+	pr_debug("(file=%s, line=%d) " _f,	\
+		 __FILE__ , __LINE__ , ## _a )
+#define IPRINTK(fmt, args...)				\
+	printk(KERN_INFO "xen_net: " fmt, ##args)
+#define WPRINTK(fmt, args...)				\
+	printk(KERN_WARNING "xen_net: " fmt, ##args)
+
+typedef struct netif_st {
+	/* Unique identifier for this interface. */
+	domid_t          domid;
+	unsigned int     handle;
+
+	u8               fe_dev_addr[6];
+
+	/* Physical parameters of the comms window. */
+	grant_handle_t   tx_shmem_handle;
+	grant_ref_t      tx_shmem_ref;
+	grant_handle_t   rx_shmem_handle;
+	grant_ref_t      rx_shmem_ref;
+	unsigned int     irq;
+
+	/* The shared rings and indexes. */
+	netif_tx_back_ring_t tx;
+	netif_rx_back_ring_t rx;
+	struct vm_struct *tx_comms_area;
+	struct vm_struct *rx_comms_area;
+
+	/* Set of features that can be turned on in dev->features. */
+	int features;
+
+	/* Internal feature information. */
+	u8 can_queue:1;	/* can queue packets for receiver? */
+	u8 copying_receiver:1;	/* copy packets to receiver?       */
+
+	/* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */
+	RING_IDX rx_req_cons_peek;
+
+	/* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
+	unsigned long   credit_bytes;
+	unsigned long   credit_usec;
+	unsigned long   remaining_credit;
+	struct timer_list credit_timeout;
+
+	/* Enforce draining of the transmit queue. */
+	struct timer_list tx_queue_timeout;
+
+	/* Statistics */
+	int nr_copied_skbs;
+
+	/* Miscellaneous private stuff. */
+	struct list_head list;  /* scheduling list */
+	atomic_t         refcnt;
+	struct net_device *dev;
+	struct net_device_stats stats;
+
+	unsigned int carrier;
+
+	wait_queue_head_t waiting_to_free;
+} netif_t;
+
+/*
+ * Implement our own carrier flag: the network stack's version causes delays
+ * when the carrier is re-enabled (in particular, dev_activate() may not
+ * immediately be called, which can cause packet loss; also the etherbridge
+ * can be rather lazy in activating its port).
+ */
+#define netback_carrier_on(netif)	((netif)->carrier = 1)
+#define netback_carrier_off(netif)	((netif)->carrier = 0)
+#define netback_carrier_ok(netif)	((netif)->carrier)
+
+enum {
+	NETBK_DONT_COPY_SKB,
+	NETBK_DELAYED_COPY_SKB,
+	NETBK_ALWAYS_COPY_SKB,
+};
+
+extern int netbk_copy_skb_mode;
+
+/* Function pointers into netback accelerator plugin modules */
+struct netback_accel_hooks {
+	struct module *owner;
+	int  (*probe)(struct xenbus_device *dev);
+	int (*remove)(struct xenbus_device *dev);
+};
+
+/* Structure to track the state of a netback accelerator plugin */
+struct netback_accelerator {
+	struct list_head link;
+	int id;
+	char *eth_name;
+	atomic_t use_count;
+	struct netback_accel_hooks *hooks;
+};
+
+struct backend_info {
+	struct xenbus_device *dev;
+	netif_t *netif;
+	enum xenbus_state frontend_state;
+
+	/* State relating to the netback accelerator */
+	void *netback_accel_priv;
+	/* The accelerator that this backend is currently using */
+	struct netback_accelerator *accelerator;
+};
+
+#define NETBACK_ACCEL_VERSION 0x00010001
+
+/* 
+ * Connect an accelerator plugin module to netback.  Returns zero on
+ * success, < 0 on error, > 0 (with highest version number supported)
+ * if version mismatch.
+ */
+extern int netback_connect_accelerator(unsigned version,
+				       int id, const char *eth_name, 
+				       struct netback_accel_hooks *hooks);
+/* Disconnect a previously connected accelerator plugin module */
+extern void netback_disconnect_accelerator(int id, const char *eth_name);
+
+
+extern
+void netback_probe_accelerators(struct backend_info *be,
+				struct xenbus_device *dev);
+extern
+void netback_remove_accelerators(struct backend_info *be,
+				 struct xenbus_device *dev);
+extern
+void netif_accel_init(void);
+
+
+#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
+
+void netif_disconnect(netif_t *netif);
+
+netif_t *netif_alloc(struct device *parent, domid_t domid, unsigned int handle);
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+	      unsigned long rx_ring_ref, unsigned int evtchn);
+
+#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define netif_put(_b)						\
+	do {							\
+		if ( atomic_dec_and_test(&(_b)->refcnt) )	\
+			wake_up(&(_b)->waiting_to_free);	\
+	} while (0)
+
+void netif_xenbus_init(void);
+
+#define netif_schedulable(netif)				\
+	(netif_running((netif)->dev) && netback_carrier_ok(netif))
+
+void netif_schedule_work(netif_t *netif);
+void netif_deschedule_work(netif_t *netif);
+
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
+struct net_device_stats *netif_be_get_stats(struct net_device *dev);
+irqreturn_t netif_be_int(int irq, void *dev_id);
+
+static inline int netbk_can_queue(struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+	return netif->can_queue;
+}
+
+static inline int netbk_can_sg(struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+	return netif->features & NETIF_F_SG;
+}
+
+#endif /* __NETIF__BACKEND__COMMON_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/netback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/netback/Makefile
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/netback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/netback/xenbus.c
@@ -0,0 +1,448 @@
+/*  Xenbus code for netif backend
+    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+    Copyright (C) 2005 XenSource Ltd
+
+    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 <stdarg.h>
+#include <linux/module.h>
+#include <xen/xenbus.h>
+#include "common.h"
+
+#if 0
+#undef DPRINTK
+#define DPRINTK(fmt, args...) \
+    printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
+#endif
+
+
+static int connect_rings(struct backend_info *);
+static void connect(struct backend_info *);
+static void backend_create_netif(struct backend_info *be);
+
+static int netback_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	netback_remove_accelerators(be, dev);
+
+	if (be->netif) {
+		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+		netif_disconnect(be->netif);
+		be->netif = NULL;
+	}
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures and switch to InitWait.
+ */
+static int netback_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	const char *message;
+	struct xenbus_transaction xbt;
+	int err;
+	int sg;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+
+	sg = 1;
+	if (netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB)
+		sg = 0;
+
+	do {
+		err = xenbus_transaction_start(&xbt);
+		if (err) {
+			xenbus_dev_fatal(dev, err, "starting transaction");
+			goto fail;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", sg);
+		if (err) {
+			message = "writing feature-sg";
+			goto abort_transaction;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
+				    "%d", sg);
+		if (err) {
+			message = "writing feature-gso-tcpv4";
+			goto abort_transaction;
+		}
+
+		/* We support rx-copy path. */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-copy", "%d", 1);
+		if (err) {
+			message = "writing feature-rx-copy";
+			goto abort_transaction;
+		}
+
+		/*
+		 * We don't support rx-flip path (except old guests who don't
+		 * grok this feature flag).
+		 */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-flip", "%d", 0);
+		if (err) {
+			message = "writing feature-rx-flip";
+			goto abort_transaction;
+		}
+
+		err = xenbus_transaction_end(xbt, 0);
+	} while (err == -EAGAIN);
+
+	if (err) {
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto fail;
+	}
+
+	netback_probe_accelerators(be, dev);
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+
+	/* This kicks hotplug scripts, so do it immediately. */
+	backend_create_netif(be);
+
+	return 0;
+
+abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+fail:
+	DPRINTK("failed");
+	netback_remove(dev);
+	return err;
+}
+
+
+/**
+ * Handle the creation of the hotplug script environment.  We add the script
+ * and vif variables to the environment, for the benefit of the vif-* hotplug
+ * scripts.
+ */
+static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *env)
+{
+	struct backend_info *be = dev_get_drvdata(&xdev->dev);
+	netif_t *netif = be->netif;
+	char *val;
+
+	DPRINTK("netback_uevent");
+
+	val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
+	if (IS_ERR(val)) {
+		int err = PTR_ERR(val);
+		xenbus_dev_fatal(xdev, err, "reading script");
+		return err;
+	}
+	else {
+		add_uevent_var(env, "script=%s", val);
+		kfree(val);
+	}
+
+	add_uevent_var(env, "vif=%s", netif->dev->name);
+
+	return 0;
+}
+
+
+static void backend_create_netif(struct backend_info *be)
+{
+	int err;
+	long handle;
+	struct xenbus_device *dev = be->dev;
+
+	if (be->netif != NULL)
+		return;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading handle");
+		return;
+	}
+
+	be->netif = netif_alloc(&dev->dev, dev->otherend_id, handle);
+	if (IS_ERR(be->netif)) {
+		err = PTR_ERR(be->netif);
+		be->netif = NULL;
+		xenbus_dev_fatal(dev, err, "creating interface");
+		return;
+	}
+
+	kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
+}
+
+
+/**
+ * Callback received when the frontend's state changes.
+ */
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	DPRINTK("%s", xenbus_strstate(frontend_state));
+
+	be->frontend_state = frontend_state;
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
+			       __FUNCTION__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateInitialised:
+		break;
+
+	case XenbusStateConnected:
+		if (dev->state == XenbusStateConnected)
+			break;
+		backend_create_netif(be);
+		if (be->netif)
+			connect(be);
+		break;
+
+	case XenbusStateClosing:
+		if (be->netif) {
+			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+			netif_disconnect(be->netif);
+			be->netif = NULL;
+		}
+		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;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+static void xen_net_read_rate(struct xenbus_device *dev,
+			      unsigned long *bytes, unsigned long *usec)
+{
+	char *s, *e;
+	unsigned long b, u;
+	char *ratestr;
+
+	/* Default to unlimited bandwidth. */
+	*bytes = ~0UL;
+	*usec = 0;
+
+	ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
+	if (IS_ERR(ratestr))
+		return;
+
+	s = ratestr;
+	b = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != ','))
+		goto fail;
+
+	s = e + 1;
+	u = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != '\0'))
+		goto fail;
+
+	*bytes = b;
+	*usec = u;
+
+	kfree(ratestr);
+	return;
+
+ fail:
+	WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
+	kfree(ratestr);
+}
+
+static int 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;
+}
+
+static void connect(struct backend_info *be)
+{
+	int err;
+	struct xenbus_device *dev = be->dev;
+
+	err = connect_rings(be);
+	if (err)
+		return;
+
+	err = xen_net_read_mac(dev, be->netif->fe_dev_addr);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+		return;
+	}
+
+	xen_net_read_rate(dev, &be->netif->credit_bytes,
+			  &be->netif->credit_usec);
+	be->netif->remaining_credit = be->netif->credit_bytes;
+
+	xenbus_switch_state(dev, XenbusStateConnected);
+
+	netif_wake_queue(be->netif->dev);
+}
+
+
+static int connect_rings(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long tx_ring_ref, rx_ring_ref;
+	unsigned int evtchn, rx_copy;
+	int err;
+	int val;
+
+	DPRINTK("");
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "tx-ring-ref", "%lu", &tx_ring_ref,
+			    "rx-ring-ref", "%lu", &rx_ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
+			   &rx_copy);
+	if (err == -ENOENT) {
+		err = 0;
+		rx_copy = 0;
+	}
+	if (err < 0) {
+		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
+				 dev->otherend);
+		return err;
+	}
+	be->netif->copying_receiver = !!rx_copy;
+
+	if (be->netif->dev->tx_queue_len != 0) {
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+				 "feature-rx-notify", "%d", &val) < 0)
+			val = 0;
+		if (val)
+			be->netif->can_queue = 1;
+		else
+			/* Must be non-zero for pfifo_fast to work. */
+			be->netif->dev->tx_queue_len = 1;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features |= NETIF_F_SG;
+		be->netif->dev->features |= NETIF_F_SG;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
+			 &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features |= NETIF_F_TSO;
+		be->netif->dev->features |= NETIF_F_TSO;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
+			 "%d", &val) < 0)
+		val = 0;
+	if (val) {
+		be->netif->features &= ~NETIF_F_IP_CSUM;
+		be->netif->dev->features &= ~NETIF_F_IP_CSUM;
+	}
+
+	/* Map the shared frame, irq etc. */
+	err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "mapping shared-frames %lu/%lu port %u",
+				 tx_ring_ref, rx_ring_ref, evtchn);
+		return err;
+	}
+	return 0;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id netback_ids[] = {
+	{ "vif" },
+	{ "" }
+};
+
+
+static struct xenbus_driver netback = {
+	.name = "vif",
+	.ids = netback_ids,
+	.probe = netback_probe,
+	.remove = netback_remove,
+	.uevent = netback_uevent,
+	.otherend_changed = frontend_changed,
+};
+
+
+void netif_xenbus_init(void)
+{
+	if (xenbus_register_backend(&netback))
+		BUG();
+}
--- linux-ec2-2.6.32.orig/drivers/xen/netback/accel.c
+++ linux-ec2-2.6.32/drivers/xen/netback/accel.c
@@ -0,0 +1,269 @@
+/******************************************************************************
+ * drivers/xen/netback/accel.c
+ *
+ * Interface between backend virtual network device and accelerated plugin. 
+ * 
+ * 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.
+ */
+
+#include <linux/list.h>
+#include <asm/atomic.h>
+#include <xen/xenbus.h>
+#include <linux/mutex.h>
+
+#include "common.h"
+
+#if 0
+#undef DPRINTK
+#define DPRINTK(fmt, args...)						\
+	printk("netback/accel (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
+#endif
+
+/* 
+ * A list of available netback accelerator plugin modules (each list
+ * entry is of type struct netback_accelerator) 
+ */ 
+static struct list_head accelerators_list;
+/* Lock used to protect access to accelerators_list */
+DEFINE_MUTEX(accelerators_mutex);
+
+/* 
+ * Compare a backend to an accelerator, and decide if they are
+ * compatible (i.e. if the accelerator should be used by the
+ * backend) 
+ */
+static int match_accelerator(struct xenbus_device *xendev,
+			     struct backend_info *be, 
+			     struct netback_accelerator *accelerator)
+{
+	int rc = 0;
+	char *eth_name = xenbus_read(XBT_NIL, xendev->nodename, "accel", NULL);
+	
+	if (IS_ERR(eth_name)) {
+		/* Probably means not present */
+		DPRINTK("%s: no match due to xenbus_read accel error %ld\n",
+			__FUNCTION__, PTR_ERR(eth_name));
+		return 0;
+	} else {
+		if (!strcmp(eth_name, accelerator->eth_name))
+			rc = 1;
+		kfree(eth_name);
+		return rc;
+	}
+}
+
+
+static void do_probe(struct backend_info *be, 
+		     struct netback_accelerator *accelerator,
+		     struct xenbus_device *xendev) 
+{
+	be->accelerator = accelerator;
+	atomic_inc(&be->accelerator->use_count);
+	if (be->accelerator->hooks->probe(xendev) != 0) {
+		atomic_dec(&be->accelerator->use_count);
+		module_put(be->accelerator->hooks->owner);
+		be->accelerator = NULL;
+	}
+}
+
+
+/*
+ * Notify suitable backends that a new accelerator is available and
+ * connected.  This will also notify the accelerator plugin module
+ * that it is being used for a device through the probe hook.
+ */
+static int netback_accelerator_probe_backend(struct device *dev, void *arg)
+{
+	struct netback_accelerator *accelerator = 
+		(struct netback_accelerator *)arg;
+	struct xenbus_device *xendev = to_xenbus_device(dev);
+
+	if (!strcmp("vif", xendev->devicetype)) {
+		struct backend_info *be = dev_get_drvdata(&xendev->dev);
+
+		if (match_accelerator(xendev, be, accelerator) &&
+		    try_module_get(accelerator->hooks->owner)) {
+			do_probe(be, accelerator, xendev);
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * Notify suitable backends that an accelerator is unavailable.
+ */
+static int netback_accelerator_remove_backend(struct device *dev, void *arg)
+{
+	struct xenbus_device *xendev = to_xenbus_device(dev);
+	struct netback_accelerator *accelerator = 
+		(struct netback_accelerator *)arg;
+	
+	if (!strcmp("vif", xendev->devicetype)) {
+		struct backend_info *be = dev_get_drvdata(&xendev->dev);
+
+		if (be->accelerator == accelerator) {
+			be->accelerator->hooks->remove(xendev);
+			atomic_dec(&be->accelerator->use_count);
+			module_put(be->accelerator->hooks->owner);
+			be->accelerator = NULL;
+		}
+	}
+	return 0;
+}
+
+
+
+/*
+ * Entry point for an netback accelerator plugin module.  Called to
+ * advertise its presence, and connect to any suitable backends.
+ */
+int netback_connect_accelerator(unsigned version, int id, const char *eth_name, 
+				struct netback_accel_hooks *hooks)
+{
+	struct netback_accelerator *new_accelerator;
+	unsigned eth_name_len;
+
+	if (version != NETBACK_ACCEL_VERSION) {
+		if (version > NETBACK_ACCEL_VERSION) {
+			/* Caller has higher version number, leave it
+			   up to them to decide whether to continue.
+			   They can recall with a lower number if
+			   they're happy to be compatible with us */
+			return NETBACK_ACCEL_VERSION;
+		} else {
+			/* We have a more recent version than caller.
+			   Currently reject, but may in future be able
+			   to be backwardly compatible */
+			return -EPROTO;
+		}
+	}
+
+	new_accelerator = 
+		kmalloc(sizeof(struct netback_accelerator), GFP_KERNEL);
+	if (!new_accelerator) {
+		DPRINTK("%s: failed to allocate memory for accelerator\n",
+			__FUNCTION__);
+		return -ENOMEM;
+	}
+
+	new_accelerator->id = id;
+	
+	eth_name_len = strlen(eth_name)+1;
+	new_accelerator->eth_name = kmalloc(eth_name_len, GFP_KERNEL);
+	if (!new_accelerator->eth_name) {
+		DPRINTK("%s: failed to allocate memory for eth_name string\n",
+			__FUNCTION__);
+		kfree(new_accelerator);
+		return -ENOMEM;
+	}
+	strlcpy(new_accelerator->eth_name, eth_name, eth_name_len);
+	
+	new_accelerator->hooks = hooks;
+
+	atomic_set(&new_accelerator->use_count, 0);
+	
+	mutex_lock(&accelerators_mutex);
+	list_add(&new_accelerator->link, &accelerators_list);
+	
+	/* tell existing backends about new plugin */
+	xenbus_for_each_backend(new_accelerator, 
+				netback_accelerator_probe_backend);
+
+	mutex_unlock(&accelerators_mutex);
+
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(netback_connect_accelerator);
+
+
+/* 
+ * Disconnect an accelerator plugin module that has previously been
+ * connected.
+ */
+void netback_disconnect_accelerator(int id, const char *eth_name)
+{
+	struct netback_accelerator *accelerator, *next;
+
+	mutex_lock(&accelerators_mutex);
+	list_for_each_entry_safe(accelerator, next, &accelerators_list, link) {
+		if (!strcmp(eth_name, accelerator->eth_name)) {
+			xenbus_for_each_backend
+				(accelerator, netback_accelerator_remove_backend);
+			BUG_ON(atomic_read(&accelerator->use_count) != 0);
+			list_del(&accelerator->link);				
+			kfree(accelerator->eth_name);
+			kfree(accelerator);
+			break;
+		}
+	}
+	mutex_unlock(&accelerators_mutex);
+}
+EXPORT_SYMBOL_GPL(netback_disconnect_accelerator);
+
+
+void netback_probe_accelerators(struct backend_info *be,
+				struct xenbus_device *dev)
+{
+	struct netback_accelerator *accelerator;
+
+	/* 
+	 * Check list of accelerators to see if any is suitable, and
+	 * use it if it is.
+	 */
+	mutex_lock(&accelerators_mutex);
+	list_for_each_entry(accelerator, &accelerators_list, link) { 
+		if (match_accelerator(dev, be, accelerator) &&
+		    try_module_get(accelerator->hooks->owner)) {
+			do_probe(be, accelerator, dev);
+			break;
+		}
+	}
+	mutex_unlock(&accelerators_mutex);
+}
+
+
+void netback_remove_accelerators(struct backend_info *be,
+				 struct xenbus_device *dev)
+{
+	mutex_lock(&accelerators_mutex);
+	/* Notify the accelerator (if any) of this device's removal */
+	if (be->accelerator != NULL) {
+		be->accelerator->hooks->remove(dev);
+		atomic_dec(&be->accelerator->use_count);
+		module_put(be->accelerator->hooks->owner);
+		be->accelerator = NULL;
+	}
+	mutex_unlock(&accelerators_mutex);
+}
+
+
+void netif_accel_init(void)
+{
+	INIT_LIST_HEAD(&accelerators_list);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/netback/netback.c
+++ linux-ec2-2.6.32/drivers/xen/netback/netback.c
@@ -0,0 +1,1680 @@
+/******************************************************************************
+ * drivers/xen/netback/netback.c
+ * 
+ * Back-end of the driver for virtual network devices. This portion of the
+ * driver exports a 'unified' network-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A 
+ * reference front-end implementation can be found in:
+ *  drivers/xen/netfront/netfront.c
+ * 
+ * Copyright (c) 2002-2005, K A Fraser
+ * 
+ * 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 "common.h"
+#include <xen/balloon.h>
+#include <xen/interface/memory.h>
+
+/*define NETBE_DEBUG_INTERRUPT*/
+
+struct netbk_rx_meta {
+	skb_frag_t frag;
+	int id;
+	u8 copy:1;
+};
+
+struct netbk_tx_pending_inuse {
+	struct list_head list;
+	unsigned long alloc_time;
+};
+
+static void netif_idx_release(u16 pending_idx);
+static void make_tx_response(netif_t *netif, 
+			     netif_tx_request_t *txp,
+			     s8       st);
+static netif_rx_response_t *make_rx_response(netif_t *netif, 
+					     u16      id, 
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags);
+
+static void net_tx_action(unsigned long unused);
+static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
+
+static void net_rx_action(unsigned long unused);
+static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
+
+static struct timer_list net_timer;
+static struct timer_list netbk_tx_pending_timer;
+
+#define MAX_PENDING_REQS (1U << CONFIG_XEN_NETDEV_TX_SHIFT)
+
+static struct sk_buff_head rx_queue;
+
+static struct page **mmap_pages;
+static inline unsigned long idx_to_pfn(unsigned int idx)
+{
+	return page_to_pfn(mmap_pages[idx]);
+}
+
+static inline unsigned long idx_to_kaddr(unsigned int idx)
+{
+	return (unsigned long)pfn_to_kaddr(idx_to_pfn(idx));
+}
+
+/* extra field used in struct page */
+static inline void netif_set_page_index(struct page *pg, unsigned int index)
+{
+	*(unsigned long *)&pg->mapping = index;
+}
+
+static inline int netif_page_index(struct page *pg)
+{
+	unsigned long idx = (unsigned long)pg->mapping;
+
+	if (!PageForeign(pg))
+		return -1;
+
+	if ((idx >= MAX_PENDING_REQS) || (mmap_pages[idx] != pg))
+		return -1;
+
+	return idx;
+}
+
+#define PKT_PROT_LEN 64
+
+static struct pending_tx_info {
+	netif_tx_request_t req;
+	netif_t *netif;
+} pending_tx_info[MAX_PENDING_REQS];
+static u16 pending_ring[MAX_PENDING_REQS];
+typedef unsigned int PEND_RING_IDX;
+#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
+static PEND_RING_IDX pending_prod, pending_cons;
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+/* Freed TX SKBs get batched on this ring before return to pending_ring. */
+static u16 dealloc_ring[MAX_PENDING_REQS];
+static PEND_RING_IDX dealloc_prod, dealloc_cons;
+
+/* Doubly-linked list of in-use pending entries. */
+static struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS];
+static LIST_HEAD(pending_inuse_head);
+
+static struct sk_buff_head tx_queue;
+
+static grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
+static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
+static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
+
+static struct list_head net_schedule_list;
+static spinlock_t net_schedule_list_lock;
+
+#define MAX_MFN_ALLOC 64
+static unsigned long mfn_list[MAX_MFN_ALLOC];
+static unsigned int alloc_index = 0;
+
+/* Setting this allows the safe use of this driver without netloop. */
+static int MODPARM_copy_skb = 1;
+module_param_named(copy_skb, MODPARM_copy_skb, bool, 0);
+MODULE_PARM_DESC(copy_skb, "Copy data received from netfront without netloop");
+static int MODPARM_permute_returns = 0;
+module_param_named(permute_returns, MODPARM_permute_returns, bool, S_IRUSR|S_IWUSR);
+MODULE_PARM_DESC(permute_returns, "Randomly permute the order in which TX responses are sent to the frontend");
+
+int netbk_copy_skb_mode;
+
+static inline unsigned long alloc_mfn(void)
+{
+	BUG_ON(alloc_index == 0);
+	return mfn_list[--alloc_index];
+}
+
+static int check_mfn(int nr)
+{
+	struct xen_memory_reservation reservation = {
+		.extent_order = 0,
+		.domid        = DOMID_SELF
+	};
+	int rc;
+
+	if (likely(alloc_index >= nr))
+		return 0;
+
+	set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index);
+	reservation.nr_extents = MAX_MFN_ALLOC - alloc_index;
+	rc = HYPERVISOR_memory_op(XENMEM_increase_reservation, &reservation);
+	if (likely(rc > 0))
+		alloc_index += rc;
+
+	return alloc_index >= nr ? 0 : -ENOMEM;
+}
+
+static inline void maybe_schedule_tx_action(void)
+{
+	smp_mb();
+	if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+	    !list_empty(&net_schedule_list))
+		tasklet_schedule(&net_tx_tasklet);
+}
+
+static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
+{
+	struct skb_shared_info *ninfo;
+	struct sk_buff *nskb;
+	unsigned long offset;
+	int ret;
+	int len;
+	int headlen;
+
+	BUG_ON(skb_shinfo(skb)->frag_list != NULL);
+
+	nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC | __GFP_NOWARN);
+	if (unlikely(!nskb))
+		goto err;
+
+	skb_reserve(nskb, 16 + NET_IP_ALIGN);
+	headlen = skb_end_pointer(nskb) - nskb->data;
+	if (headlen > skb_headlen(skb))
+		headlen = skb_headlen(skb);
+	ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen);
+	BUG_ON(ret);
+
+	ninfo = skb_shinfo(nskb);
+	ninfo->gso_size = skb_shinfo(skb)->gso_size;
+	ninfo->gso_type = skb_shinfo(skb)->gso_type;
+
+	offset = headlen;
+	len = skb->len - headlen;
+
+	nskb->len = skb->len;
+	nskb->data_len = len;
+	nskb->truesize += len;
+
+	while (len) {
+		struct page *page;
+		int copy;
+		int zero;
+
+		if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) {
+			dump_stack();
+			goto err_free;
+		}
+
+		copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
+		zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
+
+		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | zero);
+		if (unlikely(!page))
+			goto err_free;
+
+		ret = skb_copy_bits(skb, offset, page_address(page), copy);
+		BUG_ON(ret);
+
+		ninfo->frags[ninfo->nr_frags].page = page;
+		ninfo->frags[ninfo->nr_frags].page_offset = 0;
+		ninfo->frags[ninfo->nr_frags].size = copy;
+		ninfo->nr_frags++;
+
+		offset += copy;
+		len -= copy;
+	}
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+	offset = 0;
+#else
+	offset = nskb->data - skb->data;
+#endif
+
+	nskb->transport_header = skb->transport_header + offset;
+	nskb->network_header   = skb->network_header   + offset;
+	nskb->mac_header       = skb->mac_header       + offset;
+
+	return nskb;
+
+ err_free:
+	kfree_skb(nskb);
+ err:
+	return NULL;
+}
+
+static inline int netbk_max_required_rx_slots(netif_t *netif)
+{
+	if (netif->features & (NETIF_F_SG|NETIF_F_TSO))
+		return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */
+	return 1; /* all in one */
+}
+
+static inline int netbk_queue_full(netif_t *netif)
+{
+	RING_IDX peek   = netif->rx_req_cons_peek;
+	RING_IDX needed = netbk_max_required_rx_slots(netif);
+
+	return ((netif->rx.sring->req_prod - peek) < needed) ||
+	       ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed);
+}
+
+static void tx_queue_callback(unsigned long data)
+{
+	netif_t *netif = (netif_t *)data;
+	if (netif_schedulable(netif))
+		netif_wake_queue(netif->dev);
+}
+
+int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+
+	BUG_ON(skb->dev != dev);
+
+	/* Drop the packet if the target domain has no receive buffers. */
+	if (unlikely(!netif_schedulable(netif) || netbk_queue_full(netif)))
+		goto drop;
+
+	/*
+	 * Copy the packet here if it's destined for a flipping interface
+	 * but isn't flippable (e.g. extra references to data).
+	 * XXX For now we also copy skbuffs whose head crosses a page
+	 * boundary, because netbk_gop_skb can't handle them.
+	 */
+	if (!netif->copying_receiver ||
+	    ((skb_headlen(skb) + offset_in_page(skb->data)) >= PAGE_SIZE)) {
+		struct sk_buff *nskb = netbk_copy_skb(skb);
+		if ( unlikely(nskb == NULL) )
+			goto drop;
+		/* Copy only the header fields we use in this driver. */
+		nskb->dev = skb->dev;
+		nskb->ip_summed = skb->ip_summed;
+		nskb->proto_data_valid = skb->proto_data_valid;
+		dev_kfree_skb(skb);
+		skb = nskb;
+	}
+
+	netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
+				   !!skb_shinfo(skb)->gso_size;
+	netif_get(netif);
+
+	if (netbk_can_queue(dev) && netbk_queue_full(netif)) {
+		netif->rx.sring->req_event = netif->rx_req_cons_peek +
+			netbk_max_required_rx_slots(netif);
+		mb(); /* request notification /then/ check & stop the queue */
+		if (netbk_queue_full(netif)) {
+			netif_stop_queue(dev);
+			/*
+			 * Schedule 500ms timeout to restart the queue, thus
+			 * ensuring that an inactive queue will be drained.
+			 * Packets will be immediately be dropped until more
+			 * receive buffers become available (see
+			 * netbk_queue_full() check above).
+			 */
+			netif->tx_queue_timeout.data = (unsigned long)netif;
+			netif->tx_queue_timeout.function = tx_queue_callback;
+			mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
+		}
+	}
+
+	skb_queue_tail(&rx_queue, skb);
+	tasklet_schedule(&net_rx_tasklet);
+
+	return NETDEV_TX_OK;
+
+ drop:
+	netif->stats.tx_dropped++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+#if 0
+static void xen_network_done_notify(void)
+{
+	static struct net_device *eth0_dev = NULL;
+	if (unlikely(eth0_dev == NULL))
+		eth0_dev = __dev_get_by_name(&init_net, "eth0");
+	napi_schedule(???);
+}
+/* 
+ * Add following to poll() function in NAPI driver (Tigon3 is example):
+ *  if ( xen_network_done() )
+ *      tg3_enable_ints(tp);
+ */
+int xen_network_done(void)
+{
+	return skb_queue_empty(&rx_queue);
+}
+#endif
+
+struct netrx_pending_operations {
+	unsigned trans_prod, trans_cons;
+	unsigned mmu_prod, mmu_mcl;
+	unsigned mcl_prod, mcl_cons;
+	unsigned copy_prod, copy_cons;
+	unsigned meta_prod, meta_cons;
+	mmu_update_t *mmu;
+	gnttab_transfer_t *trans;
+	gnttab_copy_t *copy;
+	multicall_entry_t *mcl;
+	struct netbk_rx_meta *meta;
+};
+
+/* Set up the grant operations for this fragment.  If it's a flipping
+   interface, we also set up the unmap request from here. */
+static u16 netbk_gop_frag(netif_t *netif, struct netbk_rx_meta *meta,
+			  int i, struct netrx_pending_operations *npo,
+			  struct page *page, unsigned long size,
+			  unsigned long offset)
+{
+	mmu_update_t *mmu;
+	gnttab_transfer_t *gop;
+	gnttab_copy_t *copy_gop;
+	multicall_entry_t *mcl;
+	netif_rx_request_t *req;
+	unsigned long old_mfn, new_mfn;
+	int idx = netif_page_index(page);
+
+	old_mfn = virt_to_mfn(page_address(page));
+
+	req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i);
+	if (netif->copying_receiver) {
+		/* The fragment needs to be copied rather than
+		   flipped. */
+		meta->copy = 1;
+		copy_gop = npo->copy + npo->copy_prod++;
+		copy_gop->flags = GNTCOPY_dest_gref;
+		if (idx > -1) {
+			struct pending_tx_info *src_pend = &pending_tx_info[idx];
+			copy_gop->source.domid = src_pend->netif->domid;
+			copy_gop->source.u.ref = src_pend->req.gref;
+			copy_gop->flags |= GNTCOPY_source_gref;
+		} else {
+			copy_gop->source.domid = DOMID_SELF;
+			copy_gop->source.u.gmfn = old_mfn;
+		}
+		copy_gop->source.offset = offset;
+		copy_gop->dest.domid = netif->domid;
+		copy_gop->dest.offset = 0;
+		copy_gop->dest.u.ref = req->gref;
+		copy_gop->len = size;
+	} else {
+		meta->copy = 0;
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			new_mfn = alloc_mfn();
+
+			/*
+			 * Set the new P2M table entry before
+			 * reassigning the old data page. Heed the
+			 * comment in pgtable-2level.h:pte_page(). :-)
+			 */
+			set_phys_to_machine(page_to_pfn(page), new_mfn);
+
+			mcl = npo->mcl + npo->mcl_prod++;
+			MULTI_update_va_mapping(mcl,
+					     (unsigned long)page_address(page),
+					     pfn_pte_ma(new_mfn, PAGE_KERNEL),
+					     0);
+
+			mmu = npo->mmu + npo->mmu_prod++;
+			mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
+				MMU_MACHPHYS_UPDATE;
+			mmu->val = page_to_pfn(page);
+		}
+
+		gop = npo->trans + npo->trans_prod++;
+		gop->mfn = old_mfn;
+		gop->domid = netif->domid;
+		gop->ref = req->gref;
+	}
+	return req->id;
+}
+
+static void netbk_gop_skb(struct sk_buff *skb,
+			  struct netrx_pending_operations *npo)
+{
+	netif_t *netif = netdev_priv(skb->dev);
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	int i;
+	int extra;
+	struct netbk_rx_meta *head_meta, *meta;
+
+	head_meta = npo->meta + npo->meta_prod++;
+	head_meta->frag.page_offset = skb_shinfo(skb)->gso_type;
+	head_meta->frag.size = skb_shinfo(skb)->gso_size;
+	extra = !!head_meta->frag.size + 1;
+
+	for (i = 0; i < nr_frags; i++) {
+		meta = npo->meta + npo->meta_prod++;
+		meta->frag = skb_shinfo(skb)->frags[i];
+		meta->id = netbk_gop_frag(netif, meta, i + extra, npo,
+					  meta->frag.page,
+					  meta->frag.size,
+					  meta->frag.page_offset);
+	}
+
+	/*
+	 * This must occur at the end to ensure that we don't trash skb_shinfo
+	 * until we're done. We know that the head doesn't cross a page
+	 * boundary because such packets get copied in netif_be_start_xmit.
+	 */
+	head_meta->id = netbk_gop_frag(netif, head_meta, 0, npo,
+				       virt_to_page(skb->data),
+				       skb_headlen(skb),
+				       offset_in_page(skb->data));
+
+	netif->rx.req_cons += nr_frags + extra;
+}
+
+static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta)
+{
+	int i;
+
+	for (i = 0; i < nr_frags; i++)
+		put_page(meta[i].frag.page);
+}
+
+/* This is a twin to netbk_gop_skb.  Assume that netbk_gop_skb was
+   used to set up the operations on the top of
+   netrx_pending_operations, which have since been done.  Check that
+   they didn't give any errors and advance over them. */
+static int netbk_check_gop(int nr_frags, domid_t domid,
+			   struct netrx_pending_operations *npo)
+{
+	multicall_entry_t *mcl;
+	gnttab_transfer_t *gop;
+	gnttab_copy_t     *copy_op;
+	int status = NETIF_RSP_OKAY;
+	int i;
+
+	for (i = 0; i <= nr_frags; i++) {
+		if (npo->meta[npo->meta_cons + i].copy) {
+			copy_op = npo->copy + npo->copy_cons++;
+			if (copy_op->status != GNTST_okay) {
+				DPRINTK("Bad status %d from copy to DOM%d.\n",
+					copy_op->status, domid);
+				status = NETIF_RSP_ERROR;
+			}
+		} else {
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				mcl = npo->mcl + npo->mcl_cons++;
+				/* The update_va_mapping() must not fail. */
+				BUG_ON(mcl->result != 0);
+			}
+
+			gop = npo->trans + npo->trans_cons++;
+			/* Check the reassignment error code. */
+			if (gop->status != 0) {
+				DPRINTK("Bad status %d from grant transfer to DOM%u\n",
+					gop->status, domid);
+				/*
+				 * Page no longer belongs to us unless
+				 * GNTST_bad_page, but that should be
+				 * a fatal error anyway.
+				 */
+				BUG_ON(gop->status == GNTST_bad_page);
+				status = NETIF_RSP_ERROR;
+			}
+		}
+	}
+
+	return status;
+}
+
+static void netbk_add_frag_responses(netif_t *netif, int status,
+				     struct netbk_rx_meta *meta, int nr_frags)
+{
+	int i;
+	unsigned long offset;
+
+	for (i = 0; i < nr_frags; i++) {
+		int id = meta[i].id;
+		int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data;
+
+		if (meta[i].copy)
+			offset = 0;
+		else
+			offset = meta[i].frag.page_offset;
+		make_rx_response(netif, id, status, offset,
+				 meta[i].frag.size, flags);
+	}
+}
+
+static void net_rx_action(unsigned long unused)
+{
+	netif_t *netif = NULL;
+	s8 status;
+	u16 id, irq, flags;
+	netif_rx_response_t *resp;
+	multicall_entry_t *mcl;
+	struct sk_buff_head rxq;
+	struct sk_buff *skb;
+	int notify_nr = 0;
+	int ret;
+	int nr_frags;
+	int count;
+	unsigned long offset;
+
+	/*
+	 * Putting hundreds of bytes on the stack is considered rude.
+	 * Static works because a tasklet can only be on one CPU at any time.
+	 */
+	static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+3];
+	static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
+	static gnttab_transfer_t grant_trans_op[NET_RX_RING_SIZE];
+	static gnttab_copy_t grant_copy_op[NET_RX_RING_SIZE];
+	static DECLARE_BITMAP(rx_notify, NR_DYNIRQS);
+#if NR_DYNIRQS <= 0x10000
+	static u16 notify_list[NET_RX_RING_SIZE];
+#else
+	static int notify_list[NET_RX_RING_SIZE];
+#endif
+	static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
+
+	struct netrx_pending_operations npo = {
+		mmu: rx_mmu,
+		trans: grant_trans_op,
+		copy: grant_copy_op,
+		mcl: rx_mcl,
+		meta: meta};
+
+	skb_queue_head_init(&rxq);
+
+	count = 0;
+
+	while ((skb = skb_dequeue(&rx_queue)) != NULL) {
+		nr_frags = skb_shinfo(skb)->nr_frags;
+		*(int *)skb->cb = nr_frags;
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap) &&
+		    !((netif_t *)netdev_priv(skb->dev))->copying_receiver &&
+		    check_mfn(nr_frags + 1)) {
+			/* Memory squeeze? Back off for an arbitrary while. */
+			if ( net_ratelimit() )
+				WPRINTK("Memory squeeze in netback "
+					"driver.\n");
+			mod_timer(&net_timer, jiffies + HZ);
+			skb_queue_head(&rx_queue, skb);
+			break;
+		}
+
+		netbk_gop_skb(skb, &npo);
+
+		count += nr_frags + 1;
+
+		__skb_queue_tail(&rxq, skb);
+
+		/* Filled the batch queue? */
+		if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE)
+			break;
+	}
+
+	BUG_ON(npo.meta_prod > ARRAY_SIZE(meta));
+
+	npo.mmu_mcl = npo.mcl_prod;
+	if (npo.mcl_prod) {
+		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+		BUG_ON(npo.mmu_prod > ARRAY_SIZE(rx_mmu));
+		mcl = npo.mcl + npo.mcl_prod++;
+
+		BUG_ON(mcl[-1].op != __HYPERVISOR_update_va_mapping);
+		mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
+
+		mcl->op = __HYPERVISOR_mmu_update;
+		mcl->args[0] = (unsigned long)rx_mmu;
+		mcl->args[1] = npo.mmu_prod;
+		mcl->args[2] = 0;
+		mcl->args[3] = DOMID_SELF;
+	}
+
+	if (npo.trans_prod) {
+		BUG_ON(npo.trans_prod > ARRAY_SIZE(grant_trans_op));
+		mcl = npo.mcl + npo.mcl_prod++;
+		mcl->op = __HYPERVISOR_grant_table_op;
+		mcl->args[0] = GNTTABOP_transfer;
+		mcl->args[1] = (unsigned long)grant_trans_op;
+		mcl->args[2] = npo.trans_prod;
+	}
+
+	if (npo.copy_prod) {
+		BUG_ON(npo.copy_prod > ARRAY_SIZE(grant_copy_op));
+		mcl = npo.mcl + npo.mcl_prod++;
+		mcl->op = __HYPERVISOR_grant_table_op;
+		mcl->args[0] = GNTTABOP_copy;
+		mcl->args[1] = (unsigned long)grant_copy_op;
+		mcl->args[2] = npo.copy_prod;
+	}
+
+	/* Nothing to do? */
+	if (!npo.mcl_prod)
+		return;
+
+	BUG_ON(npo.mcl_prod > ARRAY_SIZE(rx_mcl));
+
+	ret = HYPERVISOR_multicall(npo.mcl, npo.mcl_prod);
+	BUG_ON(ret != 0);
+	/* The mmu_machphys_update() must not fail. */
+	BUG_ON(npo.mmu_mcl && npo.mcl[npo.mmu_mcl].result != 0);
+
+	while ((skb = __skb_dequeue(&rxq)) != NULL) {
+		nr_frags = *(int *)skb->cb;
+
+		netif = netdev_priv(skb->dev);
+		/* We can't rely on skb_release_data to release the
+		   pages used by fragments for us, since it tries to
+		   touch the pages in the fraglist.  If we're in
+		   flipping mode, that doesn't work.  In copying mode,
+		   we still have access to all of the pages, and so
+		   it's safe to let release_data deal with it. */
+		/* (Freeing the fragments is safe since we copy
+		   non-linear skbs destined for flipping interfaces) */
+		if (!netif->copying_receiver) {
+			atomic_set(&(skb_shinfo(skb)->dataref), 1);
+			skb_shinfo(skb)->frag_list = NULL;
+			skb_shinfo(skb)->nr_frags = 0;
+			netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
+		}
+
+		netif->stats.tx_bytes += skb->len;
+		netif->stats.tx_packets++;
+
+		status = netbk_check_gop(nr_frags, netif->domid, &npo);
+
+		id = meta[npo.meta_cons].id;
+		flags = nr_frags ? NETRXF_more_data : 0;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+			flags |= NETRXF_csum_blank | NETRXF_data_validated;
+		else if (skb->proto_data_valid) /* remote but checksummed? */
+			flags |= NETRXF_data_validated;
+
+		if (meta[npo.meta_cons].copy)
+			offset = 0;
+		else
+			offset = offset_in_page(skb->data);
+		resp = make_rx_response(netif, id, status, offset,
+					skb_headlen(skb), flags);
+
+		if (meta[npo.meta_cons].frag.size) {
+			struct netif_extra_info *gso =
+				(struct netif_extra_info *)
+				RING_GET_RESPONSE(&netif->rx,
+						  netif->rx.rsp_prod_pvt++);
+
+			resp->flags |= NETRXF_extra_info;
+
+			gso->u.gso.size = meta[npo.meta_cons].frag.size;
+			gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+			gso->u.gso.pad = 0;
+			gso->u.gso.features = 0;
+
+			gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+			gso->flags = 0;
+		}
+
+		netbk_add_frag_responses(netif, status,
+					 meta + npo.meta_cons + 1,
+					 nr_frags);
+
+		RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
+		irq = netif->irq - DYNIRQ_BASE;
+		if (ret && !__test_and_set_bit(irq, rx_notify))
+			notify_list[notify_nr++] = irq;
+
+		if (netif_queue_stopped(netif->dev) &&
+		    netif_schedulable(netif) &&
+		    !netbk_queue_full(netif))
+			netif_wake_queue(netif->dev);
+
+		netif_put(netif);
+		dev_kfree_skb(skb);
+		npo.meta_cons += nr_frags + 1;
+	}
+
+	if (notify_nr == 1) {
+		irq = *notify_list;
+		__clear_bit(irq, rx_notify);
+		notify_remote_via_irq(irq + DYNIRQ_BASE);
+	} else {
+		for (count = ret = 0; ret < notify_nr; ++ret) {
+			irq = notify_list[ret];
+			__clear_bit(irq, rx_notify);
+			if (!multi_notify_remote_via_irq(rx_mcl + count,
+							 irq + DYNIRQ_BASE))
+				++count;
+		}
+		if (HYPERVISOR_multicall(rx_mcl, count))
+			BUG();
+	}
+
+	/* More work to do? */
+	if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer))
+		tasklet_schedule(&net_rx_tasklet);
+#if 0
+	else
+		xen_network_done_notify();
+#endif
+}
+
+static void net_alarm(unsigned long unused)
+{
+	tasklet_schedule(&net_rx_tasklet);
+}
+
+static void netbk_tx_pending_timeout(unsigned long unused)
+{
+	tasklet_schedule(&net_tx_tasklet);
+}
+
+struct net_device_stats *netif_be_get_stats(struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+	return &netif->stats;
+}
+
+static int __on_net_schedule_list(netif_t *netif)
+{
+	return netif->list.next != NULL;
+}
+
+static void remove_from_net_schedule_list(netif_t *netif)
+{
+	spin_lock_irq(&net_schedule_list_lock);
+	if (likely(__on_net_schedule_list(netif))) {
+		list_del(&netif->list);
+		netif->list.next = NULL;
+		netif_put(netif);
+	}
+	spin_unlock_irq(&net_schedule_list_lock);
+}
+
+static void add_to_net_schedule_list_tail(netif_t *netif)
+{
+	if (__on_net_schedule_list(netif))
+		return;
+
+	spin_lock_irq(&net_schedule_list_lock);
+	if (!__on_net_schedule_list(netif) &&
+	    likely(netif_schedulable(netif))) {
+		list_add_tail(&netif->list, &net_schedule_list);
+		netif_get(netif);
+	}
+	spin_unlock_irq(&net_schedule_list_lock);
+}
+
+/*
+ * Note on CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER:
+ * If this driver is pipelining transmit requests then we can be very
+ * aggressive in avoiding new-packet notifications -- frontend only needs to
+ * send a notification if there are no outstanding unreceived responses.
+ * If we may be buffer transmit buffers for any reason then we must be rather
+ * more conservative and treat this as the final check for pending work.
+ */
+void netif_schedule_work(netif_t *netif)
+{
+	int more_to_do;
+
+#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER
+	more_to_do = RING_HAS_UNCONSUMED_REQUESTS(&netif->tx);
+#else
+	RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do);
+#endif
+
+	if (more_to_do) {
+		add_to_net_schedule_list_tail(netif);
+		maybe_schedule_tx_action();
+	}
+}
+
+void netif_deschedule_work(netif_t *netif)
+{
+	remove_from_net_schedule_list(netif);
+}
+
+
+static void tx_add_credit(netif_t *netif)
+{
+	unsigned long max_burst, max_credit;
+
+	/*
+	 * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
+	 * Otherwise the interface can seize up due to insufficient credit.
+	 */
+	max_burst = RING_GET_REQUEST(&netif->tx, netif->tx.req_cons)->size;
+	max_burst = min(max_burst, 131072UL);
+	max_burst = max(max_burst, netif->credit_bytes);
+
+	/* Take care that adding a new chunk of credit doesn't wrap to zero. */
+	max_credit = netif->remaining_credit + netif->credit_bytes;
+	if (max_credit < netif->remaining_credit)
+		max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
+
+	netif->remaining_credit = min(max_credit, max_burst);
+}
+
+static void tx_credit_callback(unsigned long data)
+{
+	netif_t *netif = (netif_t *)data;
+	tx_add_credit(netif);
+	netif_schedule_work(netif);
+}
+
+static inline int copy_pending_req(PEND_RING_IDX pending_idx)
+{
+	return gnttab_copy_grant_page(grant_tx_handle[pending_idx],
+				      &mmap_pages[pending_idx]);
+}
+
+static void permute_dealloc_ring(PEND_RING_IDX dc, PEND_RING_IDX dp)
+{
+	static unsigned random_src = 0x12345678;
+	unsigned dst_offset;
+	PEND_RING_IDX dest;
+	u16 tmp;
+
+	while (dc != dp) {
+		dst_offset = (random_src / 256) % (dp - dc);
+		dest = dc + dst_offset;
+		tmp = dealloc_ring[MASK_PEND_IDX(dest)];
+		dealloc_ring[MASK_PEND_IDX(dest)] =
+			dealloc_ring[MASK_PEND_IDX(dc)];
+		dealloc_ring[MASK_PEND_IDX(dc)] = tmp;
+		dc++;
+		random_src *= 68389;
+	}
+}
+
+inline static void net_tx_action_dealloc(void)
+{
+	struct netbk_tx_pending_inuse *inuse, *n;
+	gnttab_unmap_grant_ref_t *gop;
+	u16 pending_idx;
+	PEND_RING_IDX dc, dp;
+	netif_t *netif;
+	int ret;
+	LIST_HEAD(list);
+
+	dc = dealloc_cons;
+	gop = tx_unmap_ops;
+
+	/*
+	 * Free up any grants we have finished using
+	 */
+	do {
+		dp = dealloc_prod;
+
+		/* Ensure we see all indices enqueued by netif_idx_release(). */
+		smp_rmb();
+
+		if (MODPARM_permute_returns)
+			permute_dealloc_ring(dc, dp);
+
+		while (dc != dp) {
+			unsigned long pfn;
+
+			pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
+			list_move_tail(&pending_inuse[pending_idx].list, &list);
+
+			pfn = idx_to_pfn(pending_idx);
+			/* Already unmapped? */
+			if (!phys_to_machine_mapping_valid(pfn))
+				continue;
+
+			gnttab_set_unmap_op(gop, idx_to_kaddr(pending_idx),
+					    GNTMAP_host_map,
+					    grant_tx_handle[pending_idx]);
+			gop++;
+		}
+
+		if (netbk_copy_skb_mode != NETBK_DELAYED_COPY_SKB ||
+		    list_empty(&pending_inuse_head))
+			break;
+
+		/* Copy any entries that have been pending for too long. */
+		list_for_each_entry_safe(inuse, n, &pending_inuse_head, list) {
+			if (time_after(inuse->alloc_time + HZ / 2, jiffies))
+				break;
+
+			pending_idx = inuse - pending_inuse;
+
+			pending_tx_info[pending_idx].netif->nr_copied_skbs++;
+
+			switch (copy_pending_req(pending_idx)) {
+			case 0:
+				list_move_tail(&inuse->list, &list);
+				continue;
+			case -EBUSY:
+				list_del_init(&inuse->list);
+				continue;
+			case -ENOENT:
+				continue;
+			}
+
+			break;
+		}
+	} while (dp != dealloc_prod);
+
+	dealloc_cons = dc;
+
+	ret = HYPERVISOR_grant_table_op(
+		GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops);
+	BUG_ON(ret);
+
+	list_for_each_entry_safe(inuse, n, &list, list) {
+		pending_idx = inuse - pending_inuse;
+
+		netif = pending_tx_info[pending_idx].netif;
+
+		make_tx_response(netif, &pending_tx_info[pending_idx].req, 
+				 NETIF_RSP_OKAY);
+
+		/* Ready for next use. */
+		gnttab_reset_grant_page(mmap_pages[pending_idx]);
+
+		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+
+		netif_put(netif);
+
+		list_del_init(&inuse->list);
+	}
+}
+
+static void netbk_tx_err(netif_t *netif, netif_tx_request_t *txp, RING_IDX end)
+{
+	RING_IDX cons = netif->tx.req_cons;
+
+	do {
+		make_tx_response(netif, txp, NETIF_RSP_ERROR);
+		if (cons >= end)
+			break;
+		txp = RING_GET_REQUEST(&netif->tx, cons++);
+	} while (1);
+	netif->tx.req_cons = cons;
+	netif_schedule_work(netif);
+	netif_put(netif);
+}
+
+static int netbk_count_requests(netif_t *netif, netif_tx_request_t *first,
+				netif_tx_request_t *txp, int work_to_do)
+{
+	RING_IDX cons = netif->tx.req_cons;
+	int frags = 0;
+
+	if (!(first->flags & NETTXF_more_data))
+		return 0;
+
+	do {
+		if (frags >= work_to_do) {
+			DPRINTK("Need more frags\n");
+			return -frags;
+		}
+
+		if (unlikely(frags >= MAX_SKB_FRAGS)) {
+			DPRINTK("Too many frags\n");
+			return -frags;
+		}
+
+		memcpy(txp, RING_GET_REQUEST(&netif->tx, cons + frags),
+		       sizeof(*txp));
+		if (txp->size > first->size) {
+			DPRINTK("Frags galore\n");
+			return -frags;
+		}
+
+		first->size -= txp->size;
+		frags++;
+
+		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+			DPRINTK("txp->offset: %x, size: %u\n",
+				txp->offset, txp->size);
+			return -frags;
+		}
+	} while ((txp++)->flags & NETTXF_more_data);
+
+	return frags;
+}
+
+static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif,
+						  struct sk_buff *skb,
+						  netif_tx_request_t *txp,
+						  gnttab_map_grant_ref_t *mop)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	skb_frag_t *frags = shinfo->frags;
+	unsigned long pending_idx = *((u16 *)skb->data);
+	int i, start;
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < shinfo->nr_frags; i++, txp++) {
+		pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)];
+
+		gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx),
+				  GNTMAP_host_map | GNTMAP_readonly,
+				  txp->gref, netif->domid);
+
+		memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
+		netif_get(netif);
+		pending_tx_info[pending_idx].netif = netif;
+		frags[i].page = (void *)pending_idx;
+	}
+
+	return mop;
+}
+
+static int netbk_tx_check_mop(struct sk_buff *skb,
+			       gnttab_map_grant_ref_t **mopp)
+{
+	gnttab_map_grant_ref_t *mop = *mopp;
+	int pending_idx = *((u16 *)skb->data);
+	netif_t *netif = pending_tx_info[pending_idx].netif;
+	netif_tx_request_t *txp;
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i, err, start;
+
+	/* Check status of header. */
+	err = mop->status;
+	if (unlikely(err)) {
+		txp = &pending_tx_info[pending_idx].req;
+		make_tx_response(netif, txp, NETIF_RSP_ERROR);
+		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+		netif_put(netif);
+	} else {
+		set_phys_to_machine(
+			__pa(idx_to_kaddr(pending_idx)) >> PAGE_SHIFT,
+			FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
+		grant_tx_handle[pending_idx] = mop->handle;
+	}
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < nr_frags; i++) {
+		int j, newerr;
+
+		pending_idx = (unsigned long)shinfo->frags[i].page;
+
+		/* Check error status: if okay then remember grant handle. */
+		newerr = (++mop)->status;
+		if (likely(!newerr)) {
+			set_phys_to_machine(
+				__pa(idx_to_kaddr(pending_idx))>>PAGE_SHIFT,
+				FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
+			grant_tx_handle[pending_idx] = mop->handle;
+			/* Had a previous error? Invalidate this fragment. */
+			if (unlikely(err))
+				netif_idx_release(pending_idx);
+			continue;
+		}
+
+		/* Error on this fragment: respond to client with an error. */
+		txp = &pending_tx_info[pending_idx].req;
+		make_tx_response(netif, txp, NETIF_RSP_ERROR);
+		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+		netif_put(netif);
+
+		/* Not the first error? Preceding frags already invalidated. */
+		if (err)
+			continue;
+
+		/* First error: invalidate header and preceding fragments. */
+		pending_idx = *((u16 *)skb->data);
+		netif_idx_release(pending_idx);
+		for (j = start; j < i; j++) {
+			pending_idx = (unsigned long)shinfo->frags[i].page;
+			netif_idx_release(pending_idx);
+		}
+
+		/* Remember the error: invalidate all subsequent fragments. */
+		err = newerr;
+	}
+
+	*mopp = mop + 1;
+	return err;
+}
+
+static void netbk_fill_frags(struct sk_buff *skb)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i;
+
+	for (i = 0; i < nr_frags; i++) {
+		skb_frag_t *frag = shinfo->frags + i;
+		netif_tx_request_t *txp;
+		unsigned long pending_idx;
+
+		pending_idx = (unsigned long)frag->page;
+
+		pending_inuse[pending_idx].alloc_time = jiffies;
+		list_add_tail(&pending_inuse[pending_idx].list,
+			      &pending_inuse_head);
+
+		txp = &pending_tx_info[pending_idx].req;
+		frag->page = virt_to_page(idx_to_kaddr(pending_idx));
+		frag->size = txp->size;
+		frag->page_offset = txp->offset;
+
+		skb->len += txp->size;
+		skb->data_len += txp->size;
+		skb->truesize += txp->size;
+	}
+}
+
+int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras,
+		     int work_to_do)
+{
+	struct netif_extra_info extra;
+	RING_IDX cons = netif->tx.req_cons;
+
+	do {
+		if (unlikely(work_to_do-- <= 0)) {
+			DPRINTK("Missing extra info\n");
+			return -EBADR;
+		}
+
+		memcpy(&extra, RING_GET_REQUEST(&netif->tx, cons),
+		       sizeof(extra));
+		if (unlikely(!extra.type ||
+			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+			netif->tx.req_cons = ++cons;
+			DPRINTK("Invalid extra type: %d\n", extra.type);
+			return -EINVAL;
+		}
+
+		memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
+		netif->tx.req_cons = ++cons;
+	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
+
+	return work_to_do;
+}
+
+static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso)
+{
+	if (!gso->u.gso.size) {
+		DPRINTK("GSO size must not be zero.\n");
+		return -EINVAL;
+	}
+
+	/* Currently only TCPv4 S.O. is supported. */
+	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+		DPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
+		return -EINVAL;
+	}
+
+	skb_shinfo(skb)->gso_size = gso->u.gso.size;
+	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+
+	/* Header must be checked, and gso_segs computed. */
+	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+	skb_shinfo(skb)->gso_segs = 0;
+
+	return 0;
+}
+
+/* Called after netfront has transmitted */
+static void net_tx_action(unsigned long unused)
+{
+	struct list_head *ent;
+	struct sk_buff *skb;
+	netif_t *netif;
+	netif_tx_request_t txreq;
+	netif_tx_request_t txfrags[MAX_SKB_FRAGS];
+	struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
+	u16 pending_idx;
+	RING_IDX i;
+	gnttab_map_grant_ref_t *mop;
+	unsigned int data_len;
+	int ret, work_to_do;
+
+	if (dealloc_cons != dealloc_prod)
+		net_tx_action_dealloc();
+
+	mop = tx_map_ops;
+	BUILD_BUG_ON(MAX_SKB_FRAGS >= MAX_PENDING_REQS);
+	while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+		!list_empty(&net_schedule_list)) {
+		/* Get a netif from the list with work to do. */
+		ent = net_schedule_list.next;
+		netif = list_entry(ent, netif_t, list);
+		netif_get(netif);
+		remove_from_net_schedule_list(netif);
+
+		RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, work_to_do);
+		if (!work_to_do) {
+			netif_put(netif);
+			continue;
+		}
+
+		i = netif->tx.req_cons;
+		rmb(); /* Ensure that we see the request before we copy it. */
+		memcpy(&txreq, RING_GET_REQUEST(&netif->tx, i), sizeof(txreq));
+
+		/* Credit-based scheduling. */
+		if (txreq.size > netif->remaining_credit) {
+			unsigned long now = jiffies;
+			unsigned long next_credit = 
+				netif->credit_timeout.expires +
+				msecs_to_jiffies(netif->credit_usec / 1000);
+
+			/* Timer could already be pending in rare cases. */
+			if (timer_pending(&netif->credit_timeout)) {
+				netif_put(netif);
+				continue;
+			}
+
+			/* Passed the point where we can replenish credit? */
+			if (time_after_eq(now, next_credit)) {
+				netif->credit_timeout.expires = now;
+				tx_add_credit(netif);
+			}
+
+			/* Still too big to send right now? Set a callback. */
+			if (txreq.size > netif->remaining_credit) {
+				netif->credit_timeout.data     =
+					(unsigned long)netif;
+				netif->credit_timeout.function =
+					tx_credit_callback;
+				mod_timer(&netif->credit_timeout, next_credit);
+				netif_put(netif);
+				continue;
+			}
+		}
+		netif->remaining_credit -= txreq.size;
+
+		work_to_do--;
+		netif->tx.req_cons = ++i;
+
+		memset(extras, 0, sizeof(extras));
+		if (txreq.flags & NETTXF_extra_info) {
+			work_to_do = netbk_get_extras(netif, extras,
+						      work_to_do);
+			i = netif->tx.req_cons;
+			if (unlikely(work_to_do < 0)) {
+				netbk_tx_err(netif, &txreq, i);
+				continue;
+			}
+		}
+
+		ret = netbk_count_requests(netif, &txreq, txfrags, work_to_do);
+		if (unlikely(ret < 0)) {
+			netbk_tx_err(netif, &txreq, i - ret);
+			continue;
+		}
+		i += ret;
+
+		if (unlikely(txreq.size < ETH_HLEN)) {
+			DPRINTK("Bad packet size: %d\n", txreq.size);
+			netbk_tx_err(netif, &txreq, i);
+			continue;
+		}
+
+		/* No crossing a page as the payload mustn't fragment. */
+		if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
+			DPRINTK("txreq.offset: %x, size: %u, end: %lu\n", 
+				txreq.offset, txreq.size, 
+				(txreq.offset &~PAGE_MASK) + txreq.size);
+			netbk_tx_err(netif, &txreq, i);
+			continue;
+		}
+
+		pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+
+		data_len = (txreq.size > PKT_PROT_LEN &&
+			    ret < MAX_SKB_FRAGS) ?
+			PKT_PROT_LEN : txreq.size;
+
+		skb = alloc_skb(data_len + 16 + NET_IP_ALIGN,
+				GFP_ATOMIC | __GFP_NOWARN);
+		if (unlikely(skb == NULL)) {
+			DPRINTK("Can't allocate a skb in start_xmit.\n");
+			netbk_tx_err(netif, &txreq, i);
+			break;
+		}
+
+		/* Packets passed to netif_rx() must have some headroom. */
+		skb_reserve(skb, 16 + NET_IP_ALIGN);
+
+		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+			struct netif_extra_info *gso;
+			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+			if (netbk_set_skb_gso(skb, gso)) {
+				kfree_skb(skb);
+				netbk_tx_err(netif, &txreq, i);
+				continue;
+			}
+		}
+
+		gnttab_set_map_op(mop, idx_to_kaddr(pending_idx),
+				  GNTMAP_host_map | GNTMAP_readonly,
+				  txreq.gref, netif->domid);
+		mop++;
+
+		memcpy(&pending_tx_info[pending_idx].req,
+		       &txreq, sizeof(txreq));
+		pending_tx_info[pending_idx].netif = netif;
+		*((u16 *)skb->data) = pending_idx;
+
+		__skb_put(skb, data_len);
+
+		skb_shinfo(skb)->nr_frags = ret;
+		if (data_len < txreq.size) {
+			skb_shinfo(skb)->nr_frags++;
+			skb_shinfo(skb)->frags[0].page =
+				(void *)(unsigned long)pending_idx;
+		} else {
+			/* Discriminate from any valid pending_idx value. */
+			skb_shinfo(skb)->frags[0].page = (void *)~0UL;
+		}
+
+		__skb_queue_tail(&tx_queue, skb);
+
+		pending_cons++;
+
+		mop = netbk_get_requests(netif, skb, txfrags, mop);
+
+		netif->tx.req_cons = i;
+		netif_schedule_work(netif);
+
+		if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
+			break;
+	}
+
+	if (mop == tx_map_ops)
+		return;
+
+	ret = HYPERVISOR_grant_table_op(
+		GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops);
+	BUG_ON(ret);
+
+	mop = tx_map_ops;
+	while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
+		netif_tx_request_t *txp;
+
+		pending_idx = *((u16 *)skb->data);
+		netif       = pending_tx_info[pending_idx].netif;
+		txp         = &pending_tx_info[pending_idx].req;
+
+		/* Check the remap error code. */
+		if (unlikely(netbk_tx_check_mop(skb, &mop))) {
+			DPRINTK("netback grant failed.\n");
+			skb_shinfo(skb)->nr_frags = 0;
+			kfree_skb(skb);
+			continue;
+		}
+
+		data_len = skb->len;
+		memcpy(skb->data,
+		       (void *)(idx_to_kaddr(pending_idx)|txp->offset),
+		       data_len);
+		if (data_len < txp->size) {
+			/* Append the packet payload as a fragment. */
+			txp->offset += data_len;
+			txp->size -= data_len;
+		} else {
+			/* Schedule a response immediately. */
+			netif_idx_release(pending_idx);
+		}
+
+		/*
+		 * Old frontends do not assert data_validated but we
+		 * can infer it from csum_blank so test both flags.
+		 */
+		if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			skb->proto_data_valid = 1;
+		} else {
+			skb->ip_summed = CHECKSUM_NONE;
+			skb->proto_data_valid = 0;
+		}
+		skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank);
+
+		netbk_fill_frags(skb);
+
+		skb->dev      = netif->dev;
+		skb->protocol = eth_type_trans(skb, skb->dev);
+
+		netif->stats.rx_bytes += skb->len;
+		netif->stats.rx_packets++;
+
+		if (unlikely(netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB) &&
+		    unlikely(skb_linearize(skb))) {
+			DPRINTK("Can't linearize skb in net_tx_action.\n");
+			kfree_skb(skb);
+			continue;
+		}
+
+		netif_rx(skb);
+		netif->dev->last_rx = jiffies;
+	}
+
+	if (netbk_copy_skb_mode == NETBK_DELAYED_COPY_SKB &&
+	    !list_empty(&pending_inuse_head)) {
+		struct netbk_tx_pending_inuse *oldest;
+
+		oldest = list_entry(pending_inuse_head.next,
+				    struct netbk_tx_pending_inuse, list);
+		mod_timer(&netbk_tx_pending_timer, oldest->alloc_time + HZ);
+	}
+}
+
+static void netif_idx_release(u16 pending_idx)
+{
+	static DEFINE_SPINLOCK(_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&_lock, flags);
+	dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx;
+	/* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */
+	smp_wmb();
+	dealloc_prod++;
+	spin_unlock_irqrestore(&_lock, flags);
+
+	tasklet_schedule(&net_tx_tasklet);
+}
+
+static void netif_page_release(struct page *page, unsigned int order)
+{
+	int idx = netif_page_index(page);
+	BUG_ON(order);
+	BUG_ON(idx < 0);
+	netif_idx_release(idx);
+}
+
+irqreturn_t netif_be_int(int irq, void *dev_id)
+{
+	netif_t *netif = dev_id;
+
+	add_to_net_schedule_list_tail(netif);
+	maybe_schedule_tx_action();
+
+	if (netif_schedulable(netif) && !netbk_queue_full(netif))
+		netif_wake_queue(netif->dev);
+
+	return IRQ_HANDLED;
+}
+
+static void make_tx_response(netif_t *netif, 
+			     netif_tx_request_t *txp,
+			     s8       st)
+{
+	RING_IDX i = netif->tx.rsp_prod_pvt;
+	netif_tx_response_t *resp;
+	int notify;
+
+	resp = RING_GET_RESPONSE(&netif->tx, i);
+	resp->id     = txp->id;
+	resp->status = st;
+
+	if (txp->flags & NETTXF_extra_info)
+		RING_GET_RESPONSE(&netif->tx, ++i)->status = NETIF_RSP_NULL;
+
+	netif->tx.rsp_prod_pvt = ++i;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->tx, notify);
+	if (notify)
+		notify_remote_via_irq(netif->irq);
+
+#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER
+	if (i == netif->tx.req_cons) {
+		int more_to_do;
+		RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do);
+		if (more_to_do)
+			add_to_net_schedule_list_tail(netif);
+	}
+#endif
+}
+
+static netif_rx_response_t *make_rx_response(netif_t *netif, 
+					     u16      id, 
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags)
+{
+	RING_IDX i = netif->rx.rsp_prod_pvt;
+	netif_rx_response_t *resp;
+
+	resp = RING_GET_RESPONSE(&netif->rx, i);
+	resp->offset     = offset;
+	resp->flags      = flags;
+	resp->id         = id;
+	resp->status     = (s16)size;
+	if (st < 0)
+		resp->status = (s16)st;
+
+	netif->rx.rsp_prod_pvt = ++i;
+
+	return resp;
+}
+
+#ifdef NETBE_DEBUG_INTERRUPT
+static irqreturn_t netif_be_dbg(int irq, void *dev_id)
+{
+	struct list_head *ent;
+	netif_t *netif;
+	int i = 0;
+
+	printk(KERN_ALERT "netif_schedule_list:\n");
+	spin_lock_irq(&net_schedule_list_lock);
+
+	list_for_each (ent, &net_schedule_list) {
+		netif = list_entry(ent, netif_t, list);
+		printk(KERN_ALERT " %d: private(rx_req_cons=%08x "
+		       "rx_resp_prod=%08x\n",
+		       i, netif->rx.req_cons, netif->rx.rsp_prod_pvt);
+		printk(KERN_ALERT "   tx_req_cons=%08x tx_resp_prod=%08x)\n",
+		       netif->tx.req_cons, netif->tx.rsp_prod_pvt);
+		printk(KERN_ALERT "   shared(rx_req_prod=%08x "
+		       "rx_resp_prod=%08x\n",
+		       netif->rx.sring->req_prod, netif->rx.sring->rsp_prod);
+		printk(KERN_ALERT "   rx_event=%08x tx_req_prod=%08x\n",
+		       netif->rx.sring->rsp_event, netif->tx.sring->req_prod);
+		printk(KERN_ALERT "   tx_resp_prod=%08x, tx_event=%08x)\n",
+		       netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event);
+		i++;
+	}
+
+	spin_unlock_irq(&net_schedule_list_lock);
+	printk(KERN_ALERT " ** End of netif_schedule_list **\n");
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction netif_be_dbg_action = {
+	.handler = netif_be_dbg,
+	.flags   = IRQF_SHARED,
+	.name    = "net-be-dbg"
+};
+#endif
+
+static int __init netback_init(void)
+{
+	int i;
+	struct page *page;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	/* We can increase reservation by this much in net_rx_action(). */
+	balloon_update_driver_allowance(NET_RX_RING_SIZE);
+
+	skb_queue_head_init(&rx_queue);
+	skb_queue_head_init(&tx_queue);
+
+	init_timer(&net_timer);
+	net_timer.data = 0;
+	net_timer.function = net_alarm;
+
+	init_timer(&netbk_tx_pending_timer);
+	netbk_tx_pending_timer.data = 0;
+	netbk_tx_pending_timer.function = netbk_tx_pending_timeout;
+
+	mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
+	if (mmap_pages == NULL) {
+		printk("%s: out of memory\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < MAX_PENDING_REQS; i++) {
+		page = mmap_pages[i];
+		SetPageForeign(page, netif_page_release);
+		netif_set_page_index(page, i);
+		INIT_LIST_HEAD(&pending_inuse[i].list);
+	}
+
+	pending_cons = 0;
+	pending_prod = MAX_PENDING_REQS;
+	for (i = 0; i < MAX_PENDING_REQS; i++)
+		pending_ring[i] = i;
+
+	spin_lock_init(&net_schedule_list_lock);
+	INIT_LIST_HEAD(&net_schedule_list);
+
+	netbk_copy_skb_mode = NETBK_DONT_COPY_SKB;
+	if (MODPARM_copy_skb) {
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
+					      NULL, 0))
+			netbk_copy_skb_mode = NETBK_ALWAYS_COPY_SKB;
+		else
+			netbk_copy_skb_mode = NETBK_DELAYED_COPY_SKB;
+	}
+
+	netif_accel_init();
+
+	netif_xenbus_init();
+
+#ifdef NETBE_DEBUG_INTERRUPT
+	(void)bind_virq_to_irqaction(VIRQ_DEBUG,
+				     0,
+				     &netif_be_dbg_action);
+#endif
+
+	return 0;
+}
+
+module_init(netback_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/netback/interface.c
+++ linux-ec2-2.6.32/drivers/xen/netback/interface.c
@@ -0,0 +1,398 @@
+/******************************************************************************
+ * arch/xen/drivers/netif/backend/interface.c
+ * 
+ * Network-device interface management.
+ * 
+ * Copyright (c) 2004-2005, Keir Fraser
+ * 
+ * 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 "common.h"
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+
+/*
+ * Module parameter 'queue_length':
+ * 
+ * Enables queuing in the network stack when a client has run out of receive
+ * descriptors. Although this feature can improve receive bandwidth by avoiding
+ * packet loss, it can also result in packets sitting in the 'tx_queue' for
+ * unbounded time. This is bad if those packets hold onto foreign resources.
+ * For example, consider a packet that holds onto resources belonging to the
+ * guest for which it is queued (e.g., packet received on vif1.0, destined for
+ * vif1.1 which is not activated in the guest): in this situation the guest
+ * will never be destroyed, unless vif1.1 is taken down. To avoid this, we
+ * run a timer (tx_queue_timeout) to drain the queue when the interface is
+ * blocked.
+ */
+static unsigned long netbk_queue_length = 32;
+module_param_named(queue_length, netbk_queue_length, ulong, 0644);
+
+static void __netif_up(netif_t *netif)
+{
+	enable_irq(netif->irq);
+	netif_schedule_work(netif);
+}
+
+static void __netif_down(netif_t *netif)
+{
+	disable_irq(netif->irq);
+	netif_deschedule_work(netif);
+}
+
+static int net_open(struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+	if (netback_carrier_ok(netif)) {
+		__netif_up(netif);
+		netif_start_queue(dev);
+	}
+	return 0;
+}
+
+static int net_close(struct net_device *dev)
+{
+	netif_t *netif = netdev_priv(dev);
+	if (netback_carrier_ok(netif))
+		__netif_down(netif);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static int netbk_change_mtu(struct net_device *dev, int mtu)
+{
+	int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
+
+	if (mtu > max)
+		return -EINVAL;
+	dev->mtu = mtu;
+	return 0;
+}
+
+static int netbk_set_sg(struct net_device *dev, u32 data)
+{
+	if (data) {
+		netif_t *netif = netdev_priv(dev);
+
+		if (!(netif->features & NETIF_F_SG))
+			return -ENOSYS;
+	}
+
+	return ethtool_op_set_sg(dev, data);
+}
+
+static int netbk_set_tso(struct net_device *dev, u32 data)
+{
+	if (data) {
+		netif_t *netif = netdev_priv(dev);
+
+		if (!(netif->features & NETIF_F_TSO))
+			return -ENOSYS;
+	}
+
+	return ethtool_op_set_tso(dev, data);
+}
+
+static void netbk_get_drvinfo(struct net_device *dev,
+			      struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "netbk");
+	strcpy(info->bus_info, dev_name(dev->dev.parent));
+}
+
+static const struct netif_stat {
+	char name[ETH_GSTRING_LEN];
+	u16 offset;
+} netbk_stats[] = {
+	{ "copied_skbs", offsetof(netif_t, nr_copied_skbs) },
+};
+
+static int netbk_get_stats_count(struct net_device *dev)
+{
+	return ARRAY_SIZE(netbk_stats);
+}
+
+static void netbk_get_ethtool_stats(struct net_device *dev,
+				   struct ethtool_stats *stats, u64 * data)
+{
+	void *netif = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(netbk_stats); i++)
+		data[i] = *(int *)(netif + netbk_stats[i].offset);
+}
+
+static void netbk_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(netbk_stats); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       netbk_stats[i].name, ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+static const struct ethtool_ops network_ethtool_ops =
+{
+	.get_drvinfo = netbk_get_drvinfo,
+
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = netbk_set_sg,
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = netbk_set_tso,
+	.get_link = ethtool_op_get_link,
+
+	.get_stats_count = netbk_get_stats_count,
+	.get_ethtool_stats = netbk_get_ethtool_stats,
+	.get_strings = netbk_get_strings,
+};
+
+static const struct net_device_ops netif_be_netdev_ops = {
+	.ndo_open               = net_open,
+	.ndo_stop               = net_close,
+	.ndo_start_xmit         = netif_be_start_xmit,
+	.ndo_change_mtu	        = netbk_change_mtu,
+	.ndo_get_stats          = netif_be_get_stats,
+};
+
+netif_t *netif_alloc(struct device *parent, domid_t domid, unsigned int handle)
+{
+	int err = 0;
+	struct net_device *dev;
+	netif_t *netif;
+	char name[IFNAMSIZ] = {};
+
+	snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
+	dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
+	if (dev == NULL) {
+		DPRINTK("Could not create netif: out of memory\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	SET_NETDEV_DEV(dev, parent);
+
+	netif = netdev_priv(dev);
+	memset(netif, 0, sizeof(*netif));
+	netif->domid  = domid;
+	netif->handle = handle;
+	atomic_set(&netif->refcnt, 1);
+	init_waitqueue_head(&netif->waiting_to_free);
+	netif->dev = dev;
+
+	netback_carrier_off(netif);
+
+	netif->credit_bytes = netif->remaining_credit = ~0UL;
+	netif->credit_usec  = 0UL;
+	init_timer(&netif->credit_timeout);
+	/* Initialize 'expires' now: it's used to track the credit window. */
+	netif->credit_timeout.expires = jiffies;
+
+	init_timer(&netif->tx_queue_timeout);
+
+	dev->netdev_ops	     = &netif_be_netdev_ops;
+	dev->features        = NETIF_F_IP_CSUM;
+
+	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
+
+	dev->tx_queue_len = netbk_queue_length;
+
+	/*
+	 * Initialise a dummy MAC address. We choose the numerically
+	 * largest non-broadcast address to prevent the address getting
+	 * stolen by an Ethernet bridge for STP purposes.
+	 * (FE:FF:FF:FF:FF:FF)
+	 */ 
+	memset(dev->dev_addr, 0xFF, ETH_ALEN);
+	dev->dev_addr[0] &= ~0x01;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		DPRINTK("Could not register new net device %s: err=%d\n",
+			dev->name, err);
+		free_netdev(dev);
+		return ERR_PTR(err);
+	}
+
+	DPRINTK("Successfully created netif\n");
+	return netif;
+}
+
+static int map_frontend_pages(
+	netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
+{
+	struct gnttab_map_grant_ref op;
+
+	gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
+			  GNTMAP_host_map, tx_ring_ref, netif->domid);
+    
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) { 
+		DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
+		return op.status;
+	}
+
+	netif->tx_shmem_ref    = tx_ring_ref;
+	netif->tx_shmem_handle = op.handle;
+
+	gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
+			  GNTMAP_host_map, rx_ring_ref, netif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		struct gnttab_unmap_grant_ref unop;
+
+		gnttab_set_unmap_op(&unop,
+				    (unsigned long)netif->tx_comms_area->addr,
+				    GNTMAP_host_map, netif->tx_shmem_handle);
+		VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+					       &unop, 1));
+		DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
+		return op.status;
+	}
+
+	netif->rx_shmem_ref    = rx_ring_ref;
+	netif->rx_shmem_handle = op.handle;
+
+	return 0;
+}
+
+static void unmap_frontend_pages(netif_t *netif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
+			    GNTMAP_host_map, netif->tx_shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+
+	gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
+			    GNTMAP_host_map, netif->rx_shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+}
+
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+	      unsigned long rx_ring_ref, unsigned int evtchn)
+{
+	int err = -ENOMEM;
+	netif_tx_sring_t *txs;
+	netif_rx_sring_t *rxs;
+
+	/* Already connected through? */
+	if (netif->irq)
+		return 0;
+
+	netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (netif->tx_comms_area == NULL)
+		return -ENOMEM;
+	netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (netif->rx_comms_area == NULL)
+		goto err_rx;
+
+	err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
+	if (err)
+		goto err_map;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		netif->domid, evtchn, netif_be_int, 0,
+		netif->dev->name, netif);
+	if (err < 0)
+		goto err_hypervisor;
+	BUG_ON(err < DYNIRQ_BASE || err >= DYNIRQ_BASE + NR_DYNIRQS);
+	netif->irq = err;
+	disable_irq(netif->irq);
+
+	txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
+	BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
+
+	rxs = (netif_rx_sring_t *)
+		((char *)netif->rx_comms_area->addr);
+	BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
+
+	netif->rx_req_cons_peek = 0;
+
+	netif_get(netif);
+
+	rtnl_lock();
+	netback_carrier_on(netif);
+	if (netif_running(netif->dev))
+		__netif_up(netif);
+	rtnl_unlock();
+
+	return 0;
+err_hypervisor:
+	unmap_frontend_pages(netif);
+err_map:
+	free_vm_area(netif->rx_comms_area);
+err_rx:
+	free_vm_area(netif->tx_comms_area);
+	return err;
+}
+
+void netif_disconnect(netif_t *netif)
+{
+	if (netback_carrier_ok(netif)) {
+		rtnl_lock();
+		netback_carrier_off(netif);
+		netif_carrier_off(netif->dev); /* discard queued packets */
+		if (netif_running(netif->dev))
+			__netif_down(netif);
+		rtnl_unlock();
+		netif_put(netif);
+	}
+
+	atomic_dec(&netif->refcnt);
+	wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
+
+	del_timer_sync(&netif->credit_timeout);
+	del_timer_sync(&netif->tx_queue_timeout);
+
+	if (netif->irq)
+		unbind_from_irqhandler(netif->irq, netif);
+	
+	unregister_netdev(netif->dev);
+
+	if (netif->tx.sring) {
+		unmap_frontend_pages(netif);
+		free_vm_area(netif->tx_comms_area);
+		free_vm_area(netif->rx_comms_area);
+	}
+
+	free_netdev(netif->dev);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/netfront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/netfront/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_XEN_NETDEV_FRONTEND)	:= xennet.o
+
+xennet-objs := netfront.o accel.o
--- linux-ec2-2.6.32.orig/drivers/xen/netfront/netfront.h
+++ linux-ec2-2.6.32/drivers/xen/netfront/netfront.h
@@ -0,0 +1,276 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ * Copyright (c) 2005, 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.
+ */
+
+#ifndef NETFRONT_H
+#define NETFRONT_H
+
+#include <xen/interface/io/netif.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+
+#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
+
+#include <xen/xenbus.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+/* 
+ * Function pointer table for hooks into a network acceleration
+ * plugin.  These are called at appropriate points from the netfront
+ * driver 
+ */
+struct netfront_accel_hooks {
+	/* 
+	 * new_device: Accelerator hook to ask the plugin to support a
+	 * new network interface
+	 */
+	int (*new_device)(struct net_device *net_dev, struct xenbus_device *dev);
+	/*
+	 * remove: Opposite of new_device
+	 */
+	int (*remove)(struct xenbus_device *dev);
+	/*
+	 * The net_device is being polled, check the accelerated
+	 * hardware for any pending packets
+	 */
+	int (*netdev_poll)(struct net_device *dev, int *pbudget);
+	/*
+	 * start_xmit: Used to give the accelerated plugin the option
+	 * of sending a packet.  Returns non-zero if has done so, or
+	 * zero to decline and force the packet onto normal send
+	 * path
+	 */
+	int (*start_xmit)(struct sk_buff *skb, struct net_device *dev);
+	/* 
+	 * start/stop_napi_interrupts Used by netfront to indicate
+	 * when napi interrupts should be enabled or disabled 
+	 */
+	int (*start_napi_irq)(struct net_device *dev);
+	void (*stop_napi_irq)(struct net_device *dev);
+	/* 
+	 * Called before re-enabling the TX queue to check the fast
+	 * path has slots too
+	 */
+	int (*check_ready)(struct net_device *dev);
+	/*
+	 * Get the fastpath network statistics
+	 */
+	int (*get_stats)(struct net_device *dev,
+			 struct net_device_stats *stats);
+};
+
+
+/* Version of API/protocol for communication between netfront and
+   acceleration plugin supported */
+#define NETFRONT_ACCEL_VERSION 0x00010003
+
+/* 
+ * Per-netfront device state for the accelerator.  This is used to
+ * allow efficient per-netfront device access to the accelerator
+ * hooks 
+ */
+struct netfront_accel_vif_state {
+	struct list_head link;
+
+	struct xenbus_device *dev;
+	struct netfront_info *np;
+	struct netfront_accel_hooks *hooks;
+
+	/* Watch on the accelerator configuration value */
+	struct xenbus_watch accel_watch;
+	/* Work item to process change in accelerator */
+	struct work_struct accel_work;
+	/* The string from xenbus last time accel_watch fired */
+	char *accel_frontend;
+}; 
+
+/* 
+ * Per-accelerator state stored in netfront.  These form a list that
+ * is used to track which devices are accelerated by which plugins,
+ * and what plugins are available/have been requested 
+ */
+struct netfront_accelerator {
+	/* Used to make a list */
+	struct list_head link;
+	/* ID of the accelerator */
+	int id;
+	/*
+	 * String describing the accelerator.  Currently this is the
+	 * name of the accelerator module.  This is provided by the
+	 * backend accelerator through xenstore 
+	 */
+	char *frontend;
+	/* The hooks into the accelerator plugin module */
+	struct netfront_accel_hooks *hooks;
+
+	/* 
+	 * List of per-netfront device state (struct
+	 * netfront_accel_vif_state) for each netfront device that is
+	 * using this accelerator
+	 */
+	struct list_head vif_states;
+	spinlock_t vif_states_lock;
+};
+
+struct netfront_info {
+	struct list_head list;
+	struct net_device *netdev;
+
+	struct net_device_stats stats;
+
+	struct netif_tx_front_ring tx;
+	struct netif_rx_front_ring rx;
+
+	spinlock_t   tx_lock;
+	spinlock_t   rx_lock;
+
+	struct napi_struct	napi;
+
+	unsigned int irq;
+	unsigned int copying_receiver;
+	unsigned int carrier;
+
+	/* Receive-ring batched refills. */
+#define RX_MIN_TARGET 8
+#define RX_DFL_MIN_TARGET 64
+#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+	unsigned rx_min_target, rx_max_target, rx_target;
+	struct sk_buff_head rx_batch;
+
+	struct timer_list rx_refill_timer;
+
+	/*
+	 * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs
+	 * is an index into a chain of free entries.
+	 */
+	struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
+	struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
+
+#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+	grant_ref_t gref_tx_head;
+	grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
+	grant_ref_t gref_rx_head;
+	grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
+
+	struct xenbus_device *xbdev;
+	int tx_ring_ref;
+	int rx_ring_ref;
+	u8 mac[ETH_ALEN];
+
+	unsigned long rx_pfn_array[NET_RX_RING_SIZE];
+	struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
+	struct mmu_update rx_mmu[NET_RX_RING_SIZE];
+
+	/* Private pointer to state internal to accelerator module */
+	void *accel_priv;
+	/* The accelerator used by this netfront device */
+	struct netfront_accelerator *accelerator;
+	/* The accelerator state for this netfront device */
+	struct netfront_accel_vif_state accel_vif_state;
+};
+
+
+/* Exported Functions */
+
+/*
+ * Called by an accelerator plugin module when it has loaded.
+ *
+ * frontend: the string describing the accelerator, currently the module name 
+ * hooks: the hooks for netfront to use to call into the accelerator
+ * version: the version of API between frontend and plugin requested
+ * 
+ * return: 0 on success, <0 on error, >0 (with version supported) on
+ * version mismatch
+ */
+extern int netfront_accelerator_loaded(int version, const char *frontend, 
+				       struct netfront_accel_hooks *hooks);
+
+/* 
+ * Called by an accelerator plugin module when it is about to unload.
+ *
+ * frontend: the string describing the accelerator.  Must match the
+ * one passed to netfront_accelerator_loaded()
+ */ 
+extern void netfront_accelerator_stop(const char *frontend);
+
+/* 
+ * Called by an accelerator before waking the net device's TX queue to
+ * ensure the slow path has available slots.  Returns true if OK to
+ * wake, false if still busy 
+ */
+extern int netfront_check_queue_ready(struct net_device *net_dev);
+
+
+/* Internal-to-netfront Functions */
+
+/* 
+ * Call into accelerator and check to see if it has tx space before we
+ * wake the net device's TX queue.  Returns true if OK to wake, false
+ * if still busy
+ */ 
+extern 
+int netfront_check_accelerator_queue_ready(struct net_device *dev,
+					   struct netfront_info *np);
+extern
+int netfront_accelerator_call_remove(struct netfront_info *np,
+				     struct xenbus_device *dev);
+extern
+int netfront_accelerator_suspend(struct netfront_info *np,
+				 struct xenbus_device *dev);
+extern
+int netfront_accelerator_suspend_cancel(struct netfront_info *np,
+					struct xenbus_device *dev);
+extern
+void netfront_accelerator_resume(struct netfront_info *np,
+				 struct xenbus_device *dev);
+extern
+void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
+					     struct net_device *dev);
+extern
+int netfront_accelerator_call_get_stats(struct netfront_info *np,
+					struct net_device *dev);
+extern
+void netfront_accelerator_add_watch(struct netfront_info *np);
+
+extern
+void netif_init_accel(void);
+extern
+void netif_exit_accel(void);
+
+extern
+void init_accelerator_vif(struct netfront_info *np,
+			  struct xenbus_device *dev);
+#endif /* NETFRONT_H */
--- linux-ec2-2.6.32.orig/drivers/xen/netfront/accel.c
+++ linux-ec2-2.6.32/drivers/xen/netfront/accel.c
@@ -0,0 +1,828 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
+ * 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.
+ */
+
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+
+#include "netfront.h"
+
+#define DPRINTK(fmt, args...)				\
+	pr_debug("netfront/accel (%s:%d) " fmt,		\
+	       __FUNCTION__, __LINE__, ##args)
+#define IPRINTK(fmt, args...)				\
+	printk(KERN_INFO "netfront/accel: " fmt, ##args)
+#define WPRINTK(fmt, args...)				\
+	printk(KERN_WARNING "netfront/accel: " fmt, ##args)
+
+static int netfront_remove_accelerator(struct netfront_info *np,
+				       struct xenbus_device *dev);
+static int netfront_load_accelerator(struct netfront_info *np, 
+				     struct xenbus_device *dev, 
+				     const char *frontend);
+
+static void netfront_accelerator_remove_watch(struct netfront_info *np);
+
+/*
+ * List of all netfront accelerator plugin modules available.  Each
+ * list entry is of type struct netfront_accelerator.
+ */ 
+static struct list_head accelerators_list;
+
+/* Workqueue to process acceleration configuration changes */
+struct workqueue_struct *accel_watch_workqueue;
+
+/* Mutex to prevent concurrent loads and suspends, etc. */
+DEFINE_MUTEX(accelerator_mutex);
+
+void netif_init_accel(void)
+{
+	INIT_LIST_HEAD(&accelerators_list);
+
+	accel_watch_workqueue = create_workqueue("net_accel");
+}
+
+void netif_exit_accel(void)
+{
+	struct netfront_accelerator *accelerator, *tmp;
+
+	flush_workqueue(accel_watch_workqueue);
+	destroy_workqueue(accel_watch_workqueue);
+
+	/* No lock required as everything else should be quiet by now */
+	list_for_each_entry_safe(accelerator, tmp, &accelerators_list, link) {
+		BUG_ON(!list_empty(&accelerator->vif_states));
+
+		list_del(&accelerator->link);
+		kfree(accelerator->frontend);
+		kfree(accelerator);
+	}
+}
+
+
+/* 
+ * Watch the configured accelerator and change plugin if it's modified 
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+static void accel_watch_work(struct work_struct *context)
+#else
+static void accel_watch_work(void *context)
+#endif
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	struct netfront_accel_vif_state *vif_state = 
+		container_of(context, struct netfront_accel_vif_state, 
+			     accel_work);
+#else
+        struct netfront_accel_vif_state *vif_state = 
+		(struct netfront_accel_vif_state *)context;
+#endif
+	struct netfront_info *np = vif_state->np;
+	char *accel_frontend;
+	int accel_len, rc = -1;
+
+	mutex_lock(&accelerator_mutex);
+
+	accel_frontend = xenbus_read(XBT_NIL, np->xbdev->otherend, 
+				     "accel-frontend", &accel_len);
+	if (IS_ERR(accel_frontend)) {
+		accel_frontend = NULL;
+		netfront_remove_accelerator(np, np->xbdev);
+	} else {
+		/* If this is the first time, request the accelerator,
+		   otherwise only request one if it has changed */
+		if (vif_state->accel_frontend == NULL) {
+			rc = netfront_load_accelerator(np, np->xbdev, 
+						       accel_frontend);
+		} else {
+			if (strncmp(vif_state->accel_frontend, accel_frontend,
+				    accel_len)) {
+				netfront_remove_accelerator(np, np->xbdev);
+				rc = netfront_load_accelerator(np, np->xbdev, 
+							       accel_frontend);
+			}
+		}
+	}
+
+	/* Get rid of previous state and replace with the new name */
+	if (vif_state->accel_frontend != NULL)
+		kfree(vif_state->accel_frontend);
+	vif_state->accel_frontend = accel_frontend;
+
+	mutex_unlock(&accelerator_mutex);
+
+	if (rc == 0) {
+		DPRINTK("requesting module %s\n", accel_frontend);
+		request_module("%s", accel_frontend);
+		/*
+		 * Module should now call netfront_accelerator_loaded() once
+		 * it's up and running, and we can continue from there 
+		 */
+	}
+}
+
+
+static void accel_watch_changed(struct xenbus_watch *watch,
+				const char **vec, unsigned int len)
+{
+	struct netfront_accel_vif_state *vif_state = 
+		container_of(watch, struct netfront_accel_vif_state,
+			     accel_watch);
+	queue_work(accel_watch_workqueue, &vif_state->accel_work);
+}
+
+
+void netfront_accelerator_add_watch(struct netfront_info *np)
+{
+	int err;
+	
+	/* 
+	 * If old watch exists, e.g. from before suspend/resume,
+	 * remove it now 
+	 */
+	netfront_accelerator_remove_watch(np);
+
+	/* Get a watch on the accelerator plugin */
+	err = xenbus_watch_path2(np->xbdev, np->xbdev->otherend, 
+				 "accel-frontend", 
+				 &np->accel_vif_state.accel_watch,
+				 accel_watch_changed);
+	if (err) {
+		DPRINTK("%s: Failed to register accel watch: %d\n",
+                        __FUNCTION__, err);
+		np->accel_vif_state.accel_watch.node = NULL;
+        }
+}
+
+
+static void 
+netfront_accelerator_purge_watch(struct netfront_accel_vif_state *vif_state)
+{
+	flush_workqueue(accel_watch_workqueue);
+
+	/* Clean up any state left from watch */
+	if (vif_state->accel_frontend != NULL) {
+		kfree(vif_state->accel_frontend);
+		vif_state->accel_frontend = NULL;
+	}
+}
+
+
+static
+void netfront_accelerator_remove_watch(struct netfront_info *np)
+{
+	struct netfront_accel_vif_state *vif_state = &np->accel_vif_state;
+
+	/* Get rid of watch on accelerator plugin */
+	if (vif_state->accel_watch.node != NULL) {
+		unregister_xenbus_watch(&vif_state->accel_watch);
+		kfree(vif_state->accel_watch.node);
+		vif_state->accel_watch.node = NULL;
+
+		netfront_accelerator_purge_watch(vif_state);
+	}	
+}
+
+
+/* 
+ * Initialise the accel_vif_state field in the netfront state
+ */ 
+void init_accelerator_vif(struct netfront_info *np,
+			  struct xenbus_device *dev)
+{
+	np->accelerator = NULL;
+
+	/* It's assumed that these things don't change */
+	np->accel_vif_state.np = np;
+	np->accel_vif_state.dev = dev;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	INIT_WORK(&np->accel_vif_state.accel_work, accel_watch_work);
+#else
+	INIT_WORK(&np->accel_vif_state.accel_work, accel_watch_work, 
+		  &np->accel_vif_state);
+#endif
+}
+
+
+/*
+ * Compare a frontend description string against an accelerator to see
+ * if they match.  Would ultimately be nice to replace the string with
+ * a unique numeric identifier for each accelerator.
+ */
+static int match_accelerator(const char *frontend, 
+			     struct netfront_accelerator *accelerator)
+{
+	return strcmp(frontend, accelerator->frontend) == 0;
+}
+
+
+/* 
+ * Add a frontend vif to the list of vifs that is using a netfront
+ * accelerator plugin module.  Must be called with the accelerator
+ * mutex held.
+ */
+static void add_accelerator_vif(struct netfront_accelerator *accelerator,
+				struct netfront_info *np)
+{
+	if (np->accelerator == NULL) {
+		np->accelerator = accelerator;
+		
+		list_add(&np->accel_vif_state.link, &accelerator->vif_states);
+	} else {
+		/* 
+		 * May get here legitimately if suspend_cancel is
+		 * called, but in that case configuration should not
+		 * have changed
+		 */
+		BUG_ON(np->accelerator != accelerator);
+	}
+}
+
+
+/*
+ * Initialise the state to track an accelerator plugin module.  
+ * 
+ * Must be called with the accelerator mutex held.
+ */ 
+static int init_accelerator(const char *frontend, 
+			    struct netfront_accelerator **result,
+			    struct netfront_accel_hooks *hooks)
+{
+	struct netfront_accelerator *accelerator = 
+		kmalloc(sizeof(struct netfront_accelerator), GFP_KERNEL);
+	int frontend_len;
+
+	if (!accelerator) {
+		DPRINTK("no memory for accelerator\n");
+		return -ENOMEM;
+	}
+
+	frontend_len = strlen(frontend) + 1;
+	accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
+	if (!accelerator->frontend) {
+		DPRINTK("no memory for accelerator\n");
+		kfree(accelerator);
+		return -ENOMEM;
+	}
+	strlcpy(accelerator->frontend, frontend, frontend_len);
+	
+	INIT_LIST_HEAD(&accelerator->vif_states);
+	spin_lock_init(&accelerator->vif_states_lock);
+
+	accelerator->hooks = hooks;
+
+	list_add(&accelerator->link, &accelerators_list);
+
+	*result = accelerator;
+
+	return 0;
+}					
+
+
+/* 
+ * Modify the hooks stored in the per-vif state to match that in the
+ * netfront accelerator's state.
+ * 
+ * Takes the vif_states_lock spinlock and may sleep.
+ */
+static void 
+accelerator_set_vif_state_hooks(struct netfront_accel_vif_state *vif_state)
+{
+	struct netfront_accelerator *accelerator;
+	unsigned long flags;
+
+	DPRINTK("%p\n",vif_state);
+
+	/* Make sure there are no data path operations going on */
+	napi_disable(&vif_state->np->napi);
+	netif_tx_lock_bh(vif_state->np->netdev);
+
+	accelerator = vif_state->np->accelerator;
+	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+	vif_state->hooks = accelerator->hooks;
+	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+
+	netif_tx_unlock_bh(vif_state->np->netdev);
+	napi_enable(&vif_state->np->napi);
+}
+
+
+/* 
+ * Must be called with the accelerator mutex held.  Takes the
+ * vif_states_lock spinlock.
+ */
+static void accelerator_probe_new_vif(struct netfront_info *np,
+				      struct xenbus_device *dev, 
+				      struct netfront_accelerator *accelerator)
+{
+	struct netfront_accel_hooks *hooks;
+
+	DPRINTK("\n");
+
+	/* Include this frontend device on the accelerator's list */
+	add_accelerator_vif(accelerator, np);
+	
+	hooks = accelerator->hooks;
+	
+	if (hooks && hooks->new_device(np->netdev, dev) == 0)
+		accelerator_set_vif_state_hooks(&np->accel_vif_state);
+
+	return;
+}
+
+
+/*  
+ * Request that a particular netfront accelerator plugin is loaded.
+ * Usually called as a result of the vif configuration specifying
+ * which one to use.
+ *
+ * Must be called with accelerator_mutex held.  Takes the
+ * vif_states_lock spinlock.
+ */
+static int netfront_load_accelerator(struct netfront_info *np, 
+				     struct xenbus_device *dev, 
+				     const char *frontend)
+{
+	struct netfront_accelerator *accelerator;
+	int rc = 0;
+
+	DPRINTK(" %s\n", frontend);
+
+	/* 
+	 * Look at list of loaded accelerators to see if the requested
+	 * one is already there 
+	 */
+	list_for_each_entry(accelerator, &accelerators_list, link) {
+		if (match_accelerator(frontend, accelerator)) {
+			accelerator_probe_new_vif(np, dev, accelerator);
+			return 0;
+		}
+	}
+
+	/* Couldn't find it, so create a new one and load the module */
+	if ((rc = init_accelerator(frontend, &accelerator, NULL)) < 0) {
+		return rc;
+	}
+
+	/* Include this frontend device on the accelerator's list */
+	add_accelerator_vif(accelerator, np);
+
+	return rc;
+}
+
+
+/*
+ * Go through all the netfront vifs and see if they have requested
+ * this accelerator.  Notify the accelerator plugin of the relevant
+ * device if so.  Called when an accelerator plugin module is first
+ * loaded and connects to netfront.
+ *
+ * Must be called with accelerator_mutex held.  Takes the
+ * vif_states_lock spinlock.
+ */
+static void 
+accelerator_probe_vifs(struct netfront_accelerator *accelerator,
+		       struct netfront_accel_hooks *hooks)
+{
+	struct netfront_accel_vif_state *vif_state, *tmp;
+
+	DPRINTK("%p\n", accelerator);
+
+	/* 
+	 * Store the hooks for future calls to probe a new device, and
+	 * to wire into the vif_state once the accelerator plugin is
+	 * ready to accelerate each vif
+	 */
+	BUG_ON(hooks == NULL);
+	accelerator->hooks = hooks;
+
+	/* Holds accelerator_mutex to iterate list */
+	list_for_each_entry_safe(vif_state, tmp, &accelerator->vif_states,
+				 link) {
+		struct netfront_info *np = vif_state->np;
+		
+		if (hooks->new_device(np->netdev, vif_state->dev) == 0)
+			accelerator_set_vif_state_hooks(vif_state);
+	}
+}
+
+
+/* 
+ * Called by the netfront accelerator plugin module when it has
+ * loaded.
+ *
+ * Takes the accelerator_mutex and vif_states_lock spinlock.
+ */
+int netfront_accelerator_loaded(int version, const char *frontend, 
+				struct netfront_accel_hooks *hooks)
+{
+	struct netfront_accelerator *accelerator;
+
+	if (is_initial_xendomain())
+		return -EINVAL;
+
+	if (version != NETFRONT_ACCEL_VERSION) {
+		if (version > NETFRONT_ACCEL_VERSION) {
+			/* Caller has higher version number, leave it
+			   up to them to decide whether to continue.
+			   They can re-call with a lower number if
+			   they're happy to be compatible with us */
+			return NETFRONT_ACCEL_VERSION;
+		} else {
+			/* We have a more recent version than caller.
+			   Currently reject, but may in future be able
+			   to be backwardly compatible */
+			return -EPROTO;
+		}
+	}
+
+	mutex_lock(&accelerator_mutex);
+
+	/* 
+	 * Look through list of accelerators to see if it has already
+	 * been requested
+	 */
+	list_for_each_entry(accelerator, &accelerators_list, link) {
+		if (match_accelerator(frontend, accelerator)) {
+			accelerator_probe_vifs(accelerator, hooks);
+			goto out;
+		}
+	}
+
+	/*
+	 * If it wasn't in the list, add it now so that when it is
+	 * requested the caller will find it
+	 */
+	DPRINTK("Couldn't find matching accelerator (%s)\n",
+		frontend);
+
+	init_accelerator(frontend, &accelerator, hooks);
+
+ out:
+	mutex_unlock(&accelerator_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(netfront_accelerator_loaded);
+
+
+/* 
+ * Remove the hooks from a single vif state.
+ * 
+ * Takes the vif_states_lock spinlock and may sleep.
+ */
+static void 
+accelerator_remove_single_hook(struct netfront_accelerator *accelerator,
+			       struct netfront_accel_vif_state *vif_state)
+{
+	unsigned long flags;
+
+	/* Make sure there are no data path operations going on */
+	napi_disable(&vif_state->np->napi);
+	netif_tx_lock_bh(vif_state->np->netdev);
+
+	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+
+	/* 
+	 * Remove the hooks, but leave the vif_state on the
+	 * accelerator's list as that signifies this vif is
+	 * interested in using that accelerator if it becomes
+	 * available again
+	 */
+	vif_state->hooks = NULL;
+	
+	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+
+	netif_tx_unlock_bh(vif_state->np->netdev);
+	napi_enable(&vif_state->np->napi);
+}
+
+
+/* 
+ * Safely remove the accelerator function hooks from a netfront state.
+ * 
+ * Must be called with the accelerator mutex held.  Takes the
+ * vif_states_lock spinlock.
+ */
+static void accelerator_remove_hooks(struct netfront_accelerator *accelerator)
+{
+	struct netfront_accel_vif_state *vif_state, *tmp;
+	unsigned long flags;
+
+	/* Mutex is held to iterate list */
+	list_for_each_entry_safe(vif_state, tmp,
+				 &accelerator->vif_states,
+				 link) {
+		if(vif_state->hooks) {
+			spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+
+			/* Last chance to get statistics from the accelerator */
+			vif_state->hooks->get_stats(vif_state->np->netdev,
+						    &vif_state->np->stats);
+
+			spin_unlock_irqrestore(&accelerator->vif_states_lock,
+					       flags);
+
+			accelerator_remove_single_hook(accelerator, vif_state);
+
+			accelerator->hooks->remove(vif_state->dev);
+		}
+	}
+	
+	accelerator->hooks = NULL;
+}
+
+
+/* 
+ * Called by a netfront accelerator when it is unloaded.  This safely
+ * removes the hooks into the plugin and blocks until all devices have
+ * finished using it, so on return it is safe to unload.
+ *
+ * Takes the accelerator mutex, and vif_states_lock spinlock.
+ */
+void netfront_accelerator_stop(const char *frontend)
+{
+	struct netfront_accelerator *accelerator;
+
+	mutex_lock(&accelerator_mutex);
+
+	list_for_each_entry(accelerator, &accelerators_list, link) {
+		if (match_accelerator(frontend, accelerator)) {
+			accelerator_remove_hooks(accelerator);
+			goto out;
+		}
+	}
+ out:
+	mutex_unlock(&accelerator_mutex);
+}
+EXPORT_SYMBOL_GPL(netfront_accelerator_stop);
+
+
+/* 
+ * Helper for call_remove and do_suspend
+ * 
+ * Must be called with the accelerator mutex held.  Takes the
+ * vif_states_lock spinlock.
+ */
+static int do_remove(struct netfront_info *np, struct xenbus_device *dev)
+{
+	struct netfront_accelerator *accelerator = np->accelerator;
+	unsigned long flags;
+ 	int rc = 0;
+ 
+	if (np->accel_vif_state.hooks) {
+		spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+
+		/* Last chance to get statistics from the accelerator */
+		np->accel_vif_state.hooks->get_stats(np->netdev, &np->stats);
+
+		spin_unlock_irqrestore(&accelerator->vif_states_lock, 
+				       flags);
+
+ 		/* 
+ 		 * Try and do the opposite of accelerator_probe_new_vif
+ 		 * to ensure there's no state pointing back at the 
+ 		 * netdev 
+ 		 */
+		accelerator_remove_single_hook(accelerator, 
+ 					       &np->accel_vif_state);
+
+		rc = accelerator->hooks->remove(dev);
+	}
+ 
+ 	return rc;
+}
+
+
+/*
+ * Must be called with the accelerator mutex held.  Takes the
+ * vif_states_lock spinlock
+ */
+static int netfront_remove_accelerator(struct netfront_info *np,
+				       struct xenbus_device *dev)
+{
+	struct netfront_accelerator *accelerator;
+ 	struct netfront_accel_vif_state *tmp_vif_state;
+	int rc = 0; 
+
+ 	/* Check that we've got a device that was accelerated */
+ 	if (np->accelerator == NULL)
+		return rc;
+
+	accelerator = np->accelerator;
+
+	list_for_each_entry(tmp_vif_state, &accelerator->vif_states,
+			    link) {
+		if (tmp_vif_state == &np->accel_vif_state) {
+			list_del(&np->accel_vif_state.link);
+			break;
+		}
+	}
+
+	rc = do_remove(np, dev);
+
+	np->accelerator = NULL;
+
+	return rc;
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the accelerator mutex and the
+ * vif_states_lock spinlock.
+ */
+int netfront_accelerator_call_remove(struct netfront_info *np,
+				     struct xenbus_device *dev)
+{
+	int rc;
+	netfront_accelerator_remove_watch(np);
+	mutex_lock(&accelerator_mutex);
+	rc = netfront_remove_accelerator(np, dev);
+	mutex_unlock(&accelerator_mutex);
+	return rc;
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the accelerator mutex and the
+ * vif_states_lock spinlock.
+ */
+int netfront_accelerator_suspend(struct netfront_info *np,
+ 				 struct xenbus_device *dev)
+{
+	int rc = 0;
+	
+	mutex_lock(&accelerator_mutex);
+
+ 	/* Check that we've got a device that was accelerated */
+ 	if (np->accelerator == NULL)
+		goto out;
+
+	/* 
+	 * Call the remove accelerator hook, but leave the vif_state
+	 * on the accelerator's list in case there is a suspend_cancel.
+	 */
+	rc = do_remove(np, dev);
+ out:
+	mutex_unlock(&accelerator_mutex);
+	return rc;
+}
+  
+  
+int netfront_accelerator_suspend_cancel(struct netfront_info *np,
+ 					struct xenbus_device *dev)
+{
+	netfront_accelerator_purge_watch(&np->accel_vif_state);
+
+	/* 
+	 * Gratuitously fire the watch handler to reinstate the
+	 * configured accelerator
+	 */
+	if (dev->state == XenbusStateConnected)
+		queue_work(accel_watch_workqueue, 
+			   &np->accel_vif_state.accel_work);
+
+	return 0;
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the accelerator mutex
+ */
+void netfront_accelerator_resume(struct netfront_info *np,
+ 				 struct xenbus_device *dev)
+{
+ 	struct netfront_accel_vif_state *accel_vif_state = NULL;
+
+ 	mutex_lock(&accelerator_mutex);
+
+	/* Check that we've got a device that was accelerated */
+ 	if(np->accelerator == NULL)
+		goto out;
+
+ 	/* Find the vif_state from the accelerator's list */
+ 	list_for_each_entry(accel_vif_state, &np->accelerator->vif_states, 
+ 			    link) {
+ 		if (accel_vif_state->dev == dev) {
+ 			BUG_ON(accel_vif_state != &np->accel_vif_state);
+ 
+ 			/* 
+ 			 * Remove it from the accelerator's list so
+ 			 * state is consistent for probing new vifs
+ 			 * when they get connected
+ 			 */
+ 			list_del(&accel_vif_state->link);
+ 			np->accelerator = NULL;
+
+			break;
+ 		}
+ 	}
+
+ out:
+	mutex_unlock(&accelerator_mutex);
+	return;
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the vif_states_lock spinlock
+ */
+int netfront_check_accelerator_queue_ready(struct net_device *dev,
+					   struct netfront_info *np)
+{
+	struct netfront_accelerator *accelerator;
+	int rc = 1;
+	unsigned long flags;
+
+	accelerator = np->accelerator;
+
+	/* Call the check_ready accelerator hook. */ 
+	if (np->accel_vif_state.hooks && accelerator) {
+		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
+		if (np->accel_vif_state.hooks &&
+		    np->accelerator == accelerator)
+			rc = np->accel_vif_state.hooks->check_ready(dev);
+		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+	}
+
+	return rc;
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the vif_states_lock spinlock
+ */
+void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
+					     struct net_device *dev)
+{
+	struct netfront_accelerator *accelerator;
+	unsigned long flags;
+
+	accelerator = np->accelerator;
+
+	/* Call the stop_napi_interrupts accelerator hook. */
+	if (np->accel_vif_state.hooks && accelerator != NULL) {
+		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
+		if (np->accel_vif_state.hooks &&
+		    np->accelerator == accelerator)
+ 			np->accel_vif_state.hooks->stop_napi_irq(dev);
+		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+	}
+}
+
+
+/*
+ * No lock pre-requisites.  Takes the vif_states_lock spinlock
+ */
+int netfront_accelerator_call_get_stats(struct netfront_info *np,
+					struct net_device *dev)
+{
+	struct netfront_accelerator *accelerator;
+	unsigned long flags;
+	int rc = 0;
+
+	accelerator = np->accelerator;
+
+	/* Call the get_stats accelerator hook. */
+	if (np->accel_vif_state.hooks && accelerator != NULL) {
+		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
+		if (np->accel_vif_state.hooks && 
+		    np->accelerator == accelerator)
+ 			rc = np->accel_vif_state.hooks->get_stats(dev,
+								  &np->stats);
+		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+	}
+	return rc;
+}
+
--- linux-ec2-2.6.32.orig/drivers/xen/netfront/netfront.c
+++ linux-ec2-2.6.32/drivers/xen/netfront/netfront.c
@@ -0,0 +1,2185 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ * Copyright (c) 2005, 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.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/ethtool.h>
+#include <linux/in.h>
+#include <linux/if_ether.h>
+#include <linux/io.h>
+#include <linux/moduleparam.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <net/route.h>
+#include <asm/uaccess.h>
+#include <xen/evtchn.h>
+#include <xen/xenbus.h>
+#include <xen/interface/io/netif.h>
+#include <xen/interface/memory.h>
+#include <xen/balloon.h>
+#include <asm/page.h>
+#include <asm/maddr.h>
+#include <asm/uaccess.h>
+#include <xen/interface/grant_table.h>
+#include <xen/gnttab.h>
+
+struct netfront_cb {
+	struct page *page;
+	unsigned offset;
+};
+
+#define NETFRONT_SKB_CB(skb)	((struct netfront_cb *)((skb)->cb))
+
+#include "netfront.h"
+
+/*
+ * Mutually-exclusive module options to select receive data path:
+ *  rx_copy : Packets are copied by network backend into local memory
+ *  rx_flip : Page containing packet data is transferred to our ownership
+ * For fully-virtualised guests there is no option - copying must be used.
+ * For paravirtualised guests, flipping is the default.
+ */
+#ifdef CONFIG_XEN
+static int MODPARM_rx_copy = 0;
+module_param_named(rx_copy, MODPARM_rx_copy, bool, 0);
+MODULE_PARM_DESC(rx_copy, "Copy packets from network card (rather than flip)");
+static int MODPARM_rx_flip = 0;
+module_param_named(rx_flip, MODPARM_rx_flip, bool, 0);
+MODULE_PARM_DESC(rx_flip, "Flip packets from network card (rather than copy)");
+#else
+static const int MODPARM_rx_copy = 1;
+static const int MODPARM_rx_flip = 0;
+#endif
+
+#define RX_COPY_THRESHOLD 256
+
+/* If we don't have GSO, fake things up so that we never try to use it. */
+#if defined(NETIF_F_GSO)
+#define HAVE_GSO			1
+#define HAVE_TSO			1 /* TSO is a subset of GSO */
+#define HAVE_CSUM_OFFLOAD		1
+static inline void dev_disable_gso_features(struct net_device *dev)
+{
+	/* Turn off all GSO bits except ROBUST. */
+	dev->features &= ~NETIF_F_GSO_MASK;
+	dev->features |= NETIF_F_GSO_ROBUST;
+}
+#elif defined(NETIF_F_TSO)
+#define HAVE_GSO		       0
+#define HAVE_TSO                       1
+
+/* Some older kernels cannot cope with incorrect checksums,
+ * particularly in netfilter. I'm not sure there is 100% correlation
+ * with the presence of NETIF_F_TSO but it appears to be a good first
+ * approximiation.
+ */
+#define HAVE_CSUM_OFFLOAD              0
+
+#define gso_size tso_size
+#define gso_segs tso_segs
+static inline void dev_disable_gso_features(struct net_device *dev)
+{
+       /* Turn off all TSO bits. */
+       dev->features &= ~NETIF_F_TSO;
+}
+static inline int skb_is_gso(const struct sk_buff *skb)
+{
+        return skb_shinfo(skb)->tso_size;
+}
+static inline int skb_gso_ok(struct sk_buff *skb, int features)
+{
+        return (features & NETIF_F_TSO);
+}
+
+static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+{
+        return skb_is_gso(skb) &&
+               (!skb_gso_ok(skb, dev->features) ||
+                unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+}
+#else
+#define HAVE_GSO			0
+#define HAVE_TSO			0
+#define HAVE_CSUM_OFFLOAD		0
+#define netif_needs_gso(dev, skb)	0
+#define dev_disable_gso_features(dev)	((void)0)
+#define ethtool_op_set_tso(dev, data)	(-ENOSYS)
+#endif
+
+#define GRANT_INVALID_REF	0
+
+struct netfront_rx_info {
+	struct netif_rx_response rx;
+	struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
+};
+
+/*
+ * Implement our own carrier flag: the network stack's version causes delays
+ * when the carrier is re-enabled (in particular, dev_activate() may not
+ * immediately be called, which can cause packet loss).
+ */
+#define netfront_carrier_on(netif)	((netif)->carrier = 1)
+#define netfront_carrier_off(netif)	((netif)->carrier = 0)
+#define netfront_carrier_ok(netif)	((netif)->carrier)
+
+/*
+ * Access macros for acquiring freeing slots in tx_skbs[].
+ */
+
+static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id)
+{
+	list[id] = list[0];
+	list[0]  = (void *)(unsigned long)id;
+}
+
+static inline unsigned short get_id_from_freelist(struct sk_buff **list)
+{
+	unsigned int id = (unsigned int)(unsigned long)list[0];
+	list[0] = list[id];
+	return id;
+}
+
+static inline int xennet_rxidx(RING_IDX idx)
+{
+	return idx & (NET_RX_RING_SIZE - 1);
+}
+
+static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np,
+						RING_IDX ri)
+{
+	int i = xennet_rxidx(ri);
+	struct sk_buff *skb = np->rx_skbs[i];
+	np->rx_skbs[i] = NULL;
+	return skb;
+}
+
+static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np,
+					    RING_IDX ri)
+{
+	int i = xennet_rxidx(ri);
+	grant_ref_t ref = np->grant_rx_ref[i];
+	np->grant_rx_ref[i] = GRANT_INVALID_REF;
+	return ref;
+}
+
+#define DPRINTK(fmt, args...)				\
+	pr_debug("netfront (%s:%d) " fmt,		\
+		 __FUNCTION__, __LINE__, ##args)
+#define IPRINTK(fmt, args...)				\
+	printk(KERN_INFO "netfront: " fmt, ##args)
+#define WPRINTK(fmt, args...)				\
+	printk(KERN_WARNING "netfront: " fmt, ##args)
+
+static int setup_device(struct xenbus_device *, struct netfront_info *);
+static struct net_device *create_netdev(struct xenbus_device *);
+
+static void end_access(int, void *);
+static void netif_disconnect_backend(struct netfront_info *);
+
+static int network_connect(struct net_device *);
+static void network_tx_buf_gc(struct net_device *);
+static void network_alloc_rx_buffers(struct net_device *);
+
+static irqreturn_t netif_int(int irq, void *dev_id);
+
+#ifdef CONFIG_SYSFS
+static int xennet_sysfs_addif(struct net_device *netdev);
+static void xennet_sysfs_delif(struct net_device *netdev);
+#else /* !CONFIG_SYSFS */
+#define xennet_sysfs_addif(dev) (0)
+#define xennet_sysfs_delif(dev) do { } while(0)
+#endif
+
+static inline int xennet_can_sg(struct net_device *dev)
+{
+	return dev->features & NETIF_F_SG;
+}
+
+/*
+ * Work around net.ipv4.conf.*.arp_notify no being enabled by default.
+ */
+static void __devinit netfront_enable_arp_notify(struct netfront_info *info)
+{
+#ifdef CONFIG_INET
+	struct in_device *in_dev;
+
+	rtnl_lock();
+	in_dev = __in_dev_get_rtnl(info->netdev);
+	if (in_dev && !IN_DEV_CONF_GET(in_dev, ARP_NOTIFY))
+		IN_DEV_CONF_SET(in_dev, ARP_NOTIFY, 1);
+	rtnl_unlock();
+	if (!in_dev)
+		printk(KERN_WARNING "Cannot enable ARP notification on %s\n",
+		       info->xbdev->nodename);
+#endif
+}
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures and the ring buffers for communication with the backend, and
+ * inform the backend of the appropriate details for those.
+ */
+static int __devinit netfront_probe(struct xenbus_device *dev,
+				    const struct xenbus_device_id *id)
+{
+	int err;
+	struct net_device *netdev;
+	struct netfront_info *info;
+
+	netdev = create_netdev(dev);
+	if (IS_ERR(netdev)) {
+		err = PTR_ERR(netdev);
+		xenbus_dev_fatal(dev, err, "creating netdev");
+		return err;
+	}
+
+	info = netdev_priv(netdev);
+	dev_set_drvdata(&dev->dev, info);
+
+	err = register_netdev(info->netdev);
+	if (err) {
+		printk(KERN_WARNING "%s: register_netdev err=%d\n",
+		       __FUNCTION__, err);
+		goto fail;
+	}
+
+	netfront_enable_arp_notify(info);
+
+	err = xennet_sysfs_addif(info->netdev);
+	if (err) {
+		unregister_netdev(info->netdev);
+		printk(KERN_WARNING "%s: add sysfs failed err=%d\n",
+		       __FUNCTION__, err);
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	free_netdev(netdev);
+	dev_set_drvdata(&dev->dev, NULL);
+	return err;
+}
+
+static int __devexit netfront_remove(struct xenbus_device *dev)
+{
+	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+
+	DPRINTK("%s\n", dev->nodename);
+
+	netfront_accelerator_call_remove(info, dev);
+
+	netif_disconnect_backend(info);
+
+	del_timer_sync(&info->rx_refill_timer);
+
+	xennet_sysfs_delif(info->netdev);
+
+	unregister_netdev(info->netdev);
+
+	free_netdev(info->netdev);
+
+	return 0;
+}
+
+
+static int netfront_suspend(struct xenbus_device *dev)
+{
+	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+	return netfront_accelerator_suspend(info, dev);
+}
+
+
+static int netfront_suspend_cancel(struct xenbus_device *dev)
+{
+	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+	return netfront_accelerator_suspend_cancel(info, dev);
+}
+
+
+/**
+ * We are reconnecting to the backend, due to a suspend/resume, or a backend
+ * driver restart.  We tear down our netif structure and recreate it, but
+ * leave the device-layer structures intact so that this is transparent to the
+ * rest of the kernel.
+ */
+static int netfront_resume(struct xenbus_device *dev)
+{
+	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+
+	DPRINTK("%s\n", dev->nodename);
+
+	netfront_accelerator_resume(info, dev);
+
+	netif_disconnect_backend(info);
+	return 0;
+}
+
+static int 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;
+}
+
+/* Common code used when first setting up, and when resuming. */
+static int talk_to_backend(struct xenbus_device *dev,
+			   struct netfront_info *info)
+{
+	const char *message;
+	struct xenbus_transaction xbt;
+	int err;
+
+	/* 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. */
+	err = setup_device(dev, info);
+	if (err)
+		goto out;
+
+	/* This will load an accelerator if one is configured when the
+	 * watch fires */
+	netfront_accelerator_add_watch(info);
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		goto destroy_ring;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
+			    info->tx_ring_ref);
+	if (err) {
+		message = "writing tx ring-ref";
+		goto abort_transaction;
+	}
+	err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
+			    info->rx_ring_ref);
+	if (err) {
+		message = "writing rx ring-ref";
+		goto abort_transaction;
+	}
+	err = xenbus_printf(xbt, dev->nodename,
+			    "event-channel", "%u",
+			    irq_to_evtchn_port(info->irq));
+	if (err) {
+		message = "writing event-channel";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
+			    info->copying_receiver);
+	if (err) {
+		message = "writing request-rx-copy";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
+	if (err) {
+		message = "writing feature-rx-notify";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-no-csum-offload",
+			    "%d", !HAVE_CSUM_OFFLOAD);
+	if (err) {
+		message = "writing feature-no-csum-offload";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
+	if (err) {
+		message = "writing feature-sg";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d",
+			    HAVE_TSO);
+	if (err) {
+		message = "writing feature-gso-tcpv4";
+		goto abort_transaction;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err) {
+		if (err == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto destroy_ring;
+	}
+
+	return 0;
+
+ abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+ destroy_ring:
+	netfront_accelerator_call_remove(info, dev);
+	netif_disconnect_backend(info);
+ out:
+	return err;
+}
+
+static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
+{
+	struct netif_tx_sring *txs;
+	struct netif_rx_sring *rxs;
+	int err;
+	struct net_device *netdev = info->netdev;
+
+	info->tx_ring_ref = GRANT_INVALID_REF;
+	info->rx_ring_ref = GRANT_INVALID_REF;
+	info->rx.sring = NULL;
+	info->tx.sring = NULL;
+	info->irq = 0;
+
+	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");
+		goto fail;
+	}
+	SHARED_RING_INIT(txs);
+	FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(txs));
+	if (err < 0) {
+		free_page((unsigned long)txs);
+		goto fail;
+	}
+	info->tx_ring_ref = err;
+
+	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");
+		goto fail;
+	}
+	SHARED_RING_INIT(rxs);
+	FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
+	if (err < 0) {
+		free_page((unsigned long)rxs);
+		goto fail;
+	}
+	info->rx_ring_ref = err;
+
+	memcpy(netdev->dev_addr, info->mac, ETH_ALEN);
+
+	err = bind_listening_port_to_irqhandler(
+		dev->otherend_id, netif_int, IRQF_SAMPLE_RANDOM, netdev->name,
+		netdev);
+	if (err < 0)
+		goto fail;
+	info->irq = err;
+
+	return 0;
+
+ fail:
+	return err;
+}
+
+/**
+ * Callback received when the backend's state changes.
+ */
+static void backend_changed(struct xenbus_device *dev,
+			    enum xenbus_state backend_state)
+{
+	struct netfront_info *np = dev_get_drvdata(&dev->dev);
+	struct net_device *netdev = np->netdev;
+
+	DPRINTK("%s\n", xenbus_strstate(backend_state));
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateConnected:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+		if (dev->state != XenbusStateInitialising)
+			break;
+		if (network_connect(netdev) != 0)
+			break;
+		xenbus_switch_state(dev, XenbusStateConnected);
+		netif_notify_peers(netdev);
+		break;
+
+	case XenbusStateClosing:
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static inline int netfront_tx_slot_available(struct netfront_info *np)
+{
+	return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
+		(TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
+}
+
+
+static inline void network_maybe_wake_tx(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+
+	if (unlikely(netif_queue_stopped(dev)) &&
+	    netfront_tx_slot_available(np) &&
+	    likely(netif_running(dev)) &&
+	    netfront_check_accelerator_queue_ready(dev, np))
+		netif_wake_queue(dev);
+}
+
+
+int netfront_check_queue_ready(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+
+	return unlikely(netif_queue_stopped(dev)) &&
+		netfront_tx_slot_available(np) &&
+		likely(netif_running(dev));
+}
+EXPORT_SYMBOL(netfront_check_queue_ready);
+
+
+static int network_open(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+
+	memset(&np->stats, 0, sizeof(np->stats));
+	napi_enable(&np->napi);
+
+	spin_lock_bh(&np->rx_lock);
+	if (netfront_carrier_ok(np)) {
+		network_alloc_rx_buffers(dev);
+		np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
+		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
+			netfront_accelerator_call_stop_napi_irq(np, dev);
+
+			napi_schedule(&np->napi);
+		}
+	}
+	spin_unlock_bh(&np->rx_lock);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static void network_tx_buf_gc(struct net_device *dev)
+{
+	RING_IDX cons, prod;
+	unsigned short id;
+	struct netfront_info *np = netdev_priv(dev);
+	struct sk_buff *skb;
+
+	BUG_ON(!netfront_carrier_ok(np));
+
+	do {
+		prod = np->tx.sring->rsp_prod;
+		rmb(); /* Ensure we see responses up to 'rp'. */
+
+		for (cons = np->tx.rsp_cons; cons != prod; cons++) {
+			struct netif_tx_response *txrsp;
+
+			txrsp = RING_GET_RESPONSE(&np->tx, cons);
+			if (txrsp->status == NETIF_RSP_NULL)
+				continue;
+
+			id  = txrsp->id;
+			skb = np->tx_skbs[id];
+			if (unlikely(gnttab_query_foreign_access(
+				np->grant_tx_ref[id]) != 0)) {
+				printk(KERN_ALERT "network_tx_buf_gc: warning "
+				       "-- grant still in use by backend "
+				       "domain.\n");
+				BUG();
+			}
+			gnttab_end_foreign_access_ref(np->grant_tx_ref[id]);
+			gnttab_release_grant_reference(
+				&np->gref_tx_head, np->grant_tx_ref[id]);
+			np->grant_tx_ref[id] = GRANT_INVALID_REF;
+			add_id_to_freelist(np->tx_skbs, id);
+			dev_kfree_skb_irq(skb);
+		}
+
+		np->tx.rsp_cons = prod;
+
+		/*
+		 * Set a new event, then check for race with update of tx_cons.
+		 * Note that it is essential to schedule a callback, no matter
+		 * how few buffers are pending. Even if there is space in the
+		 * transmit ring, higher layers may be blocked because too much
+		 * data is outstanding: in such cases notification from Xen is
+		 * likely to be the only kick that we'll get.
+		 */
+		np->tx.sring->rsp_event =
+			prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
+		mb();
+	} while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
+
+	network_maybe_wake_tx(dev);
+}
+
+static void rx_refill_timeout(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct netfront_info *np = netdev_priv(dev);
+
+	netfront_accelerator_call_stop_napi_irq(np, dev);
+
+	napi_schedule(&np->napi);
+}
+
+static void network_alloc_rx_buffers(struct net_device *dev)
+{
+	unsigned short id;
+	struct netfront_info *np = netdev_priv(dev);
+	struct sk_buff *skb;
+	struct page *page;
+	int i, batch_target, notify;
+	RING_IDX req_prod = np->rx.req_prod_pvt;
+	struct xen_memory_reservation reservation;
+	grant_ref_t ref;
+ 	unsigned long pfn;
+ 	void *vaddr;
+	int nr_flips;
+	netif_rx_request_t *req;
+
+	if (unlikely(!netfront_carrier_ok(np)))
+		return;
+
+	/*
+	 * Allocate skbuffs greedily, even though we batch updates to the
+	 * receive ring. This creates a less bursty demand on the memory
+	 * allocator, so should reduce the chance of failed allocation requests
+	 * both for ourself and for other kernel subsystems.
+	 */
+	batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
+	for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
+		/*
+		 * Allocate an skb and a page. Do not use __dev_alloc_skb as
+		 * that will allocate page-sized buffers which is not
+		 * necessary here.
+		 * 16 bytes added as necessary headroom for netif_receive_skb.
+		 */
+		skb = alloc_skb(RX_COPY_THRESHOLD + 16 + NET_IP_ALIGN,
+				GFP_ATOMIC | __GFP_NOWARN);
+		if (unlikely(!skb))
+			goto no_skb;
+
+		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+		if (!page) {
+			kfree_skb(skb);
+no_skb:
+			/* Any skbuffs queued for refill? Force them out. */
+			if (i != 0)
+				goto refill;
+			/* Could not allocate any skbuffs. Try again later. */
+			mod_timer(&np->rx_refill_timer,
+				  jiffies + (HZ/10));
+			break;
+		}
+
+		skb_reserve(skb, 16 + NET_IP_ALIGN); /* mimic dev_alloc_skb() */
+		skb_shinfo(skb)->frags[0].page = page;
+		skb_shinfo(skb)->nr_frags = 1;
+		__skb_queue_tail(&np->rx_batch, skb);
+	}
+
+	/* Is the batch large enough to be worthwhile? */
+	if (i < (np->rx_target/2)) {
+		if (req_prod > np->rx.sring->req_prod)
+			goto push;
+		return;
+	}
+
+	/* Adjust our fill target if we risked running out of buffers. */
+	if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
+	    ((np->rx_target *= 2) > np->rx_max_target))
+		np->rx_target = np->rx_max_target;
+
+ refill:
+	for (nr_flips = i = 0; ; i++) {
+		if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
+			break;
+
+		skb->dev = dev;
+
+		id = xennet_rxidx(req_prod + i);
+
+		BUG_ON(np->rx_skbs[id]);
+		np->rx_skbs[id] = skb;
+
+		ref = gnttab_claim_grant_reference(&np->gref_rx_head);
+		BUG_ON((signed short)ref < 0);
+		np->grant_rx_ref[id] = ref;
+
+		pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
+		vaddr = page_address(skb_shinfo(skb)->frags[0].page);
+
+		req = RING_GET_REQUEST(&np->rx, req_prod + i);
+		if (!np->copying_receiver) {
+			gnttab_grant_foreign_transfer_ref(ref,
+							  np->xbdev->otherend_id,
+							  pfn);
+			np->rx_pfn_array[nr_flips] = pfn_to_mfn(pfn);
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				/* Remove this page before passing
+				 * back to Xen. */
+				set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+				MULTI_update_va_mapping(np->rx_mcl+i,
+							(unsigned long)vaddr,
+							__pte(0), 0);
+			}
+			nr_flips++;
+		} else {
+			gnttab_grant_foreign_access_ref(ref,
+							np->xbdev->otherend_id,
+							pfn_to_mfn(pfn),
+							0);
+		}
+
+		req->id = id;
+		req->gref = ref;
+	}
+
+	if ( nr_flips != 0 ) {
+		/* Tell the ballon driver what is going on. */
+		balloon_update_driver_allowance(i);
+
+		set_xen_guest_handle(reservation.extent_start,
+				     np->rx_pfn_array);
+		reservation.nr_extents   = nr_flips;
+		reservation.extent_order = 0;
+		reservation.address_bits = 0;
+		reservation.domid        = DOMID_SELF;
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			/* After all PTEs have been zapped, flush the TLB. */
+			np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
+				UVMF_TLB_FLUSH|UVMF_ALL;
+
+			/* Give away a batch of pages. */
+			np->rx_mcl[i].op = __HYPERVISOR_memory_op;
+			np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
+			np->rx_mcl[i].args[1] = (unsigned long)&reservation;
+
+			/* Zap PTEs and give away pages in one big
+			 * multicall. */
+			if (unlikely(HYPERVISOR_multicall(np->rx_mcl, i+1)))
+				BUG();
+
+			/* Check return status of HYPERVISOR_memory_op(). */
+			if (unlikely(np->rx_mcl[i].result != i))
+				panic("Unable to reduce memory reservation\n");
+			while (nr_flips--)
+				BUG_ON(np->rx_mcl[nr_flips].result);
+		} else {
+			if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+						 &reservation) != i)
+				panic("Unable to reduce memory reservation\n");
+		}
+	} else {
+		wmb();
+	}
+
+	/* Above is a suitable barrier to ensure backend will see requests. */
+	np->rx.req_prod_pvt = req_prod + i;
+ push:
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+	if (notify)
+		notify_remote_via_irq(np->irq);
+}
+
+static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
+			      struct netif_tx_request *tx)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	char *data = skb->data;
+	unsigned long mfn;
+	RING_IDX prod = np->tx.req_prod_pvt;
+	int frags = skb_shinfo(skb)->nr_frags;
+	unsigned int offset = offset_in_page(data);
+	unsigned int len = skb_headlen(skb);
+	unsigned int id;
+	grant_ref_t ref;
+	int i;
+
+	while (len > PAGE_SIZE - offset) {
+		tx->size = PAGE_SIZE - offset;
+		tx->flags |= NETTXF_more_data;
+		len -= tx->size;
+		data += tx->size;
+		offset = 0;
+
+		id = get_id_from_freelist(np->tx_skbs);
+		np->tx_skbs[id] = skb_get(skb);
+		tx = RING_GET_REQUEST(&np->tx, prod++);
+		tx->id = id;
+		ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+		BUG_ON((signed short)ref < 0);
+
+		mfn = virt_to_mfn(data);
+		gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+						mfn, GTF_readonly);
+
+		tx->gref = np->grant_tx_ref[id] = ref;
+		tx->offset = offset;
+		tx->size = len;
+		tx->flags = 0;
+	}
+
+	for (i = 0; i < frags; i++) {
+		skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+
+		tx->flags |= NETTXF_more_data;
+
+		id = get_id_from_freelist(np->tx_skbs);
+		np->tx_skbs[id] = skb_get(skb);
+		tx = RING_GET_REQUEST(&np->tx, prod++);
+		tx->id = id;
+		ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+		BUG_ON((signed short)ref < 0);
+
+		mfn = pfn_to_mfn(page_to_pfn(frag->page));
+		gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
+						mfn, GTF_readonly);
+
+		tx->gref = np->grant_tx_ref[id] = ref;
+		tx->offset = frag->page_offset;
+		tx->size = frag->size;
+		tx->flags = 0;
+	}
+
+	np->tx.req_prod_pvt = prod;
+}
+
+static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	unsigned short id;
+	struct netfront_info *np = netdev_priv(dev);
+	struct netif_tx_request *tx;
+	struct netif_extra_info *extra;
+	char *data = skb->data;
+	RING_IDX i;
+	grant_ref_t ref;
+	unsigned long mfn;
+	int notify;
+	int frags = skb_shinfo(skb)->nr_frags;
+	unsigned int offset = offset_in_page(data);
+	unsigned int len = skb_headlen(skb);
+
+	/* Check the fast path, if hooks are available */
+ 	if (np->accel_vif_state.hooks && 
+ 	    np->accel_vif_state.hooks->start_xmit(skb, dev)) { 
+ 		/* Fast path has sent this packet */ 
+ 		return NETDEV_TX_OK;
+ 	} 
+
+	frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
+	if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
+		printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
+		       frags);
+		dump_stack();
+		goto drop;
+	}
+
+	spin_lock_irq(&np->tx_lock);
+
+	if (unlikely(!netfront_carrier_ok(np) ||
+		     (frags > 1 && !xennet_can_sg(dev)) ||
+		     netif_needs_gso(dev, skb))) {
+		spin_unlock_irq(&np->tx_lock);
+		goto drop;
+	}
+
+	i = np->tx.req_prod_pvt;
+
+	id = get_id_from_freelist(np->tx_skbs);
+	np->tx_skbs[id] = skb;
+
+	tx = RING_GET_REQUEST(&np->tx, i);
+
+	tx->id   = id;
+	ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+	BUG_ON((signed short)ref < 0);
+	mfn = virt_to_mfn(data);
+	gnttab_grant_foreign_access_ref(
+		ref, np->xbdev->otherend_id, mfn, GTF_readonly);
+	tx->gref = np->grant_tx_ref[id] = ref;
+	tx->offset = offset;
+	tx->size = len;
+
+	tx->flags = 0;
+	extra = NULL;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
+#ifdef CONFIG_XEN
+	if (skb->proto_data_valid) /* remote but checksummed? */
+		tx->flags |= NETTXF_data_validated;
+#endif
+
+#if HAVE_TSO
+	if (skb_shinfo(skb)->gso_size) {
+		struct netif_extra_info *gso = (struct netif_extra_info *)
+			RING_GET_REQUEST(&np->tx, ++i);
+
+		if (extra)
+			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
+		else
+			tx->flags |= NETTXF_extra_info;
+
+		gso->u.gso.size = skb_shinfo(skb)->gso_size;
+		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+		gso->u.gso.pad = 0;
+		gso->u.gso.features = 0;
+
+		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+		gso->flags = 0;
+		extra = gso;
+	}
+#endif
+
+	np->tx.req_prod_pvt = i + 1;
+
+	xennet_make_frags(skb, dev, tx);
+	tx->size = skb->len;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
+	if (notify)
+		notify_remote_via_irq(np->irq);
+
+	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);
+
+	if (!netfront_tx_slot_available(np))
+		netif_stop_queue(dev);
+
+	spin_unlock_irq(&np->tx_lock);
+
+	return NETDEV_TX_OK;
+
+ drop:
+	np->stats.tx_dropped++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static irqreturn_t netif_int(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct netfront_info *np = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&np->tx_lock, flags);
+
+	if (likely(netfront_carrier_ok(np))) {
+		network_tx_buf_gc(dev);
+		/* Under tx_lock: protects access to rx shared-ring indexes. */
+		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
+			netfront_accelerator_call_stop_napi_irq(np, dev);
+
+			napi_schedule(&np->napi);
+		}
+	}
+
+	spin_unlock_irqrestore(&np->tx_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
+				grant_ref_t ref)
+{
+	int new = xennet_rxidx(np->rx.req_prod_pvt);
+
+	BUG_ON(np->rx_skbs[new]);
+	np->rx_skbs[new] = skb;
+	np->grant_rx_ref[new] = ref;
+	RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new;
+	RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref;
+	np->rx.req_prod_pvt++;
+}
+
+int xennet_get_extras(struct netfront_info *np,
+		      struct netif_extra_info *extras, RING_IDX rp)
+
+{
+	struct netif_extra_info *extra;
+	RING_IDX cons = np->rx.rsp_cons;
+	int err = 0;
+
+	do {
+		struct sk_buff *skb;
+		grant_ref_t ref;
+
+		if (unlikely(cons + 1 == rp)) {
+			if (net_ratelimit())
+				WPRINTK("Missing extra info\n");
+			err = -EBADR;
+			break;
+		}
+
+		extra = (struct netif_extra_info *)
+			RING_GET_RESPONSE(&np->rx, ++cons);
+
+		if (unlikely(!extra->type ||
+			     extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+			if (net_ratelimit())
+				WPRINTK("Invalid extra type: %d\n",
+					extra->type);
+			err = -EINVAL;
+		} else {
+			memcpy(&extras[extra->type - 1], extra,
+			       sizeof(*extra));
+		}
+
+		skb = xennet_get_rx_skb(np, cons);
+		ref = xennet_get_rx_ref(np, cons);
+		xennet_move_rx_slot(np, skb, ref);
+	} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+
+	np->rx.rsp_cons = cons;
+	return err;
+}
+
+static int xennet_get_responses(struct netfront_info *np,
+				struct netfront_rx_info *rinfo, RING_IDX rp,
+				struct sk_buff_head *list,
+				int *pages_flipped_p)
+{
+	int pages_flipped = *pages_flipped_p;
+	struct mmu_update *mmu;
+	struct multicall_entry *mcl;
+	struct netif_rx_response *rx = &rinfo->rx;
+	struct netif_extra_info *extras = rinfo->extras;
+	RING_IDX cons = np->rx.rsp_cons;
+	struct sk_buff *skb = xennet_get_rx_skb(np, cons);
+	grant_ref_t ref = xennet_get_rx_ref(np, cons);
+	int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
+	int frags = 1;
+	int err = 0;
+	unsigned long ret;
+
+	if (rx->flags & NETRXF_extra_info) {
+		err = xennet_get_extras(np, extras, rp);
+		cons = np->rx.rsp_cons;
+	}
+
+	for (;;) {
+		unsigned long mfn;
+
+		if (unlikely(rx->status < 0 ||
+			     rx->offset + rx->status > PAGE_SIZE)) {
+			if (net_ratelimit())
+				WPRINTK("rx->offset: %x, size: %u\n",
+					rx->offset, rx->status);
+			xennet_move_rx_slot(np, skb, ref);
+			err = -EINVAL;
+			goto next;
+		}
+
+		/*
+		 * This definitely indicates a bug, either in this driver or in
+		 * the backend driver. In future this should flag the bad
+		 * situation to the system controller to reboot the backed.
+		 */
+		if (ref == GRANT_INVALID_REF) {
+			if (net_ratelimit())
+				WPRINTK("Bad rx response id %d.\n", rx->id);
+			err = -EINVAL;
+			goto next;
+		}
+
+		if (!np->copying_receiver) {
+			/* Memory pressure, insufficient buffer
+			 * headroom, ... */
+			if (!(mfn = gnttab_end_foreign_transfer_ref(ref))) {
+				if (net_ratelimit())
+					WPRINTK("Unfulfilled rx req "
+						"(id=%d, st=%d).\n",
+						rx->id, rx->status);
+				xennet_move_rx_slot(np, skb, ref);
+				err = -ENOMEM;
+				goto next;
+			}
+
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				/* Remap the page. */
+				struct page *page =
+					skb_shinfo(skb)->frags[0].page;
+				unsigned long pfn = page_to_pfn(page);
+				void *vaddr = page_address(page);
+
+				mcl = np->rx_mcl + pages_flipped;
+				mmu = np->rx_mmu + pages_flipped;
+
+				MULTI_update_va_mapping(mcl,
+							(unsigned long)vaddr,
+							pfn_pte_ma(mfn,
+								   PAGE_KERNEL),
+							0);
+				mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
+					| MMU_MACHPHYS_UPDATE;
+				mmu->val = pfn;
+
+				set_phys_to_machine(pfn, mfn);
+			}
+			pages_flipped++;
+		} else {
+			ret = gnttab_end_foreign_access_ref(ref);
+			BUG_ON(!ret);
+		}
+
+		gnttab_release_grant_reference(&np->gref_rx_head, ref);
+
+		__skb_queue_tail(list, skb);
+
+next:
+		if (!(rx->flags & NETRXF_more_data))
+			break;
+
+		if (cons + frags == rp) {
+			if (net_ratelimit())
+				WPRINTK("Need more frags\n");
+			err = -ENOENT;
+			break;
+		}
+
+		rx = RING_GET_RESPONSE(&np->rx, cons + frags);
+		skb = xennet_get_rx_skb(np, cons + frags);
+		ref = xennet_get_rx_ref(np, cons + frags);
+		frags++;
+	}
+
+	if (unlikely(frags > max)) {
+		if (net_ratelimit())
+			WPRINTK("Too many frags\n");
+		err = -E2BIG;
+	}
+
+	if (unlikely(err))
+		np->rx.rsp_cons = cons + frags;
+
+	*pages_flipped_p = pages_flipped;
+
+	return err;
+}
+
+static RING_IDX xennet_fill_frags(struct netfront_info *np,
+				  struct sk_buff *skb,
+				  struct sk_buff_head *list)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	RING_IDX cons = np->rx.rsp_cons;
+	skb_frag_t *frag = shinfo->frags + nr_frags;
+	struct sk_buff *nskb;
+
+	while ((nskb = __skb_dequeue(list))) {
+		struct netif_rx_response *rx =
+			RING_GET_RESPONSE(&np->rx, ++cons);
+
+		frag->page = skb_shinfo(nskb)->frags[0].page;
+		frag->page_offset = rx->offset;
+		frag->size = rx->status;
+
+		skb->data_len += rx->status;
+
+		skb_shinfo(nskb)->nr_frags = 0;
+		kfree_skb(nskb);
+
+		frag++;
+		nr_frags++;
+	}
+
+	shinfo->nr_frags = nr_frags;
+	return cons;
+}
+
+static int xennet_set_skb_gso(struct sk_buff *skb,
+			      struct netif_extra_info *gso)
+{
+	if (!gso->u.gso.size) {
+		if (net_ratelimit())
+			WPRINTK("GSO size must not be zero.\n");
+		return -EINVAL;
+	}
+
+	/* Currently only TCPv4 S.O. is supported. */
+	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+		if (net_ratelimit())
+			WPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
+		return -EINVAL;
+	}
+
+#if HAVE_TSO
+	skb_shinfo(skb)->gso_size = gso->u.gso.size;
+#if HAVE_GSO
+	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+
+	/* Header must be checked, and gso_segs computed. */
+	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+#endif
+	skb_shinfo(skb)->gso_segs = 0;
+
+	return 0;
+#else
+	if (net_ratelimit())
+		WPRINTK("GSO unsupported by this kernel.\n");
+	return -EINVAL;
+#endif
+}
+
+static int netif_poll(struct napi_struct *napi, int budget)
+{
+	struct netfront_info *np = container_of(napi, struct netfront_info, napi);
+	struct net_device *dev = np->netdev;
+	struct sk_buff *skb;
+	struct netfront_rx_info rinfo;
+	struct netif_rx_response *rx = &rinfo.rx;
+	struct netif_extra_info *extras = rinfo.extras;
+	RING_IDX i, rp;
+	struct multicall_entry *mcl;
+	int work_done, more_to_do = 1, accel_more_to_do = 1;
+	struct sk_buff_head rxq;
+	struct sk_buff_head errq;
+	struct sk_buff_head tmpq;
+	unsigned long flags;
+	unsigned int len;
+	int pages_flipped = 0;
+	int err;
+
+	spin_lock(&np->rx_lock); /* no need for spin_lock_bh() in ->poll() */
+
+	if (unlikely(!netfront_carrier_ok(np))) {
+		spin_unlock(&np->rx_lock);
+		return 0;
+	}
+
+	skb_queue_head_init(&rxq);
+	skb_queue_head_init(&errq);
+	skb_queue_head_init(&tmpq);
+
+	rp = np->rx.sring->rsp_prod;
+	rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+	i = np->rx.rsp_cons;
+	work_done = 0;
+	while ((i != rp) && (work_done < budget)) {
+		memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
+		memset(extras, 0, sizeof(rinfo.extras));
+
+		err = xennet_get_responses(np, &rinfo, rp, &tmpq,
+					   &pages_flipped);
+
+		if (unlikely(err)) {
+err:	
+			while ((skb = __skb_dequeue(&tmpq)))
+				__skb_queue_tail(&errq, skb);
+			np->stats.rx_errors++;
+			i = np->rx.rsp_cons;
+			continue;
+		}
+
+		skb = __skb_dequeue(&tmpq);
+
+		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+			struct netif_extra_info *gso;
+			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+			if (unlikely(xennet_set_skb_gso(skb, gso))) {
+				__skb_queue_head(&tmpq, skb);
+				np->rx.rsp_cons += skb_queue_len(&tmpq);
+				goto err;
+			}
+		}
+
+		NETFRONT_SKB_CB(skb)->page = skb_shinfo(skb)->frags[0].page;
+		NETFRONT_SKB_CB(skb)->offset = rx->offset;
+
+		len = rx->status;
+		if (len > RX_COPY_THRESHOLD)
+			len = RX_COPY_THRESHOLD;
+		skb_put(skb, len);
+
+		if (rx->status > len) {
+			skb_shinfo(skb)->frags[0].page_offset =
+				rx->offset + len;
+			skb_shinfo(skb)->frags[0].size = rx->status - len;
+			skb->data_len = rx->status - len;
+		} else {
+			skb_shinfo(skb)->frags[0].page = NULL;
+			skb_shinfo(skb)->nr_frags = 0;
+		}
+
+		i = xennet_fill_frags(np, skb, &tmpq);
+
+		/*
+		 * Truesize must approximates the size of true data plus
+		 * any supervisor overheads. Adding hypervisor overheads
+		 * has been shown to significantly reduce achievable
+		 * bandwidth with the default receive buffer size. It is
+		 * therefore not wise to account for it here.
+		 *
+		 * After alloc_skb(RX_COPY_THRESHOLD), truesize is set to
+		 * RX_COPY_THRESHOLD + the supervisor overheads. Here, we
+		 * add the size of the data pulled in xennet_fill_frags().
+		 *
+		 * We also adjust for any unused space in the main data
+		 * area by subtracting (RX_COPY_THRESHOLD - len). This is
+		 * especially important with drivers which split incoming
+		 * packets into header and data, using only 66 bytes of
+		 * the main data area (see the e1000 driver for example.)
+		 * On such systems, without this last adjustement, our
+		 * achievable receive throughout using the standard receive
+		 * buffer size was cut by 25%(!!!).
+		 */
+		skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
+		skb->len += skb->data_len;
+
+		/*
+		 * Old backends do not assert data_validated but we
+		 * can infer it from csum_blank so test both flags.
+		 */
+		if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
+#ifdef CONFIG_XEN
+		skb->proto_data_valid = (skb->ip_summed != CHECKSUM_NONE);
+		skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
+#endif
+		np->stats.rx_packets++;
+		np->stats.rx_bytes += skb->len;
+
+		__skb_queue_tail(&rxq, skb);
+
+		np->rx.rsp_cons = ++i;
+		work_done++;
+	}
+
+	if (pages_flipped) {
+		/* Some pages are no longer absent... */
+		balloon_update_driver_allowance(-pages_flipped);
+
+		/* Do all the remapping work and M2P updates. */
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			mcl = np->rx_mcl + pages_flipped;
+			mcl->op = __HYPERVISOR_mmu_update;
+			mcl->args[0] = (unsigned long)np->rx_mmu;
+			mcl->args[1] = pages_flipped;
+			mcl->args[2] = 0;
+			mcl->args[3] = DOMID_SELF;
+			err = HYPERVISOR_multicall_check(np->rx_mcl,
+							 pages_flipped + 1,
+							 NULL);
+			BUG_ON(err);
+		}
+	}
+
+	__skb_queue_purge(&errq);
+
+	while ((skb = __skb_dequeue(&rxq)) != NULL) {
+		struct page *page = NETFRONT_SKB_CB(skb)->page;
+		void *vaddr = page_address(page);
+		unsigned offset = NETFRONT_SKB_CB(skb)->offset;
+
+		memcpy(skb->data, vaddr + offset, skb_headlen(skb));
+
+		if (page != skb_shinfo(skb)->frags[0].page)
+			__free_page(page);
+
+		/* Ethernet work: Delayed to here as it peeks the header. */
+		skb->protocol = eth_type_trans(skb, dev);
+
+		/* Pass it up. */
+		netif_receive_skb(skb);
+	}
+
+	/* If we get a callback with very few responses, reduce fill target. */
+	/* NB. Note exponential increase, linear decrease. */
+	if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) >
+	     ((3*np->rx_target) / 4)) &&
+	    (--np->rx_target < np->rx_min_target))
+		np->rx_target = np->rx_min_target;
+
+	network_alloc_rx_buffers(dev);
+
+	if (work_done < budget) {
+		/* there's some spare capacity, try the accelerated path */
+		int accel_budget = budget - work_done;
+		int accel_budget_start = accel_budget;
+
+ 		if (np->accel_vif_state.hooks) { 
+ 			accel_more_to_do =  
+ 				np->accel_vif_state.hooks->netdev_poll 
+ 				(dev, &accel_budget); 
+ 			work_done += (accel_budget_start - accel_budget); 
+ 		} else
+			accel_more_to_do = 0;
+	}
+
+	if (work_done < budget) {
+		local_irq_save(flags);
+
+		RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
+
+		if (!more_to_do && !accel_more_to_do && 
+		    np->accel_vif_state.hooks) {
+			/* 
+			 *  Slow path has nothing more to do, see if
+			 *  fast path is likewise
+			 */
+			accel_more_to_do = 
+				np->accel_vif_state.hooks->start_napi_irq(dev);
+		}
+
+		if (!more_to_do && !accel_more_to_do)
+			__napi_complete(napi);
+
+		local_irq_restore(flags);
+	}
+
+	spin_unlock(&np->rx_lock);
+	
+	return work_done;
+}
+
+static void netif_release_tx_bufs(struct netfront_info *np)
+{
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 1; i <= NET_TX_RING_SIZE; i++) {
+		if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
+			continue;
+
+		skb = np->tx_skbs[i];
+		gnttab_end_foreign_access_ref(np->grant_tx_ref[i]);
+		gnttab_release_grant_reference(
+			&np->gref_tx_head, np->grant_tx_ref[i]);
+		np->grant_tx_ref[i] = GRANT_INVALID_REF;
+		add_id_to_freelist(np->tx_skbs, i);
+		dev_kfree_skb_irq(skb);
+	}
+}
+
+static void netif_release_rx_bufs_flip(struct netfront_info *np)
+{
+	struct mmu_update      *mmu = np->rx_mmu;
+	struct multicall_entry *mcl = np->rx_mcl;
+	struct sk_buff_head free_list;
+	struct sk_buff *skb;
+	unsigned long mfn;
+	int xfer = 0, noxfer = 0, unused = 0;
+	int id, ref, rc;
+
+	skb_queue_head_init(&free_list);
+
+	spin_lock_bh(&np->rx_lock);
+
+	for (id = 0; id < NET_RX_RING_SIZE; id++) {
+		if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
+			unused++;
+			continue;
+		}
+
+		skb = np->rx_skbs[id];
+		mfn = gnttab_end_foreign_transfer_ref(ref);
+		gnttab_release_grant_reference(&np->gref_rx_head, ref);
+		np->grant_rx_ref[id] = GRANT_INVALID_REF;
+		add_id_to_freelist(np->rx_skbs, id);
+
+		if (0 == mfn) {
+			struct page *page = skb_shinfo(skb)->frags[0].page;
+			balloon_release_driver_page(page);
+			skb_shinfo(skb)->nr_frags = 0;
+			dev_kfree_skb(skb);
+			noxfer++;
+			continue;
+		}
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			/* Remap the page. */
+			struct page *page = skb_shinfo(skb)->frags[0].page;
+			unsigned long pfn = page_to_pfn(page);
+			void *vaddr = page_address(page);
+
+			MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
+						pfn_pte_ma(mfn, PAGE_KERNEL),
+						0);
+			mcl++;
+			mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
+				| MMU_MACHPHYS_UPDATE;
+			mmu->val = pfn;
+			mmu++;
+
+			set_phys_to_machine(pfn, mfn);
+		}
+		__skb_queue_tail(&free_list, skb);
+		xfer++;
+	}
+
+	DPRINTK("%s: %d xfer, %d noxfer, %d unused\n",
+		__FUNCTION__, xfer, noxfer, unused);
+
+	if (xfer) {
+		/* Some pages are no longer absent... */
+		balloon_update_driver_allowance(-xfer);
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			/* Do all the remapping work and M2P updates. */
+			mcl->op = __HYPERVISOR_mmu_update;
+			mcl->args[0] = (unsigned long)np->rx_mmu;
+			mcl->args[1] = mmu - np->rx_mmu;
+			mcl->args[2] = 0;
+			mcl->args[3] = DOMID_SELF;
+			mcl++;
+			rc = HYPERVISOR_multicall_check(
+				np->rx_mcl, mcl - np->rx_mcl, NULL);
+			BUG_ON(rc);
+		}
+	}
+
+	__skb_queue_purge(&free_list);
+
+	spin_unlock_bh(&np->rx_lock);
+}
+
+static void netif_release_rx_bufs_copy(struct netfront_info *np)
+{
+	struct sk_buff *skb;
+	int i, ref;
+	int busy = 0, inuse = 0;
+
+	spin_lock_bh(&np->rx_lock);
+
+	for (i = 0; i < NET_RX_RING_SIZE; i++) {
+		ref = np->grant_rx_ref[i];
+
+		if (ref == GRANT_INVALID_REF)
+			continue;
+
+		inuse++;
+
+		skb = np->rx_skbs[i];
+
+		if (!gnttab_end_foreign_access_ref(ref))
+		{
+			busy++;
+			continue;
+		}
+
+		gnttab_release_grant_reference(&np->gref_rx_head, ref);
+		np->grant_rx_ref[i] = GRANT_INVALID_REF;
+		add_id_to_freelist(np->rx_skbs, i);
+
+		dev_kfree_skb(skb);
+	}
+
+	if (busy)
+		DPRINTK("%s: Unable to release %d of %d inuse grant references out of %ld total.\n",
+			__FUNCTION__, busy, inuse, NET_RX_RING_SIZE);
+
+	spin_unlock_bh(&np->rx_lock);
+}
+
+static int network_close(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	netif_stop_queue(np->netdev);
+	napi_disable(&np->napi);
+	return 0;
+}
+
+
+static struct net_device_stats *network_get_stats(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+
+	netfront_accelerator_call_get_stats(np, dev);
+	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;
+
+	if (mtu > max)
+		return -EINVAL;
+	dev->mtu = mtu;
+	return 0;
+}
+
+static int xennet_set_sg(struct net_device *dev, u32 data)
+{
+	if (data) {
+		struct netfront_info *np = netdev_priv(dev);
+		int val;
+
+		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg",
+				 "%d", &val) < 0)
+			val = 0;
+		if (!val)
+			return -ENOSYS;
+	} else if (dev->mtu > ETH_DATA_LEN)
+		dev->mtu = ETH_DATA_LEN;
+
+	return ethtool_op_set_sg(dev, data);
+}
+
+static int xennet_set_tso(struct net_device *dev, u32 data)
+{
+	if (data) {
+		struct netfront_info *np = netdev_priv(dev);
+		int val;
+
+		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+				 "feature-gso-tcpv4", "%d", &val) < 0)
+			val = 0;
+		if (!val)
+			return -ENOSYS;
+	}
+
+	return ethtool_op_set_tso(dev, data);
+}
+
+static void xennet_set_features(struct net_device *dev)
+{
+	dev_disable_gso_features(dev);
+	xennet_set_sg(dev, 0);
+
+	/* We need checksum offload to enable scatter/gather and TSO. */
+	if (!(dev->features & NETIF_F_IP_CSUM))
+		return;
+
+	if (xennet_set_sg(dev, 1))
+		return;
+
+	/* Before 2.6.9 TSO seems to be unreliable so do not enable it
+	 * on older kernels.
+	 */
+	if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9))
+		xennet_set_tso(dev, 1);
+}
+
+static int network_connect(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	int i, requeue_idx, err;
+	struct sk_buff *skb;
+	grant_ref_t ref;
+	netif_rx_request_t *req;
+	unsigned int feature_rx_copy, feature_rx_flip;
+
+	err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+			   "feature-rx-copy", "%u", &feature_rx_copy);
+	if (err != 1)
+		feature_rx_copy = 0;
+	err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
+			   "feature-rx-flip", "%u", &feature_rx_flip);
+	if (err != 1)
+		feature_rx_flip = 1;
+
+	/*
+	 * Copy packets on receive path if:
+	 *  (a) This was requested by user, and the backend supports it; or
+	 *  (b) Flipping was requested, but this is unsupported by the backend.
+	 */
+	np->copying_receiver = ((MODPARM_rx_copy && feature_rx_copy) ||
+				(MODPARM_rx_flip && !feature_rx_flip));
+
+	err = talk_to_backend(np->xbdev, np);
+	if (err)
+		return err;
+
+	xennet_set_features(dev);
+
+	DPRINTK("device %s has %sing receive path.\n",
+		dev->name, np->copying_receiver ? "copy" : "flipp");
+
+	spin_lock_bh(&np->rx_lock);
+	spin_lock_irq(&np->tx_lock);
+
+	/*
+	 * Recovery procedure:
+	 *  NB. Freelist index entries are always going to be less than
+	 *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
+	 *  greater than PAGE_OFFSET: we use this property to distinguish
+	 *  them.
+	 */
+
+	/* Step 1: Discard all pending TX packet fragments. */
+	netif_release_tx_bufs(np);
+
+	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
+	for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
+		if (!np->rx_skbs[i])
+			continue;
+
+		skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
+		ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
+		req = RING_GET_REQUEST(&np->rx, requeue_idx);
+
+		if (!np->copying_receiver) {
+			gnttab_grant_foreign_transfer_ref(
+				ref, np->xbdev->otherend_id,
+				page_to_pfn(skb_shinfo(skb)->frags->page));
+		} else {
+			gnttab_grant_foreign_access_ref(
+				ref, np->xbdev->otherend_id,
+				pfn_to_mfn(page_to_pfn(skb_shinfo(skb)->
+						       frags->page)),
+				0);
+		}
+		req->gref = ref;
+		req->id   = requeue_idx;
+
+		requeue_idx++;
+	}
+
+	np->rx.req_prod_pvt = requeue_idx;
+
+	/*
+	 * Step 3: All public and private state should now be sane.  Get
+	 * ready to start sending and receiving packets and give the driver
+	 * domain a kick because we've probably just requeued some
+	 * packets.
+	 */
+	netfront_carrier_on(np);
+	notify_remote_via_irq(np->irq);
+	network_tx_buf_gc(dev);
+	network_alloc_rx_buffers(dev);
+
+	spin_unlock_irq(&np->tx_lock);
+	spin_unlock_bh(&np->rx_lock);
+
+	return 0;
+}
+
+static void netif_uninit(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	netif_release_tx_bufs(np);
+	if (np->copying_receiver)
+		netif_release_rx_bufs_copy(np);
+	else
+		netif_release_rx_bufs_flip(np);
+	gnttab_free_grant_references(np->gref_tx_head);
+	gnttab_free_grant_references(np->gref_rx_head);
+}
+
+static const struct ethtool_ops network_ethtool_ops =
+{
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = xennet_set_sg,
+#if HAVE_TSO
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = xennet_set_tso,
+#endif
+	.get_link = ethtool_op_get_link,
+};
+
+#ifdef CONFIG_SYSFS
+static ssize_t show_rxbuf_min(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+
+	return sprintf(buf, "%u\n", info->rx_min_target);
+}
+
+static ssize_t store_rxbuf_min(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t len)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	struct netfront_info *np = netdev_priv(netdev);
+	char *endp;
+	unsigned long target;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	target = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		return -EBADMSG;
+
+	if (target < RX_MIN_TARGET)
+		target = RX_MIN_TARGET;
+	if (target > RX_MAX_TARGET)
+		target = RX_MAX_TARGET;
+
+	spin_lock_bh(&np->rx_lock);
+	if (target > np->rx_max_target)
+		np->rx_max_target = target;
+	np->rx_min_target = target;
+	if (target > np->rx_target)
+		np->rx_target = target;
+
+	network_alloc_rx_buffers(netdev);
+
+	spin_unlock_bh(&np->rx_lock);
+	return len;
+}
+
+static ssize_t show_rxbuf_max(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+
+	return sprintf(buf, "%u\n", info->rx_max_target);
+}
+
+static ssize_t store_rxbuf_max(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t len)
+{
+	struct net_device *netdev = to_net_dev(dev);
+	struct netfront_info *np = netdev_priv(netdev);
+	char *endp;
+	unsigned long target;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	target = simple_strtoul(buf, &endp, 0);
+	if (endp == buf)
+		return -EBADMSG;
+
+	if (target < RX_MIN_TARGET)
+		target = RX_MIN_TARGET;
+	if (target > RX_MAX_TARGET)
+		target = RX_MAX_TARGET;
+
+	spin_lock_bh(&np->rx_lock);
+	if (target < np->rx_min_target)
+		np->rx_min_target = target;
+	np->rx_max_target = target;
+	if (target < np->rx_target)
+		np->rx_target = target;
+
+	network_alloc_rx_buffers(netdev);
+
+	spin_unlock_bh(&np->rx_lock);
+	return len;
+}
+
+static ssize_t show_rxbuf_cur(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+
+	return sprintf(buf, "%u\n", info->rx_target);
+}
+
+static struct device_attribute xennet_attrs[] = {
+	__ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
+	__ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
+	__ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
+};
+
+static int xennet_sysfs_addif(struct net_device *netdev)
+{
+	int i;
+	int error = 0;
+
+	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
+		error = device_create_file(&netdev->dev,
+					   &xennet_attrs[i]);
+		if (error)
+			goto fail;
+	}
+	return 0;
+
+ fail:
+	while (--i >= 0)
+		device_remove_file(&netdev->dev, &xennet_attrs[i]);
+	return error;
+}
+
+static void xennet_sysfs_delif(struct net_device *netdev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++)
+		device_remove_file(&netdev->dev, &xennet_attrs[i]);
+}
+
+#endif /* CONFIG_SYSFS */
+
+
+/*
+ * Nothing to do here. Virtual interface is point-to-point and the
+ * physical interface is probably promiscuous anyway.
+ */
+static void network_set_multicast_list(struct net_device *dev)
+{
+}
+
+static const struct net_device_ops xennet_netdev_ops = {
+	.ndo_uninit             = netif_uninit,
+	.ndo_open               = network_open,
+	.ndo_stop               = network_close,
+	.ndo_start_xmit         = network_start_xmit,
+	.ndo_set_multicast_list = network_set_multicast_list,
+	.ndo_set_mac_address    = xennet_set_mac_address,
+	.ndo_validate_addr      = eth_validate_addr,
+	.ndo_change_mtu	        = xennet_change_mtu,
+	.ndo_get_stats          = network_get_stats,
+};
+
+static struct net_device * __devinit create_netdev(struct xenbus_device *dev)
+{
+	int i, err = 0;
+	struct net_device *netdev = NULL;
+	struct netfront_info *np = NULL;
+
+	netdev = alloc_etherdev(sizeof(struct netfront_info));
+	if (!netdev) {
+		printk(KERN_WARNING "%s> alloc_etherdev failed.\n",
+		       __FUNCTION__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	np                   = netdev_priv(netdev);
+	np->xbdev            = dev;
+
+	spin_lock_init(&np->tx_lock);
+	spin_lock_init(&np->rx_lock);
+
+	init_accelerator_vif(np, dev);
+
+	skb_queue_head_init(&np->rx_batch);
+	np->rx_target     = RX_DFL_MIN_TARGET;
+	np->rx_min_target = RX_DFL_MIN_TARGET;
+	np->rx_max_target = RX_MAX_TARGET;
+
+	init_timer(&np->rx_refill_timer);
+	np->rx_refill_timer.data = (unsigned long)netdev;
+	np->rx_refill_timer.function = rx_refill_timeout;
+
+	/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
+	for (i = 0; i <= NET_TX_RING_SIZE; i++) {
+		np->tx_skbs[i] = (void *)((unsigned long) i+1);
+		np->grant_tx_ref[i] = GRANT_INVALID_REF;
+	}
+
+	for (i = 0; i < NET_RX_RING_SIZE; i++) {
+		np->rx_skbs[i] = NULL;
+		np->grant_rx_ref[i] = GRANT_INVALID_REF;
+	}
+
+	/* A grant for every tx ring slot */
+	if (gnttab_alloc_grant_references(TX_MAX_TARGET,
+					  &np->gref_tx_head) < 0) {
+		printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
+		err = -ENOMEM;
+		goto exit;
+	}
+	/* A grant for every rx ring slot */
+	if (gnttab_alloc_grant_references(RX_MAX_TARGET,
+					  &np->gref_rx_head) < 0) {
+		printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
+		err = -ENOMEM;
+		goto exit_free_tx;
+	}
+
+	netdev->netdev_ops	= &xennet_netdev_ops;
+	netif_napi_add(netdev, &np->napi, netif_poll, 64);
+	netdev->features        = NETIF_F_IP_CSUM;
+
+	SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+	SET_NETDEV_DEV(netdev, &dev->dev);
+
+	np->netdev = netdev;
+
+	netfront_carrier_off(np);
+
+	return netdev;
+
+ exit_free_tx:
+	gnttab_free_grant_references(np->gref_tx_head);
+ exit:
+	free_netdev(netdev);
+	return ERR_PTR(err);
+}
+
+static void netif_disconnect_backend(struct netfront_info *info)
+{
+	/* Stop old i/f to prevent errors whilst we rebuild the state. */
+	spin_lock_bh(&info->rx_lock);
+	spin_lock_irq(&info->tx_lock);
+	netfront_carrier_off(info);
+	spin_unlock_irq(&info->tx_lock);
+	spin_unlock_bh(&info->rx_lock);
+
+	if (info->irq)
+		unbind_from_irqhandler(info->irq, info->netdev);
+	info->irq = 0;
+
+	end_access(info->tx_ring_ref, info->tx.sring);
+	end_access(info->rx_ring_ref, info->rx.sring);
+	info->tx_ring_ref = GRANT_INVALID_REF;
+	info->rx_ring_ref = GRANT_INVALID_REF;
+	info->tx.sring = NULL;
+	info->rx.sring = NULL;
+}
+
+
+static void end_access(int ref, void *page)
+{
+	if (ref != GRANT_INVALID_REF)
+		gnttab_end_foreign_access(ref, (unsigned long)page);
+}
+
+
+/* ** Driver registration ** */
+
+
+static const struct xenbus_device_id netfront_ids[] = {
+	{ "vif" },
+	{ "" }
+};
+MODULE_ALIAS("xen:vif");
+
+
+static struct xenbus_driver netfront_driver = {
+	.name = "vif",
+	.ids = netfront_ids,
+	.probe = netfront_probe,
+	.remove = __devexit_p(netfront_remove),
+	.suspend = netfront_suspend,
+	.suspend_cancel = netfront_suspend_cancel,
+	.resume = netfront_resume,
+	.otherend_changed = backend_changed,
+};
+
+
+static int __init netif_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+#ifdef CONFIG_XEN
+	if (MODPARM_rx_flip && MODPARM_rx_copy) {
+		WPRINTK("Cannot specify both rx_copy and rx_flip.\n");
+		return -EINVAL;
+	}
+
+	if (!MODPARM_rx_flip && !MODPARM_rx_copy)
+		MODPARM_rx_flip = 1; /* Default is to flip. */
+#endif
+
+	netif_init_accel();
+
+	IPRINTK("Initialising virtual ethernet driver.\n");
+
+	return xenbus_register_frontend(&netfront_driver);
+}
+module_init(netif_init);
+
+
+static void __exit netif_exit(void)
+{
+	xenbus_unregister_driver(&netfront_driver);
+
+	netif_exit_accel();
+}
+module_exit(netif_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/common.h
+++ linux-ec2-2.6.32/drivers/xen/blktap/common.h
@@ -0,0 +1,123 @@
+/* 
+ * 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 __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <xen/evtchn.h>
+#include <asm/hypervisor.h>
+#include <xen/blkif.h>
+#include <xen/gnttab.h>
+#include <xen/driver_util.h>
+
+#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \
+                                    __FILE__ , __LINE__ , ## _a )
+
+#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
+
+struct backend_info;
+
+typedef struct blkif_st {
+	/* Unique identifier for this interface. */
+	domid_t           domid;
+	unsigned int      handle;
+	/* Physical parameters of the comms window. */
+	unsigned int      irq;
+	/* Comms information. */
+	enum blkif_protocol blk_protocol;
+	blkif_back_rings_t blk_rings;
+	struct vm_struct *blk_ring_area;
+	/* Back pointer to the backend_info. */
+	struct backend_info *be;
+	/* Private fields. */
+	spinlock_t       blk_ring_lock;
+	atomic_t         refcnt;
+
+	wait_queue_head_t   wq;
+	struct task_struct  *xenblkd;
+	unsigned int        waiting_reqs;
+	struct request_queue *plug;
+
+	/* statistics */
+	unsigned long       st_print;
+	int                 st_rd_req;
+	int                 st_wr_req;
+	int                 st_oo_req;
+	int                 st_pk_req;
+	int                 st_rd_sect;
+	int                 st_wr_sect;
+
+	wait_queue_head_t waiting_to_free;
+
+	grant_handle_t shmem_handle;
+	grant_ref_t    shmem_ref;
+	
+	int		dev_num;
+	uint64_t        sectors;
+} blkif_t;
+
+blkif_t *tap_alloc_blkif(domid_t domid);
+void tap_blkif_free(blkif_t *blkif);
+void tap_blkif_kmem_cache_free(blkif_t *blkif);
+int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
+		  unsigned int evtchn);
+void tap_blkif_unmap(blkif_t *blkif);
+
+#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blkif_put(_b)					\
+	do {						\
+		if (atomic_dec_and_test(&(_b)->refcnt))	\
+			wake_up(&(_b)->waiting_to_free);\
+	} while (0)
+
+
+struct phys_req {
+	unsigned short       dev;
+	unsigned short       nr_sects;
+	struct block_device *bdev;
+	blkif_sector_t       sector_number;
+};
+
+void tap_blkif_interface_init(void);
+
+void tap_blkif_xenbus_init(void);
+
+irqreturn_t tap_blkif_be_int(int irq, void *dev_id);
+int tap_blkif_schedule(void *arg);
+
+int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif);
+void signal_tapdisk(int idx);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/Makefile
+++ linux-ec2-2.6.32/drivers/xen/blktap/Makefile
@@ -0,0 +1,5 @@
+LINUXINCLUDE += -I../xen/include/public/io
+
+obj-$(CONFIG_XEN_BLKDEV_TAP) := blktap.o
+
+blktap-y := xenbus.o interface.o blocktap.o
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/blktap/xenbus.c
@@ -0,0 +1,509 @@
+/* drivers/xen/blktap/xenbus.c
+ *
+ * Xenbus code for blktap
+ *
+ * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
+ *
+ * Based on the blkback xenbus code:
+ *
+ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ * Copyright (C) 2005 XenSource Ltd
+ *
+ * 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 <xen/xenbus.h>
+#include "common.h"
+#include "../core/domctl.h"
+
+
+struct backend_info
+{
+	struct xenbus_device *dev;
+	blkif_t *blkif;
+	struct xenbus_watch backend_watch;
+	int xenbus_id;
+	int group_added;
+};
+
+
+static void connect(struct backend_info *);
+static int connect_ring(struct backend_info *);
+static int blktap_remove(struct xenbus_device *dev);
+static int blktap_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id);
+static void tap_backend_changed(struct xenbus_watch *, const char **,
+			    unsigned int);
+static void tap_frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state);
+
+static int strsep_len(const char *str, char c, unsigned int len)
+{
+        unsigned int i;
+
+        for (i = 0; str[i]; i++)
+                if (str[i] == c) {
+                        if (len == 0)
+                                return i;
+                        len--;
+                }
+        return (len == 0) ? i : -ERANGE;
+}
+
+static long get_id(const char *str)
+{
+        int len,end;
+        const char *ptr;
+        char *tptr, num[10];
+	
+        len = strsep_len(str, '/', 2);
+        end = strlen(str);
+        if ( (len < 0) || (end < 0) ) return -1;
+	
+        ptr = str + len + 1;
+        strncpy(num,ptr,end - len);
+        tptr = num + (end - (len + 1));
+        *tptr = '\0';
+	DPRINTK("Get_id called for %s (%s)\n",str,num);
+	
+        return simple_strtol(num, NULL, 10);
+}				
+
+static int blktap_name(blkif_t *blkif, char *buf)
+{
+	char *devpath, *devname;
+	struct xenbus_device *dev = blkif->be->dev;
+
+	devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
+	if (IS_ERR(devpath)) 
+		return PTR_ERR(devpath);
+	
+	if ((devname = strstr(devpath, "/dev/")) != NULL)
+		devname += strlen("/dev/");
+	else
+		devname  = devpath;
+
+	snprintf(buf, TASK_COMM_LEN, "blktap.%d.%s", blkif->domid, devname);
+	kfree(devpath);
+	
+	return 0;
+}
+
+/****************************************************************
+ *  sysfs interface for I/O requests of blktap device
+ */
+
+#define VBD_SHOW(name, format, args...)					\
+	static ssize_t show_##name(struct device *_dev,			\
+				   struct device_attribute *attr,	\
+				   char *buf)				\
+	{								\
+		struct xenbus_device *dev = to_xenbus_device(_dev);	\
+		struct backend_info *be = dev_get_drvdata(&dev->dev);	\
+									\
+		return sprintf(buf, format, ##args);			\
+	}								\
+	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
+VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
+VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
+VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
+VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
+
+static struct attribute *tapstat_attrs[] = {
+	&dev_attr_oo_req.attr,
+	&dev_attr_rd_req.attr,
+	&dev_attr_wr_req.attr,
+	&dev_attr_rd_sect.attr,
+	&dev_attr_wr_sect.attr,
+	NULL
+};
+
+static struct attribute_group tapstat_group = {
+	.name = "statistics",
+	.attrs = tapstat_attrs,
+};
+
+int xentap_sysfs_addif(struct xenbus_device *dev)
+{
+	int err;
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+	err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
+	if (!err)
+		be->group_added = 1;
+	return err;
+}
+
+void xentap_sysfs_delif(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+	sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
+	be->group_added = 0;
+}
+
+static int blktap_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	if (be->group_added)
+		xentap_sysfs_delif(be->dev);
+	if (be->backend_watch.node) {
+		unregister_xenbus_watch(&be->backend_watch);
+		kfree(be->backend_watch.node);
+		be->backend_watch.node = NULL;
+	}
+	if (be->blkif) {
+		if (be->blkif->xenblkd)
+			kthread_stop(be->blkif->xenblkd);
+		signal_tapdisk(be->blkif->dev_num);
+		tap_blkif_free(be->blkif);
+		tap_blkif_kmem_cache_free(be->blkif);
+		be->blkif = NULL;
+	}
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+static void tap_update_blkif_status(blkif_t *blkif)
+{ 
+	int err;
+	char name[TASK_COMM_LEN];
+
+	/* Not ready to connect? */
+	if(!blkif->irq || !blkif->sectors) {
+		return;
+	} 
+
+	/* Already connected? */
+	if (blkif->be->dev->state == XenbusStateConnected)
+		return;
+
+	/* Attempt to connect: exit if we fail to. */
+	connect(blkif->be);
+	if (blkif->be->dev->state != XenbusStateConnected)
+		return;
+
+	err = blktap_name(blkif, name);
+	if (err) {
+		xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
+		return;
+	}
+
+	if (!blkif->be->group_added) {
+		err = xentap_sysfs_addif(blkif->be->dev);
+		if (err) {
+			xenbus_dev_fatal(blkif->be->dev, err, 
+					 "creating sysfs entries");
+			return;
+		}
+	}
+
+	blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name);
+	if (IS_ERR(blkif->xenblkd)) {
+		err = PTR_ERR(blkif->xenblkd);
+		blkif->xenblkd = NULL;
+		xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
+		WPRINTK("Error starting thread\n");
+	}
+}
+
+/**
+ * Entry point to this code when a new device is created.  Allocate
+ * the basic structures, and watch the store waiting for the
+ * user-space program to tell us the physical device info.  Switch to
+ * InitWait.
+ */
+static int blktap_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	int err;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+	be->xenbus_id = get_id(dev->nodename);
+
+	be->blkif = tap_alloc_blkif(dev->otherend_id);
+	if (IS_ERR(be->blkif)) {
+		err = PTR_ERR(be->blkif);
+		be->blkif = NULL;
+		xenbus_dev_fatal(dev, err, "creating block interface");
+		goto fail;
+	}
+
+	/* setup back pointer */
+	be->blkif->be = be;
+	be->blkif->sectors = 0;
+
+	/* set a watch on disk info, waiting for userspace to update details*/
+	err = xenbus_watch_path2(dev, dev->nodename, "info",
+				 &be->backend_watch, tap_backend_changed);
+	if (err)
+		goto fail;
+	
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+	return 0;
+
+fail:
+	DPRINTK("blktap probe failed\n");
+	blktap_remove(dev);
+	return err;
+}
+
+
+/**
+ * Callback received when the user space code has placed the device
+ * information in xenstore. 
+ */
+static void tap_backend_changed(struct xenbus_watch *watch,
+			    const char **vec, unsigned int len)
+{
+	int err;
+	unsigned long info;
+	struct backend_info *be
+		= container_of(watch, struct backend_info, backend_watch);
+	struct xenbus_device *dev = be->dev;
+	
+	/** 
+	 * Check to see whether userspace code has opened the image 
+	 * and written sector
+	 * and disk info to xenstore
+	 */
+	err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info, 
+			    NULL);
+	if (XENBUS_EXIST_ERR(err))
+		return;
+	if (err) {
+		xenbus_dev_error(dev, err, "getting info");
+		return;
+	}
+
+	DPRINTK("Userspace update on disk info, %lu\n",info);
+
+	err = xenbus_gather(XBT_NIL, dev->nodename, "sectors", "%llu", 
+			    &be->blkif->sectors, NULL);
+
+	/* Associate tap dev with domid*/
+	be->blkif->dev_num = dom_to_devid(be->blkif->domid, be->xenbus_id, 
+					  be->blkif);
+	DPRINTK("Thread started for domid [%d], connecting disk\n", 
+		be->blkif->dev_num);
+
+	tap_update_blkif_status(be->blkif);
+}
+
+/**
+ * Callback received when the frontend's state changes.
+ */
+static void tap_frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+	int err;
+
+	DPRINTK("\n");
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
+			       __FUNCTION__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateInitialised:
+	case XenbusStateConnected:
+		/* Ensure we connect even when two watches fire in 
+		   close successsion and we miss the intermediate value 
+		   of frontend_state. */
+		if (dev->state == XenbusStateConnected)
+			break;
+
+		err = connect_ring(be);
+		if (err)
+			break;
+		tap_update_blkif_status(be->blkif);
+		break;
+
+	case XenbusStateClosing:
+		if (be->blkif->xenblkd) {
+			kthread_stop(be->blkif->xenblkd);
+			be->blkif->xenblkd = NULL;
+		}
+		tap_blkif_free(be->blkif);
+		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;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+/**
+ * Switch to Connected state.
+ */
+static void connect(struct backend_info *be)
+{
+	int err;
+
+	struct xenbus_device *dev = be->dev;
+	struct xenbus_transaction xbt;
+
+	/* Write feature-barrier to xenstore */
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		return;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",  "1");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "writing feature-barrier");
+		xenbus_transaction_end(xbt, 1);
+		return;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+
+	/* Switch state */
+	err = xenbus_switch_state(dev, XenbusStateConnected);
+	if (err)
+		xenbus_dev_fatal(dev, err, "switching to Connected state",
+				 dev->nodename);
+
+	return;
+}
+
+
+static int connect_ring(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long ring_ref;
+	unsigned int evtchn;
+	char protocol[64];
+	int err;
+
+	DPRINTK("%s\n", dev->otherend);
+
+	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-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+			    "%63s", protocol, NULL);
+	if (err) {
+		strcpy(protocol, "unspecified");
+		be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
+	}
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */
+	else if (0 == strcmp(protocol, "1"))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+	else if (0 == strcmp(protocol, "2"))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+#endif
+	else {
+		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+		return -1;
+	}
+	printk(KERN_INFO
+	       "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
+	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
+
+	/* Map the shared frame, irq etc. */
+	err = tap_blkif_map(be->blkif, ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
+				 ring_ref, evtchn);
+		return err;
+	} 
+
+	return 0;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id blktap_ids[] = {
+	{ "tap" },
+	{ "" }
+};
+
+
+static struct xenbus_driver blktap = {
+	.name = "tap",
+	.ids = blktap_ids,
+	.probe = blktap_probe,
+	.remove = blktap_remove,
+	.otherend_changed = tap_frontend_changed
+};
+
+
+void tap_blkif_xenbus_init(void)
+{
+	if (xenbus_register_backend(&blktap))
+		BUG();
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/blocktap.c
+++ linux-ec2-2.6.32/drivers/xen/blktap/blocktap.c
@@ -0,0 +1 @@
+#include "blktap.c"
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/interface.c
+++ linux-ec2-2.6.32/drivers/xen/blktap/interface.c
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * drivers/xen/blktap/interface.c
+ * 
+ * Block-device interface management.
+ * 
+ * Copyright (c) 2004, Keir Fraser
+ *
+ * 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 "common.h"
+#include <xen/evtchn.h>
+
+static struct kmem_cache *blkif_cachep;
+
+blkif_t *tap_alloc_blkif(domid_t domid)
+{
+	blkif_t *blkif;
+
+	blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+	if (!blkif)
+		return ERR_PTR(-ENOMEM);
+
+	memset(blkif, 0, sizeof(*blkif));
+	blkif->domid = domid;
+	spin_lock_init(&blkif->blk_ring_lock);
+	atomic_set(&blkif->refcnt, 1);
+	init_waitqueue_head(&blkif->wq);
+	blkif->st_print = jiffies;
+	init_waitqueue_head(&blkif->waiting_to_free);
+
+	return blkif;
+}
+
+static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
+{
+	struct gnttab_map_grant_ref op;
+
+	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
+			  GNTMAP_host_map, shared_page, blkif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		DPRINTK(" Grant table operation failure !\n");
+		return op.status;
+	}
+
+	blkif->shmem_ref = shared_page;
+	blkif->shmem_handle = op.handle;
+
+	return 0;
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
+			    GNTMAP_host_map, blkif->shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+}
+
+int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
+		  unsigned int evtchn)
+{
+	int err;
+
+	/* Already connected through? */
+	if (blkif->irq)
+		return 0;
+
+	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+		return -ENOMEM;
+
+	err = map_frontend_page(blkif, shared_page);
+	if (err) {
+		free_vm_area(blkif->blk_ring_area);
+		return err;
+	}
+
+	switch (blkif->blk_protocol) {
+	case BLKIF_PROTOCOL_NATIVE:
+	{
+		blkif_sring_t *sring;
+		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
+		break;
+	}
+	case BLKIF_PROTOCOL_X86_32:
+	{
+		blkif_x86_32_sring_t *sring_x86_32;
+		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
+		break;
+	}
+	case BLKIF_PROTOCOL_X86_64:
+	{
+		blkif_x86_64_sring_t *sring_x86_64;
+		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
+		break;
+	}
+	default:
+		BUG();
+	}
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		blkif->domid, evtchn, tap_blkif_be_int,
+		0, "blkif-backend", blkif);
+	if (err < 0) {
+		unmap_frontend_page(blkif);
+		free_vm_area(blkif->blk_ring_area);
+		blkif->blk_rings.common.sring = NULL;
+		return err;
+	}
+	blkif->irq = err;
+
+	return 0;
+}
+
+void tap_blkif_unmap(blkif_t *blkif)
+{
+	if (blkif->irq) {
+		unbind_from_irqhandler(blkif->irq, blkif);
+		blkif->irq = 0;
+	}
+	if (blkif->blk_rings.common.sring) {
+		unmap_frontend_page(blkif);
+		free_vm_area(blkif->blk_ring_area);
+		blkif->blk_rings.common.sring = NULL;
+	}
+}
+
+void tap_blkif_free(blkif_t *blkif)
+{
+	atomic_dec(&blkif->refcnt);
+	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
+	atomic_inc(&blkif->refcnt);
+
+	tap_blkif_unmap(blkif);
+}
+
+void tap_blkif_kmem_cache_free(blkif_t *blkif)
+{
+	if (!atomic_dec_and_test(&blkif->refcnt))
+		BUG();
+	kmem_cache_free(blkif_cachep, blkif);
+}
+
+void __init tap_blkif_interface_init(void)
+{
+	blkif_cachep = kmem_cache_create("blktapif_cache", sizeof(blkif_t), 
+					 0, 0, NULL);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blktap/blktap.c
+++ linux-ec2-2.6.32/drivers/xen/blktap/blktap.c
@@ -0,0 +1,1783 @@
+/******************************************************************************
+ * drivers/xen/blktap/blktap.c
+ * 
+ * Back-end driver for user level virtual block devices. This portion of the
+ * driver exports a 'unified' block-device interface that can be accessed
+ * by any operating system that implements a compatible front end. Requests
+ * are remapped to a user-space memory region.
+ *
+ * Based on the blkback driver code.
+ * 
+ * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
+ *
+ * Clean ups and fix ups:
+ *    Copyright (c) 2006, Steven Rostedt - Red Hat, 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.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/list.h>
+#include <asm/hypervisor.h>
+#include "common.h"
+#include <xen/balloon.h>
+#include <xen/driver_util.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/gfp.h>
+#include <linux/poll.h>
+#include <linux/delay.h>
+#include <linux/nsproxy.h>
+#include <asm/tlbflush.h>
+
+#define MAX_TAP_DEV 256     /*the maximum number of tapdisk ring devices    */
+#define MAX_DEV_NAME 100    /*the max tapdisk ring device name e.g. blktap0 */
+
+/*
+ * The maximum number of requests that can be outstanding at any time
+ * is determined by 
+ *
+ *   [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] 
+ *
+ * where mmap_alloc < MAX_DYNAMIC_MEM.
+ *
+ * TODO:
+ * mmap_alloc is initialised to 2 and should be adjustable on the fly via
+ * sysfs.
+ */
+#define BLK_RING_SIZE		__RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+#define MAX_DYNAMIC_MEM		BLK_RING_SIZE
+#define MAX_PENDING_REQS	BLK_RING_SIZE
+#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg)                                   \
+        (_start +                                                       \
+         ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +        \
+         ((_seg) * PAGE_SIZE))
+static int blkif_reqs = MAX_PENDING_REQS;
+static int mmap_pages = MMAP_PAGES;
+
+#define RING_PAGES 1 /* BLKTAP - immediately before the mmap area, we
+		      * have a bunch of pages reserved for shared
+		      * memory rings.
+		      */
+
+/*Data struct handed back to userspace for tapdisk device to VBD mapping*/
+typedef struct domid_translate {
+	unsigned short domid;
+	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 mm_struct *mm;         /*User address space                   */
+	unsigned long rings_vstart;   /*Kernel memory mapping                */
+	unsigned long user_vstart;    /*User memory mapping                  */
+	unsigned long dev_inuse;      /*One process opens device at a time.  */
+	unsigned long dev_pending;    /*In process of being opened           */
+	unsigned long ring_ok;        /*make this ring->state                */
+	blkif_front_ring_t ufe_ring;  /*Rings up to user space.              */
+	wait_queue_head_t wait;       /*for poll                             */
+	unsigned long mode;           /*current switching mode               */
+	int minor;                    /*Minor number for tapdisk device      */
+	pid_t pid;                    /*tapdisk process id                   */
+	struct pid_namespace *pid_ns; /*... and its corresponding namespace  */
+	enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace 
+						  shutdown                   */
+	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_ext trans; /*Translation from domid to bus.   */
+	struct vm_foreign_map foreign_map;    /*Mapping page */
+} tap_blkif_t;
+
+static struct tap_blkif *tapfds[MAX_TAP_DEV];
+static int blktap_next_minor;
+
+module_param(blkif_reqs, int, 0);
+/* Run-time switchable: /sys/module/blktap/parameters/ */
+static unsigned int log_stats = 0;
+static unsigned int debug_lvl = 0;
+module_param(log_stats, int, 0644);
+module_param(debug_lvl, int, 0644);
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a 
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+ * the pendcnt towards zero. When it hits zero, the specified domain has a 
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+	blkif_t       *blkif;
+	u64            id;
+	unsigned short mem_idx;
+	int            nr_pages;
+	atomic_t       pendcnt;
+	unsigned short operation;
+	int            status;
+	struct list_head free_list;
+	int            inuse;
+} pending_req_t;
+
+static pending_req_t *pending_reqs[MAX_PENDING_REQS];
+static struct list_head pending_free;
+static DEFINE_SPINLOCK(pending_free_lock);
+static DECLARE_WAIT_QUEUE_HEAD (pending_free_wq);
+static int alloc_pending_reqs;
+
+typedef unsigned int PEND_RING_IDX;
+
+static inline int MASK_PEND_IDX(int i) { 
+	return (i & (MAX_PENDING_REQS-1));
+}
+
+static inline unsigned int RTN_PEND_IDX(pending_req_t *req, int idx) {
+	return (req - pending_reqs[idx]);
+}
+
+#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
+
+#define BLKBACK_INVALID_HANDLE (~0)
+
+static struct page **foreign_pages[MAX_DYNAMIC_MEM];
+static inline unsigned long idx_to_kaddr(
+	unsigned int mmap_idx, unsigned int req_idx, unsigned int sg_idx)
+{
+	unsigned int arr_idx = req_idx*BLKIF_MAX_SEGMENTS_PER_REQUEST + sg_idx;
+	unsigned long pfn = page_to_pfn(foreign_pages[mmap_idx][arr_idx]);
+	return (unsigned long)pfn_to_kaddr(pfn);
+}
+
+static unsigned short mmap_alloc = 0;
+static unsigned short mmap_lock = 0;
+static unsigned short mmap_inuse = 0;
+
+/******************************************************************
+ * GRANT HANDLES
+ */
+
+/* When using grant tables to map a frame for device access then the
+ * handle returned must be used to unmap the frame. This is needed to
+ * drop the ref count on the frame.
+ */
+struct grant_handle_pair
+{
+        grant_handle_t kernel;
+        grant_handle_t user;
+};
+#define INVALID_GRANT_HANDLE	0xFFFF
+
+static struct grant_handle_pair 
+    pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES];
+#define pending_handle(_id, _idx, _i) \
+    (pending_grant_handles[_id][((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) \
+    + (_i)])
+
+
+static int blktap_read_ufe_ring(tap_blkif_t *info); /*local prototypes*/
+
+#define BLKTAP_MINOR 0  /*/dev/xen/blktap has a dynamic major */
+#define BLKTAP_DEV_DIR  "/dev/xen"
+
+static int blktap_major;
+
+/* blktap IOCTLs: */
+#define BLKTAP_IOCTL_KICK_FE         1
+#define BLKTAP_IOCTL_KICK_BE         2 /* currently unused */
+#define BLKTAP_IOCTL_SETMODE         3
+#define BLKTAP_IOCTL_SENDPID	     4
+#define BLKTAP_IOCTL_NEWINTF	     5
+#define BLKTAP_IOCTL_MINOR	     6
+#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)             */
+#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
+#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
+#define BLKTAP_MODE_INTERCEPT_BE     0x00000002  /* unimp.             */
+
+#define BLKTAP_MODE_INTERPOSE \
+           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
+
+
+static inline int BLKTAP_MODE_VALID(unsigned long arg)
+{
+	return ((arg == BLKTAP_MODE_PASSTHROUGH ) ||
+		(arg == BLKTAP_MODE_INTERCEPT_FE) ||
+                (arg == BLKTAP_MODE_INTERPOSE   ));
+}
+
+/* Requests passing through the tap to userspace are re-assigned an ID.
+ * We must record a mapping between the BE [IDX,ID] tuple and the userspace
+ * ring ID. 
+ */
+
+static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
+{
+        return ((fe_dom << 16) | MASK_PEND_IDX(idx));
+}
+
+extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
+{
+        return (PEND_RING_IDX)(id & 0x0000ffff);
+}
+
+extern inline int ID_TO_MIDX(unsigned long id)
+{
+        return (int)(id >> 16);
+}
+
+#define INVALID_REQ 0xdead0000
+
+/*TODO: Convert to a free list*/
+static inline int GET_NEXT_REQ(unsigned long *idx_map)
+{
+	int i;
+	for (i = 0; i < MAX_PENDING_REQS; i++)
+		if (idx_map[i] == INVALID_REQ)
+			return i;
+
+	return INVALID_REQ;
+}
+
+static inline int OFFSET_TO_USR_IDX(int offset)
+{
+	return offset / BLKIF_MAX_SEGMENTS_PER_REQUEST;
+}
+
+static inline int OFFSET_TO_SEG(int offset)
+{
+	return offset % BLKIF_MAX_SEGMENTS_PER_REQUEST;
+}
+
+
+#define BLKTAP_INVALID_HANDLE(_g) \
+    (((_g->kernel) == INVALID_GRANT_HANDLE) &&  \
+     ((_g->user) == INVALID_GRANT_HANDLE))
+
+#define BLKTAP_INVALIDATE_HANDLE(_g) do {       \
+    (_g)->kernel = INVALID_GRANT_HANDLE; (_g)->user = INVALID_GRANT_HANDLE; \
+    } while(0)
+
+
+/******************************************************************
+ * BLKTAP VM OPS
+ */
+
+static int blktap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	/*
+	 * if the page has not been mapped in by the driver then return
+	 * VM_FAULT_SIGBUS to the domain.
+	 */
+
+	return VM_FAULT_SIGBUS;
+}
+
+static pte_t blktap_clear_pte(struct vm_area_struct *vma,
+			      unsigned long uvaddr,
+			      pte_t *ptep, int is_fullmm)
+{
+	pte_t copy;
+	tap_blkif_t *info = NULL;
+	int offset, seg, usr_idx, pending_idx, mmap_idx;
+	unsigned long uvstart = 0;
+	unsigned long kvaddr;
+	struct page *pg;
+	struct grant_handle_pair *khandle;
+	struct gnttab_unmap_grant_ref unmap[2];
+	int count = 0;
+
+	/*
+	 * If the address is before the start of the grant mapped region or
+	 * if vm_file is NULL (meaning mmap failed and we have nothing to do)
+	 */
+	if (vma->vm_file != NULL) {
+		info = vma->vm_file->private_data;
+		uvstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
+	}
+	if (vma->vm_file == NULL || uvaddr < uvstart)
+		return xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
+						   is_fullmm);
+
+	/* TODO Should these be changed to if statements? */
+	BUG_ON(!info);
+	BUG_ON(!info->idx_map);
+
+	offset = (int) ((uvaddr - uvstart) >> PAGE_SHIFT);
+	usr_idx = OFFSET_TO_USR_IDX(offset);
+	seg = OFFSET_TO_SEG(offset);
+
+	pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
+	mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
+
+	kvaddr = idx_to_kaddr(mmap_idx, pending_idx, seg);
+	pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+	ClearPageReserved(pg);
+	info->foreign_map.map[offset + RING_PAGES] = NULL;
+
+	khandle = &pending_handle(mmap_idx, pending_idx, seg);
+
+	if (khandle->kernel != INVALID_GRANT_HANDLE) {
+		gnttab_set_unmap_op(&unmap[count], kvaddr, 
+				    GNTMAP_host_map, khandle->kernel);
+		count++;
+
+		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, 
+				    INVALID_P2M_ENTRY);
+	}
+
+	if (khandle->user != INVALID_GRANT_HANDLE) {
+		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+
+		copy = *ptep;
+		gnttab_set_unmap_op(&unmap[count], ptep_to_machine(ptep),
+				    GNTMAP_host_map 
+				    | GNTMAP_application_map 
+				    | GNTMAP_contains_pte,
+				    khandle->user);
+		count++;
+	} else {
+		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap));
+
+		/* USING SHADOW PAGE TABLES. */
+		copy = xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
+						   is_fullmm);
+	}
+
+	if (count) {
+		BLKTAP_INVALIDATE_HANDLE(khandle);
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+					      unmap, count))
+			BUG();
+	}
+
+	return copy;
+}
+
+static void blktap_vma_open(struct vm_area_struct *vma)
+{
+	tap_blkif_t *info;
+	if (vma->vm_file == NULL)
+		return;
+
+	info = vma->vm_file->private_data;
+	vma->vm_private_data =
+		&info->foreign_map.map[(vma->vm_start - info->rings_vstart) >> PAGE_SHIFT];
+}
+
+/* tricky part
+ * When partial munmapping, ->open() is called only splitted vma which
+ * will be released soon. * See split_vma() and do_munmap() in mm/mmap.c
+ * So there is no chance to fix up vm_private_data of the end vma.
+ */
+static void blktap_vma_close(struct vm_area_struct *vma)
+{
+	tap_blkif_t *info;
+	struct vm_area_struct *next = vma->vm_next;
+
+	if (next == NULL ||
+	    vma->vm_ops != next->vm_ops ||
+	    vma->vm_end != next->vm_start ||
+	    vma->vm_file == NULL ||
+	    vma->vm_file != next->vm_file)
+		return;
+
+	info = vma->vm_file->private_data;
+	next->vm_private_data =
+		&info->foreign_map.map[(next->vm_start - info->rings_vstart) >> PAGE_SHIFT];
+}
+
+static struct vm_operations_struct blktap_vm_ops = {
+	fault:    blktap_fault,
+	zap_pte:  blktap_clear_pte,
+	open:     blktap_vma_open,
+	close:    blktap_vma_close,
+};
+
+/******************************************************************
+ * BLKTAP FILE OPS
+ */
+ 
+/*Function Declarations*/
+static tap_blkif_t *get_next_free_dev(void);
+static int blktap_open(struct inode *inode, struct file *filp);
+static int blktap_release(struct inode *inode, struct file *filp);
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma);
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg);
+static unsigned int blktap_poll(struct file *file, poll_table *wait);
+
+static const struct file_operations blktap_fops = {
+	.owner   = THIS_MODULE,
+	.poll    = blktap_poll,
+	.ioctl   = blktap_ioctl,
+	.open    = blktap_open,
+	.release = blktap_release,
+	.mmap    = blktap_mmap,
+};
+
+
+static tap_blkif_t *get_next_free_dev(void)
+{
+	struct class *class;
+	tap_blkif_t *info;
+	int minor;
+
+	/*
+	 * This is called only from the ioctl, which
+	 * means we should always have interrupts enabled.
+	 */
+	BUG_ON(irqs_disabled());
+
+	spin_lock_irq(&pending_free_lock);
+
+	/* tapfds[0] is always NULL */
+
+	for (minor = 1; minor < blktap_next_minor; minor++) {
+		info = tapfds[minor];
+		/* we could have failed a previous attempt. */
+		if (!info ||
+		    ((!test_bit(0, &info->dev_inuse)) &&
+		     (info->dev_pending == 0)) ) {
+			info->dev_pending = 1;
+			goto found;
+		}
+	}
+	info = NULL;
+	minor = -1;
+
+	/*
+	 * We didn't find free device. If we can still allocate
+	 * more, then we grab the next device minor that is
+	 * available.  This is done while we are still under
+	 * the protection of the pending_free_lock.
+	 */
+	if (blktap_next_minor < MAX_TAP_DEV)
+		minor = blktap_next_minor++;
+found:
+	spin_unlock_irq(&pending_free_lock);
+
+	if (!info && minor > 0) {
+		info = kzalloc(sizeof(*info), GFP_KERNEL);
+		if (unlikely(!info)) {
+			/*
+			 * If we failed here, try to put back
+			 * the next minor number. But if one
+			 * was just taken, then we just lose this
+			 * minor.  We can try to allocate this
+			 * minor again later.
+			 */
+			spin_lock_irq(&pending_free_lock);
+			if (blktap_next_minor == minor+1)
+				blktap_next_minor--;
+			spin_unlock_irq(&pending_free_lock);
+			goto out;
+		}
+
+		info->minor = minor;
+		/*
+		 * Make sure that we have a minor before others can
+		 * see us.
+		 */
+		wmb();
+		tapfds[minor] = info;
+
+		if ((class = get_xen_class()) != NULL)
+			device_create(class, NULL, MKDEV(blktap_major, minor),
+				      NULL, "blktap%d", minor);
+	}
+
+out:
+	return info;
+}
+
+int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif) 
+{
+	tap_blkif_t *info;
+	int i;
+
+	for (i = 1; i < blktap_next_minor; i++) {
+		info = tapfds[i];
+		if ( info &&
+		     (info->trans.domid == domid) &&
+		     (info->trans.busid == xenbus_id) ) {
+			info->blkif = blkif;
+			info->status = RUNNING;
+			return i;
+		}
+	}
+	return -1;
+}
+
+void signal_tapdisk(int idx) 
+{
+	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;
+
+	if (info->pid > 0) {
+		ptask = pid_task(find_pid_ns(info->pid, info->pid_ns),
+				 PIDTYPE_PID);
+		if (ptask)
+			info->status = CLEANSHUTDOWN;
+	}
+	info->blkif = NULL;
+
+	return;
+}
+
+static int blktap_open(struct inode *inode, struct file *filp)
+{
+	blkif_sring_t *sring;
+	int idx = iminor(inode) - BLKTAP_MINOR;
+	tap_blkif_t *info;
+	int i;
+	
+	/* ctrl device, treat differently */
+	if (!idx)
+		return 0;
+
+	info = tapfds[idx];
+
+	if ((idx < 0) || (idx > MAX_TAP_DEV) || !info) {
+		WPRINTK("Unable to open device /dev/xen/blktap%d\n",
+			idx);
+		return -ENODEV;
+	}
+
+	DPRINTK("Opening device /dev/xen/blktap%d\n",idx);
+	
+	/*Only one process can access device at a time*/
+	if (test_and_set_bit(0, &info->dev_inuse))
+		return -EBUSY;
+
+	info->dev_pending = 0;
+	    
+	/* Allocate the fe ring. */
+	sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+	if (sring == NULL)
+		goto fail_nomem;
+
+	SetPageReserved(virt_to_page(sring));
+    
+	SHARED_RING_INIT(sring);
+	FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE);
+	
+	filp->private_data = info;
+	info->mm = NULL;
+
+	info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, 
+				GFP_KERNEL);
+	
+	if (info->idx_map == NULL)
+		goto fail_nomem;
+
+	if (idx > 0) {
+		init_waitqueue_head(&info->wait);
+		for (i = 0; i < MAX_PENDING_REQS; i++) 
+			info->idx_map[i] = INVALID_REQ;
+	}
+
+	DPRINTK("Tap open: device /dev/xen/blktap%d\n",idx);
+	return 0;
+
+ fail_nomem:
+	return -ENOMEM;
+}
+
+static int blktap_release(struct inode *inode, struct file *filp)
+{
+	tap_blkif_t *info = filp->private_data;
+	
+	/* check for control device */
+	if (!info)
+		return 0;
+
+	info->ring_ok = 0;
+	smp_wmb();
+
+	mmput(info->mm);
+	info->mm = NULL;
+	kfree(info->foreign_map.map);
+	info->foreign_map.map = NULL;
+
+	/* Free the ring page. */
+	ClearPageReserved(virt_to_page(info->ufe_ring.sring));
+	free_page((unsigned long) info->ufe_ring.sring);
+
+	if (info->idx_map) {
+		kfree(info->idx_map);
+		info->idx_map = NULL;
+	}
+
+	if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) {
+		if (info->blkif->xenblkd != NULL) {
+			kthread_stop(info->blkif->xenblkd);
+			info->blkif->xenblkd = NULL;
+		}
+		info->status = CLEANSHUTDOWN;
+	}
+
+	clear_bit(0, &info->dev_inuse);
+	DPRINTK("Freeing device [/dev/xen/blktap%d]\n",info->minor);
+
+	return 0;
+}
+
+
+/* Note on mmap:
+ * We need to map pages to user space in a way that will allow the block
+ * subsystem set up direct IO to them.  This couldn't be done before, because
+ * there isn't really a sane way to translate a user virtual address down to a 
+ * physical address when the page belongs to another domain.
+ *
+ * My first approach was to map the page in to kernel memory, add an entry
+ * for it in the physical frame list (using alloc_lomem_region as in blkback)
+ * and then attempt to map that page up to user space.  This is disallowed
+ * by xen though, which realizes that we don't really own the machine frame
+ * underlying the physical page.
+ *
+ * The new approach is to provide explicit support for this in xen linux.
+ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
+ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
+ * from pages to actual page structs.  There is a new clause in get_user_pages
+ * that does the right thing for this sort of mapping.
+ */
+static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int size;
+	tap_blkif_t *info = filp->private_data;
+	int ret;
+
+	if (info == NULL) {
+		WPRINTK("blktap: mmap, retrieving idx failed\n");
+		return -ENOMEM;
+	}
+	
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_ops = &blktap_vm_ops;
+
+	size = vma->vm_end - vma->vm_start;
+	if (size != ((mmap_pages + RING_PAGES) << PAGE_SHIFT)) {
+		WPRINTK("you _must_ map exactly %d pages!\n",
+		       mmap_pages + RING_PAGES);
+		return -EAGAIN;
+	}
+
+	size >>= PAGE_SHIFT;
+	info->rings_vstart = vma->vm_start;
+	info->user_vstart  = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
+    
+	/* Map the ring pages to the start of the region and reserve it. */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		ret = vm_insert_page(vma, vma->vm_start,
+				     virt_to_page(info->ufe_ring.sring));
+	else
+		ret = remap_pfn_range(vma, vma->vm_start,
+				      __pa(info->ufe_ring.sring) >> PAGE_SHIFT,
+				      PAGE_SIZE, vma->vm_page_prot);
+	if (ret) {
+		WPRINTK("Mapping user ring failed!\n");
+		goto fail;
+	}
+
+	/* Mark this VM as containing foreign pages, and set up mappings. */
+	info->foreign_map.map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) *
+			    sizeof(*info->foreign_map.map), GFP_KERNEL);
+	if (info->foreign_map.map == NULL) {
+		WPRINTK("Couldn't alloc VM_FOREIGN map.\n");
+		goto fail;
+	}
+
+	vma->vm_private_data = &info->foreign_map;
+	vma->vm_flags |= VM_FOREIGN;
+	vma->vm_flags |= VM_DONTCOPY;
+
+#ifdef CONFIG_X86
+	vma->vm_mm->context.has_foreign_mappings = 1;
+#endif
+
+	info->mm = get_task_mm(current);
+	smp_wmb();
+	info->ring_ok = 1;
+	return 0;
+ fail:
+	/* Clear any active mappings. */
+	zap_page_range(vma, vma->vm_start, 
+		       vma->vm_end - vma->vm_start, NULL);
+
+	return -ENOMEM;
+}
+
+
+static int blktap_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg)
+{
+	tap_blkif_t *info = filp->private_data;
+
+	switch(cmd) {
+	case BLKTAP_IOCTL_KICK_FE: 
+	{
+		/* There are fe messages to process. */
+		return blktap_read_ufe_ring(info);
+	}
+	case BLKTAP_IOCTL_SETMODE:
+	{
+		if (info) {
+			if (BLKTAP_MODE_VALID(arg)) {
+				info->mode = arg;
+				/* XXX: may need to flush rings here. */
+				DPRINTK("blktap: set mode to %lx\n", 
+				       arg);
+				return 0;
+			}
+		}
+		return 0;
+	}
+	case BLKTAP_IOCTL_PRINT_IDXS:
+        {
+		if (info) {
+			printk("User Rings: \n-----------\n");
+			printk("UF: rsp_cons: %2d, req_prod_prv: %2d "
+				"| req_prod: %2d, rsp_prod: %2d\n",
+				info->ufe_ring.rsp_cons,
+				info->ufe_ring.req_prod_pvt,
+				info->ufe_ring.sring->req_prod,
+				info->ufe_ring.sring->rsp_prod);
+		}
+            	return 0;
+        }
+	case BLKTAP_IOCTL_SENDPID:
+	{
+		if (info) {
+			info->pid = (pid_t)arg;
+			info->pid_ns = current->nsproxy->pid_ns;
+			DPRINTK("blktap: pid received %p:%d\n",
+			        info->pid_ns, info->pid);
+		}
+		return 0;
+	}
+	case BLKTAP_IOCTL_NEWINTF:
+	{		
+		uint64_t val = (uint64_t)arg;
+		domid_translate_t *tr = (domid_translate_t *)&val;
+
+		DPRINTK("NEWINTF 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_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;
+		unsigned long flags;
+
+		info = tapfds[dev];
+
+		if ((dev > MAX_TAP_DEV) || !info)
+			return 0; /* should this be an error? */
+
+		spin_lock_irqsave(&pending_free_lock, flags);
+		if (info->dev_pending)
+			info->dev_pending = 0;
+		spin_unlock_irqrestore(&pending_free_lock, flags);
+
+		return 0;
+	}
+	case BLKTAP_IOCTL_MINOR:
+	{
+		unsigned long dev = arg;
+
+		info = tapfds[dev];
+
+		if ((dev > MAX_TAP_DEV) || !info)
+			return -EINVAL;
+
+		return info->minor;
+	}
+	case BLKTAP_IOCTL_MAJOR:
+		return blktap_major;
+
+	case BLKTAP_QUERY_ALLOC_REQS:
+	{
+		WPRINTK("BLKTAP_QUERY_ALLOC_REQS ioctl: %d/%d\n",
+		       alloc_pending_reqs, blkif_reqs);
+		return (alloc_pending_reqs/blkif_reqs) * 100;
+	}
+	}
+	return -ENOIOCTLCMD;
+}
+
+static unsigned int blktap_poll(struct file *filp, poll_table *wait)
+{
+	tap_blkif_t *info = filp->private_data;
+	
+	/* do not work on the control device */
+	if (!info)
+		return 0;
+
+	poll_wait(filp, &info->wait, wait);
+	if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) {
+		RING_PUSH_REQUESTS(&info->ufe_ring);
+		return POLLIN | POLLRDNORM;
+	}
+	return 0;
+}
+
+static void blktap_kick_user(int idx)
+{
+	tap_blkif_t *info;
+
+	info = tapfds[idx];
+
+	if ((idx < 0) || (idx > MAX_TAP_DEV) || !info)
+		return;
+
+	wake_up_interruptible(&info->wait);
+
+	return;
+}
+
+static int do_block_io_op(blkif_t *blkif);
+static void dispatch_rw_block_io(blkif_t *blkif,
+				 blkif_request_t *req,
+				 pending_req_t *pending_req);
+static void make_response(blkif_t *blkif, u64 id,
+                          unsigned short op, int st);
+
+/******************************************************************
+ * misc small helpers
+ */
+static int req_increase(void)
+{
+	int i, j;
+
+	if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) 
+		return -EINVAL;
+
+	pending_reqs[mmap_alloc]  = kzalloc(sizeof(pending_req_t)
+					    * blkif_reqs, GFP_KERNEL);
+	foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages);
+
+	if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc])
+		goto out_of_memory;
+
+	DPRINTK("%s: reqs=%d, pages=%d\n",
+		__FUNCTION__, blkif_reqs, mmap_pages);
+
+	for (i = 0; i < MAX_PENDING_REQS; i++) {
+		list_add_tail(&pending_reqs[mmap_alloc][i].free_list, 
+			      &pending_free);
+		pending_reqs[mmap_alloc][i].mem_idx = mmap_alloc;
+		for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+			BLKTAP_INVALIDATE_HANDLE(&pending_handle(mmap_alloc, 
+								 i, j));
+	}
+
+	mmap_alloc++;
+	DPRINTK("# MMAPs increased to %d\n",mmap_alloc);
+	return 0;
+
+ out_of_memory:
+	free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
+	kfree(pending_reqs[mmap_alloc]);
+	WPRINTK("%s: out of memory\n", __FUNCTION__);
+	return -ENOMEM;
+}
+
+static void mmap_req_del(int mmap)
+{
+	assert_spin_locked(&pending_free_lock);
+
+	kfree(pending_reqs[mmap]);
+	pending_reqs[mmap] = NULL;
+
+	free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
+	foreign_pages[mmap] = NULL;
+
+	mmap_lock = 0;
+	DPRINTK("# MMAPs decreased to %d\n",mmap_alloc);
+	mmap_alloc--;
+}
+
+static pending_req_t* alloc_req(void)
+{
+	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);
+	}
+
+	if (req) {
+		req->inuse = 1;
+		alloc_pending_reqs++;
+	}
+	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);
+
+	alloc_pending_reqs--;
+	req->inuse = 0;
+	if (mmap_lock && (req->mem_idx == mmap_alloc-1)) {
+		mmap_inuse--;
+		if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1);
+		spin_unlock_irqrestore(&pending_free_lock, flags);
+		return;
+	}
+	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 blktap_zap_page_range(struct mm_struct *mm,
+				  unsigned long uvaddr, int nr_pages)
+{
+	unsigned long end = uvaddr + (nr_pages << PAGE_SHIFT);
+	struct vm_area_struct *vma;
+
+	vma = find_vma(mm, uvaddr);
+	while (vma && uvaddr < end) {
+		unsigned long s = max(uvaddr, vma->vm_start);
+		unsigned long e = min(end, vma->vm_end);
+
+		zap_page_range(vma, s, e - s, NULL);
+
+		uvaddr = e;
+		vma = vma->vm_next;
+	}
+}
+
+static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx,
+			    int tapidx)
+{
+	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+	unsigned int i, invcount = 0, locked = 0;
+	struct grant_handle_pair *khandle;
+	uint64_t ptep;
+	int ret, mmap_idx;
+	unsigned long kvaddr, uvaddr;
+	tap_blkif_t *info;
+	struct mm_struct *mm;
+	
+
+	info = tapfds[tapidx];
+
+	if ((tapidx < 0) || (tapidx > MAX_TAP_DEV) || !info) {
+		WPRINTK("fast_flush: Couldn't get info!\n");
+		return;
+	}
+
+	mm = info->mm;
+
+	if (mm != NULL && xen_feature(XENFEAT_auto_translated_physmap)) {
+		down_write(&mm->mmap_sem);
+		blktap_zap_page_range(mm,
+				      MMAP_VADDR(info->user_vstart, u_idx, 0),
+				      req->nr_pages);
+		up_write(&mm->mmap_sem);
+		return;
+	}
+
+	mmap_idx = req->mem_idx;
+
+	for (i = 0; i < req->nr_pages; i++) {
+		kvaddr = idx_to_kaddr(mmap_idx, k_idx, i);
+		uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i);
+
+		khandle = &pending_handle(mmap_idx, k_idx, i);
+
+		if (khandle->kernel != INVALID_GRANT_HANDLE) {
+			gnttab_set_unmap_op(&unmap[invcount],
+					    idx_to_kaddr(mmap_idx, k_idx, i),
+					    GNTMAP_host_map, khandle->kernel);
+			invcount++;
+
+			set_phys_to_machine(
+				__pa(idx_to_kaddr(mmap_idx, k_idx, i))
+				>> PAGE_SHIFT, INVALID_P2M_ENTRY);
+		}
+
+		if (khandle->user != INVALID_GRANT_HANDLE) {
+			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+			if (!locked++)
+				down_write(&mm->mmap_sem);
+			if (create_lookup_pte_addr(
+				mm,
+				MMAP_VADDR(info->user_vstart, u_idx, i),
+				&ptep) !=0) {
+				up_write(&mm->mmap_sem);
+				WPRINTK("Couldn't get a pte addr!\n");
+				return;
+			}
+
+			gnttab_set_unmap_op(&unmap[invcount], ptep,
+					    GNTMAP_host_map
+					    | GNTMAP_application_map
+					    | GNTMAP_contains_pte,
+					    khandle->user);
+			invcount++;
+		}
+
+		BLKTAP_INVALIDATE_HANDLE(khandle);
+	}
+	ret = HYPERVISOR_grant_table_op(
+		GNTTABOP_unmap_grant_ref, unmap, invcount);
+	BUG_ON(ret);
+	
+	if (mm != NULL && !xen_feature(XENFEAT_auto_translated_physmap)) {
+		if (!locked++)
+			down_write(&mm->mmap_sem);
+		blktap_zap_page_range(mm, 
+				      MMAP_VADDR(info->user_vstart, u_idx, 0), 
+				      req->nr_pages);
+	}
+
+	if (locked)
+		up_write(&mm->mmap_sem);
+}
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static void print_stats(blkif_t *blkif)
+{
+	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d |  pk %4d\n",
+	       current->comm, blkif->st_oo_req,
+	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_pk_req);
+	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
+	blkif->st_rd_req = 0;
+	blkif->st_wr_req = 0;
+	blkif->st_oo_req = 0;
+	blkif->st_pk_req = 0;
+}
+
+int tap_blkif_schedule(void *arg)
+{
+	blkif_t *blkif = arg;
+
+	blkif_get(blkif);
+
+	if (debug_lvl)
+		printk(KERN_DEBUG "%s: started\n", current->comm);
+
+	while (!kthread_should_stop()) {
+		if (try_to_freeze())
+			continue;
+
+		wait_event_interruptible(
+			blkif->wq,
+			blkif->waiting_reqs || kthread_should_stop());
+		wait_event_interruptible(
+			pending_free_wq,
+			!list_empty(&pending_free) || kthread_should_stop());
+
+		blkif->waiting_reqs = 0;
+		smp_mb(); /* clear flag *before* checking for work */
+
+		if (do_block_io_op(blkif))
+			blkif->waiting_reqs = 1;
+
+		if (log_stats && time_after(jiffies, blkif->st_print))
+			print_stats(blkif);
+	}
+
+	if (log_stats)
+		print_stats(blkif);
+	if (debug_lvl)
+		printk(KERN_DEBUG "%s: exiting\n", current->comm);
+
+	blkif->xenblkd = NULL;
+	blkif_put(blkif);
+
+	return 0;
+}
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called by user level ioctl()
+ */
+
+static int blktap_read_ufe_ring(tap_blkif_t *info)
+{
+	/* This is called to read responses from the UFE ring. */
+	RING_IDX i, j, rp;
+	blkif_response_t *resp;
+	blkif_t *blkif=NULL;
+	int pending_idx, usr_idx, mmap_idx;
+	pending_req_t *pending_req;
+	
+	if (!info)
+		return 0;
+
+	/* We currently only forward packets in INTERCEPT_FE mode. */
+	if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE))
+		return 0;
+
+	/* for each outstanding message on the UFEring  */
+	rp = info->ufe_ring.sring->rsp_prod;
+	rmb();
+        
+	for (i = info->ufe_ring.rsp_cons; i != rp; i++) {
+		blkif_response_t res;
+		resp = RING_GET_RESPONSE(&info->ufe_ring, i);
+		memcpy(&res, resp, sizeof(res));
+		mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */
+		++info->ufe_ring.rsp_cons;
+
+		/*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/
+		usr_idx = (int)res.id;
+		pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
+		mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
+
+		if ( (mmap_idx >= mmap_alloc) || 
+		   (ID_TO_IDX(info->idx_map[usr_idx]) >= MAX_PENDING_REQS) )
+			WPRINTK("Incorrect req map"
+			       "[%d], internal map [%d,%d (%d)]\n", 
+			       usr_idx, mmap_idx, 
+			       ID_TO_IDX(info->idx_map[usr_idx]),
+			       MASK_PEND_IDX(
+				       ID_TO_IDX(info->idx_map[usr_idx])));
+
+		pending_req = &pending_reqs[mmap_idx][pending_idx];
+		blkif = pending_req->blkif;
+
+		for (j = 0; j < pending_req->nr_pages; j++) {
+
+			unsigned long kvaddr, uvaddr;
+			struct page *pg;
+			int offset;
+
+			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, j);
+			kvaddr = idx_to_kaddr(mmap_idx, pending_idx, j);
+
+			pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+			ClearPageReserved(pg);
+			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
+			info->foreign_map.map[offset] = NULL;
+		}
+		fast_flush_area(pending_req, pending_idx, usr_idx, info->minor);
+		info->idx_map[usr_idx] = INVALID_REQ;
+		make_response(blkif, pending_req->id, res.operation,
+			      res.status);
+		blkif_put(pending_req->blkif);
+		free_req(pending_req);
+	}
+		
+	return 0;
+}
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+static void blkif_notify_work(blkif_t *blkif)
+{
+	blkif->waiting_reqs = 1;
+	wake_up(&blkif->wq);
+}
+
+irqreturn_t tap_blkif_be_int(int irq, void *dev_id)
+{
+	blkif_notify_work(dev_id);
+	return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+static int print_dbug = 1;
+static int do_block_io_op(blkif_t *blkif)
+{
+	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
+	blkif_request_t req;
+	pending_req_t *pending_req;
+	RING_IDX rc, rp;
+	int more_to_do = 0;
+	tap_blkif_t *info;
+
+	rc = blk_rings->common.req_cons;
+	rp = blk_rings->common.sring->req_prod;
+	rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+	/*Check blkif has corresponding UE ring*/
+	if (blkif->dev_num < 0) {
+		/*oops*/
+		if (print_dbug) {
+			WPRINTK("Corresponding UE " 
+			       "ring does not exist!\n");
+			print_dbug = 0; /*We only print this message once*/
+		}
+		return 0;
+	}
+
+	info = tapfds[blkif->dev_num];
+
+	if (blkif->dev_num > MAX_TAP_DEV || !info ||
+	    !test_bit(0, &info->dev_inuse)) {
+		if (print_dbug) {
+			WPRINTK("Can't get UE info!\n");
+			print_dbug = 0;
+		}
+		return 0;
+	}
+
+	while (rc != rp) {
+		
+		if (RING_FULL(&info->ufe_ring)) {
+			WPRINTK("RING_FULL! More to do\n");
+			more_to_do = 1;
+			break;
+		}
+
+		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) {
+			WPRINTK("RING_REQUEST_CONS_OVERFLOW!"
+			       " More to do\n");
+			more_to_do = 1;
+			break;		
+		}
+
+		if (kthread_should_stop()) {
+			more_to_do = 1;
+			break;
+		}
+
+		pending_req = alloc_req();
+		if (NULL == pending_req) {
+			blkif->st_oo_req++;
+			more_to_do = 1;
+			break;
+		}
+
+		switch (blkif->blk_protocol) {
+		case BLKIF_PROTOCOL_NATIVE:
+			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc),
+			       sizeof(req));
+			break;
+		case BLKIF_PROTOCOL_X86_32:
+			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
+			break;
+		case BLKIF_PROTOCOL_X86_64:
+			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
+			break;
+		default:
+			BUG();
+		}
+		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++;
+			dispatch_rw_block_io(blkif, &req, pending_req);
+			break;
+
+		case BLKIF_OP_WRITE_BARRIER:
+			/* TODO Some counter? */
+			/* Fall through */
+		case BLKIF_OP_WRITE:
+			blkif->st_wr_req++;
+			dispatch_rw_block_io(blkif, &req, pending_req);
+			break;
+
+		case BLKIF_OP_PACKET:
+			blkif->st_pk_req++;
+			dispatch_rw_block_io(blkif, &req, pending_req);
+			break;
+
+		default:
+			/* A good sign something is wrong: sleep for a while to
+			 * avoid excessive CPU consumption by a bad guest. */
+			msleep(1);
+			WPRINTK("unknown operation [%d]\n",
+				req.operation);
+			make_response(blkif, req.id, req.operation,
+				      BLKIF_RSP_ERROR);
+			free_req(pending_req);
+			break;
+		}
+
+		/* Yield point for this unbounded loop. */
+		cond_resched();
+	}
+		
+	blktap_kick_user(blkif->dev_num);
+
+	return more_to_do;
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif,
+				 blkif_request_t *req,
+				 pending_req_t *pending_req)
+{
+	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+	int op, operation;
+	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+	unsigned int nseg;
+	int ret, i, nr_sects = 0;
+	tap_blkif_t *info;
+	blkif_request_t *target;
+	int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
+	int usr_idx;
+	uint16_t mmap_idx = pending_req->mem_idx;
+	struct mm_struct *mm;
+	struct vm_area_struct *vma = NULL;
+
+	switch (req->operation) {
+	case BLKIF_OP_PACKET:
+		/* Fall through */
+	case BLKIF_OP_READ:
+		operation = READ;
+		break;
+	case BLKIF_OP_WRITE:
+		operation = WRITE;
+		break;
+	case BLKIF_OP_WRITE_BARRIER:
+		operation = WRITE_BARRIER;
+		break;
+	default:
+		operation = 0; /* make gcc happy */
+		BUG();
+	}
+
+	if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
+		goto fail_response;
+
+	info = tapfds[blkif->dev_num];
+	if (info == NULL)
+		goto fail_response;
+
+	/* Check we have space on user ring - should never fail. */
+	usr_idx = GET_NEXT_REQ(info->idx_map);
+	if (usr_idx == INVALID_REQ) {
+		BUG();
+		goto fail_response;
+	}
+
+	/* Check that number of segments is sane. */
+	nseg = req->nr_segments;
+	if ( unlikely(nseg == 0) || 
+	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) {
+		WPRINTK("Bad number of segments in request (%d)\n", nseg);
+		goto fail_response;
+	}
+	
+	/* Make sure userspace is ready. */
+	if (!info->ring_ok) {
+		WPRINTK("blktap: ring not ready for requests!\n");
+		goto fail_response;
+	}
+	smp_rmb();
+
+	if (RING_FULL(&info->ufe_ring)) {
+		WPRINTK("blktap: fe_ring is full, can't add "
+			"IO Request will be dropped. %d %d\n",
+			RING_SIZE(&info->ufe_ring),
+			RING_SIZE(&blkif->blk_rings.common));
+		goto fail_response;
+	}
+
+	pending_req->blkif     = blkif;
+	pending_req->id        = req->id;
+	pending_req->operation = req->operation;
+	pending_req->status    = BLKIF_RSP_OKAY;
+	pending_req->nr_pages  = nseg;
+	op = 0;
+	mm = info->mm;
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		down_write(&mm->mmap_sem);
+	for (i = 0; i < nseg; i++) {
+		unsigned long uvaddr;
+		unsigned long kvaddr;
+		uint64_t ptep;
+		uint32_t flags;
+
+		uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
+		kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+
+		flags = GNTMAP_host_map;
+		if (operation != READ)
+			flags |= GNTMAP_readonly;
+		gnttab_set_map_op(&map[op], kvaddr, flags,
+				  req->seg[i].gref, blkif->domid);
+		op++;
+
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+			/* Now map it to user. */
+			ret = create_lookup_pte_addr(mm, uvaddr, &ptep);
+			if (ret) {
+				up_write(&mm->mmap_sem);
+				WPRINTK("Couldn't get a pte addr!\n");
+				goto fail_flush;
+			}
+
+			flags = GNTMAP_host_map | GNTMAP_application_map
+				| GNTMAP_contains_pte;
+			if (operation != READ)
+				flags |= GNTMAP_readonly;
+			gnttab_set_map_op(&map[op], ptep, flags,
+					  req->seg[i].gref, blkif->domid);
+			op++;
+		}
+
+		nr_sects += (req->seg[i].last_sect - 
+			     req->seg[i].first_sect + 1);
+	}
+
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op);
+	BUG_ON(ret);
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+		up_write(&mm->mmap_sem);
+
+		for (i = 0; i < (nseg*2); i+=2) {
+			unsigned long uvaddr;
+			unsigned long kvaddr;
+			unsigned long offset;
+			struct page *pg;
+
+			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);
+			kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i/2);
+
+			if (unlikely(map[i].status != 0)) {
+				WPRINTK("invalid kernel buffer -- "
+					"could not remap it\n");
+				ret |= 1;
+				map[i].handle = INVALID_GRANT_HANDLE;
+			}
+
+			if (unlikely(map[i+1].status != 0)) {
+				WPRINTK("invalid user buffer -- "
+					"could not remap it\n");
+				ret |= 1;
+				map[i+1].handle = INVALID_GRANT_HANDLE;
+			}
+
+			pending_handle(mmap_idx, pending_idx, i/2).kernel 
+				= map[i].handle;
+			pending_handle(mmap_idx, pending_idx, i/2).user   
+				= map[i+1].handle;
+
+			if (ret)
+				continue;
+
+			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+					    FOREIGN_FRAME(map[i].dev_bus_addr
+							  >> PAGE_SHIFT));
+			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
+			pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+			info->foreign_map.map[offset] = pg;
+		}
+	} else {
+		for (i = 0; i < nseg; i++) {
+			unsigned long uvaddr;
+			unsigned long kvaddr;
+			unsigned long offset;
+			struct page *pg;
+
+			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
+			kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+
+			if (unlikely(map[i].status != 0)) {
+				WPRINTK("invalid kernel buffer -- "
+					"could not remap it\n");
+				ret |= 1;
+				map[i].handle = INVALID_GRANT_HANDLE;
+			}
+
+			pending_handle(mmap_idx, pending_idx, i).kernel 
+				= map[i].handle;
+
+			if (ret)
+				continue;
+
+			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
+			pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+			info->foreign_map.map[offset] = pg;
+		}
+	}
+
+	if (ret)
+		goto fail_flush;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		down_write(&mm->mmap_sem);
+	/* Mark mapped pages as reserved: */
+	for (i = 0; i < req->nr_segments; i++) {
+		unsigned long kvaddr;
+		struct page *pg;
+
+		kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+		pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+		SetPageReserved(pg);
+		if (xen_feature(XENFEAT_auto_translated_physmap)) {
+			unsigned long uvaddr = MMAP_VADDR(info->user_vstart,
+							  usr_idx, i);
+			if (vma && uvaddr >= vma->vm_end) {
+				vma = vma->vm_next;
+				if (vma &&
+				    (uvaddr < vma->vm_start ||
+				     uvaddr >= vma->vm_end))
+					vma = NULL;
+			}
+			if (vma == NULL) {
+				vma = find_vma(mm, uvaddr);
+				/* this virtual area was already munmapped.
+				   so skip to next page */
+				if (!vma)
+					continue;
+			}
+			ret = vm_insert_page(vma, uvaddr, pg);
+			if (ret) {
+				up_write(&mm->mmap_sem);
+				goto fail_flush;
+			}
+		}
+	}
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		up_write(&mm->mmap_sem);
+	
+	/*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
+	info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
+
+	blkif_get(blkif);
+	/* Finally, write the request message to the user ring. */
+	target = RING_GET_REQUEST(&info->ufe_ring,
+				  info->ufe_ring.req_prod_pvt);
+	memcpy(target, req, sizeof(*req));
+	target->id = usr_idx;
+	wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
+	info->ufe_ring.req_prod_pvt++;
+
+	if (operation == READ)
+		blkif->st_rd_sect += nr_sects;
+	else if (operation == WRITE)
+		blkif->st_wr_sect += nr_sects;
+
+	return;
+
+ fail_flush:
+	WPRINTK("Reached Fail_flush\n");
+	fast_flush_area(pending_req, pending_idx, usr_idx, blkif->dev_num);
+ fail_response:
+	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+	free_req(pending_req);
+	msleep(1); /* back off a bit */
+}
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, u64 id,
+                          unsigned short op, int st)
+{
+	blkif_response_t  resp;
+	unsigned long     flags;
+	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
+	int more_to_do = 0;
+	int notify;
+
+	resp.id        = id;
+	resp.operation = op;
+	resp.status    = st;
+
+	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+	/* Place on the response ring for the relevant domain. */
+	switch (blkif->blk_protocol) {
+	case BLKIF_PROTOCOL_NATIVE:
+		memcpy(RING_GET_RESPONSE(&blk_rings->native,
+					 blk_rings->native.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	case BLKIF_PROTOCOL_X86_32:
+		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32,
+					 blk_rings->x86_32.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	case BLKIF_PROTOCOL_X86_64:
+		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64,
+					 blk_rings->x86_64.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	default:
+		BUG();
+	}
+	blk_rings->common.rsp_prod_pvt++;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
+
+	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
+		/*
+		 * Tail check for pending requests. Allows frontend to avoid
+		 * notifications if requests are already in flight (lower
+		 * overheads and promotes batching).
+		 */
+		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
+	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
+		more_to_do = 1;
+	}
+
+	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+	if (more_to_do)
+		blkif_notify_work(blkif);
+	if (notify)
+		notify_remote_via_irq(blkif->irq);
+}
+
+static int __init blkif_init(void)
+{
+	int i, ret;
+	struct class *class;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	INIT_LIST_HEAD(&pending_free);
+        for(i = 0; i < 2; i++) {
+		ret = req_increase();
+		if (ret)
+			break;
+	}
+	if (i == 0)
+		return ret;
+
+	tap_blkif_interface_init();
+
+	alloc_pending_reqs = 0;
+
+	tap_blkif_xenbus_init();
+
+	/* Dynamically allocate a major for this device */
+	ret = register_chrdev(0, "blktap", &blktap_fops);
+
+	if (ret < 0) {
+		WPRINTK("Couldn't register /dev/xen/blktap\n");
+		return -ENOMEM;
+	}	
+	
+	blktap_major = ret;
+
+	/* tapfds[0] is always NULL */
+	blktap_next_minor++;
+
+	DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i);
+
+	/* Make sure the xen class exists */
+	if ((class = get_xen_class()) != NULL) {
+		/*
+		 * This will allow udev to create the blktap ctrl device.
+		 * We only want to create blktap0 first.  We don't want
+		 * to flood the sysfs system with needless blktap devices.
+		 * We only create the device when a request of a new device is
+		 * made.
+		 */
+		device_create(class, NULL, MKDEV(blktap_major, 0), NULL,
+			      "blktap0");
+	} else {
+		/* this is bad, but not fatal */
+		WPRINTK("blktap: sysfs xen_class not created\n");
+	}
+
+	DPRINTK("Blktap device successfully created\n");
+
+	return 0;
+}
+
+module_init(blkif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/char/Makefile
+++ linux-ec2-2.6.32/drivers/xen/char/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_XEN_DEVMEM)	:= mem.o
--- linux-ec2-2.6.32.orig/drivers/xen/char/mem.c
+++ linux-ec2-2.6.32/drivers/xen/char/mem.c
@@ -0,0 +1,231 @@
+/*
+ *  Originally from linux/drivers/char/mem.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Added devfs support. 
+ *    Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
+ *  Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mman.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/raw.h>
+#include <linux/tty.h>
+#include <linux/capability.h>
+#include <linux/ptrace.h>
+#include <linux/device.h>
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hypervisor.h>
+
+static inline int uncached_access(struct file *file)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+	/* Xen sets correct MTRR type on non-RAM for us. */
+	return 0;
+}
+
+static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+{
+#ifdef CONFIG_STRICT_DEVMEM
+	u64 from = ((u64)pfn) << PAGE_SHIFT;
+	u64 to = from + size;
+	u64 cursor = from;
+
+	while (cursor < to) {
+		if (!devmem_is_allowed(pfn)) {
+			printk(KERN_INFO
+		"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+				current->comm, from, to);
+			return 0;
+		}
+		cursor += PAGE_SIZE;
+		pfn++;
+	}
+#endif
+	return 1;
+}
+
+/*
+ * This funcion reads the *physical* memory. The f_pos points directly to the 
+ * memory location. 
+ */
+static ssize_t read_mem(struct file * file, char __user * buf,
+			size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos, ignored;
+	ssize_t read = 0, sz;
+	void __iomem *v;
+
+	while (count > 0) {
+		/*
+		 * Handle first page in case it's not aligned
+		 */
+		if (-p & (PAGE_SIZE - 1))
+			sz = -p & (PAGE_SIZE - 1);
+		else
+			sz = PAGE_SIZE;
+
+		sz = min_t(unsigned long, sz, count);
+
+		if (!range_is_allowed(p >> PAGE_SHIFT, count))
+			return -EPERM;
+
+		v = ioremap(p, sz);
+		if (IS_ERR(v) || v == NULL) {
+			/*
+			 * Some programs (e.g., dmidecode) groove off into
+			 * weird RAM areas where no tables can possibly exist
+			 * (because Xen will have stomped on them!). These
+			 * programs get rather upset if we let them know that
+			 * Xen failed their access, so we fake out a read of
+			 * all zeroes.
+			 */
+			if (clear_user(buf, count))
+				return -EFAULT;
+			read += count;
+			break;
+		}
+
+		ignored = copy_to_user(buf, v, sz);
+		iounmap(v);
+		if (ignored)
+			return -EFAULT;
+		buf += sz;
+		p += sz;
+		count -= sz;
+		read += sz;
+	}
+
+	*ppos += read;
+	return read;
+}
+
+static ssize_t write_mem(struct file * file, const char __user * buf, 
+			 size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos, ignored;
+	ssize_t written = 0, sz;
+	void __iomem *v;
+
+	while (count > 0) {
+		/*
+		 * Handle first page in case it's not aligned
+		 */
+		if (-p & (PAGE_SIZE - 1))
+			sz = -p & (PAGE_SIZE - 1);
+		else
+			sz = PAGE_SIZE;
+
+		sz = min_t(unsigned long, sz, count);
+
+		if (!range_is_allowed(p >> PAGE_SHIFT, sz))
+			return -EPERM;
+
+		v = ioremap(p, sz);
+		if (v == NULL)
+			break;
+		if (IS_ERR(v)) {
+			if (written == 0)
+				return PTR_ERR(v);
+			break;
+		}
+
+		ignored = copy_from_user(v, buf, sz);
+		iounmap(v);
+		if (ignored) {
+			written += sz - ignored;
+			if (written)
+				break;
+			return -EFAULT;
+		}
+		buf += sz;
+		p += sz;
+		count -= sz;
+		written += sz;
+	}
+
+	*ppos += written;
+	return written;
+}
+
+#ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
+static struct vm_operations_struct mmap_mem_ops = {
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+	.access = generic_access_phys
+#endif
+};
+
+static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma)
+{
+	size_t size = vma->vm_end - vma->vm_start;
+
+	if (uncached_access(file))
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (!range_is_allowed(vma->vm_pgoff, size))
+		return -EPERM;
+
+	if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
+						&vma->vm_page_prot))
+		return -EINVAL;
+
+	vma->vm_ops = &mmap_mem_ops;
+
+	/* We want to return the real error code, not EAGAIN. */
+	return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				      size, vma->vm_page_prot, DOMID_IO);
+}
+#endif
+
+/*
+ * The memory devices use the full 32/64 bits of the offset, and so we cannot
+ * check against negative addresses: they are ok. The return value is weird,
+ * though, in that case (0).
+ *
+ * also note that seeking relative to the "end of file" isn't supported:
+ * it has no meaning, so it returns -EINVAL.
+ */
+static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
+{
+	loff_t ret;
+
+	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+	switch (orig) {
+		case 0:
+			file->f_pos = offset;
+			ret = file->f_pos;
+			force_successful_syscall_return();
+			break;
+		case 1:
+			file->f_pos += offset;
+			ret = file->f_pos;
+			force_successful_syscall_return();
+			break;
+		default:
+			ret = -EINVAL;
+	}
+	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+	return ret;
+}
+
+static int open_mem(struct inode * inode, struct file * filp)
+{
+	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+const struct file_operations mem_fops = {
+	.llseek		= memory_lseek,
+	.read		= read_mem,
+	.write		= write_mem,
+	.mmap		= xen_mmap_mem,
+	.open		= open_mem,
+};
--- linux-ec2-2.6.32.orig/drivers/xen/gntdev/Makefile
+++ linux-ec2-2.6.32/drivers/xen/gntdev/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_XEN_GRANT_DEV) := gntdev.o
--- linux-ec2-2.6.32.orig/drivers/xen/gntdev/gntdev.c
+++ linux-ec2-2.6.32/drivers/xen/gntdev/gntdev.c
@@ -0,0 +1,1075 @@
+/******************************************************************************
+ * gntdev.c
+ * 
+ * Device for accessing (in user-space) pages that have been granted by other
+ * domains.
+ *
+ * Copyright (c) 2006-2007, D G Murray.
+ * 
+ * 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 <asm/atomic.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <xen/gnttab.h>
+#include <asm/hypervisor.h>
+#include <xen/balloon.h>
+#include <xen/evtchn.h>
+#include <xen/driver_util.h>
+
+#include <linux/types.h>
+#include <xen/public/gntdev.h>
+
+
+#define DRIVER_AUTHOR "Derek G. Murray <Derek.Murray@cl.cam.ac.uk>"
+#define DRIVER_DESC   "User-space granted page access driver"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+#define MAX_GRANTS_LIMIT   1024
+#define DEFAULT_MAX_GRANTS 128
+
+/* A slot can be in one of three states:
+ *
+ * 0. GNTDEV_SLOT_INVALID:
+ *    This slot is not associated with a grant reference, and is therefore free
+ *    to be overwritten by a new grant reference.
+ *
+ * 1. GNTDEV_SLOT_NOT_YET_MAPPED:
+ *    This slot is associated with a grant reference (via the 
+ *    IOCTL_GNTDEV_MAP_GRANT_REF ioctl), but it has not yet been mmap()-ed.
+ *
+ * 2. GNTDEV_SLOT_MAPPED:
+ *    This slot is associated with a grant reference, and has been mmap()-ed.
+ */
+typedef enum gntdev_slot_state {
+	GNTDEV_SLOT_INVALID = 0,
+	GNTDEV_SLOT_NOT_YET_MAPPED,
+	GNTDEV_SLOT_MAPPED
+} gntdev_slot_state_t;
+
+#define GNTDEV_INVALID_HANDLE    -1
+#define GNTDEV_FREE_LIST_INVALID -1
+/* Each opened instance of gntdev is associated with a list of grants,
+ * represented by an array of elements of the following type,
+ * gntdev_grant_info_t.
+ */
+typedef struct gntdev_grant_info {
+	gntdev_slot_state_t state;
+	union {
+		uint32_t free_list_index;
+		struct {
+			domid_t domid;
+			grant_ref_t ref;
+			grant_handle_t kernel_handle;
+			grant_handle_t user_handle;
+			uint64_t dev_bus_addr;
+		} valid;
+	} u;
+} gntdev_grant_info_t;
+
+/* Private data structure, which is stored in the file pointer for files
+ * associated with this device.
+ */
+typedef struct gntdev_file_private_data {
+  
+	/* Array of grant information. */
+	gntdev_grant_info_t *grants;
+	uint32_t grants_size;
+
+	/* Read/write semaphore used to protect the grants array. */
+	struct rw_semaphore grants_sem;
+
+	/* An array of indices of free slots in the grants array.
+	 * N.B. An entry in this list may temporarily have the value
+	 * GNTDEV_FREE_LIST_INVALID if the corresponding slot has been removed
+	 * from the list by the contiguous allocator, but the list has not yet
+	 * been compressed. However, this is not visible across invocations of
+	 * the device.
+	 */
+	int32_t *free_list;
+	
+	/* The number of free slots in the grants array. */
+	uint32_t free_list_size;
+
+	/* Read/write semaphore used to protect the free list. */
+	struct rw_semaphore free_list_sem;
+	
+	/* Index of the next slot after the most recent contiguous allocation, 
+	 * for use in a next-fit allocator.
+	 */
+	uint32_t next_fit_index;
+
+	/* Used to map grants into the kernel, before mapping them into user
+	 * space.
+	 */
+	struct page **foreign_pages;
+
+} gntdev_file_private_data_t;
+
+/* Module lifecycle operations. */
+static int __init gntdev_init(void);
+static void __exit gntdev_exit(void);
+
+module_init(gntdev_init);
+module_exit(gntdev_exit);
+
+/* File operations. */
+static int gntdev_open(struct inode *inode, struct file *flip);
+static int gntdev_release(struct inode *inode, struct file *flip);
+static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma);
+static long gntdev_ioctl(struct file *flip,
+			 unsigned int cmd, unsigned long arg);
+
+static const struct file_operations gntdev_fops = {
+	.owner = THIS_MODULE,
+	.open = gntdev_open,
+	.release = gntdev_release,
+	.mmap = gntdev_mmap,
+	.unlocked_ioctl = gntdev_ioctl
+};
+
+/* VM operations. */
+static void gntdev_vma_close(struct vm_area_struct *vma);
+static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t *ptep, int is_fullmm);
+
+static struct vm_operations_struct gntdev_vmops = {
+	.close = gntdev_vma_close,
+	.zap_pte = gntdev_clear_pte
+};
+
+/* Global variables. */
+
+/* The driver major number, for use when unregistering the driver. */
+static int gntdev_major;
+
+#define GNTDEV_NAME "gntdev"
+
+/* Memory mapping functions
+ * ------------------------
+ *
+ * Every granted page is mapped into both kernel and user space, and the two
+ * following functions return the respective virtual addresses of these pages.
+ *
+ * When shadow paging is disabled, the granted page is mapped directly into
+ * user space; when it is enabled, it is mapped into the kernel and remapped
+ * into user space using vm_insert_page() (see gntdev_mmap(), below).
+ */
+
+/* Returns the virtual address (in user space) of the @page_index'th page
+ * in the given VM area.
+ */
+static inline unsigned long get_user_vaddr (struct vm_area_struct *vma,
+					    int page_index)
+{
+	return (unsigned long) vma->vm_start + (page_index << PAGE_SHIFT);
+}
+
+/* Returns the virtual address (in kernel space) of the @slot_index'th page
+ * mapped by the gntdev instance that owns the given private data struct.
+ */
+static inline unsigned long get_kernel_vaddr (gntdev_file_private_data_t *priv,
+					      int slot_index)
+{
+	unsigned long pfn;
+	void *kaddr;
+	pfn = page_to_pfn(priv->foreign_pages[slot_index]);
+	kaddr = pfn_to_kaddr(pfn);
+	return (unsigned long) kaddr;
+}
+
+/* Helper functions. */
+
+/* Adds information about a grant reference to the list of grants in the file's
+ * private data structure. Returns non-zero on failure. On success, sets the
+ * value of *offset to the offset that should be mmap()-ed in order to map the
+ * grant reference.
+ */
+static int add_grant_reference(struct file *flip,
+			       struct ioctl_gntdev_grant_ref *op,
+			       uint64_t *offset)
+{
+	gntdev_file_private_data_t *private_data 
+		= (gntdev_file_private_data_t *) flip->private_data;
+
+	uint32_t slot_index;
+
+	if (unlikely(private_data->free_list_size == 0)) {
+		return -ENOMEM;
+	}
+
+	slot_index = private_data->free_list[--private_data->free_list_size];
+	private_data->free_list[private_data->free_list_size]
+		= GNTDEV_FREE_LIST_INVALID;
+
+	/* Copy the grant information into file's private data. */
+	private_data->grants[slot_index].state = GNTDEV_SLOT_NOT_YET_MAPPED;
+	private_data->grants[slot_index].u.valid.domid = op->domid;
+	private_data->grants[slot_index].u.valid.ref = op->ref;
+
+	/* The offset is calculated as the index of the chosen entry in the
+	 * file's private data's array of grant information. This is then
+	 * shifted to give an offset into the virtual "file address space".
+	 */
+	*offset = slot_index << PAGE_SHIFT;
+
+	return 0;
+}
+
+/* Adds the @count grant references to the contiguous range in the slot array
+ * beginning at @first_slot. It is assumed that @first_slot was returned by a
+ * previous invocation of find_contiguous_free_range(), during the same
+ * invocation of the driver.
+ */
+static int add_grant_references(struct file *flip,
+				int count,
+				struct ioctl_gntdev_grant_ref *ops,
+				uint32_t first_slot)
+{
+	gntdev_file_private_data_t *private_data 
+		= (gntdev_file_private_data_t *) flip->private_data;
+	int i;
+	
+	for (i = 0; i < count; ++i) {
+
+		/* First, mark the slot's entry in the free list as invalid. */
+		int free_list_index = 
+			private_data->grants[first_slot+i].u.free_list_index;
+		private_data->free_list[free_list_index] = 
+			GNTDEV_FREE_LIST_INVALID;
+
+		/* Now, update the slot. */
+		private_data->grants[first_slot+i].state = 
+			GNTDEV_SLOT_NOT_YET_MAPPED;
+		private_data->grants[first_slot+i].u.valid.domid =
+			ops[i].domid;
+		private_data->grants[first_slot+i].u.valid.ref = ops[i].ref;
+	}
+
+	return 0;	
+}
+
+/* Scans through the free list for @flip, removing entries that are marked as
+ * GNTDEV_SLOT_INVALID. This will reduce the recorded size of the free list to
+ * the number of valid entries.
+ */
+static void compress_free_list(struct file *flip) 
+{
+	gntdev_file_private_data_t *private_data 
+		= (gntdev_file_private_data_t *) flip->private_data;
+	int i, j = 0, old_size, slot_index;
+	
+	old_size = private_data->free_list_size;
+	for (i = 0; i < old_size; ++i) {
+		if (private_data->free_list[i] != GNTDEV_FREE_LIST_INVALID) {
+			if (i > j) {
+				slot_index = private_data->free_list[i];
+				private_data->free_list[j] = slot_index;
+				private_data->grants[slot_index].u
+					.free_list_index = j;
+				private_data->free_list[i] 
+					= GNTDEV_FREE_LIST_INVALID;
+			}
+			++j;
+		} else {
+			--private_data->free_list_size;
+		}
+	}
+}
+
+/* Searches the grant array in the private data of @flip for a range of
+ * @num_slots contiguous slots in the GNTDEV_SLOT_INVALID state.
+ *
+ * Returns the index of the first slot if a range is found, otherwise -ENOMEM.
+ */
+static int find_contiguous_free_range(struct file *flip,
+				      uint32_t num_slots) 
+{
+	gntdev_file_private_data_t *private_data 
+		= (gntdev_file_private_data_t *) flip->private_data;
+	
+	int i;
+	int start_index = private_data->next_fit_index;
+	int range_start = 0, range_length;
+
+	if (private_data->free_list_size < num_slots) {
+		return -ENOMEM;
+	}
+
+	/* First search from the start_index to the end of the array. */
+	range_length = 0;
+	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;
+			}
+			++range_length;
+			if (range_length == num_slots) {
+				return range_start;
+			}
+		}
+	}
+	
+	/* Now search from the start of the array to the start_index. */
+	range_length = 0;
+	for (i = 0; i < start_index; ++i) {
+		if (private_data->grants[i].state == GNTDEV_SLOT_INVALID) {
+			if (range_length == 0) {
+				range_start = i;
+			}
+			++range_length;
+			if (range_length == num_slots) {
+				return range_start;
+			}
+		}
+	}
+	
+	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. */
+static int __init gntdev_init(void)
+{
+	struct class *class;
+	struct device *device;
+
+	if (!is_running_on_xen()) {
+		printk(KERN_ERR "You must be running Xen to use gntdev\n");
+		return -ENODEV;
+	}
+
+	gntdev_major = register_chrdev(0, GNTDEV_NAME, &gntdev_fops);
+	if (gntdev_major < 0)
+	{
+		printk(KERN_ERR "Could not register gntdev device\n");
+		return -ENOMEM;
+	}
+
+	/* Note that if the sysfs code fails, we will still initialise the
+	 * device, and output the major number so that the device can be
+	 * created manually using mknod.
+	 */
+	if ((class = get_xen_class()) == NULL) {
+		printk(KERN_ERR "Error setting up xen_class\n");
+		printk(KERN_ERR "gntdev created with major number = %d\n", 
+		       gntdev_major);
+		return 0;
+	}
+
+	device = device_create(class, NULL, MKDEV(gntdev_major, 0),
+			       NULL, GNTDEV_NAME);
+	if (IS_ERR(device)) {
+		printk(KERN_ERR "Error creating gntdev device in xen_class\n");
+		printk(KERN_ERR "gntdev created with major number = %d\n",
+		       gntdev_major);
+		return 0;
+	}
+
+	return 0;
+}
+
+/* Cleans up and unregisters the driver. Called when the driver is unloaded.
+ */
+static void __exit gntdev_exit(void)
+{
+	struct class *class;
+	if ((class = get_xen_class()) != NULL)
+		device_destroy(class, MKDEV(gntdev_major, 0));
+	unregister_chrdev(gntdev_major, GNTDEV_NAME);
+}
+
+/* Called when the device is opened. */
+static int gntdev_open(struct inode *inode, struct file *flip)
+{
+	gntdev_file_private_data_t *private_data;
+
+	try_module_get(THIS_MODULE);
+
+	/* Allocate space for the per-instance private data. */
+	private_data = kmalloc(sizeof(*private_data), GFP_KERNEL);
+	if (!private_data)
+		goto nomem_out;
+
+	/* 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);
+
+	flip->private_data = private_data;
+
+	return 0;
+
+nomem_out:
+	return -ENOMEM;
+}
+
+/* Called when the device is closed.
+ */
+static int gntdev_release(struct inode *inode, struct file *flip)
+{
+	if (flip->private_data) {
+		gntdev_file_private_data_t *private_data = 
+			(gntdev_file_private_data_t *) flip->private_data;
+		if (private_data->foreign_pages)
+			free_empty_pages_and_pagevec
+				(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);
+	return 0;
+}
+
+/* Called when an attempt is made to mmap() the device. The private data from
+ * @flip contains the list of grant references that can be mapped. The vm_pgoff
+ * field of @vma contains the index into that list that refers to the grant
+ * reference that will be mapped. Only mappings that are a multiple of
+ * PAGE_SIZE are handled.
+ */
+static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) 
+{
+	struct gnttab_map_grant_ref op;
+	unsigned long slot_index = vma->vm_pgoff;
+	unsigned long kernel_vaddr, user_vaddr;
+	uint32_t size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	uint64_t ptep;
+	int ret;
+	int flags;
+	int i;
+	struct page *page;
+	gntdev_file_private_data_t *private_data = flip->private_data;
+
+	if (unlikely(!private_data)) {
+		printk(KERN_ERR "File's private data is NULL.\n");
+		return -EINVAL;
+	}
+
+	/* 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);
+		return -ENXIO;
+	}
+
+	if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+		printk(KERN_ERR "Writable mappings must be shared.\n");
+		return -EINVAL;
+	}
+
+	/* Slots must be in the NOT_YET_MAPPED state. */
+	down_write(&private_data->grants_sem);
+	for (i = 0; i < size; ++i) {
+		if (private_data->grants[slot_index + i].state != 
+		    GNTDEV_SLOT_NOT_YET_MAPPED) {
+			printk(KERN_ERR "Slot (index = %ld) is in the wrong "
+			       "state (%d).\n", slot_index + i, 
+			       private_data->grants[slot_index + i].state);
+			up_write(&private_data->grants_sem);
+			return -EINVAL;
+		}
+	}
+
+	/* Install the hook for unmapping. */
+	vma->vm_ops = &gntdev_vmops;
+    
+	/* The VM area contains pages from another VM. */
+	vma->vm_flags |= VM_FOREIGN;
+	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 "
+		       "area.\n");
+		return -ENOMEM;
+	}
+
+	/* This flag prevents Bad PTE errors when the memory is unmapped. */
+	vma->vm_flags |= VM_RESERVED;
+
+	/* This flag prevents this VM area being copied on a fork(). A better
+	 * behaviour might be to explicitly carry out the appropriate mappings
+	 * on fork(), but I don't know if there's a hook for this.
+	 */
+	vma->vm_flags |= VM_DONTCOPY;
+
+#ifdef CONFIG_X86
+	/* This flag ensures that the page tables are not unpinned before the
+	 * VM area is unmapped. Therefore Xen still recognises the PTE as
+	 * belonging to an L1 pagetable, and the grant unmap operation will
+	 * succeed, even if the process does not exit cleanly.
+	 */
+	vma->vm_mm->context.has_foreign_mappings = 1;
+#endif
+
+	for (i = 0; i < size; ++i) {
+
+		flags = GNTMAP_host_map;
+		if (!(vma->vm_flags & VM_WRITE))
+			flags |= GNTMAP_readonly;
+
+		kernel_vaddr = get_kernel_vaddr(private_data, slot_index + i);
+		user_vaddr = get_user_vaddr(vma, i);
+		page = pfn_to_page(__pa(kernel_vaddr) >> PAGE_SHIFT);
+
+		gnttab_set_map_op(&op, kernel_vaddr, flags,   
+				  private_data->grants[slot_index+i]
+				  .u.valid.ref, 
+				  private_data->grants[slot_index+i]
+				  .u.valid.domid);
+
+		/* Carry out the mapping of the grant reference. */
+		ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, 
+						&op, 1);
+		BUG_ON(ret);
+		if (op.status) {
+			printk(KERN_ERR "Error mapping the grant reference "
+			       "into the kernel (%d). domid = %d; ref = %d\n",
+			       op.status,
+			       private_data->grants[slot_index+i]
+			       .u.valid.domid,
+			       private_data->grants[slot_index+i]
+			       .u.valid.ref);
+			goto undo_map_out;
+		}
+
+		/* Store a reference to the page that will be mapped into user
+		 * space.
+		 */
+		((struct page **) vma->vm_private_data)[i] = page;
+
+		/* Mark mapped page as reserved. */
+		SetPageReserved(page);
+
+		/* Record the grant handle, for use in the unmap operation. */
+		private_data->grants[slot_index+i].u.valid.kernel_handle = 
+			op.handle;
+		private_data->grants[slot_index+i].u.valid.dev_bus_addr = 
+			op.dev_bus_addr;
+		
+		private_data->grants[slot_index+i].state = GNTDEV_SLOT_MAPPED;
+		private_data->grants[slot_index+i].u.valid.user_handle =
+			GNTDEV_INVALID_HANDLE;
+
+		/* Now perform the mapping to user space. */
+		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+
+			/* NOT USING SHADOW PAGE TABLES. */
+			/* In this case, we map the grant(s) straight into user
+			 * space.
+			 */
+
+			/* Get the machine address of the PTE for the user 
+			 *  page.
+			 */
+			if ((ret = create_lookup_pte_addr(vma->vm_mm, 
+							  vma->vm_start 
+							  + (i << PAGE_SHIFT), 
+							  &ptep)))
+			{
+				printk(KERN_ERR "Error obtaining PTE pointer "
+				       "(%d).\n", ret);
+				goto undo_map_out;
+			}
+			
+			/* Configure the map operation. */
+		
+			/* The reference is to be used by host CPUs. */
+			flags = GNTMAP_host_map;
+			
+			/* Specifies a user space mapping. */
+			flags |= GNTMAP_application_map;
+			
+			/* The map request contains the machine address of the
+			 * PTE to update.
+			 */
+			flags |= GNTMAP_contains_pte;
+			
+			if (!(vma->vm_flags & VM_WRITE))
+				flags |= GNTMAP_readonly;
+
+			gnttab_set_map_op(&op, ptep, flags, 
+					  private_data->grants[slot_index+i]
+					  .u.valid.ref, 
+					  private_data->grants[slot_index+i]
+					  .u.valid.domid);
+
+			/* Carry out the mapping of the grant reference. */
+			ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+							&op, 1);
+			BUG_ON(ret);
+			if (op.status) {
+				printk(KERN_ERR "Error mapping the grant "
+				       "reference into user space (%d). domid "
+				       "= %d; ref = %d\n", op.status,
+				       private_data->grants[slot_index+i].u
+				       .valid.domid,
+				       private_data->grants[slot_index+i].u
+				       .valid.ref);
+				goto undo_map_out;
+			}
+			
+			/* Record the grant handle, for use in the unmap 
+			 * operation. 
+			 */
+			private_data->grants[slot_index+i].u.
+				valid.user_handle = op.handle;
+
+			/* Update p2m structure with the new mapping. */
+			set_phys_to_machine(__pa(kernel_vaddr) >> PAGE_SHIFT,
+					    FOREIGN_FRAME(private_data->
+							  grants[slot_index+i]
+							  .u.valid.dev_bus_addr
+							  >> PAGE_SHIFT));
+		} else {
+			/* USING SHADOW PAGE TABLES. */
+			/* In this case, we simply insert the page into the VM
+			 * area. */
+			ret = vm_insert_page(vma, user_vaddr, page);
+		}
+
+	}
+
+	up_write(&private_data->grants_sem);
+	return 0;
+
+undo_map_out:
+	/* If we have a mapping failure, the unmapping will be taken care of
+	 * by do_mmap_pgoff(), which will eventually call gntdev_clear_pte().
+	 * All we need to do here is free the vma_private_data.
+	 */
+	kfree(vma->vm_private_data);
+
+	/* THIS IS VERY UNPLEASANT: do_mmap_pgoff() will set the vma->vm_file
+	 * to NULL on failure. However, we need this in gntdev_clear_pte() to
+	 * unmap the grants. Therefore, we smuggle a reference to the file's
+	 * private data in the VM area's private data pointer.
+	 */
+	vma->vm_private_data = private_data;
+	
+	up_write(&private_data->grants_sem);
+
+	return -ENOMEM;
+}
+
+static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t *ptep, int is_fullmm)
+{
+	int slot_index, ret;
+	pte_t copy;
+	struct gnttab_unmap_grant_ref op;
+	gntdev_file_private_data_t *private_data;
+
+	/* THIS IS VERY UNPLEASANT: do_mmap_pgoff() will set the vma->vm_file
+	 * to NULL on failure. However, we need this in gntdev_clear_pte() to
+	 * unmap the grants. Therefore, we smuggle a reference to the file's
+	 * private data in the VM area's private data pointer.
+	 */
+	if (vma->vm_file) {
+		private_data = (gntdev_file_private_data_t *)
+			vma->vm_file->private_data;
+	} else if (vma->vm_private_data) {
+		private_data = (gntdev_file_private_data_t *)
+			vma->vm_private_data;
+	} else {
+		private_data = NULL; /* gcc warning */
+		BUG();
+	}
+
+	/* Calculate the grant relating to this PTE. */
+	slot_index = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
+
+	/* Only unmap grants if the slot has been mapped. This could be being
+	 * called from a failing mmap().
+	 */
+	if (private_data->grants[slot_index].state == GNTDEV_SLOT_MAPPED) {
+
+		/* First, we clear the user space mapping, if it has been made.
+		 */
+		if (private_data->grants[slot_index].u.valid.user_handle !=
+		    GNTDEV_INVALID_HANDLE && 
+		    !xen_feature(XENFEAT_auto_translated_physmap)) {
+			/* NOT USING SHADOW PAGE TABLES. */
+
+			/* Copy the existing value of the PTE for returning. */
+			copy = *ptep;
+
+			gnttab_set_unmap_op(&op, ptep_to_machine(ptep), 
+					    GNTMAP_contains_pte,
+					    private_data->grants[slot_index]
+					    .u.valid.user_handle);
+			ret = HYPERVISOR_grant_table_op(
+				GNTTABOP_unmap_grant_ref, &op, 1);
+			BUG_ON(ret);
+			if (op.status)
+				printk("User unmap grant status = %d\n", 
+				       op.status);
+		} else {
+			/* USING SHADOW PAGE TABLES. */
+			copy = xen_ptep_get_and_clear_full(vma, addr, ptep, is_fullmm);
+		}
+
+		/* Finally, we unmap the grant from kernel space. */
+		gnttab_set_unmap_op(&op, 
+				    get_kernel_vaddr(private_data, slot_index),
+				    GNTMAP_host_map, 
+				    private_data->grants[slot_index].u.valid
+				    .kernel_handle);
+		ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 
+						&op, 1);
+		BUG_ON(ret);
+		if (op.status)
+			printk("Kernel unmap grant status = %d\n", op.status);
+
+
+		/* Return slot to the not-yet-mapped state, so that it may be
+		 * mapped again, or removed by a subsequent ioctl.
+		 */
+		private_data->grants[slot_index].state = 
+			GNTDEV_SLOT_NOT_YET_MAPPED;
+
+		/* Invalidate the physical to machine mapping for this page. */
+		set_phys_to_machine(__pa(get_kernel_vaddr(private_data, 
+							  slot_index)) 
+				    >> PAGE_SHIFT, INVALID_P2M_ENTRY);
+
+	} else {
+		copy = xen_ptep_get_and_clear_full(vma, addr, ptep, is_fullmm);
+	}
+
+	return copy;
+}
+
+/* "Destructor" for a VM area.
+ */
+static void gntdev_vma_close(struct vm_area_struct *vma) {
+	if (vma->vm_private_data) {
+		kfree(vma->vm_private_data);
+	}
+}
+
+/* Called when an ioctl is made on the device.
+ */
+static long gntdev_ioctl(struct file *flip,
+			 unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	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:
+	{
+		struct ioctl_gntdev_map_grant_ref op;
+		down_write(&private_data->grants_sem);
+		down_write(&private_data->free_list_sem);
+
+		if ((rc = copy_from_user(&op, (void __user *) arg, 
+					 sizeof(op)))) {
+			rc = -EFAULT;
+			goto map_out;
+		}
+		if (unlikely(op.count <= 0)) {
+			rc = -EINVAL;
+			goto map_out;
+		}
+
+		if (op.count == 1) {
+			if ((rc = add_grant_reference(flip, &op.refs[0],
+						      &op.index)) < 0) {
+				printk(KERN_ERR "Adding grant reference "
+				       "failed (%d).\n", rc);
+				goto map_out;
+			}
+		} else {
+			struct ioctl_gntdev_grant_ref *refs, *u;
+			refs = kmalloc(op.count * sizeof(*refs), GFP_KERNEL);
+			if (!refs) {
+				rc = -ENOMEM;
+				goto map_out;
+			}
+			u = ((struct ioctl_gntdev_map_grant_ref *)arg)->refs;
+			if ((rc = copy_from_user(refs,
+						 (void __user *)u,
+						 sizeof(*refs) * op.count))) {
+				printk(KERN_ERR "Copying refs from user failed"
+				       " (%d).\n", rc);
+				rc = -EINVAL;
+				goto map_out;
+			}
+			if ((rc = find_contiguous_free_range(flip, op.count))
+			    < 0) {
+				printk(KERN_ERR "Finding contiguous range "
+				       "failed (%d).\n", rc);
+				kfree(refs);
+				goto map_out;
+			}
+			op.index = rc << PAGE_SHIFT;
+			if ((rc = add_grant_references(flip, op.count,
+						       refs, rc))) {
+				printk(KERN_ERR "Adding grant references "
+				       "failed (%d).\n", rc);
+				kfree(refs);
+				goto map_out;
+			}
+			compress_free_list(flip);
+			kfree(refs);
+		}
+		if ((rc = copy_to_user((void __user *) arg, 
+				       &op, 
+				       sizeof(op)))) {
+			printk(KERN_ERR "Copying result back to user failed "
+			       "(%d)\n", rc);
+			rc = -EFAULT;
+			goto map_out;
+		}
+	map_out:
+		up_write(&private_data->grants_sem);
+		up_write(&private_data->free_list_sem);
+		return rc;
+	}
+	case IOCTL_GNTDEV_UNMAP_GRANT_REF:
+	{
+		struct ioctl_gntdev_unmap_grant_ref op;
+		int i, start_index;
+
+		down_write(&private_data->grants_sem);
+		down_write(&private_data->free_list_sem);
+
+		if ((rc = copy_from_user(&op, 
+					 (void __user *) arg, 
+					 sizeof(op)))) {
+			rc = -EFAULT;
+			goto unmap_out;
+		}
+
+		start_index = op.index >> PAGE_SHIFT;
+
+		/* First, check that all pages are in the NOT_YET_MAPPED
+		 * state.
+		 */
+		for (i = 0; i < op.count; ++i) {
+			if (unlikely
+			    (private_data->grants[start_index + i].state
+			     != GNTDEV_SLOT_NOT_YET_MAPPED)) {
+				if (private_data->grants[start_index + i].state
+				    == GNTDEV_SLOT_INVALID) {
+					printk(KERN_ERR
+					       "Tried to remove an invalid "
+					       "grant at offset 0x%x.",
+					       (start_index + i) 
+					       << PAGE_SHIFT);
+					rc = -EINVAL;
+				} else {
+					printk(KERN_ERR
+					       "Tried to remove a grant which "
+					       "is currently mmap()-ed at "
+					       "offset 0x%x.",
+					       (start_index + i) 
+					       << PAGE_SHIFT);
+					rc = -EBUSY;
+				}
+				goto unmap_out;
+			}
+		}
+
+		/* Unmap pages and add them to the free list.
+		 */
+		for (i = 0; i < op.count; ++i) {
+			private_data->grants[start_index+i].state = 
+				GNTDEV_SLOT_INVALID;
+			private_data->grants[start_index+i].u.free_list_index =
+				private_data->free_list_size;
+			private_data->free_list[private_data->free_list_size] =
+				start_index + i;
+			++private_data->free_list_size;
+		}
+
+	unmap_out:
+		up_write(&private_data->grants_sem);
+		up_write(&private_data->free_list_sem);
+		return rc;
+	}
+	case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR:
+	{
+		struct ioctl_gntdev_get_offset_for_vaddr op;
+		struct vm_area_struct *vma;
+		unsigned long vaddr;
+
+		if ((rc = copy_from_user(&op, 
+					 (void __user *) arg, 
+					 sizeof(op)))) {
+			rc = -EFAULT;
+			goto get_offset_out;
+		}
+		vaddr = (unsigned long)op.vaddr;
+
+		down_read(&current->mm->mmap_sem);		
+		vma = find_vma(current->mm, vaddr);
+		if (vma == NULL) {
+			rc = -EFAULT;
+			goto get_offset_unlock_out;
+		}
+		if ((!vma->vm_ops) || (vma->vm_ops != &gntdev_vmops)) {
+			printk(KERN_ERR "The vaddr specified does not belong "
+			       "to a gntdev instance: %#lx\n", vaddr);
+			rc = -EFAULT;
+			goto get_offset_unlock_out;
+		}
+		if (vma->vm_start != vaddr) {
+			printk(KERN_ERR "The vaddr specified in an "
+			       "IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR must be at "
+			       "the start of the VM area. vma->vm_start = "
+			       "%#lx; vaddr = %#lx\n",
+			       vma->vm_start, vaddr);
+			rc = -EFAULT;
+			goto get_offset_unlock_out;
+		}
+		op.offset = vma->vm_pgoff << PAGE_SHIFT;
+		op.count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+		up_read(&current->mm->mmap_sem);
+		if ((rc = copy_to_user((void __user *) arg, 
+				       &op, 
+				       sizeof(op)))) {
+			rc = -EFAULT;
+			goto get_offset_out;
+		}
+		goto get_offset_out;
+	get_offset_unlock_out:
+		up_read(&current->mm->mmap_sem);
+	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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/core/machine_kexec.c
+++ linux-ec2-2.6.32/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,267 @@
+/*
+ * drivers/xen/core/machine_kexec.c 
+ * handle transition of Linux booting another kernel
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/reboot.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+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;
+	struct resource *res;
+	int k = 0;
+	int rc;
+
+	if (strstr(boot_command_line, "crashkernel="))
+		printk(KERN_WARNING "Ignoring crashkernel command line, "
+		       "parameter will be supplied by xen\n");
+
+	if (!is_initial_xendomain())
+		return;
+
+	/* determine maximum number of physical cpus */
+
+	while (1) {
+		memset(&range, 0, sizeof(range));
+		range.range = KEXEC_RANGE_MA_CPU;
+		range.nr = k;
+
+		if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
+			break;
+
+		k++;
+	}
+
+	if (k == 0)
+		return;
+
+	xen_max_nr_phys_cpus = k;
+
+	/* allocate xen_phys_cpus */
+
+	xen_phys_cpus = alloc_bootmem(k * sizeof(struct resource));
+
+	/* fill in xen_phys_cpus with per-cpu crash note information */
+
+	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
+		memset(&range, 0, sizeof(range));
+		range.range = KEXEC_RANGE_MA_CPU;
+		range.nr = k;
+
+		if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
+			goto err;
+
+		res = xen_phys_cpus + k;
+
+		memset(res, 0, sizeof(*res));
+		res->name = "Crash note";
+		res->start = range.start;
+		res->end = range.start + range.size - 1;
+		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+	}
+
+	/* fill in xen_hypervisor_res with hypervisor machine address range */
+
+	memset(&range, 0, sizeof(range));
+	range.range = KEXEC_RANGE_MA_XEN;
+
+	if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
+		goto err;
+
+	xen_hypervisor_res.name = "Hypervisor code and data";
+	xen_hypervisor_res.start = range.start;
+	xen_hypervisor_res.end = range.start + range.size - 1;
+	xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+#ifdef CONFIG_X86
+	insert_resource(&iomem_resource, &xen_hypervisor_res);
+#endif
+
+	/* fill in crashk_res if range is reserved by hypervisor */
+
+	memset(&range, 0, sizeof(range));
+	range.range = KEXEC_RANGE_MA_CRASH;
+
+	if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
+		goto err;
+
+	if (range.size) {
+		crashk_res.start = range.start;
+		crashk_res.end = range.start + range.size - 1;
+#ifdef CONFIG_X86
+		insert_resource(&iomem_resource, &crashk_res);
+#endif
+	}
+
+	/* get physical address of vmcoreinfo */
+	memset(&range, 0, sizeof(range));
+	range.range = KEXEC_RANGE_MA_VMCOREINFO;
+
+	rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
+
+	if (rc == 0) {
+		/* Hypercall succeeded */
+		vmcoreinfo_size_xen = range.size;
+		paddr_vmcoreinfo_xen = range.start;
+
+	} else {
+		/* Hypercall failed.
+		 * Indicate not to create sysfs file by resetting globals
+		 */
+		vmcoreinfo_size_xen = 0;
+		paddr_vmcoreinfo_xen = 0;
+		
+		/* The KEXEC_CMD_kexec_get_range hypercall did not implement
+		 * KEXEC_RANGE_MA_VMCOREINFO until Xen 3.3.
+		 * Do not bail out if it fails for this reason.
+		 */
+		if (rc != -EINVAL)
+			return;
+	}
+
+	if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
+					  xen_max_nr_phys_cpus))
+		goto err;
+
+#ifdef CONFIG_X86
+	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
+		res = xen_phys_cpus + k;
+		if (!res->parent) /* outside of xen_hypervisor_res range */
+			insert_resource(&iomem_resource, res);
+	}
+
+	if (xen_create_contiguous_region((unsigned long)&vmcoreinfo_note,
+					 get_order(sizeof(vmcoreinfo_note)),
+					 BITS_PER_LONG))
+		goto err;
+#endif
+
+	return;
+
+ err:
+	/*
+	 * It isn't possible to free xen_phys_cpus this early in the
+	 * boot. Failure at this stage is unexpected and the amount of
+	 * memory is small therefore we tolerate the potential leak.
+         */
+	xen_max_nr_phys_cpus = 0;
+	return;
+}
+
+#ifndef CONFIG_X86
+void __init xen_machine_kexec_register_resources(struct resource *res)
+{
+	int k;
+	struct resource *r;
+
+	request_resource(res, &xen_hypervisor_res);
+	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
+		r = xen_phys_cpus + k;
+		if (r->parent == NULL) /* out of xen_hypervisor_res range */
+			request_resource(res, r);
+	} 
+	machine_kexec_register_resources(res);
+}
+#endif
+
+static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+{
+	machine_kexec_setup_load_arg(xki, image);
+
+	xki->indirection_page = image->head;
+	xki->start_address = image->start;
+}
+
+/*
+ * Load the image into xen so xen can kdump itself
+ * This might have been done in prepare, but prepare
+ * is currently called too early. It might make sense
+ * to move prepare, but for now, just add an extra hook.
+ */
+int xen_machine_kexec_load(struct kimage *image)
+{
+	xen_kexec_load_t xkl;
+
+	memset(&xkl, 0, sizeof(xkl));
+	xkl.type = image->type;
+	setup_load_arg(&xkl.image, image);
+	return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
+}
+
+/*
+ * Unload the image that was stored by machine_kexec_load()
+ * This might have been done in machine_kexec_cleanup() but it
+ * is called too late, and its possible xen could try and kdump
+ * using resources that have been freed.
+ */
+void xen_machine_kexec_unload(struct kimage *image)
+{
+	xen_kexec_load_t xkl;
+
+	memset(&xkl, 0, sizeof(xkl));
+	xkl.type = image->type;
+	WARN_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl));
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ *
+ * This has the hypervisor move to the prefered reboot CPU, 
+ * stop all CPUs and kexec. That is it combines machine_shutdown()
+ * and machine_kexec() in Linux kexec terms.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+	xen_kexec_exec_t xke;
+
+	memset(&xke, 0, sizeof(xke));
+	xke.type = image->type;
+	VOID(HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke));
+	panic("KEXEC_CMD_kexec hypercall should not return\n");
+}
+
+#ifdef CONFIG_X86
+unsigned long paddr_vmcoreinfo_note(void)
+{
+	return virt_to_machine(&vmcoreinfo_note);
+}
+#endif
+
+void machine_shutdown(void)
+{
+	/* do nothing */
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* The kernel is broken so disable interrupts */
+	local_irq_disable();
+}
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
--- linux-ec2-2.6.32.orig/drivers/xen/core/reboot.c
+++ linux-ec2-2.6.32/drivers/xen/core/reboot.c
@@ -0,0 +1,349 @@
+#define __KERNEL_SYSCALLS__
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/unistd.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#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>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#undef handle_sysrq
+#endif
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define SHUTDOWN_INVALID  -1
+#define SHUTDOWN_POWEROFF  0
+#define SHUTDOWN_SUSPEND   2
+#define SHUTDOWN_RESUMING  3
+#define SHUTDOWN_HALT      4
+
+/* Ignore multiple shutdown requests. */
+static int shutting_down = SHUTDOWN_INVALID;
+
+/* Can we leave APs online when we suspend? */
+static int fast_suspend;
+
+static void __shutdown_handler(struct work_struct *unused);
+static DECLARE_DELAYED_WORK(shutdown_work, __shutdown_handler);
+
+int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
+
+static int shutdown_process(void *__unused)
+{
+	static char *envp[] = { "HOME=/", "TERM=linux",
+				"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+	static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
+
+	extern asmlinkage long sys_reboot(int magic1, int magic2,
+					  unsigned int cmd, void *arg);
+
+	if ((shutting_down == SHUTDOWN_POWEROFF) ||
+	    (shutting_down == SHUTDOWN_HALT)) {
+		if (call_usermodehelper("/sbin/poweroff", poweroff_argv,
+					envp, 0) < 0) {
+#ifdef CONFIG_XEN
+			sys_reboot(LINUX_REBOOT_MAGIC1,
+				   LINUX_REBOOT_MAGIC2,
+				   LINUX_REBOOT_CMD_POWER_OFF,
+				   NULL);
+#endif /* CONFIG_XEN */
+		}
+	}
+
+	shutting_down = SHUTDOWN_INVALID; /* could try again */
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int setup_suspend_evtchn(void);
+
+/* Was last suspend request cancelled? */
+static int suspend_cancelled;
+
+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, 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 fail;
+	}
+
+	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_delayed_work(&shutdown_work, 0);
+		break;
+	}
+
+	return 0;
+
+ fail:
+	old_state = xchg(&shutting_down, SHUTDOWN_INVALID);
+	BUG_ON(old_state != SHUTDOWN_SUSPEND);
+	return 0;
+}
+
+#else
+# define xen_suspend NULL
+#endif
+
+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_delayed_work(&shutdown_work, 0);
+	else
+		BUG_ON(old_state != SHUTDOWN_RESUMING);
+}
+
+static void __shutdown_handler(struct work_struct *unused)
+{
+	int err;
+
+	err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
+			    xen_suspend : shutdown_process,
+			    NULL, CLONE_FS | CLONE_FILES);
+
+	if (err < 0) {
+		printk(KERN_WARNING "Error creating shutdown process (%d): "
+		       "retrying...\n", -err);
+		schedule_delayed_work(&shutdown_work, HZ/2);
+	}
+}
+
+static void shutdown_handler(struct xenbus_watch *watch,
+			     const char **vec, unsigned int len)
+{
+	extern void ctrl_alt_del(void);
+	char *str;
+	struct xenbus_transaction xbt;
+	int err, new_state = SHUTDOWN_INVALID;
+
+	if ((shutting_down != SHUTDOWN_INVALID) &&
+	    (shutting_down != SHUTDOWN_RESUMING))
+		return;
+
+ again:
+	err = xenbus_transaction_start(&xbt);
+	if (err)
+		return;
+
+	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
+	/* Ignore read errors and empty reads. */
+	if (XENBUS_IS_ERR_READ(str)) {
+		xenbus_transaction_end(xbt, 1);
+		return;
+	}
+
+	xenbus_write(xbt, "control", "shutdown", "");
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN) {
+		kfree(str);
+		goto again;
+	}
+
+	if (strcmp(str, "poweroff") == 0)
+		new_state = SHUTDOWN_POWEROFF;
+	else if (strcmp(str, "reboot") == 0)
+		ctrl_alt_del();
+#ifdef CONFIG_PM_SLEEP
+	else if (strcmp(str, "suspend") == 0)
+		new_state = SHUTDOWN_SUSPEND;
+#endif
+	else if (strcmp(str, "halt") == 0)
+		new_state = SHUTDOWN_HALT;
+	else
+		printk("Ignoring shutdown request: %s\n", str);
+
+	switch_shutdown_state(new_state);
+
+	kfree(str);
+}
+
+static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
+			  unsigned int len)
+{
+	char sysrq_key = '\0';
+	struct xenbus_transaction xbt;
+	int err;
+
+ again:
+	err = xenbus_transaction_start(&xbt);
+	if (err)
+		return;
+	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
+		printk(KERN_ERR "Unable to read sysrq code in "
+		       "control/sysrq\n");
+		xenbus_transaction_end(xbt, 1);
+		return;
+	}
+
+	if (sysrq_key != '\0')
+		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+
+#ifdef CONFIG_MAGIC_SYSRQ
+	if (sysrq_key != '\0')
+		handle_sysrq(sysrq_key, NULL);
+#endif
+}
+
+static struct xenbus_watch shutdown_watch = {
+	.node = "control/shutdown",
+	.callback = shutdown_handler
+};
+
+static struct xenbus_watch sysrq_watch = {
+	.node = "control/sysrq",
+	.callback = sysrq_handler
+};
+
+#ifdef CONFIG_PM_SLEEP
+static irqreturn_t suspend_int(int irq, void* dev_id)
+{
+	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;
+}
+#else
+#define setup_suspend_evtchn() 0
+#endif
+
+static int setup_shutdown_watcher(void)
+{
+	int err;
+
+	xenbus_scanf(XBT_NIL, "control",
+		     "platform-feature-multiprocessor-suspend",
+		     "%d", &fast_suspend);
+
+	err = register_xenbus_watch(&shutdown_watch);
+	if (err) {
+		printk(KERN_ERR "Failed to set shutdown watcher\n");
+		return err;
+	}
+
+	err = register_xenbus_watch(&sysrq_watch);
+	if (err) {
+		printk(KERN_ERR "Failed to set sysrq watcher\n");
+		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;
+}
+
+#ifdef CONFIG_XEN
+
+static int shutdown_event(struct notifier_block *notifier,
+			  unsigned long event,
+			  void *data)
+{
+	setup_shutdown_watcher();
+	return NOTIFY_DONE;
+}
+
+static int __init setup_shutdown_event(void)
+{
+	static struct notifier_block xenstore_notifier = {
+		.notifier_call = shutdown_event
+	};
+	register_xenstore_notifier(&xenstore_notifier);
+
+	return 0;
+}
+
+subsys_initcall(setup_shutdown_event);
+
+#else /* !defined(CONFIG_XEN) */
+
+int xen_reboot_init(void)
+{
+	return setup_shutdown_watcher();
+}
+
+#endif /* !defined(CONFIG_XEN) */
--- linux-ec2-2.6.32.orig/drivers/xen/core/Makefile
+++ linux-ec2-2.6.32/drivers/xen/core/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o
+
+priv-$(CONFIG_PCI)		+= pci.o
+obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += firmware.o $(priv-y)
+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_SMP)		+= spinlock.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o
+obj-$(CONFIG_XEN_DOMCTL)	+= domctl.o
+CFLAGS_domctl.o			:= -D__XEN_TOOLS__ -D__XEN_PUBLIC_XEN_H__ -imacros xen/interface/domctl.h
+obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
--- linux-ec2-2.6.32.orig/drivers/xen/core/xencomm.c
+++ linux-ec2-2.6.32/drivers/xen/core/xencomm.c
@@ -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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/core/hypervisor_sysfs.c
+++ linux-ec2-2.6.32/drivers/xen/core/hypervisor_sysfs.c
@@ -0,0 +1,57 @@
+/*
+ *  copyright (c) 2006 IBM Corporation
+ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <xen/hypervisor_sysfs.h>
+#include <asm/hypervisor.h>
+
+static ssize_t hyp_sysfs_show(struct kobject *kobj,
+			      struct attribute *attr,
+			      char *buffer)
+{
+	struct hyp_sysfs_attr *hyp_attr;
+	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
+	if (hyp_attr->show)
+		return hyp_attr->show(hyp_attr, buffer);
+	return 0;
+}
+
+static ssize_t hyp_sysfs_store(struct kobject *kobj,
+			       struct attribute *attr,
+			       const char *buffer,
+			       size_t len)
+{
+	struct hyp_sysfs_attr *hyp_attr;
+	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
+	if (hyp_attr->store)
+		return hyp_attr->store(hyp_attr, buffer, len);
+	return 0;
+}
+
+static struct sysfs_ops hyp_sysfs_ops = {
+	.show = hyp_sysfs_show,
+	.store = hyp_sysfs_store,
+};
+
+static struct kobj_type hyp_sysfs_kobj_type = {
+	.sysfs_ops = &hyp_sysfs_ops,
+};
+
+static int __init hypervisor_subsys_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
+	return 0;
+}
+
+device_initcall(hypervisor_subsys_init);
--- linux-ec2-2.6.32.orig/drivers/xen/core/gnttab.c
+++ linux-ec2-2.6.32/drivers/xen/core/gnttab.c
@@ -0,0 +1,884 @@
+/******************************************************************************
+ * gnttab.c
+ *
+ * Granting foreign access to our memory reservation.
+ *
+ * Copyright (c) 2005-2006, Christopher Clark
+ * Copyright (c) 2004-2005, K A Fraser
+ *
+ * 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/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/seqlock.h>
+#include <linux/sysdev.h>
+#include <xen/interface/xen.h>
+#include <xen/gnttab.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/synch_bitops.h>
+#include <asm/io.h>
+#include <xen/interface/memory.h>
+#include <xen/driver_util.h>
+#include <asm/gnttab_dma.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+/* External tools reserve first few grant table entries. */
+#define NR_RESERVED_ENTRIES 8
+#define GNTTAB_LIST_END 0xffffffff
+#define ENTRIES_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
+
+static grant_ref_t **gnttab_list;
+static unsigned int nr_grant_frames;
+static unsigned int boot_max_nr_grant_frames;
+static int gnttab_free_count;
+static grant_ref_t gnttab_free_head;
+static DEFINE_SPINLOCK(gnttab_list_lock);
+
+static struct grant_entry *shared;
+
+static struct gnttab_free_callback *gnttab_free_callback_list;
+
+static int gnttab_expand(unsigned int req_entries);
+
+#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;
+	int ref, rc;
+	grant_ref_t head;
+
+	spin_lock_irqsave(&gnttab_list_lock, flags);
+
+	if ((gnttab_free_count < count) &&
+	    ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
+		spin_unlock_irqrestore(&gnttab_list_lock, flags);
+		return rc;
+	}
+
+	ref = head = gnttab_free_head;
+	gnttab_free_count -= count;
+	while (count-- > 1)
+		head = gnttab_entry(head);
+ 	gnttab_free_head = gnttab_entry(head);
+	gnttab_entry(head) = GNTTAB_LIST_END;
+
+	spin_unlock_irqrestore(&gnttab_list_lock, flags);
+
+	return ref;
+}
+
+#define get_free_entry() get_free_entries(1)
+
+static void do_free_callbacks(void)
+{
+	struct gnttab_free_callback *callback, *next;
+
+	callback = gnttab_free_callback_list;
+	gnttab_free_callback_list = NULL;
+
+	while (callback != NULL) {
+		next = callback->next;
+		if (gnttab_free_count >= callback->count) {
+			callback->next = NULL;
+			callback->queued = 0;
+			callback->fn(callback->arg);
+		} else {
+			callback->next = gnttab_free_callback_list;
+			gnttab_free_callback_list = callback;
+		}
+		callback = next;
+	}
+}
+
+static inline void check_free_callbacks(void)
+{
+	if (unlikely(gnttab_free_callback_list))
+		do_free_callbacks();
+}
+
+static void put_free_entry(grant_ref_t ref)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&gnttab_list_lock, flags);
+	gnttab_entry(ref) = gnttab_free_head;
+	gnttab_free_head = ref;
+	gnttab_free_count++;
+	check_free_callbacks();
+	spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+
+/*
+ * Public grant-issuing interface functions
+ */
+
+int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
+				int flags)
+{
+	int ref;
+
+	if (unlikely((ref = get_free_entry()) < 0))
+		return -ENOSPC;
+
+	shared[ref].frame = frame;
+	shared[ref].domid = domid;
+	wmb();
+	BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
+	shared[ref].flags = GTF_permit_access | flags;
+
+	return ref;
+}
+EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
+
+void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+				     unsigned long frame, int flags)
+{
+	shared[ref].frame = frame;
+	shared[ref].domid = domid;
+	wmb();
+	BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
+	shared[ref].flags = GTF_permit_access | flags;
+}
+EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
+
+
+int gnttab_query_foreign_access(grant_ref_t ref)
+{
+	u16 nflags;
+
+	nflags = shared[ref].flags;
+
+	return (nflags & (GTF_reading|GTF_writing));
+}
+EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
+
+int gnttab_end_foreign_access_ref(grant_ref_t ref)
+{
+	u16 flags, nflags;
+
+	nflags = shared[ref].flags;
+	do {
+		if ((flags = nflags) & (GTF_reading|GTF_writing)) {
+			printk(KERN_DEBUG "WARNING: g.e. still in use!\n");
+			return 0;
+		}
+	} while ((nflags = synch_cmpxchg_subword(&shared[ref].flags, flags, 0)) !=
+		 flags);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
+
+void gnttab_end_foreign_access(grant_ref_t ref, unsigned long page)
+{
+	if (gnttab_end_foreign_access_ref(ref)) {
+		put_free_entry(ref);
+		if (page != 0)
+			free_page(page);
+	} else {
+		/* XXX This needs to be fixed so that the ref and page are
+		   placed on a list to be freed up later. */
+		printk(KERN_DEBUG
+		       "WARNING: leaking g.e. and page still in use!\n");
+	}
+}
+EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
+
+int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
+{
+	int ref;
+
+	if (unlikely((ref = get_free_entry()) < 0))
+		return -ENOSPC;
+	gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
+
+	return ref;
+}
+EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
+
+void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
+				       unsigned long pfn)
+{
+	shared[ref].frame = pfn;
+	shared[ref].domid = domid;
+	wmb();
+	shared[ref].flags = GTF_accept_transfer;
+}
+EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
+
+unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
+{
+	unsigned long frame;
+	u16           flags;
+
+	/*
+	 * If a transfer is not even yet started, try to reclaim the grant
+	 * reference and return failure (== 0).
+	 */
+	while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
+		if (synch_cmpxchg_subword(&shared[ref].flags, flags, 0) == flags)
+			return 0;
+		cpu_relax();
+	}
+
+	/* If a transfer is in progress then wait until it is completed. */
+	while (!(flags & GTF_transfer_completed)) {
+		flags = shared[ref].flags;
+		cpu_relax();
+	}
+
+	/* Read the frame number /after/ reading completion status. */
+	rmb();
+	frame = shared[ref].frame;
+	BUG_ON(frame == 0);
+
+	return frame;
+}
+EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
+
+unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
+{
+	unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
+	put_free_entry(ref);
+	return frame;
+}
+EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
+
+void gnttab_free_grant_reference(grant_ref_t ref)
+{
+	put_free_entry(ref);
+}
+EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
+
+void gnttab_free_grant_references(grant_ref_t head)
+{
+	grant_ref_t ref;
+	unsigned long flags;
+	int count = 1;
+	if (head == GNTTAB_LIST_END)
+		return;
+	spin_lock_irqsave(&gnttab_list_lock, flags);
+	ref = head;
+	while (gnttab_entry(ref) != GNTTAB_LIST_END) {
+		ref = gnttab_entry(ref);
+		count++;
+	}
+	gnttab_entry(ref) = gnttab_free_head;
+	gnttab_free_head = head;
+	gnttab_free_count += count;
+	check_free_callbacks();
+	spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
+
+int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
+{
+	int h = get_free_entries(count);
+
+	if (h < 0)
+		return -ENOSPC;
+
+	*head = h;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
+
+int gnttab_empty_grant_references(const grant_ref_t *private_head)
+{
+	return (*private_head == GNTTAB_LIST_END);
+}
+EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
+
+int gnttab_claim_grant_reference(grant_ref_t *private_head)
+{
+	grant_ref_t g = *private_head;
+	if (unlikely(g == GNTTAB_LIST_END))
+		return -ENOSPC;
+	*private_head = gnttab_entry(g);
+	return g;
+}
+EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
+
+void gnttab_release_grant_reference(grant_ref_t *private_head,
+				    grant_ref_t release)
+{
+	gnttab_entry(release) = *private_head;
+	*private_head = release;
+}
+EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
+
+void gnttab_request_free_callback(struct gnttab_free_callback *callback,
+				  void (*fn)(void *), void *arg, u16 count)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&gnttab_list_lock, flags);
+	if (callback->queued)
+		goto out;
+	callback->fn = fn;
+	callback->arg = arg;
+	callback->count = count;
+	callback->queued = 1;
+	callback->next = gnttab_free_callback_list;
+	gnttab_free_callback_list = callback;
+	check_free_callbacks();
+out:
+	spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
+
+void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
+{
+	struct gnttab_free_callback **pcb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gnttab_list_lock, flags);
+	for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
+		if (*pcb == callback) {
+			*pcb = callback->next;
+			callback->queued = 0;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
+
+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 * ENTRIES_PER_GRANT_FRAME;
+
+	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 = 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 = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
+	gnttab_free_count += extra_entries;
+
+	nr_grant_frames = new_nr_grant_frames;
+
+	check_free_callbacks();
+
+	return 0;
+	
+grow_nomem:
+	for ( ; i >= nr_glist_frames; i--)
+		free_page((unsigned long) gnttab_list[i]);
+	return -ENOMEM;
+}
+
+static unsigned int __max_nr_grant_frames(void)
+{
+	struct gnttab_query_size query;
+	int rc;
+
+	query.dom = DOMID_SELF;
+
+	rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
+	if ((rc < 0) || (query.status != GNTST_okay))
+		return 4; /* Legacy max supported number of frames */
+
+	return query.max_nr_frames;
+}
+
+static inline unsigned int max_nr_grant_frames(void)
+{
+	unsigned int xen_max = __max_nr_grant_frames();
+
+	if (xen_max > boot_max_nr_grant_frames)
+		return boot_max_nr_grant_frames;
+	return xen_max;
+}
+
+#ifdef CONFIG_XEN
+
+static DEFINE_SEQLOCK(gnttab_dma_lock);
+
+#ifdef CONFIG_X86
+static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+		      unsigned long addr, void *data)
+{
+	unsigned long **frames = (unsigned long **)data;
+
+	set_pte_at(&init_mm, addr, pte, pfn_pte_ma((*frames)[0], PAGE_KERNEL));
+	(*frames)++;
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+			unsigned long addr, void *data)
+{
+
+	set_pte_at(&init_mm, addr, pte, __pte(0));
+	return 0;
+}
+#endif
+
+void *arch_gnttab_alloc_shared(unsigned long *frames)
+{
+	struct vm_struct *area;
+	area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
+	BUG_ON(area == NULL);
+	return area->addr;
+}
+#endif /* CONFIG_X86 */
+
+static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+{
+	struct gnttab_setup_table setup;
+	unsigned long *frames;
+	unsigned int nr_gframes = end_idx + 1;
+	int rc;
+
+	frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
+	if (!frames)
+		return -ENOMEM;
+
+	setup.dom        = DOMID_SELF;
+	setup.nr_frames  = nr_gframes;
+	set_xen_guest_handle(setup.frame_list, frames);
+
+	rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
+	if (rc == -ENOSYS) {
+		kfree(frames);
+		return -ENOSYS;
+	}
+
+	BUG_ON(rc || setup.status);
+
+	if (shared == NULL)
+		shared = arch_gnttab_alloc_shared(frames);
+
+#ifdef CONFIG_X86
+	rc = apply_to_page_range(&init_mm, (unsigned long)shared,
+				 PAGE_SIZE * nr_gframes,
+				 map_pte_fn, &frames);
+	BUG_ON(rc);
+	frames -= nr_gframes; /* adjust after map_pte_fn() */
+#endif /* CONFIG_X86 */
+
+	kfree(frames);
+
+	return 0;
+}
+
+static void gnttab_page_free(struct page *page, unsigned int order)
+{
+	BUG_ON(order);
+	ClearPageForeign(page);
+	gnttab_reset_grant_page(page);
+	put_page(page);
+}
+
+/*
+ * Must not be called with IRQs off.  This should only be used on the
+ * slow path.
+ *
+ * Copy a foreign granted page to local memory.
+ */
+int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep)
+{
+	struct gnttab_unmap_and_replace unmap;
+	mmu_update_t mmu;
+	struct page *page;
+	struct page *new_page;
+	void *new_addr;
+	void *addr;
+	paddr_t pfn;
+	maddr_t mfn;
+	maddr_t new_mfn;
+	int err;
+
+	page = *pagep;
+	if (!get_page_unless_zero(page))
+		return -ENOENT;
+
+	err = -ENOMEM;
+	new_page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+	if (!new_page)
+		goto out;
+
+	new_addr = page_address(new_page);
+	addr = page_address(page);
+	memcpy(new_addr, addr, PAGE_SIZE);
+
+	pfn = page_to_pfn(page);
+	mfn = pfn_to_mfn(pfn);
+	new_mfn = virt_to_mfn(new_addr);
+
+	write_seqlock(&gnttab_dma_lock);
+
+	/* Make seq visible before checking page_mapped. */
+	smp_mb();
+
+	/* Has the page been DMA-mapped? */
+	if (unlikely(page_mapped(page))) {
+		write_sequnlock(&gnttab_dma_lock);
+		put_page(new_page);
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		set_phys_to_machine(pfn, new_mfn);
+
+	gnttab_set_replace_op(&unmap, (unsigned long)addr,
+			      (unsigned long)new_addr, ref);
+
+	err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
+					&unmap, 1);
+	BUG_ON(err);
+	BUG_ON(unmap.status);
+
+	write_sequnlock(&gnttab_dma_lock);
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+		set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY);
+
+		mmu.ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+		mmu.val = pfn;
+		err = HYPERVISOR_mmu_update(&mmu, 1, NULL, DOMID_SELF);
+		BUG_ON(err);
+	}
+
+	new_page->mapping = page->mapping;
+	new_page->index = page->index;
+	set_bit(PG_foreign, &new_page->flags);
+	*pagep = new_page;
+
+	SetPageForeign(page, gnttab_page_free);
+	page->mapping = NULL;
+
+out:
+	put_page(page);
+	return err;
+}
+EXPORT_SYMBOL_GPL(gnttab_copy_grant_page);
+
+void gnttab_reset_grant_page(struct page *page)
+{
+	init_page_count(page);
+	reset_page_mapcount(page);
+}
+EXPORT_SYMBOL_GPL(gnttab_reset_grant_page);
+
+/*
+ * Keep track of foreign pages marked as PageForeign so that we don't
+ * return them to the remote domain prematurely.
+ *
+ * PageForeign pages are pinned down by increasing their mapcount.
+ *
+ * All other pages are simply returned as is.
+ */
+void __gnttab_dma_map_page(struct page *page)
+{
+	unsigned int seq;
+
+	if (!is_running_on_xen() || !PageForeign(page))
+		return;
+
+	do {
+		seq = read_seqbegin(&gnttab_dma_lock);
+
+		if (gnttab_dma_local_pfn(page))
+			break;
+
+		atomic_set(&page->_mapcount, 0);
+
+		/* Make _mapcount visible before read_seqretry. */
+		smp_mb();
+	} while (unlikely(read_seqretry(&gnttab_dma_lock, seq)));
+}
+
+#ifdef __HAVE_ARCH_PTE_SPECIAL
+
+static unsigned int GNTMAP_pte_special;
+
+bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *map,
+			   unsigned int count)
+{
+	unsigned int i;
+
+	if (unlikely(cmd != GNTTABOP_map_grant_ref))
+		count = 0;
+
+	for (i = 0; i < count; ++i, ++map) {
+		if (!(map->flags & GNTMAP_host_map)
+		    || !(map->flags & GNTMAP_application_map))
+			continue;
+		if (GNTMAP_pte_special)
+			map->flags |= GNTMAP_pte_special;
+		else {
+			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+			return true;
+		}
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(gnttab_pre_map_adjust);
+
+#if CONFIG_XEN_COMPAT < 0x030400
+int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *map, unsigned int count)
+{
+	unsigned int i;
+	int rc = 0;
+
+	for (i = 0; i < count && rc == 0; ++i, ++map) {
+		pte_t pte;
+
+		if (!(map->flags & GNTMAP_host_map)
+		    || !(map->flags & GNTMAP_application_map))
+			continue;
+
+#ifdef CONFIG_X86
+		pte = __pte_ma((map->dev_bus_addr | _PAGE_PRESENT | _PAGE_USER
+				| _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NX
+				| _PAGE_SPECIAL)
+			       & __supported_pte_mask);
+#else
+#error Architecture not yet supported.
+#endif
+		if (!(map->flags & GNTMAP_readonly))
+			pte = pte_mkwrite(pte);
+
+		if (map->flags & GNTMAP_contains_pte) {
+			mmu_update_t u;
+
+			u.ptr = map->host_addr;
+			u.val = __pte_val(pte);
+			rc = HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF);
+		} else
+			rc = HYPERVISOR_update_va_mapping(map->host_addr, pte, 0);
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(gnttab_post_map_adjust);
+#endif
+
+#endif /* __HAVE_ARCH_PTE_SPECIAL */
+
+static int gnttab_resume(struct sys_device *dev)
+{
+	if (max_nr_grant_frames() < nr_grant_frames)
+		return -ENOSYS;
+	return gnttab_map(0, nr_grant_frames - 1);
+}
+#define gnttab_resume() gnttab_resume(NULL)
+
+#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_X86
+static int gnttab_suspend(struct sys_device *dev, pm_message_t state)
+{
+	apply_to_page_range(&init_mm, (unsigned long)shared,
+			    PAGE_SIZE * nr_grant_frames,
+			    unmap_pte_fn, NULL);
+	return 0;
+}
+#else
+#define gnttab_suspend NULL
+#endif
+
+static struct sysdev_class gnttab_sysclass = {
+	.name		= "gnttab",
+	.resume		= gnttab_resume,
+	.suspend	= gnttab_suspend,
+};
+
+static struct sys_device device_gnttab = {
+	.id		= 0,
+	.cls		= &gnttab_sysclass,
+};
+#endif
+
+#else /* !CONFIG_XEN */
+
+#include <platform-pci.h>
+
+static unsigned long resume_frames;
+
+static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
+{
+	struct xen_add_to_physmap xatp;
+	unsigned int i = end_idx;
+
+	/* Loop backwards, so that the first hypercall has the largest index,
+	 * ensuring that the table will grow only once.
+	 */
+	do {
+		xatp.domid = DOMID_SELF;
+		xatp.idx = i;
+		xatp.space = XENMAPSPACE_grant_table;
+		xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i;
+		if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
+			BUG();
+	} while (i-- > start_idx);
+
+	return 0;
+}
+
+int gnttab_resume(void)
+{
+	unsigned int max_nr_gframes, nr_gframes;
+
+	nr_gframes = nr_grant_frames;
+	max_nr_gframes = max_nr_grant_frames();
+	if (max_nr_gframes < nr_gframes)
+		return -ENOSYS;
+
+	if (!resume_frames) {
+		resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
+		shared = ioremap(resume_frames, PAGE_SIZE * max_nr_gframes);
+		if (shared == NULL) {
+			printk("error to ioremap gnttab share frames\n");
+			return -1;
+		}
+	}
+
+	gnttab_map(0, nr_gframes - 1);
+
+	return 0;
+}
+
+#endif /* !CONFIG_XEN */
+
+static int gnttab_expand(unsigned int req_entries)
+{
+	int rc;
+	unsigned int cur, extra;
+
+	cur = nr_grant_frames;
+	extra = ((req_entries + (ENTRIES_PER_GRANT_FRAME-1)) /
+		 ENTRIES_PER_GRANT_FRAME);
+	if (cur + extra > max_nr_grant_frames())
+		return -ENOSPC;
+
+	if ((rc = gnttab_map(cur, cur + extra - 1)) == 0)
+		rc = grow_gnttab_list(extra);
+
+	return rc;
+}
+
+int __devinit gnttab_init(void)
+{
+	int i;
+	unsigned int max_nr_glist_frames, nr_glist_frames;
+	unsigned int nr_init_grefs;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+#if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP)
+	if (!is_initial_xendomain()) {
+		int err = sysdev_class_register(&gnttab_sysclass);
+
+		if (!err)
+			err = sysdev_register(&device_gnttab);
+		if (err)
+			return err;
+	}
+#endif
+
+	nr_grant_frames = 1;
+	boot_max_nr_grant_frames = __max_nr_grant_frames();
+
+	/* Determine the maximum number of frames required for the
+	 * grant reference free list on the current hypervisor.
+	 */
+	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;
+
+	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;
+	}
+
+	if (gnttab_resume() < 0)
+		return -ENODEV;
+
+	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;
+
+	gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
+	gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
+	gnttab_free_head  = NR_RESERVED_ENTRIES;
+
+#if defined(CONFIG_XEN) && defined(__HAVE_ARCH_PTE_SPECIAL)
+	if (!xen_feature(XENFEAT_auto_translated_physmap)
+	    && xen_feature(XENFEAT_gnttab_map_avail_bits)) {
+#ifdef CONFIG_X86
+		GNTMAP_pte_special = (__pte_val(pte_mkspecial(__pte_ma(0)))
+				      >> _PAGE_BIT_UNUSED1) << _GNTMAP_guest_avail0;
+#else
+#error Architecture not yet supported.
+#endif
+	}
+#endif
+
+	return 0;
+
+ ini_nomem:
+	for (i--; i >= 0; i--)
+		free_page((unsigned long)gnttab_list[i]);
+	kfree(gnttab_list);
+	return -ENOMEM;
+}
+
+#ifdef CONFIG_XEN
+core_initcall(gnttab_init);
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/core/cpu_hotplug.c
+++ linux-ec2-2.6.32/drivers/xen/core/cpu_hotplug.c
@@ -0,0 +1,181 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <xen/cpu_hotplug.h>
+#include <xen/xenbus.h>
+
+/*
+ * Set of CPUs that remote admin software will allow us to bring online.
+ * Notified to us via xenbus.
+ */
+static cpumask_var_t xenbus_allowed_cpumask;
+
+/* Set of CPUs that local admin will allow us to bring online. */
+static cpumask_var_t local_allowed_cpumask;
+
+static int local_cpu_hotplug_request(void)
+{
+	/*
+	 * We assume a CPU hotplug request comes from local admin if it is made
+	 * via a userspace process (i.e., one with a real mm_struct).
+	 */
+	return (current->mm != NULL);
+}
+
+static void __cpuinit vcpu_hotplug(unsigned int cpu)
+{
+	int err;
+	char dir[32], state[32];
+
+	if ((cpu >= NR_CPUS) || !cpu_possible(cpu))
+		return;
+
+	sprintf(dir, "cpu/%u", cpu);
+	err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
+	if (err != 1) {
+		printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
+		return;
+	}
+
+	if (strcmp(state, "online") == 0) {
+		cpumask_set_cpu(cpu, xenbus_allowed_cpumask);
+		(void)cpu_up(cpu);
+	} else if (strcmp(state, "offline") == 0) {
+		cpumask_clear_cpu(cpu, xenbus_allowed_cpumask);
+		(void)cpu_down(cpu);
+	} else {
+		printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
+		       state, cpu);
+	}
+}
+
+static void __cpuinit handle_vcpu_hotplug_event(
+	struct xenbus_watch *watch, const char **vec, unsigned int len)
+{
+	unsigned int cpu;
+	char *cpustr;
+	const char *node = vec[XS_WATCH_PATH];
+
+	if ((cpustr = strstr(node, "cpu/")) != NULL) {
+		sscanf(cpustr, "cpu/%u", &cpu);
+		vcpu_hotplug(cpu);
+	}
+}
+
+static int smpboot_cpu_notify(struct notifier_block *notifier,
+			      unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (long)hcpu;
+
+	/*
+	 * We do this in a callback notifier rather than __cpu_disable()
+	 * because local_cpu_hotplug_request() does not work in the latter
+	 * as it's always executed from within a stopmachine kthread.
+	 */
+	if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
+		cpumask_clear_cpu(cpu, local_allowed_cpumask);
+
+	return NOTIFY_OK;
+}
+
+static int __cpuinit setup_cpu_watcher(struct notifier_block *notifier,
+				       unsigned long event, void *data)
+{
+	unsigned int i;
+
+	static struct xenbus_watch __cpuinitdata cpu_watch = {
+		.node = "cpu",
+		.callback = handle_vcpu_hotplug_event,
+		.flags = XBWF_new_thread };
+	(void)register_xenbus_watch(&cpu_watch);
+
+	if (!is_initial_xendomain()) {
+		for_each_possible_cpu(i)
+			vcpu_hotplug(i);
+		printk(KERN_INFO "Brought up %ld CPUs\n",
+		       (long)num_online_cpus());
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int __init setup_vcpu_hotplug_event(void)
+{
+	static struct notifier_block hotplug_cpu = {
+		.notifier_call = smpboot_cpu_notify };
+	static struct notifier_block __cpuinitdata xsn_cpu = {
+		.notifier_call = setup_cpu_watcher };
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	register_cpu_notifier(&hotplug_cpu);
+	register_xenstore_notifier(&xsn_cpu);
+
+	return 0;
+}
+
+arch_initcall(setup_vcpu_hotplug_event);
+
+int __ref smp_suspend(void)
+{
+	unsigned int cpu;
+	int err;
+
+	for_each_online_cpu(cpu) {
+		if (cpu == 0)
+			continue;
+		err = cpu_down(cpu);
+		if (err) {
+			printk(KERN_CRIT "Failed to take all CPUs "
+			       "down: %d.\n", err);
+			for_each_possible_cpu(cpu)
+				vcpu_hotplug(cpu);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+void __ref smp_resume(void)
+{
+	unsigned int cpu;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == 0)
+			continue;
+		vcpu_hotplug(cpu);
+	}
+}
+
+int cpu_up_check(unsigned int cpu)
+{
+	int rc = 0;
+
+	if (local_cpu_hotplug_request()) {
+		cpumask_set_cpu(cpu, local_allowed_cpumask);
+		if (!cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
+			printk("%s: attempt to bring up CPU %u disallowed by "
+			       "remote admin.\n", __FUNCTION__, cpu);
+			rc = -EBUSY;
+		}
+	} else if (!cpumask_test_cpu(cpu, local_allowed_cpumask) ||
+		   !cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
+		rc = -EBUSY;
+	}
+
+	return rc;
+}
+
+void __init init_xenbus_allowed_cpumask(void)
+{
+	if (!alloc_cpumask_var(&xenbus_allowed_cpumask, GFP_KERNEL))
+		BUG();
+	cpumask_copy(xenbus_allowed_cpumask, cpu_present_mask);
+	if (!alloc_cpumask_var(&local_allowed_cpumask, GFP_KERNEL))
+		BUG();
+	cpumask_setall(local_allowed_cpumask);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/core/machine_reboot.c
+++ linux-ec2-2.6.32/drivers/xen/core/machine_reboot.c
@@ -0,0 +1,283 @@
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/unistd.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sysrq.h>
+#include <linux/stringify.h>
+#include <linux/stop_machine.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <xen/evtchn.h>
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+#include <linux/cpu.h>
+#include <xen/gnttab.h>
+#include <xen/xencons.h>
+#include <xen/cpu_hotplug.h>
+#include <xen/interface/vcpu.h>
+#include "../../base/base.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include <asm/pci_x86.h>
+/* TBD: Dom0 should propagate the determined value to Xen. */
+bool port_cf9_safe = false;
+
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+void machine_emergency_restart(void)
+{
+	/* We really want to get pending console data out before we die. */
+	xencons_force_flush();
+	HYPERVISOR_shutdown(SHUTDOWN_reboot);
+}
+
+void machine_restart(char * __unused)
+{
+	machine_emergency_restart();
+}
+
+void machine_halt(void)
+{
+	machine_power_off();
+}
+
+void machine_power_off(void)
+{
+	/* We really want to get pending console data out before we die. */
+	xencons_force_flush();
+	if (pm_power_off)
+		pm_power_off();
+	HYPERVISOR_shutdown(SHUTDOWN_poweroff);
+}
+
+int reboot_thru_bios = 0;	/* for dmi_scan.c */
+EXPORT_SYMBOL(machine_restart);
+EXPORT_SYMBOL(machine_halt);
+EXPORT_SYMBOL(machine_power_off);
+
+#ifdef CONFIG_PM_SLEEP
+static void pre_suspend(void)
+{
+	HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+	WARN_ON(HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO),
+					     __pte_ma(0), 0));
+
+	xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+	xen_start_info->console.domU.mfn =
+		mfn_to_pfn(xen_start_info->console.domU.mfn);
+}
+
+static void post_suspend(int suspend_cancelled)
+{
+	int i, j, k, fpp;
+	unsigned long shinfo_mfn;
+	extern unsigned long max_pfn;
+	extern unsigned long *pfn_to_mfn_frame_list_list;
+	extern unsigned long **pfn_to_mfn_frame_list;
+
+	if (suspend_cancelled) {
+		xen_start_info->store_mfn =
+			pfn_to_mfn(xen_start_info->store_mfn);
+		xen_start_info->console.domU.mfn =
+			pfn_to_mfn(xen_start_info->console.domU.mfn);
+	} else {
+#ifdef CONFIG_SMP
+		cpumask_copy(vcpu_initialized_mask, cpu_online_mask);
+#endif
+	}
+
+	shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT;
+	if (HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO),
+					 pfn_pte_ma(shinfo_mfn, PAGE_KERNEL),
+					 0))
+		BUG();
+	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+
+	memset(empty_zero_page, 0, PAGE_SIZE);
+
+	fpp = PAGE_SIZE/sizeof(unsigned long);
+	for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
+		if ((j % fpp) == 0) {
+			k++;
+			pfn_to_mfn_frame_list_list[k] =
+				virt_to_mfn(pfn_to_mfn_frame_list[k]);
+			j = 0;
+		}
+		pfn_to_mfn_frame_list[k][j] =
+			virt_to_mfn(&phys_to_machine_mapping[i]);
+	}
+	HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+		virt_to_mfn(pfn_to_mfn_frame_list_list);
+}
+#endif
+
+#else /* !(defined(__i386__) || defined(__x86_64__)) */
+
+#ifndef HAVE_XEN_PRE_SUSPEND
+#define xen_pre_suspend()	((void)0)
+#endif
+
+#ifndef HAVE_XEN_POST_SUSPEND
+#define xen_post_suspend(x)	((void)0)
+#endif
+
+#define switch_idle_mm()	((void)0)
+#define mm_pin_all()		((void)0)
+#define pre_suspend()		xen_pre_suspend()
+#define post_suspend(x)		xen_post_suspend(x)
+
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+struct suspend {
+	int fast_suspend;
+	void (*resume_notifier)(int);
+};
+
+static int take_machine_down(void *_suspend)
+{
+	struct suspend *suspend = _suspend;
+	int suspend_cancelled, err;
+
+	if (suspend->fast_suspend) {
+		BUG_ON(!irqs_disabled());
+	} else {
+		BUG_ON(irqs_disabled());
+
+		for (;;) {
+			err = smp_suspend();
+			if (err)
+				return err;
+
+			xenbus_suspend();
+			preempt_disable();
+
+			if (num_online_cpus() == 1)
+				break;
+
+			preempt_enable();
+			xenbus_suspend_cancel();
+		}
+
+		local_irq_disable();
+	}
+
+	mm_pin_all();
+	suspend_cancelled = sysdev_suspend(PMSG_SUSPEND);
+	if (!suspend_cancelled) {
+		pre_suspend();
+
+		/*
+		 * This hypercall returns 1 if suspend was cancelled or the domain was
+		 * merely checkpointed, and 0 if it is resuming in a new domain.
+		 */
+		suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+		if (!suspend_cancelled) {
+			unsigned int cpu;
+
+			for_each_possible_cpu(cpu) {
+				if (suspend->fast_suspend
+				    && cpu != smp_processor_id()
+				    && HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL))
+					BUG();
+
+				setup_vcpu_info(cpu);
+
+				if (suspend->fast_suspend
+				    && cpu != smp_processor_id()
+				    && HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL))
+					BUG();
+			}
+		}
+	} else
+		BUG_ON(suspend_cancelled > 0);
+	suspend->resume_notifier(suspend_cancelled);
+	if (suspend_cancelled >= 0) {
+		post_suspend(suspend_cancelled);
+		sysdev_resume();
+	}
+	if (!suspend_cancelled) {
+#ifdef __x86_64__
+		/*
+		 * Older versions of Xen do not save/restore the user %cr3.
+		 * 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 (!suspend->fast_suspend)
+			xen_new_user_pt(current->active_mm->pgd);
+#endif
+	}
+
+	if (!suspend->fast_suspend)
+		local_irq_enable();
+
+	return suspend_cancelled;
+}
+
+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());
+
+#if defined(__i386__) || defined(__x86_64__)
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		printk(KERN_WARNING "Cannot suspend in "
+		       "auto_translated_physmap mode.\n");
+		return -EOPNOTSUPP;
+	}
+#endif
+
+	err = dpm_suspend_noirq(PMSG_SUSPEND);
+	if (err) {
+		printk(KERN_ERR "dpm_suspend_noirq() failed: %d\n", err);
+		return err;
+	}
+
+	/* If we are definitely UP then 'slow mode' is actually faster. */
+	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(take_machine_down, &suspend,
+				   &cpumask_of_cpu(0));
+		if (err < 0)
+			xenbus_suspend_cancel();
+	} else {
+		err = take_machine_down(&suspend);
+	}
+
+	if (err < 0) {
+		dpm_resume_noirq(PMSG_RESUME);
+		return err;
+	}
+
+	suspend_cancelled = err;
+	if (!suspend_cancelled) {
+		xencons_resume();
+		xenbus_resume();
+	} else {
+		xenbus_suspend_cancel();
+	}
+
+	if (!fast_suspend)
+		smp_resume();
+
+	dpm_resume_noirq(PMSG_RESUME);
+
+	return 0;
+}
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/core/xen_sysfs.c
+++ linux-ec2-2.6.32/drivers/xen/core/xen_sysfs.c
@@ -0,0 +1,421 @@
+/*
+ *  copyright (c) 2006 IBM Corporation
+ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/hypervisor.h>
+#include <xen/features.h>
+#include <xen/hypervisor_sysfs.h>
+#include <xen/xenbus.h>
+#include <xen/interface/kexec.h>
+#include "../xenbus/xenbus_comms.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike D. Day <ncmike@us.ibm.com>");
+
+static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	return sprintf(buffer, "xen\n");
+}
+
+HYPERVISOR_ATTR_RO(type);
+
+static int __init xen_sysfs_type_init(void)
+{
+	return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
+}
+
+static void xen_sysfs_type_destroy(void)
+{
+	sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
+}
+
+/* xen version attributes */
+static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
+	if (version)
+		return sprintf(buffer, "%d\n", version >> 16);
+	return -ENODEV;
+}
+
+HYPERVISOR_ATTR_RO(major);
+
+static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
+	if (version)
+		return sprintf(buffer, "%d\n", version & 0xff);
+	return -ENODEV;
+}
+
+HYPERVISOR_ATTR_RO(minor);
+
+static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	char *extra;
+
+	extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
+	if (extra) {
+		ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", extra);
+		kfree(extra);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(extra);
+
+static struct attribute *version_attrs[] = {
+	&major_attr.attr,
+	&minor_attr.attr,
+	&extra_attr.attr,
+	NULL
+};
+
+static struct attribute_group version_group = {
+	.name = "version",
+	.attrs = version_attrs,
+};
+
+static int __init xen_sysfs_version_init(void)
+{
+	return sysfs_create_group(hypervisor_kobj, &version_group);
+}
+
+static void xen_sysfs_version_destroy(void)
+{
+	sysfs_remove_group(hypervisor_kobj, &version_group);
+}
+
+/* UUID */
+
+static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	char *vm, *val;
+	int ret;
+
+	if (!is_xenstored_ready())
+		return -EBUSY;
+
+	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
+	if (IS_ERR(vm))
+		return PTR_ERR(vm);
+	val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
+	kfree(vm);
+	if (IS_ERR(val))
+		return PTR_ERR(val);
+	ret = sprintf(buffer, "%s\n", val);
+	kfree(val);
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(uuid);
+
+static int __init xen_sysfs_uuid_init(void)
+{
+	return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
+}
+
+static void xen_sysfs_uuid_destroy(void)
+{
+	sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
+}
+
+/* xen compilation attributes */
+
+static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	struct xen_compile_info *info;
+
+	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+	if (info) {
+		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", info->compiler);
+		kfree(info);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(compiler);
+
+static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	struct xen_compile_info *info;
+
+	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+	if (info) {
+		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", info->compile_by);
+		kfree(info);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(compiled_by);
+
+static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	struct xen_compile_info *info;
+
+	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
+	if (info) {
+		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", info->compile_date);
+		kfree(info);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(compile_date);
+
+static struct attribute *xen_compile_attrs[] = {
+	&compiler_attr.attr,
+	&compiled_by_attr.attr,
+	&compile_date_attr.attr,
+	NULL
+};
+
+static struct attribute_group xen_compilation_group = {
+	.name = "compilation",
+	.attrs = xen_compile_attrs,
+};
+
+int __init static xen_compilation_init(void)
+{
+	return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
+}
+
+static void xen_compilation_destroy(void)
+{
+	sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
+}
+
+/* xen properties info */
+
+static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	char *caps;
+
+	caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
+	if (caps) {
+		ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", caps);
+		kfree(caps);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(capabilities);
+
+static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	char *cset;
+
+	cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
+	if (cset) {
+		ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
+		if (!ret)
+			ret = sprintf(buffer, "%s\n", cset);
+		kfree(cset);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(changeset);
+
+static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret = -ENOMEM;
+	struct xen_platform_parameters *parms;
+
+	parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
+	if (parms) {
+		ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
+					     parms);
+		if (!ret)
+			ret = sprintf(buffer, "%lx\n", parms->virt_start);
+		kfree(parms);
+	}
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(virtual_start);
+
+static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	int ret;
+
+	ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
+	if (ret > 0)
+		ret = sprintf(buffer, "%x\n", ret);
+
+	return ret;
+}
+
+HYPERVISOR_ATTR_RO(pagesize);
+
+/* eventually there will be several more features to export */
+static ssize_t xen_feature_show(int index, char *buffer)
+{
+	int ret = -ENOMEM;
+	struct xen_feature_info *info;
+
+	info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL);
+	if (info) {
+		info->submap_idx = index;
+		ret = HYPERVISOR_xen_version(XENVER_get_features, info);
+		if (!ret)
+			ret = sprintf(buffer, "%d\n", info->submap);
+		kfree(info);
+	}
+
+	return ret;
+}
+
+static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer)
+{
+	return xen_feature_show(XENFEAT_writable_page_tables, buffer);
+}
+
+HYPERVISOR_ATTR_RO(writable_pt);
+
+static struct attribute *xen_properties_attrs[] = {
+	&capabilities_attr.attr,
+	&changeset_attr.attr,
+	&virtual_start_attr.attr,
+	&pagesize_attr.attr,
+	&writable_pt_attr.attr,
+	NULL
+};
+
+static struct attribute_group xen_properties_group = {
+	.name = "properties",
+	.attrs = xen_properties_attrs,
+};
+
+static int __init xen_properties_init(void)
+{
+	return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
+}
+
+static void xen_properties_destroy(void)
+{
+	sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
+}
+
+#ifdef CONFIG_KEXEC
+
+extern size_t vmcoreinfo_size_xen;
+extern unsigned long paddr_vmcoreinfo_xen;
+
+static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
+{
+	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_kobj, &vmcoreinfo_attr.attr);
+}
+
+static void xen_sysfs_vmcoreinfo_destroy(void)
+{
+	sysfs_remove_file(hypervisor_kobj, &vmcoreinfo_attr.attr);
+}
+
+#endif
+
+static int __init hyper_sysfs_init(void)
+{
+	int ret;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	ret = xen_sysfs_type_init();
+	if (ret)
+		goto out;
+	ret = xen_sysfs_version_init();
+	if (ret)
+		goto version_out;
+	ret = xen_compilation_init();
+	if (ret)
+		goto comp_out;
+	ret = xen_sysfs_uuid_init();
+	if (ret)
+		goto uuid_out;
+	ret = xen_properties_init();
+	if (ret)
+		goto prop_out;
+#ifdef CONFIG_KEXEC
+	if (vmcoreinfo_size_xen != 0) {
+		ret = xen_sysfs_vmcoreinfo_init();
+		if (ret)
+			goto vmcoreinfo_out;
+	}
+#endif
+
+	goto out;
+
+#ifdef CONFIG_KEXEC
+vmcoreinfo_out:
+#endif
+	xen_properties_destroy();
+prop_out:
+	xen_sysfs_uuid_destroy();
+uuid_out:
+	xen_compilation_destroy();
+comp_out:
+	xen_sysfs_version_destroy();
+version_out:
+	xen_sysfs_type_destroy();
+out:
+	return ret;
+}
+
+static void __exit hyper_sysfs_exit(void)
+{
+#ifdef CONFIG_KEXEC
+	if (vmcoreinfo_size_xen != 0)
+		xen_sysfs_vmcoreinfo_destroy();
+#endif
+	xen_properties_destroy();
+	xen_compilation_destroy();
+	xen_sysfs_uuid_destroy();
+	xen_sysfs_version_destroy();
+	xen_sysfs_type_destroy();
+
+}
+
+module_init(hyper_sysfs_init);
+module_exit(hyper_sysfs_exit);
--- linux-ec2-2.6.32.orig/drivers/xen/core/spinlock.c
+++ linux-ec2-2.6.32/drivers/xen/core/spinlock.c
@@ -0,0 +1,162 @@
+/*
+ *	Xen spinlock functions
+ *
+ *	See arch/x86/xen/smp.c for copyright and credits for derived
+ *	portions of this file.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <xen/evtchn.h>
+
+#ifdef TICKET_SHIFT
+
+static int __read_mostly spinlock_irq = -1;
+
+struct spinning {
+	raw_spinlock_t *lock;
+	unsigned int ticket;
+	struct spinning *prev;
+};
+static DEFINE_PER_CPU(struct spinning *, spinning);
+/*
+ * Protect removal of objects: Addition can be done lockless, and even
+ * removal itself doesn't need protection - what needs to be prevented is
+ * removed objects going out of scope (as they're allocated on the stack.
+ */
+static DEFINE_PER_CPU(raw_rwlock_t, spinning_rm_lock) = __RAW_RW_LOCK_UNLOCKED;
+
+int __cpuinit xen_spinlock_init(unsigned int cpu)
+{
+	static struct irqaction spinlock_action = {
+		.handler = smp_reschedule_interrupt,
+		.flags   = IRQF_DISABLED,
+		.name    = "spinlock"
+	};
+	int rc;
+
+	rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR,
+				   cpu,
+				   &spinlock_action);
+ 	if (rc < 0)
+ 		return rc;
+
+	if (spinlock_irq < 0) {
+		disable_irq(rc); /* make sure it's never delivered */
+		spinlock_irq = rc;
+	} else
+		BUG_ON(spinlock_irq != rc);
+
+	return 0;
+}
+
+void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
+{
+	unbind_from_per_cpu_irq(spinlock_irq, cpu, NULL);
+}
+
+int xen_spin_wait(raw_spinlock_t *lock, unsigned int token)
+{
+	int rc = 0, irq = spinlock_irq;
+	raw_rwlock_t *rm_lock;
+	unsigned long flags;
+	struct spinning spinning;
+
+	/* If kicker interrupt not initialized yet, just spin. */
+	if (unlikely(irq < 0) || unlikely(!cpu_online(raw_smp_processor_id())))
+		return 0;
+
+	token >>= TICKET_SHIFT;
+
+	/* announce we're spinning */
+	spinning.ticket = token;
+	spinning.lock = lock;
+	spinning.prev = percpu_read(spinning);
+	smp_wmb();
+	percpu_write(spinning, &spinning);
+
+	/* clear pending */
+	xen_clear_irq_pending(irq);
+
+	do {
+		/* Check again to make sure it didn't become free while
+		 * we weren't looking. */
+		if ((lock->slock & ((1U << TICKET_SHIFT) - 1)) == token) {
+			/* If we interrupted another spinlock while it was
+			 * blocking, make sure it doesn't block (again)
+			 * without rechecking the lock. */
+			if (spinning.prev)
+				xen_set_irq_pending(irq);
+			rc = 1;
+			break;
+		}
+
+		/* block until irq becomes pending */
+		xen_poll_irq(irq);
+	} while (!xen_test_irq_pending(irq));
+
+	/* Leave the irq pending so that any interrupted blocker will
+	 * re-check. */
+	if (!rc)
+		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+
+	/* announce we're done */
+	percpu_write(spinning, spinning.prev);
+	rm_lock = &__get_cpu_var(spinning_rm_lock);
+	raw_local_irq_save(flags);
+	__raw_write_lock(rm_lock);
+	__raw_write_unlock(rm_lock);
+	raw_local_irq_restore(flags);
+
+	return rc;
+}
+
+unsigned int xen_spin_adjust(raw_spinlock_t *lock, unsigned int token)
+{
+	return token;//todo
+}
+
+int xen_spin_wait_flags(raw_spinlock_t *lock, unsigned int *token,
+			  unsigned int flags)
+{
+	return xen_spin_wait(lock, *token);//todo
+}
+
+void xen_spin_kick(raw_spinlock_t *lock, unsigned int token)
+{
+	unsigned int cpu;
+
+	token &= (1U << TICKET_SHIFT) - 1;
+	for_each_online_cpu(cpu) {
+		raw_rwlock_t *rm_lock;
+		unsigned long flags;
+		struct spinning *spinning;
+
+		if (cpu == raw_smp_processor_id() || !per_cpu(spinning, cpu))
+			continue;
+
+		rm_lock = &per_cpu(spinning_rm_lock, cpu);
+		raw_local_irq_save(flags);
+		__raw_read_lock(rm_lock);
+
+		spinning = per_cpu(spinning, cpu);
+		smp_rmb();
+		if (spinning
+		    && (spinning->lock != lock || spinning->ticket != token))
+			spinning = NULL;
+
+		__raw_read_unlock(rm_lock);
+		raw_local_irq_restore(flags);
+
+		if (unlikely(spinning)) {
+			notify_remote_via_ipi(SPIN_UNLOCK_VECTOR, cpu);
+			return;
+		}
+	}
+}
+EXPORT_SYMBOL(xen_spin_kick);
+
+#endif /* TICKET_SHIFT */
--- linux-ec2-2.6.32.orig/drivers/xen/core/xen_proc.c
+++ linux-ec2-2.6.32/drivers/xen/core/xen_proc.c
@@ -0,0 +1,23 @@
+
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <xen/xen_proc.h>
+
+static struct proc_dir_entry *xen_base;
+
+struct proc_dir_entry *create_xen_proc_entry(const char *name, mode_t mode)
+{
+	if ( xen_base == NULL )
+		if ( (xen_base = proc_mkdir("xen", NULL)) == NULL )
+			panic("Couldn't create /proc/xen");
+	return create_proc_entry(name, mode, xen_base);
+}
+
+EXPORT_SYMBOL_GPL(create_xen_proc_entry); 
+
+void remove_xen_proc_entry(const char *name)
+{
+	remove_proc_entry(name, xen_base);
+}
+
+EXPORT_SYMBOL_GPL(remove_xen_proc_entry); 
--- linux-ec2-2.6.32.orig/drivers/xen/core/domctl.c
+++ linux-ec2-2.6.32/drivers/xen/core/domctl.c
@@ -0,0 +1,116 @@
+/*
+ * !!!  dirty hack alert  !!!
+ *
+ * Problem: old guests kernels don't have a "protocol" node
+ *          in the frontend xenstore directory, so mixing
+ *          32 and 64bit domains doesn't work.
+ *
+ * Upstream plans to solve this in the tools, by letting them
+ * create a protocol node.  Which certainly makes sense.
+ * But it isn't trivial and isn't done yet.  Too bad.
+ *
+ * So for the time being we use the get_address_size domctl
+ * hypercall for a pretty good guess.  Not nice as the domctl
+ * hypercall isn't supposed to be used by the kernel.  Because
+ * we don't want to have dependencies between dom0 kernel and
+ * xen kernel versions.  Now we have one.  Ouch.
+ */
+#undef __XEN_PUBLIC_XEN_H__
+#undef __XEN_TOOLS__
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/hypervisor.h>
+#include <xen/blkif.h>
+
+#include "domctl.h"
+
+/* stuff copied from xen/interface/domctl.h, which we can't
+ * include directly for the reasons outlined above .... */
+
+typedef struct xen_domctl_address_size {
+	uint32_t size;
+} xen_domctl_address_size_t;
+
+typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t;
+
+union xen_domctl {
+	/* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */
+	struct {
+		uint32_t cmd;
+		uint32_t interface_version;
+		domid_t  domain;
+		union {
+			/* left out lots of other struct xen_domctl_foobar */
+			struct xen_domctl_address_size       address_size;
+			uint64_t                             dummy_align;
+			uint8_t                              dummy_pad[128];
+		};
+	} v4;
+
+	/* v5: upstream: xen 3.1 */
+	struct {
+		uint32_t cmd;
+		uint32_t interface_version;
+		domid_t  domain;
+		union {
+			struct xen_domctl_address_size       address_size;
+			uint64_aligned_t                     dummy_align;
+			uint8_t                              dummy_pad[128];
+		};
+	} v5;
+};
+
+/* The actual code comes here */
+
+static inline int hypervisor_domctl(void *domctl)
+{
+	return _hypercall1(int, domctl, domctl);
+}
+
+int xen_guest_address_size(int domid)
+{
+	union xen_domctl domctl;
+	int low, ret;
+
+#define guest_address_size(ver) do {					\
+	memset(&domctl, 0, sizeof(domctl));				\
+	domctl.v##ver.cmd = XEN_DOMCTL_get_address_size;		\
+	domctl.v##ver.interface_version = low = ver;			\
+	domctl.v##ver.domain = domid;					\
+	ret = hypervisor_domctl(&domctl) ?: domctl.v##ver.address_size.size; \
+	if (ret == 32 || ret == 64) {					\
+		printk("v" #ver " domctl worked ok: dom%d is %d-bit\n",	\
+		       domid, ret);					\
+		return ret;						\
+	}								\
+} while (0)
+
+	BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 5);
+	guest_address_size(5);
+#if CONFIG_XEN_COMPAT < 0x030100
+	guest_address_size(4);
+#endif
+
+	ret = BITS_PER_LONG;
+	printk("v%d...5 domctls failed, assuming dom%d is native: %d\n",
+	       low, domid, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xen_guest_address_size);
+
+int xen_guest_blkif_protocol(int domid)
+{
+	int address_size = xen_guest_address_size(domid);
+
+	if (address_size == BITS_PER_LONG)
+		return BLKIF_PROTOCOL_NATIVE;
+	if (address_size == 32)
+		return BLKIF_PROTOCOL_X86_32;
+	if (address_size == 64)
+		return BLKIF_PROTOCOL_X86_64;
+	return BLKIF_PROTOCOL_NATIVE;
+}
+EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol);
+
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/core/smpboot.c
+++ linux-ec2-2.6.32/drivers/xen/core/smpboot.c
@@ -0,0 +1,475 @@
+/*
+ *	Xen SMP booting functions
+ *
+ *	See arch/i386/kernel/smpboot.c for copyright and credits for derived
+ *	portions of this file.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/smp_lock.h>
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <asm/desc.h>
+#include <asm/pgalloc.h>
+#include <xen/evtchn.h>
+#include <xen/interface/vcpu.h>
+#include <xen/cpu_hotplug.h>
+#include <xen/xenbus.h>
+
+extern int local_setup_timer(unsigned int cpu);
+extern void local_teardown_timer(unsigned int cpu);
+
+extern void hypervisor_callback(void);
+extern void failsafe_callback(void);
+extern void system_call(void);
+extern void smp_trap_init(trap_info_t *);
+
+/* Number of siblings per CPU package */
+int smp_num_siblings = 1;
+
+cpumask_var_t vcpu_initialized_mask;
+
+DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info);
+EXPORT_PER_CPU_SYMBOL(cpu_info);
+
+static int __read_mostly resched_irq = -1;
+static int __read_mostly callfunc_irq = -1;
+static int __read_mostly call1func_irq = -1;
+static int __read_mostly reboot_irq = -1;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
+#else
+#define set_cpu_to_apicid(cpu, apicid)
+#endif
+
+DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
+DEFINE_PER_CPU(cpumask_var_t, cpu_core_map);
+
+void __init prefill_possible_map(void)
+{
+	int i, rc;
+
+	for_each_possible_cpu(i)
+	    if (i != smp_processor_id())
+		return;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+		if (rc >= 0) {
+			set_cpu_possible(i, true);
+			nr_cpu_ids = i + 1;
+		}
+	}
+}
+
+static inline void
+set_cpu_sibling_map(unsigned int cpu)
+{
+	cpu_data(cpu).phys_proc_id = cpu;
+	cpu_data(cpu).cpu_core_id  = 0;
+
+	cpumask_copy(cpu_sibling_mask(cpu), cpumask_of(cpu));
+	cpumask_copy(cpu_core_mask(cpu), cpumask_of(cpu));
+
+	cpu_data(cpu).booted_cores = 1;
+}
+
+static void
+remove_siblinginfo(unsigned int cpu)
+{
+	cpu_data(cpu).phys_proc_id = BAD_APICID;
+	cpu_data(cpu).cpu_core_id  = BAD_APICID;
+
+	cpumask_clear(cpu_sibling_mask(cpu));
+	cpumask_clear(cpu_core_mask(cpu));
+
+	cpu_data(cpu).booted_cores = 0;
+}
+
+static int __cpuinit xen_smp_intr_init(unsigned int cpu)
+{
+	static struct irqaction resched_action = {
+		.handler = smp_reschedule_interrupt,
+		.flags   = IRQF_DISABLED,
+		.name    = "resched"
+	}, callfunc_action = {
+		.handler = smp_call_function_interrupt,
+		.flags   = IRQF_DISABLED,
+		.name    = "callfunc"
+	}, call1func_action = {
+		.handler = smp_call_function_single_interrupt,
+		.flags   = IRQF_DISABLED,
+		.name    = "call1func"
+	}, reboot_action = {
+		.handler = smp_reboot_interrupt,
+		.flags   = IRQF_DISABLED,
+		.name    = "reboot"
+	};
+	int rc;
+
+	rc = bind_ipi_to_irqaction(RESCHEDULE_VECTOR,
+				   cpu,
+				   &resched_action);
+	if (rc < 0)
+		return rc;
+	if (resched_irq < 0)
+		resched_irq = rc;
+	else
+		BUG_ON(resched_irq != rc);
+
+	rc = bind_ipi_to_irqaction(CALL_FUNCTION_VECTOR,
+				   cpu,
+				   &callfunc_action);
+	if (rc < 0)
+		goto unbind_resched;
+	if (callfunc_irq < 0)
+		callfunc_irq = rc;
+	else
+		BUG_ON(callfunc_irq != rc);
+
+	rc = bind_ipi_to_irqaction(CALL_FUNC_SINGLE_VECTOR,
+				   cpu,
+				   &call1func_action);
+	if (rc < 0)
+		goto unbind_call;
+	if (call1func_irq < 0)
+		call1func_irq = rc;
+	else
+		BUG_ON(call1func_irq != rc);
+
+	rc = bind_ipi_to_irqaction(REBOOT_VECTOR,
+				   cpu,
+				   &reboot_action);
+	if (rc < 0)
+		goto unbind_call1;
+	if (reboot_irq < 0)
+		reboot_irq = rc;
+	else
+		BUG_ON(reboot_irq != rc);
+
+	rc = xen_spinlock_init(cpu);
+	if (rc < 0)
+		goto unbind_reboot;
+
+	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
+		goto fail;
+
+	return 0;
+
+ fail:
+	xen_spinlock_cleanup(cpu);
+ unbind_reboot:
+	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
+ unbind_call1:
+	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
+ unbind_call:
+	unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL);
+ unbind_resched:
+	unbind_from_per_cpu_irq(resched_irq, cpu, NULL);
+	return rc;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void __cpuinit xen_smp_intr_exit(unsigned int cpu)
+{
+	if (cpu != 0)
+		local_teardown_timer(cpu);
+
+	unbind_from_per_cpu_irq(resched_irq, cpu, NULL);
+	unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL);
+	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
+	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
+	xen_spinlock_cleanup(cpu);
+}
+#endif
+
+static void __cpuinit cpu_bringup(void)
+{
+	cpu_init();
+	identify_secondary_cpu(&current_cpu_data);
+	touch_softlockup_watchdog();
+	preempt_disable();
+	local_irq_enable();
+}
+
+static void __cpuinit cpu_bringup_and_idle(void)
+{
+	cpu_bringup();
+	cpu_idle();
+}
+
+static void __cpuinit cpu_initialize_context(unsigned int cpu)
+{
+	/* vcpu_guest_context_t is too large to allocate on the stack.
+	 * Hence we allocate statically and protect it with a lock */
+	static vcpu_guest_context_t ctxt;
+	static DEFINE_SPINLOCK(ctxt_lock);
+
+	struct task_struct *idle = idle_task(cpu);
+
+	if (cpumask_test_and_set_cpu(cpu, vcpu_initialized_mask))
+		return;
+
+	spin_lock(&ctxt_lock);
+
+	memset(&ctxt, 0, sizeof(ctxt));
+
+	ctxt.flags = VGCF_IN_KERNEL;
+	ctxt.user_regs.ds = __USER_DS;
+	ctxt.user_regs.es = __USER_DS;
+	ctxt.user_regs.fs = 0;
+	ctxt.user_regs.gs = 0;
+	ctxt.user_regs.ss = __KERNEL_DS;
+	ctxt.user_regs.eip = (unsigned long)cpu_bringup_and_idle;
+	ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
+
+	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
+
+	smp_trap_init(ctxt.trap_ctxt);
+
+	ctxt.ldt_ents = 0;
+	ctxt.gdt_frames[0] = arbitrary_virt_to_mfn(get_cpu_gdt_table(cpu));
+	ctxt.gdt_ents = GDT_SIZE / 8;
+
+	ctxt.user_regs.cs = __KERNEL_CS;
+	ctxt.user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+
+	ctxt.kernel_ss = __KERNEL_DS;
+	ctxt.kernel_sp = idle->thread.sp0;
+
+	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
+	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
+#ifdef __i386__
+	ctxt.event_callback_cs     = __KERNEL_CS;
+	ctxt.failsafe_callback_cs  = __KERNEL_CS;
+
+	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
+
+	ctxt.user_regs.fs = __KERNEL_PERCPU;
+	ctxt.user_regs.gs = __KERNEL_STACK_CANARY;
+#else /* __x86_64__ */
+	ctxt.syscall_callback_eip  = (unsigned long)system_call;
+
+	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
+
+	ctxt.gs_base_kernel = per_cpu_offset(cpu);
+#endif
+
+	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt))
+		BUG();
+
+	spin_unlock(&ctxt_lock);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int cpu;
+	struct task_struct *idle;
+	int apicid;
+	struct vcpu_get_physid cpu_id;
+	void *gdt_addr;
+
+	apicid = 0;
+	if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0)
+		apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
+	boot_cpu_data.apicid = apicid;
+	cpu_data(0) = boot_cpu_data;
+
+	set_cpu_to_apicid(0, apicid);
+
+	current_thread_info()->cpu = 0;
+
+	for_each_possible_cpu (cpu) {
+		alloc_cpumask_var(&per_cpu(cpu_sibling_map, cpu), GFP_KERNEL);
+		alloc_cpumask_var(&per_cpu(cpu_core_map, cpu), GFP_KERNEL);
+		cpumask_clear(cpu_sibling_mask(cpu));
+		cpumask_clear(cpu_core_mask(cpu));
+	}
+
+	set_cpu_sibling_map(0);
+
+	if (xen_smp_intr_init(0))
+		BUG();
+
+	if (!alloc_cpumask_var(&vcpu_initialized_mask, GFP_KERNEL))
+		BUG();
+	cpumask_copy(vcpu_initialized_mask, cpumask_of(0));
+
+	/* Restrict the possible_map according to max_cpus. */
+	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
+		for (cpu = nr_cpu_ids-1; !cpumask_test_cpu(cpu, cpu_possible_mask); cpu--)
+			continue;
+		set_cpu_possible(cpu, false);
+	}
+
+	for_each_possible_cpu (cpu) {
+		if (cpu == 0)
+			continue;
+
+		idle = fork_idle(cpu);
+		if (IS_ERR(idle))
+			panic("failed fork for CPU %d", cpu);
+
+		gdt_addr = get_cpu_gdt_table(cpu);
+		make_page_readonly(gdt_addr, 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);
+		cpu_data(cpu) = boot_cpu_data;
+		cpu_data(cpu).cpu_index = cpu;
+		cpu_data(cpu).apicid = apicid;
+
+		set_cpu_to_apicid(cpu, apicid);
+
+#ifdef __x86_64__
+		clear_tsk_thread_flag(idle, TIF_FORK);
+		per_cpu(kernel_stack, cpu) =
+			(unsigned long)task_stack_page(idle) -
+			KERNEL_STACK_OFFSET + THREAD_SIZE;
+#endif
+	 	per_cpu(current_task, cpu) = idle;
+
+		irq_ctx_init(cpu);
+
+#ifdef CONFIG_HOTPLUG_CPU
+		if (is_initial_xendomain())
+#endif
+			set_cpu_present(cpu, true);
+	}
+
+	init_xenbus_allowed_cpumask();
+
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * Here we can be sure that there is an IO-APIC in the system. Let's
+	 * go and set it up:
+	 */
+	if (cpu_has_apic && !skip_ioapic_setup && nr_ioapics)
+		setup_IO_APIC();
+#endif
+}
+
+void __init smp_prepare_boot_cpu(void)
+{
+	unsigned int cpu;
+
+	switch_to_new_gdt(smp_processor_id());
+	prefill_possible_map();
+	for_each_possible_cpu(cpu)
+		if (cpu != smp_processor_id())
+			setup_vcpu_info(cpu);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/*
+ * Initialize cpu_present_map late to skip SMP boot code in init/main.c.
+ * But do it early enough to catch critical for_each_present_cpu() loops
+ * in i386-specific code.
+ */
+static int __init initialize_cpu_present_map(void)
+{
+	unsigned int cpu;
+
+	for_each_possible_cpu(cpu)
+		set_cpu_present(cpu, true);
+
+	return 0;
+}
+core_initcall(initialize_cpu_present_map);
+
+int __cpuexit __cpu_disable(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == 0)
+		return -EBUSY;
+
+	remove_siblinginfo(cpu);
+
+	set_cpu_online(cpu, false);
+	fixup_irqs();
+
+	return 0;
+}
+
+void __cpuinit __cpu_die(unsigned int cpu)
+{
+	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ/10);
+	}
+
+	xen_smp_intr_exit(cpu);
+
+	if (num_online_cpus() == 1)
+		alternatives_smp_switch(0);
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+	int rc;
+
+	rc = cpu_up_check(cpu);
+	if (rc)
+		return rc;
+
+	cpu_initialize_context(cpu);
+
+	if (num_online_cpus() == 1)
+		alternatives_smp_switch(1);
+
+	/* This must be done before setting cpu_online_map */
+	set_cpu_sibling_map(cpu);
+	wmb();
+
+	rc = xen_smp_intr_init(cpu);
+	if (rc) {
+		remove_siblinginfo(cpu);
+		return rc;
+	}
+
+	set_cpu_online(cpu, true);
+
+	rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
+	BUG_ON(rc);
+
+	return 0;
+}
+
+void __ref play_dead(void)
+{
+	idle_task_exit();
+	local_irq_disable();
+	cpumask_clear_cpu(smp_processor_id(), cpu_initialized_mask);
+	preempt_enable_no_resched();
+	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+#ifdef CONFIG_HOTPLUG_CPU
+	cpu_bringup();
+#else
+	BUG();
+#endif
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+#ifndef CONFIG_X86_LOCAL_APIC
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/core/domctl.h
+++ linux-ec2-2.6.32/drivers/xen/core/domctl.h
@@ -0,0 +1,2 @@
+int xen_guest_address_size(int domid);
+int xen_guest_blkif_protocol(int domid);
--- linux-ec2-2.6.32.orig/drivers/xen/core/evtchn.c
+++ linux-ec2-2.6.32/drivers/xen/core/evtchn.c
@@ -0,0 +1,1829 @@
+/******************************************************************************
+ * evtchn.c
+ * 
+ * Communication via Xen event channels.
+ * 
+ * Copyright (c) 2002-2005, K A Fraser
+ * 
+ * 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/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/sysdev.h>
+#include <linux/ftrace.h>
+#include <linux/version.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/synch_bitops.h>
+#include <xen/evtchn.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <asm/hypervisor.h>
+#include <linux/mc146818rtc.h> /* RTC_IRQ */
+
+/*
+ * This lock protects updates to the following mapping and reference-count
+ * arrays. The lock does not need to be acquired to read the mapping tables.
+ */
+static DEFINE_SPINLOCK(irq_mapping_update_lock);
+
+/* IRQ <-> event-channel mappings. */
+static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
+
+#if defined(CONFIG_SMP) && defined(CONFIG_X86)
+static struct per_cpu_irqaction {
+	struct irqaction action; /* must be first */
+	struct per_cpu_irqaction *next;
+	cpumask_t cpus;
+} *virq_actions[NR_VIRQS];
+/* IRQ <-> VIRQ mapping. */
+static DECLARE_BITMAP(virq_per_cpu, NR_VIRQS) __read_mostly;
+static DEFINE_PER_CPU(int[NR_VIRQS], virq_to_evtchn);
+#define BUG_IF_VIRQ_PER_CPU(irq) \
+	BUG_ON(type_from_irq(irq) == IRQT_VIRQ \
+	       && test_bit(index_from_irq(irq), virq_per_cpu))
+#else
+#define BUG_IF_VIRQ_PER_CPU(irq) ((void)(irq))
+#define PER_CPU_VIRQ_IRQ
+#endif
+
+/* IRQ <-> IPI mapping. */
+#ifndef NR_IPIS
+#define NR_IPIS 1
+#endif
+#if defined(CONFIG_SMP) && defined(CONFIG_X86)
+static int ipi_to_irq[NR_IPIS] __read_mostly = {[0 ... NR_IPIS-1] = -1};
+static DEFINE_PER_CPU(int[NR_IPIS], ipi_to_evtchn);
+#else
+#define PER_CPU_IPI_IRQ
+#endif
+#if !defined(CONFIG_SMP) || !defined(PER_CPU_IPI_IRQ)
+#define BUG_IF_IPI(irq) BUG_ON(type_from_irq(irq) == IRQT_IPI)
+#else
+#define BUG_IF_IPI(irq) ((void)(irq))
+#endif
+
+/* Binding types. */
+enum {
+	IRQT_UNBOUND,
+	IRQT_PIRQ,
+	IRQT_VIRQ,
+	IRQT_IPI,
+	IRQT_LOCAL_PORT,
+	IRQT_CALLER_PORT,
+	_IRQT_COUNT
+};
+
+#define _IRQT_BITS 4
+#define _EVTCHN_BITS 12
+#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
+
+/* Convenient shorthand for packed representation of an unbound IRQ. */
+#define IRQ_UNBOUND	(IRQT_UNBOUND << (32 - _IRQT_BITS))
+
+static struct irq_cfg _irq_cfg[] = {
+	[0 ...
+#ifdef CONFIG_SPARSE_IRQ
+	       BUILD_BUG_ON_ZERO(PIRQ_BASE) + NR_IRQS_LEGACY
+#else
+	       NR_IRQS
+#endif
+		       - 1].info = IRQ_UNBOUND
+};
+
+static inline struct irq_cfg *__pure irq_cfg(unsigned int irq)
+{
+#ifdef CONFIG_SPARSE_IRQ
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	return desc ? desc->chip_data : NULL;
+#else
+	return irq < NR_IRQS ? _irq_cfg + irq : NULL;
+#endif
+}
+
+/* Constructor for packed IRQ information. */
+static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
+{
+	BUILD_BUG_ON(_IRQT_COUNT > (1U << _IRQT_BITS));
+
+	BUILD_BUG_ON(NR_PIRQS > (1U << _INDEX_BITS));
+	BUILD_BUG_ON(NR_VIRQS > (1U << _INDEX_BITS));
+	BUILD_BUG_ON(NR_IPIS > (1U << _INDEX_BITS));
+	BUG_ON(index >> _INDEX_BITS);
+
+	BUILD_BUG_ON(NR_EVENT_CHANNELS > (1U << _EVTCHN_BITS));
+
+	return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
+}
+
+/*
+ * Accessors for packed IRQ information.
+ */
+
+static inline unsigned int index_from_irq(int irq)
+{
+	const struct irq_cfg *cfg = irq_cfg(irq);
+
+	return cfg ? (cfg->info >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1)
+		   : 0;
+}
+
+static inline unsigned int type_from_irq(int irq)
+{
+	const struct irq_cfg *cfg = irq_cfg(irq);
+
+	return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
+}
+
+static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq,
+						    unsigned int cpu)
+{
+	switch (type_from_irq(irq)) {
+#ifndef PER_CPU_VIRQ_IRQ
+	case IRQT_VIRQ:
+		return per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)];
+#endif
+#ifndef PER_CPU_IPI_IRQ
+	case IRQT_IPI:
+		return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)];
+#endif
+	}
+	BUG();
+	return 0;
+}
+
+static inline unsigned int evtchn_from_irq(unsigned int irq)
+{
+	const struct irq_cfg *cfg;
+
+	switch (type_from_irq(irq)) {
+#ifndef PER_CPU_VIRQ_IRQ
+	case IRQT_VIRQ:
+#endif
+#ifndef PER_CPU_IPI_IRQ
+	case IRQT_IPI:
+#endif
+		return evtchn_from_per_cpu_irq(irq, smp_processor_id());
+	}
+	cfg = irq_cfg(irq);
+	return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
+}
+
+/* IRQ <-> VIRQ mapping. */
+DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
+
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+/* IRQ <-> IPI mapping. */
+DEFINE_PER_CPU(int[NR_IPIS], ipi_to_irq) = {[0 ... NR_IPIS-1] = -1};
+#endif
+
+#ifdef CONFIG_SMP
+
+static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+static DEFINE_PER_CPU(unsigned long[BITS_TO_LONGS(NR_EVENT_CHANNELS)],
+		      cpu_evtchn_mask);
+
+static inline unsigned long active_evtchns(unsigned int idx)
+{
+	shared_info_t *sh = HYPERVISOR_shared_info;
+
+	return (sh->evtchn_pending[idx] &
+		percpu_read(cpu_evtchn_mask[idx]) &
+		~sh->evtchn_mask[idx]);
+}
+
+static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	int irq = evtchn_to_irq[chn];
+
+	BUG_ON(!test_bit(chn, s->evtchn_mask));
+
+	if (irq != -1) {
+		struct irq_desc *desc = irq_to_desc(irq);
+
+		if (!(desc->status & IRQ_PER_CPU))
+			cpumask_copy(desc->affinity, cpumask_of(cpu));
+		else
+			cpumask_set_cpu(cpu, desc->affinity);
+	}
+
+	clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_evtchn[chn]));
+	set_bit(chn, per_cpu(cpu_evtchn_mask, cpu));
+	cpu_evtchn[chn] = cpu;
+}
+
+static void init_evtchn_cpu_bindings(void)
+{
+	int i;
+
+	/* By default all event channels notify CPU#0. */
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_desc *desc = irq_to_desc(i);
+
+		if (desc)
+			cpumask_copy(desc->affinity, cpumask_of(0));
+	}
+
+	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+	memset(per_cpu(cpu_evtchn_mask, 0), ~0, sizeof(per_cpu(cpu_evtchn_mask, 0)));
+}
+
+static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
+{
+	return cpu_evtchn[evtchn];
+}
+
+#else
+
+static inline unsigned long active_evtchns(unsigned int idx)
+{
+	shared_info_t *sh = HYPERVISOR_shared_info;
+
+	return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
+}
+
+static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+{
+}
+
+static void init_evtchn_cpu_bindings(void)
+{
+}
+
+static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
+{
+	return 0;
+}
+
+#endif
+
+#ifdef CONFIG_X86
+void __init xen_init_IRQ(void);
+void __init init_IRQ(void)
+{
+	irq_ctx_init(0);
+	xen_init_IRQ();
+}
+#include <asm/idle.h>
+#endif
+
+/* Xen will never allocate port zero for any purpose. */
+#define VALID_EVTCHN(chn)	((chn) != 0)
+
+/*
+ * Force a proper event-channel callback from Xen after clearing the
+ * callback mask. We do this in a very simple manner, by making a call
+ * down into Xen. The pending flag will be checked by Xen on return.
+ */
+void force_evtchn_callback(void)
+{
+	VOID(HYPERVISOR_xen_version(0, NULL));
+}
+/* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */
+EXPORT_SYMBOL(force_evtchn_callback);
+
+static DEFINE_PER_CPU(unsigned int, upcall_count) = { 0 };
+static DEFINE_PER_CPU(unsigned int, last_processed_l1i) = { BITS_PER_LONG - 1 };
+static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 };
+
+#ifndef vcpu_info_xchg
+#define vcpu_info_xchg(fld, val) xchg(&current_vcpu_info()->fld, val)
+#endif
+
+#ifndef percpu_xadd
+#define percpu_xadd(var, val)					\
+({								\
+	typeof(per_cpu_var(var)) __tmp_var__;			\
+	unsigned long flags;					\
+	local_irq_save(flags);					\
+	__tmp_var__ = get_cpu_var(var);				\
+	__get_cpu_var(var) += (val);				\
+	put_cpu_var(var);					\
+	local_irq_restore(flags);				\
+	__tmp_var__;						\
+})
+#endif
+
+/* NB. Interrupts are disabled on entry. */
+asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs)
+{
+	struct pt_regs     *old_regs = set_irq_regs(regs);
+	unsigned long       l1, l2;
+	unsigned long       masked_l1, masked_l2;
+	unsigned int        l1i, l2i, port, count;
+	int                 irq;
+
+	exit_idle();
+	irq_enter();
+
+	do {
+		/* Avoid a callback storm when we reenable delivery. */
+		vcpu_info_write(evtchn_upcall_pending, 0);
+
+		/* Nested invocations bail immediately. */
+		if (unlikely(percpu_xadd(upcall_count, 1)))
+			break;
+
+#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+		/* Clear master flag /before/ clearing selector flag. */
+		wmb();
+#else
+		barrier();
+#endif
+		l1 = vcpu_info_xchg(evtchn_pending_sel, 0);
+
+		l1i = percpu_read(last_processed_l1i);
+		l2i = percpu_read(last_processed_l2i);
+
+		while (l1 != 0) {
+
+			l1i = (l1i + 1) % BITS_PER_LONG;
+			masked_l1 = l1 & ((~0UL) << l1i);
+
+			if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */
+				l1i = BITS_PER_LONG - 1;
+				l2i = BITS_PER_LONG - 1;
+				continue;
+			}
+			l1i = __ffs(masked_l1);
+
+			do {
+				l2 = active_evtchns(l1i);
+
+				l2i = (l2i + 1) % BITS_PER_LONG;
+				masked_l2 = l2 & ((~0UL) << l2i);
+
+				if (masked_l2 == 0) { /* if we masked out all events, move on */
+					l2i = BITS_PER_LONG - 1;
+					break;
+				}
+
+				l2i = __ffs(masked_l2);
+
+				/* process port */
+				port = (l1i * BITS_PER_LONG) + l2i;
+				if (unlikely((irq = evtchn_to_irq[port]) == -1))
+					evtchn_device_upcall(port);
+				else if (!handle_irq(irq, regs) && printk_ratelimit())
+					printk(KERN_EMERG "%s(%d): No handler for irq %d\n",
+					       __func__, smp_processor_id(), irq);
+
+				/* if this is the final port processed, we'll pick up here+1 next time */
+				percpu_write(last_processed_l1i, l1i);
+				percpu_write(last_processed_l2i, l2i);
+
+			} while (l2i != BITS_PER_LONG - 1);
+
+			l2 = active_evtchns(l1i);
+			if (l2 == 0) /* we handled all ports, so we can clear the selector bit */
+				l1 &= ~(1UL << l1i);
+
+		}
+
+		/* If there were nested callbacks then we have more to do. */
+		count = percpu_read(upcall_count);
+		percpu_write(upcall_count, 0);
+	} while (unlikely(count != 1));
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
+static struct irq_chip dynirq_chip;
+
+static int find_unbound_irq(unsigned int cpu, bool percpu)
+{
+	static int warned;
+	int irq;
+
+	for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++) {
+		struct irq_desc *desc = irq_to_desc_alloc_node(irq, cpu_to_node(cpu));
+		struct irq_cfg *cfg = desc->chip_data;
+
+		if (!cfg->bindcount) {
+			irq_flow_handler_t handle;
+			const char *name;
+
+			desc->status |= IRQ_NOPROBE;
+			if (!percpu) {
+				handle = handle_level_irq;
+				name = "level";
+			} else {
+				handle = handle_percpu_irq;
+				name = "percpu";
+			}
+			set_irq_chip_and_handler_name(irq, &dynirq_chip,
+						      handle, name);
+			return irq;
+		}
+	}
+
+	if (!warned) {
+		warned = 1;
+		printk(KERN_WARNING "No available IRQ to bind to: "
+		       "increase NR_DYNIRQS.\n");
+	}
+
+	return -ENOSPC;
+}
+
+static int bind_caller_port_to_irq(unsigned int caller_port)
+{
+	int irq;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if ((irq = evtchn_to_irq[caller_port]) == -1) {
+		if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0)
+			goto out;
+
+		evtchn_to_irq[caller_port] = irq;
+		irq_cfg(irq)->info = mk_irq_info(IRQT_CALLER_PORT,
+						  0, caller_port);
+	}
+
+	irq_cfg(irq)->bindcount++;
+
+ out:
+	spin_unlock(&irq_mapping_update_lock);
+	return irq;
+}
+
+static int bind_local_port_to_irq(unsigned int local_port)
+{
+	int irq;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	BUG_ON(evtchn_to_irq[local_port] != -1);
+
+	if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0) {
+		struct evtchn_close close = { .port = local_port };
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+			BUG();
+		goto out;
+	}
+
+	evtchn_to_irq[local_port] = irq;
+	irq_cfg(irq)->info = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
+	irq_cfg(irq)->bindcount++;
+
+ out:
+	spin_unlock(&irq_mapping_update_lock);
+	return irq;
+}
+
+static int bind_listening_port_to_irq(unsigned int remote_domain)
+{
+	struct evtchn_alloc_unbound alloc_unbound;
+	int err;
+
+	alloc_unbound.dom        = DOMID_SELF;
+	alloc_unbound.remote_dom = remote_domain;
+
+	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+					  &alloc_unbound);
+
+	return err ? : bind_local_port_to_irq(alloc_unbound.port);
+}
+
+static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
+					  unsigned int remote_port)
+{
+	struct evtchn_bind_interdomain bind_interdomain;
+	int err;
+
+	bind_interdomain.remote_dom  = remote_domain;
+	bind_interdomain.remote_port = remote_port;
+
+	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+					  &bind_interdomain);
+
+	return err ? : bind_local_port_to_irq(bind_interdomain.local_port);
+}
+
+static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+{
+	struct evtchn_bind_virq bind_virq;
+	int evtchn, irq;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+		if ((irq = find_unbound_irq(cpu, false)) < 0)
+			goto out;
+
+		bind_virq.virq = virq;
+		bind_virq.vcpu = cpu;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+						&bind_virq) != 0)
+			BUG();
+		evtchn = bind_virq.port;
+
+		evtchn_to_irq[evtchn] = irq;
+#ifndef PER_CPU_VIRQ_IRQ
+		{
+			unsigned int cpu;
+
+			for_each_possible_cpu(cpu)
+				per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
+		}
+#endif
+		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+
+		per_cpu(virq_to_irq, cpu)[virq] = irq;
+
+		bind_evtchn_to_cpu(evtchn, cpu);
+	}
+
+	irq_cfg(irq)->bindcount++;
+
+ out:
+	spin_unlock(&irq_mapping_update_lock);
+	return irq;
+}
+
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+{
+	struct evtchn_bind_ipi bind_ipi;
+	int evtchn, irq;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
+		if ((irq = find_unbound_irq(cpu, false)) < 0)
+			goto out;
+
+		bind_ipi.vcpu = cpu;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+						&bind_ipi) != 0)
+			BUG();
+		evtchn = bind_ipi.port;
+
+		evtchn_to_irq[evtchn] = irq;
+		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
+
+		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+
+		bind_evtchn_to_cpu(evtchn, cpu);
+	}
+
+	irq_cfg(irq)->bindcount++;
+
+ out:
+	spin_unlock(&irq_mapping_update_lock);
+	return irq;
+}
+#endif
+
+static void unbind_from_irq(unsigned int irq)
+{
+	struct evtchn_close close;
+	unsigned int cpu;
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_IF_VIRQ_PER_CPU(irq);
+	BUG_IF_IPI(irq);
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
+		close.port = evtchn;
+		if ((type_from_irq(irq) != IRQT_CALLER_PORT) &&
+		    HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+			BUG();
+
+		switch (type_from_irq(irq)) {
+		case IRQT_VIRQ:
+			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
+				[index_from_irq(irq)] = -1;
+#ifndef PER_CPU_VIRQ_IRQ
+			for_each_possible_cpu(cpu)
+				per_cpu(virq_to_evtchn, cpu)
+					[index_from_irq(irq)] = 0;
+#endif
+			break;
+#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+		case IRQT_IPI:
+			per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
+				[index_from_irq(irq)] = -1;
+			break;
+#endif
+		default:
+			break;
+		}
+
+		/* Closed ports are implicitly re-bound to VCPU0. */
+		bind_evtchn_to_cpu(evtchn, 0);
+
+		evtchn_to_irq[evtchn] = -1;
+		irq_cfg(irq)->info = IRQ_UNBOUND;
+
+		/* Zap stats across IRQ changes of use. */
+		for_each_possible_cpu(cpu)
+#ifdef CONFIG_GENERIC_HARDIRQS
+			irq_to_desc(irq)->kstat_irqs[cpu] = 0;
+#else
+			kstat_cpu(cpu).irqs[irq] = 0;
+#endif
+	}
+
+	spin_unlock(&irq_mapping_update_lock);
+}
+
+#if defined(CONFIG_SMP) && (!defined(PER_CPU_IPI_IRQ) || !defined(PER_CPU_VIRQ_IRQ))
+void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu,
+			     struct irqaction *action)
+{
+	struct evtchn_close close;
+	int evtchn = evtchn_from_per_cpu_irq(irq, cpu);
+	struct irqaction *free_action = NULL;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if (VALID_EVTCHN(evtchn)) {
+		struct irq_desc *desc = irq_to_desc(irq);
+
+		mask_evtchn(evtchn);
+
+		BUG_ON(irq_cfg(irq)->bindcount <= 1);
+		irq_cfg(irq)->bindcount--;
+
+#ifndef PER_CPU_VIRQ_IRQ
+		if (type_from_irq(irq) == IRQT_VIRQ) {
+			unsigned int virq = index_from_irq(irq);
+			struct per_cpu_irqaction *cur, *prev = NULL;
+
+			cur = virq_actions[virq];
+			while (cur) {
+				if (cur->action.dev_id == action) {
+					cpu_clear(cpu, cur->cpus);
+					if (cpus_empty(cur->cpus)) {
+						if (prev)
+							prev->next = cur->next;
+						else
+							virq_actions[virq] = cur->next;
+						free_action = action;
+					}
+				} else if (cpu_isset(cpu, cur->cpus))
+					evtchn = 0;
+				cur = (prev = cur)->next;
+			}
+			if (!VALID_EVTCHN(evtchn))
+				goto done;
+		}
+#endif
+
+		cpumask_clear_cpu(cpu, desc->affinity);
+
+		close.port = evtchn;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+			BUG();
+
+		switch (type_from_irq(irq)) {
+#ifndef PER_CPU_VIRQ_IRQ
+		case IRQT_VIRQ:
+			per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)] = 0;
+			break;
+#endif
+#ifndef PER_CPU_IPI_IRQ
+		case IRQT_IPI:
+			per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0;
+			break;
+#endif
+		default:
+			BUG();
+			break;
+		}
+
+		/* Closed ports are implicitly re-bound to VCPU0. */
+		bind_evtchn_to_cpu(evtchn, 0);
+
+		evtchn_to_irq[evtchn] = -1;
+	}
+
+#ifndef PER_CPU_VIRQ_IRQ
+done:
+#endif
+	spin_unlock(&irq_mapping_update_lock);
+
+	if (free_action)
+		free_irq(irq, free_action);
+}
+EXPORT_SYMBOL_GPL(unbind_from_per_cpu_irq);
+#endif /* CONFIG_SMP && (!PER_CPU_IPI_IRQ || !PER_CPU_VIRQ_IRQ) */
+
+int bind_caller_port_to_irqhandler(
+	unsigned int caller_port,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id)
+{
+	int irq, retval;
+
+	irq = bind_caller_port_to_irq(caller_port);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_caller_port_to_irqhandler);
+
+int bind_listening_port_to_irqhandler(
+	unsigned int remote_domain,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id)
+{
+	int irq, retval;
+
+	irq = bind_listening_port_to_irq(remote_domain);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_listening_port_to_irqhandler);
+
+int bind_interdomain_evtchn_to_irqhandler(
+	unsigned int remote_domain,
+	unsigned int remote_port,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id)
+{
+	int irq, retval;
+
+	irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler);
+
+int bind_virq_to_irqhandler(
+	unsigned int virq,
+	unsigned int cpu,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id)
+{
+	int irq, retval;
+
+	BUG_IF_VIRQ_PER_CPU(virq);
+
+	irq = bind_virq_to_irq(virq, cpu);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+
+#ifdef CONFIG_SMP
+#ifndef PER_CPU_VIRQ_IRQ
+int bind_virq_to_irqaction(
+	unsigned int virq,
+	unsigned int cpu,
+	struct irqaction *action)
+{
+	struct evtchn_bind_virq bind_virq;
+	int evtchn, irq, retval = 0;
+	struct per_cpu_irqaction *cur = NULL, *new;
+
+	BUG_ON(!test_bit(virq, virq_per_cpu));
+
+	if (action->dev_id)
+		return -EINVAL;
+
+	new = kzalloc(sizeof(*new), GFP_ATOMIC);
+	if (new) {
+		new->action = *action;
+		new->action.dev_id = action;
+	}
+
+	spin_lock(&irq_mapping_update_lock);
+
+	for (cur = virq_actions[virq]; cur; cur = cur->next)
+		if (cur->action.dev_id == action)
+			break;
+	if (!cur) {
+		if (!new) {
+			spin_unlock(&irq_mapping_update_lock);
+			return -ENOMEM;
+		}
+		new->next = virq_actions[virq];
+		virq_actions[virq] = cur = new;
+		retval = 1;
+	}
+	cpu_set(cpu, cur->cpus);
+	action = &cur->action;
+
+	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+		unsigned int nr;
+
+		BUG_ON(!retval);
+
+		if ((irq = find_unbound_irq(cpu, true)) < 0) {
+			if (cur)
+				virq_actions[virq] = cur->next;
+			spin_unlock(&irq_mapping_update_lock);
+			if (cur != new)
+				kfree(new);
+			return irq;
+		}
+
+		/* Extra reference so count will never drop to zero. */
+		irq_cfg(irq)->bindcount++;
+
+		for_each_possible_cpu(nr)
+			per_cpu(virq_to_irq, nr)[virq] = irq;
+		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, 0);
+	}
+
+	evtchn = per_cpu(virq_to_evtchn, cpu)[virq];
+	if (!VALID_EVTCHN(evtchn)) {
+		bind_virq.virq = virq;
+		bind_virq.vcpu = cpu;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+						&bind_virq) != 0)
+			BUG();
+		evtchn = bind_virq.port;
+		evtchn_to_irq[evtchn] = irq;
+		per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
+
+		bind_evtchn_to_cpu(evtchn, cpu);
+	}
+
+	irq_cfg(irq)->bindcount++;
+
+	spin_unlock(&irq_mapping_update_lock);
+
+	if (cur != new)
+		kfree(new);
+
+	if (retval == 0) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		unmask_evtchn(evtchn);
+		local_irq_restore(flags);
+	} else {
+		action->flags |= IRQF_PERCPU;
+		retval = setup_irq(irq, action);
+		if (retval) {
+			unbind_from_per_cpu_irq(irq, cpu, cur->action.dev_id);
+			BUG_ON(retval > 0);
+			irq = retval;
+		}
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_virq_to_irqaction);
+#endif
+
+#ifdef PER_CPU_IPI_IRQ
+int bind_ipi_to_irqhandler(
+	unsigned int ipi,
+	unsigned int cpu,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id)
+{
+	int irq, retval;
+
+	irq = bind_ipi_to_irq(ipi, cpu);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags | IRQF_NO_SUSPEND,
+			     devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+#else
+int __cpuinit bind_ipi_to_irqaction(
+	unsigned int ipi,
+	unsigned int cpu,
+	struct irqaction *action)
+{
+	struct evtchn_bind_ipi bind_ipi;
+	int evtchn, irq, retval = 0;
+
+	spin_lock(&irq_mapping_update_lock);
+
+	if (VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi])) {
+		spin_unlock(&irq_mapping_update_lock);
+		return -EBUSY;
+	}
+
+	if ((irq = ipi_to_irq[ipi]) == -1) {
+		if ((irq = find_unbound_irq(cpu, true)) < 0) {
+			spin_unlock(&irq_mapping_update_lock);
+			return irq;
+		}
+
+		/* Extra reference so count will never drop to zero. */
+		irq_cfg(irq)->bindcount++;
+
+		ipi_to_irq[ipi] = irq;
+		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, 0);
+		retval = 1;
+	}
+
+	bind_ipi.vcpu = cpu;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+					&bind_ipi) != 0)
+		BUG();
+
+	evtchn = bind_ipi.port;
+	evtchn_to_irq[evtchn] = irq;
+	per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
+
+	bind_evtchn_to_cpu(evtchn, cpu);
+
+	irq_cfg(irq)->bindcount++;
+
+	spin_unlock(&irq_mapping_update_lock);
+
+	if (retval == 0) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		unmask_evtchn(evtchn);
+		local_irq_restore(flags);
+	} else {
+		action->flags |= IRQF_PERCPU | IRQF_NO_SUSPEND;
+		retval = setup_irq(irq, action);
+		if (retval) {
+			unbind_from_per_cpu_irq(irq, cpu, NULL);
+			BUG_ON(retval > 0);
+			irq = retval;
+		}
+	}
+
+	return irq;
+}
+#endif /* PER_CPU_IPI_IRQ */
+#endif /* CONFIG_SMP */
+
+void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+{
+	free_irq(irq, dev_id);
+	unbind_from_irq(irq);
+}
+EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
+
+#ifdef CONFIG_SMP
+void rebind_evtchn_to_cpu(int port, unsigned int cpu)
+{
+	struct evtchn_bind_vcpu ebv = { .port = port, .vcpu = cpu };
+	int masked;
+
+	masked = test_and_set_evtchn_mask(port);
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &ebv) == 0)
+		bind_evtchn_to_cpu(port, cpu);
+	if (!masked)
+		unmask_evtchn(port);
+}
+
+static void rebind_irq_to_cpu(unsigned int irq, unsigned int tcpu)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_IF_VIRQ_PER_CPU(irq);
+	BUG_IF_IPI(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		rebind_evtchn_to_cpu(evtchn, tcpu);
+}
+
+static int set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+{
+	rebind_irq_to_cpu(irq, cpumask_first(dest));
+
+	return 0;
+}
+#endif
+
+int resend_irq_on_evtchn(unsigned int irq)
+{
+	int masked, evtchn = evtchn_from_irq(irq);
+
+	if (!VALID_EVTCHN(evtchn))
+		return 1;
+
+	masked = test_and_set_evtchn_mask(evtchn);
+	set_evtchn(evtchn);
+	if (!masked)
+		unmask_evtchn(evtchn);
+
+	return 1;
+}
+
+/*
+ * Interface to generic handling in irq.c
+ */
+
+static unsigned int startup_dynirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		unmask_evtchn(evtchn);
+	return 0;
+}
+
+static void unmask_dynirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		unmask_evtchn(evtchn);
+}
+
+static void mask_dynirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		mask_evtchn(evtchn);
+}
+
+static void ack_dynirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	move_native_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)) {
+		mask_evtchn(evtchn);
+		clear_evtchn(evtchn);
+	}
+}
+
+static void end_dynirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn) && !(irq_to_desc(irq)->status & IRQ_DISABLED))
+		unmask_evtchn(evtchn);
+}
+
+static struct irq_chip dynirq_chip = {
+	.name     = "Dynamic",
+	.startup  = startup_dynirq,
+	.shutdown = mask_dynirq,
+	.disable  = mask_dynirq,
+	.mask     = mask_dynirq,
+	.unmask   = unmask_dynirq,
+	.mask_ack = ack_dynirq,
+	.ack      = ack_dynirq,
+	.eoi      = end_dynirq,
+	.end      = end_dynirq,
+#ifdef CONFIG_SMP
+	.set_affinity = set_affinity_irq,
+#endif
+	.retrigger = resend_irq_on_evtchn,
+};
+
+/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
+static bool pirq_eoi_does_unmask;
+static unsigned long *pirq_needs_eoi;
+static DECLARE_BITMAP(probing_pirq, NR_PIRQS);
+
+static void pirq_unmask_and_notify(unsigned int evtchn, unsigned int irq)
+{
+	struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
+
+	if (pirq_eoi_does_unmask) {
+		if (test_bit(eoi.irq, pirq_needs_eoi))
+			VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
+		else
+			unmask_evtchn(evtchn);
+	} else if (test_bit(irq - PIRQ_BASE, pirq_needs_eoi)) {
+		if (smp_processor_id() != cpu_from_evtchn(evtchn)) {
+			struct evtchn_unmask unmask = { .port = evtchn };
+			struct multicall_entry mcl[2];
+
+			mcl[0].op = __HYPERVISOR_event_channel_op;
+			mcl[0].args[0] = EVTCHNOP_unmask;
+			mcl[0].args[1] = (unsigned long)&unmask;
+			mcl[1].op = __HYPERVISOR_physdev_op;
+			mcl[1].args[0] = PHYSDEVOP_eoi;
+			mcl[1].args[1] = (unsigned long)&eoi;
+
+			if (HYPERVISOR_multicall(mcl, 2))
+				BUG();
+		} else {
+			unmask_evtchn(evtchn);
+			VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
+		}
+	} else
+		unmask_evtchn(evtchn);
+}
+
+static inline void pirq_query_unmask(int irq)
+{
+	struct physdev_irq_status_query irq_status;
+
+	if (pirq_eoi_does_unmask)
+		return;
+	irq_status.irq = evtchn_get_xen_pirq(irq);
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+		irq_status.flags = 0;
+	clear_bit(irq - PIRQ_BASE, pirq_needs_eoi);
+	if (irq_status.flags & XENIRQSTAT_needs_eoi)
+		set_bit(irq - PIRQ_BASE, pirq_needs_eoi);
+}
+
+static int set_type_pirq(unsigned int irq, unsigned int type)
+{
+	if (type != IRQ_TYPE_PROBE)
+		return -EINVAL;
+	set_bit(irq - PIRQ_BASE, probing_pirq);
+	return 0;
+}
+
+static unsigned int startup_pirq(unsigned int irq)
+{
+	struct evtchn_bind_pirq bind_pirq;
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)) {
+		clear_bit(irq - PIRQ_BASE, probing_pirq);
+		goto out;
+	}
+
+	bind_pirq.pirq = evtchn_get_xen_pirq(irq);
+	/* NB. We are happy to share unless we are probing. */
+	bind_pirq.flags = test_and_clear_bit(irq - PIRQ_BASE, probing_pirq)
+			  || (irq_to_desc(irq)->status & IRQ_AUTODETECT)
+			  ? 0 : BIND_PIRQ__WILL_SHARE;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+		if (bind_pirq.flags)
+			printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
+			       irq);
+		return 0;
+	}
+	evtchn = bind_pirq.port;
+
+	pirq_query_unmask(irq);
+
+	evtchn_to_irq[evtchn] = irq;
+	bind_evtchn_to_cpu(evtchn, 0);
+	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
+
+ out:
+	pirq_unmask_and_notify(evtchn, irq);
+
+	return 0;
+}
+
+static void shutdown_pirq(unsigned int irq)
+{
+	struct evtchn_close close;
+	int evtchn = evtchn_from_irq(irq);
+
+	if (!VALID_EVTCHN(evtchn))
+		return;
+
+	mask_evtchn(evtchn);
+
+	close.port = evtchn;
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+		BUG();
+
+	bind_evtchn_to_cpu(evtchn, 0);
+	evtchn_to_irq[evtchn] = -1;
+	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
+}
+
+static void unmask_pirq(unsigned int irq)
+{
+	startup_pirq(irq);
+}
+
+static void mask_pirq(unsigned int irq)
+{
+}
+
+static void ack_pirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	move_native_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)) {
+		mask_evtchn(evtchn);
+		clear_evtchn(evtchn);
+	}
+}
+
+static void end_pirq(unsigned int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if ((irq_to_desc(irq)->status & (IRQ_DISABLED|IRQ_PENDING)) ==
+	    (IRQ_DISABLED|IRQ_PENDING)) {
+		shutdown_pirq(irq);
+	} else if (VALID_EVTCHN(evtchn))
+		pirq_unmask_and_notify(evtchn, irq);
+}
+
+static struct irq_chip pirq_chip = {
+	.name     = "Phys",
+	.startup  = startup_pirq,
+	.shutdown = shutdown_pirq,
+	.mask     = mask_pirq,
+	.unmask   = unmask_pirq,
+	.mask_ack = ack_pirq,
+	.ack      = ack_pirq,
+	.end      = end_pirq,
+	.set_type = set_type_pirq,
+#ifdef CONFIG_SMP
+	.set_affinity = set_affinity_irq,
+#endif
+	.retrigger = resend_irq_on_evtchn,
+};
+
+int irq_ignore_unhandled(unsigned int irq)
+{
+	struct physdev_irq_status_query irq_status = { .irq = irq };
+
+	if (!is_running_on_xen())
+		return 0;
+
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+		return 0;
+	return !!(irq_status.flags & XENIRQSTAT_shared);
+}
+
+#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
+void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu)
+{
+	int evtchn = evtchn_from_per_cpu_irq(ipi_to_irq[ipi], cpu);
+
+	if (VALID_EVTCHN(evtchn))
+		notify_remote_via_evtchn(evtchn);
+}
+#endif
+
+void notify_remote_via_irq(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_ON(type_from_irq(irq) == IRQT_VIRQ);
+	BUG_IF_IPI(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		notify_remote_via_evtchn(evtchn);
+}
+EXPORT_SYMBOL_GPL(notify_remote_via_irq);
+
+int multi_notify_remote_via_irq(multicall_entry_t *mcl, int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	BUG_ON(type_from_irq(irq) == IRQT_VIRQ);
+	BUG_IF_IPI(irq);
+
+	if (!VALID_EVTCHN(evtchn))
+		return -EINVAL;
+
+	multi_notify_remote_via_evtchn(mcl, evtchn);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(multi_notify_remote_via_irq);
+
+int irq_to_evtchn_port(int irq)
+{
+	BUG_IF_VIRQ_PER_CPU(irq);
+	BUG_IF_IPI(irq);
+	return evtchn_from_irq(irq);
+}
+EXPORT_SYMBOL_GPL(irq_to_evtchn_port);
+
+void mask_evtchn(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	synch_set_bit(port, s->evtchn_mask);
+}
+EXPORT_SYMBOL_GPL(mask_evtchn);
+
+void unmask_evtchn(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	unsigned int cpu = smp_processor_id();
+
+	BUG_ON(!irqs_disabled());
+
+	/* Slow path (hypercall) if this is a non-local port. */
+	if (unlikely(cpu != cpu_from_evtchn(port))) {
+		struct evtchn_unmask unmask = { .port = port };
+		VOID(HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask));
+		return;
+	}
+
+	synch_clear_bit(port, s->evtchn_mask);
+
+	/* Did we miss an interrupt 'edge'? Re-fire if so. */
+	if (synch_test_bit(port, s->evtchn_pending)) {
+		vcpu_info_t *vcpu_info = current_vcpu_info();
+
+		if (!synch_test_and_set_bit(port / BITS_PER_LONG,
+					    &vcpu_info->evtchn_pending_sel))
+			vcpu_info->evtchn_upcall_pending = 1;
+	}
+}
+EXPORT_SYMBOL_GPL(unmask_evtchn);
+
+void disable_all_local_evtchn(void)
+{
+	unsigned i, cpu = smp_processor_id();
+	shared_info_t *s = HYPERVISOR_shared_info;
+
+	for (i = 0; i < NR_EVENT_CHANNELS; ++i)
+		if (cpu_from_evtchn(i) == cpu)
+			synch_set_bit(i, &s->evtchn_mask[0]);
+}
+
+/* Clear an irq's pending state, in preparation for polling on it. */
+void xen_clear_irq_pending(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		clear_evtchn(evtchn);
+}
+
+/* Set an irq's pending state, to avoid blocking on it. */
+void xen_set_irq_pending(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		set_evtchn(evtchn);
+}
+
+/* Test an irq's pending state. */
+int xen_test_irq_pending(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	return VALID_EVTCHN(evtchn) && test_evtchn(evtchn);
+}
+
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq)
+{
+	evtchn_port_t evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)
+	    && HYPERVISOR_poll_no_timeout(&evtchn, 1))
+		BUG();
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void restore_cpu_virqs(unsigned int cpu)
+{
+	struct evtchn_bind_virq bind_virq;
+	int virq, irq, evtchn;
+
+	for (virq = 0; virq < NR_VIRQS; virq++) {
+		if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
+			continue;
+
+#ifndef PER_CPU_VIRQ_IRQ
+		if (test_bit(virq, virq_per_cpu)
+		    && !VALID_EVTCHN(per_cpu(virq_to_evtchn, cpu)[virq]))
+			continue;
+#endif
+
+		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_VIRQ, virq, 0));
+
+		/* Get a new binding from Xen. */
+		bind_virq.virq = virq;
+		bind_virq.vcpu = cpu;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+						&bind_virq) != 0)
+			BUG();
+		evtchn = bind_virq.port;
+
+		/* Record the new mapping. */
+		evtchn_to_irq[evtchn] = irq;
+#ifdef PER_CPU_VIRQ_IRQ
+		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+#else
+		if (test_bit(virq, virq_per_cpu))
+			per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
+		else {
+			unsigned int cpu;
+
+			irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq,
+							 evtchn);
+			for_each_possible_cpu(cpu)
+				per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
+		}
+#endif
+		bind_evtchn_to_cpu(evtchn, cpu);
+
+		/* Ready for use. */
+		unmask_evtchn(evtchn);
+	}
+}
+
+static void restore_cpu_ipis(unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+	struct evtchn_bind_ipi bind_ipi;
+	int ipi, irq, evtchn;
+
+	for (ipi = 0; ipi < NR_IPIS; ipi++) {
+#ifdef PER_CPU_IPI_IRQ
+		if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
+#else
+		if ((irq = ipi_to_irq[ipi]) == -1
+		    || !VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi]))
+#endif
+			continue;
+
+		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_IPI, ipi, 0));
+
+		/* Get a new binding from Xen. */
+		bind_ipi.vcpu = cpu;
+		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
+						&bind_ipi) != 0)
+			BUG();
+		evtchn = bind_ipi.port;
+
+		/* Record the new mapping. */
+		evtchn_to_irq[evtchn] = irq;
+#ifdef PER_CPU_IPI_IRQ
+		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
+#else
+		per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
+#endif
+		bind_evtchn_to_cpu(evtchn, cpu);
+
+		/* Ready for use. */
+		if (!(irq_to_desc(irq)->status & IRQ_DISABLED))
+			unmask_evtchn(evtchn);
+	}
+#endif
+}
+
+static int evtchn_resume(struct sys_device *dev)
+{
+	unsigned int cpu, irq, evtchn;
+	struct irq_cfg *cfg;
+	struct evtchn_status status;
+
+	/* Avoid doing anything in the 'suspend cancelled' case. */
+	status.dom = DOMID_SELF;
+#ifdef PER_CPU_VIRQ_IRQ
+	status.port = evtchn_from_irq(percpu_read(virq_to_irq[VIRQ_TIMER]));
+#else
+	status.port = percpu_read(virq_to_evtchn[VIRQ_TIMER]);
+#endif
+	if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status))
+		BUG();
+	if (status.status == EVTCHNSTAT_virq
+	    && status.vcpu == smp_processor_id()
+	    && status.u.virq == VIRQ_TIMER)
+		return 0;
+
+	init_evtchn_cpu_bindings();
+
+	if (pirq_eoi_does_unmask) {
+		struct physdev_pirq_eoi_gmfn eoi_gmfn;
+
+		eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
+		if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn))
+			BUG();
+	}
+
+	/* New event-channel space is not 'live' yet. */
+	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
+		mask_evtchn(evtchn);
+
+	/* Check that no PIRQs are still bound. */
+	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + nr_pirqs); irq++) {
+		cfg = irq_cfg(irq);
+		BUG_ON(cfg && cfg->info != IRQ_UNBOUND);
+	}
+
+	/* No IRQ <-> event-channel mappings. */
+	for (irq = 0; irq < nr_irqs; irq++) {
+		cfg = irq_cfg(irq);
+		if (cfg)
+			cfg->info &= ~((1U << _EVTCHN_BITS) - 1);
+	}
+	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
+		evtchn_to_irq[evtchn] = -1;
+
+	for_each_possible_cpu(cpu) {
+		restore_cpu_virqs(cpu);
+		restore_cpu_ipis(cpu);
+	}
+
+	return 0;
+}
+
+static struct sysdev_class evtchn_sysclass = {
+	.name		= "evtchn",
+	.resume		= evtchn_resume,
+};
+
+static struct sys_device device_evtchn = {
+	.id		= 0,
+	.cls		= &evtchn_sysclass,
+};
+
+static int __init evtchn_register(void)
+{
+	int err;
+
+	if (is_initial_xendomain())
+		return 0;
+
+	err = sysdev_class_register(&evtchn_sysclass);
+	if (!err)
+		err = sysdev_register(&device_evtchn);
+	return err;
+}
+core_initcall(evtchn_register);
+#endif
+
+int __init arch_early_irq_init(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(_irq_cfg); i++)
+		irq_to_desc(i)->chip_data = _irq_cfg + i;
+
+	return 0;
+}
+
+#ifdef CONFIG_SPARSE_IRQ
+int arch_init_chip_data(struct irq_desc *desc, int cpu)
+{
+	if (!desc->chip_data) {
+		/* By default all event channels notify CPU#0. */
+		cpumask_copy(desc->affinity, cpumask_of(0));
+
+		desc->chip_data = kzalloc(sizeof(struct irq_cfg), GFP_ATOMIC);
+	}
+	if (!desc->chip_data) {
+		printk(KERN_ERR "cannot alloc irq_cfg\n");
+		BUG();
+	}
+
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_X86_IO_APIC)
+#ifdef CONFIG_SPARSE_IRQ
+int nr_pirqs = NR_PIRQS;
+EXPORT_SYMBOL_GPL(nr_pirqs);
+
+int __init arch_probe_nr_irqs(void)
+{
+	int nr_irqs_gsi, nr = acpi_probe_gsi();
+
+	if (nr <= NR_IRQS_LEGACY) {
+		/* for acpi=off or acpi not compiled in */
+		int idx;
+
+		for (nr = idx = 0; idx < nr_ioapics; idx++)
+			nr += io_apic_get_redir_entries(idx) + 1;
+	}
+	nr_irqs_gsi = max(nr, NR_IRQS_LEGACY);
+
+	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+#ifdef CONFIG_PCI_MSI
+	nr += nr_irqs_gsi * 16;
+#endif
+	if (nr_pirqs > nr) {
+		nr_pirqs = nr;
+		nr_irqs = nr + NR_DYNIRQS;
+	}
+
+	printk(KERN_DEBUG "nr_irqs_gsi=%d nr_pirqs=%d\n",
+	       nr_irqs_gsi, nr_pirqs);
+
+	return 0;
+}
+#endif
+
+int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
+{
+	struct physdev_irq irq_op;
+
+	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= nr_pirqs)
+		return -EINVAL;
+
+	if (cfg->vector)
+		return 0;
+
+	irq_op.irq = irq;
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+		return -ENOSPC;
+
+	cfg->vector = irq_op.vector;
+
+	return 0;
+}
+#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
+#elif defined(CONFIG_X86)
+#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < NR_IRQS_LEGACY)
+#else
+#define identity_mapped_irq(irq) (1)
+#endif
+
+void evtchn_register_pirq(int irq)
+{
+	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE >= nr_pirqs);
+	if (identity_mapped_irq(irq) || type_from_irq(irq) != IRQT_UNBOUND)
+		return;
+	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, irq, 0);
+	set_irq_chip_and_handler_name(irq, &pirq_chip, handle_level_irq,
+				      "level");
+}
+
+int evtchn_map_pirq(int irq, int xen_pirq)
+{
+	if (irq < 0) {
+		static DEFINE_SPINLOCK(irq_alloc_lock);
+
+		irq = PIRQ_BASE + nr_pirqs - 1;
+		spin_lock(&irq_alloc_lock);
+		do {
+			struct irq_desc *desc;
+			struct irq_cfg *cfg;
+
+			if (identity_mapped_irq(irq))
+				continue;
+			desc = irq_to_desc_alloc_node(irq, numa_node_id());
+			cfg = desc->chip_data;
+			if (!index_from_irq(irq)) {
+				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
+				cfg->info = mk_irq_info(IRQT_PIRQ,
+							xen_pirq, 0);
+				break;
+			}
+		} while (--irq >= PIRQ_BASE);
+		spin_unlock(&irq_alloc_lock);
+		if (irq < PIRQ_BASE)
+			return -ENOSPC;
+		set_irq_chip_and_handler_name(irq, &pirq_chip,
+					      handle_level_irq, "level");
+	} else if (!xen_pirq) {
+		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
+			return -EINVAL;
+		/*
+		 * dynamic_irq_cleanup(irq) would seem to be the correct thing
+		 * here, but cannot be used as we get here also during shutdown
+		 * when a driver didn't free_irq() its MSI(-X) IRQ(s), which
+		 * then causes a warning in dynamic_irq_cleanup().
+		 */
+		set_irq_chip_and_handler(irq, NULL, NULL);
+		irq_cfg(irq)->info = IRQ_UNBOUND;
+		return 0;
+	} else if (type_from_irq(irq) != IRQT_PIRQ
+		   || index_from_irq(irq) != xen_pirq) {
+		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
+				"cannot map to PIRQ#%u\n",
+		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
+		return -EINVAL;
+	}
+	return index_from_irq(irq) ? irq : -EINVAL;
+}
+
+int evtchn_get_xen_pirq(int irq)
+{
+	if (identity_mapped_irq(irq))
+		return irq;
+	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
+	return index_from_irq(irq);
+}
+
+void __init xen_init_IRQ(void)
+{
+	unsigned int i;
+	struct physdev_pirq_eoi_gmfn eoi_gmfn;
+
+#ifndef PER_CPU_VIRQ_IRQ
+	__set_bit(VIRQ_TIMER, virq_per_cpu);
+	__set_bit(VIRQ_DEBUG, virq_per_cpu);
+	__set_bit(VIRQ_XENOPROF, virq_per_cpu);
+#ifdef CONFIG_IA64
+	__set_bit(VIRQ_ITC, virq_per_cpu);
+#endif
+#endif
+
+	init_evtchn_cpu_bindings();
+
+	i = get_order(sizeof(unsigned long) * BITS_TO_LONGS(nr_pirqs));
+	pirq_needs_eoi = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, i);
+	BUILD_BUG_ON(NR_PIRQS > PAGE_SIZE * 8);
+ 	eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
+	if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
+		pirq_eoi_does_unmask = true;
+
+	/* No event channels are 'live' right now. */
+	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+		mask_evtchn(i);
+
+#ifndef CONFIG_SPARSE_IRQ
+	for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
+		irq_to_desc(i)->status |= IRQ_NOPROBE;
+		set_irq_chip_and_handler_name(i, &dynirq_chip,
+					      handle_level_irq, "level");
+	}
+
+	for (i = PIRQ_BASE; i < (PIRQ_BASE + nr_pirqs); i++) {
+#else
+	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_IRQS_LEGACY); i++) {
+#endif
+		if (!identity_mapped_irq(i))
+			continue;
+
+#ifdef RTC_IRQ
+		/* If not domain 0, force our RTC driver to fail its probe. */
+		if (i - PIRQ_BASE == RTC_IRQ && !is_initial_xendomain())
+			continue;
+#endif
+
+		set_irq_chip_and_handler_name(i, &pirq_chip,
+					      handle_level_irq, "level");
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/xen/core/firmware.c
+++ linux-ec2-2.6.32/drivers/xen/core/firmware.c
@@ -0,0 +1,75 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/edd.h>
+#include <video/edid.h>
+#include <xen/interface/platform.h>
+#include <asm/hypervisor.h>
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+void __init copy_edd(void)
+{
+	int ret;
+	struct xen_platform_op op;
+
+	if (!is_initial_xendomain())
+		return;
+
+	op.cmd = XENPF_firmware_info;
+
+	op.u.firmware_info.type = XEN_FW_DISK_INFO;
+	for (op.u.firmware_info.index = 0;
+	     edd.edd_info_nr < EDDMAXNR;
+	     op.u.firmware_info.index++) {
+		struct edd_info *info = edd.edd_info + edd.edd_info_nr;
+
+		info->params.length = sizeof(info->params);
+		set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
+				     &info->params);
+		ret = HYPERVISOR_platform_op(&op);
+		if (ret)
+			break;
+
+#define C(x) info->x = op.u.firmware_info.u.disk_info.x
+		C(device);
+		C(version);
+		C(interface_support);
+		C(legacy_max_cylinder);
+		C(legacy_max_head);
+		C(legacy_sectors_per_track);
+#undef C
+
+		edd.edd_info_nr++;
+	}
+
+	op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
+	for (op.u.firmware_info.index = 0;
+	     edd.mbr_signature_nr < EDD_MBR_SIG_MAX;
+	     op.u.firmware_info.index++) {
+		ret = HYPERVISOR_platform_op(&op);
+		if (ret)
+			break;
+		edd.mbr_signature[edd.mbr_signature_nr++] =
+			op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
+	}
+}
+#endif
+
+void __init copy_edid(void)
+{
+#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
+	struct xen_platform_op op;
+
+	if (!is_initial_xendomain())
+		return;
+
+	op.cmd = XENPF_firmware_info;
+	op.u.firmware_info.index = 0;
+	op.u.firmware_info.type = XEN_FW_VBEDDC_INFO;
+	set_xen_guest_handle(op.u.firmware_info.u.vbeddc_info.edid,
+			     edid_info.dummy);
+	if (HYPERVISOR_platform_op(&op) != 0)
+		memset(edid_info.dummy, 0x13, sizeof(edid_info.dummy));
+#endif
+}
--- linux-ec2-2.6.32.orig/drivers/xen/core/pci.c
+++ linux-ec2-2.6.32/drivers/xen/core/pci.c
@@ -0,0 +1,83 @@
+/*
+ * vim:shiftwidth=8:noexpandtab
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <xen/interface/physdev.h>
+#include "../../pci/pci.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;
+	struct physdev_manage_pci_ext manage_pci_ext;
+
+#ifdef CONFIG_PCI_IOV
+	if (pci_dev->is_virtfn) {
+		memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
+		manage_pci_ext.bus = pci_dev->bus->number;
+		manage_pci_ext.devfn = pci_dev->devfn;
+		manage_pci_ext.is_virtfn = 1;
+		manage_pci_ext.physfn.bus = pci_dev->physfn->bus->number;
+		manage_pci_ext.physfn.devfn = pci_dev->physfn->devfn;
+		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
+					  &manage_pci_ext);
+	} else
+#endif
+	if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
+		memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
+		manage_pci_ext.bus = pci_dev->bus->number;
+		manage_pci_ext.devfn = pci_dev->devfn;
+		manage_pci_ext.is_extfn = 1;
+		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
+					  &manage_pci_ext);
+	} else {
+		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);
+	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);
--- linux-ec2-2.6.32.orig/drivers/xen/blkfront/block.h
+++ linux-ec2-2.6.32/drivers/xen/blkfront/block.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ * block.h
+ * 
+ * Shared definitions between all levels of XenLinux Virtual block devices.
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ * 
+ * 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_BLOCK_H__
+#define __XEN_DRIVERS_BLOCK_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/major.h>
+#include <asm/hypervisor.h>
+#include <xen/xenbus.h>
+#include <xen/gnttab.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/io/blkif.h>
+#include <xen/interface/io/ring.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+
+#define DPRINTK(_f, _a...) pr_debug(_f, ## _a)
+
+#if 0
+#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a)
+#else
+#define DPRINTK_IOCTL(_f, _a...) ((void)0)
+#endif
+
+struct xlbd_type_info
+{
+	int partn_shift;
+	int disks_per_major;
+	char *devname;
+	char *diskname;
+};
+
+struct xlbd_major_info
+{
+	int major;
+	int index;
+	int usage;
+	struct xlbd_type_info *type;
+};
+
+struct blk_shadow {
+	blkif_request_t req;
+	unsigned long request;
+	unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+
+#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+
+/*
+ * We have one of these per vbd, whether ide, scsi or 'other'.  They
+ * hang in private_data off the gendisk structure. We may end up
+ * putting all kinds of interesting stuff here :-)
+ */
+struct blkfront_info
+{
+	struct xenbus_device *xbdev;
+ 	struct gendisk *gd;
+	int vdevice;
+	blkif_vdev_t handle;
+	int connected;
+	int ring_ref;
+	blkif_front_ring_t ring;
+	struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	unsigned int irq;
+	struct xlbd_major_info *mi;
+	struct request_queue *rq;
+	struct work_struct work;
+	struct gnttab_free_callback callback;
+	struct blk_shadow shadow[BLK_RING_SIZE];
+	unsigned long shadow_free;
+	int feature_barrier;
+	int is_ready;
+
+	/**
+	 * The number of people holding this device open.  We won't allow a
+	 * hot-unplug unless this is 0.
+	 */
+	int users;
+};
+
+extern spinlock_t blkif_io_lock;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+extern int blkif_open(struct inode *inode, struct file *filep);
+extern int blkif_release(struct inode *inode, struct file *filep);
+extern int blkif_ioctl(struct inode *inode, struct file *filep,
+		       unsigned command, unsigned long argument);
+#else
+extern int blkif_open(struct block_device *bdev, fmode_t mode);
+extern int blkif_release(struct gendisk *disk, fmode_t mode);
+extern int blkif_ioctl(struct block_device *bdev, fmode_t mode,
+ 		       unsigned command, unsigned long argument);
+#endif
+extern int blkif_getgeo(struct block_device *, struct hd_geometry *);
+extern int blkif_check(dev_t dev);
+extern int blkif_revalidate(dev_t dev);
+extern void do_blkif_request (struct request_queue *rq);
+
+/* Virtual block-device subsystem. */
+/* Note that xlvbd_add doesn't call add_disk for you: you're expected
+   to call add_disk on info->gd once the disk is properly connected
+   up. */
+int xlvbd_add(blkif_sector_t capacity, int device,
+	      u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
+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
+
+/* Virtual cdrom block-device */
+extern void register_vcd(struct blkfront_info *info);
+extern void unregister_vcd(struct blkfront_info *info);
+
+#endif /* __XEN_DRIVERS_BLOCK_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/blkfront/vcd.c
+++ linux-ec2-2.6.32/drivers/xen/blkfront/vcd.c
@@ -0,0 +1,504 @@
+/*******************************************************************************
+* vcd.c
+*
+* Implements CDROM cmd packet passing between frontend guest and backend driver.
+*
+* Copyright (c) 2008, Pat Campell  plc@novell.com
+*
+* 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 REVISION "$Revision: 1.0 $"
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/list.h>
+#include <linux/cdrom.h>
+#include <xen/interface/io/cdromif.h>
+#include "block.h"
+
+/* List of cdrom_device_info, can have as many as blkfront supports */
+struct vcd_disk {
+	struct list_head vcd_entry;
+	struct cdrom_device_info vcd_cdrom_info;
+	spinlock_t vcd_cdrom_info_lock;
+};
+static LIST_HEAD(vcd_disks);
+static DEFINE_SPINLOCK(vcd_disks_lock);
+
+static struct vcd_disk *xencdrom_get_list_entry(struct gendisk *disk)
+{
+	struct vcd_disk *ret_vcd = NULL;
+	struct vcd_disk *vcd;
+
+	spin_lock(&vcd_disks_lock);
+	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
+		if (vcd->vcd_cdrom_info.disk == disk) {
+			spin_lock(&vcd->vcd_cdrom_info_lock);
+			ret_vcd = vcd;
+			break;
+		}
+	}
+	spin_unlock(&vcd_disks_lock);
+	return ret_vcd;
+}
+
+static void submit_message(struct blkfront_info *info, void *sp)
+{
+	struct request *req = NULL;
+
+	req = blk_get_request(info->rq, READ, __GFP_WAIT);
+	if (blk_rq_map_kern(info->rq, req, sp, PAGE_SIZE, __GFP_WAIT))
+		goto out;
+
+	req->rq_disk = info->gd;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->cmd_flags |= REQ_NOMERGE;
+#else
+	req->flags |= REQ_BLOCK_PC;
+#endif
+	req->__sector = 0;
+	req->__data_len = PAGE_SIZE;
+	req->timeout = 60*HZ;
+
+	blk_execute_rq(req->q, info->gd, req, 1);
+
+out:
+	blk_put_request(req);
+}
+
+static int submit_cdrom_cmd(struct blkfront_info *info,
+			    struct packet_command *cgc)
+{
+	int ret = 0;
+	struct page *page;
+	size_t size;
+	union xen_block_packet *sp;
+	struct xen_cdrom_packet *xcp;
+	struct vcd_generic_command *vgc;
+
+	if (cgc->buffer && cgc->buflen > MAX_PACKET_DATA) {
+		printk(KERN_WARNING "%s() Packet buffer length is to large \n", __func__);
+		return -EIO;
+	}
+
+	page = alloc_page(GFP_NOIO);
+	if (!page) {
+		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
+		return -ENOMEM;
+	}
+
+	size = PAGE_SIZE;
+	memset(page_address(page), 0, PAGE_SIZE);
+	sp = page_address(page);
+	xcp = &(sp->xcp);
+	xcp->type = XEN_TYPE_CDROM_PACKET;
+	xcp->payload_offset = PACKET_PAYLOAD_OFFSET;
+
+	vgc = (struct vcd_generic_command *)((char *)sp + xcp->payload_offset);
+	memcpy(vgc->cmd, cgc->cmd, CDROM_PACKET_SIZE);
+	vgc->stat = cgc->stat;
+	vgc->data_direction = cgc->data_direction;
+	vgc->quiet = cgc->quiet;
+	vgc->timeout = cgc->timeout;
+	if (cgc->sense) {
+		vgc->sense_offset = PACKET_SENSE_OFFSET;
+		memcpy((char *)sp + vgc->sense_offset, cgc->sense, sizeof(struct request_sense));
+	}
+	if (cgc->buffer) {
+		vgc->buffer_offset = PACKET_BUFFER_OFFSET;
+		memcpy((char *)sp + vgc->buffer_offset, cgc->buffer, cgc->buflen);
+		vgc->buflen = cgc->buflen;
+	}
+
+	submit_message(info,sp);
+
+	if (xcp->ret)
+		ret = xcp->err;
+
+	if (cgc->sense) {
+		memcpy(cgc->sense, (char *)sp + PACKET_SENSE_OFFSET, sizeof(struct request_sense));
+	}
+	if (cgc->buffer && cgc->buflen) {
+		memcpy(cgc->buffer, (char *)sp + PACKET_BUFFER_OFFSET, cgc->buflen);
+	}
+
+	__free_page(page);
+	return ret;
+}
+
+
+static int xencdrom_open(struct cdrom_device_info *cdi, int purpose)
+{
+	int ret = 0;
+	struct page *page;
+	struct blkfront_info *info;
+	union xen_block_packet *sp;
+	struct xen_cdrom_open *xco;
+
+	info = cdi->disk->private_data;
+
+	if (strlen(info->xbdev->otherend) > MAX_PACKET_DATA) {
+		return -EIO;
+	}
+
+	page = alloc_page(GFP_NOIO);
+	if (!page) {
+		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(page_address(page), 0, PAGE_SIZE);
+	sp = page_address(page);
+	xco = &(sp->xco);
+	xco->type = XEN_TYPE_CDROM_OPEN;
+	xco->payload_offset = sizeof(struct xen_cdrom_open);
+	strcpy((char *)sp + xco->payload_offset, info->xbdev->otherend);
+
+	submit_message(info,sp);
+
+	if (xco->ret) {
+		ret = xco->err;
+		goto out;
+	}
+
+	if (xco->media_present)
+		set_capacity(cdi->disk, xco->sectors);
+
+out:
+	__free_page(page);
+	return ret;
+}
+
+static void xencdrom_release(struct cdrom_device_info *cdi)
+{
+}
+
+static int xencdrom_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+{
+	int ret;
+	struct page *page;
+	struct blkfront_info *info;
+	union xen_block_packet *sp;
+	struct xen_cdrom_media_changed *xcmc;
+
+	info = cdi->disk->private_data;
+
+	page = alloc_page(GFP_NOIO);
+	if (!page) {
+		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(page_address(page), 0, PAGE_SIZE);
+	sp = page_address(page);
+	xcmc = &(sp->xcmc);
+	xcmc->type = XEN_TYPE_CDROM_MEDIA_CHANGED;
+	submit_message(info,sp);
+	ret = xcmc->media_changed;
+
+	__free_page(page);
+
+	return ret;
+}
+
+static int xencdrom_tray_move(struct cdrom_device_info *cdi, int position)
+{
+	int ret;
+	struct packet_command cgc;
+	struct blkfront_info *info;
+
+	info = cdi->disk->private_data;
+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
+	cgc.cmd[0] = GPCMD_START_STOP_UNIT;
+	if (position)
+		cgc.cmd[4] = 2;
+	else
+		cgc.cmd[4] = 3;
+	ret = submit_cdrom_cmd(info, &cgc);
+	return ret;
+}
+
+static int xencdrom_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+	int ret = 0;
+	struct blkfront_info *info;
+	struct packet_command cgc;
+
+	info = cdi->disk->private_data;
+	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
+	cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+	cgc.cmd[4] = lock;
+	ret = submit_cdrom_cmd(info, &cgc);
+	return ret;
+}
+
+static int xencdrom_packet(struct cdrom_device_info *cdi,
+		struct packet_command *cgc)
+{
+	int ret = -EIO;
+	struct blkfront_info *info;
+
+	info = cdi->disk->private_data;
+	ret = submit_cdrom_cmd(info, cgc);
+	cgc->stat = ret;
+	return ret;
+}
+
+static int xencdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+		void *arg)
+{
+	return -EINVAL;
+}
+
+/* Query backend to see if CDROM packets are supported */
+static int xencdrom_supported(struct blkfront_info *info)
+{
+	struct page *page;
+	union xen_block_packet *sp;
+	struct xen_cdrom_support *xcs;
+
+	page = alloc_page(GFP_NOIO);
+	if (!page) {
+		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(page_address(page), 0, PAGE_SIZE);
+	sp = page_address(page);
+	xcs = &(sp->xcs);
+	xcs->type = XEN_TYPE_CDROM_SUPPORT;
+	submit_message(info,sp);
+	return xcs->supported;
+}
+
+static struct cdrom_device_ops xencdrom_dops = {
+    .open           = xencdrom_open,
+    .release        = xencdrom_release,
+    .media_changed  = xencdrom_media_changed,
+    .tray_move      = xencdrom_tray_move,
+    .lock_door      = xencdrom_lock_door,
+    .generic_packet = xencdrom_packet,
+    .audio_ioctl    = xencdrom_audio_ioctl,
+    .capability     = (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | \
+                       CDC_MEDIA_CHANGED | CDC_GENERIC_PACKET |  CDC_DVD | \
+                       CDC_CD_R),
+    .n_minors       = 1,
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+static int xencdrom_block_open(struct inode *inode, struct file *file)
+{
+	struct block_device *bd = inode->i_bdev;
+#else
+static int xencdrom_block_open(struct block_device *bd, fmode_t mode)
+{
+#endif
+	struct blkfront_info *info = bd->bd_disk->private_data;
+	struct vcd_disk *vcd;
+	int ret = 0;
+
+	if ((vcd = xencdrom_get_list_entry(info->gd))) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+		ret = cdrom_open(&vcd->vcd_cdrom_info, inode, file);
+#else
+		ret = cdrom_open(&vcd->vcd_cdrom_info, bd, mode);
+#endif
+		info->users = vcd->vcd_cdrom_info.use_count;
+		spin_unlock(&vcd->vcd_cdrom_info_lock);
+	}
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+static int xencdrom_block_release(struct inode *inode, struct file *file)
+{
+	struct gendisk *gd = inode->i_bdev->bd_disk;
+#else
+static int xencdrom_block_release(struct gendisk *gd, fmode_t mode)
+{
+#endif
+	struct blkfront_info *info = gd->private_data;
+	struct vcd_disk *vcd;
+	int ret = 0;
+
+	if ((vcd = xencdrom_get_list_entry(info->gd))) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+		ret = cdrom_release(&vcd->vcd_cdrom_info, file);
+#else
+		cdrom_release(&vcd->vcd_cdrom_info, mode);
+#endif
+		spin_unlock(&vcd->vcd_cdrom_info_lock);
+		if (vcd->vcd_cdrom_info.use_count == 0) {
+			info->users = 1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+			blkif_release(inode, file);
+#else
+			blkif_release(gd, mode);
+#endif
+		}
+	}
+	return ret;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+static int xencdrom_block_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg)
+{
+	struct block_device *bd = inode->i_bdev;
+#else
+static int xencdrom_block_ioctl(struct block_device *bd, fmode_t mode,
+				unsigned cmd, unsigned long arg)
+{
+#endif
+	struct blkfront_info *info = bd->bd_disk->private_data;
+	struct vcd_disk *vcd;
+	int ret = 0;
+
+	if (!(vcd = xencdrom_get_list_entry(info->gd)))
+		goto out;
+
+	switch (cmd) {
+	case 2285: /* SG_IO */
+		ret = -ENOSYS;
+		break;
+	case CDROMEJECT:
+		ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 1);
+		break;
+	case CDROMCLOSETRAY:
+		ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 0);
+		break;
+	case CDROM_GET_CAPABILITY:
+		ret = vcd->vcd_cdrom_info.ops->capability & ~vcd->vcd_cdrom_info.mask;
+		break;
+	case CDROM_SET_OPTIONS:
+		ret = vcd->vcd_cdrom_info.options;
+		break;
+	case CDROM_SEND_PACKET:
+		ret = submit_cdrom_cmd(info, (struct packet_command *)arg);
+		break;
+	default:
+		/* Not supported, augment supported above if necessary */
+		printk("%s():%d Unsupported IOCTL:%x \n", __func__, __LINE__, cmd);
+		ret = -ENOTTY;
+		break;
+	}
+	spin_unlock(&vcd->vcd_cdrom_info_lock);
+out:
+	return ret;
+}
+
+/* Called as result of cdrom_open, vcd_cdrom_info_lock already held */
+static int xencdrom_block_media_changed(struct gendisk *disk)
+{
+	struct vcd_disk *vcd;
+	struct vcd_disk *ret_vcd = NULL;
+	int ret = 0;
+
+	spin_lock(&vcd_disks_lock);
+	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
+		if (vcd->vcd_cdrom_info.disk == disk) {
+			ret_vcd = vcd;
+			break;
+		}
+	}
+	spin_unlock(&vcd_disks_lock);
+	if (ret_vcd) {
+		ret = cdrom_media_changed(&ret_vcd->vcd_cdrom_info);
+	}
+	return ret;
+}
+
+static struct block_device_operations xencdrom_bdops =
+{
+	.owner		= THIS_MODULE,
+	.open		= xencdrom_block_open,
+	.release	= xencdrom_block_release,
+	.ioctl		= xencdrom_block_ioctl,
+	.media_changed	= xencdrom_block_media_changed,
+};
+
+void register_vcd(struct blkfront_info *info)
+{
+	struct gendisk *gd = info->gd;
+	struct vcd_disk *vcd;
+
+	/* Make sure this is for a CD device */
+	if (!(gd->flags & GENHD_FL_CD))
+		goto out;
+
+	/* Make sure we have backend support */
+	if (!xencdrom_supported(info)) {
+		goto out;
+	}
+
+	/* Create new vcd_disk and fill in cdrom_info */
+	vcd = (struct vcd_disk *)kzalloc(sizeof(struct vcd_disk), GFP_KERNEL);
+	if (!vcd) {
+		printk(KERN_INFO "%s():  Unable to allocate vcd struct!\n", __func__);
+		goto out;
+	}
+	spin_lock_init(&vcd->vcd_cdrom_info_lock);
+
+	vcd->vcd_cdrom_info.ops	= &xencdrom_dops;
+	vcd->vcd_cdrom_info.speed = 4;
+	vcd->vcd_cdrom_info.capacity = 1;
+	vcd->vcd_cdrom_info.options	= 0;
+	strcpy(vcd->vcd_cdrom_info.name, gd->disk_name);
+	vcd->vcd_cdrom_info.mask = (CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM |
+			CDC_SELECT_DISC | CDC_SELECT_SPEED |
+			CDC_MRW | CDC_MRW_W | CDC_RAM);
+
+	if (register_cdrom(&(vcd->vcd_cdrom_info)) != 0) {
+		printk(KERN_WARNING "%s() Cannot register blkdev as a cdrom %d!\n", __func__,
+				gd->major);
+		goto err_out;
+	}
+	xencdrom_bdops.owner = gd->fops->owner;
+	gd->fops = &xencdrom_bdops;
+	vcd->vcd_cdrom_info.disk = gd;
+
+	spin_lock(&vcd_disks_lock);
+	list_add(&(vcd->vcd_entry), &vcd_disks);
+	spin_unlock(&vcd_disks_lock);
+out:
+	return;
+err_out:
+	kfree(vcd);
+}
+
+void unregister_vcd(struct blkfront_info *info) {
+	struct gendisk *gd = info->gd;
+	struct vcd_disk *vcd;
+
+	spin_lock(&vcd_disks_lock);
+	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
+		if (vcd->vcd_cdrom_info.disk == gd) {
+			spin_lock(&vcd->vcd_cdrom_info_lock);
+			unregister_cdrom(&vcd->vcd_cdrom_info);
+			list_del(&vcd->vcd_entry);
+			spin_unlock(&vcd->vcd_cdrom_info_lock);
+			kfree(vcd);
+			break;
+		}
+	}
+	spin_unlock(&vcd_disks_lock);
+}
+
--- linux-ec2-2.6.32.orig/drivers/xen/blkfront/vbd.c
+++ linux-ec2-2.6.32/drivers/xen/blkfront/vbd.c
@@ -0,0 +1,443 @@
+/******************************************************************************
+ * vbd.c
+ * 
+ * XenLinux virtual block-device driver (xvd).
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004-2005, Christian Limpach
+ * 
+ * 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 "block.h"
+#include <linux/blkdev.h>
+#include <linux/list.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#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
+ * places.
+ */
+
+#define NUM_IDE_MAJORS 10
+#define NUM_SCSI_MAJORS 17
+#define NUM_VBD_MAJORS 2
+
+static struct xlbd_type_info xlbd_ide_type = {
+	.partn_shift = 6,
+	.disks_per_major = 2,
+	.devname = "ide",
+	.diskname = "hd",
+};
+
+static struct xlbd_type_info xlbd_scsi_type = {
+	.partn_shift = 4,
+	.disks_per_major = 16,
+	.devname = "sd",
+	.diskname = "sd",
+};
+
+static struct xlbd_type_info xlbd_vbd_type = {
+	.partn_shift = 4,
+	.disks_per_major = 16,
+	.devname = "xvd",
+	.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];
+
+#define XLBD_MAJOR_IDE_START	0
+#define XLBD_MAJOR_SCSI_START	(NUM_IDE_MAJORS)
+#define XLBD_MAJOR_VBD_START	(NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
+
+#define XLBD_MAJOR_IDE_RANGE	XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
+#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
+
+static const struct block_device_operations xlvbd_block_fops =
+{
+	.owner = THIS_MODULE,
+	.open = blkif_open,
+	.release = blkif_release,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+	.ioctl  = blkif_ioctl,
+#else
+	.locked_ioctl  = blkif_ioctl,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+	.getgeo = blkif_getgeo
+#endif
+};
+
+DEFINE_SPINLOCK(blkif_io_lock);
+
+static struct xlbd_major_info *
+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:
+		ptr->type = &xlbd_ide_type;
+		ptr->index = index - XLBD_MAJOR_IDE_START;
+		break;
+	case XLBD_MAJOR_SCSI_RANGE:
+		ptr->type = &xlbd_scsi_type;
+		ptr->index = index - XLBD_MAJOR_SCSI_START;
+		break;
+	case XLBD_MAJOR_VBD_RANGE:
+		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 (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);
+	}
+
+	major_info[index] = ptr;
+	return ptr;
+}
+
+static struct xlbd_major_info *
+xlbd_get_major_info(int major, int minor, int vdevice)
+{
+	struct xlbd_major_info *mi;
+	int index;
+
+	switch (major) {
+	case IDE0_MAJOR: index = 0; break;
+	case IDE1_MAJOR: index = 1; break;
+	case IDE2_MAJOR: index = 2; break;
+	case IDE3_MAJOR: index = 3; break;
+	case IDE4_MAJOR: index = 4; break;
+	case IDE5_MAJOR: index = 5; break;
+	case IDE6_MAJOR: index = 6; break;
+	case IDE7_MAJOR: index = 7; break;
+	case IDE8_MAJOR: index = 8; break;
+	case IDE9_MAJOR: index = 9; break;
+	case SCSI_DISK0_MAJOR: index = 10; break;
+	case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
+		index = 11 + major - SCSI_DISK1_MAJOR;
+		break;
+        case SCSI_DISK8_MAJOR ... SCSI_DISK15_MAJOR:
+                index = 18 + major - SCSI_DISK8_MAJOR;
+                break;
+        case SCSI_CDROM_MAJOR: index = 26; break;
+        default:
+		if (!VDEV_IS_EXTENDED(vdevice))
+			index = 27;
+		else
+			index = 28;
+		break;
+	}
+
+	mi = ((major_info[index] != NULL) ? major_info[index] :
+	      xlbd_alloc_major_info(major, minor, index));
+	if (mi)
+		mi->usage++;
+	return mi;
+}
+
+static void
+xlbd_put_major_info(struct xlbd_major_info *mi)
+{
+	mi->usage--;
+	/* XXX: release major if 0 */
+}
+
+static int
+xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
+{
+	struct request_queue *rq;
+
+	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
+	if (rq == NULL)
+		return -1;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
+#endif
+
+	/* Hard sector size and max sectors impersonate the equiv. hardware. */
+	blk_queue_logical_block_size(rq, sector_size);
+	blk_queue_max_sectors(rq, 512);
+
+	/* Each segment in a request is up to an aligned page in size. */
+	blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
+	blk_queue_max_segment_size(rq, PAGE_SIZE);
+
+	/* Ensure a merged request will fit in a single I/O ring slot. */
+	blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+	/* Make sure buffer addresses are sector-aligned. */
+	blk_queue_dma_alignment(rq, 511);
+
+	/* Make sure we don't use bounce buffers. */
+	blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
+
+	gd->queue = rq;
+
+	return 0;
+}
+
+int
+xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info,
+	  u16 sector_size, struct blkfront_info *info)
+{
+	int major, minor;
+	struct gendisk *gd;
+	struct xlbd_major_info *mi;
+	int nr_minors = 1;
+	int err = -ENODEV;
+	unsigned int offset;
+
+	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;
+	}
+
+	if (!VDEV_IS_EXTENDED(vdevice)) {
+		major = BLKIF_MAJOR(vdevice);
+		minor = BLKIF_MINOR(vdevice);
+	}
+	else {
+		major = 202;
+		minor = BLKIF_MINOR_EXT(vdevice);
+	}
+
+	BUG_ON(info->gd != NULL);
+	BUG_ON(info->mi != NULL);
+	BUG_ON(info->rq != NULL);
+
+	mi = xlbd_get_major_info(major, minor, vdevice);
+	if (mi == NULL)
+		goto out;
+	info->mi = mi;
+
+	if (!(vdisk_info & VDISK_CDROM) &&
+	    (minor & ((1 << mi->type->partn_shift) - 1)) == 0)
+		nr_minors = 1 << mi->type->partn_shift;
+
+	gd = alloc_disk(nr_minors);
+	if (gd == NULL)
+		goto out;
+
+	offset =  mi->index * mi->type->disks_per_major +
+			(minor >> mi->type->partn_shift);
+	if (nr_minors > 1 || (vdisk_info & VDISK_CDROM)) {
+		if (offset < 26) {
+			sprintf(gd->disk_name, "%s%c",
+				 mi->type->diskname, 'a' + offset );
+		}
+		else {
+			sprintf(gd->disk_name, "%s%c%c",
+				mi->type->diskname,
+				'a' + ((offset/26)-1), 'a' + (offset%26) );
+		}
+	}
+	else {
+		if (offset < 26) {
+			sprintf(gd->disk_name, "%s%c%d",
+				mi->type->diskname,
+				'a' + offset,
+				minor & ((1 << mi->type->partn_shift) - 1));
+		}
+		else {
+			sprintf(gd->disk_name, "%s%c%c%d",
+				mi->type->diskname,
+				'a' + ((offset/26)-1), 'a' + (offset%26),
+				minor & ((1 << mi->type->partn_shift) - 1));
+		}
+	}
+
+	gd->major = mi->major;
+	gd->first_minor = minor;
+	gd->fops = &xlvbd_block_fops;
+	gd->private_data = info;
+	gd->driverfs_dev = &(info->xbdev->dev);
+	set_capacity(gd, capacity);
+
+	if (xlvbd_init_blk_queue(gd, sector_size)) {
+		del_gendisk(gd);
+		goto out;
+	}
+
+	info->rq = gd->queue;
+	info->gd = gd;
+
+	if (info->feature_barrier)
+		xlvbd_barrier(info);
+
+	if (vdisk_info & VDISK_READONLY)
+		set_disk_ro(gd, 1);
+
+	if (vdisk_info & VDISK_REMOVABLE)
+		gd->flags |= GENHD_FL_REMOVABLE;
+
+	if (vdisk_info & VDISK_CDROM)
+		gd->flags |= GENHD_FL_CD;
+
+	return 0;
+
+ out:
+	if (mi)
+		xlbd_put_major_info(mi);
+	info->mi = NULL;
+	return err;
+}
+
+void
+xlvbd_del(struct blkfront_info *info)
+{
+	if (info->mi == NULL)
+		return;
+
+	BUG_ON(info->gd == NULL);
+	del_gendisk(info->gd);
+	put_disk(info->gd);
+	info->gd = NULL;
+
+	xlbd_put_major_info(info->mi);
+	info->mi = NULL;
+
+	BUG_ON(info->rq == NULL);
+	blk_cleanup_queue(info->rq);
+	info->rq = NULL;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+int
+xlvbd_barrier(struct blkfront_info *info)
+{
+	int err;
+
+	err = blk_queue_ordered(info->rq,
+		info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, NULL);
+	if (err)
+		return err;
+	printk(KERN_INFO "blkfront: %s: barriers %s\n",
+	       info->gd->disk_name, info->feature_barrier ? "enabled" : "disabled");
+	return 0;
+}
+#else
+int
+xlvbd_barrier(struct blkfront_info *info)
+{
+	printk(KERN_INFO "blkfront: %s: barriers disabled\n", info->gd->disk_name);
+	return -ENOSYS;
+}
+#endif
+
+#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 = dev_get_drvdata(&xendev->dev);
+
+	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 */
--- linux-ec2-2.6.32.orig/drivers/xen/blkfront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/blkfront/Makefile
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	:= xenblk.o
+
+xenblk-objs := blkfront.o vbd.o vcd.o
+
--- linux-ec2-2.6.32.orig/drivers/xen/blkfront/blkfront.c
+++ linux-ec2-2.6.32/drivers/xen/blkfront/blkfront.c
@@ -0,0 +1,955 @@
+/******************************************************************************
+ * blkfront.c
+ * 
+ * XenLinux virtual block-device driver.
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ * Copyright (c) 2004, Christian Limpach
+ * Copyright (c) 2004, Andrew Warfield
+ * Copyright (c) 2005, Christopher Clark
+ * Copyright (c) 2005, XenSource Ltd
+ * 
+ * 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 "block.h"
+#include <linux/cdrom.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <scsi/scsi.h>
+#include <xen/evtchn.h>
+#include <xen/xenbus.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/protocols.h>
+#include <xen/gnttab.h>
+#include <asm/hypervisor.h>
+#include <asm/maddr.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#define BLKIF_STATE_DISCONNECTED 0
+#define BLKIF_STATE_CONNECTED    1
+#define BLKIF_STATE_SUSPENDED    2
+
+#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
+    (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE)
+#define GRANT_INVALID_REF	0
+
+static void connect(struct blkfront_info *);
+static void blkfront_closing(struct xenbus_device *);
+static int blkfront_remove(struct xenbus_device *);
+static int talk_to_backend(struct xenbus_device *, struct blkfront_info *);
+static int setup_blkring(struct xenbus_device *, struct blkfront_info *);
+
+static void kick_pending_request_queues(struct blkfront_info *);
+
+static irqreturn_t blkif_int(int irq, void *dev_id);
+static void blkif_restart_queue(struct work_struct *arg);
+static void blkif_recover(struct blkfront_info *);
+static void blkif_completion(struct blk_shadow *);
+static void blkif_free(struct blkfront_info *, int);
+
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures and the ring buffer for communication with the backend, and
+ * inform the backend of the appropriate details for those.  Switch to
+ * Initialised state.
+ */
+static int blkfront_probe(struct xenbus_device *dev,
+			  const struct xenbus_device_id *id)
+{
+	int err, vdevice, i;
+	struct blkfront_info *info;
+
+	/* FIXME: Use dynamic device id if this is not set. */
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+			   "virtual-device", "%i", &vdevice);
+	if (err != 1) {
+		/* 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);
+	if (!info) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+		return -ENOMEM;
+	}
+
+	info->xbdev = dev;
+	info->vdevice = vdevice;
+	info->connected = BLKIF_STATE_DISCONNECTED;
+	INIT_WORK(&info->work, blkif_restart_queue);
+
+	for (i = 0; i < BLK_RING_SIZE; i++)
+		info->shadow[i].req.id = i+1;
+	info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+	/* Front end dir is a number, which is used as the id. */
+	info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
+	dev_set_drvdata(&dev->dev, info);
+
+	err = talk_to_backend(dev, info);
+	if (err) {
+		kfree(info);
+		dev_set_drvdata(&dev->dev, NULL);
+		return err;
+	}
+
+	return 0;
+}
+
+
+/**
+ * We are reconnecting to the backend, due to a suspend/resume, or a backend
+ * driver restart.  We tear down our blkif structure and recreate it, but
+ * leave the device-layer structures intact so that this is transparent to the
+ * rest of the kernel.
+ */
+static int blkfront_resume(struct xenbus_device *dev)
+{
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+	int err;
+
+	DPRINTK("blkfront_resume: %s\n", dev->nodename);
+
+	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
+
+	err = talk_to_backend(dev, info);
+	if (info->connected == BLKIF_STATE_SUSPENDED && !err)
+		blkif_recover(info);
+
+	return err;
+}
+
+
+/* Common code used when first setting up, and when resuming. */
+static int talk_to_backend(struct xenbus_device *dev,
+			   struct blkfront_info *info)
+{
+	const char *message = NULL;
+	struct xenbus_transaction xbt;
+	int err;
+
+	/* Create shared ring, alloc event channel. */
+	err = setup_blkring(dev, info);
+	if (err)
+		goto out;
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		goto destroy_blkring;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename,
+			    "ring-ref","%u", info->ring_ref);
+	if (err) {
+		message = "writing ring-ref";
+		goto abort_transaction;
+	}
+	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    irq_to_evtchn_port(info->irq));
+	if (err) {
+		message = "writing event-channel";
+		goto abort_transaction;
+	}
+	err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
+			    XEN_IO_PROTO_ABI_NATIVE);
+	if (err) {
+		message = "writing protocol";
+		goto abort_transaction;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err) {
+		if (err == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto destroy_blkring;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+
+	return 0;
+
+ abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	if (message)
+		xenbus_dev_fatal(dev, err, "%s", message);
+ destroy_blkring:
+	blkif_free(info, 0);
+ out:
+	return err;
+}
+
+
+static int setup_blkring(struct xenbus_device *dev,
+			 struct blkfront_info *info)
+{
+	blkif_sring_t *sring;
+	int err;
+
+	info->ring_ref = GRANT_INVALID_REF;
+
+	sring = (blkif_sring_t *)__get_free_page(GFP_NOIO | __GFP_HIGH);
+	if (!sring) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+		return -ENOMEM;
+	}
+	SHARED_RING_INIT(sring);
+	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
+
+	sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
+	if (err < 0) {
+		free_page((unsigned long)sring);
+		info->ring.sring = NULL;
+		goto fail;
+	}
+	info->ring_ref = err;
+
+	err = bind_listening_port_to_irqhandler(
+		dev->otherend_id, blkif_int, IRQF_SAMPLE_RANDOM, "blkif", info);
+	if (err <= 0) {
+		xenbus_dev_fatal(dev, err,
+				 "bind_listening_port_to_irqhandler");
+		goto fail;
+	}
+	info->irq = err;
+
+	return 0;
+fail:
+	blkif_free(info, 0);
+	return err;
+}
+
+
+/**
+ * Callback received when the backend's state changes.
+ */
+static void backend_changed(struct xenbus_device *dev,
+			    enum xenbus_state backend_state)
+{
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+	struct block_device *bd;
+
+	DPRINTK("blkfront:backend_changed.\n");
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitWait:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateConnected:
+		connect(info);
+		break;
+
+	case XenbusStateClosing:
+		if (!info->gd) {
+			xenbus_frontend_closed(dev);
+			break;
+		}
+		bd = bdget_disk(info->gd, 0);
+		if (bd == NULL)
+			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+		down(&bd->bd_sem);
+#else
+		mutex_lock(&bd->bd_mutex);
+#endif
+		if (info->users > 0)
+			xenbus_dev_error(dev, -EBUSY,
+					 "Device in use; refusing to close");
+		else
+			blkfront_closing(dev);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
+		up(&bd->bd_sem);
+#else
+		mutex_unlock(&bd->bd_mutex);
+#endif
+		bdput(bd);
+		break;
+	}
+}
+
+
+/* ** Connection ** */
+
+
+/*
+ * Invoked when the backend is finally 'ready' (and has told produced
+ * the details about the physical device - #sectors, size, etc).
+ */
+static void connect(struct blkfront_info *info)
+{
+	unsigned long long sectors;
+	unsigned long sector_size;
+	unsigned int binfo;
+	int err;
+
+	if ((info->connected == BLKIF_STATE_CONNECTED) ||
+	    (info->connected == BLKIF_STATE_SUSPENDED) )
+		return;
+
+	DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend);
+
+	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			    "sectors", "%Lu", &sectors,
+			    "info", "%u", &binfo,
+			    "sector-size", "%lu", &sector_size,
+			    NULL);
+	if (err) {
+		xenbus_dev_fatal(info->xbdev, err,
+				 "reading backend fields at %s",
+				 info->xbdev->otherend);
+		return;
+	}
+
+	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+			    "feature-barrier", "%lu", &info->feature_barrier,
+			    NULL);
+	if (err)
+		info->feature_barrier = 0;
+
+	err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
+	if (err) {
+		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
+				 info->xbdev->otherend);
+		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. */
+	spin_lock_irq(&blkif_io_lock);
+	info->connected = BLKIF_STATE_CONNECTED;
+	kick_pending_request_queues(info);
+	spin_unlock_irq(&blkif_io_lock);
+
+	add_disk(info->gd);
+
+	info->is_ready = 1;
+
+	register_vcd(info);
+}
+
+/**
+ * Handle the change of state of the backend to Closing.  We must delete our
+ * device-layer structures now, to ensure that writes are flushed through to
+ * the backend.  Once is this done, we can switch to Closed in
+ * acknowledgement.
+ */
+static void blkfront_closing(struct xenbus_device *dev)
+{
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+	unsigned long flags;
+
+	DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
+
+	if (info->rq == NULL)
+		goto out;
+
+	spin_lock_irqsave(&blkif_io_lock, flags);
+	/* No more blkif_request(). */
+	blk_stop_queue(info->rq);
+	/* No more gnttab callback work. */
+	gnttab_cancel_free_callback(&info->callback);
+	spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+	/* Flush gnttab callback work. Must be done with no locks held. */
+	flush_scheduled_work();
+
+	xlvbd_sysfs_delif(info);
+
+	unregister_vcd(info);
+
+	xlvbd_del(info);
+
+ out:
+	xenbus_frontend_closed(dev);
+}
+
+
+static int blkfront_remove(struct xenbus_device *dev)
+{
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+
+	DPRINTK("blkfront_remove: %s removed\n", dev->nodename);
+
+	blkif_free(info, 0);
+
+	kfree(info);
+
+	return 0;
+}
+
+
+static inline int GET_ID_FROM_FREELIST(
+	struct blkfront_info *info)
+{
+	unsigned long free = info->shadow_free;
+	BUG_ON(free >= BLK_RING_SIZE);
+	info->shadow_free = info->shadow[free].req.id;
+	info->shadow[free].req.id = 0x0fffffee; /* debug */
+	return free;
+}
+
+static inline void ADD_ID_TO_FREELIST(
+	struct blkfront_info *info, unsigned long id)
+{
+	info->shadow[id].req.id  = info->shadow_free;
+	info->shadow[id].request = 0;
+	info->shadow_free = id;
+}
+
+static inline void flush_requests(struct blkfront_info *info)
+{
+	int notify;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);
+
+	if (notify)
+		notify_remote_via_irq(info->irq);
+}
+
+static void kick_pending_request_queues(struct blkfront_info *info)
+{
+	if (!RING_FULL(&info->ring)) {
+		/* Re-enable calldowns. */
+		blk_start_queue(info->rq);
+		/* Kick things off immediately. */
+		do_blkif_request(info->rq);
+	}
+}
+
+static void blkif_restart_queue(struct work_struct *arg)
+{
+	struct blkfront_info *info = container_of(arg, struct blkfront_info, work);
+	spin_lock_irq(&blkif_io_lock);
+	if (info->connected == BLKIF_STATE_CONNECTED)
+		kick_pending_request_queues(info);
+	spin_unlock_irq(&blkif_io_lock);
+}
+
+static void blkif_restart_queue_callback(void *arg)
+{
+	struct blkfront_info *info = (struct blkfront_info *)arg;
+	schedule_work(&info->work);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+int blkif_open(struct inode *inode, struct file *filep)
+{
+	struct block_device *bd = inode->i_bdev;
+#else
+int blkif_open(struct block_device *bd, fmode_t mode)
+{
+#endif
+	struct blkfront_info *info = bd->bd_disk->private_data;
+
+	info->users++;
+	return 0;
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+int blkif_release(struct inode *inode, struct file *filep)
+{
+	struct gendisk *disk = inode->i_bdev->bd_disk;
+#else
+int blkif_release(struct gendisk *disk, fmode_t mode)
+{
+#endif
+	struct blkfront_info *info = disk->private_data;
+
+	info->users--;
+	if (info->users == 0) {
+		/* Check whether we have been instructed to close.  We will
+		   have ignored this request initially, as the device was
+		   still mounted. */
+		struct xenbus_device * dev = info->xbdev;
+		enum xenbus_state state = xenbus_read_driver_state(dev->otherend);
+
+		if (state == XenbusStateClosing && info->is_ready)
+			blkfront_closing(dev);
+	}
+	return 0;
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+int blkif_ioctl(struct inode *inode, struct file *filep,
+		unsigned command, unsigned long argument)
+{
+	struct block_device *bd = inode->i_bdev;
+#else
+int blkif_ioctl(struct block_device *bd, fmode_t mode,
+		unsigned command, unsigned long argument)
+{
+#endif
+	int i;
+
+	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+		      command, (long)argument, inode->i_rdev);
+
+	switch (command) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+	case HDIO_GETGEO: {
+		struct hd_geometry geo;
+		int ret;
+
+                if (!argument)
+                        return -EINVAL;
+
+		geo.start = get_start_sect(bd);
+		ret = blkif_getgeo(bd, &geo);
+		if (ret)
+			return ret;
+
+		if (copy_to_user((struct hd_geometry __user *)argument, &geo,
+				 sizeof(geo)))
+                        return -EFAULT;
+
+                return 0;
+	}
+#endif
+	case CDROMMULTISESSION:
+		DPRINTK("FIXME: support multisession CDs later\n");
+		for (i = 0; i < sizeof(struct cdrom_multisession); i++)
+			if (put_user(0, (char __user *)(argument + i)))
+				return -EFAULT;
+		return 0;
+
+	case CDROM_GET_CAPABILITY: {
+		struct blkfront_info *info = bd->bd_disk->private_data;
+		struct gendisk *gd = info->gd;
+		if (gd->flags & GENHD_FL_CD)
+			return 0;
+		return -EINVAL;
+	}
+	default:
+		/*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+		  command);*/
+		return -EINVAL; /* same return as native Linux */
+	}
+
+	return 0;
+}
+
+
+int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
+{
+	/* We don't have real geometry info, but let's at least return
+	   values consistent with the size of the device */
+	sector_t nsect = get_capacity(bd->bd_disk);
+	sector_t cylinders = nsect;
+
+	hg->heads = 0xff;
+	hg->sectors = 0x3f;
+	sector_div(cylinders, hg->heads * hg->sectors);
+	hg->cylinders = cylinders;
+	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
+		hg->cylinders = 0xffff;
+	return 0;
+}
+
+
+/*
+ * blkif_queue_request
+ *
+ * request block io
+ *
+ * id: for guest use only.
+ * operation: BLKIF_OP_{READ,WRITE,PROBE}
+ * buffer: buffer to read/write into. this should be a
+ *   virtual address in the guest os.
+ */
+static int blkif_queue_request(struct request *req)
+{
+	struct blkfront_info *info = req->rq_disk->private_data;
+	unsigned long buffer_mfn;
+	blkif_request_t *ring_req;
+	unsigned long id;
+	unsigned int fsect, lsect;
+	int i, ref;
+	grant_ref_t gref_head;
+	struct scatterlist *sg;
+
+	if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+		return 1;
+
+	if (gnttab_alloc_grant_references(
+		BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) {
+		gnttab_request_free_callback(
+			&info->callback,
+			blkif_restart_queue_callback,
+			info,
+			BLKIF_MAX_SEGMENTS_PER_REQUEST);
+		return 1;
+	}
+
+	/* Fill out a communications ring structure. */
+	ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+	id = GET_ID_FROM_FREELIST(info);
+	info->shadow[id].request = (unsigned long)req;
+
+	ring_req->id = id;
+	ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
+	ring_req->handle = info->handle;
+
+	ring_req->operation = rq_data_dir(req) ?
+		BLKIF_OP_WRITE : BLKIF_OP_READ;
+	if (blk_barrier_rq(req))
+		ring_req->operation = BLKIF_OP_WRITE_BARRIER;
+	if (blk_pc_request(req))
+		ring_req->operation = BLKIF_OP_PACKET;
+
+	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+	for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+			buffer_mfn = page_to_phys(sg_page(sg)) >> PAGE_SHIFT;
+			fsect = sg->offset >> 9;
+			lsect = fsect + (sg->length >> 9) - 1;
+			/* install a grant reference. */
+			ref = gnttab_claim_grant_reference(&gref_head);
+			BUG_ON(ref == -ENOSPC);
+
+			gnttab_grant_foreign_access_ref(
+				ref,
+				info->xbdev->otherend_id,
+				buffer_mfn,
+				rq_data_dir(req) ? GTF_readonly : 0 );
+
+			info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+			ring_req->seg[i] =
+				(struct blkif_request_segment) {
+					.gref       = ref,
+					.first_sect = fsect,
+					.last_sect  = lsect };
+	}
+
+	info->ring.req_prod_pvt++;
+
+	/* Keep a private copy so we can reissue requests when recovering. */
+	info->shadow[id].req = *ring_req;
+
+	gnttab_free_grant_references(gref_head);
+
+	return 0;
+}
+
+/*
+ * do_blkif_request
+ *  read a block; request is in a request queue
+ */
+void do_blkif_request(struct request_queue *rq)
+{
+	struct blkfront_info *info = NULL;
+	struct request *req;
+	int queued;
+
+	DPRINTK("Entered do_blkif_request\n");
+
+	queued = 0;
+
+	while ((req = blk_peek_request(rq)) != NULL) {
+		info = req->rq_disk->private_data;
+
+		if (RING_FULL(&info->ring))
+			goto wait;
+
+		blk_start_request(req);
+
+		if (!blk_fs_request(req) && !blk_pc_request(req)) {
+			__blk_end_request_all(req, -EIO);
+			continue;
+		}
+
+		DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
+			"(%u/%u) buffer:%p [%s]\n",
+			req, req->cmd, (long long)blk_rq_pos(req),
+			blk_rq_cur_sectors(req), blk_rq_sectors(req),
+			req->buffer, rq_data_dir(req) ? "write" : "read");
+
+		if (blkif_queue_request(req)) {
+			blk_requeue_request(rq, req);
+		wait:
+			/* Avoid pointless unplugs. */
+			blk_stop_queue(rq);
+			break;
+		}
+
+		queued++;
+	}
+
+	if (queued != 0)
+		flush_requests(info);
+}
+
+
+static irqreturn_t blkif_int(int irq, void *dev_id)
+{
+	struct request *req;
+	blkif_response_t *bret;
+	RING_IDX i, rp;
+	unsigned long flags;
+	struct blkfront_info *info = (struct blkfront_info *)dev_id;
+
+	spin_lock_irqsave(&blkif_io_lock, flags);
+
+	if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
+		spin_unlock_irqrestore(&blkif_io_lock, flags);
+		return IRQ_HANDLED;
+	}
+
+ again:
+	rp = info->ring.sring->rsp_prod;
+	rmb(); /* Ensure we see queued responses up to 'rp'. */
+
+	for (i = info->ring.rsp_cons; i != rp; i++) {
+		unsigned long id;
+		int ret;
+
+		bret = RING_GET_RESPONSE(&info->ring, i);
+		id   = bret->id;
+		req  = (struct request *)info->shadow[id].request;
+
+		blkif_completion(&info->shadow[id]);
+
+		ADD_ID_TO_FREELIST(info, id);
+
+		ret = bret->status == BLKIF_RSP_OKAY ? 0 : -EIO;
+		switch (bret->operation) {
+		case BLKIF_OP_WRITE_BARRIER:
+			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+				printk("blkfront: %s: write barrier op failed\n",
+				       info->gd->disk_name);
+				ret = -EOPNOTSUPP;
+				info->feature_barrier = 0;
+			        xlvbd_barrier(info);
+			}
+			/* fall through */
+		case BLKIF_OP_READ:
+		case BLKIF_OP_WRITE:
+		case BLKIF_OP_PACKET:
+			if (unlikely(bret->status != BLKIF_RSP_OKAY))
+				DPRINTK("Bad return from blkdev data "
+					"request: %x\n", bret->status);
+
+			__blk_end_request_all(req, ret);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	info->ring.rsp_cons = i;
+
+	if (i != info->ring.req_prod_pvt) {
+		int more_to_do;
+		RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
+		if (more_to_do)
+			goto again;
+	} else
+		info->ring.sring->rsp_event = i + 1;
+
+	kick_pending_request_queues(info);
+
+	spin_unlock_irqrestore(&blkif_io_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static void blkif_free(struct blkfront_info *info, int suspend)
+{
+	/* Prevent new requests being issued until we fix things up. */
+	spin_lock_irq(&blkif_io_lock);
+	info->connected = suspend ?
+		BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
+	/* No more blkif_request(). */
+	if (info->rq)
+		blk_stop_queue(info->rq);
+	/* No more gnttab callback work. */
+	gnttab_cancel_free_callback(&info->callback);
+	spin_unlock_irq(&blkif_io_lock);
+
+	/* Flush gnttab callback work. Must be done with no locks held. */
+	flush_scheduled_work();
+
+	/* Free resources associated with old device channel. */
+	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;
+}
+
+static void blkif_completion(struct blk_shadow *s)
+{
+	int i;
+	for (i = 0; i < s->req.nr_segments; i++)
+		gnttab_end_foreign_access(s->req.seg[i].gref, 0UL);
+}
+
+static void blkif_recover(struct blkfront_info *info)
+{
+	int i;
+	blkif_request_t *req;
+	struct blk_shadow *copy;
+	int j;
+
+	/* Stage 1: Make a safe copy of the shadow state. */
+	copy = kmalloc(sizeof(info->shadow), GFP_NOIO | __GFP_NOFAIL | __GFP_HIGH);
+	memcpy(copy, info->shadow, sizeof(info->shadow));
+
+	/* Stage 2: Set up free list. */
+	memset(&info->shadow, 0, sizeof(info->shadow));
+	for (i = 0; i < BLK_RING_SIZE; i++)
+		info->shadow[i].req.id = i+1;
+	info->shadow_free = info->ring.req_prod_pvt;
+	info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
+
+	/* Stage 3: Find pending requests and requeue them. */
+	for (i = 0; i < BLK_RING_SIZE; i++) {
+		/* Not in use? */
+		if (copy[i].request == 0)
+			continue;
+
+		/* Grab a request slot and copy shadow state into it. */
+		req = RING_GET_REQUEST(
+			&info->ring, info->ring.req_prod_pvt);
+		*req = copy[i].req;
+
+		/* We get a new request id, and must reset the shadow state. */
+		req->id = GET_ID_FROM_FREELIST(info);
+		memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
+
+		/* Rewrite any grant references invalidated by susp/resume. */
+		for (j = 0; j < req->nr_segments; j++)
+			gnttab_grant_foreign_access_ref(
+				req->seg[j].gref,
+				info->xbdev->otherend_id,
+				pfn_to_mfn(info->shadow[req->id].frame[j]),
+				rq_data_dir((struct request *)
+					    info->shadow[req->id].request) ?
+				GTF_readonly : 0);
+		info->shadow[req->id].req = *req;
+
+		info->ring.req_prod_pvt++;
+	}
+
+	kfree(copy);
+
+	(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
+
+	spin_lock_irq(&blkif_io_lock);
+
+	/* Now safe for us to use the shared ring */
+	info->connected = BLKIF_STATE_CONNECTED;
+
+	/* Send off requeued requests */
+	flush_requests(info);
+
+	/* Kick any other new requests queued since we resumed */
+	kick_pending_request_queues(info);
+
+	spin_unlock_irq(&blkif_io_lock);
+}
+
+int blkfront_is_ready(struct xenbus_device *dev)
+{
+	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+
+	return info->is_ready;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id blkfront_ids[] = {
+	{ "vbd" },
+	{ "" }
+};
+MODULE_ALIAS("xen:vbd");
+
+static struct xenbus_driver blkfront = {
+	.name = "vbd",
+	.ids = blkfront_ids,
+	.probe = blkfront_probe,
+	.remove = blkfront_remove,
+	.resume = blkfront_resume,
+	.otherend_changed = backend_changed,
+	.is_ready = blkfront_is_ready,
+};
+
+
+static int __init xlblk_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&blkfront);
+}
+module_init(xlblk_init);
+
+
+static void __exit xlblk_exit(void)
+{
+	return xenbus_unregister_driver(&blkfront);
+}
+module_exit(xlblk_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/pcifront/pcifront.h
+++ linux-ec2-2.6.32/drivers/xen/pcifront/pcifront.h
@@ -0,0 +1,55 @@
+/*
+ * 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 <linux/interrupt.h>
+#include <xen/pcifront.h>
+#include <asm/atomic.h>
+#include <linux/workqueue.h>
+
+struct pci_bus_entry {
+	struct list_head list;
+	struct pci_bus *bus;
+};
+
+#define _PDEVB_op_active		(0)
+#define PDEVB_op_active 		(1 << (_PDEVB_op_active))
+
+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;
+	struct work_struct op_work;
+	unsigned long flags;
+
+};
+
+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);
+
+void pcifront_do_aer(struct work_struct *data);
+
+irqreturn_t pcifront_handler_aer(int irq, void *dev);
+
+#endif	/* __XEN_PCIFRONT_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/pcifront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/pcifront/Makefile
@@ -0,0 +1,5 @@
+obj-y += pcifront.o
+
+pcifront-y := pci_op.o xenbus.o pci.o
+
+ccflags-$(CONFIG_XEN_PCIDEV_FE_DEBUG) += -DDEBUG
--- linux-ec2-2.6.32.orig/drivers/xen/pcifront/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/pcifront/xenbus.c
@@ -0,0 +1,463 @@
+/*
+ * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <xen/xenbus.h>
+#include <xen/evtchn.h>
+#include <xen/gnttab.h>
+#include "pcifront.h"
+
+#define INVALID_GRANT_REF (0)
+#define INVALID_EVTCHN    (-1)
+
+static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
+{
+	struct pcifront_device *pdev;
+
+	pdev = kzalloc(sizeof(struct pcifront_device), GFP_KERNEL);
+	if (pdev == NULL)
+		goto out;
+
+	pdev->sh_info =
+	    (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
+	if (pdev->sh_info == NULL) {
+		kfree(pdev);
+		pdev = NULL;
+		goto out;
+	}
+	pdev->sh_info->flags = 0;
+
+	/*Flag for registering PV AER handler*/
+	set_bit(_XEN_PCIB_AERHANDLER, (void*)&pdev->sh_info->flags);
+
+	dev_set_drvdata(&xdev->dev, pdev);
+	pdev->xdev = xdev;
+
+	INIT_LIST_HEAD(&pdev->root_buses);
+
+	spin_lock_init(&pdev->dev_lock);
+	spin_lock_init(&pdev->sh_info_lock);
+
+	pdev->evtchn = INVALID_EVTCHN;
+	pdev->gnt_ref = INVALID_GRANT_REF;
+
+	INIT_WORK(&pdev->op_work, pcifront_do_aer);
+
+	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
+		pdev, pdev->sh_info);
+      out:
+	return pdev;
+}
+
+static void free_pdev(struct pcifront_device *pdev)
+{
+	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
+
+	pcifront_free_roots(pdev);
+
+	/*For PCIE_AER error handling job*/
+	flush_scheduled_work();
+	unbind_from_irqhandler(pdev->evtchn, pdev);
+
+	if (pdev->evtchn != INVALID_EVTCHN)
+		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+
+	if (pdev->gnt_ref != INVALID_GRANT_REF)
+		gnttab_end_foreign_access(pdev->gnt_ref,
+					  (unsigned long)pdev->sh_info);
+
+	dev_set_drvdata(&pdev->xdev->dev, NULL);
+
+	kfree(pdev);
+}
+
+static int pcifront_publish_info(struct pcifront_device *pdev)
+{
+	int err = 0;
+	struct xenbus_transaction trans;
+
+	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
+	if (err < 0)
+		goto out;
+
+	pdev->gnt_ref = err;
+
+	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
+	if (err)
+		goto out;
+
+	bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, 
+		IRQF_SAMPLE_RANDOM, "pcifront", pdev);
+
+      do_publish:
+	err = xenbus_transaction_start(&trans);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error writing configuration for backend "
+				 "(start transaction)");
+		goto out;
+	}
+
+	err = xenbus_printf(trans, pdev->xdev->nodename,
+			    "pci-op-ref", "%u", pdev->gnt_ref);
+	if (!err)
+		err = xenbus_printf(trans, pdev->xdev->nodename,
+				    "event-channel", "%u", pdev->evtchn);
+	if (!err)
+		err = xenbus_printf(trans, pdev->xdev->nodename,
+				    "magic", XEN_PCI_MAGIC);
+
+	if (err) {
+		xenbus_transaction_end(trans, 1);
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error writing configuration for backend");
+		goto out;
+	} else {
+		err = xenbus_transaction_end(trans, 0);
+		if (err == -EAGAIN)
+			goto do_publish;
+		else if (err) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error completing transaction "
+					 "for backend");
+			goto out;
+		}
+	}
+
+	xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
+
+	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
+
+      out:
+	return err;
+}
+
+static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
+{
+	int err = -EFAULT;
+	int i, num_roots, len;
+	char str[64];
+	unsigned int domain, bus;
+
+	spin_lock(&pdev->dev_lock);
+
+	/* Only connect once */
+	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
+	    XenbusStateInitialised)
+		goto out;
+
+	err = pcifront_connect(pdev);
+	if (err) {
+		xenbus_dev_fatal(pdev->xdev, err,
+				 "Error connecting PCI Frontend");
+		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_scan_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_scan_root(pdev, domain, bus);
+		if (err) {
+			xenbus_dev_fatal(pdev->xdev, err,
+					 "Error scanning PCI root %04x:%02x",
+					 domain, bus);
+			goto out;
+		}
+	}
+
+	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
+	if (err)
+		goto out;
+
+      out:
+	spin_unlock(&pdev->dev_lock);
+	return err;
+}
+
+static int pcifront_try_disconnect(struct pcifront_device *pdev)
+{
+	int err = 0;
+	enum xenbus_state prev_state;
+
+	spin_lock(&pdev->dev_lock);
+
+	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+
+	if (prev_state >= XenbusStateClosing)
+		goto out;
+
+	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 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 = dev_get_drvdata(&xdev->dev);
+
+	switch (be_state) {
+	case XenbusStateUnknown:
+	case XenbusStateInitialising:
+	case XenbusStateInitWait:
+	case XenbusStateInitialised:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateConnected:
+		pcifront_try_connect(pdev);
+		break;
+
+	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;
+	}
+}
+
+static int pcifront_xenbus_probe(struct xenbus_device *xdev,
+				 const struct xenbus_device_id *id)
+{
+	int err = 0;
+	struct pcifront_device *pdev = alloc_pdev(xdev);
+
+	if (pdev == NULL) {
+		err = -ENOMEM;
+		xenbus_dev_fatal(xdev, err,
+				 "Error allocating pcifront_device struct");
+		goto out;
+	}
+
+	err = pcifront_publish_info(pdev);
+
+      out:
+	return err;
+}
+
+static int pcifront_xenbus_remove(struct xenbus_device *xdev)
+{
+	if (dev_get_drvdata(&xdev->dev))
+		free_pdev(dev_get_drvdata(&xdev->dev));
+
+	return 0;
+}
+
+static const struct xenbus_device_id xenpci_ids[] = {
+	{"pci"},
+	{{0}},
+};
+MODULE_ALIAS("xen:pci");
+
+static struct xenbus_driver xenbus_pcifront_driver = {
+	.name 			= "pcifront",
+	.ids 			= xenpci_ids,
+	.probe 			= pcifront_xenbus_probe,
+	.remove 		= pcifront_xenbus_remove,
+	.otherend_changed 	= pcifront_backend_changed,
+};
+
+static int __init pcifront_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenbus_pcifront_driver);
+}
+
+/* Initialize after the Xen PCI Frontend Stub is initialized */
+subsys_initcall(pcifront_init);
--- linux-ec2-2.6.32.orig/drivers/xen/pcifront/pci_op.c
+++ linux-ec2-2.6.32/drivers/xen/pcifront/pci_op.c
@@ -0,0 +1,674 @@
+/*
+ * PCI Frontend Operations - Communicates with frontend
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <asm/bitops.h>
+#include <linux/time.h>
+#include <xen/evtchn.h>
+#include "pcifront.h"
+
+static int verbose_request = 0;
+module_param(verbose_request, int, 0644);
+
+#ifdef __ia64__
+static void pcifront_init_sd(struct pcifront_sd *sd,
+			     unsigned int domain, unsigned int bus,
+			     struct pcifront_device *pdev)
+{
+	int err, i, j, k, len, root_num, res_count;
+	struct acpi_resource res;
+	unsigned int d, b, byte;
+	unsigned long magic;
+	char str[64], tmp[3];
+	unsigned char *buf, *bufp;
+	u8 *ptr;
+
+	memset(sd, 0, sizeof(*sd));
+
+	sd->segment = domain;
+	sd->node = -1;	/* Revisit for NUMA */
+	sd->platform_data = pdev;
+
+	/* Look for resources for this controller in xenbus. */
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "root_num",
+			   "%d", &root_num);
+	if (err != 1)
+		return;
+
+	for (i = 0; i < root_num; i++) {
+		len = snprintf(str, sizeof(str), "root-%d", i);
+		if (unlikely(len >= (sizeof(str) - 1)))
+			return;
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+				   str, "%x:%x", &d, &b);
+		if (err != 2)
+			return;
+
+		if (d == domain && b == bus)
+			break;
+	}
+
+	if (i == root_num)
+		return;
+
+	len = snprintf(str, sizeof(str), "root-resource-magic");
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+			   str, "%lx", &magic);
+
+	if (err != 1)
+		return; /* No resources, nothing to do */
+
+	if (magic != (sizeof(res) * 2) + 1) {
+		printk(KERN_WARNING "pcifront: resource magic mismatch\n");
+		return;
+	}
+
+	len = snprintf(str, sizeof(str), "root-%d-resources", i);
+	if (unlikely(len >= (sizeof(str) - 1)))
+		return;
+
+	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
+			   str, "%d", &res_count);
+
+	if (err != 1)
+		return; /* No resources, nothing to do */
+
+	sd->window = kzalloc(sizeof(*sd->window) * res_count, GFP_KERNEL);
+	if (!sd->window)
+		return;
+
+	/* magic is also the size of the byte stream in xenbus */
+	buf = kmalloc(magic, GFP_KERNEL);
+	if (!buf) {
+		kfree(sd->window);
+		sd->window = NULL;
+		return;
+	}
+
+	/* Read the resources out of xenbus */
+	for (j = 0; j < res_count; j++) {
+		memset(&res, 0, sizeof(res));
+		memset(buf, 0, magic);
+
+		len = snprintf(str, sizeof(str), "root-%d-resource-%d", i, j);
+		if (unlikely(len >= (sizeof(str) - 1)))
+			return;
+
+		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
+				   "%s", buf);
+		if (err != 1) {
+			printk(KERN_WARNING "pcifront: error reading "
+			       "resource %d on bus %04x:%02x\n",
+			       j, domain, bus);
+			continue;
+		}
+
+		bufp = buf;
+		ptr = (u8 *)&res;
+		memset(tmp, 0, sizeof(tmp));
+
+		/* Copy ASCII byte stream into structure */
+		for (k = 0; k < magic - 1; k += 2) {
+			memcpy(tmp, bufp, 2);
+			bufp += 2;
+
+			sscanf(tmp, "%02x", &byte);
+			*ptr = byte;
+			ptr++;
+		}
+
+		xen_add_resource(sd, domain, bus, &res);
+		sd->windows++;
+	}
+	kfree(buf);
+}
+#endif
+
+static int errno_to_pcibios_err(int errno)
+{
+	switch (errno) {
+	case XEN_PCI_ERR_success:
+		return PCIBIOS_SUCCESSFUL;
+
+	case XEN_PCI_ERR_dev_not_found:
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	case XEN_PCI_ERR_invalid_offset:
+	case XEN_PCI_ERR_op_failed:
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	case XEN_PCI_ERR_not_implemented:
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	case XEN_PCI_ERR_access_denied:
+		return PCIBIOS_SET_FAILED;
+	}
+	return errno;
+}
+
+static inline void schedule_pcifront_aer_op(struct pcifront_device *pdev)
+{
+	if (test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
+		&& !test_and_set_bit(_PDEVB_op_active, &pdev->flags)) {
+		dev_dbg(&pdev->xdev->dev, "schedule aer frontend job\n");
+		schedule_work(&pdev->op_work);
+	}
+}
+
+static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
+{
+	int err = 0;
+	struct xen_pci_op *active_op = &pdev->sh_info->op;
+	unsigned long irq_flags;
+	evtchn_port_t port = pdev->evtchn;
+	s64 ns, ns_timeout;
+	struct timeval tv;
+
+	spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
+
+	memcpy(active_op, op, sizeof(struct xen_pci_op));
+
+	/* Go */
+	wmb();
+	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
+	notify_remote_via_evtchn(port);
+
+	/*
+	 * We set a poll timeout of 3 seconds but give up on return after
+	 * 2 seconds. It is better to time out too late rather than too early
+	 * (in the latter case we end up continually re-executing poll() with a
+	 * timeout in the past). 1s difference gives plenty of slack for error.
+	 */
+	do_gettimeofday(&tv);
+	ns_timeout = timeval_to_ns(&tv) + 2 * (s64)NSEC_PER_SEC;
+
+	clear_evtchn(port);
+
+	while (test_bit(_XEN_PCIF_active,
+			(unsigned long *)&pdev->sh_info->flags)) {
+		if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
+			BUG();
+		clear_evtchn(port);
+		do_gettimeofday(&tv);
+		ns = timeval_to_ns(&tv);
+		if (ns > ns_timeout) {
+			dev_err(&pdev->xdev->dev,
+				"pciback not responding!!!\n");
+			clear_bit(_XEN_PCIF_active,
+				  (unsigned long *)&pdev->sh_info->flags);
+			err = XEN_PCI_ERR_dev_not_found;
+			goto out;
+		}
+	}
+
+	/*
+	* We might lose backend service request since we 
+	* reuse same evtchn with pci_conf backend response. So re-schedule
+	* aer pcifront service.
+	*/
+	if (test_bit(_XEN_PCIB_active, 
+			(unsigned long*)&pdev->sh_info->flags)) {
+		dev_err(&pdev->xdev->dev, 
+			"schedule aer pcifront service\n");
+		schedule_pcifront_aer_op(pdev);
+	}
+
+	memcpy(op, active_op, sizeof(struct xen_pci_op));
+
+	err = op->err;
+      out:
+	spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags);
+	return err;
+}
+
+/* Access to this function is spinlocked in drivers/pci/access.c */
+static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 * val)
+{
+	int err = 0;
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_conf_read,
+		.domain = pci_domain_nr(bus),
+		.bus    = bus->number,
+		.devfn  = devfn,
+		.offset = where,
+		.size   = size,
+	};
+	struct pcifront_sd *sd = bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	if (verbose_request)
+		dev_info(&pdev->xdev->dev,
+			 "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
+			 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
+			 PCI_FUNC(devfn), where, size);
+
+	err = do_pci_op(pdev, &op);
+
+	if (likely(!err)) {
+		if (verbose_request)
+			dev_info(&pdev->xdev->dev, "read got back value %x\n",
+				 op.value);
+
+		*val = op.value;
+	} else if (err == -ENODEV) {
+		/* No device here, pretend that it just returned 0 */
+		err = 0;
+		*val = 0;
+	}
+
+	return errno_to_pcibios_err(err);
+}
+
+/* Access to this function is spinlocked in drivers/pci/access.c */
+static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	struct xen_pci_op op = {
+		.cmd    = XEN_PCI_OP_conf_write,
+		.domain = pci_domain_nr(bus),
+		.bus    = bus->number,
+		.devfn  = devfn,
+		.offset = where,
+		.size   = size,
+		.value  = val,
+	};
+	struct pcifront_sd *sd = bus->sysdata;
+	struct pcifront_device *pdev = pcifront_get_pdev(sd);
+
+	if (verbose_request)
+		dev_info(&pdev->xdev->dev,
+			 "write dev=%04x:%02x:%02x.%01x - "
+			 "offset %x size %d val %x\n",
+			 pci_domain_nr(bus), bus->number,
+			 PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
+
+	return errno_to_pcibios_err(do_pci_op(pdev, &op));
+}
+
+struct pci_ops pcifront_bus_ops = {
+	.read = pcifront_bus_read,
+	.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 int pcifront_claim_resource(struct pci_dev *dev, void *data)
+{
+	struct pcifront_device *pdev = data;
+	int i;
+	struct resource *r;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		r = &dev->resource[i];
+
+		if (!r->parent && r->start && r->flags) {
+			dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
+				pci_name(dev), i);
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	return 0;
+}
+
+int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+				 unsigned int domain, unsigned int bus)
+{
+	struct pci_bus *b;
+	struct pcifront_sd *sd = NULL;
+	struct pci_bus_entry *bus_entry = NULL;
+	int err = 0;
+
+#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");
+		err = -EINVAL;
+		goto err_out;
+	}
+#endif
+
+	dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
+		 domain, bus);
+
+	bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
+	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+	if (!bus_entry || !sd) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	pcifront_init_sd(sd, domain, bus, pdev);
+
+	b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
+				  &pcifront_bus_ops, sd);
+	if (!b) {
+		dev_err(&pdev->xdev->dev,
+			"Error creating PCI Frontend Bus!\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	pcifront_setup_root_resources(b, sd);
+	bus_entry->bus = b;
+
+	list_add(&bus_entry->list, &pdev->root_buses);
+
+	/* Claim resources before going "live" with our devices */
+	pci_walk_bus(b, pcifront_claim_resource, pdev);
+
+	pci_bus_add_devices(b);
+
+	return 0;
+
+      err_out:
+	kfree(bus_entry);
+	kfree(sd);
+
+	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) {
+			int err;
+
+			dev_info(&pdev->xdev->dev, "New device on "
+				 "%04x:%02x:%02x.%02x found.\n", domain, bus,
+				 PCI_SLOT(devfn), PCI_FUNC(devfn));
+			err = pci_bus_add_device(d);
+			if (err)
+				dev_err(&pdev->xdev->dev,
+				        "error %d adding device, continuing.\n",
+					err);
+		}
+	}
+
+	return 0;
+}
+
+static void free_root_bus_devs(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	while (!list_empty(&bus->devices)) {
+		dev = container_of(bus->devices.next, struct pci_dev,
+				   bus_list);
+		dev_dbg(&dev->dev, "removing device\n");
+		pci_remove_bus_device(dev);
+	}
+}
+
+void pcifront_free_roots(struct pcifront_device *pdev)
+{
+	struct pci_bus_entry *bus_entry, *t;
+
+	dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
+
+	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
+		list_del(&bus_entry->list);
+
+		free_root_bus_devs(bus_entry->bus);
+
+		kfree(bus_entry->bus->sysdata);
+
+		device_unregister(bus_entry->bus->bridge);
+		pci_remove_bus(bus_entry->bus);
+
+		kfree(bus_entry);
+	}
+}
+
+static pci_ers_result_t pcifront_common_process( int cmd, struct pcifront_device *pdev,
+	pci_channel_state_t state)
+{
+	pci_ers_result_t result;
+	struct pci_driver *pdrv;
+	int bus = pdev->sh_info->aer_op.bus;
+	int devfn = pdev->sh_info->aer_op.devfn;
+	struct pci_dev *pcidev;
+	int flag = 0;
+
+	dev_dbg(&pdev->xdev->dev, 
+		"pcifront AER process: cmd %x (bus:%x, devfn%x)",
+		cmd, bus, devfn);
+	result = PCI_ERS_RESULT_NONE;
+
+	pcidev = pci_get_bus_and_slot(bus, devfn);
+	if (!pcidev || !pcidev->driver){
+		dev_err(&pcidev->dev, 
+			"device or driver is NULL\n");
+		return result;
+	}
+	pdrv = pcidev->driver;
+
+	if (get_driver(&pdrv->driver)) {
+		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
+			dev_dbg(&pcidev->dev,
+				"trying to call AER service\n");
+			if (pcidev) {
+				flag = 1;
+				switch(cmd) {
+				case XEN_PCI_OP_aer_detected:
+					result = pdrv->err_handler->error_detected(pcidev, state);
+					break;
+				case XEN_PCI_OP_aer_mmio:
+					result = pdrv->err_handler->mmio_enabled(pcidev);
+					break;
+				case XEN_PCI_OP_aer_slotreset:
+					result = pdrv->err_handler->slot_reset(pcidev);
+					break;
+				case XEN_PCI_OP_aer_resume:
+					pdrv->err_handler->resume(pcidev);
+					break;
+				default:
+					dev_err(&pdev->xdev->dev,
+						"bad request in aer recovery operation!\n");
+
+				}
+			}
+		}
+		put_driver(&pdrv->driver);
+	}
+	if (!flag)
+		result = PCI_ERS_RESULT_NONE;
+
+	return result;
+}
+
+
+void pcifront_do_aer(struct work_struct *data)
+{
+	struct pcifront_device *pdev = container_of(data, struct pcifront_device, op_work);
+	int cmd = pdev->sh_info->aer_op.cmd;
+	pci_channel_state_t state = 
+		(pci_channel_state_t)pdev->sh_info->aer_op.err;
+
+	/*If a pci_conf op is in progress, 
+		we have to wait until it is done before service aer op*/
+	dev_dbg(&pdev->xdev->dev, 
+		"pcifront service aer bus %x devfn %x\n", pdev->sh_info->aer_op.bus,
+		pdev->sh_info->aer_op.devfn);
+
+	pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state);
+
+	wmb();
+	clear_bit(_XEN_PCIB_active, (unsigned long*)&pdev->sh_info->flags);
+	notify_remote_via_evtchn(pdev->evtchn);
+
+	/*in case of we lost an aer request in four lines time_window*/
+	smp_mb__before_clear_bit();
+	clear_bit( _PDEVB_op_active, &pdev->flags);
+	smp_mb__after_clear_bit();
+
+	schedule_pcifront_aer_op(pdev);
+
+}
+
+irqreturn_t pcifront_handler_aer(int irq, void *dev)
+{
+	struct pcifront_device *pdev = dev;
+	schedule_pcifront_aer_op(pdev);
+	return IRQ_HANDLED;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/pcifront/pci.c
+++ linux-ec2-2.6.32/drivers/xen/pcifront/pci.c
@@ -0,0 +1,46 @@
+/*
+ * PCI Frontend Operations - ensure only one PCI frontend runs at a time
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "pcifront.h"
+
+DEFINE_SPINLOCK(pcifront_dev_lock);
+static struct pcifront_device *pcifront_dev = NULL;
+
+int pcifront_connect(struct pcifront_device *pdev)
+{
+	int err = 0;
+
+	spin_lock(&pcifront_dev_lock);
+
+	if (!pcifront_dev) {
+		dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
+		pcifront_dev = pdev;
+	}
+	else {
+		dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
+		err = -EEXIST;
+	}
+
+	spin_unlock(&pcifront_dev_lock);
+
+	return err;
+}
+
+void pcifront_disconnect(struct pcifront_device *pdev)
+{
+	spin_lock(&pcifront_dev_lock);
+
+	if (pdev == pcifront_dev) {
+		dev_info(&pdev->xdev->dev,
+			 "Disconnecting PCI Frontend Buses\n");
+		pcifront_dev = NULL;
+	}
+
+	spin_unlock(&pcifront_dev_lock);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_msg.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_msg.c
@@ -0,0 +1,567 @@
+/****************************************************************************
+ * 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)) {
+		struct netfront_info *np = netdev_priv(vnic->net_dev);
+
+		/* 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++);
+		napi_schedule(&np->napi);
+	} 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;
+	struct netfront_info *np = netdev_priv(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);
+	
+	napi_disable(&np->napi);
+	vnic->poll_enabled = 1;
+	napi_enable(&np->napi);
+	
+	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 */
+	napi_disable(&np->napi);
+	spin_lock_irqsave(&vnic->irq_enabled_lock, flags1);
+	vnic->poll_enabled = 0;
+	spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags1);
+	napi_enable(&np->napi);
+}
+
+
+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: %pM\n",
+			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)
+{
+	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)
+{
+	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) {
+		struct netfront_info *np = netdev_priv(net_dev);
+
+		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
+		napi_schedule(&np->napi);
+	}
+	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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/ef_vi_falcon_core.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/ef_vi_falcon_core.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_tso.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_tso.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_debugfs.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_debugfs.c
@@ -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
+ ****************************************************************************
+ */
+
+#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.fastpath_crc_bad = debugfs_create_u64
+		("fastpath_crc_bad", S_IRUSR | S_IRGRP | S_IROTH,
+		 vnic->dbfs_dir, &vnic->stats.fastpath_crc_bad);
+	vnic->dbfs.fastpath_csum_bad = debugfs_create_u64
+		("fastpath_csum_bad", S_IRUSR | S_IRGRP | S_IROTH,
+		 vnic->dbfs_dir, &vnic->stats.fastpath_csum_bad);
+	vnic->dbfs.fastpath_rights_bad = debugfs_create_u64
+		("fastpath_rights_bad", S_IRUSR | S_IRGRP | S_IROTH,
+		 vnic->dbfs_dir, &vnic->stats.fastpath_rights_bad);
+	vnic->dbfs.fastpath_discard_other = debugfs_create_u64
+		("fastpath_discard_other", S_IRUSR | S_IRGRP | S_IROTH,
+		 vnic->dbfs_dir, &vnic->stats.fastpath_discard_other);
+	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.fastpath_crc_bad);
+		debugfs_remove(vnic->dbfs.fastpath_csum_bad);
+		debugfs_remove(vnic->dbfs.fastpath_rights_bad);
+		debugfs_remove(vnic->dbfs.fastpath_discard_other);
+		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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_ssr.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_ssr.c
@@ -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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/Makefile
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/ef_vi_falcon_event.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/ef_vi_falcon_event.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel.h
@@ -0,0 +1,494 @@
+/****************************************************************************
+ * 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/version.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 rx discard (bad crc) events seen on fastpath */
+	u64 fastpath_crc_bad;
+
+	/** Number of rx discard (bad csum) events seen on fastpath */
+	u64 fastpath_csum_bad;
+
+	/** Number of rx discard (bad rights) events seen on fastpath */
+	u64 fastpath_rights_bad;
+
+	/** Number of rx discard ("other") events seen on fastpath */
+	u64 fastpath_discard_other;
+
+	/** Number of no rx descriptor trunc events seen on fastpath */
+	u64 rx_no_desc_trunc;
+
+	/** The number of misc bad events 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 *fastpath_crc_bad;
+	struct dentry *fastpath_csum_bad;
+	struct dentry *fastpath_rights_bad;
+	struct dentry *fastpath_discard_other;
+	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.  Reads require either
+	 * netfront's tx_lock or the vnic tx_lock; writes require both
+	 * locks */
+	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);
+irqreturn_t netfront_accel_net_channel_irq_from_bend(int irq, void *context);
+
+#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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/sysdep.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/sysdep.h
@@ -0,0 +1,185 @@
+/****************************************************************************
+ * 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__
+
+
+#define ef_vi_wiob()  mmiowb()
+
+
+/**********************************************************************
+ * 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; 
+# endif
+#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
+
+#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;
+
+#  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;
+# 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
+# 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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/pt_tx.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/pt_tx.c
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/ef_vi_falcon.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/ef_vi_falcon.h
@@ -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) 
+
+
+/* ---- ef_vi_event 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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_xenbus.c
@@ -0,0 +1,775 @@
+/****************************************************************************
+ * 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,
+		 IRQF_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,
+		 IRQF_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 = dev_get_drvdata(&dev->dev);
+	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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_netfront.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_netfront.c
@@ -0,0 +1,328 @@
+/****************************************************************************
+ * 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__);
+
+		/* Need netfront's tx_lock and vnic tx_lock to write 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);
+
+	/* Read of tx_skb is protected by netfront's tx_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");
+		goto fail;
+	}
+
+	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");
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	netfront_accel_debugfs_fini();
+	flush_workqueue(netfront_accel_workqueue);
+	destroy_workqueue(netfront_accel_workqueue);
+#ifdef EFX_GCOV
+ 	gcov_provider_fini(THIS_MODULE);
+#endif
+	return -EINVAL;
+}
+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");
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_bufs.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_bufs.h
@@ -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 */
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_bufs.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_bufs.c
@@ -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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_vi.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_vi.c
@@ -0,0 +1,1199 @@
+/****************************************************************************
+ * 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_PARTIAL) {
+		/* Set to zero to encourage falcon to work it out for us */
+		*(u16*)(skb->head + skb->csum_start + skb->csum_offset) = 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_PARTIAL) {
+		/* Set to zero to encourage falcon to work it out for us */
+		*(u16*)(skb->head + skb->csum_start + skb->csum_offset) = 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: %pM\n", 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 %pM\n",
+			__FUNCTION__, 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) );
+			NETFRONT_ACCEL_STATS_OP(++vnic->stats.fastpath_discard_other);
+		} else if (EF_EVENT_RX_DISCARD_TYPE(*ev) ==
+			   EF_EVENT_RX_DISCARD_CSUM_BAD) {
+			DPRINTK("%s: " EF_EVENT_FMT 
+				" buffer %d DISCARD CSUM_BAD 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_csum_bad);
+		} else if (EF_EVENT_RX_DISCARD_TYPE(*ev) ==
+			   EF_EVENT_RX_DISCARD_CRC_BAD) {
+			DPRINTK("%s: " EF_EVENT_FMT 
+				" buffer %d DISCARD CRC_BAD 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_crc_bad);
+		} else {
+			BUG_ON(EF_EVENT_RX_DISCARD_TYPE(*ev) !=
+			       EF_EVENT_RX_DISCARD_RIGHTS);
+			DPRINTK("%s: " EF_EVENT_FMT 
+				" buffer %d DISCARD RIGHTS 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_rights_bad);
+		}
+	}
+
+	/* 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));
+	int handled;
+	unsigned long flags;
+
+	/*
+	 * We hold the vnic tx_lock which is sufficient to exclude
+	 * writes to tx_skb
+	 */
+
+	if (vnic->tx_skb != NULL) {
+		DPRINTK("%s trying to send spare buffer\n", __FUNCTION__);
+		
+		handled = netfront_accel_vi_tx_post(vnic, vnic->tx_skb);
+		
+		if (handled != NETFRONT_ACCEL_STATUS_BUSY) {
+			DPRINTK("%s restarting tx\n", __FUNCTION__);
+
+			/* Need netfront tx_lock and vnic tx_lock to
+			 * write tx_skb */
+			spin_lock_irqsave(&np->tx_lock, flags);
+
+			vnic->tx_skb = NULL;
+
+			if (netfront_check_queue_ready(vnic->net_dev)) {
+				netif_wake_queue(vnic->net_dev);
+				NETFRONT_ACCEL_STATS_OP
+					(vnic->stats.queue_wakes++);
+			}
+			spin_unlock_irqrestore(&np->tx_lock, flags);
+
+		}
+		
+		/*
+		 * Should never get a CANT, as it checks that before
+		 * deciding it was BUSY first time round 
+		 */
+		BUG_ON(handled == NETFRONT_ACCEL_STATUS_CANT);
+	}
+}
+
+
+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;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/ef_vi_internal.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/ef_vi_internal.h
@@ -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__ */
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/falcon_vi.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/falcon_vi.c
@@ -0,0 +1,473 @@
+/****************************************************************************
+ * 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;
+}
+
+
+int ef_vi_receive_post(ef_vi* vi, ef_addr addr, ef_request_id dma_id)
+{
+  int rc = ef_vi_receive_init(vi, addr, dma_id, 0);
+  if( rc == 0 )  ef_vi_receive_push(vi);
+  return rc;
+}
+
+
+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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_ssr.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_ssr.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/accel_tso.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/accel_tso.c
@@ -0,0 +1,509 @@
+/****************************************************************************
+ * 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 ETH_HDR_LEN(skb)  skb_network_offset(skb)
+#define SKB_TCP_OFF(skb)  skb_transport_offset(skb)
+#define SKB_IP_OFF(skb)   skb_network_offset(skb)
+
+/*
+ * 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(ip_hdr(skb)->protocol != IPPROTO_TCP);
+	EPRINTK_ON((SKB_TCP_OFF(skb) + tcp_hdrlen(skb)) > 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 = tcp_hdrlen(skb) + 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(ip_hdr(skb)->id);
+	st->seqnum = ntohl(tcp_hdr(skb)->seq);
+
+	EPRINTK_ON(tcp_hdr(skb)->urg);
+	EPRINTK_ON(tcp_hdr(skb)->syn);
+	EPRINTK_ON(tcp_hdr(skb)->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 = tcp_hdr(skb)->fin;
+		tsoh_th->psh = tcp_hdr(skb)->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_PARTIAL)
+		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;
+}
+
+
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/vi_init.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/vi_init.c
@@ -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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/falcon_event.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/falcon_event.c
@@ -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);
+	uint16_t 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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netfront/etherfabric/ef_vi.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netfront/etherfabric/ef_vi.h
@@ -0,0 +1,647 @@
+/****************************************************************************
+ * 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_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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/usbfront/Makefile
@@ -0,0 +1,11 @@
+obj-$(CONFIG_XEN_USB_FRONTEND) := xen-hcd.o
+
+xen-hcd-y   := usbfront-hcd.o xenbus.o
+
+ifeq ($(CONFIG_XEN_USB_FRONTEND_HCD_STATS),y)
+EXTRA_CFLAGS += -DXENHCD_STATS
+endif
+
+ifeq ($(CONFIG_XEN_USB_FRONTEND_HCD_PM),y)
+EXTRA_CFLAGS += -DXENHCD_PM
+endif
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/usbfront-hcd.c
+++ linux-ec2-2.6.32/drivers/xen/usbfront/usbfront-hcd.c
@@ -0,0 +1,232 @@
+/*
+ * usbfront-hcd.c
+ *
+ * Xen USB Virtual Host Controller driver
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include "usbfront.h"
+#include "usbfront-dbg.c"
+#include "usbfront-hub.c"
+#include "usbfront-q.c"
+
+static void xenhcd_watchdog(unsigned long param)
+{
+	struct usbfront_info *info = (struct usbfront_info *) param;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (likely(HC_IS_RUNNING(info_to_hcd(info)->state))) {
+		timer_action_done(info, TIMER_RING_WATCHDOG);
+		xenhcd_giveback_unlinked_urbs(info);
+		xenhcd_kick_pending_urbs(info);
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+/*
+ * one-time HC init
+ */
+static int xenhcd_setup(struct usb_hcd *hcd)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+
+	spin_lock_init(&info->lock);
+	INIT_LIST_HEAD(&info->pending_submit_list);
+	INIT_LIST_HEAD(&info->pending_unlink_list);
+	INIT_LIST_HEAD(&info->in_progress_list);
+	INIT_LIST_HEAD(&info->giveback_waiting_list);
+	init_timer(&info->watchdog);
+	info->watchdog.function = xenhcd_watchdog;
+	info->watchdog.data = (unsigned long) info;
+	return 0;
+}
+
+/*
+ * start HC running
+ */
+static int xenhcd_run(struct usb_hcd *hcd)
+{
+	hcd->uses_new_polling = 1;
+	hcd->poll_rh = 0;
+	hcd->state = HC_STATE_RUNNING;
+	create_debug_file(hcd_to_info(hcd));
+	return 0;
+}
+
+/*
+ * stop running HC
+ */
+static void xenhcd_stop(struct usb_hcd *hcd)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+
+	del_timer_sync(&info->watchdog);
+	remove_debug_file(info);
+	spin_lock_irq(&info->lock);
+	/* cancel all urbs */
+	hcd->state = HC_STATE_HALT;
+	xenhcd_cancel_all_enqueued_urbs(info);
+	xenhcd_giveback_unlinked_urbs(info);
+	spin_unlock_irq(&info->lock);
+}
+
+/*
+ * called as .urb_enqueue()
+ * non-error returns are promise to giveback the urb later
+ */
+static int xenhcd_urb_enqueue(struct usb_hcd *hcd,
+				    struct urb *urb,
+				    gfp_t mem_flags)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+	struct urb_priv *urbp;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	urbp = alloc_urb_priv(urb);
+	if (!urbp) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	urbp->status = 1;
+
+	ret = xenhcd_submit_urb(info, urbp);
+	if (ret != 0)
+		free_urb_priv(urbp);
+
+done:
+	spin_unlock_irqrestore(&info->lock, flags);
+	return ret;
+}
+
+/*
+ * called as .urb_dequeue()
+ */
+static int xenhcd_urb_dequeue(struct usb_hcd *hcd,
+			      struct urb *urb, int status)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+	struct urb_priv *urbp;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	urbp = urb->hcpriv;
+	if (!urbp)
+		goto done;
+
+	urbp->status = status;
+	ret = xenhcd_unlink_urb(info, urbp);
+
+done:
+	spin_unlock_irqrestore(&info->lock, flags);
+	return ret;
+}
+
+/*
+ * called from usb_get_current_frame_number(),
+ * but, almost all drivers not use such function.
+ */
+static int xenhcd_get_frame(struct usb_hcd *hcd)
+{
+	/* it means error, but probably no problem :-) */
+	return 0;
+}
+
+static const char hcd_name[] = "xen_hcd";
+
+struct hc_driver xen_usb20_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Xen USB2.0 Virtual Host Controller",
+	.hcd_priv_size = sizeof(struct usbfront_info),
+	.flags = HCD_USB2,
+
+	/* basic HC lifecycle operations */
+	.reset = xenhcd_setup,
+	.start = xenhcd_run,
+	.stop = xenhcd_stop,
+
+	/* managing urb I/O */
+	.urb_enqueue = xenhcd_urb_enqueue,
+	.urb_dequeue = xenhcd_urb_dequeue,
+	.get_frame_number = xenhcd_get_frame,
+
+	/* root hub operations */
+	.hub_status_data = xenhcd_hub_status_data,
+	.hub_control = xenhcd_hub_control,
+#ifdef XENHCD_PM
+#ifdef CONFIG_PM
+	.bus_suspend = xenhcd_bus_suspend,
+	.bus_resume = xenhcd_bus_resume,
+#endif
+#endif
+};
+
+struct hc_driver xen_usb11_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Xen USB1.1 Virtual Host Controller",
+	.hcd_priv_size = sizeof(struct usbfront_info),
+	.flags = HCD_USB11,
+
+	/* basic HC lifecycle operations */
+	.reset = xenhcd_setup,
+	.start = xenhcd_run,
+	.stop = xenhcd_stop,
+
+	/* managing urb I/O */
+	.urb_enqueue = xenhcd_urb_enqueue,
+	.urb_dequeue = xenhcd_urb_dequeue,
+	.get_frame_number = xenhcd_get_frame,
+
+	/* root hub operations */
+	.hub_status_data = xenhcd_hub_status_data,
+	.hub_control = xenhcd_hub_control,
+#ifdef XENHCD_PM
+#ifdef CONFIG_PM
+	.bus_suspend = xenhcd_bus_suspend,
+	.bus_resume = xenhcd_bus_resume,
+#endif
+#endif
+};
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/usbfront-dbg.c
+++ linux-ec2-2.6.32/drivers/xen/usbfront/usbfront-dbg.c
@@ -0,0 +1,101 @@
+/*
+ * usbfront-dbg.c
+ *
+ * Xen USB Virtual Host Controller - debugging
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+static ssize_t show_statistics(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct usb_hcd *hcd;
+	struct usbfront_info *info;
+	unsigned long flags;
+	unsigned temp, size;
+	char *next;
+
+	hcd = dev_get_drvdata(dev);
+	info = hcd_to_info(hcd);
+	next = buf;
+	size = PAGE_SIZE;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	temp = scnprintf(next, size,
+			"bus %s, device %s\n"
+			"%s\n"
+			"xenhcd, hcd state %d\n",
+			hcd->self.controller->bus->name,
+			dev_name(hcd->self.controller),
+			hcd->product_desc,
+			hcd->state);
+	size -= temp;
+	next += temp;
+
+#ifdef XENHCD_STATS
+	temp = scnprintf(next, size,
+		"complete %ld unlink %ld ring_full %ld\n",
+		info->stats.complete, info->stats.unlink,
+		info->stats.ring_full);
+	size -= temp;
+	next += temp;
+#endif
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	return PAGE_SIZE - size;
+}
+
+static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
+
+static inline void create_debug_file(struct usbfront_info *info)
+{
+	struct device *dev = info_to_hcd(info)->self.controller;
+	if (device_create_file(dev, &dev_attr_statistics))
+		printk(KERN_WARNING "statistics file not created for %s\n",
+		       info_to_hcd(info)->self.bus_name);
+}
+
+static inline void remove_debug_file(struct usbfront_info *info)
+{
+	struct device *dev = info_to_hcd(info)->self.controller;
+	device_remove_file(dev, &dev_attr_statistics);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/usbfront/xenbus.c
@@ -0,0 +1,411 @@
+/*
+ * xenbus.c
+ *
+ * Xenbus interface for Xen USB Virtual Host Controller
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include "usbfront.h"
+
+#define GRANT_INVALID_REF 0
+
+static void destroy_rings(struct usbfront_info *info)
+{
+	if (info->irq)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = 0;
+
+	if (info->urb_ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(info->urb_ring_ref,
+					  (unsigned long)info->urb_ring.sring);
+		info->urb_ring_ref = GRANT_INVALID_REF;
+	}
+	info->urb_ring.sring = NULL;
+
+	if (info->conn_ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(info->conn_ring_ref,
+					  (unsigned long)info->conn_ring.sring);
+		info->conn_ring_ref = GRANT_INVALID_REF;
+	}
+	info->conn_ring.sring = NULL;
+}
+
+static int setup_rings(struct xenbus_device *dev,
+			   struct usbfront_info *info)
+{
+	usbif_urb_sring_t *urb_sring;
+	usbif_conn_sring_t *conn_sring;
+	int err;
+
+	info->urb_ring_ref = GRANT_INVALID_REF;
+	info->conn_ring_ref = GRANT_INVALID_REF;
+
+	urb_sring = (usbif_urb_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+	if (!urb_sring) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating urb ring");
+		return -ENOMEM;
+	}
+	SHARED_RING_INIT(urb_sring);
+	FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(info->urb_ring.sring));
+	if (err < 0) {
+		free_page((unsigned long)urb_sring);
+		info->urb_ring.sring = NULL;
+		goto fail;
+	}
+	info->urb_ring_ref = err;
+
+	conn_sring = (usbif_conn_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+	if (!conn_sring) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating conn ring");
+		return -ENOMEM;
+	}
+	SHARED_RING_INIT(conn_sring);
+	FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(info->conn_ring.sring));
+	if (err < 0) {
+		free_page((unsigned long)conn_sring);
+		info->conn_ring.sring = NULL;
+		goto fail;
+	}
+	info->conn_ring_ref = err;
+
+	err = bind_listening_port_to_irqhandler(
+		dev->otherend_id, xenhcd_int, IRQF_SAMPLE_RANDOM, "usbif", info);
+	if (err <= 0) {
+		xenbus_dev_fatal(dev, err,
+				 "bind_listening_port_to_irqhandler");
+		goto fail;
+	}
+	info->irq = err;
+
+	return 0;
+fail:
+	destroy_rings(info);
+	return err;
+}
+
+static int talk_to_backend(struct xenbus_device *dev,
+			   struct usbfront_info *info)
+{
+	const char *message;
+	struct xenbus_transaction xbt;
+	int err;
+
+	err = setup_rings(dev, info);
+	if (err)
+		goto out;
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		goto destroy_ring;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "urb-ring-ref", "%u",
+			    info->urb_ring_ref);
+	if (err) {
+		message = "writing urb-ring-ref";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "conn-ring-ref", "%u",
+			    info->conn_ring_ref);
+	if (err) {
+		message = "writing conn-ring-ref";
+		goto abort_transaction;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    irq_to_evtchn_port(info->irq));
+	if (err) {
+		message = "writing event-channel";
+		goto abort_transaction;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err) {
+		if (err == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto destroy_ring;
+	}
+
+	return 0;
+
+abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+
+destroy_ring:
+	destroy_rings(info);
+
+out:
+	return err;
+}
+
+static int connect(struct xenbus_device *dev)
+{
+	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+
+	usbif_conn_request_t *req;
+	int i, idx, err;
+	int notify;
+
+	err = talk_to_backend(dev, info);
+	if (err)
+		return err;
+
+	/* prepare ring for hotplug notification */
+	for (idx = 0, i = 0; i < USB_CONN_RING_SIZE; i++) {
+		req = RING_GET_REQUEST(&info->conn_ring, idx);
+		req->id = idx;
+		idx++;
+	}
+	info->conn_ring.req_prod_pvt = idx;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
+	if (notify)
+		notify_remote_via_irq(info->irq);
+
+	return 0;
+}
+
+static struct usb_hcd *create_hcd(struct xenbus_device *dev)
+{
+	int i;
+	int err = 0;
+	int num_ports;
+	int usb_ver;
+	struct usb_hcd *hcd = NULL;
+	struct usbfront_info *info = NULL;
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend,
+					"num-ports", "%d", &num_ports);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading num-ports");
+		return ERR_PTR(-EINVAL);
+	}
+	if (num_ports < 1 || num_ports > USB_MAXCHILDREN) {
+		xenbus_dev_fatal(dev, err, "invalid num-ports");
+		return ERR_PTR(-EINVAL);
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend,
+					"usb-ver", "%d", &usb_ver);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading usb-ver");
+		return ERR_PTR(-EINVAL);
+	}
+	switch (usb_ver) {
+	case USB_VER_USB11:
+		hcd = usb_create_hcd(&xen_usb11_hc_driver, &dev->dev, dev_name(&dev->dev));
+		break;
+	case USB_VER_USB20:
+		hcd = usb_create_hcd(&xen_usb20_hc_driver, &dev->dev, dev_name(&dev->dev));
+		break;
+	default:
+		xenbus_dev_fatal(dev, err, "invalid usb-ver");
+		return ERR_PTR(-EINVAL);
+	}
+	if (!hcd) {
+		xenbus_dev_fatal(dev, err,
+				"fail to allocate USB host controller");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	info = hcd_to_info(hcd);
+	info->xbdev = dev;
+	info->rh_numports = num_ports;
+
+	for (i = 0; i < USB_URB_RING_SIZE; i++) {
+		info->shadow[i].req.id = i + 1;
+		info->shadow[i].urb = NULL;
+	}
+	info->shadow[USB_URB_RING_SIZE-1].req.id = 0x0fff;
+
+	return hcd;
+}
+
+static int usbfront_probe(struct xenbus_device *dev,
+			  const struct xenbus_device_id *id)
+{
+	int err;
+	struct usb_hcd *hcd;
+	struct usbfront_info *info;
+	char name[TASK_COMM_LEN];
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	hcd = create_hcd(dev);
+	if (IS_ERR(hcd)) {
+		err = PTR_ERR(hcd);
+		xenbus_dev_fatal(dev, err,
+				"fail to create usb host controller");
+		goto fail;
+	}
+
+	info = hcd_to_info(hcd);
+	dev_set_drvdata(&dev->dev, info);
+
+	err = usb_add_hcd(hcd, 0, 0);
+	if (err != 0) {
+		xenbus_dev_fatal(dev, err,
+				"fail to adding USB host controller");
+		goto fail;
+	}
+
+	init_waitqueue_head(&info->wq);
+	snprintf(name, TASK_COMM_LEN, "xenhcd.%d", hcd->self.busnum);
+	info->kthread = kthread_run(xenhcd_schedule, info, name);
+	if (IS_ERR(info->kthread)) {
+		err = PTR_ERR(info->kthread);
+		info->kthread = NULL;
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	usb_put_hcd(hcd);
+	dev_set_drvdata(&dev->dev, NULL);
+	return err;
+}
+
+static void usbfront_disconnect(struct xenbus_device *dev)
+{
+	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+	struct usb_hcd *hcd = info_to_hcd(info);
+
+	usb_remove_hcd(hcd);
+	if (info->kthread) {
+		kthread_stop(info->kthread);
+		info->kthread = NULL;
+	}
+	xenbus_frontend_closed(dev);
+}
+
+static void backend_changed(struct xenbus_device *dev,
+				     enum xenbus_state backend_state)
+{
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateConnected:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+		if (dev->state != XenbusStateInitialising)
+			break;
+		connect(dev);
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateClosing:
+		usbfront_disconnect(dev);
+		break;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 backend_state);
+		break;
+	}
+}
+
+static int usbfront_remove(struct xenbus_device *dev)
+{
+	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+	struct usb_hcd *hcd = info_to_hcd(info);
+
+	destroy_rings(info);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static const struct xenbus_device_id usbfront_ids[] = {
+	{ "vusb" },
+	{ "" },
+};
+
+static struct xenbus_driver usbfront_driver = {
+	.name = "vusb",
+	.ids = usbfront_ids,
+	.probe = usbfront_probe,
+	.otherend_changed = backend_changed,
+	.remove = usbfront_remove,
+};
+
+static int __init usbfront_init(void)
+{
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	xenhcd_urbp_cachep = kmem_cache_create("xenhcd_urb_priv",
+			sizeof(struct urb_priv), 0, 0, NULL);
+	if (!xenhcd_urbp_cachep) {
+		printk(KERN_ERR "usbfront failed to create kmem cache\n");
+		return -ENOMEM;
+	}
+
+	return xenbus_register_frontend(&usbfront_driver);
+}
+
+static void __exit usbfront_exit(void)
+{
+	kmem_cache_destroy(xenhcd_urbp_cachep);
+	xenbus_unregister_driver(&usbfront_driver);
+}
+
+module_init(usbfront_init);
+module_exit(usbfront_exit);
+
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("Xen USB Virtual Host Controller driver (usbfront)");
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/usbfront-hub.c
+++ linux-ec2-2.6.32/drivers/xen/usbfront/usbfront-hub.c
@@ -0,0 +1,471 @@
+/*
+ * usbfront-hub.c
+ *
+ * Xen USB Virtual Host Controller - Root Hub Emulations
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+/*
+ * set virtual port connection status
+ */
+void set_connect_state(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	if (info->ports[port].status & USB_PORT_STAT_POWER) {
+		switch (info->devices[port].speed) {
+		case USB_SPEED_UNKNOWN:
+			info->ports[port].status &=
+				~(USB_PORT_STAT_CONNECTION |
+					USB_PORT_STAT_ENABLE |
+					USB_PORT_STAT_LOW_SPEED |
+					USB_PORT_STAT_HIGH_SPEED |
+					USB_PORT_STAT_SUSPEND);
+			break;
+		case USB_SPEED_LOW:
+			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
+			info->ports[port].status |= USB_PORT_STAT_LOW_SPEED;
+			break;
+		case USB_SPEED_FULL:
+			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
+			break;
+		case USB_SPEED_HIGH:
+			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
+			info->ports[port].status |= USB_PORT_STAT_HIGH_SPEED;
+			break;
+		default: /* error */
+			return;
+		}
+		info->ports[port].status |= (USB_PORT_STAT_C_CONNECTION << 16);
+	}
+}
+
+/*
+ * set virtual device connection status
+ */
+void rhport_connect(struct usbfront_info *info,
+				int portnum, enum usb_device_speed speed)
+{
+	int port;
+
+	if (portnum < 1 || portnum > info->rh_numports)
+		return; /* invalid port number */
+
+	port = portnum - 1;
+	if (info->devices[port].speed != speed) {
+		switch (speed) {
+		case USB_SPEED_UNKNOWN: /* disconnect */
+			info->devices[port].status = USB_STATE_NOTATTACHED;
+			break;
+		case USB_SPEED_LOW:
+		case USB_SPEED_FULL:
+		case USB_SPEED_HIGH:
+			info->devices[port].status = USB_STATE_ATTACHED;
+			break;
+		default: /* error */
+			return;
+		}
+		info->devices[port].speed = speed;
+		info->ports[port].c_connection = 1;
+
+		set_connect_state(info, portnum);
+	}
+}
+
+/*
+ * SetPortFeature(PORT_SUSPENDED)
+ */
+void rhport_suspend(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	info->ports[port].status |= USB_PORT_STAT_SUSPEND;
+	info->devices[port].status = USB_STATE_SUSPENDED;
+}
+
+/*
+ * ClearPortFeature(PORT_SUSPENDED)
+ */
+void rhport_resume(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	if (info->ports[port].status & USB_PORT_STAT_SUSPEND) {
+		info->ports[port].resuming = 1;
+		info->ports[port].timeout = jiffies + msecs_to_jiffies(20);
+	}
+}
+
+/*
+ * SetPortFeature(PORT_POWER)
+ */
+void rhport_power_on(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	if ((info->ports[port].status & USB_PORT_STAT_POWER) == 0) {
+		info->ports[port].status |= USB_PORT_STAT_POWER;
+		if (info->devices[port].status != USB_STATE_NOTATTACHED)
+			info->devices[port].status = USB_STATE_POWERED;
+		if (info->ports[port].c_connection)
+			set_connect_state(info, portnum);
+	}
+}
+
+/*
+ * ClearPortFeature(PORT_POWER)
+ * SetConfiguration(non-zero)
+ * Power_Source_Off
+ * Over-current
+ */
+void rhport_power_off(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	if (info->ports[port].status & USB_PORT_STAT_POWER) {
+		info->ports[port].status = 0;
+		if (info->devices[port].status != USB_STATE_NOTATTACHED)
+			info->devices[port].status = USB_STATE_ATTACHED;
+	}
+}
+
+/*
+ * ClearPortFeature(PORT_ENABLE)
+ */
+void rhport_disable(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	info->ports[port].status &= ~USB_PORT_STAT_ENABLE;
+	info->ports[port].status &= ~USB_PORT_STAT_SUSPEND;
+	info->ports[port].resuming = 0;
+	if (info->devices[port].status != USB_STATE_NOTATTACHED)
+		info->devices[port].status = USB_STATE_POWERED;
+}
+
+/*
+ * SetPortFeature(PORT_RESET)
+ */
+void rhport_reset(struct usbfront_info *info, int portnum)
+{
+	int port;
+
+	port = portnum - 1;
+	info->ports[port].status &= ~(USB_PORT_STAT_ENABLE
+					| USB_PORT_STAT_LOW_SPEED
+					| USB_PORT_STAT_HIGH_SPEED);
+	info->ports[port].status |= USB_PORT_STAT_RESET;
+
+	if (info->devices[port].status != USB_STATE_NOTATTACHED)
+		info->devices[port].status = USB_STATE_ATTACHED;
+
+	/* 10msec reset signaling */
+	info->ports[port].timeout = jiffies + msecs_to_jiffies(10);
+}
+
+#ifdef XENHCD_PM
+#ifdef CONFIG_PM
+static int xenhcd_bus_suspend(struct usb_hcd *hcd)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+	int ret = 0;
+	int i, ports;
+
+	ports = info->rh_numports;
+
+	spin_lock_irq(&info->lock);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+		ret = -ESHUTDOWN;
+	else {
+		/* suspend any active ports*/
+		for (i = 1; i <= ports; i++)
+			rhport_suspend(info, i);
+	}
+	spin_unlock_irq(&info->lock);
+
+	del_timer_sync(&info->watchdog);
+
+	return ret;
+}
+
+static int xenhcd_bus_resume(struct usb_hcd *hcd)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+	int ret = 0;
+	int i, ports;
+
+	ports = info->rh_numports;
+
+	spin_lock_irq(&info->lock);
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+		ret = -ESHUTDOWN;
+	else {
+		/* resume any suspended ports*/
+		for (i = 1; i <= ports; i++)
+			rhport_resume(info, i);
+	}
+	spin_unlock_irq(&info->lock);
+
+	return ret;
+}
+#endif
+#endif
+
+static void xenhcd_hub_descriptor(struct usbfront_info *info,
+				  struct usb_hub_descriptor *desc)
+{
+	u16 temp;
+	int ports = info->rh_numports;
+
+	desc->bDescriptorType = 0x29;
+	desc->bPwrOn2PwrGood = 10; /* EHCI says 20ms max */
+	desc->bHubContrCurrent = 0;
+	desc->bNbrPorts = ports;
+
+	/* size of DeviceRemovable and PortPwrCtrlMask fields*/
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* bitmaps for DeviceRemovable and PortPwrCtrlMask */
+	memset(&desc->bitmap[0], 0, temp);
+	memset(&desc->bitmap[temp], 0xff, temp);
+
+	/* per-port over current reporting and no power switching */
+	temp = 0x000a;
+	desc->wHubCharacteristics = cpu_to_le16(temp);
+}
+
+/* port status change mask for hub_status_data */
+#define PORT_C_MASK \
+	((USB_PORT_STAT_C_CONNECTION \
+	| USB_PORT_STAT_C_ENABLE \
+	| USB_PORT_STAT_C_SUSPEND \
+	| USB_PORT_STAT_C_OVERCURRENT \
+	| USB_PORT_STAT_C_RESET) << 16)
+
+/*
+ * See USB 2.0 Spec, 11.12.4 Hub and Port Status Change Bitmap.
+ * If port status changed, writes the bitmap to buf and return
+ * that length(number of bytes).
+ * If Nothing changed, return 0.
+ */
+static int xenhcd_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+
+	int ports;
+	int i;
+	int length;
+
+	unsigned long flags;
+	int ret = 0;
+
+	int changed = 0;
+
+	if (!HC_IS_RUNNING(hcd->state))
+		return 0;
+
+	/* initialize the status to no-changes */
+	ports = info->rh_numports;
+	length = 1 + (ports / 8);
+	for (i = 0; i < length; i++) {
+		buf[i] = 0;
+		ret++;
+	}
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	for (i = 0; i < ports; i++) {
+		/* check status for each port */
+		if (info->ports[i].status & PORT_C_MASK) {
+			if (i < 7)
+				buf[0] |= 1 << (i + 1);
+			else if (i < 15)
+				buf[1] |= 1 << (i - 7);
+			else if (i < 23)
+				buf[2] |= 1 << (i - 15);
+			else
+				buf[3] |= 1 << (i - 23);
+			changed = 1;
+		}
+	}
+
+	if (!changed)
+		ret = 0;
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	return ret;
+}
+
+static int xenhcd_hub_control(struct usb_hcd *hcd,
+			       u16 typeReq,
+			       u16 wValue,
+			       u16 wIndex,
+			       char *buf,
+			       u16 wLength)
+{
+	struct usbfront_info *info = hcd_to_info(hcd);
+	int ports = info->rh_numports;
+	unsigned long flags;
+	int ret = 0;
+	int i;
+	int changed = 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+	switch (typeReq) {
+	case ClearHubFeature:
+		/* ignore this request */
+		break;
+	case ClearPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			rhport_resume(info, wIndex);
+			break;
+		case USB_PORT_FEAT_POWER:
+			rhport_power_off(info, wIndex);
+			break;
+		case USB_PORT_FEAT_ENABLE:
+			rhport_disable(info, wIndex);
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			info->ports[wIndex-1].c_connection = 0;
+			/* falling through */
+		default:
+			info->ports[wIndex-1].status &= ~(1 << wValue);
+			break;
+		}
+		break;
+	case GetHubDescriptor:
+		xenhcd_hub_descriptor(info,
+				      (struct usb_hub_descriptor *) buf);
+		break;
+	case GetHubStatus:
+		/* always local power supply good and no over-current exists. */
+		*(__le32 *)buf = cpu_to_le32(0);
+		break;
+	case GetPortStatus:
+		if (!wIndex || wIndex > ports)
+			goto error;
+
+		wIndex--;
+
+		/* resume completion */
+		if (info->ports[wIndex].resuming &&
+			time_after_eq(jiffies, info->ports[wIndex].timeout)) {
+			info->ports[wIndex].status |= (USB_PORT_STAT_C_SUSPEND << 16);
+			info->ports[wIndex].status &= ~USB_PORT_STAT_SUSPEND;
+		}
+
+		/* reset completion */
+		if ((info->ports[wIndex].status & USB_PORT_STAT_RESET) != 0 &&
+			time_after_eq(jiffies, info->ports[wIndex].timeout)) {
+			info->ports[wIndex].status |= (USB_PORT_STAT_C_RESET << 16);
+			info->ports[wIndex].status &= ~USB_PORT_STAT_RESET;
+
+			if (info->devices[wIndex].status != USB_STATE_NOTATTACHED) {
+				info->ports[wIndex].status |= USB_PORT_STAT_ENABLE;
+				info->devices[wIndex].status = USB_STATE_DEFAULT;
+			}
+
+			switch (info->devices[wIndex].speed) {
+			case USB_SPEED_LOW:
+				info->ports[wIndex].status |= USB_PORT_STAT_LOW_SPEED;
+				break;
+			case USB_SPEED_HIGH:
+				info->ports[wIndex].status |= USB_PORT_STAT_HIGH_SPEED;
+				break;
+			default:
+				break;
+			}
+		}
+
+		((u16 *) buf)[0] = cpu_to_le16 (info->ports[wIndex].status);
+		((u16 *) buf)[1] = cpu_to_le16 (info->ports[wIndex].status >> 16);
+		break;
+	case SetHubFeature:
+		/* not supported */
+		goto error;
+	case SetPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_POWER:
+			rhport_power_on(info, wIndex);
+			break;
+		case USB_PORT_FEAT_RESET:
+			rhport_reset(info, wIndex);
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			rhport_suspend(info, wIndex);
+			break;
+		default:
+			if ((info->ports[wIndex-1].status & USB_PORT_STAT_POWER) != 0)
+				info->ports[wIndex-1].status |= (1 << wValue);
+		}
+		break;
+
+	default:
+error:
+		ret = -EPIPE;
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	/* check status for each port */
+	for (i = 0; i < ports; i++) {
+		if (info->ports[i].status & PORT_C_MASK)
+			changed = 1;
+	}
+	if (changed)
+		usb_hcd_poll_rh_status(hcd);
+
+	return ret;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/usbfront-q.c
+++ linux-ec2-2.6.32/drivers/xen/usbfront/usbfront-q.c
@@ -0,0 +1,542 @@
+/*
+ * usbfront-q.c
+ *
+ * Xen USB Virtual Host Controller - RING operations.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+struct kmem_cache *xenhcd_urbp_cachep;
+
+static struct urb_priv *alloc_urb_priv(struct urb *urb)
+{
+	struct urb_priv *urbp;
+
+	urbp = kmem_cache_zalloc(xenhcd_urbp_cachep, GFP_ATOMIC);
+	if (!urbp)
+		return NULL;
+
+	urbp->urb = urb;
+	urb->hcpriv = urbp;
+	urbp->req_id = ~0;
+	urbp->unlink_req_id = ~0;
+	INIT_LIST_HEAD(&urbp->list);
+
+	return urbp;
+}
+
+static void free_urb_priv(struct urb_priv *urbp)
+{
+	urbp->urb->hcpriv = NULL;
+	kmem_cache_free(xenhcd_urbp_cachep, urbp);
+}
+
+static inline int get_id_from_freelist(
+	struct usbfront_info *info)
+{
+	unsigned long free;
+	free = info->shadow_free;
+	BUG_ON(free >= USB_URB_RING_SIZE);
+	info->shadow_free = info->shadow[free].req.id;
+	info->shadow[free].req.id = (unsigned int)0x0fff; /* debug */
+	return free;
+}
+
+static inline void add_id_to_freelist(
+	struct usbfront_info *info, unsigned long id)
+{
+	info->shadow[id].req.id  = info->shadow_free;
+	info->shadow[id].urb = NULL;
+	info->shadow_free = id;
+}
+
+static inline int count_pages(void *addr, int length)
+{
+	unsigned long start = (unsigned long) addr >> PAGE_SHIFT;
+	unsigned long end = (unsigned long) (addr + length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	return end - start;
+}
+
+static inline void xenhcd_gnttab_map(struct usbfront_info *info,
+		void *addr, int length, grant_ref_t *gref_head,
+		struct usbif_request_segment *seg, int nr_pages, int flags)
+{
+	grant_ref_t ref;
+	struct page *page;
+	unsigned long buffer_pfn;
+	unsigned int offset;
+	unsigned int len;
+	unsigned int bytes;
+	int i;
+
+	len = length;
+
+	for (i = 0; i < nr_pages; i++) {
+		BUG_ON(!len);
+
+		page = virt_to_page(addr);
+		buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
+		offset = offset_in_page(addr);
+
+		bytes = PAGE_SIZE - offset;
+		if (bytes > len)
+			bytes = len;
+
+		ref = gnttab_claim_grant_reference(gref_head);
+		BUG_ON(ref == -ENOSPC);
+		gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, buffer_pfn, flags);
+		seg[i].gref = ref;
+		seg[i].offset = (uint16_t)offset;
+		seg[i].length = (uint16_t)bytes;
+
+		addr += bytes;
+		len -= bytes;
+	}
+}
+
+static int map_urb_for_request(struct usbfront_info *info, struct urb *urb,
+		usbif_urb_request_t *req)
+{
+	grant_ref_t gref_head;
+	int nr_buff_pages = 0;
+	int nr_isodesc_pages = 0;
+	int ret = 0;
+
+	if (urb->transfer_buffer_length) {
+		nr_buff_pages = count_pages(urb->transfer_buffer, urb->transfer_buffer_length);
+
+		if (usb_pipeisoc(urb->pipe))
+			nr_isodesc_pages = count_pages(&urb->iso_frame_desc[0],
+					sizeof(struct usb_iso_packet_descriptor) * urb->number_of_packets);
+
+		if (nr_buff_pages + nr_isodesc_pages > USBIF_MAX_SEGMENTS_PER_REQUEST)
+			return -E2BIG;
+
+		ret = gnttab_alloc_grant_references(USBIF_MAX_SEGMENTS_PER_REQUEST, &gref_head);
+		if (ret) {
+			printk(KERN_ERR "usbfront: gnttab_alloc_grant_references() error\n");
+			return -ENOMEM;
+		}
+
+		xenhcd_gnttab_map(info, urb->transfer_buffer,
+				urb->transfer_buffer_length,
+				&gref_head, &req->seg[0], nr_buff_pages,
+				usb_pipein(urb->pipe) ? 0 : GTF_readonly);
+
+		if (!usb_pipeisoc(urb->pipe))
+			gnttab_free_grant_references(gref_head);
+	}
+
+	req->pipe = usbif_setportnum_pipe(urb->pipe, urb->dev->portnum);
+	req->transfer_flags = urb->transfer_flags;
+	req->buffer_length = urb->transfer_buffer_length;
+	req->nr_buffer_segs = nr_buff_pages;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_ISOCHRONOUS:
+		req->u.isoc.interval = urb->interval;
+		req->u.isoc.start_frame = urb->start_frame;
+		req->u.isoc.number_of_packets = urb->number_of_packets;
+		req->u.isoc.nr_frame_desc_segs = nr_isodesc_pages;
+		/* urb->number_of_packets must be > 0 */
+		if (unlikely(urb->number_of_packets <= 0))
+			BUG();
+		xenhcd_gnttab_map(info, &urb->iso_frame_desc[0],
+			sizeof(struct usb_iso_packet_descriptor) * urb->number_of_packets,
+			&gref_head, &req->seg[nr_buff_pages], nr_isodesc_pages, 0);
+		gnttab_free_grant_references(gref_head);
+		break;
+	case PIPE_INTERRUPT:
+		req->u.intr.interval = urb->interval;
+		break;
+	case PIPE_CONTROL:
+		if (urb->setup_packet)
+			memcpy(req->u.ctrl, urb->setup_packet, 8);
+		break;
+	case PIPE_BULK:
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void xenhcd_gnttab_done(struct usb_shadow *shadow)
+{
+	int nr_segs = 0;
+	int i;
+
+	nr_segs = shadow->req.nr_buffer_segs;
+
+	if (usb_pipeisoc(shadow->req.pipe))
+		nr_segs +=  shadow->req.u.isoc.nr_frame_desc_segs;
+
+	for (i = 0; i < nr_segs; i++)
+		gnttab_end_foreign_access(shadow->req.seg[i].gref, 0UL);
+
+	shadow->req.nr_buffer_segs = 0;
+	shadow->req.u.isoc.nr_frame_desc_segs = 0;
+}
+
+static void xenhcd_giveback_urb(struct usbfront_info *info, struct urb *urb, int status)
+__releases(info->lock)
+__acquires(info->lock)
+{
+	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+
+	list_del_init(&urbp->list);
+	free_urb_priv(urbp);
+	switch (urb->status) {
+	case -ECONNRESET:
+	case -ENOENT:
+		COUNT(info->stats.unlink);
+		break;
+	case -EINPROGRESS:
+		urb->status = status;
+		/* falling through */
+	default:
+		COUNT(info->stats.complete);
+	}
+	spin_unlock(&info->lock);
+	usb_hcd_giveback_urb(info_to_hcd(info), urb,
+			     urbp->status <= 0 ? urbp->status : urb->status);
+	spin_lock(&info->lock);
+}
+
+static inline int xenhcd_do_request(struct usbfront_info *info, struct urb_priv *urbp)
+{
+	usbif_urb_request_t *req;
+	struct urb *urb = urbp->urb;
+	uint16_t id;
+	int notify;
+	int ret = 0;
+
+	req = RING_GET_REQUEST(&info->urb_ring, info->urb_ring.req_prod_pvt);
+	id = get_id_from_freelist(info);
+	req->id = id;
+
+	if (unlikely(urbp->unlinked)) {
+		req->u.unlink.unlink_id = urbp->req_id;
+		req->pipe = usbif_setunlink_pipe(usbif_setportnum_pipe(
+				urb->pipe, urb->dev->portnum));
+		urbp->unlink_req_id = id;
+	} else {
+		ret = map_urb_for_request(info, urb, req);
+		if (ret < 0) {
+			add_id_to_freelist(info, id);
+			return ret;
+		}
+		urbp->req_id = id;
+	}
+
+	info->urb_ring.req_prod_pvt++;
+	info->shadow[id].urb = urb;
+	info->shadow[id].req = *req;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->urb_ring, notify);
+	if (notify)
+		notify_remote_via_irq(info->irq);
+
+	return ret;
+}
+
+static void xenhcd_kick_pending_urbs(struct usbfront_info *info)
+{
+	struct urb_priv *urbp;
+	int ret;
+
+	while (!list_empty(&info->pending_submit_list)) {
+		if (RING_FULL(&info->urb_ring)) {
+			COUNT(info->stats.ring_full);
+			timer_action(info, TIMER_RING_WATCHDOG);
+			goto done;
+		}
+
+		urbp = list_entry(info->pending_submit_list.next, struct urb_priv, list);
+		ret = xenhcd_do_request(info, urbp);
+		if (ret == 0)
+			list_move_tail(&urbp->list, &info->in_progress_list);
+		else
+			xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
+	}
+	timer_action_done(info, TIMER_SCAN_PENDING_URBS);
+
+done:
+	return;
+}
+
+/*
+ * caller must lock info->lock
+ */
+static void xenhcd_cancel_all_enqueued_urbs(struct usbfront_info *info)
+{
+	struct urb_priv *urbp, *tmp;
+
+	list_for_each_entry_safe(urbp, tmp, &info->in_progress_list, list) {
+		if (!urbp->unlinked) {
+			xenhcd_gnttab_done(&info->shadow[urbp->req_id]);
+			barrier();
+			if (urbp->urb->status == -EINPROGRESS)	/* not dequeued */
+				xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
+			else					/* dequeued */
+				xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status);
+		}
+		info->shadow[urbp->req_id].urb = NULL;
+	}
+
+	list_for_each_entry_safe(urbp, tmp, &info->pending_submit_list, list) {
+		xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
+	}
+
+	return;
+}
+
+/*
+ * caller must lock info->lock
+ */
+static void xenhcd_giveback_unlinked_urbs(struct usbfront_info *info)
+{
+	struct urb_priv *urbp, *tmp;
+
+	list_for_each_entry_safe(urbp, tmp, &info->giveback_waiting_list, list) {
+		xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status);
+	}
+}
+
+static int xenhcd_submit_urb(struct usbfront_info *info, struct urb_priv *urbp)
+{
+	int ret = 0;
+
+	if (RING_FULL(&info->urb_ring)) {
+		list_add_tail(&urbp->list, &info->pending_submit_list);
+		COUNT(info->stats.ring_full);
+		timer_action(info, TIMER_RING_WATCHDOG);
+		goto done;
+	}
+
+	if (!list_empty(&info->pending_submit_list)) {
+		list_add_tail(&urbp->list, &info->pending_submit_list);
+		timer_action(info, TIMER_SCAN_PENDING_URBS);
+		goto done;
+	}
+
+	ret = xenhcd_do_request(info, urbp);
+	if (ret == 0)
+		list_add_tail(&urbp->list, &info->in_progress_list);
+
+done:
+	return ret;
+}
+
+static int xenhcd_unlink_urb(struct usbfront_info *info, struct urb_priv *urbp)
+{
+	int ret = 0;
+
+	/* already unlinked? */
+	if (urbp->unlinked)
+		return -EBUSY;
+
+	urbp->unlinked = 1;
+
+	/* the urb is still in pending_submit queue */
+	if (urbp->req_id == ~0) {
+		list_move_tail(&urbp->list, &info->giveback_waiting_list);
+		timer_action(info, TIMER_SCAN_PENDING_URBS);
+		goto done;
+	}
+
+	/* send unlink request to backend */
+	if (RING_FULL(&info->urb_ring)) {
+		list_move_tail(&urbp->list, &info->pending_unlink_list);
+		COUNT(info->stats.ring_full);
+		timer_action(info, TIMER_RING_WATCHDOG);
+		goto done;
+	}
+
+	if (!list_empty(&info->pending_unlink_list)) {
+		list_move_tail(&urbp->list, &info->pending_unlink_list);
+		timer_action(info, TIMER_SCAN_PENDING_URBS);
+		goto done;
+	}
+
+	ret = xenhcd_do_request(info, urbp);
+	if (ret == 0)
+		list_move_tail(&urbp->list, &info->in_progress_list);
+
+done:
+	return ret;
+}
+
+static int xenhcd_urb_request_done(struct usbfront_info *info)
+{
+	usbif_urb_response_t *res;
+	struct urb *urb;
+
+	RING_IDX i, rp;
+	uint16_t id;
+	int more_to_do = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	rp = info->urb_ring.sring->rsp_prod;
+	rmb(); /* ensure we see queued responses up to "rp" */
+
+	for (i = info->urb_ring.rsp_cons; i != rp; i++) {
+		res = RING_GET_RESPONSE(&info->urb_ring, i);
+		id = res->id;
+
+		if (likely(usbif_pipesubmit(info->shadow[id].req.pipe))) {
+			xenhcd_gnttab_done(&info->shadow[id]);
+			urb = info->shadow[id].urb;
+			barrier();
+			if (likely(urb)) {
+				urb->actual_length = res->actual_length;
+				urb->error_count = res->error_count;
+				urb->start_frame = res->start_frame;
+				barrier();
+				xenhcd_giveback_urb(info, urb, res->status);
+			}
+		}
+
+		add_id_to_freelist(info, id);
+	}
+	info->urb_ring.rsp_cons = i;
+
+	if (i != info->urb_ring.req_prod_pvt)
+		RING_FINAL_CHECK_FOR_RESPONSES(&info->urb_ring, more_to_do);
+	else
+		info->urb_ring.sring->rsp_event = i + 1;
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	cond_resched();
+
+	return more_to_do;
+}
+
+static int xenhcd_conn_notify(struct usbfront_info *info)
+{
+	usbif_conn_response_t *res;
+	usbif_conn_request_t *req;
+	RING_IDX rc, rp;
+	uint16_t id;
+	uint8_t portnum, speed;
+	int more_to_do = 0;
+	int notify;
+	int port_changed = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	rc = info->conn_ring.rsp_cons;
+	rp = info->conn_ring.sring->rsp_prod;
+	rmb(); /* ensure we see queued responses up to "rp" */
+
+	while (rc != rp) {
+		res = RING_GET_RESPONSE(&info->conn_ring, rc);
+		id = res->id;
+		portnum = res->portnum;
+		speed = res->speed;
+		info->conn_ring.rsp_cons = ++rc;
+
+		rhport_connect(info, portnum, speed);
+		if (info->ports[portnum-1].c_connection)
+			port_changed = 1;
+
+		barrier();
+
+		req = RING_GET_REQUEST(&info->conn_ring, info->conn_ring.req_prod_pvt);
+		req->id = id;
+		info->conn_ring.req_prod_pvt++;
+	}
+
+	if (rc != info->conn_ring.req_prod_pvt)
+		RING_FINAL_CHECK_FOR_RESPONSES(&info->conn_ring, more_to_do);
+	else
+		info->conn_ring.sring->rsp_event = rc + 1;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
+	if (notify)
+		notify_remote_via_irq(info->irq);
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	if (port_changed)
+		usb_hcd_poll_rh_status(info_to_hcd(info));
+
+	cond_resched();
+
+	return more_to_do;
+}
+
+int xenhcd_schedule(void *arg)
+{
+	struct usbfront_info *info = (struct usbfront_info *) arg;
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(
+				info->wq,
+				info->waiting_resp || kthread_should_stop());
+		info->waiting_resp = 0;
+		smp_mb();
+
+		if (xenhcd_urb_request_done(info))
+			info->waiting_resp = 1;
+
+		if (xenhcd_conn_notify(info))
+			info->waiting_resp = 1;
+	}
+
+	return 0;
+}
+
+static void xenhcd_notify_work(struct usbfront_info *info)
+{
+	info->waiting_resp = 1;
+	wake_up(&info->wq);
+}
+
+irqreturn_t xenhcd_int(int irq, void *dev_id)
+{
+	xenhcd_notify_work((struct usbfront_info *) dev_id);
+	return IRQ_HANDLED;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/usbfront/usbfront.h
+++ linux-ec2-2.6.32/drivers/xen/usbfront/usbfront.h
@@ -0,0 +1,204 @@
+/*
+ * usbfront.h
+ *
+ * This file is part of Xen USB Virtual Host Controller driver.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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_USBFRONT_H__
+#define __XEN_USBFRONT_H__
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/list.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <xen/xenbus.h>
+#include <xen/evtchn.h>
+#include <xen/gnttab.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/io/usbif.h>
+
+/*
+ * usbfront needs USB HCD headers,
+ * drivers/usb/core/hcd.h and drivers/usb/core/hub.h,
+ * but, they are not in public include path.
+ */
+#include "../../usb/core/hcd.h"
+#include "../../usb/core/hub.h"
+
+static inline struct usbfront_info *hcd_to_info(struct usb_hcd *hcd)
+{
+	return (struct usbfront_info *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *info_to_hcd(struct usbfront_info *info)
+{
+	return container_of((void *) info, struct usb_hcd, hcd_priv);
+}
+
+/* Private per-URB data */
+struct urb_priv {
+	struct list_head list;
+	struct urb *urb;
+	int req_id;	/* RING_REQUEST id for submitting */
+	int unlink_req_id; /* RING_REQUEST id for unlinking */
+	int status;
+	unsigned unlinked:1; /* dequeued marker */
+};
+
+/* virtual roothub port status */
+struct rhport_status {
+	u32 status;
+	unsigned resuming:1; /* in resuming */
+	unsigned c_connection:1; /* connection changed */
+	unsigned long timeout;
+};
+
+/* status of attached device */
+struct vdevice_status {
+	int devnum;
+	enum usb_device_state status;
+	enum usb_device_speed speed;
+};
+
+/* RING request shadow */
+struct usb_shadow {
+	usbif_urb_request_t req;
+	struct urb *urb;
+};
+
+/* statistics for tuning, monitoring, ... */
+struct xenhcd_stats {
+	unsigned long ring_full; /* RING_FULL conditions */
+	unsigned long complete; /* normal givebacked urbs */
+	unsigned long unlink; /* unlinked urbs */
+};
+
+struct usbfront_info {
+	/* Virtual Host Controller has 4 urb queues */
+	struct list_head pending_submit_list;
+	struct list_head pending_unlink_list;
+	struct list_head in_progress_list;
+	struct list_head giveback_waiting_list;
+
+	spinlock_t lock;
+
+	/* timer that kick pending and giveback waiting urbs */
+	struct timer_list watchdog;
+	unsigned long actions;
+
+	/* virtual root hub */
+	int rh_numports;
+	struct rhport_status ports[USB_MAXCHILDREN];
+	struct vdevice_status devices[USB_MAXCHILDREN];
+
+	/* Xen related staff */
+	struct xenbus_device *xbdev;
+	int urb_ring_ref;
+	int conn_ring_ref;
+	usbif_urb_front_ring_t urb_ring;
+	usbif_conn_front_ring_t conn_ring;
+
+	unsigned int irq; /* event channel */
+	struct usb_shadow shadow[USB_URB_RING_SIZE];
+	unsigned long shadow_free;
+
+	/* RING_RESPONSE thread */
+	struct task_struct *kthread;
+	wait_queue_head_t wq;
+	unsigned int waiting_resp;
+
+	/* xmit statistics */
+#ifdef XENHCD_STATS
+	struct xenhcd_stats stats;
+#define COUNT(x) do { (x)++; } while (0)
+#else
+#define COUNT(x) do {} while (0)
+#endif
+};
+
+#define XENHCD_RING_JIFFIES (HZ/200)
+#define XENHCD_SCAN_JIFFIES 1
+
+enum xenhcd_timer_action {
+	TIMER_RING_WATCHDOG,
+	TIMER_SCAN_PENDING_URBS,
+};
+
+static inline void
+timer_action_done(struct usbfront_info *info, enum xenhcd_timer_action action)
+{
+	clear_bit(action, &info->actions);
+}
+
+static inline void
+timer_action(struct usbfront_info *info, enum xenhcd_timer_action action)
+{
+	if (timer_pending(&info->watchdog)
+			&& test_bit(TIMER_SCAN_PENDING_URBS, &info->actions))
+		return;
+
+	if (!test_and_set_bit(action, &info->actions)) {
+		unsigned long t;
+
+		switch (action) {
+		case TIMER_RING_WATCHDOG:
+			t = XENHCD_RING_JIFFIES;
+			break;
+		default:
+			t = XENHCD_SCAN_JIFFIES;
+			break;
+		}
+		mod_timer(&info->watchdog, t + jiffies);
+	}
+}
+
+extern struct kmem_cache *xenhcd_urbp_cachep;
+extern struct hc_driver xen_usb20_hc_driver;
+extern struct hc_driver xen_usb11_hc_driver;
+irqreturn_t xenhcd_int(int irq, void *dev_id);
+void xenhcd_rhport_state_change(struct usbfront_info *info,
+				int port, enum usb_device_speed speed);
+int xenhcd_schedule(void *arg);
+
+#endif /* __XEN_USBFRONT_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/common.h
+++ linux-ec2-2.6.32/drivers/xen/scsiback/common.h
@@ -0,0 +1,186 @@
+/*
+ * 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;
+
+	int feature;
+
+	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;
+	
+	uint16_t v_chn, v_tgt;
+
+	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)
+
+#define VSCSI_TYPE_HOST		1
+
+irqreturn_t scsiback_intr(int, void *);
+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__ */
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/scsiback/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_XEN_SCSI_BACKEND) := xen-scsibk.o
+
+xen-scsibk-y	:= interface.o scsiback.o xenbus.o translate.o emulate.o
+
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/scsiback/xenbus.c
@@ -0,0 +1,377 @@
+/*
+ * 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_get_drvdata(&dev->dev);
+	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_get_drvdata(&dev->dev);
+
+	if (be->info) {
+		scsiback_disconnect(be->info);
+		scsiback_release_translation_entry(be->info);
+		scsiback_free(be->info);
+		be->info = NULL;
+	}
+
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+
+	return 0;
+}
+
+
+static int scsiback_probe(struct xenbus_device *dev,
+			   const struct xenbus_device_id *id)
+{
+	int err;
+	unsigned val = 0;
+
+	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_set_drvdata(&dev->dev, 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;
+	be->info->feature = 0;	/*default not HOSTMODE.*/
+
+	scsiback_init_translation_table(be->info);
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+				"feature-host", "%d", &val);
+	if (XENBUS_EXIST_ERR(err))
+		val = 0;
+
+	if (val)
+		be->info->feature = VSCSI_TYPE_HOST;
+
+	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",
+	.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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/translate.c
+++ linux-ec2-2.6.32/drivers/xen/scsiback/translate.c
@@ -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;
+
+}
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/emulate.c
+++ linux-ec2-2.6.32/drivers/xen/scsiback/emulate.c
@@ -0,0 +1,473 @@
+/*
+ * 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];
+
+#define NO_EMULATE(cmd) \
+	bitmap[cmd] = VSCSIIF_NEED_CMD_EXEC; \
+	pre_function[cmd] = NULL; \
+	post_function[cmd] = NULL
+
+
+
+/*
+  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 *sgl, unsigned int nr_sg,
+	       void *buf, unsigned int buflen)
+{
+	struct scatterlist *sg;
+	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_each_sg (sgl, sg, nr_sg, i) {
+		if (sg_page(sg) == 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(sg));
+		to = pfn_to_kaddr(pfn) + (sg->offset);
+		memcpy(to, from, copy_size);
+
+		from_rest  -= copy_size;
+		if (from_rest == 0) {
+			return 0;
+		}
+		
+		from += copy_size;
+	}
+
+	printk(KERN_WARNING "%s: no space in scatterlist\n",
+	       __FUNCTION__);
+	return -ENOMEM;
+}
+
+static int __copy_from_sg(struct scatterlist *sgl, unsigned int nr_sg,
+		 void *buf, unsigned int buflen)
+{
+	struct scatterlist *sg;
+	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_each_sg (sgl, sg, nr_sg, i) {
+		if (sg_page(sg) == 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(sg));
+		from = pfn_to_kaddr(pfn) + (sg->offset);
+		memcpy(to, from, copy_size);
+
+		to_capa  -= copy_size;
+		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->v_chn;
+	unsigned int        target  = pending_req->v_tgt;
+	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.)
+	*/
+
+	/*
+	  Following commands do not require emulation.
+	*/
+	NO_EMULATE(TEST_UNIT_READY);       /*0x00*/
+	NO_EMULATE(REZERO_UNIT);           /*0x01*/
+	NO_EMULATE(REQUEST_SENSE);         /*0x03*/
+	NO_EMULATE(FORMAT_UNIT);           /*0x04*/
+	NO_EMULATE(READ_BLOCK_LIMITS);     /*0x05*/
+	/*NO_EMULATE(REASSIGN_BLOCKS);       *//*0x07*/
+	/*NO_EMULATE(INITIALIZE_ELEMENT_STATUS); *//*0x07*/
+	NO_EMULATE(READ_6);                /*0x08*/
+	NO_EMULATE(WRITE_6);               /*0x0a*/
+	/*NO_EMULATE(SEEK_6);                *//*0x0b*/
+	/*NO_EMULATE(READ_REVERSE);          *//*0x0f*/
+	NO_EMULATE(WRITE_FILEMARKS);       /*0x10*/
+	NO_EMULATE(SPACE);                 /*0x11*/
+	NO_EMULATE(INQUIRY);               /*0x12*/
+	/*NO_EMULATE(RECOVER_BUFFERED_DATA); *//*0x14*/
+	/*NO_EMULATE(MODE_SELECT);           *//*0x15*/
+	/*NO_EMULATE(RESERVE);               *//*0x16*/
+	/*NO_EMULATE(RELEASE);               *//*0x17*/
+	/*NO_EMULATE(COPY);                  *//*0x18*/
+	NO_EMULATE(ERASE);                 /*0x19*/
+	NO_EMULATE(MODE_SENSE);            /*0x1a*/
+	/*NO_EMULATE(START_STOP);            *//*0x1b*/
+	/*NO_EMULATE(RECEIVE_DIAGNOSTIC);    *//*0x1c*/
+	NO_EMULATE(SEND_DIAGNOSTIC);       /*0x1d*/
+	/*NO_EMULATE(ALLOW_MEDIUM_REMOVAL);  *//*0x1e*/
+
+	/*NO_EMULATE(SET_WINDOW);            *//*0x24*/
+	NO_EMULATE(READ_CAPACITY);         /*0x25*/
+	NO_EMULATE(READ_10);               /*0x28*/
+	NO_EMULATE(WRITE_10);              /*0x2a*/
+	/*NO_EMULATE(SEEK_10);               *//*0x2b*/
+	/*NO_EMULATE(POSITION_TO_ELEMENT);   *//*0x2b*/
+	/*NO_EMULATE(WRITE_VERIFY);          *//*0x2e*/
+	/*NO_EMULATE(VERIFY);                *//*0x2f*/
+	/*NO_EMULATE(SEARCH_HIGH);           *//*0x30*/
+	/*NO_EMULATE(SEARCH_EQUAL);          *//*0x31*/
+	/*NO_EMULATE(SEARCH_LOW);            *//*0x32*/
+	/*NO_EMULATE(SET_LIMITS);            *//*0x33*/
+	/*NO_EMULATE(PRE_FETCH);             *//*0x34*/
+	/*NO_EMULATE(READ_POSITION);         *//*0x34*/
+	/*NO_EMULATE(SYNCHRONIZE_CACHE);     *//*0x35*/
+	/*NO_EMULATE(LOCK_UNLOCK_CACHE);     *//*0x36*/
+	/*NO_EMULATE(READ_DEFECT_DATA);      *//*0x37*/
+	/*NO_EMULATE(MEDIUM_SCAN);           *//*0x38*/
+	/*NO_EMULATE(COMPARE);               *//*0x39*/
+	/*NO_EMULATE(COPY_VERIFY);           *//*0x3a*/
+	/*NO_EMULATE(WRITE_BUFFER);          *//*0x3b*/
+	/*NO_EMULATE(READ_BUFFER);           *//*0x3c*/
+	/*NO_EMULATE(UPDATE_BLOCK);          *//*0x3d*/
+	/*NO_EMULATE(READ_LONG);             *//*0x3e*/
+	/*NO_EMULATE(WRITE_LONG);            *//*0x3f*/
+	/*NO_EMULATE(CHANGE_DEFINITION);     *//*0x40*/
+	/*NO_EMULATE(WRITE_SAME);            *//*0x41*/
+	/*NO_EMULATE(READ_TOC);              *//*0x43*/
+	/*NO_EMULATE(LOG_SELECT);            *//*0x4c*/
+	/*NO_EMULATE(LOG_SENSE);             *//*0x4d*/
+	/*NO_EMULATE(MODE_SELECT_10);        *//*0x55*/
+	/*NO_EMULATE(RESERVE_10);            *//*0x56*/
+	/*NO_EMULATE(RELEASE_10);            *//*0x57*/
+	/*NO_EMULATE(MODE_SENSE_10);         *//*0x5a*/
+	/*NO_EMULATE(PERSISTENT_RESERVE_IN); *//*0x5e*/
+	/*NO_EMULATE(PERSISTENT_RESERVE_OUT); *//*0x5f*/
+	/*           REPORT_LUNS             *//*0xa0*//*Full emulaiton*/
+	/*NO_EMULATE(MOVE_MEDIUM);           *//*0xa5*/
+	/*NO_EMULATE(EXCHANGE_MEDIUM);       *//*0xa6*/
+	/*NO_EMULATE(READ_12);               *//*0xa8*/
+	/*NO_EMULATE(WRITE_12);              *//*0xaa*/
+	/*NO_EMULATE(WRITE_VERIFY_12);       *//*0xae*/
+	/*NO_EMULATE(SEARCH_HIGH_12);        *//*0xb0*/
+	/*NO_EMULATE(SEARCH_EQUAL_12);       *//*0xb1*/
+	/*NO_EMULATE(SEARCH_LOW_12);         *//*0xb2*/
+	/*NO_EMULATE(READ_ELEMENT_STATUS);   *//*0xb8*/
+	/*NO_EMULATE(SEND_VOLUME_TAG);       *//*0xb6*/
+	/*NO_EMULATE(WRITE_LONG_2);          *//*0xea*/
+	/*NO_EMULATE(READ_16);               *//*0x88*/
+	/*NO_EMULATE(WRITE_16);              *//*0x8a*/
+	/*NO_EMULATE(VERIFY_16);	      *//*0x8f*/
+	/*NO_EMULATE(SERVICE_ACTION_IN);     *//*0x9e*/
+
+	/*
+	  Following commands require emulation.
+	*/
+	pre_function[REPORT_LUNS] = __report_luns;
+	bitmap[REPORT_LUNS] = (VSCSIIF_NEED_EMULATE_REQBUF | 
+					VSCSIIF_NEED_EMULATE_RSPBUF);
+
+	return;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/interface.c
+++ linux-ec2-2.6.32/drivers/xen/scsiback/interface.c
@@ -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 struct kmem_cache *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);
+	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);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/scsiback/scsiback.c
+++ linux-ec2-2.6.32/drivers/xen/scsiback/scsiback.c
@@ -0,0 +1,725 @@
+/*
+ * 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;
+	struct scsi_sense_hdr sshdr;
+	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) {
+		if (scsi_normalize_sense(sense_buffer,
+			sizeof(sense_buffer), &sshdr)) {
+
+			int len = 8 + sense_buffer[7];
+
+			if (len > VSCSIIF_SENSE_BUFFERSIZE)
+				len = VSCSIIF_SENSE_BUFFERSIZE;
+
+			memcpy(ring_res->sense_buffer, sense_buffer, len);
+			ring_res->sense_len = len;
+		}
+	} 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 uptodate)
+{
+	pending_req_t *pending_req = req->end_io_data;
+	unsigned char *sense_buffer;
+	unsigned int resid;
+	int errors;
+
+	sense_buffer = req->sense;
+	resid        = blk_rq_bytes(req);
+	errors       = req->errors;
+
+	if (errors != 0) {
+		if (log_print_stat)
+			scsiback_print_status(sense_buffer, errors, pending_req);
+	}
+
+	/* The Host mode is through as for Emulation. */
+	if (pending_req->info->feature != VSCSI_TYPE_HOST)
+		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) {
+		struct scatterlist *sg;
+
+		/* 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;
+		}
+
+		sg_init_table(pending_req->sgl, nr_segments);
+
+		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_each_sg (pending_req->sgl, sg, 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));
+
+			sg_set_page(sg, virt_to_page(vaddr(pending_req, i)),
+				    ring_req->seg[i].length,
+				    ring_req->seg[i].offset);
+			data_len += sg->length;
+
+			barrier();
+			if (sg->offset >= PAGE_SIZE ||
+			    sg->length > PAGE_SIZE ||
+			    sg->offset + sg->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_bi_endio */
+static void scsiback_bi_endio(struct bio *bio, int error)
+{
+	bio_put(bio);
+}
+
+
+
+/* quoted scsi_lib.c/scsi_req_map_sg . */
+static struct bio *request_map_sg(pending_req_t *pending_req)
+{
+	struct request_queue *q = pending_req->sdev->request_queue;
+	unsigned int nsegs = (unsigned int)pending_req->nr_segments;
+	unsigned int i, len, bytes, off, nr_pages, nr_vecs = 0;
+	struct scatterlist *sg;
+	struct page *page;
+	struct bio *bio = NULL, *bio_first = NULL, *bio_last = NULL;
+	int err;
+
+	for_each_sg (pending_req->sgl, sg, nsegs, i) {
+		page = sg_page(sg);
+		off = sg->offset;
+		len = sg->length;
+
+		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(unsigned 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_last)
+					bio_last->bi_next = bio;
+				else
+					bio_first = bio;
+				bio_last = bio;
+			}
+
+			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) {
+				bio->bi_flags &= ~(1 << BIO_SEG_VALID);
+				if (pending_req->sc_data_direction == WRITE)
+					bio->bi_rw |= (1 << BIO_RW);
+				bio = NULL;
+			}
+
+			page++;
+			len -= bytes;
+			off = 0;
+		}
+	}
+
+	return bio_first;
+
+free_bios:
+	while ((bio = bio_first) != NULL) {
+		bio_first = bio->bi_next;
+		bio_put(bio);
+	}
+
+	return ERR_PTR(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 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);
+	if (pending_req->nr_segments) {
+		struct bio *bio = request_map_sg(pending_req);
+
+		if (IS_ERR(bio)) {
+			printk(KERN_ERR "scsiback: SG Request Map Error\n");
+			return;
+		}
+
+		rq = blk_make_request(pending_req->sdev->request_queue, bio,
+				      GFP_KERNEL);
+		if (IS_ERR(rq)) {
+			printk(KERN_ERR "scsiback: Make Request Error\n");
+			return;
+		}
+
+		rq->buffer = NULL;
+	} else {
+		rq = blk_get_request(pending_req->sdev->request_queue, write,
+				     GFP_KERNEL);
+		if (unlikely(!rq)) {
+			printk(KERN_ERR "scsiback: Get Request Error\n");
+			return;
+		}
+	}
+
+	rq->cmd_type = REQ_TYPE_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;
+
+	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)
+{
+	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;
+
+	pending_req->v_chn = vir.chn = ring_req->channel;
+	pending_req->v_tgt = 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) {
+
+			/* The Host mode is through as for Emulation. */
+			if (info->feature == VSCSI_TYPE_HOST)
+				scsiback_cmd_exec(pending_req);
+			else
+				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;
+}
+
+#if 0
+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));
+
+}
+#endif
+
+module_init(scsiback_init);
+
+#if 0
+module_exit(scsiback_exit);
+#endif
+
+MODULE_DESCRIPTION("Xen SCSI backend driver");
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/xenoprof/xenoprofile.c
+++ linux-ec2-2.6.32/drivers/xen/xenoprof/xenoprofile.c
@@ -0,0 +1,542 @@
+/**
+ * @file xenoprofile.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ *
+ * Modified by Aravind Menon and Jose Renato Santos for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ *
+ * Separated out arch-generic part
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ */
+
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/smp.h>
+#include <linux/oprofile.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
+#include <xen/evtchn.h>
+#include <xen/xenoprof.h>
+#include <xen/driver_util.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/xenoprof.h>
+#include "../../../drivers/oprofile/event_buffer.h"
+
+#define MAX_XENOPROF_SAMPLES 16
+
+/* sample buffers shared with Xen */
+static xenoprof_buf_t *xenoprof_buf[MAX_VIRT_CPUS];
+/* Shared buffer area */
+static struct xenoprof_shared_buffer shared_buffer;
+
+/* Passive sample buffers shared with Xen */
+static xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
+/* Passive shared buffer area */
+static struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS];
+
+static int xenoprof_start(void);
+static void xenoprof_stop(void);
+
+static int xenoprof_enabled = 0;
+static int xenoprof_is_primary = 0;
+static int active_defined;
+
+extern unsigned long oprofile_backtrace_depth;
+
+/* Number of buffers in shared area (one per VCPU) */
+static int nbuf;
+/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
+static int ovf_irq[NR_CPUS];
+/* cpu model type string - copied from Xen on XENOPROF_init command */
+static char cpu_type[XENOPROF_CPU_TYPE_SIZE];
+
+#ifdef CONFIG_PM
+
+static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
+{
+	if (xenoprof_enabled == 1)
+		xenoprof_stop();
+	return 0;
+}
+
+
+static int xenoprof_resume(struct sys_device * dev)
+{
+	if (xenoprof_enabled == 1)
+		xenoprof_start();
+	return 0;
+}
+
+
+static struct sysdev_class oprofile_sysclass = {
+	.name		= "oprofile",
+	.resume		= xenoprof_resume,
+	.suspend	= xenoprof_suspend
+};
+
+
+static struct sys_device device_oprofile = {
+	.id	= 0,
+	.cls	= &oprofile_sysclass,
+};
+
+
+static int __init init_driverfs(void)
+{
+	int error;
+	if (!(error = sysdev_class_register(&oprofile_sysclass)))
+		error = sysdev_register(&device_oprofile);
+	return error;
+}
+
+
+static void exit_driverfs(void)
+{
+	sysdev_unregister(&device_oprofile);
+	sysdev_class_unregister(&oprofile_sysclass);
+}
+
+#else
+#define init_driverfs() do { } while (0)
+#define exit_driverfs() do { } while (0)
+#endif /* CONFIG_PM */
+
+static unsigned long long oprofile_samples;
+static unsigned long long p_oprofile_samples;
+
+static unsigned int pdomains;
+static struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
+
+/* Check whether the given entry is an escape code */
+static int xenoprof_is_escape(xenoprof_buf_t * buf, int tail)
+{
+	return (buf->event_log[tail].eip == XENOPROF_ESCAPE_CODE);
+}
+
+/* Get the event at the given entry  */
+static uint8_t xenoprof_get_event(xenoprof_buf_t * buf, int tail)
+{
+	return (buf->event_log[tail].event);
+}
+
+static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
+{
+	int head, tail, size;
+	int tracing = 0;
+
+	head = buf->event_head;
+	tail = buf->event_tail;
+	size = buf->event_size;
+
+	while (tail != head) {
+		if (xenoprof_is_escape(buf, tail) &&
+		    xenoprof_get_event(buf, tail) == XENOPROF_TRACE_BEGIN) {
+			tracing=1;
+			oprofile_add_mode(buf->event_log[tail].mode);
+			if (!is_passive)
+				oprofile_samples++;
+			else
+				p_oprofile_samples++;
+			
+		} else {
+			oprofile_add_pc(buf->event_log[tail].eip,
+					buf->event_log[tail].mode,
+					buf->event_log[tail].event);
+			if (!tracing) {
+				if (!is_passive)
+					oprofile_samples++;
+				else
+					p_oprofile_samples++;
+			}
+       
+		}
+		tail++;
+		if(tail==size)
+		    tail=0;
+	}
+	buf->event_tail = tail;
+}
+
+static void xenoprof_handle_passive(void)
+{
+	int i, j;
+	int flag_domain, flag_switch = 0;
+	
+	for (i = 0; i < pdomains; i++) {
+		flag_domain = 0;
+		for (j = 0; j < passive_domains[i].nbuf; j++) {
+			xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
+			if (buf->event_head == buf->event_tail)
+				continue;
+			if (!flag_domain) {
+				if (!oprofile_add_domain_switch(
+					passive_domains[i].domain_id))
+					goto done;
+				flag_domain = 1;
+			}
+			xenoprof_add_pc(buf, 1);
+			flag_switch = 1;
+		}
+	}
+done:
+	if (flag_switch)
+		oprofile_add_domain_switch(COORDINATOR_DOMAIN);
+}
+
+static irqreturn_t xenoprof_ovf_interrupt(int irq, void *dev_id)
+{
+	struct xenoprof_buf * buf;
+	static unsigned long flag;
+
+	buf = xenoprof_buf[smp_processor_id()];
+
+	xenoprof_add_pc(buf, 0);
+
+	if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) {
+		xenoprof_handle_passive();
+		smp_mb__before_clear_bit();
+		clear_bit(0, &flag);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ovf_action = {
+	.handler = xenoprof_ovf_interrupt,
+	.flags   = IRQF_DISABLED,
+	.name    = "xenoprof"
+};
+
+static void unbind_virq(void)
+{
+	unsigned int i;
+
+	for_each_online_cpu(i) {
+		if (ovf_irq[i] >= 0) {
+			unbind_from_per_cpu_irq(ovf_irq[i], i, &ovf_action);
+			ovf_irq[i] = -1;
+		}
+	}
+}
+
+
+static int bind_virq(void)
+{
+	unsigned int i;
+	int result;
+
+	for_each_online_cpu(i) {
+		result = bind_virq_to_irqaction(VIRQ_XENOPROF, i, &ovf_action);
+
+		if (result < 0) {
+			unbind_virq();
+			return result;
+		}
+
+		ovf_irq[i] = result;
+	}
+		
+	return 0;
+}
+
+
+static void unmap_passive_list(void)
+{
+	int i;
+	for (i = 0; i < pdomains; i++)
+		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
+	pdomains = 0;
+}
+
+
+static int map_xenoprof_buffer(int max_samples)
+{
+	struct xenoprof_get_buffer get_buffer;
+	struct xenoprof_buf *buf;
+	int ret, i;
+
+	if ( shared_buffer.buffer )
+		return 0;
+
+	get_buffer.max_samples = max_samples;
+	ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer);
+	if (ret)
+		return ret;
+	nbuf = get_buffer.nbuf;
+
+	for (i=0; i< nbuf; i++) {
+		buf = (struct xenoprof_buf*) 
+			&shared_buffer.buffer[i * get_buffer.bufsize];
+		BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+		xenoprof_buf[buf->vcpu_id] = buf;
+	}
+
+	return 0;
+}
+
+
+static int xenoprof_setup(void)
+{
+	int ret;
+
+	if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
+		return ret;
+
+	if ( (ret = bind_virq()) )
+		return ret;
+
+	if (xenoprof_is_primary) {
+		/* Define dom0 as an active domain if not done yet */
+		if (!active_defined) {
+			domid_t domid;
+			ret = HYPERVISOR_xenoprof_op(
+				XENOPROF_reset_active_list, NULL);
+			if (ret)
+				goto err;
+			domid = 0;
+			ret = HYPERVISOR_xenoprof_op(
+				XENOPROF_set_active, &domid);
+			if (ret)
+				goto err;
+			active_defined = 1;
+		}
+
+		if (oprofile_backtrace_depth > 0) {
+			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_backtrace, 
+						     &oprofile_backtrace_depth);
+			if (ret)
+				oprofile_backtrace_depth = 0;
+		}
+
+		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
+		if (ret)
+			goto err;
+		
+		xenoprof_arch_counter();
+		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
+		if (ret)
+			goto err;
+	}
+
+	ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
+	if (ret)
+		goto err;
+
+	xenoprof_enabled = 1;
+	return 0;
+ err:
+	unbind_virq();
+	return ret;
+}
+
+
+static void xenoprof_shutdown(void)
+{
+	xenoprof_enabled = 0;
+
+	WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL));
+
+	if (xenoprof_is_primary) {
+		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_release_counters,
+					       NULL));
+		active_defined = 0;
+	}
+
+	unbind_virq();
+
+	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
+	if (xenoprof_is_primary)
+		unmap_passive_list();
+}
+
+
+static int xenoprof_start(void)
+{
+	int ret = 0;
+
+	if (xenoprof_is_primary)
+		ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
+	if (!ret)
+		xenoprof_arch_start();
+	return ret;
+}
+
+
+static void xenoprof_stop(void)
+{
+	if (xenoprof_is_primary)
+		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL));
+	xenoprof_arch_stop();
+}
+
+
+static int xenoprof_set_active(int * active_domains,
+			       unsigned int adomains)
+{
+	int ret = 0;
+	int i;
+	int set_dom0 = 0;
+	domid_t domid;
+
+	if (!xenoprof_is_primary)
+		return 0;
+
+	if (adomains > MAX_OPROF_DOMAINS)
+		return -E2BIG;
+
+	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+	if (ret)
+		return ret;
+
+	for (i=0; i<adomains; i++) {
+		domid = active_domains[i];
+		if (domid != active_domains[i]) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+		if (ret)
+			goto out;
+		if (active_domains[i] == 0)
+			set_dom0 = 1;
+	}
+	/* dom0 must always be active but may not be in the list */ 
+	if (!set_dom0) {
+		domid = 0;
+		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+	}
+
+out:
+	if (ret)
+		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list,
+					       NULL));
+	active_defined = !ret;
+	return ret;
+}
+
+static int xenoprof_set_passive(int * p_domains,
+                                unsigned int pdoms)
+{
+	int ret;
+	unsigned int i, j;
+	struct xenoprof_buf *buf;
+
+	if (!xenoprof_is_primary)
+        	return 0;
+
+	if (pdoms > MAX_OPROF_DOMAINS)
+		return -E2BIG;
+
+	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
+	if (ret)
+		return ret;
+	unmap_passive_list();
+
+	for (i = 0; i < pdoms; i++) {
+		passive_domains[i].domain_id = p_domains[i];
+		passive_domains[i].max_samples = 2048;
+		ret = xenoprof_arch_set_passive(&passive_domains[i],
+						&p_shared_buffer[i]);
+		if (ret)
+			goto out;
+		for (j = 0; j < passive_domains[i].nbuf; j++) {
+			buf = (struct xenoprof_buf *)
+				&p_shared_buffer[i].buffer[
+				j * passive_domains[i].bufsize];
+			BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
+			p_xenoprof_buf[i][buf->vcpu_id] = buf;
+		}
+	}
+
+	pdomains = pdoms;
+	return 0;
+
+out:
+	for (j = 0; j < i; j++)
+		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
+
+	return ret;
+}
+
+
+/* The dummy backtrace function to keep oprofile happy
+ * The real backtrace is done in xen
+ */
+static void xenoprof_dummy_backtrace(struct pt_regs * const regs, 
+				     unsigned int depth)
+{
+	/* this should never be called */
+	BUG();
+	return;
+}
+
+
+static struct oprofile_operations xenoprof_ops = {
+#ifdef HAVE_XENOPROF_CREATE_FILES
+	.create_files 	= xenoprof_create_files,
+#endif
+	.set_active	= xenoprof_set_active,
+	.set_passive    = xenoprof_set_passive,
+	.setup 		= xenoprof_setup,
+	.shutdown	= xenoprof_shutdown,
+	.start		= xenoprof_start,
+	.stop		= xenoprof_stop,
+	.backtrace	= xenoprof_dummy_backtrace
+};
+
+
+/* in order to get driverfs right */
+static int using_xenoprof;
+
+int __init xenoprofile_init(struct oprofile_operations * ops)
+{
+	struct xenoprof_init init;
+	unsigned int i;
+	int ret;
+
+	ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
+	if (!ret) {
+		xenoprof_arch_init_counter(&init);
+		xenoprof_is_primary = init.is_primary;
+
+		/*  cpu_type is detected by Xen */
+		cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
+		strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
+		xenoprof_ops.cpu_type = cpu_type;
+
+		init_driverfs();
+		using_xenoprof = 1;
+		*ops = xenoprof_ops;
+
+		for (i=0; i<NR_CPUS; i++)
+			ovf_irq[i] = -1;
+
+		active_defined = 0;
+	}
+
+	printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n",
+	       __func__, ret, init.num_events, xenoprof_is_primary);
+	return ret;
+}
+
+
+void xenoprofile_exit(void)
+{
+	if (using_xenoprof)
+		exit_driverfs();
+
+	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
+	if (xenoprof_is_primary) {
+		unmap_passive_list();
+		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL));
+        }
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/blkback-pagemap.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/blkback-pagemap.c
@@ -0,0 +1,96 @@
+#include <linux/module.h>
+#include "blkback-pagemap.h"
+
+static int blkback_pagemap_size;
+static struct blkback_pagemap *blkback_pagemap;
+
+static inline int
+blkback_pagemap_entry_clear(struct blkback_pagemap *map)
+{
+	static struct blkback_pagemap zero;
+	return !memcmp(map, &zero, sizeof(zero));
+}
+
+int
+blkback_pagemap_init(int pages)
+{
+	blkback_pagemap = kzalloc(pages * sizeof(struct blkback_pagemap),
+				  GFP_KERNEL);
+	if (!blkback_pagemap)
+		return -ENOMEM;
+
+	blkback_pagemap_size = pages;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blkback_pagemap_init);
+
+void
+blkback_pagemap_set(int idx, struct page *page,
+		    domid_t domid, busid_t busid, grant_ref_t gref)
+{
+	struct blkback_pagemap *entry;
+
+	BUG_ON(!blkback_pagemap);
+	BUG_ON(idx >= blkback_pagemap_size);
+
+	SetPageBlkback(page);
+	set_page_private(page, idx);
+
+	entry = blkback_pagemap + idx;
+	if (!blkback_pagemap_entry_clear(entry)) {
+		printk("overwriting pagemap %d: d %u b %u g %u\n",
+		       idx, entry->domid, entry->busid, entry->gref);
+		BUG();
+	}
+
+	entry->domid = domid;
+	entry->busid = busid;
+	entry->gref  = gref;
+}
+EXPORT_SYMBOL_GPL(blkback_pagemap_set);
+
+void
+blkback_pagemap_clear(struct page *page)
+{
+	int idx;
+	struct blkback_pagemap *entry;
+
+	idx = (int)page_private(page);
+
+	BUG_ON(!blkback_pagemap);
+	BUG_ON(!PageBlkback(page));
+	BUG_ON(idx >= blkback_pagemap_size);
+
+	entry = blkback_pagemap + idx;
+	if (blkback_pagemap_entry_clear(entry)) {
+		printk("clearing empty pagemap %d\n", idx);
+		BUG();
+	}
+
+	memset(entry, 0, sizeof(*entry));
+}
+EXPORT_SYMBOL_GPL(blkback_pagemap_clear);
+
+struct blkback_pagemap
+blkback_pagemap_read(struct page *page)
+{
+	int idx;
+	struct blkback_pagemap *entry;
+
+	idx = (int)page_private(page);
+
+	BUG_ON(!blkback_pagemap);
+	BUG_ON(!PageBlkback(page));
+	BUG_ON(idx >= blkback_pagemap_size);
+
+	entry = blkback_pagemap + idx;
+	if (blkback_pagemap_entry_clear(entry)) {
+		printk("reading empty pagemap %d\n", idx);
+		BUG();
+	}
+
+	return *entry;
+}
+EXPORT_SYMBOL(blkback_pagemap_read);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/vbd.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/vbd.c
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * blkback/vbd.c
+ * 
+ * Routines for managing virtual block devices (VBDs).
+ * 
+ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
+ * 
+ * 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 "common.h"
+
+#define vbd_sz(_v)   ((_v)->bdev->bd_part ?				\
+	(_v)->bdev->bd_part->nr_sects : get_capacity((_v)->bdev->bd_disk))
+
+unsigned long long vbd_size(struct vbd *vbd)
+{
+	return vbd_sz(vbd);
+}
+
+unsigned int vbd_info(struct vbd *vbd)
+{
+	return vbd->type | (vbd->readonly?VDISK_READONLY:0);
+}
+
+unsigned long vbd_secsize(struct vbd *vbd)
+{
+	return bdev_logical_block_size(vbd->bdev);
+}
+
+int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
+	       unsigned minor, int readonly, int cdrom)
+{
+	struct vbd *vbd;
+	struct block_device *bdev;
+
+	vbd = &blkif->vbd;
+	vbd->handle   = handle; 
+	vbd->readonly = readonly;
+	vbd->type     = 0;
+
+	vbd->pdevice  = MKDEV(major, minor);
+
+	bdev = open_by_devnum(vbd->pdevice,
+			      vbd->readonly ? FMODE_READ : FMODE_WRITE);
+
+	if (IS_ERR(bdev)) {
+		DPRINTK("vbd_creat: device %08x could not be opened.\n",
+			vbd->pdevice);
+		return -ENOENT;
+	}
+
+	vbd->bdev = bdev;
+
+	if (vbd->bdev->bd_disk == NULL) {
+		DPRINTK("vbd_creat: device %08x doesn't exist.\n",
+			vbd->pdevice);
+		vbd_free(vbd);
+		return -ENOENT;
+	}
+
+	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;
+
+	DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
+		handle, blkif->domid);
+	return 0;
+}
+
+void vbd_free(struct vbd *vbd)
+{
+	if (vbd->bdev)
+		blkdev_put(vbd->bdev,
+			   vbd->readonly ? FMODE_READ : FMODE_WRITE);
+	vbd->bdev = NULL;
+}
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
+{
+	struct vbd *vbd = &blkif->vbd;
+	int rc = -EACCES;
+
+	if ((operation != READ) && vbd->readonly)
+		goto out;
+
+	if (vbd->bdev == NULL)
+		goto out;
+
+	if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
+		goto out;
+
+	req->dev  = vbd->pdevice;
+	req->bdev = vbd->bdev;
+	rc = 0;
+
+ out:
+	return rc;
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/common.h
+++ linux-ec2-2.6.32/drivers/xen/blkback/common.h
@@ -0,0 +1,156 @@
+/* 
+ * 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 __BLKIF__BACKEND__COMMON_H__
+#define __BLKIF__BACKEND__COMMON_H__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/pgalloc.h>
+#include <xen/evtchn.h>
+#include <asm/hypervisor.h>
+#include <xen/blkif.h>
+#include <xen/gnttab.h>
+#include <xen/driver_util.h>
+#include <xen/xenbus.h>
+#include "blkback-pagemap.h"
+
+
+#define DPRINTK(_f, _a...)			\
+	pr_debug("(file=%s, line=%d) " _f,	\
+		 __FILE__ , __LINE__ , ## _a )
+
+struct vbd {
+	blkif_vdev_t   handle;      /* what the domain refers to this vbd as */
+	unsigned char  readonly;    /* Non-zero -> read-only */
+	unsigned char  type;        /* VDISK_xxx */
+	u32            pdevice;     /* phys device that this vbd maps to */
+	struct block_device *bdev;
+};
+
+struct backend_info;
+
+typedef struct blkif_st {
+	/* Unique identifier for this interface. */
+	domid_t           domid;
+	unsigned int      handle;
+	/* Physical parameters of the comms window. */
+	unsigned int      irq;
+	/* Comms information. */
+	enum blkif_protocol blk_protocol;
+	blkif_back_rings_t blk_rings;
+	struct vm_struct *blk_ring_area;
+	/* The VBD attached to this interface. */
+	struct vbd        vbd;
+	/* Back pointer to the backend_info. */
+	struct backend_info *be;
+	/* Private fields. */
+	spinlock_t       blk_ring_lock;
+	atomic_t         refcnt;
+
+	wait_queue_head_t   wq;
+	struct task_struct  *xenblkd;
+	unsigned int        waiting_reqs;
+	struct request_queue *plug;
+
+	/* statistics */
+	unsigned long       st_print;
+	int                 st_rd_req;
+	int                 st_wr_req;
+	int                 st_oo_req;
+	int                 st_br_req;
+	int                 st_pk_req;
+	int                 st_rd_sect;
+	int                 st_wr_sect;
+
+	wait_queue_head_t waiting_to_free;
+
+	grant_handle_t shmem_handle;
+	grant_ref_t    shmem_ref;
+} blkif_t;
+
+struct backend_info
+{
+	struct xenbus_device *dev;
+	blkif_t *blkif;
+	struct xenbus_watch backend_watch;
+	struct xenbus_watch backend_cdrom_watch;
+	unsigned major;
+	unsigned minor;
+	char *mode;
+};
+
+blkif_t *blkif_alloc(domid_t domid);
+void blkif_disconnect(blkif_t *blkif);
+void blkif_free(blkif_t *blkif);
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+
+#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define blkif_put(_b)					\
+	do {						\
+		if (atomic_dec_and_test(&(_b)->refcnt))	\
+			wake_up(&(_b)->waiting_to_free);\
+	} while (0)
+
+/* Create a vbd. */
+int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, unsigned major,
+	       unsigned minor, int readonly, int cdrom);
+void vbd_free(struct vbd *vbd);
+
+unsigned long long vbd_size(struct vbd *vbd);
+unsigned int vbd_info(struct vbd *vbd);
+unsigned long vbd_secsize(struct vbd *vbd);
+
+struct phys_req {
+	unsigned short       dev;
+	unsigned short       nr_sects;
+	struct block_device *bdev;
+	blkif_sector_t       sector_number;
+};
+
+int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
+
+void blkif_interface_init(void);
+
+void blkif_xenbus_init(void);
+
+irqreturn_t blkif_be_int(int irq, void *dev_id);
+int blkif_schedule(void *arg);
+
+int blkback_barrier(struct xenbus_transaction xbt,
+		    struct backend_info *be, int state);
+
+/* cdrom media change */
+void cdrom_add_media_watch(struct backend_info *be);
+
+#endif /* __BLKIF__BACKEND__COMMON_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/blkback/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
+obj-$(CONFIG_XEN_BLKBACK_PAGEMAP) += blkback-pagemap.o
+
+blkbk-y	:= blkback.o xenbus.o interface.o vbd.o cdrom.o
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/cdrom.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/cdrom.c
@@ -0,0 +1,162 @@
+/******************************************************************************
+ * blkback/cdrom.c
+ *
+ * Routines for managing cdrom watch and media-present attribute of a
+ * cdrom type virtual block device (VBD).
+ *
+ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
+ * Copyright (c) 2007       Pat Campbell
+ *
+ * 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 "common.h"
+
+#undef DPRINTK
+#define DPRINTK(_f, _a...)			\
+	printk("(%s() file=%s, line=%d) " _f "\n",	\
+		 __PRETTY_FUNCTION__, __FILE__ , __LINE__ , ##_a )
+
+
+#define MEDIA_PRESENT "media-present"
+
+static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int);
+
+/**
+ * Writes media-present=1 attribute for the given vbd device if not
+ * already there
+ */
+static int cdrom_xenstore_write_media_present(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	struct xenbus_transaction xbt;
+	int err;
+	int media_present;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
+			   &media_present);
+	if (0 < err) {
+		DPRINTK("already written err%d", err);
+		return(0);
+	}
+	media_present = 1;
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		return(-1);
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present );
+	if (err) {
+		xenbus_dev_fatal(dev, err, "writing %s/%s",
+			 dev->nodename, MEDIA_PRESENT);
+		goto abort;
+	}
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err)
+		xenbus_dev_fatal(dev, err, "ending transaction");
+	return 0;
+ abort:
+	xenbus_transaction_end(xbt, 1);
+	return -1;
+}
+
+/**
+ *
+ */
+static int cdrom_is_type(struct backend_info *be)
+{
+	DPRINTK("type:%x", be->blkif->vbd.type );
+	return (be->blkif->vbd.type & VDISK_CDROM)
+	       && (be->blkif->vbd.type & GENHD_FL_REMOVABLE);
+}
+
+/**
+ *
+ */
+void cdrom_add_media_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	DPRINTK("nodename:%s", dev->nodename);
+	if (cdrom_is_type(be)) {
+		DPRINTK("is a cdrom");
+		if ( cdrom_xenstore_write_media_present(be) == 0 ) {
+			DPRINTK( "xenstore wrote OK");
+			err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT,
+						 &be->backend_cdrom_watch,
+						 cdrom_media_changed);
+			if (err)
+				DPRINTK( "media_present watch add failed" );
+		}
+	}
+}
+
+/**
+ * Callback received when the "media_present" xenstore node is changed
+ */
+static void cdrom_media_changed(struct xenbus_watch *watch,
+				const char **vec, unsigned int len)
+{
+	int err;
+	unsigned media_present;
+	struct backend_info *be
+		= container_of(watch, struct backend_info, backend_cdrom_watch);
+	struct xenbus_device *dev = be->dev;
+
+	if (!cdrom_is_type(be)) {
+		DPRINTK("callback not for a cdrom" );
+		return;
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
+			   &media_present);
+	if (err == 0 || err == -ENOENT) {
+		DPRINTK("xenbus_read of cdrom media_present node error:%d",err);
+		return;
+	}
+
+	if (media_present == 0)
+		vbd_free(&be->blkif->vbd);
+	else {
+		char *p = strrchr(dev->otherend, '/') + 1;
+		long handle = simple_strtoul(p, NULL, 0);
+
+		if (!be->blkif->vbd.bdev) {
+			err = vbd_create(be->blkif, handle, be->major, be->minor,
+					 !strchr(be->mode, 'w'), 1);
+			if (err) {
+				be->major = be->minor = 0;
+				xenbus_dev_fatal(dev, err, "creating vbd structure");
+				return;
+			}
+		}
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/blkback-pagemap.h
+++ linux-ec2-2.6.32/drivers/xen/blkback/blkback-pagemap.h
@@ -0,0 +1,37 @@
+#ifndef _BLKBACK_PAGEMAP_H_
+#define _BLKBACK_PAGEMAP_H_
+
+#include <linux/mm.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/grant_table.h>
+
+typedef unsigned int busid_t;
+
+struct blkback_pagemap {
+	domid_t          domid;
+	busid_t          busid;
+	grant_ref_t      gref;
+};
+
+#if defined(CONFIG_XEN_BLKBACK_PAGEMAP) || defined(CONFIG_XEN_BLKBACK_PAGEMAP_MODULE)
+
+int blkback_pagemap_init(int);
+void blkback_pagemap_set(int, struct page *, domid_t, busid_t, grant_ref_t);
+void blkback_pagemap_clear(struct page *);
+struct blkback_pagemap blkback_pagemap_read(struct page *);
+
+#else /* CONFIG_XEN_BLKBACK_PAGEMAP */
+
+static inline int blkback_pagemap_init(int pages) { return 0; }
+static inline void blkback_pagemap_set(int idx, struct page *page, domid_t dom,
+				       busid_t bus, grant_ref_t gnt) {}
+static inline void blkback_pagemap_clear(struct page *page) {}
+static inline struct blkback_pagemap blkback_pagemap_read(struct page *page)
+{
+	BUG();
+	return (struct blkback_pagemap){-1, -1, -1};
+}
+
+#endif /* CONFIG_XEN_BLKBACK_PAGEMAP */
+
+#endif
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/xenbus.c
@@ -0,0 +1,549 @@
+/*  Xenbus code for blkif backend
+    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+    Copyright (C) 2005 XenSource Ltd
+
+    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 <stdarg.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include "common.h"
+#include "../core/domctl.h"
+
+#undef DPRINTK
+#define DPRINTK(fmt, args...)				\
+	pr_debug("blkback/xenbus (%s:%d) " fmt ".\n",	\
+		 __FUNCTION__, __LINE__, ##args)
+
+static void connect(struct backend_info *);
+static int connect_ring(struct backend_info *);
+static void backend_changed(struct xenbus_watch *, const char **,
+			    unsigned int);
+
+static int blkback_name(blkif_t *blkif, char *buf)
+{
+	char *devpath, *devname;
+	struct xenbus_device *dev = blkif->be->dev;
+
+	devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
+	if (IS_ERR(devpath)) 
+		return PTR_ERR(devpath);
+	
+	if ((devname = strstr(devpath, "/dev/")) != NULL)
+		devname += strlen("/dev/");
+	else
+		devname  = devpath;
+
+	snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname);
+	kfree(devpath);
+	
+	return 0;
+}
+
+static void update_blkif_status(blkif_t *blkif)
+{ 
+	int err;
+	char name[TASK_COMM_LEN];
+
+	/* Not ready to connect? */
+	if (!blkif->irq || !blkif->vbd.bdev)
+		return;
+
+	/* Already connected? */
+	if (blkif->be->dev->state == XenbusStateConnected)
+		return;
+
+	/* Attempt to connect: exit if we fail to. */
+	connect(blkif->be);
+	if (blkif->be->dev->state != XenbusStateConnected)
+		return;
+
+	err = blkback_name(blkif, name);
+	if (err) {
+		xenbus_dev_error(blkif->be->dev, err, "get blkback dev name");
+		return;
+	}
+
+	blkif->xenblkd = kthread_run(blkif_schedule, blkif, name);
+	if (IS_ERR(blkif->xenblkd)) {
+		err = PTR_ERR(blkif->xenblkd);
+		blkif->xenblkd = NULL;
+		xenbus_dev_error(blkif->be->dev, err, "start xenblkd");
+	}
+}
+
+
+/****************************************************************
+ *  sysfs interface for VBD I/O requests
+ */
+
+#define VBD_SHOW(name, format, args...)					\
+	static ssize_t show_##name(struct device *_dev,			\
+				   struct device_attribute *attr,	\
+				   char *buf)				\
+	{								\
+		struct xenbus_device *dev = to_xenbus_device(_dev);	\
+		struct backend_info *be = dev_get_drvdata(&dev->dev);	\
+									\
+		return sprintf(buf, format, ##args);			\
+	}								\
+	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
+VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
+VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
+VBD_SHOW(br_req,  "%d\n", be->blkif->st_br_req);
+VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
+VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
+
+static struct attribute *vbdstat_attrs[] = {
+	&dev_attr_oo_req.attr,
+	&dev_attr_rd_req.attr,
+	&dev_attr_wr_req.attr,
+	&dev_attr_br_req.attr,
+	&dev_attr_rd_sect.attr,
+	&dev_attr_wr_sect.attr,
+	NULL
+};
+
+static struct attribute_group vbdstat_group = {
+	.name = "statistics",
+	.attrs = vbdstat_attrs,
+};
+
+VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
+VBD_SHOW(mode, "%s\n", be->mode);
+
+int xenvbd_sysfs_addif(struct xenbus_device *dev)
+{
+	int error;
+	
+	error = device_create_file(&dev->dev, &dev_attr_physical_device);
+ 	if (error)
+		goto fail1;
+
+	error = device_create_file(&dev->dev, &dev_attr_mode);
+	if (error)
+		goto fail2;
+
+	error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group);
+	if (error)
+		goto fail3;
+
+	return 0;
+
+fail3:	sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
+fail2:	device_remove_file(&dev->dev, &dev_attr_mode);
+fail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);
+	return error;
+}
+
+void xenvbd_sysfs_delif(struct xenbus_device *dev)
+{
+	sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
+	device_remove_file(&dev->dev, &dev_attr_mode);
+	device_remove_file(&dev->dev, &dev_attr_physical_device);
+}
+
+static int blkback_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	DPRINTK("");
+
+	if (be->major || be->minor)
+		xenvbd_sysfs_delif(dev);
+
+	if (be->backend_watch.node) {
+		unregister_xenbus_watch(&be->backend_watch);
+		kfree(be->backend_watch.node);
+		be->backend_watch.node = NULL;
+	}
+
+	if (be->backend_cdrom_watch.node) {
+		unregister_xenbus_watch(&be->backend_cdrom_watch);
+		kfree(be->backend_cdrom_watch.node);
+		be->backend_cdrom_watch.node = NULL;
+	}
+
+	if (be->blkif) {
+		blkif_disconnect(be->blkif);
+		vbd_free(&be->blkif->vbd);
+		blkif_free(be->blkif);
+		be->blkif = NULL;
+	}
+
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+int blkback_barrier(struct xenbus_transaction xbt,
+		    struct backend_info *be, int state)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
+			    "%d", state);
+	if (err)
+		xenbus_dev_fatal(dev, err, "writing feature-barrier");
+
+	return err;
+}
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures, and watch the store waiting for the hotplug scripts to tell us
+ * the device's physical major and minor numbers.  Switch to InitWait.
+ */
+static int blkback_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	int err;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+
+	be->blkif = blkif_alloc(dev->otherend_id);
+	if (IS_ERR(be->blkif)) {
+		err = PTR_ERR(be->blkif);
+		be->blkif = NULL;
+		xenbus_dev_fatal(dev, err, "creating block interface");
+		goto fail;
+	}
+
+	/* setup back pointer */
+	be->blkif->be = be;
+
+	err = xenbus_watch_path2(dev, dev->nodename, "physical-device",
+				 &be->backend_watch, backend_changed);
+	if (err)
+		goto fail;
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	DPRINTK("failed");
+	blkback_remove(dev);
+	return err;
+}
+
+
+/**
+ * Callback received when the hotplug scripts have placed the physical-device
+ * node.  Read it and the mode node, and create a vbd.  If the frontend is
+ * ready, connect.
+ */
+static void backend_changed(struct xenbus_watch *watch,
+			    const char **vec, unsigned int len)
+{
+	int err;
+	unsigned major;
+	unsigned minor;
+	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("");
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x",
+			   &major, &minor);
+	if (XENBUS_EXIST_ERR(err)) {
+		/* Since this watch will fire once immediately after it is
+		   registered, we expect this.  Ignore it, and wait for the
+		   hotplug scripts. */
+		return;
+	}
+	if (err != 2) {
+		xenbus_dev_fatal(dev, err, "reading physical-device");
+		return;
+	}
+
+	if ((be->major || be->minor) &&
+	    ((be->major != major) || (be->minor != minor))) {
+		printk(KERN_WARNING
+		       "blkback: changing physical device (from %x:%x to "
+		       "%x:%x) not supported.\n", be->major, be->minor,
+		       major, minor);
+		return;
+	}
+
+	be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
+	if (IS_ERR(be->mode)) {
+		err = PTR_ERR(be->mode);
+		be->mode = NULL;
+		xenbus_dev_fatal(dev, err, "reading mode");
+		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. */
+
+		char *p = strrchr(dev->otherend, '/') + 1;
+		long handle = simple_strtoul(p, NULL, 0);
+
+		be->major = major;
+		be->minor = minor;
+
+		err = vbd_create(be->blkif, handle, major, minor,
+				 (NULL == strchr(be->mode, 'w')), cdrom);
+		if (err) {
+			be->major = be->minor = 0;
+			xenbus_dev_fatal(dev, err, "creating vbd structure");
+			return;
+		}
+
+		err = xenvbd_sysfs_addif(dev);
+		if (err) {
+			vbd_free(&be->blkif->vbd);
+			be->major = be->minor = 0;
+			xenbus_dev_fatal(dev, err, "creating sysfs entries");
+			return;
+		}
+
+		/* We're potentially connected now */
+		update_blkif_status(be->blkif);
+
+		/* Add watch for cdrom media status if necessay */
+		cdrom_add_media_watch(be);
+	}
+}
+
+
+/**
+ * Callback received when the frontend's state changes.
+ */
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+	int err;
+
+	DPRINTK("%s", xenbus_strstate(frontend_state));
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
+			       __FUNCTION__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateInitialised:
+	case XenbusStateConnected:
+		/* Ensure we connect even when two watches fire in 
+		   close successsion and we miss the intermediate value 
+		   of frontend_state. */
+		if (dev->state == XenbusStateConnected)
+			break;
+
+		err = connect_ring(be);
+		if (err)
+			break;
+		update_blkif_status(be->blkif);
+		break;
+
+	case XenbusStateClosing:
+		blkif_disconnect(be->blkif);
+		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;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+/* ** Connection ** */
+
+
+/**
+ * Write the physical details regarding the block device to the store, and
+ * switch to Connected state.
+ */
+static void connect(struct backend_info *be)
+{
+	struct xenbus_transaction xbt;
+	int err;
+	struct xenbus_device *dev = be->dev;
+
+	DPRINTK("%s", dev->otherend);
+
+	/* Supply the information about the device the frontend needs */
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		return;
+	}
+
+	err = blkback_barrier(xbt, be, 1);
+	if (err)
+		goto abort;
+
+	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
+			    vbd_size(&be->blkif->vbd));
+	if (err) {
+		xenbus_dev_fatal(dev, err, "writing %s/sectors",
+				 dev->nodename);
+		goto abort;
+	}
+
+	/* FIXME: use a typename instead */
+	err = xenbus_printf(xbt, dev->nodename, "info", "%u",
+			    vbd_info(&be->blkif->vbd));
+	if (err) {
+		xenbus_dev_fatal(dev, err, "writing %s/info",
+				 dev->nodename);
+		goto abort;
+	}
+	err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
+			    vbd_secsize(&be->blkif->vbd));
+	if (err) {
+		xenbus_dev_fatal(dev, err, "writing %s/sector-size",
+				 dev->nodename);
+		goto abort;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err)
+		xenbus_dev_fatal(dev, err, "ending transaction");
+
+	err = xenbus_switch_state(dev, XenbusStateConnected);
+	if (err)
+		xenbus_dev_fatal(dev, err, "switching to Connected state",
+				 dev->nodename);
+
+	return;
+ abort:
+	xenbus_transaction_end(xbt, 1);
+}
+
+
+static int connect_ring(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	unsigned long ring_ref;
+	unsigned int evtchn;
+	char protocol[64] = "";
+	int err;
+
+	DPRINTK("%s", dev->otherend);
+
+	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-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+			    "%63s", protocol, NULL);
+	if (err) {
+		strcpy(protocol, "unspecified");
+		be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
+	}
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */
+	else if (0 == strcmp(protocol, "1"))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+	else if (0 == strcmp(protocol, "2"))
+		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
+#endif
+	else {
+		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+		return -1;
+	}
+	printk(KERN_INFO
+	       "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
+	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
+
+	/* Map the shared frame, irq etc. */
+	err = blkif_map(be->blkif, ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
+				 ring_ref, evtchn);
+		return err;
+	}
+
+	return 0;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id blkback_ids[] = {
+	{ "vbd" },
+	{ "" }
+};
+
+
+static struct xenbus_driver blkback = {
+	.name = "vbd",
+	.ids = blkback_ids,
+	.probe = blkback_probe,
+	.remove = blkback_remove,
+	.otherend_changed = frontend_changed
+};
+
+
+void blkif_xenbus_init(void)
+{
+	if (xenbus_register_backend(&blkback))
+		BUG();
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/interface.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/interface.c
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/interface.c
+ * 
+ * Block-device interface management.
+ * 
+ * Copyright (c) 2004, Keir Fraser
+ * 
+ * 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 "common.h"
+#include <xen/evtchn.h>
+#include <linux/kthread.h>
+
+static struct kmem_cache *blkif_cachep;
+
+blkif_t *blkif_alloc(domid_t domid)
+{
+	blkif_t *blkif;
+
+	blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+	if (!blkif)
+		return ERR_PTR(-ENOMEM);
+
+	memset(blkif, 0, sizeof(*blkif));
+	blkif->domid = domid;
+	spin_lock_init(&blkif->blk_ring_lock);
+	atomic_set(&blkif->refcnt, 1);
+	init_waitqueue_head(&blkif->wq);
+	blkif->st_print = jiffies;
+	init_waitqueue_head(&blkif->waiting_to_free);
+
+	return blkif;
+}
+
+static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
+{
+	struct gnttab_map_grant_ref op;
+
+	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
+			  GNTMAP_host_map, shared_page, blkif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		DPRINTK(" Grant table operation failure !\n");
+		return op.status;
+	}
+
+	blkif->shmem_ref = shared_page;
+	blkif->shmem_handle = op.handle;
+
+	return 0;
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
+			    GNTMAP_host_map, blkif->shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+}
+
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
+{
+	int err;
+
+	/* Already connected through? */
+	if (blkif->irq)
+		return 0;
+
+	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+		return -ENOMEM;
+
+	err = map_frontend_page(blkif, shared_page);
+	if (err) {
+		free_vm_area(blkif->blk_ring_area);
+		return err;
+	}
+
+	switch (blkif->blk_protocol) {
+	case BLKIF_PROTOCOL_NATIVE:
+	{
+		blkif_sring_t *sring;
+		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
+		break;
+	}
+	case BLKIF_PROTOCOL_X86_32:
+	{
+		blkif_x86_32_sring_t *sring_x86_32;
+		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
+		break;
+	}
+	case BLKIF_PROTOCOL_X86_64:
+	{
+		blkif_x86_64_sring_t *sring_x86_64;
+		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
+		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
+		break;
+	}
+	default:
+		BUG();
+	}
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif);
+	if (err < 0)
+	{
+		unmap_frontend_page(blkif);
+		free_vm_area(blkif->blk_ring_area);
+		blkif->blk_rings.common.sring = NULL;
+		return err;
+	}
+	blkif->irq = err;
+
+	return 0;
+}
+
+void blkif_disconnect(blkif_t *blkif)
+{
+	if (blkif->xenblkd) {
+		kthread_stop(blkif->xenblkd);
+		blkif->xenblkd = NULL;
+	}
+
+	atomic_dec(&blkif->refcnt);
+	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
+	atomic_inc(&blkif->refcnt);
+
+	if (blkif->irq) {
+		unbind_from_irqhandler(blkif->irq, blkif);
+		blkif->irq = 0;
+	}
+
+	if (blkif->blk_rings.common.sring) {
+		unmap_frontend_page(blkif);
+		free_vm_area(blkif->blk_ring_area);
+		blkif->blk_rings.common.sring = NULL;
+	}
+}
+
+void blkif_free(blkif_t *blkif)
+{
+	if (!atomic_dec_and_test(&blkif->refcnt))
+		BUG();
+	kmem_cache_free(blkif_cachep, blkif);
+}
+
+void __init blkif_interface_init(void)
+{
+	blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
+					 0, 0, NULL);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/blkback/blkback.c
+++ linux-ec2-2.6.32/drivers/xen/blkback/blkback.c
@@ -0,0 +1,673 @@
+/******************************************************************************
+ * arch/xen/drivers/blkif/backend/main.c
+ * 
+ * Back-end of the driver for virtual block devices. This portion of the
+ * driver exports a 'unified' block-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A 
+ * reference front-end implementation can be found in:
+ *  arch/xen/drivers/blkif/frontend
+ * 
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Copyright (c) 2005, Christopher Clark
+ * 
+ * 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/freezer.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <xen/balloon.h>
+#include <asm/hypervisor.h>
+#include "common.h"
+
+/*
+ * These are rather arbitrary. They are fairly large because adjacent requests
+ * pulled from a communication ring are quite likely to end up being part of
+ * the same scatter/gather request at the disc.
+ * 
+ * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW **
+ * 
+ * This will increase the chances of being able to write whole tracks.
+ * 64 should be enough to keep us competitive with Linux.
+ */
+static int blkif_reqs = 64;
+module_param_named(reqs, blkif_reqs, int, 0);
+MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate");
+
+/* Run-time switchable: /sys/module/blkback/parameters/ */
+static unsigned int log_stats = 0;
+static unsigned int debug_lvl = 0;
+module_param(log_stats, int, 0644);
+module_param(debug_lvl, int, 0644);
+
+/*
+ * Each outstanding request that we've passed to the lower device layers has a 
+ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
+ * the pendcnt towards zero. When it hits zero, the specified domain has a 
+ * response queued for it, with the saved 'id' passed back.
+ */
+typedef struct {
+	blkif_t       *blkif;
+	u64            id;
+	int            nr_pages;
+	atomic_t       pendcnt;
+	unsigned short operation;
+	int            status;
+	struct list_head free_list;
+} pending_req_t;
+
+static pending_req_t *pending_reqs;
+static struct list_head pending_free;
+static DEFINE_SPINLOCK(pending_free_lock);
+static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
+
+#define BLKBACK_INVALID_HANDLE (~0)
+
+static struct page **pending_pages;
+static grant_handle_t *pending_grant_handles;
+
+static inline int vaddr_pagenr(pending_req_t *req, int seg)
+{
+	return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
+}
+
+static inline 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)])
+
+
+static int do_block_io_op(blkif_t *blkif);
+static void dispatch_rw_block_io(blkif_t *blkif,
+				 blkif_request_t *req,
+				 pending_req_t *pending_req);
+static void make_response(blkif_t *blkif, u64 id,
+			  unsigned short op, int st);
+
+/******************************************************************
+ * misc small helpers
+ */
+static pending_req_t* alloc_req(void)
+{
+	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 unplug_queue(blkif_t *blkif)
+{
+	if (blkif->plug == NULL)
+		return;
+	if (blkif->plug->unplug_fn)
+		blkif->plug->unplug_fn(blkif->plug);
+	kobject_put(&blkif->plug->kobj);
+	blkif->plug = NULL;
+}
+
+static void plug_queue(blkif_t *blkif, struct block_device *bdev)
+{
+	struct request_queue *q = bdev_get_queue(bdev);
+
+	if (q == blkif->plug)
+		return;
+	unplug_queue(blkif);
+	WARN_ON(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags));
+	kobject_get(&q->kobj);
+	blkif->plug = q;
+}
+
+static void fast_flush_area(pending_req_t *req)
+{
+	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	unsigned int i, invcount = 0;
+	grant_handle_t handle;
+	int ret;
+
+	for (i = 0; i < req->nr_pages; i++) {
+		handle = pending_handle(req, i);
+		if (handle == BLKBACK_INVALID_HANDLE)
+			continue;
+		blkback_pagemap_clear(virt_to_page(vaddr(req, i)));
+		gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
+				    GNTMAP_host_map, handle);
+		pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
+		invcount++;
+	}
+
+	ret = HYPERVISOR_grant_table_op(
+		GNTTABOP_unmap_grant_ref, unmap, invcount);
+	BUG_ON(ret);
+}
+
+/******************************************************************
+ * SCHEDULER FUNCTIONS
+ */
+
+static void print_stats(blkif_t *blkif)
+{
+	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d  |  br %4d |  pk %4d\n",
+	       current->comm, blkif->st_oo_req,
+	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req,
+	       blkif->st_pk_req);
+	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
+	blkif->st_rd_req = 0;
+	blkif->st_wr_req = 0;
+	blkif->st_oo_req = 0;
+	blkif->st_pk_req = 0;
+}
+
+int blkif_schedule(void *arg)
+{
+	blkif_t *blkif = arg;
+
+	blkif_get(blkif);
+
+	if (debug_lvl)
+		printk(KERN_DEBUG "%s: started\n", current->comm);
+
+	while (!kthread_should_stop()) {
+		if (try_to_freeze())
+			continue;
+
+		wait_event_interruptible(
+			blkif->wq,
+			blkif->waiting_reqs || kthread_should_stop());
+		wait_event_interruptible(
+			pending_free_wq,
+			!list_empty(&pending_free) || kthread_should_stop());
+
+		blkif->waiting_reqs = 0;
+		smp_mb(); /* clear flag *before* checking for work */
+
+		if (do_block_io_op(blkif))
+			blkif->waiting_reqs = 1;
+		unplug_queue(blkif);
+
+		if (log_stats && time_after(jiffies, blkif->st_print))
+			print_stats(blkif);
+	}
+
+	if (log_stats)
+		print_stats(blkif);
+	if (debug_lvl)
+		printk(KERN_DEBUG "%s: exiting\n", current->comm);
+
+	blkif->xenblkd = NULL;
+	blkif_put(blkif);
+
+	return 0;
+}
+
+/******************************************************************
+ * COMPLETION CALLBACK -- Called as bh->b_end_io()
+ */
+
+static void __end_block_io_op(pending_req_t *pending_req, int error)
+{
+	/* An error fails the entire request. */
+	if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
+	    (error == -EOPNOTSUPP)) {
+		DPRINTK("blkback: write barrier op failed, not supported\n");
+		blkback_barrier(XBT_NIL, pending_req->blkif->be, 0);
+		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
+	} else if (error) {
+		DPRINTK("Buffer not up-to-date at end of operation, "
+			"error=%d\n", error);
+		pending_req->status = BLKIF_RSP_ERROR;
+	}
+
+	if (atomic_dec_and_test(&pending_req->pendcnt)) {
+		fast_flush_area(pending_req);
+		make_response(pending_req->blkif, pending_req->id,
+			      pending_req->operation, pending_req->status);
+		blkif_put(pending_req->blkif);
+		free_req(pending_req);
+	}
+}
+
+static void end_block_io_op(struct bio *bio, int error)
+{
+	__end_block_io_op(bio->bi_private, error);
+	bio_put(bio);
+}
+
+
+/******************************************************************************
+ * NOTIFICATION FROM GUEST OS.
+ */
+
+static void blkif_notify_work(blkif_t *blkif)
+{
+	blkif->waiting_reqs = 1;
+	wake_up(&blkif->wq);
+}
+
+irqreturn_t blkif_be_int(int irq, void *dev_id)
+{
+	blkif_notify_work(dev_id);
+	return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************
+ * DOWNWARD CALLS -- These interface with the block-device layer proper.
+ */
+
+static int do_block_io_op(blkif_t *blkif)
+{
+	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
+	blkif_request_t req;
+	pending_req_t *pending_req;
+	RING_IDX rc, rp;
+	int more_to_do = 0;
+
+	rc = blk_rings->common.req_cons;
+	rp = blk_rings->common.sring->req_prod;
+	rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+	while (rc != rp) {
+
+		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
+			break;
+
+		if (kthread_should_stop()) {
+			more_to_do = 1;
+			break;
+		}
+
+		pending_req = alloc_req();
+		if (NULL == pending_req) {
+			blkif->st_oo_req++;
+			more_to_do = 1;
+			break;
+		}
+
+		switch (blkif->blk_protocol) {
+		case BLKIF_PROTOCOL_NATIVE:
+			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
+			break;
+		case BLKIF_PROTOCOL_X86_32:
+			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
+			break;
+		case BLKIF_PROTOCOL_X86_64:
+			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
+			break;
+		default:
+			BUG();
+		}
+		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++;
+			dispatch_rw_block_io(blkif, &req, pending_req);
+			break;
+		case BLKIF_OP_WRITE_BARRIER:
+			blkif->st_br_req++;
+			/* fall through */
+		case BLKIF_OP_WRITE:
+			blkif->st_wr_req++;
+			dispatch_rw_block_io(blkif, &req, pending_req);
+			break;
+		case BLKIF_OP_PACKET:
+			DPRINTK("error: block operation BLKIF_OP_PACKET not implemented\n");
+			blkif->st_pk_req++;
+			make_response(blkif, req.id, req.operation,
+				      BLKIF_RSP_ERROR);
+			free_req(pending_req);
+			break;
+		default:
+			/* A good sign something is wrong: sleep for a while to
+			 * avoid excessive CPU consumption by a bad guest. */
+			msleep(1);
+			DPRINTK("error: unknown block io operation [%d]\n",
+				req.operation);
+			make_response(blkif, req.id, req.operation,
+				      BLKIF_RSP_ERROR);
+			free_req(pending_req);
+			break;
+		}
+
+		/* Yield point for this unbounded loop. */
+		cond_resched();
+	}
+
+	return more_to_do;
+}
+
+static void dispatch_rw_block_io(blkif_t *blkif,
+				 blkif_request_t *req,
+				 pending_req_t *pending_req)
+{
+	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	struct phys_req preq;
+	struct { 
+		unsigned long buf; unsigned int nsec;
+	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+	unsigned int nseg;
+	struct bio *bio = NULL;
+	int ret, i;
+	int operation;
+
+	switch (req->operation) {
+	case BLKIF_OP_READ:
+		operation = READ;
+		break;
+	case BLKIF_OP_WRITE:
+		operation = WRITE;
+		break;
+	case BLKIF_OP_WRITE_BARRIER:
+		operation = WRITE_BARRIER;
+		break;
+	default:
+		operation = 0; /* make gcc happy */
+		BUG();
+	}
+
+	/* Check that number of segments is sane. */
+	nseg = req->nr_segments;
+	if (unlikely(nseg == 0 && operation != WRITE_BARRIER) || 
+	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
+		DPRINTK("Bad number of segments in request (%d)\n", nseg);
+		goto fail_response;
+	}
+
+	preq.dev           = req->handle;
+	preq.sector_number = req->sector_number;
+	preq.nr_sects      = 0;
+
+	pending_req->blkif     = blkif;
+	pending_req->id        = req->id;
+	pending_req->operation = req->operation;
+	pending_req->status    = BLKIF_RSP_OKAY;
+	pending_req->nr_pages  = nseg;
+
+	for (i = 0; i < nseg; i++) {
+		uint32_t flags;
+
+		seg[i].nsec = req->seg[i].last_sect -
+			req->seg[i].first_sect + 1;
+
+		if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
+		    (req->seg[i].last_sect < req->seg[i].first_sect))
+			goto fail_response;
+		preq.nr_sects += seg[i].nsec;
+
+		flags = GNTMAP_host_map;
+		if (operation != READ)
+			flags |= GNTMAP_readonly;
+		gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
+				  req->seg[i].gref, blkif->domid);
+	}
+
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
+	BUG_ON(ret);
+
+	for (i = 0; i < nseg; i++) {
+		if (unlikely(map[i].status != 0)) {
+			DPRINTK("invalid buffer -- could not remap it\n");
+			map[i].handle = BLKBACK_INVALID_HANDLE;
+			ret |= 1;
+		} else {
+			blkback_pagemap_set(vaddr_pagenr(pending_req, i),
+					    virt_to_page(vaddr(pending_req, i)),
+					    blkif->domid, req->handle,
+					    req->seg[i].gref);
+		}
+
+		pending_handle(pending_req, i) = map[i].handle;
+
+		if (ret)
+			continue;
+
+		set_phys_to_machine(__pa(vaddr(
+			pending_req, i)) >> PAGE_SHIFT,
+			FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
+		seg[i].buf  = map[i].dev_bus_addr | 
+			(req->seg[i].first_sect << 9);
+	}
+
+	if (ret)
+		goto fail_flush;
+
+	if (vbd_translate(&preq, blkif, operation) != 0) {
+		DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", 
+			operation == READ ? "read" : "write",
+			preq.sector_number,
+			preq.sector_number + preq.nr_sects, preq.dev);
+		goto fail_flush;
+	}
+
+	plug_queue(blkif, preq.bdev);
+	atomic_set(&pending_req->pendcnt, 1);
+	blkif_get(blkif);
+
+	for (i = 0; i < nseg; i++) {
+		if (((int)preq.sector_number|(int)seg[i].nsec) &
+		    ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) {
+			DPRINTK("Misaligned I/O request from domain %d",
+				blkif->domid);
+			goto fail_put_bio;
+		}
+
+		while ((bio == NULL) ||
+		       (bio_add_page(bio,
+				     virt_to_page(vaddr(pending_req, i)),
+				     seg[i].nsec << 9,
+				     seg[i].buf & ~PAGE_MASK) == 0)) {
+			if (bio) {
+				atomic_inc(&pending_req->pendcnt);
+				submit_bio(operation, bio);
+			}
+
+			bio = bio_alloc(GFP_KERNEL, nseg-i);
+			if (unlikely(bio == NULL))
+				goto fail_put_bio;
+
+			bio->bi_bdev    = preq.bdev;
+			bio->bi_private = pending_req;
+			bio->bi_end_io  = end_block_io_op;
+			bio->bi_sector  = preq.sector_number;
+		}
+
+		preq.sector_number += seg[i].nsec;
+	}
+
+	if (!bio) {
+		BUG_ON(operation != WRITE_BARRIER);
+		bio = bio_alloc(GFP_KERNEL, 0);
+		if (unlikely(bio == NULL))
+			goto fail_put_bio;
+
+		bio->bi_bdev    = preq.bdev;
+		bio->bi_private = pending_req;
+		bio->bi_end_io  = end_block_io_op;
+		bio->bi_sector  = -1;
+	}
+
+	submit_bio(operation, bio);
+
+	if (operation == READ)
+		blkif->st_rd_sect += preq.nr_sects;
+	else if (operation == WRITE || operation == WRITE_BARRIER)
+		blkif->st_wr_sect += preq.nr_sects;
+
+	return;
+
+ fail_flush:
+	fast_flush_area(pending_req);
+ fail_response:
+	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+	free_req(pending_req);
+	msleep(1); /* back off a bit */
+	return;
+
+ fail_put_bio:
+	__end_block_io_op(pending_req, -EINVAL);
+	if (bio)
+		bio_put(bio);
+	unplug_queue(blkif);
+	msleep(1); /* back off a bit */
+	return;
+}
+
+
+
+/******************************************************************
+ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
+ */
+
+
+static void make_response(blkif_t *blkif, u64 id,
+			  unsigned short op, int st)
+{
+	blkif_response_t  resp;
+	unsigned long     flags;
+	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
+	int more_to_do = 0;
+	int notify;
+
+	resp.id        = id;
+	resp.operation = op;
+	resp.status    = st;
+
+	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+	/* Place on the response ring for the relevant domain. */
+	switch (blkif->blk_protocol) {
+	case BLKIF_PROTOCOL_NATIVE:
+		memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	case BLKIF_PROTOCOL_X86_32:
+		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	case BLKIF_PROTOCOL_X86_64:
+		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
+		       &resp, sizeof(resp));
+		break;
+	default:
+		BUG();
+	}
+	blk_rings->common.rsp_prod_pvt++;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
+	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
+		/*
+		 * Tail check for pending requests. Allows frontend to avoid
+		 * notifications if requests are already in flight (lower
+		 * overheads and promotes batching).
+		 */
+		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
+
+	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
+		more_to_do = 1;
+	}
+
+	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+	if (more_to_do)
+		blkif_notify_work(blkif);
+	if (notify)
+		notify_remote_via_irq(blkif->irq);
+}
+
+static int __init blkif_init(void)
+{
+	int i, mmap_pages;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
+
+	pending_reqs          = kmalloc(sizeof(pending_reqs[0]) *
+					blkif_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 (blkback_pagemap_init(mmap_pages))
+		goto out_of_memory;
+
+	if (!pending_reqs || !pending_grant_handles || !pending_pages)
+		goto out_of_memory;
+
+	for (i = 0; i < mmap_pages; i++)
+		pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
+
+	blkif_interface_init();
+
+	memset(pending_reqs, 0, sizeof(pending_reqs));
+	INIT_LIST_HEAD(&pending_free);
+
+	for (i = 0; i < blkif_reqs; i++)
+		list_add_tail(&pending_reqs[i].free_list, &pending_free);
+
+	blkif_xenbus_init();
+
+	return 0;
+
+ out_of_memory:
+	kfree(pending_reqs);
+	kfree(pending_grant_handles);
+	free_empty_pages_and_pagevec(pending_pages, mmap_pages);
+	printk("%s: out of memory\n", __FUNCTION__);
+	return -ENOMEM;
+}
+
+module_init(blkif_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/usbstub.c
+++ linux-ec2-2.6.32/drivers/xen/usbback/usbstub.c
@@ -0,0 +1,325 @@
+/*
+ * usbstub.c
+ *
+ * USB stub driver - grabbing and managing USB devices.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include "usbback.h"
+
+static LIST_HEAD(port_list);
+static DEFINE_SPINLOCK(port_list_lock);
+
+struct vusb_port_id *find_portid_by_busid(const char *busid)
+{
+	struct vusb_port_id *portid;
+	int found = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port_list_lock, flags);
+	list_for_each_entry(portid, &port_list, id_list) {
+		if (!(strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))) {
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&port_list_lock, flags);
+
+	if (found)
+		return portid;
+
+	return NULL;
+}
+
+struct vusb_port_id *find_portid(const domid_t domid,
+						const unsigned int handle,
+						const int portnum)
+{
+	struct vusb_port_id *portid;
+	int found = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port_list_lock, flags);
+	list_for_each_entry(portid, &port_list, id_list) {
+		if ((portid->domid == domid)
+				&& (portid->handle == handle)
+				&& (portid->portnum == portnum)) {
+				found = 1;
+				break;
+		}
+	}
+	spin_unlock_irqrestore(&port_list_lock, flags);
+
+	if (found)
+		return portid;
+
+	return NULL;
+}
+
+int portid_add(const char *busid,
+					const domid_t domid,
+					const unsigned int handle,
+					const int portnum)
+{
+	struct vusb_port_id *portid;
+	unsigned long flags;
+
+	portid = kzalloc(sizeof(*portid), GFP_KERNEL);
+	if (!portid)
+		return -ENOMEM;
+
+	portid->domid = domid;
+	portid->handle = handle;
+	portid->portnum = portnum;
+
+	strncpy(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE);
+
+	spin_lock_irqsave(&port_list_lock, flags);
+	list_add(&portid->id_list, &port_list);
+	spin_unlock_irqrestore(&port_list_lock, flags);
+
+	return 0;
+}
+
+int portid_remove(const domid_t domid,
+					const unsigned int handle,
+					const int portnum)
+{
+	struct vusb_port_id *portid, *tmp;
+	int err = -ENOENT;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port_list_lock, flags);
+	list_for_each_entry_safe(portid, tmp, &port_list, id_list) {
+		if (portid->domid == domid
+				&& portid->handle == handle
+				&& portid->portnum == portnum) {
+			list_del(&portid->id_list);
+			kfree(portid);
+
+			err = 0;
+		}
+	}
+	spin_unlock_irqrestore(&port_list_lock, flags);
+
+	return err;
+}
+
+static struct usbstub *usbstub_alloc(struct usb_device *udev,
+						struct vusb_port_id *portid)
+{
+	struct usbstub *stub;
+
+	stub = kzalloc(sizeof(*stub), GFP_KERNEL);
+	if (!stub) {
+		printk(KERN_ERR "no memory for alloc usbstub\n");
+		return NULL;
+	}
+	kref_init(&stub->kref);
+	stub->udev = usb_get_dev(udev);
+	stub->portid = portid;
+	spin_lock_init(&stub->submitting_lock);
+	INIT_LIST_HEAD(&stub->submitting_list);
+
+	return stub;
+}
+
+static void usbstub_release(struct kref *kref)
+{
+	struct usbstub *stub;
+
+	stub = container_of(kref, struct usbstub, kref);
+
+	usb_put_dev(stub->udev);
+	stub->udev = NULL;
+	stub->portid = NULL;
+	kfree(stub);
+}
+
+static inline void usbstub_get(struct usbstub *stub)
+{
+	kref_get(&stub->kref);
+}
+
+static inline void usbstub_put(struct usbstub *stub)
+{
+	kref_put(&stub->kref, usbstub_release);
+}
+
+static int usbstub_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	const char *busid = dev_name(intf->dev.parent);
+	struct vusb_port_id *portid = NULL;
+	struct usbstub *stub = NULL;
+	usbif_t *usbif = NULL;
+	int retval = -ENODEV;
+
+	/* hub currently not supported, so skip. */
+	if (udev->descriptor.bDeviceClass ==  USB_CLASS_HUB)
+		goto out;
+
+	portid = find_portid_by_busid(busid);
+	if (!portid)
+		goto out;
+
+	usbif = find_usbif(portid->domid, portid->handle);
+	if (!usbif)
+		goto out;
+
+	switch (udev->speed) {
+	case USB_SPEED_LOW:
+	case USB_SPEED_FULL:
+		break;
+	case USB_SPEED_HIGH:
+		if (usbif->usb_ver >= USB_VER_USB20)
+			break;
+		/* fall through */
+	default:
+		goto out;
+	}
+
+	stub = find_attached_device(usbif, portid->portnum);
+	if (!stub) {
+		/* new connection */
+		stub = usbstub_alloc(udev, portid);
+		if (!stub)
+			return -ENOMEM;
+		usbbk_attach_device(usbif, stub);
+		usbbk_hotplug_notify(usbif, portid->portnum, udev->speed);
+	} else {
+		/* maybe already called and connected by other intf */
+		if (strncmp(stub->portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))
+			goto out; /* invalid call */
+	}
+
+	usbstub_get(stub);
+	usb_set_intfdata(intf, stub);
+	retval = 0;
+
+out:
+	return retval;
+}
+
+static void usbstub_disconnect(struct usb_interface *intf)
+{
+	struct usbstub *stub
+		= (struct usbstub *) usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!stub)
+		return;
+
+	if (stub->usbif) {
+		usbbk_hotplug_notify(stub->usbif, stub->portid->portnum, 0);
+		usbbk_detach_device(stub->usbif, stub);
+	}
+	usbbk_unlink_urbs(stub);
+	usbstub_put(stub);
+}
+
+static ssize_t usbstub_show_portids(struct device_driver *driver,
+		char *buf)
+{
+	struct vusb_port_id *portid;
+	size_t count = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port_list_lock, flags);
+	list_for_each_entry(portid, &port_list, id_list) {
+		if (count >= PAGE_SIZE)
+			break;
+		count += scnprintf((char *)buf + count, PAGE_SIZE - count,
+				"%s:%d:%d:%d\n",
+				&portid->phys_bus[0],
+				portid->domid,
+				portid->handle,
+				portid->portnum);
+	}
+	spin_unlock_irqrestore(&port_list_lock, flags);
+
+	return count;
+}
+
+DRIVER_ATTR(port_ids, S_IRUSR, usbstub_show_portids, NULL);
+
+/* table of devices that matches any usbdevice */
+static const struct usb_device_id usbstub_table[] = {
+		{ .driver_info = 1 }, /* wildcard, see usb_match_id() */
+		{ } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, usbstub_table);
+
+static struct usb_driver usbback_usb_driver = {
+		.name = "usbback",
+		.probe = usbstub_probe,
+		.disconnect = usbstub_disconnect,
+		.id_table = usbstub_table,
+		.no_dynamic_id = 1,
+};
+
+int __init usbstub_init(void)
+{
+	int err;
+
+	err = usb_register(&usbback_usb_driver);
+	if (err < 0) {
+		printk(KERN_ERR "usbback: usb_register failed (error %d)\n", err);
+		goto out;
+	}
+
+	err = driver_create_file(&usbback_usb_driver.drvwrap.driver,
+				&driver_attr_port_ids);
+	if (err)
+		usb_deregister(&usbback_usb_driver);
+
+out:
+	return err;
+}
+
+void usbstub_exit(void)
+{
+	driver_remove_file(&usbback_usb_driver.drvwrap.driver,
+				&driver_attr_port_ids);
+	usb_deregister(&usbback_usb_driver);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/Makefile
+++ linux-ec2-2.6.32/drivers/xen/usbback/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_XEN_USB_BACKEND) := usbbk.o
+
+usbbk-y   := usbstub.o xenbus.o interface.o usbback.o
+
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/usbback/xenbus.c
@@ -0,0 +1,337 @@
+/*
+ * xenbus.c
+ *
+ * Xenbus interface for USB backend driver.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include "usbback.h"
+
+static int start_xenusbd(usbif_t *usbif)
+{
+	int err = 0;
+	char name[TASK_COMM_LEN];
+
+	snprintf(name, TASK_COMM_LEN, "usbback.%d.%d", usbif->domid,
+			usbif->handle);
+	usbif->xenusbd = kthread_run(usbbk_schedule, usbif, name);
+	if (IS_ERR(usbif->xenusbd)) {
+		err = PTR_ERR(usbif->xenusbd);
+		usbif->xenusbd = NULL;
+		xenbus_dev_error(usbif->xbdev, err, "start xenusbd");
+	}
+
+	return err;
+}
+
+static void backend_changed(struct xenbus_watch *watch,
+			const char **vec, unsigned int len)
+{
+	struct xenbus_transaction xbt;
+	int err;
+	int i;
+	char node[8];
+	char *busid;
+	struct vusb_port_id *portid = NULL;
+
+	usbif_t *usbif = container_of(watch, usbif_t, backend_watch);
+	struct xenbus_device *dev = usbif->xbdev;
+
+again:
+	err = xenbus_transaction_start(&xbt);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		return;
+	}
+
+	for (i = 1; i <= usbif->num_ports; i++) {
+		sprintf(node, "port/%d", i);
+		busid = xenbus_read(xbt, dev->nodename, node, NULL);
+		if (IS_ERR(busid)) {
+			err = PTR_ERR(busid);
+			xenbus_dev_fatal(dev, err, "reading port/%d", i);
+			goto abort;
+		}
+
+		/*
+		 * remove portid, if the port is not connected,
+		 */
+		if (strlen(busid) == 0) {
+			portid = find_portid(usbif->domid, usbif->handle, i);
+			if (portid) {
+				if (portid->is_connected)
+					xenbus_dev_fatal(dev, err,
+						"can't remove port/%d, unbind first", i);
+				else
+					portid_remove(usbif->domid, usbif->handle, i);
+			}
+			continue; /* never configured, ignore */
+		}
+
+		/*
+		 * add portid,
+		 * if the port is not configured and not used from other usbif.
+		 */
+		portid = find_portid(usbif->domid, usbif->handle, i);
+		if (portid) {
+			if ((strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE)))
+				xenbus_dev_fatal(dev, err,
+					"can't add port/%d, remove first", i);
+			else
+				continue; /* already configured, ignore */
+		} else {
+			if (find_portid_by_busid(busid))
+				xenbus_dev_fatal(dev, err,
+					"can't add port/%d, busid already used", i);
+			else
+				portid_add(busid, usbif->domid, usbif->handle, i);
+		}
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err)
+		xenbus_dev_fatal(dev, err, "completing transaction");
+
+	return;
+
+abort:
+	xenbus_transaction_end(xbt, 1);
+
+	return;
+}
+
+static int usbback_remove(struct xenbus_device *dev)
+{
+	usbif_t *usbif = dev_get_drvdata(&dev->dev);
+	int i;
+
+	if (usbif->backend_watch.node) {
+		unregister_xenbus_watch(&usbif->backend_watch);
+		kfree(usbif->backend_watch.node);
+		usbif->backend_watch.node = NULL;
+	}
+
+	if (usbif) {
+		/* remove all ports */
+		for (i = 1; i <= usbif->num_ports; i++)
+			portid_remove(usbif->domid, usbif->handle, i);
+		usbif_disconnect(usbif);
+		usbif_free(usbif);;
+	}
+	dev_set_drvdata(&dev->dev, NULL);
+
+	return 0;
+}
+
+static int usbback_probe(struct xenbus_device *dev,
+			  const struct xenbus_device_id *id)
+{
+	usbif_t *usbif;
+	unsigned int handle;
+	int num_ports;
+	int usb_ver;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	handle = simple_strtoul(strrchr(dev->otherend, '/') + 1, NULL, 0);
+	usbif = usbif_alloc(dev->otherend_id, handle);
+	if (!usbif) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating backend interface");
+		return -ENOMEM;
+	}
+	usbif->xbdev = dev;
+	dev_set_drvdata(&dev->dev, usbif);
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+				"num-ports", "%d", &num_ports);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading num-ports");
+		goto fail;
+	}
+	if (num_ports < 1 || num_ports > USB_MAXCHILDREN) {
+		xenbus_dev_fatal(dev, err, "invalid num-ports");
+		goto fail;
+	}
+	usbif->num_ports = num_ports;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename,
+				"usb-ver", "%d", &usb_ver);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading usb-ver");
+		goto fail;
+	}
+	switch (usb_ver) {
+	case USB_VER_USB11:
+	case USB_VER_USB20:
+		usbif->usb_ver = usb_ver;
+		break;
+	default:
+		xenbus_dev_fatal(dev, err, "invalid usb-ver");
+		goto fail;
+	}
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+
+	return 0;
+
+fail:
+	usbback_remove(dev);
+	return err;
+}
+
+static int connect_rings(usbif_t *usbif)
+{
+	struct xenbus_device *dev = usbif->xbdev;
+	unsigned long urb_ring_ref;
+	unsigned long conn_ring_ref;
+	unsigned int evtchn;
+	int err;
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "urb-ring-ref", "%lu", &urb_ring_ref,
+			    "conn-ring-ref", "%lu", &conn_ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	printk("usbback: urb-ring-ref %ld, conn-ring-ref %ld, event-channel %d\n",
+	       urb_ring_ref, conn_ring_ref, evtchn);
+
+	err = usbif_map(usbif, urb_ring_ref, conn_ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				"mapping urb-ring-ref %lu conn-ring-ref %lu port %u",
+				urb_ring_ref, conn_ring_ref, evtchn);
+		return err;
+	}
+
+	return 0;
+}
+
+static void frontend_changed(struct xenbus_device *dev,
+				     enum xenbus_state frontend_state)
+{
+	usbif_t *usbif = dev_get_drvdata(&dev->dev);
+	int err;
+
+	switch (frontend_state) {
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+		break;
+
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk("%s: %s: prepare for reconnect\n",
+			       __FUNCTION__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateConnected:
+		if (dev->state == XenbusStateConnected)
+			break;
+		err = connect_rings(usbif);
+		if (err)
+			break;
+		err = start_xenusbd(usbif);
+		if (err)
+			break;
+		err = xenbus_watch_path2(dev, dev->nodename, "port",
+					&usbif->backend_watch, backend_changed);
+		if (err)
+			break;
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateClosing:
+		usbif_disconnect(usbif);
+		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;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+static const struct xenbus_device_id usbback_ids[] = {
+	{ "vusb" },
+	{ "" },
+};
+
+static struct xenbus_driver usbback_driver = {
+	.name = "vusb",
+	.ids = usbback_ids,
+	.probe = usbback_probe,
+	.otherend_changed = frontend_changed,
+	.remove = usbback_remove,
+};
+
+int __init usbback_xenbus_init(void)
+{
+	return xenbus_register_backend(&usbback_driver);
+}
+
+void __exit usbback_xenbus_exit(void)
+{
+	xenbus_unregister_driver(&usbback_driver);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/usbback.h
+++ linux-ec2-2.6.32/drivers/xen/usbback/usbback.h
@@ -0,0 +1,179 @@
+/*
+ * usbback.h
+ *
+ * This file is part of Xen USB backend driver.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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_USBBACK_H__
+#define __XEN_USBBACK_H__
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <xen/evtchn.h>
+#include <xen/gnttab.h>
+#include <xen/driver_util.h>
+#include <xen/interface/xen.h>
+#include <xen/xenbus.h>
+#include <xen/interface/io/usbif.h>
+
+struct usbstub;
+
+#ifndef BUS_ID_SIZE
+#define USBBACK_BUS_ID_SIZE 20
+#else
+#define USBBACK_BUS_ID_SIZE BUS_ID_SIZE
+#endif
+
+#define USB_DEV_ADDR_SIZE 128
+
+typedef struct usbif_st {
+	domid_t domid;
+	unsigned int handle;
+	int num_ports;
+	enum usb_spec_version usb_ver;
+
+	struct xenbus_device *xbdev;
+	struct list_head usbif_list;
+
+	unsigned int      irq;
+
+	usbif_urb_back_ring_t urb_ring;
+	usbif_conn_back_ring_t conn_ring;
+	struct vm_struct *urb_ring_area;
+	struct vm_struct *conn_ring_area;
+
+	spinlock_t urb_ring_lock;
+	spinlock_t conn_ring_lock;
+	atomic_t refcnt;
+
+	grant_handle_t urb_shmem_handle;
+	grant_ref_t urb_shmem_ref;
+	grant_handle_t conn_shmem_handle;
+	grant_ref_t conn_shmem_ref;
+
+	struct xenbus_watch backend_watch;
+
+	/* device address lookup table */
+	struct usbstub *addr_table[USB_DEV_ADDR_SIZE];
+	spinlock_t addr_lock;
+
+	/* connected device list */
+	struct list_head stub_list;
+	spinlock_t stub_lock;
+
+	/* request schedule */
+	struct task_struct *xenusbd;
+	unsigned int waiting_reqs;
+	wait_queue_head_t waiting_to_free;
+	wait_queue_head_t wq;
+} usbif_t;
+
+struct vusb_port_id {
+	struct list_head id_list;
+
+	char phys_bus[USBBACK_BUS_ID_SIZE];
+	domid_t domid;
+	unsigned int handle;
+	int portnum;
+	unsigned is_connected:1;
+};
+
+struct usbstub {
+	struct kref kref;
+	struct list_head dev_list;
+
+	struct vusb_port_id *portid;
+	struct usb_device *udev;
+	usbif_t *usbif;
+	int addr;
+
+	struct list_head submitting_list;
+	spinlock_t submitting_lock;
+};
+
+usbif_t *usbif_alloc(domid_t domid, unsigned int handle);
+void usbif_disconnect(usbif_t *usbif);
+void usbif_free(usbif_t *usbif);
+int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref,
+		unsigned long conn_ring_ref, unsigned int evtchn);
+
+#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
+#define usbif_put(_b) \
+	do { \
+		if (atomic_dec_and_test(&(_b)->refcnt)) \
+			wake_up(&(_b)->waiting_to_free); \
+	} while (0)
+
+usbif_t *find_usbif(domid_t domid, unsigned int handle);
+int usbback_xenbus_init(void);
+void usbback_xenbus_exit(void);
+struct vusb_port_id *find_portid_by_busid(const char *busid);
+struct vusb_port_id *find_portid(const domid_t domid,
+						const unsigned int handle,
+						const int portnum);
+int portid_add(const char *busid,
+					const domid_t domid,
+					const unsigned int handle,
+					const int portnum);
+int portid_remove(const domid_t domid,
+					const unsigned int handle,
+					const int portnum);
+irqreturn_t usbbk_be_int(int irq, void *dev_id);
+int usbbk_schedule(void *arg);
+struct usbstub *find_attached_device(usbif_t *usbif, int port);
+void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub);
+void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub);
+void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed);
+void detach_device_without_lock(usbif_t *usbif, struct usbstub *stub);
+void usbbk_unlink_urbs(struct usbstub *stub);
+
+int usbstub_init(void);
+void usbstub_exit(void);
+
+#endif /* __XEN_USBBACK_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/usbback.c
+++ linux-ec2-2.6.32/drivers/xen/usbback/usbback.c
@@ -0,0 +1,1158 @@
+/*
+ * usbback.c
+ *
+ * Xen USB backend driver
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include <linux/mm.h>
+#include <xen/balloon.h>
+#include "usbback.h"
+
+#if 0
+#include "../../usb/core/hub.h"
+#endif
+
+int usbif_reqs = USBIF_BACK_MAX_PENDING_REQS;
+module_param_named(reqs, usbif_reqs, int, 0);
+MODULE_PARM_DESC(reqs, "Number of usbback requests to allocate");
+
+struct pending_req_segment {
+	uint16_t offset;
+	uint16_t length;
+};
+
+typedef struct {
+	usbif_t *usbif;
+
+	uint16_t id; /* request id */
+
+	struct usbstub *stub;
+	struct list_head urb_list;
+
+	/* urb */
+	struct urb *urb;
+	void *buffer;
+	dma_addr_t transfer_dma;
+	struct usb_ctrlrequest *setup;
+	dma_addr_t setup_dma;
+
+	/* request segments */
+	uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
+	uint16_t nr_extra_segs; /* number of iso_frame_desc segments (ISO) */
+	struct pending_req_segment *seg;
+
+	struct list_head free_list;
+} pending_req_t;
+
+static pending_req_t *pending_reqs;
+static struct list_head pending_free;
+static DEFINE_SPINLOCK(pending_free_lock);
+static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
+
+#define USBBACK_INVALID_HANDLE (~0)
+
+static struct page **pending_pages;
+static grant_handle_t *pending_grant_handles;
+
+static inline int vaddr_pagenr(pending_req_t *req, int seg)
+{
+	return (req - pending_reqs) * USBIF_MAX_SEGMENTS_PER_REQUEST + seg;
+}
+
+static inline 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)])
+
+static pending_req_t *alloc_req(void)
+{
+	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 inline void add_req_to_submitting_list(struct usbstub *stub, pending_req_t *pending_req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&stub->submitting_lock, flags);
+	list_add_tail(&pending_req->urb_list, &stub->submitting_list);
+	spin_unlock_irqrestore(&stub->submitting_lock, flags);
+}
+
+static inline void remove_req_from_submitting_list(struct usbstub *stub, pending_req_t *pending_req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&stub->submitting_lock, flags);
+	list_del_init(&pending_req->urb_list);
+	spin_unlock_irqrestore(&stub->submitting_lock, flags);
+}
+
+void usbbk_unlink_urbs(struct usbstub *stub)
+{
+	pending_req_t *req, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&stub->submitting_lock, flags);
+	list_for_each_entry_safe(req, tmp, &stub->submitting_list, urb_list) {
+		usb_unlink_urb(req->urb);
+	}
+	spin_unlock_irqrestore(&stub->submitting_lock, flags);
+}
+
+static void fast_flush_area(pending_req_t *pending_req)
+{
+	struct gnttab_unmap_grant_ref unmap[USBIF_MAX_SEGMENTS_PER_REQUEST];
+	unsigned int i, nr_segs, invcount = 0;
+	grant_handle_t handle;
+	int ret;
+
+	nr_segs = pending_req->nr_buffer_segs + pending_req->nr_extra_segs;
+
+	if (nr_segs) {
+		for (i = 0; i < nr_segs; i++) {
+			handle = pending_handle(pending_req, i);
+			if (handle == USBBACK_INVALID_HANDLE)
+				continue;
+			gnttab_set_unmap_op(&unmap[invcount], vaddr(pending_req, i),
+					    GNTMAP_host_map, handle);
+			pending_handle(pending_req, i) = USBBACK_INVALID_HANDLE;
+			invcount++;
+		}
+
+		ret = HYPERVISOR_grant_table_op(
+			GNTTABOP_unmap_grant_ref, unmap, invcount);
+		BUG_ON(ret);
+
+		kfree(pending_req->seg);
+	}
+
+	return;
+}
+
+static void copy_buff_to_pages(void *buff, pending_req_t *pending_req,
+		int start, int nr_pages)
+{
+	unsigned long copied = 0;
+	int i;
+
+	for (i = start; i < start + nr_pages; i++) {
+		memcpy((void *) vaddr(pending_req, i) + pending_req->seg[i].offset,
+			buff + copied,
+			pending_req->seg[i].length);
+		copied += pending_req->seg[i].length;
+	}
+}
+
+static void copy_pages_to_buff(void *buff, pending_req_t *pending_req,
+		int start, int nr_pages)
+{
+	unsigned long copied = 0;
+	int i;
+
+	for (i = start; i < start + nr_pages; i++) {
+		memcpy(buff + copied,
+			(void *) vaddr(pending_req, i) + pending_req->seg[i].offset,
+			pending_req->seg[i].length);
+		copied += pending_req->seg[i].length;
+	}
+}
+
+static int usbbk_alloc_urb(usbif_urb_request_t *req, pending_req_t *pending_req)
+{
+	int ret;
+
+	if (usb_pipeisoc(req->pipe))
+		pending_req->urb = usb_alloc_urb(req->u.isoc.number_of_packets, GFP_KERNEL);
+	else
+		pending_req->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pending_req->urb) {
+		printk(KERN_ERR "usbback: can't alloc urb\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (req->buffer_length) {
+		pending_req->buffer = usb_buffer_alloc(pending_req->stub->udev,
+				req->buffer_length, GFP_KERNEL,
+				&pending_req->transfer_dma);
+		if (!pending_req->buffer) {
+			printk(KERN_ERR "usbback: can't alloc urb buffer\n");
+			ret = -ENOMEM;
+			goto fail_free_urb;
+		}
+	}
+
+	if (usb_pipecontrol(req->pipe)) {
+		pending_req->setup = usb_buffer_alloc(pending_req->stub->udev,
+				sizeof(struct usb_ctrlrequest), GFP_KERNEL,
+				&pending_req->setup_dma);
+		if (!pending_req->setup) {
+			printk(KERN_ERR "usbback: can't alloc usb_ctrlrequest\n");
+			ret = -ENOMEM;
+			goto fail_free_buffer;
+		}
+	}
+
+	return 0;
+
+fail_free_buffer:
+	if (req->buffer_length)
+		usb_buffer_free(pending_req->stub->udev, req->buffer_length,
+				pending_req->buffer, pending_req->transfer_dma);
+fail_free_urb:
+	usb_free_urb(pending_req->urb);
+fail:
+	return ret;
+}
+
+static void usbbk_free_urb(struct urb *urb)
+{
+	if (usb_pipecontrol(urb->pipe))
+		usb_buffer_free(urb->dev, sizeof(struct usb_ctrlrequest),
+				urb->setup_packet, urb->setup_dma);
+	if (urb->transfer_buffer_length)
+		usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+				urb->transfer_buffer, urb->transfer_dma);
+	barrier();
+	usb_free_urb(urb);
+}
+
+static void usbbk_notify_work(usbif_t *usbif)
+{
+	usbif->waiting_reqs = 1;
+	wake_up(&usbif->wq);
+}
+
+irqreturn_t usbbk_be_int(int irq, void *dev_id)
+{
+	usbbk_notify_work(dev_id);
+	return IRQ_HANDLED;
+}
+
+static void usbbk_do_response(pending_req_t *pending_req, int32_t status,
+					int32_t actual_length, int32_t error_count, uint16_t start_frame)
+{
+	usbif_t *usbif = pending_req->usbif;
+	usbif_urb_response_t *res;
+	unsigned long flags;
+	int notify;
+
+	spin_lock_irqsave(&usbif->urb_ring_lock, flags);
+	res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt);
+	res->id = pending_req->id;
+	res->status = status;
+	res->actual_length = actual_length;
+	res->error_count = error_count;
+	res->start_frame = start_frame;
+	usbif->urb_ring.rsp_prod_pvt++;
+	barrier();
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify);
+	spin_unlock_irqrestore(&usbif->urb_ring_lock, flags);
+
+	if (notify)
+		notify_remote_via_irq(usbif->irq);
+}
+
+static void usbbk_urb_complete(struct urb *urb)
+{
+	pending_req_t *pending_req = (pending_req_t *)urb->context;
+
+	if (usb_pipein(urb->pipe) && urb->status == 0 && urb->actual_length > 0)
+		copy_buff_to_pages(pending_req->buffer, pending_req,
+					0, pending_req->nr_buffer_segs);
+
+	if (usb_pipeisoc(urb->pipe))
+		copy_buff_to_pages(&urb->iso_frame_desc[0], pending_req,
+					pending_req->nr_buffer_segs, pending_req->nr_extra_segs);
+
+	barrier();
+
+	fast_flush_area(pending_req);
+
+	usbbk_do_response(pending_req, urb->status, urb->actual_length,
+					urb->error_count, urb->start_frame);
+
+	remove_req_from_submitting_list(pending_req->stub, pending_req);
+
+	barrier();
+	usbbk_free_urb(urb);
+	usbif_put(pending_req->usbif);
+	free_req(pending_req);
+}
+
+static int usbbk_gnttab_map(usbif_t *usbif,
+			usbif_urb_request_t *req, pending_req_t *pending_req)
+{
+	int i, ret;
+	unsigned int nr_segs;
+	uint32_t flags;
+	struct gnttab_map_grant_ref map[USBIF_MAX_SEGMENTS_PER_REQUEST];
+
+	nr_segs = pending_req->nr_buffer_segs + pending_req->nr_extra_segs;
+
+	if (nr_segs > USBIF_MAX_SEGMENTS_PER_REQUEST) {
+		printk(KERN_ERR "Bad number of segments in request\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (nr_segs) {
+		pending_req->seg = kmalloc(sizeof(struct pending_req_segment)
+				* nr_segs, GFP_KERNEL);
+		if (!pending_req->seg) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		if (pending_req->nr_buffer_segs) {
+			flags = GNTMAP_host_map;
+			if (usb_pipeout(req->pipe))
+				flags |= GNTMAP_readonly;
+			for (i = 0; i < pending_req->nr_buffer_segs; i++)
+				gnttab_set_map_op(&map[i], vaddr(
+						pending_req, i), flags,
+						req->seg[i].gref,
+						usbif->domid);
+		}
+
+		if (pending_req->nr_extra_segs) {
+			flags = GNTMAP_host_map;
+			for (i = req->nr_buffer_segs; i < nr_segs; i++)
+				gnttab_set_map_op(&map[i], vaddr(
+						pending_req, i), flags,
+						req->seg[i].gref,
+						usbif->domid);
+		}
+
+		ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
+					map, nr_segs);
+		BUG_ON(ret);
+
+		for (i = 0; i < nr_segs; i++) {
+			if (unlikely(map[i].status != 0)) {
+				printk(KERN_ERR "usbback: invalid buffer -- could not remap it\n");
+				map[i].handle = USBBACK_INVALID_HANDLE;
+				ret |= 1;
+			}
+
+			pending_handle(pending_req, i) = map[i].handle;
+
+			if (ret)
+				continue;
+
+			set_phys_to_machine(__pa(vaddr(
+				pending_req, i)) >> PAGE_SHIFT,
+				FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
+
+			pending_req->seg[i].offset = req->seg[i].offset;
+			pending_req->seg[i].length = req->seg[i].length;
+
+			barrier();
+
+			if (pending_req->seg[i].offset >= PAGE_SIZE ||
+					pending_req->seg[i].length > PAGE_SIZE ||
+					pending_req->seg[i].offset + pending_req->seg[i].length > PAGE_SIZE)
+					ret |= 1;
+		}
+
+		if (ret)
+			goto fail_flush;
+	}
+
+	return 0;
+
+fail_flush:
+	fast_flush_area(pending_req);
+	ret = -ENOMEM;
+
+fail:
+	return ret;
+}
+
+static void usbbk_init_urb(usbif_urb_request_t *req, pending_req_t *pending_req)
+{
+	unsigned int pipe;
+	struct usb_device *udev = pending_req->stub->udev;
+	struct urb *urb = pending_req->urb;
+
+	switch (usb_pipetype(req->pipe)) {
+	case PIPE_ISOCHRONOUS:
+		if (usb_pipein(req->pipe))
+			pipe = usb_rcvisocpipe(udev, usb_pipeendpoint(req->pipe));
+		else
+			pipe = usb_sndisocpipe(udev, usb_pipeendpoint(req->pipe));
+
+		urb->dev = udev;
+		urb->pipe = pipe;
+		urb->transfer_flags = req->transfer_flags;
+		urb->transfer_flags |= URB_ISO_ASAP;
+		urb->transfer_buffer = pending_req->buffer;
+		urb->transfer_buffer_length = req->buffer_length;
+		urb->complete = usbbk_urb_complete;
+		urb->context = pending_req;
+		urb->interval = req->u.isoc.interval;
+		urb->start_frame = req->u.isoc.start_frame;
+		urb->number_of_packets = req->u.isoc.number_of_packets;
+
+		break;
+	case PIPE_INTERRUPT:
+		if (usb_pipein(req->pipe))
+			pipe = usb_rcvintpipe(udev, usb_pipeendpoint(req->pipe));
+		else
+			pipe = usb_sndintpipe(udev, usb_pipeendpoint(req->pipe));
+
+		usb_fill_int_urb(urb, udev, pipe,
+				pending_req->buffer, req->buffer_length,
+				usbbk_urb_complete,
+				pending_req, req->u.intr.interval);
+		/*
+		 * high speed interrupt endpoints use a logarithmic encoding of
+		 * the endpoint interval, and usb_fill_int_urb() initializes a
+		 * interrupt urb with the encoded interval value.
+		 *
+		 * req->u.intr.interval is the interval value that already
+		 * encoded in the frontend part, and the above usb_fill_int_urb()
+		 * initializes the urb->interval with double encoded value.
+		 *
+		 * so, simply overwrite the urb->interval with original value.
+		 */
+		urb->interval = req->u.intr.interval;
+		urb->transfer_flags = req->transfer_flags;
+
+		break;
+	case PIPE_CONTROL:
+		if (usb_pipein(req->pipe))
+			pipe = usb_rcvctrlpipe(udev, 0);
+		else
+			pipe = usb_sndctrlpipe(udev, 0);
+
+		usb_fill_control_urb(urb, udev, pipe,
+				(unsigned char *) pending_req->setup,
+				pending_req->buffer, req->buffer_length,
+				usbbk_urb_complete, pending_req);
+		memcpy(pending_req->setup, req->u.ctrl, 8);
+		urb->setup_dma = pending_req->setup_dma;
+		urb->transfer_flags = req->transfer_flags;
+		urb->transfer_flags |= URB_NO_SETUP_DMA_MAP;
+
+		break;
+	case PIPE_BULK:
+		if (usb_pipein(req->pipe))
+			pipe = usb_rcvbulkpipe(udev, usb_pipeendpoint(req->pipe));
+		else
+			pipe = usb_sndbulkpipe(udev, usb_pipeendpoint(req->pipe));
+
+		usb_fill_bulk_urb(urb, udev, pipe,
+				pending_req->buffer, req->buffer_length,
+				usbbk_urb_complete, pending_req);
+		urb->transfer_flags = req->transfer_flags;
+
+		break;
+	default:
+		break;
+	}
+
+	if (req->buffer_length) {
+		urb->transfer_dma = pending_req->transfer_dma;
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	}
+}
+
+struct set_interface_request {
+	pending_req_t *pending_req;
+	int interface;
+	int alternate;
+	struct work_struct work;
+};
+
+static void usbbk_set_interface_work(struct work_struct *arg)
+{
+	struct set_interface_request *req
+		= container_of(arg, struct set_interface_request, work);
+	pending_req_t *pending_req = req->pending_req;
+	struct usb_device *udev = req->pending_req->stub->udev;
+
+	int ret;
+
+	usb_lock_device(udev);
+	ret = usb_set_interface(udev, req->interface, req->alternate);
+	usb_unlock_device(udev);
+	usb_put_dev(udev);
+
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(pending_req->usbif);
+	free_req(pending_req);
+	kfree(req);
+}
+
+static int usbbk_set_interface(pending_req_t *pending_req, int interface, int alternate)
+{
+	struct set_interface_request *req;
+	struct usb_device *udev = pending_req->stub->udev;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+	req->pending_req = pending_req;
+	req->interface = interface;
+	req->alternate = alternate;
+	INIT_WORK(&req->work, usbbk_set_interface_work);
+	usb_get_dev(udev);
+	schedule_work(&req->work);
+	return 0;
+}
+
+struct clear_halt_request {
+	pending_req_t *pending_req;
+	int pipe;
+	struct work_struct work;
+};
+
+static void usbbk_clear_halt_work(struct work_struct *arg)
+{
+	struct clear_halt_request *req
+		= container_of(arg, struct clear_halt_request, work);
+	pending_req_t *pending_req = req->pending_req;
+	struct usb_device *udev = req->pending_req->stub->udev;
+	int ret;
+
+	usb_lock_device(udev);
+	ret = usb_clear_halt(req->pending_req->stub->udev, req->pipe);
+	usb_unlock_device(udev);
+	usb_put_dev(udev);
+
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(pending_req->usbif);
+	free_req(pending_req);
+	kfree(req);
+}
+
+static int usbbk_clear_halt(pending_req_t *pending_req, int pipe)
+{
+	struct clear_halt_request *req;
+	struct usb_device *udev = pending_req->stub->udev;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+	req->pending_req = pending_req;
+	req->pipe = pipe;
+	INIT_WORK(&req->work, usbbk_clear_halt_work);
+
+	usb_get_dev(udev);
+	schedule_work(&req->work);
+	return 0;
+}
+
+#if 0
+struct port_reset_request {
+	pending_req_t *pending_req;
+	struct work_struct work;
+};
+
+static void usbbk_port_reset_work(struct work_struct *arg)
+{
+	struct port_reset_request *req
+		= container_of(arg, struct port_reset_request, work);
+	pending_req_t *pending_req = req->pending_req;
+	struct usb_device *udev = pending_req->stub->udev;
+	int ret, ret_lock;
+
+	ret = ret_lock = usb_lock_device_for_reset(udev, NULL);
+	if (ret_lock >= 0) {
+		ret = usb_reset_device(udev);
+		if (ret_lock)
+			usb_unlock_device(udev);
+	}
+	usb_put_dev(udev);
+
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(pending_req->usbif);
+	free_req(pending_req);
+	kfree(req);
+}
+
+static int usbbk_port_reset(pending_req_t *pending_req)
+{
+	struct port_reset_request *req;
+	struct usb_device *udev = pending_req->stub->udev;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	req->pending_req = pending_req;
+	INIT_WORK(&req->work, usbbk_port_reset_work);
+
+	usb_get_dev(udev);
+	schedule_work(&req->work);
+	return 0;
+}
+#endif
+
+static void usbbk_set_address(usbif_t *usbif, struct usbstub *stub, int cur_addr, int new_addr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&usbif->addr_lock, flags);
+	if (cur_addr)
+		usbif->addr_table[cur_addr] = NULL;
+	if (new_addr)
+		usbif->addr_table[new_addr] = stub;
+	stub->addr = new_addr;
+	spin_unlock_irqrestore(&usbif->addr_lock, flags);
+}
+
+struct usbstub *find_attached_device(usbif_t *usbif, int portnum)
+{
+	struct usbstub *stub;
+	int found = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&usbif->stub_lock, flags);
+	list_for_each_entry(stub, &usbif->stub_list, dev_list) {
+		if (stub->portid->portnum == portnum) {
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&usbif->stub_lock, flags);
+
+	if (found)
+		return stub;
+
+	return NULL;
+}
+
+static void process_unlink_req(usbif_t *usbif,
+		usbif_urb_request_t *req, pending_req_t *pending_req)
+{
+	pending_req_t *unlink_req = NULL;
+	int devnum;
+	int ret = 0;
+	unsigned long flags;
+
+	devnum = usb_pipedevice(req->pipe);
+	if (unlikely(devnum == 0)) {
+		pending_req->stub = find_attached_device(usbif, usbif_pipeportnum(req->pipe));
+		if (unlikely(!pending_req->stub)) {
+			ret = -ENODEV;
+			goto fail_response;
+		}
+	} else {
+		if (unlikely(!usbif->addr_table[devnum])) {
+			ret = -ENODEV;
+			goto fail_response;
+		}
+		pending_req->stub = usbif->addr_table[devnum];
+	}
+
+	spin_lock_irqsave(&pending_req->stub->submitting_lock, flags);
+	list_for_each_entry(unlink_req, &pending_req->stub->submitting_list, urb_list) {
+		if (unlink_req->id == req->u.unlink.unlink_id) {
+			ret = usb_unlink_urb(unlink_req->urb);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&pending_req->stub->submitting_lock, flags);
+
+fail_response:
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(usbif);
+	free_req(pending_req);
+	return;
+}
+
+static int check_and_submit_special_ctrlreq(usbif_t *usbif,
+		usbif_urb_request_t *req, pending_req_t *pending_req)
+{
+	int devnum;
+	struct usbstub *stub = NULL;
+	struct usb_ctrlrequest *ctrl = (struct usb_ctrlrequest *) req->u.ctrl;
+	int ret;
+	int done = 0;
+
+	devnum = usb_pipedevice(req->pipe);
+
+	/*
+	 * When the device is first connected or reseted, USB device has no address.
+	 * In this initial state, following requests are send to device address (#0),
+	 *
+	 *  1. GET_DESCRIPTOR (with Descriptor Type is "DEVICE") is send,
+	 *     and OS knows what device is connected to.
+	 *
+	 *  2. SET_ADDRESS is send, and then, device has its address.
+	 *
+	 * In the next step, SET_CONFIGURATION is send to addressed device, and then,
+	 * the device is finally ready to use.
+	 */
+	if (unlikely(devnum == 0)) {
+		stub = find_attached_device(usbif, usbif_pipeportnum(req->pipe));
+		if (unlikely(!stub)) {
+			ret = -ENODEV;
+			goto fail_response;
+		}
+
+		switch (ctrl->bRequest) {
+		case USB_REQ_GET_DESCRIPTOR:
+			/*
+			 * GET_DESCRIPTOR request to device #0.
+			 * through to normal urb transfer.
+			 */
+			pending_req->stub = stub;
+			return 0;
+			break;
+		case USB_REQ_SET_ADDRESS:
+			/*
+			 * SET_ADDRESS request to device #0.
+			 * add attached device to addr_table.
+			 */
+			{
+				__u16 addr = le16_to_cpu(ctrl->wValue);
+				usbbk_set_address(usbif, stub, 0, addr);
+			}
+			ret = 0;
+			goto fail_response;
+			break;
+		default:
+			ret = -EINVAL;
+			goto fail_response;
+		}
+	} else {
+		if (unlikely(!usbif->addr_table[devnum])) {
+			ret = -ENODEV;
+			goto fail_response;
+		}
+		pending_req->stub = usbif->addr_table[devnum];
+	}
+
+	/*
+	 * Check special request
+	 */
+	switch (ctrl->bRequest) {
+	case USB_REQ_SET_ADDRESS:
+		/*
+		 * SET_ADDRESS request to addressed device.
+		 * change addr or remove from addr_table.
+		 */
+		{
+			__u16 addr = le16_to_cpu(ctrl->wValue);
+			usbbk_set_address(usbif, stub, devnum, addr);
+		}
+		ret = 0;
+		goto fail_response;
+		break;
+#if 0
+	case USB_REQ_SET_CONFIGURATION:
+		/*
+		 * linux 2.6.27 or later version only!
+		 */
+		if (ctrl->RequestType == USB_RECIP_DEVICE) {
+			__u16 config = le16_to_cpu(ctrl->wValue);
+			usb_driver_set_configuration(pending_req->stub->udev, config);
+			done = 1;
+		}
+		break;
+#endif
+	case USB_REQ_SET_INTERFACE:
+		if (ctrl->bRequestType == USB_RECIP_INTERFACE) {
+			__u16 alt = le16_to_cpu(ctrl->wValue);
+			__u16 intf = le16_to_cpu(ctrl->wIndex);
+			usbbk_set_interface(pending_req, intf, alt);
+			done = 1;
+		}
+		break;
+	case USB_REQ_CLEAR_FEATURE:
+		if (ctrl->bRequestType == USB_RECIP_ENDPOINT
+			&& ctrl->wValue == USB_ENDPOINT_HALT) {
+			int pipe;
+			int ep = le16_to_cpu(ctrl->wIndex) & 0x0f;
+			int dir = le16_to_cpu(ctrl->wIndex)
+					& USB_DIR_IN;
+			if (dir)
+				pipe = usb_rcvctrlpipe(pending_req->stub->udev, ep);
+			else
+				pipe = usb_sndctrlpipe(pending_req->stub->udev, ep);
+			usbbk_clear_halt(pending_req, pipe);
+			done = 1;
+		}
+		break;
+#if 0 /* not tested yet */
+	case USB_REQ_SET_FEATURE:
+		if (ctrl->bRequestType == USB_RT_PORT) {
+			__u16 feat = le16_to_cpu(ctrl->wValue);
+			if (feat == USB_PORT_FEAT_RESET) {
+				usbbk_port_reset(pending_req);
+				done = 1;
+			}
+		}
+		break;
+#endif
+	default:
+		break;
+	}
+
+	return done;
+
+fail_response:
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(usbif);
+	free_req(pending_req);
+	return 1;
+}
+
+static void dispatch_request_to_pending_reqs(usbif_t *usbif,
+		usbif_urb_request_t *req,
+		pending_req_t *pending_req)
+{
+	int ret;
+
+	pending_req->id = req->id;
+	pending_req->usbif = usbif;
+
+	barrier();
+
+	usbif_get(usbif);
+
+	/* unlink request */
+	if (unlikely(usbif_pipeunlink(req->pipe))) {
+		process_unlink_req(usbif, req, pending_req);
+		return;
+	}
+
+	if (usb_pipecontrol(req->pipe)) {
+		if (check_and_submit_special_ctrlreq(usbif, req, pending_req))
+			return;
+	} else {
+		int devnum = usb_pipedevice(req->pipe);
+		if (unlikely(!usbif->addr_table[devnum])) {
+			ret = -ENODEV;
+			goto fail_response;
+		}
+		pending_req->stub = usbif->addr_table[devnum];
+	}
+
+	barrier();
+
+	ret = usbbk_alloc_urb(req, pending_req);
+	if (ret) {
+		ret = -ESHUTDOWN;
+		goto fail_response;
+	}
+
+	add_req_to_submitting_list(pending_req->stub, pending_req);
+
+	barrier();
+
+	usbbk_init_urb(req, pending_req);
+
+	barrier();
+
+	pending_req->nr_buffer_segs = req->nr_buffer_segs;
+	if (usb_pipeisoc(req->pipe))
+		pending_req->nr_extra_segs = req->u.isoc.nr_frame_desc_segs;
+	else
+		pending_req->nr_extra_segs = 0;
+
+	barrier();
+
+	ret = usbbk_gnttab_map(usbif, req, pending_req);
+	if (ret) {
+		printk(KERN_ERR "usbback: invalid buffer\n");
+		ret = -ESHUTDOWN;
+		goto fail_free_urb;
+	}
+
+	barrier();
+
+	if (usb_pipeout(req->pipe) && req->buffer_length)
+		copy_pages_to_buff(pending_req->buffer,
+					pending_req,
+					0,
+					pending_req->nr_buffer_segs);
+	if (usb_pipeisoc(req->pipe)) {
+		copy_pages_to_buff(&pending_req->urb->iso_frame_desc[0],
+			pending_req,
+			pending_req->nr_buffer_segs,
+			pending_req->nr_extra_segs);
+	}
+
+	barrier();
+
+	ret = usb_submit_urb(pending_req->urb, GFP_KERNEL);
+	if (ret) {
+		printk(KERN_ERR "usbback: failed submitting urb, error %d\n", ret);
+		ret = -ESHUTDOWN;
+		goto fail_flush_area;
+	}
+	return;
+
+fail_flush_area:
+	fast_flush_area(pending_req);
+fail_free_urb:
+	remove_req_from_submitting_list(pending_req->stub, pending_req);
+	barrier();
+	usbbk_free_urb(pending_req->urb);
+fail_response:
+	usbbk_do_response(pending_req, ret, 0, 0, 0);
+	usbif_put(usbif);
+	free_req(pending_req);
+}
+
+static int usbbk_start_submit_urb(usbif_t *usbif)
+{
+	usbif_urb_back_ring_t *urb_ring = &usbif->urb_ring;
+	usbif_urb_request_t *req;
+	pending_req_t *pending_req;
+	RING_IDX rc, rp;
+	int more_to_do = 0;
+
+	rc = urb_ring->req_cons;
+	rp = urb_ring->sring->req_prod;
+	rmb();
+
+	while (rc != rp) {
+		if (RING_REQUEST_CONS_OVERFLOW(urb_ring, rc)) {
+			printk(KERN_WARNING "RING_REQUEST_CONS_OVERFLOW\n");
+			break;
+		}
+
+		pending_req = alloc_req();
+		if (NULL == pending_req) {
+			more_to_do = 1;
+			break;
+		}
+
+		req = RING_GET_REQUEST(urb_ring, rc);
+		urb_ring->req_cons = ++rc;
+
+		dispatch_request_to_pending_reqs(usbif, req,
+							pending_req);
+	}
+
+	RING_FINAL_CHECK_FOR_REQUESTS(&usbif->urb_ring, more_to_do);
+
+	cond_resched();
+
+	return more_to_do;
+}
+
+void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed)
+{
+	usbif_conn_back_ring_t *ring = &usbif->conn_ring;
+	usbif_conn_request_t *req;
+	usbif_conn_response_t *res;
+	unsigned long flags;
+	u16 id;
+	int notify;
+
+	spin_lock_irqsave(&usbif->conn_ring_lock, flags);
+
+	req = RING_GET_REQUEST(ring, ring->req_cons);;
+	id = req->id;
+	ring->req_cons++;
+	ring->sring->req_event = ring->req_cons + 1;
+
+	res = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
+	res->id = id;
+	res->portnum = portnum;
+	res->speed = speed;
+	ring->rsp_prod_pvt++;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify);
+
+	spin_unlock_irqrestore(&usbif->conn_ring_lock, flags);
+
+	if (notify)
+		notify_remote_via_irq(usbif->irq);
+}
+
+int usbbk_schedule(void *arg)
+{
+	usbif_t *usbif = (usbif_t *) arg;
+
+	usbif_get(usbif);
+
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(
+			usbif->wq,
+			usbif->waiting_reqs || kthread_should_stop());
+		wait_event_interruptible(
+			pending_free_wq,
+			!list_empty(&pending_free) || kthread_should_stop());
+		usbif->waiting_reqs = 0;
+		smp_mb();
+
+		if (usbbk_start_submit_urb(usbif))
+			usbif->waiting_reqs = 1;
+	}
+
+	usbif->xenusbd = NULL;
+	usbif_put(usbif);
+
+	return 0;
+}
+
+/*
+ * attach usbstub device to usbif.
+ */
+void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&usbif->stub_lock, flags);
+	list_add(&stub->dev_list, &usbif->stub_list);
+	spin_unlock_irqrestore(&usbif->stub_lock, flags);
+	stub->usbif = usbif;
+}
+
+/*
+ * detach usbstub device from usbif.
+ */
+void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub)
+{
+	unsigned long flags;
+
+	if (stub->addr)
+		usbbk_set_address(usbif, stub, stub->addr, 0);
+	spin_lock_irqsave(&usbif->stub_lock, flags);
+	list_del(&stub->dev_list);
+	spin_unlock_irqrestore(&usbif->stub_lock, flags);
+	stub->usbif = NULL;
+}
+
+void detach_device_without_lock(usbif_t *usbif, struct usbstub *stub)
+{
+	if (stub->addr)
+		usbbk_set_address(usbif, stub, stub->addr, 0);
+	list_del(&stub->dev_list);
+	stub->usbif = NULL;
+}
+
+static int __init usbback_init(void)
+{
+	int i, mmap_pages;
+	int err = 0;
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	mmap_pages = usbif_reqs * USBIF_MAX_SEGMENTS_PER_REQUEST;
+	pending_reqs = kmalloc(sizeof(pending_reqs[0]) *
+			usbif_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) {
+		err = -ENOMEM;
+		goto out_mem;
+	}
+
+	for (i = 0; i < mmap_pages; i++)
+		pending_grant_handles[i] = USBBACK_INVALID_HANDLE;
+
+	memset(pending_reqs, 0, sizeof(pending_reqs));
+	INIT_LIST_HEAD(&pending_free);
+
+	for (i = 0; i < usbif_reqs; i++)
+		list_add_tail(&pending_reqs[i].free_list, &pending_free);
+
+	err = usbstub_init();
+	if (err)
+		goto out_mem;
+
+	err = usbback_xenbus_init();
+	if (err)
+		goto out_xenbus;
+
+	return 0;
+
+out_xenbus:
+	usbstub_exit();
+out_mem:
+	kfree(pending_reqs);
+	kfree(pending_grant_handles);
+	free_empty_pages_and_pagevec(pending_pages, mmap_pages);
+	return err;
+}
+
+static void __exit usbback_exit(void)
+{
+	usbback_xenbus_exit();
+	usbstub_exit();
+	kfree(pending_reqs);
+	kfree(pending_grant_handles);
+	free_empty_pages_and_pagevec(pending_pages, usbif_reqs * USBIF_MAX_SEGMENTS_PER_REQUEST);
+}
+
+module_init(usbback_init);
+module_exit(usbback_exit);
+
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("Xen USB backend driver (usbback)");
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/usbback/interface.c
+++ linux-ec2-2.6.32/drivers/xen/usbback/interface.c
@@ -0,0 +1,249 @@
+/*
+ * interface.c
+ *
+ * Xen USB backend interface management.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * or, by your choice,
+ *
+ * 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 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.
+ */
+
+#include "usbback.h"
+
+static LIST_HEAD(usbif_list);
+static DEFINE_SPINLOCK(usbif_list_lock);
+
+usbif_t *find_usbif(domid_t domid, unsigned int handle)
+{
+	usbif_t *usbif;
+	int found = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&usbif_list_lock, flags);
+	list_for_each_entry(usbif, &usbif_list, usbif_list) {
+		if (usbif->domid == domid
+			&& usbif->handle == handle) {
+			found = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&usbif_list_lock, flags);
+
+	if (found)
+		return usbif;
+
+	return NULL;
+}
+
+usbif_t *usbif_alloc(domid_t domid, unsigned int handle)
+{
+	usbif_t *usbif;
+	unsigned long flags;
+	int i;
+
+	usbif = kzalloc(sizeof(usbif_t), GFP_KERNEL);
+	if (!usbif)
+		return NULL;
+
+	usbif->domid = domid;
+	usbif->handle = handle;
+	spin_lock_init(&usbif->urb_ring_lock);
+	spin_lock_init(&usbif->conn_ring_lock);
+	atomic_set(&usbif->refcnt, 0);
+	init_waitqueue_head(&usbif->wq);
+	init_waitqueue_head(&usbif->waiting_to_free);
+	spin_lock_init(&usbif->stub_lock);
+	INIT_LIST_HEAD(&usbif->stub_list);
+	spin_lock_init(&usbif->addr_lock);
+	for (i = 0; i < USB_DEV_ADDR_SIZE; i++)
+		usbif->addr_table[i] = NULL;
+
+	spin_lock_irqsave(&usbif_list_lock, flags);
+	list_add(&usbif->usbif_list, &usbif_list);
+	spin_unlock_irqrestore(&usbif_list_lock, flags);
+
+	return usbif;
+}
+
+static int map_frontend_pages(usbif_t *usbif,
+				grant_ref_t urb_ring_ref,
+				grant_ref_t conn_ring_ref)
+{
+	struct gnttab_map_grant_ref op;
+
+	gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr,
+			  GNTMAP_host_map, urb_ring_ref, usbif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		printk(KERN_ERR "grant table failure mapping urb_ring_ref\n");
+		return op.status;
+	}
+
+	usbif->urb_shmem_ref = urb_ring_ref;
+	usbif->urb_shmem_handle = op.handle;
+
+	gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr,
+			  GNTMAP_host_map, conn_ring_ref, usbif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		struct gnttab_unmap_grant_ref unop;
+		gnttab_set_unmap_op(&unop,
+				(unsigned long) usbif->urb_ring_area->addr,
+				GNTMAP_host_map, usbif->urb_shmem_handle);
+		VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unop,
+				1));
+		printk(KERN_ERR "grant table failure mapping conn_ring_ref\n");
+		return op.status;
+	}
+
+	usbif->conn_shmem_ref = conn_ring_ref;
+	usbif->conn_shmem_handle = op.handle;
+
+	return 0;
+}
+
+static void unmap_frontend_pages(usbif_t *usbif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	gnttab_set_unmap_op(&op, (unsigned long)usbif->urb_ring_area->addr,
+			    GNTMAP_host_map, usbif->urb_shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+
+	gnttab_set_unmap_op(&op, (unsigned long)usbif->conn_ring_area->addr,
+			    GNTMAP_host_map, usbif->conn_shmem_handle);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+		BUG();
+}
+
+int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref,
+		unsigned long conn_ring_ref, unsigned int evtchn)
+{
+	int err = -ENOMEM;
+
+	usbif_urb_sring_t *urb_sring;
+	usbif_conn_sring_t *conn_sring;
+
+	if (usbif->irq)
+		return 0;
+
+	if ((usbif->urb_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
+		return err;
+	if ((usbif->conn_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
+		goto fail_alloc;
+
+	err = map_frontend_pages(usbif, urb_ring_ref, conn_ring_ref);
+	if (err)
+		goto fail_map;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+			usbif->domid, evtchn, usbbk_be_int, 0,
+			"usbif-backend", usbif);
+	if (err < 0)
+		goto fail_evtchn;
+	usbif->irq = err;
+
+	urb_sring = (usbif_urb_sring_t *) usbif->urb_ring_area->addr;
+	BACK_RING_INIT(&usbif->urb_ring, urb_sring, PAGE_SIZE);
+
+	conn_sring = (usbif_conn_sring_t *) usbif->conn_ring_area->addr;
+	BACK_RING_INIT(&usbif->conn_ring, conn_sring, PAGE_SIZE);
+
+	return 0;
+
+fail_evtchn:
+	unmap_frontend_pages(usbif);
+fail_map:
+	free_vm_area(usbif->conn_ring_area);
+fail_alloc:
+	free_vm_area(usbif->urb_ring_area);
+
+	return err;
+}
+
+void usbif_disconnect(usbif_t *usbif)
+{
+	struct usbstub *stub, *tmp;
+	unsigned long flags;
+
+	if (usbif->xenusbd) {
+		kthread_stop(usbif->xenusbd);
+		usbif->xenusbd = NULL;
+	}
+
+	spin_lock_irqsave(&usbif->stub_lock, flags);
+	list_for_each_entry_safe(stub, tmp, &usbif->stub_list, dev_list) {
+		usbbk_unlink_urbs(stub);
+		detach_device_without_lock(usbif, stub);
+	}
+	spin_unlock_irqrestore(&usbif->stub_lock, flags);
+
+	wait_event(usbif->waiting_to_free, atomic_read(&usbif->refcnt) == 0);
+
+	if (usbif->irq) {
+		unbind_from_irqhandler(usbif->irq, usbif);
+		usbif->irq = 0;
+	}
+
+	if (usbif->urb_ring.sring) {
+		unmap_frontend_pages(usbif);
+		free_vm_area(usbif->urb_ring_area);
+		free_vm_area(usbif->conn_ring_area);
+		usbif->urb_ring.sring = NULL;
+		usbif->conn_ring.sring = NULL;
+	}
+}
+
+void usbif_free(usbif_t *usbif)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&usbif_list_lock, flags);
+	list_del(&usbif->usbif_list);
+	spin_unlock_irqrestore(&usbif_list_lock, flags);
+	kfree(usbif);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/Makefile
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/Makefile
@@ -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 
+
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_cuckoo_hash.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_cuckoo_hash.c
@@ -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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_util.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_util.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+ * 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)
+
+#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
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_msg_iface.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_msg_iface.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_cuckoo_hash.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_cuckoo_hash.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_util.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_util.c
@@ -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");
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_shared_fifo.h
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_shared_fifo.h
@@ -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 */
--- linux-ec2-2.6.32.orig/drivers/xen/sfc_netutil/accel_msg_iface.c
+++ linux-ec2-2.6.32/drivers/xen/sfc_netutil/accel_msg_iface.c
@@ -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);
--- linux-ec2-2.6.32.orig/drivers/xen/balloon/common.h
+++ linux-ec2-2.6.32/drivers/xen/balloon/common.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * balloon/common.h
+ *
+ * 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_BALLOON_COMMON_H__
+#define __XEN_BALLOON_COMMON_H__
+
+#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
+
+struct balloon_stats {
+	/* We aim for 'current allocation' == 'target allocation'. */
+	unsigned long current_pages;
+	unsigned long target_pages;
+	/*
+	 * Drivers may alter the memory reservation independently, but they
+	 * must inform the balloon driver so we avoid hitting the hard limit.
+	 */
+	unsigned long driver_pages;
+	/* Number of pages in high- and low-memory balloons. */
+	unsigned long balloon_low;
+	unsigned long balloon_high;
+};
+
+extern struct balloon_stats balloon_stats;
+#define bs balloon_stats
+
+int balloon_sysfs_init(void);
+void balloon_sysfs_exit(void);
+
+void balloon_set_new_target(unsigned long target);
+unsigned long balloon_minimum_target(void);
+
+#endif /* __XEN_BALLOON_COMMON_H__ */
--- linux-ec2-2.6.32.orig/drivers/xen/balloon/Makefile
+++ linux-ec2-2.6.32/drivers/xen/balloon/Makefile
@@ -0,0 +1,2 @@
+
+obj-y := balloon.o sysfs.o
--- linux-ec2-2.6.32.orig/drivers/xen/balloon/sysfs.c
+++ linux-ec2-2.6.32/drivers/xen/balloon/sysfs.c
@@ -0,0 +1,204 @@
+/******************************************************************************
+ * balloon/sysfs.c
+ *
+ * Xen balloon driver - sysfs interfaces.
+ * 
+ * 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/capability.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include "common.h"
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#define BALLOON_CLASS_NAME "xen_memory"
+
+#define BALLOON_SHOW(name, format, args...)			\
+	static ssize_t show_##name(struct sys_device *dev,	\
+				   struct sysdev_attribute *attr, \
+				   char *buf)			\
+	{							\
+		return sprintf(buf, format, ##args);		\
+	}							\
+	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+
+BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages));
+BALLOON_SHOW(min_kb, "%lu\n", PAGES2KB(balloon_minimum_target()));
+BALLOON_SHOW(max_kb, "%lu\n", PAGES2KB(num_physpages));
+BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low));
+BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high));
+BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages));
+
+static ssize_t show_target_kb(struct sys_device *dev,
+			      struct sysdev_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", PAGES2KB(bs.target_pages));
+}
+
+static ssize_t store_target_kb(struct sys_device *dev,
+			       struct sysdev_attribute *attr,
+			       const char *buf, size_t count)
+{
+	char *endchar;
+	unsigned long long target_bytes;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	
+	if (count <= 1)
+		return -EBADMSG; /* runt */
+	
+	target_bytes = simple_strtoull(buf, &endchar, 0) << 10;
+	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+	
+	return count;
+}
+
+static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
+		   show_target_kb, store_target_kb);
+
+static ssize_t show_target(struct sys_device *dev,
+			   struct sysdev_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%llu\n",
+		       (unsigned long long)balloon_stats.target_pages
+		       << PAGE_SHIFT);
+}
+
+static ssize_t store_target(struct sys_device *dev,
+			    struct sysdev_attribute *attr,
+			    const char *buf,
+			    size_t count)
+{
+	char *endchar;
+	unsigned long long target_bytes;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (count <= 1)
+		return -EBADMSG; /* runt */
+
+	target_bytes = memparse(buf, &endchar);
+	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+
+	return count;
+}
+
+static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
+		   show_target, store_target);
+
+static struct sysdev_attribute *balloon_attrs[] = {
+	&attr_target_kb,
+	&attr_target,
+};
+
+static struct attribute *balloon_info_attrs[] = {
+	&attr_current_kb.attr,
+	&attr_min_kb.attr,
+	&attr_max_kb.attr,
+	&attr_low_kb.attr,
+	&attr_high_kb.attr,
+	&attr_driver_kb.attr,
+	NULL
+};
+
+static struct attribute_group balloon_info_group = {
+	.name = "info",
+	.attrs = balloon_info_attrs,
+};
+
+static struct sysdev_class balloon_sysdev_class = {
+	.name = BALLOON_CLASS_NAME,
+};
+
+static struct sys_device balloon_sysdev;
+
+static int __init register_balloon(struct sys_device *sysdev)
+{
+	int i, error;
+
+	error = sysdev_class_register(&balloon_sysdev_class);
+	if (error)
+		return error;
+
+	sysdev->id = 0;
+	sysdev->cls = &balloon_sysdev_class;
+
+	error = sysdev_register(sysdev);
+	if (error) {
+		sysdev_class_unregister(&balloon_sysdev_class);
+		return error;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
+		error = sysdev_create_file(sysdev, balloon_attrs[i]);
+		if (error)
+			goto fail;
+	}
+
+	error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
+	if (error)
+		goto fail;
+	
+	return 0;
+
+ fail:
+	while (--i >= 0)
+		sysdev_remove_file(sysdev, balloon_attrs[i]);
+	sysdev_unregister(sysdev);
+	sysdev_class_unregister(&balloon_sysdev_class);
+	return error;
+}
+
+static __exit void unregister_balloon(struct sys_device *sysdev)
+{
+	int i;
+
+	sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
+	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
+		sysdev_remove_file(sysdev, balloon_attrs[i]);
+	sysdev_unregister(sysdev);
+	sysdev_class_unregister(&balloon_sysdev_class);
+}
+
+int __init balloon_sysfs_init(void)
+{
+	return register_balloon(&balloon_sysdev);
+}
+
+void __exit balloon_sysfs_exit(void)
+{
+	unregister_balloon(&balloon_sysdev);
+}
--- linux-ec2-2.6.32.orig/drivers/xen/balloon/balloon.c
+++ linux-ec2-2.6.32/drivers/xen/balloon/balloon.c
@@ -0,0 +1,771 @@
+/******************************************************************************
+ * balloon.c
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ * 
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <linux/mutex.h>
+#include <xen/xen_proc.h>
+#include <asm/hypervisor.h>
+#include <xen/balloon.h>
+#include <xen/interface/memory.h>
+#include <asm/maddr.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+#include <xen/xenbus.h>
+#include "common.h"
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *balloon_pde;
+#endif
+
+static DEFINE_MUTEX(balloon_mutex);
+
+/*
+ * Protects atomic reservation decrease/increase against concurrent increases.
+ * Also protects non-atomic updates of current_pages and driver_pages, and
+ * balloon lists.
+ */
+DEFINE_SPINLOCK(balloon_lock);
+
+#ifndef MODULE
+#include <linux/pagevec.h>
+static struct pagevec free_pagevec;
+#endif
+
+struct balloon_stats balloon_stats;
+
+/* We increase/decrease in batches which fit in a page */
+static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+
+#ifdef CONFIG_HIGHMEM
+#define inc_totalhigh_pages() (totalhigh_pages++)
+#define dec_totalhigh_pages() (totalhigh_pages--)
+#else
+#define inc_totalhigh_pages() ((void)0)
+#define dec_totalhigh_pages() ((void)0)
+#endif
+
+/* List of ballooned pages, threaded through the mem_map array. */
+static LIST_HEAD(ballooned_pages);
+
+/* Main work function, always executed in process context. */
+static void balloon_process(struct work_struct *unused);
+static DECLARE_WORK(balloon_worker, balloon_process);
+static struct timer_list balloon_timer;
+
+/* When ballooning out (allocating memory to return to Xen) we don't really 
+   want the kernel to try too hard since that can trigger the oom killer. */
+#define GFP_BALLOON \
+	(GFP_HIGHUSER|__GFP_NOWARN|__GFP_NORETRY|__GFP_NOMEMALLOC|__GFP_COLD)
+
+#define PAGE_TO_LIST(p) (&(p)->lru)
+#define LIST_TO_PAGE(l) list_entry((l), struct page, lru)
+#define UNLIST_PAGE(p)				\
+	do {					\
+		list_del(PAGE_TO_LIST(p));	\
+		PAGE_TO_LIST(p)->next = NULL;	\
+		PAGE_TO_LIST(p)->prev = NULL;	\
+	} while(0)
+
+#define IPRINTK(fmt, args...) \
+	printk(KERN_INFO "xen_mem: " fmt, ##args)
+#define WPRINTK(fmt, args...) \
+	printk(KERN_WARNING "xen_mem: " fmt, ##args)
+
+/* balloon_append: add the given page to the balloon. */
+static void balloon_append(struct page *page, int account)
+{
+	unsigned long pfn;
+
+	/* Lowmem is re-populated first, so highmem pages go at list tail. */
+	if (PageHighMem(page)) {
+		list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
+		bs.balloon_high++;
+		if (account)
+			dec_totalhigh_pages();
+	} else {
+		list_add(PAGE_TO_LIST(page), &ballooned_pages);
+		bs.balloon_low++;
+	}
+
+	pfn = page_to_pfn(page);
+	if (account) {
+		SetPageReserved(page);
+		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+		page_zone(page)->present_pages--;
+	} else {
+		BUG_ON(!PageReserved(page));
+		WARN_ON_ONCE(phys_to_machine_mapping_valid(pfn));
+	}
+}
+
+/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
+static struct page *balloon_retrieve(int *was_empty)
+{
+	struct page *page;
+	struct zone *zone;
+
+	if (list_empty(&ballooned_pages))
+		return NULL;
+
+	page = LIST_TO_PAGE(ballooned_pages.next);
+	UNLIST_PAGE(page);
+	BUG_ON(!PageReserved(page));
+
+	if (PageHighMem(page)) {
+		bs.balloon_high--;
+		inc_totalhigh_pages();
+	}
+	else
+		bs.balloon_low--;
+	zone = page_zone(page);
+	*was_empty |= !populated_zone(zone);
+	zone->present_pages++;
+
+	return page;
+}
+
+static struct page *balloon_first_page(void)
+{
+	if (list_empty(&ballooned_pages))
+		return NULL;
+	return LIST_TO_PAGE(ballooned_pages.next);
+}
+
+static struct page *balloon_next_page(struct page *page)
+{
+	struct list_head *next = PAGE_TO_LIST(page)->next;
+	if (next == &ballooned_pages)
+		return NULL;
+	return LIST_TO_PAGE(next);
+}
+
+static inline void balloon_free_page(struct page *page)
+{
+#ifndef MODULE
+	if (put_page_testzero(page) && !pagevec_add(&free_pagevec, page)) {
+		__pagevec_free(&free_pagevec);
+		pagevec_reinit(&free_pagevec);
+	}
+#else
+	/* pagevec interface is not being exported. */
+	__free_page(page);
+#endif
+}
+
+static inline void balloon_free_and_unlock(unsigned long flags)
+{
+#ifndef MODULE
+	if (pagevec_count(&free_pagevec)) {
+		__pagevec_free(&free_pagevec);
+		pagevec_reinit(&free_pagevec);
+	}
+#endif
+	balloon_unlock(flags);
+}
+
+static void balloon_alarm(unsigned long unused)
+{
+	schedule_work(&balloon_worker);
+}
+
+static unsigned long current_target(void)
+{
+	unsigned long target = bs.target_pages;
+	if (target > (bs.current_pages + bs.balloon_low + bs.balloon_high))
+		target = bs.current_pages + bs.balloon_low + bs.balloon_high;
+	return target;
+}
+
+unsigned long balloon_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;
+	struct page   *page;
+	long           rc;
+	int            need_zonelists_rebuild = 0;
+	struct xen_memory_reservation reservation = {
+		.address_bits = 0,
+		.extent_order = 0,
+		.domid        = DOMID_SELF
+	};
+
+	if (nr_pages > ARRAY_SIZE(frame_list))
+		nr_pages = ARRAY_SIZE(frame_list);
+
+	balloon_lock(flags);
+
+	page = balloon_first_page();
+	for (i = 0; i < nr_pages; i++) {
+		BUG_ON(page == NULL);
+		frame_list[i] = page_to_pfn(page);;
+		page = balloon_next_page(page);
+	}
+
+	set_xen_guest_handle(reservation.extent_start, frame_list);
+	reservation.nr_extents = nr_pages;
+	rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
+	if (rc < 0)
+		goto out;
+
+	for (i = 0; i < rc; i++) {
+		page = balloon_retrieve(&need_zonelists_rebuild);
+		BUG_ON(page == NULL);
+
+		pfn = page_to_pfn(page);
+		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
+		       phys_to_machine_mapping_valid(pfn));
+
+		set_phys_to_machine(pfn, frame_list[i]);
+
+#ifdef CONFIG_XEN
+		/* Link back into the page tables if not highmem. */
+		if (pfn < max_low_pfn) {
+			int ret;
+			ret = HYPERVISOR_update_va_mapping(
+				(unsigned long)__va(pfn << PAGE_SHIFT),
+				pfn_pte_ma(frame_list[i], PAGE_KERNEL),
+				0);
+			BUG_ON(ret);
+		}
+#endif
+
+		/* Relinquish the page back to the allocator. */
+		ClearPageReserved(page);
+		init_page_count(page);
+		balloon_free_page(page);
+	}
+
+	bs.current_pages += rc;
+	totalram_pages = bs.current_pages;
+
+ out:
+	balloon_free_and_unlock(flags);
+
+#ifndef MODULE
+	setup_per_zone_wmarks();
+	if (rc > 0)
+		kswapd_run(0);
+	if (need_zonelists_rebuild)
+		build_all_zonelists();
+	else
+		vm_total_pages = nr_free_pagecache_pages();
+#endif
+
+	return rc < 0 ? rc : rc != nr_pages;
+}
+
+static int decrease_reservation(unsigned long nr_pages)
+{
+	unsigned long  pfn, i, flags;
+	struct page   *page;
+	void          *v;
+	int            need_sleep = 0;
+	int ret;
+	struct xen_memory_reservation reservation = {
+		.address_bits = 0,
+		.extent_order = 0,
+		.domid        = DOMID_SELF
+	};
+
+	if (nr_pages > ARRAY_SIZE(frame_list))
+		nr_pages = ARRAY_SIZE(frame_list);
+
+	for (i = 0; i < nr_pages; i++) {
+		if ((page = alloc_page(GFP_BALLOON)) == NULL) {
+			nr_pages = i;
+			need_sleep = 1;
+			break;
+		}
+
+		pfn = page_to_pfn(page);
+		frame_list[i] = pfn_to_mfn(pfn);
+
+		if (!PageHighMem(page)) {
+			v = phys_to_virt(pfn << PAGE_SHIFT);
+			scrub_pages(v, 1);
+#ifdef CONFIG_XEN
+			ret = HYPERVISOR_update_va_mapping(
+				(unsigned long)v, __pte_ma(0), 0);
+			BUG_ON(ret);
+#endif
+		}
+#ifdef CONFIG_XEN_SCRUB_PAGES
+		else {
+			v = kmap(page);
+			scrub_pages(v, 1);
+			kunmap(page);
+		}
+#endif
+	}
+
+#ifdef CONFIG_XEN
+	/* Ensure that ballooned highmem pages don't have kmaps. */
+	kmap_flush_unused();
+	flush_tlb_all();
+#endif
+
+	balloon_lock(flags);
+
+	/* No more mappings: invalidate P2M and add to balloon. */
+	for (i = 0; i < nr_pages; i++) {
+		pfn = mfn_to_pfn(frame_list[i]);
+		balloon_append(pfn_to_page(pfn), 1);
+	}
+
+	set_xen_guest_handle(reservation.extent_start, frame_list);
+	reservation.nr_extents   = nr_pages;
+	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+	BUG_ON(ret != nr_pages);
+
+	bs.current_pages -= nr_pages;
+	totalram_pages = bs.current_pages;
+
+	balloon_unlock(flags);
+
+	return need_sleep;
+}
+
+/*
+ * We avoid multiple worker processes conflicting via the balloon mutex.
+ * We may of course race updates of the target counts (which are protected
+ * by the balloon lock), or with changes to the Xen hard limit, but we will
+ * recover from these in time.
+ */
+static void balloon_process(struct work_struct *unused)
+{
+	int need_sleep = 0;
+	long credit;
+
+	mutex_lock(&balloon_mutex);
+
+	do {
+		credit = current_target() - bs.current_pages;
+		if (credit > 0)
+			need_sleep = (increase_reservation(credit) != 0);
+		if (credit < 0)
+			need_sleep = (decrease_reservation(-credit) != 0);
+
+#ifndef CONFIG_PREEMPT
+		if (need_resched())
+			schedule();
+#endif
+	} while ((credit != 0) && !need_sleep);
+
+	/* Schedule more work if there is some still to be done. */
+	if (current_target() != bs.current_pages)
+		mod_timer(&balloon_timer, jiffies + HZ);
+
+	mutex_unlock(&balloon_mutex);
+}
+
+/* Resets the Xen limit, sets new target, and kicks off processing. */
+void balloon_set_new_target(unsigned long target)
+{
+	/* No need for lock. Not read-modify-write updates. */
+	bs.target_pages = max(target, balloon_minimum_target());
+	schedule_work(&balloon_worker);
+}
+
+static struct xenbus_watch target_watch =
+{
+	.node = "memory/target"
+};
+
+/* React to a change in the target key */
+static void watch_target(struct xenbus_watch *watch,
+			 const char **vec, unsigned int len)
+{
+	unsigned long long new_target;
+	int err;
+
+	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
+	if (err != 1) {
+		/* This is ok (for domain0 at least) - so just return */
+		return;
+	}
+
+	/* The given memory/target value is in KiB, so it needs converting to
+	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
+	 */
+	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
+}
+
+static int balloon_init_watcher(struct notifier_block *notifier,
+				unsigned long event,
+				void *data)
+{
+	int err;
+
+	err = register_xenbus_watch(&target_watch);
+	if (err)
+		printk(KERN_ERR "Failed to set balloon watcher\n");
+
+	return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_PROC_FS
+static int balloon_write(struct file *file, const char __user *buffer,
+			 unsigned long count, void *data)
+{
+	char memstring[64], *endchar;
+	unsigned long long target_bytes;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (count <= 1)
+		return -EBADMSG; /* runt */
+	if (count > sizeof(memstring))
+		return -EFBIG;   /* too long */
+
+	if (copy_from_user(memstring, buffer, count))
+		return -EFAULT;
+	memstring[sizeof(memstring)-1] = '\0';
+
+	target_bytes = memparse(memstring, &endchar);
+	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+
+	return count;
+}
+
+static int balloon_read(char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(
+		page,
+		"Current allocation: %8lu kB\n"
+		"Requested target:   %8lu kB\n"
+		"Minimum target:     %8lu kB\n"
+		"Maximum target:     %8lu kB\n"
+		"Low-mem balloon:    %8lu kB\n"
+		"High-mem balloon:   %8lu kB\n"
+		"Driver pages:       %8lu kB\n",
+		PAGES2KB(bs.current_pages), PAGES2KB(bs.target_pages), 
+		PAGES2KB(balloon_minimum_target()), PAGES2KB(num_physpages),
+		PAGES2KB(bs.balloon_low), PAGES2KB(bs.balloon_high),
+		PAGES2KB(bs.driver_pages));
+
+
+	*eof = 1;
+	return len;
+}
+#endif
+
+static struct notifier_block xenstore_notifier;
+
+static int __init balloon_init(void)
+{
+#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
+	unsigned long pfn;
+	struct page *page;
+#endif
+
+	if (!is_running_on_xen())
+		return -ENODEV;
+
+	IPRINTK("Initialising balloon driver.\n");
+
+#ifdef CONFIG_XEN
+	pagevec_init(&free_pagevec, true);
+	bs.current_pages = min(xen_start_info->nr_pages, max_pfn);
+	totalram_pages   = bs.current_pages;
+#else 
+	bs.current_pages = totalram_pages; 
+#endif
+	bs.target_pages  = bs.current_pages;
+	bs.balloon_low   = 0;
+	bs.balloon_high  = 0;
+	bs.driver_pages  = 0UL;
+
+	init_timer(&balloon_timer);
+	balloon_timer.data = 0;
+	balloon_timer.function = balloon_alarm;
+    
+#ifdef CONFIG_PROC_FS
+	if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) {
+		WPRINTK("Unable to create /proc/xen/balloon.\n");
+		return -1;
+	}
+
+	balloon_pde->read_proc  = balloon_read;
+	balloon_pde->write_proc = balloon_write;
+#endif
+	balloon_sysfs_init();
+
+#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
+	/* Initialise the balloon with excess memory space. */
+	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+		page = pfn_to_page(pfn);
+		if (!PageReserved(page)) {
+			SetPageReserved(page);
+			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+			balloon_append(page, 0);
+		}
+	}
+#endif
+
+	target_watch.callback = watch_target;
+	xenstore_notifier.notifier_call = balloon_init_watcher;
+
+	register_xenstore_notifier(&xenstore_notifier);
+    
+	return 0;
+}
+
+subsys_initcall(balloon_init);
+
+static void __exit balloon_exit(void)
+{
+	balloon_sysfs_exit();
+	/* XXX - release balloon here */
+}
+
+module_exit(balloon_exit); 
+
+void balloon_update_driver_allowance(long delta)
+{
+	unsigned long flags;
+
+	balloon_lock(flags);
+	bs.driver_pages += delta;
+	balloon_unlock(flags);
+}
+
+#ifdef CONFIG_XEN
+static int dealloc_pte_fn(
+	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+	unsigned long pfn, mfn = pte_mfn(*pte);
+	int ret;
+	struct xen_memory_reservation reservation = {
+		.nr_extents   = 1,
+		.extent_order = 0,
+		.domid        = DOMID_SELF
+	};
+	set_xen_guest_handle(reservation.extent_start, &mfn);
+	set_pte_at(&init_mm, addr, pte, __pte_ma(0));
+	pfn = __pa(addr) >> PAGE_SHIFT;
+	set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+	SetPageReserved(pfn_to_page(pfn));
+	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+	BUG_ON(ret != 1);
+	return 0;
+}
+#endif
+
+struct page **alloc_empty_pages_and_pagevec(int nr_pages)
+{
+	unsigned long flags;
+	void *v;
+	struct page *page, **pagevec;
+	int i, ret;
+
+	pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
+	if (pagevec == NULL)
+		return NULL;
+
+	for (i = 0; i < nr_pages; i++) {
+		page = pagevec[i] = alloc_page(GFP_KERNEL|__GFP_COLD);
+		if (page == NULL)
+			goto err;
+
+		v = page_address(page);
+		scrub_pages(v, 1);
+
+		balloon_lock(flags);
+
+		if (xen_feature(XENFEAT_auto_translated_physmap)) {
+			unsigned long gmfn = page_to_pfn(page);
+			struct xen_memory_reservation reservation = {
+				.nr_extents   = 1,
+				.extent_order = 0,
+				.domid        = DOMID_SELF
+			};
+			set_xen_guest_handle(reservation.extent_start, &gmfn);
+			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+						   &reservation);
+			if (ret == 1)
+				ret = 0; /* success */
+		} else {
+#ifdef CONFIG_XEN
+			ret = apply_to_page_range(&init_mm, (unsigned long)v,
+						  PAGE_SIZE, dealloc_pte_fn,
+						  NULL);
+#else
+			/* Cannot handle non-auto translate mode. */
+			ret = 1;
+#endif
+		}
+
+		if (ret != 0) {
+			balloon_free_page(page);
+			balloon_free_and_unlock(flags);
+			goto err;
+		}
+
+		totalram_pages = --bs.current_pages;
+		if (PageHighMem(page))
+			dec_totalhigh_pages();
+		page_zone(page)->present_pages--;
+
+		balloon_unlock(flags);
+	}
+
+ out:
+	schedule_work(&balloon_worker);
+#ifdef CONFIG_XEN
+	flush_tlb_all();
+#endif
+	return pagevec;
+
+ err:
+	balloon_lock(flags);
+	while (--i >= 0)
+		balloon_append(pagevec[i], 0);
+	balloon_unlock(flags);
+	kfree(pagevec);
+	pagevec = NULL;
+	goto out;
+}
+
+static void _free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages,
+					  int free_vec)
+{
+	unsigned long flags;
+	int i;
+
+	if (pagevec == NULL)
+		return;
+
+	balloon_lock(flags);
+	for (i = 0; i < nr_pages; i++) {
+		BUG_ON(page_count(pagevec[i]) != 1);
+		balloon_append(pagevec[i], !free_vec);
+	}
+	if (!free_vec)
+		totalram_pages = bs.current_pages -= nr_pages;
+	balloon_unlock(flags);
+
+	if (free_vec)
+		kfree(pagevec);
+
+	schedule_work(&balloon_worker);
+}
+
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
+{
+	_free_empty_pages_and_pagevec(pagevec, nr_pages, 1);
+}
+
+void free_empty_pages(struct page **pagevec, int nr_pages)
+{
+	_free_empty_pages_and_pagevec(pagevec, nr_pages, 0);
+}
+
+void balloon_release_driver_page(struct page *page)
+{
+	unsigned long flags;
+
+	balloon_lock(flags);
+	balloon_append(page, 1);
+	bs.driver_pages--;
+	balloon_unlock(flags);
+
+	schedule_work(&balloon_worker);
+}
+
+EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
+EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(balloon_release_driver_page);
+
+MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/drivers/xen/scsifront/scsifront.c
+++ linux-ec2-2.6.32/drivers/xen/scsifront/scsifront.c
@@ -0,0 +1,478 @@
+/*
+ * 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)
+{
+	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;
+	scsi_set_resid(sc, 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, ref, ref_cnt = 0;
+	int write = (sc->sc_data_direction == DMA_TO_DEVICE);
+	unsigned int i, nr_pages, off, len, bytes;
+	unsigned long buffer_pfn;
+
+	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 (scsi_bufflen(sc)) {
+		/* quoted scsi_lib.c/scsi_req_map_sg . */
+		struct scatterlist *sg, *sgl = scsi_sglist(sc);
+		unsigned int data_len = scsi_bufflen(sc);
+
+		nr_pages = (data_len + sgl->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_each_sg (sgl, sg, scsi_sg_count(sc), i) {
+			page = sg_page(sg);
+			off = sg->offset;
+			len = sg->length;
+
+			buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
+
+			while (len > 0 && data_len > 0) {
+				/*
+				 * sg sends a scatterlist that is larger than
+				 * the data_len it wants transferred for certain
+				 * IO sizes
+				 */
+				bytes = min_t(unsigned int, len, PAGE_SIZE - off);
+				bytes = min(bytes, data_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[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;
+				data_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->request->timeout / 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->request->timeout / 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");
--- linux-ec2-2.6.32.orig/drivers/xen/scsifront/common.h
+++ linux-ec2-2.6.32/drivers/xen/scsifront/common.h
@@ -0,0 +1,136 @@
+/*
+ * 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 <xen/interface/grant_table.h>
+#include <xen/interface/io/protocols.h>
+#include <asm/delay.h>
+#include <asm/hypervisor.h>
+#include <asm/maddr.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#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);
+int scsifront_cmd_done(struct vscsifrnt_info *info);
+
+
+#endif /* __XEN_DRIVERS_SCSIFRONT_H__  */
--- linux-ec2-2.6.32.orig/drivers/xen/scsifront/Makefile
+++ linux-ec2-2.6.32/drivers/xen/scsifront/Makefile
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_XEN_SCSI_FRONTEND)	:= xenscsi.o
+xenscsi-objs := scsifront.o xenbus.o
--- linux-ec2-2.6.32.orig/drivers/xen/scsifront/xenbus.c
+++ linux-ec2-2.6.32/drivers/xen/scsifront/xenbus.c
@@ -0,0 +1,420 @@
+/*
+ * 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,
+			IRQF_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_set_drvdata(&dev->dev, 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_get_drvdata(&dev->dev);
+
+	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_get_drvdata(&dev->dev);
+
+	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",
+	.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);
+}
+
--- linux-ec2-2.6.32.orig/drivers/ide/ide-cd.c
+++ linux-ec2-2.6.32/drivers/ide/ide-cd.c
@@ -506,15 +506,22 @@
 	return (flags & REQ_FAILED) ? -EIO : 0;
 }
 
-static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
+/*
+ * returns true if rq has been completed
+ */
+static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
 {
 	unsigned int nr_bytes = cmd->nbytes - cmd->nleft;
 
 	if (cmd->tf_flags & IDE_TFLAG_WRITE)
 		nr_bytes -= cmd->last_xfer_len;
 
-	if (nr_bytes > 0)
+	if (nr_bytes > 0) {
 		ide_complete_rq(drive, 0, nr_bytes);
+		return true;
+	}
+
+	return false;
 }
 
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
@@ -679,7 +686,8 @@
 		}
 
 		if (uptodate == 0 && rq->bio)
-			ide_cd_error_cmd(drive, cmd);
+			if (ide_cd_error_cmd(drive, cmd))
+				return ide_stopped;
 
 		/* make sure it's fully ended */
 		if (blk_fs_request(rq) == 0) {
--- linux-ec2-2.6.32.orig/drivers/ide/ide-taskfile.c
+++ linux-ec2-2.6.32/drivers/ide/ide-taskfile.c
@@ -428,13 +428,11 @@
 {
 	struct request *rq;
 	int error;
+	int rw = !(cmd->tf_flags & IDE_TFLAG_WRITE) ? READ : WRITE;
 
-	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+	rq = blk_get_request(drive->queue, rw, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
 
-	if (cmd->tf_flags & IDE_TFLAG_WRITE)
-		rq->cmd_flags |= REQ_RW;
-
 	/*
 	 * (ks) We transfer currently only whole sectors.
 	 * This is suffient for now.  But, it would be great,
--- linux-ec2-2.6.32.orig/drivers/ide/slc90e66.c
+++ linux-ec2-2.6.32/drivers/ide/slc90e66.c
@@ -91,8 +91,7 @@
 
 		if (!(reg48 & u_flag))
 			pci_write_config_word(dev, 0x48, reg48|u_flag);
-		/* FIXME: (reg4a & a_speed) ? */
-		if ((reg4a & u_speed) != u_speed) {
+		if ((reg4a & a_speed) != u_speed) {
 			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 			pci_read_config_word(dev, 0x4a, &reg4a);
 			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
--- linux-ec2-2.6.32.orig/drivers/ide/cmd640.c
+++ linux-ec2-2.6.32/drivers/ide/cmd640.c
@@ -632,12 +632,10 @@
 
 static int cmd640_test_irq(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
-	u8  irq_stat, irq_mask	= hwif->channel ? ARTTIM23_IDE23INTR :
+	u8  irq_mask		= hwif->channel ? ARTTIM23_IDE23INTR :
 						  CFR_IDE01INTR;
-
-	pci_read_config_byte(dev, irq_reg, &irq_stat);
+	u8  irq_stat		= get_cmd640_reg(irq_reg);
 
 	return (irq_stat & irq_mask) ? 1 : 0;
 }
--- linux-ec2-2.6.32.orig/drivers/ide/ide-lib.c
+++ linux-ec2-2.6.32/drivers/ide/ide-lib.c
@@ -18,6 +18,7 @@
 {
 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
 
+#ifndef CONFIG_XEN
 	if (!PCI_DMA_BUS_IS_PHYS) {
 		addr = BLK_BOUNCE_ANY;
 	} else if (on && drive->media == ide_disk) {
@@ -26,6 +27,16 @@
 		if (dev && dev->dma_mask)
 			addr = *dev->dma_mask;
 	}
+#else
+	if (on && drive->media == ide_disk) {
+		struct device *dev = drive->hwif->dev;
+
+		if (!PCI_DMA_BUS_IS_PHYS)
+			addr = BLK_BOUNCE_ANY;
+		else if (dev && dev->dma_mask)
+			addr = *dev->dma_mask;
+	}
+#endif
 
 	if (drive->queue)
 		blk_queue_bounce_limit(drive->queue, addr);
--- linux-ec2-2.6.32.orig/drivers/regulator/core.c
+++ linux-ec2-2.6.32/drivers/regulator/core.c
@@ -640,7 +640,7 @@
 static void print_constraints(struct regulator_dev *rdev)
 {
 	struct regulation_constraints *constraints = rdev->constraints;
-	char buf[80];
+	char buf[80] = "";
 	int count;
 
 	if (rdev->desc->type == REGULATOR_VOLTAGE) {
--- linux-ec2-2.6.32.orig/drivers/regulator/wm8350-regulator.c
+++ linux-ec2-2.6.32/drivers/regulator/wm8350-regulator.c
@@ -1504,7 +1504,8 @@
 	led->isink_init.consumer_supplies = &led->isink_consumer;
 	led->isink_init.constraints.min_uA = 0;
 	led->isink_init.constraints.max_uA = pdata->max_uA;
-	led->isink_init.constraints.valid_ops_mask = REGULATOR_CHANGE_CURRENT;
+	led->isink_init.constraints.valid_ops_mask
+		= REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS;
 	led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
 	ret = wm8350_register_regulator(wm8350, isink, &led->isink_init);
 	if (ret != 0) {
@@ -1517,6 +1518,7 @@
 	led->dcdc_init.num_consumer_supplies = 1;
 	led->dcdc_init.consumer_supplies = &led->dcdc_consumer;
 	led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
+	led->dcdc_init.constraints.valid_ops_mask =  REGULATOR_CHANGE_STATUS;
 	ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init);
 	if (ret != 0) {
 		platform_device_put(pdev);
--- linux-ec2-2.6.32.orig/drivers/edac/Kconfig
+++ linux-ec2-2.6.32/drivers/edac/Kconfig
@@ -72,6 +72,7 @@
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
 	depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
+	depends on !XEN
 	help
 	  Support for error detection and correction on the AMD 64
 	  Families of Memory Controllers (K8, F10h and F11h)
--- linux-ec2-2.6.32.orig/drivers/edac/edac_mc.c
+++ linux-ec2-2.6.32/drivers/edac/edac_mc.c
@@ -578,6 +578,10 @@
 
 	debugf3("%s()\n", __func__);
 
+#ifdef CONFIG_XEN
+	page = mfn_to_local_pfn(page);
+#endif
+
 	/* ECC error page was not in our memory. Ignore it. */
 	if (!pfn_valid(page))
 		return;
--- linux-ec2-2.6.32.orig/drivers/edac/amd64_edac.c
+++ linux-ec2-2.6.32/drivers/edac/amd64_edac.c
@@ -13,6 +13,8 @@
 static int ecc_enable_override;
 module_param(ecc_enable_override, int, 0644);
 
+static struct msr *msrs;
+
 /* Lookup table for all possible MC control instances */
 struct amd64_pvt;
 static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES];
@@ -154,7 +156,7 @@
 
 	default:
 		amd64_printk(KERN_ERR, "Unsupported family!\n");
-		break;
+		return -EINVAL;
 	}
 	return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth,
 			min_scrubrate);
@@ -1489,7 +1491,7 @@
 	u64 chan_off;
 
 	if (hi_range_sel) {
-		if (!(dct_sel_base_addr & 0xFFFFF800) &&
+		if (!(dct_sel_base_addr & 0xFFFF0000) &&
 		   hole_valid && (sys_addr >= 0x100000000ULL))
 			chan_off = hole_off << 16;
 		else
@@ -1626,7 +1628,7 @@
 	debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
 			hole_off, hole_valid, intlv_sel);
 
-	if (intlv_en ||
+	if (intlv_en &&
 	    (intlv_sel != ((sys_addr >> 12) & intlv_en)))
 		return -EINVAL;
 
@@ -2618,6 +2620,90 @@
 	return empty;
 }
 
+/* get all cores on this DCT */
+static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		if (amd_get_nb_id(cpu) == nid)
+			cpumask_set_cpu(cpu, mask);
+}
+
+/* check MCG_CTL on all the cpus on this node */
+static bool amd64_nb_mce_bank_enabled_on_node(int nid)
+{
+	cpumask_var_t mask;
+	int cpu, nbe;
+	bool ret = false;
+
+	if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
+		amd64_printk(KERN_WARNING, "%s: error allocating mask\n",
+			     __func__);
+		return false;
+	}
+
+	get_cpus_on_this_dct_cpumask(mask, nid);
+
+	rdmsr_on_cpus(mask, MSR_IA32_MCG_CTL, msrs);
+
+	for_each_cpu(cpu, mask) {
+		struct msr *reg = per_cpu_ptr(msrs, cpu);
+		nbe = reg->l & K8_MSR_MCGCTL_NBE;
+
+		debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
+			cpu, reg->q,
+			(nbe ? "enabled" : "disabled"));
+
+		if (!nbe)
+			goto out;
+	}
+	ret = true;
+
+out:
+	free_cpumask_var(mask);
+	return ret;
+}
+
+static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
+{
+	cpumask_var_t cmask;
+	int cpu;
+
+	if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) {
+		amd64_printk(KERN_WARNING, "%s: error allocating mask\n",
+			     __func__);
+		return false;
+	}
+
+	get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id);
+
+	rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
+
+	for_each_cpu(cpu, cmask) {
+
+		struct msr *reg = per_cpu_ptr(msrs, cpu);
+
+		if (on) {
+			if (reg->l & K8_MSR_MCGCTL_NBE)
+				pvt->flags.ecc_report = 1;
+
+			reg->l |= K8_MSR_MCGCTL_NBE;
+		} else {
+			/*
+			 * Turn off ECC reporting only when it was off before
+			 */
+			if (!pvt->flags.ecc_report)
+				reg->l &= ~K8_MSR_MCGCTL_NBE;
+		}
+	}
+	wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
+
+	free_cpumask_var(cmask);
+
+	return 0;
+}
+
 /*
  * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we"
  * enable it.
@@ -2625,17 +2711,12 @@
 static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id);
-	int cpu, idx = 0, err = 0;
-	struct msr msrs[cpumask_weight(cpumask)];
-	u32 value;
-	u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	int err = 0;
+	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
 
 	if (!ecc_enable_override)
 		return;
 
-	memset(msrs, 0, sizeof(msrs));
-
 	amd64_printk(KERN_WARNING,
 		"'ecc_enable_override' parameter is active, "
 		"Enabling AMD ECC hardware now: CAUTION\n");
@@ -2651,16 +2732,9 @@
 	value |= mask;
 	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
 
-	rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
-
-	for_each_cpu(cpu, cpumask) {
-		if (msrs[idx].l & K8_MSR_MCGCTL_NBE)
-			set_bit(idx, &pvt->old_mcgctl);
-
-		msrs[idx].l |= K8_MSR_MCGCTL_NBE;
-		idx++;
-	}
-	wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
+	if (amd64_toggle_ecc_err_reporting(pvt, ON))
+		amd64_printk(KERN_WARNING, "Error enabling ECC reporting over "
+					   "MCGCTL!\n");
 
 	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value);
 	if (err)
@@ -2701,17 +2775,12 @@
 
 static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt)
 {
-	const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id);
-	int cpu, idx = 0, err = 0;
-	struct msr msrs[cpumask_weight(cpumask)];
-	u32 value;
-	u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	int err = 0;
+	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
 
 	if (!pvt->nbctl_mcgctl_saved)
 		return;
 
-	memset(msrs, 0, sizeof(msrs));
-
 	err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value);
 	if (err)
 		debugf0("Reading K8_NBCTL failed\n");
@@ -2721,66 +2790,9 @@
 	/* restore the NB Enable MCGCTL bit */
 	pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value);
 
-	rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
-
-	for_each_cpu(cpu, cpumask) {
-		msrs[idx].l &= ~K8_MSR_MCGCTL_NBE;
-		msrs[idx].l |=
-			test_bit(idx, &pvt->old_mcgctl) << K8_MSR_MCGCTL_NBE;
-		idx++;
-	}
-
-	wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs);
-}
-
-/* get all cores on this DCT */
-static void get_cpus_on_this_dct_cpumask(cpumask_t *mask, int nid)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu)
-		if (amd_get_nb_id(cpu) == nid)
-			cpumask_set_cpu(cpu, mask);
-}
-
-/* check MCG_CTL on all the cpus on this node */
-static bool amd64_nb_mce_bank_enabled_on_node(int nid)
-{
-	cpumask_t mask;
-	struct msr *msrs;
-	int cpu, nbe, idx = 0;
-	bool ret = false;
-
-	cpumask_clear(&mask);
-
-	get_cpus_on_this_dct_cpumask(&mask, nid);
-
-	msrs = kzalloc(sizeof(struct msr) * cpumask_weight(&mask), GFP_KERNEL);
-	if (!msrs) {
-		amd64_printk(KERN_WARNING, "%s: error allocating msrs\n",
-			      __func__);
-		 return false;
-	}
-
-	rdmsr_on_cpus(&mask, MSR_IA32_MCG_CTL, msrs);
-
-	for_each_cpu(cpu, &mask) {
-		nbe = msrs[idx].l & K8_MSR_MCGCTL_NBE;
-
-		debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
-			cpu, msrs[idx].q,
-			(nbe ? "enabled" : "disabled"));
-
-		if (!nbe)
-			goto out;
-
-		idx++;
-	}
-	ret = true;
-
-out:
-	kfree(msrs);
-	return ret;
+	if (amd64_toggle_ecc_err_reporting(pvt, OFF))
+		amd64_printk(KERN_WARNING, "Error restoring ECC reporting over "
+					   "MCGCTL!\n");
 }
 
 /*
@@ -2789,10 +2801,11 @@
  * the memory system completely. A command line option allows to force-enable
  * hardware ECC later in amd64_enable_ecc_error_reporting().
  */
-static const char *ecc_warning =
-	"WARNING: ECC is disabled by BIOS. Module will NOT be loaded.\n"
-	" Either Enable ECC in the BIOS, or set 'ecc_enable_override'.\n"
-	" Also, use of the override can cause unknown side effects.\n";
+static const char *ecc_msg =
+	"ECC disabled in the BIOS or no ECC capability, module will not load.\n"
+	" Either enable ECC checking or force module loading by setting "
+	"'ecc_enable_override'.\n"
+	" (Note that use of the override may cause unknown side effects.)\n";
 
 static int amd64_check_ecc_enabled(struct amd64_pvt *pvt)
 {
@@ -2807,7 +2820,7 @@
 
 	ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE);
 	if (!ecc_enabled)
-		amd64_printk(KERN_WARNING, "This node reports that Memory ECC "
+		amd64_printk(KERN_NOTICE, "This node reports that Memory ECC "
 			     "is currently disabled, set F3x%x[22] (%s).\n",
 			     K8_NBCFG, pci_name(pvt->misc_f3_ctl));
 	else
@@ -2815,18 +2828,17 @@
 
 	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(pvt->mc_node_id);
 	if (!nb_mce_en)
-		amd64_printk(KERN_WARNING, "NB MCE bank disabled, set MSR "
+		amd64_printk(KERN_NOTICE, "NB MCE bank disabled, set MSR "
 			     "0x%08x[4] on node %d to enable.\n",
 			     MSR_IA32_MCG_CTL, pvt->mc_node_id);
 
 	if (!ecc_enabled || !nb_mce_en) {
 		if (!ecc_enable_override) {
-			amd64_printk(KERN_WARNING, "%s", ecc_warning);
+			amd64_printk(KERN_NOTICE, "%s", ecc_msg);
 			return -ENODEV;
 		}
-	} else
-		/* CLEAR the override, since BIOS controlled it */
 		ecc_enable_override = 0;
+	}
 
 	return 0;
 }
@@ -2909,7 +2921,6 @@
 	pvt->ext_model		= boot_cpu_data.x86_model >> 4;
 	pvt->mc_type_index	= mc_type_index;
 	pvt->ops		= family_ops(mc_type_index);
-	pvt->old_mcgctl		= 0;
 
 	/*
 	 * We have the dram_f2_ctl device as an argument, now go reserve its
@@ -3071,16 +3082,15 @@
 
 	amd64_free_mc_sibling_devices(pvt);
 
-	kfree(pvt);
-	mci->pvt_info = NULL;
-
-	mci_lookup[pvt->mc_node_id] = NULL;
-
 	/* unregister from EDAC MCE */
 	amd_report_gart_errors(false);
 	amd_unregister_ecc_decoder(amd64_decode_bus_error);
 
 	/* Free the EDAC CORE resources */
+	mci->pvt_info = NULL;
+	mci_lookup[pvt->mc_node_id] = NULL;
+
+	kfree(pvt);
 	edac_mc_free(mci);
 }
 
@@ -3157,23 +3167,29 @@
 static int __init amd64_edac_init(void)
 {
 	int nb, err = -ENODEV;
+	bool load_ok = false;
 
 	edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
 
 	opstate_init();
 
 	if (cache_k8_northbridges() < 0)
-		return err;
+		goto err_ret;
+
+	msrs = msrs_alloc();
+	if (!msrs)
+		goto err_ret;
 
 	err = pci_register_driver(&amd64_pci_driver);
 	if (err)
-		return err;
+		goto err_pci;
 
 	/*
 	 * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd
 	 * amd64_pvt structs. These will be used in the 2nd stage init function
 	 * to finish initialization of the MC instances.
 	 */
+	err = -ENODEV;
 	for (nb = 0; nb < num_k8_northbridges; nb++) {
 		if (!pvt_lookup[nb])
 			continue;
@@ -3181,16 +3197,21 @@
 		err = amd64_init_2nd_stage(pvt_lookup[nb]);
 		if (err)
 			goto err_2nd_stage;
-	}
 
-	amd64_setup_pci_device();
+		load_ok = true;
+	}
 
-	return 0;
+	if (load_ok) {
+		amd64_setup_pci_device();
+		return 0;
+	}
 
 err_2nd_stage:
-	debugf0("2nd stage failed\n");
 	pci_unregister_driver(&amd64_pci_driver);
-
+err_pci:
+	msrs_free(msrs);
+	msrs = NULL;
+err_ret:
 	return err;
 }
 
@@ -3200,6 +3221,9 @@
 		edac_pci_release_generic_ctl(amd64_ctl_pci);
 
 	pci_unregister_driver(&amd64_pci_driver);
+
+	msrs_free(msrs);
+	msrs = NULL;
 }
 
 module_init(amd64_edac_init);
--- linux-ec2-2.6.32.orig/drivers/edac/i5000_edac.c
+++ linux-ec2-2.6.32/drivers/edac/i5000_edac.c
@@ -577,7 +577,13 @@
 		debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
 
 		branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
-		channel = branch;
+
+		/*
+		 * According with i5000 datasheet, bit 28 has no significance
+		 * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD
+		 */
+		channel = branch & 2;
+
 		bank = NREC_BANK(info->nrecmema);
 		rank = NREC_RANK(info->nrecmema);
 		rdwr = NREC_RDWR(info->nrecmema);
--- linux-ec2-2.6.32.orig/drivers/edac/edac_mce_amd.c
+++ linux-ec2-2.6.32/drivers/edac/edac_mce_amd.c
@@ -295,7 +295,6 @@
 void amd_decode_nb_mce(int node_id, struct err_regs *regs, int handle_errors)
 {
 	u32 ec  = ERROR_CODE(regs->nbsl);
-	u32 xec = EXT_ERROR_CODE(regs->nbsl);
 
 	if (!handle_errors)
 		return;
@@ -311,11 +310,15 @@
 		if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
 			pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
 	} else {
-		pr_cont(", core: %d\n", ilog2((regs->nbsh & 0xf)));
-	}
+		u8 assoc_cpus = regs->nbsh & 0xf;
+
+		if (assoc_cpus > 0)
+			pr_cont(", core: %d", fls(assoc_cpus) - 1);
 
+		pr_cont("\n");
+	}
 
-	pr_emerg("%s.\n", EXT_ERR_MSG(xec));
+	pr_emerg("%s.\n", EXT_ERR_MSG(regs->nbsl));
 
 	if (BUS_ERROR(ec) && nb_bus_decoder)
 		nb_bus_decoder(node_id, regs);
@@ -378,7 +381,7 @@
 		 ((m->status & MCI_STATUS_PCC) ? "yes" : "no"));
 
 	/* do the two bits[14:13] together */
-	ecc = m->status & (3ULL << 45);
+	ecc = (m->status >> 45) & 0x3;
 	if (ecc)
 		pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U"));
 
--- linux-ec2-2.6.32.orig/drivers/edac/amd64_edac.h
+++ linux-ec2-2.6.32/drivers/edac/amd64_edac.h
@@ -147,6 +147,8 @@
 #define MAX_CS_COUNT			8
 #define DRAM_REG_COUNT			8
 
+#define ON true
+#define OFF false
 
 /*
  * PCI-defined configuration space registers
@@ -386,10 +388,7 @@
 #define K8_NBCAP_DUAL_NODE		BIT(1)
 #define K8_NBCAP_DCT_DUAL		BIT(0)
 
-/*
- * MSR Regs
- */
-#define K8_MSR_MCGCTL			0x017b
+/* MSRs */
 #define K8_MSR_MCGCTL_NBE		BIT(4)
 
 #define K8_MSR_MC4CTL			0x0410
@@ -487,7 +486,6 @@
 	/* Save old hw registers' values before we modified them */
 	u32 nbctl_mcgctl_saved;		/* When true, following 2 are valid */
 	u32 old_nbctl;
-	unsigned long old_mcgctl;	/* per core on this node */
 
 	/* MC Type Index value: socket F vs Family 10h */
 	u32 mc_type_index;
@@ -495,6 +493,7 @@
 	/* misc settings */
 	struct flags {
 		unsigned long cf8_extcfg:1;
+		unsigned long ecc_report:1;
 	} flags;
 };
 
--- linux-ec2-2.6.32.orig/drivers/media/dvb/ttpci/budget.c
+++ linux-ec2-2.6.32/drivers/media/dvb/ttpci/budget.c
@@ -643,9 +643,6 @@
 					&budget->i2c_adap,
 					&tt1600_isl6423_config);
 
-			} else {
-				dvb_frontend_detach(budget->dvb_frontend);
-				budget->dvb_frontend = NULL;
 			}
 		}
 		break;
--- linux-ec2-2.6.32.orig/drivers/media/dvb/ttpci/Kconfig
+++ linux-ec2-2.6.32/drivers/media/dvb/ttpci/Kconfig
@@ -68,13 +68,14 @@
 	select DVB_VES1820 if !DVB_FE_CUSTOMISE
 	select DVB_L64781 if !DVB_FE_CUSTOMISE
 	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
 	select DVB_S5H1420 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
 	select DVB_TDA826X if !DVB_FE_CUSTOMISE
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+	select DVB_ISL6423 if !DVB_FE_CUSTOMISE
+	select DVB_STV090x if !DVB_FE_CUSTOMISE
+	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	help
 	  Support for simple SAA7146 based DVB cards (so called Budget-
 	  or Nova-PCI cards) without onboard MPEG2 decoder, and without
--- linux-ec2-2.6.32.orig/drivers/media/dvb/ttpci/av7110_ca.c
+++ linux-ec2-2.6.32/drivers/media/dvb/ttpci/av7110_ca.c
@@ -277,7 +277,7 @@
 	{
 		ca_slot_info_t *info=(ca_slot_info_t *)parg;
 
-		if (info->num > 1)
+		if (info->num < 0 || info->num > 1)
 			return -EINVAL;
 		av7110->ci_slot[info->num].num = info->num;
 		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
--- linux-ec2-2.6.32.orig/drivers/media/dvb/dvb-core/dvb_net.c
+++ linux-ec2-2.6.32/drivers/media/dvb/dvb-core/dvb_net.c
@@ -350,6 +350,7 @@
 	const u8 *ts, *ts_end, *from_where = NULL;
 	u8 ts_remain = 0, how_much = 0, new_ts = 1;
 	struct ethhdr *ethh = NULL;
+	bool error = false;
 
 #ifdef ULE_DEBUG
 	/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
@@ -459,10 +460,16 @@
 
 						/* Drop partly decoded SNDU, reset state, resync on PUSI. */
 						if (priv->ule_skb) {
-							dev_kfree_skb( priv->ule_skb );
+							error = true;
+							dev_kfree_skb(priv->ule_skb);
+						}
+
+						if (error || priv->ule_sndu_remain) {
 							dev->stats.rx_errors++;
 							dev->stats.rx_frame_errors++;
+							error = false;
 						}
+
 						reset_ule(priv);
 						priv->need_pusi = 1;
 						continue;
@@ -504,6 +511,7 @@
 				       "bytes left in TS.  Resyncing.\n", ts_remain);
 				priv->ule_sndu_len = 0;
 				priv->need_pusi = 1;
+				ts += TS_SZ;
 				continue;
 			}
 
@@ -533,6 +541,7 @@
 				from_where += 2;
 			}
 
+			priv->ule_sndu_remain = priv->ule_sndu_len + 2;
 			/*
 			 * State of current TS:
 			 *   ts_remain (remaining bytes in the current TS cell)
@@ -542,6 +551,7 @@
 			 */
 			switch (ts_remain) {
 				case 1:
+					priv->ule_sndu_remain--;
 					priv->ule_sndu_type = from_where[0] << 8;
 					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
 					ts_remain -= 1; from_where += 1;
@@ -555,6 +565,7 @@
 				default: /* complete ULE header is present in current TS. */
 					/* Extract ULE type field. */
 					if (priv->ule_sndu_type_1) {
+						priv->ule_sndu_type_1 = 0;
 						priv->ule_sndu_type |= from_where[0];
 						from_where += 1; /* points to payload start. */
 						ts_remain -= 1;
--- linux-ec2-2.6.32.orig/drivers/media/dvb/dvb-core/dmxdev.c
+++ linux-ec2-2.6.32/drivers/media/dvb/dvb-core/dmxdev.c
@@ -761,7 +761,6 @@
 	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
 	dmxdevfilter->type = DMXDEV_TYPE_NONE;
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
-	INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
 	init_timer(&dmxdevfilter->timer);
 
 	dvbdev->users++;
@@ -887,6 +886,7 @@
 	dmxdevfilter->type = DMXDEV_TYPE_PES;
 	memcpy(&dmxdevfilter->params, params,
 	       sizeof(struct dmx_pes_filter_params));
+	INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
 
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
 
--- linux-ec2-2.6.32.orig/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ linux-ec2-2.6.32/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -874,6 +874,43 @@
 	{ 0x1d37, KEY_RECORD },
 	{ 0x1d3b, KEY_GOTO },
 	{ 0x1d3d, KEY_POWER },
+
+	/* Key codes for the Elgato EyeTV Diversity silver remote,
+	   set dvb_usb_dib0700_ir_proto=0 */
+	{ 0x4501, KEY_POWER },
+	{ 0x4502, KEY_MUTE },
+	{ 0x4503, KEY_1 },
+	{ 0x4504, KEY_2 },
+	{ 0x4505, KEY_3 },
+	{ 0x4506, KEY_4 },
+	{ 0x4507, KEY_5 },
+	{ 0x4508, KEY_6 },
+	{ 0x4509, KEY_7 },
+	{ 0x450a, KEY_8 },
+	{ 0x450b, KEY_9 },
+	{ 0x450c, KEY_LAST },
+	{ 0x450d, KEY_0 },
+	{ 0x450e, KEY_ENTER },
+	{ 0x450f, KEY_RED },
+	{ 0x4510, KEY_CHANNELUP },
+	{ 0x4511, KEY_GREEN },
+	{ 0x4512, KEY_VOLUMEDOWN },
+	{ 0x4513, KEY_OK },
+	{ 0x4514, KEY_VOLUMEUP },
+	{ 0x4515, KEY_YELLOW },
+	{ 0x4516, KEY_CHANNELDOWN },
+	{ 0x4517, KEY_BLUE },
+	{ 0x4518, KEY_LEFT }, /* Skip backwards */
+	{ 0x4519, KEY_PLAYPAUSE },
+	{ 0x451a, KEY_RIGHT }, /* Skip forward */
+	{ 0x451b, KEY_REWIND },
+	{ 0x451c, KEY_L }, /* Live */
+	{ 0x451d, KEY_FASTFORWARD },
+	{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
+	{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
+	{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
+	{ 0x4541, KEY_SCREEN }, /*  Full screen toggle, 'Hold' for Teletext */
+	{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
 };
 
 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@@ -1861,6 +1898,7 @@
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XPVR) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XP) },
 	{ USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
+	{ USB_DEVICE(USB_VID_ELGATO,    USB_PID_ELGATO_EYETV_DIVERSITY) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -2173,7 +2211,7 @@
 			}
 		},
 
-		.num_device_descs = 6,
+		.num_device_descs = 7,
 		.devices = {
 			{   "DiBcom STK7070PD reference design",
 				{ &dib0700_usb_id_table[17], NULL },
@@ -2199,7 +2237,11 @@
 			{  "Sony PlayTV",
 				{ &dib0700_usb_id_table[44], NULL },
 				{ NULL },
-			}
+			},
+			{   "Elgato EyeTV Diversity",
+				{ &dib0700_usb_id_table[64], NULL },
+				{ NULL },
+			},
 		},
 		.rc_interval      = DEFAULT_RC_INTERVAL,
 		.rc_key_map       = dib0700_rc_keys,
--- linux-ec2-2.6.32.orig/drivers/media/dvb/dvb-usb/Kconfig
+++ linux-ec2-2.6.32/drivers/media/dvb/dvb-usb/Kconfig
@@ -112,8 +112,8 @@
 	select DVB_MT352 if !DVB_FE_CUSTOMISE
 	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-	select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE
 	select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
+	select DVB_LGS8GXX if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
--- linux-ec2-2.6.32.orig/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ linux-ec2-2.6.32/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -271,6 +271,7 @@
 #define USB_PID_TELESTAR_STARSTICK_2			0x8000
 #define USB_PID_MSI_DIGI_VOX_MINI_III                   0x8807
 #define USB_PID_SONY_PLAYTV				0x0003
+#define USB_PID_ELGATO_EYETV_DIVERSITY			0x0011
 #define USB_PID_ELGATO_EYETV_DTT			0x0021
 #define USB_PID_ELGATO_EYETV_DTT_Dlx			0x0020
 #define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD		0x5000
--- linux-ec2-2.6.32.orig/drivers/media/dvb/frontends/l64781.c
+++ linux-ec2-2.6.32/drivers/media/dvb/frontends/l64781.c
@@ -192,8 +192,8 @@
 	spi_bias *= qam_tab[p->constellation];
 	spi_bias /= p->code_rate_HP + 1;
 	spi_bias /= (guard_tab[p->guard_interval] + 32);
-	spi_bias *= 1000ULL;
-	spi_bias /= 1000ULL + ppm/1000;
+	spi_bias *= 1000;
+	spi_bias /= 1000 + ppm/1000;
 	spi_bias *= p->code_rate_HP;
 
 	val0x04 = (p->transmission_mode << 2) | p->guard_interval;
--- linux-ec2-2.6.32.orig/drivers/media/dvb/siano/smsusb.c
+++ linux-ec2-2.6.32/drivers/media/dvb/siano/smsusb.c
@@ -533,8 +533,18 @@
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0xb910),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xb980),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xb990),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0xc000),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc010),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc080),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc090),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ } /* Terminating entry */
 	};
 
--- linux-ec2-2.6.32.orig/drivers/media/dvb/b2c2/flexcop-pci.c
+++ linux-ec2-2.6.32/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -38,7 +38,7 @@
 	DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_NAME "flexcop-pci"
 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 
 struct flexcop_pci {
--- linux-ec2-2.6.32.orig/drivers/media/common/tuners/mxl5007t.c
+++ linux-ec2-2.6.32/drivers/media/common/tuners/mxl5007t.c
@@ -196,7 +196,7 @@
 	i = j = 0;
 
 	while (reg_pair1[i].reg || reg_pair1[i].val) {
-		while (reg_pair2[j].reg || reg_pair2[j].reg) {
+		while (reg_pair2[j].reg || reg_pair2[j].val) {
 			if (reg_pair1[i].reg != reg_pair2[j].reg) {
 				j++;
 				continue;
--- linux-ec2-2.6.32.orig/drivers/media/radio/radio-aimslab.c
+++ linux-ec2-2.6.32/drivers/media/radio/radio-aimslab.c
@@ -31,7 +31,7 @@
 #include <linux/module.h>	/* Modules 			*/
 #include <linux/init.h>		/* Initdata			*/
 #include <linux/ioport.h>	/* request_region		*/
-#include <linux/delay.h>	/* udelay			*/
+#include <linux/delay.h>	/* msleep			*/
 #include <linux/videodev2.h>	/* kernel radio structs		*/
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
 #include <linux/io.h>		/* outb, outb_p			*/
@@ -71,27 +71,17 @@
 
 /* local things */
 
-static void sleep_delay(long n)
-{
-	/* Sleep nicely for 'n' uS */
-	int d = n / msecs_to_jiffies(1000);
-	if (!d)
-		udelay(n);
-	else
-		msleep(jiffies_to_msecs(d));
-}
-
 static void rt_decvol(struct rtrack *rt)
 {
 	outb(0x58, rt->io);		/* volume down + sigstr + on	*/
-	sleep_delay(100000);
+	msleep(100);
 	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
 static void rt_incvol(struct rtrack *rt)
 {
 	outb(0x98, rt->io);		/* volume up + sigstr + on	*/
-	sleep_delay(100000);
+	msleep(100);
 	outb(0xd8, rt->io);		/* volume steady + sigstr + on	*/
 }
 
@@ -120,7 +110,7 @@
 
 	if (vol == 0) {			/* volume = 0 means mute the card */
 		outb(0x48, rt->io);	/* volume down but still "on"	*/
-		sleep_delay(2000000);	/* make sure it's totally down	*/
+		msleep(2000);	/* make sure it's totally down	*/
 		outb(0xd0, rt->io);	/* volume steady, off		*/
 		rt->curvol = 0;		/* track the volume state!	*/
 		mutex_unlock(&rt->lock);
@@ -155,7 +145,7 @@
 		outb_p(128+64+16+8+  1, rt->io);  /* on + wr-enable + data low */
 		outb_p(128+64+16+8+2+1, rt->io);  /* clock */
 	}
-	sleep_delay(1000);
+	msleep(1);
 }
 
 static void send_1_byte(struct rtrack *rt)
@@ -169,7 +159,7 @@
 		outb_p(128+64+16+8+4+2+1, rt->io); /* clock */
 	}
 
-	sleep_delay(1000);
+	msleep(1);
 }
 
 static int rt_setfreq(struct rtrack *rt, unsigned long freq)
@@ -423,7 +413,7 @@
 
 	/* this ensures that the volume is all the way down  */
 	outb(0x48, rt->io);		/* volume down but still "on"	*/
-	sleep_delay(2000000);	/* make sure it's totally down	*/
+	msleep(2000);	/* make sure it's totally down	*/
 	outb(0xc0, rt->io);		/* steady volume, mute card	*/
 
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/media/video/ov511.c
+++ linux-ec2-2.6.32/drivers/media/video/ov511.c
@@ -5878,7 +5878,7 @@
 		goto error;
 	}
 
-	mutex_lock(&ov->lock);
+	mutex_unlock(&ov->lock);
 
 	return 0;
 
--- linux-ec2-2.6.32.orig/drivers/media/video/v4l2-compat-ioctl32.c
+++ linux-ec2-2.6.32/drivers/media/video/v4l2-compat-ioctl32.c
@@ -193,17 +193,24 @@
 struct video_code32 {
 	char		loadwhat[16];	/* name or tag of file being passed */
 	compat_int_t	datasize;
-	unsigned char	*data;
+	compat_uptr_t	data;
 };
 
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
-		copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
-		get_user(kp->datasize, &up->datasize) ||
-		copy_from_user(kp->data, up->data, up->datasize))
-			return -EFAULT;
-	return 0;
+	struct video_code __user *up;
+
+	up = compat_alloc_user_space(sizeof(*up));
+
+	/*
+	 * NOTE! We don't actually care if these fail. If the
+	 * user address is invalid, the native ioctl will do
+	 * the error handling for us
+	 */
+	(void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
+	(void) put_user(kp->datasize, &up->datasize);
+	(void) put_user(compat_ptr(kp->data), &up->data);
+	return up;
 }
 
 #define VIDIOCGTUNER32		_IOWR('v', 4, struct video_tuner32)
@@ -741,7 +748,7 @@
 		struct video_tuner vt;
 		struct video_buffer vb;
 		struct video_window vw;
-		struct video_code vc;
+		struct video_code32 vc;
 		struct video_audio va;
 #endif
 		struct v4l2_format v2f;
@@ -820,8 +827,11 @@
 		break;
 
 	case VIDIOCSMICROCODE:
-		err = get_microcode32(&karg.vc, up);
-		compatible_arg = 0;
+		/* Copy the 32-bit "video_code32" to kernel space */
+		if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
+			return -EFAULT;
+		/* Convert the 32-bit version to a 64-bit version in user space */
+		up = get_microcode32(&karg.vc);
 		break;
 
 	case VIDIOCSFREQ:
--- linux-ec2-2.6.32.orig/drivers/media/video/saa7134/saa7134-ts.c
+++ linux-ec2-2.6.32/drivers/media/video/saa7134/saa7134-ts.c
@@ -250,6 +250,19 @@
 
 	BUG_ON(dev->ts_started);
 
+	/* dma: setup channel 5 (= TS) */
+	saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
+	saa_writeb(SAA7134_TS_DMA1,
+		((dev->ts.nr_packets - 1) >> 8) & 0xff);
+	/* TSNOPIT=0, TSCOLAP=0 */
+	saa_writeb(SAA7134_TS_DMA2,
+		(((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
+	saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+	saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
+					  SAA7134_RS_CONTROL_ME |
+					  (dev->ts.pt_ts.dma >> 12));
+
+	/* reset hardware TS buffers */
 	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
 	saa_writeb(SAA7134_TS_SERIAL1, 0x03);
 	saa_writeb(SAA7134_TS_SERIAL1, 0x00);
--- linux-ec2-2.6.32.orig/drivers/media/video/saa7134/saa7134-dvb.c
+++ linux-ec2-2.6.32/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1116,6 +1116,7 @@
 		break;
 	case SAA7134_BOARD_PHILIPS_EUROPA:
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+	case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
 		fe0->dvb.frontend = dvb_attach(tda10046_attach,
 					       &philips_europa_config,
 					       &dev->i2c_adap);
--- linux-ec2-2.6.32.orig/drivers/media/video/saa7134/saa7134-cards.c
+++ linux-ec2-2.6.32/drivers/media/video/saa7134/saa7134-cards.c
@@ -5279,6 +5279,30 @@
 			.amux = TV,
 		},
 	},
+	[SAA7134_BOARD_ASUS_EUROPA_HYBRID] = {
+		.name           = "Asus Europa Hybrid OEM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TD1316,
+		.radio_type     = UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 4,
+			.amux   = LINE2,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+	},
 
 };
 
@@ -6418,6 +6442,12 @@
 		.subdevice    = 0x2004,
 		.driver_data  = SAA7134_BOARD_ZOLID_HYBRID_PCI,
 	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4847,
+		.driver_data  = SAA7134_BOARD_ASUS_EUROPA_HYBRID,
+	}, {
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -7079,6 +7109,7 @@
 		/* break intentionally omitted */
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
 	case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+	case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
 	{
 
 		/* The Philips EUROPA based hybrid boards have the tuner
--- linux-ec2-2.6.32.orig/drivers/media/video/saa7134/saa7134.h
+++ linux-ec2-2.6.32/drivers/media/video/saa7134/saa7134.h
@@ -297,6 +297,7 @@
 #define SAA7134_BOARD_BEHOLD_X7             171
 #define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172
 #define SAA7134_BOARD_ZOLID_HYBRID_PCI		173
+#define SAA7134_BOARD_ASUS_EUROPA_HYBRID	174
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
--- linux-ec2-2.6.32.orig/drivers/media/video/saa7134/saa7134-core.c
+++ linux-ec2-2.6.32/drivers/media/video/saa7134/saa7134-core.c
@@ -420,19 +420,6 @@
 		ctrl |= SAA7134_MAIN_CTRL_TE5;
 		irq  |= SAA7134_IRQ1_INTE_RA2_1 |
 			SAA7134_IRQ1_INTE_RA2_0;
-
-		/* dma: setup channel 5 (= TS) */
-
-		saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
-		saa_writeb(SAA7134_TS_DMA1,
-			((dev->ts.nr_packets - 1) >> 8) & 0xff);
-		/* TSNOPIT=0, TSCOLAP=0 */
-		saa_writeb(SAA7134_TS_DMA2,
-			(((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
-		saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
-		saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
-						  SAA7134_RS_CONTROL_ME |
-						  (dev->ts.pt_ts.dma >> 12));
 	}
 
 	/* set task conditions + field handling */
--- linux-ec2-2.6.32.orig/drivers/media/video/cx231xx/cx231xx-cards.c
+++ linux-ec2-2.6.32/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -225,14 +225,16 @@
 		     dev->board.name, dev->model);
 
 	/* set the direction for GPIO pins */
-	cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
-	cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
-	cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
+	if (dev->board.tuner_gpio) {
+		cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
+		cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
+		cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
 
-	/* request some modules if any required */
+		/* request some modules if any required */
 
-	/* reset the Tuner */
-	cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+		/* reset the Tuner */
+		cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+	}
 
 	/* set the mode to Analog mode initially */
 	cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
--- linux-ec2-2.6.32.orig/drivers/media/video/sn9c102/sn9c102_core.c
+++ linux-ec2-2.6.32/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1430,9 +1430,9 @@
 		   sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
 		   sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
+static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
+static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
+static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
 static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
 
 
--- linux-ec2-2.6.32.orig/drivers/media/video/gspca/mr97310a.c
+++ linux-ec2-2.6.32/drivers/media/video/gspca/mr97310a.c
@@ -530,6 +530,12 @@
 			{0x13, 0x00, {0x01}, 1},
 			{0, 0, {0}, 0}
 		};
+		/* Without this command the cam won't work with USB-UHCI */
+		gspca_dev->usb_buf[0] = 0x0a;
+		gspca_dev->usb_buf[1] = 0x00;
+		err_code = mr_write(gspca_dev, 2);
+		if (err_code < 0)
+			return err_code;
 		err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
 					 ARRAY_SIZE(cif_sensor1_init_data));
 	}
--- linux-ec2-2.6.32.orig/drivers/media/video/gspca/sunplus.c
+++ linux-ec2-2.6.32/drivers/media/video/gspca/sunplus.c
@@ -705,7 +705,7 @@
 		rc = spca504B_PollingDataReady(gspca_dev);
 
 		/* Init the cam width height with some values get on init ? */
-		reg_w_riv(dev, 0x31, 0, 0x04);
+		reg_w_riv(dev, 0x31, 0x04, 0);
 		spca504B_WaitCmdStatus(gspca_dev);
 		rc = spca504B_PollingDataReady(gspca_dev);
 		break;
@@ -807,14 +807,14 @@
 	default:
 /*	case BRIDGE_SPCA533: */
 /*	case BRIDGE_SPCA504B: */
-		reg_w_riv(dev, 0, 0x00, 0x21ad);	/* hue */
-		reg_w_riv(dev, 0, 0x01, 0x21ac);	/* sat/hue */
-		reg_w_riv(dev, 0, 0x00, 0x21a3);	/* gamma */
+		reg_w_riv(dev, 0, 0x21ad, 0x00);	/* hue */
+		reg_w_riv(dev, 0, 0x21ac, 0x01);	/* sat/hue */
+		reg_w_riv(dev, 0, 0x21a3, 0x00);	/* gamma */
 		break;
 	case BRIDGE_SPCA536:
-		reg_w_riv(dev, 0, 0x40, 0x20f5);
-		reg_w_riv(dev, 0, 0x01, 0x20f4);
-		reg_w_riv(dev, 0, 0x00, 0x2089);
+		reg_w_riv(dev, 0, 0x20f5, 0x40);
+		reg_w_riv(dev, 0, 0x20f4, 0x01);
+		reg_w_riv(dev, 0, 0x2089, 0x00);
 		break;
 	}
 	if (pollreg)
@@ -888,11 +888,11 @@
 	switch (sd->bridge) {
 	case BRIDGE_SPCA504B:
 		reg_w_riv(dev, 0x1d, 0x00, 0);
-		reg_w_riv(dev, 0, 0x01, 0x2306);
-		reg_w_riv(dev, 0, 0x00, 0x0d04);
-		reg_w_riv(dev, 0, 0x00, 0x2000);
-		reg_w_riv(dev, 0, 0x13, 0x2301);
-		reg_w_riv(dev, 0, 0x00, 0x2306);
+		reg_w_riv(dev, 0, 0x2306, 0x01);
+		reg_w_riv(dev, 0, 0x0d04, 0x00);
+		reg_w_riv(dev, 0, 0x2000, 0x00);
+		reg_w_riv(dev, 0, 0x2301, 0x13);
+		reg_w_riv(dev, 0, 0x2306, 0x00);
 		/* fall thru */
 	case BRIDGE_SPCA533:
 		spca504B_PollingDataReady(gspca_dev);
@@ -1011,7 +1011,7 @@
 			spca504B_WaitCmdStatus(gspca_dev);
 			break;
 		default:
-			reg_w_riv(dev, 0x31, 0, 0x04);
+			reg_w_riv(dev, 0x31, 0x04, 0);
 			spca504B_WaitCmdStatus(gspca_dev);
 			spca504B_PollingDataReady(gspca_dev);
 			break;
--- linux-ec2-2.6.32.orig/drivers/media/video/gspca/ov519.c
+++ linux-ec2-2.6.32/drivers/media/video/gspca/ov519.c
@@ -3364,6 +3364,7 @@
 	{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4064),
 	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+	{USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
 	{USB_DEVICE(0x041e, 0x4068),
 	 .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
 	{USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
--- linux-ec2-2.6.32.orig/drivers/media/video/gspca/sn9c20x.c
+++ linux-ec2-2.6.32/drivers/media/video/gspca/sn9c20x.c
@@ -2319,7 +2319,7 @@
 		}
 	}
 	if (avg_lum > MAX_AVG_LUM) {
-		if (sd->gain - 1 >= 0) {
+		if (sd->gain >= 1) {
 			sd->gain--;
 			set_gain(gspca_dev);
 		}
--- linux-ec2-2.6.32.orig/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ linux-ec2-2.6.32/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -497,8 +497,6 @@
 	{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
 	/* QuickCam Messenger (new) */
 	{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
-	/* QuickCam Messenger (new) */
-	{USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
--- linux-ec2-2.6.32.orig/drivers/media/video/uvc/uvcvideo.h
+++ linux-ec2-2.6.32/drivers/media/video/uvc/uvcvideo.h
@@ -112,6 +112,9 @@
 #define UVC_GUID_FORMAT_YUY2 \
 	{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2_ISIGHT \
+	{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_NV12 \
 	{ 'N',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
@@ -127,11 +130,13 @@
 #define UVC_GUID_FORMAT_Y800 \
 	{ 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y16 \
+	{ 'Y',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_BY8 \
 	{ 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
-
 /* ------------------------------------------------------------------------
  * Driver specific constants.
  */
--- linux-ec2-2.6.32.orig/drivers/media/video/uvc/uvc_ctrl.c
+++ linux-ec2-2.6.32/drivers/media/video/uvc/uvc_ctrl.c
@@ -826,6 +826,13 @@
 		ret = 0;
 		goto out;
 
+	case V4L2_CTRL_TYPE_BUTTON:
+		v4l2_ctrl->minimum = 0;
+		v4l2_ctrl->maximum = 0;
+		v4l2_ctrl->step = 0;
+		ret = 0;
+		goto out;
+
 	default:
 		break;
 	}
@@ -1405,7 +1412,7 @@
 	size = entity->processing.bControlSize;
 
 	for (i = 0; i < ARRAY_SIZE(blacklist); ++i) {
-		if (!usb_match_id(dev->intf, &blacklist[i].id))
+		if (!usb_match_one_id(dev->intf, &blacklist[i].id))
 			continue;
 
 		if (blacklist[i].index >= 8 * size ||
--- linux-ec2-2.6.32.orig/drivers/media/video/uvc/uvc_video.c
+++ linux-ec2-2.6.32/drivers/media/video/uvc/uvc_video.c
@@ -64,15 +64,19 @@
 static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl)
 {
-	struct uvc_format *format;
+	struct uvc_format *format = NULL;
 	struct uvc_frame *frame = NULL;
 	unsigned int i;
 
-	if (ctrl->bFormatIndex <= 0 ||
-	    ctrl->bFormatIndex > stream->nformats)
-		return;
+	for (i = 0; i < stream->nformats; ++i) {
+		if (stream->format[i].index == ctrl->bFormatIndex) {
+			format = &stream->format[i];
+			break;
+		}
+	}
 
-	format = &stream->format[ctrl->bFormatIndex - 1];
+	if (format == NULL)
+		return;
 
 	for (i = 0; i < format->nframes; ++i) {
 		if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
--- linux-ec2-2.6.32.orig/drivers/media/video/uvc/uvc_driver.c
+++ linux-ec2-2.6.32/drivers/media/video/uvc/uvc_driver.c
@@ -58,6 +58,11 @@
 		.fcc		= V4L2_PIX_FMT_YUYV,
 	},
 	{
+		.name		= "YUV 4:2:2 (YUYV)",
+		.guid		= UVC_GUID_FORMAT_YUY2_ISIGHT,
+		.fcc		= V4L2_PIX_FMT_YUYV,
+	},
+	{
 		.name		= "YUV 4:2:0 (NV12)",
 		.guid		= UVC_GUID_FORMAT_NV12,
 		.fcc		= V4L2_PIX_FMT_NV12,
@@ -83,11 +88,16 @@
 		.fcc		= V4L2_PIX_FMT_UYVY,
 	},
 	{
-		.name		= "Greyscale",
+		.name		= "Greyscale (8-bit)",
 		.guid		= UVC_GUID_FORMAT_Y800,
 		.fcc		= V4L2_PIX_FMT_GREY,
 	},
 	{
+		.name		= "Greyscale (16-bit)",
+		.guid		= UVC_GUID_FORMAT_Y16,
+		.fcc		= V4L2_PIX_FMT_Y16,
+	},
+	{
 		.name		= "RGB Bayer",
 		.guid		= UVC_GUID_FORMAT_BY8,
 		.fcc		= V4L2_PIX_FMT_SBGGR8,
@@ -426,7 +436,8 @@
 	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
 	 * based formats have frame descriptors.
 	 */
-	while (buflen > 2 && buffer[2] == ftype) {
+	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+	       buffer[2] == ftype) {
 		frame = &format->frame[format->nframes];
 		if (ftype != UVC_VS_FRAME_FRAME_BASED)
 			n = buflen > 25 ? buffer[25] : 0;
@@ -503,12 +514,14 @@
 		buffer += buffer[0];
 	}
 
-	if (buflen > 2 && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
+	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+	    buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
 		buflen -= buffer[0];
 		buffer += buffer[0];
 	}
 
-	if (buflen > 2 && buffer[2] == UVC_VS_COLORFORMAT) {
+	if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+	    buffer[2] == UVC_VS_COLORFORMAT) {
 		if (buflen < 6) {
 			uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
 			       "interface %d COLORFORMAT error\n",
@@ -749,6 +762,11 @@
 		buffer += buffer[0];
 	}
 
+	if (buflen)
+		uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+			"%d has %u bytes of trailing descriptor garbage.\n",
+			dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
+
 	/* Parse the alternate settings to find the maximum bandwidth. */
 	for (i = 0; i < intf->num_altsetting; ++i) {
 		struct usb_host_endpoint *ep;
@@ -2048,6 +2066,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
+	/* Syntek (Packard Bell EasyNote MX52 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x174f,
+	  .idProduct		= 0x8a12,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_STREAM_NO_FID },
 	/* Syntek (Asus F9SG) */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2112,6 +2139,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
+	/* Arkmicro unbranded */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x18ec,
+	  .idProduct		= 0x3290,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_PROBE_DEF },
 	/* Bodelin ProScopeHR */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_DEV_HI
--- linux-ec2-2.6.32.orig/drivers/media/video/em28xx/em28xx-dvb.c
+++ linux-ec2-2.6.32/drivers/media/video/em28xx/em28xx-dvb.c
@@ -610,6 +610,7 @@
 
 	if (dev->dvb) {
 		unregister_dvb(dev->dvb);
+		kfree(dev->dvb);
 		dev->dvb = NULL;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/media/video/em28xx/em28xx-cards.c
+++ linux-ec2-2.6.32/drivers/media/video/em28xx/em28xx-cards.c
@@ -1525,11 +1525,11 @@
 		.input           = { {
 			.type     = EM28XX_VMUX_COMPOSITE1,
 			.vmux     = SAA7115_COMPOSITE0,
-			.amux     = EM28XX_AMUX_VIDEO2,
+			.amux     = EM28XX_AMUX_LINE_IN,
 		}, {
 			.type     = EM28XX_VMUX_SVIDEO,
 			.vmux     = SAA7115_SVIDEO3,
-			.amux     = EM28XX_AMUX_VIDEO2,
+			.amux     = EM28XX_AMUX_LINE_IN,
 		} },
 	},
 	[EM2860_BOARD_TERRATEC_AV350] = {
--- linux-ec2-2.6.32.orig/drivers/media/video/cx23885/cx23885-i2c.c
+++ linux-ec2-2.6.32/drivers/media/video/cx23885/cx23885-i2c.c
@@ -365,7 +365,17 @@
 
 		memset(&info, 0, sizeof(struct i2c_board_info));
 		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-		i2c_new_probed_device(&bus->i2c_adap, &info, addr_list);
+		/*
+		 * We can't call i2c_new_probed_device() because it uses
+		 * quick writes for probing and the IR receiver device only
+		 * replies to reads.
+		 */
+		if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0,
+				   I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK,
+				   NULL) >= 0) {
+			info.addr = addr_list[0];
+			i2c_new_device(&bus->i2c_adap, &info);
+		}
 	}
 
 	return bus->i2c_rc;
--- linux-ec2-2.6.32.orig/drivers/media/video/pwc/pwc-ctrl.c
+++ linux-ec2-2.6.32/drivers/media/video/pwc/pwc-ctrl.c
@@ -753,7 +753,7 @@
 		buf[0] = 0xff; /* fixed */
 
 	ret = send_control_msg(pdev,
-		SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf));
+		SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, 1);
 
 	if (!mode && ret >= 0) {
 		if (value < 0)
--- linux-ec2-2.6.32.orig/drivers/media/video/cx88/cx88-i2c.c
+++ linux-ec2-2.6.32/drivers/media/video/cx88/cx88-i2c.c
@@ -188,10 +188,24 @@
 			0x18, 0x6b, 0x71,
 			I2C_CLIENT_END
 		};
+		const unsigned short *addrp;
 
 		memset(&info, 0, sizeof(struct i2c_board_info));
 		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-		i2c_new_probed_device(&core->i2c_adap, &info, addr_list);
+		/*
+		 * We can't call i2c_new_probed_device() because it uses
+		 * quick writes for probing and at least some R receiver
+		 * devices only reply to reads.
+		 */
+		for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
+			if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
+					   I2C_SMBUS_READ, 0,
+					   I2C_SMBUS_QUICK, NULL) >= 0) {
+				info.addr = *addrp;
+				i2c_new_device(&core->i2c_adap, &info);
+				break;
+			}
+		}
 	}
 	return core->i2c_rc;
 }
--- linux-ec2-2.6.32.orig/drivers/media/video/bt8xx/bttv-driver.c
+++ linux-ec2-2.6.32/drivers/media/video/bt8xx/bttv-driver.c
@@ -4468,6 +4468,7 @@
 		request_modules(btv);
 	}
 
+	init_bttv_i2c_ir(btv);
 	bttv_input_init(btv);
 
 	/* everything is fine */
--- linux-ec2-2.6.32.orig/drivers/media/video/bt8xx/bttvp.h
+++ linux-ec2-2.6.32/drivers/media/video/bt8xx/bttvp.h
@@ -279,6 +279,7 @@
 extern unsigned int bttv_gpio;
 extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
 extern int init_bttv_i2c(struct bttv *btv);
+extern void init_bttv_i2c_ir(struct bttv *btv);
 extern int fini_bttv_i2c(struct bttv *btv);
 
 #define bttv_printk if (bttv_verbose) printk
--- linux-ec2-2.6.32.orig/drivers/media/video/bt8xx/bttv-i2c.c
+++ linux-ec2-2.6.32/drivers/media/video/bt8xx/bttv-i2c.c
@@ -388,7 +388,12 @@
 	if (0 == btv->i2c_rc && i2c_scan)
 		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
 
-	/* Instantiate the IR receiver device, if present */
+	return btv->i2c_rc;
+}
+
+/* Instantiate the I2C IR receiver device, if present */
+void __devinit init_bttv_i2c_ir(struct bttv *btv)
+{
 	if (0 == btv->i2c_rc) {
 		struct i2c_board_info info;
 		/* The external IR receiver is at i2c address 0x34 (0x35 for
@@ -408,7 +413,6 @@
 		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
 		i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list);
 	}
-	return btv->i2c_rc;
 }
 
 int __devexit fini_bttv_i2c(struct bttv *btv)
--- linux-ec2-2.6.32.orig/drivers/media/video/zc0301/zc0301_sensor.h
+++ linux-ec2-2.6.32/drivers/media/video/zc0301/zc0301_sensor.h
@@ -62,7 +62,6 @@
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
 	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
-	{ ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */           \
 	{ }                                                                   \
 };
 #else
--- linux-ec2-2.6.32.orig/drivers/media/video/ivtv/ivtvfb.c
+++ linux-ec2-2.6.32/drivers/media/video/ivtv/ivtvfb.c
@@ -457,6 +457,8 @@
 			struct fb_vblank vblank;
 			u32 trace;
 
+			memset(&vblank, 0, sizeof(struct fb_vblank));
+
 			vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
 					FB_VBLANK_HAVE_VSYNC;
 			trace = read_reg(0x028c0) >> 16;
--- linux-ec2-2.6.32.orig/drivers/pcmcia/cardbus.c
+++ linux-ec2-2.6.32/drivers/pcmcia/cardbus.c
@@ -214,7 +214,7 @@
 	unsigned int max, pass;
 
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
-//	pcibios_fixup_bus(bus);
+	pci_fixup_cardbus(bus);
 
 	max = bus->secondary;
 	for (pass = 0; pass < 2; pass++)
--- linux-ec2-2.6.32.orig/drivers/pcmcia/pcmcia_resource.c
+++ linux-ec2-2.6.32/drivers/pcmcia/pcmcia_resource.c
@@ -39,7 +39,7 @@
 #ifdef CONFIG_PCMCIA_PROBE
 #include <asm/irq.h>
 /* mask of IRQs already reserved by other cards, we should avoid using them */
-static u8 pcmcia_used_irq[NR_IRQS];
+static u8 pcmcia_used_irq[32];
 #endif
 
 
@@ -719,6 +719,9 @@
 		for (try = 0; try < 64; try++) {
 			irq = try % 32;
 
+			if (irq > NR_IRQS)
+				continue;
+
 			/* marked as available by driver, and not blocked by userspace? */
 			if (!((mask >> irq) & 1))
 				continue;
--- linux-ec2-2.6.32.orig/drivers/crypto/padlock-sha.c
+++ linux-ec2-2.6.32/drivers/crypto/padlock-sha.c
@@ -57,6 +57,23 @@
 	return crypto_shash_update(&dctx->fallback, data, length);
 }
 
+static int padlock_sha_export(struct shash_desc *desc, void *out)
+{
+	struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
+
+	return crypto_shash_export(&dctx->fallback, out);
+}
+
+static int padlock_sha_import(struct shash_desc *desc, const void *in)
+{
+	struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
+	struct padlock_sha_ctx *ctx = crypto_shash_ctx(desc->tfm);
+
+	dctx->fallback.tfm = ctx->fallback;
+	dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+	return crypto_shash_import(&dctx->fallback, in);
+}
+
 static inline void padlock_output_block(uint32_t *src,
 		 	uint32_t *dst, size_t count)
 {
@@ -235,7 +252,10 @@
 	.update 	=	padlock_sha_update,
 	.finup  	=	padlock_sha1_finup,
 	.final  	=	padlock_sha1_final,
+	.export		=	padlock_sha_export,
+	.import		=	padlock_sha_import,
 	.descsize	=	sizeof(struct padlock_sha_desc),
+	.statesize	=	sizeof(struct sha1_state),
 	.base		=	{
 		.cra_name		=	"sha1",
 		.cra_driver_name	=	"sha1-padlock",
@@ -256,7 +276,10 @@
 	.update 	=	padlock_sha_update,
 	.finup  	=	padlock_sha256_finup,
 	.final  	=	padlock_sha256_final,
+	.export		=	padlock_sha_export,
+	.import		=	padlock_sha_import,
 	.descsize	=	sizeof(struct padlock_sha_desc),
+	.statesize	=	sizeof(struct sha256_state),
 	.base		=	{
 		.cra_name		=	"sha256",
 		.cra_driver_name	=	"sha256-padlock",
--- linux-ec2-2.6.32.orig/drivers/crypto/padlock-aes.c
+++ linux-ec2-2.6.32/drivers/crypto/padlock-aes.c
@@ -285,7 +285,7 @@
 	if (initial)
 		asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
 			      : "+S" (input), "+D" (output), "+a" (iv)
-			      : "d" (control_word), "b" (key), "c" (count));
+			      : "d" (control_word), "b" (key), "c" (initial));
 
 	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"	/* rep xcryptcbc */
 		      : "+S" (input), "+D" (output), "+a" (iv)
--- linux-ec2-2.6.32.orig/drivers/mmc/core/sdio.c
+++ linux-ec2-2.6.32/drivers/mmc/core/sdio.c
@@ -267,6 +267,14 @@
 		if (err)
 			goto remove;
 
+		/*
+		 * Update oldcard with the new RCA received from the SDIO
+		 * device -- we're doing this so that it's updated in the
+		 * "card" struct when oldcard overwrites that later.
+		 */
+		if (oldcard)
+			oldcard->rca = card->rca;
+
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
--- linux-ec2-2.6.32.orig/drivers/mmc/core/core.c
+++ linux-ec2-2.6.32/drivers/mmc/core/core.c
@@ -48,6 +48,22 @@
 module_param(use_spi_crc, bool, 0);
 
 /*
+ * We normally treat cards as removed during suspend if they are not
+ * known to be on a non-removable bus, to avoid the risk of writing
+ * back data to a different card after resume.  Allow this to be
+ * overridden if necessary.
+ */
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+int mmc_assume_removable;
+#else
+int mmc_assume_removable = 1;
+#endif
+module_param_named(removable, mmc_assume_removable, bool, 0644);
+MODULE_PARM_DESC(
+	removable,
+	"MMC/SD cards are removable and may be removed during suspend");
+
+/*
  * Internal function. Schedule delayed work in the MMC work queue.
  */
 static int mmc_schedule_delayed_work(struct delayed_work *work,
@@ -1041,6 +1057,17 @@
 		container_of(work, struct mmc_host, detect.work);
 	u32 ocr;
 	int err;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (host->rescan_disable) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
 
 	mmc_bus_get(host);
 
@@ -1247,18 +1274,6 @@
 	if (host->bus_ops && !host->bus_dead) {
 		if (host->bus_ops->suspend)
 			err = host->bus_ops->suspend(host);
-		if (err == -ENOSYS || !host->bus_ops->resume) {
-			/*
-			 * We simply "remove" the card in this case.
-			 * It will be redetected on resume.
-			 */
-			if (host->bus_ops->remove)
-				host->bus_ops->remove(host);
-			mmc_claim_host(host);
-			mmc_detach_bus(host);
-			mmc_release_host(host);
-			err = 0;
-		}
 	}
 	mmc_bus_put(host);
 
@@ -1288,28 +1303,60 @@
 			printk(KERN_WARNING "%s: error %d during resume "
 					    "(card was removed?)\n",
 					    mmc_hostname(host), err);
-			if (host->bus_ops->remove)
-				host->bus_ops->remove(host);
-			mmc_claim_host(host);
-			mmc_detach_bus(host);
-			mmc_release_host(host);
-			/* no need to bother upper layers */
 			err = 0;
 		}
 	}
 	mmc_bus_put(host);
 
-	/*
-	 * We add a slight delay here so that resume can progress
-	 * in parallel.
-	 */
-	mmc_detect_change(host, 1);
-
 	return err;
 }
-
 EXPORT_SYMBOL(mmc_resume_host);
 
+/* Do the card removal on suspend if card is assumed removeable
+ * Do that in pm notifier while userspace isn't yet frozen, so we will be able
+   to sync the card.
+*/
+int mmc_pm_notify(struct notifier_block *notify_block,
+					unsigned long mode, void *unused)
+{
+	struct mmc_host *host = container_of(
+		notify_block, struct mmc_host, pm_notify);
+	unsigned long flags;
+
+
+	switch (mode) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+
+		spin_lock_irqsave(&host->lock, flags);
+		host->rescan_disable = 1;
+		spin_unlock_irqrestore(&host->lock, flags);
+		cancel_delayed_work_sync(&host->detect);
+
+		if (!host->bus_ops || host->bus_ops->suspend)
+			break;
+
+		mmc_claim_host(host);
+
+		if (host->bus_ops->remove)
+			host->bus_ops->remove(host);
+
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+		break;
+
+	case PM_POST_SUSPEND:
+	case PM_POST_HIBERNATION:
+
+		spin_lock_irqsave(&host->lock, flags);
+		host->rescan_disable = 0;
+		spin_unlock_irqrestore(&host->lock, flags);
+		mmc_detect_change(host, 0);
+
+	}
+
+	return 0;
+}
 #endif
 
 static int __init mmc_init(void)
--- linux-ec2-2.6.32.orig/drivers/mmc/core/Kconfig
+++ linux-ec2-2.6.32/drivers/mmc/core/Kconfig
@@ -3,7 +3,7 @@
 #
 
 config MMC_UNSAFE_RESUME
-	bool "Allow unsafe resume (DANGEROUS)"
+	bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
 	help
 	  If you say Y here, the MMC layer will assume that all cards
 	  stayed in their respective slots during the suspend. The
@@ -14,3 +14,5 @@
 	  This option is usually just for embedded systems which use
 	  a MMC/SD card for rootfs. Most people should say N here.
 
+	  This option sets a default which can be overridden by the
+	  module parameter "removable=0" or "removable=1".
--- linux-ec2-2.6.32.orig/drivers/mmc/core/mmc.c
+++ linux-ec2-2.6.32/drivers/mmc/core/mmc.c
@@ -602,25 +602,6 @@
 	return err;
 }
 
-#ifdef CONFIG_MMC_UNSAFE_RESUME
-
-static const struct mmc_bus_ops mmc_ops = {
-	.awake = mmc_awake,
-	.sleep = mmc_sleep,
-	.remove = mmc_remove,
-	.detect = mmc_detect,
-	.suspend = mmc_suspend,
-	.resume = mmc_resume,
-	.power_restore = mmc_power_restore,
-};
-
-static void mmc_attach_bus_ops(struct mmc_host *host)
-{
-	mmc_attach_bus(host, &mmc_ops);
-}
-
-#else
-
 static const struct mmc_bus_ops mmc_ops = {
 	.awake = mmc_awake,
 	.sleep = mmc_sleep,
@@ -645,15 +626,13 @@
 {
 	const struct mmc_bus_ops *bus_ops;
 
-	if (host->caps & MMC_CAP_NONREMOVABLE)
+	if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable)
 		bus_ops = &mmc_ops_unsafe;
 	else
 		bus_ops = &mmc_ops;
 	mmc_attach_bus(host, bus_ops);
 }
 
-#endif
-
 /*
  * Starting point for MMC card init.
  */
--- linux-ec2-2.6.32.orig/drivers/mmc/core/core.h
+++ linux-ec2-2.6.32/drivers/mmc/core/core.h
@@ -54,7 +54,9 @@
 int mmc_attach_sd(struct mmc_host *host, u32 ocr);
 int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
 
+/* Module parameters */
 extern int use_spi_crc;
+extern int mmc_assume_removable;
 
 /* Debugfs information for hosts and cards */
 void mmc_add_host_debugfs(struct mmc_host *host);
--- linux-ec2-2.6.32.orig/drivers/mmc/core/sd.c
+++ linux-ec2-2.6.32/drivers/mmc/core/sd.c
@@ -606,23 +606,6 @@
 	mmc_release_host(host);
 }
 
-#ifdef CONFIG_MMC_UNSAFE_RESUME
-
-static const struct mmc_bus_ops mmc_sd_ops = {
-	.remove = mmc_sd_remove,
-	.detect = mmc_sd_detect,
-	.suspend = mmc_sd_suspend,
-	.resume = mmc_sd_resume,
-	.power_restore = mmc_sd_power_restore,
-};
-
-static void mmc_sd_attach_bus_ops(struct mmc_host *host)
-{
-	mmc_attach_bus(host, &mmc_sd_ops);
-}
-
-#else
-
 static const struct mmc_bus_ops mmc_sd_ops = {
 	.remove = mmc_sd_remove,
 	.detect = mmc_sd_detect,
@@ -643,15 +626,13 @@
 {
 	const struct mmc_bus_ops *bus_ops;
 
-	if (host->caps & MMC_CAP_NONREMOVABLE)
+	if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable)
 		bus_ops = &mmc_sd_ops_unsafe;
 	else
 		bus_ops = &mmc_sd_ops;
 	mmc_attach_bus(host, bus_ops);
 }
 
-#endif
-
 /*
  * Starting point for SD card init.
  */
--- linux-ec2-2.6.32.orig/drivers/mmc/core/host.c
+++ linux-ec2-2.6.32/drivers/mmc/core/host.c
@@ -16,6 +16,7 @@
 #include <linux/idr.h>
 #include <linux/pagemap.h>
 #include <linux/leds.h>
+#include <linux/suspend.h>
 
 #include <linux/mmc/host.h>
 
@@ -84,6 +85,9 @@
 	init_waitqueue_head(&host->wq);
 	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 	INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
+#ifdef CONFIG_PM
+	host->pm_notify.notifier_call = mmc_pm_notify;
+#endif
 
 	/*
 	 * By default, hosts do not support SGIO or large requests.
@@ -132,6 +136,7 @@
 #endif
 
 	mmc_start_host(host);
+	register_pm_notifier(&host->pm_notify);
 
 	return 0;
 }
@@ -148,6 +153,7 @@
  */
 void mmc_remove_host(struct mmc_host *host)
 {
+	unregister_pm_notifier(&host->pm_notify);
 	mmc_stop_host(host);
 
 #ifdef CONFIG_DEBUG_FS
--- linux-ec2-2.6.32.orig/drivers/mmc/card/block.c
+++ linux-ec2-2.6.32/drivers/mmc/card/block.c
@@ -85,7 +85,14 @@
 	mutex_lock(&open_lock);
 	md->usage--;
 	if (md->usage == 0) {
+		int devmaj = MAJOR(disk_devt(md->disk));
 		int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
+
+		if (!devmaj)
+			devidx = md->disk->first_minor >> MMC_SHIFT;
+
+		blk_cleanup_queue(md->queue.queue);
+
 		__clear_bit(devidx, dev_use);
 
 		put_disk(md->disk);
@@ -613,6 +620,7 @@
 	return 0;
 
  out:
+	mmc_cleanup_queue(&md->queue);
 	mmc_blk_put(md);
 
 	return err;
--- linux-ec2-2.6.32.orig/drivers/mmc/card/queue.c
+++ linux-ec2-2.6.32/drivers/mmc/card/queue.c
@@ -90,9 +90,10 @@
 	struct request *req;
 
 	if (!mq) {
-		printk(KERN_ERR "MMC: killing requests for dead queue\n");
-		while ((req = blk_fetch_request(q)) != NULL)
+		while ((req = blk_fetch_request(q)) != NULL) {
+			req->cmd_flags |= REQ_QUIET;
 			__blk_end_request_all(req, -EIO);
+		}
 		return;
 	}
 
@@ -223,17 +224,18 @@
 	struct request_queue *q = mq->queue;
 	unsigned long flags;
 
-	/* Mark that we should start throwing out stragglers */
-	spin_lock_irqsave(q->queue_lock, flags);
-	q->queuedata = NULL;
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
 	/* Make sure the queue isn't suspended, as that will deadlock */
 	mmc_queue_resume(mq);
 
 	/* Then terminate our worker thread */
 	kthread_stop(mq->thread);
 
+	/* Empty the queue */
+	spin_lock_irqsave(q->queue_lock, flags);
+	q->queuedata = NULL;
+	blk_start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
  	if (mq->bounce_sg)
  		kfree(mq->bounce_sg);
  	mq->bounce_sg = NULL;
@@ -245,8 +247,6 @@
 		kfree(mq->bounce_buf);
 	mq->bounce_buf = NULL;
 
-	blk_cleanup_queue(mq->queue);
-
 	mq->card = NULL;
 }
 EXPORT_SYMBOL(mmc_cleanup_queue);
--- linux-ec2-2.6.32.orig/drivers/mmc/host/sdhci-pci.c
+++ linux-ec2-2.6.32/drivers/mmc/host/sdhci-pci.c
@@ -569,6 +569,7 @@
 	host->ioaddr = pci_ioremap_bar(pdev, bar);
 	if (!host->ioaddr) {
 		dev_err(&pdev->dev, "failed to remap registers\n");
+		ret = -ENOMEM;
 		goto release;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/mmc/host/s3cmci.c
+++ linux-ec2-2.6.32/drivers/mmc/host/s3cmci.c
@@ -1178,7 +1178,7 @@
 	struct s3c24xx_mci_pdata *pdata = host->pdata;
 	int ret;
 
-	if (pdata->gpio_detect == 0)
+	if (pdata->no_detect)
 		return -ENOSYS;
 
 	ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
@@ -1361,6 +1361,8 @@
 static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
 	/* This is currently here to avoid a number of if (host->pdata)
 	 * checks. Any zero fields to ensure reaonable defaults are picked. */
+	.no_wprotect = 1,
+	.no_detect = 1,
 };
 
 #ifdef CONFIG_CPU_FREQ
--- linux-ec2-2.6.32.orig/drivers/mmc/host/sdhci.c
+++ linux-ec2-2.6.32/drivers/mmc/host/sdhci.c
@@ -1266,6 +1266,13 @@
 
 	host = (struct sdhci_host*)param;
 
+        /*
+         * If this tasklet gets rescheduled while running, it will
+         * be run again afterwards but without any active request.
+         */
+	if (!host->mrq)
+		return;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	del_timer(&host->timer);
@@ -1277,7 +1284,7 @@
 	 * upon error conditions.
 	 */
 	if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-		(mrq->cmd->error ||
+	    ((mrq->cmd && mrq->cmd->error) ||
 		 (mrq->data && (mrq->data->error ||
 		  (mrq->data->stop && mrq->data->stop->error))) ||
 		   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
--- linux-ec2-2.6.32.orig/drivers/mmc/host/tmio_mmc.c
+++ linux-ec2-2.6.32/drivers/mmc/host/tmio_mmc.c
@@ -161,6 +161,7 @@
 static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 {
 	struct mmc_data *data = host->data;
+	void *sg_virt;
 	unsigned short *buf;
 	unsigned int count;
 	unsigned long flags;
@@ -170,8 +171,8 @@
 		return;
 	}
 
-	buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) +
-	      host->sg_off);
+	sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags);
+	buf = (unsigned short *)(sg_virt + host->sg_off);
 
 	count = host->sg_ptr->length - host->sg_off;
 	if (count > data->blksz)
@@ -188,7 +189,7 @@
 
 	host->sg_off += count;
 
-	tmio_mmc_kunmap_atomic(host, &flags);
+	tmio_mmc_kunmap_atomic(sg_virt, &flags);
 
 	if (host->sg_off == host->sg_ptr->length)
 		tmio_mmc_next_sg(host);
--- linux-ec2-2.6.32.orig/drivers/mmc/host/sdhci-s3c.c
+++ linux-ec2-2.6.32/drivers/mmc/host/sdhci-s3c.c
@@ -372,6 +372,28 @@
 
 static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
 {
+	struct sdhci_host *host =  platform_get_drvdata(pdev);
+	struct sdhci_s3c *sc = sdhci_priv(host);
+	int ptr;
+
+	sdhci_remove_host(host, 1);
+
+	for (ptr = 0; ptr < 3; ptr++) {
+		if (sc->clk_bus[ptr]) {
+			clk_disable(sc->clk_bus[ptr]);
+			clk_put(sc->clk_bus[ptr]);
+		}
+	}
+	clk_disable(sc->clk_io);
+	clk_put(sc->clk_io);
+
+	iounmap(host->ioaddr);
+	release_resource(sc->ioarea);
+	kfree(sc->ioarea);
+
+	sdhci_free_host(host);
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/mmc/host/atmel-mci.c
+++ linux-ec2-2.6.32/drivers/mmc/host/atmel-mci.c
@@ -530,9 +530,10 @@
 {
 	struct mmc_data			*data = host->data;
 
-	dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
-		     ((data->flags & MMC_DATA_WRITE)
-		      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+	if (data)
+		dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+			     ((data->flags & MMC_DATA_WRITE)
+			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
 }
 
 static void atmci_stop_dma(struct atmel_mci *host)
@@ -1037,8 +1038,8 @@
 			"command error: status=0x%08x\n", status);
 
 		if (cmd->data) {
-			host->data = NULL;
 			atmci_stop_dma(host);
+			host->data = NULL;
 			mci_writel(host, IDR, MCI_NOTBUSY
 					| MCI_TXRDY | MCI_RXRDY
 					| ATMCI_DATA_ERROR_FLAGS);
@@ -1229,6 +1230,7 @@
 			} else {
 				data->bytes_xfered = data->blocks * data->blksz;
 				data->error = 0;
+				mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS);
 			}
 
 			if (!data->stop) {
@@ -1669,13 +1671,13 @@
 	ret = -ENODEV;
 	if (pdata->slot[0].bus_width) {
 		ret = atmci_init_slot(host, &pdata->slot[0],
-				MCI_SDCSEL_SLOT_A, 0);
+				0, MCI_SDCSEL_SLOT_A);
 		if (!ret)
 			nr_slots++;
 	}
 	if (pdata->slot[1].bus_width) {
 		ret = atmci_init_slot(host, &pdata->slot[1],
-				MCI_SDCSEL_SLOT_B, 1);
+				1, MCI_SDCSEL_SLOT_B);
 		if (!ret)
 			nr_slots++;
 	}
--- linux-ec2-2.6.32.orig/drivers/mmc/host/tmio_mmc.h
+++ linux-ec2-2.6.32/drivers/mmc/host/tmio_mmc.h
@@ -102,10 +102,7 @@
 
 #define ack_mmc_irqs(host, i) \
 	do { \
-		u32 mask;\
-		mask  = sd_ctrl_read32((host), CTL_STATUS); \
-		mask &= ~((i) & TMIO_MASK_IRQ); \
-		sd_ctrl_write32((host), CTL_STATUS, mask); \
+		sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
 	} while (0)
 
 
@@ -200,19 +197,17 @@
 	return --host->sg_len;
 }
 
-static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host,
+static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
 	unsigned long *flags)
 {
-	struct scatterlist *sg = host->sg_ptr;
-
 	local_irq_save(*flags);
 	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
 }
 
-static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host,
+static inline void tmio_mmc_kunmap_atomic(void *virt,
 	unsigned long *flags)
 {
-	kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ);
+	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
 	local_irq_restore(*flags);
 }
 
--- linux-ec2-2.6.32.orig/drivers/staging/Makefile
+++ linux-ec2-2.6.32/drivers/staging/Makefile
@@ -5,10 +5,10 @@
 
 obj-$(CONFIG_ET131X)		+= et131x/
 obj-$(CONFIG_SLICOSS)		+= slicoss/
-obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
+#obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
 obj-$(CONFIG_VIDEO_CX25821)	+= cx25821/
 obj-$(CONFIG_USB_IP_COMMON)	+= usbip/
-obj-$(CONFIG_W35UND)		+= winbond/
+#obj-$(CONFIG_W35UND)		+= winbond/
 obj-$(CONFIG_PRISM2_USB)	+= wlan-ng/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_POCH)		+= poch/
@@ -23,10 +23,9 @@
 obj-$(CONFIG_RTL8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192SU)		+= rtl8192su/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
-obj-$(CONFIG_INPUT_MIMIO)	+= mimio/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
-obj-$(CONFIG_ANDROID)		+= android/
-obj-$(CONFIG_ANDROID)		+= dream/
+#obj-$(CONFIG_ANDROID)		+= android/
+#obj-$(CONFIG_ANDROID)		+= dream/
 obj-$(CONFIG_DST)		+= dst/
 obj-$(CONFIG_POHMELFS)		+= pohmelfs/
 obj-$(CONFIG_B3DFG)		+= b3dfg/
--- linux-ec2-2.6.32.orig/drivers/staging/Kconfig
+++ linux-ec2-2.6.32/drivers/staging/Kconfig
@@ -81,8 +81,6 @@
 
 source "drivers/staging/rtl8192e/Kconfig"
 
-source "drivers/staging/mimio/Kconfig"
-
 source "drivers/staging/frontier/Kconfig"
 
 source "drivers/staging/android/Kconfig"
@@ -101,7 +99,7 @@
 
 source "drivers/staging/line6/Kconfig"
 
-source "drivers/gpu/drm/radeon/Kconfig"
+source "drivers/gpu/drm/nouveau/Kconfig"
 
 source "drivers/staging/octeon/Kconfig"
 
--- linux-ec2-2.6.32.orig/drivers/staging/panel/panel.c
+++ linux-ec2-2.6.32/drivers/staging/panel/panel.c
@@ -2181,6 +2181,7 @@
 		if (pprt) {
 			parport_release(pprt);
 			parport_unregister_device(pprt);
+			pprt = NULL;
 		}
 		parport_unregister_driver(&panel_driver);
 		printk(KERN_ERR "Panel driver version " PANEL_VERSION
@@ -2230,6 +2231,7 @@
 		/* TODO: free all input signals */
 		parport_release(pprt);
 		parport_unregister_device(pprt);
+		pprt = NULL;
 	}
 	parport_unregister_driver(&panel_driver);
 }
--- linux-ec2-2.6.32.orig/drivers/staging/line6/control.c
+++ linux-ec2-2.6.32/drivers/staging/line6/control.c
@@ -259,108 +259,108 @@
 VARIAX_PARAM_R(float, mix1);
 VARIAX_PARAM_R(int, pickup_wiring);
 
-static DEVICE_ATTR(tweak, S_IWUGO | S_IRUGO, pod_get_tweak, pod_set_tweak);
-static DEVICE_ATTR(wah_position, S_IWUGO | S_IRUGO, pod_get_wah_position, pod_set_wah_position);
-static DEVICE_ATTR(compression_gain, S_IWUGO | S_IRUGO, pod_get_compression_gain, pod_set_compression_gain);
-static DEVICE_ATTR(vol_pedal_position, S_IWUGO | S_IRUGO, pod_get_vol_pedal_position, pod_set_vol_pedal_position);
-static DEVICE_ATTR(compression_threshold, S_IWUGO | S_IRUGO, pod_get_compression_threshold, pod_set_compression_threshold);
-static DEVICE_ATTR(pan, S_IWUGO | S_IRUGO, pod_get_pan, pod_set_pan);
-static DEVICE_ATTR(amp_model_setup, S_IWUGO | S_IRUGO, pod_get_amp_model_setup, pod_set_amp_model_setup);
-static DEVICE_ATTR(amp_model, S_IWUGO | S_IRUGO, pod_get_amp_model, pod_set_amp_model);
-static DEVICE_ATTR(drive, S_IWUGO | S_IRUGO, pod_get_drive, pod_set_drive);
-static DEVICE_ATTR(bass, S_IWUGO | S_IRUGO, pod_get_bass, pod_set_bass);
-static DEVICE_ATTR(mid, S_IWUGO | S_IRUGO, pod_get_mid, pod_set_mid);
-static DEVICE_ATTR(lowmid, S_IWUGO | S_IRUGO, pod_get_lowmid, pod_set_lowmid);
-static DEVICE_ATTR(treble, S_IWUGO | S_IRUGO, pod_get_treble, pod_set_treble);
-static DEVICE_ATTR(highmid, S_IWUGO | S_IRUGO, pod_get_highmid, pod_set_highmid);
-static DEVICE_ATTR(chan_vol, S_IWUGO | S_IRUGO, pod_get_chan_vol, pod_set_chan_vol);
-static DEVICE_ATTR(reverb_mix, S_IWUGO | S_IRUGO, pod_get_reverb_mix, pod_set_reverb_mix);
-static DEVICE_ATTR(effect_setup, S_IWUGO | S_IRUGO, pod_get_effect_setup, pod_set_effect_setup);
-static DEVICE_ATTR(band_1_frequency, S_IWUGO | S_IRUGO, pod_get_band_1_frequency, pod_set_band_1_frequency);
-static DEVICE_ATTR(presence, S_IWUGO | S_IRUGO, pod_get_presence, pod_set_presence);
-static DEVICE_ATTR2(treble__bass, treble, S_IWUGO | S_IRUGO, pod_get_treble__bass, pod_set_treble__bass);
-static DEVICE_ATTR(noise_gate_enable, S_IWUGO | S_IRUGO, pod_get_noise_gate_enable, pod_set_noise_gate_enable);
-static DEVICE_ATTR(gate_threshold, S_IWUGO | S_IRUGO, pod_get_gate_threshold, pod_set_gate_threshold);
-static DEVICE_ATTR(gate_decay_time, S_IWUGO | S_IRUGO, pod_get_gate_decay_time, pod_set_gate_decay_time);
-static DEVICE_ATTR(stomp_enable, S_IWUGO | S_IRUGO, pod_get_stomp_enable, pod_set_stomp_enable);
-static DEVICE_ATTR(comp_enable, S_IWUGO | S_IRUGO, pod_get_comp_enable, pod_set_comp_enable);
-static DEVICE_ATTR(stomp_time, S_IWUGO | S_IRUGO, pod_get_stomp_time, pod_set_stomp_time);
-static DEVICE_ATTR(delay_enable, S_IWUGO | S_IRUGO, pod_get_delay_enable, pod_set_delay_enable);
-static DEVICE_ATTR(mod_param_1, S_IWUGO | S_IRUGO, pod_get_mod_param_1, pod_set_mod_param_1);
-static DEVICE_ATTR(delay_param_1, S_IWUGO | S_IRUGO, pod_get_delay_param_1, pod_set_delay_param_1);
-static DEVICE_ATTR(delay_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_delay_param_1_note_value, pod_set_delay_param_1_note_value);
-static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency__bass, pod_set_band_2_frequency__bass);
-static DEVICE_ATTR(delay_param_2, S_IWUGO | S_IRUGO, pod_get_delay_param_2, pod_set_delay_param_2);
-static DEVICE_ATTR(delay_volume_mix, S_IWUGO | S_IRUGO, pod_get_delay_volume_mix, pod_set_delay_volume_mix);
-static DEVICE_ATTR(delay_param_3, S_IWUGO | S_IRUGO, pod_get_delay_param_3, pod_set_delay_param_3);
-static DEVICE_ATTR(reverb_enable, S_IWUGO | S_IRUGO, pod_get_reverb_enable, pod_set_reverb_enable);
-static DEVICE_ATTR(reverb_type, S_IWUGO | S_IRUGO, pod_get_reverb_type, pod_set_reverb_type);
-static DEVICE_ATTR(reverb_decay, S_IWUGO | S_IRUGO, pod_get_reverb_decay, pod_set_reverb_decay);
-static DEVICE_ATTR(reverb_tone, S_IWUGO | S_IRUGO, pod_get_reverb_tone, pod_set_reverb_tone);
-static DEVICE_ATTR(reverb_pre_delay, S_IWUGO | S_IRUGO, pod_get_reverb_pre_delay, pod_set_reverb_pre_delay);
-static DEVICE_ATTR(reverb_pre_post, S_IWUGO | S_IRUGO, pod_get_reverb_pre_post, pod_set_reverb_pre_post);
-static DEVICE_ATTR(band_2_frequency, S_IWUGO | S_IRUGO, pod_get_band_2_frequency, pod_set_band_2_frequency);
-static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency__bass, pod_set_band_3_frequency__bass);
-static DEVICE_ATTR(wah_enable, S_IWUGO | S_IRUGO, pod_get_wah_enable, pod_set_wah_enable);
-static DEVICE_ATTR(modulation_lo_cut, S_IWUGO | S_IRUGO, pod_get_modulation_lo_cut, pod_set_modulation_lo_cut);
-static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUGO | S_IRUGO, pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut);
-static DEVICE_ATTR(volume_pedal_minimum, S_IWUGO | S_IRUGO, pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum);
-static DEVICE_ATTR(eq_pre_post, S_IWUGO | S_IRUGO, pod_get_eq_pre_post, pod_set_eq_pre_post);
-static DEVICE_ATTR(volume_pre_post, S_IWUGO | S_IRUGO, pod_get_volume_pre_post, pod_set_volume_pre_post);
-static DEVICE_ATTR(di_model, S_IWUGO | S_IRUGO, pod_get_di_model, pod_set_di_model);
-static DEVICE_ATTR(di_delay, S_IWUGO | S_IRUGO, pod_get_di_delay, pod_set_di_delay);
-static DEVICE_ATTR(mod_enable, S_IWUGO | S_IRUGO, pod_get_mod_enable, pod_set_mod_enable);
-static DEVICE_ATTR(mod_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_mod_param_1_note_value, pod_set_mod_param_1_note_value);
-static DEVICE_ATTR(mod_param_2, S_IWUGO | S_IRUGO, pod_get_mod_param_2, pod_set_mod_param_2);
-static DEVICE_ATTR(mod_param_3, S_IWUGO | S_IRUGO, pod_get_mod_param_3, pod_set_mod_param_3);
-static DEVICE_ATTR(mod_param_4, S_IWUGO | S_IRUGO, pod_get_mod_param_4, pod_set_mod_param_4);
-static DEVICE_ATTR(mod_param_5, S_IWUGO | S_IRUGO, pod_get_mod_param_5, pod_set_mod_param_5);
-static DEVICE_ATTR(mod_volume_mix, S_IWUGO | S_IRUGO, pod_get_mod_volume_mix, pod_set_mod_volume_mix);
-static DEVICE_ATTR(mod_pre_post, S_IWUGO | S_IRUGO, pod_get_mod_pre_post, pod_set_mod_pre_post);
-static DEVICE_ATTR(modulation_model, S_IWUGO | S_IRUGO, pod_get_modulation_model, pod_set_modulation_model);
-static DEVICE_ATTR(band_3_frequency, S_IWUGO | S_IRUGO, pod_get_band_3_frequency, pod_set_band_3_frequency);
-static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency__bass, pod_set_band_4_frequency__bass);
-static DEVICE_ATTR(mod_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_mod_param_1_double_precision, pod_set_mod_param_1_double_precision);
-static DEVICE_ATTR(delay_param_1_double_precision, S_IWUGO | S_IRUGO, pod_get_delay_param_1_double_precision, pod_set_delay_param_1_double_precision);
-static DEVICE_ATTR(eq_enable, S_IWUGO | S_IRUGO, pod_get_eq_enable, pod_set_eq_enable);
-static DEVICE_ATTR(tap, S_IWUGO | S_IRUGO, pod_get_tap, pod_set_tap);
-static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUGO | S_IRUGO, pod_get_volume_tweak_pedal_assign, pod_set_volume_tweak_pedal_assign);
-static DEVICE_ATTR(band_5_frequency, S_IWUGO | S_IRUGO, pod_get_band_5_frequency, pod_set_band_5_frequency);
-static DEVICE_ATTR(tuner, S_IWUGO | S_IRUGO, pod_get_tuner, pod_set_tuner);
-static DEVICE_ATTR(mic_selection, S_IWUGO | S_IRUGO, pod_get_mic_selection, pod_set_mic_selection);
-static DEVICE_ATTR(cabinet_model, S_IWUGO | S_IRUGO, pod_get_cabinet_model, pod_set_cabinet_model);
-static DEVICE_ATTR(stomp_model, S_IWUGO | S_IRUGO, pod_get_stomp_model, pod_set_stomp_model);
-static DEVICE_ATTR(roomlevel, S_IWUGO | S_IRUGO, pod_get_roomlevel, pod_set_roomlevel);
-static DEVICE_ATTR(band_4_frequency, S_IWUGO | S_IRUGO, pod_get_band_4_frequency, pod_set_band_4_frequency);
-static DEVICE_ATTR(band_6_frequency, S_IWUGO | S_IRUGO, pod_get_band_6_frequency, pod_set_band_6_frequency);
-static DEVICE_ATTR(stomp_param_1_note_value, S_IWUGO | S_IRUGO, pod_get_stomp_param_1_note_value, pod_set_stomp_param_1_note_value);
-static DEVICE_ATTR(stomp_param_2, S_IWUGO | S_IRUGO, pod_get_stomp_param_2, pod_set_stomp_param_2);
-static DEVICE_ATTR(stomp_param_3, S_IWUGO | S_IRUGO, pod_get_stomp_param_3, pod_set_stomp_param_3);
-static DEVICE_ATTR(stomp_param_4, S_IWUGO | S_IRUGO, pod_get_stomp_param_4, pod_set_stomp_param_4);
-static DEVICE_ATTR(stomp_param_5, S_IWUGO | S_IRUGO, pod_get_stomp_param_5, pod_set_stomp_param_5);
-static DEVICE_ATTR(stomp_param_6, S_IWUGO | S_IRUGO, pod_get_stomp_param_6, pod_set_stomp_param_6);
-static DEVICE_ATTR(amp_switch_select, S_IWUGO | S_IRUGO, pod_get_amp_switch_select, pod_set_amp_switch_select);
-static DEVICE_ATTR(delay_param_4, S_IWUGO | S_IRUGO, pod_get_delay_param_4, pod_set_delay_param_4);
-static DEVICE_ATTR(delay_param_5, S_IWUGO | S_IRUGO, pod_get_delay_param_5, pod_set_delay_param_5);
-static DEVICE_ATTR(delay_pre_post, S_IWUGO | S_IRUGO, pod_get_delay_pre_post, pod_set_delay_pre_post);
-static DEVICE_ATTR(delay_model, S_IWUGO | S_IRUGO, pod_get_delay_model, pod_set_delay_model);
-static DEVICE_ATTR(delay_verb_model, S_IWUGO | S_IRUGO, pod_get_delay_verb_model, pod_set_delay_verb_model);
-static DEVICE_ATTR(tempo_msb, S_IWUGO | S_IRUGO, pod_get_tempo_msb, pod_set_tempo_msb);
-static DEVICE_ATTR(tempo_lsb, S_IWUGO | S_IRUGO, pod_get_tempo_lsb, pod_set_tempo_lsb);
-static DEVICE_ATTR(wah_model, S_IWUGO | S_IRUGO, pod_get_wah_model, pod_set_wah_model);
-static DEVICE_ATTR(bypass_volume, S_IWUGO | S_IRUGO, pod_get_bypass_volume, pod_set_bypass_volume);
-static DEVICE_ATTR(fx_loop_on_off, S_IWUGO | S_IRUGO, pod_get_fx_loop_on_off, pod_set_fx_loop_on_off);
-static DEVICE_ATTR(tweak_param_select, S_IWUGO | S_IRUGO, pod_get_tweak_param_select, pod_set_tweak_param_select);
-static DEVICE_ATTR(amp1_engage, S_IWUGO | S_IRUGO, pod_get_amp1_engage, pod_set_amp1_engage);
-static DEVICE_ATTR(band_1_gain, S_IWUGO | S_IRUGO, pod_get_band_1_gain, pod_set_band_1_gain);
-static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain__bass, pod_set_band_2_gain__bass);
-static DEVICE_ATTR(band_2_gain, S_IWUGO | S_IRUGO, pod_get_band_2_gain, pod_set_band_2_gain);
-static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain__bass, pod_set_band_3_gain__bass);
-static DEVICE_ATTR(band_3_gain, S_IWUGO | S_IRUGO, pod_get_band_3_gain, pod_set_band_3_gain);
-static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain__bass, pod_set_band_4_gain__bass);
-static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUGO | S_IRUGO, pod_get_band_5_gain__bass, pod_set_band_5_gain__bass);
-static DEVICE_ATTR(band_4_gain, S_IWUGO | S_IRUGO, pod_get_band_4_gain, pod_set_band_4_gain);
-static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUGO | S_IRUGO, pod_get_band_6_gain__bass, pod_set_band_6_gain__bass);
+static DEVICE_ATTR(tweak, S_IWUSR | S_IRUGO, pod_get_tweak, pod_set_tweak);
+static DEVICE_ATTR(wah_position, S_IWUSR | S_IRUGO, pod_get_wah_position, pod_set_wah_position);
+static DEVICE_ATTR(compression_gain, S_IWUSR | S_IRUGO, pod_get_compression_gain, pod_set_compression_gain);
+static DEVICE_ATTR(vol_pedal_position, S_IWUSR | S_IRUGO, pod_get_vol_pedal_position, pod_set_vol_pedal_position);
+static DEVICE_ATTR(compression_threshold, S_IWUSR | S_IRUGO, pod_get_compression_threshold, pod_set_compression_threshold);
+static DEVICE_ATTR(pan, S_IWUSR | S_IRUGO, pod_get_pan, pod_set_pan);
+static DEVICE_ATTR(amp_model_setup, S_IWUSR | S_IRUGO, pod_get_amp_model_setup, pod_set_amp_model_setup);
+static DEVICE_ATTR(amp_model, S_IWUSR | S_IRUGO, pod_get_amp_model, pod_set_amp_model);
+static DEVICE_ATTR(drive, S_IWUSR | S_IRUGO, pod_get_drive, pod_set_drive);
+static DEVICE_ATTR(bass, S_IWUSR | S_IRUGO, pod_get_bass, pod_set_bass);
+static DEVICE_ATTR(mid, S_IWUSR | S_IRUGO, pod_get_mid, pod_set_mid);
+static DEVICE_ATTR(lowmid, S_IWUSR | S_IRUGO, pod_get_lowmid, pod_set_lowmid);
+static DEVICE_ATTR(treble, S_IWUSR | S_IRUGO, pod_get_treble, pod_set_treble);
+static DEVICE_ATTR(highmid, S_IWUSR | S_IRUGO, pod_get_highmid, pod_set_highmid);
+static DEVICE_ATTR(chan_vol, S_IWUSR | S_IRUGO, pod_get_chan_vol, pod_set_chan_vol);
+static DEVICE_ATTR(reverb_mix, S_IWUSR | S_IRUGO, pod_get_reverb_mix, pod_set_reverb_mix);
+static DEVICE_ATTR(effect_setup, S_IWUSR | S_IRUGO, pod_get_effect_setup, pod_set_effect_setup);
+static DEVICE_ATTR(band_1_frequency, S_IWUSR | S_IRUGO, pod_get_band_1_frequency, pod_set_band_1_frequency);
+static DEVICE_ATTR(presence, S_IWUSR | S_IRUGO, pod_get_presence, pod_set_presence);
+static DEVICE_ATTR2(treble__bass, treble, S_IWUSR | S_IRUGO, pod_get_treble__bass, pod_set_treble__bass);
+static DEVICE_ATTR(noise_gate_enable, S_IWUSR | S_IRUGO, pod_get_noise_gate_enable, pod_set_noise_gate_enable);
+static DEVICE_ATTR(gate_threshold, S_IWUSR | S_IRUGO, pod_get_gate_threshold, pod_set_gate_threshold);
+static DEVICE_ATTR(gate_decay_time, S_IWUSR | S_IRUGO, pod_get_gate_decay_time, pod_set_gate_decay_time);
+static DEVICE_ATTR(stomp_enable, S_IWUSR | S_IRUGO, pod_get_stomp_enable, pod_set_stomp_enable);
+static DEVICE_ATTR(comp_enable, S_IWUSR | S_IRUGO, pod_get_comp_enable, pod_set_comp_enable);
+static DEVICE_ATTR(stomp_time, S_IWUSR | S_IRUGO, pod_get_stomp_time, pod_set_stomp_time);
+static DEVICE_ATTR(delay_enable, S_IWUSR | S_IRUGO, pod_get_delay_enable, pod_set_delay_enable);
+static DEVICE_ATTR(mod_param_1, S_IWUSR | S_IRUGO, pod_get_mod_param_1, pod_set_mod_param_1);
+static DEVICE_ATTR(delay_param_1, S_IWUSR | S_IRUGO, pod_get_delay_param_1, pod_set_delay_param_1);
+static DEVICE_ATTR(delay_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_delay_param_1_note_value, pod_set_delay_param_1_note_value);
+static DEVICE_ATTR2(band_2_frequency__bass, band_2_frequency, S_IWUSR | S_IRUGO, pod_get_band_2_frequency__bass, pod_set_band_2_frequency__bass);
+static DEVICE_ATTR(delay_param_2, S_IWUSR | S_IRUGO, pod_get_delay_param_2, pod_set_delay_param_2);
+static DEVICE_ATTR(delay_volume_mix, S_IWUSR | S_IRUGO, pod_get_delay_volume_mix, pod_set_delay_volume_mix);
+static DEVICE_ATTR(delay_param_3, S_IWUSR | S_IRUGO, pod_get_delay_param_3, pod_set_delay_param_3);
+static DEVICE_ATTR(reverb_enable, S_IWUSR | S_IRUGO, pod_get_reverb_enable, pod_set_reverb_enable);
+static DEVICE_ATTR(reverb_type, S_IWUSR | S_IRUGO, pod_get_reverb_type, pod_set_reverb_type);
+static DEVICE_ATTR(reverb_decay, S_IWUSR | S_IRUGO, pod_get_reverb_decay, pod_set_reverb_decay);
+static DEVICE_ATTR(reverb_tone, S_IWUSR | S_IRUGO, pod_get_reverb_tone, pod_set_reverb_tone);
+static DEVICE_ATTR(reverb_pre_delay, S_IWUSR | S_IRUGO, pod_get_reverb_pre_delay, pod_set_reverb_pre_delay);
+static DEVICE_ATTR(reverb_pre_post, S_IWUSR | S_IRUGO, pod_get_reverb_pre_post, pod_set_reverb_pre_post);
+static DEVICE_ATTR(band_2_frequency, S_IWUSR | S_IRUGO, pod_get_band_2_frequency, pod_set_band_2_frequency);
+static DEVICE_ATTR2(band_3_frequency__bass, band_3_frequency, S_IWUSR | S_IRUGO, pod_get_band_3_frequency__bass, pod_set_band_3_frequency__bass);
+static DEVICE_ATTR(wah_enable, S_IWUSR | S_IRUGO, pod_get_wah_enable, pod_set_wah_enable);
+static DEVICE_ATTR(modulation_lo_cut, S_IWUSR | S_IRUGO, pod_get_modulation_lo_cut, pod_set_modulation_lo_cut);
+static DEVICE_ATTR(delay_reverb_lo_cut, S_IWUSR | S_IRUGO, pod_get_delay_reverb_lo_cut, pod_set_delay_reverb_lo_cut);
+static DEVICE_ATTR(volume_pedal_minimum, S_IWUSR | S_IRUGO, pod_get_volume_pedal_minimum, pod_set_volume_pedal_minimum);
+static DEVICE_ATTR(eq_pre_post, S_IWUSR | S_IRUGO, pod_get_eq_pre_post, pod_set_eq_pre_post);
+static DEVICE_ATTR(volume_pre_post, S_IWUSR | S_IRUGO, pod_get_volume_pre_post, pod_set_volume_pre_post);
+static DEVICE_ATTR(di_model, S_IWUSR | S_IRUGO, pod_get_di_model, pod_set_di_model);
+static DEVICE_ATTR(di_delay, S_IWUSR | S_IRUGO, pod_get_di_delay, pod_set_di_delay);
+static DEVICE_ATTR(mod_enable, S_IWUSR | S_IRUGO, pod_get_mod_enable, pod_set_mod_enable);
+static DEVICE_ATTR(mod_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_mod_param_1_note_value, pod_set_mod_param_1_note_value);
+static DEVICE_ATTR(mod_param_2, S_IWUSR | S_IRUGO, pod_get_mod_param_2, pod_set_mod_param_2);
+static DEVICE_ATTR(mod_param_3, S_IWUSR | S_IRUGO, pod_get_mod_param_3, pod_set_mod_param_3);
+static DEVICE_ATTR(mod_param_4, S_IWUSR | S_IRUGO, pod_get_mod_param_4, pod_set_mod_param_4);
+static DEVICE_ATTR(mod_param_5, S_IWUSR | S_IRUGO, pod_get_mod_param_5, pod_set_mod_param_5);
+static DEVICE_ATTR(mod_volume_mix, S_IWUSR | S_IRUGO, pod_get_mod_volume_mix, pod_set_mod_volume_mix);
+static DEVICE_ATTR(mod_pre_post, S_IWUSR | S_IRUGO, pod_get_mod_pre_post, pod_set_mod_pre_post);
+static DEVICE_ATTR(modulation_model, S_IWUSR | S_IRUGO, pod_get_modulation_model, pod_set_modulation_model);
+static DEVICE_ATTR(band_3_frequency, S_IWUSR | S_IRUGO, pod_get_band_3_frequency, pod_set_band_3_frequency);
+static DEVICE_ATTR2(band_4_frequency__bass, band_4_frequency, S_IWUSR | S_IRUGO, pod_get_band_4_frequency__bass, pod_set_band_4_frequency__bass);
+static DEVICE_ATTR(mod_param_1_double_precision, S_IWUSR | S_IRUGO, pod_get_mod_param_1_double_precision, pod_set_mod_param_1_double_precision);
+static DEVICE_ATTR(delay_param_1_double_precision, S_IWUSR | S_IRUGO, pod_get_delay_param_1_double_precision, pod_set_delay_param_1_double_precision);
+static DEVICE_ATTR(eq_enable, S_IWUSR | S_IRUGO, pod_get_eq_enable, pod_set_eq_enable);
+static DEVICE_ATTR(tap, S_IWUSR | S_IRUGO, pod_get_tap, pod_set_tap);
+static DEVICE_ATTR(volume_tweak_pedal_assign, S_IWUSR | S_IRUGO, pod_get_volume_tweak_pedal_assign, pod_set_volume_tweak_pedal_assign);
+static DEVICE_ATTR(band_5_frequency, S_IWUSR | S_IRUGO, pod_get_band_5_frequency, pod_set_band_5_frequency);
+static DEVICE_ATTR(tuner, S_IWUSR | S_IRUGO, pod_get_tuner, pod_set_tuner);
+static DEVICE_ATTR(mic_selection, S_IWUSR | S_IRUGO, pod_get_mic_selection, pod_set_mic_selection);
+static DEVICE_ATTR(cabinet_model, S_IWUSR | S_IRUGO, pod_get_cabinet_model, pod_set_cabinet_model);
+static DEVICE_ATTR(stomp_model, S_IWUSR | S_IRUGO, pod_get_stomp_model, pod_set_stomp_model);
+static DEVICE_ATTR(roomlevel, S_IWUSR | S_IRUGO, pod_get_roomlevel, pod_set_roomlevel);
+static DEVICE_ATTR(band_4_frequency, S_IWUSR | S_IRUGO, pod_get_band_4_frequency, pod_set_band_4_frequency);
+static DEVICE_ATTR(band_6_frequency, S_IWUSR | S_IRUGO, pod_get_band_6_frequency, pod_set_band_6_frequency);
+static DEVICE_ATTR(stomp_param_1_note_value, S_IWUSR | S_IRUGO, pod_get_stomp_param_1_note_value, pod_set_stomp_param_1_note_value);
+static DEVICE_ATTR(stomp_param_2, S_IWUSR | S_IRUGO, pod_get_stomp_param_2, pod_set_stomp_param_2);
+static DEVICE_ATTR(stomp_param_3, S_IWUSR | S_IRUGO, pod_get_stomp_param_3, pod_set_stomp_param_3);
+static DEVICE_ATTR(stomp_param_4, S_IWUSR | S_IRUGO, pod_get_stomp_param_4, pod_set_stomp_param_4);
+static DEVICE_ATTR(stomp_param_5, S_IWUSR | S_IRUGO, pod_get_stomp_param_5, pod_set_stomp_param_5);
+static DEVICE_ATTR(stomp_param_6, S_IWUSR | S_IRUGO, pod_get_stomp_param_6, pod_set_stomp_param_6);
+static DEVICE_ATTR(amp_switch_select, S_IWUSR | S_IRUGO, pod_get_amp_switch_select, pod_set_amp_switch_select);
+static DEVICE_ATTR(delay_param_4, S_IWUSR | S_IRUGO, pod_get_delay_param_4, pod_set_delay_param_4);
+static DEVICE_ATTR(delay_param_5, S_IWUSR | S_IRUGO, pod_get_delay_param_5, pod_set_delay_param_5);
+static DEVICE_ATTR(delay_pre_post, S_IWUSR | S_IRUGO, pod_get_delay_pre_post, pod_set_delay_pre_post);
+static DEVICE_ATTR(delay_model, S_IWUSR | S_IRUGO, pod_get_delay_model, pod_set_delay_model);
+static DEVICE_ATTR(delay_verb_model, S_IWUSR | S_IRUGO, pod_get_delay_verb_model, pod_set_delay_verb_model);
+static DEVICE_ATTR(tempo_msb, S_IWUSR | S_IRUGO, pod_get_tempo_msb, pod_set_tempo_msb);
+static DEVICE_ATTR(tempo_lsb, S_IWUSR | S_IRUGO, pod_get_tempo_lsb, pod_set_tempo_lsb);
+static DEVICE_ATTR(wah_model, S_IWUSR | S_IRUGO, pod_get_wah_model, pod_set_wah_model);
+static DEVICE_ATTR(bypass_volume, S_IWUSR | S_IRUGO, pod_get_bypass_volume, pod_set_bypass_volume);
+static DEVICE_ATTR(fx_loop_on_off, S_IWUSR | S_IRUGO, pod_get_fx_loop_on_off, pod_set_fx_loop_on_off);
+static DEVICE_ATTR(tweak_param_select, S_IWUSR | S_IRUGO, pod_get_tweak_param_select, pod_set_tweak_param_select);
+static DEVICE_ATTR(amp1_engage, S_IWUSR | S_IRUGO, pod_get_amp1_engage, pod_set_amp1_engage);
+static DEVICE_ATTR(band_1_gain, S_IWUSR | S_IRUGO, pod_get_band_1_gain, pod_set_band_1_gain);
+static DEVICE_ATTR2(band_2_gain__bass, band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain__bass, pod_set_band_2_gain__bass);
+static DEVICE_ATTR(band_2_gain, S_IWUSR | S_IRUGO, pod_get_band_2_gain, pod_set_band_2_gain);
+static DEVICE_ATTR2(band_3_gain__bass, band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain__bass, pod_set_band_3_gain__bass);
+static DEVICE_ATTR(band_3_gain, S_IWUSR | S_IRUGO, pod_get_band_3_gain, pod_set_band_3_gain);
+static DEVICE_ATTR2(band_4_gain__bass, band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain__bass, pod_set_band_4_gain__bass);
+static DEVICE_ATTR2(band_5_gain__bass, band_5_gain, S_IWUSR | S_IRUGO, pod_get_band_5_gain__bass, pod_set_band_5_gain__bass);
+static DEVICE_ATTR(band_4_gain, S_IWUSR | S_IRUGO, pod_get_band_4_gain, pod_set_band_4_gain);
+static DEVICE_ATTR2(band_6_gain__bass, band_6_gain, S_IWUSR | S_IRUGO, pod_get_band_6_gain__bass, pod_set_band_6_gain__bass);
 static DEVICE_ATTR(body, S_IRUGO, variax_get_body, line6_nop_write);
 static DEVICE_ATTR(pickup1_enable, S_IRUGO, variax_get_pickup1_enable, line6_nop_write);
 static DEVICE_ATTR(pickup1_type, S_IRUGO, variax_get_pickup1_type, line6_nop_write);
--- linux-ec2-2.6.32.orig/drivers/staging/line6/pod.c
+++ linux-ec2-2.6.32/drivers/staging/line6/pod.c
@@ -912,33 +912,33 @@
 #undef GET_SYSTEM_PARAM
 
 /* POD special files: */
-static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel);
+static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel, pod_set_channel);
 static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
 static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
 static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
-static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
-static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf);
-static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
+static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump);
+static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf);
+static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish);
 static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write);
-static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess);
-static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level);
+static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess);
+static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level);
 static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
 static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
-static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup);
-static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel);
-static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup);
-static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing);
+static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read, pod_set_retrieve_amp_setup);
+static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read, pod_set_retrieve_channel);
+static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read, pod_set_retrieve_effects_setup);
+static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing, pod_set_routing);
 static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write);
-static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup);
-static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel);
-static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup);
-static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq);
-static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute);
+static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read, pod_set_store_amp_setup);
+static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read, pod_set_store_channel);
+static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read, pod_set_store_effects_setup);
+static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq);
+static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute);
 static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
 static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
 
 #if CREATE_RAW_FILE
-static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
+static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
 #endif
 
 /*
--- linux-ec2-2.6.32.orig/drivers/staging/line6/toneport.c
+++ linux-ec2-2.6.32/drivers/staging/line6/toneport.c
@@ -117,8 +117,8 @@
 	return count;
 }
 
-static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_red);
-static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_green);
+static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read, toneport_set_led_red);
+static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read, toneport_set_led_green);
 
 
 static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
--- linux-ec2-2.6.32.orig/drivers/staging/line6/Kconfig
+++ linux-ec2-2.6.32/drivers/staging/line6/Kconfig
@@ -2,6 +2,7 @@
 	tristate "Line6 USB support"
 	depends on USB && SND
 	select SND_RAWMIDI
+	select SND_PCM
 	help
 	  This is a driver for the guitar amp, cab, and effects modeller
 	  PODxt Pro by Line6 (and similar devices), supporting the
--- linux-ec2-2.6.32.orig/drivers/staging/line6/midi.c
+++ linux-ec2-2.6.32/drivers/staging/line6/midi.c
@@ -349,8 +349,8 @@
 	return count;
 }
 
-static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
-static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive);
+static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
+static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive);
 
 /* MIDI device destructor */
 static int snd_line6_midi_free(struct snd_device *device)
--- linux-ec2-2.6.32.orig/drivers/staging/line6/variax.c
+++ linux-ec2-2.6.32/drivers/staging/line6/variax.c
@@ -366,17 +366,17 @@
 #endif
 
 /* Variax workbench special files: */
-static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model, variax_set_model);
-static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume, variax_set_volume);
-static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone);
+static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model, variax_set_model);
+static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume, variax_set_volume);
+static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
 static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
 static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
-static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active);
+static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active, variax_set_active);
 
 #if CREATE_RAW_FILE
-static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
-static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2);
+static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
+static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
 #endif
 
 
--- linux-ec2-2.6.32.orig/drivers/staging/pohmelfs/inode.c
+++ linux-ec2-2.6.32/drivers/staging/pohmelfs/inode.c
@@ -143,7 +143,6 @@
 	struct inode *inode = mapping->host;
 	struct pohmelfs_inode *pi = POHMELFS_I(inode);
 	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb);
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	int err = 0;
 	int done = 0;
 	int nr_pages;
@@ -152,11 +151,6 @@
 	int scanned = 0;
 	int range_whole = 0;
 
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		return 0;
-	}
-
 	if (wbc->range_cyclic) {
 		index = mapping->writeback_index; /* Start from prev offset */
 		end = -1;
@@ -248,10 +242,6 @@
 
 			if (wbc->nr_to_write <= 0)
 				done = 1;
-			if (wbc->nonblocking && bdi_write_congested(bdi)) {
-				wbc->encountered_congestion = 1;
-				done = 1;
-			}
 
 			continue;
 out_continue:
--- linux-ec2-2.6.32.orig/drivers/staging/rt2860/common/2860_rtmp_init.c
+++ linux-ec2-2.6.32/drivers/staging/rt2860/common/2860_rtmp_init.c
@@ -716,7 +716,7 @@
 	{
 		if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
 		{
-			PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
+			PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
 			RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
 		}
 	}
--- linux-ec2-2.6.32.orig/drivers/staging/hv/storvsc_drv.c
+++ linux-ec2-2.6.32/drivers/staging/hv/storvsc_drv.c
@@ -532,7 +532,7 @@
 
 		ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
 
-		if (j == 0)
+		if (bounce_addr == 0)
 			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
 
 		while (srclen) {
@@ -593,7 +593,7 @@
 		destlen = orig_sgl[i].length;
 		ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
 
-		if (j == 0)
+		if (bounce_addr == 0)
 			bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
 
 		while (destlen) {
@@ -652,6 +652,7 @@
 	unsigned int request_size = 0;
 	int i;
 	struct scatterlist *sgl;
+	unsigned int sg_count = 0;
 
 	DPRINT_ENTER(STORVSC_DRV);
 
@@ -736,6 +737,7 @@
 	request->DataBuffer.Length = scsi_bufflen(scmnd);
 	if (scsi_sg_count(scmnd)) {
 		sgl = (struct scatterlist *)scsi_sglist(scmnd);
+		sg_count = scsi_sg_count(scmnd);
 
 		/* check if we need to bounce the sgl */
 		if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
@@ -770,11 +772,12 @@
 					      scsi_sg_count(scmnd));
 
 			sgl = cmd_request->bounce_sgl;
+			sg_count = cmd_request->bounce_sgl_count;
 		}
 
 		request->DataBuffer.Offset = sgl[0].offset;
 
-		for (i = 0; i < scsi_sg_count(scmnd); i++) {
+		for (i = 0; i < sg_count; i++) {
 			DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d \n",
 				   i, sgl[i].length, sgl[i].offset);
 			request->DataBuffer.PfnArray[i] =
--- linux-ec2-2.6.32.orig/drivers/staging/hv/vmbus_drv.c
+++ linux-ec2-2.6.32/drivers/staging/hv/vmbus_drv.c
@@ -24,6 +24,8 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
 #include "osd.h"
 #include "logging.h"
 #include "vmbus.h"
@@ -946,6 +948,19 @@
 	}
 }
 
+static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
+	{
+		.ident = "Hyper-V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+		},
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
+
 static int __init vmbus_init(void)
 {
 	int ret = 0;
@@ -957,6 +972,9 @@
 		vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
 	/* Todo: it is used for loglevel, to be ported to new kernel. */
 
+	if (!dmi_check_system(microsoft_hv_dmi_table))
+		return -ENODEV;
+
 	ret = vmbus_bus_init(VmbusInitialize);
 
 	DPRINT_EXIT(VMBUS_DRV);
@@ -973,6 +991,18 @@
 	return;
 }
 
+/*
+ * We use a PCI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+	{ PCI_DEVICE(0x1414, 0x5353) },	/* VGA compatible controller */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+
 MODULE_LICENSE("GPL");
 module_param(vmbus_irq, int, S_IRUGO);
 module_param(vmbus_loglevel, int, S_IRUGO);
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Hv.c
+++ linux-ec2-2.6.32/drivers/staging/hv/Hv.c
@@ -306,9 +306,9 @@
 	DPRINT_ENTER(VMBUS);
 
 	if (gHvContext.SignalEventBuffer) {
+		kfree(gHvContext.SignalEventBuffer);
 		gHvContext.SignalEventBuffer = NULL;
 		gHvContext.SignalEventParam = NULL;
-		kfree(gHvContext.SignalEventBuffer);
 	}
 
 	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
@@ -386,7 +386,7 @@
  * retrieve the initialized message and event pages.  Otherwise, we create and
  * initialize the message and event pages.
  */
-int HvSynicInit(u32 irqVector)
+void HvSynicInit(void *irqarg)
 {
 	u64 version;
 	union hv_synic_simp simp;
@@ -394,13 +394,14 @@
 	union hv_synic_sint sharedSint;
 	union hv_synic_scontrol sctrl;
 	u64 guestID;
-	int ret = 0;
+	u32 irqVector = *((u32 *)(irqarg));
+	int cpu = smp_processor_id();
 
 	DPRINT_ENTER(VMBUS);
 
 	if (!gHvContext.HypercallPage) {
 		DPRINT_EXIT(VMBUS);
-		return ret;
+		return;
 	}
 
 	/* Check the version */
@@ -425,27 +426,27 @@
 		 */
 		rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
 		if (guestID == HV_LINUX_GUEST_ID) {
-			gHvContext.synICMessagePage[0] =
+			gHvContext.synICMessagePage[cpu] =
 				phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
-			gHvContext.synICEventPage[0] =
+			gHvContext.synICEventPage[cpu] =
 				phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
 		} else {
 			DPRINT_ERR(VMBUS, "unknown guest id!!");
 			goto Cleanup;
 		}
 		DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p",
-			   gHvContext.synICMessagePage[0],
-			   gHvContext.synICEventPage[0]);
+			   gHvContext.synICMessagePage[cpu],
+			   gHvContext.synICEventPage[cpu]);
 	} else {
-		gHvContext.synICMessagePage[0] = osd_PageAlloc(1);
-		if (gHvContext.synICMessagePage[0] == NULL) {
+		gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
+		if (gHvContext.synICMessagePage[cpu] == NULL) {
 			DPRINT_ERR(VMBUS,
 				   "unable to allocate SYNIC message page!!");
 			goto Cleanup;
 		}
 
-		gHvContext.synICEventPage[0] = osd_PageAlloc(1);
-		if (gHvContext.synICEventPage[0] == NULL) {
+		gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
+		if (gHvContext.synICEventPage[cpu] == NULL) {
 			DPRINT_ERR(VMBUS,
 				   "unable to allocate SYNIC event page!!");
 			goto Cleanup;
@@ -454,7 +455,7 @@
 		/* Setup the Synic's message page */
 		rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
 		simp.SimpEnabled = 1;
-		simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0])
+		simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
 					>> PAGE_SHIFT;
 
 		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx",
@@ -465,7 +466,7 @@
 		/* Setup the Synic's event page */
 		rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
 		siefp.SiefpEnabled = 1;
-		siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0])
+		siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
 					>> PAGE_SHIFT;
 
 		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx",
@@ -501,32 +502,30 @@
 
 	DPRINT_EXIT(VMBUS);
 
-	return ret;
+	return;
 
 Cleanup:
-	ret = -1;
-
 	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
-		if (gHvContext.synICEventPage[0])
-			osd_PageFree(gHvContext.synICEventPage[0], 1);
+		if (gHvContext.synICEventPage[cpu])
+			osd_PageFree(gHvContext.synICEventPage[cpu], 1);
 
-		if (gHvContext.synICMessagePage[0])
-			osd_PageFree(gHvContext.synICMessagePage[0], 1);
+		if (gHvContext.synICMessagePage[cpu])
+			osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
 	}
 
 	DPRINT_EXIT(VMBUS);
-
-	return ret;
+	return;
 }
 
 /**
  * HvSynicCleanup - Cleanup routine for HvSynicInit().
  */
-void HvSynicCleanup(void)
+void HvSynicCleanup(void *arg)
 {
 	union hv_synic_sint sharedSint;
 	union hv_synic_simp simp;
 	union hv_synic_siefp siefp;
+	int cpu = smp_processor_id();
 
 	DPRINT_ENTER(VMBUS);
 
@@ -539,6 +538,7 @@
 
 	sharedSint.Masked = 1;
 
+	/* Need to correctly cleanup in the case of SMP!!! */
 	/* Disable the interrupt */
 	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
 
@@ -560,8 +560,8 @@
 
 		wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
 
-		osd_PageFree(gHvContext.synICMessagePage[0], 1);
-		osd_PageFree(gHvContext.synICEventPage[0], 1);
+		osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
+		osd_PageFree(gHvContext.synICEventPage[cpu], 1);
 	}
 
 	DPRINT_EXIT(VMBUS);
--- linux-ec2-2.6.32.orig/drivers/staging/hv/StorVscApi.h
+++ linux-ec2-2.6.32/drivers/staging/hv/StorVscApi.h
@@ -28,10 +28,10 @@
 #include "VmbusApi.h"
 
 /* Defines */
-#define STORVSC_RING_BUFFER_SIZE			(10*PAGE_SIZE)
+#define STORVSC_RING_BUFFER_SIZE			(20*PAGE_SIZE)
 #define BLKVSC_RING_BUFFER_SIZE				(20*PAGE_SIZE)
 
-#define STORVSC_MAX_IO_REQUESTS				64
+#define STORVSC_MAX_IO_REQUESTS				128
 
 /*
  * In Hyper-V, each port/path/target maps to 1 scsi host adapter.  In
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Hv.h
+++ linux-ec2-2.6.32/drivers/staging/hv/Hv.h
@@ -93,7 +93,7 @@
 	},
 };
 
-#define MAX_NUM_CPUS	1
+#define MAX_NUM_CPUS	32
 
 
 struct hv_input_signal_event_buffer {
@@ -137,8 +137,8 @@
 
 extern u16 HvSignalEvent(void);
 
-extern int HvSynicInit(u32 irqVector);
+extern void HvSynicInit(void *irqarg);
 
-extern void HvSynicCleanup(void);
+extern void HvSynicCleanup(void *arg);
 
 #endif /* __HV_H__ */
--- linux-ec2-2.6.32.orig/drivers/staging/hv/netvsc_drv.c
+++ linux-ec2-2.6.32/drivers/staging/hv/netvsc_drv.c
@@ -44,6 +44,7 @@
 	/* point back to our device context */
 	struct device_context *device_ctx;
 	struct net_device_stats stats;
+	struct work_struct work;
 };
 
 struct netvsc_driver_context {
@@ -284,6 +285,7 @@
 {
 	struct device_context *device_ctx = to_device_context(device_obj);
 	struct net_device *net = dev_get_drvdata(&device_ctx->device);
+	struct net_device_context *ndev_ctx;
 
 	DPRINT_ENTER(NETVSC_DRV);
 
@@ -296,6 +298,9 @@
 	if (status == 1) {
 		netif_carrier_on(net);
 		netif_wake_queue(net);
+		netif_notify_peers(net);
+		ndev_ctx = netdev_priv(net);
+		schedule_work(&ndev_ctx->work);
 	} else {
 		netif_carrier_off(net);
 		netif_stop_queue(net);
@@ -392,8 +397,30 @@
 	.ndo_start_xmit =		netvsc_start_xmit,
 	.ndo_get_stats =		netvsc_get_stats,
 	.ndo_set_multicast_list =	netvsc_set_multicast_list,
+	.ndo_change_mtu =		eth_change_mtu,
+	.ndo_validate_addr =		eth_validate_addr,
+	.ndo_set_mac_address =		eth_mac_addr,
 };
 
+/*
+ * Send GARP packet to network peers after migrations.
+ * After Quick Migration, the network is not immediately operational in the
+ * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
+ * another netif_notify_peers() into a scheduled work, otherwise GARP packet
+ * will not be sent after quick migration, and cause network disconnection.
+ */
+static void netvsc_send_garp(struct work_struct *w)
+{
+	struct net_device_context *ndev_ctx;
+	struct net_device *net;
+
+	msleep(20);
+	ndev_ctx = container_of(w, struct net_device_context, work);
+	net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
+	netif_notify_peers(net);
+}
+
+
 static int netvsc_probe(struct device *device)
 {
 	struct driver_context *driver_ctx =
@@ -413,8 +440,7 @@
 	if (!net_drv_obj->Base.OnDeviceAdd)
 		return -1;
 
-	net = alloc_netdev(sizeof(struct net_device_context), "seth%d",
-			   ether_setup);
+	net = alloc_etherdev(sizeof(struct net_device_context));
 	if (!net)
 		return -1;
 
@@ -425,6 +451,7 @@
 	net_device_ctx = netdev_priv(net);
 	net_device_ctx->device_ctx = device_ctx;
 	dev_set_drvdata(device, net);
+	INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
 
 	/* Notify the netvsc driver of the new device */
 	ret = net_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
--- linux-ec2-2.6.32.orig/drivers/staging/hv/VmbusPrivate.h
+++ linux-ec2-2.6.32/drivers/staging/hv/VmbusPrivate.h
@@ -32,6 +32,7 @@
 #include "ChannelInterface.h"
 #include "RingBuffer.h"
 #include <linux/list.h>
+#include <asm/sync_bitops.h>
 
 
 /*
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Channel.c
+++ linux-ec2-2.6.32/drivers/staging/hv/Channel.c
@@ -75,14 +75,14 @@
 
 	if (Channel->OfferMsg.MonitorAllocated) {
 		/* Each u32 represents 32 channels */
-		set_bit(Channel->OfferMsg.ChildRelId & 31,
+		sync_set_bit(Channel->OfferMsg.ChildRelId & 31,
 			(unsigned long *) gVmbusConnection.SendInterruptPage +
 			(Channel->OfferMsg.ChildRelId >> 5));
 
 		monitorPage = gVmbusConnection.MonitorPages;
 		monitorPage++; /* Get the child to parent monitor page */
 
-		set_bit(Channel->MonitorBit,
+		sync_set_bit(Channel->MonitorBit,
 			(unsigned long *)&monitorPage->TriggerGroup
 					[Channel->MonitorGroup].Pending);
 
@@ -102,7 +102,7 @@
 
 	if (Channel->OfferMsg.MonitorAllocated) {
 		/* Each u32 represents 32 channels */
-		clear_bit(Channel->OfferMsg.ChildRelId & 31,
+		sync_clear_bit(Channel->OfferMsg.ChildRelId & 31,
 			  (unsigned long *)gVmbusConnection.SendInterruptPage +
 			  (Channel->OfferMsg.ChildRelId >> 5));
 
@@ -110,7 +110,7 @@
 			(struct hv_monitor_page *)gVmbusConnection.MonitorPages;
 		monitorPage++; /* Get the child to parent monitor page */
 
-		clear_bit(Channel->MonitorBit,
+		sync_clear_bit(Channel->MonitorBit,
 			  (unsigned long *)&monitorPage->TriggerGroup
 					[Channel->MonitorGroup].Pending);
 	}
--- linux-ec2-2.6.32.orig/drivers/staging/hv/RndisFilter.c
+++ linux-ec2-2.6.32/drivers/staging/hv/RndisFilter.c
@@ -756,6 +756,7 @@
 
 	ret = RndisFilterSetPacketFilter(Device,
 					 NDIS_PACKET_TYPE_BROADCAST |
+					 NDIS_PACKET_TYPE_ALL_MULTICAST |
 					 NDIS_PACKET_TYPE_DIRECTED);
 	if (ret == 0)
 		Device->State = RNDIS_DEV_DATAINITIALIZED;
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Kconfig
+++ linux-ec2-2.6.32/drivers/staging/hv/Kconfig
@@ -1,6 +1,6 @@
 config HYPERV
 	tristate "Microsoft Hyper-V client drivers"
-	depends on X86 && m
+	depends on X86 && !XEN && m
 	default n
 	help
 	  Select this option to run Linux as a Hyper-V client operating
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Connection.c
+++ linux-ec2-2.6.32/drivers/staging/hv/Connection.c
@@ -284,7 +284,9 @@
 		for (dword = 0; dword < maxdword; dword++) {
 			if (recvInterruptPage[dword]) {
 				for (bit = 0; bit < 32; bit++) {
-					if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
+					if (sync_test_and_clear_bit(bit,
+						(unsigned long *)
+						&recvInterruptPage[dword])) {
 						relid = (dword << 5) + bit;
 						DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
 
@@ -329,7 +331,7 @@
 	DPRINT_ENTER(VMBUS);
 
 	/* Each u32 represents 32 channels */
-	set_bit(childRelId & 31,
+	sync_set_bit(childRelId & 31,
 		(unsigned long *)gVmbusConnection.SendInterruptPage +
 		(childRelId >> 5));
 
--- linux-ec2-2.6.32.orig/drivers/staging/hv/Vmbus.c
+++ linux-ec2-2.6.32/drivers/staging/hv/Vmbus.c
@@ -129,7 +129,7 @@
 
 	/* strcpy(dev->name, "vmbus"); */
 	/* SynIC setup... */
-	ret = HvSynicInit(*irqvector);
+	on_each_cpu(HvSynicInit, (void *)irqvector, 1);
 
 	/* Connect to VMBus in the root partition */
 	ret = VmbusConnect();
@@ -150,7 +150,7 @@
 	DPRINT_ENTER(VMBUS);
 	VmbusChannelReleaseUnattachedChannels();
 	VmbusDisconnect();
-	HvSynicCleanup();
+	on_each_cpu(HvSynicCleanup, NULL, 1);
 	DPRINT_EXIT(VMBUS);
 
 	return ret;
@@ -173,7 +173,8 @@
  */
 static void VmbusOnMsgDPC(struct hv_driver *drv)
 {
-	void *page_addr = gHvContext.synICMessagePage[0];
+	int cpu = smp_processor_id();
+	void *page_addr = gHvContext.synICMessagePage[cpu];
 	struct hv_message *msg = (struct hv_message *)page_addr +
 				  VMBUS_MESSAGE_SINT;
 	struct hv_message *copied;
@@ -230,11 +231,12 @@
 static int VmbusOnISR(struct hv_driver *drv)
 {
 	int ret = 0;
+	int cpu = smp_processor_id();
 	void *page_addr;
 	struct hv_message *msg;
 	union hv_synic_event_flags *event;
 
-	page_addr = gHvContext.synICMessagePage[0];
+	page_addr = gHvContext.synICMessagePage[cpu];
 	msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
 
 	DPRINT_ENTER(VMBUS);
@@ -248,11 +250,11 @@
 	}
 
 	/* TODO: Check if there are events to be process */
-	page_addr = gHvContext.synICEventPage[0];
+	page_addr = gHvContext.synICEventPage[cpu];
 	event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
 
 	/* Since we are a child, we only need to check bit 0 */
-	if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) {
+	if (sync_test_and_clear_bit(0, (unsigned long *) &event->Flags32[0])) {
 		DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
 		ret |= 0x2;
 	}
--- linux-ec2-2.6.32.orig/drivers/staging/hv/RingBuffer.c
+++ linux-ec2-2.6.32/drivers/staging/hv/RingBuffer.c
@@ -192,7 +192,7 @@
 static inline u64
 GetRingBufferIndices(RING_BUFFER_INFO* RingInfo)
 {
-	return ((u64)RingInfo->RingBuffer->WriteIndex << 32) || RingInfo->RingBuffer->ReadIndex;
+	return (u64)RingInfo->RingBuffer->WriteIndex << 32;
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/staging/hv/blkvsc_drv.c
+++ linux-ec2-2.6.32/drivers/staging/hv/blkvsc_drv.c
@@ -378,6 +378,7 @@
 		blkdev->gd->first_minor = 0;
 	blkdev->gd->fops = &block_ops;
 	blkdev->gd->private_data = blkdev;
+	blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
 	sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum);
 
 	blkvsc_do_inquiry(blkdev);
--- linux-ec2-2.6.32.orig/drivers/staging/asus_oled/asus_oled.c
+++ linux-ec2-2.6.32/drivers/staging/asus_oled/asus_oled.c
@@ -194,9 +194,11 @@
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct asus_oled_dev *odev = usb_get_intfdata(intf);
-	int temp = strict_strtoul(buf, 10, NULL);
+	unsigned long value;
+	if (strict_strtoul(buf, 10, &value))
+		return -EINVAL;
 
-	enable_oled(odev, temp);
+	enable_oled(odev, value);
 
 	return count;
 }
@@ -207,10 +209,12 @@
 {
 	struct asus_oled_dev *odev =
 		(struct asus_oled_dev *) dev_get_drvdata(device);
+	unsigned long value;
 
-	int temp = strict_strtoul(buf, 10, NULL);
+	if (strict_strtoul(buf, 10, &value))
+		return -EINVAL;
 
-	enable_oled(odev, temp);
+	enable_oled(odev, value);
 
 	return count;
 }
@@ -605,13 +609,13 @@
 
 #define ASUS_OLED_DEVICE_ATTR(_file)		dev_attr_asus_oled_##_file
 
-static DEVICE_ATTR(asus_oled_enabled, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO,
 		   get_enabled, set_enabled);
-static DEVICE_ATTR(asus_oled_picture, S_IWUGO , NULL, set_picture);
+static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture);
 
-static DEVICE_ATTR(enabled, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO,
 		   class_get_enabled, class_set_enabled);
-static DEVICE_ATTR(picture, S_IWUGO, NULL, class_set_picture);
+static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture);
 
 static int asus_oled_probe(struct usb_interface *interface,
 			   const struct usb_device_id *id)
--- linux-ec2-2.6.32.orig/drivers/staging/vt6655/device_main.c
+++ linux-ec2-2.6.32/drivers/staging/vt6655/device_main.c
@@ -1089,11 +1089,13 @@
     }
 //2008-07-21-01<Add>by MikeLiu
 //register wpadev
+#if 0
    if(wpa_set_wpadev(pDevice, 1)!=0) {
      printk("Fail to Register WPADEV?\n");
         unregister_netdev(pDevice->dev);
         free_netdev(dev);
    }
+#endif
     device_print_info(pDevice);
     pci_set_drvdata(pcid, pDevice);
     return 0;
--- linux-ec2-2.6.32.orig/drivers/staging/vt6655/ttype.h
+++ linux-ec2-2.6.32/drivers/staging/vt6655/ttype.h
@@ -30,6 +30,9 @@
 #ifndef __TTYPE_H__
 #define __TTYPE_H__
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#endif
 
 /******* Common definitions and typedefs ***********************************/
 
--- linux-ec2-2.6.32.orig/drivers/staging/vt6655/wpactl.c
+++ linux-ec2-2.6.32/drivers/staging/vt6655/wpactl.c
@@ -767,9 +767,14 @@
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
 
 
-	if (param->u.wpa_associate.wpa_ie &&
-	    copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
-	    return -EINVAL;
+	if (param->u.wpa_associate.wpa_ie_len) {
+		if (!param->u.wpa_associate.wpa_ie)
+			return -EINVAL;
+		if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
+			return -EINVAL;
+		if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len))
+			return -EFAULT;
+	}
 
 	if (param->u.wpa_associate.mode == 1)
 	    pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/comedi.h
+++ linux-ec2-2.6.32/drivers/staging/comedi/comedi.h
@@ -455,7 +455,7 @@
 
 #define COMEDI_CB_EOS		1	/* end of scan */
 #define COMEDI_CB_EOA		2	/* end of acquisition */
-#define COMEDI_CB_BLOCK		4	/* DEPRECATED: convenient block size */
+#define COMEDI_CB_BLOCK		4	/* data has arrived: wakes up read() / write() */
 #define COMEDI_CB_EOBUF		8	/* DEPRECATED: end of buffer */
 #define COMEDI_CB_ERROR		16	/* card error during acquisition */
 #define COMEDI_CB_OVERFLOW	32	/* buffer overflow/underflow */
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/Kconfig
+++ linux-ec2-2.6.32/drivers/staging/comedi/Kconfig
@@ -16,6 +16,7 @@
 config COMEDI_PCI_DRIVERS
 	tristate "Comedi PCI drivers"
 	depends on COMEDI && PCI
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable lots of comedi PCI drivers to be built
@@ -23,6 +24,7 @@
 config COMEDI_PCMCIA_DRIVERS
 	tristate "Comedi PCMCIA drivers"
 	depends on COMEDI && PCMCIA && PCCARD
+	select COMEDI_8255
 	default N
 	---help---
 	  Enable lots of comedi PCMCIA and PCCARD drivers to be built
@@ -33,3 +35,6 @@
 	default N
 	---help---
 	  Enable lots of comedi USB drivers to be built
+
+config COMEDI_8255
+	tristate
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/drivers/jr3_pci.c
+++ linux-ec2-2.6.32/drivers/staging/comedi/drivers/jr3_pci.c
@@ -52,6 +52,7 @@
 
 #define PCI_VENDOR_ID_JR3 0x1762
 #define PCI_DEVICE_ID_JR3_1_CHANNEL 0x3111
+#define PCI_DEVICE_ID_JR3_1_CHANNEL_NEW 0x1111
 #define PCI_DEVICE_ID_JR3_2_CHANNEL 0x3112
 #define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
 #define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
@@ -71,6 +72,8 @@
 	{
 	PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL,
 		    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
+	PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW,
+		    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL,
 		    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL,
@@ -807,6 +810,10 @@
 					devpriv->n_channels = 1;
 				}
 				break;
+			case PCI_DEVICE_ID_JR3_1_CHANNEL_NEW:{
+					devpriv->n_channels = 1;
+				}
+				break;
 			case PCI_DEVICE_ID_JR3_2_CHANNEL:{
 					devpriv->n_channels = 2;
 				}
@@ -849,8 +856,11 @@
 	}
 
 	devpriv->pci_enabled = 1;
-	devpriv->iobase =
-	    ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t));
+	devpriv->iobase = ioremap(pci_resource_start(card, 0),
+			offsetof(struct jr3_t, channel[devpriv->n_channels]));
+	if (!devpriv->iobase)
+		return -ENOMEM;
+
 	result = alloc_subdevices(dev, devpriv->n_channels);
 	if (result < 0)
 		goto out;
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/drivers/ni_labpc.c
+++ linux-ec2-2.6.32/drivers/staging/comedi/drivers/ni_labpc.c
@@ -528,7 +528,8 @@
 	/* grab our IRQ */
 	if (irq) {
 		isr_flags = 0;
-		if (thisboard->bustype == pci_bustype)
+		if (thisboard->bustype == pci_bustype
+		    || thisboard->bustype == pcmcia_bustype)
 			isr_flags |= IRQF_SHARED;
 		if (request_irq(irq, labpc_interrupt, isr_flags,
 				driver_labpc.driver_name, dev)) {
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/drivers/Makefile
+++ linux-ec2-2.6.32/drivers/staging/comedi/drivers/Makefile
@@ -8,8 +8,10 @@
 obj-$(CONFIG_COMEDI)			+= comedi_parport.o
 obj-$(CONFIG_COMEDI)			+= pcm_common.o
 
+# Comedi 8255 module
+obj-$(CONFIG_COMEDI_8255)		+= 8255.o
+
 # Comedi PCI drivers
-obj-$(CONFIG_COMEDI_PCI_DRIVERS)	+= 8255.o
 obj-$(CONFIG_COMEDI_PCI_DRIVERS)	+= acl7225b.o
 obj-$(CONFIG_COMEDI_PCI_DRIVERS)	+= addi_apci_035.o
 obj-$(CONFIG_COMEDI_PCI_DRIVERS)	+= addi_apci_1032.o
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ linux-ec2-2.6.32/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -123,7 +123,7 @@
 	 .adbits = 12,
 	 .ai_fifo_depth = 1024,
 	 .alwaysdither = 0,
-	 .gainlkup = ai_gain_16,
+	 .gainlkup = ai_gain_4,
 	 .ai_speed = 5000,
 	 .n_aochan = 2,
 	 .aobits = 12,
--- linux-ec2-2.6.32.orig/drivers/staging/comedi/drivers/usbdux.c
+++ linux-ec2-2.6.32/drivers/staging/comedi/drivers/usbdux.c
@@ -1,4 +1,4 @@
-#define DRIVER_VERSION "v2.2"
+#define DRIVER_VERSION "v2.4"
 #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
 #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
 /*
@@ -80,6 +80,9 @@
  * 2.0:  PWM seems to be stable and is not interfering with the other functions
  * 2.1:  changed PWM API
  * 2.2:  added firmware kernel request to fix an udev problem
+ * 2.3:  corrected a bug in bulk timeouts which were far too short
+ * 2.4:  fixed a bug which causes the driver to hang when it ran out of data.
+ *       Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
  *
  */
 
@@ -101,8 +104,8 @@
 
 #define BOARDNAME "usbdux"
 
-/* timeout for the USB-transfer */
-#define EZTIMEOUT 30
+/* timeout for the USB-transfer in ms*/
+#define BULK_TIMEOUT 1000
 
 /* constants for "firmware" upload and download */
 #define USBDUXSUB_FIRMWARE 0xA0
@@ -531,6 +534,7 @@
 		}
 	}
 	/* tell comedi that data is there */
+	s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
 	comedi_event(this_usbduxsub->comedidev, s);
 }
 
@@ -750,7 +754,7 @@
 				  /* Length */
 				  1,
 				  /* Timeout */
-				  EZTIMEOUT);
+				  BULK_TIMEOUT);
 	if (errcode < 0) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: control msg failed (start)\n");
@@ -780,7 +784,7 @@
 				  /* Length */
 				  1,
 				  /* Timeout */
-				  EZTIMEOUT);
+				  BULK_TIMEOUT);
 	if (errcode < 0) {
 		dev_err(&usbduxsub->interface->dev,
 			"comedi_: control msg failed (stop)\n");
@@ -810,7 +814,7 @@
 				  /* length */
 				  len,
 				  /* timeout */
-				  EZTIMEOUT);
+				  BULK_TIMEOUT);
 	dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
 	if (errcode < 0) {
 		dev_err(&usbduxsub->interface->dev, "comedi_: upload failed\n");
@@ -1110,7 +1114,7 @@
 			      usb_sndbulkpipe(this_usbduxsub->usbdev,
 					      COMMAND_OUT_EP),
 			      this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
-			      &nsent, 10);
+			      &nsent, BULK_TIMEOUT);
 	if (result < 0)
 		dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
 			"could not transmit dux_command to the usb-device, "
@@ -1130,7 +1134,7 @@
 				      usb_rcvbulkpipe(this_usbduxsub->usbdev,
 						      COMMAND_IN_EP),
 				      this_usbduxsub->insnBuffer, SIZEINSNBUF,
-				      &nrec, 1);
+				      &nrec, BULK_TIMEOUT);
 		if (result < 0) {
 			dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
 				"insn: USB error %d while receiving DUX command"
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8192su/r819xU_cmdpkt.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8192su/r819xU_cmdpkt.c
@@ -56,6 +56,12 @@
 
 	//Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
 	skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
+	if (skb == NULL) {
+		RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n",
+								__func__);
+		rtStatus = false;
+		return rtStatus;
+	}
 	memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
 	tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
 	tcb_desc->queue_index = TXCMD_QUEUE;
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8192su/r8192S_firmware.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8192su/r8192S_firmware.c
@@ -68,6 +68,11 @@
 
 		/* Allocate skb buffer to contain firmware info and tx descriptor info. */
 		skb  = dev_alloc_skb(frag_length);
+		if (skb == NULL) {
+			RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n",
+								__func__);
+			goto cmdsend_downloadcode_fail;
+		}
 		memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
 
 		tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8192su/r8192U_core.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8192su/r8192U_core.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/vmalloc.h>
+#include <linux/notifier.h>
 
 #undef LOOP_TEST
 #undef DUMP_RX
@@ -111,23 +112,30 @@
 #define CAM_CONTENT_COUNT 8
 
 static struct usb_device_id rtl8192_usb_id_tbl[] = {
-	/* Realtek */
-	{USB_DEVICE(0x0bda, 0x8192)},
-	{USB_DEVICE(0x0bda, 0x8709)},
-	/* Corega */
-	{USB_DEVICE(0x07aa, 0x0043)},
-	/* Belkin */
-	{USB_DEVICE(0x050d, 0x805E)},
-	/* Sitecom */
-	{USB_DEVICE(0x0df6, 0x0031)},
-	/* EnGenius */
-	{USB_DEVICE(0x1740, 0x9201)},
-	/* Dlink */
-	{USB_DEVICE(0x2001, 0x3301)},
-	/* Zinwell */
-	{USB_DEVICE(0x5a57, 0x0290)},
-	//92SU
+	{USB_DEVICE(0x0bda, 0x8171)}, /* Realtek */
 	{USB_DEVICE(0x0bda, 0x8172)},
+	{USB_DEVICE(0x0bda, 0x8173)},
+	{USB_DEVICE(0x0bda, 0x8174)},
+	{USB_DEVICE(0x0bda, 0x8712)},
+	{USB_DEVICE(0x0bda, 0x8713)},
+	{USB_DEVICE(0x07aa, 0x0047)},
+	{USB_DEVICE(0x07d1, 0x3303)},
+	{USB_DEVICE(0x07d1, 0x3302)},
+	{USB_DEVICE(0x07d1, 0x3300)},
+	{USB_DEVICE(0x1740, 0x9603)},
+	{USB_DEVICE(0x1740, 0x9605)},
+	{USB_DEVICE(0x050d, 0x815F)},
+	{USB_DEVICE(0x06f8, 0xe031)},
+	{USB_DEVICE(0x7392, 0x7611)},
+	{USB_DEVICE(0x7392, 0x7612)},
+	{USB_DEVICE(0x7392, 0x7622)},
+	{USB_DEVICE(0x0DF6, 0x0045)},
+	{USB_DEVICE(0x0E66, 0x0015)},
+	{USB_DEVICE(0x0E66, 0x0016)},
+	{USB_DEVICE(0x0b05, 0x1786)},
+	/* these are not in the official list */
+	{USB_DEVICE(0x050d, 0x815F)}, /* Belkin F5D8053 v6 */
+	{USB_DEVICE(0x0df6, 0x004b)}, /* WL-349 */
 	{}
 };
 
@@ -155,6 +163,8 @@
 static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id);
 static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf);
+static const struct net_device_ops rtl8192_netdev_ops;
+static struct notifier_block proc_netdev_notifier;
 
 static struct usb_driver rtl8192_usb_driver = {
 	.name		= RTL819xU_MODULE_NAME,	          /* Driver name   */
@@ -954,15 +964,24 @@
 	return len;
 }
 
-void rtl8192_proc_module_init(void)
+int rtl8192_proc_module_init(void)
 {
+	int ret;
+
 	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
 	rtl8192_proc=create_proc_entry(RTL819xU_MODULE_NAME, S_IFDIR, init_net.proc_net);
+	if (!rtl8192_proc)
+		return -ENOMEM;
+	ret = register_netdevice_notifier(&proc_netdev_notifier);
+	if (ret)
+		remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
+	return ret;
 }
 
 
 void rtl8192_proc_module_remove(void)
 {
+	unregister_netdevice_notifier(&proc_netdev_notifier);
 	remove_proc_entry(RTL819xU_MODULE_NAME, init_net.proc_net);
 }
 
@@ -990,8 +1009,7 @@
 		remove_proc_entry("registers-e", priv->dir_dev);
 	//	remove_proc_entry("cck-registers",priv->dir_dev);
 	//	remove_proc_entry("ofdm-registers",priv->dir_dev);
-		//remove_proc_entry(dev->name, rtl8192_proc);
-		remove_proc_entry("wlan0", rtl8192_proc);
+		remove_proc_entry(priv->dir_dev->name, rtl8192_proc);
 		priv->dir_dev = NULL;
 	}
 }
@@ -1108,6 +1126,25 @@
 		      dev->name);
 	}
 }
+
+static int proc_netdev_event(struct notifier_block *this,
+			     unsigned long event, void *ptr)
+{
+	struct net_device *net_dev = ptr;
+
+	if (net_dev->netdev_ops == &rtl8192_netdev_ops &&
+	    event == NETDEV_CHANGENAME) {
+		rtl8192_proc_remove_one(net_dev);
+		rtl8192_proc_init_one(net_dev);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block proc_netdev_notifier = {
+	.notifier_call = proc_netdev_event,
+};
+
 /****************************************************************************
    -----------------------------MISC STUFF-------------------------
 *****************************************************************************/
@@ -7559,35 +7596,63 @@
 	ret = ieee80211_crypto_init();
 	if (ret) {
 		printk(KERN_ERR "ieee80211_crypto_init() failed %d\n", ret);
-		return ret;
+		goto fail_crypto;
 	}
 
 	ret = ieee80211_crypto_tkip_init();
 	if (ret) {
 		printk(KERN_ERR "ieee80211_crypto_tkip_init() failed %d\n",
 			ret);
-		return ret;
+		goto fail_crypto_tkip;
 	}
 
 	ret = ieee80211_crypto_ccmp_init();
 	if (ret) {
 		printk(KERN_ERR "ieee80211_crypto_ccmp_init() failed %d\n",
 			ret);
-		return ret;
+		goto fail_crypto_ccmp;
 	}
 
 	ret = ieee80211_crypto_wep_init();
 	if (ret) {
 		printk(KERN_ERR "ieee80211_crypto_wep_init() failed %d\n", ret);
-		return ret;
+		goto fail_crypto_wep;
 	}
 
 	printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
 	printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
 	RT_TRACE(COMP_INIT, "Initializing module");
 	RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
-	rtl8192_proc_module_init();
-	return usb_register(&rtl8192_usb_driver);
+
+	ret = rtl8192_proc_module_init();
+	if (ret) {
+		pr_err("rtl8192_proc_module_init() failed %d\n", ret);
+		goto fail_proc;
+	}
+
+	ret = usb_register(&rtl8192_usb_driver);
+	if (ret) {
+		pr_err("usb_register() failed %d\n", ret);
+		goto fail_usb;
+	}
+
+	return 0;
+
+fail_usb:
+	rtl8192_proc_module_remove();
+fail_proc:
+	ieee80211_crypto_wep_exit();
+fail_crypto_wep:
+	ieee80211_crypto_ccmp_exit();
+fail_crypto_ccmp:
+	ieee80211_crypto_tkip_exit();
+fail_crypto_tkip:
+	ieee80211_crypto_deinit();
+fail_crypto:
+#ifdef CONFIG_IEEE80211_DEBUG
+	ieee80211_debug_exit();
+#endif
+	return ret;
 }
 
 
--- linux-ec2-2.6.32.orig/drivers/staging/vt6656/ttype.h
+++ linux-ec2-2.6.32/drivers/staging/vt6656/ttype.h
@@ -30,6 +30,9 @@
 #ifndef __TTYPE_H__
 #define __TTYPE_H__
 
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#endif
 
 /******* Common definitions and typedefs ***********************************/
 
--- linux-ec2-2.6.32.orig/drivers/staging/rt2870/2870_main_dev.c
+++ linux-ec2-2.6.32/drivers/staging/rt2870/2870_main_dev.c
@@ -142,6 +142,7 @@
 	{ USB_DEVICE(0x7392, 0x7717) }, /* Edimax */
 	{ USB_DEVICE(0x1EDA, 0x2310) }, /* AirTies 3070 */
 	{ USB_DEVICE(0x1737, 0x0077) }, /* Linksys WUSB54GC-EU v3 */
+	{ USB_DEVICE(0x0411, 0x015D) }, /* Buffalo Airstation WLI-UC-GN */
 	{ } /* Terminating entry */
 };
 
--- linux-ec2-2.6.32.orig/drivers/staging/frontier/tranzport.c
+++ linux-ec2-2.6.32/drivers/staging/frontier/tranzport.c
@@ -202,7 +202,7 @@
     t->value = temp;							\
     return count;							\
   }									\
-  static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+  static DEVICE_ATTR(value, S_IWUSR | S_IRUGO, show_##value, set_##value);
 
 show_int(enable);
 show_int(offline);
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/r8185b_init.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/r8185b_init.c
@@ -356,8 +356,12 @@
 			}
 			udelay(10);
 		}
-		if (TryCnt == TC_3W_POLL_MAX_TRY_CNT)
-			panic("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", u1bTmp);
+		if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) {
+			printk(KERN_ERR "rtl8187se: HwThreeWire(): CmdReg:"
+			       " %#X RE|WE bits are not clear!!\n", u1bTmp);
+			dump_stack();
+			return 0;
+		}
 
 		// RTL8187S HSSI Read/Write Function
 		u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
@@ -397,13 +401,23 @@
 				int idx;
 				int ByteCnt = nDataBufBitCnt / 8;
                                 //printk("%d\n",nDataBufBitCnt);
-				if ((nDataBufBitCnt % 8) != 0)
-				panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
-				nDataBufBitCnt);
+				if ((nDataBufBitCnt % 8) != 0) {
+					printk(KERN_ERR "rtl8187se: "
+					       "HwThreeWire(): nDataBufBitCnt(%d)"
+					       " should be multiple of 8!!!\n",
+					       nDataBufBitCnt);
+					dump_stack();
+					nDataBufBitCnt += 8;
+					nDataBufBitCnt &= ~7;
+				}
 
-			       if (nDataBufBitCnt > 64)
-				panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
-				nDataBufBitCnt);
+			       if (nDataBufBitCnt > 64) {
+					printk(KERN_ERR "rtl8187se: HwThreeWire():"
+					       " nDataBufBitCnt(%d) should <= 64!!!\n",
+					       nDataBufBitCnt);
+					dump_stack();
+					nDataBufBitCnt = 64;
+				}
 
 				for(idx = 0; idx < ByteCnt; idx++)
 				{
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/r8180_core.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/r8180_core.c
@@ -1830,7 +1830,7 @@
 			if(priv->rx_skb->len > 4)
 				skb_trim(priv->rx_skb,priv->rx_skb->len-4);
 #ifndef RX_DONT_PASS_UL
-			if(!ieee80211_rx(priv->ieee80211,
+			if(!ieee80211_rtl_rx(priv->ieee80211,
 					 priv->rx_skb, &stats)){
 #endif // RX_DONT_PASS_UL
 
@@ -1936,11 +1936,11 @@
 	if (!check_nic_enought_desc(dev, priority)){
 		DMESGW("Error: no descriptor left by previous TX (avail %d) ",
 			get_curr_tx_free_desc(dev, priority));
-		ieee80211_stop_queue(priv->ieee80211);
+		ieee80211_rtl_stop_queue(priv->ieee80211);
 	}
 	rtl8180_tx(dev, skb->data, skb->len, priority, morefrag,0,rate);
 	if (!check_nic_enought_desc(dev, priority))
-		ieee80211_stop_queue(priv->ieee80211);
+		ieee80211_rtl_stop_queue(priv->ieee80211);
 
 	spin_unlock_irqrestore(&priv->tx_lock,flags);
 }
@@ -3846,7 +3846,7 @@
 	.ndo_set_mac_address	= r8180_set_mac_adr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_start_xmit		= ieee80211_xmit,
+	.ndo_start_xmit		= ieee80211_rtl_xmit,
 };
 
 static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
@@ -4066,7 +4066,7 @@
 	spin_unlock_irqrestore(&priv->tx_lock,flags);
 
 	if(enough_desc)
-		ieee80211_wake_queue(priv->ieee80211);
+		ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
 void rtl8180_tx_isr(struct net_device *dev, int pri,short error)
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/r8180_wx.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/r8180_wx.c
@@ -377,7 +377,7 @@
 	//	queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq);
 		//printk("start scan============================>\n");
 		ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
-//ieee80211_start_scan(priv->ieee80211);
+//ieee80211_rtl_start_scan(priv->ieee80211);
 		/* intentionally forget to up sem */
 //			up(&priv->ieee80211->wx_sem);
 			ret = 0;
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
@@ -470,7 +470,7 @@
 /* All received frames are sent to this function. @skb contains the frame in
  * IEEE 802.11 format, i.e., in the format it was sent over air.
  * This function is called only as a tasklet (software IRQ). */
-int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 		 struct ieee80211_rx_stats *rx_stats)
 {
 	struct net_device *dev = ieee->dev;
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -1318,13 +1318,13 @@
 	struct sk_buff *frag,
 	int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int ieee80211_rtl_xmit(struct sk_buff *skb,
 			  struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
 			     struct ieee80211_hdr_4addr *header,
@@ -1376,8 +1376,8 @@
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
@@ -1385,7 +1385,7 @@
 extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
 extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
 extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn);
-extern void ieee80211_start_scan(struct ieee80211_device *ieee);
+extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee);
 
 //Add for RF power on power off by lizhaoming 080512
 extern void SendDisassociation(struct ieee80211_device *ieee,
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -305,7 +305,7 @@
 }
 
 /* SKBs are added to the ieee->tx_queue. */
-int ieee80211_xmit(struct sk_buff *skb,
+int ieee80211_rtl_xmit(struct sk_buff *skb,
 		   struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
--- linux-ec2-2.6.32.orig/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ linux-ec2-2.6.32/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -689,7 +689,7 @@
 }
 
 /* called with ieee->lock held */
-void ieee80211_start_scan(struct ieee80211_device *ieee)
+void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
 	if(IS_DOT11D_ENABLE(ieee) )
 	{
@@ -1196,7 +1196,7 @@
 	}
 }
 
-void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
+void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
 {
 	u8 *c;
 	struct sk_buff *skb;
@@ -1898,7 +1898,7 @@
 
 								ieee80211_associate_step2(ieee);
 							}else{
-								ieee80211_auth_challenge(ieee, challenge, chlen);
+								ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
 							}
 						}else{
 							ieee->softmac_stats.rx_auth_rs_err++;
@@ -2047,7 +2047,7 @@
 
 }
 
-void ieee80211_wake_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 {
 
 	unsigned long flags;
@@ -2089,7 +2089,7 @@
 }
 
 
-void ieee80211_stop_queue(struct ieee80211_device *ieee)
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
 	//unsigned long flags;
 	//spin_lock_irqsave(&ieee->lock,flags);
@@ -2301,7 +2301,7 @@
 //#else
 	if (ieee->state == IEEE80211_NOLINK){
 		ieee->actscanning = true;
-		ieee80211_start_scan(ieee);
+		ieee80211_rtl_start_scan(ieee);
 	}
 //#endif
 	spin_unlock_irqrestore(&ieee->lock, flags);
@@ -2357,7 +2357,7 @@
 	if(ieee->state == IEEE80211_NOLINK){
 		ieee->beinretry = false;
 		ieee->actscanning = true;
-		ieee80211_start_scan(ieee);
+		ieee80211_rtl_start_scan(ieee);
 	}
 	//YJ,add,080828, notify os here
 	if(ieee->state == IEEE80211_NOLINK)
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/vhci.h
+++ linux-ec2-2.6.32/drivers/staging/usbip/vhci.h
@@ -100,9 +100,6 @@
 	 * But, the index of this array begins from 0.
 	 */
 	struct vhci_device vdev[VHCI_NPORTS];
-
-	/* vhci_device which has not been assiged its address yet */
-	int pending_port;
 };
 
 
@@ -119,6 +116,9 @@
 void vhci_rx_loop(struct usbip_task *ut);
 void vhci_tx_loop(struct usbip_task *ut);
 
+struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
+					    __u32 seqnum);
+
 #define hardware		(&the_controller->pdev.dev)
 
 static inline struct vhci_device *port_to_vdev(__u32 port)
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/vhci_rx.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/vhci_rx.c
@@ -21,16 +21,14 @@
 #include "vhci.h"
 
 
-/* get URB from transmitted urb queue */
-static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
+/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */
+struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
 					    __u32 seqnum)
 {
 	struct vhci_priv *priv, *tmp;
 	struct urb *urb = NULL;
 	int status;
 
-	spin_lock(&vdev->priv_lock);
-
 	list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
 		if (priv->seqnum == seqnum) {
 			urb = priv->urb;
@@ -61,8 +59,6 @@
 		}
 	}
 
-	spin_unlock(&vdev->priv_lock);
-
 	return urb;
 }
 
@@ -72,9 +68,11 @@
 	struct usbip_device *ud = &vdev->ud;
 	struct urb *urb;
 
+	spin_lock(&vdev->priv_lock);
 
 	urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
 
+	spin_unlock(&vdev->priv_lock);
 
 	if (!urb) {
 		usbip_uerr("cannot find a urb of seqnum %u\n",
@@ -99,6 +97,9 @@
 	if (usbip_recv_iso(ud, urb) < 0)
 		return;
 
+	/* restore the padding in iso packets */
+	if (usbip_pad_iso(ud, urb) < 0)
+		return;
 
 	if (usbip_dbg_flag_vhci_rx)
 		usbip_dump_urb(urb);
@@ -159,7 +160,12 @@
 		return;
 	}
 
+	spin_lock(&vdev->priv_lock);
+
 	urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+
+	spin_unlock(&vdev->priv_lock);
+
 	if (!urb) {
 		/*
 		 * I get the result of a unlink request. But, it seems that I
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/usbip_common.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/usbip_common.c
@@ -361,10 +361,11 @@
 		usbip_udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum);
 		break;
 	case USBIP_RET_SUBMIT:
-		usbip_udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n",
+		usbip_udbg("RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n",
 				pdu->u.ret_submit.status,
 				pdu->u.ret_submit.actual_length,
 				pdu->u.ret_submit.start_frame,
+				pdu->u.ret_submit.number_of_packets,
 				pdu->u.ret_submit.error_count);
 	case USBIP_RET_UNLINK:
 		usbip_udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status);
@@ -686,6 +687,7 @@
 		rpdu->status		= urb->status;
 		rpdu->actual_length	= urb->actual_length;
 		rpdu->start_frame	= urb->start_frame;
+		rpdu->number_of_packets = urb->number_of_packets;
 		rpdu->error_count	= urb->error_count;
 	} else {
 		/* vhci_rx.c */
@@ -693,6 +695,7 @@
 		urb->status		= rpdu->status;
 		urb->actual_length	= rpdu->actual_length;
 		urb->start_frame	= rpdu->start_frame;
+		urb->number_of_packets = rpdu->number_of_packets;
 		urb->error_count	= rpdu->error_count;
 	}
 }
@@ -761,11 +764,13 @@
 		cpu_to_be32s(&pdu->status);
 		cpu_to_be32s(&pdu->actual_length);
 		cpu_to_be32s(&pdu->start_frame);
+		cpu_to_be32s(&pdu->number_of_packets);
 		cpu_to_be32s(&pdu->error_count);
 	} else {
 		be32_to_cpus(&pdu->status);
 		be32_to_cpus(&pdu->actual_length);
 		be32_to_cpus(&pdu->start_frame);
+		cpu_to_be32s(&pdu->number_of_packets);
 		be32_to_cpus(&pdu->error_count);
 	}
 }
@@ -891,6 +896,7 @@
 	int size = np * sizeof(*iso);
 	int i;
 	int ret;
+	int total_length = 0;
 
 	if (!usb_pipeisoc(urb->pipe))
 		return 0;
@@ -920,19 +926,75 @@
 		return -EPIPE;
 	}
 
+
 	for (i = 0; i < np; i++) {
 		iso = buff + (i * sizeof(*iso));
 
 		usbip_iso_pakcet_correct_endian(iso, 0);
 		usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
+		total_length += urb->iso_frame_desc[i].actual_length;
 	}
 
 	kfree(buff);
 
+	if (total_length != urb->actual_length) {
+		dev_err(&urb->dev->dev,
+		  "total length of iso packets (%d) not equal to actual length of buffer (%d)\n",
+		  total_length, urb->actual_length);
+
+		if (ud->side == USBIP_STUB)
+			usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+		else
+			usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+
+		return -EPIPE;
+	}
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(usbip_recv_iso);
 
+/*
+ * This functions restores the padding which was removed for optimizing
+ * the bandwidth during transfer over tcp/ip
+ *
+ * buffer and iso packets need to be stored and be in propeper endian in urb
+ * before calling this function
+ */
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
+{
+	int np = urb->number_of_packets;
+	int i;
+	int ret;
+	int actualoffset = urb->actual_length;
+
+	if (!usb_pipeisoc(urb->pipe))
+		return 0;
+
+	/* if no packets or length of data is 0, then nothing to unpack */
+	if (np == 0 || urb->actual_length == 0)
+		return 0;
+
+	/*
+	 * if actual_length is transfer_buffer_length then no padding is
+	 * present.
+	*/
+	if (urb->actual_length == urb->transfer_buffer_length)
+		return 0;
+
+	/*
+	 * loop over all packets from last to first (to prevent overwritting
+	 * memory when padding) and move them into the proper place
+	 */
+	for (i = np-1; i > 0; i--) {
+		actualoffset -= urb->iso_frame_desc[i].actual_length;
+		memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+				  urb->transfer_buffer + actualoffset,
+				  urb->iso_frame_desc[i].actual_length);
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_pad_iso);
 
 /* some members of urb must be substituted before. */
 int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/vhci_hcd.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/vhci_hcd.c
@@ -137,8 +137,6 @@
 	 * the_controller->vdev[rhport].ud.status = VDEV_CONNECT;
 	 * spin_unlock(&the_controller->vdev[rhport].ud.lock); */
 
-	the_controller->pending_port = rhport;
-
 	spin_unlock_irqrestore(&the_controller->lock, flags);
 
 	usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
@@ -163,6 +161,8 @@
 	 * spin_unlock(&vdev->ud.lock); */
 
 	spin_unlock_irqrestore(&the_controller->lock, flags);
+
+	usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
 }
 
 
@@ -556,6 +556,7 @@
 	struct device *dev = &urb->dev->dev;
 	int ret = 0;
 	unsigned long flags;
+	struct vhci_device *vdev;
 
 	usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
 		    hcd, urb, mem_flags);
@@ -571,6 +572,18 @@
 		return urb->status;
 	}
 
+	vdev = port_to_vdev(urb->dev->portnum-1);
+
+	/* refuse enqueue for dead connection */
+	spin_lock(&vdev->ud.lock);
+	if (vdev->ud.status == VDEV_ST_NULL || vdev->ud.status == VDEV_ST_ERROR) {
+		usbip_uerr("enqueue for inactive port %d\n", vdev->rhport);
+		spin_unlock(&vdev->ud.lock);
+		spin_unlock_irqrestore(&the_controller->lock, flags);
+		return -ENODEV;
+	}
+	spin_unlock(&vdev->ud.lock);
+
 	ret = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (ret)
 		goto no_need_unlink;
@@ -589,8 +602,6 @@
 		__u8 type = usb_pipetype(urb->pipe);
 		struct usb_ctrlrequest *ctrlreq =
 				(struct usb_ctrlrequest *) urb->setup_packet;
-		struct vhci_device *vdev =
-				port_to_vdev(the_controller->pending_port);
 
 		if (type != PIPE_CONTROL || !ctrlreq) {
 			dev_err(dev, "invalid request to devnum 0\n");
@@ -604,7 +615,9 @@
 			dev_info(dev, "SetAddress Request (%d) to port %d\n",
 				 ctrlreq->wValue, vdev->rhport);
 
-			vdev->udev = urb->dev;
+			if (vdev->udev)
+				usb_put_dev(vdev->udev);
+			vdev->udev = usb_get_dev(urb->dev);
 
 			spin_lock(&vdev->ud.lock);
 			vdev->ud.status = VDEV_ST_USED;
@@ -624,8 +637,9 @@
 						"Get_Descriptor to device 0 "
 						"(get max pipe size)\n");
 
-			/* FIXME: reference count? (usb_get_dev()) */
-			vdev->udev = urb->dev;
+			if (vdev->udev)
+				usb_put_dev(vdev->udev);
+			vdev->udev = usb_get_dev(urb->dev);
 			goto out;
 
 		default:
@@ -796,27 +810,12 @@
 		spin_unlock_irqrestore(&vdev->priv_lock, flags2);
 	}
 
-
-	if (!vdev->ud.tcp_socket) {
-		/* tcp connection is closed */
-		usbip_uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n",
-									urb);
-
-		usb_hcd_unlink_urb_from_ep(hcd, urb);
-
-		spin_unlock_irqrestore(&the_controller->lock, flags);
-		usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
-								urb->status);
-		spin_lock_irqsave(&the_controller->lock, flags);
-	}
-
 	spin_unlock_irqrestore(&the_controller->lock, flags);
 
 	usbip_dbg_vhci_hc("leave\n");
 	return 0;
 }
 
-
 static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
 {
 	struct vhci_unlink *unlink, *tmp;
@@ -824,11 +823,34 @@
 	spin_lock(&vdev->priv_lock);
 
 	list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+		usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum);
 		list_del(&unlink->list);
 		kfree(unlink);
 	}
 
 	list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
+		struct urb *urb;
+
+		/* give back URB of unanswered unlink request */
+		usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum);
+
+		urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+		if (!urb) {
+			usbip_uinfo("the urb (seqnum %lu) was already given back\n",
+							unlink->unlink_seqnum);
+			list_del(&unlink->list);
+			kfree(unlink);
+			continue;
+		}
+
+		urb->status = -ENODEV;
+
+		spin_lock(&the_controller->lock);
+		usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+		spin_unlock(&the_controller->lock);
+
+		usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+
 		list_del(&unlink->list);
 		kfree(unlink);
 	}
@@ -898,6 +920,10 @@
 	vdev->speed  = 0;
 	vdev->devid  = 0;
 
+	if (vdev->udev)
+		usb_put_dev(vdev->udev);
+	vdev->udev = NULL;
+
 	ud->tcp_socket = NULL;
 
 	ud->status = VDEV_ST_NULL;
@@ -1108,7 +1134,7 @@
 		usbip_uerr("create hcd failed\n");
 		return -ENOMEM;
 	}
-
+	hcd->has_tt = 1;
 
 	/* this is private data for vhci_hcd */
 	the_controller = hcd_to_vhci(hcd);
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/stub_rx.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/stub_rx.c
@@ -168,33 +168,23 @@
 
 static int tweak_reset_device_cmd(struct urb *urb)
 {
-	struct usb_ctrlrequest *req;
-	__u16 value;
-	__u16 index;
-	int ret;
-
-	req = (struct usb_ctrlrequest *) urb->setup_packet;
-	value = le16_to_cpu(req->wValue);
-	index = le16_to_cpu(req->wIndex);
-
-	usbip_uinfo("reset_device (port %d) to %s\n", index,
-						dev_name(&urb->dev->dev));
-
-	/* all interfaces should be owned by usbip driver, so just reset it.  */
-	ret = usb_lock_device_for_reset(urb->dev, NULL);
-	if (ret < 0) {
-		dev_err(&urb->dev->dev, "lock for reset\n");
-		return ret;
-	}
+	struct stub_priv *priv = (struct stub_priv *) urb->context;
+	struct stub_device *sdev = priv->sdev;
 
-	/* try to reset the device */
-	ret = usb_reset_device(urb->dev);
-	if (ret < 0)
-		dev_err(&urb->dev->dev, "device reset\n");
+	usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev));
 
-	usb_unlock_device(urb->dev);
-
-	return ret;
+	/*
+	 * usb_lock_device_for_reset caused a deadlock: it causes the driver
+	 * to unbind. In the shutdown the rx thread is signalled to shut down
+	 * but this thread is pending in the usb_lock_device_for_reset.
+	 *
+	 * Instead queue the reset.
+	 *
+	 * Unfortunatly an existing usbip connection will be dropped due to
+	 * driver unbinding.
+	 */
+	usb_queue_reset_device(sdev->interface);
+	return 0;
 }
 
 /*
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/usbip_common.h
+++ linux-ec2-2.6.32/drivers/staging/usbip/usbip_common.h
@@ -393,6 +393,8 @@
 int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
 /* some members of urb must be substituted before. */
 int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
+/* some members of urb must be substituted before. */
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
 void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
 
 
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/usbip_event.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/usbip_event.c
@@ -38,21 +38,13 @@
 			ud->eh_ops.shutdown(ud);
 
 			ud->event &= ~USBIP_EH_SHUTDOWN;
-
-			break;
 		}
 
-		/* Stop the error handler. */
-		if (ud->event & USBIP_EH_BYE)
-			return -1;
-
 		/* Reset the device. */
 		if (ud->event & USBIP_EH_RESET) {
 			ud->eh_ops.reset(ud);
 
 			ud->event &= ~USBIP_EH_RESET;
-
-			break;
 		}
 
 		/* Mark the device as unusable. */
@@ -60,13 +52,11 @@
 			ud->eh_ops.unusable(ud);
 
 			ud->event &= ~USBIP_EH_UNUSABLE;
-
-			break;
 		}
 
-		/* NOTREACHED */
-		printk(KERN_ERR "%s: unknown event\n", __func__);
-		return -1;
+		/* Stop the error handler. */
+		if (ud->event & USBIP_EH_BYE)
+			return -1;
 	}
 
 	return 0;
@@ -117,6 +107,9 @@
 {
 	struct usbip_task *eh = &ud->eh;
 
+	if (eh->thread == current)
+		return; /* do not wait for myself */
+
 	wait_for_completion(&eh->thread_done);
 	usbip_dbg_eh("usbip_eh has finished\n");
 }
--- linux-ec2-2.6.32.orig/drivers/staging/usbip/stub_tx.c
+++ linux-ec2-2.6.32/drivers/staging/usbip/stub_tx.c
@@ -167,7 +167,6 @@
 	struct stub_priv *priv, *tmp;
 
 	struct msghdr msg;
-	struct kvec iov[3];
 	size_t txsize;
 
 	size_t total_size = 0;
@@ -177,28 +176,73 @@
 		struct urb *urb = priv->urb;
 		struct usbip_header pdu_header;
 		void *iso_buffer = NULL;
+		struct kvec *iov = NULL;
+		int iovnum = 0;
 
 		txsize = 0;
 		memset(&pdu_header, 0, sizeof(pdu_header));
 		memset(&msg, 0, sizeof(msg));
-		memset(&iov, 0, sizeof(iov));
 
-		usbip_dbg_stub_tx("setup txdata urb %p\n", urb);
+		if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+			iovnum = 2 + urb->number_of_packets;
+		else
+			iovnum = 2;
+
+		iov = kzalloc(iovnum * sizeof(struct kvec), GFP_KERNEL);
 
+		if (!iov) {
+			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
+			return -1;
+		}
+
+		iovnum = 0;
 
 		/* 1. setup usbip_header */
 		setup_ret_submit_pdu(&pdu_header, urb);
+		usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
+						pdu_header.base.seqnum, urb);
+		/*usbip_dump_header(pdu_header);*/
 		usbip_header_correct_endian(&pdu_header, 1);
 
-		iov[0].iov_base = &pdu_header;
-		iov[0].iov_len  = sizeof(pdu_header);
+		iov[iovnum].iov_base = &pdu_header;
+		iov[iovnum].iov_len  = sizeof(pdu_header);
+		iovnum++;
 		txsize += sizeof(pdu_header);
 
 		/* 2. setup transfer buffer */
-		if (usb_pipein(urb->pipe) && urb->actual_length > 0) {
-			iov[1].iov_base = urb->transfer_buffer;
-			iov[1].iov_len  = urb->actual_length;
+		if (usb_pipein(urb->pipe) &&
+				usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
+					urb->actual_length > 0) {
+			iov[iovnum].iov_base = urb->transfer_buffer;
+			iov[iovnum].iov_len  = urb->actual_length;
+			iovnum++;
 			txsize += urb->actual_length;
+		} else if (usb_pipein(urb->pipe) &&
+				usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+			/*
+			 * For isochronous packets: actual length is the sum of
+			 * the actual length of the individual, packets, but as
+			 * the packet offsets are not changed there will be
+			 * padding between the packets. To optimally use the
+			 * bandwidth the padding is not transmitted.
+			 */
+
+			int i;
+			for (i = 0; i < urb->number_of_packets; i++) {
+				iov[iovnum].iov_base = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+				iov[iovnum].iov_len = urb->iso_frame_desc[i].actual_length;
+				iovnum++;
+				txsize += urb->iso_frame_desc[i].actual_length;
+			}
+
+			if (txsize != sizeof(pdu_header) + urb->actual_length) {
+				dev_err(&sdev->interface->dev,
+					"actual length of urb (%d) does not match iso packet sizes (%d)\n",
+					urb->actual_length, txsize-sizeof(pdu_header));
+				kfree(iov);
+				usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+			   return -1;
+			}
 		}
 
 		/* 3. setup iso_packet_descriptor */
@@ -209,32 +253,34 @@
 			if (!iso_buffer) {
 				usbip_event_add(&sdev->ud,
 						SDEV_EVENT_ERROR_MALLOC);
+				kfree(iov);
 				return -1;
 			}
 
-			iov[2].iov_base = iso_buffer;
-			iov[2].iov_len  = len;
+			iov[iovnum].iov_base = iso_buffer;
+			iov[iovnum].iov_len  = len;
 			txsize += len;
+			iovnum++;
 		}
 
-		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
-				     3, txsize);
+		ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
+						iov,  iovnum, txsize);
 		if (ret != txsize) {
 			dev_err(&sdev->interface->dev,
 				"sendmsg failed!, retval %d for %zd\n",
 				ret, txsize);
+			kfree(iov);
 			kfree(iso_buffer);
 			usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
 			return -1;
 		}
 
+		kfree(iov);
 		kfree(iso_buffer);
-		usbip_dbg_stub_tx("send txdata\n");
 
 		total_size += txsize;
 	}
 
-
 	spin_lock_irqsave(&sdev->priv_lock, flags);
 
 	list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
--- linux-ec2-2.6.32.orig/drivers/input/xen-kbdfront.c
+++ linux-ec2-2.6.32/drivers/input/xen-kbdfront.c
@@ -105,7 +105,7 @@
 static int __devinit xenkbd_probe(struct xenbus_device *dev,
 				  const struct xenbus_device_id *id)
 {
-	int ret, i;
+	int ret, i, abs;
 	struct xenkbd_info *info;
 	struct input_dev *kbd, *ptr;
 
@@ -123,6 +123,11 @@
 	if (!info->page)
 		goto error_nomem;
 
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
+		abs = 0;
+	if (abs)
+		xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+
 	/* keyboard */
 	kbd = input_allocate_device();
 	if (!kbd)
@@ -132,11 +137,12 @@
 	kbd->id.bustype = BUS_PCI;
 	kbd->id.vendor = 0x5853;
 	kbd->id.product = 0xffff;
-	kbd->evbit[0] = BIT(EV_KEY);
+
+	__set_bit(EV_KEY, kbd->evbit);
 	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
-		set_bit(i, kbd->keybit);
+		__set_bit(i, kbd->keybit);
 	for (i = KEY_OK; i < KEY_MAX; i++)
-		set_bit(i, kbd->keybit);
+		__set_bit(i, kbd->keybit);
 
 	ret = input_register_device(kbd);
 	if (ret) {
@@ -155,12 +161,20 @@
 	ptr->id.bustype = BUS_PCI;
 	ptr->id.vendor = 0x5853;
 	ptr->id.product = 0xfffe;
-	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+
+	if (abs) {
+		__set_bit(EV_ABS, ptr->evbit);
+		input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+		input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+	} else {
+		input_set_capability(ptr, EV_REL, REL_X);
+		input_set_capability(ptr, EV_REL, REL_Y);
+	}
+	input_set_capability(ptr, EV_REL, REL_WHEEL);
+
+	__set_bit(EV_KEY, ptr->evbit);
 	for (i = BTN_LEFT; i <= BTN_TASK; i++)
-		set_bit(i, ptr->keybit);
-	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
-	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+		__set_bit(i, ptr->keybit);
 
 	ret = input_register_device(ptr);
 	if (ret) {
@@ -286,8 +300,7 @@
 			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
 					    "request-abs-pointer", "1");
 			if (ret)
-				printk(KERN_WARNING
-				       "xenkbd: can't request abs-pointer");
+				pr_warning("can't request abs-pointer\n");
 		}
 		xenbus_switch_state(dev, XenbusStateConnected);
 		break;
@@ -325,7 +338,6 @@
 
 static struct xenbus_driver xenkbd_driver = {
 	.name = "vkbd",
-	.owner = THIS_MODULE,
 	.ids = xenkbd_ids,
 	.probe = xenkbd_probe,
 	.remove = xenkbd_remove,
--- linux-ec2-2.6.32.orig/drivers/input/input.c
+++ linux-ec2-2.6.32/drivers/input/input.c
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include <linux/smp_lock.h>
+#include "input-compat.h"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -45,6 +46,7 @@
 	ABS_MT_TOOL_TYPE,
 	ABS_MT_BLOB_ID,
 	ABS_MT_TRACKING_ID,
+	ABS_MT_PRESSURE,
 	0
 };
 static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
@@ -90,19 +92,26 @@
  */
 static void input_pass_event(struct input_dev *dev,
 			     unsigned int type, unsigned int code, int value)
-{
-	struct input_handle *handle;
+
+{	struct input_handle *handle;
 
 	rcu_read_lock();
 
 	handle = rcu_dereference(dev->grab);
-	if (handle)
+	if (handle) {
 		handle->handler->event(handle, type, code, value);
-	else
-		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
-			if (handle->open)
-				handle->handler->event(handle,
-							type, code, value);
+		goto out;
+	}
+
+	handle = rcu_dereference(dev->filter);
+	if (handle && handle->handler->filter(handle, type, code, value))
+		goto out;
+
+	list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+		if (handle->open)
+			handle->handler->event(handle,
+					       type, code, value);
+out:
 	rcu_read_unlock();
 }
 
@@ -377,12 +386,15 @@
 }
 EXPORT_SYMBOL(input_grab_device);
 
-static void __input_release_device(struct input_handle *handle)
+static void __input_release_device(struct input_handle *handle, bool filter)
 {
 	struct input_dev *dev = handle->dev;
 
-	if (dev->grab == handle) {
-		rcu_assign_pointer(dev->grab, NULL);
+	if (handle == (filter ? dev->filter : dev->grab)) {
+		if (filter)
+			rcu_assign_pointer(dev->filter, NULL);
+		else
+			rcu_assign_pointer(dev->grab, NULL);
 		/* Make sure input_pass_event() notices that grab is gone */
 		synchronize_rcu();
 
@@ -406,12 +418,65 @@
 	struct input_dev *dev = handle->dev;
 
 	mutex_lock(&dev->mutex);
-	__input_release_device(handle);
+	__input_release_device(handle, false);
 	mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL(input_release_device);
 
 /**
+ * input_filter_device - allow input events to be filtered from higher layers
+ * @handle: input handle that wants to filter the device
+ *
+ * When a device is filtered by an input handle all events generated by
+ * the device are to this handle. If the filter function returns true then
+ * the event is discarded rather than being passed to any other input handles,
+ * otherwise it is passed to them as normal. Grabs will be handled before
+ * filters, so a grabbed device will not deliver events to a filter function.
+ */
+int input_filter_device(struct input_handle *handle)
+{
+	struct input_dev *dev = handle->dev;
+	int retval;
+
+	retval = mutex_lock_interruptible(&dev->mutex);
+	if (retval)
+		return retval;
+
+	if (dev->filter) {
+		retval = -EBUSY;
+		goto out;
+	}
+
+	rcu_assign_pointer(dev->filter, handle);
+	synchronize_rcu();
+
+ out:
+	mutex_unlock(&dev->mutex);
+	return retval;
+}
+EXPORT_SYMBOL(input_filter_device);
+
+/**
+ * input_unfilter_device - removes a filter from a device
+ * @handle: input handle that owns the device
+ *
+ * Removes the filter from a device so that other input handles can
+ * start receiving unfiltered input events. Upon release all handlers
+ * attached to the device have their start() method called so they
+ * have a change to synchronize device state with the rest of the
+ * system.
+ */
+void input_unfilter_device(struct input_handle *handle)
+{
+	struct input_dev *dev = handle->dev;
+
+	mutex_lock(&dev->mutex);
+	__input_release_device(handle, true);
+	mutex_unlock(&dev->mutex);
+}
+EXPORT_SYMBOL(input_unfilter_device);
+
+/**
  * input_open_device - open input device
  * @handle: handle through which device is being accessed
  *
@@ -484,7 +549,9 @@
 
 	mutex_lock(&dev->mutex);
 
-	__input_release_device(handle);
+	/* Release both grabs and filters */
+	__input_release_device(handle, false);
+	__input_release_device(handle, true);
 
 	if (!--dev->users && dev->close)
 		dev->close(dev);
@@ -758,6 +825,40 @@
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+
+static int input_bits_to_string(char *buf, int buf_size,
+				unsigned long bits, bool skip_empty)
+{
+	int len = 0;
+
+	if (INPUT_COMPAT_TEST) {
+		u32 dword = bits >> 32;
+		if (dword || !skip_empty)
+			len += snprintf(buf, buf_size, "%x ", dword);
+
+		dword = bits & 0xffffffffUL;
+		if (dword || !skip_empty || len)
+			len += snprintf(buf + len, max(buf_size - len, 0),
+					"%x", dword);
+	} else {
+		if (bits || !skip_empty)
+			len += snprintf(buf, buf_size, "%lx", bits);
+	}
+
+	return len;
+}
+
+#else /* !CONFIG_COMPAT */
+
+static int input_bits_to_string(char *buf, int buf_size,
+				unsigned long bits, bool skip_empty)
+{
+	return bits || !skip_empty ?
+		snprintf(buf, buf_size, "%lx", bits) : 0;
+}
+
+#endif
 
 #ifdef CONFIG_PROC_FS
 
@@ -826,14 +927,25 @@
 				   unsigned long *bitmap, int max)
 {
 	int i;
-
-	for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-		if (bitmap[i])
-			break;
+	bool skip_empty = true;
+	char buf[18];
 
 	seq_printf(seq, "B: %s=", name);
-	for (; i >= 0; i--)
-		seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : "");
+
+	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+		if (input_bits_to_string(buf, sizeof(buf),
+					 bitmap[i], skip_empty)) {
+			skip_empty = false;
+			seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
+		}
+	}
+
+	/*
+	 * If no output was produced print a single 0.
+	 */
+	if (skip_empty)
+		seq_puts(seq, "0");
+
 	seq_putc(seq, '\n');
 }
 
@@ -1122,14 +1234,23 @@
 {
 	int i;
 	int len = 0;
+	bool skip_empty = true;
 
-	for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
-		if (bitmap[i])
-			break;
+	for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
+		len += input_bits_to_string(buf + len, max(buf_size - len, 0),
+					    bitmap[i], skip_empty);
+		if (len) {
+			skip_empty = false;
+			if (i > 0)
+				len += snprintf(buf + len, max(buf_size - len, 0), " ");
+		}
+	}
 
-	for (; i >= 0; i--)
-		len += snprintf(buf + len, max(buf_size - len, 0),
-				"%lx%s", bitmap[i], i > 0 ? " " : "");
+	/*
+	 * If no output was produced print a single 0.
+	 */
+	if (len == 0)
+		len = snprintf(buf, buf_size, "%d", 0);
 
 	if (add_cr)
 		len += snprintf(buf + len, max(buf_size - len, 0), "\n");
@@ -1144,7 +1265,8 @@
 {									\
 	struct input_dev *input_dev = to_input_dev(dev);		\
 	int len = input_print_bitmap(buf, PAGE_SIZE,			\
-				     input_dev->bm##bit, ev##_MAX, 1);	\
+				     input_dev->bm##bit, ev##_MAX,	\
+				     true);				\
 	return min_t(int, len, PAGE_SIZE);				\
 }									\
 static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
@@ -1208,7 +1330,7 @@
 
 	len = input_print_bitmap(&env->buf[env->buflen - 1],
 				 sizeof(env->buf) - env->buflen,
-				 bitmap, max, 0);
+				 bitmap, max, false);
 	if (len >= (sizeof(env->buf) - env->buflen))
 		return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/drivers/input/joydev.c
+++ linux-ec2-2.6.32/drivers/input/joydev.c
@@ -481,6 +481,9 @@
 
 	memcpy(joydev->abspam, abspam, len);
 
+	for (i = 0; i < joydev->nabs; i++)
+		joydev->absmap[joydev->abspam[i]] = i;
+
  out:
 	kfree(abspam);
 	return retval;
--- linux-ec2-2.6.32.orig/drivers/input/tablet/wacom_wac.h
+++ linux-ec2-2.6.32/drivers/input/tablet/wacom_wac.h
@@ -9,6 +9,19 @@
 #ifndef WACOM_WAC_H
 #define WACOM_WAC_H
 
+/* maximum packet length for USB devices */
+#define WACOM_PKGLEN_MAX	32
+
+/* packet length for individual models */
+#define WACOM_PKGLEN_PENPRTN	 7
+#define WACOM_PKGLEN_GRAPHIRE	 8
+#define WACOM_PKGLEN_BBFUN 	 9
+#define WACOM_PKGLEN_INTUOS 	10
+#define WACOM_PKGLEN_PENABLED	 8
+#define WACOM_PKGLEN_TPC1FG	 5
+#define WACOM_PKGLEN_TPC2FG 	14
+
+/* device IDs */
 #define STYLUS_DEVICE_ID	0x02
 #define TOUCH_DEVICE_ID		0x03
 #define CURSOR_DEVICE_ID	0x06
@@ -32,6 +45,7 @@
 	WACOM_BEE,
 	WACOM_MO,
 	TABLETPC,
+	TABLETPC2FG,
 	MAX_TYPE
 };
 
@@ -43,8 +57,11 @@
 	int pressure_max;
 	int distance_max;
 	int type;
-	int touch_x_max;
-	int touch_y_max;
+	int device_type;
+	int x_phy;
+	int y_phy;
+	unsigned char unit;
+	unsigned char unitExpo;
 };
 
 struct wacom_wac {
--- linux-ec2-2.6.32.orig/drivers/input/tablet/wacom_wac.c
+++ linux-ec2-2.6.32/drivers/input/tablet/wacom_wac.c
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom_wac.c
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
+ *  USB Wacom tablet support - Wacom specific code
  *
  */
 
@@ -65,9 +65,8 @@
 
 	prox = data[1] & 0x40;
 
-	wacom->id[0] = ERASER_DEVICE_ID;
 	if (prox) {
-
+		wacom->id[0] = ERASER_DEVICE_ID;
 		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
 		if (wacom->features->pressure_max > 255)
 			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
@@ -608,54 +607,146 @@
 	return 1;
 }
 
+
+static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
+{
+	wacom_report_abs(wcombo, ABS_X,
+		(data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8));
+	wacom_report_abs(wcombo, ABS_Y,
+		(data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8));
+	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+	wacom_report_key(wcombo, wacom->tool[idx], 1);
+	if (idx)
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+	else
+		wacom_report_key(wcombo, BTN_TOUCH, 1);
+}
+
+static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
+{
+	wacom_report_abs(wcombo, ABS_X, 0);
+	wacom_report_abs(wcombo, ABS_Y, 0);
+	wacom_report_abs(wcombo, ABS_MISC, 0);
+	wacom_report_key(wcombo, wacom->tool[idx], 0);
+	if (idx)
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+	else
+		wacom_report_key(wcombo, BTN_TOUCH, 0);
+	return;
+}
+
+static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
+{
+	char *data = wacom->data;
+	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
+	static int firstFinger = 0;
+	static int secondFinger = 0;
+
+	wacom->tool[0] = BTN_TOOL_DOUBLETAP;
+	wacom->id[0] = TOUCH_DEVICE_ID;
+	wacom->tool[1] = BTN_TOOL_TRIPLETAP;
+
+	if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
+		switch (data[0]) {
+			case 6:
+				wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+				wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+				wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+				wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
+				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+				wacom_report_key(wcombo, wacom->tool[0], 1);
+				break;
+			case 13:
+				/* keep this byte to send proper out-prox event */
+				wacom->id[1] = data[1] & 0x03;
+
+				if (data[1] & 0x01) {
+					wacom_tpc_finger_in(wacom, wcombo, data, 0);
+					firstFinger = 1;
+				} else if (firstFinger) {
+					wacom_tpc_touch_out(wacom, wcombo, 0);
+				}
+
+				if (data[1] & 0x02) {
+					/* sync first finger data */
+					if (firstFinger)
+						wacom_input_sync(wcombo);
+
+					wacom_tpc_finger_in(wacom, wcombo, data, 1);
+					secondFinger = 1;
+				} else if (secondFinger) {
+					/* sync first finger data */
+					if (firstFinger)
+						wacom_input_sync(wcombo);
+
+					wacom_tpc_touch_out(wacom, wcombo, 1);
+					secondFinger = 0;
+				}
+				if (!(data[1] & 0x01))
+					firstFinger = 0;
+				break;
+		}
+	} else {
+		wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+		wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+		wacom_report_key(wcombo, BTN_TOUCH, 1);
+		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+		wacom_report_key(wcombo, wacom->tool[0], 1);
+	}
+	return;
+}
+
 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
 {
 	char *data = wacom->data;
-	int prox = 0, pressure;
+	int prox = 0, pressure, idx = -1;
 	static int stylusInProx, touchInProx = 1, touchOut;
 	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
 
 	dbg("wacom_tpc_irq: received report #%d", data[0]);
 
-	if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
-		if (urb->actual_length == 5) {  /* with touch */
-			prox = data[0] & 0x03;
+	if (urb->actual_length == WACOM_PKGLEN_TPC1FG ||
+	    data[0] == 6 || /* single touch */
+	    data[0] == 13) { /* 2FG touch */
+		if (urb->actual_length == WACOM_PKGLEN_TPC1FG) {  /* with touch */
+			prox = data[0] & 0x01;
 		} else {  /* with capacity */
-			prox = data[1] & 0x03;
+			if (data[0] == 6)
+				/* single touch */
+				prox = data[1] & 0x01;
+			else
+				/* 2FG touch data */
+				prox = data[1] & 0x03;
 		}
 
 		if (!stylusInProx) { /* stylus not in prox */
 			if (prox) {
 				if (touchInProx) {
-					wacom->tool[1] = BTN_TOOL_DOUBLETAP;
-					wacom->id[0] = TOUCH_DEVICE_ID;
-					if (urb->actual_length != 5) {
-						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
-						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
-						wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
-						wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
-					} else {
-						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
-						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
-						wacom_report_key(wcombo, BTN_TOUCH, 1);
-					}
-					wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-					wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+					wacom_tpc_touch_in(wacom, wcombo);
 					touchOut = 1;
 					return 1;
 				}
 			} else {
-				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-				wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
-				wacom_report_key(wcombo, BTN_TOUCH, 0);
+				/* 2FGT out-prox */
+				if ((data[0] & 0xff) == 13) {
+					idx = (wacom->id[1] & 0x01) - 1;
+					if (idx == 0) {
+						wacom_tpc_touch_out(wacom, wcombo, idx);
+						/* sync first finger event */
+						if (wacom->id[1] & 0x02)
+							wacom_input_sync(wcombo);
+					}
+					idx = (wacom->id[1] & 0x02) - 1;
+					if (idx == 1)
+						wacom_tpc_touch_out(wacom, wcombo, idx);
+				} else /* one finger touch */
+					wacom_tpc_touch_out(wacom, wcombo, 0);
 				touchOut = 0;
 				touchInProx = 1;
 				return 1;
 			}
 		} else if (touchOut || !prox) { /* force touch out-prox */
-			wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
-			wacom_report_key(wcombo, wacom->tool[1], 0);
-			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_tpc_touch_out(wacom, wcombo, 0);
 			touchOut = 0;
 			touchInProx = 1;
 			return 1;
@@ -665,38 +756,14 @@
 
 		touchInProx = 0;
 
-		wacom->id[0] = ERASER_DEVICE_ID;
-
-		/*
-		 * if going from out of proximity into proximity select between the eraser
-		 * and the pen based on the state of the stylus2 button, choose eraser if
-		 * pressed else choose pen. if not a proximity change from out to in, send
-		 * an out of proximity for previous tool then a in for new tool.
-		 */
 		if (prox) { /* in prox */
-			if (!wacom->tool[0]) {
+			if (!wacom->id[0]) {
 				/* Going into proximity select tool */
-				wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-				if (wacom->tool[1] == BTN_TOOL_PEN)
+				wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+				if (wacom->tool[0] == BTN_TOOL_PEN)
 					wacom->id[0] = STYLUS_DEVICE_ID;
-			} else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
-				/*
-				 * was entered with stylus2 pressed
-				 * report out proximity for previous tool
-				*/
-				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-				wacom_report_key(wcombo, wacom->tool[1], 0);
-				wacom_input_sync(wcombo);
-
-				/* set new tool */
-				wacom->tool[1] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
-				return 0;
-			}
-			if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-				/* Unknown tool selected default to pen tool */
-				wacom->tool[1] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
+				else
+					wacom->id[0] = ERASER_DEVICE_ID;
 			}
 			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
@@ -706,17 +773,21 @@
 			if (pressure < 0)
 				pressure = wacom->features->pressure_max + pressure + 1;
 			wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
-			wacom_report_key(wcombo, BTN_TOUCH, pressure);
+			wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
 		} else {
+			wacom_report_abs(wcombo, ABS_X, 0);
+			wacom_report_abs(wcombo, ABS_Y, 0);
 			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 			wacom_report_key(wcombo, BTN_STYLUS, 0);
 			wacom_report_key(wcombo, BTN_STYLUS2, 0);
 			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom->id[0] = 0;
+			/* pen is out so touch can be enabled now */
+			touchInProx = 1;
 		}
-		wacom_report_key(wcombo, wacom->tool[1], prox);
+		wacom_report_key(wcombo, wacom->tool[0], prox);
 		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 		stylusInProx = prox;
-		wacom->tool[0] = prox;
 		return 1;
 	}
 	return 0;
@@ -751,6 +822,7 @@
 			return wacom_intuos_irq(wacom_wac, wcombo);
 
 		case TABLETPC:
+		case TABLETPC2FG:
 			return wacom_tpc_irq(wacom_wac, wcombo);
 
 		default:
@@ -791,9 +863,17 @@
 			input_dev_i4s(input_dev, wacom_wac);
 			input_dev_i(input_dev, wacom_wac);
 			break;
+		case TABLETPC2FG:
+			input_dev_tpc2fg(input_dev, wacom_wac);
+			/* fall through */
+		case TABLETPC:
+			input_dev_tpc(input_dev, wacom_wac);
+			if (wacom_wac->features->device_type != BTN_TOOL_PEN)
+				break;  /* no need to process stylus stuff */
+
+			/* fall through */
 		case PL:
 		case PTU:
-		case TABLETPC:
 			input_dev_pl(input_dev, wacom_wac);
 			/* fall through */
 		case PENPARTNER:
@@ -804,66 +884,69 @@
 }
 
 static struct wacom_features wacom_features[] = {
-	{ "Wacom Penpartner",    7,   5040,  3780,  255,  0, PENPARTNER },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire3",     8,  10208,  7424,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 },
-	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 },
-	{ "Wacom BambooFun 4x5", 9,  14760,  9225,  511, 63, WACOM_MO },
-	{ "Wacom BambooFun 6x8", 9,  21648, 13530,  511, 63, WACOM_MO },
-	{ "Wacom Bamboo1 Medium",8,  16704, 12064,  511, 63, GRAPHIRE },
-	{ "Wacom Volito",        8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom PenStation2",   8,   3250,  2320,  255, 63, GRAPHIRE },
-	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
-	{ "Wacom PenPartner2",   8,   3250,  2320,  511, 63, GRAPHIRE },
-	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
-	{ "Wacom Bamboo1",       8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
-	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
-	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
-	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
-	{ "Wacom PL600SX",       8,   6260,  5016,  255,  0, PL },
-	{ "Wacom PL550",         8,   6144,  4608,  511,  0, PL },
-	{ "Wacom PL800",         8,   7220,  5780,  511,  0, PL },
-	{ "Wacom PL700",         8,   6758,  5406,  511,  0, PL },
-	{ "Wacom PL510",         8,   6282,  4762,  511,  0, PL },
-	{ "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
-	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
-	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
-	{ "Wacom DTF720a",       8,   6858,  5506,  511,  0, PL },
-	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
-	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
-	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
-	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
-	{ "Wacom Intuos4 4x6",   10, 31496, 19685, 2047, 63, INTUOS4S },
-	{ "Wacom Intuos4 6x9",   10, 44704, 27940, 2047, 63, INTUOS4 },
-	{ "Wacom Intuos4 8x13",  10, 65024, 40640, 2047, 63, INTUOS4L },
-	{ "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L },
-	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
-	{ "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
-	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
-	{ "Wacom DTU1931",        8, 37832, 30305,  511,  0, PL },
-	{ "Wacom ISDv4 90",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom ISDv4 93",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom ISDv4 9A",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,  0, PENPARTNER },
+	{ "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, WACOM_G4 },
+	{ "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, WACOM_G4 },
+	{ "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
+	{ "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511, 63, WACOM_MO },
+	{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
+	{ "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255, 63, GRAPHIRE },
+	{ "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511, 63, GRAPHIRE },
+	{ "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511, 63, GRAPHIRE },
+	{ "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
+	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
+	{ "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,  0, PL },
+	{ "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,  0, PL },
+	{ "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,  0, PL },
+	{ "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,  0, PL },
+	{ "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,  0, PL },
+	{ "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,  0, PL },
+	{ "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,  0, PL },
+	{ "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,  0, PL },
+	{ "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
+	{ "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
+	{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,  0, PTU },
+	{ "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047, 63, INTUOS4S },
+	{ "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047, 63, INTUOS4 },
+	{ "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047, 63, INTUOS4L },
+	{ "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047, 63, INTUOS4L },
+	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023, 63, CINTIQ },
+	{ "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023, 63, WACOM_BEE },
+	{ "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023, 63, WACOM_BEE },
+	{ "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,  0, PL },
+	{ "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 9F",       WACOM_PKGLEN_PENABLED,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
+	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
 	{ }
 };
 
@@ -927,6 +1010,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 	{ }
 };
--- linux-ec2-2.6.32.orig/drivers/input/tablet/wacom.h
+++ linux-ec2-2.6.32/drivers/input/tablet/wacom.h
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom.h
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support
+ *  USB Wacom tablet support
  *
  *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
@@ -69,6 +69,9 @@
  *      v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
  *      v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
  *      v1.51 (pc) - Added support for Intuos4
+ *      v1.52 (pc) - Query Wacom data upon system resume
+ *                 - add defines for features->type
+ *                 - add new devices (0x9F, 0xE2, and 0XE3)
  */
 
 /*
@@ -89,9 +92,9 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.51"
+#define DRIVER_VERSION "v1.52"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_DESC "USB Wacom tablet driver"
 #define DRIVER_LICENSE "GPL"
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -133,6 +136,8 @@
 extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern __u16 wacom_le16_to_cpu(unsigned char *data);
--- linux-ec2-2.6.32.orig/drivers/input/tablet/wacom_sys.c
+++ linux-ec2-2.6.32/drivers/input/tablet/wacom_sys.c
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom_sys.c
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
+ *  USB Wacom tablet support - system specific code
  */
 
 /*
@@ -209,6 +209,7 @@
 	input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+		BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
 		BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
 	input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
 }
@@ -256,6 +257,7 @@
 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
 		BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+		BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
 		BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) |
 		BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) |
 		BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2);
@@ -269,7 +271,8 @@
 
 void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
-	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2);
+	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
+		BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2);
 }
 
 void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -277,12 +280,32 @@
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
 }
 
+void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP ||
+	    wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
+		input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0);
+		input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0);
+		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
+	}
+}
+
+void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
+		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
+		input_dev->evbit[0] |= BIT_MASK(EV_MSC);
+		input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
+	}
+}
+
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
-			   struct wacom_wac *wacom_wac)
+			   struct wacom_features *features)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct wacom_features *features = wacom_wac->features;
-	char limit = 0, result = 0;
+	char limit = 0;
+	/* result has to be defined as int for some devices */
+	int result = 0;
 	int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
 	unsigned char *report;
 
@@ -328,13 +351,24 @@
 			case HID_USAGE_X:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->touch_x_max =
-							features->touch_y_max =
-							wacom_le16_to_cpu(&report[i + 3]);
+						features->device_type = BTN_TOOL_DOUBLETAP;
+						if (features->type == TABLETPC2FG) {
+							/* need to reset back */
+							features->pktlen = WACOM_PKGLEN_TPC2FG;
+							features->device_type = BTN_TOOL_TRIPLETAP;
+						}
 						features->x_max =
+							wacom_le16_to_cpu(&report[i + 3]);
+						features->x_phy =
 							wacom_le16_to_cpu(&report[i + 6]);
-						i += 7;
+						features->unit = report[i + 9];
+						features->unitExpo = report[i + 11];
+						i += 12;
 					} else if (pen) {
+						/* penabled only accepts exact bytes of data */
+						if (features->type == TABLETPC2FG)
+							features->pktlen = WACOM_PKGLEN_PENABLED;
+						features->device_type = BTN_TOOL_PEN;
 						features->x_max =
 							wacom_le16_to_cpu(&report[i + 3]);
 						i += 4;
@@ -350,10 +384,35 @@
 				break;
 
 			case HID_USAGE_Y:
-				if (usage == WCM_DESKTOP)
-					features->y_max =
-						wacom_le16_to_cpu(&report[i + 3]);
-				i += 4;
+				if (usage == WCM_DESKTOP) {
+					if (finger) {
+						features->device_type = BTN_TOOL_DOUBLETAP;
+						if (features->type == TABLETPC2FG) {
+							/* need to reset back */
+							features->pktlen = WACOM_PKGLEN_TPC2FG;
+							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->y_max =
+								wacom_le16_to_cpu(&report[i + 3]);
+							features->y_phy =
+								wacom_le16_to_cpu(&report[i + 6]);
+							i += 7;
+						} else {
+							features->y_max =
+								features->x_max;
+							features->y_phy =
+								wacom_le16_to_cpu(&report[i + 3]);
+							i += 4;
+						}
+					} else if (pen) {
+						/* penabled only accepts exact bytes of data */
+						if (features->type == TABLETPC2FG)
+							features->pktlen = WACOM_PKGLEN_PENABLED;
+						features->device_type = BTN_TOOL_PEN;
+						features->y_max =
+							wacom_le16_to_cpu(&report[i + 3]);
+						i += 4;
+					}
+				}
 				break;
 
 			case HID_USAGE_FINGER:
@@ -376,7 +435,7 @@
 			break;
 
 		case HID_COLLECTION:
-			/* reset UsagePage ans Finger */
+			/* reset UsagePage and Finger */
 			finger = usage = 0;
 			break;
 		}
@@ -388,43 +447,92 @@
 	return result;
 }
 
-static int wacom_query_tablet_data(struct usb_interface *intf)
+static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
 {
 	unsigned char *rep_data;
-	int limit = 0;
-	int error;
+	int limit = 0, report_id = 2;
+	int error = -ENOMEM;
 
 	rep_data = kmalloc(2, GFP_KERNEL);
 	if (!rep_data)
-		return -ENOMEM;
+		return error;
 
-	do {
-		rep_data[0] = 2;
-		rep_data[1] = 2;
-		error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-					2, rep_data, 2);
-		if (error >= 0)
-			error = usb_get_report(intf,
-						WAC_HID_FEATURE_REPORT, 2,
-						rep_data, 2);
-	} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+	/* ask to report tablet data if it is 2FGT or not a Tablet PC */
+	if (features->device_type == BTN_TOOL_TRIPLETAP) {
+		do {
+			rep_data[0] = 3;
+			rep_data[1] = 4;
+			report_id = 3;
+			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+				report_id, rep_data, 2);
+			if (error >= 0)
+				error = usb_get_report(intf,
+					WAC_HID_FEATURE_REPORT, report_id,
+					rep_data, 3);
+		} while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
+	} else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
+		do {
+			rep_data[0] = 2;
+			rep_data[1] = 2;
+			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+				report_id, rep_data, 2);
+			if (error >= 0)
+				error = usb_get_report(intf,
+					WAC_HID_FEATURE_REPORT, report_id,
+					rep_data, 2);
+		} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+	}
 
 	kfree(rep_data);
 
 	return error < 0 ? error : 0;
 }
 
+static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
+		struct wacom_features *features)
+{
+	int error = 0;
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	struct hid_descriptor *hid_desc;
+
+	/* default device to penabled */
+	features->device_type = BTN_TOOL_PEN;
+
+	/* only Tablet PCs need to retrieve the info */
+	if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
+		goto out;
+
+	if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
+		if (usb_get_extra_descriptor(&interface->endpoint[0],
+				HID_DEVICET_REPORT, &hid_desc)) {
+			printk("wacom: can not retrieve extra class descriptor\n");
+			error = 1;
+			goto out;
+		}
+	}
+	error = wacom_parse_hid(intf, hid_desc, features);
+	if (error)
+		goto out;
+
+	/* touch device found but size is not defined. use default */
+	if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+		features->x_max = 1023;
+		features->y_max = 1023;
+	}
+
+ out:
+	return error;
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct wacom_features *features;
 	struct input_dev *input_dev;
 	int error = -ENOMEM;
-	struct hid_descriptor *hid_desc;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
 	wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
@@ -432,7 +540,7 @@
 	if (!wacom || !input_dev || !wacom_wac)
 		goto fail1;
 
-	wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
+	wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma);
 	if (!wacom_wac->data)
 		goto fail1;
 
@@ -448,7 +556,7 @@
 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
 	wacom_wac->features = features = get_wacom_feature(id);
-	BUG_ON(features->pktlen > 10);
+	BUG_ON(features->pktlen > WACOM_PKGLEN_MAX);
 
 	input_dev->name = wacom_wac->features->name;
 	wacom->wacom_wac = wacom_wac;
@@ -463,47 +571,24 @@
 
 	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
-	/* Initialize touch_x_max and touch_y_max in case it is not defined */
-	if (wacom_wac->features->type == TABLETPC) {
-		features->touch_x_max = 1023;
-		features->touch_y_max = 1023;
-	} else {
-		features->touch_x_max = 0;
-		features->touch_y_max = 0;
-	}
-
-	/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
-	if (wacom_wac->features->type == TABLETPC) {
-		if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
-			if (usb_get_extra_descriptor(&interface->endpoint[0],
-						     HID_DEVICET_REPORT, &hid_desc)) {
-				printk("wacom: can not retrive extra class descriptor\n");
-				goto fail2;
-			}
-		}
-		error = wacom_parse_hid(intf, hid_desc, wacom_wac);
-		if (error)
-			goto fail2;
-	}
+	/* Retrieve the physical and logical size for OEM devices */
+	error = wacom_retrieve_hid_descriptor(intf, features);
+	if (error)
+		goto fail2;
 
 	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
-		BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
+	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH);
+
 	input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
-	if (features->type == TABLETPC) {
-		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
-		input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
-		input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
-	}
 	input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
 
 	wacom_init_input_dev(input_dev, wacom_wac);
 
 	usb_fill_int_urb(wacom->irq, dev,
 			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-			 wacom_wac->data, wacom_wac->features->pktlen,
+			 wacom_wac->data, features->pktlen,
 			 wacom_sys_irq, wacom, endpoint->bInterval);
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -512,18 +597,14 @@
 	if (error)
 		goto fail3;
 
-	/*
-	 * Ask the tablet to report tablet data if it is not a Tablet PC.
-	 * Note that if query fails it is not a hard failure.
-	 */
-	if (wacom_wac->features->type != TABLETPC)
-		wacom_query_tablet_data(intf);
+	/* Note that if query fails it is not a hard failure */
+	wacom_query_tablet_data(intf, features);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
  fail3:	usb_free_urb(wacom->irq);
- fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+ fail2:	usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
  fail1:	input_free_device(input_dev);
 	kfree(wacom);
 	kfree(wacom_wac);
@@ -539,7 +620,7 @@
 	usb_kill_urb(wacom->irq);
 	input_unregister_device(wacom->dev);
 	usb_free_urb(wacom->irq);
-	usb_buffer_free(interface_to_usbdev(intf), 10,
+	usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
 			wacom->wacom_wac->data, wacom->data_dma);
 	kfree(wacom->wacom_wac);
 	kfree(wacom);
@@ -559,13 +640,19 @@
 static int wacom_resume(struct usb_interface *intf)
 {
 	struct wacom *wacom = usb_get_intfdata(intf);
+	struct wacom_features *features = wacom->wacom_wac->features;
 	int rv;
 
 	mutex_lock(&wacom->lock);
+
+	/* switch to wacom mode first */
+	wacom_query_tablet_data(intf, features);
+
 	if (wacom->open)
 		rv = usb_submit_urb(wacom->irq, GFP_NOIO);
 	else
 		rv = 0;
+
 	mutex_unlock(&wacom->lock);
 
 	return rv;
--- linux-ec2-2.6.32.orig/drivers/input/mouse/synaptics.c
+++ linux-ec2-2.6.32/drivers/input/mouse/synaptics.c
@@ -135,7 +135,8 @@
 	if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
 		return -1;
 	priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
-	priv->ext_cap = 0;
+	priv->ext_cap = priv->ext_cap_0c = 0;
+
 	if (!SYN_CAP_VALID(priv->capabilities))
 		return -1;
 
@@ -148,7 +149,7 @@
 	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
 			printk(KERN_ERR "Synaptics claims to have extended capabilities,"
-			       " but I'm not able to read them.");
+			       " but I'm not able to read them.\n");
 		} else {
 			priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 
@@ -160,6 +161,16 @@
 				priv->ext_cap &= 0xff0fff;
 		}
 	}
+
+	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
+		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
+			printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
+			       " but I'm not able to read it.\n");
+		} else {
+			priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
+		}
+	}
+
 	return 0;
 }
 
@@ -346,7 +357,15 @@
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 
-		if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
+		if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+			/*
+			 * Clickpad's button is transmitted as middle button,
+			 * however, since it is primary button, we will report
+			 * it as BTN_LEFT.
+			 */
+			hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+
+		} else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 			hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
 			if (hw->w == 2)
 				hw->scroll = (signed char)(buf[1]);
@@ -591,6 +610,12 @@
 
 	dev->absres[ABS_X] = priv->x_res;
 	dev->absres[ABS_Y] = priv->y_res;
+
+	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+		/* Clickpads report only left button */
+		__clear_bit(BTN_RIGHT, dev->keybit);
+		__clear_bit(BTN_MIDDLE, dev->keybit);
+	}
 }
 
 static void synaptics_disconnect(struct psmouse *psmouse)
@@ -689,10 +714,10 @@
 
 	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
-	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n",
+	printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
 		SYN_ID_MODEL(priv->identity),
 		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
-		priv->model_id, priv->capabilities, priv->ext_cap);
+		priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
 
 	set_input_params(psmouse->dev, priv);
 
--- linux-ec2-2.6.32.orig/drivers/input/mouse/bcm5974.c
+++ linux-ec2-2.6.32/drivers/input/mouse/bcm5974.c
@@ -55,6 +55,14 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI	0x0236
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO	0x0237
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS	0x0238
+/* MacbookAir3,2 (unibody), aka wellspring5 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI	0x023f
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO	0x0240
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS	0x0241
+/* MacbookAir3,1 (unibody), aka wellspring4 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
 
 #define BCM5974_DEVICE(prod) {					\
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -80,6 +88,14 @@
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
+	/* MacbookAir3,2 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
+	/* MacbookAir3,1 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
 	/* Terminating entry */
 	{}
 };
@@ -233,6 +249,30 @@
 		{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
 		{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
 	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING4_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
+		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
+		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
+	},
 	{}
 };
 
--- linux-ec2-2.6.32.orig/drivers/input/mouse/psmouse-base.c
+++ linux-ec2-2.6.32/drivers/input/mouse/psmouse-base.c
@@ -667,19 +667,6 @@
 		max_proto = PSMOUSE_IMEX;
 	}
 
-/*
- * Try Finger Sensing Pad
- */
-	if (max_proto > PSMOUSE_IMEX) {
-		if (fsp_detect(psmouse, set_properties) == 0) {
-			if (!set_properties || fsp_init(psmouse) == 0)
-				return PSMOUSE_FSP;
-/*
- * Init failed, try basic relative protocols
- */
-			max_proto = PSMOUSE_IMEX;
-		}
-	}
 
 	if (max_proto > PSMOUSE_IMEX) {
 		if (genius_detect(psmouse, set_properties) == 0)
@@ -696,6 +683,21 @@
 	}
 
 /*
+ * Try Finger Sensing Pad. We do it here because its probe upsets
+ * Trackpoint devices (causing TP_READ_ID command to time out).
+ */
+	if (max_proto > PSMOUSE_IMEX) {
+		if (fsp_detect(psmouse, set_properties) == 0) {
+			if (!set_properties || fsp_init(psmouse) == 0)
+				return PSMOUSE_FSP;
+/*
+ * Init failed, try basic relative protocols
+ */
+			max_proto = PSMOUSE_IMEX;
+		}
+	}
+
+/*
  * Reset to defaults in case the device got confused by extended
  * protocol probes. Note that we follow up with full reset because
  * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS.
@@ -1347,6 +1349,7 @@
 	struct psmouse *psmouse = serio_get_drvdata(serio);
 	struct psmouse *parent = NULL;
 	struct serio_driver *drv = serio->drv;
+	unsigned char type;
 	int rc = -1;
 
 	if (!drv || !psmouse) {
@@ -1366,10 +1369,15 @@
 	if (psmouse->reconnect) {
 		if (psmouse->reconnect(psmouse))
 			goto out;
-	} else if (psmouse_probe(psmouse) < 0 ||
-		   psmouse->type != psmouse_extensions(psmouse,
-						psmouse_max_proto, false)) {
-		goto out;
+	} else {
+		psmouse_reset(psmouse);
+
+		if (psmouse_probe(psmouse) < 0)
+			goto out;
+
+		type = psmouse_extensions(psmouse, psmouse_max_proto, false);
+		if (psmouse->type != type)
+			goto out;
 	}
 
 	/* ok, the device type (and capabilities) match the old one,
--- linux-ec2-2.6.32.orig/drivers/input/mouse/alps.h
+++ linux-ec2-2.6.32/drivers/input/mouse/alps.h
@@ -23,6 +23,7 @@
 	char phys[32];			/* Phys */
 	const struct alps_model_info *i;/* Info */
 	int prev_fin;			/* Finger bit from previous packet */
+	struct timer_list timer;
 };
 
 #ifdef CONFIG_MOUSE_PS2_ALPS
--- linux-ec2-2.6.32.orig/drivers/input/mouse/elantech.h
+++ linux-ec2-2.6.32/drivers/input/mouse/elantech.h
@@ -100,11 +100,11 @@
 	unsigned char reg_26;
 	unsigned char debug;
 	unsigned char capabilities;
-	unsigned char fw_version_maj;
-	unsigned char fw_version_min;
+	bool paritycheck;
+	bool jumpy_cursor;
 	unsigned char hw_version;
-	unsigned char paritycheck;
-	unsigned char jumpy_cursor;
+	unsigned int fw_version;
+	unsigned int single_finger_reports;
 	unsigned char parity[256];
 };
 
--- linux-ec2-2.6.32.orig/drivers/input/mouse/alps.c
+++ linux-ec2-2.6.32/drivers/input/mouse/alps.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
  * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
  * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
  *
  * ALPS detection, tap switching and status querying info is taken from
  * tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -35,6 +36,8 @@
 #define ALPS_OLDPROTO	0x10
 #define ALPS_PASS	0x20
 #define ALPS_FW_BK_2	0x40
+#define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
+					   6-byte ALPS packet */
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -55,8 +58,12 @@
 	{ { 0x20, 0x02, 0x0e },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
 	{ { 0x22, 0x02, 0x0a },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
 	{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
-	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
+	/* Dell Latitude E5500, E6400, E6500, Precision M4400 */
+	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,
+		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
 	{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 },		  /* Dell Vostro 1400 */
+	{ { 0x52, 0x01, 0x14 }, 0xff, 0xff,
+		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },	  /* Toshiba Tecra A11-11L */
 };
 
 /*
@@ -66,20 +73,88 @@
  */
 
 /*
- * ALPS abolute Mode - new format
+ * PS/2 packet format
+ *
+ * byte 0:  0    0 YSGN XSGN    1    M    R    L
+ * byte 1: X7   X6   X5   X4   X3   X2   X1   X0
+ * byte 2: Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+ *
+ * Note that the device never signals overflow condition.
+ *
+ * ALPS absolute Mode - new format
  *
  * byte 0:  1    ?    ?    ?    1    ?    ?    ?
  * byte 1:  0   x6   x5   x4   x3   x2   x1   x0
- * byte 2:  0   x10  x9   x8   x7    ?  fin  ges
+ * byte 2:  0  x10   x9   x8   x7    ?  fin  ges
  * byte 3:  0   y9   y8   y7    1    M    R    L
  * byte 4:  0   y6   y5   y4   y3   y2   y1   y0
  * byte 5:  0   z6   z5   z4   z3   z2   z1   z0
  *
+ * Dualpoint device -- interleaved packet format
+ *
+ * byte 0:    1    1    0    0    1    1    1    1
+ * byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ * byte 2:    0  x10   x9   x8   x7    0  fin  ges
+ * byte 3:    0    0 YSGN XSGN    1    1    1    1
+ * byte 4:   X7   X6   X5   X4   X3   X2   X1   X0
+ * byte 5:   Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+ * byte 6:    0   y9   y8   y7    1    m    r    l
+ * byte 7:    0   y6   y5   y4   y3   y2   y1   y0
+ * byte 8:    0   z6   z5   z4   z3   z2   z1   z0
+ *
+ * CAPITALS = stick, miniscules = touchpad
+ *
  * ?'s can have different meanings on different models,
  * such as wheel rotation, extra buttons, stick buttons
  * on a dualpoint, etc.
  */
 
+static bool alps_is_valid_first_byte(const struct alps_model_info *model,
+				     unsigned char data)
+{
+	return (data & model->mask0) == model->byte0;
+}
+
+static void alps_report_buttons(struct psmouse *psmouse,
+				struct input_dev *dev1, struct input_dev *dev2,
+				int left, int right, int middle)
+{
+	struct alps_data *priv = psmouse->private;
+	const struct alps_model_info *model = priv->i;
+
+	if (model->flags & ALPS_PS2_INTERLEAVED) {
+		struct input_dev *dev;
+
+		/*
+		 * If shared button has already been reported on the
+		 * other device (dev2) then this event should be also
+		 * sent through that device.
+		 */
+		dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_LEFT, left);
+
+		dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_RIGHT, right);
+
+		dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_MIDDLE, middle);
+
+		/*
+		 * Sync the _other_ device now, we'll do the first
+		 * device later once we report the rest of the events.
+		 */
+		input_sync(dev2);
+	} else {
+		/*
+		 * For devices with non-interleaved packets we know what
+		 * device buttons belong to so we can simply report them.
+		 */
+		input_report_key(dev1, BTN_LEFT, left);
+		input_report_key(dev1, BTN_RIGHT, right);
+		input_report_key(dev1, BTN_MIDDLE, middle);
+	}
+}
+
 static void alps_process_packet(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -89,18 +164,6 @@
 	int x, y, z, ges, fin, left, right, middle;
 	int back = 0, forward = 0;
 
-	if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
-		input_report_key(dev2, BTN_LEFT,   packet[0] & 1);
-		input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
-		input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
-		input_report_rel(dev2, REL_X,
-			packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
-		input_report_rel(dev2, REL_Y,
-			packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
-		input_sync(dev2);
-		return;
-	}
-
 	if (priv->i->flags & ALPS_OLDPROTO) {
 		left = packet[2] & 0x10;
 		right = packet[2] & 0x08;
@@ -136,18 +199,13 @@
 		input_report_rel(dev2, REL_X,  (x > 383 ? (x - 768) : x));
 		input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
 
-		input_report_key(dev2, BTN_LEFT, left);
-		input_report_key(dev2, BTN_RIGHT, right);
-		input_report_key(dev2, BTN_MIDDLE, middle);
+		alps_report_buttons(psmouse, dev2, dev, left, right, middle);
 
-		input_sync(dev);
 		input_sync(dev2);
 		return;
 	}
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev, BTN_MIDDLE, middle);
+	alps_report_buttons(psmouse, dev, dev2, left, right, middle);
 
 	/* Convert hardware tap to a reasonable Z value */
 	if (ges && !fin) z = 40;
@@ -188,25 +246,168 @@
 	input_sync(dev);
 }
 
+static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
+					unsigned char packet[],
+					bool report_buttons)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev2 = priv->dev2;
+
+	if (report_buttons)
+		alps_report_buttons(psmouse, dev2, psmouse->dev,
+				packet[0] & 1, packet[0] & 2, packet[0] & 4);
+
+	input_report_rel(dev2, REL_X,
+		packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
+	input_report_rel(dev2, REL_Y,
+		packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+
+	input_sync(dev2);
+}
+
+static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+
+	if (psmouse->pktcnt < 6)
+		return PSMOUSE_GOOD_DATA;
+
+	if (psmouse->pktcnt == 6) {
+		/*
+		 * Start a timer to flush the packet if it ends up last
+		 * 6-byte packet in the stream. Timer needs to fire
+		 * psmouse core times out itself. 20 ms should be enough
+		 * to decide if we are getting more data or not.
+		 */
+		mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
+		return PSMOUSE_GOOD_DATA;
+	}
+
+	del_timer(&priv->timer);
+
+	if (psmouse->packet[6] & 0x80) {
+
+		/*
+		 * Highest bit is set - that means we either had
+		 * complete ALPS packet and this is start of the
+		 * next packet or we got garbage.
+		 */
+
+		if (((psmouse->packet[3] |
+		      psmouse->packet[4] |
+		      psmouse->packet[5]) & 0x80) ||
+		    (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
+			dbg("refusing packet %x %x %x %x "
+			    "(suspected interleaved ps/2)\n",
+			    psmouse->packet[3], psmouse->packet[4],
+			    psmouse->packet[5], psmouse->packet[6]);
+			return PSMOUSE_BAD_DATA;
+		}
+
+		alps_process_packet(psmouse);
+
+		/* Continue with the next packet */
+		psmouse->packet[0] = psmouse->packet[6];
+		psmouse->pktcnt = 1;
+
+	} else {
+
+		/*
+		 * High bit is 0 - that means that we indeed got a PS/2
+		 * packet in the middle of ALPS packet.
+		 *
+		 * There is also possibility that we got 6-byte ALPS
+		 * packet followed  by 3-byte packet from trackpoint. We
+		 * can not distinguish between these 2 scenarios but
+		 * becase the latter is unlikely to happen in course of
+		 * normal operation (user would need to press all
+		 * buttons on the pad and start moving trackpoint
+		 * without touching the pad surface) we assume former.
+		 * Even if we are wrong the wost thing that would happen
+		 * the cursor would jump but we should not get protocol
+		 * desynchronization.
+		 */
+
+		alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
+					    false);
+
+		/*
+		 * Continue with the standard ALPS protocol handling,
+		 * but make sure we won't process it as an interleaved
+		 * packet again, which may happen if all buttons are
+		 * pressed. To avoid this let's reset the 4th bit which
+		 * is normally 1.
+		 */
+		psmouse->packet[3] = psmouse->packet[6] & 0xf7;
+		psmouse->pktcnt = 4;
+	}
+
+	return PSMOUSE_GOOD_DATA;
+}
+
+static void alps_flush_packet(unsigned long data)
+{
+	struct psmouse *psmouse = (struct psmouse *)data;
+
+	serio_pause_rx(psmouse->ps2dev.serio);
+
+	if (psmouse->pktcnt == 6) {
+
+		/*
+		 * We did not any more data in reasonable amount of time.
+		 * Validate the last 3 bytes and process as a standard
+		 * ALPS packet.
+		 */
+		if ((psmouse->packet[3] |
+		     psmouse->packet[4] |
+		     psmouse->packet[5]) & 0x80) {
+			dbg("refusing packet %x %x %x "
+			    "(suspected interleaved ps/2)\n",
+			    psmouse->packet[3], psmouse->packet[4],
+			    psmouse->packet[5]);
+		} else {
+			alps_process_packet(psmouse);
+		}
+		psmouse->pktcnt = 0;
+	}
+
+	serio_continue_rx(psmouse->ps2dev.serio);
+}
+
 static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
+	const struct alps_model_info *model = priv->i;
 
 	if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
 		if (psmouse->pktcnt == 3) {
-			alps_process_packet(psmouse);
+			alps_report_bare_ps2_packet(psmouse, psmouse->packet,
+						    true);
 			return PSMOUSE_FULL_PACKET;
 		}
 		return PSMOUSE_GOOD_DATA;
 	}
 
-	if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
+	/* Check for PS/2 packet stuffed in the middle of ALPS packet. */
+
+	if ((model->flags & ALPS_PS2_INTERLEAVED) &&
+	    psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
+		return alps_handle_interleaved_ps2(psmouse);
+	}
+
+	if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
+		dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+		    psmouse->packet[0], model->mask0, model->byte0);
 		return PSMOUSE_BAD_DATA;
+	}
 
 	/* Bytes 2 - 6 should have 0 in the highest bit */
 	if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
-	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
+	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
+		dbg("refusing packet[%i] = %x\n",
+		    psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
 		return PSMOUSE_BAD_DATA;
+	}
 
 	if (psmouse->pktcnt == 6) {
 		alps_process_packet(psmouse);
@@ -432,7 +633,8 @@
 
 static int alps_reconnect(struct psmouse *psmouse)
 {
-	psmouse_reset(psmouse);
+	/* UBUNTU: Causes lockups on resume */
+	/* psmouse_reset(psmouse); */
 
 	if (alps_hw_init(psmouse, NULL))
 		return -1;
@@ -445,6 +647,7 @@
 	struct alps_data *priv = psmouse->private;
 
 	psmouse_reset(psmouse);
+	del_timer_sync(&priv->timer);
 	input_unregister_device(priv->dev2);
 	kfree(priv);
 }
@@ -461,6 +664,8 @@
 		goto init_fail;
 
 	priv->dev2 = dev2;
+	setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
+
 	psmouse->private = priv;
 
 	if (alps_hw_init(psmouse, &version))
--- linux-ec2-2.6.32.orig/drivers/input/mouse/elantech.c
+++ linux-ec2-2.6.32/drivers/input/mouse/elantech.c
@@ -24,6 +24,10 @@
 			printk(KERN_DEBUG format, ##arg);	\
 	} while (0)
 
+static bool force_elantech;
+module_param_named(force_elantech, force_elantech, bool, 0644);
+MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
+
 /*
  * Send a Synaptics style sliced query command
  */
@@ -178,36 +182,44 @@
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	int fingers;
-	static int old_fingers;
 
-	if (etd->fw_version_maj == 0x01) {
-		/* byte 0:  D   U  p1  p2   1  p3   R   L
-		   byte 1:  f   0  th  tw  x9  x8  y9  y8 */
+	if (etd->fw_version < 0x020000) {
+		/*
+		 * byte 0:  D   U  p1  p2   1  p3   R   L
+		 * byte 1:  f   0  th  tw  x9  x8  y9  y8
+		 */
 		fingers = ((packet[1] & 0x80) >> 7) +
 				((packet[1] & 0x30) >> 4);
 	} else {
-		/* byte 0: n1  n0  p2  p1   1  p3   R   L
-		   byte 1:  0   0   0   0  x9  x8  y9  y8 */
+		/*
+		 * byte 0: n1  n0  p2  p1   1  p3   R   L
+		 * byte 1:  0   0   0   0  x9  x8  y9  y8
+		 */
 		fingers = (packet[0] & 0xc0) >> 6;
 	}
 
 	if (etd->jumpy_cursor) {
-		/* Discard packets that are likely to have bogus coordinates */
-		if (fingers > old_fingers) {
+		if (fingers != 1) {
+			etd->single_finger_reports = 0;
+		} else if (etd->single_finger_reports < 2) {
+			/* Discard first 2 reports of one finger, bogus */
+			etd->single_finger_reports++;
 			elantech_debug("elantech.c: discarding packet\n");
-			goto discard_packet_v1;
+			return;
 		}
 	}
 
 	input_report_key(dev, BTN_TOUCH, fingers != 0);
 
-	/* byte 2: x7  x6  x5  x4  x3  x2  x1  x0
-	   byte 3: y7  y6  y5  y4  y3  y2  y1  y0 */
+	/*
+	 * byte 2: x7  x6  x5  x4  x3  x2  x1  x0
+	 * byte 3: y7  y6  y5  y4  y3  y2  y1  y0
+	 */
 	if (fingers) {
 		input_report_abs(dev, ABS_X,
 			((packet[1] & 0x0c) << 6) | packet[2]);
-		input_report_abs(dev, ABS_Y, ETP_YMAX_V1 -
-			(((packet[1] & 0x03) << 8) | packet[3]));
+		input_report_abs(dev, ABS_Y,
+			ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
 	}
 
 	input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
@@ -216,7 +228,7 @@
 	input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
 	input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
 
-	if ((etd->fw_version_maj == 0x01) &&
+	if (etd->fw_version < 0x020000 &&
 	    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
 		/* rocker up */
 		input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
@@ -225,9 +237,6 @@
 	}
 
 	input_sync(dev);
-
- discard_packet_v1:
-	old_fingers = fingers;
 }
 
 /*
@@ -246,34 +255,47 @@
 
 	switch (fingers) {
 	case 1:
-		/* byte 1: x15 x14 x13 x12 x11 x10 x9  x8
-		   byte 2: x7  x6  x5  x4  x4  x2  x1  x0 */
-		input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]);
-		/* byte 4: y15 y14 y13 y12 y11 y10 y8  y8
-		   byte 5: y7  y6  y5  y4  y3  y2  y1  y0 */
-		input_report_abs(dev, ABS_Y, ETP_YMAX_V2 -
-			((packet[4] << 8) | packet[5]));
+		/*
+		 * byte 1:  .   .   .   .   .  x10 x9  x8
+		 * byte 2: x7  x6  x5  x4  x4  x2  x1  x0
+		 */
+		input_report_abs(dev, ABS_X,
+			((packet[1] & 0x07) << 8) | packet[2]);
+		/*
+		 * byte 4:  .   .   .   .   .   .  y9  y8
+		 * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+		 */
+		input_report_abs(dev, ABS_Y,
+			ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]));
 		break;
 
 	case 2:
-		/* The coordinate of each finger is reported separately with
-		   a lower resolution for two finger touches */
-		/* byte 0:  .   .  ay8 ax8  .   .   .   .
-		   byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */
+		/*
+		 * The coordinate of each finger is reported separately
+		 * with a lower resolution for two finger touches:
+		 * byte 0:  .   .  ay8 ax8  .   .   .   .
+		 * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
+		 */
 		x1 = ((packet[0] & 0x10) << 4) | packet[1];
 		/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
 		y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
-		/* byte 3:  .   .  by8 bx8  .   .   .   .
-		   byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */
+		/*
+		 * byte 3:  .   .  by8 bx8  .   .   .   .
+		 * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
+		 */
 		x2 = ((packet[3] & 0x10) << 4) | packet[4];
 		/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
 		y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
-		/* For compatibility with the X Synaptics driver scale up one
-		   coordinate and report as ordinary mouse movent */
+		/*
+		 * For compatibility with the X Synaptics driver scale up
+		 * one coordinate and report as ordinary mouse movent
+		 */
 		input_report_abs(dev, ABS_X, x1 << 2);
 		input_report_abs(dev, ABS_Y, y1 << 2);
-		/* For compatibility with the proprietary X Elantech driver
-		   report both coordinates as hat coordinates */
+		/*
+		 * For compatibility with the proprietary X Elantech driver
+		 * report both coordinates as hat coordinates
+		 */
 		input_report_abs(dev, ABS_HAT0X, x1);
 		input_report_abs(dev, ABS_HAT0Y, y1);
 		input_report_abs(dev, ABS_HAT1X, x2);
@@ -297,7 +319,7 @@
 	unsigned char p1, p2, p3;
 
 	/* Parity bits are placed differently */
-	if (etd->fw_version_maj == 0x01) {
+	if (etd->fw_version < 0x020000) {
 		/* byte 0:  D   U  p1  p2   1  p3   R   L */
 		p1 = (packet[0] & 0x20) >> 5;
 		p2 = (packet[0] & 0x10) >> 4;
@@ -420,6 +442,7 @@
 
 	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
+	__clear_bit(EV_REL, dev->evbit);
 
 	__set_bit(BTN_LEFT, dev->keybit);
 	__set_bit(BTN_RIGHT, dev->keybit);
@@ -432,7 +455,7 @@
 	switch (etd->hw_version) {
 	case 1:
 		/* Rocker button */
-		if ((etd->fw_version_maj == 0x01) &&
+		if (etd->fw_version < 0x020000 &&
 		    (etd->capabilities & ETP_CAP_HAS_ROCKER)) {
 			__set_bit(BTN_FORWARD, dev->keybit);
 			__set_bit(BTN_BACK, dev->keybit);
@@ -550,6 +573,24 @@
 	.attrs = elantech_attrs,
 };
 
+static bool elantech_is_signature_valid(const unsigned char *param)
+{
+	static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 };
+	int i;
+
+	if (param[0] == 0)
+		return false;
+
+	if (param[1] == 0)
+		return true;
+
+	for (i = 0; i < ARRAY_SIZE(rates); i++)
+		if (param[2] == rates[i])
+			return false;
+
+	return true;
+}
+
 /*
  * Use magic knock to detect Elantech touchpad
  */
@@ -593,9 +634,13 @@
 	pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n",
 		 param[0], param[1], param[2]);
 
-	if (param[0] == 0 || param[1] != 0) {
-		pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n");
-		return -1;
+	if (!elantech_is_signature_valid(param)) {
+		if (!force_elantech) {
+			pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n");
+			return -1;
+		}
+
+		pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
 	}
 
 	if (set_properties) {
@@ -657,14 +702,14 @@
 		pr_err("elantech.c: failed to query firmware version.\n");
 		goto init_fail;
 	}
-	etd->fw_version_maj = param[0];
-	etd->fw_version_min = param[2];
+
+	etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
 
 	/*
 	 * Assume every version greater than this is new EeePC style
 	 * hardware with 6 byte packets
 	 */
-	if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) {
+	if (etd->fw_version >= 0x020030) {
 		etd->hw_version = 2;
 		/* For now show extra debug information */
 		etd->debug = 1;
@@ -674,8 +719,9 @@
 		etd->hw_version = 1;
 		etd->paritycheck = 1;
 	}
-	pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n",
-		etd->hw_version, etd->fw_version_maj, etd->fw_version_min);
+
+	pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n",
+		etd->hw_version, param[0], param[1], param[2]);
 
 	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
 		pr_err("elantech.c: failed to query capabilities.\n");
@@ -686,14 +732,14 @@
 	etd->capabilities = param[0];
 
 	/*
-	 * This firmware seems to suffer from misreporting coordinates when
+	 * This firmware suffers from misreporting coordinates when
 	 * a touch action starts causing the mouse cursor or scrolled page
 	 * to jump. Enable a workaround.
 	 */
-	if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
-		pr_info("elantech.c: firmware version 2.34 detected, "
+	if (etd->fw_version == 0x020022 || etd->fw_version == 0x020600) {
+		pr_info("elantech.c: firmware version 2.0.34/2.6.0 detected, "
 			"enabling jumpy cursor workaround\n");
-		etd->jumpy_cursor = 1;
+		etd->jumpy_cursor = true;
 	}
 
 	if (elantech_set_absolute_mode(psmouse)) {
--- linux-ec2-2.6.32.orig/drivers/input/mouse/synaptics.h
+++ linux-ec2-2.6.32/drivers/input/mouse/synaptics.h
@@ -18,6 +18,7 @@
 #define SYN_QUE_SERIAL_NUMBER_SUFFIX	0x07
 #define SYN_QUE_RESOLUTION		0x08
 #define SYN_QUE_EXT_CAPAB		0x09
+#define SYN_QUE_EXT_CAPAB_0C		0x0c
 
 /* synatics modes */
 #define SYN_BIT_ABSOLUTE_MODE		(1 << 7)
@@ -48,6 +49,8 @@
 #define SYN_CAP_VALID(c)		((((c) & 0x00ff00) >> 8) == 0x47)
 #define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12)
+#define SYN_CAP_PRODUCT_ID(ec)		(((ec) & 0xff0000) >> 16)
+#define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100100)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
@@ -96,6 +99,7 @@
 	unsigned long int model_id;		/* Model-ID */
 	unsigned long int capabilities;		/* Capabilities */
 	unsigned long int ext_cap;		/* Extended Capabilities */
+	unsigned long int ext_cap_0c;		/* Ext Caps from 0x0c query */
 	unsigned long int identity;		/* Identification */
 	int x_res;				/* X resolution in units/mm */
 	int y_res;				/* Y resolution in units/mm */
--- linux-ec2-2.6.32.orig/drivers/input/keyboard/twl4030_keypad.c
+++ linux-ec2-2.6.32/drivers/input/keyboard/twl4030_keypad.c
@@ -50,8 +50,12 @@
  */
 #define TWL4030_MAX_ROWS	8	/* TWL4030 hard limit */
 #define TWL4030_MAX_COLS	8
-#define TWL4030_ROW_SHIFT	3
-#define TWL4030_KEYMAP_SIZE	(TWL4030_MAX_ROWS * TWL4030_MAX_COLS)
+/*
+ * Note that we add space for an extra column so that we can handle
+ * row lines connected to the gnd (see twl4030_col_xlate()).
+ */
+#define TWL4030_ROW_SHIFT	4
+#define TWL4030_KEYMAP_SIZE	(TWL4030_MAX_ROWS << TWL4030_ROW_SHIFT)
 
 struct twl4030_keypad {
 	unsigned short	keymap[TWL4030_KEYMAP_SIZE];
@@ -181,7 +185,7 @@
 	return ret;
 }
 
-static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
+static bool twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state)
 {
 	int i;
 	u16 check = 0;
@@ -190,12 +194,12 @@
 		u16 col = key_state[i];
 
 		if ((col & check) && hweight16(col) > 1)
-			return 1;
+			return true;
 
 		check |= col;
 	}
 
-	return 0;
+	return false;
 }
 
 static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all)
@@ -224,7 +228,8 @@
 		if (!changed)
 			continue;
 
-		for (col = 0; col < kp->n_cols; col++) {
+		/* Extra column handles "all gnd" rows */
+		for (col = 0; col < kp->n_cols + 1; col++) {
 			int code;
 
 			if (!(changed & (1 << col)))
--- linux-ec2-2.6.32.orig/drivers/input/keyboard/atkbd.c
+++ linux-ec2-2.6.32/drivers/input/keyboard/atkbd.c
@@ -912,6 +912,14 @@
 };
 
 /*
+ * Fujitsu Siemens system with broken key release on volume keys and mute key
+ */
+
+static unsigned int atkbd_amilo_xi_2428_forced_release_keys[] = {
+	0xa0, 0xae, 0xb0, -1U
+};
+
+/*
  * Soltech TA12 system with broken key release on volume keys and mute key
  */
 static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
@@ -1695,6 +1703,34 @@
 		.driver_data = atkbd_amilo_xi3650_forced_release_keys,
 	},
 	{
+		.ident = "Znote 6615WD",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Zepto"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Znote 6615WD"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_volume_forced_release_keys,
+	},
+	{
+		.ident = "Znote 6625WD",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Zepto"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Znote"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "6625WD"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_volume_forced_release_keys,
+	},
+	{
+		.ident = "AMILO Xi 2428",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428"),
+		},
+		.callback = atkbd_setup_forced_release,
+		.driver_data = atkbd_amilo_xi_2428_forced_release_keys,
+	},
+	{
 		.ident = "Soltech Corporation TA12",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
--- linux-ec2-2.6.32.orig/drivers/input/serio/i8042-x86ia64io.h
+++ linux-ec2-2.6.32/drivers/input/serio/i8042-x86ia64io.h
@@ -67,10 +67,12 @@
 
 #include <linux/dmi.h>
 
-static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
 	{
-		/* AUX LOOP command does not raise AUX IRQ */
-		.ident = "Arima-Rioworks HDAMB",
+		/*
+		 * Arima-Rioworks HDAMB -
+		 * AUX LOOP command does not raise AUX IRQ
+		 */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
 			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
@@ -78,7 +80,7 @@
 		},
 	},
 	{
-		.ident = "ASUS G1S",
+		/* ASUS G1S */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
 			DMI_MATCH(DMI_BOARD_NAME, "G1S"),
@@ -86,8 +88,7 @@
 		},
 	},
 	{
-		/* AUX LOOP command does not raise AUX IRQ */
-		.ident = "ASUS P65UP5",
+		/* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
 			DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),
@@ -95,7 +96,6 @@
 		},
 	},
 	{
-		.ident = "Compaq Proliant 8500",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
 			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
@@ -103,7 +103,6 @@
 		},
 	},
 	{
-		.ident = "Compaq Proliant DL760",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
 			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
@@ -111,7 +110,7 @@
 		},
 	},
 	{
-		.ident = "OQO Model 01",
+		/* OQO Model 01 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
@@ -119,8 +118,7 @@
 		},
 	},
 	{
-		/* AUX LOOP does not work properly */
-		.ident = "ULI EV4873",
+		/* ULI EV4873 - AUX LOOP does not work properly */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
@@ -128,7 +126,7 @@
 		},
 	},
 	{
-		.ident = "Microsoft Virtual Machine",
+		/* Microsoft Virtual Machine */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
@@ -136,7 +134,7 @@
 		},
 	},
 	{
-		.ident = "Medion MAM 2070",
+		/* Medion MAM 2070 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
@@ -144,7 +142,7 @@
 		},
 	},
 	{
-		.ident = "Blue FB5601",
+		/* Blue FB5601 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "blue"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"),
@@ -152,7 +150,7 @@
 		},
 	},
 	{
-		.ident = "Gigabyte M912",
+		/* Gigabyte M912 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
@@ -160,7 +158,21 @@
 		},
 	},
 	{
-		.ident = "HP DV9700",
+		/* Gigabyte M1022M netbook */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
+			DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
+			DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
+		},
+	},
+	{
+		/* Gigabyte Spring Peak - defines wrong chassis type */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
+		},
+	},
+	{
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
@@ -177,72 +189,72 @@
  * ... apparently some Toshibas don't like MUX mode either and
  * die horrible death on reboot.
  */
-static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
 	{
-		.ident = "Fujitsu Lifebook P7010/P7010D",
+		/* Fujitsu Lifebook P7010/P7010D */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
 		},
 	},
 	{
-		.ident = "Fujitsu Lifebook P7010",
+		/* Fujitsu Lifebook P7010 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
 		},
 	},
 	{
-		.ident = "Fujitsu Lifebook P5020D",
+		/* Fujitsu Lifebook P5020D */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
 		},
 	},
 	{
-		.ident = "Fujitsu Lifebook S2000",
+		/* Fujitsu Lifebook S2000 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
 		},
 	},
 	{
-		.ident = "Fujitsu Lifebook S6230",
+		/* Fujitsu Lifebook S6230 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
 		},
 	},
 	{
-		.ident = "Fujitsu T70H",
+		/* Fujitsu T70H */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
 		},
 	},
 	{
-		.ident = "Fujitsu-Siemens Lifebook T3010",
+		/* Fujitsu-Siemens Lifebook T3010 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
 		},
 	},
 	{
-		.ident = "Fujitsu-Siemens Lifebook E4010",
+		/* Fujitsu-Siemens Lifebook E4010 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
 		},
 	},
 	{
-		.ident = "Fujitsu-Siemens Amilo Pro 2010",
+		/* Fujitsu-Siemens Amilo Pro 2010 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),
 		},
 	},
 	{
-		.ident = "Fujitsu-Siemens Amilo Pro 2030",
+		/* Fujitsu-Siemens Amilo Pro 2030 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
@@ -253,7 +265,7 @@
 		 * No data is coming from the touchscreen unless KBC
 		 * is in legacy mode.
 		 */
-		.ident = "Panasonic CF-29",
+		/* Panasonic CF-29 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
@@ -261,10 +273,10 @@
 	},
 	{
 		/*
-		 * Errors on MUX ports are reported without raising AUXDATA
+		 * HP Pavilion DV4017EA -
+		 * errors on MUX ports are reported without raising AUXDATA
 		 * causing "spurious NAK" messages.
 		 */
-		.ident = "HP Pavilion DV4017EA",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
@@ -272,9 +284,9 @@
 	},
 	{
 		/*
-		 * Like DV4017EA does not raise AUXERR for errors on MUX ports.
+		 * HP Pavilion ZT1000 -
+		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
 		 */
-		.ident = "HP Pavilion ZT1000",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
@@ -283,44 +295,48 @@
 	},
 	{
 		/*
-		 * Like DV4017EA does not raise AUXERR for errors on MUX ports.
+		 * HP Pavilion DV4270ca -
+		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
 		 */
-		.ident = "HP Pavilion DV4270ca",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
 		},
 	},
 	{
-		.ident = "Toshiba P10",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
 		},
 	},
 	{
-		.ident = "Toshiba Equium A110",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
 		},
 	},
 	{
-		.ident = "Alienware Sentia",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
 		},
 	},
 	{
-		.ident = "Sharp Actius MM20",
+		/* Sharp Actius MM20 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
 		},
 	},
 	{
-		.ident = "Sony Vaio FS-115b",
+		/* Sony Vaio VPCZ122GX */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VPCZ122GX"),
+		},
+	},
+	{
+		/* Sony Vaio FS-115b */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
@@ -328,141 +344,154 @@
 	},
 	{
 		/*
-		 * Reset and GET ID commands issued via KBD port are
+		 * Sony Vaio FZ-240E -
+		 * reset and GET ID commands issued via KBD port are
 		 * sometimes being delivered to AUX3.
 		 */
-		.ident = "Sony Vaio FZ-240E",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
 		},
 	},
 	{
-		.ident = "Amoi M636/A737",
+		/* Amoi M636/A737 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
 		},
 	},
 	{
-		.ident = "Lenovo 3000 n100",
+		/* Lenovo 3000 n100 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 1360",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
 		},
 	},
 	{
-		.ident = "Gericom Bellagio",
+		/* Gericom Bellagio */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
 		},
 	},
 	{
-		.ident = "IBM 2656",
+		/* IBM 2656 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
 		},
 	},
 	{
-		.ident = "Dell XPS M1530",
+		/* Dell XPS M1530 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
 		},
 	},
 	{
-		.ident = "Compal HEL80I",
+		/* Compal HEL80I */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
 		},
 	},
 	{
-		.ident = "Dell Vostro 1510",
+		/* Dell Vostro 1510 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 5536",
+		/* Acer Aspire 5536 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
 			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
 		},
 	},
+	{
+		/* Dell Vostro V13 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+		},
+	},
 	{ }
 };
 
-static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
 	{
-		.ident = "MSI Wind U-100",
+		/* MSI Wind U-100 */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "U-100"),
 			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
 		},
 	},
 	{
-		.ident = "LG Electronics X110",
+		/* LG Electronics X110 */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "X110"),
 			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
 		},
 	},
 	{
-		.ident = "Acer Aspire One 150",
+		/* Acer Aspire One 150 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
 		},
 	},
 	{
-		.ident = "Advent 4211",
+		/* Advent 4211 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
 		},
 	},
 	{
-		.ident = "Medion Akoya Mini E1210",
+		/* Medion Akoya Mini E1210 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
 		},
 	},
 	{
-		.ident = "Mivvy M310",
+		/* Medion Akoya E1222 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E122X"),
+		},
+	},
+	{
+		/* Mivvy M310 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
 		},
 	},
 	{
-		.ident = "Dell Vostro 1320",
+		/* Dell Vostro 1320 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
 		},
 	},
 	{
-		.ident = "Dell Vostro 1520",
+		/* Dell Vostro 1520 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
 		},
 	},
 	{
-		.ident = "Dell Vostro 1720",
+		/* Dell Vostro 1720 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
@@ -472,16 +501,16 @@
 };
 
 #ifdef CONFIG_PNP
-static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
 	{
-		.ident = "Intel MBO Desktop D845PESV",
+		/* Intel MBO Desktop D845PESV */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
 		},
 	},
 	{
-		.ident = "MSI Wind U-100",
+		/* MSI Wind U-100 */
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "U-100"),
 			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
@@ -490,27 +519,23 @@
 	{ }
 };
 
-static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = {
 	{
-		.ident = "Portable",
 		.matches = {
 			DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
 		},
 	},
 	{
-		.ident = "Laptop",
 		.matches = {
 			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
 		},
 	},
 	{
-		.ident = "Notebook",
 		.matches = {
 			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
 		},
 	},
 	{
-		.ident = "Sub-Notebook",
 		.matches = {
 			DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
 		},
@@ -519,64 +544,82 @@
 };
 #endif
 
+static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
+	{
+		/* Dell Vostro V13 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+		},
+	},
+	{ }
+};
+
 /*
  * Some Wistron based laptops need us to explicitly enable the 'Dritek
  * keyboard extension' to make their extra keys start generating scancodes.
  * Originally, this was just confined to older laptops, but a few Acer laptops
  * have turned up in 2007 that also need this again.
  */
-static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
+	{
+		/* Acer Aspire 5610 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+		},
+	},
 	{
-		.ident = "Acer Aspire 5630",
+		/* Acer Aspire 5630 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 5650",
+		/* Acer Aspire 5650 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 5680",
+		/* Acer Aspire 5680 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 5720",
+		/* Acer Aspire 5720 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
 		},
 	},
 	{
-		.ident = "Acer Aspire 9110",
+		/* Acer Aspire 9110 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
 		},
 	},
 	{
-		.ident = "Acer TravelMate 660",
+		/* Acer TravelMate 660 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
 		},
 	},
 	{
-		.ident = "Acer TravelMate 2490",
+		/* Acer TravelMate 2490 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
 		},
 	},
 	{
-		.ident = "Acer TravelMate 4280",
+		/* Acer TravelMate 4280 */
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
@@ -841,6 +884,9 @@
 	if (dmi_check_system(i8042_dmi_nomux_table))
 		i8042_nomux = true;
 
+	if (dmi_check_system(i8042_dmi_notimeout_table))
+		i8042_notimeout = true;
+
 	if (dmi_check_system(i8042_dmi_dritek_table))
 		i8042_dritek = true;
 #endif /* CONFIG_X86 */
--- linux-ec2-2.6.32.orig/drivers/input/serio/i8042.c
+++ linux-ec2-2.6.32/drivers/input/serio/i8042.c
@@ -64,6 +64,10 @@
 module_param_named(panicblink, i8042_blink_frequency, uint, 0600);
 MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics");
 
+static bool i8042_notimeout;
+module_param_named(notimeout, i8042_notimeout, bool, 0);
+MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042");
+
 #ifdef CONFIG_X86
 static bool i8042_dritek;
 module_param_named(dritek, i8042_dritek, bool, 0);
@@ -434,7 +438,7 @@
 	} else {
 
 		dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
-		      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+		      ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0);
 
 		port_no = (str & I8042_STR_AUXDATA) ?
 				I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
@@ -1412,8 +1416,8 @@
 
 static void __exit i8042_exit(void)
 {
-	platform_driver_unregister(&i8042_driver);
 	platform_device_unregister(i8042_platform_device);
+	platform_driver_unregister(&i8042_driver);
 	i8042_platform_exit();
 
 	panic_blink = NULL;
--- linux-ec2-2.6.32.orig/drivers/input/misc/winbond-cir.c
+++ linux-ec2-2.6.32/drivers/input/misc/winbond-cir.c
@@ -768,7 +768,7 @@
 		return;
 	}
 
-	dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
+	dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
 		"toggle %u mode %u scan 0x%08X\n",
 		address,
 		command,
--- linux-ec2-2.6.32.orig/drivers/isdn/gigaset/interface.c
+++ linux-ec2-2.6.32/drivers/isdn/gigaset/interface.c
@@ -635,7 +635,6 @@
 	if ((tty = cs->tty) == NULL)
 		gig_dbg(DEBUG_ANY, "receive on closed device");
 	else {
-		tty_buffer_request_room(tty, len);
 		tty_insert_flip_string(tty, buffer, len);
 		tty_flip_buffer_push(tty);
 	}
--- linux-ec2-2.6.32.orig/drivers/isdn/gigaset/ev-layer.c
+++ linux-ec2-2.6.32/drivers/isdn/gigaset/ev-layer.c
@@ -1243,14 +1243,10 @@
 		 * note that bcs may be NULL if no B channel is free
 		 */
 		at_state2->ConState = 700;
-		kfree(at_state2->str_var[STR_NMBR]);
-		at_state2->str_var[STR_NMBR] = NULL;
-		kfree(at_state2->str_var[STR_ZCPN]);
-		at_state2->str_var[STR_ZCPN] = NULL;
-		kfree(at_state2->str_var[STR_ZBC]);
-		at_state2->str_var[STR_ZBC] = NULL;
-		kfree(at_state2->str_var[STR_ZHLC]);
-		at_state2->str_var[STR_ZHLC] = NULL;
+		for (i = 0; i < STR_NUM; ++i) {
+			kfree(at_state2->str_var[i]);
+			at_state2->str_var[i] = NULL;
+		}
 		at_state2->int_var[VAR_ZCTP] = -1;
 
 		spin_lock_irqsave(&cs->lock, flags);
--- linux-ec2-2.6.32.orig/drivers/isdn/hisax/config.c
+++ linux-ec2-2.6.32/drivers/isdn/hisax/config.c
@@ -800,6 +800,16 @@
 	ll_unload(csta);
 }
 
+static irqreturn_t card_irq(int intno, void *dev_id)
+{
+	struct IsdnCardState *cs = dev_id;
+	irqreturn_t ret = cs->irq_func(intno, cs);
+
+	if (ret == IRQ_HANDLED)
+		cs->irq_cnt++;
+	return ret;
+}
+
 static int init_card(struct IsdnCardState *cs)
 {
 	int 	irq_cnt, cnt = 3, ret;
@@ -808,10 +818,10 @@
 		ret = cs->cardmsg(cs, CARD_INIT, NULL);
 		return(ret);
 	}
-	irq_cnt = kstat_irqs(cs->irq);
+	irq_cnt = cs->irq_cnt = 0;
 	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
 	       cs->irq, irq_cnt);
-	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+	if (request_irq(cs->irq, card_irq, cs->irq_flags, "HiSax", cs)) {
 		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
 		       cs->irq);
 		return 1;
@@ -821,8 +831,8 @@
 		/* Timeout 10ms */
 		msleep(10);
 		printk(KERN_INFO "%s: IRQ %d count %d\n",
-		       CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
-		if (kstat_irqs(cs->irq) == irq_cnt) {
+		       CardType[cs->typ], cs->irq, cs->irq_cnt);
+		if (cs->irq_cnt == irq_cnt) {
 			printk(KERN_WARNING
 			       "%s: IRQ(%d) getting no interrupts during init %d\n",
 			       CardType[cs->typ], cs->irq, 4 - cnt);
--- linux-ec2-2.6.32.orig/drivers/isdn/hisax/hisax.h
+++ linux-ec2-2.6.32/drivers/isdn/hisax/hisax.h
@@ -959,6 +959,7 @@
 	u_long		event;
 	struct work_struct tqueue;
 	struct timer_list dbusytimer;
+	unsigned int	irq_cnt;
 #ifdef ERROR_STATISTIC
 	int		err_crc;
 	int		err_tx;
--- linux-ec2-2.6.32.orig/drivers/isdn/i4l/isdn_tty.c
+++ linux-ec2-2.6.32/drivers/isdn/i4l/isdn_tty.c
@@ -2635,12 +2635,6 @@
 		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
 			return;
 		}
-#ifdef CONFIG_ISDN_AUDIO
-		if ( !info->vonline )
-			tty_ldisc_flush(info->tty);
-#else
-		tty_ldisc_flush(info->tty);
-#endif
 		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
 		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
 		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
--- linux-ec2-2.6.32.orig/drivers/isdn/sc/ioctl.c
+++ linux-ec2-2.6.32/drivers/isdn/sc/ioctl.c
@@ -174,7 +174,7 @@
 		pr_debug("%s: SCIOGETSPID: ioctl received\n",
 				sc_adapter[card]->devicename);
 
-		spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
+		spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
 		if (!spid) {
 			kfree(rcvmsg);
 			return -ENOMEM;
@@ -194,7 +194,7 @@
 			kfree(rcvmsg);
 			return status;
 		}
-		strcpy(spid, rcvmsg->msg_data.byte_array);
+		strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE);
 
 		/*
 		 * Package the switch type and send to user space
@@ -272,12 +272,12 @@
 			return status;
 		}
 
-		dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL);
+		dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL);
 		if (!dn) {
 			kfree(rcvmsg);
 			return -ENOMEM;
 		}
-		strcpy(dn, rcvmsg->msg_data.byte_array);
+		strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE);
 		kfree(rcvmsg);
 
 		/*
@@ -348,7 +348,7 @@
 		pr_debug("%s: SCIOSTAT: ioctl received\n",
 				sc_adapter[card]->devicename);
 
-		bi = kmalloc (sizeof(boardInfo), GFP_KERNEL);
+		bi = kzalloc(sizeof(boardInfo), GFP_KERNEL);
 		if (!bi) {
 			kfree(rcvmsg);
 			return -ENOMEM;
--- linux-ec2-2.6.32.orig/drivers/connector/connector.c
+++ linux-ec2-2.6.32/drivers/connector/connector.c
@@ -36,17 +36,6 @@
 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
 
-static u32 cn_idx = CN_IDX_CONNECTOR;
-static u32 cn_val = CN_VAL_CONNECTOR;
-
-module_param(cn_idx, uint, 0);
-module_param(cn_val, uint, 0);
-MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
-MODULE_PARM_DESC(cn_val, "Connector's main device val.");
-
-static DEFINE_MUTEX(notify_lock);
-static LIST_HEAD(notify_list);
-
 static struct cn_dev cdev;
 
 static int cn_already_initialized;
@@ -210,54 +199,6 @@
 }
 
 /*
- * Notification routing.
- *
- * Gets id and checks if there are notification request for it's idx
- * and val.  If there are such requests notify the listeners with the
- * given notify event.
- *
- */
-static void cn_notify(struct cb_id *id, u32 notify_event)
-{
-	struct cn_ctl_entry *ent;
-
-	mutex_lock(&notify_lock);
-	list_for_each_entry(ent, &notify_list, notify_entry) {
-		int i;
-		struct cn_notify_req *req;
-		struct cn_ctl_msg *ctl = ent->msg;
-		int idx_found, val_found;
-
-		idx_found = val_found = 0;
-
-		req = (struct cn_notify_req *)ctl->data;
-		for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
-			if (id->idx >= req->first &&
-					id->idx < req->first + req->range) {
-				idx_found = 1;
-				break;
-			}
-		}
-
-		for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
-			if (id->val >= req->first &&
-					id->val < req->first + req->range) {
-				val_found = 1;
-				break;
-			}
-		}
-
-		if (idx_found && val_found) {
-			struct cn_msg m = { .ack = notify_event, };
-
-			memcpy(&m.id, id, sizeof(m.id));
-			cn_netlink_send(&m, ctl->group, GFP_KERNEL);
-		}
-	}
-	mutex_unlock(&notify_lock);
-}
-
-/*
  * Callback add routing - adds callback with given ID and name.
  * If there is registered callback with the same ID it will not be added.
  *
@@ -276,8 +217,6 @@
 	if (err)
 		return err;
 
-	cn_notify(id, 0);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(cn_add_callback);
@@ -295,111 +234,9 @@
 	struct cn_dev *dev = &cdev;
 
 	cn_queue_del_callback(dev->cbdev, id);
-	cn_notify(id, 1);
 }
 EXPORT_SYMBOL_GPL(cn_del_callback);
 
-/*
- * Checks two connector's control messages to be the same.
- * Returns 1 if they are the same or if the first one is corrupted.
- */
-static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
-{
-	int i;
-	struct cn_notify_req *req1, *req2;
-
-	if (m1->idx_notify_num != m2->idx_notify_num)
-		return 0;
-
-	if (m1->val_notify_num != m2->val_notify_num)
-		return 0;
-
-	if (m1->len != m2->len)
-		return 0;
-
-	if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
-	    m1->len)
-		return 1;
-
-	req1 = (struct cn_notify_req *)m1->data;
-	req2 = (struct cn_notify_req *)m2->data;
-
-	for (i = 0; i < m1->idx_notify_num; ++i) {
-		if (req1->first != req2->first || req1->range != req2->range)
-			return 0;
-		req1++;
-		req2++;
-	}
-
-	for (i = 0; i < m1->val_notify_num; ++i) {
-		if (req1->first != req2->first || req1->range != req2->range)
-			return 0;
-		req1++;
-		req2++;
-	}
-
-	return 1;
-}
-
-/*
- * Main connector device's callback.
- *
- * Used for notification of a request's processing.
- */
-static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-	struct cn_ctl_msg *ctl;
-	struct cn_ctl_entry *ent;
-	u32 size;
-
-	if (msg->len < sizeof(*ctl))
-		return;
-
-	ctl = (struct cn_ctl_msg *)msg->data;
-
-	size = (sizeof(*ctl) + ((ctl->idx_notify_num +
-				 ctl->val_notify_num) *
-				sizeof(struct cn_notify_req)));
-
-	if (msg->len != size)
-		return;
-
-	if (ctl->len + sizeof(*ctl) != msg->len)
-		return;
-
-	/*
-	 * Remove notification.
-	 */
-	if (ctl->group == 0) {
-		struct cn_ctl_entry *n;
-
-		mutex_lock(&notify_lock);
-		list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
-			if (cn_ctl_msg_equals(ent->msg, ctl)) {
-				list_del(&ent->notify_entry);
-				kfree(ent);
-			}
-		}
-		mutex_unlock(&notify_lock);
-
-		return;
-	}
-
-	size += sizeof(*ent);
-
-	ent = kzalloc(size, GFP_KERNEL);
-	if (!ent)
-		return;
-
-	ent->msg = (struct cn_ctl_msg *)(ent + 1);
-
-	memcpy(ent->msg, ctl, size - sizeof(*ent));
-
-	mutex_lock(&notify_lock);
-	list_add(&ent->notify_entry, &notify_list);
-	mutex_unlock(&notify_lock);
-}
-
 static int cn_proc_show(struct seq_file *m, void *v)
 {
 	struct cn_queue_dev *dev = cdev.cbdev;
@@ -437,11 +274,8 @@
 static int __devinit cn_init(void)
 {
 	struct cn_dev *dev = &cdev;
-	int err;
 
 	dev->input = cn_rx_skb;
-	dev->id.idx = cn_idx;
-	dev->id.val = cn_val;
 
 	dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
 					 CN_NETLINK_USERS + 0xf,
@@ -457,14 +291,6 @@
 
 	cn_already_initialized = 1;
 
-	err = cn_add_callback(&dev->id, "connector", &cn_callback);
-	if (err) {
-		cn_already_initialized = 0;
-		cn_queue_free_dev(dev->cbdev);
-		netlink_kernel_release(dev->nls);
-		return -EINVAL;
-	}
-
 	proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
 
 	return 0;
@@ -478,7 +304,6 @@
 
 	proc_net_remove(&init_net, "connector");
 
-	cn_del_callback(&dev->id);
 	cn_queue_free_dev(dev->cbdev);
 	netlink_kernel_release(dev->nls);
 }
--- linux-ec2-2.6.32.orig/drivers/cpufreq/Kconfig
+++ linux-ec2-2.6.32/drivers/cpufreq/Kconfig
@@ -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 
--- linux-ec2-2.6.32.orig/drivers/cpufreq/cpufreq.c
+++ linux-ec2-2.6.32/drivers/cpufreq/cpufreq.c
@@ -1741,17 +1741,8 @@
 			dprintk("governor switch\n");
 
 			/* end old governor */
-			if (data->governor) {
-				/*
-				 * Need to release the rwsem around governor
-				 * stop due to lock dependency between
-				 * cancel_delayed_work_sync and the read lock
-				 * taken in the delayed work handler.
-				 */
-				unlock_policy_rwsem_write(data->cpu);
+			if (data->governor)
 				__cpufreq_governor(data, CPUFREQ_GOV_STOP);
-				lock_policy_rwsem_write(data->cpu);
-			}
 
 			/* start new governor */
 			data->governor = policy->governor;
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_int.h
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_int.h
@@ -108,6 +108,16 @@
 			    d_data); \
 } while(0)
 
+#define DBF_EVENT_DEVID(d_level, d_cdev, d_str, d_data...)	\
+do { \
+	struct ccw_dev_id __dev_id;			\
+	ccw_device_get_id(d_cdev, &__dev_id);		\
+	debug_sprintf_event(dasd_debug_area,		\
+			    d_level,					\
+			    "0.%x.%04x " d_str "\n",			\
+			    __dev_id.ssid, __dev_id.devno, d_data);	\
+} while (0)
+
 #define DBF_EXC(d_level, d_str, d_data...)\
 do { \
 	debug_sprintf_exception(dasd_debug_area, \
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_eckd.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_eckd.c
@@ -63,7 +63,7 @@
 static struct ccw_device_id dasd_eckd_ids[] = {
 	{ CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3390, 0), .driver_info = 0x1},
 	{ CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3390, 0), .driver_info = 0x2},
-	{ CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3390, 0), .driver_info = 0x3},
+	{ CCW_DEVICE_DEVTYPE (0x3880, 0, 0x3380, 0), .driver_info = 0x3},
 	{ CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), .driver_info = 0x4},
 	{ CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), .driver_info = 0x5},
 	{ CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), .driver_info = 0x6},
@@ -88,9 +88,9 @@
 	/* set ECKD specific ccw-device options */
 	ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE);
 	if (ret) {
-		DBF_EVENT(DBF_WARNING,
-		       "dasd_eckd_probe: could not set ccw-device options "
-		       "for %s\n", dev_name(&cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s",
+				"dasd_eckd_probe: could not set "
+				"ccw-device options");
 		return ret;
 	}
 	ret = dasd_generic_probe(cdev, &dasd_eckd_discipline);
@@ -885,16 +885,15 @@
 			rc = dasd_eckd_read_conf_lpm(device, &conf_data,
 						     &conf_len, lpm);
 			if (rc && rc != -EOPNOTSUPP) {	/* -EOPNOTSUPP is ok */
-				DBF_EVENT(DBF_WARNING,
+				DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
 					  "Read configuration data returned "
-					  "error %d for device: %s", rc,
-					  dev_name(&device->cdev->dev));
+					  "error %d", rc);
 				return rc;
 			}
 			if (conf_data == NULL) {
-				DBF_EVENT(DBF_WARNING, "No configuration "
-					  "data retrieved for device: %s",
-					  dev_name(&device->cdev->dev));
+				DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+						"No configuration data "
+						"retrieved");
 				continue;	/* no error */
 			}
 			/* save first valid configuration data */
@@ -941,9 +940,8 @@
 				    sizeof(struct dasd_rssd_features)),
 				   device);
 	if (IS_ERR(cqr)) {
-		DBF_EVENT(DBF_WARNING, "Could not allocate initialization "
-			  "request for device: %s",
-			  dev_name(&device->cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", "Could not "
+				"allocate initialization request");
 		return PTR_ERR(cqr);
 	}
 	cqr->startdev = device;
@@ -1071,10 +1069,8 @@
 	/* may be requested feature is not available on server,
 	 * therefore just report error and go ahead */
 	private = (struct dasd_eckd_private *) device->private;
-	DBF_EVENT(DBF_WARNING, "PSF-SSC on storage subsystem %s.%s.%04x "
-		  "returned rc=%d for device: %s",
-		  private->uid.vendor, private->uid.serial,
-		  private->uid.ssid, rc, dev_name(&device->cdev->dev));
+	DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
+			"returned rc=%d", private->uid.ssid, rc);
 	/* RE-Read Configuration Data */
 	return dasd_eckd_read_conf(device);
 }
@@ -1123,9 +1119,9 @@
 	if (private->uid.type == UA_BASE_DEVICE) {
 		block = dasd_alloc_block();
 		if (IS_ERR(block)) {
-			DBF_EVENT(DBF_WARNING, "could not allocate dasd "
-				  "block structure for device: %s",
-				  dev_name(&device->cdev->dev));
+			DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
+					"could not allocate dasd "
+					"block structure");
 			rc = PTR_ERR(block);
 			goto out_err1;
 		}
@@ -1153,9 +1149,8 @@
 	rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
 					 &private->rdc_data, 64);
 	if (rc) {
-		DBF_EVENT(DBF_WARNING,
-			  "Read device characteristics failed, rc=%d for "
-			  "device: %s", rc, dev_name(&device->cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+				"Read device characteristic failed, rc=%d", rc);
 		goto out_err3;
 	}
 	/* find the vaild cylinder size */
@@ -2980,7 +2975,7 @@
 	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
 		       " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n",
 		       req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
-		       scsw_cc(&irb->scsw), req->intrc);
+		       scsw_cc(&irb->scsw), req ? req->intrc : 0);
 	len += sprintf(page + len, KERN_ERR PRINTK_HEADER
 		       " device %s: Failing CCW: %p\n",
 		       dev_name(&device->cdev->dev),
@@ -3253,9 +3248,8 @@
 	rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC,
 					 &temp_rdc_data, 64);
 	if (rc) {
-		DBF_EVENT(DBF_WARNING,
-			  "Read device characteristics failed, rc=%d for "
-			  "device: %s", rc, dev_name(&device->cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
+				"Read device characteristic failed, rc=%d", rc);
 		goto out_err;
 	}
 	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_ioctl.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_ioctl.c
@@ -260,7 +260,7 @@
 	struct ccw_dev_id dev_id;
 
 	base = block->base;
-	if (!base->discipline->fill_info)
+	if (!base->discipline || !base->discipline->fill_info)
 		return -EINVAL;
 
 	dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
@@ -303,10 +303,7 @@
 	dasd_info->features |=
 		((base->features & DASD_FEATURE_READONLY) != 0);
 
-	if (base->discipline)
-		memcpy(dasd_info->type, base->discipline->name, 4);
-	else
-		memcpy(dasd_info->type, "none", 4);
+	memcpy(dasd_info->type, base->discipline->name, 4);
 
 	if (block->request_queue->request_fn) {
 		struct list_head *l;
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_diag.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_diag.c
@@ -145,6 +145,15 @@
 
 	mdsk_term_io(device);
 	rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
+	if (rc == 4) {
+		if (!(device->features & DASD_FEATURE_READONLY)) {
+			dev_warn(&device->cdev->dev,
+				 "The access mode of a DIAG device changed"
+				 " to read-only");
+			device->features |= DASD_FEATURE_READONLY;
+		}
+		rc = 0;
+	}
 	if (rc)
 		dev_warn(&device->cdev->dev, "DIAG ERP failed with "
 			    "rc=%d\n", rc);
@@ -433,16 +442,20 @@
 	for (sb = 512; sb < bsize; sb = sb << 1)
 		block->s2b_shift++;
 	rc = mdsk_init_io(device, block->bp_block, 0, NULL);
-	if (rc) {
+	if (rc && (rc != 4)) {
 		dev_warn(&device->cdev->dev, "DIAG initialization "
 			"failed with rc=%d\n", rc);
 		rc = -EIO;
 	} else {
+		if (rc == 4)
+			device->features |= DASD_FEATURE_READONLY;
 		dev_info(&device->cdev->dev,
-			 "New DASD with %ld byte/block, total size %ld KB\n",
+			 "New DASD with %ld byte/block, total size %ld KB%s\n",
 			 (unsigned long) block->bp_block,
 			 (unsigned long) (block->blocks <<
-					  block->s2b_shift) >> 1);
+					  block->s2b_shift) >> 1,
+			 (rc == 4) ? ", read-only device" : "");
+		rc = 0;
 	}
 out_label:
 	free_page((long) label);
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_proc.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_proc.c
@@ -71,7 +71,7 @@
 	/* Print device number. */
 	seq_printf(m, "%s", dev_name(&device->cdev->dev));
 	/* Print discipline string. */
-	if (device != NULL && device->discipline != NULL)
+	if (device->discipline != NULL)
 		seq_printf(m, "(%s)", device->discipline->name);
 	else
 		seq_printf(m, "(none)");
@@ -91,10 +91,7 @@
 	substr = (device->features & DASD_FEATURE_READONLY) ? "(ro)" : " ";
 	seq_printf(m, "%4s: ", substr);
 	/* Print device status information. */
-	switch ((device != NULL) ? device->state : -1) {
-	case -1:
-		seq_printf(m, "unknown");
-		break;
+	switch (device->state) {
 	case DASD_STATE_NEW:
 		seq_printf(m, "new");
 		break;
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd_fba.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd_fba.c
@@ -141,9 +141,8 @@
 	}
 	block = dasd_alloc_block();
 	if (IS_ERR(block)) {
-		DBF_EVENT(DBF_WARNING, "could not allocate dasd block "
-			  "structure for device: %s",
-			  dev_name(&device->cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s", "could not allocate "
+				"dasd block structure");
 		device->private = NULL;
 		kfree(private);
 		return PTR_ERR(block);
@@ -155,9 +154,8 @@
 	rc = dasd_generic_read_dev_chars(device, DASD_FBA_MAGIC,
 					 &private->rdc_data, 32);
 	if (rc) {
-		DBF_EVENT(DBF_WARNING, "Read device characteristics returned "
-			  "error %d for device: %s",
-			  rc, dev_name(&device->cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, cdev, "Read device "
+				"characteristics returned error %d", rc);
 		device->block = NULL;
 		dasd_free_block(block);
 		device->private = NULL;
--- linux-ec2-2.6.32.orig/drivers/s390/block/dasd.c
+++ linux-ec2-2.6.32/drivers/s390/block/dasd.c
@@ -994,10 +994,9 @@
 		return;
 	cqr = (struct dasd_ccw_req *) intparm;
 	if (cqr->status != DASD_CQR_IN_IO) {
-		DBF_EVENT(DBF_DEBUG,
-			"invalid status in handle_killed_request: "
-			"bus_id %s, status %02x",
-			dev_name(&cdev->dev), cqr->status);
+		DBF_EVENT_DEVID(DBF_DEBUG, cdev,
+				"invalid status in handle_killed_request: "
+				"%02x", cqr->status);
 		return;
 	}
 
@@ -1005,8 +1004,8 @@
 	if (device == NULL ||
 	    device != dasd_device_from_cdev_locked(cdev) ||
 	    strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-		DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: "
-			      "bus_id %s", dev_name(&cdev->dev));
+		DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
+				"invalid device in request");
 		return;
 	}
 
@@ -1045,12 +1044,13 @@
 		case -EIO:
 			break;
 		case -ETIMEDOUT:
-			DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n",
-			       __func__, dev_name(&cdev->dev));
+			DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
+					"request timed out\n", __func__);
 			break;
 		default:
-			DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n",
-			       __func__, dev_name(&cdev->dev), PTR_ERR(irb));
+			DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
+					"unknown error %ld\n", __func__,
+					PTR_ERR(irb));
 		}
 		dasd_handle_killed_request(cdev, intparm);
 		return;
@@ -1078,8 +1078,8 @@
 	device = (struct dasd_device *) cqr->startdev;
 	if (!device ||
 	    strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) {
-		DBF_DEV_EVENT(DBF_DEBUG, device, "invalid device in request: "
-			      "bus_id %s", dev_name(&cdev->dev));
+		DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
+				"invalid device in request");
 		return;
 	}
 
@@ -2217,9 +2217,9 @@
 	}
 	ret = dasd_add_sysfs_files(cdev);
 	if (ret) {
-		DBF_EVENT(DBF_WARNING,
-		       "dasd_generic_probe: could not add sysfs entries "
-		       "for %s\n", dev_name(&cdev->dev));
+		DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s",
+				"dasd_generic_probe: could not add "
+				"sysfs entries");
 		return ret;
 	}
 	cdev->handler = &dasd_int_handler;
--- linux-ec2-2.6.32.orig/drivers/s390/char/keyboard.c
+++ linux-ec2-2.6.32/drivers/s390/char/keyboard.c
@@ -462,7 +462,8 @@
 	  unsigned int cmd, unsigned long arg)
 {
 	void __user *argp;
-	int ct, perm;
+	unsigned int ct;
+	int perm;
 
 	argp = (void __user *)arg;
 
--- linux-ec2-2.6.32.orig/drivers/s390/crypto/zcrypt_pcicc.c
+++ linux-ec2-2.6.32/drivers/s390/crypto/zcrypt_pcicc.c
@@ -373,6 +373,8 @@
 			zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
 			return -EAGAIN;
 		}
+		if (service_rc == 8 && service_rs == 72)
+			return -EINVAL;
 		zdev->online = 0;
 		return -EAGAIN;	/* repeat the request on a different device. */
 	}
--- linux-ec2-2.6.32.orig/drivers/s390/crypto/zcrypt_pcixcc.c
+++ linux-ec2-2.6.32/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -462,6 +462,8 @@
 		}
 		if (service_rc == 12 && service_rs == 769)
 			return -EINVAL;
+		if (service_rc == 8 && service_rs == 72)
+			return -EINVAL;
 		zdev->online = 0;
 		return -EAGAIN;	/* repeat the request on a different device. */
 	}
--- linux-ec2-2.6.32.orig/drivers/s390/net/netiucv.c
+++ linux-ec2-2.6.32/drivers/s390/net/netiucv.c
@@ -741,13 +741,13 @@
 	if (single_flag) {
 		if ((skb = skb_dequeue(&conn->commit_queue))) {
 			atomic_dec(&skb->users);
-			dev_kfree_skb_any(skb);
 			if (privptr) {
 				privptr->stats.tx_packets++;
 				privptr->stats.tx_bytes +=
 					(skb->len - NETIUCV_HDRLEN
-					 	  - NETIUCV_HDRLEN);
+						  - NETIUCV_HDRLEN);
 			}
+			dev_kfree_skb_any(skb);
 		}
 	}
 	conn->tx_buff->data = conn->tx_buff->head;
--- linux-ec2-2.6.32.orig/drivers/s390/cio/device.c
+++ linux-ec2-2.6.32/drivers/s390/cio/device.c
@@ -1292,7 +1292,7 @@
 	sch->private = kzalloc(sizeof(struct io_subchannel_private),
 			       GFP_KERNEL | GFP_DMA);
 	if (!sch->private)
-		goto out_err;
+		goto out_schedule;
 	/*
 	 * First check if a fitting device may be found amongst the
 	 * disconnected devices or in the orphanage.
@@ -1317,7 +1317,7 @@
 	}
 	cdev = io_subchannel_create_ccwdev(sch);
 	if (IS_ERR(cdev))
-		goto out_err;
+		goto out_schedule;
 	rc = io_subchannel_recog(cdev, sch);
 	if (rc) {
 		spin_lock_irqsave(sch->lock, flags);
@@ -1325,9 +1325,7 @@
 		spin_unlock_irqrestore(sch->lock, flags);
 	}
 	return 0;
-out_err:
-	kfree(sch->private);
-	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
+
 out_schedule:
 	io_subchannel_schedule_removal(sch);
 	return 0;
@@ -1341,13 +1339,14 @@
 
 	cdev = sch_get_cdev(sch);
 	if (!cdev)
-		return 0;
+		goto out_free;
 	/* Set ccw device to not operational and drop reference. */
 	spin_lock_irqsave(cdev->ccwlock, flags);
 	sch_set_cdev(sch, NULL);
 	cdev->private->state = DEV_STATE_NOT_OPER;
 	spin_unlock_irqrestore(cdev->ccwlock, flags);
 	ccw_device_unregister(cdev);
+out_free:
 	kfree(sch->private);
 	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/s390/cio/cio.c
+++ linux-ec2-2.6.32/drivers/s390/cio/cio.c
@@ -618,6 +618,7 @@
 	old_regs = set_irq_regs(regs);
 	s390_idle_check();
 	irq_enter();
+	__get_cpu_var(s390_idle).nohz_delay = 1;
 	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
 		/* Serve timer interrupts first. */
 		clock_comparator_work();
--- linux-ec2-2.6.32.orig/drivers/s390/cio/device_fsm.c
+++ linux-ec2-2.6.32/drivers/s390/cio/device_fsm.c
@@ -1080,14 +1080,14 @@
 		ccw_device_start_id(cdev, 0);
 }
 
-static void
-ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event)
+static void ccw_device_disabled_irq(struct ccw_device *cdev,
+				    enum dev_event dev_event)
 {
 	struct subchannel *sch;
 
 	sch = to_subchannel(cdev->dev.parent);
 	/*
-	 * An interrupt in state offline means a previous disable was not
+	 * An interrupt in a disabled state means a previous disable was not
 	 * successful - should not happen, but we try to disable again.
 	 */
 	cio_disable_subchannel(sch);
@@ -1150,25 +1150,12 @@
 }
 
 /*
- * Bug operation action. 
- */
-static void
-ccw_device_bug(struct ccw_device *cdev, enum dev_event dev_event)
-{
-	CIO_MSG_EVENT(0, "Internal state [%i][%i] not handled for device "
-		      "0.%x.%04x\n", cdev->private->state, dev_event,
-		      cdev->private->dev_id.ssid,
-		      cdev->private->dev_id.devno);
-	BUG();
-}
-
-/*
  * device statemachine
  */
 fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
 	[DEV_STATE_NOT_OPER] = {
 		[DEV_EVENT_NOTOPER]	= ccw_device_nop,
-		[DEV_EVENT_INTERRUPT]	= ccw_device_bug,
+		[DEV_EVENT_INTERRUPT]	= ccw_device_disabled_irq,
 		[DEV_EVENT_TIMEOUT]	= ccw_device_nop,
 		[DEV_EVENT_VERIFY]	= ccw_device_nop,
 	},
@@ -1186,7 +1173,7 @@
 	},
 	[DEV_STATE_OFFLINE] = {
 		[DEV_EVENT_NOTOPER]	= ccw_device_generic_notoper,
-		[DEV_EVENT_INTERRUPT]	= ccw_device_offline_irq,
+		[DEV_EVENT_INTERRUPT]	= ccw_device_disabled_irq,
 		[DEV_EVENT_TIMEOUT]	= ccw_device_nop,
 		[DEV_EVENT_VERIFY]	= ccw_device_offline_verify,
 	},
@@ -1243,7 +1230,7 @@
 	[DEV_STATE_DISCONNECTED] = {
 		[DEV_EVENT_NOTOPER]	= ccw_device_nop,
 		[DEV_EVENT_INTERRUPT]	= ccw_device_start_id,
-		[DEV_EVENT_TIMEOUT]	= ccw_device_bug,
+		[DEV_EVENT_TIMEOUT]	= ccw_device_nop,
 		[DEV_EVENT_VERIFY]	= ccw_device_start_id,
 	},
 	[DEV_STATE_DISCONNECTED_SENSE_ID] = {
--- linux-ec2-2.6.32.orig/drivers/pnp/isapnp/core.c
+++ linux-ec2-2.6.32/drivers/pnp/isapnp/core.c
@@ -42,6 +42,7 @@
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include <linux/mutex.h>
+#include <linux/async.h>
 #include <asm/io.h>
 
 #include "../base.h"
@@ -1002,7 +1003,7 @@
 	.disable = isapnp_disable_resources,
 };
 
-static int __init isapnp_init(void)
+static int __init real_isapnp_init(void)
 {
 	int cards;
 	struct pnp_card *card;
@@ -1096,6 +1097,15 @@
 	return 0;
 }
 
+static void __init async_isapnp_init(void *unused, async_cookie_t cookie)
+{
+	(void)real_isapnp_init();
+}
+
+static int __init isapnp_init(void)
+{
+       async_schedule(async_isapnp_init, NULL);
+}
 device_initcall(isapnp_init);
 
 /* format is: noisapnp */
--- linux-ec2-2.6.32.orig/drivers/net/via-velocity.c
+++ linux-ec2-2.6.32/drivers/net/via-velocity.c
@@ -2186,8 +2186,6 @@
 	/* Ensure chip is running */
 	pci_set_power_state(vptr->pdev, PCI_D0);
 
-	velocity_give_many_rx_descs(vptr);
-
 	velocity_init_registers(vptr, VELOCITY_INIT_COLD);
 
 	ret = request_irq(vptr->pdev->irq, &velocity_intr, IRQF_SHARED,
@@ -2199,6 +2197,8 @@
 		goto out;
 	}
 
+	velocity_give_many_rx_descs(vptr);
+
 	mac_enable_int(vptr->mac_regs);
 	netif_start_queue(dev);
 	vptr->flags |= VELOCITY_FLAGS_OPENED;
@@ -2287,10 +2287,10 @@
 
 		dev->mtu = new_mtu;
 
-		velocity_give_many_rx_descs(vptr);
-
 		velocity_init_registers(vptr, VELOCITY_INIT_COLD);
 
+		velocity_give_many_rx_descs(vptr);
+
 		mac_enable_int(vptr->mac_regs);
 		netif_start_queue(dev);
 
--- linux-ec2-2.6.32.orig/drivers/net/dm9000.c
+++ linux-ec2-2.6.32/drivers/net/dm9000.c
@@ -471,17 +471,13 @@
 	return dm->rx_csum;
 }
 
-static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
+static int dm9000_set_rx_csum_unlocked(struct net_device *dev, uint32_t data)
 {
 	board_info_t *dm = to_dm9000_board(dev);
-	unsigned long flags;
 
 	if (dm->can_csum) {
 		dm->rx_csum = data;
-
-		spin_lock_irqsave(&dm->lock, flags);
 		iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);
-		spin_unlock_irqrestore(&dm->lock, flags);
 
 		return 0;
 	}
@@ -489,6 +485,19 @@
 	return -EOPNOTSUPP;
 }
 
+static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)
+{
+	board_info_t *dm = to_dm9000_board(dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&dm->lock, flags);
+	ret = dm9000_set_rx_csum_unlocked(dev, data);
+	spin_unlock_irqrestore(&dm->lock, flags);
+
+	return ret;
+}
+
 static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data)
 {
 	board_info_t *dm = to_dm9000_board(dev);
@@ -667,7 +676,7 @@
  *  Set DM9000 multicast address
  */
 static void
-dm9000_hash_table(struct net_device *dev)
+dm9000_hash_table_unlocked(struct net_device *dev)
 {
 	board_info_t *db = netdev_priv(dev);
 	struct dev_mc_list *mcptr = dev->mc_list;
@@ -676,12 +685,9 @@
 	u32 hash_val;
 	u16 hash_table[4];
 	u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
-	unsigned long flags;
 
 	dm9000_dbg(db, 1, "entering %s\n", __func__);
 
-	spin_lock_irqsave(&db->lock, flags);
-
 	for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
 		iow(db, oft, dev->dev_addr[i]);
 
@@ -711,6 +717,16 @@
 	}
 
 	iow(db, DM9000_RCR, rcr);
+}
+
+static void
+dm9000_hash_table(struct net_device *dev)
+{
+	board_info_t *db = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&db->lock, flags);
+	dm9000_hash_table_unlocked(dev);
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
@@ -729,7 +745,7 @@
 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
 
 	/* Checksum mode */
-	dm9000_set_rx_csum(dev, db->rx_csum);
+	dm9000_set_rx_csum_unlocked(dev, db->rx_csum);
 
 	/* GPIO0 on pre-activate PHY */
 	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
@@ -749,7 +765,7 @@
 	iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
 
 	/* Set address filter table */
-	dm9000_hash_table(dev);
+	dm9000_hash_table_unlocked(dev);
 
 	imr = IMR_PAR | IMR_PTM | IMR_PRM;
 	if (db->type != TYPE_DM9000E)
--- linux-ec2-2.6.32.orig/drivers/net/tun.c
+++ linux-ec2-2.6.32/drivers/net/tun.c
@@ -721,8 +721,18 @@
 				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
 			else if (sinfo->gso_type & SKB_GSO_UDP)
 				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
-			else
-				BUG();
+			else {
+				printk(KERN_ERR "tun: unexpected GSO type: "
+				       "0x%x, gso_size %d, hdr_len %d\n",
+				       sinfo->gso_type, gso.gso_size,
+				       gso.hdr_len);
+				print_hex_dump(KERN_ERR, "tun: ",
+					       DUMP_PREFIX_NONE,
+					       16, 1, skb->head,
+					       min((int)gso.hdr_len, 64), true);
+				WARN_ON_ONCE(1);
+				return -EINVAL;
+			}
 			if (sinfo->gso_type & SKB_GSO_TCP_ECN)
 				gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
 		} else
@@ -1006,7 +1016,8 @@
 		if (err < 0)
 			goto err_free_sk;
 
-		if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
+		if (!net_eq(dev_net(tun->dev), &init_net) ||
+		    device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			printk(KERN_ERR "Failed to create tun sysfs files\n");
--- linux-ec2-2.6.32.orig/drivers/net/niu.c
+++ linux-ec2-2.6.32/drivers/net/niu.c
@@ -7315,33 +7315,28 @@
 	struct niu_parent *parent = np->parent;
 	struct niu_tcam_entry *tp;
 	int i, idx, cnt;
-	u16 n_entries;
 	unsigned long flags;
-
+	int ret = 0;
 
 	/* put the tcam size here */
 	nfc->data = tcam_get_size(np);
 
 	niu_lock_parent(np, flags);
-	n_entries = nfc->rule_cnt;
 	for (cnt = 0, i = 0; i < nfc->data; i++) {
 		idx = tcam_get_index(np, i);
 		tp = &parent->tcam[idx];
 		if (!tp->valid)
 			continue;
+		if (cnt == nfc->rule_cnt) {
+			ret = -EMSGSIZE;
+			break;
+		}
 		rule_locs[cnt] = i;
 		cnt++;
 	}
 	niu_unlock_parent(np, flags);
 
-	if (n_entries != cnt) {
-		/* print warning, this should not happen */
-		pr_info(PFX "niu%d: %s In niu_get_ethtool_tcam_all, "
-			"n_entries[%d] != cnt[%d]!!!\n\n",
-			np->parent->index, np->dev->name, n_entries, cnt);
-	}
-
-	return 0;
+	return ret;
 }
 
 static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
--- linux-ec2-2.6.32.orig/drivers/net/ipg.c
+++ linux-ec2-2.6.32/drivers/net/ipg.c
@@ -88,7 +88,6 @@
 	"Sundance Technology ST2021 based NIC",
 	"Tamarack Microelectronics TC9020/9021 based NIC",
 	"Tamarack Microelectronics TC9020/9021 based NIC",
-	"D-Link NIC",
 	"D-Link NIC IP1000A"
 };
 
@@ -97,8 +96,7 @@
 	{ PCI_VDEVICE(SUNDANCE,	0x2021), 1 },
 	{ PCI_VDEVICE(SUNDANCE,	0x1021), 2 },
 	{ PCI_VDEVICE(DLINK,	0x9021), 3 },
-	{ PCI_VDEVICE(DLINK,	0x4000), 4 },
-	{ PCI_VDEVICE(DLINK,	0x4020), 5 },
+	{ PCI_VDEVICE(DLINK,	0x4020), 4 },
 	{ 0, }
 };
 
--- linux-ec2-2.6.32.orig/drivers/net/tg3.h
+++ linux-ec2-2.6.32/drivers/net/tg3.h
@@ -2759,6 +2759,9 @@
 #define TG3_FLG3_TOGGLE_10_100_L1PLLPD	0x00008000
 #define TG3_FLG3_PHY_IS_FET		0x00010000
 #define TG3_FLG3_ENABLE_RSS		0x00020000
+#define TG3_FLG3_4G_DMA_BNDRY_BUG      0x00080000
+#define TG3_FLG3_40BIT_DMA_LIMIT_BUG   0x00100000
+#define TG3_FLG3_SHORT_DMA_BUG  0x00200000
 
 	struct timer_list		timer;
 	u16				timer_counter;
--- linux-ec2-2.6.32.orig/drivers/net/smsc911x.c
+++ linux-ec2-2.6.32/drivers/net/smsc911x.c
@@ -85,8 +85,7 @@
 	 */
 	spinlock_t mac_lock;
 
-	/* spinlock to ensure 16-bit accesses are serialised.
-	 * unused with a 32-bit bus */
+	/* spinlock to ensure register accesses are serialised */
 	spinlock_t dev_lock;
 
 	struct phy_device *phy_dev;
@@ -119,37 +118,33 @@
 	unsigned int hashlo;
 };
 
-/* The 16-bit access functions are significantly slower, due to the locking
- * necessary.  If your bus hardware can be configured to do this for you
- * (in response to a single 32-bit operation from software), you should use
- * the 32-bit access functions instead. */
-
-static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
+static inline u32 __smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
 {
 	if (pdata->config.flags & SMSC911X_USE_32BIT)
 		return readl(pdata->ioaddr + reg);
 
-	if (pdata->config.flags & SMSC911X_USE_16BIT) {
-		u32 data;
-		unsigned long flags;
-
-		/* these two 16-bit reads must be performed consecutively, so
-		 * must not be interrupted by our own ISR (which would start
-		 * another read operation) */
-		spin_lock_irqsave(&pdata->dev_lock, flags);
-		data = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
+	if (pdata->config.flags & SMSC911X_USE_16BIT)
+		return ((readw(pdata->ioaddr + reg) & 0xFFFF) |
 			((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
-		spin_unlock_irqrestore(&pdata->dev_lock, flags);
-
-		return data;
-	}
 
 	BUG();
 	return 0;
 }
 
-static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
-				      u32 val)
+static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
+{
+	u32 data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+	data = __smsc911x_reg_read(pdata, reg);
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
+
+	return data;
+}
+
+static inline void __smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
+					u32 val)
 {
 	if (pdata->config.flags & SMSC911X_USE_32BIT) {
 		writel(val, pdata->ioaddr + reg);
@@ -157,44 +152,54 @@
 	}
 
 	if (pdata->config.flags & SMSC911X_USE_16BIT) {
-		unsigned long flags;
-
-		/* these two 16-bit writes must be performed consecutively, so
-		 * must not be interrupted by our own ISR (which would start
-		 * another read operation) */
-		spin_lock_irqsave(&pdata->dev_lock, flags);
 		writew(val & 0xFFFF, pdata->ioaddr + reg);
 		writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
-		spin_unlock_irqrestore(&pdata->dev_lock, flags);
 		return;
 	}
 
 	BUG();
 }
 
+static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
+				      u32 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+	__smsc911x_reg_write(pdata, reg, val);
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
+}
+
 /* Writes a packet to the TX_DATA_FIFO */
 static inline void
 smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
 		      unsigned int wordcount)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+
 	if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
 		while (wordcount--)
-			smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++));
-		return;
+			__smsc911x_reg_write(pdata, TX_DATA_FIFO,
+					     swab32(*buf++));
+		goto out;
 	}
 
 	if (pdata->config.flags & SMSC911X_USE_32BIT) {
 		writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
-		return;
+		goto out;
 	}
 
 	if (pdata->config.flags & SMSC911X_USE_16BIT) {
 		while (wordcount--)
-			smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
-		return;
+			__smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
+		goto out;
 	}
 
 	BUG();
+out:
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
 }
 
 /* Reads a packet out of the RX_DATA_FIFO */
@@ -202,24 +207,31 @@
 smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
 		     unsigned int wordcount)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->dev_lock, flags);
+
 	if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
 		while (wordcount--)
-			*buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO));
-		return;
+			*buf++ = swab32(__smsc911x_reg_read(pdata,
+							    RX_DATA_FIFO));
+		goto out;
 	}
 
 	if (pdata->config.flags & SMSC911X_USE_32BIT) {
 		readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
-		return;
+		goto out;
 	}
 
 	if (pdata->config.flags & SMSC911X_USE_16BIT) {
 		while (wordcount--)
-			*buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
-		return;
+			*buf++ = __smsc911x_reg_read(pdata, RX_DATA_FIFO);
+		goto out;
 	}
 
 	BUG();
+out:
+	spin_unlock_irqrestore(&pdata->dev_lock, flags);
 }
 
 /* waits for MAC not busy, with timeout.  Only called by smsc911x_mac_read
--- linux-ec2-2.6.32.orig/drivers/net/sky2.c
+++ linux-ec2-2.6.32/drivers/net/sky2.c
@@ -139,6 +139,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */
 	{ 0 }
 };
 
@@ -602,6 +603,16 @@
 		/* apply workaround for integrated resistors calibration */
 		gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
 		gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
+	} else if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
+		/* apply fixes in PHY AFE */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0x00ff);
+
+		/* apply RDAC termination workaround */
+		gm_phy_write(hw, port, 24, 0x2800);
+		gm_phy_write(hw, port, 23, 0x2001);
+
+		/* set page register back to 0 */
+		gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
 	} else if (hw->chip_id != CHIP_ID_YUKON_EX &&
 		   hw->chip_id < CHIP_ID_YUKON_SUPR) {
 		/* no effect on Yukon-XL */
@@ -704,11 +715,24 @@
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+	struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	u16 reg;
+
+	reg = gma_read16(hw, port, GM_GP_CTRL);
+	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+	gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
 /* Force a renegotiation */
 static void sky2_phy_reinit(struct sky2_port *sky2)
 {
 	spin_lock_bh(&sky2->phy_lock);
 	sky2_phy_init(sky2->hw, sky2->port);
+	sky2_enable_rx_tx(sky2);
 	spin_unlock_bh(&sky2->phy_lock);
 }
 
@@ -1008,11 +1032,8 @@
 static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2, u16 *slot)
 {
 	struct sky2_tx_le *le = sky2->tx_le + *slot;
-	struct tx_ring_info *re = sky2->tx_ring + *slot;
 
 	*slot = RING_NEXT(*slot, sky2->tx_ring_size);
-	re->flags = 0;
-	re->skb = NULL;
 	le->ctrl = 0;
 	return le;
 }
@@ -1580,8 +1601,7 @@
 	return count;
 }
 
-static void sky2_tx_unmap(struct pci_dev *pdev,
-			  const struct tx_ring_info *re)
+static void sky2_tx_unmap(struct pci_dev *pdev, struct tx_ring_info *re)
 {
 	if (re->flags & TX_MAP_SINGLE)
 		pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr),
@@ -1591,6 +1611,7 @@
 		pci_unmap_page(pdev, pci_unmap_addr(re, mapaddr),
 			       pci_unmap_len(re, maplen),
 			       PCI_DMA_TODEVICE);
+	re->flags = 0;
 }
 
 /*
@@ -1797,6 +1818,7 @@
 			dev->stats.tx_packets++;
 			dev->stats.tx_bytes += skb->len;
 
+			re->skb = NULL;
 			dev_kfree_skb_any(skb);
 
 			sky2->tx_next = RING_NEXT(idx, sky2->tx_ring_size);
@@ -1806,7 +1828,8 @@
 	sky2->tx_cons = idx;
 	smp_mb();
 
-	if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
+	/* Wake unless it's detached, and called e.g. from sky2_down() */
+	if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev))
 		netif_wake_queue(dev);
 }
 
@@ -1930,7 +1953,6 @@
 {
 	struct sky2_hw *hw = sky2->hw;
 	unsigned port = sky2->port;
-	u16 reg;
 	static const char *fc_name[] = {
 		[FC_NONE]	= "none",
 		[FC_TX]		= "tx",
@@ -1938,10 +1960,7 @@
 		[FC_BOTH]	= "both",
 	};
 
-	/* enable Rx/Tx */
-	reg = gma_read16(hw, port, GM_GP_CTRL);
-	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
-	gma_write16(hw, port, GM_GP_CTRL, reg);
+	sky2_enable_rx_tx(sky2);
 
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
@@ -2096,6 +2115,27 @@
 	spin_unlock(&sky2->phy_lock);
 }
 
+/* Special quick link interrupt (Yukon-2 Optima only) */
+static void sky2_qlink_intr(struct sky2_hw *hw)
+{
+	struct sky2_port *sky2 = netdev_priv(hw->dev[0]);
+	u32 imask;
+	u16 phy;
+
+	/* disable irq */
+	imask = sky2_read32(hw, B0_IMSK);
+	imask &= ~Y2_IS_PHY_QLNK;
+	sky2_write32(hw, B0_IMSK, imask);
+
+	/* reset PHY Link Detect */
+	phy = sky2_pci_read16(hw, PSM_CONFIG_REG4);
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+	sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1);
+	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+	sky2_link_up(sky2);
+}
+
 /* Transmit timeout is only called if we are running, carrier is up
  * and tx queue is full (stopped).
  */
@@ -2766,6 +2806,9 @@
 	if (status & Y2_IS_IRQ_PHY2)
 		sky2_phy_intr(hw, 1);
 
+	if (status & Y2_IS_PHY_QLNK)
+		sky2_qlink_intr(hw);
+
 	while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) {
 		work_done += sky2_status_intr(hw, work_limit - work_done, idx);
 
@@ -2815,6 +2858,7 @@
 	case CHIP_ID_YUKON_EX:
 	case CHIP_ID_YUKON_SUPR:
 	case CHIP_ID_YUKON_UL_2:
+	case CHIP_ID_YUKON_OPT:
 		return 125;
 
 	case CHIP_ID_YUKON_FE:
@@ -2908,6 +2952,12 @@
 			| SKY2_HW_ADV_POWER_CTL;
 		break;
 
+	case CHIP_ID_YUKON_OPT:
+		hw->flags = SKY2_HW_GIGABIT
+			| SKY2_HW_NEW_LE
+			| SKY2_HW_ADV_POWER_CTL;
+		break;
+
 	default:
 		dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
 			hw->chip_id);
@@ -2988,6 +3038,48 @@
 				     | GMC_BYP_RETR_ON);
 	}
 
+	if (hw->chip_id == CHIP_ID_YUKON_OPT) {
+		u16 reg;
+		u32 msk;
+
+		if (hw->chip_rev == 0) {
+			/* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
+			sky2_write32(hw, Y2_PEX_PHY_DATA, (0x80UL << 16) | (1 << 7));
+
+			/* set PHY Link Detect Timer to 1.1 second (11x 100ms) */
+			reg = 10;
+		} else {
+			/* set PHY Link Detect Timer to 0.4 second (4x 100ms) */
+			reg = 3;
+		}
+
+		reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
+
+		/* reset PHY Link Detect */
+		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+		sky2_pci_write16(hw, PSM_CONFIG_REG4,
+				 reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
+		sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
+
+
+		/* enable PHY Quick Link */
+		msk = sky2_read32(hw, B0_IMSK);
+		msk |= Y2_IS_PHY_QLNK;
+		sky2_write32(hw, B0_IMSK, msk);
+
+		/* check if PSMv2 was running before */
+		reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
+		if (reg & PCI_EXP_LNKCTL_ASPMC) {
+			int cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+			/* restore the PCIe Link Control register */
+			sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
+		}
+		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+		/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
+		sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
+	}
+
 	/* Clear I2C IRQ noise */
 	sky2_write32(hw, B2_I2C_IRQ, 1);
 
@@ -4406,9 +4498,11 @@
 		"FE+",		/* 0xb8 */
 		"Supreme",	/* 0xb9 */
 		"UL 2",		/* 0xba */
+		"Unknown",	/* 0xbb */
+		"Optima",	/* 0xbc */
 	};
 
-	if (chipid >= CHIP_ID_YUKON_XL && chipid < CHIP_ID_YUKON_UL_2)
+	if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OPT)
 		strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
 	else
 		snprintf(buf, sz, "(chip %#x)", chipid);
--- linux-ec2-2.6.32.orig/drivers/net/Makefile
+++ linux-ec2-2.6.32/drivers/net/Makefile
@@ -138,7 +138,7 @@
 obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
 
@@ -162,7 +162,7 @@
 obj-$(CONFIG_SLIP) += slip.o
 obj-$(CONFIG_SLHC) += slhc.o
 
-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETFRONT) += xen-netfront.o
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
@@ -208,7 +208,7 @@
 obj-$(CONFIG_LP486E) += lp486e.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o
 obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
 obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
 obj-$(CONFIG_EQUALIZER) += eql.o
@@ -220,7 +220,7 @@
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
--- linux-ec2-2.6.32.orig/drivers/net/3c503.c
+++ linux-ec2-2.6.32/drivers/net/3c503.c
@@ -380,6 +380,12 @@
     return retval;
 }
 
+static irqreturn_t el2_probe_interrupt(int irq, void *seen)
+{
+	*(bool *)seen = true;
+	return IRQ_HANDLED;
+}
+
 static int
 el2_open(struct net_device *dev)
 {
@@ -391,22 +397,35 @@
 
 	outb(EGACFR_NORM, E33G_GACFR);	/* Enable RAM and interrupts. */
 	do {
-	    retval = request_irq(*irqp, NULL, 0, "bogus", dev);
-	    if (retval >= 0) {
+		bool seen;
+
+		retval = request_irq(*irqp, el2_probe_interrupt, 0,
+				     dev->name, &seen);
+		if (retval == -EBUSY)
+			continue;
+		if (retval < 0)
+			goto err_disable;
+
 		/* Twinkle the interrupt, and check if it's seen. */
-		unsigned long cookie = probe_irq_on();
+		seen = false;
+		smp_wmb();
 		outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
 		outb_p(0x00, E33G_IDCFR);
-		if (*irqp == probe_irq_off(cookie)	/* It's a good IRQ line! */
-		    && ((retval = request_irq(dev->irq = *irqp,
-		    eip_interrupt, 0, dev->name, dev)) == 0))
-		    break;
-	    } else {
-		    if (retval != -EBUSY)
-			    return retval;
-	    }
+		msleep(1);
+		free_irq(*irqp, el2_probe_interrupt);
+		if (!seen)
+			continue;
+
+		retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
+				     dev->name, dev);
+		if (retval == -EBUSY)
+			continue;
+		if (retval < 0)
+			goto err_disable;
 	} while (*++irqp);
+
 	if (*irqp == 0) {
+	err_disable:
 	    outb(EGACFR_IRQOFF, E33G_GACFR);	/* disable interrupts. */
 	    return -EAGAIN;
 	}
--- linux-ec2-2.6.32.orig/drivers/net/bnx2.c
+++ linux-ec2-2.6.32/drivers/net/bnx2.c
@@ -247,6 +247,9 @@
 
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
+static void bnx2_init_napi(struct bnx2 *bp);
+static void bnx2_del_napi(struct bnx2 *bp);
+
 static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
 {
 	u32 diff;
@@ -4752,8 +4755,12 @@
 		rc = bnx2_alloc_bad_rbuf(bp);
 	}
 
-	if (bp->flags & BNX2_FLAG_USING_MSIX)
+	if (bp->flags & BNX2_FLAG_USING_MSIX) {
 		bnx2_setup_msix_tbl(bp);
+		/* Prevent MSIX table reads and write from timing out */
+		REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
+			BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
+	}
 
 	return rc;
 }
@@ -6169,6 +6176,7 @@
 	bnx2_disable_int(bp);
 
 	bnx2_setup_int_mode(bp, disable_msi);
+	bnx2_init_napi(bp);
 	bnx2_napi_enable(bp);
 	rc = bnx2_alloc_mem(bp);
 	if (rc)
@@ -6230,6 +6238,7 @@
 	bnx2_free_skbs(bp);
 	bnx2_free_irq(bp);
 	bnx2_free_mem(bp);
+	bnx2_del_napi(bp);
 	return rc;
 }
 
@@ -6437,6 +6446,7 @@
 	bnx2_free_irq(bp);
 	bnx2_free_skbs(bp);
 	bnx2_free_mem(bp);
+	bnx2_del_napi(bp);
 	bp->link_up = 0;
 	netif_carrier_off(bp->dev);
 	bnx2_set_power_state(bp, PCI_D3hot);
@@ -8012,12 +8022,21 @@
 	return str;
 }
 
-static void __devinit
+static void
+bnx2_del_napi(struct bnx2 *bp)
+{
+	int i;
+
+	for (i = 0; i < bp->irq_nvecs; i++)
+		netif_napi_del(&bp->bnx2_napi[i].napi);
+}
+
+static void
 bnx2_init_napi(struct bnx2 *bp)
 {
 	int i;
 
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
+	for (i = 0; i < bp->irq_nvecs; i++) {
 		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
 		int (*poll)(struct napi_struct *, int);
 
@@ -8086,7 +8105,6 @@
 	dev->ethtool_ops = &bnx2_ethtool_ops;
 
 	bp = netdev_priv(dev);
-	bnx2_init_napi(bp);
 
 	pci_set_drvdata(pdev, dev);
 
--- linux-ec2-2.6.32.orig/drivers/net/tehuti.c
+++ linux-ec2-2.6.32/drivers/net/tehuti.c
@@ -324,7 +324,7 @@
 	ENTER;
 	master = READ_REG(priv, regINIT_SEMAPHORE);
 	if (!READ_REG(priv, regINIT_STATUS) && master) {
-		rc = request_firmware(&fw, "tehuti/firmware.bin", &priv->pdev->dev);
+		rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev);
 		if (rc)
 			goto out;
 		bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size);
@@ -2524,4 +2524,4 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(BDX_DRV_DESC);
-MODULE_FIRMWARE("tehuti/firmware.bin");
+MODULE_FIRMWARE("tehuti/bdx.bin");
--- linux-ec2-2.6.32.orig/drivers/net/gianfar.c
+++ linux-ec2-2.6.32/drivers/net/gianfar.c
@@ -1621,7 +1621,7 @@
 		if (skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size &&
 				skb_recycle_check(skb, priv->rx_buffer_size +
 					RXBUF_ALIGNMENT))
-			__skb_queue_head(&priv->rx_recycle, skb);
+			skb_queue_head(&priv->rx_recycle, skb);
 		else
 			dev_kfree_skb_any(skb);
 
@@ -1703,7 +1703,7 @@
 	struct gfar_private *priv = netdev_priv(dev);
 	struct sk_buff *skb = NULL;
 
-	skb = __skb_dequeue(&priv->rx_recycle);
+	skb = skb_dequeue(&priv->rx_recycle);
 	if (!skb)
 		skb = netdev_alloc_skb(dev,
 				priv->rx_buffer_size + RXBUF_ALIGNMENT);
@@ -1862,7 +1862,7 @@
 				 * recycle list.
 				 */
 				skb->data = skb->head + NET_SKB_PAD;
-				__skb_queue_head(&priv->rx_recycle, skb);
+				skb_queue_head(&priv->rx_recycle, skb);
 			}
 		} else {
 			/* Increment the number of packets */
--- linux-ec2-2.6.32.orig/drivers/net/forcedeth.c
+++ linux-ec2-2.6.32/drivers/net/forcedeth.c
@@ -5900,7 +5900,7 @@
 	/* Limit the number of tx's outstanding for hw bug */
 	if (id->driver_data & DEV_NEED_TX_LIMIT) {
 		np->tx_limit = 1;
-		if ((id->driver_data & DEV_NEED_TX_LIMIT2) &&
+		if (((id->driver_data & DEV_NEED_TX_LIMIT2) == DEV_NEED_TX_LIMIT2) &&
 		    pci_dev->revision >= 0xA2)
 			np->tx_limit = 0;
 	}
--- linux-ec2-2.6.32.orig/drivers/net/Kconfig
+++ linux-ec2-2.6.32/drivers/net/Kconfig
@@ -2784,9 +2784,9 @@
 
 source "drivers/s390/net/Kconfig"
 
-config XEN_NETDEV_FRONTEND
+config XEN_NETFRONT
 	tristate "Xen network device frontend driver"
-	depends on XEN
+	depends on PARAVIRT_XEN
 	default y
 	help
 	  The network device frontend driver allows the kernel to
@@ -3235,7 +3235,7 @@
 
 config VMXNET3
        tristate "VMware VMXNET3 ethernet driver"
-       depends on PCI && X86 && INET
+       depends on PCI && X86 && !XEN && INET
        help
          This driver supports VMware's vmxnet3 virtual ethernet NIC.
          To compile this driver as a module, choose M here: the
--- linux-ec2-2.6.32.orig/drivers/net/tg3.c
+++ linux-ec2-2.6.32/drivers/net/tg3.c
@@ -4995,7 +4995,7 @@
 	struct tg3 *tp = netdev_priv(dev);
 
 	for (i = 0; i < tp->irq_cnt; i++)
-		tg3_interrupt(tp->napi[i].irq_vec, dev);
+		tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]);
 }
 #endif
 
@@ -5392,7 +5392,7 @@
 	mss = 0;
 	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
 		struct iphdr *iph;
-		int tcp_opt_len, ip_tcp_len, hdr_len;
+		u32 tcp_opt_len, ip_tcp_len, hdr_len;
 
 		if (skb_header_cloned(skb) &&
 		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -5423,8 +5423,10 @@
 								 IPPROTO_TCP,
 								 0);
 
-		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) ||
-		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
+		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)
+			mss |= hdr_len << 9;
+		else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) ||
+			GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 			if (tcp_opt_len || iph->ihl > 5) {
 				int tsflags;
 
@@ -5459,6 +5461,9 @@
 
 	would_hit_hwbug = 0;
 
+	if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) && len <= 8)
+		would_hit_hwbug = 1;
+
 	if (tp->tg3_flags3 & TG3_FLG3_5701_DMA_BUG)
 		would_hit_hwbug = 1;
 	else if (tg3_4g_overflow_test(mapping, len))
@@ -5482,6 +5487,10 @@
 
 			tnapi->tx_buffers[entry].skb = NULL;
 
+			if ((tp->tg3_flags3 & TG3_FLG3_SHORT_DMA_BUG) &&
+				len <= 8)
+					would_hit_hwbug = 1;
+
 			if (tg3_4g_overflow_test(mapping, len))
 				would_hit_hwbug = 1;
 
@@ -8159,6 +8168,7 @@
 	pci_disable_msi(tp->pdev);
 
 	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
+	tp->napi[0].irq_vec = tp->pdev->irq;
 
 	err = tg3_request_irq(tp, 0);
 	if (err)
@@ -12608,6 +12618,9 @@
 		}
 	}
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+		tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG;
+
 	tp->irq_max = 1;
 
 #ifdef TG3_NAPI
@@ -13975,8 +13988,7 @@
 		goto err_out_iounmap;
 	}
 
-	if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+	if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
 		dev->netdev_ops = &tg3_netdev_ops;
 	else
 		dev->netdev_ops = &tg3_netdev_ops_dma_bug;
--- linux-ec2-2.6.32.orig/drivers/net/slip.c
+++ linux-ec2-2.6.32/drivers/net/slip.c
@@ -850,7 +850,9 @@
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
 	tty->receive_room = 65536;	/* We don't flow control */
-	return sl->dev->base_addr;
+
+	/* TTY layer expects 0 on success */
+	return 0;
 
 err_free_bufs:
 	sl_free_bufs(sl);
--- linux-ec2-2.6.32.orig/drivers/net/r8169.c
+++ linux-ec2-2.6.32/drivers/net/r8169.c
@@ -23,6 +23,7 @@
 #include <linux/tcp.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
+#include <linux/pci-aspm.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -186,7 +187,12 @@
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
-static int rx_copybreak = 200;
+/*
+ * we set our copybreak very high so that we don't have
+ * to allocate 16k frames all the time (see note in
+ * rtl8169_open()
+ */
+static int rx_copybreak = 16383;
 static int use_dac;
 static struct {
 	u32 msg_enable;
@@ -552,6 +558,11 @@
 			break;
 		udelay(25);
 	}
+	/*
+	 * According to hardware specs a 20us delay is required after write
+	 * complete indication, but before sending next command.
+	 */
+	udelay(20);
 }
 
 static int mdio_read(void __iomem *ioaddr, int reg_addr)
@@ -571,6 +582,12 @@
 		}
 		udelay(25);
 	}
+	/*
+	 * According to hardware specs a 20us delay is required after read
+	 * complete indication, but before sending next command.
+	 */
+	udelay(20);
+
 	return value;
 }
 
@@ -2827,8 +2844,13 @@
 	spin_lock_irq(&tp->lock);
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
-	RTL_W32(MAC0, low);
+
 	RTL_W32(MAC4, high);
+	RTL_R32(MAC4);
+
+	RTL_W32(MAC0, low);
+	RTL_R32(MAC0);
+
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 
 	spin_unlock_irq(&tp->lock);
@@ -3009,6 +3031,11 @@
 	mii->reg_num_mask = 0x1f;
 	mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
 
+	/* disable ASPM completely as that cause random device stop working
+	 * problems as well as full system hangs for some PCIe devices users */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				     PCIE_LINK_STATE_CLKPM);
+
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
 	rc = pci_enable_device(pdev);
 	if (rc < 0) {
@@ -3169,6 +3196,13 @@
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 #endif
 
+	/* Ubuntu temporary workaround for bug #76489, disable
+	 * NETIF_F_TSO by default for RTL8111/8168B chipsets.
+	 * People can re-enable if required */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_11
+				|| tp->mac_version == RTL_GIGA_MAC_VER_12)
+		dev->features &= ~NETIF_F_TSO;
+
 	tp->intr_mask = 0xffff;
 	tp->align = cfg->align;
 	tp->hw_start = cfg->hw_start;
@@ -3245,9 +3279,13 @@
 }
 
 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
-				  struct net_device *dev)
+				  unsigned int mtu)
 {
-	unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+	unsigned int max_frame = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+
+	if (max_frame != 16383)
+		printk(KERN_WARNING PFX "WARNING! Changing of MTU on this "
+			"NIC may lead to frame reception errors!\n");
 
 	tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
 }
@@ -3259,7 +3297,17 @@
 	int retval = -ENOMEM;
 
 
-	rtl8169_set_rxbufsize(tp, dev);
+	/*
+	 * Note that we use a magic value here, its wierd I know
+	 * its done because, some subset of rtl8169 hardware suffers from
+	 * a problem in which frames received that are longer than
+	 * the size set in RxMaxSize register return garbage sizes
+	 * when received.  To avoid this we need to turn off filtering,
+	 * which is done by setting a value of 16383 in the RxMaxSize register
+	 * and allocating 16k frames to handle the largest possible rx value
+	 * thats what the magic math below does.
+	 */
+	rtl8169_set_rxbufsize(tp, 16383 - VLAN_ETH_HLEN - ETH_FCS_LEN);
 
 	/*
 	 * Rx and Tx desscriptors needs 256 bytes alignment.
@@ -3700,7 +3748,8 @@
 	RTL_W16(IntrMitigate, 0x5151);
 
 	/* Work around for RxFIFO overflow. */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+	if (tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_22) {
 		tp->intr_event |= RxFIFOOver | PCSTimeout;
 		tp->intr_event &= ~RxOverflow;
 	}
@@ -3912,7 +3961,7 @@
 
 	rtl8169_down(dev);
 
-	rtl8169_set_rxbufsize(tp, dev);
+	rtl8169_set_rxbufsize(tp, dev->mtu);
 
 	ret = rtl8169_init_ring(dev);
 	if (ret < 0)
@@ -3964,7 +4013,7 @@
 static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
 					    struct net_device *dev,
 					    struct RxDesc *desc, int rx_buf_sz,
-					    unsigned int align)
+					    unsigned int align, gfp_t gfp)
 {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
@@ -3972,7 +4021,7 @@
 
 	pad = align ? align : NET_IP_ALIGN;
 
-	skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
+	skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp);
 	if (!skb)
 		goto err_out;
 
@@ -4003,7 +4052,7 @@
 }
 
 static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
-			   u32 start, u32 end)
+			   u32 start, u32 end, gfp_t gfp)
 {
 	u32 cur;
 
@@ -4018,7 +4067,7 @@
 
 		skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
 					   tp->RxDescArray + i,
-					   tp->rx_buf_sz, tp->align);
+					   tp->rx_buf_sz, tp->align, gfp);
 		if (!skb)
 			break;
 
@@ -4046,7 +4095,7 @@
 	memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
 	memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
 
-	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+	if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC)
 		goto err_out;
 
 	rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
@@ -4297,7 +4346,7 @@
 
 	tp->cur_tx += frags + 1;
 
-	smp_wmb();
+	wmb();
 
 	RTL_W8(TxPoll, NPQ);	/* set polling bit */
 
@@ -4549,7 +4598,7 @@
 	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
-	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC);
 	if (!delta && count && netif_msg_intr(tp))
 		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
 	tp->dirty_rx += delta;
@@ -4592,7 +4641,8 @@
 
 		/* Work around for rx fifo overflow */
 		if (unlikely(status & RxFIFOOver) &&
-		(tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+		    (tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+		     tp->mac_version == RTL_GIGA_MAC_VER_22)) {
 			netif_stop_queue(dev);
 			rtl8169_tx_timeout(dev);
 			break;
@@ -4657,7 +4707,7 @@
 		 * until it does.
 		 */
 		tp->intr_mask = 0xffff;
-		smp_wmb();
+		wmb();
 		RTL_W16(IntrMask, tp->intr_event);
 	}
 
@@ -4795,8 +4845,8 @@
 		mc_filter[1] = swab32(data);
 	}
 
-	RTL_W32(MAR0 + 0, mc_filter[0]);
 	RTL_W32(MAR0 + 4, mc_filter[1]);
+	RTL_W32(MAR0 + 0, mc_filter[0]);
 
 	RTL_W32(RxConfig, tmp);
 
--- linux-ec2-2.6.32.orig/drivers/net/r6040.c
+++ linux-ec2-2.6.32/drivers/net/r6040.c
@@ -135,7 +135,7 @@
 #define RX_DESC_SIZE	(RX_DCNT * sizeof(struct r6040_descriptor))
 #define TX_DESC_SIZE	(TX_DCNT * sizeof(struct r6040_descriptor))
 #define MBCR_DEFAULT	0x012A	/* MAC Bus Control Register */
-#define MCAST_MAX	4	/* Max number multicast addresses to filter */
+#define MCAST_MAX	3	/* Max number multicast addresses to filter */
 
 /* Descriptor status */
 #define DSC_OWNER_MAC	0x8000	/* MAC is the owner of this descriptor */
@@ -985,9 +985,6 @@
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
 		}
-		/* Write the index of the hash table */
-		for (i = 0; i < 4; i++)
-			iowrite16(hash_table[i] << 14, ioaddr + MCR1);
 		/* Fill the MAC hash tables with their values */
 		iowrite16(hash_table[0], ioaddr + MAR0);
 		iowrite16(hash_table[1], ioaddr + MAR1);
@@ -995,6 +992,7 @@
 		iowrite16(hash_table[3], ioaddr + MAR3);
 	}
 	/* Multicast Address 1~4 case */
+	dmi = dev->mc_list;
 	for (i = 0, dmi; (i < dev->mc_count) && (i < MCAST_MAX); i++) {
 		adrp = (u16 *)dmi->dmi_addr;
 		iowrite16(adrp[0], ioaddr + MID_1L + 8*i);
@@ -1003,9 +1001,9 @@
 		dmi = dmi->next;
 	}
 	for (i = dev->mc_count; i < MCAST_MAX; i++) {
-		iowrite16(0xffff, ioaddr + MID_0L + 8*i);
-		iowrite16(0xffff, ioaddr + MID_0M + 8*i);
-		iowrite16(0xffff, ioaddr + MID_0H + 8*i);
+		iowrite16(0xffff, ioaddr + MID_1L + 8*i);
+		iowrite16(0xffff, ioaddr + MID_1M + 8*i);
+		iowrite16(0xffff, ioaddr + MID_1H + 8*i);
 	}
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/zorro8390.c
+++ linux-ec2-2.6.32/drivers/net/zorro8390.c
@@ -125,7 +125,7 @@
 
     board = z->resource.start;
     ioaddr = board+cards[i].offset;
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
     if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
@@ -145,15 +145,15 @@
 static const struct net_device_ops zorro8390_netdev_ops = {
 	.ndo_open		= zorro8390_open,
 	.ndo_stop		= zorro8390_close,
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
--- linux-ec2-2.6.32.orig/drivers/net/ne-h8300.c
+++ linux-ec2-2.6.32/drivers/net/ne-h8300.c
@@ -167,7 +167,7 @@
 #ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
-	struct net_device *dev = alloc_ei_netdev();
+	struct net_device *dev = ____alloc_ei_netdev(0);
 	int err;
 
 	if (!dev)
@@ -197,15 +197,15 @@
 	.ndo_open		= ne_open,
 	.ndo_stop		= ne_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -638,7 +638,7 @@
 	int err;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = alloc_ei_netdev();
+		struct net_device *dev = ____alloc_ei_netdev(0);
 		if (!dev)
 			break;
 		if (io[this_dev]) {
--- linux-ec2-2.6.32.orig/drivers/net/bcm63xx_enet.c
+++ linux-ec2-2.6.32/drivers/net/bcm63xx_enet.c
@@ -1248,9 +1248,15 @@
 	drvinfo->n_stats = BCM_ENET_STATS_LEN;
 }
 
-static int bcm_enet_get_stats_count(struct net_device *netdev)
+static int bcm_enet_get_sset_count(struct net_device *netdev,
+					int string_set)
 {
-	return BCM_ENET_STATS_LEN;
+	switch (string_set) {
+	case ETH_SS_STATS:
+		return BCM_ENET_STATS_LEN;
+	default:
+		return -EINVAL;
+	}
 }
 
 static void bcm_enet_get_strings(struct net_device *netdev,
@@ -1476,7 +1482,7 @@
 
 static struct ethtool_ops bcm_enet_ethtool_ops = {
 	.get_strings		= bcm_enet_get_strings,
-	.get_stats_count	= bcm_enet_get_stats_count,
+	.get_sset_count		= bcm_enet_get_sset_count,
 	.get_ethtool_stats      = bcm_enet_get_ethtool_stats,
 	.get_settings		= bcm_enet_get_settings,
 	.set_settings		= bcm_enet_set_settings,
--- linux-ec2-2.6.32.orig/drivers/net/eql.c
+++ linux-ec2-2.6.32/drivers/net/eql.c
@@ -554,6 +554,8 @@
 	equalizer_t *eql;
 	master_config_t mc;
 
+	memset(&mc, 0, sizeof(master_config_t));
+
 	if (eql_is_master(dev)) {
 		eql = netdev_priv(dev);
 		mc.max_slaves = eql->max_slaves;
--- linux-ec2-2.6.32.orig/drivers/net/spider_net.c
+++ linux-ec2-2.6.32/drivers/net/spider_net.c
@@ -57,6 +57,7 @@
 MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(VERSION);
+MODULE_FIRMWARE(SPIDER_NET_FIRMWARE_NAME);
 
 static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
 static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
--- linux-ec2-2.6.32.orig/drivers/net/ks8851_mll.c
+++ linux-ec2-2.6.32/drivers/net/ks8851_mll.c
@@ -854,8 +854,8 @@
 
 static irqreturn_t ks_irq(int irq, void *pw)
 {
-	struct ks_net *ks = pw;
-	struct net_device *netdev = ks->netdev;
+	struct net_device *netdev = pw;
+	struct ks_net *ks = netdev_priv(netdev);
 	u16 status;
 
 	/*this should be the first in IRQ handler */
--- linux-ec2-2.6.32.orig/drivers/net/sky2.h
+++ linux-ec2-2.6.32/drivers/net/sky2.h
@@ -16,6 +16,13 @@
 	PCI_DEV_REG5    = 0x88,
 	PCI_CFG_REG_0	= 0x90,
 	PCI_CFG_REG_1	= 0x94,
+
+	PSM_CONFIG_REG0  = 0x98,
+	PSM_CONFIG_REG1	 = 0x9C,
+	PSM_CONFIG_REG2  = 0x160,
+	PSM_CONFIG_REG3  = 0x164,
+	PSM_CONFIG_REG4  = 0x168,
+
 };
 
 /* Yukon-2 */
@@ -48,6 +55,37 @@
 	PCI_USEDATA64	= 1<<0,		/* Use 64Bit Data bus ext */
 };
 
+/*	PCI_OUR_REG_3		32 bit	Our Register 3 (Yukon-ECU only) */
+enum pci_dev_reg_3 {
+	P_CLK_ASF_REGS_DIS	= 1<<18,/* Disable Clock ASF (Yukon-Ext.) */
+	P_CLK_COR_REGS_D0_DIS	= 1<<17,/* Disable Clock Core Regs D0 */
+	P_CLK_MACSEC_DIS	= 1<<17,/* Disable Clock MACSec (Yukon-Ext.) */
+	P_CLK_PCI_REGS_D0_DIS	= 1<<16,/* Disable Clock PCI  Regs D0 */
+	P_CLK_COR_YTB_ARB_DIS	= 1<<15,/* Disable Clock YTB  Arbiter */
+	P_CLK_MAC_LNK1_D3_DIS	= 1<<14,/* Disable Clock MAC  Link1 D3 */
+	P_CLK_COR_LNK1_D0_DIS	= 1<<13,/* Disable Clock Core Link1 D0 */
+	P_CLK_MAC_LNK1_D0_DIS	= 1<<12,/* Disable Clock MAC  Link1 D0 */
+	P_CLK_COR_LNK1_D3_DIS	= 1<<11,/* Disable Clock Core Link1 D3 */
+	P_CLK_PCI_MST_ARB_DIS	= 1<<10,/* Disable Clock PCI  Master Arb. */
+	P_CLK_COR_REGS_D3_DIS	= 1<<9,	/* Disable Clock Core Regs D3 */
+	P_CLK_PCI_REGS_D3_DIS	= 1<<8,	/* Disable Clock PCI  Regs D3 */
+	P_CLK_REF_LNK1_GM_DIS	= 1<<7,	/* Disable Clock Ref. Link1 GMAC */
+	P_CLK_COR_LNK1_GM_DIS	= 1<<6,	/* Disable Clock Core Link1 GMAC */
+	P_CLK_PCI_COMMON_DIS	= 1<<5,	/* Disable Clock PCI  Common */
+	P_CLK_COR_COMMON_DIS	= 1<<4,	/* Disable Clock Core Common */
+	P_CLK_PCI_LNK1_BMU_DIS	= 1<<3,	/* Disable Clock PCI  Link1 BMU */
+	P_CLK_COR_LNK1_BMU_DIS	= 1<<2,	/* Disable Clock Core Link1 BMU */
+	P_CLK_PCI_LNK1_BIU_DIS	= 1<<1,	/* Disable Clock PCI  Link1 BIU */
+	P_CLK_COR_LNK1_BIU_DIS	= 1<<0,	/* Disable Clock Core Link1 BIU */
+	PCIE_OUR3_WOL_D3_COLD_SET = P_CLK_ASF_REGS_DIS |
+				    P_CLK_COR_REGS_D0_DIS |
+				    P_CLK_COR_LNK1_D0_DIS |
+				    P_CLK_MAC_LNK1_D0_DIS |
+				    P_CLK_PCI_MST_ARB_DIS |
+				    P_CLK_COR_COMMON_DIS |
+				    P_CLK_COR_LNK1_BMU_DIS,
+};
+
 /*	PCI_OUR_REG_4		32 bit	Our Register 4 (Yukon-ECU only) */
 enum pci_dev_reg_4 {
 				/* (Link Training & Status State Machine) */
@@ -114,7 +152,7 @@
 				     P_GAT_PCIE_RX_EL_IDLE,
 };
 
-#/*	PCI_CFG_REG_1			32 bit	Config Register 1 (Yukon-Ext only) */
+/*	PCI_CFG_REG_1			32 bit	Config Register 1 (Yukon-Ext only) */
 enum pci_cfg_reg1 {
 	P_CF1_DIS_REL_EVT_RST	= 1<<24, /* Dis. Rel. Event during PCIE reset */
 										/* Bit 23..21: Release Clock on Event */
@@ -145,6 +183,72 @@
 					P_CF1_ENA_TXBMU_WR_IDLE,
 };
 
+/* Yukon-Optima */
+enum {
+	PSM_CONFIG_REG1_AC_PRESENT_STATUS = 1<<31,   /* AC Present Status */
+
+	PSM_CONFIG_REG1_PTP_CLK_SEL	  = 1<<29,   /* PTP Clock Select */
+	PSM_CONFIG_REG1_PTP_MODE	  = 1<<28,   /* PTP Mode */
+
+	PSM_CONFIG_REG1_MUX_PHY_LINK	  = 1<<27,   /* PHY Energy Detect Event */
+
+	PSM_CONFIG_REG1_EN_PIN63_AC_PRESENT = 1<<26,  /* Enable LED_DUPLEX for ac_present */
+	PSM_CONFIG_REG1_EN_PCIE_TIMER	  = 1<<25,    /* Enable PCIe Timer */
+	PSM_CONFIG_REG1_EN_SPU_TIMER	  = 1<<24,    /* Enable SPU Timer */
+	PSM_CONFIG_REG1_POLARITY_AC_PRESENT = 1<<23,  /* AC Present Polarity */
+
+	PSM_CONFIG_REG1_EN_AC_PRESENT	  = 1<<21,    /* Enable AC Present */
+
+	PSM_CONFIG_REG1_EN_GPHY_INT_PSM	= 1<<20,      /* Enable GPHY INT for PSM */
+	PSM_CONFIG_REG1_DIS_PSM_TIMER	= 1<<19,      /* Disable PSM Timer */
+};
+
+/* Yukon-Supreme */
+enum {
+	PSM_CONFIG_REG1_GPHY_ENERGY_STS	= 1<<31, /* GPHY Energy Detect Status */
+
+	PSM_CONFIG_REG1_UART_MODE_MSK	= 3<<29, /* UART_Mode */
+	PSM_CONFIG_REG1_CLK_RUN_ASF	= 1<<28, /* Enable Clock Free Running for ASF Subsystem */
+	PSM_CONFIG_REG1_UART_CLK_DISABLE= 1<<27, /* Disable UART clock */
+	PSM_CONFIG_REG1_VAUX_ONE	= 1<<26, /* Tie internal Vaux to 1'b1 */
+	PSM_CONFIG_REG1_UART_FC_RI_VAL	= 1<<25, /* Default value for UART_RI_n */
+	PSM_CONFIG_REG1_UART_FC_DCD_VAL	= 1<<24, /* Default value for UART_DCD_n */
+	PSM_CONFIG_REG1_UART_FC_DSR_VAL	= 1<<23, /* Default value for UART_DSR_n */
+	PSM_CONFIG_REG1_UART_FC_CTS_VAL	= 1<<22, /* Default value for UART_CTS_n */
+	PSM_CONFIG_REG1_LATCH_VAUX	= 1<<21, /* Enable Latch current Vaux_avlbl */
+	PSM_CONFIG_REG1_FORCE_TESTMODE_INPUT= 1<<20, /* Force Testmode pin as input PAD */
+	PSM_CONFIG_REG1_UART_RST	= 1<<19, /* UART_RST */
+	PSM_CONFIG_REG1_PSM_PCIE_L1_POL	= 1<<18, /* PCIE L1 Event Polarity for PSM */
+	PSM_CONFIG_REG1_TIMER_STAT	= 1<<17, /* PSM Timer Status */
+	PSM_CONFIG_REG1_GPHY_INT	= 1<<16, /* GPHY INT Status */
+	PSM_CONFIG_REG1_FORCE_TESTMODE_ZERO= 1<<15, /* Force internal Testmode as 1'b0 */
+	PSM_CONFIG_REG1_EN_INT_ASPM_CLKREQ = 1<<14, /* ENABLE INT for CLKRUN on ASPM and CLKREQ */
+	PSM_CONFIG_REG1_EN_SND_TASK_ASPM_CLKREQ	= 1<<13, /* ENABLE Snd_task for CLKRUN on ASPM and CLKREQ */
+	PSM_CONFIG_REG1_DIS_CLK_GATE_SND_TASK	= 1<<12, /* Disable CLK_GATE control snd_task */
+	PSM_CONFIG_REG1_DIS_FF_CHIAN_SND_INTA	= 1<<11, /* Disable flip-flop chain for sndmsg_inta */
+
+	PSM_CONFIG_REG1_DIS_LOADER	= 1<<9, /* Disable Loader SM after PSM Goes back to IDLE */
+	PSM_CONFIG_REG1_DO_PWDN		= 1<<8, /* Do Power Down, Start PSM Scheme */
+	PSM_CONFIG_REG1_DIS_PIG		= 1<<7, /* Disable Plug-in-Go SM after PSM Goes back to IDLE */
+	PSM_CONFIG_REG1_DIS_PERST	= 1<<6, /* Disable Internal PCIe Reset after PSM Goes back to IDLE */
+	PSM_CONFIG_REG1_EN_REG18_PD	= 1<<5, /* Enable REG18 Power Down for PSM */
+	PSM_CONFIG_REG1_EN_PSM_LOAD	= 1<<4, /* Disable EEPROM Loader after PSM Goes back to IDLE */
+	PSM_CONFIG_REG1_EN_PSM_HOT_RST	= 1<<3, /* Enable PCIe Hot Reset for PSM */
+	PSM_CONFIG_REG1_EN_PSM_PERST	= 1<<2, /* Enable PCIe Reset Event for PSM */
+	PSM_CONFIG_REG1_EN_PSM_PCIE_L1	= 1<<1, /* Enable PCIe L1 Event for PSM */
+	PSM_CONFIG_REG1_EN_PSM		= 1<<0, /* Enable PSM Scheme */
+};
+
+/*	PSM_CONFIG_REG4				0x0168	PSM Config Register 4 */
+enum {
+						/* PHY Link Detect Timer */
+	PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_MSK = 0xf<<4,
+	PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE = 4,
+
+	PSM_CONFIG_REG4_DEBUG_TIMER	    = 1<<1, /* Debug Timer */
+	PSM_CONFIG_REG4_RST_PHY_LINK_DETECT = 1<<0, /* Reset GPHY Link Detect */
+};
+
 
 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
 			       PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -197,6 +301,9 @@
 	B2_I2C_IRQ	= 0x0168,
 	B2_I2C_SW	= 0x016c,
 
+	Y2_PEX_PHY_DATA = 0x0170,
+	Y2_PEX_PHY_ADDR = 0x0172,
+
 	B3_RAM_ADDR	= 0x0180,
 	B3_RAM_DATA_LO	= 0x0184,
 	B3_RAM_DATA_HI	= 0x0188,
@@ -317,6 +424,10 @@
 	Y2_IS_CHK_TXS2	= 1<<9,		/* Descriptor error TXS 2 */
 	Y2_IS_CHK_TXA2	= 1<<8,		/* Descriptor error TXA 2 */
 
+	Y2_IS_PSM_ACK	= 1<<7,		/* PSM Acknowledge (Yukon-Optima only) */
+	Y2_IS_PTP_TIST	= 1<<6,		/* PTP Time Stamp (Yukon-Optima only) */
+	Y2_IS_PHY_QLNK	= 1<<5,		/* PHY Quick Link (Yukon-Optima only) */
+
 	Y2_IS_IRQ_PHY1	= 1<<4,		/* Interrupt from PHY 1 */
 	Y2_IS_IRQ_MAC1	= 1<<3,		/* Interrupt from MAC 1 */
 	Y2_IS_CHK_RX1	= 1<<2,		/* Descriptor error Rx 1 */
@@ -435,6 +546,7 @@
  	CHIP_ID_YUKON_FE_P = 0xb8, /* YUKON-2 FE+ */
 	CHIP_ID_YUKON_SUPR = 0xb9, /* YUKON-2 Supreme */
 	CHIP_ID_YUKON_UL_2 = 0xba, /* YUKON-2 Ultra 2 */
+	CHIP_ID_YUKON_OPT  = 0xbc, /* YUKON-2 Optima */
 };
 enum yukon_ec_rev {
 	CHIP_REV_YU_EC_A1    = 0,  /* Chip Rev. for Yukon-EC A1/A0 */
@@ -459,6 +571,8 @@
 };
 enum yukon_supr_rev {
 	CHIP_REV_YU_SU_A0    = 0,
+	CHIP_REV_YU_SU_B0    = 1,
+	CHIP_REV_YU_SU_B1    = 3,
 };
 
 
@@ -513,6 +627,12 @@
 	TIM_T_STEP	= 1<<0,	/* Test step */
 };
 
+/*	Y2_PEX_PHY_ADDR/DATA		PEX PHY address and data reg  (Yukon-2 only) */
+enum {
+	PEX_RD_ACCESS	= 1<<31, /* Access Mode Read = 1, Write = 0 */
+	PEX_DB_ACCESS	= 1<<30, /* Access to debug register */
+};
+
 /*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
 					/* Bit 31..19:	reserved */
 #define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
@@ -754,6 +874,42 @@
 	BMU_TX_CLR_IRQ_TCP	= 1<<11, /* Clear IRQ on TCP segment length mismatch */
 };
 
+/*	TBMU_TEST			0x06B8	Transmit BMU Test Register */
+enum {
+	TBMU_TEST_BMU_TX_CHK_AUTO_OFF		= 1<<31, /* BMU Tx Checksum Auto Calculation Disable */
+	TBMU_TEST_BMU_TX_CHK_AUTO_ON		= 1<<30, /* BMU Tx Checksum Auto Calculation Enable */
+	TBMU_TEST_HOME_ADD_PAD_FIX1_EN		= 1<<29, /* Home Address Paddiing FIX1 Enable */
+	TBMU_TEST_HOME_ADD_PAD_FIX1_DIS		= 1<<28, /* Home Address Paddiing FIX1 Disable */
+	TBMU_TEST_ROUTING_ADD_FIX_EN		= 1<<27, /* Routing Address Fix Enable */
+	TBMU_TEST_ROUTING_ADD_FIX_DIS		= 1<<26, /* Routing Address Fix Disable */
+	TBMU_TEST_HOME_ADD_FIX_EN		= 1<<25, /* Home address checksum fix enable */
+	TBMU_TEST_HOME_ADD_FIX_DIS		= 1<<24, /* Home address checksum fix disable */
+
+	TBMU_TEST_TEST_RSPTR_ON			= 1<<22, /* Testmode Shadow Read Ptr On */
+	TBMU_TEST_TEST_RSPTR_OFF		= 1<<21, /* Testmode Shadow Read Ptr Off */
+	TBMU_TEST_TESTSTEP_RSPTR		= 1<<20, /* Teststep Shadow Read Ptr */
+
+	TBMU_TEST_TEST_RPTR_ON			= 1<<18, /* Testmode Read Ptr On */
+	TBMU_TEST_TEST_RPTR_OFF			= 1<<17, /* Testmode Read Ptr Off */
+	TBMU_TEST_TESTSTEP_RPTR			= 1<<16, /* Teststep Read Ptr */
+
+	TBMU_TEST_TEST_WSPTR_ON			= 1<<14, /* Testmode Shadow Write Ptr On */
+	TBMU_TEST_TEST_WSPTR_OFF		= 1<<13, /* Testmode Shadow Write Ptr Off */
+	TBMU_TEST_TESTSTEP_WSPTR		= 1<<12, /* Teststep Shadow Write Ptr */
+
+	TBMU_TEST_TEST_WPTR_ON			= 1<<10, /* Testmode Write Ptr On */
+	TBMU_TEST_TEST_WPTR_OFF			= 1<<9, /* Testmode Write Ptr Off */
+	TBMU_TEST_TESTSTEP_WPTR			= 1<<8,			/* Teststep Write Ptr */
+
+	TBMU_TEST_TEST_REQ_NB_ON		= 1<<6, /* Testmode Req Nbytes/Addr On */
+	TBMU_TEST_TEST_REQ_NB_OFF		= 1<<5, /* Testmode Req Nbytes/Addr Off */
+	TBMU_TEST_TESTSTEP_REQ_NB		= 1<<4, /* Teststep Req Nbytes/Addr */
+
+	TBMU_TEST_TEST_DONE_IDX_ON		= 1<<2, /* Testmode Done Index On */
+	TBMU_TEST_TEST_DONE_IDX_OFF		= 1<<1, /* Testmode Done Index Off */
+	TBMU_TEST_TESTSTEP_DONE_IDX		= 1<<0,	/* Teststep Done Index */
+};
+
 /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
 /* PREF_UNIT_CTRL	32 bit	Prefetch Control register */
 enum {
@@ -1674,6 +1830,12 @@
 
 /*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
 enum {
+	RX_GCLKMAC_ENA	= 1<<31,	/* RX MAC Clock Gating Enable */
+	RX_GCLKMAC_OFF	= 1<<30,
+
+	RX_STFW_DIS	= 1<<29,	/* RX Store and Forward Enable */
+	RX_STFW_ENA	= 1<<28,
+
 	RX_TRUNC_ON	= 1<<27,  	/* enable  packet truncation */
 	RX_TRUNC_OFF	= 1<<26, 	/* disable packet truncation */
 	RX_VLAN_STRIP_ON = 1<<25,	/* enable  VLAN stripping */
@@ -1711,6 +1873,20 @@
 	GMF_RX_CTRL_DEF	= GMF_OPER_ON | GMF_RX_F_FL_ON,
 };
 
+/*	RX_GMF_FL_CTRL	16 bit	Rx GMAC FIFO Flush Control (Yukon-Supreme) */
+enum {
+	RX_IPV6_SA_MOB_ENA	= 1<<9,	/* IPv6 SA Mobility Support Enable */
+	RX_IPV6_SA_MOB_DIS	= 1<<8,	/* IPv6 SA Mobility Support Disable */
+	RX_IPV6_DA_MOB_ENA	= 1<<7,	/* IPv6 DA Mobility Support Enable */
+	RX_IPV6_DA_MOB_DIS	= 1<<6,	/* IPv6 DA Mobility Support Disable */
+	RX_PTR_SYNCDLY_ENA	= 1<<5,	/* Pointers Delay Synch Enable */
+	RX_PTR_SYNCDLY_DIS	= 1<<4,	/* Pointers Delay Synch Disable */
+	RX_ASF_NEWFLAG_ENA	= 1<<3,	/* RX ASF Flag New Logic Enable */
+	RX_ASF_NEWFLAG_DIS	= 1<<2,	/* RX ASF Flag New Logic Disable */
+	RX_FLSH_MISSPKT_ENA	= 1<<1,	/* RX Flush Miss-Packet Enable */
+	RX_FLSH_MISSPKT_DIS	= 1<<0,	/* RX Flush Miss-Packet Disable */
+};
+
 /*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
 enum {
 	TX_DYN_WM_ENA	= 3,	/* Yukon-FE+ specific */
--- linux-ec2-2.6.32.orig/drivers/net/bnx2x_main.c
+++ linux-ec2-2.6.32/drivers/net/bnx2x_main.c
@@ -49,6 +49,7 @@
 #include <linux/prefetch.h>
 #include <linux/zlib.h>
 #include <linux/io.h>
+#include <linux/stringify.h>
 
 
 #include "bnx2x.h"
@@ -63,8 +64,13 @@
 #include <linux/firmware.h>
 #include "bnx2x_fw_file_hdr.h"
 /* FW files */
-#define FW_FILE_PREFIX_E1	"bnx2x-e1-"
-#define FW_FILE_PREFIX_E1H	"bnx2x-e1h-"
+#define FW_FILE_VERSION					\
+	__stringify(BCM_5710_FW_MAJOR_VERSION) "."	\
+	__stringify(BCM_5710_FW_MINOR_VERSION) "."	\
+	__stringify(BCM_5710_FW_REVISION_VERSION) "."	\
+	__stringify(BCM_5710_FW_ENGINEERING_VERSION)
+#define FW_FILE_NAME_E1		"bnx2x-e1-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1H	"bnx2x-e1h-" FW_FILE_VERSION ".fw"
 
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT		(5*HZ)
@@ -77,6 +83,8 @@
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FW_FILE_NAME_E1);
+MODULE_FIRMWARE(FW_FILE_NAME_E1H);
 
 static int multi_mode = 1;
 module_param(multi_mode, int, 0);
@@ -11830,21 +11838,14 @@
 
 static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
 {
-	char fw_file_name[40] = {0};
+	const char *fw_file_name;
 	struct bnx2x_fw_file_hdr *fw_hdr;
-	int rc, offset;
+	int rc;
 
-	/* Create a FW file name */
 	if (CHIP_IS_E1(bp))
-		offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
+		fw_file_name = FW_FILE_NAME_E1;
 	else
-		offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H);
-
-	sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw",
-		BCM_5710_FW_MAJOR_VERSION,
-		BCM_5710_FW_MINOR_VERSION,
-		BCM_5710_FW_REVISION_VERSION,
-		BCM_5710_FW_ENGINEERING_VERSION);
+		fw_file_name = FW_FILE_NAME_E1H;
 
 	printk(KERN_INFO PFX "Loading %s\n", fw_file_name);
 
--- linux-ec2-2.6.32.orig/drivers/net/xen-netfront.c
+++ linux-ec2-2.6.32/drivers/net/xen-netfront.c
@@ -36,8 +36,6 @@
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
 #include <linux/if_ether.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
 #include <linux/moduleparam.h>
 #include <linux/mm.h>
 #include <net/ip.h>
@@ -768,45 +766,6 @@
 	return cons;
 }
 
-static int skb_checksum_setup(struct sk_buff *skb)
-{
-	struct iphdr *iph;
-	unsigned char *th;
-	int err = -EPROTO;
-
-	if (skb->protocol != htons(ETH_P_IP))
-		goto out;
-
-	iph = (void *)skb->data;
-	th = skb->data + 4 * iph->ihl;
-	if (th >= skb_tail_pointer(skb))
-		goto out;
-
-	skb->csum_start = th - skb->head;
-	switch (iph->protocol) {
-	case IPPROTO_TCP:
-		skb->csum_offset = offsetof(struct tcphdr, check);
-		break;
-	case IPPROTO_UDP:
-		skb->csum_offset = offsetof(struct udphdr, check);
-		break;
-	default:
-		if (net_ratelimit())
-			printk(KERN_ERR "Attempting to checksum a non-"
-			       "TCP/UDP packet, dropping a protocol"
-			       " %d packet", iph->protocol);
-		goto out;
-	}
-
-	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
-		goto out;
-
-	err = 0;
-
-out:
-	return err;
-}
-
 static int handle_incoming_queue(struct net_device *dev,
 				 struct sk_buff_head *rxq)
 {
@@ -1619,6 +1578,7 @@
 		if (xennet_connect(netdev) != 0)
 			break;
 		xenbus_switch_state(dev, XenbusStateConnected);
+		netif_notify_peers(netdev);
 		break;
 
 	case XenbusStateClosing:
@@ -1793,7 +1753,6 @@
 
 static struct xenbus_driver netfront_driver = {
 	.name = "vif",
-	.owner = THIS_MODULE,
 	.ids = netfront_ids,
 	.probe = netfront_probe,
 	.remove = __devexit_p(xennet_remove),
--- linux-ec2-2.6.32.orig/drivers/net/pppol2tp.c
+++ linux-ec2-2.6.32/drivers/net/pppol2tp.c
@@ -756,6 +756,7 @@
 
 	/* Try to dequeue as many skbs from reorder_q as we can. */
 	pppol2tp_recv_dequeue(session);
+	sock_put(sock);
 
 	return 0;
 
@@ -772,6 +773,7 @@
 	UDP_INC_STATS_USER(&init_net, UDP_MIB_INERRORS, 0);
 	tunnel->stats.rx_errors++;
 	kfree_skb(skb);
+	sock_put(sock);
 
 	return 0;
 
@@ -1178,7 +1180,8 @@
 	/* Calculate UDP checksum if configured to do so */
 	if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
 		skb->ip_summed = CHECKSUM_NONE;
-	else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
+	else if ((skb_dst(skb) && skb_dst(skb)->dev) &&
+		 (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		csum = skb_checksum(skb, 0, udp_len, 0);
 		uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
@@ -1657,6 +1660,7 @@
 		if (tunnel_sock == NULL)
 			goto end;
 
+		sock_hold(tunnel_sock);
 		tunnel = tunnel_sock->sk_user_data;
 	} else {
 		tunnel = pppol2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel);
--- linux-ec2-2.6.32.orig/drivers/net/starfire.c
+++ linux-ec2-2.6.32/drivers/net/starfire.c
@@ -1063,7 +1063,7 @@
 	if (retval) {
 		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
 		       FIRMWARE_RX);
-		return retval;
+		goto out_init;
 	}
 	if (fw_rx->size % 4) {
 		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
@@ -1108,6 +1108,9 @@
 	release_firmware(fw_tx);
 out_rx:
 	release_firmware(fw_rx);
+out_init:
+	if (retval)
+		netdev_close(dev);
 	return retval;
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/e100.c
+++ linux-ec2-2.6.32/drivers/net/e100.c
@@ -1817,6 +1817,7 @@
 				  &nic->cbs_dma_addr);
 	if (!nic->cbs)
 		return -ENOMEM;
+	memset(nic->cbs, 0, count * sizeof(struct cb));
 
 	for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
 		cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
@@ -1825,7 +1826,6 @@
 		cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb);
 		cb->link = cpu_to_le32(nic->cbs_dma_addr +
 			((i+1) % count) * sizeof(struct cb));
-		cb->skb = NULL;
 	}
 
 	nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs;
--- linux-ec2-2.6.32.orig/drivers/net/jme.c
+++ linux-ec2-2.6.32/drivers/net/jme.c
@@ -946,6 +946,8 @@
 				jme->jme_vlan_rx(skb, jme->vlgrp,
 					le16_to_cpu(rxdesc->descwb.vlan));
 				NET_STAT(jme).rx_bytes += 4;
+			} else {
+				dev_kfree_skb(skb);
 			}
 		} else {
 			jme->jme_rx(skb);
@@ -1576,6 +1578,16 @@
 	}
 }
 
+static inline void
+jme_phy_on(struct jme_adapter *jme)
+{
+	u32 bmcr;
+
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr &= ~BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+}
+
 static int
 jme_open(struct net_device *netdev)
 {
@@ -1596,10 +1608,12 @@
 
 	jme_start_irq(jme);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags))
+	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+		jme_phy_on(jme);
 		jme_set_settings(netdev, &jme->old_ecmd);
-	else
+	} else {
 		jme_reset_phy_processor(jme);
+	}
 
 	jme_reset_link(jme);
 
@@ -2085,12 +2099,45 @@
 	jme_reset_link(jme);
 }
 
+static inline void jme_pause_rx(struct jme_adapter *jme)
+{
+	atomic_dec(&jme->link_changing);
+
+	jme_set_rx_pcc(jme, PCC_OFF);
+	if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+		JME_NAPI_DISABLE(jme);
+	} else {
+		tasklet_disable(&jme->rxclean_task);
+		tasklet_disable(&jme->rxempty_task);
+	}
+}
+
+static inline void jme_resume_rx(struct jme_adapter *jme)
+{
+	struct dynpcc_info *dpi = &(jme->dpi);
+
+	if (test_bit(JME_FLAG_POLL, &jme->flags)) {
+		JME_NAPI_ENABLE(jme);
+	} else {
+		tasklet_hi_enable(&jme->rxclean_task);
+		tasklet_hi_enable(&jme->rxempty_task);
+	}
+	dpi->cur		= PCC_P1;
+	dpi->attempt		= PCC_P1;
+	dpi->cnt		= 0;
+	jme_set_rx_pcc(jme, PCC_P1);
+
+	atomic_inc(&jme->link_changing);
+}
+
 static void
 jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 
+	jme_pause_rx(jme);
 	jme->vlgrp = grp;
+	jme_resume_rx(jme);
 }
 
 static void
@@ -2978,10 +3025,12 @@
 	jme_clear_pm(jme);
 	pci_restore_state(pdev);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags))
+	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
+		jme_phy_on(jme);
 		jme_set_settings(netdev, &jme->old_ecmd);
-	else
+	} else {
 		jme_reset_phy_processor(jme);
+	}
 
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
--- linux-ec2-2.6.32.orig/drivers/net/via-rhine.c
+++ linux-ec2-2.6.32/drivers/net/via-rhine.c
@@ -102,6 +102,7 @@
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
+#include <linux/workqueue.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -389,6 +390,7 @@
 	struct net_device *dev;
 	struct napi_struct napi;
 	spinlock_t lock;
+	struct work_struct reset_task;
 
 	/* Frequently used values: keep some adjacent for cache effect. */
 	u32 quirks;
@@ -407,6 +409,7 @@
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
+static void rhine_reset_task(struct work_struct *work);
 static void rhine_tx_timeout(struct net_device *dev);
 static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 				  struct net_device *dev);
@@ -775,6 +778,8 @@
 	dev->irq = pdev->irq;
 
 	spin_lock_init(&rp->lock);
+	INIT_WORK(&rp->reset_task, rhine_reset_task);
+
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
 	rp->mii_if.mdio_write = mdio_write;
@@ -1179,22 +1184,18 @@
 	return 0;
 }
 
-static void rhine_tx_timeout(struct net_device *dev)
+static void rhine_reset_task(struct work_struct *work)
 {
-	struct rhine_private *rp = netdev_priv(dev);
-	void __iomem *ioaddr = rp->base;
-
-	printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
-	       "%4.4x, resetting...\n",
-	       dev->name, ioread16(ioaddr + IntrStatus),
-	       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+	struct rhine_private *rp = container_of(work, struct rhine_private,
+						reset_task);
+	struct net_device *dev = rp->dev;
 
 	/* protect against concurrent rx interrupts */
 	disable_irq(rp->pdev->irq);
 
 	napi_disable(&rp->napi);
 
-	spin_lock(&rp->lock);
+	spin_lock_bh(&rp->lock);
 
 	/* clear all descriptors */
 	free_tbufs(dev);
@@ -1206,7 +1207,7 @@
 	rhine_chip_reset(dev);
 	init_registers(dev);
 
-	spin_unlock(&rp->lock);
+	spin_unlock_bh(&rp->lock);
 	enable_irq(rp->pdev->irq);
 
 	dev->trans_start = jiffies;
@@ -1214,6 +1215,19 @@
 	netif_wake_queue(dev);
 }
 
+static void rhine_tx_timeout(struct net_device *dev)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	void __iomem *ioaddr = rp->base;
+
+	printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
+	       "%4.4x, resetting...\n",
+	       dev->name, ioread16(ioaddr + IntrStatus),
+	       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
+
+	schedule_work(&rp->reset_task);
+}
+
 static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
 				  struct net_device *dev)
 {
@@ -1830,10 +1844,11 @@
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 
-	spin_lock_irq(&rp->lock);
-
-	netif_stop_queue(dev);
 	napi_disable(&rp->napi);
+	cancel_work_sync(&rp->reset_task);
+	netif_stop_queue(dev);
+
+	spin_lock_irq(&rp->lock);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, "
--- linux-ec2-2.6.32.orig/drivers/net/ucc_geth.c
+++ linux-ec2-2.6.32/drivers/net/ucc_geth.c
@@ -1563,7 +1563,10 @@
 
 static void ugeth_quiesce(struct ucc_geth_private *ugeth)
 {
-	/* Wait for and prevent any further xmits. */
+	/* Prevent any further xmits, plus detach the device. */
+	netif_device_detach(ugeth->ndev);
+
+	/* Wait for any current xmits to finish. */
 	netif_tx_disable(ugeth->ndev);
 
 	/* Disable the interrupt to avoid NAPI rescheduling. */
@@ -1577,7 +1580,7 @@
 {
 	napi_enable(&ugeth->napi);
 	enable_irq(ugeth->ug_info->uf_info.irq);
-	netif_tx_wake_all_queues(ugeth->ndev);
+	netif_device_attach(ugeth->ndev);
 }
 
 /* Called every time the controller might need to be made
@@ -3273,13 +3276,12 @@
 		/* Handle the transmitted buffer and release */
 		/* the BD to be used with the current frame  */
 
-		if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
+		if (!skb)
 			break;
 
 		dev->stats.tx_packets++;
 
-		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
-
 		if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN &&
 			     skb_recycle_check(skb,
 				    ugeth->ug_info->uf_info.max_rx_buf_length +
--- linux-ec2-2.6.32.orig/drivers/net/hydra.c
+++ linux-ec2-2.6.32/drivers/net/hydra.c
@@ -98,15 +98,15 @@
 	.ndo_open		= hydra_open,
 	.ndo_stop		= hydra_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -125,7 +125,7 @@
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
 
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/drivers/net/virtio_net.c
+++ linux-ec2-2.6.32/drivers/net/virtio_net.c
@@ -391,6 +391,20 @@
 	}
 }
 
+static void virtnet_napi_enable(struct virtnet_info *vi)
+{
+	napi_enable(&vi->napi);
+
+	/* If all buffers were filled by other side before we napi_enabled, we
+	 * won't get another interrupt, so process any outstanding packets
+	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
+	 * We synchronize against interrupts via NAPI_STATE_SCHED */
+	if (napi_schedule_prep(&vi->napi)) {
+		vi->rvq->vq_ops->disable_cb(vi->rvq);
+		__napi_schedule(&vi->napi);
+	}
+}
+
 static void refill_work(struct work_struct *work)
 {
 	struct virtnet_info *vi;
@@ -398,9 +412,8 @@
 
 	vi = container_of(work, struct virtnet_info, refill.work);
 	napi_disable(&vi->napi);
-	try_fill_recv(vi, GFP_KERNEL);
-	still_empty = (vi->num == 0);
-	napi_enable(&vi->napi);
+	still_empty = !try_fill_recv(vi, GFP_KERNEL);
+	virtnet_napi_enable(vi);
 
 	/* In theory, this can happen: if we don't get any buffers in
 	 * we will *never* try to fill again. */
@@ -512,7 +525,6 @@
 	struct virtnet_info *vi = netdev_priv(dev);
 	int capacity;
 
-again:
 	/* Free up any pending old buffers before queueing new ones. */
 	free_old_xmit_skbs(vi);
 
@@ -521,14 +533,20 @@
 
 	/* This can happen with OOM and indirect buffers. */
 	if (unlikely(capacity < 0)) {
-		netif_stop_queue(dev);
-		dev_warn(&dev->dev, "Unexpected full queue\n");
-		if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
-			vi->svq->vq_ops->disable_cb(vi->svq);
-			netif_start_queue(dev);
-			goto again;
+		if (net_ratelimit()) {
+			if (likely(capacity == -ENOMEM)) {
+				dev_warn(&dev->dev,
+					 "TX queue failure: out of memory\n");
+			} else {
+				dev->stats.tx_fifo_errors++;
+				dev_warn(&dev->dev,
+					 "Unexpected TX queue failure: %d\n",
+					 capacity);
+			}
 		}
-		return NETDEV_TX_BUSY;
+		dev->stats.tx_dropped++;
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
 	}
 	vi->svq->vq_ops->kick(vi->svq);
 
@@ -592,16 +610,7 @@
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	napi_enable(&vi->napi);
-
-	/* If all buffers were filled by other side before we napi_enabled, we
-	 * won't get another interrupt, so process any outstanding packets
-	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
-	 * We synchronize against interrupts via NAPI_STATE_SCHED */
-	if (napi_schedule_prep(&vi->napi)) {
-		vi->rvq->vq_ops->disable_cb(vi->rvq);
-		__napi_schedule(&vi->napi);
-	}
+	virtnet_napi_enable(vi);
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/netx-eth.c
+++ linux-ec2-2.6.32/drivers/net/netx-eth.c
@@ -510,3 +510,6 @@
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" CARDNAME);
+MODULE_FIRMWARE("xc0.bin");
+MODULE_FIRMWARE("xc1.bin");
+MODULE_FIRMWARE("xc2.bin");
--- linux-ec2-2.6.32.orig/drivers/net/cpmac.c
+++ linux-ec2-2.6.32/drivers/net/cpmac.c
@@ -1176,7 +1176,8 @@
 		if (netif_msg_drv(priv))
 			printk(KERN_ERR "%s: Could not attach to PHY\n",
 			       dev->name);
-		return PTR_ERR(priv->phy);
+		rc = PTR_ERR(priv->phy);
+		goto fail;
 	}
 
 	if ((rc = register_netdev(dev))) {
--- linux-ec2-2.6.32.orig/drivers/net/b44.c
+++ linux-ec2-2.6.32/drivers/net/b44.c
@@ -1505,8 +1505,7 @@
 		for (k = 0; k< ethaddr_bytes; k++) {
 			ppattern[offset + magicsync +
 				(j * ETH_ALEN) + k] = macaddr[k];
-			len++;
-			set_bit(len, (unsigned long *) pmask);
+			set_bit(len++, (unsigned long *) pmask);
 		}
 	}
 	return len - 1;
@@ -2176,8 +2175,6 @@
 	dev->irq = sdev->irq;
 	SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
 
-	netif_carrier_off(dev);
-
 	err = ssb_bus_powerup(sdev->bus, 0);
 	if (err) {
 		dev_err(sdev->dev,
@@ -2217,6 +2214,8 @@
 		goto err_out_powerdown;
 	}
 
+	netif_carrier_off(dev);
+
 	ssb_set_drvdata(sdev, dev);
 
 	/* Chip reset provides power to the b44 MAC & PCI cores, which
--- linux-ec2-2.6.32.orig/drivers/net/skge.c
+++ linux-ec2-2.6.32/drivers/net/skge.c
@@ -40,6 +40,7 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/mii.h>
+#include <linux/dmi.h>
 #include <asm/irq.h>
 
 #include "skge.h"
@@ -3890,6 +3891,8 @@
 		       dev->name, dev->dev_addr);
 }
 
+static int only_32bit_dma;
+
 static int __devinit skge_probe(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
@@ -3911,7 +3914,7 @@
 
 	pci_set_master(pdev);
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
 		using_dac = 1;
 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 	} else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
@@ -4168,8 +4171,21 @@
 	.shutdown =	skge_shutdown,
 };
 
+static struct dmi_system_id skge_32bit_dma_boards[] = {
+	{
+		.ident = "Gigabyte nForce boards",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"),
+			DMI_MATCH(DMI_BOARD_NAME, "nForce"),
+		},
+	},
+	{}
+};
+
 static int __init skge_init_module(void)
 {
+	if (dmi_check_system(skge_32bit_dma_boards))
+		only_32bit_dma = 1;
 	skge_debug_init();
 	return pci_register_driver(&skge_driver);
 }
--- linux-ec2-2.6.32.orig/drivers/net/ehea/ehea_ethtool.c
+++ linux-ec2-2.6.32/drivers/net/ehea/ehea_ethtool.c
@@ -53,15 +53,20 @@
 		cmd->duplex = -1;
 	}
 
-	cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full
-		       | SUPPORTED_100baseT_Full |  SUPPORTED_100baseT_Half
-		       | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half
-		       | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-	cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg
-			 | ADVERTISED_FIBRE);
+	if (cmd->speed == SPEED_10000) {
+		cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+		cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+		cmd->port = PORT_FIBRE;
+	} else {
+		cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full
+			       | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full
+			       | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg
+			       | SUPPORTED_TP);
+		cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg
+				 | ADVERTISED_TP);
+		cmd->port = PORT_TP;
+	}
 
-	cmd->port = PORT_FIBRE;
 	cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/net/can/sja1000/sja1000.h
+++ linux-ec2-2.6.32/drivers/net/can/sja1000/sja1000.h
@@ -165,6 +165,7 @@
 
 	void __iomem *reg_base;	 /* ioremap'ed address to registers */
 	unsigned long irq_flags; /* for request_irq() */
+	spinlock_t cmdreg_lock;  /* lock for concurrent cmd register writes */
 
 	u16 flags;		/* custom mode flags */
 	u8 ocr;			/* output control register */
--- linux-ec2-2.6.32.orig/drivers/net/can/sja1000/sja1000.c
+++ linux-ec2-2.6.32/drivers/net/can/sja1000/sja1000.c
@@ -84,6 +84,20 @@
 	.brp_inc = 1,
 };
 
+static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
+{
+	unsigned long flags;
+
+	/*
+	 * The command register needs some locking and time to settle
+	 * the write_reg() operation - especially on SMP systems.
+	 */
+	spin_lock_irqsave(&priv->cmdreg_lock, flags);
+	priv->write_reg(priv, REG_CMR, val);
+	priv->read_reg(priv, REG_SR);
+	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
+}
+
 static int sja1000_probe_chip(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
@@ -279,7 +293,7 @@
 
 	can_put_echo_skb(skb, dev, 0);
 
-	priv->write_reg(priv, REG_CMR, CMD_TR);
+	sja1000_write_cmdreg(priv, CMD_TR);
 
 	return NETDEV_TX_OK;
 }
@@ -334,7 +348,7 @@
 		cf->data[i++] = 0;
 
 	/* release receive buffer */
-	priv->write_reg(priv, REG_CMR, CMD_RRB);
+	sja1000_write_cmdreg(priv, CMD_RRB);
 
 	netif_rx(skb);
 
@@ -368,7 +382,7 @@
 		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
 		stats->rx_over_errors++;
 		stats->rx_errors++;
-		priv->write_reg(priv, REG_CMR, CMD_CDO);	/* clear bit */
+		sja1000_write_cmdreg(priv, CMD_CDO);	/* clear bit */
 	}
 
 	if (isrc & IRQ_EI) {
--- linux-ec2-2.6.32.orig/drivers/net/benet/be.h
+++ linux-ec2-2.6.32/drivers/net/benet/be.h
@@ -35,20 +35,31 @@
 #define DRV_VER			"2.101.205"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
+#define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
 #define OC_NAME			"Emulex OneConnect 10Gbps NIC"
+#define OC_NAME1		"Emulex OneConnect 10Gbps NIC (be3)"
 #define DRV_DESC		BE_NAME "Driver"
 
 #define BE_VENDOR_ID 		0x19a2
 #define BE_DEVICE_ID1		0x211
+#define BE_DEVICE_ID2		0x221
 #define OC_DEVICE_ID1		0x700
 #define OC_DEVICE_ID2		0x701
+#define OC_DEVICE_ID3		0x710
 
 static inline char *nic_name(struct pci_dev *pdev)
 {
-	if (pdev->device == OC_DEVICE_ID1 || pdev->device == OC_DEVICE_ID2)
+	switch (pdev->device) {
+	case OC_DEVICE_ID1:
+	case OC_DEVICE_ID2:
 		return OC_NAME;
-	else
+	case OC_DEVICE_ID3:
+		return OC_NAME1;
+	case BE_DEVICE_ID2:
+		return BE3_NAME;
+	default:
 		return BE_NAME;
+	}
 }
 
 /* Number of bytes of an RX frame that are copied to skb->data */
@@ -154,6 +165,7 @@
 	ulong be_tx_jiffies;
 	u64 be_tx_bytes;
 	u64 be_tx_bytes_prev;
+	u64 be_tx_pkts;
 	u32 be_tx_rate;
 
 	u32 cache_barrier[16];
@@ -165,6 +177,7 @@
 	ulong be_rx_jiffies;
 	u64 be_rx_bytes;
 	u64 be_rx_bytes_prev;
+	u64 be_rx_pkts;
 	u32 be_rx_rate;
 	/* number of non ether type II frames dropped where
 	 * frame len > length field of Mac Hdr */
@@ -261,8 +274,13 @@
 	u32 cap;
 	u32 rx_fc;		/* Rx flow control */
 	u32 tx_fc;		/* Tx flow control */
+	u8 generation;		/* BladeEngine ASIC generation */
 };
 
+/* BladeEngine Generation numbers */
+#define BE_GEN2 2
+#define BE_GEN3 3
+
 extern const struct ethtool_ops be_ethtool_ops;
 
 #define drvr_stats(adapter)		(&adapter->stats.drvr_stats)
--- linux-ec2-2.6.32.orig/drivers/net/benet/be_cmds.h
+++ linux-ec2-2.6.32/drivers/net/benet/be_cmds.h
@@ -154,7 +154,8 @@
 	u8 domain;		/* dword 0 */
 	u32 timeout;		/* dword 1 */
 	u32 request_length;	/* dword 2 */
-	u32 rsvd;		/* dword 3 */
+	u8 version;		/* dword 3 */
+	u8 rsvd[3];		/* dword 3 */
 };
 
 #define RESP_HDR_INFO_OPCODE_SHIFT	0	/* bits 0 - 7 */
--- linux-ec2-2.6.32.orig/drivers/net/benet/be_main.c
+++ linux-ec2-2.6.32/drivers/net/benet/be_main.c
@@ -31,8 +31,10 @@
 
 static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
+	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -144,13 +146,10 @@
 	struct net_device_stats *dev_stats = &adapter->stats.net_stats;
 	struct be_erx_stats *erx_stats = &hw_stats->erx;
 
-	dev_stats->rx_packets = port_stats->rx_total_frames;
-	dev_stats->tx_packets = port_stats->tx_unicastframes +
-		port_stats->tx_multicastframes + port_stats->tx_broadcastframes;
-	dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 |
-				(u64) port_stats->rx_bytes_lsd;
-	dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 |
-				(u64) port_stats->tx_bytes_lsd;
+	dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts;
+	dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
+	dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
+	dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
 
 	/* bad pkts received */
 	dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -307,12 +306,13 @@
 }
 
 static void be_tx_stats_update(struct be_adapter *adapter,
-			u32 wrb_cnt, u32 copied, bool stopped)
+			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)
 {
 	struct be_drvr_stats *stats = drvr_stats(adapter);
 	stats->be_tx_reqs++;
 	stats->be_tx_wrbs += wrb_cnt;
 	stats->be_tx_bytes += copied;
+	stats->be_tx_pkts += (gso_segs ? gso_segs : 1);
 	if (stopped)
 		stats->be_tx_stops++;
 }
@@ -460,7 +460,8 @@
 
 		be_txq_notify(adapter, txq->id, wrb_cnt);
 
-		be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
+		be_tx_stats_update(adapter, wrb_cnt, copied,
+				skb_shinfo(skb)->gso_segs, stopped);
 	} else {
 		txq->head = start;
 		dev_kfree_skb_any(skb);
@@ -603,6 +604,7 @@
 	stats->be_rx_compl++;
 	stats->be_rx_frags += numfrags;
 	stats->be_rx_bytes += pktsize;
+	stats->be_rx_pkts++;
 }
 
 static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@@ -1942,6 +1944,7 @@
 static int be_map_pci_bars(struct be_adapter *adapter)
 {
 	u8 __iomem *addr;
+	int pcicfg_reg;
 
 	addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
 			pci_resource_len(adapter->pdev, 2));
@@ -1955,8 +1958,13 @@
 		goto pci_map_err;
 	adapter->db = addr;
 
-	addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1),
-			pci_resource_len(adapter->pdev, 1));
+	if (adapter->generation == BE_GEN2)
+		pcicfg_reg = 1;
+	else
+		pcicfg_reg = 0;
+
+	addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg),
+			pci_resource_len(adapter->pdev, pcicfg_reg));
 	if (addr == NULL)
 		goto pci_map_err;
 	adapter->pcicfg = addr;
@@ -2026,6 +2034,7 @@
 	cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma);
 	if (cmd->va == NULL)
 		return -1;
+	memset(cmd->va, 0, cmd->size);
 	return 0;
 }
 
@@ -2099,6 +2108,20 @@
 		goto rel_reg;
 	}
 	adapter = netdev_priv(netdev);
+
+	switch (pdev->device) {
+	case BE_DEVICE_ID1:
+	case OC_DEVICE_ID1:
+		adapter->generation = BE_GEN2;
+		break;
+	case BE_DEVICE_ID2:
+	case OC_DEVICE_ID2:
+		adapter->generation = BE_GEN3;
+		break;
+	default:
+		adapter->generation = 0;
+	}
+
 	adapter->pdev = pdev;
 	pci_set_drvdata(pdev, adapter);
 	adapter->netdev = netdev;
--- linux-ec2-2.6.32.orig/drivers/net/atl1c/atl1c.h
+++ linux-ec2-2.6.32/drivers/net/atl1c/atl1c.h
@@ -534,6 +534,9 @@
 #define __AT_TESTING        0x0001
 #define __AT_RESETTING      0x0002
 #define __AT_DOWN           0x0003
+	u8 work_event;
+#define ATL1C_WORK_EVENT_RESET 		0x01
+#define ATL1C_WORK_EVENT_LINK_CHANGE	0x02
 	u32 msg_enable;
 
 	bool have_msi;
@@ -545,8 +548,7 @@
 	spinlock_t tx_lock;
 	atomic_t irq_sem;
 
-	struct work_struct reset_task;
-	struct work_struct link_chg_task;
+	struct work_struct common_task;
 	struct timer_list watchdog_timer;
 	struct timer_list phy_config_timer;
 
--- linux-ec2-2.6.32.orig/drivers/net/atl1c/atl1c_main.c
+++ linux-ec2-2.6.32/drivers/net/atl1c/atl1c_main.c
@@ -198,27 +198,12 @@
 
 void atl1c_reinit_locked(struct atl1c_adapter *adapter)
 {
-
 	WARN_ON(in_interrupt());
 	atl1c_down(adapter);
 	atl1c_up(adapter);
 	clear_bit(__AT_RESETTING, &adapter->flags);
 }
 
-static void atl1c_reset_task(struct work_struct *work)
-{
-	struct atl1c_adapter *adapter;
-	struct net_device *netdev;
-
-	adapter = container_of(work, struct atl1c_adapter, reset_task);
-	netdev = adapter->netdev;
-
-	netif_device_detach(netdev);
-	atl1c_down(adapter);
-	atl1c_up(adapter);
-	netif_device_attach(netdev);
-}
-
 static void atl1c_check_link_status(struct atl1c_adapter *adapter)
 {
 	struct atl1c_hw *hw = &adapter->hw;
@@ -275,18 +260,6 @@
 	}
 }
 
-/*
- * atl1c_link_chg_task - deal with link change event Out of interrupt context
- * @netdev: network interface device structure
- */
-static void atl1c_link_chg_task(struct work_struct *work)
-{
-	struct atl1c_adapter *adapter;
-
-	adapter = container_of(work, struct atl1c_adapter, link_chg_task);
-	atl1c_check_link_status(adapter);
-}
-
 static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -311,20 +284,40 @@
 			adapter->link_speed = SPEED_0;
 		}
 	}
-	schedule_work(&adapter->link_chg_task);
+
+	adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
+	schedule_work(&adapter->common_task);
 }
 
-static void atl1c_del_timer(struct atl1c_adapter *adapter)
+static void atl1c_common_task(struct work_struct *work)
 {
-	del_timer_sync(&adapter->phy_config_timer);
+	struct atl1c_adapter *adapter;
+	struct net_device *netdev;
+
+	adapter = container_of(work, struct atl1c_adapter, common_task);
+	netdev = adapter->netdev;
+
+	if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
+		netif_device_detach(netdev);
+		atl1c_down(adapter);
+		atl1c_up(adapter);
+		netif_device_attach(netdev);
+		return;
+	}
+
+	if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE)
+		atl1c_check_link_status(adapter);
+
+	return;
 }
 
-static void atl1c_cancel_work(struct atl1c_adapter *adapter)
+
+static void atl1c_del_timer(struct atl1c_adapter *adapter)
 {
-	cancel_work_sync(&adapter->reset_task);
-	cancel_work_sync(&adapter->link_chg_task);
+	del_timer_sync(&adapter->phy_config_timer);
 }
 
+
 /*
  * atl1c_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
@@ -334,7 +327,8 @@
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
 	/* Do the reset outside of interrupt context */
-	schedule_work(&adapter->reset_task);
+	adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+	schedule_work(&adapter->common_task);
 }
 
 /*
@@ -1536,7 +1530,8 @@
 			/* reset MAC */
 			hw->intr_mask &= ~ISR_ERROR;
 			AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
-			schedule_work(&adapter->reset_task);
+			adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+			schedule_work(&adapter->common_task);
 			break;
 		}
 
@@ -1981,8 +1976,6 @@
 		else {
 			use_tpd = atl1c_get_tpd(adapter, type);
 			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
-			use_tpd = atl1c_get_tpd(adapter, type);
-			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
 		}
 		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
 		buffer_info->length = buf_len - mapped_len;
@@ -2200,8 +2193,7 @@
 	struct net_device *netdev = adapter->netdev;
 
 	atl1c_del_timer(adapter);
-	atl1c_cancel_work(adapter);
-
+	adapter->work_event = 0; /* clear all event */
 	/* signal that we're down so the interrupt handler does not
 	 * reschedule our watchdog timer */
 	set_bit(__AT_DOWN, &adapter->flags);
@@ -2601,8 +2593,8 @@
 			adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
 
 	atl1c_hw_set_mac_addr(&adapter->hw);
-	INIT_WORK(&adapter->reset_task, atl1c_reset_task);
-	INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task);
+	INIT_WORK(&adapter->common_task, atl1c_common_task);
+	adapter->work_event = 0;
 	err = register_netdev(netdev);
 	if (err) {
 		dev_err(&pdev->dev, "register netdevice failed\n");
--- linux-ec2-2.6.32.orig/drivers/net/bonding/bond_ipv6.c
+++ linux-ec2-2.6.32/drivers/net/bonding/bond_ipv6.c
@@ -66,6 +66,13 @@
 	};
 	struct sk_buff *skb;
 
+	/* The Ethernet header is built in ndisc_send_skb(), not
+	 * ndisc_build_skb(), so we cannot insert a VLAN tag.  Only an
+	 * out-of-line tag inserted by the hardware will work.
+	 */
+	if (vlan_id && !(slave_dev->features & NETIF_F_HW_VLAN_TX))
+		return;
+
 	icmp6h.icmp6_router = router;
 	icmp6h.icmp6_solicited = 0;
 	icmp6h.icmp6_override = 1;
@@ -84,7 +91,7 @@
 	}
 
 	if (vlan_id) {
-		skb = vlan_put_tag(skb, vlan_id);
+		skb = __vlan_hwaccel_put_tag(skb, vlan_id);
 		if (!skb) {
 			pr_err(DRV_NAME ": failed to insert VLAN tag\n");
 			return;
--- linux-ec2-2.6.32.orig/drivers/net/bonding/bond_alb.c
+++ linux-ec2-2.6.32/drivers/net/bonding/bond_alb.c
@@ -370,6 +370,13 @@
 		goto out;
 	}
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
+	if (!pskb_may_pull(skb, arp_hdr_len(bond_dev)))
+		goto out;
+
 	if (skb->len < sizeof(struct arp_pkt)) {
 		pr_debug("Packet is too small to be an ARP\n");
 		goto out;
--- linux-ec2-2.6.32.orig/drivers/net/bonding/bond_3ad.c
+++ linux-ec2-2.6.32/drivers/net/bonding/bond_3ad.c
@@ -2451,6 +2451,13 @@
 	if (!(dev->flags & IFF_MASTER))
 		goto out;
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out;
+
+	if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
+		goto out;
+
 	read_lock(&bond->lock);
 	slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev),
 					orig_dev);
--- linux-ec2-2.6.32.orig/drivers/net/bonding/bond_main.c
+++ linux-ec2-2.6.32/drivers/net/bonding/bond_main.c
@@ -2692,6 +2692,10 @@
 	if (!slave || !slave_do_arp_validate(bond, slave))
 		goto out_unlock;
 
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		goto out_unlock;
+
 	if (!pskb_may_pull(skb, arp_hdr_len(dev)))
 		goto out_unlock;
 
--- linux-ec2-2.6.32.orig/drivers/net/e1000e/netdev.c
+++ linux-ec2-2.6.32/drivers/net/e1000e/netdev.c
@@ -482,14 +482,24 @@
 
 		length = le16_to_cpu(rx_desc->length);
 
-		/* !EOP means multiple descriptors were used to store a single
-		 * packet, also make sure the frame isn't just CRC only */
-		if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
+		/*
+		 * !EOP means multiple descriptors were used to store a single
+		 * packet, if that's the case we need to toss it.  In fact, we
+		 * need to toss every packet with the EOP bit clear and the
+		 * next frame that _does_ have the EOP bit set, as it is by
+		 * definition only a frame fragment
+		 */
+		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+			adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
 			/* All receives must fit into a single buffer */
 			e_dbg("%s: Receive packet consumed multiple buffers\n",
 			      netdev->name);
 			/* recycle */
 			buffer_info->skb = skb;
+			if (status & E1000_RXD_STAT_EOP)
+				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 			goto next_desc;
 		}
 
@@ -655,6 +665,8 @@
 				i = 0;
 		}
 
+		if (i == tx_ring->next_to_use)
+			break;
 		eop = tx_ring->buffer_info[i].next_to_watch;
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
 	}
@@ -747,10 +759,16 @@
 				 PCI_DMA_FROMDEVICE);
 		buffer_info->dma = 0;
 
-		if (!(staterr & E1000_RXD_STAT_EOP)) {
+		/* see !EOP comment in other rx routine */
+		if (!(staterr & E1000_RXD_STAT_EOP))
+			adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+		if (adapter->flags2 & FLAG2_IS_DISCARDING) {
 			e_dbg("%s: Packet Split buffers didn't pick up the "
 			      "full packet\n", netdev->name);
 			dev_kfree_skb_irq(skb);
+			if (staterr & E1000_RXD_STAT_EOP)
+				adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 			goto next_desc;
 		}
 
@@ -1120,6 +1138,7 @@
 
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
+	adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 
 	writel(0, adapter->hw.hw_addr + rx_ring->head);
 	writel(0, adapter->hw.hw_addr + rx_ring->tail);
@@ -2330,18 +2349,6 @@
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
 	switch (adapter->rx_buffer_len) {
-	case 256:
-		rctl |= E1000_RCTL_SZ_256;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
-	case 512:
-		rctl |= E1000_RCTL_SZ_512;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
-	case 1024:
-		rctl |= E1000_RCTL_SZ_1024;
-		rctl &= ~E1000_RCTL_BSEX;
-		break;
 	case 2048:
 	default:
 		rctl |= E1000_RCTL_SZ_2048;
@@ -3066,13 +3073,18 @@
 
 	/* disable SERR in case the MSI write causes a master abort */
 	pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
-	pci_write_config_word(adapter->pdev, PCI_COMMAND,
-			      pci_cmd & ~PCI_COMMAND_SERR);
+	if (pci_cmd & PCI_COMMAND_SERR)
+		pci_write_config_word(adapter->pdev, PCI_COMMAND,
+				      pci_cmd & ~PCI_COMMAND_SERR);
 
 	err = e1000_test_msi_interrupt(adapter);
 
-	/* restore previous setting of command word */
-	pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+	/* re-enable SERR */
+	if (pci_cmd & PCI_COMMAND_SERR) {
+		pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd);
+		pci_cmd |= PCI_COMMAND_SERR;
+		pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd);
+	}
 
 	/* success ! */
 	if (!err)
@@ -4321,13 +4333,7 @@
 	 * fragmented skbs
 	 */
 
-	if (max_frame <= 256)
-		adapter->rx_buffer_len = 256;
-	else if (max_frame <= 512)
-		adapter->rx_buffer_len = 512;
-	else if (max_frame <= 1024)
-		adapter->rx_buffer_len = 1024;
-	else if (max_frame <= 2048)
+	if (max_frame <= 2048)
 		adapter->rx_buffer_len = 2048;
 	else
 		adapter->rx_buffer_len = 4096;
@@ -5180,7 +5186,8 @@
 		/* APME bit in EEPROM is mapped to WUC.APME */
 		eeprom_data = er32(WUC);
 		eeprom_apme_mask = E1000_WUC_APME;
-		if (eeprom_data & E1000_WUC_PHY_WAKE)
+		if ((hw->mac.type > e1000_ich10lan) &&
+		    (eeprom_data & E1000_WUC_PHY_WAKE))
 			adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP;
 	} else if (adapter->flags & FLAG_APME_IN_CTRL3) {
 		if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
@@ -5361,6 +5368,7 @@
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan },
 
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },
@@ -5371,6 +5379,7 @@
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V_2), board_ich9lan },
 
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan },
--- linux-ec2-2.6.32.orig/drivers/net/e1000e/e1000.h
+++ linux-ec2-2.6.32/drivers/net/e1000e/e1000.h
@@ -417,6 +417,7 @@
 /* CRC Stripping defines */
 #define FLAG2_CRC_STRIPPING               (1 << 0)
 #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
+#define FLAG2_IS_DISCARDING               (1 << 2)
 
 #define E1000_RX_DESC_PS(R, i)	    \
 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
--- linux-ec2-2.6.32.orig/drivers/net/e1000e/ich8lan.c
+++ linux-ec2-2.6.32/drivers/net/e1000e/ich8lan.c
@@ -274,6 +274,16 @@
 	phy->ops.write_phy_reg_locked = e1000_write_phy_reg_hv_locked;
 	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
+	/*
+	 * Reset the PHY before any acccess to it.  Doing so, ensures that
+	 * the PHY is in a known good state before we read/write PHY registers.
+	 * The generic reset is sufficient here, because we haven't determined
+	 * the PHY type yet.
+	 */
+	ret_val = e1000e_phy_hw_reset_generic(hw);
+	if (ret_val)
+		goto out;
+
 	phy->id = e1000_phy_unknown;
 	e1000e_get_phy_id(hw);
 	phy->type = e1000e_get_phy_type_from_id(phy->id);
@@ -287,6 +297,7 @@
 		phy->ops.commit_phy = e1000e_phy_sw_reset;
 	}
 
+ out:
 	return ret_val;
 }
 
@@ -3209,6 +3220,7 @@
 	u32 phy_ctrl;
 
 	switch (hw->mac.type) {
+	case e1000_ich8lan:
 	case e1000_ich9lan:
 	case e1000_ich10lan:
 	case e1000_pchlan:
--- linux-ec2-2.6.32.orig/drivers/net/e1000e/hw.h
+++ linux-ec2-2.6.32/drivers/net/e1000e/hw.h
@@ -304,7 +304,7 @@
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
 #define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE	0x140E
+#define E1000_KMRNCTRLSTA_K1_ENABLE	0x0002
 #define E1000_KMRNCTRLSTA_K1_DISABLE	0x1400
 
 #define IFE_PHY_EXTENDED_STATUS_CONTROL	0x10
@@ -356,6 +356,7 @@
 #define E1000_DEV_ID_80003ES2LAN_COPPER_SPT	0x10BA
 #define E1000_DEV_ID_80003ES2LAN_SERDES_SPT	0x10BB
 
+#define E1000_DEV_ID_ICH8_82567V_3		0x1501
 #define E1000_DEV_ID_ICH8_IGP_M_AMT		0x1049
 #define E1000_DEV_ID_ICH8_IGP_AMT		0x104A
 #define E1000_DEV_ID_ICH8_IGP_C			0x104B
@@ -368,6 +369,7 @@
 #define E1000_DEV_ID_ICH9_IGP_M_AMT		0x10F5
 #define E1000_DEV_ID_ICH9_IGP_M			0x10BF
 #define E1000_DEV_ID_ICH9_IGP_M_V		0x10CB
+#define E1000_DEV_ID_ICH9_IGP_M_V_2		0x10BE
 #define E1000_DEV_ID_ICH9_IGP_C			0x294C
 #define E1000_DEV_ID_ICH9_IFE			0x10C0
 #define E1000_DEV_ID_ICH9_IFE_GT		0x10C3
--- linux-ec2-2.6.32.orig/drivers/net/tokenring/tms380tr.c
+++ linux-ec2-2.6.32/drivers/net/tokenring/tms380tr.c
@@ -1364,6 +1364,8 @@
 	return (-1);
 }
 
+MODULE_FIRMWARE("tms380tr.bin");
+
 /*
  * Starts bring up diagnostics of token ring adapter and evaluates
  * diagnostic results.
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_phy.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_phy.h
@@ -43,7 +43,6 @@
 
 s32  igb_check_downshift(struct e1000_hw *hw);
 s32  igb_check_reset_block(struct e1000_hw *hw);
-s32  igb_copper_link_autoneg(struct e1000_hw *hw);
 s32  igb_copper_link_setup_igp(struct e1000_hw *hw);
 s32  igb_copper_link_setup_m88(struct e1000_hw *hw);
 s32  igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
@@ -57,10 +56,19 @@
 s32  igb_phy_hw_reset(struct e1000_hw *hw);
 s32  igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  igb_set_d3_lplu_state(struct e1000_hw *hw, bool active);
+s32  igb_setup_copper_link(struct e1000_hw *hw);
 s32  igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
 s32  igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
 				u32 usec_interval, bool *success);
 s32  igb_phy_init_script_igp3(struct e1000_hw *hw);
+s32  igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+s32  igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
+s32  igb_copper_link_setup_82580(struct e1000_hw *hw);
+s32  igb_get_phy_info_82580(struct e1000_hw *hw);
+s32  igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
+s32  igb_get_cable_length_82580(struct e1000_hw *hw);
 
 /* IGP01E1000 Specific Registers */
 #define IGP01E1000_PHY_PORT_CONFIG        0x10 /* Port Config */
@@ -75,6 +83,33 @@
 #define IGP01E1000_PSCR_FORCE_MDI_MDIX    0x2000 /* 0=MDI, 1=MDIX */
 #define IGP01E1000_PSCFR_SMART_SPEED      0x0080
 
+#define I82580_ADDR_REG                   16
+#define I82580_CFG_REG                    22
+#define I82580_CFG_ASSERT_CRS_ON_TX       (1 << 15)
+#define I82580_CFG_ENABLE_DOWNSHIFT       (3 << 10) /* auto downshift 100/10 */
+#define I82580_CTRL_REG                   23
+#define I82580_CTRL_DOWNSHIFT_MASK        (7 << 10)
+
+/* 82580 specific PHY registers */
+#define I82580_PHY_CTRL_2            18
+#define I82580_PHY_LBK_CTRL          19
+#define I82580_PHY_STATUS_2          26
+#define I82580_PHY_DIAG_STATUS       31
+
+/* I82580 PHY Status 2 */
+#define I82580_PHY_STATUS2_REV_POLARITY   0x0400
+#define I82580_PHY_STATUS2_MDIX           0x0800
+#define I82580_PHY_STATUS2_SPEED_MASK     0x0300
+#define I82580_PHY_STATUS2_SPEED_1000MBPS 0x0200
+#define I82580_PHY_STATUS2_SPEED_100MBPS  0x0100
+
+/* I82580 PHY Control 2 */
+#define I82580_PHY_CTRL2_AUTO_MDIX        0x0400
+#define I82580_PHY_CTRL2_FORCE_MDI_MDIX   0x0200
+
+/* I82580 PHY Diagnostics Status */
+#define I82580_DSTATUS_CABLE_LENGTH       0x03FC
+#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
 /* Enable flexible speed on link-up */
 #define IGP02E1000_PM_D0_LPLU             0x0002 /* For D0a states */
 #define IGP02E1000_PM_D3_LPLU             0x0004 /* For all other states */
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_mbx.c
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_mbx.c
@@ -143,12 +143,16 @@
 	if (!countdown || !mbx->ops.check_for_msg)
 		goto out;
 
-	while (mbx->ops.check_for_msg(hw, mbx_id)) {
+	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
 			break;
 		udelay(mbx->usec_delay);
 	}
+
+	/* if we failed, all future posted messages fail until reset */
+	if (!countdown)
+		mbx->timeout = 0;
 out:
 	return countdown ? 0 : -E1000_ERR_MBX;
 }
@@ -168,12 +172,16 @@
 	if (!countdown || !mbx->ops.check_for_ack)
 		goto out;
 
-	while (mbx->ops.check_for_ack(hw, mbx_id)) {
+	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
 			break;
 		udelay(mbx->usec_delay);
 	}
+
+	/* if we failed, all future posted messages fail until reset */
+	if (!countdown)
+		mbx->timeout = 0;
 out:
 	return countdown ? 0 : -E1000_ERR_MBX;
 }
@@ -217,12 +225,13 @@
 static s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
 {
 	struct e1000_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = 0;
+	s32 ret_val = -E1000_ERR_MBX;
 
-	if (!mbx->ops.write)
+	/* exit if either we can't write or there isn't a defined timeout */
+	if (!mbx->ops.write || !mbx->timeout)
 		goto out;
 
-	/* send msg*/
+	/* send msg */
 	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
 
 	/* if msg sent wait until we receive an ack */
@@ -305,6 +314,30 @@
 }
 
 /**
+ *  igb_obtain_mbx_lock_pf - obtain mailbox lock
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  return SUCCESS if we obtained the mailbox lock
+ **/
+static s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
+{
+	s32 ret_val = -E1000_ERR_MBX;
+	u32 p2v_mailbox;
+
+
+	/* Take ownership of the buffer */
+	wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
+
+	/* reserve mailbox for vf use */
+	p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
+	if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
+		ret_val = 0;
+
+	return ret_val;
+}
+
+/**
  *  igb_write_mbx_pf - Places a message in the mailbox
  *  @hw: pointer to the HW structure
  *  @msg: The message buffer
@@ -316,27 +349,17 @@
 static s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
                               u16 vf_number)
 {
-	u32 p2v_mailbox;
-	s32 ret_val = 0;
+	s32 ret_val;
 	u16 i;
 
-	/* Take ownership of the buffer */
-	wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
-
-	/* Make sure we have ownership now... */
-	p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
-	if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) {
-		/* failed to grab ownership */
-		ret_val = -E1000_ERR_MBX;
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
+	if (ret_val)
 		goto out_no_write;
-	}
 
-	/*
-	 * flush any ack or msg which may already be in the queue
-	 * as they are likely the result of an error
-	 */
-	igb_check_for_ack_pf(hw, vf_number);
+	/* flush msg and acks as we are overwriting the message buffer */
 	igb_check_for_msg_pf(hw, vf_number);
+	igb_check_for_ack_pf(hw, vf_number);
 
 	/* copy the caller specified message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
@@ -367,20 +390,13 @@
 static s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
                              u16 vf_number)
 {
-	u32 p2v_mailbox;
-	s32 ret_val = 0;
+	s32 ret_val;
 	u16 i;
 
-	/* Take ownership of the buffer */
-	wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
-
-	/* Make sure we have ownership now... */
-	p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
-	if (!(p2v_mailbox & E1000_P2VMAILBOX_PFU)) {
-		/* failed to grab ownership */
-		ret_val = -E1000_ERR_MBX;
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
+	if (ret_val)
 		goto out_no_read;
-	}
 
 	/* copy the message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
@@ -392,8 +408,6 @@
 	/* update stats */
 	hw->mbx.stats.msgs_rx++;
 
-	ret_val = 0;
-
 out_no_read:
 	return ret_val;
 }
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_82575.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_82575.h
@@ -38,6 +38,11 @@
 
 #define E1000_RAR_ENTRIES_82575   16
 #define E1000_RAR_ENTRIES_82576   24
+#define E1000_RAR_ENTRIES_82580   24
+
+#define E1000_SW_SYNCH_MB              0x00000100
+#define E1000_STAT_DEV_RST_SET         0x00100000
+#define E1000_CTRL_DEV_RST             0x20000000
 
 /* SRRCTL bit definitions */
 #define E1000_SRRCTL_BSIZEPKT_SHIFT                     10 /* Shift _right_ */
@@ -66,6 +71,8 @@
     E1000_EICR_RX_QUEUE3)
 
 /* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
+#define E1000_IMIREXT_SIZE_BP     0x00001000  /* Packet size bypass */
+#define E1000_IMIREXT_CTRL_BP     0x00080000  /* Bypass check of ctrl bits */
 
 /* Receive Descriptor - Advanced */
 union e1000_adv_rx_desc {
@@ -98,6 +105,7 @@
 
 #define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
 #define E1000_RXDADV_HDRBUFLEN_SHIFT     5
+#define E1000_RXDADV_STAT_TS             0x10000 /* Pkt was time stamped */
 
 /* Transmit Descriptor - Advanced */
 union e1000_adv_tx_desc {
@@ -167,6 +175,18 @@
 #define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
 #define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
 
+/* ETQF register bit definitions */
+#define E1000_ETQF_FILTER_ENABLE   (1 << 26)
+#define E1000_ETQF_1588            (1 << 30)
+
+/* FTQF register bit definitions */
+#define E1000_FTQF_VF_BP               0x00008000
+#define E1000_FTQF_1588_TIME_STAMP     0x08000000
+#define E1000_FTQF_MASK                0xF0000000
+#define E1000_FTQF_MASK_PROTO_BP       0x10000000
+#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
+
+#define E1000_NVM_APME_82575          0x0400
 #define MAX_NUM_VFS                   8
 
 #define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31)  /* global VF LB enable */
@@ -202,9 +222,21 @@
 #define E1000_IOVCTL 0x05BBC
 #define E1000_IOVCTL_REUSE_VFQ 0x00000001
 
+#define E1000_RPLOLR_STRVLAN   0x40000000
+#define E1000_RPLOLR_STRCRC    0x80000000
+
+#define E1000_DTXCTL_8023LL     0x0004
+#define E1000_DTXCTL_VLAN_ADDED 0x0008
+#define E1000_DTXCTL_OOS_ENABLE 0x0010
+#define E1000_DTXCTL_MDP_EN     0x0020
+#define E1000_DTXCTL_SPOOF_INT  0x0040
+
 #define ALL_QUEUES   0xFFFF
 
+/* RX packet buffer size defines */
+#define E1000_RXPBS_SIZE_MASK_82576  0x0000007F
 void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
 void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
+u16 igb_rxpbs_adjust_82580(u32 data);
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_nvm.c
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_nvm.c
@@ -78,9 +78,7 @@
 	u32 mask;
 
 	mask = 0x01 << (count - 1);
-	if (nvm->type == e1000_nvm_eeprom_microwire)
-		eecd &= ~E1000_EECD_DO;
-	else if (nvm->type == e1000_nvm_eeprom_spi)
+	if (nvm->type == e1000_nvm_eeprom_spi)
 		eecd |= E1000_EECD_DO;
 
 	do {
@@ -220,22 +218,7 @@
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	u32 eecd = rd32(E1000_EECD);
 
-	if (nvm->type == e1000_nvm_eeprom_microwire) {
-		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
-		wr32(E1000_EECD, eecd);
-		wrfl();
-		udelay(nvm->delay_usec);
-
-		igb_raise_eec_clk(hw, &eecd);
-
-		/* Select EEPROM */
-		eecd |= E1000_EECD_CS;
-		wr32(E1000_EECD, eecd);
-		wrfl();
-		udelay(nvm->delay_usec);
-
-		igb_lower_eec_clk(hw, &eecd);
-	} else if (nvm->type == e1000_nvm_eeprom_spi) {
+	if (nvm->type == e1000_nvm_eeprom_spi) {
 		/* Toggle CS to flush commands */
 		eecd |= E1000_EECD_CS;
 		wr32(E1000_EECD, eecd);
@@ -263,12 +246,6 @@
 		/* Pull CS high */
 		eecd |= E1000_EECD_CS;
 		igb_lower_eec_clk(hw, &eecd);
-	} else if (hw->nvm.type == e1000_nvm_eeprom_microwire) {
-		/* CS on Microcwire is active-high */
-		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
-		wr32(E1000_EECD, eecd);
-		igb_raise_eec_clk(hw, &eecd);
-		igb_lower_eec_clk(hw, &eecd);
 	}
 }
 
@@ -304,14 +281,7 @@
 	u8 spi_stat_reg;
 
 
-	if (nvm->type == e1000_nvm_eeprom_microwire) {
-		/* Clear SK and DI */
-		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
-		wr32(E1000_EECD, eecd);
-		/* Set CS */
-		eecd |= E1000_EECD_CS;
-		wr32(E1000_EECD, eecd);
-	} else if (nvm->type == e1000_nvm_eeprom_spi) {
+	if (nvm->type == e1000_nvm_eeprom_spi) {
 		/* Clear SK and CS */
 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
 		wr32(E1000_EECD, eecd);
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_mbx.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_mbx.h
@@ -58,10 +58,12 @@
 #define E1000_VT_MSGINFO_MASK     (0xFF << E1000_VT_MSGINFO_SHIFT)
 
 #define E1000_VF_RESET            0x01 /* VF requests reset */
-#define E1000_VF_SET_MAC_ADDR     0x02 /* VF requests PF to set MAC addr */
-#define E1000_VF_SET_MULTICAST    0x03 /* VF requests PF to set MC addr */
-#define E1000_VF_SET_VLAN         0x04 /* VF requests PF to set VLAN */
-#define E1000_VF_SET_LPE          0x05 /* VF requests PF to set VMOLR.LPE */
+#define E1000_VF_SET_MAC_ADDR     0x02 /* VF requests to set MAC addr */
+#define E1000_VF_SET_MULTICAST    0x03 /* VF requests to set MC addr */
+#define E1000_VF_SET_VLAN         0x04 /* VF requests to set VLAN */
+#define E1000_VF_SET_LPE          0x05 /* VF requests to set VMOLR.LPE */
+#define E1000_VF_SET_PROMISC      0x06 /*VF requests to clear VMOLR.ROPE/MPME*/
+#define E1000_VF_SET_PROMISC_MULTICAST    (0x02 << E1000_VT_MSGINFO_SHIFT)
 
 #define E1000_PF_CONTROL_MSG      0x0100 /* PF control message */
 
--- linux-ec2-2.6.32.orig/drivers/net/igb/igb_main.c
+++ linux-ec2-2.6.32/drivers/net/igb/igb_main.c
@@ -49,7 +49,7 @@
 #endif
 #include "igb.h"
 
-#define DRV_VERSION "1.3.16-k2"
+#define DRV_VERSION "2.1.0-k2"
 char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
@@ -61,8 +61,14 @@
 };
 
 static struct pci_device_id igb_pci_tbl[] = {
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 },
@@ -81,6 +87,7 @@
 static int igb_setup_all_rx_resources(struct igb_adapter *);
 static void igb_free_all_tx_resources(struct igb_adapter *);
 static void igb_free_all_rx_resources(struct igb_adapter *);
+static void igb_setup_mrqc(struct igb_adapter *);
 void igb_update_stats(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void __devexit igb_remove(struct pci_dev *pdev);
@@ -89,7 +96,6 @@
 static int igb_close(struct net_device *);
 static void igb_configure_tx(struct igb_adapter *);
 static void igb_configure_rx(struct igb_adapter *);
-static void igb_setup_rctl(struct igb_adapter *);
 static void igb_clean_all_tx_rings(struct igb_adapter *);
 static void igb_clean_all_rx_rings(struct igb_adapter *);
 static void igb_clean_tx_ring(struct igb_ring *);
@@ -98,28 +104,22 @@
 static void igb_update_phy_info(unsigned long);
 static void igb_watchdog(unsigned long);
 static void igb_watchdog_task(struct work_struct *);
-static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *,
-					   struct net_device *,
-					   struct igb_ring *);
-static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb,
-				      struct net_device *);
+static netdev_tx_t igb_xmit_frame_adv(struct sk_buff *skb, struct net_device *);
 static struct net_device_stats *igb_get_stats(struct net_device *);
 static int igb_change_mtu(struct net_device *, int);
 static int igb_set_mac(struct net_device *, void *);
+static void igb_set_uta(struct igb_adapter *adapter);
 static irqreturn_t igb_intr(int irq, void *);
 static irqreturn_t igb_intr_msi(int irq, void *);
 static irqreturn_t igb_msix_other(int irq, void *);
-static irqreturn_t igb_msix_rx(int irq, void *);
-static irqreturn_t igb_msix_tx(int irq, void *);
+static irqreturn_t igb_msix_ring(int irq, void *);
 #ifdef CONFIG_IGB_DCA
-static void igb_update_rx_dca(struct igb_ring *);
-static void igb_update_tx_dca(struct igb_ring *);
+static void igb_update_dca(struct igb_q_vector *);
 static void igb_setup_dca(struct igb_adapter *);
 #endif /* CONFIG_IGB_DCA */
-static bool igb_clean_tx_irq(struct igb_ring *);
+static bool igb_clean_tx_irq(struct igb_q_vector *);
 static int igb_poll(struct napi_struct *, int);
-static bool igb_clean_rx_irq_adv(struct igb_ring *, int *, int);
-static void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
+static bool igb_clean_rx_irq_adv(struct igb_q_vector *, int *, int);
 static int igb_ioctl(struct net_device *, struct ifreq *, int cmd);
 static void igb_tx_timeout(struct net_device *);
 static void igb_reset_task(struct work_struct *);
@@ -127,57 +127,13 @@
 static void igb_vlan_rx_add_vid(struct net_device *, u16);
 static void igb_vlan_rx_kill_vid(struct net_device *, u16);
 static void igb_restore_vlan(struct igb_adapter *);
+static void igb_rar_set_qsel(struct igb_adapter *, u8 *, u32 , u8);
 static void igb_ping_all_vfs(struct igb_adapter *);
 static void igb_msg_task(struct igb_adapter *);
-static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
-static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
 static void igb_vmm_control(struct igb_adapter *);
-static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
+static int igb_set_vf_mac(struct igb_adapter *, int, unsigned char *);
 static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
 
-static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
-{
-	u32 reg_data;
-
-	reg_data = rd32(E1000_VMOLR(vfn));
-	reg_data |= E1000_VMOLR_BAM |	 /* Accept broadcast */
-	            E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
-	            E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
-	            E1000_VMOLR_AUPE |   /* Accept untagged packets */
-	            E1000_VMOLR_STRVLAN; /* Strip vlan tags */
-	wr32(E1000_VMOLR(vfn), reg_data);
-}
-
-static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
-                                 int vfn)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vmolr;
-
-	/* if it isn't the PF check to see if VFs are enabled and
-	 * increase the size to support vlan tags */
-	if (vfn < adapter->vfs_allocated_count &&
-	    adapter->vf_data[vfn].vlans_enabled)
-		size += VLAN_TAG_SIZE;
-
-	vmolr = rd32(E1000_VMOLR(vfn));
-	vmolr &= ~E1000_VMOLR_RLPML_MASK;
-	vmolr |= size | E1000_VMOLR_LPE;
-	wr32(E1000_VMOLR(vfn), vmolr);
-
-	return 0;
-}
-
-static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
-{
-	u32 reg_data;
-
-	reg_data = rd32(E1000_RAH(entry));
-	reg_data &= ~E1000_RAH_POOL_MASK;
-	reg_data |= E1000_RAH_POOL_1 << pool;;
-	wr32(E1000_RAH(entry), reg_data);
-}
-
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
 static int igb_resume(struct pci_dev *);
@@ -228,46 +184,12 @@
 	.err_handler = &igb_err_handler
 };
 
-static int global_quad_port_a; /* global quad port a indication */
-
 MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
 MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
 /**
- * Scale the NIC clock cycle by a large factor so that
- * relatively small clock corrections can be added or
- * substracted at each clock tick. The drawbacks of a
- * large factor are a) that the clock register overflows
- * more quickly (not such a big deal) and b) that the
- * increment per tick has to fit into 24 bits.
- *
- * Note that
- *   TIMINCA = IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS *
- *             IGB_TSYNC_SCALE
- *   TIMINCA += TIMINCA * adjustment [ppm] / 1e9
- *
- * The base scale factor is intentionally a power of two
- * so that the division in %struct timecounter can be done with
- * a shift.
- */
-#define IGB_TSYNC_SHIFT (19)
-#define IGB_TSYNC_SCALE (1<<IGB_TSYNC_SHIFT)
-
-/**
- * The duration of one clock cycle of the NIC.
- *
- * @todo This hard-coded value is part of the specification and might change
- * in future hardware revisions. Add revision check.
- */
-#define IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS 16
-
-#if (IGB_TSYNC_SCALE * IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS) >= (1<<24)
-# error IGB_TSYNC_SCALE and/or IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS are too large to fit into TIMINCA
-#endif
-
-/**
  * igb_read_clock - read raw cycle counter (to be used by time counter)
  */
 static cycle_t igb_read_clock(const struct cyclecounter *tc)
@@ -275,11 +197,21 @@
 	struct igb_adapter *adapter =
 		container_of(tc, struct igb_adapter, cycles);
 	struct e1000_hw *hw = &adapter->hw;
-	u64 stamp;
+	u64 stamp = 0;
+	int shift = 0;
 
-	stamp =  rd32(E1000_SYSTIML);
-	stamp |= (u64)rd32(E1000_SYSTIMH) << 32ULL;
+	/*
+	 * The timestamp latches on lowest register read. For the 82580
+	 * the lowest register is SYSTIMR instead of SYSTIML.  However we never
+	 * adjusted TIMINCA so SYSTIMR will just read as all 0s so ignore it.
+	 */
+	if (hw->mac.type == e1000_82580) {
+		stamp = rd32(E1000_SYSTIMR) >> 8;
+		shift = IGB_82580_TSYNC_SHIFT;
+	}
 
+	stamp |= (u64)rd32(E1000_SYSTIML) << shift;
+	stamp |= (u64)rd32(E1000_SYSTIMH) << (shift + 32);
 	return stamp;
 }
 
@@ -320,17 +252,6 @@
 #endif
 
 /**
- * igb_desc_unused - calculate if we have unused descriptors
- **/
-static int igb_desc_unused(struct igb_ring *ring)
-{
-	if (ring->next_to_clean > ring->next_to_use)
-		return ring->next_to_clean - ring->next_to_use - 1;
-
-	return ring->count + ring->next_to_clean - ring->next_to_use - 1;
-}
-
-/**
  * igb_init_module - Driver Registration Routine
  *
  * igb_init_module is the first routine called when the driver is
@@ -344,12 +265,9 @@
 
 	printk(KERN_INFO "%s\n", igb_copyright);
 
-	global_quad_port_a = 0;
-
 #ifdef CONFIG_IGB_DCA
 	dca_register_notify(&dca_notifier);
 #endif
-
 	ret = pci_register_driver(&igb_driver);
 	return ret;
 }
@@ -382,8 +300,8 @@
  **/
 static void igb_cache_ring_register(struct igb_adapter *adapter)
 {
-	int i;
-	unsigned int rbase_offset = adapter->vfs_allocated_count;
+	int i = 0, j = 0;
+	u32 rbase_offset = adapter->vfs_allocated_count;
 
 	switch (adapter->hw.mac.type) {
 	case e1000_82576:
@@ -392,23 +310,37 @@
 		 * In order to avoid collision we start at the first free queue
 		 * and continue consuming queues in the same sequence
 		 */
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i].reg_idx = rbase_offset +
-			                              Q_IDX_82576(i);
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].reg_idx = rbase_offset +
-			                              Q_IDX_82576(i);
-		break;
+		if (adapter->vfs_allocated_count) {
+			for (; i < adapter->rss_queues; i++)
+				adapter->rx_ring[i].reg_idx = rbase_offset +
+				                              Q_IDX_82576(i);
+			for (; j < adapter->rss_queues; j++)
+				adapter->tx_ring[j].reg_idx = rbase_offset +
+				                              Q_IDX_82576(j);
+		}
 	case e1000_82575:
+	case e1000_82580:
 	default:
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			adapter->rx_ring[i].reg_idx = i;
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			adapter->tx_ring[i].reg_idx = i;
+		for (; i < adapter->num_rx_queues; i++)
+			adapter->rx_ring[i].reg_idx = rbase_offset + i;
+		for (; j < adapter->num_tx_queues; j++)
+			adapter->tx_ring[j].reg_idx = rbase_offset + j;
 		break;
 	}
 }
 
+static void igb_free_queues(struct igb_adapter *adapter)
+{
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+
+	adapter->tx_ring = NULL;
+	adapter->rx_ring = NULL;
+
+	adapter->num_rx_queues = 0;
+	adapter->num_tx_queues = 0;
+}
+
 /**
  * igb_alloc_queues - Allocate memory for all rings
  * @adapter: board private structure to initialize
@@ -423,59 +355,61 @@
 	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
 				   sizeof(struct igb_ring), GFP_KERNEL);
 	if (!adapter->tx_ring)
-		return -ENOMEM;
+		goto err;
 
 	adapter->rx_ring = kcalloc(adapter->num_rx_queues,
 				   sizeof(struct igb_ring), GFP_KERNEL);
-	if (!adapter->rx_ring) {
-		kfree(adapter->tx_ring);
-		return -ENOMEM;
-	}
-
-	adapter->rx_ring->buddy = adapter->tx_ring;
+	if (!adapter->rx_ring)
+		goto err;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
 		struct igb_ring *ring = &(adapter->tx_ring[i]);
 		ring->count = adapter->tx_ring_count;
-		ring->adapter = adapter;
 		ring->queue_index = i;
+		ring->pdev = adapter->pdev;
+		ring->netdev = adapter->netdev;
+		/* For 82575, context index must be unique per ring. */
+		if (adapter->hw.mac.type == e1000_82575)
+			ring->flags = IGB_RING_FLAG_TX_CTX_IDX;
 	}
+
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		struct igb_ring *ring = &(adapter->rx_ring[i]);
 		ring->count = adapter->rx_ring_count;
-		ring->adapter = adapter;
 		ring->queue_index = i;
-		ring->itr_register = E1000_ITR;
-
-		/* set a default napi handler for each rx_ring */
-		netif_napi_add(adapter->netdev, &ring->napi, igb_poll, 64);
+		ring->pdev = adapter->pdev;
+		ring->netdev = adapter->netdev;
+		ring->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+		ring->flags = IGB_RING_FLAG_RX_CSUM; /* enable rx checksum */
+		/* set flag indicating ring supports SCTP checksum offload */
+		if (adapter->hw.mac.type >= e1000_82576)
+			ring->flags |= IGB_RING_FLAG_RX_SCTP_CSUM;
 	}
 
 	igb_cache_ring_register(adapter);
-	return 0;
-}
-
-static void igb_free_queues(struct igb_adapter *adapter)
-{
-	int i;
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		netif_napi_del(&adapter->rx_ring[i].napi);
+	return 0;
 
-	adapter->num_rx_queues = 0;
-	adapter->num_tx_queues = 0;
+err:
+	igb_free_queues(adapter);
 
-	kfree(adapter->tx_ring);
-	kfree(adapter->rx_ring);
+	return -ENOMEM;
 }
 
 #define IGB_N0_QUEUE -1
-static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
-			      int tx_queue, int msix_vector)
+static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
 {
 	u32 msixbm = 0;
+	struct igb_adapter *adapter = q_vector->adapter;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ivar, index;
+	int rx_queue = IGB_N0_QUEUE;
+	int tx_queue = IGB_N0_QUEUE;
+
+	if (q_vector->rx_ring)
+		rx_queue = q_vector->rx_ring->reg_idx;
+	if (q_vector->tx_ring)
+		tx_queue = q_vector->tx_ring->reg_idx;
 
 	switch (hw->mac.type) {
 	case e1000_82575:
@@ -483,16 +417,14 @@
 		   bitmask for the EICR/EIMS/EIMC registers.  To assign one
 		   or more queues to a vector, we write the appropriate bits
 		   into the MSIXBM register for that vector. */
-		if (rx_queue > IGB_N0_QUEUE) {
+		if (rx_queue > IGB_N0_QUEUE)
 			msixbm = E1000_EICR_RX_QUEUE0 << rx_queue;
-			adapter->rx_ring[rx_queue].eims_value = msixbm;
-		}
-		if (tx_queue > IGB_N0_QUEUE) {
+		if (tx_queue > IGB_N0_QUEUE)
 			msixbm |= E1000_EICR_TX_QUEUE0 << tx_queue;
-			adapter->tx_ring[tx_queue].eims_value =
-				  E1000_EICR_TX_QUEUE0 << tx_queue;
-		}
+		if (!adapter->msix_entries && msix_vector == 0)
+			msixbm |= E1000_EIMS_OTHER;
 		array_wr32(E1000_MSIXBM(0), msix_vector, msixbm);
+		q_vector->eims_value = msixbm;
 		break;
 	case e1000_82576:
 		/* 82576 uses a table-based method for assigning vectors.
@@ -500,7 +432,40 @@
 		   a vector number along with a "valid" bit.  Sadly, the layout
 		   of the table is somewhat counterintuitive. */
 		if (rx_queue > IGB_N0_QUEUE) {
-			index = (rx_queue >> 1) + adapter->vfs_allocated_count;
+			index = (rx_queue & 0x7);
+			ivar = array_rd32(E1000_IVAR0, index);
+			if (rx_queue < 8) {
+				/* vector goes into low byte of register */
+				ivar = ivar & 0xFFFFFF00;
+				ivar |= msix_vector | E1000_IVAR_VALID;
+			} else {
+				/* vector goes into third byte of register */
+				ivar = ivar & 0xFF00FFFF;
+				ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
+			}
+			array_wr32(E1000_IVAR0, index, ivar);
+		}
+		if (tx_queue > IGB_N0_QUEUE) {
+			index = (tx_queue & 0x7);
+			ivar = array_rd32(E1000_IVAR0, index);
+			if (tx_queue < 8) {
+				/* vector goes into second byte of register */
+				ivar = ivar & 0xFFFF00FF;
+				ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
+			} else {
+				/* vector goes into high byte of register */
+				ivar = ivar & 0x00FFFFFF;
+				ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
+			}
+			array_wr32(E1000_IVAR0, index, ivar);
+		}
+		q_vector->eims_value = 1 << msix_vector;
+		break;
+	case e1000_82580:
+		/* 82580 uses the same table-based approach as 82576 but has fewer
+		   entries as a result we carry over for queues greater than 4. */
+		if (rx_queue > IGB_N0_QUEUE) {
+			index = (rx_queue >> 1);
 			ivar = array_rd32(E1000_IVAR0, index);
 			if (rx_queue & 0x1) {
 				/* vector goes into third byte of register */
@@ -511,11 +476,10 @@
 				ivar = ivar & 0xFFFFFF00;
 				ivar |= msix_vector | E1000_IVAR_VALID;
 			}
-			adapter->rx_ring[rx_queue].eims_value= 1 << msix_vector;
 			array_wr32(E1000_IVAR0, index, ivar);
 		}
 		if (tx_queue > IGB_N0_QUEUE) {
-			index = (tx_queue >> 1) + adapter->vfs_allocated_count;
+			index = (tx_queue >> 1);
 			ivar = array_rd32(E1000_IVAR0, index);
 			if (tx_queue & 0x1) {
 				/* vector goes into high byte of register */
@@ -526,9 +490,9 @@
 				ivar = ivar & 0xFFFF00FF;
 				ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
 			}
-			adapter->tx_ring[tx_queue].eims_value= 1 << msix_vector;
 			array_wr32(E1000_IVAR0, index, ivar);
 		}
+		q_vector->eims_value = 1 << msix_vector;
 		break;
 	default:
 		BUG();
@@ -549,43 +513,10 @@
 	struct e1000_hw *hw = &adapter->hw;
 
 	adapter->eims_enable_mask = 0;
-	if (hw->mac.type == e1000_82576)
-		/* Turn on MSI-X capability first, or our settings
-		 * won't stick.  And it will take days to debug. */
-		wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
-				   E1000_GPIE_PBA | E1000_GPIE_EIAME |
- 				   E1000_GPIE_NSICR);
-
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct igb_ring *tx_ring = &adapter->tx_ring[i];
-		igb_assign_vector(adapter, IGB_N0_QUEUE, i, vector++);
-		adapter->eims_enable_mask |= tx_ring->eims_value;
-		if (tx_ring->itr_val)
-			writel(tx_ring->itr_val,
-			       hw->hw_addr + tx_ring->itr_register);
-		else
-			writel(1, hw->hw_addr + tx_ring->itr_register);
-	}
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct igb_ring *rx_ring = &adapter->rx_ring[i];
-		rx_ring->buddy = NULL;
-		igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++);
-		adapter->eims_enable_mask |= rx_ring->eims_value;
-		if (rx_ring->itr_val)
-			writel(rx_ring->itr_val,
-			       hw->hw_addr + rx_ring->itr_register);
-		else
-			writel(1, hw->hw_addr + rx_ring->itr_register);
-	}
-
 
 	/* set vector for other causes, i.e. link changes */
 	switch (hw->mac.type) {
 	case e1000_82575:
-		array_wr32(E1000_MSIXBM(0), vector++,
-				      E1000_EIMS_OTHER);
-
 		tmp = rd32(E1000_CTRL_EXT);
 		/* enable MSI-X PBA support*/
 		tmp |= E1000_CTRL_EXT_PBA_CLR;
@@ -595,22 +526,41 @@
 		tmp |= E1000_CTRL_EXT_IRCA;
 
 		wr32(E1000_CTRL_EXT, tmp);
-		adapter->eims_enable_mask |= E1000_EIMS_OTHER;
+
+		/* enable msix_other interrupt */
+		array_wr32(E1000_MSIXBM(0), vector++,
+		                      E1000_EIMS_OTHER);
 		adapter->eims_other = E1000_EIMS_OTHER;
 
 		break;
 
 	case e1000_82576:
+	case e1000_82580:
+		/* Turn on MSI-X capability first, or our settings
+		 * won't stick.  And it will take days to debug. */
+		wr32(E1000_GPIE, E1000_GPIE_MSIX_MODE |
+		                E1000_GPIE_PBA | E1000_GPIE_EIAME |
+		                E1000_GPIE_NSICR);
+
+		/* enable msix_other interrupt */
+		adapter->eims_other = 1 << vector;
 		tmp = (vector++ | E1000_IVAR_VALID) << 8;
-		wr32(E1000_IVAR_MISC, tmp);
 
-		adapter->eims_enable_mask = (1 << (vector)) - 1;
-		adapter->eims_other = 1 << (vector - 1);
+		wr32(E1000_IVAR_MISC, tmp);
 		break;
 	default:
 		/* do nothing, since nothing else supports MSI-X */
 		break;
 	} /* switch (hw->mac.type) */
+
+	adapter->eims_enable_mask |= adapter->eims_other;
+
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		igb_assign_vector(q_vector, vector++);
+		adapter->eims_enable_mask |= q_vector->eims_value;
+	}
+
 	wrfl();
 }
 
@@ -623,43 +573,40 @@
 static int igb_request_msix(struct igb_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	struct e1000_hw *hw = &adapter->hw;
 	int i, err = 0, vector = 0;
 
-	vector = 0;
+	err = request_irq(adapter->msix_entries[vector].vector,
+	                  &igb_msix_other, 0, netdev->name, adapter);
+	if (err)
+		goto out;
+	vector++;
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct igb_ring *ring = &(adapter->tx_ring[i]);
-		sprintf(ring->name, "%s-tx-%d", netdev->name, i);
-		err = request_irq(adapter->msix_entries[vector].vector,
-				  &igb_msix_tx, 0, ring->name,
-				  &(adapter->tx_ring[i]));
-		if (err)
-			goto out;
-		ring->itr_register = E1000_EITR(0) + (vector << 2);
-		ring->itr_val = 976; /* ~4000 ints/sec */
-		vector++;
-	}
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct igb_ring *ring = &(adapter->rx_ring[i]);
-		if (strlen(netdev->name) < (IFNAMSIZ - 5))
-			sprintf(ring->name, "%s-rx-%d", netdev->name, i);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+
+		q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
+
+		if (q_vector->rx_ring && q_vector->tx_ring)
+			sprintf(q_vector->name, "%s-TxRx-%u", netdev->name,
+			        q_vector->rx_ring->queue_index);
+		else if (q_vector->tx_ring)
+			sprintf(q_vector->name, "%s-tx-%u", netdev->name,
+			        q_vector->tx_ring->queue_index);
+		else if (q_vector->rx_ring)
+			sprintf(q_vector->name, "%s-rx-%u", netdev->name,
+			        q_vector->rx_ring->queue_index);
 		else
-			memcpy(ring->name, netdev->name, IFNAMSIZ);
+			sprintf(q_vector->name, "%s-unused", netdev->name);
+
 		err = request_irq(adapter->msix_entries[vector].vector,
-				  &igb_msix_rx, 0, ring->name,
-				  &(adapter->rx_ring[i]));
+		                  &igb_msix_ring, 0, q_vector->name,
+		                  q_vector);
 		if (err)
 			goto out;
-		ring->itr_register = E1000_EITR(0) + (vector << 2);
-		ring->itr_val = adapter->itr;
 		vector++;
 	}
 
-	err = request_irq(adapter->msix_entries[vector].vector,
-			  &igb_msix_other, 0, netdev->name, netdev);
-	if (err)
-		goto out;
-
 	igb_configure_msix(adapter);
 	return 0;
 out:
@@ -672,11 +619,44 @@
 		pci_disable_msix(adapter->pdev);
 		kfree(adapter->msix_entries);
 		adapter->msix_entries = NULL;
-	} else if (adapter->flags & IGB_FLAG_HAS_MSI)
+	} else if (adapter->flags & IGB_FLAG_HAS_MSI) {
 		pci_disable_msi(adapter->pdev);
-	return;
+	}
+}
+
+/**
+ * igb_free_q_vectors - Free memory allocated for interrupt vectors
+ * @adapter: board private structure to initialize
+ *
+ * This function frees the memory allocated to the q_vectors.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vectors(struct igb_adapter *adapter)
+{
+	int v_idx;
+
+	for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+		adapter->q_vector[v_idx] = NULL;
+		netif_napi_del(&q_vector->napi);
+		kfree(q_vector);
+	}
+	adapter->num_q_vectors = 0;
 }
 
+/**
+ * igb_clear_interrupt_scheme - reset the device to a state of no interrupts
+ *
+ * This function resets the device so that it has 0 rx queues, tx queues, and
+ * MSI-X interrupts allocated.
+ */
+static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
+{
+	igb_free_queues(adapter);
+	igb_free_q_vectors(adapter);
+	igb_reset_interrupt_capability(adapter);
+}
 
 /**
  * igb_set_interrupt_capability - set MSI or MSI-X if supported
@@ -690,11 +670,21 @@
 	int numvecs, i;
 
 	/* Number of supported queues. */
-	/* Having more queues than CPUs doesn't make sense. */
-	adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
-	adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus());
+	adapter->num_rx_queues = adapter->rss_queues;
+	adapter->num_tx_queues = adapter->rss_queues;
+
+	/* start with one vector for every rx queue */
+	numvecs = adapter->num_rx_queues;
+
+	/* if tx handler is seperate add 1 for every tx queue */
+	if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS))
+		numvecs += adapter->num_tx_queues;
+
+	/* store the number of vectors reserved for queues */
+	adapter->num_q_vectors = numvecs;
 
-	numvecs = adapter->num_tx_queues + adapter->num_rx_queues + 1;
+	/* add 1 vector for link status interrupts */
+	numvecs++;
 	adapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),
 					GFP_KERNEL);
 	if (!adapter->msix_entries)
@@ -728,8 +718,12 @@
 		dev_info(&adapter->pdev->dev, "IOV Disabled\n");
 	}
 #endif
+	adapter->vfs_allocated_count = 0;
+	adapter->rss_queues = 1;
+	adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
 	adapter->num_rx_queues = 1;
 	adapter->num_tx_queues = 1;
+	adapter->num_q_vectors = 1;
 	if (!pci_enable_msi(adapter->pdev))
 		adapter->flags |= IGB_FLAG_HAS_MSI;
 out:
@@ -739,93 +733,238 @@
 }
 
 /**
- * igb_request_irq - initialize interrupts
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
  *
- * Attempts to configure interrupts using the best available
- * capabilities of the hardware and kernel.
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
  **/
-static int igb_request_irq(struct igb_adapter *adapter)
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
+	struct igb_q_vector *q_vector;
 	struct e1000_hw *hw = &adapter->hw;
-	int err = 0;
+	int v_idx;
 
-	if (adapter->msix_entries) {
-		err = igb_request_msix(adapter);
-		if (!err)
-			goto request_done;
-		/* fall back to MSI */
-		igb_reset_interrupt_capability(adapter);
-		if (!pci_enable_msi(adapter->pdev))
-			adapter->flags |= IGB_FLAG_HAS_MSI;
-		igb_free_all_tx_resources(adapter);
-		igb_free_all_rx_resources(adapter);
-		adapter->num_rx_queues = 1;
-		igb_alloc_queues(adapter);
-	} else {
-		switch (hw->mac.type) {
-		case e1000_82575:
-			wr32(E1000_MSIXBM(0),
-			     (E1000_EICR_RX_QUEUE0 | E1000_EIMS_OTHER));
-			break;
-		case e1000_82576:
-			wr32(E1000_IVAR0, E1000_IVAR_VALID);
-			break;
-		default:
-			break;
-		}
+	for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
+		q_vector = kzalloc(sizeof(struct igb_q_vector), GFP_KERNEL);
+		if (!q_vector)
+			goto err_out;
+		q_vector->adapter = adapter;
+		q_vector->itr_shift = (hw->mac.type == e1000_82575) ? 16 : 0;
+		q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
+		q_vector->itr_val = IGB_START_ITR;
+		q_vector->set_itr = 1;
+		netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
+		adapter->q_vector[v_idx] = q_vector;
 	}
+	return 0;
 
-	if (adapter->flags & IGB_FLAG_HAS_MSI) {
-		err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0,
-				  netdev->name, netdev);
-		if (!err)
-			goto request_done;
-		/* fall back to legacy interrupts */
-		igb_reset_interrupt_capability(adapter);
-		adapter->flags &= ~IGB_FLAG_HAS_MSI;
+err_out:
+	while (v_idx) {
+		v_idx--;
+		q_vector = adapter->q_vector[v_idx];
+		netif_napi_del(&q_vector->napi);
+		kfree(q_vector);
+		adapter->q_vector[v_idx] = NULL;
 	}
+	return -ENOMEM;
+}
 
-	err = request_irq(adapter->pdev->irq, &igb_intr, IRQF_SHARED,
-			  netdev->name, netdev);
+static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
+                                      int ring_idx, int v_idx)
+{
+	struct igb_q_vector *q_vector;
 
-	if (err)
-		dev_err(&adapter->pdev->dev, "Error %d getting interrupt\n",
-			err);
+	q_vector = adapter->q_vector[v_idx];
+	q_vector->rx_ring = &adapter->rx_ring[ring_idx];
+	q_vector->rx_ring->q_vector = q_vector;
+	q_vector->itr_val = adapter->rx_itr_setting;
+	if (q_vector->itr_val && q_vector->itr_val <= 3)
+		q_vector->itr_val = IGB_START_ITR;
+}
 
-request_done:
-	return err;
+static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
+                                      int ring_idx, int v_idx)
+{
+	struct igb_q_vector *q_vector;
+
+	q_vector = adapter->q_vector[v_idx];
+	q_vector->tx_ring = &adapter->tx_ring[ring_idx];
+	q_vector->tx_ring->q_vector = q_vector;
+	q_vector->itr_val = adapter->tx_itr_setting;
+	if (q_vector->itr_val && q_vector->itr_val <= 3)
+		q_vector->itr_val = IGB_START_ITR;
 }
 
-static void igb_free_irq(struct igb_adapter *adapter)
+/**
+ * igb_map_ring_to_vector - maps allocated queues to vectors
+ *
+ * This function maps the recently allocated queues to vectors.
+ **/
+static int igb_map_ring_to_vector(struct igb_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
+	int i;
+	int v_idx = 0;
 
-	if (adapter->msix_entries) {
-		int vector = 0, i;
+	if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
+	    (adapter->num_q_vectors < adapter->num_tx_queues))
+		return -ENOMEM;
 
-		for (i = 0; i < adapter->num_tx_queues; i++)
-			free_irq(adapter->msix_entries[vector++].vector,
-				&(adapter->tx_ring[i]));
+	if (adapter->num_q_vectors >=
+	    (adapter->num_rx_queues + adapter->num_tx_queues)) {
 		for (i = 0; i < adapter->num_rx_queues; i++)
-			free_irq(adapter->msix_entries[vector++].vector,
-				&(adapter->rx_ring[i]));
-
-		free_irq(adapter->msix_entries[vector++].vector, netdev);
-		return;
+			igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+		for (i = 0; i < adapter->num_tx_queues; i++)
+			igb_map_tx_ring_to_vector(adapter, i, v_idx++);
+	} else {
+		for (i = 0; i < adapter->num_rx_queues; i++) {
+			if (i < adapter->num_tx_queues)
+				igb_map_tx_ring_to_vector(adapter, i, v_idx);
+			igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+		}
+		for (; i < adapter->num_tx_queues; i++)
+			igb_map_tx_ring_to_vector(adapter, i, v_idx++);
 	}
-
-	free_irq(adapter->pdev->irq, netdev);
+	return 0;
 }
 
 /**
- * igb_irq_disable - Mask off interrupt generation on the NIC
+ * igb_init_interrupt_scheme - initialize interrupts, allocate queues/vectors
+ *
+ * This function initializes the interrupts and allocates all of the queues.
+ **/
+static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int err;
+
+	igb_set_interrupt_capability(adapter);
+
+	err = igb_alloc_q_vectors(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to allocate memory for vectors\n");
+		goto err_alloc_q_vectors;
+	}
+
+	err = igb_alloc_queues(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+		goto err_alloc_queues;
+	}
+
+	err = igb_map_ring_to_vector(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
+		goto err_map_queues;
+	}
+
+
+	return 0;
+err_map_queues:
+	igb_free_queues(adapter);
+err_alloc_queues:
+	igb_free_q_vectors(adapter);
+err_alloc_q_vectors:
+	igb_reset_interrupt_capability(adapter);
+	return err;
+}
+
+/**
+ * igb_request_irq - initialize interrupts
+ *
+ * Attempts to configure interrupts using the best available
+ * capabilities of the hardware and kernel.
+ **/
+static int igb_request_irq(struct igb_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	int err = 0;
+
+	if (adapter->msix_entries) {
+		err = igb_request_msix(adapter);
+		if (!err)
+			goto request_done;
+		/* fall back to MSI */
+		igb_clear_interrupt_scheme(adapter);
+		if (!pci_enable_msi(adapter->pdev))
+			adapter->flags |= IGB_FLAG_HAS_MSI;
+		igb_free_all_tx_resources(adapter);
+		igb_free_all_rx_resources(adapter);
+		adapter->num_tx_queues = 1;
+		adapter->num_rx_queues = 1;
+		adapter->num_q_vectors = 1;
+		err = igb_alloc_q_vectors(adapter);
+		if (err) {
+			dev_err(&pdev->dev,
+			        "Unable to allocate memory for vectors\n");
+			goto request_done;
+		}
+		err = igb_alloc_queues(adapter);
+		if (err) {
+			dev_err(&pdev->dev,
+			        "Unable to allocate memory for queues\n");
+			igb_free_q_vectors(adapter);
+			goto request_done;
+		}
+		igb_setup_all_tx_resources(adapter);
+		igb_setup_all_rx_resources(adapter);
+	} else {
+		igb_assign_vector(adapter->q_vector[0], 0);
+	}
+
+	if (adapter->flags & IGB_FLAG_HAS_MSI) {
+		err = request_irq(adapter->pdev->irq, &igb_intr_msi, 0,
+				  netdev->name, adapter);
+		if (!err)
+			goto request_done;
+
+		/* fall back to legacy interrupts */
+		igb_reset_interrupt_capability(adapter);
+		adapter->flags &= ~IGB_FLAG_HAS_MSI;
+	}
+
+	err = request_irq(adapter->pdev->irq, &igb_intr, IRQF_SHARED,
+			  netdev->name, adapter);
+
+	if (err)
+		dev_err(&adapter->pdev->dev, "Error %d getting interrupt\n",
+			err);
+
+request_done:
+	return err;
+}
+
+static void igb_free_irq(struct igb_adapter *adapter)
+{
+	if (adapter->msix_entries) {
+		int vector = 0, i;
+
+		free_irq(adapter->msix_entries[vector++].vector, adapter);
+
+		for (i = 0; i < adapter->num_q_vectors; i++) {
+			struct igb_q_vector *q_vector = adapter->q_vector[i];
+			free_irq(adapter->msix_entries[vector++].vector,
+			         q_vector);
+		}
+	} else {
+		free_irq(adapter->pdev->irq, adapter);
+	}
+}
+
+/**
+ * igb_irq_disable - Mask off interrupt generation on the NIC
  * @adapter: board private structure
  **/
 static void igb_irq_disable(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 
+	/*
+	 * we need to be careful when disabling interrupts.  The VFs are also
+	 * mapped into these registers and so clearing the bits can cause
+	 * issues on the VF drivers so we only need to clear what we set
+	 */
 	if (adapter->msix_entries) {
 		u32 regval = rd32(E1000_EIAM);
 		wr32(E1000_EIAM, regval & ~adapter->eims_enable_mask);
@@ -849,41 +988,47 @@
 	struct e1000_hw *hw = &adapter->hw;
 
 	if (adapter->msix_entries) {
+		u32 ims = E1000_IMS_LSC | E1000_IMS_DOUTSYNC;
 		u32 regval = rd32(E1000_EIAC);
 		wr32(E1000_EIAC, regval | adapter->eims_enable_mask);
 		regval = rd32(E1000_EIAM);
 		wr32(E1000_EIAM, regval | adapter->eims_enable_mask);
 		wr32(E1000_EIMS, adapter->eims_enable_mask);
-		if (adapter->vfs_allocated_count)
+		if (adapter->vfs_allocated_count) {
 			wr32(E1000_MBVFIMR, 0xFF);
-		wr32(E1000_IMS, (E1000_IMS_LSC | E1000_IMS_VMMB |
-		                 E1000_IMS_DOUTSYNC));
+			ims |= E1000_IMS_VMMB;
+		}
+		if (adapter->hw.mac.type == e1000_82580)
+			ims |= E1000_IMS_DRSTA;
+
+		wr32(E1000_IMS, ims);
 	} else {
-		wr32(E1000_IMS, IMS_ENABLE_MASK);
-		wr32(E1000_IAM, IMS_ENABLE_MASK);
+		wr32(E1000_IMS, IMS_ENABLE_MASK |
+				E1000_IMS_DRSTA);
+		wr32(E1000_IAM, IMS_ENABLE_MASK |
+				E1000_IMS_DRSTA);
 	}
 }
 
 static void igb_update_mng_vlan(struct igb_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
+	struct e1000_hw *hw = &adapter->hw;
 	u16 vid = adapter->hw.mng_cookie.vlan_id;
 	u16 old_vid = adapter->mng_vlan_id;
-	if (adapter->vlgrp) {
-		if (!vlan_group_get_device(adapter->vlgrp, vid)) {
-			if (adapter->hw.mng_cookie.status &
-				E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
-				igb_vlan_rx_add_vid(netdev, vid);
-				adapter->mng_vlan_id = vid;
-			} else
-				adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
-
-			if ((old_vid != (u16)IGB_MNG_VLAN_NONE) &&
-					(vid != old_vid) &&
-			    !vlan_group_get_device(adapter->vlgrp, old_vid))
-				igb_vlan_rx_kill_vid(netdev, old_vid);
-		} else
-			adapter->mng_vlan_id = vid;
+
+	if (hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
+		/* add VID to filter table */
+		igb_vfta_set(hw, vid, true);
+		adapter->mng_vlan_id = vid;
+	} else {
+		adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
+	}
+
+	if ((old_vid != (u16)IGB_MNG_VLAN_NONE) &&
+	    (vid != old_vid) &&
+	    !vlan_group_get_device(adapter->vlgrp, old_vid)) {
+		/* remove VID from filter table */
+		igb_vfta_set(hw, old_vid, false);
 	}
 }
 
@@ -907,7 +1052,6 @@
 			ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
 }
 
-
 /**
  * igb_get_hw_control - get control of the h/w from f/w
  * @adapter: address of board private structure
@@ -942,8 +1086,11 @@
 
 	igb_restore_vlan(adapter);
 
-	igb_configure_tx(adapter);
+	igb_setup_tctl(adapter);
+	igb_setup_mrqc(adapter);
 	igb_setup_rctl(adapter);
+
+	igb_configure_tx(adapter);
 	igb_configure_rx(adapter);
 
 	igb_rx_fifo_flush_82575(&adapter->hw);
@@ -965,7 +1112,6 @@
  * igb_up - Open the interface and prepare it to handle traffic
  * @adapter: board private structure
  **/
-
 int igb_up(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
@@ -976,30 +1122,39 @@
 
 	clear_bit(__IGB_DOWN, &adapter->state);
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		napi_enable(&adapter->rx_ring[i].napi);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		napi_enable(&q_vector->napi);
+	}
 	if (adapter->msix_entries)
 		igb_configure_msix(adapter);
-
-	igb_vmm_control(adapter);
-	igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0);
-	igb_set_vmolr(hw, adapter->vfs_allocated_count);
+	else
+		igb_assign_vector(adapter->q_vector[0], 0);
 
 	/* Clear any pending interrupts. */
 	rd32(E1000_ICR);
 	igb_irq_enable(adapter);
 
+	/* notify VFs that reset has been completed */
+	if (adapter->vfs_allocated_count) {
+		u32 reg_data = rd32(E1000_CTRL_EXT);
+		reg_data |= E1000_CTRL_EXT_PFRSTD;
+		wr32(E1000_CTRL_EXT, reg_data);
+	}
+
 	netif_tx_start_all_queues(adapter->netdev);
 
-	/* Fire a link change interrupt to start the watchdog. */
-	wr32(E1000_ICS, E1000_ICS_LSC);
+	/* start the watchdog. */
+	hw->mac.get_link_status = 1;
+	schedule_work(&adapter->watchdog_task);
+
 	return 0;
 }
 
 void igb_down(struct igb_adapter *adapter)
 {
-	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
+	struct e1000_hw *hw = &adapter->hw;
 	u32 tctl, rctl;
 	int i;
 
@@ -1022,8 +1177,10 @@
 	wrfl();
 	msleep(10);
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		napi_disable(&adapter->rx_ring[i].napi);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		napi_disable(&q_vector->napi);
+	}
 
 	igb_irq_disable(adapter);
 
@@ -1062,6 +1219,7 @@
 
 void igb_reset(struct igb_adapter *adapter)
 {
+	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_mac_info *mac = &hw->mac;
 	struct e1000_fc_info *fc = &hw->fc;
@@ -1072,8 +1230,13 @@
 	 * To take effect CTRL.RST is required.
 	 */
 	switch (mac->type) {
+	case e1000_82580:
+		pba = rd32(E1000_RXPBS);
+		pba = igb_rxpbs_adjust_82580(pba);
+		break;
 	case e1000_82576:
-		pba = E1000_PBA_64K;
+		pba = rd32(E1000_RXPBS);
+		pba &= E1000_RXPBS_SIZE_MASK_82576;
 		break;
 	case e1000_82575:
 	default:
@@ -1133,13 +1296,8 @@
 	hwm = min(((pba << 10) * 9 / 10),
 			((pba << 10) - 2 * adapter->max_frame_size));
 
-	if (mac->type < e1000_82576) {
-		fc->high_water = hwm & 0xFFF8;	/* 8-byte granularity */
-		fc->low_water = fc->high_water - 8;
-	} else {
-		fc->high_water = hwm & 0xFFF0;	/* 16-byte granularity */
-		fc->low_water = fc->high_water - 16;
-	}
+	fc->high_water = hwm & 0xFFF0;	/* 16-byte granularity */
+	fc->low_water = fc->high_water - 16;
 	fc->pause_time = 0xFFFF;
 	fc->send_xon = 1;
 	fc->current_mode = fc->requested_mode;
@@ -1148,10 +1306,10 @@
 	if (adapter->vfs_allocated_count) {
 		int i;
 		for (i = 0 ; i < adapter->vfs_allocated_count; i++)
-			adapter->vf_data[i].clear_to_send = false;
+			adapter->vf_data[i].flags = 0;
 
 		/* ping all the active vfs to let them know we are going down */
-			igb_ping_all_vfs(adapter);
+		igb_ping_all_vfs(adapter);
 
 		/* disable transmits and receives */
 		wr32(E1000_VFRE, 0);
@@ -1159,23 +1317,28 @@
 	}
 
 	/* Allow time for pending master requests to run */
-	adapter->hw.mac.ops.reset_hw(&adapter->hw);
+	hw->mac.ops.reset_hw(hw);
 	wr32(E1000_WUC, 0);
 
-	if (adapter->hw.mac.ops.init_hw(&adapter->hw))
-		dev_err(&adapter->pdev->dev, "Hardware Error\n");
+	if (hw->mac.ops.init_hw(hw))
+		dev_err(&pdev->dev, "Hardware Error\n");
 
+	if (hw->mac.type == e1000_82580) {
+		u32 reg = rd32(E1000_PCIEMISC);
+		wr32(E1000_PCIEMISC,
+		                reg & ~E1000_PCIEMISC_LX_DECISION);
+	}
 	igb_update_mng_vlan(adapter);
 
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
 	wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
 
-	igb_reset_adaptive(&adapter->hw);
-	igb_get_phy_info(&adapter->hw);
+	igb_reset_adaptive(hw);
+	igb_get_phy_info(hw);
 }
 
 static const struct net_device_ops igb_netdev_ops = {
-	.ndo_open 		= igb_open,
+	.ndo_open		= igb_open,
 	.ndo_stop		= igb_close,
 	.ndo_start_xmit		= igb_xmit_frame_adv,
 	.ndo_get_stats		= igb_get_stats,
@@ -1211,10 +1374,11 @@
 	struct net_device *netdev;
 	struct igb_adapter *adapter;
 	struct e1000_hw *hw;
+	u16 eeprom_data = 0;
+	static int global_quad_port_a; /* global quad port a indication */
 	const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
 	unsigned long mmio_start, mmio_len;
 	int err, pci_using_dac;
-	u16 eeprom_data = 0;
 	u16 eeprom_apme_mask = IGB_EEPROM_APME;
 	u32 part_num;
 
@@ -1291,8 +1455,6 @@
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
 
-	/* setup the private structure */
-	hw->back = adapter;
 	/* Copy the default MAC, PHY and NVM function pointers */
 	memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
 	memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));
@@ -1302,46 +1464,6 @@
 	if (err)
 		goto err_sw_init;
 
-#ifdef CONFIG_PCI_IOV
-	/* since iov functionality isn't critical to base device function we
-	 * can accept failure.  If it fails we don't allow iov to be enabled */
-	if (hw->mac.type == e1000_82576) {
-		/* 82576 supports a maximum of 7 VFs in addition to the PF */
-		unsigned int num_vfs = (max_vfs > 7) ? 7 : max_vfs;
-		int i;
-		unsigned char mac_addr[ETH_ALEN];
-
-		if (num_vfs) {
-			adapter->vf_data = kcalloc(num_vfs,
-						sizeof(struct vf_data_storage),
-						GFP_KERNEL);
-			if (!adapter->vf_data) {
-				dev_err(&pdev->dev,
-				        "Could not allocate VF private data - "
-					"IOV enable failed\n");
-			} else {
-				err = pci_enable_sriov(pdev, num_vfs);
-				if (!err) {
-					adapter->vfs_allocated_count = num_vfs;
-					dev_info(&pdev->dev,
-					         "%d vfs allocated\n",
-					         num_vfs);
-					for (i = 0;
-					     i < adapter->vfs_allocated_count;
-					     i++) {
-						random_ether_addr(mac_addr);
-						igb_set_vf_mac(adapter, i,
-						               mac_addr);
-					}
-				} else {
-					kfree(adapter->vf_data);
-					adapter->vf_data = NULL;
-				}
-			}
-		}
-	}
-
-#endif
 	/* setup the private structure */
 	err = igb_sw_init(adapter);
 	if (err)
@@ -1349,16 +1471,6 @@
 
 	igb_get_bus_info_pcie(hw);
 
-	/* set flags */
-	switch (hw->mac.type) {
-	case e1000_82575:
-		adapter->flags |= IGB_FLAG_NEED_CTX_IDX;
-		break;
-	case e1000_82576:
-	default:
-		break;
-	}
-
 	hw->phy.autoneg_wait_to_complete = false;
 	hw->mac.adaptive_ifs = true;
 
@@ -1382,7 +1494,6 @@
 	netdev->features |= NETIF_F_IPV6_CSUM;
 	netdev->features |= NETIF_F_TSO;
 	netdev->features |= NETIF_F_TSO6;
-
 	netdev->features |= NETIF_F_GRO;
 
 	netdev->vlan_features |= NETIF_F_TSO;
@@ -1394,10 +1505,10 @@
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
-	if (adapter->hw.mac.type == e1000_82576)
+	if (hw->mac.type >= e1000_82576)
 		netdev->features |= NETIF_F_SCTP_CSUM;
 
-	adapter->en_mng_pt = igb_enable_mng_pass_thru(&adapter->hw);
+	adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
 	/* before reading the NVM, reset the controller to put the device in a
 	 * known good starting state */
@@ -1439,9 +1550,6 @@
 	hw->fc.requested_mode = e1000_fc_default;
 	hw->fc.current_mode = e1000_fc_default;
 
-	adapter->itr_setting = IGB_DEFAULT_ITR;
-	adapter->itr = IGB_START_ITR;
-
 	igb_validate_mdi_setting(hw);
 
 	/* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
@@ -1450,6 +1558,10 @@
 
 	if (hw->bus.func == 0)
 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
+	else if (hw->mac.type == e1000_82580)
+		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
+		                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
+		                 &eeprom_data);
 	else if (hw->bus.func == 1)
 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
 
@@ -1508,66 +1620,14 @@
 		dev_info(&pdev->dev, "DCA enabled\n");
 		igb_setup_dca(adapter);
 	}
-#endif
-
-	/*
-	 * Initialize hardware timer: we keep it running just in case
-	 * that some program needs it later on.
-	 */
-	memset(&adapter->cycles, 0, sizeof(adapter->cycles));
-	adapter->cycles.read = igb_read_clock;
-	adapter->cycles.mask = CLOCKSOURCE_MASK(64);
-	adapter->cycles.mult = 1;
-	adapter->cycles.shift = IGB_TSYNC_SHIFT;
-	wr32(E1000_TIMINCA,
-	     (1<<24) |
-	     IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE);
-#if 0
-	/*
-	 * Avoid rollover while we initialize by resetting the time counter.
-	 */
-	wr32(E1000_SYSTIML, 0x00000000);
-	wr32(E1000_SYSTIMH, 0x00000000);
-#else
-	/*
-	 * Set registers so that rollover occurs soon to test this.
-	 */
-	wr32(E1000_SYSTIML, 0x00000000);
-	wr32(E1000_SYSTIMH, 0xFF800000);
-#endif
-	wrfl();
-	timecounter_init(&adapter->clock,
-			 &adapter->cycles,
-			 ktime_to_ns(ktime_get_real()));
-
-	/*
-	 * Synchronize our NIC clock against system wall clock. NIC
-	 * time stamp reading requires ~3us per sample, each sample
-	 * was pretty stable even under load => only require 10
-	 * samples for each offset comparison.
-	 */
-	memset(&adapter->compare, 0, sizeof(adapter->compare));
-	adapter->compare.source = &adapter->clock;
-	adapter->compare.target = ktime_get_real;
-	adapter->compare.num_samples = 10;
-	timecompare_update(&adapter->compare, 0);
 
-#ifdef DEBUG
-	{
-		char buffer[160];
-		printk(KERN_DEBUG
-			"igb: %s: hw %p initialized timer\n",
-			igb_get_time_str(adapter, buffer),
-			&adapter->hw);
-	}
 #endif
-
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info */
 	dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
 		 netdev->name,
-		 ((hw->bus.speed == e1000_bus_speed_2500)
-		  ? "2.5Gb/s" : "unknown"),
+		 ((hw->bus.speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+		                                            "unknown"),
 		 ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
 		  (hw->bus.width == e1000_bus_width_pcie_x2) ? "Width x2" :
 		  (hw->bus.width == e1000_bus_width_pcie_x1) ? "Width x1" :
@@ -1594,15 +1654,14 @@
 
 	if (hw->flash_address)
 		iounmap(hw->flash_address);
-
-	igb_free_queues(adapter);
 err_sw_init:
+	igb_clear_interrupt_scheme(adapter);
 	iounmap(hw->hw_addr);
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_selected_regions(pdev, pci_select_bars(pdev,
-	                             IORESOURCE_MEM));
+	pci_release_selected_regions(pdev,
+	                             pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -1647,12 +1706,10 @@
 
 	unregister_netdev(netdev);
 
-	if (!igb_check_reset_block(&adapter->hw))
-		igb_reset_phy(&adapter->hw);
-
-	igb_reset_interrupt_capability(adapter);
+	if (!igb_check_reset_block(hw))
+		igb_reset_phy(hw);
 
-	igb_free_queues(adapter);
+	igb_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_PCI_IOV
 	/* reclaim resources allocated to VFs */
@@ -1668,11 +1725,12 @@
 		dev_info(&pdev->dev, "IOV Disabled\n");
 	}
 #endif
+
 	iounmap(hw->hw_addr);
 	if (hw->flash_address)
 		iounmap(hw->flash_address);
-	pci_release_selected_regions(pdev, pci_select_bars(pdev,
-	                             IORESOURCE_MEM));
+	pci_release_selected_regions(pdev,
+	                             pci_select_bars(pdev, IORESOURCE_MEM));
 
 	free_netdev(netdev);
 
@@ -1682,6 +1740,160 @@
 }
 
 /**
+ * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space
+ * @adapter: board private structure to initialize
+ *
+ * This function initializes the vf specific data storage and then attempts to
+ * allocate the VFs.  The reason for ordering it this way is because it is much
+ * mor expensive time wise to disable SR-IOV than it is to allocate and free
+ * the memory for the VFs.
+ **/
+static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+{
+#ifdef CONFIG_PCI_IOV
+	struct pci_dev *pdev = adapter->pdev;
+
+	if (adapter->vfs_allocated_count > 7)
+		adapter->vfs_allocated_count = 7;
+
+	if (adapter->vfs_allocated_count) {
+		adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
+		                           sizeof(struct vf_data_storage),
+		                           GFP_KERNEL);
+		/* if allocation failed then we do not support SR-IOV */
+		if (!adapter->vf_data) {
+			adapter->vfs_allocated_count = 0;
+			dev_err(&pdev->dev, "Unable to allocate memory for VF "
+			        "Data Storage\n");
+		}
+	}
+
+	if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
+		kfree(adapter->vf_data);
+		adapter->vf_data = NULL;
+#endif /* CONFIG_PCI_IOV */
+		adapter->vfs_allocated_count = 0;
+#ifdef CONFIG_PCI_IOV
+	} else {
+		unsigned char mac_addr[ETH_ALEN];
+		int i;
+		dev_info(&pdev->dev, "%d vfs allocated\n",
+		         adapter->vfs_allocated_count);
+		for (i = 0; i < adapter->vfs_allocated_count; i++) {
+			random_ether_addr(mac_addr);
+			igb_set_vf_mac(adapter, i, mac_addr);
+		}
+	}
+#endif /* CONFIG_PCI_IOV */
+}
+
+
+/**
+ * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
+ * @adapter: board private structure to initialize
+ *
+ * igb_init_hw_timer initializes the function pointer and values for the hw
+ * timer found in hardware.
+ **/
+static void igb_init_hw_timer(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+
+	switch (hw->mac.type) {
+	case e1000_82580:
+		memset(&adapter->cycles, 0, sizeof(adapter->cycles));
+		adapter->cycles.read = igb_read_clock;
+		adapter->cycles.mask = CLOCKSOURCE_MASK(64);
+		adapter->cycles.mult = 1;
+		/*
+		 * The 82580 timesync updates the system timer every 8ns by 8ns
+		 * and the value cannot be shifted.  Instead we need to shift
+		 * the registers to generate a 64bit timer value.  As a result
+		 * SYSTIMR/L/H, TXSTMPL/H, RXSTMPL/H all have to be shifted by
+		 * 24 in order to generate a larger value for synchronization.
+		 */
+		adapter->cycles.shift = IGB_82580_TSYNC_SHIFT;
+		/* disable system timer temporarily by setting bit 31 */
+		wr32(E1000_TSAUXC, 0x80000000);
+		wrfl();
+
+		/* Set registers so that rollover occurs soon to test this. */
+		wr32(E1000_SYSTIMR, 0x00000000);
+		wr32(E1000_SYSTIML, 0x80000000);
+		wr32(E1000_SYSTIMH, 0x000000FF);
+		wrfl();
+
+		/* enable system timer by clearing bit 31 */
+		wr32(E1000_TSAUXC, 0x0);
+		wrfl();
+
+		timecounter_init(&adapter->clock,
+				 &adapter->cycles,
+				 ktime_to_ns(ktime_get_real()));
+		/*
+		 * Synchronize our NIC clock against system wall clock. NIC
+		 * time stamp reading requires ~3us per sample, each sample
+		 * was pretty stable even under load => only require 10
+		 * samples for each offset comparison.
+		 */
+		memset(&adapter->compare, 0, sizeof(adapter->compare));
+		adapter->compare.source = &adapter->clock;
+		adapter->compare.target = ktime_get_real;
+		adapter->compare.num_samples = 10;
+		timecompare_update(&adapter->compare, 0);
+		break;
+	case e1000_82576:
+		/*
+		 * Initialize hardware timer: we keep it running just in case
+		 * that some program needs it later on.
+		 */
+		memset(&adapter->cycles, 0, sizeof(adapter->cycles));
+		adapter->cycles.read = igb_read_clock;
+		adapter->cycles.mask = CLOCKSOURCE_MASK(64);
+		adapter->cycles.mult = 1;
+		/**
+		 * Scale the NIC clock cycle by a large factor so that
+		 * relatively small clock corrections can be added or
+		 * substracted at each clock tick. The drawbacks of a large
+		 * factor are a) that the clock register overflows more quickly
+		 * (not such a big deal) and b) that the increment per tick has
+		 * to fit into 24 bits.  As a result we need to use a shift of
+		 * 19 so we can fit a value of 16 into the TIMINCA register.
+		 */
+		adapter->cycles.shift = IGB_82576_TSYNC_SHIFT;
+		wr32(E1000_TIMINCA,
+		                (1 << E1000_TIMINCA_16NS_SHIFT) |
+		                (16 << IGB_82576_TSYNC_SHIFT));
+
+		/* Set registers so that rollover occurs soon to test this. */
+		wr32(E1000_SYSTIML, 0x00000000);
+		wr32(E1000_SYSTIMH, 0xFF800000);
+		wrfl();
+
+		timecounter_init(&adapter->clock,
+				 &adapter->cycles,
+				 ktime_to_ns(ktime_get_real()));
+		/*
+		 * Synchronize our NIC clock against system wall clock. NIC
+		 * time stamp reading requires ~3us per sample, each sample
+		 * was pretty stable even under load => only require 10
+		 * samples for each offset comparison.
+		 */
+		memset(&adapter->compare, 0, sizeof(adapter->compare));
+		adapter->compare.source = &adapter->clock;
+		adapter->compare.target = ktime_get_real;
+		adapter->compare.num_samples = 10;
+		timecompare_update(&adapter->compare, 0);
+		break;
+	case e1000_82575:
+		/* 82575 does not support timesync */
+	default:
+		break;
+	}
+
+}
+
+/**
  * igb_sw_init - Initialize general software structures (struct igb_adapter)
  * @adapter: board private structure to initialize
  *
@@ -1699,20 +1911,37 @@
 
 	adapter->tx_ring_count = IGB_DEFAULT_TXD;
 	adapter->rx_ring_count = IGB_DEFAULT_RXD;
-	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-	adapter->rx_ps_hdr_size = 0; /* disable packet split */
+	adapter->rx_itr_setting = IGB_DEFAULT_ITR;
+	adapter->tx_itr_setting = IGB_DEFAULT_ITR;
+
 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
-	/* This call may decrease the number of queues depending on
-	 * interrupt mode. */
-	igb_set_interrupt_capability(adapter);
+#ifdef CONFIG_PCI_IOV
+	if (hw->mac.type == e1000_82576)
+		adapter->vfs_allocated_count = max_vfs;
+
+#endif /* CONFIG_PCI_IOV */
+	adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
+
+	/*
+	 * if rss_queues > 4 or vfs are going to be allocated with rss_queues
+	 * then we should combine the queues into a queue pair in order to
+	 * conserve interrupts due to limited supply
+	 */
+	if ((adapter->rss_queues > 4) ||
+	    ((adapter->rss_queues > 1) && (adapter->vfs_allocated_count > 6)))
+		adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
 
-	if (igb_alloc_queues(adapter)) {
+	/* This call may decrease the number of queues */
+	if (igb_init_interrupt_scheme(adapter)) {
 		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
 		return -ENOMEM;
 	}
 
+	igb_init_hw_timer(adapter);
+	igb_probe_vfs(adapter);
+
 	/* Explicitly disable IRQ since the NIC can be in any state. */
 	igb_irq_disable(adapter);
 
@@ -1757,21 +1986,12 @@
 
 	/* e1000_power_up_phy(adapter); */
 
-	adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
-		igb_update_mng_vlan(adapter);
-
 	/* before we allocate an interrupt, we must be ready to handle it.
 	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
 	 * as soon as we call pci_request_irq, so we have to setup our
 	 * clean_rx handler before we do so.  */
 	igb_configure(adapter);
 
-	igb_vmm_control(adapter);
-	igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0);
-	igb_set_vmolr(hw, adapter->vfs_allocated_count);
-
 	err = igb_request_irq(adapter);
 	if (err)
 		goto err_req_irq;
@@ -1779,18 +1999,28 @@
 	/* From here on the code is the same as igb_up() */
 	clear_bit(__IGB_DOWN, &adapter->state);
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		napi_enable(&adapter->rx_ring[i].napi);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		napi_enable(&q_vector->napi);
+	}
 
 	/* Clear any pending interrupts. */
 	rd32(E1000_ICR);
 
 	igb_irq_enable(adapter);
 
+	/* notify VFs that reset has been completed */
+	if (adapter->vfs_allocated_count) {
+		u32 reg_data = rd32(E1000_CTRL_EXT);
+		reg_data |= E1000_CTRL_EXT_PFRSTD;
+		wr32(E1000_CTRL_EXT, reg_data);
+	}
+
 	netif_tx_start_all_queues(netdev);
 
-	/* Fire a link status change interrupt to start the watchdog. */
-	wr32(E1000_ICS, E1000_ICS_LSC);
+	/* start the watchdog. */
+	hw->mac.get_link_status = 1;
+	schedule_work(&adapter->watchdog_task);
 
 	return 0;
 
@@ -1829,28 +2059,18 @@
 	igb_free_all_tx_resources(adapter);
 	igb_free_all_rx_resources(adapter);
 
-	/* kill manageability vlan ID if supported, but not if a vlan with
-	 * the same ID is registered on the host OS (let 8021q kill it) */
-	if ((adapter->hw.mng_cookie.status &
-			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
-	     !(adapter->vlgrp &&
-	       vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id)))
-		igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-
 	return 0;
 }
 
 /**
  * igb_setup_tx_resources - allocate Tx resources (Descriptors)
- * @adapter: board private structure
  * @tx_ring: tx descriptor ring (for a specific queue) to setup
  *
  * Return 0 on success, negative on failure
  **/
-int igb_setup_tx_resources(struct igb_adapter *adapter,
-			   struct igb_ring *tx_ring)
+int igb_setup_tx_resources(struct igb_ring *tx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct pci_dev *pdev = tx_ring->pdev;
 	int size;
 
 	size = sizeof(struct igb_buffer) * tx_ring->count;
@@ -1863,20 +2083,20 @@
 	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
 	tx_ring->size = ALIGN(tx_ring->size, 4096);
 
-	tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
+	tx_ring->desc = pci_alloc_consistent(pdev,
+	                                     tx_ring->size,
 					     &tx_ring->dma);
 
 	if (!tx_ring->desc)
 		goto err;
 
-	tx_ring->adapter = adapter;
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
 	return 0;
 
 err:
 	vfree(tx_ring->buffer_info);
-	dev_err(&adapter->pdev->dev,
+	dev_err(&pdev->dev,
 		"Unable to allocate memory for the transmit descriptor ring\n");
 	return -ENOMEM;
 }
@@ -1890,13 +2110,13 @@
  **/
 static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
 {
+	struct pci_dev *pdev = adapter->pdev;
 	int i, err = 0;
-	int r_idx;
 
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		err = igb_setup_tx_resources(adapter, &adapter->tx_ring[i]);
+		err = igb_setup_tx_resources(&adapter->tx_ring[i]);
 		if (err) {
-			dev_err(&adapter->pdev->dev,
+			dev_err(&pdev->dev,
 				"Allocation for Tx Queue %u failed\n", i);
 			for (i--; i >= 0; i--)
 				igb_free_tx_resources(&adapter->tx_ring[i]);
@@ -1904,57 +2124,24 @@
 		}
 	}
 
-	for (i = 0; i < IGB_MAX_TX_QUEUES; i++) {
-		r_idx = i % adapter->num_tx_queues;
+	for (i = 0; i < IGB_ABS_MAX_TX_QUEUES; i++) {
+		int r_idx = i % adapter->num_tx_queues;
 		adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx];
 	}
 	return err;
 }
 
 /**
- * igb_configure_tx - Configure transmit Unit after Reset
- * @adapter: board private structure
- *
- * Configure the Tx unit of the MAC after a reset.
+ * igb_setup_tctl - configure the transmit control registers
+ * @adapter: Board private structure
  **/
-static void igb_configure_tx(struct igb_adapter *adapter)
+void igb_setup_tctl(struct igb_adapter *adapter)
 {
-	u64 tdba;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 tctl;
-	u32 txdctl, txctrl;
-	int i, j;
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct igb_ring *ring = &adapter->tx_ring[i];
-		j = ring->reg_idx;
-		wr32(E1000_TDLEN(j),
-		     ring->count * sizeof(union e1000_adv_tx_desc));
-		tdba = ring->dma;
-		wr32(E1000_TDBAL(j),
-		     tdba & 0x00000000ffffffffULL);
-		wr32(E1000_TDBAH(j), tdba >> 32);
-
-		ring->head = E1000_TDH(j);
-		ring->tail = E1000_TDT(j);
-		writel(0, hw->hw_addr + ring->tail);
-		writel(0, hw->hw_addr + ring->head);
-		txdctl = rd32(E1000_TXDCTL(j));
-		txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
-		wr32(E1000_TXDCTL(j), txdctl);
-
-		/* Turn off Relaxed Ordering on head write-backs.  The
-		 * writebacks MUST be delivered in order or it will
-		 * completely screw up our bookeeping.
-		 */
-		txctrl = rd32(E1000_DCA_TXCTRL(j));
-		txctrl &= ~E1000_DCA_TXCTRL_TX_WB_RO_EN;
-		wr32(E1000_DCA_TXCTRL(j), txctrl);
-	}
-
-	/* disable queue 0 to prevent tail bump w/o re-configuration */
-	if (adapter->vfs_allocated_count)
-		wr32(E1000_TXDCTL(0), 0);
+	/* disable queue 0 which is enabled by default on 82575 and 82576 */
+	wr32(E1000_TXDCTL(0), 0);
 
 	/* Program the Transmit Control Register */
 	tctl = rd32(E1000_TCTL);
@@ -1964,9 +2151,6 @@
 
 	igb_config_collision_dist(hw);
 
-	/* Setup Transmit Descriptor Settings for eop descriptor */
-	adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS;
-
 	/* Enable transmits */
 	tctl |= E1000_TCTL_EN;
 
@@ -1974,16 +2158,69 @@
 }
 
 /**
- * igb_setup_rx_resources - allocate Rx resources (Descriptors)
+ * igb_configure_tx_ring - Configure transmit ring after Reset
+ * @adapter: board private structure
+ * @ring: tx ring to configure
+ *
+ * Configure a transmit ring after a reset.
+ **/
+void igb_configure_tx_ring(struct igb_adapter *adapter,
+                           struct igb_ring *ring)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 txdctl;
+	u64 tdba = ring->dma;
+	int reg_idx = ring->reg_idx;
+
+	/* disable the queue */
+	txdctl = rd32(E1000_TXDCTL(reg_idx));
+	wr32(E1000_TXDCTL(reg_idx),
+	                txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
+	wrfl();
+	mdelay(10);
+
+	wr32(E1000_TDLEN(reg_idx),
+	                ring->count * sizeof(union e1000_adv_tx_desc));
+	wr32(E1000_TDBAL(reg_idx),
+	                tdba & 0x00000000ffffffffULL);
+	wr32(E1000_TDBAH(reg_idx), tdba >> 32);
+
+	ring->head = hw->hw_addr + E1000_TDH(reg_idx);
+	ring->tail = hw->hw_addr + E1000_TDT(reg_idx);
+	writel(0, ring->head);
+	writel(0, ring->tail);
+
+	txdctl |= IGB_TX_PTHRESH;
+	txdctl |= IGB_TX_HTHRESH << 8;
+	txdctl |= IGB_TX_WTHRESH << 16;
+
+	txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+	wr32(E1000_TXDCTL(reg_idx), txdctl);
+}
+
+/**
+ * igb_configure_tx - Configure transmit Unit after Reset
  * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+static void igb_configure_tx(struct igb_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		igb_configure_tx_ring(adapter, &adapter->tx_ring[i]);
+}
+
+/**
+ * igb_setup_rx_resources - allocate Rx resources (Descriptors)
  * @rx_ring:    rx descriptor ring (for a specific queue) to setup
  *
  * Returns 0 on success, negative on failure
  **/
-int igb_setup_rx_resources(struct igb_adapter *adapter,
-			   struct igb_ring *rx_ring)
+int igb_setup_rx_resources(struct igb_ring *rx_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
+	struct pci_dev *pdev = rx_ring->pdev;
 	int size, desc_len;
 
 	size = sizeof(struct igb_buffer) * rx_ring->count;
@@ -2007,13 +2244,12 @@
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 
-	rx_ring->adapter = adapter;
-
 	return 0;
 
 err:
 	vfree(rx_ring->buffer_info);
-	dev_err(&adapter->pdev->dev, "Unable to allocate memory for "
+	rx_ring->buffer_info = NULL;
+	dev_err(&pdev->dev, "Unable to allocate memory for "
 		"the receive descriptor ring\n");
 	return -ENOMEM;
 }
@@ -2027,12 +2263,13 @@
  **/
 static int igb_setup_all_rx_resources(struct igb_adapter *adapter)
 {
+	struct pci_dev *pdev = adapter->pdev;
 	int i, err = 0;
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		err = igb_setup_rx_resources(adapter, &adapter->rx_ring[i]);
+		err = igb_setup_rx_resources(&adapter->rx_ring[i]);
 		if (err) {
-			dev_err(&adapter->pdev->dev,
+			dev_err(&pdev->dev,
 				"Allocation for Rx Queue %u failed\n", i);
 			for (i--; i >= 0; i--)
 				igb_free_rx_resources(&adapter->rx_ring[i]);
@@ -2044,15 +2281,122 @@
 }
 
 /**
+ * igb_setup_mrqc - configure the multiple receive queue control registers
+ * @adapter: Board private structure
+ **/
+static void igb_setup_mrqc(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 mrqc, rxcsum;
+	u32 j, num_rx_queues, shift = 0, shift2 = 0;
+	union e1000_reta {
+		u32 dword;
+		u8  bytes[4];
+	} reta;
+	static const u8 rsshash[40] = {
+		0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 0x41, 0x67,
+		0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 0xd0, 0xca, 0x2b, 0xcb,
+		0xae, 0x7b, 0x30, 0xb4,	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30,
+		0xf2, 0x0c, 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa };
+
+	/* Fill out hash function seeds */
+	for (j = 0; j < 10; j++) {
+		u32 rsskey = rsshash[(j * 4)];
+		rsskey |= rsshash[(j * 4) + 1] << 8;
+		rsskey |= rsshash[(j * 4) + 2] << 16;
+		rsskey |= rsshash[(j * 4) + 3] << 24;
+		array_wr32(E1000_RSSRK(0), j, rsskey);
+	}
+
+	num_rx_queues = adapter->rss_queues;
+
+	if (adapter->vfs_allocated_count) {
+		/* 82575 and 82576 supports 2 RSS queues for VMDq */
+		switch (hw->mac.type) {
+		case e1000_82580:
+			num_rx_queues = 1;
+			shift = 0;
+			break;
+		case e1000_82576:
+			shift = 3;
+			num_rx_queues = 2;
+			break;
+		case e1000_82575:
+			shift = 2;
+			shift2 = 6;
+		default:
+			break;
+		}
+	} else {
+		if (hw->mac.type == e1000_82575)
+			shift = 6;
+	}
+
+	for (j = 0; j < (32 * 4); j++) {
+		reta.bytes[j & 3] = (j % num_rx_queues) << shift;
+		if (shift2)
+			reta.bytes[j & 3] |= num_rx_queues << shift2;
+		if ((j & 3) == 3)
+			wr32(E1000_RETA(j >> 2), reta.dword);
+	}
+
+	/*
+	 * Disable raw packet checksumming so that RSS hash is placed in
+	 * descriptor on writeback.  No need to enable TCP/UDP/IP checksum
+	 * offloads as they are enabled by default
+	 */
+	rxcsum = rd32(E1000_RXCSUM);
+	rxcsum |= E1000_RXCSUM_PCSD;
+
+	if (adapter->hw.mac.type >= e1000_82576)
+		/* Enable Receive Checksum Offload for SCTP */
+		rxcsum |= E1000_RXCSUM_CRCOFL;
+
+	/* Don't need to set TUOFL or IPOFL, they default to 1 */
+	wr32(E1000_RXCSUM, rxcsum);
+
+	/* If VMDq is enabled then we set the appropriate mode for that, else
+	 * we default to RSS so that an RSS hash is calculated per packet even
+	 * if we are only using one queue */
+	if (adapter->vfs_allocated_count) {
+		if (hw->mac.type > e1000_82575) {
+			/* Set the default pool for the PF's first queue */
+			u32 vtctl = rd32(E1000_VT_CTL);
+			vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK |
+				   E1000_VT_CTL_DISABLE_DEF_POOL);
+			vtctl |= adapter->vfs_allocated_count <<
+				E1000_VT_CTL_DEFAULT_POOL_SHIFT;
+			wr32(E1000_VT_CTL, vtctl);
+		}
+		if (adapter->rss_queues > 1)
+			mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
+		else
+			mrqc = E1000_MRQC_ENABLE_VMDQ;
+	} else {
+		mrqc = E1000_MRQC_ENABLE_RSS_4Q;
+	}
+	igb_vmm_control(adapter);
+
+	mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
+		 E1000_MRQC_RSS_FIELD_IPV4_TCP);
+	mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 |
+		 E1000_MRQC_RSS_FIELD_IPV6_TCP);
+	mrqc |= (E1000_MRQC_RSS_FIELD_IPV4_UDP |
+		 E1000_MRQC_RSS_FIELD_IPV6_UDP);
+	mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
+		 E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
+
+	wr32(E1000_MRQC, mrqc);
+}
+
+/**
  * igb_setup_rctl - configure the receive control registers
  * @adapter: Board private structure
  **/
-static void igb_setup_rctl(struct igb_adapter *adapter)
+void igb_setup_rctl(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl;
-	u32 srrctl = 0;
-	int i;
 
 	rctl = rd32(E1000_RCTL);
 
@@ -2069,75 +2413,45 @@
 	 */
 	rctl |= E1000_RCTL_SECRC;
 
-	/*
-	 * disable store bad packets and clear size bits.
-	 */
+	/* disable store bad packets and clear size bits. */
 	rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
 
-	/* enable LPE when to prevent packets larger than max_frame_size */
-		rctl |= E1000_RCTL_LPE;
+	/* enable LPE to prevent packets larger than max_frame_size */
+	rctl |= E1000_RCTL_LPE;
 
-	/* Setup buffer sizes */
-	switch (adapter->rx_buffer_len) {
-	case IGB_RXBUFFER_256:
-		rctl |= E1000_RCTL_SZ_256;
-		break;
-	case IGB_RXBUFFER_512:
-		rctl |= E1000_RCTL_SZ_512;
-		break;
-	default:
-		srrctl = ALIGN(adapter->rx_buffer_len, 1024)
-		         >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-		break;
-	}
-
-	/* 82575 and greater support packet-split where the protocol
-	 * header is placed in skb->data and the packet data is
-	 * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
-	 * In the case of a non-split, skb->data is linearly filled,
-	 * followed by the page buffers.  Therefore, skb->data is
-	 * sized to hold the largest protocol header.
-	 */
-	/* allocations using alloc_page take too long for regular MTU
-	 * so only enable packet split for jumbo frames */
-	if (adapter->netdev->mtu > ETH_DATA_LEN) {
-		adapter->rx_ps_hdr_size = IGB_RXBUFFER_128;
-		srrctl |= adapter->rx_ps_hdr_size <<
-			 E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-		srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-	} else {
-		adapter->rx_ps_hdr_size = 0;
-		srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
-	}
+	/* disable queue 0 to prevent tail write w/o re-config */
+	wr32(E1000_RXDCTL(0), 0);
 
 	/* Attention!!!  For SR-IOV PF driver operations you must enable
 	 * queue drop for all VF and PF queues to prevent head of line blocking
 	 * if an un-trusted VF does not provide descriptors to hardware.
 	 */
 	if (adapter->vfs_allocated_count) {
-		u32 vmolr;
-
 		/* set all queue drop enable bits */
 		wr32(E1000_QDE, ALL_QUEUES);
-		srrctl |= E1000_SRRCTL_DROP_EN;
+	}
 
-		/* disable queue 0 to prevent tail write w/o re-config */
-		wr32(E1000_RXDCTL(0), 0);
+	wr32(E1000_RCTL, rctl);
+}
 
-		vmolr = rd32(E1000_VMOLR(adapter->vfs_allocated_count));
-		if (rctl & E1000_RCTL_LPE)
-			vmolr |= E1000_VMOLR_LPE;
-		if (adapter->num_rx_queues > 1)
-			vmolr |= E1000_VMOLR_RSSE;
-		wr32(E1000_VMOLR(adapter->vfs_allocated_count), vmolr);
-	}
+static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
+                                   int vfn)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 vmolr;
 
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		int j = adapter->rx_ring[i].reg_idx;
-		wr32(E1000_SRRCTL(j), srrctl);
-	}
+	/* if it isn't the PF check to see if VFs are enabled and
+	 * increase the size to support vlan tags */
+	if (vfn < adapter->vfs_allocated_count &&
+	    adapter->vf_data[vfn].vlans_enabled)
+		size += VLAN_TAG_SIZE;
 
-	wr32(E1000_RCTL, rctl);
+	vmolr = rd32(E1000_VMOLR(vfn));
+	vmolr &= ~E1000_VMOLR_RLPML_MASK;
+	vmolr |= size | E1000_VMOLR_LPE;
+	wr32(E1000_VMOLR(vfn), vmolr);
+
+	return 0;
 }
 
 /**
@@ -2159,33 +2473,107 @@
 	 * size and set the VMOLR RLPML to the size we need */
 	if (pf_id) {
 		igb_set_vf_rlpml(adapter, max_frame_size, pf_id);
-		max_frame_size = MAX_STD_JUMBO_FRAME_SIZE + VLAN_TAG_SIZE;
+		max_frame_size = MAX_JUMBO_FRAME_SIZE;
 	}
 
 	wr32(E1000_RLPML, max_frame_size);
 }
 
+static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 vmolr;
+
+	/*
+	 * This register exists only on 82576 and newer so if we are older then
+	 * we should exit and do nothing
+	 */
+	if (hw->mac.type < e1000_82576)
+		return;
+
+	vmolr = rd32(E1000_VMOLR(vfn));
+	vmolr |= E1000_VMOLR_AUPE |        /* Accept untagged packets */
+	         E1000_VMOLR_STRVLAN;      /* Strip vlan tags */
+
+	/* clear all bits that might not be set */
+	vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE);
+
+	if (adapter->rss_queues > 1 && vfn == adapter->vfs_allocated_count)
+		vmolr |= E1000_VMOLR_RSSE; /* enable RSS */
+	/*
+	 * for VMDq only allow the VFs and pool 0 to accept broadcast and
+	 * multicast packets
+	 */
+	if (vfn <= adapter->vfs_allocated_count)
+		vmolr |= E1000_VMOLR_BAM;	   /* Accept broadcast */
+
+	wr32(E1000_VMOLR(vfn), vmolr);
+}
+
 /**
- * igb_configure_vt_default_pool - Configure VT default pool
+ * igb_configure_rx_ring - Configure a receive ring after Reset
  * @adapter: board private structure
+ * @ring: receive ring to be configured
  *
- * Configure the default pool
+ * Configure the Rx unit of the MAC after a reset.
  **/
-static void igb_configure_vt_default_pool(struct igb_adapter *adapter)
+void igb_configure_rx_ring(struct igb_adapter *adapter,
+                           struct igb_ring *ring)
 {
 	struct e1000_hw *hw = &adapter->hw;
-	u16 pf_id = adapter->vfs_allocated_count;
-	u32 vtctl;
+	u64 rdba = ring->dma;
+	int reg_idx = ring->reg_idx;
+	u32 srrctl, rxdctl;
+
+	/* disable the queue */
+	rxdctl = rd32(E1000_RXDCTL(reg_idx));
+	wr32(E1000_RXDCTL(reg_idx),
+	                rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
+
+	/* Set DMA base address registers */
+	wr32(E1000_RDBAL(reg_idx),
+	     rdba & 0x00000000ffffffffULL);
+	wr32(E1000_RDBAH(reg_idx), rdba >> 32);
+	wr32(E1000_RDLEN(reg_idx),
+	               ring->count * sizeof(union e1000_adv_rx_desc));
+
+	/* initialize head and tail */
+	ring->head = hw->hw_addr + E1000_RDH(reg_idx);
+	ring->tail = hw->hw_addr + E1000_RDT(reg_idx);
+	writel(0, ring->head);
+	writel(0, ring->tail);
+
+	/* set descriptor configuration */
+	if (ring->rx_buffer_len < IGB_RXBUFFER_1024) {
+		srrctl = ALIGN(ring->rx_buffer_len, 64) <<
+		         E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
+		srrctl |= IGB_RXBUFFER_16384 >>
+		          E1000_SRRCTL_BSIZEPKT_SHIFT;
+#else
+		srrctl |= (PAGE_SIZE / 2) >>
+		          E1000_SRRCTL_BSIZEPKT_SHIFT;
+#endif
+		srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+	} else {
+		srrctl = ALIGN(ring->rx_buffer_len, 1024) >>
+		         E1000_SRRCTL_BSIZEPKT_SHIFT;
+		srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
+	}
 
-	/* not in sr-iov mode - do nothing */
-	if (!pf_id)
-		return;
+	wr32(E1000_SRRCTL(reg_idx), srrctl);
+
+	/* set filtering for VMDQ pools */
+	igb_set_vmolr(adapter, reg_idx & 0x7);
 
-	vtctl = rd32(E1000_VT_CTL);
-	vtctl &= ~(E1000_VT_CTL_DEFAULT_POOL_MASK |
-		   E1000_VT_CTL_DISABLE_DEF_POOL);
-	vtctl |= pf_id << E1000_VT_CTL_DEFAULT_POOL_SHIFT;
-	wr32(E1000_VT_CTL, vtctl);
+	/* enable receive descriptor fetching */
+	rxdctl = rd32(E1000_RXDCTL(reg_idx));
+	rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
+	rxdctl &= 0xFFF00000;
+	rxdctl |= IGB_RX_PTHRESH;
+	rxdctl |= IGB_RX_HTHRESH << 8;
+	rxdctl |= IGB_RX_WTHRESH << 16;
+	wr32(E1000_RXDCTL(reg_idx), rxdctl);
 }
 
 /**
@@ -2196,112 +2584,19 @@
  **/
 static void igb_configure_rx(struct igb_adapter *adapter)
 {
-	u64 rdba;
-	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl, rxcsum;
-	u32 rxdctl;
 	int i;
 
-	/* disable receives while setting up the descriptors */
-	rctl = rd32(E1000_RCTL);
-	wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
-	wrfl();
-	mdelay(10);
+	/* set UTA to appropriate mode */
+	igb_set_uta(adapter);
 
-	if (adapter->itr_setting > 3)
-		wr32(E1000_ITR, adapter->itr);
+	/* set the correct pool for the PF default MAC address in entry 0 */
+	igb_rar_set_qsel(adapter, adapter->hw.mac.addr, 0,
+	                 adapter->vfs_allocated_count);
 
 	/* Setup the HW Rx Head and Tail Descriptor Pointers and
 	 * the Base and Length of the Rx Descriptor Ring */
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct igb_ring *ring = &adapter->rx_ring[i];
-		int j = ring->reg_idx;
-		rdba = ring->dma;
-		wr32(E1000_RDBAL(j),
-		     rdba & 0x00000000ffffffffULL);
-		wr32(E1000_RDBAH(j), rdba >> 32);
-		wr32(E1000_RDLEN(j),
-		     ring->count * sizeof(union e1000_adv_rx_desc));
-
-		ring->head = E1000_RDH(j);
-		ring->tail = E1000_RDT(j);
-		writel(0, hw->hw_addr + ring->tail);
-		writel(0, hw->hw_addr + ring->head);
-
-		rxdctl = rd32(E1000_RXDCTL(j));
-		rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
-		rxdctl &= 0xFFF00000;
-		rxdctl |= IGB_RX_PTHRESH;
-		rxdctl |= IGB_RX_HTHRESH << 8;
-		rxdctl |= IGB_RX_WTHRESH << 16;
-		wr32(E1000_RXDCTL(j), rxdctl);
-	}
-
-	if (adapter->num_rx_queues > 1) {
-		u32 random[10];
-		u32 mrqc;
-		u32 j, shift;
-		union e1000_reta {
-			u32 dword;
-			u8  bytes[4];
-		} reta;
-
-		get_random_bytes(&random[0], 40);
-
-		if (hw->mac.type >= e1000_82576)
-			shift = 0;
-		else
-			shift = 6;
-		for (j = 0; j < (32 * 4); j++) {
-			reta.bytes[j & 3] =
-				adapter->rx_ring[(j % adapter->num_rx_queues)].reg_idx << shift;
-			if ((j & 3) == 3)
-				writel(reta.dword,
-				       hw->hw_addr + E1000_RETA(0) + (j & ~3));
-		}
-		if (adapter->vfs_allocated_count)
-			mrqc = E1000_MRQC_ENABLE_VMDQ_RSS_2Q;
-		else
-			mrqc = E1000_MRQC_ENABLE_RSS_4Q;
-
-		/* Fill out hash function seeds */
-		for (j = 0; j < 10; j++)
-			array_wr32(E1000_RSSRK(0), j, random[j]);
-
-		mrqc |= (E1000_MRQC_RSS_FIELD_IPV4 |
-			 E1000_MRQC_RSS_FIELD_IPV4_TCP);
-		mrqc |= (E1000_MRQC_RSS_FIELD_IPV6 |
-			 E1000_MRQC_RSS_FIELD_IPV6_TCP);
-		mrqc |= (E1000_MRQC_RSS_FIELD_IPV4_UDP |
-			 E1000_MRQC_RSS_FIELD_IPV6_UDP);
-		mrqc |= (E1000_MRQC_RSS_FIELD_IPV6_UDP_EX |
-			 E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);
-
-		wr32(E1000_MRQC, mrqc);
-	} else if (adapter->vfs_allocated_count) {
-		/* Enable multi-queue for sr-iov */
-		wr32(E1000_MRQC, E1000_MRQC_ENABLE_VMDQ);
-	}
-
-	/* Enable Receive Checksum Offload for TCP and UDP */
-	rxcsum = rd32(E1000_RXCSUM);
-	/* Disable raw packet checksumming */
-	rxcsum |= E1000_RXCSUM_PCSD;
-
-	if (adapter->hw.mac.type == e1000_82576)
-		/* Enable Receive Checksum Offload for SCTP */
-		rxcsum |= E1000_RXCSUM_CRCOFL;
-
-	/* Don't need to set TUOFL or IPOFL, they default to 1 */
-	wr32(E1000_RXCSUM, rxcsum);
-
-	/* Set the default pool for the PF's first queue */
-	igb_configure_vt_default_pool(adapter);
-
-	igb_rlpml_set(adapter);
-
-	/* Enable Receives */
-	wr32(E1000_RCTL, rctl);
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		igb_configure_rx_ring(adapter, &adapter->rx_ring[i]);
 }
 
 /**
@@ -2312,14 +2607,17 @@
  **/
 void igb_free_tx_resources(struct igb_ring *tx_ring)
 {
-	struct pci_dev *pdev = tx_ring->adapter->pdev;
-
 	igb_clean_tx_ring(tx_ring);
 
 	vfree(tx_ring->buffer_info);
 	tx_ring->buffer_info = NULL;
 
-	pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma);
+	/* if not set, then don't free */
+	if (!tx_ring->desc)
+		return;
+
+	pci_free_consistent(tx_ring->pdev, tx_ring->size,
+	                    tx_ring->desc, tx_ring->dma);
 
 	tx_ring->desc = NULL;
 }
@@ -2338,18 +2636,30 @@
 		igb_free_tx_resources(&adapter->tx_ring[i]);
 }
 
-static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter,
-					   struct igb_buffer *buffer_info)
+void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring,
+				    struct igb_buffer *buffer_info)
 {
-	buffer_info->dma = 0;
+	if (buffer_info->dma) {
+		if (buffer_info->mapped_as_page)
+			pci_unmap_page(tx_ring->pdev,
+					buffer_info->dma,
+					buffer_info->length,
+					PCI_DMA_TODEVICE);
+		else
+			pci_unmap_single(tx_ring->pdev,
+					buffer_info->dma,
+					buffer_info->length,
+					PCI_DMA_TODEVICE);
+		buffer_info->dma = 0;
+	}
 	if (buffer_info->skb) {
-		skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb,
-		              DMA_TO_DEVICE);
 		dev_kfree_skb_any(buffer_info->skb);
 		buffer_info->skb = NULL;
 	}
 	buffer_info->time_stamp = 0;
-	/* buffer_info must be completely set up in the transmit path */
+	buffer_info->length = 0;
+	buffer_info->next_to_watch = 0;
+	buffer_info->mapped_as_page = false;
 }
 
 /**
@@ -2358,7 +2668,6 @@
  **/
 static void igb_clean_tx_ring(struct igb_ring *tx_ring)
 {
-	struct igb_adapter *adapter = tx_ring->adapter;
 	struct igb_buffer *buffer_info;
 	unsigned long size;
 	unsigned int i;
@@ -2369,21 +2678,17 @@
 
 	for (i = 0; i < tx_ring->count; i++) {
 		buffer_info = &tx_ring->buffer_info[i];
-		igb_unmap_and_free_tx_resource(adapter, buffer_info);
+		igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
 	}
 
 	size = sizeof(struct igb_buffer) * tx_ring->count;
 	memset(tx_ring->buffer_info, 0, size);
 
 	/* Zero out the descriptor ring */
-
 	memset(tx_ring->desc, 0, tx_ring->size);
 
 	tx_ring->next_to_use = 0;
 	tx_ring->next_to_clean = 0;
-
-	writel(0, adapter->hw.hw_addr + tx_ring->head);
-	writel(0, adapter->hw.hw_addr + tx_ring->tail);
 }
 
 /**
@@ -2406,14 +2711,17 @@
  **/
 void igb_free_rx_resources(struct igb_ring *rx_ring)
 {
-	struct pci_dev *pdev = rx_ring->adapter->pdev;
-
 	igb_clean_rx_ring(rx_ring);
 
 	vfree(rx_ring->buffer_info);
 	rx_ring->buffer_info = NULL;
 
-	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
+	/* if not set, then don't free */
+	if (!rx_ring->desc)
+		return;
+
+	pci_free_consistent(rx_ring->pdev, rx_ring->size,
+	                    rx_ring->desc, rx_ring->dma);
 
 	rx_ring->desc = NULL;
 }
@@ -2438,26 +2746,21 @@
  **/
 static void igb_clean_rx_ring(struct igb_ring *rx_ring)
 {
-	struct igb_adapter *adapter = rx_ring->adapter;
 	struct igb_buffer *buffer_info;
-	struct pci_dev *pdev = adapter->pdev;
 	unsigned long size;
 	unsigned int i;
 
 	if (!rx_ring->buffer_info)
 		return;
+
 	/* Free all the Rx ring sk_buffs */
 	for (i = 0; i < rx_ring->count; i++) {
 		buffer_info = &rx_ring->buffer_info[i];
 		if (buffer_info->dma) {
-			if (adapter->rx_ps_hdr_size)
-				pci_unmap_single(pdev, buffer_info->dma,
-						 adapter->rx_ps_hdr_size,
-						 PCI_DMA_FROMDEVICE);
-			else
-				pci_unmap_single(pdev, buffer_info->dma,
-						 adapter->rx_buffer_len,
-						 PCI_DMA_FROMDEVICE);
+			pci_unmap_single(rx_ring->pdev,
+			                 buffer_info->dma,
+					 rx_ring->rx_buffer_len,
+					 PCI_DMA_FROMDEVICE);
 			buffer_info->dma = 0;
 		}
 
@@ -2465,14 +2768,16 @@
 			dev_kfree_skb(buffer_info->skb);
 			buffer_info->skb = NULL;
 		}
+		if (buffer_info->page_dma) {
+			pci_unmap_page(rx_ring->pdev,
+			               buffer_info->page_dma,
+				       PAGE_SIZE / 2,
+				       PCI_DMA_FROMDEVICE);
+			buffer_info->page_dma = 0;
+		}
 		if (buffer_info->page) {
-			if (buffer_info->page_dma)
-				pci_unmap_page(pdev, buffer_info->page_dma,
-					       PAGE_SIZE / 2,
-					       PCI_DMA_FROMDEVICE);
 			put_page(buffer_info->page);
 			buffer_info->page = NULL;
-			buffer_info->page_dma = 0;
 			buffer_info->page_offset = 0;
 		}
 	}
@@ -2483,48 +2788,135 @@
 	/* Zero out the descriptor ring */
 	memset(rx_ring->desc, 0, rx_ring->size);
 
-	rx_ring->next_to_clean = 0;
-	rx_ring->next_to_use = 0;
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+}
+
+/**
+ * igb_clean_all_rx_rings - Free Rx Buffers for all queues
+ * @adapter: board private structure
+ **/
+static void igb_clean_all_rx_rings(struct igb_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		igb_clean_rx_ring(&adapter->rx_ring[i]);
+}
+
+/**
+ * igb_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int igb_set_mac(struct net_device *netdev, void *p)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
+
+	/* set the correct pool for the new PF MAC address in entry 0 */
+	igb_rar_set_qsel(adapter, hw->mac.addr, 0,
+	                 adapter->vfs_allocated_count);
+
+	return 0;
+}
+
+/**
+ * igb_write_mc_addr_list - write multicast addresses to MTA
+ * @netdev: network interface device structure
+ *
+ * Writes multicast address list to the MTA hash table.
+ * Returns: -ENOMEM on failure
+ *                0 on no addresses written
+ *                X on writing X addresses to MTA
+ **/
+static int igb_write_mc_addr_list(struct net_device *netdev)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr = netdev->mc_list;
+	u8  *mta_list;
+	u32 vmolr = 0;
+	int i;
+
+	if (!netdev->mc_count) {
+		/* nothing to program, so clear mc list */
+		igb_update_mc_addr_list(hw, NULL, 0);
+		igb_restore_vf_multicasts(adapter);
+		return 0;
+	}
+
+	mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC);
+	if (!mta_list)
+		return -ENOMEM;
+
+	/* set vmolr receive overflow multicast bit */
+	vmolr |= E1000_VMOLR_ROMPE;
 
-	writel(0, adapter->hw.hw_addr + rx_ring->head);
-	writel(0, adapter->hw.hw_addr + rx_ring->tail);
-}
+	/* The shared function expects a packed array of only addresses. */
+	mc_ptr = netdev->mc_list;
 
-/**
- * igb_clean_all_rx_rings - Free Rx Buffers for all queues
- * @adapter: board private structure
- **/
-static void igb_clean_all_rx_rings(struct igb_adapter *adapter)
-{
-	int i;
+	for (i = 0; i < netdev->mc_count; i++) {
+		if (!mc_ptr)
+			break;
+		memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
+		mc_ptr = mc_ptr->next;
+	}
+	igb_update_mc_addr_list(hw, mta_list, i);
+	kfree(mta_list);
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		igb_clean_rx_ring(&adapter->rx_ring[i]);
+	return netdev->mc_count;
 }
 
 /**
- * igb_set_mac - Change the Ethernet Address of the NIC
+ * igb_write_uc_addr_list - write unicast addresses to RAR table
  * @netdev: network interface device structure
- * @p: pointer to an address structure
  *
- * Returns 0 on success, negative on failure
+ * Writes unicast address list to the RAR table.
+ * Returns: -ENOMEM on failure/insufficient address space
+ *                0 on no addresses written
+ *                X on writing X addresses to the RAR table
  **/
-static int igb_set_mac(struct net_device *netdev, void *p)
+static int igb_write_uc_addr_list(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	struct sockaddr *addr = p;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
+	unsigned int vfn = adapter->vfs_allocated_count;
+	unsigned int rar_entries = hw->mac.rar_entry_count - (vfn + 1);
+	int count = 0;
 
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
+	/* return ENOMEM indicating insufficient memory for addresses */
+	if (netdev->uc.count > rar_entries)
+		return -ENOMEM;
 
-	igb_rar_set(hw, hw->mac.addr, 0);
-	igb_set_rah_pool(hw, adapter->vfs_allocated_count, 0);
+	if (netdev->uc.count && rar_entries) {
+		struct netdev_hw_addr *ha;
+		list_for_each_entry(ha, &netdev->uc.list, list) {
+			if (!rar_entries)
+				break;
+			igb_rar_set_qsel(adapter, ha->addr,
+			                 rar_entries--,
+			                 vfn);
+			count++;
+		}
+	}
+	/* write the addresses in reverse order to avoid write combining */
+	for (; rar_entries > 0 ; rar_entries--) {
+		wr32(E1000_RAH(rar_entries), 0);
+		wr32(E1000_RAL(rar_entries), 0);
+	}
+	wrfl();
 
-	return 0;
+	return count;
 }
 
 /**
@@ -2540,74 +2932,63 @@
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	unsigned int rar_entries = hw->mac.rar_entry_count -
-	                           (adapter->vfs_allocated_count + 1);
-	struct dev_mc_list *mc_ptr = netdev->mc_list;
-	u8  *mta_list = NULL;
-	u32 rctl;
-	int i;
+	unsigned int vfn = adapter->vfs_allocated_count;
+	u32 rctl, vmolr = 0;
+	int count;
 
 	/* Check for Promiscuous and All Multicast modes */
 	rctl = rd32(E1000_RCTL);
 
+	/* clear the effected bits */
+	rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_VFE);
+
 	if (netdev->flags & IFF_PROMISC) {
 		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-		rctl &= ~E1000_RCTL_VFE;
+		vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME);
 	} else {
-		if (netdev->flags & IFF_ALLMULTI)
+		if (netdev->flags & IFF_ALLMULTI) {
 			rctl |= E1000_RCTL_MPE;
-		else
-			rctl &= ~E1000_RCTL_MPE;
-
-		if (netdev->uc.count > rar_entries)
+			vmolr |= E1000_VMOLR_MPME;
+		} else {
+			/*
+			 * Write addresses to the MTA, if the attempt fails
+			 * then we should just turn on promiscous mode so
+			 * that we can at least receive multicast traffic
+			 */
+			count = igb_write_mc_addr_list(netdev);
+			if (count < 0) {
+				rctl |= E1000_RCTL_MPE;
+				vmolr |= E1000_VMOLR_MPME;
+			} else if (count) {
+				vmolr |= E1000_VMOLR_ROMPE;
+			}
+		}
+		/*
+		 * Write addresses to available RAR registers, if there is not
+		 * sufficient space to store all the addresses then enable
+		 * unicast promiscous mode
+		 */
+		count = igb_write_uc_addr_list(netdev);
+		if (count < 0) {
 			rctl |= E1000_RCTL_UPE;
-		else
-			rctl &= ~E1000_RCTL_UPE;
+			vmolr |= E1000_VMOLR_ROPE;
+		}
 		rctl |= E1000_RCTL_VFE;
 	}
 	wr32(E1000_RCTL, rctl);
 
-	if (netdev->uc.count && rar_entries) {
-		struct netdev_hw_addr *ha;
-		list_for_each_entry(ha, &netdev->uc.list, list) {
-			if (!rar_entries)
-				break;
-			igb_rar_set(hw, ha->addr, rar_entries);
-			igb_set_rah_pool(hw, adapter->vfs_allocated_count,
-			                 rar_entries);
-			rar_entries--;
-		}
-	}
-	/* write the addresses in reverse order to avoid write combining */
-	for (; rar_entries > 0 ; rar_entries--) {
-		wr32(E1000_RAH(rar_entries), 0);
-		wr32(E1000_RAL(rar_entries), 0);
-	}
-	wrfl();
-
-	if (!netdev->mc_count) {
-		/* nothing to program, so clear mc list */
-		igb_update_mc_addr_list(hw, NULL, 0);
-		igb_restore_vf_multicasts(adapter);
-		return;
-	}
-
-	mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC);
-	if (!mta_list) {
-		dev_err(&adapter->pdev->dev,
-		        "failed to allocate multicast filter list\n");
+	/*
+	 * In order to support SR-IOV and eventually VMDq it is necessary to set
+	 * the VMOLR to enable the appropriate modes.  Without this workaround
+	 * we will have issues with VLAN tag stripping not being done for frames
+	 * that are only arriving because we are the default pool
+	 */
+	if (hw->mac.type < e1000_82576)
 		return;
-	}
 
-	/* The shared function expects a packed array of only addresses. */
-	for (i = 0; i < netdev->mc_count; i++) {
-		if (!mc_ptr)
-			break;
-		memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
-		mc_ptr = mc_ptr->next;
-	}
-	igb_update_mc_addr_list(hw, mta_list, i);
-	kfree(mta_list);
+	vmolr |= rd32(E1000_VMOLR(vfn)) &
+	         ~(E1000_VMOLR_ROPE | E1000_VMOLR_MPME | E1000_VMOLR_ROMPE);
+	wr32(E1000_VMOLR(vfn), vmolr);
 	igb_restore_vf_multicasts(adapter);
 }
 
@@ -2669,37 +3050,33 @@
 static void igb_watchdog_task(struct work_struct *work)
 {
 	struct igb_adapter *adapter = container_of(work,
-					struct igb_adapter, watchdog_task);
+	                                           struct igb_adapter,
+                                                   watchdog_task);
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	struct igb_ring *tx_ring = adapter->tx_ring;
 	u32 link;
-	u32 eics = 0;
 	int i;
 
 	link = igb_has_link(adapter);
-	if ((netif_carrier_ok(netdev)) && link)
-		goto link_up;
-
 	if (link) {
 		if (!netif_carrier_ok(netdev)) {
 			u32 ctrl;
-			hw->mac.ops.get_speed_and_duplex(&adapter->hw,
-						   &adapter->link_speed,
-						   &adapter->link_duplex);
+			hw->mac.ops.get_speed_and_duplex(hw,
+			                                 &adapter->link_speed,
+			                                 &adapter->link_duplex);
 
 			ctrl = rd32(E1000_CTRL);
 			/* Links status message must follow this format */
 			printk(KERN_INFO "igb: %s NIC Link is Up %d Mbps %s, "
 				 "Flow Control: %s\n",
-			         netdev->name,
-				 adapter->link_speed,
-				 adapter->link_duplex == FULL_DUPLEX ?
+			       netdev->name,
+			       adapter->link_speed,
+			       adapter->link_duplex == FULL_DUPLEX ?
 				 "Full Duplex" : "Half Duplex",
-				 ((ctrl & E1000_CTRL_TFCE) && (ctrl &
-				 E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
-				 E1000_CTRL_RFCE) ? "RX" : ((ctrl &
-				 E1000_CTRL_TFCE) ? "TX" : "None")));
+			       ((ctrl & E1000_CTRL_TFCE) &&
+			        (ctrl & E1000_CTRL_RFCE)) ? "RX/TX" :
+			       ((ctrl & E1000_CTRL_RFCE) ?  "RX" :
+			       ((ctrl & E1000_CTRL_TFCE) ?  "TX" : "None")));
 
 			/* tweak tx_queue_len according to speed/duplex and
 			 * adjust the timeout factor */
@@ -2743,46 +3120,40 @@
 		}
 	}
 
-link_up:
 	igb_update_stats(adapter);
+	igb_update_adaptive(hw);
 
-	hw->mac.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
-	adapter->tpt_old = adapter->stats.tpt;
-	hw->mac.collision_delta = adapter->stats.colc - adapter->colc_old;
-	adapter->colc_old = adapter->stats.colc;
-
-	adapter->gorc = adapter->stats.gorc - adapter->gorc_old;
-	adapter->gorc_old = adapter->stats.gorc;
-	adapter->gotc = adapter->stats.gotc - adapter->gotc_old;
-	adapter->gotc_old = adapter->stats.gotc;
-
-	igb_update_adaptive(&adapter->hw);
-
-	if (!netif_carrier_ok(netdev)) {
-		if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) {
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		struct igb_ring *tx_ring = &adapter->tx_ring[i];
+		if (!netif_carrier_ok(netdev)) {
 			/* We've lost link, so the controller stops DMA,
 			 * but we've got queued Tx work that's never going
 			 * to get done, so reset controller to flush Tx.
 			 * (Do the reset outside of interrupt context). */
-			adapter->tx_timeout_count++;
-			schedule_work(&adapter->reset_task);
-			/* return immediately since reset is imminent */
-			return;
+			if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) {
+				adapter->tx_timeout_count++;
+				schedule_work(&adapter->reset_task);
+				/* return immediately since reset is imminent */
+				return;
+			}
 		}
+
+		/* Force detection of hung controller every watchdog period */
+		tx_ring->detect_tx_hung = true;
 	}
 
 	/* Cause software interrupt to ensure rx ring is cleaned */
 	if (adapter->msix_entries) {
-		for (i = 0; i < adapter->num_rx_queues; i++)
-			eics |= adapter->rx_ring[i].eims_value;
+		u32 eics = 0;
+		for (i = 0; i < adapter->num_q_vectors; i++) {
+			struct igb_q_vector *q_vector = adapter->q_vector[i];
+			eics |= q_vector->eims_value;
+		}
 		wr32(E1000_EICS, eics);
 	} else {
 		wr32(E1000_ICS, E1000_ICS_RXDMT0);
 	}
 
-	/* Force detection of hung controller every watchdog period */
-	tx_ring->detect_tx_hung = true;
-
 	/* Reset the timer */
 	if (!test_bit(__IGB_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -2796,7 +3167,6 @@
 	latency_invalid = 255
 };
 
-
 /**
  * igb_update_ring_itr - update the dynamic ITR value based on packet size
  *
@@ -2811,25 +3181,37 @@
  *      parameter (see igb_param.c)
  *      NOTE:  This function is called only when operating in a multiqueue
  *             receive environment.
- * @rx_ring: pointer to ring
+ * @q_vector: pointer to q_vector
  **/
-static void igb_update_ring_itr(struct igb_ring *rx_ring)
+static void igb_update_ring_itr(struct igb_q_vector *q_vector)
 {
-	int new_val = rx_ring->itr_val;
+	int new_val = q_vector->itr_val;
 	int avg_wire_size = 0;
-	struct igb_adapter *adapter = rx_ring->adapter;
-
-	if (!rx_ring->total_packets)
-		goto clear_counts; /* no packets, so don't do anything */
+	struct igb_adapter *adapter = q_vector->adapter;
 
 	/* For non-gigabit speeds, just fix the interrupt rate at 4000
 	 * ints/sec - ITR timer value of 120 ticks.
 	 */
 	if (adapter->link_speed != SPEED_1000) {
-		new_val = 120;
+		new_val = 976;
 		goto set_itr_val;
 	}
-	avg_wire_size = rx_ring->total_bytes / rx_ring->total_packets;
+
+	if (q_vector->rx_ring && q_vector->rx_ring->total_packets) {
+		struct igb_ring *ring = q_vector->rx_ring;
+		avg_wire_size = ring->total_bytes / ring->total_packets;
+	}
+
+	if (q_vector->tx_ring && q_vector->tx_ring->total_packets) {
+		struct igb_ring *ring = q_vector->tx_ring;
+		avg_wire_size = max_t(u32, avg_wire_size,
+		                      (ring->total_bytes /
+		                       ring->total_packets));
+	}
+
+	/* if avg_wire_size isn't set no work was done */
+	if (!avg_wire_size)
+		goto clear_counts;
 
 	/* Add 24 bytes to size to account for CRC, preamble, and gap */
 	avg_wire_size += 24;
@@ -2844,13 +3226,19 @@
 		new_val = avg_wire_size / 2;
 
 set_itr_val:
-	if (new_val != rx_ring->itr_val) {
-		rx_ring->itr_val = new_val;
-		rx_ring->set_itr = 1;
+	if (new_val != q_vector->itr_val) {
+		q_vector->itr_val = new_val;
+		q_vector->set_itr = 1;
 	}
 clear_counts:
-	rx_ring->total_bytes = 0;
-	rx_ring->total_packets = 0;
+	if (q_vector->rx_ring) {
+		q_vector->rx_ring->total_bytes = 0;
+		q_vector->rx_ring->total_packets = 0;
+	}
+	if (q_vector->tx_ring) {
+		q_vector->tx_ring->total_bytes = 0;
+		q_vector->tx_ring->total_packets = 0;
+	}
 }
 
 /**
@@ -2867,7 +3255,7 @@
  *      NOTE:  These calculations are only valid when operating in a single-
  *             queue environment.
  * @adapter: pointer to adapter
- * @itr_setting: current adapter->itr
+ * @itr_setting: current q_vector->itr_val
  * @packets: the number of packets during this measurement interval
  * @bytes: the number of bytes during this measurement interval
  **/
@@ -2919,8 +3307,9 @@
 
 static void igb_set_itr(struct igb_adapter *adapter)
 {
+	struct igb_q_vector *q_vector = adapter->q_vector[0];
 	u16 current_itr;
-	u32 new_itr = adapter->itr;
+	u32 new_itr = q_vector->itr_val;
 
 	/* for non-gigabit speeds, just fix the interrupt rate at 4000 */
 	if (adapter->link_speed != SPEED_1000) {
@@ -2934,18 +3323,14 @@
 				    adapter->rx_ring->total_packets,
 				    adapter->rx_ring->total_bytes);
 
-	if (adapter->rx_ring->buddy) {
-		adapter->tx_itr = igb_update_itr(adapter,
-					    adapter->tx_itr,
-					    adapter->tx_ring->total_packets,
-					    adapter->tx_ring->total_bytes);
-		current_itr = max(adapter->rx_itr, adapter->tx_itr);
-	} else {
-		current_itr = adapter->rx_itr;
-	}
+	adapter->tx_itr = igb_update_itr(adapter,
+				    adapter->tx_itr,
+				    adapter->tx_ring->total_packets,
+				    adapter->tx_ring->total_bytes);
+	current_itr = max(adapter->rx_itr, adapter->tx_itr);
 
 	/* conservative mode (itr 3) eliminates the lowest_latency setting */
-	if (adapter->itr_setting == 3 && current_itr == lowest_latency)
+	if (adapter->rx_itr_setting == 3 && current_itr == lowest_latency)
 		current_itr = low_latency;
 
 	switch (current_itr) {
@@ -2966,18 +3351,17 @@
 set_itr_now:
 	adapter->rx_ring->total_bytes = 0;
 	adapter->rx_ring->total_packets = 0;
-	if (adapter->rx_ring->buddy) {
-		adapter->rx_ring->buddy->total_bytes = 0;
-		adapter->rx_ring->buddy->total_packets = 0;
-	}
+	adapter->tx_ring->total_bytes = 0;
+	adapter->tx_ring->total_packets = 0;
 
-	if (new_itr != adapter->itr) {
+	if (new_itr != q_vector->itr_val) {
 		/* this attempts to bias the interrupt rate towards Bulk
 		 * by adding intermediate steps when interrupt rate is
 		 * increasing */
-		new_itr = new_itr > adapter->itr ?
-			     max((new_itr * adapter->itr) /
-			         (new_itr + (adapter->itr >> 2)), new_itr) :
+		new_itr = new_itr > q_vector->itr_val ?
+		             max((new_itr * q_vector->itr_val) /
+		                 (new_itr + (q_vector->itr_val >> 2)),
+		                 new_itr) :
 			     new_itr;
 		/* Don't write the value here; it resets the adapter's
 		 * internal timer, and causes us to delay far longer than
@@ -2985,25 +3369,22 @@
 		 * value at the beginning of the next interrupt so the timing
 		 * ends up being correct.
 		 */
-		adapter->itr = new_itr;
-		adapter->rx_ring->itr_val = new_itr;
-		adapter->rx_ring->set_itr = 1;
+		q_vector->itr_val = new_itr;
+		q_vector->set_itr = 1;
 	}
 
 	return;
 }
 
-
 #define IGB_TX_FLAGS_CSUM		0x00000001
 #define IGB_TX_FLAGS_VLAN		0x00000002
 #define IGB_TX_FLAGS_TSO		0x00000004
 #define IGB_TX_FLAGS_IPV4		0x00000008
-#define IGB_TX_FLAGS_TSTAMP             0x00000010
-#define IGB_TX_FLAGS_VLAN_MASK	0xffff0000
-#define IGB_TX_FLAGS_VLAN_SHIFT	16
+#define IGB_TX_FLAGS_TSTAMP		0x00000010
+#define IGB_TX_FLAGS_VLAN_MASK		0xffff0000
+#define IGB_TX_FLAGS_VLAN_SHIFT		        16
 
-static inline int igb_tso_adv(struct igb_adapter *adapter,
-			      struct igb_ring *tx_ring,
+static inline int igb_tso_adv(struct igb_ring *tx_ring,
 			      struct sk_buff *skb, u32 tx_flags, u8 *hdr_len)
 {
 	struct e1000_adv_tx_context_desc *context_desc;
@@ -3065,8 +3446,8 @@
 	mss_l4len_idx |= (l4len << E1000_ADVTXD_L4LEN_SHIFT);
 
 	/* For 82575, context index must be unique per ring. */
-	if (adapter->flags & IGB_FLAG_NEED_CTX_IDX)
-		mss_l4len_idx |= tx_ring->queue_index << 4;
+	if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
+		mss_l4len_idx |= tx_ring->reg_idx << 4;
 
 	context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx);
 	context_desc->seqnum_seed = 0;
@@ -3083,14 +3464,14 @@
 	return true;
 }
 
-static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
-					struct igb_ring *tx_ring,
-					struct sk_buff *skb, u32 tx_flags)
+static inline bool igb_tx_csum_adv(struct igb_ring *tx_ring,
+				   struct sk_buff *skb, u32 tx_flags)
 {
 	struct e1000_adv_tx_context_desc *context_desc;
-	unsigned int i;
+	struct pci_dev *pdev = tx_ring->pdev;
 	struct igb_buffer *buffer_info;
 	u32 info = 0, tu_cmd = 0;
+	unsigned int i;
 
 	if ((skb->ip_summed == CHECKSUM_PARTIAL) ||
 	    (tx_flags & IGB_TX_FLAGS_VLAN)) {
@@ -3100,6 +3481,7 @@
 
 		if (tx_flags & IGB_TX_FLAGS_VLAN)
 			info |= (tx_flags & IGB_TX_FLAGS_VLAN_MASK);
+
 		info |= (skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT);
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			info |= skb_network_header_len(skb);
@@ -3137,7 +3519,7 @@
 				break;
 			default:
 				if (unlikely(net_ratelimit()))
-					dev_warn(&adapter->pdev->dev,
+					dev_warn(&pdev->dev,
 					    "partial checksum but proto=%x!\n",
 					    skb->protocol);
 				break;
@@ -3146,11 +3528,9 @@
 
 		context_desc->type_tucmd_mlhl = cpu_to_le32(tu_cmd);
 		context_desc->seqnum_seed = 0;
-		if (adapter->flags & IGB_FLAG_NEED_CTX_IDX)
+		if (tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX)
 			context_desc->mss_l4len_idx =
-				cpu_to_le32(tx_ring->queue_index << 4);
-		else
-			context_desc->mss_l4len_idx = 0;
+				cpu_to_le32(tx_ring->reg_idx << 4);
 
 		buffer_info->time_stamp = jiffies;
 		buffer_info->next_to_watch = i;
@@ -3169,36 +3549,32 @@
 #define IGB_MAX_TXD_PWR	16
 #define IGB_MAX_DATA_PER_TXD	(1<<IGB_MAX_TXD_PWR)
 
-static inline int igb_tx_map_adv(struct igb_adapter *adapter,
-				 struct igb_ring *tx_ring, struct sk_buff *skb,
+static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb,
 				 unsigned int first)
 {
 	struct igb_buffer *buffer_info;
+	struct pci_dev *pdev = tx_ring->pdev;
 	unsigned int len = skb_headlen(skb);
 	unsigned int count = 0, i;
 	unsigned int f;
-	dma_addr_t *map;
 
 	i = tx_ring->next_to_use;
 
-	if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) {
-		dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
-		return 0;
-	}
-
-	map = skb_shinfo(skb)->dma_maps;
-
 	buffer_info = &tx_ring->buffer_info[i];
 	BUG_ON(len >= IGB_MAX_DATA_PER_TXD);
 	buffer_info->length = len;
 	/* set time_stamp *before* dma to help avoid a possible race */
 	buffer_info->time_stamp = jiffies;
 	buffer_info->next_to_watch = i;
-	buffer_info->dma = skb_shinfo(skb)->dma_head;
+	buffer_info->dma = pci_map_single(pdev, skb->data, len,
+					  PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(pdev, buffer_info->dma))
+		goto dma_error;
 
 	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
 		struct skb_frag_struct *frag;
 
+		count++;
 		i++;
 		if (i == tx_ring->count)
 			i = 0;
@@ -3211,25 +3587,54 @@
 		buffer_info->length = len;
 		buffer_info->time_stamp = jiffies;
 		buffer_info->next_to_watch = i;
-		buffer_info->dma = map[count];
-		count++;
+		buffer_info->mapped_as_page = true;
+		buffer_info->dma = pci_map_page(pdev,
+						frag->page,
+						frag->page_offset,
+						len,
+						PCI_DMA_TODEVICE);
+		if (pci_dma_mapping_error(pdev, buffer_info->dma))
+			goto dma_error;
+
 	}
 
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
 
-	return count + 1;
+	return ++count;
+
+dma_error:
+	dev_err(&pdev->dev, "TX DMA map failed\n");
+
+	/* clear timestamp and dma mappings for failed buffer_info mapping */
+	buffer_info->dma = 0;
+	buffer_info->time_stamp = 0;
+	buffer_info->length = 0;
+	buffer_info->next_to_watch = 0;
+	buffer_info->mapped_as_page = false;
+	count--;
+
+	/* clear timestamp and dma mappings for remaining portion of packet */
+	while (count >= 0) {
+		count--;
+		i--;
+		if (i < 0)
+			i += tx_ring->count;
+		buffer_info = &tx_ring->buffer_info[i];
+		igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
+	}
+
+	return 0;
 }
 
-static inline void igb_tx_queue_adv(struct igb_adapter *adapter,
-				    struct igb_ring *tx_ring,
+static inline void igb_tx_queue_adv(struct igb_ring *tx_ring,
 				    int tx_flags, int count, u32 paylen,
 				    u8 hdr_len)
 {
-	union e1000_adv_tx_desc *tx_desc = NULL;
+	union e1000_adv_tx_desc *tx_desc;
 	struct igb_buffer *buffer_info;
 	u32 olinfo_status = 0, cmd_type_len;
-	unsigned int i;
+	unsigned int i = tx_ring->next_to_use;
 
 	cmd_type_len = (E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS |
 			E1000_ADVTXD_DCMD_DEXT);
@@ -3254,27 +3659,28 @@
 		olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
 	}
 
-	if ((adapter->flags & IGB_FLAG_NEED_CTX_IDX) &&
-	    (tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_TSO |
+	if ((tx_ring->flags & IGB_RING_FLAG_TX_CTX_IDX) &&
+	    (tx_flags & (IGB_TX_FLAGS_CSUM |
+	                 IGB_TX_FLAGS_TSO |
 			 IGB_TX_FLAGS_VLAN)))
-		olinfo_status |= tx_ring->queue_index << 4;
+		olinfo_status |= tx_ring->reg_idx << 4;
 
 	olinfo_status |= ((paylen - hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT);
 
-	i = tx_ring->next_to_use;
-	while (count--) {
+	do {
 		buffer_info = &tx_ring->buffer_info[i];
 		tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
 		tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
 		tx_desc->read.cmd_type_len =
 			cpu_to_le32(cmd_type_len | buffer_info->length);
 		tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+		count--;
 		i++;
 		if (i == tx_ring->count)
 			i = 0;
-	}
+	} while (count > 0);
 
-	tx_desc->read.cmd_type_len |= cpu_to_le32(adapter->txd_cmd);
+	tx_desc->read.cmd_type_len |= cpu_to_le32(IGB_ADVTXD_DCMD);
 	/* Force memory writes to complete before letting h/w
 	 * know there are new descriptors to fetch.  (Only
 	 * applicable for weak-ordered memory model archs,
@@ -3282,16 +3688,15 @@
 	wmb();
 
 	tx_ring->next_to_use = i;
-	writel(i, adapter->hw.hw_addr + tx_ring->tail);
+	writel(i, tx_ring->tail);
 	/* we need this if more than one processor can write to our tail
 	 * at a time, it syncronizes IO on IA64/Altix systems */
 	mmiowb();
 }
 
-static int __igb_maybe_stop_tx(struct net_device *netdev,
-			       struct igb_ring *tx_ring, int size)
+static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
 {
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct net_device *netdev = tx_ring->netdev;
 
 	netif_stop_subqueue(netdev, tx_ring->queue_index);
 
@@ -3307,66 +3712,43 @@
 
 	/* A reprieve! */
 	netif_wake_subqueue(netdev, tx_ring->queue_index);
-	++adapter->restart_queue;
+	tx_ring->tx_stats.restart_queue++;
 	return 0;
 }
 
-static int igb_maybe_stop_tx(struct net_device *netdev,
-			     struct igb_ring *tx_ring, int size)
+static int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size)
 {
 	if (igb_desc_unused(tx_ring) >= size)
 		return 0;
-	return __igb_maybe_stop_tx(netdev, tx_ring, size);
+	return __igb_maybe_stop_tx(tx_ring, size);
 }
 
-static netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
-					   struct net_device *netdev,
-					   struct igb_ring *tx_ring)
+netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb,
+				    struct igb_ring *tx_ring)
 {
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
 	unsigned int first;
 	unsigned int tx_flags = 0;
 	u8 hdr_len = 0;
-	int count = 0;
-	int tso = 0;
-	union skb_shared_tx *shtx;
-
-	if (test_bit(__IGB_DOWN, &adapter->state)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
-	if (skb->len <= 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
+	int tso = 0, count;
+	union skb_shared_tx *shtx = skb_tx(skb);
 
 	/* need: 1 descriptor per page,
 	 *       + 2 desc gap to keep tail from touching head,
 	 *       + 1 desc for skb->data,
 	 *       + 1 desc for context descriptor,
 	 * otherwise try next time */
-	if (igb_maybe_stop_tx(netdev, tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
+	if (igb_maybe_stop_tx(tx_ring, skb_shinfo(skb)->nr_frags + 4)) {
 		/* this is a hard error */
 		return NETDEV_TX_BUSY;
 	}
 
-	/*
-	 * TODO: check that there currently is no other packet with
-	 * time stamping in the queue
-	 *
-	 * When doing time stamping, keep the connection to the socket
-	 * a while longer: it is still needed by skb_hwtstamp_tx(),
-	 * called either in igb_tx_hwtstamp() or by our caller when
-	 * doing software time stamping.
-	 */
-	shtx = skb_tx(skb);
 	if (unlikely(shtx->hardware)) {
 		shtx->in_progress = 1;
 		tx_flags |= IGB_TX_FLAGS_TSTAMP;
 	}
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb) && adapter->vlgrp) {
 		tx_flags |= IGB_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << IGB_TX_FLAGS_VLAN_SHIFT);
 	}
@@ -3375,37 +3757,38 @@
 		tx_flags |= IGB_TX_FLAGS_IPV4;
 
 	first = tx_ring->next_to_use;
-	tso = skb_is_gso(skb) ? igb_tso_adv(adapter, tx_ring, skb, tx_flags,
-					      &hdr_len) : 0;
+	if (skb_is_gso(skb)) {
+		tso = igb_tso_adv(tx_ring, skb, tx_flags, &hdr_len);
 
-	if (tso < 0) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
+		if (tso < 0) {
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
 	}
 
 	if (tso)
 		tx_flags |= IGB_TX_FLAGS_TSO;
-	else if (igb_tx_csum_adv(adapter, tx_ring, skb, tx_flags) &&
+	else if (igb_tx_csum_adv(tx_ring, skb, tx_flags) &&
 	         (skb->ip_summed == CHECKSUM_PARTIAL))
 		tx_flags |= IGB_TX_FLAGS_CSUM;
 
 	/*
-	 * count reflects descriptors mapped, if 0 then mapping error
+	 * count reflects descriptors mapped, if 0 or less then mapping error
 	 * has occured and we need to rewind the descriptor queue
 	 */
-	count = igb_tx_map_adv(adapter, tx_ring, skb, first);
-
-	if (count) {
-		igb_tx_queue_adv(adapter, tx_ring, tx_flags, count,
-			         skb->len, hdr_len);
-		/* Make sure there is space in the ring for the next send. */
-		igb_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 4);
-	} else {
+	count = igb_tx_map_adv(tx_ring, skb, first);
+	if (!count) {
 		dev_kfree_skb_any(skb);
 		tx_ring->buffer_info[first].time_stamp = 0;
 		tx_ring->next_to_use = first;
+		return NETDEV_TX_OK;
 	}
 
+	igb_tx_queue_adv(tx_ring, tx_flags, count, skb->len, hdr_len);
+
+	/* Make sure there is space in the ring for the next send. */
+	igb_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 4);
+
 	return NETDEV_TX_OK;
 }
 
@@ -3414,8 +3797,18 @@
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct igb_ring *tx_ring;
-
 	int r_idx = 0;
+
+	if (test_bit(__IGB_DOWN, &adapter->state)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (skb->len <= 0) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
 	r_idx = skb->queue_mapping & (IGB_ABS_MAX_TX_QUEUES - 1);
 	tx_ring = adapter->multi_tx_table[r_idx];
 
@@ -3423,7 +3816,7 @@
 	 * to a flow.  Right now, performance is impacted slightly negatively
 	 * if using multiple tx queues.  If the stack breaks away from a
 	 * single qdisc implementation, we can look at this again. */
-	return igb_xmit_frame_ring_adv(skb, netdev, tx_ring);
+	return igb_xmit_frame_ring_adv(skb, tx_ring);
 }
 
 /**
@@ -3437,6 +3830,10 @@
 
 	/* Do the reset outside of interrupt context */
 	adapter->tx_timeout_count++;
+
+	if (hw->mac.type == e1000_82580)
+		hw->dev_spec._82575.global_device_reset = true;
+
 	schedule_work(&adapter->reset_task);
 	wr32(E1000_EICS,
 	     (adapter->eims_enable_mask & ~adapter->eims_other));
@@ -3459,10 +3856,8 @@
  **/
 static struct net_device_stats *igb_get_stats(struct net_device *netdev)
 {
-	struct igb_adapter *adapter = netdev_priv(netdev);
-
 	/* only return the current stats */
-	return &adapter->net_stats;
+	return &netdev->stats;
 }
 
 /**
@@ -3475,16 +3870,17 @@
 static int igb_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+	u32 rx_buffer_len, i;
 
-	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
-	    (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		dev_err(&adapter->pdev->dev, "Invalid MTU setting\n");
+	if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		dev_err(&pdev->dev, "Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
 	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-		dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
+		dev_err(&pdev->dev, "MTU > 9216 not supported.\n");
 		return -EINVAL;
 	}
 
@@ -3493,8 +3889,6 @@
 
 	/* igb_down has a dependency on max_frame_size */
 	adapter->max_frame_size = max_frame;
-	if (netif_running(netdev))
-		igb_down(adapter);
 
 	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
 	 * means we reserve 2 more, this pushes us to allocate from the next
@@ -3502,35 +3896,23 @@
 	 * i.e. RXBUFFER_2048 --> size-4096 slab
 	 */
 
-	if (max_frame <= IGB_RXBUFFER_256)
-		adapter->rx_buffer_len = IGB_RXBUFFER_256;
-	else if (max_frame <= IGB_RXBUFFER_512)
-		adapter->rx_buffer_len = IGB_RXBUFFER_512;
-	else if (max_frame <= IGB_RXBUFFER_1024)
-		adapter->rx_buffer_len = IGB_RXBUFFER_1024;
-	else if (max_frame <= IGB_RXBUFFER_2048)
-		adapter->rx_buffer_len = IGB_RXBUFFER_2048;
+	if (max_frame <= IGB_RXBUFFER_1024)
+		rx_buffer_len = IGB_RXBUFFER_1024;
+	else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
+		rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 	else
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
-		adapter->rx_buffer_len = IGB_RXBUFFER_16384;
-#else
-		adapter->rx_buffer_len = PAGE_SIZE / 2;
-#endif
+		rx_buffer_len = IGB_RXBUFFER_128;
 
-	/* if sr-iov is enabled we need to force buffer size to 1K or larger */
-	if (adapter->vfs_allocated_count &&
-	    (adapter->rx_buffer_len < IGB_RXBUFFER_1024))
-		adapter->rx_buffer_len = IGB_RXBUFFER_1024;
-
-	/* adjust allocation if LPE protects us, and we aren't using SBP */
-	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
-	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))
-		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+	if (netif_running(netdev))
+		igb_down(adapter);
 
-	dev_info(&adapter->pdev->dev, "changing MTU from %d to %d\n",
+	dev_info(&pdev->dev, "changing MTU from %d to %d\n",
 		 netdev->mtu, new_mtu);
 	netdev->mtu = new_mtu;
 
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		adapter->rx_ring[i].rx_buffer_len = rx_buffer_len;
+
 	if (netif_running(netdev))
 		igb_up(adapter);
 	else
@@ -3548,9 +3930,13 @@
 
 void igb_update_stats(struct igb_adapter *adapter)
 {
+	struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
+	u32 rnbc;
 	u16 phy_tmp;
+	int i;
+	u64 bytes, packets;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
@@ -3563,6 +3949,29 @@
 	if (pci_channel_offline(pdev))
 		return;
 
+	bytes = 0;
+	packets = 0;
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF;
+		adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp;
+		net_stats->rx_fifo_errors += rqdpc_tmp;
+		bytes += adapter->rx_ring[i].rx_stats.bytes;
+		packets += adapter->rx_ring[i].rx_stats.packets;
+	}
+
+	net_stats->rx_bytes = bytes;
+	net_stats->rx_packets = packets;
+
+	bytes = 0;
+	packets = 0;
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		bytes += adapter->tx_ring[i].tx_stats.bytes;
+		packets += adapter->tx_ring[i].tx_stats.packets;
+	}
+	net_stats->tx_bytes = bytes;
+	net_stats->tx_packets = packets;
+
+	/* read stats registers */
 	adapter->stats.crcerrs += rd32(E1000_CRCERRS);
 	adapter->stats.gprc += rd32(E1000_GPRC);
 	adapter->stats.gorc += rd32(E1000_GORCL);
@@ -3595,7 +4004,9 @@
 	adapter->stats.gptc += rd32(E1000_GPTC);
 	adapter->stats.gotc += rd32(E1000_GOTCL);
 	rd32(E1000_GOTCH); /* clear GOTCL */
-	adapter->stats.rnbc += rd32(E1000_RNBC);
+	rnbc = rd32(E1000_RNBC);
+	adapter->stats.rnbc += rnbc;
+	net_stats->rx_fifo_errors += rnbc;
 	adapter->stats.ruc += rd32(E1000_RUC);
 	adapter->stats.rfc += rd32(E1000_RFC);
 	adapter->stats.rjc += rd32(E1000_RJC);
@@ -3614,7 +4025,6 @@
 	adapter->stats.bptc += rd32(E1000_BPTC);
 
 	/* used for adaptive IFS */
-
 	hw->mac.tx_packet_delta = rd32(E1000_TPT);
 	adapter->stats.tpt += hw->mac.tx_packet_delta;
 	hw->mac.collision_delta = rd32(E1000_COLC);
@@ -3637,56 +4047,29 @@
 	adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC);
 
 	/* Fill out the OS statistics structure */
-	adapter->net_stats.multicast = adapter->stats.mprc;
-	adapter->net_stats.collisions = adapter->stats.colc;
+	net_stats->multicast = adapter->stats.mprc;
+	net_stats->collisions = adapter->stats.colc;
 
 	/* Rx Errors */
 
-	if (hw->mac.type != e1000_82575) {
-		u32 rqdpc_tmp;
-		u64 rqdpc_total = 0;
-		int i;
-		/* Read out drops stats per RX queue.  Notice RQDPC (Receive
-		 * Queue Drop Packet Count) stats only gets incremented, if
-		 * the DROP_EN but it set (in the SRRCTL register for that
-		 * queue).  If DROP_EN bit is NOT set, then the some what
-		 * equivalent count is stored in RNBC (not per queue basis).
-		 * Also note the drop count is due to lack of available
-		 * descriptors.
-		 */
-		for (i = 0; i < adapter->num_rx_queues; i++) {
-			rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0xFFF;
-			adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp;
-			rqdpc_total += adapter->rx_ring[i].rx_stats.drops;
-		}
-		adapter->net_stats.rx_fifo_errors = rqdpc_total;
-	}
-
-	/* Note RNBC (Receive No Buffers Count) is an not an exact
-	 * drop count as the hardware FIFO might save the day.  Thats
-	 * one of the reason for saving it in rx_fifo_errors, as its
-	 * potentially not a true drop.
-	 */
-	adapter->net_stats.rx_fifo_errors += adapter->stats.rnbc;
-
 	/* RLEC on some newer hardware can be incorrect so build
 	 * our own version based on RUC and ROC */
-	adapter->net_stats.rx_errors = adapter->stats.rxerrc +
+	net_stats->rx_errors = adapter->stats.rxerrc +
 		adapter->stats.crcerrs + adapter->stats.algnerrc +
 		adapter->stats.ruc + adapter->stats.roc +
 		adapter->stats.cexterr;
-	adapter->net_stats.rx_length_errors = adapter->stats.ruc +
-					      adapter->stats.roc;
-	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
-	adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
-	adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
+	net_stats->rx_length_errors = adapter->stats.ruc +
+				      adapter->stats.roc;
+	net_stats->rx_crc_errors = adapter->stats.crcerrs;
+	net_stats->rx_frame_errors = adapter->stats.algnerrc;
+	net_stats->rx_missed_errors = adapter->stats.mpc;
 
 	/* Tx Errors */
-	adapter->net_stats.tx_errors = adapter->stats.ecol +
-				       adapter->stats.latecol;
-	adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
-	adapter->net_stats.tx_window_errors = adapter->stats.latecol;
-	adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
+	net_stats->tx_errors = adapter->stats.ecol +
+			       adapter->stats.latecol;
+	net_stats->tx_aborted_errors = adapter->stats.ecol;
+	net_stats->tx_window_errors = adapter->stats.latecol;
+	net_stats->tx_carrier_errors = adapter->stats.tncrs;
 
 	/* Tx Dropped needs to be maintained elsewhere */
 
@@ -3707,14 +4090,12 @@
 
 static irqreturn_t igb_msix_other(int irq, void *data)
 {
-	struct net_device *netdev = data;
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct igb_adapter *adapter = data;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 icr = rd32(E1000_ICR);
-
 	/* reading ICR causes bit 31 of EICR to be cleared */
 
-	if(icr & E1000_ICR_DOUTSYNC) {
+	if (icr & E1000_ICR_DOUTSYNC) {
 		/* HW is reporting DMA is out of sync */
 		adapter->stats.doosync++;
 	}
@@ -3730,125 +4111,90 @@
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-	wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC | E1000_IMS_VMMB);
+	if (adapter->vfs_allocated_count)
+		wr32(E1000_IMS, E1000_IMS_LSC |
+				E1000_IMS_VMMB |
+				E1000_IMS_DOUTSYNC);
+	else
+		wr32(E1000_IMS, E1000_IMS_LSC | E1000_IMS_DOUTSYNC);
 	wr32(E1000_EIMS, adapter->eims_other);
 
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t igb_msix_tx(int irq, void *data)
+static void igb_write_itr(struct igb_q_vector *q_vector)
 {
-	struct igb_ring *tx_ring = data;
-	struct igb_adapter *adapter = tx_ring->adapter;
-	struct e1000_hw *hw = &adapter->hw;
+	u32 itr_val = q_vector->itr_val & 0x7FFC;
 
-#ifdef CONFIG_IGB_DCA
-	if (adapter->flags & IGB_FLAG_DCA_ENABLED)
-		igb_update_tx_dca(tx_ring);
-#endif
+	if (!q_vector->set_itr)
+		return;
 
-	tx_ring->total_bytes = 0;
-	tx_ring->total_packets = 0;
+	if (!itr_val)
+		itr_val = 0x4;
 
-	/* auto mask will automatically reenable the interrupt when we write
-	 * EICS */
-	if (!igb_clean_tx_irq(tx_ring))
-		/* Ring was not completely cleaned, so fire another interrupt */
-		wr32(E1000_EICS, tx_ring->eims_value);
+	if (q_vector->itr_shift)
+		itr_val |= itr_val << q_vector->itr_shift;
 	else
-		wr32(E1000_EIMS, tx_ring->eims_value);
-
-	return IRQ_HANDLED;
-}
+		itr_val |= 0x8000000;
 
-static void igb_write_itr(struct igb_ring *ring)
-{
-	struct e1000_hw *hw = &ring->adapter->hw;
-	if ((ring->adapter->itr_setting & 3) && ring->set_itr) {
-		switch (hw->mac.type) {
-		case e1000_82576:
-			wr32(ring->itr_register, ring->itr_val |
-			     0x80000000);
-			break;
-		default:
-			wr32(ring->itr_register, ring->itr_val |
-			     (ring->itr_val << 16));
-			break;
-		}
-		ring->set_itr = 0;
-	}
+	writel(itr_val, q_vector->itr_register);
+	q_vector->set_itr = 0;
 }
 
-static irqreturn_t igb_msix_rx(int irq, void *data)
+static irqreturn_t igb_msix_ring(int irq, void *data)
 {
-	struct igb_ring *rx_ring = data;
-
-	/* Write the ITR value calculated at the end of the
-	 * previous interrupt.
-	 */
+	struct igb_q_vector *q_vector = data;
 
-	igb_write_itr(rx_ring);
+	/* Write the ITR value calculated from the previous interrupt. */
+	igb_write_itr(q_vector);
 
-	if (napi_schedule_prep(&rx_ring->napi))
-		__napi_schedule(&rx_ring->napi);
-
-#ifdef CONFIG_IGB_DCA
-	if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
-		igb_update_rx_dca(rx_ring);
-#endif
-		return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_IGB_DCA
-static void igb_update_rx_dca(struct igb_ring *rx_ring)
-{
-	u32 dca_rxctrl;
-	struct igb_adapter *adapter = rx_ring->adapter;
-	struct e1000_hw *hw = &adapter->hw;
-	int cpu = get_cpu();
-	int q = rx_ring->reg_idx;
+	napi_schedule(&q_vector->napi);
 
-	if (rx_ring->cpu != cpu) {
-		dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
-		if (hw->mac.type == e1000_82576) {
-			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
-			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-			              E1000_DCA_RXCTRL_CPUID_SHIFT;
-		} else {
-			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
-			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-		}
-		dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
-		dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
-		dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
-		wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
-		rx_ring->cpu = cpu;
-	}
-	put_cpu();
+	return IRQ_HANDLED;
 }
 
-static void igb_update_tx_dca(struct igb_ring *tx_ring)
+#ifdef CONFIG_IGB_DCA
+static void igb_update_dca(struct igb_q_vector *q_vector)
 {
-	u32 dca_txctrl;
-	struct igb_adapter *adapter = tx_ring->adapter;
+	struct igb_adapter *adapter = q_vector->adapter;
 	struct e1000_hw *hw = &adapter->hw;
 	int cpu = get_cpu();
-	int q = tx_ring->reg_idx;
 
-	if (tx_ring->cpu != cpu) {
-		dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
-		if (hw->mac.type == e1000_82576) {
+	if (q_vector->cpu == cpu)
+		goto out_no_update;
+
+	if (q_vector->tx_ring) {
+		int q = q_vector->tx_ring->reg_idx;
+		u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
+		if (hw->mac.type == e1000_82575) {
+			dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
+			dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+		} else {
 			dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
 			dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
 			              E1000_DCA_TXCTRL_CPUID_SHIFT;
-		} else {
-			dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
-			dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
 		}
 		dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
 		wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
-		tx_ring->cpu = cpu;
 	}
+	if (q_vector->rx_ring) {
+		int q = q_vector->rx_ring->reg_idx;
+		u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
+		if (hw->mac.type == e1000_82575) {
+			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
+			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
+		} else {
+			dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
+			dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
+			              E1000_DCA_RXCTRL_CPUID_SHIFT;
+		}
+		dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
+		dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
+		dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
+		wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
+	}
+	q_vector->cpu = cpu;
+out_no_update:
 	put_cpu();
 }
 
@@ -3863,13 +4209,10 @@
 	/* Always use CB2 mode, difference is masked in the CB driver. */
 	wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2);
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		adapter->tx_ring[i].cpu = -1;
-		igb_update_tx_dca(&adapter->tx_ring[i]);
-	}
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		adapter->rx_ring[i].cpu = -1;
-		igb_update_rx_dca(&adapter->rx_ring[i]);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		q_vector->cpu = -1;
+		igb_update_dca(q_vector);
 	}
 }
 
@@ -3877,6 +4220,7 @@
 {
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_hw *hw = &adapter->hw;
 	unsigned long event = *(unsigned long *)data;
 
@@ -3885,12 +4229,9 @@
 		/* if already enabled, don't do it again */
 		if (adapter->flags & IGB_FLAG_DCA_ENABLED)
 			break;
-		/* Always use CB2 mode, difference is masked
-		 * in the CB driver. */
-		wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2);
 		if (dca_add_requester(dev) == 0) {
 			adapter->flags |= IGB_FLAG_DCA_ENABLED;
-			dev_info(&adapter->pdev->dev, "DCA enabled\n");
+			dev_info(&pdev->dev, "DCA enabled\n");
 			igb_setup_dca(adapter);
 			break;
 		}
@@ -3898,9 +4239,9 @@
 	case DCA_PROVIDER_REMOVE:
 		if (adapter->flags & IGB_FLAG_DCA_ENABLED) {
 			/* without this a class_device is left
- 			 * hanging around in the sysfs model */
+			 * hanging around in the sysfs model */
 			dca_remove_requester(dev);
-			dev_info(&adapter->pdev->dev, "DCA disabled\n");
+			dev_info(&pdev->dev, "DCA disabled\n");
 			adapter->flags &= ~IGB_FLAG_DCA_ENABLED;
 			wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_DISABLE);
 		}
@@ -3930,12 +4271,51 @@
 
 	for (i = 0 ; i < adapter->vfs_allocated_count; i++) {
 		ping = E1000_PF_CONTROL_MSG;
-		if (adapter->vf_data[i].clear_to_send)
+		if (adapter->vf_data[i].flags & IGB_VF_FLAG_CTS)
 			ping |= E1000_VT_MSGTYPE_CTS;
 		igb_write_mbx(hw, &ping, 1, i);
 	}
 }
 
+static int igb_set_vf_promisc(struct igb_adapter *adapter, u32 *msgbuf, u32 vf)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 vmolr = rd32(E1000_VMOLR(vf));
+	struct vf_data_storage *vf_data = &adapter->vf_data[vf];
+
+	vf_data->flags |= ~(IGB_VF_FLAG_UNI_PROMISC |
+	                    IGB_VF_FLAG_MULTI_PROMISC);
+	vmolr &= ~(E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | E1000_VMOLR_MPME);
+
+	if (*msgbuf & E1000_VF_SET_PROMISC_MULTICAST) {
+		vmolr |= E1000_VMOLR_MPME;
+		*msgbuf &= ~E1000_VF_SET_PROMISC_MULTICAST;
+	} else {
+		/*
+		 * if we have hashes and we are clearing a multicast promisc
+		 * flag we need to write the hashes to the MTA as this step
+		 * was previously skipped
+		 */
+		if (vf_data->num_vf_mc_hashes > 30) {
+			vmolr |= E1000_VMOLR_MPME;
+		} else if (vf_data->num_vf_mc_hashes) {
+			int j;
+			vmolr |= E1000_VMOLR_ROMPE;
+			for (j = 0; j < vf_data->num_vf_mc_hashes; j++)
+				igb_mta_set(hw, vf_data->vf_mc_hashes[j]);
+		}
+	}
+
+	wr32(E1000_VMOLR(vf), vmolr);
+
+	/* there are flags left unprocessed, likely not supported */
+	if (*msgbuf & E1000_VT_MSGINFO_MASK)
+		return -EINVAL;
+
+	return 0;
+
+}
+
 static int igb_set_vf_multicasts(struct igb_adapter *adapter,
 				  u32 *msgbuf, u32 vf)
 {
@@ -3944,18 +4324,17 @@
 	struct vf_data_storage *vf_data = &adapter->vf_data[vf];
 	int i;
 
-	/* only up to 30 hash values supported */
-	if (n > 30)
-		n = 30;
-
-	/* salt away the number of multi cast addresses assigned
+	/* salt away the number of multicast addresses assigned
 	 * to this VF for later use to restore when the PF multi cast
 	 * list changes
 	 */
 	vf_data->num_vf_mc_hashes = n;
 
-	/* VFs are limited to using the MTA hash table for their multicast
-	 * addresses */
+	/* only up to 30 hash values supported */
+	if (n > 30)
+		n = 30;
+
+	/* store the hashes for later use */
 	for (i = 0; i < n; i++)
 		vf_data->vf_mc_hashes[i] = hash_list[i];
 
@@ -3972,9 +4351,20 @@
 	int i, j;
 
 	for (i = 0; i < adapter->vfs_allocated_count; i++) {
+		u32 vmolr = rd32(E1000_VMOLR(i));
+		vmolr &= ~(E1000_VMOLR_ROMPE | E1000_VMOLR_MPME);
+
 		vf_data = &adapter->vf_data[i];
-		for (j = 0; j < vf_data->num_vf_mc_hashes; j++)
-			igb_mta_set(hw, vf_data->vf_mc_hashes[j]);
+
+		if ((vf_data->num_vf_mc_hashes > 30) ||
+		    (vf_data->flags & IGB_VF_FLAG_MULTI_PROMISC)) {
+			vmolr |= E1000_VMOLR_MPME;
+		} else if (vf_data->num_vf_mc_hashes) {
+			vmolr |= E1000_VMOLR_ROMPE;
+			for (j = 0; j < vf_data->num_vf_mc_hashes; j++)
+				igb_mta_set(hw, vf_data->vf_mc_hashes[j]);
+		}
+		wr32(E1000_VMOLR(i), vmolr);
 	}
 }
 
@@ -4012,7 +4402,11 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u32 reg, i;
 
-	/* It is an error to call this function when VFs are not enabled */
+	/* The vlvf table only exists on 82576 hardware and newer */
+	if (hw->mac.type < e1000_82576)
+		return -1;
+
+	/* we only need to do this if VMDq is enabled */
 	if (!adapter->vfs_allocated_count)
 		return -1;
 
@@ -4042,16 +4436,12 @@
 
 			/* if !enabled we need to set this up in vfta */
 			if (!(reg & E1000_VLVF_VLANID_ENABLE)) {
-				/* add VID to filter table, if bit already set
-				 * PF must have added it outside of table */
-				if (igb_vfta_set(hw, vid, true))
-					reg |= 1 << (E1000_VLVF_POOLSEL_SHIFT +
-						adapter->vfs_allocated_count);
+				/* add VID to filter table */
+				igb_vfta_set(hw, vid, true);
 				reg |= E1000_VLVF_VLANID_ENABLE;
 			}
 			reg &= ~E1000_VLVF_VLANID_MASK;
 			reg |= vid;
-
 			wr32(E1000_VLVF(i), reg);
 
 			/* do not modify RLPML for PF devices */
@@ -4067,8 +4457,8 @@
 				reg |= size;
 				wr32(E1000_VMOLR(vf), reg);
 			}
-			adapter->vf_data[vf].vlans_enabled++;
 
+			adapter->vf_data[vf].vlans_enabled++;
 			return 0;
 		}
 	} else {
@@ -4110,15 +4500,14 @@
 	return igb_vlvf_set(adapter, vid, add, vf);
 }
 
-static inline void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf)
+static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf)
 {
-	struct e1000_hw *hw = &adapter->hw;
-
-	/* disable mailbox functionality for vf */
-	adapter->vf_data[vf].clear_to_send = false;
+	/* clear all flags */
+	adapter->vf_data[vf].flags = 0;
+	adapter->vf_data[vf].last_nack = jiffies;
 
 	/* reset offloads to defaults */
-	igb_set_vmolr(hw, vf);
+	igb_set_vmolr(adapter, vf);
 
 	/* reset vlans for device */
 	igb_clear_vf_vfta(adapter, vf);
@@ -4130,7 +4519,18 @@
 	igb_set_rx_mode(adapter->netdev);
 }
 
-static inline void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf)
+static void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf)
+{
+	unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses;
+
+	/* generate a new mac address as we were hotplug removed/added */
+	random_ether_addr(vf_mac);
+
+	/* process remaining reset events */
+	igb_vf_reset(adapter, vf);
+}
+
+static void igb_vf_reset_msg(struct igb_adapter *adapter, u32 vf)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses;
@@ -4139,11 +4539,10 @@
 	u8 *addr = (u8 *)(&msgbuf[1]);
 
 	/* process all the same items cleared in a function level reset */
-	igb_vf_reset_event(adapter, vf);
+	igb_vf_reset(adapter, vf);
 
 	/* set vf mac address */
-	igb_rar_set(hw, vf_mac, rar_entry);
-	igb_set_rah_pool(hw, vf, rar_entry);
+	igb_rar_set_qsel(adapter, vf_mac, rar_entry, vf);
 
 	/* enable transmit and receive for vf */
 	reg = rd32(E1000_VFTE);
@@ -4151,8 +4550,7 @@
 	reg = rd32(E1000_VFRE);
 	wr32(E1000_VFRE, reg | (1 << vf));
 
-	/* enable mailbox functionality for vf */
-	adapter->vf_data[vf].clear_to_send = true;
+	adapter->vf_data[vf].flags = IGB_VF_FLAG_CTS;
 
 	/* reply to reset with ack and vf mac address */
 	msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK;
@@ -4162,66 +4560,51 @@
 
 static int igb_set_vf_mac_addr(struct igb_adapter *adapter, u32 *msg, int vf)
 {
-		unsigned char *addr = (char *)&msg[1];
-		int err = -1;
+	unsigned char *addr = (char *)&msg[1];
+	int err = -1;
 
-		if (is_valid_ether_addr(addr))
-			err = igb_set_vf_mac(adapter, vf, addr);
-
-		return err;
+	if (is_valid_ether_addr(addr))
+		err = igb_set_vf_mac(adapter, vf, addr);
 
+	return err;
 }
 
 static void igb_rcv_ack_from_vf(struct igb_adapter *adapter, u32 vf)
 {
 	struct e1000_hw *hw = &adapter->hw;
+	struct vf_data_storage *vf_data = &adapter->vf_data[vf];
 	u32 msg = E1000_VT_MSGTYPE_NACK;
 
 	/* if device isn't clear to send it shouldn't be reading either */
-	if (!adapter->vf_data[vf].clear_to_send)
+	if (!(vf_data->flags & IGB_VF_FLAG_CTS) &&
+	    time_after(jiffies, vf_data->last_nack + (2 * HZ))) {
 		igb_write_mbx(hw, &msg, 1, vf);
-}
-
-
-static void igb_msg_task(struct igb_adapter *adapter)
-{
-	struct e1000_hw *hw = &adapter->hw;
-	u32 vf;
-
-	for (vf = 0; vf < adapter->vfs_allocated_count; vf++) {
-		/* process any reset requests */
-		if (!igb_check_for_rst(hw, vf)) {
-			adapter->vf_data[vf].clear_to_send = false;
-			igb_vf_reset_event(adapter, vf);
-		}
-
-		/* process any messages pending */
-		if (!igb_check_for_msg(hw, vf))
-			igb_rcv_msg_from_vf(adapter, vf);
-
-		/* process any acks */
-		if (!igb_check_for_ack(hw, vf))
-			igb_rcv_ack_from_vf(adapter, vf);
-
+		vf_data->last_nack = jiffies;
 	}
 }
 
-static int igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
+static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf)
 {
-	u32 mbx_size = E1000_VFMAILBOX_SIZE;
-	u32 msgbuf[mbx_size];
+	struct pci_dev *pdev = adapter->pdev;
+	u32 msgbuf[E1000_VFMAILBOX_SIZE];
 	struct e1000_hw *hw = &adapter->hw;
+	struct vf_data_storage *vf_data = &adapter->vf_data[vf];
 	s32 retval;
 
-	retval = igb_read_mbx(hw, msgbuf, mbx_size, vf);
+	retval = igb_read_mbx(hw, msgbuf, E1000_VFMAILBOX_SIZE, vf);
 
-	if (retval)
-		dev_err(&adapter->pdev->dev,
-		        "Error receiving message from VF\n");
+	if (retval) {
+		/* if receive failed revoke VF CTS stats and restart init */
+		dev_err(&pdev->dev, "Error receiving message from VF\n");
+		vf_data->flags &= ~IGB_VF_FLAG_CTS;
+		if (!time_after(jiffies, vf_data->last_nack + (2 * HZ)))
+			return;
+		goto out;
+	}
 
 	/* this is a message we already processed, do nothing */
 	if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK))
-		return retval;
+		return;
 
 	/*
 	 * until the vf completes a reset it should not be
@@ -4230,20 +4613,23 @@
 
 	if (msgbuf[0] == E1000_VF_RESET) {
 		igb_vf_reset_msg(adapter, vf);
-
-		return retval;
+		return;
 	}
 
-	if (!adapter->vf_data[vf].clear_to_send) {
-		msgbuf[0] |= E1000_VT_MSGTYPE_NACK;
-		igb_write_mbx(hw, msgbuf, 1, vf);
-		return retval;
+	if (!(vf_data->flags & IGB_VF_FLAG_CTS)) {
+		if (!time_after(jiffies, vf_data->last_nack + (2 * HZ)))
+			return;
+		retval = -1;
+		goto out;
 	}
 
 	switch ((msgbuf[0] & 0xFFFF)) {
 	case E1000_VF_SET_MAC_ADDR:
 		retval = igb_set_vf_mac_addr(adapter, msgbuf, vf);
 		break;
+	case E1000_VF_SET_PROMISC:
+		retval = igb_set_vf_promisc(adapter, msgbuf, vf);
+		break;
 	case E1000_VF_SET_MULTICAST:
 		retval = igb_set_vf_multicasts(adapter, msgbuf, vf);
 		break;
@@ -4254,22 +4640,67 @@
 		retval = igb_set_vf_vlan(adapter, msgbuf, vf);
 		break;
 	default:
-		dev_err(&adapter->pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]);
+		dev_err(&pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]);
 		retval = -1;
 		break;
 	}
 
+	msgbuf[0] |= E1000_VT_MSGTYPE_CTS;
+out:
 	/* notify the VF of the results of what it sent us */
 	if (retval)
 		msgbuf[0] |= E1000_VT_MSGTYPE_NACK;
 	else
 		msgbuf[0] |= E1000_VT_MSGTYPE_ACK;
 
-	msgbuf[0] |= E1000_VT_MSGTYPE_CTS;
-
 	igb_write_mbx(hw, msgbuf, 1, vf);
+}
 
-	return retval;
+static void igb_msg_task(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 vf;
+
+	for (vf = 0; vf < adapter->vfs_allocated_count; vf++) {
+		/* process any reset requests */
+		if (!igb_check_for_rst(hw, vf))
+			igb_vf_reset_event(adapter, vf);
+
+		/* process any messages pending */
+		if (!igb_check_for_msg(hw, vf))
+			igb_rcv_msg_from_vf(adapter, vf);
+
+		/* process any acks */
+		if (!igb_check_for_ack(hw, vf))
+			igb_rcv_ack_from_vf(adapter, vf);
+	}
+}
+
+/**
+ *  igb_set_uta - Set unicast filter table address
+ *  @adapter: board private structure
+ *
+ *  The unicast table address is a register array of 32-bit registers.
+ *  The table is meant to be used in a way similar to how the MTA is used
+ *  however due to certain limitations in the hardware it is necessary to
+ *  set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscous
+ *  enable bit to allow vlan tag stripping when promiscous mode is enabled
+ **/
+static void igb_set_uta(struct igb_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	int i;
+
+	/* The UTA table only exists on 82576 hardware and newer */
+	if (hw->mac.type < e1000_82576)
+		return;
+
+	/* we only need to do this if VMDq is enabled */
+	if (!adapter->vfs_allocated_count)
+		return;
+
+	for (i = 0; i < hw->mac.uta_reg_count; i++)
+		array_wr32(E1000_UTA, i, ~0);
 }
 
 /**
@@ -4279,15 +4710,15 @@
  **/
 static irqreturn_t igb_intr_msi(int irq, void *data)
 {
-	struct net_device *netdev = data;
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct igb_adapter *adapter = data;
+	struct igb_q_vector *q_vector = adapter->q_vector[0];
 	struct e1000_hw *hw = &adapter->hw;
 	/* read ICR disables interrupts using IAM */
 	u32 icr = rd32(E1000_ICR);
 
-	igb_write_itr(adapter->rx_ring);
+	igb_write_itr(q_vector);
 
-	if(icr & E1000_ICR_DOUTSYNC) {
+	if (icr & E1000_ICR_DOUTSYNC) {
 		/* HW is reporting DMA is out of sync */
 		adapter->stats.doosync++;
 	}
@@ -4298,7 +4729,7 @@
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-	napi_schedule(&adapter->rx_ring[0].napi);
+	napi_schedule(&q_vector->napi);
 
 	return IRQ_HANDLED;
 }
@@ -4310,8 +4741,8 @@
  **/
 static irqreturn_t igb_intr(int irq, void *data)
 {
-	struct net_device *netdev = data;
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct igb_adapter *adapter = data;
+	struct igb_q_vector *q_vector = adapter->q_vector[0];
 	struct e1000_hw *hw = &adapter->hw;
 	/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked.  No
 	 * need for the IMC write */
@@ -4319,14 +4750,14 @@
 	if (!icr)
 		return IRQ_NONE;  /* Not our interrupt */
 
-	igb_write_itr(adapter->rx_ring);
+	igb_write_itr(q_vector);
 
 	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
 	 * not set, then the adapter didn't send an interrupt */
 	if (!(icr & E1000_ICR_INT_ASSERTED))
 		return IRQ_NONE;
 
-	if(icr & E1000_ICR_DOUTSYNC) {
+	if (icr & E1000_ICR_DOUTSYNC) {
 		/* HW is reporting DMA is out of sync */
 		adapter->stats.doosync++;
 	}
@@ -4338,26 +4769,27 @@
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-	napi_schedule(&adapter->rx_ring[0].napi);
+	napi_schedule(&q_vector->napi);
 
 	return IRQ_HANDLED;
 }
 
-static inline void igb_rx_irq_enable(struct igb_ring *rx_ring)
+static inline void igb_ring_irq_enable(struct igb_q_vector *q_vector)
 {
-	struct igb_adapter *adapter = rx_ring->adapter;
+	struct igb_adapter *adapter = q_vector->adapter;
 	struct e1000_hw *hw = &adapter->hw;
 
-	if (adapter->itr_setting & 3) {
-		if (adapter->num_rx_queues == 1)
+	if ((q_vector->rx_ring && (adapter->rx_itr_setting & 3)) ||
+	    (!q_vector->rx_ring && (adapter->tx_itr_setting & 3))) {
+		if (!adapter->msix_entries)
 			igb_set_itr(adapter);
 		else
-			igb_update_ring_itr(rx_ring);
+			igb_update_ring_itr(q_vector);
 	}
 
 	if (!test_bit(__IGB_DOWN, &adapter->state)) {
 		if (adapter->msix_entries)
-			wr32(E1000_EIMS, rx_ring->eims_value);
+			wr32(E1000_EIMS, q_vector->eims_value);
 		else
 			igb_irq_enable(adapter);
 	}
@@ -4370,76 +4802,101 @@
  **/
 static int igb_poll(struct napi_struct *napi, int budget)
 {
-	struct igb_ring *rx_ring = container_of(napi, struct igb_ring, napi);
-	int work_done = 0;
+	struct igb_q_vector *q_vector = container_of(napi,
+	                                             struct igb_q_vector,
+	                                             napi);
+	int tx_clean_complete = 1, work_done = 0;
 
 #ifdef CONFIG_IGB_DCA
-	if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
-		igb_update_rx_dca(rx_ring);
+	if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
+		igb_update_dca(q_vector);
 #endif
-	igb_clean_rx_irq_adv(rx_ring, &work_done, budget);
+	if (q_vector->tx_ring)
+		tx_clean_complete = igb_clean_tx_irq(q_vector);
 
-	if (rx_ring->buddy) {
-#ifdef CONFIG_IGB_DCA
-		if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
-			igb_update_tx_dca(rx_ring->buddy);
-#endif
-		if (!igb_clean_tx_irq(rx_ring->buddy))
-			work_done = budget;
-	}
+	if (q_vector->rx_ring)
+		igb_clean_rx_irq_adv(q_vector, &work_done, budget);
+
+	if (!tx_clean_complete)
+		work_done = budget;
 
 	/* If not enough Rx work done, exit the polling mode */
 	if (work_done < budget) {
 		napi_complete(napi);
-		igb_rx_irq_enable(rx_ring);
+		igb_ring_irq_enable(q_vector);
 	}
 
 	return work_done;
 }
 
 /**
- * igb_hwtstamp - utility function which checks for TX time stamp
+ * igb_systim_to_hwtstamp - convert system time value to hw timestamp
  * @adapter: board private structure
+ * @shhwtstamps: timestamp structure to update
+ * @regval: unsigned 64bit system time value.
+ *
+ * We need to convert the system time value stored in the RX/TXSTMP registers
+ * into a hwtstamp which can be used by the upper level timestamping functions
+ */
+static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
+                                   struct skb_shared_hwtstamps *shhwtstamps,
+                                   u64 regval)
+{
+	u64 ns;
+
+	/*
+	 * The 82580 starts with 1ns at bit 0 in RX/TXSTMPL, shift this up to
+	 * 24 to match clock shift we setup earlier.
+	 */
+	if (adapter->hw.mac.type == e1000_82580)
+		regval <<= IGB_82580_TSYNC_SHIFT;
+
+	ns = timecounter_cyc2time(&adapter->clock, regval);
+	timecompare_update(&adapter->compare, ns);
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(ns);
+	shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns);
+}
+
+/**
+ * igb_tx_hwtstamp - utility function which checks for TX time stamp
+ * @q_vector: pointer to q_vector containing needed info
  * @skb: packet that was just sent
  *
  * If we were asked to do hardware stamping and such a time stamp is
  * available, then it must have been for this skb here because we only
  * allow only one such packet into the queue.
  */
-static void igb_tx_hwtstamp(struct igb_adapter *adapter, struct sk_buff *skb)
+static void igb_tx_hwtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)
 {
+	struct igb_adapter *adapter = q_vector->adapter;
 	union skb_shared_tx *shtx = skb_tx(skb);
 	struct e1000_hw *hw = &adapter->hw;
+	struct skb_shared_hwtstamps shhwtstamps;
+	u64 regval;
 
-	if (unlikely(shtx->hardware)) {
-		u32 valid = rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID;
-		if (valid) {
-			u64 regval = rd32(E1000_TXSTMPL);
-			u64 ns;
-			struct skb_shared_hwtstamps shhwtstamps;
-
-			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-			regval |= (u64)rd32(E1000_TXSTMPH) << 32;
-			ns = timecounter_cyc2time(&adapter->clock,
-						  regval);
-			timecompare_update(&adapter->compare, ns);
-			shhwtstamps.hwtstamp = ns_to_ktime(ns);
-			shhwtstamps.syststamp =
-				timecompare_transform(&adapter->compare, ns);
-			skb_tstamp_tx(skb, &shhwtstamps);
-		}
-	}
+	/* if skb does not support hw timestamp or TX stamp not valid exit */
+	if (likely(!shtx->hardware) ||
+	    !(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
+		return;
+
+	regval = rd32(E1000_TXSTMPL);
+	regval |= (u64)rd32(E1000_TXSTMPH) << 32;
+
+	igb_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
+	skb_tstamp_tx(skb, &shhwtstamps);
 }
 
 /**
  * igb_clean_tx_irq - Reclaim resources after transmit completes
- * @adapter: board private structure
+ * @q_vector: pointer to q_vector containing needed info
  * returns true if ring is completely cleaned
  **/
-static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
+static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
 {
-	struct igb_adapter *adapter = tx_ring->adapter;
-	struct net_device *netdev = adapter->netdev;
+	struct igb_adapter *adapter = q_vector->adapter;
+	struct igb_ring *tx_ring = q_vector->tx_ring;
+	struct net_device *netdev = tx_ring->netdev;
 	struct e1000_hw *hw = &adapter->hw;
 	struct igb_buffer *buffer_info;
 	struct sk_buff *skb;
@@ -4470,10 +4927,10 @@
 				total_packets += segs;
 				total_bytes += bytecount;
 
-				igb_tx_hwtstamp(adapter, skb);
+				igb_tx_hwtstamp(q_vector, skb);
 			}
 
-			igb_unmap_and_free_tx_resource(adapter, buffer_info);
+			igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
 			tx_desc->wb.status = 0;
 
 			i++;
@@ -4496,7 +4953,7 @@
 		if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
 		    !(test_bit(__IGB_DOWN, &adapter->state))) {
 			netif_wake_subqueue(netdev, tx_ring->queue_index);
-			++adapter->restart_queue;
+			tx_ring->tx_stats.restart_queue++;
 		}
 	}
 
@@ -4511,7 +4968,7 @@
 			 E1000_STATUS_TXOFF)) {
 
 			/* detected Tx unit hang */
-			dev_err(&adapter->pdev->dev,
+			dev_err(&tx_ring->pdev->dev,
 				"Detected Tx Unit Hang\n"
 				"  Tx Queue             <%d>\n"
 				"  TDH                  <%x>\n"
@@ -4524,11 +4981,11 @@
 				"  jiffies              <%lx>\n"
 				"  desc.status          <%x>\n",
 				tx_ring->queue_index,
-				readl(adapter->hw.hw_addr + tx_ring->head),
-				readl(adapter->hw.hw_addr + tx_ring->tail),
+				readl(tx_ring->head),
+				readl(tx_ring->tail),
 				tx_ring->next_to_use,
 				tx_ring->next_to_clean,
-				tx_ring->buffer_info[i].time_stamp,
+				tx_ring->buffer_info[eop].time_stamp,
 				eop,
 				jiffies,
 				eop_desc->wb.status);
@@ -4539,43 +4996,38 @@
 	tx_ring->total_packets += total_packets;
 	tx_ring->tx_stats.bytes += total_bytes;
 	tx_ring->tx_stats.packets += total_packets;
-	adapter->net_stats.tx_bytes += total_bytes;
-	adapter->net_stats.tx_packets += total_packets;
 	return (count < tx_ring->count);
 }
 
 /**
  * igb_receive_skb - helper function to handle rx indications
- * @ring: pointer to receive ring receving this packet
- * @status: descriptor status field as written by hardware
- * @rx_desc: receive descriptor containing vlan and type information.
- * @skb: pointer to sk_buff to be indicated to stack
- **/
-static void igb_receive_skb(struct igb_ring *ring, u8 status,
-                            union e1000_adv_rx_desc * rx_desc,
-                            struct sk_buff *skb)
-{
-	struct igb_adapter * adapter = ring->adapter;
-	bool vlan_extracted = (adapter->vlgrp && (status & E1000_RXD_STAT_VP));
-
-	skb_record_rx_queue(skb, ring->queue_index);
-	if (vlan_extracted)
-		vlan_gro_receive(&ring->napi, adapter->vlgrp,
-		                 le16_to_cpu(rx_desc->wb.upper.vlan),
-		                 skb);
+ * @q_vector: structure containing interrupt and ring information
+ * @skb: packet to send up
+ * @vlan_tag: vlan tag for packet
+ **/
+static void igb_receive_skb(struct igb_q_vector *q_vector,
+                            struct sk_buff *skb,
+                            u16 vlan_tag)
+{
+	struct igb_adapter *adapter = q_vector->adapter;
+
+	if (vlan_tag && adapter->vlgrp)
+		vlan_gro_receive(&q_vector->napi, adapter->vlgrp,
+		                 vlan_tag, skb);
 	else
-		napi_gro_receive(&ring->napi, skb);
+		napi_gro_receive(&q_vector->napi, skb);
 }
 
-static inline void igb_rx_checksum_adv(struct igb_adapter *adapter,
+static inline void igb_rx_checksum_adv(struct igb_ring *ring,
 				       u32 status_err, struct sk_buff *skb)
 {
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
-	if ((status_err & E1000_RXD_STAT_IXSM) ||
-	    (adapter->flags & IGB_FLAG_RX_CSUM_DISABLED))
+	if (!(ring->flags & IGB_RING_FLAG_RX_CSUM) ||
+	     (status_err & E1000_RXD_STAT_IXSM))
 		return;
+
 	/* TCP/UDP checksum error bit is set */
 	if (status_err &
 	    (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
@@ -4584,9 +5036,10 @@
 		 * L4E bit is set incorrectly on 64 byte (60 byte w/o crc)
 		 * packets, (aka let the stack check the crc32c)
 		 */
-		if (!((adapter->hw.mac.type == e1000_82576) &&
-		      (skb->len == 60)))
-			adapter->hw_csum_err++;
+		if ((skb->len == 60) &&
+		    (ring->flags & IGB_RING_FLAG_RX_SCTP_CSUM))
+			ring->rx_stats.csum_err++;
+
 		/* let the stack verify checksum errors */
 		return;
 	}
@@ -4594,11 +5047,38 @@
 	if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	dev_dbg(&adapter->pdev->dev, "cksum success: bits %08X\n", status_err);
-	adapter->hw_csum_good++;
+	dev_dbg(&ring->pdev->dev, "cksum success: bits %08X\n", status_err);
 }
 
-static inline u16 igb_get_hlen(struct igb_adapter *adapter,
+static inline void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
+                                   struct sk_buff *skb)
+{
+	struct igb_adapter *adapter = q_vector->adapter;
+	struct e1000_hw *hw = &adapter->hw;
+	u64 regval;
+
+	/*
+	 * If this bit is set, then the RX registers contain the time stamp. No
+	 * other packet will be time stamped until we read these registers, so
+	 * read the registers to make them available again. Because only one
+	 * packet can be time stamped at a time, we know that the register
+	 * values must belong to this one here and therefore we don't need to
+	 * compare any of the additional attributes stored for it.
+	 *
+	 * If nothing went wrong, then it should have a skb_shared_tx that we
+	 * can turn into a skb_shared_hwtstamps.
+	 */
+	if (likely(!(staterr & E1000_RXDADV_STAT_TS)))
+		return;
+	if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+		return;
+
+	regval = rd32(E1000_RXSTMPL);
+	regval |= (u64)rd32(E1000_RXSTMPH) << 32;
+
+	igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
+}
+static inline u16 igb_get_hlen(struct igb_ring *rx_ring,
                                union e1000_adv_rx_desc *rx_desc)
 {
 	/* HW will not DMA in data larger than the given buffer, even if it
@@ -4607,27 +5087,28 @@
 	 */
 	u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
 	           E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
-	if (hlen > adapter->rx_ps_hdr_size)
-		hlen = adapter->rx_ps_hdr_size;
+	if (hlen > rx_ring->rx_buffer_len)
+		hlen = rx_ring->rx_buffer_len;
 	return hlen;
 }
 
-static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
-				 int *work_done, int budget)
+static bool igb_clean_rx_irq_adv(struct igb_q_vector *q_vector,
+                                 int *work_done, int budget)
 {
-	struct igb_adapter *adapter = rx_ring->adapter;
-	struct net_device *netdev = adapter->netdev;
-	struct e1000_hw *hw = &adapter->hw;
-	struct pci_dev *pdev = adapter->pdev;
+	struct igb_ring *rx_ring = q_vector->rx_ring;
+	struct net_device *netdev = rx_ring->netdev;
+	struct pci_dev *pdev = rx_ring->pdev;
 	union e1000_adv_rx_desc *rx_desc , *next_rxd;
 	struct igb_buffer *buffer_info , *next_buffer;
 	struct sk_buff *skb;
 	bool cleaned = false;
 	int cleaned_count = 0;
+	int current_node = numa_node_id();
 	unsigned int total_bytes = 0, total_packets = 0;
 	unsigned int i;
 	u32 staterr;
 	u16 length;
+	u16 vlan_tag;
 
 	i = rx_ring->next_to_clean;
 	buffer_info = &rx_ring->buffer_info[i];
@@ -4646,6 +5127,7 @@
 		i++;
 		if (i == rx_ring->count)
 			i = 0;
+
 		next_rxd = E1000_RX_DESC_ADV(*rx_ring, i);
 		prefetch(next_rxd);
 		next_buffer = &rx_ring->buffer_info[i];
@@ -4654,23 +5136,16 @@
 		cleaned = true;
 		cleaned_count++;
 
-		/* this is the fast path for the non-packet split case */
-		if (!adapter->rx_ps_hdr_size) {
-			pci_unmap_single(pdev, buffer_info->dma,
-					 adapter->rx_buffer_len,
-					 PCI_DMA_FROMDEVICE);
-			buffer_info->dma = 0;
-			skb_put(skb, length);
-			goto send_up;
-		}
-
 		if (buffer_info->dma) {
-			u16 hlen = igb_get_hlen(adapter, rx_desc);
 			pci_unmap_single(pdev, buffer_info->dma,
-					 adapter->rx_ps_hdr_size,
+					 rx_ring->rx_buffer_len,
 					 PCI_DMA_FROMDEVICE);
 			buffer_info->dma = 0;
-			skb_put(skb, hlen);
+			if (rx_ring->rx_buffer_len >= IGB_RXBUFFER_1024) {
+				skb_put(skb, length);
+				goto send_up;
+			}
+			skb_put(skb, igb_get_hlen(rx_ring, rx_desc));
 		}
 
 		if (length) {
@@ -4683,15 +5158,14 @@
 						buffer_info->page_offset,
 						length);
 
-			if ((adapter->rx_buffer_len > (PAGE_SIZE / 2)) ||
-			    (page_count(buffer_info->page) != 1))
+			if ((page_count(buffer_info->page) != 1) ||
+			    (page_to_nid(buffer_info->page) != current_node))
 				buffer_info->page = NULL;
 			else
 				get_page(buffer_info->page);
 
 			skb->len += length;
 			skb->data_len += length;
-
 			skb->truesize += length;
 		}
 
@@ -4703,60 +5177,24 @@
 			goto next_desc;
 		}
 send_up:
-		/*
-		 * If this bit is set, then the RX registers contain
-		 * the time stamp. No other packet will be time
-		 * stamped until we read these registers, so read the
-		 * registers to make them available again. Because
-		 * only one packet can be time stamped at a time, we
-		 * know that the register values must belong to this
-		 * one here and therefore we don't need to compare
-		 * any of the additional attributes stored for it.
-		 *
-		 * If nothing went wrong, then it should have a
-		 * skb_shared_tx that we can turn into a
-		 * skb_shared_hwtstamps.
-		 *
-		 * TODO: can time stamping be triggered (thus locking
-		 * the registers) without the packet reaching this point
-		 * here? In that case RX time stamping would get stuck.
-		 *
-		 * TODO: in "time stamp all packets" mode this bit is
-		 * not set. Need a global flag for this mode and then
-		 * always read the registers. Cannot be done without
-		 * a race condition.
-		 */
-		if (unlikely(staterr & E1000_RXD_STAT_TS)) {
-			u64 regval;
-			u64 ns;
-			struct skb_shared_hwtstamps *shhwtstamps =
-				skb_hwtstamps(skb);
-
-			WARN(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID),
-			     "igb: no RX time stamp available for time stamped packet");
-			regval = rd32(E1000_RXSTMPL);
-			regval |= (u64)rd32(E1000_RXSTMPH) << 32;
-			ns = timecounter_cyc2time(&adapter->clock, regval);
-			timecompare_update(&adapter->compare, ns);
-			memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-			shhwtstamps->hwtstamp = ns_to_ktime(ns);
-			shhwtstamps->syststamp =
-				timecompare_transform(&adapter->compare, ns);
-		}
-
 		if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
 			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
 
+		igb_rx_hwtstamp(q_vector, staterr, skb);
 		total_bytes += skb->len;
 		total_packets++;
 
-		igb_rx_checksum_adv(adapter, staterr, skb);
+		igb_rx_checksum_adv(rx_ring, staterr, skb);
 
 		skb->protocol = eth_type_trans(skb, netdev);
+		skb_record_rx_queue(skb, rx_ring->queue_index);
+
+		vlan_tag = ((staterr & E1000_RXD_STAT_VP) ?
+		            le16_to_cpu(rx_desc->wb.upper.vlan) : 0);
 
-		igb_receive_skb(rx_ring, staterr, rx_desc, skb);
+		igb_receive_skb(q_vector, skb, vlan_tag);
 
 next_desc:
 		rx_desc->wb.upper.status_error = 0;
@@ -4783,8 +5221,6 @@
 	rx_ring->total_bytes += total_bytes;
 	rx_ring->rx_stats.packets += total_packets;
 	rx_ring->rx_stats.bytes += total_bytes;
-	adapter->net_stats.rx_bytes += total_bytes;
-	adapter->net_stats.rx_packets += total_packets;
 	return cleaned;
 }
 
@@ -4792,12 +5228,9 @@
  * igb_alloc_rx_buffers_adv - Replace used receive buffers; packet split
  * @adapter: address of board private structure
  **/
-static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
-				     int cleaned_count)
+void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring, int cleaned_count)
 {
-	struct igb_adapter *adapter = rx_ring->adapter;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = rx_ring->netdev;
 	union e1000_adv_rx_desc *rx_desc;
 	struct igb_buffer *buffer_info;
 	struct sk_buff *skb;
@@ -4807,19 +5240,16 @@
 	i = rx_ring->next_to_use;
 	buffer_info = &rx_ring->buffer_info[i];
 
-	if (adapter->rx_ps_hdr_size)
-		bufsz = adapter->rx_ps_hdr_size;
-	else
-		bufsz = adapter->rx_buffer_len;
+	bufsz = rx_ring->rx_buffer_len;
 
 	while (cleaned_count--) {
 		rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
 
-		if (adapter->rx_ps_hdr_size && !buffer_info->page_dma) {
+		if ((bufsz < IGB_RXBUFFER_1024) && !buffer_info->page_dma) {
 			if (!buffer_info->page) {
-				buffer_info->page = alloc_page(GFP_ATOMIC);
+				buffer_info->page = netdev_alloc_page(netdev);
 				if (!buffer_info->page) {
-					adapter->alloc_rx_buff_failed++;
+					rx_ring->rx_stats.alloc_failed++;
 					goto no_buffers;
 				}
 				buffer_info->page_offset = 0;
@@ -4827,16 +5257,23 @@
 				buffer_info->page_offset ^= PAGE_SIZE / 2;
 			}
 			buffer_info->page_dma =
-				pci_map_page(pdev, buffer_info->page,
+				pci_map_page(rx_ring->pdev, buffer_info->page,
 					     buffer_info->page_offset,
 					     PAGE_SIZE / 2,
 					     PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(rx_ring->pdev,
+			                          buffer_info->page_dma)) {
+				buffer_info->page_dma = 0;
+				rx_ring->rx_stats.alloc_failed++;
+				goto no_buffers;
+			}
 		}
 
+		skb = buffer_info->skb;
 		if (!buffer_info->skb) {
 			skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN);
 			if (!skb) {
-				adapter->alloc_rx_buff_failed++;
+				rx_ring->rx_stats.alloc_failed++;
 				goto no_buffers;
 			}
 
@@ -4847,19 +5284,27 @@
 			skb_reserve(skb, NET_IP_ALIGN);
 
 			buffer_info->skb = skb;
-			buffer_info->dma = pci_map_single(pdev, skb->data,
+		}
+		if (!buffer_info->dma) {
+			buffer_info->dma = pci_map_single(rx_ring->pdev,
+			                                  skb->data,
 							  bufsz,
 							  PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(rx_ring->pdev,
+			                          buffer_info->dma)) {
+				buffer_info->dma = 0;
+				rx_ring->rx_stats.alloc_failed++;
+				goto no_buffers;
+			}
 		}
 		/* Refresh the desc even if buffer_addrs didn't change because
 		 * each write-back erases this info. */
-		if (adapter->rx_ps_hdr_size) {
+		if (bufsz < IGB_RXBUFFER_1024) {
 			rx_desc->read.pkt_addr =
 			     cpu_to_le64(buffer_info->page_dma);
 			rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma);
 		} else {
-			rx_desc->read.pkt_addr =
-			     cpu_to_le64(buffer_info->dma);
+			rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma);
 			rx_desc->read.hdr_addr = 0;
 		}
 
@@ -4882,7 +5327,7 @@
 		 * applicable for weak-ordered memory model archs,
 		 * such as IA-64). */
 		wmb();
-		writel(i, adapter->hw.hw_addr + rx_ring->tail);
+		writel(i, rx_ring->tail);
 	}
 }
 
@@ -4941,13 +5386,11 @@
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	struct hwtstamp_config config;
-	u32 tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
-	u32 tsync_rx_ctl_bit = E1000_TSYNCRXCTL_ENABLED;
-	u32 tsync_rx_ctl_type = 0;
+	u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED;
+	u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
 	u32 tsync_rx_cfg = 0;
-	int is_l4 = 0;
-	int is_l2 = 0;
-	short port = 319; /* PTP */
+	bool is_l4 = false;
+	bool is_l2 = false;
 	u32 regval;
 
 	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
@@ -4959,10 +5402,8 @@
 
 	switch (config.tx_type) {
 	case HWTSTAMP_TX_OFF:
-		tsync_tx_ctl_bit = 0;
-		break;
+		tsync_tx_ctl = 0;
 	case HWTSTAMP_TX_ON:
-		tsync_tx_ctl_bit = E1000_TSYNCTXCTL_ENABLED;
 		break;
 	default:
 		return -ERANGE;
@@ -4970,7 +5411,7 @@
 
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
-		tsync_rx_ctl_bit = 0;
+		tsync_rx_ctl = 0;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
@@ -4981,86 +5422,97 @@
 		 * possible to time stamp both Sync and Delay_Req messages
 		 * => fall back to time stamping all packets
 		 */
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_ALL;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
-		is_l4 = 1;
+		is_l4 = true;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L4_V1;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
-		is_l4 = 1;
+		is_l4 = true;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
-		is_l2 = 1;
-		is_l4 = 1;
+		is_l2 = true;
+		is_l4 = true;
 		config.rx_filter = HWTSTAMP_FILTER_SOME;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
 		tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
-		is_l2 = 1;
-		is_l4 = 1;
+		is_l2 = true;
+		is_l4 = true;
 		config.rx_filter = HWTSTAMP_FILTER_SOME;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
-		tsync_rx_ctl_type = E1000_TSYNCRXCTL_TYPE_EVENT_V2;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
 		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-		is_l2 = 1;
+		is_l2 = true;
 		break;
 	default:
 		return -ERANGE;
 	}
 
+	if (hw->mac.type == e1000_82575) {
+		if (tsync_rx_ctl | tsync_tx_ctl)
+			return -EINVAL;
+		return 0;
+	}
+
 	/* enable/disable TX */
 	regval = rd32(E1000_TSYNCTXCTL);
-	regval = (regval & ~E1000_TSYNCTXCTL_ENABLED) | tsync_tx_ctl_bit;
+	regval &= ~E1000_TSYNCTXCTL_ENABLED;
+	regval |= tsync_tx_ctl;
 	wr32(E1000_TSYNCTXCTL, regval);
 
-	/* enable/disable RX, define which PTP packets are time stamped */
+	/* enable/disable RX */
 	regval = rd32(E1000_TSYNCRXCTL);
-	regval = (regval & ~E1000_TSYNCRXCTL_ENABLED) | tsync_rx_ctl_bit;
-	regval = (regval & ~0xE) | tsync_rx_ctl_type;
+	regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK);
+	regval |= tsync_rx_ctl;
 	wr32(E1000_TSYNCRXCTL, regval);
-	wr32(E1000_TSYNCRXCFG, tsync_rx_cfg);
 
-	/*
-	 * Ethertype Filter Queue Filter[0][15:0] = 0x88F7
-	 *                                          (Ethertype to filter on)
-	 * Ethertype Filter Queue Filter[0][26] = 0x1 (Enable filter)
-	 * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable Timestamping)
-	 */
-	wr32(E1000_ETQF0, is_l2 ? 0x440088f7 : 0);
+	/* define which PTP packets are time stamped */
+	wr32(E1000_TSYNCRXCFG, tsync_rx_cfg);
 
-	/* L4 Queue Filter[0]: only filter by source and destination port */
-	wr32(E1000_SPQF0, htons(port));
-	wr32(E1000_IMIREXT(0), is_l4 ?
-	     ((1<<12) | (1<<19) /* bypass size and control flags */) : 0);
-	wr32(E1000_IMIR(0), is_l4 ?
-	     (htons(port)
-	      | (0<<16) /* immediate interrupt disabled */
-	      | 0 /* (1<<17) bit cleared: do not bypass
-		     destination port check */)
-		: 0);
-	wr32(E1000_FTQF0, is_l4 ?
-	     (0x11 /* UDP */
-	      | (1<<15) /* VF not compared */
-	      | (1<<27) /* Enable Timestamping */
-	      | (7<<28) /* only source port filter enabled,
-			   source/target address and protocol
-			   masked */)
-	     : ((1<<15) | (15<<28) /* all mask bits set = filter not
-				      enabled */));
+	/* define ethertype filter for timestamped packets */
+	if (is_l2)
+		wr32(E1000_ETQF(3),
+		                (E1000_ETQF_FILTER_ENABLE | /* enable filter */
+		                 E1000_ETQF_1588 | /* enable timestamping */
+		                 ETH_P_1588));     /* 1588 eth protocol type */
+	else
+		wr32(E1000_ETQF(3), 0);
 
+#define PTP_PORT 319
+	/* L4 Queue Filter[3]: filter by destination port and protocol */
+	if (is_l4) {
+		u32 ftqf = (IPPROTO_UDP /* UDP */
+			| E1000_FTQF_VF_BP /* VF not compared */
+			| E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */
+			| E1000_FTQF_MASK); /* mask all inputs */
+		ftqf &= ~E1000_FTQF_MASK_PROTO_BP; /* enable protocol check */
+
+		wr32(E1000_IMIR(3), htons(PTP_PORT));
+		wr32(E1000_IMIREXT(3),
+		     (E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP));
+		if (hw->mac.type == e1000_82576) {
+			/* enable source port check */
+			wr32(E1000_SPQF(3), htons(PTP_PORT));
+			ftqf &= ~E1000_FTQF_MASK_SOURCE_PORT_BP;
+		}
+		wr32(E1000_FTQF(3), ftqf);
+	} else {
+		wr32(E1000_FTQF(3), E1000_FTQF_MASK);
+	}
 	wrfl();
 
 	adapter->hwtstamp_config = config;
@@ -5137,21 +5589,15 @@
 		ctrl |= E1000_CTRL_VME;
 		wr32(E1000_CTRL, ctrl);
 
-		/* enable VLAN receive filtering */
+		/* Disable CFI check */
 		rctl = rd32(E1000_RCTL);
 		rctl &= ~E1000_RCTL_CFIEN;
 		wr32(E1000_RCTL, rctl);
-		igb_update_mng_vlan(adapter);
 	} else {
 		/* disable VLAN tag insert/strip */
 		ctrl = rd32(E1000_CTRL);
 		ctrl &= ~E1000_CTRL_VME;
 		wr32(E1000_CTRL, ctrl);
-
-		if (adapter->mng_vlan_id != (u16)IGB_MNG_VLAN_NONE) {
-			igb_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
-			adapter->mng_vlan_id = IGB_MNG_VLAN_NONE;
-		}
 	}
 
 	igb_rlpml_set(adapter);
@@ -5166,16 +5612,11 @@
 	struct e1000_hw *hw = &adapter->hw;
 	int pf_id = adapter->vfs_allocated_count;
 
-	if ((hw->mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
-	    (vid == adapter->mng_vlan_id))
-		return;
-
-	/* add vid to vlvf if sr-iov is enabled,
-	 * if that fails add directly to filter table */
-	if (igb_vlvf_set(adapter, vid, true, pf_id))
-		igb_vfta_set(hw, vid, true);
+	/* attempt to add filter to vlvf array */
+	igb_vlvf_set(adapter, vid, true, pf_id);
 
+	/* add the filter since PF can receive vlans w/o entry in vlvf */
+	igb_vfta_set(hw, vid, true);
 }
 
 static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -5183,6 +5624,7 @@
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	int pf_id = adapter->vfs_allocated_count;
+	s32 err;
 
 	igb_irq_disable(adapter);
 	vlan_group_set_device(adapter->vlgrp, vid, NULL);
@@ -5190,17 +5632,11 @@
 	if (!test_bit(__IGB_DOWN, &adapter->state))
 		igb_irq_enable(adapter);
 
-	if ((adapter->hw.mng_cookie.status &
-	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
-	    (vid == adapter->mng_vlan_id)) {
-		/* release control to f/w */
-		igb_release_hw_control(adapter);
-		return;
-	}
+	/* remove vlan from VLVF table array */
+	err = igb_vlvf_set(adapter, vid, false, pf_id);
 
-	/* remove vid from vlvf if sr-iov is enabled,
-	 * if not in vlvf remove from vfta */
-	if (igb_vlvf_set(adapter, vid, false, pf_id))
+	/* if vid was not present in VLVF just remove it from table */
+	if (err)
 		igb_vfta_set(hw, vid, false);
 }
 
@@ -5220,6 +5656,7 @@
 
 int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx)
 {
+	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_mac_info *mac = &adapter->hw.mac;
 
 	mac->autoneg = 0;
@@ -5243,8 +5680,7 @@
 		break;
 	case SPEED_1000 + DUPLEX_HALF: /* not supported */
 	default:
-		dev_err(&adapter->pdev->dev,
-			"Unsupported Speed/Duplex configuration\n");
+		dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -5266,9 +5702,7 @@
 	if (netif_running(netdev))
 		igb_close(netdev);
 
-	igb_reset_interrupt_capability(adapter);
-
-	igb_free_queues(adapter);
+	igb_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
@@ -5300,7 +5734,7 @@
 		wr32(E1000_CTRL, ctrl);
 
 		/* Allow time for pending master requests to run */
-		igb_disable_pcie_master(&adapter->hw);
+		igb_disable_pcie_master(hw);
 
 		wr32(E1000_WUC, E1000_WUC_PME_EN);
 		wr32(E1000_WUFC, wufc);
@@ -5363,9 +5797,7 @@
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
-	igb_set_interrupt_capability(adapter);
-
-	if (igb_alloc_queues(adapter)) {
+	if (igb_init_interrupt_scheme(adapter)) {
 		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
 		return -ENOMEM;
 	}
@@ -5417,22 +5849,16 @@
 	int i;
 
 	if (!adapter->msix_entries) {
+		struct igb_q_vector *q_vector = adapter->q_vector[0];
 		igb_irq_disable(adapter);
-		napi_schedule(&adapter->rx_ring[0].napi);
+		napi_schedule(&q_vector->napi);
 		return;
 	}
 
-	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct igb_ring *tx_ring = &adapter->tx_ring[i];
-		wr32(E1000_EIMC, tx_ring->eims_value);
-		igb_clean_tx_irq(tx_ring);
-		wr32(E1000_EIMS, tx_ring->eims_value);
-	}
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct igb_ring *rx_ring = &adapter->rx_ring[i];
-		wr32(E1000_EIMC, rx_ring->eims_value);
-		napi_schedule(&rx_ring->napi);
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		wr32(E1000_EIMC, q_vector->eims_value);
+		napi_schedule(&q_vector->napi);
 	}
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -5532,6 +5958,33 @@
 	igb_get_hw_control(adapter);
 }
 
+static void igb_rar_set_qsel(struct igb_adapter *adapter, u8 *addr, u32 index,
+                             u8 qsel)
+{
+	u32 rar_low, rar_high;
+	struct e1000_hw *hw = &adapter->hw;
+
+	/* HW expects these in little endian so we reverse the byte order
+	 * from network order (big endian) to little endian
+	 */
+	rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+	          ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+	/* Indicate to hardware the Address is Valid. */
+	rar_high |= E1000_RAH_AV;
+
+	if (hw->mac.type == e1000_82575)
+		rar_high |= E1000_RAH_POOL_1 * qsel;
+	else
+		rar_high |= E1000_RAH_POOL_1 << qsel;
+
+	wr32(E1000_RAL(index), rar_low);
+	wrfl();
+	wr32(E1000_RAH(index), rar_high);
+	wrfl();
+}
+
 static int igb_set_vf_mac(struct igb_adapter *adapter,
                           int vf, unsigned char *mac_addr)
 {
@@ -5542,8 +5995,7 @@
 
 	memcpy(adapter->vf_data[vf].vf_mac_addresses, mac_addr, ETH_ALEN);
 
-	igb_rar_set(hw, mac_addr, rar_entry);
-	igb_set_rah_pool(hw, vf, rar_entry);
+	igb_rar_set_qsel(adapter, mac_addr, rar_entry, vf);
 
 	return 0;
 }
@@ -5551,19 +6003,29 @@
 static void igb_vmm_control(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
-	u32 reg_data;
+	u32 reg;
 
-	if (!adapter->vfs_allocated_count)
+	/* replication is not supported for 82575 */
+	if (hw->mac.type == e1000_82575)
 		return;
 
-	/* VF's need PF reset indication before they
-	 * can send/receive mail */
-	reg_data = rd32(E1000_CTRL_EXT);
-	reg_data |= E1000_CTRL_EXT_PFRSTD;
-	wr32(E1000_CTRL_EXT, reg_data);
+	/* enable replication vlan tag stripping */
+	reg = rd32(E1000_RPLOLR);
+	reg |= E1000_RPLOLR_STRVLAN;
+	wr32(E1000_RPLOLR, reg);
+
+	/* notify HW that the MAC is adding vlan tags */
+	reg = rd32(E1000_DTXCTL);
+	reg |= E1000_DTXCTL_VLAN_ADDED;
+	wr32(E1000_DTXCTL, reg);
 
-	igb_vmdq_set_loopback_pf(hw, true);
-	igb_vmdq_set_replication_pf(hw, true);
+	if (adapter->vfs_allocated_count) {
+		igb_vmdq_set_loopback_pf(hw, true);
+		igb_vmdq_set_replication_pf(hw, true);
+	} else {
+		igb_vmdq_set_loopback_pf(hw, false);
+		igb_vmdq_set_replication_pf(hw, false);
+	}
 }
 
 /* igb_main.c */
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_mac.c
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_mac.c
@@ -185,13 +185,12 @@
 	}
 
 	if (nvm_alt_mac_addr_offset == 0xFFFF) {
-		ret_val = -(E1000_NOT_IMPLEMENTED);
+		/* There is no Alternate MAC Address */
 		goto out;
 	}
 
 	if (hw->bus.func == E1000_FUNC_1)
-		nvm_alt_mac_addr_offset += ETH_ALEN/sizeof(u16);
-
+		nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
 	for (i = 0; i < ETH_ALEN; i += 2) {
 		offset = nvm_alt_mac_addr_offset + (i >> 1);
 		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
@@ -206,14 +205,16 @@
 
 	/* if multicast bit is set, the alternate address will not be used */
 	if (alt_mac_addr[0] & 0x01) {
-		ret_val = -(E1000_NOT_IMPLEMENTED);
+		hw_dbg("Ignoring Alternate Mac Address with MC bit set\n");
 		goto out;
 	}
 
-	for (i = 0; i < ETH_ALEN; i++)
-		hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i];
-
-	hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0);
+	/*
+	 * We have a valid alternate MAC address, and we want to treat it the
+	 * same as the normal permanent MAC address stored by the HW into the
+	 * RAR. Do this by mapping this address into RAR0.
+	 */
+	hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
 
 out:
 	return ret_val;
@@ -246,8 +247,15 @@
 	if (rar_low || rar_high)
 		rar_high |= E1000_RAH_AV;
 
+	/*
+	 * Some bridges will combine consecutive 32-bit writes into
+	 * a single burst write, which will malfunction on some parts.
+	 * The flushes avoid this.
+	 */
 	wr32(E1000_RAL(index), rar_low);
+	wrfl();
 	wr32(E1000_RAH(index), rar_high);
+	wrfl();
 }
 
 /**
@@ -399,45 +407,43 @@
  **/
 void igb_clear_hw_cntrs_base(struct e1000_hw *hw)
 {
-	u32 temp;
-
-	temp = rd32(E1000_CRCERRS);
-	temp = rd32(E1000_SYMERRS);
-	temp = rd32(E1000_MPC);
-	temp = rd32(E1000_SCC);
-	temp = rd32(E1000_ECOL);
-	temp = rd32(E1000_MCC);
-	temp = rd32(E1000_LATECOL);
-	temp = rd32(E1000_COLC);
-	temp = rd32(E1000_DC);
-	temp = rd32(E1000_SEC);
-	temp = rd32(E1000_RLEC);
-	temp = rd32(E1000_XONRXC);
-	temp = rd32(E1000_XONTXC);
-	temp = rd32(E1000_XOFFRXC);
-	temp = rd32(E1000_XOFFTXC);
-	temp = rd32(E1000_FCRUC);
-	temp = rd32(E1000_GPRC);
-	temp = rd32(E1000_BPRC);
-	temp = rd32(E1000_MPRC);
-	temp = rd32(E1000_GPTC);
-	temp = rd32(E1000_GORCL);
-	temp = rd32(E1000_GORCH);
-	temp = rd32(E1000_GOTCL);
-	temp = rd32(E1000_GOTCH);
-	temp = rd32(E1000_RNBC);
-	temp = rd32(E1000_RUC);
-	temp = rd32(E1000_RFC);
-	temp = rd32(E1000_ROC);
-	temp = rd32(E1000_RJC);
-	temp = rd32(E1000_TORL);
-	temp = rd32(E1000_TORH);
-	temp = rd32(E1000_TOTL);
-	temp = rd32(E1000_TOTH);
-	temp = rd32(E1000_TPR);
-	temp = rd32(E1000_TPT);
-	temp = rd32(E1000_MPTC);
-	temp = rd32(E1000_BPTC);
+	rd32(E1000_CRCERRS);
+	rd32(E1000_SYMERRS);
+	rd32(E1000_MPC);
+	rd32(E1000_SCC);
+	rd32(E1000_ECOL);
+	rd32(E1000_MCC);
+	rd32(E1000_LATECOL);
+	rd32(E1000_COLC);
+	rd32(E1000_DC);
+	rd32(E1000_SEC);
+	rd32(E1000_RLEC);
+	rd32(E1000_XONRXC);
+	rd32(E1000_XONTXC);
+	rd32(E1000_XOFFRXC);
+	rd32(E1000_XOFFTXC);
+	rd32(E1000_FCRUC);
+	rd32(E1000_GPRC);
+	rd32(E1000_BPRC);
+	rd32(E1000_MPRC);
+	rd32(E1000_GPTC);
+	rd32(E1000_GORCL);
+	rd32(E1000_GORCH);
+	rd32(E1000_GOTCL);
+	rd32(E1000_GOTCH);
+	rd32(E1000_RNBC);
+	rd32(E1000_RUC);
+	rd32(E1000_RFC);
+	rd32(E1000_ROC);
+	rd32(E1000_RJC);
+	rd32(E1000_TORL);
+	rd32(E1000_TORH);
+	rd32(E1000_TOTL);
+	rd32(E1000_TOTH);
+	rd32(E1000_TPR);
+	rd32(E1000_TPT);
+	rd32(E1000_MPTC);
+	rd32(E1000_BPTC);
 }
 
 /**
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_phy.c
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_phy.c
@@ -39,6 +39,9 @@
 /* Cable length tables */
 static const u16 e1000_m88_cable_length_table[] =
 	{ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
+                (sizeof(e1000_m88_cable_length_table) / \
+                 sizeof(e1000_m88_cable_length_table[0]))
 
 static const u16 e1000_igp_2_cable_length_table[] =
     { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
@@ -109,7 +112,10 @@
  **/
 static s32 igb_phy_reset_dsp(struct e1000_hw *hw)
 {
-	s32 ret_val;
+	s32 ret_val = 0;
+
+	if (!(hw->phy.ops.write_reg))
+		goto out;
 
 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
 	if (ret_val)
@@ -130,7 +136,7 @@
  *  Reads the MDI control regsiter in the PHY at offset and stores the
  *  information read to data.
  **/
-static s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 {
 	struct e1000_phy_info *phy = &hw->phy;
 	u32 i, mdic = 0;
@@ -188,7 +194,7 @@
  *
  *  Writes data to MDI control register in the PHY at offset.
  **/
-static s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 {
 	struct e1000_phy_info *phy = &hw->phy;
 	u32 i, mdic = 0;
@@ -239,6 +245,103 @@
 }
 
 /**
+ *  igb_read_phy_reg_i2c - Read PHY register using i2c
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the PHY register at offset using the i2c interface and stores the
+ *  retrieved information in data.
+ **/
+s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	u32 i, i2ccmd = 0;
+
+
+	/*
+	 * Set up Op-code, Phy Address, and register address in the I2CCMD
+	 * register.  The MAC will take care of interfacing with the
+	 * PHY to retrieve the desired data.
+	 */
+	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+	          (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+	          (E1000_I2CCMD_OPCODE_READ));
+
+	wr32(E1000_I2CCMD, i2ccmd);
+
+	/* Poll the ready bit to see if the I2C read completed */
+	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+		udelay(50);
+		i2ccmd = rd32(E1000_I2CCMD);
+		if (i2ccmd & E1000_I2CCMD_READY)
+			break;
+	}
+	if (!(i2ccmd & E1000_I2CCMD_READY)) {
+		hw_dbg("I2CCMD Read did not complete\n");
+		return -E1000_ERR_PHY;
+	}
+	if (i2ccmd & E1000_I2CCMD_ERROR) {
+		hw_dbg("I2CCMD Error bit set\n");
+		return -E1000_ERR_PHY;
+	}
+
+	/* Need to byte-swap the 16-bit value. */
+	*data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
+
+	return 0;
+}
+
+/**
+ *  igb_write_phy_reg_i2c - Write PHY register using i2c
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset using the i2c interface.
+ **/
+s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	u32 i, i2ccmd = 0;
+	u16 phy_data_swapped;
+
+
+	/* Swap the data bytes for the I2C interface */
+	phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
+
+	/*
+	 * Set up Op-code, Phy Address, and register address in the I2CCMD
+	 * register.  The MAC will take care of interfacing with the
+	 * PHY to retrieve the desired data.
+	 */
+	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
+	          (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
+	          E1000_I2CCMD_OPCODE_WRITE |
+	          phy_data_swapped);
+
+	wr32(E1000_I2CCMD, i2ccmd);
+
+	/* Poll the ready bit to see if the I2C read completed */
+	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
+		udelay(50);
+		i2ccmd = rd32(E1000_I2CCMD);
+		if (i2ccmd & E1000_I2CCMD_READY)
+			break;
+	}
+	if (!(i2ccmd & E1000_I2CCMD_READY)) {
+		hw_dbg("I2CCMD Write did not complete\n");
+		return -E1000_ERR_PHY;
+	}
+	if (i2ccmd & E1000_I2CCMD_ERROR) {
+		hw_dbg("I2CCMD Error bit set\n");
+		return -E1000_ERR_PHY;
+	}
+
+	return 0;
+}
+
+/**
  *  igb_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
@@ -318,6 +421,48 @@
 }
 
 /**
+ *  igb_copper_link_setup_82580 - Setup 82580 PHY for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets up Carrier-sense on Transmit and downshift values.
+ **/
+s32 igb_copper_link_setup_82580(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data;
+
+
+	if (phy->reset_disable) {
+		ret_val = 0;
+		goto out;
+	}
+
+	if (phy->type == e1000_phy_82580) {
+		ret_val = hw->phy.ops.reset(hw);
+		if (ret_val) {
+			hw_dbg("Error resetting the PHY.\n");
+			goto out;
+		}
+	}
+
+	/* Enable CRS on TX. This must be set for half-duplex operation. */
+	ret_val = phy->ops.read_reg(hw, I82580_CFG_REG, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data |= I82580_CFG_ASSERT_CRS_ON_TX;
+
+	/* Enable downshift */
+	phy_data |= I82580_CFG_ENABLE_DOWNSHIFT;
+
+	ret_val = phy->ops.write_reg(hw, I82580_CFG_REG, phy_data);
+
+out:
+	return ret_val;
+}
+
+/**
  *  igb_copper_link_setup_m88 - Setup m88 PHY's for copper link
  *  @hw: pointer to the HW structure
  *
@@ -572,7 +717,7 @@
  *  and restart the negotiation process between the link partner.  If
  *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
  **/
-s32 igb_copper_link_autoneg(struct e1000_hw *hw)
+static s32 igb_copper_link_autoneg(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
 	s32 ret_val;
@@ -796,6 +941,65 @@
 }
 
 /**
+ *  igb_setup_copper_link - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -E1000_ERR_PHY (-2).
+ **/
+s32 igb_setup_copper_link(struct e1000_hw *hw)
+{
+	s32 ret_val;
+	bool link;
+
+
+	if (hw->mac.autoneg) {
+		/*
+		 * Setup autoneg and flow control advertisement and perform
+		 * autonegotiation.
+		 */
+		ret_val = igb_copper_link_autoneg(hw);
+		if (ret_val)
+			goto out;
+	} else {
+		/*
+		 * PHY will be set to 10H, 10F, 100H or 100F
+		 * depending on user settings.
+		 */
+		hw_dbg("Forcing Speed and Duplex\n");
+		ret_val = hw->phy.ops.force_speed_duplex(hw);
+		if (ret_val) {
+			hw_dbg("Error Forcing Speed and Duplex\n");
+			goto out;
+		}
+	}
+
+	/*
+	 * Check link status. Wait up to 100 microseconds for link to become
+	 * valid.
+	 */
+	ret_val = igb_phy_has_link(hw,
+	                           COPPER_LINK_UP_LIMIT,
+	                           10,
+	                           &link);
+	if (ret_val)
+		goto out;
+
+	if (link) {
+		hw_dbg("Valid link established!!!\n");
+		igb_config_collision_dist(hw);
+		ret_val = igb_config_fc_after_link_up(hw);
+	} else {
+		hw_dbg("Unable to establish link!!!\n");
+	}
+
+out:
+	return ret_val;
+}
+
+/**
  *  igb_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY
  *  @hw: pointer to the HW structure
  *
@@ -903,22 +1107,19 @@
 
 	igb_phy_force_speed_duplex_setup(hw, &phy_data);
 
-	/* Reset the phy to commit changes. */
-	phy_data |= MII_CR_RESET;
-
 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
 	if (ret_val)
 		goto out;
 
-	udelay(1);
+	/* Reset the phy to commit changes. */
+	ret_val = igb_phy_sw_reset(hw);
+	if (ret_val)
+		goto out;
 
 	if (phy->autoneg_wait_to_complete) {
 		hw_dbg("Waiting for forced speed/duplex link on M88 phy.\n");
 
-		ret_val = igb_phy_has_link(hw,
-						     PHY_FORCE_LIMIT,
-						     100000,
-						     &link);
+		ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT, 100000, &link);
 		if (ret_val)
 			goto out;
 
@@ -928,8 +1129,8 @@
 			 * Reset the DSP and cross our fingers.
 			 */
 			ret_val = phy->ops.write_reg(hw,
-						      M88E1000_PHY_PAGE_SELECT,
-						      0x001d);
+						     M88E1000_PHY_PAGE_SELECT,
+						     0x001d);
 			if (ret_val)
 				goto out;
 			ret_val = igb_phy_reset_dsp(hw);
@@ -939,7 +1140,7 @@
 
 		/* Try once more */
 		ret_val = igb_phy_has_link(hw, PHY_FORCE_LIMIT,
-					     100000, &link);
+					   100000, &link);
 		if (ret_val)
 			goto out;
 	}
@@ -1051,9 +1252,12 @@
 s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active)
 {
 	struct e1000_phy_info *phy = &hw->phy;
-	s32 ret_val;
+	s32 ret_val = 0;
 	u16 data;
 
+	if (!(hw->phy.ops.read_reg))
+		goto out;
+
 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
 	if (ret_val)
 		goto out;
@@ -1288,8 +1492,14 @@
 		 * it across the board.
 		 */
 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
-		if (ret_val)
-			break;
+		if (ret_val) {
+			/*
+			 * If the first read fails, another entity may have
+			 * ownership of the resources, wait and try again to
+			 * see if they have relinquished the resources yet.
+			 */
+			udelay(usec_interval);
+		}
 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
 		if (ret_val)
 			break;
@@ -1333,8 +1543,13 @@
 
 	index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
 		M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+	if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+		ret_val = -E1000_ERR_PHY;
+		goto out;
+	}
+
 	phy->min_cable_length = e1000_m88_cable_length_table[index];
-	phy->max_cable_length = e1000_m88_cable_length_table[index+1];
+	phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
 
 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
 
@@ -1715,3 +1930,194 @@
 	return 0;
 }
 
+/**
+ *  igb_check_polarity_82580 - Checks the polarity.
+ *  @hw: pointer to the HW structure
+ *
+ *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ *
+ *  Polarity is determined based on the PHY specific status register.
+ **/
+static s32 igb_check_polarity_82580(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+
+
+	ret_val = phy->ops.read_reg(hw, I82580_PHY_STATUS_2, &data);
+
+	if (!ret_val)
+		phy->cable_polarity = (data & I82580_PHY_STATUS2_REV_POLARITY)
+		                      ? e1000_rev_polarity_reversed
+		                      : e1000_rev_polarity_normal;
+
+	return ret_val;
+}
+
+/**
+ *  igb_phy_force_speed_duplex_82580 - Force speed/duplex for I82580 PHY
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the PHY setup function to force speed and duplex.  Clears the
+ *  auto-crossover to force MDI manually.  Waits for link and returns
+ *  successful if link up is successful, else -E1000_ERR_PHY (-2).
+ **/
+s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data;
+	bool link;
+
+
+	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
+	if (ret_val)
+		goto out;
+
+	igb_phy_force_speed_duplex_setup(hw, &phy_data);
+
+	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * Clear Auto-Crossover to force MDI manually.  82580 requires MDI
+	 * forced whenever speed and duplex are forced.
+	 */
+	ret_val = phy->ops.read_reg(hw, I82580_PHY_CTRL_2, &phy_data);
+	if (ret_val)
+		goto out;
+
+	phy_data &= ~I82580_PHY_CTRL2_AUTO_MDIX;
+	phy_data &= ~I82580_PHY_CTRL2_FORCE_MDI_MDIX;
+
+	ret_val = phy->ops.write_reg(hw, I82580_PHY_CTRL_2, phy_data);
+	if (ret_val)
+		goto out;
+
+	hw_dbg("I82580_PHY_CTRL_2: %X\n", phy_data);
+
+	udelay(1);
+
+	if (phy->autoneg_wait_to_complete) {
+		hw_dbg("Waiting for forced speed/duplex link on 82580 phy\n");
+
+		ret_val = igb_phy_has_link(hw,
+		                           PHY_FORCE_LIMIT,
+		                           100000,
+		                           &link);
+		if (ret_val)
+			goto out;
+
+		if (!link)
+			hw_dbg("Link taking longer than expected.\n");
+
+		/* Try once more */
+		ret_val = igb_phy_has_link(hw,
+		                           PHY_FORCE_LIMIT,
+		                           100000,
+		                           &link);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_get_phy_info_82580 - Retrieve I82580 PHY information
+ *  @hw: pointer to the HW structure
+ *
+ *  Read PHY status to determine if link is up.  If link is up, then
+ *  set/determine 10base-T extended distance and polarity correction.  Read
+ *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
+ *  determine on the cable length, local and remote receiver.
+ **/
+s32 igb_get_phy_info_82580(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 data;
+	bool link;
+
+
+	ret_val = igb_phy_has_link(hw, 1, 0, &link);
+	if (ret_val)
+		goto out;
+
+	if (!link) {
+		hw_dbg("Phy info is only valid if link is up\n");
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
+	}
+
+	phy->polarity_correction = true;
+
+	ret_val = igb_check_polarity_82580(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = phy->ops.read_reg(hw, I82580_PHY_STATUS_2, &data);
+	if (ret_val)
+		goto out;
+
+	phy->is_mdix = (data & I82580_PHY_STATUS2_MDIX) ? true : false;
+
+	if ((data & I82580_PHY_STATUS2_SPEED_MASK) ==
+	    I82580_PHY_STATUS2_SPEED_1000MBPS) {
+		ret_val = hw->phy.ops.get_cable_length(hw);
+		if (ret_val)
+			goto out;
+
+		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
+		if (ret_val)
+			goto out;
+
+		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
+		                ? e1000_1000t_rx_status_ok
+		                : e1000_1000t_rx_status_not_ok;
+
+		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
+		                 ? e1000_1000t_rx_status_ok
+		                 : e1000_1000t_rx_status_not_ok;
+	} else {
+		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
+		phy->local_rx = e1000_1000t_rx_status_undefined;
+		phy->remote_rx = e1000_1000t_rx_status_undefined;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_get_cable_length_82580 - Determine cable length for 82580 PHY
+ *  @hw: pointer to the HW structure
+ *
+ * Reads the diagnostic status register and verifies result is valid before
+ * placing it in the phy_cable_length field.
+ **/
+s32 igb_get_cable_length_82580(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_data, length;
+
+
+	ret_val = phy->ops.read_reg(hw, I82580_PHY_DIAG_STATUS, &phy_data);
+	if (ret_val)
+		goto out;
+
+	length = (phy_data & I82580_DSTATUS_CABLE_LENGTH) >>
+	         I82580_DSTATUS_CABLE_LENGTH_SHIFT;
+
+	if (length == E1000_CABLE_LENGTH_UNDEFINED)
+		ret_val = -E1000_ERR_PHY;
+
+	phy->cable_length = length;
+
+out:
+	return ret_val;
+}
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_defines.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_defines.h
@@ -49,6 +49,7 @@
 #define E1000_CTRL_EXT_PFRSTD    0x00004000
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX  0x00400000
 #define E1000_CTRL_EXT_LINK_MODE_SGMII   0x00800000
 #define E1000_CTRL_EXT_EIAME          0x01000000
 #define E1000_CTRL_EXT_IRCA           0x00000001
@@ -329,6 +330,7 @@
 #define E1000_ICR_RXDMT0        0x00000010 /* rx desc min. threshold (0) */
 #define E1000_ICR_RXT0          0x00000080 /* rx timer intr (ring 0) */
 #define E1000_ICR_VMMB          0x00000100 /* VM MB event */
+#define E1000_ICR_DRSTA         0x40000000 /* Device Reset Asserted */
 /* If this bit asserted, the driver should claim the interrupt */
 #define E1000_ICR_INT_ASSERTED  0x80000000
 /* LAN connected device generates an interrupt */
@@ -370,6 +372,7 @@
 #define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
 #define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
 #define E1000_IMS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
+#define E1000_IMS_DRSTA     E1000_ICR_DRSTA     /* Device Reset Asserted */
 #define E1000_IMS_DOUTSYNC  E1000_ICR_DOUTSYNC /* NIC DMA out of sync */
 
 /* Extended Interrupt Mask Set */
@@ -378,6 +381,7 @@
 /* Interrupt Cause Set */
 #define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
 #define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
+#define E1000_ICS_DRSTA     E1000_ICR_DRSTA     /* Device Reset Aserted */
 
 /* Extended Interrupt Cause Set */
 
@@ -435,6 +439,39 @@
 /* Flow Control */
 #define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
 
+#define E1000_TSYNCTXCTL_VALID    0x00000001 /* tx timestamp valid */
+#define E1000_TSYNCTXCTL_ENABLED  0x00000010 /* enable tx timestampping */
+
+#define E1000_TSYNCRXCTL_VALID      0x00000001 /* rx timestamp valid */
+#define E1000_TSYNCRXCTL_TYPE_MASK  0x0000000E /* rx type mask */
+#define E1000_TSYNCRXCTL_TYPE_L2_V2       0x00
+#define E1000_TSYNCRXCTL_TYPE_L4_V1       0x02
+#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2    0x04
+#define E1000_TSYNCRXCTL_TYPE_ALL         0x08
+#define E1000_TSYNCRXCTL_TYPE_EVENT_V2    0x0A
+#define E1000_TSYNCRXCTL_ENABLED    0x00000010 /* enable rx timestampping */
+
+#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK   0x000000FF
+#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE       0x00
+#define E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE  0x01
+#define E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE   0x02
+#define E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE 0x03
+#define E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE 0x04
+
+#define E1000_TSYNCRXCFG_PTP_V2_MSGID_MASK               0x00000F00
+#define E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE                 0x0000
+#define E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE            0x0100
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE       0x0200
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE      0x0300
+#define E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE             0x0800
+#define E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE           0x0900
+#define E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE  0x0A00
+#define E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE             0x0B00
+#define E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE           0x0C00
+#define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE           0x0D00
+
+#define E1000_TIMINCA_16NS_SHIFT 24
+
 /* PCI Express Control */
 #define E1000_GCR_CMPL_TMOUT_MASK       0x0000F000
 #define E1000_GCR_CMPL_TMOUT_10ms       0x00001000
@@ -524,8 +561,12 @@
 #define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
 
-#define E1000_NVM_CFG_DONE_PORT_0  0x40000 /* MNG config cycle done */
-#define E1000_NVM_CFG_DONE_PORT_1  0x80000 /* ...for second port */
+#define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
+#define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
+#define E1000_NVM_CFG_DONE_PORT_2  0x100000 /* ...for third port */
+#define E1000_NVM_CFG_DONE_PORT_3  0x200000 /* ...for fourth port */
+
+#define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0)
 
 /* Mask bits for fields in Word 0x0f of the NVM */
 #define NVM_WORD0F_PAUSE_MASK       0x3000
@@ -592,6 +633,7 @@
  */
 #define M88E1111_I_PHY_ID    0x01410CC0
 #define IGP03E1000_E_PHY_ID  0x02A80390
+#define I82580_I_PHY_ID      0x015403A0
 #define M88_VENDOR           0x0141
 
 /* M88E1000 Specific Registers */
@@ -678,4 +720,8 @@
 #define E1000_VFTA_ENTRY_MASK                0x7F
 #define E1000_VFTA_ENTRY_BIT_SHIFT_MASK      0x1F
 
+/* DMA Coalescing register fields */
+#define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based
+                                                      on DMA coal */
+
 #endif
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_82575.c
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_82575.c
@@ -46,7 +46,10 @@
 static s32  igb_init_hw_82575(struct e1000_hw *);
 static s32  igb_phy_hw_reset_sgmii_82575(struct e1000_hw *);
 static s32  igb_read_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16 *);
+static s32  igb_read_phy_reg_82580(struct e1000_hw *, u32, u16 *);
+static s32  igb_write_phy_reg_82580(struct e1000_hw *, u32, u16);
 static s32  igb_reset_hw_82575(struct e1000_hw *);
+static s32  igb_reset_hw_82580(struct e1000_hw *);
 static s32  igb_set_d0_lplu_state_82575(struct e1000_hw *, bool);
 static s32  igb_setup_copper_link_82575(struct e1000_hw *);
 static s32  igb_setup_serdes_link_82575(struct e1000_hw *);
@@ -62,6 +65,12 @@
 static s32  igb_read_mac_addr_82575(struct e1000_hw *);
 static s32  igb_set_pcie_completion_timeout(struct e1000_hw *hw);
 
+static const u16 e1000_82580_rxpbs_table[] =
+	{ 36, 72, 144, 1, 2, 4, 8, 16,
+	  35, 70, 140 };
+#define E1000_82580_RXPBS_TABLE_SIZE \
+	(sizeof(e1000_82580_rxpbs_table)/sizeof(u16))
+
 static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 {
 	struct e1000_phy_info *phy = &hw->phy;
@@ -81,12 +90,20 @@
 		break;
 	case E1000_DEV_ID_82576:
 	case E1000_DEV_ID_82576_NS:
+	case E1000_DEV_ID_82576_NS_SERDES:
 	case E1000_DEV_ID_82576_FIBER:
 	case E1000_DEV_ID_82576_SERDES:
 	case E1000_DEV_ID_82576_QUAD_COPPER:
 	case E1000_DEV_ID_82576_SERDES_QUAD:
 		mac->type = e1000_82576;
 		break;
+	case E1000_DEV_ID_82580_COPPER:
+	case E1000_DEV_ID_82580_FIBER:
+	case E1000_DEV_ID_82580_SERDES:
+	case E1000_DEV_ID_82580_SGMII:
+	case E1000_DEV_ID_82580_COPPER_DUAL:
+		mac->type = e1000_82580;
+		break;
 	default:
 		return -E1000_ERR_MAC_INIT;
 		break;
@@ -109,6 +126,7 @@
 		dev_spec->sgmii_active = true;
 		ctrl_ext |= E1000_CTRL_I2C_ENA;
 		break;
+	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
 	case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
 		hw->phy.media_type = e1000_media_type_internal_serdes;
 		ctrl_ext |= E1000_CTRL_I2C_ENA;
@@ -120,12 +138,26 @@
 
 	wr32(E1000_CTRL_EXT, ctrl_ext);
 
+	/*
+	 * if using i2c make certain the MDICNFG register is cleared to prevent
+	 * communications from being misrouted to the mdic registers
+	 */
+	if ((ctrl_ext & E1000_CTRL_I2C_ENA) && (hw->mac.type == e1000_82580))
+		wr32(E1000_MDICNFG, 0);
+
 	/* Set mta register count */
 	mac->mta_reg_count = 128;
 	/* Set rar entry count */
 	mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
 	if (mac->type == e1000_82576)
 		mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
+	if (mac->type == e1000_82580)
+		mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+	/* reset */
+	if (mac->type == e1000_82580)
+		mac->ops.reset_hw = igb_reset_hw_82580;
+	else
+		mac->ops.reset_hw = igb_reset_hw_82575;
 	/* Set if part includes ASF firmware */
 	mac->asf_firmware_present = true;
 	/* Set if manageability features are enabled. */
@@ -193,6 +225,10 @@
 		phy->ops.reset              = igb_phy_hw_reset_sgmii_82575;
 		phy->ops.read_reg           = igb_read_phy_reg_sgmii_82575;
 		phy->ops.write_reg          = igb_write_phy_reg_sgmii_82575;
+	} else if (hw->mac.type == e1000_82580) {
+		phy->ops.reset              = igb_phy_hw_reset;
+		phy->ops.read_reg           = igb_read_phy_reg_82580;
+		phy->ops.write_reg          = igb_write_phy_reg_82580;
 	} else {
 		phy->ops.reset              = igb_phy_hw_reset;
 		phy->ops.read_reg           = igb_read_phy_reg_igp;
@@ -224,6 +260,12 @@
 		phy->ops.set_d0_lplu_state  = igb_set_d0_lplu_state_82575;
 		phy->ops.set_d3_lplu_state  = igb_set_d3_lplu_state;
 		break;
+	case I82580_I_PHY_ID:
+		phy->type                   = e1000_phy_82580;
+		phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580;
+		phy->ops.get_cable_length   = igb_get_cable_length_82580;
+		phy->ops.get_phy_info       = igb_get_phy_info_82580;
+		break;
 	default:
 		return -E1000_ERR_PHY;
 	}
@@ -240,9 +282,10 @@
  **/
 static s32 igb_acquire_phy_82575(struct e1000_hw *hw)
 {
-	u16 mask;
+	u16 mask = E1000_SWFW_PHY0_SM;
 
-	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
+	if (hw->bus.func == E1000_FUNC_1)
+		mask = E1000_SWFW_PHY1_SM;
 
 	return igb_acquire_swfw_sync_82575(hw, mask);
 }
@@ -256,9 +299,11 @@
  **/
 static void igb_release_phy_82575(struct e1000_hw *hw)
 {
-	u16 mask;
+	u16 mask = E1000_SWFW_PHY0_SM;
+
+	if (hw->bus.func == E1000_FUNC_1)
+		mask = E1000_SWFW_PHY1_SM;
 
-	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
 	igb_release_swfw_sync_82575(hw, mask);
 }
 
@@ -274,45 +319,23 @@
 static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
 					  u16 *data)
 {
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 i, i2ccmd = 0;
+	s32 ret_val = -E1000_ERR_PARAM;
 
 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
 		hw_dbg("PHY Address %u is out of range\n", offset);
-		return -E1000_ERR_PARAM;
+		goto out;
 	}
 
-	/*
-	 * Set up Op-code, Phy Address, and register address in the I2CCMD
-	 * register.  The MAC will take care of interfacing with the
-	 * PHY to retrieve the desired data.
-	 */
-	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
-		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
-		  (E1000_I2CCMD_OPCODE_READ));
-
-	wr32(E1000_I2CCMD, i2ccmd);
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
 
-	/* Poll the ready bit to see if the I2C read completed */
-	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
-		udelay(50);
-		i2ccmd = rd32(E1000_I2CCMD);
-		if (i2ccmd & E1000_I2CCMD_READY)
-			break;
-	}
-	if (!(i2ccmd & E1000_I2CCMD_READY)) {
-		hw_dbg("I2CCMD Read did not complete\n");
-		return -E1000_ERR_PHY;
-	}
-	if (i2ccmd & E1000_I2CCMD_ERROR) {
-		hw_dbg("I2CCMD Error bit set\n");
-		return -E1000_ERR_PHY;
-	}
+	ret_val = igb_read_phy_reg_i2c(hw, offset, data);
 
-	/* Need to byte-swap the 16-bit value. */
-	*data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
+	hw->phy.ops.release(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
@@ -327,47 +350,24 @@
 static s32 igb_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
 					   u16 data)
 {
-	struct e1000_phy_info *phy = &hw->phy;
-	u32 i, i2ccmd = 0;
-	u16 phy_data_swapped;
+	s32 ret_val = -E1000_ERR_PARAM;
+
 
 	if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
 		hw_dbg("PHY Address %d is out of range\n", offset);
-		return -E1000_ERR_PARAM;
+		goto out;
 	}
 
-	/* Swap the data bytes for the I2C interface */
-	phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
-
-	/*
-	 * Set up Op-code, Phy Address, and register address in the I2CCMD
-	 * register.  The MAC will take care of interfacing with the
-	 * PHY to retrieve the desired data.
-	 */
-	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
-		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
-		  E1000_I2CCMD_OPCODE_WRITE |
-		  phy_data_swapped);
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
 
-	wr32(E1000_I2CCMD, i2ccmd);
+	ret_val = igb_write_phy_reg_i2c(hw, offset, data);
 
-	/* Poll the ready bit to see if the I2C read completed */
-	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
-		udelay(50);
-		i2ccmd = rd32(E1000_I2CCMD);
-		if (i2ccmd & E1000_I2CCMD_READY)
-			break;
-	}
-	if (!(i2ccmd & E1000_I2CCMD_READY)) {
-		hw_dbg("I2CCMD Write did not complete\n");
-		return -E1000_ERR_PHY;
-	}
-	if (i2ccmd & E1000_I2CCMD_ERROR) {
-		hw_dbg("I2CCMD Error bit set\n");
-		return -E1000_ERR_PHY;
-	}
+	hw->phy.ops.release(hw);
 
-	return 0;
+out:
+	return ret_val;
 }
 
 /**
@@ -676,6 +676,10 @@
 
 	if (hw->bus.func == 1)
 		mask = E1000_NVM_CFG_DONE_PORT_1;
+	else if (hw->bus.func == E1000_FUNC_2)
+		mask = E1000_NVM_CFG_DONE_PORT_2;
+	else if (hw->bus.func == E1000_FUNC_3)
+		mask = E1000_NVM_CFG_DONE_PORT_3;
 
 	while (timeout) {
 		if (rd32(E1000_EEMNGCTL) & mask)
@@ -706,9 +710,7 @@
 	s32 ret_val;
 	u16 speed, duplex;
 
-	/* SGMII link check is done through the PCS register. */
-	if ((hw->phy.media_type != e1000_media_type_copper) ||
-	    (igb_sgmii_active_82575(hw))) {
+	if (hw->phy.media_type != e1000_media_type_copper) {
 		ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed,
 		                                             &duplex);
 		/*
@@ -723,6 +725,7 @@
 
 	return ret_val;
 }
+
 /**
  *  igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
  *  @hw: pointer to the HW structure
@@ -788,13 +791,27 @@
 void igb_shutdown_serdes_link_82575(struct e1000_hw *hw)
 {
 	u32 reg;
+	u16 eeprom_data = 0;
 
 	if (hw->phy.media_type != e1000_media_type_internal_serdes ||
 	    igb_sgmii_active_82575(hw))
 		return;
 
-	/* if the management interface is not enabled, then power down */
-	if (!igb_enable_mng_pass_thru(hw)) {
+	if (hw->bus.func == E1000_FUNC_0)
+		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
+	else if (hw->mac.type == e1000_82580)
+		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
+		                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
+		                 &eeprom_data);
+	else if (hw->bus.func == E1000_FUNC_1)
+		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
+
+	/*
+	 * If APM is not enabled in the EEPROM and management interface is
+	 * not enabled, then power down.
+	 */
+	if (!(eeprom_data & E1000_NVM_APME_82575) &&
+	    !igb_enable_mng_pass_thru(hw)) {
 		/* Disable PCS to turn off link */
 		reg = rd32(E1000_PCS_CFG0);
 		reg &= ~E1000_PCS_CFG_PCS_EN;
@@ -908,6 +925,11 @@
 	for (i = 0; i < mac->mta_reg_count; i++)
 		array_wr32(E1000_MTA, i, 0);
 
+	/* Zero out the Unicast HASH table */
+	hw_dbg("Zeroing the UTA\n");
+	for (i = 0; i < mac->uta_reg_count; i++)
+		array_wr32(E1000_UTA, i, 0);
+
 	/* Setup link and flow control */
 	ret_val = igb_setup_link(hw);
 
@@ -934,7 +956,6 @@
 {
 	u32 ctrl;
 	s32  ret_val;
-	bool link;
 
 	ctrl = rd32(E1000_CTRL);
 	ctrl |= E1000_CTRL_SLU;
@@ -946,6 +967,9 @@
 		goto out;
 
 	if (igb_sgmii_active_82575(hw) && !hw->phy.reset_disable) {
+		/* allow time for SFP cage time to power up phy */
+		msleep(300);
+
 		ret_val = hw->phy.ops.reset(hw);
 		if (ret_val) {
 			hw_dbg("Error resetting the PHY.\n");
@@ -959,6 +983,9 @@
 	case e1000_phy_igp_3:
 		ret_val = igb_copper_link_setup_igp(hw);
 		break;
+	case e1000_phy_82580:
+		ret_val = igb_copper_link_setup_82580(hw);
+		break;
 	default:
 		ret_val = -E1000_ERR_PHY;
 		break;
@@ -967,57 +994,24 @@
 	if (ret_val)
 		goto out;
 
-	if (hw->mac.autoneg) {
-		/*
-		 * Setup autoneg and flow control advertisement
-		 * and perform autonegotiation.
-		 */
-		ret_val = igb_copper_link_autoneg(hw);
-		if (ret_val)
-			goto out;
-	} else {
-		/*
-		 * PHY will be set to 10H, 10F, 100H or 100F
-		 * depending on user settings.
-		 */
-		hw_dbg("Forcing Speed and Duplex\n");
-		ret_val = hw->phy.ops.force_speed_duplex(hw);
-		if (ret_val) {
-			hw_dbg("Error Forcing Speed and Duplex\n");
-			goto out;
-		}
-	}
-
-	/*
-	 * Check link status. Wait up to 100 microseconds for link to become
-	 * valid.
-	 */
-	ret_val = igb_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
-	if (ret_val)
-		goto out;
-
-	if (link) {
-		hw_dbg("Valid link established!!!\n");
-		/* Config the MAC and PHY after link is up */
-		igb_config_collision_dist(hw);
-		ret_val = igb_config_fc_after_link_up(hw);
-	} else {
-		hw_dbg("Unable to establish link!!!\n");
-	}
-
+	ret_val = igb_setup_copper_link(hw);
 out:
 	return ret_val;
 }
 
 /**
- *  igb_setup_serdes_link_82575 - Setup link for fiber/serdes
+ *  igb_setup_serdes_link_82575 - Setup link for serdes
  *  @hw: pointer to the HW structure
  *
- *  Configures speed and duplex for fiber and serdes links.
+ *  Configure the physical coding sub-layer (PCS) link.  The PCS link is
+ *  used on copper connections where the serialized gigabit media independent
+ *  interface (sgmii), or serdes fiber is being used.  Configures the link
+ *  for auto-negotiation or forces speed/duplex.
  **/
 static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 {
-	u32 ctrl_reg, reg;
+	u32 ctrl_ext, ctrl_reg, reg;
+	bool pcs_autoneg;
 
 	if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
 	    !igb_sgmii_active_82575(hw))
@@ -1032,9 +1026,9 @@
 	wr32(E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
 
 	/* power on the sfp cage if present */
-	reg = rd32(E1000_CTRL_EXT);
-	reg &= ~E1000_CTRL_EXT_SDP3_DATA;
-	wr32(E1000_CTRL_EXT, reg);
+	ctrl_ext = rd32(E1000_CTRL_EXT);
+	ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
+	wr32(E1000_CTRL_EXT, ctrl_ext);
 
 	ctrl_reg = rd32(E1000_CTRL);
 	ctrl_reg |= E1000_CTRL_SLU;
@@ -1051,15 +1045,31 @@
 
 	reg = rd32(E1000_PCS_LCTL);
 
-	if (igb_sgmii_active_82575(hw)) {
-		/* allow time for SFP cage to power up phy */
-		msleep(300);
+	/* default pcs_autoneg to the same setting as mac autoneg */
+	pcs_autoneg = hw->mac.autoneg;
 
-		/* AN time out should be disabled for SGMII mode */
+	switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
+	case E1000_CTRL_EXT_LINK_MODE_SGMII:
+		/* sgmii mode lets the phy handle forcing speed/duplex */
+		pcs_autoneg = true;
+		/* autoneg time out should be disabled for SGMII mode */
 		reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
-	} else {
+		break;
+	case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
+		/* disable PCS autoneg and support parallel detect only */
+		pcs_autoneg = false;
+	default:
+		/*
+		 * non-SGMII modes only supports a speed of 1000/Full for the
+		 * link so it is best to just force the MAC and let the pcs
+		 * link either autoneg or be forced to 1000/Full
+		 */
 		ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
 		            E1000_CTRL_FD | E1000_CTRL_FRCDPX;
+
+		/* set speed of 1000/Full if speed/duplex is forced */
+		reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
+		break;
 	}
 
 	wr32(E1000_CTRL, ctrl_reg);
@@ -1070,7 +1080,6 @@
 	 * mode that will be compatible with older link partners and switches.
 	 * However, both are supported by the hardware and some drivers/tools.
 	 */
-
 	reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
 		E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
 
@@ -1080,25 +1089,16 @@
 	 */
 	reg |= E1000_PCS_LCTL_FORCE_FCTRL;
 
-	/*
-	 * we always set sgmii to autoneg since it is the phy that will be
-	 * forcing the link and the serdes is just a go-between
-	 */
-	if (hw->mac.autoneg || igb_sgmii_active_82575(hw)) {
+	if (pcs_autoneg) {
 		/* Set PCS register for autoneg */
-		reg |= E1000_PCS_LCTL_FSV_1000 |      /* Force 1000    */
-		       E1000_PCS_LCTL_FDV_FULL |      /* SerDes Full duplex */
-		       E1000_PCS_LCTL_AN_ENABLE |     /* Enable Autoneg */
-		       E1000_PCS_LCTL_AN_RESTART;     /* Restart autoneg */
-		hw_dbg("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
+		reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
+		       E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+		hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
 	} else {
-		/* Set PCS register for forced speed */
-		reg |= E1000_PCS_LCTL_FLV_LINK_UP |   /* Force link up */
-		       E1000_PCS_LCTL_FSV_1000 |      /* Force 1000    */
-		       E1000_PCS_LCTL_FDV_FULL |      /* SerDes Full duplex */
-		       E1000_PCS_LCTL_FSD |           /* Force Speed */
-		       E1000_PCS_LCTL_FORCE_LINK;     /* Force Link */
-		hw_dbg("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg);
+		/* Set PCS register for forced link */
+		reg |= E1000_PCS_LCTL_FSD;        /* Force Speed */
+
+		hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
 	}
 
 	wr32(E1000_PCS_LCTL, reg);
@@ -1167,9 +1167,18 @@
 {
 	s32 ret_val = 0;
 
-	if (igb_check_alt_mac_addr(hw))
-		ret_val = igb_read_mac_addr(hw);
+	/*
+	 * If there's an alternate MAC address place it in RAR0
+	 * so that it will override the Si installed default perm
+	 * address.
+	 */
+	ret_val = igb_check_alt_mac_addr(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igb_read_mac_addr(hw);
 
+out:
 	return ret_val;
 }
 
@@ -1181,61 +1190,59 @@
  **/
 static void igb_clear_hw_cntrs_82575(struct e1000_hw *hw)
 {
-	u32 temp;
-
 	igb_clear_hw_cntrs_base(hw);
 
-	temp = rd32(E1000_PRC64);
-	temp = rd32(E1000_PRC127);
-	temp = rd32(E1000_PRC255);
-	temp = rd32(E1000_PRC511);
-	temp = rd32(E1000_PRC1023);
-	temp = rd32(E1000_PRC1522);
-	temp = rd32(E1000_PTC64);
-	temp = rd32(E1000_PTC127);
-	temp = rd32(E1000_PTC255);
-	temp = rd32(E1000_PTC511);
-	temp = rd32(E1000_PTC1023);
-	temp = rd32(E1000_PTC1522);
-
-	temp = rd32(E1000_ALGNERRC);
-	temp = rd32(E1000_RXERRC);
-	temp = rd32(E1000_TNCRS);
-	temp = rd32(E1000_CEXTERR);
-	temp = rd32(E1000_TSCTC);
-	temp = rd32(E1000_TSCTFC);
-
-	temp = rd32(E1000_MGTPRC);
-	temp = rd32(E1000_MGTPDC);
-	temp = rd32(E1000_MGTPTC);
-
-	temp = rd32(E1000_IAC);
-	temp = rd32(E1000_ICRXOC);
-
-	temp = rd32(E1000_ICRXPTC);
-	temp = rd32(E1000_ICRXATC);
-	temp = rd32(E1000_ICTXPTC);
-	temp = rd32(E1000_ICTXATC);
-	temp = rd32(E1000_ICTXQEC);
-	temp = rd32(E1000_ICTXQMTC);
-	temp = rd32(E1000_ICRXDMTC);
-
-	temp = rd32(E1000_CBTMPC);
-	temp = rd32(E1000_HTDPMC);
-	temp = rd32(E1000_CBRMPC);
-	temp = rd32(E1000_RPTHC);
-	temp = rd32(E1000_HGPTC);
-	temp = rd32(E1000_HTCBDPC);
-	temp = rd32(E1000_HGORCL);
-	temp = rd32(E1000_HGORCH);
-	temp = rd32(E1000_HGOTCL);
-	temp = rd32(E1000_HGOTCH);
-	temp = rd32(E1000_LENERRS);
+	rd32(E1000_PRC64);
+	rd32(E1000_PRC127);
+	rd32(E1000_PRC255);
+	rd32(E1000_PRC511);
+	rd32(E1000_PRC1023);
+	rd32(E1000_PRC1522);
+	rd32(E1000_PTC64);
+	rd32(E1000_PTC127);
+	rd32(E1000_PTC255);
+	rd32(E1000_PTC511);
+	rd32(E1000_PTC1023);
+	rd32(E1000_PTC1522);
+
+	rd32(E1000_ALGNERRC);
+	rd32(E1000_RXERRC);
+	rd32(E1000_TNCRS);
+	rd32(E1000_CEXTERR);
+	rd32(E1000_TSCTC);
+	rd32(E1000_TSCTFC);
+
+	rd32(E1000_MGTPRC);
+	rd32(E1000_MGTPDC);
+	rd32(E1000_MGTPTC);
+
+	rd32(E1000_IAC);
+	rd32(E1000_ICRXOC);
+
+	rd32(E1000_ICRXPTC);
+	rd32(E1000_ICRXATC);
+	rd32(E1000_ICTXPTC);
+	rd32(E1000_ICTXATC);
+	rd32(E1000_ICTXQEC);
+	rd32(E1000_ICTXQMTC);
+	rd32(E1000_ICRXDMTC);
+
+	rd32(E1000_CBTMPC);
+	rd32(E1000_HTDPMC);
+	rd32(E1000_CBRMPC);
+	rd32(E1000_RPTHC);
+	rd32(E1000_HGPTC);
+	rd32(E1000_HTCBDPC);
+	rd32(E1000_HGORCL);
+	rd32(E1000_HGORCH);
+	rd32(E1000_HGOTCL);
+	rd32(E1000_HGOTCH);
+	rd32(E1000_LENERRS);
 
 	/* This register should not be read in copper configurations */
 	if (hw->phy.media_type == e1000_media_type_internal_serdes ||
 	    igb_sgmii_active_82575(hw))
-		temp = rd32(E1000_SCVPC);
+		rd32(E1000_SCVPC);
 }
 
 /**
@@ -1400,8 +1407,183 @@
 	wr32(E1000_VT_CTL, vt_ctl);
 }
 
+/**
+ *  igb_read_phy_reg_82580 - Read 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read
+ *  @data: pointer to the read data
+ *
+ *  Reads the MDI control register in the PHY at offset and stores the
+ *  information read to data.
+ **/
+static s32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+	u32 mdicnfg = 0;
+	s32 ret_val;
+
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * We config the phy address in MDICNFG register now. Same bits
+	 * as before. The values in MDIC can be written but will be
+	 * ignored. This allows us to call the old function after
+	 * configuring the PHY address in the new register
+	 */
+	mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT);
+	wr32(E1000_MDICNFG, mdicnfg);
+
+	ret_val = igb_read_phy_reg_mdic(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_write_phy_reg_82580 - Write 82580 MDI control register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write to register at offset
+ *
+ *  Writes data to MDI control register in the PHY at offset.
+ **/
+static s32 igb_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
+{
+	u32 mdicnfg = 0;
+	s32 ret_val;
+
+
+	ret_val = hw->phy.ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	/*
+	 * We config the phy address in MDICNFG register now. Same bits
+	 * as before. The values in MDIC can be written but will be
+	 * ignored. This allows us to call the old function after
+	 * configuring the PHY address in the new register
+	 */
+	mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT);
+	wr32(E1000_MDICNFG, mdicnfg);
+
+	ret_val = igb_write_phy_reg_mdic(hw, offset, data);
+
+	hw->phy.ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_reset_hw_82580 - Reset hardware
+ *  @hw: pointer to the HW structure
+ *
+ *  This resets function or entire device (all ports, etc.)
+ *  to a known state.
+ **/
+static s32 igb_reset_hw_82580(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	/* BH SW mailbox bit in SW_FW_SYNC */
+	u16 swmbsw_mask = E1000_SW_SYNCH_MB;
+	u32 ctrl, icr;
+	bool global_device_reset = hw->dev_spec._82575.global_device_reset;
+
+
+	hw->dev_spec._82575.global_device_reset = false;
+
+	/* Get current control state. */
+	ctrl = rd32(E1000_CTRL);
+
+	/*
+	 * Prevent the PCI-E bus from sticking if there is no TLP connection
+	 * on the last TLP read/write transaction when MAC is reset.
+	 */
+	ret_val = igb_disable_pcie_master(hw);
+	if (ret_val)
+		hw_dbg("PCI-E Master disable polling has failed.\n");
+
+	hw_dbg("Masking off all interrupts\n");
+	wr32(E1000_IMC, 0xffffffff);
+	wr32(E1000_RCTL, 0);
+	wr32(E1000_TCTL, E1000_TCTL_PSP);
+	wrfl();
+
+	msleep(10);
+
+	/* Determine whether or not a global dev reset is requested */
+	if (global_device_reset &&
+		igb_acquire_swfw_sync_82575(hw, swmbsw_mask))
+			global_device_reset = false;
+
+	if (global_device_reset &&
+		!(rd32(E1000_STATUS) & E1000_STAT_DEV_RST_SET))
+		ctrl |= E1000_CTRL_DEV_RST;
+	else
+		ctrl |= E1000_CTRL_RST;
+
+	wr32(E1000_CTRL, ctrl);
+
+	/* Add delay to insure DEV_RST has time to complete */
+	if (global_device_reset)
+		msleep(5);
+
+	ret_val = igb_get_auto_rd_done(hw);
+	if (ret_val) {
+		/*
+		 * When auto config read does not complete, do not
+		 * return with an error. This can happen in situations
+		 * where there is no eeprom and prevents getting link.
+		 */
+		hw_dbg("Auto Read Done did not complete\n");
+	}
+
+	/* If EEPROM is not present, run manual init scripts */
+	if ((rd32(E1000_EECD) & E1000_EECD_PRES) == 0)
+		igb_reset_init_script_82575(hw);
+
+	/* clear global device reset status bit */
+	wr32(E1000_STATUS, E1000_STAT_DEV_RST_SET);
+
+	/* Clear any pending interrupt events. */
+	wr32(E1000_IMC, 0xffffffff);
+	icr = rd32(E1000_ICR);
+
+	/* Install any alternate MAC address into RAR0 */
+	ret_val = igb_check_alt_mac_addr(hw);
+
+	/* Release semaphore */
+	if (global_device_reset)
+		igb_release_swfw_sync_82575(hw, swmbsw_mask);
+
+	return ret_val;
+}
+
+/**
+ *  igb_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual RX PBA size
+ *  @data: data received by reading RXPBS register
+ *
+ *  The 82580 uses a table based approach for packet buffer allocation sizes.
+ *  This function converts the retrieved value into the correct table value
+ *     0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
+ *  0x0 36  72 144   1   2   4   8  16
+ *  0x8 35  70 140 rsv rsv rsv rsv rsv
+ */
+u16 igb_rxpbs_adjust_82580(u32 data)
+{
+	u16 ret_val = 0;
+
+	if (data < E1000_82580_RXPBS_TABLE_SIZE)
+		ret_val = e1000_82580_rxpbs_table[data];
+
+	return ret_val;
+}
+
 static struct e1000_mac_operations e1000_mac_ops_82575 = {
-	.reset_hw             = igb_reset_hw_82575,
 	.init_hw              = igb_init_hw_82575,
 	.check_for_link       = igb_check_for_link_82575,
 	.rar_set              = igb_rar_set,
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_regs.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_regs.h
@@ -34,6 +34,7 @@
 #define E1000_EERD     0x00014  /* EEPROM Read - RW */
 #define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
 #define E1000_MDIC     0x00020  /* MDI Control - RW */
+#define E1000_MDICNFG  0x00E04  /* MDI Config - RW */
 #define E1000_SCTL     0x00024  /* SerDes Control - RW */
 #define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
 #define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
@@ -76,59 +77,20 @@
 #define E1000_FCRTV    0x02460  /* Flow Control Refresh Timer Value - RW */
 
 /* IEEE 1588 TIMESYNCH */
-#define E1000_TSYNCTXCTL 0x0B614
-#define E1000_TSYNCTXCTL_VALID (1<<0)
-#define E1000_TSYNCTXCTL_ENABLED (1<<4)
-#define E1000_TSYNCRXCTL 0x0B620
-#define E1000_TSYNCRXCTL_VALID (1<<0)
-#define E1000_TSYNCRXCTL_ENABLED (1<<4)
-enum {
-	E1000_TSYNCRXCTL_TYPE_L2_V2 = 0,
-	E1000_TSYNCRXCTL_TYPE_L4_V1 = (1<<1),
-	E1000_TSYNCRXCTL_TYPE_L2_L4_V2 = (1<<2),
-	E1000_TSYNCRXCTL_TYPE_ALL = (1<<3),
-	E1000_TSYNCRXCTL_TYPE_EVENT_V2 = (1<<3) | (1<<1),
-};
-#define E1000_TSYNCRXCFG 0x05F50
-enum {
-	E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE = 0<<0,
-	E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE = 1<<0,
-	E1000_TSYNCRXCFG_PTP_V1_FOLLOWUP_MESSAGE = 2<<0,
-	E1000_TSYNCRXCFG_PTP_V1_DELAY_RESP_MESSAGE = 3<<0,
-	E1000_TSYNCRXCFG_PTP_V1_MANAGEMENT_MESSAGE = 4<<0,
-
-	E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE = 0<<8,
-	E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE = 1<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_REQ_MESSAGE = 2<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_RESP_MESSAGE = 3<<8,
-	E1000_TSYNCRXCFG_PTP_V2_FOLLOWUP_MESSAGE = 8<<8,
-	E1000_TSYNCRXCFG_PTP_V2_DELAY_RESP_MESSAGE = 9<<8,
-	E1000_TSYNCRXCFG_PTP_V2_PATH_DELAY_FOLLOWUP_MESSAGE = 0xA<<8,
-	E1000_TSYNCRXCFG_PTP_V2_ANNOUNCE_MESSAGE = 0xB<<8,
-	E1000_TSYNCRXCFG_PTP_V2_SIGNALLING_MESSAGE = 0xC<<8,
-	E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE = 0xD<<8,
-};
-#define E1000_SYSTIML 0x0B600
-#define E1000_SYSTIMH 0x0B604
-#define E1000_TIMINCA 0x0B608
-
-#define E1000_RXMTRL     0x0B634
-#define E1000_RXSTMPL 0x0B624
-#define E1000_RXSTMPH 0x0B628
-#define E1000_RXSATRL 0x0B62C
-#define E1000_RXSATRH 0x0B630
-
-#define E1000_TXSTMPL 0x0B618
-#define E1000_TXSTMPH 0x0B61C
-
-#define E1000_ETQF0   0x05CB0
-#define E1000_ETQF1   0x05CB4
-#define E1000_ETQF2   0x05CB8
-#define E1000_ETQF3   0x05CBC
-#define E1000_ETQF4   0x05CC0
-#define E1000_ETQF5   0x05CC4
-#define E1000_ETQF6   0x05CC8
-#define E1000_ETQF7   0x05CCC
+#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
+#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
+#define E1000_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
+#define E1000_RXSTMPL    0x0B624 /* Rx timestamp Low - RO */
+#define E1000_RXSTMPH    0x0B628 /* Rx timestamp High - RO */
+#define E1000_RXSATRL    0x0B62C /* Rx timestamp attribute low - RO */
+#define E1000_RXSATRH    0x0B630 /* Rx timestamp attribute high - RO */
+#define E1000_TXSTMPL    0x0B618 /* Tx timestamp value Low - RO */
+#define E1000_TXSTMPH    0x0B61C /* Tx timestamp value High - RO */
+#define E1000_SYSTIML    0x0B600 /* System time register Low - RO */
+#define E1000_SYSTIMH    0x0B604 /* System time register High - RO */
+#define E1000_TIMINCA    0x0B608 /* Increment attributes register - RW */
+#define E1000_TSAUXC     0x0B640 /* Timesync Auxiliary Control register */
+#define E1000_SYSTIMR    0x0B6F8 /* System time register Residue */
 
 /* Filtering Registers */
 #define E1000_SAQF(_n) (0x5980 + 4 * (_n))
@@ -143,7 +105,9 @@
 #define E1000_ETQF(_n)  (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
 
 #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
+
 /* Split and Replication RX Control - RW */
+#define E1000_RXPBS    0x02404  /* Rx Packet Buffer Size - RW */
 /*
  * Convenience macros
  *
@@ -288,10 +252,17 @@
 #define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
 #define E1000_RA       0x05400  /* Receive Address - RW Array */
 #define E1000_RA2      0x054E0  /* 2nd half of receive address array - RW Array */
+#define E1000_PSRTYPE(_i)       (0x05480 + ((_i) * 4))
 #define E1000_RAL(_i)  (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
                                        (0x054E0 + ((_i - 16) * 8)))
 #define E1000_RAH(_i)  (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
                                        (0x054E4 + ((_i - 16) * 8)))
+#define E1000_IP4AT_REG(_i)     (0x05840 + ((_i) * 8))
+#define E1000_IP6AT_REG(_i)     (0x05880 + ((_i) * 4))
+#define E1000_WUPM_REG(_i)      (0x05A00 + ((_i) * 4))
+#define E1000_FFMT_REG(_i)      (0x09000 + ((_i) * 8))
+#define E1000_FFVT_REG(_i)      (0x09800 + ((_i) * 8))
+#define E1000_FFLT_REG(_i)      (0x05F00 + ((_i) * 8))
 #define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
 #define E1000_VT_CTL   0x0581C  /* VMDq Control - RW */
 #define E1000_WUC      0x05800  /* Wakeup Control - RW */
@@ -331,6 +302,7 @@
 #define E1000_QDE       0x02408 /* Queue Drop Enable - RW */
 #define E1000_DTXSWC    0x03500 /* DMA Tx Switch Control - RW */
 #define E1000_RPLOLR    0x05AF0 /* Replication Offload - RW */
+#define E1000_UTA       0x0A000 /* Unicast Table Array - RW */
 #define E1000_IOVTCL    0x05BBC /* IOV Control Register */
 /* These act per VF so an array friendly macro is used */
 #define E1000_P2VMAILBOX(_n)   (0x00C00 + (4 * (_n)))
@@ -348,4 +320,6 @@
 #define array_rd32(reg, offset) \
 	(readl(hw->hw_addr + reg + ((offset) << 2)))
 
+/* DMA Coalescing registers */
+#define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */
 #endif
--- linux-ec2-2.6.32.orig/drivers/net/igb/igb_ethtool.c
+++ linux-ec2-2.6.32/drivers/net/igb/igb_ethtool.c
@@ -44,78 +44,94 @@
 	int stat_offset;
 };
 
-#define IGB_STAT(m) FIELD_SIZEOF(struct igb_adapter, m), \
-		      offsetof(struct igb_adapter, m)
+#define IGB_STAT(_name, _stat) { \
+	.stat_string = _name, \
+	.sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \
+	.stat_offset = offsetof(struct igb_adapter, _stat) \
+}
 static const struct igb_stats igb_gstrings_stats[] = {
-	{ "rx_packets", IGB_STAT(stats.gprc) },
-	{ "tx_packets", IGB_STAT(stats.gptc) },
-	{ "rx_bytes", IGB_STAT(stats.gorc) },
-	{ "tx_bytes", IGB_STAT(stats.gotc) },
-	{ "rx_broadcast", IGB_STAT(stats.bprc) },
-	{ "tx_broadcast", IGB_STAT(stats.bptc) },
-	{ "rx_multicast", IGB_STAT(stats.mprc) },
-	{ "tx_multicast", IGB_STAT(stats.mptc) },
-	{ "rx_errors", IGB_STAT(net_stats.rx_errors) },
-	{ "tx_errors", IGB_STAT(net_stats.tx_errors) },
-	{ "tx_dropped", IGB_STAT(net_stats.tx_dropped) },
-	{ "multicast", IGB_STAT(stats.mprc) },
-	{ "collisions", IGB_STAT(stats.colc) },
-	{ "rx_length_errors", IGB_STAT(net_stats.rx_length_errors) },
-	{ "rx_over_errors", IGB_STAT(net_stats.rx_over_errors) },
-	{ "rx_crc_errors", IGB_STAT(stats.crcerrs) },
-	{ "rx_frame_errors", IGB_STAT(net_stats.rx_frame_errors) },
-	{ "rx_no_buffer_count", IGB_STAT(stats.rnbc) },
-	{ "rx_queue_drop_packet_count", IGB_STAT(net_stats.rx_fifo_errors) },
-	{ "rx_missed_errors", IGB_STAT(stats.mpc) },
-	{ "tx_aborted_errors", IGB_STAT(stats.ecol) },
-	{ "tx_carrier_errors", IGB_STAT(stats.tncrs) },
-	{ "tx_fifo_errors", IGB_STAT(net_stats.tx_fifo_errors) },
-	{ "tx_heartbeat_errors", IGB_STAT(net_stats.tx_heartbeat_errors) },
-	{ "tx_window_errors", IGB_STAT(stats.latecol) },
-	{ "tx_abort_late_coll", IGB_STAT(stats.latecol) },
-	{ "tx_deferred_ok", IGB_STAT(stats.dc) },
-	{ "tx_single_coll_ok", IGB_STAT(stats.scc) },
-	{ "tx_multi_coll_ok", IGB_STAT(stats.mcc) },
-	{ "tx_timeout_count", IGB_STAT(tx_timeout_count) },
-	{ "tx_restart_queue", IGB_STAT(restart_queue) },
-	{ "rx_long_length_errors", IGB_STAT(stats.roc) },
-	{ "rx_short_length_errors", IGB_STAT(stats.ruc) },
-	{ "rx_align_errors", IGB_STAT(stats.algnerrc) },
-	{ "tx_tcp_seg_good", IGB_STAT(stats.tsctc) },
-	{ "tx_tcp_seg_failed", IGB_STAT(stats.tsctfc) },
-	{ "rx_flow_control_xon", IGB_STAT(stats.xonrxc) },
-	{ "rx_flow_control_xoff", IGB_STAT(stats.xoffrxc) },
-	{ "tx_flow_control_xon", IGB_STAT(stats.xontxc) },
-	{ "tx_flow_control_xoff", IGB_STAT(stats.xofftxc) },
-	{ "rx_long_byte_count", IGB_STAT(stats.gorc) },
-	{ "rx_csum_offload_good", IGB_STAT(hw_csum_good) },
-	{ "rx_csum_offload_errors", IGB_STAT(hw_csum_err) },
-	{ "tx_dma_out_of_sync", IGB_STAT(stats.doosync) },
-	{ "alloc_rx_buff_failed", IGB_STAT(alloc_rx_buff_failed) },
-	{ "tx_smbus", IGB_STAT(stats.mgptc) },
-	{ "rx_smbus", IGB_STAT(stats.mgprc) },
-	{ "dropped_smbus", IGB_STAT(stats.mgpdc) },
+	IGB_STAT("rx_packets", stats.gprc),
+	IGB_STAT("tx_packets", stats.gptc),
+	IGB_STAT("rx_bytes", stats.gorc),
+	IGB_STAT("tx_bytes", stats.gotc),
+	IGB_STAT("rx_broadcast", stats.bprc),
+	IGB_STAT("tx_broadcast", stats.bptc),
+	IGB_STAT("rx_multicast", stats.mprc),
+	IGB_STAT("tx_multicast", stats.mptc),
+	IGB_STAT("multicast", stats.mprc),
+	IGB_STAT("collisions", stats.colc),
+	IGB_STAT("rx_crc_errors", stats.crcerrs),
+	IGB_STAT("rx_no_buffer_count", stats.rnbc),
+	IGB_STAT("rx_missed_errors", stats.mpc),
+	IGB_STAT("tx_aborted_errors", stats.ecol),
+	IGB_STAT("tx_carrier_errors", stats.tncrs),
+	IGB_STAT("tx_window_errors", stats.latecol),
+	IGB_STAT("tx_abort_late_coll", stats.latecol),
+	IGB_STAT("tx_deferred_ok", stats.dc),
+	IGB_STAT("tx_single_coll_ok", stats.scc),
+	IGB_STAT("tx_multi_coll_ok", stats.mcc),
+	IGB_STAT("tx_timeout_count", tx_timeout_count),
+	IGB_STAT("rx_long_length_errors", stats.roc),
+	IGB_STAT("rx_short_length_errors", stats.ruc),
+	IGB_STAT("rx_align_errors", stats.algnerrc),
+	IGB_STAT("tx_tcp_seg_good", stats.tsctc),
+	IGB_STAT("tx_tcp_seg_failed", stats.tsctfc),
+	IGB_STAT("rx_flow_control_xon", stats.xonrxc),
+	IGB_STAT("rx_flow_control_xoff", stats.xoffrxc),
+	IGB_STAT("tx_flow_control_xon", stats.xontxc),
+	IGB_STAT("tx_flow_control_xoff", stats.xofftxc),
+	IGB_STAT("rx_long_byte_count", stats.gorc),
+	IGB_STAT("tx_dma_out_of_sync", stats.doosync),
+	IGB_STAT("tx_smbus", stats.mgptc),
+	IGB_STAT("rx_smbus", stats.mgprc),
+	IGB_STAT("dropped_smbus", stats.mgpdc),
+};
+
+#define IGB_NETDEV_STAT(_net_stat) { \
+	.stat_string = __stringify(_net_stat), \
+	.sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
+	.stat_offset = offsetof(struct net_device_stats, _net_stat) \
+}
+static const struct igb_stats igb_gstrings_net_stats[] = {
+	IGB_NETDEV_STAT(rx_errors),
+	IGB_NETDEV_STAT(tx_errors),
+	IGB_NETDEV_STAT(tx_dropped),
+	IGB_NETDEV_STAT(rx_length_errors),
+	IGB_NETDEV_STAT(rx_over_errors),
+	IGB_NETDEV_STAT(rx_frame_errors),
+	IGB_NETDEV_STAT(rx_fifo_errors),
+	IGB_NETDEV_STAT(tx_fifo_errors),
+	IGB_NETDEV_STAT(tx_heartbeat_errors)
 };
 
-#define IGB_QUEUE_STATS_LEN \
-	(((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues)* \
-	  (sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \
-	 ((((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
-	  (sizeof(struct igb_tx_queue_stats) / sizeof(u64))))
 #define IGB_GLOBAL_STATS_LEN	\
-	sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)
-#define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN)
+	(sizeof(igb_gstrings_stats) / sizeof(struct igb_stats))
+#define IGB_NETDEV_STATS_LEN	\
+	(sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats))
+#define IGB_RX_QUEUE_STATS_LEN \
+	(sizeof(struct igb_rx_queue_stats) / sizeof(u64))
+#define IGB_TX_QUEUE_STATS_LEN \
+	(sizeof(struct igb_tx_queue_stats) / sizeof(u64))
+#define IGB_QUEUE_STATS_LEN \
+	((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \
+	  IGB_RX_QUEUE_STATS_LEN) + \
+	 (((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues * \
+	  IGB_TX_QUEUE_STATS_LEN))
+#define IGB_STATS_LEN \
+	(IGB_GLOBAL_STATS_LEN + IGB_NETDEV_STATS_LEN + IGB_QUEUE_STATS_LEN)
+
 static const char igb_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register test  (offline)", "Eeprom test    (offline)",
 	"Interrupt test (offline)", "Loopback test  (offline)",
 	"Link test   (on/offline)"
 };
-#define IGB_TEST_LEN sizeof(igb_gstrings_test) / ETH_GSTRING_LEN
+#define IGB_TEST_LEN (sizeof(igb_gstrings_test) / ETH_GSTRING_LEN)
 
 static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	u32 status;
 
 	if (hw->phy.media_type == e1000_media_type_copper) {
 
@@ -150,17 +166,20 @@
 
 	ecmd->transceiver = XCVR_INTERNAL;
 
-	if (rd32(E1000_STATUS) & E1000_STATUS_LU) {
+	status = rd32(E1000_STATUS);
 
-		adapter->hw.mac.ops.get_speed_and_duplex(hw,
-					&adapter->link_speed,
-					&adapter->link_duplex);
-		ecmd->speed = adapter->link_speed;
+	if (status & E1000_STATUS_LU) {
 
-		/* unfortunately FULL_DUPLEX != DUPLEX_FULL
-		 *          and HALF_DUPLEX != DUPLEX_HALF */
+		if ((status & E1000_STATUS_SPEED_1000) ||
+		    hw->phy.media_type != e1000_media_type_copper)
+			ecmd->speed = SPEED_1000;
+		else if (status & E1000_STATUS_SPEED_100)
+			ecmd->speed = SPEED_100;
+		else
+			ecmd->speed = SPEED_10;
 
-		if (adapter->link_duplex == FULL_DUPLEX)
+		if ((status & E1000_STATUS_FD) ||
+		    hw->phy.media_type != e1000_media_type_copper)
 			ecmd->duplex = DUPLEX_FULL;
 		else
 			ecmd->duplex = DUPLEX_HALF;
@@ -251,8 +270,9 @@
 		if (netif_running(adapter->netdev)) {
 			igb_down(adapter);
 			igb_up(adapter);
-		} else
+		} else {
 			igb_reset(adapter);
+		}
 	} else {
 		if (pause->rx_pause && pause->tx_pause)
 			hw->fc.requested_mode = e1000_fc_full;
@@ -276,17 +296,20 @@
 static u32 igb_get_rx_csum(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
-	return !(adapter->flags & IGB_FLAG_RX_CSUM_DISABLED);
+	return !!(adapter->rx_ring[0].flags & IGB_RING_FLAG_RX_CSUM);
 }
 
 static int igb_set_rx_csum(struct net_device *netdev, u32 data)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
+	int i;
 
-	if (data)
-		adapter->flags &= ~IGB_FLAG_RX_CSUM_DISABLED;
-	else
-		adapter->flags |= IGB_FLAG_RX_CSUM_DISABLED;
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		if (data)
+			adapter->rx_ring[i].flags |= IGB_RING_FLAG_RX_CSUM;
+		else
+			adapter->rx_ring[i].flags &= ~IGB_RING_FLAG_RX_CSUM;
+	}
 
 	return 0;
 }
@@ -302,7 +325,7 @@
 
 	if (data) {
 		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-		if (adapter->hw.mac.type == e1000_82576)
+		if (adapter->hw.mac.type >= e1000_82576)
 			netdev->features |= NETIF_F_SCTP_CSUM;
 	} else {
 		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -496,19 +519,10 @@
 	regs_buff[119] = adapter->stats.scvpc;
 	regs_buff[120] = adapter->stats.hrmpc;
 
-	/* These should probably be added to e1000_regs.h instead */
-	#define E1000_PSRTYPE_REG(_i) (0x05480 + ((_i) * 4))
-	#define E1000_IP4AT_REG(_i)   (0x05840 + ((_i) * 8))
-	#define E1000_IP6AT_REG(_i)   (0x05880 + ((_i) * 4))
-	#define E1000_WUPM_REG(_i)    (0x05A00 + ((_i) * 4))
-	#define E1000_FFMT_REG(_i)    (0x09000 + ((_i) * 8))
-	#define E1000_FFVT_REG(_i)    (0x09800 + ((_i) * 8))
-	#define E1000_FFLT_REG(_i)    (0x05F00 + ((_i) * 8))
-
 	for (i = 0; i < 4; i++)
 		regs_buff[121 + i] = rd32(E1000_SRRCTL(i));
 	for (i = 0; i < 4; i++)
-		regs_buff[125 + i] = rd32(E1000_PSRTYPE_REG(i));
+		regs_buff[125 + i] = rd32(E1000_PSRTYPE(i));
 	for (i = 0; i < 4; i++)
 		regs_buff[129 + i] = rd32(E1000_RDBAL(i));
 	for (i = 0; i < 4; i++)
@@ -733,17 +747,17 @@
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct igb_ring *temp_ring;
 	int i, err = 0;
-	u32 new_rx_count, new_tx_count;
+	u16 new_rx_count, new_tx_count;
 
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
-	new_rx_count = max(ring->rx_pending, (u32)IGB_MIN_RXD);
-	new_rx_count = min(new_rx_count, (u32)IGB_MAX_RXD);
+	new_rx_count = min_t(u32, ring->rx_pending, IGB_MAX_RXD);
+	new_rx_count = max_t(u16, new_rx_count, IGB_MIN_RXD);
 	new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
 
-	new_tx_count = max(ring->tx_pending, (u32)IGB_MIN_TXD);
-	new_tx_count = min(new_tx_count, (u32)IGB_MAX_TXD);
+	new_tx_count = min_t(u32, ring->tx_pending, IGB_MAX_TXD);
+	new_tx_count = max_t(u16, new_tx_count, IGB_MIN_TXD);
 	new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
 
 	if ((new_tx_count == adapter->tx_ring_count) &&
@@ -788,7 +802,7 @@
 
 		for (i = 0; i < adapter->num_tx_queues; i++) {
 			temp_ring[i].count = new_tx_count;
-			err = igb_setup_tx_resources(adapter, &temp_ring[i]);
+			err = igb_setup_tx_resources(&temp_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
@@ -813,7 +827,7 @@
 
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			temp_ring[i].count = new_rx_count;
-			err = igb_setup_rx_resources(adapter, &temp_ring[i]);
+			err = igb_setup_rx_resources(&temp_ring[i]);
 			if (err) {
 				while (i) {
 					i--;
@@ -867,6 +881,49 @@
 #define TABLE64_TEST_LO	5
 #define TABLE64_TEST_HI	6
 
+/* 82580 reg test */
+static struct igb_reg_test reg_test_82580[] = {
+	{ E1000_FCAL,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_FCAH,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+	{ E1000_FCT,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
+	{ E1000_VET,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_RDBAL(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ E1000_RDBAH(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_RDLEN(0),  0x100, 4,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
+	{ E1000_RDBAL(4),  0x40,  4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ E1000_RDBAH(4),  0x40,  4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_RDLEN(4),  0x40,  4,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
+	/* RDH is read-only for 82580, only test RDT. */
+	{ E1000_RDT(0),	   0x100, 4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ E1000_RDT(4),	   0x40,  4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ E1000_FCRTH,	   0x100, 1,  PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 },
+	{ E1000_FCTTV,	   0x100, 1,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ E1000_TIPG,	   0x100, 1,  PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
+	{ E1000_TDBAL(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ E1000_TDBAH(0),  0x100, 4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_TDLEN(0),  0x100, 4,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
+	{ E1000_TDBAL(4),  0x40,  4,  PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+	{ E1000_TDBAH(4),  0x40,  4,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_TDLEN(4),  0x40,  4,  PATTERN_TEST, 0x000FFFF0, 0x000FFFFF },
+	{ E1000_TDT(0),	   0x100, 4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ E1000_TDT(4),	   0x40,  4,  PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+	{ E1000_RCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+	{ E1000_RCTL, 	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB },
+	{ E1000_RCTL, 	   0x100, 1,  SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF },
+	{ E1000_TCTL,	   0x100, 1,  SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
+	{ E1000_RA,	   0, 16, TABLE64_TEST_LO,
+						0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_RA,	   0, 16, TABLE64_TEST_HI,
+						0x83FFFFFF, 0xFFFFFFFF },
+	{ E1000_RA2,	   0, 8, TABLE64_TEST_LO,
+						0xFFFFFFFF, 0xFFFFFFFF },
+	{ E1000_RA2,	   0, 8, TABLE64_TEST_HI,
+						0x83FFFFFF, 0xFFFFFFFF },
+	{ E1000_MTA,	   0, 128, TABLE32_TEST,
+						0xFFFFFFFF, 0xFFFFFFFF },
+	{ 0, 0, 0, 0 }
+};
+
 /* 82576 reg test */
 static struct igb_reg_test reg_test_82576[] = {
 	{ E1000_FCAL,	   0x100, 1,  PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
@@ -944,7 +1001,7 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 pat, val;
-	u32 _test[] =
+	static const u32 _test[] =
 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {
 		wr32(reg, (_test[pat] & write));
@@ -957,6 +1014,7 @@
 			return 1;
 		}
 	}
+
 	return 0;
 }
 
@@ -974,6 +1032,7 @@
 		*data = reg;
 		return 1;
 	}
+
 	return 0;
 }
 
@@ -996,14 +1055,18 @@
 	u32 value, before, after;
 	u32 i, toggle;
 
-	toggle = 0x7FFFF3FF;
-
 	switch (adapter->hw.mac.type) {
+	case e1000_82580:
+		test = reg_test_82580;
+		toggle = 0x7FEFF3FF;
+		break;
 	case e1000_82576:
 		test = reg_test_82576;
+		toggle = 0x7FFFF3FF;
 		break;
 	default:
 		test = reg_test_82575;
+		toggle = 0x7FFFF3FF;
 		break;
 	}
 
@@ -1081,8 +1144,7 @@
 	*data = 0;
 	/* Read and add up the contents of the EEPROM */
 	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
-		if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp))
-		    < 0) {
+		if ((adapter->hw.nvm.ops.read(&adapter->hw, i, 1, &temp)) < 0) {
 			*data = 1;
 			break;
 		}
@@ -1098,8 +1160,7 @@
 
 static irqreturn_t igb_test_intr(int irq, void *data)
 {
-	struct net_device *netdev = (struct net_device *) data;
-	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct igb_adapter *adapter = (struct igb_adapter *) data;
 	struct e1000_hw *hw = &adapter->hw;
 
 	adapter->test_icr |= rd32(E1000_ICR);
@@ -1117,38 +1178,45 @@
 	*data = 0;
 
 	/* Hook up test interrupt handler just for this test */
-	if (adapter->msix_entries)
-		/* NOTE: we don't test MSI-X interrupts here, yet */
-		return 0;
-
-	if (adapter->flags & IGB_FLAG_HAS_MSI) {
+	if (adapter->msix_entries) {
+		if (request_irq(adapter->msix_entries[0].vector,
+		                &igb_test_intr, 0, netdev->name, adapter)) {
+			*data = 1;
+			return -1;
+		}
+	} else if (adapter->flags & IGB_FLAG_HAS_MSI) {
 		shared_int = false;
-		if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) {
+		if (request_irq(irq,
+		                &igb_test_intr, 0, netdev->name, adapter)) {
 			*data = 1;
 			return -1;
 		}
 	} else if (!request_irq(irq, &igb_test_intr, IRQF_PROBE_SHARED,
-				netdev->name, netdev)) {
+				netdev->name, adapter)) {
 		shared_int = false;
 	} else if (request_irq(irq, &igb_test_intr, IRQF_SHARED,
-		 netdev->name, netdev)) {
+		 netdev->name, adapter)) {
 		*data = 1;
 		return -1;
 	}
 	dev_info(&adapter->pdev->dev, "testing %s interrupt\n",
 		(shared_int ? "shared" : "unshared"));
+
 	/* Disable all the interrupts */
-	wr32(E1000_IMC, 0xFFFFFFFF);
+	wr32(E1000_IMC, ~0);
 	msleep(10);
 
 	/* Define all writable bits for ICS */
-	switch(hw->mac.type) {
+	switch (hw->mac.type) {
 	case e1000_82575:
 		ics_mask = 0x37F47EDD;
 		break;
 	case e1000_82576:
 		ics_mask = 0x77D4FBFD;
 		break;
+	case e1000_82580:
+		ics_mask = 0x77DCFED5;
+		break;
 	default:
 		ics_mask = 0x7FFFFFFF;
 		break;
@@ -1232,190 +1300,61 @@
 	msleep(10);
 
 	/* Unhook test interrupt handler */
-	free_irq(irq, netdev);
+	if (adapter->msix_entries)
+		free_irq(adapter->msix_entries[0].vector, adapter);
+	else
+		free_irq(irq, adapter);
 
 	return *data;
 }
 
 static void igb_free_desc_rings(struct igb_adapter *adapter)
 {
-	struct igb_ring *tx_ring = &adapter->test_tx_ring;
-	struct igb_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i;
-
-	if (tx_ring->desc && tx_ring->buffer_info) {
-		for (i = 0; i < tx_ring->count; i++) {
-			struct igb_buffer *buf = &(tx_ring->buffer_info[i]);
-			if (buf->dma)
-				pci_unmap_single(pdev, buf->dma, buf->length,
-						 PCI_DMA_TODEVICE);
-			if (buf->skb)
-				dev_kfree_skb(buf->skb);
-		}
-	}
-
-	if (rx_ring->desc && rx_ring->buffer_info) {
-		for (i = 0; i < rx_ring->count; i++) {
-			struct igb_buffer *buf = &(rx_ring->buffer_info[i]);
-			if (buf->dma)
-				pci_unmap_single(pdev, buf->dma,
-						 IGB_RXBUFFER_2048,
-						 PCI_DMA_FROMDEVICE);
-			if (buf->skb)
-				dev_kfree_skb(buf->skb);
-		}
-	}
-
-	if (tx_ring->desc) {
-		pci_free_consistent(pdev, tx_ring->size, tx_ring->desc,
-				    tx_ring->dma);
-		tx_ring->desc = NULL;
-	}
-	if (rx_ring->desc) {
-		pci_free_consistent(pdev, rx_ring->size, rx_ring->desc,
-				    rx_ring->dma);
-		rx_ring->desc = NULL;
-	}
-
-	kfree(tx_ring->buffer_info);
-	tx_ring->buffer_info = NULL;
-	kfree(rx_ring->buffer_info);
-	rx_ring->buffer_info = NULL;
-
-	return;
+	igb_free_tx_resources(&adapter->test_tx_ring);
+	igb_free_rx_resources(&adapter->test_rx_ring);
 }
 
 static int igb_setup_desc_rings(struct igb_adapter *adapter)
 {
-	struct e1000_hw *hw = &adapter->hw;
 	struct igb_ring *tx_ring = &adapter->test_tx_ring;
 	struct igb_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct igb_buffer *buffer_info;
-	u32 rctl;
-	int i, ret_val;
+	struct e1000_hw *hw = &adapter->hw;
+	int ret_val;
 
 	/* Setup Tx descriptor ring and Tx buffers */
+	tx_ring->count = IGB_DEFAULT_TXD;
+	tx_ring->pdev = adapter->pdev;
+	tx_ring->netdev = adapter->netdev;
+	tx_ring->reg_idx = adapter->vfs_allocated_count;
 
-	if (!tx_ring->count)
-		tx_ring->count = IGB_DEFAULT_TXD;
-
-	tx_ring->buffer_info = kcalloc(tx_ring->count,
-				       sizeof(struct igb_buffer),
-				       GFP_KERNEL);
-	if (!tx_ring->buffer_info) {
+	if (igb_setup_tx_resources(tx_ring)) {
 		ret_val = 1;
 		goto err_nomem;
 	}
 
-	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
-	tx_ring->size = ALIGN(tx_ring->size, 4096);
-	tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
-					     &tx_ring->dma);
-	if (!tx_ring->desc) {
-		ret_val = 2;
-		goto err_nomem;
-	}
-	tx_ring->next_to_use = tx_ring->next_to_clean = 0;
-
-	wr32(E1000_TDBAL(0),
-			((u64) tx_ring->dma & 0x00000000FFFFFFFF));
-	wr32(E1000_TDBAH(0), ((u64) tx_ring->dma >> 32));
-	wr32(E1000_TDLEN(0),
-			tx_ring->count * sizeof(union e1000_adv_tx_desc));
-	wr32(E1000_TDH(0), 0);
-	wr32(E1000_TDT(0), 0);
-	wr32(E1000_TCTL,
-			E1000_TCTL_PSP | E1000_TCTL_EN |
-			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
-			E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT);
-
-	for (i = 0; i < tx_ring->count; i++) {
-		union e1000_adv_tx_desc *tx_desc;
-		struct sk_buff *skb;
-		unsigned int size = 1024;
-
-		tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
-		skb = alloc_skb(size, GFP_KERNEL);
-		if (!skb) {
-			ret_val = 3;
-			goto err_nomem;
-		}
-		skb_put(skb, size);
-		buffer_info = &tx_ring->buffer_info[i];
-		buffer_info->skb = skb;
-		buffer_info->length = skb->len;
-		buffer_info->dma = pci_map_single(pdev, skb->data, skb->len,
-		                                  PCI_DMA_TODEVICE);
-		tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
-		tx_desc->read.olinfo_status = cpu_to_le32(skb->len) <<
-		                              E1000_ADVTXD_PAYLEN_SHIFT;
-		tx_desc->read.cmd_type_len = cpu_to_le32(skb->len);
-		tx_desc->read.cmd_type_len |= cpu_to_le32(E1000_TXD_CMD_EOP |
-		                                          E1000_TXD_CMD_IFCS |
-		                                          E1000_TXD_CMD_RS |
-		                                          E1000_ADVTXD_DTYP_DATA |
-		                                          E1000_ADVTXD_DCMD_DEXT);
-	}
+	igb_setup_tctl(adapter);
+	igb_configure_tx_ring(adapter, tx_ring);
 
 	/* Setup Rx descriptor ring and Rx buffers */
+	rx_ring->count = IGB_DEFAULT_RXD;
+	rx_ring->pdev = adapter->pdev;
+	rx_ring->netdev = adapter->netdev;
+	rx_ring->rx_buffer_len = IGB_RXBUFFER_2048;
+	rx_ring->reg_idx = adapter->vfs_allocated_count;
 
-	if (!rx_ring->count)
-		rx_ring->count = IGB_DEFAULT_RXD;
-
-	rx_ring->buffer_info = kcalloc(rx_ring->count,
-				       sizeof(struct igb_buffer),
-				       GFP_KERNEL);
-	if (!rx_ring->buffer_info) {
-		ret_val = 4;
+	if (igb_setup_rx_resources(rx_ring)) {
+		ret_val = 3;
 		goto err_nomem;
 	}
 
-	rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
-	rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size,
-					     &rx_ring->dma);
-	if (!rx_ring->desc) {
-		ret_val = 5;
-		goto err_nomem;
-	}
-	rx_ring->next_to_use = rx_ring->next_to_clean = 0;
+	/* set the default queue to queue 0 of PF */
+	wr32(E1000_MRQC, adapter->vfs_allocated_count << 3);
 
-	rctl = rd32(E1000_RCTL);
-	wr32(E1000_RCTL, rctl & ~E1000_RCTL_EN);
-	wr32(E1000_RDBAL(0),
-			((u64) rx_ring->dma & 0xFFFFFFFF));
-	wr32(E1000_RDBAH(0),
-			((u64) rx_ring->dma >> 32));
-	wr32(E1000_RDLEN(0), rx_ring->size);
-	wr32(E1000_RDH(0), 0);
-	wr32(E1000_RDT(0), 0);
-	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
-	wr32(E1000_RCTL, rctl);
-	wr32(E1000_SRRCTL(0), E1000_SRRCTL_DESCTYPE_ADV_ONEBUF);
+	/* enable receive ring */
+	igb_setup_rctl(adapter);
+	igb_configure_rx_ring(adapter, rx_ring);
 
-	for (i = 0; i < rx_ring->count; i++) {
-		union e1000_adv_rx_desc *rx_desc;
-		struct sk_buff *skb;
-
-		buffer_info = &rx_ring->buffer_info[i];
-		rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
-		skb = alloc_skb(IGB_RXBUFFER_2048 + NET_IP_ALIGN,
-				GFP_KERNEL);
-		if (!skb) {
-			ret_val = 6;
-			goto err_nomem;
-		}
-		skb_reserve(skb, NET_IP_ALIGN);
-		buffer_info->skb = skb;
-		buffer_info->dma = pci_map_single(pdev, skb->data,
-		                                  IGB_RXBUFFER_2048,
-		                                  PCI_DMA_FROMDEVICE);
-		rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma);
-		memset(skb->data, 0x00, skb->len);
-	}
+	igb_alloc_rx_buffers_adv(rx_ring, igb_desc_unused(rx_ring));
 
 	return 0;
 
@@ -1449,6 +1388,9 @@
 		igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
 		/* autoneg off */
 		igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
+	} else if (hw->phy.type == e1000_phy_82580) {
+		/* enable MII loopback */
+		igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041);
 	}
 
 	ctrl_reg = rd32(E1000_CTRL);
@@ -1491,7 +1433,10 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u32 reg;
 
-	if (hw->phy.media_type == e1000_media_type_internal_serdes) {
+	reg = rd32(E1000_CTRL_EXT);
+
+	/* use CTRL_EXT to identify link type as SGMII can appear as copper */
+	if (reg & E1000_CTRL_EXT_LINK_MODE_MASK) {
 		reg = rd32(E1000_RCTL);
 		reg |= E1000_RCTL_LBM_TCVR;
 		wr32(E1000_RCTL, reg);
@@ -1522,11 +1467,9 @@
 		wr32(E1000_PCS_LCTL, reg);
 
 		return 0;
-	} else if (hw->phy.media_type == e1000_media_type_copper) {
-		return igb_set_phy_loopback(adapter);
 	}
 
-	return 7;
+	return igb_set_phy_loopback(adapter);
 }
 
 static void igb_loopback_cleanup(struct igb_adapter *adapter)
@@ -1552,35 +1495,99 @@
 				    unsigned int frame_size)
 {
 	memset(skb->data, 0xFF, frame_size);
-	frame_size &= ~1;
-	memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
-	memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
-	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
+	frame_size /= 2;
+	memset(&skb->data[frame_size], 0xAA, frame_size - 1);
+	memset(&skb->data[frame_size + 10], 0xBE, 1);
+	memset(&skb->data[frame_size + 12], 0xAF, 1);
 }
 
 static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
 {
-	frame_size &= ~1;
-	if (*(skb->data + 3) == 0xFF)
-		if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
-		   (*(skb->data + frame_size / 2 + 12) == 0xAF))
+	frame_size /= 2;
+	if (*(skb->data + 3) == 0xFF) {
+		if ((*(skb->data + frame_size + 10) == 0xBE) &&
+		   (*(skb->data + frame_size + 12) == 0xAF)) {
 			return 0;
+		}
+	}
 	return 13;
 }
 
+static int igb_clean_test_rings(struct igb_ring *rx_ring,
+                                struct igb_ring *tx_ring,
+                                unsigned int size)
+{
+	union e1000_adv_rx_desc *rx_desc;
+	struct igb_buffer *buffer_info;
+	int rx_ntc, tx_ntc, count = 0;
+	u32 staterr;
+
+	/* initialize next to clean and descriptor values */
+	rx_ntc = rx_ring->next_to_clean;
+	tx_ntc = tx_ring->next_to_clean;
+	rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
+	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+
+	while (staterr & E1000_RXD_STAT_DD) {
+		/* check rx buffer */
+		buffer_info = &rx_ring->buffer_info[rx_ntc];
+
+		/* unmap rx buffer, will be remapped by alloc_rx_buffers */
+		pci_unmap_single(rx_ring->pdev,
+		                 buffer_info->dma,
+				 rx_ring->rx_buffer_len,
+				 PCI_DMA_FROMDEVICE);
+		buffer_info->dma = 0;
+
+		/* verify contents of skb */
+		if (!igb_check_lbtest_frame(buffer_info->skb, size))
+			count++;
+
+		/* unmap buffer on tx side */
+		buffer_info = &tx_ring->buffer_info[tx_ntc];
+		igb_unmap_and_free_tx_resource(tx_ring, buffer_info);
+
+		/* increment rx/tx next to clean counters */
+		rx_ntc++;
+		if (rx_ntc == rx_ring->count)
+			rx_ntc = 0;
+		tx_ntc++;
+		if (tx_ntc == tx_ring->count)
+			tx_ntc = 0;
+
+		/* fetch next descriptor */
+		rx_desc = E1000_RX_DESC_ADV(*rx_ring, rx_ntc);
+		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+	}
+
+	/* re-map buffers to ring, store next to clean values */
+	igb_alloc_rx_buffers_adv(rx_ring, count);
+	rx_ring->next_to_clean = rx_ntc;
+	tx_ring->next_to_clean = tx_ntc;
+
+	return count;
+}
+
 static int igb_run_loopback_test(struct igb_adapter *adapter)
 {
-	struct e1000_hw *hw = &adapter->hw;
 	struct igb_ring *tx_ring = &adapter->test_tx_ring;
 	struct igb_ring *rx_ring = &adapter->test_rx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	int i, j, k, l, lc, good_cnt;
-	int ret_val = 0;
-	unsigned long time;
+	int i, j, lc, good_cnt, ret_val = 0;
+	unsigned int size = 1024;
+	netdev_tx_t tx_ret_val;
+	struct sk_buff *skb;
+
+	/* allocate test skb */
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+		return 11;
+
+	/* place data into test skb */
+	igb_create_lbtest_frame(skb, size);
+	skb_put(skb, size);
 
-	wr32(E1000_RDT(0), rx_ring->count - 1);
-
-	/* Calculate the loop count based on the largest descriptor ring
+	/*
+	 * Calculate the loop count based on the largest descriptor ring
 	 * The idea is to wrap the largest ring a number of times using 64
 	 * send/receive pairs during each loop
 	 */
@@ -1590,50 +1597,36 @@
 	else
 		lc = ((rx_ring->count / 64) * 2) + 1;
 
-	k = l = 0;
 	for (j = 0; j <= lc; j++) { /* loop count loop */
-		for (i = 0; i < 64; i++) { /* send the packets */
-			igb_create_lbtest_frame(tx_ring->buffer_info[k].skb,
-						1024);
-			pci_dma_sync_single_for_device(pdev,
-				tx_ring->buffer_info[k].dma,
-				tx_ring->buffer_info[k].length,
-				PCI_DMA_TODEVICE);
-			k++;
-			if (k == tx_ring->count)
-				k = 0;
-		}
-		wr32(E1000_TDT(0), k);
-		msleep(200);
-		time = jiffies; /* set the start time for the receive */
+		/* reset count of good packets */
 		good_cnt = 0;
-		do { /* receive the sent packets */
-			pci_dma_sync_single_for_cpu(pdev,
-					rx_ring->buffer_info[l].dma,
-					IGB_RXBUFFER_2048,
-					PCI_DMA_FROMDEVICE);
-
-			ret_val = igb_check_lbtest_frame(
-					     rx_ring->buffer_info[l].skb, 1024);
-			if (!ret_val)
+
+		/* place 64 packets on the transmit queue*/
+		for (i = 0; i < 64; i++) {
+			skb_get(skb);
+			tx_ret_val = igb_xmit_frame_ring_adv(skb, tx_ring);
+			if (tx_ret_val == NETDEV_TX_OK)
 				good_cnt++;
-			l++;
-			if (l == rx_ring->count)
-				l = 0;
-			/* time + 20 msecs (200 msecs on 2.4) is more than
-			 * enough time to complete the receives, if it's
-			 * exceeded, break and error off
-			 */
-		} while (good_cnt < 64 && jiffies < (time + 20));
+		}
+
 		if (good_cnt != 64) {
-			ret_val = 13; /* ret_val is the same as mis-compare */
+			ret_val = 12;
 			break;
 		}
-		if (jiffies >= (time + 20)) {
-			ret_val = 14; /* error code for time out error */
+
+		/* allow 200 milliseconds for packets to go from tx to rx */
+		msleep(200);
+
+		good_cnt = igb_clean_test_rings(rx_ring, tx_ring, size);
+		if (good_cnt != 64) {
+			ret_val = 13;
 			break;
 		}
 	} /* end loop count loop */
+
+	/* free the original skb */
+	kfree_skb(skb);
+
 	return ret_val;
 }
 
@@ -1686,8 +1679,7 @@
 		if (hw->mac.autoneg)
 			msleep(4000);
 
-		if (!(rd32(E1000_STATUS) &
-		      E1000_STATUS_LU))
+		if (!(rd32(E1000_STATUS) & E1000_STATUS_LU))
 			*data = 1;
 	}
 	return *data;
@@ -1803,7 +1795,7 @@
 		/* dual port cards only support WoL on port A from now on
 		 * unless it was enabled in the eeprom for port B
 		 * so exclude FUNC_1 ports from having WoL enabled */
-		if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1 &&
+		if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) &&
 		    !adapter->eeprom_wol) {
 			wol->supported = 0;
 			break;
@@ -1869,7 +1861,6 @@
 		adapter->wol |= E1000_WUFC_BC;
 	if (wol->wolopts & WAKE_MAGIC)
 		adapter->wol |= E1000_WUFC_MAG;
-
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
 	return 0;
@@ -1882,12 +1873,19 @@
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	unsigned long timeout;
 
-	if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+	timeout = data * 1000;
+
+	/*
+	 *  msleep_interruptable only accepts unsigned int so we are limited
+	 * in how long a duration we can wait
+	 */
+	if (!timeout || timeout > UINT_MAX)
+		timeout = UINT_MAX;
 
 	igb_blink_led(hw);
-	msleep_interruptible(data * 1000);
+	msleep_interruptible(timeout);
 
 	igb_led_off(hw);
 	clear_bit(IGB_LED_ON, &adapter->led_status);
@@ -1900,7 +1898,6 @@
 			    struct ethtool_coalesce *ec)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
 	int i;
 
 	if ((ec->rx_coalesce_usecs > IGB_MAX_ITR_USECS) ||
@@ -1909,17 +1906,39 @@
 	    (ec->rx_coalesce_usecs == 2))
 		return -EINVAL;
 
+	if ((ec->tx_coalesce_usecs > IGB_MAX_ITR_USECS) ||
+	    ((ec->tx_coalesce_usecs > 3) &&
+	     (ec->tx_coalesce_usecs < IGB_MIN_ITR_USECS)) ||
+	    (ec->tx_coalesce_usecs == 2))
+		return -EINVAL;
+
+	if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
+		return -EINVAL;
+
 	/* convert to rate of irq's per second */
-	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
-		adapter->itr_setting = ec->rx_coalesce_usecs;
-		adapter->itr = IGB_START_ITR;
-	} else {
-		adapter->itr_setting = ec->rx_coalesce_usecs << 2;
-		adapter->itr = adapter->itr_setting;
-	}
+	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
+		adapter->rx_itr_setting = ec->rx_coalesce_usecs;
+	else
+		adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2;
 
-	for (i = 0; i < adapter->num_rx_queues; i++)
-		wr32(adapter->rx_ring[i].itr_register, adapter->itr);
+	/* convert to rate of irq's per second */
+	if (adapter->flags & IGB_FLAG_QUEUE_PAIRS)
+		adapter->tx_itr_setting = adapter->rx_itr_setting;
+	else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3)
+		adapter->tx_itr_setting = ec->tx_coalesce_usecs;
+	else
+		adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2;
+
+	for (i = 0; i < adapter->num_q_vectors; i++) {
+		struct igb_q_vector *q_vector = adapter->q_vector[i];
+		if (q_vector->rx_ring)
+			q_vector->itr_val = adapter->rx_itr_setting;
+		else
+			q_vector->itr_val = adapter->tx_itr_setting;
+		if (q_vector->itr_val && q_vector->itr_val <= 3)
+			q_vector->itr_val = IGB_START_ITR;
+		q_vector->set_itr = 1;
+	}
 
 	return 0;
 }
@@ -1929,15 +1948,21 @@
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
 
-	if (adapter->itr_setting <= 3)
-		ec->rx_coalesce_usecs = adapter->itr_setting;
+	if (adapter->rx_itr_setting <= 3)
+		ec->rx_coalesce_usecs = adapter->rx_itr_setting;
 	else
-		ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
+		ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2;
+
+	if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS)) {
+		if (adapter->tx_itr_setting <= 3)
+			ec->tx_coalesce_usecs = adapter->tx_itr_setting;
+		else
+			ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2;
+	}
 
 	return 0;
 }
 
-
 static int igb_nway_reset(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
@@ -1962,31 +1987,32 @@
 				  struct ethtool_stats *stats, u64 *data)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct net_device_stats *net_stats = &netdev->stats;
 	u64 *queue_stat;
-	int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64);
-	int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64);
-	int j;
-	int i;
+	int i, j, k;
+	char *p;
 
 	igb_update_stats(adapter);
+
 	for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
-		char *p = (char *)adapter+igb_gstrings_stats[i].stat_offset;
+		p = (char *)adapter + igb_gstrings_stats[i].stat_offset;
 		data[i] = (igb_gstrings_stats[i].sizeof_stat ==
 			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 	}
+	for (j = 0; j < IGB_NETDEV_STATS_LEN; j++, i++) {
+		p = (char *)net_stats + igb_gstrings_net_stats[j].stat_offset;
+		data[i] = (igb_gstrings_net_stats[j].sizeof_stat ==
+			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+	}
 	for (j = 0; j < adapter->num_tx_queues; j++) {
-		int k;
 		queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;
-		for (k = 0; k < stat_count_tx; k++)
-			data[i + k] = queue_stat[k];
-		i += k;
+		for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++)
+			data[i] = queue_stat[k];
 	}
 	for (j = 0; j < adapter->num_rx_queues; j++) {
-		int k;
 		queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;
-		for (k = 0; k < stat_count_rx; k++)
-			data[i + k] = queue_stat[k];
-		i += k;
+		for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++)
+			data[i] = queue_stat[k];
 	}
 }
 
@@ -2007,11 +2033,18 @@
 			       ETH_GSTRING_LEN);
 			p += ETH_GSTRING_LEN;
 		}
+		for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) {
+			memcpy(p, igb_gstrings_net_stats[i].stat_string,
+			       ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
 		for (i = 0; i < adapter->num_tx_queues; i++) {
 			sprintf(p, "tx_queue_%u_packets", i);
 			p += ETH_GSTRING_LEN;
 			sprintf(p, "tx_queue_%u_bytes", i);
 			p += ETH_GSTRING_LEN;
+			sprintf(p, "tx_queue_%u_restart", i);
+			p += ETH_GSTRING_LEN;
 		}
 		for (i = 0; i < adapter->num_rx_queues; i++) {
 			sprintf(p, "rx_queue_%u_packets", i);
@@ -2020,6 +2053,10 @@
 			p += ETH_GSTRING_LEN;
 			sprintf(p, "rx_queue_%u_drops", i);
 			p += ETH_GSTRING_LEN;
+			sprintf(p, "rx_queue_%u_csum_err", i);
+			p += ETH_GSTRING_LEN;
+			sprintf(p, "rx_queue_%u_alloc_failed", i);
+			p += ETH_GSTRING_LEN;
 		}
 /*		BUG_ON(p - data != IGB_STATS_LEN * ETH_GSTRING_LEN); */
 		break;
--- linux-ec2-2.6.32.orig/drivers/net/igb/e1000_hw.h
+++ linux-ec2-2.6.32/drivers/net/igb/e1000_hw.h
@@ -42,20 +42,35 @@
 #define E1000_DEV_ID_82576_SERDES             0x10E7
 #define E1000_DEV_ID_82576_QUAD_COPPER        0x10E8
 #define E1000_DEV_ID_82576_NS                 0x150A
+#define E1000_DEV_ID_82576_NS_SERDES          0x1518
 #define E1000_DEV_ID_82576_SERDES_QUAD        0x150D
 #define E1000_DEV_ID_82575EB_COPPER           0x10A7
 #define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
 #define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
+#define E1000_DEV_ID_82580_COPPER             0x150E
+#define E1000_DEV_ID_82580_FIBER              0x150F
+#define E1000_DEV_ID_82580_SERDES             0x1510
+#define E1000_DEV_ID_82580_SGMII              0x1511
+#define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
 
 #define E1000_REVISION_2 2
 #define E1000_REVISION_4 4
 
+#define E1000_FUNC_0     0
 #define E1000_FUNC_1     1
+#define E1000_FUNC_2     2
+#define E1000_FUNC_3     3
+
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0   0
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1   3
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2   6
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3   9
 
 enum e1000_mac_type {
 	e1000_undefined = 0,
 	e1000_82575,
 	e1000_82576,
+	e1000_82580,
 	e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
 };
 
@@ -70,7 +85,6 @@
 	e1000_nvm_unknown = 0,
 	e1000_nvm_none,
 	e1000_nvm_eeprom_spi,
-	e1000_nvm_eeprom_microwire,
 	e1000_nvm_flash_hw,
 	e1000_nvm_flash_sw
 };
@@ -79,8 +93,6 @@
 	e1000_nvm_override_none = 0,
 	e1000_nvm_override_spi_small,
 	e1000_nvm_override_spi_large,
-	e1000_nvm_override_microwire_small,
-	e1000_nvm_override_microwire_large
 };
 
 enum e1000_phy_type {
@@ -92,6 +104,7 @@
 	e1000_phy_gg82563,
 	e1000_phy_igp_3,
 	e1000_phy_ife,
+	e1000_phy_82580,
 };
 
 enum e1000_bus_type {
@@ -288,6 +301,7 @@
 
 struct e1000_phy_operations {
 	s32  (*acquire)(struct e1000_hw *);
+	s32  (*check_polarity)(struct e1000_hw *);
 	s32  (*check_reset_block)(struct e1000_hw *);
 	s32  (*force_speed_duplex)(struct e1000_hw *);
 	s32  (*get_cfg_done)(struct e1000_hw *hw);
@@ -339,6 +353,7 @@
 	u16 ifs_ratio;
 	u16 ifs_step_size;
 	u16 mta_reg_count;
+	u16 uta_reg_count;
 
 	/* Maximum size of the MTA register table in all supported adapters */
 	#define MAX_MTA_REG 128
@@ -463,6 +478,7 @@
 
 struct e1000_dev_spec_82575 {
 	bool sgmii_active;
+	bool global_device_reset;
 };
 
 struct e1000_hw {
--- linux-ec2-2.6.32.orig/drivers/net/igb/igb.h
+++ linux-ec2-2.6.32/drivers/net/igb/igb.h
@@ -55,12 +55,14 @@
 #define IGB_DEFAULT_ITR                    3 /* dynamic */
 #define IGB_MAX_ITR_USECS              10000
 #define IGB_MIN_ITR_USECS                 10
+#define NON_Q_VECTORS                      1
+#define MAX_Q_VECTORS                      8
 
 /* Transmit and receive queues */
-#define IGB_MAX_RX_QUEUES     (adapter->vfs_allocated_count ? \
-                               (adapter->vfs_allocated_count > 6 ? 1 : 2) : 4)
-#define IGB_MAX_TX_QUEUES     IGB_MAX_RX_QUEUES
-#define IGB_ABS_MAX_TX_QUEUES     4
+#define IGB_MAX_RX_QUEUES                  (adapter->vfs_allocated_count ? 2 : \
+                                           (hw->mac.type > e1000_82575 ? 8 : 4))
+#define IGB_ABS_MAX_TX_QUEUES              8
+#define IGB_MAX_TX_QUEUES                  IGB_MAX_RX_QUEUES
 
 #define IGB_MAX_VF_MC_ENTRIES              30
 #define IGB_MAX_VF_FUNCTIONS               8
@@ -71,9 +73,14 @@
 	u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
 	u16 num_vf_mc_hashes;
 	u16 vlans_enabled;
-	bool clear_to_send;
+	u32 flags;
+	unsigned long last_nack;
 };
 
+#define IGB_VF_FLAG_CTS            0x00000001 /* VF is clear to send data */
+#define IGB_VF_FLAG_UNI_PROMISC    0x00000002 /* VF has unicast promisc */
+#define IGB_VF_FLAG_MULTI_PROMISC  0x00000004 /* VF has multicast promisc */
+
 /* RX descriptor control thresholds.
  * PTHRESH - MAC will consider prefetch if it has fewer than this number of
  *           descriptors available in its onboard memory.
@@ -85,17 +92,19 @@
  *           descriptors until either it has this many to write back, or the
  *           ITR timer expires.
  */
-#define IGB_RX_PTHRESH                    16
+#define IGB_RX_PTHRESH                    (hw->mac.type <= e1000_82576 ? 16 : 8)
 #define IGB_RX_HTHRESH                     8
 #define IGB_RX_WTHRESH                     1
+#define IGB_TX_PTHRESH                     8
+#define IGB_TX_HTHRESH                     1
+#define IGB_TX_WTHRESH                     ((hw->mac.type == e1000_82576 && \
+                                             adapter->msix_entries) ? 0 : 16)
 
 /* this is the size past which hardware will drop packets when setting LPE=0 */
 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
 
 /* Supported Rx Buffer Sizes */
 #define IGB_RXBUFFER_128   128    /* Used for packet split */
-#define IGB_RXBUFFER_256   256    /* Used for packet split */
-#define IGB_RXBUFFER_512   512
 #define IGB_RXBUFFER_1024  1024
 #define IGB_RXBUFFER_2048  2048
 #define IGB_RXBUFFER_16384 16384
@@ -128,12 +137,13 @@
 			unsigned long time_stamp;
 			u16 length;
 			u16 next_to_watch;
+			u16 mapped_as_page;
 		};
 		/* RX */
 		struct {
 			struct page *page;
-			u64 page_dma;
-			unsigned int page_offset;
+			dma_addr_t page_dma;
+			u16 page_offset;
 		};
 	};
 };
@@ -141,36 +151,55 @@
 struct igb_tx_queue_stats {
 	u64 packets;
 	u64 bytes;
+	u64 restart_queue;
 };
 
 struct igb_rx_queue_stats {
 	u64 packets;
 	u64 bytes;
 	u64 drops;
+	u64 csum_err;
+	u64 alloc_failed;
 };
 
-struct igb_ring {
+struct igb_q_vector {
 	struct igb_adapter *adapter; /* backlink */
-	void *desc;                  /* descriptor ring memory */
-	dma_addr_t dma;              /* phys address of the ring */
-	unsigned int size;           /* length of desc. ring in bytes */
-	unsigned int count;          /* number of desc. in the ring */
-	u16 next_to_use;
-	u16 next_to_clean;
-	u16 head;
-	u16 tail;
-	struct igb_buffer *buffer_info; /* array of buffer info structs */
+	struct igb_ring *rx_ring;
+	struct igb_ring *tx_ring;
+	struct napi_struct napi;
 
 	u32 eims_value;
-	u32 itr_val;
-	u16 itr_register;
 	u16 cpu;
 
-	u16 queue_index;
-	u16 reg_idx;
+	u16 itr_val;
+	u8 set_itr;
+	u8 itr_shift;
+	void __iomem *itr_register;
+
+	char name[IFNAMSIZ + 9];
+};
+
+struct igb_ring {
+	struct igb_q_vector *q_vector; /* backlink to q_vector */
+	struct net_device *netdev;     /* back pointer to net_device */
+	struct pci_dev *pdev;          /* pci device for dma mapping */
+	dma_addr_t dma;                /* phys address of the ring */
+	void *desc;                    /* descriptor ring memory */
+	unsigned int size;             /* length of desc. ring in bytes */
+	u16 count;                     /* number of desc. in the ring */
+	u16 next_to_use;
+	u16 next_to_clean;
+	u8 queue_index;
+	u8 reg_idx;
+	void __iomem *head;
+	void __iomem *tail;
+	struct igb_buffer *buffer_info; /* array of buffer info structs */
+
 	unsigned int total_bytes;
 	unsigned int total_packets;
 
+	u32 flags;
+
 	union {
 		/* TX */
 		struct {
@@ -180,16 +209,18 @@
 		/* RX */
 		struct {
 			struct igb_rx_queue_stats rx_stats;
-			u64 rx_queue_drops;
-			struct napi_struct napi;
-			int set_itr;
-			struct igb_ring *buddy;
+			u32 rx_buffer_len;
 		};
 	};
-
-	char name[IFNAMSIZ + 5];
 };
 
+#define IGB_RING_FLAG_RX_CSUM        0x00000001 /* RX CSUM enabled */
+#define IGB_RING_FLAG_RX_SCTP_CSUM   0x00000002 /* SCTP CSUM offload enabled */
+
+#define IGB_RING_FLAG_TX_CTX_IDX     0x00000001 /* HW requires context index */
+
+#define IGB_ADVTXD_DCMD (E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS)
+
 #define E1000_RX_DESC_ADV(R, i)	    \
 	(&(((union e1000_adv_rx_desc *)((R).desc))[i]))
 #define E1000_TX_DESC_ADV(R, i)	    \
@@ -197,6 +228,15 @@
 #define E1000_TX_CTXTDESC_ADV(R, i)	    \
 	(&(((struct e1000_adv_tx_context_desc *)((R).desc))[i]))
 
+/* igb_desc_unused - calculate if we have unused descriptors */
+static inline int igb_desc_unused(struct igb_ring *ring)
+{
+	if (ring->next_to_clean > ring->next_to_use)
+		return ring->next_to_clean - ring->next_to_use - 1;
+
+	return ring->count + ring->next_to_clean - ring->next_to_use - 1;
+}
+
 /* board specific private data structure */
 
 struct igb_adapter {
@@ -205,18 +245,14 @@
 	struct vlan_group *vlgrp;
 	u16 mng_vlan_id;
 	u32 bd_number;
-	u32 rx_buffer_len;
 	u32 wol;
 	u32 en_mng_pt;
 	u16 link_speed;
 	u16 link_duplex;
-	unsigned int total_tx_bytes;
-	unsigned int total_tx_packets;
-	unsigned int total_rx_bytes;
-	unsigned int total_rx_packets;
+
 	/* Interrupt Throttle Rate */
-	u32 itr;
-	u32 itr_setting;
+	u32 rx_itr_setting;
+	u32 tx_itr_setting;
 	u16 tx_itr;
 	u16 rx_itr;
 
@@ -229,13 +265,7 @@
 
 	/* TX */
 	struct igb_ring *tx_ring;      /* One per active queue */
-	unsigned int restart_queue;
 	unsigned long tx_queue_len;
-	u32 txd_cmd;
-	u32 gotc;
-	u64 gotc_old;
-	u64 tpt_old;
-	u64 colc_old;
 	u32 tx_timeout_count;
 
 	/* RX */
@@ -243,20 +273,12 @@
 	int num_tx_queues;
 	int num_rx_queues;
 
-	u64 hw_csum_err;
-	u64 hw_csum_good;
-	u32 alloc_rx_buff_failed;
-	u32 gorc;
-	u64 gorc_old;
-	u16 rx_ps_hdr_size;
 	u32 max_frame_size;
 	u32 min_frame_size;
 
 	/* OS defined structs */
 	struct net_device *netdev;
-	struct napi_struct napi;
 	struct pci_dev *pdev;
-	struct net_device_stats net_stats;
 	struct cyclecounter cycles;
 	struct timecounter clock;
 	struct timecompare compare;
@@ -273,6 +295,9 @@
 	struct igb_ring test_rx_ring;
 
 	int msg_enable;
+
+	unsigned int num_q_vectors;
+	struct igb_q_vector *q_vector[MAX_Q_VECTORS];
 	struct msix_entry *msix_entries;
 	u32 eims_enable_mask;
 	u32 eims_other;
@@ -283,18 +308,20 @@
 	u32 eeprom_wol;
 
 	struct igb_ring *multi_tx_table[IGB_ABS_MAX_TX_QUEUES];
-	unsigned int tx_ring_count;
-	unsigned int rx_ring_count;
+	u16 tx_ring_count;
+	u16 rx_ring_count;
 	unsigned int vfs_allocated_count;
 	struct vf_data_storage *vf_data;
+	u32 rss_queues;
 };
 
 #define IGB_FLAG_HAS_MSI           (1 << 0)
 #define IGB_FLAG_DCA_ENABLED       (1 << 1)
 #define IGB_FLAG_QUAD_PORT_A       (1 << 2)
-#define IGB_FLAG_NEED_CTX_IDX      (1 << 3)
-#define IGB_FLAG_RX_CSUM_DISABLED  (1 << 4)
+#define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
 
+#define IGB_82576_TSYNC_SHIFT 19
+#define IGB_82580_TSYNC_SHIFT 24
 enum e1000_state_t {
 	__IGB_TESTING,
 	__IGB_RESETTING,
@@ -314,10 +341,18 @@
 extern void igb_reinit_locked(struct igb_adapter *);
 extern void igb_reset(struct igb_adapter *);
 extern int igb_set_spd_dplx(struct igb_adapter *, u16);
-extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *);
-extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *);
+extern int igb_setup_tx_resources(struct igb_ring *);
+extern int igb_setup_rx_resources(struct igb_ring *);
 extern void igb_free_tx_resources(struct igb_ring *);
 extern void igb_free_rx_resources(struct igb_ring *);
+extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
+extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
+extern void igb_setup_tctl(struct igb_adapter *);
+extern void igb_setup_rctl(struct igb_adapter *);
+extern netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *, struct igb_ring *);
+extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
+					   struct igb_buffer *);
+extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
 extern void igb_update_stats(struct igb_adapter *);
 extern void igb_set_ethtool_ops(struct net_device *);
 
--- linux-ec2-2.6.32.orig/drivers/net/qlge/qlge_mpi.c
+++ linux-ec2-2.6.32/drivers/net/qlge/qlge_mpi.c
@@ -446,6 +446,9 @@
 		ql_aen_lost(qdev, mbcp);
 		break;
 
+	case AEN_DCBX_CHG:
+		/* Need to support AEN 8110 */
+		break;
 	default:
 		QPRINTK(qdev, DRV, ERR,
 			"Unsupported AE %.08x.\n", mbcp->mbox_out[0]);
--- linux-ec2-2.6.32.orig/drivers/net/qlge/qlge_main.c
+++ linux-ec2-2.6.32/drivers/net/qlge/qlge_main.c
@@ -3310,10 +3310,8 @@
 
 	/* Initialize the port and set the max framesize. */
 	status = qdev->nic_ops->port_initialize(qdev);
-       if (status) {
-              QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n");
-              return status;
-       }
+	if (status)
+		QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n");
 
 	/* Set up the MAC address and frame routing filter. */
 	status = ql_cam_route_initialize(qdev);
@@ -3714,9 +3712,6 @@
 	struct sockaddr *addr = p;
 	int status;
 
-	if (netif_running(ndev))
-		return -EBUSY;
-
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
@@ -3868,8 +3863,7 @@
 				    struct net_device *ndev, int cards_found)
 {
 	struct ql_adapter *qdev = netdev_priv(ndev);
-	int pos, err = 0;
-	u16 val16;
+	int err = 0;
 
 	memset((void *)qdev, 0, sizeof(*qdev));
 	err = pci_enable_device(pdev);
@@ -3881,18 +3875,12 @@
 	qdev->ndev = ndev;
 	qdev->pdev = pdev;
 	pci_set_drvdata(pdev, ndev);
-	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-	if (pos <= 0) {
-		dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, "
-			"aborting.\n");
-		return pos;
-	} else {
-		pci_read_config_word(pdev, pos + PCI_EXP_DEVCTL, &val16);
-		val16 &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
-		val16 |= (PCI_EXP_DEVCTL_CERE |
-			  PCI_EXP_DEVCTL_NFERE |
-			  PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
-		pci_write_config_word(pdev, pos + PCI_EXP_DEVCTL, val16);
+
+	/* Set PCIe read request size */
+	err = pcie_set_readrq(pdev, 4096);
+	if (err) {
+		dev_err(&pdev->dev, "Set readrq failed.\n");
+		goto err_out;
 	}
 
 	err = pci_request_regions(pdev, DRV_NAME);
--- linux-ec2-2.6.32.orig/drivers/net/arcnet/com20020-pci.c
+++ linux-ec2-2.6.32/drivers/net/arcnet/com20020-pci.c
@@ -165,8 +165,8 @@
 	{ 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
-	{ 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
-	{ 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x9030, 0x10B5,     0x2978,     0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x9050, 0x10B5,     0x2273,     0, 0, ARC_CAN_10MBIT },
 	{ 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{0,}
--- linux-ec2-2.6.32.orig/drivers/net/usb/cdc-phonet.c
+++ linux-ec2-2.6.32/drivers/net/usb/cdc-phonet.c
@@ -325,13 +325,13 @@
 {
 	static const char ifname[] = "usbpn%d";
 	const struct usb_cdc_union_desc *union_header = NULL;
-	const struct usb_cdc_header_desc *phonet_header = NULL;
 	const struct usb_host_interface *data_desc;
 	struct usb_interface *data_intf;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	struct net_device *dev;
 	struct usbpn_dev *pnd;
 	u8 *data;
+	int phonet = 0;
 	int len, err;
 
 	data = intf->altsetting->extra;
@@ -352,10 +352,7 @@
 					(struct usb_cdc_union_desc *)data;
 				break;
 			case 0xAB:
-				if (phonet_header || dlen < 5)
-					break;
-				phonet_header =
-					(struct usb_cdc_header_desc *)data;
+				phonet = 1;
 				break;
 			}
 		}
@@ -363,7 +360,7 @@
 		len -= dlen;
 	}
 
-	if (!union_header || !phonet_header)
+	if (!union_header || !phonet)
 		return -EINVAL;
 
 	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
--- linux-ec2-2.6.32.orig/drivers/net/usb/dm9601.c
+++ linux-ec2-2.6.32/drivers/net/usb/dm9601.c
@@ -238,7 +238,7 @@
 		goto out;
 
 	dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
-	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14);
+	dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);
 
 	for (i = 0; i < DM_TIMEOUT; i++) {
 		u8 tmp;
--- linux-ec2-2.6.32.orig/drivers/net/usb/rtl8150.c
+++ linux-ec2-2.6.32/drivers/net/usb/rtl8150.c
@@ -324,7 +324,7 @@
 		dbg("%02X:", netdev->dev_addr[i]);
 	dbg("%02X\n", netdev->dev_addr[i]);
 	/* Set the IDR registers. */
-	set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr);
+	set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);
 #ifdef EEPROM_WRITE
 	{
 	u8 cr;
--- linux-ec2-2.6.32.orig/drivers/net/usb/hso.c
+++ linux-ec2-2.6.32/drivers/net/usb/hso.c
@@ -1634,6 +1634,8 @@
 	struct uart_icount cnow;
 	struct hso_tiocmget  *tiocmget = serial->tiocmget;
 
+	memset(&icount, 0, sizeof(struct serial_icounter_struct));
+
 	if (!tiocmget)
 		 return -ENOENT;
 	spin_lock_irq(&serial->serial_lock);
--- linux-ec2-2.6.32.orig/drivers/net/usb/asix.c
+++ linux-ec2-2.6.32/drivers/net/usb/asix.c
@@ -54,6 +54,7 @@
 #define AX_CMD_WRITE_IPG0		0x12
 #define AX_CMD_WRITE_IPG1		0x13
 #define AX_CMD_READ_NODE_ID		0x13
+#define AX_CMD_WRITE_NODE_ID		0x14
 #define AX_CMD_WRITE_IPG2		0x14
 #define AX_CMD_WRITE_MULTI_FILTER	0x16
 #define AX88172_CMD_READ_NODE_ID	0x17
@@ -165,6 +166,7 @@
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
 	u8 multi_filter[AX_MCAST_FILTER_SIZE];
+	u8 mac_addr[ETH_ALEN];
 	u8 phymode;
 	u8 ledmode;
 	u8 eeprom_len;
@@ -728,6 +730,30 @@
 	return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
 }
 
+static int asix_set_mac_address(struct net_device *net, void *p)
+{
+	struct usbnet *dev = netdev_priv(net);
+	struct asix_data *data = (struct asix_data *)&dev->data;
+	struct sockaddr *addr = p;
+
+	if (netif_running(net))
+		return -EBUSY;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
+
+	/* We use the 20 byte dev->data
+	 * for our 6 byte mac buffer
+	 * to avoid allocating memory that
+	 * is tricky to free later */
+	memcpy(data->mac_addr, addr->sa_data, ETH_ALEN);
+	asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
+							data->mac_addr);
+
+	return 0;
+}
+
 /* We need to override some ethtool_ops so we require our
    own structure so we don't interfere with other usbnet
    devices that may be connected at the same time. */
@@ -915,7 +941,7 @@
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
 	.ndo_change_mtu		= usbnet_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address 	= asix_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= asix_ioctl,
 	.ndo_set_multicast_list = asix_set_multicast,
@@ -1208,7 +1234,7 @@
 	.ndo_stop		= usbnet_stop,
 	.ndo_start_xmit		= usbnet_start_xmit,
 	.ndo_tx_timeout		= usbnet_tx_timeout,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address 	= asix_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list = asix_set_multicast,
 	.ndo_do_ioctl 		= asix_ioctl,
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mtd.c
+++ linux-ec2-2.6.32/drivers/net/sfc/mtd.c
@@ -1,36 +1,79 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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, incorporated herein by reference.
  */
 
+#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/delay.h>
+#include <linux/rtnetlink.h>
 
 #define EFX_DRIVER_NAME "sfc_mtd"
 #include "net_driver.h"
 #include "spi.h"
 #include "efx.h"
+#include "nic.h"
+#include "mcdi.h"
+#include "mcdi_pcol.h"
 
 #define EFX_SPI_VERIFY_BUF_LEN 16
 
-struct efx_mtd {
-	const struct efx_spi_device *spi;
+struct efx_mtd_partition {
 	struct mtd_info mtd;
+	union {
+		struct {
+			bool updating;
+			u8 nvram_type;
+			u16 fw_subtype;
+		} mcdi;
+		size_t offset;
+	};
+	const char *type_name;
 	char name[IFNAMSIZ + 20];
 };
 
+struct efx_mtd_ops {
+	int (*read)(struct mtd_info *mtd, loff_t start, size_t len,
+		    size_t *retlen, u8 *buffer);
+	int (*erase)(struct mtd_info *mtd, loff_t start, size_t len);
+	int (*write)(struct mtd_info *mtd, loff_t start, size_t len,
+		     size_t *retlen, const u8 *buffer);
+	int (*sync)(struct mtd_info *mtd);
+};
+
+struct efx_mtd {
+	struct list_head node;
+	struct efx_nic *efx;
+	const struct efx_spi_device *spi;
+	const char *name;
+	const struct efx_mtd_ops *ops;
+	size_t n_parts;
+	struct efx_mtd_partition part[0];
+};
+
+#define efx_for_each_partition(part, efx_mtd)			\
+	for ((part) = &(efx_mtd)->part[0];			\
+	     (part) != &(efx_mtd)->part[(efx_mtd)->n_parts];	\
+	     (part)++)
+
+#define to_efx_mtd_partition(mtd)				\
+	container_of(mtd, struct efx_mtd_partition, mtd)
+
+static int falcon_mtd_probe(struct efx_nic *efx);
+static int siena_mtd_probe(struct efx_nic *efx);
+
 /* SPI utilities */
 
 static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
 {
 	const struct efx_spi_device *spi = efx_mtd->spi;
-	struct efx_nic *efx = spi->efx;
+	struct efx_nic *efx = efx_mtd->efx;
 	u8 status;
 	int rc, i;
 
@@ -39,7 +82,7 @@
 		__set_current_state(uninterruptible ?
 				    TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 10);
-		rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
+		rc = falcon_spi_cmd(efx, spi, SPI_RDSR, -1, NULL,
 				    &status, sizeof(status));
 		if (rc)
 			return rc;
@@ -52,32 +95,35 @@
 	return -ETIMEDOUT;
 }
 
-static int efx_spi_unlock(const struct efx_spi_device *spi)
+static int
+efx_spi_unlock(struct efx_nic *efx, const struct efx_spi_device *spi)
 {
 	const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
 				SPI_STATUS_BP0);
 	u8 status;
 	int rc;
 
-	rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status));
+	rc = falcon_spi_cmd(efx, spi, SPI_RDSR, -1, NULL,
+			    &status, sizeof(status));
 	if (rc)
 		return rc;
 
 	if (!(status & unlock_mask))
 		return 0; /* already unlocked */
 
-	rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+	rc = falcon_spi_cmd(efx, spi, SPI_WREN, -1, NULL, NULL, 0);
 	if (rc)
 		return rc;
-	rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
+	rc = falcon_spi_cmd(efx, spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
 	if (rc)
 		return rc;
 
 	status &= ~unlock_mask;
-	rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status));
+	rc = falcon_spi_cmd(efx, spi, SPI_WRSR, -1, &status,
+			    NULL, sizeof(status));
 	if (rc)
 		return rc;
-	rc = falcon_spi_wait_write(spi);
+	rc = falcon_spi_wait_write(efx, spi);
 	if (rc)
 		return rc;
 
@@ -87,6 +133,7 @@
 static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
 {
 	const struct efx_spi_device *spi = efx_mtd->spi;
+	struct efx_nic *efx = efx_mtd->efx;
 	unsigned pos, block_len;
 	u8 empty[EFX_SPI_VERIFY_BUF_LEN];
 	u8 buffer[EFX_SPI_VERIFY_BUF_LEN];
@@ -98,13 +145,14 @@
 	if (spi->erase_command == 0)
 		return -EOPNOTSUPP;
 
-	rc = efx_spi_unlock(spi);
+	rc = efx_spi_unlock(efx, spi);
 	if (rc)
 		return rc;
-	rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+	rc = falcon_spi_cmd(efx, spi, SPI_WREN, -1, NULL, NULL, 0);
 	if (rc)
 		return rc;
-	rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0);
+	rc = falcon_spi_cmd(efx, spi, spi->erase_command, start, NULL,
+			    NULL, 0);
 	if (rc)
 		return rc;
 	rc = efx_spi_slow_wait(efx_mtd, false);
@@ -113,7 +161,8 @@
 	memset(empty, 0xff, sizeof(empty));
 	for (pos = 0; pos < len; pos += block_len) {
 		block_len = min(len - pos, sizeof(buffer));
-		rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer);
+		rc = falcon_spi_read(efx, spi, start + pos, block_len,
+				     NULL, buffer);
 		if (rc)
 			return rc;
 		if (memcmp(empty, buffer, block_len))
@@ -130,140 +179,473 @@
 
 /* MTD interface */
 
-static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
-			size_t *retlen, u8 *buffer)
+static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+	struct efx_mtd *efx_mtd = mtd->priv;
+	int rc;
+
+	rc = efx_mtd->ops->erase(mtd, erase->addr, erase->len);
+	if (rc == 0) {
+		erase->state = MTD_ERASE_DONE;
+	} else {
+		erase->state = MTD_ERASE_FAILED;
+		erase->fail_addr = 0xffffffff;
+	}
+	mtd_erase_callback(erase);
+	return rc;
+}
+
+static void efx_mtd_sync(struct mtd_info *mtd)
 {
 	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->efx;
+	int rc;
+
+	rc = efx_mtd->ops->sync(mtd);
+	if (rc)
+		EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
+}
+
+static void efx_mtd_remove_partition(struct efx_mtd_partition *part)
+{
+	int rc;
+
+	for (;;) {
+		rc = del_mtd_device(&part->mtd);
+		if (rc != -EBUSY)
+			break;
+		ssleep(1);
+	}
+	WARN_ON(rc);
+}
+
+static void efx_mtd_remove_device(struct efx_mtd *efx_mtd)
+{
+	struct efx_mtd_partition *part;
+
+	efx_for_each_partition(part, efx_mtd)
+		efx_mtd_remove_partition(part);
+	list_del(&efx_mtd->node);
+	kfree(efx_mtd);
+}
+
+static void efx_mtd_rename_device(struct efx_mtd *efx_mtd)
+{
+	struct efx_mtd_partition *part;
+
+	efx_for_each_partition(part, efx_mtd)
+		if (efx_nic_rev(efx_mtd->efx) >= EFX_REV_SIENA_A0)
+			snprintf(part->name, sizeof(part->name),
+				 "%s %s:%02x", efx_mtd->efx->name,
+				 part->type_name, part->mcdi.fw_subtype);
+		else
+			snprintf(part->name, sizeof(part->name),
+				 "%s %s", efx_mtd->efx->name,
+				 part->type_name);
+}
+
+static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd)
+{
+	struct efx_mtd_partition *part;
+
+	efx_mtd->efx = efx;
+
+	efx_mtd_rename_device(efx_mtd);
+
+	efx_for_each_partition(part, efx_mtd) {
+		part->mtd.writesize = 1;
+
+		part->mtd.owner = THIS_MODULE;
+		part->mtd.priv = efx_mtd;
+		part->mtd.name = part->name;
+		part->mtd.erase = efx_mtd_erase;
+		part->mtd.read = efx_mtd->ops->read;
+		part->mtd.write = efx_mtd->ops->write;
+		part->mtd.sync = efx_mtd_sync;
+
+		if (add_mtd_device(&part->mtd))
+			goto fail;
+	}
+
+	list_add(&efx_mtd->node, &efx->mtd_list);
+	return 0;
+
+fail:
+	while (part != &efx_mtd->part[0]) {
+		--part;
+		efx_mtd_remove_partition(part);
+	}
+	/* add_mtd_device() returns 1 if the MTD table is full */
+	return -ENOMEM;
+}
+
+void efx_mtd_remove(struct efx_nic *efx)
+{
+	struct efx_mtd *efx_mtd, *next;
+
+	WARN_ON(efx_dev_registered(efx));
+
+	list_for_each_entry_safe(efx_mtd, next, &efx->mtd_list, node)
+		efx_mtd_remove_device(efx_mtd);
+}
+
+void efx_mtd_rename(struct efx_nic *efx)
+{
+	struct efx_mtd *efx_mtd;
+
+	ASSERT_RTNL();
+
+	list_for_each_entry(efx_mtd, &efx->mtd_list, node)
+		efx_mtd_rename_device(efx_mtd);
+}
+
+int efx_mtd_probe(struct efx_nic *efx)
+{
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
+		return siena_mtd_probe(efx);
+	else
+		return falcon_mtd_probe(efx);
+}
+
+/* Implementation of MTD operations for Falcon */
+
+static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
+			   size_t len, size_t *retlen, u8 *buffer)
+{
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
+	struct efx_mtd *efx_mtd = mtd->priv;
 	const struct efx_spi_device *spi = efx_mtd->spi;
-	struct efx_nic *efx = spi->efx;
+	struct efx_nic *efx = efx_mtd->efx;
 	int rc;
 
 	rc = mutex_lock_interruptible(&efx->spi_lock);
 	if (rc)
 		return rc;
-	rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start,
-			     len, retlen, buffer);
+	rc = falcon_spi_read(efx, spi, part->offset + start, len,
+			     retlen, buffer);
 	mutex_unlock(&efx->spi_lock);
 	return rc;
 }
 
-static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
 {
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
 	struct efx_mtd *efx_mtd = mtd->priv;
-	struct efx_nic *efx = efx_mtd->spi->efx;
+	struct efx_nic *efx = efx_mtd->efx;
 	int rc;
 
 	rc = mutex_lock_interruptible(&efx->spi_lock);
 	if (rc)
 		return rc;
-	rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr,
-			   erase->len);
+	rc = efx_spi_erase(efx_mtd, part->offset + start, len);
 	mutex_unlock(&efx->spi_lock);
-
-	if (rc == 0) {
-		erase->state = MTD_ERASE_DONE;
-	} else {
-		erase->state = MTD_ERASE_FAILED;
-		erase->fail_addr = 0xffffffff;
-	}
-	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)
+static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
+			    size_t len, size_t *retlen, const u8 *buffer)
 {
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
 	struct efx_mtd *efx_mtd = mtd->priv;
 	const struct efx_spi_device *spi = efx_mtd->spi;
-	struct efx_nic *efx = spi->efx;
+	struct efx_nic *efx = efx_mtd->efx;
 	int rc;
 
 	rc = mutex_lock_interruptible(&efx->spi_lock);
 	if (rc)
 		return rc;
-	rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start,
-			      len, retlen, buffer);
+	rc = falcon_spi_write(efx, spi, part->offset + start, len,
+			      retlen, buffer);
 	mutex_unlock(&efx->spi_lock);
 	return rc;
 }
 
-static void efx_mtd_sync(struct mtd_info *mtd)
+static int falcon_mtd_sync(struct mtd_info *mtd)
 {
 	struct efx_mtd *efx_mtd = mtd->priv;
-	struct efx_nic *efx = efx_mtd->spi->efx;
+	struct efx_nic *efx = efx_mtd->efx;
 	int rc;
 
 	mutex_lock(&efx->spi_lock);
 	rc = efx_spi_slow_wait(efx_mtd, true);
 	mutex_unlock(&efx->spi_lock);
+	return rc;
+}
+
+static struct efx_mtd_ops falcon_mtd_ops = {
+	.read	= falcon_mtd_read,
+	.erase	= falcon_mtd_erase,
+	.write	= falcon_mtd_write,
+	.sync	= falcon_mtd_sync,
+};
+
+static int falcon_mtd_probe(struct efx_nic *efx)
+{
+	struct efx_spi_device *spi = efx->spi_flash;
+	struct efx_mtd *efx_mtd;
+	int rc;
 
+	ASSERT_RTNL();
+
+	if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
+		return -ENODEV;
+
+	efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
+			  GFP_KERNEL);
+	if (!efx_mtd)
+		return -ENOMEM;
+
+	efx_mtd->spi = spi;
+	efx_mtd->name = "flash";
+	efx_mtd->ops = &falcon_mtd_ops;
+
+	efx_mtd->n_parts = 1;
+	efx_mtd->part[0].mtd.type = MTD_NORFLASH;
+	efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH;
+	efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
+	efx_mtd->part[0].mtd.erasesize = spi->erase_size;
+	efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START;
+	efx_mtd->part[0].type_name = "sfc_flash_bootrom";
+
+	rc = efx_mtd_probe_device(efx, efx_mtd);
 	if (rc)
-		EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
-	return;
+		kfree(efx_mtd);
+	return rc;
 }
 
-void efx_mtd_remove(struct efx_nic *efx)
+/* Implementation of MTD operations for Siena */
+
+static int siena_mtd_read(struct mtd_info *mtd, loff_t start,
+			  size_t len, size_t *retlen, u8 *buffer)
 {
-	if (efx->spi_flash && efx->spi_flash->mtd) {
-		struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
-		int rc;
-
-		for (;;) {
-			rc = del_mtd_device(&efx_mtd->mtd);
-			if (rc != -EBUSY)
-				break;
-			ssleep(1);
-		}
-		WARN_ON(rc);
-		kfree(efx_mtd);
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->efx;
+	loff_t offset = start;
+	loff_t end = min_t(loff_t, start + len, mtd->size);
+	size_t chunk;
+	int rc = 0;
+
+	while (offset < end) {
+		chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
+		rc = efx_mcdi_nvram_read(efx, part->mcdi.nvram_type, offset,
+					 buffer, chunk);
+		if (rc)
+			goto out;
+		offset += chunk;
+		buffer += chunk;
 	}
+out:
+	*retlen = offset - start;
+	return rc;
 }
 
-void efx_mtd_rename(struct efx_nic *efx)
+static int siena_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
 {
-	if (efx->spi_flash && efx->spi_flash->mtd) {
-		struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
-		snprintf(efx_mtd->name, sizeof(efx_mtd->name),
-			 "%s sfc_flash_bootrom", efx->name);
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->efx;
+	loff_t offset = start & ~((loff_t)(mtd->erasesize - 1));
+	loff_t end = min_t(loff_t, start + len, mtd->size);
+	size_t chunk = part->mtd.erasesize;
+	int rc = 0;
+
+	if (!part->mcdi.updating) {
+		rc = efx_mcdi_nvram_update_start(efx, part->mcdi.nvram_type);
+		if (rc)
+			goto out;
+		part->mcdi.updating = 1;
 	}
+
+	/* The MCDI interface can in fact do multiple erase blocks at once;
+	 * but erasing may be slow, so we make multiple calls here to avoid
+	 * tripping the MCDI RPC timeout. */
+	while (offset < end) {
+		rc = efx_mcdi_nvram_erase(efx, part->mcdi.nvram_type, offset,
+					  chunk);
+		if (rc)
+			goto out;
+		offset += chunk;
+	}
+out:
+	return rc;
 }
 
-int efx_mtd_probe(struct efx_nic *efx)
+static int siena_mtd_write(struct mtd_info *mtd, loff_t start,
+			   size_t len, size_t *retlen, const u8 *buffer)
 {
-	struct efx_spi_device *spi = efx->spi_flash;
-	struct efx_mtd *efx_mtd;
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->efx;
+	loff_t offset = start;
+	loff_t end = min_t(loff_t, start + len, mtd->size);
+	size_t chunk;
+	int rc = 0;
 
-	if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
+	if (!part->mcdi.updating) {
+		rc = efx_mcdi_nvram_update_start(efx, part->mcdi.nvram_type);
+		if (rc)
+			goto out;
+		part->mcdi.updating = 1;
+	}
+
+	while (offset < end) {
+		chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
+		rc = efx_mcdi_nvram_write(efx, part->mcdi.nvram_type, offset,
+					  buffer, chunk);
+		if (rc)
+			goto out;
+		offset += chunk;
+		buffer += chunk;
+	}
+out:
+	*retlen = offset - start;
+	return rc;
+}
+
+static int siena_mtd_sync(struct mtd_info *mtd)
+{
+	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
+	struct efx_mtd *efx_mtd = mtd->priv;
+	struct efx_nic *efx = efx_mtd->efx;
+	int rc = 0;
+
+	if (part->mcdi.updating) {
+		part->mcdi.updating = 0;
+		rc = efx_mcdi_nvram_update_finish(efx, part->mcdi.nvram_type);
+	}
+
+	return rc;
+}
+
+static struct efx_mtd_ops siena_mtd_ops = {
+	.read	= siena_mtd_read,
+	.erase	= siena_mtd_erase,
+	.write	= siena_mtd_write,
+	.sync	= siena_mtd_sync,
+};
+
+struct siena_nvram_type_info {
+	int port;
+	const char *name;
+};
+
+static struct siena_nvram_type_info siena_nvram_types[] = {
+	[MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO]	= { 0, "sfc_dummy_phy" },
+	[MC_CMD_NVRAM_TYPE_MC_FW]		= { 0, "sfc_mcfw" },
+	[MC_CMD_NVRAM_TYPE_MC_FW_BACKUP]	= { 0, "sfc_mcfw_backup" },
+	[MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0]	= { 0, "sfc_static_cfg" },
+	[MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1]	= { 1, "sfc_static_cfg" },
+	[MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0]	= { 0, "sfc_dynamic_cfg" },
+	[MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1]	= { 1, "sfc_dynamic_cfg" },
+	[MC_CMD_NVRAM_TYPE_EXP_ROM]		= { 0, "sfc_exp_rom" },
+	[MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0]	= { 0, "sfc_exp_rom_cfg" },
+	[MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1]	= { 1, "sfc_exp_rom_cfg" },
+	[MC_CMD_NVRAM_TYPE_PHY_PORT0]		= { 0, "sfc_phy_fw" },
+	[MC_CMD_NVRAM_TYPE_PHY_PORT1]		= { 1, "sfc_phy_fw" },
+};
+
+static int siena_mtd_probe_partition(struct efx_nic *efx,
+				     struct efx_mtd *efx_mtd,
+				     unsigned int part_id,
+				     unsigned int type)
+{
+	struct efx_mtd_partition *part = &efx_mtd->part[part_id];
+	struct siena_nvram_type_info *info;
+	size_t size, erase_size;
+	bool protected;
+	int rc;
+
+	if (type >= ARRAY_SIZE(siena_nvram_types))
+		return -ENODEV;
+
+	info = &siena_nvram_types[type];
+
+	if (info->port != efx_port_num(efx))
 		return -ENODEV;
 
-	efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
+	rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected);
+	if (rc)
+		return rc;
+	if (protected)
+		return -ENODEV; /* hide it */
+
+	part->mcdi.nvram_type = type;
+	part->type_name = info->name;
+
+	part->mtd.type = MTD_NORFLASH;
+	part->mtd.flags = MTD_CAP_NORFLASH;
+	part->mtd.size = size;
+	part->mtd.erasesize = erase_size;
+
+	return 0;
+}
+
+static int siena_mtd_get_fw_subtypes(struct efx_nic *efx,
+				     struct efx_mtd *efx_mtd)
+{
+	struct efx_mtd_partition *part;
+	uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN /
+				 sizeof(uint16_t)];
+	int rc;
+
+	rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list);
+	if (rc)
+		return rc;
+
+	efx_for_each_partition(part, efx_mtd)
+		part->mcdi.fw_subtype = fw_subtype_list[part->mcdi.nvram_type];
+
+	return 0;
+}
+
+static int siena_mtd_probe(struct efx_nic *efx)
+{
+	struct efx_mtd *efx_mtd;
+	int rc = -ENODEV;
+	u32 nvram_types;
+	unsigned int type;
+
+	ASSERT_RTNL();
+
+	rc = efx_mcdi_nvram_types(efx, &nvram_types);
+	if (rc)
+		return rc;
+
+	efx_mtd = kzalloc(sizeof(*efx_mtd) +
+			  hweight32(nvram_types) * sizeof(efx_mtd->part[0]),
+			  GFP_KERNEL);
 	if (!efx_mtd)
 		return -ENOMEM;
 
-	efx_mtd->spi = spi;
-	spi->mtd = efx_mtd;
+	efx_mtd->name = "Siena NVRAM manager";
 
-	efx_mtd->mtd.type = MTD_NORFLASH;
-	efx_mtd->mtd.flags = MTD_CAP_NORFLASH;
-	efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
-	efx_mtd->mtd.erasesize = spi->erase_size;
-	efx_mtd->mtd.writesize = 1;
-	efx_mtd_rename(efx);
-
-	efx_mtd->mtd.owner = THIS_MODULE;
-	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;
+	efx_mtd->ops = &siena_mtd_ops;
 
-	if (add_mtd_device(&efx_mtd->mtd)) {
-		kfree(efx_mtd);
-		spi->mtd = NULL;
-		/* add_mtd_device() returns 1 if the MTD table is full */
-		return -ENOMEM;
+	type = 0;
+	efx_mtd->n_parts = 0;
+
+	while (nvram_types != 0) {
+		if (nvram_types & 1) {
+			rc = siena_mtd_probe_partition(efx, efx_mtd,
+						       efx_mtd->n_parts, type);
+			if (rc == 0)
+				efx_mtd->n_parts++;
+			else if (rc != -ENODEV)
+				goto fail;
+		}
+		type++;
+		nvram_types >>= 1;
 	}
 
-	return 0;
+	rc = siena_mtd_get_fw_subtypes(efx, efx_mtd);
+	if (rc)
+		goto fail;
+
+	rc = efx_mtd_probe_device(efx, efx_mtd);
+fail:
+	if (rc)
+		kfree(efx_mtd);
+	return rc;
 }
+
--- linux-ec2-2.6.32.orig/drivers/net/sfc/falcon_xmac.c
+++ linux-ec2-2.6.32/drivers/net/sfc/falcon_xmac.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -11,13 +11,12 @@
 #include <linux/delay.h>
 #include "net_driver.h"
 #include "efx.h"
-#include "falcon.h"
-#include "falcon_hwdefs.h"
-#include "falcon_io.h"
+#include "nic.h"
+#include "regs.h"
+#include "io.h"
 #include "mac.h"
 #include "mdio_10g.h"
 #include "phy.h"
-#include "boards.h"
 #include "workarounds.h"
 
 /**************************************************************************
@@ -36,43 +35,47 @@
 	if (efx->phy_type == PHY_TYPE_NONE)
 		return;
 
-	falcon_read(efx, &sdctl, XX_SD_CTL_REG);
-	EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT);
-	EFX_SET_OWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT);
-	falcon_write(efx, &sdctl, XX_SD_CTL_REG);
+	efx_reado(efx, &sdctl, FR_AB_XX_SD_CTL);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVD, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVC, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVB, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_HIDRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
+	EFX_SET_OWORD_FIELD(sdctl, FRF_AB_XX_LODRVA, FFE_AB_XX_SD_CTL_DRV_DEF);
+	efx_writeo(efx, &sdctl, FR_AB_XX_SD_CTL);
 
 	EFX_POPULATE_OWORD_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);
-	falcon_write(efx, &txdrv, XX_TXDRV_CTL_REG);
+			     FRF_AB_XX_DEQD, FFE_AB_XX_TXDRV_DEQ_DEF,
+			     FRF_AB_XX_DEQC, FFE_AB_XX_TXDRV_DEQ_DEF,
+			     FRF_AB_XX_DEQB, FFE_AB_XX_TXDRV_DEQ_DEF,
+			     FRF_AB_XX_DEQA, FFE_AB_XX_TXDRV_DEQ_DEF,
+			     FRF_AB_XX_DTXD, FFE_AB_XX_TXDRV_DTX_DEF,
+			     FRF_AB_XX_DTXC, FFE_AB_XX_TXDRV_DTX_DEF,
+			     FRF_AB_XX_DTXB, FFE_AB_XX_TXDRV_DTX_DEF,
+			     FRF_AB_XX_DTXA, FFE_AB_XX_TXDRV_DTX_DEF);
+	efx_writeo(efx, &txdrv, FR_AB_XX_TXDRV_CTL);
 }
 
 int falcon_reset_xaui(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t reg;
 	int count;
 
+	/* Don't fetch MAC statistics over an XMAC reset */
+	WARN_ON(nic_data->stats_disable_count == 0);
+
 	/* Start reset sequence */
-	EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
-	falcon_write(efx, &reg, XX_PWR_RST_REG);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
+	efx_writeo(efx, &reg, FR_AB_XX_PWR_RST);
 
 	/* Wait up to 10 ms for completion, then reinitialise */
 	for (count = 0; count < 1000; count++) {
-		falcon_read(efx, &reg, XX_PWR_RST_REG);
-		if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0 &&
-		    EFX_OWORD_FIELD(reg, XX_SD_RST_ACT) == 0) {
+		efx_reado(efx, &reg, FR_AB_XX_PWR_RST);
+		if (EFX_OWORD_FIELD(reg, FRF_AB_XX_RST_XX_EN) == 0 &&
+		    EFX_OWORD_FIELD(reg, FRF_AB_XX_SD_RST_ACT) == 0) {
 			falcon_setup_xaui(efx);
 			return 0;
 		}
@@ -86,117 +89,118 @@
 {
 	efx_oword_t reg;
 
-	if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
+	if ((efx_nic_rev(efx) != EFX_REV_FALCON_B0) || LOOPBACK_INTERNAL(efx))
 		return;
 
 	/* We expect xgmii faults if the wireside link is up */
-	if (!EFX_WORKAROUND_5147(efx) || !efx->link_up)
+	if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up)
 		return;
 
 	/* We can only use this interrupt to signal the negative edge of
 	 * xaui_align [we have to poll the positive edge]. */
-	if (!efx->mac_up)
+	if (efx->xmac_poll_required)
 		return;
 
 	/* Flush the ISR */
 	if (enable)
-		falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
+		efx_reado(efx, &reg, FR_AB_XM_MGT_INT_MSK);
 
 	EFX_POPULATE_OWORD_2(reg,
-			     XM_MSK_RMTFLT, !enable,
-			     XM_MSK_LCLFLT, !enable);
-	falcon_write(efx, &reg, XM_MGT_INT_MSK_REG_B0);
+			     FRF_AB_XM_MSK_RMTFLT, !enable,
+			     FRF_AB_XM_MSK_LCLFLT, !enable);
+	efx_writeo(efx, &reg, FR_AB_XM_MGT_INT_MASK);
 }
 
-/* Get status of XAUI link */
-bool falcon_xaui_link_ok(struct efx_nic *efx)
+static bool falcon_xgxs_link_ok(struct efx_nic *efx)
 {
 	efx_oword_t reg;
 	bool align_done, link_ok = false;
 	int sync_status;
 
-	if (LOOPBACK_INTERNAL(efx))
-		return true;
-
 	/* Read link status */
-	falcon_read(efx, &reg, XX_CORE_STAT_REG);
+	efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
 
-	align_done = EFX_OWORD_FIELD(reg, XX_ALIGN_DONE);
-	sync_status = EFX_OWORD_FIELD(reg, XX_SYNC_STAT);
-	if (align_done && (sync_status == XX_SYNC_STAT_DECODE_SYNCED))
+	align_done = EFX_OWORD_FIELD(reg, FRF_AB_XX_ALIGN_DONE);
+	sync_status = EFX_OWORD_FIELD(reg, FRF_AB_XX_SYNC_STAT);
+	if (align_done && (sync_status == FFE_AB_XX_STAT_ALL_LANES))
 		link_ok = true;
 
 	/* Clear link status ready for next read */
-	EFX_SET_OWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET);
-	EFX_SET_OWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET);
-	EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
-	falcon_write(efx, &reg, XX_CORE_STAT_REG);
-
-	/* If the link is up, then check the phy side of the xaui link */
-	if (efx->link_up && link_ok)
-		if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
-			link_ok = efx_mdio_phyxgxs_lane_sync(efx);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_COMMA_DET, FFE_AB_XX_STAT_ALL_LANES);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_CHAR_ERR, FFE_AB_XX_STAT_ALL_LANES);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES);
+	efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
 
 	return link_ok;
 }
 
-static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
+static bool falcon_xmac_link_ok(struct efx_nic *efx)
+{
+	/*
+	 * Check MAC's XGXS link status except when using XGMII loopback
+	 * which bypasses the XGXS block.
+	 * If possible, check PHY's XGXS link status except when using
+	 * MAC loopback.
+	 */
+	return (efx->loopback_mode == LOOPBACK_XGMII ||
+		falcon_xgxs_link_ok(efx)) &&
+		(!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) ||
+		 LOOPBACK_INTERNAL(efx) || 
+		 efx_mdio_phyxgxs_lane_sync(efx));
+}
+
+void falcon_reconfigure_xmac_core(struct efx_nic *efx)
 {
 	unsigned int max_frame_len;
 	efx_oword_t reg;
-	bool rx_fc = !!(efx->link_fc & EFX_FC_RX);
+	bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX);
+	bool tx_fc = !!(efx->link_state.fc & EFX_FC_TX);
 
 	/* 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);
-	falcon_write(efx, &reg, XM_GLB_CFG_REG);
+	EFX_POPULATE_OWORD_3(reg,
+			     FRF_AB_XM_RX_JUMBO_MODE, 1,
+			     FRF_AB_XM_TX_STAT_EN, 1,
+			     FRF_AB_XM_RX_STAT_EN, 1);
+	efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
 
 	/* 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);
-	falcon_write(efx, &reg, XM_TX_CFG_REG);
+	EFX_POPULATE_OWORD_6(reg,
+			     FRF_AB_XM_TXEN, 1,
+			     FRF_AB_XM_TX_PRMBL, 1,
+			     FRF_AB_XM_AUTO_PAD, 1,
+			     FRF_AB_XM_TXCRC, 1,
+			     FRF_AB_XM_FCNTL, tx_fc,
+			     FRF_AB_XM_IPG, 0x3);
+	efx_writeo(efx, &reg, FR_AB_XM_TX_CFG);
 
 	/* 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);
-	falcon_write(efx, &reg, XM_RX_CFG_REG);
+	EFX_POPULATE_OWORD_5(reg,
+			     FRF_AB_XM_RXEN, 1,
+			     FRF_AB_XM_AUTO_DEPAD, 0,
+			     FRF_AB_XM_ACPT_ALL_MCAST, 1,
+			     FRF_AB_XM_ACPT_ALL_UCAST, efx->promiscuous,
+			     FRF_AB_XM_PASS_CRC_ERR, 1);
+	efx_writeo(efx, &reg, FR_AB_XM_RX_CFG);
 
 	/* 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);
-	falcon_write(efx, &reg, XM_RX_PARAM_REG);
-	EFX_POPULATE_DWORD_2(reg,
-			     XM_MAX_TX_FRM_SIZE, max_frame_len,
-			     XM_TX_JUMBO_MODE, 1);
-	falcon_write(efx, &reg, XM_TX_PARAM_REG);
-
-	EFX_POPULATE_DWORD_2(reg,
-			     XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
-			     XM_DIS_FCNTL, !rx_fc);
-	falcon_write(efx, &reg, XM_FC_REG);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
+	efx_writeo(efx, &reg, FR_AB_XM_RX_PARAM);
+	EFX_POPULATE_OWORD_2(reg,
+			     FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len,
+			     FRF_AB_XM_TX_JUMBO_MODE, 1);
+	efx_writeo(efx, &reg, FR_AB_XM_TX_PARAM);
+
+	EFX_POPULATE_OWORD_2(reg,
+			     FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
+			     FRF_AB_XM_DIS_FCNTL, !rx_fc);
+	efx_writeo(efx, &reg, FR_AB_XM_FC);
 
 	/* 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]);
-	falcon_write(efx, &reg, XM_ADR_LO_REG);
-	EFX_POPULATE_DWORD_2(reg,
-			     XM_ADR_4, efx->net_dev->dev_addr[4],
-			     XM_ADR_5, efx->net_dev->dev_addr[5]);
-	falcon_write(efx, &reg, XM_ADR_HI_REG);
+	memcpy(&reg, &efx->net_dev->dev_addr[0], 4);
+	efx_writeo(efx, &reg, FR_AB_XM_ADR_LO);
+	memcpy(&reg, &efx->net_dev->dev_addr[4], 2);
+	efx_writeo(efx, &reg, FR_AB_XM_ADR_HI);
 }
 
 static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
@@ -212,12 +216,13 @@
 		bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback;
 		bool reset_xgxs;
 
-		falcon_read(efx, &reg, XX_CORE_STAT_REG);
-		old_xgxs_loopback = EFX_OWORD_FIELD(reg, XX_XGXS_LB_EN);
-		old_xgmii_loopback = EFX_OWORD_FIELD(reg, XX_XGMII_LB_EN);
+		efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
+		old_xgxs_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN);
+		old_xgmii_loopback =
+			EFX_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN);
 
-		falcon_read(efx, &reg, XX_SD_CTL_REG);
-		old_xaui_loopback = EFX_OWORD_FIELD(reg, XX_LPBKA);
+		efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
+		old_xaui_loopback = EFX_OWORD_FIELD(reg, FRF_AB_XX_LPBKA);
 
 		/* The PHY driver may have turned XAUI off */
 		reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) ||
@@ -228,45 +233,55 @@
 			falcon_reset_xaui(efx);
 	}
 
-	falcon_read(efx, &reg, XX_CORE_STAT_REG);
-	EFX_SET_OWORD_FIELD(reg, XX_FORCE_SIG,
+	efx_reado(efx, &reg, FR_AB_XX_CORE_STAT);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_FORCE_SIG,
 			    (xgxs_loopback || xaui_loopback) ?
-			    XX_FORCE_SIG_DECODE_FORCED : 0);
-	EFX_SET_OWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback);
-	EFX_SET_OWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback);
-	falcon_write(efx, &reg, XX_CORE_STAT_REG);
+			    FFE_AB_XX_FORCE_SIG_ALL_LANES : 0);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGXS_LB_EN, xgxs_loopback);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_XGMII_LB_EN, xgmii_loopback);
+	efx_writeo(efx, &reg, FR_AB_XX_CORE_STAT);
 
-	falcon_read(efx, &reg, XX_SD_CTL_REG);
-	EFX_SET_OWORD_FIELD(reg, XX_LPBKD, xaui_loopback);
-	EFX_SET_OWORD_FIELD(reg, XX_LPBKC, xaui_loopback);
-	EFX_SET_OWORD_FIELD(reg, XX_LPBKB, xaui_loopback);
-	EFX_SET_OWORD_FIELD(reg, XX_LPBKA, xaui_loopback);
-	falcon_write(efx, &reg, XX_SD_CTL_REG);
+	efx_reado(efx, &reg, FR_AB_XX_SD_CTL);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKD, xaui_loopback);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKC, xaui_loopback);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKB, xaui_loopback);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_LPBKA, xaui_loopback);
+	efx_writeo(efx, &reg, FR_AB_XX_SD_CTL);
 }
 
 
-/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
- * to come back up. Bash it until it comes back up */
-static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
+/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
+static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries)
 {
-	efx->mac_up = falcon_xaui_link_ok(efx);
+	bool mac_up = falcon_xmac_link_ok(efx);
 
-	if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
+	if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS ||
 	    efx_phy_mode_disabled(efx->phy_mode))
 		/* XAUI link is expected to be down */
-		return;
+		return mac_up;
+
+	falcon_stop_nic_stats(efx);
 
-	while (!efx->mac_up && tries) {
+	while (!mac_up && tries) {
 		EFX_LOG(efx, "bashing xaui\n");
 		falcon_reset_xaui(efx);
 		udelay(200);
 
-		efx->mac_up = falcon_xaui_link_ok(efx);
+		mac_up = falcon_xmac_link_ok(efx);
 		--tries;
 	}
+
+	falcon_start_nic_stats(efx);
+
+	return mac_up;
+}
+
+static bool falcon_xmac_check_fault(struct efx_nic *efx)
+{
+	return !falcon_xmac_link_ok_retry(efx, 5);
 }
 
-static void falcon_reconfigure_xmac(struct efx_nic *efx)
+static int falcon_reconfigure_xmac(struct efx_nic *efx)
 {
 	falcon_mask_status_intr(efx, false);
 
@@ -275,18 +290,15 @@
 
 	falcon_reconfigure_mac_wrapper(efx);
 
-	falcon_check_xaui_link_up(efx, 5);
+	efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5);
 	falcon_mask_status_intr(efx, true);
+
+	return 0;
 }
 
 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);
@@ -344,35 +356,19 @@
 		 mac_stats->rx_control * 64);
 }
 
-static void falcon_xmac_irq(struct efx_nic *efx)
-{
-	/* The XGMII link has a transient fault, which indicates either:
-	 *   - there's a transient xgmii fault
-	 *   - falcon's end of the xaui link may need a kick
-	 *   - the wire-side link may have gone down, but the lasi/poll()
-	 *     hasn't noticed yet.
-	 *
-	 * We only want to even bother polling XAUI if we're confident it's
-	 * not (1) or (3). In both cases, the only reliable way to spot this
-	 * is to wait a bit. We do this here by forcing the mac link state
-	 * to down, and waiting for the mac poll to come round and check
-	 */
-	efx->mac_up = false;
-}
-
-static void falcon_poll_xmac(struct efx_nic *efx)
+void falcon_poll_xmac(struct efx_nic *efx)
 {
-	if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up)
+	if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up ||
+	    !efx->xmac_poll_required)
 		return;
 
 	falcon_mask_status_intr(efx, false);
-	falcon_check_xaui_link_up(efx, 1);
+	efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1);
 	falcon_mask_status_intr(efx, true);
 }
 
 struct efx_mac_operations falcon_xmac_operations = {
 	.reconfigure	= falcon_reconfigure_xmac,
 	.update_stats	= falcon_update_stats_xmac,
-	.irq		= falcon_xmac_irq,
-	.poll		= falcon_poll_xmac,
+	.check_fault	= falcon_xmac_check_fault,
 };
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mdio_10g.c
+++ linux-ec2-2.6.32/drivers/net/sfc/mdio_10g.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -14,8 +14,8 @@
 #include <linux/delay.h>
 #include "net_driver.h"
 #include "mdio_10g.h"
-#include "boards.h"
 #include "workarounds.h"
+#include "nic.h"
 
 unsigned efx_mdio_id_oui(u32 id)
 {
@@ -174,7 +174,7 @@
 	 * of mmd's */
 	if (LOOPBACK_INTERNAL(efx))
 		return true;
-	else if (efx->loopback_mode == LOOPBACK_NETWORK)
+	else if (LOOPBACK_MASK(efx) & LOOPBACKS_WS)
 		return false;
 	else if (efx_phy_mode_disabled(efx->phy_mode))
 		return false;
@@ -211,7 +211,7 @@
 			  efx->loopback_mode == LOOPBACK_PCS);
 	efx_mdio_set_flag(efx, MDIO_MMD_PHYXS,
 			  MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK,
-			  efx->loopback_mode == LOOPBACK_NETWORK);
+			  efx->loopback_mode == LOOPBACK_PHYXS_WS);
 }
 
 static void efx_mdio_set_mmd_lpower(struct efx_nic *efx,
@@ -249,8 +249,6 @@
 int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
 	struct ethtool_cmd prev;
-	u32 required;
-	int reg;
 
 	efx->phy_op->get_settings(efx, &prev);
 
@@ -266,86 +264,74 @@
 		return -EINVAL;
 
 	/* Check that PHY supports these settings */
-	if (ecmd->autoneg) {
-		required = SUPPORTED_Autoneg;
-	} else if (ecmd->duplex) {
-		switch (ecmd->speed) {
-		case SPEED_10:  required = SUPPORTED_10baseT_Full;  break;
-		case SPEED_100: required = SUPPORTED_100baseT_Full; break;
-		default:        return -EINVAL;
-		}
-	} else {
-		switch (ecmd->speed) {
-		case SPEED_10:  required = SUPPORTED_10baseT_Half;  break;
-		case SPEED_100: required = SUPPORTED_100baseT_Half; break;
-		default:        return -EINVAL;
-		}
-	}
-	required |= ecmd->advertising;
-	if (required & ~prev.supported)
+	if (!ecmd->autoneg ||
+	    (ecmd->advertising | SUPPORTED_Autoneg) & ~prev.supported)
 		return -EINVAL;
 
-	if (ecmd->autoneg) {
-		bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full
-			    || EFX_WORKAROUND_13204(efx));
-
-		/* Set up the base page */
-		reg = ADVERTISE_CSMA;
-		if (ecmd->advertising & ADVERTISED_10baseT_Half)
-			reg |= ADVERTISE_10HALF;
-		if (ecmd->advertising & ADVERTISED_10baseT_Full)
-			reg |= ADVERTISE_10FULL;
-		if (ecmd->advertising & ADVERTISED_100baseT_Half)
-			reg |= ADVERTISE_100HALF;
-		if (ecmd->advertising & ADVERTISED_100baseT_Full)
-			reg |= ADVERTISE_100FULL;
-		if (xnp)
-			reg |= ADVERTISE_RESV;
-		else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
-					      ADVERTISED_1000baseT_Full))
-			reg |= ADVERTISE_NPAGE;
-		reg |= mii_advertise_flowctrl(efx->wanted_fc);
-		efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
-
-		/* Set up the (extended) next page if necessary */
-		if (efx->phy_op->set_npage_adv)
-			efx->phy_op->set_npage_adv(efx, ecmd->advertising);
-
-		/* Enable and restart AN */
-		reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
-		reg |= MDIO_AN_CTRL1_ENABLE;
-		if (!(EFX_WORKAROUND_15195(efx) &&
-		      LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
-			reg |= MDIO_AN_CTRL1_RESTART;
-		if (xnp)
-			reg |= MDIO_AN_CTRL1_XNP;
-		else
-			reg &= ~MDIO_AN_CTRL1_XNP;
-		efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
-	} else {
-		/* Disable AN */
-		efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1,
-				  MDIO_AN_CTRL1_ENABLE, false);
-
-		/* Set the basic control bits */
-		reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1);
-		reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX);
-		if (ecmd->speed == SPEED_100)
-			reg |= MDIO_PMA_CTRL1_SPEED100;
-		if (ecmd->duplex)
-			reg |= MDIO_CTRL1_FULLDPLX;
-		efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg);
-	}
-
+	efx_link_set_advertising(efx, ecmd->advertising | ADVERTISED_Autoneg);
+	efx_mdio_an_reconfigure(efx);
 	return 0;
 }
 
+/**
+ * efx_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
+ * @efx:		Efx NIC
+ */
+void efx_mdio_an_reconfigure(struct efx_nic *efx)
+{
+	bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full
+		    || EFX_WORKAROUND_13204(efx));
+	int reg;
+
+	WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
+
+	/* Set up the base page */
+	reg = ADVERTISE_CSMA;
+	if (efx->link_advertising & ADVERTISED_10baseT_Half)
+		reg |= ADVERTISE_10HALF;
+	if (efx->link_advertising & ADVERTISED_10baseT_Full)
+		reg |= ADVERTISE_10FULL;
+	if (efx->link_advertising & ADVERTISED_100baseT_Half)
+		reg |= ADVERTISE_100HALF;
+	if (efx->link_advertising & ADVERTISED_100baseT_Full)
+		reg |= ADVERTISE_100FULL;
+	if (xnp)
+		reg |= ADVERTISE_RESV;
+	else if (efx->link_advertising & (ADVERTISED_1000baseT_Half |
+					  ADVERTISED_1000baseT_Full))
+		reg |= ADVERTISE_NPAGE;
+	if (efx->link_advertising & ADVERTISED_Pause)
+		reg |= ADVERTISE_PAUSE_CAP;
+	if (efx->link_advertising & ADVERTISED_Asym_Pause)
+		reg |= ADVERTISE_PAUSE_ASYM;
+	efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
+
+	/* Set up the (extended) next page if necessary */
+	if (efx->phy_op->set_npage_adv)
+		efx->phy_op->set_npage_adv(efx, efx->link_advertising);
+
+	/* Enable and restart AN */
+	reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1);
+	reg |= MDIO_AN_CTRL1_ENABLE;
+	if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx)))
+		reg |= MDIO_AN_CTRL1_RESTART;
+	if (xnp)
+		reg |= MDIO_AN_CTRL1_XNP;
+	else
+		reg &= ~MDIO_AN_CTRL1_XNP;
+	efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg);
+}
+
 enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx)
 {
-	int lpa;
+	BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX));
 
-	if (!(efx->phy_op->mmds & MDIO_DEVS_AN))
+	if (!(efx->wanted_fc & EFX_FC_AUTO))
 		return efx->wanted_fc;
-	lpa = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA);
-	return efx_fc_resolve(efx->wanted_fc, lpa);
+
+	WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN));
+
+	return mii_resolve_flowctrl_fdx(
+		mii_advertise_flowctrl(efx->wanted_fc),
+		efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA));
 }
--- linux-ec2-2.6.32.orig/drivers/net/sfc/falcon.c
+++ linux-ec2-2.6.32/drivers/net/sfc/falcon.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -14,1344 +14,124 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
 #include <linux/mii.h>
 #include "net_driver.h"
 #include "bitfield.h"
 #include "efx.h"
 #include "mac.h"
 #include "spi.h"
-#include "falcon.h"
-#include "falcon_hwdefs.h"
-#include "falcon_io.h"
+#include "nic.h"
+#include "regs.h"
+#include "io.h"
 #include "mdio_10g.h"
 #include "phy.h"
-#include "boards.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 - Falcon NIC state
- * @next_buffer_table: First available buffer table id
- * @pci_dev2: The secondary PCI device if present
- * @i2c_data: Operations and state for I2C bit-bashing algorithm
- * @int_error_count: Number of internal errors seen recently
- * @int_error_expire: Time at which error count will be expired
- */
-struct falcon_nic_data {
-	unsigned next_buffer_table;
-	struct pci_dev *pci_dev2;
-	struct i2c_algo_bit_data i2c_data;
-
-	unsigned int_error_count;
-	unsigned long int_error_expire;
-};
-
-/**************************************************************************
- *
- * Configurable values
- *
- **************************************************************************
- */
-
-static int disable_dma_stats;
-
-/* 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.
- */
-#define TX_DC_ENTRIES 16
-#define TX_DC_ENTRIES_ORDER 0
-#define TX_DC_BASE 0x130000
-
-#define RX_DC_ENTRIES 64
-#define RX_DC_ENTRIES_ORDER 2
-#define RX_DC_BASE 0x100000
-
-static const unsigned int
-/* "Large" EEPROM device: Atmel AT25640 or similar
- * 8 KB, 16-bit address, 32 B write block */
-large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
-		     | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
-		     | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
-/* Default flash device: Atmel AT25F1024
- * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
-default_flash_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));
-
-/* 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)
-
-/* If FALCON_MAX_INT_ERRORS internal errors occur within
- * FALCON_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
- * disable it.
- */
-#define FALCON_INT_ERROR_EXPIRE 3600
-#define FALCON_MAX_INT_ERRORS 5
-
-/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
- */
-#define FALCON_FLUSH_INTERVAL 10
-#define FALCON_FLUSH_POLL_COUNT 100
-
-/**************************************************************************
- *
- * Falcon constants
- *
- **************************************************************************
- */
-
-/* DMA address mask */
-#define FALCON_DMA_MASK DMA_BIT_MASK(46)
-
-/* TX DMA length mask (13-bit) */
-#define FALCON_TX_DMA_MASK (4096 - 1)
-
-/* Size and alignment of special buffers (4KB) */
-#define FALCON_BUF_SIZE 4096
-
-/* Dummy SRAM size code */
-#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
-
-#define FALCON_IS_DUAL_FUNC(efx)		\
-	(falcon_rev(efx) < FALCON_REV_B0)
-
-/**************************************************************************
- *
- * 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])));
-}
-
-/**************************************************************************
- *
- * 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_setsda(void *data, int state)
-{
-	struct efx_nic *efx = (struct efx_nic *)data;
-	efx_oword_t reg;
-
-	falcon_read(efx, &reg, GPIO_CTL_REG_KER);
-	EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, !state);
-	falcon_write(efx, &reg, GPIO_CTL_REG_KER);
-}
-
-static void falcon_setscl(void *data, int state)
-{
-	struct efx_nic *efx = (struct efx_nic *)data;
-	efx_oword_t reg;
-
-	falcon_read(efx, &reg, GPIO_CTL_REG_KER);
-	EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, !state);
-	falcon_write(efx, &reg, GPIO_CTL_REG_KER);
-}
-
-static int falcon_getsda(void *data)
-{
-	struct efx_nic *efx = (struct efx_nic *)data;
-	efx_oword_t reg;
-
-	falcon_read(efx, &reg, GPIO_CTL_REG_KER);
-	return EFX_OWORD_FIELD(reg, GPIO3_IN);
-}
-
-static int falcon_getscl(void *data)
-{
-	struct efx_nic *efx = (struct efx_nic *)data;
-	efx_oword_t reg;
-
-	falcon_read(efx, &reg, GPIO_CTL_REG_KER);
-	return EFX_OWORD_FIELD(reg, GPIO0_IN);
-}
-
-static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
-	.setsda		= falcon_setsda,
-	.setscl		= falcon_setscl,
-	.getsda		= falcon_getsda,
-	.getscl		= falcon_getscl,
-	.udelay		= 5,
-	/* Wait up to 50 ms for slave to let us pull SCL high */
-	.timeout	= DIV_ROUND_UP(HZ, 20),
-};
-
-/**************************************************************************
- *
- * Falcon special buffer handling
- * Special buffers are used for event queues and the TX and RX
- * descriptor rings.
- *
- *************************************************************************/
-
-/*
- * 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 void
-falcon_init_special_buffer(struct efx_nic *efx,
-			   struct efx_special_buffer *buffer)
-{
-	efx_qword_t buf_desc;
-	int index;
-	dma_addr_t dma_addr;
-	int i;
-
-	EFX_BUG_ON_PARANOID(!buffer->addr);
-
-	/* 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);
-	}
-}
-
-/* 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)
-{
-	efx_oword_t buf_tbl_upd;
-	unsigned int start = buffer->index;
-	unsigned int end = (buffer->index + buffer->entries - 1);
-
-	if (!buffer->entries)
-		return;
-
-	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.
- */
-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;
-
-	len = ALIGN(len, FALCON_BUF_SIZE);
-
-	buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
-					    &buffer->dma_addr);
-	if (!buffer->addr)
-		return -ENOMEM;
-	buffer->len = len;
-	buffer->entries = len / FALCON_BUF_SIZE;
-	BUG_ON(buffer->dma_addr & (FALCON_BUF_SIZE - 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->next_buffer_table;
-	nic_data->next_buffer_table += buffer->entries;
-
-	EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
-		"(virt %p phys %llx)\n", buffer->index,
-		buffer->index + buffer->entries - 1,
-		(u64)buffer->dma_addr, len,
-		buffer->addr, (u64)virt_to_phys(buffer->addr));
-
-	return 0;
-}
-
-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 %llx)\n", buffer->index,
-		buffer->index + buffer->entries - 1,
-		(u64)buffer->dma_addr, buffer->len,
-		buffer->addr, (u64)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);
-}
-
-/* This writes to the TX_DESC_WPTR; write pointer for TX 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.
- */
-void falcon_push_buffers(struct efx_tx_queue *tx_queue)
-{
-
-	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;
-	return falcon_alloc_special_buffer(efx, &tx_queue->txd,
-					   FALCON_TXD_RING_SIZE *
-					   sizeof(efx_qword_t));
-}
-
-void falcon_init_tx(struct efx_tx_queue *tx_queue)
-{
-	efx_oword_t tx_desc_ptr;
-	struct efx_nic *efx = tx_queue->efx;
-
-	tx_queue->flushed = false;
-
-	/* Pin TX descriptor ring */
-	falcon_init_special_buffer(efx, &tx_queue->txd);
-
-	/* 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->channel,
-			      TX_DESCQ_OWNER_ID, 0,
-			      TX_DESCQ_LABEL, tx_queue->queue,
-			      TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER,
-			      TX_DESCQ_TYPE, 0,
-			      TX_NON_IP_DROP_DIS_B0, 1);
-
-	if (falcon_rev(efx) >= FALCON_REV_B0) {
-		int csum = tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_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 */
-		BUILD_BUG_ON(EFX_TX_QUEUE_COUNT >= 128);
-
-		falcon_read(efx, &reg, TX_CHKSM_CFG_REG_KER_A1);
-		if (tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_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);
-	}
-}
-
-static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
-{
-	struct efx_nic *efx = tx_queue->efx;
-	efx_oword_t tx_flush_descq;
-
-	/* 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);
-}
-
-void falcon_fini_tx(struct efx_tx_queue *tx_queue)
-{
-	struct efx_nic *efx = tx_queue->efx;
-	efx_oword_t tx_desc_ptr;
-
-	/* The queue should have been flushed */
-	WARN_ON(!tx_queue->flushed);
-
-	/* 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 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 */
-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.
- */
-void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue)
-{
-	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;
-	return falcon_alloc_special_buffer(efx, &rx_queue->rxd,
-					   FALCON_RXD_RING_SIZE *
-					   sizeof(efx_qword_t));
-}
-
-void falcon_init_rx(struct efx_rx_queue *rx_queue)
-{
-	efx_oword_t rx_desc_ptr;
-	struct efx_nic *efx = rx_queue->efx;
-	bool is_b0 = falcon_rev(efx) >= FALCON_REV_B0;
-	bool 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);
-
-	rx_queue->flushed = false;
-
-	/* Pin RX descriptor ring */
-	falcon_init_special_buffer(efx, &rx_queue->rxd);
-
-	/* 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->channel,
-			      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);
-}
-
-static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
-{
-	struct efx_nic *efx = rx_queue->efx;
-	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);
-}
-
-void falcon_fini_rx(struct efx_rx_queue *rx_queue)
-{
-	efx_oword_t rx_desc_ptr;
-	struct efx_nic *efx = rx_queue->efx;
-
-	/* The queue should already have been flushed */
-	WARN_ON(!rx_queue->flushed);
-
-	/* 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.
- */
-void falcon_eventq_read_ack(struct efx_channel *channel)
-{
-	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->channel);
-}
-
-/* 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->channel,
-			     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 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];
-		channel->irq_mod_score +=
-			(tx_ev_desc_ptr - tx_queue->read_count) &
-			efx->type->txd_ring_mask;
-		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_dev_registered(efx))
-			netif_tx_lock(efx->net_dev);
-		falcon_notify_tx_desc(tx_queue);
-		if (efx_dev_registered(efx))
-			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));
-	}
-}
-
-/* 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,
-				    bool *rx_ev_pkt_ok,
-				    bool *discard)
-{
-	struct efx_nic *efx = rx_queue->efx;
-	bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
-	bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
-	bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
-	bool rx_ev_other_err, rx_ev_pause_frm;
-	bool rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt;
-	unsigned rx_ev_pkt_type;
-
-	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);
-
-	/* Count errors that are not in MAC stats.  Ignore expected
-	 * checksum errors during self-test. */
-	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 (!efx->loopback_selftest) {
-		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\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]" : "");
-	}
-#endif
-}
-
-/* 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);
-
-	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 void falcon_handle_rx_event(struct efx_channel *channel,
-				   const efx_qword_t *event)
-{
-	unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
-	unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
-	unsigned expected_ptr;
-	bool rx_ev_pkt_ok, discard = false, 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);
-	WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL) != channel->channel);
-
-	rx_queue = &efx->rx_queue[channel->channel];
-
-	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);
-
-	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);
-		checksummed = false;
-	}
-
-	/* 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 = true;
-	}
-
-	channel->irq_mod_score += 2;
-
-	/* Handle received packet */
-	efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
-		      checksummed, discard);
-}
-
-/* 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;
-	bool handled = false;
-
-	if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
-	    EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
-	    EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
-	    EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
-		efx->phy_op->clear_interrupt(efx);
-		queue_work(efx->workqueue, &efx->phy_work);
-		handled = true;
-	}
-
-	if ((falcon_rev(efx) >= FALCON_REV_B0) &&
-	    EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
-		queue_work(efx->workqueue, &efx->mac_work);
-		handled = true;
-	}
-
-	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->rx_reset);
-		efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
-				   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
-		handled = true;
-	}
-
-	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);
-		break;
-	case RX_DESCQ_FLS_DONE_EV_DECODE:
-		EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
-			  channel->channel, ev_sub_data);
-		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);
-		break;
-	case WAKE_UP_EV_DECODE:
-		EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
-			  channel->channel, ev_sub_data);
-		break;
-	case TIMER_EV_DECODE:
-		EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
-			  channel->channel, ev_sub_data);
-		break;
-	case RX_RECOVERY_EV_DECODE:
-		EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
-			"Resetting.\n", channel->channel);
-		atomic_inc(&efx->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);
-		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);
-		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);
-		break;
-	}
-}
-
-int falcon_process_eventq(struct efx_channel *channel, int rx_quota)
-{
-	unsigned int read_ptr;
-	efx_qword_t event, *p_event;
-	int ev_code;
-	int rx_packets = 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:
-			falcon_handle_rx_event(channel, &event);
-			++rx_packets;
-			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_packets < rx_quota);
-
-	channel->eventq_read_ptr = read_ptr;
-	return rx_packets;
-}
-
-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).
-		 */
-		channel->irq_moderation -= (channel->irq_moderation %
-					    FALCON_IRQ_MOD_RESOLUTION);
-		if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION)
-			channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION;
-		EFX_POPULATE_DWORD_2(timer_cmd,
-				     TIMER_MODE, TIMER_MODE_INT_HLDOFF,
-				     TIMER_VAL,
-				     channel->irq_moderation /
-				     FALCON_IRQ_MOD_RESOLUTION - 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->channel);
-
-}
-
-/* Allocate buffer table entries for event queue */
-int falcon_probe_eventq(struct efx_channel *channel)
-{
-	struct efx_nic *efx = channel->efx;
-	unsigned int evq_size;
-
-	evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t);
-	return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
-}
-
-void falcon_init_eventq(struct efx_channel *channel)
-{
-	efx_oword_t evq_ptr;
-	struct efx_nic *efx = channel->efx;
-
-	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 */
-	falcon_init_special_buffer(efx, &channel->eventq);
-
-	/* 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->channel);
-
-	falcon_set_int_moderation(channel);
-}
-
-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->channel);
-
-	/* 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);
-}
+/* Hardware control for SFC4000 (aka Falcon). */
 
+static const unsigned int
+/* "Large" EEPROM device: Atmel AT25640 or similar
+ * 8 KB, 16-bit address, 32 B write block */
+large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
+		     | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+		     | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
+/* Default flash device: Atmel AT25F1024
+ * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
+default_flash_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));
 
-/* 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;
+/**************************************************************************
+ *
+ * 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
+ *
+ **************************************************************************
  */
-void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
+static void falcon_setsda(void *data, int state)
 {
-	efx_qword_t test_event;
+	struct efx_nic *efx = (struct efx_nic *)data;
+	efx_oword_t reg;
 
-	EFX_POPULATE_QWORD_2(test_event,
-			     EV_CODE, DRV_GEN_EV_DECODE,
-			     EVQ_MAGIC, magic);
-	falcon_generate_event(channel, &test_event);
+	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN, !state);
+	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
 }
 
-void falcon_sim_phy_event(struct efx_nic *efx)
+static void falcon_setscl(void *data, int state)
 {
-	efx_qword_t phy_event;
-
-	EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE);
-	if (EFX_IS10G(efx))
-		EFX_SET_QWORD_FIELD(phy_event, XG_PHY_INTR, 1);
-	else
-		EFX_SET_QWORD_FIELD(phy_event, G_PHY0_INTR, 1);
+	struct efx_nic *efx = (struct efx_nic *)data;
+	efx_oword_t reg;
 
-	falcon_generate_event(&efx->channel[0], &phy_event);
+	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO0_OEN, !state);
+	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
 }
 
-/**************************************************************************
- *
- * Flush handling
- *
- **************************************************************************/
-
-
-static void falcon_poll_flush_events(struct efx_nic *efx)
+static int falcon_getsda(void *data)
 {
-	struct efx_channel *channel = &efx->channel[0];
-	struct efx_tx_queue *tx_queue;
-	struct efx_rx_queue *rx_queue;
-	unsigned int read_ptr = channel->eventq_read_ptr;
-	unsigned int end_ptr = (read_ptr - 1) & FALCON_EVQ_MASK;
-
-	do {
-		efx_qword_t *event = falcon_event(channel, read_ptr);
-		int ev_code, ev_sub_code, ev_queue;
-		bool 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);
-		if (ev_code == DRIVER_EV_DECODE &&
-		    ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) {
-			ev_queue = EFX_QWORD_FIELD(*event,
-						   DRIVER_EV_TX_DESCQ_ID);
-			if (ev_queue < EFX_TX_QUEUE_COUNT) {
-				tx_queue = efx->tx_queue + ev_queue;
-				tx_queue->flushed = true;
-			}
-		} else if (ev_code == DRIVER_EV_DECODE &&
-			   ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) {
-			ev_queue = EFX_QWORD_FIELD(*event,
-						   DRIVER_EV_RX_DESCQ_ID);
-			ev_failed = EFX_QWORD_FIELD(*event,
-						    DRIVER_EV_RX_FLUSH_FAIL);
-			if (ev_queue < efx->n_rx_queues) {
-				rx_queue = efx->rx_queue + ev_queue;
-
-				/* retry the rx flush */
-				if (ev_failed)
-					falcon_flush_rx_queue(rx_queue);
-				else
-					rx_queue->flushed = true;
-			}
-		}
+	struct efx_nic *efx = (struct efx_nic *)data;
+	efx_oword_t reg;
 
-		read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK;
-	} while (read_ptr != end_ptr);
+	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
+	return EFX_OWORD_FIELD(reg, FRF_AB_GPIO3_IN);
 }
 
-/* Handle tx and rx flushes at the same time, since they run in
- * parallel in the hardware and there's no reason for us to
- * serialise them */
-int falcon_flush_queues(struct efx_nic *efx)
+static int falcon_getscl(void *data)
 {
-	struct efx_rx_queue *rx_queue;
-	struct efx_tx_queue *tx_queue;
-	int i;
-	bool outstanding;
-
-	/* Issue flush requests */
-	efx_for_each_tx_queue(tx_queue, efx) {
-		tx_queue->flushed = false;
-		falcon_flush_tx_queue(tx_queue);
-	}
-	efx_for_each_rx_queue(rx_queue, efx) {
-		rx_queue->flushed = false;
-		falcon_flush_rx_queue(rx_queue);
-	}
-
-	/* Poll the evq looking for flush completions. Since we're not pushing
-	 * any more rx or tx descriptors at this point, we're in no danger of
-	 * overflowing the evq whilst we wait */
-	for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) {
-		msleep(FALCON_FLUSH_INTERVAL);
-		falcon_poll_flush_events(efx);
-
-		/* Check if every queue has been succesfully flushed */
-		outstanding = false;
-		efx_for_each_tx_queue(tx_queue, efx)
-			outstanding |= !tx_queue->flushed;
-		efx_for_each_rx_queue(rx_queue, efx)
-			outstanding |= !rx_queue->flushed;
-		if (!outstanding)
-			return 0;
-	}
-
-	/* Mark the queues as all flushed. We're going to return failure
-	 * leading to a reset, or fake up success anyway. "flushed" now
-	 * indicates that we tried to flush. */
-	efx_for_each_tx_queue(tx_queue, efx) {
-		if (!tx_queue->flushed)
-			EFX_ERR(efx, "tx queue %d flush command timed out\n",
-				tx_queue->queue);
-		tx_queue->flushed = true;
-	}
-	efx_for_each_rx_queue(rx_queue, efx) {
-		if (!rx_queue->flushed)
-			EFX_ERR(efx, "rx queue %d flush command timed out\n",
-				rx_queue->queue);
-		rx_queue->flushed = true;
-	}
-
-	if (EFX_WORKAROUND_7803(efx))
-		return 0;
+	struct efx_nic *efx = (struct efx_nic *)data;
+	efx_oword_t reg;
 
-	return -ETIMEDOUT;
+	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
+	return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN);
 }
 
-/**************************************************************************
- *
- * Falcon hardware interrupts
- * The hardware interrupt handler does very little work; all the event
- * queue processing is carried out by per-channel tasklets.
- *
- **************************************************************************/
+static struct i2c_algo_bit_data falcon_i2c_bit_operations = {
+	.setsda		= falcon_setsda,
+	.setscl		= falcon_setscl,
+	.getsda		= falcon_getsda,
+	.getscl		= falcon_getscl,
+	.udelay		= 5,
+	/* Wait up to 50 ms for slave to let us pull SCL high */
+	.timeout	= DIV_ROUND_UP(HZ, 20),
+};
 
-/* Enable/disable/generate Falcon interrupts */
-static inline void falcon_interrupts(struct efx_nic *efx, int enabled,
-				     int force)
+static void falcon_push_irq_moderation(struct efx_channel *channel)
 {
-	efx_oword_t int_en_reg_ker;
+	efx_dword_t timer_cmd;
+	struct efx_nic *efx = channel->efx;
 
-	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);
+	/* Set timer register */
+	if (channel->irq_moderation) {
+		EFX_POPULATE_DWORD_2(timer_cmd,
+				     FRF_AB_TC_TIMER_MODE,
+				     FFE_BB_TIMER_MODE_INT_HLDOFF,
+				     FRF_AB_TC_TIMER_VAL,
+				     channel->irq_moderation - 1);
+	} else {
+		EFX_POPULATE_DWORD_2(timer_cmd,
+				     FRF_AB_TC_TIMER_MODE,
+				     FFE_BB_TIMER_MODE_DIS,
+				     FRF_AB_TC_TIMER_VAL, 0);
+	}
+	BUILD_BUG_ON(FR_AA_TIMER_COMMAND_KER != FR_BZ_TIMER_COMMAND_P0);
+	efx_writed_page_locked(efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
+			       channel->channel);
 }
 
-void falcon_enable_interrupts(struct efx_nic *efx)
-{
-	efx_oword_t int_adr_reg_ker;
-	struct efx_channel *channel;
-
-	EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr));
-	wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
+static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
 
-	/* Program address */
-	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(channel, efx)
-		efx_schedule_channel(channel);
-}
-
-void falcon_disable_interrupts(struct efx_nic *efx)
+static void falcon_prepare_flush(struct efx_nic *efx)
 {
-	/* Disable interrupts */
-	falcon_interrupts(efx, 0, 0);
-}
+	falcon_deconfigure_mac_wrapper(efx);
 
-/* 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);
+	/* Wait for the tx and rx fifo's to get to the next packet boundary
+	 * (~1ms without back-pressure), then to drain the remainder of the
+	 * fifo's at data path speeds (negligible), with a healthy margin. */
+	msleep(10);
 }
 
 /* Acknowledge a legacy interrupt from Falcon
@@ -1364,113 +144,17 @@
  *
  * 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)
-{
-	struct falcon_nic_data *nic_data = efx->nic_data;
-	efx_oword_t *int_ker = efx->irq_status.addr;
-	efx_oword_t fatal_intr;
-	int error, mem_perr;
-
-	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 both devices */
-	pci_clear_master(efx->pci_dev);
-	if (FALCON_IS_DUAL_FUNC(efx))
-		pci_clear_master(nic_data->pci_dev2);
-	falcon_disable_interrupts(efx);
-
-	/* Count errors and reset or disable the NIC accordingly */
-	if (nic_data->int_error_count == 0 ||
-	    time_after(jiffies, nic_data->int_error_expire)) {
-		nic_data->int_error_count = 0;
-		nic_data->int_error_expire =
-			jiffies + FALCON_INT_ERROR_EXPIRE * HZ;
-	}
-	if (++nic_data->int_error_count < 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.
- */
-static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id)
+inline void falcon_irq_ack_a1(struct efx_nic *efx)
 {
-	struct efx_nic *efx = dev_id;
-	efx_oword_t *int_ker = efx->irq_status.addr;
-	irqreturn_t result = IRQ_NONE;
-	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);
-
-	/* Schedule processing of any interrupting queues */
-	efx_for_each_channel(channel, efx) {
-		if ((queues & 1) ||
-		    falcon_event_present(
-			    falcon_event(channel, channel->eventq_read_ptr))) {
-			efx_schedule_channel(channel);
-			result = IRQ_HANDLED;
-		}
-		queues >>= 1;
-	}
-
-	if (result == IRQ_HANDLED) {
-		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));
-	}
 
-	return result;
+	EFX_POPULATE_DWORD_1(reg, FRF_AA_INT_ACK_KER_FIELD, 0xb7eb7e);
+	efx_writed(efx, &reg, FR_AA_INT_ACK_KER);
+	efx_readd(efx, &reg, FR_AA_WORK_AROUND_BROKEN_PCI_READS);
 }
 
 
-static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
+irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
 {
 	struct efx_nic *efx = dev_id;
 	efx_oword_t *int_ker = efx->irq_status.addr;
@@ -1491,15 +175,15 @@
 		  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);
+	syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
 	if (unlikely(syserr))
-		return falcon_fatal_interrupt(efx);
+		return efx_nic_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);
+	BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS);
+	queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q);
 	EFX_ZERO_OWORD(*int_ker);
 	wmb(); /* Ensure the vector is cleared before interrupt ack */
 	falcon_irq_ack_a1(efx);
@@ -1515,126 +199,6 @@
 
 	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.
- */
-static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id)
-{
-	struct efx_channel *channel = dev_id;
-	struct efx_nic *efx = channel->efx;
-	efx_oword_t *int_ker = 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;
-	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->n_rx_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(channel, efx) {
-		rc = request_irq(channel->irq, falcon_msi_interrupt,
-				 IRQF_PROBE_SHARED, /* Not shared */
-				 channel->name, channel);
-		if (rc) {
-			EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
-			goto fail2;
-		}
-	}
-
-	return 0;
-
- fail2:
-	efx_for_each_channel(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(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
@@ -1647,8 +211,8 @@
 static int falcon_spi_poll(struct efx_nic *efx)
 {
 	efx_oword_t reg;
-	falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
-	return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
+	efx_reado(efx, &reg, FR_AB_EE_SPI_HCMD);
+	return EFX_OWORD_FIELD(reg, FRF_AB_EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
 }
 
 /* Wait for SPI command completion */
@@ -1678,11 +242,10 @@
 	}
 }
 
-int falcon_spi_cmd(const struct efx_spi_device *spi,
+int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi,
 		   unsigned int command, int address,
 		   const void *in, void *out, size_t len)
 {
-	struct efx_nic *efx = spi->efx;
 	bool addressed = (address >= 0);
 	bool reading = (out != NULL);
 	efx_oword_t reg;
@@ -1700,27 +263,27 @@
 
 	/* 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);
+		EFX_POPULATE_OWORD_1(reg, FRF_AB_EE_SPI_HADR_ADR, address);
+		efx_writeo(efx, &reg, FR_AB_EE_SPI_HADR);
 	}
 
 	/* Program data register, if we have data */
 	if (in != NULL) {
 		memcpy(&reg, in, len);
-		falcon_write(efx, &reg, EE_SPI_HDATA_REG_KER);
+		efx_writeo(efx, &reg, FR_AB_EE_SPI_HDATA);
 	}
 
 	/* Issue read/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, reading,
-			     EE_SPI_HCMD_DUBCNT, 0,
-			     EE_SPI_HCMD_ADBCNT,
+			     FRF_AB_EE_SPI_HCMD_CMD_EN, 1,
+			     FRF_AB_EE_SPI_HCMD_SF_SEL, spi->device_id,
+			     FRF_AB_EE_SPI_HCMD_DABCNT, len,
+			     FRF_AB_EE_SPI_HCMD_READ, reading,
+			     FRF_AB_EE_SPI_HCMD_DUBCNT, 0,
+			     FRF_AB_EE_SPI_HCMD_ADBCNT,
 			     (addressed ? spi->addr_len : 0),
-			     EE_SPI_HCMD_ENC, command);
-	falcon_write(efx, &reg, EE_SPI_HCMD_REG_KER);
+			     FRF_AB_EE_SPI_HCMD_ENC, command);
+	efx_writeo(efx, &reg, FR_AB_EE_SPI_HCMD);
 
 	/* Wait for read/write to complete */
 	rc = falcon_spi_wait(efx);
@@ -1729,7 +292,7 @@
 
 	/* Read data */
 	if (out != NULL) {
-		falcon_read(efx, &reg, EE_SPI_HDATA_REG_KER);
+		efx_reado(efx, &reg, FR_AB_EE_SPI_HDATA);
 		memcpy(out, &reg, len);
 	}
 
@@ -1751,15 +314,15 @@
 }
 
 /* Wait up to 10 ms for buffered write completion */
-int falcon_spi_wait_write(const struct efx_spi_device *spi)
+int
+falcon_spi_wait_write(struct efx_nic *efx, const struct efx_spi_device *spi)
 {
-	struct efx_nic *efx = spi->efx;
 	unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
 	u8 status;
 	int rc;
 
 	for (;;) {
-		rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
+		rc = falcon_spi_cmd(efx, spi, SPI_RDSR, -1, NULL,
 				    &status, sizeof(status));
 		if (rc)
 			return rc;
@@ -1775,8 +338,8 @@
 	}
 }
 
-int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
-		    size_t len, size_t *retlen, u8 *buffer)
+int falcon_spi_read(struct efx_nic *efx, const struct efx_spi_device *spi,
+		    loff_t start, size_t len, size_t *retlen, u8 *buffer)
 {
 	size_t block_len, pos = 0;
 	unsigned int command;
@@ -1786,7 +349,7 @@
 		block_len = min(len - pos, FALCON_SPI_MAX_LEN);
 
 		command = efx_spi_munge_command(spi, SPI_READ, start + pos);
-		rc = falcon_spi_cmd(spi, command, start + pos, NULL,
+		rc = falcon_spi_cmd(efx, spi, command, start + pos, NULL,
 				    buffer + pos, block_len);
 		if (rc)
 			break;
@@ -1805,8 +368,9 @@
 	return rc;
 }
 
-int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
-		     size_t len, size_t *retlen, const u8 *buffer)
+int
+falcon_spi_write(struct efx_nic *efx, const struct efx_spi_device *spi,
+		 loff_t start, size_t len, size_t *retlen, const u8 *buffer)
 {
 	u8 verify_buffer[FALCON_SPI_MAX_LEN];
 	size_t block_len, pos = 0;
@@ -1814,24 +378,24 @@
 	int rc = 0;
 
 	while (pos < len) {
-		rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+		rc = falcon_spi_cmd(efx, spi, SPI_WREN, -1, NULL, NULL, 0);
 		if (rc)
 			break;
 
 		block_len = min(len - pos,
 				falcon_spi_write_limit(spi, start + pos));
 		command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
-		rc = falcon_spi_cmd(spi, command, start + pos,
+		rc = falcon_spi_cmd(efx, spi, command, start + pos,
 				    buffer + pos, NULL, block_len);
 		if (rc)
 			break;
 
-		rc = falcon_spi_wait_write(spi);
+		rc = falcon_spi_wait_write(efx, spi);
 		if (rc)
 			break;
 
 		command = efx_spi_munge_command(spi, SPI_READ, start + pos);
-		rc = falcon_spi_cmd(spi, command, start + pos,
+		rc = falcon_spi_cmd(efx, spi, command, start + pos,
 				    NULL, verify_buffer, block_len);
 		if (memcmp(verify_buffer, buffer + pos, block_len)) {
 			rc = -EIO;
@@ -1860,60 +424,70 @@
  **************************************************************************
  */
 
-static int falcon_reset_macs(struct efx_nic *efx)
+static void falcon_push_multicast_hash(struct efx_nic *efx)
 {
-	efx_oword_t reg;
+	union efx_multicast_hash *mc_hash = &efx->multicast_hash;
+
+	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+	efx_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0);
+	efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
+}
+
+static void falcon_reset_macs(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	efx_oword_t reg, mac_ctrl;
 	int count;
 
-	if (falcon_rev(efx) < FALCON_REV_B0) {
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
 		/* It's not safe to use GLB_CTL_REG to reset the
 		 * macs, so instead use the internal MAC resets
 		 */
 		if (!EFX_IS10G(efx)) {
-			EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1);
-			falcon_write(efx, &reg, GM_CFG1_REG);
+			EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 1);
+			efx_writeo(efx, &reg, FR_AB_GM_CFG1);
 			udelay(1000);
 
-			EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0);
-			falcon_write(efx, &reg, GM_CFG1_REG);
+			EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0);
+			efx_writeo(efx, &reg, FR_AB_GM_CFG1);
 			udelay(1000);
-			return 0;
+			return;
 		} else {
-			EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
-			falcon_write(efx, &reg, XM_GLB_CFG_REG);
+			EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1);
+			efx_writeo(efx, &reg, FR_AB_XM_GLB_CFG);
 
 			for (count = 0; count < 10000; count++) {
-				falcon_read(efx, &reg, XM_GLB_CFG_REG);
-				if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
-					return 0;
+				efx_reado(efx, &reg, FR_AB_XM_GLB_CFG);
+				if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) ==
+				    0)
+					return;
 				udelay(10);
 			}
 
 			EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
-			return -ETIMEDOUT;
 		}
 	}
 
-	/* MAC stats will fail whilst the TX fifo is draining. Serialise
-	 * the drain sequence with the statistics fetch */
-	efx_stats_disable(efx);
-
-	falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
-	EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
-	falcon_write(efx, &reg, MAC0_CTRL_REG_KER);
-
-	falcon_read(efx, &reg, GLB_CTL_REG_KER);
-	EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1);
-	EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1);
-	EFX_SET_OWORD_FIELD(reg, RST_EM, 1);
-	falcon_write(efx, &reg, GLB_CTL_REG_KER);
+	/* Mac stats will fail whist the TX fifo is draining */
+	WARN_ON(nic_data->stats_disable_count == 0);
+
+	efx_reado(efx, &mac_ctrl, FR_AB_MAC_CTRL);
+	EFX_SET_OWORD_FIELD(mac_ctrl, FRF_BB_TXFIFO_DRAIN_EN, 1);
+	efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
+
+	efx_reado(efx, &reg, FR_AB_GLB_CTL);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGTX, 1);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_XGRX, 1);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_RST_EM, 1);
+	efx_writeo(efx, &reg, FR_AB_GLB_CTL);
 
 	count = 0;
 	while (1) {
-		falcon_read(efx, &reg, GLB_CTL_REG_KER);
-		if (!EFX_OWORD_FIELD(reg, RST_XGTX) &&
-		    !EFX_OWORD_FIELD(reg, RST_XGRX) &&
-		    !EFX_OWORD_FIELD(reg, RST_EM)) {
+		efx_reado(efx, &reg, FR_AB_GLB_CTL);
+		if (!EFX_OWORD_FIELD(reg, FRF_AB_RST_XGTX) &&
+		    !EFX_OWORD_FIELD(reg, FRF_AB_RST_XGRX) &&
+		    !EFX_OWORD_FIELD(reg, FRF_AB_RST_EM)) {
 			EFX_LOG(efx, "Completed MAC reset after %d loops\n",
 				count);
 			break;
@@ -1926,55 +500,50 @@
 		udelay(10);
 	}
 
-	efx_stats_enable(efx);
-
-	/* 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);
-
-	return 0;
+	/* Ensure the correct MAC is selected before statistics
+	 * are re-enabled by the caller */
+	efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL);
 }
 
 void falcon_drain_tx_fifo(struct efx_nic *efx)
 {
 	efx_oword_t reg;
 
-	if ((falcon_rev(efx) < FALCON_REV_B0) ||
+	if ((efx_nic_rev(efx) < EFX_REV_FALCON_B0) ||
 	    (efx->loopback_mode != LOOPBACK_NONE))
 		return;
 
-	falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
+	efx_reado(efx, &reg, FR_AB_MAC_CTRL);
 	/* There is no point in draining more than once */
-	if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0))
+	if (EFX_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN))
 		return;
 
 	falcon_reset_macs(efx);
 }
 
-void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
+static void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
 {
 	efx_oword_t reg;
 
-	if (falcon_rev(efx) < FALCON_REV_B0)
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
 		return;
 
 	/* Isolate the MAC -> RX */
-	falcon_read(efx, &reg, RX_CFG_REG_KER);
-	EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0);
-	falcon_write(efx, &reg, RX_CFG_REG_KER);
+	efx_reado(efx, &reg, FR_AZ_RX_CFG);
+	EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 0);
+	efx_writeo(efx, &reg, FR_AZ_RX_CFG);
 
-	if (!efx->link_up)
-		falcon_drain_tx_fifo(efx);
+	/* Isolate TX -> MAC */
+	falcon_drain_tx_fifo(efx);
 }
 
 void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
 {
+	struct efx_link_state *link_state = &efx->link_state;
 	efx_oword_t reg;
 	int link_speed;
-	bool tx_fc;
 
-	switch (efx->link_speed) {
+	switch (link_state->speed) {
 	case 10000: link_speed = 3; break;
 	case 1000:  link_speed = 2; break;
 	case 100:   link_speed = 1; break;
@@ -1985,75 +554,139 @@
 	 * 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);
+			     FRF_AB_MAC_XOFF_VAL, 0xffff /* max pause time */,
+			     FRF_AB_MAC_BCAD_ACPT, 1,
+			     FRF_AB_MAC_UC_PROM, efx->promiscuous,
+			     FRF_AB_MAC_LINK_STATUS, 1, /* always set */
+			     FRF_AB_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);
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN,
+				    !link_state->up);
+	}
+
+	efx_writeo(efx, &reg, FR_AB_MAC_CTRL);
+
+	/* Restore the multicast hash registers. */
+	falcon_push_multicast_hash(efx);
+
+	efx_reado(efx, &reg, FR_AZ_RX_CFG);
+	/* Enable XOFF signal from RX FIFO (we enabled it during NIC
+	 * initialisation but it may read back as 0) */
+	EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
+	/* Unisolate the MAC -> RX */
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+	efx_writeo(efx, &reg, FR_AZ_RX_CFG);
+}
+
+static void falcon_stats_request(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	efx_oword_t reg;
+
+	WARN_ON(nic_data->stats_pending);
+	WARN_ON(nic_data->stats_disable_count);
+
+	if (nic_data->stats_dma_done == NULL)
+		return;	/* no mac selected */
+
+	*nic_data->stats_dma_done = FALCON_STATS_NOT_DONE;
+	nic_data->stats_pending = true;
+	wmb(); /* ensure done flag is clear */
+
+	/* Initiate DMA transfer of stats */
+	EFX_POPULATE_OWORD_2(reg,
+			     FRF_AB_MAC_STAT_DMA_CMD, 1,
+			     FRF_AB_MAC_STAT_DMA_ADR,
+			     efx->stats_buffer.dma_addr);
+	efx_writeo(efx, &reg, FR_AB_MAC_STAT_DMA);
+
+	mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2));
+}
+
+static void falcon_stats_complete(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
+	if (!nic_data->stats_pending)
+		return;
+
+	nic_data->stats_pending = 0;
+	if (*nic_data->stats_dma_done == FALCON_STATS_DONE) {
+		rmb(); /* read the done flag before the stats */
+		efx->mac_op->update_stats(efx);
+	} else {
+		EFX_ERR(efx, "timed out waiting for statistics\n");
 	}
+}
+
+static void falcon_stats_timer_func(unsigned long context)
+{
+	struct efx_nic *efx = (struct efx_nic *)context;
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
+	spin_lock(&efx->stats_lock);
 
-	falcon_write(efx, &reg, MAC0_CTRL_REG_KER);
+	falcon_stats_complete(efx);
+	if (nic_data->stats_disable_count == 0)
+		falcon_stats_request(efx);
 
-	/* Restore the multicast hash registers. */
-	falcon_set_multicast_hash(efx);
+	spin_unlock(&efx->stats_lock);
+}
 
-	/* 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->link_fc & EFX_FC_TX);
-	falcon_read(efx, &reg, RX_CFG_REG_KER);
-	EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
+static void falcon_switch_mac(struct efx_nic *efx);
 
-	/* 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);
+static bool falcon_loopback_link_poll(struct efx_nic *efx)
+{
+	struct efx_link_state old_state = efx->link_state;
+
+	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+	WARN_ON(!LOOPBACK_INTERNAL(efx));
+
+	efx->link_state.fd = true;
+	efx->link_state.fc = efx->wanted_fc;
+	efx->link_state.up = true;
+
+	if (efx->loopback_mode == LOOPBACK_GMAC)
+		efx->link_state.speed = 1000;
+	else
+		efx->link_state.speed = 10000;
+
+	return !efx_link_state_equal(&efx->link_state, &old_state);
 }
 
-int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
+static int falcon_reconfigure_port(struct efx_nic *efx)
 {
-	efx_oword_t reg;
-	u32 *dma_done;
-	int i;
+	int rc;
 
-	if (disable_dma_stats)
-		return 0;
+	WARN_ON(efx_nic_rev(efx) > EFX_REV_FALCON_B0);
 
-	/* 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;
-	}
+	/* Poll the PHY link state *before* reconfiguring it. This means we
+	 * will pick up the correct speed (in loopback) to select the correct
+	 * MAC.
+	 */
+	if (LOOPBACK_INTERNAL(efx))
+		falcon_loopback_link_poll(efx);
+	else
+		efx->phy_op->poll(efx);
 
-	dma_done = (efx->stats_buffer.addr + done_offset);
-	*dma_done = FALCON_STATS_NOT_DONE;
-	wmb(); /* ensure done flag is clear */
+	falcon_stop_nic_stats(efx);
+	falcon_deconfigure_mac_wrapper(efx);
 
-	/* 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);
+	falcon_switch_mac(efx);
 
-	/* Wait for transfer to complete */
-	for (i = 0; i < 400; i++) {
-		if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
-			rmb(); /* Ensure the stats are valid. */
-			return 0;
-		}
-		udelay(10);
-	}
+	efx->phy_op->reconfigure(efx);
+	rc = efx->mac_op->reconfigure(efx);
+	BUG_ON(rc);
 
-	EFX_ERR(efx, "timed out waiting for statistics\n");
-	return -ETIMEDOUT;
+	falcon_start_nic_stats(efx);
+
+	/* Synchronise efx->link_state with the kernel */
+	efx_link_status_changed(efx);
+
+	return 0;
 }
 
 /**************************************************************************
@@ -2066,18 +699,18 @@
 /* Wait for GMII access to complete */
 static int falcon_gmii_wait(struct efx_nic *efx)
 {
-	efx_dword_t md_stat;
+	efx_oword_t md_stat;
 	int count;
 
 	/* wait upto 50ms - taken max from datasheet */
 	for (count = 0; count < 5000; count++) {
-		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_reado(efx, &md_stat, FR_AB_MD_STAT);
+		if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
+			if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
+			    EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
 				EFX_ERR(efx, "error from GMII access "
-					EFX_DWORD_FMT"\n",
-					EFX_DWORD_VAL(md_stat));
+					EFX_OWORD_FMT"\n",
+					EFX_OWORD_VAL(md_stat));
 				return -EIO;
 			}
 			return 0;
@@ -2099,7 +732,7 @@
 	EFX_REGDUMP(efx, "writing MDIO %d register %d.%d with 0x%04x\n",
 		    prtad, devad, addr, value);
 
-	spin_lock_bh(&efx->phy_lock);
+	mutex_lock(&efx->mdio_lock);
 
 	/* Check MDIO not currently being accessed */
 	rc = falcon_gmii_wait(efx);
@@ -2107,34 +740,35 @@
 		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);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
+	efx_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
 
-	EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
-	falcon_write(efx, &reg, MD_ID_REG_KER);
+	EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
+			     FRF_AB_MD_DEV_ADR, devad);
+	efx_writeo(efx, &reg, FR_AB_MD_ID);
 
 	/* Write data */
-	EFX_POPULATE_OWORD_1(reg, MD_TXD, value);
-	falcon_write(efx, &reg, MD_TXD_REG_KER);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_TXD, value);
+	efx_writeo(efx, &reg, FR_AB_MD_TXD);
 
 	EFX_POPULATE_OWORD_2(reg,
-			     MD_WRC, 1,
-			     MD_GC, 0);
-	falcon_write(efx, &reg, MD_CS_REG_KER);
+			     FRF_AB_MD_WRC, 1,
+			     FRF_AB_MD_GC, 0);
+	efx_writeo(efx, &reg, FR_AB_MD_CS);
 
 	/* Wait for data to be written */
 	rc = falcon_gmii_wait(efx);
 	if (rc) {
 		/* Abort the write operation */
 		EFX_POPULATE_OWORD_2(reg,
-				     MD_WRC, 0,
-				     MD_GC, 1);
-		falcon_write(efx, &reg, MD_CS_REG_KER);
+				     FRF_AB_MD_WRC, 0,
+				     FRF_AB_MD_GC, 1);
+		efx_writeo(efx, &reg, FR_AB_MD_CS);
 		udelay(10);
 	}
 
- out:
-	spin_unlock_bh(&efx->phy_lock);
+out:
+	mutex_unlock(&efx->mdio_lock);
 	return rc;
 }
 
@@ -2146,152 +780,139 @@
 	efx_oword_t reg;
 	int rc;
 
-	spin_lock_bh(&efx->phy_lock);
+	mutex_lock(&efx->mdio_lock);
 
 	/* Check MDIO not currently being accessed */
 	rc = falcon_gmii_wait(efx);
 	if (rc)
 		goto out;
 
-	EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr);
-	falcon_write(efx, &reg, MD_PHY_ADR_REG_KER);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_MD_PHY_ADR, addr);
+	efx_writeo(efx, &reg, FR_AB_MD_PHY_ADR);
 
-	EFX_POPULATE_OWORD_2(reg, MD_PRT_ADR, prtad, MD_DEV_ADR, devad);
-	falcon_write(efx, &reg, MD_ID_REG_KER);
+	EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_PRT_ADR, prtad,
+			     FRF_AB_MD_DEV_ADR, devad);
+	efx_writeo(efx, &reg, FR_AB_MD_ID);
 
 	/* Request data to be read */
-	EFX_POPULATE_OWORD_2(reg, MD_RDC, 1, MD_GC, 0);
-	falcon_write(efx, &reg, MD_CS_REG_KER);
+	EFX_POPULATE_OWORD_2(reg, FRF_AB_MD_RDC, 1, FRF_AB_MD_GC, 0);
+	efx_writeo(efx, &reg, FR_AB_MD_CS);
 
 	/* Wait for data to become available */
 	rc = falcon_gmii_wait(efx);
 	if (rc == 0) {
-		falcon_read(efx, &reg, MD_RXD_REG_KER);
-		rc = EFX_OWORD_FIELD(reg, MD_RXD);
+		efx_reado(efx, &reg, FR_AB_MD_RXD);
+		rc = EFX_OWORD_FIELD(reg, FRF_AB_MD_RXD);
 		EFX_REGDUMP(efx, "read from MDIO %d register %d.%d, got %04x\n",
 			    prtad, devad, addr, rc);
 	} else {
 		/* Abort the read operation */
 		EFX_POPULATE_OWORD_2(reg,
-				     MD_RIC, 0,
-				     MD_GC, 1);
-		falcon_write(efx, &reg, MD_CS_REG_KER);
+				     FRF_AB_MD_RIC, 0,
+				     FRF_AB_MD_GC, 1);
+		efx_writeo(efx, &reg, FR_AB_MD_CS);
 
 		EFX_LOG(efx, "read from MDIO %d register %d.%d, got error %d\n",
 			prtad, devad, addr, rc);
 	}
 
- out:
-	spin_unlock_bh(&efx->phy_lock);
+out:
+	mutex_unlock(&efx->mdio_lock);
 	return rc;
 }
 
-static int falcon_probe_phy(struct efx_nic *efx)
+static void falcon_clock_mac(struct efx_nic *efx)
 {
-	switch (efx->phy_type) {
-	case PHY_TYPE_SFX7101:
-		efx->phy_op = &falcon_sfx7101_phy_ops;
-		break;
-	case PHY_TYPE_SFT9001A:
-	case PHY_TYPE_SFT9001B:
-		efx->phy_op = &falcon_sft9001_phy_ops;
-		break;
-	case PHY_TYPE_QT2022C2:
-	case PHY_TYPE_QT2025C:
-		efx->phy_op = &falcon_xfp_phy_ops;
-		break;
-	default:
-		EFX_ERR(efx, "Unknown PHY type %d\n",
-			efx->phy_type);
-		return -1;
-	}
-
-	if (efx->phy_op->macs & EFX_XMAC)
-		efx->loopback_modes |= ((1 << LOOPBACK_XGMII) |
-					(1 << LOOPBACK_XGXS) |
-					(1 << LOOPBACK_XAUI));
-	if (efx->phy_op->macs & EFX_GMAC)
-		efx->loopback_modes |= (1 << LOOPBACK_GMAC);
-	efx->loopback_modes |= efx->phy_op->loopbacks;
+	unsigned strap_val;
+	efx_oword_t nic_stat;
 
-	return 0;
+	/* Configure the NIC generated MAC clock correctly */
+	efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+	strap_val = EFX_IS10G(efx) ? 5 : 3;
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
+		EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
+		efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
+	} else {
+		/* Falcon A1 does not support 1G/10G speed switching
+		 * and must not be used with a PHY that does. */
+		BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
+		       strap_val);
+	}
 }
 
-int falcon_switch_mac(struct efx_nic *efx)
+static void falcon_switch_mac(struct efx_nic *efx)
 {
 	struct efx_mac_operations *old_mac_op = efx->mac_op;
-	efx_oword_t nic_stat;
-	unsigned strap_val;
-	int rc = 0;
-
-	/* Don't try to fetch MAC stats while we're switching MACs */
-	efx_stats_disable(efx);
-
-	/* Internal loopbacks override the phy speed setting */
-	if (efx->loopback_mode == LOOPBACK_GMAC) {
-		efx->link_speed = 1000;
-		efx->link_fd = true;
-	} else if (LOOPBACK_INTERNAL(efx)) {
-		efx->link_speed = 10000;
-		efx->link_fd = true;
-	}
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	unsigned int stats_done_offset;
 
 	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+	WARN_ON(nic_data->stats_disable_count == 0);
+
 	efx->mac_op = (EFX_IS10G(efx) ?
 		       &falcon_xmac_operations : &falcon_gmac_operations);
 
-	/* Always push the NIC_STAT_REG setting even if the mac hasn't
-	 * changed, because this function is run post online reset */
-	falcon_read(efx, &nic_stat, NIC_STAT_REG);
-	strap_val = EFX_IS10G(efx) ? 5 : 3;
-	if (falcon_rev(efx) >= FALCON_REV_B0) {
-		EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1);
-		EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val);
-		falcon_write(efx, &nic_stat, NIC_STAT_REG);
-	} else {
-		/* Falcon A1 does not support 1G/10G speed switching
-		 * and must not be used with a PHY that does. */
-		BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
-	}
+	if (EFX_IS10G(efx))
+		stats_done_offset = XgDmaDone_offset;
+	else
+		stats_done_offset = GDmaDone_offset;
+	nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
 
 	if (old_mac_op == efx->mac_op)
-		goto out;
+		return;
+
+	falcon_clock_mac(efx);
 
 	EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
 	/* Not all macs support a mac-level link state */
-	efx->mac_up = true;
-
-	rc = falcon_reset_macs(efx);
-out:
-	efx_stats_enable(efx);
-	return rc;
+	efx->xmac_poll_required = false;
+	falcon_reset_macs(efx);
 }
 
 /* This call is responsible for hooking in the MAC and PHY operations */
-int falcon_probe_port(struct efx_nic *efx)
+static int falcon_probe_port(struct efx_nic *efx)
 {
 	int rc;
 
-	/* Hook in PHY operations table */
-	rc = falcon_probe_phy(efx);
-	if (rc)
-		return rc;
+	switch (efx->phy_type) {
+	case PHY_TYPE_SFX7101:
+		efx->phy_op = &falcon_sfx7101_phy_ops;
+		break;
+	case PHY_TYPE_SFT9001A:
+	case PHY_TYPE_SFT9001B:
+		efx->phy_op = &falcon_sft9001_phy_ops;
+		break;
+	case PHY_TYPE_QT2022C2:
+	case PHY_TYPE_QT2025C:
+		efx->phy_op = &falcon_qt202x_phy_ops;
+		break;
+	default:
+		EFX_ERR(efx, "Unknown PHY type %d\n",
+			efx->phy_type);
+		return -ENODEV;
+	}
 
-	/* Set up MDIO structure for PHY */
-	efx->mdio.mmds = efx->phy_op->mmds;
-	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+	/* Fill out MDIO structure and loopback modes */
 	efx->mdio.mdio_read = falcon_mdio_read;
 	efx->mdio.mdio_write = falcon_mdio_write;
+	rc = efx->phy_op->probe(efx);
+	if (rc != 0)
+		return rc;
+
+	/* Initial assumption */
+	efx->link_state.speed = 10000;
+	efx->link_state.fd = true;
 
 	/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
-	if (falcon_rev(efx) >= FALCON_REV_B0)
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
 		efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
 	else
 		efx->wanted_fc = EFX_FC_RX;
 
 	/* Allocate buffer for stats */
-	rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
-				 FALCON_MAC_STATS_SIZE);
+	rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
+				  FALCON_MAC_STATS_SIZE);
 	if (rc)
 		return rc;
 	EFX_LOG(efx, "stats buffer at %llx (virt %p phys %llx)\n",
@@ -2302,40 +923,20 @@
 	return 0;
 }
 
-void falcon_remove_port(struct efx_nic *efx)
-{
-	falcon_free_buffer(efx, &efx->stats_buffer);
-}
-
-/**************************************************************************
- *
- * Multicast filtering
- *
- **************************************************************************
- */
-
-void falcon_set_multicast_hash(struct efx_nic *efx)
+static void falcon_remove_port(struct efx_nic *efx)
 {
-	union efx_multicast_hash *mc_hash = &efx->multicast_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.
-	 */
-	set_bit_le(0xff, mc_hash->byte);
-
-	falcon_write(efx, &mc_hash->oword[0], MAC_MCAST_HASH_REG0_KER);
-	falcon_write(efx, &mc_hash->oword[1], MAC_MCAST_HASH_REG1_KER);
+	efx->phy_op->remove(efx);
+	efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
-
 /**************************************************************************
  *
  * Falcon test code
  *
  **************************************************************************/
 
-int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
+static int
+falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
 {
 	struct falcon_nvconfig *nvconfig;
 	struct efx_spi_device *spi;
@@ -2351,10 +952,10 @@
 	region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
 	if (!region)
 		return -ENOMEM;
-	nvconfig = region + NVCONFIG_OFFSET;
+	nvconfig = region + FALCON_NVCONFIG_OFFSET;
 
 	mutex_lock(&efx->spi_lock);
-	rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
+	rc = falcon_spi_read(efx, spi, 0, FALCON_NVCONFIG_END, NULL, region);
 	mutex_unlock(&efx->spi_lock);
 	if (rc) {
 		EFX_ERR(efx, "Failed to read %s\n",
@@ -2367,7 +968,7 @@
 	struct_ver = le16_to_cpu(nvconfig->board_struct_ver);
 
 	rc = -EINVAL;
-	if (magic_num != NVCONFIG_BOARD_MAGIC_NUM) {
+	if (magic_num != FALCON_NVCONFIG_BOARD_MAGIC_NUM) {
 		EFX_ERR(efx, "NVRAM bad magic 0x%x\n", magic_num);
 		goto out;
 	}
@@ -2398,107 +999,54 @@
 	return rc;
 }
 
-/* Registers tested in the falcon register test */
-static struct {
-	unsigned address;
-	efx_oword_t mask;
-} efx_test_registers[] = {
-	{ ADR_REGION_REG_KER,
+static int falcon_test_nvram(struct efx_nic *efx)
+{
+	return falcon_read_nvram(efx, NULL);
+}
+
+static const struct efx_nic_register_test falcon_b0_register_tests[] = {
+	{ FR_AZ_ADR_REGION,
 	  EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) },
-	{ RX_CFG_REG_KER,
+	{ FR_AZ_RX_CFG,
 	  EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) },
-	{ TX_CFG_REG_KER,
+	{ FR_AZ_TX_CFG,
 	  EFX_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) },
-	{ TX_CFG2_REG_KER,
+	{ FR_AZ_TX_RESERVED,
 	  EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
-	{ MAC0_CTRL_REG_KER,
+	{ FR_AB_MAC_CTRL,
 	  EFX_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) },
-	{ SRM_TX_DC_CFG_REG_KER,
+	{ FR_AZ_SRM_TX_DC_CFG,
 	  EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
-	{ RX_DC_CFG_REG_KER,
+	{ FR_AZ_RX_DC_CFG,
 	  EFX_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) },
-	{ RX_DC_PF_WM_REG_KER,
+	{ FR_AZ_RX_DC_PF_WM,
 	  EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
-	{ DP_CTRL_REG,
+	{ FR_BZ_DP_CTRL,
 	  EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
-	{ GM_CFG2_REG,
+	{ FR_AB_GM_CFG2,
 	  EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
-	{ GMF_CFG0_REG,
+	{ FR_AB_GMF_CFG0,
 	  EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_GLB_CFG_REG,
+	{ FR_AB_XM_GLB_CFG,
 	  EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_TX_CFG_REG,
+	{ FR_AB_XM_TX_CFG,
 	  EFX_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_RX_CFG_REG,
+	{ FR_AB_XM_RX_CFG,
 	  EFX_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_RX_PARAM_REG,
+	{ FR_AB_XM_RX_PARAM,
 	  EFX_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_FC_REG,
+	{ FR_AB_XM_FC,
 	  EFX_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) },
-	{ XM_ADR_LO_REG,
+	{ FR_AB_XM_ADR_LO,
 	  EFX_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) },
-	{ XX_SD_CTL_REG,
+	{ FR_AB_XX_SD_CTL,
 	  EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
 };
 
-static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
-				     const efx_oword_t *mask)
-{
-	return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) ||
-		((a->u64[1] ^ b->u64[1]) & mask->u64[1]);
-}
-
-int falcon_test_registers(struct efx_nic *efx)
+static int falcon_b0_test_registers(struct efx_nic *efx)
 {
-	unsigned address = 0, i, j;
-	efx_oword_t mask, imask, original, reg, buf;
-
-	/* Falcon should be in loopback to isolate the XMAC from the PHY */
-	WARN_ON(!LOOPBACK_INTERNAL(efx));
-
-	for (i = 0; i < ARRAY_SIZE(efx_test_registers); ++i) {
-		address = efx_test_registers[i].address;
-		mask = imask = efx_test_registers[i].mask;
-		EFX_INVERT_OWORD(imask);
-
-		falcon_read(efx, &original, address);
-
-		/* bit sweep on and off */
-		for (j = 0; j < 128; j++) {
-			if (!EFX_EXTRACT_OWORD32(mask, j, j))
-				continue;
-
-			/* Test this testable bit can be set in isolation */
-			EFX_AND_OWORD(reg, original, mask);
-			EFX_SET_OWORD32(reg, j, j, 1);
-
-			falcon_write(efx, &reg, address);
-			falcon_read(efx, &buf, address);
-
-			if (efx_masked_compare_oword(&reg, &buf, &mask))
-				goto fail;
-
-			/* Test this testable bit can be cleared in isolation */
-			EFX_OR_OWORD(reg, original, mask);
-			EFX_SET_OWORD32(reg, j, j, 0);
-
-			falcon_write(efx, &reg, address);
-			falcon_read(efx, &buf, address);
-
-			if (efx_masked_compare_oword(&reg, &buf, &mask))
-				goto fail;
-		}
-
-		falcon_write(efx, &original, address);
-	}
-
-	return 0;
-
-fail:
-	EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
-		" at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
-		EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
-	return -EIO;
+	return efx_nic_test_registers(efx, falcon_b0_register_tests,
+				      ARRAY_SIZE(falcon_b0_register_tests));
 }
 
 /**************************************************************************
@@ -2510,13 +1058,13 @@
 
 /* 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)
+static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method)
 {
 	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t glb_ctl_reg_ker;
 	int rc;
 
-	EFX_LOG(efx, "performing hardware reset (%d)\n", method);
+	EFX_LOG(efx, "performing %s hardware reset\n", RESET_TYPE(method));
 
 	/* Initiate device reset */
 	if (method == RESET_TYPE_WORLD) {
@@ -2526,7 +1074,7 @@
 				"function prior to hardware reset\n");
 			goto fail1;
 		}
-		if (FALCON_IS_DUAL_FUNC(efx)) {
+		if (efx_nic_is_dual_func(efx)) {
 			rc = pci_save_state(nic_data->pci_dev2);
 			if (rc) {
 				EFX_ERR(efx, "failed to backup PCI state of "
@@ -2537,29 +1085,31 @@
 		}
 
 		EFX_POPULATE_OWORD_2(glb_ctl_reg_ker,
-				     EXT_PHY_RST_DUR, 0x7,
-				     SWRST, 1);
+				     FRF_AB_EXT_PHY_RST_DUR,
+				     FFE_AB_EXT_PHY_RST_DUR_10240US,
+				     FRF_AB_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);
+				     /* exclude PHY from "invisible" reset */
+				     FRF_AB_EXT_PHY_RST_CTL,
+				     method == RESET_TYPE_INVISIBLE,
+				     /* exclude EEPROM/flash and PCIe */
+				     FRF_AB_PCIE_CORE_RST_CTL, 1,
+				     FRF_AB_PCIE_NSTKY_RST_CTL, 1,
+				     FRF_AB_PCIE_SD_RST_CTL, 1,
+				     FRF_AB_EE_RST_CTL, 1,
+				     FRF_AB_EXT_PHY_RST_DUR,
+				     FFE_AB_EXT_PHY_RST_DUR_10240US,
+				     FRF_AB_SWRST, 1);
 	}
-	falcon_write(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER);
+	efx_writeo(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
 
 	EFX_LOG(efx, "waiting for hardware reset\n");
 	schedule_timeout_uninterruptible(HZ / 20);
 
 	/* Restore PCI configuration if needed */
 	if (method == RESET_TYPE_WORLD) {
-		if (FALCON_IS_DUAL_FUNC(efx)) {
+		if (efx_nic_is_dual_func(efx)) {
 			rc = pci_restore_state(nic_data->pci_dev2);
 			if (rc) {
 				EFX_ERR(efx, "failed to restore PCI config for "
@@ -2577,8 +1127,8 @@
 	}
 
 	/* 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) {
+	efx_reado(efx, &glb_ctl_reg_ker, FR_AB_GLB_CTL);
+	if (EFX_OWORD_FIELD(glb_ctl_reg_ker, FRF_AB_SWRST) != 0) {
 		rc = -ETIMEDOUT;
 		EFX_ERR(efx, "timed out waiting for hardware reset\n");
 		goto fail5;
@@ -2597,6 +1147,44 @@
 	return rc;
 }
 
+static void falcon_monitor(struct efx_nic *efx)
+{
+	bool link_changed;
+	int rc;
+
+	BUG_ON(!mutex_is_locked(&efx->mac_lock));
+
+	rc = falcon_board(efx)->type->monitor(efx);
+	if (rc) {
+		EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
+			(rc == -ERANGE) ? "reported fault" : "failed");
+		efx->phy_mode |= PHY_MODE_LOW_POWER;
+		rc = __efx_reconfigure_port(efx);
+		WARN_ON(rc);
+	}
+
+	if (LOOPBACK_INTERNAL(efx))
+		link_changed = falcon_loopback_link_poll(efx);
+	else
+		link_changed = efx->phy_op->poll(efx);
+
+	if (link_changed) {
+		falcon_stop_nic_stats(efx);
+		falcon_deconfigure_mac_wrapper(efx);
+
+		falcon_switch_mac(efx);
+		rc = efx->mac_op->reconfigure(efx);
+		BUG_ON(rc);
+
+		falcon_start_nic_stats(efx);
+
+		efx_link_status_changed(efx);
+	}
+
+	if (EFX_IS10G(efx))
+		falcon_poll_xmac(efx);
+}
+
 /* Zeroes out the SRAM contents.  This routine must be called in
  * process context and is allowed to sleep.
  */
@@ -2606,16 +1194,16 @@
 	int count;
 
 	/* Set the SRAM wake/sleep GPIO appropriately. */
-	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, 1);
-	falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
+	efx_reado(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
+	EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OEN, 1);
+	EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, FRF_AB_GPIO1_OUT, 1);
+	efx_writeo(efx, &gpio_cfg_reg_ker, FR_AB_GPIO_CTL);
 
 	/* Initiate SRAM reset */
 	EFX_POPULATE_OWORD_2(srm_cfg_reg_ker,
-			     SRAM_OOB_BT_INIT_EN, 1,
-			     SRM_NUM_BANKS_AND_BANK_SIZE, 0);
-	falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER);
+			     FRF_AZ_SRM_INIT_EN, 1,
+			     FRF_AZ_SRM_NB_SZ, 0);
+	efx_writeo(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
 
 	/* Wait for SRAM reset to complete */
 	count = 0;
@@ -2626,8 +1214,8 @@
 		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_reado(efx, &srm_cfg_reg_ker, FR_AZ_SRM_CFG);
+		if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, FRF_AZ_SRM_INIT_EN)) {
 			EFX_LOG(efx, "SRAM reset complete\n");
 
 			return 0;
@@ -2663,8 +1251,6 @@
 		spi_device->block_size =
 			1 << SPI_DEV_TYPE_FIELD(device_type,
 						SPI_DEV_TYPE_BLOCK_SIZE);
-
-		spi_device->efx = efx;
 	} else {
 		spi_device = NULL;
 	}
@@ -2674,7 +1260,6 @@
 	return 0;
 }
 
-
 static void falcon_remove_spi_devices(struct efx_nic *efx)
 {
 	kfree(efx->spi_eeprom);
@@ -2712,16 +1297,16 @@
 		board_rev = le16_to_cpu(v2->board_revision);
 
 		if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
-			__le32 fl = v3->spi_device_type[EE_SPI_FLASH];
-			__le32 ee = v3->spi_device_type[EE_SPI_EEPROM];
-			rc = falcon_spi_device_init(efx, &efx->spi_flash,
-						    EE_SPI_FLASH,
-						    le32_to_cpu(fl));
+			rc = falcon_spi_device_init(
+				efx, &efx->spi_flash, FFE_AB_SPI_DEVICE_FLASH,
+				le32_to_cpu(v3->spi_device_type
+					    [FFE_AB_SPI_DEVICE_FLASH]));
 			if (rc)
 				goto fail2;
-			rc = falcon_spi_device_init(efx, &efx->spi_eeprom,
-						    EE_SPI_EEPROM,
-						    le32_to_cpu(ee));
+			rc = falcon_spi_device_init(
+				efx, &efx->spi_eeprom, FFE_AB_SPI_DEVICE_EEPROM,
+				le32_to_cpu(v3->spi_device_type
+					    [FFE_AB_SPI_DEVICE_EEPROM]));
 			if (rc)
 				goto fail2;
 		}
@@ -2732,7 +1317,9 @@
 
 	EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mdio.prtad);
 
-	efx_set_board_info(efx, board_rev);
+	rc = falcon_probe_board(efx, board_rev);
+	if (rc)
+		goto fail2;
 
 	kfree(nvconfig);
 	return 0;
@@ -2744,89 +1331,49 @@
 	return rc;
 }
 
-/* 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;
-	efx_oword_t nic_stat;
-
-	falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
-	if (EFX_OWORD_FIELD(altera_build, VER_ALL)) {
-		EFX_ERR(efx, "Falcon FPGA not supported\n");
-		return -ENODEV;
-	}
-
-	falcon_read(efx, &nic_stat, NIC_STAT_REG);
-
-	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:
-		if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
-			EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
-			return -ENODEV;
-		}
-		break;
-
-	case FALCON_REV_B0:
-		break;
-
-	default:
-		EFX_ERR(efx, "Unknown Falcon rev %d\n", falcon_rev(efx));
-		return -ENODEV;
-	}
-
-	/* Initial assumed speed */
-	efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000;
-
-	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;
 	int boot_dev;
 
-	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);
-
-	if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) {
-		boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ?
-			    EE_SPI_FLASH : EE_SPI_EEPROM);
+	efx_reado(efx, &gpio_ctl, FR_AB_GPIO_CTL);
+	efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+	efx_reado(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
+
+	if (EFX_OWORD_FIELD(gpio_ctl, FRF_AB_GPIO3_PWRUP_VALUE)) {
+		boot_dev = (EFX_OWORD_FIELD(nic_stat, FRF_AB_SF_PRST) ?
+			    FFE_AB_SPI_DEVICE_FLASH : FFE_AB_SPI_DEVICE_EEPROM);
 		EFX_LOG(efx, "Booted from %s\n",
-			boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM");
+			boot_dev == FFE_AB_SPI_DEVICE_FLASH ? "flash" : "EEPROM");
 	} else {
 		/* Disable VPD and set clock dividers to safe
 		 * values for initial programming. */
 		boot_dev = -1;
 		EFX_LOG(efx, "Booted from internal ASIC settings;"
 			" setting SPI config\n");
-		EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
+		EFX_POPULATE_OWORD_3(ee_vpd_cfg, FRF_AB_EE_VPD_EN, 0,
 				     /* 125 MHz / 7 ~= 20 MHz */
-				     EE_SF_CLOCK_DIV, 7,
+				     FRF_AB_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);
+				     FRF_AB_EE_EE_CLOCK_DIV, 63);
+		efx_writeo(efx, &ee_vpd_cfg, FR_AB_EE_VPD_CFG0);
 	}
 
-	if (boot_dev == EE_SPI_FLASH)
-		falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH,
+	if (boot_dev == FFE_AB_SPI_DEVICE_FLASH)
+		falcon_spi_device_init(efx, &efx->spi_flash,
+				       FFE_AB_SPI_DEVICE_FLASH,
 				       default_flash_type);
-	if (boot_dev == EE_SPI_EEPROM)
-		falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM,
+	if (boot_dev == FFE_AB_SPI_DEVICE_EEPROM)
+		falcon_spi_device_init(efx, &efx->spi_eeprom,
+				       FFE_AB_SPI_DEVICE_EEPROM,
 				       large_eeprom_type);
 }
 
-int falcon_probe_nic(struct efx_nic *efx)
+static int falcon_probe_nic(struct efx_nic *efx)
 {
 	struct falcon_nic_data *nic_data;
+	struct falcon_board *board;
 	int rc;
 
 	/* Allocate storage for hardware specific data */
@@ -2835,15 +1382,33 @@
 		return -ENOMEM;
 	efx->nic_data = nic_data;
 
-	/* Determine number of ports etc. */
-	rc = falcon_probe_nic_variant(efx);
-	if (rc)
+	rc = -ENODEV;
+
+	if (efx_nic_fpga_ver(efx) != 0) {
+		EFX_ERR(efx, "Falcon FPGA not supported\n");
 		goto fail1;
+	}
 
-	/* Probe secondary function if expected */
-	if (FALCON_IS_DUAL_FUNC(efx)) {
-		struct pci_dev *dev = pci_dev_get(efx->pci_dev);
+	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
+		efx_oword_t nic_stat;
+		struct pci_dev *dev;
+		u8 pci_rev = efx->pci_dev->revision;
+
+		if ((pci_rev == 0xff) || (pci_rev == 0)) {
+			EFX_ERR(efx, "Falcon rev A0 not supported\n");
+			goto fail1;
+		}
+		efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+		if (EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_10G) == 0) {
+			EFX_ERR(efx, "Falcon rev A1 1G not supported\n");
+			goto fail1;
+		}
+		if (EFX_OWORD_FIELD(nic_stat, FRF_AA_STRAP_PCIE) == 0) {
+			EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
+			goto fail1;
+		}
 
+		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 &&
@@ -2867,7 +1432,7 @@
 	}
 
 	/* Allocate memory for INT_KER */
-	rc = falcon_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
+	rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
 	if (rc)
 		goto fail4;
 	BUG_ON(efx->irq_status.dma_addr & 0x0f);
@@ -2884,21 +1449,36 @@
 		goto fail5;
 
 	/* Initialise I2C adapter */
-	efx->i2c_adap.owner = THIS_MODULE;
-	nic_data->i2c_data = falcon_i2c_bit_operations;
-	nic_data->i2c_data.data = efx;
-	efx->i2c_adap.algo_data = &nic_data->i2c_data;
-	efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
-	strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
-	rc = i2c_bit_add_bus(&efx->i2c_adap);
+	board = falcon_board(efx);
+	board->i2c_adap.owner = THIS_MODULE;
+	board->i2c_data = falcon_i2c_bit_operations;
+	board->i2c_data.data = efx;
+	board->i2c_adap.algo_data = &board->i2c_data;
+	board->i2c_adap.dev.parent = &efx->pci_dev->dev;
+	strlcpy(board->i2c_adap.name, "SFC4000 GPIO",
+		sizeof(board->i2c_adap.name));
+	rc = i2c_bit_add_bus(&board->i2c_adap);
 	if (rc)
 		goto fail5;
 
+	rc = falcon_board(efx)->type->init(efx);
+	if (rc) {
+		EFX_ERR(efx, "failed to initialise board\n");
+		goto fail6;
+	}
+
+	nic_data->stats_disable_count = 1;
+	setup_timer(&nic_data->stats_timer, &falcon_stats_timer_func,
+		    (unsigned long)efx);
+
 	return 0;
 
+ fail6:
+	BUG_ON(i2c_del_adapter(&board->i2c_adap));
+	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
  fail5:
 	falcon_remove_spi_devices(efx);
-	falcon_free_buffer(efx, &efx->irq_status);
+	efx_nic_free_buffer(efx, &efx->irq_status);
  fail4:
  fail3:
 	if (nic_data->pci_dev2) {
@@ -2911,166 +1491,147 @@
 	return rc;
 }
 
+static void falcon_init_rx_cfg(struct efx_nic *efx)
+{
+	/* Prior to Siena the RX DMA engine will split each frame at
+	 * intervals of RX_USR_BUF_SIZE (32-byte units). We set it to
+	 * be so large that that never happens. */
+	const unsigned huge_buf_size = (3 * 4096) >> 5;
+	/* RX control FIFO thresholds (32 entries) */
+	const unsigned ctrl_xon_thr = 20;
+	const unsigned ctrl_xoff_thr = 25;
+	/* RX data FIFO thresholds (256-byte units; size varies) */
+	int data_xon_thr = efx_nic_rx_xon_thresh >> 8;
+	int data_xoff_thr = efx_nic_rx_xoff_thresh >> 8;
+	efx_oword_t reg;
+
+	efx_reado(efx, &reg, FR_AZ_RX_CFG);
+	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
+		/* Data FIFO size is 5.5K */
+		if (data_xon_thr < 0)
+			data_xon_thr = 512 >> 8;
+		if (data_xoff_thr < 0)
+			data_xoff_thr = 2048 >> 8;
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_DESC_PUSH_EN, 0);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_USR_BUF_SIZE,
+				    huge_buf_size);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, data_xon_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, data_xoff_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_TX_TH, ctrl_xon_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_TX_TH, ctrl_xoff_thr);
+	} else {
+		/* Data FIFO size is 80K; register fields moved */
+		if (data_xon_thr < 0)
+			data_xon_thr = 27648 >> 8; /* ~3*max MTU */
+		if (data_xoff_thr < 0)
+			data_xoff_thr = 54272 >> 8; /* ~80Kb - 3*max MTU */
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_DESC_PUSH_EN, 0);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_USR_BUF_SIZE,
+				    huge_buf_size);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, data_xon_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, data_xoff_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
+	}
+	/* Always enable XOFF signal from RX FIFO.  We enable
+	 * or disable transmission of pause frames at the MAC. */
+	EFX_SET_OWORD_FIELD(reg, FRF_AZ_RX_XOFF_MAC_EN, 1);
+	efx_writeo(efx, &reg, FR_AZ_RX_CFG);
+}
+
 /* 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)
+static int falcon_init_nic(struct efx_nic *efx)
 {
 	efx_oword_t temp;
-	unsigned thresh;
 	int rc;
 
 	/* Use on-chip SRAM */
-	falcon_read(efx, &temp, NIC_STAT_REG);
-	EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
-	falcon_write(efx, &temp, NIC_STAT_REG);
+	efx_reado(efx, &temp, FR_AB_NIC_STAT);
+	EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1);
+	efx_writeo(efx, &temp, FR_AB_NIC_STAT);
 
 	/* Set the source of the GMAC clock */
-	if (falcon_rev(efx) == FALCON_REV_B0) {
-		falcon_read(efx, &temp, GPIO_CTL_REG_KER);
-		EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true);
-		falcon_write(efx, &temp, GPIO_CTL_REG_KER);
+	if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) {
+		efx_reado(efx, &temp, FR_AB_GPIO_CTL);
+		EFX_SET_OWORD_FIELD(temp, FRF_AB_USE_NIC_CLK, true);
+		efx_writeo(efx, &temp, FR_AB_GPIO_CTL);
 	}
 
-	/* 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);
+	/* Select the correct MAC */
+	falcon_clock_mac(efx);
 
 	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, TX_DC_BASE / 8);
-	falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER);
-	EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, RX_DC_BASE / 8);
-	falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER);
-
-	/* Set TX descriptor cache size. */
-	BUILD_BUG_ON(TX_DC_ENTRIES != (16 << TX_DC_ENTRIES_ORDER));
-	EFX_POPULATE_OWORD_1(temp, TX_DC_SIZE, TX_DC_ENTRIES_ORDER);
-	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.
-	 */
-	BUILD_BUG_ON(RX_DC_ENTRIES != (16 << RX_DC_ENTRIES_ORDER));
-	EFX_POPULATE_OWORD_1(temp, RX_DC_SIZE, RX_DC_ENTRIES_ORDER);
-	falcon_write(efx, &temp, RX_DC_CFG_REG_KER);
-	EFX_POPULATE_OWORD_1(temp, RX_DC_PF_LWM, 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);
+		efx_reado(efx, &temp, FR_AZ_CSR_SPARE);
+		EFX_SET_OWORD_FIELD(temp, FRF_AB_MEM_PERR_EN_TX_DATA, 0);
+		efx_writeo(efx, &temp, FR_AZ_CSR_SPARE);
 	}
 
-	/* 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);
-
 	if (EFX_WORKAROUND_7244(efx)) {
-		falcon_read(efx, &temp, RX_FILTER_CTL_REG);
-		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);
+		efx_reado(efx, &temp, FR_BZ_RX_FILTER_CTL);
+		EFX_SET_OWORD_FIELD(temp, FRF_BZ_UDP_FULL_SRCH_LIMIT, 8);
+		EFX_SET_OWORD_FIELD(temp, FRF_BZ_UDP_WILD_SRCH_LIMIT, 8);
+		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TCP_FULL_SRCH_LIMIT, 8);
+		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TCP_WILD_SRCH_LIMIT, 8);
+		efx_writeo(efx, &temp, FR_BZ_RX_FILTER_CTL);
 	}
 
-	falcon_setup_rss_indir_table(efx);
-
+	/* XXX This is documented only for Falcon A0/A1 */
 	/* 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);
+	efx_reado(efx, &temp, FR_AA_RX_SELF_RST);
+	EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_NODESC_WAIT_DIS, 1);
+	EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_SELF_RST_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);
-	/* 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);
+		EFX_SET_OWORD_FIELD(temp, FRF_AA_RX_ISCSI_DIS, 1);
+	efx_writeo(efx, &temp, FR_AA_RX_SELF_RST);
 
 	/* 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, 20);
-	EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 25);
-	falcon_write(efx, &temp, RX_CFG_REG_KER);
+	efx_reado(efx, &temp, FR_AZ_TX_CFG);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
+	efx_writeo(efx, &temp, FR_AZ_TX_CFG);
+
+	falcon_init_rx_cfg(efx);
 
 	/* 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);
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
+		efx_writeo(efx, &temp, FR_BZ_DP_CTRL);
 	}
 
+	efx_nic_init_common(efx);
+
 	return 0;
 }
 
-void falcon_remove_nic(struct efx_nic *efx)
+static void falcon_remove_nic(struct efx_nic *efx)
 {
 	struct falcon_nic_data *nic_data = efx->nic_data;
+	struct falcon_board *board = falcon_board(efx);
 	int rc;
 
+	board->type->fini(efx);
+
 	/* Remove I2C adapter and clear it in preparation for a retry */
-	rc = i2c_del_adapter(&efx->i2c_adap);
+	rc = i2c_del_adapter(&board->i2c_adap);
 	BUG_ON(rc);
-	memset(&efx->i2c_adap, 0, sizeof(efx->i2c_adap));
+	memset(&board->i2c_adap, 0, sizeof(board->i2c_adap));
 
 	falcon_remove_spi_devices(efx);
-	falcon_free_buffer(efx, &efx->irq_status);
+	efx_nic_free_buffer(efx, &efx->irq_status);
 
 	falcon_reset_hw(efx, RESET_TYPE_ALL);
 
@@ -3085,12 +1646,86 @@
 	efx->nic_data = NULL;
 }
 
-void falcon_update_nic_stats(struct efx_nic *efx)
+static void falcon_update_nic_stats(struct efx_nic *efx)
 {
+	struct falcon_nic_data *nic_data = efx->nic_data;
 	efx_oword_t cnt;
 
-	falcon_read(efx, &cnt, RX_NODESC_DROP_REG_KER);
-	efx->n_rx_nodesc_drop_cnt += EFX_OWORD_FIELD(cnt, RX_NODESC_DROP_CNT);
+	if (nic_data->stats_disable_count)
+		return;
+
+	efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
+	efx->n_rx_nodesc_drop_cnt +=
+		EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);
+
+	if (nic_data->stats_pending &&
+	    *nic_data->stats_dma_done == FALCON_STATS_DONE) {
+		nic_data->stats_pending = false;
+		rmb(); /* read the done flag before the stats */
+		efx->mac_op->update_stats(efx);
+	}
+}
+
+void falcon_start_nic_stats(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+
+	spin_lock_bh(&efx->stats_lock);
+	if (--nic_data->stats_disable_count == 0)
+		falcon_stats_request(efx);
+	spin_unlock_bh(&efx->stats_lock);
+}
+
+void falcon_stop_nic_stats(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	int i;
+
+	might_sleep();
+
+	spin_lock_bh(&efx->stats_lock);
+	++nic_data->stats_disable_count;
+	spin_unlock_bh(&efx->stats_lock);
+
+	del_timer_sync(&nic_data->stats_timer);
+
+	/* Wait enough time for the most recent transfer to
+	 * complete. */
+	for (i = 0; i < 4 && nic_data->stats_pending; i++) {
+		if (*nic_data->stats_dma_done == FALCON_STATS_DONE)
+			break;
+		msleep(1);
+	}
+
+	spin_lock_bh(&efx->stats_lock);
+	falcon_stats_complete(efx);
+	spin_unlock_bh(&efx->stats_lock);
+}
+
+static void falcon_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+	falcon_board(efx)->type->set_id_led(efx, mode);
+}
+
+/**************************************************************************
+ *
+ * Wake on LAN
+ *
+ **************************************************************************
+ */
+
+static void falcon_get_wol(struct efx_nic *efx, struct ethtool_wolinfo *wol)
+{
+	wol->supported = 0;
+	wol->wolopts = 0;
+	memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int falcon_set_wol(struct efx_nic *efx, u32 type)
+{
+	if (type != 0)
+		return -EINVAL;
+	return 0;
 }
 
 /**************************************************************************
@@ -3100,50 +1735,91 @@
  **************************************************************************
  */
 
-struct efx_nic_type falcon_a_nic_type = {
-	.mem_bar = 2,
+struct efx_nic_type falcon_a1_nic_type = {
+	.probe = falcon_probe_nic,
+	.remove = falcon_remove_nic,
+	.init = falcon_init_nic,
+	.fini = efx_port_dummy_op_void,
+	.monitor = falcon_monitor,
+	.reset = falcon_reset_hw,
+	.probe_port = falcon_probe_port,
+	.remove_port = falcon_remove_port,
+	.prepare_flush = falcon_prepare_flush,
+	.update_stats = falcon_update_nic_stats,
+	.start_stats = falcon_start_nic_stats,
+	.stop_stats = falcon_stop_nic_stats,
+	.set_id_led = falcon_set_id_led,
+	.push_irq_moderation = falcon_push_irq_moderation,
+	.push_multicast_hash = falcon_push_multicast_hash,
+	.reconfigure_port = falcon_reconfigure_port,
+	.get_wol = falcon_get_wol,
+	.set_wol = falcon_set_wol,
+	.resume_wol = efx_port_dummy_op_void,
+	.test_nvram = falcon_test_nvram,
+	.default_mac_ops = &falcon_xmac_operations,
+
+	.revision = EFX_REV_FALCON_A1,
 	.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,
+	.txd_ptr_tbl_base = FR_AA_TX_DESC_PTR_TBL_KER,
+	.rxd_ptr_tbl_base = FR_AA_RX_DESC_PTR_TBL_KER,
+	.buf_tbl_base = FR_AA_BUF_FULL_TBL_KER,
+	.evq_ptr_tbl_base = FR_AA_EVQ_PTR_TBL_KER,
+	.evq_rptr_tbl_base = FR_AA_EVQ_RPTR_KER,
+	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
 	.rx_buffer_padding = 0x24,
 	.max_interrupt_mode = EFX_INT_MODE_MSI,
 	.phys_addr_channels = 4,
+	.tx_dc_base = 0x130000,
+	.rx_dc_base = 0x100000,
+	.offload_features = NETIF_F_IP_CSUM,
+	.reset_world_flags = ETH_RESET_IRQ,
 };
 
-struct efx_nic_type falcon_b_nic_type = {
-	.mem_bar = 2,
+struct efx_nic_type falcon_b0_nic_type = {
+	.probe = falcon_probe_nic,
+	.remove = falcon_remove_nic,
+	.init = falcon_init_nic,
+	.fini = efx_port_dummy_op_void,
+	.monitor = falcon_monitor,
+	.reset = falcon_reset_hw,
+	.probe_port = falcon_probe_port,
+	.remove_port = falcon_remove_port,
+	.prepare_flush = falcon_prepare_flush,
+	.update_stats = falcon_update_nic_stats,
+	.start_stats = falcon_start_nic_stats,
+	.stop_stats = falcon_stop_nic_stats,
+	.set_id_led = falcon_set_id_led,
+	.push_irq_moderation = falcon_push_irq_moderation,
+	.push_multicast_hash = falcon_push_multicast_hash,
+	.reconfigure_port = falcon_reconfigure_port,
+	.get_wol = falcon_get_wol,
+	.set_wol = falcon_set_wol,
+	.resume_wol = efx_port_dummy_op_void,
+	.test_registers = falcon_b0_test_registers,
+	.test_nvram = falcon_test_nvram,
+	.default_mac_ops = &falcon_xmac_operations,
+
+	.revision = EFX_REV_FALCON_B0,
 	/* 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 */
+	.mem_map_size = (FR_BZ_RX_INDIRECTION_TBL +
+			 FR_BZ_RX_INDIRECTION_TBL_STEP *
+			 FR_BZ_RX_INDIRECTION_TBL_ROWS),
+	.txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
+	.rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
+	.buf_tbl_base = FR_BZ_BUF_FULL_TBL,
+	.evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
+	.evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
+	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
 	.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 */
+	.tx_dc_base = 0x130000,
+	.rx_dc_base = 0x100000,
+	.offload_features = NETIF_F_IP_CSUM,
+	.reset_world_flags = ETH_RESET_IRQ,
 };
 
--- linux-ec2-2.6.32.orig/drivers/net/sfc/qt202x_phy.c
+++ linux-ec2-2.6.32/drivers/net/sfc/qt202x_phy.c
@@ -0,0 +1,448 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+/*
+ * Driver for AMCC QT202x SFP+ and XFP adapters; see www.amcc.com for details
+ */
+
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include "efx.h"
+#include "mdio_10g.h"
+#include "phy.h"
+#include "nic.h"
+
+#define QT202X_REQUIRED_DEVS (MDIO_DEVS_PCS |		\
+			      MDIO_DEVS_PMAPMD |	\
+			      MDIO_DEVS_PHYXS)
+
+#define QT202X_LOOPBACKS ((1 << LOOPBACK_PCS) |		\
+			  (1 << LOOPBACK_PMAPMD) |	\
+			  (1 << LOOPBACK_PHYXS_WS))
+
+/****************************************************************************/
+/* Quake-specific MDIO registers */
+#define MDIO_QUAKE_LED0_REG	(0xD006)
+
+/* QT2025C only */
+#define PCS_FW_HEARTBEAT_REG	0xd7ee
+#define PCS_FW_HEARTB_LBN	0
+#define PCS_FW_HEARTB_WIDTH	8
+#define PCS_FW_PRODUCT_CODE_1	0xd7f0
+#define PCS_FW_VERSION_1	0xd7f3
+#define PCS_FW_BUILD_1		0xd7f6
+#define PCS_UC8051_STATUS_REG	0xd7fd
+#define PCS_UC_STATUS_LBN	0
+#define PCS_UC_STATUS_WIDTH	8
+#define PCS_UC_STATUS_FW_SAVE	0x20
+#define PMA_PMD_FTX_CTRL2_REG	0xc309
+#define PMA_PMD_FTX_STATIC_LBN	13
+#define PMA_PMD_VEND1_REG	0xc001
+#define PMA_PMD_VEND1_LBTXD_LBN	15
+#define PCS_VEND1_REG	   	0xc000
+#define PCS_VEND1_LBTXD_LBN	5
+
+void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode)
+{
+	int addr = MDIO_QUAKE_LED0_REG + led;
+	efx_mdio_write(p, MDIO_MMD_PMAPMD, addr, mode);
+}
+
+struct qt202x_phy_data {
+	enum efx_phy_mode phy_mode;
+	bool bug17190_in_bad_state;
+	unsigned long bug17190_timer;
+	u32 firmware_ver;
+};
+
+#define QT2022C2_MAX_RESET_TIME 500
+#define QT2022C2_RESET_WAIT 10
+
+#define QT2025C_MAX_HEARTB_TIME (5 * HZ)
+#define QT2025C_HEARTB_WAIT 100
+#define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10)
+#define QT2025C_FWSTART_WAIT 100
+
+#define BUG17190_INTERVAL (2 * HZ)
+
+static int qt2025c_wait_heartbeat(struct efx_nic *efx)
+{
+	unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME;
+	int reg, old_counter = 0;
+
+	/* Wait for firmware heartbeat to start */
+	for (;;) {
+		int counter;
+		reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_FW_HEARTBEAT_REG);
+		if (reg < 0)
+			return reg;
+		counter = ((reg >> PCS_FW_HEARTB_LBN) &
+			    ((1 << PCS_FW_HEARTB_WIDTH) - 1));
+		if (old_counter == 0)
+			old_counter = counter;
+		else if (counter != old_counter)
+			break;
+		if (time_after(jiffies, timeout)) {
+			/* Some cables have EEPROMs that conflict with the
+			 * PHY's on-board EEPROM so it cannot load firmware */
+			EFX_ERR(efx, "If an SFP+ direct attach cable is"
+				" connected, please check that it complies"
+				" with the SFP+ specification\n");
+			return -ETIMEDOUT;
+		}
+		msleep(QT2025C_HEARTB_WAIT);
+	}
+
+	return 0;
+}
+
+static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
+{
+	unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME;
+	int reg;
+
+	/* Wait for firmware status to look good */
+	for (;;) {
+		reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
+		if (reg < 0)
+			return reg;
+		if ((reg &
+		     ((1 << PCS_UC_STATUS_WIDTH) - 1) << PCS_UC_STATUS_LBN) >=
+		    PCS_UC_STATUS_FW_SAVE)
+			break;
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		msleep(QT2025C_FWSTART_WAIT);
+	}
+
+	return 0;
+}
+
+static void qt2025c_restart_firmware(struct efx_nic *efx)
+{
+	/* Restart microcontroller execution of firmware from RAM */
+	efx_mdio_write(efx, 3, 0xe854, 0x00c0);
+	efx_mdio_write(efx, 3, 0xe854, 0x0040);
+	msleep(50);
+}
+
+static int qt2025c_wait_reset(struct efx_nic *efx)
+{
+	int rc;
+
+	rc = qt2025c_wait_heartbeat(efx);
+	if (rc != 0)
+		return rc;
+
+	rc = qt2025c_wait_fw_status_good(efx);
+	if (rc == -ETIMEDOUT) {
+		/* Bug 17689: occasionally heartbeat starts but firmware status
+		 * code never progresses beyond 0x00.  Try again, once, after
+		 * restarting execution of the firmware image. */
+		EFX_LOG(efx, "bashing QT2025C microcontroller\n");
+		qt2025c_restart_firmware(efx);
+		rc = qt2025c_wait_heartbeat(efx);
+		if (rc != 0)
+			return rc;
+		rc = qt2025c_wait_fw_status_good(efx);
+	}
+
+	return rc;
+}
+
+static void qt2025c_firmware_id(struct efx_nic *efx)
+{
+	struct qt202x_phy_data *phy_data = efx->phy_data;
+	u8 firmware_id[9];
+	size_t i;
+
+	for (i = 0; i < sizeof(firmware_id); i++)
+		firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS,
+					       PCS_FW_PRODUCT_CODE_1 + i);
+	EFX_INFO(efx, "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n",
+		 (firmware_id[0] << 8) | firmware_id[1], firmware_id[2],
+		 firmware_id[3] >> 4, firmware_id[3] & 0xf,
+		 firmware_id[4], firmware_id[5],
+		 firmware_id[6], firmware_id[7], firmware_id[8]);
+	phy_data->firmware_ver = ((firmware_id[3] & 0xf0) << 20) |
+				 ((firmware_id[3] & 0x0f) << 16) |
+				 (firmware_id[4] << 8) | firmware_id[5];
+}
+
+static void qt2025c_bug17190_workaround(struct efx_nic *efx)
+{
+	struct qt202x_phy_data *phy_data = efx->phy_data;
+
+	/* The PHY can get stuck in a state where it reports PHY_XS and PMA/PMD
+	 * layers up, but PCS down (no block_lock).  If we notice this state
+	 * persisting for a couple of seconds, we switch PMA/PMD loopback
+	 * briefly on and then off again, which is normally sufficient to
+	 * recover it.
+	 */
+	if (efx->link_state.up ||
+	    !efx_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) {
+		phy_data->bug17190_in_bad_state = false;
+		return;
+	}
+
+	if (!phy_data->bug17190_in_bad_state) {
+		phy_data->bug17190_in_bad_state = true;
+		phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL;
+		return;
+	}
+
+	if (time_after_eq(jiffies, phy_data->bug17190_timer)) {
+		EFX_LOG(efx, "bashing QT2025C PMA/PMD\n");
+		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+				  MDIO_PMA_CTRL1_LOOPBACK, true);
+		msleep(100);
+		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+				  MDIO_PMA_CTRL1_LOOPBACK, false);
+		phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL;
+	}
+}
+
+static int qt2025c_select_phy_mode(struct efx_nic *efx)
+{
+	struct qt202x_phy_data *phy_data = efx->phy_data;
+	struct falcon_board *board = falcon_board(efx);
+	int reg, rc, i;
+	uint16_t phy_op_mode;
+
+	/* Only 2.0.1.0+ PHY firmware supports the more optimal SFP+
+	 * Self-Configure mode.  Don't attempt any switching if we encounter
+	 * older firmware. */
+	if (phy_data->firmware_ver < 0x02000100)
+		return 0;
+
+	/* In general we will get optimal behaviour in "SFP+ Self-Configure"
+	 * mode; however, that powers down most of the PHY when no module is
+	 * present, so we must use a different mode (any fixed mode will do)
+	 * to be sure that loopbacks will work. */
+	phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020;
+
+	/* Only change mode if really necessary */
+	reg = efx_mdio_read(efx, 1, 0xc319);
+	if ((reg & 0x0038) == phy_op_mode)
+		return 0;
+	EFX_LOG(efx, "Switching PHY to mode 0x%04x\n", phy_op_mode);
+
+	/* This sequence replicates the register writes configured in the boot
+	 * EEPROM (including the differences between board revisions), except
+	 * that the operating mode is changed, and the PHY is prevented from
+	 * unnecessarily reloading the main firmware image again. */
+	efx_mdio_write(efx, 1, 0xc300, 0x0000);
+	/* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9
+	 * STOPs onto the firmware/module I2C bus to reset it, varies across
+	 * board revisions, as the bus is connected to different GPIO/LED
+	 * outputs on the PHY.) */
+	if (board->major == 0 && board->minor < 2) {
+		efx_mdio_write(efx, 1, 0xc303, 0x4498);
+		for (i = 0; i < 9; i++) {
+			efx_mdio_write(efx, 1, 0xc303, 0x4488);
+			efx_mdio_write(efx, 1, 0xc303, 0x4480);
+			efx_mdio_write(efx, 1, 0xc303, 0x4490);
+			efx_mdio_write(efx, 1, 0xc303, 0x4498);
+		}
+	} else {
+		efx_mdio_write(efx, 1, 0xc303, 0x0920);
+		efx_mdio_write(efx, 1, 0xd008, 0x0004);
+		for (i = 0; i < 9; i++) {
+			efx_mdio_write(efx, 1, 0xc303, 0x0900);
+			efx_mdio_write(efx, 1, 0xd008, 0x0005);
+			efx_mdio_write(efx, 1, 0xc303, 0x0920);
+			efx_mdio_write(efx, 1, 0xd008, 0x0004);
+		}
+		efx_mdio_write(efx, 1, 0xc303, 0x4900);
+	}
+	efx_mdio_write(efx, 1, 0xc303, 0x4900);
+	efx_mdio_write(efx, 1, 0xc302, 0x0004);
+	efx_mdio_write(efx, 1, 0xc316, 0x0013);
+	efx_mdio_write(efx, 1, 0xc318, 0x0054);
+	efx_mdio_write(efx, 1, 0xc319, phy_op_mode);
+	efx_mdio_write(efx, 1, 0xc31a, 0x0098);
+	efx_mdio_write(efx, 3, 0x0026, 0x0e00);
+	efx_mdio_write(efx, 3, 0x0027, 0x0013);
+	efx_mdio_write(efx, 3, 0x0028, 0xa528);
+	efx_mdio_write(efx, 1, 0xd006, 0x000a);
+	efx_mdio_write(efx, 1, 0xd007, 0x0009);
+	efx_mdio_write(efx, 1, 0xd008, 0x0004);
+	/* This additional write is not present in the boot EEPROM.  It
+	 * prevents the PHY's internal boot ROM doing another pointless (and
+	 * slow) reload of the firmware image (the microcontroller's code
+	 * memory is not affected by the microcontroller reset). */
+	efx_mdio_write(efx, 1, 0xc317, 0x00ff);
+	efx_mdio_write(efx, 1, 0xc300, 0x0002);
+	msleep(20);
+
+	/* Restart microcontroller execution of firmware from RAM */
+	qt2025c_restart_firmware(efx);
+
+	/* Wait for the microcontroller to be ready again */
+	rc = qt2025c_wait_reset(efx);
+	if (rc < 0) {
+		EFX_ERR(efx, "PHY microcontroller reset during mode switch "
+				"timed out\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+static int qt202x_reset_phy(struct efx_nic *efx)
+{
+	int rc;
+
+	if (efx->phy_type == PHY_TYPE_QT2025C) {
+		/* Wait for the reset triggered by falcon_reset_hw()
+		 * to complete */
+		rc = qt2025c_wait_reset(efx);
+		if (rc < 0)
+			goto fail;
+	} else {
+		/* Reset the PHYXS MMD. This is documented as doing
+		 * a complete soft reset. */
+		rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
+					QT2022C2_MAX_RESET_TIME /
+					QT2022C2_RESET_WAIT,
+					QT2022C2_RESET_WAIT);
+		if (rc < 0)
+			goto fail;
+	}
+
+	/* Wait 250ms for the PHY to complete bootup */
+	msleep(250);
+
+	falcon_board(efx)->type->init_phy(efx);
+
+	return 0;
+
+ fail:
+	EFX_ERR(efx, "PHY reset timed out\n");
+	return rc;
+}
+
+static int qt202x_phy_probe(struct efx_nic *efx)
+{
+	struct qt202x_phy_data *phy_data;
+
+	phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL);
+	if (!phy_data)
+		return -ENOMEM;
+	efx->phy_data = phy_data;
+	phy_data->phy_mode = efx->phy_mode;
+	phy_data->bug17190_in_bad_state = false;
+	phy_data->bug17190_timer = 0;
+
+	efx->mdio.mmds = QT202X_REQUIRED_DEVS;
+	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+	efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+	return 0;
+}
+
+static int qt202x_phy_init(struct efx_nic *efx)
+{
+	u32 devid;
+	int rc;
+
+	rc = qt202x_reset_phy(efx);
+	if (rc) {
+		EFX_ERR(efx, "PHY init failed\n");
+		return rc;
+	}
+
+	devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS);
+	EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n",
+		 devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid),
+		 efx_mdio_id_rev(devid));
+
+	if (efx->phy_type == PHY_TYPE_QT2025C)
+		qt2025c_firmware_id(efx);
+
+	return 0;
+}
+
+static int qt202x_link_ok(struct efx_nic *efx)
+{
+	return efx_mdio_links_ok(efx, QT202X_REQUIRED_DEVS);
+}
+
+static bool qt202x_phy_poll(struct efx_nic *efx)
+{
+	bool was_up = efx->link_state.up;
+
+	efx->link_state.up = qt202x_link_ok(efx);
+	efx->link_state.speed = 10000;
+	efx->link_state.fd = true;
+	efx->link_state.fc = efx->wanted_fc;
+
+	if (efx->phy_type == PHY_TYPE_QT2025C)
+		qt2025c_bug17190_workaround(efx);
+
+	return efx->link_state.up != was_up;
+}
+
+static int qt202x_phy_reconfigure(struct efx_nic *efx)
+{
+	struct qt202x_phy_data *phy_data = efx->phy_data;
+
+	if (efx->phy_type == PHY_TYPE_QT2025C) {
+		int rc = qt2025c_select_phy_mode(efx);
+		if (rc)
+			return rc;
+
+		/* There are several different register bits which can
+		 * disable TX (and save power) on direct-attach cables
+		 * or optical transceivers, varying somewhat between
+		 * firmware versions.  Only 'static mode' appears to
+		 * cover everything. */
+		mdio_set_flag(
+			&efx->mdio, efx->mdio.prtad, MDIO_MMD_PMAPMD,
+			PMA_PMD_FTX_CTRL2_REG, 1 << PMA_PMD_FTX_STATIC_LBN,
+			efx->phy_mode & PHY_MODE_TX_DISABLED ||
+			efx->phy_mode & PHY_MODE_LOW_POWER ||
+			efx->loopback_mode == LOOPBACK_PCS ||
+			efx->loopback_mode == LOOPBACK_PMAPMD);
+	} else {
+		/* Reset the PHY when moving from tx off to tx on */
+		if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) &&
+		    (phy_data->phy_mode & PHY_MODE_TX_DISABLED))
+			qt202x_reset_phy(efx);
+
+		efx_mdio_transmit_disable(efx);
+	}
+
+	efx_mdio_phy_reconfigure(efx);
+
+	phy_data->phy_mode = efx->phy_mode;
+
+	return 0;
+}
+
+static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+	mdio45_ethtool_gset(&efx->mdio, ecmd);
+}
+
+static void qt202x_phy_remove(struct efx_nic *efx)
+{
+	/* Free the context block */
+	kfree(efx->phy_data);
+	efx->phy_data = NULL;
+}
+
+struct efx_phy_operations falcon_qt202x_phy_ops = {
+	.probe		 = qt202x_phy_probe,
+	.init		 = qt202x_phy_init,
+	.reconfigure	 = qt202x_phy_reconfigure,
+	.poll	     	 = qt202x_phy_poll,
+	.fini		 = efx_port_dummy_op_void,
+	.remove	  	 = qt202x_phy_remove,
+	.get_settings	 = qt202x_phy_get_settings,
+	.set_settings	 = efx_mdio_set_settings,
+};
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mcdi.h
+++ linux-ec2-2.6.32/drivers/net/sfc/mcdi.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2008-2009 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, incorporated herein by reference.
+ */
+
+#ifndef EFX_MCDI_H
+#define EFX_MCDI_H
+
+/**
+ * enum efx_mcdi_state
+ * @MCDI_STATE_QUIESCENT: No pending MCDI requests. If the caller holds the
+ *	mcdi_lock then they are able to move to MCDI_STATE_RUNNING
+ * @MCDI_STATE_RUNNING: There is an MCDI request pending. Only the thread that
+ *	moved into this state is allowed to move out of it.
+ * @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread
+ *	has not yet consumed the result. For all other threads, equivalent to
+ *	MCDI_STATE_RUNNING.
+ */
+enum efx_mcdi_state {
+	MCDI_STATE_QUIESCENT,
+	MCDI_STATE_RUNNING,
+	MCDI_STATE_COMPLETED,
+};
+
+enum efx_mcdi_mode {
+	MCDI_MODE_POLL,
+	MCDI_MODE_EVENTS,
+};
+
+/**
+ * struct efx_mcdi_iface
+ * @state: Interface state. Waited for by mcdi_wq.
+ * @wq: Wait queue for threads waiting for state != STATE_RUNNING
+ * @iface_lock: Protects @credits, @seqno, @resprc, @resplen
+ * @mode: Poll for mcdi completion, or wait for an mcdi_event.
+ *	Serialised by @lock
+ * @seqno: The next sequence number to use for mcdi requests.
+ *	Serialised by @lock
+ * @credits: Number of spurious MCDI completion events allowed before we
+ *	trigger a fatal error. Protected by @lock
+ * @resprc: Returned MCDI completion
+ * @resplen: Returned payload length
+ */
+struct efx_mcdi_iface {
+	atomic_t state;
+	wait_queue_head_t wq;
+	spinlock_t iface_lock;
+	enum efx_mcdi_mode mode;
+	unsigned int credits;
+	unsigned int seqno;
+	unsigned int resprc;
+	size_t resplen;
+};
+
+extern void efx_mcdi_init(struct efx_nic *efx);
+
+extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
+			size_t inlen, u8 *outbuf, size_t outlen,
+			size_t *outlen_actual);
+
+extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
+extern void efx_mcdi_mode_poll(struct efx_nic *efx);
+extern void efx_mcdi_mode_event(struct efx_nic *efx);
+
+extern void efx_mcdi_process_event(struct efx_channel *channel,
+				   efx_qword_t *event);
+
+#define MCDI_PTR2(_buf, _ofst)						\
+	(((u8 *)_buf) + _ofst)
+#define MCDI_SET_DWORD2(_buf, _ofst, _value)				\
+	EFX_POPULATE_DWORD_1(*((efx_dword_t *)MCDI_PTR2(_buf, _ofst)),	\
+			     EFX_DWORD_0, _value)
+#define MCDI_DWORD2(_buf, _ofst)					\
+	EFX_DWORD_FIELD(*((efx_dword_t *)MCDI_PTR2(_buf, _ofst)),	\
+			EFX_DWORD_0)
+#define MCDI_QWORD2(_buf, _ofst)					\
+	EFX_QWORD_FIELD64(*((efx_qword_t *)MCDI_PTR2(_buf, _ofst)),	\
+			  EFX_QWORD_0)
+
+#define MCDI_PTR(_buf, _ofst)						\
+	MCDI_PTR2(_buf, MC_CMD_ ## _ofst ## _OFST)
+#define MCDI_SET_DWORD(_buf, _ofst, _value)				\
+	MCDI_SET_DWORD2(_buf, MC_CMD_ ## _ofst ## _OFST, _value)
+#define MCDI_DWORD(_buf, _ofst)						\
+	MCDI_DWORD2(_buf, MC_CMD_ ## _ofst ## _OFST)
+#define MCDI_QWORD(_buf, _ofst)						\
+	MCDI_QWORD2(_buf, MC_CMD_ ## _ofst ## _OFST)
+
+#define MCDI_EVENT_FIELD(_ev, _field)			\
+	EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
+
+extern int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build);
+extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
+			       bool *was_attached_out);
+extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
+				  u16 *fw_subtype_list);
+extern int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart,
+			     u32 dest_evq);
+extern int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out);
+extern int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
+			       size_t *size_out, size_t *erase_size_out,
+			       bool *protected_out);
+extern int efx_mcdi_nvram_update_start(struct efx_nic *efx,
+				       unsigned int type);
+extern int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
+			       loff_t offset, u8 *buffer, size_t length);
+extern int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
+				loff_t offset, const u8 *buffer,
+				size_t length);
+#define EFX_MCDI_NVRAM_LEN_MAX 128
+extern int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
+				loff_t offset, size_t length);
+extern int efx_mcdi_nvram_update_finish(struct efx_nic *efx,
+					unsigned int type);
+extern int efx_mcdi_handle_assertion(struct efx_nic *efx);
+extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
+extern int efx_mcdi_reset_port(struct efx_nic *efx);
+extern int efx_mcdi_reset_mc(struct efx_nic *efx);
+extern int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
+				   const u8 *mac, int *id_out);
+extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
+					 const u8 *mac, int *id_out);
+extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
+extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
+extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
+
+#endif /* EFX_MCDI_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mdio_10g.h
+++ linux-ec2-2.6.32/drivers/net/sfc/mdio_10g.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -17,7 +17,6 @@
  */
 
 #include "efx.h"
-#include "boards.h"
 
 static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; }
 static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
@@ -87,6 +86,9 @@
 /* Set (some of) the PHY settings over MDIO */
 extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
 
+/* Push advertising flags and restart autonegotiation */
+extern void efx_mdio_an_reconfigure(struct efx_nic *efx);
+
 /* Get pause parameters from AN if available (otherwise return
  * requested pause parameters)
  */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/Makefile
+++ linux-ec2-2.6.32/drivers/net/sfc/Makefile
@@ -1,6 +1,9 @@
-sfc-y			+= efx.o falcon.o tx.o rx.o falcon_gmac.o \
-			   falcon_xmac.o selftest.o ethtool.o xfp_phy.o \
-			   mdio_10g.o tenxpress.o boards.o sfe4001.o
+sfc-y			+= efx.o nic.o falcon.o siena.o tx.o rx.o \
+			   falcon_gmac.o falcon_xmac.o mcdi_mac.o \
+			   selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
+			   tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 
 obj-$(CONFIG_SFC)	+= sfc.o
+
+obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
--- linux-ec2-2.6.32.orig/drivers/net/sfc/spi.h
+++ linux-ec2-2.6.32/drivers/net/sfc/spi.h
@@ -36,8 +36,6 @@
 
 /**
  * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
- * @efx:		The Efx controller that owns this device
- * @mtd:		MTD state
  * @device_id:		Controller's id for the device
  * @size:		Size (in bytes)
  * @addr_len:		Number of address bytes in read/write commands
@@ -54,10 +52,6 @@
  *	Write commands are limited to blocks with this size and alignment.
  */
 struct efx_spi_device {
-	struct efx_nic *efx;
-#ifdef CONFIG_SFC_MTD
-	void *mtd;
-#endif
 	int device_id;
 	unsigned int size;
 	unsigned int addr_len;
@@ -67,12 +61,16 @@
 	unsigned int block_size;
 };
 
-int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command,
+int falcon_spi_cmd(struct efx_nic *efx,
+		   const struct efx_spi_device *spi, unsigned int command,
 		   int address, const void* in, void *out, size_t len);
-int falcon_spi_wait_write(const struct efx_spi_device *spi);
-int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
+int falcon_spi_wait_write(struct efx_nic *efx,
+			  const struct efx_spi_device *spi);
+int falcon_spi_read(struct efx_nic *efx,
+		    const struct efx_spi_device *spi, loff_t start,
 		    size_t len, size_t *retlen, u8 *buffer);
-int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
+int falcon_spi_write(struct efx_nic *efx,
+		     const struct efx_spi_device *spi, loff_t start,
 		     size_t len, size_t *retlen, const u8 *buffer);
 
 /*
--- linux-ec2-2.6.32.orig/drivers/net/sfc/tx.c
+++ linux-ec2-2.6.32/drivers/net/sfc/tx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2008 Solarflare Communications Inc.
+ * Copyright 2005-2009 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
@@ -12,12 +12,13 @@
 #include <linux/tcp.h>
 #include <linux/ip.h>
 #include <linux/in.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
 #include <linux/if_ether.h>
 #include <linux/highmem.h>
 #include "net_driver.h"
-#include "tx.h"
 #include "efx.h"
-#include "falcon.h"
+#include "nic.h"
 #include "workarounds.h"
 
 /*
@@ -26,8 +27,7 @@
  * 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)
+#define EFX_TXQ_THRESHOLD (EFX_TXQ_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.
@@ -125,6 +125,24 @@
 }
 
 
+static inline unsigned
+efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
+{
+	/* Depending on the NIC revision, we can use descriptor
+	 * lengths up to 8K or 8K-1.  However, since PCI Express
+	 * devices must split read requests at 4K boundaries, there is
+	 * little benefit from using descriptors that cross those
+	 * boundaries and we keep things simple by not doing so.
+	 */
+	unsigned len = (~dma_addr & 0xfff) + 1;
+
+	/* Work around hardware bug for unaligned buffers. */
+	if (EFX_WORKAROUND_5391(efx) && (dma_addr & 0xf))
+		len = min_t(unsigned, len, 512 - (dma_addr & 0xf));
+
+	return len;
+}
+
 /*
  * Add a socket buffer to a TX queue
  *
@@ -135,11 +153,13 @@
  * If any DMA mapping fails, any mapped fragments will be unmapped,
  * the queue's insert pointer will be restored to its original value.
  *
+ * This function is split out from efx_hard_start_xmit to allow the
+ * loopback test to direct packets via specific TX queues.
+ *
  * Returns NETDEV_TX_OK or NETDEV_TX_BUSY
  * You must hold netif_tx_lock() to call this function.
  */
-static netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue,
-					 struct sk_buff *skb)
+netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
 {
 	struct efx_nic *efx = tx_queue->efx;
 	struct pci_dev *pci_dev = efx->pci_dev;
@@ -147,7 +167,7 @@
 	skb_frag_t *fragment;
 	struct page *page;
 	int page_offset;
-	unsigned int len, unmap_len = 0, fill_level, insert_ptr, misalign;
+	unsigned int len, unmap_len = 0, fill_level, insert_ptr;
 	dma_addr_t dma_addr, unmap_addr = 0;
 	unsigned int dma_len;
 	bool unmap_single;
@@ -156,7 +176,7 @@
 
 	EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
 
-	if (skb_shinfo((struct sk_buff *)skb)->gso_size)
+	if (skb_shinfo(skb)->gso_size)
 		return efx_enqueue_skb_tso(tx_queue, skb);
 
 	/* Get size of the initial fragment */
@@ -171,7 +191,7 @@
 	}
 
 	fill_level = tx_queue->insert_count - tx_queue->old_read_count;
-	q_space = efx->type->txd_ring_mask - 1 - fill_level;
+	q_space = EFX_TXQ_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
@@ -208,16 +228,14 @@
 					&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);
+				q_space = EFX_TXQ_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);
+			insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
 			buffer = &tx_queue->buffer[insert_ptr];
 			efx_tsoh_free(tx_queue, buffer);
 			EFX_BUG_ON_PARANOID(buffer->tsoh);
@@ -226,14 +244,10 @@
 			EFX_BUG_ON_PARANOID(!buffer->continuation);
 			EFX_BUG_ON_PARANOID(buffer->unmap_len);
 
-			dma_len = (((~dma_addr) & efx->type->tx_dma_mask) + 1);
-			if (likely(dma_len > len))
+			dma_len = efx_max_tx_len(efx, dma_addr);
+			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;
@@ -266,7 +280,7 @@
 	buffer->continuation = false;
 
 	/* Pass off to hardware */
-	falcon_push_buffers(tx_queue);
+	efx_nic_push_buffers(tx_queue);
 
 	return NETDEV_TX_OK;
 
@@ -276,7 +290,7 @@
 		   skb_shinfo(skb)->nr_frags + 1);
 
 	/* Mark the packet as transmitted, and free the SKB ourselves */
-	dev_kfree_skb_any((struct sk_buff *)skb);
+	dev_kfree_skb_any(skb);
 	goto unwind;
 
  stop:
@@ -289,7 +303,7 @@
 	/* 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;
+		insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
 		buffer = &tx_queue->buffer[insert_ptr];
 		efx_dequeue_buffer(tx_queue, buffer);
 		buffer->len = 0;
@@ -318,10 +332,9 @@
 {
 	struct efx_nic *efx = tx_queue->efx;
 	unsigned int stop_index, read_ptr;
-	unsigned int mask = tx_queue->efx->type->txd_ring_mask;
 
-	stop_index = (index + 1) & mask;
-	read_ptr = tx_queue->read_count & mask;
+	stop_index = (index + 1) & EFX_TXQ_MASK;
+	read_ptr = tx_queue->read_count & EFX_TXQ_MASK;
 
 	while (read_ptr != stop_index) {
 		struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
@@ -338,28 +351,10 @@
 		buffer->len = 0;
 
 		++tx_queue->read_count;
-		read_ptr = tx_queue->read_count & mask;
+		read_ptr = tx_queue->read_count & EFX_TXQ_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 netdev_tx_t efx_xmit(struct efx_nic *efx,
-			   struct efx_tx_queue *tx_queue, struct sk_buff *skb)
-{
-	/* Map fragments for DMA and add to TX queue */
-	return efx_enqueue_skb(tx_queue, skb);
-}
-
 /* 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
@@ -383,7 +378,7 @@
 	else
 		tx_queue = &efx->tx_queue[EFX_TX_QUEUE_NO_CSUM];
 
-	return efx_xmit(efx, tx_queue, skb);
+	return efx_enqueue_skb(tx_queue, skb);
 }
 
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
@@ -391,7 +386,7 @@
 	unsigned fill_level;
 	struct efx_nic *efx = tx_queue->efx;
 
-	EFX_BUG_ON_PARANOID(index > efx->type->txd_ring_mask);
+	EFX_BUG_ON_PARANOID(index > EFX_TXQ_MASK);
 
 	efx_dequeue_buffers(tx_queue, index);
 
@@ -401,7 +396,7 @@
 	smp_mb();
 	if (unlikely(tx_queue->stopped) && likely(efx->port_enabled)) {
 		fill_level = tx_queue->insert_count - tx_queue->read_count;
-		if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) {
+		if (fill_level < EFX_TXQ_THRESHOLD) {
 			EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
 
 			/* Do this under netif_tx_lock(), to avoid racing
@@ -425,15 +420,15 @@
 	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);
+	txq_size = EFX_TXQ_SIZE * sizeof(*tx_queue->buffer);
 	tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL);
 	if (!tx_queue->buffer)
 		return -ENOMEM;
-	for (i = 0; i <= efx->type->txd_ring_mask; ++i)
+	for (i = 0; i <= EFX_TXQ_MASK; ++i)
 		tx_queue->buffer[i].continuation = true;
 
 	/* Allocate hardware ring */
-	rc = falcon_probe_tx(tx_queue);
+	rc = efx_nic_probe_tx(tx_queue);
 	if (rc)
 		goto fail;
 
@@ -456,7 +451,7 @@
 	BUG_ON(tx_queue->stopped);
 
 	/* Set up TX descriptor ring */
-	falcon_init_tx(tx_queue);
+	efx_nic_init_tx(tx_queue);
 }
 
 void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
@@ -468,8 +463,7 @@
 
 	/* Free any buffers left in the ring */
 	while (tx_queue->read_count != tx_queue->write_count) {
-		buffer = &tx_queue->buffer[tx_queue->read_count &
-					   tx_queue->efx->type->txd_ring_mask];
+		buffer = &tx_queue->buffer[tx_queue->read_count & EFX_TXQ_MASK];
 		efx_dequeue_buffer(tx_queue, buffer);
 		buffer->continuation = true;
 		buffer->len = 0;
@@ -483,7 +477,7 @@
 	EFX_LOG(tx_queue->efx, "shutting down TX queue %d\n", tx_queue->queue);
 
 	/* Flush TX queue, remove descriptor ring */
-	falcon_fini_tx(tx_queue);
+	efx_nic_fini_tx(tx_queue);
 
 	efx_release_tx_buffers(tx_queue);
 
@@ -500,7 +494,7 @@
 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);
+	efx_nic_remove_tx(tx_queue);
 
 	kfree(tx_queue->buffer);
 	tx_queue->buffer = NULL;
@@ -539,6 +533,7 @@
 #define ETH_HDR_LEN(skb)  (skb_network_header(skb) - (skb)->data)
 #define SKB_TCP_OFF(skb)  PTR_DIFF(tcp_hdr(skb), (skb)->data)
 #define SKB_IPV4_OFF(skb) PTR_DIFF(ip_hdr(skb), (skb)->data)
+#define SKB_IPV6_OFF(skb) PTR_DIFF(ipv6_hdr(skb), (skb)->data)
 
 /**
  * struct tso_state - TSO state for an SKB
@@ -551,6 +546,7 @@
  * @unmap_len: Length of SKB fragment
  * @unmap_addr: DMA address of SKB fragment
  * @unmap_single: DMA single vs page mapping flag
+ * @protocol: Network protocol (after any VLAN header)
  * @header_len: Number of bytes of header
  * @full_packet_size: Number of bytes to put in each outgoing segment
  *
@@ -571,6 +567,7 @@
 	dma_addr_t unmap_addr;
 	bool unmap_single;
 
+	__be16 protocol;
 	unsigned header_len;
 	int full_packet_size;
 };
@@ -578,9 +575,9 @@
 
 /*
  * Verify that our various assumptions about sk_buffs and the conditions
- * under which TSO will be attempted hold true.
+ * under which TSO will be attempted hold true.  Return the protocol number.
  */
-static void efx_tso_check_safe(struct sk_buff *skb)
+static __be16 efx_tso_check_protocol(struct sk_buff *skb)
 {
 	__be16 protocol = skb->protocol;
 
@@ -595,13 +592,22 @@
 		if (protocol == htons(ETH_P_IP))
 			skb_set_transport_header(skb, sizeof(*veh) +
 						 4 * ip_hdr(skb)->ihl);
+		else if (protocol == htons(ETH_P_IPV6))
+			skb_set_transport_header(skb, sizeof(*veh) +
+						 sizeof(struct ipv6hdr));
 	}
 
-	EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IP));
-	EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP);
+	if (protocol == htons(ETH_P_IP)) {
+		EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP);
+	} else {
+		EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IPV6));
+		EFX_BUG_ON_PARANOID(ipv6_hdr(skb)->nexthdr != NEXTHDR_TCP);
+	}
 	EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data)
 			     + (tcp_hdr(skb)->doff << 2u)) >
 			    skb_headlen(skb));
+
+	return protocol;
 }
 
 
@@ -708,14 +714,14 @@
 {
 	struct efx_tx_buffer *buffer;
 	struct efx_nic *efx = tx_queue->efx;
-	unsigned dma_len, fill_level, insert_ptr, misalign;
+	unsigned dma_len, fill_level, insert_ptr;
 	int q_space;
 
 	EFX_BUG_ON_PARANOID(len <= 0);
 
 	fill_level = tx_queue->insert_count - tx_queue->old_read_count;
 	/* -1 as there is no way to represent all descriptors used */
-	q_space = efx->type->txd_ring_mask - 1 - fill_level;
+	q_space = EFX_TXQ_MASK - 1 - fill_level;
 
 	while (1) {
 		if (unlikely(q_space-- <= 0)) {
@@ -731,7 +737,7 @@
 				*(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;
+			q_space = EFX_TXQ_MASK - 1 - fill_level;
 			if (unlikely(q_space-- <= 0)) {
 				*final_buffer = NULL;
 				return 1;
@@ -740,13 +746,13 @@
 			--tx_queue->stopped;
 		}
 
-		insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask;
+		insert_ptr = tx_queue->insert_count & EFX_TXQ_MASK;
 		buffer = &tx_queue->buffer[insert_ptr];
 		++tx_queue->insert_count;
 
 		EFX_BUG_ON_PARANOID(tx_queue->insert_count -
 				    tx_queue->read_count >
-				    efx->type->txd_ring_mask);
+				    EFX_TXQ_MASK);
 
 		efx_tsoh_free(tx_queue, buffer);
 		EFX_BUG_ON_PARANOID(buffer->len);
@@ -757,12 +763,7 @@
 
 		buffer->dma_addr = dma_addr;
 
-		/* Ensure we do not cross a boundary unsupported by H/W */
-		dma_len = (~dma_addr & efx->type->tx_dma_mask) + 1;
-
-		misalign = (unsigned)dma_addr & efx->type->bug5391_mask;
-		if (misalign && dma_len + misalign > 512)
-			dma_len = 512 - misalign;
+		dma_len = efx_max_tx_len(efx, dma_addr);
 
 		/* If there is enough space to send then do so */
 		if (dma_len >= len)
@@ -792,8 +793,7 @@
 {
 	struct efx_tx_buffer *buffer;
 
-	buffer = &tx_queue->buffer[tx_queue->insert_count &
-				   tx_queue->efx->type->txd_ring_mask];
+	buffer = &tx_queue->buffer[tx_queue->insert_count & EFX_TXQ_MASK];
 	efx_tsoh_free(tx_queue, buffer);
 	EFX_BUG_ON_PARANOID(buffer->len);
 	EFX_BUG_ON_PARANOID(buffer->unmap_len);
@@ -818,11 +818,9 @@
 	while (tx_queue->insert_count != tx_queue->write_count) {
 		--tx_queue->insert_count;
 		buffer = &tx_queue->buffer[tx_queue->insert_count &
-					   tx_queue->efx->type->txd_ring_mask];
+					   EFX_TXQ_MASK];
 		efx_tsoh_free(tx_queue, buffer);
 		EFX_BUG_ON_PARANOID(buffer->skb);
-		buffer->len = 0;
-		buffer->continuation = true;
 		if (buffer->unmap_len) {
 			unmap_addr = (buffer->dma_addr + buffer->len -
 				      buffer->unmap_len);
@@ -836,6 +834,8 @@
 					       PCI_DMA_TODEVICE);
 			buffer->unmap_len = 0;
 		}
+		buffer->len = 0;
+		buffer->continuation = true;
 	}
 }
 
@@ -850,7 +850,10 @@
 			  + PTR_DIFF(tcp_hdr(skb), skb->data));
 	st->full_packet_size = st->header_len + skb_shinfo(skb)->gso_size;
 
-	st->ipv4_id = ntohs(ip_hdr(skb)->id);
+	if (st->protocol == htons(ETH_P_IP))
+		st->ipv4_id = ntohs(ip_hdr(skb)->id);
+	else
+		st->ipv4_id = 0;
 	st->seqnum = ntohl(tcp_hdr(skb)->seq);
 
 	EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg);
@@ -965,7 +968,6 @@
 				struct tso_state *st)
 {
 	struct efx_tso_header *tsoh;
-	struct iphdr *tsoh_iph;
 	struct tcphdr *tsoh_th;
 	unsigned ip_length;
 	u8 *header;
@@ -989,7 +991,6 @@
 
 	header = TSOH_BUFFER(tsoh);
 	tsoh_th = (struct tcphdr *)(header + SKB_TCP_OFF(skb));
-	tsoh_iph = (struct iphdr *)(header + SKB_IPV4_OFF(skb));
 
 	/* Copy and update the headers. */
 	memcpy(header, skb->data, st->header_len);
@@ -1007,11 +1008,22 @@
 		tsoh_th->fin = tcp_hdr(skb)->fin;
 		tsoh_th->psh = tcp_hdr(skb)->psh;
 	}
-	tsoh_iph->tot_len = htons(ip_length);
 
-	/* Linux leaves suitable gaps in the IP ID space for us to fill. */
-	tsoh_iph->id = htons(st->ipv4_id);
-	st->ipv4_id++;
+	if (st->protocol == htons(ETH_P_IP)) {
+		struct iphdr *tsoh_iph =
+			(struct iphdr *)(header + SKB_IPV4_OFF(skb));
+
+		tsoh_iph->tot_len = htons(ip_length);
+
+		/* Linux leaves suitable gaps in the IP ID space for us to fill. */
+		tsoh_iph->id = htons(st->ipv4_id);
+		st->ipv4_id++;
+	} else {
+		struct ipv6hdr *tsoh_iph =
+			(struct ipv6hdr *)(header + SKB_IPV6_OFF(skb));
+
+		tsoh_iph->payload_len = htons(ip_length - sizeof(*tsoh_iph));
+	}
 
 	st->packet_space = skb_shinfo(skb)->gso_size;
 	++tx_queue->tso_packets;
@@ -1041,8 +1053,8 @@
 	int frag_i, rc, rc2 = NETDEV_TX_OK;
 	struct tso_state state;
 
-	/* Verify TSO is safe - these checks should never fail. */
-	efx_tso_check_safe(skb);
+	/* Find the packet protocol and sanity-check it */
+	state.protocol = efx_tso_check_protocol(skb);
 
 	EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
 
@@ -1092,14 +1104,14 @@
 	}
 
 	/* Pass off to hardware */
-	falcon_push_buffers(tx_queue);
+	efx_nic_push_buffers(tx_queue);
 
 	tx_queue->tso_bursts++;
 	return NETDEV_TX_OK;
 
  mem_err:
 	EFX_ERR(efx, "Out of memory for TSO headers, or PCI mapping error\n");
-	dev_kfree_skb_any((struct sk_buff *)skb);
+	dev_kfree_skb_any(skb);
 	goto unwind;
 
  stop:
@@ -1135,7 +1147,7 @@
 	unsigned i;
 
 	if (tx_queue->buffer) {
-		for (i = 0; i <= tx_queue->efx->type->txd_ring_mask; ++i)
+		for (i = 0; i <= EFX_TXQ_MASK; ++i)
 			efx_tsoh_free(tx_queue, &tx_queue->buffer[i]);
 	}
 
--- linux-ec2-2.6.32.orig/drivers/net/sfc/regs.h
+++ linux-ec2-2.6.32/drivers/net/sfc/regs.h
@@ -0,0 +1,3168 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+
+#ifndef EFX_REGS_H
+#define EFX_REGS_H
+
+/*
+ * Falcon hardware architecture definitions have a name prefix following
+ * the format:
+ *
+ *     F<type>_<min-rev><max-rev>_
+ *
+ * The following <type> strings are used:
+ *
+ *             MMIO register  MC register  Host memory structure
+ * -------------------------------------------------------------
+ * Address     R              MCR
+ * Bitfield    RF             MCRF         SF
+ * Enumerator  FE             MCFE         SE
+ *
+ * <min-rev> is the first revision to which the definition applies:
+ *
+ *     A: Falcon A1 (SFC4000AB)
+ *     B: Falcon B0 (SFC4000BA)
+ *     C: Siena A0 (SFL9021AA)
+ *
+ * If the definition has been changed or removed in later revisions
+ * then <max-rev> is the last revision to which the definition applies;
+ * otherwise it is "Z".
+ */
+
+/**************************************************************************
+ *
+ * Falcon/Siena registers and descriptors
+ *
+ **************************************************************************
+ */
+
+/* ADR_REGION_REG: Address region register */
+#define	FR_AZ_ADR_REGION 0x00000000
+#define	FRF_AZ_ADR_REGION3_LBN 96
+#define	FRF_AZ_ADR_REGION3_WIDTH 18
+#define	FRF_AZ_ADR_REGION2_LBN 64
+#define	FRF_AZ_ADR_REGION2_WIDTH 18
+#define	FRF_AZ_ADR_REGION1_LBN 32
+#define	FRF_AZ_ADR_REGION1_WIDTH 18
+#define	FRF_AZ_ADR_REGION0_LBN 0
+#define	FRF_AZ_ADR_REGION0_WIDTH 18
+
+/* INT_EN_REG_KER: Kernel driver Interrupt enable register */
+#define	FR_AZ_INT_EN_KER 0x00000010
+#define	FRF_AZ_KER_INT_LEVE_SEL_LBN 8
+#define	FRF_AZ_KER_INT_LEVE_SEL_WIDTH 6
+#define	FRF_AZ_KER_INT_CHAR_LBN 4
+#define	FRF_AZ_KER_INT_CHAR_WIDTH 1
+#define	FRF_AZ_KER_INT_KER_LBN 3
+#define	FRF_AZ_KER_INT_KER_WIDTH 1
+#define	FRF_AZ_DRV_INT_EN_KER_LBN 0
+#define	FRF_AZ_DRV_INT_EN_KER_WIDTH 1
+
+/* INT_EN_REG_CHAR: Char Driver interrupt enable register */
+#define	FR_BZ_INT_EN_CHAR 0x00000020
+#define	FRF_BZ_CHAR_INT_LEVE_SEL_LBN 8
+#define	FRF_BZ_CHAR_INT_LEVE_SEL_WIDTH 6
+#define	FRF_BZ_CHAR_INT_CHAR_LBN 4
+#define	FRF_BZ_CHAR_INT_CHAR_WIDTH 1
+#define	FRF_BZ_CHAR_INT_KER_LBN 3
+#define	FRF_BZ_CHAR_INT_KER_WIDTH 1
+#define	FRF_BZ_DRV_INT_EN_CHAR_LBN 0
+#define	FRF_BZ_DRV_INT_EN_CHAR_WIDTH 1
+
+/* INT_ADR_REG_KER: Interrupt host address for Kernel driver */
+#define	FR_AZ_INT_ADR_KER 0x00000030
+#define	FRF_AZ_NORM_INT_VEC_DIS_KER_LBN 64
+#define	FRF_AZ_NORM_INT_VEC_DIS_KER_WIDTH 1
+#define	FRF_AZ_INT_ADR_KER_LBN 0
+#define	FRF_AZ_INT_ADR_KER_WIDTH 64
+
+/* INT_ADR_REG_CHAR: Interrupt host address for Char driver */
+#define	FR_BZ_INT_ADR_CHAR 0x00000040
+#define	FRF_BZ_NORM_INT_VEC_DIS_CHAR_LBN 64
+#define	FRF_BZ_NORM_INT_VEC_DIS_CHAR_WIDTH 1
+#define	FRF_BZ_INT_ADR_CHAR_LBN 0
+#define	FRF_BZ_INT_ADR_CHAR_WIDTH 64
+
+/* INT_ACK_KER: Kernel interrupt acknowledge register */
+#define	FR_AA_INT_ACK_KER 0x00000050
+#define	FRF_AA_INT_ACK_KER_FIELD_LBN 0
+#define	FRF_AA_INT_ACK_KER_FIELD_WIDTH 32
+
+/* INT_ISR0_REG: Function 0 Interrupt Acknowlege Status register */
+#define	FR_BZ_INT_ISR0 0x00000090
+#define	FRF_BZ_INT_ISR_REG_LBN 0
+#define	FRF_BZ_INT_ISR_REG_WIDTH 64
+
+/* HW_INIT_REG: Hardware initialization register */
+#define	FR_AZ_HW_INIT 0x000000c0
+#define	FRF_BB_BDMRD_CPLF_FULL_LBN 124
+#define	FRF_BB_BDMRD_CPLF_FULL_WIDTH 1
+#define	FRF_BB_PCIE_CPL_TIMEOUT_CTRL_LBN 121
+#define	FRF_BB_PCIE_CPL_TIMEOUT_CTRL_WIDTH 3
+#define	FRF_CZ_TX_MRG_TAGS_LBN 120
+#define	FRF_CZ_TX_MRG_TAGS_WIDTH 1
+#define	FRF_AB_TRGT_MASK_ALL_LBN 100
+#define	FRF_AB_TRGT_MASK_ALL_WIDTH 1
+#define	FRF_AZ_DOORBELL_DROP_LBN 92
+#define	FRF_AZ_DOORBELL_DROP_WIDTH 8
+#define	FRF_AB_TX_RREQ_MASK_EN_LBN 76
+#define	FRF_AB_TX_RREQ_MASK_EN_WIDTH 1
+#define	FRF_AB_PE_EIDLE_DIS_LBN 75
+#define	FRF_AB_PE_EIDLE_DIS_WIDTH 1
+#define	FRF_AA_FC_BLOCKING_EN_LBN 45
+#define	FRF_AA_FC_BLOCKING_EN_WIDTH 1
+#define	FRF_BZ_B2B_REQ_EN_LBN 45
+#define	FRF_BZ_B2B_REQ_EN_WIDTH 1
+#define	FRF_AA_B2B_REQ_EN_LBN 44
+#define	FRF_AA_B2B_REQ_EN_WIDTH 1
+#define	FRF_BB_FC_BLOCKING_EN_LBN 44
+#define	FRF_BB_FC_BLOCKING_EN_WIDTH 1
+#define	FRF_AZ_POST_WR_MASK_LBN 40
+#define	FRF_AZ_POST_WR_MASK_WIDTH 4
+#define	FRF_AZ_TLP_TC_LBN 34
+#define	FRF_AZ_TLP_TC_WIDTH 3
+#define	FRF_AZ_TLP_ATTR_LBN 32
+#define	FRF_AZ_TLP_ATTR_WIDTH 2
+#define	FRF_AB_INTB_VEC_LBN 24
+#define	FRF_AB_INTB_VEC_WIDTH 5
+#define	FRF_AB_INTA_VEC_LBN 16
+#define	FRF_AB_INTA_VEC_WIDTH 5
+#define	FRF_AZ_WD_TIMER_LBN 8
+#define	FRF_AZ_WD_TIMER_WIDTH 8
+#define	FRF_AZ_US_DISABLE_LBN 5
+#define	FRF_AZ_US_DISABLE_WIDTH 1
+#define	FRF_AZ_TLP_EP_LBN 4
+#define	FRF_AZ_TLP_EP_WIDTH 1
+#define	FRF_AZ_ATTR_SEL_LBN 3
+#define	FRF_AZ_ATTR_SEL_WIDTH 1
+#define	FRF_AZ_TD_SEL_LBN 1
+#define	FRF_AZ_TD_SEL_WIDTH 1
+#define	FRF_AZ_TLP_TD_LBN 0
+#define	FRF_AZ_TLP_TD_WIDTH 1
+
+/* EE_SPI_HCMD_REG: SPI host command register */
+#define	FR_AB_EE_SPI_HCMD 0x00000100
+#define	FRF_AB_EE_SPI_HCMD_CMD_EN_LBN 31
+#define	FRF_AB_EE_SPI_HCMD_CMD_EN_WIDTH 1
+#define	FRF_AB_EE_WR_TIMER_ACTIVE_LBN 28
+#define	FRF_AB_EE_WR_TIMER_ACTIVE_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_SF_SEL_LBN 24
+#define	FRF_AB_EE_SPI_HCMD_SF_SEL_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_DABCNT_LBN 16
+#define	FRF_AB_EE_SPI_HCMD_DABCNT_WIDTH 5
+#define	FRF_AB_EE_SPI_HCMD_READ_LBN 15
+#define	FRF_AB_EE_SPI_HCMD_READ_WIDTH 1
+#define	FRF_AB_EE_SPI_HCMD_DUBCNT_LBN 12
+#define	FRF_AB_EE_SPI_HCMD_DUBCNT_WIDTH 2
+#define	FRF_AB_EE_SPI_HCMD_ADBCNT_LBN 8
+#define	FRF_AB_EE_SPI_HCMD_ADBCNT_WIDTH 2
+#define	FRF_AB_EE_SPI_HCMD_ENC_LBN 0
+#define	FRF_AB_EE_SPI_HCMD_ENC_WIDTH 8
+
+/* USR_EV_CFG: User Level Event Configuration register */
+#define	FR_CZ_USR_EV_CFG 0x00000100
+#define	FRF_CZ_USREV_DIS_LBN 16
+#define	FRF_CZ_USREV_DIS_WIDTH 1
+#define	FRF_CZ_DFLT_EVQ_LBN 0
+#define	FRF_CZ_DFLT_EVQ_WIDTH 10
+
+/* EE_SPI_HADR_REG: SPI host address register */
+#define	FR_AB_EE_SPI_HADR 0x00000110
+#define	FRF_AB_EE_SPI_HADR_DUBYTE_LBN 24
+#define	FRF_AB_EE_SPI_HADR_DUBYTE_WIDTH 8
+#define	FRF_AB_EE_SPI_HADR_ADR_LBN 0
+#define	FRF_AB_EE_SPI_HADR_ADR_WIDTH 24
+
+/* EE_SPI_HDATA_REG: SPI host data register */
+#define	FR_AB_EE_SPI_HDATA 0x00000120
+#define	FRF_AB_EE_SPI_HDATA3_LBN 96
+#define	FRF_AB_EE_SPI_HDATA3_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA2_LBN 64
+#define	FRF_AB_EE_SPI_HDATA2_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA1_LBN 32
+#define	FRF_AB_EE_SPI_HDATA1_WIDTH 32
+#define	FRF_AB_EE_SPI_HDATA0_LBN 0
+#define	FRF_AB_EE_SPI_HDATA0_WIDTH 32
+
+/* EE_BASE_PAGE_REG: Expansion ROM base mirror register */
+#define	FR_AB_EE_BASE_PAGE 0x00000130
+#define	FRF_AB_EE_EXPROM_MASK_LBN 16
+#define	FRF_AB_EE_EXPROM_MASK_WIDTH 13
+#define	FRF_AB_EE_EXP_ROM_WINDOW_BASE_LBN 0
+#define	FRF_AB_EE_EXP_ROM_WINDOW_BASE_WIDTH 13
+
+/* EE_VPD_CFG0_REG: SPI/VPD configuration register 0 */
+#define	FR_AB_EE_VPD_CFG0 0x00000140
+#define	FRF_AB_EE_SF_FASTRD_EN_LBN 127
+#define	FRF_AB_EE_SF_FASTRD_EN_WIDTH 1
+#define	FRF_AB_EE_SF_CLOCK_DIV_LBN 120
+#define	FRF_AB_EE_SF_CLOCK_DIV_WIDTH 7
+#define	FRF_AB_EE_VPD_WIP_POLL_LBN 119
+#define	FRF_AB_EE_VPD_WIP_POLL_WIDTH 1
+#define	FRF_AB_EE_EE_CLOCK_DIV_LBN 112
+#define	FRF_AB_EE_EE_CLOCK_DIV_WIDTH 7
+#define	FRF_AB_EE_EE_WR_TMR_VALUE_LBN 96
+#define	FRF_AB_EE_EE_WR_TMR_VALUE_WIDTH 16
+#define	FRF_AB_EE_VPDW_LENGTH_LBN 80
+#define	FRF_AB_EE_VPDW_LENGTH_WIDTH 15
+#define	FRF_AB_EE_VPDW_BASE_LBN 64
+#define	FRF_AB_EE_VPDW_BASE_WIDTH 15
+#define	FRF_AB_EE_VPD_WR_CMD_EN_LBN 56
+#define	FRF_AB_EE_VPD_WR_CMD_EN_WIDTH 8
+#define	FRF_AB_EE_VPD_BASE_LBN 32
+#define	FRF_AB_EE_VPD_BASE_WIDTH 24
+#define	FRF_AB_EE_VPD_LENGTH_LBN 16
+#define	FRF_AB_EE_VPD_LENGTH_WIDTH 15
+#define	FRF_AB_EE_VPD_AD_SIZE_LBN 8
+#define	FRF_AB_EE_VPD_AD_SIZE_WIDTH 5
+#define	FRF_AB_EE_VPD_ACCESS_ON_LBN 5
+#define	FRF_AB_EE_VPD_ACCESS_ON_WIDTH 1
+#define	FRF_AB_EE_VPD_ACCESS_BLOCK_LBN 4
+#define	FRF_AB_EE_VPD_ACCESS_BLOCK_WIDTH 1
+#define	FRF_AB_EE_VPD_DEV_SF_SEL_LBN 2
+#define	FRF_AB_EE_VPD_DEV_SF_SEL_WIDTH 1
+#define	FRF_AB_EE_VPD_EN_AD9_MODE_LBN 1
+#define	FRF_AB_EE_VPD_EN_AD9_MODE_WIDTH 1
+#define	FRF_AB_EE_VPD_EN_LBN 0
+#define	FRF_AB_EE_VPD_EN_WIDTH 1
+
+/* EE_VPD_SW_CNTL_REG: VPD access SW control register */
+#define	FR_AB_EE_VPD_SW_CNTL 0x00000150
+#define	FRF_AB_EE_VPD_CYCLE_PENDING_LBN 31
+#define	FRF_AB_EE_VPD_CYCLE_PENDING_WIDTH 1
+#define	FRF_AB_EE_VPD_CYC_WRITE_LBN 28
+#define	FRF_AB_EE_VPD_CYC_WRITE_WIDTH 1
+#define	FRF_AB_EE_VPD_CYC_ADR_LBN 0
+#define	FRF_AB_EE_VPD_CYC_ADR_WIDTH 15
+
+/* EE_VPD_SW_DATA_REG: VPD access SW data register */
+#define	FR_AB_EE_VPD_SW_DATA 0x00000160
+#define	FRF_AB_EE_VPD_CYC_DAT_LBN 0
+#define	FRF_AB_EE_VPD_CYC_DAT_WIDTH 32
+
+/* PBMX_DBG_IADDR_REG: Capture Module address register */
+#define	FR_CZ_PBMX_DBG_IADDR 0x000001f0
+#define	FRF_CZ_PBMX_DBG_IADDR_LBN 0
+#define	FRF_CZ_PBMX_DBG_IADDR_WIDTH 32
+
+/* PCIE_CORE_INDIRECT_REG: Indirect Access to PCIE Core registers */
+#define	FR_BB_PCIE_CORE_INDIRECT 0x000001f0
+#define	FRF_BB_PCIE_CORE_TARGET_DATA_LBN 32
+#define	FRF_BB_PCIE_CORE_TARGET_DATA_WIDTH 32
+#define	FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_LBN 15
+#define	FRF_BB_PCIE_CORE_INDIRECT_ACCESS_DIR_WIDTH 1
+#define	FRF_BB_PCIE_CORE_TARGET_REG_ADRS_LBN 0
+#define	FRF_BB_PCIE_CORE_TARGET_REG_ADRS_WIDTH 12
+
+/* PBMX_DBG_IDATA_REG: Capture Module data register */
+#define	FR_CZ_PBMX_DBG_IDATA 0x000001f8
+#define	FRF_CZ_PBMX_DBG_IDATA_LBN 0
+#define	FRF_CZ_PBMX_DBG_IDATA_WIDTH 64
+
+/* NIC_STAT_REG: NIC status register */
+#define	FR_AB_NIC_STAT 0x00000200
+#define	FRF_BB_AER_DIS_LBN 34
+#define	FRF_BB_AER_DIS_WIDTH 1
+#define	FRF_BB_EE_STRAP_EN_LBN 31
+#define	FRF_BB_EE_STRAP_EN_WIDTH 1
+#define	FRF_BB_EE_STRAP_LBN 24
+#define	FRF_BB_EE_STRAP_WIDTH 4
+#define	FRF_BB_REVISION_ID_LBN 17
+#define	FRF_BB_REVISION_ID_WIDTH 7
+#define	FRF_AB_ONCHIP_SRAM_LBN 16
+#define	FRF_AB_ONCHIP_SRAM_WIDTH 1
+#define	FRF_AB_SF_PRST_LBN 9
+#define	FRF_AB_SF_PRST_WIDTH 1
+#define	FRF_AB_EE_PRST_LBN 8
+#define	FRF_AB_EE_PRST_WIDTH 1
+#define	FRF_AB_ATE_MODE_LBN 3
+#define	FRF_AB_ATE_MODE_WIDTH 1
+#define	FRF_AB_STRAP_PINS_LBN 0
+#define	FRF_AB_STRAP_PINS_WIDTH 3
+
+/* GPIO_CTL_REG: GPIO control register */
+#define	FR_AB_GPIO_CTL 0x00000210
+#define	FRF_AB_GPIO_OUT3_LBN 112
+#define	FRF_AB_GPIO_OUT3_WIDTH 16
+#define	FRF_AB_GPIO_IN3_LBN 104
+#define	FRF_AB_GPIO_IN3_WIDTH 8
+#define	FRF_AB_GPIO_PWRUP_VALUE3_LBN 96
+#define	FRF_AB_GPIO_PWRUP_VALUE3_WIDTH 8
+#define	FRF_AB_GPIO_OUT2_LBN 80
+#define	FRF_AB_GPIO_OUT2_WIDTH 16
+#define	FRF_AB_GPIO_IN2_LBN 72
+#define	FRF_AB_GPIO_IN2_WIDTH 8
+#define	FRF_AB_GPIO_PWRUP_VALUE2_LBN 64
+#define	FRF_AB_GPIO_PWRUP_VALUE2_WIDTH 8
+#define	FRF_AB_GPIO15_OEN_LBN 63
+#define	FRF_AB_GPIO15_OEN_WIDTH 1
+#define	FRF_AB_GPIO14_OEN_LBN 62
+#define	FRF_AB_GPIO14_OEN_WIDTH 1
+#define	FRF_AB_GPIO13_OEN_LBN 61
+#define	FRF_AB_GPIO13_OEN_WIDTH 1
+#define	FRF_AB_GPIO12_OEN_LBN 60
+#define	FRF_AB_GPIO12_OEN_WIDTH 1
+#define	FRF_AB_GPIO11_OEN_LBN 59
+#define	FRF_AB_GPIO11_OEN_WIDTH 1
+#define	FRF_AB_GPIO10_OEN_LBN 58
+#define	FRF_AB_GPIO10_OEN_WIDTH 1
+#define	FRF_AB_GPIO9_OEN_LBN 57
+#define	FRF_AB_GPIO9_OEN_WIDTH 1
+#define	FRF_AB_GPIO8_OEN_LBN 56
+#define	FRF_AB_GPIO8_OEN_WIDTH 1
+#define	FRF_AB_GPIO15_OUT_LBN 55
+#define	FRF_AB_GPIO15_OUT_WIDTH 1
+#define	FRF_AB_GPIO14_OUT_LBN 54
+#define	FRF_AB_GPIO14_OUT_WIDTH 1
+#define	FRF_AB_GPIO13_OUT_LBN 53
+#define	FRF_AB_GPIO13_OUT_WIDTH 1
+#define	FRF_AB_GPIO12_OUT_LBN 52
+#define	FRF_AB_GPIO12_OUT_WIDTH 1
+#define	FRF_AB_GPIO11_OUT_LBN 51
+#define	FRF_AB_GPIO11_OUT_WIDTH 1
+#define	FRF_AB_GPIO10_OUT_LBN 50
+#define	FRF_AB_GPIO10_OUT_WIDTH 1
+#define	FRF_AB_GPIO9_OUT_LBN 49
+#define	FRF_AB_GPIO9_OUT_WIDTH 1
+#define	FRF_AB_GPIO8_OUT_LBN 48
+#define	FRF_AB_GPIO8_OUT_WIDTH 1
+#define	FRF_AB_GPIO15_IN_LBN 47
+#define	FRF_AB_GPIO15_IN_WIDTH 1
+#define	FRF_AB_GPIO14_IN_LBN 46
+#define	FRF_AB_GPIO14_IN_WIDTH 1
+#define	FRF_AB_GPIO13_IN_LBN 45
+#define	FRF_AB_GPIO13_IN_WIDTH 1
+#define	FRF_AB_GPIO12_IN_LBN 44
+#define	FRF_AB_GPIO12_IN_WIDTH 1
+#define	FRF_AB_GPIO11_IN_LBN 43
+#define	FRF_AB_GPIO11_IN_WIDTH 1
+#define	FRF_AB_GPIO10_IN_LBN 42
+#define	FRF_AB_GPIO10_IN_WIDTH 1
+#define	FRF_AB_GPIO9_IN_LBN 41
+#define	FRF_AB_GPIO9_IN_WIDTH 1
+#define	FRF_AB_GPIO8_IN_LBN 40
+#define	FRF_AB_GPIO8_IN_WIDTH 1
+#define	FRF_AB_GPIO15_PWRUP_VALUE_LBN 39
+#define	FRF_AB_GPIO15_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO14_PWRUP_VALUE_LBN 38
+#define	FRF_AB_GPIO14_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO13_PWRUP_VALUE_LBN 37
+#define	FRF_AB_GPIO13_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO12_PWRUP_VALUE_LBN 36
+#define	FRF_AB_GPIO12_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO11_PWRUP_VALUE_LBN 35
+#define	FRF_AB_GPIO11_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO10_PWRUP_VALUE_LBN 34
+#define	FRF_AB_GPIO10_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO9_PWRUP_VALUE_LBN 33
+#define	FRF_AB_GPIO9_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO8_PWRUP_VALUE_LBN 32
+#define	FRF_AB_GPIO8_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_CLK156_OUT_EN_LBN 31
+#define	FRF_AB_CLK156_OUT_EN_WIDTH 1
+#define	FRF_AB_USE_NIC_CLK_LBN 30
+#define	FRF_AB_USE_NIC_CLK_WIDTH 1
+#define	FRF_AB_GPIO5_OEN_LBN 29
+#define	FRF_AB_GPIO5_OEN_WIDTH 1
+#define	FRF_AB_GPIO4_OEN_LBN 28
+#define	FRF_AB_GPIO4_OEN_WIDTH 1
+#define	FRF_AB_GPIO3_OEN_LBN 27
+#define	FRF_AB_GPIO3_OEN_WIDTH 1
+#define	FRF_AB_GPIO2_OEN_LBN 26
+#define	FRF_AB_GPIO2_OEN_WIDTH 1
+#define	FRF_AB_GPIO1_OEN_LBN 25
+#define	FRF_AB_GPIO1_OEN_WIDTH 1
+#define	FRF_AB_GPIO0_OEN_LBN 24
+#define	FRF_AB_GPIO0_OEN_WIDTH 1
+#define	FRF_AB_GPIO7_OUT_LBN 23
+#define	FRF_AB_GPIO7_OUT_WIDTH 1
+#define	FRF_AB_GPIO6_OUT_LBN 22
+#define	FRF_AB_GPIO6_OUT_WIDTH 1
+#define	FRF_AB_GPIO5_OUT_LBN 21
+#define	FRF_AB_GPIO5_OUT_WIDTH 1
+#define	FRF_AB_GPIO4_OUT_LBN 20
+#define	FRF_AB_GPIO4_OUT_WIDTH 1
+#define	FRF_AB_GPIO3_OUT_LBN 19
+#define	FRF_AB_GPIO3_OUT_WIDTH 1
+#define	FRF_AB_GPIO2_OUT_LBN 18
+#define	FRF_AB_GPIO2_OUT_WIDTH 1
+#define	FRF_AB_GPIO1_OUT_LBN 17
+#define	FRF_AB_GPIO1_OUT_WIDTH 1
+#define	FRF_AB_GPIO0_OUT_LBN 16
+#define	FRF_AB_GPIO0_OUT_WIDTH 1
+#define	FRF_AB_GPIO7_IN_LBN 15
+#define	FRF_AB_GPIO7_IN_WIDTH 1
+#define	FRF_AB_GPIO6_IN_LBN 14
+#define	FRF_AB_GPIO6_IN_WIDTH 1
+#define	FRF_AB_GPIO5_IN_LBN 13
+#define	FRF_AB_GPIO5_IN_WIDTH 1
+#define	FRF_AB_GPIO4_IN_LBN 12
+#define	FRF_AB_GPIO4_IN_WIDTH 1
+#define	FRF_AB_GPIO3_IN_LBN 11
+#define	FRF_AB_GPIO3_IN_WIDTH 1
+#define	FRF_AB_GPIO2_IN_LBN 10
+#define	FRF_AB_GPIO2_IN_WIDTH 1
+#define	FRF_AB_GPIO1_IN_LBN 9
+#define	FRF_AB_GPIO1_IN_WIDTH 1
+#define	FRF_AB_GPIO0_IN_LBN 8
+#define	FRF_AB_GPIO0_IN_WIDTH 1
+#define	FRF_AB_GPIO7_PWRUP_VALUE_LBN 7
+#define	FRF_AB_GPIO7_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO6_PWRUP_VALUE_LBN 6
+#define	FRF_AB_GPIO6_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO5_PWRUP_VALUE_LBN 5
+#define	FRF_AB_GPIO5_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO4_PWRUP_VALUE_LBN 4
+#define	FRF_AB_GPIO4_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO3_PWRUP_VALUE_LBN 3
+#define	FRF_AB_GPIO3_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO2_PWRUP_VALUE_LBN 2
+#define	FRF_AB_GPIO2_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO1_PWRUP_VALUE_LBN 1
+#define	FRF_AB_GPIO1_PWRUP_VALUE_WIDTH 1
+#define	FRF_AB_GPIO0_PWRUP_VALUE_LBN 0
+#define	FRF_AB_GPIO0_PWRUP_VALUE_WIDTH 1
+
+/* GLB_CTL_REG: Global control register */
+#define	FR_AB_GLB_CTL 0x00000220
+#define	FRF_AB_EXT_PHY_RST_CTL_LBN 63
+#define	FRF_AB_EXT_PHY_RST_CTL_WIDTH 1
+#define	FRF_AB_XAUI_SD_RST_CTL_LBN 62
+#define	FRF_AB_XAUI_SD_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_SD_RST_CTL_LBN 61
+#define	FRF_AB_PCIE_SD_RST_CTL_WIDTH 1
+#define	FRF_AA_PCIX_RST_CTL_LBN 60
+#define	FRF_AA_PCIX_RST_CTL_WIDTH 1
+#define	FRF_BB_BIU_RST_CTL_LBN 60
+#define	FRF_BB_BIU_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_STKY_RST_CTL_LBN 59
+#define	FRF_AB_PCIE_STKY_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_NSTKY_RST_CTL_LBN 58
+#define	FRF_AB_PCIE_NSTKY_RST_CTL_WIDTH 1
+#define	FRF_AB_PCIE_CORE_RST_CTL_LBN 57
+#define	FRF_AB_PCIE_CORE_RST_CTL_WIDTH 1
+#define	FRF_AB_XGRX_RST_CTL_LBN 56
+#define	FRF_AB_XGRX_RST_CTL_WIDTH 1
+#define	FRF_AB_XGTX_RST_CTL_LBN 55
+#define	FRF_AB_XGTX_RST_CTL_WIDTH 1
+#define	FRF_AB_EM_RST_CTL_LBN 54
+#define	FRF_AB_EM_RST_CTL_WIDTH 1
+#define	FRF_AB_EV_RST_CTL_LBN 53
+#define	FRF_AB_EV_RST_CTL_WIDTH 1
+#define	FRF_AB_SR_RST_CTL_LBN 52
+#define	FRF_AB_SR_RST_CTL_WIDTH 1
+#define	FRF_AB_RX_RST_CTL_LBN 51
+#define	FRF_AB_RX_RST_CTL_WIDTH 1
+#define	FRF_AB_TX_RST_CTL_LBN 50
+#define	FRF_AB_TX_RST_CTL_WIDTH 1
+#define	FRF_AB_EE_RST_CTL_LBN 49
+#define	FRF_AB_EE_RST_CTL_WIDTH 1
+#define	FRF_AB_CS_RST_CTL_LBN 48
+#define	FRF_AB_CS_RST_CTL_WIDTH 1
+#define	FRF_AB_HOT_RST_CTL_LBN 40
+#define	FRF_AB_HOT_RST_CTL_WIDTH 2
+#define	FRF_AB_RST_EXT_PHY_LBN 31
+#define	FRF_AB_RST_EXT_PHY_WIDTH 1
+#define	FRF_AB_RST_XAUI_SD_LBN 30
+#define	FRF_AB_RST_XAUI_SD_WIDTH 1
+#define	FRF_AB_RST_PCIE_SD_LBN 29
+#define	FRF_AB_RST_PCIE_SD_WIDTH 1
+#define	FRF_AA_RST_PCIX_LBN 28
+#define	FRF_AA_RST_PCIX_WIDTH 1
+#define	FRF_BB_RST_BIU_LBN 28
+#define	FRF_BB_RST_BIU_WIDTH 1
+#define	FRF_AB_RST_PCIE_STKY_LBN 27
+#define	FRF_AB_RST_PCIE_STKY_WIDTH 1
+#define	FRF_AB_RST_PCIE_NSTKY_LBN 26
+#define	FRF_AB_RST_PCIE_NSTKY_WIDTH 1
+#define	FRF_AB_RST_PCIE_CORE_LBN 25
+#define	FRF_AB_RST_PCIE_CORE_WIDTH 1
+#define	FRF_AB_RST_XGRX_LBN 24
+#define	FRF_AB_RST_XGRX_WIDTH 1
+#define	FRF_AB_RST_XGTX_LBN 23
+#define	FRF_AB_RST_XGTX_WIDTH 1
+#define	FRF_AB_RST_EM_LBN 22
+#define	FRF_AB_RST_EM_WIDTH 1
+#define	FRF_AB_RST_EV_LBN 21
+#define	FRF_AB_RST_EV_WIDTH 1
+#define	FRF_AB_RST_SR_LBN 20
+#define	FRF_AB_RST_SR_WIDTH 1
+#define	FRF_AB_RST_RX_LBN 19
+#define	FRF_AB_RST_RX_WIDTH 1
+#define	FRF_AB_RST_TX_LBN 18
+#define	FRF_AB_RST_TX_WIDTH 1
+#define	FRF_AB_RST_SF_LBN 17
+#define	FRF_AB_RST_SF_WIDTH 1
+#define	FRF_AB_RST_CS_LBN 16
+#define	FRF_AB_RST_CS_WIDTH 1
+#define	FRF_AB_INT_RST_DUR_LBN 4
+#define	FRF_AB_INT_RST_DUR_WIDTH 3
+#define	FRF_AB_EXT_PHY_RST_DUR_LBN 1
+#define	FRF_AB_EXT_PHY_RST_DUR_WIDTH 3
+#define	FFE_AB_EXT_PHY_RST_DUR_10240US 7
+#define	FFE_AB_EXT_PHY_RST_DUR_5120US 6
+#define	FFE_AB_EXT_PHY_RST_DUR_2560US 5
+#define	FFE_AB_EXT_PHY_RST_DUR_1280US 4
+#define	FFE_AB_EXT_PHY_RST_DUR_640US 3
+#define	FFE_AB_EXT_PHY_RST_DUR_320US 2
+#define	FFE_AB_EXT_PHY_RST_DUR_160US 1
+#define	FFE_AB_EXT_PHY_RST_DUR_80US 0
+#define	FRF_AB_SWRST_LBN 0
+#define	FRF_AB_SWRST_WIDTH 1
+
+/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */
+#define	FR_AZ_FATAL_INTR_KER 0x00000230
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_EN_LBN 44
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_EN_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_KER_EN_LBN 43
+#define	FRF_AB_PCI_BUSERR_INT_KER_EN_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_KER_EN_LBN 43
+#define	FRF_CZ_MBU_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_KER_EN_LBN 42
+#define	FRF_AZ_SRAM_OOB_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_BUFID_OOB_INT_KER_EN_LBN 41
+#define	FRF_AZ_BUFID_OOB_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_KER_EN_LBN 40
+#define	FRF_AZ_MEM_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_KER_EN_LBN 39
+#define	FRF_AZ_RBUF_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_KER_EN_LBN 38
+#define	FRF_AZ_TBUF_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_EN_LBN 37
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_EN_LBN 36
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_KER_EN_LBN 35
+#define	FRF_AZ_EVQ_OWN_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_KER_EN_LBN 34
+#define	FRF_AZ_EVF_OFLO_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_KER_EN_LBN 33
+#define	FRF_AZ_ILL_ADR_INT_KER_EN_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_KER_EN_LBN 32
+#define	FRF_AZ_SRM_PERR_INT_KER_EN_WIDTH 1
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_LBN 12
+#define	FRF_CZ_SRAM_PERR_INT_P_KER_WIDTH 1
+#define	FRF_AB_PCI_BUSERR_INT_KER_LBN 11
+#define	FRF_AB_PCI_BUSERR_INT_KER_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_KER_LBN 11
+#define	FRF_CZ_MBU_PERR_INT_KER_WIDTH 1
+#define	FRF_AZ_SRAM_OOB_INT_KER_LBN 10
+#define	FRF_AZ_SRAM_OOB_INT_KER_WIDTH 1
+#define	FRF_AZ_BUFID_DC_OOB_INT_KER_LBN 9
+#define	FRF_AZ_BUFID_DC_OOB_INT_KER_WIDTH 1
+#define	FRF_AZ_MEM_PERR_INT_KER_LBN 8
+#define	FRF_AZ_MEM_PERR_INT_KER_WIDTH 1
+#define	FRF_AZ_RBUF_OWN_INT_KER_LBN 7
+#define	FRF_AZ_RBUF_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_TBUF_OWN_INT_KER_LBN 6
+#define	FRF_AZ_TBUF_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_LBN 5
+#define	FRF_AZ_RDESCQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_LBN 4
+#define	FRF_AZ_TDESCQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_EVQ_OWN_INT_KER_LBN 3
+#define	FRF_AZ_EVQ_OWN_INT_KER_WIDTH 1
+#define	FRF_AZ_EVF_OFLO_INT_KER_LBN 2
+#define	FRF_AZ_EVF_OFLO_INT_KER_WIDTH 1
+#define	FRF_AZ_ILL_ADR_INT_KER_LBN 1
+#define	FRF_AZ_ILL_ADR_INT_KER_WIDTH 1
+#define	FRF_AZ_SRM_PERR_INT_KER_LBN 0
+#define	FRF_AZ_SRM_PERR_INT_KER_WIDTH 1
+
+/* FATAL_INTR_REG_CHAR: Fatal interrupt register for Char */
+#define	FR_BZ_FATAL_INTR_CHAR 0x00000240
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_LBN 44
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_EN_WIDTH 1
+#define	FRF_BB_PCI_BUSERR_INT_CHAR_EN_LBN 43
+#define	FRF_BB_PCI_BUSERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_CHAR_EN_LBN 43
+#define	FRF_CZ_MBU_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_SRAM_OOB_INT_CHAR_EN_LBN 42
+#define	FRF_BZ_SRAM_OOB_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_BUFID_OOB_INT_CHAR_EN_LBN 41
+#define	FRF_BZ_BUFID_OOB_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_MEM_PERR_INT_CHAR_EN_LBN 40
+#define	FRF_BZ_MEM_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_RBUF_OWN_INT_CHAR_EN_LBN 39
+#define	FRF_BZ_RBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_TBUF_OWN_INT_CHAR_EN_LBN 38
+#define	FRF_BZ_TBUF_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_LBN 37
+#define	FRF_BZ_RDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_LBN 36
+#define	FRF_BZ_TDESCQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_EVQ_OWN_INT_CHAR_EN_LBN 35
+#define	FRF_BZ_EVQ_OWN_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_EVF_OFLO_INT_CHAR_EN_LBN 34
+#define	FRF_BZ_EVF_OFLO_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_ILL_ADR_INT_CHAR_EN_LBN 33
+#define	FRF_BZ_ILL_ADR_INT_CHAR_EN_WIDTH 1
+#define	FRF_BZ_SRM_PERR_INT_CHAR_EN_LBN 32
+#define	FRF_BZ_SRM_PERR_INT_CHAR_EN_WIDTH 1
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_LBN 12
+#define	FRF_CZ_SRAM_PERR_INT_P_CHAR_WIDTH 1
+#define	FRF_BB_PCI_BUSERR_INT_CHAR_LBN 11
+#define	FRF_BB_PCI_BUSERR_INT_CHAR_WIDTH 1
+#define	FRF_CZ_MBU_PERR_INT_CHAR_LBN 11
+#define	FRF_CZ_MBU_PERR_INT_CHAR_WIDTH 1
+#define	FRF_BZ_SRAM_OOB_INT_CHAR_LBN 10
+#define	FRF_BZ_SRAM_OOB_INT_CHAR_WIDTH 1
+#define	FRF_BZ_BUFID_DC_OOB_INT_CHAR_LBN 9
+#define	FRF_BZ_BUFID_DC_OOB_INT_CHAR_WIDTH 1
+#define	FRF_BZ_MEM_PERR_INT_CHAR_LBN 8
+#define	FRF_BZ_MEM_PERR_INT_CHAR_WIDTH 1
+#define	FRF_BZ_RBUF_OWN_INT_CHAR_LBN 7
+#define	FRF_BZ_RBUF_OWN_INT_CHAR_WIDTH 1
+#define	FRF_BZ_TBUF_OWN_INT_CHAR_LBN 6
+#define	FRF_BZ_TBUF_OWN_INT_CHAR_WIDTH 1
+#define	FRF_BZ_RDESCQ_OWN_INT_CHAR_LBN 5
+#define	FRF_BZ_RDESCQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_BZ_TDESCQ_OWN_INT_CHAR_LBN 4
+#define	FRF_BZ_TDESCQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_BZ_EVQ_OWN_INT_CHAR_LBN 3
+#define	FRF_BZ_EVQ_OWN_INT_CHAR_WIDTH 1
+#define	FRF_BZ_EVF_OFLO_INT_CHAR_LBN 2
+#define	FRF_BZ_EVF_OFLO_INT_CHAR_WIDTH 1
+#define	FRF_BZ_ILL_ADR_INT_CHAR_LBN 1
+#define	FRF_BZ_ILL_ADR_INT_CHAR_WIDTH 1
+#define	FRF_BZ_SRM_PERR_INT_CHAR_LBN 0
+#define	FRF_BZ_SRM_PERR_INT_CHAR_WIDTH 1
+
+/* DP_CTRL_REG: Datapath control register */
+#define	FR_BZ_DP_CTRL 0x00000250
+#define	FRF_BZ_FLS_EVQ_ID_LBN 0
+#define	FRF_BZ_FLS_EVQ_ID_WIDTH 12
+
+/* MEM_STAT_REG: Memory status register */
+#define	FR_AZ_MEM_STAT 0x00000260
+#define	FRF_AB_MEM_PERR_VEC_LBN 53
+#define	FRF_AB_MEM_PERR_VEC_WIDTH 38
+#define	FRF_AB_MBIST_CORR_LBN 38
+#define	FRF_AB_MBIST_CORR_WIDTH 15
+#define	FRF_AB_MBIST_ERR_LBN 0
+#define	FRF_AB_MBIST_ERR_WIDTH 40
+#define	FRF_CZ_MEM_PERR_VEC_LBN 0
+#define	FRF_CZ_MEM_PERR_VEC_WIDTH 35
+
+/* CS_DEBUG_REG: Debug register */
+#define	FR_AZ_CS_DEBUG 0x00000270
+#define	FRF_AB_GLB_DEBUG2_SEL_LBN 50
+#define	FRF_AB_GLB_DEBUG2_SEL_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL2_LBN 47
+#define	FRF_AB_DEBUG_BLK_SEL2_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL1_LBN 44
+#define	FRF_AB_DEBUG_BLK_SEL1_WIDTH 3
+#define	FRF_AB_DEBUG_BLK_SEL0_LBN 41
+#define	FRF_AB_DEBUG_BLK_SEL0_WIDTH 3
+#define	FRF_CZ_CS_PORT_NUM_LBN 40
+#define	FRF_CZ_CS_PORT_NUM_WIDTH 2
+#define	FRF_AB_MISC_DEBUG_ADDR_LBN 36
+#define	FRF_AB_MISC_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_SERDES_DEBUG_ADDR_LBN 31
+#define	FRF_AB_SERDES_DEBUG_ADDR_WIDTH 5
+#define	FRF_CZ_CS_PORT_FPE_LBN 1
+#define	FRF_CZ_CS_PORT_FPE_WIDTH 35
+#define	FRF_AB_EM_DEBUG_ADDR_LBN 26
+#define	FRF_AB_EM_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_SR_DEBUG_ADDR_LBN 21
+#define	FRF_AB_SR_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_EV_DEBUG_ADDR_LBN 16
+#define	FRF_AB_EV_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_RX_DEBUG_ADDR_LBN 11
+#define	FRF_AB_RX_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_TX_DEBUG_ADDR_LBN 6
+#define	FRF_AB_TX_DEBUG_ADDR_WIDTH 5
+#define	FRF_AB_CS_BIU_DEBUG_ADDR_LBN 1
+#define	FRF_AB_CS_BIU_DEBUG_ADDR_WIDTH 5
+#define	FRF_AZ_CS_DEBUG_EN_LBN 0
+#define	FRF_AZ_CS_DEBUG_EN_WIDTH 1
+
+/* DRIVER_REG: Driver scratch register [0-7] */
+#define	FR_AZ_DRIVER 0x00000280
+#define	FR_AZ_DRIVER_STEP 16
+#define	FR_AZ_DRIVER_ROWS 8
+#define	FRF_AZ_DRIVER_DW0_LBN 0
+#define	FRF_AZ_DRIVER_DW0_WIDTH 32
+
+/* ALTERA_BUILD_REG: Altera build register */
+#define	FR_AZ_ALTERA_BUILD 0x00000300
+#define	FRF_AZ_ALTERA_BUILD_VER_LBN 0
+#define	FRF_AZ_ALTERA_BUILD_VER_WIDTH 32
+
+/* CSR_SPARE_REG: Spare register */
+#define	FR_AZ_CSR_SPARE 0x00000310
+#define	FRF_AB_MEM_PERR_EN_LBN 64
+#define	FRF_AB_MEM_PERR_EN_WIDTH 38
+#define	FRF_CZ_MEM_PERR_EN_LBN 64
+#define	FRF_CZ_MEM_PERR_EN_WIDTH 35
+#define	FRF_AB_MEM_PERR_EN_TX_DATA_LBN 72
+#define	FRF_AB_MEM_PERR_EN_TX_DATA_WIDTH 2
+#define	FRF_AZ_CSR_SPARE_BITS_LBN 0
+#define	FRF_AZ_CSR_SPARE_BITS_WIDTH 32
+
+/* PCIE_SD_CTL0123_REG: PCIE SerDes control register 0 to 3 */
+#define	FR_AB_PCIE_SD_CTL0123 0x00000320
+#define	FRF_AB_PCIE_TESTSIG_H_LBN 96
+#define	FRF_AB_PCIE_TESTSIG_H_WIDTH 19
+#define	FRF_AB_PCIE_TESTSIG_L_LBN 64
+#define	FRF_AB_PCIE_TESTSIG_L_WIDTH 19
+#define	FRF_AB_PCIE_OFFSET_LBN 56
+#define	FRF_AB_PCIE_OFFSET_WIDTH 8
+#define	FRF_AB_PCIE_OFFSETEN_H_LBN 55
+#define	FRF_AB_PCIE_OFFSETEN_H_WIDTH 1
+#define	FRF_AB_PCIE_OFFSETEN_L_LBN 54
+#define	FRF_AB_PCIE_OFFSETEN_L_WIDTH 1
+#define	FRF_AB_PCIE_HIVMODE_H_LBN 53
+#define	FRF_AB_PCIE_HIVMODE_H_WIDTH 1
+#define	FRF_AB_PCIE_HIVMODE_L_LBN 52
+#define	FRF_AB_PCIE_HIVMODE_L_WIDTH 1
+#define	FRF_AB_PCIE_PARRESET_H_LBN 51
+#define	FRF_AB_PCIE_PARRESET_H_WIDTH 1
+#define	FRF_AB_PCIE_PARRESET_L_LBN 50
+#define	FRF_AB_PCIE_PARRESET_L_WIDTH 1
+#define	FRF_AB_PCIE_LPBKWDRV_H_LBN 49
+#define	FRF_AB_PCIE_LPBKWDRV_H_WIDTH 1
+#define	FRF_AB_PCIE_LPBKWDRV_L_LBN 48
+#define	FRF_AB_PCIE_LPBKWDRV_L_WIDTH 1
+#define	FRF_AB_PCIE_LPBK_LBN 40
+#define	FRF_AB_PCIE_LPBK_WIDTH 8
+#define	FRF_AB_PCIE_PARLPBK_LBN 32
+#define	FRF_AB_PCIE_PARLPBK_WIDTH 8
+#define	FRF_AB_PCIE_RXTERMADJ_H_LBN 30
+#define	FRF_AB_PCIE_RXTERMADJ_H_WIDTH 2
+#define	FRF_AB_PCIE_RXTERMADJ_L_LBN 28
+#define	FRF_AB_PCIE_RXTERMADJ_L_WIDTH 2
+#define	FFE_AB_PCIE_RXTERMADJ_MIN15PCNT 3
+#define	FFE_AB_PCIE_RXTERMADJ_PL10PCNT 2
+#define	FFE_AB_PCIE_RXTERMADJ_MIN17PCNT 1
+#define	FFE_AB_PCIE_RXTERMADJ_NOMNL 0
+#define	FRF_AB_PCIE_TXTERMADJ_H_LBN 26
+#define	FRF_AB_PCIE_TXTERMADJ_H_WIDTH 2
+#define	FRF_AB_PCIE_TXTERMADJ_L_LBN 24
+#define	FRF_AB_PCIE_TXTERMADJ_L_WIDTH 2
+#define	FFE_AB_PCIE_TXTERMADJ_MIN15PCNT 3
+#define	FFE_AB_PCIE_TXTERMADJ_PL10PCNT 2
+#define	FFE_AB_PCIE_TXTERMADJ_MIN17PCNT 1
+#define	FFE_AB_PCIE_TXTERMADJ_NOMNL 0
+#define	FRF_AB_PCIE_RXEQCTL_H_LBN 18
+#define	FRF_AB_PCIE_RXEQCTL_H_WIDTH 2
+#define	FRF_AB_PCIE_RXEQCTL_L_LBN 16
+#define	FRF_AB_PCIE_RXEQCTL_L_WIDTH 2
+#define	FFE_AB_PCIE_RXEQCTL_OFF_ALT 3
+#define	FFE_AB_PCIE_RXEQCTL_OFF 2
+#define	FFE_AB_PCIE_RXEQCTL_MIN 1
+#define	FFE_AB_PCIE_RXEQCTL_MAX 0
+#define	FRF_AB_PCIE_HIDRV_LBN 8
+#define	FRF_AB_PCIE_HIDRV_WIDTH 8
+#define	FRF_AB_PCIE_LODRV_LBN 0
+#define	FRF_AB_PCIE_LODRV_WIDTH 8
+
+/* PCIE_SD_CTL45_REG: PCIE SerDes control register 4 and 5 */
+#define	FR_AB_PCIE_SD_CTL45 0x00000330
+#define	FRF_AB_PCIE_DTX7_LBN 60
+#define	FRF_AB_PCIE_DTX7_WIDTH 4
+#define	FRF_AB_PCIE_DTX6_LBN 56
+#define	FRF_AB_PCIE_DTX6_WIDTH 4
+#define	FRF_AB_PCIE_DTX5_LBN 52
+#define	FRF_AB_PCIE_DTX5_WIDTH 4
+#define	FRF_AB_PCIE_DTX4_LBN 48
+#define	FRF_AB_PCIE_DTX4_WIDTH 4
+#define	FRF_AB_PCIE_DTX3_LBN 44
+#define	FRF_AB_PCIE_DTX3_WIDTH 4
+#define	FRF_AB_PCIE_DTX2_LBN 40
+#define	FRF_AB_PCIE_DTX2_WIDTH 4
+#define	FRF_AB_PCIE_DTX1_LBN 36
+#define	FRF_AB_PCIE_DTX1_WIDTH 4
+#define	FRF_AB_PCIE_DTX0_LBN 32
+#define	FRF_AB_PCIE_DTX0_WIDTH 4
+#define	FRF_AB_PCIE_DEQ7_LBN 28
+#define	FRF_AB_PCIE_DEQ7_WIDTH 4
+#define	FRF_AB_PCIE_DEQ6_LBN 24
+#define	FRF_AB_PCIE_DEQ6_WIDTH 4
+#define	FRF_AB_PCIE_DEQ5_LBN 20
+#define	FRF_AB_PCIE_DEQ5_WIDTH 4
+#define	FRF_AB_PCIE_DEQ4_LBN 16
+#define	FRF_AB_PCIE_DEQ4_WIDTH 4
+#define	FRF_AB_PCIE_DEQ3_LBN 12
+#define	FRF_AB_PCIE_DEQ3_WIDTH 4
+#define	FRF_AB_PCIE_DEQ2_LBN 8
+#define	FRF_AB_PCIE_DEQ2_WIDTH 4
+#define	FRF_AB_PCIE_DEQ1_LBN 4
+#define	FRF_AB_PCIE_DEQ1_WIDTH 4
+#define	FRF_AB_PCIE_DEQ0_LBN 0
+#define	FRF_AB_PCIE_DEQ0_WIDTH 4
+
+/* PCIE_PCS_CTL_STAT_REG: PCIE PCS control and status register */
+#define	FR_AB_PCIE_PCS_CTL_STAT 0x00000340
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_H_LBN 52
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_H_WIDTH 4
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_L_LBN 48
+#define	FRF_AB_PCIE_PRBSERRCOUNT0_L_WIDTH 4
+#define	FRF_AB_PCIE_PRBSERR_LBN 40
+#define	FRF_AB_PCIE_PRBSERR_WIDTH 8
+#define	FRF_AB_PCIE_PRBSERRH0_LBN 32
+#define	FRF_AB_PCIE_PRBSERRH0_WIDTH 8
+#define	FRF_AB_PCIE_FASTINIT_H_LBN 15
+#define	FRF_AB_PCIE_FASTINIT_H_WIDTH 1
+#define	FRF_AB_PCIE_FASTINIT_L_LBN 14
+#define	FRF_AB_PCIE_FASTINIT_L_WIDTH 1
+#define	FRF_AB_PCIE_CTCDISABLE_H_LBN 13
+#define	FRF_AB_PCIE_CTCDISABLE_H_WIDTH 1
+#define	FRF_AB_PCIE_CTCDISABLE_L_LBN 12
+#define	FRF_AB_PCIE_CTCDISABLE_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSYNC_H_LBN 11
+#define	FRF_AB_PCIE_PRBSSYNC_H_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSYNC_L_LBN 10
+#define	FRF_AB_PCIE_PRBSSYNC_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSERRACK_H_LBN 9
+#define	FRF_AB_PCIE_PRBSERRACK_H_WIDTH 1
+#define	FRF_AB_PCIE_PRBSERRACK_L_LBN 8
+#define	FRF_AB_PCIE_PRBSERRACK_L_WIDTH 1
+#define	FRF_AB_PCIE_PRBSSEL_LBN 0
+#define	FRF_AB_PCIE_PRBSSEL_WIDTH 8
+
+/* DEBUG_DATA_OUT_REG: Live Debug and Debug 2 out ports */
+#define	FR_BB_DEBUG_DATA_OUT 0x00000350
+#define	FRF_BB_DEBUG2_PORT_LBN 25
+#define	FRF_BB_DEBUG2_PORT_WIDTH 15
+#define	FRF_BB_DEBUG1_PORT_LBN 0
+#define	FRF_BB_DEBUG1_PORT_WIDTH 25
+
+/* EVQ_RPTR_REGP0: Event queue read pointer register */
+#define	FR_BZ_EVQ_RPTR_P0 0x00000400
+#define	FR_BZ_EVQ_RPTR_P0_STEP 8192
+#define	FR_BZ_EVQ_RPTR_P0_ROWS 1024
+/* EVQ_RPTR_REG_KER: Event queue read pointer register */
+#define	FR_AA_EVQ_RPTR_KER 0x00011b00
+#define	FR_AA_EVQ_RPTR_KER_STEP 4
+#define	FR_AA_EVQ_RPTR_KER_ROWS 4
+/* EVQ_RPTR_REG: Event queue read pointer register */
+#define	FR_BZ_EVQ_RPTR 0x00fa0000
+#define	FR_BZ_EVQ_RPTR_STEP 16
+#define	FR_BB_EVQ_RPTR_ROWS 4096
+#define	FR_CZ_EVQ_RPTR_ROWS 1024
+/* EVQ_RPTR_REGP123: Event queue read pointer register */
+#define	FR_BB_EVQ_RPTR_P123 0x01000400
+#define	FR_BB_EVQ_RPTR_P123_STEP 8192
+#define	FR_BB_EVQ_RPTR_P123_ROWS 3072
+#define	FRF_AZ_EVQ_RPTR_VLD_LBN 15
+#define	FRF_AZ_EVQ_RPTR_VLD_WIDTH 1
+#define	FRF_AZ_EVQ_RPTR_LBN 0
+#define	FRF_AZ_EVQ_RPTR_WIDTH 15
+
+/* TIMER_COMMAND_REGP0: Timer Command Registers */
+#define	FR_BZ_TIMER_COMMAND_P0 0x00000420
+#define	FR_BZ_TIMER_COMMAND_P0_STEP 8192
+#define	FR_BZ_TIMER_COMMAND_P0_ROWS 1024
+/* TIMER_COMMAND_REG_KER: Timer Command Registers */
+#define	FR_AA_TIMER_COMMAND_KER 0x00000420
+#define	FR_AA_TIMER_COMMAND_KER_STEP 8192
+#define	FR_AA_TIMER_COMMAND_KER_ROWS 4
+/* TIMER_COMMAND_REGP123: Timer Command Registers */
+#define	FR_BB_TIMER_COMMAND_P123 0x01000420
+#define	FR_BB_TIMER_COMMAND_P123_STEP 8192
+#define	FR_BB_TIMER_COMMAND_P123_ROWS 3072
+#define	FRF_CZ_TC_TIMER_MODE_LBN 14
+#define	FRF_CZ_TC_TIMER_MODE_WIDTH 2
+#define	FRF_AB_TC_TIMER_MODE_LBN 12
+#define	FRF_AB_TC_TIMER_MODE_WIDTH 2
+#define	FRF_CZ_TC_TIMER_VAL_LBN 0
+#define	FRF_CZ_TC_TIMER_VAL_WIDTH 14
+#define	FRF_AB_TC_TIMER_VAL_LBN 0
+#define	FRF_AB_TC_TIMER_VAL_WIDTH 12
+
+/* DRV_EV_REG: Driver generated event register */
+#define	FR_AZ_DRV_EV 0x00000440
+#define	FRF_AZ_DRV_EV_QID_LBN 64
+#define	FRF_AZ_DRV_EV_QID_WIDTH 12
+#define	FRF_AZ_DRV_EV_DATA_LBN 0
+#define	FRF_AZ_DRV_EV_DATA_WIDTH 64
+
+/* EVQ_CTL_REG: Event queue control register */
+#define	FR_AZ_EVQ_CTL 0x00000450
+#define	FRF_CZ_RX_EVQ_WAKEUP_MASK_LBN 15
+#define	FRF_CZ_RX_EVQ_WAKEUP_MASK_WIDTH 10
+#define	FRF_BB_RX_EVQ_WAKEUP_MASK_LBN 15
+#define	FRF_BB_RX_EVQ_WAKEUP_MASK_WIDTH 6
+#define	FRF_AZ_EVQ_OWNERR_CTL_LBN 14
+#define	FRF_AZ_EVQ_OWNERR_CTL_WIDTH 1
+#define	FRF_AZ_EVQ_FIFO_AF_TH_LBN 7
+#define	FRF_AZ_EVQ_FIFO_AF_TH_WIDTH 7
+#define	FRF_AZ_EVQ_FIFO_NOTAF_TH_LBN 0
+#define	FRF_AZ_EVQ_FIFO_NOTAF_TH_WIDTH 7
+
+/* EVQ_CNT1_REG: Event counter 1 register */
+#define	FR_AZ_EVQ_CNT1 0x00000460
+#define	FRF_AZ_EVQ_CNT_PRE_FIFO_LBN 120
+#define	FRF_AZ_EVQ_CNT_PRE_FIFO_WIDTH 7
+#define	FRF_AZ_EVQ_CNT_TOBIU_LBN 100
+#define	FRF_AZ_EVQ_CNT_TOBIU_WIDTH 20
+#define	FRF_AZ_EVQ_TX_REQ_CNT_LBN 80
+#define	FRF_AZ_EVQ_TX_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_RX_REQ_CNT_LBN 60
+#define	FRF_AZ_EVQ_RX_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_EM_REQ_CNT_LBN 40
+#define	FRF_AZ_EVQ_EM_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_CSR_REQ_CNT_LBN 20
+#define	FRF_AZ_EVQ_CSR_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_ERR_REQ_CNT_LBN 0
+#define	FRF_AZ_EVQ_ERR_REQ_CNT_WIDTH 20
+
+/* EVQ_CNT2_REG: Event counter 2 register */
+#define	FR_AZ_EVQ_CNT2 0x00000470
+#define	FRF_AZ_EVQ_UPD_REQ_CNT_LBN 104
+#define	FRF_AZ_EVQ_UPD_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_CLR_REQ_CNT_LBN 84
+#define	FRF_AZ_EVQ_CLR_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_RDY_CNT_LBN 80
+#define	FRF_AZ_EVQ_RDY_CNT_WIDTH 4
+#define	FRF_AZ_EVQ_WU_REQ_CNT_LBN 60
+#define	FRF_AZ_EVQ_WU_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_WET_REQ_CNT_LBN 40
+#define	FRF_AZ_EVQ_WET_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_INIT_REQ_CNT_LBN 20
+#define	FRF_AZ_EVQ_INIT_REQ_CNT_WIDTH 20
+#define	FRF_AZ_EVQ_TM_REQ_CNT_LBN 0
+#define	FRF_AZ_EVQ_TM_REQ_CNT_WIDTH 20
+
+/* USR_EV_REG: Event mailbox register */
+#define	FR_CZ_USR_EV 0x00000540
+#define	FR_CZ_USR_EV_STEP 8192
+#define	FR_CZ_USR_EV_ROWS 1024
+#define	FRF_CZ_USR_EV_DATA_LBN 0
+#define	FRF_CZ_USR_EV_DATA_WIDTH 32
+
+/* BUF_TBL_CFG_REG: Buffer table configuration register */
+#define	FR_AZ_BUF_TBL_CFG 0x00000600
+#define	FRF_AZ_BUF_TBL_MODE_LBN 3
+#define	FRF_AZ_BUF_TBL_MODE_WIDTH 1
+
+/* SRM_RX_DC_CFG_REG: SRAM receive descriptor cache configuration register */
+#define	FR_AZ_SRM_RX_DC_CFG 0x00000610
+#define	FRF_AZ_SRM_CLK_TMP_EN_LBN 21
+#define	FRF_AZ_SRM_CLK_TMP_EN_WIDTH 1
+#define	FRF_AZ_SRM_RX_DC_BASE_ADR_LBN 0
+#define	FRF_AZ_SRM_RX_DC_BASE_ADR_WIDTH 21
+
+/* SRM_TX_DC_CFG_REG: SRAM transmit descriptor cache configuration register */
+#define	FR_AZ_SRM_TX_DC_CFG 0x00000620
+#define	FRF_AZ_SRM_TX_DC_BASE_ADR_LBN 0
+#define	FRF_AZ_SRM_TX_DC_BASE_ADR_WIDTH 21
+
+/* SRM_CFG_REG: SRAM configuration register */
+#define	FR_AZ_SRM_CFG 0x00000630
+#define	FRF_AZ_SRM_OOB_ADR_INTEN_LBN 5
+#define	FRF_AZ_SRM_OOB_ADR_INTEN_WIDTH 1
+#define	FRF_AZ_SRM_OOB_BUF_INTEN_LBN 4
+#define	FRF_AZ_SRM_OOB_BUF_INTEN_WIDTH 1
+#define	FRF_AZ_SRM_INIT_EN_LBN 3
+#define	FRF_AZ_SRM_INIT_EN_WIDTH 1
+#define	FRF_AZ_SRM_NUM_BANK_LBN 2
+#define	FRF_AZ_SRM_NUM_BANK_WIDTH 1
+#define	FRF_AZ_SRM_BANK_SIZE_LBN 0
+#define	FRF_AZ_SRM_BANK_SIZE_WIDTH 2
+
+/* BUF_TBL_UPD_REG: Buffer table update register */
+#define	FR_AZ_BUF_TBL_UPD 0x00000650
+#define	FRF_AZ_BUF_UPD_CMD_LBN 63
+#define	FRF_AZ_BUF_UPD_CMD_WIDTH 1
+#define	FRF_AZ_BUF_CLR_CMD_LBN 62
+#define	FRF_AZ_BUF_CLR_CMD_WIDTH 1
+#define	FRF_AZ_BUF_CLR_END_ID_LBN 32
+#define	FRF_AZ_BUF_CLR_END_ID_WIDTH 20
+#define	FRF_AZ_BUF_CLR_START_ID_LBN 0
+#define	FRF_AZ_BUF_CLR_START_ID_WIDTH 20
+
+/* SRM_UPD_EVQ_REG: Buffer table update register */
+#define	FR_AZ_SRM_UPD_EVQ 0x00000660
+#define	FRF_AZ_SRM_UPD_EVQ_ID_LBN 0
+#define	FRF_AZ_SRM_UPD_EVQ_ID_WIDTH 12
+
+/* SRAM_PARITY_REG: SRAM parity register. */
+#define	FR_AZ_SRAM_PARITY 0x00000670
+#define	FRF_CZ_BYPASS_ECC_LBN 3
+#define	FRF_CZ_BYPASS_ECC_WIDTH 1
+#define	FRF_CZ_SEC_INT_LBN 2
+#define	FRF_CZ_SEC_INT_WIDTH 1
+#define	FRF_CZ_FORCE_SRAM_DOUBLE_ERR_LBN 1
+#define	FRF_CZ_FORCE_SRAM_DOUBLE_ERR_WIDTH 1
+#define	FRF_AB_FORCE_SRAM_PERR_LBN 0
+#define	FRF_AB_FORCE_SRAM_PERR_WIDTH 1
+#define	FRF_CZ_FORCE_SRAM_SINGLE_ERR_LBN 0
+#define	FRF_CZ_FORCE_SRAM_SINGLE_ERR_WIDTH 1
+
+/* RX_CFG_REG: Receive configuration register */
+#define	FR_AZ_RX_CFG 0x00000800
+#define	FRF_CZ_RX_MIN_KBUF_SIZE_LBN 72
+#define	FRF_CZ_RX_MIN_KBUF_SIZE_WIDTH 14
+#define	FRF_CZ_RX_HDR_SPLIT_EN_LBN 71
+#define	FRF_CZ_RX_HDR_SPLIT_EN_WIDTH 1
+#define	FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_LBN 62
+#define	FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH 9
+#define	FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_LBN 53
+#define	FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH 9
+#define	FRF_CZ_RX_PRE_RFF_IPG_LBN 49
+#define	FRF_CZ_RX_PRE_RFF_IPG_WIDTH 4
+#define	FRF_BZ_RX_TCP_SUP_LBN 48
+#define	FRF_BZ_RX_TCP_SUP_WIDTH 1
+#define	FRF_BZ_RX_INGR_EN_LBN 47
+#define	FRF_BZ_RX_INGR_EN_WIDTH 1
+#define	FRF_BZ_RX_IP_HASH_LBN 46
+#define	FRF_BZ_RX_IP_HASH_WIDTH 1
+#define	FRF_BZ_RX_HASH_ALG_LBN 45
+#define	FRF_BZ_RX_HASH_ALG_WIDTH 1
+#define	FRF_BZ_RX_HASH_INSRT_HDR_LBN 44
+#define	FRF_BZ_RX_HASH_INSRT_HDR_WIDTH 1
+#define	FRF_BZ_RX_DESC_PUSH_EN_LBN 43
+#define	FRF_BZ_RX_DESC_PUSH_EN_WIDTH 1
+#define	FRF_BZ_RX_RDW_PATCH_EN_LBN 42
+#define	FRF_BZ_RX_RDW_PATCH_EN_WIDTH 1
+#define	FRF_BB_RX_PCI_BURST_SIZE_LBN 39
+#define	FRF_BB_RX_PCI_BURST_SIZE_WIDTH 3
+#define	FRF_BZ_RX_OWNERR_CTL_LBN 38
+#define	FRF_BZ_RX_OWNERR_CTL_WIDTH 1
+#define	FRF_BZ_RX_XON_TX_TH_LBN 33
+#define	FRF_BZ_RX_XON_TX_TH_WIDTH 5
+#define	FRF_AA_RX_DESC_PUSH_EN_LBN 35
+#define	FRF_AA_RX_DESC_PUSH_EN_WIDTH 1
+#define	FRF_AA_RX_RDW_PATCH_EN_LBN 34
+#define	FRF_AA_RX_RDW_PATCH_EN_WIDTH 1
+#define	FRF_AA_RX_PCI_BURST_SIZE_LBN 31
+#define	FRF_AA_RX_PCI_BURST_SIZE_WIDTH 3
+#define	FRF_BZ_RX_XOFF_TX_TH_LBN 28
+#define	FRF_BZ_RX_XOFF_TX_TH_WIDTH 5
+#define	FRF_AA_RX_OWNERR_CTL_LBN 30
+#define	FRF_AA_RX_OWNERR_CTL_WIDTH 1
+#define	FRF_AA_RX_XON_TX_TH_LBN 25
+#define	FRF_AA_RX_XON_TX_TH_WIDTH 5
+#define	FRF_BZ_RX_USR_BUF_SIZE_LBN 19
+#define	FRF_BZ_RX_USR_BUF_SIZE_WIDTH 9
+#define	FRF_AA_RX_XOFF_TX_TH_LBN 20
+#define	FRF_AA_RX_XOFF_TX_TH_WIDTH 5
+#define	FRF_AA_RX_USR_BUF_SIZE_LBN 11
+#define	FRF_AA_RX_USR_BUF_SIZE_WIDTH 9
+#define	FRF_BZ_RX_XON_MAC_TH_LBN 10
+#define	FRF_BZ_RX_XON_MAC_TH_WIDTH 9
+#define	FRF_AA_RX_XON_MAC_TH_LBN 6
+#define	FRF_AA_RX_XON_MAC_TH_WIDTH 5
+#define	FRF_BZ_RX_XOFF_MAC_TH_LBN 1
+#define	FRF_BZ_RX_XOFF_MAC_TH_WIDTH 9
+#define	FRF_AA_RX_XOFF_MAC_TH_LBN 1
+#define	FRF_AA_RX_XOFF_MAC_TH_WIDTH 5
+#define	FRF_AZ_RX_XOFF_MAC_EN_LBN 0
+#define	FRF_AZ_RX_XOFF_MAC_EN_WIDTH 1
+
+/* RX_FILTER_CTL_REG: Receive filter control registers */
+#define	FR_BZ_RX_FILTER_CTL 0x00000810
+#define	FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_LBN 94
+#define	FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT_WIDTH 8
+#define	FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_LBN 86
+#define	FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT_WIDTH 8
+#define	FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_LBN 85
+#define	FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES_WIDTH 1
+#define	FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_LBN 69
+#define	FRF_CZ_RX_VLAN_MATCH_ETHERTYPE_WIDTH 16
+#define	FRF_CZ_MULTICAST_NOMATCH_Q_ID_LBN 57
+#define	FRF_CZ_MULTICAST_NOMATCH_Q_ID_WIDTH 12
+#define	FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_LBN 56
+#define	FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define	FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_LBN 55
+#define	FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define	FRF_CZ_UNICAST_NOMATCH_Q_ID_LBN 43
+#define	FRF_CZ_UNICAST_NOMATCH_Q_ID_WIDTH 12
+#define	FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_LBN 42
+#define	FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED_WIDTH 1
+#define	FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_LBN 41
+#define	FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE_WIDTH 1
+#define	FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_LBN 40
+#define	FRF_BZ_SCATTER_ENBL_NO_MATCH_Q_WIDTH 1
+#define	FRF_BZ_UDP_FULL_SRCH_LIMIT_LBN 32
+#define	FRF_BZ_UDP_FULL_SRCH_LIMIT_WIDTH 8
+#define	FRF_BZ_NUM_KER_LBN 24
+#define	FRF_BZ_NUM_KER_WIDTH 2
+#define	FRF_BZ_UDP_WILD_SRCH_LIMIT_LBN 16
+#define	FRF_BZ_UDP_WILD_SRCH_LIMIT_WIDTH 8
+#define	FRF_BZ_TCP_WILD_SRCH_LIMIT_LBN 8
+#define	FRF_BZ_TCP_WILD_SRCH_LIMIT_WIDTH 8
+#define	FRF_BZ_TCP_FULL_SRCH_LIMIT_LBN 0
+#define	FRF_BZ_TCP_FULL_SRCH_LIMIT_WIDTH 8
+
+/* RX_FLUSH_DESCQ_REG: Receive flush descriptor queue register */
+#define	FR_AZ_RX_FLUSH_DESCQ 0x00000820
+#define	FRF_AZ_RX_FLUSH_DESCQ_CMD_LBN 24
+#define	FRF_AZ_RX_FLUSH_DESCQ_CMD_WIDTH 1
+#define	FRF_AZ_RX_FLUSH_DESCQ_LBN 0
+#define	FRF_AZ_RX_FLUSH_DESCQ_WIDTH 12
+
+/* RX_DESC_UPD_REGP0: Receive descriptor update register. */
+#define	FR_BZ_RX_DESC_UPD_P0 0x00000830
+#define	FR_BZ_RX_DESC_UPD_P0_STEP 8192
+#define	FR_BZ_RX_DESC_UPD_P0_ROWS 1024
+/* RX_DESC_UPD_REG_KER: Receive descriptor update register. */
+#define	FR_AA_RX_DESC_UPD_KER 0x00000830
+#define	FR_AA_RX_DESC_UPD_KER_STEP 8192
+#define	FR_AA_RX_DESC_UPD_KER_ROWS 4
+/* RX_DESC_UPD_REGP123: Receive descriptor update register. */
+#define	FR_BB_RX_DESC_UPD_P123 0x01000830
+#define	FR_BB_RX_DESC_UPD_P123_STEP 8192
+#define	FR_BB_RX_DESC_UPD_P123_ROWS 3072
+#define	FRF_AZ_RX_DESC_WPTR_LBN 96
+#define	FRF_AZ_RX_DESC_WPTR_WIDTH 12
+#define	FRF_AZ_RX_DESC_PUSH_CMD_LBN 95
+#define	FRF_AZ_RX_DESC_PUSH_CMD_WIDTH 1
+#define	FRF_AZ_RX_DESC_LBN 0
+#define	FRF_AZ_RX_DESC_WIDTH 64
+
+/* RX_DC_CFG_REG: Receive descriptor cache configuration register */
+#define	FR_AZ_RX_DC_CFG 0x00000840
+#define	FRF_AB_RX_MAX_PF_LBN 2
+#define	FRF_AB_RX_MAX_PF_WIDTH 2
+#define	FRF_AZ_RX_DC_SIZE_LBN 0
+#define	FRF_AZ_RX_DC_SIZE_WIDTH 2
+#define	FFE_AZ_RX_DC_SIZE_64 3
+#define	FFE_AZ_RX_DC_SIZE_32 2
+#define	FFE_AZ_RX_DC_SIZE_16 1
+#define	FFE_AZ_RX_DC_SIZE_8 0
+
+/* RX_DC_PF_WM_REG: Receive descriptor cache pre-fetch watermark register */
+#define	FR_AZ_RX_DC_PF_WM 0x00000850
+#define	FRF_AZ_RX_DC_PF_HWM_LBN 6
+#define	FRF_AZ_RX_DC_PF_HWM_WIDTH 6
+#define	FRF_AZ_RX_DC_PF_LWM_LBN 0
+#define	FRF_AZ_RX_DC_PF_LWM_WIDTH 6
+
+/* RX_RSS_TKEY_REG: RSS Toeplitz hash key */
+#define	FR_BZ_RX_RSS_TKEY 0x00000860
+#define	FRF_BZ_RX_RSS_TKEY_HI_LBN 64
+#define	FRF_BZ_RX_RSS_TKEY_HI_WIDTH 64
+#define	FRF_BZ_RX_RSS_TKEY_LO_LBN 0
+#define	FRF_BZ_RX_RSS_TKEY_LO_WIDTH 64
+
+/* RX_NODESC_DROP_REG: Receive dropped packet counter register */
+#define	FR_AZ_RX_NODESC_DROP 0x00000880
+#define	FRF_CZ_RX_NODESC_DROP_CNT_LBN 0
+#define	FRF_CZ_RX_NODESC_DROP_CNT_WIDTH 32
+#define	FRF_AB_RX_NODESC_DROP_CNT_LBN 0
+#define	FRF_AB_RX_NODESC_DROP_CNT_WIDTH 16
+
+/* RX_SELF_RST_REG: Receive self reset register */
+#define	FR_AA_RX_SELF_RST 0x00000890
+#define	FRF_AA_RX_ISCSI_DIS_LBN 17
+#define	FRF_AA_RX_ISCSI_DIS_WIDTH 1
+#define	FRF_AA_RX_SW_RST_REG_LBN 16
+#define	FRF_AA_RX_SW_RST_REG_WIDTH 1
+#define FRF_AA_RX_NODESC_WAIT_DIS_LBN 9
+#define FRF_AA_RX_NODESC_WAIT_DIS_WIDTH 1
+#define	FRF_AA_RX_SELF_RST_EN_LBN 8
+#define	FRF_AA_RX_SELF_RST_EN_WIDTH 1
+#define	FRF_AA_RX_MAX_PF_LAT_LBN 4
+#define	FRF_AA_RX_MAX_PF_LAT_WIDTH 4
+#define	FRF_AA_RX_MAX_LU_LAT_LBN 0
+#define	FRF_AA_RX_MAX_LU_LAT_WIDTH 4
+
+/* RX_DEBUG_REG: undocumented register */
+#define	FR_AZ_RX_DEBUG 0x000008a0
+#define	FRF_AZ_RX_DEBUG_LBN 0
+#define	FRF_AZ_RX_DEBUG_WIDTH 64
+
+/* RX_PUSH_DROP_REG: Receive descriptor push dropped counter register */
+#define	FR_AZ_RX_PUSH_DROP 0x000008b0
+#define	FRF_AZ_RX_PUSH_DROP_CNT_LBN 0
+#define	FRF_AZ_RX_PUSH_DROP_CNT_WIDTH 32
+
+/* RX_RSS_IPV6_REG1: IPv6 RSS Toeplitz hash key low bytes */
+#define	FR_CZ_RX_RSS_IPV6_REG1 0x000008d0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH 128
+
+/* RX_RSS_IPV6_REG2: IPv6 RSS Toeplitz hash key middle bytes */
+#define	FR_CZ_RX_RSS_IPV6_REG2 0x000008e0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH 128
+
+/* RX_RSS_IPV6_REG3: IPv6 RSS Toeplitz hash key upper bytes and IPv6 RSS settings */
+#define	FR_CZ_RX_RSS_IPV6_REG3 0x000008f0
+#define	FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_LBN 66
+#define	FRF_CZ_RX_RSS_IPV6_THASH_ENABLE_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_LBN 65
+#define	FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_LBN 64
+#define	FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS_WIDTH 1
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN 0
+#define	FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH 64
+
+/* TX_FLUSH_DESCQ_REG: Transmit flush descriptor queue register */
+#define	FR_AZ_TX_FLUSH_DESCQ 0x00000a00
+#define	FRF_AZ_TX_FLUSH_DESCQ_CMD_LBN 12
+#define	FRF_AZ_TX_FLUSH_DESCQ_CMD_WIDTH 1
+#define	FRF_AZ_TX_FLUSH_DESCQ_LBN 0
+#define	FRF_AZ_TX_FLUSH_DESCQ_WIDTH 12
+
+/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */
+#define	FR_BZ_TX_DESC_UPD_P0 0x00000a10
+#define	FR_BZ_TX_DESC_UPD_P0_STEP 8192
+#define	FR_BZ_TX_DESC_UPD_P0_ROWS 1024
+/* TX_DESC_UPD_REG_KER: Transmit descriptor update register. */
+#define	FR_AA_TX_DESC_UPD_KER 0x00000a10
+#define	FR_AA_TX_DESC_UPD_KER_STEP 8192
+#define	FR_AA_TX_DESC_UPD_KER_ROWS 8
+/* TX_DESC_UPD_REGP123: Transmit descriptor update register. */
+#define	FR_BB_TX_DESC_UPD_P123 0x01000a10
+#define	FR_BB_TX_DESC_UPD_P123_STEP 8192
+#define	FR_BB_TX_DESC_UPD_P123_ROWS 3072
+#define	FRF_AZ_TX_DESC_WPTR_LBN 96
+#define	FRF_AZ_TX_DESC_WPTR_WIDTH 12
+#define	FRF_AZ_TX_DESC_PUSH_CMD_LBN 95
+#define	FRF_AZ_TX_DESC_PUSH_CMD_WIDTH 1
+#define	FRF_AZ_TX_DESC_LBN 0
+#define	FRF_AZ_TX_DESC_WIDTH 95
+
+/* TX_DC_CFG_REG: Transmit descriptor cache configuration register */
+#define	FR_AZ_TX_DC_CFG 0x00000a20
+#define	FRF_AZ_TX_DC_SIZE_LBN 0
+#define	FRF_AZ_TX_DC_SIZE_WIDTH 2
+#define	FFE_AZ_TX_DC_SIZE_32 2
+#define	FFE_AZ_TX_DC_SIZE_16 1
+#define	FFE_AZ_TX_DC_SIZE_8 0
+
+/* TX_CHKSM_CFG_REG: Transmit checksum configuration register */
+#define	FR_AA_TX_CHKSM_CFG 0x00000a30
+#define	FRF_AA_TX_Q_CHKSM_DIS_96_127_LBN 96
+#define	FRF_AA_TX_Q_CHKSM_DIS_96_127_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_64_95_LBN 64
+#define	FRF_AA_TX_Q_CHKSM_DIS_64_95_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_32_63_LBN 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_32_63_WIDTH 32
+#define	FRF_AA_TX_Q_CHKSM_DIS_0_31_LBN 0
+#define	FRF_AA_TX_Q_CHKSM_DIS_0_31_WIDTH 32
+
+/* TX_CFG_REG: Transmit configuration register */
+#define	FR_AZ_TX_CFG 0x00000a50
+#define	FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_LBN 114
+#define	FRF_CZ_TX_CONT_LOOKUP_THRESH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_FILTER_TEST_MODE_BIT_LBN 113
+#define	FRF_CZ_TX_FILTER_TEST_MODE_BIT_WIDTH 1
+#define	FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_LBN 105
+#define	FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_LBN 97
+#define	FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_LBN 89
+#define	FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_LBN 81
+#define	FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_LBN 73
+#define	FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_LBN 65
+#define	FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE_WIDTH 8
+#define	FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_LBN 64
+#define	FRF_CZ_TX_FILTER_ALL_VLAN_ETHERTYPES_BIT_WIDTH 1
+#define	FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_LBN 48
+#define	FRF_CZ_TX_VLAN_MATCH_ETHERTYPE_RANGE_WIDTH 16
+#define	FRF_CZ_TX_FILTER_EN_BIT_LBN 47
+#define	FRF_CZ_TX_FILTER_EN_BIT_WIDTH 1
+#define	FRF_AZ_TX_IP_ID_P0_OFS_LBN 16
+#define	FRF_AZ_TX_IP_ID_P0_OFS_WIDTH 15
+#define	FRF_AZ_TX_NO_EOP_DISC_EN_LBN 5
+#define	FRF_AZ_TX_NO_EOP_DISC_EN_WIDTH 1
+#define	FRF_AZ_TX_P1_PRI_EN_LBN 4
+#define	FRF_AZ_TX_P1_PRI_EN_WIDTH 1
+#define	FRF_AZ_TX_OWNERR_CTL_LBN 2
+#define	FRF_AZ_TX_OWNERR_CTL_WIDTH 1
+#define	FRF_AA_TX_NON_IP_DROP_DIS_LBN 1
+#define	FRF_AA_TX_NON_IP_DROP_DIS_WIDTH 1
+#define	FRF_AZ_TX_IP_ID_REP_EN_LBN 0
+#define	FRF_AZ_TX_IP_ID_REP_EN_WIDTH 1
+
+/* TX_PUSH_DROP_REG: Transmit push dropped register */
+#define	FR_AZ_TX_PUSH_DROP 0x00000a60
+#define	FRF_AZ_TX_PUSH_DROP_CNT_LBN 0
+#define	FRF_AZ_TX_PUSH_DROP_CNT_WIDTH 32
+
+/* TX_RESERVED_REG: Transmit configuration register */
+#define	FR_AZ_TX_RESERVED 0x00000a80
+#define	FRF_AZ_TX_EVT_CNT_LBN 121
+#define	FRF_AZ_TX_EVT_CNT_WIDTH 7
+#define	FRF_AZ_TX_PREF_AGE_CNT_LBN 119
+#define	FRF_AZ_TX_PREF_AGE_CNT_WIDTH 2
+#define	FRF_AZ_TX_RD_COMP_TMR_LBN 96
+#define	FRF_AZ_TX_RD_COMP_TMR_WIDTH 23
+#define	FRF_AZ_TX_PUSH_EN_LBN 89
+#define	FRF_AZ_TX_PUSH_EN_WIDTH 1
+#define	FRF_AZ_TX_PUSH_CHK_DIS_LBN 88
+#define	FRF_AZ_TX_PUSH_CHK_DIS_WIDTH 1
+#define	FRF_AZ_TX_D_FF_FULL_P0_LBN 85
+#define	FRF_AZ_TX_D_FF_FULL_P0_WIDTH 1
+#define	FRF_AZ_TX_DMAR_ST_P0_LBN 81
+#define	FRF_AZ_TX_DMAR_ST_P0_WIDTH 1
+#define	FRF_AZ_TX_DMAQ_ST_LBN 78
+#define	FRF_AZ_TX_DMAQ_ST_WIDTH 1
+#define	FRF_AZ_TX_RX_SPACER_LBN 64
+#define	FRF_AZ_TX_RX_SPACER_WIDTH 8
+#define	FRF_AZ_TX_DROP_ABORT_EN_LBN 60
+#define	FRF_AZ_TX_DROP_ABORT_EN_WIDTH 1
+#define	FRF_AZ_TX_SOFT_EVT_EN_LBN 59
+#define	FRF_AZ_TX_SOFT_EVT_EN_WIDTH 1
+#define	FRF_AZ_TX_PS_EVT_DIS_LBN 58
+#define	FRF_AZ_TX_PS_EVT_DIS_WIDTH 1
+#define	FRF_AZ_TX_RX_SPACER_EN_LBN 57
+#define	FRF_AZ_TX_RX_SPACER_EN_WIDTH 1
+#define	FRF_AZ_TX_XP_TIMER_LBN 52
+#define	FRF_AZ_TX_XP_TIMER_WIDTH 5
+#define	FRF_AZ_TX_PREF_SPACER_LBN 44
+#define	FRF_AZ_TX_PREF_SPACER_WIDTH 8
+#define	FRF_AZ_TX_PREF_WD_TMR_LBN 22
+#define	FRF_AZ_TX_PREF_WD_TMR_WIDTH 22
+#define	FRF_AZ_TX_ONLY1TAG_LBN 21
+#define	FRF_AZ_TX_ONLY1TAG_WIDTH 1
+#define	FRF_AZ_TX_PREF_THRESHOLD_LBN 19
+#define	FRF_AZ_TX_PREF_THRESHOLD_WIDTH 2
+#define	FRF_AZ_TX_ONE_PKT_PER_Q_LBN 18
+#define	FRF_AZ_TX_ONE_PKT_PER_Q_WIDTH 1
+#define	FRF_AZ_TX_DIS_NON_IP_EV_LBN 17
+#define	FRF_AZ_TX_DIS_NON_IP_EV_WIDTH 1
+#define	FRF_AA_TX_DMA_FF_THR_LBN 16
+#define	FRF_AA_TX_DMA_FF_THR_WIDTH 1
+#define	FRF_AZ_TX_DMA_SPACER_LBN 8
+#define	FRF_AZ_TX_DMA_SPACER_WIDTH 8
+#define	FRF_AA_TX_TCP_DIS_LBN 7
+#define	FRF_AA_TX_TCP_DIS_WIDTH 1
+#define	FRF_BZ_TX_FLUSH_MIN_LEN_EN_LBN 7
+#define	FRF_BZ_TX_FLUSH_MIN_LEN_EN_WIDTH 1
+#define	FRF_AA_TX_IP_DIS_LBN 6
+#define	FRF_AA_TX_IP_DIS_WIDTH 1
+#define	FRF_AZ_TX_MAX_CPL_LBN 2
+#define	FRF_AZ_TX_MAX_CPL_WIDTH 2
+#define	FFE_AZ_TX_MAX_CPL_16 3
+#define	FFE_AZ_TX_MAX_CPL_8 2
+#define	FFE_AZ_TX_MAX_CPL_4 1
+#define	FFE_AZ_TX_MAX_CPL_NOLIMIT 0
+#define	FRF_AZ_TX_MAX_PREF_LBN 0
+#define	FRF_AZ_TX_MAX_PREF_WIDTH 2
+#define	FFE_AZ_TX_MAX_PREF_32 3
+#define	FFE_AZ_TX_MAX_PREF_16 2
+#define	FFE_AZ_TX_MAX_PREF_8 1
+#define	FFE_AZ_TX_MAX_PREF_OFF 0
+
+/* TX_PACE_REG: Transmit pace control register */
+#define	FR_BZ_TX_PACE 0x00000a90
+#define	FRF_BZ_TX_PACE_SB_NOT_AF_LBN 19
+#define	FRF_BZ_TX_PACE_SB_NOT_AF_WIDTH 10
+#define	FRF_BZ_TX_PACE_SB_AF_LBN 9
+#define	FRF_BZ_TX_PACE_SB_AF_WIDTH 10
+#define	FRF_BZ_TX_PACE_FB_BASE_LBN 5
+#define	FRF_BZ_TX_PACE_FB_BASE_WIDTH 4
+#define	FRF_BZ_TX_PACE_BIN_TH_LBN 0
+#define	FRF_BZ_TX_PACE_BIN_TH_WIDTH 5
+
+/* TX_PACE_DROP_QID_REG: PACE Drop QID Counter */
+#define	FR_BZ_TX_PACE_DROP_QID 0x00000aa0
+#define	FRF_BZ_TX_PACE_QID_DRP_CNT_LBN 0
+#define	FRF_BZ_TX_PACE_QID_DRP_CNT_WIDTH 16
+
+/* TX_VLAN_REG: Transmit VLAN tag register */
+#define	FR_BB_TX_VLAN 0x00000ae0
+#define	FRF_BB_TX_VLAN_EN_LBN 127
+#define	FRF_BB_TX_VLAN_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN7_PORT1_EN_LBN 125
+#define	FRF_BB_TX_VLAN7_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN7_PORT0_EN_LBN 124
+#define	FRF_BB_TX_VLAN7_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN7_LBN 112
+#define	FRF_BB_TX_VLAN7_WIDTH 12
+#define	FRF_BB_TX_VLAN6_PORT1_EN_LBN 109
+#define	FRF_BB_TX_VLAN6_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN6_PORT0_EN_LBN 108
+#define	FRF_BB_TX_VLAN6_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN6_LBN 96
+#define	FRF_BB_TX_VLAN6_WIDTH 12
+#define	FRF_BB_TX_VLAN5_PORT1_EN_LBN 93
+#define	FRF_BB_TX_VLAN5_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN5_PORT0_EN_LBN 92
+#define	FRF_BB_TX_VLAN5_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN5_LBN 80
+#define	FRF_BB_TX_VLAN5_WIDTH 12
+#define	FRF_BB_TX_VLAN4_PORT1_EN_LBN 77
+#define	FRF_BB_TX_VLAN4_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN4_PORT0_EN_LBN 76
+#define	FRF_BB_TX_VLAN4_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN4_LBN 64
+#define	FRF_BB_TX_VLAN4_WIDTH 12
+#define	FRF_BB_TX_VLAN3_PORT1_EN_LBN 61
+#define	FRF_BB_TX_VLAN3_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN3_PORT0_EN_LBN 60
+#define	FRF_BB_TX_VLAN3_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN3_LBN 48
+#define	FRF_BB_TX_VLAN3_WIDTH 12
+#define	FRF_BB_TX_VLAN2_PORT1_EN_LBN 45
+#define	FRF_BB_TX_VLAN2_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN2_PORT0_EN_LBN 44
+#define	FRF_BB_TX_VLAN2_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN2_LBN 32
+#define	FRF_BB_TX_VLAN2_WIDTH 12
+#define	FRF_BB_TX_VLAN1_PORT1_EN_LBN 29
+#define	FRF_BB_TX_VLAN1_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN1_PORT0_EN_LBN 28
+#define	FRF_BB_TX_VLAN1_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN1_LBN 16
+#define	FRF_BB_TX_VLAN1_WIDTH 12
+#define	FRF_BB_TX_VLAN0_PORT1_EN_LBN 13
+#define	FRF_BB_TX_VLAN0_PORT1_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN0_PORT0_EN_LBN 12
+#define	FRF_BB_TX_VLAN0_PORT0_EN_WIDTH 1
+#define	FRF_BB_TX_VLAN0_LBN 0
+#define	FRF_BB_TX_VLAN0_WIDTH 12
+
+/* TX_IPFIL_PORTEN_REG: Transmit filter control register */
+#define	FR_BZ_TX_IPFIL_PORTEN 0x00000af0
+#define	FRF_BZ_TX_MADR0_FIL_EN_LBN 64
+#define	FRF_BZ_TX_MADR0_FIL_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL31_PORT_EN_LBN 62
+#define	FRF_BB_TX_IPFIL31_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL30_PORT_EN_LBN 60
+#define	FRF_BB_TX_IPFIL30_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL29_PORT_EN_LBN 58
+#define	FRF_BB_TX_IPFIL29_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL28_PORT_EN_LBN 56
+#define	FRF_BB_TX_IPFIL28_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL27_PORT_EN_LBN 54
+#define	FRF_BB_TX_IPFIL27_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL26_PORT_EN_LBN 52
+#define	FRF_BB_TX_IPFIL26_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL25_PORT_EN_LBN 50
+#define	FRF_BB_TX_IPFIL25_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL24_PORT_EN_LBN 48
+#define	FRF_BB_TX_IPFIL24_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL23_PORT_EN_LBN 46
+#define	FRF_BB_TX_IPFIL23_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL22_PORT_EN_LBN 44
+#define	FRF_BB_TX_IPFIL22_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL21_PORT_EN_LBN 42
+#define	FRF_BB_TX_IPFIL21_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL20_PORT_EN_LBN 40
+#define	FRF_BB_TX_IPFIL20_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL19_PORT_EN_LBN 38
+#define	FRF_BB_TX_IPFIL19_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL18_PORT_EN_LBN 36
+#define	FRF_BB_TX_IPFIL18_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL17_PORT_EN_LBN 34
+#define	FRF_BB_TX_IPFIL17_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL16_PORT_EN_LBN 32
+#define	FRF_BB_TX_IPFIL16_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL15_PORT_EN_LBN 30
+#define	FRF_BB_TX_IPFIL15_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL14_PORT_EN_LBN 28
+#define	FRF_BB_TX_IPFIL14_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL13_PORT_EN_LBN 26
+#define	FRF_BB_TX_IPFIL13_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL12_PORT_EN_LBN 24
+#define	FRF_BB_TX_IPFIL12_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL11_PORT_EN_LBN 22
+#define	FRF_BB_TX_IPFIL11_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL10_PORT_EN_LBN 20
+#define	FRF_BB_TX_IPFIL10_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL9_PORT_EN_LBN 18
+#define	FRF_BB_TX_IPFIL9_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL8_PORT_EN_LBN 16
+#define	FRF_BB_TX_IPFIL8_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL7_PORT_EN_LBN 14
+#define	FRF_BB_TX_IPFIL7_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL6_PORT_EN_LBN 12
+#define	FRF_BB_TX_IPFIL6_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL5_PORT_EN_LBN 10
+#define	FRF_BB_TX_IPFIL5_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL4_PORT_EN_LBN 8
+#define	FRF_BB_TX_IPFIL4_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL3_PORT_EN_LBN 6
+#define	FRF_BB_TX_IPFIL3_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL2_PORT_EN_LBN 4
+#define	FRF_BB_TX_IPFIL2_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL1_PORT_EN_LBN 2
+#define	FRF_BB_TX_IPFIL1_PORT_EN_WIDTH 1
+#define	FRF_BB_TX_IPFIL0_PORT_EN_LBN 0
+#define	FRF_BB_TX_IPFIL0_PORT_EN_WIDTH 1
+
+/* TX_IPFIL_TBL: Transmit IP source address filter table */
+#define	FR_BB_TX_IPFIL_TBL 0x00000b00
+#define	FR_BB_TX_IPFIL_TBL_STEP 16
+#define	FR_BB_TX_IPFIL_TBL_ROWS 16
+#define	FRF_BB_TX_IPFIL_MASK_1_LBN 96
+#define	FRF_BB_TX_IPFIL_MASK_1_WIDTH 32
+#define	FRF_BB_TX_IP_SRC_ADR_1_LBN 64
+#define	FRF_BB_TX_IP_SRC_ADR_1_WIDTH 32
+#define	FRF_BB_TX_IPFIL_MASK_0_LBN 32
+#define	FRF_BB_TX_IPFIL_MASK_0_WIDTH 32
+#define	FRF_BB_TX_IP_SRC_ADR_0_LBN 0
+#define	FRF_BB_TX_IP_SRC_ADR_0_WIDTH 32
+
+/* MD_TXD_REG: PHY management transmit data register */
+#define	FR_AB_MD_TXD 0x00000c00
+#define	FRF_AB_MD_TXD_LBN 0
+#define	FRF_AB_MD_TXD_WIDTH 16
+
+/* MD_RXD_REG: PHY management receive data register */
+#define	FR_AB_MD_RXD 0x00000c10
+#define	FRF_AB_MD_RXD_LBN 0
+#define	FRF_AB_MD_RXD_WIDTH 16
+
+/* MD_CS_REG: PHY management configuration & status register */
+#define	FR_AB_MD_CS 0x00000c20
+#define	FRF_AB_MD_RD_EN_CMD_LBN 15
+#define	FRF_AB_MD_RD_EN_CMD_WIDTH 1
+#define	FRF_AB_MD_WR_EN_CMD_LBN 14
+#define	FRF_AB_MD_WR_EN_CMD_WIDTH 1
+#define	FRF_AB_MD_ADDR_CMD_LBN 13
+#define	FRF_AB_MD_ADDR_CMD_WIDTH 1
+#define	FRF_AB_MD_PT_LBN 7
+#define	FRF_AB_MD_PT_WIDTH 3
+#define	FRF_AB_MD_PL_LBN 6
+#define	FRF_AB_MD_PL_WIDTH 1
+#define	FRF_AB_MD_INT_CLR_LBN 5
+#define	FRF_AB_MD_INT_CLR_WIDTH 1
+#define	FRF_AB_MD_GC_LBN 4
+#define	FRF_AB_MD_GC_WIDTH 1
+#define	FRF_AB_MD_PRSP_LBN 3
+#define	FRF_AB_MD_PRSP_WIDTH 1
+#define	FRF_AB_MD_RIC_LBN 2
+#define	FRF_AB_MD_RIC_WIDTH 1
+#define	FRF_AB_MD_RDC_LBN 1
+#define	FRF_AB_MD_RDC_WIDTH 1
+#define	FRF_AB_MD_WRC_LBN 0
+#define	FRF_AB_MD_WRC_WIDTH 1
+
+/* MD_PHY_ADR_REG: PHY management PHY address register */
+#define	FR_AB_MD_PHY_ADR 0x00000c30
+#define	FRF_AB_MD_PHY_ADR_LBN 0
+#define	FRF_AB_MD_PHY_ADR_WIDTH 16
+
+/* MD_ID_REG: PHY management ID register */
+#define	FR_AB_MD_ID 0x00000c40
+#define	FRF_AB_MD_PRT_ADR_LBN 11
+#define	FRF_AB_MD_PRT_ADR_WIDTH 5
+#define	FRF_AB_MD_DEV_ADR_LBN 6
+#define	FRF_AB_MD_DEV_ADR_WIDTH 5
+
+/* MD_STAT_REG: PHY management status & mask register */
+#define	FR_AB_MD_STAT 0x00000c50
+#define	FRF_AB_MD_PINT_LBN 4
+#define	FRF_AB_MD_PINT_WIDTH 1
+#define	FRF_AB_MD_DONE_LBN 3
+#define	FRF_AB_MD_DONE_WIDTH 1
+#define	FRF_AB_MD_BSERR_LBN 2
+#define	FRF_AB_MD_BSERR_WIDTH 1
+#define	FRF_AB_MD_LNFL_LBN 1
+#define	FRF_AB_MD_LNFL_WIDTH 1
+#define	FRF_AB_MD_BSY_LBN 0
+#define	FRF_AB_MD_BSY_WIDTH 1
+
+/* MAC_STAT_DMA_REG: Port MAC statistical counter DMA register */
+#define	FR_AB_MAC_STAT_DMA 0x00000c60
+#define	FRF_AB_MAC_STAT_DMA_CMD_LBN 48
+#define	FRF_AB_MAC_STAT_DMA_CMD_WIDTH 1
+#define	FRF_AB_MAC_STAT_DMA_ADR_LBN 0
+#define	FRF_AB_MAC_STAT_DMA_ADR_WIDTH 48
+
+/* MAC_CTRL_REG: Port MAC control register */
+#define	FR_AB_MAC_CTRL 0x00000c80
+#define	FRF_AB_MAC_XOFF_VAL_LBN 16
+#define	FRF_AB_MAC_XOFF_VAL_WIDTH 16
+#define	FRF_BB_TXFIFO_DRAIN_EN_LBN 7
+#define	FRF_BB_TXFIFO_DRAIN_EN_WIDTH 1
+#define	FRF_AB_MAC_XG_DISTXCRC_LBN 5
+#define	FRF_AB_MAC_XG_DISTXCRC_WIDTH 1
+#define	FRF_AB_MAC_BCAD_ACPT_LBN 4
+#define	FRF_AB_MAC_BCAD_ACPT_WIDTH 1
+#define	FRF_AB_MAC_UC_PROM_LBN 3
+#define	FRF_AB_MAC_UC_PROM_WIDTH 1
+#define	FRF_AB_MAC_LINK_STATUS_LBN 2
+#define	FRF_AB_MAC_LINK_STATUS_WIDTH 1
+#define	FRF_AB_MAC_SPEED_LBN 0
+#define	FRF_AB_MAC_SPEED_WIDTH 2
+#define	FFE_AB_MAC_SPEED_10G 3
+#define	FFE_AB_MAC_SPEED_1G 2
+#define	FFE_AB_MAC_SPEED_100M 1
+#define	FFE_AB_MAC_SPEED_10M 0
+
+/* GEN_MODE_REG: General Purpose mode register (external interrupt mask) */
+#define	FR_BB_GEN_MODE 0x00000c90
+#define	FRF_BB_XFP_PHY_INT_POL_SEL_LBN 3
+#define	FRF_BB_XFP_PHY_INT_POL_SEL_WIDTH 1
+#define	FRF_BB_XG_PHY_INT_POL_SEL_LBN 2
+#define	FRF_BB_XG_PHY_INT_POL_SEL_WIDTH 1
+#define	FRF_BB_XFP_PHY_INT_MASK_LBN 1
+#define	FRF_BB_XFP_PHY_INT_MASK_WIDTH 1
+#define	FRF_BB_XG_PHY_INT_MASK_LBN 0
+#define	FRF_BB_XG_PHY_INT_MASK_WIDTH 1
+
+/* MAC_MC_HASH_REG0: Multicast address hash table */
+#define	FR_AB_MAC_MC_HASH_REG0 0x00000ca0
+#define	FRF_AB_MAC_MCAST_HASH0_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH0_WIDTH 128
+
+/* MAC_MC_HASH_REG1: Multicast address hash table */
+#define	FR_AB_MAC_MC_HASH_REG1 0x00000cb0
+#define	FRF_AB_MAC_MCAST_HASH1_LBN 0
+#define	FRF_AB_MAC_MCAST_HASH1_WIDTH 128
+
+/* GM_CFG1_REG: GMAC configuration register 1 */
+#define	FR_AB_GM_CFG1 0x00000e00
+#define	FRF_AB_GM_SW_RST_LBN 31
+#define	FRF_AB_GM_SW_RST_WIDTH 1
+#define	FRF_AB_GM_SIM_RST_LBN 30
+#define	FRF_AB_GM_SIM_RST_WIDTH 1
+#define	FRF_AB_GM_RST_RX_MAC_CTL_LBN 19
+#define	FRF_AB_GM_RST_RX_MAC_CTL_WIDTH 1
+#define	FRF_AB_GM_RST_TX_MAC_CTL_LBN 18
+#define	FRF_AB_GM_RST_TX_MAC_CTL_WIDTH 1
+#define	FRF_AB_GM_RST_RX_FUNC_LBN 17
+#define	FRF_AB_GM_RST_RX_FUNC_WIDTH 1
+#define	FRF_AB_GM_RST_TX_FUNC_LBN 16
+#define	FRF_AB_GM_RST_TX_FUNC_WIDTH 1
+#define	FRF_AB_GM_LOOP_LBN 8
+#define	FRF_AB_GM_LOOP_WIDTH 1
+#define	FRF_AB_GM_RX_FC_EN_LBN 5
+#define	FRF_AB_GM_RX_FC_EN_WIDTH 1
+#define	FRF_AB_GM_TX_FC_EN_LBN 4
+#define	FRF_AB_GM_TX_FC_EN_WIDTH 1
+#define	FRF_AB_GM_SYNC_RXEN_LBN 3
+#define	FRF_AB_GM_SYNC_RXEN_WIDTH 1
+#define	FRF_AB_GM_RX_EN_LBN 2
+#define	FRF_AB_GM_RX_EN_WIDTH 1
+#define	FRF_AB_GM_SYNC_TXEN_LBN 1
+#define	FRF_AB_GM_SYNC_TXEN_WIDTH 1
+#define	FRF_AB_GM_TX_EN_LBN 0
+#define	FRF_AB_GM_TX_EN_WIDTH 1
+
+/* GM_CFG2_REG: GMAC configuration register 2 */
+#define	FR_AB_GM_CFG2 0x00000e10
+#define	FRF_AB_GM_PAMBL_LEN_LBN 12
+#define	FRF_AB_GM_PAMBL_LEN_WIDTH 4
+#define	FRF_AB_GM_IF_MODE_LBN 8
+#define	FRF_AB_GM_IF_MODE_WIDTH 2
+#define	FFE_AB_IF_MODE_BYTE_MODE 2
+#define	FFE_AB_IF_MODE_NIBBLE_MODE 1
+#define	FRF_AB_GM_HUGE_FRM_EN_LBN 5
+#define	FRF_AB_GM_HUGE_FRM_EN_WIDTH 1
+#define	FRF_AB_GM_LEN_CHK_LBN 4
+#define	FRF_AB_GM_LEN_CHK_WIDTH 1
+#define	FRF_AB_GM_PAD_CRC_EN_LBN 2
+#define	FRF_AB_GM_PAD_CRC_EN_WIDTH 1
+#define	FRF_AB_GM_CRC_EN_LBN 1
+#define	FRF_AB_GM_CRC_EN_WIDTH 1
+#define	FRF_AB_GM_FD_LBN 0
+#define	FRF_AB_GM_FD_WIDTH 1
+
+/* GM_IPG_REG: GMAC IPG register */
+#define	FR_AB_GM_IPG 0x00000e20
+#define	FRF_AB_GM_NONB2B_IPG1_LBN 24
+#define	FRF_AB_GM_NONB2B_IPG1_WIDTH 7
+#define	FRF_AB_GM_NONB2B_IPG2_LBN 16
+#define	FRF_AB_GM_NONB2B_IPG2_WIDTH 7
+#define	FRF_AB_GM_MIN_IPG_ENF_LBN 8
+#define	FRF_AB_GM_MIN_IPG_ENF_WIDTH 8
+#define	FRF_AB_GM_B2B_IPG_LBN 0
+#define	FRF_AB_GM_B2B_IPG_WIDTH 7
+
+/* GM_HD_REG: GMAC half duplex register */
+#define	FR_AB_GM_HD 0x00000e30
+#define	FRF_AB_GM_ALT_BOFF_VAL_LBN 20
+#define	FRF_AB_GM_ALT_BOFF_VAL_WIDTH 4
+#define	FRF_AB_GM_ALT_BOFF_EN_LBN 19
+#define	FRF_AB_GM_ALT_BOFF_EN_WIDTH 1
+#define	FRF_AB_GM_BP_NO_BOFF_LBN 18
+#define	FRF_AB_GM_BP_NO_BOFF_WIDTH 1
+#define	FRF_AB_GM_DIS_BOFF_LBN 17
+#define	FRF_AB_GM_DIS_BOFF_WIDTH 1
+#define	FRF_AB_GM_EXDEF_TX_EN_LBN 16
+#define	FRF_AB_GM_EXDEF_TX_EN_WIDTH 1
+#define	FRF_AB_GM_RTRY_LIMIT_LBN 12
+#define	FRF_AB_GM_RTRY_LIMIT_WIDTH 4
+#define	FRF_AB_GM_COL_WIN_LBN 0
+#define	FRF_AB_GM_COL_WIN_WIDTH 10
+
+/* GM_MAX_FLEN_REG: GMAC maximum frame length register */
+#define	FR_AB_GM_MAX_FLEN 0x00000e40
+#define	FRF_AB_GM_MAX_FLEN_LBN 0
+#define	FRF_AB_GM_MAX_FLEN_WIDTH 16
+
+/* GM_TEST_REG: GMAC test register */
+#define	FR_AB_GM_TEST 0x00000e70
+#define	FRF_AB_GM_MAX_BOFF_LBN 3
+#define	FRF_AB_GM_MAX_BOFF_WIDTH 1
+#define	FRF_AB_GM_REG_TX_FLOW_EN_LBN 2
+#define	FRF_AB_GM_REG_TX_FLOW_EN_WIDTH 1
+#define	FRF_AB_GM_TEST_PAUSE_LBN 1
+#define	FRF_AB_GM_TEST_PAUSE_WIDTH 1
+#define	FRF_AB_GM_SHORT_SLOT_LBN 0
+#define	FRF_AB_GM_SHORT_SLOT_WIDTH 1
+
+/* GM_ADR1_REG: GMAC station address register 1 */
+#define	FR_AB_GM_ADR1 0x00000f00
+#define	FRF_AB_GM_ADR_B0_LBN 24
+#define	FRF_AB_GM_ADR_B0_WIDTH 8
+#define	FRF_AB_GM_ADR_B1_LBN 16
+#define	FRF_AB_GM_ADR_B1_WIDTH 8
+#define	FRF_AB_GM_ADR_B2_LBN 8
+#define	FRF_AB_GM_ADR_B2_WIDTH 8
+#define	FRF_AB_GM_ADR_B3_LBN 0
+#define	FRF_AB_GM_ADR_B3_WIDTH 8
+
+/* GM_ADR2_REG: GMAC station address register 2 */
+#define	FR_AB_GM_ADR2 0x00000f10
+#define	FRF_AB_GM_ADR_B4_LBN 24
+#define	FRF_AB_GM_ADR_B4_WIDTH 8
+#define	FRF_AB_GM_ADR_B5_LBN 16
+#define	FRF_AB_GM_ADR_B5_WIDTH 8
+
+/* GMF_CFG0_REG: GMAC FIFO configuration register 0 */
+#define	FR_AB_GMF_CFG0 0x00000f20
+#define	FRF_AB_GMF_FTFENRPLY_LBN 20
+#define	FRF_AB_GMF_FTFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_STFENRPLY_LBN 19
+#define	FRF_AB_GMF_STFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_FRFENRPLY_LBN 18
+#define	FRF_AB_GMF_FRFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_SRFENRPLY_LBN 17
+#define	FRF_AB_GMF_SRFENRPLY_WIDTH 1
+#define	FRF_AB_GMF_WTMENRPLY_LBN 16
+#define	FRF_AB_GMF_WTMENRPLY_WIDTH 1
+#define	FRF_AB_GMF_FTFENREQ_LBN 12
+#define	FRF_AB_GMF_FTFENREQ_WIDTH 1
+#define	FRF_AB_GMF_STFENREQ_LBN 11
+#define	FRF_AB_GMF_STFENREQ_WIDTH 1
+#define	FRF_AB_GMF_FRFENREQ_LBN 10
+#define	FRF_AB_GMF_FRFENREQ_WIDTH 1
+#define	FRF_AB_GMF_SRFENREQ_LBN 9
+#define	FRF_AB_GMF_SRFENREQ_WIDTH 1
+#define	FRF_AB_GMF_WTMENREQ_LBN 8
+#define	FRF_AB_GMF_WTMENREQ_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTFT_LBN 4
+#define	FRF_AB_GMF_HSTRSTFT_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTST_LBN 3
+#define	FRF_AB_GMF_HSTRSTST_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTFR_LBN 2
+#define	FRF_AB_GMF_HSTRSTFR_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTSR_LBN 1
+#define	FRF_AB_GMF_HSTRSTSR_WIDTH 1
+#define	FRF_AB_GMF_HSTRSTWT_LBN 0
+#define	FRF_AB_GMF_HSTRSTWT_WIDTH 1
+
+/* GMF_CFG1_REG: GMAC FIFO configuration register 1 */
+#define	FR_AB_GMF_CFG1 0x00000f30
+#define	FRF_AB_GMF_CFGFRTH_LBN 16
+#define	FRF_AB_GMF_CFGFRTH_WIDTH 5
+#define	FRF_AB_GMF_CFGXOFFRTX_LBN 0
+#define	FRF_AB_GMF_CFGXOFFRTX_WIDTH 16
+
+/* GMF_CFG2_REG: GMAC FIFO configuration register 2 */
+#define	FR_AB_GMF_CFG2 0x00000f40
+#define	FRF_AB_GMF_CFGHWM_LBN 16
+#define	FRF_AB_GMF_CFGHWM_WIDTH 6
+#define	FRF_AB_GMF_CFGLWM_LBN 0
+#define	FRF_AB_GMF_CFGLWM_WIDTH 6
+
+/* GMF_CFG3_REG: GMAC FIFO configuration register 3 */
+#define	FR_AB_GMF_CFG3 0x00000f50
+#define	FRF_AB_GMF_CFGHWMFT_LBN 16
+#define	FRF_AB_GMF_CFGHWMFT_WIDTH 6
+#define	FRF_AB_GMF_CFGFTTH_LBN 0
+#define	FRF_AB_GMF_CFGFTTH_WIDTH 6
+
+/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */
+#define	FR_AB_GMF_CFG4 0x00000f60
+#define	FRF_AB_GMF_HSTFLTRFRM_LBN 0
+#define	FRF_AB_GMF_HSTFLTRFRM_WIDTH 18
+
+/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */
+#define	FR_AB_GMF_CFG5 0x00000f70
+#define	FRF_AB_GMF_CFGHDPLX_LBN 22
+#define	FRF_AB_GMF_CFGHDPLX_WIDTH 1
+#define	FRF_AB_GMF_SRFULL_LBN 21
+#define	FRF_AB_GMF_SRFULL_WIDTH 1
+#define	FRF_AB_GMF_HSTSRFULLCLR_LBN 20
+#define	FRF_AB_GMF_HSTSRFULLCLR_WIDTH 1
+#define	FRF_AB_GMF_CFGBYTMODE_LBN 19
+#define	FRF_AB_GMF_CFGBYTMODE_WIDTH 1
+#define	FRF_AB_GMF_HSTDRPLT64_LBN 18
+#define	FRF_AB_GMF_HSTDRPLT64_WIDTH 1
+#define	FRF_AB_GMF_HSTFLTRFRMDC_LBN 0
+#define	FRF_AB_GMF_HSTFLTRFRMDC_WIDTH 18
+
+/* TX_SRC_MAC_TBL: Transmit IP source address filter table */
+#define	FR_BB_TX_SRC_MAC_TBL 0x00001000
+#define	FR_BB_TX_SRC_MAC_TBL_STEP 16
+#define	FR_BB_TX_SRC_MAC_TBL_ROWS 16
+#define	FRF_BB_TX_SRC_MAC_ADR_1_LBN 64
+#define	FRF_BB_TX_SRC_MAC_ADR_1_WIDTH 48
+#define	FRF_BB_TX_SRC_MAC_ADR_0_LBN 0
+#define	FRF_BB_TX_SRC_MAC_ADR_0_WIDTH 48
+
+/* TX_SRC_MAC_CTL_REG: Transmit MAC source address filter control */
+#define	FR_BB_TX_SRC_MAC_CTL 0x00001100
+#define	FRF_BB_TX_SRC_DROP_CTR_LBN 16
+#define	FRF_BB_TX_SRC_DROP_CTR_WIDTH 16
+#define	FRF_BB_TX_SRC_FLTR_EN_LBN 15
+#define	FRF_BB_TX_SRC_FLTR_EN_WIDTH 1
+#define	FRF_BB_TX_DROP_CTR_CLR_LBN 12
+#define	FRF_BB_TX_DROP_CTR_CLR_WIDTH 1
+#define	FRF_BB_TX_MAC_QID_SEL_LBN 0
+#define	FRF_BB_TX_MAC_QID_SEL_WIDTH 3
+
+/* XM_ADR_LO_REG: XGMAC address register low */
+#define	FR_AB_XM_ADR_LO 0x00001200
+#define	FRF_AB_XM_ADR_LO_LBN 0
+#define	FRF_AB_XM_ADR_LO_WIDTH 32
+
+/* XM_ADR_HI_REG: XGMAC address register high */
+#define	FR_AB_XM_ADR_HI 0x00001210
+#define	FRF_AB_XM_ADR_HI_LBN 0
+#define	FRF_AB_XM_ADR_HI_WIDTH 16
+
+/* XM_GLB_CFG_REG: XGMAC global configuration */
+#define	FR_AB_XM_GLB_CFG 0x00001220
+#define	FRF_AB_XM_RMTFLT_GEN_LBN 17
+#define	FRF_AB_XM_RMTFLT_GEN_WIDTH 1
+#define	FRF_AB_XM_DEBUG_MODE_LBN 16
+#define	FRF_AB_XM_DEBUG_MODE_WIDTH 1
+#define	FRF_AB_XM_RX_STAT_EN_LBN 11
+#define	FRF_AB_XM_RX_STAT_EN_WIDTH 1
+#define	FRF_AB_XM_TX_STAT_EN_LBN 10
+#define	FRF_AB_XM_TX_STAT_EN_WIDTH 1
+#define	FRF_AB_XM_RX_JUMBO_MODE_LBN 6
+#define	FRF_AB_XM_RX_JUMBO_MODE_WIDTH 1
+#define	FRF_AB_XM_WAN_MODE_LBN 5
+#define	FRF_AB_XM_WAN_MODE_WIDTH 1
+#define	FRF_AB_XM_INTCLR_MODE_LBN 3
+#define	FRF_AB_XM_INTCLR_MODE_WIDTH 1
+#define	FRF_AB_XM_CORE_RST_LBN 0
+#define	FRF_AB_XM_CORE_RST_WIDTH 1
+
+/* XM_TX_CFG_REG: XGMAC transmit configuration */
+#define	FR_AB_XM_TX_CFG 0x00001230
+#define	FRF_AB_XM_TX_PROG_LBN 24
+#define	FRF_AB_XM_TX_PROG_WIDTH 1
+#define	FRF_AB_XM_IPG_LBN 16
+#define	FRF_AB_XM_IPG_WIDTH 4
+#define	FRF_AB_XM_FCNTL_LBN 10
+#define	FRF_AB_XM_FCNTL_WIDTH 1
+#define	FRF_AB_XM_TXCRC_LBN 8
+#define	FRF_AB_XM_TXCRC_WIDTH 1
+#define	FRF_AB_XM_EDRC_LBN 6
+#define	FRF_AB_XM_EDRC_WIDTH 1
+#define	FRF_AB_XM_AUTO_PAD_LBN 5
+#define	FRF_AB_XM_AUTO_PAD_WIDTH 1
+#define	FRF_AB_XM_TX_PRMBL_LBN 2
+#define	FRF_AB_XM_TX_PRMBL_WIDTH 1
+#define	FRF_AB_XM_TXEN_LBN 1
+#define	FRF_AB_XM_TXEN_WIDTH 1
+#define	FRF_AB_XM_TX_RST_LBN 0
+#define	FRF_AB_XM_TX_RST_WIDTH 1
+
+/* XM_RX_CFG_REG: XGMAC receive configuration */
+#define	FR_AB_XM_RX_CFG 0x00001240
+#define	FRF_AB_XM_PASS_LENERR_LBN 26
+#define	FRF_AB_XM_PASS_LENERR_WIDTH 1
+#define	FRF_AB_XM_PASS_CRC_ERR_LBN 25
+#define	FRF_AB_XM_PASS_CRC_ERR_WIDTH 1
+#define	FRF_AB_XM_PASS_PRMBLE_ERR_LBN 24
+#define	FRF_AB_XM_PASS_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_REJ_BCAST_LBN 20
+#define	FRF_AB_XM_REJ_BCAST_WIDTH 1
+#define	FRF_AB_XM_ACPT_ALL_MCAST_LBN 11
+#define	FRF_AB_XM_ACPT_ALL_MCAST_WIDTH 1
+#define	FRF_AB_XM_ACPT_ALL_UCAST_LBN 9
+#define	FRF_AB_XM_ACPT_ALL_UCAST_WIDTH 1
+#define	FRF_AB_XM_AUTO_DEPAD_LBN 8
+#define	FRF_AB_XM_AUTO_DEPAD_WIDTH 1
+#define	FRF_AB_XM_RXCRC_LBN 3
+#define	FRF_AB_XM_RXCRC_WIDTH 1
+#define	FRF_AB_XM_RX_PRMBL_LBN 2
+#define	FRF_AB_XM_RX_PRMBL_WIDTH 1
+#define	FRF_AB_XM_RXEN_LBN 1
+#define	FRF_AB_XM_RXEN_WIDTH 1
+#define	FRF_AB_XM_RX_RST_LBN 0
+#define	FRF_AB_XM_RX_RST_WIDTH 1
+
+/* XM_MGT_INT_MASK: documentation to be written for sum_XM_MGT_INT_MASK */
+#define	FR_AB_XM_MGT_INT_MASK 0x00001250
+#define	FRF_AB_XM_MSK_STA_INTR_LBN 16
+#define	FRF_AB_XM_MSK_STA_INTR_WIDTH 1
+#define	FRF_AB_XM_MSK_STAT_CNTR_HF_LBN 9
+#define	FRF_AB_XM_MSK_STAT_CNTR_HF_WIDTH 1
+#define	FRF_AB_XM_MSK_STAT_CNTR_OF_LBN 8
+#define	FRF_AB_XM_MSK_STAT_CNTR_OF_WIDTH 1
+#define	FRF_AB_XM_MSK_PRMBLE_ERR_LBN 2
+#define	FRF_AB_XM_MSK_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_MSK_RMTFLT_LBN 1
+#define	FRF_AB_XM_MSK_RMTFLT_WIDTH 1
+#define	FRF_AB_XM_MSK_LCLFLT_LBN 0
+#define	FRF_AB_XM_MSK_LCLFLT_WIDTH 1
+
+/* XM_FC_REG: XGMAC flow control register */
+#define	FR_AB_XM_FC 0x00001270
+#define	FRF_AB_XM_PAUSE_TIME_LBN 16
+#define	FRF_AB_XM_PAUSE_TIME_WIDTH 16
+#define	FRF_AB_XM_RX_MAC_STAT_LBN 11
+#define	FRF_AB_XM_RX_MAC_STAT_WIDTH 1
+#define	FRF_AB_XM_TX_MAC_STAT_LBN 10
+#define	FRF_AB_XM_TX_MAC_STAT_WIDTH 1
+#define	FRF_AB_XM_MCNTL_PASS_LBN 8
+#define	FRF_AB_XM_MCNTL_PASS_WIDTH 2
+#define	FRF_AB_XM_REJ_CNTL_UCAST_LBN 6
+#define	FRF_AB_XM_REJ_CNTL_UCAST_WIDTH 1
+#define	FRF_AB_XM_REJ_CNTL_MCAST_LBN 5
+#define	FRF_AB_XM_REJ_CNTL_MCAST_WIDTH 1
+#define	FRF_AB_XM_ZPAUSE_LBN 2
+#define	FRF_AB_XM_ZPAUSE_WIDTH 1
+#define	FRF_AB_XM_XMIT_PAUSE_LBN 1
+#define	FRF_AB_XM_XMIT_PAUSE_WIDTH 1
+#define	FRF_AB_XM_DIS_FCNTL_LBN 0
+#define	FRF_AB_XM_DIS_FCNTL_WIDTH 1
+
+/* XM_PAUSE_TIME_REG: XGMAC pause time register */
+#define	FR_AB_XM_PAUSE_TIME 0x00001290
+#define	FRF_AB_XM_TX_PAUSE_CNT_LBN 16
+#define	FRF_AB_XM_TX_PAUSE_CNT_WIDTH 16
+#define	FRF_AB_XM_RX_PAUSE_CNT_LBN 0
+#define	FRF_AB_XM_RX_PAUSE_CNT_WIDTH 16
+
+/* XM_TX_PARAM_REG: XGMAC transmit parameter register */
+#define	FR_AB_XM_TX_PARAM 0x000012d0
+#define	FRF_AB_XM_TX_JUMBO_MODE_LBN 31
+#define	FRF_AB_XM_TX_JUMBO_MODE_WIDTH 1
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_HI_LBN 19
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH 11
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN 16
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH 3
+#define	FRF_AB_XM_PAD_CHAR_LBN 0
+#define	FRF_AB_XM_PAD_CHAR_WIDTH 8
+
+/* XM_RX_PARAM_REG: XGMAC receive parameter register */
+#define	FR_AB_XM_RX_PARAM 0x000012e0
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_HI_LBN 3
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH 11
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN 0
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH 3
+
+/* XM_MGT_INT_MSK_REG: XGMAC management interrupt mask register */
+#define	FR_AB_XM_MGT_INT_MSK 0x000012f0
+#define	FRF_AB_XM_STAT_CNTR_OF_LBN 9
+#define	FRF_AB_XM_STAT_CNTR_OF_WIDTH 1
+#define	FRF_AB_XM_STAT_CNTR_HF_LBN 8
+#define	FRF_AB_XM_STAT_CNTR_HF_WIDTH 1
+#define	FRF_AB_XM_PRMBLE_ERR_LBN 2
+#define	FRF_AB_XM_PRMBLE_ERR_WIDTH 1
+#define	FRF_AB_XM_RMTFLT_LBN 1
+#define	FRF_AB_XM_RMTFLT_WIDTH 1
+#define	FRF_AB_XM_LCLFLT_LBN 0
+#define	FRF_AB_XM_LCLFLT_WIDTH 1
+
+/* XX_PWR_RST_REG: XGXS/XAUI powerdown/reset register */
+#define	FR_AB_XX_PWR_RST 0x00001300
+#define	FRF_AB_XX_PWRDND_SIG_LBN 31
+#define	FRF_AB_XX_PWRDND_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNC_SIG_LBN 30
+#define	FRF_AB_XX_PWRDNC_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNB_SIG_LBN 29
+#define	FRF_AB_XX_PWRDNB_SIG_WIDTH 1
+#define	FRF_AB_XX_PWRDNA_SIG_LBN 28
+#define	FRF_AB_XX_PWRDNA_SIG_WIDTH 1
+#define	FRF_AB_XX_SIM_MODE_LBN 27
+#define	FRF_AB_XX_SIM_MODE_WIDTH 1
+#define	FRF_AB_XX_RSTPLLCD_SIG_LBN 25
+#define	FRF_AB_XX_RSTPLLCD_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTPLLAB_SIG_LBN 24
+#define	FRF_AB_XX_RSTPLLAB_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETD_SIG_LBN 23
+#define	FRF_AB_XX_RESETD_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETC_SIG_LBN 22
+#define	FRF_AB_XX_RESETC_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETB_SIG_LBN 21
+#define	FRF_AB_XX_RESETB_SIG_WIDTH 1
+#define	FRF_AB_XX_RESETA_SIG_LBN 20
+#define	FRF_AB_XX_RESETA_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSRX_SIG_LBN 18
+#define	FRF_AB_XX_RSTXGXSRX_SIG_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSTX_SIG_LBN 17
+#define	FRF_AB_XX_RSTXGXSTX_SIG_WIDTH 1
+#define	FRF_AB_XX_SD_RST_ACT_LBN 16
+#define	FRF_AB_XX_SD_RST_ACT_WIDTH 1
+#define	FRF_AB_XX_PWRDND_EN_LBN 15
+#define	FRF_AB_XX_PWRDND_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNC_EN_LBN 14
+#define	FRF_AB_XX_PWRDNC_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNB_EN_LBN 13
+#define	FRF_AB_XX_PWRDNB_EN_WIDTH 1
+#define	FRF_AB_XX_PWRDNA_EN_LBN 12
+#define	FRF_AB_XX_PWRDNA_EN_WIDTH 1
+#define	FRF_AB_XX_RSTPLLCD_EN_LBN 9
+#define	FRF_AB_XX_RSTPLLCD_EN_WIDTH 1
+#define	FRF_AB_XX_RSTPLLAB_EN_LBN 8
+#define	FRF_AB_XX_RSTPLLAB_EN_WIDTH 1
+#define	FRF_AB_XX_RESETD_EN_LBN 7
+#define	FRF_AB_XX_RESETD_EN_WIDTH 1
+#define	FRF_AB_XX_RESETC_EN_LBN 6
+#define	FRF_AB_XX_RESETC_EN_WIDTH 1
+#define	FRF_AB_XX_RESETB_EN_LBN 5
+#define	FRF_AB_XX_RESETB_EN_WIDTH 1
+#define	FRF_AB_XX_RESETA_EN_LBN 4
+#define	FRF_AB_XX_RESETA_EN_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSRX_EN_LBN 2
+#define	FRF_AB_XX_RSTXGXSRX_EN_WIDTH 1
+#define	FRF_AB_XX_RSTXGXSTX_EN_LBN 1
+#define	FRF_AB_XX_RSTXGXSTX_EN_WIDTH 1
+#define	FRF_AB_XX_RST_XX_EN_LBN 0
+#define	FRF_AB_XX_RST_XX_EN_WIDTH 1
+
+/* XX_SD_CTL_REG: XGXS/XAUI powerdown/reset control register */
+#define	FR_AB_XX_SD_CTL 0x00001310
+#define	FRF_AB_XX_TERMADJ1_LBN 17
+#define	FRF_AB_XX_TERMADJ1_WIDTH 1
+#define	FRF_AB_XX_TERMADJ0_LBN 16
+#define	FRF_AB_XX_TERMADJ0_WIDTH 1
+#define	FRF_AB_XX_HIDRVD_LBN 15
+#define	FRF_AB_XX_HIDRVD_WIDTH 1
+#define	FRF_AB_XX_LODRVD_LBN 14
+#define	FRF_AB_XX_LODRVD_WIDTH 1
+#define	FRF_AB_XX_HIDRVC_LBN 13
+#define	FRF_AB_XX_HIDRVC_WIDTH 1
+#define	FRF_AB_XX_LODRVC_LBN 12
+#define	FRF_AB_XX_LODRVC_WIDTH 1
+#define	FRF_AB_XX_HIDRVB_LBN 11
+#define	FRF_AB_XX_HIDRVB_WIDTH 1
+#define	FRF_AB_XX_LODRVB_LBN 10
+#define	FRF_AB_XX_LODRVB_WIDTH 1
+#define	FRF_AB_XX_HIDRVA_LBN 9
+#define	FRF_AB_XX_HIDRVA_WIDTH 1
+#define	FRF_AB_XX_LODRVA_LBN 8
+#define	FRF_AB_XX_LODRVA_WIDTH 1
+#define	FRF_AB_XX_LPBKD_LBN 3
+#define	FRF_AB_XX_LPBKD_WIDTH 1
+#define	FRF_AB_XX_LPBKC_LBN 2
+#define	FRF_AB_XX_LPBKC_WIDTH 1
+#define	FRF_AB_XX_LPBKB_LBN 1
+#define	FRF_AB_XX_LPBKB_WIDTH 1
+#define	FRF_AB_XX_LPBKA_LBN 0
+#define	FRF_AB_XX_LPBKA_WIDTH 1
+
+/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */
+#define	FR_AB_XX_TXDRV_CTL 0x00001320
+#define	FRF_AB_XX_DEQD_LBN 28
+#define	FRF_AB_XX_DEQD_WIDTH 4
+#define	FRF_AB_XX_DEQC_LBN 24
+#define	FRF_AB_XX_DEQC_WIDTH 4
+#define	FRF_AB_XX_DEQB_LBN 20
+#define	FRF_AB_XX_DEQB_WIDTH 4
+#define	FRF_AB_XX_DEQA_LBN 16
+#define	FRF_AB_XX_DEQA_WIDTH 4
+#define	FRF_AB_XX_DTXD_LBN 12
+#define	FRF_AB_XX_DTXD_WIDTH 4
+#define	FRF_AB_XX_DTXC_LBN 8
+#define	FRF_AB_XX_DTXC_WIDTH 4
+#define	FRF_AB_XX_DTXB_LBN 4
+#define	FRF_AB_XX_DTXB_WIDTH 4
+#define	FRF_AB_XX_DTXA_LBN 0
+#define	FRF_AB_XX_DTXA_WIDTH 4
+
+/* XX_PRBS_CTL_REG: documentation to be written for sum_XX_PRBS_CTL_REG */
+#define	FR_AB_XX_PRBS_CTL 0x00001330
+#define	FRF_AB_XX_CH3_RX_PRBS_SEL_LBN 30
+#define	FRF_AB_XX_CH3_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH3_RX_PRBS_INV_LBN 29
+#define	FRF_AB_XX_CH3_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH3_RX_PRBS_CHKEN_LBN 28
+#define	FRF_AB_XX_CH3_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH2_RX_PRBS_SEL_LBN 26
+#define	FRF_AB_XX_CH2_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH2_RX_PRBS_INV_LBN 25
+#define	FRF_AB_XX_CH2_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH2_RX_PRBS_CHKEN_LBN 24
+#define	FRF_AB_XX_CH2_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH1_RX_PRBS_SEL_LBN 22
+#define	FRF_AB_XX_CH1_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH1_RX_PRBS_INV_LBN 21
+#define	FRF_AB_XX_CH1_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH1_RX_PRBS_CHKEN_LBN 20
+#define	FRF_AB_XX_CH1_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH0_RX_PRBS_SEL_LBN 18
+#define	FRF_AB_XX_CH0_RX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH0_RX_PRBS_INV_LBN 17
+#define	FRF_AB_XX_CH0_RX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH0_RX_PRBS_CHKEN_LBN 16
+#define	FRF_AB_XX_CH0_RX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH3_TX_PRBS_SEL_LBN 14
+#define	FRF_AB_XX_CH3_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH3_TX_PRBS_INV_LBN 13
+#define	FRF_AB_XX_CH3_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH3_TX_PRBS_CHKEN_LBN 12
+#define	FRF_AB_XX_CH3_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH2_TX_PRBS_SEL_LBN 10
+#define	FRF_AB_XX_CH2_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH2_TX_PRBS_INV_LBN 9
+#define	FRF_AB_XX_CH2_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH2_TX_PRBS_CHKEN_LBN 8
+#define	FRF_AB_XX_CH2_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH1_TX_PRBS_SEL_LBN 6
+#define	FRF_AB_XX_CH1_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH1_TX_PRBS_INV_LBN 5
+#define	FRF_AB_XX_CH1_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH1_TX_PRBS_CHKEN_LBN 4
+#define	FRF_AB_XX_CH1_TX_PRBS_CHKEN_WIDTH 1
+#define	FRF_AB_XX_CH0_TX_PRBS_SEL_LBN 2
+#define	FRF_AB_XX_CH0_TX_PRBS_SEL_WIDTH 2
+#define	FRF_AB_XX_CH0_TX_PRBS_INV_LBN 1
+#define	FRF_AB_XX_CH0_TX_PRBS_INV_WIDTH 1
+#define	FRF_AB_XX_CH0_TX_PRBS_CHKEN_LBN 0
+#define	FRF_AB_XX_CH0_TX_PRBS_CHKEN_WIDTH 1
+
+/* XX_PRBS_CHK_REG: documentation to be written for sum_XX_PRBS_CHK_REG */
+#define	FR_AB_XX_PRBS_CHK 0x00001340
+#define	FRF_AB_XX_REV_LB_EN_LBN 16
+#define	FRF_AB_XX_REV_LB_EN_WIDTH 1
+#define	FRF_AB_XX_CH3_DEG_DET_LBN 15
+#define	FRF_AB_XX_CH3_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH3_LFSR_LOCK_IND_LBN 14
+#define	FRF_AB_XX_CH3_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH3_PRBS_FRUN_LBN 13
+#define	FRF_AB_XX_CH3_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH3_ERR_CHK_LBN 12
+#define	FRF_AB_XX_CH3_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH2_DEG_DET_LBN 11
+#define	FRF_AB_XX_CH2_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH2_LFSR_LOCK_IND_LBN 10
+#define	FRF_AB_XX_CH2_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH2_PRBS_FRUN_LBN 9
+#define	FRF_AB_XX_CH2_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH2_ERR_CHK_LBN 8
+#define	FRF_AB_XX_CH2_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH1_DEG_DET_LBN 7
+#define	FRF_AB_XX_CH1_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH1_LFSR_LOCK_IND_LBN 6
+#define	FRF_AB_XX_CH1_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH1_PRBS_FRUN_LBN 5
+#define	FRF_AB_XX_CH1_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH1_ERR_CHK_LBN 4
+#define	FRF_AB_XX_CH1_ERR_CHK_WIDTH 1
+#define	FRF_AB_XX_CH0_DEG_DET_LBN 3
+#define	FRF_AB_XX_CH0_DEG_DET_WIDTH 1
+#define	FRF_AB_XX_CH0_LFSR_LOCK_IND_LBN 2
+#define	FRF_AB_XX_CH0_LFSR_LOCK_IND_WIDTH 1
+#define	FRF_AB_XX_CH0_PRBS_FRUN_LBN 1
+#define	FRF_AB_XX_CH0_PRBS_FRUN_WIDTH 1
+#define	FRF_AB_XX_CH0_ERR_CHK_LBN 0
+#define	FRF_AB_XX_CH0_ERR_CHK_WIDTH 1
+
+/* XX_PRBS_ERR_REG: documentation to be written for sum_XX_PRBS_ERR_REG */
+#define	FR_AB_XX_PRBS_ERR 0x00001350
+#define	FRF_AB_XX_CH3_PRBS_ERR_CNT_LBN 24
+#define	FRF_AB_XX_CH3_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH2_PRBS_ERR_CNT_LBN 16
+#define	FRF_AB_XX_CH2_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH1_PRBS_ERR_CNT_LBN 8
+#define	FRF_AB_XX_CH1_PRBS_ERR_CNT_WIDTH 8
+#define	FRF_AB_XX_CH0_PRBS_ERR_CNT_LBN 0
+#define	FRF_AB_XX_CH0_PRBS_ERR_CNT_WIDTH 8
+
+/* XX_CORE_STAT_REG: XAUI XGXS core status register */
+#define	FR_AB_XX_CORE_STAT 0x00001360
+#define	FRF_AB_XX_FORCE_SIG3_LBN 31
+#define	FRF_AB_XX_FORCE_SIG3_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG3_VAL_LBN 30
+#define	FRF_AB_XX_FORCE_SIG3_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG2_LBN 29
+#define	FRF_AB_XX_FORCE_SIG2_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG2_VAL_LBN 28
+#define	FRF_AB_XX_FORCE_SIG2_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG1_LBN 27
+#define	FRF_AB_XX_FORCE_SIG1_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG1_VAL_LBN 26
+#define	FRF_AB_XX_FORCE_SIG1_VAL_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG0_LBN 25
+#define	FRF_AB_XX_FORCE_SIG0_WIDTH 1
+#define	FRF_AB_XX_FORCE_SIG0_VAL_LBN 24
+#define	FRF_AB_XX_FORCE_SIG0_VAL_WIDTH 1
+#define	FRF_AB_XX_XGXS_LB_EN_LBN 23
+#define	FRF_AB_XX_XGXS_LB_EN_WIDTH 1
+#define	FRF_AB_XX_XGMII_LB_EN_LBN 22
+#define	FRF_AB_XX_XGMII_LB_EN_WIDTH 1
+#define	FRF_AB_XX_MATCH_FAULT_LBN 21
+#define	FRF_AB_XX_MATCH_FAULT_WIDTH 1
+#define	FRF_AB_XX_ALIGN_DONE_LBN 20
+#define	FRF_AB_XX_ALIGN_DONE_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT3_LBN 19
+#define	FRF_AB_XX_SYNC_STAT3_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT2_LBN 18
+#define	FRF_AB_XX_SYNC_STAT2_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT1_LBN 17
+#define	FRF_AB_XX_SYNC_STAT1_WIDTH 1
+#define	FRF_AB_XX_SYNC_STAT0_LBN 16
+#define	FRF_AB_XX_SYNC_STAT0_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH3_LBN 15
+#define	FRF_AB_XX_COMMA_DET_CH3_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH2_LBN 14
+#define	FRF_AB_XX_COMMA_DET_CH2_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH1_LBN 13
+#define	FRF_AB_XX_COMMA_DET_CH1_WIDTH 1
+#define	FRF_AB_XX_COMMA_DET_CH0_LBN 12
+#define	FRF_AB_XX_COMMA_DET_CH0_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH3_LBN 11
+#define	FRF_AB_XX_CGRP_ALIGN_CH3_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH2_LBN 10
+#define	FRF_AB_XX_CGRP_ALIGN_CH2_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH1_LBN 9
+#define	FRF_AB_XX_CGRP_ALIGN_CH1_WIDTH 1
+#define	FRF_AB_XX_CGRP_ALIGN_CH0_LBN 8
+#define	FRF_AB_XX_CGRP_ALIGN_CH0_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH3_LBN 7
+#define	FRF_AB_XX_CHAR_ERR_CH3_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH2_LBN 6
+#define	FRF_AB_XX_CHAR_ERR_CH2_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH1_LBN 5
+#define	FRF_AB_XX_CHAR_ERR_CH1_WIDTH 1
+#define	FRF_AB_XX_CHAR_ERR_CH0_LBN 4
+#define	FRF_AB_XX_CHAR_ERR_CH0_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH3_LBN 3
+#define	FRF_AB_XX_DISPERR_CH3_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH2_LBN 2
+#define	FRF_AB_XX_DISPERR_CH2_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH1_LBN 1
+#define	FRF_AB_XX_DISPERR_CH1_WIDTH 1
+#define	FRF_AB_XX_DISPERR_CH0_LBN 0
+#define	FRF_AB_XX_DISPERR_CH0_WIDTH 1
+
+/* RX_DESC_PTR_TBL_KER: Receive descriptor pointer table */
+#define	FR_AA_RX_DESC_PTR_TBL_KER 0x00011800
+#define	FR_AA_RX_DESC_PTR_TBL_KER_STEP 16
+#define	FR_AA_RX_DESC_PTR_TBL_KER_ROWS 4
+/* RX_DESC_PTR_TBL: Receive descriptor pointer table */
+#define	FR_BZ_RX_DESC_PTR_TBL 0x00f40000
+#define	FR_BZ_RX_DESC_PTR_TBL_STEP 16
+#define	FR_BB_RX_DESC_PTR_TBL_ROWS 4096
+#define	FR_CZ_RX_DESC_PTR_TBL_ROWS 1024
+#define	FRF_CZ_RX_HDR_SPLIT_LBN 90
+#define	FRF_CZ_RX_HDR_SPLIT_WIDTH 1
+#define	FRF_AA_RX_RESET_LBN 89
+#define	FRF_AA_RX_RESET_WIDTH 1
+#define	FRF_AZ_RX_ISCSI_DDIG_EN_LBN 88
+#define	FRF_AZ_RX_ISCSI_DDIG_EN_WIDTH 1
+#define	FRF_AZ_RX_ISCSI_HDIG_EN_LBN 87
+#define	FRF_AZ_RX_ISCSI_HDIG_EN_WIDTH 1
+#define	FRF_AZ_RX_DESC_PREF_ACT_LBN 86
+#define	FRF_AZ_RX_DESC_PREF_ACT_WIDTH 1
+#define	FRF_AZ_RX_DC_HW_RPTR_LBN 80
+#define	FRF_AZ_RX_DC_HW_RPTR_WIDTH 6
+#define	FRF_AZ_RX_DESCQ_HW_RPTR_LBN 68
+#define	FRF_AZ_RX_DESCQ_HW_RPTR_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_SW_WPTR_LBN 56
+#define	FRF_AZ_RX_DESCQ_SW_WPTR_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_BUF_BASE_ID_LBN 36
+#define	FRF_AZ_RX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define	FRF_AZ_RX_DESCQ_EVQ_ID_LBN 24
+#define	FRF_AZ_RX_DESCQ_EVQ_ID_WIDTH 12
+#define	FRF_AZ_RX_DESCQ_OWNER_ID_LBN 10
+#define	FRF_AZ_RX_DESCQ_OWNER_ID_WIDTH 14
+#define	FRF_AZ_RX_DESCQ_LABEL_LBN 5
+#define	FRF_AZ_RX_DESCQ_LABEL_WIDTH 5
+#define	FRF_AZ_RX_DESCQ_SIZE_LBN 3
+#define	FRF_AZ_RX_DESCQ_SIZE_WIDTH 2
+#define	FFE_AZ_RX_DESCQ_SIZE_4K 3
+#define	FFE_AZ_RX_DESCQ_SIZE_2K 2
+#define	FFE_AZ_RX_DESCQ_SIZE_1K 1
+#define	FFE_AZ_RX_DESCQ_SIZE_512 0
+#define	FRF_AZ_RX_DESCQ_TYPE_LBN 2
+#define	FRF_AZ_RX_DESCQ_TYPE_WIDTH 1
+#define	FRF_AZ_RX_DESCQ_JUMBO_LBN 1
+#define	FRF_AZ_RX_DESCQ_JUMBO_WIDTH 1
+#define	FRF_AZ_RX_DESCQ_EN_LBN 0
+#define	FRF_AZ_RX_DESCQ_EN_WIDTH 1
+
+/* TX_DESC_PTR_TBL_KER: Transmit descriptor pointer */
+#define	FR_AA_TX_DESC_PTR_TBL_KER 0x00011900
+#define	FR_AA_TX_DESC_PTR_TBL_KER_STEP 16
+#define	FR_AA_TX_DESC_PTR_TBL_KER_ROWS 8
+/* TX_DESC_PTR_TBL: Transmit descriptor pointer */
+#define	FR_BZ_TX_DESC_PTR_TBL 0x00f50000
+#define	FR_BZ_TX_DESC_PTR_TBL_STEP 16
+#define	FR_BB_TX_DESC_PTR_TBL_ROWS 4096
+#define	FR_CZ_TX_DESC_PTR_TBL_ROWS 1024
+#define	FRF_CZ_TX_DPT_Q_MASK_WIDTH_LBN 94
+#define	FRF_CZ_TX_DPT_Q_MASK_WIDTH_WIDTH 2
+#define	FRF_CZ_TX_DPT_ETH_FILT_EN_LBN 93
+#define	FRF_CZ_TX_DPT_ETH_FILT_EN_WIDTH 1
+#define	FRF_CZ_TX_DPT_IP_FILT_EN_LBN 92
+#define	FRF_CZ_TX_DPT_IP_FILT_EN_WIDTH 1
+#define	FRF_BZ_TX_NON_IP_DROP_DIS_LBN 91
+#define	FRF_BZ_TX_NON_IP_DROP_DIS_WIDTH 1
+#define	FRF_BZ_TX_IP_CHKSM_DIS_LBN 90
+#define	FRF_BZ_TX_IP_CHKSM_DIS_WIDTH 1
+#define	FRF_BZ_TX_TCP_CHKSM_DIS_LBN 89
+#define	FRF_BZ_TX_TCP_CHKSM_DIS_WIDTH 1
+#define	FRF_AZ_TX_DESCQ_EN_LBN 88
+#define	FRF_AZ_TX_DESCQ_EN_WIDTH 1
+#define	FRF_AZ_TX_ISCSI_DDIG_EN_LBN 87
+#define	FRF_AZ_TX_ISCSI_DDIG_EN_WIDTH 1
+#define	FRF_AZ_TX_ISCSI_HDIG_EN_LBN 86
+#define	FRF_AZ_TX_ISCSI_HDIG_EN_WIDTH 1
+#define	FRF_AZ_TX_DC_HW_RPTR_LBN 80
+#define	FRF_AZ_TX_DC_HW_RPTR_WIDTH 6
+#define	FRF_AZ_TX_DESCQ_HW_RPTR_LBN 68
+#define	FRF_AZ_TX_DESCQ_HW_RPTR_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_SW_WPTR_LBN 56
+#define	FRF_AZ_TX_DESCQ_SW_WPTR_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_BUF_BASE_ID_LBN 36
+#define	FRF_AZ_TX_DESCQ_BUF_BASE_ID_WIDTH 20
+#define	FRF_AZ_TX_DESCQ_EVQ_ID_LBN 24
+#define	FRF_AZ_TX_DESCQ_EVQ_ID_WIDTH 12
+#define	FRF_AZ_TX_DESCQ_OWNER_ID_LBN 10
+#define	FRF_AZ_TX_DESCQ_OWNER_ID_WIDTH 14
+#define	FRF_AZ_TX_DESCQ_LABEL_LBN 5
+#define	FRF_AZ_TX_DESCQ_LABEL_WIDTH 5
+#define	FRF_AZ_TX_DESCQ_SIZE_LBN 3
+#define	FRF_AZ_TX_DESCQ_SIZE_WIDTH 2
+#define	FFE_AZ_TX_DESCQ_SIZE_4K 3
+#define	FFE_AZ_TX_DESCQ_SIZE_2K 2
+#define	FFE_AZ_TX_DESCQ_SIZE_1K 1
+#define	FFE_AZ_TX_DESCQ_SIZE_512 0
+#define	FRF_AZ_TX_DESCQ_TYPE_LBN 1
+#define	FRF_AZ_TX_DESCQ_TYPE_WIDTH 2
+#define	FRF_AZ_TX_DESCQ_FLUSH_LBN 0
+#define	FRF_AZ_TX_DESCQ_FLUSH_WIDTH 1
+
+/* EVQ_PTR_TBL_KER: Event queue pointer table */
+#define	FR_AA_EVQ_PTR_TBL_KER 0x00011a00
+#define	FR_AA_EVQ_PTR_TBL_KER_STEP 16
+#define	FR_AA_EVQ_PTR_TBL_KER_ROWS 4
+/* EVQ_PTR_TBL: Event queue pointer table */
+#define	FR_BZ_EVQ_PTR_TBL 0x00f60000
+#define	FR_BZ_EVQ_PTR_TBL_STEP 16
+#define	FR_CZ_EVQ_PTR_TBL_ROWS 1024
+#define	FR_BB_EVQ_PTR_TBL_ROWS 4096
+#define	FRF_BZ_EVQ_RPTR_IGN_LBN 40
+#define	FRF_BZ_EVQ_RPTR_IGN_WIDTH 1
+#define	FRF_AB_EVQ_WKUP_OR_INT_EN_LBN 39
+#define	FRF_AB_EVQ_WKUP_OR_INT_EN_WIDTH 1
+#define	FRF_CZ_EVQ_DOS_PROTECT_EN_LBN 39
+#define	FRF_CZ_EVQ_DOS_PROTECT_EN_WIDTH 1
+#define	FRF_AZ_EVQ_NXT_WPTR_LBN 24
+#define	FRF_AZ_EVQ_NXT_WPTR_WIDTH 15
+#define	FRF_AZ_EVQ_EN_LBN 23
+#define	FRF_AZ_EVQ_EN_WIDTH 1
+#define	FRF_AZ_EVQ_SIZE_LBN 20
+#define	FRF_AZ_EVQ_SIZE_WIDTH 3
+#define	FFE_AZ_EVQ_SIZE_32K 6
+#define	FFE_AZ_EVQ_SIZE_16K 5
+#define	FFE_AZ_EVQ_SIZE_8K 4
+#define	FFE_AZ_EVQ_SIZE_4K 3
+#define	FFE_AZ_EVQ_SIZE_2K 2
+#define	FFE_AZ_EVQ_SIZE_1K 1
+#define	FFE_AZ_EVQ_SIZE_512 0
+#define	FRF_AZ_EVQ_BUF_BASE_ID_LBN 0
+#define	FRF_AZ_EVQ_BUF_BASE_ID_WIDTH 20
+
+/* BUF_HALF_TBL_KER: Buffer table in half buffer table mode direct access by driver */
+#define	FR_AA_BUF_HALF_TBL_KER 0x00018000
+#define	FR_AA_BUF_HALF_TBL_KER_STEP 8
+#define	FR_AA_BUF_HALF_TBL_KER_ROWS 4096
+/* BUF_HALF_TBL: Buffer table in half buffer table mode direct access by driver */
+#define	FR_BZ_BUF_HALF_TBL 0x00800000
+#define	FR_BZ_BUF_HALF_TBL_STEP 8
+#define	FR_CZ_BUF_HALF_TBL_ROWS 147456
+#define	FR_BB_BUF_HALF_TBL_ROWS 524288
+#define	FRF_AZ_BUF_ADR_HBUF_ODD_LBN 44
+#define	FRF_AZ_BUF_ADR_HBUF_ODD_WIDTH 20
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_ODD_LBN 32
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_ODD_WIDTH 12
+#define	FRF_AZ_BUF_ADR_HBUF_EVEN_LBN 12
+#define	FRF_AZ_BUF_ADR_HBUF_EVEN_WIDTH 20
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_LBN 0
+#define	FRF_AZ_BUF_OWNER_ID_HBUF_EVEN_WIDTH 12
+
+/* BUF_FULL_TBL_KER: Buffer table in full buffer table mode direct access by driver */
+#define	FR_AA_BUF_FULL_TBL_KER 0x00018000
+#define	FR_AA_BUF_FULL_TBL_KER_STEP 8
+#define	FR_AA_BUF_FULL_TBL_KER_ROWS 4096
+/* BUF_FULL_TBL: Buffer table in full buffer table mode direct access by driver */
+#define	FR_BZ_BUF_FULL_TBL 0x00800000
+#define	FR_BZ_BUF_FULL_TBL_STEP 8
+#define	FR_CZ_BUF_FULL_TBL_ROWS 147456
+#define	FR_BB_BUF_FULL_TBL_ROWS 917504
+#define	FRF_AZ_BUF_FULL_UNUSED_LBN 51
+#define	FRF_AZ_BUF_FULL_UNUSED_WIDTH 13
+#define	FRF_AZ_IP_DAT_BUF_SIZE_LBN 50
+#define	FRF_AZ_IP_DAT_BUF_SIZE_WIDTH 1
+#define	FRF_AZ_BUF_ADR_REGION_LBN 48
+#define	FRF_AZ_BUF_ADR_REGION_WIDTH 2
+#define	FFE_AZ_BUF_ADR_REGN3 3
+#define	FFE_AZ_BUF_ADR_REGN2 2
+#define	FFE_AZ_BUF_ADR_REGN1 1
+#define	FFE_AZ_BUF_ADR_REGN0 0
+#define	FRF_AZ_BUF_ADR_FBUF_LBN 14
+#define	FRF_AZ_BUF_ADR_FBUF_WIDTH 34
+#define	FRF_AZ_BUF_OWNER_ID_FBUF_LBN 0
+#define	FRF_AZ_BUF_OWNER_ID_FBUF_WIDTH 14
+
+/* RX_FILTER_TBL0: TCP/IPv4 Receive filter table */
+#define	FR_BZ_RX_FILTER_TBL0 0x00f00000
+#define	FR_BZ_RX_FILTER_TBL0_STEP 32
+#define	FR_BZ_RX_FILTER_TBL0_ROWS 8192
+/* RX_FILTER_TBL1: TCP/IPv4 Receive filter table */
+#define	FR_BB_RX_FILTER_TBL1 0x00f00010
+#define	FR_BB_RX_FILTER_TBL1_STEP 32
+#define	FR_BB_RX_FILTER_TBL1_ROWS 8192
+#define	FRF_BZ_RSS_EN_LBN 110
+#define	FRF_BZ_RSS_EN_WIDTH 1
+#define	FRF_BZ_SCATTER_EN_LBN 109
+#define	FRF_BZ_SCATTER_EN_WIDTH 1
+#define	FRF_BZ_TCP_UDP_LBN 108
+#define	FRF_BZ_TCP_UDP_WIDTH 1
+#define	FRF_BZ_RXQ_ID_LBN 96
+#define	FRF_BZ_RXQ_ID_WIDTH 12
+#define	FRF_BZ_DEST_IP_LBN 64
+#define	FRF_BZ_DEST_IP_WIDTH 32
+#define	FRF_BZ_DEST_PORT_TCP_LBN 48
+#define	FRF_BZ_DEST_PORT_TCP_WIDTH 16
+#define	FRF_BZ_SRC_IP_LBN 16
+#define	FRF_BZ_SRC_IP_WIDTH 32
+#define	FRF_BZ_SRC_TCP_DEST_UDP_LBN 0
+#define	FRF_BZ_SRC_TCP_DEST_UDP_WIDTH 16
+
+/* RX_MAC_FILTER_TBL0: Receive Ethernet filter table */
+#define	FR_CZ_RX_MAC_FILTER_TBL0 0x00f00010
+#define	FR_CZ_RX_MAC_FILTER_TBL0_STEP 32
+#define	FR_CZ_RX_MAC_FILTER_TBL0_ROWS 512
+#define	FRF_CZ_RMFT_RSS_EN_LBN 75
+#define	FRF_CZ_RMFT_RSS_EN_WIDTH 1
+#define	FRF_CZ_RMFT_SCATTER_EN_LBN 74
+#define	FRF_CZ_RMFT_SCATTER_EN_WIDTH 1
+#define	FRF_CZ_RMFT_IP_OVERRIDE_LBN 73
+#define	FRF_CZ_RMFT_IP_OVERRIDE_WIDTH 1
+#define	FRF_CZ_RMFT_RXQ_ID_LBN 61
+#define	FRF_CZ_RMFT_RXQ_ID_WIDTH 12
+#define	FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60
+#define	FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1
+#define	FRF_CZ_RMFT_DEST_MAC_LBN 16
+#define	FRF_CZ_RMFT_DEST_MAC_WIDTH 44
+#define	FRF_CZ_RMFT_VLAN_ID_LBN 0
+#define	FRF_CZ_RMFT_VLAN_ID_WIDTH 12
+
+/* TIMER_TBL: Timer table */
+#define	FR_BZ_TIMER_TBL 0x00f70000
+#define	FR_BZ_TIMER_TBL_STEP 16
+#define	FR_CZ_TIMER_TBL_ROWS 1024
+#define	FR_BB_TIMER_TBL_ROWS 4096
+#define	FRF_CZ_TIMER_Q_EN_LBN 33
+#define	FRF_CZ_TIMER_Q_EN_WIDTH 1
+#define	FRF_CZ_INT_ARMD_LBN 32
+#define	FRF_CZ_INT_ARMD_WIDTH 1
+#define	FRF_CZ_INT_PEND_LBN 31
+#define	FRF_CZ_INT_PEND_WIDTH 1
+#define	FRF_CZ_HOST_NOTIFY_MODE_LBN 30
+#define	FRF_CZ_HOST_NOTIFY_MODE_WIDTH 1
+#define	FRF_CZ_RELOAD_TIMER_VAL_LBN 16
+#define	FRF_CZ_RELOAD_TIMER_VAL_WIDTH 14
+#define	FRF_CZ_TIMER_MODE_LBN 14
+#define	FRF_CZ_TIMER_MODE_WIDTH 2
+#define	FFE_CZ_TIMER_MODE_INT_HLDOFF 3
+#define	FFE_CZ_TIMER_MODE_TRIG_START 2
+#define	FFE_CZ_TIMER_MODE_IMMED_START 1
+#define	FFE_CZ_TIMER_MODE_DIS 0
+#define	FRF_BB_TIMER_MODE_LBN 12
+#define	FRF_BB_TIMER_MODE_WIDTH 2
+#define	FFE_BB_TIMER_MODE_INT_HLDOFF 2
+#define	FFE_BB_TIMER_MODE_TRIG_START 2
+#define	FFE_BB_TIMER_MODE_IMMED_START 1
+#define	FFE_BB_TIMER_MODE_DIS 0
+#define	FRF_CZ_TIMER_VAL_LBN 0
+#define	FRF_CZ_TIMER_VAL_WIDTH 14
+#define	FRF_BB_TIMER_VAL_LBN 0
+#define	FRF_BB_TIMER_VAL_WIDTH 12
+
+/* TX_PACE_TBL: Transmit pacing table */
+#define	FR_BZ_TX_PACE_TBL 0x00f80000
+#define	FR_BZ_TX_PACE_TBL_STEP 16
+#define	FR_CZ_TX_PACE_TBL_ROWS 1024
+#define	FR_BB_TX_PACE_TBL_ROWS 4096
+#define	FRF_BZ_TX_PACE_LBN 0
+#define	FRF_BZ_TX_PACE_WIDTH 5
+
+/* RX_INDIRECTION_TBL: RX Indirection Table */
+#define	FR_BZ_RX_INDIRECTION_TBL 0x00fb0000
+#define	FR_BZ_RX_INDIRECTION_TBL_STEP 16
+#define	FR_BZ_RX_INDIRECTION_TBL_ROWS 128
+#define	FRF_BZ_IT_QUEUE_LBN 0
+#define	FRF_BZ_IT_QUEUE_WIDTH 6
+
+/* TX_FILTER_TBL0: TCP/IPv4 Transmit filter table */
+#define	FR_CZ_TX_FILTER_TBL0 0x00fc0000
+#define	FR_CZ_TX_FILTER_TBL0_STEP 16
+#define	FR_CZ_TX_FILTER_TBL0_ROWS 8192
+#define	FRF_CZ_TIFT_TCP_UDP_LBN 108
+#define	FRF_CZ_TIFT_TCP_UDP_WIDTH 1
+#define	FRF_CZ_TIFT_TXQ_ID_LBN 96
+#define	FRF_CZ_TIFT_TXQ_ID_WIDTH 12
+#define	FRF_CZ_TIFT_DEST_IP_LBN 64
+#define	FRF_CZ_TIFT_DEST_IP_WIDTH 32
+#define	FRF_CZ_TIFT_DEST_PORT_TCP_LBN 48
+#define	FRF_CZ_TIFT_DEST_PORT_TCP_WIDTH 16
+#define	FRF_CZ_TIFT_SRC_IP_LBN 16
+#define	FRF_CZ_TIFT_SRC_IP_WIDTH 32
+#define	FRF_CZ_TIFT_SRC_TCP_DEST_UDP_LBN 0
+#define	FRF_CZ_TIFT_SRC_TCP_DEST_UDP_WIDTH 16
+
+/* TX_MAC_FILTER_TBL0: Transmit Ethernet filter table */
+#define	FR_CZ_TX_MAC_FILTER_TBL0 0x00fe0000
+#define	FR_CZ_TX_MAC_FILTER_TBL0_STEP 16
+#define	FR_CZ_TX_MAC_FILTER_TBL0_ROWS 512
+#define	FRF_CZ_TMFT_TXQ_ID_LBN 61
+#define	FRF_CZ_TMFT_TXQ_ID_WIDTH 12
+#define	FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60
+#define	FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1
+#define	FRF_CZ_TMFT_SRC_MAC_LBN 16
+#define	FRF_CZ_TMFT_SRC_MAC_WIDTH 44
+#define	FRF_CZ_TMFT_VLAN_ID_LBN 0
+#define	FRF_CZ_TMFT_VLAN_ID_WIDTH 12
+
+/* MC_TREG_SMEM: MC Shared Memory */
+#define	FR_CZ_MC_TREG_SMEM 0x00ff0000
+#define	FR_CZ_MC_TREG_SMEM_STEP 4
+#define	FR_CZ_MC_TREG_SMEM_ROWS 512
+#define	FRF_CZ_MC_TREG_SMEM_ROW_LBN 0
+#define	FRF_CZ_MC_TREG_SMEM_ROW_WIDTH 32
+
+/* MSIX_VECTOR_TABLE: MSIX Vector Table */
+#define	FR_BB_MSIX_VECTOR_TABLE 0x00ff0000
+#define	FR_BZ_MSIX_VECTOR_TABLE_STEP 16
+#define	FR_BB_MSIX_VECTOR_TABLE_ROWS 64
+/* MSIX_VECTOR_TABLE: MSIX Vector Table */
+#define	FR_CZ_MSIX_VECTOR_TABLE 0x00000000
+/* FR_BZ_MSIX_VECTOR_TABLE_STEP 16 */
+#define	FR_CZ_MSIX_VECTOR_TABLE_ROWS 1024
+#define	FRF_BZ_MSIX_VECTOR_RESERVED_LBN 97
+#define	FRF_BZ_MSIX_VECTOR_RESERVED_WIDTH 31
+#define	FRF_BZ_MSIX_VECTOR_MASK_LBN 96
+#define	FRF_BZ_MSIX_VECTOR_MASK_WIDTH 1
+#define	FRF_BZ_MSIX_MESSAGE_DATA_LBN 64
+#define	FRF_BZ_MSIX_MESSAGE_DATA_WIDTH 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_LBN 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_HI_WIDTH 32
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_LBN 0
+#define	FRF_BZ_MSIX_MESSAGE_ADDRESS_LO_WIDTH 32
+
+/* MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define	FR_BB_MSIX_PBA_TABLE 0x00ff2000
+#define	FR_BZ_MSIX_PBA_TABLE_STEP 4
+#define	FR_BB_MSIX_PBA_TABLE_ROWS 2
+/* MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define	FR_CZ_MSIX_PBA_TABLE 0x00008000
+/* FR_BZ_MSIX_PBA_TABLE_STEP 4 */
+#define	FR_CZ_MSIX_PBA_TABLE_ROWS 32
+#define	FRF_BZ_MSIX_PBA_PEND_DWORD_LBN 0
+#define	FRF_BZ_MSIX_PBA_PEND_DWORD_WIDTH 32
+
+/* SRM_DBG_REG: SRAM debug access */
+#define	FR_BZ_SRM_DBG 0x03000000
+#define	FR_BZ_SRM_DBG_STEP 8
+#define	FR_CZ_SRM_DBG_ROWS 262144
+#define	FR_BB_SRM_DBG_ROWS 2097152
+#define	FRF_BZ_SRM_DBG_LBN 0
+#define	FRF_BZ_SRM_DBG_WIDTH 64
+
+/* TB_MSIX_PBA_TABLE: MSIX Pending Bit Array */
+#define	FR_CZ_TB_MSIX_PBA_TABLE 0x00008000
+#define	FR_CZ_TB_MSIX_PBA_TABLE_STEP 4
+#define	FR_CZ_TB_MSIX_PBA_TABLE_ROWS 1024
+#define	FRF_CZ_TB_MSIX_PBA_PEND_DWORD_LBN 0
+#define	FRF_CZ_TB_MSIX_PBA_PEND_DWORD_WIDTH 32
+
+/* DRIVER_EV */
+#define	FSF_AZ_DRIVER_EV_SUBCODE_LBN 56
+#define	FSF_AZ_DRIVER_EV_SUBCODE_WIDTH 4
+#define	FSE_BZ_TX_DSC_ERROR_EV 15
+#define	FSE_BZ_RX_DSC_ERROR_EV 14
+#define	FSE_AA_RX_RECOVER_EV 11
+#define	FSE_AZ_TIMER_EV 10
+#define	FSE_AZ_TX_PKT_NON_TCP_UDP 9
+#define	FSE_AZ_WAKE_UP_EV 6
+#define	FSE_AZ_SRM_UPD_DONE_EV 5
+#define	FSE_AB_EVQ_NOT_EN_EV 3
+#define	FSE_AZ_EVQ_INIT_DONE_EV 2
+#define	FSE_AZ_RX_DESCQ_FLS_DONE_EV 1
+#define	FSE_AZ_TX_DESCQ_FLS_DONE_EV 0
+#define	FSF_AZ_DRIVER_EV_SUBDATA_LBN 0
+#define	FSF_AZ_DRIVER_EV_SUBDATA_WIDTH 14
+
+/* EVENT_ENTRY */
+#define	FSF_AZ_EV_CODE_LBN 60
+#define	FSF_AZ_EV_CODE_WIDTH 4
+#define	FSE_CZ_EV_CODE_MCDI_EV 12
+#define	FSE_CZ_EV_CODE_USER_EV 8
+#define	FSE_AZ_EV_CODE_DRV_GEN_EV 7
+#define	FSE_AZ_EV_CODE_GLOBAL_EV 6
+#define	FSE_AZ_EV_CODE_DRIVER_EV 5
+#define	FSE_AZ_EV_CODE_TX_EV 2
+#define	FSE_AZ_EV_CODE_RX_EV 0
+#define	FSF_AZ_EV_DATA_LBN 0
+#define	FSF_AZ_EV_DATA_WIDTH 60
+
+/* GLOBAL_EV */
+#define	FSF_BB_GLB_EV_RX_RECOVERY_LBN 12
+#define	FSF_BB_GLB_EV_RX_RECOVERY_WIDTH 1
+#define	FSF_AA_GLB_EV_RX_RECOVERY_LBN 11
+#define	FSF_AA_GLB_EV_RX_RECOVERY_WIDTH 1
+#define	FSF_BB_GLB_EV_XG_MGT_INTR_LBN 11
+#define	FSF_BB_GLB_EV_XG_MGT_INTR_WIDTH 1
+#define	FSF_AB_GLB_EV_XFP_PHY0_INTR_LBN 10
+#define	FSF_AB_GLB_EV_XFP_PHY0_INTR_WIDTH 1
+#define	FSF_AB_GLB_EV_XG_PHY0_INTR_LBN 9
+#define	FSF_AB_GLB_EV_XG_PHY0_INTR_WIDTH 1
+#define	FSF_AB_GLB_EV_G_PHY0_INTR_LBN 7
+#define	FSF_AB_GLB_EV_G_PHY0_INTR_WIDTH 1
+
+/* LEGACY_INT_VEC */
+#define	FSF_AZ_NET_IVEC_FATAL_INT_LBN 64
+#define	FSF_AZ_NET_IVEC_FATAL_INT_WIDTH 1
+#define	FSF_AZ_NET_IVEC_INT_Q_LBN 40
+#define	FSF_AZ_NET_IVEC_INT_Q_WIDTH 4
+#define	FSF_AZ_NET_IVEC_INT_FLAG_LBN 32
+#define	FSF_AZ_NET_IVEC_INT_FLAG_WIDTH 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_HF_LBN 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_HF_WIDTH 1
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_AF_LBN 0
+#define	FSF_AZ_NET_IVEC_EVQ_FIFO_AF_WIDTH 1
+
+/* MC_XGMAC_FLTR_RULE_DEF */
+#define	FSF_CZ_MC_XFRC_MODE_LBN 416
+#define	FSF_CZ_MC_XFRC_MODE_WIDTH 1
+#define	FSE_CZ_MC_XFRC_MODE_LAYERED 1
+#define	FSE_CZ_MC_XFRC_MODE_SIMPLE 0
+#define	FSF_CZ_MC_XFRC_HASH_LBN 384
+#define	FSF_CZ_MC_XFRC_HASH_WIDTH 32
+#define	FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_LBN 256
+#define	FSF_CZ_MC_XFRC_LAYER4_BYTE_MASK_WIDTH 128
+#define	FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_LBN 128
+#define	FSF_CZ_MC_XFRC_LAYER3_BYTE_MASK_WIDTH 128
+#define	FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_LBN 0
+#define	FSF_CZ_MC_XFRC_LAYER2_OR_SIMPLE_BYTE_MASK_WIDTH 128
+
+/* RX_EV */
+#define	FSF_CZ_RX_EV_PKT_NOT_PARSED_LBN 58
+#define	FSF_CZ_RX_EV_PKT_NOT_PARSED_WIDTH 1
+#define	FSF_CZ_RX_EV_IPV6_PKT_LBN 57
+#define	FSF_CZ_RX_EV_IPV6_PKT_WIDTH 1
+#define	FSF_AZ_RX_EV_PKT_OK_LBN 56
+#define	FSF_AZ_RX_EV_PKT_OK_WIDTH 1
+#define	FSF_AZ_RX_EV_PAUSE_FRM_ERR_LBN 55
+#define	FSF_AZ_RX_EV_PAUSE_FRM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_LBN 54
+#define	FSF_AZ_RX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_IP_FRAG_ERR_LBN 53
+#define	FSF_AZ_RX_EV_IP_FRAG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_LBN 52
+#define	FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51
+#define	FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_ETH_CRC_ERR_LBN 50
+#define	FSF_AZ_RX_EV_ETH_CRC_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_FRM_TRUNC_LBN 49
+#define	FSF_AZ_RX_EV_FRM_TRUNC_WIDTH 1
+#define	FSF_AA_RX_EV_DRIB_NIB_LBN 49
+#define	FSF_AA_RX_EV_DRIB_NIB_WIDTH 1
+#define	FSF_AZ_RX_EV_TOBE_DISC_LBN 47
+#define	FSF_AZ_RX_EV_TOBE_DISC_WIDTH 1
+#define	FSF_AZ_RX_EV_PKT_TYPE_LBN 44
+#define	FSF_AZ_RX_EV_PKT_TYPE_WIDTH 3
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN_JUMBO 5
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN_LLC 4
+#define	FSE_AZ_RX_EV_PKT_TYPE_VLAN 3
+#define	FSE_AZ_RX_EV_PKT_TYPE_JUMBO 2
+#define	FSE_AZ_RX_EV_PKT_TYPE_LLC 1
+#define	FSE_AZ_RX_EV_PKT_TYPE_ETH 0
+#define	FSF_AZ_RX_EV_HDR_TYPE_LBN 42
+#define	FSF_AZ_RX_EV_HDR_TYPE_WIDTH 2
+#define	FSE_AZ_RX_EV_HDR_TYPE_OTHER 3
+#define	FSE_AB_RX_EV_HDR_TYPE_IPV4_OTHER 2
+#define	FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER 2
+#define	FSE_AB_RX_EV_HDR_TYPE_IPV4_UDP 1
+#define	FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP 1
+#define	FSE_AB_RX_EV_HDR_TYPE_IPV4_TCP 0
+#define	FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP 0
+#define	FSF_AZ_RX_EV_DESC_Q_EMPTY_LBN 41
+#define	FSF_AZ_RX_EV_DESC_Q_EMPTY_WIDTH 1
+#define	FSF_AZ_RX_EV_MCAST_HASH_MATCH_LBN 40
+#define	FSF_AZ_RX_EV_MCAST_HASH_MATCH_WIDTH 1
+#define	FSF_AZ_RX_EV_MCAST_PKT_LBN 39
+#define	FSF_AZ_RX_EV_MCAST_PKT_WIDTH 1
+#define	FSF_AA_RX_EV_RECOVERY_FLAG_LBN 37
+#define	FSF_AA_RX_EV_RECOVERY_FLAG_WIDTH 1
+#define	FSF_AZ_RX_EV_Q_LABEL_LBN 32
+#define	FSF_AZ_RX_EV_Q_LABEL_WIDTH 5
+#define	FSF_AZ_RX_EV_JUMBO_CONT_LBN 31
+#define	FSF_AZ_RX_EV_JUMBO_CONT_WIDTH 1
+#define	FSF_AZ_RX_EV_PORT_LBN 30
+#define	FSF_AZ_RX_EV_PORT_WIDTH 1
+#define	FSF_AZ_RX_EV_BYTE_CNT_LBN 16
+#define	FSF_AZ_RX_EV_BYTE_CNT_WIDTH 14
+#define	FSF_AZ_RX_EV_SOP_LBN 15
+#define	FSF_AZ_RX_EV_SOP_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_PKT_OK_LBN 14
+#define	FSF_AZ_RX_EV_ISCSI_PKT_OK_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_DDIG_ERR_LBN 13
+#define	FSF_AZ_RX_EV_ISCSI_DDIG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_ISCSI_HDIG_ERR_LBN 12
+#define	FSF_AZ_RX_EV_ISCSI_HDIG_ERR_WIDTH 1
+#define	FSF_AZ_RX_EV_DESC_PTR_LBN 0
+#define	FSF_AZ_RX_EV_DESC_PTR_WIDTH 12
+
+/* RX_KER_DESC */
+#define	FSF_AZ_RX_KER_BUF_SIZE_LBN 48
+#define	FSF_AZ_RX_KER_BUF_SIZE_WIDTH 14
+#define	FSF_AZ_RX_KER_BUF_REGION_LBN 46
+#define	FSF_AZ_RX_KER_BUF_REGION_WIDTH 2
+#define	FSF_AZ_RX_KER_BUF_ADDR_LBN 0
+#define	FSF_AZ_RX_KER_BUF_ADDR_WIDTH 46
+
+/* RX_USER_DESC */
+#define	FSF_AZ_RX_USER_2BYTE_OFFSET_LBN 20
+#define	FSF_AZ_RX_USER_2BYTE_OFFSET_WIDTH 12
+#define	FSF_AZ_RX_USER_BUF_ID_LBN 0
+#define	FSF_AZ_RX_USER_BUF_ID_WIDTH 20
+
+/* TX_EV */
+#define	FSF_AZ_TX_EV_PKT_ERR_LBN 38
+#define	FSF_AZ_TX_EV_PKT_ERR_WIDTH 1
+#define	FSF_AZ_TX_EV_PKT_TOO_BIG_LBN 37
+#define	FSF_AZ_TX_EV_PKT_TOO_BIG_WIDTH 1
+#define	FSF_AZ_TX_EV_Q_LABEL_LBN 32
+#define	FSF_AZ_TX_EV_Q_LABEL_WIDTH 5
+#define	FSF_AZ_TX_EV_PORT_LBN 16
+#define	FSF_AZ_TX_EV_PORT_WIDTH 1
+#define	FSF_AZ_TX_EV_WQ_FF_FULL_LBN 15
+#define	FSF_AZ_TX_EV_WQ_FF_FULL_WIDTH 1
+#define	FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_LBN 14
+#define	FSF_AZ_TX_EV_BUF_OWNER_ID_ERR_WIDTH 1
+#define	FSF_AZ_TX_EV_COMP_LBN 12
+#define	FSF_AZ_TX_EV_COMP_WIDTH 1
+#define	FSF_AZ_TX_EV_DESC_PTR_LBN 0
+#define	FSF_AZ_TX_EV_DESC_PTR_WIDTH 12
+
+/* TX_KER_DESC */
+#define	FSF_AZ_TX_KER_CONT_LBN 62
+#define	FSF_AZ_TX_KER_CONT_WIDTH 1
+#define	FSF_AZ_TX_KER_BYTE_COUNT_LBN 48
+#define	FSF_AZ_TX_KER_BYTE_COUNT_WIDTH 14
+#define	FSF_AZ_TX_KER_BUF_REGION_LBN 46
+#define	FSF_AZ_TX_KER_BUF_REGION_WIDTH 2
+#define	FSF_AZ_TX_KER_BUF_ADDR_LBN 0
+#define	FSF_AZ_TX_KER_BUF_ADDR_WIDTH 46
+
+/* TX_USER_DESC */
+#define	FSF_AZ_TX_USER_SW_EV_EN_LBN 48
+#define	FSF_AZ_TX_USER_SW_EV_EN_WIDTH 1
+#define	FSF_AZ_TX_USER_CONT_LBN 46
+#define	FSF_AZ_TX_USER_CONT_WIDTH 1
+#define	FSF_AZ_TX_USER_BYTE_CNT_LBN 33
+#define	FSF_AZ_TX_USER_BYTE_CNT_WIDTH 13
+#define	FSF_AZ_TX_USER_BUF_ID_LBN 13
+#define	FSF_AZ_TX_USER_BUF_ID_WIDTH 20
+#define	FSF_AZ_TX_USER_BYTE_OFS_LBN 0
+#define	FSF_AZ_TX_USER_BYTE_OFS_WIDTH 13
+
+/* USER_EV */
+#define	FSF_CZ_USER_QID_LBN 32
+#define	FSF_CZ_USER_QID_WIDTH 10
+#define	FSF_CZ_USER_EV_REG_VALUE_LBN 0
+#define	FSF_CZ_USER_EV_REG_VALUE_WIDTH 32
+
+/**************************************************************************
+ *
+ * Falcon B0 PCIe core indirect registers
+ *
+ **************************************************************************
+ */
+
+#define FPCR_BB_PCIE_DEVICE_CTRL_STAT 0x68
+
+#define FPCR_BB_PCIE_LINK_CTRL_STAT 0x70
+
+#define FPCR_BB_ACK_RPL_TIMER 0x700
+#define FPCRF_BB_ACK_TL_LBN 0
+#define FPCRF_BB_ACK_TL_WIDTH 16
+#define FPCRF_BB_RPL_TL_LBN 16
+#define FPCRF_BB_RPL_TL_WIDTH 16
+
+#define FPCR_BB_ACK_FREQ 0x70C
+#define FPCRF_BB_ACK_FREQ_LBN 0
+#define FPCRF_BB_ACK_FREQ_WIDTH 7
+
+/**************************************************************************
+ *
+ * Pseudo-registers and fields
+ *
+ **************************************************************************
+ */
+
+/* Interrupt acknowledge work-around register (A0/A1 only) */
+#define FR_AA_WORK_AROUND_BROKEN_PCI_READS 0x0070
+
+/* EE_SPI_HCMD_REG: SPI host command register */
+/* Values for the EE_SPI_HCMD_SF_SEL register field */
+#define FFE_AB_SPI_DEVICE_EEPROM 0
+#define FFE_AB_SPI_DEVICE_FLASH 1
+
+/* NIC_STAT_REG: NIC status register */
+#define FRF_AB_STRAP_10G_LBN 2
+#define FRF_AB_STRAP_10G_WIDTH 1
+#define FRF_AA_STRAP_PCIE_LBN 0
+#define FRF_AA_STRAP_PCIE_WIDTH 1
+
+/* FATAL_INTR_REG_KER: Fatal interrupt register for Kernel */
+#define FRF_AZ_FATAL_INTR_LBN 0
+#define FRF_AZ_FATAL_INTR_WIDTH 12
+
+/* SRM_CFG_REG: SRAM configuration register */
+/* We treat the number of SRAM banks and bank size as a single field */
+#define	FRF_AZ_SRM_NB_SZ_LBN FRF_AZ_SRM_BANK_SIZE_LBN
+#define	FRF_AZ_SRM_NB_SZ_WIDTH \
+	(FRF_AZ_SRM_BANK_SIZE_WIDTH + FRF_AZ_SRM_NUM_BANK_WIDTH)
+#define FFE_AB_SRM_NB1_SZ2M 0
+#define FFE_AB_SRM_NB1_SZ4M 1
+#define FFE_AB_SRM_NB1_SZ8M 2
+#define FFE_AB_SRM_NB_SZ_DEF 3
+#define FFE_AB_SRM_NB2_SZ4M 4
+#define FFE_AB_SRM_NB2_SZ8M 5
+#define FFE_AB_SRM_NB2_SZ16M 6
+#define FFE_AB_SRM_NB_SZ_RES 7
+
+/* RX_DESC_UPD_REGP0: Receive descriptor update register. */
+/* We write just the last dword of these registers */
+#define	FR_AZ_RX_DESC_UPD_DWORD_P0 \
+	(BUILD_BUG_ON_ZERO(FR_AA_RX_DESC_UPD_KER != FR_BZ_RX_DESC_UPD_P0) + \
+	 FR_BZ_RX_DESC_UPD_P0 + 3 * 4)
+#define	FRF_AZ_RX_DESC_WPTR_DWORD_LBN (FRF_AZ_RX_DESC_WPTR_LBN - 3 * 32)
+#define	FRF_AZ_RX_DESC_WPTR_DWORD_WIDTH FRF_AZ_RX_DESC_WPTR_WIDTH
+
+/* TX_DESC_UPD_REGP0: Transmit descriptor update register. */
+#define FR_AZ_TX_DESC_UPD_DWORD_P0 \
+	(BUILD_BUG_ON_ZERO(FR_AA_TX_DESC_UPD_KER != FR_BZ_TX_DESC_UPD_P0) + \
+	 FR_BZ_TX_DESC_UPD_P0 + 3 * 4)
+#define	FRF_AZ_TX_DESC_WPTR_DWORD_LBN (FRF_AZ_TX_DESC_WPTR_LBN - 3 * 32)
+#define	FRF_AZ_TX_DESC_WPTR_DWORD_WIDTH FRF_AZ_TX_DESC_WPTR_WIDTH
+
+/* GMF_CFG4_REG: GMAC FIFO configuration register 4 */
+#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_LBN 12
+#define FRF_AB_GMF_HSTFLTRFRM_PAUSE_WIDTH 1
+
+/* GMF_CFG5_REG: GMAC FIFO configuration register 5 */
+#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_LBN 12
+#define FRF_AB_GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
+
+/* XM_TX_PARAM_REG: XGMAC transmit parameter register */
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_LBN FRF_AB_XM_MAX_TX_FRM_SIZE_LO_LBN
+#define	FRF_AB_XM_MAX_TX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_TX_FRM_SIZE_HI_WIDTH + \
+					 FRF_AB_XM_MAX_TX_FRM_SIZE_LO_WIDTH)
+
+/* XM_RX_PARAM_REG: XGMAC receive parameter register */
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_LBN FRF_AB_XM_MAX_RX_FRM_SIZE_LO_LBN
+#define	FRF_AB_XM_MAX_RX_FRM_SIZE_WIDTH (FRF_AB_XM_MAX_RX_FRM_SIZE_HI_WIDTH + \
+					 FRF_AB_XM_MAX_RX_FRM_SIZE_LO_WIDTH)
+
+/* XX_TXDRV_CTL_REG: XAUI SerDes transmit drive control register */
+/* Default values */
+#define FFE_AB_XX_TXDRV_DEQ_DEF 0xe /* deq=.6 */
+#define FFE_AB_XX_TXDRV_DTX_DEF 0x5 /* 1.25 */
+#define FFE_AB_XX_SD_CTL_DRV_DEF 0  /* 20mA */
+
+/* XX_CORE_STAT_REG: XAUI XGXS core status register */
+/* XGXS all-lanes status fields */
+#define	FRF_AB_XX_SYNC_STAT_LBN FRF_AB_XX_SYNC_STAT0_LBN
+#define	FRF_AB_XX_SYNC_STAT_WIDTH 4
+#define	FRF_AB_XX_COMMA_DET_LBN FRF_AB_XX_COMMA_DET_CH0_LBN
+#define	FRF_AB_XX_COMMA_DET_WIDTH 4
+#define	FRF_AB_XX_CHAR_ERR_LBN FRF_AB_XX_CHAR_ERR_CH0_LBN
+#define	FRF_AB_XX_CHAR_ERR_WIDTH 4
+#define	FRF_AB_XX_DISPERR_LBN FRF_AB_XX_DISPERR_CH0_LBN
+#define	FRF_AB_XX_DISPERR_WIDTH 4
+#define	FFE_AB_XX_STAT_ALL_LANES 0xf
+#define	FRF_AB_XX_FORCE_SIG_LBN FRF_AB_XX_FORCE_SIG0_VAL_LBN
+#define	FRF_AB_XX_FORCE_SIG_WIDTH 8
+#define	FFE_AB_XX_FORCE_SIG_ALL_LANES 0xff
+
+/* DRIVER_EV */
+/* Sub-fields of an RX flush completion event */
+#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
+#define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1
+#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_LBN 0
+#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_WIDTH 12
+
+/* EVENT_ENTRY */
+/* Magic number field for event test */
+#define FSF_AZ_DRV_GEN_EV_MAGIC_LBN 0
+#define FSF_AZ_DRV_GEN_EV_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
+
+/**************************************************************************
+ *
+ * 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;
+} __packed;
+
+/* Board configuration v3 extra information */
+struct falcon_nvconfig_board_v3 {
+	__le32 spi_device_type[2];
+} __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(EFX_WIDTH(field)))
+
+#define FALCON_NVCONFIG_OFFSET 0x300
+
+#define FALCON_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 */
+} __packed;
+
+#endif /* EFX_REGS_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mcdi.c
+++ linux-ec2-2.6.32/drivers/net/sfc/mcdi.c
@@ -0,0 +1,1114 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2008-2009 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, incorporated herein by reference.
+ */
+
+#include <linux/delay.h>
+#include "net_driver.h"
+#include "nic.h"
+#include "io.h"
+#include "regs.h"
+#include "mcdi_pcol.h"
+#include "phy.h"
+
+/**************************************************************************
+ *
+ * Management-Controller-to-Driver Interface
+ *
+ **************************************************************************
+ */
+
+/* Software-defined structure to the shared-memory */
+#define CMD_NOTIFY_PORT0 0
+#define CMD_NOTIFY_PORT1 4
+#define CMD_PDU_PORT0    0x008
+#define CMD_PDU_PORT1    0x108
+#define REBOOT_FLAG_PORT0 0x3f8
+#define REBOOT_FLAG_PORT1 0x3fc
+
+#define MCDI_RPC_TIMEOUT       10 /*seconds */
+
+#define MCDI_PDU(efx)							\
+	(efx_port_num(efx) ? CMD_PDU_PORT1 : CMD_PDU_PORT0)
+#define MCDI_DOORBELL(efx)						\
+	(efx_port_num(efx) ? CMD_NOTIFY_PORT1 : CMD_NOTIFY_PORT0)
+#define MCDI_REBOOT_FLAG(efx)						\
+	(efx_port_num(efx) ? REBOOT_FLAG_PORT1 : REBOOT_FLAG_PORT0)
+
+#define SEQ_MASK							\
+	EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ))
+
+static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
+{
+	struct siena_nic_data *nic_data;
+	EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
+	nic_data = efx->nic_data;
+	return &nic_data->mcdi;
+}
+
+void efx_mcdi_init(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi;
+
+	if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+		return;
+
+	mcdi = efx_mcdi(efx);
+	init_waitqueue_head(&mcdi->wq);
+	spin_lock_init(&mcdi->iface_lock);
+	atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
+	mcdi->mode = MCDI_MODE_POLL;
+
+	(void) efx_mcdi_poll_reboot(efx);
+}
+
+static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
+			    const u8 *inbuf, size_t inlen)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+	unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+	unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
+	unsigned int i;
+	efx_dword_t hdr;
+	u32 xflags, seqno;
+
+	BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
+	BUG_ON(inlen & 3 || inlen >= 0x100);
+
+	seqno = mcdi->seqno & SEQ_MASK;
+	xflags = 0;
+	if (mcdi->mode == MCDI_MODE_EVENTS)
+		xflags |= MCDI_HEADER_XFLAGS_EVREQ;
+
+	EFX_POPULATE_DWORD_6(hdr,
+			     MCDI_HEADER_RESPONSE, 0,
+			     MCDI_HEADER_RESYNC, 1,
+			     MCDI_HEADER_CODE, cmd,
+			     MCDI_HEADER_DATALEN, inlen,
+			     MCDI_HEADER_SEQ, seqno,
+			     MCDI_HEADER_XFLAGS, xflags);
+
+	efx_writed(efx, &hdr, pdu);
+
+	for (i = 0; i < inlen; i += 4)
+		_efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i);
+
+	/* Ensure the payload is written out before the header */
+	wmb();
+
+	/* ring the doorbell with a distinctive value */
+	_efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
+}
+
+static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+	unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+	int i;
+
+	BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
+	BUG_ON(outlen & 3 || outlen >= 0x100);
+
+	for (i = 0; i < outlen; i += 4)
+		*((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i);
+}
+
+static int efx_mcdi_poll(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+	unsigned int time, finish;
+	unsigned int respseq, respcmd, error;
+	unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+	unsigned int rc, spins;
+	efx_dword_t reg;
+
+	/* Check for a reboot atomically with respect to efx_mcdi_copyout() */
+	rc = -efx_mcdi_poll_reboot(efx);
+	if (rc)
+		goto out;
+
+	/* Poll for completion. Poll quickly (once a us) for the 1st jiffy,
+	 * because generally mcdi responses are fast. After that, back off
+	 * and poll once a jiffy (approximately)
+	 */
+	spins = TICK_USEC;
+	finish = get_seconds() + MCDI_RPC_TIMEOUT;
+
+	while (1) {
+		if (spins != 0) {
+			--spins;
+			udelay(1);
+		} else {
+			schedule_timeout_uninterruptible(1);
+		}
+
+		time = get_seconds();
+
+		rmb();
+		efx_readd(efx, &reg, pdu);
+
+		/* All 1's indicates that shared memory is in reset (and is
+		 * not a valid header). Wait for it to come out reset before
+		 * completing the command */
+		if (EFX_DWORD_FIELD(reg, EFX_DWORD_0) != 0xffffffff &&
+		    EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
+			break;
+
+		if (time >= finish)
+			return -ETIMEDOUT;
+	}
+
+	mcdi->resplen = EFX_DWORD_FIELD(reg, MCDI_HEADER_DATALEN);
+	respseq = EFX_DWORD_FIELD(reg, MCDI_HEADER_SEQ);
+	respcmd = EFX_DWORD_FIELD(reg, MCDI_HEADER_CODE);
+	error = EFX_DWORD_FIELD(reg, MCDI_HEADER_ERROR);
+
+	if (error && mcdi->resplen == 0) {
+		EFX_ERR(efx, "MC rebooted\n");
+		rc = EIO;
+	} else if ((respseq ^ mcdi->seqno) & SEQ_MASK) {
+		EFX_ERR(efx, "MC response mismatch tx seq 0x%x rx seq 0x%x\n",
+			respseq, mcdi->seqno);
+		rc = EIO;
+	} else if (error) {
+		efx_readd(efx, &reg, pdu + 4);
+		switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
+#define TRANSLATE_ERROR(name)					\
+		case MC_CMD_ERR_ ## name:			\
+			rc = name;				\
+			break
+			TRANSLATE_ERROR(ENOENT);
+			TRANSLATE_ERROR(EINTR);
+			TRANSLATE_ERROR(EACCES);
+			TRANSLATE_ERROR(EBUSY);
+			TRANSLATE_ERROR(EINVAL);
+			TRANSLATE_ERROR(EDEADLK);
+			TRANSLATE_ERROR(ENOSYS);
+			TRANSLATE_ERROR(ETIME);
+#undef TRANSLATE_ERROR
+		default:
+			rc = EIO;
+			break;
+		}
+	} else
+		rc = 0;
+
+out:
+	mcdi->resprc = rc;
+	if (rc)
+		mcdi->resplen = 0;
+
+	/* Return rc=0 like wait_event_timeout() */
+	return 0;
+}
+
+/* Test and clear MC-rebooted flag for this port/function */
+int efx_mcdi_poll_reboot(struct efx_nic *efx)
+{
+	unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx);
+	efx_dword_t reg;
+	uint32_t value;
+
+	if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+		return false;
+
+	efx_readd(efx, &reg, addr);
+	value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
+
+	if (value == 0)
+		return 0;
+
+	EFX_ZERO_DWORD(reg);
+	efx_writed(efx, &reg, addr);
+
+	if (value == MC_STATUS_DWORD_ASSERT)
+		return -EINTR;
+	else
+		return -EIO;
+}
+
+static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
+{
+	/* Wait until the interface becomes QUIESCENT and we win the race
+	 * to mark it RUNNING. */
+	wait_event(mcdi->wq,
+		   atomic_cmpxchg(&mcdi->state,
+				  MCDI_STATE_QUIESCENT,
+				  MCDI_STATE_RUNNING)
+		   == MCDI_STATE_QUIESCENT);
+}
+
+static int efx_mcdi_await_completion(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+	if (wait_event_timeout(
+		    mcdi->wq,
+		    atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
+		    msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0)
+		return -ETIMEDOUT;
+
+	/* Check if efx_mcdi_set_mode() switched us back to polled completions.
+	 * In which case, poll for completions directly. If efx_mcdi_ev_cpl()
+	 * completed the request first, then we'll just end up completing the
+	 * request again, which is safe.
+	 *
+	 * We need an smp_rmb() to synchronise with efx_mcdi_mode_poll(), which
+	 * wait_event_timeout() implicitly provides.
+	 */
+	if (mcdi->mode == MCDI_MODE_POLL)
+		return efx_mcdi_poll(efx);
+
+	return 0;
+}
+
+static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
+{
+	/* If the interface is RUNNING, then move to COMPLETED and wake any
+	 * waiters. If the interface isn't in RUNNING then we've received a
+	 * duplicate completion after we've already transitioned back to
+	 * QUIESCENT. [A subsequent invocation would increment seqno, so would
+	 * have failed the seqno check].
+	 */
+	if (atomic_cmpxchg(&mcdi->state,
+			   MCDI_STATE_RUNNING,
+			   MCDI_STATE_COMPLETED) == MCDI_STATE_RUNNING) {
+		wake_up(&mcdi->wq);
+		return true;
+	}
+
+	return false;
+}
+
+static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
+{
+	atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
+	wake_up(&mcdi->wq);
+}
+
+static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
+			    unsigned int datalen, unsigned int errno)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+	bool wake = false;
+
+	spin_lock(&mcdi->iface_lock);
+
+	if ((seqno ^ mcdi->seqno) & SEQ_MASK) {
+		if (mcdi->credits)
+			/* The request has been cancelled */
+			--mcdi->credits;
+		else
+			EFX_ERR(efx, "MC response mismatch tx seq 0x%x rx "
+				"seq 0x%x\n", seqno, mcdi->seqno);
+	} else {
+		mcdi->resprc = errno;
+		mcdi->resplen = datalen;
+
+		wake = true;
+	}
+
+	spin_unlock(&mcdi->iface_lock);
+
+	if (wake)
+		efx_mcdi_complete(mcdi);
+}
+
+/* Issue the given command by writing the data into the shared memory PDU,
+ * ring the doorbell and wait for completion. Copyout the result. */
+int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
+		 const u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen,
+		 size_t *outlen_actual)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+	int rc;
+	BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
+
+	efx_mcdi_acquire(mcdi);
+
+	/* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
+	spin_lock_bh(&mcdi->iface_lock);
+	++mcdi->seqno;
+	spin_unlock_bh(&mcdi->iface_lock);
+
+	efx_mcdi_copyin(efx, cmd, inbuf, inlen);
+
+	if (mcdi->mode == MCDI_MODE_POLL)
+		rc = efx_mcdi_poll(efx);
+	else
+		rc = efx_mcdi_await_completion(efx);
+
+	if (rc != 0) {
+		/* Close the race with efx_mcdi_ev_cpl() executing just too late
+		 * and completing a request we've just cancelled, by ensuring
+		 * that the seqno check therein fails.
+		 */
+		spin_lock_bh(&mcdi->iface_lock);
+		++mcdi->seqno;
+		++mcdi->credits;
+		spin_unlock_bh(&mcdi->iface_lock);
+
+		EFX_ERR(efx, "MC command 0x%x inlen %d mode %d timed out\n",
+			cmd, (int)inlen, mcdi->mode);
+	} else {
+		size_t resplen;
+
+		/* At the very least we need a memory barrier here to ensure
+		 * we pick up changes from efx_mcdi_ev_cpl(). Protect against
+		 * a spurious efx_mcdi_ev_cpl() running concurrently by
+		 * acquiring the iface_lock. */
+		spin_lock_bh(&mcdi->iface_lock);
+		rc = -mcdi->resprc;
+		resplen = mcdi->resplen;
+		spin_unlock_bh(&mcdi->iface_lock);
+
+		if (rc == 0) {
+			efx_mcdi_copyout(efx, outbuf,
+					 min(outlen, mcdi->resplen + 3) & ~0x3);
+			if (outlen_actual != NULL)
+				*outlen_actual = resplen;
+		} else if (cmd == MC_CMD_REBOOT && rc == -EIO)
+			; /* Don't reset if MC_CMD_REBOOT returns EIO */
+		else if (rc == -EIO || rc == -EINTR) {
+			EFX_ERR(efx, "MC fatal error %d\n", -rc);
+			efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
+		} else
+			EFX_ERR(efx, "MC command 0x%x inlen %d failed rc=%d\n",
+				cmd, (int)inlen, -rc);
+	}
+
+	efx_mcdi_release(mcdi);
+	return rc;
+}
+
+void efx_mcdi_mode_poll(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi;
+
+	if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+		return;
+
+	mcdi = efx_mcdi(efx);
+	if (mcdi->mode == MCDI_MODE_POLL)
+		return;
+
+	/* We can switch from event completion to polled completion, because
+	 * mcdi requests are always completed in shared memory. We do this by
+	 * switching the mode to POLL'd then completing the request.
+	 * efx_mcdi_await_completion() will then call efx_mcdi_poll().
+	 *
+	 * We need an smp_wmb() to synchronise with efx_mcdi_await_completion(),
+	 * which efx_mcdi_complete() provides for us.
+	 */
+	mcdi->mode = MCDI_MODE_POLL;
+
+	efx_mcdi_complete(mcdi);
+}
+
+void efx_mcdi_mode_event(struct efx_nic *efx)
+{
+	struct efx_mcdi_iface *mcdi;
+
+	if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+		return;
+
+	mcdi = efx_mcdi(efx);
+
+	if (mcdi->mode == MCDI_MODE_EVENTS)
+		return;
+
+	/* We can't switch from polled to event completion in the middle of a
+	 * request, because the completion method is specified in the request.
+	 * So acquire the interface to serialise the requestors. We don't need
+	 * to acquire the iface_lock to change the mode here, but we do need a
+	 * write memory barrier ensure that efx_mcdi_rpc() sees it, which
+	 * efx_mcdi_acquire() provides.
+	 */
+	efx_mcdi_acquire(mcdi);
+	mcdi->mode = MCDI_MODE_EVENTS;
+	efx_mcdi_release(mcdi);
+}
+
+static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
+{
+	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+	/* If there is an outstanding MCDI request, it has been terminated
+	 * either by a BADASSERT or REBOOT event. If the mcdi interface is
+	 * in polled mode, then do nothing because the MC reboot handler will
+	 * set the header correctly. However, if the mcdi interface is waiting
+	 * for a CMDDONE event it won't receive it [and since all MCDI events
+	 * are sent to the same queue, we can't be racing with
+	 * efx_mcdi_ev_cpl()]
+	 *
+	 * There's a race here with efx_mcdi_rpc(), because we might receive
+	 * a REBOOT event *before* the request has been copied out. In polled
+	 * mode (during startup) this is irrelevent, because efx_mcdi_complete()
+	 * is ignored. In event mode, this condition is just an edge-case of
+	 * receiving a REBOOT event after posting the MCDI request. Did the mc
+	 * reboot before or after the copyout? The best we can do always is
+	 * just return failure.
+	 */
+	spin_lock(&mcdi->iface_lock);
+	if (efx_mcdi_complete(mcdi)) {
+		if (mcdi->mode == MCDI_MODE_EVENTS) {
+			mcdi->resprc = rc;
+			mcdi->resplen = 0;
+		}
+	} else
+		/* Nobody was waiting for an MCDI request, so trigger a reset */
+		efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
+
+	spin_unlock(&mcdi->iface_lock);
+}
+
+static unsigned int efx_mcdi_event_link_speed[] = {
+	[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
+	[MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
+	[MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
+};
+
+
+static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
+{
+	u32 flags, fcntl, speed, lpa;
+
+	speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
+	EFX_BUG_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
+	speed = efx_mcdi_event_link_speed[speed];
+
+	flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
+	fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
+	lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
+
+	/* efx->link_state is only modified by efx_mcdi_phy_get_link(),
+	 * which is only run after flushing the event queues. Therefore, it
+	 * is safe to modify the link state outside of the mac_lock here.
+	 */
+	efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
+
+	efx_mcdi_phy_check_fcntl(efx, lpa);
+
+	efx_link_status_changed(efx);
+}
+
+static const char *sensor_names[] = {
+	[MC_CMD_SENSOR_CONTROLLER_TEMP] = "Controller temp. sensor",
+	[MC_CMD_SENSOR_PHY_COMMON_TEMP] = "PHY shared temp. sensor",
+	[MC_CMD_SENSOR_CONTROLLER_COOLING] = "Controller cooling",
+	[MC_CMD_SENSOR_PHY0_TEMP] = "PHY 0 temp. sensor",
+	[MC_CMD_SENSOR_PHY0_COOLING] = "PHY 0 cooling",
+	[MC_CMD_SENSOR_PHY1_TEMP] = "PHY 1 temp. sensor",
+	[MC_CMD_SENSOR_PHY1_COOLING] = "PHY 1 cooling",
+	[MC_CMD_SENSOR_IN_1V0] = "1.0V supply sensor",
+	[MC_CMD_SENSOR_IN_1V2] = "1.2V supply sensor",
+	[MC_CMD_SENSOR_IN_1V8] = "1.8V supply sensor",
+	[MC_CMD_SENSOR_IN_2V5] = "2.5V supply sensor",
+	[MC_CMD_SENSOR_IN_3V3] = "3.3V supply sensor",
+	[MC_CMD_SENSOR_IN_12V0] = "12V supply sensor"
+};
+
+static const char *sensor_status_names[] = {
+	[MC_CMD_SENSOR_STATE_OK] = "OK",
+	[MC_CMD_SENSOR_STATE_WARNING] = "Warning",
+	[MC_CMD_SENSOR_STATE_FATAL] = "Fatal",
+	[MC_CMD_SENSOR_STATE_BROKEN] = "Device failure",
+};
+
+static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev)
+{
+	unsigned int monitor, state, value;
+	const char *name, *state_txt;
+	monitor = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR);
+	state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE);
+	value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE);
+	/* Deal gracefully with the board having more drivers than we
+	 * know about, but do not expect new sensor states. */
+	name = (monitor >= ARRAY_SIZE(sensor_names))
+				    ? "No sensor name available" :
+				    sensor_names[monitor];
+	EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names));
+	state_txt = sensor_status_names[state];
+
+	EFX_ERR(efx, "Sensor %d (%s) reports condition '%s' for raw value %d\n",
+		monitor, name, state_txt, value);
+}
+
+/* Called from  falcon_process_eventq for MCDI events */
+void efx_mcdi_process_event(struct efx_channel *channel,
+			    efx_qword_t *event)
+{
+	struct efx_nic *efx = channel->efx;
+	int code = EFX_QWORD_FIELD(*event, MCDI_EVENT_CODE);
+	u32 data = EFX_QWORD_FIELD(*event, MCDI_EVENT_DATA);
+
+	switch (code) {
+	case MCDI_EVENT_CODE_BADSSERT:
+		EFX_ERR(efx, "MC watchdog or assertion failure at 0x%x\n", data);
+		efx_mcdi_ev_death(efx, EINTR);
+		break;
+
+	case MCDI_EVENT_CODE_PMNOTICE:
+		EFX_INFO(efx, "MCDI PM event.\n");
+		break;
+
+	case MCDI_EVENT_CODE_CMDDONE:
+		efx_mcdi_ev_cpl(efx,
+				MCDI_EVENT_FIELD(*event, CMDDONE_SEQ),
+				MCDI_EVENT_FIELD(*event, CMDDONE_DATALEN),
+				MCDI_EVENT_FIELD(*event, CMDDONE_ERRNO));
+		break;
+
+	case MCDI_EVENT_CODE_LINKCHANGE:
+		efx_mcdi_process_link_change(efx, event);
+		break;
+	case MCDI_EVENT_CODE_SENSOREVT:
+		efx_mcdi_sensor_event(efx, event);
+		break;
+	case MCDI_EVENT_CODE_SCHEDERR:
+		EFX_INFO(efx, "MC Scheduler error address=0x%x\n", data);
+		break;
+	case MCDI_EVENT_CODE_REBOOT:
+		EFX_INFO(efx, "MC Reboot\n");
+		efx_mcdi_ev_death(efx, EIO);
+		break;
+	case MCDI_EVENT_CODE_MAC_STATS_DMA:
+		/* MAC stats are gather lazily.  We can ignore this. */
+		break;
+
+	default:
+		EFX_ERR(efx, "Unknown MCDI event 0x%x\n", code);
+	}
+}
+
+/**************************************************************************
+ *
+ * Specific request functions
+ *
+ **************************************************************************
+ */
+
+int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
+{
+	u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)];
+	size_t outlength;
+	const __le16 *ver_words;
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlength);
+	if (rc)
+		goto fail;
+
+	if (outlength == MC_CMD_GET_VERSION_V0_OUT_LEN) {
+		*version = 0;
+		*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
+		return 0;
+	}
+
+	if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
+	*version = (((u64)le16_to_cpu(ver_words[0]) << 48) |
+		    ((u64)le16_to_cpu(ver_words[1]) << 32) |
+		    ((u64)le16_to_cpu(ver_words[2]) << 16) |
+		    le16_to_cpu(ver_words[3]));
+	*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
+			bool *was_attached)
+{
+	u8 inbuf[MC_CMD_DRV_ATTACH_IN_LEN];
+	u8 outbuf[MC_CMD_DRV_ATTACH_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_NEW_STATE,
+		       driver_operating ? 1 : 0);
+	MCDI_SET_DWORD(inbuf, DRV_ATTACH_IN_UPDATE, 1);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_DRV_ATTACH, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+	if (outlen < MC_CMD_DRV_ATTACH_OUT_LEN)
+		goto fail;
+
+	if (was_attached != NULL)
+		*was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
+			   u16 *fw_subtype_list)
+{
+	uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LEN];
+	size_t outlen;
+	int port_num = efx_port_num(efx);
+	int offset;
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_BOARD_CFG, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	offset = (port_num)
+		? MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST
+		: MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST;
+	if (mac_address)
+		memcpy(mac_address, outbuf + offset, ETH_ALEN);
+	if (fw_subtype_list)
+		memcpy(fw_subtype_list,
+		       outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST,
+		       MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN);
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d len=%d\n", __func__, rc, (int)outlen);
+
+	return rc;
+}
+
+int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq)
+{
+	u8 inbuf[MC_CMD_LOG_CTRL_IN_LEN];
+	u32 dest = 0;
+	int rc;
+
+	if (uart)
+		dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_UART;
+	if (evq)
+		dest |= MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ;
+
+	MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST, dest);
+	MCDI_SET_DWORD(inbuf, LOG_CTRL_IN_LOG_DEST_EVQ, dest_evq);
+
+	BUILD_BUG_ON(MC_CMD_LOG_CTRL_OUT_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_LOG_CTRL, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out)
+{
+	u8 outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_NVRAM_TYPES_IN_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TYPES, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+	if (outlen < MC_CMD_NVRAM_TYPES_OUT_LEN)
+		goto fail;
+
+	*nvram_types_out = MCDI_DWORD(outbuf, NVRAM_TYPES_OUT_TYPES);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n",
+		__func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
+			size_t *size_out, size_t *erase_size_out,
+			bool *protected_out)
+{
+	u8 inbuf[MC_CMD_NVRAM_INFO_IN_LEN];
+	u8 outbuf[MC_CMD_NVRAM_INFO_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_INFO_IN_TYPE, type);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_INFO, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+	if (outlen < MC_CMD_NVRAM_INFO_OUT_LEN)
+		goto fail;
+
+	*size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE);
+	*erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE);
+	*protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) &
+				(1 << MC_CMD_NVRAM_PROTECTED_LBN));
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
+{
+	u8 inbuf[MC_CMD_NVRAM_UPDATE_START_IN_LEN];
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
+
+	BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
+			loff_t offset, u8 *buffer, size_t length)
+{
+	u8 inbuf[MC_CMD_NVRAM_READ_IN_LEN];
+	u8 outbuf[MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
+	MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
+	MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
+			   loff_t offset, const u8 *buffer, size_t length)
+{
+	u8 inbuf[MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX)];
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
+	MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
+	MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
+	memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
+
+	BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
+			  ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
+			 loff_t offset, size_t length)
+{
+	u8 inbuf[MC_CMD_NVRAM_ERASE_IN_LEN];
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
+	MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
+	MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
+
+	BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
+{
+	u8 inbuf[MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN];
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
+
+	BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_handle_assertion(struct efx_nic *efx)
+{
+	union {
+		u8 asserts[MC_CMD_GET_ASSERTS_IN_LEN];
+		u8 reboot[MC_CMD_REBOOT_IN_LEN];
+	} inbuf;
+	u8 assertion[MC_CMD_GET_ASSERTS_OUT_LEN];
+	unsigned int flags, index, ofst;
+	const char *reason;
+	size_t outlen;
+	int retry;
+	int rc;
+
+	/* Check if the MC is in the assertion handler, retrying twice. Once
+	 * because a boot-time assertion might cause this command to fail
+	 * with EINTR. And once again because GET_ASSERTS can race with
+	 * MC_CMD_REBOOT running on the other port. */
+	retry = 2;
+	do {
+		MCDI_SET_DWORD(inbuf.asserts, GET_ASSERTS_IN_CLEAR, 0);
+		rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS,
+				  inbuf.asserts, MC_CMD_GET_ASSERTS_IN_LEN,
+				  assertion, sizeof(assertion), &outlen);
+	} while ((rc == -EINTR || rc == -EIO) && retry-- > 0);
+
+	if (rc)
+		return rc;
+	if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN)
+		return -EINVAL;
+
+	flags = MCDI_DWORD(assertion, GET_ASSERTS_OUT_GLOBAL_FLAGS);
+	if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
+		return 0;
+
+	/* Reset the hardware atomically such that only one port with succeed.
+	 * This command will succeed if a reboot is no longer required (because
+	 * the other port did it first), but fail with EIO if it succeeds.
+	 */
+	BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
+	MCDI_SET_DWORD(inbuf.reboot, REBOOT_IN_FLAGS,
+		       MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
+	efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf.reboot, MC_CMD_REBOOT_IN_LEN,
+		     NULL, 0, NULL);
+
+	/* Print out the assertion */
+	reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
+		? "system-level assertion"
+		: (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
+		? "thread-level assertion"
+		: (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
+		? "watchdog reset"
+		: "unknown assertion";
+	EFX_ERR(efx, "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason,
+		MCDI_DWORD(assertion, GET_ASSERTS_OUT_SAVED_PC_OFFS),
+		MCDI_DWORD(assertion, GET_ASSERTS_OUT_THREAD_OFFS));
+
+	/* Print out the registers */
+	ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
+	for (index = 1; index < 32; index++) {
+		EFX_ERR(efx, "R%.2d (?): 0x%.8x\n", index,
+			MCDI_DWORD2(assertion, ofst));
+		ofst += sizeof(efx_dword_t);
+	}
+
+	return 0;
+}
+
+void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+	u8 inbuf[MC_CMD_SET_ID_LED_IN_LEN];
+	int rc;
+
+	BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF);
+	BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON);
+	BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT);
+
+	BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0);
+
+	MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+}
+
+int efx_mcdi_reset_port(struct efx_nic *efx)
+{
+	int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL);
+	if (rc)
+		EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_reset_mc(struct efx_nic *efx)
+{
+	u8 inbuf[MC_CMD_REBOOT_IN_LEN];
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0);
+	MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0);
+	rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	/* White is black, and up is down */
+	if (rc == -EIO)
+		return 0;
+	if (rc == 0)
+		rc = -EIO;
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
+			    const u8 *mac, int *id_out)
+{
+	u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN];
+	u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_WOL_TYPE, type);
+	MCDI_SET_DWORD(inbuf, WOL_FILTER_SET_IN_FILTER_MODE,
+		       MC_CMD_FILTER_MODE_SIMPLE);
+	memcpy(MCDI_PTR(inbuf, WOL_FILTER_SET_IN_MAGIC_MAC), mac, ETH_ALEN);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_SET, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	if (outlen < MC_CMD_WOL_FILTER_SET_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	*id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_SET_OUT_FILTER_ID);
+
+	return 0;
+
+fail:
+	*id_out = -1;
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+
+}
+
+
+int
+efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,  const u8 *mac, int *id_out)
+{
+	return efx_mcdi_wol_filter_set(efx, MC_CMD_WOL_TYPE_MAGIC, mac, id_out);
+}
+
+
+int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out)
+{
+	u8 outbuf[MC_CMD_WOL_FILTER_GET_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_GET, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	if (outlen < MC_CMD_WOL_FILTER_GET_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	*id_out = (int)MCDI_DWORD(outbuf, WOL_FILTER_GET_OUT_FILTER_ID);
+
+	return 0;
+
+fail:
+	*id_out = -1;
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+
+int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
+{
+	u8 inbuf[MC_CMD_WOL_FILTER_REMOVE_IN_LEN];
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+
+int efx_mcdi_wol_filter_reset(struct efx_nic *efx)
+{
+	int rc;
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
--- linux-ec2-2.6.32.orig/drivers/net/sfc/phy.h
+++ linux-ec2-2.6.32/drivers/net/sfc/phy.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2008 Solarflare Communications Inc.
+ * Copyright 2007-2009 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
@@ -16,16 +16,16 @@
 extern struct efx_phy_operations falcon_sfx7101_phy_ops;
 extern struct efx_phy_operations falcon_sft9001_phy_ops;
 
-extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
+extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
 
 /* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed
  * to boot due to corrupt flash, or some other negative error code. */
 extern int sft9001_wait_boot(struct efx_nic *efx);
 
 /****************************************************************************
- * AMCC/Quake QT20xx PHYs
+ * AMCC/Quake QT202x PHYs
  */
-extern struct efx_phy_operations falcon_xfp_phy_ops;
+extern struct efx_phy_operations falcon_qt202x_phy_ops;
 
 /* These PHYs provide various H/W control states for LEDs */
 #define QUAKE_LED_LINK_INVAL	(0)
@@ -39,6 +39,23 @@
 #define QUAKE_LED_TXLINK	(0)
 #define QUAKE_LED_RXLINK	(8)
 
-extern void xfp_set_led(struct efx_nic *p, int led, int state);
+extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
+
+/****************************************************************************
+ * Siena managed PHYs
+ */
+extern struct efx_phy_operations efx_mcdi_phy_ops;
+
+extern int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
+			      unsigned int prtad, unsigned int devad,
+			      u16 addr, u16 *value_out, u32 *status_out);
+extern int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
+			       unsigned int prtad, unsigned int devad,
+			       u16 addr, u16 value, u32 *status_out);
+extern void efx_mcdi_phy_decode_link(struct efx_nic *efx,
+				     struct efx_link_state *link_state,
+				     u32 speed, u32 flags, u32 fcntl);
+extern int efx_mcdi_phy_reconfigure(struct efx_nic *efx);
+extern void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa);
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/net/sfc/bitfield.h
+++ linux-ec2-2.6.32/drivers/net/sfc/bitfield.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -37,6 +37,8 @@
 #define EFX_DWORD_2_WIDTH 32
 #define EFX_DWORD_3_LBN 96
 #define EFX_DWORD_3_WIDTH 32
+#define EFX_QWORD_0_LBN 0
+#define EFX_QWORD_0_WIDTH 64
 
 /* Specified attribute (e.g. LBN) of the specified field */
 #define EFX_VAL(field, attribute) field ## _ ## attribute
@@ -520,19 +522,6 @@
 #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.
  */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/efx.h
+++ linux-ec2-2.6.32/drivers/net/sfc/efx.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -18,35 +18,64 @@
 #define FALCON_A_P_DEVID	0x0703
 #define FALCON_A_S_DEVID        0x6703
 #define FALCON_B_P_DEVID        0x0710
+#define BETHPAGE_A_P_DEVID      0x0803
+#define SIENA_A_P_DEVID         0x0813
+
+/* Solarstorm controllers use BAR 0 for I/O space and BAR 2(&3) for memory */
+#define EFX_MEM_BAR 2
 
 /* TX */
-extern netdev_tx_t efx_xmit(struct efx_nic *efx,
-				  struct efx_tx_queue *tx_queue,
-				  struct sk_buff *skb);
+extern int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
+extern netdev_tx_t
+efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
+extern netdev_tx_t
+efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
+extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
 extern void efx_stop_queue(struct efx_nic *efx);
 extern void efx_wake_queue(struct efx_nic *efx);
+#define EFX_TXQ_SIZE 1024
+#define EFX_TXQ_MASK (EFX_TXQ_SIZE - 1)
 
 /* RX */
-extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
+extern void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
+extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
+extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
+extern void efx_rx_strategy(struct efx_channel *channel);
+extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
+extern void efx_rx_work(struct work_struct *data);
+extern void __efx_rx_packet(struct efx_channel *channel,
+			    struct efx_rx_buffer *rx_buf, bool checksummed);
 extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
 			  unsigned int len, bool checksummed, bool discard);
 extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
+#define EFX_RXQ_SIZE 1024
+#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)
 
 /* Channels */
 extern void efx_process_channel_now(struct efx_channel *channel);
-extern void efx_flush_queues(struct efx_nic *efx);
+#define EFX_EVQ_SIZE 4096
+#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
 
 /* Ports */
-extern void efx_stats_disable(struct efx_nic *efx);
-extern void efx_stats_enable(struct efx_nic *efx);
-extern void efx_reconfigure_port(struct efx_nic *efx);
-extern void __efx_reconfigure_port(struct efx_nic *efx);
+extern int efx_reconfigure_port(struct efx_nic *efx);
+extern int __efx_reconfigure_port(struct efx_nic *efx);
+
+/* 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 const struct ethtool_ops efx_ethtool_ops;
 
 /* Reset handling */
-extern void efx_reset_down(struct efx_nic *efx, enum reset_type method,
-			   struct ethtool_cmd *ecmd);
-extern int efx_reset_up(struct efx_nic *efx, enum reset_type method,
-			struct ethtool_cmd *ecmd, bool ok);
+extern int efx_reset(struct efx_nic *efx, enum reset_type method);
+extern void efx_reset_down(struct efx_nic *efx, enum reset_type method);
+extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
 
 /* Global */
 extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
@@ -60,7 +89,9 @@
 /* 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, bool blink);
+extern void
+efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
+extern bool efx_port_dummy_op_poll(struct efx_nic *efx);
 
 /* MTD */
 #ifdef CONFIG_SFC_MTD
@@ -84,4 +115,8 @@
 	napi_schedule(&channel->napi_str);
 }
 
+extern void efx_link_status_changed(struct efx_nic *efx);
+extern void efx_link_set_advertising(struct efx_nic *efx, u32);
+extern void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type);
+
 #endif /* EFX_EFX_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/falcon_gmac.c
+++ linux-ec2-2.6.32/drivers/net/sfc/falcon_gmac.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -11,11 +11,10 @@
 #include <linux/delay.h>
 #include "net_driver.h"
 #include "efx.h"
-#include "falcon.h"
+#include "nic.h"
 #include "mac.h"
-#include "falcon_hwdefs.h"
-#include "falcon_io.h"
-#include "gmii.h"
+#include "regs.h"
+#include "io.h"
 
 /**************************************************************************
  *
@@ -23,106 +22,109 @@
  *
  *************************************************************************/
 
-static void falcon_reconfigure_gmac(struct efx_nic *efx)
+static int falcon_reconfigure_gmac(struct efx_nic *efx)
 {
+	struct efx_link_state *link_state = &efx->link_state;
 	bool loopback, tx_fc, rx_fc, bytemode;
 	int if_mode;
 	unsigned int max_frame_len;
 	efx_oword_t reg;
 
 	/* Configuration register 1 */
-	tx_fc = (efx->link_fc & EFX_FC_TX) || !efx->link_fd;
-	rx_fc = !!(efx->link_fc & EFX_FC_RX);
+	tx_fc = (link_state->fc & EFX_FC_TX) || !link_state->fd;
+	rx_fc = !!(link_state->fc & EFX_FC_RX);
 	loopback = (efx->loopback_mode == LOOPBACK_GMAC);
-	bytemode = (efx->link_speed == 1000);
+	bytemode = (link_state->speed == 1000);
 
 	EFX_POPULATE_OWORD_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);
-	falcon_write(efx, &reg, GM_CFG1_REG);
+			     FRF_AB_GM_LOOP, loopback,
+			     FRF_AB_GM_TX_EN, 1,
+			     FRF_AB_GM_TX_FC_EN, tx_fc,
+			     FRF_AB_GM_RX_EN, 1,
+			     FRF_AB_GM_RX_FC_EN, rx_fc);
+	efx_writeo(efx, &reg, FR_AB_GM_CFG1);
 	udelay(10);
 
 	/* Configuration register 2 */
 	if_mode = (bytemode) ? 2 : 1;
 	EFX_POPULATE_OWORD_5(reg,
-			     GM_IF_MODE, if_mode,
-			     GM_PAD_CRC_EN, 1,
-			     GM_LEN_CHK, 1,
-			     GM_FD, efx->link_fd,
-			     GM_PAMBL_LEN, 0x7/*datasheet recommended */);
+			     FRF_AB_GM_IF_MODE, if_mode,
+			     FRF_AB_GM_PAD_CRC_EN, 1,
+			     FRF_AB_GM_LEN_CHK, 1,
+			     FRF_AB_GM_FD, link_state->fd,
+			     FRF_AB_GM_PAMBL_LEN, 0x7/*datasheet recommended */);
 
-	falcon_write(efx, &reg, GM_CFG2_REG);
+	efx_writeo(efx, &reg, FR_AB_GM_CFG2);
 	udelay(10);
 
 	/* Max frame len register */
 	max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
-	EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len);
-	falcon_write(efx, &reg, GM_MAX_FLEN_REG);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_MAX_FLEN, max_frame_len);
+	efx_writeo(efx, &reg, FR_AB_GM_MAX_FLEN);
 	udelay(10);
 
 	/* FIFO configuration register 0 */
 	EFX_POPULATE_OWORD_5(reg,
-			     GMF_FTFENREQ, 1,
-			     GMF_STFENREQ, 1,
-			     GMF_FRFENREQ, 1,
-			     GMF_SRFENREQ, 1,
-			     GMF_WTMENREQ, 1);
-	falcon_write(efx, &reg, GMF_CFG0_REG);
+			     FRF_AB_GMF_FTFENREQ, 1,
+			     FRF_AB_GMF_STFENREQ, 1,
+			     FRF_AB_GMF_FRFENREQ, 1,
+			     FRF_AB_GMF_SRFENREQ, 1,
+			     FRF_AB_GMF_WTMENREQ, 1);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG0);
 	udelay(10);
 
 	/* FIFO configuration register 1 */
 	EFX_POPULATE_OWORD_2(reg,
-			     GMF_CFGFRTH, 0x12,
-			     GMF_CFGXOFFRTX, 0xffff);
-	falcon_write(efx, &reg, GMF_CFG1_REG);
+			     FRF_AB_GMF_CFGFRTH, 0x12,
+			     FRF_AB_GMF_CFGXOFFRTX, 0xffff);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG1);
 	udelay(10);
 
 	/* FIFO configuration register 2 */
 	EFX_POPULATE_OWORD_2(reg,
-			     GMF_CFGHWM, 0x3f,
-			     GMF_CFGLWM, 0xa);
-	falcon_write(efx, &reg, GMF_CFG2_REG);
+			     FRF_AB_GMF_CFGHWM, 0x3f,
+			     FRF_AB_GMF_CFGLWM, 0xa);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG2);
 	udelay(10);
 
 	/* FIFO configuration register 3 */
 	EFX_POPULATE_OWORD_2(reg,
-			     GMF_CFGHWMFT, 0x1c,
-			     GMF_CFGFTTH, 0x08);
-	falcon_write(efx, &reg, GMF_CFG3_REG);
+			     FRF_AB_GMF_CFGHWMFT, 0x1c,
+			     FRF_AB_GMF_CFGFTTH, 0x08);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG3);
 	udelay(10);
 
 	/* FIFO configuration register 4 */
-	EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1);
-	falcon_write(efx, &reg, GMF_CFG4_REG);
+	EFX_POPULATE_OWORD_1(reg, FRF_AB_GMF_HSTFLTRFRM_PAUSE, 1);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG4);
 	udelay(10);
 
 	/* FIFO configuration register 5 */
-	falcon_read(efx, &reg, GMF_CFG5_REG);
-	EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode);
-	EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd);
-	EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd);
-	EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0);
-	falcon_write(efx, &reg, GMF_CFG5_REG);
+	efx_reado(efx, &reg, FR_AB_GMF_CFG5);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGBYTMODE, bytemode);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGHDPLX, !link_state->fd);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTDRPLT64, !link_state->fd);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTFLTRFRMDC_PAUSE, 0);
+	efx_writeo(efx, &reg, FR_AB_GMF_CFG5);
 	udelay(10);
 
 	/* MAC address */
 	EFX_POPULATE_OWORD_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]);
-	falcon_write(efx, &reg, GM_ADR1_REG);
+			     FRF_AB_GM_ADR_B0, efx->net_dev->dev_addr[5],
+			     FRF_AB_GM_ADR_B1, efx->net_dev->dev_addr[4],
+			     FRF_AB_GM_ADR_B2, efx->net_dev->dev_addr[3],
+			     FRF_AB_GM_ADR_B3, efx->net_dev->dev_addr[2]);
+	efx_writeo(efx, &reg, FR_AB_GM_ADR1);
 	udelay(10);
 	EFX_POPULATE_OWORD_2(reg,
-			     GM_HWADDR_1, efx->net_dev->dev_addr[1],
-			     GM_HWADDR_0, efx->net_dev->dev_addr[0]);
-	falcon_write(efx, &reg, GM_ADR2_REG);
+			     FRF_AB_GM_ADR_B4, efx->net_dev->dev_addr[1],
+			     FRF_AB_GM_ADR_B5, efx->net_dev->dev_addr[0]);
+	efx_writeo(efx, &reg, FR_AB_GM_ADR2);
 	udelay(10);
 
 	falcon_reconfigure_mac_wrapper(efx);
+
+	return 0;
 }
 
 static void falcon_update_stats_gmac(struct efx_nic *efx)
@@ -130,11 +132,6 @@
 	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;
@@ -221,9 +218,13 @@
 	mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
 }
 
+static bool falcon_gmac_check_fault(struct efx_nic *efx)
+{
+	return false;
+}
+
 struct efx_mac_operations falcon_gmac_operations = {
 	.reconfigure	= falcon_reconfigure_gmac,
 	.update_stats	= falcon_update_stats_gmac,
-	.irq		= efx_port_dummy_op_void,
-	.poll		= efx_port_dummy_op_void,
+	.check_fault 	= falcon_gmac_check_fault,
 };
--- linux-ec2-2.6.32.orig/drivers/net/sfc/selftest.c
+++ linux-ec2-2.6.32/drivers/net/sfc/selftest.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -20,14 +20,12 @@
 #include <linux/rtnetlink.h>
 #include <asm/io.h>
 #include "net_driver.h"
-#include "ethtool.h"
 #include "efx.h"
-#include "falcon.h"
+#include "nic.h"
 #include "selftest.h"
-#include "boards.h"
 #include "workarounds.h"
 #include "spi.h"
-#include "falcon_io.h"
+#include "io.h"
 #include "mdio_10g.h"
 
 /*
@@ -49,7 +47,7 @@
 	0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b,
 };
 
-static const char *payload_msg =
+static const char payload_msg[] =
 	"Hello world! This is an Efx loopback test in progress!";
 
 /**
@@ -57,6 +55,7 @@
  * @flush:		Drop all packets in efx_loopback_rx_packet
  * @packet_count:	Number of packets being used in this test
  * @skbs:		An array of skbs transmitted
+ * @offload_csum:	Checksums are being offloaded
  * @rx_good:		RX good packet count
  * @rx_bad:		RX bad packet count
  * @payload:		Payload used in tests
@@ -65,10 +64,7 @@
 	bool flush;
 	int packet_count;
 	struct sk_buff **skbs;
-
-	/* Checksums are being offloaded */
 	bool offload_csum;
-
 	atomic_t rx_good;
 	atomic_t rx_bad;
 	struct efx_loopback_payload payload;
@@ -83,10 +79,14 @@
 static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests)
 {
 	int rc = 0;
-	int devad = __ffs(efx->mdio.mmds);
+	int devad;
 	u16 physid1, physid2;
 
-	if (efx->phy_type == PHY_TYPE_NONE)
+	if (efx->mdio.mode_support & MDIO_SUPPORTS_C45)
+		devad = __ffs(efx->mdio.mmds);
+	else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22)
+		devad = MDIO_DEVAD_NONE;
+	else
 		return 0;
 
 	mutex_lock(&efx->mac_lock);
@@ -104,7 +104,7 @@
 	}
 
 	if (EFX_IS10G(efx)) {
-		rc = efx_mdio_check_mmds(efx, efx->phy_op->mmds, 0);
+		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
 		if (rc)
 			goto out;
 	}
@@ -117,23 +117,26 @@
 
 static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests)
 {
-	int rc;
+	int rc = 0;
+
+	if (efx->type->test_nvram) {
+		rc = efx->type->test_nvram(efx);
+		tests->nvram = rc ? -1 : 1;
+	}
 
-	rc = falcon_read_nvram(efx, NULL);
-	tests->nvram = rc ? -1 : 1;
 	return rc;
 }
 
 static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
 {
-	int rc;
+	int rc = 0;
 
-	/* Not supported on A-series silicon */
-	if (falcon_rev(efx) < FALCON_REV_B0)
-		return 0;
+	/* Test register access */
+	if (efx->type->test_registers) {
+		rc = efx->type->test_registers(efx);
+		tests->registers = rc ? -1 : 1;
+	}
 
-	rc = falcon_test_registers(efx);
-	tests->registers = rc ? -1 : 1;
 	return rc;
 }
 
@@ -165,7 +168,7 @@
 			goto success;
 	}
 
-	falcon_generate_interrupt(efx);
+	efx_nic_generate_interrupt(efx);
 
 	/* Wait for arrival of test interrupt. */
 	EFX_LOG(efx, "waiting for test interrupt\n");
@@ -177,8 +180,8 @@
 	return -ETIMEDOUT;
 
  success:
-	EFX_LOG(efx, "test interrupt (mode %d) seen on CPU%d\n",
-		efx->interrupt_mode, efx->last_irq_cpu);
+	EFX_LOG(efx, "%s test interrupt seen on CPU%d\n", INT_MODE(efx),
+		efx->last_irq_cpu);
 	tests->interrupt = 1;
 	return 0;
 }
@@ -203,7 +206,7 @@
 	channel->eventq_magic = 0;
 	smp_wmb();
 
-	falcon_generate_test_event(channel, magic);
+	efx_nic_generate_test_event(channel, magic);
 
 	/* Wait for arrival of interrupt */
 	count = 0;
@@ -254,9 +257,6 @@
 	if (!efx->phy_op->run_tests)
 		return 0;
 
-	EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 ||
-			    efx->phy_op->num_tests > EFX_MAX_PHY_TESTS);
-
 	mutex_lock(&efx->mac_lock);
 	rc = efx->phy_op->run_tests(efx, tests->phy, flags);
 	mutex_unlock(&efx->mac_lock);
@@ -426,7 +426,7 @@
 
 		if (efx_dev_registered(efx))
 			netif_tx_lock_bh(efx->net_dev);
-		rc = efx_xmit(efx, tx_queue, skb);
+		rc = efx_enqueue_skb(tx_queue, skb);
 		if (efx_dev_registered(efx))
 			netif_tx_unlock_bh(efx->net_dev);
 
@@ -439,7 +439,6 @@
 			kfree_skb(skb);
 			return -EPIPE;
 		}
-		efx->net_dev->trans_start = jiffies;
 	}
 
 	return 0;
@@ -527,7 +526,7 @@
 
 	for (i = 0; i < 3; i++) {
 		/* Determine how many packets to send */
-		state->packet_count = (efx->type->txd_ring_mask + 1) / 3;
+		state->packet_count = EFX_TXQ_SIZE / 3;
 		state->packet_count = min(1 << (i << 2), state->packet_count);
 		state->skbs = kzalloc(sizeof(state->skbs[0]) *
 				      state->packet_count, GFP_KERNEL);
@@ -568,14 +567,49 @@
 	return 0;
 }
 
+/* Wait for link up. On Falcon, we would prefer to rely on efx_monitor, but
+ * any contention on the mac lock (via e.g. efx_mac_mcast_work) causes it
+ * to delay and retry. Therefore, it's safer to just poll directly. Wait
+ * for link up and any faults to dissipate. */
+static int efx_wait_for_link(struct efx_nic *efx)
+{
+	struct efx_link_state *link_state = &efx->link_state;
+	int count;
+	bool link_up;
+
+	for (count = 0; count < 40; count++) {
+		schedule_timeout_uninterruptible(HZ / 10);
+
+		if (efx->type->monitor != NULL) {
+			mutex_lock(&efx->mac_lock);
+			efx->type->monitor(efx);
+			mutex_unlock(&efx->mac_lock);
+		} else {
+			struct efx_channel *channel = &efx->channel[0];
+			if (channel->work_pending)
+				efx_process_channel_now(channel);
+		}
+
+		mutex_lock(&efx->mac_lock);
+		link_up = link_state->up;
+		if (link_up)
+			link_up = !efx->mac_op->check_fault(efx);
+		mutex_unlock(&efx->mac_lock);
+
+		if (link_up)
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
 static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
 			      unsigned int loopback_modes)
 {
 	enum efx_loopback_mode mode;
 	struct efx_loopback_state *state;
 	struct efx_tx_queue *tx_queue;
-	bool link_up;
-	int count, rc = 0;
+	int rc = 0;
 
 	/* Set the port loopback_selftest member. From this point on
 	 * all received packets will be dropped. Mark the state as
@@ -594,46 +628,23 @@
 
 		/* Move the port into the specified loopback mode. */
 		state->flush = true;
+		mutex_lock(&efx->mac_lock);
 		efx->loopback_mode = mode;
-		efx_reconfigure_port(efx);
-
-		/* Wait for the PHY to signal the link is up. Interrupts
-		 * are enabled for PHY's using LASI, otherwise we poll()
-		 * quickly */
-		count = 0;
-		do {
-			struct efx_channel *channel = &efx->channel[0];
+		rc = __efx_reconfigure_port(efx);
+		mutex_unlock(&efx->mac_lock);
+		if (rc) {
+			EFX_ERR(efx, "unable to move into %s loopback\n",
+				LOOPBACK_MODE(efx));
+			goto out;
+		}
 
-			efx->phy_op->poll(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();
-
-			/* We need both the phy and xaui links to be ok.
-			 * rather than relying on the falcon_xmac irq/poll
-			 * regime, just poll xaui directly */
-			link_up = efx->link_up;
-			if (link_up && EFX_IS10G(efx) &&
-			    !falcon_xaui_link_ok(efx))
-				link_up = false;
-
-		} while ((++count < 20) && !link_up);
-
-		/* The link should now be up. If it isn't, there is no point
-		 * in attempting a loopback test */
-		if (!link_up) {
+		rc = efx_wait_for_link(efx);
+		if (rc) {
 			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) {
 			state->offload_csum = (tx_queue->queue ==
@@ -667,7 +678,6 @@
 	enum efx_loopback_mode loopback_mode = efx->loopback_mode;
 	int phy_mode = efx->phy_mode;
 	enum reset_type reset_method = RESET_TYPE_INVISIBLE;
-	struct ethtool_cmd ecmd;
 	struct efx_channel *channel;
 	int rc_test = 0, rc_reset = 0, rc;
 
@@ -720,21 +730,21 @@
 	mutex_unlock(&efx->mac_lock);
 
 	/* free up all consumers of SRAM (including all the queues) */
-	efx_reset_down(efx, reset_method, &ecmd);
+	efx_reset_down(efx, reset_method);
 
 	rc = efx_test_chip(efx, tests);
 	if (rc && !rc_test)
 		rc_test = rc;
 
 	/* reset the chip to recover from the register test */
-	rc_reset = falcon_reset_hw(efx, reset_method);
+	rc_reset = efx->type->reset(efx, reset_method);
 
 	/* Ensure that the phy is powered and out of loopback
 	 * for the bist and loopback tests */
 	efx->phy_mode &= ~PHY_MODE_LOW_POWER;
 	efx->loopback_mode = LOOPBACK_NONE;
 
-	rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0);
+	rc = efx_reset_up(efx, reset_method, rc_reset == 0);
 	if (rc && !rc_reset)
 		rc_reset = rc;
 
@@ -753,10 +763,12 @@
 		rc_test = rc;
 
 	/* restore the PHY to the previous state */
-	efx->loopback_mode = loopback_mode;
+	mutex_lock(&efx->mac_lock);
 	efx->phy_mode = phy_mode;
 	efx->port_inhibited = false;
-	efx_ethtool_set_settings(efx->net_dev, &ecmd);
+	efx->loopback_mode = loopback_mode;
+	__efx_reconfigure_port(efx);
+	mutex_unlock(&efx->mac_lock);
 
 	return rc_test;
 }
--- linux-ec2-2.6.32.orig/drivers/net/sfc/workarounds.h
+++ linux-ec2-2.6.32/drivers/net/sfc/workarounds.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -16,7 +16,9 @@
  */
 
 #define EFX_WORKAROUND_ALWAYS(efx) 1
-#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
+#define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1)
+#define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0)
+#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
 #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
 #define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
 				     (efx)->phy_type == PHY_TYPE_SFT9001B)
@@ -27,20 +29,22 @@
 #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
 /* Bit-bashed I2C reads cause performance drop */
 #define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
-/* TX pkt parser problem with <= 16 byte TXes */
-#define EFX_WORKAROUND_9141 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
 /* 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
+#define EFX_WORKAROUND_11482 EFX_WORKAROUND_FALCON_AB
 /* Truncated IPv4 packets can confuse the TX packet parser */
-#define EFX_WORKAROUND_15592 EFX_WORKAROUND_ALWAYS
+#define EFX_WORKAROUND_15592 EFX_WORKAROUND_FALCON_AB
+/* Legacy ISR read can return zero once */
+#define EFX_WORKAROUND_15783 EFX_WORKAROUND_SIENA
+/* Legacy interrupt storm when interrupt fifo fills */
+#define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA
 
 /* Spurious parity errors in TSORT buffers */
 #define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
+/* Unaligned read request >512 bytes after aligning may break TSORT */
+#define EFX_WORKAROUND_5391 EFX_WORKAROUND_FALCON_A
 /* iSCSI parsing errors */
 #define EFX_WORKAROUND_5583 EFX_WORKAROUND_FALCON_A
 /* RX events go missing */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/Kconfig
+++ linux-ec2-2.6.32/drivers/net/sfc/Kconfig
@@ -1,5 +1,5 @@
 config SFC
-	tristate "Solarflare Solarstorm SFC4000 support"
+	tristate "Solarflare Solarstorm SFC4000/SFC9000-family support"
 	depends on PCI && INET
 	select MDIO
 	select CRC32
@@ -7,15 +7,23 @@
 	select I2C_ALGOBIT
 	help
 	  This driver supports 10-gigabit Ethernet cards based on
-	  the Solarflare Communications Solarstorm SFC4000 controller.
+	  the Solarflare Communications Solarstorm SFC4000 and
+	  SFC9000-family controllers.
 
 	  To compile this driver as a module, choose M here.  The module
 	  will be called sfc.
+
+config SFC_RESOURCE
+	depends on SFC && X86
+	tristate "Solarflare Solarstorm SFC4000 resource driver"
+	help
+	  This module provides the SFC resource manager driver.
+
 config SFC_MTD
-	bool "Solarflare Solarstorm SFC4000 flash MTD support"
+	bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support"
 	depends on SFC && MTD && !(SFC=y && MTD=m)
 	default y
 	help
-	  This exposes the on-board flash memory as an MTD device (e.g.
-          /dev/mtd1).  This makes it possible to upload new boot code
-          to the NIC.
+	  This exposes the on-board flash memory as MTD devices (e.g.
+	  /dev/mtd1).  This makes it possible to upload new firmware
+	  to the NIC.
--- linux-ec2-2.6.32.orig/drivers/net/sfc/siena.c
+++ linux-ec2-2.6.32/drivers/net/sfc/siena.c
@@ -0,0 +1,614 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include "net_driver.h"
+#include "bitfield.h"
+#include "efx.h"
+#include "nic.h"
+#include "mac.h"
+#include "spi.h"
+#include "regs.h"
+#include "io.h"
+#include "phy.h"
+#include "workarounds.h"
+#include "mcdi.h"
+#include "mcdi_pcol.h"
+
+/* Hardware control for SFC9000 family including SFL9021 (aka Siena). */
+
+static void siena_init_wol(struct efx_nic *efx);
+
+
+static void siena_push_irq_moderation(struct efx_channel *channel)
+{
+	efx_dword_t timer_cmd;
+
+	if (channel->irq_moderation)
+		EFX_POPULATE_DWORD_2(timer_cmd,
+				     FRF_CZ_TC_TIMER_MODE,
+				     FFE_CZ_TIMER_MODE_INT_HLDOFF,
+				     FRF_CZ_TC_TIMER_VAL,
+				     channel->irq_moderation - 1);
+	else
+		EFX_POPULATE_DWORD_2(timer_cmd,
+				     FRF_CZ_TC_TIMER_MODE,
+				     FFE_CZ_TIMER_MODE_DIS,
+				     FRF_CZ_TC_TIMER_VAL, 0);
+	efx_writed_page_locked(channel->efx, &timer_cmd, FR_BZ_TIMER_COMMAND_P0,
+			       channel->channel);
+}
+
+static void siena_push_multicast_hash(struct efx_nic *efx)
+{
+	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+	efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH,
+		     efx->multicast_hash.byte, sizeof(efx->multicast_hash),
+		     NULL, 0, NULL);
+}
+
+static int siena_mdio_write(struct net_device *net_dev,
+			    int prtad, int devad, u16 addr, u16 value)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	uint32_t status;
+	int rc;
+
+	rc = efx_mcdi_mdio_write(efx, efx->mdio_bus, prtad, devad,
+				 addr, value, &status);
+	if (rc)
+		return rc;
+	if (status != MC_CMD_MDIO_STATUS_GOOD)
+		return -EIO;
+
+	return 0;
+}
+
+static int siena_mdio_read(struct net_device *net_dev,
+			   int prtad, int devad, u16 addr)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	uint16_t value;
+	uint32_t status;
+	int rc;
+
+	rc = efx_mcdi_mdio_read(efx, efx->mdio_bus, prtad, devad,
+				addr, &value, &status);
+	if (rc)
+		return rc;
+	if (status != MC_CMD_MDIO_STATUS_GOOD)
+		return -EIO;
+
+	return (int)value;
+}
+
+/* This call is responsible for hooking in the MAC and PHY operations */
+static int siena_probe_port(struct efx_nic *efx)
+{
+	int rc;
+
+	/* Hook in PHY operations table */
+	efx->phy_op = &efx_mcdi_phy_ops;
+
+	/* Set up MDIO structure for PHY */
+	efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+	efx->mdio.mdio_read = siena_mdio_read;
+	efx->mdio.mdio_write = siena_mdio_write;
+
+	/* Fill out MDIO structure and loopback modes */
+	rc = efx->phy_op->probe(efx);
+	if (rc != 0)
+		return rc;
+
+	/* Initial assumption */
+	efx->link_state.speed = 10000;
+	efx->link_state.fd = true;
+	efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
+
+	/* Allocate buffer for stats */
+	rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
+				  MC_CMD_MAC_NSTATS * sizeof(u64));
+	if (rc)
+		return rc;
+	EFX_LOG(efx, "stats buffer at %llx (virt %p phys %llx)\n",
+		(u64)efx->stats_buffer.dma_addr,
+		efx->stats_buffer.addr,
+		(u64)virt_to_phys(efx->stats_buffer.addr));
+
+	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1);
+
+	return 0;
+}
+
+void siena_remove_port(struct efx_nic *efx)
+{
+	efx->phy_op->remove(efx);
+	efx_nic_free_buffer(efx, &efx->stats_buffer);
+}
+
+static const struct efx_nic_register_test siena_register_tests[] = {
+	{ FR_AZ_ADR_REGION,
+	  EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) },
+	{ FR_CZ_USR_EV_CFG,
+	  EFX_OWORD32(0x000103FF, 0x00000000, 0x00000000, 0x00000000) },
+	{ FR_AZ_RX_CFG,
+	  EFX_OWORD32(0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000) },
+	{ FR_AZ_TX_CFG,
+	  EFX_OWORD32(0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF) },
+	{ FR_AZ_TX_RESERVED,
+	  EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) },
+	{ FR_AZ_SRM_TX_DC_CFG,
+	  EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) },
+	{ FR_AZ_RX_DC_CFG,
+	  EFX_OWORD32(0x00000003, 0x00000000, 0x00000000, 0x00000000) },
+	{ FR_AZ_RX_DC_PF_WM,
+	  EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
+	{ FR_BZ_DP_CTRL,
+	  EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+	{ FR_BZ_RX_RSS_TKEY,
+	  EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) },
+	{ FR_CZ_RX_RSS_IPV6_REG1,
+	  EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) },
+	{ FR_CZ_RX_RSS_IPV6_REG2,
+	  EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) },
+	{ FR_CZ_RX_RSS_IPV6_REG3,
+	  EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000) },
+};
+
+static int siena_test_registers(struct efx_nic *efx)
+{
+	return efx_nic_test_registers(efx, siena_register_tests,
+				      ARRAY_SIZE(siena_register_tests));
+}
+
+/**************************************************************************
+ *
+ * Device reset
+ *
+ **************************************************************************
+ */
+
+static int siena_reset_hw(struct efx_nic *efx, enum reset_type method)
+{
+
+	if (method == RESET_TYPE_WORLD)
+		return efx_mcdi_reset_mc(efx);
+	else
+		return efx_mcdi_reset_port(efx);
+}
+
+static int siena_probe_nvconfig(struct efx_nic *efx)
+{
+	int rc;
+
+	rc = efx_mcdi_get_board_cfg(efx, efx->mac_address, NULL);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int siena_probe_nic(struct efx_nic *efx)
+{
+	struct siena_nic_data *nic_data;
+	bool already_attached = 0;
+	int rc;
+
+	/* Allocate storage for hardware specific data */
+	nic_data = kzalloc(sizeof(struct siena_nic_data), GFP_KERNEL);
+	if (!nic_data)
+		return -ENOMEM;
+	efx->nic_data = nic_data;
+
+	if (efx_nic_fpga_ver(efx) != 0) {
+		EFX_ERR(efx, "Siena FPGA not supported\n");
+		rc = -ENODEV;
+		goto fail1;
+	}
+
+	efx_mcdi_init(efx);
+
+	/* Recover from a failed assertion before probing */
+	rc = efx_mcdi_handle_assertion(efx);
+	if (rc)
+		goto fail1;
+
+	rc = efx_mcdi_fwver(efx, &nic_data->fw_version, &nic_data->fw_build);
+	if (rc) {
+		EFX_ERR(efx, "Failed to read MCPU firmware version - "
+			"rc %d\n", rc);
+		goto fail1; /* MCPU absent? */
+	}
+
+	/* Let the BMC know that the driver is now in charge of link and
+	 * filter settings. We must do this before we reset the NIC */
+	rc = efx_mcdi_drv_attach(efx, true, &already_attached);
+	if (rc) {
+		EFX_ERR(efx, "Unable to register driver with MCPU\n");
+		goto fail2;
+	}
+	if (already_attached)
+		/* Not a fatal error */
+		EFX_ERR(efx, "Host already registered with MCPU\n");
+
+	/* Now we can reset the NIC */
+	rc = siena_reset_hw(efx, RESET_TYPE_ALL);
+	if (rc) {
+		EFX_ERR(efx, "failed to reset NIC\n");
+		goto fail3;
+	}
+
+	siena_init_wol(efx);
+
+	/* Allocate memory for INT_KER */
+	rc = efx_nic_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 %llx)\n",
+		(unsigned long long)efx->irq_status.dma_addr,
+		efx->irq_status.addr,
+		(unsigned long long)virt_to_phys(efx->irq_status.addr));
+
+	/* Read in the non-volatile configuration */
+	rc = siena_probe_nvconfig(efx);
+	if (rc == -EINVAL) {
+		EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n");
+		efx->phy_type = PHY_TYPE_NONE;
+		efx->mdio.prtad = MDIO_PRTAD_NONE;
+	} else if (rc) {
+		goto fail5;
+	}
+
+	return 0;
+
+fail5:
+	efx_nic_free_buffer(efx, &efx->irq_status);
+fail4:
+fail3:
+	efx_mcdi_drv_attach(efx, false, NULL);
+fail2:
+fail1:
+	kfree(efx->nic_data);
+	return rc;
+}
+
+/* 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.
+ */
+static int siena_init_nic(struct efx_nic *efx)
+{
+	efx_oword_t temp;
+	int rc;
+
+	/* Recover from a failed assertion post-reset */
+	rc = efx_mcdi_handle_assertion(efx);
+	if (rc)
+		return rc;
+
+	/* Squash TX of packets of 16 bytes or less */
+	efx_reado(efx, &temp, FR_AZ_TX_RESERVED);
+	EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
+	efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+
+	/* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16
+	 * descriptors (which is bad).
+	 */
+	efx_reado(efx, &temp, FR_AZ_TX_CFG);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_NO_EOP_DISC_EN, 0);
+	EFX_SET_OWORD_FIELD(temp, FRF_CZ_TX_FILTER_EN_BIT, 1);
+	efx_writeo(efx, &temp, FR_AZ_TX_CFG);
+
+	efx_reado(efx, &temp, FR_AZ_RX_CFG);
+	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_DESC_PUSH_EN, 0);
+	EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1);
+	efx_writeo(efx, &temp, FR_AZ_RX_CFG);
+
+	if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0)
+		/* No MCDI operation has been defined to set thresholds */
+		EFX_ERR(efx, "ignoring RX flow control thresholds\n");
+
+	/* Enable event logging */
+	rc = efx_mcdi_log_ctrl(efx, true, false, 0);
+	if (rc)
+		return rc;
+
+	/* Set destination of both TX and RX Flush events */
+	EFX_POPULATE_OWORD_1(temp, FRF_BZ_FLS_EVQ_ID, 0);
+	efx_writeo(efx, &temp, FR_BZ_DP_CTRL);
+
+	EFX_POPULATE_OWORD_1(temp, FRF_CZ_USREV_DIS, 1);
+	efx_writeo(efx, &temp, FR_CZ_USR_EV_CFG);
+
+	efx_nic_init_common(efx);
+	return 0;
+}
+
+static void siena_remove_nic(struct efx_nic *efx)
+{
+	efx_nic_free_buffer(efx, &efx->irq_status);
+
+	siena_reset_hw(efx, RESET_TYPE_ALL);
+
+	/* Relinquish the device back to the BMC */
+	if (efx_nic_has_mc(efx))
+		efx_mcdi_drv_attach(efx, false, NULL);
+
+	/* Tear down the private nic state */
+	kfree(efx->nic_data);
+	efx->nic_data = NULL;
+}
+
+#define STATS_GENERATION_INVALID ((u64)(-1))
+
+static int siena_try_update_nic_stats(struct efx_nic *efx)
+{
+	u64 *dma_stats;
+	struct efx_mac_stats *mac_stats;
+	u64 generation_start;
+	u64 generation_end;
+
+	mac_stats = &efx->mac_stats;
+	dma_stats = (u64 *)efx->stats_buffer.addr;
+
+	generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
+	if (generation_end == STATS_GENERATION_INVALID)
+		return 0;
+	rmb();
+
+#define MAC_STAT(M, D) \
+	mac_stats->M = dma_stats[MC_CMD_MAC_ ## D]
+
+	MAC_STAT(tx_bytes, TX_BYTES);
+	MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
+	mac_stats->tx_good_bytes = (mac_stats->tx_bytes -
+				    mac_stats->tx_bad_bytes);
+	MAC_STAT(tx_packets, TX_PKTS);
+	MAC_STAT(tx_bad, TX_BAD_FCS_PKTS);
+	MAC_STAT(tx_pause, TX_PAUSE_PKTS);
+	MAC_STAT(tx_control, TX_CONTROL_PKTS);
+	MAC_STAT(tx_unicast, TX_UNICAST_PKTS);
+	MAC_STAT(tx_multicast, TX_MULTICAST_PKTS);
+	MAC_STAT(tx_broadcast, TX_BROADCAST_PKTS);
+	MAC_STAT(tx_lt64, TX_LT64_PKTS);
+	MAC_STAT(tx_64, TX_64_PKTS);
+	MAC_STAT(tx_65_to_127, TX_65_TO_127_PKTS);
+	MAC_STAT(tx_128_to_255, TX_128_TO_255_PKTS);
+	MAC_STAT(tx_256_to_511, TX_256_TO_511_PKTS);
+	MAC_STAT(tx_512_to_1023, TX_512_TO_1023_PKTS);
+	MAC_STAT(tx_1024_to_15xx, TX_1024_TO_15XX_PKTS);
+	MAC_STAT(tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS);
+	MAC_STAT(tx_gtjumbo, TX_GTJUMBO_PKTS);
+	mac_stats->tx_collision = 0;
+	MAC_STAT(tx_single_collision, TX_SINGLE_COLLISION_PKTS);
+	MAC_STAT(tx_multiple_collision, TX_MULTIPLE_COLLISION_PKTS);
+	MAC_STAT(tx_excessive_collision, TX_EXCESSIVE_COLLISION_PKTS);
+	MAC_STAT(tx_deferred, TX_DEFERRED_PKTS);
+	MAC_STAT(tx_late_collision, TX_LATE_COLLISION_PKTS);
+	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_STAT(tx_excessive_deferred, TX_EXCESSIVE_DEFERRED_PKTS);
+	MAC_STAT(tx_non_tcpudp, TX_NON_TCPUDP_PKTS);
+	MAC_STAT(tx_mac_src_error, TX_MAC_SRC_ERR_PKTS);
+	MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS);
+	MAC_STAT(rx_bytes, RX_BYTES);
+	MAC_STAT(rx_bad_bytes, RX_BAD_BYTES);
+	mac_stats->rx_good_bytes = (mac_stats->rx_bytes -
+				    mac_stats->rx_bad_bytes);
+	MAC_STAT(rx_packets, RX_PKTS);
+	MAC_STAT(rx_good, RX_GOOD_PKTS);
+	mac_stats->rx_bad = mac_stats->rx_packets - mac_stats->rx_good;
+	MAC_STAT(rx_pause, RX_PAUSE_PKTS);
+	MAC_STAT(rx_control, RX_CONTROL_PKTS);
+	MAC_STAT(rx_unicast, RX_UNICAST_PKTS);
+	MAC_STAT(rx_multicast, RX_MULTICAST_PKTS);
+	MAC_STAT(rx_broadcast, RX_BROADCAST_PKTS);
+	MAC_STAT(rx_lt64, RX_UNDERSIZE_PKTS);
+	MAC_STAT(rx_64, RX_64_PKTS);
+	MAC_STAT(rx_65_to_127, RX_65_TO_127_PKTS);
+	MAC_STAT(rx_128_to_255, RX_128_TO_255_PKTS);
+	MAC_STAT(rx_256_to_511, RX_256_TO_511_PKTS);
+	MAC_STAT(rx_512_to_1023, RX_512_TO_1023_PKTS);
+	MAC_STAT(rx_1024_to_15xx, RX_1024_TO_15XX_PKTS);
+	MAC_STAT(rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS);
+	MAC_STAT(rx_gtjumbo, RX_GTJUMBO_PKTS);
+	mac_stats->rx_bad_lt64 = 0;
+	mac_stats->rx_bad_64_to_15xx = 0;
+	mac_stats->rx_bad_15xx_to_jumbo = 0;
+	MAC_STAT(rx_bad_gtjumbo, RX_JABBER_PKTS);
+	MAC_STAT(rx_overflow, RX_OVERFLOW_PKTS);
+	mac_stats->rx_missed = 0;
+	MAC_STAT(rx_false_carrier, RX_FALSE_CARRIER_PKTS);
+	MAC_STAT(rx_symbol_error, RX_SYMBOL_ERROR_PKTS);
+	MAC_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS);
+	MAC_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS);
+	MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS);
+	mac_stats->rx_good_lt64 = 0;
+
+	efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS];
+
+#undef MAC_STAT
+
+	rmb();
+	generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
+	if (generation_end != generation_start)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static void siena_update_nic_stats(struct efx_nic *efx)
+{
+	int retry;
+
+	/* If we're unlucky enough to read statistics wduring the DMA, wait
+	 * up to 10ms for it to finish (typically takes <500us) */
+	for (retry = 0; retry < 100; ++retry) {
+		if (siena_try_update_nic_stats(efx) == 0)
+			return;
+		udelay(100);
+	}
+
+	/* Use the old values instead */
+}
+
+static void siena_start_nic_stats(struct efx_nic *efx)
+{
+	u64 *dma_stats = (u64 *)efx->stats_buffer.addr;
+
+	dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID;
+
+	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr,
+			   MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0);
+}
+
+static void siena_stop_nic_stats(struct efx_nic *efx)
+{
+	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
+}
+
+void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+	snprintf(buf, len, "%u.%u.%u.%u",
+		 (unsigned int)(nic_data->fw_version >> 48),
+		 (unsigned int)(nic_data->fw_version >> 32 & 0xffff),
+		 (unsigned int)(nic_data->fw_version >> 16 & 0xffff),
+		 (unsigned int)(nic_data->fw_version & 0xffff));
+}
+
+/**************************************************************************
+ *
+ * Wake on LAN
+ *
+ **************************************************************************
+ */
+
+static void siena_get_wol(struct efx_nic *efx, struct ethtool_wolinfo *wol)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+
+	wol->supported = WAKE_MAGIC;
+	if (nic_data->wol_filter_id != -1)
+		wol->wolopts = WAKE_MAGIC;
+	else
+		wol->wolopts = 0;
+	memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+
+static int siena_set_wol(struct efx_nic *efx, u32 type)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+	int rc;
+
+	if (type & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	if (type & WAKE_MAGIC) {
+		if (nic_data->wol_filter_id != -1)
+			efx_mcdi_wol_filter_remove(efx,
+						   nic_data->wol_filter_id);
+		rc = efx_mcdi_wol_filter_set_magic(efx, efx->mac_address,
+						   &nic_data->wol_filter_id);
+		if (rc)
+			goto fail;
+
+		pci_wake_from_d3(efx->pci_dev, true);
+	} else {
+		rc = efx_mcdi_wol_filter_reset(efx);
+		nic_data->wol_filter_id = -1;
+		pci_wake_from_d3(efx->pci_dev, false);
+		if (rc)
+			goto fail;
+	}
+
+	return 0;
+ fail:
+	EFX_ERR(efx, "%s failed: type=%d rc=%d\n", __func__, type, rc);
+	return rc;
+}
+
+
+static void siena_init_wol(struct efx_nic *efx)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+	int rc;
+
+	rc = efx_mcdi_wol_filter_get_magic(efx, &nic_data->wol_filter_id);
+
+	if (rc != 0) {
+		/* If it failed, attempt to get into a synchronised
+		 * state with MC by resetting any set WoL filters */
+		efx_mcdi_wol_filter_reset(efx);
+		nic_data->wol_filter_id = -1;
+	} else if (nic_data->wol_filter_id != -1) {
+		pci_wake_from_d3(efx->pci_dev, true);
+	}
+}
+
+
+/**************************************************************************
+ *
+ * Revision-dependent attributes used by efx.c and nic.c
+ *
+ **************************************************************************
+ */
+
+struct efx_nic_type siena_a0_nic_type = {
+	.probe = siena_probe_nic,
+	.remove = siena_remove_nic,
+	.init = siena_init_nic,
+	.fini = efx_port_dummy_op_void,
+	.monitor = NULL,
+	.reset = siena_reset_hw,
+	.probe_port = siena_probe_port,
+	.remove_port = siena_remove_port,
+	.prepare_flush = efx_port_dummy_op_void,
+	.update_stats = siena_update_nic_stats,
+	.start_stats = siena_start_nic_stats,
+	.stop_stats = siena_stop_nic_stats,
+	.set_id_led = efx_mcdi_set_id_led,
+	.push_irq_moderation = siena_push_irq_moderation,
+	.push_multicast_hash = siena_push_multicast_hash,
+	.reconfigure_port = efx_mcdi_phy_reconfigure,
+	.get_wol = siena_get_wol,
+	.set_wol = siena_set_wol,
+	.resume_wol = siena_init_wol,
+	.test_registers = siena_test_registers,
+	.default_mac_ops = &efx_mcdi_mac_operations,
+
+	.revision = EFX_REV_SIENA_A0,
+	.mem_map_size = (FR_CZ_MC_TREG_SMEM +
+			 FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS),
+	.txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
+	.rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
+	.buf_tbl_base = FR_BZ_BUF_FULL_TBL,
+	.evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL,
+	.evq_rptr_tbl_base = FR_BZ_EVQ_RPTR,
+	.max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH),
+	.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 */
+	.tx_dc_base = 0x88000,
+	.rx_dc_base = 0x68000,
+	.offload_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM,
+	.reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT,
+};
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mcdi_pcol.h
+++ linux-ec2-2.6.32/drivers/net/sfc/mcdi_pcol.h
@@ -0,0 +1,1580 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2009 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, incorporated herein by reference.
+ */
+
+
+#ifndef MCDI_PCOL_H
+#define MCDI_PCOL_H
+
+/* Values to be written into FMCR_CZ_RESET_STATE_REG to control boot. */
+/* Power-on reset state */
+#define MC_FW_STATE_POR (1)
+/* If this is set in MC_RESET_STATE_REG then it should be
+ * possible to jump into IMEM without loading code from flash. */
+#define MC_FW_WARM_BOOT_OK (2)
+/* The MC main image has started to boot. */
+#define MC_FW_STATE_BOOTING (4)
+/* The Scheduler has started. */
+#define MC_FW_STATE_SCHED (8)
+
+/* Values to be written to the per-port status dword in shared
+ * memory on reboot and assert */
+#define MC_STATUS_DWORD_REBOOT (0xb007b007)
+#define MC_STATUS_DWORD_ASSERT (0xdeaddead)
+
+/* The current version of the MCDI protocol.
+ *
+ * Note that the ROM burnt into the card only talks V0, so at the very
+ * least every driver must support version 0 and MCDI_PCOL_VERSION
+ */
+#define MCDI_PCOL_VERSION 1
+
+/**
+ * MCDI version 1
+ *
+ * Each MCDI request starts with an MCDI_HEADER, which is a 32byte
+ * structure, filled in by the client.
+ *
+ *       0       7  8     16    20     22  23  24    31
+ *      | CODE | R | LEN | SEQ | Rsvd | E | R | XFLAGS |
+ *               |                      |   |
+ *               |                      |   \--- Response
+ *               |                      \------- Error
+ *               \------------------------------ Resync (always set)
+ *
+ * The client writes it's request into MC shared memory, and rings the
+ * doorbell. Each request is completed by either by the MC writting
+ * back into shared memory, or by writting out an event.
+ *
+ * All MCDI commands support completion by shared memory response. Each
+ * request may also contain additional data (accounted for by HEADER.LEN),
+ * and some response's may also contain additional data (again, accounted
+ * for by HEADER.LEN).
+ *
+ * Some MCDI commands support completion by event, in which any associated
+ * response data is included in the event.
+ *
+ * The protocol requires one response to be delivered for every request, a
+ * request should not be sent unless the response for the previous request
+ * has been received (either by polling shared memory, or by receiving
+ * an event).
+ */
+
+/** Request/Response structure */
+#define MCDI_HEADER_OFST 0
+#define MCDI_HEADER_CODE_LBN 0
+#define MCDI_HEADER_CODE_WIDTH 7
+#define MCDI_HEADER_RESYNC_LBN 7
+#define MCDI_HEADER_RESYNC_WIDTH 1
+#define MCDI_HEADER_DATALEN_LBN 8
+#define MCDI_HEADER_DATALEN_WIDTH 8
+#define MCDI_HEADER_SEQ_LBN 16
+#define MCDI_HEADER_RSVD_LBN 20
+#define MCDI_HEADER_RSVD_WIDTH 2
+#define MCDI_HEADER_SEQ_WIDTH 4
+#define MCDI_HEADER_ERROR_LBN 22
+#define MCDI_HEADER_ERROR_WIDTH 1
+#define MCDI_HEADER_RESPONSE_LBN 23
+#define MCDI_HEADER_RESPONSE_WIDTH 1
+#define MCDI_HEADER_XFLAGS_LBN 24
+#define MCDI_HEADER_XFLAGS_WIDTH 8
+/* Request response using event */
+#define MCDI_HEADER_XFLAGS_EVREQ 0x01
+
+/* Maximum number of payload bytes */
+#define MCDI_CTL_SDU_LEN_MAX 0xfc
+
+/* The MC can generate events for two reasons:
+ *   - To complete a shared memory request if XFLAGS_EVREQ was set
+ *   - As a notification (link state, i2c event), controlled
+ *     via MC_CMD_LOG_CTRL
+ *
+ * Both events share a common structure:
+ *
+ *  0      32     33      36    44     52     60
+ * | Data | Cont | Level | Src | Code | Rsvd |
+ *           |
+ *           \ There is another event pending in this notification
+ *
+ * If Code==CMDDONE, then the fields are further interpreted as:
+ *
+ *   - LEVEL==INFO    Command succeded
+ *   - LEVEL==ERR     Command failed
+ *
+ *    0     8         16      24     32
+ *   | Seq | Datalen | Errno | Rsvd |
+ *
+ *   These fields are taken directly out of the standard MCDI header, i.e.,
+ *   LEVEL==ERR, Datalen == 0 => Reboot
+ *
+ * Events can be squirted out of the UART (using LOG_CTRL) without a
+ * MCDI header.  An event can be distinguished from a MCDI response by
+ * examining the first byte which is 0xc0.  This corresponds to the
+ * non-existent MCDI command MC_CMD_DEBUG_LOG.
+ *
+ *      0         7        8
+ *     | command | Resync |     = 0xc0
+ *
+ * Since the event is written in big-endian byte order, this works
+ * providing bits 56-63 of the event are 0xc0.
+ *
+ *      56     60  63
+ *     | Rsvd | Code |    = 0xc0
+ *
+ * Which means for convenience the event code is 0xc for all MC
+ * generated events.
+ */
+#define FSE_AZ_EV_CODE_MCDI_EVRESPONSE 0xc
+
+#define MCDI_EVENT_DATA_LBN 0
+#define MCDI_EVENT_DATA_WIDTH 32
+#define MCDI_EVENT_CONT_LBN 32
+#define MCDI_EVENT_CONT_WIDTH 1
+#define MCDI_EVENT_LEVEL_LBN 33
+#define MCDI_EVENT_LEVEL_WIDTH 3
+#define MCDI_EVENT_LEVEL_INFO (0)
+#define MCDI_EVENT_LEVEL_WARN (1)
+#define MCDI_EVENT_LEVEL_ERR (2)
+#define MCDI_EVENT_LEVEL_FATAL (3)
+#define MCDI_EVENT_SRC_LBN 36
+#define MCDI_EVENT_SRC_WIDTH 8
+#define MCDI_EVENT_CODE_LBN 44
+#define MCDI_EVENT_CODE_WIDTH 8
+#define MCDI_EVENT_CODE_BADSSERT (1)
+#define MCDI_EVENT_CODE_PMNOTICE (2)
+#define MCDI_EVENT_CODE_CMDDONE (3)
+#define  MCDI_EVENT_CMDDONE_SEQ_LBN 0
+#define  MCDI_EVENT_CMDDONE_SEQ_WIDTH 8
+#define  MCDI_EVENT_CMDDONE_DATALEN_LBN 8
+#define  MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8
+#define  MCDI_EVENT_CMDDONE_ERRNO_LBN 16
+#define  MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8
+#define MCDI_EVENT_CODE_LINKCHANGE (4)
+#define  MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0
+#define  MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16
+#define  MCDI_EVENT_LINKCHANGE_SPEED_LBN 16
+#define  MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4
+#define  MCDI_EVENT_LINKCHANGE_SPEED_100M 1
+#define  MCDI_EVENT_LINKCHANGE_SPEED_1G 2
+#define  MCDI_EVENT_LINKCHANGE_SPEED_10G 3
+#define  MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20
+#define  MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4
+#define  MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24
+#define  MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8
+#define MCDI_EVENT_CODE_SENSOREVT (5)
+#define  MCDI_EVENT_SENSOREVT_MONITOR_LBN 0
+#define  MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8
+#define  MCDI_EVENT_SENSOREVT_STATE_LBN 8
+#define  MCDI_EVENT_SENSOREVT_STATE_WIDTH 8
+#define  MCDI_EVENT_SENSOREVT_VALUE_LBN 16
+#define  MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16
+#define MCDI_EVENT_CODE_SCHEDERR (6)
+#define MCDI_EVENT_CODE_REBOOT (7)
+#define MCDI_EVENT_CODE_MAC_STATS_DMA (8)
+#define  MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0
+#define  MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32
+
+/* Non-existent command target */
+#define MC_CMD_ERR_ENOENT 2
+/* assert() has killed the MC */
+#define MC_CMD_ERR_EINTR 4
+/* Caller does not hold required locks */
+#define MC_CMD_ERR_EACCES 13
+/* Resource is currently unavailable (e.g. lock contention) */
+#define MC_CMD_ERR_EBUSY 16
+/* Invalid argument to target */
+#define MC_CMD_ERR_EINVAL 22
+/* Non-recursive resource is already acquired */
+#define MC_CMD_ERR_EDEADLK 35
+/* Operation not implemented */
+#define MC_CMD_ERR_ENOSYS 38
+/* Operation timed out */
+#define MC_CMD_ERR_ETIME 62
+
+#define MC_CMD_ERR_CODE_OFST 0
+
+
+/* MC_CMD_READ32: (debug, variadic out)
+ * Read multiple 32byte words from MC memory
+ */
+#define MC_CMD_READ32 0x01
+#define MC_CMD_READ32_IN_LEN 8
+#define MC_CMD_READ32_IN_ADDR_OFST 0
+#define MC_CMD_READ32_IN_NUMWORDS_OFST 4
+#define MC_CMD_READ32_OUT_LEN(_numwords) \
+	(4 * (_numwords))
+#define MC_CMD_READ32_OUT_BUFFER_OFST 0
+
+/* MC_CMD_WRITE32: (debug, variadic in)
+ * Write multiple 32byte words to MC memory
+ */
+#define MC_CMD_WRITE32 0x02
+#define MC_CMD_WRITE32_IN_LEN(_numwords) (((_numwords) * 4) + 4)
+#define MC_CMD_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_WRITE32_IN_BUFFER_OFST 4
+#define MC_CMD_WRITE32_OUT_LEN 0
+
+/* MC_CMD_COPYCODE: (debug)
+ * Copy MC code between two locations and jump
+ */
+#define MC_CMD_COPYCODE 0x03
+#define MC_CMD_COPYCODE_IN_LEN 16
+#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0
+#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4
+#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8
+#define MC_CMD_COPYCODE_IN_JUMP_OFST 12
+/* Control should return to the caller rather than jumping */
+#define MC_CMD_COPYCODE_JUMP_NONE 1
+#define MC_CMD_COPYCODE_OUT_LEN 0
+
+/* MC_CMD_SET_FUNC: (debug)
+ * Select function for function-specific commands.
+ */
+#define MC_CMD_SET_FUNC 0x04
+#define MC_CMD_SET_FUNC_IN_LEN 4
+#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0
+#define MC_CMD_SET_FUNC_OUT_LEN 0
+
+/* MC_CMD_GET_BOOT_STATUS:
+ * Get the instruction address from which the MC booted.
+ */
+#define MC_CMD_GET_BOOT_STATUS 0x05
+#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0
+#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8
+#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0
+#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4
+/* Reboot caused by watchdog */
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_LBN   (0)
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_WIDTH (1)
+/* MC booted from primary flash partition */
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_LBN    (1)
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_WIDTH  (1)
+/* MC booted from backup flash partition */
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_LBN     (2)
+#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_WIDTH   (1)
+
+/* MC_CMD_GET_ASSERTS: (debug, variadic out)
+ * Get (and optionally clear) the current assertion status.
+ *
+ * Only OUT.GLOBAL_FLAGS is guaranteed to exist in the completion
+ * payload. The other fields will only be present if
+ * OUT.GLOBAL_FLAGS != NO_FAILS
+ */
+#define MC_CMD_GET_ASSERTS 0x06
+#define MC_CMD_GET_ASSERTS_IN_LEN 4
+#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0
+#define MC_CMD_GET_ASSERTS_OUT_LEN 140
+/* Assertion status flag */
+#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0
+/*! No assertions have failed. */
+#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 1
+/*! A system-level assertion has failed. */
+#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 2
+/*! A thread-level assertion has failed. */
+#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 3
+/*! The system was reset by the watchdog. */
+#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 4
+/* Failing PC value */
+#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4
+/* Saved GP regs */
+#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8
+#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_LEN 124
+/* Failing thread address */
+#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132
+
+/* MC_CMD_LOG_CTRL:
+ * Determine the output stream for various events and messages
+ */
+#define MC_CMD_LOG_CTRL 0x07
+#define MC_CMD_LOG_CTRL_IN_LEN 8
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART (1)
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ (2)
+#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4
+#define MC_CMD_LOG_CTRL_OUT_LEN 0
+
+/* MC_CMD_GET_VERSION:
+ * Get version information about the MC firmware
+ */
+#define MC_CMD_GET_VERSION 0x08
+#define MC_CMD_GET_VERSION_IN_LEN 0
+#define MC_CMD_GET_VERSION_V0_OUT_LEN 4
+#define MC_CMD_GET_VERSION_V1_OUT_LEN 32
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0
+/* Reserved version number to indicate "any" version. */
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff
+/* The version response of a boot ROM awaiting rescue */
+#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000
+#define MC_CMD_GET_VERSION_V1_OUT_PCOL_OFST 4
+/* 128bit mask of functions supported by the current firmware */
+#define MC_CMD_GET_VERSION_V1_OUT_SUPPORTED_FUNCS_OFST 8
+/* The command set exported by the boot ROM (MCDI v0) */
+#define MC_CMD_GET_VERSION_V0_SUPPORTED_FUNCS {		\
+	(1 << MC_CMD_READ32)	|			\
+	(1 << MC_CMD_WRITE32)	|			\
+	(1 << MC_CMD_COPYCODE)	|			\
+	(1 << MC_CMD_GET_VERSION),			\
+	0, 0, 0 }
+#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24
+
+/* Vectors in the boot ROM */
+/* Point to the copycode entry point. */
+#define MC_BOOTROM_COPYCODE_VEC (0x7f4)
+/* Points to the recovery mode entry point. */
+#define MC_BOOTROM_NOFLASH_VEC (0x7f8)
+
+/* Test execution limits */
+#define MC_TESTEXEC_VARIANT_COUNT 16
+#define MC_TESTEXEC_RESULT_COUNT 7
+
+/* MC_CMD_SET_TESTVARS: (debug, variadic in)
+ * Write variant words for test.
+ *
+ * The user supplies a bitmap of the variants they wish to set.
+ * They must ensure that IN.LEN >= 4 + 4 * ffs(BITMAP)
+ */
+#define MC_CMD_SET_TESTVARS 0x09
+#define MC_CMD_SET_TESTVARS_IN_LEN(_numwords)	\
+  (4 + 4*(_numwords))
+#define MC_CMD_SET_TESTVARS_IN_ARGS_BITMAP_OFST 0
+/* Up to MC_TESTEXEC_VARIANT_COUNT of 32byte words start here */
+#define MC_CMD_SET_TESTVARS_IN_ARGS_BUFFER_OFST 4
+#define MC_CMD_SET_TESTVARS_OUT_LEN 0
+
+/* MC_CMD_GET_TESTRCS: (debug, variadic out)
+ * Return result words from test.
+ */
+#define MC_CMD_GET_TESTRCS 0x0a
+#define MC_CMD_GET_TESTRCS_IN_LEN 4
+#define MC_CMD_GET_TESTRCS_IN_NUMWORDS_OFST 0
+#define MC_CMD_GET_TESTRCS_OUT_LEN(_numwords) \
+	(4 * (_numwords))
+#define MC_CMD_GET_TESTRCS_OUT_BUFFER_OFST 0
+
+/* MC_CMD_RUN_TEST: (debug)
+ * Run the test exported by this firmware image
+ */
+#define MC_CMD_RUN_TEST 0x0b
+#define MC_CMD_RUN_TEST_IN_LEN 0
+#define MC_CMD_RUN_TEST_OUT_LEN 0
+
+/* MC_CMD_CSR_READ32: (debug, variadic out)
+ * Read 32bit words from the indirect memory map
+ */
+#define MC_CMD_CSR_READ32 0x0c
+#define MC_CMD_CSR_READ32_IN_LEN 12
+#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0
+#define MC_CMD_CSR_READ32_IN_STEP_OFST 4
+#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8
+#define MC_CMD_CSR_READ32_OUT_LEN(_numwords)	\
+	(((_numwords) * 4) + 4)
+/* IN.NUMWORDS of 32bit words start here */
+#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0
+#define MC_CMD_CSR_READ32_OUT_IREG_STATUS_OFST(_numwords)	\
+	((_numwords) * 4)
+
+/* MC_CMD_CSR_WRITE32: (debug, variadic in)
+ * Write 32bit dwords to the indirect memory map
+ */
+#define MC_CMD_CSR_WRITE32 0x0d
+#define MC_CMD_CSR_WRITE32_IN_LEN(_numwords)	\
+	(((_numwords) * 4) + 8)
+#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4
+/* Multiple 32bit words of data to write start here */
+#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8
+#define MC_CMD_CSR_WRITE32_OUT_LEN 4
+#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0
+
+/* MC_CMD_JTAG_WORK: (debug, fpga only)
+ * Process JTAG work buffer for RBF acceleration.
+ *
+ *  Host: bit count, (up to) 32 words of data to clock out to JTAG
+ *   (bits 1,0=TMS,TDO for first bit; bits 3,2=TMS,TDO for second bit, etc.)
+ *  MC: bit count, (up to) 32 words of data clocked in from JTAG
+ *   (bit 0=TDI for first bit, bit 1=TDI for second bit, etc.; [31:16] unused)
+ */
+#define MC_CMD_JTAG_WORK 0x0e
+
+/* MC_CMD_STACKINFO: (debug, variadic out)
+ * Get stack information
+ *
+ * Host: nothing
+ * MC: (thread ptr, stack size, free space) for each thread in system
+ */
+#define MC_CMD_STACKINFO 0x0f
+
+/* MC_CMD_MDIO_READ:
+ * MDIO register read
+ */
+#define MC_CMD_MDIO_READ 0x10
+#define MC_CMD_MDIO_READ_IN_LEN 16
+#define MC_CMD_MDIO_READ_IN_BUS_OFST 0
+#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4
+#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8
+#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12
+#define MC_CMD_MDIO_READ_OUT_LEN 8
+#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0
+#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4
+
+/* MC_CMD_MDIO_WRITE:
+ * MDIO register write
+ */
+#define MC_CMD_MDIO_WRITE 0x11
+#define MC_CMD_MDIO_WRITE_IN_LEN 20
+#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0
+#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4
+#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8
+#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12
+#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16
+#define MC_CMD_MDIO_WRITE_OUT_LEN 4
+#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0
+
+/* By default all the MCDI MDIO operations perform clause45 mode.
+ * If you want to use clause22 then set DEVAD = MC_CMD_MDIO_CLAUSE22.
+ */
+#define MC_CMD_MDIO_CLAUSE22 32
+
+/* There are two MDIO buses: one for the internal PHY, and one for external
+ * devices.
+ */
+#define MC_CMD_MDIO_BUS_INTERNAL 0
+#define MC_CMD_MDIO_BUS_EXTERNAL 1
+
+/* The MDIO commands return the raw status bits from the MDIO block.  A "good"
+ * transaction should have the DONE bit set and all other bits clear.
+ */
+#define MC_CMD_MDIO_STATUS_GOOD 0x08
+
+
+/* MC_CMD_DBI_WRITE: (debug)
+ * Write DBI register(s)
+ *
+ * Host: address, byte-enables (and VF selection, and cs2 flag),
+ *       value [,address ...]
+ * MC: nothing
+ */
+#define MC_CMD_DBI_WRITE 0x12
+#define MC_CMD_DBI_WRITE_IN_LEN(_numwords)		\
+	(12 * (_numwords))
+#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(_word)		\
+	(((_word) * 12) + 0)
+#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(_word)	\
+	(((_word) * 12) + 4)
+#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(_word)		\
+	(((_word) * 12) + 8)
+#define MC_CMD_DBI_WRITE_OUT_LEN 0
+
+/* MC_CMD_DBI_READ: (debug)
+ * Read DBI register(s)
+ *
+ * Host: address, [,address ...]
+ * MC: value [,value ...]
+ * (note: this does not support reading from VFs, but is retained for backwards
+ * compatibility; see MC_CMD_DBI_READX below)
+ */
+#define MC_CMD_DBI_READ 0x13
+#define MC_CMD_DBI_READ_IN_LEN(_numwords)		\
+	(4 * (_numwords))
+#define MC_CMD_DBI_READ_OUT_LEN(_numwords)		\
+	(4 * (_numwords))
+
+/* MC_CMD_PORT_READ32: (debug)
+ * Read a 32-bit register from the indirect port register map.
+ *
+ * The port to access is implied by the Shared memory channel used.
+ */
+#define MC_CMD_PORT_READ32 0x14
+#define MC_CMD_PORT_READ32_IN_LEN 4
+#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0
+#define MC_CMD_PORT_READ32_OUT_LEN 8
+#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0
+#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4
+
+/* MC_CMD_PORT_WRITE32: (debug)
+ * Write a 32-bit register to the indirect port register map.
+ *
+ * The port to access is implied by the Shared memory channel used.
+ */
+#define MC_CMD_PORT_WRITE32 0x15
+#define MC_CMD_PORT_WRITE32_IN_LEN 8
+#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0
+#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4
+#define MC_CMD_PORT_WRITE32_OUT_LEN 4
+#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0
+
+/* MC_CMD_PORT_READ128: (debug)
+ * Read a 128-bit register from indirect port register map
+ *
+ * The port to access is implied by the Shared memory channel used.
+ */
+#define MC_CMD_PORT_READ128 0x16
+#define MC_CMD_PORT_READ128_IN_LEN 4
+#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0
+#define MC_CMD_PORT_READ128_OUT_LEN 20
+#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0
+#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16
+
+/* MC_CMD_PORT_WRITE128: (debug)
+ * Write a 128-bit register to indirect port register map.
+ *
+ * The port to access is implied by the Shared memory channel used.
+ */
+#define MC_CMD_PORT_WRITE128 0x17
+#define MC_CMD_PORT_WRITE128_IN_LEN 20
+#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0
+#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4
+#define MC_CMD_PORT_WRITE128_OUT_LEN 4
+#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0
+
+/* MC_CMD_GET_BOARD_CFG:
+ * Returns the MC firmware configuration structure
+ *
+ * The FW_SUBTYPE_LIST contains a 16-bit value for each of the 12 types of
+ * NVRAM area.  The values are defined in the firmware/mc/platform/<xxx>.c file
+ * for a specific board type, but otherwise have no meaning to the MC; they
+ * are used by the driver to manage selection of appropriate firmware updates.
+ */
+#define MC_CMD_GET_BOARD_CFG 0x18
+#define MC_CMD_GET_BOARD_CFG_IN_LEN 0
+#define MC_CMD_GET_BOARD_CFG_OUT_LEN 96
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4
+#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32
+#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36
+#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64
+#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72
+#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 24
+
+/* MC_CMD_DBI_READX: (debug)
+ * Read DBI register(s) -- extended functionality
+ *
+ * Host: vf selection, address, [,vf selection ...]
+ * MC: value [,value ...]
+ */
+#define MC_CMD_DBI_READX 0x19
+#define MC_CMD_DBI_READX_IN_LEN(_numwords)	\
+  (8*(_numwords))
+#define MC_CMD_DBI_READX_OUT_LEN(_numwords)	\
+  (4*(_numwords))
+
+/* MC_CMD_SET_RAND_SEED:
+ * Set the 16byte seed for the MC psuedo-random generator
+ */
+#define MC_CMD_SET_RAND_SEED 0x1a
+#define MC_CMD_SET_RAND_SEED_IN_LEN 16
+#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0
+#define MC_CMD_SET_RAND_SEED_OUT_LEN 0
+
+/* MC_CMD_LTSSM_HIST: (debug)
+ * Retrieve the history of the LTSSM, if the build supports it.
+ *
+ * Host: nothing
+ * MC: variable number of LTSSM values, as bytes
+ * The history is read-to-clear.
+ */
+#define MC_CMD_LTSSM_HIST 0x1b
+
+/* MC_CMD_DRV_ATTACH:
+ * Inform MCPU that this port is managed on the host (i.e. driver active)
+ */
+#define MC_CMD_DRV_ATTACH 0x1c
+#define MC_CMD_DRV_ATTACH_IN_LEN 8
+#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0
+#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4
+#define MC_CMD_DRV_ATTACH_OUT_LEN 4
+#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0
+
+/* MC_CMD_NCSI_PROD: (debug)
+ * Trigger an NC-SI event (and possibly an AEN in response)
+ */
+#define MC_CMD_NCSI_PROD 0x1d
+#define MC_CMD_NCSI_PROD_IN_LEN 4
+#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0
+#define MC_CMD_NCSI_PROD_LINKCHANGE_LBN 0
+#define MC_CMD_NCSI_PROD_LINKCHANGE_WIDTH 1
+#define MC_CMD_NCSI_PROD_RESET_LBN 1
+#define MC_CMD_NCSI_PROD_RESET_WIDTH 1
+#define MC_CMD_NCSI_PROD_DRVATTACH_LBN 2
+#define MC_CMD_NCSI_PROD_DRVATTACH_WIDTH 1
+#define MC_CMD_NCSI_PROD_OUT_LEN 0
+
+/* Enumeration */
+#define MC_CMD_NCSI_PROD_LINKCHANGE 0
+#define MC_CMD_NCSI_PROD_RESET 1
+#define MC_CMD_NCSI_PROD_DRVATTACH 2
+
+/* MC_CMD_DEVEL: (debug)
+ * Reserved for development
+ */
+#define MC_CMD_DEVEL 0x1e
+
+/* MC_CMD_SHMUART: (debug)
+ * Route UART output to circular buffer in shared memory instead.
+ */
+#define MC_CMD_SHMUART 0x1f
+#define MC_CMD_SHMUART_IN_FLAG_OFST 0
+#define MC_CMD_SHMUART_IN_LEN 4
+#define MC_CMD_SHMUART_OUT_LEN 0
+
+/* MC_CMD_PORT_RESET:
+ * Generic per-port reset. There is no equivalent for per-board reset.
+ *
+ * Locks required: None
+ * Return code: 0, ETIME
+ */
+#define MC_CMD_PORT_RESET 0x20
+#define MC_CMD_PORT_RESET_IN_LEN 0
+#define MC_CMD_PORT_RESET_OUT_LEN 0
+
+/* MC_CMD_RESOURCE_LOCK:
+ * Generic resource lock/unlock interface.
+ *
+ * Locks required: None
+ * Return code: 0,
+ *              EBUSY (if trylock is contended by other port),
+ *              EDEADLK (if trylock is already acquired by this port)
+ *              EINVAL (if unlock doesn't own the lock)
+ */
+#define MC_CMD_RESOURCE_LOCK 0x21
+#define MC_CMD_RESOURCE_LOCK_IN_LEN 8
+#define MC_CMD_RESOURCE_LOCK_IN_ACTION_OFST 0
+#define MC_CMD_RESOURCE_LOCK_ACTION_TRYLOCK 1
+#define MC_CMD_RESOURCE_LOCK_ACTION_UNLOCK 0
+#define MC_CMD_RESOURCE_LOCK_IN_RESOURCE_OFST 4
+#define MC_CMD_RESOURCE_LOCK_I2C 2
+#define MC_CMD_RESOURCE_LOCK_PHY 3
+#define MC_CMD_RESOURCE_LOCK_OUT_LEN 0
+
+/* MC_CMD_SPI_COMMAND: (variadic in, variadic out)
+ * Read/Write to/from the SPI device.
+ *
+ * Locks required: SPI_LOCK
+ * Return code: 0, ETIME, EINVAL, EACCES (if SPI_LOCK is not held)
+ */
+#define MC_CMD_SPI_COMMAND 0x22
+#define MC_CMD_SPI_COMMAND_IN_LEN(_write_bytes)	(12 + (_write_bytes))
+#define MC_CMD_SPI_COMMAND_IN_ARGS_OFST 0
+#define MC_CMD_SPI_COMMAND_IN_ARGS_ADDRESS_OFST 0
+#define MC_CMD_SPI_COMMAND_IN_ARGS_READ_BYTES_OFST 4
+#define MC_CMD_SPI_COMMAND_IN_ARGS_CHIP_SELECT_OFST 8
+/* Data to write here */
+#define MC_CMD_SPI_COMMAND_IN_WRITE_BUFFER_OFST 12
+#define MC_CMD_SPI_COMMAND_OUT_LEN(_read_bytes) (_read_bytes)
+/* Data read here */
+#define MC_CMD_SPI_COMMAND_OUT_READ_BUFFER_OFST 0
+
+/* MC_CMD_I2C_READ_WRITE: (variadic in, variadic out)
+ * Read/Write to/from the I2C bus.
+ *
+ * Locks required: I2C_LOCK
+ * Return code: 0, ETIME, EINVAL, EACCES (if I2C_LOCK is not held)
+ */
+#define MC_CMD_I2C_RW 0x23
+#define MC_CMD_I2C_RW_IN_LEN(_write_bytes) (8 + (_write_bytes))
+#define MC_CMD_I2C_RW_IN_ARGS_OFST 0
+#define MC_CMD_I2C_RW_IN_ARGS_ADDR_OFST 0
+#define MC_CMD_I2C_RW_IN_ARGS_READ_BYTES_OFST 4
+/* Data to write here */
+#define MC_CMD_I2C_RW_IN_WRITE_BUFFER_OFSET 8
+#define MC_CMD_I2C_RW_OUT_LEN(_read_bytes) (_read_bytes)
+/* Data read here */
+#define MC_CMD_I2C_RW_OUT_READ_BUFFER_OFST 0
+
+/* Generic phy capability bitmask */
+#define MC_CMD_PHY_CAP_10HDX_LBN 1
+#define MC_CMD_PHY_CAP_10HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_10FDX_LBN 2
+#define MC_CMD_PHY_CAP_10FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_100HDX_LBN 3
+#define MC_CMD_PHY_CAP_100HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_100FDX_LBN 4
+#define MC_CMD_PHY_CAP_100FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_1000HDX_LBN 5
+#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1
+#define MC_CMD_PHY_CAP_1000FDX_LBN 6
+#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_10000FDX_LBN 7
+#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1
+#define MC_CMD_PHY_CAP_PAUSE_LBN 8
+#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1
+#define MC_CMD_PHY_CAP_ASYM_LBN 9
+#define MC_CMD_PHY_CAP_ASYM_WIDTH 1
+#define MC_CMD_PHY_CAP_AN_LBN 10
+#define MC_CMD_PHY_CAP_AN_WIDTH 1
+
+/* Generic loopback enumeration */
+#define MC_CMD_LOOPBACK_NONE 0
+#define MC_CMD_LOOPBACK_DATA 1
+#define MC_CMD_LOOPBACK_GMAC 2
+#define MC_CMD_LOOPBACK_XGMII 3
+#define MC_CMD_LOOPBACK_XGXS 4
+#define MC_CMD_LOOPBACK_XAUI 5
+#define MC_CMD_LOOPBACK_GMII 6
+#define MC_CMD_LOOPBACK_SGMII 7
+#define MC_CMD_LOOPBACK_XGBR 8
+#define MC_CMD_LOOPBACK_XFI 9
+#define MC_CMD_LOOPBACK_XAUI_FAR 10
+#define MC_CMD_LOOPBACK_GMII_FAR 11
+#define MC_CMD_LOOPBACK_SGMII_FAR 12
+#define MC_CMD_LOOPBACK_XFI_FAR 13
+#define MC_CMD_LOOPBACK_GPHY 14
+#define MC_CMD_LOOPBACK_PHYXS 15
+#define MC_CMD_LOOPBACK_PCS 16
+#define MC_CMD_LOOPBACK_PMAPMD 17
+#define MC_CMD_LOOPBACK_XPORT 18
+#define MC_CMD_LOOPBACK_XGMII_WS 19
+#define MC_CMD_LOOPBACK_XAUI_WS 20
+#define MC_CMD_LOOPBACK_XAUI_WS_FAR 21
+#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 22
+#define MC_CMD_LOOPBACK_GMII_WS 23
+#define MC_CMD_LOOPBACK_XFI_WS 24
+#define MC_CMD_LOOPBACK_XFI_WS_FAR 25
+#define MC_CMD_LOOPBACK_PHYXS_WS 26
+
+/* Generic PHY statistics enumeration */
+#define MC_CMD_OUI 0
+#define MC_CMD_PMA_PMD_LINK_UP 1
+#define MC_CMD_PMA_PMD_RX_FAULT 2
+#define MC_CMD_PMA_PMD_TX_FAULT 3
+#define MC_CMD_PMA_PMD_SIGNAL 4
+#define MC_CMD_PMA_PMD_SNR_A 5
+#define MC_CMD_PMA_PMD_SNR_B 6
+#define MC_CMD_PMA_PMD_SNR_C 7
+#define MC_CMD_PMA_PMD_SNR_D 8
+#define MC_CMD_PCS_LINK_UP 9
+#define MC_CMD_PCS_RX_FAULT 10
+#define MC_CMD_PCS_TX_FAULT 11
+#define MC_CMD_PCS_BER 12
+#define MC_CMD_PCS_BLOCK_ERRORS 13
+#define MC_CMD_PHYXS_LINK_UP 14
+#define MC_CMD_PHYXS_RX_FAULT 15
+#define MC_CMD_PHYXS_TX_FAULT 16
+#define MC_CMD_PHYXS_ALIGN 17
+#define MC_CMD_PHYXS_SYNC 18
+#define MC_CMD_AN_LINK_UP 19
+#define MC_CMD_AN_COMPLETE 20
+#define MC_CMD_AN_10GBT_STATUS 21
+#define MC_CMD_CL22_LINK_UP 22
+#define MC_CMD_PHY_NSTATS 23
+
+/* MC_CMD_GET_PHY_CFG:
+ * Report PHY configuration.  This guarantees to succeed even if the PHY is in
+ * a "zombie" state.
+ *
+ * Locks required: None
+ * Return code: 0
+ */
+#define MC_CMD_GET_PHY_CFG 0x24
+
+#define MC_CMD_GET_PHY_CFG_IN_LEN 0
+#define MC_CMD_GET_PHY_CFG_OUT_LEN 72
+
+#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0
+#define MC_CMD_GET_PHY_CFG_PRESENT_LBN 0
+#define MC_CMD_GET_PHY_CFG_PRESENT_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_SHORTBIST_LBN 1
+#define MC_CMD_GET_PHY_CFG_SHORTBIST_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_LONGBIST_LBN 2
+#define MC_CMD_GET_PHY_CFG_LONGBIST_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_LOWPOWER_LBN 3
+#define MC_CMD_GET_PHY_CFG_LOWPOWER_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_POWEROFF_LBN 4
+#define MC_CMD_GET_PHY_CFG_POWEROFF_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_TXDIS_LBN 5
+#define MC_CMD_GET_PHY_CFG_TXDIS_WIDTH 1
+#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4
+/* Bitmask of supported capabilities */
+#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8
+#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
+#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16
+/* PHY statistics bitmap */
+#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20
+/* PHY type/name string */
+#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24
+#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20
+#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44
+#define MC_CMD_MEDIA_XAUI 1
+#define MC_CMD_MEDIA_CX4 2
+#define MC_CMD_MEDIA_KX4 3
+#define MC_CMD_MEDIA_XFP 4
+#define MC_CMD_MEDIA_SFP_PLUS 5
+#define MC_CMD_MEDIA_BASE_T 6
+/* MDIO "MMDS" supported */
+#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
+/* Native clause 22 */
+#define MC_CMD_MMD_CLAUSE22  0
+#define MC_CMD_MMD_CLAUSE45_PMAPMD 1
+#define MC_CMD_MMD_CLAUSE45_WIS 2
+#define MC_CMD_MMD_CLAUSE45_PCS 3
+#define MC_CMD_MMD_CLAUSE45_PHYXS 4
+#define MC_CMD_MMD_CLAUSE45_DTEXS 5
+#define MC_CMD_MMD_CLAUSE45_TC 6
+#define MC_CMD_MMD_CLAUSE45_AN 7
+/* Clause22 proxied over clause45 by PHY */
+#define MC_CMD_MMD_CLAUSE45_C22EXT 29
+#define MC_CMD_MMD_CLAUSE45_VEND1 30
+#define MC_CMD_MMD_CLAUSE45_VEND2 31
+/* PHY stepping version */
+#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52
+#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20
+
+/* MC_CMD_START_PHY_BIST:
+ * Start a BIST test on the PHY.
+ *
+ * Locks required: PHY_LOCK if doing a  PHY BIST
+ * Return code: 0, EINVAL, EACCES (if PHY_LOCK is not held)
+ */
+#define MC_CMD_START_BIST 0x25
+#define MC_CMD_START_BIST_IN_LEN 4
+#define MC_CMD_START_BIST_TYPE_OFST 0
+
+/* Run the PHY's short BIST */
+#define MC_CMD_PHY_BIST_SHORT  1
+/* Run the PHY's long BIST */
+#define MC_CMD_PHY_BIST_LONG   2
+/* Run BIST on the currently selected BPX Serdes (XAUI or XFI) */
+#define MC_CMD_BPX_SERDES_BIST 3
+
+/* MC_CMD_POLL_PHY_BIST: (variadic output)
+ * Poll for BIST completion
+ *
+ * Returns a single status code, and a binary blob of phy-specific
+ * bist output. If the driver can't succesfully parse the BIST output,
+ * it should still respect the Pass/Fail in OUT.RESULT.
+ *
+ * Locks required: PHY_LOCK  if doing a  PHY BIST
+ * Return code: 0, EACCES (if PHY_LOCK is not held)
+ */
+#define MC_CMD_POLL_BIST 0x26
+#define MC_CMD_POLL_BIST_IN_LEN 0
+#define MC_CMD_POLL_BIST_OUT_LEN UNKNOWN
+#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0
+#define MC_CMD_POLL_BIST_RUNNING 1
+#define MC_CMD_POLL_BIST_PASSED 2
+#define MC_CMD_POLL_BIST_FAILED 3
+#define MC_CMD_POLL_BIST_TIMEOUT 4
+#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4
+
+/* MC_CMD_PHY_SPI: (variadic in, variadic out)
+ * Read/Write/Erase the PHY SPI device
+ *
+ * Locks required: PHY_LOCK
+ * Return code: 0, ETIME, EINVAL, EACCES (if PHY_LOCK is not held)
+ */
+#define MC_CMD_PHY_SPI 0x27
+#define MC_CMD_PHY_SPI_IN_LEN(_write_bytes) (12 + (_write_bytes))
+#define MC_CMD_PHY_SPI_IN_ARGS_OFST 0
+#define MC_CMD_PHY_SPI_IN_ARGS_ADDR_OFST 0
+#define MC_CMD_PHY_SPI_IN_ARGS_READ_BYTES_OFST 4
+#define MC_CMD_PHY_SPI_IN_ARGS_ERASE_ALL_OFST 8
+/* Data to write here */
+#define MC_CMD_PHY_SPI_IN_WRITE_BUFFER_OFSET 12
+#define MC_CMD_PHY_SPI_OUT_LEN(_read_bytes) (_read_bytes)
+/* Data read here */
+#define MC_CMD_PHY_SPI_OUT_READ_BUFFER_OFST 0
+
+
+/* MC_CMD_GET_LOOPBACK_MODES:
+ * Returns a bitmask of loopback modes evailable at each speed.
+ *
+ * Locks required: None
+ * Return code: 0
+ */
+#define MC_CMD_GET_LOOPBACK_MODES 0x28
+#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
+#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32
+#define MC_CMD_GET_LOOPBACK_MODES_100M_OFST 0
+#define MC_CMD_GET_LOOPBACK_MODES_1G_OFST 8
+#define MC_CMD_GET_LOOPBACK_MODES_10G_OFST 16
+#define MC_CMD_GET_LOOPBACK_MODES_SUGGESTED_OFST 24
+
+/* Flow control enumeration */
+#define MC_CMD_FCNTL_OFF 0
+#define MC_CMD_FCNTL_RESPOND 1
+#define MC_CMD_FCNTL_BIDIR 2
+/* Auto - Use what the link has autonegotiated
+ *      - The driver should modify the advertised capabilities via SET_LINK.CAP
+ *        to control the negotiated flow control mode.
+ *      - Can only be set if the PHY supports PAUSE+ASYM capabilities
+ *      - Never returned by GET_LINK as the value programmed into the MAC
+ */
+#define MC_CMD_FCNTL_AUTO 3
+
+/* Generic mac fault bitmask */
+#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0
+#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1
+#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1
+#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1
+#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2
+#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1
+
+/* MC_CMD_GET_LINK:
+ * Read the unified MAC/PHY link state
+ *
+ * Locks required: None
+ * Return code: 0, ETIME
+ */
+#define MC_CMD_GET_LINK 0x29
+#define MC_CMD_GET_LINK_IN_LEN 0
+#define MC_CMD_GET_LINK_OUT_LEN 28
+/* near-side and link-partner advertised capabilities */
+#define MC_CMD_GET_LINK_OUT_CAP_OFST 0
+#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4
+/* Autonegotiated speed in mbit/s. The link may still be down
+ * even if this reads non-zero */
+#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8
+#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12
+#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16
+/* Whether we have overall link up */
+#define MC_CMD_GET_LINK_LINK_UP_LBN 0
+#define MC_CMD_GET_LINK_LINK_UP_WIDTH 1
+#define MC_CMD_GET_LINK_FULL_DUPLEX_LBN 1
+#define MC_CMD_GET_LINK_FULL_DUPLEX_WIDTH 1
+/* Whether we have link at the layers provided by the BPX */
+#define MC_CMD_GET_LINK_BPX_LINK_LBN 2
+#define MC_CMD_GET_LINK_BPX_LINK_WIDTH 1
+/* Whether the PHY has external link */
+#define MC_CMD_GET_LINK_PHY_LINK_LBN 3
+#define MC_CMD_GET_LINK_PHY_LINK_WIDTH 1
+#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20
+#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24
+
+/* MC_CMD_SET_LINK:
+ * Write the unified MAC/PHY link configuration
+ *
+ * A loopback speed of "0" is supported, and means
+ * (choose any available speed)
+ *
+ * Locks required: None
+ * Return code: 0, EINVAL, ETIME
+ */
+#define MC_CMD_SET_LINK 0x2a
+#define MC_CMD_SET_LINK_IN_LEN 16
+#define MC_CMD_SET_LINK_IN_CAP_OFST 0
+#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4
+#define MC_CMD_SET_LINK_LOWPOWER_LBN 0
+#define MC_CMD_SET_LINK_LOWPOWER_WIDTH 1
+#define MC_CMD_SET_LINK_POWEROFF_LBN 1
+#define MC_CMD_SET_LINK_POWEROFF_WIDTH 1
+#define MC_CMD_SET_LINK_TXDIS_LBN 2
+#define MC_CMD_SET_LINK_TXDIS_WIDTH 1
+#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8
+#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12
+#define MC_CMD_SET_LINK_OUT_LEN 0
+
+/* MC_CMD_SET_ID_LED:
+ * Set indentification LED state
+ *
+ * Locks required: None
+ * Return code: 0, EINVAL
+ */
+#define MC_CMD_SET_ID_LED 0x2b
+#define MC_CMD_SET_ID_LED_IN_LEN 4
+#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0
+#define  MC_CMD_LED_OFF 0
+#define  MC_CMD_LED_ON 1
+#define  MC_CMD_LED_DEFAULT 2
+#define MC_CMD_SET_ID_LED_OUT_LEN 0
+
+/* MC_CMD_SET_MAC:
+ * Set MAC configuration
+ *
+ * The MTU is the MTU programmed directly into the XMAC/GMAC
+ * (inclusive of EtherII, VLAN, bug16011 padding)
+ *
+ * Locks required: None
+ * Return code: 0, EINVAL
+ */
+#define MC_CMD_SET_MAC 0x2c
+#define MC_CMD_SET_MAC_IN_LEN 24
+#define MC_CMD_SET_MAC_IN_MTU_OFST 0
+#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4
+#define MC_CMD_SET_MAC_IN_ADDR_OFST 8
+#define MC_CMD_SET_MAC_IN_REJECT_OFST 16
+#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0
+#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1
+#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1
+#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1
+#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20
+#define MC_CMD_SET_MAC_OUT_LEN 0
+
+/* MC_CMD_PHY_STATS:
+ * Get generic PHY statistics
+ *
+ * This call returns the statistics for a generic PHY, by direct DMA
+ * into host memory, in a sparse array (indexed by the enumerate).
+ * Each value is represented by a 32bit number.
+ *
+ * Locks required: None
+ * Returns: 0, ETIME
+ * Response methods: shared memory, event
+ */
+#define MC_CMD_PHY_STATS 0x2d
+#define MC_CMD_PHY_STATS_IN_LEN 8
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4
+#define MC_CMD_PHY_STATS_OUT_LEN 0
+
+/* Unified MAC statistics enumeration */
+#define MC_CMD_MAC_GENERATION_START 0
+#define MC_CMD_MAC_TX_PKTS 1
+#define MC_CMD_MAC_TX_PAUSE_PKTS 2
+#define MC_CMD_MAC_TX_CONTROL_PKTS 3
+#define MC_CMD_MAC_TX_UNICAST_PKTS 4
+#define MC_CMD_MAC_TX_MULTICAST_PKTS 5
+#define MC_CMD_MAC_TX_BROADCAST_PKTS 6
+#define MC_CMD_MAC_TX_BYTES 7
+#define MC_CMD_MAC_TX_BAD_BYTES 8
+#define MC_CMD_MAC_TX_LT64_PKTS 9
+#define MC_CMD_MAC_TX_64_PKTS 10
+#define MC_CMD_MAC_TX_65_TO_127_PKTS 11
+#define MC_CMD_MAC_TX_128_TO_255_PKTS 12
+#define MC_CMD_MAC_TX_256_TO_511_PKTS 13
+#define MC_CMD_MAC_TX_512_TO_1023_PKTS 14
+#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 15
+#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 16
+#define MC_CMD_MAC_TX_GTJUMBO_PKTS 17
+#define MC_CMD_MAC_TX_BAD_FCS_PKTS 18
+#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 19
+#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 20
+#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 21
+#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 22
+#define MC_CMD_MAC_TX_DEFERRED_PKTS 23
+#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 24
+#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 25
+#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 26
+#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 27
+#define MC_CMD_MAC_RX_PKTS 28
+#define MC_CMD_MAC_RX_PAUSE_PKTS 29
+#define MC_CMD_MAC_RX_GOOD_PKTS 30
+#define MC_CMD_MAC_RX_CONTROL_PKTS 31
+#define MC_CMD_MAC_RX_UNICAST_PKTS 32
+#define MC_CMD_MAC_RX_MULTICAST_PKTS 33
+#define MC_CMD_MAC_RX_BROADCAST_PKTS 34
+#define MC_CMD_MAC_RX_BYTES 35
+#define MC_CMD_MAC_RX_BAD_BYTES 36
+#define MC_CMD_MAC_RX_64_PKTS 37
+#define MC_CMD_MAC_RX_65_TO_127_PKTS 38
+#define MC_CMD_MAC_RX_128_TO_255_PKTS 39
+#define MC_CMD_MAC_RX_256_TO_511_PKTS 40
+#define MC_CMD_MAC_RX_512_TO_1023_PKTS 41
+#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 42
+#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 43
+#define MC_CMD_MAC_RX_GTJUMBO_PKTS 44
+#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 45
+#define MC_CMD_MAC_RX_BAD_FCS_PKTS 46
+#define MC_CMD_MAC_RX_OVERFLOW_PKTS 47
+#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 48
+#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 49
+#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 50
+#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 51
+#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 52
+#define MC_CMD_MAC_RX_JABBER_PKTS 53
+#define MC_CMD_MAC_RX_NODESC_DROPS 54
+#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 55
+#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 56
+#define MC_CMD_MAC_RX_LANES01_DISP_ERR 57
+#define MC_CMD_MAC_RX_LANES23_DISP_ERR 58
+#define MC_CMD_MAC_RX_MATCH_FAULT 59
+#define MC_CMD_GMAC_DMABUF_START 64
+#define MC_CMD_GMAC_DMABUF_END   95
+/* Insert new members here. */
+#define MC_CMD_MAC_GENERATION_END 96
+#define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1)
+
+/* MC_CMD_MAC_STATS:
+ * Get unified GMAC/XMAC statistics
+ *
+ * This call returns unified statistics maintained by the MC as it
+ * switches between the GMAC and XMAC. The MC will write out all
+ * supported stats.  The driver should zero initialise the buffer to
+ * guarantee consistent results.
+ *
+ * Locks required: None
+ * Returns: 0
+ * Response methods: shared memory, event
+ */
+#define MC_CMD_MAC_STATS 0x2e
+#define MC_CMD_MAC_STATS_IN_LEN 16
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4
+#define MC_CMD_MAC_STATS_IN_CMD_OFST 8
+#define MC_CMD_MAC_STATS_CMD_DMA_LBN 0
+#define MC_CMD_MAC_STATS_CMD_DMA_WIDTH 1
+#define MC_CMD_MAC_STATS_CMD_CLEAR_LBN 1
+#define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1
+/* Fields only relevent when PERIODIC_CHANGE is set */
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4
+#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_WIDTH 1
+#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_LBN 16
+#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_WIDTH 16
+#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12
+
+#define MC_CMD_MAC_STATS_OUT_LEN 0
+
+/* Callisto flags */
+#define MC_CMD_SFT9001_ROBUST_LBN 0
+#define MC_CMD_SFT9001_ROBUST_WIDTH 1
+#define MC_CMD_SFT9001_SHORT_REACH_LBN 1
+#define MC_CMD_SFT9001_SHORT_REACH_WIDTH 1
+
+/* MC_CMD_SFT9001_GET:
+ * Read current callisto specific setting
+ *
+ * Locks required: None
+ * Returns: 0, ETIME
+ */
+#define MC_CMD_SFT9001_GET 0x30
+#define MC_CMD_SFT9001_GET_IN_LEN 0
+#define MC_CMD_SFT9001_GET_OUT_LEN 4
+#define MC_CMD_SFT9001_GET_OUT_FLAGS_OFST 0
+
+/* MC_CMD_SFT9001_SET:
+ * Write current callisto specific setting
+ *
+ * Locks required: None
+ * Returns: 0, ETIME, EINVAL
+ */
+#define MC_CMD_SFT9001_SET 0x31
+#define MC_CMD_SFT9001_SET_IN_LEN 4
+#define MC_CMD_SFT9001_SET_IN_FLAGS_OFST 0
+#define MC_CMD_SFT9001_SET_OUT_LEN 0
+
+
+/* MC_CMD_WOL_FILTER_SET:
+ * Set a WoL filter
+ *
+ * Locks required: None
+ * Returns: 0, EBUSY, EINVAL, ENOSYS
+ */
+#define MC_CMD_WOL_FILTER_SET 0x32
+#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 /* 190 rounded up to a word */
+#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0
+#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4
+
+/* There is a union at offset 8, following defines overlap due to
+ * this */
+#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8
+
+#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST		\
+	MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
+
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST   \
+	MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST   \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 4)
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 8)
+#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 10)
+
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST   \
+	MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST   \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 16)
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 32)
+#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST \
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 34)
+
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST	\
+	MC_CMD_WOL_FILTER_SET_IN_DATA_OFST
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_OFST		\
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 48)
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST	\
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 176)
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST	\
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 177)
+#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST	\
+	(MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 178)
+
+#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4
+#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0
+
+/* WOL Filter types enumeration */
+#define MC_CMD_WOL_TYPE_MAGIC      0x0
+			 /* unused 0x1 */
+#define MC_CMD_WOL_TYPE_WIN_MAGIC  0x2
+#define MC_CMD_WOL_TYPE_IPV4_SYN   0x3
+#define MC_CMD_WOL_TYPE_IPV6_SYN   0x4
+#define MC_CMD_WOL_TYPE_BITMAP     0x5
+#define MC_CMD_WOL_TYPE_MAX        0x6
+
+#define MC_CMD_FILTER_MODE_SIMPLE     0x0
+#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff
+
+/* MC_CMD_WOL_FILTER_REMOVE:
+ * Remove a WoL filter
+ *
+ * Locks required: None
+ * Returns: 0, EINVAL, ENOSYS
+ */
+#define MC_CMD_WOL_FILTER_REMOVE 0x33
+#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4
+#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0
+#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0
+
+
+/* MC_CMD_WOL_FILTER_RESET:
+ * Reset (i.e. remove all) WoL filters
+ *
+ * Locks required: None
+ * Returns: 0, ENOSYS
+ */
+#define MC_CMD_WOL_FILTER_RESET 0x34
+#define MC_CMD_WOL_FILTER_RESET_IN_LEN 0
+#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0
+
+/* MC_CMD_SET_MCAST_HASH:
+ * Set the MCASH hash value without otherwise
+ * reconfiguring the MAC
+ */
+#define MC_CMD_SET_MCAST_HASH 0x35
+#define MC_CMD_SET_MCAST_HASH_IN_LEN 32
+#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0
+#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16
+#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0
+
+/* MC_CMD_NVRAM_TYPES:
+ * Return bitfield indicating available types of virtual NVRAM partitions
+ *
+ * Locks required: none
+ * Returns: 0
+ */
+#define MC_CMD_NVRAM_TYPES 0x36
+#define MC_CMD_NVRAM_TYPES_IN_LEN 0
+#define MC_CMD_NVRAM_TYPES_OUT_LEN 4
+#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
+
+/* Supported NVRAM types */
+#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0
+#define MC_CMD_NVRAM_TYPE_MC_FW 1
+#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 2
+#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 3
+#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 4
+#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 5
+#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 6
+#define MC_CMD_NVRAM_TYPE_EXP_ROM 7
+#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 8
+#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 9
+#define MC_CMD_NVRAM_TYPE_PHY_PORT0 10
+#define MC_CMD_NVRAM_TYPE_PHY_PORT1 11
+#define MC_CMD_NVRAM_TYPE_LOG 12
+
+/* MC_CMD_NVRAM_INFO:
+ * Read info about a virtual NVRAM partition
+ *
+ * Locks required: none
+ * Returns: 0, EINVAL (bad type)
+ */
+#define MC_CMD_NVRAM_INFO 0x37
+#define MC_CMD_NVRAM_INFO_IN_LEN 4
+#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_INFO_OUT_LEN 24
+#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0
+#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4
+#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8
+#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12
+#define   MC_CMD_NVRAM_PROTECTED_LBN 0
+#define   MC_CMD_NVRAM_PROTECTED_WIDTH 1
+#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16
+#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20
+
+/* MC_CMD_NVRAM_UPDATE_START:
+ * Start a group of update operations on a virtual NVRAM partition
+ *
+ * Locks required: PHY_LOCK if type==*PHY*
+ * Returns: 0, EINVAL (bad type), EACCES (if PHY_LOCK required and not held)
+ */
+#define MC_CMD_NVRAM_UPDATE_START 0x38
+#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4
+#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0
+
+/* MC_CMD_NVRAM_READ:
+ * Read data from a virtual NVRAM partition
+ *
+ * Locks required: PHY_LOCK if type==*PHY*
+ * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+ */
+#define MC_CMD_NVRAM_READ 0x39
+#define MC_CMD_NVRAM_READ_IN_LEN 12
+#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8
+#define MC_CMD_NVRAM_READ_OUT_LEN(_read_bytes) (_read_bytes)
+#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0
+
+/* MC_CMD_NVRAM_WRITE:
+ * Write data to a virtual NVRAM partition
+ *
+ * Locks required: PHY_LOCK if type==*PHY*
+ * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+ */
+#define MC_CMD_NVRAM_WRITE 0x3a
+#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8
+#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12
+#define MC_CMD_NVRAM_WRITE_IN_LEN(_write_bytes) (12 + _write_bytes)
+#define MC_CMD_NVRAM_WRITE_OUT_LEN 0
+
+/* MC_CMD_NVRAM_ERASE:
+ * Erase sector(s) from a virtual NVRAM partition
+ *
+ * Locks required: PHY_LOCK if type==*PHY*
+ * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+ */
+#define MC_CMD_NVRAM_ERASE 0x3b
+#define MC_CMD_NVRAM_ERASE_IN_LEN 12
+#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4
+#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8
+#define MC_CMD_NVRAM_ERASE_OUT_LEN 0
+
+/* MC_CMD_NVRAM_UPDATE_FINISH:
+ * Finish a group of update operations on a virtual NVRAM partition
+ *
+ * Locks required: PHY_LOCK if type==*PHY*
+ * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held)
+ */
+#define MC_CMD_NVRAM_UPDATE_FINISH 0x3c
+#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 4
+#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0
+#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0
+
+/* MC_CMD_REBOOT:
+ * Reboot the MC. The AFTER_ASSERTION flag is intended to be used
+ * when the driver notices an assertion failure, to allow two ports to
+ * both recover (semi-)gracefully.
+ *
+ * Locks required: NONE
+ * Returns: Nothing. You get back a response with ERR=1, DATALEN=0
+ */
+#define MC_CMD_REBOOT 0x3d
+#define MC_CMD_REBOOT_IN_LEN 4
+#define MC_CMD_REBOOT_IN_FLAGS_OFST 0
+#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 1
+#define MC_CMD_REBOOT_OUT_LEN 0
+
+/* MC_CMD_SCHEDINFO:
+ * Request scheduler info. from the MC.
+ *
+ * Locks required: NONE
+ * Returns: An array of (timeslice,maximum overrun), one for each thread,
+ * in ascending order of thread address.s
+ */
+#define MC_CMD_SCHEDINFO 0x3e
+#define MC_CMD_SCHEDINFO_IN_LEN 0
+
+
+/* MC_CMD_SET_REBOOT_MODE: (debug)
+ * Set the mode for the next MC reboot.
+ *
+ * Locks required: NONE
+ *
+ * Sets the reboot mode to the specified value.  Returns the old mode.
+ */
+#define MC_CMD_REBOOT_MODE 0x3f
+#define MC_CMD_REBOOT_MODE_IN_LEN 4
+#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0
+#define MC_CMD_REBOOT_MODE_OUT_LEN 4
+#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0
+#define   MC_CMD_REBOOT_MODE_NORMAL 0
+#define   MC_CMD_REBOOT_MODE_SNAPPER 3
+
+/* MC_CMD_DEBUG_LOG:
+ * Null request/response command (debug)
+ * - sequence number is always zero
+ * - only supported on the UART interface
+ * (the same set of bytes is delivered as an
+ * event over PCI)
+ */
+#define MC_CMD_DEBUG_LOG 0x40
+#define MC_CMD_DEBUG_LOG_IN_LEN 0
+#define MC_CMD_DEBUG_LOG_OUT_LEN 0
+
+/* Generic sensor enumeration. Note that a dual port NIC
+ * will EITHER expose PHY_COMMON_TEMP OR PHY0_TEMP and
+ * PHY1_TEMP depending on whether there is a single sensor
+ * in the vicinity of the two port, or one per port.
+ */
+#define MC_CMD_SENSOR_CONTROLLER_TEMP 0		/* degC */
+#define MC_CMD_SENSOR_PHY_COMMON_TEMP 1		/* degC */
+#define MC_CMD_SENSOR_CONTROLLER_COOLING 2	/* bool */
+#define MC_CMD_SENSOR_PHY0_TEMP 3		/* degC */
+#define MC_CMD_SENSOR_PHY0_COOLING 4		/* bool */
+#define MC_CMD_SENSOR_PHY1_TEMP 5		/* degC */
+#define MC_CMD_SENSOR_PHY1_COOLING 6		/* bool */
+#define MC_CMD_SENSOR_IN_1V0 7			/* mV */
+#define MC_CMD_SENSOR_IN_1V2 8			/* mV */
+#define MC_CMD_SENSOR_IN_1V8 9			/* mV */
+#define MC_CMD_SENSOR_IN_2V5 10			/* mV */
+#define MC_CMD_SENSOR_IN_3V3 11			/* mV */
+#define MC_CMD_SENSOR_IN_12V0 12		/* mV */
+
+
+/* Sensor state */
+#define MC_CMD_SENSOR_STATE_OK 0
+#define MC_CMD_SENSOR_STATE_WARNING 1
+#define MC_CMD_SENSOR_STATE_FATAL 2
+#define MC_CMD_SENSOR_STATE_BROKEN 3
+
+/* MC_CMD_SENSOR_INFO:
+ * Returns information about every available sensor.
+ *
+ * Each sensor has a single (16bit) value, and a corresponding state.
+ * The mapping between value and sensor is nominally determined by the
+ * MC, but in practise is implemented as zero (BROKEN), one (TEMPERATURE),
+ * or two (VOLTAGE) ranges per sensor per state.
+ *
+ * This call returns a mask (32bit) of the sensors that are supported
+ * by this platform, then an array (indexed by MC_CMD_SENSOR) of byte
+ * offsets to the per-sensor arrays. Each sensor array has four 16bit
+ * numbers, min1, max1, min2, max2.
+ *
+ * Locks required: None
+ * Returns: 0
+ */
+#define MC_CMD_SENSOR_INFO 0x41
+#define MC_CMD_SENSOR_INFO_IN_LEN 0
+#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0
+#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \
+	(4 + (_x))
+#define MC_CMD_SENSOR_INFO_OUT_MIN1_OFST(_ofst) \
+	((_ofst) + 0)
+#define MC_CMD_SENSOR_INFO_OUT_MAX1_OFST(_ofst) \
+	((_ofst) + 2)
+#define MC_CMD_SENSOR_INFO_OUT_MIN2_OFST(_ofst) \
+	((_ofst) + 4)
+#define MC_CMD_SENSOR_INFO_OUT_MAX2_OFST(_ofst) \
+	((_ofst) + 6)
+
+/* MC_CMD_READ_SENSORS
+ * Returns the current (value, state) for each sensor
+ *
+ * Returns the current (value, state) [each 16bit] of each sensor supported by
+ * this board, by DMA'ing a sparse array (indexed by the sensor type) into host
+ * memory.
+ *
+ * The MC will send a SENSOREVT event every time any sensor changes state. The
+ * driver is responsible for ensuring that it doesn't miss any events. The board
+ * will function normally if all sensors are in STATE_OK or state_WARNING.
+ * Otherwise the board should not be expected to function.
+ */
+#define MC_CMD_READ_SENSORS 0x42
+#define MC_CMD_READ_SENSORS_IN_LEN 8
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0
+#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4
+#define MC_CMD_READ_SENSORS_OUT_LEN 0
+
+
+/* MC_CMD_GET_PHY_STATE:
+ * Report current state of PHY.  A "zombie" PHY is a PHY that has failed to
+ * boot (e.g. due to missing or corrupted firmware).
+ *
+ * Locks required: None
+ * Return code: 0
+ */
+#define MC_CMD_GET_PHY_STATE 0x43
+
+#define MC_CMD_GET_PHY_STATE_IN_LEN 0
+#define MC_CMD_GET_PHY_STATE_OUT_LEN 4
+#define MC_CMD_GET_PHY_STATE_STATE_OFST 0
+/* PHY state enumeration: */
+#define MC_CMD_PHY_STATE_OK 1
+#define MC_CMD_PHY_STATE_ZOMBIE 2
+
+
+/* 802.1Qbb control. 8 Tx queues that map to priorities 0 - 7. Use all 1s to
+ * disable 802.Qbb for a given priority. */
+#define MC_CMD_SETUP_8021QBB 0x44
+#define MC_CMD_SETUP_8021QBB_IN_LEN 32
+#define MC_CMD_SETUP_8021QBB_OUT_LEN 0
+#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFFST 0
+
+
+/* MC_CMD_WOL_FILTER_GET:
+ * Retrieve ID of any WoL filters
+ *
+ * Locks required: None
+ * Returns: 0, ENOSYS
+ */
+#define MC_CMD_WOL_FILTER_GET 0x45
+#define MC_CMD_WOL_FILTER_GET_IN_LEN 0
+#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4
+#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0
+
+
+/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD:
+ * Offload a protocol to NIC for lights-out state
+ *
+ * Locks required: None
+ * Returns: 0, ENOSYS
+ */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46
+
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN 16
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+
+/* There is a union at offset 4, following defines overlap due to
+ * this */
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPMAC_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPIP_OFST 10
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSMAC_OFST 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSSNIPV6_OFST 10
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSIPV6_OFST 26
+
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4
+#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0
+
+
+/* MC_CMD_REMOVE_LIGHTSOUT_PROTOCOL_OFFLOAD:
+ * Offload a protocol to NIC for lights-out state
+ *
+ * Locks required: None
+ * Returns: 0, ENOSYS
+ */
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD 0x47
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0
+
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0
+#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4
+
+/* Lights-out offload protocols enumeration */
+#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1
+#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS  0x2
+
+
+/* MC_CMD_MAC_RESET_RESTORE:
+ * Restore MAC after block reset
+ *
+ * Locks required: None
+ * Returns: 0
+ */
+
+#define MC_CMD_MAC_RESET_RESTORE 0x48
+#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0
+#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0
+
+#endif /* MCDI_PCOL_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/falcon_boards.c
+++ linux-ec2-2.6.32/drivers/net/sfc/falcon_boards.c
@@ -0,0 +1,754 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2007-2009 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, incorporated herein by reference.
+ */
+
+#include <linux/rtnetlink.h>
+
+#include "net_driver.h"
+#include "phy.h"
+#include "efx.h"
+#include "nic.h"
+#include "regs.h"
+#include "io.h"
+#include "workarounds.h"
+
+/* Macros for unpacking the board revision */
+/* The revision info is in host byte order. */
+#define FALCON_BOARD_TYPE(_rev) (_rev >> 8)
+#define FALCON_BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf)
+#define FALCON_BOARD_MINOR(_rev) (_rev & 0xf)
+
+/* Board types */
+#define FALCON_BOARD_SFE4001 0x01
+#define FALCON_BOARD_SFE4002 0x02
+#define FALCON_BOARD_SFN4111T 0x51
+#define FALCON_BOARD_SFN4112F 0x52
+
+/* Board temperature is about 15°C above ambient when air flow is
+ * limited. */
+#define FALCON_BOARD_TEMP_BIAS	15
+
+/* SFC4000 datasheet says: 'The maximum permitted junction temperature
+ * is 125°C; the thermal design of the environment for the SFC4000
+ * should aim to keep this well below 100°C.' */
+#define FALCON_JUNC_TEMP_MAX	90
+
+/*****************************************************************************
+ * Support for LM87 sensor chip used on several boards
+ */
+#define LM87_REG_ALARMS1		0x41
+#define LM87_REG_ALARMS2		0x42
+#define LM87_IN_LIMITS(nr, _min, _max)			\
+	0x2B + (nr) * 2, _max, 0x2C + (nr) * 2, _min
+#define LM87_AIN_LIMITS(nr, _min, _max)			\
+	0x3B + (nr), _max, 0x1A + (nr), _min
+#define LM87_TEMP_INT_LIMITS(_min, _max)		\
+	0x39, _max, 0x3A, _min
+#define LM87_TEMP_EXT1_LIMITS(_min, _max)		\
+	0x37, _max, 0x38, _min
+
+#define LM87_ALARM_TEMP_INT		0x10
+#define LM87_ALARM_TEMP_EXT1		0x20
+
+#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
+
+static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+			 const u8 *reg_values)
+{
+	struct falcon_board *board = falcon_board(efx);
+	struct i2c_client *client = i2c_new_device(&board->i2c_adap, info);
+	int rc;
+
+	if (!client)
+		return -EIO;
+
+	while (*reg_values) {
+		u8 reg = *reg_values++;
+		u8 value = *reg_values++;
+		rc = i2c_smbus_write_byte_data(client, reg, value);
+		if (rc)
+			goto err;
+	}
+
+	board->hwmon_client = client;
+	return 0;
+
+err:
+	i2c_unregister_device(client);
+	return rc;
+}
+
+static void efx_fini_lm87(struct efx_nic *efx)
+{
+	i2c_unregister_device(falcon_board(efx)->hwmon_client);
+}
+
+static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+	struct i2c_client *client = falcon_board(efx)->hwmon_client;
+	s32 alarms1, alarms2;
+
+	/* If link is up then do not monitor temperature */
+	if (EFX_WORKAROUND_7884(efx) && efx->link_state.up)
+		return 0;
+
+	alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+	alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+	if (alarms1 < 0)
+		return alarms1;
+	if (alarms2 < 0)
+		return alarms2;
+	alarms1 &= mask;
+	alarms2 &= mask >> 8;
+	if (alarms1 || alarms2) {
+		EFX_ERR(efx,
+			"LM87 detected a hardware failure (status %02x:%02x)"
+			"%s%s\n",
+			alarms1, alarms2,
+			(alarms1 & LM87_ALARM_TEMP_INT) ? " INTERNAL" : "",
+			(alarms1 & LM87_ALARM_TEMP_EXT1) ? " EXTERNAL" : "");
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+#else /* !CONFIG_SENSORS_LM87 */
+
+static inline int
+efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+	      const u8 *reg_values)
+{
+	return 0;
+}
+static inline void efx_fini_lm87(struct efx_nic *efx)
+{
+}
+static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SENSORS_LM87 */
+
+/*****************************************************************************
+ * Support for the SFE4001 and SFN4111T NICs.
+ *
+ * The SFE4001 does not power-up fully at reset due to its high power
+ * consumption.  We control its power via a PCA9539 I/O expander.
+ * Both boards have a MAX6647 temperature monitor which we expose to
+ * the lm90 driver.
+ *
+ * This also provides minimal support for reflashing the PHY, which is
+ * initiated by resetting it with the FLASH_CFG_1 pin pulled down.
+ * On SFE4001 rev A2 and later this is connected to the 3V3X output of
+ * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
+ * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
+ * exclusive with the network device being open.
+ */
+
+/**************************************************************************
+ * Support for I2C IO Expander device on SFE4001
+ */
+#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 MAX664X_REG_RSL		0x02
+#define MAX664X_REG_WLHO	0x0B
+
+static void sfe4001_poweroff(struct efx_nic *efx)
+{
+	struct i2c_client *ioexp_client = falcon_board(efx)->ioexp_client;
+	struct i2c_client *hwmon_client = falcon_board(efx)->hwmon_client;
+
+	/* Turn off all power rails and disable outputs */
+	i2c_smbus_write_byte_data(ioexp_client, P0_OUT, 0xff);
+	i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, 0xff);
+	i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff);
+
+	/* Clear any over-temperature alert */
+	i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
+}
+
+static int sfe4001_poweron(struct efx_nic *efx)
+{
+	struct i2c_client *ioexp_client = falcon_board(efx)->ioexp_client;
+	struct i2c_client *hwmon_client = falcon_board(efx)->hwmon_client;
+	unsigned int i, j;
+	int rc;
+	u8 out;
+
+	/* Clear any previous over-temperature alert */
+	rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
+	if (rc < 0)
+		return rc;
+
+	/* Enable port 0 and port 1 outputs on IO expander */
+	rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00);
+	if (rc)
+		return rc;
+	rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG,
+				       0xff & ~(1 << P1_SPARE_LBN));
+	if (rc)
+		goto fail_on;
+
+	/* If PHY power is on, turn it all off and wait 1 second to
+	 * ensure a full reset.
+	 */
+	rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT);
+	if (rc < 0)
+		goto fail_on;
+	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));
+	if (rc != out) {
+		EFX_INFO(efx, "power-cycling PHY\n");
+		rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+		if (rc)
+			goto fail_on;
+		schedule_timeout_uninterruptible(HZ);
+	}
+
+	for (i = 0; i < 20; ++i) {
+		/* 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));
+		if (efx->phy_mode & PHY_MODE_SPECIAL)
+			out |= 1 << P0_EN_3V3X_LBN;
+
+		rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+		if (rc)
+			goto fail_on;
+		msleep(10);
+
+		/* Turn on 1V power rail */
+		out &= ~(1 << P0_EN_1V0X_LBN);
+		rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out);
+		if (rc)
+			goto fail_on;
+
+		EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i);
+
+		/* In flash config mode, DSP does not turn on AFE, so
+		 * just wait 1 second.
+		 */
+		if (efx->phy_mode & PHY_MODE_SPECIAL) {
+			schedule_timeout_uninterruptible(HZ);
+			return 0;
+		}
+
+		for (j = 0; j < 10; ++j) {
+			msleep(100);
+
+			/* Check DSP has asserted AFE power line */
+			rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN);
+			if (rc < 0)
+				goto fail_on;
+			if (rc & (1 << P1_AFE_PWD_LBN))
+				return 0;
+		}
+	}
+
+	EFX_INFO(efx, "timed out waiting for DSP boot\n");
+	rc = -ETIMEDOUT;
+fail_on:
+	sfe4001_poweroff(efx);
+	return rc;
+}
+
+static int sfn4111t_reset(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+	efx_oword_t reg;
+
+	/* GPIO 3 and the GPIO register are shared with I2C, so block that */
+	i2c_lock_adapter(&board->i2c_adap);
+
+	/* Pull RST_N (GPIO 2) low then let it up again, setting the
+	 * FLASH_CFG_1 strap (GPIO 3) appropriately.  Only change the
+	 * output enables; the output levels should always be 0 (low)
+	 * and we rely on external pull-ups. */
+	efx_reado(efx, &reg, FR_AB_GPIO_CTL);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, true);
+	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
+	msleep(1000);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, false);
+	EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN,
+			    !!(efx->phy_mode & PHY_MODE_SPECIAL));
+	efx_writeo(efx, &reg, FR_AB_GPIO_CTL);
+	msleep(1);
+
+	i2c_unlock_adapter(&board->i2c_adap);
+
+	ssleep(1);
+	return 0;
+}
+
+static ssize_t show_phy_flash_cfg(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+	return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL));
+}
+
+static ssize_t set_phy_flash_cfg(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+	enum efx_phy_mode old_mode, new_mode;
+	int err;
+
+	rtnl_lock();
+	old_mode = efx->phy_mode;
+	if (count == 0 || *buf == '0')
+		new_mode = old_mode & ~PHY_MODE_SPECIAL;
+	else
+		new_mode = PHY_MODE_SPECIAL;
+	if (old_mode == new_mode) {
+		err = 0;
+	} else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
+		err = -EBUSY;
+	} else {
+		/* Reset the PHY, reconfigure the MAC and enable/disable
+		 * MAC stats accordingly. */
+		efx->phy_mode = new_mode;
+		if (new_mode & PHY_MODE_SPECIAL)
+			falcon_stop_nic_stats(efx);
+		if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
+			err = sfe4001_poweron(efx);
+		else
+			err = sfn4111t_reset(efx);
+		if (!err)
+			err = efx_reconfigure_port(efx);
+		if (!(new_mode & PHY_MODE_SPECIAL))
+			falcon_start_nic_stats(efx);
+	}
+	rtnl_unlock();
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg);
+
+static void sfe4001_fini(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+
+	EFX_INFO(efx, "%s\n", __func__);
+
+	device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+	sfe4001_poweroff(efx);
+	i2c_unregister_device(board->ioexp_client);
+	i2c_unregister_device(board->hwmon_client);
+}
+
+static int sfe4001_check_hw(struct efx_nic *efx)
+{
+	s32 status;
+
+	/* If XAUI link is up then do not monitor */
+	if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
+		return 0;
+
+	/* 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.
+	 * We know we can read from the IO expander because we did
+	 * it during power-on. Assume failure now is bad news. */
+	status = i2c_smbus_read_byte_data(falcon_board(efx)->ioexp_client, P1_IN);
+	if (status >= 0 &&
+	    (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0)
+		return 0;
+
+	/* Use board power control, not PHY power control */
+	sfe4001_poweroff(efx);
+	efx->phy_mode = PHY_MODE_OFF;
+
+	return (status < 0) ? -EIO : -ERANGE;
+}
+
+static struct i2c_board_info sfe4001_hwmon_info = {
+	I2C_BOARD_INFO("max6647", 0x4e),
+};
+
+/* 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
+ */
+static int sfe4001_init(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+	int rc;
+
+#if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE)
+	board->hwmon_client =
+		i2c_new_device(&board->i2c_adap, &sfe4001_hwmon_info);
+#else
+	board->hwmon_client =
+		i2c_new_dummy(&board->i2c_adap, sfe4001_hwmon_info.addr);
+#endif
+	if (!board->hwmon_client)
+		return -EIO;
+
+	/* Raise board/PHY high limit from 85 to 90 degrees Celsius */
+	rc = i2c_smbus_write_byte_data(board->hwmon_client,
+				       MAX664X_REG_WLHO, 90);
+	if (rc)
+		goto fail_hwmon;
+
+	board->ioexp_client = i2c_new_dummy(&board->i2c_adap, PCA9539);
+	if (!board->ioexp_client) {
+		rc = -EIO;
+		goto fail_hwmon;
+	}
+
+	if (efx->phy_mode & PHY_MODE_SPECIAL) {
+		/* PHY won't generate a 156.25 MHz clock and MAC stats fetch
+		 * will fail. */
+		falcon_stop_nic_stats(efx);
+	}
+	rc = sfe4001_poweron(efx);
+	if (rc)
+		goto fail_ioexp;
+
+	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+	if (rc)
+		goto fail_on;
+
+	EFX_INFO(efx, "PHY is powered on\n");
+	return 0;
+
+fail_on:
+	sfe4001_poweroff(efx);
+fail_ioexp:
+	i2c_unregister_device(board->ioexp_client);
+fail_hwmon:
+	i2c_unregister_device(board->hwmon_client);
+	return rc;
+}
+
+static int sfn4111t_check_hw(struct efx_nic *efx)
+{
+	s32 status;
+
+	/* If XAUI link is up then do not monitor */
+	if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
+		return 0;
+
+	/* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
+	status = i2c_smbus_read_byte_data(falcon_board(efx)->hwmon_client,
+					  MAX664X_REG_RSL);
+	if (status < 0)
+		return -EIO;
+	if (status & 0x57)
+		return -ERANGE;
+	return 0;
+}
+
+static void sfn4111t_fini(struct efx_nic *efx)
+{
+	EFX_INFO(efx, "%s\n", __func__);
+
+	device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+	i2c_unregister_device(falcon_board(efx)->hwmon_client);
+}
+
+static struct i2c_board_info sfn4111t_a0_hwmon_info = {
+	I2C_BOARD_INFO("max6647", 0x4e),
+};
+
+static struct i2c_board_info sfn4111t_r5_hwmon_info = {
+	I2C_BOARD_INFO("max6646", 0x4d),
+};
+
+static void sfn4111t_init_phy(struct efx_nic *efx)
+{
+	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
+		if (sft9001_wait_boot(efx) != -EINVAL)
+			return;
+
+		efx->phy_mode = PHY_MODE_SPECIAL;
+		falcon_stop_nic_stats(efx);
+	}
+
+	sfn4111t_reset(efx);
+	sft9001_wait_boot(efx);
+}
+
+static int sfn4111t_init(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+	int rc;
+
+	board->hwmon_client =
+		i2c_new_device(&board->i2c_adap,
+			       (board->minor < 5) ?
+			       &sfn4111t_a0_hwmon_info :
+			       &sfn4111t_r5_hwmon_info);
+	if (!board->hwmon_client)
+		return -EIO;
+
+	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+	if (rc)
+		goto fail_hwmon;
+
+	if (efx->phy_mode & PHY_MODE_SPECIAL)
+		/* PHY may not generate a 156.25 MHz clock and MAC
+		 * stats fetch will fail. */
+		falcon_stop_nic_stats(efx);
+
+	return 0;
+
+fail_hwmon:
+	i2c_unregister_device(board->hwmon_client);
+	return rc;
+}
+
+/*****************************************************************************
+ * Support for the SFE4002
+ *
+ */
+static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4002_lm87_regs[] = {
+	LM87_IN_LIMITS(0, 0x7c, 0x99),		/* 2.5V:  1.8V +/- 10% */
+	LM87_IN_LIMITS(1, 0x4c, 0x5e),		/* Vccp1: 1.2V +/- 10% */
+	LM87_IN_LIMITS(2, 0xac, 0xd4),		/* 3.3V:  3.3V +/- 10% */
+	LM87_IN_LIMITS(3, 0xac, 0xd4),		/* 5V:    5.0V +/- 10% */
+	LM87_IN_LIMITS(4, 0xac, 0xe0),		/* 12V:   10.8-14V */
+	LM87_IN_LIMITS(5, 0x3f, 0x4f),		/* Vccp2: 1.0V +/- 10% */
+	LM87_AIN_LIMITS(0, 0x98, 0xbb),		/* AIN1:  1.66V +/- 10% */
+	LM87_AIN_LIMITS(1, 0x8a, 0xa9),		/* AIN2:  1.5V +/- 10% */
+	LM87_TEMP_INT_LIMITS(0, 80 + FALCON_BOARD_TEMP_BIAS),
+	LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX),
+	0
+};
+
+static struct i2c_board_info sfe4002_hwmon_info = {
+	I2C_BOARD_INFO("lm87", 0x2e),
+	.platform_data	= &sfe4002_lm87_channel,
+};
+
+/****************************************************************************/
+/* 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 void sfe4002_init_phy(struct efx_nic *efx)
+{
+	/* Set the TX and RX LEDs to reflect status and activity, and the
+	 * fault LED off */
+	falcon_qt202x_set_led(efx, SFE4002_TX_LED,
+			      QUAKE_LED_TXLINK | QUAKE_LED_LINK_ACTSTAT);
+	falcon_qt202x_set_led(efx, SFE4002_RX_LED,
+			      QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACTSTAT);
+	falcon_qt202x_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF);
+}
+
+static void sfe4002_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+	falcon_qt202x_set_led(
+		efx, SFE4002_FAULT_LED,
+		(mode == EFX_LED_ON) ? QUAKE_LED_ON : QUAKE_LED_OFF);
+}
+
+static int sfe4002_check_hw(struct efx_nic *efx)
+{
+	struct falcon_board *board = falcon_board(efx);
+
+	/* A0 board rev. 4002s report a temperature fault the whole time
+	 * (bad sensor) so we mask it out. */
+	unsigned alarm_mask =
+		(board->major == 0 && board->minor == 0) ?
+		~LM87_ALARM_TEMP_EXT1 : ~0;
+
+	return efx_check_lm87(efx, alarm_mask);
+}
+
+static int sfe4002_init(struct efx_nic *efx)
+{
+	return efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
+}
+
+/*****************************************************************************
+ * Support for the SFN4112F
+ *
+ */
+static u8 sfn4112f_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfn4112f_lm87_regs[] = {
+	LM87_IN_LIMITS(0, 0x7c, 0x99),		/* 2.5V:  1.8V +/- 10% */
+	LM87_IN_LIMITS(1, 0x4c, 0x5e),		/* Vccp1: 1.2V +/- 10% */
+	LM87_IN_LIMITS(2, 0xac, 0xd4),		/* 3.3V:  3.3V +/- 10% */
+	LM87_IN_LIMITS(4, 0xac, 0xe0),		/* 12V:   10.8-14V */
+	LM87_IN_LIMITS(5, 0x3f, 0x4f),		/* Vccp2: 1.0V +/- 10% */
+	LM87_AIN_LIMITS(1, 0x8a, 0xa9),		/* AIN2:  1.5V +/- 10% */
+	LM87_TEMP_INT_LIMITS(0, 60 + FALCON_BOARD_TEMP_BIAS),
+	LM87_TEMP_EXT1_LIMITS(0, FALCON_JUNC_TEMP_MAX),
+	0
+};
+
+static struct i2c_board_info sfn4112f_hwmon_info = {
+	I2C_BOARD_INFO("lm87", 0x2e),
+	.platform_data	= &sfn4112f_lm87_channel,
+};
+
+#define SFN4112F_ACT_LED	0
+#define SFN4112F_LINK_LED	1
+
+static void sfn4112f_init_phy(struct efx_nic *efx)
+{
+	falcon_qt202x_set_led(efx, SFN4112F_ACT_LED,
+			      QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACT);
+	falcon_qt202x_set_led(efx, SFN4112F_LINK_LED,
+			      QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT);
+}
+
+static void sfn4112f_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+	int reg;
+
+	switch (mode) {
+	case EFX_LED_OFF:
+		reg = QUAKE_LED_OFF;
+		break;
+	case EFX_LED_ON:
+		reg = QUAKE_LED_ON;
+		break;
+	default:
+		reg = QUAKE_LED_RXLINK | QUAKE_LED_LINK_STAT;
+		break;
+	}
+
+	falcon_qt202x_set_led(efx, SFN4112F_LINK_LED, reg);
+}
+
+static int sfn4112f_check_hw(struct efx_nic *efx)
+{
+	/* Mask out unused sensors */
+	return efx_check_lm87(efx, ~0x48);
+}
+
+static int sfn4112f_init(struct efx_nic *efx)
+{
+	return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
+}
+
+static const struct falcon_board_type board_types[] = {
+	{
+		.id		= FALCON_BOARD_SFE4001,
+		.ref_model	= "SFE4001",
+		.gen_type	= "10GBASE-T adapter",
+		.init		= sfe4001_init,
+		.init_phy	= efx_port_dummy_op_void,
+		.fini		= sfe4001_fini,
+		.set_id_led	= tenxpress_set_id_led,
+		.monitor	= sfe4001_check_hw,
+	},
+	{
+		.id		= FALCON_BOARD_SFE4002,
+		.ref_model	= "SFE4002",
+		.gen_type	= "XFP adapter",
+		.init		= sfe4002_init,
+		.init_phy	= sfe4002_init_phy,
+		.fini		= efx_fini_lm87,
+		.set_id_led	= sfe4002_set_id_led,
+		.monitor	= sfe4002_check_hw,
+	},
+	{
+		.id		= FALCON_BOARD_SFN4111T,
+		.ref_model	= "SFN4111T",
+		.gen_type	= "100/1000/10GBASE-T adapter",
+		.init		= sfn4111t_init,
+		.init_phy	= sfn4111t_init_phy,
+		.fini		= sfn4111t_fini,
+		.set_id_led	= tenxpress_set_id_led,
+		.monitor	= sfn4111t_check_hw,
+	},
+	{
+		.id		= FALCON_BOARD_SFN4112F,
+		.ref_model	= "SFN4112F",
+		.gen_type	= "SFP+ adapter",
+		.init		= sfn4112f_init,
+		.init_phy	= sfn4112f_init_phy,
+		.fini		= efx_fini_lm87,
+		.set_id_led	= sfn4112f_set_id_led,
+		.monitor	= sfn4112f_check_hw,
+	},
+};
+
+int falcon_probe_board(struct efx_nic *efx, u16 revision_info)
+{
+	struct falcon_board *board = falcon_board(efx);
+	u8 type_id = FALCON_BOARD_TYPE(revision_info);
+	int i;
+
+	board->major = FALCON_BOARD_MAJOR(revision_info);
+	board->minor = FALCON_BOARD_MINOR(revision_info);
+
+	for (i = 0; i < ARRAY_SIZE(board_types); i++)
+		if (board_types[i].id == type_id)
+			board->type = &board_types[i];
+
+	if (board->type) {
+		EFX_INFO(efx, "board is %s rev %c%d\n",
+			 (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
+			 ? board->type->ref_model : board->type->gen_type,
+			 'A' + board->major, board->minor);
+		return 0;
+	} else {
+		EFX_ERR(efx, "unknown board type %d\n", type_id);
+		return -ENODEV;
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mcdi_mac.c
+++ linux-ec2-2.6.32/drivers/net/sfc/mcdi_mac.c
@@ -0,0 +1,152 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2009 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, incorporated herein by reference.
+ */
+
+#include "net_driver.h"
+#include "efx.h"
+#include "mac.h"
+#include "mcdi.h"
+#include "mcdi_pcol.h"
+
+static int efx_mcdi_set_mac(struct efx_nic *efx)
+{
+	u32 reject, fcntl;
+	u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN];
+
+	memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST,
+	       efx->net_dev->dev_addr, ETH_ALEN);
+
+	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
+			EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
+	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
+
+	/* The MCDI command provides for controlling accept/reject
+	 * of broadcast packets too, but the driver doesn't currently
+	 * expose this. */
+	reject = (efx->promiscuous) ? 0 :
+		(1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN);
+	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject);
+
+	switch (efx->wanted_fc) {
+	case EFX_FC_RX | EFX_FC_TX:
+		fcntl = MC_CMD_FCNTL_BIDIR;
+		break;
+	case EFX_FC_RX:
+		fcntl = MC_CMD_FCNTL_RESPOND;
+		break;
+	default:
+		fcntl = MC_CMD_FCNTL_OFF;
+		break;
+	}
+	if (efx->wanted_fc & EFX_FC_AUTO)
+		fcntl = MC_CMD_FCNTL_AUTO;
+
+	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
+
+	return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
+			    NULL, 0, NULL);
+}
+
+static int efx_mcdi_get_mac_faults(struct efx_nic *efx, u32 *faults)
+{
+	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
+	size_t outlength;
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlength);
+	if (rc)
+		goto fail;
+
+	*faults = MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n",
+		__func__, rc);
+	return rc;
+}
+
+int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
+		       u32 dma_len, int enable, int clear)
+{
+	u8 inbuf[MC_CMD_MAC_STATS_IN_LEN];
+	int rc;
+	efx_dword_t *cmd_ptr;
+	int period = 1000;
+	u32 addr_hi;
+	u32 addr_lo;
+
+	BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN != 0);
+
+	addr_lo = ((u64)dma_addr) >> 0;
+	addr_hi = ((u64)dma_addr) >> 32;
+
+	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_LO, addr_lo);
+	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi);
+	cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD);
+	if (enable)
+		EFX_POPULATE_DWORD_6(*cmd_ptr,
+				     MC_CMD_MAC_STATS_CMD_DMA, 1,
+				     MC_CMD_MAC_STATS_CMD_CLEAR, clear,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, 1,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0,
+				     MC_CMD_MAC_STATS_CMD_PERIOD_MS, period);
+	else
+		EFX_POPULATE_DWORD_5(*cmd_ptr,
+				     MC_CMD_MAC_STATS_CMD_DMA, 0,
+				     MC_CMD_MAC_STATS_CMD_CLEAR, clear,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, 0,
+				     MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0);
+	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: %s failed rc=%d\n",
+		__func__, enable ? "enable" : "disable", rc);
+	return rc;
+}
+
+static int efx_mcdi_mac_reconfigure(struct efx_nic *efx)
+{
+	int rc;
+
+	rc = efx_mcdi_set_mac(efx);
+	if (rc != 0)
+		return rc;
+
+	/* Restore the multicast hash registers. */
+	efx->type->push_multicast_hash(efx);
+
+	return 0;
+}
+
+
+static bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
+{
+	u32 faults;
+	int rc = efx_mcdi_get_mac_faults(efx, &faults);
+	return (rc != 0) || (faults != 0);
+}
+
+
+struct efx_mac_operations efx_mcdi_mac_operations = {
+	.reconfigure	= efx_mcdi_mac_reconfigure,
+	.update_stats	= efx_port_dummy_op_void,
+	.check_fault 	= efx_mcdi_mac_check_fault,
+};
--- linux-ec2-2.6.32.orig/drivers/net/sfc/net_driver.h
+++ linux-ec2-2.6.32/drivers/net/sfc/net_driver.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2008 Solarflare Communications Inc.
+ * Copyright 2005-2009 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
@@ -38,7 +38,7 @@
 #ifndef EFX_DRIVER_NAME
 #define EFX_DRIVER_NAME	"sfc"
 #endif
-#define EFX_DRIVER_VERSION	"2.3"
+#define EFX_DRIVER_VERSION	"3.0"
 
 #ifdef EFX_ENABLE_DEBUG
 #define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@@ -113,6 +113,13 @@
 	int entries;
 };
 
+enum efx_flush_state {
+	FLUSH_NONE,
+	FLUSH_PENDING,
+	FLUSH_FAILED,
+	FLUSH_DONE,
+};
+
 /**
  * struct efx_tx_buffer - An Efx TX buffer
  * @skb: The associated socket buffer.
@@ -189,7 +196,7 @@
 	struct efx_nic *nic;
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
-	bool flushed;
+	enum efx_flush_state flushed;
 
 	/* Members used mainly on the completion path */
 	unsigned int read_count ____cacheline_aligned_in_smp;
@@ -284,7 +291,7 @@
 	struct page *buf_page;
 	dma_addr_t buf_dma_addr;
 	char *buf_data;
-	bool flushed;
+	enum efx_flush_state flushed;
 };
 
 /**
@@ -327,7 +334,7 @@
  * @used_flags: Channel is used by net driver
  * @enabled: Channel enabled indicator
  * @irq: IRQ number (MSI and MSI-X only)
- * @irq_moderation: IRQ moderation value (in us)
+ * @irq_moderation: IRQ moderation value (in hardware ticks)
  * @napi_dev: Net device used with NAPI
  * @napi_str: NAPI control structure
  * @reset_work: Scheduled reset work thread
@@ -343,9 +350,9 @@
  * @rx_alloc_push_pages: RX allocation method currently in use for pushing
  *	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_mcast_mismatch: Count of unmatched multicast frames
  * @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
@@ -373,9 +380,9 @@
 	int rx_alloc_push_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_mcast_mismatch;
 	unsigned n_rx_frm_trunc;
 	unsigned n_rx_overlength;
 	unsigned n_skbuff_leaks;
@@ -388,53 +395,29 @@
 
 };
 
-/**
- * struct efx_blinker - S/W LED blinking context
- * @state: Current state - on or off
- * @resubmit: Timer resubmission flag
- * @timer: Control timer for blinking
- */
-struct efx_blinker {
-	bool state;
-	bool 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. May be called repeatedly.
- * @set_id_led: Turns the identification LED on or off
- * @blink: Starts/stops blinking
- * @monitor: Board-specific health check function
- * @fini: Cleanup function
- * @blinker: used to blink LEDs in software
- * @hwmon_client: I2C client for hardware monitor
- * @ioexp_client: I2C client for power/port control
- */
-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. */
-	void (*init_leds)(struct efx_nic *efx);
-	void (*set_id_led) (struct efx_nic *efx, bool state);
-	int (*monitor) (struct efx_nic *nic);
-	void (*blink) (struct efx_nic *efx, bool start);
-	void (*fini) (struct efx_nic *nic);
-	struct efx_blinker blinker;
-	struct i2c_client *hwmon_client, *ioexp_client;
-};
-
-#define STRING_TABLE_LOOKUP(val, member)	\
-	member ## _names[val]
+enum efx_led_mode {
+	EFX_LED_OFF	= 0,
+	EFX_LED_ON	= 1,
+	EFX_LED_DEFAULT	= 2
+};
+
+#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)
 
 enum efx_int_mode {
 	/* Be careful if altering to correct macro below */
@@ -445,20 +428,7 @@
 };
 #define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI)
 
-enum phy_type {
-	PHY_TYPE_NONE = 0,
-	PHY_TYPE_TXC43128 = 1,
-	PHY_TYPE_88E1111 = 2,
-	PHY_TYPE_SFX7101 = 3,
-	PHY_TYPE_QT2022C2 = 4,
-	PHY_TYPE_PM8358 = 6,
-	PHY_TYPE_SFT9001A = 8,
-	PHY_TYPE_QT2025C = 9,
-	PHY_TYPE_SFT9001B = 10,
-	PHY_TYPE_MAX	/* Insert any new items before this */
-};
-
-#define EFX_IS10G(efx) ((efx)->link_speed == 10000)
+#define EFX_IS10G(efx) ((efx)->link_state.speed == 10000)
 
 enum nic_state {
 	STATE_INIT = 0,
@@ -500,73 +470,70 @@
 	EFX_FC_AUTO = 4,
 };
 
-/* Supported MAC bit-mask */
-enum efx_mac_type {
-	EFX_GMAC = 1,
-	EFX_XMAC = 2,
+/**
+ * struct efx_link_state - Current state of the link
+ * @up: Link is up
+ * @fd: Link is full-duplex
+ * @fc: Actual flow control flags
+ * @speed: Link speed (Mbps)
+ */
+struct efx_link_state {
+	bool up;
+	bool fd;
+	enum efx_fc_type fc;
+	unsigned int speed;
 };
 
-static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
-					      unsigned int lpa)
+static inline bool efx_link_state_equal(const struct efx_link_state *left,
+					const struct efx_link_state *right)
 {
-	BUILD_BUG_ON(EFX_FC_AUTO & (EFX_FC_RX | EFX_FC_TX));
-
-	if (!(wanted_fc & EFX_FC_AUTO))
-		return wanted_fc;
-
-	return mii_resolve_flowctrl_fdx(mii_advertise_flowctrl(wanted_fc), lpa);
+	return left->up == right->up && left->fd == right->fd &&
+		left->fc == right->fc && left->speed == right->speed;
 }
 
 /**
  * struct efx_mac_operations - Efx MAC operations table
  * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
  * @update_stats: Update statistics
- * @irq: Hardware MAC event callback. Serialised by the mac_lock
- * @poll: Poll for hardware state. Serialised by the mac_lock
+ * @check_fault: Check fault state. True if fault present.
  */
 struct efx_mac_operations {
-	void (*reconfigure) (struct efx_nic *efx);
+	int (*reconfigure) (struct efx_nic *efx);
 	void (*update_stats) (struct efx_nic *efx);
-	void (*irq) (struct efx_nic *efx);
-	void (*poll) (struct efx_nic *efx);
+	bool (*check_fault)(struct efx_nic *efx);
 };
 
 /**
  * struct efx_phy_operations - Efx PHY operations table
+ * @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds,
+ *	efx->loopback_modes.
  * @init: Initialise PHY
  * @fini: Shut down PHY
  * @reconfigure: Reconfigure PHY (e.g. for new link parameters)
- * @clear_interrupt: Clear down interrupt
- * @blink: Blink LEDs
- * @poll: Poll for hardware state. Serialised by the mac_lock.
+ * @poll: Update @link_state and report whether it changed.
+ *	Serialised by the mac_lock.
  * @get_settings: Get ethtool settings. Serialised by the mac_lock.
  * @set_settings: Set ethtool settings. Serialised by the mac_lock.
  * @set_npage_adv: Set abilities advertised in (Extended) Next Page
  *	(only needed where AN bit is set in mmds)
- * @num_tests: Number of PHY-specific tests/results
- * @test_names: Names of the tests/results
+ * @test_name: Get the name of a PHY-specific test/result
  * @run_tests: Run tests and record results as appropriate.
  *	Flags are the ethtool tests flags.
- * @mmds: MMD presence mask
- * @loopbacks: Supported loopback modes mask
  */
 struct efx_phy_operations {
-	enum efx_mac_type macs;
+	int (*probe) (struct efx_nic *efx);
 	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);
-	void (*poll) (struct efx_nic *efx);
+	void (*remove) (struct efx_nic *efx);
+	int (*reconfigure) (struct efx_nic *efx);
+	bool (*poll) (struct efx_nic *efx);
 	void (*get_settings) (struct efx_nic *efx,
 			      struct ethtool_cmd *ecmd);
 	int (*set_settings) (struct efx_nic *efx,
 			     struct ethtool_cmd *ecmd);
 	void (*set_npage_adv) (struct efx_nic *efx, u32);
-	u32 num_tests;
-	const char *const *test_names;
+	const char *(*test_name) (struct efx_nic *efx, unsigned int index);
 	int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
-	int mmds;
-	unsigned loopbacks;
 };
 
 /**
@@ -690,36 +657,38 @@
  * @interrupt_mode: Interrupt mode
  * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
  * @irq_rx_moderation: IRQ moderation time for RX event queues
- * @i2c_adap: I2C adapter
- * @board_info: Board-level information
  * @state: Device state flag. Serialised by the rtnl_lock.
  * @reset_pending: Pending reset method (normally RESET_TYPE_NONE)
  * @tx_queue: TX DMA queues
  * @rx_queue: RX DMA queues
  * @channel: Channels
+ * @next_buffer_table: First available buffer table id
  * @n_rx_queues: Number of RX queues
  * @n_channels: Number of channels in use
  * @rx_buffer_len: RX buffer length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
+ * @int_error_count: Number of internal errors seen recently
+ * @int_error_expire: Time at which error count will be expired
  * @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.
+ *	This field will be %NULL if no flash device is present (or for Siena).
  * @spi_eeprom: SPI EEPROM device
- *	This field will be %NULL if no EEPROM device is present.
+ *	This field will be %NULL if no EEPROM device is present (or for Siena).
  * @spi_lock: SPI bus lock
+ * @mtd_list: List of MTDs attached to the NIC
  * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
  * @nic_data: Hardware dependant state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
  *	@port_inhibited, efx_monitor() and efx_reconfigure_port()
  * @port_enabled: Port enabled indicator.
- *	Serialises efx_stop_all(), efx_start_all(), efx_monitor(),
- *	efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read
- *	under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all
- *	three must be held to modify it.
+ *	Serialises efx_stop_all(), efx_start_all(), efx_monitor() and
+ *	efx_mac_work() with kernel interfaces. Safe to read under any
+ *	one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
+ *	be held to modify it.
  * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
  * @port_initialized: Port initialized?
  * @net_dev: Operating system network device. Consider holding the rtnl lock
@@ -731,26 +700,23 @@
  *	&struct net_device_stats.
  * @stats_buffer: DMA buffer for statistics
  * @stats_lock: Statistics update lock. Serialises statistics fetches
- * @stats_disable_count: Nest count for disabling statistics fetches
  * @mac_op: MAC interface
  * @mac_address: Permanent MAC address
  * @phy_type: PHY type
- * @phy_lock: PHY access lock
+ * @mdio_lock: MDIO lock
  * @phy_op: PHY interface
  * @phy_data: PHY private data (including PHY-specific stats)
  * @mdio: PHY MDIO interface
+ * @mdio_bus: PHY MDIO bus ID (only used by Siena)
  * @phy_mode: PHY operating mode. Serialised by @mac_lock.
- * @mac_up: MAC link state
- * @link_up: Link status
- * @link_fd: Link is full duplex
- * @link_fc: Actualy flow control flags
- * @link_speed: Link speed (Mbps)
+ * @xmac_poll_required: XMAC link state needs polling
+ * @link_advertising: Autonegotiation advertising flags
+ * @link_state: Current state of the link
  * @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
  * @wanted_fc: Wanted flow control flags
- * @phy_work: work item for dealing with PHY events
- * @mac_work: work item for dealing with MAC events
+ * @mac_work: Work item for changing MAC promiscuity and multicast hash
  * @loopback_mode: Loopback status
  * @loopback_modes: Supported loopback mode bitmask
  * @loopback_selftest: Offline self-test private state
@@ -774,9 +740,6 @@
 	bool irq_rx_adaptive;
 	unsigned int irq_rx_moderation;
 
-	struct i2c_adapter i2c_adap;
-	struct efx_board board_info;
-
 	enum nic_state state;
 	enum reset_type reset_pending;
 
@@ -784,21 +747,29 @@
 	struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES];
 	struct efx_channel channel[EFX_MAX_CHANNELS];
 
+	unsigned next_buffer_table;
 	int n_rx_queues;
 	int n_channels;
 	unsigned int rx_buffer_len;
 	unsigned int rx_buffer_order;
 
+	unsigned int_error_count;
+	unsigned long int_error_expire;
+
 	struct efx_buffer irq_status;
 	volatile signed int last_irq_cpu;
+	unsigned long irq_zero_count;
 
 	struct efx_spi_device *spi_flash;
 	struct efx_spi_device *spi_eeprom;
 	struct mutex spi_lock;
+#ifdef CONFIG_SFC_MTD
+	struct list_head mtd_list;
+#endif
 
 	unsigned n_rx_nodesc_drop_cnt;
 
-	struct falcon_nic_data *nic_data;
+	void *nic_data;
 
 	struct mutex mac_lock;
 	struct work_struct mac_work;
@@ -815,24 +786,21 @@
 	struct efx_mac_stats mac_stats;
 	struct efx_buffer stats_buffer;
 	spinlock_t stats_lock;
-	unsigned int stats_disable_count;
 
 	struct efx_mac_operations *mac_op;
 	unsigned char mac_address[ETH_ALEN];
 
-	enum phy_type phy_type;
-	spinlock_t phy_lock;
-	struct work_struct phy_work;
+	unsigned int phy_type;
+	struct mutex mdio_lock;
 	struct efx_phy_operations *phy_op;
 	void *phy_data;
 	struct mdio_if_info mdio;
+	unsigned int mdio_bus;
 	enum efx_phy_mode phy_mode;
 
-	bool mac_up;
-	bool link_up;
-	bool link_fd;
-	enum efx_fc_type link_fc;
-	unsigned int link_speed;
+	bool xmac_poll_required;
+	u32 link_advertising;
+	struct efx_link_state link_state;
 	unsigned int n_link_state_changes;
 
 	bool promiscuous;
@@ -841,7 +809,7 @@
 
 	atomic_t rx_reset;
 	enum efx_loopback_mode loopback_mode;
-	unsigned int loopback_modes;
+	u64 loopback_modes;
 
 	void *loopback_selftest;
 };
@@ -860,50 +828,95 @@
 	return efx_dev_registered(efx) ? efx->name : "";
 }
 
+static inline unsigned int efx_port_num(struct efx_nic *efx)
+{
+	return PCI_FUNC(efx->pci_dev->devfn);
+}
+
 /**
  * struct efx_nic_type - Efx device type definition
- * @mem_bar: Memory BAR number
+ * @probe: Probe the controller
+ * @remove: Free resources allocated by probe()
+ * @init: Initialise the controller
+ * @fini: Shut down the controller
+ * @monitor: Periodic function for polling link state and hardware monitor
+ * @reset: Reset the controller hardware and possibly the PHY.  This will
+ *	be called while the controller is uninitialised.
+ * @probe_port: Probe the MAC and PHY
+ * @remove_port: Free resources allocated by probe_port()
+ * @prepare_flush: Prepare the hardware for flushing the DMA queues
+ * @update_stats: Update statistics not provided by event handling
+ * @start_stats: Start the regular fetching of statistics
+ * @stop_stats: Stop the regular fetching of statistics
+ * @set_id_led: Set state of identifying LED or revert to automatic function
+ * @push_irq_moderation: Apply interrupt moderation value
+ * @push_multicast_hash: Apply multicast hash table
+ * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY
+ * @get_wol: Get WoL configuration from driver state
+ * @set_wol: Push WoL configuration to the NIC
+ * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume)
+ * @test_registers: Test read/write functionality of control registers
+ * @test_nvram: Test validity of NVRAM contents
+ * @default_mac_ops: efx_mac_operations to set at startup
+ * @revision: Hardware architecture revision
  * @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
+ * @tx_dc_base: Base address in SRAM of TX queue descriptor caches
+ * @rx_dc_base: Base address in SRAM of RX queue descriptor caches
+ * @offload_features: net_device feature flags for protocol offload
+ *	features implemented in hardware
+ * @reset_world_flags: Flags for additional components covered by
+ *	reset method RESET_TYPE_WORLD
  */
 struct efx_nic_type {
-	unsigned int mem_bar;
+	int (*probe)(struct efx_nic *efx);
+	void (*remove)(struct efx_nic *efx);
+	int (*init)(struct efx_nic *efx);
+	void (*fini)(struct efx_nic *efx);
+	void (*monitor)(struct efx_nic *efx);
+	int (*reset)(struct efx_nic *efx, enum reset_type method);
+	int (*probe_port)(struct efx_nic *efx);
+	void (*remove_port)(struct efx_nic *efx);
+	void (*prepare_flush)(struct efx_nic *efx);
+	void (*update_stats)(struct efx_nic *efx);
+	void (*start_stats)(struct efx_nic *efx);
+	void (*stop_stats)(struct efx_nic *efx);
+	void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode);
+	void (*push_irq_moderation)(struct efx_channel *channel);
+	void (*push_multicast_hash)(struct efx_nic *efx);
+	int (*reconfigure_port)(struct efx_nic *efx);
+	void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol);
+	int (*set_wol)(struct efx_nic *efx, u32 type);
+	void (*resume_wol)(struct efx_nic *efx);
+	int (*test_registers)(struct efx_nic *efx);
+	int (*test_nvram)(struct efx_nic *efx);
+	struct efx_mac_operations *default_mac_ops;
+
+	int revision;
 	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;
 	u64 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;
+	unsigned int tx_dc_base;
+	unsigned int rx_dc_base;
+	unsigned long offload_features;
+	u32 reset_world_flags;
 };
 
 /**************************************************************************
--- linux-ec2-2.6.32.orig/drivers/net/sfc/ethtool.c
+++ linux-ec2-2.6.32/drivers/net/sfc/ethtool.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -10,30 +10,15 @@
 
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
-#include <linux/mdio.h>
 #include <linux/rtnetlink.h>
 #include "net_driver.h"
 #include "workarounds.h"
 #include "selftest.h"
 #include "efx.h"
-#include "ethtool.h"
-#include "falcon.h"
+#include "nic.h"
 #include "spi.h"
 #include "mdio_10g.h"
 
-const char *efx_loopback_mode_names[] = {
-	[LOOPBACK_NONE]		= "NONE",
-	[LOOPBACK_GMAC]		= "GMAC",
-	[LOOPBACK_XGMII]	= "XGMII",
-	[LOOPBACK_XGXS]		= "XGXS",
-	[LOOPBACK_XAUI] 	= "XAUI",
-	[LOOPBACK_GPHY]		= "GPHY",
-	[LOOPBACK_PHYXS]	= "PHYXS",
-	[LOOPBACK_PCS]	 	= "PCS",
-	[LOOPBACK_PMAPMD]	= "PMA/PMD",
-	[LOOPBACK_NETWORK]	= "NETWORK",
-};
-
 struct ethtool_string {
 	char name[ETH_GSTRING_LEN];
 };
@@ -167,6 +152,7 @@
 	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_mcast_mismatch),
 	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
 };
 
@@ -187,13 +173,15 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
-	efx->board_info.blink(efx, 1);
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (count)
-		schedule_timeout(count * HZ);
-	else
-		schedule();
-	efx->board_info.blink(efx, 0);
+	do {
+		efx->type->set_id_led(efx, EFX_LED_ON);
+		schedule_timeout_interruptible(HZ / 2);
+
+		efx->type->set_id_led(efx, EFX_LED_OFF);
+		schedule_timeout_interruptible(HZ / 2);
+	} while (!signal_pending(current) && --count != 0);
+
+	efx->type->set_id_led(efx, EFX_LED_DEFAULT);
 	return 0;
 }
 
@@ -202,6 +190,7 @@
 			     struct ethtool_cmd *ecmd)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_link_state *link_state = &efx->link_state;
 
 	mutex_lock(&efx->mac_lock);
 	efx->phy_op->get_settings(efx, ecmd);
@@ -209,6 +198,13 @@
 
 	/* Falcon GMAC does not support 1000Mbps HD */
 	ecmd->supported &= ~SUPPORTED_1000baseT_Half;
+	/* Both MACs support pause frames (bidirectional and respond-only) */
+	ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+
+	if (LOOPBACK_INTERNAL(efx)) {
+		ecmd->speed = link_state->speed;
+		ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF;
+	}
 
 	return 0;
 }
@@ -230,9 +226,6 @@
 	mutex_lock(&efx->mac_lock);
 	rc = efx->phy_op->set_settings(efx, ecmd);
 	mutex_unlock(&efx->mac_lock);
-	if (!rc)
-		efx_reconfigure_port(efx);
-
 	return rc;
 }
 
@@ -243,6 +236,9 @@
 
 	strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver));
 	strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
+		siena_print_fwver(efx, info->fw_version,
+				  sizeof(info->fw_version));
 	strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
@@ -289,7 +285,7 @@
 #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
 #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
 #define EFX_LOOPBACK_NAME(_mode, _counter)			\
-	"loopback.%s." _counter, LOOPBACK_MODE_NAME(mode)
+	"loopback.%s." _counter, STRING_TABLE_LOOKUP(_mode, efx_loopback_mode)
 
 /**
  * efx_fill_loopback_test - fill in a block of loopback self-test entries
@@ -372,9 +368,21 @@
 	efx_fill_test(n++, strings, data, &tests->registers,
 		      "core", 0, "registers", NULL);
 
-	for (i = 0; i < efx->phy_op->num_tests; i++)
-		efx_fill_test(n++, strings, data, &tests->phy[i],
-			      "phy", 0, efx->phy_op->test_names[i], NULL);
+	if (efx->phy_op->run_tests != NULL) {
+		EFX_BUG_ON_PARANOID(efx->phy_op->test_name == NULL);
+
+		for (i = 0; true; ++i) {
+			const char *name;
+
+			EFX_BUG_ON_PARANOID(i >= EFX_MAX_PHY_TESTS);
+			name = efx->phy_op->test_name(efx, i);
+			if (name == NULL)
+				break;
+
+			efx_fill_test(n++, strings, data, &tests->phy[i],
+				      "phy", 0, name, NULL);
+		}
+	}
 
 	/* Loopback tests */
 	for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
@@ -463,6 +471,36 @@
 	}
 }
 
+static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
+{
+	struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev);
+	unsigned long features;
+
+	features = NETIF_F_TSO;
+	if (efx->type->offload_features & NETIF_F_V6_CSUM)
+		features |= NETIF_F_TSO6;
+
+	if (enable)
+		net_dev->features |= features;
+	else
+		net_dev->features &= ~features;
+
+	return 0;
+}
+
+static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	unsigned long features = efx->type->offload_features & NETIF_F_ALL_CSUM;
+
+	if (enable)
+		net_dev->features |= features;
+	else
+		net_dev->features &= ~features;
+
+	return 0;
+}
+
 static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
@@ -537,7 +575,7 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
-	return efx->link_up;
+	return efx->link_state.up;
 }
 
 static int efx_ethtool_get_eeprom_len(struct net_device *net_dev)
@@ -562,7 +600,8 @@
 	rc = mutex_lock_interruptible(&efx->spi_lock);
 	if (rc)
 		return rc;
-	rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
+	rc = falcon_spi_read(efx, spi,
+			     eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			     eeprom->len, &len, buf);
 	mutex_unlock(&efx->spi_lock);
 
@@ -585,7 +624,8 @@
 	rc = mutex_lock_interruptible(&efx->spi_lock);
 	if (rc)
 		return rc;
-	rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
+	rc = falcon_spi_write(efx, spi,
+			      eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
 			      eeprom->len, &len, buf);
 	mutex_unlock(&efx->spi_lock);
 
@@ -618,6 +658,9 @@
 	coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive;
 	coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation;
 
+	coalesce->tx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION;
+	coalesce->rx_coalesce_usecs_irq *= EFX_IRQ_MOD_RESOLUTION;
+
 	return 0;
 }
 
@@ -656,13 +699,8 @@
 	}
 
 	efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive);
-
-	/* 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);
+		efx->type->push_irq_moderation(channel);
 
 	return 0;
 }
@@ -671,8 +709,12 @@
 				      struct ethtool_pauseparam *pause)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	enum efx_fc_type wanted_fc;
+	enum efx_fc_type wanted_fc, old_fc;
+	u32 old_adv;
 	bool reset;
+	int rc = 0;
+
+	mutex_lock(&efx->mac_lock);
 
 	wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) |
 		     (pause->tx_pause ? EFX_FC_TX : 0) |
@@ -680,14 +722,14 @@
 
 	if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) {
 		EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out;
 	}
 
-	if (!(efx->phy_op->mmds & MDIO_DEVS_AN) &&
-	    (wanted_fc & EFX_FC_AUTO)) {
-		EFX_LOG(efx, "PHY does not support flow control "
-			"autonegotiation\n");
-		return -EINVAL;
+	if ((wanted_fc & EFX_FC_AUTO) && !efx->link_advertising) {
+		EFX_LOG(efx, "Autonegotiation is disabled\n");
+		rc = -EINVAL;
+		goto out;
 	}
 
 	/* TX flow control may automatically turn itself off if the
@@ -697,27 +739,40 @@
 	 * and fix it be cycling transmit flow control on this end. */
 	reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX);
 	if (EFX_WORKAROUND_11482(efx) && reset) {
-		if (falcon_rev(efx) >= FALCON_REV_B0) {
+		if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) {
 			/* Recover by resetting the EM block */
-			if (efx->link_up)
-				falcon_drain_tx_fifo(efx);
+			falcon_stop_nic_stats(efx);
+			falcon_drain_tx_fifo(efx);
+			efx->mac_op->reconfigure(efx);
+			falcon_start_nic_stats(efx);
 		} else {
 			/* Schedule a reset to recover */
 			efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
 		}
 	}
 
-	/* Try to push the pause parameters */
-	mutex_lock(&efx->mac_lock);
+	old_adv = efx->link_advertising;
+	old_fc = efx->wanted_fc;
+	efx_link_set_wanted_fc(efx, wanted_fc);
+	if (efx->link_advertising != old_adv ||
+	    (efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) {
+		rc = efx->phy_op->reconfigure(efx);
+		if (rc) {
+			EFX_ERR(efx, "Unable to advertise requested flow "
+				"control setting\n");
+			goto out;
+		}
+	}
 
-	efx->wanted_fc = wanted_fc;
-	if (efx->phy_op->mmds & MDIO_DEVS_AN)
-		mdio45_ethtool_spauseparam_an(&efx->mdio, pause);
-	__efx_reconfigure_port(efx);
+	/* Reconfigure the MAC. The PHY *may* generate a link state change event
+	 * if the user just changed the advertised capabilities, but there's no
+	 * harm doing this twice */
+	efx->mac_op->reconfigure(efx);
 
+out:
 	mutex_unlock(&efx->mac_lock);
 
-	return 0;
+	return rc;
 }
 
 static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
@@ -731,6 +786,50 @@
 }
 
 
+static void efx_ethtool_get_wol(struct net_device *net_dev,
+				struct ethtool_wolinfo *wol)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	return efx->type->get_wol(efx, wol);
+}
+
+
+static int efx_ethtool_set_wol(struct net_device *net_dev,
+			       struct ethtool_wolinfo *wol)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	return efx->type->set_wol(efx, wol->wolopts);
+}
+
+extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	enum reset_type method;
+	enum {
+		ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER |
+					   ETH_RESET_OFFLOAD | ETH_RESET_MAC)
+	};
+
+	/* Check for minimal reset flags */
+	if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE)
+		return -EINVAL;
+	*flags ^= ETH_RESET_EFX_INVISIBLE;
+	method = RESET_TYPE_INVISIBLE;
+
+	if (*flags & ETH_RESET_PHY) {
+		*flags ^= ETH_RESET_PHY;
+		method = RESET_TYPE_ALL;
+	}
+
+	if ((*flags & efx->type->reset_world_flags) ==
+	    efx->type->reset_world_flags) {
+		*flags ^= efx->type->reset_world_flags;
+		method = RESET_TYPE_WORLD;
+	}
+
+	return efx_reset(efx, method);
+}
+
 const struct ethtool_ops efx_ethtool_ops = {
 	.get_settings		= efx_ethtool_get_settings,
 	.set_settings		= efx_ethtool_set_settings,
@@ -747,11 +846,13 @@
 	.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		= ethtool_op_set_tx_csum,
+	/* Need to enable/disable IPv6 too */
+	.set_tx_csum		= efx_ethtool_set_tx_csum,
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
 	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= ethtool_op_set_tso,
+	/* Need to enable/disable TSO-IPv6 too */
+	.set_tso		= efx_ethtool_set_tso,
 	.get_flags		= ethtool_op_get_flags,
 	.set_flags		= ethtool_op_set_flags,
 	.get_sset_count		= efx_ethtool_get_sset_count,
@@ -759,4 +860,7 @@
 	.get_strings		= efx_ethtool_get_strings,
 	.phys_id		= efx_ethtool_phys_id,
 	.get_ethtool_stats	= efx_ethtool_get_stats,
+	.get_wol                = efx_ethtool_get_wol,
+	.set_wol                = efx_ethtool_set_wol,
+	.reset			= efx_ethtool_reset,
 };
--- linux-ec2-2.6.32.orig/drivers/net/sfc/io.h
+++ linux-ec2-2.6.32/drivers/net/sfc/io.h
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+
+#ifndef EFX_IO_H
+#define EFX_IO_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+/**************************************************************************
+ *
+ * NIC register I/O
+ *
+ **************************************************************************
+ *
+ * Notes on locking strategy:
+ *
+ * Most NIC registers require 16-byte (or 8-byte, for SRAM) atomic writes
+ * which necessitates locking.
+ * Under normal operation few writes to NIC registers 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 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).
+ */
+
+#if BITS_PER_LONG == 64
+#define EFX_USE_QWORD_IO 1
+#endif
+
+#ifdef EFX_USE_QWORD_IO
+static inline void _efx_writeq(struct efx_nic *efx, __le64 value,
+				  unsigned int reg)
+{
+	__raw_writeq((__force u64)value, efx->membase + reg);
+}
+static inline __le64 _efx_readq(struct efx_nic *efx, unsigned int reg)
+{
+	return (__force __le64)__raw_readq(efx->membase + reg);
+}
+#endif
+
+static inline void _efx_writed(struct efx_nic *efx, __le32 value,
+				  unsigned int reg)
+{
+	__raw_writel((__force u32)value, efx->membase + reg);
+}
+static inline __le32 _efx_readd(struct efx_nic *efx, unsigned int reg)
+{
+	return (__force __le32)__raw_readl(efx->membase + reg);
+}
+
+/* Writes to a normal 16-byte Efx register, locking as appropriate. */
+static inline void efx_writeo(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 EFX_USE_QWORD_IO
+	_efx_writeq(efx, value->u64[0], reg + 0);
+	wmb();
+	_efx_writeq(efx, value->u64[1], reg + 8);
+#else
+	_efx_writed(efx, value->u32[0], reg + 0);
+	_efx_writed(efx, value->u32[1], reg + 4);
+	_efx_writed(efx, value->u32[2], reg + 8);
+	wmb();
+	_efx_writed(efx, value->u32[3], reg + 12);
+#endif
+	mmiowb();
+	spin_unlock_irqrestore(&efx->biu_lock, flags);
+}
+
+/* Write an 8-byte NIC SRAM entry through the supplied mapping,
+ * locking as appropriate. */
+static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase,
+				   efx_qword_t *value, unsigned int index)
+{
+	unsigned int addr = index * sizeof(*value);
+	unsigned long flags __attribute__ ((unused));
+
+	EFX_REGDUMP(efx, "writing SRAM address %x with " EFX_QWORD_FMT "\n",
+		    addr, EFX_QWORD_VAL(*value));
+
+	spin_lock_irqsave(&efx->biu_lock, flags);
+#ifdef EFX_USE_QWORD_IO
+	__raw_writeq((__force u64)value->u64[0], membase + addr);
+#else
+	__raw_writel((__force u32)value->u32[0], membase + addr);
+	wmb();
+	__raw_writel((__force u32)value->u32[1], membase + addr + 4);
+#endif
+	mmiowb();
+	spin_unlock_irqrestore(&efx->biu_lock, flags);
+}
+
+/* Write dword to NIC register that allows partial writes
+ *
+ * Some 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 efx_writed(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 */
+	_efx_writed(efx, value->u32[0], reg);
+}
+
+/* Read from a NIC register
+ *
+ * This reads an entire 16-byte register in one go, locking as
+ * appropriate.  It is essential to read the first dword first, as this
+ * prompts the NIC to load the current value into the shadow register.
+ */
+static inline void efx_reado(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] = _efx_readd(efx, reg + 0);
+	rmb();
+	value->u32[1] = _efx_readd(efx, reg + 4);
+	value->u32[2] = _efx_readd(efx, reg + 8);
+	value->u32[3] = _efx_readd(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));
+}
+
+/* Read an 8-byte SRAM entry through supplied mapping,
+ * locking as appropriate. */
+static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
+				  efx_qword_t *value, unsigned int index)
+{
+	unsigned int addr = index * sizeof(*value);
+	unsigned long flags __attribute__ ((unused));
+
+	spin_lock_irqsave(&efx->biu_lock, flags);
+#ifdef EFX_USE_QWORD_IO
+	value->u64[0] = (__force __le64)__raw_readq(membase + addr);
+#else
+	value->u32[0] = (__force __le32)__raw_readl(membase + addr);
+	rmb();
+	value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
+#endif
+	spin_unlock_irqrestore(&efx->biu_lock, flags);
+
+	EFX_REGDUMP(efx, "read from SRAM address %x, got "EFX_QWORD_FMT"\n",
+		    addr, EFX_QWORD_VAL(*value));
+}
+
+/* Read dword from register that allows partial writes (sic) */
+static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value,
+				unsigned int reg)
+{
+	value->u32[0] = _efx_readd(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 efx_writeo_table(struct efx_nic *efx, efx_oword_t *value,
+				      unsigned int reg, unsigned int index)
+{
+	efx_writeo(efx, value, reg + index * sizeof(efx_oword_t));
+}
+
+/* Read to a register forming part of a table */
+static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
+				     unsigned int reg, unsigned int index)
+{
+	efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
+}
+
+/* Write to a dword register forming part of a table */
+static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value,
+				       unsigned int reg, unsigned int index)
+{
+	efx_writed(efx, value, reg + index * sizeof(efx_oword_t));
+}
+
+/* Page-mapped register block size */
+#define EFX_PAGE_BLOCK_SIZE 0x2000
+
+/* Calculate offset to page-mapped register block */
+#define EFX_PAGED_REG(page, reg) \
+	((page) * EFX_PAGE_BLOCK_SIZE + (reg))
+
+/* As for efx_writeo(), but for a page-mapped register. */
+static inline void efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
+				   unsigned int reg, unsigned int page)
+{
+	efx_writeo(efx, value, EFX_PAGED_REG(page, reg));
+}
+
+/* As for efx_writed(), but for a page-mapped register. */
+static inline void efx_writed_page(struct efx_nic *efx, efx_dword_t *value,
+				   unsigned int reg, unsigned int page)
+{
+	efx_writed(efx, value, EFX_PAGED_REG(page, reg));
+}
+
+/* Write dword to page-mapped register with an extra lock.
+ *
+ * As for efx_writed_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 efx_writed_page_locked(struct efx_nic *efx,
+					  efx_dword_t *value,
+					  unsigned int reg,
+					  unsigned int page)
+{
+	unsigned long flags __attribute__ ((unused));
+
+	if (page == 0) {
+		spin_lock_irqsave(&efx->biu_lock, flags);
+		efx_writed(efx, value, EFX_PAGED_REG(page, reg));
+		spin_unlock_irqrestore(&efx->biu_lock, flags);
+	} else {
+		efx_writed(efx, value, EFX_PAGED_REG(page, reg));
+	}
+}
+
+#endif /* EFX_IO_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/tenxpress.c
+++ linux-ec2-2.6.32/drivers/net/sfc/tenxpress.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2008 Solarflare Communications Inc.
+ * Copyright 2007-2009 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
@@ -12,10 +12,9 @@
 #include <linux/seq_file.h>
 #include "efx.h"
 #include "mdio_10g.h"
-#include "falcon.h"
+#include "nic.h"
 #include "phy.h"
-#include "falcon_hwdefs.h"
-#include "boards.h"
+#include "regs.h"
 #include "workarounds.h"
 #include "selftest.h"
 
@@ -31,13 +30,13 @@
 #define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) |	\
 			   (1 << LOOPBACK_PCS) |	\
 			   (1 << LOOPBACK_PMAPMD) |	\
-			   (1 << LOOPBACK_NETWORK))
+			   (1 << LOOPBACK_PHYXS_WS))
 
 #define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) |	\
 			   (1 << LOOPBACK_PHYXS) |	\
 			   (1 << LOOPBACK_PCS) |	\
 			   (1 << LOOPBACK_PMAPMD) |	\
-			   (1 << LOOPBACK_NETWORK))
+			   (1 << LOOPBACK_PHYXS_WS))
 
 /* 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)
@@ -84,9 +83,9 @@
 #define PMA_PMD_LED_FLASH	(3)
 #define PMA_PMD_LED_MASK	3
 /* All LEDs under hardware control */
-#define PMA_PMD_LED_FULL_AUTO	(0)
+#define SFT9001_PMA_PMD_LED_DEFAULT 0
 /* Green and Amber under hardware control, Red off */
-#define PMA_PMD_LED_DEFAULT	(PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
+#define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
 
 #define PMA_PMD_SPEED_ENABLE_REG 49192
 #define PMA_PMD_100TX_ADV_LBN    1
@@ -200,15 +199,20 @@
 				   const char *buf, size_t count)
 {
 	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+	int rc;
 
 	rtnl_lock();
-	efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
-			  MDIO_PMA_10GBT_TXPWR_SHORT,
-			  count != 0 && *buf != '0');
-	efx_reconfigure_port(efx);
+	if (efx->state != STATE_RUNNING) {
+		rc = -EBUSY;
+	} else {
+		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR,
+				  MDIO_PMA_10GBT_TXPWR_SHORT,
+				  count != 0 && *buf != '0');
+		rc = efx_reconfigure_port(efx);
+	}
 	rtnl_unlock();
 
-	return count;
+	return rc < 0 ? rc : (ssize_t)count;
 }
 
 static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
@@ -292,23 +296,68 @@
 		efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG,
 				  1 << PMA_PMA_LED_ACTIVITY_LBN, true);
 		efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG,
-			       PMA_PMD_LED_DEFAULT);
+			       SFX7101_PMA_PMD_LED_DEFAULT);
 	}
 
 	return 0;
 }
 
-static int tenxpress_phy_init(struct efx_nic *efx)
+static int tenxpress_phy_probe(struct efx_nic *efx)
 {
 	struct tenxpress_phy_data *phy_data;
-	int rc = 0;
+	int rc;
 
+	/* Allocate phy private storage */
 	phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
 	if (!phy_data)
 		return -ENOMEM;
 	efx->phy_data = phy_data;
 	phy_data->phy_mode = efx->phy_mode;
 
+	/* Create any special files */
+	if (efx->phy_type == PHY_TYPE_SFT9001B) {
+		rc = device_create_file(&efx->pci_dev->dev,
+					&dev_attr_phy_short_reach);
+		if (rc)
+			goto fail;
+	}
+
+	if (efx->phy_type == PHY_TYPE_SFX7101) {
+		efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+		efx->mdio.mode_support = MDIO_SUPPORTS_C45;
+
+		efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS;
+
+		efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+					 ADVERTISED_10000baseT_Full);
+	} else {
+		efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS;
+		efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+		efx->loopback_modes = (SFT9001_LOOPBACKS |
+				       FALCON_XMAC_LOOPBACKS | 
+				       FALCON_GMAC_LOOPBACKS);
+
+		efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg |
+					 ADVERTISED_10000baseT_Full |
+					 ADVERTISED_1000baseT_Full |
+					 ADVERTISED_100baseT_Full);
+	}
+
+	return 0;
+
+fail:
+	kfree(efx->phy_data);
+	efx->phy_data = NULL;
+	return rc;
+}
+
+static int tenxpress_phy_init(struct efx_nic *efx)
+{
+	int rc;
+
+	falcon_board(efx)->type->init_phy(efx);
+
 	if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
 		if (efx->phy_type == PHY_TYPE_SFT9001A) {
 			int reg;
@@ -322,23 +371,20 @@
 
 		rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 		if (rc < 0)
-			goto fail;
+			return rc;
 
 		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
 		if (rc < 0)
-			goto fail;
+			return rc;
 	}
 
 	rc = tenxpress_init(efx);
 	if (rc < 0)
-		goto fail;
+		return rc;
 
-	if (efx->phy_type == PHY_TYPE_SFT9001B) {
-		rc = device_create_file(&efx->pci_dev->dev,
-					&dev_attr_phy_short_reach);
-		if (rc)
-			goto fail;
-	}
+	/* Reinitialise flow control settings */
+	efx_link_set_wanted_fc(efx, efx->wanted_fc);
+	efx_mdio_an_reconfigure(efx);
 
 	schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
 
@@ -346,11 +392,6 @@
 	falcon_reset_xaui(efx);
 
 	return 0;
-
- fail:
-	kfree(efx->phy_data);
-	efx->phy_data = NULL;
-	return rc;
 }
 
 /* Perform a "special software reset" on the PHY. The caller is
@@ -363,7 +404,7 @@
 	/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
 	 * a special software reset can glitch the XGMAC sufficiently for stats
 	 * requests to fail. */
-	efx_stats_disable(efx);
+	falcon_stop_nic_stats(efx);
 
 	/* Initiate reset */
 	reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
@@ -385,7 +426,7 @@
 	/* Wait for the XGXS state machine to churn */
 	mdelay(10);
 out:
-	efx_stats_enable(efx);
+	falcon_start_nic_stats(efx);
 	return rc;
 }
 
@@ -489,133 +530,126 @@
 			!!(efx->phy_mode & PHY_MODE_LOW_POWER));
 }
 
-static void tenxpress_phy_reconfigure(struct efx_nic *efx)
+static int tenxpress_phy_reconfigure(struct efx_nic *efx)
 {
 	struct tenxpress_phy_data *phy_data = efx->phy_data;
-	struct ethtool_cmd ecmd;
 	bool phy_mode_change, loop_reset;
 
 	if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
 		phy_data->phy_mode = efx->phy_mode;
-		return;
+		return 0;
 	}
 
-	tenxpress_low_power(efx);
-
 	phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
 			   phy_data->phy_mode != PHY_MODE_NORMAL);
-	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
+	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, LOOPBACKS_EXTERNAL(efx)) ||
 		      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
 
 	if (loop_reset || phy_mode_change) {
-		int rc;
-
-		efx->phy_op->get_settings(efx, &ecmd);
-
-		if (loop_reset || phy_mode_change) {
-			tenxpress_special_reset(efx);
+		tenxpress_special_reset(efx);
 
-			/* Reset XAUI if we were in 10G, and are staying
-			 * in 10G. If we're moving into and out of 10G
-			 * then xaui will be reset anyway */
-			if (EFX_IS10G(efx))
-				falcon_reset_xaui(efx);
-		}
-
-		rc = efx->phy_op->set_settings(efx, &ecmd);
-		WARN_ON(rc);
+		/* Reset XAUI if we were in 10G, and are staying
+		 * in 10G. If we're moving into and out of 10G
+		 * then xaui will be reset anyway */
+		if (EFX_IS10G(efx))
+			falcon_reset_xaui(efx);
 	}
 
+	tenxpress_low_power(efx);
 	efx_mdio_transmit_disable(efx);
 	efx_mdio_phy_reconfigure(efx);
 	tenxpress_ext_loopback(efx);
+	efx_mdio_an_reconfigure(efx);
 
 	phy_data->loopback_mode = efx->loopback_mode;
 	phy_data->phy_mode = efx->phy_mode;
 
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		efx->link_speed = 10000;
-		efx->link_fd = true;
-		efx->link_up = sfx7101_link_ok(efx);
-	} else {
-		efx->phy_op->get_settings(efx, &ecmd);
-		efx->link_speed = ecmd.speed;
-		efx->link_fd = ecmd.duplex == DUPLEX_FULL;
-		efx->link_up = sft9001_link_ok(efx, &ecmd);
-	}
-	efx->link_fc = efx_mdio_get_pause(efx);
+	return 0;
 }
 
-/* Poll PHY for interrupt */
-static void tenxpress_phy_poll(struct efx_nic *efx)
+static void
+tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+
+/* Poll for link state changes */
+static bool tenxpress_phy_poll(struct efx_nic *efx)
 {
-	struct tenxpress_phy_data *phy_data = efx->phy_data;
-	bool change = false;
+	struct efx_link_state old_state = efx->link_state;
 
 	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		bool link_ok = sfx7101_link_ok(efx);
-		if (link_ok != efx->link_up) {
-			change = true;
-		} else {
-			unsigned int link_fc = efx_mdio_get_pause(efx);
-			if (link_fc != efx->link_fc)
-				change = true;
-		}
-		sfx7101_check_bad_lp(efx, link_ok);
-	} else if (efx->loopback_mode) {
-		bool link_ok = sft9001_link_ok(efx, NULL);
-		if (link_ok != efx->link_up)
-			change = true;
+		efx->link_state.up = sfx7101_link_ok(efx);
+		efx->link_state.speed = 10000;
+		efx->link_state.fd = true;
+		efx->link_state.fc = efx_mdio_get_pause(efx);
+
+		sfx7101_check_bad_lp(efx, efx->link_state.up);
 	} else {
-		int status = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
-					   MDIO_PMA_LASI_STAT);
-		if (status & MDIO_PMA_LASI_LSALARM)
-			change = true;
-	}
+		struct ethtool_cmd ecmd;
 
-	if (change)
-		falcon_sim_phy_event(efx);
+		/* Check the LASI alarm first */
+		if (efx->loopback_mode == LOOPBACK_NONE &&
+		    !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) &
+		      MDIO_PMA_LASI_LSALARM))
+			return false;
 
-	if (phy_data->phy_mode != PHY_MODE_NORMAL)
-		return;
+		tenxpress_get_settings(efx, &ecmd);
+
+		efx->link_state.up = sft9001_link_ok(efx, &ecmd);
+		efx->link_state.speed = ecmd.speed;
+		efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL);
+		efx->link_state.fc = efx_mdio_get_pause(efx);
+	}
+
+	return !efx_link_state_equal(&efx->link_state, &old_state);
 }
 
-static void tenxpress_phy_fini(struct efx_nic *efx)
+static void sfx7101_phy_fini(struct efx_nic *efx)
 {
 	int reg;
 
+	/* Power down the LNPGA */
+	reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
+	efx_mdio_write(efx, 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 */
+}
+
+static void tenxpress_phy_remove(struct efx_nic *efx)
+{
 	if (efx->phy_type == PHY_TYPE_SFT9001B)
 		device_remove_file(&efx->pci_dev->dev,
 				   &dev_attr_phy_short_reach);
 
-	if (efx->phy_type == PHY_TYPE_SFX7101) {
-		/* Power down the LNPGA */
-		reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
-		efx_mdio_write(efx, 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, bool blink)
+/* Override the RX, TX and link LEDs */
+void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
 {
 	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;
+	switch (mode) {
+	case EFX_LED_OFF:
+		reg = (PMA_PMD_LED_OFF << PMA_PMD_LED_TX_LBN) |
+			(PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
+			(PMA_PMD_LED_OFF << PMA_PMD_LED_LINK_LBN);
+		break;
+	case EFX_LED_ON:
+		reg = (PMA_PMD_LED_ON << PMA_PMD_LED_TX_LBN) |
+			(PMA_PMD_LED_ON << PMA_PMD_LED_RX_LBN) |
+			(PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN);
+		break;
+	default:
+		if (efx->phy_type == PHY_TYPE_SFX7101)
+			reg = SFX7101_PMA_PMD_LED_DEFAULT;
+		else
+			reg = SFT9001_PMA_PMD_LED_DEFAULT;
+		break;
+	}
 
 	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, reg);
 }
@@ -624,6 +658,13 @@
 	"bist"
 };
 
+static const char *sfx7101_test_name(struct efx_nic *efx, unsigned int index)
+{
+	if (index < ARRAY_SIZE(sfx7101_test_names))
+		return sfx7101_test_names[index];
+	return NULL;
+}
+
 static int
 sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
 {
@@ -635,6 +676,9 @@
 	/* BIST is automatically run after a special software reset */
 	rc = tenxpress_special_reset(efx);
 	results[0] = rc ? -1 : 1;
+
+	efx_mdio_an_reconfigure(efx);
+
 	return rc;
 }
 
@@ -650,14 +694,17 @@
 	"cable.pairD.length",
 };
 
+static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index)
+{
+	if (index < ARRAY_SIZE(sft9001_test_names))
+		return sft9001_test_names[index];
+	return NULL;
+}
+
 static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
 {
-	struct ethtool_cmd ecmd;
 	int rc = 0, rc2, i, ctrl_reg, res_reg;
 
-	if (flags & ETH_TEST_FL_OFFLINE)
-		efx->phy_op->get_settings(efx, &ecmd);
-
 	/* Initialise cable diagnostic results to unknown failure */
 	for (i = 1; i < 9; ++i)
 		results[i] = -1;
@@ -709,9 +756,7 @@
 		if (!rc)
 			rc = rc2;
 
-		rc2 = efx->phy_op->set_settings(efx, &ecmd);
-		if (!rc)
-			rc = rc2;
+		efx_mdio_an_reconfigure(efx);
 	}
 
 	return rc;
@@ -758,7 +803,7 @@
 	 * but doesn't advertise the correct speed. So override it */
 	if (efx->loopback_mode == LOOPBACK_GPHY)
 		ecmd->speed = SPEED_1000;
-	else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
+	else if (LOOPBACK_EXTERNAL(efx))
 		ecmd->speed = SPEED_10000;
 }
 
@@ -788,35 +833,29 @@
 }
 
 struct efx_phy_operations falcon_sfx7101_phy_ops = {
-	.macs		  = EFX_XMAC,
+	.probe		  = tenxpress_phy_probe,
 	.init             = tenxpress_phy_init,
 	.reconfigure      = tenxpress_phy_reconfigure,
 	.poll             = tenxpress_phy_poll,
-	.fini             = tenxpress_phy_fini,
-	.clear_interrupt  = efx_port_dummy_op_void,
+	.fini             = sfx7101_phy_fini,
+	.remove		  = tenxpress_phy_remove,
 	.get_settings	  = tenxpress_get_settings,
 	.set_settings	  = tenxpress_set_settings,
 	.set_npage_adv    = sfx7101_set_npage_adv,
-	.num_tests	  = ARRAY_SIZE(sfx7101_test_names),
-	.test_names	  = sfx7101_test_names,
+	.test_name	  = sfx7101_test_name,
 	.run_tests	  = sfx7101_run_tests,
-	.mmds             = TENXPRESS_REQUIRED_DEVS,
-	.loopbacks        = SFX7101_LOOPBACKS,
 };
 
 struct efx_phy_operations falcon_sft9001_phy_ops = {
-	.macs		  = EFX_GMAC | EFX_XMAC,
+	.probe		  = tenxpress_phy_probe,
 	.init             = tenxpress_phy_init,
 	.reconfigure      = tenxpress_phy_reconfigure,
 	.poll             = tenxpress_phy_poll,
-	.fini             = tenxpress_phy_fini,
-	.clear_interrupt  = efx_port_dummy_op_void,
+	.fini             = efx_port_dummy_op_void,
+	.remove		  = tenxpress_phy_remove,
 	.get_settings	  = tenxpress_get_settings,
 	.set_settings	  = tenxpress_set_settings,
 	.set_npage_adv    = sft9001_set_npage_adv,
-	.num_tests	  = ARRAY_SIZE(sft9001_test_names),
-	.test_names	  = sft9001_test_names,
+	.test_name	  = sft9001_test_name,
 	.run_tests	  = sft9001_run_tests,
-	.mmds             = TENXPRESS_REQUIRED_DEVS,
-	.loopbacks        = SFT9001_LOOPBACKS,
 };
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mcdi_phy.c
+++ linux-ec2-2.6.32/drivers/net/sfc/mcdi_phy.c
@@ -0,0 +1,574 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2009 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, incorporated herein by reference.
+ */
+
+/*
+ * Driver for PHY related operations via MCDI.
+ */
+
+#include "efx.h"
+#include "phy.h"
+#include "mcdi.h"
+#include "mcdi_pcol.h"
+#include "mdio_10g.h"
+
+struct efx_mcdi_phy_cfg {
+	u32 flags;
+	u32 type;
+	u32 supported_cap;
+	u32 channel;
+	u32 port;
+	u32 stats_mask;
+	u8 name[20];
+	u32 media;
+	u32 mmd_mask;
+	u8 revision[20];
+	u32 forced_cap;
+};
+
+static int
+efx_mcdi_get_phy_cfg(struct efx_nic *efx, struct efx_mcdi_phy_cfg *cfg)
+{
+	u8 outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_IN_LEN != 0);
+	BUILD_BUG_ON(MC_CMD_GET_PHY_CFG_OUT_NAME_LEN != sizeof(cfg->name));
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_CFG, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	if (outlen < MC_CMD_GET_PHY_CFG_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	cfg->flags = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_FLAGS);
+	cfg->type = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_TYPE);
+	cfg->supported_cap =
+		MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
+	cfg->channel = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_CHANNEL);
+	cfg->port = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_PRT);
+	cfg->stats_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_STATS_MASK);
+	memcpy(cfg->name, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_NAME),
+	       sizeof(cfg->name));
+	cfg->media = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MEDIA_TYPE);
+	cfg->mmd_mask = MCDI_DWORD(outbuf, GET_PHY_CFG_OUT_MMD_MASK);
+	memcpy(cfg->revision, MCDI_PTR(outbuf, GET_PHY_CFG_OUT_REVISION),
+	       sizeof(cfg->revision));
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+static int efx_mcdi_set_link(struct efx_nic *efx, u32 capabilities,
+			     u32 flags, u32 loopback_mode,
+			     u32 loopback_speed)
+{
+	u8 inbuf[MC_CMD_SET_LINK_IN_LEN];
+	int rc;
+
+	BUILD_BUG_ON(MC_CMD_SET_LINK_OUT_LEN != 0);
+
+	MCDI_SET_DWORD(inbuf, SET_LINK_IN_CAP, capabilities);
+	MCDI_SET_DWORD(inbuf, SET_LINK_IN_FLAGS, flags);
+	MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_MODE, loopback_mode);
+	MCDI_SET_DWORD(inbuf, SET_LINK_IN_LOOPBACK_SPEED, loopback_speed);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_SET_LINK, inbuf, sizeof(inbuf),
+			  NULL, 0, NULL);
+	if (rc)
+		goto fail;
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes)
+{
+	u8 outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0,
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	if (outlen < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
+		rc = -EMSGSIZE;
+		goto fail;
+	}
+
+	*loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_SUGGESTED);
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
+			 unsigned int prtad, unsigned int devad, u16 addr,
+			 u16 *value_out, u32 *status_out)
+{
+	u8 inbuf[MC_CMD_MDIO_READ_IN_LEN];
+	u8 outbuf[MC_CMD_MDIO_READ_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, bus);
+	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
+	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
+	MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	*value_out = (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
+	*status_out = MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
+			  unsigned int prtad, unsigned int devad, u16 addr,
+			  u16 value, u32 *status_out)
+{
+	u8 inbuf[MC_CMD_MDIO_WRITE_IN_LEN];
+	u8 outbuf[MC_CMD_MDIO_WRITE_OUT_LEN];
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, bus);
+	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
+	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
+	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
+	MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		goto fail;
+
+	*status_out = MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS);
+	return 0;
+
+fail:
+	EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
+{
+	u32 result = 0;
+
+	switch (media) {
+	case MC_CMD_MEDIA_KX4:
+		result |= SUPPORTED_Backplane;
+		if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
+			result |= SUPPORTED_1000baseKX_Full;
+		if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
+			result |= SUPPORTED_10000baseKX4_Full;
+		break;
+
+	case MC_CMD_MEDIA_XFP:
+	case MC_CMD_MEDIA_SFP_PLUS:
+		result |= SUPPORTED_FIBRE;
+		break;
+
+	case MC_CMD_MEDIA_BASE_T:
+		result |= SUPPORTED_TP;
+		if (cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN))
+			result |= SUPPORTED_10baseT_Half;
+		if (cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN))
+			result |= SUPPORTED_10baseT_Full;
+		if (cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN))
+			result |= SUPPORTED_100baseT_Half;
+		if (cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN))
+			result |= SUPPORTED_100baseT_Full;
+		if (cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN))
+			result |= SUPPORTED_1000baseT_Half;
+		if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
+			result |= SUPPORTED_1000baseT_Full;
+		if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
+			result |= SUPPORTED_10000baseT_Full;
+		break;
+	}
+
+	if (cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
+		result |= SUPPORTED_Pause;
+	if (cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
+		result |= SUPPORTED_Asym_Pause;
+	if (cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
+		result |= SUPPORTED_Autoneg;
+
+	return result;
+}
+
+static u32 ethtool_to_mcdi_cap(u32 cap)
+{
+	u32 result = 0;
+
+	if (cap & SUPPORTED_10baseT_Half)
+		result |= (1 << MC_CMD_PHY_CAP_10HDX_LBN);
+	if (cap & SUPPORTED_10baseT_Full)
+		result |= (1 << MC_CMD_PHY_CAP_10FDX_LBN);
+	if (cap & SUPPORTED_100baseT_Half)
+		result |= (1 << MC_CMD_PHY_CAP_100HDX_LBN);
+	if (cap & SUPPORTED_100baseT_Full)
+		result |= (1 << MC_CMD_PHY_CAP_100FDX_LBN);
+	if (cap & SUPPORTED_1000baseT_Half)
+		result |= (1 << MC_CMD_PHY_CAP_1000HDX_LBN);
+	if (cap & (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseKX_Full))
+		result |= (1 << MC_CMD_PHY_CAP_1000FDX_LBN);
+	if (cap & (SUPPORTED_10000baseT_Full | SUPPORTED_10000baseKX4_Full))
+		result |= (1 << MC_CMD_PHY_CAP_10000FDX_LBN);
+	if (cap & SUPPORTED_Pause)
+		result |= (1 << MC_CMD_PHY_CAP_PAUSE_LBN);
+	if (cap & SUPPORTED_Asym_Pause)
+		result |= (1 << MC_CMD_PHY_CAP_ASYM_LBN);
+	if (cap & SUPPORTED_Autoneg)
+		result |= (1 << MC_CMD_PHY_CAP_AN_LBN);
+
+	return result;
+}
+
+static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx)
+{
+	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	enum efx_phy_mode mode, supported;
+	u32 flags;
+
+	/* TODO: Advertise the capabilities supported by this PHY */
+	supported = 0;
+	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_TXDIS_LBN))
+		supported |= PHY_MODE_TX_DISABLED;
+	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_LOWPOWER_LBN))
+		supported |= PHY_MODE_LOW_POWER;
+	if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_POWEROFF_LBN))
+		supported |= PHY_MODE_OFF;
+
+	mode = efx->phy_mode & supported;
+
+	flags = 0;
+	if (mode & PHY_MODE_TX_DISABLED)
+		flags |= (1 << MC_CMD_SET_LINK_TXDIS_LBN);
+	if (mode & PHY_MODE_LOW_POWER)
+		flags |= (1 << MC_CMD_SET_LINK_LOWPOWER_LBN);
+	if (mode & PHY_MODE_OFF)
+		flags |= (1 << MC_CMD_SET_LINK_POWEROFF_LBN);
+
+	return flags;
+}
+
+static u32 mcdi_to_ethtool_media(u32 media)
+{
+	switch (media) {
+	case MC_CMD_MEDIA_XAUI:
+	case MC_CMD_MEDIA_CX4:
+	case MC_CMD_MEDIA_KX4:
+		return PORT_OTHER;
+
+	case MC_CMD_MEDIA_XFP:
+	case MC_CMD_MEDIA_SFP_PLUS:
+		return PORT_FIBRE;
+
+	case MC_CMD_MEDIA_BASE_T:
+		return PORT_TP;
+
+	default:
+		return PORT_OTHER;
+	}
+}
+
+static int efx_mcdi_phy_probe(struct efx_nic *efx)
+{
+	struct efx_mcdi_phy_cfg *phy_data;
+	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
+	u32 caps;
+	int rc;
+
+	/* Initialise and populate phy_data */
+	phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
+	if (phy_data == NULL)
+		return -ENOMEM;
+
+	rc = efx_mcdi_get_phy_cfg(efx, phy_data);
+	if (rc != 0)
+		goto fail;
+
+	/* Read initial link advertisement */
+	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
+			  outbuf, sizeof(outbuf), NULL);
+	if (rc)
+		goto fail;
+
+	/* Fill out nic state */
+	efx->phy_data = phy_data;
+	efx->phy_type = phy_data->type;
+
+	efx->mdio_bus = phy_data->channel;
+	efx->mdio.prtad = phy_data->port;
+	efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22);
+	efx->mdio.mode_support = 0;
+	if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22))
+		efx->mdio.mode_support |= MDIO_SUPPORTS_C22;
+	if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22))
+		efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
+
+	caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP);
+	if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN))
+		efx->link_advertising =
+			mcdi_to_ethtool_cap(phy_data->media, caps);
+	else
+		phy_data->forced_cap = caps;
+
+	/* Assert that we can map efx -> mcdi loopback modes */
+	BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE);
+	BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA);
+	BUILD_BUG_ON(LOOPBACK_GMAC != MC_CMD_LOOPBACK_GMAC);
+	BUILD_BUG_ON(LOOPBACK_XGMII != MC_CMD_LOOPBACK_XGMII);
+	BUILD_BUG_ON(LOOPBACK_XGXS != MC_CMD_LOOPBACK_XGXS);
+	BUILD_BUG_ON(LOOPBACK_XAUI != MC_CMD_LOOPBACK_XAUI);
+	BUILD_BUG_ON(LOOPBACK_GMII != MC_CMD_LOOPBACK_GMII);
+	BUILD_BUG_ON(LOOPBACK_SGMII != MC_CMD_LOOPBACK_SGMII);
+	BUILD_BUG_ON(LOOPBACK_XGBR != MC_CMD_LOOPBACK_XGBR);
+	BUILD_BUG_ON(LOOPBACK_XFI != MC_CMD_LOOPBACK_XFI);
+	BUILD_BUG_ON(LOOPBACK_XAUI_FAR != MC_CMD_LOOPBACK_XAUI_FAR);
+	BUILD_BUG_ON(LOOPBACK_GMII_FAR != MC_CMD_LOOPBACK_GMII_FAR);
+	BUILD_BUG_ON(LOOPBACK_SGMII_FAR != MC_CMD_LOOPBACK_SGMII_FAR);
+	BUILD_BUG_ON(LOOPBACK_XFI_FAR != MC_CMD_LOOPBACK_XFI_FAR);
+	BUILD_BUG_ON(LOOPBACK_GPHY != MC_CMD_LOOPBACK_GPHY);
+	BUILD_BUG_ON(LOOPBACK_PHYXS != MC_CMD_LOOPBACK_PHYXS);
+	BUILD_BUG_ON(LOOPBACK_PCS != MC_CMD_LOOPBACK_PCS);
+	BUILD_BUG_ON(LOOPBACK_PMAPMD != MC_CMD_LOOPBACK_PMAPMD);
+	BUILD_BUG_ON(LOOPBACK_XPORT != MC_CMD_LOOPBACK_XPORT);
+	BUILD_BUG_ON(LOOPBACK_XGMII_WS != MC_CMD_LOOPBACK_XGMII_WS);
+	BUILD_BUG_ON(LOOPBACK_XAUI_WS != MC_CMD_LOOPBACK_XAUI_WS);
+	BUILD_BUG_ON(LOOPBACK_XAUI_WS_FAR != MC_CMD_LOOPBACK_XAUI_WS_FAR);
+	BUILD_BUG_ON(LOOPBACK_XAUI_WS_NEAR != MC_CMD_LOOPBACK_XAUI_WS_NEAR);
+	BUILD_BUG_ON(LOOPBACK_GMII_WS != MC_CMD_LOOPBACK_GMII_WS);
+	BUILD_BUG_ON(LOOPBACK_XFI_WS != MC_CMD_LOOPBACK_XFI_WS);
+	BUILD_BUG_ON(LOOPBACK_XFI_WS_FAR != MC_CMD_LOOPBACK_XFI_WS_FAR);
+	BUILD_BUG_ON(LOOPBACK_PHYXS_WS != MC_CMD_LOOPBACK_PHYXS_WS);
+
+	rc = efx_mcdi_loopback_modes(efx, &efx->loopback_modes);
+	if (rc != 0)
+		goto fail;
+	/* The MC indicates that LOOPBACK_NONE is a valid loopback mode,
+	 * but by convention we don't */
+	efx->loopback_modes &= ~(1 << LOOPBACK_NONE);
+
+	return 0;
+
+fail:
+	kfree(phy_data);
+	return rc;
+}
+
+int efx_mcdi_phy_reconfigure(struct efx_nic *efx)
+{
+	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	u32 caps = (efx->link_advertising ?
+		    ethtool_to_mcdi_cap(efx->link_advertising) :
+		    phy_cfg->forced_cap);
+
+	return efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
+				 efx->loopback_mode, 0);
+}
+
+void efx_mcdi_phy_decode_link(struct efx_nic *efx,
+			      struct efx_link_state *link_state,
+			      u32 speed, u32 flags, u32 fcntl)
+{
+	switch (fcntl) {
+	case MC_CMD_FCNTL_AUTO:
+		WARN_ON(1);	/* This is not a link mode */
+		link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
+		break;
+	case MC_CMD_FCNTL_BIDIR:
+		link_state->fc = EFX_FC_TX | EFX_FC_RX;
+		break;
+	case MC_CMD_FCNTL_RESPOND:
+		link_state->fc = EFX_FC_RX;
+		break;
+	default:
+		WARN_ON(1);
+	case MC_CMD_FCNTL_OFF:
+		link_state->fc = 0;
+		break;
+	}
+
+	link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_LINK_UP_LBN));
+	link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_FULL_DUPLEX_LBN));
+	link_state->speed = speed;
+}
+
+/* Verify that the forced flow control settings (!EFX_FC_AUTO) are
+ * supported by the link partner. Warn the user if this isn't the case
+ */
+void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
+{
+	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	u32 rmtadv;
+
+	/* The link partner capabilities are only relevent if the
+	 * link supports flow control autonegotiation */
+	if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
+		return;
+
+	/* If flow control autoneg is supported and enabled, then fine */
+	if (efx->wanted_fc & EFX_FC_AUTO)
+		return;
+
+	rmtadv = 0;
+	if (lpa & (1 << MC_CMD_PHY_CAP_PAUSE_LBN))
+		rmtadv |= ADVERTISED_Pause;
+	if (lpa & (1 << MC_CMD_PHY_CAP_ASYM_LBN))
+		rmtadv |=  ADVERTISED_Asym_Pause;
+
+	if ((efx->wanted_fc & EFX_FC_TX) && rmtadv == ADVERTISED_Asym_Pause)
+		EFX_ERR(efx, "warning: link partner doesn't support "
+			"pause frames");
+}
+
+static bool efx_mcdi_phy_poll(struct efx_nic *efx)
+{
+	struct efx_link_state old_state = efx->link_state;
+	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
+	int rc;
+
+	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
+			  outbuf, sizeof(outbuf), NULL);
+	if (rc) {
+		EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+		efx->link_state.up = false;
+	} else {
+		efx_mcdi_phy_decode_link(
+			efx, &efx->link_state,
+			MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED),
+			MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS),
+			MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL));
+	}
+
+	return !efx_link_state_equal(&efx->link_state, &old_state);
+}
+
+static void efx_mcdi_phy_remove(struct efx_nic *efx)
+{
+	struct efx_mcdi_phy_data *phy_data = efx->phy_data;
+
+	efx->phy_data = NULL;
+	kfree(phy_data);
+}
+
+static void efx_mcdi_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
+	int rc;
+
+	ecmd->supported =
+		mcdi_to_ethtool_cap(phy_cfg->media, phy_cfg->supported_cap);
+	ecmd->advertising = efx->link_advertising;
+	ecmd->speed = efx->link_state.speed;
+	ecmd->duplex = efx->link_state.fd;
+	ecmd->port = mcdi_to_ethtool_media(phy_cfg->media);
+	ecmd->phy_address = phy_cfg->port;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->autoneg = !!(efx->link_advertising & ADVERTISED_Autoneg);
+	ecmd->mdio_support = (efx->mdio.mode_support &
+			      (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22));
+
+	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
+			  outbuf, sizeof(outbuf), NULL);
+	if (rc) {
+		EFX_ERR(efx, "%s: failed rc=%d\n", __func__, rc);
+		return;
+	}
+	ecmd->lp_advertising =
+		mcdi_to_ethtool_cap(phy_cfg->media,
+				    MCDI_DWORD(outbuf, GET_LINK_OUT_LP_CAP));
+}
+
+static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+	struct efx_mcdi_phy_cfg *phy_cfg = efx->phy_data;
+	u32 caps;
+	int rc;
+
+	if (ecmd->autoneg) {
+		caps = (ethtool_to_mcdi_cap(ecmd->advertising) |
+			 1 << MC_CMD_PHY_CAP_AN_LBN);
+	} else if (ecmd->duplex) {
+		switch (ecmd->speed) {
+		case 10:    caps = 1 << MC_CMD_PHY_CAP_10FDX_LBN;    break;
+		case 100:   caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN;   break;
+		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN;  break;
+		case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
+		default:    return -EINVAL;
+		}
+	} else {
+		switch (ecmd->speed) {
+		case 10:    caps = 1 << MC_CMD_PHY_CAP_10HDX_LBN;    break;
+		case 100:   caps = 1 << MC_CMD_PHY_CAP_100HDX_LBN;   break;
+		case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000HDX_LBN;  break;
+		default:    return -EINVAL;
+		}
+	}
+
+	rc = efx_mcdi_set_link(efx, caps, efx_get_mcdi_phy_flags(efx),
+			       efx->loopback_mode, 0);
+	if (rc)
+		return rc;
+
+	if (ecmd->autoneg) {
+		efx_link_set_advertising(
+			efx, ecmd->advertising | ADVERTISED_Autoneg);
+		phy_cfg->forced_cap = 0;
+	} else {
+		efx_link_set_advertising(efx, 0);
+		phy_cfg->forced_cap = caps;
+	}
+	return 0;
+}
+
+struct efx_phy_operations efx_mcdi_phy_ops = {
+	.probe		= efx_mcdi_phy_probe,
+	.init 	 	= efx_port_dummy_op_int,
+	.reconfigure	= efx_mcdi_phy_reconfigure,
+	.poll		= efx_mcdi_phy_poll,
+	.fini		= efx_port_dummy_op_void,
+	.remove		= efx_mcdi_phy_remove,
+	.get_settings	= efx_mcdi_phy_get_settings,
+	.set_settings	= efx_mcdi_phy_set_settings,
+	.run_tests	= NULL,
+	.test_name	= NULL,
+};
--- linux-ec2-2.6.32.orig/drivers/net/sfc/enum.h
+++ linux-ec2-2.6.32/drivers/net/sfc/enum.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2008 Solarflare Communications Inc.
+ * Copyright 2007-2009 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
@@ -13,44 +13,101 @@
 /**
  * enum efx_loopback_mode - loopback modes
  * @LOOPBACK_NONE: no loopback
- * @LOOPBACK_GMAC: loopback within GMAC at unspecified level
- * @LOOPBACK_XGMII: loopback within XMAC at XGMII level
- * @LOOPBACK_XGXS: loopback within XMAC at XGXS level
- * @LOOPBACK_XAUI: loopback within XMAC at XAUI level
+ * @LOOPBACK_DATA: data path loopback
+ * @LOOPBACK_GMAC: loopback within GMAC
+ * @LOOPBACK_XGMII: loopback after XMAC
+ * @LOOPBACK_XGXS: loopback within BPX after XGXS
+ * @LOOPBACK_XAUI: loopback within BPX before XAUI serdes
+ * @LOOPBACK_GMII: loopback within BPX after GMAC
+ * @LOOPBACK_SGMII: loopback within BPX within SGMII
+ * @LOOPBACK_XGBR: loopback within BPX within XGBR
+ * @LOOPBACK_XFI: loopback within BPX before XFI serdes
+ * @LOOPBACK_XAUI_FAR: loopback within BPX after XAUI serdes
+ * @LOOPBACK_GMII_FAR: loopback within BPX before SGMII
+ * @LOOPBACK_SGMII_FAR: loopback within BPX after SGMII
+ * @LOOPBACK_XFI_FAR: loopback after XFI serdes
  * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level
  * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level
  * @LOOPBACK_PCS: loopback within 10G PHY at PCS level
  * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level
- * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
+ * @LOOPBACK_XPORT: cross port loopback
+ * @LOOPBACK_XGMII_WS: wireside loopback excluding XMAC
+ * @LOOPBACK_XAUI_WS: wireside loopback within BPX within XAUI serdes
+ * @LOOPBACK_XAUI_WS_FAR: wireside loopback within BPX including XAUI serdes
+ * @LOOPBACK_XAUI_WS_NEAR: wireside loopback within BPX excluding XAUI serdes
+ * @LOOPBACK_GMII_WS: wireside loopback excluding GMAC
+ * @LOOPBACK_XFI_WS: wireside loopback excluding XFI serdes
+ * @LOOPBACK_XFI_WS_FAR: wireside loopback including XFI serdes
+ * @LOOPBACK_PHYXS_WS: wireside loopback within 10G PHY at PHYXS level
  */
-/* Please keep in order and up-to-date w.r.t the following two #defines */
+/* Please keep up-to-date w.r.t the following two #defines */
 enum efx_loopback_mode {
 	LOOPBACK_NONE = 0,
-	LOOPBACK_GMAC = 1,
-	LOOPBACK_XGMII = 2,
-	LOOPBACK_XGXS = 3,
-	LOOPBACK_XAUI = 4,
-	LOOPBACK_GPHY = 5,
-	LOOPBACK_PHYXS = 6,
-	LOOPBACK_PCS = 7,
-	LOOPBACK_PMAPMD = 8,
-	LOOPBACK_NETWORK = 9,
+	LOOPBACK_DATA = 1,
+	LOOPBACK_GMAC = 2,
+	LOOPBACK_XGMII = 3,
+	LOOPBACK_XGXS = 4,
+	LOOPBACK_XAUI = 5,
+	LOOPBACK_GMII = 6,
+	LOOPBACK_SGMII = 7,
+	LOOPBACK_XGBR = 8,
+	LOOPBACK_XFI = 9,
+	LOOPBACK_XAUI_FAR = 10,
+	LOOPBACK_GMII_FAR = 11,
+	LOOPBACK_SGMII_FAR = 12,
+	LOOPBACK_XFI_FAR = 13,
+	LOOPBACK_GPHY = 14,
+	LOOPBACK_PHYXS = 15,
+	LOOPBACK_PCS = 16,
+	LOOPBACK_PMAPMD = 17,
+	LOOPBACK_XPORT = 18,
+	LOOPBACK_XGMII_WS = 19,
+	LOOPBACK_XAUI_WS = 20,
+	LOOPBACK_XAUI_WS_FAR = 21,
+	LOOPBACK_XAUI_WS_NEAR = 22,
+	LOOPBACK_GMII_WS = 23,
+	LOOPBACK_XFI_WS = 24,
+	LOOPBACK_XFI_WS_FAR = 25,
+	LOOPBACK_PHYXS_WS = 26,
 	LOOPBACK_MAX
 };
-
 #define LOOPBACK_TEST_MAX LOOPBACK_PMAPMD
 
-extern const char *efx_loopback_mode_names[];
-#define LOOPBACK_MODE_NAME(mode)			\
-	STRING_TABLE_LOOKUP(mode, efx_loopback_mode)
-#define LOOPBACK_MODE(efx)				\
-	LOOPBACK_MODE_NAME(efx->loopback_mode)
-
 /* These loopbacks occur within the controller */
-#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) |     \
-			    (1 << LOOPBACK_XGMII)|     \
-			    (1 << LOOPBACK_XGXS) |     \
-			    (1 << LOOPBACK_XAUI))
+#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_DATA) |		\
+			    (1 << LOOPBACK_GMAC) |		\
+			    (1 << LOOPBACK_XGMII)|		\
+			    (1 << LOOPBACK_XGXS) |		\
+			    (1 << LOOPBACK_XAUI) |		\
+			    (1 << LOOPBACK_GMII) |		\
+			    (1 << LOOPBACK_SGMII) |		\
+			    (1 << LOOPBACK_SGMII) |		\
+			    (1 << LOOPBACK_XGBR) |		\
+			    (1 << LOOPBACK_XFI) |		\
+			    (1 << LOOPBACK_XAUI_FAR) |		\
+			    (1 << LOOPBACK_GMII_FAR) |		\
+			    (1 << LOOPBACK_SGMII_FAR) |		\
+			    (1 << LOOPBACK_XFI_FAR) |		\
+			    (1 << LOOPBACK_XGMII_WS) |		\
+			    (1 << LOOPBACK_XAUI_WS) |		\
+			    (1 << LOOPBACK_XAUI_WS_FAR) |	\
+			    (1 << LOOPBACK_XAUI_WS_NEAR) |	\
+			    (1 << LOOPBACK_GMII_WS) |		\
+			    (1 << LOOPBACK_XFI_WS) |		\
+			    (1 << LOOPBACK_XFI_WS_FAR))
+
+#define LOOPBACKS_WS ((1 << LOOPBACK_XGMII_WS) |		\
+		      (1 << LOOPBACK_XAUI_WS) |			\
+		      (1 << LOOPBACK_XAUI_WS_FAR) |		\
+		      (1 << LOOPBACK_XAUI_WS_NEAR) |		\
+		      (1 << LOOPBACK_GMII_WS) |			\
+		      (1 << LOOPBACK_XFI_WS) |			\
+		      (1 << LOOPBACK_XFI_WS_FAR) |		\
+		      (1 << LOOPBACK_PHYXS_WS))
+
+#define LOOPBACKS_EXTERNAL(_efx)					\
+	((_efx)->loopback_modes & ~LOOPBACKS_INTERNAL &			\
+	 ~(1 << LOOPBACK_NONE))
 
 #define LOOPBACK_MASK(_efx)			\
 	(1 << (_efx)->loopback_mode)
@@ -58,6 +115,9 @@
 #define LOOPBACK_INTERNAL(_efx)				\
 	(!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx)))
 
+#define LOOPBACK_EXTERNAL(_efx)				\
+	(!!(LOOPBACK_MASK(_efx) & LOOPBACKS_EXTERNAL(_efx)))
+
 #define LOOPBACK_CHANGED(_from, _to, _mask)				\
 	(!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask)))
 
@@ -84,6 +144,7 @@
  * @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch
  * @RESET_TYPE_TX_DESC_FETCH: pcie error during tx descriptor fetch
  * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors
+ * @RESET_TYPE_MC_FAILURE: MC reboot/assertion
  */
 enum reset_type {
 	RESET_TYPE_NONE = -1,
@@ -98,6 +159,7 @@
 	RESET_TYPE_RX_DESC_FETCH,
 	RESET_TYPE_TX_DESC_FETCH,
 	RESET_TYPE_TX_SKIP,
+	RESET_TYPE_MC_FAILURE,
 	RESET_TYPE_MAX,
 };
 
--- linux-ec2-2.6.32.orig/drivers/net/sfc/efx.c
+++ linux-ec2-2.6.32/drivers/net/sfc/efx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2008 Solarflare Communications Inc.
+ * Copyright 2005-2009 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
@@ -21,12 +21,73 @@
 #include <linux/ethtool.h>
 #include <linux/topology.h>
 #include "net_driver.h"
-#include "ethtool.h"
-#include "tx.h"
-#include "rx.h"
 #include "efx.h"
 #include "mdio_10g.h"
-#include "falcon.h"
+#include "nic.h"
+
+#include "mcdi.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_DATA]		= "DATAPATH",
+	[LOOPBACK_GMAC]		= "GMAC",
+	[LOOPBACK_XGMII]	= "XGMII",
+	[LOOPBACK_XGXS]		= "XGXS",
+	[LOOPBACK_XAUI]  	= "XAUI",
+	[LOOPBACK_GMII] 	= "GMII",
+	[LOOPBACK_SGMII] 	= "SGMII",
+	[LOOPBACK_XGBR]		= "XGBR",
+	[LOOPBACK_XFI]		= "XFI",
+	[LOOPBACK_XAUI_FAR]	= "XAUI_FAR",
+	[LOOPBACK_GMII_FAR]	= "GMII_FAR",
+	[LOOPBACK_SGMII_FAR]	= "SGMII_FAR",
+	[LOOPBACK_XFI_FAR]	= "XFI_FAR",
+	[LOOPBACK_GPHY]		= "GPHY",
+	[LOOPBACK_PHYXS]	= "PHYXS",
+	[LOOPBACK_PCS]	 	= "PCS",
+	[LOOPBACK_PMAPMD] 	= "PMA/PMD",
+	[LOOPBACK_XPORT]	= "XPORT",
+	[LOOPBACK_XGMII_WS]	= "XGMII_WS",
+	[LOOPBACK_XAUI_WS]  	= "XAUI_WS",
+	[LOOPBACK_XAUI_WS_FAR]  = "XAUI_WS_FAR",
+	[LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR",
+	[LOOPBACK_GMII_WS] 	= "GMII_WS",
+	[LOOPBACK_XFI_WS]	= "XFI_WS",
+	[LOOPBACK_XFI_WS_FAR]	= "XFI_WS_FAR",
+	[LOOPBACK_PHYXS_WS]  	= "PHYXS_WS",
+};
+
+/* 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",
+};
+
+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_TX_WATCHDOG]   = "TX_WATCHDOG",
+	[RESET_TYPE_INT_ERROR]     = "INT_ERROR",
+	[RESET_TYPE_RX_RECOVERY]   = "RX_RECOVERY",
+	[RESET_TYPE_RX_DESC_FETCH] = "RX_DESC_FETCH",
+	[RESET_TYPE_TX_DESC_FETCH] = "TX_DESC_FETCH",
+	[RESET_TYPE_TX_SKIP]       = "TX_SKIP",
+	[RESET_TYPE_MC_FAILURE]    = "MC_FAILURE",
+};
 
 #define EFX_MAX_MTU (9 * 1024)
 
@@ -145,7 +206,8 @@
 
 #define EFX_ASSERT_RESET_SERIALISED(efx)		\
 	do {						\
-		if (efx->state == STATE_RUNNING)	\
+		if ((efx->state == STATE_RUNNING) ||	\
+		    (efx->state == STATE_DISABLED))	\
 			ASSERT_RTNL();			\
 	} while (0)
 
@@ -171,7 +233,7 @@
 		     !channel->enabled))
 		return 0;
 
-	rx_packets = falcon_process_eventq(channel, rx_quota);
+	rx_packets = efx_nic_process_eventq(channel, rx_quota);
 	if (rx_packets == 0)
 		return 0;
 
@@ -203,7 +265,7 @@
 	channel->work_pending = false;
 	smp_wmb();
 
-	falcon_eventq_read_ack(channel);
+	efx_nic_eventq_read_ack(channel);
 }
 
 /* NAPI poll handler
@@ -228,26 +290,20 @@
 		if (channel->used_flags & EFX_USED_BY_RX &&
 		    efx->irq_rx_adaptive &&
 		    unlikely(++channel->irq_count == 1000)) {
-			unsigned old_irq_moderation = channel->irq_moderation;
-
 			if (unlikely(channel->irq_mod_score <
 				     irq_adapt_low_thresh)) {
-				channel->irq_moderation =
-					max_t(int,
-					      channel->irq_moderation -
-					      FALCON_IRQ_MOD_RESOLUTION,
-					      FALCON_IRQ_MOD_RESOLUTION);
+				if (channel->irq_moderation > 1) {
+					channel->irq_moderation -= 1;
+					efx->type->push_irq_moderation(channel);
+				}
 			} else if (unlikely(channel->irq_mod_score >
 					    irq_adapt_high_thresh)) {
-				channel->irq_moderation =
-					min(channel->irq_moderation +
-					    FALCON_IRQ_MOD_RESOLUTION,
-					    efx->irq_rx_moderation);
+				if (channel->irq_moderation <
+				    efx->irq_rx_moderation) {
+					channel->irq_moderation += 1;
+					efx->type->push_irq_moderation(channel);
+				}
 			}
-
-			if (channel->irq_moderation != old_irq_moderation)
-				falcon_set_int_moderation(channel);
-
 			channel->irq_count = 0;
 			channel->irq_mod_score = 0;
 		}
@@ -280,7 +336,7 @@
 	BUG_ON(!channel->enabled);
 
 	/* Disable interrupts and wait for ISRs to complete */
-	falcon_disable_interrupts(efx);
+	efx_nic_disable_interrupts(efx);
 	if (efx->legacy_irq)
 		synchronize_irq(efx->legacy_irq);
 	if (channel->irq)
@@ -290,14 +346,14 @@
 	napi_disable(&channel->napi_str);
 
 	/* Poll the channel */
-	efx_process_channel(channel, efx->type->evq_size);
+	efx_process_channel(channel, EFX_EVQ_SIZE);
 
 	/* Ack the eventq. This may cause an interrupt to be generated
 	 * when they are reenabled */
 	efx_channel_processed(channel);
 
 	napi_enable(&channel->napi_str);
-	falcon_enable_interrupts(efx);
+	efx_nic_enable_interrupts(efx);
 }
 
 /* Create event queue
@@ -309,7 +365,7 @@
 {
 	EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel);
 
-	return falcon_probe_eventq(channel);
+	return efx_nic_probe_eventq(channel);
 }
 
 /* Prepare channel's event queue */
@@ -319,21 +375,21 @@
 
 	channel->eventq_read_ptr = 0;
 
-	falcon_init_eventq(channel);
+	efx_nic_init_eventq(channel);
 }
 
 static void efx_fini_eventq(struct efx_channel *channel)
 {
 	EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel);
 
-	falcon_fini_eventq(channel);
+	efx_nic_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);
+	efx_nic_remove_eventq(channel);
 }
 
 /**************************************************************************
@@ -499,7 +555,7 @@
 	EFX_ASSERT_RESET_SERIALISED(efx);
 	BUG_ON(efx->port_enabled);
 
-	rc = falcon_flush_queues(efx);
+	rc = efx_nic_flush_queues(efx);
 	if (rc)
 		EFX_ERR(efx, "failed to flush queues\n");
 	else
@@ -547,8 +603,10 @@
  * 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)
+void efx_link_status_changed(struct efx_nic *efx)
 {
+	struct efx_link_state *link_state = &efx->link_state;
+
 	/* SFC Bug 5356: A net_dev notifier is registered, so we must ensure
 	 * that no events are triggered between unregister_netdev() and the
 	 * driver unloading. A more general condition is that NETDEV_CHANGE
@@ -561,19 +619,19 @@
 		return;
 	}
 
-	if (efx->link_up != netif_carrier_ok(efx->net_dev)) {
+	if (link_state->up != netif_carrier_ok(efx->net_dev)) {
 		efx->n_link_state_changes++;
 
-		if (efx->link_up)
+		if (link_state->up)
 			netif_carrier_on(efx->net_dev);
 		else
 			netif_carrier_off(efx->net_dev);
 	}
 
 	/* Status message for kernel log */
-	if (efx->link_up) {
+	if (link_state->up) {
 		EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n",
-			 efx->link_speed, efx->link_fd ? "full" : "half",
+			 link_state->speed, link_state->fd ? "full" : "half",
 			 efx->net_dev->mtu,
 			 (efx->promiscuous ? " [PROMISC]" : ""));
 	} else {
@@ -582,16 +640,49 @@
 
 }
 
+void efx_link_set_advertising(struct efx_nic *efx, u32 advertising)
+{
+	efx->link_advertising = advertising;
+	if (advertising) {
+		if (advertising & ADVERTISED_Pause)
+			efx->wanted_fc |= (EFX_FC_TX | EFX_FC_RX);
+		else
+			efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX);
+		if (advertising & ADVERTISED_Asym_Pause)
+			efx->wanted_fc ^= EFX_FC_TX;
+	}
+}
+
+void efx_link_set_wanted_fc(struct efx_nic *efx, enum efx_fc_type wanted_fc)
+{
+	efx->wanted_fc = wanted_fc;
+	if (efx->link_advertising) {
+		if (wanted_fc & EFX_FC_RX)
+			efx->link_advertising |= (ADVERTISED_Pause |
+						  ADVERTISED_Asym_Pause);
+		else
+			efx->link_advertising &= ~(ADVERTISED_Pause |
+						   ADVERTISED_Asym_Pause);
+		if (wanted_fc & EFX_FC_TX)
+			efx->link_advertising ^= ADVERTISED_Asym_Pause;
+	}
+}
+
 static void efx_fini_port(struct efx_nic *efx);
 
-/* This call reinitialises the MAC to pick up new PHY settings. The
- * caller must hold the mac_lock */
-void __efx_reconfigure_port(struct efx_nic *efx)
+/* Push loopback/power/transmit disable settings to the PHY, and reconfigure
+ * the MAC appropriately. All other PHY configuration changes are pushed
+ * through phy_op->set_settings(), and pushed asynchronously to the MAC
+ * through efx_monitor().
+ *
+ * Callers must hold the mac_lock
+ */
+int __efx_reconfigure_port(struct efx_nic *efx)
 {
-	WARN_ON(!mutex_is_locked(&efx->mac_lock));
+	enum efx_phy_mode phy_mode;
+	int rc;
 
-	EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n",
-		raw_smp_processor_id());
+	WARN_ON(!mutex_is_locked(&efx->mac_lock));
 
 	/* Serialise the promiscuous flag with efx_set_multicast_list. */
 	if (efx_dev_registered(efx)) {
@@ -599,61 +690,48 @@
 		netif_addr_unlock_bh(efx->net_dev);
 	}
 
-	falcon_deconfigure_mac_wrapper(efx);
-
-	/* Reconfigure the PHY, disabling transmit in mac level loopback. */
+	/* Disable PHY transmit in mac level loopbacks */
+	phy_mode = efx->phy_mode;
 	if (LOOPBACK_INTERNAL(efx))
 		efx->phy_mode |= PHY_MODE_TX_DISABLED;
 	else
 		efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
-	efx->phy_op->reconfigure(efx);
-
-	if (falcon_switch_mac(efx))
-		goto fail;
 
-	efx->mac_op->reconfigure(efx);
+	rc = efx->type->reconfigure_port(efx);
 
-	/* Inform kernel of loss/gain of carrier */
-	efx_link_status_changed(efx);
-	return;
+	if (rc)
+		efx->phy_mode = phy_mode;
 
-fail:
-	EFX_ERR(efx, "failed to reconfigure MAC\n");
-	efx->port_enabled = false;
-	efx_fini_port(efx);
+	return rc;
 }
 
 /* Reinitialise the MAC to pick up new PHY settings, even if the port is
  * disabled. */
-void efx_reconfigure_port(struct efx_nic *efx)
+int efx_reconfigure_port(struct efx_nic *efx)
 {
+	int rc;
+
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
 	mutex_lock(&efx->mac_lock);
-	__efx_reconfigure_port(efx);
+	rc = __efx_reconfigure_port(efx);
 	mutex_unlock(&efx->mac_lock);
-}
-
-/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
- * we don't efx_reconfigure_port() if the port is disabled. Care is taken
- * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
-static void efx_phy_work(struct work_struct *data)
-{
-	struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);
 
-	mutex_lock(&efx->mac_lock);
-	if (efx->port_enabled)
-		__efx_reconfigure_port(efx);
-	mutex_unlock(&efx->mac_lock);
+	return rc;
 }
 
+/* Asynchronous work item for changing MAC promiscuity and multicast
+ * hash.  Avoid a drain/rx_ingress enable by reconfiguring the current
+ * MAC directly. */
 static void efx_mac_work(struct work_struct *data)
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
 
 	mutex_lock(&efx->mac_lock);
-	if (efx->port_enabled)
-		efx->mac_op->irq(efx);
+	if (efx->port_enabled) {
+		efx->type->push_multicast_hash(efx);
+		efx->mac_op->reconfigure(efx);
+	}
 	mutex_unlock(&efx->mac_lock);
 }
 
@@ -663,14 +741,14 @@
 
 	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;
-
 	if (phy_flash_cfg)
 		efx->phy_mode = PHY_MODE_SPECIAL;
 
+	/* Connect up MAC/PHY operations table */
+	rc = efx->type->probe_port(efx);
+	if (rc)
+		goto err;
+
 	/* Sanity check MAC address */
 	if (is_valid_ether_addr(efx->mac_address)) {
 		memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
@@ -699,29 +777,33 @@
 
 	EFX_LOG(efx, "init port\n");
 
-	rc = efx->phy_op->init(efx);
-	if (rc)
-		return rc;
 	mutex_lock(&efx->mac_lock);
-	efx->phy_op->reconfigure(efx);
-	rc = falcon_switch_mac(efx);
-	mutex_unlock(&efx->mac_lock);
+
+	rc = efx->phy_op->init(efx);
 	if (rc)
-		goto fail;
-	efx->mac_op->reconfigure(efx);
+		goto fail1;
 
 	efx->port_initialized = true;
-	efx_stats_enable(efx);
+
+	/* Reconfigure the MAC before creating dma queues (required for
+	 * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */
+	efx->mac_op->reconfigure(efx);
+
+	/* Ensure the PHY advertises the correct flow control settings */
+	rc = efx->phy_op->reconfigure(efx);
+	if (rc)
+		goto fail2;
+
+	mutex_unlock(&efx->mac_lock);
 	return 0;
 
-fail:
+fail2:
 	efx->phy_op->fini(efx);
+fail1:
+	mutex_unlock(&efx->mac_lock);
 	return rc;
 }
 
-/* Allow efx_reconfigure_port() to be scheduled, and close the window
- * between efx_stop_port and efx_flush_all whereby a previously scheduled
- * efx_phy_work()/efx_mac_work() may have been cancelled */
 static void efx_start_port(struct efx_nic *efx)
 {
 	EFX_LOG(efx, "start port\n");
@@ -729,15 +811,16 @@
 
 	mutex_lock(&efx->mac_lock);
 	efx->port_enabled = true;
-	__efx_reconfigure_port(efx);
-	efx->mac_op->irq(efx);
+
+	/* efx_mac_work() might have been scheduled after efx_stop_port(),
+	 * and then cancelled by efx_flush_all() */
+	efx->type->push_multicast_hash(efx);
+	efx->mac_op->reconfigure(efx);
+
 	mutex_unlock(&efx->mac_lock);
 }
 
-/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing,
- * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
- * and efx_mac_work may still be scheduled via NAPI processing until
- * efx_flush_all() is called */
+/* Prevent efx_mac_work() and efx_monitor() from working */
 static void efx_stop_port(struct efx_nic *efx)
 {
 	EFX_LOG(efx, "stop port\n");
@@ -760,11 +843,10 @@
 	if (!efx->port_initialized)
 		return;
 
-	efx_stats_disable(efx);
 	efx->phy_op->fini(efx);
 	efx->port_initialized = false;
 
-	efx->link_up = false;
+	efx->link_state.up = false;
 	efx_link_status_changed(efx);
 }
 
@@ -772,7 +854,7 @@
 {
 	EFX_LOG(efx, "destroying port\n");
 
-	falcon_remove_port(efx);
+	efx->type->remove_port(efx);
 }
 
 /**************************************************************************
@@ -824,9 +906,8 @@
 		goto fail2;
 	}
 
-	efx->membase_phys = pci_resource_start(efx->pci_dev,
-					       efx->type->mem_bar);
-	rc = pci_request_region(pci_dev, efx->type->mem_bar, "sfc");
+	efx->membase_phys = pci_resource_start(efx->pci_dev, EFX_MEM_BAR);
+	rc = pci_request_region(pci_dev, EFX_MEM_BAR, "sfc");
 	if (rc) {
 		EFX_ERR(efx, "request for memory BAR failed\n");
 		rc = -EIO;
@@ -835,21 +916,20 @@
 	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 %llx+%x\n",
-			efx->type->mem_bar,
+		EFX_ERR(efx, "could not map memory BAR at %llx+%x\n",
 			(unsigned long long)efx->membase_phys,
 			efx->type->mem_map_size);
 		rc = -ENOMEM;
 		goto fail4;
 	}
-	EFX_LOG(efx, "memory BAR %u at %llx+%x (virtual %p)\n",
-		efx->type->mem_bar, (unsigned long long)efx->membase_phys,
+	EFX_LOG(efx, "memory BAR at %llx+%x (virtual %p)\n",
+		(unsigned long long)efx->membase_phys,
 		efx->type->mem_map_size, efx->membase);
 
 	return 0;
 
  fail4:
-	pci_release_region(efx->pci_dev, efx->type->mem_bar);
+	pci_release_region(efx->pci_dev, EFX_MEM_BAR);
  fail3:
 	efx->membase_phys = 0;
  fail2:
@@ -868,7 +948,7 @@
 	}
 
 	if (efx->membase_phys) {
-		pci_release_region(efx->pci_dev, efx->type->mem_bar);
+		pci_release_region(efx->pci_dev, EFX_MEM_BAR);
 		efx->membase_phys = 0;
 	}
 
@@ -1011,7 +1091,7 @@
 	EFX_LOG(efx, "creating NIC\n");
 
 	/* Carry out hardware-type specific initialisation */
-	rc = falcon_probe_nic(efx);
+	rc = efx->type->probe(efx);
 	if (rc)
 		return rc;
 
@@ -1032,7 +1112,7 @@
 	EFX_LOG(efx, "destroying NIC\n");
 
 	efx_remove_interrupts(efx);
-	falcon_remove_nic(efx);
+	efx->type->remove(efx);
 }
 
 /**************************************************************************
@@ -1112,12 +1192,31 @@
 	efx_for_each_channel(channel, efx)
 		efx_start_channel(channel);
 
-	falcon_enable_interrupts(efx);
+	efx_nic_enable_interrupts(efx);
 
-	/* Start hardware monitor if we're in RUNNING */
-	if (efx->state == STATE_RUNNING)
+	/* Switch to event based MCDI completions after enabling interrupts.
+	 * If a reset has been scheduled, then we need to stay in polled mode.
+	 * Rather than serialising efx_mcdi_mode_event() [which sleeps] and
+	 * reset_pending [modified from an atomic context], we instead guarantee
+	 * that efx_mcdi_mode_poll() isn't reverted erroneously */
+	efx_mcdi_mode_event(efx);
+	if (efx->reset_pending != RESET_TYPE_NONE)
+		efx_mcdi_mode_poll(efx);
+
+	/* Start the hardware monitor if there is one. Otherwise (we're link
+	 * event driven), we have to poll the PHY because after an event queue
+	 * flush, we could have a missed a link state change */
+	if (efx->type->monitor != NULL) {
 		queue_delayed_work(efx->workqueue, &efx->monitor_work,
 				   efx_monitor_interval);
+	} else {
+		mutex_lock(&efx->mac_lock);
+		if (efx->phy_op->poll(efx))
+			efx_link_status_changed(efx);
+		mutex_unlock(&efx->mac_lock);
+	}
+
+	efx->type->start_stats(efx);
 }
 
 /* Flush all delayed work. Should only be called when no more delayed work
@@ -1136,8 +1235,6 @@
 
 	/* Stop scheduled port reconfigurations */
 	cancel_work_sync(&efx->mac_work);
-	cancel_work_sync(&efx->phy_work);
-
 }
 
 /* Quiesce hardware and software without bringing the link down.
@@ -1155,8 +1252,13 @@
 	if (!efx->port_enabled)
 		return;
 
+	efx->type->stop_stats(efx);
+
+	/* Switch to MCDI polling on Siena before disabling interrupts */
+	efx_mcdi_mode_poll(efx);
+
 	/* Disable interrupts and wait for ISR to complete */
-	falcon_disable_interrupts(efx);
+	efx_nic_disable_interrupts(efx);
 	if (efx->legacy_irq)
 		synchronize_irq(efx->legacy_irq);
 	efx_for_each_channel(channel, efx) {
@@ -1173,15 +1275,9 @@
 	 * window to loose phy events */
 	efx_stop_port(efx);
 
-	/* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */
+	/* Flush efx_mac_work(), refill_workqueue, monitor_work */
 	efx_flush_all(efx);
 
-	/* Isolate the MAC from the TX and RX engines, so that queue
-	 * flushes will complete in a timely fashion. */
-	falcon_deconfigure_mac_wrapper(efx);
-	msleep(10); /* Let the Rx FIFO drain */
-	falcon_drain_tx_fifo(efx);
-
 	/* Stop the kernel transmit interface late, so the watchdog
 	 * timer isn't ticking over the flush */
 	if (efx_dev_registered(efx)) {
@@ -1201,41 +1297,39 @@
 	efx_remove_nic(efx);
 }
 
-/* A convinience function to safely flush all the queues */
-void efx_flush_queues(struct efx_nic *efx)
-{
-	EFX_ASSERT_RESET_SERIALISED(efx);
-
-	efx_stop_all(efx);
-
-	efx_fini_channels(efx);
-	efx_init_channels(efx);
-
-	efx_start_all(efx);
-}
-
 /**************************************************************************
  *
  * Interrupt moderation
  *
  **************************************************************************/
 
+static unsigned irq_mod_ticks(int usecs, int resolution)
+{
+	if (usecs <= 0)
+		return 0; /* cannot receive interrupts ahead of time :-) */
+	if (usecs < resolution)
+		return 1; /* never round down to 0 */
+	return usecs / resolution;
+}
+
 /* Set interrupt moderation parameters */
 void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
 			     bool rx_adaptive)
 {
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
+	unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION);
+	unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION);
 
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
 	efx_for_each_tx_queue(tx_queue, efx)
-		tx_queue->channel->irq_moderation = tx_usecs;
+		tx_queue->channel->irq_moderation = tx_ticks;
 
 	efx->irq_rx_adaptive = rx_adaptive;
-	efx->irq_rx_moderation = rx_usecs;
+	efx->irq_rx_moderation = rx_ticks;
 	efx_for_each_rx_queue(rx_queue, efx)
-		rx_queue->channel->irq_moderation = rx_usecs;
+		rx_queue->channel->irq_moderation = rx_ticks;
 }
 
 /**************************************************************************
@@ -1250,10 +1344,10 @@
 {
 	struct efx_nic *efx = container_of(data, struct efx_nic,
 					   monitor_work.work);
-	int rc;
 
 	EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
 		  raw_smp_processor_id());
+	BUG_ON(efx->type->monitor == NULL);
 
 	/* If the mac_lock is already held then it is likely a port
 	 * reconfiguration is already in place, which will likely do
@@ -1262,15 +1356,7 @@
 		goto out_requeue;
 	if (!efx->port_enabled)
 		goto out_unlock;
-	rc = efx->board_info.monitor(efx);
-	if (rc) {
-		EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
-			(rc == -ERANGE) ? "reported fault" : "failed");
-		efx->phy_mode |= PHY_MODE_LOW_POWER;
-		falcon_sim_phy_event(efx);
-	}
-	efx->phy_op->poll(efx);
-	efx->mac_op->poll(efx);
+	efx->type->monitor(efx);
 
 out_unlock:
 	mutex_unlock(&efx->mac_lock);
@@ -1374,6 +1460,12 @@
 		return -EIO;
 	if (efx->phy_mode & PHY_MODE_SPECIAL)
 		return -EBUSY;
+	if (efx_mcdi_poll_reboot(efx) && efx_reset(efx, RESET_TYPE_ALL))
+		return -EIO;
+
+	/* Notify the kernel of the link state polled during driver load,
+	 * before the monitor starts running */
+	efx_link_status_changed(efx);
 
 	efx_start_all(efx);
 	return 0;
@@ -1400,20 +1492,6 @@
 	return 0;
 }
 
-void efx_stats_disable(struct efx_nic *efx)
-{
-	spin_lock(&efx->stats_lock);
-	++efx->stats_disable_count;
-	spin_unlock(&efx->stats_lock);
-}
-
-void efx_stats_enable(struct efx_nic *efx)
-{
-	spin_lock(&efx->stats_lock);
-	--efx->stats_disable_count;
-	spin_unlock(&efx->stats_lock);
-}
-
 /* Context: process, dev_base_lock or RTNL held, non-blocking. */
 static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
 {
@@ -1421,17 +1499,9 @@
 	struct efx_mac_stats *mac_stats = &efx->mac_stats;
 	struct net_device_stats *stats = &net_dev->stats;
 
-	/* Update stats if possible, but do not wait if another thread
-	 * is updating them or if MAC stats fetches are temporarily
-	 * disabled; slightly stale stats are acceptable.
-	 */
-	if (!spin_trylock(&efx->stats_lock))
-		return stats;
-	if (!efx->stats_disable_count) {
-		efx->mac_op->update_stats(efx);
-		falcon_update_nic_stats(efx);
-	}
-	spin_unlock(&efx->stats_lock);
+	spin_lock_bh(&efx->stats_lock);
+	efx->type->update_stats(efx);
+	spin_unlock_bh(&efx->stats_lock);
 
 	stats->rx_packets = mac_stats->rx_packets;
 	stats->tx_packets = mac_stats->tx_packets;
@@ -1490,7 +1560,14 @@
 	EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
 
 	efx_fini_channels(efx);
+
+	mutex_lock(&efx->mac_lock);
+	/* Reconfigure the MAC before enabling the dma queues so that
+	 * the RX buffers don't overflow */
 	net_dev->mtu = new_mtu;
+	efx->mac_op->reconfigure(efx);
+	mutex_unlock(&efx->mac_lock);
+
 	efx_init_channels(efx);
 
 	efx_start_all(efx);
@@ -1514,7 +1591,9 @@
 	memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len);
 
 	/* Reconfigure the MAC */
-	efx_reconfigure_port(efx);
+	mutex_lock(&efx->mac_lock);
+	efx->mac_op->reconfigure(efx);
+	mutex_unlock(&efx->mac_lock);
 
 	return 0;
 }
@@ -1525,16 +1604,14 @@
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct dev_mc_list *mc_list = net_dev->mc_list;
 	union efx_multicast_hash *mc_hash = &efx->multicast_hash;
-	bool promiscuous = !!(net_dev->flags & IFF_PROMISC);
-	bool changed = (efx->promiscuous != promiscuous);
 	u32 crc;
 	int bit;
 	int i;
 
-	efx->promiscuous = promiscuous;
+	efx->promiscuous = !!(net_dev->flags & IFF_PROMISC);
 
 	/* Build multicast hash table */
-	if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
+	if (efx->promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
 		memset(mc_hash, 0xff, sizeof(*mc_hash));
 	} else {
 		memset(mc_hash, 0x00, sizeof(*mc_hash));
@@ -1544,17 +1621,17 @@
 			set_bit_le(bit, mc_hash->byte);
 			mc_list = mc_list->next;
 		}
-	}
 
-	if (!efx->port_enabled)
-		/* Delay pushing settings until efx_start_port() */
-		return;
-
-	if (changed)
-		queue_work(efx->workqueue, &efx->phy_work);
+		/* 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.
+		 */
+		set_bit_le(0xff, mc_hash->byte);
+	}
 
-	/* Create and activate new global multicast hash table */
-	falcon_set_multicast_hash(efx);
+	if (efx->port_enabled)
+		queue_work(efx->workqueue, &efx->mac_work);
+	/* Otherwise efx_start_port() will do this */
 }
 
 static const struct net_device_ops efx_netdev_ops = {
@@ -1683,21 +1760,18 @@
 
 /* Tears down the entire software state and most of the hardware state
  * before reset.  */
-void efx_reset_down(struct efx_nic *efx, enum reset_type method,
-		    struct ethtool_cmd *ecmd)
+void efx_reset_down(struct efx_nic *efx, enum reset_type method)
 {
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
-	efx_stats_disable(efx);
 	efx_stop_all(efx);
 	mutex_lock(&efx->mac_lock);
 	mutex_lock(&efx->spi_lock);
 
-	efx->phy_op->get_settings(efx, ecmd);
-
 	efx_fini_channels(efx);
 	if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
 		efx->phy_op->fini(efx);
+	efx->type->fini(efx);
 }
 
 /* This function will always ensure that the locks acquired in
@@ -1705,79 +1779,67 @@
  * that we were unable to reinitialise the hardware, and the
  * driver should be disabled. If ok is false, then the rx and tx
  * engines are not restarted, pending a RESET_DISABLE. */
-int efx_reset_up(struct efx_nic *efx, enum reset_type method,
-		 struct ethtool_cmd *ecmd, bool ok)
+int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
 {
 	int rc;
 
 	EFX_ASSERT_RESET_SERIALISED(efx);
 
-	rc = falcon_init_nic(efx);
+	rc = efx->type->init(efx);
 	if (rc) {
 		EFX_ERR(efx, "failed to initialise NIC\n");
-		ok = false;
+		goto fail;
 	}
 
+	if (!ok)
+		goto fail;
+
 	if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
-		if (ok) {
-			rc = efx->phy_op->init(efx);
-			if (rc)
-				ok = false;
-		}
-		if (!ok)
-			efx->port_initialized = false;
+		rc = efx->phy_op->init(efx);
+		if (rc)
+			goto fail;
+		if (efx->phy_op->reconfigure(efx))
+			EFX_ERR(efx, "could not restore PHY settings\n");
 	}
 
-	if (ok) {
-		efx_init_channels(efx);
+	efx->mac_op->reconfigure(efx);
 
-		if (efx->phy_op->set_settings(efx, ecmd))
-			EFX_ERR(efx, "could not restore PHY settings\n");
-	}
+	efx_init_channels(efx);
+
+	mutex_unlock(&efx->spi_lock);
+	mutex_unlock(&efx->mac_lock);
+
+	efx_start_all(efx);
+
+	return 0;
+
+fail:
+	efx->port_initialized = false;
 
 	mutex_unlock(&efx->spi_lock);
 	mutex_unlock(&efx->mac_lock);
 
-	if (ok) {
-		efx_start_all(efx);
-		efx_stats_enable(efx);
-	}
 	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.
+/* Reset the NIC using the specified method.  Note that the reset may
+ * fail, in which case the card will be left in an unusable state.
  *
- * This function will sleep.  You cannot reset from within an atomic
- * state; use efx_schedule_reset() instead.
- *
- * Grabs the rtnl_lock.
+ * Caller must hold the rtnl_lock.
  */
-static int efx_reset(struct efx_nic *efx)
+int efx_reset(struct efx_nic *efx, enum reset_type method)
 {
-	struct ethtool_cmd ecmd;
-	enum reset_type method = efx->reset_pending;
-	int rc = 0;
-
-	/* Serialise with kernel interfaces */
-	rtnl_lock();
-
-	/* If we're not RUNNING then don't reset. Leave the reset_pending
-	 * flag set so that efx_pci_probe_main will be retried */
-	if (efx->state != STATE_RUNNING) {
-		EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
-		goto out_unlock;
-	}
+	int rc, rc2;
+	bool disabled;
 
-	EFX_INFO(efx, "resetting (%d)\n", method);
+	EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
 
-	efx_reset_down(efx, method, &ecmd);
+	efx_reset_down(efx, method);
 
-	rc = falcon_reset_hw(efx, method);
+	rc = efx->type->reset(efx, method);
 	if (rc) {
 		EFX_ERR(efx, "failed to reset hardware\n");
-		goto out_disable;
+		goto out;
 	}
 
 	/* Allow resets to be rescheduled. */
@@ -1789,25 +1851,23 @@
 	 * can respond to requests. */
 	pci_set_master(efx->pci_dev);
 
+out:
 	/* Leave device stopped if necessary */
-	if (method == RESET_TYPE_DISABLE) {
-		efx_reset_up(efx, method, &ecmd, false);
-		rc = -EIO;
-	} else {
-		rc = efx_reset_up(efx, method, &ecmd, true);
+	disabled = rc || method == RESET_TYPE_DISABLE;
+	rc2 = efx_reset_up(efx, method, !disabled);
+	if (rc2) {
+		disabled = true;
+		if (!rc)
+			rc = rc2;
 	}
 
-out_disable:
-	if (rc) {
+	if (disabled) {
+		dev_close(efx->net_dev);
 		EFX_ERR(efx, "has been disabled\n");
 		efx->state = STATE_DISABLED;
-		dev_close(efx->net_dev);
 	} else {
 		EFX_LOG(efx, "reset complete\n");
 	}
-
-out_unlock:
-	rtnl_unlock();
 	return rc;
 }
 
@@ -1816,9 +1876,18 @@
  */
 static void efx_reset_work(struct work_struct *data)
 {
-	struct efx_nic *nic = container_of(data, struct efx_nic, reset_work);
+	struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
+
+	/* If we're not RUNNING then don't reset. Leave the reset_pending
+	 * flag set so that efx_pci_probe_main will be retried */
+	if (efx->state != STATE_RUNNING) {
+		EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
+		return;
+	}
 
-	efx_reset(nic);
+	rtnl_lock();
+	(void)efx_reset(efx, efx->reset_pending);
+	rtnl_unlock();
 }
 
 void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
@@ -1843,18 +1912,24 @@
 	case RESET_TYPE_TX_SKIP:
 		method = RESET_TYPE_INVISIBLE;
 		break;
+	case RESET_TYPE_MC_FAILURE:
 	default:
 		method = RESET_TYPE_ALL;
 		break;
 	}
 
 	if (method != type)
-		EFX_LOG(efx, "scheduling reset (%d:%d)\n", type, method);
+		EFX_LOG(efx, "scheduling %s reset for %s\n",
+			RESET_TYPE(method), RESET_TYPE(type));
 	else
-		EFX_LOG(efx, "scheduling reset (%d)\n", method);
+		EFX_LOG(efx, "scheduling %s reset\n", RESET_TYPE(method));
 
 	efx->reset_pending = method;
 
+	/* efx_process_channel() will no longer read events once a
+	 * reset is scheduled. So switch back to poll'd MCDI completions. */
+	efx_mcdi_mode_poll(efx);
+
 	queue_work(reset_workqueue, &efx->reset_work);
 }
 
@@ -1867,15 +1942,19 @@
 /* PCI device ID table */
 static struct pci_device_id efx_pci_table[] __devinitdata = {
 	{PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID),
-	 .driver_data = (unsigned long) &falcon_a_nic_type},
+	 .driver_data = (unsigned long) &falcon_a1_nic_type},
 	{PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID),
-	 .driver_data = (unsigned long) &falcon_b_nic_type},
+	 .driver_data = (unsigned long) &falcon_b0_nic_type},
+	{PCI_DEVICE(EFX_VENDID_SFC, BETHPAGE_A_P_DEVID),
+	 .driver_data = (unsigned long) &siena_a0_nic_type},
+	{PCI_DEVICE(EFX_VENDID_SFC, SIENA_A_P_DEVID),
+	 .driver_data = (unsigned long) &siena_a0_nic_type},
 	{0}			/* end of list */
 };
 
 /**************************************************************************
  *
- * Dummy PHY/MAC/Board operations
+ * Dummy PHY/MAC operations
  *
  * Can be used for some unimplemented operations
  * Needed so all function pointers are valid and do not have to be tested
@@ -1887,29 +1966,19 @@
 	return 0;
 }
 void efx_port_dummy_op_void(struct efx_nic *efx) {}
-void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
-
-static struct efx_mac_operations efx_dummy_mac_operations = {
-	.reconfigure	= efx_port_dummy_op_void,
-	.poll		= efx_port_dummy_op_void,
-	.irq		= efx_port_dummy_op_void,
-};
+void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
+{
+}
+bool efx_port_dummy_op_poll(struct efx_nic *efx)
+{
+	return false;
+}
 
 static struct efx_phy_operations efx_dummy_phy_operations = {
 	.init		 = efx_port_dummy_op_int,
-	.reconfigure	 = efx_port_dummy_op_void,
-	.poll		 = efx_port_dummy_op_void,
+	.reconfigure	 = efx_port_dummy_op_int,
+	.poll		 = efx_port_dummy_op_poll,
 	.fini		 = efx_port_dummy_op_void,
-	.clear_interrupt = efx_port_dummy_op_void,
-};
-
-static struct efx_board efx_dummy_board_info = {
-	.init		= efx_port_dummy_op_int,
-	.init_leds	= efx_port_dummy_op_void,
-	.set_id_led	= efx_port_dummy_op_blink,
-	.monitor	= efx_port_dummy_op_int,
-	.blink		= efx_port_dummy_op_blink,
-	.fini		= efx_port_dummy_op_void,
 };
 
 /**************************************************************************
@@ -1932,26 +2001,26 @@
 	/* Initialise common structures */
 	memset(efx, 0, sizeof(*efx));
 	spin_lock_init(&efx->biu_lock);
-	spin_lock_init(&efx->phy_lock);
+	mutex_init(&efx->mdio_lock);
 	mutex_init(&efx->spi_lock);
+#ifdef CONFIG_SFC_MTD
+	INIT_LIST_HEAD(&efx->mtd_list);
+#endif
 	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->net_dev = net_dev;
 	efx->rx_checksum_enabled = true;
 	spin_lock_init(&efx->netif_stop_lock);
 	spin_lock_init(&efx->stats_lock);
-	efx->stats_disable_count = 1;
 	mutex_init(&efx->mac_lock);
-	efx->mac_op = &efx_dummy_mac_operations;
+	efx->mac_op = type->default_mac_ops;
 	efx->phy_op = &efx_dummy_phy_operations;
 	efx->mdio.dev = net_dev;
-	INIT_WORK(&efx->phy_work, efx_phy_work);
 	INIT_WORK(&efx->mac_work, efx_mac_work);
 	atomic_set(&efx->netif_stop_count, 1);
 
@@ -1981,17 +2050,9 @@
 
 	efx->type = 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));
+	BUILD_BUG_ON(EFX_EVQ_SIZE < EFX_TXQ_SIZE + EFX_RXQ_SIZE);
+
 	EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
 
 	/* Higher numbered interrupt modes are less capable! */
@@ -2027,19 +2088,10 @@
  */
 static void efx_pci_remove_main(struct efx_nic *efx)
 {
-	EFX_ASSERT_RESET_SERIALISED(efx);
-
-	/* Skip everything if we never obtained a valid membase */
-	if (!efx->membase)
-		return;
-
+	efx_nic_fini_interrupt(efx);
 	efx_fini_channels(efx);
 	efx_fini_port(efx);
-
-	/* Shutdown the board, then the NIC and board state */
-	efx->board_info.fini(efx);
-	falcon_fini_interrupt(efx);
-
+	efx->type->fini(efx);
 	efx_fini_napi(efx);
 	efx_remove_all(efx);
 }
@@ -2063,9 +2115,6 @@
 	/* Allow any queued efx_resets() to complete */
 	rtnl_unlock();
 
-	if (efx->membase == NULL)
-		goto out;
-
 	efx_unregister_netdev(efx);
 
 	efx_mtd_remove(efx);
@@ -2078,7 +2127,6 @@
 
 	efx_pci_remove_main(efx);
 
-out:
 	efx_fini_io(efx);
 	EFX_LOG(efx, "shutdown successful\n");
 
@@ -2103,39 +2151,31 @@
 	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;
-	}
-
-	rc = falcon_init_nic(efx);
+	rc = efx->type->init(efx);
 	if (rc) {
 		EFX_ERR(efx, "failed to initialise NIC\n");
-		goto fail4;
+		goto fail3;
 	}
 
 	rc = efx_init_port(efx);
 	if (rc) {
 		EFX_ERR(efx, "failed to initialise port\n");
-		goto fail5;
+		goto fail4;
 	}
 
 	efx_init_channels(efx);
 
-	rc = falcon_init_interrupt(efx);
+	rc = efx_nic_init_interrupt(efx);
 	if (rc)
-		goto fail6;
+		goto fail5;
 
 	return 0;
 
- fail6:
+ fail5:
 	efx_fini_channels(efx);
 	efx_fini_port(efx);
- fail5:
  fail4:
-	efx->board_info.fini(efx);
+	efx->type->fini(efx);
  fail3:
 	efx_fini_napi(efx);
  fail2:
@@ -2165,9 +2205,11 @@
 	net_dev = alloc_etherdev(sizeof(*efx));
 	if (!net_dev)
 		return -ENOMEM;
-	net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG |
+	net_dev->features |= (type->offload_features | NETIF_F_SG |
 			      NETIF_F_HIGHDMA | NETIF_F_TSO |
 			      NETIF_F_GRO);
+	if (type->offload_features & NETIF_F_V6_CSUM)
+		net_dev->features |= NETIF_F_TSO6;
 	/* Mask for features that also apply to VLAN devices */
 	net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
 				   NETIF_F_HIGHDMA | NETIF_F_TSO);
@@ -2219,18 +2261,19 @@
 		goto fail4;
 	}
 
-	/* 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. */
+	/* Switch to the running state before we expose the device to the OS,
+	 * so that dev_open()|efx_start_all() will actually start the device */
 	efx->state = STATE_RUNNING;
 
-	efx_mtd_probe(efx); /* allowed to fail */
-
 	rc = efx_register_netdev(efx);
 	if (rc)
 		goto fail5;
 
 	EFX_LOG(efx, "initialisation successful\n");
+
+	rtnl_lock();
+	efx_mtd_probe(efx); /* allowed to fail */
+	rtnl_unlock();
 	return 0;
 
  fail5:
@@ -2241,16 +2284,113 @@
  fail2:
 	efx_fini_struct(efx);
  fail1:
+	WARN_ON(rc > 0);
 	EFX_LOG(efx, "initialisation failed. rc=%d\n", rc);
 	free_netdev(net_dev);
 	return rc;
 }
 
+static int efx_pm_freeze(struct device *dev)
+{
+	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+
+	efx->state = STATE_FINI;
+
+	netif_device_detach(efx->net_dev);
+
+	efx_stop_all(efx);
+	efx_fini_channels(efx);
+
+	return 0;
+}
+
+static int efx_pm_thaw(struct device *dev)
+{
+	struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+
+	efx->state = STATE_INIT;
+
+	efx_init_channels(efx);
+
+	mutex_lock(&efx->mac_lock);
+	efx->phy_op->reconfigure(efx);
+	mutex_unlock(&efx->mac_lock);
+
+	efx_start_all(efx);
+
+	netif_device_attach(efx->net_dev);
+
+	efx->state = STATE_RUNNING;
+
+	efx->type->resume_wol(efx);
+
+	return 0;
+}
+
+static int efx_pm_poweroff(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct efx_nic *efx = pci_get_drvdata(pci_dev);
+
+	efx->type->fini(efx);
+
+	efx->reset_pending = RESET_TYPE_NONE;
+
+	pci_save_state(pci_dev);
+	return pci_set_power_state(pci_dev, PCI_D3hot);
+}
+
+/* Used for both resume and restore */
+static int efx_pm_resume(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct efx_nic *efx = pci_get_drvdata(pci_dev);
+	int rc;
+
+	rc = pci_set_power_state(pci_dev, PCI_D0);
+	if (rc)
+		return rc;
+	pci_restore_state(pci_dev);
+	rc = pci_enable_device(pci_dev);
+	if (rc)
+		return rc;
+	pci_set_master(efx->pci_dev);
+	rc = efx->type->reset(efx, RESET_TYPE_ALL);
+	if (rc)
+		return rc;
+	rc = efx->type->init(efx);
+	if (rc)
+		return rc;
+	efx_pm_thaw(dev);
+	return 0;
+}
+
+static int efx_pm_suspend(struct device *dev)
+{
+	int rc;
+
+	efx_pm_freeze(dev);
+	rc = efx_pm_poweroff(dev);
+	if (rc)
+		efx_pm_resume(dev);
+	return rc;
+}
+
+static struct dev_pm_ops efx_pm_ops = {
+	.suspend	= efx_pm_suspend,
+	.resume		= efx_pm_resume,
+	.freeze		= efx_pm_freeze,
+	.thaw		= efx_pm_thaw,
+	.poweroff	= efx_pm_poweroff,
+	.restore	= efx_pm_resume,
+};
+
 static struct pci_driver efx_pci_driver = {
 	.name		= EFX_DRIVER_NAME,
 	.id_table	= efx_pci_table,
 	.probe		= efx_pci_probe,
 	.remove		= efx_pci_remove,
+	.driver.pm	= &efx_pm_ops,
 };
 
 /**************************************************************************
@@ -2314,8 +2454,8 @@
 module_init(efx_init_module);
 module_exit(efx_exit_module);
 
-MODULE_AUTHOR("Michael Brown <mbrown@fensystems.co.uk> and "
-	      "Solarflare Communications");
+MODULE_AUTHOR("Solarflare Communications and "
+	      "Michael Brown <mbrown@fensystems.co.uk>");
 MODULE_DESCRIPTION("Solarflare Communications network driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, efx_pci_table);
--- linux-ec2-2.6.32.orig/drivers/net/sfc/rx.c
+++ linux-ec2-2.6.32/drivers/net/sfc/rx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2008 Solarflare Communications Inc.
+ * Copyright 2005-2009 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
@@ -16,9 +16,8 @@
 #include <net/ip.h>
 #include <net/checksum.h>
 #include "net_driver.h"
-#include "rx.h"
 #include "efx.h"
-#include "falcon.h"
+#include "nic.h"
 #include "selftest.h"
 #include "workarounds.h"
 
@@ -61,7 +60,7 @@
  *   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;
+static int rx_alloc_method = RX_ALLOC_METHOD_AUTO;
 
 #define RX_ALLOC_LEVEL_LRO 0x2000
 #define RX_ALLOC_LEVEL_MAX 0x3000
@@ -293,8 +292,7 @@
 	 * 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);
+	EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
 
 	/* Don't fill if we don't need to */
 	if (fill_level >= rx_queue->fast_fill_trigger)
@@ -316,8 +314,7 @@
  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);
+	EFX_BUG_ON_PARANOID(fill_level > EFX_RXQ_SIZE);
 	space = rx_queue->fast_fill_limit - fill_level;
 	if (space < EFX_RX_BATCH)
 		goto out_unlock;
@@ -329,8 +326,7 @@
 
 	do {
 		for (i = 0; i < EFX_RX_BATCH; ++i) {
-			index = (rx_queue->added_count &
-				 rx_queue->efx->type->rxd_ring_mask);
+			index = rx_queue->added_count & EFX_RXQ_MASK;
 			rx_buf = efx_rx_buffer(rx_queue, index);
 			rc = efx_init_rx_buffer(rx_queue, rx_buf);
 			if (unlikely(rc))
@@ -345,7 +341,7 @@
 
  out:
 	/* Send write pointer to card. */
-	falcon_notify_rx_desc(rx_queue);
+	efx_nic_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
@@ -448,17 +444,23 @@
 			      bool checksummed)
 {
 	struct napi_struct *napi = &channel->napi_str;
+	gro_result_t gro_result;
 
 	/* Pass the skb/page into the LRO engine */
 	if (rx_buf->page) {
-		struct sk_buff *skb = napi_get_frags(napi);
+		struct page *page = rx_buf->page;
+		struct sk_buff *skb;
 
+		EFX_BUG_ON_PARANOID(rx_buf->skb);
+		rx_buf->page = NULL;
+
+		skb = napi_get_frags(napi);
 		if (!skb) {
-			put_page(rx_buf->page);
-			goto out;
+			put_page(page);
+			return;
 		}
 
-		skb_shinfo(skb)->frags[0].page = rx_buf->page;
+		skb_shinfo(skb)->frags[0].page = page;
 		skb_shinfo(skb)->frags[0].page_offset =
 			efx_rx_buf_offset(rx_buf);
 		skb_shinfo(skb)->frags[0].size = rx_buf->len;
@@ -470,17 +472,24 @@
 		skb->ip_summed =
 			checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
 
-		napi_gro_frags(napi);
+		skb_record_rx_queue(skb, channel->channel);
 
-out:
-		EFX_BUG_ON_PARANOID(rx_buf->skb);
-		rx_buf->page = NULL;
+		gro_result = napi_gro_frags(napi);
 	} else {
-		EFX_BUG_ON_PARANOID(!rx_buf->skb);
-		EFX_BUG_ON_PARANOID(!checksummed);
+		struct sk_buff *skb = rx_buf->skb;
 
-		napi_gro_receive(napi, rx_buf->skb);
+		EFX_BUG_ON_PARANOID(!skb);
+		EFX_BUG_ON_PARANOID(!checksummed);
 		rx_buf->skb = NULL;
+
+		gro_result = napi_gro_receive(napi, skb);
+	}
+
+	if (gro_result == GRO_NORMAL) {
+		channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
+	} else if (gro_result != GRO_DROP) {
+		channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO;
+		channel->irq_mod_score += 2;
 	}
 }
 
@@ -558,7 +567,7 @@
 	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;
+		return;
 	}
 
 	if (rx_buf->skb) {
@@ -570,34 +579,28 @@
 		 * at the ethernet header */
 		rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
 						       efx->net_dev);
+
+		skb_record_rx_queue(rx_buf->skb, channel->channel);
 	}
 
 	if (likely(checksummed || rx_buf->page)) {
 		efx_rx_packet_lro(channel, rx_buf, checksummed);
-		goto done;
+		return;
 	}
 
 	/* 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 */
 	skb->ip_summed = CHECKSUM_NONE;
 
-	skb_record_rx_queue(skb, channel->channel);
-
 	/* Pass the packet up */
 	netif_receive_skb(skb);
 
 	/* Update allocation strategy method */
 	channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
-
-done:
-	;
 }
 
 void efx_rx_strategy(struct efx_channel *channel)
@@ -632,12 +635,12 @@
 	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);
+	rxq_size = EFX_RXQ_SIZE * sizeof(*rx_queue->buffer);
 	rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL);
 	if (!rx_queue->buffer)
 		return -ENOMEM;
 
-	rc = falcon_probe_rx(rx_queue);
+	rc = efx_nic_probe_rx(rx_queue);
 	if (rc) {
 		kfree(rx_queue->buffer);
 		rx_queue->buffer = NULL;
@@ -647,7 +650,6 @@
 
 void 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);
@@ -660,7 +662,7 @@
 	rx_queue->min_overfill = -1U;
 
 	/* Initialise limit fields */
-	max_fill = efx->type->rxd_ring_mask + 1 - EFX_RXD_HEAD_ROOM;
+	max_fill = EFX_RXQ_SIZE - EFX_RXD_HEAD_ROOM;
 	trigger = max_fill * min(rx_refill_threshold, 100U) / 100U;
 	limit = max_fill * min(rx_refill_limit, 100U) / 100U;
 
@@ -669,7 +671,7 @@
 	rx_queue->fast_fill_limit = limit;
 
 	/* Set up RX descriptor ring */
-	falcon_init_rx(rx_queue);
+	efx_nic_init_rx(rx_queue);
 }
 
 void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
@@ -679,11 +681,11 @@
 
 	EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue);
 
-	falcon_fini_rx(rx_queue);
+	efx_nic_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++) {
+		for (i = 0; i <= EFX_RXQ_MASK; i++) {
 			rx_buf = efx_rx_buffer(rx_queue, i);
 			efx_fini_rx_buffer(rx_queue, rx_buf);
 		}
@@ -704,7 +706,7 @@
 {
 	EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue);
 
-	falcon_remove_rx(rx_queue);
+	efx_nic_remove_rx(rx_queue);
 
 	kfree(rx_queue->buffer);
 	rx_queue->buffer = NULL;
--- linux-ec2-2.6.32.orig/drivers/net/sfc/nic.c
+++ linux-ec2-2.6.32/drivers/net/sfc/nic.c
@@ -0,0 +1,1585 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+
+#include <linux/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 "nic.h"
+#include "regs.h"
+#include "io.h"
+#include "workarounds.h"
+
+/**************************************************************************
+ *
+ * Configurable values
+ *
+ **************************************************************************
+ */
+
+/* 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.
+ */
+#define TX_DC_ENTRIES 16
+#define TX_DC_ENTRIES_ORDER 1
+
+#define RX_DC_ENTRIES 64
+#define RX_DC_ENTRIES_ORDER 3
+
+/* 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
+ */
+int efx_nic_rx_xoff_thresh = -1;
+module_param_named(rx_xoff_thresh_bytes, efx_nic_rx_xoff_thresh, 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
+ */
+int efx_nic_rx_xon_thresh = -1;
+module_param_named(rx_xon_thresh_bytes, efx_nic_rx_xon_thresh, int, 0644);
+MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
+
+/* If EFX_MAX_INT_ERRORS internal errors occur within
+ * EFX_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
+ * disable it.
+ */
+#define EFX_INT_ERROR_EXPIRE 3600
+#define EFX_MAX_INT_ERRORS 5
+
+/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times
+ */
+#define EFX_FLUSH_INTERVAL 10
+#define EFX_FLUSH_POLL_COUNT 100
+
+/* Size and alignment of special buffers (4KB) */
+#define EFX_BUF_SIZE 4096
+
+/* Depth of RX flush request fifo */
+#define EFX_RX_FLUSH_COUNT 4
+
+/**************************************************************************
+ *
+ * Solarstorm hardware access
+ *
+ **************************************************************************/
+
+static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
+				     unsigned int index)
+{
+	efx_sram_writeq(efx, efx->membase + efx->type->buf_tbl_base,
+			value, index);
+}
+
+/* Read the current event from the event queue */
+static inline efx_qword_t *efx_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 efx_event_present(efx_qword_t *event)
+{
+	return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) |
+		  EFX_DWORD_IS_ALL_ONES(event->dword[1])));
+}
+
+static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b,
+				     const efx_oword_t *mask)
+{
+	return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) ||
+		((a->u64[1] ^ b->u64[1]) & mask->u64[1]);
+}
+
+int efx_nic_test_registers(struct efx_nic *efx,
+			   const struct efx_nic_register_test *regs,
+			   size_t n_regs)
+{
+	unsigned address = 0, i, j;
+	efx_oword_t mask, imask, original, reg, buf;
+
+	/* Falcon should be in loopback to isolate the XMAC from the PHY */
+	WARN_ON(!LOOPBACK_INTERNAL(efx));
+
+	for (i = 0; i < n_regs; ++i) {
+		address = regs[i].address;
+		mask = imask = regs[i].mask;
+		EFX_INVERT_OWORD(imask);
+
+		efx_reado(efx, &original, address);
+
+		/* bit sweep on and off */
+		for (j = 0; j < 128; j++) {
+			if (!EFX_EXTRACT_OWORD32(mask, j, j))
+				continue;
+
+			/* Test this testable bit can be set in isolation */
+			EFX_AND_OWORD(reg, original, mask);
+			EFX_SET_OWORD32(reg, j, j, 1);
+
+			efx_writeo(efx, &reg, address);
+			efx_reado(efx, &buf, address);
+
+			if (efx_masked_compare_oword(&reg, &buf, &mask))
+				goto fail;
+
+			/* Test this testable bit can be cleared in isolation */
+			EFX_OR_OWORD(reg, original, mask);
+			EFX_SET_OWORD32(reg, j, j, 0);
+
+			efx_writeo(efx, &reg, address);
+			efx_reado(efx, &buf, address);
+
+			if (efx_masked_compare_oword(&reg, &buf, &mask))
+				goto fail;
+		}
+
+		efx_writeo(efx, &original, address);
+	}
+
+	return 0;
+
+fail:
+	EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT
+		" at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg),
+		EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask));
+	return -EIO;
+}
+
+/**************************************************************************
+ *
+ * Special buffer handling
+ * Special buffers are used for event queues and the TX and RX
+ * descriptor rings.
+ *
+ *************************************************************************/
+
+/*
+ * Initialise a special buffer
+ *
+ * This will define a buffer (previously allocated via
+ * efx_alloc_special_buffer()) in the buffer table, allowing
+ * it to be used for event queues, descriptor rings etc.
+ */
+static void
+efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
+{
+	efx_qword_t buf_desc;
+	int index;
+	dma_addr_t dma_addr;
+	int i;
+
+	EFX_BUG_ON_PARANOID(!buffer->addr);
+
+	/* 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_3(buf_desc,
+				     FRF_AZ_BUF_ADR_REGION, 0,
+				     FRF_AZ_BUF_ADR_FBUF, dma_addr >> 12,
+				     FRF_AZ_BUF_OWNER_ID_FBUF, 0);
+		efx_write_buf_tbl(efx, &buf_desc, index);
+	}
+}
+
+/* Unmaps a buffer and clears the buffer table entries */
+static void
+efx_fini_special_buffer(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);
+
+	if (!buffer->entries)
+		return;
+
+	EFX_LOG(efx, "unmapping special buffers %d-%d\n",
+		buffer->index, buffer->index + buffer->entries - 1);
+
+	EFX_POPULATE_OWORD_4(buf_tbl_upd,
+			     FRF_AZ_BUF_UPD_CMD, 0,
+			     FRF_AZ_BUF_CLR_CMD, 1,
+			     FRF_AZ_BUF_CLR_END_ID, end,
+			     FRF_AZ_BUF_CLR_START_ID, start);
+	efx_writeo(efx, &buf_tbl_upd, FR_AZ_BUF_TBL_UPD);
+}
+
+/*
+ * Allocate a new special buffer
+ *
+ * This allocates memory for a new buffer, clears it and allocates a
+ * new buffer ID range.  It does not write into the buffer table.
+ *
+ * This call will allocate 4KB buffers, since 8KB buffers can't be
+ * used for event queues and descriptor rings.
+ */
+static int efx_alloc_special_buffer(struct efx_nic *efx,
+				    struct efx_special_buffer *buffer,
+				    unsigned int len)
+{
+	len = ALIGN(len, EFX_BUF_SIZE);
+
+	buffer->addr = pci_alloc_consistent(efx->pci_dev, len,
+					    &buffer->dma_addr);
+	if (!buffer->addr)
+		return -ENOMEM;
+	buffer->len = len;
+	buffer->entries = len / EFX_BUF_SIZE;
+	BUG_ON(buffer->dma_addr & (EFX_BUF_SIZE - 1));
+
+	/* All zeros is a potentially valid event so memset to 0xff */
+	memset(buffer->addr, 0xff, len);
+
+	/* Select new buffer ID */
+	buffer->index = efx->next_buffer_table;
+	efx->next_buffer_table += buffer->entries;
+
+	EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
+		"(virt %p phys %llx)\n", buffer->index,
+		buffer->index + buffer->entries - 1,
+		(u64)buffer->dma_addr, len,
+		buffer->addr, (u64)virt_to_phys(buffer->addr));
+
+	return 0;
+}
+
+static void
+efx_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 %llx)\n", buffer->index,
+		buffer->index + buffer->entries - 1,
+		(u64)buffer->dma_addr, buffer->len,
+		buffer->addr, (u64)virt_to_phys(buffer->addr));
+
+	pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr,
+			    buffer->dma_addr);
+	buffer->addr = NULL;
+	buffer->entries = 0;
+}
+
+/**************************************************************************
+ *
+ * Generic buffer handling
+ * These buffers are used for interrupt status and MAC stats
+ *
+ **************************************************************************/
+
+int efx_nic_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;
+}
+
+void efx_nic_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;
+	}
+}
+
+/**************************************************************************
+ *
+ * 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 *
+efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
+{
+	return (((efx_qword_t *) (tx_queue->txd.addr)) + index);
+}
+
+/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
+static inline void efx_notify_tx_desc(struct efx_tx_queue *tx_queue)
+{
+	unsigned write_ptr;
+	efx_dword_t reg;
+
+	write_ptr = tx_queue->write_count & EFX_TXQ_MASK;
+	EFX_POPULATE_DWORD_1(reg, FRF_AZ_TX_DESC_WPTR_DWORD, write_ptr);
+	efx_writed_page(tx_queue->efx, &reg,
+			FR_AZ_TX_DESC_UPD_DWORD_P0, 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.
+ */
+void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
+{
+
+	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 & EFX_TXQ_MASK;
+		buffer = &tx_queue->buffer[write_ptr];
+		txd = efx_tx_desc(tx_queue, write_ptr);
+		++tx_queue->write_count;
+
+		/* Create TX descriptor ring entry */
+		EFX_POPULATE_QWORD_4(*txd,
+				     FSF_AZ_TX_KER_CONT, buffer->continuation,
+				     FSF_AZ_TX_KER_BYTE_COUNT, buffer->len,
+				     FSF_AZ_TX_KER_BUF_REGION, 0,
+				     FSF_AZ_TX_KER_BUF_ADDR, buffer->dma_addr);
+	} while (tx_queue->write_count != tx_queue->insert_count);
+
+	wmb(); /* Ensure descriptors are written before they are fetched */
+	efx_notify_tx_desc(tx_queue);
+}
+
+/* Allocate hardware resources for a TX queue */
+int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
+{
+	struct efx_nic *efx = tx_queue->efx;
+	BUILD_BUG_ON(EFX_TXQ_SIZE < 512 || EFX_TXQ_SIZE > 4096 ||
+		     EFX_TXQ_SIZE & EFX_TXQ_MASK);
+	return efx_alloc_special_buffer(efx, &tx_queue->txd,
+					EFX_TXQ_SIZE * sizeof(efx_qword_t));
+}
+
+void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
+{
+	efx_oword_t tx_desc_ptr;
+	struct efx_nic *efx = tx_queue->efx;
+
+	tx_queue->flushed = FLUSH_NONE;
+
+	/* Pin TX descriptor ring */
+	efx_init_special_buffer(efx, &tx_queue->txd);
+
+	/* Push TX descriptor ring to card */
+	EFX_POPULATE_OWORD_10(tx_desc_ptr,
+			      FRF_AZ_TX_DESCQ_EN, 1,
+			      FRF_AZ_TX_ISCSI_DDIG_EN, 0,
+			      FRF_AZ_TX_ISCSI_HDIG_EN, 0,
+			      FRF_AZ_TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index,
+			      FRF_AZ_TX_DESCQ_EVQ_ID,
+			      tx_queue->channel->channel,
+			      FRF_AZ_TX_DESCQ_OWNER_ID, 0,
+			      FRF_AZ_TX_DESCQ_LABEL, tx_queue->queue,
+			      FRF_AZ_TX_DESCQ_SIZE,
+			      __ffs(tx_queue->txd.entries),
+			      FRF_AZ_TX_DESCQ_TYPE, 0,
+			      FRF_BZ_TX_NON_IP_DROP_DIS, 1);
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		int csum = tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM;
+		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_TCP_CHKSM_DIS,
+				    !csum);
+	}
+
+	efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+			 tx_queue->queue);
+
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
+		efx_oword_t reg;
+
+		/* Only 128 bits in this register */
+		BUILD_BUG_ON(EFX_TX_QUEUE_COUNT >= 128);
+
+		efx_reado(efx, &reg, FR_AA_TX_CHKSM_CFG);
+		if (tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM)
+			clear_bit_le(tx_queue->queue, (void *)&reg);
+		else
+			set_bit_le(tx_queue->queue, (void *)&reg);
+		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
+	}
+}
+
+static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
+{
+	struct efx_nic *efx = tx_queue->efx;
+	efx_oword_t tx_flush_descq;
+
+	tx_queue->flushed = FLUSH_PENDING;
+
+	/* Post a flush command */
+	EFX_POPULATE_OWORD_2(tx_flush_descq,
+			     FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
+			     FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
+	efx_writeo(efx, &tx_flush_descq, FR_AZ_TX_FLUSH_DESCQ);
+}
+
+void efx_nic_fini_tx(struct efx_tx_queue *tx_queue)
+{
+	struct efx_nic *efx = tx_queue->efx;
+	efx_oword_t tx_desc_ptr;
+
+	/* The queue should have been flushed */
+	WARN_ON(tx_queue->flushed != FLUSH_DONE);
+
+	/* Remove TX descriptor ring from card */
+	EFX_ZERO_OWORD(tx_desc_ptr);
+	efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+			 tx_queue->queue);
+
+	/* Unpin TX descriptor ring */
+	efx_fini_special_buffer(efx, &tx_queue->txd);
+}
+
+/* Free buffers backing TX queue */
+void efx_nic_remove_tx(struct efx_tx_queue *tx_queue)
+{
+	efx_free_special_buffer(tx_queue->efx, &tx_queue->txd);
+}
+
+/**************************************************************************
+ *
+ * RX path
+ *
+ **************************************************************************/
+
+/* Returns a pointer to the specified descriptor in the RX descriptor queue */
+static inline efx_qword_t *
+efx_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 */
+static inline void
+efx_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned index)
+{
+	struct efx_rx_buffer *rx_buf;
+	efx_qword_t *rxd;
+
+	rxd = efx_rx_desc(rx_queue, index);
+	rx_buf = efx_rx_buffer(rx_queue, index);
+	EFX_POPULATE_QWORD_3(*rxd,
+			     FSF_AZ_RX_KER_BUF_SIZE,
+			     rx_buf->len -
+			     rx_queue->efx->type->rx_buffer_padding,
+			     FSF_AZ_RX_KER_BUF_REGION, 0,
+			     FSF_AZ_RX_KER_BUF_ADDR, rx_buf->dma_addr);
+}
+
+/* This writes to the RX_DESC_WPTR register for the specified receive
+ * descriptor ring.
+ */
+void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue)
+{
+	efx_dword_t reg;
+	unsigned write_ptr;
+
+	while (rx_queue->notified_count != rx_queue->added_count) {
+		efx_build_rx_desc(rx_queue,
+				  rx_queue->notified_count &
+				  EFX_RXQ_MASK);
+		++rx_queue->notified_count;
+	}
+
+	wmb();
+	write_ptr = rx_queue->added_count & EFX_RXQ_MASK;
+	EFX_POPULATE_DWORD_1(reg, FRF_AZ_RX_DESC_WPTR_DWORD, write_ptr);
+	efx_writed_page(rx_queue->efx, &reg,
+			FR_AZ_RX_DESC_UPD_DWORD_P0, rx_queue->queue);
+}
+
+int efx_nic_probe_rx(struct efx_rx_queue *rx_queue)
+{
+	struct efx_nic *efx = rx_queue->efx;
+	BUILD_BUG_ON(EFX_RXQ_SIZE < 512 || EFX_RXQ_SIZE > 4096 ||
+		     EFX_RXQ_SIZE & EFX_RXQ_MASK);
+	return efx_alloc_special_buffer(efx, &rx_queue->rxd,
+					EFX_RXQ_SIZE * sizeof(efx_qword_t));
+}
+
+void efx_nic_init_rx(struct efx_rx_queue *rx_queue)
+{
+	efx_oword_t rx_desc_ptr;
+	struct efx_nic *efx = rx_queue->efx;
+	bool is_b0 = efx_nic_rev(efx) >= EFX_REV_FALCON_B0;
+	bool 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);
+
+	rx_queue->flushed = FLUSH_NONE;
+
+	/* Pin RX descriptor ring */
+	efx_init_special_buffer(efx, &rx_queue->rxd);
+
+	/* Push RX descriptor ring to card */
+	EFX_POPULATE_OWORD_10(rx_desc_ptr,
+			      FRF_AZ_RX_ISCSI_DDIG_EN, iscsi_digest_en,
+			      FRF_AZ_RX_ISCSI_HDIG_EN, iscsi_digest_en,
+			      FRF_AZ_RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index,
+			      FRF_AZ_RX_DESCQ_EVQ_ID,
+			      rx_queue->channel->channel,
+			      FRF_AZ_RX_DESCQ_OWNER_ID, 0,
+			      FRF_AZ_RX_DESCQ_LABEL, rx_queue->queue,
+			      FRF_AZ_RX_DESCQ_SIZE,
+			      __ffs(rx_queue->rxd.entries),
+			      FRF_AZ_RX_DESCQ_TYPE, 0 /* kernel queue */ ,
+			      /* For >=B0 this is scatter so disable */
+			      FRF_AZ_RX_DESCQ_JUMBO, !is_b0,
+			      FRF_AZ_RX_DESCQ_EN, 1);
+	efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
+			 rx_queue->queue);
+}
+
+static void efx_flush_rx_queue(struct efx_rx_queue *rx_queue)
+{
+	struct efx_nic *efx = rx_queue->efx;
+	efx_oword_t rx_flush_descq;
+
+	rx_queue->flushed = FLUSH_PENDING;
+
+	/* Post a flush command */
+	EFX_POPULATE_OWORD_2(rx_flush_descq,
+			     FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
+			     FRF_AZ_RX_FLUSH_DESCQ, rx_queue->queue);
+	efx_writeo(efx, &rx_flush_descq, FR_AZ_RX_FLUSH_DESCQ);
+}
+
+void efx_nic_fini_rx(struct efx_rx_queue *rx_queue)
+{
+	efx_oword_t rx_desc_ptr;
+	struct efx_nic *efx = rx_queue->efx;
+
+	/* The queue should already have been flushed */
+	WARN_ON(rx_queue->flushed != FLUSH_DONE);
+
+	/* Remove RX descriptor ring from card */
+	EFX_ZERO_OWORD(rx_desc_ptr);
+	efx_writeo_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base,
+			 rx_queue->queue);
+
+	/* Unpin RX descriptor ring */
+	efx_fini_special_buffer(efx, &rx_queue->rxd);
+}
+
+/* Free buffers backing RX queue */
+void efx_nic_remove_rx(struct efx_rx_queue *rx_queue)
+{
+	efx_free_special_buffer(rx_queue->efx, &rx_queue->rxd);
+}
+
+/**************************************************************************
+ *
+ * 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.
+ */
+void efx_nic_eventq_read_ack(struct efx_channel *channel)
+{
+	efx_dword_t reg;
+	struct efx_nic *efx = channel->efx;
+
+	EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr);
+	efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
+			 channel->channel);
+}
+
+/* Use HW to insert a SW defined event */
+void efx_generate_event(struct efx_channel *channel, efx_qword_t *event)
+{
+	efx_oword_t drv_ev_reg;
+
+	BUILD_BUG_ON(FRF_AZ_DRV_EV_DATA_LBN != 0 ||
+		     FRF_AZ_DRV_EV_DATA_WIDTH != 64);
+	drv_ev_reg.u32[0] = event->u32[0];
+	drv_ev_reg.u32[1] = event->u32[1];
+	drv_ev_reg.u32[2] = 0;
+	drv_ev_reg.u32[3] = 0;
+	EFX_SET_OWORD_FIELD(drv_ev_reg, FRF_AZ_DRV_EV_QID, channel->channel);
+	efx_writeo(channel->efx, &drv_ev_reg, FR_AZ_DRV_EV);
+}
+
+/* Handle a transmit completion event
+ *
+ * The NIC batches TX completion events; the message we receive is of
+ * the form "complete all TX events up to this index".
+ */
+static void
+efx_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, FSF_AZ_TX_EV_COMP))) {
+		/* Transmit completion */
+		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_DESC_PTR);
+		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
+		tx_queue = &efx->tx_queue[tx_ev_q_label];
+		channel->irq_mod_score +=
+			(tx_ev_desc_ptr - tx_queue->read_count) &
+			EFX_TXQ_MASK;
+		efx_xmit_done(tx_queue, tx_ev_desc_ptr);
+	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_WQ_FF_FULL)) {
+		/* Rewrite the FIFO write pointer */
+		tx_ev_q_label = EFX_QWORD_FIELD(*event, FSF_AZ_TX_EV_Q_LABEL);
+		tx_queue = &efx->tx_queue[tx_ev_q_label];
+
+		if (efx_dev_registered(efx))
+			netif_tx_lock(efx->net_dev);
+		efx_notify_tx_desc(tx_queue);
+		if (efx_dev_registered(efx))
+			netif_tx_unlock(efx->net_dev);
+	} else if (EFX_QWORD_FIELD(*event, FSF_AZ_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));
+	}
+}
+
+/* Detect errors included in the rx_evt_pkt_ok bit. */
+static void efx_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
+				 const efx_qword_t *event,
+				 bool *rx_ev_pkt_ok,
+				 bool *discard)
+{
+	struct efx_nic *efx = rx_queue->efx;
+	bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
+	bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
+	bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
+	bool rx_ev_other_err, rx_ev_pause_frm;
+	bool rx_ev_hdr_type, rx_ev_mcast_pkt;
+	unsigned rx_ev_pkt_type;
+
+	rx_ev_hdr_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
+	rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_PKT);
+	rx_ev_tobe_disc = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_TOBE_DISC);
+	rx_ev_pkt_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_TYPE);
+	rx_ev_buf_owner_id_err = EFX_QWORD_FIELD(*event,
+						 FSF_AZ_RX_EV_BUF_OWNER_ID_ERR);
+	rx_ev_ip_hdr_chksum_err = EFX_QWORD_FIELD(*event,
+						  FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR);
+	rx_ev_tcp_udp_chksum_err = EFX_QWORD_FIELD(*event,
+						   FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR);
+	rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_ETH_CRC_ERR);
+	rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_FRM_TRUNC);
+	rx_ev_drib_nib = ((efx_nic_rev(efx) >= EFX_REV_FALCON_B0) ?
+			  0 : EFX_QWORD_FIELD(*event, FSF_AA_RX_EV_DRIB_NIB));
+	rx_ev_pause_frm = EFX_QWORD_FIELD(*event, FSF_AZ_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);
+
+	/* Count errors that are not in MAC stats.  Ignore expected
+	 * checksum errors during self-test. */
+	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 (!efx->loopback_selftest) {
+		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;
+	}
+
+	/* 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\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]" : "");
+	}
+#endif
+}
+
+/* Handle receive events that are not in-order. */
+static void
+efx_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 & EFX_RXQ_MASK;
+	dropped = (index - expected) & EFX_RXQ_MASK;
+	EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n",
+		dropped, index, expected);
+
+	efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ?
+			   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+}
+
+/* Handle a packet received event
+ *
+ * The NIC 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 void
+efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
+{
+	unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt;
+	unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt;
+	unsigned expected_ptr;
+	bool rx_ev_pkt_ok, discard = false, checksummed;
+	struct efx_rx_queue *rx_queue;
+	struct efx_nic *efx = channel->efx;
+
+	/* Basic packet information */
+	rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_BYTE_CNT);
+	rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_OK);
+	rx_ev_hdr_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
+	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_JUMBO_CONT));
+	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_SOP) != 1);
+	WARN_ON(EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_Q_LABEL) !=
+		channel->channel);
+
+	rx_queue = &efx->rx_queue[channel->channel];
+
+	rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_DESC_PTR);
+	expected_ptr = rx_queue->removed_count & EFX_RXQ_MASK;
+	if (unlikely(rx_ev_desc_ptr != expected_ptr))
+		efx_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr);
+
+	if (likely(rx_ev_pkt_ok)) {
+		/* If packet is marked as OK and packet type is TCP/IP or
+		 * UDP/IP, then we can rely on the hardware checksum.
+		 */
+		checksummed =
+			likely(efx->rx_checksum_enabled) &&
+			(rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP ||
+			 rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP);
+	} else {
+		efx_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, &discard);
+		checksummed = false;
+	}
+
+	/* Detect multicast packets that didn't match the filter */
+	rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_PKT);
+	if (rx_ev_mcast_pkt) {
+		unsigned int rx_ev_mcast_hash_match =
+			EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_HASH_MATCH);
+
+		if (unlikely(!rx_ev_mcast_hash_match)) {
+			++channel->n_rx_mcast_mismatch;
+			discard = true;
+		}
+	}
+
+	channel->irq_mod_score += 2;
+
+	/* Handle received packet */
+	efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt,
+		      checksummed, discard);
+}
+
+/* Global events are basically PHY events */
+static void
+efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
+{
+	struct efx_nic *efx = channel->efx;
+	bool handled = false;
+
+	if (EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_G_PHY0_INTR) ||
+	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XG_PHY0_INTR) ||
+	    EFX_QWORD_FIELD(*event, FSF_AB_GLB_EV_XFP_PHY0_INTR)) {
+		/* Ignored */
+		handled = true;
+	}
+
+	if ((efx_nic_rev(efx) >= EFX_REV_FALCON_B0) &&
+	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
+		efx->xmac_poll_required = true;
+		handled = true;
+	}
+
+	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1 ?
+	    EFX_QWORD_FIELD(*event, FSF_AA_GLB_EV_RX_RECOVERY) :
+	    EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_RX_RECOVERY)) {
+		EFX_ERR(efx, "channel %d seen global RX_RESET "
+			"event. Resetting.\n", channel->channel);
+
+		atomic_inc(&efx->rx_reset);
+		efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ?
+				   RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE);
+		handled = true;
+	}
+
+	if (!handled)
+		EFX_ERR(efx, "channel %d unknown global event "
+			EFX_QWORD_FMT "\n", channel->channel,
+			EFX_QWORD_VAL(*event));
+}
+
+static void
+efx_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, FSF_AZ_DRIVER_EV_SUBCODE);
+	ev_sub_data = EFX_QWORD_FIELD(*event, FSF_AZ_DRIVER_EV_SUBDATA);
+
+	switch (ev_sub_code) {
+	case FSE_AZ_TX_DESCQ_FLS_DONE_EV:
+		EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
+			  channel->channel, ev_sub_data);
+		break;
+	case FSE_AZ_RX_DESCQ_FLS_DONE_EV:
+		EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
+			  channel->channel, ev_sub_data);
+		break;
+	case FSE_AZ_EVQ_INIT_DONE_EV:
+		EFX_LOG(efx, "channel %d EVQ %d initialised\n",
+			channel->channel, ev_sub_data);
+		break;
+	case FSE_AZ_SRM_UPD_DONE_EV:
+		EFX_TRACE(efx, "channel %d SRAM update done\n",
+			  channel->channel);
+		break;
+	case FSE_AZ_WAKE_UP_EV:
+		EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
+			  channel->channel, ev_sub_data);
+		break;
+	case FSE_AZ_TIMER_EV:
+		EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
+			  channel->channel, ev_sub_data);
+		break;
+	case FSE_AA_RX_RECOVER_EV:
+		EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
+			"Resetting.\n", channel->channel);
+		atomic_inc(&efx->rx_reset);
+		efx_schedule_reset(efx,
+				   EFX_WORKAROUND_6555(efx) ?
+				   RESET_TYPE_RX_RECOVERY :
+				   RESET_TYPE_DISABLE);
+		break;
+	case FSE_BZ_RX_DSC_ERROR_EV:
+		EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error."
+			" RX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
+		efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH);
+		break;
+	case FSE_BZ_TX_DSC_ERROR_EV:
+		EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error."
+			" TX Q %d is disabled.\n", ev_sub_data, ev_sub_data);
+		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);
+		break;
+	}
+}
+
+int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota)
+{
+	unsigned int read_ptr;
+	efx_qword_t event, *p_event;
+	int ev_code;
+	int rx_packets = 0;
+
+	read_ptr = channel->eventq_read_ptr;
+
+	do {
+		p_event = efx_event(channel, read_ptr);
+		event = *p_event;
+
+		if (!efx_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, FSF_AZ_EV_CODE);
+
+		switch (ev_code) {
+		case FSE_AZ_EV_CODE_RX_EV:
+			efx_handle_rx_event(channel, &event);
+			++rx_packets;
+			break;
+		case FSE_AZ_EV_CODE_TX_EV:
+			efx_handle_tx_event(channel, &event);
+			break;
+		case FSE_AZ_EV_CODE_DRV_GEN_EV:
+			channel->eventq_magic = EFX_QWORD_FIELD(
+				event, FSF_AZ_DRV_GEN_EV_MAGIC);
+			EFX_LOG(channel->efx, "channel %d received generated "
+				"event "EFX_QWORD_FMT"\n", channel->channel,
+				EFX_QWORD_VAL(event));
+			break;
+		case FSE_AZ_EV_CODE_GLOBAL_EV:
+			efx_handle_global_event(channel, &event);
+			break;
+		case FSE_AZ_EV_CODE_DRIVER_EV:
+			efx_handle_driver_event(channel, &event);
+			break;
+		case FSE_CZ_EV_CODE_MCDI_EV:
+			efx_mcdi_process_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) & EFX_EVQ_MASK;
+
+	} while (rx_packets < rx_quota);
+
+	channel->eventq_read_ptr = read_ptr;
+	return rx_packets;
+}
+
+
+/* Allocate buffer table entries for event queue */
+int efx_nic_probe_eventq(struct efx_channel *channel)
+{
+	struct efx_nic *efx = channel->efx;
+	BUILD_BUG_ON(EFX_EVQ_SIZE < 512 || EFX_EVQ_SIZE > 32768 ||
+		     EFX_EVQ_SIZE & EFX_EVQ_MASK);
+	return efx_alloc_special_buffer(efx, &channel->eventq,
+					EFX_EVQ_SIZE * sizeof(efx_qword_t));
+}
+
+void efx_nic_init_eventq(struct efx_channel *channel)
+{
+	efx_oword_t reg;
+	struct efx_nic *efx = channel->efx;
+
+	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);
+
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
+		EFX_POPULATE_OWORD_3(reg,
+				     FRF_CZ_TIMER_Q_EN, 1,
+				     FRF_CZ_HOST_NOTIFY_MODE, 0,
+				     FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS);
+		efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
+	}
+
+	/* Pin event queue buffer */
+	efx_init_special_buffer(efx, &channel->eventq);
+
+	/* 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(reg,
+			     FRF_AZ_EVQ_EN, 1,
+			     FRF_AZ_EVQ_SIZE, __ffs(channel->eventq.entries),
+			     FRF_AZ_EVQ_BUF_BASE_ID, channel->eventq.index);
+	efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
+			 channel->channel);
+
+	efx->type->push_irq_moderation(channel);
+}
+
+void efx_nic_fini_eventq(struct efx_channel *channel)
+{
+	efx_oword_t reg;
+	struct efx_nic *efx = channel->efx;
+
+	/* Remove event queue from card */
+	EFX_ZERO_OWORD(reg);
+	efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
+			 channel->channel);
+	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
+		efx_writeo_table(efx, &reg, FR_BZ_TIMER_TBL, channel->channel);
+
+	/* Unpin event queue */
+	efx_fini_special_buffer(efx, &channel->eventq);
+}
+
+/* Free buffers backing event queue */
+void efx_nic_remove_eventq(struct efx_channel *channel)
+{
+	efx_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 efx_nic_generate_test_event(struct efx_channel *channel, unsigned int magic)
+{
+	efx_qword_t test_event;
+
+	EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
+			     FSE_AZ_EV_CODE_DRV_GEN_EV,
+			     FSF_AZ_DRV_GEN_EV_MAGIC, magic);
+	efx_generate_event(channel, &test_event);
+}
+
+/**************************************************************************
+ *
+ * Flush handling
+ *
+ **************************************************************************/
+
+
+static void efx_poll_flush_events(struct efx_nic *efx)
+{
+	struct efx_channel *channel = &efx->channel[0];
+	struct efx_tx_queue *tx_queue;
+	struct efx_rx_queue *rx_queue;
+	unsigned int read_ptr = channel->eventq_read_ptr;
+	unsigned int end_ptr = (read_ptr - 1) & EFX_EVQ_MASK;
+
+	do {
+		efx_qword_t *event = efx_event(channel, read_ptr);
+		int ev_code, ev_sub_code, ev_queue;
+		bool ev_failed;
+
+		if (!efx_event_present(event))
+			break;
+
+		ev_code = EFX_QWORD_FIELD(*event, FSF_AZ_EV_CODE);
+		ev_sub_code = EFX_QWORD_FIELD(*event,
+					      FSF_AZ_DRIVER_EV_SUBCODE);
+		if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
+		    ev_sub_code == FSE_AZ_TX_DESCQ_FLS_DONE_EV) {
+			ev_queue = EFX_QWORD_FIELD(*event,
+						   FSF_AZ_DRIVER_EV_SUBDATA);
+			if (ev_queue < EFX_TX_QUEUE_COUNT) {
+				tx_queue = efx->tx_queue + ev_queue;
+				tx_queue->flushed = FLUSH_DONE;
+			}
+		} else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
+			   ev_sub_code == FSE_AZ_RX_DESCQ_FLS_DONE_EV) {
+			ev_queue = EFX_QWORD_FIELD(
+				*event, FSF_AZ_DRIVER_EV_RX_DESCQ_ID);
+			ev_failed = EFX_QWORD_FIELD(
+				*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
+			if (ev_queue < efx->n_rx_queues) {
+				rx_queue = efx->rx_queue + ev_queue;
+				rx_queue->flushed =
+					ev_failed ? FLUSH_FAILED : FLUSH_DONE;
+			}
+		}
+
+		/* We're about to destroy the queue anyway, so
+		 * it's ok to throw away every non-flush event */
+		EFX_SET_QWORD(*event);
+
+		read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
+	} while (read_ptr != end_ptr);
+
+	channel->eventq_read_ptr = read_ptr;
+}
+
+/* Handle tx and rx flushes at the same time, since they run in
+ * parallel in the hardware and there's no reason for us to
+ * serialise them */
+int efx_nic_flush_queues(struct efx_nic *efx)
+{
+	struct efx_rx_queue *rx_queue;
+	struct efx_tx_queue *tx_queue;
+	int i, tx_pending, rx_pending;
+
+	/* If necessary prepare the hardware for flushing */
+	efx->type->prepare_flush(efx);
+
+	/* Flush all tx queues in parallel */
+	efx_for_each_tx_queue(tx_queue, efx)
+		efx_flush_tx_queue(tx_queue);
+
+	/* The hardware supports four concurrent rx flushes, each of which may
+	 * need to be retried if there is an outstanding descriptor fetch */
+	for (i = 0; i < EFX_FLUSH_POLL_COUNT; ++i) {
+		rx_pending = tx_pending = 0;
+		efx_for_each_rx_queue(rx_queue, efx) {
+			if (rx_queue->flushed == FLUSH_PENDING)
+				++rx_pending;
+		}
+		efx_for_each_rx_queue(rx_queue, efx) {
+			if (rx_pending == EFX_RX_FLUSH_COUNT)
+				break;
+			if (rx_queue->flushed == FLUSH_FAILED ||
+			    rx_queue->flushed == FLUSH_NONE) {
+				efx_flush_rx_queue(rx_queue);
+				++rx_pending;
+			}
+		}
+		efx_for_each_tx_queue(tx_queue, efx) {
+			if (tx_queue->flushed != FLUSH_DONE)
+				++tx_pending;
+		}
+
+		if (rx_pending == 0 && tx_pending == 0)
+			return 0;
+
+		msleep(EFX_FLUSH_INTERVAL);
+		efx_poll_flush_events(efx);
+	}
+
+	/* Mark the queues as all flushed. We're going to return failure
+	 * leading to a reset, or fake up success anyway */
+	efx_for_each_tx_queue(tx_queue, efx) {
+		if (tx_queue->flushed != FLUSH_DONE)
+			EFX_ERR(efx, "tx queue %d flush command timed out\n",
+				tx_queue->queue);
+		tx_queue->flushed = FLUSH_DONE;
+	}
+	efx_for_each_rx_queue(rx_queue, efx) {
+		if (rx_queue->flushed != FLUSH_DONE)
+			EFX_ERR(efx, "rx queue %d flush command timed out\n",
+				rx_queue->queue);
+		rx_queue->flushed = FLUSH_DONE;
+	}
+
+	if (EFX_WORKAROUND_7803(efx))
+		return 0;
+
+	return -ETIMEDOUT;
+}
+
+/**************************************************************************
+ *
+ * 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 interrupts */
+static inline void efx_nic_interrupts(struct efx_nic *efx,
+				      bool enabled, bool force)
+{
+	efx_oword_t int_en_reg_ker;
+	unsigned int level = 0;
+
+	if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx))
+		/* Set the level always even if we're generating a test
+		 * interrupt, because our legacy interrupt handler is safe */
+		level = 0x1f;
+
+	EFX_POPULATE_OWORD_3(int_en_reg_ker,
+			     FRF_AZ_KER_INT_LEVE_SEL, level,
+			     FRF_AZ_KER_INT_KER, force,
+			     FRF_AZ_DRV_INT_EN_KER, enabled);
+	efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER);
+}
+
+void efx_nic_enable_interrupts(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+
+	EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr));
+	wmb(); /* Ensure interrupt vector is clear before interrupts enabled */
+
+	/* Enable interrupts */
+	efx_nic_interrupts(efx, true, false);
+
+	/* Force processing of all the channels to get the EVQ RPTRs up to
+	   date */
+	efx_for_each_channel(channel, efx)
+		efx_schedule_channel(channel);
+}
+
+void efx_nic_disable_interrupts(struct efx_nic *efx)
+{
+	/* Disable interrupts */
+	efx_nic_interrupts(efx, false, false);
+}
+
+/* Generate a test interrupt
+ * Interrupt must already have been enabled, otherwise nasty things
+ * may happen.
+ */
+void efx_nic_generate_interrupt(struct efx_nic *efx)
+{
+	efx_nic_interrupts(efx, true, true);
+}
+
+/* Process a fatal interrupt
+ * Disable bus mastering ASAP and schedule a reset
+ */
+irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
+{
+	struct falcon_nic_data *nic_data = efx->nic_data;
+	efx_oword_t *int_ker = efx->irq_status.addr;
+	efx_oword_t fatal_intr;
+	int error, mem_perr;
+
+	efx_reado(efx, &fatal_intr, FR_AZ_FATAL_INTR_KER);
+	error = EFX_OWORD_FIELD(fatal_intr, FRF_AZ_FATAL_INTR);
+
+	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, FRF_AZ_MEM_PERR_INT_KER);
+	if (mem_perr) {
+		efx_oword_t reg;
+		efx_reado(efx, &reg, FR_AZ_MEM_STAT);
+		EFX_ERR(efx, "SYSTEM ERROR: memory parity error "
+			EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg));
+	}
+
+	/* Disable both devices */
+	pci_clear_master(efx->pci_dev);
+	if (efx_nic_is_dual_func(efx))
+		pci_clear_master(nic_data->pci_dev2);
+	efx_nic_disable_interrupts(efx);
+
+	/* Count errors and reset or disable the NIC accordingly */
+	if (efx->int_error_count == 0 ||
+	    time_after(jiffies, efx->int_error_expire)) {
+		efx->int_error_count = 0;
+		efx->int_error_expire =
+			jiffies + EFX_INT_ERROR_EXPIRE * HZ;
+	}
+	if (++efx->int_error_count < EFX_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
+ * Acknowledges the interrupt and schedule event queue processing.
+ */
+static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
+{
+	struct efx_nic *efx = dev_id;
+	efx_oword_t *int_ker = efx->irq_status.addr;
+	irqreturn_t result = IRQ_NONE;
+	struct efx_channel *channel;
+	efx_dword_t reg;
+	u32 queues;
+	int syserr;
+
+	/* Read the ISR which also ACKs the interrupts */
+	efx_readd(efx, &reg, FR_BZ_INT_ISR0);
+	queues = EFX_EXTRACT_DWORD(reg, 0, 31);
+
+	/* Check to see if we have a serious error condition */
+	syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
+	if (unlikely(syserr))
+		return efx_nic_fatal_interrupt(efx);
+
+	if (queues != 0) {
+		if (EFX_WORKAROUND_15783(efx))
+			efx->irq_zero_count = 0;
+
+		/* Schedule processing of any interrupting queues */
+		efx_for_each_channel(channel, efx) {
+			if (queues & 1)
+				efx_schedule_channel(channel);
+			queues >>= 1;
+		}
+		result = IRQ_HANDLED;
+
+	} else if (EFX_WORKAROUND_15783(efx) &&
+		   efx->irq_zero_count++ == 0) {
+		efx_qword_t *event;
+
+		/* Ensure we rearm all event queues */
+		efx_for_each_channel(channel, efx) {
+			event = efx_event(channel, channel->eventq_read_ptr);
+			if (efx_event_present(event))
+				efx_schedule_channel(channel);
+		}
+
+		result = IRQ_HANDLED;
+	}
+
+	if (result == IRQ_HANDLED) {
+		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));
+	}
+
+	return result;
+}
+
+/* Handle an MSI interrupt
+ *
+ * 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.
+ */
+static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
+{
+	struct efx_channel *channel = dev_id;
+	struct efx_nic *efx = channel->efx;
+	efx_oword_t *int_ker = 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, FSF_AZ_NET_IVEC_FATAL_INT);
+	if (unlikely(syserr))
+		return efx_nic_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 efx_setup_rss_indir_table(struct efx_nic *efx)
+{
+	int i = 0;
+	unsigned long offset;
+	efx_dword_t dword;
+
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
+		return;
+
+	for (offset = FR_BZ_RX_INDIRECTION_TBL;
+	     offset < FR_BZ_RX_INDIRECTION_TBL + 0x800;
+	     offset += 0x10) {
+		EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
+				     i % efx->n_rx_queues);
+		efx_writed(efx, &dword, offset);
+		i++;
+	}
+}
+
+/* Hook interrupt handler(s)
+ * Try MSI and then legacy interrupts.
+ */
+int efx_nic_init_interrupt(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+	int rc;
+
+	if (!EFX_INT_MODE_USE_MSI(efx)) {
+		irq_handler_t handler;
+		if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
+			handler = efx_legacy_interrupt;
+		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(channel, efx) {
+		rc = request_irq(channel->irq, efx_msi_interrupt,
+				 IRQF_PROBE_SHARED, /* Not shared */
+				 channel->name, channel);
+		if (rc) {
+			EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
+			goto fail2;
+		}
+	}
+
+	return 0;
+
+ fail2:
+	efx_for_each_channel(channel, efx)
+		free_irq(channel->irq, channel);
+ fail1:
+	return rc;
+}
+
+void efx_nic_fini_interrupt(struct efx_nic *efx)
+{
+	struct efx_channel *channel;
+	efx_oword_t reg;
+
+	/* Disable MSI/MSI-X interrupts */
+	efx_for_each_channel(channel, efx) {
+		if (channel->irq)
+			free_irq(channel->irq, channel);
+	}
+
+	/* ACK legacy interrupt */
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
+		efx_reado(efx, &reg, FR_BZ_INT_ISR0);
+	else
+		falcon_irq_ack_a1(efx);
+
+	/* Disable legacy interrupt */
+	if (efx->legacy_irq)
+		free_irq(efx->legacy_irq, efx);
+}
+
+u32 efx_nic_fpga_ver(struct efx_nic *efx)
+{
+	efx_oword_t altera_build;
+	efx_reado(efx, &altera_build, FR_AZ_ALTERA_BUILD);
+	return EFX_OWORD_FIELD(altera_build, FRF_AZ_ALTERA_BUILD_VER);
+}
+
+void efx_nic_init_common(struct efx_nic *efx)
+{
+	efx_oword_t temp;
+
+	/* Set positions of descriptor caches in SRAM. */
+	EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR,
+			     efx->type->tx_dc_base / 8);
+	efx_writeo(efx, &temp, FR_AZ_SRM_TX_DC_CFG);
+	EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR,
+			     efx->type->rx_dc_base / 8);
+	efx_writeo(efx, &temp, FR_AZ_SRM_RX_DC_CFG);
+
+	/* Set TX descriptor cache size. */
+	BUILD_BUG_ON(TX_DC_ENTRIES != (8 << TX_DC_ENTRIES_ORDER));
+	EFX_POPULATE_OWORD_1(temp, FRF_AZ_TX_DC_SIZE, TX_DC_ENTRIES_ORDER);
+	efx_writeo(efx, &temp, FR_AZ_TX_DC_CFG);
+
+	/* Set RX descriptor cache size.  Set low watermark to size-8, as
+	 * this allows most efficient prefetching.
+	 */
+	BUILD_BUG_ON(RX_DC_ENTRIES != (8 << RX_DC_ENTRIES_ORDER));
+	EFX_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_SIZE, RX_DC_ENTRIES_ORDER);
+	efx_writeo(efx, &temp, FR_AZ_RX_DC_CFG);
+	EFX_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_PF_LWM, RX_DC_ENTRIES - 8);
+	efx_writeo(efx, &temp, FR_AZ_RX_DC_PF_WM);
+
+	/* Program INT_KER address */
+	EFX_POPULATE_OWORD_2(temp,
+			     FRF_AZ_NORM_INT_VEC_DIS_KER,
+			     EFX_INT_MODE_USE_MSI(efx),
+			     FRF_AZ_INT_ADR_KER, efx->irq_status.dma_addr);
+	efx_writeo(efx, &temp, FR_AZ_INT_ADR_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,
+			     FRF_AZ_ILL_ADR_INT_KER_EN, 1,
+			     FRF_AZ_RBUF_OWN_INT_KER_EN, 1,
+			     FRF_AZ_TBUF_OWN_INT_KER_EN, 1);
+	EFX_INVERT_OWORD(temp);
+	efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
+
+	efx_setup_rss_indir_table(efx);
+
+	/* 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.
+	 */
+	efx_reado(efx, &temp, FR_AZ_TX_RESERVED);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER, 0xfe);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_RX_SPACER_EN, 1);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_ONE_PKT_PER_Q, 1);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PUSH_EN, 0);
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_DIS_NON_IP_EV, 1);
+	/* Enable SW_EV to inherit in char driver - assume harmless here */
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1);
+	/* Prefetch threshold 2 => fetch when descriptor cache half empty */
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2);
+	/* Disable hardware watchdog which can misfire */
+	EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff);
+	/* Squash TX of packets of 16 bytes or less */
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
+		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
+	efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/nic.h
+++ linux-ec2-2.6.32/drivers/net/sfc/nic.h
@@ -0,0 +1,261 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2009 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, incorporated herein by reference.
+ */
+
+#ifndef EFX_NIC_H
+#define EFX_NIC_H
+
+#include <linux/i2c-algo-bit.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "mcdi.h"
+
+/*
+ * Falcon hardware control
+ */
+
+enum {
+	EFX_REV_FALCON_A0 = 0,
+	EFX_REV_FALCON_A1 = 1,
+	EFX_REV_FALCON_B0 = 2,
+	EFX_REV_SIENA_A0 = 3,
+};
+
+static inline int efx_nic_rev(struct efx_nic *efx)
+{
+	return efx->type->revision;
+}
+
+extern u32 efx_nic_fpga_ver(struct efx_nic *efx);
+
+static inline bool efx_nic_has_mc(struct efx_nic *efx)
+{
+	return efx_nic_rev(efx) >= EFX_REV_SIENA_A0;
+}
+/* NIC has two interlinked PCI functions for the same port. */
+static inline bool efx_nic_is_dual_func(struct efx_nic *efx)
+{
+	return efx_nic_rev(efx) < EFX_REV_FALCON_B0;
+}
+
+enum {
+	PHY_TYPE_NONE = 0,
+	PHY_TYPE_TXC43128 = 1,
+	PHY_TYPE_88E1111 = 2,
+	PHY_TYPE_SFX7101 = 3,
+	PHY_TYPE_QT2022C2 = 4,
+	PHY_TYPE_PM8358 = 6,
+	PHY_TYPE_SFT9001A = 8,
+	PHY_TYPE_QT2025C = 9,
+	PHY_TYPE_SFT9001B = 10,
+};
+
+#define FALCON_XMAC_LOOPBACKS			\
+	((1 << LOOPBACK_XGMII) |		\
+	 (1 << LOOPBACK_XGXS) |			\
+	 (1 << LOOPBACK_XAUI))
+
+#define FALCON_GMAC_LOOPBACKS			\
+	(1 << LOOPBACK_GMAC)
+
+/**
+ * struct falcon_board_type - board operations and type information
+ * @id: Board type id, as found in NVRAM
+ * @ref_model: Model number of Solarflare reference design
+ * @gen_type: Generic board type description
+ * @init: Allocate resources and initialise peripheral hardware
+ * @init_phy: Do board-specific PHY initialisation
+ * @fini: Shut down hardware and free resources
+ * @set_id_led: Set state of identifying LED or revert to automatic function
+ * @monitor: Board-specific health check function
+ */
+struct falcon_board_type {
+	u8 id;
+	const char *ref_model;
+	const char *gen_type;
+	int (*init) (struct efx_nic *nic);
+	void (*init_phy) (struct efx_nic *efx);
+	void (*fini) (struct efx_nic *nic);
+	void (*set_id_led) (struct efx_nic *efx, enum efx_led_mode mode);
+	int (*monitor) (struct efx_nic *nic);
+};
+
+/**
+ * struct falcon_board - board information
+ * @type: Type of board
+ * @major: Major rev. ('A', 'B' ...)
+ * @minor: Minor rev. (0, 1, ...)
+ * @i2c_adap: I2C adapter for on-board peripherals
+ * @i2c_data: Data for bit-banging algorithm
+ * @hwmon_client: I2C client for hardware monitor
+ * @ioexp_client: I2C client for power/port control
+ */
+struct falcon_board {
+	const struct falcon_board_type *type;
+	int major;
+	int minor;
+	struct i2c_adapter i2c_adap;
+	struct i2c_algo_bit_data i2c_data;
+	struct i2c_client *hwmon_client, *ioexp_client;
+};
+
+/**
+ * struct falcon_nic_data - Falcon NIC state
+ * @pci_dev2: Secondary function of Falcon A
+ * @board: Board state and functions
+ * @stats_disable_count: Nest count for disabling statistics fetches
+ * @stats_pending: Is there a pending DMA of MAC statistics.
+ * @stats_timer: A timer for regularly fetching MAC statistics.
+ * @stats_dma_done: Pointer to the flag which indicates DMA completion.
+ */
+struct falcon_nic_data {
+	struct pci_dev *pci_dev2;
+	struct falcon_board board;
+	unsigned int stats_disable_count;
+	bool stats_pending;
+	struct timer_list stats_timer;
+	u32 *stats_dma_done;
+};
+
+static inline struct falcon_board *falcon_board(struct efx_nic *efx)
+{
+	struct falcon_nic_data *data = efx->nic_data;
+	return &data->board;
+}
+
+/**
+ * struct siena_nic_data - Siena NIC state
+ * @fw_version: Management controller firmware version
+ * @fw_build: Firmware build number
+ * @mcdi: Management-Controller-to-Driver Interface
+ * @wol_filter_id: Wake-on-LAN packet filter id
+ */
+struct siena_nic_data {
+	u64 fw_version;
+	u32 fw_build;
+	struct efx_mcdi_iface mcdi;
+	int wol_filter_id;
+};
+
+extern void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len);
+
+extern struct efx_nic_type falcon_a1_nic_type;
+extern struct efx_nic_type falcon_b0_nic_type;
+extern struct efx_nic_type siena_a0_nic_type;
+
+/**************************************************************************
+ *
+ * Externs
+ *
+ **************************************************************************
+ */
+
+extern int falcon_probe_board(struct efx_nic *efx, u16 revision_info);
+
+/* TX data path */
+extern int efx_nic_probe_tx(struct efx_tx_queue *tx_queue);
+extern void efx_nic_init_tx(struct efx_tx_queue *tx_queue);
+extern void efx_nic_fini_tx(struct efx_tx_queue *tx_queue);
+extern void efx_nic_remove_tx(struct efx_tx_queue *tx_queue);
+extern void efx_nic_push_buffers(struct efx_tx_queue *tx_queue);
+
+/* RX data path */
+extern int efx_nic_probe_rx(struct efx_rx_queue *rx_queue);
+extern void efx_nic_init_rx(struct efx_rx_queue *rx_queue);
+extern void efx_nic_fini_rx(struct efx_rx_queue *rx_queue);
+extern void efx_nic_remove_rx(struct efx_rx_queue *rx_queue);
+extern void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue);
+
+/* Event data path */
+extern int efx_nic_probe_eventq(struct efx_channel *channel);
+extern void efx_nic_init_eventq(struct efx_channel *channel);
+extern void efx_nic_fini_eventq(struct efx_channel *channel);
+extern void efx_nic_remove_eventq(struct efx_channel *channel);
+extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
+extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
+
+/* MAC/PHY */
+extern void falcon_drain_tx_fifo(struct efx_nic *efx);
+extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
+extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
+
+/* Interrupts and test events */
+extern int efx_nic_init_interrupt(struct efx_nic *efx);
+extern void efx_nic_enable_interrupts(struct efx_nic *efx);
+extern void efx_nic_generate_test_event(struct efx_channel *channel,
+					unsigned int magic);
+extern void efx_nic_generate_interrupt(struct efx_nic *efx);
+extern void efx_nic_disable_interrupts(struct efx_nic *efx);
+extern void efx_nic_fini_interrupt(struct efx_nic *efx);
+extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx);
+extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id);
+extern void falcon_irq_ack_a1(struct efx_nic *efx);
+
+#define EFX_IRQ_MOD_RESOLUTION 5
+
+/* Global Resources */
+extern int efx_nic_flush_queues(struct efx_nic *efx);
+extern void falcon_start_nic_stats(struct efx_nic *efx);
+extern void falcon_stop_nic_stats(struct efx_nic *efx);
+extern int falcon_reset_xaui(struct efx_nic *efx);
+extern void efx_nic_init_common(struct efx_nic *efx);
+
+int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
+			 unsigned int len);
+void efx_nic_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer);
+
+/* Tests */
+struct efx_nic_register_test {
+	unsigned address;
+	efx_oword_t mask;
+};
+extern int efx_nic_test_registers(struct efx_nic *efx,
+				  const struct efx_nic_register_test *regs,
+				  size_t n_regs);
+
+/**************************************************************************
+ *
+ * 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 efx_nic_generate_event(struct efx_channel *channel,
+				   efx_qword_t *event);
+
+extern void falcon_poll_xmac(struct efx_nic *efx);
+
+#endif /* EFX_NIC_H */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/mac.h
+++ linux-ec2-2.6.32/drivers/net/sfc/mac.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2009 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
@@ -15,5 +15,9 @@
 
 extern struct efx_mac_operations falcon_gmac_operations;
 extern struct efx_mac_operations falcon_xmac_operations;
+extern struct efx_mac_operations efx_mcdi_mac_operations;
+extern void falcon_reconfigure_xmac_core(struct efx_nic *efx);
+extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
+			      u32 dma_len, int enable, int clear);
 
 #endif
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/efrm_internal.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/efrm_internal.h
@@ -0,0 +1,41 @@
+#ifndef __EFRM_INTERNAL_H__
+#define __EFRM_INTERNAL_H__
+
+
+struct filter_resource {
+	struct efrm_resource rs;
+	struct vi_resource *pt;
+	int filter_idx;
+};
+
+#define filter_resource(rs1)  container_of((rs1), struct filter_resource, rs)
+
+
+struct efrm_client {
+	void *user_data;
+	struct list_head link;
+	struct efrm_client_callbacks *callbacks;
+	struct efhw_nic *nic;
+	int ref_count;
+	struct list_head resources;
+};
+
+
+extern void efrm_client_add_resource(struct efrm_client *,
+				     struct efrm_resource *);
+
+extern int efrm_buffer_table_size(void);
+
+
+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);
+	rs->rs_ref_count = 1;
+	rs->rs_handle.handle = (type << 28u) |
+		(((unsigned)jiffies & 0xfff) << 16) | instance;
+}
+
+
+#endif  /* __EFRM_INTERNAL_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/vi_resource_alloc.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/vi_resource_alloc.c
@@ -0,0 +1,820 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/efrm_client.h>
+#include "efrm_internal.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(struct efrm_client *client,
+			       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(virs->rs.rs_client, 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_tablep->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_tablep->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",
+			     __func__);
+			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",
+				  __func__);
+			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_tablep->a_nic == NULL)	/* ?? FIXME: surely not right */
+		return;
+
+	if (efrm_nic_tablep->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 ((size & sizes) && size >= size_rq)
+			return size;
+		else if ((sizes & ~((size - 1) | size)) == 0)
+			return -1;
+}
+
+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 ", __func__,
+				   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, __func__,
+				   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)",
+			   __func__,
+			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
+	}
+}
+
+/*** Buffer Table allocations ********************************************/
+
+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",
+			     __func__, 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",
+			     __func__, 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;
+}
+
+/*** Per-NIC allocations *************************************************/
+
+static inline int
+efrm_vi_rm_init_evq(struct vi_resource *virs, struct efhw_nic *nic)
+{
+	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	struct eventq_resource_hardware *evq_hw =
+	    &virs->nic_info.evq_pages;
+	uint32_t buf_bytes = efrm_vi_rm_evq_bytes(virs);
+	int rc;
+
+	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",
+			  __func__, 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", __func__, 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,
+				    instance < 64);
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " capacity=%u", __func__,
+		   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_ROUNDUP(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, struct efhw_nic *nic)
+{
+	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	struct vi_resource_nic_info *nic_info = &virs->nic_info;
+
+	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;
+	int evq_instance;
+	efhw_buffer_addr_t buf_addr;
+
+	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	evq_instance = EFRM_RESOURCE_INSTANCE(virs->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,
+			     struct efhw_nic *nic)
+{
+	int rc;
+	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	uint32_t buf_bytes;
+	struct vi_resource_nic_info *nic_info = &virs->nic_info;
+	int page_order;
+	uint32_t num_pages;
+	struct efhw_iopages *iobuff;
+
+	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));
+
+	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.", __func__,
+			 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 += roundup(buf_bytes, PAGE_SIZE);
+
+	/* Make sure there is an event queue. */
+	if (virs->evq_virs->evq_capacity <= 0) {
+		EFRM_ERR("%s: Cannot use empty event queue for %s DMA",
+			 __func__, 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;
+
+	/* Ensure TX pacing turned off -- queue flush doesn't reset this. */
+	if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX)
+		falcon_nic_pace(nic, instance, 0);
+
+	/* No need to disable the queue here.  Nobody is using it anyway. */
+
+fail_evq:
+	efhw_iopages_free(nic, &nic_info->dmaq_pages[queue_type]);
+fail_iopages:
+
+	return rc;
+}
+
+static int
+efrm_vi_rm_init_or_fini_nic(struct vi_resource *virs, int init,
+			    struct efhw_nic *nic)
+{
+	int rc;
+#ifndef NDEBUG
+	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+#endif
+
+	if (!init)
+		goto destroy;
+
+	rc = efrm_vi_rm_init_evq(virs, nic);
+	if (rc != 0)
+		goto fail_evq;
+
+	rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
+					  init, nic);
+	if (rc != 0)
+		goto fail_txq;
+
+	rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
+					  init, nic);
+	if (rc != 0)
+		goto fail_rxq;
+
+	/* 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;
+
+	return 0;
+
+destroy:
+	rc = 0;
+
+	efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
+				     false, nic);
+fail_rxq:
+
+	efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
+				     false, nic);
+fail_txq:
+
+	efrm_vi_rm_fini_evq(virs, nic);
+fail_evq:
+
+	EFRM_ASSERT(rc != 0 || !init);
+	return rc;
+}
+
+static int
+efrm_vi_resource_alloc_or_free(struct efrm_client *client,
+			       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 efhw_nic *nic = client->nic;
+	struct vi_resource *virs;
+	int rc;
+	int instance;
+
+	EFRM_ASSERT(virs_in_out);
+	EFRM_ASSERT(efrm_vi_manager);
+	EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
+
+	if (!alloc)
+		goto destroy;
+
+	rx_q_tag &= (1 << TX_DESCQ_LABEL_WIDTH) - 1;
+	tx_q_tag &= (1 << RX_DESCQ_LABEL_WIDTH) - 1;
+
+	virs = kmalloc(sizeof(*virs), GFP_KERNEL);
+	if (virs == NULL) {
+		EFRM_ERR("%s: Error allocating VI resource object",
+			 __func__);
+		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.", __func__);
+	}
+
+	if (instance < 0) {
+		/* Could flush resources and try again here. */
+		EFRM_ERR("%s: Out of appropriate VI resources", __func__);
+		rc = -EBUSY;
+		goto fail_alloc_id;
+	}
+
+	EFRM_TRACE("%s: new VI ID %d", __func__, 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);
+
+	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);
+	virs->tx_flushing = 0;
+	virs->rx_flushing = 0;
+
+	/* Adjust the queue sizes. */
+	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", __func__,
+			   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, __func__,
+				 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,
+			   __func__,
+			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
+			   EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
+	}
+	virs->evq_virs = evq_virs;
+
+	rc = efrm_vi_rm_alloc_or_free_buffer_table(virs, true);
+	if (rc != 0)
+		goto fail_buffer_table;
+
+	rc = efrm_vi_rm_init_or_fini_nic(virs, true, nic);
+	if (rc != 0)
+		goto fail_init_nic;
+
+	efrm_client_add_resource(client, &virs->rs);
+	*virs_in_out = virs;
+	EFRM_TRACE("%s: Allocated " EFRM_RESOURCE_FMT, __func__,
+		   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", __func__,
+		   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_vi_rm_init_or_fini_nic(virs, false, nic);
+
+	efrm_vi_rm_alloc_or_free_buffer_table(virs, false);
+fail_buffer_table:
+
+	efrm_vi_rm_detach_evq(virs);
+
+fail_adjust_request:
+
+	EFRM_ASSERT(virs->evq_callback_fn == NULL);
+	EFRM_TRACE("%s: delete VI ID %d", __func__, instance);
+	efrm_vi_rm_free_id(instance);
+fail_alloc_id:
+	if (!alloc)
+		efrm_client_put(virs->rs.rs_client);
+	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 efrm_client *client,
+		       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;
+	EFRM_ASSERT(client != NULL);
+	rc = efrm_vi_resource_alloc_or_free(client, 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(virs->rs.rs_ref_count == 0);
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
+		   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);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/falcon.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/falcon.c
@@ -0,0 +1,2525 @@
+/****************************************************************************
+ * 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
+ *
+ *---------------------------------------------------------------------------*/
+
+/* Keep a software copy of the filter table and check for duplicates. */
+#define FALCON_FULL_FILTER_CACHE 1
+
+/* Read filters back from the hardware to detect corruption. */
+#define FALCON_VERIFY_FILTERS    0
+
+/* 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 FALCON_MAC_SET_TYPE_BY_SPEED           0
+
+/* FIXME: We should detect mode at runtime. */
+#define FALCON_BUFFER_TABLE_FULL_MODE          1
+
+/* "Fudge factors" - difference between programmed value and actual depth */
+#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 TX_FILTER_CTL_SRCH_FUDGE_WILD 3	/* increase the search limit */
+#define TX_FILTER_CTL_SRCH_FUDGE_FULL 1	/* increase the search limit */
+
+/*----------------------------------------------------------------------------
+ *
+ * Debug Macros
+ *
+ *---------------------------------------------------------------------------*/
+
+#define _DEBUG_SYM_ static
+
+ /*----------------------------------------------------------------------------
+  *
+  * 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
+
+
+/*----------------------------------------------------------------------------
+ *
+ * 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
+
+*/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * 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 < nic->num_dmaqs);
+	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;
+	volatile char __iomem *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",
+				 __func__, 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,
+		   __func__,
+		   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 < nic->num_dmaqs);
+	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;
+	volatile char __iomem *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,
+		   __func__,
+		   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;
+	volatile char __iomem *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,
+		   __func__, 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;
+	volatile char __iomem *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;
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+	volatile char __iomem *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]: %lx:%x:%" PRIx64 "->%x = %"
+		   PRIx64, __func__, buffer_id, (unsigned long) 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", __func__);
+				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)
+{
+	volatile char __iomem *offset;
+	uint64_t entry;
+	volatile char __iomem *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]: %lx:bufsz=%x:region=%x:ownid=%x",
+		   __func__, buffer_id, (unsigned long) dma_addr, bufsz,
+		   region, own_id);
+
+	EFHW_TRACE("%s: BUF[%x]:NIC[%x]->%" PRIx64,
+		   __func__, 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")",
+					  __func__, 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 */
+	volatile char __iomem *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;
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+
+	volatile char __iomem *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;
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+
+	EFHW_BUILD_ASSERT(SRM_UPD_EVQ_REG_OFST == SRM_UPD_EVQ_REG_KER_OFST);
+
+	__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 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;
+	volatile char __iomem *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 < nic->num_evqs);
+
+	offset = EVQ_PTR_TBL_CHAR_OFST;
+	offset += evq * FALCON_REGISTER128;
+
+	EFHW_TRACE("%s: evq %u en=%x:buf=%x:size=%x->%x at %lx",
+		   __func__, 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;
+	volatile char __iomem *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 < nic->num_evqs);
+
+	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", __func__, evq, rptr, wakeup, val);
+
+	writel(val, efhw_kva + offset);
+	mmiowb();
+}
+
+/*---------------------------------------------------------------------------*/
+
+static inline void
+falcon_drv_ev(struct efhw_nic *nic, uint64_t data, uint qid)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *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_ab_timer_tbl_set(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;
+	volatile char __iomem *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 < nic->num_evqs);
+
+	EFHW_TRACE("%s: evq %u mode %x (%s) time %x -> %08x",
+		   __func__, 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;
+	volatile char __iomem *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",
+		   __func__, dmaq, offset, pace);
+}
+
+/*--------------------------------------------------------------------
+ *
+ * Interrupt - Low level interface
+ *
+ *--------------------------------------------------------------------*/
+
+static void falcon_nic_handle_fatal_int(struct efhw_nic *nic)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *offset;
+	volatile char __iomem *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;
+	volatile char __iomem *offset;
+	volatile char __iomem *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", __func__, (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;
+	volatile char __iomem *offset;
+	volatile char __iomem *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", __func__, (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);
+}
+
+static void falcon_nic_irq_addr_set(struct efhw_nic *nic, dma_addr_t dma_addr)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *offset;
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+
+	offset = (efhw_kva + INT_ADR_REG_CHAR_OFST);
+
+	EFHW_NOTICE("%s: %x -> " DMA_ADDR_T_FMT, __func__,
+		    (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);
+}
+
+
+/*--------------------------------------------------------------------
+ *
+ * RXDP - low level interface
+ *
+ *--------------------------------------------------------------------*/
+
+void
+falcon_nic_set_rx_usr_buf_size(struct efhw_nic *nic, int usr_buf_bytes)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *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);
+
+
+/*--------------------------------------------------------------------
+ *
+ * TXDP - low level interface
+ *
+ *--------------------------------------------------------------------*/
+
+_DEBUG_SYM_ void falcon_nic_tx_cfg(struct efhw_nic *nic, int unlocked)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *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)
+ *
+ *--------------------------------------------------------------------*/
+
+void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base, int bin_thresh)
+{
+	FALCON_LOCK_DECL;
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+	unsigned offset = 0;
+	uint64_t val;
+
+	__DWCHCK(TX_PACE_FB_BASE_LBN, TX_PACE_FB_BASE_WIDTH);
+	__DWCHCK(TX_PACE_BIN_TH_LBN, TX_PACE_BIN_TH_WIDTH);
+
+	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;
+	}
+
+	val = (0x15 << TX_PACE_SB_NOTAF_LBN);
+	val |= (0xb << TX_PACE_SB_AF_LBN);
+
+	val |= ((fb_base & __FALCON_MASK64(TX_PACE_FB_BASE_WIDTH)) <<
+		 TX_PACE_FB_BASE_LBN);
+	val |= ((bin_thresh & __FALCON_MASK64(TX_PACE_BIN_TH_WIDTH)) <<
+		 TX_PACE_BIN_TH_LBN);
+
+	/* Falcon requires 128 bit atomic access for this register */
+	FALCON_LOCK_LOCK(nic);
+	falcon_write_qq(efhw_kva + offset, val, 0);
+	mmiowb();
+	FALCON_LOCK_UNLOCK(nic);
+}
+
+
+/**********************************************************************
+ * Implementation of the HAL. ********************************************
+ **********************************************************************/
+
+/*----------------------------------------------------------------------------
+ *
+ * Initialisation and configuration discovery
+ *
+ *---------------------------------------------------------------------------*/
+
+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: %lx %sable", __func__,
+		   (unsigned long) efhw_iopage_dma_addr(&nic->irq_iobuff),
+		   enable ? "en" : "dis");
+
+	return 0;
+}
+
+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);
+	falcon_nic_filter_dtor(nic);
+
+	EFHW_NOTICE("%s:", __func__);
+}
+
+static int
+falcon_nic_init_hardware(struct efhw_nic *nic,
+			 struct efhw_ev_handler *ev_handlers,
+			 const uint8_t *mac_addr, int non_irq_evq)
+{
+	int rc;
+
+	/* header sanity checks */
+	FALCON_ASSERT_VALID();
+
+	/* Initialise supporting modules */
+	rc = falcon_nic_filter_ctor(nic);
+	if (rc < 0)
+		return rc;
+
+#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:", __func__);
+
+	/* 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 = 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, non_irq_evq);
+
+	/* 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, 4, 2);
+
+	/* ?? 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->interrupting_evq, ev_handlers);
+		if (rc < 0) {
+			EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
+				 __func__, rc, FALCON_EVQ_CHAR);
+			return rc;
+		}
+	}
+	rc = efhw_keventq_ctor(nic, non_irq_evq,
+			       &nic->non_interrupting_evq, NULL);
+	if (rc < 0) {
+		EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
+			 __func__, rc, non_irq_evq);
+		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)
+{
+	struct efhw_keventq *q;
+	unsigned rdptr;
+
+	if (nic->flags & NIC_FLAG_NO_INTERRUPT)
+		return;
+
+	/* Enable driver interrupts */
+	EFHW_NOTICE("%s: enable master interrupt", __func__);
+	falcon_nic_interrupt_hw_enable(nic);
+
+	/* An interrupting eventq must start of day ack its read pointer */
+	q = &nic->interrupting_evq;
+	rdptr = EFHW_EVENT_OFFSET(q, q, 1) / sizeof(efhw_event_t);
+	falcon_nic_evq_ack(nic, FALCON_EVQ_CHAR, rdptr, false);
+	EFHW_NOTICE("%s: ACK evq[%d]:%x", __func__,
+		    FALCON_EVQ_CHAR, rdptr);
+}
+
+static void falcon_nic_interrupt_disable(struct efhw_nic *nic)
+{
+	/* NB. No need to check for NIC_FLAG_NO_INTERRUPT, as
+	 ** falcon_nic_interrupt_hw_disable() will do it. */
+	falcon_nic_interrupt_hw_disable(nic);
+}
+
+static void
+falcon_nic_set_interrupt_moderation(struct efhw_nic *nic, int evq,
+				    uint32_t val)
+{
+	if (evq < 0)
+		evq = FALCON_EVQ_CHAR;
+
+	falcon_ab_timer_tbl_set(nic, evq, 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)
+{
+	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", __func__,
+			  *(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", __func__, 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, int interrupting)
+{
+	EFHW_ASSERT(nic);
+
+	/* Whether or not queue has an interrupt depends on
+	 * instance number and h/w variant, so [interrupting] is
+	 * ignored.
+	 */
+	falcon_ab_timer_tbl_set(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", __func__, evq, evq_size);
+}
+
+static void
+falcon_nic_event_queue_disable(struct efhw_nic *nic, uint evq, int timer_only)
+{
+	EFHW_ASSERT(nic);
+
+	falcon_ab_timer_tbl_set(nic, evq, 0 /* disable */ , 0);
+
+	if (!timer_only)
+		falcon_nic_evq_ptr_tbl(nic, evq, 0, 0, 0);
+	EFHW_TRACE("%s: disenable evq %u", __func__, 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", __func__, 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", __func__, evq, data);
+}
+
+
+/*--------------------------------------------------------------------
+ *
+ * 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)
+{
+	/* 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;
+
+	/* 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", __func__, 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->non_interrupting_evq.ev_handlers = &handler;
+		rc = efhw_keventq_poll(nic, &nic->non_interrupting_evq);
+		nic->non_interrupting_evq.ev_handlers = NULL;
+
+		if (rc < 0) {
+			EFHW_ERR("%s: poll ERROR (%d:%d) ***** ",
+				 __func__, rc,
+				 nic->buf_commit_outstanding);
+			goto out;
+		}
+
+		FALCON_LOCK_UNLOCK(nic);
+
+		if (count++)
+			udelay(1);
+
+		if (count > 1000) {
+			EFHW_WARN("%s: poll Timeout ***** (%d)", __func__,
+				  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;
+
+	/* 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;
+	volatile char __iomem *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;
+	volatile char __iomem *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;
+	volatile char __iomem *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;
+	volatile char __iomem *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, __func__,
+		   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", __func__, 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;
+	volatile char __iomem *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;
+	volatile char __iomem *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", __func__, 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));
+		efhw_handle_txdmaq_flushed(nic, h, ev);
+		break;
+
+	case RX_DESCQ_FLS_DONE_EV_DECODE:
+		EFHW_TRACE("RX[%d] flushed",
+			   (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
+		efhw_handle_rxdmaq_flushed(nic, h, ev);
+		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("%sEVQ INIT", "");
+		break;
+
+	case WAKE_UP_EV_DECODE:
+		EFHW_TRACE("%sWAKE UP", "");
+		efhw_handle_wakeup_event(nic, h, ev);
+		break;
+
+	case TIMER_EV_DECODE:
+		EFHW_TRACE("%sTIMER", "");
+		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", __func__);
+		return -EINVAL;
+
+	default:
+		EFHW_TRACE("UNKOWN DRIVER EVENT: " FALCON_EVENT_FMT,
+			   FALCON_EVENT_PRI_ARG(*ev));
+		break;
+	}
+	return 0;
+}
+
+
+/*--------------------------------------------------------------------
+ *
+ * Filter search depth control
+ *
+ *--------------------------------------------------------------------*/
+
+
+#define Q0_READ(q0, name) \
+	((unsigned)(((q0) >> name##_LBN) & (__FALCON_MASK64(name##_WIDTH))))
+#define Q0_MASK(name) \
+	((__FALCON_MASK64(name##_WIDTH)) << name##_LBN)
+#define Q0_VALUE(name, value) \
+	(((uint64_t)(value)) << name##_LBN)
+
+#define Q1_READ(q1, name) \
+	((unsigned)(((q1) >> (name##_LBN - 64)) & \
+		    (__FALCON_MASK64(name##_WIDTH))))
+#define Q1_MASK(name) \
+	((__FALCON_MASK64(name##_WIDTH)) << (name##_LBN - 64))
+#define Q1_VALUE(name, value) \
+	(((uint64_t)(value)) << (name##_LBN - 64))
+
+
+void
+falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values)
+{
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+	FALCON_LOCK_DECL;
+	uint64_t q0, q1;
+	unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
+	unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
+
+	FALCON_LOCK_LOCK(nic);
+	falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
+	FALCON_LOCK_UNLOCK(nic);
+
+	lim->tcp_full = Q0_READ(q0, TCP_FULL_SRCH_LIMIT) - ff;
+	lim->tcp_wild = Q0_READ(q0, TCP_WILD_SRCH_LIMIT) - wf;
+	lim->udp_full = Q0_READ(q0, UDP_FULL_SRCH_LIMIT) - ff;
+	lim->udp_wild = Q0_READ(q0, UDP_WILD_SRCH_LIMIT) - wf;
+}
+EXPORT_SYMBOL(falcon_nic_get_rx_filter_search_limits);
+
+
+void
+falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values)
+{
+	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
+	FALCON_LOCK_DECL;
+	uint64_t q0, q1;
+	unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
+	unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
+
+	FALCON_LOCK_LOCK(nic);
+	falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
+
+	q0 &= ~Q0_MASK(TCP_FULL_SRCH_LIMIT);
+	q0 &= ~Q0_MASK(TCP_WILD_SRCH_LIMIT);
+	q0 &= ~Q0_MASK(UDP_FULL_SRCH_LIMIT);
+	q0 &= ~Q0_MASK(UDP_WILD_SRCH_LIMIT);
+	q0 |= Q0_VALUE(TCP_FULL_SRCH_LIMIT, lim->tcp_full + ff);
+	q0 |= Q0_VALUE(TCP_WILD_SRCH_LIMIT, lim->tcp_wild + wf);
+	q0 |= Q0_VALUE(UDP_FULL_SRCH_LIMIT, lim->udp_full + ff);
+	q0 |= Q0_VALUE(UDP_WILD_SRCH_LIMIT, lim->udp_wild + wf);
+	nic->tcp_full_srch.max = lim->tcp_full + ff
+					- RX_FILTER_CTL_SRCH_FUDGE_FULL;
+	nic->tcp_wild_srch.max = lim->tcp_wild + wf
+					- RX_FILTER_CTL_SRCH_FUDGE_WILD;
+	nic->udp_full_srch.max = lim->udp_full + ff
+					- RX_FILTER_CTL_SRCH_FUDGE_FULL;
+	nic->udp_wild_srch.max = lim->udp_wild + wf
+					- RX_FILTER_CTL_SRCH_FUDGE_WILD;
+
+	falcon_write_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, q0, q1);
+	mmiowb();
+	FALCON_LOCK_UNLOCK(nic);
+}
+EXPORT_SYMBOL(falcon_nic_set_rx_filter_search_limits);
+
+
+#undef READ_Q0
+#undef Q0_MASK
+#undef Q0_VALUE
+#undef READ_Q1
+#undef Q1_MASK
+#undef Q1_VALUE
+
+
+/*--------------------------------------------------------------------
+ *
+ * New unified filter API
+ *
+ *--------------------------------------------------------------------*/
+
+
+#if FALCON_FULL_FILTER_CACHE
+static inline struct efhw_filter_spec *
+filter_spec_cache_entry(struct efhw_nic *nic, int filter_idx)
+{
+	EFHW_ASSERT(nic->filter_spec_cache);
+	return &nic->filter_spec_cache[filter_idx];
+}
+#endif
+
+
+static int filter_is_active(struct efhw_nic *nic, int filter_idx)
+{
+	return nic->filter_in_use[filter_idx];
+}
+
+
+static void set_filter_cache_entry(struct efhw_nic *nic,
+				   struct efhw_filter_spec *spec,
+				   int filter_idx)
+{
+	nic->filter_in_use[filter_idx] = 1;
+#if FALCON_FULL_FILTER_CACHE
+	memcpy(filter_spec_cache_entry(nic, filter_idx), spec,
+	       sizeof(struct efhw_filter_spec));
+#endif
+}
+
+
+static void clear_filter_cache_entry(struct efhw_nic *nic,
+				     int filter_idx)
+{
+	nic->filter_in_use[filter_idx] = 0;
+#if FALCON_FULL_FILTER_CACHE
+	memset(filter_spec_cache_entry(nic, filter_idx), 0,
+	       sizeof(struct efhw_filter_spec));
+#endif
+}
+
+
+#if FALCON_FULL_FILTER_CACHE
+static int filter_is_duplicate(struct efhw_nic *nic,
+			       struct efhw_filter_spec *spec, int filter_idx)
+{
+	struct efhw_filter_spec *cmp;
+
+	cmp = filter_spec_cache_entry(nic, filter_idx);
+
+	EFHW_ASSERT(filter_is_active(nic, filter_idx));
+
+	return (spec->saddr_le32 == cmp->saddr_le32) &&
+	       (spec->daddr_le32 == cmp->daddr_le32) &&
+	       (spec->sport_le16 == cmp->sport_le16) &&
+	       (spec->dport_le16 == cmp->dport_le16) &&
+	       (spec->tcp == cmp->tcp) &&
+	       (spec->full == cmp->full);
+}
+#endif
+
+
+static void common_build_ip_filter(struct efhw_nic *nic, int tcp, int full,
+				   int rss, int scatter, 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;
+	unsigned tmp_port_le16;
+
+	if (!full) {
+		saddr_le32 = 0;
+		sport_le16 = 0;
+		if (!tcp) {
+			tmp_port_le16 = sport_le16;
+			sport_le16 = dport_le16;
+			dport_le16 = tmp_port_le16;
+		}
+	}
+
+	v4 = (((!tcp) << __DW4(TCP_UDP_0_LBN)) |
+	      (dmaq_id << __DW4(RXQ_ID_0_LBN)));
+
+	switch (nic->devtype.variant) {
+	case 'A':
+		EFHW_ASSERT(!rss);
+		break;
+	case 'B':
+		v4 |= scatter << __DW4(SCATTER_EN_0_B0_LBN);
+		v4 |= rss << __DW4(RSS_EN_0_B0_LBN);
+		break;
+	default:
+		EFHW_ASSERT(0);
+		break;
+	}
+
+	v3 = daddr_le32;
+	v2 = ((dport_le16 << __DW2(DEST_PORT_TCP_0_LBN)) |
+	      (__HIGH(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)));
+	v1 = ((__LOW(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)) |
+	      (sport_le16 << SRC_TCP_DEST_UDP_0_LBN));
+
+	*q0 = (v2 << 32) | v1;
+	*q1 = (v4 << 32) | v3;
+}
+
+
+static void build_filter(struct efhw_nic *nic, struct efhw_filter_spec *spec,
+			 unsigned *key, unsigned *tbl_size,
+			 struct efhw_filter_depth **depth,
+			 uint64_t *q0, uint64_t *q1)
+{
+	*key = falcon_hash_get_ip_key(spec->saddr_le32,
+				      spec->sport_le16,
+				      spec->daddr_le32,
+				      spec->dport_le16,
+				      spec->tcp,
+				      spec->full);
+	*tbl_size = nic->ip_filter_tbl_size;
+	if (spec->tcp && spec->full)
+		*depth = &nic->tcp_full_srch;
+	else if (spec->tcp && !spec->full)
+		*depth = &nic->tcp_wild_srch;
+	else if (!spec->tcp && spec->full)
+		*depth = &nic->udp_full_srch;
+	else
+		*depth = &nic->udp_wild_srch;
+	common_build_ip_filter(nic, spec->tcp, spec->full,
+			       spec->rss, spec->scatter,
+			       spec->dmaq_id,
+			       spec->saddr_le32,
+			       spec->sport_le16,
+			       spec->daddr_le32,
+			       spec->dport_le16,
+			       q0, q1);
+}
+
+
+#if FALCON_VERIFY_FILTERS
+static void verify_filters(struct efhw_nic *nic)
+{
+	unsigned table_offset, table_stride;
+	unsigned i, dummy_key, dummy_tbl_size;
+	struct efhw_filter_depth *dummy_depth;
+	unsigned filter_tbl_size;
+	struct efhw_filter_spec *spec;
+	uint64_t q0_expect, q1_expect, q0_got, q1_got;
+
+	filter_tbl_size = nic->ip_filter_tbl_size;
+	table_offset = RX_FILTER_TBL0_OFST;
+	table_stride = 2 * FALCON_REGISTER128;
+
+	for (i = 0; i < filter_tbl_size; i++) {
+		if (!filter_is_active(nic, type, i))
+			continue;
+
+		spec = filter_spec_cache_entry(nic, type, i);
+
+		build_filter(nic, spec, &dummy_key, &dummy_tbl_size,
+			     &dummy_depth, &q0_expect, &q1_expect);
+
+		falcon_read_qq(EFHW_KVA(nic) + table_offset + i * table_stride,
+			       &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
+
+
+static void write_filter_table_entry(struct efhw_nic *nic,
+				     unsigned filter_idx,
+				     uint64_t q0, uint64_t q1)
+{
+	unsigned table_offset, table_stride, offset;
+
+	EFHW_ASSERT(filter_idx < nic->ip_filter_tbl_size);
+	table_offset = RX_FILTER_TBL0_OFST;
+	table_stride = 2 * FALCON_REGISTER128;
+
+	offset = table_offset + filter_idx * table_stride;
+	falcon_write_qq(EFHW_KVA(nic) + offset, q0, q1);
+	mmiowb();
+
+#if FALCON_VERIFY_FILTERS
+	{
+		uint64_t q0read, q1read;
+
+		/* Read a different entry first - ensure 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);
+
+		verify_filters(nic, type);
+	}
+#endif
+}
+
+
+static int falcon_nic_filter_set(struct efhw_nic *nic,
+				 struct efhw_filter_spec *spec,
+				 int *filter_idx_out)
+{
+	FALCON_LOCK_DECL;
+	unsigned key = 0, tbl_size = 0, hash1, hash2, k;
+	struct efhw_filter_depth *depth = NULL;
+	int filter_idx = -1;
+	int rc = 0;
+	uint64_t q0, q1;
+
+	build_filter(nic, spec, &key, &tbl_size, &depth, &q0, &q1);
+
+	if (tbl_size == 0)
+		return -EINVAL;
+
+	EFHW_TRACE("%s: depth->max=%d", __func__, depth->max);
+
+	hash1 = falcon_hash_function1(key, tbl_size);
+	hash2 = falcon_hash_function2(key, tbl_size);
+
+	FALCON_LOCK_LOCK(nic);
+
+	for (k = 0; k < depth->max; k++) {
+		filter_idx = falcon_hash_iterator(hash1, hash2, k, tbl_size);
+		if (!filter_is_active(nic, filter_idx))
+			break;
+#if FALCON_FULL_FILTER_CACHE
+		if (filter_is_duplicate(nic, spec, filter_idx)) {
+			EFHW_WARN("%s: ERROR: duplicate filter (disabling "
+				  "interrupts)", __func__);
+			falcon_nic_interrupt_hw_disable(nic);
+			rc = -EINVAL;
+			goto fail1;
+		}
+#endif
+	}
+	if (k == depth->max) {
+		rc = -EADDRINUSE;
+		filter_idx = -1;
+		goto fail1;
+	} else if (depth->needed < (k + 1)) {
+		depth->needed = k + 1;
+	}
+
+	EFHW_ASSERT(filter_idx < (int)tbl_size);
+
+	set_filter_cache_entry(nic, spec, filter_idx);
+	write_filter_table_entry(nic, filter_idx, q0, q1);
+
+	++nic->ip_filter_tbl_used;
+
+	*filter_idx_out = filter_idx;
+
+	EFHW_TRACE("%s: filter index %d rxq %u set in %u",
+		   __func__, filter_idx, spec->dmaq_id, k);
+
+fail1:
+	FALCON_LOCK_UNLOCK(nic);
+	return rc;
+}
+
+
+static void falcon_nic_filter_clear(struct efhw_nic *nic,
+				    int filter_idx)
+{
+	FALCON_LOCK_DECL;
+
+	if (filter_idx < 0)
+		return;
+
+	FALCON_LOCK_LOCK(nic);
+	if (filter_is_active(nic, filter_idx)) {
+		if (--nic->ip_filter_tbl_used == 0) {
+			nic->tcp_full_srch.needed = 0;
+			nic->tcp_wild_srch.needed = 0;
+			nic->udp_full_srch.needed = 0;
+			nic->udp_wild_srch.needed = 0;
+		}
+	}
+	clear_filter_cache_entry(nic, filter_idx);
+	write_filter_table_entry(nic, filter_idx, 0, 0);
+	FALCON_LOCK_UNLOCK(nic);
+}
+
+
+int
+falcon_nic_filter_ctor(struct efhw_nic *nic)
+{
+	nic->ip_filter_tbl_size = 8 * 1024;
+	nic->ip_filter_tbl_used = 0;
+
+	nic->tcp_full_srch.needed = 0;
+	nic->tcp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL
+				   - RX_FILTER_CTL_SRCH_FUDGE_FULL;
+	nic->tcp_wild_srch.needed = 0;
+	nic->tcp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD
+				   - RX_FILTER_CTL_SRCH_FUDGE_WILD;
+	nic->udp_full_srch.needed = 0;
+	nic->udp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL
+				   - RX_FILTER_CTL_SRCH_FUDGE_FULL;
+	nic->udp_wild_srch.needed = 0;
+	nic->udp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD
+				   - RX_FILTER_CTL_SRCH_FUDGE_WILD;
+
+	nic->filter_in_use = vmalloc(FALCON_FILTER_TBL_NUM);
+	if (nic->filter_in_use == NULL)
+		return -ENOMEM;
+	memset(nic->filter_in_use, 0, FALCON_FILTER_TBL_NUM);
+#if FALCON_FULL_FILTER_CACHE
+	nic->filter_spec_cache = vmalloc(FALCON_FILTER_TBL_NUM
+					 * sizeof(struct efhw_filter_spec));
+	if (nic->filter_spec_cache == NULL)
+		return -ENOMEM;
+	memset(nic->filter_spec_cache, 0, FALCON_FILTER_TBL_NUM
+					  * sizeof(struct efhw_filter_spec));
+#endif
+
+	return 0;
+}
+
+
+void
+falcon_nic_filter_dtor(struct efhw_nic *nic)
+{
+#if FALCON_FULL_FILTER_CACHE
+	if (nic->filter_spec_cache)
+		vfree(nic->filter_spec_cache);
+#endif
+	if (nic->filter_in_use)
+		vfree(nic->filter_in_use);
+}
+
+
+/*--------------------------------------------------------------------
+ *
+ * Compatibility with old filter API
+ *
+ *--------------------------------------------------------------------*/
+
+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)
+{
+	struct efhw_filter_search_limits lim;
+
+	falcon_nic_get_rx_filter_search_limits(nic, &lim, 0);
+	*tcp_full = (uint32_t)lim.tcp_full;
+	*tcp_wild = (uint32_t)lim.tcp_wild;
+	*udp_full = (uint32_t)lim.udp_full;
+	*udp_wild = (uint32_t)lim.udp_wild;
+}
+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)
+{
+	struct efhw_filter_search_limits lim;
+
+	lim.tcp_full = (unsigned)tcp_full;
+	lim.tcp_wild = (unsigned)tcp_wild;
+	lim.udp_full = (unsigned)udp_full;
+	lim.udp_wild = (unsigned)udp_wild;
+	falcon_nic_set_rx_filter_search_limits(nic, &lim, 0);
+}
+EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_set);
+
+
+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)
+{
+	struct efhw_filter_spec spec;
+
+	spec.dmaq_id = dmaq;
+	spec.saddr_le32 = ntohl(saddr_be32);
+	spec.daddr_le32 = ntohl(daddr_be32);
+	spec.sport_le16 = ntohs((unsigned short) sport_be16);
+	spec.dport_le16 = ntohs((unsigned short) dport_be16);
+	spec.tcp = ((type & EFHW_IP_FILTER_TYPE_TCP_MASK) != 0);
+	spec.full = ((type & EFHW_IP_FILTER_TYPE_FULL_MASK) != 0);
+	spec.rss = ((type & EFHW_IP_FILTER_TYPE_RSS_B0_MASK) != 0);
+	spec.scatter = ((type & EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK) == 0);
+	return falcon_nic_filter_set(nic, &spec, _filter_idx);
+}
+
+static void falcon_nic_ipfilter_clear(struct efhw_nic *nic, int filter_idx)
+{
+	falcon_nic_filter_clear(nic, filter_idx);
+}
+
+
+/*--------------------------------------------------------------------
+ *
+ * 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_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,
+	falcon_nic_filter_set,
+	falcon_nic_filter_clear,
+};
+
+
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/iopage.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/iopage.c
@@ -0,0 +1,103 @@
+/****************************************************************************
+ * 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, struct efhw_iopage *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, struct efhw_iopage *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, struct efhw_iopages *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, struct efhw_iopages *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);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/resources.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/resources.c
@@ -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_lim)
+{
+	int i, rc;
+
+	rc = efrm_buffer_table_ctor(buffer_table_min, buffer_table_lim);
+	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)",
+				 __func__, 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();
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/falcon_hash.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/falcon_hash.c
@@ -0,0 +1,159 @@
+/****************************************************************************
+ * 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>
+
+
+static unsigned int
+common_get_ip_key(unsigned int src_ip, unsigned int src_port,
+		  unsigned int dest_ip, unsigned int dest_port,
+		  int tcp, int full, int tx, unsigned int masked_q_id)
+{
+
+	unsigned int tmp_port, result;
+
+	EFHW_ASSERT(tcp == 0 || tcp == 1);
+	EFHW_ASSERT(full == 0 || full == 1);
+	EFHW_ASSERT(masked_q_id < (1 << 10));
+
+	/* m=masked_q_id(TX)/0(RX)  u=UDP  S,D=src/dest addr  s,d=src/dest port
+	 *
+	 * Wildcard filters have src(TX)/dest(RX) addr and port = 0;
+	 * and UDP wildcard filters have the src and dest port fields swapped.
+	 *
+	 * Addr/port fields are little-endian.
+	 *
+	 * 3322222222221111111111
+	 * 10987654321098765432109876543210
+	 *
+	 * 000000000000000000000mmmmmmmmmmu ^
+	 * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ^
+	 * ddddddddddddddddSSSSSSSSSSSSSSSS ^
+	 * SSSSSSSSSSSSSSSSssssssssssssssss
+	 */
+
+	if (!tx)
+		masked_q_id = 0;
+
+	if (!full) {
+		if (tx) {
+			dest_ip = 0;
+			dest_port = 0;
+		} else {
+			src_ip = 0;
+			src_port = 0;
+		}
+		if (!tcp) {
+			tmp_port = src_port;
+			src_port = dest_port;
+			dest_port = tmp_port;
+		}
+	}
+
+	result = ((masked_q_id << 1) | (!tcp))                              ^
+		 (dest_ip)                                                  ^
+		 (((dest_port & 0xffff) << 16) | ((src_ip >> 16) & 0xffff)) ^
+		 (((src_ip & 0xffff) << 16) | (src_port & 0xffff));
+
+	EFHW_TRACE("%s: IP %s %s %x", __func__, tcp ? "TCP" : "UDP",
+		   full ? "Full" : "Wildcard", result);
+
+	return result;
+}
+
+
+unsigned int
+falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
+		       unsigned int dest_ip, unsigned int dest_port,
+		       int tcp, int full)
+{
+	return common_get_ip_key(src_ip, src_port, dest_ip, dest_port, tcp,
+				 full, 0, 0);
+}
+
+
+/* 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 & (nfilters - 1);
+
+	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) &
+			      (nfilters - 1));
+}
+
+/* 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)) & (nfilters - 1);
+}
+
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/Makefile
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/Makefile
@@ -0,0 +1,14 @@
+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_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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/vi_resource_flush.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/vi_resource_flush.c
@@ -0,0 +1,483 @@
+/****************************************************************************
+ * 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>
+#include "efrm_internal.h"
+
+
+/* can fail as workitem can already be scheuled -- ignore failure */
+#define EFRM_VI_RM_DELAYED_FREE(manager) \
+	queue_work(manager->workqueue, &manager->work_item)
+
+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, bool *completed)
+{
+	/* We should only get a flush event if there is a flush
+	 * outstanding. */
+	EFRM_ASSERT(virs->rx_flush_outstanding);
+
+	virs->rx_flush_outstanding = 0;
+	virs->rx_flushing = 0;
+
+	list_del(&virs->rx_flush_link);
+	efrm_vi_manager->rx_flush_outstanding_count--;
+
+	if (virs->tx_flushing == 0) {
+		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, bool *completed)
+{
+	/* We should only get a flush event if there is a flush
+	 * outstanding. */
+	EFRM_ASSERT(virs->tx_flushing);
+
+	virs->tx_flushing = 0;
+
+	list_del(&virs->tx_flush_link);
+
+	if (virs->rx_flushing == 0) {
+		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 = virs->rs.rs_client->nic;
+	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 = virs->rx_flushing;
+	efrm_vi_manager->rx_flush_outstanding_count++;
+
+	EFRM_TRACE("%s: rx queue %d flush requested for nic %d",
+		   __func__, instance, nic->index);
+	rc = efhw_nic_flush_rx_dma_channel(nic, instance);
+	if (rc == -EAGAIN)
+		efrm_vi_resource_rx_flush_done(virs, completed);
+}
+
+static void
+efrm_vi_resource_issue_tx_flush(struct vi_resource *virs, bool *completed)
+{
+	struct efhw_nic *nic = virs->rs.rs_client->nic;
+	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_TRACE("%s: tx queue %d flush requested for nic %d",
+		   __func__, instance, nic->index);
+	rc = efhw_nic_flush_tx_dma_channel(nic, instance);
+	if (rc == -EAGAIN)
+		efrm_vi_resource_tx_flush_done(virs, 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 instance;
+
+	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+
+	virs->flush_count++;
+	virs->flush_time = time_now;
+	nic = virs->rs.rs_client->nic;
+
+#if BUG7916_WORKAROUND
+	if (virs->rx_flush_outstanding) {
+		EFRM_TRACE("%s: Retrying RX flush on instance %d",
+			   __func__, 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 (virs->tx_flushing) {
+		if (virs->flush_count > 5) {
+			EFRM_TRACE("%s: VI resource stuck flush pending "
+				   "(instance=%d, count=%d)",
+				   __func__, instance, virs->flush_count);
+			falcon_clobber_tx_dma_ptrs(nic, instance);
+		} else {
+			EFRM_TRACE("%s: Retrying TX flush on instance %d",
+				   __func__, 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 (virs->rx_flushing == 0 && virs->tx_flushing == 0)
+		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(virs->rx_flushing == 0);
+	EFRM_ASSERT(virs->rx_flush_outstanding == 0);
+	EFRM_ASSERT(virs->tx_flushing == 0);
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " EVQ=%d TXQ=%d RXQ=%d",
+		   __func__, 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_flushing = 1;
+
+	if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
+		virs->tx_flushing = 1;
+
+	/* Clean up immediately if there are no flushes. */
+	if (virs->rx_flushing == 0 && virs->tx_flushing == 0) {
+		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 (virs->rx_flushing) {
+#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 (virs->tx_flushing)
+		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, completed);
+			efrm_vi_resource_process_waiting_flushes(completed);
+			return;
+		}
+	}
+	EFRM_TRACE("%s: Unhandled rx flush event, nic %d, instance %d",
+		   __func__, 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, completed);
+			return;
+		}
+	}
+	EFRM_TRACE("%s: Unhandled tx flush event, nic %d, instance %d",
+		   __func__, flush_nic->index, instance);
+}
+
+void
+efrm_handle_dmaq_flushed(struct efhw_nic *flush_nic, unsigned instance,
+			 int rx_flush)
+{
+	irq_flags_t lock_flags;
+	bool completed = false;
+
+	EFRM_TRACE("%s: nic_i=%d  instance=%d  rx_flush=%d", __func__,
+		   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 = virs->rs.rs_client->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", __func__, 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", __func__,
+			   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);
+
+
+void efrm_vi_resource_release(struct vi_resource *virs)
+{
+	if (__efrm_resource_release(&virs->rs))
+		efrm_vi_resource_free(virs);
+}
+EXPORT_SYMBOL(efrm_vi_resource_release);
+
+/*
+ * vi: sw=8:ai:aw
+ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/vi_resource_manager.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/vi_resource_manager.c
@@ -0,0 +1,231 @@
+/****************************************************************************
+ * 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>
+#include "efrm_internal.h"
+
+
+int efrm_pt_pace(struct vi_resource *virs, unsigned int val)
+{
+	struct efhw_nic *nic = virs->rs.rs_client->nic;
+	int instance;
+
+	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
+	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	falcon_nic_pace(nic, instance, val);
+	EFRM_TRACE("%s[%d]=%d DONE", __func__, instance, val);
+	return 0;
+}
+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;
+	unsigned dmaq_min, dmaq_lim;
+
+	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_lim,
+		    dims->evq_timer_min, dims->evq_timer_lim);
+	EFRM_NOTICE("vi_resource_manager: rxq=%u-%u txq=%u-%u",
+		    dims->rxq_min, dims->rxq_lim,
+		    dims->txq_min, dims->txq_lim);
+
+	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_lim = min(dims->rxq_lim, dims->txq_lim);
+
+	efrm_vi_manager->with_timer_base =
+	    max(dmaq_min, dims->evq_timer_min);
+	efrm_vi_manager->with_timer_limit =
+	    min(dmaq_lim, dims->evq_timer_lim);
+	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_lim, dims->evq_int_lim);
+	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;
+
+	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);
+	efrm_vi_manager->workqueue = create_workqueue("sfc_vi");
+	if (efrm_vi_manager->workqueue == NULL)
+		goto fail_create_workqueue;
+	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);
+	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_flushing
+	 * 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 (virs->tx_flushing == 0)
+			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 (virs->tx_flushing == 0)
+			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]",
+			   __func__,
+			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
+			   virs->tx_flushing,
+			   virs->rx_flushing,
+			   virs->rx_flush_outstanding);
+		efrm_vi_rm_free_flushed_resource(virs);
+	}
+
+fail_rm_ctor:
+
+	/* Complete outstanding closes. */
+	destroy_workqueue(efrm_vi_manager->workqueue);
+fail_create_workqueue:
+	EFRM_ASSERT(list_empty(&efrm_vi_manager->close_pending));
+	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", __func__, 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);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/iobufset_resource.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/iobufset_resource.c
@@ -0,0 +1,404 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/efrm_client.h>
+#include "efrm_internal.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 n_pages)
+{
+	return offsetof(struct iobufset_resource, bufs) +
+	    n_pages * sizeof(struct efhw_iopage);
+}
+
+void efrm_iobufset_resource_free(struct iobufset_resource *rs)
+{
+	unsigned int i;
+	int id;
+
+	EFRM_RESOURCE_ASSERT_VALID(&rs->rs, 1);
+
+	if (!rs->linked && 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_tablep->a_nic here */
+	EFRM_ASSERT(efrm_nic_tablep->a_nic);
+	if (rs->linked) {
+		/* Nothing to do. */
+	} else if (rs->chunk_order == 0) {
+		for (i = 0; i < rs->n_bufs; ++i)
+			efhw_iopage_free(efrm_nic_tablep->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) {
+			struct efhw_iopages iopages;
+			efhw_iopages_init_from_iopage(&iopages, &rs->bufs[i],
+						    rs->chunk_order);
+			efhw_iopages_free(efrm_nic_tablep->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);
+	if (rs->linked)
+		efrm_iobufset_resource_release(rs->linked);
+
+	efrm_client_put(rs->rs.rs_client);
+	if (iobsrs_size(rs->n_bufs) < PAGE_SIZE) {
+		EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
+		kfree(rs);
+	} else {
+		EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
+		vfree(rs);
+	}
+}
+EXPORT_SYMBOL(efrm_iobufset_resource_free);
+
+
+void efrm_iobufset_resource_release(struct iobufset_resource *iobrs)
+{
+	if (__efrm_resource_release(&iobrs->rs))
+		efrm_iobufset_resource_free(iobrs);
+}
+EXPORT_SYMBOL(efrm_iobufset_resource_release);
+
+
+
+int
+efrm_iobufset_resource_alloc(int32_t n_pages,
+			     int32_t pages_per_contiguous_chunk,
+			     struct vi_resource *vi_evq,
+			     struct iobufset_resource *linked,
+			     bool phys_addr_mode,
+			     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_tablep->a_nic);
+
+	if (linked) {
+		/* This resource will share properties and memory with
+		 * another.  Only difference is that we'll program it into
+		 * the buffer table of another nic.
+		 */
+		n_pages = linked->n_bufs;
+		pages_per_contiguous_chunk = linked->pages_per_contiguous_chunk;
+		phys_addr_mode = linked->buf_tbl_alloc.base == (unsigned) -1;
+	}
+
+	/* 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",
+				 __func__, n_pages);
+			EFRM_ASSERT(!in_interrupt());
+			EFRM_ASSERT(!in_atomic());
+		}
+#endif
+		iobrs = (struct iobufset_resource *) vmalloc(object_size);
+	}
+	if (iobrs == NULL) {
+		EFRM_WARN("%s: failed to allocate container", __func__);
+		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_WARN("%s: out of instances", __func__);
+		EFRM_ASSERT(rc == 0);
+		rc = -EBUSY;
+		goto fail3;
+	}
+
+	efrm_resource_init(&iobrs->rs, EFRM_RESOURCE_IOBUFSET, instance);
+
+	iobrs->evq = vi_evq;
+	iobrs->linked = linked;
+	iobrs->n_bufs = n_pages;
+	iobrs->pages_per_contiguous_chunk = pages_per_contiguous_chunk;
+	iobrs->chunk_order = fls(iobrs->pages_per_contiguous_chunk - 1);
+	iobrs->buf_tbl_alloc.base = (unsigned) -1;
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %u pages", __func__,
+		   EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), iobrs->n_bufs);
+
+	/* Allocate the iobuffers. */
+	if (linked) {
+		memcpy(iobrs->bufs, linked->bufs,
+		       iobrs->n_bufs * sizeof(iobrs->bufs[0]));
+	} else if (iobrs->chunk_order == 0) {
+		memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
+		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_tablep->a_nic),
+			 * it is suitable for all NICs.
+			 * XXX I bet that breaks in Solaris.
+			 */
+			rc = efhw_iopage_alloc(efrm_nic_tablep->a_nic,
+					     &iobrs->bufs[i]);
+			if (rc < 0) {
+				EFRM_WARN("%s: failed (rc %d) to allocate "
+					  "page (i=%u)", __func__, rc, i);
+				goto fail4;
+			}
+		}
+	} else {
+		struct efhw_iopages iopages;
+		unsigned j;
+
+		memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
+		for (i = 0; i < iobrs->n_bufs;
+		     i += iobrs->pages_per_contiguous_chunk) {
+			rc = efhw_iopages_alloc(efrm_nic_tablep->a_nic,
+						&iopages, iobrs->chunk_order);
+			if (rc < 0) {
+				EFRM_WARN("%s: failed (rc %d) to allocate "
+					  "pages (i=%u order %d)",
+					  __func__, rc, i,
+					  iobrs->chunk_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);
+			}
+		}
+	}
+
+	if (!phys_addr_mode) {
+		unsigned owner_id = EFAB_VI_RESOURCE_INSTANCE(iobrs->evq);
+
+		if (!linked) {
+			/* 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_WARN("%s: failed (%d) to alloc %d buffer "
+					  "table entries", __func__, rc,
+					  iobrs->n_bufs);
+				goto fail5;
+			}
+			EFRM_ASSERT(((unsigned)1 << iobrs->buf_tbl_alloc.order)
+				    >= (unsigned) iobrs->n_bufs);
+		} else {
+			iobrs->buf_tbl_alloc = linked->buf_tbl_alloc;
+		}
+
+		/* Initialise the buffer table entries. */
+		for (i = 0; i < iobrs->n_bufs; ++i) {
+			/*\ ?? \TODO burst them! */
+			efrm_buffer_table_set(&iobrs->buf_tbl_alloc,
+					      vi_evq->rs.rs_client->nic,
+					      i,
+					      efhw_iopage_dma_addr(&iobrs->
+								   bufs[i]),
+					      owner_id);
+		}
+		efrm_buffer_table_commit();
+	}
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %d pages @ "
+		   EFHW_BUFFER_ADDR_FMT, __func__,
+		   EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle),
+		   iobrs->n_bufs, EFHW_BUFFER_ADDR(iobrs->buf_tbl_alloc.base,
+						   0));
+	efrm_resource_ref(&iobrs->evq->rs);
+	if (linked != NULL)
+		efrm_resource_ref(&linked->rs);
+	efrm_client_add_resource(vi_evq->rs.rs_client, &iobrs->rs);
+	*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_tablep->a_nic here */
+	if (linked) {
+		/* Nothing to do. */
+	} else if (iobrs->chunk_order == 0) {
+		while (i--) {
+			struct efhw_iopage *page = &iobrs->bufs[i];
+			efhw_iopage_free(efrm_nic_tablep->a_nic, page);
+		}
+	} else {
+		unsigned int j;
+		for (j = 0; j < i; j += iobrs->pages_per_contiguous_chunk) {
+			struct efhw_iopages 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->chunk_order);
+			efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages);
+		}
+	}
+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);
+
+	/* HACK: There currently exists an option to allocate buffers that
+	 * are not programmed into the buffer table, so the max number is
+	 * not limited by the buffer table size.  I'm hoping this usage
+	 * will go away eventually.
+	 */
+	max = 32768;
+
+	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);
+	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;
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/assert_valid.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/assert_valid.c
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * 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_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 || rs->rs_ref_count > 0)
+		    || !(!ref_count_is_zero || rs->rs_ref_count == 0))
+			EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT,
+				  __func__,
+				  ref_count_is_zero == 0 ? "non-" : "",
+				  rs->rs_ref_count,
+				  EFRM_RESOURCE_PRI_ARG(rs->rs_handle));
+
+		_EFRM_ASSERT(!(ref_count_is_zero == 0) ||
+			     rs->rs_ref_count != 0, file, line);
+		_EFRM_ASSERT(!(ref_count_is_zero > 0) ||
+			     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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/kfifo.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/kfifo.c
@@ -0,0 +1,208 @@
+/*
+ * 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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/vi_resource_event.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/vi_resource_event.c
@@ -0,0 +1,250 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/efrm_nic.h>
+#include "efrm_internal.h"
+
+
+static inline int
+efrm_eventq_bytes(struct vi_resource *virs)
+{
+	return efrm_vi_rm_evq_bytes(virs);
+}
+
+
+static inline efhw_event_t *
+efrm_eventq_base(struct vi_resource *virs)
+{
+	struct eventq_resource_hardware *hw;
+	hw = &(virs->nic_info.evq_pages);
+	return (efhw_event_t *) (efhw_iopages_ptr(&(hw->iobuff)) +
+				 hw->iobuff_off);
+}
+
+
+void
+efrm_eventq_request_wakeup(struct vi_resource *virs, unsigned current_ptr)
+{
+	struct efhw_nic *nic = virs->rs.rs_client->nic;
+	int next_i;
+	next_i = ((current_ptr / sizeof(efhw_event_t)) &
+		  (virs->evq_capacity - 1));
+
+	efhw_nic_wakeup_request(nic, efrm_eventq_dma_addr(virs), next_i,
+				EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
+}
+EXPORT_SYMBOL(efrm_eventq_request_wakeup);
+
+void efrm_eventq_reset(struct vi_resource *virs)
+{
+	struct efhw_nic *nic = virs->rs.rs_client->nic;
+	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+
+	EFRM_ASSERT(virs->evq_capacity != 0);
+
+	/* FIXME: Protect against concurrent resets. */
+
+	efhw_nic_event_queue_disable(nic, instance, 0);
+
+	memset(efrm_eventq_base(virs), EFHW_CLEAR_EVENT_VALUE,
+	       efrm_eventq_bytes(virs));
+	efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
+				    efrm_eventq_dma_addr(virs),
+				    virs->nic_info.evq_pages.
+				      buf_tbl_alloc.base,
+				    instance < 64);
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
+		   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)
+{
+	struct efrm_nic_per_vi *cb_info;
+	int instance;
+	int bit;
+
+	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
+	EFRM_ASSERT(virs->evq_capacity != 0);
+	EFRM_ASSERT(handler != NULL);
+
+	/* ?? TODO: Get rid of this test when client is compulsory. */
+	if (virs->rs.rs_client == NULL) {
+		EFRM_ERR("%s: no client", __func__);
+		return -EINVAL;
+	}
+
+	virs->evq_callback_arg = arg;
+	virs->evq_callback_fn = handler;
+	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
+
+	/* The handler can be set only once. */
+	bit = test_and_set_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
+			       &cb_info->state);
+	if (bit)
+		return -EBUSY;
+	cb_info->vi = virs;
+
+	return 0;
+}
+EXPORT_SYMBOL(efrm_eventq_register_callback);
+
+void efrm_eventq_kill_callback(struct vi_resource *virs)
+{
+	struct efrm_nic_per_vi *cb_info;
+	int32_t evq_state;
+	int instance;
+	int bit;
+
+	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
+	EFRM_ASSERT(virs->evq_capacity != 0);
+	EFRM_ASSERT(virs->rs.rs_client != NULL);
+
+	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
+	cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
+	cb_info->vi = NULL;
+
+	/* Disable the timer. */
+	efhw_nic_event_queue_disable(virs->rs.rs_client->nic,
+				     instance, /*timer_only */ 1);
+
+	/* Disable the callback. */
+	bit = test_and_clear_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
+				 &cb_info->state);
+	EFRM_ASSERT(bit);	/* do not call me twice! */
+
+	/* Spin until the callback is complete. */
+	do {
+		rmb();
+
+		udelay(1);
+		evq_state = cb_info->state;
+	} while ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)));
+
+	virs->evq_callback_fn = NULL;
+}
+EXPORT_SYMBOL(efrm_eventq_kill_callback);
+
+static void
+efrm_eventq_do_callback(struct efhw_nic *nic, unsigned instance,
+			bool is_timeout)
+{
+	struct efrm_nic *rnic = efrm_nic(nic);
+	void (*handler) (void *, int is_timeout, struct efhw_nic *nic);
+	void *arg;
+	struct efrm_nic_per_vi *cb_info;
+	int32_t evq_state;
+	int32_t new_evq_state;
+	struct vi_resource *virs;
+	int bit;
+
+	EFRM_ASSERT(efrm_vi_manager);
+
+	cb_info = &rnic->vis[instance];
+
+	/* Set the BUSY bit and clear WAKEUP_PENDING.  Do this
+	 * before waking up the sleeper to avoid races. */
+	while (1) {
+		evq_state = cb_info->state;
+		new_evq_state = evq_state;
+
+		if ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)) != 0) {
+			EFRM_ERR("%s:%d: evq_state[%d] corrupted!",
+				 __func__, __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);
+			virs = cb_info->vi;
+			if (cmpxchg(&cb_info->state, evq_state,
+				    new_evq_state) == evq_state)
+				break;
+		} else {
+			/* Just update the state if necessary. */
+			if (new_evq_state == evq_state ||
+			    cmpxchg(&cb_info->state, evq_state,
+				    new_evq_state) == evq_state)
+				return;
+		}
+	}
+
+	if (virs) {
+		handler = virs->evq_callback_fn;
+		arg = virs->evq_callback_arg;
+		EFRM_ASSERT(handler != NULL);
+		handler(arg, is_timeout, nic);
+	}
+
+	/* Clear the BUSY bit. */
+	bit =
+	    test_and_clear_bit(VI_RESOURCE_EVQ_STATE_BUSY,
+			       &cb_info->state);
+	if (!bit) {
+		EFRM_ERR("%s:%d: evq_state corrupted!",
+			 __func__, __LINE__);
+	}
+}
+
+void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned instance)
+{
+	efrm_eventq_do_callback(nic, instance, false);
+}
+
+void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned instance)
+{
+	efrm_eventq_do_callback(nic, instance, true);
+}
+
+void efrm_handle_sram_event(struct efhw_nic *nic)
+{
+  if (nic->buf_commit_outstanding > 0)
+    nic->buf_commit_outstanding--;
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/driverlink_new.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/driverlink_new.c
@@ -0,0 +1,260 @@
+/****************************************************************************
+ * 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>
+#include <net/net_namespace.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_lim = res->evq_timer_lim;
+	rd->evq_int_min = res->evq_int_min;
+	rd->evq_int_lim = res->evq_int_lim;
+	rd->rxq_min = res->rxq_min;
+	rd->rxq_lim = res->rxq_lim;
+	rd->txq_min = res->txq_min;
+	rd->txq_lim = res->txq_lim;
+	EFRM_TRACE
+	    ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)",
+	     res->evq_int_min, res->evq_int_lim, res->evq_timer_min,
+	     res->evq_timer_lim, res->rxq_min, res->rxq_lim, res->txq_min,
+	     res->txq_lim);
+}
+
+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 non_irq_evq;
+	int rc;
+
+	efrm_dev->priv = NULL;
+
+	efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
+				  struct efx_dl_falcon_resources,
+				  hdr, res);
+
+	if (res == NULL) {
+		EFRM_ERR("%s: Unable to find falcon driverlink resources",
+			 __func__);
+		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;
+
+		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.", __func__);
+			return -ENODEV;
+		}
+		pci_dev_put(dev);
+	}
+
+	init_vi_resource_dimensions(&res_dim, res);
+
+	EFRM_ASSERT(res_dim.evq_timer_lim > res_dim.evq_timer_min);
+	res_dim.evq_timer_lim--;
+	non_irq_evq = res_dim.evq_timer_lim;
+
+	rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic,
+			  res->biu_lock,
+			  res->buffer_table_min, res->buffer_table_lim,
+			  non_irq_evq, &res_dim);
+	if (rc != 0)
+		return rc;
+
+	nic = &lnic->efrm_nic.efhw_nic;
+	nic->mtu = net_dev->mtu + ETH_HLEN;
+	nic->net_driver_dev = efrm_dev;
+	nic->ifindex = net_dev->ifindex;
+#ifdef CONFIG_NET_NS
+	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)", __func__);
+		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)",
+			 __func__, 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", __func__);
+	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", __func__);
+}
+
+static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev)
+{
+	EFRM_NOTICE("%s:", __func__);
+}
+
+static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok)
+{
+	EFRM_NOTICE("%s: ok=%d", __func__, ok);
+}
+
+int efrm_driverlink_register(void)
+{
+	EFRM_TRACE("%s:", __func__);
+	return efx_dl_register_driver(&efrm_dl_driver);
+}
+
+void efrm_driverlink_unregister(void)
+{
+	EFRM_TRACE("%s:", __func__);
+	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", __func__, 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", __func__,
+			  (unsigned)FALCON_EVENT_CODE(ev));
+		break;
+	}
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/resource_driver.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/resource_driver.c
@@ -0,0 +1,600 @@
+/****************************************************************************
+ * 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>
+
+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,
+};
+
+const int max_hardware_init_repeats = 10;
+
+/*--------------------------------------------------------------------
+ *
+ * Module load time variables
+ *
+ *--------------------------------------------------------------------*/
+/* See docs/notes/pci_alloc_consistent */
+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(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
+ *
+ *--------------------------------------------------------------------*/
+
+static inline irqreturn_t
+linux_efrm_interrupt(int irr, void *dev_id)
+{
+	return efhw_nic_interrupt((struct efhw_nic *)dev_id);
+}
+
+int linux_efrm_irq_ctor(struct linux_efhw_nic *lnic)
+{
+	struct efhw_nic *nic = &lnic->efrm_nic.efhw_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)",
+				  __func__, rc);
+			EFRM_WARN("%s: Continuing with legacy interrupt mode",
+				  __func__);
+		} else {
+			EFRM_NOTICE("%s: MSI enabled", __func__);
+			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("%s: start", __func__);
+
+	if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_OS_IRQ_EN) {
+		free_irq(lnic->pci_dev->irq, &lnic->efrm_nic.efhw_nic);
+		lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_OS_IRQ_EN;
+	}
+
+	if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_MSI) {
+		pci_disable_msi(lnic->pci_dev);
+		lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_MSI;
+	}
+
+	EFRM_TRACE("%s: done", __func__);
+}
+
+/* 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 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)",
+			     __func__, nic->evq_sizes);
+			return -E2BIG;
+		} else if (capacity & nic->evq_sizes)
+			break;
+	}
+
+	nic->interrupting_evq.hw.capacity = capacity;
+	nic->interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1;
+
+	nic->non_interrupting_evq.hw.capacity = capacity;
+	nic->non_interrupting_evq.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->interrupting_evq
+					     .hw.buf_tbl_alloc);
+		if (rc < 0) {
+			EFRM_WARN
+			    ("%s: failed (%d) to alloc %d buffer table entries",
+			     __func__, rc, page_order);
+			return rc;
+		}
+	}
+	rc = efrm_buffer_table_alloc(page_order,
+				     &nic->non_interrupting_evq.hw.
+				     buf_tbl_alloc);
+	if (rc < 0) {
+		EFRM_WARN
+		    ("%s: failed (%d) to alloc %d buffer table entries",
+		     __func__, 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)
+{
+	if (nic->interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
+		efrm_buffer_table_free(&nic->interrupting_evq.hw
+				       .buf_tbl_alloc);
+	if (nic->non_interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
+		efrm_buffer_table_free(&nic->non_interrupting_evq
+				       .hw.buf_tbl_alloc);
+}
+
+static int iomap_bar(struct linux_efhw_nic *lnic, size_t len)
+{
+	volatile char __iomem *ioaddr;
+
+	ioaddr = ioremap_nocache(lnic->ctr_ap_pci_addr, len);
+	if (ioaddr == 0)
+		return -ENOMEM;
+
+	lnic->efrm_nic.efhw_nic.bar_ioaddr = ioaddr;
+	return 0;
+}
+
+static int linux_efhw_nic_map_ctr_ap(struct linux_efhw_nic *lnic)
+{
+	struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
+	int rc;
+
+	rc = iomap_bar(lnic, nic->ctr_ap_bytes);
+
+	/* 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);
+	}
+
+	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->efrm_nic.efhw_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)",
+			 __func__, 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)",
+			 __func__, (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)",
+			 __func__, 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", __func__,
+			 (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", __func__,
+			 (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",
+			 __func__, (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->efrm_nic.efhw_nic;
+	volatile char __iomem *bar_ioaddr = nic->bar_ioaddr;
+
+	efhw_nic_dtor(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->interrupting_evq);
+	EFRM_TRACE("%s: complete", __func__);
+}
+
+/****************************************************************************
+ *
+ * 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", __func__);
+	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_lim, int non_irq_evq,
+	     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)", __func__,
+		   pci_name(dev) ? pci_name(dev) : "?", dev->irq);
+
+	/* Ensure that we have room for the new adapter-structure. */
+	if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
+		EFRM_WARN("%s: WARNING: too many devices", __func__);
+		rc = -ENOMEM;
+		goto failed;
+	}
+
+	if (n_nics_probed == 0) {
+		rc = efrm_resources_init(res_dim, bt_min, bt_lim);
+		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", __func__);
+		rc = -ENOMEM;
+		goto failed;
+	}
+	memset(lnic, 0, sizeof(*lnic));
+	nic = &lnic->efrm_nic.efhw_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", __func__);
+		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(&lnic->efrm_nic, nic_index,
+				      /* TODO: ifindex */ nic_index);
+	if (rc < 0) {
+		EFRM_ERR("%s: cannot register nic %d with nic error code %d",
+			 __func__, efrm_nic_tablep->nic_count, rc);
+		goto failed;
+	}
+	++nic_index;
+	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,
+					    non_irq_evq);
+		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, -1, irq_moderation);
+		efhw_nic_interrupt_enable(nic);
+	}
+	EFRM_TRACE("interrupts are %sregistered", do_irq ? "" : "not ");
+
+	*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(&lnic->efrm_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->efrm_nic.efhw_nic;
+
+	EFRM_TRACE("%s:", __func__);
+	EFRM_ASSERT(nic);
+
+	efrm_nic_buffer_table_free(nic);
+
+	efrm_driver_unregister_nic(&lnic->efrm_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("%s: done", __func__);
+}
+
+/****************************************************************************
+ *
+ * init_module: register as a PCI driver.
+ *
+ ****************************************************************************/
+static int init_sfc_resource(void)
+{
+	int rc = 0;
+
+	EFRM_TRACE("%s: RESOURCE driver starting", __func__);
+
+	efrm_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", __func__);
+	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",
+			  __func__);
+	}
+
+	return 0;
+
+failed_driverlink:
+	efrm_driver_dtor();
+	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("%s: unloaded", __func__);
+}
+
+module_init(init_sfc_resource);
+module_exit(cleanup_sfc_resource);
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/filter_resource.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/filter_resource.c
@@ -0,0 +1,250 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/efrm_client.h>
+#include "efrm_internal.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 = frs->rs.rs_client->nic;
+	int id;
+
+	EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 1);
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
+		   EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle));
+
+	efhw_nic_ipfilter_clear(nic, frs->filter_idx);
+	frs->filter_idx = -1;
+	efrm_vi_resource_release(frs->pt);
+
+	/* 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_client_put(frs->rs.rs_client);
+	EFRM_DO_DEBUG(memset(frs, 0, sizeof(*frs)));
+	kfree(frs);
+}
+EXPORT_SYMBOL(efrm_filter_resource_free);
+
+
+void efrm_filter_resource_release(struct filter_resource *frs)
+{
+	if (__efrm_resource_release(&frs->rs))
+		efrm_filter_resource_free(frs);
+}
+EXPORT_SYMBOL(efrm_filter_resource_release);
+
+
+static void filter_rm_dtor(struct efrm_resource_manager *rm)
+{
+	EFRM_TRACE("%s:", __func__);
+
+	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("%s: done", __func__);
+}
+
+/**********************************************************************/
+/**********************************************************************/
+/**********************************************************************/
+
+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);
+	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",
+		   __func__, 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;
+
+}
+
+
+int efrm_filter_resource_clear(struct filter_resource *frs)
+{
+	struct efhw_nic *nic = frs->rs.rs_client->nic;
+
+	efhw_nic_ipfilter_clear(nic, frs->filter_idx);
+	frs->filter_idx = -1;
+	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 = frs->rs.rs_client->nic;
+	int vi_instance;
+
+	EFRM_ASSERT(frs);
+
+	if (efrm_nic_tablep->a_nic->devtype.variant >= 'B' &&
+	    (frs->pt->flags & EFHW_VI_JUMBO_EN) == 0)
+		type |= EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK;
+	vi_instance = EFRM_RESOURCE_INSTANCE(frs->pt->rs.rs_handle);
+
+	return efhw_nic_ipfilter_set(nic, type, &frs->filter_idx,
+				     vi_instance, saddr, sport, daddr, dport);
+}
+EXPORT_SYMBOL(__efrm_filter_resource_set);;
+
+
+int
+efrm_filter_resource_alloc(struct vi_resource *vi_parent,
+			   struct filter_resource **frs_out)
+{
+	struct filter_resource *frs;
+	int rc, instance;
+
+	EFRM_ASSERT(frs_out);
+	EFRM_ASSERT(efrm_filter_manager);
+	EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
+	EFRM_ASSERT(vi_parent != NULL);
+	EFRM_ASSERT(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;
+
+	/* 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", __func__);
+		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;
+	efrm_resource_ref(&frs->pt->rs);
+	frs->filter_idx = -1;
+
+	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " VI %d", __func__,
+		   EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle),
+		   EFRM_RESOURCE_INSTANCE(vi_parent->rs.rs_handle));
+
+	efrm_client_add_resource(vi_parent->rs.rs_client, &frs->rs);
+	*frs_out = frs;
+	return 0;
+
+fail1:
+	memset(frs, 0, sizeof(*frs));
+	kfree(frs);
+	return rc;
+}
+EXPORT_SYMBOL(efrm_filter_resource_alloc);
+
+
+int efrm_filter_resource_instance(struct filter_resource *frs)
+{
+	return EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
+}
+EXPORT_SYMBOL(efrm_filter_resource_instance);
+
+
+struct efrm_resource *
+efrm_filter_resource_to_resource(struct filter_resource *frs)
+{
+	return &frs->rs;
+}
+EXPORT_SYMBOL(efrm_filter_resource_to_resource);
+
+
+struct filter_resource *
+efrm_filter_resource_from_resource(struct efrm_resource *rs)
+{
+	return filter_resource(rs);
+}
+EXPORT_SYMBOL(efrm_filter_resource_from_resource);
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/resource_manager.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/resource_manager.c
@@ -0,0 +1,145 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/private.h>
+#include "efrm_internal.h"
+
+/**********************************************************************
+ * 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",
+			       __func__, rm->rm_name, rm->rm_resources));
+	EFRM_ASSERT(rm->rm_resources == 0);
+	EFRM_ASSERT(list_empty(&rm->rm_resources_list));
+
+	rm->rm_dtor(rm);
+
+	/* clear out things built by efrm_resource_manager_ctor */
+	spin_lock_destroy(&rm->rm_lock);
+
+	/* 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)
+{
+	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;
+	INIT_LIST_HEAD(&rm->rm_resources_list);
+	EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
+	return 0;
+}
+
+
+void efrm_client_add_resource(struct efrm_client *client,
+			      struct efrm_resource *rs)
+{
+	struct efrm_resource_manager *rm;
+	irq_flags_t lock_flags;
+
+	EFRM_ASSERT(client != NULL);
+	EFRM_ASSERT(rs != NULL);
+
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
+	++rm->rm_resources;
+	list_add(&rs->rs_manager_link, &rm->rm_resources_list);
+	if (rm->rm_resources > rm->rm_resources_hiwat)
+		rm->rm_resources_hiwat = rm->rm_resources;
+	rs->rs_client = client;
+	++client->ref_count;
+	list_add(&rs->rs_client_link, &client->resources);
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+}
+
+
+void efrm_resource_ref(struct efrm_resource *rs)
+{
+	irq_flags_t lock_flags;
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	++rs->rs_ref_count;
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+}
+EXPORT_SYMBOL(efrm_resource_ref);
+
+
+int __efrm_resource_release(struct efrm_resource *rs)
+{
+	struct efrm_resource_manager *rm;
+	irq_flags_t lock_flags;
+	int free_rs;
+
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	free_rs = --rs->rs_ref_count == 0;
+	if (free_rs) {
+		rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
+		EFRM_ASSERT(rm->rm_resources > 0);
+		--rm->rm_resources;
+		list_del(&rs->rs_manager_link);
+		list_del(&rs->rs_client_link);
+	}
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+	return free_rs;
+}
+EXPORT_SYMBOL(__efrm_resource_release);
+
+/*
+ * vi: sw=8:ai:aw
+ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/kernel_proc.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/kernel_proc.c
@@ -0,0 +1,109 @@
+/****************************************************************************
+ * 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/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("driver/sfc_resource", NULL);
+	if (!efrm_proc_root)
+		return -ENOMEM;
+
+	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", __func__);
+	}
+	return 0;
+}
+
+void efrm_uninstall_proc_entries(void)
+{
+	EFRM_ASSERT(efrm_proc_root);
+	remove_proc_entry("resources", efrm_proc_root);
+	remove_proc_entry(efrm_proc_root->name, efrm_proc_root->parent);
+	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;
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/linux_resource_internal.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/linux_resource_internal.h
@@ -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 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, int non_irq_evq,
+	     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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/kernel_compat.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/kernel_compat.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * 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/moduleparam.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+
+/********* pci_map_*() ********************/
+
+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 */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/kernel_compat.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/kernel_compat.c
@@ -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 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
+
+
+/****************************************************************************
+ *
+ * allocate a buffer suitable for DMA to/from the NIC
+ *
+ ****************************************************************************/
+
+#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)
+{
+	void *ptr;
+	unsigned order;
+
+	order = __ffs(size/PAGE_SIZE);
+	EFRM_ASSERT(size == (PAGE_SIZE<<order));
+
+	/* 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;
+
+#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)
+{
+	unsigned order;
+
+	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
+
+	dma_free_coherent(dev, size, ptr, dma_addr);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/buddy.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/buddy.c
@@ -0,0 +1,220 @@
+
+/****************************************************************************
+ * 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",
+		    __func__, 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", __func__, 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) 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)", __func__, 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)", __func__, 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)", __func__, 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, buddy_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);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/eventq.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/eventq.c
@@ -0,0 +1,321 @@
+/****************************************************************************
+ * 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",
+			  __func__, 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", __func__, 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,
+				    1 /* interrupting */);
+
+	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", __func__, 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]", __func__, 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", __func__, instance);
+
+	if (!h->dmaq_flushed_fn) {
+		EFHW_WARN("%s: no handler registered", __func__);
+		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)
+{
+	unsigned instance = (unsigned)FALCON_EVENT_RX_FLUSH_Q_ID(evp);
+	EFHW_TRACE("%s: instance=%d", __func__, instance);
+
+	if (!h->dmaq_flushed_fn) {
+		EFHW_WARN("%s: no handler registered", __func__);
+		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)
+{
+	unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
+
+	if (!h->wakeup_fn) {
+		EFHW_WARN("%s: no handler registered", __func__);
+		return;
+	}
+
+	h->wakeup_fn(nic, instance);
+}
+
+void
+efhw_handle_timeout_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
+			  efhw_event_t *evp)
+{
+	unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
+
+	if (!h->timeout_fn) {
+		EFHW_WARN("%s: no handler registered", __func__);
+		return;
+	}
+
+	h->timeout_fn(nic, instance);
+}
+
+/**********************************************************************
+ * 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!", __func__, 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)) {
+
+			case FALCON_EVENT_CODE_CHAR:
+				falcon_handle_char_event(nic, q->ev_handlers,
+							 ev);
+				break;
+
+			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:
+	/* 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);
+	return count;
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/efx_vi_shm.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/efx_vi_shm.c
@@ -0,0 +1,707 @@
+/****************************************************************************
+ * 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/vi_resource_manager.h>
+#include <ci/driver/resource/efx_vi.h>
+#include <ci/efrm/filter.h>
+#include <ci/efrm/buffer_table.h>
+#include <ci/efrm/efrm_client.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 ifindex;
+	struct efrm_client *efrm_client;
+	struct efhw_nic *nic;
+
+	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(state->efrm_client, 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",
+			 __func__, 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",
+			     __func__, 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 ifindex)
+{
+	struct efx_vi_state *efx_state;
+	int rc;
+
+	efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL);
+
+	if (!efx_state) {
+		EFRM_ERR("%s: failed to allocate memory for efx_vi_state",
+			 __func__);
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	efx_state->ifindex = ifindex;
+	rc = efrm_client_get(ifindex, NULL, NULL, &efx_state->efrm_client);
+	if (rc < 0) {
+		EFRM_ERR("%s: efrm_client_get(%d) failed: %d", __func__,
+			 ifindex, rc);
+		rc = -ENODEV;
+		goto fail_no_ifindex;
+	}
+	efx_state->nic = efrm_client_get_nic(efx_state->efrm_client);
+
+	init_completion(&efx_state->flush_completion);
+
+	/* basically allocate_pt_endpoint() */
+	rc = alloc_ep(efx_state);
+	if (rc) {
+		EFRM_ERR("%s: alloc_ep failed: %d", __func__, 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:
+	efrm_client_put(efx_state->efrm_client);
+fail_no_ifindex:
+	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);
+
+	efrm_client_put(efx_state->efrm_client);
+
+	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);
+	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)", __func__, 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(efx_state->nic)->
+					  pci_dev, pages[i], 0, PAGE_SIZE,
+					PCI_DMA_TODEVICE);
+
+		efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic,
+				      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)", __func__, 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",
+		  __func__, 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, efx_state->nic,
+				      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(efx_state->nic)->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", __func__);
+#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 *uninitialized_var(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!", __func__);
+
+	return 0;
+}
+EXPORT_SYMBOL(efx_vi_hw_resource_get_virt);
+
+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;
+	struct linux_efhw_nic *lnic = linux_efhw_nic(efx_state->nic);
+	unsigned long phys = lnic->ctr_ap_pci_addr;
+	struct efrm_resource *ep_res = &efx_state->vi_res->rs;
+	unsigned ep_mmap_bytes;
+	int i;
+
+	if (*length < EFX_VI_HW_RESOURCE_MAXSIZE)
+		return -EINVAL;
+
+	mdata->nic_arch = efx_state->nic->devtype.arch;
+	mdata->nic_variant = efx_state->nic->devtype.variant;
+	mdata->nic_revision = efx_state->nic->devtype.revision;
+
+	mdata->evq_order =
+	    efx_state->vi_res->nic_info.evq_pages.iobuff.order;
+	mdata->evq_offs = efx_state->vi_res->nic_info.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.
+			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.
+			dmaq_pages[EFRM_VI_RM_DMA_QUEUE_RX].kva;
+
+	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 (efx_state->nic->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.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);
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/nic.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/nic.c
@@ -0,0 +1,176 @@
+/****************************************************************************
+ * 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)
+{
+	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;
+
+	nic->irq_unit = EFHW_IRQ_UNIT_UNUSED;
+
+	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;
+		nic->num_evqs   = 4096;
+		nic->num_dmaqs  = 4096;
+		nic->num_timers = 4096;
+		break;
+	case 'B':
+		nic->flags |= NIC_FLAG_NO_INTERRUPT;
+		nic->ctr_ap_bar = FALCON_P_CTR_AP_BAR;
+		nic->num_evqs   = 4096;
+		nic->num_dmaqs  = 4096;
+		nic->num_timers = 4096;
+		break;
+	default:
+		EFHW_ASSERT(0);
+		break;
+	}
+}
+
+
+void efhw_nic_close_interrupts(struct efhw_nic *nic)
+{
+	EFHW_ASSERT(nic);
+	if (!efhw_nic_have_hw(nic))
+		return;
+
+	EFHW_ASSERT(efhw_nic_have_hw(nic));
+
+	if (nic->irq_unit != EFHW_IRQ_UNIT_UNUSED)
+		efhw_nic_interrupt_disable(nic);
+}
+
+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 */
+
+	/* 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 ... ", __func__);
+
+	if (efhw_nic_have_functional_units(nic)) {
+		efhw_nic_close_interrupts(nic);
+		efhw_nic_close_hardware(nic);
+	}
+	EFHW_TRACE("%s: functional units ... done", __func__);
+
+	/* destroy event queues */
+	EFHW_TRACE("%s: event queues ... ", __func__);
+
+	if (nic->interrupting_evq.evq_mask)
+		efhw_keventq_dtor(nic, &nic->interrupting_evq);
+	if (nic->non_interrupting_evq.evq_mask)
+		efhw_keventq_dtor(nic, &nic->non_interrupting_evq);
+
+	EFHW_TRACE("%s: event queues ... done", __func__);
+
+	spin_lock_destroy(&nic->the_reg_lock);
+
+	EFHW_TRACE("%s: DONE", __func__);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/driver_object.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/driver_object.c
@@ -0,0 +1,328 @@
+/****************************************************************************
+ * 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>
+#include <ci/efrm/efrm_client.h>
+#include <ci/efrm/efrm_nic.h>
+#include "efrm_internal.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_tablep->lock, irqlock_state)
+
+#define efrm_driver_unlock(irqlock_state)		\
+	spin_unlock_irqrestore(&efrm_nic_tablep->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 */
+static struct efrm_nic_table efrm_nic_table;
+struct efrm_nic_table *efrm_nic_tablep;
+EXPORT_SYMBOL(efrm_nic_tablep);
+
+
+/* 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);
+
+
+/* List of registered nics. */
+static LIST_HEAD(efrm_nics);
+
+
+void efrm_driver_ctor(void)
+{
+	efrm_nic_tablep = &efrm_nic_table;
+	spin_lock_init(&efrm_nic_tablep->lock);
+	EFRM_TRACE("%s: driver created", __func__);
+}
+
+void efrm_driver_dtor(void)
+{
+	EFRM_ASSERT(!efrm_nic_table_held());
+
+	spin_lock_destroy(&efrm_nic_tablep->lock);
+	memset(&efrm_nic_table, 0, sizeof(efrm_nic_table));
+	memset(&efrm_rm_table, 0, sizeof(efrm_rm_table));
+	EFRM_TRACE("%s: driver deleted", __func__);
+}
+
+int efrm_driver_register_nic(struct efrm_nic *rnic, int nic_index,
+			     int ifindex)
+{
+	struct efhw_nic *nic = &rnic->efhw_nic;
+	struct efrm_nic_per_vi *vis;
+	int max_vis, rc = 0;
+	irq_flags_t lock_flags;
+
+	EFRM_ASSERT(nic_index >= 0);
+	EFRM_ASSERT(ifindex >= 0);
+
+	max_vis = 4096; /* TODO: Get runtime value. */
+	vis = vmalloc(max_vis * sizeof(rnic->vis[0]));
+	if (vis == NULL) {
+		EFRM_ERR("%s: Out of memory", __func__);
+		return -ENOMEM;
+	}
+
+	efrm_driver_lock(lock_flags);
+
+	if (efrm_nic_table_held()) {
+		EFRM_ERR("%s: driver object is in use", __func__);
+		rc = -EBUSY;
+		goto done;
+	}
+
+	if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
+		EFRM_ERR("%s: filled up NIC table size %d", __func__,
+			 EFHW_MAX_NR_DEVS);
+		rc = -E2BIG;
+		goto done;
+	}
+
+	rnic->vis = vis;
+
+	EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == NULL);
+	efrm_nic_tablep->nic[nic_index] = nic;
+	nic->index = nic_index;
+	nic->ifindex = ifindex;
+
+	if (efrm_nic_tablep->a_nic == NULL)
+		efrm_nic_tablep->a_nic = nic;
+
+	efrm_nic_tablep->nic_count++;
+
+	INIT_LIST_HEAD(&rnic->clients);
+	list_add(&rnic->link, &efrm_nics);
+
+	efrm_driver_unlock(lock_flags);
+	return 0;
+
+done:
+	efrm_driver_unlock(lock_flags);
+	vfree(vis);
+	return rc;
+}
+
+int efrm_driver_unregister_nic(struct efrm_nic *rnic)
+{
+	struct efhw_nic *nic = &rnic->efhw_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_ERR("%s: driver object is in use", __func__);
+		rc = -EBUSY;
+		goto done;
+	}
+	if (!list_empty(&rnic->clients)) {
+		EFRM_ERR("%s: nic has active clients", __func__);
+		rc = -EBUSY;
+		goto done;
+	}
+
+	EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == nic);
+	EFRM_ASSERT(list_empty(&rnic->clients));
+
+	list_del(&rnic->link);
+
+	nic->index = -1;
+	efrm_nic_tablep->nic[nic_index] = NULL;
+
+	--efrm_nic_tablep->nic_count;
+
+	if (efrm_nic_tablep->a_nic == nic) {
+		if (efrm_nic_tablep->nic_count == 0) {
+			efrm_nic_tablep->a_nic = NULL;
+		} else {
+			for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS;
+			     nic_index++) {
+				if (efrm_nic_tablep->nic[nic_index] != NULL)
+					efrm_nic_tablep->a_nic =
+					    efrm_nic_tablep->nic[nic_index];
+			}
+			EFRM_ASSERT(efrm_nic_tablep->a_nic);
+		}
+	}
+
+done:
+	efrm_driver_unlock(lock_flags);
+	return rc;
+}
+
+
+int efrm_nic_pre_reset(struct efhw_nic *nic)
+{
+	struct efrm_nic *rnic = efrm_nic(nic);
+	struct efrm_client *client;
+	struct efrm_resource *rs;
+	struct list_head *client_link;
+	struct list_head *rs_link;
+	irq_flags_t lock_flags;
+
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	list_for_each(client_link, &rnic->clients) {
+		client = container_of(client_link, struct efrm_client, link);
+		EFRM_ERR("%s: client %p", __func__, client);
+		if (client->callbacks->pre_reset)
+			client->callbacks->pre_reset(client, client->user_data);
+		list_for_each(rs_link, &client->resources) {
+			rs = container_of(rs_link, struct efrm_resource,
+					  rs_client_link);
+			EFRM_ERR("%s: resource %p", __func__, rs);
+			/* TODO: mark rs defunct */
+		}
+	}
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+
+	return 0;
+}
+
+
+int efrm_nic_stop(struct efhw_nic *nic)
+{
+	/* TODO */
+	return 0;
+}
+
+
+int efrm_nic_resume(struct efhw_nic *nic)
+{
+	/* TODO */
+	return 0;
+}
+
+
+static void efrm_client_nullcb(struct efrm_client *client, void *user_data)
+{
+}
+
+static struct efrm_client_callbacks efrm_null_callbacks = {
+	efrm_client_nullcb,
+	efrm_client_nullcb,
+	efrm_client_nullcb
+};
+
+
+int efrm_client_get(int ifindex, struct efrm_client_callbacks *callbacks,
+		    void *user_data, struct efrm_client **client_out)
+{
+	struct efrm_nic *n, *rnic = NULL;
+	irq_flags_t lock_flags;
+	struct list_head *link;
+	struct efrm_client *client;
+
+	if (callbacks == NULL)
+		callbacks = &efrm_null_callbacks;
+
+	client = kmalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	list_for_each(link, &efrm_nics) {
+		n = container_of(link, struct efrm_nic, link);
+		if (n->efhw_nic.ifindex == ifindex || ifindex < 0) {
+			rnic = n;
+			break;
+		}
+	}
+	if (rnic) {
+		client->user_data = user_data;
+		client->callbacks = callbacks;
+		client->nic = &rnic->efhw_nic;
+		client->ref_count = 1;
+		INIT_LIST_HEAD(&client->resources);
+		list_add(&client->link, &rnic->clients);
+	}
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+
+	if (rnic == NULL)
+		return -ENODEV;
+
+	*client_out = client;
+	return 0;
+}
+EXPORT_SYMBOL(efrm_client_get);
+
+
+void efrm_client_put(struct efrm_client *client)
+{
+	irq_flags_t lock_flags;
+
+	EFRM_ASSERT(client->ref_count > 0);
+
+	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
+	if (--client->ref_count > 0)
+		client = NULL;
+	else
+		list_del(&client->link);
+	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
+	kfree(client);
+}
+EXPORT_SYMBOL(efrm_client_put);
+
+
+struct efhw_nic *efrm_client_get_nic(struct efrm_client *client)
+{
+	return client->nic;
+}
+EXPORT_SYMBOL(efrm_client_get_nic);
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/buffer_table.c
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/buffer_table.c
@@ -0,0 +1,209 @@
+/****************************************************************************
+ * 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, i;
+
+	EFRM_ASSERT(high > 0);
+	EFRM_ASSERT(low < high);
+
+	EFRM_TRACE("%s: low=%u high=%u", __func__, low, high);
+	EFRM_NOTICE("%s: low=%u high=%u", __func__, 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;
+	}
+	for (i = 0; i < (1 << log2_n_entries); ++i) {
+		rc = efrm_buddy_alloc(&efrm_buffers.buddy, 0);
+		EFRM_ASSERT(rc >= 0);
+		EFRM_ASSERT(rc < (1 << log2_n_entries));
+	}
+	for (i = low; i < (int) high; ++i)
+		efrm_buddy_free(&efrm_buffers.buddy, i, 0);
+
+	spin_lock_init(&efrm_buffers.lock);
+
+	EFRM_TRACE("%s: done", __func__);
+
+	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("%s: done", __func__);
+}
+
+/**********************************************************************/
+
+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,
+		      struct efhw_nic *nic,
+		      unsigned i, dma_addr_t dma_addr, int owner)
+{
+	EFRM_ASSERT(a);
+	EFRM_ASSERT(i < (unsigned)1 << a->order);
+
+	efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE,
+				  0, owner, a->base + i);
+}
+
+
+int efrm_buffer_table_size(void)
+{
+	return efrm_buddy_size(&efrm_buffers.buddy);
+}
+
+/**********************************************************************/
+
+int
+efrm_page_register(struct efhw_nic *nic, 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, nic, 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);
+}
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h
@@ -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 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, non_irq_evq) \
+	((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr), \
+					 (non_irq_evq)))
+
+/*-------------- 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) \
+	((nic)->efhw_func->interrupt_enable(nic))
+
+#define efhw_nic_interrupt_disable(nic) \
+	((nic)->efhw_func->interrupt_disable(nic))
+
+#define efhw_nic_set_interrupt_moderation(nic, evq, val)                 \
+	((nic)->efhw_func->set_interrupt_moderation(nic, evq, val))
+
+/*-------------- Event support  ------------ */
+
+#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base,   \
+				    interrupting)                       \
+	((nic)->efhw_func->event_queue_enable((nic), (evq), (size), (q_base), \
+					      (buf_base), (interrupting)))
+
+#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_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))
+
+/*-------------- New filter API ------------ */
+#define efhw_nic_filter_set(nic, spec, index_out) \
+	((nic)->efhw_func->filter_set(nic, spec, index_out))
+
+#define efhw_nic_filter_clear(nic, type, index_out) \
+	((nic)->efhw_func->filter_clear(nic, type, index_out))
+
+
+/* --- 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
+
+#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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h
@@ -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 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_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 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 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 */
+
+#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h
@@ -0,0 +1,422 @@
+/****************************************************************************
+ * 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_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
+ *
+ *---------------------------------------------------------------------------*/
+
+/* Note: the following constants have moved to values in struct efhw_nic:
+ *   FALCON_EVQ_TBL_NUM  ->  nic->num_evqs
+ *   FALCON_DMAQ_NUM     ->  nic->num_dmaqs
+ *   FALCON_TIMERS_NUM   ->  nic->num_times
+ * These replacement constants are used as sanity checks in assertions in
+ * certain functions that don't have access to struct efhw_nic.
+ */
+#define FALCON_DMAQ_NUM_SANITY          (EFHW_4K)
+#define FALCON_EVQ_TBL_NUM_SANITY       (EFHW_4K)
+#define FALCON_TIMERS_NUM_SANITY        (EFHW_4K)
+
+/* This value is an upper limit on the total number of filter table
+ * entries.  The actual size of filter table is determined at runtime, as
+ * it can vary.
+ */
+#define FALCON_FILTER_TBL_NUM		(EFHW_8K)
+
+/* 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(volatile char __iomem *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(volatile char __iomem *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(volatile char __iomem *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(volatile char __iomem *kva, uint64_t q0, uint64_t q1)
+{
+	writeq(q0, kva + 0);
+	falcon_write_q(kva + 8, q1);
+}
+
+static inline void
+falcon_read_qq(volatile char __iomem *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_SANITY);
+
+	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_SANITY);
+
+	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_SANITY);
+
+	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      */
+
+/* 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(volatile char __iomem *efhw_kva, unsigned what)
+{
+	writel(what, efhw_kva + 0x300);
+	mmiowb();
+}
+#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */
+/*! \cidoxg_end */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h
@@ -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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h
@@ -0,0 +1,1147 @@
+/****************************************************************************
+ * 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 NIC_STAT_REG_KER_OFST 0x200 /* ASIC strap status register */
+#define NIC_STAT_REG_OFST 0x200 /* ASIC strap status register */
+  #define ONCHIP_SRAM_LBN 16
+  #define ONCHIP_SRAM_WIDTH 0
+  #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_NOTAF_LBN 19
+  #define TX_PACE_SB_NOTAF_WIDTH 10
+  #define TX_PACE_SB_AF_LBN 9
+  #define TX_PACE_SB_AF_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
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * 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__
+
+#include <ci/efrm/efrm_nic.h>
+#include <linux/interrupt.h>
+
+
+/************************************************************************
+ * Per-nic structure in the resource driver                             *
+ ************************************************************************/
+
+struct linux_efhw_nic {
+	struct efrm_nic efrm_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, efrm_nic.efhw_nic)
+
+#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+ * 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 ifindex Index of the network interface desired
+ * \return Zero on success (and vih_out set), non-zero on failure.
+ */
+extern int
+efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex);
+
+/*!
+ * 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_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 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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h
@@ -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 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);
+
+
+#endif /* __CI_EFRM_BUDDY_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * 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/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>
+#include <linux/log2.h>
+#include <linux/kfifo.h>
+
+
+/********************************************************************
+ *
+ * List API
+ *
+ ********************************************************************/
+
+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;
+}
+
+/********************************************************************
+ *
+ * Kfifo API
+ *
+ ********************************************************************/
+
+static inline void kfifo_vfree(struct kfifo *fifo)
+{
+	vfree(fifo->buffer);
+	kfree(fifo);
+}
+
+#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h
@@ -0,0 +1,26 @@
+#ifndef __EFRM_NIC_H__
+#define __EFRM_NIC_H__
+
+#include <ci/efhw/efhw_types.h>
+
+
+struct efrm_nic_per_vi {
+	unsigned long state;
+	struct vi_resource *vi;
+};
+
+
+struct efrm_nic {
+	struct efhw_nic efhw_nic;
+	struct list_head link;
+	struct list_head clients;
+	struct efrm_nic_per_vi *vis;
+};
+
+
+#define efrm_nic(_efhw_nic)				\
+  container_of(_efhw_nic, struct efrm_nic, efhw_nic)
+
+
+
+#endif  /* __EFRM_NIC_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/resource.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/resource.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * 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 {
+	int rs_ref_count;
+	efrm_resource_handle_t rs_handle;
+	struct efrm_client *rs_client;
+	struct list_head rs_client_link;
+	struct list_head rs_manager_link;
+};
+
+/*--------------------------------------------------------------------
+ *
+ * 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;
+	struct list_head rm_resources_list;
+	/**
+	 * 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
+
+
+extern void efrm_resource_ref(struct efrm_resource *rs);
+extern int  __efrm_resource_release(struct efrm_resource *);
+
+
+#endif /* __CI_EFRM_RESOURCE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * 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);
+
+/*! Wakeup handler */
+extern void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned id);
+
+/*! Timeout handler */
+extern void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned id);
+
+/*! DMA flush handler */
+extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, unsigned id,
+				   int rx_flush);
+
+/*! SRAM update handler */
+extern void efrm_handle_sram_event(struct efhw_nic *nic);
+
+#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+ * 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 iobufset_resource *linked;
+	struct efhw_buffer_table_allocation buf_tbl_alloc;
+	unsigned int n_bufs;
+	unsigned int pages_per_contiguous_chunk;
+	unsigned chunk_order;
+	struct efhw_iopage 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        VI that "owns" these buffers. Grabs a reference
+ *                  on success.
+ * \param linked    Uses memory from an existing iobufset.  Grabs a
+ *                  reference 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,
+			     struct iobufset_resource *linked,
+			     bool phys_addr_mode,
+			     struct iobufset_resource **iobrs_out);
+
+extern void efrm_iobufset_resource_free(struct iobufset_resource *);
+extern void efrm_iobufset_resource_release(struct iobufset_resource *);
+
+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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * 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>
+
+#include <ci/efrm/sysdep_linux.h>
+
+#endif /* __CI_EFRM_SYSDEP_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h
@@ -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 {
+	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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/debug.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/debug.h
@@ -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 __func__ 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 !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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h
@@ -0,0 +1,32 @@
+#ifndef __EFRM_CLIENT_H__
+#define __EFRM_CLIENT_H__
+
+
+struct efrm_client;
+
+
+struct efrm_client_callbacks {
+	/* Called before device is reset.  Callee may block. */
+	void (*pre_reset)(struct efrm_client *, void *user_data);
+	void (*stop)(struct efrm_client *, void *user_data);
+	void (*restart)(struct efrm_client *, void *user_data);
+};
+
+
+#define EFRM_IFINDEX_DEFAULT  -1
+
+
+/* NB. Callbacks may be invoked even before this returns. */
+extern int  efrm_client_get(int ifindex, struct efrm_client_callbacks *,
+			    void *user_data, struct efrm_client **client_out);
+extern void efrm_client_put(struct efrm_client *);
+
+extern struct efhw_nic *efrm_client_get_nic(struct efrm_client *);
+
+#if 0
+/* For each resource type... */
+extern void efrm_x_resource_resume(struct x_resource *);
+#endif
+
+
+#endif  /* __EFRM_CLIENT_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/filter.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/filter.h
@@ -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 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/efhw/common.h>
+
+
+struct filter_resource;
+struct vi_resource;
+struct efrm_client;
+
+
+/*!
+ * 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);
+
+extern void
+efrm_filter_resource_release(struct filter_resource *);
+
+
+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);
+}
+
+
+extern int
+efrm_filter_resource_instance(struct filter_resource *);
+
+extern struct efrm_resource *
+efrm_filter_resource_to_resource(struct filter_resource *);
+
+extern struct filter_resource *
+efrm_filter_resource_from_resource(struct efrm_resource *);
+
+extern void
+efrm_filter_resource_free(struct filter_resource *);
+
+
+#endif /* __CI_EFRM_FILTER_H__ */
+/*! \cidoxg_end */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+ * 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 efrm_client *client,
+		       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);
+
+extern void efrm_vi_resource_free(struct vi_resource *);
+extern void efrm_vi_resource_release(struct vi_resource *);
+
+
+/*--------------------------------------------------------------------
+ *
+ * eventq handling
+ *
+ *--------------------------------------------------------------------*/
+
+/*! Reset an event queue and clear any associated timers */
+extern void efrm_eventq_reset(struct vi_resource *virs);
+
+/*! 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);
+
+/*! 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 */);
+
+
+/* Fill [out_vi_data] with information required to allow a VI to be init'd.
+ * [out_vi_data] must ref at least VI_MAPPINGS_SIZE bytes.
+ */
+extern void efrm_vi_resource_mappings(struct vi_resource *, void *out_vi_data);
+
+
+#endif /* __CI_EFRM_VI_RESOURCE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h
@@ -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_tablep;
+
+static inline void efrm_nic_table_hold(void)
+{
+	atomic_inc(&efrm_nic_tablep->ref_count);
+}
+
+static inline void efrm_nic_table_rele(void)
+{
+	atomic_dec(&efrm_nic_tablep->ref_count);
+}
+
+static inline int efrm_nic_table_held(void)
+{
+	return atomic_read(&efrm_nic_tablep->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_tablep->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_tablep->nic[_i]) &&		\
+		    efrm_nic_set_read((_set), (_i)))
+
+#endif /* __CI_EFRM_NIC_TABLE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+ * 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
+ *
+ *--------------------------------------------------------------------*/
+
+struct efrm_nic;
+
+extern void efrm_driver_ctor(void);
+extern void efrm_driver_dtor(void);
+extern int efrm_driver_register_nic(struct efrm_nic *, int nic_index,
+				    int ifindex);
+extern int efrm_driver_unregister_nic(struct efrm_nic *);
+
+/*--------------------------------------------------------------------
+ *
+ * create/destroy resource managers
+ *
+ *--------------------------------------------------------------------*/
+
+struct vi_resource_dimensions {
+	unsigned evq_int_min, evq_int_lim;
+	unsigned evq_timer_min, evq_timer_lim;
+	unsigned rxq_min, rxq_lim;
+	unsigned txq_min, txq_lim;
+};
+
+/*! Initialise resources */
+extern int
+efrm_resources_init(const struct vi_resource_dimensions *,
+		    int buffer_table_min, int buffer_table_lim);
+
+/*! Tear down resources */
+extern void efrm_resources_fini(void);
+
+#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h
@@ -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 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);
+
+
+/*--------------------------------------------------------------------
+ *
+ * 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 */
+extern void efrm_buffer_table_commit(void);
+
+extern void efrm_buffer_table_set(struct efhw_buffer_table_allocation *,
+				  struct efhw_nic *,
+				  unsigned i, dma_addr_t dma_addr, int owner);
+
+
+#endif /* __CI_EFRM_BUFFER_TABLE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+ * 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>
+
+
+#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))
+
+
+/*! 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;
+
+	/* 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;
+	struct workqueue_struct *workqueue;
+};
+
+struct vi_resource_nic_info {
+	struct eventq_resource_hardware evq_pages;
+	struct efhw_iopages dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT];
+};
+
+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. */
+
+	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;
+	int rx_flushing;
+	int rx_flush_outstanding;
+	int tx_flushing;
+	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 */
+
+	 struct efhw_buffer_table_allocation
+	    dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT];
+
+	struct vi_resource_nic_info nic_info;
+};
+
+#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)
+{
+	struct eventq_resource_hardware *hw;
+	hw = &virs->nic_info.evq_pages;
+	return efhw_iopages_dma_addr(&hw->iobuff) + hw->iobuff_off;
+}
+
+#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efrm/private.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efrm/private.h
@@ -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 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 *);
+
+
+/*--------------------------------------------------------------------
+ *
+ * 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);
+
+extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm);
+
+
+#endif /* __CI_EFRM_PRIVATE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h
@@ -0,0 +1,382 @@
+/****************************************************************************
+ * 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>
+
+/*--------------------------------------------------------------------
+ *
+ * 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 */
+	struct efhw_iopages 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 {
+	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;
+};
+
+/*--------------------------------------------------------------------
+ *
+ * filters
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_filter_spec {
+	uint dmaq_id;
+	uint32_t saddr_le32;
+	uint32_t daddr_le32;
+	uint16_t sport_le16;
+	uint16_t dport_le16;
+	unsigned tcp     : 1;
+	unsigned full    : 1;
+	unsigned rss     : 1;  /* not supported on A1 */
+	unsigned scatter : 1;  /* not supported on A1 */
+};
+
+struct efhw_filter_depth {
+	unsigned needed;
+	unsigned max;
+};
+
+struct efhw_filter_search_limits {
+	unsigned tcp_full;
+	unsigned tcp_wild;
+	unsigned udp_full;
+	unsigned udp_wild;
+};
+
+
+/**********************************************************************
+ * 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, int non_irq_evq);
+
+  /*-------------- 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 the interrupt */
+	void (*interrupt_enable) (struct efhw_nic *nic);
+
+	/*! Disable the interrupt */
+	void (*interrupt_disable) (struct efhw_nic *nic);
+
+	/*! Set interrupt moderation strategy for the given IRQ unit
+	 ** val is in usec
+	 */
+	void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq,
+					 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,
+				    int interrupting);
+
+	/*! 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);
+
+  /*-------------- IP Filter API  ------------ */
+
+	/*! 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);
+
+	/*! 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);
+
+  /*-------------- New filter API ------------ */
+
+	/*! Set a given filter */
+	int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec,
+			   int *filter_idx_out);
+
+	/*! Clear a given filter */
+	void (*filter_clear) (struct efhw_nic *nic, int filter_idx);
+};
+
+
+/*----------------------------------------------------------------------------
+ *
+ * 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_tablep->nic array */
+	int index;
+	int ifindex;		/*!< OS level nic index */
+	struct net *nd_net;
+
+	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
+
+	unsigned mtu;		/*!< MAC MTU (includes MAC hdr) */
+
+	/* hardware resources */
+
+	/*! I/O address of the start of the bar */
+	volatile char __iomem *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;
+
+	/*! 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 interrupting_evq;
+
+/* 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 for the interrupting event queue  */
+	unsigned int irq_unit;
+
+	struct efhw_keventq non_interrupting_evq;
+
+	struct efhw_iopage 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. */
+	unsigned ip_filter_tbl_size;
+
+	/* Number of filters currently used */
+	unsigned ip_filter_tbl_used;
+
+	/* Dynamically allocated filter state. */
+	uint8_t *filter_in_use;
+	struct efhw_filter_spec *filter_spec_cache;
+
+	/* Currently required and maximum filter table search depths. */
+	struct efhw_filter_depth tcp_full_srch;
+	struct efhw_filter_depth tcp_wild_srch;
+	struct efhw_filter_depth udp_full_srch;
+	struct efhw_filter_depth udp_wild_srch;
+
+	/* Number of event queues, DMA queues and timers. */
+	unsigned num_evqs;
+	unsigned num_dmaqs;
+	unsigned num_timers;
+};
+
+
+#define EFHW_KVA(nic)       ((nic)->bar_ioaddr)
+
+
+#endif /* __CI_EFHW_EFHW_TYPES_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/common.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/common.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * 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,
+};
+
+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;
+} 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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+ * 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 */
+/* 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
+
+#define EFHW_EVENT_OVERFLOW(evq, s)			\
+	(EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1)))
+
+#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * 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/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/if_ether.h>
+
+#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
+#include <linux/etherdevice.h>
+
+typedef unsigned long irq_flags_t;
+
+#define spin_lock_destroy(l_)  do {} while (0)
+
+#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h
@@ -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 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 <linux/io.h>
+
+#if defined(__LITTLE_ENDIAN)
+#define EFHW_IS_LITTLE_ENDIAN
+#elif defined(__BIG_ENDIAN)
+#define EFHW_IS_BIG_ENDIAN
+#else
+#error Unknown endianness
+#endif
+
+#ifndef readq
+static inline uint64_t __readq(volatile void __iomem *addr)
+{
+	return *(volatile uint64_t *)addr;
+}
+#define readq(x) __readq(x)
+#endif
+
+#ifndef writeq
+static inline void __writeq(uint64_t v, volatile void __iomem *addr)
+{
+	*(volatile uint64_t *)addr = v;
+}
+#define writeq(val, addr) __writeq((val), (addr))
+#endif
+
+#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h
@@ -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__
+
+extern unsigned int
+falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
+		       unsigned int dest_ip, unsigned int dest_port,
+		       int tcp, int full);
+
+extern unsigned int
+falcon_hash_function1(unsigned int key, unsigned int nfilters);
+
+extern unsigned int
+falcon_hash_function2(unsigned int key, unsigned int nfilters);
+
+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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/public.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/public.h
@@ -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 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);
+
+/*! Get RX filter search limits from RX_FILTER_CTL_REG.
+ *  use_raw_values = 0 to get actual depth of search, or 1 to get raw values
+ *  from register.
+ */
+extern void
+falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values);
+
+/*! Set RX filter search limits in RX_FILTER_CTL_REG.
+ *  use_raw_values = 0 if specifying actual depth of search, or 1 if specifying
+ *  raw values to write to the register.
+ */
+extern void
+falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
+				       struct efhw_filter_search_limits *lim,
+				       int use_raw_values);
+
+
+/*! Legacy RX IP filter search depth control interface */
+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);
+
+/*! Legacy RX IP filter search depth control interface */
+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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h
@@ -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 *, struct efhw_iopage *p);
+extern void efhw_iopage_free(struct efhw_nic *, struct efhw_iopage *p);
+
+extern int efhw_iopages_alloc(struct efhw_nic *, struct efhw_iopages *p,
+			      unsigned order);
+extern void efhw_iopages_free(struct efhw_nic *, struct efhw_iopages *p);
+
+#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/debug.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/debug.h
@@ -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 __func__ 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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ * 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>
+
+/* 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
+
+#endif /* __CI_EFHW_COMMON_LINUX_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * 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, unsigned);
+	void (*timeout_fn)(struct efhw_nic *nic, unsigned);
+	void (*dmaq_flushed_fn) (struct efhw_nic *, unsigned, 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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+ * Driver for Solarflare network controllers -
+ *          resource management for Xen backend, OpenOnload, etc
+ *           (including support for SFE4001 10GBT NIC)
+ *
+ * This file provides struct efhw_page and struct efhw_iopage 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 <linux/errno.h>
+#include <ci/efhw/debug.h>
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_page: A single page of memory.  Directly mapped in the
+ * driver, and can be mapped to userlevel.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_page {
+	unsigned long kva;
+};
+
+static inline int efhw_page_alloc(struct efhw_page *p)
+{
+	p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+	return p->kva ? 0 : -ENOMEM;
+}
+
+static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
+{
+	p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+	return p->kva ? 0 : -ENOMEM;
+}
+
+static inline void efhw_page_free(struct efhw_page *p)
+{
+	free_page(p->kva);
+	EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
+}
+
+static inline char *efhw_page_ptr(struct efhw_page *p)
+{
+	return (char *)p->kva;
+}
+
+static inline unsigned efhw_page_pfn(struct efhw_page *p)
+{
+	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
+}
+
+static inline void efhw_page_mark_invalid(struct efhw_page *p)
+{
+	p->kva = 0;
+}
+
+static inline int efhw_page_is_valid(struct efhw_page *p)
+{
+	return p->kva != 0;
+}
+
+static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
+{
+	p->kva = (unsigned long)va;
+}
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_iopage: A single page of memory.  Directly mapped in the driver,
+ * and can be mapped to userlevel.  Can also be accessed by the NIC.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_iopage {
+	struct efhw_page p;
+	dma_addr_t dma_addr;
+};
+
+static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *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)
+
+/*--------------------------------------------------------------------
+ *
+ * struct efhw_iopages: 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.
+ *
+ *--------------------------------------------------------------------*/
+
+struct efhw_iopages {
+	caddr_t kva;
+	unsigned order;
+	dma_addr_t dma_addr;
+};
+
+static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
+{
+	return p->kva;
+}
+
+static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
+{
+	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
+}
+
+static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
+{
+	return p->dma_addr;
+}
+
+static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
+{
+	return 1u << (p->order + PAGE_SHIFT);
+}
+
+/* struct efhw_iopage <-> struct efhw_iopages 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 struct efhw_iopage 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(struct efhw_iopage *iopage,
+			      struct efhw_iopages *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(struct efhw_iopages *iopages,
+			      struct efhw_iopage *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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h
@@ -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 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);
+
+/*! configure the pace engine */
+extern void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base,
+				int bin_thresh);
+
+/*! 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);
+
+/*! 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 int falcon_nic_filter_ctor(struct efhw_nic *nic);
+
+extern void falcon_nic_filter_dtor(struct efhw_nic *nic);
+
+#endif /* __CI_EFHW_FALCON_H__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/checks.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/checks.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/net/sfc/sfc_resource/ci/efhw/nic.h
+++ linux-ec2-2.6.32/drivers/net/sfc/sfc_resource/ci/efhw/nic.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/drivers/net/ixgbe/ixgbe_82599.c
+++ linux-ec2-2.6.32/drivers/net/ixgbe/ixgbe_82599.c
@@ -332,11 +332,13 @@
 	case IXGBE_DEV_ID_82599_KX4:
 	case IXGBE_DEV_ID_82599_KX4_MEZZ:
 	case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
+	case IXGBE_DEV_ID_82599_KR:
 	case IXGBE_DEV_ID_82599_XAUI_LOM:
 		/* Default device ID is mezzanine card KX/KX4 */
 		media_type = ixgbe_media_type_backplane;
 		break;
 	case IXGBE_DEV_ID_82599_SFP:
+	case IXGBE_DEV_ID_82599_SFP_EM:
 		media_type = ixgbe_media_type_fiber;
 		break;
 	case IXGBE_DEV_ID_82599_CX4:
--- linux-ec2-2.6.32.orig/drivers/net/ixgbe/ixgbe_main.c
+++ linux-ec2-2.6.32/drivers/net/ixgbe/ixgbe_main.c
@@ -96,8 +96,12 @@
 	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM),
 	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR),
+	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
 	 board_82599 },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM),
+	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ),
 	 board_82599 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
@@ -789,6 +793,7 @@
 			break;
 		(*work_done)++;
 
+		rmb(); /* read descriptor and rx_buffer_info after status DD */
 		if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 			hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
 			len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
@@ -2129,6 +2134,10 @@
 	/* Decide whether to use packet split mode or not */
 	adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
 
+	/* Disable packet split due to 82599 erratum #45 */
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
+
 	/* Set the RX buffer length according to the mode */
 	if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
 		rx_buf_len = IXGBE_RX_HDR_SIZE;
@@ -5239,9 +5248,13 @@
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int txq = smp_processor_id();
 
-	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
-		return smp_processor_id();
+	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
+		while (unlikely(txq >= dev->real_num_tx_queues))
+			txq -= dev->real_num_tx_queues;
+		return txq;
+	}
 
 	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 		return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13;
--- linux-ec2-2.6.32.orig/drivers/net/ixgbe/ixgbe_type.h
+++ linux-ec2-2.6.32/drivers/net/ixgbe/ixgbe_type.h
@@ -50,8 +50,10 @@
 #define IXGBE_DEV_ID_82598EB_XF_LR       0x10F4
 #define IXGBE_DEV_ID_82599_KX4           0x10F7
 #define IXGBE_DEV_ID_82599_KX4_MEZZ      0x1514
+#define IXGBE_DEV_ID_82599_KR            0x1517
 #define IXGBE_DEV_ID_82599_CX4           0x10F9
 #define IXGBE_DEV_ID_82599_SFP           0x10FB
+#define IXGBE_DEV_ID_82599_SFP_EM        0x1507
 #define IXGBE_DEV_ID_82599_XAUI_LOM      0x10FC
 #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
 
--- linux-ec2-2.6.32.orig/drivers/net/atlx/atl1.c
+++ linux-ec2-2.6.32/drivers/net/atlx/atl1.c
@@ -2856,10 +2856,11 @@
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	atl1_reset_hw(&adapter->hw);
-	adapter->cmb.cmb->int_stats = 0;
 
-	if (netif_running(netdev))
+	if (netif_running(netdev)) {
+		adapter->cmb.cmb->int_stats = 0;
 		atl1_up(adapter);
+	}
 	netif_device_attach(netdev);
 
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/net/pcmcia/pcnet_cs.c
+++ linux-ec2-2.6.32/drivers/net/pcmcia/pcnet_cs.c
@@ -1768,6 +1768,13 @@
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
+MODULE_FIRMWARE("cis/PCMLM28.cis");
+MODULE_FIRMWARE("cis/DP83903.cis");
+MODULE_FIRMWARE("cis/LA-PCM.cis");
+MODULE_FIRMWARE("PE520.cis");
+MODULE_FIRMWARE("cis/NE2K.cis");
+MODULE_FIRMWARE("cis/PE-200.cis");
+MODULE_FIRMWARE("cis/tamarack.cis");
 
 static struct pcmcia_driver pcnet_driver = {
 	.drv		= {
--- linux-ec2-2.6.32.orig/drivers/net/cxgb3/common.h
+++ linux-ec2-2.6.32/drivers/net/cxgb3/common.h
@@ -125,11 +125,9 @@
 	IRQ_NUM_STATS		/* keep last */
 };
 
-enum {
-	TP_VERSION_MAJOR	= 1,
-	TP_VERSION_MINOR	= 1,
-	TP_VERSION_MICRO	= 0
-};
+#define TP_VERSION_MAJOR	1
+#define TP_VERSION_MINOR	1
+#define TP_VERSION_MICRO	0
 
 #define S_TP_VERSION_MAJOR		16
 #define M_TP_VERSION_MAJOR		0xFF
--- linux-ec2-2.6.32.orig/drivers/net/cxgb3/ael1002.c
+++ linux-ec2-2.6.32/drivers/net/cxgb3/ael1002.c
@@ -934,7 +934,7 @@
 int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
 			    int phy_addr, const struct mdio_ops *mdio_ops)
 {
-	cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
+	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
 		  "10GBASE-CX4");
 	return 0;
--- linux-ec2-2.6.32.orig/drivers/net/cxgb3/cxgb3_main.c
+++ linux-ec2-2.6.32/drivers/net/cxgb3/cxgb3_main.c
@@ -44,6 +44,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/firmware.h>
 #include <linux/log2.h>
+#include <linux/stringify.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -989,11 +990,21 @@
 	return err;
 }
 
-#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin"
-#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin"
+#define FW_VERSION __stringify(FW_VERSION_MAJOR) "."			\
+	__stringify(FW_VERSION_MINOR) "." __stringify(FW_VERSION_MICRO)
+#define FW_FNAME "cxgb3/t3fw-" FW_VERSION ".bin"
+#define TPSRAM_VERSION __stringify(TP_VERSION_MAJOR) "."		\
+	__stringify(TP_VERSION_MINOR) "." __stringify(TP_VERSION_MICRO)
+#define TPSRAM_NAME "cxgb3/t3%c_psram-" TPSRAM_VERSION ".bin"
 #define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin"
 #define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin"
 #define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin"
+MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE("cxgb3/t3b_psram-" TPSRAM_VERSION ".bin");
+MODULE_FIRMWARE("cxgb3/t3c_psram-" TPSRAM_VERSION ".bin");
+MODULE_FIRMWARE(AEL2005_OPT_EDC_NAME);
+MODULE_FIRMWARE(AEL2005_TWX_EDC_NAME);
+MODULE_FIRMWARE(AEL2020_TWX_EDC_NAME);
 
 static inline const char *get_edc_fw_name(int edc_idx)
 {
@@ -1064,16 +1075,13 @@
 static int upgrade_fw(struct adapter *adap)
 {
 	int ret;
-	char buf[64];
 	const struct firmware *fw;
 	struct device *dev = &adap->pdev->dev;
 
-	snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
-		 FW_VERSION_MINOR, FW_VERSION_MICRO);
-	ret = request_firmware(&fw, buf, dev);
+	ret = request_firmware(&fw, FW_FNAME, dev);
 	if (ret < 0) {
 		dev_err(dev, "could not upgrade firmware: unable to load %s\n",
-			buf);
+			FW_FNAME);
 		return ret;
 	}
 	ret = t3_load_fw(adap, fw->data, fw->size);
@@ -1117,8 +1125,7 @@
 	if (!rev)
 		return 0;
 
-	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
-		 TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
 
 	ret = request_firmware(&tpsram, buf, dev);
 	if (ret < 0) {
@@ -1274,6 +1281,7 @@
 
 	free_irq_resources(adapter);
 	quiesce_rx(adapter);
+	t3_sge_stop(adapter);
 	flush_workqueue(cxgb3_wq);	/* wait for external IRQ handler */
 }
 
@@ -2274,6 +2282,8 @@
 	case CHELSIO_GET_QSET_NUM:{
 		struct ch_reg edata;
 
+		memset(&edata, 0, sizeof(struct ch_reg));
+
 		edata.cmd = CHELSIO_GET_QSET_NUM;
 		edata.val = pi->nqsets;
 		if (copy_to_user(useraddr, &edata, sizeof(edata)))
--- linux-ec2-2.6.32.orig/drivers/net/tulip/Kconfig
+++ linux-ec2-2.6.32/drivers/net/tulip/Kconfig
@@ -101,6 +101,10 @@
 
 	  If in doubt, say Y.
 
+config TULIP_DM910X
+	def_bool y
+	depends on TULIP && SPARC
+
 config DE4X5
 	tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
 	depends on PCI || EISA
--- linux-ec2-2.6.32.orig/drivers/net/tulip/tulip_core.c
+++ linux-ec2-2.6.32/drivers/net/tulip/tulip_core.c
@@ -196,9 +196,13 @@
 	| HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task },
 
   /* DM910X */
+#ifdef CONFIG_TULIP_DM910X
   { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
 	tulip_timer, tulip_media_task },
+#else
+  { NULL },
+#endif
 
   /* RS7112 */
   { "Conexant LANfinity", 256, 0x0001ebef,
@@ -228,8 +232,10 @@
 	{ 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
 	{ 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
+#ifdef CONFIG_TULIP_DM910X
 	{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
 	{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
+#endif
 	{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
 	{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
@@ -243,6 +249,7 @@
 	{ 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */
 	{ 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */
+	{ 0x1414, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Microsoft MN-120 */
 	{ 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ } /* terminate list */
 };
@@ -1299,18 +1306,30 @@
 	}
 
 	/*
-	 *	Early DM9100's need software CRC and the DMFE driver
+	 *	DM910x chips should be handled by the dmfe driver, except
+	 *	on-board chips on SPARC systems.  Also, early DM9100s need
+	 *	software CRC which only the dmfe driver supports.
 	 */
 
-	if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
-	{
-		/* Read Chip revision */
-		if (pdev->revision < 0x30)
-		{
-			printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n");
+#ifdef CONFIG_TULIP_DM910X
+	if (chip_idx == DM910X) {
+		struct device_node *dp;
+
+		if (pdev->vendor == 0x1282 && pdev->device == 0x9100 &&
+		    pdev->revision < 0x30) {
+			printk(KERN_INFO PFX
+			       "skipping early DM9100 with Crc bug (use dmfe)\n");
+			return -ENODEV;
+		}
+
+		dp = pci_device_to_OF_node(pdev);
+		if (!(dp && of_get_property(dp, "local-mac-address", NULL))) {
+			printk(KERN_INFO PFX
+			       "skipping DM910x expansion card (use dmfe)\n");
 			return -ENODEV;
 		}
 	}
+#endif
 
 	/*
 	 *	Looks for early PCI chipsets where people report hangs
--- linux-ec2-2.6.32.orig/drivers/net/tulip/dmfe.c
+++ linux-ec2-2.6.32/drivers/net/tulip/dmfe.c
@@ -92,6 +92,10 @@
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_TULIP_DM910X
+#include <linux/of.h>
+#endif
+
 
 /* Board/System/Debug information/definition ---------------- */
 #define PCI_DM9132_ID   0x91321282      /* Davicom DM9132 ID */
@@ -377,6 +381,23 @@
 	if (!printed_version++)
 		printk(version);
 
+	/*
+	 *	SPARC on-board DM910x chips should be handled by the main
+	 *	tulip driver, except for early DM9100s.
+	 */
+#ifdef CONFIG_TULIP_DM910X
+	if ((ent->driver_data == PCI_DM9100_ID && pdev->revision >= 0x30) ||
+	    ent->driver_data == PCI_DM9102_ID) {
+		struct device_node *dp = pci_device_to_OF_node(pdev);
+
+		if (dp && of_get_property(dp, "local-mac-address", NULL)) {
+			printk(KERN_INFO DRV_NAME
+			       ": skipping on-board DM910x (use tulip)\n");
+			return -ENODEV;
+		}
+	}
+#endif
+
 	/* Init network device */
 	dev = alloc_etherdev(sizeof(*db));
 	if (dev == NULL)
--- linux-ec2-2.6.32.orig/drivers/net/mlx4/icm.c
+++ linux-ec2-2.6.32/drivers/net/mlx4/icm.c
@@ -174,9 +174,10 @@
 
 				if (chunk->nsg <= 0)
 					goto fail;
+			}
 
+			if (chunk->npages == MLX4_ICM_CHUNK_LEN)
 				chunk = NULL;
-			}
 
 			npages -= 1 << cur_order;
 		} else {
--- linux-ec2-2.6.32.orig/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ linux-ec2-2.6.32/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -288,6 +288,9 @@
 		/* toggle the LRO feature*/
 		netdev->features ^= NETIF_F_LRO;
 
+		/* Update private LRO flag */
+		adapter->lro = lro_requested;
+
 		/* update harware LRO capability accordingly */
 		if (lro_requested)
 			adapter->shared->devRead.misc.uptFeatures &= UPT1_F_LRO;
--- linux-ec2-2.6.32.orig/drivers/net/e1000/e1000_main.c
+++ linux-ec2-2.6.32/drivers/net/e1000/e1000_main.c
@@ -790,6 +790,70 @@
 };
 
 /**
+ * e1000_init_hw_struct - initialize members of hw struct
+ * @adapter: board private struct
+ * @hw: structure used by e1000_hw.c
+ *
+ * Factors out initialization of the e1000_hw struct to its own function
+ * that can be called very early at init (just after struct allocation).
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ * Returns negative error codes if MAC type setup fails.
+ */
+static int e1000_init_hw_struct(struct e1000_adapter *adapter,
+				struct e1000_hw *hw)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* PCI config space info */
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id = pdev->revision;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+	hw->max_frame_size = adapter->netdev->mtu +
+			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+	/* identify the MAC */
+	if (e1000_set_mac_type(hw)) {
+		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
+		return -EIO;
+	}
+
+	switch (hw->mac_type) {
+	default:
+		break;
+	case e1000_82541:
+	case e1000_82547:
+	case e1000_82541_rev_2:
+	case e1000_82547_rev_2:
+		hw->phy_init_script = 1;
+		break;
+	}
+
+	e1000_set_media_type(hw);
+	e1000_get_bus_info(hw);
+
+	hw->wait_autoneg_complete = false;
+	hw->tbi_compatibility_en = true;
+	hw->adaptive_ifs = true;
+
+	/* Copper options */
+
+	if (hw->media_type == e1000_media_type_copper) {
+		hw->mdix = AUTO_ALL_MODES;
+		hw->disable_polarity_correction = false;
+		hw->master_slave = E1000_MASTER_SLAVE;
+	}
+
+	return 0;
+}
+
+/**
  * e1000_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in e1000_pci_tbl
@@ -826,22 +890,6 @@
 	if (err)
 		return err;
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
-	    !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		pci_using_dac = 1;
-	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-		if (err) {
-			err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-			if (err) {
-				E1000_ERR("No usable DMA configuration, "
-					  "aborting\n");
-				goto err_dma;
-			}
-		}
-		pci_using_dac = 0;
-	}
-
 	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
 	if (err)
 		goto err_pci_reg;
@@ -882,6 +930,32 @@
 		}
 	}
 
+	/* make ready for any if (hw->...) below */
+	err = e1000_init_hw_struct(adapter, hw);
+	if (err)
+		goto err_sw_init;
+
+	/*
+	 * there is a workaround being applied below that limits
+	 * 64-bit DMA addresses to 64-bit hardware.  There are some
+	 * 32-bit adapters that Tx hang when given 64-bit DMA addresses
+	 */
+	pci_using_dac = 0;
+	if ((hw->bus_type == e1000_bus_type_pcix) &&
+	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		/*
+		 * according to DMA-API-HOWTO, coherent calls will always
+		 * succeed if the set call did
+		 */
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+		pci_using_dac = 1;
+	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	} else {
+		E1000_ERR("No usable DMA configuration, aborting\n");
+		goto err_dma;
+	}
+
 	netdev->netdev_ops = &e1000_netdev_ops;
 	e1000_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
@@ -956,8 +1030,6 @@
 	if (!is_valid_ether_addr(netdev->perm_addr))
 		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 
-	e1000_get_bus_info(hw);
-
 	init_timer(&adapter->tx_fifo_stall_timer);
 	adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
 	adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
@@ -1070,6 +1142,7 @@
 		iounmap(hw->flash_address);
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
+err_dma:
 err_sw_init:
 	iounmap(hw->hw_addr);
 err_ioremap:
@@ -1077,7 +1150,6 @@
 err_alloc_etherdev:
 	pci_release_selected_regions(pdev, bars);
 err_pci_reg:
-err_dma:
 	pci_disable_device(pdev);
 	return err;
 }
@@ -1129,62 +1201,12 @@
  * @adapter: board private structure to initialize
  *
  * e1000_sw_init initializes the Adapter private data structure.
- * Fields are initialized based on PCI device information and
- * OS network device settings (MTU size).
+ * e1000_init_hw_struct MUST be called before this function
  **/
 
 static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
 {
-	struct e1000_hw *hw = &adapter->hw;
-	struct net_device *netdev = adapter->netdev;
-	struct pci_dev *pdev = adapter->pdev;
-
-	/* PCI config space info */
-
-	hw->vendor_id = pdev->vendor;
-	hw->device_id = pdev->device;
-	hw->subsystem_vendor_id = pdev->subsystem_vendor;
-	hw->subsystem_id = pdev->subsystem_device;
-	hw->revision_id = pdev->revision;
-
-	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
-
 	adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-	hw->max_frame_size = netdev->mtu +
-			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
-	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
-
-	/* identify the MAC */
-
-	if (e1000_set_mac_type(hw)) {
-		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
-		return -EIO;
-	}
-
-	switch (hw->mac_type) {
-	default:
-		break;
-	case e1000_82541:
-	case e1000_82547:
-	case e1000_82541_rev_2:
-	case e1000_82547_rev_2:
-		hw->phy_init_script = 1;
-		break;
-	}
-
-	e1000_set_media_type(hw);
-
-	hw->wait_autoneg_complete = false;
-	hw->tbi_compatibility_en = true;
-	hw->adaptive_ifs = true;
-
-	/* Copper options */
-
-	if (hw->media_type == e1000_media_type_copper) {
-		hw->mdix = AUTO_ALL_MODES;
-		hw->disable_polarity_correction = false;
-		hw->master_slave = E1000_MASTER_SLAVE;
-	}
 
 	adapter->num_tx_queues = 1;
 	adapter->num_rx_queues = 1;
@@ -1698,18 +1720,6 @@
 	rctl &= ~E1000_RCTL_SZ_4096;
 	rctl |= E1000_RCTL_BSEX;
 	switch (adapter->rx_buffer_len) {
-		case E1000_RXBUFFER_256:
-			rctl |= E1000_RCTL_SZ_256;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_512:
-			rctl |= E1000_RCTL_SZ_512;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
-		case E1000_RXBUFFER_1024:
-			rctl |= E1000_RCTL_SZ_1024;
-			rctl &= ~E1000_RCTL_BSEX;
-			break;
 		case E1000_RXBUFFER_2048:
 		default:
 			rctl |= E1000_RCTL_SZ_2048;
@@ -3154,13 +3164,7 @@
 	 *  however with the new *_jumbo_rx* routines, jumbo receives will use
 	 *  fragmented skbs */
 
-	if (max_frame <= E1000_RXBUFFER_256)
-		adapter->rx_buffer_len = E1000_RXBUFFER_256;
-	else if (max_frame <= E1000_RXBUFFER_512)
-		adapter->rx_buffer_len = E1000_RXBUFFER_512;
-	else if (max_frame <= E1000_RXBUFFER_1024)
-		adapter->rx_buffer_len = E1000_RXBUFFER_1024;
-	else if (max_frame <= E1000_RXBUFFER_2048)
+	if (max_frame <= E1000_RXBUFFER_2048)
 		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
 	else
 #if (PAGE_SIZE >= E1000_RXBUFFER_16384)
@@ -3827,13 +3831,22 @@
 
 		length = le16_to_cpu(rx_desc->length);
 		/* !EOP means multiple descriptors were used to store a single
-		 * packet, also make sure the frame isn't just CRC only */
-		if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
+		 * packet, if thats the case we need to toss it.  In fact, we
+		 * to toss every packet with the EOP bit clear and the next
+		 * frame that _does_ have the EOP bit set, as it is by
+		 * definition only a frame fragment
+		 */
+		if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+			adapter->discarding = true;
+
+		if (adapter->discarding) {
 			/* All receives must fit into a single buffer */
 			E1000_DBG("%s: Receive packet consumed multiple"
 				  " buffers\n", netdev->name);
 			/* recycle */
 			buffer_info->skb = skb;
+			if (status & E1000_RXD_STAT_EOP)
+				adapter->discarding = false;
 			goto next_desc;
 		}
 
--- linux-ec2-2.6.32.orig/drivers/net/e1000/e1000.h
+++ linux-ec2-2.6.32/drivers/net/e1000/e1000.h
@@ -326,6 +326,8 @@
 	/* for ioport free */
 	int bars;
 	int need_ioport;
+
+	bool discarding;
 };
 
 enum e1000_state_t {
--- linux-ec2-2.6.32.orig/drivers/net/myri10ge/myri10ge.c
+++ linux-ec2-2.6.32/drivers/net/myri10ge/myri10ge.c
@@ -264,6 +264,10 @@
 static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
 static char *myri10ge_fw_rss_unaligned = "myri10ge_rss_ethp_z8e.dat";
 static char *myri10ge_fw_rss_aligned = "myri10ge_rss_eth_z8e.dat";
+MODULE_FIRMWARE("myri10ge_ethp_z8e.dat");
+MODULE_FIRMWARE("myri10ge_eth_z8e.dat");
+MODULE_FIRMWARE("myri10ge_rss_ethp_z8e.dat");
+MODULE_FIRMWARE("myri10ge_rss_eth_z8e.dat");
 
 static char *myri10ge_fw_name = NULL;
 module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
@@ -3640,6 +3644,7 @@
 			dma_free_coherent(&pdev->dev, bytes,
 					  ss->fw_stats, ss->fw_stats_bus);
 			ss->fw_stats = NULL;
+			netif_napi_del(&ss->napi);
 		}
 	}
 	kfree(mgp->ss);
--- linux-ec2-2.6.32.orig/drivers/net/igbvf/igbvf.h
+++ linux-ec2-2.6.32/drivers/net/igbvf/igbvf.h
@@ -125,7 +125,6 @@
 			unsigned int page_offset;
 		};
 	};
-	struct page *page;
 };
 
 union igbvf_desc {
--- linux-ec2-2.6.32.orig/drivers/net/netxen/netxen_nic_main.c
+++ linux-ec2-2.6.32/drivers/net/netxen/netxen_nic_main.c
@@ -38,6 +38,9 @@
 MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
+MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME);
+MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME);
+MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME);
 
 char netxen_nic_driver_name[] = "netxen_nic";
 static char netxen_nic_driver_string[] = "NetXen Network Driver version "
--- linux-ec2-2.6.32.orig/drivers/net/netxen/netxen_nic.h
+++ linux-ec2-2.6.32/drivers/net/netxen/netxen_nic.h
@@ -487,6 +487,11 @@
 #define NX_P3_MN_ROMIMAGE	2
 #define NX_FLASH_ROMIMAGE	3
 
+#define NX_P2_MN_ROMIMAGE_NAME		"nxromimg.bin"
+#define NX_P3_CT_ROMIMAGE_NAME		"nx3fwct.bin"
+#define NX_P3_MN_ROMIMAGE_NAME		"nx3fwmn.bin"
+#define NX_FLASH_ROMIMAGE_NAME		"flash"
+
 extern char netxen_nic_driver_name[];
 
 /* Number of status descriptors to handle per interrupt */
--- linux-ec2-2.6.32.orig/drivers/net/netxen/netxen_nic_init.c
+++ linux-ec2-2.6.32/drivers/net/netxen/netxen_nic_init.c
@@ -673,7 +673,10 @@
 }
 
 static char *fw_name[] = {
-	"nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
+	NX_P2_MN_ROMIMAGE_NAME,
+	NX_P3_CT_ROMIMAGE_NAME,
+	NX_P3_MN_ROMIMAGE_NAME,
+	NX_FLASH_ROMIMAGE_NAME,
 };
 
 int
@@ -1199,7 +1202,6 @@
 	if (pkt_offset)
 		skb_pull(skb, pkt_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff);
 	skb->protocol = eth_type_trans(skb, netdev);
 
 	napi_gro_receive(&sds_ring->napi, skb);
@@ -1261,8 +1263,6 @@
 
 	skb_put(skb, lro_length + data_offset);
 
-	skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb);
-
 	skb_pull(skb, l2_hdr_offset);
 	skb->protocol = eth_type_trans(skb, netdev);
 
--- linux-ec2-2.6.32.orig/drivers/net/netxen/netxen_nic_hw.c
+++ linux-ec2-2.6.32/drivers/net/netxen/netxen_nic_hw.c
@@ -685,6 +685,9 @@
 	struct list_head *head;
 	nx_mac_list_t *cur;
 
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+		return;
+
 	list_splice_tail_init(&adapter->mac_list, &del_list);
 
 	nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rndis_wlan.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rndis_wlan.c
@@ -83,11 +83,11 @@
 	"set roaming tendency: 0=aggressive, 1=moderate, "
 				"2=conservative (default: moderate)");
 
-static int modparam_workaround_interval = 500;
+static int modparam_workaround_interval;
 module_param_named(workaround_interval, modparam_workaround_interval,
 							int, 0444);
 MODULE_PARM_DESC(workaround_interval,
-	"set stall workaround interval in msecs (default: 500)");
+	"set stall workaround interval in msecs (0=disabled) (default: 0)");
 
 
 /* various RNDIS OID defs */
@@ -733,12 +733,13 @@
 			le32_to_cpu(u.get_c->status));
 
 	if (ret == 0) {
+		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
+
 		ret = le32_to_cpu(u.get_c->len);
 		if (ret > *len)
 			*len = ret;
-		memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
-		ret = rndis_error_status(u.get_c->status);
 
+		ret = rndis_error_status(u.get_c->status);
 		if (ret < 0)
 			devdbg(dev, "rndis_query_oid(%s): device returned "
 				"error,  0x%08x (%d)", oid_to_string(oid),
@@ -1072,6 +1073,8 @@
 		auth_mode = NDIS_80211_AUTH_SHARED;
 	else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
 		auth_mode = NDIS_80211_AUTH_OPEN;
+	else if (auth_type == NL80211_AUTHTYPE_AUTOMATIC)
+		auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
 	else
 		return -ENOTSUPP;
 
@@ -2547,7 +2550,7 @@
 	/* Workaround transfer stalls on poor quality links.
 	 * TODO: find right way to fix these stalls (as stalls do not happen
 	 * with ndiswrapper/windows driver). */
-	if (priv->last_qual <= 25) {
+	if (priv->param_workaround_interval > 0 && priv->last_qual <= 25) {
 		/* Decrease stats worker interval to catch stalls.
 		 * faster. Faster than 400-500ms causes packet loss,
 		 * Slower doesn't catch stalls fast enough.
--- linux-ec2-2.6.32.orig/drivers/net/wireless/airo.c
+++ linux-ec2-2.6.32/drivers/net/wireless/airo.c
@@ -5254,11 +5254,7 @@
 	WepKeyRid wkr;
 	int rc;
 
-	if (keylen == 0) {
-		airo_print_err(ai->dev->name, "%s: key length to set was zero",
-			       __func__);
-		return -1;
-	}
+	WARN_ON(keylen == 0);
 
 	memset(&wkr, 0, sizeof(wkr));
 	wkr.len = cpu_to_le16(sizeof(wkr));
@@ -6404,11 +6400,7 @@
 		if (dwrq->length > MIN_KEY_SIZE)
 			key.len = MAX_KEY_SIZE;
 		else
-			if (dwrq->length > 0)
-				key.len = MIN_KEY_SIZE;
-			else
-				/* Disable the key */
-				key.len = 0;
+			key.len = MIN_KEY_SIZE;
 		/* Check if the key is not marked as invalid */
 		if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
 			/* Cleanup */
@@ -6589,12 +6581,22 @@
 		default:
 			return -EINVAL;
 		}
-		/* Send the key to the card */
-		rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
-		if (rc < 0) {
-			airo_print_err(local->dev->name, "failed to set WEP key"
-			               " at index %d: %d.", idx, rc);
-			return rc;
+		if (key.len == 0) {
+			rc = set_wep_tx_idx(local, idx, perm, 1);
+			if (rc < 0) {
+				airo_print_err(local->dev->name,
+					       "failed to set WEP transmit index to %d: %d.",
+					       idx, rc);
+				return rc;
+			}
+		} else {
+			rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+			if (rc < 0) {
+				airo_print_err(local->dev->name,
+					       "failed to set WEP key at index %d: %d.",
+					       idx, rc);
+				return rc;
+			}
 		}
 	}
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/p54/txrx.c
+++ linux-ec2-2.6.32/drivers/net/wireless/p54/txrx.c
@@ -186,7 +186,7 @@
 	struct ieee80211_tx_queue_stats *queue;
 	unsigned long flags;
 
-	if (WARN_ON(p54_queue > P54_QUEUE_NUM))
+	if (WARN_ON(p54_queue >= P54_QUEUE_NUM))
 		return -EINVAL;
 
 	queue = &priv->tx_stats[p54_queue];
@@ -445,7 +445,7 @@
 	}
 
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-	     (!payload->status))
+	     !(payload->status & P54_TX_FAILED))
 		info->flags |= IEEE80211_TX_STAT_ACK;
 	if (payload->status & P54_TX_PSM_CANCELLED)
 		info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
@@ -617,7 +617,7 @@
 	else
 		*burst_possible = false;
 
-	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+	if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
 		*flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
 
 	if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)
@@ -703,7 +703,7 @@
 	struct p54_tx_info *p54info;
 	struct p54_hdr *hdr;
 	struct p54_tx_data *txhdr;
-	unsigned int padding, len, extra_len;
+	unsigned int padding, len, extra_len = 0;
 	int i, j, ridx;
 	u16 hdr_flags = 0, aid = 0;
 	u8 rate, queue = 0, crypt_offset = 0;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/p54/p54pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/p54/p54pci.c
@@ -40,6 +40,8 @@
 	{ PCI_DEVICE(0x1260, 0x3877) },
 	/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
 	{ PCI_DEVICE(0x1260, 0x3886) },
+	/* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+	{ PCI_DEVICE(0x1260, 0xffff) },
 	{ },
 };
 
@@ -157,6 +159,14 @@
 						 skb_tail_pointer(skb),
 						 priv->common.rx_mtu + 32,
 						 PCI_DMA_FROMDEVICE);
+
+			if (pci_dma_mapping_error(priv->pdev, mapping)) {
+				dev_kfree_skb_any(skb);
+				dev_err(&priv->pdev->dev,
+					"RX DMA Mapping error\n");
+				break;
+			}
+
 			desc->host_addr = cpu_to_le32(mapping);
 			desc->device_addr = 0;	// FIXME: necessary?
 			desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
@@ -188,6 +198,7 @@
 	while (i != idx) {
 		u16 len;
 		struct sk_buff *skb;
+		dma_addr_t dma_addr;
 		desc = &ring[i];
 		len = le16_to_cpu(desc->len);
 		skb = rx_buf[i];
@@ -197,17 +208,28 @@
 			i %= ring_limit;
 			continue;
 		}
+
+		if (unlikely(len > priv->common.rx_mtu)) {
+			if (net_ratelimit())
+				dev_err(&priv->pdev->dev, "rx'd frame size "
+					"exceeds length threshold.\n");
+
+			len = priv->common.rx_mtu;
+		}
+		dma_addr = le32_to_cpu(desc->host_addr);
+		pci_dma_sync_single_for_cpu(priv->pdev, dma_addr,
+			priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 		skb_put(skb, len);
 
 		if (p54_rx(dev, skb)) {
-			pci_unmap_single(priv->pdev,
-					 le32_to_cpu(desc->host_addr),
-					 priv->common.rx_mtu + 32,
-					 PCI_DMA_FROMDEVICE);
+			pci_unmap_single(priv->pdev, dma_addr,
+				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 			rx_buf[i] = NULL;
-			desc->host_addr = 0;
+			desc->host_addr = cpu_to_le32(0);
 		} else {
 			skb_trim(skb, 0);
+			pci_dma_sync_single_for_device(priv->pdev, dma_addr,
+				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
 			desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
 		}
 
@@ -229,7 +251,7 @@
 	u32 idx, i;
 
 	i = (*index) % ring_limit;
-	(*index) = idx = le32_to_cpu(ring_control->device_idx[1]);
+	(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
 	idx %= ring_limit;
 
 	while (i != idx) {
@@ -317,14 +339,20 @@
 	u32 device_idx, idx, i;
 
 	spin_lock_irqsave(&priv->lock, flags);
-
 	device_idx = le32_to_cpu(ring_control->device_idx[1]);
 	idx = le32_to_cpu(ring_control->host_idx[1]);
 	i = idx % ARRAY_SIZE(ring_control->tx_data);
 
-	priv->tx_buf_data[i] = skb;
 	mapping = pci_map_single(priv->pdev, skb->data, skb->len,
 				 PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(priv->pdev, mapping)) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		p54_free_skb(dev, skb);
+		dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
+		return ;
+	}
+	priv->tx_buf_data[i] = skb;
+
 	desc = &ring_control->tx_data[i];
 	desc->host_addr = cpu_to_le32(mapping);
 	desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/p54/p54usb.c
+++ linux-ec2-2.6.32/drivers/net/wireless/p54/p54usb.c
@@ -32,10 +32,21 @@
 MODULE_FIRMWARE("isl3886usb");
 MODULE_FIRMWARE("isl3887usb");
 
+/*
+ * Note:
+ *
+ * Always update our wiki's device list (located at:
+ * http://wireless.kernel.org/en/users/Drivers/p54/devices ),
+ * whenever you add a new device.
+ */
+
 static struct usb_device_id p54u_table[] __devinitdata = {
 	/* Version 1 devices (pci chip + net2280) */
+	{USB_DEVICE(0x0411, 0x0050)},	/* Buffalo WLI2-USB2-G54 */
+	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */
 	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */
 	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
+	{USB_DEVICE(0x07aa, 0x001c)},	/* Corega CG-WLUSB2GT */
 	{USB_DEVICE(0x083a, 0x4501)},	/* Accton 802.11g WN4501 USB */
 	{USB_DEVICE(0x083a, 0x4502)},	/* Siemens Gigaset USB Adapter */
 	{USB_DEVICE(0x083a, 0x5501)},	/* Phillips CPWUA054 */
@@ -43,12 +54,20 @@
 	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
 	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
 	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
+	{USB_DEVICE(0x0bf8, 0x1007)},	/* Fujitsu E-5400 USB */
 	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
+	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */
+	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */
 	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+	{USB_DEVICE(0x1435, 0x0210)},	/* Inventel UR054G */
+	{USB_DEVICE(0x15a9, 0x0002)},	/* Gemtek WUBI-100GW 802.11g */
+	{USB_DEVICE(0x1630, 0x0005)},	/* 2Wire 802.11g USB (v1) / Z-Com */
+	{USB_DEVICE(0x182d, 0x096b)},	/* Sitecom WL-107 */
 	{USB_DEVICE(0x1915, 0x2234)},	/* Linksys WUSB54G OEM */
 	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
 	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
 	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */
+	{USB_DEVICE(0x2001, 0x3762)},	/* Conceptronic C54U */
 	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */
 	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */
 
@@ -57,15 +76,17 @@
 	{USB_DEVICE(0x050d, 0x7050)},	/* Belkin F5D7050 ver 1000 */
 	{USB_DEVICE(0x0572, 0x2000)},	/* Cohiba Proto board */
 	{USB_DEVICE(0x0572, 0x2002)},	/* Cohiba Proto board */
+	{USB_DEVICE(0x06a9, 0x000e)},	/* Westell 802.11g USB (A90-211WG-01) */
 	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */
 	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
 	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
+	{USB_DEVICE(0x083a, 0xf503)},	/* Accton FD7050E ver 1010ec  */
 	{USB_DEVICE(0x0846, 0x4240)},	/* Netgear WG111 (v2) */
 	{USB_DEVICE(0x0915, 0x2000)},	/* Cohiba Proto board */
 	{USB_DEVICE(0x0915, 0x2002)},	/* Cohiba Proto board */
 	{USB_DEVICE(0x0baf, 0x0118)},   /* U.S. Robotics U5 802.11g Adapter*/
 	{USB_DEVICE(0x0bf8, 0x1009)},   /* FUJITSU E-5400 USB D1700*/
-	{USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */
+// DUPE	{USB_DEVICE(0x0cde, 0x0006)},   /* Medion MD40900 */
 	{USB_DEVICE(0x0cde, 0x0008)},	/* Sagem XG703A */
 	{USB_DEVICE(0x0cde, 0x0015)},	/* Zcomax XG-705A */
 	{USB_DEVICE(0x0d8e, 0x3762)},	/* DLink DWL-G120 Cohiba */
@@ -75,7 +96,11 @@
 	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
 	{USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
 	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
+	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */
+	{USB_DEVICE(0x1740, 0x1000)},	/* Senao NUB-350 */
 	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
+	{USB_DEVICE(0x2001, 0x3705)},	/* D-Link DWL-G120 rev C1 */
+	{USB_DEVICE(0x413c, 0x5513)},	/* Dell WLA3310 USB Wireless Adapter */
 	{USB_DEVICE(0x413c, 0x8102)},	/* Spinnaker DUT */
 	{USB_DEVICE(0x413c, 0x8104)},	/* Cohiba Proto board */
 	{}
@@ -926,8 +951,8 @@
 #ifdef CONFIG_PM
 		/* ISL3887 needs a full reset on resume */
 		udev->reset_resume = 1;
+#endif /* CONFIG_PM */
 		err = p54u_device_reset(dev);
-#endif
 
 		priv->hw_type = P54U_3887;
 		dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/p54/eeprom.c
+++ linux-ec2-2.6.32/drivers/net/wireless/p54/eeprom.c
@@ -126,7 +126,7 @@
 	int ret = -ENOMEM;
 
 	if ((!list->entries) || (!list->band_channel_num[band]))
-		return 0;
+		return -EINVAL;
 
 	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
 	if (!tmp)
@@ -158,6 +158,7 @@
 			       (list->channels[i].data & CHAN_HAS_CURVE ? "" :
 				" [curve data]"),
 			       list->channels[i].index, list->channels[i].freq);
+			continue;
 		}
 
 		tmp->channels[j].band = list->channels[i].band;
@@ -165,7 +166,16 @@
 		j++;
 	}
 
-	tmp->n_channels = list->band_channel_num[band];
+	if (j == 0) {
+		printk(KERN_ERR "%s: Disabling totally damaged %s band.\n",
+		       wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ?
+		       "2 GHz" : "5 GHz");
+
+		ret = -ENODATA;
+		goto err_out;
+	}
+
+	tmp->n_channels = j;
 	old = priv->band_table[band];
 	priv->band_table[band] = tmp;
 	if (old) {
@@ -228,13 +238,13 @@
 	struct p54_common *priv = dev->priv;
 	struct p54_channel_list *list;
 	unsigned int i, j, max_channel_num;
-	int ret = -ENOMEM;
+	int ret = 0;
 	u16 freq;
 
 	if ((priv->iq_autocal_len != priv->curve_data->entries) ||
 	    (priv->iq_autocal_len != priv->output_limit->entries))
-		printk(KERN_ERR "%s: EEPROM is damaged... you may not be able"
-				"to use all channels with this device.\n",
+		printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. "
+				"You may not be able to use all channels.\n",
 				wiphy_name(dev->wiphy));
 
 	max_channel_num = max_t(unsigned int, priv->output_limit->entries,
@@ -243,14 +253,18 @@
 				priv->curve_data->entries);
 
 	list = kzalloc(sizeof(*list), GFP_KERNEL);
-	if (!list)
+	if (!list) {
+		ret = -ENOMEM;
 		goto free;
+	}
 
 	list->max_entries = max_channel_num;
 	list->channels = kzalloc(sizeof(struct p54_channel_entry) *
 				 max_channel_num, GFP_KERNEL);
-	if (!list->channels)
+	if (!list->channels) {
+		ret = -ENOMEM;
 		goto free;
+	}
 
 	for (i = 0; i < max_channel_num; i++) {
 		if (i < priv->iq_autocal_len) {
@@ -282,13 +296,8 @@
 	     p54_compare_channels, NULL);
 
 	for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
-		if (list->band_channel_num[i]) {
-			ret = p54_generate_band(dev, list, i);
-			if (ret)
-				goto free;
-
+		if (p54_generate_band(dev, list, i) == 0)
 			j++;
-		}
 	}
 	if (j == 0) {
 		/* no useable band available. */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ipw2x00/ipw2200.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -90,7 +90,7 @@
 static u32 ipw_debug_level;
 static int associate;
 static int auto_create = 1;
-static int led_support = 0;
+static int led_support = 1;
 static int disable = 0;
 static int bt_coexist = 0;
 static int hwcrypto = 0;
@@ -11962,7 +11962,7 @@
 MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
 
 module_param_named(led, led_support, int, 0444);
-MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)");
+MODULE_PARM_DESC(led, "enable led control on some systems (default 1 on)");
 
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ipw2x00/ipw2100.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6487,6 +6487,16 @@
 }
 #endif
 
+static void ipw2100_shutdown(struct pci_dev *pci_dev)
+{
+	struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+
+	/* Take down the device; powers it off, etc. */
+	ipw2100_down(priv);
+
+	pci_disable_device(pci_dev);
+}
+
 #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
 
 static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
@@ -6550,6 +6560,7 @@
 	.suspend = ipw2100_suspend,
 	.resume = ipw2100_resume,
 #endif
+	.shutdown = ipw2100_shutdown,
 };
 
 /**
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rtl818x/rtl8187_rfkill.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rtl818x/rtl8187_rfkill.c
@@ -25,10 +25,10 @@
 	u8 gpio;
 
 	gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
-	rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02);
+	rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask);
 	gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
 
-	return gpio & 0x02;
+	return gpio & priv->rfkill_mask;
 }
 
 void rtl8187_rfkill_init(struct ieee80211_hw *hw)
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -190,6 +190,7 @@
 			info->flags |= IEEE80211_TX_STAT_ACK;
 
 		info->status.rates[0].count = (flags & 0xFF) + 1;
+		info->status.rates[1].idx = -1;
 
 		ieee80211_tx_status_irqsafe(dev, skb);
 		if (ring->entries - skb_queue_len(&ring->queue) == 2)
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rtl818x/rtl8187.h
+++ linux-ec2-2.6.32/drivers/net/wireless/rtl818x/rtl8187.h
@@ -23,6 +23,7 @@
 #define RTL8187_EEPROM_TXPWR_CHAN_1	0x16	/* 3 channels */
 #define RTL8187_EEPROM_TXPWR_CHAN_6	0x1B	/* 2 channels */
 #define RTL8187_EEPROM_TXPWR_CHAN_4	0x3D	/* 2 channels */
+#define RTL8187_EEPROM_SELECT_GPIO	0x3B
 
 #define RTL8187_REQT_READ	0xC0
 #define RTL8187_REQT_WRITE	0x40
@@ -31,6 +32,9 @@
 
 #define RTL8187_MAX_RX		0x9C4
 
+#define RFKILL_MASK_8187_89_97	0x2
+#define RFKILL_MASK_8198	0x4
+
 struct rtl8187_rx_info {
 	struct urb *urb;
 	struct ieee80211_hw *dev;
@@ -123,6 +127,7 @@
 	u8 noise;
 	u8 slot_time;
 	u8 aifsn[4];
+	u8 rfkill_mask;
 	struct {
 		__le64 buf;
 		struct sk_buff_head queue;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -65,6 +65,7 @@
 	/* Sitecom */
 	{USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187},
 	{USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B},
+	{USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B},
 	/* Sphairon Access Systems GmbH */
 	{USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187},
 	/* Dick Smith Electronics */
@@ -1329,6 +1330,7 @@
 	struct ieee80211_channel *channel;
 	const char *chip_name;
 	u16 txpwr, reg;
+	u16 product_id = le16_to_cpu(udev->descriptor.idProduct);
 	int err, i;
 
 	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
@@ -1488,6 +1490,13 @@
 		(*channel++).hw_value = txpwr & 0xFF;
 		(*channel++).hw_value = txpwr >> 8;
 	}
+	/* Handle the differing rfkill GPIO bit in different models */
+	priv->rfkill_mask = RFKILL_MASK_8187_89_97;
+	if (product_id == 0x8197 || product_id == 0x8198) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, &reg);
+		if (reg & 0xFF00)
+			priv->rfkill_mask = RFKILL_MASK_8198;
+	}
 
 	/*
 	 * XXX: Once this driver supports anything that requires
@@ -1516,9 +1525,9 @@
 	mutex_init(&priv->conf_mutex);
 	skb_queue_head_init(&priv->b_tx_status.queue);
 
-	printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
+	printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
 	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
-	       chip_name, priv->asic_rev, priv->rf->name);
+	       chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);
 
 #ifdef CONFIG_RTL8187_LEDS
 	eeprom_93cx6_read(&eeprom, 0x3F, &reg);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/orinoco/wext.c
+++ linux-ec2-2.6.32/drivers/net/wireless/orinoco/wext.c
@@ -23,7 +23,7 @@
 #define MAX_RID_LEN 1024
 
 /* Helper routine to record keys
- * Do not call from interrupt context */
+ * It is called under orinoco_lock so it may not sleep */
 static int orinoco_set_key(struct orinoco_private *priv, int index,
 			   enum orinoco_alg alg, const u8 *key, int key_len,
 			   const u8 *seq, int seq_len)
@@ -32,14 +32,14 @@
 	kzfree(priv->keys[index].seq);
 
 	if (key_len) {
-		priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
+		priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
 		if (!priv->keys[index].key)
 			goto nomem;
 	} else
 		priv->keys[index].key = NULL;
 
 	if (seq_len) {
-		priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
+		priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
 		if (!priv->keys[index].seq)
 			goto free_key;
 	} else
@@ -1022,10 +1022,10 @@
 		 */
 		if (param->value) {
 			priv->tkip_cm_active = 1;
-			ret = hermes_enable_port(hw, 0);
+			ret = hermes_disable_port(hw, 0);
 		} else {
 			priv->tkip_cm_active = 0;
-			ret = hermes_disable_port(hw, 0);
+			ret = hermes_enable_port(hw, 0);
 		}
 		break;
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/orinoco/main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/orinoco/main.c
@@ -1767,6 +1767,12 @@
 	struct net_device *dev = priv->ndev;
 	int err = 0;
 
+	/* If we've called commit, we are reconfiguring or bringing the
+	 * interface up. Maintaining countermeasures across this would
+	 * be confusing, so note that we've disabled them. The port will
+	 * be enabled later in orinoco_commit or __orinoco_up. */
+	priv->tkip_cm_active = 0;
+
 	err = orinoco_hw_program_rids(priv);
 
 	/* FIXME: what about netif_tx_lock */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/pio.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/pio.c
@@ -342,12 +342,15 @@
 			q->mmio_base + B43_PIO_TXDATA,
 			sizeof(u16));
 	if (data_len & 1) {
+		u8 *tail = wl->pio_tailspace;
+		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
+
 		/* Write the last byte. */
 		ctl &= ~B43_PIO_TXCTL_WRITEHI;
 		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-		wl->tx_tail[0] = data[data_len - 1];
-		wl->tx_tail[1] = 0;
-		ssb_block_write(dev->dev, wl->tx_tail, 2,
+		tail[0] = data[data_len - 1];
+		tail[1] = 0;
+		ssb_block_write(dev->dev, tail, 2,
 				q->mmio_base + B43_PIO_TXDATA,
 				sizeof(u16));
 	}
@@ -393,31 +396,31 @@
 			q->mmio_base + B43_PIO8_TXDATA,
 			sizeof(u32));
 	if (data_len & 3) {
-		wl->tx_tail[3] = 0;
+		u8 *tail = wl->pio_tailspace;
+		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
+
+		memset(tail, 0, 4);
 		/* Write the last few bytes. */
 		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
 			 B43_PIO8_TXCTL_24_31);
 		switch (data_len & 3) {
 		case 3:
 			ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
-			wl->tx_tail[0] = data[data_len - 3];
-			wl->tx_tail[1] = data[data_len - 2];
-			wl->tx_tail[2] = data[data_len - 1];
+			tail[0] = data[data_len - 3];
+			tail[1] = data[data_len - 2];
+			tail[2] = data[data_len - 1];
 			break;
 		case 2:
 			ctl |= B43_PIO8_TXCTL_8_15;
-			wl->tx_tail[0] = data[data_len - 2];
-			wl->tx_tail[1] = data[data_len - 1];
-			wl->tx_tail[2] = 0;
+			tail[0] = data[data_len - 2];
+			tail[1] = data[data_len - 1];
 			break;
 		case 1:
-			wl->tx_tail[0] = data[data_len - 1];
-			wl->tx_tail[1] = 0;
-			wl->tx_tail[2] = 0;
+			tail[0] = data[data_len - 1];
 			break;
 		}
 		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-		ssb_block_write(dev->dev, wl->tx_tail, 4,
+		ssb_block_write(dev->dev, tail, 4,
 				q->mmio_base + B43_PIO8_TXDATA,
 				sizeof(u32));
 	}
@@ -456,6 +459,7 @@
 	int err;
 	unsigned int hdrlen;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
 
 	B43_WARN_ON(list_empty(&q->packets_list));
 	pack = list_entry(q->packets_list.next,
@@ -463,7 +467,9 @@
 
 	cookie = generate_cookie(q, pack);
 	hdrlen = b43_txhdr_size(dev);
-	err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
+	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
+	B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
+	err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
 				 info, cookie);
 	if (err)
 		return err;
@@ -477,9 +483,9 @@
 
 	pack->skb = skb;
 	if (q->rev >= 8)
-		pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
+		pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
 	else
-		pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
+		pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
 
 	/* Remove it from the list of available packet slots.
 	 * It will be put back when we receive the status report. */
@@ -625,8 +631,11 @@
 	unsigned int i, padding;
 	struct sk_buff *skb;
 	const char *err_msg = NULL;
+	struct b43_rxhdr_fw4 *rxhdr =
+		(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
 
-	memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
+	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
+	memset(rxhdr, 0, sizeof(*rxhdr));
 
 	/* Check if we have data and wait for it to get ready. */
 	if (q->rev >= 8) {
@@ -664,16 +673,16 @@
 
 	/* Get the preamble (RX header) */
 	if (q->rev >= 8) {
-		ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
+		ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
 			       q->mmio_base + B43_PIO8_RXDATA,
 			       sizeof(u32));
 	} else {
-		ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
+		ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
 			       q->mmio_base + B43_PIO_RXDATA,
 			       sizeof(u16));
 	}
 	/* Sanity checks. */
-	len = le16_to_cpu(wl->rxhdr.frame_len);
+	len = le16_to_cpu(rxhdr->frame_len);
 	if (unlikely(len > 0x700)) {
 		err_msg = "len > 0x700";
 		goto rx_error;
@@ -683,7 +692,7 @@
 		goto rx_error;
 	}
 
-	macstat = le32_to_cpu(wl->rxhdr.mac_status);
+	macstat = le32_to_cpu(rxhdr->mac_status);
 	if (macstat & B43_RX_MAC_FCSERR) {
 		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
 			/* Drop frames with failed FCS. */
@@ -708,22 +717,25 @@
 			       q->mmio_base + B43_PIO8_RXDATA,
 			       sizeof(u32));
 		if (len & 3) {
+			u8 *tail = wl->pio_tailspace;
+			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
+
 			/* Read the last few bytes. */
-			ssb_block_read(dev->dev, wl->rx_tail, 4,
+			ssb_block_read(dev->dev, tail, 4,
 				       q->mmio_base + B43_PIO8_RXDATA,
 				       sizeof(u32));
 			switch (len & 3) {
 			case 3:
-				skb->data[len + padding - 3] = wl->rx_tail[0];
-				skb->data[len + padding - 2] = wl->rx_tail[1];
-				skb->data[len + padding - 1] = wl->rx_tail[2];
+				skb->data[len + padding - 3] = tail[0];
+				skb->data[len + padding - 2] = tail[1];
+				skb->data[len + padding - 1] = tail[2];
 				break;
 			case 2:
-				skb->data[len + padding - 2] = wl->rx_tail[0];
-				skb->data[len + padding - 1] = wl->rx_tail[1];
+				skb->data[len + padding - 2] = tail[0];
+				skb->data[len + padding - 1] = tail[1];
 				break;
 			case 1:
-				skb->data[len + padding - 1] = wl->rx_tail[0];
+				skb->data[len + padding - 1] = tail[0];
 				break;
 			}
 		}
@@ -732,15 +744,18 @@
 			       q->mmio_base + B43_PIO_RXDATA,
 			       sizeof(u16));
 		if (len & 1) {
+			u8 *tail = wl->pio_tailspace;
+			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
+
 			/* Read the last byte. */
-			ssb_block_read(dev->dev, wl->rx_tail, 2,
+			ssb_block_read(dev->dev, tail, 2,
 				       q->mmio_base + B43_PIO_RXDATA,
 				       sizeof(u16));
-			skb->data[len + padding - 1] = wl->rx_tail[0];
+			skb->data[len + padding - 1] = tail[0];
 		}
 	}
 
-	b43_rx(q->dev, skb, &wl->rxhdr);
+	b43_rx(q->dev, skb, rxhdr);
 
 	return 1;
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/sdio.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/sdio.c
@@ -162,6 +162,7 @@
 err_free_ssb:
 	kfree(sdio);
 err_disable_func:
+	sdio_claim_host(func);
 	sdio_disable_func(func);
 err_release_host:
 	sdio_release_host(func);
@@ -174,7 +175,9 @@
 	struct b43_sdio *sdio = sdio_get_drvdata(func);
 
 	ssb_bus_unregister(&sdio->ssb);
+	sdio_claim_host(func);
 	sdio_disable_func(func);
+	sdio_release_host(func);
 	kfree(sdio);
 	sdio_set_drvdata(func, NULL);
 }
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/xmit.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/xmit.c
@@ -27,7 +27,7 @@
 
 */
 
-#include "b43.h"
+#include "xmit.h"
 #include "phy_common.h"
 #include "dma.h"
 #include "pio.h"
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/Makefile
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/Makefile
@@ -12,7 +12,7 @@
 b43-y				+= lo.o
 b43-y				+= wa.o
 b43-y				+= dma.o
-b43-$(CONFIG_B43_PIO)		+= pio.o
+b43-y				+= pio.o
 b43-y				+= rfkill.o
 b43-$(CONFIG_B43_LEDS)		+= leds.o
 b43-$(CONFIG_B43_PCMCIA)	+= pcmcia.o
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/pio.h
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/pio.h
@@ -55,8 +55,6 @@
 #define B43_PIO_MAX_NR_TXPACKETS	32
 
 
-#ifdef CONFIG_B43_PIO
-
 struct b43_pio_txpacket {
 	/* Pointer to the TX queue we belong to. */
 	struct b43_pio_txqueue *queue;
@@ -169,42 +167,4 @@
 void b43_pio_tx_suspend(struct b43_wldev *dev);
 void b43_pio_tx_resume(struct b43_wldev *dev);
 
-
-#else /* CONFIG_B43_PIO */
-
-
-static inline int b43_pio_init(struct b43_wldev *dev)
-{
-	return 0;
-}
-static inline void b43_pio_free(struct b43_wldev *dev)
-{
-}
-static inline void b43_pio_stop(struct b43_wldev *dev)
-{
-}
-static inline int b43_pio_tx(struct b43_wldev *dev,
-			     struct sk_buff *skb)
-{
-	return 0;
-}
-static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
-					   const struct b43_txstatus *status)
-{
-}
-static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
-					struct ieee80211_tx_queue_stats *stats)
-{
-}
-static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
-{
-}
-static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
-{
-}
-static inline void b43_pio_tx_resume(struct b43_wldev *dev)
-{
-}
-
-#endif /* CONFIG_B43_PIO */
 #endif /* B43_PIO_H_ */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/b43.h
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/b43.h
@@ -117,6 +117,7 @@
 #define B43_MMIO_TSF_2			0x636	/* core rev < 3 only */
 #define B43_MMIO_TSF_3			0x638	/* core rev < 3 only */
 #define B43_MMIO_RNG			0x65A
+#define B43_MMIO_IFSSLOT		0x684	/* Interframe slot time */
 #define B43_MMIO_IFSCTL			0x688 /* Interframe space control */
 #define  B43_MMIO_IFSCTL_USE_EDCF	0x0004
 #define B43_MMIO_POWERUP_DELAY		0x6A8
@@ -695,6 +696,7 @@
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool qos_enabled;		/* TRUE, if QoS is used. */
 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
+	bool use_pio;			/* TRUE if next init should use PIO */
 
 	/* PHY/Radio device. */
 	struct b43_phy phy;
@@ -749,12 +751,6 @@
 #endif
 };
 
-/*
- * Include goes here to avoid a dependency problem.
- * A better fix would be to integrate xmit.h into b43.h.
- */
-#include "xmit.h"
-
 /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
 struct b43_wl {
 	/* Pointer to the active wireless device on this chip */
@@ -829,15 +825,9 @@
 	/* The device LEDs. */
 	struct b43_leds leds;
 
-#ifdef CONFIG_B43_PIO
-	/*
-	 * RX/TX header/tail buffers used by the frame transmit functions.
-	 */
-	struct b43_rxhdr_fw4 rxhdr;
-	struct b43_txhdr txhdr;
-	u8 rx_tail[4];
-	u8 tx_tail[4];
-#endif /* CONFIG_B43_PIO */
+	/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
+	u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
+	u8 pio_tailspace[4] __attribute__((__aligned__(8)));
 };
 
 static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
@@ -888,20 +878,15 @@
 
 static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
 {
-#ifdef CONFIG_B43_PIO
 	return dev->__using_pio_transfers;
-#else
-	return 0;
-#endif
 }
 
 #ifdef CONFIG_B43_FORCE_PIO
-# define B43_FORCE_PIO	1
+# define B43_PIO_DEFAULT 1
 #else
-# define B43_FORCE_PIO	0
+# define B43_PIO_DEFAULT 0
 #endif
 
-
 /* Message printing */
 void b43info(struct b43_wl *wl, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/Kconfig
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/Kconfig
@@ -78,11 +78,11 @@
 
 	  If unsure, say N.
 
-# Data transfers to the device via PIO
-# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
+#Data transfers to the device via PIO. We want it as a fallback even
+# if we can do DMA.
 config B43_PIO
 	bool
-	depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
+	depends on B43
 	select SSB_BLOCKIO
 	default y
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/main.c
@@ -66,8 +66,38 @@
 MODULE_AUTHOR("Gábor Stefanik");
 MODULE_LICENSE("GPL");
 
-MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
-
+MODULE_FIRMWARE("b43/a0g0bsinitvals5.fw");
+MODULE_FIRMWARE("b43/a0g0bsinitvals9.fw");
+MODULE_FIRMWARE("b43/a0g0initvals5.fw");
+MODULE_FIRMWARE("b43/a0g0initvals9.fw");
+MODULE_FIRMWARE("b43/a0g1bsinitvals13.fw");
+MODULE_FIRMWARE("b43/a0g1bsinitvals5.fw");
+MODULE_FIRMWARE("b43/a0g1bsinitvals9.fw");
+MODULE_FIRMWARE("b43/a0g1initvals13.fw");
+MODULE_FIRMWARE("b43/a0g1initvals5.fw");
+MODULE_FIRMWARE("b43/a0g1initvals9.fw");
+MODULE_FIRMWARE("b43/b0g0bsinitvals13.fw");
+MODULE_FIRMWARE("b43/b0g0bsinitvals5.fw");
+MODULE_FIRMWARE("b43/b0g0bsinitvals9.fw");
+MODULE_FIRMWARE("b43/b0g0initvals13.fw");
+MODULE_FIRMWARE("b43/b0g0initvals5.fw");
+MODULE_FIRMWARE("b43/b0g0initvals9.fw");
+MODULE_FIRMWARE("b43/lp0bsinitvals13.fw");
+MODULE_FIRMWARE("b43/lp0bsinitvals14.fw");
+MODULE_FIRMWARE("b43/lp0bsinitvals15.fw");
+MODULE_FIRMWARE("b43/lp0initvals13.fw");
+MODULE_FIRMWARE("b43/lp0initvals14.fw");
+MODULE_FIRMWARE("b43/lp0initvals15.fw");
+MODULE_FIRMWARE("b43/n0absinitvals11.fw");
+MODULE_FIRMWARE("b43/n0bsinitvals11.fw");
+MODULE_FIRMWARE("b43/n0initvals11.fw");
+MODULE_FIRMWARE("b43/pcm5.fw");
+MODULE_FIRMWARE("b43/ucode11.fw");
+MODULE_FIRMWARE("b43/ucode13.fw");
+MODULE_FIRMWARE("b43/ucode14.fw");
+MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode5.fw");
+MODULE_FIRMWARE("b43/ucode9.fw");
 
 static int modparam_bad_frames_preempt;
 module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
@@ -102,6 +132,9 @@
 module_param_named(verbose, b43_modparam_verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
 
+int b43_modparam_pio = B43_PIO_DEFAULT;
+module_param_named(pio, b43_modparam_pio, int, 0644);
+MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
 
 static const struct ssb_device_id b43_ssb_tbl[] = {
 	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
@@ -628,10 +661,17 @@
 static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
 {
 	/* slot_time is in usec. */
-	if (dev->phy.type != B43_PHYTYPE_G)
+	/* This test used to exit for all but a G PHY. */
+	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
 		return;
-	b43_write16(dev, 0x684, 510 + slot_time);
-	b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
+	b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time);
+	/* Shared memory location 0x0010 is the slot time and should be
+	 * set to slot_time; however, this register is initially 0 and changing
+	 * the value adversely affects the transmit rate for BCM4311
+	 * devices. Until this behavior is unterstood, delete this step
+	 *
+	 * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
+	 */
 }
 
 static void b43_short_slot_timing_enable(struct b43_wldev *dev)
@@ -845,19 +885,16 @@
 	if (B43_WARN_ON(!modparam_hwtkip))
 		return;
 
-	mutex_lock(&wl->mutex);
-
+	/* This is only called from the RX path through mac80211, where
+	 * our mutex is already locked. */
+	B43_WARN_ON(!mutex_is_locked(&wl->mutex));
 	dev = wl->current_dev;
-	if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
-		goto out_unlock;
+	B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED);
 
 	keymac_write(dev, index, NULL);	/* First zero out mac to avoid race */
 
 	rx_tkip_phase1_write(dev, index, iv32, phase1key);
 	keymac_write(dev, index, addr);
-
-out_unlock:
-	mutex_unlock(&wl->mutex);
 }
 
 static void do_key_write(struct b43_wldev *dev,
@@ -1784,6 +1821,10 @@
 			       dma_reason[0], dma_reason[1],
 			       dma_reason[2], dma_reason[3],
 			       dma_reason[4], dma_reason[5]);
+			b43err(dev->wl, "This device does not support DMA "
+			       "on your system. Please use PIO instead.\n");
+			/* Fall back to PIO transfers if we get fatal DMA errors! */
+			dev->use_pio = 1;
 			b43_controller_restart(dev, "DMA error");
 			return;
 		}
@@ -3960,6 +4001,7 @@
 	}
 
 	/* We are ready to run. */
+	ieee80211_wake_queues(dev->wl->hw);
 	b43_set_status(dev, B43_STAT_STARTED);
 
 	/* Start data flow (TX/RX). */
@@ -4350,7 +4392,7 @@
 
 	if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
 	    (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
-	    B43_FORCE_PIO) {
+	    dev->use_pio) {
 		dev->__using_pio_transfers = 1;
 		err = b43_pio_init(dev);
 	} else {
@@ -4369,8 +4411,6 @@
 
 	ieee80211_wake_queues(dev->wl->hw);
 
-	ieee80211_wake_queues(dev->wl->hw);
-
 	b43_set_status(dev, B43_STAT_INITIALIZED);
 
 out:
@@ -4820,6 +4860,7 @@
 	if (!wldev)
 		goto out;
 
+	wldev->use_pio = b43_modparam_pio;
 	wldev->dev = dev;
 	wldev->wl = wl;
 	b43_set_status(wldev, B43_STAT_UNINIT);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/dma.h
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/dma.h
@@ -163,7 +163,7 @@
 /* DMA engine tuning knobs */
 #define B43_TXRING_SLOTS		256
 #define B43_RXRING_SLOTS		64
-#define B43_DMA0_RX_BUFFERSIZE		IEEE80211_MAX_FRAME_LEN
+#define B43_DMA0_RX_BUFFERSIZE		(B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
 
 
 struct sk_buff;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/dma.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/dma.c
@@ -1521,7 +1521,7 @@
 		dmaaddr = meta->dmaaddr;
 		goto drop_recycle_buffer;
 	}
-	if (unlikely(len > ring->rx_buffersize)) {
+	if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
 		/* The data did not fit into one descriptor buffer
 		 * and is split over multiple buffers.
 		 * This should never happen, as we try to allocate buffers
@@ -1620,7 +1620,6 @@
 	b43_power_saving_ctl_bits(dev, 0);
 }
 
-#ifdef CONFIG_B43_PIO
 static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
 			   u16 mmio_base, bool enable)
 {
@@ -1654,4 +1653,3 @@
 	mmio_base = b43_dmacontroller_base(type, engine_index);
 	direct_fifo_rx(dev, type, mmio_base, enable);
 }
-#endif /* CONFIG_B43_PIO */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43/rfkill.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43/rfkill.c
@@ -33,8 +33,14 @@
 		      & B43_MMIO_RADIO_HWENABLED_HI_MASK))
 			return 1;
 	} else {
-		if (b43_status(dev) >= B43_STAT_STARTED &&
-		    b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
+		/* To prevent CPU fault on PPC, do not read a register
+		 * unless the interface is started; however, on resume
+		 * for hibernation, this routine is entered early. When
+		 * that happens, unconditionally return TRUE.
+		 */
+		if (b43_status(dev) < B43_STAT_STARTED)
+			return 1;
+		if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
 		    & B43_MMIO_RADIO_HWENABLED_LO_MASK)
 			return 1;
 	}
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43legacy/main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43legacy/main.c
@@ -2921,6 +2921,7 @@
 		goto out;
 	}
 	/* We are ready to run. */
+	ieee80211_wake_queues(dev->wl->hw);
 	b43legacy_set_status(dev, B43legacy_STAT_STARTED);
 
 	/* Start data flow (TX/RX) */
@@ -3341,6 +3342,7 @@
 	b43legacy_security_init(dev);
 	b43legacy_rng_init(wl);
 
+	ieee80211_wake_queues(dev->wl->hw);
 	b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
 
 	b43legacy_leds_init(dev);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/b43legacy/rfkill.c
+++ linux-ec2-2.6.32/drivers/net/wireless/b43legacy/rfkill.c
@@ -34,6 +34,13 @@
 		      & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
 			return 1;
 	} else {
+		/* To prevent CPU fault on PPC, do not read a register
+		 * unless the interface is started; however, on resume
+		 * for hibernation, this routine is entered early. When
+		 * that happens, unconditionally return TRUE.
+		 */
+		if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+			return 1;
 		if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
 		    & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
 			return 1;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/regd.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/regd.h
@@ -31,7 +31,6 @@
 #define NO_CTL 0xff
 #define SD_NO_CTL               0xE0
 #define NO_CTL                  0xff
-#define CTL_MODE_M              7
 #define CTL_11A                 0
 #define CTL_11B                 1
 #define CTL_11G                 2
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/regd_common.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/regd_common.h
@@ -195,6 +195,7 @@
 	{APL9_WORLD, CTL_ETSI, CTL_ETSI},
 
 	{APL3_FCCA, CTL_FCC, CTL_FCC},
+	{APL7_FCCA, CTL_FCC, CTL_FCC},
 	{APL1_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_APLD, CTL_FCC, NO_CTL},
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/qcu.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/qcu.c
@@ -408,12 +408,13 @@
 			break;
 
 		case AR5K_TX_QUEUE_CAB:
+			/* XXX: use BCN_SENT_GT, if we can figure out how */
 			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
-				AR5K_QCU_MISC_FRSHED_BCN_SENT_GT |
+				AR5K_QCU_MISC_FRSHED_DBA_GT |
 				AR5K_QCU_MISC_CBREXP_DIS |
 				AR5K_QCU_MISC_CBREXP_BCN_DIS);
 
-			ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
+			ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
 				(AR5K_TUNE_SW_BEACON_RESP -
 				AR5K_TUNE_DMA_BEACON_RESP) -
 				AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/ath5k.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -540,13 +540,12 @@
 	u32	tqi_cbr_period; /* Constant bit rate period */
 	u32	tqi_cbr_overflow_limit;
 	u32	tqi_burst_time;
-	u32	tqi_ready_time; /* Not used */
+	u32	tqi_ready_time; /* Time queue waits after an event */
 };
 
 /*
  * Transmit packet types.
  * used on tx control descriptor
- * TODO: Use them inside base.c corectly
  */
 enum ath5k_pkt_type {
 	AR5K_PKT_TYPE_NORMAL		= 0,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/eeprom.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -37,6 +37,14 @@
 #define AR5K_EEPROM_RFKILL_POLARITY_S	1
 
 #define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* EEPROM regdom */
+
+/* FLASH(EEPROM) Defines for AR531X chips */
+#define AR5K_EEPROM_SIZE_LOWER		0x1b /* size info -- lower */
+#define AR5K_EEPROM_SIZE_UPPER		0x1c /* size info -- upper */
+#define AR5K_EEPROM_SIZE_UPPER_MASK	0xfff0
+#define AR5K_EEPROM_SIZE_UPPER_SHIFT	4
+#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT	12
+
 #define AR5K_EEPROM_CHECKSUM		0x00c0	/* EEPROM checksum */
 #define AR5K_EEPROM_INFO_BASE		0x00c0	/* EEPROM header */
 #define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/attach.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/attach.c
@@ -133,6 +133,7 @@
 	ah->ah_cw_min = AR5K_TUNE_CWMIN;
 	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
 	ah->ah_software_retry = false;
+	ah->ah_current_channel = &sc->channels[0];
 
 	/*
 	 * Find the mac version
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/reset.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/reset.c
@@ -1382,8 +1382,9 @@
 	 * Set clocks to 32KHz operation and use an
 	 * external 32KHz crystal when sleeping if one
 	 * exists */
-	if (ah->ah_version == AR5K_AR5212)
-			ath5k_hw_set_sleep_clock(ah, true);
+	if (ah->ah_version == AR5K_AR5212 &&
+	    ah->ah_op_mode != NL80211_IFTYPE_AP)
+		ath5k_hw_set_sleep_clock(ah, true);
 
 	/*
 	 * Disable beacons and reset the register
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/phy.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/phy.c
@@ -2954,8 +2954,6 @@
 		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
 		return -EINVAL;
 	}
-	if (txpower == 0)
-		txpower = AR5K_TUNE_DEFAULT_TXPOWER;
 
 	/* Reset TX power values */
 	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/eeprom.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -97,6 +97,7 @@
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	int ret;
 	u16 val;
+	u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
 
 	/*
 	 * Read values from EEPROM and store them in the capability structure
@@ -111,20 +112,44 @@
 	if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
 		return 0;
 
-#ifdef notyet
 	/*
 	 * Validate the checksum of the EEPROM date. There are some
 	 * devices with invalid EEPROMs.
 	 */
-	for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+	AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val);
+	if (val) {
+		eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
+			   AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
+		AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val);
+		eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE;
+
+		/*
+		 * Fail safe check to prevent stupid loops due
+		 * to busted EEPROMs. XXX: This value is likely too
+		 * big still, waiting on a better value.
+		 */
+		if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) {
+			ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: "
+				  "%d (0x%04x) max expected: %d (0x%04x)\n",
+				  eep_max, eep_max,
+				  3 * AR5K_EEPROM_INFO_MAX,
+				  3 * AR5K_EEPROM_INFO_MAX);
+			return -EIO;
+		}
+	}
+
+	for (cksum = 0, offset = 0; offset < eep_max; offset++) {
 		AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
 		cksum ^= val;
 	}
 	if (cksum != AR5K_EEPROM_INFO_CKSUM) {
-		ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+		ATH5K_ERR(ah->ah_sc, "Invalid EEPROM "
+			  "checksum: 0x%04x eep_max: 0x%04x (%s)\n",
+			  cksum, eep_max,
+			  eep_max == AR5K_EEPROM_INFO_MAX ?
+				"default size" : "custom size");
 		return -EIO;
 	}
-#endif
 
 	AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
 	    ee_ant_gain);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath5k/base.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath5k/base.c
@@ -48,6 +48,7 @@
 #include <linux/netdevice.h>
 #include <linux/cache.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/ethtool.h>
 #include <linux/uaccess.h>
 
@@ -448,6 +449,26 @@
 	int ret;
 	u8 csz;
 
+	/*
+	 * L0s needs to be disabled on all ath5k cards.
+	 *
+	 * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
+	 * by default in the future in 2.6.36) this will also mean both L1 and
+	 * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
+	 * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
+	 * though but cannot currently undue the effect of a blacklist, for
+	 * details you can read pcie_aspm_sanity_check() and see how it adjusts
+	 * the device link capability.
+	 *
+	 * It may be possible in the future to implement some PCI API to allow
+	 * drivers to override blacklists for pre 1.1 PCIe but for now it is
+	 * best to accept that both L0s and L1 will be disabled completely for
+	 * distributions shipping with CONFIG_PCIEASPM rather than having this
+	 * issue present. Motivation for adding this new API will be to help
+	 * with power consumption for some of these devices.
+	 */
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
 	ret = pci_enable_device(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "can't enable device\n");
@@ -1220,6 +1241,29 @@
 	return 0;
 }
 
+static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+	enum ath5k_pkt_type htype;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	if (ieee80211_is_beacon(fc))
+		htype = AR5K_PKT_TYPE_BEACON;
+	else if (ieee80211_is_probe_resp(fc))
+		htype = AR5K_PKT_TYPE_PROBE_RESP;
+	else if (ieee80211_is_atim(fc))
+		htype = AR5K_PKT_TYPE_ATIM;
+	else if (ieee80211_is_pspoll(fc))
+		htype = AR5K_PKT_TYPE_PSPOLL;
+	else
+		htype = AR5K_PKT_TYPE_NORMAL;
+
+	return htype;
+}
+
 static int
 ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 		  struct ath5k_txq *txq)
@@ -1244,6 +1288,10 @@
 			PCI_DMA_TODEVICE);
 
 	rate = ieee80211_get_tx_rate(sc->hw, info);
+	if (!rate) {
+		ret = -EINVAL;
+		goto err_unmap;
+	}
 
 	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
 		flags |= AR5K_TXDESC_NOACK;
@@ -1274,7 +1322,8 @@
 			sc->vif, pktlen, info));
 	}
 	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
-		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
+		ieee80211_get_hdrlen_from_skb(skb),
+		get_hw_packet_type(skb),
 		(sc->power_level * 2),
 		hw_rate,
 		info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags,
@@ -1487,7 +1536,8 @@
 
 	ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
 	if (ret)
-		return ret;
+		goto err;
+
 	if (sc->opmode == NL80211_IFTYPE_AP ||
 		sc->opmode == NL80211_IFTYPE_MESH_POINT) {
 		/*
@@ -1514,10 +1564,25 @@
 	if (ret) {
 		ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
 			"hardware queue!\n", __func__);
-		return ret;
+		goto err;
 	}
+	ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */
+	if (ret)
+		goto err;
+
+	/* reconfigure cabq with ready time to 80% of beacon_interval */
+	ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
+	if (ret)
+		goto err;
+
+	qi.tqi_ready_time = (sc->bintval * 80) / 100;
+	ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi);
+	if (ret)
+		goto err;
 
-	return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
+	ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB);
+err:
+	return ret;
 }
 
 static void
@@ -1778,11 +1843,6 @@
 			return;
 		}
 
-		if (unlikely(rs.rs_more)) {
-			ATH5K_WARN(sc, "unsupported jumbo\n");
-			goto next;
-		}
-
 		if (unlikely(rs.rs_status)) {
 			if (rs.rs_status & AR5K_RXERR_PHY)
 				goto next;
@@ -1812,6 +1872,8 @@
 					sc->opmode != NL80211_IFTYPE_MONITOR)
 				goto next;
 		}
+		if (unlikely(rs.rs_more))
+			goto next;
 accept:
 		next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
 
@@ -2349,6 +2411,9 @@
 	 */
 	ath5k_stop_locked(sc);
 
+	/* Set PHY calibration interval */
+	ah->ah_cal_intval = ath5k_calinterval;
+
 	/*
 	 * The basic interface to setting the hardware in a good
 	 * state is ``reset''.  On return the hardware is known to
@@ -2376,10 +2441,6 @@
 
 	/* Set ack to be sent at low bit-rates */
 	ath5k_hw_set_ack_bitrate_high(ah, false);
-
-	/* Set PHY calibration inteval */
-	ah->ah_cal_intval = ath5k_calinterval;
-
 	ret = 0;
 done:
 	mmiowb();
@@ -2936,13 +2997,15 @@
 
 	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
 		if (*new_flags & FIF_PROMISC_IN_BSS) {
-			rfilt |= AR5K_RX_FILTER_PROM;
 			__set_bit(ATH_STAT_PROMISC, sc->status);
 		} else {
 			__clear_bit(ATH_STAT_PROMISC, sc->status);
 		}
 	}
 
+	if (test_bit(ATH_STAT_PROMISC, sc->status))
+		rfilt |= AR5K_RX_FILTER_PROM;
+
 	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
 	if (*new_flags & FIF_ALLMULTI) {
 		mfilt[0] =  ~0;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/hw.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/hw.c
@@ -398,7 +398,6 @@
 	ah->config.pcie_clock_req = 0;
 	ah->config.pcie_waen = 0;
 	ah->config.analog_shiftreg = 1;
-	ah->config.ht_enable = 1;
 	ah->config.ofdm_trig_low = 200;
 	ah->config.ofdm_trig_high = 500;
 	ah->config.cck_trig_high = 200;
@@ -412,6 +411,11 @@
 		ah->config.spurchans[i][1] = AR_NO_SPUR;
 	}
 
+	if (ah->hw_version.devid != AR2427_DEVID_PCIE)
+		ah->config.ht_enable = 1;
+	else
+		ah->config.ht_enable = 0;
+
 	ah->config.intr_mitigation = true;
 
 	/*
@@ -617,6 +621,7 @@
 	case AR9285_DEVID_PCIE:
 	case AR5416_DEVID_AR9287_PCI:
 	case AR5416_DEVID_AR9287_PCIE:
+	case AR2427_DEVID_PCIE:
 		return true;
 	default:
 		break;
@@ -880,12 +885,11 @@
 	}
 }
 
-static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
+static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
 {
 	u32 i, j;
 
-	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
-	    test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
+	if (ah->hw_version.devid == AR9280_DEVID_PCI) {
 
 		/* EEPROM Fixup */
 		for (i = 0; i < ah->iniModes.ia_rows; i++) {
@@ -913,6 +917,8 @@
 	ath9k_hw_init_defaults(ah);
 	ath9k_hw_init_config(ah);
 
+	ath9k_hw_read_revisions(ah);
+
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
 		return -EIO;
@@ -925,7 +931,8 @@
 
 	if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
 		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
-		    (AR_SREV_9280(ah) && !ah->is_pciexpress)) {
+		    ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+		     !ah->is_pciexpress)) {
 			ah->config.serialize_regmode =
 				SER_REG_MODE_ON;
 		} else {
@@ -937,6 +944,11 @@
 	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n",
 		ah->config.serialize_regmode);
 
+	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+		ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
+	else
+		ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
+
 	if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"Mac Chip Rev 0x%02x.%x is not supported by "
@@ -975,7 +987,7 @@
 
 	ath9k_hw_init_mode_gain_regs(ah);
 	ath9k_hw_fill_cap_info(ah);
-	ath9k_hw_init_11a_eeprom_fix(ah);
+	ath9k_hw_init_eeprom_fix(ah);
 
 	r = ath9k_hw_init_macaddr(ah);
 	if (r) {
@@ -1291,6 +1303,16 @@
 	 * Necessary to avoid issues on AR5416 2.0
 	 */
 	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+
+	/*
+	 * Disable RIFS search on some chips to avoid baseband
+	 * hang issues.
+	 */
+	if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
+		val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
+		val &= ~AR_PHY_RIFS_INIT_DELAY;
+		REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
+	}
 }
 
 static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
@@ -1738,8 +1760,6 @@
 		return false;
 	}
 
-	ath9k_hw_read_revisions(ah);
-
 	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
 }
 
@@ -2383,7 +2403,8 @@
 	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 
 	/* For chips on which RTC reset is done, save TSF before it gets cleared */
-	if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+	if (AR_SREV_9100(ah) ||
+	    (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
 		tsf = ath9k_hw_gettsf64(ah);
 
 	saveLedState = REG_READ(ah, AR_CFG_LED) &
@@ -2413,7 +2434,7 @@
 	}
 
 	/* Restore TSF */
-	if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+	if (tsf)
 		ath9k_hw_settsf64(ah, tsf);
 
 	if (AR_SREV_9280_10_OR_LATER(ah))
@@ -2433,6 +2454,17 @@
 	if (r)
 		return r;
 
+	/*
+	 * Some AR91xx SoC devices frequently fail to accept TSF writes
+	 * right after the chip reset. When that happens, write a new
+	 * value after the initvals have been applied, with an offset
+	 * based on measured time difference
+	 */
+	if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
+		tsf += 1500;
+		ath9k_hw_settsf64(ah, tsf);
+	}
+
 	/* Setup MFP options for CCMP */
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
@@ -3670,7 +3702,11 @@
 		pCap->keycache_size = AR_KEYTABLE_SIZE;
 
 	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+
+	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
+	else
+		pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
 
 	if (AR_SREV_9285_10_OR_LATER(ah))
 		pCap->num_gpio_pins = AR9285_NUM_GPIO;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/ath9k.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -139,6 +139,7 @@
 	dma_addr_t bf_daddr;		/* physical addr of desc */
 	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
 	bool bf_stale;
+	bool bf_isnullfunc;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
 	dma_addr_t bf_dmacontext;
@@ -213,8 +214,8 @@
 
 /* returns delimiter padding required given the packet length */
 #define ATH_AGGR_GET_NDELIM(_len)					\
-	(((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?           \
-	  (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+       (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
+        DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
 
 #define BAW_WITHIN(_start, _bawsz, _seqno) \
 	((((_seqno) - (_start)) & 4095) < (_bawsz))
@@ -367,6 +368,7 @@
 		       u16 tid, u16 *ssn);
 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath9k_enable_ps(struct ath_softc *sc);
 
 /********/
 /* VIFs */
@@ -524,6 +526,8 @@
 #define SC_OP_BEACON_SYNC       BIT(19)
 #define SC_OP_BTCOEX_ENABLED    BIT(20)
 #define SC_OP_BT_PRIORITY_DETECTED BIT(21)
+#define SC_OP_NULLFUNC_COMPLETED   BIT(22)
+#define SC_OP_PS_ENABLED	BIT(23)
 
 struct ath_bus_ops {
 	void		(*read_cachesize)(struct ath_softc *sc, int *csz);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/xmit.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/xmit.c
@@ -423,6 +423,14 @@
 		bf = bf_next;
 	}
 
+	/* prepend un-acked frames to the beginning of the pending frame queue */
+	if (!list_empty(&bf_pending)) {
+		spin_lock_bh(&txq->axq_lock);
+		list_splice(&bf_pending, &tid->buf_q);
+		ath_tx_queue_tid(txq, tid);
+		spin_unlock_bh(&txq->axq_lock);
+	}
+
 	if (tid->state & AGGR_CLEANUP) {
 		if (tid->baw_head == tid->baw_tail) {
 			tid->state &= ~AGGR_ADDBA_COMPLETE;
@@ -435,14 +443,6 @@
 		return;
 	}
 
-	/* prepend un-acked frames to the beginning of the pending frame queue */
-	if (!list_empty(&bf_pending)) {
-		spin_lock_bh(&txq->axq_lock);
-		list_splice(&bf_pending, &tid->buf_q);
-		ath_tx_queue_tid(txq, tid);
-		spin_unlock_bh(&txq->axq_lock);
-	}
-
 	rcu_read_unlock();
 
 	if (needreset)
@@ -1076,10 +1076,10 @@
 	if (npend) {
 		int r;
 
-		DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
+		DPRINTF(sc, ATH_DBG_FATAL, "Unable to stop TxDMA. Reset HAL!\n");
 
 		spin_lock_bh(&sc->sc_resetlock);
-		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
+		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
 		if (r)
 			DPRINTF(sc, ATH_DBG_FATAL,
 				"Unable to reset hardware; reset status %d\n",
@@ -1320,25 +1320,6 @@
 	return htype;
 }
 
-static bool is_pae(struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr;
-	__le16 fc;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-
-	if (ieee80211_is_data(fc)) {
-		if (ieee80211_is_nullfunc(fc) ||
-		    /* Port Access Entity (IEEE 802.1X) */
-		    (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
-			return true;
-		}
-	}
-
-	return false;
-}
-
 static int get_hw_crypto_keytype(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1563,7 +1544,7 @@
 
 	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
 
-	if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
+	if (conf_is_ht(&sc->hw->conf))
 		bf->bf_state.bf_type |= BUF_HT;
 
 	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
@@ -1592,6 +1573,13 @@
 	}
 
 	bf->bf_buf_addr = bf->bf_dmacontext;
+
+	if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
+		bf->bf_isnullfunc = true;
+		sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
+	} else
+		bf->bf_isnullfunc = false;
+
 	return 0;
 }
 
@@ -1989,6 +1977,14 @@
 		if (ds == txq->axq_gatingds)
 			txq->axq_gatingds = NULL;
 
+		if (bf->bf_isnullfunc &&
+		    (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) {
+			if ((sc->sc_flags & SC_OP_PS_ENABLED))
+				ath9k_enable_ps(sc);
+			else
+				sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED;
+		}
+
 		/*
 		 * Remove ath_buf's of the same transmit unit from txq,
 		 * however leave the last descriptor back as the holding
@@ -2004,7 +2000,7 @@
 		if (bf_isaggr(bf))
 			txq->axq_aggr_depth--;
 
-		txok = (ds->ds_txstat.ts_status == 0);
+		txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK);
 		txq->axq_tx_inprogress = false;
 		spin_unlock_bh(&txq->axq_lock);
 
@@ -2065,7 +2061,9 @@
 
 	if (needreset) {
 		DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n");
+		ath9k_ps_wakeup(sc);
 		ath_reset(sc, false);
+		ath9k_ps_restore(sc);
 	}
 
 	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/phy.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/phy.h
@@ -368,6 +368,9 @@
 
 #define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0
 
+#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS    0x99EC
+#define AR_PHY_RIFS_INIT_DELAY         0x03ff0000
+
 #define AR_PHY_M_SLEEP      0x99f0
 #define AR_PHY_REFCLKDLY    0x99f4
 #define AR_PHY_REFCLKPD     0x99f8
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/rc.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/rc.c
@@ -757,7 +757,7 @@
 	struct ieee80211_tx_rate *rates = tx_info->control.rates;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	__le16 fc = hdr->frame_control;
-	u8 try_per_rate, i = 0, rix, nrix;
+	u8 try_per_rate, i = 0, rix;
 	int is_probe = 0;
 
 	if (rate_control_send_low(sta, priv_sta, txrc))
@@ -777,26 +777,25 @@
 
 	rate_table = sc->cur_rate_table;
 	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
-	nrix = rix;
 
 	if (is_probe) {
 		/* set one try for probe rates. For the
 		 * probes don't enable rts */
 		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       1, nrix, 0);
+				       1, rix, 0);
 
 		/* Get the next tried/allowed rate. No RTS for the next series
 		 * after the probe rate
 		 */
-		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
+		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
 		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, nrix, 0);
+				       try_per_rate, rix, 0);
 
 		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 	} else {
 		/* Set the choosen rate. No RTS for first series entry. */
 		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
-				       try_per_rate, nrix, 0);
+				       try_per_rate, rix, 0);
 	}
 
 	/* Fill in the other rates for multirate retry */
@@ -805,10 +804,10 @@
 		if (i + 1 == 4)
 			try_per_rate = 4;
 
-		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
+		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
 		/* All other rates in the series have RTS enabled */
 		ath_rc_rate_set_series(rate_table, &rates[i], txrc,
-				       try_per_rate, nrix, 1);
+				       try_per_rate, rix, 1);
 	}
 
 	/*
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/eeprom.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -60,7 +60,7 @@
 
 #define SD_NO_CTL               0xE0
 #define NO_CTL                  0xff
-#define CTL_MODE_M              7
+#define CTL_MODE_M              0xf
 #define CTL_11A                 0
 #define CTL_11B                 1
 #define CTL_11G                 2
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/initvals.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/initvals.h
@@ -2762,7 +2762,7 @@
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
@@ -3935,7 +3935,7 @@
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
@@ -5072,7 +5072,7 @@
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
@@ -6864,7 +6864,7 @@
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/mac.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/mac.c
@@ -70,7 +70,7 @@
 	u32 txcfg, curLevel, newLevel;
 	enum ath9k_int omask;
 
-	if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
+	if (ah->tx_trig_level >= ah->config.max_txtrig_level)
 		return false;
 
 	omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
@@ -79,7 +79,7 @@
 	curLevel = MS(txcfg, AR_FTRIG);
 	newLevel = curLevel;
 	if (bIncTrigLevel) {
-		if (curLevel < MAX_TX_FIFO_THRESHOLD)
+		if (curLevel < ah->config.max_txtrig_level)
 			newLevel++;
 	} else if (curLevel > MIN_TX_FIFO_THRESHOLD)
 		newLevel--;
@@ -155,7 +155,7 @@
 		wait = wait_time;
 		while (ath9k_hw_numtxpending(ah, q)) {
 			if ((--wait) == 0) {
-				DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 					"Failed to stop TX DMA in 100 "
 					"msec after killing last frame\n");
 				break;
@@ -222,6 +222,8 @@
 	ds->ds_txstat.ts_status = 0;
 	ds->ds_txstat.ts_flags = 0;
 
+	if (ads->ds_txstatus1 & AR_FrmXmitOK)
+		ds->ds_txstat.ts_status |= ATH9K_TX_ACKED;
 	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
 		ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
 	if (ads->ds_txstatus1 & AR_Filtered)
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/reg.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/reg.h
@@ -969,10 +969,10 @@
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB      0x00000400
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S    10
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB      0x00001000
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S    1
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/beacon.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/beacon.c
@@ -512,16 +512,13 @@
 {
 	u32 nexttbtt, intval;
 
-	/* Configure the timers only when the TSF has to be reset */
-
-	if (!(sc->sc_flags & SC_OP_TSF_RESET))
-		return;
-
 	/* NB: the beacon interval is kept internally in TU's */
 	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
 	intval /= ATH_BCBUF;    /* for staggered beacons */
 	nexttbtt = intval;
-	intval |= ATH9K_BEACON_RESET_TSF;
+
+	if (sc->sc_flags & SC_OP_TSF_RESET)
+		intval |= ATH9K_BEACON_RESET_TSF;
 
 	/*
 	 * In AP mode we enable the beacon timers and SWBA interrupts to
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/main.c
@@ -1538,14 +1538,19 @@
 
 void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
+	struct ath_hw *ah = sc->sc_ah;
+
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_AMPDU_AGGREGATION |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_PS_NULLFUNC_STACK |
+		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
 		IEEE80211_HW_SPECTRUM_MGMT;
 
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+		 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+
 	if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
@@ -1555,7 +1560,10 @@
 		BIT(NL80211_IFTYPE_ADHOC) |
 		BIT(NL80211_IFTYPE_MESH_POINT);
 
-	hw->wiphy->ps_default = false;
+	if (AR_SREV_5416(ah))
+		hw->wiphy->ps_default = false;
+	else
+		hw->wiphy->ps_default = true;
 
 	hw->queues = 4;
 	hw->max_rates = 4;
@@ -1910,6 +1918,8 @@
 	DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with "
 		"initial channel: %d MHz\n", curchan->center_freq);
 
+	ath9k_ps_wakeup(sc);
+
 	mutex_lock(&sc->mutex);
 
 	if (ath9k_wiphy_started(sc)) {
@@ -2017,6 +2027,8 @@
 mutex_unlock:
 	mutex_unlock(&sc->mutex);
 
+	ath9k_ps_restore(sc);
+
 	return r;
 }
 
@@ -2147,6 +2159,9 @@
 		return; /* another wiphy still in use */
 	}
 
+	/* Ensure HW is awake when we try to shut it down. */
+	ath9k_ps_wakeup(sc);
+
 	if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) {
 		ath9k_hw_btcoex_disable(sc->sc_ah);
 		if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
@@ -2167,6 +2182,9 @@
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(sc->sc_ah);
 	ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1);
+	ath9k_ps_restore(sc);
+
+	/* Finally, put the chip in FULL SLEEP mode */
 	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
 
 	sc->sc_flags |= SC_OP_INVALID;
@@ -2277,10 +2295,12 @@
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
 	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
 	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
+		ath9k_ps_wakeup(sc);
 		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		ath_beacon_return(sc, avp);
+		ath9k_ps_restore(sc);
 	}
 
+	ath_beacon_return(sc, avp);
 	sc->sc_flags &= ~SC_OP_BEACONS;
 
 	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
@@ -2297,6 +2317,19 @@
 	mutex_unlock(&sc->mutex);
 }
 
+void ath9k_enable_ps(struct ath_softc *sc)
+{
+	sc->ps_enabled = true;
+	if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+		if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
+			sc->imask |= ATH9K_INT_TIM_TIMER;
+			ath9k_hw_set_interrupts(sc->sc_ah,
+					sc->imask);
+		}
+	}
+	ath9k_hw_setrxabort(sc->sc_ah, 1);
+}
+
 static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct ath_wiphy *aphy = hw->priv;
@@ -2327,18 +2360,15 @@
 
 	if (changed & IEEE80211_CONF_CHANGE_PS) {
 		if (conf->flags & IEEE80211_CONF_PS) {
-			if (!(ah->caps.hw_caps &
-			      ATH9K_HW_CAP_AUTOSLEEP)) {
-				if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
-					sc->imask |= ATH9K_INT_TIM_TIMER;
-					ath9k_hw_set_interrupts(sc->sc_ah,
-							sc->imask);
-				}
-				ath9k_hw_setrxabort(sc->sc_ah, 1);
+			sc->sc_flags |= SC_OP_PS_ENABLED;
+			if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) {
+				sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
+				ath9k_enable_ps(sc);
 			}
-			sc->ps_enabled = true;
 		} else {
 			sc->ps_enabled = false;
+			sc->sc_flags &= ~(SC_OP_PS_ENABLED |
+					  SC_OP_NULLFUNC_COMPLETED);
 			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
 			if (!(ah->caps.hw_caps &
 			      ATH9K_HW_CAP_AUTOSLEEP)) {
@@ -2717,15 +2747,21 @@
 	case IEEE80211_AMPDU_RX_STOP:
 		break;
 	case IEEE80211_AMPDU_TX_START:
+		ath9k_ps_wakeup(sc);
 		ath_tx_aggr_start(sc, sta, tid, ssn);
 		ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+		ath9k_ps_restore(sc);
 		break;
 	case IEEE80211_AMPDU_TX_STOP:
+		ath9k_ps_wakeup(sc);
 		ath_tx_aggr_stop(sc, sta, tid);
 		ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+		ath9k_ps_restore(sc);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ath9k_ps_wakeup(sc);
 		ath_tx_aggr_resume(sc, sta, tid);
+		ath9k_ps_restore(sc);
 		break;
 	default:
 		DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n");
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -714,7 +714,7 @@
 				    vpdTableI[i][sizeCurrVpdTable - 2]);
 		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
 
-		if (tgtIndex > maxIndex) {
+		if (tgtIndex >= maxIndex) {
 			while ((ss <= tgtIndex) &&
 			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
 				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/hw.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/hw.h
@@ -37,6 +37,7 @@
 #define AR9280_DEVID_PCI	0x0029
 #define AR9280_DEVID_PCIE	0x002a
 #define AR9285_DEVID_PCIE	0x002b
+#define AR2427_DEVID_PCIE	0x002c
 #define AR5416_AR9100_DEVID	0x000b
 #define	AR_SUBVENDOR_ID_NOG	0x0e11
 #define AR_SUBVENDOR_ID_NEW_A	0x7065
@@ -218,6 +219,7 @@
 #define AR_SPUR_FEEQ_BOUND_HT20 10
 	int spurmode;
 	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+	u8 max_txtrig_level;
 };
 
 enum ath9k_int {
@@ -407,7 +409,7 @@
  * Using de Bruijin sequence to to look up 1's index in a 32 bit number
  * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
  */
-#define debruijn32 0x077CB531UL
+#define debruijn32 0x077CB531U
 
 struct ath_gen_timer_configuration {
 	u32 next_addr;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/mac.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/mac.h
@@ -76,6 +76,10 @@
 #define ATH9K_TXERR_FIFO           0x04
 #define ATH9K_TXERR_XTXOP          0x08
 #define ATH9K_TXERR_TIMER_EXPIRED  0x10
+#define ATH9K_TX_ACKED		   0x20
+#define ATH9K_TXERR_MASK						\
+	(ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO |	\
+	 ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
 
 #define ATH9K_TX_BA                0x01
 #define ATH9K_TX_PWRMGMT           0x02
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ath9k/pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ath9k/pci.c
@@ -25,6 +25,7 @@
 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
 	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
+	{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
 	{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
 	{ 0 }
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ar9170/usb.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ar9170/usb.c
@@ -66,16 +66,28 @@
 	{ USB_DEVICE(0x0cf3, 0x1001) },
 	/* TP-Link TL-WN821N v2 */
 	{ USB_DEVICE(0x0cf3, 0x1002) },
+	/* 3Com Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1010) },
+	/* H3C Dual Band 802.11n USB Adapter */
+	{ USB_DEVICE(0x0cf3, 0x1011) },
 	/* Cace Airpcap NX */
 	{ USB_DEVICE(0xcace, 0x0300) },
-	/* D-Link DWA 160A */
+	/* D-Link DWA 160 A1 */
 	{ USB_DEVICE(0x07d1, 0x3c10) },
+	/* D-Link DWA 160 A2 */
+	{ USB_DEVICE(0x07d1, 0x3a09) },
+	/* Netgear WNA1000 */
+	{ USB_DEVICE(0x0846, 0x9040) },
 	/* Netgear WNDA3100 */
 	{ USB_DEVICE(0x0846, 0x9010) },
 	/* Netgear WN111 v2 */
 	{ USB_DEVICE(0x0846, 0x9001) },
 	/* Zydas ZD1221 */
 	{ USB_DEVICE(0x0ace, 0x1221) },
+	/* Proxim ORiNOCO 802.11n USB */
+	{ USB_DEVICE(0x1435, 0x0804) },
+	/* WNC Generic 11n USB Dongle */
+	{ USB_DEVICE(0x1435, 0x0326) },
 	/* ZyXEL NWD271N */
 	{ USB_DEVICE(0x0586, 0x3417) },
 	/* Z-Com UB81 BG */
@@ -412,7 +424,7 @@
 	spin_unlock_irqrestore(&aru->common.cmdlock, flags);
 
 	usb_fill_int_urb(urb, aru->udev,
-			 usb_sndbulkpipe(aru->udev, AR9170_EP_CMD),
+			 usb_sndintpipe(aru->udev, AR9170_EP_CMD),
 			 aru->common.cmdbuf, plen + 4,
 			 ar9170_usb_tx_urb_complete, NULL, 1);
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ar9170/main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ar9170/main.c
@@ -2526,7 +2526,7 @@
 	 * tends to split the streams into seperate rx descriptors.
 	 */
 
-	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
+	skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
 	if (!skb)
 		goto err_nomem;
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/ath/ar9170/hw.h
+++ linux-ec2-2.6.32/drivers/net/wireless/ath/ar9170/hw.h
@@ -422,5 +422,6 @@
 
 #define AR9170_TXQ_DEPTH	32
 #define AR9170_TX_MAX_PENDING	128
+#define AR9170_RX_STREAM_MAX_SIZE 65535
 
 #endif /* __AR9170_HW_H */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -684,6 +684,21 @@
 	rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues;
 
 	/*
+	 * Initialize extra TX headroom required.
+	 */
+	rt2x00dev->hw->extra_tx_headroom =
+		max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM,
+		      rt2x00dev->ops->extra_tx_headroom);
+
+	/*
+	 * Take TX headroom required for alignment into account.
+	 */
+	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+		rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
+	else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
+
+	/*
 	 * Register HW.
 	 */
 	status = ieee80211_register_hw(rt2x00dev->hw);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2500usb.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -347,6 +347,7 @@
 	int timeout;
 	u32 mask;
 	u16 reg;
+	enum cipher curr_cipher;
 
 	if (crypto->cmd == SET_KEY) {
 		/*
@@ -357,6 +358,7 @@
 		mask = TXRX_CSR0_KEY_ID.bit_mask;
 
 		rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+		curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
 		reg &= mask;
 
 		if (reg && reg == mask)
@@ -365,6 +367,14 @@
 		reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
 
 		key->hw_key_idx += reg ? ffz(reg) : 0;
+		/*
+		 * Hardware requires that all keys use the same cipher
+		 * (e.g. TKIP-only, AES-only, but not TKIP+AES).
+		 * If this is not the first key, compare the cipher with the
+		 * first one and fall back to SW crypto if not the same.
+		 */
+		if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
+			return -EOPNOTSUPP;
 
 		/*
 		 * The encryption key doesn't fit within the CSR cache,
@@ -1788,8 +1798,6 @@
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
 
-	rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
 				rt2x00_eeprom_addr(rt2x00dev,
@@ -1962,6 +1970,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = TXD_DESC_SIZE,
 	.rx		= &rt2500usb_queue_rx,
 	.tx		= &rt2500usb_queue_tx,
 	.bcn		= &rt2500usb_queue_bcn,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2500pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1732,8 +1732,6 @@
 			       IEEE80211_HW_SUPPORTS_PS |
 			       IEEE80211_HW_PS_NULLFUNC_STACK;
 
-	rt2x00dev->hw->extra_tx_headroom = 0;
-
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
 				rt2x00_eeprom_addr(rt2x00dev,
@@ -1927,6 +1925,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = 0,
 	.rx		= &rt2500pci_queue_rx,
 	.tx		= &rt2500pci_queue_tx,
 	.bcn		= &rt2500pci_queue_bcn,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2x00.h
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2x00.h
@@ -112,6 +112,12 @@
 	(  ((unsigned long)((__skb)->data + (__header))) & 3 )
 
 /*
+ * Constants for extra TX headroom for alignment purposes.
+ */
+#define RT2X00_ALIGN_SIZE	4 /* Only whole frame needs alignment */
+#define RT2X00_L2PAD_SIZE	8 /* Both header & payload need alignment */
+
+/*
  * Standard timing and size defines.
  * These values should follow the ieee80211 specifications.
  */
@@ -579,6 +585,7 @@
 	const unsigned int eeprom_size;
 	const unsigned int rf_size;
 	const unsigned int tx_queues;
+	const unsigned int extra_tx_headroom;
 	const struct data_queue_desc *rx;
 	const struct data_queue_desc *tx;
 	const struct data_queue_desc *bcn;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt61pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2538,6 +2538,11 @@
 	unsigned int i;
 
 	/*
+	 * Disable powersaving as default.
+	 */
+	rt2x00dev->hw->wiphy->ps_default = false;
+
+	/*
 	 * Initialize all hw fields.
 	 */
 	rt2x00dev->hw->flags =
@@ -2545,7 +2550,6 @@
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = 0;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2793,6 +2797,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = 0,
 	.rx		= &rt61pci_queue_rx,
 	.tx		= &rt61pci_queue_tx,
 	.bcn		= &rt61pci_queue_bcn,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt73usb.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2068,7 +2068,6 @@
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2311,6 +2310,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = TXD_DESC_SIZE,
 	.rx		= &rt73usb_queue_rx,
 	.tx		= &rt73usb_queue_tx,
 	.bcn		= &rt73usb_queue_bcn,
@@ -2400,6 +2400,7 @@
 	{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* Qcom */
 	{ USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2800usb.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -2509,7 +2509,6 @@
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
 	    IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2858,6 +2857,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.rx		= &rt2800usb_queue_rx,
 	.tx		= &rt2800usb_queue_tx,
 	.bcn		= &rt2800usb_queue_bcn,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -103,7 +103,7 @@
 	 * is also mapped to the DMA so it can be used for transfering
 	 * additional descriptor information to the hardware.
 	 */
-	skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
+	skb_push(skb, rt2x00dev->ops->extra_tx_headroom);
 
 	skbdesc->skb_dma =
 	    dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
@@ -111,7 +111,7 @@
 	/*
 	 * Restore data pointer to original location again.
 	 */
-	skb_pull(skb, rt2x00dev->hw->extra_tx_headroom);
+	skb_pull(skb, rt2x00dev->ops->extra_tx_headroom);
 
 	skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
 }
@@ -133,7 +133,7 @@
 		 * by the driver, but it was actually mapped to DMA.
 		 */
 		dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
-				 skb->len + rt2x00dev->hw->extra_tx_headroom,
+				 skb->len + rt2x00dev->ops->extra_tx_headroom,
 				 DMA_TO_DEVICE);
 		skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
 	}
--- linux-ec2-2.6.32.orig/drivers/net/wireless/rt2x00/rt2400pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1431,7 +1431,6 @@
 			       IEEE80211_HW_SIGNAL_DBM |
 			       IEEE80211_HW_SUPPORTS_PS |
 			       IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = 0;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -1628,6 +1627,7 @@
 	.eeprom_size	= EEPROM_SIZE,
 	.rf_size	= RF_SIZE,
 	.tx_queues	= NUM_TX_QUEUES,
+	.extra_tx_headroom = 0,
 	.rx		= &rt2400pci_queue_rx,
 	.tx		= &rt2400pci_queue_tx,
 	.bcn		= &rt2400pci_queue_bcn,
--- linux-ec2-2.6.32.orig/drivers/net/wireless/libertas/wext.c
+++ linux-ec2-2.6.32/drivers/net/wireless/libertas/wext.c
@@ -1953,10 +1953,8 @@
 	if (priv->connect_status == LBS_CONNECTED) {
 		memcpy(extra, priv->curbssparams.ssid,
 		       priv->curbssparams.ssid_len);
-		extra[priv->curbssparams.ssid_len] = '\0';
 	} else {
 		memset(extra, 0, 32);
-		extra[priv->curbssparams.ssid_len] = '\0';
 	}
 	/*
 	 * If none, we may want to get the one that was set
--- linux-ec2-2.6.32.orig/drivers/net/wireless/libertas/scan.c
+++ linux-ec2-2.6.32/drivers/net/wireless/libertas/scan.c
@@ -399,11 +399,8 @@
 	chan_count = lbs_scan_create_channel_list(priv, chan_list);
 
 	netif_stop_queue(priv->dev);
-	netif_carrier_off(priv->dev);
-	if (priv->mesh_dev) {
+	if (priv->mesh_dev)
 		netif_stop_queue(priv->mesh_dev);
-		netif_carrier_off(priv->mesh_dev);
-	}
 
 	/* Prepare to continue an interrupted scan */
 	lbs_deb_scan("chan_count %d, scan_channel %d\n",
@@ -467,16 +464,13 @@
 	priv->scan_channel = 0;
 
 out:
-	if (priv->connect_status == LBS_CONNECTED) {
-		netif_carrier_on(priv->dev);
-		if (!priv->tx_pending_len)
-			netif_wake_queue(priv->dev);
-	}
-	if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) {
-		netif_carrier_on(priv->mesh_dev);
-		if (!priv->tx_pending_len)
-			netif_wake_queue(priv->mesh_dev);
-	}
+	if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
+		netif_wake_queue(priv->dev);
+
+	if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) &&
+	    !priv->tx_pending_len)
+		netif_wake_queue(priv->mesh_dev);
+
 	kfree(chan_list);
 
 	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/libertas/if_sdio.c
+++ linux-ec2-2.6.32/drivers/net/wireless/libertas/if_sdio.c
@@ -34,6 +34,8 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/host.h>
 
 #include "host.h"
 #include "decl.h"
@@ -883,6 +885,7 @@
 	int ret, i;
 	unsigned int model;
 	struct if_sdio_packet *packet;
+	struct mmc_host *host = func->card->host;
 
 	lbs_deb_enter(LBS_DEB_SDIO);
 
@@ -963,6 +966,25 @@
 	if (ret)
 		goto disable;
 
+	/* For 1-bit transfers to the 8686 model, we need to enable the
+	 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
+	 * bit to allow access to non-vendor registers. */
+	if ((card->model == IF_SDIO_MODEL_8686) &&
+	    (host->caps & MMC_CAP_SDIO_IRQ) &&
+	    (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
+		u8 reg;
+
+		func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+		reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
+		if (ret)
+			goto release_int;
+
+		reg |= SDIO_BUS_ECSI;
+		sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
+		if (ret)
+			goto release_int;
+	}
+
 	card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
 	if (ret)
 		goto release_int;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/libertas/cmd.c
+++ linux-ec2-2.6.32/drivers/net/wireless/libertas/cmd.c
@@ -1758,8 +1758,8 @@
 				    cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 
@@ -1771,8 +1771,8 @@
 				    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 					priv->needtowakeup = 1;
@@ -1785,7 +1785,9 @@
 				       "EXEC_NEXT_CMD: sending EXIT_PS\n");
 			}
 		}
+		spin_lock_irqsave(&priv->driver_lock, flags);
 		list_del(&cmdnode->list);
+		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
 			    le16_to_cpu(cmd->command));
 		lbs_submit_command(priv, cmdnode);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_pci.c
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_pci.c
@@ -329,6 +329,7 @@
 
         dev->irq = pdev->irq;
         hw_priv->mem_start = mem;
+	dev->base_addr = (unsigned long) mem;
 
 	prism2_pci_cor_sreset(local);
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_main.c
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_main.c
@@ -1100,6 +1100,7 @@
 				   (u8 *) &val, 2);
 	memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
 	wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+	wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL);
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_info.c
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_info.c
@@ -238,6 +238,7 @@
 	wrqu.data.length = 0;
 	wrqu.data.flags = 0;
 	wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL);
+	wireless_send_event(local->ddev, SIOCGIWSCAN, &wrqu, NULL);
 
 	/* Allow SIOCGIWSCAN handling to occur since we have received
 	 * scanning result */
@@ -449,8 +450,10 @@
 	 * frames and can confuse wpa_supplicant about the current association
 	 * status.
 	 */
-	if (connected || local->prev_linkstatus_connected)
+	if (connected || local->prev_linkstatus_connected) {
 		wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+		wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL);
+	}
 	local->prev_linkstatus_connected = connected;
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_cs.c
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_cs.c
@@ -626,6 +626,7 @@
 	int ret = 1;
 	int last_fn, last_ret;
 	struct hostap_cs_priv *hw_priv;
+	unsigned long flags;
 
 	PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
@@ -683,8 +684,11 @@
 	CS_CHECK(RequestConfiguration,
 		 pcmcia_request_configuration(link, &link->conf));
 
+	/* IRQ handler cannot proceed until at dev->base_addr is initialized */
+	spin_lock_irqsave(&local->irq_init_lock, flags);
 	dev->irq = link->irq.AssignedIRQ;
 	dev->base_addr = link->io.BasePort1;
+	spin_unlock_irqrestore(&local->irq_init_lock, flags);
 
 	/* Finally, report what we've done */
 	printk(KERN_INFO "%s: index 0x%02x: ",
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_hw.c
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_hw.c
@@ -68,7 +68,7 @@
 module_param_string(essid, essid, sizeof(essid), 0444);
 MODULE_PARM_DESC(essid, "Host AP's ESSID");
 
-static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS };
+static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_INFRA, DEF_INTS };
 module_param_array(iw_mode, int, NULL, 0444);
 MODULE_PARM_DESC(iw_mode, "Initial operation mode");
 
@@ -2618,9 +2618,30 @@
 	int events = 0;
 	u16 ev;
 
+	/* Detect early interrupt before driver is fully configued */
+	if (!dev->base_addr) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+			       dev->name);
+		}
+		return IRQ_HANDLED;
+	}
+
 	iface = netdev_priv(dev);
 	local = iface->local;
 
+	/* Detect early interrupt before driver is fully configued */
+	spin_lock(&local->irq_init_lock);
+	if (!dev->base_addr) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+			       dev->name);
+		}
+		spin_unlock(&local->irq_init_lock);
+		return IRQ_HANDLED;
+	}
+	spin_unlock(&local->irq_init_lock);
+
 	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
 
 	if (local->func->card_present && !local->func->card_present(local)) {
@@ -3138,6 +3159,7 @@
 	spin_lock_init(&local->cmdlock);
 	spin_lock_init(&local->baplock);
 	spin_lock_init(&local->lock);
+	spin_lock_init(&local->irq_init_lock);
 	mutex_init(&local->rid_bap_mtx);
 
 	if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
@@ -3383,6 +3405,7 @@
 	memset(&wrqu, 0, sizeof(wrqu));
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 	wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
+	wireless_send_event(local->ddev, SIOCGIWAP, &wrqu, NULL);
 
 	/* Disable hardware and firmware */
 	prism2_hw_shutdown(dev, 0);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/hostap/hostap_wlan.h
+++ linux-ec2-2.6.32/drivers/net/wireless/hostap/hostap_wlan.h
@@ -654,7 +654,7 @@
 	rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
 			      * when removing entries from the list.
 			      * TX and RX paths can use read lock. */
-	spinlock_t cmdlock, baplock, lock;
+	spinlock_t cmdlock, baplock, lock, irq_init_lock;
 	struct mutex rid_bap_mtx;
 	u16 infofid; /* MAC buffer id for info frame */
 	/* txfid, intransmitfid, next_txtid, and next_alloc are protected by
--- linux-ec2-2.6.32.orig/drivers/net/wireless/wl12xx/wl1251_debugfs.c
+++ linux-ec2-2.6.32/drivers/net/wireless/wl12xx/wl1251_debugfs.c
@@ -443,7 +443,8 @@
 
 void wl1251_debugfs_reset(struct wl1251 *wl)
 {
-	memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
+	if (wl->stats.fw_stats != NULL)
+		memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
 	wl->stats.retry_count = 0;
 	wl->stats.excessive_retries = 0;
 }
--- linux-ec2-2.6.32.orig/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ linux-ec2-2.6.32/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -160,6 +160,7 @@
 	sdio_disable_func(func);
 release:
 	sdio_release_host(func);
+	wl1251_free_hw(wl);
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -258,7 +258,7 @@
 
 	struct sk_buff_head rx_list;
 	struct list_head rx_tickets;
-	struct list_head rx_packets[IWM_RX_ID_HASH];
+	struct list_head rx_packets[IWM_RX_ID_HASH + 1];
 	struct workqueue_struct *rx_wq;
 	struct work_struct rx_worker;
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -80,8 +80,8 @@
 				    struct fw_desc *desc)
 {
 	if (desc->v_addr)
-		pci_free_consistent(pci_dev, desc->len,
-				    desc->v_addr, desc->p_addr);
+		dma_free_coherent(&pci_dev->dev, desc->len,
+				  desc->v_addr, desc->p_addr);
 	desc->v_addr = NULL;
 	desc->len = 0;
 }
@@ -89,7 +89,8 @@
 static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
 				    struct fw_desc *desc)
 {
-	desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
+	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+					  &desc->p_addr, GFP_KERNEL);
 	return (desc->v_addr != NULL) ? 0 : -ENOMEM;
 }
 
@@ -159,6 +160,12 @@
 	IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
 }
 
+static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
+{
+	IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
+	iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
+}
+
 static inline void iwl_enable_interrupts(struct iwl_priv *priv)
 {
 	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -460,14 +460,15 @@
 static int iwl5000_set_Xtal_calib(struct iwl_priv *priv)
 {
 	struct iwl_calib_xtal_freq_cmd cmd;
-	u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
+	__le16 *xtal_calib =
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
 
 	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
 	cmd.hdr.first_group = 0;
 	cmd.hdr.groups_num = 1;
 	cmd.hdr.data_valid = 1;
-	cmd.cap_pin1 = (u8)xtal_calib[0];
-	cmd.cap_pin2 = (u8)xtal_calib[1];
+	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
+	cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
 	return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
 			     (u8 *)&cmd, sizeof(cmd));
 }
@@ -792,6 +793,13 @@
 
 	iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
 
+	/* make sure all queue are not stopped */
+	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+	for (i = 0; i < 4; i++)
+		atomic_set(&priv->queue_stop_count[i], 0);
+
+	/* reset to 0 to enable all the queue first */
+	priv->txq_ctx_active_msk = 0;
 	/* map qos queues to fifos one-to-one */
 	for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
 		int ac = iwl5000_default_queue_to_tx_fifo[i];
@@ -1263,7 +1271,7 @@
 					scd_ssn , index, txq_id, txq->swq_id);
 
 			freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+			iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
 			if (priv->mac80211_registered &&
 			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
@@ -1292,16 +1300,14 @@
 				   tx_resp->failure_frame);
 
 		freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-		if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
-			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+		iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
 		if (priv->mac80211_registered &&
 		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
 			iwl_wake_queue(priv, txq_id);
 	}
 
-	if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
-		iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+	iwl_txq_check_empty(priv, sta_id, tid, txq_id);
 
 	if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
 		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
@@ -1665,14 +1671,15 @@
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = true,
 	.ht_greenfield_support = true,
+	.use_rts_for_ht = true, /* use rts/cts protection */
 };
 
-struct iwl_cfg iwl5100_bg_cfg = {
-	.name = "5100BG",
+struct iwl_cfg iwl5100_bgn_cfg = {
+	.name = "5100BGN",
 	.fw_name_pre = IWL5000_FW_PRE,
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
+	.sku = IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl5000_ops,
 	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
@@ -1698,7 +1705,6 @@
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
-	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
@@ -1716,6 +1722,7 @@
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
 	.ht_greenfield_support = true,
+	.use_rts_for_ht = true, /* use rts/cts protection */
 };
 
 struct iwl_cfg iwl5350_agn_cfg = {
@@ -1733,6 +1740,7 @@
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = true,
 	.ht_greenfield_support = true,
+	.use_rts_for_ht = true, /* use rts/cts protection */
 };
 
 struct iwl_cfg iwl5150_agn_cfg = {
@@ -1750,6 +1758,23 @@
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
 	.ht_greenfield_support = true,
+	.use_rts_for_ht = true, /* use rts/cts protection */
+};
+
+struct iwl_cfg iwl5150_abg_cfg = {
+	.name = "5150ABG",
+	.fw_name_pre = IWL5150_FW_PRE,
+	.ucode_api_max = IWL5150_UCODE_API_MAX,
+	.ucode_api_min = IWL5150_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G,
+	.ops = &iwl5150_ops,
+	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+	.mod_params = &iwl50_mod_params,
+	.valid_tx_ant = ANT_A,
+	.valid_rx_ant = ANT_AB,
+	.need_pll_cfg = true,
 };
 
 MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -402,10 +402,23 @@
 				      struct iwl_lq_sta *lq_data, u8 tid,
 				      struct ieee80211_sta *sta)
 {
+	int ret;
+
 	if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
 		IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
 				sta->addr, tid);
-		ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
+		ret = ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
+		if (ret == -EAGAIN) {
+			/*
+			 * driver and mac80211 is out of sync
+			 * this might be cause by reloading firmware
+			 * stop the tx ba session here
+			 */
+			IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
+				tid);
+			ret = ieee80211_stop_tx_ba_session(priv->hw, sta->addr, tid,
+						WLAN_BACK_INITIATOR);
+		}
 	}
 }
 
@@ -2180,9 +2193,12 @@
 
 	/* Else we have enough samples; calculate estimate of
 	 * actual average throughput */
-
-	BUG_ON(window->average_tpt != ((window->success_ratio *
-			tbl->expected_tpt[index] + 64) / 128));
+	if (window->average_tpt != ((window->success_ratio *
+			tbl->expected_tpt[index] + 64) / 128)) {
+		IWL_ERR(priv, "expected_tpt should have been calculated by now\n");
+		window->average_tpt = ((window->success_ratio *
+					tbl->expected_tpt[index] + 64) / 128);
+	}
 
 	/* If we are searching for better modulation mode, check success. */
 	if (lq_sta->search_better_tbl &&
@@ -2808,7 +2824,7 @@
 		repeat_rate--;
 	}
 
-	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX;
+	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 	lq_cmd->agg_params.agg_time_limit =
 		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -53,9 +53,10 @@
 extern struct iwl_cfg iwl5300_agn_cfg;
 extern struct iwl_cfg iwl5100_agn_cfg;
 extern struct iwl_cfg iwl5350_agn_cfg;
-extern struct iwl_cfg iwl5100_bg_cfg;
+extern struct iwl_cfg iwl5100_bgn_cfg;
 extern struct iwl_cfg iwl5100_abg_cfg;
 extern struct iwl_cfg iwl5150_agn_cfg;
+extern struct iwl_cfg iwl5150_abg_cfg;
 extern struct iwl_cfg iwl6000h_2agn_cfg;
 extern struct iwl_cfg iwl6000i_2agn_cfg;
 extern struct iwl_cfg iwl6000_3agn_cfg;
@@ -703,7 +704,7 @@
 extern int iwl_queue_space(const struct iwl_queue *q);
 static inline int iwl_queue_used(const struct iwl_queue *q, int i)
 {
-	return q->write_ptr > q->read_ptr ?
+	return q->write_ptr >= q->read_ptr ?
 		(i >= q->read_ptr && i < q->write_ptr) :
 		!(i < q->read_ptr && i >= q->write_ptr);
 }
@@ -1149,7 +1150,7 @@
 	u32 last_beacon_time;
 	u64 last_tsf;
 
-	/* eeprom */
+	/* eeprom -- this is in the card's little endian byte order */
 	u8 *eeprom;
 	int    nvm_device_type;
 	struct iwl_eeprom_calib_info *calib_info;
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-core.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1598,9 +1598,9 @@
 void iwl_free_isr_ict(struct iwl_priv *priv)
 {
 	if (priv->ict_tbl_vir) {
-		pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
-					PAGE_SIZE, priv->ict_tbl_vir,
-					priv->ict_tbl_dma);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+				  priv->ict_tbl_vir, priv->ict_tbl_dma);
 		priv->ict_tbl_vir = NULL;
 	}
 }
@@ -1616,9 +1616,9 @@
 	if (priv->cfg->use_isr_legacy)
 		return 0;
 	/* allocate shrared data table */
-	priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
-						  ICT_COUNT) + PAGE_SIZE,
-						  &priv->ict_tbl_dma);
+	priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
+					(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
+					&priv->ict_tbl_dma, GFP_KERNEL);
 	if (!priv->ict_tbl_vir)
 		return -ENOMEM;
 
@@ -2646,6 +2646,7 @@
 			priv->staging_rxon.flags = 0;
 
 		iwl_set_rxon_channel(priv, conf->channel);
+		iwl_set_rxon_ht(priv, ht_conf);
 
 		iwl_set_flags_for_band(priv, conf->channel->band);
 		spin_unlock_irqrestore(&priv->lock, flags);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-core.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -410,6 +410,8 @@
 int iwl_hw_tx_queue_init(struct iwl_priv *priv,
 			 struct iwl_tx_queue *txq);
 int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+void iwl_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed);
 int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 		      int slots_num, u32 txq_id);
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1044,6 +1044,9 @@
 	/* only Re-enable if diabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
 		iwl_enable_interrupts(priv);
+	/* Re-enable RF_KILL if it occurred */
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(priv);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
@@ -1245,6 +1248,9 @@
 	/* only Re-enable if diabled by irq */
 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
 		iwl_enable_interrupts(priv);
+	/* Re-enable RF_KILL if it occurred */
+	else if (handled & CSR_INT_BIT_RF_KILL)
+		iwl_enable_rfkill_int(priv);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -2358,9 +2364,10 @@
 
 	flush_workqueue(priv->workqueue);
 
-	/* enable interrupts again in order to receive rfkill changes */
+	/* User space software may expect getting rfkill changes
+	 * even if interface is down */
 	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl_enable_interrupts(priv);
+	iwl_enable_rfkill_int(priv);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
@@ -3060,14 +3067,14 @@
 	 * 8. Setup and register mac80211
 	 **********************************/
 
-	/* enable interrupts if needed: hw bug w/a */
+	/* enable rfkill interrupt: hw bug w/a */
 	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
 	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
 		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
 		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
 	}
 
-	iwl_enable_interrupts(priv);
+	iwl_enable_rfkill_int(priv);
 
 	err = iwl_setup_mac(priv);
 	if (err)
@@ -3203,23 +3210,63 @@
 	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
 #endif /* CONFIG_IWL4965 */
 #ifdef CONFIG_IWL5000
-	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
-	{IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
-	{IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
-	{IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
-/* 5350 WiFi/WiMax */
-	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
-	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
-	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
-/* 5150 Wifi/WiMax */
-	{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
-	{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
+/* 5100 Series WiFi */
+	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+
+/* 5300 Series WiFi */
+	{IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+
+/* 5350 Series WiFi/WiMax */
+	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+
+/* 5150 Series Wifi/WiMax */
+	{IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+
+	{IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+	{IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
 /* 6000/6050 Series */
 	{IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)},
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2545,11 +2545,9 @@
 	memset((void *)&priv->hw_params, 0,
 	       sizeof(struct iwl_hw_params));
 
-	priv->shared_virt =
-	    pci_alloc_consistent(priv->pci_dev,
-				 sizeof(struct iwl3945_shared),
-				 &priv->shared_phys);
-
+	priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
+					       sizeof(struct iwl3945_shared),
+					       &priv->shared_phys, GFP_KERNEL);
 	if (!priv->shared_virt) {
 		IWL_ERR(priv, "failed to allocate pci memory\n");
 		mutex_unlock(&priv->mutex);
@@ -2895,6 +2893,7 @@
 	.mod_params = &iwl3945_mod_params,
 	.use_isr_legacy = true,
 	.ht_greenfield_support = false,
+	.broken_powersave = true,
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2909,6 +2908,7 @@
 	.mod_params = &iwl3945_mod_params,
 	.use_isr_legacy = true,
 	.ht_greenfield_support = false,
+	.broken_powersave = true,
 };
 
 struct pci_device_id iwl3945_hw_card_ids[] = {
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -356,10 +356,10 @@
 static void iwl3945_unset_hw_params(struct iwl_priv *priv)
 {
 	if (priv->shared_virt)
-		pci_free_consistent(priv->pci_dev,
-				    sizeof(struct iwl3945_shared),
-				    priv->shared_virt,
-				    priv->shared_phys);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct iwl3945_shared),
+				  priv->shared_virt,
+				  priv->shared_phys);
 }
 
 static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
@@ -562,6 +562,9 @@
 	txq = &priv->txq[txq_id];
 	q = &txq->q;
 
+	if ((iwl_queue_space(q) < q->high_mark))
+		goto drop;
+
 	spin_lock_irqsave(&priv->lock, flags);
 
 	idx = get_cmd_index(q, q->write_ptr, 0);
@@ -1269,10 +1272,10 @@
 		}
 	}
 
-	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			    rxq->dma_addr);
-	pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
-			    rxq->rb_stts, rxq->rb_stts_dma);
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->dma_addr);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
 	rxq->bd = NULL;
 	rxq->rb_stts  = NULL;
 }
@@ -1901,7 +1904,7 @@
 {
 	int i;
 
-	for (i = 0; i < IWL_RATE_COUNT; i++) {
+	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
 		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
 		rates[i].hw_value = i; /* Rate scaling will work on indexes */
 		rates[i].hw_value_short = i;
@@ -3854,9 +3857,11 @@
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		    IEEE80211_HW_NOISE_DBM |
-		    IEEE80211_HW_SPECTRUM_MGMT |
-		    IEEE80211_HW_SUPPORTS_PS |
-		    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+		    IEEE80211_HW_SPECTRUM_MGMT;
+
+	if (!priv->cfg->broken_powersave)
+		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
+			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -715,6 +715,13 @@
 
 	iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
 
+	/* make sure all queue are not stopped */
+	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+	for (i = 0; i < 4; i++)
+		atomic_set(&priv->queue_stop_count[i], 0);
+
+	/* reset to 0 to enable all the queue first */
+	priv->txq_ctx_active_msk = 0;
 	/* Map each Tx/cmd queue to its corresponding fifo */
 	for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
 		int ac = default_queue_to_tx_fifo[i];
@@ -1337,7 +1344,7 @@
 	iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
 
 	/* calculate tx gain adjustment based on power supply voltage */
-	voltage = priv->calib_info->voltage;
+	voltage = le16_to_cpu(priv->calib_info->voltage);
 	init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
 	voltage_compensation =
 	    iwl4965_get_voltage_compensation(voltage, init_voltage);
@@ -2087,7 +2094,7 @@
 	struct ieee80211_tx_info *info;
 	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32  status = le32_to_cpu(tx_resp->u.status);
-	int tid = MAX_TID_COUNT;
+	int tid = MAX_TID_COUNT - 1;
 	int sta_id;
 	int freed;
 	u8 *qc = NULL;
@@ -2134,7 +2141,9 @@
 			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
 					   "%d index %d\n", scd_ssn , index);
 			freed = iwl_tx_queue_reclaim(priv, txq_id, index);
-			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+			if (qc)
+				iwl_free_tfds_in_queue(priv, sta_id,
+						       tid, freed);
 
 			if (priv->mac80211_registered &&
 			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
@@ -2162,13 +2171,14 @@
 
 		freed = iwl_tx_queue_reclaim(priv, txq_id, index);
 		if (qc && likely(sta_id != IWL_INVALID_STATION))
-			priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+			iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
+		else if (sta_id == IWL_INVALID_STATION)
+			IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
 
 		if (priv->mac80211_registered &&
 		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
 			iwl_wake_queue(priv, txq_id);
 	}
-
 	if (qc && likely(sta_id != IWL_INVALID_STATION))
 		iwl_txq_check_empty(priv, sta_id, tid, txq_id);
 
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -92,11 +92,15 @@
 
 static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
 {
-	u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
-						       EEPROM_5000_TEMPERATURE);
-	/* offset =  temperature -  voltage / coef */
-	s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
-	return offset;
+	u16 temperature, voltage;
+	__le16 *temp_calib =
+		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+
+	temperature = le16_to_cpu(temp_calib[0]);
+	voltage = le16_to_cpu(temp_calib[1]);
+
+	/* offset = temp - volt / coeff */
+	return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
 }
 
 /* Fixed (non-configurable) rx data from phy */
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -60,7 +60,8 @@
 static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
 				    struct iwl_dma_ptr *ptr, size_t size)
 {
-	ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
+	ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
+				       GFP_KERNEL);
 	if (!ptr->addr)
 		return -ENOMEM;
 	ptr->size = size;
@@ -73,7 +74,7 @@
 	if (unlikely(!ptr->addr))
 		return;
 
-	pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
+	dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
 	memset(ptr, 0, sizeof(*ptr));
 }
 
@@ -119,6 +120,20 @@
 EXPORT_SYMBOL(iwl_txq_update_write_ptr);
 
 
+void iwl_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed)
+{
+	if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
+		priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+	else {
+		IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
+			priv->stations[sta_id].tid[tid].tfds_in_queue,
+			freed);
+		priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
+	}
+}
+EXPORT_SYMBOL(iwl_free_tfds_in_queue);
+
 /**
  * iwl_tx_queue_free - Deallocate DMA queue.
  * @txq: Transmit queue to deallocate.
@@ -131,7 +146,7 @@
 {
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
 	struct iwl_queue *q = &txq->q;
-	struct pci_dev *dev = priv->pci_dev;
+	struct device *dev = &priv->pci_dev->dev;
 	int i, len;
 
 	if (q->n_bd == 0)
@@ -150,8 +165,8 @@
 
 	/* De-alloc circular buffer of TFDs */
 	if (txq->q.n_bd)
-		pci_free_consistent(dev, priv->hw_params.tfd_size *
-				    txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+		dma_free_coherent(dev, priv->hw_params.tfd_size *
+				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
 
 	/* De-alloc array of per-TFD driver data */
 	kfree(txq->txb);
@@ -180,7 +195,7 @@
 {
 	struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
 	struct iwl_queue *q = &txq->q;
-	struct pci_dev *dev = priv->pci_dev;
+	struct device *dev = &priv->pci_dev->dev;
 	int i, len;
 
 	if (q->n_bd == 0)
@@ -195,8 +210,8 @@
 
 	/* De-alloc circular buffer of TFDs */
 	if (txq->q.n_bd)
-		pci_free_consistent(dev, priv->hw_params.tfd_size *
-				    txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+		dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
+				  txq->tfds, txq->q.dma_addr);
 
 	/* deallocate arrays */
 	kfree(txq->cmd);
@@ -287,7 +302,7 @@
 static int iwl_tx_queue_alloc(struct iwl_priv *priv,
 			      struct iwl_tx_queue *txq, u32 id)
 {
-	struct pci_dev *dev = priv->pci_dev;
+	struct device *dev = &priv->pci_dev->dev;
 	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
 
 	/* Driver private data, only for Tx (not command) queues,
@@ -306,8 +321,8 @@
 
 	/* Circular buffer of transmit frame descriptors (TFDs),
 	 * shared with device */
-	txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr);
-
+	txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
+				       GFP_KERNEL);
 	if (!txq->tfds) {
 		IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
 		goto error;
@@ -776,8 +791,10 @@
 		hdr->seq_ctrl |= cpu_to_le16(seq_number);
 		seq_number += 0x10;
 		/* aggregation is on for this <sta,tid> */
-		if (info->flags & IEEE80211_TX_CTL_AMPDU)
+		if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+		    priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
 			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+		}
 	}
 
 	txq = &priv->txq[txq_id];
@@ -1057,6 +1074,7 @@
 	struct iwl_queue *q = &txq->q;
 	struct iwl_tx_info *tx_info;
 	int nfreed = 0;
+	struct ieee80211_hdr *hdr;
 
 	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
 		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
@@ -1070,6 +1088,14 @@
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
+
+		if (WARN_ON_ONCE(tx_info->skb == NULL))
+			continue;
+
+		hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data;
+		if (ieee80211_is_data_qos(hdr->frame_control))
+			nfreed++;
+
 		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
 		tx_info->skb[0] = NULL;
 
@@ -1077,7 +1103,6 @@
 			priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
 
 		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-		nfreed++;
 	}
 	return nfreed;
 }
@@ -1254,7 +1279,7 @@
 {
 	int tx_fifo_id, txq_id, sta_id, ssn = -1;
 	struct iwl_tid_data *tid_data;
-	int ret, write_ptr, read_ptr;
+	int write_ptr, read_ptr;
 	unsigned long flags;
 
 	if (!ra) {
@@ -1306,13 +1331,17 @@
 	priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
+	/*
+	 * the only reason this call can fail is queue number out of range,
+	 * which can happen if uCode is reloaded and all the station
+	 * information are lost. if it is outside the range, there is no need
+	 * to deactivate the uCode queue, just return "success" to allow
+	 *  mac80211 to clean up it own data.
+	 */
+	priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
 						   tx_fifo_id);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	if (ret)
-		return ret;
-
 	ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
 
 	return 0;
@@ -1454,6 +1483,11 @@
 	sta_id = ba_resp->sta_id;
 	tid = ba_resp->tid;
 	agg = &priv->stations[sta_id].tid[tid].agg;
+	if (unlikely(agg->txq_id != scd_flow)) {
+		IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+			scd_flow, agg->txq_id);
+		return;
+	}
 
 	/* Find index just before block-ack window */
 	index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
@@ -1485,7 +1519,7 @@
 	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
 		/* calculate mac80211 ampdu sw queue to wake */
 		int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
-		priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+		iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
 
 		if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
 		    priv->mac80211_registered &&
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -133,7 +133,7 @@
  *
  */
 struct iwl_eeprom_enhanced_txpwr {
-	u16 reserved;
+	__le16 common;
 	s8 chain_a_max;
 	s8 chain_b_max;
 	s8 chain_c_max;
@@ -347,7 +347,7 @@
 struct iwl_eeprom_calib_info {
 	u8 saturation_power24;	/* half-dBm (e.g. "34" = 17 dBm) */
 	u8 saturation_power52;	/* half-dBm */
-	s16 voltage;		/* signed */
+	__le16 voltage;		/* signed */
 	struct iwl_eeprom_calib_subband_info
 		band_info[EEPROM_TX_POWER_BANDS];
 } __attribute__ ((packed));
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -405,21 +405,6 @@
 
 static int iwl_scan_initiate(struct iwl_priv *priv)
 {
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
-		return -EIO;
-	}
-
-	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
-		return -EAGAIN;
-	}
-
-	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
-		return -EAGAIN;
-	}
-
 	IWL_DEBUG_INFO(priv, "Starting scan...\n");
 	set_bit(STATUS_SCANNING, &priv->status);
 	priv->scan_start = jiffies;
@@ -450,6 +435,18 @@
 		goto out_unlock;
 	}
 
+	if (test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
 	/* We don't schedule scan within next_scan_jiffies period.
 	 * Avoid scanning during possible EAPOL exchange, return
 	 * success immediately.
@@ -500,11 +497,10 @@
 		return;
 
 	mutex_lock(&priv->mutex);
-	if (test_bit(STATUS_SCANNING, &priv->status) ||
-	    test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
-		IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting "
-			"adapter (%dms)\n",
-			jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+	if (test_bit(STATUS_SCANNING, &priv->status) &&
+	    !test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n",
+			       jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
 
 		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
 			iwl_send_scan_abort(priv);
@@ -800,11 +796,11 @@
 	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
 		return;
 
-	mutex_lock(&priv->mutex);
-
-	set_bit(STATUS_SCAN_ABORTING, &priv->status);
-	iwl_send_scan_abort(priv);
+	cancel_delayed_work(&priv->scan_check);
 
+	mutex_lock(&priv->mutex);
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status))
+		iwl_send_scan_abort(priv);
 	mutex_unlock(&priv->mutex);
 }
 EXPORT_SYMBOL(iwl_bg_abort_scan);
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -337,7 +337,7 @@
 	return ret;
 }
 
-static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data)
 {
 	int ret = 0;
 	u32 r;
@@ -370,7 +370,7 @@
 				CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
 		IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
 	}
-	*eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+	*eeprom_data = cpu_to_le16(r >> 16);
 	return 0;
 }
 
@@ -379,7 +379,8 @@
  */
 static bool iwl_is_otp_empty(struct iwl_priv *priv)
 {
-	u16 next_link_addr = 0, link_value;
+	u16 next_link_addr = 0;
+	__le16 link_value;
 	bool is_empty = false;
 
 	/* locate the beginning of OTP link list */
@@ -409,7 +410,8 @@
 static int iwl_find_otp_image(struct iwl_priv *priv,
 					u16 *validblockaddr)
 {
-	u16 next_link_addr = 0, link_value = 0, valid_addr;
+	u16 next_link_addr = 0, valid_addr;
+	__le16 link_value = 0;
 	int usedblocks = 0;
 
 	/* set addressing mode to absolute to traverse the link list */
@@ -429,7 +431,7 @@
 		 * check for more block on the link list
 		 */
 		valid_addr = next_link_addr;
-		next_link_addr = link_value * sizeof(u16);
+		next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
 		IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
 			       usedblocks, next_link_addr);
 		if (iwl_read_otp_word(priv, next_link_addr, &link_value))
@@ -463,7 +465,7 @@
  */
 int iwl_eeprom_init(struct iwl_priv *priv)
 {
-	u16 *e;
+	__le16 *e;
 	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
 	int sz;
 	int ret;
@@ -482,7 +484,7 @@
 		ret = -ENOMEM;
 		goto alloc_err;
 	}
-	e = (u16 *)priv->eeprom;
+	e = (__le16 *)priv->eeprom;
 
 	ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv);
 	if (ret < 0) {
@@ -521,7 +523,7 @@
 		}
 		for (addr = validblockaddr; addr < validblockaddr + sz;
 		     addr += sizeof(u16)) {
-			u16 eeprom_data;
+			__le16 eeprom_data;
 
 			ret = iwl_read_otp_word(priv, addr, &eeprom_data);
 			if (ret)
@@ -545,7 +547,7 @@
 				goto done;
 			}
 			r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
-			e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+			e[addr / 2] = cpu_to_le16(r >> 16);
 		}
 	}
 	ret = 0;
@@ -709,7 +711,8 @@
 	ch_info->ht40_min_power = 0;
 	ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
 	ch_info->ht40_flags = eeprom_ch->flags;
-	ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
+	if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
+		ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ linux-ec2-2.6.32/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -345,10 +345,10 @@
 		}
 	}
 
-	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			    rxq->dma_addr);
-	pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
-			    rxq->rb_stts, rxq->rb_stts_dma);
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->dma_addr);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
 	rxq->bd = NULL;
 	rxq->rb_stts  = NULL;
 }
@@ -357,7 +357,7 @@
 int iwl_rx_queue_alloc(struct iwl_priv *priv)
 {
 	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct pci_dev *dev = priv->pci_dev;
+	struct device *dev = &priv->pci_dev->dev;
 	int i;
 
 	spin_lock_init(&rxq->lock);
@@ -365,12 +365,13 @@
 	INIT_LIST_HEAD(&rxq->rx_used);
 
 	/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
-	rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
+	rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr,
+				     GFP_KERNEL);
 	if (!rxq->bd)
 		goto err_bd;
 
-	rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status),
-					&rxq->rb_stts_dma);
+	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
+					  &rxq->rb_stts_dma, GFP_KERNEL);
 	if (!rxq->rb_stts)
 		goto err_rb;
 
@@ -387,8 +388,8 @@
 	return 0;
 
 err_rb:
-	pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			    rxq->dma_addr);
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->dma_addr);
 err_bd:
 	return -ENOMEM;
 }
--- linux-ec2-2.6.32.orig/drivers/net/atl1e/atl1e_ethtool.c
+++ linux-ec2-2.6.32/drivers/net/atl1e/atl1e_ethtool.c
@@ -394,11 +394,13 @@
 	.get_eeprom             = atl1e_get_eeprom,
 	.set_eeprom             = atl1e_set_eeprom,
 	.get_tx_csum            = atl1e_get_tx_csum,
+	.set_tx_csum            = ethtool_op_set_tx_hw_csum,
 	.get_sg                 = ethtool_op_get_sg,
 	.set_sg                 = ethtool_op_set_sg,
 #ifdef NETIF_F_TSO
 	.get_tso                = ethtool_op_get_tso,
 #endif
+	.set_tso                = ethtool_op_set_tso,
 };
 
 void atl1e_set_ethtool_ops(struct net_device *netdev)
--- linux-ec2-2.6.32.orig/drivers/net/atl1e/atl1e_main.c
+++ linux-ec2-2.6.32/drivers/net/atl1e/atl1e_main.c
@@ -1666,41 +1666,6 @@
 			}
 			return 0;
 		}
-
-		if (offload_type & SKB_GSO_TCPV6) {
-			real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data)
-					+ ntohs(ipv6_hdr(skb)->payload_len));
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
-
-			/* check payload == 0 byte ? */
-			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
-			if (unlikely(skb->len == hdr_len)) {
-				/* only xsum need */
-				dev_warn(&pdev->dev,
-					"IPV6 tso with zero data??\n");
-				goto check_sum;
-			} else {
-				tcp_hdr(skb)->check = ~csum_ipv6_magic(
-						&ipv6_hdr(skb)->saddr,
-						&ipv6_hdr(skb)->daddr,
-						0, IPPROTO_TCP, 0);
-				tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT;
-				hdr_len >>= 1;
-				tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) <<
-					TPD_V6_IPHLLO_SHIFT;
-				tpd->word3 |= ((hdr_len >> 3) &
-					TPD_V6_IPHLHI_MASK) <<
-					TPD_V6_IPHLHI_SHIFT;
-				tpd->word3 |= (tcp_hdrlen(skb) >> 2 &
-					TPD_TCPHDRLEN_MASK) <<
-					TPD_TCPHDRLEN_SHIFT;
-				tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
-					TPD_MSS_MASK) << TPD_MSS_SHIFT;
-					tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
-			}
-		}
-		return 0;
 	}
 
 check_sum:
@@ -2289,7 +2254,6 @@
 		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	netdev->features |= NETIF_F_LLTX;
 	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/leds/Makefile
+++ linux-ec2-2.6.32/drivers/leds/Makefile
@@ -29,6 +29,7 @@
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o
 obj-$(CONFIG_LEDS_PWM)			+= leds-pwm.o
+obj-$(CONFIG_LEDS_DELL_NETBOOKS)	+= dell-led.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
--- linux-ec2-2.6.32.orig/drivers/leds/dell-led.c
+++ linux-ec2-2.6.32/drivers/leds/dell-led.c
@@ -0,0 +1,200 @@
+/*
+ * dell_led.c - Dell LED Driver
+ *
+ * Copyright (C) 2010 Dell Inc.
+ * Louis Davis <louis_davis@dell.com>
+ * Jim Dailey <jim_dailey@dell.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/leds.h>
+
+MODULE_AUTHOR("Louis Davis/Jim Dailey");
+MODULE_DESCRIPTION("Dell LED Control Driver");
+MODULE_LICENSE("GPL");
+
+#define DELL_LED_BIOS_GUID "F6E4FE6E-909D-47cb-8BAB-C9F6F2F8D396"
+MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
+
+/* Error Result Codes: */
+#define INVALID_DEVICE_ID	250
+#define INVALID_PARAMETER	251
+#define INVALID_BUFFER		252
+#define INTERFACE_ERROR		253
+#define UNSUPPORTED_COMMAND	254
+#define UNSPECIFIED_ERROR	255
+
+/* Device ID */
+#define DEVICE_ID_PANEL_BACK	1
+
+/* LED Commands */
+#define CMD_LED_ON	16
+#define CMD_LED_OFF	17
+#define CMD_LED_BLINK	18
+
+struct bios_args {
+	unsigned char length;
+	unsigned char result_code;
+	unsigned char device_id;
+	unsigned char command;
+	unsigned char on_time;
+	unsigned char off_time;
+};
+
+static int dell_led_perform_fn(u8 length,
+		u8 result_code,
+		u8 device_id,
+		u8 command,
+		u8 on_time,
+		u8 off_time)
+{
+	struct bios_args *bios_return;
+	u8 return_code;
+	union acpi_object *obj;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_buffer input;
+	acpi_status status;
+
+	struct bios_args args;
+	args.length = length;
+	args.result_code = result_code;
+	args.device_id = device_id;
+	args.command = command;
+	args.on_time = on_time;
+	args.off_time = off_time;
+
+	input.length = sizeof(struct bios_args);
+	input.pointer = &args;
+
+	status = wmi_evaluate_method(DELL_LED_BIOS_GUID,
+		1,
+		1,
+		&input,
+		&output);
+
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output.pointer;
+
+	if (!obj)
+		return -EINVAL;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return -EINVAL;
+	}
+
+	bios_return = ((struct bios_args *)obj->buffer.pointer);
+	return_code = bios_return->result_code;
+
+	kfree(obj);
+
+	return return_code;
+}
+
+static int led_on(void)
+{
+	return dell_led_perform_fn(3,	/* Length of command */
+		INTERFACE_ERROR,	/* Init to  INTERFACE_ERROR */
+		DEVICE_ID_PANEL_BACK,	/* Device ID */
+		CMD_LED_ON,		/* Command */
+		0,			/* not used */
+		0);			/* not used */
+}
+
+static int led_off(void)
+{
+	return dell_led_perform_fn(3,	/* Length of command */
+		INTERFACE_ERROR,	/* Init to  INTERFACE_ERROR */
+		DEVICE_ID_PANEL_BACK,	/* Device ID */
+		CMD_LED_OFF,		/* Command */
+		0,			/* not used */
+		0);			/* not used */
+}
+
+static int led_blink(unsigned char on_eighths,
+		unsigned char off_eighths)
+{
+	return dell_led_perform_fn(5,	/* Length of command */
+		INTERFACE_ERROR,	/* Init to  INTERFACE_ERROR */
+		DEVICE_ID_PANEL_BACK,	/* Device ID */
+		CMD_LED_BLINK,		/* Command */
+		on_eighths,		/* blink on in eigths of a second */
+		off_eighths);		/* blink off in eights of a second */
+}
+
+static void dell_led_set(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	if (value == LED_OFF)
+		led_off();
+	else
+		led_on();
+}
+
+static int dell_led_blink(struct led_classdev *led_cdev,
+		unsigned long *delay_on,
+		unsigned long *delay_off)
+{
+	unsigned long on_eighths;
+	unsigned long off_eighths;
+
+	/* The Dell LED delay is based on 125ms intervals.
+	   Need to round up to next interval. */
+
+	on_eighths = (*delay_on + 124) / 125;
+	if (0 == on_eighths)
+		on_eighths = 1;
+	if (on_eighths > 255)
+		on_eighths = 255;
+	*delay_on = on_eighths * 125;
+
+	off_eighths = (*delay_off + 124) / 125;
+	if (0 == off_eighths)
+		off_eighths = 1;
+	if (off_eighths > 255)
+		off_eighths = 255;
+	*delay_off = off_eighths * 125;
+
+	led_blink(on_eighths, off_eighths);
+
+	return 0;
+}
+
+static struct led_classdev dell_led = {
+	.name		= "dell::lid",
+	.brightness	= LED_OFF,
+	.max_brightness = 1,
+	.brightness_set = dell_led_set,
+	.blink_set	= dell_led_blink,
+	.flags		= LED_CORE_SUSPENDRESUME,
+};
+
+static int __init dell_led_init(void)
+{
+	int error = 0;
+
+	if (!wmi_has_guid(DELL_LED_BIOS_GUID))
+		return -ENODEV;
+
+	error = led_off();
+	if (error != 0)
+		return -ENODEV;
+
+	return led_classdev_register(NULL, &dell_led);
+}
+
+static void __exit dell_led_exit(void)
+{
+	led_classdev_unregister(&dell_led);
+
+	led_off();
+}
+
+module_init(dell_led_init);
+module_exit(dell_led_exit);
--- linux-ec2-2.6.32.orig/drivers/leds/leds-gpio.c
+++ linux-ec2-2.6.32/drivers/leds/leds-gpio.c
@@ -211,7 +211,6 @@
 					const struct of_device_id *match)
 {
 	struct device_node *np = ofdev->node, *child;
-	struct gpio_led led;
 	struct gpio_led_of_platform_data *pdata;
 	int count = 0, ret;
 
@@ -226,8 +225,8 @@
 	if (!pdata)
 		return -ENOMEM;
 
-	memset(&led, 0, sizeof(led));
 	for_each_child_of_node(np, child) {
+		struct gpio_led led = {};
 		enum of_gpio_flags flags;
 		const char *state;
 
--- linux-ec2-2.6.32.orig/drivers/leds/Kconfig
+++ linux-ec2-2.6.32/drivers/leds/Kconfig
@@ -236,6 +236,13 @@
 	  This option enables support for BD2802GU RGB LED driver chips
 	  accessed via the I2C bus.
 
+config LEDS_DELL_NETBOOKS
+	tristate "External LED on Dell Business Netbooks"
+	depends on LEDS_CLASS && X86 && ACPI_WMI
+	help
+	  This adds support for the Latitude 2100 and similar
+	  notebooks that have an external LED.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
--- linux-ec2-2.6.32.orig/drivers/misc/enclosure.c
+++ linux-ec2-2.6.32/drivers/misc/enclosure.c
@@ -284,8 +284,11 @@
 	cdev->groups = enclosure_groups;
 
 	err = device_register(cdev);
-	if (err)
-		ERR_PTR(err);
+	if (err) {
+		ecomp->number = -1;
+		put_device(cdev);
+		return ERR_PTR(err);
+	}
 
 	return ecomp;
 }
@@ -391,6 +394,7 @@
 	[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
 	[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
 	[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+	[ENCLOSURE_STATUS_MAX] = NULL,
 };
 
 static const char *const enclosure_type [] = {
--- linux-ec2-2.6.32.orig/drivers/misc/ep93xx_pwm.c
+++ linux-ec2-2.6.32/drivers/misc/ep93xx_pwm.c
@@ -248,11 +248,11 @@
 
 static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
 static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
-static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
-static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
-static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
 
 static struct attribute *ep93xx_pwm_attrs[] = {
--- linux-ec2-2.6.32.orig/drivers/misc/sgi-xp/xpc_uv.c
+++ linux-ec2-2.6.32/drivers/misc/sgi-xp/xpc_uv.c
@@ -203,6 +203,7 @@
 	enum xp_retval xp_ret;
 	int ret;
 	int nid;
+	int nasid;
 	int pg_order;
 	struct page *page;
 	struct xpc_gru_mq_uv *mq;
@@ -258,9 +259,11 @@
 		goto out_5;
 	}
 
+	nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu));
+
 	mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value;
 	ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size,
-				       nid, mmr_value->vector, mmr_value->dest);
+				     nasid, mmr_value->vector, mmr_value->dest);
 	if (ret != 0) {
 		dev_err(xpc_part, "gru_create_message_queue() returned "
 			"error=%d\n", ret);
@@ -409,6 +412,7 @@
 static void
 xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
 			      struct xpc_activate_mq_msghdr_uv *msg_hdr,
+			      int part_setup,
 			      int *wakeup_hb_checker)
 {
 	unsigned long irq_flags;
@@ -473,6 +477,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
 		struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_closerequest_uv,
 				   hdr);
@@ -489,6 +496,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
 		struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_closereply_uv,
 				   hdr);
@@ -503,6 +513,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
 		struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_openrequest_uv,
 				   hdr);
@@ -520,6 +533,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
 		struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				   xpc_activate_mq_msg_chctl_openreply_uv, hdr);
 		args = &part->remote_openclose_args[msg->ch_number];
@@ -537,6 +553,9 @@
 	case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
 		struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
 
+		if (!part_setup)
+			break;
+
 		msg = container_of(msg_hdr, struct
 				xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
 		spin_lock_irqsave(&part->chctl_lock, irq_flags);
@@ -613,6 +632,7 @@
 
 			part_referenced = xpc_part_ref(part);
 			xpc_handle_activate_mq_msg_uv(part, msg_hdr,
+						      part_referenced,
 						      &wakeup_hb_checker);
 			if (part_referenced)
 				xpc_part_deref(part);
@@ -945,11 +965,13 @@
 		head->first = first->next;
 		if (head->first == NULL)
 			head->last = NULL;
+
+		head->n_entries--;
+		BUG_ON(head->n_entries < 0);
+
+		first->next = NULL;
 	}
-	head->n_entries--;
-	BUG_ON(head->n_entries < 0);
 	spin_unlock_irqrestore(&head->lock, irq_flags);
-	first->next = NULL;
 	return first;
 }
 
@@ -1018,7 +1040,8 @@
 	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
 				      XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
 
-	while (part->sn.uv.remote_act_state != XPC_P_AS_ACTIVATING) {
+	while (!((part->sn.uv.remote_act_state == XPC_P_AS_ACTIVATING) ||
+		 (part->sn.uv.remote_act_state == XPC_P_AS_ACTIVE))) {
 
 		dev_dbg(xpc_part, "waiting to make first contact with "
 			"partition %d\n", XPC_PARTID(part));
@@ -1421,7 +1444,6 @@
 	msg_slot = ch_uv->recv_msg_slots +
 	    (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
 
-	BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
 	BUG_ON(msg_slot->hdr.size != 0);
 
 	memcpy(msg_slot, msg, msg->hdr.size);
@@ -1645,8 +1667,6 @@
 			       sizeof(struct xpc_notify_mq_msghdr_uv));
 	if (ret != xpSuccess)
 		XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
-
-	msg->hdr.msg_slot_number += ch->remote_nentries;
 }
 
 static struct xpc_arch_operations xpc_arch_ops_uv = {
--- linux-ec2-2.6.32.orig/drivers/misc/sgi-xp/xpc_partition.c
+++ linux-ec2-2.6.32/drivers/misc/sgi-xp/xpc_partition.c
@@ -433,18 +433,23 @@
 	 * nodes that can comprise an access protection grouping. The access
 	 * protection is in regards to memory, IOI and IPI.
 	 */
-	max_regions = 64;
 	region_size = xp_region_size;
 
-	switch (region_size) {
-	case 128:
-		max_regions *= 2;
-	case 64:
-		max_regions *= 2;
-	case 32:
-		max_regions *= 2;
-		region_size = 16;
-		DBUG_ON(!is_shub2());
+	if (is_uv())
+		max_regions = 256;
+	else {
+		max_regions = 64;
+
+		switch (region_size) {
+		case 128:
+			max_regions *= 2;
+		case 64:
+			max_regions *= 2;
+		case 32:
+			max_regions *= 2;
+			region_size = 16;
+			DBUG_ON(!is_shub2());
+		}
 	}
 
 	for (region = 0; region < max_regions; region++) {
--- linux-ec2-2.6.32.orig/drivers/dma/at_hdmac.c
+++ linux-ec2-2.6.32/drivers/dma/at_hdmac.c
@@ -815,7 +815,7 @@
 	dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n",
 			cookie, done ? *done : 0, used ? *used : 0);
 
-	spin_lock_bh(atchan->lock);
+	spin_lock_bh(&atchan->lock);
 
 	last_complete = atchan->completed_cookie;
 	last_used = chan->cookie;
@@ -830,7 +830,7 @@
 		ret = dma_async_is_complete(cookie, last_complete, last_used);
 	}
 
-	spin_unlock_bh(atchan->lock);
+	spin_unlock_bh(&atchan->lock);
 
 	if (done)
 		*done = last_complete;
--- linux-ec2-2.6.32.orig/drivers/dma/mv_xor.c
+++ linux-ec2-2.6.32/drivers/dma/mv_xor.c
@@ -161,7 +161,7 @@
 
 static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
 {
-	u32 val = (1 << (1 + (chan->idx * 16)));
+	u32 val = ~(1 << (chan->idx * 16));
 	dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
 	__raw_writel(val, XOR_INTR_CAUSE(chan));
 }
@@ -448,7 +448,7 @@
 static void mv_xor_tasklet(unsigned long data)
 {
 	struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
-	__mv_xor_slot_cleanup(chan);
+	mv_xor_slot_cleanup(chan);
 }
 
 static struct mv_xor_desc_slot *
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/dma_v3.c
+++ linux-ec2-2.6.32/drivers/dma/ioat/dma_v3.c
@@ -650,9 +650,11 @@
 
 	num_descs = ioat2_xferlen_to_descs(ioat, len);
 	/* we need 2x the number of descriptors to cover greater than 3
-	 * sources
+	 * sources (we need 1 extra source in the q-only continuation
+	 * case and 3 extra sources in the p+q continuation case.
 	 */
-	if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) {
+	if (src_cnt + dmaf_p_disabled_continue(flags) > 3 ||
+	    (dmaf_continue(flags) && !dmaf_p_disabled_continue(flags))) {
 		with_ext = 1;
 		num_descs *= 2;
 	} else
@@ -1128,6 +1130,45 @@
 	return 0;
 }
 
+static int ioat3_reset_hw(struct ioat_chan_common *chan)
+{
+	/* throw away whatever the channel was doing and get it
+	 * initialized, with ioat3 specific workarounds
+	 */
+	struct ioatdma_device *device = chan->device;
+	struct pci_dev *pdev = device->pdev;
+	u32 chanerr;
+	u16 dev_id;
+	int err;
+
+	ioat2_quiesce(chan, msecs_to_jiffies(100));
+
+	chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
+	writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
+
+	/* -= IOAT ver.3 workarounds =- */
+	/* Write CHANERRMSK_INT with 3E07h to mask out the errors
+	 * that can cause stability issues for IOAT ver.3, and clear any
+	 * pending errors
+	 */
+	pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);
+	err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr);
+	if (err) {
+		dev_err(&pdev->dev, "channel error register unreachable\n");
+		return err;
+	}
+	pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr);
+
+	/* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
+	 * (workaround for spurious config parity error after restart)
+	 */
+	pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);
+	if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)
+		pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);
+
+	return ioat2_reset_sync(chan, msecs_to_jiffies(200));
+}
+
 int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
 {
 	struct pci_dev *pdev = device->pdev;
@@ -1137,10 +1178,10 @@
 	struct ioat_chan_common *chan;
 	bool is_raid_device = false;
 	int err;
-	u16 dev_id;
 	u32 cap;
 
 	device->enumerate_channels = ioat2_enumerate_channels;
+	device->reset_hw = ioat3_reset_hw;
 	device->self_test = ioat3_dma_self_test;
 	dma = &device->common;
 	dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock;
@@ -1216,19 +1257,6 @@
 	dma->device_prep_dma_xor_val = NULL;
 	#endif
 
-	/* -= IOAT ver.3 workarounds =- */
-	/* Write CHANERRMSK_INT with 3E07h to mask out the errors
-	 * that can cause stability issues for IOAT ver.3
-	 */
-	pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07);
-
-	/* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
-	 * (workaround for spurious config parity error after restart)
-	 */
-	pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id);
-	if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0)
-		pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10);
-
 	err = ioat_probe(device);
 	if (err)
 		return err;
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/registers.h
+++ linux-ec2-2.6.32/drivers/dma/ioat/registers.h
@@ -27,6 +27,7 @@
 
 #define IOAT_PCI_DEVICE_ID_OFFSET		0x02
 #define IOAT_PCI_DMAUNCERRSTS_OFFSET		0x148
+#define IOAT_PCI_CHANERR_INT_OFFSET		0x180
 #define IOAT_PCI_CHANERRMASK_INT_OFFSET		0x184
 
 /* MMIO Device Registers */
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/dma.h
+++ linux-ec2-2.6.32/drivers/dma/ioat/dma.h
@@ -60,6 +60,7 @@
  * @dca: direct cache access context
  * @intr_quirk: interrupt setup quirk (for ioat_v1 devices)
  * @enumerate_channels: hw version specific channel enumeration
+ * @reset_hw: hw version specific channel (re)initialization
  * @cleanup_tasklet: select between the v2 and v3 cleanup routines
  * @timer_fn: select between the v2 and v3 timer watchdog routines
  * @self_test: hardware version specific self test for each supported op type
@@ -78,6 +79,7 @@
 	struct dca_provider *dca;
 	void (*intr_quirk)(struct ioatdma_device *device);
 	int (*enumerate_channels)(struct ioatdma_device *device);
+	int (*reset_hw)(struct ioat_chan_common *chan);
 	void (*cleanup_tasklet)(unsigned long data);
 	void (*timer_fn)(unsigned long data);
 	int (*self_test)(struct ioatdma_device *device);
@@ -264,6 +266,22 @@
 	writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
 }
 
+static inline void ioat_reset(struct ioat_chan_common *chan)
+{
+	u8 ver = chan->device->version;
+
+	writeb(IOAT_CHANCMD_RESET, chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
+}
+
+static inline bool ioat_reset_pending(struct ioat_chan_common *chan)
+{
+	u8 ver = chan->device->version;
+	u8 cmd;
+
+	cmd = readb(chan->reg_base + IOAT_CHANCMD_OFFSET(ver));
+	return (cmd & IOAT_CHANCMD_RESET) == IOAT_CHANCMD_RESET;
+}
+
 static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr)
 {
 	struct ioat_chan_common *chan = &ioat->base;
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/dma_v2.h
+++ linux-ec2-2.6.32/drivers/dma/ioat/dma_v2.h
@@ -185,6 +185,8 @@
 void __ioat2_issue_pending(struct ioat2_dma_chan *ioat);
 void ioat2_cleanup_tasklet(unsigned long data);
 void ioat2_timer_event(unsigned long data);
+int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo);
+int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo);
 extern struct kobj_type ioat2_ktype;
 extern struct kmem_cache *ioat2_cache;
 #endif /* IOATDMA_V2_H */
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/dma.c
+++ linux-ec2-2.6.32/drivers/dma/ioat/dma.c
@@ -1032,7 +1032,7 @@
 	dma->dev = &pdev->dev;
 
 	if (!dma->chancnt) {
-		dev_err(dev, "zero channels detected\n");
+		dev_err(dev, "channel enumeration error\n");
 		goto err_setup_interrupts;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/dma/ioat/dma_v2.c
+++ linux-ec2-2.6.32/drivers/dma/ioat/dma_v2.c
@@ -239,20 +239,50 @@
 		__ioat2_start_null_desc(ioat);
 }
 
-static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
+int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo)
 {
-	struct ioat_chan_common *chan = &ioat->base;
-	unsigned long phys_complete;
+	unsigned long end = jiffies + tmo;
+	int err = 0;
 	u32 status;
 
 	status = ioat_chansts(chan);
 	if (is_ioat_active(status) || is_ioat_idle(status))
 		ioat_suspend(chan);
 	while (is_ioat_active(status) || is_ioat_idle(status)) {
+		if (tmo && time_after(jiffies, end)) {
+			err = -ETIMEDOUT;
+			break;
+		}
 		status = ioat_chansts(chan);
 		cpu_relax();
 	}
 
+	return err;
+}
+
+int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo)
+{
+	unsigned long end = jiffies + tmo;
+	int err = 0;
+
+	ioat_reset(chan);
+	while (ioat_reset_pending(chan)) {
+		if (end && time_after(jiffies, end)) {
+			err = -ETIMEDOUT;
+			break;
+		}
+		cpu_relax();
+	}
+
+	return err;
+}
+
+static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
+{
+	struct ioat_chan_common *chan = &ioat->base;
+	unsigned long phys_complete;
+
+	ioat2_quiesce(chan, 0);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
 		__cleanup(ioat, phys_complete);
 
@@ -318,6 +348,19 @@
 	spin_unlock_bh(&chan->cleanup_lock);
 }
 
+static int ioat2_reset_hw(struct ioat_chan_common *chan)
+{
+	/* throw away whatever the channel was doing and get it initialized */
+	u32 chanerr;
+
+	ioat2_quiesce(chan, msecs_to_jiffies(100));
+
+	chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
+	writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
+
+	return ioat2_reset_sync(chan, msecs_to_jiffies(200));
+}
+
 /**
  * ioat2_enumerate_channels - find and initialize the device's channels
  * @device: the device to be enumerated
@@ -360,6 +403,10 @@
 				  (unsigned long) ioat);
 		ioat->xfercap_log = xfercap_log;
 		spin_lock_init(&ioat->ring_lock);
+		if (device->reset_hw(&ioat->base)) {
+			i = 0;
+			break;
+		}
 	}
 	dma->chancnt = i;
 	return i;
@@ -467,7 +514,6 @@
 	struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
 	struct ioat_chan_common *chan = &ioat->base;
 	struct ioat_ring_ent **ring;
-	u32 chanerr;
 	int order;
 
 	/* have we already been set up? */
@@ -477,12 +523,6 @@
 	/* Setup register to interrupt and write completion status on error */
 	writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET);
 
-	chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
-	if (chanerr) {
-		dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr);
-		writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET);
-	}
-
 	/* allocate a completion writeback area */
 	/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
 	chan->completion = pci_pool_alloc(chan->device->completion_pool,
@@ -746,13 +786,7 @@
 	tasklet_disable(&chan->cleanup_task);
 	del_timer_sync(&chan->timer);
 	device->cleanup_tasklet((unsigned long) ioat);
-
-	/* Delay 100ms after reset to allow internal DMA logic to quiesce
-	 * before removing DMA descriptor resources.
-	 */
-	writeb(IOAT_CHANCMD_RESET,
-	       chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version));
-	mdelay(100);
+	device->reset_hw(chan);
 
 	spin_lock_bh(&ioat->ring_lock);
 	descs = ioat2_ring_space(ioat);
@@ -839,6 +873,7 @@
 	int err;
 
 	device->enumerate_channels = ioat2_enumerate_channels;
+	device->reset_hw = ioat2_reset_hw;
 	device->cleanup_tasklet = ioat2_cleanup_tasklet;
 	device->timer_fn = ioat2_timer_event;
 	device->self_test = ioat_dma_self_test;
--- linux-ec2-2.6.32.orig/drivers/virtio/virtio_pci.c
+++ linux-ec2-2.6.32/drivers/virtio/virtio_pci.c
@@ -95,11 +95,6 @@
 
 MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
 
-/* A PCI device has it's own struct device and so does a virtio device so
- * we create a place for the virtio devices to show up in sysfs.  I think it
- * would make more sense for virtio to not insist on having it's own device. */
-static struct device *virtio_pci_root;
-
 /* Convert a generic virtio device to our structure */
 static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
 {
@@ -473,7 +468,8 @@
 
 	list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
 		info = vq->priv;
-		if (vp_dev->per_vq_vectors)
+		if (vp_dev->per_vq_vectors &&
+			info->msix_vector != VIRTIO_MSI_NO_VECTOR)
 			free_irq(vp_dev->msix_entries[info->msix_vector].vector,
 				 vq);
 		vp_del_vq(vq);
@@ -627,13 +623,16 @@
 	if (vp_dev == NULL)
 		return -ENOMEM;
 
-	vp_dev->vdev.dev.parent = virtio_pci_root;
+	vp_dev->vdev.dev.parent = &pci_dev->dev;
 	vp_dev->vdev.dev.release = virtio_pci_release_dev;
 	vp_dev->vdev.config = &virtio_pci_config_ops;
 	vp_dev->pci_dev = pci_dev;
 	INIT_LIST_HEAD(&vp_dev->virtqueues);
 	spin_lock_init(&vp_dev->lock);
 
+	/* Disable MSI/MSIX to bring device to a known good state. */
+	pci_msi_off(pci_dev);
+
 	/* enable the device */
 	err = pci_enable_device(pci_dev);
 	if (err)
@@ -648,6 +647,7 @@
 		goto out_req_regions;
 
 	pci_set_drvdata(pci_dev, vp_dev);
+	pci_set_master(pci_dev);
 
 	/* we use the subsystem vendor/device id as the virtio vendor/device
 	 * id.  this allows us to use the same PCI vendor/device id for all
@@ -711,17 +711,7 @@
 
 static int __init virtio_pci_init(void)
 {
-	int err;
-
-	virtio_pci_root = root_device_register("virtio-pci");
-	if (IS_ERR(virtio_pci_root))
-		return PTR_ERR(virtio_pci_root);
-
-	err = pci_register_driver(&virtio_pci_driver);
-	if (err)
-		root_device_unregister(virtio_pci_root);
-
-	return err;
+	return pci_register_driver(&virtio_pci_driver);
 }
 
 module_init(virtio_pci_init);
@@ -729,7 +719,6 @@
 static void __exit virtio_pci_exit(void)
 {
 	pci_unregister_driver(&virtio_pci_driver);
-	root_device_unregister(virtio_pci_root);
 }
 
 module_exit(virtio_pci_exit);
--- linux-ec2-2.6.32.orig/drivers/hid/hid-stantum.c
+++ linux-ec2-2.6.32/drivers/hid/hid-stantum.c
@@ -0,0 +1,283 @@
+/*
+ *  HID driver for Stantum multitouch panels
+ *
+ *  Copyright (c) 2009 Stephane Chatty <chatty@enac.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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("Stantum HID multitouch panels");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+struct stantum_data {
+	__s32 x, y, z, w, h;	/* x, y, pressure, width, height */
+	__u16 id;		/* touch id */
+	bool valid;		/* valid finger data, or just placeholder? */
+	bool first;		/* first finger in the HID packet? */
+	bool activity;		/* at least one active finger so far? */
+};
+
+static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+		case HID_DG_CONFIDENCE:
+		case HID_DG_INPUTMODE:
+		case HID_DG_DEVICEINDEX:
+		case HID_DG_CONTACTCOUNT:
+		case HID_DG_CONTACTMAX:
+			return -1;
+
+		case HID_DG_TIPSWITCH:
+			/* touchscreen emulation */
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			return 1;
+
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+					1, 1, 0, 0);
+			return 1;
+		case HID_DG_TIPPRESSURE:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_PRESSURE);
+			return 1;
+
+		case HID_DG_CONTACTID:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TRACKING_ID);
+			return 1;
+
+		}
+		return 0;
+
+	case 0xff000000:
+		/* no input-oriented meaning */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+
+/*
+ * this function is called when a whole finger has been parsed,
+ * so that it can decide what to send to the input layer.
+ */
+static void stantum_filter_event(struct stantum_data *sd,
+					struct input_dev *input)
+{
+	bool wide;
+
+	if (!sd->valid) {
+		/*
+		 * touchscreen emulation: if the first finger is not valid and
+		 * there previously was finger activity, this is a release
+		 */
+		if (sd->first && sd->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 0);
+			sd->activity = false;
+		}
+		return;
+	}
+
+	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id);
+	input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x);
+	input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y);
+
+	wide = (sd->w > sd->h);
+	input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
+	input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h);
+	input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w);
+
+	input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z);
+
+	input_mt_sync(input);
+	sd->valid = false;
+
+	/* touchscreen emulation */
+	if (sd->first) {
+		if (!sd->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 1);
+			sd->activity = true;
+		}
+		input_event(input, EV_ABS, ABS_X, sd->x);
+		input_event(input, EV_ABS, ABS_Y, sd->y);
+	}
+	sd->first = false;
+}
+
+
+static int stantum_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct stantum_data *sd = hid_get_drvdata(hid);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		struct input_dev *input = field->hidinput->input;
+
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			/* this is the last field in a finger */
+			stantum_filter_event(sd, input);
+			break;
+		case HID_DG_WIDTH:
+			sd->w = value;
+			break;
+		case HID_DG_HEIGHT:
+			sd->h = value;
+			break;
+		case HID_GD_X:
+			sd->x = value;
+			break;
+		case HID_GD_Y:
+			sd->y = value;
+			break;
+		case HID_DG_TIPPRESSURE:
+			sd->z = value;
+			break;
+		case HID_DG_CONTACTID:
+			sd->id = value;
+			break;
+		case HID_DG_CONFIDENCE:
+			sd->valid = !!value;
+			break;
+		case 0xff000002:
+			/* this comes only before the first finger */
+			sd->first = true;
+			break;
+
+		default:
+			/* ignore the others */
+			return 1;
+		}
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static int stantum_probe(struct hid_device *hdev,
+				const struct hid_device_id *id)
+{
+	int ret;
+	struct stantum_data *sd;
+
+	sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL);
+	if (!sd) {
+		dev_err(&hdev->dev, "cannot allocate Stantum data\n");
+		return -ENOMEM;
+	}
+	sd->valid = false;
+	sd->first = false;
+	sd->activity = false;
+	hid_set_drvdata(hdev, sd);
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	if (ret)
+		kfree(sd);
+
+	return ret;
+}
+
+static void stantum_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id stantum_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, stantum_devices);
+
+static const struct hid_usage_id stantum_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver stantum_driver = {
+	.name = "stantum",
+	.id_table = stantum_devices,
+	.probe = stantum_probe,
+	.remove = stantum_remove,
+	.input_mapping = stantum_input_mapping,
+	.input_mapped = stantum_input_mapped,
+	.usage_table = stantum_grabbed_usages,
+	.event = stantum_event,
+};
+
+static int __init stantum_init(void)
+{
+	return hid_register_driver(&stantum_driver);
+}
+
+static void __exit stantum_exit(void)
+{
+	hid_unregister_driver(&stantum_driver);
+}
+
+module_init(stantum_init);
+module_exit(stantum_exit);
+
--- linux-ec2-2.6.32.orig/drivers/hid/hid-gyration.c
+++ linux-ec2-2.6.32/drivers/hid/hid-gyration.c
@@ -53,10 +53,13 @@
 static int gyration_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
-	struct input_dev *input = field->hidinput->input;
+
+	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
+		return 0;
 
 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
 			(usage->hid & 0xff) == 0x82) {
+		struct input_dev *input = field->hidinput->input;
 		input_event(input, usage->type, usage->code, 1);
 		input_sync(input);
 		input_event(input, usage->type, usage->code, 0);
@@ -70,6 +73,7 @@
 static const struct hid_device_id gyration_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, gyration_devices);
--- linux-ec2-2.6.32.orig/drivers/hid/hid-cypress.c
+++ linux-ec2-2.6.32/drivers/hid/hid-cypress.c
@@ -126,6 +126,8 @@
 		.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2),
 		.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3),
+		.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
 		.driver_data = CP_2WHEEL_MOUSE_HACK },
 	{ }
--- linux-ec2-2.6.32.orig/drivers/hid/Makefile
+++ linux-ec2-2.6.32/drivers/hid/Makefile
@@ -19,6 +19,7 @@
 	hid-logitech-objs	+= hid-lg2ff.o
 endif
 
+obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
@@ -32,13 +33,17 @@
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
+obj-$(CONFIG_HID_ORTEK)		+= hid-ortek.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
+obj-$(CONFIG_HID_MOSART)	+= hid-mosart.o
 obj-$(CONFIG_HID_NTRIG)		+= hid-ntrig.o
+obj-$(CONFIG_HID_QUANTA)	+= hid-quanta.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
 obj-$(CONFIG_HID_SONY)		+= hid-sony.o
+obj-$(CONFIG_HID_STANTUM)	+= hid-stantum.o
 obj-$(CONFIG_HID_SUNPLUS)	+= hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)	+= hid-gaff.o
 obj-$(CONFIG_HID_THRUSTMASTER)	+= hid-tmff.o
--- linux-ec2-2.6.32.orig/drivers/hid/hid-input.c
+++ linux-ec2-2.6.32/drivers/hid/hid-input.c
@@ -193,12 +193,17 @@
 		break;
 
 	case HID_UP_BUTTON:
-		code = ((usage->hid - 1) & 0xf);
+		code = ((usage->hid - 1) & HID_USAGE);
 
 		switch (field->application) {
 		case HID_GD_MOUSE:
 		case HID_GD_POINTER:  code += 0x110; break;
-		case HID_GD_JOYSTICK: code += 0x120; break;
+		case HID_GD_JOYSTICK:
+				      if (code <= 0xf)
+					      code += BTN_JOYSTICK;
+				      else
+					      code += BTN_TRIGGER_HAPPY;
+				      break;
 		case HID_GD_GAMEPAD:  code += 0x130; break;
 		default:
 			switch (field->physical) {
--- linux-ec2-2.6.32.orig/drivers/hid/hid-ids.h
+++ linux-ec2-2.6.32/drivers/hid/hid-ids.h
@@ -18,6 +18,9 @@
 #ifndef HID_IDS_H_FILE
 #define HID_IDS_H_FILE
 
+#define USB_VENDOR_ID_3M		0x0596
+#define USB_DEVICE_ID_3M1968		0x0500
+
 #define USB_VENDOR_ID_A4TECH		0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 #define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
@@ -88,14 +91,26 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI	0x0236
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO	0x0237
 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS	0x0238
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI	0x023f
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO	0x0240
+#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS	0x0241
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
+#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
+#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
 #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL	0x8241
 #define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
 
-#define USB_VENDOR_ID_ASUS		0x0b05
-#define USB_DEVICE_ID_ASUS_LCM		0x1726
-#define USB_DEVICE_ID_ASUS_LCM2		0x175b
+#define USB_VENDOR_ID_ASUS		0x0486
+#define USB_DEVICE_ID_ASUS_T91MT	0x0185
+
+#define USB_VENDOR_ID_ASUSTEK		0x0b05
+#define USB_DEVICE_ID_ASUSTEK_LCM	0x1726
+#define USB_DEVICE_ID_ASUSTEK_LCM2	0x175b
 
 #define USB_VENDOR_ID_ATEN		0x0557
 #define USB_DEVICE_ID_ATEN_UC100KM	0x2004
@@ -145,6 +160,7 @@
 #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE	0x7417
 #define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
 #define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
+#define USB_DEVICE_ID_CYPRESS_BARCODE_3	0xbca1
 
 #define USB_VENDOR_ID_DEALEXTREAME	0x10c5
 #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701	0x819a
@@ -248,6 +264,7 @@
 #define USB_VENDOR_ID_GYRATION		0x0c16
 #define USB_DEVICE_ID_GYRATION_REMOTE	0x0002
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
+#define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
 
 #define USB_VENDOR_ID_HAPP		0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING	0x0010
@@ -346,12 +363,18 @@
 #define USB_VENDOR_ID_NEC		0x073e
 #define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
 
+#define USB_VENDOR_ID_NEXTWINDOW	0x1926
+#define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN	0x0003
+
 #define USB_VENDOR_ID_NTRIG                0x1b96
 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN   0x0001
 
 #define USB_VENDOR_ID_ONTRAK		0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
+#define USB_VENDOR_ID_ORTEK		0x05a4
+#define USB_DEVICE_ID_ORTEK_WKB2000	0x2000
+
 #define USB_VENDOR_ID_PANJIT		0x134c
 
 #define USB_VENDOR_ID_PANTHERLORD	0x0810
@@ -372,6 +395,10 @@
 #define USB_VENDOR_ID_SAITEK		0x06a3
 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
 
+#define USB_VENDOR_ID_QUANTA		0x0408
+#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH	0x3000
+#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN	0x3001
+
 #define USB_VENDOR_ID_SAMSUNG		0x0419
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
 
@@ -383,16 +410,15 @@
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST	0x0034
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST	0x0046
 
+#define USB_VENDOR_ID_STANTUM		0x1f87
+#define USB_DEVICE_ID_MTP		0x0002
+
 #define USB_VENDOR_ID_SUN		0x0430
 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
 
 #define USB_VENDOR_ID_SUNPLUS		0x04fc
 #define USB_DEVICE_ID_SUNPLUS_WDESKTOP	0x05d8
 
-#define USB_VENDOR_ID_TENX		0x1130
-#define USB_DEVICE_ID_TENX_IBUDDY1	0x0001
-#define USB_DEVICE_ID_TENX_IBUDDY2	0x0002
-
 #define USB_VENDOR_ID_THRUSTMASTER	0x044f
 
 #define USB_VENDOR_ID_TOPMAX		0x0663
--- linux-ec2-2.6.32.orig/drivers/hid/hid-core.c
+++ linux-ec2-2.6.32/drivers/hid/hid-core.c
@@ -1250,6 +1250,7 @@
 
 /* a list of devices for which there is a specialized driver on HID bus */
 static const struct hid_device_id hid_blacklist[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
@@ -1287,6 +1288,15 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
@@ -1294,6 +1304,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
@@ -1303,6 +1314,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
@@ -1333,10 +1345,14 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
@@ -1539,8 +1555,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)},
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)},
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)},
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
@@ -1655,8 +1672,6 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
@@ -1702,6 +1717,12 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
--- linux-ec2-2.6.32.orig/drivers/hid/hid-3m-pct.c
+++ linux-ec2-2.6.32/drivers/hid/hid-3m-pct.c
@@ -0,0 +1,290 @@
+/*
+ *  HID driver for 3M PCT multitouch panels
+ *
+ *  Copyright (c) 2009 Stephane Chatty <chatty@enac.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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("3M PCT multitouch panels");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+struct mmm_finger {
+	__s32 x, y;
+	__u8 rank;
+	bool touch, valid;
+};
+
+struct mmm_data {
+	struct mmm_finger f[10];
+	__u8 curid, num;
+	bool touch, valid;
+};
+
+static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_BUTTON:
+		return -1;
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		/* we do not want to map these: no input-oriented meaning */
+		case 0x14:
+		case 0x23:
+		case HID_DG_INPUTMODE:
+		case HID_DG_DEVICEINDEX:
+		case HID_DG_CONTACTCOUNT:
+		case HID_DG_CONTACTMAX:
+		case HID_DG_INRANGE:
+		case HID_DG_CONFIDENCE:
+			return -1;
+		case HID_DG_TIPSWITCH:
+			/* touchscreen emulation */
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			return 1;
+		case HID_DG_CONTACTID:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TRACKING_ID);
+			return 1;
+		}
+		/* let hid-input decide for the others */
+		return 0;
+
+	case 0xff000000:
+		/* we do not want to map these: no input-oriented meaning */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+
+/*
+ * this function is called when a whole packet has been received and processed,
+ * so that it can decide what to send to the input layer.
+ */
+static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
+{
+	struct mmm_finger *oldest = 0;
+	bool pressed = false, released = false;
+	int i;
+
+	/*
+	 * we need to iterate on all fingers to decide if we have a press
+	 * or a release event in our touchscreen emulation.
+	 */
+	for (i = 0; i < 10; ++i) {
+		struct mmm_finger *f = &md->f[i];
+		if (!f->valid) {
+			/* this finger is just placeholder data, ignore */
+		} else if (f->touch) {
+			/* this finger is on the screen */
+			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i);
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
+			input_mt_sync(input);
+			/*
+			 * touchscreen emulation: maintain the age rank
+			 * of this finger, decide if we have a press
+			 */
+			if (f->rank == 0) {
+				f->rank = ++(md->num);
+				if (f->rank == 1)
+					pressed = true;
+			}
+			if (f->rank == 1)
+				oldest = f;
+		} else {
+			/* this finger took off the screen */
+			/* touchscreen emulation: maintain age rank of others */
+			int j;
+
+			for (j = 0; j < 10; ++j) {
+				struct mmm_finger *g = &md->f[j];
+				if (g->rank > f->rank) {
+					g->rank--;
+					if (g->rank == 1)
+						oldest = g;
+				}
+			}
+			f->rank = 0;
+			--(md->num);
+			if (md->num == 0)
+				released = true;
+		}
+		f->valid = 0;
+	}
+
+	/* touchscreen emulation */
+	if (oldest) {
+		if (pressed)
+			input_event(input, EV_KEY, BTN_TOUCH, 1);
+		input_event(input, EV_ABS, ABS_X, oldest->x);
+		input_event(input, EV_ABS, ABS_Y, oldest->y);
+	} else if (released) {
+		input_event(input, EV_KEY, BTN_TOUCH, 0);
+	}
+}
+
+/*
+ * this function is called upon all reports
+ * so that we can accumulate contact point information,
+ * and call input_mt_sync after each point.
+ */
+static int mmm_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct mmm_data *md = hid_get_drvdata(hid);
+	/*
+	 * strangely, this function can be called before
+	 * field->hidinput is initialized!
+	 */
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		struct input_dev *input = field->hidinput->input;
+		switch (usage->hid) {
+		case HID_DG_TIPSWITCH:
+			md->touch = value;
+			break;
+		case HID_DG_CONFIDENCE:
+			md->valid = value;
+			break;
+		case HID_DG_CONTACTID:
+			if (md->valid) {
+				md->curid = value;
+				md->f[value].touch = md->touch;
+				md->f[value].valid = 1;
+			}
+			break;
+		case HID_GD_X:
+			if (md->valid)
+				md->f[md->curid].x = value;
+			break;
+		case HID_GD_Y:
+			if (md->valid)
+				md->f[md->curid].y = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			mmm_filter_event(md, input);
+			break;
+		}
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct mmm_data *md;
+
+	md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL);
+	if (!md) {
+		dev_err(&hdev->dev, "cannot allocate 3M data\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, md);
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	if (ret)
+		kfree(md);
+	return ret;
+}
+
+static void mmm_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id mmm_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mmm_devices);
+
+static const struct hid_usage_id mmm_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver mmm_driver = {
+	.name = "3m-pct",
+	.id_table = mmm_devices,
+	.probe = mmm_probe,
+	.remove = mmm_remove,
+	.input_mapping = mmm_input_mapping,
+	.input_mapped = mmm_input_mapped,
+	.usage_table = mmm_grabbed_usages,
+	.event = mmm_event,
+};
+
+static int __init mmm_init(void)
+{
+	return hid_register_driver(&mmm_driver);
+}
+
+static void __exit mmm_exit(void)
+{
+	hid_unregister_driver(&mmm_driver);
+}
+
+module_init(mmm_init);
+module_exit(mmm_exit);
+MODULE_LICENSE("GPL");
+
--- linux-ec2-2.6.32.orig/drivers/hid/hidraw.c
+++ linux-ec2-2.6.32/drivers/hid/hidraw.c
@@ -105,11 +105,15 @@
 static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	unsigned int minor = iminor(file->f_path.dentry->d_inode);
-	/* FIXME: What stops hidraw_table going NULL */
-	struct hid_device *dev = hidraw_table[minor]->hid;
+	struct hid_device *dev;
 	__u8 *buf;
 	int ret = 0;
 
+	if (!hidraw_table[minor])
+		return -ENODEV;
+
+	dev = hidraw_table[minor]->hid;
+
 	if (!dev->hid_output_raw_report)
 		return -ENODEV;
 
@@ -207,11 +211,14 @@
 	unsigned int minor = iminor(inode);
 	struct hidraw *dev;
 	struct hidraw_list *list = file->private_data;
+	int ret;
 
+	mutex_lock(&minors_lock);
 	if (!hidraw_table[minor]) {
 		printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
 				minor);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto unlock;
 	}
 
 	list_del(&list->node);
@@ -225,10 +232,12 @@
 			kfree(list->hidraw);
 		}
 	}
-
 	kfree(list);
+	ret = 0;
+unlock:
+	mutex_unlock(&minors_lock);
 
-	return 0;
+	return ret;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -237,11 +246,16 @@
 	struct inode *inode = file->f_path.dentry->d_inode;
 	unsigned int minor = iminor(inode);
 	long ret = 0;
-	/* FIXME: What stops hidraw_table going NULL */
-	struct hidraw *dev = hidraw_table[minor];
+	struct hidraw *dev;
 	void __user *user_arg = (void __user*) arg;
 
 	lock_kernel();
+	dev = hidraw_table[minor];
+	if (!dev) {
+		ret = -ENODEV;
+		goto out;
+	}
+
 	switch (cmd) {
 		case HIDIOCGRDESCSIZE:
 			if (put_user(dev->hid->rsize, (int __user *)arg))
@@ -314,6 +328,7 @@
 
 		ret = -ENOTTY;
 	}
+out:
 	unlock_kernel();
 	return ret;
 }
--- linux-ec2-2.6.32.orig/drivers/hid/hid-quanta.c
+++ linux-ec2-2.6.32/drivers/hid/hid-quanta.c
@@ -0,0 +1,260 @@
+/*
+ *  HID driver for Quanta Optical Touch dual-touch panels
+ *
+ *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("Quanta dual-touch panel");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+struct quanta_data {
+	__u16 x, y;
+	__u8 id;
+	bool valid;		/* valid finger data, or just placeholder? */
+	bool first;		/* is this the first finger in this frame? */
+	bool activity_now;	/* at least one active finger in this frame? */
+	bool activity;		/* at least one active finger previously? */
+};
+
+static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_CONFIDENCE:
+		case HID_DG_TIPSWITCH:
+		case HID_DG_INPUTMODE:
+		case HID_DG_DEVICEINDEX:
+		case HID_DG_CONTACTCOUNT:
+		case HID_DG_CONTACTMAX:
+		case HID_DG_TIPPRESSURE:
+		case HID_DG_WIDTH:
+		case HID_DG_HEIGHT:
+			return -1;
+		case HID_DG_INRANGE:
+			/* touchscreen emulation */
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			return 1;
+		case HID_DG_CONTACTID:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TRACKING_ID);
+			return 1;
+		}
+		return 0;
+
+	case 0xff000000:
+		/* ignore vendor-specific features */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+
+/*
+ * this function is called when a whole finger has been parsed,
+ * so that it can decide what to send to the input layer.
+ */
+static void quanta_filter_event(struct quanta_data *td, struct input_dev *input)
+{
+	
+	td->first = !td->first; /* touchscreen emulation */
+
+	if (!td->valid) {
+		/*
+		 * touchscreen emulation: if no finger in this frame is valid
+		 * and there previously was finger activity, this is a release
+		 */ 
+		if (!td->first && !td->activity_now && td->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 0);
+			td->activity = false;
+		}
+		return;
+	}
+
+	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
+	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
+	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
+
+	input_mt_sync(input);
+	td->valid = false;
+
+	/* touchscreen emulation: if first active finger in this frame... */
+	if (!td->activity_now) {
+		/* if there was no previous activity, emit touch event */
+		if (!td->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 1);
+			td->activity = true;
+		}
+		td->activity_now = true;
+		/* and in any case this is our preferred finger */
+		input_event(input, EV_ABS, ABS_X, td->x);
+		input_event(input, EV_ABS, ABS_Y, td->y);
+	}
+}
+
+
+static int quanta_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct quanta_data *td = hid_get_drvdata(hid);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		struct input_dev *input = field->hidinput->input;
+
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			td->valid = !!value;
+			break;
+		case HID_GD_X:
+			td->x = value;
+			break;
+		case HID_GD_Y:
+			td->y = value;
+			quanta_filter_event(td, input);
+			break;
+		case HID_DG_CONTACTID:
+			td->id = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			/* touch emulation: this is the last field in a frame */
+			td->first = false;
+			td->activity_now = false;
+			break;
+		case HID_DG_CONFIDENCE:
+		case HID_DG_TIPSWITCH:
+			/* avoid interference from generic hidinput handling */
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct quanta_data *td;
+
+	td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n");
+		return -ENOMEM;
+	}
+	td->valid = false;
+	td->activity = false;
+	td->activity_now = false;
+	td->first = false;
+	hid_set_drvdata(hdev, td);
+
+	ret = hid_parse(hdev);
+	if (!ret)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	if (ret)
+		kfree(td);
+
+	return ret;
+}
+
+static void quanta_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id quanta_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA,
+			USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, quanta_devices);
+
+static const struct hid_usage_id quanta_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver quanta_driver = {
+	.name = "quanta-touch",
+	.id_table = quanta_devices,
+	.probe = quanta_probe,
+	.remove = quanta_remove,
+	.input_mapping = quanta_input_mapping,
+	.input_mapped = quanta_input_mapped,
+	.usage_table = quanta_grabbed_usages,
+	.event = quanta_event,
+};
+
+static int __init quanta_init(void)
+{
+	return hid_register_driver(&quanta_driver);
+}
+
+static void __exit quanta_exit(void)
+{
+	hid_unregister_driver(&quanta_driver);
+}
+
+module_init(quanta_init);
+module_exit(quanta_exit);
+
--- linux-ec2-2.6.32.orig/drivers/hid/Kconfig
+++ linux-ec2-2.6.32/drivers/hid/Kconfig
@@ -55,6 +55,12 @@
 menu "Special HID drivers"
 	depends on HID
 
+config HID_3M_PCT
+	tristate "3M PCT"
+	depends on USB_HID
+	---help---
+	Support for 3M PCT touch screens.
+
 config HID_A4TECH
 	tristate "A4 tech" if EMBEDDED
 	depends on USB_HID
@@ -190,6 +196,12 @@
 	---help---
 	Support for Microsoft devices that are not fully compliant with HID standard.
 
+config HID_MOSART
+	tristate "MosArt"
+	depends on USB_HID
+	---help---
+	Support for MosArt dual-touch panels.
+
 config HID_MONTEREY
 	tristate "Monterey" if EMBEDDED
 	depends on USB_HID
@@ -204,6 +216,13 @@
 	---help---
 	Support for N-Trig touch screen.
 
+config HID_ORTEK
+	tristate "Ortek" if EMBEDDED
+	depends on USB_HID
+	default !EMBEDDED
+	---help---
+	Support for Ortek WKB-2000 wireless keyboard + mouse trackpad.
+
 config HID_PANTHERLORD
 	tristate "Pantherlord support" if EMBEDDED
 	depends on USB_HID
@@ -227,6 +246,12 @@
 	---help---
 	Support for Petalynx Maxter remote control.
 
+config HID_QUANTA
+	tristate "Quanta Optical Touch"
+	depends on USB_HID
+	---help---
+	Support for Quanta Optical Touch dual-touch panels.
+
 config HID_SAMSUNG
 	tristate "Samsung" if EMBEDDED
 	depends on USB_HID
@@ -241,6 +266,12 @@
 	---help---
 	Support for Sony PS3 controller.
 
+config HID_STANTUM
+	tristate "Stantum"
+	depends on USB_HID
+	---help---
+	Support for Stantum multitouch panel.
+
 config HID_SUNPLUS
 	tristate "Sunplus" if EMBEDDED
 	depends on USB_HID
--- linux-ec2-2.6.32.orig/drivers/hid/hid-apple.c
+++ linux-ec2-2.6.32/drivers/hid/hid-apple.c
@@ -53,6 +53,27 @@
 	u8 flags;
 };
 
+static const struct apple_key_translation macbookair_fn_keys[] = {
+	{ KEY_BACKSPACE, KEY_DELETE },
+	{ KEY_ENTER,	KEY_INSERT },
+	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
+	{ KEY_F3,	KEY_SCALE,          APPLE_FLAG_FKEY },
+	{ KEY_F4,	KEY_DASHBOARD,      APPLE_FLAG_FKEY },
+	{ KEY_F6,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
+	{ KEY_F7,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
+	{ KEY_F8,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
+	{ KEY_F9,	KEY_MUTE,           APPLE_FLAG_FKEY },
+	{ KEY_F10,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
+	{ KEY_F11,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+	{ KEY_F12,	KEY_EJECTCD,        APPLE_FLAG_FKEY },
+	{ KEY_UP,	KEY_PAGEUP },
+	{ KEY_DOWN,	KEY_PAGEDOWN },
+	{ KEY_LEFT,	KEY_HOME },
+	{ KEY_RIGHT,	KEY_END },
+	{ }
+};
+
 static const struct apple_key_translation apple_fn_keys[] = {
 	{ KEY_BACKSPACE, KEY_DELETE },
 	{ KEY_ENTER,	KEY_INSERT },
@@ -151,10 +172,15 @@
 	if (fnmode) {
 		int do_translate;
 
-		trans = apple_find_translation((hid->product < 0x21d ||
-					hid->product >= 0x300) ?
-					powerbook_fn_keys : apple_fn_keys,
-					usage->code);
+		if(hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
+				hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) {
+			trans = apple_find_translation(macbookair_fn_keys, usage->code);
+		} else if (hid->product < 0x21d || hid->product >= 0x300) {
+			trans = apple_find_translation(powerbook_fn_keys, usage->code);
+		} else {
+			trans = apple_find_translation(apple_fn_keys, usage->code);
+		}
+
 		if (trans) {
 			if (test_bit(usage->code, asc->pressed_fn))
 				do_translate = 1;
@@ -431,6 +457,25 @@
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
+			APPLE_ISO_KEYBOARD },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS),
+		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
--- linux-ec2-2.6.32.orig/drivers/hid/hid-ntrig.c
+++ linux-ec2-2.6.32/drivers/hid/hid-ntrig.c
@@ -1,8 +1,8 @@
 /*
  *  HID driver for N-Trig touchscreens
  *
- *  Copyright (c) 2008 Rafi Rubin
- *  Copyright (c) 2009 Stephane Chatty
+ *  Copyright (c) 2008-2010 Rafi Rubin
+ *  Copyright (c) 2009-2010 Stephane Chatty
  *
  */
 
@@ -15,21 +15,27 @@
 
 #include <linux/device.h>
 #include <linux/hid.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #define NTRIG_DUPLICATE_USAGES	0x001
 
-#define nt_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
-					EV_KEY, (c))
-
 struct ntrig_data {
-	__s32 x, y, id, w, h;
-	char reading_a_point, found_contact_id;
-	char pen_active;
-	char finger_active;
-	char inverted;
+	/* Incoming raw values for a single contact */
+	__u16 x, y, w, h;
+	__u16 id;
+
+	bool tipswitch;
+	bool confidence;
+	bool first_contact_touch;
+
+	bool reading_mt;
+
+	__u8 mt_footer[4];
+	__u8 mt_foot_count;
 };
 
 /*
@@ -42,8 +48,11 @@
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	switch (usage->hid & HID_USAGE_PAGE) {
+	/* No special mappings needed for the pen and single touch */
+	if (field->physical)
+		return 0;
 
+	switch (usage->hid & HID_USAGE_PAGE) {
 	case HID_UP_GENDESK:
 		switch (usage->hid) {
 		case HID_GD_X:
@@ -66,18 +75,12 @@
 	case HID_UP_DIGITIZER:
 		switch (usage->hid) {
 		/* we do not want to map these for now */
-		case HID_DG_CONTACTID: /* value is useless */
+		case HID_DG_CONTACTID: /* Not trustworthy, squelch for now */
 		case HID_DG_INPUTMODE:
 		case HID_DG_DEVICEINDEX:
-		case HID_DG_CONTACTCOUNT:
 		case HID_DG_CONTACTMAX:
 			return -1;
 
-		/* original mapping by Rafi Rubin */
-		case HID_DG_CONFIDENCE:
-			nt_map_key_clear(BTN_TOOL_DOUBLETAP);
-			return 1;
-
 		/* width/height mapped on TouchMajor/TouchMinor/Orientation */
 		case HID_DG_WIDTH:
 			hid_map_usage(hi, usage, bit, max,
@@ -104,6 +107,10 @@
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
+	/* No special mappings needed for the pen and single touch */
+	if (field->physical)
+		return 0;
+
 	if (usage->type == EV_KEY || usage->type == EV_REL
 			|| usage->type == EV_ABS)
 		clear_bit(usage->code, *bit);
@@ -123,31 +130,34 @@
 	struct input_dev *input = field->hidinput->input;
 	struct ntrig_data *nd = hid_get_drvdata(hid);
 
+	/* No special handling needed for the pen */
+	if (field->application == HID_DG_PEN)
+		return 0;
+
         if (hid->claimed & HID_CLAIMED_INPUT) {
 		switch (usage->hid) {
-
-		case HID_DG_INRANGE:
-			if (field->application & 0x3)
-				nd->pen_active = (value != 0);
-			else
-				nd->finger_active = (value != 0);
-			return 0;
-
-		case HID_DG_INVERT:
-			nd->inverted = value;
-			return 0;
-
+		case 0xff000001:
+			/* Tag indicating the start of a multitouch group */
+			nd->reading_mt = 1;
+			nd->first_contact_touch = 0;
+			break;
+		case HID_DG_TIPSWITCH:
+			nd->tipswitch = value;
+			/* Prevent emission of touch until validated */
+			return 1;
+		case HID_DG_CONFIDENCE:
+			nd->confidence = value;
+			break;
 		case HID_GD_X:
 			nd->x = value;
-			nd->reading_a_point = 1;
+			/* Clear the contact footer */
+			nd->mt_foot_count = 0;
 			break;
 		case HID_GD_Y:
 			nd->y = value;
 			break;
 		case HID_DG_CONTACTID:
 			nd->id = value;
-			/* we receive this only when in multitouch mode */
-			nd->found_contact_id = 1;
 			break;
 		case HID_DG_WIDTH:
 			nd->w = value;
@@ -159,33 +169,17 @@
 			 * report received in a finger event. We want
 			 * to emit a normal (X, Y) position
 			 */
-			if (!nd->found_contact_id) {
-				if (nd->pen_active && nd->finger_active) {
-					input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
-					input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
-				}
-				input_event(input, EV_ABS, ABS_X, nd->x);
-				input_event(input, EV_ABS, ABS_Y, nd->y);
-			}
-			break;
-		case HID_DG_TIPPRESSURE:
-			/*
-			 * when in single touch mode, this is the last
-			 * report received in a pen event. We want
-			 * to emit a normal (X, Y) position
-			 */
-			if (! nd->found_contact_id) {
-				if (nd->pen_active && nd->finger_active) {
-					input_report_key(input,
-							nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
-							, 0);
-					input_report_key(input,
-							nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN
-							, 1);
-				}
+			if (!nd->reading_mt) {
+				/*
+				 * TipSwitch indicates the presence of a
+				 * finger in single touch mode.
+				 */
+				input_report_key(input, BTN_TOUCH,
+						 nd->tipswitch);
+				input_report_key(input, BTN_TOOL_DOUBLETAP,
+						 nd->tipswitch);
 				input_event(input, EV_ABS, ABS_X, nd->x);
 				input_event(input, EV_ABS, ABS_Y, nd->y);
-				input_event(input, EV_ABS, ABS_PRESSURE, value);
 			}
 			break;
 		case 0xff000002:
@@ -195,10 +189,40 @@
 			 * this usage tells if the contact point is real
 			 * or a placeholder
 			 */
-			if (!nd->reading_a_point || value != 1)
+
+			/* Shouldn't get more than 4 footer packets, so skip */
+			if (nd->mt_foot_count >= 4)
 				break;
+
+			nd->mt_footer[nd->mt_foot_count++] = value;
+
+			/* if the footer isn't complete break */
+			if (nd->mt_foot_count != 4)
+				break;
+
+			/* Pen activity signal, trigger end of touch. */
+			if (nd->mt_footer[2]) {
+				nd->confidence = 0;
+				break;
+			}
+
+			/* If the contact was invalid */
+			if (!(nd->confidence && nd->mt_footer[0])
+					|| nd->w <= 250
+					|| nd->h <= 190) {
+				nd->confidence = 0;
+				break;
+			}
+
 			/* emit a normal (X, Y) for the first point only */
 			if (nd->id == 0) {
+				/*
+				 * TipSwitch is superfluous in multitouch
+				 * mode.  The footer events tell us
+				 * if there is a finger on the screen or
+				 * not.
+				 */
+				nd->first_contact_touch = nd->confidence;
 				input_event(input, EV_ABS, ABS_X, nd->x);
 				input_event(input, EV_ABS, ABS_Y, nd->y);
 			}
@@ -220,8 +244,21 @@
 						ABS_MT_TOUCH_MINOR, nd->w);
 			}
 			input_mt_sync(field->hidinput->input);
-			nd->reading_a_point = 0;
-			nd->found_contact_id = 0;
+			break;
+
+		case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
+			if (!nd->reading_mt)
+				break;
+
+			nd->reading_mt = 0;
+
+			if (nd->first_contact_touch) {
+				input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
+				input_report_key(input, BTN_TOUCH, 1);
+			} else {
+				input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
+				input_report_key(input, BTN_TOUCH, 0);
+			}
 			break;
 
 		default:
@@ -231,8 +268,8 @@
 	}
 
 	/* we have handled the hidinput part, now remains hiddev */
-        if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-                hid->hiddev_hid_event(hid, field, usage, value);
+	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
 
 	return 1;
 }
@@ -241,23 +278,75 @@
 {
 	int ret;
 	struct ntrig_data *nd;
+	struct hid_input *hidinput;
+	struct input_dev *input;
+	struct hid_report *report;
+
+	if (id->driver_data)
+		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
 
 	nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
 	if (!nd) {
 		dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
 		return -ENOMEM;
 	}
-	nd->reading_a_point = 0;
-	nd->found_contact_id = 0;
+
+	nd->reading_mt = 0;
 	hid_set_drvdata(hdev, nd);
 
 	ret = hid_parse(hdev);
-	if (!ret)
-		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		dev_err(&hdev->dev, "parse failed\n");
+		goto err_free;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		dev_err(&hdev->dev, "hw start failed\n");
+		goto err_free;
+	}
 
-	if (ret)
-		kfree (nd);
 
+	list_for_each_entry(hidinput, &hdev->inputs, list) {
+		if (hidinput->report->maxfield < 1)
+			continue;
+
+		input = hidinput->input;
+		switch (hidinput->report->field[0]->application) {
+		case HID_DG_PEN:
+			input->name = "N-Trig Pen";
+			break;
+		case HID_DG_TOUCHSCREEN:
+			/* These keys are redundant for fingers, clear them
+			 * to prevent incorrect identification */
+			__clear_bit(BTN_TOOL_PEN, input->keybit);
+			__clear_bit(BTN_TOOL_FINGER, input->keybit);
+			__clear_bit(BTN_0, input->keybit);
+			__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
+			/*
+			 * The physical touchscreen (single touch)
+			 * input has a value for physical, whereas
+			 * the multitouch only has logical input
+			 * fields.
+			 */
+			input->name =
+				(hidinput->report->field[0]
+				 ->physical) ?
+				"N-Trig Touchscreen" :
+				"N-Trig MultiTouch";
+			break;
+		}
+	}
+
+	/* This is needed for devices with more recent firmware versions */
+	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
+	if (report)
+		usbhid_submit_report(hdev, report, USB_DIR_OUT);
+
+
+	return 0;
+err_free:
+	kfree(nd);
 	return ret;
 }
 
@@ -276,7 +365,7 @@
 
 static const struct hid_usage_id ntrig_grabbed_usages[] = {
 	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
 };
 
 static struct hid_driver ntrig_driver = {
--- linux-ec2-2.6.32.orig/drivers/hid/hid-ortek.c
+++ linux-ec2-2.6.32/drivers/hid/hid-ortek.c
@@ -0,0 +1,56 @@
+/*
+ *  HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad).
+ *  Fixes LogicalMaximum error in USB report description, see
+ *  http://bugzilla.kernel.org/show_bug.cgi?id=14787
+ *
+ *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int rsize)
+{
+	if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
+		dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 "
+				"report descriptor.\n");
+		rdesc[55] = 0x92;
+	}
+}
+
+static const struct hid_device_id ortek_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ortek_devices);
+
+static struct hid_driver ortek_driver = {
+	.name = "ortek",
+	.id_table = ortek_devices,
+	.report_fixup = ortek_report_fixup
+};
+
+static int __init ortek_init(void)
+{
+	return hid_register_driver(&ortek_driver);
+}
+
+static void __exit ortek_exit(void)
+{
+	hid_unregister_driver(&ortek_driver);
+}
+
+module_init(ortek_init);
+module_exit(ortek_exit);
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/hid/hid-mosart.c
+++ linux-ec2-2.6.32/drivers/hid/hid-mosart.c
@@ -0,0 +1,273 @@
+/*
+ *  HID driver for the multitouch panel on the ASUS EeePC T91MT
+ *
+ *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com>
+ *
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+
+MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_DESCRIPTION("MosArt dual-touch panel");
+MODULE_LICENSE("GPL");
+
+#include "hid-ids.h"
+
+struct mosart_data {
+	__u16 x, y;
+	__u8 id;
+	bool valid;		/* valid finger data, or just placeholder? */
+	bool first;		/* is this the first finger in this frame? */
+	bool activity_now;	/* at least one active finger in this frame? */
+	bool activity;		/* at least one active finger previously? */
+};
+
+static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+	case HID_UP_GENDESK:
+		switch (usage->hid) {
+		case HID_GD_X:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_X);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_X,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		case HID_GD_Y:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_POSITION_Y);
+			/* touchscreen emulation */
+			input_set_abs_params(hi->input, ABS_Y,
+						field->logical_minimum,
+						field->logical_maximum, 0, 0);
+			return 1;
+		}
+		return 0;
+
+	case HID_UP_DIGITIZER:
+		switch (usage->hid) {
+		case HID_DG_CONFIDENCE:
+		case HID_DG_TIPSWITCH:
+		case HID_DG_INPUTMODE:
+		case HID_DG_DEVICEINDEX:
+		case HID_DG_CONTACTCOUNT:
+		case HID_DG_CONTACTMAX:
+		case HID_DG_TIPPRESSURE:
+		case HID_DG_WIDTH:
+		case HID_DG_HEIGHT:
+			return -1;
+		case HID_DG_INRANGE:
+			/* touchscreen emulation */
+			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+			return 1;
+
+		case HID_DG_CONTACTID:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TRACKING_ID);
+			return 1;
+
+		}
+		return 0;
+
+	case 0xff000000:
+		/* ignore HID features */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if (usage->type == EV_KEY || usage->type == EV_ABS)
+		clear_bit(usage->code, *bit);
+
+	return 0;
+}
+
+/*
+ * this function is called when a whole finger has been parsed,
+ * so that it can decide what to send to the input layer.
+ */
+static void mosart_filter_event(struct mosart_data *td, struct input_dev *input)
+{
+	td->first = !td->first; /* touchscreen emulation */
+
+	if (!td->valid) {
+		/*
+		 * touchscreen emulation: if no finger in this frame is valid
+		 * and there previously was finger activity, this is a release
+		 */ 
+		if (!td->first && !td->activity_now && td->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 0);
+			td->activity = false;
+		}
+		return;
+	}
+
+	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
+	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
+	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
+
+	input_mt_sync(input);
+	td->valid = false;
+
+	/* touchscreen emulation: if first active finger in this frame... */
+	if (!td->activity_now) {
+		/* if there was no previous activity, emit touch event */
+		if (!td->activity) {
+			input_event(input, EV_KEY, BTN_TOUCH, 1);
+			td->activity = true;
+		}
+		td->activity_now = true;
+		/* and in any case this is our preferred finger */
+		input_event(input, EV_ABS, ABS_X, td->x);
+		input_event(input, EV_ABS, ABS_Y, td->y);
+	}
+}
+
+
+static int mosart_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct mosart_data *td = hid_get_drvdata(hid);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		struct input_dev *input = field->hidinput->input;
+		switch (usage->hid) {
+		case HID_DG_INRANGE:
+			td->valid = !!value;
+			break;
+		case HID_GD_X:
+			td->x = value;
+			break;
+		case HID_GD_Y:
+			td->y = value;
+			mosart_filter_event(td, input);
+			break;
+		case HID_DG_CONTACTID:
+			td->id = value;
+			break;
+		case HID_DG_CONTACTCOUNT:
+			/* touch emulation: this is the last field in a frame */
+			td->first = false;
+			td->activity_now = false;
+			break;
+		case HID_DG_CONFIDENCE:
+		case HID_DG_TIPSWITCH:
+			/* avoid interference from generic hidinput handling */
+			break;
+
+		default:
+			/* fallback to the generic hidinput handling */
+			return 0;
+		}
+	}
+
+	/* we have handled the hidinput part, now remains hiddev */
+	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+		hid->hiddev_hid_event(hid, field, usage, value);
+
+	return 1;
+}
+
+static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct mosart_data *td;
+
+
+	td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate MosArt data\n");
+		return -ENOMEM;
+	}
+	td->valid = false;
+	td->activity = false;
+	td->activity_now = false;
+	td->first = false;
+	hid_set_drvdata(hdev, td);
+
+	/* currently, it's better to have one evdev device only */
+#if 0
+	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+#endif
+
+	ret = hid_parse(hdev);
+	if (ret == 0)
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+	if (ret == 0) {
+		struct hid_report_enum *re = hdev->report_enum
+						+ HID_FEATURE_REPORT;
+		struct hid_report *r = re->report_id_hash[7];
+
+		r->field[0]->value[0] = 0x02;
+		usbhid_submit_report(hdev, r, USB_DIR_OUT);
+	} else 
+		kfree(td);
+
+	return ret;
+}
+
+static void mosart_remove(struct hid_device *hdev)
+{
+	hid_hw_stop(hdev);
+	kfree(hid_get_drvdata(hdev));
+	hid_set_drvdata(hdev, NULL);
+}
+
+static const struct hid_device_id mosart_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mosart_devices);
+
+static const struct hid_usage_id mosart_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
+};
+
+static struct hid_driver mosart_driver = {
+	.name = "mosart",
+	.id_table = mosart_devices,
+	.probe = mosart_probe,
+	.remove = mosart_remove,
+	.input_mapping = mosart_input_mapping,
+	.input_mapped = mosart_input_mapped,
+	.usage_table = mosart_grabbed_usages,
+	.event = mosart_event,
+};
+
+static int __init mosart_init(void)
+{
+	return hid_register_driver(&mosart_driver);
+}
+
+static void __exit mosart_exit(void)
+{
+	hid_unregister_driver(&mosart_driver);
+}
+
+module_init(mosart_init);
+module_exit(mosart_exit);
+
--- linux-ec2-2.6.32.orig/drivers/hid/usbhid/usbhid.h
+++ linux-ec2-2.6.32/drivers/hid/usbhid/usbhid.h
@@ -80,12 +80,14 @@
 	unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
 	char *ctrlbuf;                                                  /* Control buffer */
 	dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
+	unsigned long last_ctrl;						/* record of last output for timeouts */
 
 	struct urb *urbout;                                             /* Output URB */
 	struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE];              /* Output pipe fifo */
 	unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
 	char *outbuf;                                                   /* Output buffer */
 	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
+	unsigned long last_out;							/* record of last output for timeouts */
 
 	spinlock_t lock;						/* fifo spinlock */
 	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
--- linux-ec2-2.6.32.orig/drivers/hid/usbhid/hid-core.c
+++ linux-ec2-2.6.32/drivers/hid/usbhid/hid-core.c
@@ -318,6 +318,7 @@
 			err_hid("usb_submit_urb(out) failed");
 			return -1;
 		}
+		usbhid->last_out = jiffies;
 	} else {
 		/*
 		 * queue work to wake up the device.
@@ -379,6 +380,7 @@
 			err_hid("usb_submit_urb(ctrl) failed");
 			return -1;
 		}
+		usbhid->last_ctrl = jiffies;
 	} else {
 		/*
 		 * queue work to wake up the device.
@@ -514,9 +516,20 @@
 		usbhid->out[usbhid->outhead].report = report;
 		usbhid->outhead = head;
 
-		if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
+		if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
 			if (hid_submit_out(hid))
 				clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+		} else {
+			/*
+			 * the queue is known to run
+			 * but an earlier request may be stuck
+			 * we may need to time out
+			 * no race because this is called under
+			 * spinlock
+			 */
+			if (time_after(jiffies, usbhid->last_out + HZ * 5))
+				usb_unlink_urb(usbhid->urbout);
+		}
 		return;
 	}
 
@@ -537,9 +550,20 @@
 	usbhid->ctrl[usbhid->ctrlhead].dir = dir;
 	usbhid->ctrlhead = head;
 
-	if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+	if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
 		if (hid_submit_ctrl(hid))
 			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+	} else {
+		/*
+		 * the queue is known to run
+		 * but an earlier request may be stuck
+		 * we may need to time out
+		 * no race because this is called under
+		 * spinlock
+		 */
+		if (time_after(jiffies, usbhid->last_ctrl + HZ * 5))
+			usb_unlink_urb(usbhid->urbctrl);
+	}
 }
 
 void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
@@ -976,16 +1000,6 @@
 		}
 	}
 
-	init_waitqueue_head(&usbhid->wait);
-	INIT_WORK(&usbhid->reset_work, hid_reset);
-	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
-	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
-	spin_lock_init(&usbhid->lock);
-
-	usbhid->intf = intf;
-	usbhid->ifnum = interface->desc.bInterfaceNumber;
-
 	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usbhid->urbctrl) {
 		ret = -ENOMEM;
@@ -998,7 +1012,8 @@
 	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
 	usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
 
-	usbhid_init_reports(hid);
+	if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
+		usbhid_init_reports(hid);
 
 	set_bit(HID_STARTED, &usbhid->iofl);
 
@@ -1155,6 +1170,14 @@
 
 	hid->driver_data = usbhid;
 	usbhid->hid = hid;
+	usbhid->intf = intf;
+	usbhid->ifnum = interface->desc.bInterfaceNumber;
+
+	init_waitqueue_head(&usbhid->wait);
+	INIT_WORK(&usbhid->reset_work, hid_reset);
+	INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+	spin_lock_init(&usbhid->lock);
 
 	ret = hid_add_device(hid);
 	if (ret) {
--- linux-ec2-2.6.32.orig/drivers/hid/usbhid/hid-quirks.c
+++ linux-ec2-2.6.32/drivers/hid/usbhid/hid-quirks.c
@@ -37,6 +37,7 @@
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN, HID_QUIRK_MULTI_INPUT},
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 
@@ -280,7 +281,7 @@
 	if (idVendor == USB_VENDOR_ID_NCR &&
 			idProduct >= USB_DEVICE_ID_NCR_FIRST &&
 			idProduct <= USB_DEVICE_ID_NCR_LAST)
-			return HID_QUIRK_NOGET;
+			return HID_QUIRK_NO_INIT_REPORTS;
 
 	down_read(&dquirks_rwsem);
 	bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
--- linux-ec2-2.6.32.orig/drivers/cpuidle/Kconfig
+++ linux-ec2-2.6.32/drivers/cpuidle/Kconfig
@@ -1,6 +1,7 @@
 
 config CPU_IDLE
 	bool "CPU idle PM support"
+	depends on !PROCESSOR_EXTERNAL_CONTROL
 	default ACPI
 	help
 	  CPU idle is a generic framework for supporting software-controlled
--- linux-ec2-2.6.32.orig/drivers/cpuidle/governors/menu.c
+++ linux-ec2-2.6.32/drivers/cpuidle/governors/menu.c
@@ -18,6 +18,7 @@
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 #include <linux/sched.h>
+#include <linux/math64.h>
 
 #define BUCKETS 12
 #define RESOLUTION 1024
@@ -100,7 +101,6 @@
 
 	unsigned int	expected_us;
 	u64		predicted_us;
-	unsigned int	measured_us;
 	unsigned int	exit_us;
 	unsigned int	bucket;
 	u64		correction_factor[BUCKETS];
@@ -169,6 +169,12 @@
 
 static void menu_update(struct cpuidle_device *dev);
 
+/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
+static u64 div_round64(u64 dividend, u32 divisor)
+{
+	return div_u64(dividend + (divisor / 2), divisor);
+}
+
 /**
  * menu_select - selects the next idle state to enter
  * @dev: the CPU
@@ -180,14 +186,14 @@
 	int i;
 	int multiplier;
 
-	data->last_state_idx = 0;
-	data->exit_us = 0;
-
 	if (data->needs_update) {
 		menu_update(dev);
 		data->needs_update = 0;
 	}
 
+	data->last_state_idx = 0;
+	data->exit_us = 0;
+
 	/* Special case when user has set very strict latency requirement */
 	if (unlikely(latency_req == 0))
 		return 0;
@@ -209,9 +215,8 @@
 		data->correction_factor[data->bucket] = RESOLUTION * DECAY;
 
 	/* Make sure to round up for half microseconds */
-	data->predicted_us = DIV_ROUND_CLOSEST(
-		data->expected_us * data->correction_factor[data->bucket],
-		RESOLUTION * DECAY);
+	data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
+					 RESOLUTION * DECAY);
 
 	/*
 	 * We want to default to C1 (hlt), not to busy polling
@@ -288,7 +293,7 @@
 	new_factor = data->correction_factor[data->bucket]
 			* (DECAY - 1) / DECAY;
 
-	if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING)
+	if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
 		new_factor += RESOLUTION * measured_us / data->expected_us;
 	else
 		/*
--- linux-ec2-2.6.32.orig/drivers/video/offb.c
+++ linux-ec2-2.6.32/drivers/video/offb.c
@@ -282,8 +282,17 @@
 	return 0;
 }
 
+static void offb_destroy(struct fb_info *info)
+{
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(info->aperture_base, info->aperture_size);
+	framebuffer_release(info);
+}
+
 static struct fb_ops offb_ops = {
 	.owner		= THIS_MODULE,
+	.fb_destroy	= offb_destroy,
 	.fb_setcolreg	= offb_setcolreg,
 	.fb_set_par	= offb_set_par,
 	.fb_blank	= offb_blank,
@@ -482,10 +491,14 @@
 	var->sync = 0;
 	var->vmode = FB_VMODE_NONINTERLACED;
 
+	/* set offb aperture size for generic probing */
+	info->aperture_base = address;
+	info->aperture_size = fix->smem_len;
+
 	info->fbops = &offb_ops;
 	info->screen_base = ioremap(address, fix->smem_len);
 	info->pseudo_palette = (void *) (info + 1);
-	info->flags = FBINFO_DEFAULT | foreign_endian;
+	info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE | foreign_endian;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
--- linux-ec2-2.6.32.orig/drivers/video/bfin-t350mcqb-fb.c
+++ linux-ec2-2.6.32/drivers/video/bfin-t350mcqb-fb.c
@@ -515,9 +515,9 @@
 	fbinfo->fbops = &bfin_t350mcqb_fb_ops;
 	fbinfo->flags = FBINFO_FLAG_DEFAULT;
 
-	info->fb_buffer =
-	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
-			       GFP_KERNEL);
+	info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
+				ACTIVE_VIDEO_MEM_OFFSET,
+				&info->dma_handle, GFP_KERNEL);
 
 	if (NULL == info->fb_buffer) {
 		printk(KERN_ERR DRIVER_NAME
@@ -587,8 +587,8 @@
 out6:
 	fb_dealloc_cmap(&fbinfo->cmap);
 out4:
-	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-			  info->dma_handle);
+	dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
+			 info->fb_buffer, info->dma_handle);
 out3:
 	framebuffer_release(fbinfo);
 out2:
@@ -611,8 +611,9 @@
 	free_irq(info->irq, info);
 
 	if (info->fb_buffer != NULL)
-		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
-				  info->dma_handle);
+		dma_free_coherent(NULL, fbinfo->fix.smem_len +
+			ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
+			info->dma_handle);
 
 	fb_dealloc_cmap(&fbinfo->cmap);
 
--- linux-ec2-2.6.32.orig/drivers/video/w100fb.c
+++ linux-ec2-2.6.32/drivers/video/w100fb.c
@@ -857,9 +857,9 @@
 void w100fb_gpio_write(int port, unsigned long value)
 {
 	if (port==W100_GPIO_PORT_A)
-		value = writel(value, remapped_regs + mmGPIO_DATA);
+		writel(value, remapped_regs + mmGPIO_DATA);
 	else
-		value = writel(value, remapped_regs + mmGPIO_DATA2);
+		writel(value, remapped_regs + mmGPIO_DATA2);
 }
 EXPORT_SYMBOL(w100fb_gpio_read);
 EXPORT_SYMBOL(w100fb_gpio_write);
--- linux-ec2-2.6.32.orig/drivers/video/vesafb.c
+++ linux-ec2-2.6.32/drivers/video/vesafb.c
@@ -28,6 +28,12 @@
 #define dac_reg	(0x3c8)
 #define dac_val	(0x3c9)
 
+struct vesafb_info
+{
+	u32 pseudo_palette[256];
+	int mtrr_hdl;
+};
+
 /* --------------------------------------------------------------------- */
 
 static struct fb_var_screeninfo vesafb_defined __initdata = {
@@ -47,16 +53,37 @@
 	.accel	= FB_ACCEL_NONE,
 };
 
+#ifndef MODULE
 static int   inverse    __read_mostly;
+#endif
 static int   mtrr       __read_mostly;		/* disable mtrr */
 static int   vram_remap __initdata;		/* Set amount of memory to be used */
 static int   vram_total __initdata;		/* Set total amount of memory */
 static int   pmi_setpal __read_mostly = 1;	/* pmi for palette changes ??? */
+static int	redraw		__read_mostly;
 static int   ypan       __read_mostly;		/* 0..nothing, 1..ypan, 2..ywrap */
+static int	ywrap		__read_mostly;
 static void  (*pmi_start)(void) __read_mostly;
 static void  (*pmi_pal)  (void) __read_mostly;
 static int   depth      __read_mostly;
 static int   vga_compat __read_mostly;
+
+module_param(redraw, bool, 0);
+module_param(ypan, bool, 0);
+module_param(ywrap, bool, 0);
+module_param_named(vgapal, pmi_setpal, invbool, 0);
+MODULE_PARM_DESC(vgapal, "Use VGA for setting palette (default)");
+module_param_named(pmipal, pmi_setpal, bool, 0);
+MODULE_PARM_DESC(pmipal, "Use PMI for setting palette");
+module_param(mtrr, uint, 0);
+MODULE_PARM_DESC(mtrr, "Enable MTRR support (default)");
+module_param_named(nomtrr, mtrr, invbool, 0);
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support");
+module_param(vram_remap, int, 0);
+MODULE_PARM_DESC(vram_remap, "Set total amount of memory to be used");
+module_param(vram_total, int, 0);
+MODULE_PARM_DESC(vram_total, "Total amount of memory");
+
 /* --------------------------------------------------------------------- */
 
 static int vesafb_pan_display(struct fb_var_screeninfo *var,
@@ -192,6 +219,7 @@
 	.fb_imageblit	= cfb_imageblit,
 };
 
+#ifndef MODULE
 static int __init vesafb_setup(char *options)
 {
 	char *this_opt;
@@ -225,10 +253,12 @@
 	}
 	return 0;
 }
+#endif
 
 static int __init vesafb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
+	struct vesafb_info *vfb_info;
 	int i, err;
 	unsigned int size_vmode;
 	unsigned int size_remap;
@@ -287,13 +317,14 @@
 		   spaces our resource handlers simply don't know about */
 	}
 
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
+	info = framebuffer_alloc(sizeof(struct vesafb_info), &dev->dev);
 	if (!info) {
 		release_mem_region(vesafb_fix.smem_start, size_total);
 		return -ENOMEM;
 	}
-	info->pseudo_palette = info->par;
-	info->par = NULL;
+	vfb_info = (struct vesafb_info *) info->par;
+	vfb_info->mtrr_hdl = -1;
+	info->pseudo_palette = vfb_info->pseudo_palette;
 
 	/* set vesafb aperture size for generic probing */
 	info->aperture_base = screen_info.lfb_base;
@@ -431,18 +462,16 @@
 		}
 
 		if (type) {
-			int rc;
-
 			/* Find the largest power-of-two */
 			while (temp_size & (temp_size - 1))
 				temp_size &= (temp_size - 1);
 
 			/* Try and find a power of two to add */
 			do {
-				rc = mtrr_add(vesafb_fix.smem_start, temp_size,
+				vfb_info->mtrr_hdl = mtrr_add(vesafb_fix.smem_start, temp_size,
 					      type, 1);
 				temp_size >>= 1;
-			} while (temp_size >= PAGE_SIZE && rc == -EINVAL);
+			} while (temp_size >= PAGE_SIZE && vfb_info->mtrr_hdl == -EINVAL);
 		}
 	}
 #endif
@@ -476,8 +505,28 @@
 	return err;
 }
 
+static int __exit vesafb_remove(struct platform_device *device)
+{
+	struct fb_info *info = dev_get_drvdata(&device->dev);
+
+	unregister_framebuffer(info);
+#ifdef CONFIG_MTRR
+	{
+		struct vesafb_info *vfb_info = (struct vesafb_info *) info->par;
+		if (vfb_info->mtrr_hdl >= 0)
+			mtrr_del(vfb_info->mtrr_hdl, 0, 0);
+	}
+#endif
+	iounmap(info->screen_base);
+	framebuffer_release(info);
+	release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+
+	return 0;
+}
+
 static struct platform_driver vesafb_driver = {
 	.probe	= vesafb_probe,
+	.remove = vesafb_remove,
 	.driver	= {
 		.name	= "vesafb",
 	},
@@ -488,11 +537,18 @@
 static int __init vesafb_init(void)
 {
 	int ret;
+#ifndef MODULE
 	char *option = NULL;
 
 	/* ignore error return of fb_get_options */
 	fb_get_options("vesafb", &option);
 	vesafb_setup(option);
+#else
+	if (redraw)
+		ypan = 0;
+	if (ywrap)
+		ypan = 2;
+#endif
 	ret = platform_driver_register(&vesafb_driver);
 
 	if (!ret) {
@@ -511,6 +567,14 @@
 
 	return ret;
 }
+
+static void __exit vesafb_exit(void)
+{
+	platform_device_unregister(vesafb_device);
+	platform_driver_unregister(&vesafb_driver);
+}
+
 module_init(vesafb_init);
+module_exit(vesafb_exit);
 
 MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/drivers/video/s3c-fb.c
+++ linux-ec2-2.6.32/drivers/video/s3c-fb.c
@@ -211,21 +211,23 @@
 
 /**
  * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
- * @id: window id.
  * @sfb: The hardware state.
  * @pixclock: The pixel clock wanted, in picoseconds.
  *
  * Given the specified pixel clock, work out the necessary divider to get
  * close to the output frequency.
  */
-static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk)
+static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
 {
-	struct s3c_fb_pd_win *win = sfb->pdata->win[id];
 	unsigned long clk = clk_get_rate(sfb->bus_clk);
+	unsigned long long tmp;
 	unsigned int result;
 
-	pixclk *= win->win_mode.refresh;
-	result = clk / pixclk;
+	tmp = (unsigned long long)clk;
+	tmp *= pixclk;
+
+	do_div(tmp, 1000000000UL);
+	result = (unsigned int)tmp / 1000;
 
 	dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
 		pixclk, clk, result, clk / result);
@@ -301,7 +303,7 @@
 	/* use window 0 as the basis for the lcd output timings */
 
 	if (win_no == 0) {
-		clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock);
+		clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
 
 		data = sfb->pdata->vidcon0;
 		data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
--- linux-ec2-2.6.32.orig/drivers/video/vga16fb.c
+++ linux-ec2-2.6.32/drivers/video/vga16fb.c
@@ -1355,6 +1355,16 @@
 
 	vga16fb_update_fix(info);
 
+	/*
+	 * Ubuntu: Don't register vga16fb if another fb exists. Bad interactions
+	 * can occur.
+	 */
+	if (num_registered_fb > 0) {
+		printk(KERN_NOTICE "vga16fb: not registering due to another "
+		       "framebuffer present\n");
+		goto err_check_var;
+	}
+
 	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
 		ret = -EINVAL;
@@ -1440,6 +1450,8 @@
 
 MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
 MODULE_LICENSE("GPL");
+/* Attempt to load for any VGA compatible device. */
+MODULE_ALIAS("pci:*bc03sc00i*");
 module_init(vga16fb_init);
 module_exit(vga16fb_exit);
 
--- linux-ec2-2.6.32.orig/drivers/video/xen-fbfront.c
+++ linux-ec2-2.6.32/drivers/video/xen-fbfront.c
@@ -670,7 +670,6 @@
 
 static struct xenbus_driver xenfb_driver = {
 	.name = "vfb",
-	.owner = THIS_MODULE,
 	.ids = xenfb_ids,
 	.probe = xenfb_probe,
 	.remove = xenfb_remove,
--- linux-ec2-2.6.32.orig/drivers/video/efifb.c
+++ linux-ec2-2.6.32/drivers/video/efifb.c
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
 #include <linux/dmi.h>
-
+#include <linux/pci.h>
 #include <video/vga.h>
 
 static struct fb_var_screeninfo efifb_defined __initdata = {
@@ -39,16 +39,31 @@
 	M_I20,		/* 20-Inch iMac */
 	M_I20_SR,	/* 20-Inch iMac (Santa Rosa) */
 	M_I24,		/* 24-Inch iMac */
+	M_I24_8_1,	/* 24-Inch iMac, 8,1th gen */
+	M_I24_10_1,	/* 24-Inch iMac, 10,1th gen */
+	M_I27_11_1,	/* 27-Inch iMac, 11,1th gen */
 	M_MINI,		/* Mac Mini */
+	M_MINI_3_1,	/* Mac Mini, 3,1th gen */
+	M_MINI_4_1,	/* Mac Mini, 4,1th gen */
 	M_MB,		/* MacBook */
 	M_MB_2,		/* MacBook, 2nd rev. */
 	M_MB_3,		/* MacBook, 3rd rev. */
+	M_MB_5_1,	/* MacBook, 5th rev. */
+	M_MB_6_1,	/* MacBook, 6th rev. */
+	M_MB_7_1,	/* MacBook, 7th rev. */
 	M_MB_SR,	/* MacBook, 2nd gen, (Santa Rosa) */
 	M_MBA,		/* MacBook Air */
 	M_MBP,		/* MacBook Pro */
 	M_MBP_2,	/* MacBook Pro 2nd gen */
+	M_MBP_2_2,	/* MacBook Pro 2,2nd gen */
 	M_MBP_SR,	/* MacBook Pro (Santa Rosa) */
 	M_MBP_4,	/* MacBook Pro, 4th gen */
+	M_MBP_5_1,    /* MacBook Pro, 5,1th gen */
+	M_MBP_5_2,	/* MacBook Pro, 5,2th gen */
+	M_MBP_5_3,	/* MacBook Pro, 5,3rd gen */
+	M_MBP_6_1,	/* MacBook Pro, 6,1th gen */
+	M_MBP_6_2,	/* MacBook Pro, 6,2th gen */
+	M_MBP_7_1,	/* MacBook Pro, 7,1th gen */
 	M_UNKNOWN	/* placeholder */
 };
 
@@ -63,13 +78,28 @@
 	[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
 	[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
 	[M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
+	[M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 },
+	[M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 },
+	[M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 },
 	[M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
+	[M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 },
+	[M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 },
 	[M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
+	[M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 },
+	[M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 },
+	[M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 },
 	[M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
 	[M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
 	[M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
+	[M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 },
 	[M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
 	[M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
+	[M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
+	[M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 },
+	[M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 },
+	[M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 },
+	[M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 },
+	[M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 },
 	[M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
 };
 
@@ -90,7 +120,12 @@
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
 	/* At least one of these two will be right; maybe both? */
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
@@ -99,13 +134,23 @@
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
+	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
 	EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
 	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
+	EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
 	{},
 };
 
@@ -113,7 +158,7 @@
 {
 	struct efifb_dmi_info *info = id->driver_data;
 	if (info->base == 0)
-		return -ENODEV;
+		return 0;
 
 	printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
 			 "(%dx%d, stride %d)\n", id->ident,
@@ -121,18 +166,55 @@
 			 info->stride);
 
 	/* Trust the bootloader over the DMI tables */
-	if (screen_info.lfb_base == 0)
+	if (screen_info.lfb_base == 0) {
+#if defined(CONFIG_PCI)
+		struct pci_dev *dev = NULL;
+		int found_bar = 0;
+#endif
 		screen_info.lfb_base = info->base;
-	if (screen_info.lfb_linelength == 0)
-		screen_info.lfb_linelength = info->stride;
-	if (screen_info.lfb_width == 0)
-		screen_info.lfb_width = info->width;
-	if (screen_info.lfb_height == 0)
-		screen_info.lfb_height = info->height;
-	if (screen_info.orig_video_isVGA == 0)
-		screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
 
-	return 0;
+#if defined(CONFIG_PCI)
+		/* make sure that the address in the table is actually on a
+		 * VGA device's PCI BAR */
+
+		for_each_pci_dev(dev) {
+			int i;
+			if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+				continue;
+			for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+				resource_size_t start, end;
+
+				start = pci_resource_start(dev, i);
+				if (start == 0)
+					break;
+				end = pci_resource_end(dev, i);
+				if (screen_info.lfb_base >= start &&
+						screen_info.lfb_base < end) {
+					found_bar = 1;
+				}
+			}
+		}
+		if (!found_bar)
+			screen_info.lfb_base = 0;
+#endif
+	}
+	if (screen_info.lfb_base) {
+		if (screen_info.lfb_linelength == 0)
+			screen_info.lfb_linelength = info->stride;
+		if (screen_info.lfb_width == 0)
+			screen_info.lfb_width = info->width;
+		if (screen_info.lfb_height == 0)
+			screen_info.lfb_height = info->height;
+		if (screen_info.orig_video_isVGA == 0)
+			screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
+	} else {
+		screen_info.lfb_linelength = 0;
+		screen_info.lfb_width = 0;
+		screen_info.lfb_height = 0;
+		screen_info.orig_video_isVGA = 0;
+		return 0;
+	}
+	return 1;
 }
 
 static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -161,8 +243,17 @@
 	return 0;
 }
 
+static void efifb_destroy(struct fb_info *info)
+{
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	release_mem_region(info->aperture_base, info->aperture_size);
+	framebuffer_release(info);
+}
+
 static struct fb_ops efifb_ops = {
 	.owner		= THIS_MODULE,
+	.fb_destroy	= efifb_destroy,
 	.fb_setcolreg	= efifb_setcolreg,
 	.fb_fillrect	= cfb_fillrect,
 	.fb_copyarea	= cfb_copyarea,
@@ -281,7 +372,7 @@
 	info->par = NULL;
 
 	info->aperture_base = efifb_fix.smem_start;
-	info->aperture_size = size_total;
+	info->aperture_size = size_remap;
 
 	info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
 	if (!info->screen_base) {
--- linux-ec2-2.6.32.orig/drivers/video/Kconfig
+++ linux-ec2-2.6.32/drivers/video/Kconfig
@@ -688,8 +688,8 @@
 	  If unsure, say N.
 
 config FB_VESA
-	bool "VESA VGA graphics support"
-	depends on (FB = y) && X86
+	tristate "VESA VGA graphics support"
+	depends on FB && X86
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -2057,7 +2057,7 @@
 
 config XEN_FBDEV_FRONTEND
 	tristate "Xen virtual frame buffer support"
-	depends on FB && XEN
+	depends on FB && PARAVIRT_XEN
 	select FB_SYS_FILLRECT
 	select FB_SYS_COPYAREA
 	select FB_SYS_IMAGEBLIT
--- linux-ec2-2.6.32.orig/drivers/video/sunxvr500.c
+++ linux-ec2-2.6.32/drivers/video/sunxvr500.c
@@ -242,11 +242,27 @@
 static int __devinit e3d_pci_register(struct pci_dev *pdev,
 				      const struct pci_device_id *ent)
 {
+	struct device_node *of_node;
+	const char *device_type;
 	struct fb_info *info;
 	struct e3d_info *ep;
 	unsigned int line_length;
 	int err;
 
+	of_node = pci_device_to_OF_node(pdev);
+	if (!of_node) {
+		printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
+		       pci_name(pdev));
+		return -ENODEV;
+	}
+
+	device_type = of_get_property(of_node, "device_type", NULL);
+	if (!device_type) {
+		printk(KERN_INFO "e3d: Ignoring secondary output device "
+		       "at %s\n", pci_name(pdev));
+		return -ENODEV;
+	}
+
 	err = pci_enable_device(pdev);
 	if (err < 0) {
 		printk(KERN_ERR "e3d: Cannot enable PCI device %s\n",
@@ -265,13 +281,7 @@
 	ep->info = info;
 	ep->pdev = pdev;
 	spin_lock_init(&ep->lock);
-	ep->of_node = pci_device_to_OF_node(pdev);
-	if (!ep->of_node) {
-		printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
-		       pci_name(pdev));
-		err = -ENODEV;
-		goto err_release_fb;
-	}
+	ep->of_node = of_node;
 
 	/* Read the PCI base register of the frame buffer, which we
 	 * need in order to interpret the RAMDAC_VID_*FB* values in
@@ -400,6 +410,7 @@
 
 static struct pci_device_id e3d_pci_table[] = {
 	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a0),	},
+	{	PCI_DEVICE(0x1091, 0x7a0),			},
 	{	PCI_DEVICE(PCI_VENDOR_ID_3DLABS, 0x7a2),	},
 	{	.vendor = PCI_VENDOR_ID_3DLABS,
 		.device = PCI_ANY_ID,
--- linux-ec2-2.6.32.orig/drivers/video/imxfb.c
+++ linux-ec2-2.6.32/drivers/video/imxfb.c
@@ -593,7 +593,8 @@
  */
 static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct imxfb_info *fbi = platform_get_drvdata(dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct imxfb_info *fbi = info->par;
 
 	pr_debug("%s\n", __func__);
 
@@ -603,7 +604,8 @@
 
 static int imxfb_resume(struct platform_device *dev)
 {
-	struct imxfb_info *fbi = platform_get_drvdata(dev);
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct imxfb_info *fbi = info->par;
 
 	pr_debug("%s\n", __func__);
 
--- linux-ec2-2.6.32.orig/drivers/video/mx3fb.c
+++ linux-ec2-2.6.32/drivers/video/mx3fb.c
@@ -324,8 +324,11 @@
 	unsigned long flags;
 	dma_cookie_t cookie;
 
-	dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
-		to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
+	if (mx3_fbi->txd)
+		dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
+			to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
+	else
+		dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi);
 
 	/* This enables the channel */
 	if (mx3_fbi->cookie < 0) {
@@ -646,6 +649,7 @@
 
 static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
 {
+	dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
 	/* This might be board-specific */
 	mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
 	return;
@@ -1486,12 +1490,12 @@
 		goto ersdc0;
 	}
 
+	mx3fb->backlight_level = 255;
+
 	ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
 	if (ret < 0)
 		goto eisdc0;
 
-	mx3fb->backlight_level = 255;
-
 	return 0;
 
 eisdc0:
--- linux-ec2-2.6.32.orig/drivers/video/console/tileblit.c
+++ linux-ec2-2.6.32/drivers/video/console/tileblit.c
@@ -83,7 +83,7 @@
 			int softback_lines, int fg, int bg)
 {
 	struct fb_tilecursor cursor;
-	int use_sw = (vc->vc_cursor_type & 0x01);
+	int use_sw = (vc->vc_cursor_type & 0x10);
 
 	cursor.sx = vc->vc_x;
 	cursor.sy = vc->vc_y;
--- linux-ec2-2.6.32.orig/drivers/video/backlight/mbp_nvidia_bl.c
+++ linux-ec2-2.6.32/drivers/video/backlight/mbp_nvidia_bl.c
@@ -139,6 +139,51 @@
 static const struct dmi_system_id __initdata mbp_device_table[] = {
 	{
 		.callback	= mbp_dmi_match,
+		.ident		= "MacBook 1,1",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
+		},
+		.driver_data	= (void *)&intel_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBook 2,1",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
+		},
+		.driver_data	= (void *)&intel_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBook 3,1",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"),
+		},
+		.driver_data	= (void *)&intel_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBook 4,1",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"),
+		},
+		.driver_data	= (void *)&intel_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBook 4,2",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"),
+		},
+		.driver_data	= (void *)&intel_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
 		.ident		= "MacBookPro 3,1",
 		.matches	= {
 			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
@@ -227,6 +272,24 @@
 		},
 		.driver_data	= (void *)&nvidia_chipset_data,
 	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBookAir 3,1",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"),
+		},
+		.driver_data	= (void *)&nvidia_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBookAir 3,2",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"),
+		},
+		.driver_data	= (void *)&nvidia_chipset_data,
+	},
 	{ }
 };
 
--- linux-ec2-2.6.32.orig/drivers/video/backlight/backlight.c
+++ linux-ec2-2.6.32/drivers/video/backlight/backlight.c
@@ -196,12 +196,12 @@
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
-	if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
-		mutex_lock(&bd->ops_lock);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
 		bd->props.state |= BL_CORE_SUSPENDED;
 		backlight_update_status(bd);
-		mutex_unlock(&bd->ops_lock);
 	}
+	mutex_unlock(&bd->ops_lock);
 
 	return 0;
 }
@@ -210,12 +210,12 @@
 {
 	struct backlight_device *bd = to_backlight_device(dev);
 
-	if (bd->ops->options & BL_CORE_SUSPENDRESUME) {
-		mutex_lock(&bd->ops_lock);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) {
 		bd->props.state &= ~BL_CORE_SUSPENDED;
 		backlight_update_status(bd);
-		mutex_unlock(&bd->ops_lock);
 	}
+	mutex_unlock(&bd->ops_lock);
 
 	return 0;
 }
--- linux-ec2-2.6.32.orig/drivers/video/matrox/g450_pll.c
+++ linux-ec2-2.6.32/drivers/video/matrox/g450_pll.c
@@ -368,7 +368,8 @@
 					M1064_XDVICLKCTRL_C1DVICLKEN |
 					M1064_XDVICLKCTRL_DVILOOPCTL |
 					M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
-				matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp);
+                                /* Setting this breaks PC systems so don't do it */
+				/* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
 				matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
 						 xpwrctrl);
 
--- linux-ec2-2.6.32.orig/drivers/video/sis/sis_main.c
+++ linux-ec2-2.6.32/drivers/video/sis/sis_main.c
@@ -1701,6 +1701,9 @@
 		break;
 
 	   case FBIOGET_VBLANK:
+
+		memset(&sisvbblank, 0, sizeof(struct fb_vblank));
+
 		sisvbblank.count = 0;
 		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
 
--- linux-ec2-2.6.32.orig/drivers/video/via/accel.c
+++ linux-ec2-2.6.32/drivers/video/via/accel.c
@@ -277,11 +277,12 @@
 		writel(tmp, engine + 0x1C);
 	}
 
-	if (op != VIA_BITBLT_COLOR)
+	if (op == VIA_BITBLT_FILL) {
+		writel(fg_color, engine + 0x58);
+	} else if (op == VIA_BITBLT_MONO) {
 		writel(fg_color, engine + 0x4C);
-
-	if (op == VIA_BITBLT_MONO)
 		writel(bg_color, engine + 0x50);
+	}
 
 	if (op == VIA_BITBLT_FILL)
 		ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
--- linux-ec2-2.6.32.orig/drivers/video/via/ioctl.c
+++ linux-ec2-2.6.32/drivers/video/via/ioctl.c
@@ -25,6 +25,8 @@
 {
 	struct viafb_ioctl_info viainfo;
 
+	memset(&viainfo, 0, sizeof(struct viafb_ioctl_info));
+
 	viainfo.viafb_id = VIAID;
 	viainfo.vendor_id = PCI_VIA_VENDOR_ID;
 
--- linux-ec2-2.6.32.orig/drivers/base/core.c
+++ linux-ec2-2.6.32/drivers/base/core.c
@@ -56,7 +56,14 @@
  */
 const char *dev_driver_string(const struct device *dev)
 {
-	return dev->driver ? dev->driver->name :
+	struct device_driver *drv;
+
+	/* dev->driver can change to NULL underneath us because of unbinding,
+	 * so be careful about accessing it.  dev->bus and dev->class should
+	 * never change once they are set, so they don't need special care.
+	 */
+	drv = ACCESS_ONCE(dev->driver);
+	return drv ? drv->name :
 			(dev->bus ? dev->bus->name :
 			(dev->class ? dev->class->name : ""));
 }
@@ -596,6 +603,7 @@
 	int retval;
 
 	if (dev->class) {
+		static DEFINE_MUTEX(gdp_mutex);
 		struct kobject *kobj = NULL;
 		struct kobject *parent_kobj;
 		struct kobject *k;
@@ -612,6 +620,8 @@
 		else
 			parent_kobj = &parent->kobj;
 
+		mutex_lock(&gdp_mutex);
+
 		/* find our class-directory at the parent and reference it */
 		spin_lock(&dev->class->p->class_dirs.list_lock);
 		list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
@@ -620,20 +630,26 @@
 				break;
 			}
 		spin_unlock(&dev->class->p->class_dirs.list_lock);
-		if (kobj)
+		if (kobj) {
+			mutex_unlock(&gdp_mutex);
 			return kobj;
+		}
 
 		/* or create a new class-directory at the parent device */
 		k = kobject_create();
-		if (!k)
+		if (!k) {
+			mutex_unlock(&gdp_mutex);
 			return NULL;
+		}
 		k->kset = &dev->class->p->class_dirs;
 		retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
 		if (retval < 0) {
+			mutex_unlock(&gdp_mutex);
 			kobject_put(k);
 			return NULL;
 		}
 		/* do not emit an uevent for this simple "glue" directory */
+		mutex_unlock(&gdp_mutex);
 		return k;
 	}
 
--- linux-ec2-2.6.32.orig/drivers/base/firmware_class.c
+++ linux-ec2-2.6.32/drivers/base/firmware_class.c
@@ -125,6 +125,17 @@
 	return sprintf(buf, "%d\n", loading);
 }
 
+static void firmware_free_data(const struct firmware *fw)
+{
+	int i;
+	vunmap(fw->data);
+	if (fw->pages) {
+		for (i = 0; i < PFN_UP(fw->size); i++)
+			__free_page(fw->pages[i]);
+		kfree(fw->pages);
+	}
+}
+
 /* Some architectures don't have PAGE_KERNEL_RO */
 #ifndef PAGE_KERNEL_RO
 #define PAGE_KERNEL_RO PAGE_KERNEL
@@ -157,21 +168,21 @@
 			mutex_unlock(&fw_lock);
 			break;
 		}
-		vfree(fw_priv->fw->data);
-		fw_priv->fw->data = NULL;
+		firmware_free_data(fw_priv->fw);
+		memset(fw_priv->fw, 0, sizeof(struct firmware));
+		/* If the pages are not owned by 'struct firmware' */
 		for (i = 0; i < fw_priv->nr_pages; i++)
 			__free_page(fw_priv->pages[i]);
 		kfree(fw_priv->pages);
 		fw_priv->pages = NULL;
 		fw_priv->page_array_size = 0;
 		fw_priv->nr_pages = 0;
-		fw_priv->fw->size = 0;
 		set_bit(FW_STATUS_LOADING, &fw_priv->status);
 		mutex_unlock(&fw_lock);
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
-			vfree(fw_priv->fw->data);
+			vunmap(fw_priv->fw->data);
 			fw_priv->fw->data = vmap(fw_priv->pages,
 						 fw_priv->nr_pages,
 						 0, PAGE_KERNEL_RO);
@@ -179,7 +190,10 @@
 				dev_err(dev, "%s: vmap() failed\n", __func__);
 				goto err;
 			}
-			/* Pages will be freed by vfree() */
+			/* Pages are now owned by 'struct firmware' */
+			fw_priv->fw->pages = fw_priv->pages;
+			fw_priv->pages = NULL;
+
 			fw_priv->page_array_size = 0;
 			fw_priv->nr_pages = 0;
 			complete(&fw_priv->completion);
@@ -572,7 +586,7 @@
 			if (fw->data == builtin->data)
 				goto free_fw;
 		}
-		vfree(fw->data);
+		firmware_free_data(fw);
 	free_fw:
 		kfree(fw);
 	}
--- linux-ec2-2.6.32.orig/drivers/base/Kconfig
+++ linux-ec2-2.6.32/drivers/base/Kconfig
@@ -151,4 +151,12 @@
 	bool
 	default n
 
+config SR_REPORT_TIME_LIMIT
+       int "Default low threshold"
+       depends on PM
+       default 100
+       help
+         Print suspend/resume information for driver/device for time greater
+         then default msec, ie 100 msec.
+
 endmenu
--- linux-ec2-2.6.32.orig/drivers/base/class.c
+++ linux-ec2-2.6.32/drivers/base/class.c
@@ -59,6 +59,8 @@
 	else
 		pr_debug("class '%s' does not have a release() function, "
 			 "be careful\n", class->name);
+
+	kfree(cp);
 }
 
 static struct sysfs_ops class_sysfs_ops = {
--- linux-ec2-2.6.32.orig/drivers/base/devtmpfs.c
+++ linux-ec2-2.6.32/drivers/base/devtmpfs.c
@@ -295,6 +295,19 @@
 		if (dentry->d_inode) {
 			err = vfs_getattr(nd.path.mnt, dentry, &stat);
 			if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+				struct iattr newattrs;
+				/*
+				 * before unlinking this node, reset permissions
+				 * of possible references like hardlinks
+				 */
+				newattrs.ia_uid = 0;
+				newattrs.ia_gid = 0;
+				newattrs.ia_mode = stat.mode & ~0777;
+				newattrs.ia_valid =
+					ATTR_UID|ATTR_GID|ATTR_MODE;
+				mutex_lock(&dentry->d_inode->i_mutex);
+				notify_change(dentry, &newattrs);
+				mutex_unlock(&dentry->d_inode->i_mutex);
 				err = vfs_unlink(nd.path.dentry->d_inode,
 						 dentry);
 				if (!err || err == -ENOENT)
@@ -353,6 +366,7 @@
 {
 	int err;
 	struct vfsmount *mnt;
+	char options[] = "mode=0755";
 
 	err = register_filesystem(&dev_fs_type);
 	if (err) {
@@ -361,7 +375,7 @@
 		return err;
 	}
 
-	mnt = kern_mount(&dev_fs_type);
+	mnt = kern_mount_data(&dev_fs_type, options);
 	if (IS_ERR(mnt)) {
 		err = PTR_ERR(mnt);
 		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
--- linux-ec2-2.6.32.orig/drivers/base/cpu.c
+++ linux-ec2-2.6.32/drivers/base/cpu.c
@@ -78,7 +78,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-#ifdef CONFIG_KEXEC
+#if defined(CONFIG_KEXEC) && !defined(CONFIG_XEN)
 #include <linux/kexec.h>
 
 static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
@@ -149,7 +149,7 @@
 	/* display offline cpus < nr_cpu_ids */
 	if (!alloc_cpumask_var(&offline, GFP_KERNEL))
 		return -ENOMEM;
-	cpumask_complement(offline, cpu_online_mask);
+	cpumask_andnot(offline, cpu_possible_mask, cpu_online_mask);
 	n = cpulist_scnprintf(buf, len, offline);
 	free_cpumask_var(offline);
 
@@ -217,7 +217,7 @@
 	if (!error)
 		register_cpu_under_node(num, cpu_to_node(num));
 
-#ifdef CONFIG_KEXEC
+#if defined(CONFIG_KEXEC) && !defined(CONFIG_XEN)
 	if (!error)
 		error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
 #endif
--- linux-ec2-2.6.32.orig/drivers/base/power/runtime.c
+++ linux-ec2-2.6.32/drivers/base/power/runtime.c
@@ -777,7 +777,7 @@
 	}
 
 	if (parent) {
-		spin_lock(&parent->power.lock);
+		spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);
 
 		/*
 		 * It is invalid to put an active child under a parent that is
--- linux-ec2-2.6.32.orig/drivers/base/power/main.c
+++ linux-ec2-2.6.32/drivers/base/power/main.c
@@ -324,6 +324,41 @@
 		kobject_name(&dev->kobj), pm_verb(state.event), info, error);
 }
 
+static void device_show_time(struct device *dev, ktime_t starttime, pm_message_t state, char *info)
+{
+	ktime_t calltime;
+	s64 usecs64;
+	int usecs;
+
+	calltime = ktime_get();
+	usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
+	do_div(usecs64, NSEC_PER_USEC);
+	usecs = usecs64;
+	if (usecs == 0)
+		usecs = 1;
+	if ((usecs / USEC_PER_MSEC) > CONFIG_SR_REPORT_TIME_LIMIT)
+		pr_info("PM: %s%s%s of drv:%s dev:%s complete after %ld.%03ld msecs\n", info ?: "", info ? " " : "", pm_verb(state.event),
+		dev_driver_string(dev), dev_name(dev), usecs / USEC_PER_MSEC,
+		usecs % USEC_PER_MSEC);
+}
+
+static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
+{
+	ktime_t calltime;
+	s64 usecs64;
+	int usecs;
+
+	calltime = ktime_get();
+	usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
+	do_div(usecs64, NSEC_PER_USEC);
+	usecs = usecs64;
+	if (usecs == 0)
+		usecs = 1;
+	pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
+		info ?: "", info ? " " : "", pm_verb(state.event),
+		usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
+}
+
 /*------------------------- Resume routines -------------------------*/
 
 /**
@@ -337,6 +372,7 @@
 static int device_resume_noirq(struct device *dev, pm_message_t state)
 {
 	int error = 0;
+	ktime_t starttime = ktime_get();
 
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
@@ -347,6 +383,7 @@
 	if (dev->bus->pm) {
 		pm_dev_dbg(dev, state, "EARLY ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
+		device_show_time(dev, starttime, state, "early");
 	}
  End:
 	TRACE_RESUME(error);
@@ -363,6 +400,7 @@
 void dpm_resume_noirq(pm_message_t state)
 {
 	struct device *dev;
+	ktime_t starttime = ktime_get();
 
 	mutex_lock(&dpm_list_mtx);
 	transition_started = false;
@@ -376,6 +414,7 @@
 				pm_dev_err(dev, state, " early", error);
 		}
 	mutex_unlock(&dpm_list_mtx);
+	dpm_show_time(starttime, state, "early");
 	resume_device_irqs();
 }
 EXPORT_SYMBOL_GPL(dpm_resume_noirq);
@@ -388,6 +427,7 @@
 static int device_resume(struct device *dev, pm_message_t state)
 {
 	int error = 0;
+	ktime_t starttime = ktime_get();
 
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
@@ -424,6 +464,7 @@
 			error = dev->class->resume(dev);
 		}
 	}
+	device_show_time(dev, starttime, state, NULL);
  End:
 	up(&dev->sem);
 
@@ -441,6 +482,7 @@
 static void dpm_resume(pm_message_t state)
 {
 	struct list_head list;
+	ktime_t starttime = ktime_get();
 
 	INIT_LIST_HEAD(&list);
 	mutex_lock(&dpm_list_mtx);
@@ -469,6 +511,7 @@
 	}
 	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
+	dpm_show_time(starttime, state, NULL);
 }
 
 /**
@@ -583,6 +626,7 @@
 static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
 	int error = 0;
+	ktime_t starttime = ktime_get();
 
 	if (!dev->bus)
 		return 0;
@@ -590,6 +634,7 @@
 	if (dev->bus->pm) {
 		pm_dev_dbg(dev, state, "LATE ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
+		device_show_time(dev, starttime, state, "late");
 	}
 	return error;
 }
@@ -604,6 +649,7 @@
 int dpm_suspend_noirq(pm_message_t state)
 {
 	struct device *dev;
+	ktime_t starttime = ktime_get();
 	int error = 0;
 
 	suspend_device_irqs();
@@ -619,6 +665,8 @@
 	mutex_unlock(&dpm_list_mtx);
 	if (error)
 		dpm_resume_noirq(resume_event(state));
+	else
+		dpm_show_time(starttime, state, "late");
 	return error;
 }
 EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
@@ -631,6 +679,7 @@
 static int device_suspend(struct device *dev, pm_message_t state)
 {
 	int error = 0;
+	ktime_t starttime = ktime_get();
 
 	down(&dev->sem);
 
@@ -666,6 +715,7 @@
 			suspend_report_result(dev->bus->suspend, error);
 		}
 	}
+	device_show_time(dev, starttime, state, NULL);
  End:
 	up(&dev->sem);
 
@@ -679,6 +729,7 @@
 static int dpm_suspend(pm_message_t state)
 {
 	struct list_head list;
+	ktime_t starttime = ktime_get();
 	int error = 0;
 
 	INIT_LIST_HEAD(&list);
@@ -704,6 +755,8 @@
 	}
 	list_splice(&list, dpm_list.prev);
 	mutex_unlock(&dpm_list_mtx);
+	if (!error)
+		dpm_show_time(starttime, state, NULL);
 	return error;
 }
 
--- linux-ec2-2.6.32.orig/scripts/mkmakefile
+++ linux-ec2-2.6.32/scripts/mkmakefile
@@ -44,7 +44,9 @@
 
 Makefile:;
 
-\$(all) %/: all
+\$(all): all
 	@:
 
+%/: all
+	@:
 EOF
--- linux-ec2-2.6.32.orig/scripts/Makefile.modbuiltin
+++ linux-ec2-2.6.32/scripts/Makefile.modbuiltin
@@ -0,0 +1,55 @@
+# ==========================================================================
+# Generating modules.builtin
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __modbuiltin
+__modbuiltin:
+
+-include include/config/auto.conf
+# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
+# That way, we get the list of built-in modules in obj-Y
+-include include/config/tristate.conf
+
+include scripts/Kbuild.include
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
+include $(kbuild-file)
+
+include scripts/Makefile.lib
+__subdir-Y     := $(patsubst %/,%,$(filter %/, $(obj-Y)))
+subdir-Y       += $(__subdir-Y)
+subdir-ym      := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
+subdir-ym      := $(addprefix $(obj)/,$(subdir-ym))
+obj-Y          := $(addprefix $(obj)/,$(obj-Y))
+
+modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym))
+modbuiltin-mods    := $(filter %.ko, $(obj-Y:.o=.ko))
+modbuiltin-target  := $(obj)/modules.builtin
+
+__modbuiltin: $(modbuiltin-target) $(subdir-ym)
+	@:
+
+$(modbuiltin-target): $(subdir-ym) FORCE
+	$(Q)(for m in $(modbuiltin-mods); do echo kernel/$$m; done;	\
+	cat /dev/null $(modbuiltin-subdirs)) > $@
+
+PHONY += FORCE
+
+FORCE:
+
+# Descending
+# ---------------------------------------------------------------------------
+
+PHONY += $(subdir-ym)
+$(subdir-ym):
+	$(Q)$(MAKE) $(modbuiltin)=$@
+
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
--- linux-ec2-2.6.32.orig/scripts/Makefile.xen.awk
+++ linux-ec2-2.6.32/scripts/Makefile.xen.awk
@@ -0,0 +1,34 @@
+BEGIN {
+	is_rule = 0
+}
+
+/^[[:space:]]*#/ {
+	next
+}
+
+/^[[:space:]]*$/ {
+	if (is_rule)
+		print("")
+	is_rule = 0
+	next
+}
+
+/:[[:space:]]*\$\(src\)\/%\.[cS][[:space:]]/ {
+	line = gensub(/%.([cS])/, "%-xen.\\1", "g", $0)
+	line = gensub(/(single-used-m)/, "xen-\\1", "g", line)
+	print line
+	is_rule = 1
+	next
+}
+
+/^[^\t]$/ {
+	if (is_rule)
+		print("")
+	is_rule = 0
+	next
+}
+
+is_rule {
+	print $0
+	next
+}
--- linux-ec2-2.6.32.orig/scripts/Makefile.lib
+++ linux-ec2-2.6.32/scripts/Makefile.lib
@@ -22,6 +22,12 @@
 
 lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
 
+# Remove objects forcibly disabled
+
+obj-y := $(filter-out $(disabled-obj-y),$(obj-y))
+obj-m := $(filter-out $(disabled-obj-y),$(obj-m))
+lib-y := $(filter-out $(disabled-obj-y),$(lib-y))
+
 
 # Handle objects in subdirs
 # ---------------------------------------------------------------------------
--- linux-ec2-2.6.32.orig/scripts/Makefile.build
+++ linux-ec2-2.6.32/scripts/Makefile.build
@@ -76,6 +76,21 @@
 $(warning kbuild: Makefile.build is included improperly)
 endif
 
+ifeq ($(CONFIG_XEN),y)
+Makefile.xen := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(objtree)/scripts)/Makefile.xen
+$(Makefile.xen): $(srctree)/scripts/Makefile.xen.awk $(srctree)/scripts/Makefile.build
+	@echo '  Updating $@'
+	$(if $(shell echo a | $(AWK) '{ print gensub(/a/, "AA", "g"); }'),\
+        ,$(error 'Your awk program does not define gensub.  Use gawk or another awk with gensub'))
+	@$(AWK) -f $< $(filter-out $<,$^) >$@
+
+xen-src-single-used-m	:= $(patsubst $(srctree)/%,%,$(wildcard $(addprefix $(srctree)/,$(single-used-m:.o=-xen.c))))
+xen-single-used-m	:= $(xen-src-single-used-m:-xen.c=.o)
+single-used-m		:= $(filter-out $(xen-single-used-m),$(single-used-m))
+
+-include $(Makefile.xen)
+endif
+
 # ===========================================================================
 
 ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
--- linux-ec2-2.6.32.orig/scripts/Kbuild.include
+++ linux-ec2-2.6.32/scripts/Kbuild.include
@@ -149,6 +149,12 @@
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
+# Usage:
+# $(Q)$(MAKE) $(modbuiltin)=dir
+modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
+
 # Prefix -I with $(srctree) if it is not an absolute path.
 # skip if -I has no parameter
 addtree = $(if $(patsubst -I%,%,$(1)), \
--- linux-ec2-2.6.32.orig/scripts/mod/modpost.c
+++ linux-ec2-2.6.32/scripts/mod/modpost.c
@@ -1311,7 +1311,7 @@
 	int section = sechdr->sh_info;
 
 	return (void *)elf->hdr + sechdrs[section].sh_offset +
-		(r->r_offset - sechdrs[section].sh_addr);
+		r->r_offset - sechdrs[section].sh_addr;
 }
 
 static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
--- linux-ec2-2.6.32.orig/scripts/kconfig/conf.c
+++ linux-ec2-2.6.32/scripts/kconfig/conf.c
@@ -330,7 +330,7 @@
 		}
 		if (!child)
 			continue;
-		if (line[strlen(line) - 1] == '?') {
+		if (line[0] && line[strlen(line) - 1] == '?') {
 			print_help(child);
 			continue;
 		}
--- linux-ec2-2.6.32.orig/scripts/kconfig/confdata.c
+++ linux-ec2-2.6.32/scripts/kconfig/confdata.c
@@ -677,7 +677,7 @@
 	struct symbol *sym;
 	const char *str;
 	const char *name;
-	FILE *out, *out_h;
+	FILE *out, *tristate, *out_h;
 	time_t now;
 	int i, l;
 
@@ -692,9 +692,16 @@
 	if (!out)
 		return 1;
 
+	tristate = fopen(".tmpconfig_tristate", "w");
+	if (!tristate) {
+		fclose(out);
+		return 1;
+	}
+
 	out_h = fopen(".tmpconfig.h", "w");
 	if (!out_h) {
 		fclose(out);
+		fclose(tristate);
 		return 1;
 	}
 
@@ -707,6 +714,9 @@
 		     "# %s"
 		     "#\n",
 		     sym_get_string_value(sym), ctime(&now));
+	fprintf(tristate, "#\n"
+			  "# Automatically generated - do not edit\n"
+			  "\n");
 	fprintf(out_h, "/*\n"
 		       " * Automatically generated C config: don't edit\n"
 		       " * Linux kernel version: %s\n"
@@ -727,10 +737,14 @@
 				break;
 			case mod:
 				fprintf(out, "CONFIG_%s=m\n", sym->name);
+				fprintf(tristate, "CONFIG_%s=M\n", sym->name);
 				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 				break;
 			case yes:
 				fprintf(out, "CONFIG_%s=y\n", sym->name);
+				if (sym->type == S_TRISTATE)
+					fprintf(tristate, "CONFIG_%s=Y\n",
+							sym->name);
 				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 				break;
 			}
@@ -772,6 +786,7 @@
 		}
 	}
 	fclose(out);
+	fclose(tristate);
 	fclose(out_h);
 
 	name = getenv("KCONFIG_AUTOHEADER");
@@ -779,6 +794,11 @@
 		name = "include/linux/autoconf.h";
 	if (rename(".tmpconfig.h", name))
 		return 1;
+	name = getenv("KCONFIG_TRISTATE");
+	if (!name)
+		name = "include/config/tristate.conf";
+	if (rename(".tmpconfig_tristate", name))
+		return 1;
 	name = conf_get_autoconfig_name();
 	/*
 	 * This must be the last step, kbuild has a dependency on auto.conf
--- linux-ec2-2.6.32.orig/ipc/sem.c
+++ linux-ec2-2.6.32/ipc/sem.c
@@ -129,6 +129,7 @@
 void sem_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &sem_ids(ns), freeary);
+	idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr);
 }
 #endif
 
@@ -559,6 +560,8 @@
 	    {
 		struct semid_ds out;
 
+		memset(&out, 0, sizeof(out));
+
 		ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm);
 
 		out.sem_otime	= in->sem_otime;
--- linux-ec2-2.6.32.orig/ipc/shm.c
+++ linux-ec2-2.6.32/ipc/shm.c
@@ -101,6 +101,7 @@
 void shm_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &shm_ids(ns), do_shm_rmid);
+	idr_destroy(&ns->ids[IPC_SHM_IDS].ipcs_idr);
 }
 #endif
 
@@ -290,28 +291,28 @@
 	unsigned long flags)
 {
 	struct shm_file_data *sfd = shm_file_data(file);
-	return get_unmapped_area(sfd->file, addr, len, pgoff, flags);
-}
-
-int is_file_shm_hugepages(struct file *file)
-{
-	int ret = 0;
-
-	if (file->f_op == &shm_file_operations) {
-		struct shm_file_data *sfd;
-		sfd = shm_file_data(file);
-		ret = is_file_hugepages(sfd->file);
-	}
-	return ret;
+	return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len,
+						pgoff, flags);
 }
 
 static const struct file_operations shm_file_operations = {
 	.mmap		= shm_mmap,
 	.fsync		= shm_fsync,
 	.release	= shm_release,
+};
+
+static const struct file_operations shm_file_operations_huge = {
+	.mmap		= shm_mmap,
+	.fsync		= shm_fsync,
+	.release	= shm_release,
 	.get_unmapped_area	= shm_get_unmapped_area,
 };
 
+int is_file_shm_hugepages(struct file *file)
+{
+	return file->f_op == &shm_file_operations_huge;
+}
+
 static const struct vm_operations_struct shm_vm_ops = {
 	.open	= shm_open,	/* callback for a new vm-area open */
 	.close	= shm_close,	/* callback for when the vm-area is released */
@@ -473,6 +474,7 @@
 	    {
 		struct shmid_ds out;
 
+		memset(&out, 0, sizeof(out));
 		ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
 		out.shm_segsz	= in->shm_segsz;
 		out.shm_atime	= in->shm_atime;
@@ -889,7 +891,10 @@
 	if (!sfd)
 		goto out_put_dentry;
 
-	file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations);
+	file = alloc_file(path.mnt, path.dentry, f_mode,
+			is_file_hugepages(shp->shm_file) ?
+				&shm_file_operations_huge :
+				&shm_file_operations);
 	if (!file)
 		goto out_free;
 	ima_counts_get(file);
--- linux-ec2-2.6.32.orig/ipc/compat.c
+++ linux-ec2-2.6.32/ipc/compat.c
@@ -242,6 +242,8 @@
 	struct semid64_ds __user *up64;
 	int version = compat_ipc_parse_version(&third);
 
+	memset(&s64, 0, sizeof(s64));
+
 	if (!uptr)
 		return -EINVAL;
 	if (get_user(pad, (u32 __user *) uptr))
@@ -422,6 +424,8 @@
 	int version = compat_ipc_parse_version(&second);
 	void __user *p;
 
+	memset(&m64, 0, sizeof(m64));
+
 	switch (second & (~IPC_64)) {
 	case IPC_INFO:
 	case IPC_RMID:
@@ -595,6 +599,8 @@
 	int err, err2;
 	int version = compat_ipc_parse_version(&second);
 
+	memset(&s64, 0, sizeof(s64));
+
 	switch (second & (~IPC_64)) {
 	case IPC_RMID:
 	case SHM_LOCK:
--- linux-ec2-2.6.32.orig/ipc/mqueue.c
+++ linux-ec2-2.6.32/ipc/mqueue.c
@@ -706,7 +706,7 @@
 	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
 	if (IS_ERR(dentry)) {
 		error = PTR_ERR(dentry);
-		goto out_err;
+		goto out_putfd;
 	}
 	mntget(ipc_ns->mq_mnt);
 
@@ -744,7 +744,6 @@
 	mntput(ipc_ns->mq_mnt);
 out_putfd:
 	put_unused_fd(fd);
-out_err:
 	fd = error;
 out_upsem:
 	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
--- linux-ec2-2.6.32.orig/ipc/compat_mq.c
+++ linux-ec2-2.6.32/ipc/compat_mq.c
@@ -53,6 +53,9 @@
 	void __user *p = NULL;
 	if (u_attr && oflag & O_CREAT) {
 		struct mq_attr attr;
+
+		memset(&attr, 0, sizeof(attr));
+
 		p = compat_alloc_user_space(sizeof(attr));
 		if (get_compat_mq_attr(&attr, u_attr) ||
 		    copy_to_user(p, &attr, sizeof(attr)))
@@ -127,6 +130,8 @@
 	struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p));
 	long ret;
 
+	memset(&mqstat, 0, sizeof(mqstat));
+
 	if (u_mqstat) {
 		if (get_compat_mq_attr(&mqstat, u_mqstat) ||
 		    copy_to_user(p, &mqstat, sizeof(mqstat)))
--- linux-ec2-2.6.32.orig/ipc/msg.c
+++ linux-ec2-2.6.32/ipc/msg.c
@@ -125,6 +125,7 @@
 void msg_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &msg_ids(ns), freeque);
+	idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
 }
 #endif
 
--- linux-ec2-2.6.32.orig/init/initramfs.c
+++ linux-ec2-2.6.32/init/initramfs.c
@@ -8,6 +8,7 @@
 #include <linux/dirent.h>
 #include <linux/syscalls.h>
 #include <linux/utime.h>
+#include <linux/async.h>
 
 static __initdata char *message;
 static void __init error(char *x)
@@ -455,7 +456,8 @@
 					 compress_name);
 				message = msg_buf;
 			}
-		}
+		} else
+			error("junk in compressed archive");
 		if (state != Reset)
 			error("junk in compressed archive");
 		this_header = saved_offset + my_inptr;
@@ -565,7 +567,9 @@
 }
 #endif
 
-static int __init populate_rootfs(void)
+LIST_HEAD(populate_rootfs_domain);
+
+static void __init async_populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
 			 __initramfs_end - __initramfs_start);
@@ -579,7 +583,7 @@
 			initrd_end - initrd_start);
 		if (!err) {
 			free_initrd();
-			return 0;
+			return;
 		} else {
 			clean_rootfs();
 			unpack_to_rootfs(__initramfs_start,
@@ -603,6 +607,25 @@
 		free_initrd();
 #endif
 	}
-	return 0;
+	return;
+}
+
+static int __initdata rootfs_populated;
+
+static int __init populate_rootfs_early(void)
+{
+	if (num_online_cpus() > 1) {
+		rootfs_populated = 1;
+		async_schedule_domain(async_populate_rootfs, NULL,
+						&populate_rootfs_domain);
+	}
 }
+static int __init populate_rootfs(void)
+{
+	if (!rootfs_populated)
+		async_schedule_domain(async_populate_rootfs, NULL,
+						&populate_rootfs_domain);
+}
+
+earlyrootfs_initcall(populate_rootfs_early);
 rootfs_initcall(populate_rootfs);
--- linux-ec2-2.6.32.orig/init/version.c
+++ linux-ec2-2.6.32/init/version.c
@@ -39,7 +39,11 @@
 /* FIXED STRINGS! Don't touch! */
 const char linux_banner[] =
 	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION
+#ifdef CONFIG_VERSION_SIGNATURE
+        " (" CONFIG_VERSION_SIGNATURE ")"
+#endif
+	"\n";
 
 const char linux_proc_banner[] =
 	"%s version %s"
--- linux-ec2-2.6.32.orig/init/Kconfig
+++ linux-ec2-2.6.32/init/Kconfig
@@ -166,6 +166,15 @@
 
 endchoice
 
+config VERSION_SIGNATURE
+	string "Arbitrary version signature"
+	help
+	  This string will be created in a file, /proc/version_signature. It
+	  is useful in determining arbitrary data about your kernel. For instance,
+	  if you have several kernels of the same version, but need to keep track
+	  of a revision of the same kernel, but not affect it's ability to load
+	  compatible modules, this is the easiest way to do that.
+
 config SWAP
 	bool "Support for paging of anonymous memory (swap)"
 	depends on MMU && BLOCK
@@ -426,57 +435,6 @@
 config HAVE_UNSTABLE_SCHED_CLOCK
 	bool
 
-config GROUP_SCHED
-	bool "Group CPU scheduler"
-	depends on EXPERIMENTAL
-	default n
-	help
-	  This feature lets CPU scheduler recognize task groups and control CPU
-	  bandwidth allocation to such task groups.
-	  In order to create a group from arbitrary set of processes, use
-	  CONFIG_CGROUPS. (See Control Group support.)
-
-config FAIR_GROUP_SCHED
-	bool "Group scheduling for SCHED_OTHER"
-	depends on GROUP_SCHED
-	default GROUP_SCHED
-
-config RT_GROUP_SCHED
-	bool "Group scheduling for SCHED_RR/FIFO"
-	depends on EXPERIMENTAL
-	depends on GROUP_SCHED
-	default n
-	help
-	  This feature lets you explicitly allocate real CPU bandwidth
-	  to users or control groups (depending on the "Basis for grouping tasks"
-	  setting below. If enabled, it will also make it impossible to
-	  schedule realtime tasks for non-root users until you allocate
-	  realtime bandwidth for them.
-	  See Documentation/scheduler/sched-rt-group.txt for more information.
-
-choice
-	depends on GROUP_SCHED
-	prompt "Basis for grouping tasks"
-	default USER_SCHED
-
-config USER_SCHED
-	bool "user id"
-	help
-	  This option will choose userid as the basis for grouping
-	  tasks, thus providing equal CPU bandwidth to each user.
-
-config CGROUP_SCHED
-	bool "Control groups"
- 	depends on CGROUPS
- 	help
-	  This option allows you to create arbitrary task groups
-	  using the "cgroup" pseudo filesystem and control
-	  the cpu bandwidth allocated to each such task group.
-	  Refer to Documentation/cgroups/cgroups.txt for more
-	  information on "cgroup" pseudo filesystem.
-
-endchoice
-
 menuconfig CGROUPS
 	boolean "Control Group support"
 	help
@@ -597,6 +555,35 @@
 	  Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page
 	  size is 4096bytes, 512k per 1Gbytes of swap.
 
+menuconfig CGROUP_SCHED
+	bool "Group CPU scheduler"
+	depends on EXPERIMENTAL && CGROUPS
+	default n
+	help
+	  This feature lets CPU scheduler recognize task groups and control CPU
+	  bandwidth allocation to such task groups. It uses cgroups to group
+	  tasks.
+
+if CGROUP_SCHED
+config FAIR_GROUP_SCHED
+	bool "Group scheduling for SCHED_OTHER"
+	depends on CGROUP_SCHED
+	default CGROUP_SCHED
+
+config RT_GROUP_SCHED
+	bool "Group scheduling for SCHED_RR/FIFO"
+	depends on EXPERIMENTAL
+	depends on CGROUP_SCHED
+	default n
+	help
+	  This feature lets you explicitly allocate real CPU bandwidth
+	  to task groups. If enabled, it will also make it impossible to
+	  schedule realtime tasks for non-root users until you allocate
+	  realtime bandwidth for them.
+	  See Documentation/scheduler/sched-rt-group.txt for more information.
+
+endif #CGROUP_SCHED
+
 endif # CGROUPS
 
 config MM_OWNER
@@ -1050,6 +1037,7 @@
 	  per cpu and per node queues.
 
 config SLUB
+	depends on BROKEN || NUMA || !DISCONTIGMEM
 	bool "SLUB (Unqueued Allocator)"
 	help
 	   SLUB is a slab allocator that minimizes cache line usage
--- linux-ec2-2.6.32.orig/init/main.c
+++ linux-ec2-2.6.32/init/main.c
@@ -234,7 +234,7 @@
 
 static int __init quiet_kernel(char *str)
 {
-	console_loglevel = 4;
+	console_loglevel = 2;
 	return 0;
 }
 
@@ -369,12 +369,6 @@
 {
 	unsigned int cpu;
 
-	/*
-	 * Set up the current CPU as possible to migrate to.
-	 * The other ones will be done by cpu_up/cpu_down()
-	 */
-	set_cpu_active(smp_processor_id(), true);
-
 	/* FIXME: This should be done in userspace --RR */
 	for_each_present_cpu(cpu) {
 		if (num_online_cpus() >= setup_max_cpus)
@@ -413,16 +407,24 @@
  * gcc-3.4 accidentally inlines this function, so use noinline.
  */
 
+static __initdata DECLARE_COMPLETION(kthreadd_done);
+
 static noinline void __init_refok rest_init(void)
 	__releases(kernel_lock)
 {
 	int pid;
 
 	rcu_scheduler_starting();
+	/*
+	 * We need to spawn init first so that it obtains pid-1, however
+	 * the init task will end up wanting to create kthreads, which, if
+	 * we schedule it before we create kthreadd, will OOPS.
+	 */
 	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
 	numa_default_policy();
 	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
 	kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
+	complete(&kthreadd_done);
 	unlock_kernel();
 
 	/*
@@ -486,6 +488,7 @@
 	int cpu = smp_processor_id();
 	/* Mark the boot cpu "present", "online" etc for SMP and UP case */
 	set_cpu_online(cpu, true);
+	set_cpu_active(cpu, true);
 	set_cpu_present(cpu, true);
 	set_cpu_possible(cpu, true);
 }
@@ -846,12 +849,16 @@
 
 static int __init kernel_init(void * unused)
 {
+	/*
+	 * Wait until kthreadd is all set-up.
+	 */
+	wait_for_completion(&kthreadd_done);
 	lock_kernel();
 
 	/*
 	 * init can allocate pages on any node
 	 */
-	set_mems_allowed(node_possible_map);
+	set_mems_allowed(node_states[N_HIGH_MEMORY]);
 	/*
 	 * init can run on any cpu.
 	 */
@@ -879,6 +886,12 @@
 	do_basic_setup();
 
 	/*
+	 * We need to ensure that the filesystem is ready by this point, wait for
+	 * async_populate_rootfs to complete.
+	 */
+	async_synchronize_full_domain(&populate_rootfs_domain);
+
+	/*
 	 * check if there is an early userspace init.  If yes, let it do all
 	 * the work
 	 */
--- linux-ec2-2.6.32.orig/init/calibrate.c
+++ linux-ec2-2.6.32/init/calibrate.c
@@ -66,7 +66,7 @@
 		pre_start = 0;
 		read_current_timer(&start);
 		start_jiffies = jiffies;
-		while (jiffies <= (start_jiffies + 1)) {
+		while (time_before_eq(jiffies, start_jiffies + 1)) {
 			pre_start = start;
 			read_current_timer(&start);
 		}
@@ -74,8 +74,8 @@
 
 		pre_end = 0;
 		end = post_start;
-		while (jiffies <=
-		       (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) {
+		while (time_before_eq(jiffies, start_jiffies + 1 +
+					       DELAY_CALIBRATION_TICKS)) {
 			pre_end = end;
 			read_current_timer(&end);
 		}
@@ -123,23 +123,26 @@
 {
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
+	static bool printed;
 
 	if (preset_lpj) {
 		loops_per_jiffy = preset_lpj;
-		printk(KERN_INFO
-			"Calibrating delay loop (skipped) preset value.. ");
-	} else if ((smp_processor_id() == 0) && lpj_fine) {
+		if (!printed)
+			pr_info("Calibrating delay loop (skipped) "
+				"preset value.. ");
+	} else if ((!printed) && lpj_fine) {
 		loops_per_jiffy = lpj_fine;
-		printk(KERN_INFO
-			"Calibrating delay loop (skipped), "
+		pr_info("Calibrating delay loop (skipped), "
 			"value calculated using timer frequency.. ");
 	} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
-		printk(KERN_INFO
-			"Calibrating delay using timer specific routine.. ");
+		if (!printed)
+			pr_info("Calibrating delay using timer "
+				"specific routine.. ");
 	} else {
 		loops_per_jiffy = (1<<12);
 
-		printk(KERN_INFO "Calibrating delay loop... ");
+		if (!printed)
+			pr_info("Calibrating delay loop... ");
 		while ((loops_per_jiffy <<= 1) != 0) {
 			/* wait for "start of" clock tick */
 			ticks = jiffies;
@@ -170,7 +173,10 @@
 				loops_per_jiffy &= ~loopbit;
 		}
 	}
-	printk(KERN_CONT "%lu.%02lu BogoMIPS (lpj=%lu)\n",
+	if (!printed)
+		pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
 			loops_per_jiffy/(500000/HZ),
 			(loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
+
+	printed = true;
 }
--- linux-ec2-2.6.32.orig/virt/kvm/irq_comm.c
+++ linux-ec2-2.6.32/virt/kvm/irq_comm.c
@@ -205,16 +205,17 @@
 	int irq_source_id;
 
 	mutex_lock(&kvm->irq_lock);
-	irq_source_id = find_first_zero_bit(bitmap,
-				sizeof(kvm->arch.irq_sources_bitmap));
+	irq_source_id = find_first_zero_bit(bitmap, BITS_PER_LONG);
 
-	if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) {
+	if (irq_source_id >= BITS_PER_LONG) {
 		printk(KERN_WARNING "kvm: exhaust allocatable IRQ sources!\n");
-		return -EFAULT;
+		irq_source_id = -EFAULT;
+		goto unlock;
 	}
 
 	ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID);
 	set_bit(irq_source_id, bitmap);
+unlock:
 	mutex_unlock(&kvm->irq_lock);
 
 	return irq_source_id;
@@ -228,13 +229,17 @@
 
 	mutex_lock(&kvm->irq_lock);
 	if (irq_source_id < 0 ||
-	    irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) {
+	    irq_source_id >= BITS_PER_LONG) {
 		printk(KERN_ERR "kvm: IRQ source ID out of range!\n");
-		return;
+		goto unlock;
 	}
+	clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
+	if (!irqchip_in_kernel(kvm))
+		goto unlock;
+
 	for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++)
 		clear_bit(irq_source_id, &kvm->arch.irq_states[i]);
-	clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
+unlock:
 	mutex_unlock(&kvm->irq_lock);
 }
 
--- linux-ec2-2.6.32.orig/virt/kvm/kvm_main.c
+++ linux-ec2-2.6.32/virt/kvm/kvm_main.c
@@ -1226,7 +1226,7 @@
 
 	/* Allocate page dirty bitmap if needed */
 	if ((new.flags & KVM_MEM_LOG_DIRTY_PAGES) && !new.dirty_bitmap) {
-		unsigned dirty_bytes = ALIGN(npages, BITS_PER_LONG) / 8;
+		unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(&new);
 
 		new.dirty_bitmap = vmalloc(dirty_bytes);
 		if (!new.dirty_bitmap)
@@ -1309,7 +1309,7 @@
 {
 	struct kvm_memory_slot *memslot;
 	int r, i;
-	int n;
+	unsigned long n;
 	unsigned long any = 0;
 
 	r = -EINVAL;
@@ -1321,7 +1321,7 @@
 	if (!memslot->dirty_bitmap)
 		goto out;
 
-	n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+	n = kvm_dirty_bitmap_bytes(memslot);
 
 	for (i = 0; !any && i < n/sizeof(long); ++i)
 		any = memslot->dirty_bitmap[i];
@@ -1663,10 +1663,13 @@
 	memslot = gfn_to_memslot_unaliased(kvm, gfn);
 	if (memslot && memslot->dirty_bitmap) {
 		unsigned long rel_gfn = gfn - memslot->base_gfn;
+		unsigned long *p = memslot->dirty_bitmap +
+					rel_gfn / BITS_PER_LONG;
+		int offset = rel_gfn % BITS_PER_LONG;
 
 		/* avoid RMW */
-		if (!test_bit(rel_gfn, memslot->dirty_bitmap))
-			set_bit(rel_gfn, memslot->dirty_bitmap);
+		if (!test_bit(offset, p))
+			set_bit(offset, p);
 	}
 }
 
@@ -1705,6 +1708,21 @@
 }
 EXPORT_SYMBOL_GPL(kvm_resched);
 
+void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu)
+{
+	ktime_t expires;
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
+
+	/* Sleep for 100 us, and hope lock-holder got scheduled */
+	expires = ktime_add_ns(ktime_get(), 100000UL);
+	schedule_hrtimeout(&expires, HRTIMER_MODE_ABS);
+
+	finish_wait(&vcpu->wq, &wait);
+}
+EXPORT_SYMBOL_GPL(kvm_vcpu_on_spin);
+
 static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct kvm_vcpu *vcpu = vma->vm_file->private_data;
--- linux-ec2-2.6.32.orig/virt/kvm/eventfd.c
+++ linux-ec2-2.6.32/virt/kvm/eventfd.c
@@ -168,7 +168,7 @@
 static int
 kvm_irqfd_assign(struct kvm *kvm, int fd, int gsi)
 {
-	struct _irqfd *irqfd;
+	struct _irqfd *irqfd, *tmp;
 	struct file *file = NULL;
 	struct eventfd_ctx *eventfd = NULL;
 	int ret;
@@ -205,9 +205,20 @@
 	init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
 	init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc);
 
+	spin_lock_irq(&kvm->irqfds.lock);
+
+	ret = 0;
+	list_for_each_entry(tmp, &kvm->irqfds.items, list) {
+		if (irqfd->eventfd != tmp->eventfd)
+			continue;
+		/* This fd is used for another irq already. */
+		ret = -EBUSY;
+		spin_unlock_irq(&kvm->irqfds.lock);
+		goto fail;
+	}
+
 	events = file->f_op->poll(file, &irqfd->pt);
 
-	spin_lock_irq(&kvm->irqfds.lock);
 	list_add_tail(&irqfd->list, &kvm->irqfds.items);
 	spin_unlock_irq(&kvm->irqfds.lock);
 
--- linux-ec2-2.6.32.orig/fs/super.c
+++ linux-ec2-2.6.32/fs/super.c
@@ -37,6 +37,7 @@
 #include <linux/kobject.h>
 #include <linux/mutex.h>
 #include <linux/file.h>
+#include <linux/precache.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -104,6 +105,9 @@
 		s->s_qcop = sb_quotactl_ops;
 		s->s_op = &default_op;
 		s->s_time_gran = 1000000000;
+#ifdef CONFIG_PRECACHE
+		s->precache_poolid = -1;
+#endif
 	}
 out:
 	return s;
@@ -194,6 +198,7 @@
 		vfs_dq_off(s, 0);
 		down_write(&s->s_umount);
 		fs->kill_sb(s);
+		precache_flush_filesystem(s);
 		put_filesystem(fs);
 		put_super(s);
 	}
@@ -871,6 +876,9 @@
 		return error;
 	}
 	s->s_flags |= MS_ACTIVE;
+#ifdef CONFIG_PRECACHE
+	s->precache_poolid = -2;
+#endif
 	simple_set_mnt(mnt, s);
 	return 0;
 }
@@ -901,8 +909,9 @@
 			return error;
 		}
 		s->s_flags |= MS_ACTIVE;
+	} else {
+		do_remount_sb(s, flags, data, 0);
 	}
-	do_remount_sb(s, flags, data, 0);
 	simple_set_mnt(mnt, s);
 	return 0;
 }
--- linux-ec2-2.6.32.orig/fs/buffer.c
+++ linux-ec2-2.6.32/fs/buffer.c
@@ -41,6 +41,7 @@
 #include <linux/bitops.h>
 #include <linux/mpage.h>
 #include <linux/bit_spinlock.h>
+#include <linux/precache.h>
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 
@@ -276,6 +277,11 @@
 
 	invalidate_bh_lrus();
 	invalidate_mapping_pages(mapping, 0, -1);
+
+	/* 99% of the time, we don't need to flush the precache on the bdev.
+	 * But, for the strange corners, lets be cautious
+	 */
+	precache_flush_inode(mapping);
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
--- linux-ec2-2.6.32.orig/fs/read_write.c
+++ linux-ec2-2.6.32/fs/read_write.c
@@ -826,8 +826,6 @@
 	if (!(out_file->f_mode & FMODE_WRITE))
 		goto fput_out;
 	retval = -EINVAL;
-	if (!out_file->f_op || !out_file->f_op->sendpage)
-		goto fput_out;
 	in_inode = in_file->f_path.dentry->d_inode;
 	out_inode = out_file->f_path.dentry->d_inode;
 	retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
--- linux-ec2-2.6.32.orig/fs/mpage.c
+++ linux-ec2-2.6.32/fs/mpage.c
@@ -26,6 +26,7 @@
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/pagevec.h>
+#include <linux/precache.h>
 
 /*
  * I/O completion handler for multipage BIOs.
@@ -285,6 +286,13 @@
 		SetPageMappedToDisk(page);
 	}
 
+	if (fully_mapped &&
+	    blocks_per_page == 1 && !PageUptodate(page) &&
+	    precache_get(page->mapping, page->index, page) == 1) {
+		SetPageUptodate(page);
+		goto confused;
+	}
+
 	/*
 	 * This page will go to BIO.  Do we need to send this BIO off first?
 	 */
--- linux-ec2-2.6.32.orig/fs/binfmt_misc.c
+++ linux-ec2-2.6.32/fs/binfmt_misc.c
@@ -723,7 +723,7 @@
 {
 	int err = register_filesystem(&bm_fs_type);
 	if (!err) {
-		err = register_binfmt(&misc_format);
+		err = insert_binfmt(&misc_format);
 		if (err)
 			unregister_filesystem(&bm_fs_type);
 	}
--- linux-ec2-2.6.32.orig/fs/namei.c
+++ linux-ec2-2.6.32/fs/namei.c
@@ -234,6 +234,7 @@
 	/*
 	 * Searching includes executable on directories, else just read.
 	 */
+	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
 	if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
 		if (capable(CAP_DAC_READ_SEARCH))
 			return 0;
@@ -350,6 +351,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(deny_write_access);
 
 /**
  * path_get - get a reference to a path
@@ -828,6 +830,17 @@
 }
 
 /*
+ * This is a temporary kludge to deal with "automount" symlinks; proper
+ * solution is to trigger them on follow_mount(), so that do_lookup()
+ * would DTRT.  To be killed before 2.6.34-final.
+ */
+static inline int follow_on_final(struct inode *inode, unsigned lookup_flags)
+{
+	return inode && unlikely(inode->i_op->follow_link) &&
+		((lookup_flags & LOOKUP_FOLLOW) || S_ISDIR(inode->i_mode));
+}
+
+/*
  * Name resolution.
  * This is the basic name resolution function, turning a pathname into
  * the final dentry. We expect 'base' to be positive and a directory.
@@ -963,8 +976,7 @@
 		if (err)
 			break;
 		inode = next.dentry->d_inode;
-		if ((lookup_flags & LOOKUP_FOLLOW)
-		    && inode && inode->i_op->follow_link) {
+		if (follow_on_final(inode, lookup_flags)) {
 			err = do_follow_link(&next, nd);
 			if (err)
 				goto return_err;
@@ -1219,7 +1231,7 @@
  * needs parent already locked. Doesn't follow mounts.
  * SMP-safe.
  */
-static struct dentry *lookup_hash(struct nameidata *nd)
+struct dentry *lookup_hash(struct nameidata *nd)
 {
 	int err;
 
@@ -1228,8 +1240,9 @@
 		return ERR_PTR(err);
 	return __lookup_hash(&nd->last, nd->path.dentry, nd);
 }
+EXPORT_SYMBOL(lookup_hash);
 
-static int __lookup_one_len(const char *name, struct qstr *this,
+int __lookup_one_len(const char *name, struct qstr *this,
 		struct dentry *base, int len)
 {
 	unsigned long hash;
@@ -1250,6 +1263,7 @@
 	this->hash = end_name_hash(hash);
 	return 0;
 }
+EXPORT_SYMBOL(__lookup_one_len);
 
 /**
  * lookup_one_len - filesystem helper to lookup single pathname component
--- linux-ec2-2.6.32.orig/fs/dcache.c
+++ linux-ec2-2.6.32/fs/dcache.c
@@ -1175,9 +1175,12 @@
 	spin_unlock(&tmp->d_lock);
 
 	spin_unlock(&dcache_lock);
+	security_d_instantiate(tmp, inode);
 	return tmp;
 
  out_iput:
+	if (res && !IS_ERR(res))
+		security_d_instantiate(res, inode);
 	iput(inode);
 	return res;
 }
--- linux-ec2-2.6.32.orig/fs/block_dev.c
+++ linux-ec2-2.6.32/fs/block_dev.c
@@ -246,7 +246,8 @@
 	if (!sb)
 		goto out;
 	if (sb->s_flags & MS_RDONLY) {
-		deactivate_locked_super(sb);
+		sb->s_frozen = SB_FREEZE_TRANS;
+		up_write(&sb->s_umount);
 		mutex_unlock(&bdev->bd_fsfreeze_mutex);
 		return sb;
 	}
@@ -307,7 +308,7 @@
 	BUG_ON(sb->s_bdev != bdev);
 	down_write(&sb->s_umount);
 	if (sb->s_flags & MS_RDONLY)
-		goto out_deactivate;
+		goto out_unfrozen;
 
 	if (sb->s_op->unfreeze_fs) {
 		error = sb->s_op->unfreeze_fs(sb);
@@ -321,11 +322,11 @@
 		}
 	}
 
+out_unfrozen:
 	sb->s_frozen = SB_UNFROZEN;
 	smp_wmb();
 	wake_up(&sb->s_wait_unfrozen);
 
-out_deactivate:
 	if (sb)
 		deactivate_locked_super(sb);
 out_unlock:
@@ -403,7 +404,7 @@
  *	NULL first argument is nfsd_sync_dir() and that's not a directory.
  */
  
-static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
+int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
 {
 	return sync_blockdev(I_BDEV(filp->f_mapping->host));
 }
@@ -422,6 +423,7 @@
 		return NULL;
 	return &ei->vfs_inode;
 }
+EXPORT_SYMBOL(block_fsync);
 
 static void bdev_destroy_inode(struct inode *inode)
 {
@@ -1173,10 +1175,12 @@
 	/*
 	 * hooks: /n/, see "layering violations".
 	 */
-	ret = devcgroup_inode_permission(bdev->bd_inode, perm);
-	if (ret != 0) {
-		bdput(bdev);
-		return ret;
+	if (!for_part) {
+		ret = devcgroup_inode_permission(bdev->bd_inode, perm);
+		if (ret != 0) {
+			bdput(bdev);
+			return ret;
+		}
 	}
 
 	lock_kernel();
--- linux-ec2-2.6.32.orig/fs/compat_ioctl.c
+++ linux-ec2-2.6.32/fs/compat_ioctl.c
@@ -115,6 +115,13 @@
 #include <asm/fbio.h>
 #endif
 
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#include <xen/public/evtchn.h>
+#include <xen/public/privcmd.h>
+#include <xen/compat_ioctl.h>
+#endif
+
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
 			      unsigned long arg, struct file *f)
 {
@@ -2725,6 +2732,18 @@
 IGNORE_IOCTL(FBIOSCURSOR32)
 IGNORE_IOCTL(FBIOGCURSOR32)
 #endif
+
+#ifdef CONFIG_XEN
+HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32)
+HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32)
+COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_UNBOUND_PORT)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_UNBIND)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_NOTIFY)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_RESET)
+#endif
 };
 
 #define IOCTL_HASHSIZE 256
--- linux-ec2-2.6.32.orig/fs/binfmt_elf_fdpic.c
+++ linux-ec2-2.6.32/fs/binfmt_elf_fdpic.c
@@ -171,6 +171,9 @@
 #ifdef ELF_FDPIC_PLAT_INIT
 	unsigned long dynaddr;
 #endif
+#ifndef CONFIG_MMU
+	unsigned long stack_prot;
+#endif
 	struct file *interpreter = NULL; /* to shut gcc up */
 	char *interpreter_name = NULL;
 	int executable_stack;
@@ -316,6 +319,11 @@
 	 * defunct, deceased, etc. after this point we have to exit via
 	 * error_kill */
 	set_personality(PER_LINUX_FDPIC);
+	if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
+		current->personality |= READ_IMPLIES_EXEC;
+
+	setup_new_exec(bprm);
+
 	set_binfmt(&elf_fdpic_format);
 
 	current->mm->start_code = 0;
@@ -377,9 +385,13 @@
 	if (stack_size < PAGE_SIZE * 2)
 		stack_size = PAGE_SIZE * 2;
 
+	stack_prot = PROT_READ | PROT_WRITE;
+	if (executable_stack == EXSTACK_ENABLE_X ||
+	    (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
+		stack_prot |= PROT_EXEC;
+
 	down_write(&current->mm->mmap_sem);
-	current->mm->start_brk = do_mmap(NULL, 0, stack_size,
-					 PROT_READ | PROT_WRITE | PROT_EXEC,
+	current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
 					 MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
 					 0);
 
--- linux-ec2-2.6.32.orig/fs/Kconfig
+++ linux-ec2-2.6.32/fs/Kconfig
@@ -137,6 +137,7 @@
 	bool "HugeTLB file system support"
 	depends on X86 || IA64 || SPARC64 || (S390 && 64BIT) || \
 		   SYS_SUPPORTS_HUGETLBFS || 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
--- linux-ec2-2.6.32.orig/fs/stat.c
+++ linux-ec2-2.6.32/fs/stat.c
@@ -401,9 +401,9 @@
 }
 #endif /* __ARCH_WANT_STAT64 */
 
-void inode_add_bytes(struct inode *inode, loff_t bytes)
+/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
+void __inode_add_bytes(struct inode *inode, loff_t bytes)
 {
-	spin_lock(&inode->i_lock);
 	inode->i_blocks += bytes >> 9;
 	bytes &= 511;
 	inode->i_bytes += bytes;
@@ -411,6 +411,12 @@
 		inode->i_blocks++;
 		inode->i_bytes -= 512;
 	}
+}
+
+void inode_add_bytes(struct inode *inode, loff_t bytes)
+{
+	spin_lock(&inode->i_lock);
+	__inode_add_bytes(inode, bytes);
 	spin_unlock(&inode->i_lock);
 }
 
--- linux-ec2-2.6.32.orig/fs/open.c
+++ linux-ec2-2.6.32/fs/open.c
@@ -31,6 +31,9 @@
 #include <linux/falloc.h>
 #include <linux/fs_struct.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/fs.h>
+
 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	int retval = -ENODEV;
@@ -223,6 +226,7 @@
 	mutex_unlock(&dentry->d_inode->i_mutex);
 	return ret;
 }
+EXPORT_SYMBOL(do_truncate);
 
 static long do_sys_truncate(const char __user *pathname, loff_t length)
 {
@@ -587,6 +591,9 @@
 	error = -EPERM;
 	if (!capable(CAP_SYS_CHROOT))
 		goto dput_and_out;
+	error = security_path_chroot(&path);
+	if (error)
+		goto dput_and_out;
 
 	set_fs_root(current->fs, &path);
 	error = 0;
@@ -617,11 +624,15 @@
 	if (err)
 		goto out_putf;
 	mutex_lock(&inode->i_mutex);
+	err = security_path_chmod(dentry, file->f_vfsmnt, mode);
+	if (err)
+		goto out_unlock;
 	if (mode == (mode_t) -1)
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 	err = notify_change(dentry, &newattrs);
+out_unlock:
 	mutex_unlock(&inode->i_mutex);
 	mnt_drop_write(file->f_path.mnt);
 out_putf:
@@ -646,11 +657,15 @@
 	if (error)
 		goto dput_and_out;
 	mutex_lock(&inode->i_mutex);
+	error = security_path_chmod(path.dentry, path.mnt, mode);
+	if (error)
+		goto out_unlock;
 	if (mode == (mode_t) -1)
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 	error = notify_change(path.dentry, &newattrs);
+out_unlock:
 	mutex_unlock(&inode->i_mutex);
 	mnt_drop_write(path.mnt);
 dput_and_out:
@@ -664,9 +679,9 @@
 	return sys_fchmodat(AT_FDCWD, filename, mode);
 }
 
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct path *path, uid_t user, gid_t group)
 {
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = path->dentry->d_inode;
 	int error;
 	struct iattr newattrs;
 
@@ -683,7 +698,9 @@
 		newattrs.ia_valid |=
 			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
 	mutex_lock(&inode->i_mutex);
-	error = notify_change(dentry, &newattrs);
+	error = security_path_chown(path, user, group);
+	if (!error)
+		error = notify_change(path->dentry, &newattrs);
 	mutex_unlock(&inode->i_mutex);
 
 	return error;
@@ -700,7 +717,7 @@
 	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_release;
-	error = chown_common(path.dentry, user, group);
+	error = chown_common(&path, user, group);
 	mnt_drop_write(path.mnt);
 out_release:
 	path_put(&path);
@@ -725,7 +742,7 @@
 	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_release;
-	error = chown_common(path.dentry, user, group);
+	error = chown_common(&path, user, group);
 	mnt_drop_write(path.mnt);
 out_release:
 	path_put(&path);
@@ -744,7 +761,7 @@
 	error = mnt_want_write(path.mnt);
 	if (error)
 		goto out_release;
-	error = chown_common(path.dentry, user, group);
+	error = chown_common(&path, user, group);
 	mnt_drop_write(path.mnt);
 out_release:
 	path_put(&path);
@@ -767,7 +784,7 @@
 		goto out_fput;
 	dentry = file->f_path.dentry;
 	audit_inode(NULL, dentry);
-	error = chown_common(dentry, user, group);
+	error = chown_common(&file->f_path, user, group);
 	mnt_drop_write(file->f_path.mnt);
 out_fput:
 	fput(file);
@@ -1043,6 +1060,7 @@
 			} else {
 				fsnotify_open(f->f_path.dentry);
 				fd_install(fd, f);
+				trace_do_sys_open(tmp, flags, mode);
 			}
 		}
 		putname(tmp);
--- linux-ec2-2.6.32.orig/fs/eventpoll.c
+++ linux-ec2-2.6.32/fs/eventpoll.c
@@ -63,6 +63,13 @@
  * cleanup path and it is also acquired by eventpoll_release_file()
  * if a file has been pushed inside an epoll set and it is then
  * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL).
+ * It is also acquired when inserting an epoll fd onto another epoll
+ * fd. We do this so that we walk the epoll tree and ensure that this
+ * insertion does not create a cycle of epoll file descriptors, which
+ * could lead to deadlock. We need a global mutex to prevent two
+ * simultaneous inserts (A into B and B into A) from racing and
+ * constructing a cycle without either insert observing that it is
+ * going to.
  * It is possible to drop the "ep->mtx" and to use the global
  * mutex "epmutex" (together with "ep->lock") to have it working,
  * but having "ep->mtx" will make the interface more scalable.
@@ -227,6 +234,9 @@
  */
 static DEFINE_MUTEX(epmutex);
 
+/* Used to check for epoll file descriptor inclusion loops */
+static struct nested_calls poll_loop_ncalls;
+
 /* Used for safe wake up implementation */
 static struct nested_calls poll_safewake_ncalls;
 
@@ -1182,6 +1192,62 @@
 	return res;
 }
 
+/**
+ * ep_loop_check_proc - Callback function to be passed to the @ep_call_nested()
+ *                      API, to verify that adding an epoll file inside another
+ *                      epoll structure, does not violate the constraints, in
+ *                      terms of closed loops, or too deep chains (which can
+ *                      result in excessive stack usage).
+ *
+ * @priv: Pointer to the epoll file to be currently checked.
+ * @cookie: Original cookie for this call. This is the top-of-the-chain epoll
+ *          data structure pointer.
+ * @call_nests: Current dept of the @ep_call_nested() call stack.
+ *
+ * Returns: Returns zero if adding the epoll @file inside current epoll
+ *          structure @ep does not violate the constraints, or -1 otherwise.
+ */
+static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
+{
+	int error = 0;
+	struct file *file = priv;
+	struct eventpoll *ep = file->private_data;
+	struct rb_node *rbp;
+	struct epitem *epi;
+
+	mutex_lock(&ep->mtx);
+	for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
+		epi = rb_entry(rbp, struct epitem, rbn);
+		if (unlikely(is_file_epoll(epi->ffd.file))) {
+			error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+					       ep_loop_check_proc, epi->ffd.file,
+					       epi->ffd.file->private_data, current);
+			if (error != 0)
+				break;
+		}
+	}
+	mutex_unlock(&ep->mtx);
+
+	return error;
+}
+
+/**
+ * ep_loop_check - Performs a check to verify that adding an epoll file (@file)
+ *                 another epoll file (represented by @ep) does not create
+ *                 closed loops or too deep chains.
+ *
+ * @ep: Pointer to the epoll private data structure.
+ * @file: Pointer to the epoll file to be checked.
+ *
+ * Returns: Returns zero if adding the epoll @file inside current epoll
+ *          structure @ep does not violate the constraints, or -1 otherwise.
+ */
+static int ep_loop_check(struct eventpoll *ep, struct file *file)
+{
+	return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+			      ep_loop_check_proc, file, ep, current);
+}
+
 /*
  * Open an eventpoll file descriptor.
  */
@@ -1230,6 +1296,7 @@
 		struct epoll_event __user *, event)
 {
 	int error;
+	int did_lock_epmutex = 0;
 	struct file *file, *tfile;
 	struct eventpoll *ep;
 	struct epitem *epi;
@@ -1271,6 +1338,25 @@
 	 */
 	ep = file->private_data;
 
+	/*
+	 * When we insert an epoll file descriptor, inside another epoll file
+	 * descriptor, there is the change of creating closed loops, which are
+	 * better be handled here, than in more critical paths.
+	 *
+	 * We hold epmutex across the loop check and the insert in this case, in
+	 * order to prevent two separate inserts from racing and each doing the
+	 * insert "at the same time" such that ep_loop_check passes on both
+	 * before either one does the insert, thereby creating a cycle.
+	 */
+	if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) {
+		mutex_lock(&epmutex);
+		did_lock_epmutex = 1;
+		error = -ELOOP;
+		if (ep_loop_check(ep, tfile) != 0)
+			goto error_tgt_fput;
+	}
+
+
 	mutex_lock(&ep->mtx);
 
 	/*
@@ -1306,6 +1392,9 @@
 	mutex_unlock(&ep->mtx);
 
 error_tgt_fput:
+	if (unlikely(did_lock_epmutex))
+		mutex_unlock(&epmutex);
+
 	fput(tfile);
 error_fput:
 	fput(file);
@@ -1424,6 +1513,12 @@
 	max_user_watches = (((si.totalram - si.totalhigh) / 25) << PAGE_SHIFT) /
 		EP_ITEM_COST;
 
+	/*
+	 * Initialize the structure used to perform epoll file descriptor
+	 * inclusion loops checks.
+	 */
+	ep_nested_calls_init(&poll_loop_ncalls);
+
 	/* Initialize the structure used to perform safe poll wait head wake ups */
 	ep_nested_calls_init(&poll_safewake_ncalls);
 
--- linux-ec2-2.6.32.orig/fs/compat.c
+++ linux-ec2-2.6.32/fs/compat.c
@@ -1353,6 +1353,10 @@
 			argv++;
 			if (i++ >= max)
 				return -E2BIG;
+
+			if (fatal_signal_pending(current))
+				return -ERESTARTNOHAND;
+			cond_resched();
 		}
 	}
 	return i;
@@ -1394,6 +1398,12 @@
 		while (len > 0) {
 			int offset, bytes_to_copy;
 
+			if (fatal_signal_pending(current)) {
+				ret = -ERESTARTNOHAND;
+				goto out;
+			}
+			cond_resched();
+
 			offset = pos % PAGE_SIZE;
 			if (offset == 0)
 				offset = PAGE_SIZE;
@@ -1410,18 +1420,8 @@
 			if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
 				struct page *page;
 
-#ifdef CONFIG_STACK_GROWSUP
-				ret = expand_stack_downwards(bprm->vma, pos);
-				if (ret < 0) {
-					/* We've exceed the stack rlimit. */
-					ret = -E2BIG;
-					goto out;
-				}
-#endif
-				ret = get_user_pages(current, bprm->mm, pos,
-						     1, 1, 1, &page, NULL);
-				if (ret <= 0) {
-					/* We've exceed the stack rlimit. */
+				page = get_arg_page(bprm, pos, 1);
+				if (!page) {
 					ret = -E2BIG;
 					goto out;
 				}
@@ -1532,8 +1532,6 @@
 	if (retval < 0)
 		goto out;
 
-	current->stack_start = current->mm->start_stack;
-
 	/* execve succeeded */
 	current->fs->in_exec = 0;
 	current->in_execve = 0;
@@ -1544,8 +1542,10 @@
 	return retval;
 
 out:
-	if (bprm->mm)
+	if (bprm->mm) {
+		acct_arg_size(bprm, 0);
 		mmput(bprm->mm);
+	}
 
 out_file:
 	if (bprm->file) {
--- linux-ec2-2.6.32.orig/fs/signalfd.c
+++ linux-ec2-2.6.32/fs/signalfd.c
@@ -87,6 +87,7 @@
 		 err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
 		 err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
 		 err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+		 err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
 		break;
 	case __SI_POLL:
 		err |= __put_user(kinfo->si_band, &uinfo->ssi_band);
@@ -110,6 +111,7 @@
 		err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
 		err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
 		err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+		err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
 		break;
 	default:
 		/*
--- linux-ec2-2.6.32.orig/fs/bio-integrity.c
+++ linux-ec2-2.6.32/fs/bio-integrity.c
@@ -61,7 +61,7 @@
 
 static inline int use_bip_pool(unsigned int idx)
 {
-	if (idx == BIOVEC_NR_POOLS)
+	if (idx == BIOVEC_MAX_IDX)
 		return 1;
 
 	return 0;
@@ -95,6 +95,7 @@
 
 	/* Use mempool if lower order alloc failed or max vecs were requested */
 	if (bip == NULL) {
+		idx = BIOVEC_MAX_IDX;  /* so we free the payload properly later */
 		bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
 
 		if (unlikely(bip == NULL)) {
--- linux-ec2-2.6.32.orig/fs/bio.c
+++ linux-ec2-2.6.32/fs/bio.c
@@ -371,6 +371,9 @@
 {
 	struct bio *bio;
 
+	if (nr_iovecs > UIO_MAXIOV)
+		return NULL;
+
 	bio = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec),
 		      gfp_mask);
 	if (unlikely(!bio))
@@ -542,13 +545,18 @@
 
 		if (page == prev->bv_page &&
 		    offset == prev->bv_offset + prev->bv_len) {
+			unsigned int prev_bv_len = prev->bv_len;
 			prev->bv_len += len;
 
 			if (q->merge_bvec_fn) {
 				struct bvec_merge_data bvm = {
+					/* prev_bvec is already charged in
+					   bi_size, discharge it in order to
+					   simulate merging updated prev_bvec
+					   as new bvec. */
 					.bi_bdev = bio->bi_bdev,
 					.bi_sector = bio->bi_sector,
-					.bi_size = bio->bi_size,
+					.bi_size = bio->bi_size - prev_bv_len,
 					.bi_rw = bio->bi_rw,
 				};
 
@@ -696,8 +704,12 @@
 static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
 					       gfp_t gfp_mask)
 {
-	struct bio_map_data *bmd = kmalloc(sizeof(*bmd), gfp_mask);
+	struct bio_map_data *bmd;
 
+	if (iov_count > UIO_MAXIOV)
+		return NULL;
+
+	bmd = kmalloc(sizeof(*bmd), gfp_mask);
 	if (!bmd)
 		return NULL;
 
@@ -826,6 +838,12 @@
 		end = (uaddr + iov[i].iov_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 		start = uaddr >> PAGE_SHIFT;
 
+		/*
+		 * Overflow, abort
+		 */
+		if (end < start)
+			return ERR_PTR(-EINVAL);
+
 		nr_pages += end - start;
 		len += iov[i].iov_len;
 	}
@@ -953,6 +971,12 @@
 		unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 		unsigned long start = uaddr >> PAGE_SHIFT;
 
+		/*
+		 * Overflow, abort
+		 */
+		if (end < start)
+			return ERR_PTR(-EINVAL);
+
 		nr_pages += end - start;
 		/*
 		 * buffer must be aligned to at least hardsector size for now
@@ -980,7 +1004,7 @@
 		unsigned long start = uaddr >> PAGE_SHIFT;
 		const int local_nr_pages = end - start;
 		const int page_limit = cur_page + local_nr_pages;
-		
+
 		ret = get_user_pages_fast(uaddr, local_nr_pages,
 				write_to_vm, &pages[cur_page]);
 		if (ret < local_nr_pages) {
--- linux-ec2-2.6.32.orig/fs/exec.c
+++ linux-ec2-2.6.32/fs/exec.c
@@ -57,6 +57,8 @@
 #include <linux/fs_struct.h>
 #include <linux/pipe_fs_i.h>
 
+#include <trace/events/fs.h>
+
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlb.h>
@@ -159,7 +161,22 @@
 
 #ifdef CONFIG_MMU
 
-static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
+{
+	struct mm_struct *mm = current->mm;
+	long diff = (long)(pages - bprm->vma_pages);
+
+	if (!mm || !diff)
+		return;
+
+	bprm->vma_pages = pages;
+
+	down_write(&mm->mmap_sem);
+	mm->total_vm += diff;
+	up_write(&mm->mmap_sem);
+}
+
+struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 		int write)
 {
 	struct page *page;
@@ -181,6 +198,8 @@
 		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
 		struct rlimit *rlim;
 
+		acct_arg_size(bprm, size / PAGE_SIZE);
+
 		/*
 		 * We've historically supported up to 32 pages (ARG_MAX)
 		 * of argument strings even with small stacks
@@ -247,6 +266,11 @@
 	vma->vm_start = vma->vm_end - PAGE_SIZE;
 	vma->vm_flags = VM_STACK_FLAGS;
 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+	err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+	if (err)
+		goto err;
+
 	err = insert_vm_struct(mm, vma);
 	if (err)
 		goto err;
@@ -269,7 +293,11 @@
 
 #else
 
-static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
+{
+}
+
+struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 		int write)
 {
 	struct page *page;
@@ -376,6 +404,9 @@
 			argv++;
 			if (i++ >= max)
 				return -E2BIG;
+
+			if (fatal_signal_pending(current))
+				return -ERESTARTNOHAND;
 			cond_resched();
 		}
 	}
@@ -419,6 +450,12 @@
 		while (len > 0) {
 			int offset, bytes_to_copy;
 
+			if (fatal_signal_pending(current)) {
+				ret = -ERESTARTNOHAND;
+				goto out;
+			}
+			cond_resched();
+
 			offset = pos % PAGE_SIZE;
 			if (offset == 0)
 				offset = PAGE_SIZE;
@@ -572,6 +609,9 @@
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -591,6 +631,11 @@
 #else
 	stack_top = arch_align_stack(stack_top);
 	stack_top = PAGE_ALIGN(stack_top);
+
+	if (unlikely(stack_top < mmap_min_addr) ||
+	    unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr))
+		return -ENOMEM;
+
 	stack_shift = vma->vm_end - stack_top;
 
 	bprm->p -= stack_shift;
@@ -628,10 +673,23 @@
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_start + rlim_stack;
+	else
+		stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_end - rlim_stack;
+	else
+		stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
@@ -665,6 +723,8 @@
 
 	fsnotify_open(file->f_path.dentry);
 
+	trace_open_exec(name);
+
 	err = deny_write_access(file);
 	if (err)
 		goto exit;
@@ -931,9 +991,7 @@
 
 int flush_old_exec(struct linux_binprm * bprm)
 {
-	char * name;
-	int i, ch, retval;
-	char tcomm[sizeof(current->comm)];
+	int retval;
 
 	/*
 	 * Make sure we have a private signal table and that
@@ -948,12 +1006,32 @@
 	/*
 	 * Release all of the old mmap stuff
 	 */
+	acct_arg_size(bprm, 0);
 	retval = exec_mmap(bprm->mm);
 	if (retval)
 		goto out;
 
 	bprm->mm = NULL;		/* We're using it now */
 
+	current->flags &= ~PF_RANDOMIZE;
+	flush_thread();
+	current->personality &= ~bprm->per_clear;
+
+	return 0;
+
+out:
+	return retval;
+}
+EXPORT_SYMBOL(flush_old_exec);
+
+void setup_new_exec(struct linux_binprm * bprm)
+{
+	int i, ch;
+	char * name;
+	char tcomm[sizeof(current->comm)];
+
+	arch_pick_mmap_layout(current->mm);
+
 	/* This is the point of no return */
 	current->sas_ss_sp = current->sas_ss_size = 0;
 
@@ -975,9 +1053,6 @@
 	tcomm[i] = '\0';
 	set_task_comm(current, tcomm);
 
-	current->flags &= ~PF_RANDOMIZE;
-	flush_thread();
-
 	/* Set the new mm task size. We have to do that late because it may
 	 * depend on TIF_32BIT which is only updated in flush_thread() on
 	 * some architectures like powerpc
@@ -993,8 +1068,6 @@
 		set_dumpable(current->mm, suid_dumpable);
 	}
 
-	current->personality &= ~bprm->per_clear;
-
 	/*
 	 * Flush performance counters when crossing a
 	 * security domain:
@@ -1009,14 +1082,8 @@
 			
 	flush_signal_handlers(current, 0);
 	flush_old_files(current->files);
-
-	return 0;
-
-out:
-	return retval;
 }
-
-EXPORT_SYMBOL(flush_old_exec);
+EXPORT_SYMBOL(setup_new_exec);
 
 /*
  * Prepare credentials and lock ->cred_guard_mutex.
@@ -1357,8 +1424,6 @@
 	if (retval < 0)
 		goto out;
 
-	current->stack_start = current->mm->start_stack;
-
 	/* execve succeeded */
 	current->fs->in_exec = 0;
 	current->in_execve = 0;
@@ -1369,8 +1434,10 @@
 	return retval;
 
 out:
-	if (bprm->mm)
-		mmput (bprm->mm);
+	if (bprm->mm) {
+		acct_arg_size(bprm, 0);
+		mmput(bprm->mm);
+	}
 
 out_file:
 	if (bprm->file) {
@@ -1826,15 +1893,15 @@
 		goto fail_unlock;
 
  	if (ispipe) {
-		if (core_limit == 0) {
+		if (core_limit == 1) {
 			/*
 			 * Normally core limits are irrelevant to pipes, since
 			 * we're not writing to the file system, but we use
-			 * core_limit of 0 here as a speacial value. Any
+			 * core_limit of 1 here as a special value. Any
 			 * non-zero limit gets set to RLIM_INFINITY below, but
 			 * a limit of 0 skips the dump.  This is a consistent
 			 * way to catch recursive crashes.  We can still crash
-			 * if the core_pattern binary sets RLIM_CORE =  !0
+			 * if the core_pattern binary sets RLIM_CORE =  !1
 			 * but it runs as root, and can do lots of stupid things
 			 * Note that we use task_tgid_vnr here to grab the pid
 			 * of the process group leader.  That way we get the
@@ -1842,7 +1909,7 @@
 			 * core_pattern process dies.
 			 */
 			printk(KERN_WARNING
-				"Process %d(%s) has RLIMIT_CORE set to 0\n",
+				"Process %d(%s) has RLIMIT_CORE set to 1\n",
 				task_tgid_vnr(current), current->comm);
 			printk(KERN_WARNING "Aborting core\n");
 			goto fail_unlock;
@@ -1891,8 +1958,9 @@
 	/*
 	 * Dont allow local users get cute and trick others to coredump
 	 * into their pre-created files:
+	 * Note, this is not relevant for pipes
 	 */
-	if (inode->i_uid != current_fsuid())
+	if (!ispipe && (inode->i_uid != current_fsuid()))
 		goto close_fail;
 	if (!file->f_op)
 		goto close_fail;
--- linux-ec2-2.6.32.orig/fs/inode.c
+++ linux-ec2-2.6.32/fs/inode.c
@@ -1624,3 +1624,7 @@
 				  inode->i_ino);
 }
 EXPORT_SYMBOL(init_special_inode);
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/vfs.h>
+
--- linux-ec2-2.6.32.orig/fs/binfmt_aout.c
+++ linux-ec2-2.6.32/fs/binfmt_aout.c
@@ -263,6 +263,7 @@
 #else
 	set_personality(PER_LINUX);
 #endif
+	setup_new_exec(bprm);
 
 	current->mm->end_code = ex.a_text +
 		(current->mm->start_code = N_TXTADDR(ex));
--- linux-ec2-2.6.32.orig/fs/fcntl.c
+++ linux-ec2-2.6.32/fs/fcntl.c
@@ -618,60 +618,90 @@
 static struct kmem_cache *fasync_cache __read_mostly;
 
 /*
- * fasync_helper() is used by almost all character device drivers
- * to set up the fasync queue. It returns negative on error, 0 if it did
- * no changes and positive if it added/deleted the entry.
+ * Remove a fasync entry. If successfully removed, return
+ * positive and clear the FASYNC flag. If no entry exists,
+ * do nothing and return 0.
+ *
+ * NOTE! It is very important that the FASYNC flag always
+ * match the state "is the filp on a fasync list".
+ *
+ * We always take the 'filp->f_lock', in since fasync_lock
+ * needs to be irq-safe.
  */
-int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
+static int fasync_remove_entry(struct file *filp, struct fasync_struct **fapp)
 {
 	struct fasync_struct *fa, **fp;
-	struct fasync_struct *new = NULL;
 	int result = 0;
 
-	if (on) {
-		new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
-		if (!new)
-			return -ENOMEM;
+	spin_lock(&filp->f_lock);
+	write_lock_irq(&fasync_lock);
+	for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
+		if (fa->fa_file != filp)
+			continue;
+		*fp = fa->fa_next;
+		kmem_cache_free(fasync_cache, fa);
+		filp->f_flags &= ~FASYNC;
+		result = 1;
+		break;
 	}
+	write_unlock_irq(&fasync_lock);
+	spin_unlock(&filp->f_lock);
+	return result;
+}
+
+/*
+ * Add a fasync entry. Return negative on error, positive if
+ * added, and zero if did nothing but change an existing one.
+ *
+ * NOTE! It is very important that the FASYNC flag always
+ * match the state "is the filp on a fasync list".
+ */
+static int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp)
+{
+	struct fasync_struct *new, *fa, **fp;
+	int result = 0;
+
+	new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
 
-	/*
-	 * We need to take f_lock first since it's not an IRQ-safe
-	 * lock.
-	 */
 	spin_lock(&filp->f_lock);
 	write_lock_irq(&fasync_lock);
 	for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {
-		if (fa->fa_file == filp) {
-			if(on) {
-				fa->fa_fd = fd;
-				kmem_cache_free(fasync_cache, new);
-			} else {
-				*fp = fa->fa_next;
-				kmem_cache_free(fasync_cache, fa);
-				result = 1;
-			}
-			goto out;
-		}
+		if (fa->fa_file != filp)
+			continue;
+		fa->fa_fd = fd;
+		kmem_cache_free(fasync_cache, new);
+		goto out;
 	}
 
-	if (on) {
-		new->magic = FASYNC_MAGIC;
-		new->fa_file = filp;
-		new->fa_fd = fd;
-		new->fa_next = *fapp;
-		*fapp = new;
-		result = 1;
-	}
+	new->magic = FASYNC_MAGIC;
+	new->fa_file = filp;
+	new->fa_fd = fd;
+	new->fa_next = *fapp;
+	*fapp = new;
+	result = 1;
+	filp->f_flags |= FASYNC;
+
 out:
-	if (on)
-		filp->f_flags |= FASYNC;
-	else
-		filp->f_flags &= ~FASYNC;
 	write_unlock_irq(&fasync_lock);
 	spin_unlock(&filp->f_lock);
 	return result;
 }
 
+/*
+ * fasync_helper() is used by almost all character device drivers
+ * to set up the fasync queue, and for regular files by the file
+ * lease code. It returns negative on error, 0 if it did no changes
+ * and positive if it added/deleted the entry.
+ */
+int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
+{
+	if (!on)
+		return fasync_remove_entry(filp, fapp);
+	return fasync_add_entry(fd, filp, fapp);
+}
+
 EXPORT_SYMBOL(fasync_helper);
 
 void __kill_fasync(struct fasync_struct *fa, int sig, int band)
--- linux-ec2-2.6.32.orig/fs/file_table.c
+++ linux-ec2-2.6.32/fs/file_table.c
@@ -121,13 +121,13 @@
 		goto fail;
 
 	percpu_counter_inc(&nr_files);
+	f->f_cred = get_cred(cred);
 	if (security_file_alloc(f))
 		goto fail_sec;
 
 	INIT_LIST_HEAD(&f->f_u.fu_list);
 	atomic_long_set(&f->f_count, 1);
 	rwlock_init(&f->f_owner.lock);
-	f->f_cred = get_cred(cred);
 	spin_lock_init(&f->f_lock);
 	eventpoll_init_file(f);
 	/* f->f_version: 0 */
@@ -420,7 +420,9 @@
 			continue;
 		if (!(f->f_mode & FMODE_WRITE))
 			continue;
+		spin_lock(&f->f_lock);
 		f->f_mode &= ~FMODE_WRITE;
+		spin_unlock(&f->f_lock);
 		if (file_check_writeable(f) != 0)
 			continue;
 		file_release_write(f);
--- linux-ec2-2.6.32.orig/fs/aio.c
+++ linux-ec2-2.6.32/fs/aio.c
@@ -36,6 +36,11 @@
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_EPOLL
+#include <linux/poll.h>
+#include <linux/anon_inodes.h>
+#endif
+
 #if DEBUG > 1
 #define dprintk		printk
 #else
@@ -497,7 +502,7 @@
 	ctx->reqs_active--;
 
 	if (unlikely(!ctx->reqs_active && ctx->dead))
-		wake_up(&ctx->wait);
+		wake_up_all(&ctx->wait);
 }
 
 static void aio_fput_routine(struct work_struct *data)
@@ -992,6 +997,11 @@
 	if (waitqueue_active(&ctx->wait))
 		wake_up(&ctx->wait);
 
+#ifdef CONFIG_EPOLL
+	if (ctx->file && waitqueue_active(&ctx->poll_wait))
+		wake_up(&ctx->poll_wait);
+#endif
+
 	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
 	return ret;
 }
@@ -1000,6 +1010,8 @@
 /* aio_read_evt
  *	Pull an event off of the ioctx's event ring.  Returns the number of 
  *	events fetched (0 or 1 ;-)
+ *	If ent parameter is 0, just returns the number of events that would
+ *	be fetched.
  *	FIXME: make this use cmpxchg.
  *	TODO: make the ringbuffer user mmap()able (requires FIXME).
  */
@@ -1022,13 +1034,18 @@
 
 	head = ring->head % info->nr;
 	if (head != ring->tail) {
-		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
-		*ent = *evp;
-		head = (head + 1) % info->nr;
-		smp_mb(); /* finish reading the event before updatng the head */
-		ring->head = head;
-		ret = 1;
-		put_aio_ring_event(evp, KM_USER1);
+		if (ent) { /* event requested */
+			struct io_event *evp =
+				aio_ring_event(info, head, KM_USER1);
+			*ent = *evp;
+			head = (head + 1) % info->nr;
+			/* finish reading the event before updatng the head */
+			smp_mb();
+			ring->head = head;
+			ret = 1;
+			put_aio_ring_event(evp, KM_USER1);
+		} else /* only need to know availability */
+			ret = 1;
 	}
 	spin_unlock(&info->ring_lock);
 
@@ -1213,16 +1230,88 @@
 
 	aio_cancel_all(ioctx);
 	wait_for_all_aios(ioctx);
+#ifdef CONFIG_EPOLL
+	/* forget the poll file, but it's up to the user to close it */
+	if (ioctx->file) {
+		fput(ioctx->file);
+		ioctx->file->private_data = 0;
+		ioctx->file = 0;
+	}
+#endif
 
 	/*
 	 * Wake up any waiters.  The setting of ctx->dead must be seen
 	 * by other CPUs at this point.  Right now, we rely on the
 	 * locking done by the above calls to ensure this consistency.
 	 */
-	wake_up(&ioctx->wait);
+	wake_up_all(&ioctx->wait);
 	put_ioctx(ioctx);	/* once for the lookup */
 }
 
+#ifdef CONFIG_EPOLL
+
+static int aio_queue_fd_close(struct inode *inode, struct file *file)
+{
+	struct kioctx *ioctx = file->private_data;
+	if (ioctx) {
+		file->private_data = 0;
+		spin_lock_irq(&ioctx->ctx_lock);
+		ioctx->file = 0;
+		spin_unlock_irq(&ioctx->ctx_lock);
+		fput(file);
+	}
+	return 0;
+}
+
+static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
+{	unsigned int pollflags = 0;
+	struct kioctx *ioctx = file->private_data;
+
+	if (ioctx) {
+
+		spin_lock_irq(&ioctx->ctx_lock);
+		/* Insert inside our poll wait queue */
+		poll_wait(file, &ioctx->poll_wait, wait);
+
+		/* Check our condition */
+		if (aio_read_evt(ioctx, 0))
+			pollflags = POLLIN | POLLRDNORM;
+		spin_unlock_irq(&ioctx->ctx_lock);
+	}
+
+	return pollflags;
+}
+
+static const struct file_operations aioq_fops = {
+	.release	= aio_queue_fd_close,
+	.poll		= aio_queue_fd_poll
+};
+
+/* make_aio_fd:
+ *  Create a file descriptor that can be used to poll the event queue.
+ *  Based on the excellent epoll code.
+ */
+
+static int make_aio_fd(struct kioctx *ioctx)
+{
+	int fd;
+	struct file *file;
+
+	fd = anon_inode_getfd("[aioq]", &aioq_fops, ioctx, 0);
+	if (fd < 0)
+		return fd;
+
+	/* associate the file with the IO context */
+	file = fget(fd);
+	if (!file)
+		return -EBADF;
+	file->private_data = ioctx;
+	ioctx->file = file;
+	init_waitqueue_head(&ioctx->poll_wait);
+	return fd;
+}
+#endif
+
 /* sys_io_setup:
  *	Create an aio_context capable of receiving at least nr_events.
  *	ctxp must not point to an aio_context that already exists, and
@@ -1235,18 +1324,30 @@
  *	resources are available.  May fail with -EFAULT if an invalid
  *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
  *	implemented.
+ *
+ *	To request a selectable fd, the user context has to be initialized
+ *	to 1, instead of 0, and the return value is the fd.
+ *	This keeps the system call compatible, since a non-zero value
+ *	was not allowed so far.
  */
 SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
 {
 	struct kioctx *ioctx = NULL;
 	unsigned long ctx;
 	long ret;
+	int make_fd = 0;
 
 	ret = get_user(ctx, ctxp);
 	if (unlikely(ret))
 		goto out;
 
 	ret = -EINVAL;
+#ifdef CONFIG_EPOLL
+	if (ctx == 1) {
+		make_fd = 1;
+		ctx = 0;
+	}
+#endif
 	if (unlikely(ctx || nr_events == 0)) {
 		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
 		         ctx, nr_events);
@@ -1257,8 +1358,12 @@
 	ret = PTR_ERR(ioctx);
 	if (!IS_ERR(ioctx)) {
 		ret = put_user(ioctx->user_id, ctxp);
-		if (!ret)
-			return 0;
+#ifdef CONFIG_EPOLL
+		if (make_fd && ret >= 0)
+			ret = make_aio_fd(ioctx);
+#endif
+		if (ret >= 0)
+			return ret;
 
 		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
 		io_destroy(ioctx);
@@ -1639,6 +1744,9 @@
 	if (unlikely(nr < 0))
 		return -EINVAL;
 
+	if (unlikely(nr > LONG_MAX/sizeof(*iocbpp)))
+		nr = LONG_MAX/sizeof(*iocbpp);
+
 	if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
 		return -EFAULT;
 
--- linux-ec2-2.6.32.orig/fs/pipe.c
+++ linux-ec2-2.6.32/fs/pipe.c
@@ -363,7 +363,7 @@
 			error = ops->confirm(pipe, buf);
 			if (error) {
 				if (!ret)
-					error = ret;
+					ret = error;
 				break;
 			}
 
--- linux-ec2-2.6.32.orig/fs/fs-writeback.c
+++ linux-ec2-2.6.32/fs/fs-writeback.c
@@ -25,6 +25,7 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
+#include <trace/events/vfs.h>
 #include "internal.h"
 
 #define inode_to_bdi(inode)	((inode)->i_mapping->backing_dev_info)
@@ -37,51 +38,18 @@
 /*
  * Passed into wb_writeback(), essentially a subset of writeback_control
  */
-struct wb_writeback_args {
+struct wb_writeback_work {
 	long nr_pages;
 	struct super_block *sb;
 	enum writeback_sync_modes sync_mode;
 	int for_kupdate:1;
 	int range_cyclic:1;
 	int for_background:1;
-};
 
-/*
- * Work items for the bdi_writeback threads
- */
-struct bdi_work {
 	struct list_head list;		/* pending work list */
-	struct rcu_head rcu_head;	/* for RCU free/clear of work */
-
-	unsigned long seen;		/* threads that have seen this work */
-	atomic_t pending;		/* number of threads still to do work */
-
-	struct wb_writeback_args args;	/* writeback arguments */
-
-	unsigned long state;		/* flag bits, see WS_* */
-};
-
-enum {
-	WS_USED_B = 0,
-	WS_ONSTACK_B,
+	struct completion *done;	/* set if the caller waits */
 };
 
-#define WS_USED (1 << WS_USED_B)
-#define WS_ONSTACK (1 << WS_ONSTACK_B)
-
-static inline bool bdi_work_on_stack(struct bdi_work *work)
-{
-	return test_bit(WS_ONSTACK_B, &work->state);
-}
-
-static inline void bdi_work_init(struct bdi_work *work,
-				 struct wb_writeback_args *args)
-{
-	INIT_RCU_HEAD(&work->rcu_head);
-	work->args = *args;
-	work->state = WS_USED;
-}
-
 /**
  * writeback_in_progress - determine whether there is writeback in progress
  * @bdi: the device's backing_dev_info structure.
@@ -94,76 +62,11 @@
 	return !list_empty(&bdi->work_list);
 }
 
-static void bdi_work_clear(struct bdi_work *work)
+static void bdi_queue_work(struct backing_dev_info *bdi,
+		struct wb_writeback_work *work)
 {
-	clear_bit(WS_USED_B, &work->state);
-	smp_mb__after_clear_bit();
-	/*
-	 * work can have disappeared at this point. bit waitq functions
-	 * should be able to tolerate this, provided bdi_sched_wait does
-	 * not dereference it's pointer argument.
-	*/
-	wake_up_bit(&work->state, WS_USED_B);
-}
-
-static void bdi_work_free(struct rcu_head *head)
-{
-	struct bdi_work *work = container_of(head, struct bdi_work, rcu_head);
-
-	if (!bdi_work_on_stack(work))
-		kfree(work);
-	else
-		bdi_work_clear(work);
-}
-
-static void wb_work_complete(struct bdi_work *work)
-{
-	const enum writeback_sync_modes sync_mode = work->args.sync_mode;
-	int onstack = bdi_work_on_stack(work);
-
-	/*
-	 * For allocated work, we can clear the done/seen bit right here.
-	 * For on-stack work, we need to postpone both the clear and free
-	 * to after the RCU grace period, since the stack could be invalidated
-	 * as soon as bdi_work_clear() has done the wakeup.
-	 */
-	if (!onstack)
-		bdi_work_clear(work);
-	if (sync_mode == WB_SYNC_NONE || onstack)
-		call_rcu(&work->rcu_head, bdi_work_free);
-}
-
-static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work)
-{
-	/*
-	 * The caller has retrieved the work arguments from this work,
-	 * drop our reference. If this is the last ref, delete and free it
-	 */
-	if (atomic_dec_and_test(&work->pending)) {
-		struct backing_dev_info *bdi = wb->bdi;
-
-		spin_lock(&bdi->wb_lock);
-		list_del_rcu(&work->list);
-		spin_unlock(&bdi->wb_lock);
-
-		wb_work_complete(work);
-	}
-}
-
-static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work)
-{
-	work->seen = bdi->wb_mask;
-	BUG_ON(!work->seen);
-	atomic_set(&work->pending, bdi->wb_cnt);
-	BUG_ON(!bdi->wb_cnt);
-
-	/*
-	 * list_add_tail_rcu() contains the necessary barriers to
-	 * make sure the above stores are seen before the item is
-	 * noticed on the list
-	 */
 	spin_lock(&bdi->wb_lock);
-	list_add_tail_rcu(&work->list, &bdi->work_list);
+	list_add_tail(&work->list, &bdi->work_list);
 	spin_unlock(&bdi->wb_lock);
 
 	/*
@@ -180,96 +83,59 @@
 	}
 }
 
-/*
- * Used for on-stack allocated work items. The caller needs to wait until
- * the wb threads have acked the work before it's safe to continue.
- */
-static void bdi_wait_on_work_clear(struct bdi_work *work)
-{
-	wait_on_bit(&work->state, WS_USED_B, bdi_sched_wait,
-		    TASK_UNINTERRUPTIBLE);
-}
-
-static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
-				 struct wb_writeback_args *args)
+static void
+__bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,
+		      bool range_cyclic, bool for_background)
 {
-	struct bdi_work *work;
+	struct wb_writeback_work *work;
 
 	/*
 	 * This is WB_SYNC_NONE writeback, so if allocation fails just
 	 * wakeup the thread for old dirty data writeback
 	 */
-	work = kmalloc(sizeof(*work), GFP_ATOMIC);
-	if (work) {
-		bdi_work_init(work, args);
-		bdi_queue_work(bdi, work);
-	} else {
-		struct bdi_writeback *wb = &bdi->wb;
-
-		if (wb->task)
-			wake_up_process(wb->task);
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work) {
+		if (bdi->wb.task)
+			wake_up_process(bdi->wb.task);
+		return;
 	}
+
+	work->sync_mode = WB_SYNC_NONE;
+	work->nr_pages  = nr_pages;
+	work->range_cyclic = range_cyclic;
+	work->for_background = for_background;
+
+	bdi_queue_work(bdi, work);
 }
 
 /**
- * bdi_sync_writeback - start and wait for writeback
+ * bdi_start_writeback - start writeback
  * @bdi: the backing device to write from
- * @sb: write inodes from this super_block
+ * @nr_pages: the number of pages to write
  *
  * Description:
- *   This does WB_SYNC_ALL data integrity writeback and waits for the
- *   IO to complete. Callers must hold the sb s_umount semaphore for
- *   reading, to avoid having the super disappear before we are done.
+ *   This does WB_SYNC_NONE opportunistic writeback. The IO is only
+ *   started when this function returns, we make no guarentees on
+ *   completion. Caller need not hold sb s_umount semaphore.
+ *
  */
-static void bdi_sync_writeback(struct backing_dev_info *bdi,
-			       struct super_block *sb)
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages)
 {
-	struct wb_writeback_args args = {
-		.sb		= sb,
-		.sync_mode	= WB_SYNC_ALL,
-		.nr_pages	= LONG_MAX,
-		.range_cyclic	= 0,
-	};
-	struct bdi_work work;
-
-	bdi_work_init(&work, &args);
-	work.state |= WS_ONSTACK;
-
-	bdi_queue_work(bdi, &work);
-	bdi_wait_on_work_clear(&work);
+	__bdi_start_writeback(bdi, nr_pages, true, false);
 }
 
 /**
- * bdi_start_writeback - start writeback
+ * bdi_start_background_writeback - start background writeback
  * @bdi: the backing device to write from
- * @nr_pages: the number of pages to write
  *
  * Description:
- *   This does WB_SYNC_NONE opportunistic writeback. The IO is only
+ *   This does WB_SYNC_NONE background writeback. The IO is only
  *   started when this function returns, we make no guarentees on
  *   completion. Caller need not hold sb s_umount semaphore.
- *
  */
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-			 long nr_pages)
+void bdi_start_background_writeback(struct backing_dev_info *bdi)
 {
-	struct wb_writeback_args args = {
-		.sb		= sb,
-		.sync_mode	= WB_SYNC_NONE,
-		.nr_pages	= nr_pages,
-		.range_cyclic	= 1,
-	};
-
-	/*
-	 * We treat @nr_pages=0 as the special case to do background writeback,
-	 * ie. to sync pages until the background dirty threshold is reached.
-	 */
-	if (!nr_pages) {
-		args.nr_pages = LONG_MAX;
-		args.for_background = 1;
-	}
-
-	bdi_alloc_queue_work(bdi, &args);
+	__bdi_start_writeback(bdi, LONG_MAX, true, true);
 }
 
 /*
@@ -548,134 +414,79 @@
 	return ret;
 }
 
-static void unpin_sb_for_writeback(struct super_block **psb)
-{
-	struct super_block *sb = *psb;
-
-	if (sb) {
-		up_read(&sb->s_umount);
-		put_super(sb);
-		*psb = NULL;
-	}
-}
-
 /*
- * For WB_SYNC_NONE writeback, the caller does not have the sb pinned
+ * For background writeback the caller does not have the sb pinned
  * before calling writeback. So make sure that we do pin it, so it doesn't
  * go away while we are writing inodes from it.
- *
- * Returns 0 if the super was successfully pinned (or pinning wasn't needed),
- * 1 if we failed.
  */
-static int pin_sb_for_writeback(struct writeback_control *wbc,
-				struct inode *inode, struct super_block **psb)
+static bool pin_sb_for_writeback(struct super_block *sb)
 {
-	struct super_block *sb = inode->i_sb;
-
-	/*
-	 * If this sb is already pinned, nothing more to do. If not and
-	 * *psb is non-NULL, unpin the old one first
-	 */
-	if (sb == *psb)
-		return 0;
-	else if (*psb)
-		unpin_sb_for_writeback(psb);
-
-	/*
-	 * Caller must already hold the ref for this
-	 */
-	if (wbc->sync_mode == WB_SYNC_ALL) {
-		WARN_ON(!rwsem_is_locked(&sb->s_umount));
-		return 0;
+	spin_lock(&sb_lock);
+	if (list_empty(&sb->s_instances)) {
+		spin_unlock(&sb_lock);
+		return false;
 	}
 
-	spin_lock(&sb_lock);
 	sb->s_count++;
+	spin_unlock(&sb_lock);
+
 	if (down_read_trylock(&sb->s_umount)) {
-		if (sb->s_root) {
-			spin_unlock(&sb_lock);
-			goto pinned;
-		}
-		/*
-		 * umounted, drop rwsem again and fall through to failure
-		 */
+		if (sb->s_root)
+			return true;
 		up_read(&sb->s_umount);
 	}
 
-	sb->s_count--;
-	spin_unlock(&sb_lock);
-	return 1;
-pinned:
-	*psb = sb;
-	return 0;
+	put_super(sb);
+	return false;
 }
 
-static void writeback_inodes_wb(struct bdi_writeback *wb,
-				struct writeback_control *wbc)
+/*
+ * Write a portion of b_io inodes which belong to @sb.
+ *
+ * If @only_this_sb is true, then find and write all such
+ * inodes. Otherwise write only ones which go sequentially
+ * in reverse order.
+ *
+ * Return 1, if the caller writeback routine should be
+ * interrupted. Otherwise return 0.
+ */
+static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb,
+		struct writeback_control *wbc, bool only_this_sb)
 {
-	struct super_block *sb = wbc->sb, *pin_sb = NULL;
-	const int is_blkdev_sb = sb_is_blkdev_sb(sb);
-	const unsigned long start = jiffies;	/* livelock avoidance */
-
-	spin_lock(&inode_lock);
-
-	if (!wbc->for_kupdate || list_empty(&wb->b_io))
-		queue_io(wb, wbc->older_than_this);
-
 	while (!list_empty(&wb->b_io)) {
-		struct inode *inode = list_entry(wb->b_io.prev,
-						struct inode, i_list);
 		long pages_skipped;
+		struct inode *inode = list_entry(wb->b_io.prev,
+						 struct inode, i_list);
 
-		/*
-		 * super block given and doesn't match, skip this inode
-		 */
-		if (sb && sb != inode->i_sb) {
-			redirty_tail(inode);
-			continue;
-		}
-
-		if (!bdi_cap_writeback_dirty(wb->bdi)) {
-			redirty_tail(inode);
-			if (is_blkdev_sb) {
+		if (inode->i_sb != sb) {
+			if (only_this_sb) {
 				/*
-				 * Dirty memory-backed blockdev: the ramdisk
-				 * driver does this.  Skip just this inode
+				 * We only want to write back data for this
+				 * superblock, move all inodes not belonging
+				 * to it back onto the dirty list.
 				 */
+				redirty_tail(inode);
 				continue;
 			}
+
 			/*
-			 * Dirty memory-backed inode against a filesystem other
-			 * than the kernel-internal bdev filesystem.  Skip the
-			 * entire superblock.
+			 * The inode belongs to a different superblock.
+			 * Bounce back to the caller to unpin this and
+			 * pin the next superblock.
 			 */
-			break;
+			return 0;
 		}
 
 		if (inode->i_state & (I_NEW | I_WILL_FREE)) {
 			requeue_io(inode);
 			continue;
 		}
-
-		if (wbc->nonblocking && bdi_write_congested(wb->bdi)) {
-			wbc->encountered_congestion = 1;
-			if (!is_blkdev_sb)
-				break;		/* Skip a congested fs */
-			requeue_io(inode);
-			continue;		/* Skip a congested blockdev */
-		}
-
 		/*
 		 * Was this inode dirtied after sync_sb_inodes was called?
 		 * This keeps sync from extra jobs and livelock.
 		 */
-		if (inode_dirtied_after(inode, start))
-			break;
-
-		if (pin_sb_for_writeback(wbc, inode, &pin_sb)) {
-			requeue_io(inode);
-			continue;
-		}
+		if (inode_dirtied_after(inode, wbc->wb_start))
+			return 1;
 
 		BUG_ON(inode->i_state & (I_FREEING | I_CLEAR));
 		__iget(inode);
@@ -694,23 +505,55 @@
 		spin_lock(&inode_lock);
 		if (wbc->nr_to_write <= 0) {
 			wbc->more_io = 1;
-			break;
+			return 1;
 		}
 		if (!list_empty(&wb->b_more_io))
 			wbc->more_io = 1;
 	}
+	/* b_io is empty */
+	return 1;
+}
 
-	unpin_sb_for_writeback(&pin_sb);
+void writeback_inodes_wb(struct bdi_writeback *wb,
+		struct writeback_control *wbc)
+{
+	int ret = 0;
 
+	wbc->wb_start = jiffies; /* livelock avoidance */
+	spin_lock(&inode_lock);
+	if (!wbc->for_kupdate || list_empty(&wb->b_io))
+		queue_io(wb, wbc->older_than_this);
+
+	while (!list_empty(&wb->b_io)) {
+		struct inode *inode = list_entry(wb->b_io.prev,
+						 struct inode, i_list);
+		struct super_block *sb = inode->i_sb;
+
+		if (!pin_sb_for_writeback(sb)) {
+			requeue_io(inode);
+			continue;
+		}
+		ret = writeback_sb_inodes(sb, wb, wbc, false);
+		drop_super(sb);
+
+		if (ret)
+			break;
+	}
 	spin_unlock(&inode_lock);
 	/* Leave any unwritten inodes on b_io */
 }
 
-void writeback_inodes_wbc(struct writeback_control *wbc)
+static void __writeback_inodes_sb(struct super_block *sb,
+		struct bdi_writeback *wb, struct writeback_control *wbc)
 {
-	struct backing_dev_info *bdi = wbc->bdi;
+	WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
-	writeback_inodes_wb(&bdi->wb, wbc);
+	wbc->wb_start = jiffies; /* livelock avoidance */
+	spin_lock(&inode_lock);
+	if (!wbc->for_kupdate || list_empty(&wb->b_io))
+		queue_io(wb, wbc->older_than_this);
+	writeback_sb_inodes(sb, wb, wbc, true);
+	spin_unlock(&inode_lock);
 }
 
 /*
@@ -748,15 +591,13 @@
  * all dirty pages if they are all attached to "old" mappings.
  */
 static long wb_writeback(struct bdi_writeback *wb,
-			 struct wb_writeback_args *args)
+			 struct wb_writeback_work *work)
 {
 	struct writeback_control wbc = {
-		.bdi			= wb->bdi,
-		.sb			= args->sb,
-		.sync_mode		= args->sync_mode,
+		.sync_mode		= work->sync_mode,
 		.older_than_this	= NULL,
-		.for_kupdate		= args->for_kupdate,
-		.range_cyclic		= args->range_cyclic,
+		.for_kupdate		= work->for_kupdate,
+		.range_cyclic		= work->range_cyclic,
 	};
 	unsigned long oldest_jif;
 	long wrote = 0;
@@ -776,22 +617,24 @@
 		/*
 		 * Stop writeback when nr_pages has been consumed
 		 */
-		if (args->nr_pages <= 0)
+		if (work->nr_pages <= 0)
 			break;
 
 		/*
 		 * For background writeout, stop when we are below the
 		 * background dirty threshold
 		 */
-		if (args->for_background && !over_bground_thresh())
+		if (work->for_background && !over_bground_thresh())
 			break;
 
 		wbc.more_io = 0;
-		wbc.encountered_congestion = 0;
 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
 		wbc.pages_skipped = 0;
-		writeback_inodes_wb(wb, &wbc);
-		args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
+		if (work->sb)
+			__writeback_inodes_sb(work->sb, wb, &wbc);
+		else
+			writeback_inodes_wb(wb, &wbc);
+		work->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
 		wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write;
 
 		/*
@@ -827,31 +670,21 @@
 }
 
 /*
- * Return the next bdi_work struct that hasn't been processed by this
- * wb thread yet. ->seen is initially set for each thread that exists
- * for this device, when a thread first notices a piece of work it
- * clears its bit. Depending on writeback type, the thread will notify
- * completion on either receiving the work (WB_SYNC_NONE) or after
- * it is done (WB_SYNC_ALL).
+ * Return the next wb_writeback_work struct that hasn't been processed yet.
  */
-static struct bdi_work *get_next_work_item(struct backing_dev_info *bdi,
-					   struct bdi_writeback *wb)
+static struct wb_writeback_work *
+get_next_work_item(struct backing_dev_info *bdi, struct bdi_writeback *wb)
 {
-	struct bdi_work *work, *ret = NULL;
-
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(work, &bdi->work_list, list) {
-		if (!test_bit(wb->nr, &work->seen))
-			continue;
-		clear_bit(wb->nr, &work->seen);
+	struct wb_writeback_work *work = NULL;
 
-		ret = work;
-		break;
+	spin_lock(&bdi->wb_lock);
+	if (!list_empty(&bdi->work_list)) {
+		work = list_entry(bdi->work_list.next,
+				  struct wb_writeback_work, list);
+		list_del_init(&work->list);
 	}
-
-	rcu_read_unlock();
-	return ret;
+	spin_unlock(&bdi->wb_lock);
+	return work;
 }
 
 static long wb_check_old_data_flush(struct bdi_writeback *wb)
@@ -859,6 +692,12 @@
 	unsigned long expired;
 	long nr_pages;
 
+	/*
+	 * When set to zero, disable periodic writeback
+	 */
+	if (!dirty_writeback_interval)
+		return 0;
+
 	expired = wb->last_old_flush +
 			msecs_to_jiffies(dirty_writeback_interval * 10);
 	if (time_before(jiffies, expired))
@@ -870,14 +709,14 @@
 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
 
 	if (nr_pages) {
-		struct wb_writeback_args args = {
+		struct wb_writeback_work work = {
 			.nr_pages	= nr_pages,
 			.sync_mode	= WB_SYNC_NONE,
 			.for_kupdate	= 1,
 			.range_cyclic	= 1,
 		};
 
-		return wb_writeback(wb, &args);
+		return wb_writeback(wb, &work);
 	}
 
 	return 0;
@@ -889,33 +728,27 @@
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
 {
 	struct backing_dev_info *bdi = wb->bdi;
-	struct bdi_work *work;
+	struct wb_writeback_work *work;
 	long wrote = 0;
 
 	while ((work = get_next_work_item(bdi, wb)) != NULL) {
-		struct wb_writeback_args args = work->args;
-
 		/*
 		 * Override sync mode, in case we must wait for completion
+		 * because this thread is exiting now.
 		 */
 		if (force_wait)
-			work->args.sync_mode = args.sync_mode = WB_SYNC_ALL;
-
-		/*
-		 * If this isn't a data integrity operation, just notify
-		 * that we have seen this work and we are now starting it.
-		 */
-		if (args.sync_mode == WB_SYNC_NONE)
-			wb_clear_pending(wb, work);
+			work->sync_mode = WB_SYNC_ALL;
 
-		wrote += wb_writeback(wb, &args);
+		wrote += wb_writeback(wb, work);
 
 		/*
-		 * This is a data integrity writeback, so only do the
-		 * notification when we have completed the work.
+		 * Notify the caller of completion if this is a synchronous
+		 * work item, otherwise just free it.
 		 */
-		if (args.sync_mode == WB_SYNC_ALL)
-			wb_clear_pending(wb, work);
+		if (work->done)
+			complete(work->done);
+		else
+			kfree(work);
 	}
 
 	/*
@@ -954,8 +787,12 @@
 				break;
 		}
 
-		wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10);
-		schedule_timeout_interruptible(wait_jiffies);
+		if (dirty_writeback_interval) {
+			wait_jiffies = msecs_to_jiffies(dirty_writeback_interval * 10);
+			schedule_timeout_interruptible(wait_jiffies);
+		} else
+			schedule();
+
 		try_to_freeze();
 	}
 
@@ -963,42 +800,27 @@
 }
 
 /*
- * Schedule writeback for all backing devices. This does WB_SYNC_NONE
- * writeback, for integrity writeback see bdi_sync_writeback().
+ * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
+ * the whole world.
  */
-static void bdi_writeback_all(struct super_block *sb, long nr_pages)
+void wakeup_flusher_threads(long nr_pages)
 {
-	struct wb_writeback_args args = {
-		.sb		= sb,
-		.nr_pages	= nr_pages,
-		.sync_mode	= WB_SYNC_NONE,
-	};
 	struct backing_dev_info *bdi;
 
-	rcu_read_lock();
+	if (!nr_pages) {
+		nr_pages = global_page_state(NR_FILE_DIRTY) +
+				global_page_state(NR_UNSTABLE_NFS);
+	}
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
 		if (!bdi_has_dirty_io(bdi))
 			continue;
-
-		bdi_alloc_queue_work(bdi, &args);
+		__bdi_start_writeback(bdi, nr_pages, false, false);
 	}
-
 	rcu_read_unlock();
 }
 
-/*
- * Start writeback of `nr_pages' pages.  If `nr_pages' is zero, write back
- * the whole world.
- */
-void wakeup_flusher_threads(long nr_pages)
-{
-	if (nr_pages == 0)
-		nr_pages = global_page_state(NR_FILE_DIRTY) +
-				global_page_state(NR_UNSTABLE_NFS);
-	bdi_writeback_all(NULL, nr_pages);
-}
-
 static noinline void block_dump___mark_inode_dirty(struct inode *inode)
 {
 	if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
@@ -1071,6 +893,8 @@
 	if ((inode->i_state & flags) == flags)
 		return;
 
+	trace_dirty_inode(inode, current);
+
 	if (unlikely(block_dump))
 		block_dump___mark_inode_dirty(inode);
 
@@ -1203,16 +1027,43 @@
 {
 	unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
 	unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
-	long nr_to_write;
+	DECLARE_COMPLETION_ONSTACK(done);
+	struct wb_writeback_work work = {
+		.sb		= sb,
+		.sync_mode	= WB_SYNC_NONE,
+		.done		= &done,
+	};
+
+	WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
-	nr_to_write = nr_dirty + nr_unstable +
+	work.nr_pages = nr_dirty + nr_unstable +
 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
 
-	bdi_start_writeback(sb->s_bdi, sb, nr_to_write);
+	bdi_queue_work(sb->s_bdi, &work);
+	wait_for_completion(&done);
 }
 EXPORT_SYMBOL(writeback_inodes_sb);
 
 /**
+ * writeback_inodes_sb_if_idle	-	start writeback if none underway
+ * @sb: the superblock
+ *
+ * Invoke writeback_inodes_sb if no writeback is currently underway.
+ * Returns 1 if writeback was started, 0 if not.
+ */
+int writeback_inodes_sb_if_idle(struct super_block *sb)
+{
+	if (!writeback_in_progress(sb->s_bdi)) {
+		down_read(&sb->s_umount);
+		writeback_inodes_sb(sb);
+		up_read(&sb->s_umount);
+		return 1;
+	} else
+		return 0;
+}
+EXPORT_SYMBOL(writeback_inodes_sb_if_idle);
+
+/**
  * sync_inodes_sb	-	sync sb inode pages
  * @sb: the superblock
  *
@@ -1221,7 +1072,20 @@
  */
 void sync_inodes_sb(struct super_block *sb)
 {
-	bdi_sync_writeback(sb->s_bdi, sb);
+	DECLARE_COMPLETION_ONSTACK(done);
+	struct wb_writeback_work work = {
+		.sb		= sb,
+		.sync_mode	= WB_SYNC_ALL,
+		.nr_pages	= LONG_MAX,
+		.range_cyclic	= 0,
+		.done		= &done,
+	};
+
+	WARN_ON(!rwsem_is_locked(&sb->s_umount));
+
+	bdi_queue_work(sb->s_bdi, &work);
+	wait_for_completion(&done);
+
 	wait_sb_inodes(sb);
 }
 EXPORT_SYMBOL(sync_inodes_sb);
--- linux-ec2-2.6.32.orig/fs/binfmt_elf.c
+++ linux-ec2-2.6.32/fs/binfmt_elf.c
@@ -35,6 +35,10 @@
 #include <asm/param.h>
 #include <asm/page.h>
 
+#ifndef arch_add_exec_range
+#define arch_add_exec_range(mm, limit) do { ; } while (0)
+#endif
+
 static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
 static int load_elf_library(struct file *);
 static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
@@ -662,27 +666,6 @@
 			if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
 				goto out_free_interp;
 
-			/*
-			 * The early SET_PERSONALITY here is so that the lookup
-			 * for the interpreter happens in the namespace of the 
-			 * to-be-execed image.  SET_PERSONALITY can select an
-			 * alternate root.
-			 *
-			 * However, SET_PERSONALITY is NOT allowed to switch
-			 * this task into the new images's memory mapping
-			 * policy - that is, TASK_SIZE must still evaluate to
-			 * that which is appropriate to the execing application.
-			 * This is because exit_mmap() needs to have TASK_SIZE
-			 * evaluate to the size of the old image.
-			 *
-			 * So if (say) a 64-bit application is execing a 32-bit
-			 * application it is the architecture's responsibility
-			 * to defer changing the value of TASK_SIZE until the
-			 * switch really is going to happen - do this in
-			 * flush_thread().	- akpm
-			 */
-			SET_PERSONALITY(loc->elf_ex);
-
 			interpreter = open_exec(elf_interpreter);
 			retval = PTR_ERR(interpreter);
 			if (IS_ERR(interpreter))
@@ -730,9 +713,6 @@
 		/* Verify the interpreter has a valid arch */
 		if (!elf_check_arch(&loc->interp_elf_ex))
 			goto out_free_dentry;
-	} else {
-		/* Executables without an interpreter also need a personality  */
-		SET_PERSONALITY(loc->elf_ex);
 	}
 
 	/* Flush all traces of the currently running executable */
@@ -740,6 +720,14 @@
 	if (retval)
 		goto out_free_dentry;
 
+#if defined(CONFIG_X86_32) && !defined(CONFIG_UML)
+	/*
+	 * Turn off the CS limit completely if NX active:
+	 */
+	if (executable_stack != EXSTACK_DISABLE_X || nx_enabled)
+		arch_add_exec_range(current->mm, -1);
+#endif
+
 	/* OK, This is the point of no return */
 	current->flags &= ~PF_FORKNOEXEC;
 	current->mm->def_flags = def_flags;
@@ -752,7 +740,8 @@
 
 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
 		current->flags |= PF_RANDOMIZE;
-	arch_pick_mmap_layout(current->mm);
+
+	setup_new_exec(bprm);
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
--- linux-ec2-2.6.32.orig/fs/char_dev.c
+++ linux-ec2-2.6.32/fs/char_dev.c
@@ -39,7 +39,9 @@
 #endif
 		/* permit direct mmap, for read, write or exec */
 		BDI_CAP_MAP_DIRECT |
-		BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP),
+		BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP |
+		/* no writeback happens */
+		BDI_CAP_NO_ACCT_AND_WRITEBACK),
 };
 
 static struct kobj_map *cdev_map;
--- linux-ec2-2.6.32.orig/fs/binfmt_som.c
+++ linux-ec2-2.6.32/fs/binfmt_som.c
@@ -227,6 +227,7 @@
 	/* OK, This is the point of no return */
 	current->flags &= ~PF_FORKNOEXEC;
 	current->personality = PER_HPUX;
+	setup_new_exec(bprm);
 
 	/* Set the task size for HP-UX processes such that
 	 * the gateway page is outside the address space.
--- linux-ec2-2.6.32.orig/fs/libfs.c
+++ linux-ec2-2.6.32/fs/libfs.c
@@ -415,7 +415,8 @@
  * unique inode values later for this filesystem, then you must take care
  * to pass it an appropriate max_reserved value to avoid collisions.
  */
-int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files)
+int simple_fill_super(struct super_block *s, unsigned long magic,
+		      struct tree_descr *files)
 {
 	struct inode *inode;
 	struct dentry *root;
--- linux-ec2-2.6.32.orig/fs/splice.c
+++ linux-ec2-2.6.32/fs/splice.c
@@ -365,17 +365,7 @@
 		 * If the page isn't uptodate, we may need to start io on it
 		 */
 		if (!PageUptodate(page)) {
-			/*
-			 * If in nonblock mode then dont block on waiting
-			 * for an in-flight io page
-			 */
-			if (flags & SPLICE_F_NONBLOCK) {
-				if (!trylock_page(page)) {
-					error = -EAGAIN;
-					break;
-				}
-			} else
-				lock_page(page);
+			lock_page(page);
 
 			/*
 			 * Page was truncated, or invalidated by the
@@ -648,9 +638,11 @@
 	ret = buf->ops->confirm(pipe, buf);
 	if (!ret) {
 		more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
-
-		ret = file->f_op->sendpage(file, buf->page, buf->offset,
-					   sd->len, &pos, more);
+		if (file->f_op && file->f_op->sendpage)
+			ret = file->f_op->sendpage(file, buf->page, buf->offset,
+						   sd->len, &pos, more);
+		else
+			ret = -EINVAL;
 	}
 
 	return ret;
@@ -1051,8 +1043,8 @@
 /*
  * Attempt to initiate a splice from pipe to file.
  */
-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-			   loff_t *ppos, size_t len, unsigned int flags)
+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+		    loff_t *ppos, size_t len, unsigned int flags)
 {
 	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
 				loff_t *, size_t, unsigned int);
@@ -1068,19 +1060,21 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	splice_write = out->f_op->splice_write;
-	if (!splice_write)
+	if (out->f_op && out->f_op->splice_write)
+		splice_write = out->f_op->splice_write;
+	else
 		splice_write = default_file_splice_write;
 
 	return splice_write(pipe, out, ppos, len, flags);
 }
+EXPORT_SYMBOL(do_splice_from);
 
 /*
  * Attempt to initiate a splice from a file to a pipe.
  */
-static long do_splice_to(struct file *in, loff_t *ppos,
-			 struct pipe_inode_info *pipe, size_t len,
-			 unsigned int flags)
+long do_splice_to(struct file *in, loff_t *ppos,
+		  struct pipe_inode_info *pipe, size_t len,
+		  unsigned int flags)
 {
 	ssize_t (*splice_read)(struct file *, loff_t *,
 			       struct pipe_inode_info *, size_t, unsigned int);
@@ -1093,12 +1087,14 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	splice_read = in->f_op->splice_read;
-	if (!splice_read)
+	if (in->f_op && in->f_op->splice_read)
+		splice_read = in->f_op->splice_read;
+	else
 		splice_read = default_file_splice_read;
 
 	return splice_read(in, ppos, pipe, len, flags);
 }
+EXPORT_SYMBOL(do_splice_to);
 
 /**
  * splice_direct_to_actor - splices data directly between two non-pipes
@@ -1316,7 +1312,8 @@
 		if (off_in)
 			return -ESPIPE;
 		if (off_out) {
-			if (out->f_op->llseek == no_llseek)
+			if (!out->f_op || !out->f_op->llseek ||
+			    out->f_op->llseek == no_llseek)
 				return -EINVAL;
 			if (copy_from_user(&offset, off_out, sizeof(loff_t)))
 				return -EFAULT;
@@ -1336,7 +1333,8 @@
 		if (off_out)
 			return -ESPIPE;
 		if (off_in) {
-			if (in->f_op->llseek == no_llseek)
+			if (!in->f_op || !in->f_op->llseek ||
+			    in->f_op->llseek == no_llseek)
 				return -EINVAL;
 			if (copy_from_user(&offset, off_in, sizeof(loff_t)))
 				return -EFAULT;
--- linux-ec2-2.6.32.orig/fs/binfmt_flat.c
+++ linux-ec2-2.6.32/fs/binfmt_flat.c
@@ -519,6 +519,7 @@
 
 		/* OK, This is the point of no return */
 		set_personality(PER_LINUX_32BIT);
+		setup_new_exec(bprm);
 	}
 
 	/*
--- linux-ec2-2.6.32.orig/fs/namespace.c
+++ linux-ec2-2.6.32/fs/namespace.c
@@ -39,6 +39,7 @@
 
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
+EXPORT_SYMBOL(vfsmount_lock);
 
 static int event;
 static DEFINE_IDA(mnt_id_ida);
@@ -1119,8 +1120,15 @@
 {
 	struct path path;
 	int retval;
+	int lookup_flags = 0;
 
-	retval = user_path(name, &path);
+	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+		return -EINVAL;
+
+	if (!(flags & UMOUNT_NOFOLLOW))
+		lookup_flags |= LOOKUP_FOLLOW;
+
+	retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
 	if (retval)
 		goto out;
 	retval = -EINVAL;
--- linux-ec2-2.6.32.orig/fs/nilfs2/super.c
+++ linux-ec2-2.6.32/fs/nilfs2/super.c
@@ -781,6 +781,7 @@
 	sb->s_export_op = &nilfs_export_ops;
 	sb->s_root = NULL;
 	sb->s_time_gran = 1;
+	sb->s_bdi = nilfs->ns_bdi;
 
 	if (!nilfs_loaded(nilfs)) {
 		err = load_nilfs(nilfs, sbi);
--- linux-ec2-2.6.32.orig/fs/nilfs2/file.c
+++ linux-ec2-2.6.32/fs/nilfs2/file.c
@@ -72,10 +72,9 @@
 	/*
 	 * check to see if the page is mapped already (no holes)
 	 */
-	if (PageMappedToDisk(page)) {
-		unlock_page(page);
+	if (PageMappedToDisk(page))
 		goto mapped;
-	}
+
 	if (page_has_buffers(page)) {
 		struct buffer_head *bh, *head;
 		int fully_mapped = 1;
@@ -90,7 +89,6 @@
 
 		if (fully_mapped) {
 			SetPageMappedToDisk(page);
-			unlock_page(page);
 			goto mapped;
 		}
 	}
@@ -105,16 +103,18 @@
 		return VM_FAULT_SIGBUS;
 
 	ret = block_page_mkwrite(vma, vmf, nilfs_get_block);
-	if (unlikely(ret)) {
+	if (ret != VM_FAULT_LOCKED) {
 		nilfs_transaction_abort(inode->i_sb);
 		return ret;
 	}
+	nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode,
+			     1 << (PAGE_SHIFT - inode->i_blkbits));
 	nilfs_transaction_commit(inode->i_sb);
 
  mapped:
 	SetPageChecked(page);
 	wait_on_page_writeback(page);
-	return 0;
+	return VM_FAULT_LOCKED;
 }
 
 static const struct vm_operations_struct nilfs_file_vm_ops = {
--- linux-ec2-2.6.32.orig/fs/bfs/inode.c
+++ linux-ec2-2.6.32/fs/bfs/inode.c
@@ -353,35 +353,35 @@
 	struct inode *inode;
 	unsigned i, imap_len;
 	struct bfs_sb_info *info;
-	long ret = -EINVAL;
+	int ret = -EINVAL;
 	unsigned long i_sblock, i_eblock, i_eoff, s_size;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
+	mutex_init(&info->bfs_lock);
 	s->s_fs_info = info;
 
 	sb_set_blocksize(s, BFS_BSIZE);
 
-	bh = sb_bread(s, 0);
-	if(!bh)
+	info->si_sbh = sb_bread(s, 0);
+	if (!info->si_sbh)
 		goto out;
-	bfs_sb = (struct bfs_super_block *)bh->b_data;
+	bfs_sb = (struct bfs_super_block *)info->si_sbh->b_data;
 	if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
 		if (!silent)
 			printf("No BFS filesystem on %s (magic=%08x)\n", 
 				s->s_id,  le32_to_cpu(bfs_sb->s_magic));
-		goto out;
+		goto out1;
 	}
 	if (BFS_UNCLEAN(bfs_sb, s) && !silent)
 		printf("%s is unclean, continuing\n", s->s_id);
 
 	s->s_magic = BFS_MAGIC;
-	info->si_sbh = bh;
 
 	if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) {
 		printf("Superblock is corrupted\n");
-		goto out;
+		goto out1;
 	}
 
 	info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
@@ -390,7 +390,7 @@
 	imap_len = (info->si_lasti / 8) + 1;
 	info->si_imap = kzalloc(imap_len, GFP_KERNEL);
 	if (!info->si_imap)
-		goto out;
+		goto out1;
 	for (i = 0; i < BFS_ROOT_INO; i++)
 		set_bit(i, info->si_imap);
 
@@ -398,15 +398,13 @@
 	inode = bfs_iget(s, BFS_ROOT_INO);
 	if (IS_ERR(inode)) {
 		ret = PTR_ERR(inode);
-		kfree(info->si_imap);
-		goto out;
+		goto out2;
 	}
 	s->s_root = d_alloc_root(inode);
 	if (!s->s_root) {
 		iput(inode);
 		ret = -ENOMEM;
-		kfree(info->si_imap);
-		goto out;
+		goto out2;
 	}
 
 	info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
@@ -419,10 +417,8 @@
 	bh = sb_bread(s, info->si_blocks - 1);
 	if (!bh) {
 		printf("Last block not available: %lu\n", info->si_blocks - 1);
-		iput(inode);
 		ret = -EIO;
-		kfree(info->si_imap);
-		goto out;
+		goto out3;
 	}
 	brelse(bh);
 
@@ -459,11 +455,8 @@
 			printf("Inode 0x%08x corrupted\n", i);
 
 			brelse(bh);
-			s->s_root = NULL;
-			kfree(info->si_imap);
-			kfree(info);
-			s->s_fs_info = NULL;
-			return -EIO;
+			ret = -EIO;
+			goto out3;
 		}
 
 		if (!di->i_ino) {
@@ -483,11 +476,17 @@
 		s->s_dirt = 1;
 	} 
 	dump_imap("read_super", s);
-	mutex_init(&info->bfs_lock);
 	return 0;
 
+out3:
+	dput(s->s_root);
+	s->s_root = NULL;
+out2:
+	kfree(info->si_imap);
+out1:
+	brelse(info->si_sbh);
 out:
-	brelse(bh);
+	mutex_destroy(&info->bfs_lock);
 	kfree(info);
 	s->s_fs_info = NULL;
 	return ret;
--- linux-ec2-2.6.32.orig/fs/fat/namei_vfat.c
+++ linux-ec2-2.6.32/fs/fat/namei_vfat.c
@@ -309,7 +309,7 @@
 {
 	struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;
 	wchar_t *ip, *ext_start, *end, *name_start;
-	unsigned char base[9], ext[4], buf[8], *p;
+	unsigned char base[9], ext[4], buf[5], *p;
 	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
 	int chl, chi;
 	int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
@@ -467,7 +467,7 @@
 			return 0;
 	}
 
-	i = jiffies & 0xffff;
+	i = jiffies;
 	sz = (jiffies >> 16) & 0x7;
 	if (baselen > 2) {
 		baselen = numtail2_baselen;
@@ -476,7 +476,7 @@
 	name_res[baselen + 4] = '~';
 	name_res[baselen + 5] = '1' + sz;
 	while (1) {
-		sprintf(buf, "%04X", i);
+		snprintf(buf, sizeof(buf), "%04X", i & 0xffff);
 		memcpy(&name_res[baselen], buf, 4);
 		if (vfat_find_form(dir, name_res) < 0)
 			break;
--- linux-ec2-2.6.32.orig/fs/nfsd/vfs.c
+++ linux-ec2-2.6.32/fs/nfsd/vfs.c
@@ -774,12 +774,9 @@
 	int (*fsync) (struct file *, struct dentry *, int);
 	int err;
 
-	err = filemap_fdatawrite(inode->i_mapping);
+	err = filemap_write_and_wait(inode->i_mapping);
 	if (err == 0 && fop && (fsync = fop->fsync))
 		err = fsync(filp, dp, 0);
-	if (err == 0)
-		err = filemap_fdatawait(inode->i_mapping);
-
 	return err;
 }
 
@@ -826,7 +823,7 @@
 		if (ra->p_count == 0)
 			frap = rap;
 	}
-	depth = nfsdstats.ra_size*11/10;
+	depth = nfsdstats.ra_size;
 	if (!frap) {	
 		spin_unlock(&rab->pb_lock);
 		return NULL;
@@ -1382,7 +1379,7 @@
 		goto out;
 	if (!(iap->ia_valid & ATTR_MODE))
 		iap->ia_mode = 0;
-	err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+	err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
 	if (err)
 		goto out;
 
@@ -1404,6 +1401,13 @@
 	if (IS_ERR(dchild))
 		goto out_nfserr;
 
+	/* If file doesn't exist, check for permissions to create one */
+	if (!dchild->d_inode) {
+		err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+		if (err)
+			goto out;
+	}
+
 	err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
 	if (err)
 		goto out;
--- linux-ec2-2.6.32.orig/fs/nfsd/nfs4acl.c
+++ linux-ec2-2.6.32/fs/nfsd/nfs4acl.c
@@ -389,7 +389,7 @@
 	sort_pacl_range(pacl, 1, i-1);
 
 	BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
-	j = i++;
+	j = ++i;
 	while (pacl->a_entries[j].e_tag == ACL_GROUP)
 		j++;
 	sort_pacl_range(pacl, i, j-1);
--- linux-ec2-2.6.32.orig/fs/nfsd/nfs3xdr.c
+++ linux-ec2-2.6.32/fs/nfsd/nfs3xdr.c
@@ -273,9 +273,11 @@
 	err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
 			&fhp->fh_post_attr);
 	fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
-	if (err)
+	if (err) {
 		fhp->fh_post_saved = 0;
-	else
+		/* Grab the ctime anyway - set_change_info might use it */
+		fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+	} else
 		fhp->fh_post_saved = 1;
 }
 
--- linux-ec2-2.6.32.orig/fs/nfsd/nfs4xdr.c
+++ linux-ec2-2.6.32/fs/nfsd/nfs4xdr.c
@@ -168,10 +168,10 @@
 	argp->p = page_address(argp->pagelist[0]);
 	argp->pagelist++;
 	if (argp->pagelen < PAGE_SIZE) {
-		argp->end = p + (argp->pagelen>>2);
+		argp->end = argp->p + (argp->pagelen>>2);
 		argp->pagelen = 0;
 	} else {
-		argp->end = p + (PAGE_SIZE>>2);
+		argp->end = argp->p + (PAGE_SIZE>>2);
 		argp->pagelen -= PAGE_SIZE;
 	}
 	memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
@@ -323,8 +323,8 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
-			goto out_nfserr;
+		if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
+			return status;
 		iattr->ia_valid |= ATTR_UID;
 	}
 	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
@@ -334,8 +334,8 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
-			goto out_nfserr;
+		if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
+			return status;
 		iattr->ia_valid |= ATTR_GID;
 	}
 	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
@@ -1187,8 +1187,6 @@
 			READ_BUF(4);
 			READ32(dummy);
 			READ_BUF(dummy * 4);
-			for (i = 0; i < dummy; ++i)
-				READ32(dummy);
 			break;
 		case RPC_AUTH_GSS:
 			dprintk("RPC_AUTH_GSS callback secflavor "
@@ -1204,7 +1202,6 @@
 			READ_BUF(4);
 			READ32(dummy);
 			READ_BUF(dummy);
-			p += XDR_QUADLEN(dummy);
 			break;
 		default:
 			dprintk("Illegal callback secflavor\n");
@@ -1433,10 +1430,10 @@
 			argp->p = page_address(argp->pagelist[0]);
 			argp->pagelist++;
 			if (argp->pagelen < PAGE_SIZE) {
-				argp->end = p + (argp->pagelen>>2);
+				argp->end = argp->p + (argp->pagelen>>2);
 				argp->pagelen = 0;
 			} else {
-				argp->end = p + (PAGE_SIZE>>2);
+				argp->end = argp->p + (PAGE_SIZE>>2);
 				argp->pagelen -= PAGE_SIZE;
 			}
 		}
@@ -2129,9 +2126,15 @@
 		 * and this is the root of a cross-mounted filesystem.
 		 */
 		if (ignore_crossmnt == 0 &&
-		    exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) {
-			err = vfs_getattr(exp->ex_path.mnt->mnt_parent,
-				exp->ex_path.mnt->mnt_mountpoint, &stat);
+		    dentry == exp->ex_path.mnt->mnt_root) {
+			struct path path = exp->ex_path;
+			path_get(&path);
+			while (follow_up(&path)) {
+				if (path.dentry != path.mnt->mnt_root)
+					break;
+			}
+			err = vfs_getattr(path.mnt, path.dentry, &stat);
+			path_put(&path);
 			if (err)
 				goto out_nfserr;
 		}
--- linux-ec2-2.6.32.orig/fs/nfsd/lockd.c
+++ linux-ec2-2.6.32/fs/nfsd/lockd.c
@@ -44,7 +44,6 @@
 	exp_readlock();
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
 	fh_put(&fh);
-	rqstp->rq_client = NULL;
 	exp_readunlock();
  	/* We return nlm error codes as nlm doesn't know
 	 * about nfsd, but nfsd does know about nlm..
--- linux-ec2-2.6.32.orig/fs/nfsd/nfs4state.c
+++ linux-ec2-2.6.32/fs/nfsd/nfs4state.c
@@ -2002,7 +2002,9 @@
 {
 	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
 		drop_file_write_access(filp);
+		spin_lock(&filp->f_lock);
 		filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+		spin_unlock(&filp->f_lock);
 	}
 }
 
--- linux-ec2-2.6.32.orig/fs/nfsd/nfs4proc.c
+++ linux-ec2-2.6.32/fs/nfsd/nfs4proc.c
@@ -964,8 +964,8 @@
 			      void *);
 enum nfsd4_op_flags {
 	ALLOWED_WITHOUT_FH = 1 << 0,	/* No current filehandle required */
-	ALLOWED_ON_ABSENT_FS = 2 << 0,	/* ops processed on absent fs */
-	ALLOWED_AS_FIRST_OP = 3 << 0,	/* ops reqired first in compound */
+	ALLOWED_ON_ABSENT_FS = 1 << 1,	/* ops processed on absent fs */
+	ALLOWED_AS_FIRST_OP = 1 << 2,	/* ops reqired first in compound */
 };
 
 struct nfsd4_operation {
--- linux-ec2-2.6.32.orig/fs/nfsd/nfssvc.c
+++ linux-ec2-2.6.32/fs/nfsd/nfssvc.c
@@ -136,7 +136,7 @@
 int nfsd_vers(int vers, enum vers_op change)
 {
 	if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
-		return -1;
+		return 0;
 	switch(change) {
 	case NFSD_SET:
 		nfsd_versions[vers] = nfsd_version[vers];
--- linux-ec2-2.6.32.orig/fs/9p/vfs_super.c
+++ linux-ec2-2.6.32/fs/9p/vfs_super.c
@@ -188,7 +188,8 @@
 
 	P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
 
-	v9fs_dentry_release(s->s_root);	/* clunk root */
+	if (s->s_root)
+		v9fs_dentry_release(s->s_root);	/* clunk root */
 
 	kill_anon_super(s);
 
--- linux-ec2-2.6.32.orig/fs/9p/vfs_file.c
+++ linux-ec2-2.6.32/fs/9p/vfs_file.c
@@ -114,7 +114,7 @@
 	P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
 
 	/* No mandatory locks */
-	if (__mandatory_lock(inode))
+	if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 		return -ENOLCK;
 
 	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
--- linux-ec2-2.6.32.orig/fs/exofs/dir.c
+++ linux-ec2-2.6.32/fs/exofs/dir.c
@@ -608,7 +608,7 @@
 	de->inode_no = cpu_to_le64(parent->i_ino);
 	memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR));
 	exofs_set_de_type(de, inode);
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(kaddr, KM_USER0);
 	err = exofs_commit_chunk(page, 0, chunk_size);
 fail:
 	page_cache_release(page);
--- linux-ec2-2.6.32.orig/fs/exofs/inode.c
+++ linux-ec2-2.6.32/fs/exofs/inode.c
@@ -731,13 +731,28 @@
 					fsdata);
 }
 
+static int exofs_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *page, void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	/* According to comment in simple_write_end i_mutex is held */
+	loff_t i_size = inode->i_size;
+	int ret;
+
+	ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
+	if (i_size != inode->i_size)
+		mark_inode_dirty(inode);
+	return ret;
+}
+
 const struct address_space_operations exofs_aops = {
 	.readpage	= exofs_readpage,
 	.readpages	= exofs_readpages,
 	.writepage	= exofs_writepage,
 	.writepages	= exofs_writepages,
 	.write_begin	= exofs_write_begin_export,
-	.write_end	= simple_write_end,
+	.write_end	= exofs_write_end,
 };
 
 /******************************************************************************
--- linux-ec2-2.6.32.orig/fs/squashfs/dir.c
+++ linux-ec2-2.6.32/fs/squashfs/dir.c
@@ -173,6 +173,11 @@
 		length += sizeof(dirh);
 
 		dir_count = le32_to_cpu(dirh.count) + 1;
+
+		/* dir_count should never be larger than 256 */
+		if (dir_count > 256)
+			goto failed_read;
+
 		while (dir_count--) {
 			/*
 			 * Read directory entry.
@@ -184,6 +189,10 @@
 
 			size = le16_to_cpu(dire->size) + 1;
 
+			/* size should never be larger than SQUASHFS_NAME_LEN */
+			if (size > SQUASHFS_NAME_LEN)
+				goto failed_read;
+
 			err = squashfs_read_metadata(inode->i_sb, dire->name,
 					&block, &offset, size);
 			if (err < 0)
--- linux-ec2-2.6.32.orig/fs/squashfs/namei.c
+++ linux-ec2-2.6.32/fs/squashfs/namei.c
@@ -175,6 +175,11 @@
 		length += sizeof(dirh);
 
 		dir_count = le32_to_cpu(dirh.count) + 1;
+
+		/* dir_count should never be larger than 256 */
+		if (dir_count > 256)
+			goto data_error;
+
 		while (dir_count--) {
 			/*
 			 * Read directory entry.
@@ -186,6 +191,10 @@
 
 			size = le16_to_cpu(dire->size) + 1;
 
+			/* size should never be larger than SQUASHFS_NAME_LEN */
+			if (size > SQUASHFS_NAME_LEN)
+				goto data_error;
+
 			err = squashfs_read_metadata(dir->i_sb, dire->name,
 					&block, &offset, size);
 			if (err < 0)
@@ -227,6 +236,9 @@
 	d_add(dentry, inode);
 	return ERR_PTR(0);
 
+data_error:
+	err = -EIO;
+
 read_failure:
 	ERROR("Unable to read directory block [%llx:%x]\n",
 		squashfs_i(dir)->start + msblk->directory_table,
--- linux-ec2-2.6.32.orig/fs/ext4/super.c
+++ linux-ec2-2.6.32/fs/ext4/super.c
@@ -39,6 +39,7 @@
 #include <linux/ctype.h>
 #include <linux/log2.h>
 #include <linux/crc16.h>
+#include <linux/precache.h>
 #include <asm/uaccess.h>
 
 #include "ext4.h"
@@ -227,6 +228,7 @@
 	if (sb->s_flags & MS_RDONLY)
 		return ERR_PTR(-EROFS);
 
+	vfs_check_frozen(sb, SB_FREEZE_TRANS);
 	/* Special case here: if the journal has aborted behind our
 	 * backs (eg. EIO in the commit thread), then we still need to
 	 * take the FS itself readonly cleanly. */
@@ -603,10 +605,6 @@
 	if (sb->s_dirt)
 		ext4_commit_super(sb, 1);
 
-	ext4_release_system_zone(sb);
-	ext4_mb_release(sb);
-	ext4_ext_release(sb);
-	ext4_xattr_put_super(sb);
 	if (sbi->s_journal) {
 		err = jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
@@ -614,6 +612,12 @@
 			ext4_abort(sb, __func__,
 				   "Couldn't clean up the journal");
 	}
+
+	ext4_release_system_zone(sb);
+	ext4_mb_release(sb);
+	ext4_ext_release(sb);
+	ext4_xattr_put_super(sb);
+
 	if (!(sb->s_flags & MS_RDONLY)) {
 		EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
@@ -700,10 +704,16 @@
 	ei->i_reserved_data_blocks = 0;
 	ei->i_reserved_meta_blocks = 0;
 	ei->i_allocated_meta_blocks = 0;
+	ei->i_da_metadata_calc_len = 0;
 	ei->i_delalloc_reserved_flag = 0;
 	spin_lock_init(&(ei->i_block_reservation_lock));
+#ifdef CONFIG_QUOTA
+	ei->i_reserved_quota = 0;
+#endif
 	INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
 	ei->cur_aio_dio = NULL;
+	ei->i_sync_tid = 0;
+	ei->i_datasync_tid = 0;
 
 	return &ei->vfs_inode;
 }
@@ -868,6 +878,8 @@
 	seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0");
 	if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
 		seq_puts(seq, ",journal_async_commit");
+	else if (test_opt(sb, JOURNAL_CHECKSUM))
+		seq_puts(seq, ",journal_checksum");
 	if (test_opt(sb, NOBH))
 		seq_puts(seq, ",nobh");
 	if (test_opt(sb, I_VERSION))
@@ -899,6 +911,12 @@
 	if (test_opt(sb, NO_AUTO_DA_ALLOC))
 		seq_puts(seq, ",noauto_da_alloc");
 
+	if (test_opt(sb, DISCARD))
+		seq_puts(seq, ",discard");
+
+	if (test_opt(sb, NOLOAD))
+		seq_puts(seq, ",norecovery");
+
 	ext4_show_quota_options(seq, sb);
 
 	return 0;
@@ -991,7 +1009,9 @@
 	.reserve_space	= dquot_reserve_space,
 	.claim_space	= dquot_claim_space,
 	.release_rsv	= dquot_release_reserved_space,
+#ifdef CONFIG_QUOTA
 	.get_reserved_space = ext4_get_reserved_space,
+#endif
 	.alloc_inode	= dquot_alloc_inode,
 	.free_space	= dquot_free_space,
 	.free_inode	= dquot_free_inode,
@@ -1079,7 +1099,8 @@
 	Opt_usrquota, Opt_grpquota, Opt_i_version,
 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
 	Opt_block_validity, Opt_noblock_validity,
-	Opt_inode_readahead_blks, Opt_journal_ioprio
+	Opt_inode_readahead_blks, Opt_journal_ioprio,
+	Opt_discard, Opt_nodiscard,
 };
 
 static const match_table_t tokens = {
@@ -1104,6 +1125,7 @@
 	{Opt_acl, "acl"},
 	{Opt_noacl, "noacl"},
 	{Opt_noload, "noload"},
+	{Opt_noload, "norecovery"},
 	{Opt_nobh, "nobh"},
 	{Opt_bh, "bh"},
 	{Opt_commit, "commit=%u"},
@@ -1144,6 +1166,8 @@
 	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
 	{Opt_auto_da_alloc, "auto_da_alloc"},
 	{Opt_noauto_da_alloc, "noauto_da_alloc"},
+	{Opt_discard, "discard"},
+	{Opt_nodiscard, "nodiscard"},
 	{Opt_err, NULL},
 };
 
@@ -1195,6 +1219,11 @@
 		if (!*p)
 			continue;
 
+		/*
+		 * Initialize args struct so we know whether arg was
+		 * found; some options take optional arguments.
+		 */
+		args[0].to = args[0].from = 0;
 		token = match_token(p, tokens, args);
 		switch (token) {
 		case Opt_bsd_df:
@@ -1480,10 +1509,11 @@
 			clear_opt(sbi->s_mount_opt, BARRIER);
 			break;
 		case Opt_barrier:
-			if (match_int(&args[0], &option)) {
-				set_opt(sbi->s_mount_opt, BARRIER);
-				break;
-			}
+			if (args[0].from) {
+				if (match_int(&args[0], &option))
+					return 0;
+			} else
+				option = 1;	/* No argument, default to 1 */
 			if (option)
 				set_opt(sbi->s_mount_opt, BARRIER);
 			else
@@ -1556,15 +1586,22 @@
 			set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
 			break;
 		case Opt_auto_da_alloc:
-			if (match_int(&args[0], &option)) {
-				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
-				break;
-			}
+			if (args[0].from) {
+				if (match_int(&args[0], &option))
+					return 0;
+			} else
+				option = 1;	/* No argument, default to 1 */
 			if (option)
 				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
 			else
 				set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
 			break;
+		case Opt_discard:
+			set_opt(sbi->s_mount_opt, DISCARD);
+			break;
+		case Opt_nodiscard:
+			clear_opt(sbi->s_mount_opt, DISCARD);
+			break;
 		default:
 			ext4_msg(sb, KERN_ERR,
 			       "Unrecognized mount option \"%s\" "
@@ -1660,6 +1697,8 @@
 			EXT4_INODES_PER_GROUP(sb),
 			sbi->s_mount_opt);
 
+	precache_init(sb);
+
 	return res;
 }
 
@@ -1673,14 +1712,14 @@
 	size_t size;
 	int i;
 
-	if (!sbi->s_es->s_log_groups_per_flex) {
+	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
+	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+
+	if (groups_per_flex < 2) {
 		sbi->s_log_groups_per_flex = 0;
 		return 1;
 	}
 
-	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
-	groups_per_flex = 1 << sbi->s_log_groups_per_flex;
-
 	/* We allocate both existing and potentially added groups */
 	flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
 			((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
@@ -2668,24 +2707,6 @@
 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	spin_lock_init(&sbi->s_next_gen_lock);
 
-	err = percpu_counter_init(&sbi->s_freeblocks_counter,
-			ext4_count_free_blocks(sb));
-	if (!err) {
-		err = percpu_counter_init(&sbi->s_freeinodes_counter,
-				ext4_count_free_inodes(sb));
-	}
-	if (!err) {
-		err = percpu_counter_init(&sbi->s_dirs_counter,
-				ext4_count_dirs(sb));
-	}
-	if (!err) {
-		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
-	}
-	if (err) {
-		ext4_msg(sb, KERN_ERR, "insufficient memory");
-		goto failed_mount3;
-	}
-
 	sbi->s_stripe = ext4_get_stripe_size(sbi);
 	sbi->s_max_writeback_mb_bump = 128;
 
@@ -2805,7 +2826,20 @@
 	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
 
 no_journal:
-
+	err = percpu_counter_init(&sbi->s_freeblocks_counter,
+				  ext4_count_free_blocks(sb));
+	if (!err)
+		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+					  ext4_count_free_inodes(sb));
+	if (!err)
+		err = percpu_counter_init(&sbi->s_dirs_counter,
+					  ext4_count_dirs(sb));
+	if (!err)
+		err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0);
+	if (err) {
+		ext4_msg(sb, KERN_ERR, "insufficient memory");
+		goto failed_mount_wq;
+	}
 	if (test_opt(sb, NOBH)) {
 		if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) {
 			ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - "
@@ -2880,7 +2914,7 @@
 	err = ext4_setup_system_zone(sb);
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to initialize system "
-			 "zone (%d)\n", err);
+			 "zone (%d)", err);
 		goto failed_mount4;
 	}
 
@@ -2938,6 +2972,10 @@
 		jbd2_journal_destroy(sbi->s_journal);
 		sbi->s_journal = NULL;
 	}
+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+	percpu_counter_destroy(&sbi->s_dirs_counter);
+	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
 failed_mount3:
 	if (sbi->s_flex_groups) {
 		if (is_vmalloc_addr(sbi->s_flex_groups))
@@ -2945,10 +2983,6 @@
 		else
 			kfree(sbi->s_flex_groups);
 	}
-	percpu_counter_destroy(&sbi->s_freeblocks_counter);
-	percpu_counter_destroy(&sbi->s_freeinodes_counter);
-	percpu_counter_destroy(&sbi->s_dirs_counter);
-	percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
 failed_mount2:
 	for (i = 0; i < db_count; i++)
 		brelse(sbi->s_group_desc[i]);
@@ -3365,8 +3399,10 @@
 		return 0;
 
 	journal = EXT4_SB(sb)->s_journal;
-	if (journal)
+	if (journal) {
+		vfs_check_frozen(sb, SB_FREEZE_TRANS);
 		ret = ext4_journal_force_commit(journal);
+	}
 
 	return ret;
 }
@@ -3415,18 +3451,16 @@
 	 * the journal.
 	 */
 	error = jbd2_journal_flush(journal);
-	if (error < 0) {
-	out:
-		jbd2_journal_unlock_updates(journal);
-		return error;
-	}
+	if (error < 0)
+		goto out;
 
 	/* Journal blocked and flushed, clear needs_recovery flag. */
 	EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 	error = ext4_commit_super(sb, 1);
-	if (error)
-		goto out;
-	return 0;
+out:
+	/* we rely on s_frozen to stop further updates */
+	jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+	return error;
 }
 
 /*
@@ -3443,7 +3477,6 @@
 	EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
 	ext4_commit_super(sb, 1);
 	unlock_super(sb);
-	jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
 	return 0;
 }
 
@@ -3668,13 +3701,11 @@
 	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
 		       percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
-	ext4_free_blocks_count_set(es, buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 	if (buf->f_bfree < ext4_r_blocks_count(es))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
-	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT4_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
@@ -3978,6 +4009,7 @@
 {
 	int err;
 
+	ext4_check_flag_values();
 	err = init_ext4_system_zone();
 	if (err)
 		return err;
--- linux-ec2-2.6.32.orig/fs/ext4/xattr.c
+++ linux-ec2-2.6.32/fs/ext4/xattr.c
@@ -267,7 +267,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
 		return -ENODATA;
 	error = ext4_get_inode_loc(inode, &iloc);
 	if (error)
@@ -393,7 +393,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
 		return 0;
 	error = ext4_get_inode_loc(inode, &iloc);
 	if (error)
@@ -816,7 +816,7 @@
 						EXT4_I(inode)->i_block_group);
 
 			/* non-extent files can't have physical blocks past 2^32 */
-			if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 				goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
 
 			block = ext4_new_meta_blocks(handle, inode,
@@ -824,7 +824,7 @@
 			if (error)
 				goto cleanup;
 
-			if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+			if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 				BUG_ON(block > EXT4_MAX_BLOCK_FILE_PHYS);
 
 			ea_idebug(inode, "creating block %d", block);
@@ -903,7 +903,7 @@
 	is->s.base = is->s.first = IFIRST(header);
 	is->s.here = is->s.first;
 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
 		error = ext4_xattr_check_names(IFIRST(header), is->s.end);
 		if (error)
 			return error;
@@ -935,10 +935,10 @@
 	header = IHDR(inode, ext4_raw_inode(&is->iloc));
 	if (!IS_LAST_ENTRY(s->first)) {
 		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
-		EXT4_I(inode)->i_state |= EXT4_STATE_XATTR;
+		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
 	} else {
 		header->h_magic = cpu_to_le32(0);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR;
+		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
 	}
 	return 0;
 }
@@ -981,17 +981,21 @@
 	if (strlen(name) > 255)
 		return -ERANGE;
 	down_write(&EXT4_I(inode)->xattr_sem);
-	no_expand = EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND;
-	EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
+	no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
+	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
 
 	error = ext4_get_inode_loc(inode, &is.iloc);
 	if (error)
 		goto cleanup;
 
-	if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) {
+	error = ext4_journal_get_write_access(handle, is.iloc.bh);
+	if (error)
+		goto cleanup;
+
+	if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
 		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW;
+		ext4_clear_inode_state(inode, EXT4_STATE_NEW);
 	}
 
 	error = ext4_xattr_ibody_find(inode, &i, &is);
@@ -1013,9 +1017,6 @@
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 	}
-	error = ext4_journal_get_write_access(handle, is.iloc.bh);
-	if (error)
-		goto cleanup;
 	if (!value) {
 		if (!is.s.not_found)
 			error = ext4_xattr_ibody_set(handle, inode, &i, &is);
@@ -1046,7 +1047,7 @@
 		ext4_xattr_update_super_block(handle, inode->i_sb);
 		inode->i_ctime = ext4_current_time(inode);
 		if (!value)
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
+			ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
 		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
 		/*
 		 * The bh is consumed by ext4_mark_iloc_dirty, even with
@@ -1061,7 +1062,7 @@
 	brelse(is.iloc.bh);
 	brelse(bs.bh);
 	if (no_expand == 0)
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
+		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
 	up_write(&EXT4_I(inode)->xattr_sem);
 	return error;
 }
@@ -1326,6 +1327,8 @@
 			goto cleanup;
 		kfree(b_entry_name);
 		kfree(buffer);
+		b_entry_name = NULL;
+		buffer = NULL;
 		brelse(is->iloc.bh);
 		kfree(is);
 		kfree(bs);
--- linux-ec2-2.6.32.orig/fs/ext4/ext4_jbd2.h
+++ linux-ec2-2.6.32/fs/ext4/ext4_jbd2.h
@@ -49,7 +49,7 @@
 
 #define EXT4_DATA_TRANS_BLOCKS(sb)	(EXT4_SINGLEDATA_TRANS_BLOCKS(sb) + \
 					 EXT4_XATTR_TRANS_BLOCKS - 2 + \
-					 2*EXT4_QUOTA_TRANS_BLOCKS(sb))
+					 EXT4_MAXQUOTAS_TRANS_BLOCKS(sb))
 
 /*
  * Define the number of metadata blocks we need to account to modify data.
@@ -57,7 +57,7 @@
  * This include super block, inode block, quota blocks and xattr blocks
  */
 #define EXT4_META_TRANS_BLOCKS(sb)	(EXT4_XATTR_TRANS_BLOCKS + \
-					2*EXT4_QUOTA_TRANS_BLOCKS(sb))
+					EXT4_MAXQUOTAS_TRANS_BLOCKS(sb))
 
 /* Delete operations potentially hit one directory's namespace plus an
  * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
@@ -92,6 +92,7 @@
  * but inode, sb and group updates are done only once */
 #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
 		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0)
+
 #define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
 		(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0)
 #else
@@ -99,6 +100,9 @@
 #define EXT4_QUOTA_INIT_BLOCKS(sb) 0
 #define EXT4_QUOTA_DEL_BLOCKS(sb) 0
 #endif
+#define EXT4_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_TRANS_BLOCKS(sb))
+#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
+#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
 
 int
 ext4_mark_iloc_dirty(handle_t *handle,
@@ -254,6 +258,19 @@
 	return 0;
 }
 
+static inline void ext4_update_inode_fsync_trans(handle_t *handle,
+						 struct inode *inode,
+						 int datasync)
+{
+	struct ext4_inode_info *ei = EXT4_I(inode);
+
+	if (ext4_handle_valid(handle)) {
+		ei->i_sync_tid = handle->h_transaction->t_tid;
+		if (datasync)
+			ei->i_datasync_tid = handle->h_transaction->t_tid;
+	}
+}
+
 /* super.c */
 int ext4_force_commit(struct super_block *sb);
 
@@ -265,7 +282,7 @@
 		return 1;
 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
 		return 1;
-	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
 		return 1;
 	return 0;
 }
@@ -276,7 +293,7 @@
 		return 0;
 	if (!S_ISREG(inode->i_mode))
 		return 0;
-	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
 		return 0;
 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
 		return 1;
@@ -289,7 +306,7 @@
 		return 0;
 	if (EXT4_JOURNAL(inode) == NULL)
 		return 1;
-	if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
+	if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
 		return 0;
 	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
 		return 1;
--- linux-ec2-2.6.32.orig/fs/ext4/dir.c
+++ linux-ec2-2.6.32/fs/ext4/dir.c
@@ -84,9 +84,11 @@
 
 	if (error_msg != NULL)
 		ext4_error(dir->i_sb, function,
-			"bad entry in directory #%lu: %s - "
-			"offset=%u, inode=%u, rec_len=%d, name_len=%d",
-			dir->i_ino, error_msg, offset,
+			"bad entry in directory #%lu: %s - block=%llu"
+			"offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+			dir->i_ino, error_msg,
+			(unsigned long long) bh->b_blocknr,
+			(unsigned) (offset%bh->b_size), offset,
 			le32_to_cpu(de->inode),
 			rlen, de->name_len);
 	return error_msg == NULL ? 1 : 0;
@@ -109,7 +111,7 @@
 
 	if (EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
 				    EXT4_FEATURE_COMPAT_DIR_INDEX) &&
-	    ((EXT4_I(inode)->i_flags & EXT4_INDEX_FL) ||
+	    ((ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) ||
 	     ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
 		err = ext4_dx_readdir(filp, dirent, filldir);
 		if (err != ERR_BAD_DX_DIR) {
@@ -120,7 +122,7 @@
 		 * We don't set the inode dirty flag since it's not
 		 * critical that it get flushed back to the disk.
 		 */
-		EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+		ext4_clear_inode_flag(filp->f_path.dentry->d_inode, EXT4_INODE_INDEX);
 	}
 	stored = 0;
 	offset = filp->f_pos & (sb->s_blocksize - 1);
--- linux-ec2-2.6.32.orig/fs/ext4/ialloc.c
+++ linux-ec2-2.6.32/fs/ext4/ialloc.c
@@ -244,57 +244,50 @@
 	if (fatal)
 		goto error_return;
 
-	/* Ok, now we can actually update the inode bitmaps.. */
-	cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
-					bit, bitmap_bh->b_data);
-	if (!cleared)
-		ext4_error(sb, "ext4_free_inode",
-			   "bit already cleared for inode %lu", ino);
-	else {
-		gdp = ext4_get_group_desc(sb, block_group, &bh2);
-
+	fatal = -ESRCH;
+	gdp = ext4_get_group_desc(sb, block_group, &bh2);
+	if (gdp) {
 		BUFFER_TRACE(bh2, "get_write_access");
 		fatal = ext4_journal_get_write_access(handle, bh2);
-		if (fatal) goto error_return;
+	}
+	ext4_lock_group(sb, block_group);
+	cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
+	if (fatal || !cleared) {
+		ext4_unlock_group(sb, block_group);
+		goto out;
+	}
 
-		if (gdp) {
-			ext4_lock_group(sb, block_group);
-			count = ext4_free_inodes_count(sb, gdp) + 1;
-			ext4_free_inodes_set(sb, gdp, count);
-			if (is_directory) {
-				count = ext4_used_dirs_count(sb, gdp) - 1;
-				ext4_used_dirs_set(sb, gdp, count);
-				if (sbi->s_log_groups_per_flex) {
-					ext4_group_t f;
-
-					f = ext4_flex_group(sbi, block_group);
-					atomic_dec(&sbi->s_flex_groups[f].free_inodes);
-				}
+	count = ext4_free_inodes_count(sb, gdp) + 1;
+	ext4_free_inodes_set(sb, gdp, count);
+	if (is_directory) {
+		count = ext4_used_dirs_count(sb, gdp) - 1;
+		ext4_used_dirs_set(sb, gdp, count);
+		percpu_counter_dec(&sbi->s_dirs_counter);
+	}
+	gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
+	ext4_unlock_group(sb, block_group);
 
-			}
-			gdp->bg_checksum = ext4_group_desc_csum(sbi,
-							block_group, gdp);
-			ext4_unlock_group(sb, block_group);
-			percpu_counter_inc(&sbi->s_freeinodes_counter);
-			if (is_directory)
-				percpu_counter_dec(&sbi->s_dirs_counter);
+	percpu_counter_inc(&sbi->s_freeinodes_counter);
+	if (sbi->s_log_groups_per_flex) {
+		ext4_group_t f = ext4_flex_group(sbi, block_group);
 
-			if (sbi->s_log_groups_per_flex) {
-				ext4_group_t f;
+		atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+		if (is_directory)
+			atomic_dec(&sbi->s_flex_groups[f].used_dirs);
+	}
+	BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
+	fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
+out:
+	if (cleared) {
+		BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
+		err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
+		if (!fatal)
+			fatal = err;
+		sb->s_dirt = 1;
+	} else
+		ext4_error(sb, "ext4_free_inode",
+			   "bit already cleared for inode %lu", ino);
 
-				f = ext4_flex_group(sbi, block_group);
-				atomic_inc(&sbi->s_flex_groups[f].free_inodes);
-			}
-		}
-		BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
-		err = ext4_handle_dirty_metadata(handle, NULL, bh2);
-		if (!fatal) fatal = err;
-	}
-	BUFFER_TRACE(bitmap_bh, "call ext4_handle_dirty_metadata");
-	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
-	if (!fatal)
-		fatal = err;
-	sb->s_dirt = 1;
 error_return:
 	brelse(bitmap_bh);
 	ext4_std_error(sb, fatal);
@@ -504,7 +497,7 @@
 
 	if (S_ISDIR(mode) &&
 	    ((parent == sb->s_root->d_inode) ||
-	     (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL))) {
+	     (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) {
 		int best_ndir = inodes_per_group;
 		int ret = -1;
 
@@ -779,7 +772,7 @@
 		if (sbi->s_log_groups_per_flex) {
 			ext4_group_t f = ext4_flex_group(sbi, group);
 
-			atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+			atomic_inc(&sbi->s_flex_groups[f].used_dirs);
 		}
 	}
 	gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
@@ -904,7 +897,7 @@
 				BUFFER_TRACE(inode_bitmap_bh,
 					"call ext4_handle_dirty_metadata");
 				err = ext4_handle_dirty_metadata(handle,
-								 inode,
+								 NULL,
 							inode_bitmap_bh);
 				if (err)
 					goto fail;
@@ -1029,7 +1022,8 @@
 	inode->i_generation = sbi->s_next_generation++;
 	spin_unlock(&sbi->s_next_gen_lock);
 
-	ei->i_state = EXT4_STATE_NEW;
+	ei->i_state_flags = 0;
+	ext4_set_inode_state(inode, EXT4_STATE_NEW);
 
 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
 
@@ -1050,7 +1044,7 @@
 	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
 		/* set extent flag only for directory, file and normal symlink*/
 		if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
-			EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
+			ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
 			ext4_ext_tree_init(handle, inode);
 		}
 	}
--- linux-ec2-2.6.32.orig/fs/ext4/namei.c
+++ linux-ec2-2.6.32/fs/ext4/namei.c
@@ -660,7 +660,7 @@
 	dxtrace(printk(KERN_DEBUG "In htree_fill_tree, start hash: %x:%x\n", 
 		       start_hash, start_minor_hash));
 	dir = dir_file->f_path.dentry->d_inode;
-	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+	if (!(ext4_test_inode_flag(dir, EXT4_INODE_INDEX))) {
 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
 		if (hinfo.hash_version <= DX_HASH_TEA)
 			hinfo.hash_version +=
@@ -805,7 +805,7 @@
 {
 	if (!EXT4_HAS_COMPAT_FEATURE(inode->i_sb,
 				     EXT4_FEATURE_COMPAT_DIR_INDEX))
-		EXT4_I(inode)->i_flags &= ~EXT4_INDEX_FL;
+		ext4_clear_inode_flag(inode, EXT4_INODE_INDEX);
 }
 
 /*
@@ -1292,9 +1292,6 @@
  * add_dirent_to_buf will attempt search the directory block for
  * space.  It will return -ENOSPC if no space is available, and -EIO
  * and -EEXIST if directory entry already exists.
- *
- * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
- * all other cases bh is released.
  */
 static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 			     struct inode *inode, struct ext4_dir_entry_2 *de,
@@ -1315,14 +1312,10 @@
 		top = bh->b_data + blocksize - reclen;
 		while ((char *) de <= top) {
 			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
-						  bh, offset)) {
-				brelse(bh);
+						  bh, offset))
 				return -EIO;
-			}
-			if (ext4_match(namelen, name, de)) {
-				brelse(bh);
+			if (ext4_match(namelen, name, de))
 				return -EEXIST;
-			}
 			nlen = EXT4_DIR_REC_LEN(de->name_len);
 			rlen = ext4_rec_len_from_disk(de->rec_len, blocksize);
 			if ((de->inode? rlen - nlen: rlen) >= reclen)
@@ -1337,7 +1330,6 @@
 	err = ext4_journal_get_write_access(handle, bh);
 	if (err) {
 		ext4_std_error(dir->i_sb, err);
-		brelse(bh);
 		return err;
 	}
 
@@ -1377,7 +1369,6 @@
 	err = ext4_handle_dirty_metadata(handle, dir, bh);
 	if (err)
 		ext4_std_error(dir->i_sb, err);
-	brelse(bh);
 	return 0;
 }
 
@@ -1433,7 +1424,7 @@
 		brelse(bh);
 		return retval;
 	}
-	EXT4_I(dir)->i_flags |= EXT4_INDEX_FL;
+	ext4_set_inode_flag(dir, EXT4_INODE_INDEX);
 	data1 = bh2->b_data;
 
 	memcpy (data1, de, len);
@@ -1471,7 +1462,9 @@
 	if (!(de))
 		return retval;
 
-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+	brelse(bh);
+	return retval;
 }
 
 /*
@@ -1504,7 +1497,7 @@
 		retval = ext4_dx_add_entry(handle, dentry, inode);
 		if (!retval || (retval != ERR_BAD_DX_DIR))
 			return retval;
-		EXT4_I(dir)->i_flags &= ~EXT4_INDEX_FL;
+		ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
 		dx_fallback++;
 		ext4_mark_inode_dirty(handle, dir);
 	}
@@ -1514,8 +1507,10 @@
 		if(!bh)
 			return retval;
 		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-		if (retval != -ENOSPC)
+		if (retval != -ENOSPC) {
+			brelse(bh);
 			return retval;
+		}
 
 		if (blocks == 1 && !dx_fallback &&
 		    EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
@@ -1528,7 +1523,11 @@
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
 	de->inode = 0;
 	de->rec_len = ext4_rec_len_to_disk(blocksize, blocksize);
-	return add_dirent_to_buf(handle, dentry, inode, de, bh);
+	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+	brelse(bh);
+	if (retval == 0)
+		ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
+	return retval;
 }
 
 /*
@@ -1561,10 +1560,8 @@
 		goto journal_error;
 
 	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-	if (err != -ENOSPC) {
-		bh = NULL;
+	if (err != -ENOSPC)
 		goto cleanup;
-	}
 
 	/* Block full, should compress but for now just split */
 	dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
@@ -1657,7 +1654,6 @@
 	if (!de)
 		goto cleanup;
 	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-	bh = NULL;
 	goto cleanup;
 
 journal_error:
@@ -1775,7 +1771,7 @@
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -1809,7 +1805,7 @@
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -1846,7 +1842,7 @@
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -2026,11 +2022,18 @@
 	err = ext4_reserve_inode_write(handle, inode, &iloc);
 	if (err)
 		goto out_unlock;
+	/*
+	 * Due to previous errors inode may be already a part of on-disk
+	 * orphan list. If so skip on-disk list modification.
+	 */
+	if (NEXT_ORPHAN(inode) && NEXT_ORPHAN(inode) <=
+		(le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)))
+			goto mem_insert;
 
 	/* Insert this inode at the head of the on-disk orphan list... */
 	NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan);
 	EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
-	err = ext4_handle_dirty_metadata(handle, inode, EXT4_SB(sb)->s_sbh);
+	err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
 	rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
 	if (!err)
 		err = rc;
@@ -2043,6 +2046,7 @@
 	 *
 	 * This is safe: on error we're going to ignore the orphan list
 	 * anyway on the next recovery. */
+mem_insert:
 	if (!err)
 		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
 
@@ -2102,7 +2106,7 @@
 		if (err)
 			goto out_brelse;
 		sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
-		err = ext4_handle_dirty_metadata(handle, inode, sbi->s_sbh);
+		err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
 	} else {
 		struct ext4_iloc iloc2;
 		struct inode *i_prev =
@@ -2259,7 +2263,7 @@
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-					2*EXT4_QUOTA_INIT_BLOCKS(dir->i_sb));
+					EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -2290,7 +2294,7 @@
 		}
 	} else {
 		/* clear the extent format for fast symlink */
-		EXT4_I(inode)->i_flags &= ~EXT4_EXTENTS_FL;
+		ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
 		inode->i_op = &ext4_fast_symlink_inode_operations;
 		memcpy((char *)&EXT4_I(inode)->i_data, symname, l);
 		inode->i_size = l-1;
--- linux-ec2-2.6.32.orig/fs/ext4/mballoc.c
+++ linux-ec2-2.6.32/fs/ext4/mballoc.c
@@ -658,6 +658,27 @@
 	}
 }
 
+/*
+ * Cache the order of the largest free extent we have available in this block
+ * group.
+ */
+static void
+mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
+{
+	int i;
+	int bits;
+
+	grp->bb_largest_free_order = -1; /* uninit */
+
+	bits = sb->s_blocksize_bits + 1;
+	for (i = bits; i >= 0; i--) {
+		if (grp->bb_counters[i] > 0) {
+			grp->bb_largest_free_order = i;
+			break;
+		}
+	}
+}
+
 static noinline_for_stack
 void ext4_mb_generate_buddy(struct super_block *sb,
 				void *buddy, void *bitmap, ext4_group_t group)
@@ -700,6 +721,7 @@
 		 */
 		grp->bb_free = free;
 	}
+	mb_set_largest_free_order(sb, grp);
 
 	clear_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state));
 
@@ -725,6 +747,9 @@
  * contain blocks_per_page (PAGE_CACHE_SIZE / blocksize)  blocks.
  * So it can have information regarding groups_per_page which
  * is blocks_per_page/2
+ *
+ * Locking note:  This routine takes the block group lock of all groups
+ * for this page; do not hold this lock when calling this routine!
  */
 
 static int ext4_mb_init_cache(struct page *page, char *incore)
@@ -910,6 +935,11 @@
 	return err;
 }
 
+/*
+ * Locking note:  This routine calls ext4_mb_init_cache(), which takes the
+ * block group lock of all groups for this page; do not hold the BG lock when
+ * calling this routine!
+ */
 static noinline_for_stack
 int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
 {
@@ -1004,6 +1034,11 @@
 	return ret;
 }
 
+/*
+ * Locking note:  This routine calls ext4_mb_init_cache(), which takes the
+ * block group lock of all groups for this page; do not hold the BG lock when
+ * calling this routine!
+ */
 static noinline_for_stack int
 ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
 					struct ext4_buddy *e4b)
@@ -1150,7 +1185,7 @@
 	return ret;
 }
 
-static void ext4_mb_release_desc(struct ext4_buddy *e4b)
+static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
 {
 	if (e4b->bd_bitmap_page)
 		page_cache_release(e4b->bd_bitmap_page);
@@ -1300,6 +1335,7 @@
 			buddy = buddy2;
 		} while (1);
 	}
+	mb_set_largest_free_order(sb, e4b->bd_info);
 	mb_check_buddy(e4b);
 }
 
@@ -1428,6 +1464,7 @@
 		e4b->bd_info->bb_counters[ord]++;
 		e4b->bd_info->bb_counters[ord]++;
 	}
+	mb_set_largest_free_order(e4b->bd_sb, e4b->bd_info);
 
 	mb_set_bits(EXT4_MB_BITMAP(e4b), ex->fe_start, len0);
 	mb_check_buddy(e4b);
@@ -1618,7 +1655,7 @@
 	}
 
 	ext4_unlock_group(ac->ac_sb, group);
-	ext4_mb_release_desc(e4b);
+	ext4_mb_unload_buddy(e4b);
 
 	return 0;
 }
@@ -1674,7 +1711,7 @@
 		ext4_mb_use_best_found(ac, e4b);
 	}
 	ext4_unlock_group(ac->ac_sb, group);
-	ext4_mb_release_desc(e4b);
+	ext4_mb_unload_buddy(e4b);
 
 	return 0;
 }
@@ -1823,16 +1860,22 @@
 	}
 }
 
+/* This is now called BEFORE we load the buddy bitmap. */
 static int ext4_mb_good_group(struct ext4_allocation_context *ac,
 				ext4_group_t group, int cr)
 {
 	unsigned free, fragments;
-	unsigned i, bits;
 	int flex_size = ext4_flex_bg_size(EXT4_SB(ac->ac_sb));
 	struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
 
 	BUG_ON(cr < 0 || cr >= 4);
-	BUG_ON(EXT4_MB_GRP_NEED_INIT(grp));
+
+	/* We only do this if the grp has never been initialized */
+	if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
+		int ret = ext4_mb_init_group(ac->ac_sb, group);
+		if (ret)
+			return 0;
+	}
 
 	free = grp->bb_free;
 	fragments = grp->bb_fragments;
@@ -1845,17 +1888,16 @@
 	case 0:
 		BUG_ON(ac->ac_2order == 0);
 
+		if (grp->bb_largest_free_order < ac->ac_2order)
+			return 0;
+
 		/* Avoid using the first bg of a flexgroup for data files */
 		if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
 		    (flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) &&
 		    ((group % flex_size) == 0))
 			return 0;
 
-		bits = ac->ac_sb->s_blocksize_bits + 1;
-		for (i = ac->ac_2order; i <= bits; i++)
-			if (grp->bb_counters[i] > 0)
-				return 1;
-		break;
+		return 1;
 	case 1:
 		if ((free / fragments) >= ac->ac_g_ex.fe_len)
 			return 1;
@@ -1966,7 +2008,7 @@
 	sbi = EXT4_SB(sb);
 	ngroups = ext4_get_groups_count(sb);
 	/* non-extent files are limited to low blocks/groups */
-	if (!(EXT4_I(ac->ac_inode)->i_flags & EXT4_EXTENTS_FL))
+	if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)))
 		ngroups = sbi->s_blockfile_groups;
 
 	BUG_ON(ac->ac_status == AC_STATUS_FOUND);
@@ -2026,15 +2068,11 @@
 		group = ac->ac_g_ex.fe_group;
 
 		for (i = 0; i < ngroups; group++, i++) {
-			struct ext4_group_info *grp;
-			struct ext4_group_desc *desc;
-
 			if (group == ngroups)
 				group = 0;
 
-			/* quick check to skip empty groups */
-			grp = ext4_get_group_info(sb, group);
-			if (grp->bb_free == 0)
+			/* This now checks without needing the buddy page */
+			if (!ext4_mb_good_group(ac, group, cr))
 				continue;
 
 			err = ext4_mb_load_buddy(sb, group, &e4b);
@@ -2042,15 +2080,18 @@
 				goto out;
 
 			ext4_lock_group(sb, group);
+
+			/*
+			 * We need to check again after locking the
+			 * block group
+			 */
 			if (!ext4_mb_good_group(ac, group, cr)) {
-				/* someone did allocation from this group */
 				ext4_unlock_group(sb, group);
-				ext4_mb_release_desc(&e4b);
+				ext4_mb_unload_buddy(&e4b);
 				continue;
 			}
 
 			ac->ac_groups_scanned++;
-			desc = ext4_get_group_desc(sb, group, NULL);
 			if (cr == 0)
 				ext4_mb_simple_scan_group(ac, &e4b);
 			else if (cr == 1 &&
@@ -2060,7 +2101,7 @@
 				ext4_mb_complex_scan_group(ac, &e4b);
 
 			ext4_unlock_group(sb, group);
-			ext4_mb_release_desc(&e4b);
+			ext4_mb_unload_buddy(&e4b);
 
 			if (ac->ac_status != AC_STATUS_CONTINUE)
 				break;
@@ -2150,7 +2191,7 @@
 	ext4_lock_group(sb, group);
 	memcpy(&sg, ext4_get_group_info(sb, group), i);
 	ext4_unlock_group(sb, group);
-	ext4_mb_release_desc(&e4b);
+	ext4_mb_unload_buddy(&e4b);
 
 	seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
 			sg.info.bb_fragments, sg.info.bb_first_free);
@@ -2257,6 +2298,7 @@
 	INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
 	init_rwsem(&meta_group_info[i]->alloc_sem);
 	meta_group_info[i]->bb_free_root.rb_node = NULL;
+	meta_group_info[i]->bb_largest_free_order = -1;  /* uninit */
 
 #ifdef DOUBLE_CHECK
 	{
@@ -2529,7 +2571,6 @@
 	struct ext4_group_info *db;
 	int err, count = 0, count2 = 0;
 	struct ext4_free_data *entry;
-	ext4_fsblk_t discard_block;
 	struct list_head *l, *ltmp;
 
 	list_for_each_safe(l, ltmp, &txn->t_private_list) {
@@ -2538,6 +2579,23 @@
 		mb_debug(1, "gonna free %u blocks in group %u (0x%p):",
 			 entry->count, entry->group, entry);
 
+		if (test_opt(sb, DISCARD)) {
+			int ret;
+			ext4_fsblk_t discard_block;
+
+			discard_block = entry->start_blk +
+				ext4_group_first_block_no(sb, entry->group);
+			trace_ext4_discard_blocks(sb,
+					(unsigned long long)discard_block,
+					entry->count);
+			ret = sb_issue_discard(sb, discard_block, entry->count);
+			if (ret == EOPNOTSUPP) {
+				ext4_warning(sb, __func__,
+					"discard not supported, disabling");
+				clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD);
+			}
+		}
+
 		err = ext4_mb_load_buddy(sb, entry->group, &e4b);
 		/* we expect to find existing buddy because it's pinned */
 		BUG_ON(err != 0);
@@ -2559,15 +2617,8 @@
 			page_cache_release(e4b.bd_bitmap_page);
 		}
 		ext4_unlock_group(sb, entry->group);
-		discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb)
-			+ entry->start_blk
-			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
-		trace_ext4_discard_blocks(sb, (unsigned long long)discard_block,
-					  entry->count);
-		sb_issue_discard(sb, discard_block, entry->count);
-
 		kmem_cache_free(ext4_free_ext_cachep, entry);
-		ext4_mb_release_desc(&e4b);
+		ext4_mb_unload_buddy(&e4b);
 	}
 
 	mb_debug(1, "freed %u blocks in %u structures\n", count, count2);
@@ -2750,12 +2801,6 @@
 	if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
 		/* release all the reserved blocks if non delalloc */
 		percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
-	else {
-		percpu_counter_sub(&sbi->s_dirtyblocks_counter,
-						ac->ac_b_ex.fe_len);
-		/* convert reserved quota blocks to real quota blocks */
-		vfs_dq_claim_block(ac->ac_inode, ac->ac_b_ex.fe_len);
-	}
 
 	if (sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group = ext4_flex_group(sbi,
@@ -3006,6 +3051,24 @@
 }
 
 /*
+ * Called on failure; free up any blocks from the inode PA for this
+ * context.  We don't need this for MB_GROUP_PA because we only change
+ * pa_free in ext4_mb_release_context(), but on failure, we've already
+ * zeroed out ac->ac_b_ex.fe_len, so group_pa->pa_free is not changed.
+ */
+static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+{
+	struct ext4_prealloc_space *pa = ac->ac_pa;
+	int len;
+
+	if (pa && pa->pa_type == MB_INODE_PA) {
+		len = ac->ac_b_ex.fe_len;
+		pa->pa_free += len;
+	}
+
+}
+
+/*
  * use blocks preallocated to inode
  */
 static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
@@ -3113,7 +3176,7 @@
 			continue;
 
 		/* non-extent files can't have physical blocks past 2^32 */
-		if (!(EXT4_I(ac->ac_inode)->i_flags & EXT4_EXTENTS_FL) &&
+		if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
 			pa->pa_pstart + pa->pa_len > EXT4_MAX_BLOCK_FILE_PHYS)
 			continue;
 
@@ -3692,7 +3755,7 @@
 	ext4_unlock_group(sb, group);
 	if (ac)
 		kmem_cache_free(ext4_ac_cachep, ac);
-	ext4_mb_release_desc(&e4b);
+	ext4_mb_unload_buddy(&e4b);
 	put_bh(bitmap_bh);
 	return free;
 }
@@ -3796,7 +3859,7 @@
 		if (bitmap_bh == NULL) {
 			ext4_error(sb, __func__, "Error in reading block "
 					"bitmap for %u", group);
-			ext4_mb_release_desc(&e4b);
+			ext4_mb_unload_buddy(&e4b);
 			continue;
 		}
 
@@ -3805,7 +3868,7 @@
 		ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac);
 		ext4_unlock_group(sb, group);
 
-		ext4_mb_release_desc(&e4b);
+		ext4_mb_unload_buddy(&e4b);
 		put_bh(bitmap_bh);
 
 		list_del(&pa->u.pa_tmp_list);
@@ -3921,7 +3984,7 @@
 
 	/* don't use group allocation for large files */
 	size = max(size, isize);
-	if (size >= sbi->s_mb_stream_request) {
+	if (size > sbi->s_mb_stream_request) {
 		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
 		return;
 	}
@@ -4069,7 +4132,7 @@
 		ext4_mb_release_group_pa(&e4b, pa, ac);
 		ext4_unlock_group(sb, group);
 
-		ext4_mb_release_desc(&e4b);
+		ext4_mb_unload_buddy(&e4b);
 		list_del(&pa->u.pa_tmp_list);
 		call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
 	}
@@ -4290,6 +4353,7 @@
 			ac->ac_status = AC_STATUS_CONTINUE;
 			goto repeat;
 		} else if (*errp) {
+			ext4_discard_allocated_blocks(ac);
 			ac->ac_b_ex.fe_len = 0;
 			ar->len = 0;
 			ext4_mb_show_ac(ac);
@@ -4570,7 +4634,7 @@
 		atomic_add(count, &sbi->s_flex_groups[flex_group].free_blocks);
 	}
 
-	ext4_mb_release_desc(&e4b);
+	ext4_mb_unload_buddy(&e4b);
 
 	*freed += count;
 
--- linux-ec2-2.6.32.orig/fs/ext4/block_validity.c
+++ linux-ec2-2.6.32/fs/ext4/block_validity.c
@@ -160,7 +160,7 @@
 		if (ext4_bg_has_super(sb, i) &&
 		    ((i < 5) || ((i % flex_size) == 0)))
 			add_system_zone(sbi, ext4_group_first_block_no(sb, i),
-					sbi->s_gdb_count + 1);
+					ext4_bg_num_gdb(sb, i) + 1);
 		gdp = ext4_get_group_desc(sb, i, NULL);
 		ret = add_system_zone(sbi, ext4_block_bitmap(sb, gdp), 1);
 		if (ret)
--- linux-ec2-2.6.32.orig/fs/ext4/ext4_extents.h
+++ linux-ec2-2.6.32/fs/ext4/ext4_extents.h
@@ -225,7 +225,8 @@
 	ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
 }
 
-extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
+extern int ext4_ext_calc_metadata_amount(struct inode *inode,
+					 sector_t lblocks);
 extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
 extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
 extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
--- linux-ec2-2.6.32.orig/fs/ext4/resize.c
+++ linux-ec2-2.6.32/fs/ext4/resize.c
@@ -247,7 +247,7 @@
 			goto exit_bh;
 
 		if (IS_ERR(gdb = bclean(handle, sb, block))) {
-			err = PTR_ERR(bh);
+			err = PTR_ERR(gdb);
 			goto exit_bh;
 		}
 		ext4_handle_dirty_metadata(handle, NULL, gdb);
@@ -930,7 +930,8 @@
 	percpu_counter_add(&sbi->s_freeinodes_counter,
 			   EXT4_INODES_PER_GROUP(sb));
 
-	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+	    sbi->s_log_groups_per_flex) {
 		ext4_group_t flex_group;
 		flex_group = ext4_flex_group(sbi, input->group);
 		atomic_add(input->free_blocks_count,
--- linux-ec2-2.6.32.orig/fs/ext4/move_extent.c
+++ linux-ec2-2.6.32/fs/ext4/move_extent.c
@@ -77,12 +77,14 @@
 mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
 		      struct ext4_extent **extent)
 {
+	struct ext4_extent_header *eh;
 	int ppos, leaf_ppos = path->p_depth;
 
 	ppos = leaf_ppos;
 	if (EXT_LAST_EXTENT(path[ppos].p_hdr) > path[ppos].p_ext) {
 		/* leaf block */
 		*extent = ++path[ppos].p_ext;
+		path[ppos].p_block = ext_pblock(path[ppos].p_ext);
 		return 0;
 	}
 
@@ -119,9 +121,18 @@
 					ext_block_hdr(path[cur_ppos+1].p_bh);
 			}
 
+			path[leaf_ppos].p_ext = *extent = NULL;
+
+			eh = path[leaf_ppos].p_hdr;
+			if (le16_to_cpu(eh->eh_entries) == 0)
+				/* empty leaf is found */
+				return -ENODATA;
+
 			/* leaf block */
 			path[leaf_ppos].p_ext = *extent =
 				EXT_FIRST_EXTENT(path[leaf_ppos].p_hdr);
+			path[leaf_ppos].p_block =
+					ext_pblock(path[leaf_ppos].p_ext);
 			return 0;
 		}
 	}
@@ -155,40 +166,15 @@
 }
 
 /**
- * mext_double_down_read - Acquire two inodes' read semaphore
+ * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem
  *
  * @orig_inode:		original inode structure
  * @donor_inode:	donor inode structure
- * Acquire read semaphore of the two inodes (orig and donor) by i_ino order.
+ * Acquire write lock of i_data_sem of the two inodes (orig and donor) by
+ * i_ino order.
  */
 static void
-mext_double_down_read(struct inode *orig_inode, struct inode *donor_inode)
-{
-	struct inode *first = orig_inode, *second = donor_inode;
-
-	/*
-	 * Use the inode number to provide the stable locking order instead
-	 * of its address, because the C language doesn't guarantee you can
-	 * compare pointers that don't come from the same array.
-	 */
-	if (donor_inode->i_ino < orig_inode->i_ino) {
-		first = donor_inode;
-		second = orig_inode;
-	}
-
-	down_read(&EXT4_I(first)->i_data_sem);
-	down_read(&EXT4_I(second)->i_data_sem);
-}
-
-/**
- * mext_double_down_write - Acquire two inodes' write semaphore
- *
- * @orig_inode:		original inode structure
- * @donor_inode:	donor inode structure
- * Acquire write semaphore of the two inodes (orig and donor) by i_ino order.
- */
-static void
-mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode)
+double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode)
 {
 	struct inode *first = orig_inode, *second = donor_inode;
 
@@ -203,32 +189,18 @@
 	}
 
 	down_write(&EXT4_I(first)->i_data_sem);
-	down_write(&EXT4_I(second)->i_data_sem);
-}
-
-/**
- * mext_double_up_read - Release two inodes' read semaphore
- *
- * @orig_inode:		original inode structure to be released its lock first
- * @donor_inode:	donor inode structure to be released its lock second
- * Release read semaphore of two inodes (orig and donor).
- */
-static void
-mext_double_up_read(struct inode *orig_inode, struct inode *donor_inode)
-{
-	up_read(&EXT4_I(orig_inode)->i_data_sem);
-	up_read(&EXT4_I(donor_inode)->i_data_sem);
+	down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
 }
 
 /**
- * mext_double_up_write - Release two inodes' write semaphore
+ * double_up_write_data_sem - Release two inodes' write lock of i_data_sem
  *
  * @orig_inode:		original inode structure to be released its lock first
  * @donor_inode:	donor inode structure to be released its lock second
- * Release write semaphore of two inodes (orig and donor).
+ * Release write lock of i_data_sem of two inodes (orig and donor).
  */
 static void
-mext_double_up_write(struct inode *orig_inode, struct inode *donor_inode)
+double_up_write_data_sem(struct inode *orig_inode, struct inode *donor_inode)
 {
 	up_write(&EXT4_I(orig_inode)->i_data_sem);
 	up_write(&EXT4_I(donor_inode)->i_data_sem);
@@ -280,6 +252,7 @@
 		}
 
 		o_start->ee_len = start_ext->ee_len;
+		eblock = le32_to_cpu(start_ext->ee_block);
 		new_flag = 1;
 
 	} else if (start_ext->ee_len && new_ext->ee_len &&
@@ -290,6 +263,7 @@
 		 * orig  |------------------------------|
 		 */
 		o_start->ee_len = start_ext->ee_len;
+		eblock = le32_to_cpu(start_ext->ee_block);
 		new_flag = 1;
 
 	} else if (!start_ext->ee_len && new_ext->ee_len &&
@@ -503,7 +477,6 @@
 	struct ext4_extent *oext, *o_start, *o_end, *prev_ext;
 	struct ext4_extent new_ext, start_ext, end_ext;
 	ext4_lblk_t new_ext_end;
-	ext4_fsblk_t new_phys_end;
 	int oext_alen, new_ext_alen, end_ext_alen;
 	int depth = ext_depth(orig_inode);
 	int ret;
@@ -517,7 +490,6 @@
 	new_ext.ee_len = dext->ee_len;
 	new_ext_alen = ext4_ext_get_actual_len(&new_ext);
 	new_ext_end = le32_to_cpu(new_ext.ee_block) + new_ext_alen - 1;
-	new_phys_end = ext_pblock(&new_ext) + new_ext_alen - 1;
 
 	/*
 	 * Case: original extent is first
@@ -530,6 +502,7 @@
 		le32_to_cpu(oext->ee_block) + oext_alen) {
 		start_ext.ee_len = cpu_to_le16(le32_to_cpu(new_ext.ee_block) -
 					       le32_to_cpu(oext->ee_block));
+		start_ext.ee_block = oext->ee_block;
 		copy_extent_status(oext, &start_ext);
 	} else if (oext > EXT_FIRST_EXTENT(orig_path[depth].p_hdr)) {
 		prev_ext = oext - 1;
@@ -543,6 +516,7 @@
 			start_ext.ee_len = cpu_to_le16(
 				ext4_ext_get_actual_len(prev_ext) +
 				new_ext_alen);
+			start_ext.ee_block = oext->ee_block;
 			copy_extent_status(prev_ext, &start_ext);
 			new_ext.ee_len = 0;
 		}
@@ -661,6 +635,7 @@
  * @donor_inode:	donor inode
  * @from:		block offset of orig_inode
  * @count:		block count to be replaced
+ * @err:		pointer to save return value
  *
  * Replace original inode extents and donor inode extents page by page.
  * We implement this replacement in the following three steps:
@@ -671,33 +646,33 @@
  * 3. Change the block information of donor inode to point at the saved
  *    original inode blocks in the dummy extents.
  *
- * Return 0 on success, or a negative error value on failure.
+ * Return replaced block count.
  */
 static int
 mext_replace_branches(handle_t *handle, struct inode *orig_inode,
 			   struct inode *donor_inode, ext4_lblk_t from,
-			   ext4_lblk_t count)
+			   ext4_lblk_t count, int *err)
 {
 	struct ext4_ext_path *orig_path = NULL;
 	struct ext4_ext_path *donor_path = NULL;
 	struct ext4_extent *oext, *dext;
 	struct ext4_extent tmp_dext, tmp_oext;
 	ext4_lblk_t orig_off = from, donor_off = from;
-	int err = 0;
 	int depth;
 	int replaced_count = 0;
 	int dext_alen;
 
-	mext_double_down_write(orig_inode, donor_inode);
+	/* Protect extent trees against block allocations via delalloc */
+	double_down_write_data_sem(orig_inode, donor_inode);
 
 	/* Get the original extent for the block "orig_off" */
-	err = get_ext_path(orig_inode, orig_off, &orig_path);
-	if (err)
+	*err = get_ext_path(orig_inode, orig_off, &orig_path);
+	if (*err)
 		goto out;
 
 	/* Get the donor extent for the head */
-	err = get_ext_path(donor_inode, donor_off, &donor_path);
-	if (err)
+	*err = get_ext_path(donor_inode, donor_off, &donor_path);
+	if (*err)
 		goto out;
 	depth = ext_depth(orig_inode);
 	oext = orig_path[depth].p_ext;
@@ -707,9 +682,9 @@
 	dext = donor_path[depth].p_ext;
 	tmp_dext = *dext;
 
-	err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
+	*err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
 				      donor_off, count);
-	if (err)
+	if (*err)
 		goto out;
 
 	/* Loop for the donor extents */
@@ -718,7 +693,7 @@
 		if (!dext) {
 			ext4_error(donor_inode->i_sb, __func__,
 				   "The extent for donor must be found");
-			err = -EIO;
+			*err = -EIO;
 			goto out;
 		} else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) {
 			ext4_error(donor_inode->i_sb, __func__,
@@ -726,20 +701,20 @@
 				"extent(%u) should be equal",
 				donor_off,
 				le32_to_cpu(tmp_dext.ee_block));
-			err = -EIO;
+			*err = -EIO;
 			goto out;
 		}
 
 		/* Set donor extent to orig extent */
-		err = mext_leaf_block(handle, orig_inode,
+		*err = mext_leaf_block(handle, orig_inode,
 					   orig_path, &tmp_dext, &orig_off);
-		if (err < 0)
+		if (*err)
 			goto out;
 
 		/* Set orig extent to donor extent */
-		err = mext_leaf_block(handle, donor_inode,
+		*err = mext_leaf_block(handle, donor_inode,
 					   donor_path, &tmp_oext, &donor_off);
-		if (err < 0)
+		if (*err)
 			goto out;
 
 		dext_alen = ext4_ext_get_actual_len(&tmp_dext);
@@ -753,35 +728,25 @@
 
 		if (orig_path)
 			ext4_ext_drop_refs(orig_path);
-		err = get_ext_path(orig_inode, orig_off, &orig_path);
-		if (err)
+		*err = get_ext_path(orig_inode, orig_off, &orig_path);
+		if (*err)
 			goto out;
 		depth = ext_depth(orig_inode);
 		oext = orig_path[depth].p_ext;
-		if (le32_to_cpu(oext->ee_block) +
-				ext4_ext_get_actual_len(oext) <= orig_off) {
-			err = 0;
-			goto out;
-		}
 		tmp_oext = *oext;
 
 		if (donor_path)
 			ext4_ext_drop_refs(donor_path);
-		err = get_ext_path(donor_inode, donor_off, &donor_path);
-		if (err)
+		*err = get_ext_path(donor_inode, donor_off, &donor_path);
+		if (*err)
 			goto out;
 		depth = ext_depth(donor_inode);
 		dext = donor_path[depth].p_ext;
-		if (le32_to_cpu(dext->ee_block) +
-				ext4_ext_get_actual_len(dext) <= donor_off) {
-			err = 0;
-			goto out;
-		}
 		tmp_dext = *dext;
 
-		err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
+		*err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
 					   donor_off, count - replaced_count);
-		if (err)
+		if (*err)
 			goto out;
 	}
 
@@ -795,8 +760,12 @@
 		kfree(donor_path);
 	}
 
-	mext_double_up_write(orig_inode, donor_inode);
-	return err;
+	ext4_ext_invalidate_cache(orig_inode);
+	ext4_ext_invalidate_cache(donor_inode);
+
+	double_up_write_data_sem(orig_inode, donor_inode);
+
+	return replaced_count;
 }
 
 /**
@@ -808,16 +777,17 @@
  * @data_offset_in_page:	block index where data swapping starts
  * @block_len_in_page:		the number of blocks to be swapped
  * @uninit:			orig extent is uninitialized or not
+ * @err:			pointer to save return value
  *
  * Save the data in original inode blocks and replace original inode extents
  * with donor inode extents by calling mext_replace_branches().
- * Finally, write out the saved data in new original inode blocks. Return 0
- * on success, or a negative error value on failure.
+ * Finally, write out the saved data in new original inode blocks. Return
+ * replaced block count.
  */
 static int
 move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
 		  pgoff_t orig_page_offset, int data_offset_in_page,
-		  int block_len_in_page, int uninit)
+		  int block_len_in_page, int uninit, int *err)
 {
 	struct inode *orig_inode = o_filp->f_dentry->d_inode;
 	struct address_space *mapping = orig_inode->i_mapping;
@@ -829,9 +799,11 @@
 	long long offs = orig_page_offset << PAGE_CACHE_SHIFT;
 	unsigned long blocksize = orig_inode->i_sb->s_blocksize;
 	unsigned int w_flags = 0;
-	unsigned int tmp_data_len, data_len;
+	unsigned int tmp_data_size, data_size, replaced_size;
 	void *fsdata;
-	int ret, i, jblocks;
+	int i, jblocks;
+	int err2 = 0;
+	int replaced_count = 0;
 	int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
 
 	/*
@@ -841,8 +813,8 @@
 	jblocks = ext4_writepage_trans_blocks(orig_inode) * 2;
 	handle = ext4_journal_start(orig_inode, jblocks);
 	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
-		return ret;
+		*err = PTR_ERR(handle);
+		return 0;
 	}
 
 	if (segment_eq(get_fs(), KERNEL_DS))
@@ -858,39 +830,36 @@
 	 * Just swap data blocks between orig and donor.
 	 */
 	if (uninit) {
-		ret = mext_replace_branches(handle, orig_inode,
-						 donor_inode, orig_blk_offset,
-						 block_len_in_page);
-
-		/* Clear the inode cache not to refer to the old data */
-		ext4_ext_invalidate_cache(orig_inode);
-		ext4_ext_invalidate_cache(donor_inode);
+		replaced_count = mext_replace_branches(handle, orig_inode,
+						donor_inode, orig_blk_offset,
+						block_len_in_page, err);
 		goto out2;
 	}
 
 	offs = (long long)orig_blk_offset << orig_inode->i_blkbits;
 
-	/* Calculate data_len */
+	/* Calculate data_size */
 	if ((orig_blk_offset + block_len_in_page - 1) ==
 	    ((orig_inode->i_size - 1) >> orig_inode->i_blkbits)) {
 		/* Replace the last block */
-		tmp_data_len = orig_inode->i_size & (blocksize - 1);
+		tmp_data_size = orig_inode->i_size & (blocksize - 1);
 		/*
-		 * If data_len equal zero, it shows data_len is multiples of
+		 * If data_size equal zero, it shows data_size is multiples of
 		 * blocksize. So we set appropriate value.
 		 */
-		if (tmp_data_len == 0)
-			tmp_data_len = blocksize;
+		if (tmp_data_size == 0)
+			tmp_data_size = blocksize;
 
-		data_len = tmp_data_len +
+		data_size = tmp_data_size +
 			((block_len_in_page - 1) << orig_inode->i_blkbits);
-	} else {
-		data_len = block_len_in_page << orig_inode->i_blkbits;
-	}
+	} else
+		data_size = block_len_in_page << orig_inode->i_blkbits;
 
-	ret = a_ops->write_begin(o_filp, mapping, offs, data_len, w_flags,
+	replaced_size = data_size;
+
+	*err = a_ops->write_begin(o_filp, mapping, offs, data_size, w_flags,
 				 &page, &fsdata);
-	if (unlikely(ret < 0))
+	if (unlikely(*err < 0))
 		goto out;
 
 	if (!PageUptodate(page)) {
@@ -911,14 +880,17 @@
 	/* Release old bh and drop refs */
 	try_to_release_page(page, 0);
 
-	ret = mext_replace_branches(handle, orig_inode, donor_inode,
-					 orig_blk_offset, block_len_in_page);
-	if (ret < 0)
-		goto out;
-
-	/* Clear the inode cache not to refer to the old data */
-	ext4_ext_invalidate_cache(orig_inode);
-	ext4_ext_invalidate_cache(donor_inode);
+	replaced_count = mext_replace_branches(handle, orig_inode, donor_inode,
+					orig_blk_offset, block_len_in_page,
+					&err2);
+	if (err2) {
+		if (replaced_count) {
+			block_len_in_page = replaced_count;
+			replaced_size =
+				block_len_in_page << orig_inode->i_blkbits;
+		} else
+			goto out;
+	}
 
 	if (!page_has_buffers(page))
 		create_empty_buffers(page, 1 << orig_inode->i_blkbits, 0);
@@ -928,16 +900,16 @@
 		bh = bh->b_this_page;
 
 	for (i = 0; i < block_len_in_page; i++) {
-		ret = ext4_get_block(orig_inode,
+		*err = ext4_get_block(orig_inode,
 				(sector_t)(orig_blk_offset + i), bh, 0);
-		if (ret < 0)
+		if (*err < 0)
 			goto out;
 
 		if (bh->b_this_page != NULL)
 			bh = bh->b_this_page;
 	}
 
-	ret = a_ops->write_end(o_filp, mapping, offs, data_len, data_len,
+	*err = a_ops->write_end(o_filp, mapping, offs, data_size, replaced_size,
 			       page, fsdata);
 	page = NULL;
 
@@ -951,18 +923,20 @@
 out2:
 	ext4_journal_stop(handle);
 
-	return ret < 0 ? ret : 0;
+	if (err2)
+		*err = err2;
+
+	return replaced_count;
 }
 
 /**
- * mext_check_argumants - Check whether move extent can be done
+ * mext_check_arguments - Check whether move extent can be done
  *
  * @orig_inode:		original inode
  * @donor_inode:	donor inode
  * @orig_start:		logical start offset in block for orig
  * @donor_start:	logical start offset in block for donor
  * @len:		the number of blocks to be moved
- * @moved_len:		moved block length
  *
  * Check the arguments of ext4_move_extents() whether the files can be
  * exchanged with each other.
@@ -970,21 +944,23 @@
  */
 static int
 mext_check_arguments(struct inode *orig_inode,
-			  struct inode *donor_inode, __u64 orig_start,
-			  __u64 donor_start, __u64 *len, __u64 moved_len)
+		     struct inode *donor_inode, __u64 orig_start,
+		     __u64 donor_start, __u64 *len)
 {
 	ext4_lblk_t orig_blocks, donor_blocks;
 	unsigned int blkbits = orig_inode->i_blkbits;
 	unsigned int blocksize = 1 << blkbits;
 
-	/* Regular file check */
-	if (!S_ISREG(orig_inode->i_mode) || !S_ISREG(donor_inode->i_mode)) {
-		ext4_debug("ext4 move extent: The argument files should be "
-			"regular file [ino:orig %lu, donor %lu]\n",
-			orig_inode->i_ino, donor_inode->i_ino);
+	if (donor_inode->i_mode & (S_ISUID|S_ISGID)) {
+		ext4_debug("ext4 move extent: suid or sgid is set"
+			   " to donor file [ino:orig %lu, donor %lu]\n",
+			   orig_inode->i_ino, donor_inode->i_ino);
 		return -EINVAL;
 	}
 
+	if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode))
+		return -EPERM;
+
 	/* Ext4 move extent does not support swapfile */
 	if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) {
 		ext4_debug("ext4 move extent: The argument files should "
@@ -1002,11 +978,11 @@
 	}
 
 	/* Ext4 move extent supports only extent based file */
-	if (!(EXT4_I(orig_inode)->i_flags & EXT4_EXTENTS_FL)) {
+	if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) {
 		ext4_debug("ext4 move extent: orig file is not extents "
 			"based file [ino:orig %lu]\n", orig_inode->i_ino);
 		return -EOPNOTSUPP;
-	} else if (!(EXT4_I(donor_inode)->i_flags & EXT4_EXTENTS_FL)) {
+	} else if (!(ext4_test_inode_flag(donor_inode, EXT4_INODE_EXTENTS))) {
 		ext4_debug("ext4 move extent: donor file is not extents "
 			"based file [ino:donor %lu]\n", donor_inode->i_ino);
 		return -EOPNOTSUPP;
@@ -1025,13 +1001,6 @@
 		return -EINVAL;
 	}
 
-	if (moved_len) {
-		ext4_debug("ext4 move extent: moved_len should be 0 "
-			"[ino:orig %lu, donor %lu]\n", orig_inode->i_ino,
-			donor_inode->i_ino);
-		return -EINVAL;
-	}
-
 	if ((orig_start > EXT_MAX_BLOCK) ||
 	    (donor_start > EXT_MAX_BLOCK) ||
 	    (*len > EXT_MAX_BLOCK) ||
@@ -1232,16 +1201,24 @@
 		return -EINVAL;
 	}
 
-	/* protect orig and donor against a truncate */
+	/* Regular file check */
+	if (!S_ISREG(orig_inode->i_mode) || !S_ISREG(donor_inode->i_mode)) {
+		ext4_debug("ext4 move extent: The argument files should be "
+			"regular file [ino:orig %lu, donor %lu]\n",
+			orig_inode->i_ino, donor_inode->i_ino);
+		return -EINVAL;
+	}
+
+	/* Protect orig and donor inodes against a truncate */
 	ret1 = mext_inode_double_lock(orig_inode, donor_inode);
 	if (ret1 < 0)
 		return ret1;
 
-	mext_double_down_read(orig_inode, donor_inode);
+	/* Protect extent tree against block allocations via delalloc */
+	double_down_write_data_sem(orig_inode, donor_inode);
 	/* Check the filesystem environment whether move_extent can be done */
 	ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start,
-					donor_start, &len, *moved_len);
-	mext_double_up_read(orig_inode, donor_inode);
+				    donor_start, &len);
 	if (ret1)
 		goto out;
 
@@ -1355,36 +1332,39 @@
 		seq_start = le32_to_cpu(ext_cur->ee_block);
 		rest_blocks = seq_blocks;
 
-		/* Discard preallocations of two inodes */
-		down_write(&EXT4_I(orig_inode)->i_data_sem);
-		ext4_discard_preallocations(orig_inode);
-		up_write(&EXT4_I(orig_inode)->i_data_sem);
-
-		down_write(&EXT4_I(donor_inode)->i_data_sem);
-		ext4_discard_preallocations(donor_inode);
-		up_write(&EXT4_I(donor_inode)->i_data_sem);
+		/*
+		 * Up semaphore to avoid following problems:
+		 * a. transaction deadlock among ext4_journal_start,
+		 *    ->write_begin via pagefault, and jbd2_journal_commit
+		 * b. racing with ->readpage, ->write_begin, and ext4_get_block
+		 *    in move_extent_per_page
+		 */
+		double_up_write_data_sem(orig_inode, donor_inode);
 
 		while (orig_page_offset <= seq_end_page) {
 
 			/* Swap original branches with new branches */
-			ret1 = move_extent_per_page(o_filp, donor_inode,
+			block_len_in_page = move_extent_per_page(
+						o_filp, donor_inode,
 						orig_page_offset,
 						data_offset_in_page,
-						block_len_in_page, uninit);
-			if (ret1 < 0)
-				goto out;
-			orig_page_offset++;
+						block_len_in_page, uninit,
+						&ret1);
+
 			/* Count how many blocks we have exchanged */
 			*moved_len += block_len_in_page;
+			if (ret1 < 0)
+				break;
 			if (*moved_len > len) {
 				ext4_error(orig_inode->i_sb, __func__,
 					"We replaced blocks too much! "
 					"sum of replaced: %llu requested: %llu",
 					*moved_len, len);
 				ret1 = -EIO;
-				goto out;
+				break;
 			}
 
+			orig_page_offset++;
 			data_offset_in_page = 0;
 			rest_blocks -= block_len_in_page;
 			if (rest_blocks > blocks_per_page)
@@ -1393,6 +1373,10 @@
 				block_len_in_page = rest_blocks;
 		}
 
+		double_down_write_data_sem(orig_inode, donor_inode);
+		if (ret1 < 0)
+			break;
+
 		/* Decrease buffer counter */
 		if (holecheck_path)
 			ext4_ext_drop_refs(holecheck_path);
@@ -1414,6 +1398,11 @@
 
 	}
 out:
+	if (*moved_len) {
+		ext4_discard_preallocations(orig_inode);
+		ext4_discard_preallocations(donor_inode);
+	}
+
 	if (orig_path) {
 		ext4_ext_drop_refs(orig_path);
 		kfree(orig_path);
@@ -1422,7 +1411,7 @@
 		ext4_ext_drop_refs(holecheck_path);
 		kfree(holecheck_path);
 	}
-
+	double_up_write_data_sem(orig_inode, donor_inode);
 	ret2 = mext_inode_double_unlock(orig_inode, donor_inode);
 
 	if (ret1)
--- linux-ec2-2.6.32.orig/fs/ext4/fsync.c
+++ linux-ec2-2.6.32/fs/ext4/fsync.c
@@ -35,6 +35,29 @@
 #include <trace/events/ext4.h>
 
 /*
+ * If we're not journaling and this is a just-created file, we have to
+ * sync our parent directory (if it was freshly created) since
+ * otherwise it will only be written by writeback, leaving a huge
+ * window during which a crash may lose the file.  This may apply for
+ * the parent directory's parent as well, and so on recursively, if
+ * they are also freshly created.
+ */
+static void ext4_sync_parent(struct inode *inode)
+{
+	struct dentry *dentry = NULL;
+
+	while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
+		ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
+		dentry = list_entry(inode->i_dentry.next,
+				    struct dentry, d_alias);
+		if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
+			break;
+		inode = dentry->d_parent->d_inode;
+		sync_mapping_buffers(inode->i_mapping);
+	}
+}
+
+/*
  * akpm: A new design for ext4_sync_file().
  *
  * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
@@ -51,25 +74,34 @@
 int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
 {
 	struct inode *inode = dentry->d_inode;
+	struct ext4_inode_info *ei = EXT4_I(inode);
 	journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
-	int err, ret = 0;
+	int ret;
+	tid_t commit_tid;
 
 	J_ASSERT(ext4_journal_current_handle() == NULL);
 
 	trace_ext4_sync_file(file, dentry, datasync);
 
+	if (inode->i_sb->s_flags & MS_RDONLY)
+		return 0;
+
 	ret = flush_aio_dio_completed_IO(inode);
 	if (ret < 0)
-		goto out;
+		return ret;
+
+	if (!journal) {
+		ret = simple_fsync(file, dentry, datasync);
+		if (!ret && !list_empty(&inode->i_dentry))
+			ext4_sync_parent(inode);
+		return ret;
+	}
+
 	/*
-	 * data=writeback:
+	 * data=writeback,ordered:
 	 *  The caller's filemap_fdatawrite()/wait will sync the data.
-	 *  sync_inode() will sync the metadata
-	 *
-	 * data=ordered:
-	 *  The caller's filemap_fdatawrite() will write the data and
-	 *  sync_inode() will write the inode if it is dirty.  Then the caller's
-	 *  filemap_fdatawait() will wait on the pages.
+	 *  Metadata is in the journal, we wait for proper transaction to
+	 *  commit here.
 	 *
 	 * data=journal:
 	 *  filemap_fdatawrite won't do anything (the buffers are clean).
@@ -79,32 +111,25 @@
 	 *  (they were dirtied by commit).  But that's OK - the blocks are
 	 *  safe in-journal, which is all fsync() needs to ensure.
 	 */
-	if (ext4_should_journal_data(inode)) {
-		ret = ext4_force_commit(inode->i_sb);
-		goto out;
-	}
-
-	if (!journal)
-		ret = sync_mapping_buffers(inode->i_mapping);
+	if (ext4_should_journal_data(inode))
+		return ext4_force_commit(inode->i_sb);
 
-	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
-		goto out;
-
-	/*
-	 * The VFS has written the file data.  If the inode is unaltered
-	 * then we need not start a commit.
-	 */
-	if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) {
-		struct writeback_control wbc = {
-			.sync_mode = WB_SYNC_ALL,
-			.nr_to_write = 0, /* sys_fsync did this */
-		};
-		err = sync_inode(inode, &wbc);
-		if (ret == 0)
-			ret = err;
-	}
-out:
-	if (journal && (journal->j_flags & JBD2_BARRIER))
+	commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
+	if (jbd2_log_start_commit(journal, commit_tid)) {
+		/*
+		 * When the journal is on a different device than the
+		 * fs data disk, we need to issue the barrier in
+		 * writeback mode.  (In ordered mode, the jbd2 layer
+		 * will take care of issuing the barrier.  In
+		 * data=journal, all of the data blocks are written to
+		 * the journal device.)
+		 */
+		if (ext4_should_writeback_data(inode) &&
+		    (journal->j_fs_dev != journal->j_dev) &&
+		    (journal->j_flags & JBD2_BARRIER))
+			blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
+		ret = jbd2_log_wait_commit(journal, commit_tid);
+	} else if (journal->j_flags & JBD2_BARRIER)
 		blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
 	return ret;
 }
--- linux-ec2-2.6.32.orig/fs/ext4/ext4_jbd2.c
+++ linux-ec2-2.6.32/fs/ext4/ext4_jbd2.c
@@ -89,7 +89,7 @@
 			ext4_journal_abort_handle(where, __func__, bh,
 						  handle, err);
 	} else {
-		if (inode && bh)
+		if (inode)
 			mark_buffer_dirty_inode(bh, inode);
 		else
 			mark_buffer_dirty(bh);
--- linux-ec2-2.6.32.orig/fs/ext4/inode.c
+++ linux-ec2-2.6.32/fs/ext4/inode.c
@@ -957,7 +957,7 @@
 	int count = 0;
 	ext4_fsblk_t first_block = 0;
 
-	J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL));
+	J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)));
 	J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0);
 	depth = ext4_block_to_path(inode, iblock, offsets,
 				   &blocks_to_boundary);
@@ -1021,10 +1021,12 @@
 	if (!err)
 		err = ext4_splice_branch(handle, inode, iblock,
 					 partial, indirect_blks, count);
-	else
+	if (err)
 		goto cleanup;
 
 	set_buffer_new(bh_result);
+
+	ext4_update_inode_fsync_trans(handle, inode, 1);
 got_it:
 	map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
 	if (count > blocks_to_boundary)
@@ -1043,92 +1045,121 @@
 	return err;
 }
 
-qsize_t ext4_get_reserved_space(struct inode *inode)
+#ifdef CONFIG_QUOTA
+qsize_t *ext4_get_reserved_space(struct inode *inode)
 {
-	unsigned long long total;
-
-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-	total = EXT4_I(inode)->i_reserved_data_blocks +
-		EXT4_I(inode)->i_reserved_meta_blocks;
-	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-
-	return total;
+	return &EXT4_I(inode)->i_reserved_quota;
 }
+#endif
+
 /*
  * Calculate the number of metadata blocks need to reserve
- * to allocate @blocks for non extent file based file
+ * to allocate a new block at @lblocks for non extent file based file
  */
-static int ext4_indirect_calc_metadata_amount(struct inode *inode, int blocks)
+static int ext4_indirect_calc_metadata_amount(struct inode *inode,
+					      sector_t lblock)
 {
-	int icap = EXT4_ADDR_PER_BLOCK(inode->i_sb);
-	int ind_blks, dind_blks, tind_blks;
-
-	/* number of new indirect blocks needed */
-	ind_blks = (blocks + icap - 1) / icap;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	sector_t dind_mask = ~((sector_t)EXT4_ADDR_PER_BLOCK(inode->i_sb) - 1);
+	int blk_bits;
 
-	dind_blks = (ind_blks + icap - 1) / icap;
+	if (lblock < EXT4_NDIR_BLOCKS)
+		return 0;
 
-	tind_blks = 1;
+	lblock -= EXT4_NDIR_BLOCKS;
 
-	return ind_blks + dind_blks + tind_blks;
+	if (ei->i_da_metadata_calc_len &&
+	    (lblock & dind_mask) == ei->i_da_metadata_calc_last_lblock) {
+		ei->i_da_metadata_calc_len++;
+		return 0;
+	}
+	ei->i_da_metadata_calc_last_lblock = lblock & dind_mask;
+	ei->i_da_metadata_calc_len = 1;
+	blk_bits = order_base_2(lblock);
+	return (blk_bits / EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb)) + 1;
 }
 
 /*
  * Calculate the number of metadata blocks need to reserve
- * to allocate given number of blocks
+ * to allocate a block located at @lblock
  */
-static int ext4_calc_metadata_amount(struct inode *inode, int blocks)
+static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock)
 {
-	if (!blocks)
-		return 0;
-
-	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
-		return ext4_ext_calc_metadata_amount(inode, blocks);
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+		return ext4_ext_calc_metadata_amount(inode, lblock);
 
-	return ext4_indirect_calc_metadata_amount(inode, blocks);
+	return ext4_indirect_calc_metadata_amount(inode, lblock);
 }
 
-static void ext4_da_update_reserve_space(struct inode *inode, int used)
+/*
+ * Called with i_data_sem down, which is important since we can call
+ * ext4_discard_preallocations() from here.
+ */
+void ext4_da_update_reserve_space(struct inode *inode,
+					int used, int quota_claim)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-	int total, mdb, mdb_free;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	int mdb_free = 0, allocated_meta_blocks = 0;
 
-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-	/* recalculate the number of metablocks still need to be reserved */
-	total = EXT4_I(inode)->i_reserved_data_blocks - used;
-	mdb = ext4_calc_metadata_amount(inode, total);
-
-	/* figure out how many metablocks to release */
-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-	mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
-
-	if (mdb_free) {
-		/* Account for allocated meta_blocks */
-		mdb_free -= EXT4_I(inode)->i_allocated_meta_blocks;
+	spin_lock(&ei->i_block_reservation_lock);
+	if (unlikely(used > ei->i_reserved_data_blocks)) {
+		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
+			 "with only %d reserved data blocks\n",
+			 __func__, inode->i_ino, used,
+			 ei->i_reserved_data_blocks);
+		WARN_ON(1);
+		used = ei->i_reserved_data_blocks;
+	}
+
+	/* Update per-inode reservations */
+	ei->i_reserved_data_blocks -= used;
+	used += ei->i_allocated_meta_blocks;
+	ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
+	allocated_meta_blocks = ei->i_allocated_meta_blocks;
+	ei->i_allocated_meta_blocks = 0;
+	percpu_counter_sub(&sbi->s_dirtyblocks_counter, used);
 
-		/* update fs dirty blocks counter */
+	if (ei->i_reserved_data_blocks == 0) {
+		/*
+		 * We can release all of the reserved metadata blocks
+		 * only when we have written all of the delayed
+		 * allocation blocks.
+		 */
+		mdb_free = ei->i_reserved_meta_blocks;
+		ei->i_reserved_meta_blocks = 0;
+		ei->i_da_metadata_calc_len = 0;
 		percpu_counter_sub(&sbi->s_dirtyblocks_counter, mdb_free);
-		EXT4_I(inode)->i_allocated_meta_blocks = 0;
-		EXT4_I(inode)->i_reserved_meta_blocks = mdb;
 	}
-
-	/* update per-inode reservations */
-	BUG_ON(used  > EXT4_I(inode)->i_reserved_data_blocks);
-	EXT4_I(inode)->i_reserved_data_blocks -= used;
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-	/*
-	 * free those over-booking quota for metadata blocks
-	 */
-	if (mdb_free)
-		vfs_dq_release_reservation_block(inode, mdb_free);
+	/* Update quota subsystem */
+	if (quota_claim) {
+		vfs_dq_claim_block(inode, used);
+		if (mdb_free)
+			vfs_dq_release_reservation_block(inode, mdb_free);
+	} else {
+		/*
+		 * We did fallocate with an offset that is already delayed
+		 * allocated. So on delayed allocated writeback we should
+		 * not update the quota for allocated blocks. But then
+		 * converting an fallocate region to initialized region would
+		 * have caused a metadata allocation. So claim quota for
+		 * that
+		 */
+		if (allocated_meta_blocks)
+			vfs_dq_claim_block(inode, allocated_meta_blocks);
+		vfs_dq_release_reservation_block(inode, mdb_free + used -
+						allocated_meta_blocks);
+	}
 
 	/*
 	 * If we have done all the pending block allocations and if
 	 * there aren't any writers on the inode, we can discard the
 	 * inode's preallocations.
 	 */
-	if (!total && (atomic_read(&inode->i_writecount) == 0))
+	if ((ei->i_reserved_data_blocks == 0) &&
+	    (atomic_read(&inode->i_writecount) == 0))
 		ext4_discard_preallocations(inode);
 }
 
@@ -1243,7 +1274,7 @@
 	 * file system block.
 	 */
 	down_read((&EXT4_I(inode)->i_data_sem));
-	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
 				bh, 0);
 	} else {
@@ -1305,7 +1336,7 @@
 	 * We need to check for EXT4 here because migrate
 	 * could have changed the inode type in between
 	 */
-	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
 		retval =  ext4_ext_get_blocks(handle, inode, block, max_blocks,
 					      bh, flags);
 	} else {
@@ -1318,20 +1349,22 @@
 			 * i_data's format changing.  Force the migrate
 			 * to fail by clearing migrate flags
 			 */
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+			ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 		}
-	}
 
+		/*
+		 * Update reserved blocks/metadata blocks after successful
+		 * block allocation which had been deferred till now. We don't
+		 * support fallocate for non extent files. So we can update
+		 * reserve space here.
+		 */
+		if ((retval > 0) &&
+			(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE))
+			ext4_da_update_reserve_space(inode, retval, 1);
+	}
 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
 		EXT4_I(inode)->i_delalloc_reserved_flag = 0;
 
-	/*
-	 * Update reserved blocks/metadata blocks after successful
-	 * block allocation which had been deferred till now.
-	 */
-	if ((retval > 0) && (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE))
-		ext4_da_update_reserve_space(inode, retval);
-
 	up_write((&EXT4_I(inode)->i_data_sem));
 	if (retval > 0 && buffer_mapped(bh)) {
 		int ret = check_block_validity(inode, "file system "
@@ -1534,6 +1567,16 @@
 	return ext4_journal_get_write_access(handle, bh);
 }
 
+/*
+ * Truncate blocks that were not used by write. We have to truncate the
+ * pagecache as well so that corresponding buffers get properly unmapped.
+ */
+static void ext4_truncate_failed_write(struct inode *inode)
+{
+	truncate_inode_pages(inode->i_mapping, inode->i_size);
+	ext4_truncate(inode);
+}
+
 static int ext4_write_begin(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len, unsigned flags,
 			    struct page **pagep, void **fsdata)
@@ -1599,7 +1642,7 @@
 
 		ext4_journal_stop(handle);
 		if (pos + len > inode->i_size) {
-			ext4_truncate(inode);
+			ext4_truncate_failed_write(inode);
 			/*
 			 * If truncate failed early the inode might
 			 * still be on the orphan list; we need to
@@ -1709,7 +1752,7 @@
 		ret = ret2;
 
 	if (pos + len > inode->i_size) {
-		ext4_truncate(inode);
+		ext4_truncate_failed_write(inode);
 		/*
 		 * If truncate failed early the inode might still be
 		 * on the orphan list; we need to make sure the inode
@@ -1751,7 +1794,7 @@
 		ret = ret2;
 
 	if (pos + len > inode->i_size) {
-		ext4_truncate(inode);
+		ext4_truncate_failed_write(inode);
 		/*
 		 * If truncate failed early the inode might still be
 		 * on the orphan list; we need to make sure the inode
@@ -1793,7 +1836,7 @@
 	new_i_size = pos + copied;
 	if (new_i_size > inode->i_size)
 		i_size_write(inode, pos+copied);
-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 	if (new_i_size > EXT4_I(inode)->i_disksize) {
 		ext4_update_i_disksize(inode, new_i_size);
 		ret2 = ext4_mark_inode_dirty(handle, inode);
@@ -1814,7 +1857,7 @@
 	if (!ret)
 		ret = ret2;
 	if (pos + len > inode->i_size) {
-		ext4_truncate(inode);
+		ext4_truncate_failed_write(inode);
 		/*
 		 * If truncate failed early the inode might still be
 		 * on the orphan list; we need to make sure the inode
@@ -1827,11 +1870,15 @@
 	return ret ? ret : copied;
 }
 
-static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
+/*
+ * Reserve a single block located at lblock
+ */
+static int ext4_da_reserve_space(struct inode *inode, sector_t lblock)
 {
 	int retries = 0;
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-	unsigned long md_needed, mdblocks, total = 0;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	unsigned long md_needed, md_reserved;
 
 	/*
 	 * recalculate the amount of metadata blocks to reserve
@@ -1839,86 +1886,78 @@
 	 * worse case is one extent per block
 	 */
 repeat:
-	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
-	total = EXT4_I(inode)->i_reserved_data_blocks + nrblocks;
-	mdblocks = ext4_calc_metadata_amount(inode, total);
-	BUG_ON(mdblocks < EXT4_I(inode)->i_reserved_meta_blocks);
-
-	md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
-	total = md_needed + nrblocks;
+	spin_lock(&ei->i_block_reservation_lock);
+	md_reserved = ei->i_reserved_meta_blocks;
+	md_needed = ext4_calc_metadata_amount(inode, lblock);
+	spin_unlock(&ei->i_block_reservation_lock);
 
 	/*
 	 * Make quota reservation here to prevent quota overflow
 	 * later. Real quota accounting is done at pages writeout
 	 * time.
 	 */
-	if (vfs_dq_reserve_block(inode, total)) {
-		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+	if (vfs_dq_reserve_block(inode, md_needed + 1))
 		return -EDQUOT;
-	}
 
-	if (ext4_claim_free_blocks(sbi, total)) {
-		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-		vfs_dq_release_reservation_block(inode, total);
+	if (ext4_claim_free_blocks(sbi, md_needed + 1)) {
+		vfs_dq_release_reservation_block(inode, md_needed + 1);
 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
 			yield();
 			goto repeat;
 		}
 		return -ENOSPC;
 	}
-	EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
-	EXT4_I(inode)->i_reserved_meta_blocks = mdblocks;
+	spin_lock(&ei->i_block_reservation_lock);
+	ei->i_reserved_data_blocks++;
+	ei->i_reserved_meta_blocks += md_needed;
+	spin_unlock(&ei->i_block_reservation_lock);
 
-	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 	return 0;       /* success */
 }
 
 static void ext4_da_release_space(struct inode *inode, int to_free)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-	int total, mdb, mdb_free, release;
+	struct ext4_inode_info *ei = EXT4_I(inode);
 
 	if (!to_free)
 		return;		/* Nothing to release, exit */
 
 	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
 
-	if (!EXT4_I(inode)->i_reserved_data_blocks) {
+	if (unlikely(to_free > ei->i_reserved_data_blocks)) {
 		/*
-		 * if there is no reserved blocks, but we try to free some
-		 * then the counter is messed up somewhere.
-		 * but since this function is called from invalidate
-		 * page, it's harmless to return without any action
-		 */
-		printk(KERN_INFO "ext4 delalloc try to release %d reserved "
-			    "blocks for inode %lu, but there is no reserved "
-			    "data blocks\n", to_free, inode->i_ino);
-		spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
-		return;
+		 * if there aren't enough reserved blocks, then the
+		 * counter is messed up somewhere.  Since this
+		 * function is called from invalidate page, it's
+		 * harmless to return without any action.
+		 */
+		ext4_msg(inode->i_sb, KERN_NOTICE, "ext4_da_release_space: "
+			 "ino %lu, to_free %d with only %d reserved "
+			 "data blocks\n", inode->i_ino, to_free,
+			 ei->i_reserved_data_blocks);
+		WARN_ON(1);
+		to_free = ei->i_reserved_data_blocks;
 	}
+	ei->i_reserved_data_blocks -= to_free;
 
-	/* recalculate the number of metablocks still need to be reserved */
-	total = EXT4_I(inode)->i_reserved_data_blocks - to_free;
-	mdb = ext4_calc_metadata_amount(inode, total);
-
-	/* figure out how many metablocks to release */
-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-	mdb_free = EXT4_I(inode)->i_reserved_meta_blocks - mdb;
-
-	release = to_free + mdb_free;
-
-	/* update fs dirty blocks counter for truncate case */
-	percpu_counter_sub(&sbi->s_dirtyblocks_counter, release);
+	if (ei->i_reserved_data_blocks == 0) {
+		/*
+		 * We can release all of the reserved metadata blocks
+		 * only when we have written all of the delayed
+		 * allocation blocks.
+		 */
+		to_free += ei->i_reserved_meta_blocks;
+		ei->i_reserved_meta_blocks = 0;
+		ei->i_da_metadata_calc_len = 0;
+	}
 
-	/* update per-inode reservations */
-	BUG_ON(to_free > EXT4_I(inode)->i_reserved_data_blocks);
-	EXT4_I(inode)->i_reserved_data_blocks -= to_free;
+	/* update fs dirty blocks counter */
+	percpu_counter_sub(&sbi->s_dirtyblocks_counter, to_free);
 
-	BUG_ON(mdb > EXT4_I(inode)->i_reserved_meta_blocks);
-	EXT4_I(inode)->i_reserved_meta_blocks = mdb;
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-	vfs_dq_release_reservation_block(inode, release);
+	vfs_dq_release_reservation_block(inode, to_free);
 }
 
 static void ext4_da_page_release_reservation(struct page *page,
@@ -2223,10 +2262,10 @@
 	 * variables are updated after the blocks have been allocated.
 	 */
 	new.b_state = 0;
-	get_blocks_flags = (EXT4_GET_BLOCKS_CREATE |
-			    EXT4_GET_BLOCKS_DELALLOC_RESERVE);
+	get_blocks_flags = EXT4_GET_BLOCKS_CREATE;
 	if (mpd->b_state & (1 << BH_Delay))
-		get_blocks_flags |= EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE;
+		get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE;
+
 	blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks,
 			       &new, get_blocks_flags);
 	if (blks < 0) {
@@ -2255,7 +2294,7 @@
 		ext4_msg(mpd->inode->i_sb, KERN_CRIT,
 			 "delayed block allocation failed for inode %lu at "
 			 "logical offset %llu with max blocks %zd with "
-			 "error %d\n", mpd->inode->i_ino,
+			 "error %d", mpd->inode->i_ino,
 			 (unsigned long long) next,
 			 mpd->b_size >> mpd->inode->i_blkbits, err);
 		printk(KERN_CRIT "This should not happen!!  "
@@ -2322,8 +2361,17 @@
 	sector_t next;
 	int nrblocks = mpd->b_size >> mpd->inode->i_blkbits;
 
+	/*
+	 * XXX Don't go larger than mballoc is willing to allocate
+	 * This is a stopgap solution.  We eventually need to fold
+	 * mpage_da_submit_io() into this function and then call
+	 * ext4_get_blocks() multiple times in a loop
+	 */
+	if (nrblocks >= 8*1024*1024/mpd->inode->i_sb->s_blocksize)
+		goto flush_it;
+
 	/* check if thereserved journal credits might overflow */
-	if (!(EXT4_I(mpd->inode)->i_flags & EXT4_EXTENTS_FL)) {
+	if (!(ext4_test_inode_flag(mpd->inode, EXT4_INODE_EXTENTS))) {
 		if (nrblocks >= EXT4_MAX_TRANS_DATA) {
 			/*
 			 * With non-extent format we are limited by the journal
@@ -2524,7 +2572,7 @@
 		 * XXX: __block_prepare_write() unmaps passed block,
 		 * is it OK?
 		 */
-		ret = ext4_da_reserve_space(inode, 1);
+		ret = ext4_da_reserve_space(inode, iblock);
 		if (ret)
 			/* not enough space to reserve */
 			return ret;
@@ -2635,7 +2683,7 @@
 		ret = err;
 
 	walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 out:
 	return ret;
 }
@@ -2788,7 +2836,7 @@
 	 * number of contiguous block. So we will limit
 	 * number of contiguous block to a sane value
 	 */
-	if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) &&
 	    (max_blocks > EXT4_MAX_TRANS_DATA))
 		max_blocks = EXT4_MAX_TRANS_DATA;
 
@@ -2908,7 +2956,7 @@
 		if (IS_ERR(handle)) {
 			ret = PTR_ERR(handle);
 			ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
-			       "%ld pages, ino %lu; err %d\n", __func__,
+			       "%ld pages, ino %lu; err %d", __func__,
 				wbc->nr_to_write, inode->i_ino, ret);
 			goto out_writepages;
 		}
@@ -2983,7 +3031,7 @@
 	if (pages_skipped != wbc->pages_skipped)
 		ext4_msg(inode->i_sb, KERN_CRIT,
 			 "This should not happen leaving %s "
-			 "with nr_to_write = %ld ret = %d\n",
+			 "with nr_to_write = %ld ret = %d",
 			 __func__, wbc->nr_to_write, ret);
 
 	/* Update index */
@@ -2999,8 +3047,7 @@
 out_writepages:
 	if (!no_nrwrite_index_update)
 		wbc->no_nrwrite_index_update = 0;
-	if (wbc->nr_to_write > nr_to_writebump)
-		wbc->nr_to_write -= nr_to_writebump;
+	wbc->nr_to_write -= nr_to_writebump;
 	wbc->range_start = range_start;
 	trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
 	return ret;
@@ -3025,11 +3072,18 @@
 	if (2 * free_blocks < 3 * dirty_blocks ||
 		free_blocks < (dirty_blocks + EXT4_FREEBLOCKS_WATERMARK)) {
 		/*
-		 * free block count is less that 150% of dirty blocks
-		 * or free blocks is less that watermark
+		 * free block count is less than 150% of dirty blocks
+		 * or free blocks is less than watermark
 		 */
 		return 1;
 	}
+	/*
+	 * Even if we don't switch but are nearing capacity,
+	 * start pushing delalloc when 1/2 of free blocks are dirty.
+	 */
+	if (free_blocks < 2 * dirty_blocks)
+		writeback_inodes_sb_if_idle(sb);
+
 	return 0;
 }
 
@@ -3037,7 +3091,7 @@
 			       loff_t pos, unsigned len, unsigned flags,
 			       struct page **pagep, void **fsdata)
 {
-	int ret, retries = 0;
+	int ret, retries = 0, quota_retries = 0;
 	struct page *page;
 	pgoff_t index;
 	unsigned from, to;
@@ -3091,11 +3145,27 @@
 		 * i_size_read because we hold i_mutex.
 		 */
 		if (pos + len > inode->i_size)
-			ext4_truncate(inode);
+			ext4_truncate_failed_write(inode);
 	}
 
 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
 		goto retry;
+
+	if ((ret == -EDQUOT) &&
+	    EXT4_I(inode)->i_reserved_meta_blocks &&
+	    (quota_retries++ < 3)) {
+		/*
+		 * Since we often over-estimate the number of meta
+		 * data blocks required, we may sometimes get a
+		 * spurios out of quota error even though there would
+		 * be enough space once we write the data blocks and
+		 * find out how many meta data blocks were _really_
+		 * required.  So try forcing the inode write to see if
+		 * that helps.
+		 */
+		write_inode_now(inode, (quota_retries == 3));
+		goto retry;
+	}
 out:
 	return ret;
 }
@@ -3284,7 +3354,8 @@
 		filemap_write_and_wait(mapping);
 	}
 
-	if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
+	if (EXT4_JOURNAL(inode) &&
+	    ext4_test_inode_state(inode, EXT4_STATE_JDATA)) {
 		/*
 		 * This is a REALLY heavyweight approach, but the use of
 		 * bmap on dirty files is expected to be extremely rare:
@@ -3303,7 +3374,7 @@
 		 * everything they get.
 		 */
 
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
+		ext4_clear_inode_state(inode, EXT4_STATE_JDATA);
 		journal = EXT4_JOURNAL(inode);
 		jbd2_journal_lock_updates(journal);
 		err = jbd2_journal_flush(journal);
@@ -3419,6 +3490,9 @@
 			 * but cannot extend i_size. Bail out and pretend
 			 * the write failed... */
 			ret = PTR_ERR(handle);
+			if (inode->i_nlink)
+				ext4_orphan_del(NULL, inode);
+
 			goto out;
 		}
 		if (inode->i_nlink)
@@ -3534,7 +3608,7 @@
 {
 	struct inode *inode = io->inode;
 	loff_t offset = io->offset;
-	size_t size = io->size;
+	ssize_t size = io->size;
 	int ret = 0;
 
 	ext4_debug("end_aio_dio_onlock: io 0x%p from inode %lu,list->next 0x%p,"
@@ -3771,8 +3845,8 @@
 		if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
 			ext4_free_io_end(iocb->private);
 			iocb->private = NULL;
-		} else if (ret > 0 && (EXT4_I(inode)->i_state &
-				       EXT4_STATE_DIO_UNWRITTEN)) {
+		} else if (ret > 0 && ext4_test_inode_state(inode,
+						EXT4_STATE_DIO_UNWRITTEN)) {
 			int err;
 			/*
 			 * for non AIO case, since the IO is already
@@ -3782,7 +3856,7 @@
 							     offset, ret);
 			if (err < 0)
 				ret = err;
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
+			ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
 		}
 		return ret;
 	}
@@ -3798,7 +3872,7 @@
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_mapping->host;
 
-	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
 		return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs);
 
 	return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
@@ -4120,6 +4194,8 @@
 			      __le32 *last)
 {
 	__le32 *p;
+	int	is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode);
+
 	if (try_to_extend_transaction(handle, inode)) {
 		if (bh) {
 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
@@ -4150,11 +4226,11 @@
 
 			*p = 0;
 			tbh = sb_find_get_block(inode->i_sb, nr);
-			ext4_forget(handle, 0, inode, tbh, nr);
+			ext4_forget(handle, is_metadata, inode, tbh, nr);
 		}
 	}
 
-	ext4_free_blocks(handle, inode, block_to_free, count, 0);
+	ext4_free_blocks(handle, inode, block_to_free, count, is_metadata);
 }
 
 /**
@@ -4427,10 +4503,12 @@
 	if (!ext4_can_truncate(inode))
 		return;
 
+	ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+
 	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
-		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+		ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
 
-	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
 		ext4_ext_truncate(inode);
 		return;
 	}
@@ -4714,7 +4792,7 @@
 {
 	/* We have all inode data except xattrs in memory here. */
 	return __ext4_get_inode_loc(inode, iloc,
-		!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR));
+		!ext4_test_inode_state(inode, EXT4_STATE_XATTR));
 }
 
 void ext4_set_inode_flags(struct inode *inode)
@@ -4737,20 +4815,26 @@
 /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
 void ext4_get_inode_flags(struct ext4_inode_info *ei)
 {
-	unsigned int flags = ei->vfs_inode.i_flags;
+	unsigned int vfs_fl;
+	unsigned long old_fl, new_fl;
 
-	ei->i_flags &= ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
-			EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|EXT4_DIRSYNC_FL);
-	if (flags & S_SYNC)
-		ei->i_flags |= EXT4_SYNC_FL;
-	if (flags & S_APPEND)
-		ei->i_flags |= EXT4_APPEND_FL;
-	if (flags & S_IMMUTABLE)
-		ei->i_flags |= EXT4_IMMUTABLE_FL;
-	if (flags & S_NOATIME)
-		ei->i_flags |= EXT4_NOATIME_FL;
-	if (flags & S_DIRSYNC)
-		ei->i_flags |= EXT4_DIRSYNC_FL;
+	do {
+		vfs_fl = ei->vfs_inode.i_flags;
+		old_fl = ei->i_flags;
+		new_fl = old_fl & ~(EXT4_SYNC_FL|EXT4_APPEND_FL|
+				EXT4_IMMUTABLE_FL|EXT4_NOATIME_FL|
+				EXT4_DIRSYNC_FL);
+		if (vfs_fl & S_SYNC)
+			new_fl |= EXT4_SYNC_FL;
+		if (vfs_fl & S_APPEND)
+			new_fl |= EXT4_APPEND_FL;
+		if (vfs_fl & S_IMMUTABLE)
+			new_fl |= EXT4_IMMUTABLE_FL;
+		if (vfs_fl & S_NOATIME)
+			new_fl |= EXT4_NOATIME_FL;
+		if (vfs_fl & S_DIRSYNC)
+			new_fl |= EXT4_DIRSYNC_FL;
+	} while (cmpxchg(&ei->i_flags, old_fl, new_fl) != old_fl);
 }
 
 static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
@@ -4781,8 +4865,8 @@
 	struct ext4_iloc iloc;
 	struct ext4_inode *raw_inode;
 	struct ext4_inode_info *ei;
-	struct buffer_head *bh;
 	struct inode *inode;
+	journal_t *journal = EXT4_SB(sb)->s_journal;
 	long ret;
 	int block;
 
@@ -4793,11 +4877,11 @@
 		return inode;
 
 	ei = EXT4_I(inode);
+	iloc.bh = 0;
 
 	ret = __ext4_get_inode_loc(inode, &iloc, 0);
 	if (ret < 0)
 		goto bad_inode;
-	bh = iloc.bh;
 	raw_inode = ext4_raw_inode(&iloc);
 	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
 	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
@@ -4808,7 +4892,7 @@
 	}
 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
 
-	ei->i_state = 0;
+	ei->i_state_flags = 0;
 	ei->i_dir_start_lookup = 0;
 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
 	/* We now have enough fields to check if the inode was active or not.
@@ -4820,7 +4904,6 @@
 		if (inode->i_mode == 0 ||
 		    !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
 			/* this inode is deleted */
-			brelse(bh);
 			ret = -ESTALE;
 			goto bad_inode;
 		}
@@ -4837,6 +4920,9 @@
 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
 	inode->i_size = ext4_isize(raw_inode);
 	ei->i_disksize = inode->i_size;
+#ifdef CONFIG_QUOTA
+	ei->i_reserved_quota = 0;
+#endif
 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
 	ei->i_block_group = iloc.block_group;
 	ei->i_last_alloc_group = ~0;
@@ -4848,11 +4934,35 @@
 		ei->i_data[block] = raw_inode->i_block[block];
 	INIT_LIST_HEAD(&ei->i_orphan);
 
+	/*
+	 * Set transaction id's of transactions that have to be committed
+	 * to finish f[data]sync. We set them to currently running transaction
+	 * as we cannot be sure that the inode or some of its metadata isn't
+	 * part of the transaction - the inode could have been reclaimed and
+	 * now it is reread from disk.
+	 */
+	if (journal) {
+		transaction_t *transaction;
+		tid_t tid;
+
+		spin_lock(&journal->j_state_lock);
+		if (journal->j_running_transaction)
+			transaction = journal->j_running_transaction;
+		else
+			transaction = journal->j_committing_transaction;
+		if (transaction)
+			tid = transaction->t_tid;
+		else
+			tid = journal->j_commit_sequence;
+		spin_unlock(&journal->j_state_lock);
+		ei->i_sync_tid = tid;
+		ei->i_datasync_tid = tid;
+	}
+
 	if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
 		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
 		if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
 		    EXT4_INODE_SIZE(inode->i_sb)) {
-			brelse(bh);
 			ret = -EIO;
 			goto bad_inode;
 		}
@@ -4865,7 +4975,7 @@
 					EXT4_GOOD_OLD_INODE_SIZE +
 					ei->i_extra_isize;
 			if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
-				ei->i_state |= EXT4_STATE_XATTR;
+				ext4_set_inode_state(inode, EXT4_STATE_XATTR);
 		}
 	} else
 		ei->i_extra_isize = 0;
@@ -4884,10 +4994,7 @@
 
 	ret = 0;
 	if (ei->i_file_acl &&
-	    ((ei->i_file_acl <
-	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
-	       EXT4_SB(sb)->s_gdb_count)) ||
-	     (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
+	    !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
 		ext4_error(sb, __func__,
 			   "bad extended attribute block %llu in inode #%lu",
 			   ei->i_file_acl, inode->i_ino);
@@ -4905,10 +5012,8 @@
 		/* Validate block references which are part of inode */
 		ret = ext4_check_inode_blockref(inode);
 	}
-	if (ret) {
-		brelse(bh);
+	if (ret)
 		goto bad_inode;
-	}
 
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext4_file_inode_operations;
@@ -4936,7 +5041,6 @@
 			init_special_inode(inode, inode->i_mode,
 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
 	} else {
-		brelse(bh);
 		ret = -EIO;
 		ext4_error(inode->i_sb, __func__,
 			   "bogus i_mode (%o) for inode=%lu",
@@ -4949,6 +5053,7 @@
 	return inode;
 
 bad_inode:
+	brelse(iloc.bh);
 	iget_failed(inode);
 	return ERR_PTR(ret);
 }
@@ -4968,7 +5073,7 @@
 		 */
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
 		raw_inode->i_blocks_high = 0;
-		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+		ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
 		return 0;
 	}
 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
@@ -4981,9 +5086,9 @@
 		 */
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
 		raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32);
-		ei->i_flags &= ~EXT4_HUGE_FILE_FL;
+		ext4_clear_inode_flag(inode, EXT4_INODE_HUGE_FILE);
 	} else {
-		ei->i_flags |= EXT4_HUGE_FILE_FL;
+		ext4_set_inode_flag(inode, EXT4_INODE_HUGE_FILE);
 		/* i_block is stored in file system block size */
 		i_blocks = i_blocks >> (inode->i_blkbits - 9);
 		raw_inode->i_blocks_lo   = cpu_to_le32(i_blocks);
@@ -5010,7 +5115,7 @@
 
 	/* For fields not not tracking in the in-memory inode,
 	 * initialise them to zero for new inodes. */
-	if (ei->i_state & EXT4_STATE_NEW)
+	if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
 
 	ext4_get_inode_flags(ei);
@@ -5074,7 +5179,7 @@
 					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
 			sb->s_dirt = 1;
 			ext4_handle_sync(handle);
-			err = ext4_handle_dirty_metadata(handle, inode,
+			err = ext4_handle_dirty_metadata(handle, NULL,
 					EXT4_SB(sb)->s_sbh);
 		}
 	}
@@ -5103,11 +5208,12 @@
 	}
 
 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
-	rc = ext4_handle_dirty_metadata(handle, inode, bh);
+	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
 	if (!err)
 		err = rc;
-	ei->i_state &= ~EXT4_STATE_NEW;
+	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
 
+	ext4_update_inode_fsync_trans(handle, inode, 0);
 out_brelse:
 	brelse(bh);
 	ext4_std_error(inode->i_sb, err);
@@ -5170,7 +5276,7 @@
 	} else {
 		struct ext4_iloc iloc;
 
-		err = ext4_get_inode_loc(inode, &iloc);
+		err = __ext4_get_inode_loc(inode, &iloc, 0);
 		if (err)
 			return err;
 		if (wait)
@@ -5183,6 +5289,7 @@
 				   (unsigned long long)iloc.bh->b_blocknr);
 			err = -EIO;
 		}
+		brelse(iloc.bh);
 	}
 	return err;
 }
@@ -5227,8 +5334,8 @@
 
 		/* (user+group)*(old+new) structure, inode write (sb,
 		 * inode block, ? - but truncate inode update has it) */
-		handle = ext4_journal_start(inode, 2*(EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)+
-					EXT4_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
+		handle = ext4_journal_start(inode, (EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)+
+					EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb))+3);
 		if (IS_ERR(handle)) {
 			error = PTR_ERR(handle);
 			goto err_out;
@@ -5249,7 +5356,7 @@
 	}
 
 	if (attr->ia_valid & ATTR_SIZE) {
-		if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
+		if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
 			struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 
 			if (attr->ia_size > sbi->s_bitmap_maxbytes) {
@@ -5260,7 +5367,9 @@
 	}
 
 	if (S_ISREG(inode->i_mode) &&
-	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
+	    attr->ia_valid & ATTR_SIZE &&
+	    (attr->ia_size < inode->i_size ||
+	     (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))) {
 		handle_t *handle;
 
 		handle = ext4_journal_start(inode, 3);
@@ -5291,6 +5400,9 @@
 				goto err_out;
 			}
 		}
+		/* ext4_truncate will clear the flag */
+		if ((ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)))
+			ext4_truncate(inode);
 	}
 
 	rc = inode_setattr(inode, attr);
@@ -5346,13 +5458,12 @@
 	/* if nrblocks are contiguous */
 	if (chunk) {
 		/*
-		 * With N contiguous data blocks, it need at most
-		 * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
-		 * 2 dindirect blocks
-		 * 1 tindirect block
+		 * With N contiguous data blocks, we need at most
+		 * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
+		 * 2 dindirect blocks, and 1 tindirect block
 		 */
-		indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
-		return indirects + 3;
+		return DIV_ROUND_UP(nrblocks,
+				    EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
 	}
 	/*
 	 * if nrblocks are not contiguous, worse case, each block touch
@@ -5365,7 +5476,7 @@
 
 static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
 {
-	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 		return ext4_indirect_trans_blocks(inode, nrblocks, chunk);
 	return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
 }
@@ -5529,8 +5640,8 @@
 	entry = IFIRST(header);
 
 	/* No extended attributes present */
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) ||
-		header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
+	    header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
 		memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
 			new_extra_isize);
 		EXT4_I(inode)->i_extra_isize = new_extra_isize;
@@ -5574,7 +5685,7 @@
 	err = ext4_reserve_inode_write(handle, inode, &iloc);
 	if (ext4_handle_valid(handle) &&
 	    EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
-	    !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) {
+	    !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
 		/*
 		 * We need extra buffer credits since we may write into EA block
 		 * with this same handle. If journal_extend fails, then it will
@@ -5588,7 +5699,8 @@
 						      sbi->s_want_extra_isize,
 						      iloc, handle);
 			if (ret) {
-				EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
+				ext4_set_inode_state(inode,
+						     EXT4_STATE_NO_EXPAND);
 				if (mnt_count !=
 					le16_to_cpu(sbi->s_es->s_mnt_count)) {
 					ext4_warning(inode->i_sb, __func__,
@@ -5655,7 +5767,7 @@
 			err = jbd2_journal_get_write_access(handle, iloc.bh);
 			if (!err)
 				err = ext4_handle_dirty_metadata(handle,
-								 inode,
+								 NULL,
 								 iloc.bh);
 			brelse(iloc.bh);
 		}
@@ -5699,9 +5811,9 @@
 	 */
 
 	if (val)
-		EXT4_I(inode)->i_flags |= EXT4_JOURNAL_DATA_FL;
+		ext4_set_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
 	else
-		EXT4_I(inode)->i_flags &= ~EXT4_JOURNAL_DATA_FL;
+		ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
 	ext4_set_aops(inode);
 
 	jbd2_journal_unlock_updates(journal);
--- linux-ec2-2.6.32.orig/fs/ext4/extents.c
+++ linux-ec2-2.6.32/fs/ext4/extents.c
@@ -107,11 +107,8 @@
 	if (err <= 0)
 		return err;
 	err = ext4_truncate_restart_trans(handle, inode, needed);
-	/*
-	 * We have dropped i_data_sem so someone might have cached again
-	 * an extent we are going to truncate.
-	 */
-	ext4_ext_invalidate_cache(inode);
+	if (err == 0)
+		err = -EAGAIN;
 
 	return err;
 }
@@ -296,29 +293,44 @@
  * to allocate @blocks
  * Worse case is one block per extent
  */
-int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks)
+int ext4_ext_calc_metadata_amount(struct inode *inode, sector_t lblock)
 {
-	int lcap, icap, rcap, leafs, idxs, num;
-	int newextents = blocks;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	int idxs, num = 0;
 
-	rcap = ext4_ext_space_root_idx(inode, 0);
-	lcap = ext4_ext_space_block(inode, 0);
-	icap = ext4_ext_space_block_idx(inode, 0);
+	idxs = ((inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header))
+		/ sizeof(struct ext4_extent_idx));
 
-	/* number of new leaf blocks needed */
-	num = leafs = (newextents + lcap - 1) / lcap;
+	/*
+	 * If the new delayed allocation block is contiguous with the
+	 * previous da block, it can share index blocks with the
+	 * previous block, so we only need to allocate a new index
+	 * block every idxs leaf blocks.  At ldxs**2 blocks, we need
+	 * an additional index block, and at ldxs**3 blocks, yet
+	 * another index blocks.
+	 */
+	if (ei->i_da_metadata_calc_len &&
+	    ei->i_da_metadata_calc_last_lblock+1 == lblock) {
+		if ((ei->i_da_metadata_calc_len % idxs) == 0)
+			num++;
+		if ((ei->i_da_metadata_calc_len % (idxs*idxs)) == 0)
+			num++;
+		if ((ei->i_da_metadata_calc_len % (idxs*idxs*idxs)) == 0) {
+			num++;
+			ei->i_da_metadata_calc_len = 0;
+		} else
+			ei->i_da_metadata_calc_len++;
+		ei->i_da_metadata_calc_last_lblock++;
+		return num;
+	}
 
 	/*
-	 * Worse case, we need separate index block(s)
-	 * to link all new leaf blocks
+	 * In the worst case we need a new set of index blocks at
+	 * every level of the inode's extent tree.
 	 */
-	idxs = (leafs + icap - 1) / icap;
-	do {
-		num += idxs;
-		idxs = (idxs + icap - 1) / icap;
-	} while (idxs > rcap);
-
-	return num;
+	ei->i_da_metadata_calc_len = 1;
+	ei->i_da_metadata_calc_last_lblock = lblock;
+	return ext_depth(inode) + 1;
 }
 
 static int
@@ -1761,7 +1773,9 @@
 	while (block < last && block != EXT_MAX_BLOCK) {
 		num = last - block;
 		/* find extent for this block */
+		down_read(&EXT4_I(inode)->i_data_sem);
 		path = ext4_ext_find_extent(inode, block, path);
+		up_read(&EXT4_I(inode)->i_data_sem);
 		if (IS_ERR(path)) {
 			err = PTR_ERR(path);
 			path = NULL;
@@ -1934,7 +1948,7 @@
 
 	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
 			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
-	if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+	if (in_range(block, cex->ec_block, cex->ec_len)) {
 		ex->ee_block = cpu_to_le32(cex->ec_block);
 		ext4_ext_store_pblock(ex, cex->ec_start);
 		ex->ee_len = cpu_to_le16(cex->ec_len);
@@ -2074,7 +2088,7 @@
 		ext_debug("free last %u blocks starting %llu\n", num, start);
 		for (i = 0; i < num; i++) {
 			bh = sb_find_get_block(inode->i_sb, start + i);
-			ext4_forget(handle, 0, inode, bh, start + i);
+			ext4_forget(handle, metadata, inode, bh, start + i);
 		}
 		ext4_free_blocks(handle, inode, start, num, metadata);
 	} else if (from == le32_to_cpu(ex->ee_block)
@@ -2167,7 +2181,7 @@
 			correct_index = 1;
 			credits += (ext_depth(inode)) + 1;
 		}
-		credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+		credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb);
 
 		err = ext4_ext_truncate_extend_restart(handle, inode, credits);
 		if (err)
@@ -2246,7 +2260,7 @@
 	int depth = ext_depth(inode);
 	struct ext4_ext_path *path;
 	handle_t *handle;
-	int i = 0, err = 0;
+	int i, err;
 
 	ext_debug("truncate since %u\n", start);
 
@@ -2255,23 +2269,26 @@
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
+again:
 	ext4_ext_invalidate_cache(inode);
 
 	/*
 	 * We start scanning from right side, freeing all the blocks
 	 * after i_size and walking into the tree depth-wise.
 	 */
+	depth = ext_depth(inode);
 	path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS);
 	if (path == NULL) {
 		ext4_journal_stop(handle);
 		return -ENOMEM;
 	}
+	path[0].p_depth = depth;
 	path[0].p_hdr = ext_inode_hdr(inode);
 	if (ext4_ext_check(inode, path[0].p_hdr, depth)) {
 		err = -EIO;
 		goto out;
 	}
-	path[0].p_depth = depth;
+	i = err = 0;
 
 	while (i >= 0 && err == 0) {
 		if (i == depth) {
@@ -2365,6 +2382,8 @@
 out:
 	ext4_ext_drop_refs(path);
 	kfree(path);
+	if (err == -EAGAIN)
+		goto again;
 	ext4_journal_stop(handle);
 
 	return err;
@@ -2429,7 +2448,7 @@
 /* FIXME!! we need to try to merge to left or right after zero-out  */
 static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
 {
-	int ret = -EIO;
+	int ret;
 	struct bio *bio;
 	int blkbits, blocksize;
 	sector_t ee_pblock;
@@ -2453,6 +2472,9 @@
 			len = ee_len;
 
 		bio = bio_alloc(GFP_NOIO, len);
+		if (!bio)
+			return -ENOMEM;
+
 		bio->bi_sector = ee_pblock;
 		bio->bi_bdev   = inode->i_sb->s_bdev;
 
@@ -2480,17 +2502,15 @@
 		submit_bio(WRITE, bio);
 		wait_for_completion(&event);
 
-		if (test_bit(BIO_UPTODATE, &bio->bi_flags))
-			ret = 0;
-		else {
-			ret = -EIO;
-			break;
+		if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+			bio_put(bio);
+			return -EIO;
 		}
 		bio_put(bio);
 		ee_len    -= done;
 		ee_pblock += done  << (blkbits - 9);
 	}
-	return ret;
+	return 0;
 }
 
 #define EXT4_EXT_ZERO_LEN 7
@@ -2515,11 +2535,21 @@
 	struct ext4_extent *ex2 = NULL;
 	struct ext4_extent *ex3 = NULL;
 	struct ext4_extent_header *eh;
-	ext4_lblk_t ee_block;
+	ext4_lblk_t ee_block, eof_block;
 	unsigned int allocated, ee_len, depth;
 	ext4_fsblk_t newblock;
 	int err = 0;
 	int ret = 0;
+	int may_zeroout;
+
+	ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
+		"block %llu, max_blocks %u\n", inode->i_ino,
+		(unsigned long long)iblock, max_blocks);
+
+	eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+		inode->i_sb->s_blocksize_bits;
+	if (eof_block < iblock + max_blocks)
+		eof_block = iblock + max_blocks;
 
 	depth = ext_depth(inode);
 	eh = path[depth].p_hdr;
@@ -2528,16 +2558,23 @@
 	ee_len = ext4_ext_get_actual_len(ex);
 	allocated = ee_len - (iblock - ee_block);
 	newblock = iblock - ee_block + ext_pblock(ex);
+
 	ex2 = ex;
 	orig_ex.ee_block = ex->ee_block;
 	orig_ex.ee_len   = cpu_to_le16(ee_len);
 	ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
 
+	/*
+	 * It is safe to convert extent to initialized via explicit
+	 * zeroout only if extent is fully insde i_size or new_size.
+	 */
+	may_zeroout = ee_block + ee_len <= eof_block;
+
 	err = ext4_ext_get_access(handle, inode, path + depth);
 	if (err)
 		goto out;
 	/* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */
-	if (ee_len <= 2*EXT4_EXT_ZERO_LEN) {
+	if (ee_len <= 2*EXT4_EXT_ZERO_LEN && may_zeroout) {
 		err =  ext4_ext_zeroout(inode, &orig_ex);
 		if (err)
 			goto fix_extent_len;
@@ -2568,7 +2605,7 @@
 	if (allocated > max_blocks) {
 		unsigned int newdepth;
 		/* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */
-		if (allocated <= EXT4_EXT_ZERO_LEN) {
+		if (allocated <= EXT4_EXT_ZERO_LEN && may_zeroout) {
 			/*
 			 * iblock == ee_block is handled by the zerouout
 			 * at the beginning.
@@ -2644,7 +2681,7 @@
 		ex3->ee_len = cpu_to_le16(allocated - max_blocks);
 		ext4_ext_mark_uninitialized(ex3);
 		err = ext4_ext_insert_extent(handle, inode, path, ex3, 0);
-		if (err == -ENOSPC) {
+		if (err == -ENOSPC && may_zeroout) {
 			err =  ext4_ext_zeroout(inode, &orig_ex);
 			if (err)
 				goto fix_extent_len;
@@ -2668,8 +2705,10 @@
 		 * update the extent length after successful insert of the
 		 * split extent
 		 */
-		orig_ex.ee_len = cpu_to_le16(ee_len -
-						ext4_ext_get_actual_len(ex3));
+		ee_len -= ext4_ext_get_actual_len(ex3);
+		orig_ex.ee_len = cpu_to_le16(ee_len);
+		may_zeroout = ee_block + ee_len <= eof_block;
+
 		depth = newdepth;
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode, iblock, path);
@@ -2693,7 +2732,7 @@
 		 * otherwise give the extent a chance to merge to left
 		 */
 		if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN &&
-							iblock != ee_block) {
+			iblock != ee_block && may_zeroout) {
 			err =  ext4_ext_zeroout(inode, &orig_ex);
 			if (err)
 				goto fix_extent_len;
@@ -2762,7 +2801,7 @@
 	goto out;
 insert:
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, 0);
-	if (err == -ENOSPC) {
+	if (err == -ENOSPC && may_zeroout) {
 		err =  ext4_ext_zeroout(inode, &orig_ex);
 		if (err)
 			goto fix_extent_len;
@@ -2822,14 +2861,21 @@
 	struct ext4_extent *ex2 = NULL;
 	struct ext4_extent *ex3 = NULL;
 	struct ext4_extent_header *eh;
-	ext4_lblk_t ee_block;
+	ext4_lblk_t ee_block, eof_block;
 	unsigned int allocated, ee_len, depth;
 	ext4_fsblk_t newblock;
 	int err = 0;
+	int may_zeroout;
+
+	ext_debug("ext4_split_unwritten_extents: inode %lu, logical"
+		"block %llu, max_blocks %u\n", inode->i_ino,
+		(unsigned long long)iblock, max_blocks);
+
+	eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
+		inode->i_sb->s_blocksize_bits;
+	if (eof_block < iblock + max_blocks)
+		eof_block = iblock + max_blocks;
 
-	ext_debug("ext4_split_unwritten_extents: inode %lu,"
-		  "iblock %llu, max_blocks %u\n", inode->i_ino,
-		  (unsigned long long)iblock, max_blocks);
 	depth = ext_depth(inode);
 	eh = path[depth].p_hdr;
 	ex = path[depth].p_ext;
@@ -2837,12 +2883,19 @@
 	ee_len = ext4_ext_get_actual_len(ex);
 	allocated = ee_len - (iblock - ee_block);
 	newblock = iblock - ee_block + ext_pblock(ex);
+
 	ex2 = ex;
 	orig_ex.ee_block = ex->ee_block;
 	orig_ex.ee_len   = cpu_to_le16(ee_len);
 	ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
 
 	/*
+	 * It is safe to convert extent to initialized via explicit
+	 * zeroout only if extent is fully insde i_size or new_size.
+	 */
+	may_zeroout = ee_block + ee_len <= eof_block;
+
+	/*
  	 * If the uninitialized extent begins at the same logical
  	 * block where the write begins, and the write completely
  	 * covers the extent, then we don't need to split it.
@@ -2876,7 +2929,7 @@
 		ex3->ee_len = cpu_to_le16(allocated - max_blocks);
 		ext4_ext_mark_uninitialized(ex3);
 		err = ext4_ext_insert_extent(handle, inode, path, ex3, flags);
-		if (err == -ENOSPC) {
+		if (err == -ENOSPC && may_zeroout) {
 			err =  ext4_ext_zeroout(inode, &orig_ex);
 			if (err)
 				goto fix_extent_len;
@@ -2900,8 +2953,10 @@
 		 * update the extent length after successful insert of the
 		 * split extent
 		 */
-		orig_ex.ee_len = cpu_to_le16(ee_len -
-						ext4_ext_get_actual_len(ex3));
+		ee_len -= ext4_ext_get_actual_len(ex3);
+		orig_ex.ee_len = cpu_to_le16(ee_len);
+		may_zeroout = ee_block + ee_len <= eof_block;
+
 		depth = newdepth;
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode, iblock, path);
@@ -2947,7 +3002,7 @@
 	goto out;
 insert:
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
-	if (err == -ENOSPC) {
+	if (err == -ENOSPC && may_zeroout) {
 		err =  ext4_ext_zeroout(inode, &orig_ex);
 		if (err)
 			goto fix_extent_len;
@@ -3027,6 +3082,14 @@
 	return err;
 }
 
+static void unmap_underlying_metadata_blocks(struct block_device *bdev,
+			sector_t block, int count)
+{
+	int i;
+	for (i = 0; i < count; i++)
+                unmap_underlying_metadata(bdev, block + i);
+}
+
 static int
 ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
 			ext4_lblk_t iblock, unsigned int max_blocks,
@@ -3057,13 +3120,15 @@
 		if (io)
 			io->flag = DIO_AIO_UNWRITTEN;
 		else
-			EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN;
+			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
 		goto out;
 	}
 	/* async DIO end_io complete, convert the filled extent to written */
 	if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) {
 		ret = ext4_convert_unwritten_extents_dio(handle, inode,
 							path);
+		if (ret >= 0)
+			ext4_update_inode_fsync_trans(handle, inode, 1);
 		goto out2;
 	}
 	/* buffered IO case */
@@ -3091,6 +3156,8 @@
 	ret = ext4_ext_convert_to_initialized(handle, inode,
 						path, iblock,
 						max_blocks);
+	if (ret >= 0)
+		ext4_update_inode_fsync_trans(handle, inode, 1);
 out:
 	if (ret <= 0) {
 		err = ret;
@@ -3098,6 +3165,30 @@
 	} else
 		allocated = ret;
 	set_buffer_new(bh_result);
+	/*
+	 * if we allocated more blocks than requested
+	 * we need to make sure we unmap the extra block
+	 * allocated. The actual needed block will get
+	 * unmapped later when we find the buffer_head marked
+	 * new.
+	 */
+	if (allocated > max_blocks) {
+		unmap_underlying_metadata_blocks(inode->i_sb->s_bdev,
+					newblock + max_blocks,
+					allocated - max_blocks);
+		allocated = max_blocks;
+	}
+
+	/*
+	 * If we have done fallocate with the offset that is already
+	 * delayed allocated, we would have block reservation
+	 * and quota reservation done in the delayed write path.
+	 * But fallocate would have already updated quota and block
+	 * count for this offset. So cancel these reservation
+	 */
+	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+		ext4_da_update_reserve_space(inode, allocated, 0);
+
 map_out:
 	set_buffer_mapped(bh_result);
 out1:
@@ -3138,9 +3229,9 @@
 {
 	struct ext4_ext_path *path = NULL;
 	struct ext4_extent_header *eh;
-	struct ext4_extent newex, *ex;
+	struct ext4_extent newex, *ex, *last_ex;
 	ext4_fsblk_t newblock;
-	int err = 0, depth, ret, cache_type;
+	int i, err = 0, depth, ret, cache_type;
 	unsigned int allocated = 0;
 	struct ext4_allocation_request ar;
 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
@@ -3190,7 +3281,13 @@
 	 * this situation is possible, though, _during_ tree modification;
 	 * this is why assert can't be put in ext4_ext_find_extent()
 	 */
-	BUG_ON(path[depth].p_ext == NULL && depth != 0);
+	if (path[depth].p_ext == NULL && depth != 0) {
+		ext4_error(inode->i_sb, __func__, "bad extent address "
+			   "inode: %lu, iblock: %lu, depth: %d",
+			   inode->i_ino, (unsigned long) iblock, depth);
+		err = -EIO;
+		goto out2;
+	}
 	eh = path[depth].p_hdr;
 
 	ex = path[depth].p_ext;
@@ -3205,7 +3302,7 @@
 		 */
 		ee_len = ext4_ext_get_actual_len(ex);
 		/* if found extent covers block, simply return it */
-		if (iblock >= ee_block && iblock < ee_block + ee_len) {
+		if (in_range(iblock, ee_block, ee_len)) {
 			newblock = iblock - ee_block + ee_start;
 			/* number of remaining blocks in the extent */
 			allocated = ee_len - (iblock - ee_block);
@@ -3309,9 +3406,35 @@
 			if (io)
 				io->flag = DIO_AIO_UNWRITTEN;
 			else
-				EXT4_I(inode)->i_state |=
-					EXT4_STATE_DIO_UNWRITTEN;;
+				ext4_set_inode_state(inode,
+						     EXT4_STATE_DIO_UNWRITTEN);
+		}
+	}
+
+	if (unlikely(ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS))) {
+		if (unlikely(!eh->eh_entries)) {
+			ext4_error(inode->i_sb, __func__,
+				   "inode#%lu, eh->eh_entries = 0 and "
+				   "EOFBLOCKS_FL set", inode->i_ino);
+			err = -EIO;
+			goto out2;
+		}
+		last_ex = EXT_LAST_EXTENT(eh);
+		/*
+		 * If the current leaf block was reached by looking at
+		 * the last index block all the way down the tree, and
+		 * we are extending the inode beyond the last extent
+		 * in the current leaf block, then clear the
+		 * EOFBLOCKS_FL flag.
+		 */
+		for (i = depth-1; i >= 0; i--) {
+			if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr))
+				break;
 		}
+		if ((i < 0) &&
+		    (iblock + ar.len > le32_to_cpu(last_ex->ee_block) +
+		     ext4_ext_get_actual_len(last_ex)))
+			ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
 	}
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
 	if (err) {
@@ -3327,12 +3450,27 @@
 	/* previous routine could use block we allocated */
 	newblock = ext_pblock(&newex);
 	allocated = ext4_ext_get_actual_len(&newex);
+	if (allocated > max_blocks)
+		allocated = max_blocks;
 	set_buffer_new(bh_result);
 
-	/* Cache only when it is _not_ an uninitialized extent */
-	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0)
+	/*
+	 * Update reserved blocks/metadata blocks after successful
+	 * block allocation which had been deferred till now.
+	 */
+	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+		ext4_da_update_reserve_space(inode, allocated, 1);
+
+	/*
+	 * Cache the extent and update transaction to commit on fdatasync only
+	 * when it is _not_ an uninitialized extent.
+	 */
+	if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) {
 		ext4_ext_put_in_cache(inode, iblock, allocated, newblock,
 						EXT4_EXT_CACHE_EXTENT);
+		ext4_update_inode_fsync_trans(handle, inode, 1);
+	} else
+		ext4_update_inode_fsync_trans(handle, inode, 0);
 out:
 	if (allocated > max_blocks)
 		allocated = max_blocks;
@@ -3431,6 +3569,13 @@
 			i_size_write(inode, new_size);
 		if (new_size > EXT4_I(inode)->i_disksize)
 			ext4_update_i_disksize(inode, new_size);
+	} else {
+		/*
+		 * Mark that we allocate beyond EOF so the subsequent truncate
+		 * can proceed even if the new size is the same as i_size.
+		 */
+		if (new_size > i_size_read(inode))
+			ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
 	}
 
 }
@@ -3458,7 +3603,7 @@
 	 * currently supporting (pre)allocate mode for extent-based
 	 * files _only_
 	 */
-	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 		return -EOPNOTSUPP;
 
 	/* preallocation to directories is currently not supported */
@@ -3477,6 +3622,11 @@
 	 */
 	credits = ext4_chunk_trans_blocks(inode, max_blocks);
 	mutex_lock(&inode->i_mutex);
+	ret = inode_newsize_ok(inode, (len + offset));
+	if (ret) {
+		mutex_unlock(&inode->i_mutex);
+		return ret;
+	}
 retry:
 	while (ret >= 0 && ret < max_blocks) {
 		block = block + ret;
@@ -3535,7 +3685,7 @@
  * Returns 0 on success.
  */
 int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
-				    loff_t len)
+				    ssize_t len)
 {
 	handle_t *handle;
 	ext4_lblk_t block;
@@ -3671,7 +3821,7 @@
 	int error = 0;
 
 	/* in-inode? */
-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
 		struct ext4_iloc iloc;
 		int offset;	/* offset of xattr in inode */
 
@@ -3684,6 +3834,7 @@
 		physical += offset;
 		length = EXT4_SB(inode->i_sb)->s_inode_size - offset;
 		flags |= FIEMAP_EXTENT_DATA_INLINE;
+		brelse(iloc.bh);
 	} else { /* external block */
 		physical = EXT4_I(inode)->i_file_acl << blockbits;
 		length = inode->i_sb->s_blocksize;
@@ -3699,11 +3850,10 @@
 		__u64 start, __u64 len)
 {
 	ext4_lblk_t start_blk;
-	ext4_lblk_t len_blks;
 	int error = 0;
 
 	/* fallback to generic here if not in extents fmt */
-	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 		return generic_block_fiemap(inode, fieinfo, start, len,
 			ext4_get_block);
 
@@ -3713,17 +3863,21 @@
 	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
 		error = ext4_xattr_fiemap(inode, fieinfo);
 	} else {
+		ext4_lblk_t len_blks;
+		__u64 last_blk;
+
 		start_blk = start >> inode->i_sb->s_blocksize_bits;
-		len_blks = len >> inode->i_sb->s_blocksize_bits;
+		last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits;
+		if (last_blk >= EXT_MAX_BLOCK)
+			last_blk = EXT_MAX_BLOCK-1;
+		len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1;
 
 		/*
 		 * Walk the extent tree gathering extent information.
 		 * ext4_ext_fiemap_cb will push extents back to user.
 		 */
-		down_read(&EXT4_I(inode)->i_data_sem);
 		error = ext4_ext_walk_space(inode, start_blk, len_blks,
 					  ext4_ext_fiemap_cb, fieinfo);
-		up_read(&EXT4_I(inode)->i_data_sem);
 	}
 
 	return error;
--- linux-ec2-2.6.32.orig/fs/ext4/ioctl.c
+++ linux-ec2-2.6.32/fs/ext4/ioctl.c
@@ -92,6 +92,15 @@
 			flags &= ~EXT4_EXTENTS_FL;
 		}
 
+		if (flags & EXT4_EOFBLOCKS_FL) {
+			/* we don't support adding EOFBLOCKS flag */
+			if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
+				err = -EOPNOTSUPP;
+				goto flags_out;
+			}
+		} else if (oldflags & EXT4_EOFBLOCKS_FL)
+			ext4_truncate(inode);
+
 		handle = ext4_journal_start(inode, 1);
 		if (IS_ERR(handle)) {
 			err = PTR_ERR(handle);
@@ -221,31 +230,39 @@
 		struct file *donor_filp;
 		int err;
 
+		if (!(filp->f_mode & FMODE_READ) ||
+		    !(filp->f_mode & FMODE_WRITE))
+			return -EBADF;
+
 		if (copy_from_user(&me,
 			(struct move_extent __user *)arg, sizeof(me)))
 			return -EFAULT;
+		me.moved_len = 0;
 
 		donor_filp = fget(me.donor_fd);
 		if (!donor_filp)
 			return -EBADF;
 
-		if (!capable(CAP_DAC_OVERRIDE)) {
-			if ((current->real_cred->fsuid != inode->i_uid) ||
-				!(inode->i_mode & S_IRUSR) ||
-				!(donor_filp->f_dentry->d_inode->i_mode &
-				S_IRUSR)) {
-				fput(donor_filp);
-				return -EACCES;
-			}
+		if (!(donor_filp->f_mode & FMODE_WRITE)) {
+			err = -EBADF;
+			goto mext_out;
 		}
 
+		err = mnt_want_write(filp->f_path.mnt);
+		if (err)
+			goto mext_out;
+
 		err = ext4_move_extents(filp, donor_filp, me.orig_start,
 					me.donor_start, me.len, &me.moved_len);
-		fput(donor_filp);
-
-		if (copy_to_user((struct move_extent *)arg, &me, sizeof(me)))
-			return -EFAULT;
+		mnt_drop_write(filp->f_path.mnt);
+		if (me.moved_len > 0)
+			file_remove_suid(donor_filp);
 
+		if (copy_to_user((struct move_extent __user *)arg,
+				 &me, sizeof(me)))
+			err = -EFAULT;
+mext_out:
+		fput(donor_filp);
 		return err;
 	}
 
@@ -356,7 +373,30 @@
 	case EXT4_IOC32_SETRSVSZ:
 		cmd = EXT4_IOC_SETRSVSZ;
 		break;
-	case EXT4_IOC_GROUP_ADD:
+	case EXT4_IOC32_GROUP_ADD: {
+		struct compat_ext4_new_group_input __user *uinput;
+		struct ext4_new_group_input input;
+		mm_segment_t old_fs;
+		int err;
+
+		uinput = compat_ptr(arg);
+		err = get_user(input.group, &uinput->group);
+		err |= get_user(input.block_bitmap, &uinput->block_bitmap);
+		err |= get_user(input.inode_bitmap, &uinput->inode_bitmap);
+		err |= get_user(input.inode_table, &uinput->inode_table);
+		err |= get_user(input.blocks_count, &uinput->blocks_count);
+		err |= get_user(input.reserved_blocks,
+				&uinput->reserved_blocks);
+		if (err)
+			return -EFAULT;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD,
+				 (unsigned long) &input);
+		set_fs(old_fs);
+		return err;
+	}
+	case EXT4_IOC_MOVE_EXT:
 		break;
 	default:
 		return -ENOIOCTLCMD;
--- linux-ec2-2.6.32.orig/fs/ext4/migrate.c
+++ linux-ec2-2.6.32/fs/ext4/migrate.c
@@ -238,7 +238,7 @@
 	 * So allocate a credit of 3. We may update
 	 * quota (user and group).
 	 */
-	needed = 3 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+	needed = 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb);
 
 	if (ext4_journal_extend(handle, needed) != 0)
 		retval = ext4_journal_restart(handle, needed);
@@ -357,12 +357,12 @@
 	 * happened after we started the migrate. We need to
 	 * fail the migrate
 	 */
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_EXT_MIGRATE)) {
+	if (!ext4_test_inode_state(inode, EXT4_STATE_EXT_MIGRATE)) {
 		retval = -EAGAIN;
 		up_write(&EXT4_I(inode)->i_data_sem);
 		goto err_out;
 	} else
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+		ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 	/*
 	 * We have the extent map build with the tmp inode.
 	 * Now copy the i_data across
@@ -465,7 +465,7 @@
 	 */
 	if (!EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
 				       EXT4_FEATURE_INCOMPAT_EXTENTS) ||
-	    (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+	    (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
 		return -EINVAL;
 
 	if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)
@@ -477,7 +477,7 @@
 	handle = ext4_journal_start(inode,
 					EXT4_DATA_TRANS_BLOCKS(inode->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2 * EXT4_QUOTA_INIT_BLOCKS(inode->i_sb)
+					EXT4_MAXQUOTAS_INIT_BLOCKS(inode->i_sb)
 					+ 1);
 	if (IS_ERR(handle)) {
 		retval = PTR_ERR(handle);
@@ -494,14 +494,10 @@
 	}
 	i_size_write(tmp_inode, i_size_read(inode));
 	/*
-	 * We don't want the inode to be reclaimed
-	 * if we got interrupted in between. We have
-	 * this tmp inode carrying reference to the
-	 * data blocks of the original file. We set
-	 * the i_nlink to zero at the last stage after
-	 * switching the original file to extent format
+	 * Set the i_nlink to zero so it will be deleted later
+	 * when we drop inode reference.
 	 */
-	tmp_inode->i_nlink = 1;
+	tmp_inode->i_nlink = 0;
 
 	ext4_ext_tree_init(handle, tmp_inode);
 	ext4_orphan_add(handle, tmp_inode);
@@ -524,10 +520,20 @@
 	 * allocation.
 	 */
 	down_read((&EXT4_I(inode)->i_data_sem));
-	EXT4_I(inode)->i_state |= EXT4_STATE_EXT_MIGRATE;
+	ext4_set_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 	up_read((&EXT4_I(inode)->i_data_sem));
 
 	handle = ext4_journal_start(inode, 1);
+	if (IS_ERR(handle)) {
+		/*
+		 * It is impossible to update on-disk structures without
+		 * a handle, so just rollback in-core changes and live other
+		 * work to orphan_list_cleanup()
+		 */
+		ext4_orphan_del(NULL, tmp_inode);
+		retval = PTR_ERR(handle);
+		goto out;
+	}
 
 	ei = EXT4_I(inode);
 	i_data = ei->i_data;
@@ -609,15 +615,8 @@
 
 	/* Reset the extent details */
 	ext4_ext_tree_init(handle, tmp_inode);
-
-	/*
-	 * Set the i_nlink to zero so that
-	 * generic_drop_inode really deletes the
-	 * inode
-	 */
-	tmp_inode->i_nlink = 0;
-
 	ext4_journal_stop(handle);
+out:
 	unlock_new_inode(tmp_inode);
 	iput(tmp_inode);
 
--- linux-ec2-2.6.32.orig/fs/ext4/mballoc.h
+++ linux-ec2-2.6.32/fs/ext4/mballoc.h
@@ -221,8 +221,6 @@
 #define EXT4_MB_BITMAP(e4b)	((e4b)->bd_bitmap)
 #define EXT4_MB_BUDDY(e4b)	((e4b)->bd_buddy)
 
-#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
-
 static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
 					struct ext4_free_extent *fex)
 {
--- linux-ec2-2.6.32.orig/fs/ext4/balloc.c
+++ linux-ec2-2.6.32/fs/ext4/balloc.c
@@ -189,9 +189,6 @@
  * when a file system is mounted (see ext4_fill_super).
  */
 
-
-#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
-
 /**
  * ext4_get_group_desc() -- load group descriptor from disk
  * @sb:			super block
@@ -761,7 +758,13 @@
 static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
 					ext4_group_t group)
 {
-	return ext4_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0;
+	if (!ext4_bg_has_super(sb, group))
+		return 0;
+
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG))
+		return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
+	else
+		return EXT4_SB(sb)->s_gdb_count;
 }
 
 /**
--- linux-ec2-2.6.32.orig/fs/ext4/ext4.h
+++ linux-ec2-2.6.32/fs/ext4/ext4.h
@@ -29,6 +29,9 @@
 #include <linux/wait.h>
 #include <linux/blockgroup_lock.h>
 #include <linux/percpu_counter.h>
+#ifdef __KERNEL__
+#include <linux/compat.h>
+#endif
 
 /*
  * The fourth extended filesystem constants/structures
@@ -139,8 +142,8 @@
 	struct inode		*inode;		/* file being written to */
 	unsigned int		flag;		/* unwritten or not */
 	int			error;		/* I/O error code */
-	ext4_lblk_t		offset;		/* offset in the file */
-	size_t			size;		/* size of the extent */
+	loff_t			offset;		/* offset in the file */
+	ssize_t			size;		/* size of the extent */
 	struct work_struct	work;		/* data work queue */
 } ext4_io_end_t;
 
@@ -284,10 +287,12 @@
 #define EXT4_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
 #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
 #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
+#define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
+#define EXT4_EOFBLOCKS_FL		0x00400000 /* Blocks allocated beyond EOF */
 #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
 
-#define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
-#define EXT4_FL_USER_MODIFIABLE		0x000B80FF /* User modifiable flags */
+#define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
+#define EXT4_FL_USER_MODIFIABLE		0x004B80FF /* User modifiable flags */
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
@@ -314,15 +319,81 @@
 }
 
 /*
- * Inode dynamic state flags
+ * Inode flags used for atomic set/get
+ */
+enum {
+	EXT4_INODE_SECRM	= 0,	/* Secure deletion */
+	EXT4_INODE_UNRM		= 1,	/* Undelete */
+	EXT4_INODE_COMPR	= 2,	/* Compress file */
+	EXT4_INODE_SYNC		= 3,	/* Synchronous updates */
+	EXT4_INODE_IMMUTABLE	= 4,	/* Immutable file */
+	EXT4_INODE_APPEND	= 5,	/* writes to file may only append */
+	EXT4_INODE_NODUMP	= 6,	/* do not dump file */
+	EXT4_INODE_NOATIME	= 7,	/* do not update atime */
+/* Reserved for compression usage... */
+	EXT4_INODE_DIRTY	= 8,
+	EXT4_INODE_COMPRBLK	= 9,	/* One or more compressed clusters */
+	EXT4_INODE_NOCOMPR	= 10,	/* Don't compress */
+	EXT4_INODE_ECOMPR	= 11,	/* Compression error */
+/* End compression flags --- maybe not all used */
+	EXT4_INODE_INDEX	= 12,	/* hash-indexed directory */
+	EXT4_INODE_IMAGIC	= 13,	/* AFS directory */
+	EXT4_INODE_JOURNAL_DATA	= 14,	/* file data should be journaled */
+	EXT4_INODE_NOTAIL	= 15,	/* file tail should not be merged */
+	EXT4_INODE_DIRSYNC	= 16,	/* dirsync behaviour (directories only) */
+	EXT4_INODE_TOPDIR	= 17,	/* Top of directory hierarchies*/
+	EXT4_INODE_HUGE_FILE	= 18,	/* Set to each huge file */
+	EXT4_INODE_EXTENTS	= 19,	/* Inode uses extents */
+	EXT4_INODE_EA_INODE	= 21,	/* Inode used for large EA */
+	EXT4_INODE_EOFBLOCKS	= 22,	/* Blocks allocated beyond EOF */
+	EXT4_INODE_RESERVED	= 31,	/* reserved for ext4 lib */
+};
+
+#define TEST_FLAG_VALUE(FLAG) (EXT4_##FLAG##_FL == (1 << EXT4_INODE_##FLAG))
+#define CHECK_FLAG_VALUE(FLAG) if (!TEST_FLAG_VALUE(FLAG)) { \
+	printk(KERN_EMERG "EXT4 flag fail: " #FLAG ": %d %d\n", \
+		EXT4_##FLAG##_FL, EXT4_INODE_##FLAG); BUG_ON(1); }
+
+/*
+ * Since it's pretty easy to mix up bit numbers and hex values, and we
+ * can't do a compile-time test for ENUM values, we use a run-time
+ * test to make sure that EXT4_XXX_FL is consistent with respect to
+ * EXT4_INODE_XXX.  If all is well the printk and BUG_ON will all drop
+ * out so it won't cost any extra space in the compiled kernel image.
+ * But it's important that these values are the same, since we are
+ * using EXT4_INODE_XXX to test for the flag values, but EXT4_XX_FL
+ * must be consistent with the values of FS_XXX_FL defined in
+ * include/linux/fs.h and the on-disk values found in ext2, ext3, and
+ * ext4 filesystems, and of course the values defined in e2fsprogs.
+ *
+ * It's not paranoia if the Murphy's Law really *is* out to get you.  :-)
  */
-#define EXT4_STATE_JDATA		0x00000001 /* journaled data exists */
-#define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
-#define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
-#define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
-#define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
-#define EXT4_STATE_EXT_MIGRATE		0x00000020 /* Inode is migrating */
-#define EXT4_STATE_DIO_UNWRITTEN	0x00000040 /* need convert on dio done*/
+static inline void ext4_check_flag_values(void)
+{
+	CHECK_FLAG_VALUE(SECRM);
+	CHECK_FLAG_VALUE(UNRM);
+	CHECK_FLAG_VALUE(COMPR);
+	CHECK_FLAG_VALUE(SYNC);
+	CHECK_FLAG_VALUE(IMMUTABLE);
+	CHECK_FLAG_VALUE(APPEND);
+	CHECK_FLAG_VALUE(NODUMP);
+	CHECK_FLAG_VALUE(NOATIME);
+	CHECK_FLAG_VALUE(DIRTY);
+	CHECK_FLAG_VALUE(COMPRBLK);
+	CHECK_FLAG_VALUE(NOCOMPR);
+	CHECK_FLAG_VALUE(ECOMPR);
+	CHECK_FLAG_VALUE(INDEX);
+	CHECK_FLAG_VALUE(IMAGIC);
+	CHECK_FLAG_VALUE(JOURNAL_DATA);
+	CHECK_FLAG_VALUE(NOTAIL);
+	CHECK_FLAG_VALUE(DIRSYNC);
+	CHECK_FLAG_VALUE(TOPDIR);
+	CHECK_FLAG_VALUE(HUGE_FILE);
+	CHECK_FLAG_VALUE(EXTENTS);
+	CHECK_FLAG_VALUE(EA_INODE);
+	CHECK_FLAG_VALUE(EOFBLOCKS);
+	CHECK_FLAG_VALUE(RESERVED);
+}
 
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
@@ -335,6 +406,18 @@
 	__u16 unused;
 };
 
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+struct compat_ext4_new_group_input {
+	u32 group;
+	compat_u64 block_bitmap;
+	compat_u64 inode_bitmap;
+	compat_u64 inode_table;
+	u32 blocks_count;
+	u16 reserved_blocks;
+	u16 unused;
+};
+#endif
+
 /* The struct ext4_new_group_input in kernel space, with free_blocks_count */
 struct ext4_new_group_data {
 	__u32 group;
@@ -361,14 +444,11 @@
 	   so set the magic i_delalloc_reserve_flag after taking the 
 	   inode allocation semaphore for */
 #define EXT4_GET_BLOCKS_DELALLOC_RESERVE	0x0004
-	/* Call ext4_da_update_reserve_space() after successfully 
-	   allocating the blocks */
-#define EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE	0x0008
 	/* caller is from the direct IO path, request to creation of an
 	unitialized extents if not allocated, split the uninitialized
 	extent if blocks has been preallocated already*/
-#define EXT4_GET_BLOCKS_DIO			0x0010
-#define EXT4_GET_BLOCKS_CONVERT			0x0020
+#define EXT4_GET_BLOCKS_DIO			0x0008
+#define EXT4_GET_BLOCKS_CONVERT			0x0010
 #define EXT4_GET_BLOCKS_DIO_CREATE_EXT		(EXT4_GET_BLOCKS_DIO|\
 					 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
 	/* Convert extent to initialized after direct IO complete */
@@ -397,6 +477,7 @@
 #define EXT4_IOC_ALLOC_DA_BLKS		_IO('f', 12)
 #define EXT4_IOC_MOVE_EXT		_IOWR('f', 15, struct move_extent)
 
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
  * ioctl commands in 32 bit emulation
  */
@@ -407,11 +488,13 @@
 #define EXT4_IOC32_GETRSVSZ		_IOR('f', 5, int)
 #define EXT4_IOC32_SETRSVSZ		_IOW('f', 6, int)
 #define EXT4_IOC32_GROUP_EXTEND		_IOW('f', 7, unsigned int)
+#define EXT4_IOC32_GROUP_ADD		_IOW('f', 8, struct compat_ext4_new_group_input)
 #ifdef CONFIG_JBD2_DEBUG
 #define EXT4_IOC32_WAIT_FOR_READONLY	_IOR('f', 99, int)
 #endif
 #define EXT4_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
 #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
+#endif
 
 
 /*
@@ -615,9 +698,8 @@
  */
 struct ext4_inode_info {
 	__le32	i_data[15];	/* unconverted */
-	__u32	i_flags;
-	ext4_fsblk_t	i_file_acl;
 	__u32	i_dtime;
+	ext4_fsblk_t	i_file_acl;
 
 	/*
 	 * i_block_group is the number of the block group which contains
@@ -627,7 +709,8 @@
 	 * near to their parent directory's inode.
 	 */
 	ext4_group_t	i_block_group;
-	__u32	i_state;		/* Dynamic state flags for ext4 */
+	unsigned long	i_state_flags;		/* Dynamic state flags */
+	unsigned long	i_flags;
 
 	ext4_lblk_t		i_dir_start_lookup;
 #ifdef CONFIG_EXT4_FS_XATTR
@@ -693,16 +776,29 @@
 	unsigned int i_reserved_meta_blocks;
 	unsigned int i_allocated_meta_blocks;
 	unsigned short i_delalloc_reserved_flag;
+	sector_t i_da_metadata_calc_last_lblock;
+	int i_da_metadata_calc_len;
 
 	/* on-disk additional length */
 	__u16 i_extra_isize;
 
 	spinlock_t i_block_reservation_lock;
+#ifdef CONFIG_QUOTA
+	/* quota space reservation, managed internally by quota code */
+	qsize_t i_reserved_quota;
+#endif
 
 	/* completed async DIOs that might need unwritten extents handling */
 	struct list_head i_aio_dio_complete_list;
 	/* current io_end structure for async DIO write*/
 	ext4_io_end_t *cur_aio_dio;
+
+	/*
+	 * Transactions that contain inode's metadata needed to complete
+	 * fsync and fdatasync, respectively.
+	 */
+	tid_t i_sync_tid;
+	tid_t i_datasync_tid;
 };
 
 /*
@@ -750,6 +846,7 @@
 #define EXT4_MOUNT_DELALLOC		0x8000000 /* Delalloc support */
 #define EXT4_MOUNT_DATA_ERR_ABORT	0x10000000 /* Abort on file data write */
 #define EXT4_MOUNT_BLOCK_VALIDITY	0x20000000 /* Block validity checking */
+#define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
 
 #define clear_opt(o, opt)		o &= ~EXT4_MOUNT_##opt
 #define set_opt(o, opt)			o |= EXT4_MOUNT_##opt
@@ -1033,6 +1130,37 @@
 		(ino >= EXT4_FIRST_INO(sb) &&
 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
 }
+
+/*
+ * Inode dynamic state flags
+ */
+enum {
+	EXT4_STATE_JDATA,		/* journaled data exists */
+	EXT4_STATE_NEW,			/* inode is newly created */
+	EXT4_STATE_XATTR,		/* has in-inode xattrs */
+	EXT4_STATE_NO_EXPAND,		/* No space for expansion */
+	EXT4_STATE_DA_ALLOC_CLOSE,	/* Alloc DA blks on close */
+	EXT4_STATE_EXT_MIGRATE,		/* Inode is migrating */
+	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
+	EXT4_STATE_NEWENTRY,		/* File just added to dir */
+};
+
+#define EXT4_INODE_BIT_FNS(name, field)					\
+static inline int ext4_test_inode_##name(struct inode *inode, int bit)	\
+{									\
+	return test_bit(bit, &EXT4_I(inode)->i_##field);		\
+}									\
+static inline void ext4_set_inode_##name(struct inode *inode, int bit)	\
+{									\
+	set_bit(bit, &EXT4_I(inode)->i_##field);			\
+}									\
+static inline void ext4_clear_inode_##name(struct inode *inode, int bit) \
+{									\
+	clear_bit(bit, &EXT4_I(inode)->i_##field);			\
+}
+
+EXT4_INODE_BIT_FNS(flag, flags)
+EXT4_INODE_BIT_FNS(state, state_flags)
 #else
 /* Assume that user mode programs are passing in an ext4fs superblock, not
  * a kernel struct super_block.  This will allow us to call the feature-test
@@ -1217,7 +1345,7 @@
 
 #define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
 				      EXT4_FEATURE_COMPAT_DIR_INDEX) && \
-		      (EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
+		    ext4_test_inode_flag((dir), EXT4_INODE_INDEX))
 #define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
 #define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
 
@@ -1424,8 +1552,10 @@
 extern int ext4_block_truncate_page(handle_t *handle,
 		struct address_space *mapping, loff_t from);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern qsize_t ext4_get_reserved_space(struct inode *inode);
+extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int flush_aio_dio_completed_IO(struct inode *inode);
+extern void ext4_da_update_reserve_space(struct inode *inode,
+					int used, int quota_claim);
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
 extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
@@ -1625,6 +1755,7 @@
 	ext4_grpblk_t	bb_first_free;	/* first free block */
 	ext4_grpblk_t	bb_free;	/* total free blocks */
 	ext4_grpblk_t	bb_fragments;	/* nr of freespace fragments */
+	ext4_grpblk_t	bb_largest_free_order;/* order of largest frag in BG */
 	struct          list_head bb_prealloc_list;
 #ifdef DOUBLE_CHECK
 	void            *bb_bitmap;
@@ -1728,7 +1859,7 @@
 extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
 			  loff_t len);
 extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
-			  loff_t len);
+			  ssize_t len);
 extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
 			   sector_t block, unsigned int max_blocks,
 			   struct buffer_head *bh, int flags);
@@ -1757,6 +1888,8 @@
 	set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state);
 }
 
+#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
+
 #endif	/* __KERNEL__ */
 
 #endif	/* _EXT4_H */
--- linux-ec2-2.6.32.orig/fs/ext4/file.c
+++ linux-ec2-2.6.32/fs/ext4/file.c
@@ -35,9 +35,9 @@
  */
 static int ext4_release_file(struct inode *inode, struct file *filp)
 {
-	if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) {
 		ext4_alloc_da_blocks(inode);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
+		ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
 	}
 	/* if we are the last writer on the inode, drop the block reservation */
 	if ((filp->f_mode & FMODE_WRITE) &&
@@ -65,7 +65,7 @@
 	 * is smaller than s_maxbytes, which is for extent-mapped files.
 	 */
 
-	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
+	if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 		size_t length = iov_length(iov, nr_segs);
 
--- linux-ec2-2.6.32.orig/fs/afs/write.c
+++ linux-ec2-2.6.32/fs/afs/write.c
@@ -709,7 +709,6 @@
 {
 	struct address_space *mapping = vnode->vfs_inode.i_mapping;
 	struct writeback_control wbc = {
-		.bdi		= mapping->backing_dev_info,
 		.sync_mode	= WB_SYNC_ALL,
 		.nr_to_write	= LONG_MAX,
 		.range_cyclic	= 1,
--- linux-ec2-2.6.32.orig/fs/jbd/journal.c
+++ linux-ec2-2.6.32/fs/jbd/journal.c
@@ -1913,7 +1913,7 @@
 {
 	jbd_debugfs_dir = debugfs_create_dir("jbd", NULL);
 	if (jbd_debugfs_dir)
-		jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO,
+		jbd_debug = debugfs_create_u8("jbd-debug", S_IRUGO | S_IWUSR,
 					       jbd_debugfs_dir,
 					       &journal_enable_debug);
 }
--- linux-ec2-2.6.32.orig/fs/ubifs/budget.c
+++ linux-ec2-2.6.32/fs/ubifs/budget.c
@@ -62,7 +62,9 @@
  */
 static void shrink_liability(struct ubifs_info *c, int nr_to_write)
 {
+	down_read(&c->vfs_sb->s_umount);
 	writeback_inodes_sb(c->vfs_sb);
+	up_read(&c->vfs_sb->s_umount);
 }
 
 /**
--- linux-ec2-2.6.32.orig/fs/ubifs/debug.c
+++ linux-ec2-2.6.32/fs/ubifs/debug.c
@@ -965,11 +965,39 @@
 void dbg_save_space_info(struct ubifs_info *c)
 {
 	struct ubifs_debug_info *d = c->dbg;
-
-	ubifs_get_lp_stats(c, &d->saved_lst);
+	int freeable_cnt;
 
 	spin_lock(&c->space_lock);
+	memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
+
+	/*
+	 * We use a dirty hack here and zero out @c->freeable_cnt, because it
+	 * affects the free space calculations, and UBIFS might not know about
+	 * all freeable eraseblocks. Indeed, we know about freeable eraseblocks
+	 * only when we read their lprops, and we do this only lazily, upon the
+	 * need. So at any given point of time @c->freeable_cnt might be not
+	 * exactly accurate.
+	 *
+	 * Just one example about the issue we hit when we did not zero
+	 * @c->freeable_cnt.
+	 * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the
+	 *    amount of free space in @d->saved_free
+	 * 2. We re-mount R/W, which makes UBIFS to read the "lsave"
+	 *    information from flash, where we cache LEBs from various
+	 *    categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()'
+	 *    -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()'
+	 *    -> 'ubifs_get_pnode()' -> 'update_cats()'
+	 *    -> 'ubifs_add_to_cat()').
+	 * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt
+	 *    becomes %1.
+	 * 4. We calculate the amount of free space when the re-mount is
+	 *    finished in 'dbg_check_space_info()' and it does not match
+	 *    @d->saved_free.
+	 */
+	freeable_cnt = c->freeable_cnt;
+	c->freeable_cnt = 0;
 	d->saved_free = ubifs_get_free_space_nolock(c);
+	c->freeable_cnt = freeable_cnt;
 	spin_unlock(&c->space_lock);
 }
 
@@ -986,12 +1014,15 @@
 {
 	struct ubifs_debug_info *d = c->dbg;
 	struct ubifs_lp_stats lst;
-	long long avail, free;
+	long long free;
+	int freeable_cnt;
 
 	spin_lock(&c->space_lock);
-	avail = ubifs_calc_available(c, c->min_idx_lebs);
+	freeable_cnt = c->freeable_cnt;
+	c->freeable_cnt = 0;
+	free = ubifs_get_free_space_nolock(c);
+	c->freeable_cnt = freeable_cnt;
 	spin_unlock(&c->space_lock);
-	free = ubifs_get_free_space(c);
 
 	if (free != d->saved_free) {
 		ubifs_err("free space changed from %lld to %lld",
@@ -2660,19 +2691,19 @@
 	}
 
 	fname = "dump_lprops";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_lprops = dent;
 
 	fname = "dump_budg";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_budg = dent;
 
 	fname = "dump_tnc";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_tnc = dent;
--- linux-ec2-2.6.32.orig/fs/ubifs/lpt.c
+++ linux-ec2-2.6.32/fs/ubifs/lpt.c
@@ -1269,10 +1269,9 @@
 	lnum = branch->lnum;
 	offs = branch->offs;
 	pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
-	if (!pnode) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!pnode)
+		return -ENOMEM;
+
 	if (lnum == 0) {
 		/*
 		 * This pnode was not written which just means that the LEB
--- linux-ec2-2.6.32.orig/fs/ubifs/commit.c
+++ linux-ec2-2.6.32/fs/ubifs/commit.c
@@ -518,7 +518,7 @@
 	size_t sz;
 
 	if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
-		goto out;
+		return 0;
 
 	INIT_LIST_HEAD(&list);
 
--- linux-ec2-2.6.32.orig/fs/ubifs/file.c
+++ linux-ec2-2.6.32/fs/ubifs/file.c
@@ -1311,6 +1311,9 @@
 
 	dbg_gen("syncing inode %lu", inode->i_ino);
 
+	if (inode->i_sb->s_flags & MS_RDONLY)
+		return 0;
+
 	/*
 	 * VFS has already synchronized dirty pages for this inode. Synchronize
 	 * the inode unless this is a 'datasync()' call.
--- linux-ec2-2.6.32.orig/fs/ubifs/recovery.c
+++ linux-ec2-2.6.32/fs/ubifs/recovery.c
@@ -299,6 +299,32 @@
 			goto out_free;
 		}
 		memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
+
+		/*
+		 * We had to recover the master node, which means there was an
+		 * unclean reboot. However, it is possible that the master node
+		 * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
+		 * E.g., consider the following chain of events:
+		 *
+		 * 1. UBIFS was cleanly unmounted, so the master node is clean
+		 * 2. UBIFS is being mounted R/W and starts changing the master
+		 *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
+		 *    so this LEB ends up with some amount of garbage at the
+		 *    end.
+		 * 3. UBIFS is being mounted R/O. We reach this place and
+		 *    recover the master node from the second LEB
+		 *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
+		 *    because we are being mounted R/O. We have to defer the
+		 *    operation.
+		 * 4. However, this master node (@c->mst_node) is marked as
+		 *    clean (since the step 1). And if we just return, the
+		 *    mount code will be confused and won't recover the master
+		 *    node when it is re-mounter R/W later.
+		 *
+		 *    Thus, to force the recovery by marking the master node as
+		 *    dirty.
+		 */
+		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
 	} else {
 		/* Write the recovered master node */
 		c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
--- linux-ec2-2.6.32.orig/fs/jffs2/gc.c
+++ linux-ec2-2.6.32/fs/jffs2/gc.c
@@ -700,7 +700,8 @@
 	struct jffs2_raw_inode ri;
 	struct jffs2_node_frag *last_frag;
 	union jffs2_device_node dev;
-	char *mdata = NULL, mdatalen = 0;
+	char *mdata = NULL;
+	int mdatalen = 0;
 	uint32_t alloclen, ilen;
 	int ret;
 
--- linux-ec2-2.6.32.orig/fs/hfs/catalog.c
+++ linux-ec2-2.6.32/fs/hfs/catalog.c
@@ -289,6 +289,10 @@
 	err = hfs_brec_find(&src_fd);
 	if (err)
 		goto out;
+	if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
+		err = -EIO;
+		goto out;
+	}
 
 	hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
 			    src_fd.entrylength);
--- linux-ec2-2.6.32.orig/fs/hfs/super.c
+++ linux-ec2-2.6.32/fs/hfs/super.c
@@ -409,8 +409,13 @@
 	/* try to get the root inode */
 	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
 	res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
-	if (!res)
+	if (!res) {
+		if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) {
+			res =  -EIO;
+			goto bail;
+		}
 		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
+	}
 	if (res) {
 		hfs_find_exit(&fd);
 		goto bail_no_root;
--- linux-ec2-2.6.32.orig/fs/hfs/dir.c
+++ linux-ec2-2.6.32/fs/hfs/dir.c
@@ -79,6 +79,11 @@
 		filp->f_pos++;
 		/* fall through */
 	case 1:
+		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+			err = -EIO;
+			goto out;
+		}
+
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
 		if (entry.type != HFS_CDR_THD) {
 			printk(KERN_ERR "hfs: bad catalog folder thread\n");
@@ -109,6 +114,12 @@
 			err = -EIO;
 			goto out;
 		}
+
+		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+			err = -EIO;
+			goto out;
+		}
+
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
 		type = entry.type;
 		len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName);
--- linux-ec2-2.6.32.orig/fs/devpts/inode.c
+++ linux-ec2-2.6.32/fs/devpts/inode.c
@@ -517,11 +517,23 @@
 
 struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
 {
+	struct dentry *dentry;
+	struct tty_struct *tty;
+
 	BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
+	/* Ensure dentry has not been deleted by devpts_pty_kill() */
+	dentry = d_find_alias(pts_inode);
+	if (!dentry)
+		return NULL;
+
+	tty = NULL;
 	if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-		return (struct tty_struct *)pts_inode->i_private;
-	return NULL;
+		tty = (struct tty_struct *)pts_inode->i_private;
+
+	dput(dentry);
+
+	return tty;
 }
 
 void devpts_pty_kill(struct tty_struct *tty)
--- linux-ec2-2.6.32.orig/fs/sysfs/inode.c
+++ linux-ec2-2.6.32/fs/sysfs/inode.c
@@ -94,30 +94,29 @@
 		if (!sd_attrs)
 			return -ENOMEM;
 		sd->s_iattr = sd_attrs;
-	} else {
-		/* attributes were changed at least once in past */
-		iattrs = &sd_attrs->ia_iattr;
-
-		if (ia_valid & ATTR_UID)
-			iattrs->ia_uid = iattr->ia_uid;
-		if (ia_valid & ATTR_GID)
-			iattrs->ia_gid = iattr->ia_gid;
-		if (ia_valid & ATTR_ATIME)
-			iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
-					inode->i_sb->s_time_gran);
-		if (ia_valid & ATTR_MTIME)
-			iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
-					inode->i_sb->s_time_gran);
-		if (ia_valid & ATTR_CTIME)
-			iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
-					inode->i_sb->s_time_gran);
-		if (ia_valid & ATTR_MODE) {
-			umode_t mode = iattr->ia_mode;
-
-			if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-				mode &= ~S_ISGID;
-			iattrs->ia_mode = sd->s_mode = mode;
-		}
+	}
+	/* attributes were changed at least once in past */
+	iattrs = &sd_attrs->ia_iattr;
+
+	if (ia_valid & ATTR_UID)
+		iattrs->ia_uid = iattr->ia_uid;
+	if (ia_valid & ATTR_GID)
+		iattrs->ia_gid = iattr->ia_gid;
+	if (ia_valid & ATTR_ATIME)
+		iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
+			inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MTIME)
+		iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
+			inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_CTIME)
+		iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
+			inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MODE) {
+		umode_t mode = iattr->ia_mode;
+
+		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+			mode &= ~S_ISGID;
+		iattrs->ia_mode = sd->s_mode = mode;
 	}
 	return error;
 }
--- linux-ec2-2.6.32.orig/fs/sysfs/file.c
+++ linux-ec2-2.6.32/fs/sysfs/file.c
@@ -340,7 +340,7 @@
 	char *p;
 
 	p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
-	if (p)
+	if (!IS_ERR(p))
 		memmove(last_sysfs_file, p, strlen(p) + 1);
 
 	/* need attr_sd for attr and ops, its parent for kobj */
--- linux-ec2-2.6.32.orig/fs/dlm/config.c
+++ linux-ec2-2.6.32/fs/dlm/config.c
@@ -410,10 +410,10 @@
 	struct dlm_comms *cms = NULL;
 	void *gps = NULL;
 
-	cl = kzalloc(sizeof(struct dlm_cluster), GFP_KERNEL);
-	gps = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
-	sps = kzalloc(sizeof(struct dlm_spaces), GFP_KERNEL);
-	cms = kzalloc(sizeof(struct dlm_comms), GFP_KERNEL);
+	cl = kzalloc(sizeof(struct dlm_cluster), GFP_NOFS);
+	gps = kcalloc(3, sizeof(struct config_group *), GFP_NOFS);
+	sps = kzalloc(sizeof(struct dlm_spaces), GFP_NOFS);
+	cms = kzalloc(sizeof(struct dlm_comms), GFP_NOFS);
 
 	if (!cl || !gps || !sps || !cms)
 		goto fail;
@@ -482,9 +482,9 @@
 	struct dlm_nodes *nds = NULL;
 	void *gps = NULL;
 
-	sp = kzalloc(sizeof(struct dlm_space), GFP_KERNEL);
-	gps = kcalloc(2, sizeof(struct config_group *), GFP_KERNEL);
-	nds = kzalloc(sizeof(struct dlm_nodes), GFP_KERNEL);
+	sp = kzalloc(sizeof(struct dlm_space), GFP_NOFS);
+	gps = kcalloc(2, sizeof(struct config_group *), GFP_NOFS);
+	nds = kzalloc(sizeof(struct dlm_nodes), GFP_NOFS);
 
 	if (!sp || !gps || !nds)
 		goto fail;
@@ -536,7 +536,7 @@
 {
 	struct dlm_comm *cm;
 
-	cm = kzalloc(sizeof(struct dlm_comm), GFP_KERNEL);
+	cm = kzalloc(sizeof(struct dlm_comm), GFP_NOFS);
 	if (!cm)
 		return ERR_PTR(-ENOMEM);
 
@@ -569,7 +569,7 @@
 	struct dlm_space *sp = config_item_to_space(g->cg_item.ci_parent);
 	struct dlm_node *nd;
 
-	nd = kzalloc(sizeof(struct dlm_node), GFP_KERNEL);
+	nd = kzalloc(sizeof(struct dlm_node), GFP_NOFS);
 	if (!nd)
 		return ERR_PTR(-ENOMEM);
 
@@ -705,7 +705,7 @@
 	if (cm->addr_count >= DLM_MAX_ADDR_COUNT)
 		return -ENOSPC;
 
-	addr = kzalloc(sizeof(*addr), GFP_KERNEL);
+	addr = kzalloc(sizeof(*addr), GFP_NOFS);
 	if (!addr)
 		return -ENOMEM;
 
@@ -868,7 +868,7 @@
 
 	ids_count = sp->members_count;
 
-	ids = kcalloc(ids_count, sizeof(int), GFP_KERNEL);
+	ids = kcalloc(ids_count, sizeof(int), GFP_NOFS);
 	if (!ids) {
 		rv = -ENOMEM;
 		goto out;
@@ -886,7 +886,7 @@
 	if (!new_count)
 		goto out_ids;
 
-	new = kcalloc(new_count, sizeof(int), GFP_KERNEL);
+	new = kcalloc(new_count, sizeof(int), GFP_NOFS);
 	if (!new) {
 		kfree(ids);
 		rv = -ENOMEM;
--- linux-ec2-2.6.32.orig/fs/dlm/rcom.c
+++ linux-ec2-2.6.32/fs/dlm/rcom.c
@@ -38,7 +38,7 @@
 	char *mb;
 	int mb_len = sizeof(struct dlm_rcom) + len;
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb);
 	if (!mh) {
 		log_print("create_rcom to %d type %d len %d ENOBUFS",
 			  to_nodeid, type, len);
--- linux-ec2-2.6.32.orig/fs/dlm/dlm_internal.h
+++ linux-ec2-2.6.32/fs/dlm/dlm_internal.h
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2010 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -232,11 +232,17 @@
 	int8_t			lkb_status;     /* granted, waiting, convert */
 	int8_t			lkb_rqmode;	/* requested lock mode */
 	int8_t			lkb_grmode;	/* granted lock mode */
-	int8_t			lkb_bastmode;	/* requested mode */
 	int8_t			lkb_highbast;	/* highest mode bast sent for */
+
 	int8_t			lkb_wait_type;	/* type of reply waiting for */
 	int8_t			lkb_wait_count;
 	int8_t			lkb_ast_type;	/* type of ast queued for */
+	int8_t			lkb_ast_first;	/* type of first ast queued */
+
+	int8_t			lkb_bastmode;	/* req mode of queued bast */
+	int8_t			lkb_castmode;	/* gr mode of queued cast */
+	int8_t			lkb_bastmode_done; /* last delivered bastmode */
+	int8_t			lkb_castmode_done; /* last delivered castmode */
 
 	struct list_head	lkb_idtbl_list;	/* lockspace lkbtbl */
 	struct list_head	lkb_statequeue;	/* rsb g/c/w list */
@@ -473,7 +479,6 @@
 	int			ls_low_nodeid;
 	int			ls_total_weight;
 	int			*ls_node_array;
-	gfp_t			ls_allocation;
 
 	struct dlm_rsb		ls_stub_rsb;	/* for returning errors */
 	struct dlm_lkb		ls_stub_lkb;	/* for returning errors */
--- linux-ec2-2.6.32.orig/fs/dlm/member.c
+++ linux-ec2-2.6.32/fs/dlm/member.c
@@ -48,7 +48,7 @@
 	struct dlm_member *memb;
 	int w, error;
 
-	memb = kzalloc(sizeof(struct dlm_member), ls->ls_allocation);
+	memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS);
 	if (!memb)
 		return -ENOMEM;
 
@@ -143,7 +143,7 @@
 
 	ls->ls_total_weight = total;
 
-	array = kmalloc(sizeof(int) * total, ls->ls_allocation);
+	array = kmalloc(sizeof(int) * total, GFP_NOFS);
 	if (!array)
 		return;
 
@@ -226,7 +226,7 @@
 			continue;
 		log_debug(ls, "new nodeid %d is a re-added member", rv->new[i]);
 
-		memb = kzalloc(sizeof(struct dlm_member), ls->ls_allocation);
+		memb = kzalloc(sizeof(struct dlm_member), GFP_NOFS);
 		if (!memb)
 			return -ENOMEM;
 		memb->nodeid = rv->new[i];
@@ -341,7 +341,7 @@
 	int *ids = NULL, *new = NULL;
 	int error, ids_count = 0, new_count = 0;
 
-	rv = kzalloc(sizeof(struct dlm_recover), ls->ls_allocation);
+	rv = kzalloc(sizeof(struct dlm_recover), GFP_NOFS);
 	if (!rv)
 		return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/fs/dlm/dir.c
+++ linux-ec2-2.6.32/fs/dlm/dir.c
@@ -49,8 +49,7 @@
 	spin_unlock(&ls->ls_recover_list_lock);
 
 	if (!found)
-		de = kzalloc(sizeof(struct dlm_direntry) + len,
-			     ls->ls_allocation);
+		de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_NOFS);
 	return de;
 }
 
@@ -212,7 +211,7 @@
 
 	dlm_dir_clear(ls);
 
-	last_name = kmalloc(DLM_RESNAME_MAXLEN, ls->ls_allocation);
+	last_name = kmalloc(DLM_RESNAME_MAXLEN, GFP_NOFS);
 	if (!last_name)
 		goto out;
 
@@ -323,7 +322,7 @@
 	if (namelen > DLM_RESNAME_MAXLEN)
 		return -EINVAL;
 
-	de = kzalloc(sizeof(struct dlm_direntry) + namelen, ls->ls_allocation);
+	de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_NOFS);
 	if (!de)
 		return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/fs/dlm/lock.c
+++ linux-ec2-2.6.32/fs/dlm/lock.c
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2010 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -307,7 +307,7 @@
 	lkb->lkb_lksb->sb_status = rv;
 	lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
 
-	dlm_add_ast(lkb, AST_COMP, 0);
+	dlm_add_ast(lkb, AST_COMP, lkb->lkb_grmode);
 }
 
 static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -2280,20 +2280,30 @@
 	if (can_be_queued(lkb)) {
 		error = -EINPROGRESS;
 		add_lkb(r, lkb, DLM_LKSTS_WAITING);
-		send_blocking_asts(r, lkb);
 		add_timeout(lkb);
 		goto out;
 	}
 
 	error = -EAGAIN;
-	if (force_blocking_asts(lkb))
-		send_blocking_asts_all(r, lkb);
 	queue_cast(r, lkb, -EAGAIN);
-
  out:
 	return error;
 }
 
+static void do_request_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+			       int error)
+{
+	switch (error) {
+	case -EAGAIN:
+		if (force_blocking_asts(lkb))
+			send_blocking_asts_all(r, lkb);
+		break;
+	case -EINPROGRESS:
+		send_blocking_asts(r, lkb);
+		break;
+	}
+}
+
 static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
 	int error = 0;
@@ -2304,7 +2314,6 @@
 	if (can_be_granted(r, lkb, 1, &deadlk)) {
 		grant_lock(r, lkb);
 		queue_cast(r, lkb, 0);
-		grant_pending_locks(r);
 		goto out;
 	}
 
@@ -2334,7 +2343,6 @@
 		if (_can_be_granted(r, lkb, 1)) {
 			grant_lock(r, lkb);
 			queue_cast(r, lkb, 0);
-			grant_pending_locks(r);
 			goto out;
 		}
 		/* else fall through and move to convert queue */
@@ -2344,28 +2352,47 @@
 		error = -EINPROGRESS;
 		del_lkb(r, lkb);
 		add_lkb(r, lkb, DLM_LKSTS_CONVERT);
-		send_blocking_asts(r, lkb);
 		add_timeout(lkb);
 		goto out;
 	}
 
 	error = -EAGAIN;
-	if (force_blocking_asts(lkb))
-		send_blocking_asts_all(r, lkb);
 	queue_cast(r, lkb, -EAGAIN);
-
  out:
 	return error;
 }
 
+static void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+			       int error)
+{
+	switch (error) {
+	case 0:
+		grant_pending_locks(r);
+		/* grant_pending_locks also sends basts */
+		break;
+	case -EAGAIN:
+		if (force_blocking_asts(lkb))
+			send_blocking_asts_all(r, lkb);
+		break;
+	case -EINPROGRESS:
+		send_blocking_asts(r, lkb);
+		break;
+	}
+}
+
 static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
 	remove_lock(r, lkb);
 	queue_cast(r, lkb, -DLM_EUNLOCK);
-	grant_pending_locks(r);
 	return -DLM_EUNLOCK;
 }
 
+static void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+			      int error)
+{
+	grant_pending_locks(r);
+}
+
 /* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
  
 static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -2375,12 +2402,18 @@
 	error = revert_lock(r, lkb);
 	if (error) {
 		queue_cast(r, lkb, -DLM_ECANCEL);
-		grant_pending_locks(r);
 		return -DLM_ECANCEL;
 	}
 	return 0;
 }
 
+static void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
+			      int error)
+{
+	if (error)
+		grant_pending_locks(r);
+}
+
 /*
  * Four stage 3 varieties:
  * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock()
@@ -2402,11 +2435,15 @@
 		goto out;
 	}
 
-	if (is_remote(r))
+	if (is_remote(r)) {
 		/* receive_request() calls do_request() on remote node */
 		error = send_request(r, lkb);
-	else
+	} else {
 		error = do_request(r, lkb);
+		/* for remote locks the request_reply is sent
+		   between do_request and do_request_effects */
+		do_request_effects(r, lkb, error);
+	}
  out:
 	return error;
 }
@@ -2417,11 +2454,15 @@
 {
 	int error;
 
-	if (is_remote(r))
+	if (is_remote(r)) {
 		/* receive_convert() calls do_convert() on remote node */
 		error = send_convert(r, lkb);
-	else
+	} else {
 		error = do_convert(r, lkb);
+		/* for remote locks the convert_reply is sent
+		   between do_convert and do_convert_effects */
+		do_convert_effects(r, lkb, error);
+	}
 
 	return error;
 }
@@ -2432,11 +2473,15 @@
 {
 	int error;
 
-	if (is_remote(r))
+	if (is_remote(r)) {
 		/* receive_unlock() calls do_unlock() on remote node */
 		error = send_unlock(r, lkb);
-	else
+	} else {
 		error = do_unlock(r, lkb);
+		/* for remote locks the unlock_reply is sent
+		   between do_unlock and do_unlock_effects */
+		do_unlock_effects(r, lkb, error);
+	}
 
 	return error;
 }
@@ -2447,11 +2492,15 @@
 {
 	int error;
 
-	if (is_remote(r))
+	if (is_remote(r)) {
 		/* receive_cancel() calls do_cancel() on remote node */
 		error = send_cancel(r, lkb);
-	else
+	} else {
 		error = do_cancel(r, lkb);
+		/* for remote locks the cancel_reply is sent
+		   between do_cancel and do_cancel_effects */
+		do_cancel_effects(r, lkb, error);
+	}
 
 	return error;
 }
@@ -2689,7 +2738,7 @@
 	   pass into lowcomms_commit and a message buffer (mb) that we
 	   write our data into */
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_NOFS, &mb);
 	if (!mh)
 		return -ENOBUFS;
 
@@ -3191,6 +3240,7 @@
 	attach_lkb(r, lkb);
 	error = do_request(r, lkb);
 	send_request_reply(r, lkb, error);
+	do_request_effects(r, lkb, error);
 
 	unlock_rsb(r);
 	put_rsb(r);
@@ -3226,15 +3276,19 @@
 		goto out;
 
 	receive_flags(lkb, ms);
+
 	error = receive_convert_args(ls, lkb, ms);
-	if (error)
-		goto out_reply;
+	if (error) {
+		send_convert_reply(r, lkb, error);
+		goto out;
+	}
+
 	reply = !down_conversion(lkb);
 
 	error = do_convert(r, lkb);
- out_reply:
 	if (reply)
 		send_convert_reply(r, lkb, error);
+	do_convert_effects(r, lkb, error);
  out:
 	unlock_rsb(r);
 	put_rsb(r);
@@ -3266,13 +3320,16 @@
 		goto out;
 
 	receive_flags(lkb, ms);
+
 	error = receive_unlock_args(ls, lkb, ms);
-	if (error)
-		goto out_reply;
+	if (error) {
+		send_unlock_reply(r, lkb, error);
+		goto out;
+	}
 
 	error = do_unlock(r, lkb);
- out_reply:
 	send_unlock_reply(r, lkb, error);
+	do_unlock_effects(r, lkb, error);
  out:
 	unlock_rsb(r);
 	put_rsb(r);
@@ -3307,6 +3364,7 @@
 
 	error = do_cancel(r, lkb);
 	send_cancel_reply(r, lkb, error);
+	do_cancel_effects(r, lkb, error);
  out:
 	unlock_rsb(r);
 	put_rsb(r);
@@ -4512,7 +4570,7 @@
 	}
 
 	if (flags & DLM_LKF_VALBLK) {
-		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
+		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS);
 		if (!ua->lksb.sb_lvbptr) {
 			kfree(ua);
 			__put_lkb(ls, lkb);
@@ -4582,7 +4640,7 @@
 	ua = lkb->lkb_ua;
 
 	if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) {
-		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL);
+		ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS);
 		if (!ua->lksb.sb_lvbptr) {
 			error = -ENOMEM;
 			goto out_put;
--- linux-ec2-2.6.32.orig/fs/dlm/requestqueue.c
+++ linux-ec2-2.6.32/fs/dlm/requestqueue.c
@@ -35,7 +35,7 @@
 	struct rq_entry *e;
 	int length = ms->m_header.h_length - sizeof(struct dlm_message);
 
-	e = kmalloc(sizeof(struct rq_entry) + length, ls->ls_allocation);
+	e = kmalloc(sizeof(struct rq_entry) + length, GFP_NOFS);
 	if (!e) {
 		log_print("dlm_add_requestqueue: out of memory len %d", length);
 		return;
--- linux-ec2-2.6.32.orig/fs/dlm/lowcomms.c
+++ linux-ec2-2.6.32/fs/dlm/lowcomms.c
@@ -1060,7 +1060,7 @@
 		if (dlm_our_addr(&sas, i))
 			break;
 
-		addr = kmalloc(sizeof(*addr), GFP_KERNEL);
+		addr = kmalloc(sizeof(*addr), GFP_NOFS);
 		if (!addr)
 			break;
 		memcpy(addr, &sas, sizeof(*addr));
@@ -1099,7 +1099,7 @@
 	struct sockaddr_storage localaddr;
 	struct sctp_event_subscribe subscribe;
 	int result = -EINVAL, num = 1, i, addr_len;
-	struct connection *con = nodeid2con(0, GFP_KERNEL);
+	struct connection *con = nodeid2con(0, GFP_NOFS);
 	int bufsize = NEEDED_RMEM;
 
 	if (!con)
@@ -1171,7 +1171,7 @@
 static int tcp_listen_for_all(void)
 {
 	struct socket *sock = NULL;
-	struct connection *con = nodeid2con(0, GFP_KERNEL);
+	struct connection *con = nodeid2con(0, GFP_NOFS);
 	int result = -EINVAL;
 
 	if (!con)
--- linux-ec2-2.6.32.orig/fs/dlm/ast.c
+++ linux-ec2-2.6.32/fs/dlm/ast.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2010 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -33,10 +33,10 @@
 	spin_unlock(&ast_queue_lock);
 }
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode)
 {
 	if (lkb->lkb_flags & DLM_IFL_USER) {
-		dlm_user_add_ast(lkb, type, bastmode);
+		dlm_user_add_ast(lkb, type, mode);
 		return;
 	}
 
@@ -44,10 +44,21 @@
 	if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
 		kref_get(&lkb->lkb_ref);
 		list_add_tail(&lkb->lkb_astqueue, &ast_queue);
+		lkb->lkb_ast_first = type;
 	}
+
+	/* sanity check, this should not happen */
+
+	if ((type == AST_COMP) && (lkb->lkb_ast_type & AST_COMP))
+		log_print("repeat cast %d castmode %d lock %x %s",
+			  mode, lkb->lkb_castmode,
+			  lkb->lkb_id, lkb->lkb_resource->res_name);
+
 	lkb->lkb_ast_type |= type;
-	if (bastmode)
-		lkb->lkb_bastmode = bastmode;
+	if (type == AST_BAST)
+		lkb->lkb_bastmode = mode;
+	else
+		lkb->lkb_castmode = mode;
 	spin_unlock(&ast_queue_lock);
 
 	set_bit(WAKE_ASTS, &astd_wakeflags);
@@ -59,9 +70,9 @@
 	struct dlm_ls *ls = NULL;
 	struct dlm_rsb *r = NULL;
 	struct dlm_lkb *lkb;
-	void (*cast) (void *astparam);
-	void (*bast) (void *astparam, int mode);
-	int type = 0, bastmode;
+	void (*castfn) (void *astparam);
+	void (*bastfn) (void *astparam, int mode);
+	int type, first, bastmode, castmode, do_bast, do_cast, last_castmode;
 
 repeat:
 	spin_lock(&ast_queue_lock);
@@ -75,17 +86,48 @@
 		list_del(&lkb->lkb_astqueue);
 		type = lkb->lkb_ast_type;
 		lkb->lkb_ast_type = 0;
+		first = lkb->lkb_ast_first;
+		lkb->lkb_ast_first = 0;
 		bastmode = lkb->lkb_bastmode;
-
+		castmode = lkb->lkb_castmode;
+		castfn = lkb->lkb_astfn;
+		bastfn = lkb->lkb_bastfn;
 		spin_unlock(&ast_queue_lock);
-		cast = lkb->lkb_astfn;
-		bast = lkb->lkb_bastfn;
 
-		if ((type & AST_COMP) && cast)
-			cast(lkb->lkb_astparam);
+		do_cast = (type & AST_COMP) && castfn;
+		do_bast = (type & AST_BAST) && bastfn;
+
+		/* Skip a bast if its blocking mode is compatible with the
+		   granted mode of the preceding cast. */
 
-		if ((type & AST_BAST) && bast)
-			bast(lkb->lkb_astparam, bastmode);
+		if (do_bast) {
+			if (first == AST_COMP)
+				last_castmode = castmode;
+			else
+				last_castmode = lkb->lkb_castmode_done;
+			if (dlm_modes_compat(bastmode, last_castmode))
+				do_bast = 0;
+		}
+
+		if (first == AST_COMP) {
+			if (do_cast)
+				castfn(lkb->lkb_astparam);
+			if (do_bast)
+				bastfn(lkb->lkb_astparam, bastmode);
+		} else if (first == AST_BAST) {
+			if (do_bast)
+				bastfn(lkb->lkb_astparam, bastmode);
+			if (do_cast)
+				castfn(lkb->lkb_astparam);
+		} else {
+			log_error(ls, "bad ast_first %d ast_type %d",
+				  first, type);
+		}
+
+		if (do_cast)
+			lkb->lkb_castmode_done = castmode;
+		if (do_bast)
+			lkb->lkb_bastmode_done = bastmode;
 
 		/* this removes the reference added by dlm_add_ast
 		   and may result in the lkb being freed */
--- linux-ec2-2.6.32.orig/fs/dlm/debug_fs.c
+++ linux-ec2-2.6.32/fs/dlm/debug_fs.c
@@ -404,7 +404,7 @@
 	if (bucket >= ls->ls_rsbtbl_size)
 		return NULL;
 
-	ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
+	ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS);
 	if (!ri)
 		return NULL;
 	if (n == 0)
--- linux-ec2-2.6.32.orig/fs/dlm/lockspace.c
+++ linux-ec2-2.6.32/fs/dlm/lockspace.c
@@ -430,7 +430,7 @@
 
 	error = -ENOMEM;
 
-	ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_KERNEL);
+	ls = kzalloc(sizeof(struct dlm_ls) + namelen, GFP_NOFS);
 	if (!ls)
 		goto out;
 	memcpy(ls->ls_name, name, namelen);
@@ -443,11 +443,6 @@
 	if (flags & DLM_LSFL_TIMEWARN)
 		set_bit(LSFL_TIMEWARN, &ls->ls_flags);
 
-	if (flags & DLM_LSFL_FS)
-		ls->ls_allocation = GFP_NOFS;
-	else
-		ls->ls_allocation = GFP_KERNEL;
-
 	/* ls_exflags are forced to match among nodes, and we don't
 	   need to require all nodes to have some flags set */
 	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS |
@@ -456,7 +451,7 @@
 	size = dlm_config.ci_rsbtbl_size;
 	ls->ls_rsbtbl_size = size;
 
-	ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_KERNEL);
+	ls->ls_rsbtbl = kmalloc(sizeof(struct dlm_rsbtable) * size, GFP_NOFS);
 	if (!ls->ls_rsbtbl)
 		goto out_lsfree;
 	for (i = 0; i < size; i++) {
@@ -468,7 +463,7 @@
 	size = dlm_config.ci_lkbtbl_size;
 	ls->ls_lkbtbl_size = size;
 
-	ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_KERNEL);
+	ls->ls_lkbtbl = kmalloc(sizeof(struct dlm_lkbtable) * size, GFP_NOFS);
 	if (!ls->ls_lkbtbl)
 		goto out_rsbfree;
 	for (i = 0; i < size; i++) {
@@ -480,7 +475,7 @@
 	size = dlm_config.ci_dirtbl_size;
 	ls->ls_dirtbl_size = size;
 
-	ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_KERNEL);
+	ls->ls_dirtbl = kmalloc(sizeof(struct dlm_dirtable) * size, GFP_NOFS);
 	if (!ls->ls_dirtbl)
 		goto out_lkbfree;
 	for (i = 0; i < size; i++) {
@@ -527,7 +522,7 @@
 	mutex_init(&ls->ls_requestqueue_mutex);
 	mutex_init(&ls->ls_clear_proc_locks);
 
-	ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
+	ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
 	if (!ls->ls_recover_buf)
 		goto out_dirfree;
 
--- linux-ec2-2.6.32.orig/fs/dlm/netlink.c
+++ linux-ec2-2.6.32/fs/dlm/netlink.c
@@ -26,7 +26,7 @@
 	struct sk_buff *skb;
 	void *data;
 
-	skb = genlmsg_new(size, GFP_KERNEL);
+	skb = genlmsg_new(size, GFP_NOFS);
 	if (!skb)
 		return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/fs/dlm/plock.c
+++ linux-ec2-2.6.32/fs/dlm/plock.c
@@ -82,7 +82,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	xop = kzalloc(sizeof(*xop), GFP_KERNEL);
+	xop = kzalloc(sizeof(*xop), GFP_NOFS);
 	if (!xop) {
 		rv = -ENOMEM;
 		goto out;
@@ -211,7 +211,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	op = kzalloc(sizeof(*op), GFP_KERNEL);
+	op = kzalloc(sizeof(*op), GFP_NOFS);
 	if (!op) {
 		rv = -ENOMEM;
 		goto out;
@@ -266,7 +266,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	op = kzalloc(sizeof(*op), GFP_KERNEL);
+	op = kzalloc(sizeof(*op), GFP_NOFS);
 	if (!op) {
 		rv = -ENOMEM;
 		goto out;
--- linux-ec2-2.6.32.orig/fs/dlm/ast.h
+++ linux-ec2-2.6.32/fs/dlm/ast.h
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2010 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -13,7 +13,7 @@
 #ifndef __ASTD_DOT_H__
 #define __ASTD_DOT_H__
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
+void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode);
 void dlm_del_ast(struct dlm_lkb *lkb);
 
 void dlm_astd_wake(void);
--- linux-ec2-2.6.32.orig/fs/dlm/memory.c
+++ linux-ec2-2.6.32/fs/dlm/memory.c
@@ -39,7 +39,7 @@
 {
 	char *p;
 
-	p = kzalloc(ls->ls_lvblen, ls->ls_allocation);
+	p = kzalloc(ls->ls_lvblen, GFP_NOFS);
 	return p;
 }
 
@@ -57,7 +57,7 @@
 
 	DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,);
 
-	r = kzalloc(sizeof(*r) + namelen, ls->ls_allocation);
+	r = kzalloc(sizeof(*r) + namelen, GFP_NOFS);
 	return r;
 }
 
@@ -72,7 +72,7 @@
 {
 	struct dlm_lkb *lkb;
 
-	lkb = kmem_cache_zalloc(lkb_cache, ls->ls_allocation);
+	lkb = kmem_cache_zalloc(lkb_cache, GFP_NOFS);
 	return lkb;
 }
 
--- linux-ec2-2.6.32.orig/fs/dlm/user.c
+++ linux-ec2-2.6.32/fs/dlm/user.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2009 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2006-2010 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -173,7 +173,7 @@
 /* we could possibly check if the cancel of an orphan has resulted in the lkb
    being removed and then remove that lkb from the orphans list and free it */
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
 {
 	struct dlm_ls *ls;
 	struct dlm_user_args *ua;
@@ -206,8 +206,10 @@
 
 	ast_type = lkb->lkb_ast_type;
 	lkb->lkb_ast_type |= type;
-	if (bastmode)
-		lkb->lkb_bastmode = bastmode;
+	if (type == AST_BAST)
+		lkb->lkb_bastmode = mode;
+	else
+		lkb->lkb_castmode = mode;
 
 	if (!ast_type) {
 		kref_get(&lkb->lkb_ref);
@@ -267,7 +269,7 @@
 		goto out;
 	}
 
-	ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
+	ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
 	if (!ua)
 		goto out;
 	ua->proc = proc;
@@ -307,7 +309,7 @@
 	if (!ls)
 		return -ENOENT;
 
-	ua = kzalloc(sizeof(struct dlm_user_args), GFP_KERNEL);
+	ua = kzalloc(sizeof(struct dlm_user_args), GFP_NOFS);
 	if (!ua)
 		goto out;
 	ua->proc = proc;
@@ -352,7 +354,7 @@
 
 	error = -ENOMEM;
 	len = strlen(name) + strlen(name_prefix) + 2;
-	ls->ls_device.name = kzalloc(len, GFP_KERNEL);
+	ls->ls_device.name = kzalloc(len, GFP_NOFS);
 	if (!ls->ls_device.name)
 		goto fail;
 
@@ -520,7 +522,7 @@
 #endif
 		return -EINVAL;
 
-	kbuf = kzalloc(count + 1, GFP_KERNEL);
+	kbuf = kzalloc(count + 1, GFP_NOFS);
 	if (!kbuf)
 		return -ENOMEM;
 
@@ -546,7 +548,7 @@
 
 		/* add 1 after namelen so that the name string is terminated */
 		kbuf = kzalloc(sizeof(struct dlm_write_request) + namelen + 1,
-			       GFP_KERNEL);
+			       GFP_NOFS);
 		if (!kbuf) {
 			kfree(k32buf);
 			return -ENOMEM;
@@ -648,7 +650,7 @@
 	if (!ls)
 		return -ENOENT;
 
-	proc = kzalloc(sizeof(struct dlm_user_proc), GFP_KERNEL);
+	proc = kzalloc(sizeof(struct dlm_user_proc), GFP_NOFS);
 	if (!proc) {
 		dlm_put_lockspace(ls);
 		return -ENOMEM;
--- linux-ec2-2.6.32.orig/fs/dlm/user.h
+++ linux-ec2-2.6.32/fs/dlm/user.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2006-2010 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -9,7 +9,7 @@
 #ifndef __USER_DOT_H__
 #define __USER_DOT_H__
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode);
+void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode);
 int dlm_user_init(void);
 void dlm_user_exit(void);
 int dlm_device_deregister(struct dlm_ls *ls);
--- linux-ec2-2.6.32.orig/fs/reiserfs/super.c
+++ linux-ec2-2.6.32/fs/reiserfs/super.c
@@ -26,6 +26,7 @@
 #include <linux/vfs.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
+#include <linux/precache.h>
 #include <linux/crc32.h>
 #include <linux/smp_lock.h>
 
@@ -1851,6 +1852,7 @@
 
 	init_waitqueue_head(&(sbi->s_wait));
 	spin_lock_init(&sbi->bitmap_lock);
+	precache_init(s);
 
 	return (0);
 
--- linux-ec2-2.6.32.orig/fs/reiserfs/xattr.c
+++ linux-ec2-2.6.32/fs/reiserfs/xattr.c
@@ -536,7 +536,7 @@
 	if (!err && new_size < i_size_read(dentry->d_inode)) {
 		struct iattr newattrs = {
 			.ia_ctime = current_fs_time(inode->i_sb),
-			.ia_size = buffer_size,
+			.ia_size = new_size,
 			.ia_valid = ATTR_SIZE | ATTR_CTIME,
 		};
 		mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
@@ -952,21 +952,13 @@
 	return generic_permission(inode, mask, NULL);
 }
 
-/* This will catch lookups from the fs root to .reiserfs_priv */
-static int
-xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
-{
-	struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
-	if (container_of(q1, struct dentry, d_name) == priv_root)
-		return -ENOENT;
-	if (q1->len == name->len &&
-		   !memcmp(q1->name, name->name, name->len))
-		return 0;
-	return 1;
+static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	return -EPERM;
 }
 
 static const struct dentry_operations xattr_lookup_poison_ops = {
-	.d_compare = xattr_lookup_poison,
+	.d_revalidate = xattr_hide_revalidate,
 };
 
 int reiserfs_lookup_privroot(struct super_block *s)
@@ -980,8 +972,7 @@
 				strlen(PRIVROOT_NAME));
 	if (!IS_ERR(dentry)) {
 		REISERFS_SB(s)->priv_root = dentry;
-		if (!reiserfs_expose_privroot(s))
-			s->s_root->d_op = &xattr_lookup_poison_ops;
+		dentry->d_op = &xattr_lookup_poison_ops;
 		if (dentry->d_inode)
 			dentry->d_inode->i_flags |= S_PRIVATE;
 	} else
--- linux-ec2-2.6.32.orig/fs/reiserfs/dir.c
+++ linux-ec2-2.6.32/fs/reiserfs/dir.c
@@ -45,8 +45,6 @@
 				   struct reiserfs_de_head *deh)
 {
 	struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root;
-	if (reiserfs_expose_privroot(dir->d_sb))
-		return 0;
 	return (dir == dir->d_parent && privroot->d_inode &&
 	        deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid);
 }
--- linux-ec2-2.6.32.orig/fs/reiserfs/journal.c
+++ linux-ec2-2.6.32/fs/reiserfs/journal.c
@@ -2184,6 +2184,15 @@
 		brelse(d_bh);
 		return 1;
 	}
+
+	if (bdev_read_only(sb->s_bdev)) {
+		reiserfs_warning(sb, "clm-2076",
+				 "device is readonly, unable to replay log");
+		brelse(c_bh);
+		brelse(d_bh);
+		return -EROFS;
+	}
+
 	trans_id = get_desc_trans_id(desc);
 	/* now we know we've got a good transaction, and it was inside the valid time ranges */
 	log_blocks = kmalloc(get_desc_trans_len(desc) *
@@ -2422,12 +2431,6 @@
 		goto start_log_replay;
 	}
 
-	if (continue_replay && bdev_read_only(sb->s_bdev)) {
-		reiserfs_warning(sb, "clm-2076",
-				 "device is readonly, unable to replay log");
-		return -1;
-	}
-
 	/* ok, there are transactions that need to be replayed.  start with the first log block, find
 	 ** all the valid transactions, and pick out the oldest.
 	 */
--- linux-ec2-2.6.32.orig/fs/reiserfs/xattr_security.c
+++ linux-ec2-2.6.32/fs/reiserfs/xattr_security.c
@@ -75,7 +75,7 @@
 		return error;
 	}
 
-	if (sec->length) {
+	if (sec->length && reiserfs_xattrs_initialized(inode->i_sb)) {
 		blocks = reiserfs_xattr_jcreate_nblocks(inode) +
 			 reiserfs_xattr_nblocks(inode, sec->length);
 		/* We don't want to count the directories twice if we have
--- linux-ec2-2.6.32.orig/fs/reiserfs/inode.c
+++ linux-ec2-2.6.32/fs/reiserfs/inode.c
@@ -2531,6 +2531,12 @@
 	return reiserfs_write_full_page(page, wbc);
 }
 
+static void reiserfs_truncate_failed_write(struct inode *inode)
+{
+	truncate_inode_pages(inode->i_mapping, inode->i_size);
+	reiserfs_truncate_file(inode, 0);
+}
+
 static int reiserfs_write_begin(struct file *file,
 				struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
@@ -2597,6 +2603,8 @@
 	if (ret) {
 		unlock_page(page);
 		page_cache_release(page);
+		/* Truncate allocated blocks */
+		reiserfs_truncate_failed_write(inode);
 	}
 	return ret;
 }
@@ -2689,8 +2697,7 @@
 	 ** transaction tracking stuff when the size changes.  So, we have
 	 ** to do the i_size updates here.
 	 */
-	pos += copied;
-	if (pos > inode->i_size) {
+	if (pos + copied > inode->i_size) {
 		struct reiserfs_transaction_handle myth;
 		reiserfs_write_lock(inode->i_sb);
 		/* If the file have grown beyond the border where it
@@ -2708,7 +2715,7 @@
 			goto journal_error;
 		}
 		reiserfs_update_inode_transaction(inode);
-		inode->i_size = pos;
+		inode->i_size = pos + copied;
 		/*
 		 * this will just nest into our transaction.  It's important
 		 * to use mark_inode_dirty so the inode gets pushed around on the
@@ -2735,6 +2742,10 @@
       out:
 	unlock_page(page);
 	page_cache_release(page);
+
+	if (pos + len > inode->i_size)
+		reiserfs_truncate_failed_write(inode);
+
 	return ret == 0 ? copied : ret;
 
       journal_error:
--- linux-ec2-2.6.32.orig/fs/jfs/xattr.c
+++ linux-ec2-2.6.32/fs/jfs/xattr.c
@@ -85,46 +85,25 @@
 #define EA_MALLOC	0x0008
 
 
+static int is_known_namespace(const char *name)
+{
+	if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) &&
+	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
+	    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
+	    strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+		return false;
+
+	return true;
+}
+
 /*
  * These three routines are used to recognize on-disk extended attributes
  * that are in a recognized namespace.  If the attribute is not recognized,
  * "os2." is prepended to the name
  */
-static inline int is_os2_xattr(struct jfs_ea *ea)
+static int is_os2_xattr(struct jfs_ea *ea)
 {
-	/*
-	 * Check for "system."
-	 */
-	if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) &&
-	    !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-		return false;
-	/*
-	 * Check for "user."
-	 */
-	if ((ea->namelen >= XATTR_USER_PREFIX_LEN) &&
-	    !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-		return false;
-	/*
-	 * Check for "security."
-	 */
-	if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) &&
-	    !strncmp(ea->name, XATTR_SECURITY_PREFIX,
-		     XATTR_SECURITY_PREFIX_LEN))
-		return false;
-	/*
-	 * Check for "trusted."
-	 */
-	if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) &&
-	    !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
-		return false;
-	/*
-	 * Add any other valid namespace prefixes here
-	 */
-
-	/*
-	 * We assume it's OS/2's flat namespace
-	 */
-	return true;
+	return !is_known_namespace(ea->name);
 }
 
 static inline int name_size(struct jfs_ea *ea)
@@ -762,13 +741,23 @@
 	if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 		return can_set_system_xattr(inode, name, value, value_len);
 
+	if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
+		/*
+		 * This makes sure that we aren't trying to set an
+		 * attribute in a different namespace by prefixing it
+		 * with "os2."
+		 */
+		if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN))
+				return -EOPNOTSUPP;
+		return 0;
+	}
+
 	/*
 	 * Don't allow setting an attribute in an unknown namespace.
 	 */
 	if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
 	    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
-	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
-	    strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))
+	    strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
 		return -EOPNOTSUPP;
 
 	return 0;
@@ -950,19 +939,8 @@
 	int xattr_size;
 	ssize_t size;
 	int namelen = strlen(name);
-	char *os2name = NULL;
 	char *value;
 
-	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
-		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
-				  GFP_KERNEL);
-		if (!os2name)
-			return -ENOMEM;
-		strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
-		name = os2name;
-		namelen -= XATTR_OS2_PREFIX_LEN;
-	}
-
 	down_read(&JFS_IP(inode)->xattr_sem);
 
 	xattr_size = ea_get(inode, &ea_buf, 0);
@@ -1000,8 +978,6 @@
       out:
 	up_read(&JFS_IP(inode)->xattr_sem);
 
-	kfree(os2name);
-
 	return size;
 }
 
@@ -1010,6 +986,19 @@
 {
 	int err;
 
+	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
+		/*
+		 * skip past "os2." prefix
+		 */
+		name += XATTR_OS2_PREFIX_LEN;
+		/*
+		 * Don't allow retrieving properly prefixed attributes
+		 * by prepending them with "os2."
+		 */
+		if (is_known_namespace(name))
+			return -EOPNOTSUPP;
+	}
+
 	err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
 
 	return err;
--- linux-ec2-2.6.32.orig/fs/jfs/resize.c
+++ linux-ec2-2.6.32/fs/jfs/resize.c
@@ -81,6 +81,7 @@
 	struct inode *iplist[1];
 	struct jfs_superblock *j_sb, *j_sb2;
 	uint old_agsize;
+	int agsizechanged = 0;
 	struct buffer_head *bh, *bh2;
 
 	/* If the volume hasn't grown, get out now */
@@ -333,6 +334,9 @@
 	 */
 	if ((rc = dbExtendFS(ipbmap, XAddress, nblocks)))
 		goto error_out;
+
+	agsizechanged |= (bmp->db_agsize != old_agsize);
+
 	/*
 	 * the map now has extended to cover additional nblocks:
 	 * dn_mapsize = oldMapsize + nblocks;
@@ -432,7 +436,7 @@
 	 * will correctly identify the new ag);
 	 */
 	/* if new AG size the same as old AG size, done! */
-	if (bmp->db_agsize != old_agsize) {
+	if (agsizechanged) {
 		if ((rc = diExtendFS(ipimap, ipbmap)))
 			goto error_out;
 
--- linux-ec2-2.6.32.orig/fs/ext2/namei.c
+++ linux-ec2-2.6.32/fs/ext2/namei.c
@@ -327,7 +327,6 @@
 		new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page);
 		if (!new_de)
 			goto out_dir;
-		inode_inc_link_count(old_inode);
 		ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
 		new_inode->i_ctime = CURRENT_TIME_SEC;
 		if (dir_de)
@@ -339,12 +338,9 @@
 			if (new_dir->i_nlink >= EXT2_LINK_MAX)
 				goto out_dir;
 		}
-		inode_inc_link_count(old_inode);
 		err = ext2_add_link(new_dentry, old_inode);
-		if (err) {
-			inode_dec_link_count(old_inode);
+		if (err)
 			goto out_dir;
-		}
 		if (dir_de)
 			inode_inc_link_count(new_dir);
 	}
@@ -352,12 +348,11 @@
 	/*
 	 * Like most other Unix systems, set the ctime for inodes on a
  	 * rename.
-	 * inode_dec_link_count() will mark the inode dirty.
 	 */
 	old_inode->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(old_inode);
 
 	ext2_delete_entry (old_de, old_page);
-	inode_dec_link_count(old_inode);
 
 	if (dir_de) {
 		if (old_dir != new_dir)
--- linux-ec2-2.6.32.orig/fs/ecryptfs/super.c
+++ linux-ec2-2.6.32/fs/ecryptfs/super.c
@@ -85,7 +85,6 @@
 		if (lower_dentry->d_inode) {
 			fput(inode_info->lower_file);
 			inode_info->lower_file = NULL;
-			d_drop(lower_dentry);
 		}
 	}
 	ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
--- linux-ec2-2.6.32.orig/fs/ecryptfs/mmap.c
+++ linux-ec2-2.6.32/fs/ecryptfs/mmap.c
@@ -372,6 +372,11 @@
 	    && (pos != 0))
 		zero_user(page, 0, PAGE_CACHE_SIZE);
 out:
+	if (unlikely(rc)) {
+		unlock_page(page);
+		page_cache_release(page);
+		*pagep = NULL;
+	}
 	return rc;
 }
 
--- linux-ec2-2.6.32.orig/fs/ecryptfs/crypto.c
+++ linux-ec2-2.6.32/fs/ecryptfs/crypto.c
@@ -1748,7 +1748,7 @@
 			    char *cipher_name, size_t *key_size)
 {
 	char dummy_key[ECRYPTFS_MAX_KEY_BYTES];
-	char *full_alg_name;
+	char *full_alg_name = NULL;
 	int rc;
 
 	*key_tfm = NULL;
@@ -1763,7 +1763,6 @@
 	if (rc)
 		goto out;
 	*key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC);
-	kfree(full_alg_name);
 	if (IS_ERR(*key_tfm)) {
 		rc = PTR_ERR(*key_tfm);
 		printk(KERN_ERR "Unable to allocate crypto cipher with name "
@@ -1786,6 +1785,7 @@
 		goto out;
 	}
 out:
+	kfree(full_alg_name);
 	return rc;
 }
 
--- linux-ec2-2.6.32.orig/fs/ecryptfs/messaging.c
+++ linux-ec2-2.6.32/fs/ecryptfs/messaging.c
@@ -30,9 +30,9 @@
 
 static struct hlist_head *ecryptfs_daemon_hash;
 struct mutex ecryptfs_daemon_hash_mux;
-static int ecryptfs_hash_buckets;
+static int ecryptfs_hash_bits;
 #define ecryptfs_uid_hash(uid) \
-        hash_long((unsigned long)uid, ecryptfs_hash_buckets)
+        hash_long((unsigned long)uid, ecryptfs_hash_bits)
 
 static u32 ecryptfs_msg_counter;
 static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
@@ -485,18 +485,19 @@
 	}
 	mutex_init(&ecryptfs_daemon_hash_mux);
 	mutex_lock(&ecryptfs_daemon_hash_mux);
-	ecryptfs_hash_buckets = 1;
-	while (ecryptfs_number_of_users >> ecryptfs_hash_buckets)
-		ecryptfs_hash_buckets++;
+	ecryptfs_hash_bits = 1;
+	while (ecryptfs_number_of_users >> ecryptfs_hash_bits)
+		ecryptfs_hash_bits++;
 	ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head)
-					* ecryptfs_hash_buckets), GFP_KERNEL);
+					* (1 << ecryptfs_hash_bits)),
+				       GFP_KERNEL);
 	if (!ecryptfs_daemon_hash) {
 		rc = -ENOMEM;
 		printk(KERN_ERR "%s: Failed to allocate memory\n", __func__);
 		mutex_unlock(&ecryptfs_daemon_hash_mux);
 		goto out;
 	}
-	for (i = 0; i < ecryptfs_hash_buckets; i++)
+	for (i = 0; i < (1 << ecryptfs_hash_bits); i++)
 		INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]);
 	mutex_unlock(&ecryptfs_daemon_hash_mux);
 	ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
@@ -553,7 +554,7 @@
 		int i;
 
 		mutex_lock(&ecryptfs_daemon_hash_mux);
-		for (i = 0; i < ecryptfs_hash_buckets; i++) {
+		for (i = 0; i < (1 << ecryptfs_hash_bits); i++) {
 			int rc;
 
 			hlist_for_each_entry(daemon, elem,
--- linux-ec2-2.6.32.orig/fs/ecryptfs/inode.c
+++ linux-ec2-2.6.32/fs/ecryptfs/inode.c
@@ -69,15 +69,19 @@
 	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
 	struct dentry *dentry_save;
 	struct vfsmount *vfsmount_save;
+	unsigned int flags_save;
 	int rc;
 
 	dentry_save = nd->path.dentry;
 	vfsmount_save = nd->path.mnt;
+	flags_save = nd->flags;
 	nd->path.dentry = lower_dentry;
 	nd->path.mnt = lower_mnt;
+	nd->flags &= ~LOOKUP_OPEN;
 	rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd);
 	nd->path.dentry = dentry_save;
 	nd->path.mnt = vfsmount_save;
+	nd->flags = flags_save;
 	return rc;
 }
 
@@ -272,7 +276,7 @@
 		printk(KERN_ERR "%s: Out of memory whilst attempting "
 		       "to allocate ecryptfs_dentry_info struct\n",
 			__func__);
-		goto out_dput;
+		goto out_put;
 	}
 	ecryptfs_set_dentry_lower(ecryptfs_dentry, lower_dentry);
 	ecryptfs_set_dentry_lower_mnt(ecryptfs_dentry, lower_mnt);
@@ -345,8 +349,9 @@
 out_free_kmem:
 	kmem_cache_free(ecryptfs_header_cache_2, page_virt);
 	goto out;
-out_dput:
+out_put:
 	dput(lower_dentry);
+	mntput(lower_mnt);
 	d_drop(ecryptfs_dentry);
 out:
 	return rc;
@@ -638,38 +643,17 @@
 	return rc;
 }
 
-static int
-ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
+				   size_t *bufsiz)
 {
+	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	char *lower_buf;
-	size_t lower_bufsiz;
-	struct dentry *lower_dentry;
-	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
-	char *plaintext_name;
-	size_t plaintext_name_size;
+	size_t lower_bufsiz = PATH_MAX;
 	mm_segment_t old_fs;
 	int rc;
 
-	lower_dentry = ecryptfs_dentry_to_lower(dentry);
-	if (!lower_dentry->d_inode->i_op->readlink) {
-		rc = -EINVAL;
-		goto out;
-	}
-	mount_crypt_stat = &ecryptfs_superblock_to_private(
-						dentry->d_sb)->mount_crypt_stat;
-	/*
-	 * If the lower filename is encrypted, it will result in a significantly
-	 * longer name.  If needed, truncate the name after decode and decrypt.
-	 */
-	if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)
-		lower_bufsiz = PATH_MAX;
-	else
-		lower_bufsiz = bufsiz;
-	/* Released in this function */
 	lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
-	if (lower_buf == NULL) {
-		printk(KERN_ERR "%s: Out of memory whilst attempting to "
-		       "kmalloc [%zd] bytes\n", __func__, lower_bufsiz);
+	if (!lower_buf) {
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -679,29 +663,31 @@
 						   (char __user *)lower_buf,
 						   lower_bufsiz);
 	set_fs(old_fs);
-	if (rc >= 0) {
-		rc = ecryptfs_decode_and_decrypt_filename(&plaintext_name,
-							  &plaintext_name_size,
-							  dentry, lower_buf,
-							  rc);
-		if (rc) {
-			printk(KERN_ERR "%s: Error attempting to decode and "
-			       "decrypt filename; rc = [%d]\n", __func__,
-				rc);
-			goto out_free_lower_buf;
-		}
-		/* Check for bufsiz <= 0 done in sys_readlinkat() */
-		rc = copy_to_user(buf, plaintext_name,
-				  min((size_t) bufsiz, plaintext_name_size));
-		if (rc)
-			rc = -EFAULT;
-		else
-			rc = plaintext_name_size;
-		kfree(plaintext_name);
-		fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
-	}
-out_free_lower_buf:
+	if (rc < 0)
+		goto out;
+	lower_bufsiz = rc;
+	rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
+						  lower_buf, lower_bufsiz);
+out:
 	kfree(lower_buf);
+	return rc;
+}
+
+static int
+ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+{
+	char *kbuf;
+	size_t kbufsiz, copied;
+	int rc;
+
+	rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
+	if (rc)
+		goto out;
+	copied = min_t(size_t, bufsiz, kbufsiz);
+	rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
+	kfree(kbuf);
+	fsstack_copy_attr_atime(dentry->d_inode,
+				ecryptfs_dentry_to_lower(dentry)->d_inode);
 out:
 	return rc;
 }
@@ -971,6 +957,45 @@
 	return rc;
 }
 
+int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
+			  struct kstat *stat)
+{
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+	int rc = 0;
+
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+						dentry->d_sb)->mount_crypt_stat;
+	generic_fillattr(dentry->d_inode, stat);
+	if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
+		char *target;
+		size_t targetsiz;
+
+		rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
+		if (!rc) {
+			kfree(target);
+			stat->size = targetsiz;
+		}
+	}
+	return rc;
+}
+
+int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		     struct kstat *stat)
+{
+	struct kstat lower_stat;
+	int rc;
+
+	rc = vfs_getattr(ecryptfs_dentry_to_lower_mnt(dentry),
+			 ecryptfs_dentry_to_lower(dentry), &lower_stat);
+	if (!rc) {
+		fsstack_copy_attr_all(dentry->d_inode,
+				      ecryptfs_inode_to_lower(dentry->d_inode), NULL);
+		generic_fillattr(dentry->d_inode, stat);
+		stat->blocks = lower_stat.blocks;
+	}
+	return rc;
+}
+
 int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
@@ -980,7 +1005,7 @@
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	if (!lower_dentry->d_inode->i_op->setxattr) {
-		rc = -ENOSYS;
+		rc = -EOPNOTSUPP;
 		goto out;
 	}
 	mutex_lock(&lower_dentry->d_inode->i_mutex);
@@ -998,7 +1023,7 @@
 	int rc = 0;
 
 	if (!lower_dentry->d_inode->i_op->getxattr) {
-		rc = -ENOSYS;
+		rc = -EOPNOTSUPP;
 		goto out;
 	}
 	mutex_lock(&lower_dentry->d_inode->i_mutex);
@@ -1025,7 +1050,7 @@
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	if (!lower_dentry->d_inode->i_op->listxattr) {
-		rc = -ENOSYS;
+		rc = -EOPNOTSUPP;
 		goto out;
 	}
 	mutex_lock(&lower_dentry->d_inode->i_mutex);
@@ -1042,7 +1067,7 @@
 
 	lower_dentry = ecryptfs_dentry_to_lower(dentry);
 	if (!lower_dentry->d_inode->i_op->removexattr) {
-		rc = -ENOSYS;
+		rc = -EOPNOTSUPP;
 		goto out;
 	}
 	mutex_lock(&lower_dentry->d_inode->i_mutex);
@@ -1073,6 +1098,7 @@
 	.put_link = ecryptfs_put_link,
 	.permission = ecryptfs_permission,
 	.setattr = ecryptfs_setattr,
+	.getattr = ecryptfs_getattr_link,
 	.setxattr = ecryptfs_setxattr,
 	.getxattr = ecryptfs_getxattr,
 	.listxattr = ecryptfs_listxattr,
@@ -1100,6 +1126,7 @@
 const struct inode_operations ecryptfs_main_iops = {
 	.permission = ecryptfs_permission,
 	.setattr = ecryptfs_setattr,
+	.getattr = ecryptfs_getattr,
 	.setxattr = ecryptfs_setxattr,
 	.getxattr = ecryptfs_getxattr,
 	.listxattr = ecryptfs_listxattr,
--- linux-ec2-2.6.32.orig/fs/ecryptfs/keystore.c
+++ linux-ec2-2.6.32/fs/ecryptfs/keystore.c
@@ -1542,6 +1542,7 @@
 		printk(KERN_ERR "Could not find key with description: [%s]\n",
 		       sig);
 		rc = process_request_key_err(PTR_ERR(*auth_tok_key));
+		(*auth_tok_key) = NULL;
 		goto out;
 	}
 	(*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
--- linux-ec2-2.6.32.orig/fs/ecryptfs/file.c
+++ linux-ec2-2.6.32/fs/ecryptfs/file.c
@@ -191,13 +191,6 @@
 				      | ECRYPTFS_ENCRYPTED);
 	}
 	mutex_unlock(&crypt_stat->cs_mutex);
-	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
-	    && !(file->f_flags & O_RDONLY)) {
-		rc = -EPERM;
-		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
-		       "file must hence be opened RO\n", __func__);
-		goto out;
-	}
 	if (!ecryptfs_inode_to_private(inode)->lower_file) {
 		rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
 		if (rc) {
@@ -205,9 +198,16 @@
 			       "the persistent file for the dentry with name "
 			       "[%s]; rc = [%d]\n", __func__,
 			       ecryptfs_dentry->d_name.name, rc);
-			goto out;
+			goto out_free;
 		}
 	}
+	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_RDONLY)
+	    && !(file->f_flags & O_RDONLY)) {
+		rc = -EPERM;
+		printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+		       "file must hence be opened RO\n", __func__);
+		goto out_free;
+	}
 	ecryptfs_set_file_lower(
 		file, ecryptfs_inode_to_private(inode)->lower_file);
 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
@@ -293,12 +293,40 @@
 	return rc;
 }
 
-static int ecryptfs_ioctl(struct inode *inode, struct file *file,
-			  unsigned int cmd, unsigned long arg);
+static long
+ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct file *lower_file = NULL;
+	long rc = -ENOTTY;
+
+	if (ecryptfs_file_to_private(file))
+		lower_file = ecryptfs_file_to_lower(file);
+	if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
+		rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
+	return rc;
+}
+
+#ifdef CONFIG_COMPAT
+static long
+ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct file *lower_file = NULL;
+	long rc = -ENOIOCTLCMD;
+
+	if (ecryptfs_file_to_private(file))
+		lower_file = ecryptfs_file_to_lower(file);
+	if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl)
+		rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
+	return rc;
+}
+#endif
 
 const struct file_operations ecryptfs_dir_fops = {
 	.readdir = ecryptfs_readdir,
-	.ioctl = ecryptfs_ioctl,
+	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = ecryptfs_compat_ioctl,
+#endif
 	.mmap = generic_file_mmap,
 	.open = ecryptfs_open,
 	.flush = ecryptfs_flush,
@@ -315,7 +343,10 @@
 	.write = do_sync_write,
 	.aio_write = generic_file_aio_write,
 	.readdir = ecryptfs_readdir,
-	.ioctl = ecryptfs_ioctl,
+	.unlocked_ioctl = ecryptfs_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = ecryptfs_compat_ioctl,
+#endif
 	.mmap = generic_file_mmap,
 	.open = ecryptfs_open,
 	.flush = ecryptfs_flush,
@@ -324,20 +355,3 @@
 	.fasync = ecryptfs_fasync,
 	.splice_read = generic_file_splice_read,
 };
-
-static int
-ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-	       unsigned long arg)
-{
-	int rc = 0;
-	struct file *lower_file = NULL;
-
-	if (ecryptfs_file_to_private(file))
-		lower_file = ecryptfs_file_to_lower(file);
-	if (lower_file && lower_file->f_op && lower_file->f_op->ioctl)
-		rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode),
-					     lower_file, cmd, arg);
-	else
-		rc = -ENOTTY;
-	return rc;
-}
--- linux-ec2-2.6.32.orig/fs/befs/linuxvfs.c
+++ linux-ec2-2.6.32/fs/befs/linuxvfs.c
@@ -873,6 +873,7 @@
 	brelse(bh);
 
       unacquire_priv_sbp:
+	kfree(befs_sb->mount_opts.iocharset);
 	kfree(sb->s_fs_info);
 
       unacquire_none:
--- linux-ec2-2.6.32.orig/fs/udf/super.c
+++ linux-ec2-2.6.32/fs/udf/super.c
@@ -1078,21 +1078,39 @@
 	return 0;
 }
 
-static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
+static void udf_find_vat_block(struct super_block *sb, int p_index,
+			       int type1_index, sector_t start_block)
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_part_map *map = &sbi->s_partmaps[p_index];
+	sector_t vat_block;
 	struct kernel_lb_addr ino;
+
+	/*
+	 * VAT file entry is in the last recorded block. Some broken disks have
+	 * it a few blocks before so try a bit harder...
+	 */
+	ino.partitionReferenceNum = type1_index;
+	for (vat_block = start_block;
+	     vat_block >= map->s_partition_root &&
+	     vat_block >= start_block - 3 &&
+	     !sbi->s_vat_inode; vat_block--) {
+		ino.logicalBlockNum = vat_block - map->s_partition_root;
+		sbi->s_vat_inode = udf_iget(sb, &ino);
+	}
+}
+
+static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
+{
+	struct udf_sb_info *sbi = UDF_SB(sb);
+	struct udf_part_map *map = &sbi->s_partmaps[p_index];
 	struct buffer_head *bh = NULL;
 	struct udf_inode_info *vati;
 	uint32_t pos;
 	struct virtualAllocationTable20 *vat20;
 	sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
 
-	/* VAT file entry is in the last recorded block */
-	ino.partitionReferenceNum = type1_index;
-	ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
-	sbi->s_vat_inode = udf_iget(sb, &ino);
+	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
 	if (!sbi->s_vat_inode &&
 	    sbi->s_last_block != blocks - 1) {
 		printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
@@ -1100,9 +1118,7 @@
 		       "block of the device (%lu).\n",
 		       (unsigned long)sbi->s_last_block,
 		       (unsigned long)blocks - 1);
-		ino.partitionReferenceNum = type1_index;
-		ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
-		sbi->s_vat_inode = udf_iget(sb, &ino);
+		udf_find_vat_block(sb, p_index, type1_index, blocks - 1);
 	}
 	if (!sbi->s_vat_inode)
 		return 1;
--- linux-ec2-2.6.32.orig/fs/affs/super.c
+++ linux-ec2-2.6.32/fs/affs/super.c
@@ -203,7 +203,7 @@
 		switch (token) {
 		case Opt_bs:
 			if (match_int(&args[0], &n))
-				return -EINVAL;
+				return 0;
 			if (n != 512 && n != 1024 && n != 2048
 			    && n != 4096) {
 				printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
@@ -213,7 +213,7 @@
 			break;
 		case Opt_mode:
 			if (match_octal(&args[0], &option))
-				return 1;
+				return 0;
 			*mode = option & 0777;
 			*mount_opts |= SF_SETMODE;
 			break;
@@ -221,8 +221,6 @@
 			*mount_opts |= SF_MUFS;
 			break;
 		case Opt_prefix:
-			/* Free any previous prefix */
-			kfree(*prefix);
 			*prefix = match_strdup(&args[0]);
 			if (!*prefix)
 				return 0;
@@ -233,21 +231,21 @@
 			break;
 		case Opt_reserved:
 			if (match_int(&args[0], reserved))
-				return 1;
+				return 0;
 			break;
 		case Opt_root:
 			if (match_int(&args[0], root))
-				return 1;
+				return 0;
 			break;
 		case Opt_setgid:
 			if (match_int(&args[0], &option))
-				return 1;
+				return 0;
 			*gid = option;
 			*mount_opts |= SF_SETGID;
 			break;
 		case Opt_setuid:
 			if (match_int(&args[0], &option))
-				return -EINVAL;
+				return 0;
 			*uid = option;
 			*mount_opts |= SF_SETUID;
 			break;
@@ -311,11 +309,14 @@
 		return -ENOMEM;
 	sb->s_fs_info = sbi;
 	mutex_init(&sbi->s_bmlock);
+	spin_lock_init(&sbi->symlink_lock);
 
 	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
 				&blocksize,&sbi->s_prefix,
 				sbi->s_volume, &mount_flags)) {
 		printk(KERN_ERR "AFFS: Error parsing options\n");
+		kfree(sbi->s_prefix);
+		kfree(sbi);
 		return -EINVAL;
 	}
 	/* N.B. after this point s_prefix must be released */
@@ -516,14 +517,18 @@
 	unsigned long		 mount_flags;
 	int			 res = 0;
 	char			*new_opts = kstrdup(data, GFP_KERNEL);
+	char			 volume[32];
+	char			*prefix = NULL;
 
 	pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
 
 	*flags |= MS_NODIRATIME;
 
+	memcpy(volume, sbi->s_volume, 32);
 	if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
-			   &blocksize, &sbi->s_prefix, sbi->s_volume,
+			   &blocksize, &prefix, volume,
 			   &mount_flags)) {
+		kfree(prefix);
 		kfree(new_opts);
 		return -EINVAL;
 	}
@@ -534,6 +539,14 @@
 	sbi->s_mode  = mode;
 	sbi->s_uid   = uid;
 	sbi->s_gid   = gid;
+	/* protect against readers */
+	spin_lock(&sbi->symlink_lock);
+	if (prefix) {
+		kfree(sbi->s_prefix);
+		sbi->s_prefix = prefix;
+	}
+	memcpy(sbi->s_volume, volume, 32);
+	spin_unlock(&sbi->symlink_lock);
 
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
 		unlock_kernel();
--- linux-ec2-2.6.32.orig/fs/affs/namei.c
+++ linux-ec2-2.6.32/fs/affs/namei.c
@@ -341,10 +341,13 @@
 	p  = (char *)AFFS_HEAD(bh)->table;
 	lc = '/';
 	if (*symname == '/') {
+		struct affs_sb_info *sbi = AFFS_SB(sb);
 		while (*symname == '/')
 			symname++;
-		while (AFFS_SB(sb)->s_volume[i])	/* Cannot overflow */
-			*p++ = AFFS_SB(sb)->s_volume[i++];
+		spin_lock(&sbi->symlink_lock);
+		while (sbi->s_volume[i])	/* Cannot overflow */
+			*p++ = sbi->s_volume[i++];
+		spin_unlock(&sbi->symlink_lock);
 	}
 	while (i < maxlen && (c = *symname++)) {
 		if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
--- linux-ec2-2.6.32.orig/fs/affs/symlink.c
+++ linux-ec2-2.6.32/fs/affs/symlink.c
@@ -20,7 +20,6 @@
 	int			 i, j;
 	char			 c;
 	char			 lc;
-	char			*pf;
 
 	pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
 
@@ -32,11 +31,15 @@
 	j  = 0;
 	lf = (struct slink_front *)bh->b_data;
 	lc = 0;
-	pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
 
 	if (strchr(lf->symname,':')) {	/* Handle assign or volume name */
+		struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
+		char *pf;
+		spin_lock(&sbi->symlink_lock);
+		pf = sbi->s_prefix ? sbi->s_prefix : "/";
 		while (i < 1023 && (c = pf[i]))
 			link[i++] = c;
+		spin_unlock(&sbi->symlink_lock);
 		while (i < 1023 && lf->symname[j] != ':')
 			link[i++] = lf->symname[j++];
 		if (i < 1023)
--- linux-ec2-2.6.32.orig/fs/affs/affs.h
+++ linux-ec2-2.6.32/fs/affs/affs.h
@@ -106,8 +106,8 @@
 	u32 s_last_bmap;
 	struct buffer_head *s_bmap_bh;
 	char *s_prefix;			/* Prefix for volumes and assigns. */
-	int s_prefix_len;		/* Length of prefix. */
 	char s_volume[32];		/* Volume prefix for absolute symlinks. */
+	spinlock_t symlink_lock;	/* protects the previous two */
 };
 
 #define SF_INTL		0x0001		/* International filesystem. */
--- linux-ec2-2.6.32.orig/fs/debugfs/inode.c
+++ linux-ec2-2.6.32/fs/debugfs/inode.c
@@ -32,7 +32,9 @@
 static int debugfs_mount_count;
 static bool debugfs_registered;
 
-static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
+static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev,
+				       void *data, const struct file_operations *fops)
+
 {
 	struct inode *inode = new_inode(sb);
 
@@ -44,14 +46,18 @@
 			init_special_inode(inode, mode, dev);
 			break;
 		case S_IFREG:
-			inode->i_fop = &debugfs_file_operations;
+			inode->i_fop = fops ? fops : &debugfs_file_operations;
+			inode->i_private = data;
 			break;
 		case S_IFLNK:
 			inode->i_op = &debugfs_link_operations;
+			inode->i_fop = fops;
+			inode->i_private = data;
 			break;
 		case S_IFDIR:
 			inode->i_op = &simple_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
+			inode->i_fop = fops ? fops : &simple_dir_operations;
+			inode->i_private = data;
 
 			/* directory inodes start off with i_nlink == 2
 			 * (for "." entry) */
@@ -64,7 +70,8 @@
 
 /* SMP-safe */
 static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
-			 int mode, dev_t dev)
+			 int mode, dev_t dev, void *data,
+			 const struct file_operations *fops)
 {
 	struct inode *inode;
 	int error = -EPERM;
@@ -72,7 +79,7 @@
 	if (dentry->d_inode)
 		return -EEXIST;
 
-	inode = debugfs_get_inode(dir->i_sb, mode, dev);
+	inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops);
 	if (inode) {
 		d_instantiate(dentry, inode);
 		dget(dentry);
@@ -81,12 +88,13 @@
 	return error;
 }
 
-static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode,
+			 void *data, const struct file_operations *fops)
 {
 	int res;
 
 	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-	res = debugfs_mknod(dir, dentry, mode, 0);
+	res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
 	if (!res) {
 		inc_nlink(dir);
 		fsnotify_mkdir(dir, dentry);
@@ -94,18 +102,20 @@
 	return res;
 }
 
-static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode)
+static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode,
+			void *data, const struct file_operations *fops)
 {
 	mode = (mode & S_IALLUGO) | S_IFLNK;
-	return debugfs_mknod(dir, dentry, mode, 0);
+	return debugfs_mknod(dir, dentry, mode, 0, data, fops);
 }
 
-static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode,
+			  void *data, const struct file_operations *fops)
 {
 	int res;
 
 	mode = (mode & S_IALLUGO) | S_IFREG;
-	res = debugfs_mknod(dir, dentry, mode, 0);
+	res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
 	if (!res)
 		fsnotify_create(dir, dentry);
 	return res;
@@ -139,7 +149,9 @@
 
 static int debugfs_create_by_name(const char *name, mode_t mode,
 				  struct dentry *parent,
-				  struct dentry **dentry)
+				  struct dentry **dentry,
+				  void *data,
+				  const struct file_operations *fops)
 {
 	int error = 0;
 
@@ -164,13 +176,16 @@
 	if (!IS_ERR(*dentry)) {
 		switch (mode & S_IFMT) {
 		case S_IFDIR:
-			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
+			error = debugfs_mkdir(parent->d_inode, *dentry, mode,
+					      data, fops);
 			break;
 		case S_IFLNK:
-			error = debugfs_link(parent->d_inode, *dentry, mode);
+			error = debugfs_link(parent->d_inode, *dentry, mode,
+					     data, fops);
 			break;
 		default:
-			error = debugfs_create(parent->d_inode, *dentry, mode);
+			error = debugfs_create(parent->d_inode, *dentry, mode,
+					       data, fops);
 			break;
 		}
 		dput(*dentry);
@@ -221,19 +236,13 @@
 	if (error)
 		goto exit;
 
-	error = debugfs_create_by_name(name, mode, parent, &dentry);
+	error = debugfs_create_by_name(name, mode, parent, &dentry,
+				       data, fops);
 	if (error) {
 		dentry = NULL;
 		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 		goto exit;
 	}
-
-	if (dentry->d_inode) {
-		if (data)
-			dentry->d_inode->i_private = data;
-		if (fops)
-			dentry->d_inode->i_fop = fops;
-	}
 exit:
 	return dentry;
 }
--- linux-ec2-2.6.32.orig/fs/ocfs2/locks.c
+++ linux-ec2-2.6.32/fs/ocfs2/locks.c
@@ -133,7 +133,7 @@
 
 	if (!(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
-	if (__mandatory_lock(inode))
+	if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
 		return -ENOLCK;
 
 	return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
--- linux-ec2-2.6.32.orig/fs/ocfs2/super.c
+++ linux-ec2-2.6.32/fs/ocfs2/super.c
@@ -41,6 +41,7 @@
 #include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/quotaops.h>
+#include <linux/precache.h>
 #include <linux/smp_lock.h>
 
 #define MLOG_MASK_PREFIX ML_SUPER
@@ -701,6 +702,10 @@
 
 		if (!ocfs2_is_hard_readonly(osb))
 			ocfs2_set_journal_params(osb);
+
+		sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+			((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ?
+							MS_POSIXACL : 0);
 	}
 out:
 	unlock_kernel();
@@ -2228,6 +2233,7 @@
 		mlog_errno(status);
 		goto bail;
 	}
+	shared_precache_init(sb, &di->id2.i_super.s_uuid[0]);
 
 bail:
 	mlog_exit(status);
--- linux-ec2-2.6.32.orig/fs/ocfs2/acl.c
+++ linux-ec2-2.6.32/fs/ocfs2/acl.c
@@ -30,6 +30,8 @@
 #include "alloc.h"
 #include "dlmglue.h"
 #include "file.h"
+#include "inode.h"
+#include "journal.h"
 #include "ocfs2_fs.h"
 
 #include "xattr.h"
@@ -170,6 +172,60 @@
 }
 
 /*
+ * Helper function to set i_mode in memory and disk. Some call paths
+ * will not have di_bh or a journal handle to pass, in which case it
+ * will create it's own.
+ */
+static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
+			      handle_t *handle, umode_t new_mode)
+{
+	int ret, commit_handle = 0;
+	struct ocfs2_dinode *di;
+
+	if (di_bh == NULL) {
+		ret = ocfs2_read_inode_block(inode, &di_bh);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+	} else
+		get_bh(di_bh);
+
+	if (handle == NULL) {
+		handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb),
+					   OCFS2_INODE_UPDATE_CREDITS);
+		if (IS_ERR(handle)) {
+			ret = PTR_ERR(handle);
+			mlog_errno(ret);
+			goto out_brelse;
+		}
+
+		commit_handle = 1;
+	}
+
+	di = (struct ocfs2_dinode *)di_bh->b_data;
+	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
+				      OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out_commit;
+	}
+
+	inode->i_mode = new_mode;
+	di->i_mode = cpu_to_le16(inode->i_mode);
+
+	ocfs2_journal_dirty(handle, di_bh);
+
+out_commit:
+	if (commit_handle)
+		ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out_brelse:
+	brelse(di_bh);
+out:
+	return ret;
+}
+
+/*
  * Set the access or default ACL of an inode.
  */
 static int ocfs2_set_acl(handle_t *handle,
@@ -197,9 +253,14 @@
 			if (ret < 0)
 				return ret;
 			else {
-				inode->i_mode = mode;
 				if (ret == 0)
 					acl = NULL;
+
+				ret = ocfs2_acl_set_mode(inode, di_bh,
+							 handle, mode);
+				if (ret)
+					return ret;
+
 			}
 		}
 		break;
@@ -232,12 +293,30 @@
 
 int ocfs2_check_acl(struct inode *inode, int mask)
 {
-	struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct buffer_head *di_bh = NULL;
+	struct posix_acl *acl;
+	int ret = -EAGAIN;
 
-	if (IS_ERR(acl))
+	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
+		return ret;
+
+	ret = ocfs2_read_inode_block(inode, &di_bh);
+	if (ret < 0) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh);
+
+	brelse(di_bh);
+
+	if (IS_ERR(acl)) {
+		mlog_errno(PTR_ERR(acl));
 		return PTR_ERR(acl);
+	}
 	if (acl) {
-		int ret = posix_acl_permission(inode, acl, mask);
+		ret = posix_acl_permission(inode, acl, mask);
 		posix_acl_release(acl);
 		return ret;
 	}
@@ -286,7 +365,8 @@
 {
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct posix_acl *acl = NULL;
-	int ret = 0;
+	int ret = 0, ret2;
+	mode_t mode;
 
 	if (!S_ISLNK(inode->i_mode)) {
 		if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
@@ -295,12 +375,17 @@
 			if (IS_ERR(acl))
 				return PTR_ERR(acl);
 		}
-		if (!acl)
-			inode->i_mode &= ~current_umask();
+		if (!acl) {
+			mode = inode->i_mode & ~current_umask();
+			ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+			if (ret) {
+				mlog_errno(ret);
+				goto cleanup;
+			}
+		}
 	}
 	if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
 		struct posix_acl *clone;
-		mode_t mode;
 
 		if (S_ISDIR(inode->i_mode)) {
 			ret = ocfs2_set_acl(handle, inode, di_bh,
@@ -317,7 +402,12 @@
 		mode = inode->i_mode;
 		ret = posix_acl_create_masq(clone, &mode);
 		if (ret >= 0) {
-			inode->i_mode = mode;
+			ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
+			if (ret2) {
+				mlog_errno(ret2);
+				ret = ret2;
+				goto cleanup;
+			}
 			if (ret > 0) {
 				ret = ocfs2_set_acl(handle, inode,
 						    di_bh, ACL_TYPE_ACCESS,
--- linux-ec2-2.6.32.orig/fs/ocfs2/alloc.c
+++ linux-ec2-2.6.32/fs/ocfs2/alloc.c
@@ -1765,9 +1765,9 @@
  *
  * The array index of the subtree root is passed back.
  */
-static int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
-				   struct ocfs2_path *left,
-				   struct ocfs2_path *right)
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+			    struct ocfs2_path *left,
+			    struct ocfs2_path *right)
 {
 	int i = 0;
 
@@ -2872,8 +2872,8 @@
  * This looks similar, but is subtly different to
  * ocfs2_find_cpos_for_left_leaf().
  */
-static int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
-					  struct ocfs2_path *path, u32 *cpos)
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+				   struct ocfs2_path *path, u32 *cpos)
 {
 	int i, j, ret = 0;
 	u64 blkno;
--- linux-ec2-2.6.32.orig/fs/ocfs2/buffer_head_io.c
+++ linux-ec2-2.6.32/fs/ocfs2/buffer_head_io.c
@@ -407,6 +407,7 @@
 				struct buffer_head *bh)
 {
 	int ret = 0;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
 
 	mlog_entry_void();
 
@@ -426,6 +427,7 @@
 
 	get_bh(bh); /* for end_buffer_write_sync() */
 	bh->b_end_io = end_buffer_write_sync;
+	ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check);
 	submit_bh(WRITE, bh);
 
 	wait_on_buffer(bh);
--- linux-ec2-2.6.32.orig/fs/ocfs2/refcounttree.c
+++ linux-ec2-2.6.32/fs/ocfs2/refcounttree.c
@@ -969,6 +969,103 @@
 }
 
 /*
+ * Find the end range for a leaf refcount block indicated by
+ * el->l_recs[index].e_blkno.
+ */
+static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci,
+				       struct buffer_head *ref_root_bh,
+				       struct ocfs2_extent_block *eb,
+				       struct ocfs2_extent_list *el,
+				       int index,  u32 *cpos_end)
+{
+	int ret, i, subtree_root;
+	u32 cpos;
+	u64 blkno;
+	struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
+	struct ocfs2_path *left_path = NULL, *right_path = NULL;
+	struct ocfs2_extent_tree et;
+	struct ocfs2_extent_list *tmp_el;
+
+	if (index < le16_to_cpu(el->l_next_free_rec) - 1) {
+		/*
+		 * We have a extent rec after index, so just use the e_cpos
+		 * of the next extent rec.
+		 */
+		*cpos_end = le32_to_cpu(el->l_recs[index+1].e_cpos);
+		return 0;
+	}
+
+	if (!eb || (eb && !eb->h_next_leaf_blk)) {
+		/*
+		 * We are the last extent rec, so any high cpos should
+		 * be stored in this leaf refcount block.
+		 */
+		*cpos_end = UINT_MAX;
+		return 0;
+	}
+
+	/*
+	 * If the extent block isn't the last one, we have to find
+	 * the subtree root between this extent block and the next
+	 * leaf extent block and get the corresponding e_cpos from
+	 * the subroot. Otherwise we may corrupt the b-tree.
+	 */
+	ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
+
+	left_path = ocfs2_new_path_from_et(&et);
+	if (!left_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	cpos = le32_to_cpu(eb->h_list.l_recs[index].e_cpos);
+	ret = ocfs2_find_path(ci, left_path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	right_path = ocfs2_new_path_from_path(left_path);
+	if (!right_path) {
+		ret = -ENOMEM;
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_cpos_for_right_leaf(sb, left_path, &cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_find_path(ci, right_path, cpos);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	subtree_root = ocfs2_find_subtree_root(&et, left_path,
+					       right_path);
+
+	tmp_el = left_path->p_node[subtree_root].el;
+	blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
+	for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+		if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
+			*cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
+			break;
+		}
+	}
+
+	BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+
+out:
+	ocfs2_free_path(left_path);
+	ocfs2_free_path(right_path);
+	return ret;
+}
+
+/*
  * Given a cpos and len, try to find the refcount record which contains cpos.
  * 1. If cpos can be found in one refcount record, return the record.
  * 2. If cpos can't be found, return a fake record which start from cpos
@@ -983,10 +1080,10 @@
 				  struct buffer_head **ret_bh)
 {
 	int ret = 0, i, found;
-	u32 low_cpos;
+	u32 low_cpos, uninitialized_var(cpos_end);
 	struct ocfs2_extent_list *el;
-	struct ocfs2_extent_rec *tmp, *rec = NULL;
-	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_rec *rec = NULL;
+	struct ocfs2_extent_block *eb = NULL;
 	struct buffer_head *eb_bh = NULL, *ref_leaf_bh = NULL;
 	struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
 	struct ocfs2_refcount_block *rb =
@@ -1034,12 +1131,16 @@
 		}
 	}
 
-	/* adjust len when we have ocfs2_extent_rec after it. */
-	if (found && i < le16_to_cpu(el->l_next_free_rec) - 1) {
-		tmp = &el->l_recs[i+1];
+	if (found) {
+		ret = ocfs2_get_refcount_cpos_end(ci, ref_root_bh,
+						  eb, el, i, &cpos_end);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
 
-		if (le32_to_cpu(tmp->e_cpos) < cpos + len)
-			len = le32_to_cpu(tmp->e_cpos) - cpos;
+		if (cpos_end < low_cpos + len)
+			len = cpos_end - low_cpos;
 	}
 
 	ret = ocfs2_read_refcount_block(ci, le64_to_cpu(rec->e_blkno),
@@ -2353,16 +2454,26 @@
 		len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) +
 			  le32_to_cpu(rec.r_clusters)) - cpos;
 		/*
-		 * If the refcount rec already exist, cool. We just need
-		 * to check whether there is a split. Otherwise we just need
-		 * to increase the refcount.
-		 * If we will insert one, increases recs_add.
-		 *
 		 * We record all the records which will be inserted to the
 		 * same refcount block, so that we can tell exactly whether
 		 * we need a new refcount block or not.
+		 *
+		 * If we will insert a new one, this is easy and only happens
+		 * during adding refcounted flag to the extent, so we don't
+		 * have a chance of spliting. We just need one record.
+		 *
+		 * If the refcount rec already exists, that would be a little
+		 * complicated. we may have to:
+		 * 1) split at the beginning if the start pos isn't aligned.
+		 *    we need 1 more record in this case.
+		 * 2) split int the end if the end pos isn't aligned.
+		 *    we need 1 more record in this case.
+		 * 3) split in the middle because of file system fragmentation.
+		 *    we need 2 more records in this case(we can't detect this
+		 *    beforehand, so always think of the worst case).
 		 */
 		if (rec.r_refcount) {
+			recs_add += 2;
 			/* Check whether we need a split at the beginning. */
 			if (cpos == start_cpos &&
 			    cpos != le64_to_cpu(rec.r_cpos))
@@ -3125,7 +3236,7 @@
 					u32 num_clusters, unsigned int e_flags)
 {
 	int ret, delete, index, credits =  0;
-	u32 new_bit, new_len;
+	u32 new_bit, new_len, orig_num_clusters;
 	unsigned int set_len;
 	struct ocfs2_super *osb = OCFS2_SB(sb);
 	handle_t *handle;
@@ -3158,6 +3269,8 @@
 		goto out;
 	}
 
+	orig_num_clusters = num_clusters;
+
 	while (num_clusters) {
 		ret = ocfs2_get_refcount_rec(ref_ci, context->ref_root_bh,
 					     p_cluster, num_clusters,
@@ -3245,7 +3358,8 @@
 	 * in write-back mode.
 	 */
 	if (context->get_clusters == ocfs2_di_get_clusters) {
-		ret = ocfs2_cow_sync_writeback(sb, context, cpos, num_clusters);
+		ret = ocfs2_cow_sync_writeback(sb, context, cpos,
+					       orig_num_clusters);
 		if (ret)
 			mlog_errno(ret);
 	}
@@ -3995,6 +4109,9 @@
 	di->i_attr = s_di->i_attr;
 
 	if (preserve) {
+		t_inode->i_uid = s_inode->i_uid;
+		t_inode->i_gid = s_inode->i_gid;
+		t_inode->i_mode = s_inode->i_mode;
 		di->i_uid = s_di->i_uid;
 		di->i_gid = s_di->i_gid;
 		di->i_mode = s_di->i_mode;
--- linux-ec2-2.6.32.orig/fs/ocfs2/suballoc.c
+++ linux-ec2-2.6.32/fs/ocfs2/suballoc.c
@@ -152,7 +152,7 @@
 
 #define do_error(fmt, ...)						\
 	do{								\
-		if (clean_error)					\
+		if (resize)					\
 			mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__);	\
 		else							\
 			ocfs2_error(sb, fmt, ##__VA_ARGS__);		\
@@ -160,7 +160,7 @@
 
 static int ocfs2_validate_gd_self(struct super_block *sb,
 				  struct buffer_head *bh,
-				  int clean_error)
+				  int resize)
 {
 	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
 
@@ -211,7 +211,7 @@
 static int ocfs2_validate_gd_parent(struct super_block *sb,
 				    struct ocfs2_dinode *di,
 				    struct buffer_head *bh,
-				    int clean_error)
+				    int resize)
 {
 	unsigned int max_bits;
 	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
@@ -233,8 +233,11 @@
 		return -EINVAL;
 	}
 
-	if (le16_to_cpu(gd->bg_chain) >=
-	    le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
+	/* In resize, we may meet the case bg_chain == cl_next_free_rec. */
+	if ((le16_to_cpu(gd->bg_chain) >
+	     le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) ||
+	    ((le16_to_cpu(gd->bg_chain) ==
+	     le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) {
 		do_error("Group descriptor #%llu has bad chain %u",
 			 (unsigned long long)bh->b_blocknr,
 			 le16_to_cpu(gd->bg_chain));
--- linux-ec2-2.6.32.orig/fs/ocfs2/inode.c
+++ linux-ec2-2.6.32/fs/ocfs2/inode.c
@@ -485,7 +485,11 @@
 						     OCFS2_BH_IGNORE_CACHE);
 	} else {
 		status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
-		if (!status)
+		/*
+		 * If buffer is in jbd, then its checksum may not have been
+		 * computed as yet.
+		 */
+		if (!status && !buffer_jbd(bh))
 			status = ocfs2_validate_inode_block(osb->sb, bh);
 	}
 	if (status < 0) {
@@ -559,6 +563,7 @@
 		handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
 		if (IS_ERR(handle)) {
 			status = PTR_ERR(handle);
+			handle = NULL;
 			mlog_errno(status);
 			goto out;
 		}
--- linux-ec2-2.6.32.orig/fs/ocfs2/aops.c
+++ linux-ec2-2.6.32/fs/ocfs2/aops.c
@@ -591,8 +591,9 @@
 		goto bail;
 	}
 
-	/* We should already CoW the refcounted extent. */
-	BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
+	/* We should already CoW the refcounted extent in case of create. */
+	BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED));
+
 	/*
 	 * get_more_blocks() expects us to describe a hole by clearing
 	 * the mapped bit on bh_result().
@@ -1090,6 +1091,12 @@
 	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
 					&cluster_start, &cluster_end);
 
+	/* treat the write as new if the a hole/lseek spanned across
+	 * the page boundary.
+	 */
+	new = new | ((i_size_read(inode) <= page_offset(page)) &&
+			(page_offset(page) <= user_pos));
+
 	if (page == wc->w_target_page) {
 		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
 		map_to = map_from + user_len;
--- linux-ec2-2.6.32.orig/fs/ocfs2/stack_user.c
+++ linux-ec2-2.6.32/fs/ocfs2/stack_user.c
@@ -191,7 +191,7 @@
 			return c;
 	}
 
-	return c;
+	return NULL;
 }
 
 /*
--- linux-ec2-2.6.32.orig/fs/ocfs2/symlink.c
+++ linux-ec2-2.6.32/fs/ocfs2/symlink.c
@@ -128,7 +128,7 @@
 	}
 
 	/* Fast symlinks can't be large */
-	len = strlen(target);
+	len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb));
 	link = kzalloc(len + 1, GFP_NOFS);
 	if (!link) {
 		status = -ENOMEM;
--- linux-ec2-2.6.32.orig/fs/ocfs2/alloc.h
+++ linux-ec2-2.6.32/fs/ocfs2/alloc.h
@@ -317,4 +317,9 @@
 int ocfs2_journal_access_path(struct ocfs2_caching_info *ci,
 			      handle_t *handle,
 			      struct ocfs2_path *path);
+int ocfs2_find_cpos_for_right_leaf(struct super_block *sb,
+				   struct ocfs2_path *path, u32 *cpos);
+int ocfs2_find_subtree_root(struct ocfs2_extent_tree *et,
+			    struct ocfs2_path *left,
+			    struct ocfs2_path *right);
 #endif /* OCFS2_ALLOC_H */
--- linux-ec2-2.6.32.orig/fs/ocfs2/dlm/dlmthread.c
+++ linux-ec2-2.6.32/fs/ocfs2/dlm/dlmthread.c
@@ -93,19 +93,27 @@
  * truly ready to be freed. */
 int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
-	if (!__dlm_lockres_has_locks(res) &&
-	    (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) {
-		/* try not to scan the bitmap unless the first two
-		 * conditions are already true */
-		int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
-		if (bit >= O2NM_MAX_NODES) {
-			/* since the bit for dlm->node_num is not
-			 * set, inflight_locks better be zero */
-			BUG_ON(res->inflight_locks != 0);
-			return 1;
-		}
-	}
-	return 0;
+	int bit;
+
+	if (__dlm_lockres_has_locks(res))
+		return 0;
+
+	if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
+		return 0;
+
+	if (res->state & DLM_LOCK_RES_RECOVERING)
+		return 0;
+
+	bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
+	if (bit < O2NM_MAX_NODES)
+		return 0;
+
+	/*
+	 * since the bit for dlm->node_num is not set, inflight_locks better
+	 * be zero
+	 */
+	BUG_ON(res->inflight_locks != 0);
+	return 1;
 }
 
 
@@ -153,45 +161,25 @@
 	spin_unlock(&dlm->spinlock);
 }
 
-static int dlm_purge_lockres(struct dlm_ctxt *dlm,
+static void dlm_purge_lockres(struct dlm_ctxt *dlm,
 			     struct dlm_lock_resource *res)
 {
 	int master;
 	int ret = 0;
 
-	spin_lock(&res->spinlock);
-	if (!__dlm_lockres_unused(res)) {
-		mlog(0, "%s:%.*s: tried to purge but not unused\n",
-		     dlm->name, res->lockname.len, res->lockname.name);
-		__dlm_print_one_lock_resource(res);
-		spin_unlock(&res->spinlock);
-		BUG();
-	}
-
-	if (res->state & DLM_LOCK_RES_MIGRATING) {
-		mlog(0, "%s:%.*s: Delay dropref as this lockres is "
-		     "being remastered\n", dlm->name, res->lockname.len,
-		     res->lockname.name);
-		/* Re-add the lockres to the end of the purge list */
-		if (!list_empty(&res->purge)) {
-			list_del_init(&res->purge);
-			list_add_tail(&res->purge, &dlm->purge_list);
-		}
-		spin_unlock(&res->spinlock);
-		return 0;
-	}
+	assert_spin_locked(&dlm->spinlock);
+	assert_spin_locked(&res->spinlock);
 
 	master = (res->owner == dlm->node_num);
 
-	if (!master)
-		res->state |= DLM_LOCK_RES_DROPPING_REF;
-	spin_unlock(&res->spinlock);
 
 	mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len,
 	     res->lockname.name, master);
 
 	if (!master) {
+		res->state |= DLM_LOCK_RES_DROPPING_REF;
 		/* drop spinlock...  retake below */
+		spin_unlock(&res->spinlock);
 		spin_unlock(&dlm->spinlock);
 
 		spin_lock(&res->spinlock);
@@ -209,31 +197,35 @@
 		mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n",
 		     dlm->name, res->lockname.len, res->lockname.name, ret);
 		spin_lock(&dlm->spinlock);
+		spin_lock(&res->spinlock);
 	}
 
-	spin_lock(&res->spinlock);
 	if (!list_empty(&res->purge)) {
 		mlog(0, "removing lockres %.*s:%p from purgelist, "
 		     "master = %d\n", res->lockname.len, res->lockname.name,
 		     res, master);
 		list_del_init(&res->purge);
-		spin_unlock(&res->spinlock);
 		dlm_lockres_put(res);
 		dlm->purge_count--;
-	} else
-		spin_unlock(&res->spinlock);
+	}
+
+	if (!__dlm_lockres_unused(res)) {
+		mlog(ML_ERROR, "found lockres %s:%.*s: in use after deref\n",
+		     dlm->name, res->lockname.len, res->lockname.name);
+		__dlm_print_one_lock_resource(res);
+		BUG();
+	}
 
 	__dlm_unhash_lockres(res);
 
 	/* lockres is not in the hash now.  drop the flag and wake up
 	 * any processes waiting in dlm_get_lock_resource. */
 	if (!master) {
-		spin_lock(&res->spinlock);
 		res->state &= ~DLM_LOCK_RES_DROPPING_REF;
 		spin_unlock(&res->spinlock);
 		wake_up(&res->wq);
-	}
-	return 0;
+	} else
+		spin_unlock(&res->spinlock);
 }
 
 static void dlm_run_purge_list(struct dlm_ctxt *dlm,
@@ -252,17 +244,7 @@
 		lockres = list_entry(dlm->purge_list.next,
 				     struct dlm_lock_resource, purge);
 
-		/* Status of the lockres *might* change so double
-		 * check. If the lockres is unused, holding the dlm
-		 * spinlock will prevent people from getting and more
-		 * refs on it -- there's no need to keep the lockres
-		 * spinlock. */
 		spin_lock(&lockres->spinlock);
-		unused = __dlm_lockres_unused(lockres);
-		spin_unlock(&lockres->spinlock);
-
-		if (!unused)
-			continue;
 
 		purge_jiffies = lockres->last_used +
 			msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);
@@ -274,15 +256,29 @@
 			 * in tail order, we can stop at the first
 			 * unpurgable resource -- anyone added after
 			 * him will have a greater last_used value */
+			spin_unlock(&lockres->spinlock);
 			break;
 		}
 
+		/* Status of the lockres *might* change so double
+		 * check. If the lockres is unused, holding the dlm
+		 * spinlock will prevent people from getting and more
+		 * refs on it. */
+		unused = __dlm_lockres_unused(lockres);
+		if (!unused ||
+		    (lockres->state & DLM_LOCK_RES_MIGRATING)) {
+			mlog(0, "lockres %s:%.*s: is in use or "
+			     "being remastered, used %d, state %d\n",
+			     dlm->name, lockres->lockname.len,
+			     lockres->lockname.name, !unused, lockres->state);
+			list_move_tail(&dlm->purge_list, &lockres->purge);
+			spin_unlock(&lockres->spinlock);
+			continue;
+		}
+
 		dlm_lockres_get(lockres);
 
-		/* This may drop and reacquire the dlm spinlock if it
-		 * has to do migration. */
-		if (dlm_purge_lockres(dlm, lockres))
-			BUG();
+		dlm_purge_lockres(dlm, lockres);
 
 		dlm_lockres_put(lockres);
 
--- linux-ec2-2.6.32.orig/fs/ocfs2/dlm/dlmmaster.c
+++ linux-ec2-2.6.32/fs/ocfs2/dlm/dlmmaster.c
@@ -511,8 +511,6 @@
 
 	atomic_dec(&dlm->res_cur_count);
 
-	dlm_put(dlm);
-
 	if (!hlist_unhashed(&res->hash_node) ||
 	    !list_empty(&res->granted) ||
 	    !list_empty(&res->converting) ||
@@ -585,8 +583,6 @@
 	res->migration_pending = 0;
 	res->inflight_locks = 0;
 
-	/* put in dlm_lockres_release */
-	dlm_grab(dlm);
 	res->dlm = dlm;
 
 	kref_init(&res->refs);
@@ -3046,8 +3042,6 @@
 	/* check for pre-existing lock */
 	spin_lock(&dlm->spinlock);
 	res = __dlm_lookup_lockres(dlm, name, namelen, hash);
-	spin_lock(&dlm->master_lock);
-
 	if (res) {
 		spin_lock(&res->spinlock);
 		if (res->state & DLM_LOCK_RES_RECOVERING) {
@@ -3065,14 +3059,15 @@
 		spin_unlock(&res->spinlock);
 	}
 
+	spin_lock(&dlm->master_lock);
 	/* ignore status.  only nonzero status would BUG. */
 	ret = dlm_add_migration_mle(dlm, res, mle, &oldmle,
 				    name, namelen,
 				    migrate->new_master,
 				    migrate->master);
 
-unlock:
 	spin_unlock(&dlm->master_lock);
+unlock:
 	spin_unlock(&dlm->spinlock);
 
 	if (oldmle) {
--- linux-ec2-2.6.32.orig/fs/ocfs2/dlm/dlmrecovery.c
+++ linux-ec2-2.6.32/fs/ocfs2/dlm/dlmrecovery.c
@@ -1941,6 +1941,8 @@
 	struct list_head *queue;
 	struct dlm_lock *lock, *next;
 
+	assert_spin_locked(&dlm->spinlock);
+	assert_spin_locked(&res->spinlock);
 	res->state |= DLM_LOCK_RES_RECOVERING;
 	if (!list_empty(&res->recovering)) {
 		mlog(0,
@@ -2265,19 +2267,15 @@
 			/* zero the lvb if necessary */
 			dlm_revalidate_lvb(dlm, res, dead_node);
 			if (res->owner == dead_node) {
-				if (res->state & DLM_LOCK_RES_DROPPING_REF)
-					mlog(0, "%s:%.*s: owned by "
-					     "dead node %u, this node was "
-					     "dropping its ref when it died. "
-					     "continue, dropping the flag.\n",
-					     dlm->name, res->lockname.len,
-					     res->lockname.name, dead_node);
-
-				/* the wake_up for this will happen when the
-				 * RECOVERING flag is dropped later */
-				res->state &= ~DLM_LOCK_RES_DROPPING_REF;
+				if (res->state & DLM_LOCK_RES_DROPPING_REF) {
+					mlog(ML_NOTICE, "Ignore %.*s for "
+					     "recovery as it is being freed\n",
+					     res->lockname.len,
+					     res->lockname.name);
+				} else
+					dlm_move_lockres_to_recovery_list(dlm,
+									  res);
 
-				dlm_move_lockres_to_recovery_list(dlm, res);
 			} else if (res->owner == dlm->node_num) {
 				dlm_free_dead_locks(dlm, res, dead_node);
 				__dlm_lockres_calc_usage(dlm, res);
--- linux-ec2-2.6.32.orig/fs/ocfs2/dlm/dlmfs.c
+++ linux-ec2-2.6.32/fs/ocfs2/dlm/dlmfs.c
@@ -205,7 +205,7 @@
 	if ((count + *ppos) > i_size_read(inode))
 		readlen = i_size_read(inode) - *ppos;
 	else
-		readlen = count - *ppos;
+		readlen = count;
 
 	lvb_buf = kmalloc(readlen, GFP_NOFS);
 	if (!lvb_buf)
--- linux-ec2-2.6.32.orig/fs/notify/inotify/inotify_user.c
+++ linux-ec2-2.6.32/fs/notify/inotify/inotify_user.c
@@ -106,8 +106,11 @@
 {
 	__u32 mask;
 
-	/* everything should accept their own ignored and cares about children */
-	mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD);
+	/*
+	 * everything should accept their own ignored, cares about children,
+	 * and should receive events when the inode is unmounted
+	 */
+	mask = (FS_IN_IGNORED | FS_EVENT_ON_CHILD | FS_UNMOUNT);
 
 	/* mask off the flags used to open the fd */
 	mask |= (arg & (IN_ALL_EVENTS | IN_ONESHOT));
@@ -556,21 +559,24 @@
 	if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
 		goto out_err;
 
+	/* we are putting the mark on the idr, take a reference */
+	fsnotify_get_mark(&tmp_ientry->fsn_entry);
+
 	spin_lock(&group->inotify_data.idr_lock);
 	ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
-				group->inotify_data.last_wd,
+				group->inotify_data.last_wd+1,
 				&tmp_ientry->wd);
 	spin_unlock(&group->inotify_data.idr_lock);
 	if (ret) {
+		/* we didn't get on the idr, drop the idr reference */
+		fsnotify_put_mark(&tmp_ientry->fsn_entry);
+
 		/* idr was out of memory allocate and try again */
 		if (ret == -EAGAIN)
 			goto retry;
 		goto out_err;
 	}
 
-	/* we put the mark on the idr, take a reference */
-	fsnotify_get_mark(&tmp_ientry->fsn_entry);
-
 	/* we are on the idr, now get on the inode */
 	ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
 	if (ret) {
@@ -638,7 +644,7 @@
 
 	spin_lock_init(&group->inotify_data.idr_lock);
 	idr_init(&group->inotify_data.idr);
-	group->inotify_data.last_wd = 1;
+	group->inotify_data.last_wd = 0;
 	group->inotify_data.user = user;
 	group->inotify_data.fa = NULL;
 
--- linux-ec2-2.6.32.orig/fs/notify/inotify/inotify_fsnotify.c
+++ linux-ec2-2.6.32/fs/notify/inotify/inotify_fsnotify.c
@@ -28,6 +28,7 @@
 #include <linux/path.h> /* struct path */
 #include <linux/slab.h> /* kmem_* */
 #include <linux/types.h>
+#include <linux/sched.h>
 
 #include "inotify.h"
 
@@ -71,6 +72,9 @@
 			ret = 0;
 	}
 
+	if (entry->mask & IN_ONESHOT)
+		fsnotify_destroy_mark_by_entry(entry);
+
 	/*
 	 * If we hold the entry until after the event is on the queue
 	 * IN_IGNORED won't be able to pass this event in the queue
@@ -121,7 +125,7 @@
 	if (warned)
 		return 0;
 
-	warned = false;
+	warned = true;
 	entry = p;
 	ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
 
@@ -146,6 +150,7 @@
 	idr_for_each(&group->inotify_data.idr, idr_callback, group);
 	idr_remove_all(&group->inotify_data.idr);
 	idr_destroy(&group->inotify_data.idr);
+	free_uid(group->inotify_data.user);
 }
 
 void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
--- linux-ec2-2.6.32.orig/fs/gfs2/xattr.c
+++ linux-ec2-2.6.32/fs/gfs2/xattr.c
@@ -1507,18 +1507,6 @@
 	return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
 }
 
-static int gfs2_xattr_system_get(struct inode *inode, const char *name,
-				 void *buffer, size_t size)
-{
-	return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size);
-}
-
-static int gfs2_xattr_system_set(struct inode *inode, const char *name,
-				 const void *value, size_t size, int flags)
-{
-	return gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, flags);
-}
-
 static int gfs2_xattr_security_get(struct inode *inode, const char *name,
 				   void *buffer, size_t size)
 {
@@ -1543,12 +1531,6 @@
 	.set    = gfs2_xattr_security_set,
 };
 
-static struct xattr_handler gfs2_xattr_system_handler = {
-	.prefix = XATTR_SYSTEM_PREFIX,
-	.get    = gfs2_xattr_system_get,
-	.set    = gfs2_xattr_system_set,
-};
-
 struct xattr_handler *gfs2_xattr_handlers[] = {
 	&gfs2_xattr_user_handler,
 	&gfs2_xattr_security_handler,
--- linux-ec2-2.6.32.orig/fs/gfs2/bmap.c
+++ linux-ec2-2.6.32/fs/gfs2/bmap.c
@@ -541,7 +541,7 @@
 				*ptr++ = cpu_to_be64(bn++);
 			break;
 		}
-	} while (state != ALLOC_DATA);
+	} while ((state != ALLOC_DATA) || !dblock);
 
 	ip->i_height = height;
 	gfs2_add_inode_blocks(&ip->i_inode, alloced);
--- linux-ec2-2.6.32.orig/fs/gfs2/dir.c
+++ linux-ec2-2.6.32/fs/gfs2/dir.c
@@ -392,7 +392,7 @@
 	unsigned totlen = be16_to_cpu(dent->de_rec_len);
 
 	if (gfs2_dirent_sentinel(dent))
-		actual = GFS2_DIRENT_SIZE(0);
+		actual = 0;
 	if (totlen - actual >= required)
 		return 1;
 	return 0;
--- linux-ec2-2.6.32.orig/fs/gfs2/acl.c
+++ linux-ec2-2.6.32/fs/gfs2/acl.c
@@ -12,6 +12,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/buffer_head.h>
+#include <linux/xattr.h>
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/gfs2_ondisk.h>
@@ -26,61 +27,6 @@
 #include "trans.h"
 #include "util.h"
 
-#define ACL_ACCESS 1
-#define ACL_DEFAULT 0
-
-int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
-			  struct gfs2_ea_request *er, int *remove, mode_t *mode)
-{
-	struct posix_acl *acl;
-	int error;
-
-	error = gfs2_acl_validate_remove(ip, access);
-	if (error)
-		return error;
-
-	if (!er->er_data)
-		return -EINVAL;
-
-	acl = posix_acl_from_xattr(er->er_data, er->er_data_len);
-	if (IS_ERR(acl))
-		return PTR_ERR(acl);
-	if (!acl) {
-		*remove = 1;
-		return 0;
-	}
-
-	error = posix_acl_valid(acl);
-	if (error)
-		goto out;
-
-	if (access) {
-		error = posix_acl_equiv_mode(acl, mode);
-		if (!error)
-			*remove = 1;
-		else if (error > 0)
-			error = 0;
-	}
-
-out:
-	posix_acl_release(acl);
-	return error;
-}
-
-int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
-{
-	if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
-		return -EOPNOTSUPP;
-	if (!is_owner_or_cap(&ip->i_inode))
-		return -EPERM;
-	if (S_ISLNK(ip->i_inode.i_mode))
-		return -EOPNOTSUPP;
-	if (!access && !S_ISDIR(ip->i_inode.i_mode))
-		return -EACCES;
-
-	return 0;
-}
-
 static int acl_get(struct gfs2_inode *ip, const char *name,
 		   struct posix_acl **acl, struct gfs2_ea_location *el,
 		   char **datap, unsigned int *lenp)
@@ -277,3 +223,117 @@
 	return error;
 }
 
+static int gfs2_acl_type(const char *name)
+{
+	if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
+		return ACL_TYPE_ACCESS;
+	if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
+		return ACL_TYPE_DEFAULT;
+	return -EINVAL;
+}
+
+static int gfs2_xattr_system_get(struct inode *inode, const char *name,
+				 void *buffer, size_t size)
+{
+	int type;
+
+	type = gfs2_acl_type(name);
+	if (type < 0)
+		return type;
+
+	return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size);
+}
+
+static int gfs2_set_mode(struct inode *inode, mode_t mode)
+{
+	int error = 0;
+
+	if (mode != inode->i_mode) {
+		struct iattr iattr;
+
+		iattr.ia_valid = ATTR_MODE;
+		iattr.ia_mode = mode;
+
+		error = gfs2_setattr_simple(GFS2_I(inode), &iattr);
+	}
+
+	return error;
+}
+
+static int gfs2_xattr_system_set(struct inode *inode, const char *name,
+				 const void *value, size_t size, int flags)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct posix_acl *acl = NULL;
+	int error = 0, type;
+
+	if (!sdp->sd_args.ar_posix_acl)
+		return -EOPNOTSUPP;
+
+	type = gfs2_acl_type(name);
+	if (type < 0)
+		return type;
+	if (flags & XATTR_CREATE)
+		return -EINVAL;
+	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+		return value ? -EACCES : 0;
+	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	if (!value)
+		goto set_acl;
+
+	acl = posix_acl_from_xattr(value, size);
+	if (!acl) {
+		/*
+		 * acl_set_file(3) may request that we set default ACLs with
+		 * zero length -- defend (gracefully) against that here.
+		 */
+		goto out;
+	}
+	if (IS_ERR(acl)) {
+		error = PTR_ERR(acl);
+		goto out;
+	}
+
+	error = posix_acl_valid(acl);
+	if (error)
+		goto out_release;
+
+	error = -EINVAL;
+	if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
+		goto out_release;
+
+	if (type == ACL_TYPE_ACCESS) {
+		mode_t mode = inode->i_mode;
+		error = posix_acl_equiv_mode(acl, &mode);
+
+		if (error <= 0) {
+			posix_acl_release(acl);
+			acl = NULL;
+
+			if (error < 0)
+				return error;
+		}
+
+		error = gfs2_set_mode(inode, mode);
+		if (error)
+			goto out_release;
+	}
+
+set_acl:
+	error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
+out_release:
+	posix_acl_release(acl);
+out:
+	return error;
+}
+
+struct xattr_handler gfs2_xattr_system_handler = {
+	.prefix = XATTR_SYSTEM_PREFIX,
+	.get    = gfs2_xattr_system_get,
+	.set    = gfs2_xattr_system_set,
+};
+
--- linux-ec2-2.6.32.orig/fs/gfs2/acl.h
+++ linux-ec2-2.6.32/fs/gfs2/acl.h
@@ -13,26 +13,12 @@
 #include "incore.h"
 
 #define GFS2_POSIX_ACL_ACCESS		"posix_acl_access"
-#define GFS2_POSIX_ACL_ACCESS_LEN	16
 #define GFS2_POSIX_ACL_DEFAULT		"posix_acl_default"
-#define GFS2_POSIX_ACL_DEFAULT_LEN	17
+#define GFS2_ACL_MAX_ENTRIES		25
 
-#define GFS2_ACL_IS_ACCESS(name, len) \
-         ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \
-         !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len)))
-
-#define GFS2_ACL_IS_DEFAULT(name, len) \
-         ((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \
-         !memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len)))
-
-struct gfs2_ea_request;
-
-int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
-			  struct gfs2_ea_request *er,
-			  int *remove, mode_t *mode);
-int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access);
-int gfs2_check_acl(struct inode *inode, int mask);
-int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
-int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
+extern int gfs2_check_acl(struct inode *inode, int mask);
+extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
+extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
+extern struct xattr_handler gfs2_xattr_system_handler;
 
 #endif /* __ACL_DOT_H__ */
--- linux-ec2-2.6.32.orig/fs/gfs2/quota.c
+++ linux-ec2-2.6.32/fs/gfs2/quota.c
@@ -15,7 +15,7 @@
  * fuzziness in the current usage value of IDs that are being used on different
  * nodes in the cluster simultaneously.  So, it is possible for a user on
  * multiple nodes to overrun their quota, but that overrun is controlable.
- * Since quota tags are part of transactions, there is no need to a quota check
+ * Since quota tags are part of transactions, there is no need for a quota check
  * program to be run on node crashes or anything like that.
  *
  * There are couple of knobs that let the administrator manage the quota
@@ -65,13 +65,6 @@
 #define QUOTA_USER 1
 #define QUOTA_GROUP 0
 
-struct gfs2_quota_host {
-	u64 qu_limit;
-	u64 qu_warn;
-	s64 qu_value;
-	u32 qu_ll_next;
-};
-
 struct gfs2_quota_change_host {
 	u64 qc_change;
 	u32 qc_flags; /* GFS2_QCF_... */
@@ -617,33 +610,19 @@
 	mutex_unlock(&sdp->sd_quota_mutex);
 }
 
-static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
-{
-	const struct gfs2_quota *str = buf;
-
-	qu->qu_limit = be64_to_cpu(str->qu_limit);
-	qu->qu_warn = be64_to_cpu(str->qu_warn);
-	qu->qu_value = be64_to_cpu(str->qu_value);
-	qu->qu_ll_next = be32_to_cpu(str->qu_ll_next);
-}
-
-static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
-{
-	struct gfs2_quota *str = buf;
-
-	str->qu_limit = cpu_to_be64(qu->qu_limit);
-	str->qu_warn = cpu_to_be64(qu->qu_warn);
-	str->qu_value = cpu_to_be64(qu->qu_value);
-	str->qu_ll_next = cpu_to_be32(qu->qu_ll_next);
-	memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
-}
-
 /**
- * gfs2_adjust_quota
+ * gfs2_adjust_quota - adjust record of current block usage
+ * @ip: The quota inode
+ * @loc: Offset of the entry in the quota file
+ * @change: The amount of change to record
+ * @qd: The quota data
  *
  * This function was mostly borrowed from gfs2_block_truncate_page which was
  * in turn mostly borrowed from ext3
+ *
+ * Returns: 0 or -ve on error
  */
+
 static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
 			     s64 change, struct gfs2_quota_data *qd)
 {
@@ -654,15 +633,29 @@
 	unsigned blocksize, iblock, pos;
 	struct buffer_head *bh;
 	struct page *page;
-	void *kaddr;
-	char *ptr;
-	struct gfs2_quota_host qp;
-	s64 value;
-	int err = -EIO;
+	void *kaddr, *ptr;
+	struct gfs2_quota q, *qp;
+	int err, nbytes;
 
 	if (gfs2_is_stuffed(ip))
 		gfs2_unstuff_dinode(ip, NULL);
-	
+
+	memset(&q, 0, sizeof(struct gfs2_quota));
+	err = gfs2_internal_read(ip, NULL, (char *)&q, &loc, sizeof(q));
+	if (err < 0)
+		return err;
+
+	err = -EIO;
+	qp = &q;
+	qp->qu_value = be64_to_cpu(qp->qu_value);
+	qp->qu_value += change;
+	qp->qu_value = cpu_to_be64(qp->qu_value);
+	qd->qd_qb.qb_value = qp->qu_value;
+
+	/* Write the quota into the quota file on disk */
+	ptr = qp;
+	nbytes = sizeof(struct gfs2_quota);
+get_a_page:
 	page = grab_cache_page(mapping, index);
 	if (!page)
 		return -ENOMEM;
@@ -684,7 +677,10 @@
 	if (!buffer_mapped(bh)) {
 		gfs2_block_map(inode, iblock, bh, 1);
 		if (!buffer_mapped(bh))
-			goto unlock;
+			goto unlock_out;
+		/* If it's a newly allocated disk block for quota, zero it */
+		if (buffer_new(bh))
+			zero_user(page, pos - blocksize, bh->b_size);
 	}
 
 	if (PageUptodate(page))
@@ -694,25 +690,32 @@
 		ll_rw_block(READ_META, 1, &bh);
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh))
-			goto unlock;
+			goto unlock_out;
 	}
 
 	gfs2_trans_add_bh(ip->i_gl, bh, 0);
 
 	kaddr = kmap_atomic(page, KM_USER0);
-	ptr = kaddr + offset;
-	gfs2_quota_in(&qp, ptr);
-	qp.qu_value += change;
-	value = qp.qu_value;
-	gfs2_quota_out(&qp, ptr);
+	if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE)
+		nbytes = PAGE_CACHE_SIZE - offset;
+	memcpy(kaddr + offset, ptr, nbytes);
 	flush_dcache_page(page);
 	kunmap_atomic(kaddr, KM_USER0);
+	unlock_page(page);
+	page_cache_release(page);
+
+	/* If quota straddles page boundary, we need to update the rest of the
+	 * quota at the beginning of the next page */
+	if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) {
+		ptr = ptr + nbytes;
+		nbytes = sizeof(struct gfs2_quota) - nbytes;
+		offset = 0;
+		index++;
+		goto get_a_page;
+	}
 	err = 0;
-	qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
-	qd->qd_qb.qb_value = cpu_to_be64(value);
-	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
-	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
-unlock:
+	return err;
+unlock_out:
 	unlock_page(page);
 	page_cache_release(page);
 	return err;
@@ -740,8 +743,7 @@
 
 	sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL);
 	for (qx = 0; qx < num_qd; qx++) {
-		error = gfs2_glock_nq_init(qda[qx]->qd_gl,
-					   LM_ST_EXCLUSIVE,
+		error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE,
 					   GL_NOCACHE, &ghs[qx]);
 		if (error)
 			goto out;
@@ -776,8 +778,10 @@
 	 * rgrp since it won't be allocated during the transaction
 	 */
 	al->al_requested = 1;
-	/* +1 in the end for block requested above for unstuffing */
-	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 1;
+	/* +3 in the end for unstuffing block, inode size update block
+	 * and another block in case quota straddles page boundary and
+	 * two blocks need to be updated instead of 1 */
+	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3;
 
 	if (nalloc)
 		al->al_requested += nalloc * (data_blocks + ind_blocks);		
@@ -796,8 +800,7 @@
 		qd = qda[x];
 		offset = qd2offset(qd);
 		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
-					  (struct gfs2_quota_data *)
-					  qd);
+					  (struct gfs2_quota_data *)qd);
 		if (error)
 			goto out_end_trans;
 
@@ -828,8 +831,7 @@
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
 	struct gfs2_holder i_gh;
-	struct gfs2_quota_host q;
-	char buf[sizeof(struct gfs2_quota)];
+	struct gfs2_quota q;
 	int error;
 	struct gfs2_quota_lvb *qlvb;
 
@@ -853,22 +855,23 @@
 		if (error)
 			goto fail;
 
-		memset(buf, 0, sizeof(struct gfs2_quota));
+		memset(&q, 0, sizeof(struct gfs2_quota));
 		pos = qd2offset(qd);
-		error = gfs2_internal_read(ip, NULL, buf, &pos,
-					   sizeof(struct gfs2_quota));
+		error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q));
 		if (error < 0)
 			goto fail_gunlock;
-
+		if ((error < sizeof(q)) && force_refresh) {
+			error = -ENOENT;
+			goto fail_gunlock;
+		}
 		gfs2_glock_dq_uninit(&i_gh);
 
-		gfs2_quota_in(&q, buf);
 		qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
 		qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC);
 		qlvb->__pad = 0;
-		qlvb->qb_limit = cpu_to_be64(q.qu_limit);
-		qlvb->qb_warn = cpu_to_be64(q.qu_warn);
-		qlvb->qb_value = cpu_to_be64(q.qu_value);
+		qlvb->qb_limit = q.qu_limit;
+		qlvb->qb_warn = q.qu_warn;
+		qlvb->qb_value = q.qu_value;
 		qd->qd_qb = *qlvb;
 
 		if (gfs2_glock_is_blocking(qd->qd_gl)) {
@@ -1127,7 +1130,6 @@
 		gfs2_glock_dq_uninit(&q_gh);
 
 	qd_put(qd);
-
 	return error;
 }
 
--- linux-ec2-2.6.32.orig/fs/gfs2/file.c
+++ linux-ec2-2.6.32/fs/gfs2/file.c
@@ -218,6 +218,11 @@
 	if (error)
 		goto out_drop_write;
 
+	error = -EACCES;
+	if (!is_owner_or_cap(inode))
+		goto out;
+
+	error = 0;
 	flags = ip->i_diskflags;
 	new_flags = (flags & ~mask) | (reqflags & mask);
 	if ((new_flags ^ flags) == 0)
@@ -275,8 +280,10 @@
 {
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	u32 fsflags, gfsflags;
+
 	if (get_user(fsflags, ptr))
 		return -EFAULT;
+
 	gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags);
 	if (!S_ISDIR(inode->i_mode)) {
 		if (gfsflags & GFS2_DIF_INHERIT_JDATA)
@@ -606,7 +613,7 @@
 
 	if (!(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
-	if (__mandatory_lock(&ip->i_inode))
+	if (__mandatory_lock(&ip->i_inode) && fl->fl_type != F_UNLCK)
 		return -ENOLCK;
 
 	if (cmd == F_CANCELLK) {
--- linux-ec2-2.6.32.orig/fs/quota/dquot.c
+++ linux-ec2-2.6.32/fs/quota/dquot.c
@@ -229,6 +229,8 @@
 struct dqstats dqstats;
 EXPORT_SYMBOL(dqstats);
 
+static qsize_t inode_get_rsv_space(struct inode *inode);
+
 static inline unsigned int
 hashfn(const struct super_block *sb, unsigned int id, int type)
 {
@@ -386,7 +388,7 @@
  */
 int dquot_commit(struct dquot *dquot)
 {
-	int ret = 0, ret2 = 0;
+	int ret = 0;
 	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
 	mutex_lock(&dqopt->dqio_mutex);
@@ -398,15 +400,10 @@
 	spin_unlock(&dq_list_lock);
 	/* Inactive dquot can be only if there was error during read/init
 	 * => we have better not writing it */
-	if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
+	if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
 		ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
-		if (info_dirty(&dqopt->info[dquot->dq_type])) {
-			ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
-						dquot->dq_sb, dquot->dq_type);
-		}
-		if (ret >= 0)
-			ret = ret2;
-	}
+	else
+		ret = -EIO;
 out_sem:
 	mutex_unlock(&dqopt->dqio_mutex);
 	return ret;
@@ -820,11 +817,14 @@
 static void add_dquot_ref(struct super_block *sb, int type)
 {
 	struct inode *inode, *old_inode = NULL;
+	int reserved = 0;
 
 	spin_lock(&inode_lock);
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
 			continue;
+		if (unlikely(inode_get_rsv_space(inode) > 0))
+			reserved = 1;
 		if (!atomic_read(&inode->i_writecount))
 			continue;
 		if (!dqinit_needed(inode, type))
@@ -845,6 +845,12 @@
 	}
 	spin_unlock(&inode_lock);
 	iput(old_inode);
+
+	if (reserved) {
+		printk(KERN_WARNING "VFS (%s): Writes happened before quota"
+			" was turned on thus quota information is probably "
+			"inconsistent. Please run quotacheck(8).\n", sb->s_id);
+	}
 }
 
 /*
@@ -958,10 +964,12 @@
 /*
  * Claim reserved quota space
  */
-static void dquot_claim_reserved_space(struct dquot *dquot,
-						qsize_t number)
+static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
 {
-	WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
+	if (dquot->dq_dqb.dqb_rsvspace < number) {
+		WARN_ON_ONCE(1);
+		number = dquot->dq_dqb.dqb_rsvspace;
+	}
 	dquot->dq_dqb.dqb_curspace += number;
 	dquot->dq_dqb.dqb_rsvspace -= number;
 }
@@ -969,7 +977,12 @@
 static inline
 void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
 {
-	dquot->dq_dqb.dqb_rsvspace -= number;
+	if (dquot->dq_dqb.dqb_rsvspace >= number)
+		dquot->dq_dqb.dqb_rsvspace -= number;
+	else {
+		WARN_ON_ONCE(1);
+		dquot->dq_dqb.dqb_rsvspace = 0;
+	}
 }
 
 static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
@@ -1287,6 +1300,7 @@
 		return QUOTA_NL_BHARDBELOW;
 	return QUOTA_NL_NOWARN;
 }
+
 /*
  *	Initialize quota pointers in inode
  *	We do things in a bit complicated way but by that we avoid calling
@@ -1298,6 +1312,7 @@
 	int cnt, ret = 0;
 	struct dquot *got[MAXQUOTAS] = { NULL, NULL };
 	struct super_block *sb = inode->i_sb;
+	qsize_t rsv;
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
@@ -1332,6 +1347,13 @@
 		if (!inode->i_dquot[cnt]) {
 			inode->i_dquot[cnt] = got[cnt];
 			got[cnt] = NULL;
+			/*
+			 * Make quota reservation system happy if someone
+			 * did a write before quota was turned on
+			 */
+			rsv = inode_get_rsv_space(inode);
+			if (unlikely(rsv))
+				dquot_resv_space(inode->i_dquot[cnt], rsv);
 		}
 	}
 out_err:
@@ -1388,6 +1410,72 @@
 EXPORT_SYMBOL(vfs_dq_drop);
 
 /*
+ * inode_reserved_space is managed internally by quota, and protected by
+ * i_lock similar to i_blocks+i_bytes.
+ */
+static qsize_t *inode_reserved_space(struct inode * inode)
+{
+	/* Filesystem must explicitly define it's own method in order to use
+	 * quota reservation interface */
+	BUG_ON(!inode->i_sb->dq_op->get_reserved_space);
+	return inode->i_sb->dq_op->get_reserved_space(inode);
+}
+
+void inode_add_rsv_space(struct inode *inode, qsize_t number)
+{
+	spin_lock(&inode->i_lock);
+	*inode_reserved_space(inode) += number;
+	spin_unlock(&inode->i_lock);
+}
+EXPORT_SYMBOL(inode_add_rsv_space);
+
+void inode_claim_rsv_space(struct inode *inode, qsize_t number)
+{
+	spin_lock(&inode->i_lock);
+	*inode_reserved_space(inode) -= number;
+	__inode_add_bytes(inode, number);
+	spin_unlock(&inode->i_lock);
+}
+EXPORT_SYMBOL(inode_claim_rsv_space);
+
+void inode_sub_rsv_space(struct inode *inode, qsize_t number)
+{
+	spin_lock(&inode->i_lock);
+	*inode_reserved_space(inode) -= number;
+	spin_unlock(&inode->i_lock);
+}
+EXPORT_SYMBOL(inode_sub_rsv_space);
+
+static qsize_t inode_get_rsv_space(struct inode *inode)
+{
+	qsize_t ret;
+
+	if (!inode->i_sb->dq_op->get_reserved_space)
+		return 0;
+	spin_lock(&inode->i_lock);
+	ret = *inode_reserved_space(inode);
+	spin_unlock(&inode->i_lock);
+	return ret;
+}
+
+static void inode_incr_space(struct inode *inode, qsize_t number,
+				int reserve)
+{
+	if (reserve)
+		inode_add_rsv_space(inode, number);
+	else
+		inode_add_bytes(inode, number);
+}
+
+static void inode_decr_space(struct inode *inode, qsize_t number, int reserve)
+{
+	if (reserve)
+		inode_sub_rsv_space(inode, number);
+	else
+		inode_sub_bytes(inode, number);
+}
+
+/*
  * Following four functions update i_blocks+i_bytes fields and
  * quota information (together with appropriate checks)
  * NOTE: We absolutely rely on the fact that caller dirties
@@ -1405,6 +1493,21 @@
 	int cnt, ret = QUOTA_OK;
 	char warntype[MAXQUOTAS];
 
+	/*
+	 * First test before acquiring mutex - solves deadlocks when we
+	 * re-enter the quota code and are already holding the mutex
+	 */
+	if (IS_NOQUOTA(inode)) {
+		inode_incr_space(inode, number, reserve);
+		goto out;
+	}
+
+	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+	if (IS_NOQUOTA(inode)) {
+		inode_incr_space(inode, number, reserve);
+		goto out_unlock;
+	}
+
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = QUOTA_NL_NOWARN;
 
@@ -1415,7 +1518,8 @@
 		if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
 		    == NO_QUOTA) {
 			ret = NO_QUOTA;
-			goto out_unlock;
+			spin_unlock(&dq_data_lock);
+			goto out_flush_warn;
 		}
 	}
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1426,64 +1530,32 @@
 		else
 			dquot_incr_space(inode->i_dquot[cnt], number);
 	}
-	if (!reserve)
-		inode_add_bytes(inode, number);
-out_unlock:
+	inode_incr_space(inode, number, reserve);
 	spin_unlock(&dq_data_lock);
-	flush_warnings(inode->i_dquot, warntype);
-	return ret;
-}
-
-int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
-{
-	int cnt, ret = QUOTA_OK;
-
-	/*
-	 * First test before acquiring mutex - solves deadlocks when we
-	 * re-enter the quota code and are already holding the mutex
-	 */
-	if (IS_NOQUOTA(inode)) {
-		inode_add_bytes(inode, number);
-		goto out;
-	}
-
-	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode)) {
-		inode_add_bytes(inode, number);
-		goto out_unlock;
-	}
-
-	ret = __dquot_alloc_space(inode, number, warn, 0);
-	if (ret == NO_QUOTA)
-		goto out_unlock;
 
+	if (reserve)
+		goto out_flush_warn;
 	/* Dirtify all the dquots - this can block when journalling */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		if (inode->i_dquot[cnt])
 			mark_dquot_dirty(inode->i_dquot[cnt]);
+out_flush_warn:
+	flush_warnings(inode->i_dquot, warntype);
 out_unlock:
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 out:
 	return ret;
 }
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+{
+	return __dquot_alloc_space(inode, number, warn, 0);
+}
 EXPORT_SYMBOL(dquot_alloc_space);
 
 int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
 {
-	int ret = QUOTA_OK;
-
-	if (IS_NOQUOTA(inode))
-		goto out;
-
-	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode))
-		goto out_unlock;
-
-	ret = __dquot_alloc_space(inode, number, warn, 1);
-out_unlock:
-	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-	return ret;
+	return __dquot_alloc_space(inode, number, warn, 1);
 }
 EXPORT_SYMBOL(dquot_reserve_space);
 
@@ -1540,14 +1612,14 @@
 	int ret = QUOTA_OK;
 
 	if (IS_NOQUOTA(inode)) {
-		inode_add_bytes(inode, number);
+		inode_claim_rsv_space(inode, number);
 		goto out;
 	}
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	if (IS_NOQUOTA(inode))	{
 		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		inode_add_bytes(inode, number);
+		inode_claim_rsv_space(inode, number);
 		goto out;
 	}
 
@@ -1559,7 +1631,7 @@
 							number);
 	}
 	/* Update inode bytes */
-	inode_add_bytes(inode, number);
+	inode_claim_rsv_space(inode, number);
 	spin_unlock(&dq_data_lock);
 	/* Dirtify all the dquots - this can block when journalling */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
@@ -1572,38 +1644,9 @@
 EXPORT_SYMBOL(dquot_claim_space);
 
 /*
- * Release reserved quota space
- */
-void dquot_release_reserved_space(struct inode *inode, qsize_t number)
-{
-	int cnt;
-
-	if (IS_NOQUOTA(inode))
-		goto out;
-
-	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode))
-		goto out_unlock;
-
-	spin_lock(&dq_data_lock);
-	/* Release reserved dquots */
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt])
-			dquot_free_reserved_space(inode->i_dquot[cnt], number);
-	}
-	spin_unlock(&dq_data_lock);
-
-out_unlock:
-	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-	return;
-}
-EXPORT_SYMBOL(dquot_release_reserved_space);
-
-/*
  * This operation can block, but only after everything is updated
  */
-int dquot_free_space(struct inode *inode, qsize_t number)
+int __dquot_free_space(struct inode *inode, qsize_t number, int reserve)
 {
 	unsigned int cnt;
 	char warntype[MAXQUOTAS];
@@ -1612,7 +1655,7 @@
          * re-enter the quota code and are already holding the mutex */
 	if (IS_NOQUOTA(inode)) {
 out_sub:
-		inode_sub_bytes(inode, number);
+		inode_decr_space(inode, number, reserve);
 		return QUOTA_OK;
 	}
 
@@ -1627,21 +1670,43 @@
 		if (!inode->i_dquot[cnt])
 			continue;
 		warntype[cnt] = info_bdq_free(inode->i_dquot[cnt], number);
-		dquot_decr_space(inode->i_dquot[cnt], number);
+		if (reserve)
+			dquot_free_reserved_space(inode->i_dquot[cnt], number);
+		else
+			dquot_decr_space(inode->i_dquot[cnt], number);
 	}
-	inode_sub_bytes(inode, number);
+	inode_decr_space(inode, number, reserve);
 	spin_unlock(&dq_data_lock);
+
+	if (reserve)
+		goto out_unlock;
 	/* Dirtify all the dquots - this can block when journalling */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		if (inode->i_dquot[cnt])
 			mark_dquot_dirty(inode->i_dquot[cnt]);
+out_unlock:
 	flush_warnings(inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	return QUOTA_OK;
 }
+
+int dquot_free_space(struct inode *inode, qsize_t number)
+{
+	return  __dquot_free_space(inode, number, 0);
+}
 EXPORT_SYMBOL(dquot_free_space);
 
 /*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+	__dquot_free_space(inode, number, 1);
+
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
+/*
  * This operation can block, but only after everything is updated
  */
 int dquot_free_inode(const struct inode *inode, qsize_t number)
@@ -1679,19 +1744,6 @@
 EXPORT_SYMBOL(dquot_free_inode);
 
 /*
- * call back function, get reserved quota space from underlying fs
- */
-qsize_t dquot_get_reserved_space(struct inode *inode)
-{
-	qsize_t reserved_space = 0;
-
-	if (sb_any_quota_active(inode->i_sb) &&
-	    inode->i_sb->dq_op->get_reserved_space)
-		reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
-	return reserved_space;
-}
-
-/*
  * Transfer the number of inode and blocks from one diskquota to an other.
  *
  * This operation can block, but only after everything is updated
@@ -1734,7 +1786,7 @@
 	}
 	spin_lock(&dq_data_lock);
 	cur_space = inode_get_bytes(inode);
-	rsv_space = dquot_get_reserved_space(inode);
+	rsv_space = inode_get_rsv_space(inode);
 	space = cur_space + rsv_space;
 	/* Build the transfer_from list and check the limits */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -2332,34 +2384,34 @@
 	if (di->dqb_valid & QIF_SPACE) {
 		dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
 		check_blim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
 	}
 	if (di->dqb_valid & QIF_BLIMITS) {
 		dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
 		dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
 		check_blim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
 	}
 	if (di->dqb_valid & QIF_INODES) {
 		dm->dqb_curinodes = di->dqb_curinodes;
 		check_ilim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
 	}
 	if (di->dqb_valid & QIF_ILIMITS) {
 		dm->dqb_isoftlimit = di->dqb_isoftlimit;
 		dm->dqb_ihardlimit = di->dqb_ihardlimit;
 		check_ilim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
 	}
 	if (di->dqb_valid & QIF_BTIME) {
 		dm->dqb_btime = di->dqb_btime;
 		check_blim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
 	}
 	if (di->dqb_valid & QIF_ITIME) {
 		dm->dqb_itime = di->dqb_itime;
 		check_ilim = 1;
-		__set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
+		set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
 	}
 
 	if (check_blim) {
--- linux-ec2-2.6.32.orig/fs/fuse/fuse_i.h
+++ linux-ec2-2.6.32/fs/fuse/fuse_i.h
@@ -21,6 +21,7 @@
 #include <linux/rwsem.h>
 #include <linux/rbtree.h>
 #include <linux/poll.h>
+#include <linux/workqueue.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -254,7 +255,10 @@
 	union {
 		struct fuse_forget_in forget_in;
 		struct {
-			struct fuse_release_in in;
+			union {
+				struct fuse_release_in in;
+				struct work_struct work;
+			};
 			struct path path;
 		} release;
 		struct fuse_init_in init_in;
--- linux-ec2-2.6.32.orig/fs/fuse/dev.c
+++ linux-ec2-2.6.32/fs/fuse/dev.c
@@ -1158,6 +1158,14 @@
 	}
 }
 
+static void end_queued_requests(struct fuse_conn *fc)
+{
+	fc->max_background = UINT_MAX;
+	flush_bg_queue(fc);
+	end_requests(fc, &fc->pending);
+	end_requests(fc, &fc->processing);
+}
+
 /*
  * Abort all requests.
  *
@@ -1184,8 +1192,7 @@
 		fc->connected = 0;
 		fc->blocked = 0;
 		end_io_requests(fc);
-		end_requests(fc, &fc->pending);
-		end_requests(fc, &fc->processing);
+		end_queued_requests(fc);
 		wake_up_all(&fc->waitq);
 		wake_up_all(&fc->blocked_waitq);
 		kill_fasync(&fc->fasync, SIGIO, POLL_IN);
@@ -1200,8 +1207,9 @@
 	if (fc) {
 		spin_lock(&fc->lock);
 		fc->connected = 0;
-		end_requests(fc, &fc->pending);
-		end_requests(fc, &fc->processing);
+		fc->blocked = 0;
+		end_queued_requests(fc);
+		wake_up_all(&fc->blocked_waitq);
 		spin_unlock(&fc->lock);
 		fuse_conn_put(fc);
 	}
--- linux-ec2-2.6.32.orig/fs/fuse/file.c
+++ linux-ec2-2.6.32/fs/fuse/file.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/compat.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -85,18 +86,52 @@
 	return ff;
 }
 
+static void fuse_release_async(struct work_struct *work)
+{
+	struct fuse_req *req;
+	struct fuse_conn *fc;
+	struct path path;
+
+	req = container_of(work, struct fuse_req, misc.release.work);
+	path = req->misc.release.path;
+	fc = get_fuse_conn(path.dentry->d_inode);
+
+	fuse_put_request(fc, req);
+	path_put(&path);
+}
+
 static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 {
-	path_put(&req->misc.release.path);
+	if (fc->destroy_req) {
+		/*
+		 * If this is a fuseblk mount, then it's possible that
+		 * releasing the path will result in releasing the
+		 * super block and sending the DESTROY request.  If
+		 * the server is single threaded, this would hang.
+		 * For this reason do the path_put() in a separate
+		 * thread.
+		 */
+		atomic_inc(&req->count);
+		INIT_WORK(&req->misc.release.work, fuse_release_async);
+		schedule_work(&req->misc.release.work);
+	} else {
+		path_put(&req->misc.release.path);
+	}
 }
 
-static void fuse_file_put(struct fuse_file *ff)
+static void fuse_file_put(struct fuse_file *ff, bool sync)
 {
 	if (atomic_dec_and_test(&ff->count)) {
 		struct fuse_req *req = ff->reserved_req;
 
-		req->end = fuse_release_end;
-		fuse_request_send_background(ff->fc, req);
+		if (sync) {
+			fuse_request_send(ff->fc, req);
+			path_put(&req->misc.release.path);
+			fuse_put_request(ff->fc, req);
+		} else {
+			req->end = fuse_release_end;
+			fuse_request_send_background(ff->fc, req);
+		}
 		kfree(ff);
 	}
 }
@@ -134,6 +169,7 @@
 void fuse_finish_open(struct inode *inode, struct file *file)
 {
 	struct fuse_file *ff = file->private_data;
+	struct fuse_conn *fc = get_fuse_conn(inode);
 
 	if (ff->open_flags & FOPEN_DIRECT_IO)
 		file->f_op = &fuse_direct_io_file_operations;
@@ -141,6 +177,15 @@
 		invalidate_inode_pages2(inode->i_mapping);
 	if (ff->open_flags & FOPEN_NONSEEKABLE)
 		nonseekable_open(inode, file);
+	if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
+		struct fuse_inode *fi = get_fuse_inode(inode);
+
+		spin_lock(&fc->lock);
+		fi->attr_version = ++fc->attr_version;
+		i_size_write(inode, 0);
+		spin_unlock(&fc->lock);
+		fuse_invalidate_attr(inode);
+	}
 }
 
 int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
@@ -208,8 +253,12 @@
 	 * Normally this will send the RELEASE request, however if
 	 * some asynchronous READ or WRITE requests are outstanding,
 	 * the sending will be delayed.
+	 *
+	 * Make the release synchronous if this is a fuseblk mount,
+	 * synchronous RELEASE is allowed (and desirable) in this case
+	 * because the server can be trusted not to screw up.
 	 */
-	fuse_file_put(ff);
+	fuse_file_put(ff, ff->fc->destroy_req != NULL);
 }
 
 static int fuse_open(struct inode *inode, struct file *file)
@@ -538,7 +587,7 @@
 		unlock_page(page);
 	}
 	if (req->ff)
-		fuse_file_put(req->ff);
+		fuse_file_put(req->ff, false);
 }
 
 static void fuse_send_readpages(struct fuse_req *req, struct file *file)
@@ -828,6 +877,9 @@
 		if (!page)
 			break;
 
+		if (mapping_writably_mapped(mapping))
+			flush_dcache_page(page);
+
 		pagefault_disable();
 		tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
 		pagefault_enable();
@@ -1115,7 +1167,7 @@
 static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
 {
 	__free_page(req->pages[0]);
-	fuse_file_put(req->ff);
+	fuse_file_put(req->ff, false);
 }
 
 static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
@@ -1606,6 +1658,58 @@
 	return 0;
 }
 
+/* Make sure iov_length() won't overflow */
+static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
+{
+	size_t n;
+	u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+	for (n = 0; n < count; n++) {
+		if (iov->iov_len > (size_t) max)
+			return -ENOMEM;
+		max -= iov->iov_len;
+	}
+	return 0;
+}
+
+/*
+ * CUSE servers compiled on 32bit broke on 64bit kernels because the
+ * ABI was defined to be 'struct iovec' which is different on 32bit
+ * and 64bit.  Fortunately we can determine which structure the server
+ * used from the size of the reply.
+ */
+static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+				 size_t transferred, unsigned count,
+				 bool is_compat)
+{
+#ifdef CONFIG_COMPAT
+	if (count * sizeof(struct compat_iovec) == transferred) {
+		struct compat_iovec *ciov = src;
+		unsigned i;
+
+		/*
+		 * With this interface a 32bit server cannot support
+		 * non-compat (i.e. ones coming from 64bit apps) ioctl
+		 * requests
+		 */
+		if (!is_compat)
+			return -EINVAL;
+
+		for (i = 0; i < count; i++) {
+			dst[i].iov_base = compat_ptr(ciov[i].iov_base);
+			dst[i].iov_len = ciov[i].iov_len;
+		}
+		return 0;
+	}
+#endif
+
+	if (count * sizeof(struct iovec) != transferred)
+		return -EIO;
+
+	memcpy(dst, src, transferred);
+	return 0;
+}
+
 /*
  * For ioctls, there is no generic way to determine how much memory
  * needs to be read and/or written.  Furthermore, ioctls are allowed
@@ -1787,18 +1891,25 @@
 		    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
 			goto out;
 
-		err = -EIO;
-		if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred)
-			goto out;
-
-		/* okay, copy in iovs and retry */
 		vaddr = kmap_atomic(pages[0], KM_USER0);
-		memcpy(page_address(iov_page), vaddr, transferred);
+		err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr,
+					    transferred, in_iovs + out_iovs,
+					    (flags & FUSE_IOCTL_COMPAT) != 0);
 		kunmap_atomic(vaddr, KM_USER0);
+		if (err)
+			goto out;
 
 		in_iov = page_address(iov_page);
 		out_iov = in_iov + in_iovs;
 
+		err = fuse_verify_ioctl_iov(in_iov, in_iovs);
+		if (err)
+			goto out;
+
+		err = fuse_verify_ioctl_iov(out_iov, out_iovs);
+		if (err)
+			goto out;
+
 		goto retry;
 	}
 
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_itable.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_itable.c
@@ -49,24 +49,40 @@
 		 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
 }
 
-STATIC int
-xfs_bulkstat_one_iget(
-	xfs_mount_t	*mp,		/* mount point for filesystem */
-	xfs_ino_t	ino,		/* inode number to get data for */
-	xfs_daddr_t	bno,		/* starting bno of inode cluster */
-	xfs_bstat_t	*buf,		/* return buffer */
-	int		*stat)		/* BULKSTAT_RV_... */
+/*
+ * Return stat information for one inode.
+ * Return 0 if ok, else errno.
+ */
+int
+xfs_bulkstat_one_int(
+	xfs_mount_t		*mp,		/* mount point for filesystem */
+	xfs_ino_t		ino,		/* inode to get data for */
+	void __user		*buffer,	/* buffer to place output in */
+	int			ubsize,		/* size of buffer */
+	bulkstat_one_fmt_pf	formatter,	/* formatter, copy to user */
+	int			*ubused,	/* bytes used by me */
+	int			*stat)		/* BULKSTAT_RV_... */
 {
-	xfs_icdinode_t	*dic;	/* dinode core info pointer */
-	xfs_inode_t	*ip;		/* incore inode pointer */
-	struct inode	*inode;
-	int		error;
+	struct xfs_icdinode	*dic;		/* dinode core info pointer */
+	struct xfs_inode	*ip;		/* incore inode pointer */
+	struct inode		*inode;
+	struct xfs_bstat	*buf;		/* return buffer */
+	int			error = 0;	/* error value */
+
+	*stat = BULKSTAT_RV_NOTHING;
+
+	if (!buffer || xfs_internal_inum(mp, ino))
+		return XFS_ERROR(EINVAL);
+
+	buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL);
+	if (!buf)
+		return XFS_ERROR(ENOMEM);
 
 	error = xfs_iget(mp, NULL, ino,
-			 XFS_IGET_BULKSTAT, XFS_ILOCK_SHARED, &ip, bno);
+			 XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip);
 	if (error) {
 		*stat = BULKSTAT_RV_NOTHING;
-		return error;
+		goto out_free;
 	}
 
 	ASSERT(ip != NULL);
@@ -126,76 +142,16 @@
 		buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
 		break;
 	}
-
 	xfs_iput(ip, XFS_ILOCK_SHARED);
-	return error;
-}
 
-STATIC void
-xfs_bulkstat_one_dinode(
-	xfs_mount_t	*mp,		/* mount point for filesystem */
-	xfs_ino_t	ino,		/* inode number to get data for */
-	xfs_dinode_t	*dic,		/* dinode inode pointer */
-	xfs_bstat_t	*buf)		/* return buffer */
-{
-	/*
-	 * The inode format changed when we moved the link count and
-	 * made it 32 bits long.  If this is an old format inode,
-	 * convert it in memory to look like a new one.  If it gets
-	 * flushed to disk we will convert back before flushing or
-	 * logging it.  We zero out the new projid field and the old link
-	 * count field.  We'll handle clearing the pad field (the remains
-	 * of the old uuid field) when we actually convert the inode to
-	 * the new format. We don't change the version number so that we
-	 * can distinguish this from a real new format inode.
-	 */
-	if (dic->di_version == 1) {
-		buf->bs_nlink = be16_to_cpu(dic->di_onlink);
-		buf->bs_projid = 0;
-	} else {
-		buf->bs_nlink = be32_to_cpu(dic->di_nlink);
-		buf->bs_projid = be16_to_cpu(dic->di_projid);
-	}
+	error = formatter(buffer, ubsize, ubused, buf);
 
-	buf->bs_ino = ino;
-	buf->bs_mode = be16_to_cpu(dic->di_mode);
-	buf->bs_uid = be32_to_cpu(dic->di_uid);
-	buf->bs_gid = be32_to_cpu(dic->di_gid);
-	buf->bs_size = be64_to_cpu(dic->di_size);
-	buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec);
-	buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec);
-	buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec);
-	buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
-	buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
-	buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
-	buf->bs_xflags = xfs_dic2xflags(dic);
-	buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
-	buf->bs_extents = be32_to_cpu(dic->di_nextents);
-	buf->bs_gen = be32_to_cpu(dic->di_gen);
-	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
-	buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
-	buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
-	buf->bs_aextents = be16_to_cpu(dic->di_anextents);
+	if (!error)
+		*stat = BULKSTAT_RV_DIDONE;
 
-	switch (dic->di_format) {
-	case XFS_DINODE_FMT_DEV:
-		buf->bs_rdev = xfs_dinode_get_rdev(dic);
-		buf->bs_blksize = BLKDEV_IOSIZE;
-		buf->bs_blocks = 0;
-		break;
-	case XFS_DINODE_FMT_LOCAL:
-	case XFS_DINODE_FMT_UUID:
-		buf->bs_rdev = 0;
-		buf->bs_blksize = mp->m_sb.sb_blocksize;
-		buf->bs_blocks = 0;
-		break;
-	case XFS_DINODE_FMT_EXTENTS:
-	case XFS_DINODE_FMT_BTREE:
-		buf->bs_rdev = 0;
-		buf->bs_blksize = mp->m_sb.sb_blocksize;
-		buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
-		break;
-	}
+ out_free:
+	kmem_free(buf);
+	return error;
 }
 
 /* Return 0 on success or positive error */
@@ -215,118 +171,17 @@
 	return 0;
 }
 
-/*
- * Return stat information for one inode.
- * Return 0 if ok, else errno.
- */
-int		   	    		/* error status */
-xfs_bulkstat_one_int(
-	xfs_mount_t	*mp,		/* mount point for filesystem */
-	xfs_ino_t	ino,		/* inode number to get data for */
-	void		__user *buffer,	/* buffer to place output in */
-	int		ubsize,		/* size of buffer */
-	bulkstat_one_fmt_pf formatter,	/* formatter, copy to user */
-	xfs_daddr_t	bno,		/* starting bno of inode cluster */
-	int		*ubused,	/* bytes used by me */
-	void		*dibuff,	/* on-disk inode buffer */
-	int		*stat)		/* BULKSTAT_RV_... */
-{
-	xfs_bstat_t	*buf;		/* return buffer */
-	int		error = 0;	/* error value */
-	xfs_dinode_t	*dip;		/* dinode inode pointer */
-
-	dip = (xfs_dinode_t *)dibuff;
-	*stat = BULKSTAT_RV_NOTHING;
-
-	if (!buffer || xfs_internal_inum(mp, ino))
-		return XFS_ERROR(EINVAL);
-
-	buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
-
-	if (dip == NULL) {
-		/* We're not being passed a pointer to a dinode.  This happens
-		 * if BULKSTAT_FG_IGET is selected.  Do the iget.
-		 */
-		error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
-		if (error)
-			goto out_free;
-	} else {
-		xfs_bulkstat_one_dinode(mp, ino, dip, buf);
-	}
-
-	error = formatter(buffer, ubsize, ubused, buf);
-	if (error)
-		goto out_free;
-
-	*stat = BULKSTAT_RV_DIDONE;
-
- out_free:
-	kmem_free(buf);
-	return error;
-}
-
 int
 xfs_bulkstat_one(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
 	void		__user *buffer,	/* buffer to place output in */
 	int		ubsize,		/* size of buffer */
-	void		*private_data,	/* my private data */
-	xfs_daddr_t	bno,		/* starting bno of inode cluster */
 	int		*ubused,	/* bytes used by me */
-	void		*dibuff,	/* on-disk inode buffer */
 	int		*stat)		/* BULKSTAT_RV_... */
 {
 	return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-				    xfs_bulkstat_one_fmt, bno,
-				    ubused, dibuff, stat);
-}
-
-/*
- * Test to see whether we can use the ondisk inode directly, based
- * on the given bulkstat flags, filling in dipp accordingly.
- * Returns zero if the inode is dodgey.
- */
-STATIC int
-xfs_bulkstat_use_dinode(
-	xfs_mount_t	*mp,
-	int		flags,
-	xfs_buf_t	*bp,
-	int		clustidx,
-	xfs_dinode_t	**dipp)
-{
-	xfs_dinode_t	*dip;
-	unsigned int	aformat;
-
-	*dipp = NULL;
-	if (!bp || (flags & BULKSTAT_FG_IGET))
-		return 1;
-	dip = (xfs_dinode_t *)
-			xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
-	/*
-	 * Check the buffer containing the on-disk inode for di_mode == 0.
-	 * This is to prevent xfs_bulkstat from picking up just reclaimed
-	 * inodes that have their in-core state initialized but not flushed
-	 * to disk yet. This is a temporary hack that would require a proper
-	 * fix in the future.
-	 */
-	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
-	    !XFS_DINODE_GOOD_VERSION(dip->di_version) ||
-	    !dip->di_mode)
-		return 0;
-	if (flags & BULKSTAT_FG_QUICK) {
-		*dipp = dip;
-		return 1;
-	}
-	/* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
-	aformat = dip->di_aformat;
-	if ((XFS_DFORK_Q(dip) == 0) ||
-	    (aformat == XFS_DINODE_FMT_LOCAL) ||
-	    (aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_anextents)) {
-		*dipp = dip;
-		return 1;
-	}
-	return 1;
+				    xfs_bulkstat_one_fmt, ubused, stat);
 }
 
 #define XFS_BULKSTAT_UBLEFT(ubleft)	((ubleft) >= statstruct_size)
@@ -340,10 +195,8 @@
 	xfs_ino_t		*lastinop, /* last inode returned */
 	int			*ubcountp, /* size of buffer/count returned */
 	bulkstat_one_pf		formatter, /* func that'd fill a single buf */
-	void			*private_data,/* private data for formatter */
 	size_t			statstruct_size, /* sizeof struct filling */
 	char			__user *ubuffer, /* buffer with inode stats */
-	int			flags,	/* defined in xfs_itable.h */
 	int			*done)	/* 1 if there are more stats to get */
 {
 	xfs_agblock_t		agbno=0;/* allocation group block number */
@@ -378,14 +231,12 @@
 	int			ubelem;	/* spaces used in user's buffer */
 	int			ubused;	/* bytes used by formatter */
 	xfs_buf_t		*bp;	/* ptr to on-disk inode cluster buf */
-	xfs_dinode_t		*dip;	/* ptr into bp for specific inode */
 
 	/*
 	 * Get the last inode value, see if there's nothing to do.
 	 */
 	ino = (xfs_ino_t)*lastinop;
 	lastino = ino;
-	dip = NULL;
 	agno = XFS_INO_TO_AGNO(mp, ino);
 	agino = XFS_INO_TO_AGINO(mp, ino);
 	if (agno >= mp->m_sb.sb_agcount ||
@@ -610,37 +461,6 @@
 							irbp->ir_startino) +
 						((chunkidx & nimask) >>
 						 mp->m_sb.sb_inopblog);
-
-					if (flags & (BULKSTAT_FG_QUICK |
-						     BULKSTAT_FG_INLINE)) {
-						int offset;
-
-						ino = XFS_AGINO_TO_INO(mp, agno,
-								       agino);
-						bno = XFS_AGB_TO_DADDR(mp, agno,
-								       agbno);
-
-						/*
-						 * Get the inode cluster buffer
-						 */
-						if (bp)
-							xfs_buf_relse(bp);
-
-						error = xfs_inotobp(mp, NULL, ino, &dip,
-								    &bp, &offset,
-								    XFS_IGET_BULKSTAT);
-
-						if (!error)
-							clustidx = offset / mp->m_sb.sb_inodesize;
-						if (XFS_TEST_ERROR(error != 0,
-								   mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
-								   XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
-							bp = NULL;
-							ubleft = 0;
-							rval = error;
-							break;
-						}
-					}
 				}
 				ino = XFS_AGINO_TO_INO(mp, agno, agino);
 				bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
@@ -656,35 +476,13 @@
 				 * when the chunk is used up.
 				 */
 				irbp->ir_freecount++;
-				if (!xfs_bulkstat_use_dinode(mp, flags, bp,
-							     clustidx, &dip)) {
-					lastino = ino;
-					continue;
-				}
-				/*
-				 * If we need to do an iget, cannot hold bp.
-				 * Drop it, until starting the next cluster.
-				 */
-				if ((flags & BULKSTAT_FG_INLINE) && !dip) {
-					if (bp)
-						xfs_buf_relse(bp);
-					bp = NULL;
-				}
 
 				/*
 				 * Get the inode and fill in a single buffer.
-				 * BULKSTAT_FG_QUICK uses dip to fill it in.
-				 * BULKSTAT_FG_IGET uses igets.
-				 * BULKSTAT_FG_INLINE uses dip if we have an
-				 * inline attr fork, else igets.
-				 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
-				 * This is also used to count inodes/blks, etc
-				 * in xfs_qm_quotacheck.
 				 */
 				ubused = statstruct_size;
-				error = formatter(mp, ino, ubufp,
-						ubleft, private_data,
-						bno, &ubused, dip, &fmterror);
+				error = formatter(mp, ino, ubufp, ubleft,
+						  &ubused, &fmterror);
 				if (fmterror == BULKSTAT_RV_NOTHING) {
 					if (error && error != ENOENT &&
 						error != EINVAL) {
@@ -776,8 +574,7 @@
 	 */
 
 	ino = (xfs_ino_t)*lastinop;
-	error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
-				 NULL, 0, NULL, NULL, &res);
+	error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res);
 	if (error) {
 		/*
 		 * Special case way failed, do it the "long" way
@@ -786,8 +583,7 @@
 		(*lastinop)--;
 		count = 1;
 		if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
-				NULL, sizeof(xfs_bstat_t), buffer,
-				BULKSTAT_FG_IGET, done))
+				sizeof(xfs_bstat_t), buffer, done))
 			return error;
 		if (count == 0 || (xfs_ino_t)*lastinop != ino)
 			return error == EFSCORRUPTED ?
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_vnodeops.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_vnodeops.c
@@ -69,7 +69,6 @@
 	uint			commit_flags=0;
 	uid_t			uid=0, iuid=0;
 	gid_t			gid=0, igid=0;
-	int			timeflags = 0;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
 	int			need_iolock = 1;
 
@@ -134,16 +133,13 @@
 	if (flags & XFS_ATTR_NOLOCK)
 		need_iolock = 0;
 	if (!(mask & ATTR_SIZE)) {
-		if ((mask != (ATTR_CTIME|ATTR_ATIME|ATTR_MTIME)) ||
-		    (mp->m_flags & XFS_MOUNT_WSYNC)) {
-			tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
-			commit_flags = 0;
-			if ((code = xfs_trans_reserve(tp, 0,
-						     XFS_ICHANGE_LOG_RES(mp), 0,
-						     0, 0))) {
-				lock_flags = 0;
-				goto error_return;
-			}
+		tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
+		commit_flags = 0;
+		code = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp),
+					 0, 0, 0);
+		if (code) {
+			lock_flags = 0;
+			goto error_return;
 		}
 	} else {
 		if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) &&
@@ -294,15 +290,23 @@
 		 * or we are explicitly asked to change it. This handles
 		 * the semantic difference between truncate() and ftruncate()
 		 * as implemented in the VFS.
-		 */
-		if (iattr->ia_size != ip->i_size || (mask & ATTR_CTIME))
-			timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
+		 *
+		 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME
+		 * is a special case where we need to update the times despite
+		 * not having these flags set.  For all other operations the
+		 * VFS set these flags explicitly if it wants a timestamp
+		 * update.
+		 */
+		if (iattr->ia_size != ip->i_size &&
+		    (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
+			iattr->ia_ctime = iattr->ia_mtime =
+				current_fs_time(inode->i_sb);
+			mask |= ATTR_CTIME | ATTR_MTIME;
+		}
 
 		if (iattr->ia_size > ip->i_size) {
 			ip->i_d.di_size = iattr->ia_size;
 			ip->i_size = iattr->ia_size;
-			if (!(flags & XFS_ATTR_DMI))
-				xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
 			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		} else if (iattr->ia_size <= ip->i_size ||
 			   (iattr->ia_size == 0 && ip->i_d.di_nextents)) {
@@ -373,9 +377,6 @@
 			ip->i_d.di_gid = gid;
 			inode->i_gid = gid;
 		}
-
-		xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
-		timeflags |= XFS_ICHGTIME_CHG;
 	}
 
 	/*
@@ -392,51 +393,37 @@
 
 		inode->i_mode &= S_IFMT;
 		inode->i_mode |= mode & ~S_IFMT;
-
-		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-		timeflags |= XFS_ICHGTIME_CHG;
 	}
 
 	/*
 	 * Change file access or modified times.
 	 */
-	if (mask & (ATTR_ATIME|ATTR_MTIME)) {
-		if (mask & ATTR_ATIME) {
-			inode->i_atime = iattr->ia_atime;
-			ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
-			ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
-			ip->i_update_core = 1;
-		}
-		if (mask & ATTR_MTIME) {
-			inode->i_mtime = iattr->ia_mtime;
-			ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
-			ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
-			timeflags &= ~XFS_ICHGTIME_MOD;
-			timeflags |= XFS_ICHGTIME_CHG;
-		}
-		if (tp && (mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)))
-			xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
+	if (mask & ATTR_ATIME) {
+		inode->i_atime = iattr->ia_atime;
+		ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
+		ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
+		ip->i_update_core = 1;
 	}
-
-	/*
-	 * Change file inode change time only if ATTR_CTIME set
-	 * AND we have been called by a DMI function.
-	 */
-
-	if ((flags & XFS_ATTR_DMI) && (mask & ATTR_CTIME)) {
+	if (mask & ATTR_CTIME) {
 		inode->i_ctime = iattr->ia_ctime;
 		ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
 		ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
 		ip->i_update_core = 1;
-		timeflags &= ~XFS_ICHGTIME_CHG;
+	}
+	if (mask & ATTR_MTIME) {
+		inode->i_mtime = iattr->ia_mtime;
+		ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
+		ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
+		ip->i_update_core = 1;
 	}
 
 	/*
-	 * Send out timestamp changes that need to be set to the
-	 * current time.  Not done when called by a DMI function.
+	 * And finally, log the inode core if any attribute in it
+	 * has been changed.
 	 */
-	if (timeflags && !(flags & XFS_ATTR_DMI))
-		xfs_ichgtime(ip, timeflags);
+	if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE|
+		    ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
 	XFS_STATS_INC(xs_ig_attrchg);
 
@@ -451,12 +438,10 @@
 	 * mix so this probably isn't worth the trouble to optimize.
 	 */
 	code = 0;
-	if (tp) {
-		if (mp->m_flags & XFS_MOUNT_WSYNC)
-			xfs_trans_set_sync(tp);
+	if (mp->m_flags & XFS_MOUNT_WSYNC)
+		xfs_trans_set_sync(tp);
 
-		code = xfs_trans_commit(tp, commit_flags);
-	}
+	code = xfs_trans_commit(tp, commit_flags);
 
 	xfs_iunlock(ip, lock_flags);
 
@@ -612,7 +597,7 @@
 {
 	xfs_trans_t	*tp;
 	int		error = 0;
-	int		log_flushed = 0, changed = 1;
+	int		log_flushed = 0;
 
 	xfs_itrace_entry(ip);
 
@@ -642,19 +627,11 @@
 		 * disk yet, the inode will be still be pinned.  If it is,
 		 * force the log.
 		 */
-
 		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
 		if (xfs_ipincount(ip)) {
 			error = _xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
 				      XFS_LOG_FORCE | XFS_LOG_SYNC,
 				      &log_flushed);
-		} else {
-			/*
-			 * If the inode is not pinned and nothing has changed
-			 * we don't need to flush the cache.
-			 */
-			changed = 0;
 		}
 	} else	{
 		/*
@@ -689,7 +666,7 @@
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 
-	if ((ip->i_mount->m_flags & XFS_MOUNT_BARRIER) && changed) {
+	if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
 		/*
 		 * If the log write didn't issue an ordered tag we need
 		 * to flush the disk cache for the data device now.
@@ -709,6 +686,11 @@
 }
 
 /*
+ * Flags for xfs_free_eofblocks
+ */
+#define XFS_FREE_EOF_TRYLOCK	(1<<0)
+
+/*
  * This is called by xfs_inactive to free any blocks beyond eof
  * when the link count isn't zero and by xfs_dm_punch_hole() when
  * punching a hole to EOF.
@@ -726,7 +708,6 @@
 	xfs_filblks_t	map_len;
 	int		nimaps;
 	xfs_bmbt_irec_t	imap;
-	int		use_iolock = (flags & XFS_FREE_EOF_LOCK);
 
 	/*
 	 * Figure out if there are any blocks beyond the end
@@ -768,14 +749,19 @@
 		 * cache and we can't
 		 * do that within a transaction.
 		 */
-		if (use_iolock)
+		if (flags & XFS_FREE_EOF_TRYLOCK) {
+			if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
+				xfs_trans_cancel(tp, 0);
+				return 0;
+			}
+		} else {
 			xfs_ilock(ip, XFS_IOLOCK_EXCL);
+		}
 		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
 				    ip->i_size);
 		if (error) {
 			xfs_trans_cancel(tp, 0);
-			if (use_iolock)
-				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return error;
 		}
 
@@ -812,8 +798,7 @@
 			error = xfs_trans_commit(tp,
 						XFS_TRANS_RELEASE_LOG_RES);
 		}
-		xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)
-					    : XFS_ILOCK_EXCL));
+		xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
 	}
 	return error;
 }
@@ -1113,7 +1098,17 @@
 		     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
 		    (!(ip->i_d.di_flags &
 				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
-			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+
+			/*
+			 * If we can't get the iolock just skip truncating
+			 * the blocks past EOF because we could deadlock
+			 * with the mmap_sem otherwise.  We'll get another
+			 * chance to drop them once the last reference to
+			 * the inode is dropped, so we'll never leak blocks
+			 * permanently.
+			 */
+			error = xfs_free_eofblocks(mp, ip,
+						   XFS_FREE_EOF_TRYLOCK);
 			if (error)
 				return error;
 		}
@@ -1184,7 +1179,7 @@
 		     (!(ip->i_d.di_flags &
 				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
 		      (ip->i_delayed_blks != 0)))) {
-			error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+			error = xfs_free_eofblocks(mp, ip, 0);
 			if (error)
 				return VN_INACTIVE_CACHE;
 		}
@@ -1376,7 +1371,7 @@
 	if (error)
 		goto out;
 
-	error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
+	error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
 	if (error)
 		goto out_free_name;
 
@@ -2456,46 +2451,6 @@
 	return error;
 }
 
-int
-xfs_reclaim(
-	xfs_inode_t	*ip)
-{
-
-	xfs_itrace_entry(ip);
-
-	ASSERT(!VN_MAPPED(VFS_I(ip)));
-
-	/* bad inode, get out here ASAP */
-	if (is_bad_inode(VFS_I(ip))) {
-		xfs_ireclaim(ip);
-		return 0;
-	}
-
-	xfs_ioend_wait(ip);
-
-	ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
-
-	/*
-	 * If we have nothing to flush with this inode then complete the
-	 * teardown now, otherwise break the link between the xfs inode and the
-	 * linux inode and clean up the xfs inode later. This avoids flushing
-	 * the inode to disk during the delete operation itself.
-	 *
-	 * When breaking the link, we need to set the XFS_IRECLAIMABLE flag
-	 * first to ensure that xfs_iunpin() will never see an xfs inode
-	 * that has a linux inode being reclaimed. Synchronisation is provided
-	 * by the i_flags_lock.
-	 */
-	if (!ip->i_update_core && (ip->i_itemp == NULL)) {
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		xfs_iflock(ip);
-		xfs_iflags_set(ip, XFS_IRECLAIMABLE);
-		return xfs_reclaim_inode(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC);
-	}
-	xfs_inode_set_reclaim_tag(ip);
-	return 0;
-}
-
 /*
  * xfs_alloc_file_space()
  *      This routine allocates disk space for the given file.
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_fsops.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_fsops.c
@@ -56,6 +56,9 @@
 	xfs_fsop_geom_t		*geo,
 	int			new_version)
 {
+
+	memset(geo, 0, sizeof(*geo));
+
 	geo->blocksize = mp->m_sb.sb_blocksize;
 	geo->rtextsize = mp->m_sb.sb_rextsize;
 	geo->agblocks = mp->m_sb.sb_agblocks;
@@ -611,7 +614,7 @@
 	xfs_inode_t	*ip;
 	int		error;
 
-	tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
+	tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);
 	error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
 	if (error) {
 		xfs_trans_cancel(tp, 0);
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_inode.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_inode.h
@@ -468,7 +468,7 @@
  * xfs_iget.c prototypes.
  */
 int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-			 uint, uint, xfs_inode_t **, xfs_daddr_t);
+			 uint, uint, xfs_inode_t **);
 void		xfs_iput(xfs_inode_t *, uint);
 void		xfs_iput_new(xfs_inode_t *, uint);
 void		xfs_ilock(xfs_inode_t *, uint);
@@ -558,7 +558,7 @@
  * Flags for xfs_iget()
  */
 #define XFS_IGET_CREATE		0x1
-#define XFS_IGET_BULKSTAT	0x2
+#define XFS_IGET_UNTRUSTED	0x2
 
 int		xfs_inotobp(struct xfs_mount *, struct xfs_trans *,
 			    xfs_ino_t, struct xfs_dinode **,
@@ -567,7 +567,7 @@
 			  struct xfs_inode *, struct xfs_dinode **,
 			  struct xfs_buf **, uint);
 int		xfs_iread(struct xfs_mount *, struct xfs_trans *,
-			  struct xfs_inode *, xfs_daddr_t, uint);
+			  struct xfs_inode *, uint);
 void		xfs_dinode_to_disk(struct xfs_dinode *,
 				   struct xfs_icdinode *);
 void		xfs_idestroy_fork(struct xfs_inode *, int);
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_iomap.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_iomap.c
@@ -860,8 +860,15 @@
 		 * set up a transaction to convert the range of extents
 		 * from unwritten to real. Do allocations in a loop until
 		 * we have covered the range passed in.
+		 *
+		 * Note that we open code the transaction allocation here
+		 * to pass KM_NOFS--we can't risk to recursing back into
+		 * the filesystem here as we might be asked to write out
+		 * the same inode that we complete here and might deadlock
+		 * on the iolock.
 		 */
-		tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+		xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
+		tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS);
 		tp->t_flags |= XFS_TRANS_RESERVE;
 		error = xfs_trans_reserve(tp, resblks,
 				XFS_WRITE_LOG_RES(mp), 0,
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_inode.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_inode.c
@@ -177,7 +177,7 @@
 		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
 						XFS_ERRTAG_ITOBP_INOTOBP,
 						XFS_RANDOM_ITOBP_INOTOBP))) {
-			if (iget_flags & XFS_IGET_BULKSTAT) {
+			if (iget_flags & XFS_IGET_UNTRUSTED) {
 				xfs_trans_brelse(tp, bp);
 				return XFS_ERROR(EINVAL);
 			}
@@ -787,7 +787,6 @@
 	xfs_mount_t	*mp,
 	xfs_trans_t	*tp,
 	xfs_inode_t	*ip,
-	xfs_daddr_t	bno,
 	uint		iget_flags)
 {
 	xfs_buf_t	*bp;
@@ -797,11 +796,9 @@
 	/*
 	 * Fill in the location information in the in-core inode.
 	 */
-	ip->i_imap.im_blkno = bno;
 	error = xfs_imap(mp, tp, ip->i_ino, &ip->i_imap, iget_flags);
 	if (error)
 		return error;
-	ASSERT(bno == 0 || bno == ip->i_imap.im_blkno);
 
 	/*
 	 * Get pointers to the on-disk inode and the buffer containing it.
@@ -2877,8 +2874,8 @@
 	mp = ip->i_mount;
 
 	/*
-	 * If the inode isn't dirty, then just release the inode
-	 * flush lock and do nothing.
+	 * If the inode isn't dirty, then just release the inode flush lock and
+	 * do nothing.
 	 */
 	if (xfs_inode_clean(ip)) {
 		xfs_ifunlock(ip);
@@ -2904,6 +2901,19 @@
 	xfs_iunpin_wait(ip);
 
 	/*
+	 * For stale inodes we cannot rely on the backing buffer remaining
+	 * stale in cache for the remaining life of the stale inode and so
+	 * xfs_itobp() below may give us a buffer that no longer contains
+	 * inodes below. We have to check this after ensuring the inode is
+	 * unpinned so that it is safe to reclaim the stale inode after the
+	 * flush call.
+	 */
+	if (xfs_iflags_test(ip, XFS_ISTALE)) {
+		xfs_ifunlock(ip);
+		return 0;
+	}
+
+	/*
 	 * This may have been unpinned because the filesystem is shutting
 	 * down forcibly. If that's the case we must not write this inode
 	 * to disk, because the log record didn't make it to disk!
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_trans_inode.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_trans_inode.c
@@ -62,7 +62,7 @@
 {
 	int			error;
 
-	error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp, 0);
+	error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp);
 	if (!error && tp)
 		xfs_trans_ijoin(tp, *ipp, lock_flags);
 	return error;
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_log_recover.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_log_recover.c
@@ -3209,7 +3209,7 @@
 	int				error;
 
 	ino = XFS_AGINO_TO_INO(mp, agno, agino);
-	error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
+	error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
 	if (error)
 		goto fail;
 
@@ -3517,7 +3517,7 @@
 {
 	xlog_rec_header_t	*rhead;
 	xfs_daddr_t		blk_no;
-	xfs_caddr_t		bufaddr, offset;
+	xfs_caddr_t		offset;
 	xfs_buf_t		*hbp, *dbp;
 	int			error = 0, h_size;
 	int			bblks, split_bblks;
@@ -3610,7 +3610,7 @@
 			/*
 			 * Check for header wrapping around physical end-of-log
 			 */
-			offset = NULL;
+			offset = XFS_BUF_PTR(hbp);
 			split_hblks = 0;
 			wrapped_hblks = 0;
 			if (blk_no + hblks <= log->l_logBBsize) {
@@ -3646,9 +3646,8 @@
 				 *   - order is important.
 				 */
 				wrapped_hblks = hblks - split_hblks;
-				bufaddr = XFS_BUF_PTR(hbp);
 				error = XFS_BUF_SET_PTR(hbp,
-						bufaddr + BBTOB(split_hblks),
+						offset + BBTOB(split_hblks),
 						BBTOB(hblks - split_hblks));
 				if (error)
 					goto bread_err2;
@@ -3658,14 +3657,10 @@
 				if (error)
 					goto bread_err2;
 
-				error = XFS_BUF_SET_PTR(hbp, bufaddr,
+				error = XFS_BUF_SET_PTR(hbp, offset,
 							BBTOB(hblks));
 				if (error)
 					goto bread_err2;
-
-				if (!offset)
-					offset = xlog_align(log, 0,
-							wrapped_hblks, hbp);
 			}
 			rhead = (xlog_rec_header_t *)offset;
 			error = xlog_valid_rec_header(log, rhead,
@@ -3685,7 +3680,7 @@
 			} else {
 				/* This log record is split across the
 				 * physical end of log */
-				offset = NULL;
+				offset = XFS_BUF_PTR(dbp);
 				split_bblks = 0;
 				if (blk_no != log->l_logBBsize) {
 					/* some data is before the physical
@@ -3714,9 +3709,8 @@
 				 *   _first_, then the log start (LR header end)
 				 *   - order is important.
 				 */
-				bufaddr = XFS_BUF_PTR(dbp);
 				error = XFS_BUF_SET_PTR(dbp,
-						bufaddr + BBTOB(split_bblks),
+						offset + BBTOB(split_bblks),
 						BBTOB(bblks - split_bblks));
 				if (error)
 					goto bread_err2;
@@ -3727,13 +3721,9 @@
 				if (error)
 					goto bread_err2;
 
-				error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+				error = XFS_BUF_SET_PTR(dbp, offset, h_size);
 				if (error)
 					goto bread_err2;
-
-				if (!offset)
-					offset = xlog_align(log, wrapped_hblks,
-						bblks - split_bblks, dbp);
 			}
 			xlog_unpack_data(rhead, offset, log);
 			if ((error = xlog_recover_process_data(log, rhash,
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_trans.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_trans.h
@@ -924,7 +924,7 @@
  * XFS transaction mechanism exported interfaces.
  */
 xfs_trans_t	*xfs_trans_alloc(struct xfs_mount *, uint);
-xfs_trans_t	*_xfs_trans_alloc(struct xfs_mount *, uint);
+xfs_trans_t	*_xfs_trans_alloc(struct xfs_mount *, uint, uint);
 xfs_trans_t	*xfs_trans_dup(xfs_trans_t *);
 int		xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
 				  uint, uint);
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_rtalloc.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_rtalloc.c
@@ -2274,12 +2274,12 @@
 	sbp = &mp->m_sb;
 	if (sbp->sb_rbmino == NULLFSINO)
 		return 0;
-	error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
+	error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
 	if (error)
 		return error;
 	ASSERT(mp->m_rbmip != NULL);
 	ASSERT(sbp->sb_rsumino != NULLFSINO);
-	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
+	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
 	if (error) {
 		IRELE(mp->m_rbmip);
 		return error;
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_iget.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_iget.c
@@ -228,13 +228,12 @@
 		xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
 
 		/*
-		 * We need to set XFS_INEW atomically with clearing the
-		 * reclaimable tag so that we do have an indicator of the
-		 * inode still being initialized.
+		 * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+		 * from stomping over us while we recycle the inode.  We can't
+		 * clear the radix tree reclaimable tag yet as it requires
+		 * pag_ici_lock to be held exclusive.
 		 */
-		ip->i_flags |= XFS_INEW;
-		ip->i_flags &= ~XFS_IRECLAIMABLE;
-		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
+		ip->i_flags |= XFS_IRECLAIM;
 
 		spin_unlock(&ip->i_flags_lock);
 		read_unlock(&pag->pag_ici_lock);
@@ -253,7 +252,15 @@
 			__xfs_inode_set_reclaim_tag(pag, ip);
 			goto out_error;
 		}
+
+		write_lock(&pag->pag_ici_lock);
+		spin_lock(&ip->i_flags_lock);
+		ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
+		ip->i_flags |= XFS_INEW;
+		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
 		inode->i_state = I_LOCK|I_NEW;
+		spin_unlock(&ip->i_flags_lock);
+		write_unlock(&pag->pag_ici_lock);
 	} else {
 		/* If the VFS inode is being torn down, pause and try again. */
 		if (!igrab(inode)) {
@@ -288,7 +295,6 @@
 	xfs_trans_t		*tp,
 	xfs_ino_t		ino,
 	struct xfs_inode	**ipp,
-	xfs_daddr_t		bno,
 	int			flags,
 	int			lock_flags) __releases(pag->pag_ici_lock)
 {
@@ -301,7 +307,7 @@
 	if (!ip)
 		return ENOMEM;
 
-	error = xfs_iread(mp, tp, ip, bno, flags);
+	error = xfs_iread(mp, tp, ip, flags);
 	if (error)
 		goto out_destroy;
 
@@ -385,8 +391,6 @@
  *        within the file system for the inode being requested.
  * lock_flags -- flags indicating how to lock the inode.  See the comment
  *		 for xfs_ilock() for a list of valid values.
- * bno -- the block number starting the buffer containing the inode,
- *	  if known (as by bulkstat), else 0.
  */
 int
 xfs_iget(
@@ -395,8 +399,7 @@
 	xfs_ino_t	ino,
 	uint		flags,
 	uint		lock_flags,
-	xfs_inode_t	**ipp,
-	xfs_daddr_t	bno)
+	xfs_inode_t	**ipp)
 {
 	xfs_inode_t	*ip;
 	int		error;
@@ -427,7 +430,7 @@
 		read_unlock(&pag->pag_ici_lock);
 		XFS_STATS_INC(xs_ig_missed);
 
-		error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip, bno,
+		error = xfs_iget_cache_miss(mp, pag, tp, ino, &ip,
 							flags, lock_flags);
 		if (error)
 			goto out_error_or_again;
@@ -511,17 +514,21 @@
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_perag	*pag;
+	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
 
 	XFS_STATS_INC(xs_ig_reclaims);
 
 	/*
-	 * Remove the inode from the per-AG radix tree.  It doesn't matter
-	 * if it was never added to it because radix_tree_delete can deal
-	 * with that case just fine.
+	 * Remove the inode from the per-AG radix tree.
+	 *
+	 * Because radix_tree_delete won't complain even if the item was never
+	 * added to the tree assert that it's been there before to catch
+	 * problems with the inode life time early on.
 	 */
 	pag = xfs_get_perag(mp, ip->i_ino);
 	write_lock(&pag->pag_ici_lock);
-	radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino));
+	if (!radix_tree_delete(&pag->pag_ici_root, agino))
+		ASSERT(0);
 	write_unlock(&pag->pag_ici_lock);
 	xfs_put_perag(mp, pag);
 
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_trans.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_trans.c
@@ -236,19 +236,20 @@
 	uint		type)
 {
 	xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
-	return _xfs_trans_alloc(mp, type);
+	return _xfs_trans_alloc(mp, type, KM_SLEEP);
 }
 
 xfs_trans_t *
 _xfs_trans_alloc(
 	xfs_mount_t	*mp,
-	uint		type)
+	uint		type,
+	uint		memflags)
 {
 	xfs_trans_t	*tp;
 
 	atomic_inc(&mp->m_active_trans);
 
-	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
+	tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
 	tp->t_magic = XFS_TRANS_MAGIC;
 	tp->t_type = type;
 	tp->t_mountp = mp;
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_mount.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_mount.c
@@ -1207,7 +1207,7 @@
 	 * Get and sanity-check the root inode.
 	 * Save the pointer to it in the mount structure.
 	 */
-	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
+	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
 	if (error) {
 		cmn_err(CE_WARN, "XFS: failed to read root inode");
 		goto out_log_dealloc;
@@ -1471,7 +1471,7 @@
 	if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
 		return 0;
 
-	tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT);
+	tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);
 	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
 					XFS_DEFAULT_LOG_COUNT);
 	if (error) {
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_mount.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_mount.h
@@ -209,6 +209,7 @@
 	__uint64_t		m_maxioffset;	/* maximum inode offset */
 	__uint64_t		m_resblks;	/* total reserved blocks */
 	__uint64_t		m_resblks_avail;/* available reserved blocks */
+	__uint64_t		m_resblks_save;	/* reserved blks @ remount,ro */
 	int			m_dalign;	/* stripe unit */
 	int			m_swidth;	/* stripe width */
 	int			m_sinoalign;	/* stripe unit inode alignment */
@@ -242,6 +243,7 @@
 	wait_queue_head_t	m_wait_single_sync_task;
 	__int64_t		m_update_flags;	/* sb flags we need to update
 						   on the next remount,rw */
+	struct list_head	m_mplist;	/* inode shrinker mount list */
 } xfs_mount_t;
 
 /*
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_ialloc.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_ialloc.c
@@ -1206,6 +1206,69 @@
 	return error;
 }
 
+STATIC int
+xfs_imap_lookup(
+	struct xfs_mount	*mp,
+	struct xfs_trans	*tp,
+	xfs_agnumber_t		agno,
+	xfs_agino_t		agino,
+	xfs_agblock_t		agbno,
+	xfs_agblock_t		*chunk_agbno,
+	xfs_agblock_t		*offset_agbno,
+	int			flags)
+{
+	struct xfs_inobt_rec_incore rec;
+	struct xfs_btree_cur	*cur;
+	struct xfs_buf		*agbp;
+	int			error;
+	int			i;
+
+	down_read(&mp->m_peraglock);
+	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+	up_read(&mp->m_peraglock);
+	if (error) {
+		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
+				"xfs_ialloc_read_agi() returned "
+				"error %d, agno %d",
+				error, agno);
+		return error;
+	}
+
+	/*
+	 * Lookup the inode record for the given agino. If the record cannot be
+	 * found, then it's an invalid inode number and we should abort. Once
+	 * we have a record, we need to ensure it contains the inode number
+	 * we are looking up.
+	 */
+	cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
+	error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
+	if (!error) {
+		if (i)
+			error = xfs_inobt_get_rec(cur, &rec, &i);
+		if (!error && i == 0)
+			error = EINVAL;
+	}
+
+	xfs_trans_brelse(tp, agbp);
+	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+	if (error)
+		return error;
+
+	/* check that the returned record contains the required inode */
+	if (rec.ir_startino > agino ||
+	    rec.ir_startino + XFS_IALLOC_INODES(mp) <= agino)
+		return EINVAL;
+
+	/* for untrusted inodes check it is allocated first */
+	if ((flags & XFS_IGET_UNTRUSTED) &&
+	    (rec.ir_free & XFS_INOBT_MASK(agino - rec.ir_startino)))
+		return EINVAL;
+
+	*chunk_agbno = XFS_AGINO_TO_AGBNO(mp, rec.ir_startino);
+	*offset_agbno = agbno - *chunk_agbno;
+	return 0;
+}
+
 /*
  * Return the location of the inode in imap, for mapping it into a buffer.
  */
@@ -1238,8 +1301,11 @@
 	if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
 	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
 #ifdef DEBUG
-		/* no diagnostics for bulkstat, ino comes from userspace */
-		if (flags & XFS_IGET_BULKSTAT)
+		/*
+		 * Don't output diagnostic information for untrusted inodes
+		 * as they can be invalid without implying corruption.
+		 */
+		if (flags & XFS_IGET_UNTRUSTED)
 			return XFS_ERROR(EINVAL);
 		if (agno >= mp->m_sb.sb_agcount) {
 			xfs_fs_cmn_err(CE_ALERT, mp,
@@ -1266,6 +1332,23 @@
 		return XFS_ERROR(EINVAL);
 	}
 
+	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
+
+	/*
+	 * For bulkstat and handle lookups, we have an untrusted inode number
+	 * that we have to verify is valid. We cannot do this just by reading
+	 * the inode buffer as it may have been unlinked and removed leaving
+	 * inodes in stale state on disk. Hence we have to do a btree lookup
+	 * in all cases where an untrusted inode number is passed.
+	 */
+	if (flags & XFS_IGET_UNTRUSTED) {
+		error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+					&chunk_agbno, &offset_agbno, flags);
+		if (error)
+			return error;
+		goto out_map;
+	}
+
 	/*
 	 * If the inode cluster size is the same as the blocksize or
 	 * smaller we get to the buffer by simple arithmetics.
@@ -1280,24 +1363,6 @@
 		return 0;
 	}
 
-	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
-
-	/*
-	 * If we get a block number passed from bulkstat we can use it to
-	 * find the buffer easily.
-	 */
-	if (imap->im_blkno) {
-		offset = XFS_INO_TO_OFFSET(mp, ino);
-		ASSERT(offset < mp->m_sb.sb_inopblock);
-
-		cluster_agbno = xfs_daddr_to_agbno(mp, imap->im_blkno);
-		offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock;
-
-		imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
-		imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog);
-		return 0;
-	}
-
 	/*
 	 * If the inode chunks are aligned then use simple maths to
 	 * find the location. Otherwise we have to do a btree
@@ -1307,52 +1372,13 @@
 		offset_agbno = agbno & mp->m_inoalign_mask;
 		chunk_agbno = agbno - offset_agbno;
 	} else {
-		xfs_btree_cur_t	*cur;	/* inode btree cursor */
-		xfs_inobt_rec_incore_t chunk_rec;
-		xfs_buf_t	*agbp;	/* agi buffer */
-		int		i;	/* temp state */
-
-		down_read(&mp->m_peraglock);
-		error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
-		up_read(&mp->m_peraglock);
-		if (error) {
-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-					"xfs_ialloc_read_agi() returned "
-					"error %d, agno %d",
-					error, agno);
-			return error;
-		}
-
-		cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
-		error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i);
-		if (error) {
-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-					"xfs_inobt_lookup() failed");
-			goto error0;
-		}
-
-		error = xfs_inobt_get_rec(cur, &chunk_rec, &i);
-		if (error) {
-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-					"xfs_inobt_get_rec() failed");
-			goto error0;
-		}
-		if (i == 0) {
-#ifdef DEBUG
-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-					"xfs_inobt_get_rec() failed");
-#endif /* DEBUG */
-			error = XFS_ERROR(EINVAL);
-		}
- error0:
-		xfs_trans_brelse(tp, agbp);
-		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+		error = xfs_imap_lookup(mp, tp, agno, agino, agbno,
+					&chunk_agbno, &offset_agbno, flags);
 		if (error)
 			return error;
-		chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_rec.ir_startino);
-		offset_agbno = agbno - chunk_agbno;
 	}
 
+out_map:
 	ASSERT(agbno >= chunk_agbno);
 	cluster_agbno = chunk_agbno +
 		((offset_agbno / blks_per_cluster) * blks_per_cluster);
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_dfrag.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_dfrag.c
@@ -62,7 +62,9 @@
 		goto out;
 	}
 
-	if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) {
+	if (!(file->f_mode & FMODE_WRITE) ||
+	    !(file->f_mode & FMODE_READ) ||
+	    (file->f_flags & O_APPEND)) {
 		error = XFS_ERROR(EBADF);
 		goto out_put_file;
 	}
@@ -74,6 +76,7 @@
 	}
 
 	if (!(target_file->f_mode & FMODE_WRITE) ||
+	    !(target_file->f_mode & FMODE_READ) ||
 	    (target_file->f_flags & O_APPEND)) {
 		error = XFS_ERROR(EBADF);
 		goto out_put_target_file;
@@ -113,10 +116,82 @@
 	return error;
 }
 
+/*
+ * We need to check that the format of the data fork in the temporary inode is
+ * valid for the target inode before doing the swap. This is not a problem with
+ * attr1 because of the fixed fork offset, but attr2 has a dynamically sized
+ * data fork depending on the space the attribute fork is taking so we can get
+ * invalid formats on the target inode.
+ *
+ * E.g. target has space for 7 extents in extent format, temp inode only has
+ * space for 6.  If we defragment down to 7 extents, then the tmp format is a
+ * btree, but when swapped it needs to be in extent format. Hence we can't just
+ * blindly swap data forks on attr2 filesystems.
+ *
+ * Note that we check the swap in both directions so that we don't end up with
+ * a corrupt temporary inode, either.
+ *
+ * Note that fixing the way xfs_fsr sets up the attribute fork in the source
+ * inode will prevent this situation from occurring, so all we do here is
+ * reject and log the attempt. basically we are putting the responsibility on
+ * userspace to get this right.
+ */
+static int
+xfs_swap_extents_check_format(
+	xfs_inode_t	*ip,	/* target inode */
+	xfs_inode_t	*tip)	/* tmp inode */
+{
+
+	/* Should never get a local format */
+	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
+	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL)
+		return EINVAL;
+
+	/*
+	 * if the target inode has less extents that then temporary inode then
+	 * why did userspace call us?
+	 */
+	if (ip->i_d.di_nextents < tip->i_d.di_nextents)
+		return EINVAL;
+
+	/*
+	 * if the target inode is in extent form and the temp inode is in btree
+	 * form then we will end up with the target inode in the wrong format
+	 * as we already know there are less extents in the temp inode.
+	 */
+	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
+	    tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
+		return EINVAL;
+
+	/* Check temp in extent form to max in target */
+	if (tip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
+	    XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) > ip->i_df.if_ext_max)
+		return EINVAL;
+
+	/* Check target in extent form to max in temp */
+	if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
+	    XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > tip->i_df.if_ext_max)
+		return EINVAL;
+
+	/* Check root block of temp in btree form to max in target */
+	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
+	    XFS_IFORK_BOFF(ip) &&
+	    tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip))
+		return EINVAL;
+
+	/* Check root block of target in btree form to max in temp */
+	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
+	    XFS_IFORK_BOFF(tip) &&
+	    ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip))
+		return EINVAL;
+
+	return 0;
+}
+
 int
 xfs_swap_extents(
-	xfs_inode_t	*ip,
-	xfs_inode_t	*tip,
+	xfs_inode_t	*ip,	/* target inode */
+	xfs_inode_t	*tip,	/* tmp inode */
 	xfs_swapext_t	*sxp)
 {
 	xfs_mount_t	*mp;
@@ -160,13 +235,6 @@
 		goto out_unlock;
 	}
 
-	/* Should never get a local format */
-	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
-	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		error = XFS_ERROR(EINVAL);
-		goto out_unlock;
-	}
-
 	if (VN_CACHED(VFS_I(tip)) != 0) {
 		xfs_inval_cached_trace(tip, 0, -1, 0, -1);
 		error = xfs_flushinval_pages(tip, 0, -1,
@@ -189,13 +257,12 @@
 		goto out_unlock;
 	}
 
-	/*
-	 * If the target has extended attributes, the tmp file
-	 * must also in order to ensure the correct data fork
-	 * format.
-	 */
-	if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) {
-		error = XFS_ERROR(EINVAL);
+	/* check inode formats now that data is flushed */
+	error = xfs_swap_extents_check_format(ip, tip);
+	if (error) {
+		xfs_fs_cmn_err(CE_NOTE, mp,
+		    "%s: inode 0x%llx format is incompatible for exchanging.",
+				__FILE__, ip->i_ino);
 		goto out_unlock;
 	}
 
@@ -276,6 +343,16 @@
 	*tifp = *tempifp;	/* struct copy */
 
 	/*
+	 * Fix the in-memory data fork values that are dependent on the fork
+	 * offset in the inode. We can't assume they remain the same as attr2
+	 * has dynamic fork offsets.
+	 */
+	ifp->if_ext_max = XFS_IFORK_SIZE(ip, XFS_DATA_FORK) /
+					(uint)sizeof(xfs_bmbt_rec_t);
+	tifp->if_ext_max = XFS_IFORK_SIZE(tip, XFS_DATA_FORK) /
+					(uint)sizeof(xfs_bmbt_rec_t);
+
+	/*
 	 * Fix the on-disk inode values
 	 */
 	tmp = (__uint64_t)ip->i_d.di_nblocks;
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_alloc.c
+++ linux-ec2-2.6.32/fs/xfs/xfs_alloc.c
@@ -2703,45 +2703,35 @@
 	xfs_mount_t		*mp;
 	xfs_perag_busy_t	*bsy;
 	xfs_agblock_t		uend, bend;
-	xfs_lsn_t		lsn;
+	xfs_lsn_t		lsn = 0;
 	int			cnt;
 
 	mp = tp->t_mountp;
 
 	spin_lock(&mp->m_perag[agno].pagb_lock);
-	cnt = mp->m_perag[agno].pagb_count;
-
 	uend = bno + len - 1;
 
-	/* search pagb_list for this slot, skipping open slots */
-	for (bsy = mp->m_perag[agno].pagb_list; cnt; bsy++) {
-
-		/*
-		 * (start1,length1) within (start2, length2)
-		 */
-		if (bsy->busy_tp != NULL) {
-			bend = bsy->busy_start + bsy->busy_length - 1;
-			if ((bno > bend) || (uend < bsy->busy_start)) {
-				cnt--;
-			} else {
-				TRACE_BUSYSEARCH("xfs_alloc_search_busy",
-					 "found1", agno, bno, len, tp);
-				break;
-			}
-		}
-	}
-
 	/*
-	 * If a block was found, force the log through the LSN of the
-	 * transaction that freed the block
+	 * search pagb_list for this slot, skipping open slots. We have to
+	 * search the entire array as there may be multiple overlaps and
+	 * we have to get the most recent LSN for the log force to push out
+	 * all the transactions that span the range.
 	 */
-	if (cnt) {
-		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, tp);
-		lsn = bsy->busy_tp->t_commit_lsn;
-		spin_unlock(&mp->m_perag[agno].pagb_lock);
-		xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
-	} else {
-		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, tp);
-		spin_unlock(&mp->m_perag[agno].pagb_lock);
+	for (cnt = 0; cnt < mp->m_perag[agno].pagb_count; cnt++) {
+		bsy = &mp->m_perag[agno].pagb_list[cnt];
+		if (!bsy->busy_tp)
+			continue;
+		bend = bsy->busy_start + bsy->busy_length - 1;
+		if (bno > bend || uend < bsy->busy_start)
+			continue;
+
+		/* (start1,length1) within (start2, length2) */
+		if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0)
+			lsn = bsy->busy_tp->t_commit_lsn;
 	}
+	spin_unlock(&mp->m_perag[agno].pagb_lock);
+	TRACE_BUSYSEARCH("xfs_alloc_search_busy", lsn ? "found" : "not-found",
+						agno, bno, len, tp);
+	if (lsn)
+		xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_itable.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_itable.h
@@ -27,10 +27,7 @@
 			       xfs_ino_t	ino,
 			       void		__user *buffer,
 			       int		ubsize,
-			       void		*private_data,
-			       xfs_daddr_t	bno,
 			       int		*ubused,
-			       void		*dip,
 			       int		*stat);
 
 /*
@@ -41,13 +38,6 @@
 #define BULKSTAT_RV_GIVEUP	2
 
 /*
- * Values for bulkstat flag argument.
- */
-#define BULKSTAT_FG_IGET	0x1	/* Go through the buffer cache */
-#define BULKSTAT_FG_QUICK	0x2	/* No iget, walk the dinode cluster */
-#define BULKSTAT_FG_INLINE	0x4	/* No iget if inline attrs */
-
-/*
  * Return stat information in bulk (by-inode) for the filesystem.
  */
 int					/* error status */
@@ -56,10 +46,8 @@
 	xfs_ino_t	*lastino,	/* last inode returned */
 	int		*count,		/* size of buffer/count returned */
 	bulkstat_one_pf formatter,	/* func that'd fill a single buf */
-	void		*private_data,	/* private data for formatter */
 	size_t		statstruct_size,/* sizeof struct that we're filling */
 	char		__user *ubuffer,/* buffer with inode stats */
-	int		flags,		/* flag to control access method */
 	int		*done);		/* 1 if there are more stats to get */
 
 int
@@ -82,9 +70,7 @@
 	void			__user *buffer,
 	int			ubsize,
 	bulkstat_one_fmt_pf	formatter,
-	xfs_daddr_t		bno,
 	int			*ubused,
-	void			*dibuff,
 	int			*stat);
 
 int
@@ -93,10 +79,7 @@
 	xfs_ino_t		ino,
 	void			__user *buffer,
 	int			ubsize,
-	void			*private_data,
-	xfs_daddr_t		bno,
 	int			*ubused,
-	void			*dibuff,
 	int			*stat);
 
 typedef int (*inumbers_fmt_pf)(
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_rw.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_rw.h
@@ -37,13 +37,6 @@
 }
 
 /*
- * Flags for xfs_free_eofblocks
- */
-#define XFS_FREE_EOF_LOCK	(1<<0)
-#define XFS_FREE_EOF_NOLOCK	(1<<1)
-
-
-/*
  * helper function to extract extent size hint from inode
  */
 STATIC_INLINE xfs_extlen_t
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_vnodeops.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_vnodeops.h
@@ -38,7 +38,6 @@
 		const char *target_path, mode_t mode, struct xfs_inode **ipp,
 		cred_t *credp);
 int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
-int xfs_reclaim(struct xfs_inode *ip);
 int xfs_change_file_space(struct xfs_inode *ip, int cmd,
 		xfs_flock64_t *bf, xfs_off_t offset, int attr_flags);
 int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
--- linux-ec2-2.6.32.orig/fs/xfs/xfs_ag.h
+++ linux-ec2-2.6.32/fs/xfs/xfs_ag.h
@@ -215,6 +215,7 @@
 	int		pag_ici_init;	/* incore inode cache initialised */
 	rwlock_t	pag_ici_lock;	/* incore inode lock */
 	struct radix_tree_root pag_ici_root;	/* incore inode cache root */
+	int		pag_ici_reclaimable;	/* reclaimable inodes */
 #endif
 } xfs_perag_t;
 
--- linux-ec2-2.6.32.orig/fs/xfs/quota/xfs_qm_syscalls.c
+++ linux-ec2-2.6.32/fs/xfs/quota/xfs_qm_syscalls.c
@@ -266,7 +266,7 @@
 	}
 
 	if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
-		error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
+		error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip);
 		if (!error) {
 			error = xfs_truncate_file(mp, qip);
 			IRELE(qip);
@@ -275,7 +275,7 @@
 
 	if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
 	    mp->m_sb.sb_gquotino != NULLFSINO) {
-		error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+		error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip);
 		if (!error2) {
 			error2 = xfs_truncate_file(mp, qip);
 			IRELE(qip);
@@ -420,12 +420,12 @@
 	}
 	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
 		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-					0, 0, &uip, 0) == 0)
+					0, 0, &uip) == 0)
 			tempuqip = B_TRUE;
 	}
 	if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
 		if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-					0, 0, &gip, 0) == 0)
+					0, 0, &gip) == 0)
 			tempgqip = B_TRUE;
 	}
 	if (uip) {
@@ -893,7 +893,8 @@
 	uint		 flags)
 {
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, XFS_ICI_NO_TAG);
+	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags,
+				XFS_ICI_NO_TAG, 0, NULL);
 }
 
 /*------------------------------------------------------------------------*/
@@ -1113,10 +1114,7 @@
 	xfs_ino_t	ino,		/* inode number to get data for */
 	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
-	void		*private_data,	/* not used */
-	xfs_daddr_t	bno,		/* starting block of inode cluster */
 	int		*ubused,	/* not used */
-	void		*dip,		/* not used */
 	int		*res)		/* bulkstat result code */
 {
 	xfs_inode_t		*ip;
@@ -1138,7 +1136,7 @@
 	ipreleased = B_FALSE;
  again:
 	lock_flags = XFS_ILOCK_SHARED;
-	if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {
+	if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) {
 		*res = BULKSTAT_RV_NOTHING;
 		return (error);
 	}
@@ -1211,15 +1209,15 @@
 		 * Iterate thru all the inodes in the file system,
 		 * adjusting the corresponding dquot counters
 		 */
-		if ((error = xfs_bulkstat(mp, &lastino, &count,
-				 xfs_qm_internalqcheck_adjust, NULL,
-				 0, NULL, BULKSTAT_FG_IGET, &done))) {
+		error = xfs_bulkstat(mp, &lastino, &count,
+				 xfs_qm_internalqcheck_adjust,
+				 0, NULL, &done);
+		if (error) {
+			cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
 			break;
 		}
-	} while (! done);
-	if (error) {
-		cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
-	}
+	} while (!done);
+
 	cmn_err(CE_DEBUG, "Checking results against system dquots");
 	for (i = 0; i < qmtest_hashmask; i++) {
 		h1 = &qmtest_udqtab[i];
--- linux-ec2-2.6.32.orig/fs/xfs/quota/xfs_qm_bhv.c
+++ linux-ec2-2.6.32/fs/xfs/quota/xfs_qm_bhv.c
@@ -59,7 +59,7 @@
 		be64_to_cpu(dp->d_blk_hardlimit);
 	if (limit && statp->f_blocks > limit) {
 		statp->f_blocks = limit;
-		statp->f_bfree =
+		statp->f_bfree = statp->f_bavail =
 			(statp->f_blocks > be64_to_cpu(dp->d_bcount)) ?
 			 (statp->f_blocks - be64_to_cpu(dp->d_bcount)) : 0;
 	}
--- linux-ec2-2.6.32.orig/fs/xfs/quota/xfs_qm.c
+++ linux-ec2-2.6.32/fs/xfs/quota/xfs_qm.c
@@ -1606,10 +1606,7 @@
 	xfs_ino_t	ino,		/* inode number to get data for */
 	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
-	void		*private_data,	/* not used */
-	xfs_daddr_t	bno,		/* starting block of inode cluster */
 	int		*ubused,	/* not used */
-	void		*dip,		/* on-disk inode pointer (not used) */
 	int		*res)		/* result code value */
 {
 	xfs_inode_t	*ip;
@@ -1634,7 +1631,7 @@
 	 * the case in all other instances. It's OK that we do this because
 	 * quotacheck is done only at mount time.
 	 */
-	if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) {
+	if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
 		*res = BULKSTAT_RV_NOTHING;
 		return error;
 	}
@@ -1766,12 +1763,13 @@
 		 * Iterate thru all the inodes in the file system,
 		 * adjusting the corresponding dquot counters in core.
 		 */
-		if ((error = xfs_bulkstat(mp, &lastino, &count,
-				     xfs_qm_dqusage_adjust, NULL,
-				     structsz, NULL, BULKSTAT_FG_IGET, &done)))
+		error = xfs_bulkstat(mp, &lastino, &count,
+				     xfs_qm_dqusage_adjust,
+				     structsz, NULL, &done);
+		if (error)
 			break;
 
-	} while (! done);
+	} while (!done);
 
 	/*
 	 * We've made all the changes that we need to make incore.
@@ -1859,14 +1857,14 @@
 		    mp->m_sb.sb_uquotino != NULLFSINO) {
 			ASSERT(mp->m_sb.sb_uquotino > 0);
 			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
-					     0, 0, &uip, 0)))
+					     0, 0, &uip)))
 				return XFS_ERROR(error);
 		}
 		if (XFS_IS_OQUOTA_ON(mp) &&
 		    mp->m_sb.sb_gquotino != NULLFSINO) {
 			ASSERT(mp->m_sb.sb_gquotino > 0);
 			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
-					     0, 0, &gip, 0))) {
+					     0, 0, &gip))) {
 				if (uip)
 					IRELE(uip);
 				return XFS_ERROR(error);
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_super.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_super.c
@@ -930,13 +930,37 @@
  */
 STATIC void
 xfs_fs_destroy_inode(
-	struct inode	*inode)
+	struct inode		*inode)
 {
-	xfs_inode_t		*ip = XFS_I(inode);
+	struct xfs_inode	*ip = XFS_I(inode);
+
+	xfs_itrace_entry(ip);
 
 	XFS_STATS_INC(vn_reclaim);
-	if (xfs_reclaim(ip))
-		panic("%s: cannot reclaim 0x%p\n", __func__, inode);
+
+	/* bad inode, get out here ASAP */
+	if (is_bad_inode(inode))
+		goto out_reclaim;
+
+	xfs_ioend_wait(ip);
+
+	ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
+
+	/*
+	 * We should never get here with one of the reclaim flags already set.
+	 */
+	ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+	ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM));
+
+	/*
+	 * We always use background reclaim here because even if the
+	 * inode is clean, it still may be under IO and hence we have
+	 * to take the flush lock. The background reclaim path handles
+	 * this more efficiently than we can here, so simply let background
+	 * reclaim tear down all inodes.
+	 */
+out_reclaim:
+	xfs_inode_set_reclaim_tag(ip);
 }
 
 /*
@@ -1140,6 +1164,7 @@
 
 	xfs_unmountfs(mp);
 	xfs_freesb(mp);
+	xfs_inode_shrinker_unregister(mp);
 	xfs_icsb_destroy_counters(mp);
 	xfs_close_devices(mp);
 	xfs_dmops_put(mp);
@@ -1299,6 +1324,8 @@
 
 	/* ro -> rw */
 	if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
+		__uint64_t resblks;
+
 		mp->m_flags &= ~XFS_MOUNT_RDONLY;
 		if (mp->m_flags & XFS_MOUNT_BARRIER)
 			xfs_mountfs_check_barriers(mp);
@@ -1316,11 +1343,37 @@
 			}
 			mp->m_update_flags = 0;
 		}
+
+		/*
+		 * Fill out the reserve pool if it is empty. Use the stashed
+		 * value if it is non-zero, otherwise go with the default.
+		 */
+		if (mp->m_resblks_save) {
+			resblks = mp->m_resblks_save;
+			mp->m_resblks_save = 0;
+		} else {
+			resblks = mp->m_sb.sb_dblocks;
+			do_div(resblks, 20);
+			resblks = min_t(__uint64_t, resblks, 1024);
+		}
+		xfs_reserve_blocks(mp, &resblks, NULL);
 	}
 
 	/* rw -> ro */
 	if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (*flags & MS_RDONLY)) {
+		/*
+		 * After we have synced the data but before we sync the
+		 * metadata, we need to free up the reserve block pool so that
+		 * the used block count in the superblock on disk is correct at
+		 * the end of the remount. Stash the current reserve pool size
+		 * so that if we get remounted rw, we can return it to the same
+		 * size.
+		 */
+		__uint64_t resblks = 0;
+
 		xfs_quiesce_data(mp);
+		mp->m_resblks_save = mp->m_resblks;
+		xfs_reserve_blocks(mp, &resblks, NULL);
 		xfs_quiesce_attr(mp);
 		mp->m_flags |= XFS_MOUNT_RDONLY;
 	}
@@ -1503,6 +1556,8 @@
 	if (error)
 		goto fail_vnrele;
 
+	xfs_inode_shrinker_register(mp);
+
 	kfree(mtpt);
 
 	xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
@@ -1842,6 +1897,7 @@
 		goto out_cleanup_procfs;
 
 	vfs_initquota();
+	xfs_inode_shrinker_init();
 
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
@@ -1871,6 +1927,7 @@
 {
 	vfs_exitquota();
 	unregister_filesystem(&xfs_fs_type);
+	xfs_inode_shrinker_destroy();
 	xfs_sysctl_unregister();
 	xfs_cleanup_procfs();
 	xfs_buf_terminate();
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -235,15 +235,12 @@
 	xfs_ino_t	ino,		/* inode number to get data for */
 	void		__user *buffer,	/* buffer to place output in */
 	int		ubsize,		/* size of buffer */
-	void		*private_data,	/* my private data */
-	xfs_daddr_t	bno,		/* starting bno of inode cluster */
 	int		*ubused,	/* bytes used by me */
-	void		*dibuff,	/* on-disk inode buffer */
 	int		*stat)		/* BULKSTAT_RV_... */
 {
 	return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
-				    xfs_bulkstat_one_fmt_compat, bno,
-				    ubused, dibuff, stat);
+				    xfs_bulkstat_one_fmt_compat,
+				    ubused, stat);
 }
 
 /* copied from xfs_ioctl.c */
@@ -296,13 +293,11 @@
 		int res;
 
 		error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
-				sizeof(compat_xfs_bstat_t),
-				NULL, 0, NULL, NULL, &res);
+				sizeof(compat_xfs_bstat_t), 0, &res);
 	} else if (cmd == XFS_IOC_FSBULKSTAT_32) {
 		error = xfs_bulkstat(mp, &inlast, &count,
-			xfs_bulkstat_one_compat, NULL,
-			sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
-			BULKSTAT_FG_QUICK, &done);
+			xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
+			bulkreq.ubuffer, &done);
 	} else
 		error = XFS_ERROR(EINVAL);
 	if (error)
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_acl.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_acl.c
@@ -250,8 +250,9 @@
 	if (mode != inode->i_mode) {
 		struct iattr iattr;
 
-		iattr.ia_valid = ATTR_MODE;
+		iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
 		iattr.ia_mode = mode;
+		iattr.ia_ctime = current_fs_time(inode->i_sb);
 
 		error = -xfs_setattr(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
 	}
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_export.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_export.c
@@ -127,13 +127,12 @@
 		return ERR_PTR(-ESTALE);
 
 	/*
-	 * The XFS_IGET_BULKSTAT means that an invalid inode number is just
-	 * fine and not an indication of a corrupted filesystem.  Because
-	 * clients can send any kind of invalid file handle, e.g. after
-	 * a restore on the server we have to deal with this case gracefully.
+	 * The XFS_IGET_UNTRUSTED means that an invalid inode number is just
+	 * fine and not an indication of a corrupted filesystem as clients can
+	 * send invalid file handles and we have to handle it gracefully..
 	 */
-	error = xfs_iget(mp, NULL, ino, XFS_IGET_BULKSTAT,
-			 XFS_ILOCK_SHARED, &ip, 0);
+	error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED,
+			 XFS_ILOCK_SHARED, &ip);
 	if (error) {
 		/*
 		 * EINVAL means the inode cluster doesn't exist anymore.
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_aops.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_aops.c
@@ -204,14 +204,17 @@
 }
 
 /*
- * Update on-disk file size now that data has been written to disk.
- * The current in-memory file size is i_size.  If a write is beyond
- * eof i_new_size will be the intended file size until i_size is
- * updated.  If this write does not extend all the way to the valid
- * file size then restrict this update to the end of the write.
+ * Update on-disk file size now that data has been written to disk.  The
+ * current in-memory file size is i_size.  If a write is beyond eof i_new_size
+ * will be the intended file size until i_size is updated.  If this write does
+ * not extend all the way to the valid file size then restrict this update to
+ * the end of the write.
+ *
+ * This function does not block as blocking on the inode lock in IO completion
+ * can lead to IO completion order dependency deadlocks.. If it can't get the
+ * inode ilock it will return EAGAIN. Callers must handle this.
  */
-
-STATIC void
+STATIC int
 xfs_setfilesize(
 	xfs_ioend_t		*ioend)
 {
@@ -222,9 +225,11 @@
 	ASSERT(ioend->io_type != IOMAP_READ);
 
 	if (unlikely(ioend->io_error))
-		return;
+		return 0;
+
+	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
+		return EAGAIN;
 
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	isize = xfs_ioend_new_eof(ioend);
 	if (isize) {
 		ip->i_d.di_size = isize;
@@ -232,6 +237,28 @@
 	}
 
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	return 0;
+}
+
+/*
+ * Schedule IO completion handling on a xfsdatad if this was
+ * the final hold on this ioend. If we are asked to wait,
+ * flush the workqueue.
+ */
+STATIC void
+xfs_finish_ioend(
+	xfs_ioend_t	*ioend,
+	int		wait)
+{
+	if (atomic_dec_and_test(&ioend->io_remaining)) {
+		struct workqueue_struct *wq;
+
+		wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
+			xfsconvertd_workqueue : xfsdatad_workqueue;
+		queue_work(wq, &ioend->io_work);
+		if (wait)
+			flush_workqueue(wq);
+	}
 }
 
 /*
@@ -243,9 +270,23 @@
 {
 	xfs_ioend_t		*ioend =
 		container_of(work, xfs_ioend_t, io_work);
+	int			error;
 
-	xfs_setfilesize(ioend);
-	xfs_destroy_ioend(ioend);
+	/*
+	 * If we didn't complete processing of the ioend, requeue it to the
+	 * tail of the workqueue for another attempt later. Otherwise destroy
+	 * it.
+	 */
+	error = xfs_setfilesize(ioend);
+	if (error == EAGAIN) {
+		atomic_inc(&ioend->io_remaining);
+		xfs_finish_ioend(ioend, 0);
+		/* ensure we don't spin on blocked ioends */
+		delay(1);
+	} else {
+		ASSERT(!error);
+		xfs_destroy_ioend(ioend);
+	}
 }
 
 /*
@@ -257,9 +298,23 @@
 {
 	xfs_ioend_t		*ioend =
 		container_of(work, xfs_ioend_t, io_work);
+	int			error;
 
-	xfs_setfilesize(ioend);
-	xfs_destroy_ioend(ioend);
+	/*
+	 * If we didn't complete processing of the ioend, requeue it to the
+	 * tail of the workqueue for another attempt later. Otherwise destroy
+	 * it.
+	 */
+	error = xfs_setfilesize(ioend);
+	if (error == EAGAIN) {
+		atomic_inc(&ioend->io_remaining);
+		xfs_finish_ioend(ioend, 0);
+		/* ensure we don't spin on blocked ioends */
+		delay(1);
+	} else {
+		ASSERT(!error);
+		xfs_destroy_ioend(ioend);
+	}
 }
 
 /*
@@ -279,13 +334,25 @@
 	size_t			size = ioend->io_size;
 
 	if (likely(!ioend->io_error)) {
+		int	error;
 		if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-			int error;
 			error = xfs_iomap_write_unwritten(ip, offset, size);
 			if (error)
 				ioend->io_error = error;
 		}
-		xfs_setfilesize(ioend);
+		/*
+		 * If we didn't complete processing of the ioend, requeue it to the
+		 * tail of the workqueue for another attempt later. Otherwise destroy
+		 * it.
+		 */
+		error = xfs_setfilesize(ioend);
+		if (error == EAGAIN) {
+			atomic_inc(&ioend->io_remaining);
+			xfs_finish_ioend(ioend, 0);
+			/* ensure we don't spin on blocked ioends */
+			delay(1);
+			return;
+		}
 	}
 	xfs_destroy_ioend(ioend);
 }
@@ -304,27 +371,6 @@
 }
 
 /*
- * Schedule IO completion handling on a xfsdatad if this was
- * the final hold on this ioend. If we are asked to wait,
- * flush the workqueue.
- */
-STATIC void
-xfs_finish_ioend(
-	xfs_ioend_t	*ioend,
-	int		wait)
-{
-	if (atomic_dec_and_test(&ioend->io_remaining)) {
-		struct workqueue_struct *wq = xfsdatad_workqueue;
-		if (ioend->io_work.func == xfs_end_bio_unwritten)
-			wq = xfsconvertd_workqueue;
-
-		queue_work(wq, &ioend->io_work);
-		if (wait)
-			flush_workqueue(wq);
-	}
-}
-
-/*
  * Allocate and initialise an IO completion structure.
  * We need to track unwritten extent write completion here initially.
  * We'll need to extend this for updating the ondisk inode size later
@@ -904,16 +950,9 @@
 
 	if (startio) {
 		if (count) {
-			struct backing_dev_info *bdi;
-
-			bdi = inode->i_mapping->backing_dev_info;
 			wbc->nr_to_write--;
-			if (bdi_write_congested(bdi)) {
-				wbc->encountered_congestion = 1;
-				done = 1;
-			} else if (wbc->nr_to_write <= 0) {
+			if (wbc->nr_to_write <= 0)
 				done = 1;
-			}
 		}
 		xfs_start_page_writeback(page, !page_dirty, count);
 	}
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_iops.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_iops.c
@@ -573,8 +573,8 @@
 	bf.l_len = len;
 
 	xfs_ilock(ip, XFS_IOLOCK_EXCL);
-	error = xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
-				      0, XFS_ATTR_NOLOCK);
+	error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
+				       0, XFS_ATTR_NOLOCK);
 	if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
 	    offset + len > i_size_read(inode))
 		new_size = offset + len;
@@ -585,7 +585,7 @@
 
 		iattr.ia_valid = ATTR_SIZE;
 		iattr.ia_size = new_size;
-		error = xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
+		error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
 	}
 
 	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_buf.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_buf.c
@@ -194,7 +194,7 @@
 {
 	a_list_t	*aentry;
 
-#ifdef CONFIG_XEN
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
 	/*
 	 * Xen needs to be able to make sure it can get an exclusive
 	 * RO mapping of pages it wants to turn into a pagetable.  If
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_ioctl.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -673,10 +673,9 @@
 		error = xfs_bulkstat_single(mp, &inlast,
 						bulkreq.ubuffer, &done);
 	else	/* XFS_IOC_FSBULKSTAT */
-		error = xfs_bulkstat(mp, &inlast, &count,
-			(bulkstat_one_pf)xfs_bulkstat_one, NULL,
-			sizeof(xfs_bstat_t), bulkreq.ubuffer,
-			BULKSTAT_FG_QUICK, &done);
+		error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
+				     sizeof(xfs_bstat_t), bulkreq.ubuffer,
+				     &done);
 
 	if (error)
 		return -error;
@@ -698,14 +697,19 @@
 	xfs_mount_t		*mp,
 	void			__user *arg)
 {
-	xfs_fsop_geom_v1_t	fsgeo;
+	xfs_fsop_geom_t         fsgeo;
 	int			error;
 
-	error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
+	error = xfs_fs_geometry(mp, &fsgeo, 3);
 	if (error)
 		return -error;
 
-	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
+	/*
+	 * Caller should have passed an argument of type
+	 * xfs_fsop_geom_v1_t.  This is a proper subset of the
+	 * xfs_fsop_geom_t that xfs_fs_geometry() fills in.
+	 */
+	if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -789,6 +793,8 @@
 {
 	struct fsxattr		fa;
 
+	memset(&fa, 0, sizeof(struct fsxattr));
+
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 	fa.fsx_xflags = xfs_ip2xflags(ip);
 	fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_sync.c
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_sync.c
@@ -64,7 +64,6 @@
 	 * as the tree is sparse and a gang lookup walks to find
 	 * the number of objects requested.
 	 */
-	read_lock(&pag->pag_ici_lock);
 	if (tag == XFS_ICI_NO_TAG) {
 		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
 				(void **)&ip, *first_index, 1);
@@ -73,7 +72,7 @@
 				(void **)&ip, *first_index, 1, tag);
 	}
 	if (!nr_found)
-		goto unlock;
+		return NULL;
 
 	/*
 	 * Update the index for the next lookup. Catch overflows
@@ -83,13 +82,8 @@
 	 */
 	*first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
 	if (*first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
-		goto unlock;
-
+		return NULL;
 	return ip;
-
-unlock:
-	read_unlock(&pag->pag_ici_lock);
-	return NULL;
 }
 
 STATIC int
@@ -99,7 +93,9 @@
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
 	int			flags,
-	int			tag)
+	int			tag,
+	int			exclusive,
+	int			*nr_to_scan)
 {
 	struct xfs_perag	*pag = &mp->m_perag[ag];
 	uint32_t		first_index;
@@ -113,10 +109,20 @@
 		int		error = 0;
 		xfs_inode_t	*ip;
 
+		if (exclusive)
+			write_lock(&pag->pag_ici_lock);
+		else
+			read_lock(&pag->pag_ici_lock);
 		ip = xfs_inode_ag_lookup(mp, pag, &first_index, tag);
-		if (!ip)
+		if (!ip) {
+			if (exclusive)
+				write_unlock(&pag->pag_ici_lock);
+			else
+				read_unlock(&pag->pag_ici_lock);
 			break;
+		}
 
+		/* execute releases pag->pag_ici_lock */
 		error = execute(ip, pag, flags);
 		if (error == EAGAIN) {
 			skipped++;
@@ -124,13 +130,12 @@
 		}
 		if (error)
 			last_error = error;
-		/*
-		 * bail out if the filesystem is corrupted.
-		 */
+
+		/* bail out if the filesystem is corrupted.  */
 		if (error == EFSCORRUPTED)
 			break;
 
-	} while (1);
+	} while ((*nr_to_scan)--);
 
 	if (skipped) {
 		delay(1);
@@ -147,22 +152,31 @@
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
 	int			flags,
-	int			tag)
+	int			tag,
+	int			exclusive,
+	int			*nr_to_scan)
 {
 	int			error = 0;
 	int			last_error = 0;
 	xfs_agnumber_t		ag;
+	int			nr;
 
+	nr = nr_to_scan ? *nr_to_scan : INT_MAX;
 	for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
 		if (!mp->m_perag[ag].pag_ici_init)
 			continue;
-		error = xfs_inode_ag_walk(mp, ag, execute, flags, tag);
+		error = xfs_inode_ag_walk(mp, ag, execute, flags, tag,
+						exclusive, &nr);
 		if (error) {
 			last_error = error;
 			if (error == EFSCORRUPTED)
 				break;
 		}
+		if (nr <= 0)
+			break;
 	}
+	if (nr_to_scan)
+		*nr_to_scan = nr;
 	return XFS_ERROR(last_error);
 }
 
@@ -173,30 +187,31 @@
 	struct xfs_perag	*pag)
 {
 	struct inode		*inode = VFS_I(ip);
+	int			error = EFSCORRUPTED;
 
 	/* nothing to sync during shutdown */
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-		read_unlock(&pag->pag_ici_lock);
-		return EFSCORRUPTED;
-	}
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		goto out_unlock;
 
-	/*
-	 * If we can't get a reference on the inode, it must be in reclaim.
-	 * Leave it for the reclaim code to flush. Also avoid inodes that
-	 * haven't been fully initialised.
-	 */
-	if (!igrab(inode)) {
-		read_unlock(&pag->pag_ici_lock);
-		return ENOENT;
-	}
-	read_unlock(&pag->pag_ici_lock);
+	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
+	error = ENOENT;
+	if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
+		goto out_unlock;
+
+	/* If we can't grab the inode, it must on it's way to reclaim. */
+	if (!igrab(inode))
+		goto out_unlock;
 
-	if (is_bad_inode(inode) || xfs_iflags_test(ip, XFS_INEW)) {
+	if (is_bad_inode(inode)) {
 		IRELE(ip);
-		return ENOENT;
+		goto out_unlock;
 	}
 
-	return 0;
+	/* inode is valid */
+	error = 0;
+out_unlock:
+	read_unlock(&pag->pag_ici_lock);
+	return error;
 }
 
 STATIC int
@@ -281,7 +296,7 @@
 	ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);
 
 	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags,
-				      XFS_ICI_NO_TAG);
+				      XFS_ICI_NO_TAG, 0, NULL);
 	if (error)
 		return XFS_ERROR(error);
 
@@ -303,7 +318,7 @@
 	ASSERT((flags & ~SYNC_WAIT) == 0);
 
 	return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags,
-				     XFS_ICI_NO_TAG);
+				     XFS_ICI_NO_TAG, 0, NULL);
 }
 
 STATIC int
@@ -663,67 +678,6 @@
 	kthread_stop(mp->m_sync_task);
 }
 
-int
-xfs_reclaim_inode(
-	xfs_inode_t	*ip,
-	int		locked,
-	int		sync_mode)
-{
-	xfs_perag_t	*pag = xfs_get_perag(ip->i_mount, ip->i_ino);
-
-	/* The hash lock here protects a thread in xfs_iget_core from
-	 * racing with us on linking the inode back with a vnode.
-	 * Once we have the XFS_IRECLAIM flag set it will not touch
-	 * us.
-	 */
-	write_lock(&pag->pag_ici_lock);
-	spin_lock(&ip->i_flags_lock);
-	if (__xfs_iflags_test(ip, XFS_IRECLAIM) ||
-	    !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
-		spin_unlock(&ip->i_flags_lock);
-		write_unlock(&pag->pag_ici_lock);
-		if (locked) {
-			xfs_ifunlock(ip);
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		}
-		return -EAGAIN;
-	}
-	__xfs_iflags_set(ip, XFS_IRECLAIM);
-	spin_unlock(&ip->i_flags_lock);
-	write_unlock(&pag->pag_ici_lock);
-	xfs_put_perag(ip->i_mount, pag);
-
-	/*
-	 * If the inode is still dirty, then flush it out.  If the inode
-	 * is not in the AIL, then it will be OK to flush it delwri as
-	 * long as xfs_iflush() does not keep any references to the inode.
-	 * We leave that decision up to xfs_iflush() since it has the
-	 * knowledge of whether it's OK to simply do a delwri flush of
-	 * the inode or whether we need to wait until the inode is
-	 * pulled from the AIL.
-	 * We get the flush lock regardless, though, just to make sure
-	 * we don't free it while it is being flushed.
-	 */
-	if (!locked) {
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		xfs_iflock(ip);
-	}
-
-	/*
-	 * In the case of a forced shutdown we rely on xfs_iflush() to
-	 * wait for the inode to be unpinned before returning an error.
-	 */
-	if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) {
-		/* synchronize with xfs_iflush_done */
-		xfs_iflock(ip);
-		xfs_ifunlock(ip);
-	}
-
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	xfs_ireclaim(ip);
-	return 0;
-}
-
 void
 __xfs_inode_set_reclaim_tag(
 	struct xfs_perag	*pag,
@@ -732,6 +686,7 @@
 	radix_tree_tag_set(&pag->pag_ici_root,
 			   XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
 			   XFS_ICI_RECLAIM_TAG);
+	pag->pag_ici_reclaimable++;
 }
 
 /*
@@ -746,12 +701,12 @@
 	xfs_mount_t	*mp = ip->i_mount;
 	xfs_perag_t	*pag = xfs_get_perag(mp, ip->i_ino);
 
-	read_lock(&pag->pag_ici_lock);
+	write_lock(&pag->pag_ici_lock);
 	spin_lock(&ip->i_flags_lock);
 	__xfs_inode_set_reclaim_tag(pag, ip);
 	__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
 	spin_unlock(&ip->i_flags_lock);
-	read_unlock(&pag->pag_ici_lock);
+	write_unlock(&pag->pag_ici_lock);
 	xfs_put_perag(mp, pag);
 }
 
@@ -763,22 +718,59 @@
 {
 	radix_tree_tag_clear(&pag->pag_ici_root,
 			XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+	pag->pag_ici_reclaimable--;
 }
 
 STATIC int
-xfs_reclaim_inode_now(
+xfs_reclaim_inode(
 	struct xfs_inode	*ip,
 	struct xfs_perag	*pag,
-	int			flags)
+	int			sync_mode)
 {
-	/* ignore if already under reclaim */
-	if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
-		read_unlock(&pag->pag_ici_lock);
+	/*
+	 * The radix tree lock here protects a thread in xfs_iget from racing
+	 * with us starting reclaim on the inode.  Once we have the
+	 * XFS_IRECLAIM flag set it will not touch us.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+	if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
+		/* ignore as it is already under reclaim */
+		spin_unlock(&ip->i_flags_lock);
+		write_unlock(&pag->pag_ici_lock);
 		return 0;
 	}
-	read_unlock(&pag->pag_ici_lock);
+	__xfs_iflags_set(ip, XFS_IRECLAIM);
+	spin_unlock(&ip->i_flags_lock);
+	write_unlock(&pag->pag_ici_lock);
+
+	/*
+	 * If the inode is still dirty, then flush it out.  If the inode
+	 * is not in the AIL, then it will be OK to flush it delwri as
+	 * long as xfs_iflush() does not keep any references to the inode.
+	 * We leave that decision up to xfs_iflush() since it has the
+	 * knowledge of whether it's OK to simply do a delwri flush of
+	 * the inode or whether we need to wait until the inode is
+	 * pulled from the AIL.
+	 * We get the flush lock regardless, though, just to make sure
+	 * we don't free it while it is being flushed.
+	 */
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	xfs_iflock(ip);
 
-	return xfs_reclaim_inode(ip, 0, flags);
+	/*
+	 * In the case of a forced shutdown we rely on xfs_iflush() to
+	 * wait for the inode to be unpinned before returning an error.
+	 */
+	if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) {
+		/* synchronize with xfs_iflush_done */
+		xfs_iflock(ip);
+		xfs_ifunlock(ip);
+	}
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	xfs_ireclaim(ip);
+	return 0;
 }
 
 int
@@ -786,6 +778,89 @@
 	xfs_mount_t	*mp,
 	int		mode)
 {
-	return xfs_inode_ag_iterator(mp, xfs_reclaim_inode_now, mode,
-					XFS_ICI_RECLAIM_TAG);
+	return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode,
+					XFS_ICI_RECLAIM_TAG, 1, NULL);
+}
+
+/*
+ * Shrinker infrastructure.
+ *
+ * This is all far more complex than it needs to be. It adds a global list of
+ * mounts because the shrinkers can only call a global context. We need to make
+ * the shrinkers pass a context to avoid the need for global state.
+ */
+static LIST_HEAD(xfs_mount_list);
+static struct rw_semaphore xfs_mount_list_lock;
+
+static int
+xfs_reclaim_inode_shrink(
+	int		nr_to_scan,
+	gfp_t		gfp_mask)
+{
+	struct xfs_mount *mp;
+	xfs_agnumber_t	ag;
+	int		reclaimable = 0;
+
+	if (nr_to_scan) {
+		if (!(gfp_mask & __GFP_FS))
+			return -1;
+
+		down_read(&xfs_mount_list_lock);
+		list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
+			xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
+					XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
+			if (nr_to_scan <= 0)
+				break;
+		}
+		up_read(&xfs_mount_list_lock);
+	}
+
+	down_read(&xfs_mount_list_lock);
+	list_for_each_entry(mp, &xfs_mount_list, m_mplist) {
+		for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) {
+
+			if (!mp->m_perag[ag].pag_ici_init)
+				continue;
+			reclaimable += mp->m_perag[ag].pag_ici_reclaimable;
+		}
+	}
+	up_read(&xfs_mount_list_lock);
+	return reclaimable;
+}
+
+static struct shrinker xfs_inode_shrinker = {
+	.shrink = xfs_reclaim_inode_shrink,
+	.seeks = DEFAULT_SEEKS,
+};
+
+void __init
+xfs_inode_shrinker_init(void)
+{
+	init_rwsem(&xfs_mount_list_lock);
+	register_shrinker(&xfs_inode_shrinker);
+}
+
+void
+xfs_inode_shrinker_destroy(void)
+{
+	ASSERT(list_empty(&xfs_mount_list));
+	unregister_shrinker(&xfs_inode_shrinker);
+}
+
+void
+xfs_inode_shrinker_register(
+	struct xfs_mount	*mp)
+{
+	down_write(&xfs_mount_list_lock);
+	list_add_tail(&mp->m_mplist, &xfs_mount_list);
+	up_write(&xfs_mount_list_lock);
+}
+
+void
+xfs_inode_shrinker_unregister(
+	struct xfs_mount	*mp)
+{
+	down_write(&xfs_mount_list_lock);
+	list_del(&mp->m_mplist);
+	up_write(&xfs_mount_list_lock);
 }
--- linux-ec2-2.6.32.orig/fs/xfs/linux-2.6/xfs_sync.h
+++ linux-ec2-2.6.32/fs/xfs/linux-2.6/xfs_sync.h
@@ -44,7 +44,6 @@
 
 void xfs_flush_inodes(struct xfs_inode *ip);
 
-int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
@@ -55,6 +54,11 @@
 int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag);
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
-	int flags, int tag);
+	int flags, int tag, int write_lock, int *nr_to_scan);
+
+void xfs_inode_shrinker_init(void);
+void xfs_inode_shrinker_destroy(void);
+void xfs_inode_shrinker_register(struct xfs_mount *mp);
+void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
 
 #endif
--- linux-ec2-2.6.32.orig/fs/partitions/efi.c
+++ linux-ec2-2.6.32/fs/partitions/efi.c
@@ -1,7 +1,9 @@
 /************************************************************
  * EFI GUID Partition Table handling
- * Per Intel EFI Specification v1.02
- * http://developer.intel.com/technology/efi/efi.htm
+ *
+ * http://www.uefi.org/specs/
+ * http://www.intel.com/technology/efi/
+ *
  * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
  *   Copyright 2000,2001,2002,2004 Dell Inc.
  *
@@ -92,6 +94,7 @@
  *
  ************************************************************/
 #include <linux/crc32.h>
+#include <linux/math64.h>
 #include "check.h"
 #include "efi.h"
 
@@ -141,7 +144,8 @@
 {
 	if (!bdev || !bdev->bd_inode)
 		return 0;
-	return (bdev->bd_inode->i_size >> 9) - 1ULL;
+	return div_u64(bdev->bd_inode->i_size,
+		       bdev_logical_block_size(bdev)) - 1ULL;
 }
 
 static inline int
@@ -188,6 +192,7 @@
 read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count)
 {
 	size_t totalreadcount = 0;
+	sector_t n = lba * (bdev_logical_block_size(bdev) / 512);
 
 	if (!bdev || !buffer || lba > last_lba(bdev))
                 return 0;
@@ -195,7 +200,7 @@
 	while (count) {
 		int copied = 512;
 		Sector sect;
-		unsigned char *data = read_dev_sector(bdev, lba++, &sect);
+		unsigned char *data = read_dev_sector(bdev, n++, &sect);
 		if (!data)
 			break;
 		if (copied > count)
@@ -257,15 +262,16 @@
 alloc_read_gpt_header(struct block_device *bdev, u64 lba)
 {
 	gpt_header *gpt;
+	unsigned ssz = bdev_logical_block_size(bdev);
+
 	if (!bdev)
 		return NULL;
 
-	gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL);
+	gpt = kzalloc(ssz, GFP_KERNEL);
 	if (!gpt)
 		return NULL;
 
-	if (read_lba(bdev, lba, (u8 *) gpt,
-		     sizeof (gpt_header)) < sizeof (gpt_header)) {
+	if (read_lba(bdev, lba, (u8 *) gpt, ssz) < ssz) {
 		kfree(gpt);
                 gpt=NULL;
 		return NULL;
@@ -343,6 +349,12 @@
 		goto fail;
 	}
 
+	/* Check that sizeof_partition_entry has the correct value */
+	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
+		pr_debug("GUID Partitition Entry Size check failed.\n");
+		goto fail;
+	}
+
 	if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt)))
 		goto fail;
 
@@ -601,6 +613,7 @@
 	gpt_header *gpt = NULL;
 	gpt_entry *ptes = NULL;
 	u32 i;
+	unsigned ssz = bdev_logical_block_size(bdev) / 512;
 
 	if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) {
 		kfree(gpt);
@@ -611,13 +624,14 @@
 	pr_debug("GUID Partition Table is valid!  Yea!\n");
 
 	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
+		u64 start = le64_to_cpu(ptes[i].starting_lba);
+		u64 size = le64_to_cpu(ptes[i].ending_lba) -
+			   le64_to_cpu(ptes[i].starting_lba) + 1ULL;
+
 		if (!is_pte_valid(&ptes[i], last_lba(bdev)))
 			continue;
 
-		put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba),
-				 (le64_to_cpu(ptes[i].ending_lba) -
-                                  le64_to_cpu(ptes[i].starting_lba) +
-				  1ULL));
+		put_partition(state, i+1, start * ssz, size * ssz);
 
 		/* If this is a RAID volume, tell md */
 		if (!efi_guidcmp(ptes[i].partition_type_guid,
--- linux-ec2-2.6.32.orig/fs/partitions/mac.c
+++ linux-ec2-2.6.32/fs/partitions/mac.c
@@ -29,10 +29,9 @@
 
 int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int slot = 1;
 	Sector sect;
 	unsigned char *data;
-	int blk, blocks_in_map;
+	int slot, blocks_in_map;
 	unsigned secsize;
 #ifdef CONFIG_PPC_PMAC
 	int found_root = 0;
@@ -59,10 +58,14 @@
 		put_dev_sector(sect);
 		return 0;		/* not a MacOS disk */
 	}
-	printk(" [mac]");
 	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map; ++blk) {
-		int pos = blk * secsize;
+	if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) {
+		put_dev_sector(sect);
+		return 0;
+	}
+	printk(" [mac]");
+	for (slot = 1; slot <= blocks_in_map; ++slot) {
+		int pos = slot * secsize;
 		put_dev_sector(sect);
 		data = read_dev_sector(bdev, pos/512, &sect);
 		if (!data)
@@ -113,13 +116,11 @@
 			}
 
 			if (goodness > found_root_goodness) {
-				found_root = blk;
+				found_root = slot;
 				found_root_goodness = goodness;
 			}
 		}
 #endif /* CONFIG_PPC_PMAC */
-
-		++slot;
 	}
 #ifdef CONFIG_PPC_PMAC
 	if (found_root_goodness)
--- linux-ec2-2.6.32.orig/fs/partitions/msdos.c
+++ linux-ec2-2.6.32/fs/partitions/msdos.c
@@ -31,14 +31,17 @@
  */
 #include <asm/unaligned.h>
 
-#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
-#define NR_SECTS(p)	({ __le32 __a =	get_unaligned(&p->nr_sects);	\
-				le32_to_cpu(__a); \
-			})
-
-#define START_SECT(p)	({ __le32 __a =	get_unaligned(&p->start_sect);	\
-				le32_to_cpu(__a); \
-			})
+#define SYS_IND(p)	get_unaligned(&p->sys_ind)
+
+static inline sector_t nr_sects(struct partition *p)
+{
+	return (sector_t)get_unaligned_le32(&p->nr_sects);
+}
+
+static inline sector_t start_sect(struct partition *p)
+{
+	return (sector_t)get_unaligned_le32(&p->start_sect);
+}
 
 static inline int is_extended_partition(struct partition *p)
 {
@@ -104,13 +107,13 @@
 
 static void
 parse_extended(struct parsed_partitions *state, struct block_device *bdev,
-			u32 first_sector, u32 first_size)
+			sector_t first_sector, sector_t first_size)
 {
 	struct partition *p;
 	Sector sect;
 	unsigned char *data;
-	u32 this_sector, this_size;
-	int sector_size = bdev_logical_block_size(bdev) / 512;
+	sector_t this_sector, this_size;
+	sector_t sector_size = bdev_logical_block_size(bdev) / 512;
 	int loopct = 0;		/* number of links followed
 				   without finding a data partition */
 	int i;
@@ -145,14 +148,14 @@
 		 * First process the data partition(s)
 		 */
 		for (i=0; i<4; i++, p++) {
-			u32 offs, size, next;
-			if (!NR_SECTS(p) || is_extended_partition(p))
+			sector_t offs, size, next;
+			if (!nr_sects(p) || is_extended_partition(p))
 				continue;
 
 			/* Check the 3rd and 4th entries -
 			   these sometimes contain random garbage */
-			offs = START_SECT(p)*sector_size;
-			size = NR_SECTS(p)*sector_size;
+			offs = start_sect(p)*sector_size;
+			size = nr_sects(p)*sector_size;
 			next = this_sector + offs;
 			if (i >= 2) {
 				if (offs + size > this_size)
@@ -179,13 +182,13 @@
 		 */
 		p -= 4;
 		for (i=0; i<4; i++, p++)
-			if (NR_SECTS(p) && is_extended_partition(p))
+			if (nr_sects(p) && is_extended_partition(p))
 				break;
 		if (i == 4)
 			goto done;	 /* nothing left to do */
 
-		this_sector = first_sector + START_SECT(p) * sector_size;
-		this_size = NR_SECTS(p) * sector_size;
+		this_sector = first_sector + start_sect(p) * sector_size;
+		this_size = nr_sects(p) * sector_size;
 		put_dev_sector(sect);
 	}
 done:
@@ -197,7 +200,7 @@
 
 static void
 parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
-			u32 offset, u32 size, int origin)
+			sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_SOLARIS_X86_PARTITION
 	Sector sect;
@@ -244,7 +247,7 @@
  */
 static void
 parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin, char *flavour,
+		sector_t offset, sector_t size, int origin, char *flavour,
 		int max_partitions)
 {
 	Sector sect;
@@ -263,7 +266,7 @@
 	if (le16_to_cpu(l->d_npartitions) < max_partitions)
 		max_partitions = le16_to_cpu(l->d_npartitions);
 	for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
-		u32 bsd_start, bsd_size;
+		sector_t bsd_start, bsd_size;
 
 		if (state->next == state->limit)
 			break;
@@ -290,7 +293,7 @@
 
 static void
 parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin)
+		sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
 	parse_bsd(state, bdev, offset, size, origin,
@@ -300,7 +303,7 @@
 
 static void
 parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin)
+		sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
 	parse_bsd(state, bdev, offset, size, origin,
@@ -310,7 +313,7 @@
 
 static void
 parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin)
+		sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_BSD_DISKLABEL
 	parse_bsd(state, bdev, offset, size, origin,
@@ -324,7 +327,7 @@
  */
 static void
 parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin)
+		sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_UNIXWARE_DISKLABEL
 	Sector sect;
@@ -348,7 +351,8 @@
 
 		if (p->s_label != UNIXWARE_FS_UNUSED)
 			put_partition(state, state->next++,
-						START_SECT(p), NR_SECTS(p));
+				      le32_to_cpu(p->start_sect),
+				      le32_to_cpu(p->nr_sects));
 		p++;
 	}
 	put_dev_sector(sect);
@@ -363,7 +367,7 @@
  */
 static void
 parse_minix(struct parsed_partitions *state, struct block_device *bdev,
-		u32 offset, u32 size, int origin)
+		sector_t offset, sector_t size, int origin)
 {
 #ifdef CONFIG_MINIX_SUBPARTITION
 	Sector sect;
@@ -390,7 +394,7 @@
 			/* add each partition in use */
 			if (SYS_IND(p) == MINIX_PARTITION)
 				put_partition(state, state->next++,
-					      START_SECT(p), NR_SECTS(p));
+					      start_sect(p), nr_sects(p));
 		}
 		printk(" >\n");
 	}
@@ -401,7 +405,7 @@
 static struct {
 	unsigned char id;
 	void (*parse)(struct parsed_partitions *, struct block_device *,
-			u32, u32, int);
+			sector_t, sector_t, int);
 } subtypes[] = {
 	{FREEBSD_PARTITION, parse_freebsd},
 	{NETBSD_PARTITION, parse_netbsd},
@@ -415,7 +419,7 @@
  
 int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int sector_size = bdev_logical_block_size(bdev) / 512;
+	sector_t sector_size = bdev_logical_block_size(bdev) / 512;
 	Sector sect;
 	unsigned char *data;
 	struct partition *p;
@@ -483,14 +487,21 @@
 
 	state->next = 5;
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {
-		u32 start = START_SECT(p)*sector_size;
-		u32 size = NR_SECTS(p)*sector_size;
+		sector_t start = start_sect(p)*sector_size;
+		sector_t size = nr_sects(p)*sector_size;
 		if (!size)
 			continue;
 		if (is_extended_partition(p)) {
-			/* prevent someone doing mkfs or mkswap on an
-			   extended partition, but leave room for LILO */
-			put_partition(state, slot, start, size == 1 ? 1 : 2);
+			/*
+			 * prevent someone doing mkfs or mkswap on an
+			 * extended partition, but leave room for LILO
+			 * FIXME: this uses one logical sector for > 512b
+			 * sector, although it may not be enough/proper.
+			 */
+			sector_t n = 2;
+			n = min(size, max(sector_size, n));
+			put_partition(state, slot, start, n);
+
 			printk(" <");
 			parse_extended(state, bdev, start, size);
 			printk(" >");
@@ -513,7 +524,7 @@
 		unsigned char id = SYS_IND(p);
 		int n;
 
-		if (!NR_SECTS(p))
+		if (!nr_sects(p))
 			continue;
 
 		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
@@ -521,8 +532,8 @@
 
 		if (!subtypes[n].parse)
 			continue;
-		subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
-						NR_SECTS(p)*sector_size, slot);
+		subtypes[n].parse(state, bdev, start_sect(p)*sector_size,
+						nr_sects(p)*sector_size, slot);
 	}
 	put_dev_sector(sect);
 	return 1;
--- linux-ec2-2.6.32.orig/fs/partitions/osf.c
+++ linux-ec2-2.6.32/fs/partitions/osf.c
@@ -10,10 +10,13 @@
 #include "check.h"
 #include "osf.h"
 
+#define MAX_OSF_PARTITIONS 18
+
 int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
 	int i;
 	int slot = 1;
+	unsigned int npartitions;
 	Sector sect;
 	unsigned char *data;
 	struct disklabel {
@@ -45,7 +48,7 @@
 			u8  p_fstype;
 			u8  p_frag;
 			__le16 p_cpg;
-		} d_partitions[8];
+		} d_partitions[MAX_OSF_PARTITIONS];
 	} * label;
 	struct d_partition * partition;
 
@@ -63,7 +66,12 @@
 		put_dev_sector(sect);
 		return 0;
 	}
-	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
+	npartitions = le16_to_cpu(label->d_npartitions);
+	if (npartitions > MAX_OSF_PARTITIONS) {
+		put_dev_sector(sect);
+		return 0;
+	}
+	for (i = 0 ; i < npartitions; i++, partition++) {
 		if (slot == state->limit)
 		        break;
 		if (le32_to_cpu(partition->p_size))
--- linux-ec2-2.6.32.orig/fs/partitions/efi.h
+++ linux-ec2-2.6.32/fs/partitions/efi.h
@@ -37,7 +37,6 @@
 #define EFI_PMBR_OSTYPE_EFI 0xEF
 #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
 
-#define GPT_BLOCK_SIZE 512
 #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
 #define GPT_HEADER_REVISION_V1 0x00010000
 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1
@@ -79,7 +78,12 @@
 	__le32 num_partition_entries;
 	__le32 sizeof_partition_entry;
 	__le32 partition_entry_array_crc32;
-	u8 reserved2[GPT_BLOCK_SIZE - 92];
+
+	/* The rest of the logical block is reserved by UEFI and must be zero.
+	 * EFI standard handles this by:
+	 *
+	 * uint8_t		reserved2[ BlockSize - 92 ];
+	 */
 } __attribute__ ((packed)) gpt_header;
 
 typedef struct _gpt_entry_attributes {
--- linux-ec2-2.6.32.orig/fs/partitions/ibm.c
+++ linux-ec2-2.6.32/fs/partitions/ibm.c
@@ -74,6 +74,7 @@
 	} *label;
 	unsigned char *data;
 	Sector sect;
+	sector_t labelsect;
 
 	res = 0;
 	blocksize = bdev_logical_block_size(bdev);
@@ -98,9 +99,19 @@
 		goto out_freeall;
 
 	/*
+	 * Special case for FBA disks: label sector does not depend on
+	 * blocksize.
+	 */
+	if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) ||
+	    (info->cu_type == 0x3880 && info->dev_type == 0x3370))
+		labelsect = info->label_block;
+	else
+		labelsect = info->label_block * (blocksize >> 9);
+
+	/*
 	 * Get volume label, extract name and type.
 	 */
-	data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect);
+	data = read_dev_sector(bdev, labelsect, &sect);
 	if (data == NULL)
 		goto out_readerr;
 
--- linux-ec2-2.6.32.orig/fs/partitions/ldm.c
+++ linux-ec2-2.6.32/fs/partitions/ldm.c
@@ -251,6 +251,11 @@
 	}
 
 	vm->vblk_size     = get_unaligned_be32(data + 0x08);
+	if (vm->vblk_size == 0) {
+		ldm_error ("Illegal VBLK size");
+		return false;
+	}
+
 	vm->vblk_offset   = get_unaligned_be32(data + 0x0C);
 	vm->last_vblk_seq = get_unaligned_be32(data + 0x04);
 
@@ -1294,6 +1299,11 @@
 
 	BUG_ON (!data || !frags);
 
+	if (size < 2 * VBLK_SIZE_HEAD) {
+		ldm_error("Value of size is to small.");
+		return false;
+	}
+
 	group = get_unaligned_be32(data + 0x08);
 	rec   = get_unaligned_be16(data + 0x0C);
 	num   = get_unaligned_be16(data + 0x0E);
@@ -1301,6 +1311,10 @@
 		ldm_error ("A VBLK claims to have %d parts.", num);
 		return false;
 	}
+	if (rec >= num) {
+		ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num);
+		return false;
+	}
 
 	list_for_each (item, frags) {
 		f = list_entry (item, struct frag, list);
@@ -1329,10 +1343,9 @@
 
 	f->map |= (1 << rec);
 
-	if (num > 0) {
-		data += VBLK_SIZE_HEAD;
-		size -= VBLK_SIZE_HEAD;
-	}
+	data += VBLK_SIZE_HEAD;
+	size -= VBLK_SIZE_HEAD;
+
 	memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
 
 	return true;
--- linux-ec2-2.6.32.orig/fs/cachefiles/security.c
+++ linux-ec2-2.6.32/fs/cachefiles/security.c
@@ -77,6 +77,8 @@
 /*
  * check the security details of the on-disk cache
  * - must be called with security override in force
+ * - must return with a security override in force - even in the case of an
+ *   error
  */
 int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
 					struct dentry *root,
@@ -99,6 +101,8 @@
 	 * which create files */
 	ret = set_create_files_as(new, root->d_inode);
 	if (ret < 0) {
+		abort_creds(new);
+		cachefiles_begin_secure(cache, _saved_cred);
 		_leave(" = %d [cfa]", ret);
 		return ret;
 	}
--- linux-ec2-2.6.32.orig/fs/ramfs/file-nommu.c
+++ linux-ec2-2.6.32/fs/ramfs/file-nommu.c
@@ -111,6 +111,7 @@
 		SetPageDirty(page);
 
 		unlock_page(page);
+		put_page(page);
 	}
 
 	return 0;
--- linux-ec2-2.6.32.orig/fs/ext3/super.c
+++ linux-ec2-2.6.32/fs/ext3/super.c
@@ -37,6 +37,7 @@
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
 #include <linux/log2.h>
+#include <linux/precache.h>
 
 #include <asm/uaccess.h>
 
@@ -1307,6 +1308,7 @@
 	} else {
 		printk("internal journal\n");
 	}
+	precache_init(sb);
 	return res;
 }
 
@@ -1404,6 +1406,13 @@
 		return;
 	}
 
+	/* Check if feature set allows readwrite operations */
+	if (EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) {
+		printk(KERN_INFO "EXT3-fs: %s: Skipping orphan cleanup due to "
+			 "unknown ROCOMPAT features\n", sb->s_id);
+		return;
+	}
+
 	if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
 		if (es->s_last_orphan)
 			jbd_debug(1, "Errors on filesystem, "
@@ -2686,13 +2695,11 @@
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
 	buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
-	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
 	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
-	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT3_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
--- linux-ec2-2.6.32.orig/fs/ext3/xattr.c
+++ linux-ec2-2.6.32/fs/ext3/xattr.c
@@ -960,6 +960,10 @@
 	if (error)
 		goto cleanup;
 
+	error = ext3_journal_get_write_access(handle, is.iloc.bh);
+	if (error)
+		goto cleanup;
+
 	if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
 		struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc);
 		memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
@@ -985,9 +989,6 @@
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 	}
-	error = ext3_journal_get_write_access(handle, is.iloc.bh);
-	if (error)
-		goto cleanup;
 	if (!value) {
 		if (!is.s.not_found)
 			error = ext3_xattr_ibody_set(handle, inode, &i, &is);
--- linux-ec2-2.6.32.orig/fs/ext3/namei.c
+++ linux-ec2-2.6.32/fs/ext3/namei.c
@@ -1550,8 +1550,8 @@
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
 		entries2 = node2->entries;
+		memset(&node2->fake, 0, sizeof(struct fake_dirent));
 		node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
-		node2->fake.inode = 0;
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext3_journal_get_write_access(handle, frame->bh);
 		if (err)
--- linux-ec2-2.6.32.orig/fs/ext3/inode.c
+++ linux-ec2-2.6.32/fs/ext3/inode.c
@@ -1151,6 +1151,16 @@
 	return ext3_journal_get_write_access(handle, bh);
 }
 
+/*
+ * Truncate blocks that were not used by write. We have to truncate the
+ * pagecache as well so that corresponding buffers get properly unmapped.
+ */
+static void ext3_truncate_failed_write(struct inode *inode)
+{
+	truncate_inode_pages(inode->i_mapping, inode->i_size);
+	ext3_truncate(inode);
+}
+
 static int ext3_write_begin(struct file *file, struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
 				struct page **pagep, void **fsdata)
@@ -1209,7 +1219,7 @@
 		unlock_page(page);
 		page_cache_release(page);
 		if (pos + len > inode->i_size)
-			ext3_truncate(inode);
+			ext3_truncate_failed_write(inode);
 	}
 	if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
 		goto retry;
@@ -1304,7 +1314,7 @@
 	page_cache_release(page);
 
 	if (pos + len > inode->i_size)
-		ext3_truncate(inode);
+		ext3_truncate_failed_write(inode);
 	return ret ? ret : copied;
 }
 
@@ -1330,7 +1340,7 @@
 	page_cache_release(page);
 
 	if (pos + len > inode->i_size)
-		ext3_truncate(inode);
+		ext3_truncate_failed_write(inode);
 	return ret ? ret : copied;
 }
 
@@ -1383,7 +1393,7 @@
 	page_cache_release(page);
 
 	if (pos + len > inode->i_size)
-		ext3_truncate(inode);
+		ext3_truncate_failed_write(inode);
 	return ret ? ret : copied;
 }
 
--- linux-ec2-2.6.32.orig/fs/btrfs/ordered-data.c
+++ linux-ec2-2.6.32/fs/btrfs/ordered-data.c
@@ -291,16 +291,16 @@
 
 /*
  * remove an ordered extent from the tree.  No references are dropped
- * but, anyone waiting on this extent is woken up.
+ * and you must wake_up entry->wait.  You must hold the tree mutex
+ * while you call this function.
  */
-int btrfs_remove_ordered_extent(struct inode *inode,
+static int __btrfs_remove_ordered_extent(struct inode *inode,
 				struct btrfs_ordered_extent *entry)
 {
 	struct btrfs_ordered_inode_tree *tree;
 	struct rb_node *node;
 
 	tree = &BTRFS_I(inode)->ordered_tree;
-	mutex_lock(&tree->mutex);
 	node = &entry->rb_node;
 	rb_erase(node, &tree->tree);
 	tree->last = NULL;
@@ -326,16 +326,34 @@
 	}
 	spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
 
+	return 0;
+}
+
+/*
+ * remove an ordered extent from the tree.  No references are dropped
+ * but any waiters are woken.
+ */
+int btrfs_remove_ordered_extent(struct inode *inode,
+				struct btrfs_ordered_extent *entry)
+{
+	struct btrfs_ordered_inode_tree *tree;
+	int ret;
+
+	tree = &BTRFS_I(inode)->ordered_tree;
+	mutex_lock(&tree->mutex);
+	ret = __btrfs_remove_ordered_extent(inode, entry);
 	mutex_unlock(&tree->mutex);
 	wake_up(&entry->wait);
-	return 0;
+
+	return ret;
 }
 
 /*
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+			       int nocow_only, int delay_iput)
 {
 	struct list_head splice;
 	struct list_head *cur;
@@ -372,7 +390,10 @@
 		if (inode) {
 			btrfs_start_ordered_extent(inode, ordered, 1);
 			btrfs_put_ordered_extent(ordered);
-			iput(inode);
+			if (delay_iput)
+				btrfs_add_delayed_iput(inode);
+			else
+				iput(inode);
 		} else {
 			btrfs_put_ordered_extent(ordered);
 		}
@@ -430,7 +451,7 @@
 				btrfs_wait_ordered_range(inode, 0, (u64)-1);
 			else
 				filemap_flush(inode->i_mapping);
-			iput(inode);
+			btrfs_add_delayed_iput(inode);
 		}
 
 		cond_resched();
@@ -589,7 +610,7 @@
  * After an extent is done, call this to conditionally update the on disk
  * i_size.  i_size is updated to cover any fully written part of the file.
  */
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 				struct btrfs_ordered_extent *ordered)
 {
 	struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
@@ -597,18 +618,32 @@
 	u64 disk_i_size;
 	u64 new_i_size;
 	u64 i_size_test;
+	u64 i_size = i_size_read(inode);
 	struct rb_node *node;
+	struct rb_node *prev = NULL;
 	struct btrfs_ordered_extent *test;
+	int ret = 1;
+
+	if (ordered)
+		offset = entry_end(ordered);
+	else
+		offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize);
 
 	mutex_lock(&tree->mutex);
 	disk_i_size = BTRFS_I(inode)->disk_i_size;
 
+	/* truncate file */
+	if (disk_i_size > i_size) {
+		BTRFS_I(inode)->disk_i_size = i_size;
+		ret = 0;
+		goto out;
+	}
+
 	/*
 	 * if the disk i_size is already at the inode->i_size, or
 	 * this ordered extent is inside the disk i_size, we're done
 	 */
-	if (disk_i_size >= inode->i_size ||
-	    ordered->file_offset + ordered->len <= disk_i_size) {
+	if (disk_i_size == i_size || offset <= disk_i_size) {
 		goto out;
 	}
 
@@ -616,8 +651,7 @@
 	 * we can't update the disk_isize if there are delalloc bytes
 	 * between disk_i_size and  this ordered extent
 	 */
-	if (test_range_bit(io_tree, disk_i_size,
-			   ordered->file_offset + ordered->len - 1,
+	if (test_range_bit(io_tree, disk_i_size, offset - 1,
 			   EXTENT_DELALLOC, 0, NULL)) {
 		goto out;
 	}
@@ -626,20 +660,32 @@
 	 * if we find an ordered extent then we can't update disk i_size
 	 * yet
 	 */
-	node = &ordered->rb_node;
-	while (1) {
-		node = rb_prev(node);
-		if (!node)
-			break;
+	if (ordered) {
+		node = rb_prev(&ordered->rb_node);
+	} else {
+		prev = tree_search(tree, offset);
+		/*
+		 * we insert file extents without involving ordered struct,
+		 * so there should be no ordered struct cover this offset
+		 */
+		if (prev) {
+			test = rb_entry(prev, struct btrfs_ordered_extent,
+					rb_node);
+			BUG_ON(offset_in_entry(test, offset));
+		}
+		node = prev;
+	}
+	while (node) {
 		test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
 		if (test->file_offset + test->len <= disk_i_size)
 			break;
-		if (test->file_offset >= inode->i_size)
+		if (test->file_offset >= i_size)
 			break;
 		if (test->file_offset >= disk_i_size)
 			goto out;
+		node = rb_prev(node);
 	}
-	new_i_size = min_t(u64, entry_end(ordered), i_size_read(inode));
+	new_i_size = min_t(u64, offset, i_size);
 
 	/*
 	 * at this point, we know we can safely update i_size to at least
@@ -647,7 +693,14 @@
 	 * walk forward and see if ios from higher up in the file have
 	 * finished.
 	 */
-	node = rb_next(&ordered->rb_node);
+	if (ordered) {
+		node = rb_next(&ordered->rb_node);
+	} else {
+		if (prev)
+			node = rb_next(prev);
+		else
+			node = rb_first(&tree->tree);
+	}
 	i_size_test = 0;
 	if (node) {
 		/*
@@ -655,10 +708,10 @@
 		 * between our ordered extent and the next one.
 		 */
 		test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-		if (test->file_offset > entry_end(ordered))
+		if (test->file_offset > offset)
 			i_size_test = test->file_offset;
 	} else {
-		i_size_test = i_size_read(inode);
+		i_size_test = i_size;
 	}
 
 	/*
@@ -667,15 +720,25 @@
 	 * are no delalloc bytes in this area, it is safe to update
 	 * disk_i_size to the end of the region.
 	 */
-	if (i_size_test > entry_end(ordered) &&
-	    !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1,
-			   EXTENT_DELALLOC, 0, NULL)) {
-		new_i_size = min_t(u64, i_size_test, i_size_read(inode));
+	if (i_size_test > offset &&
+	    !test_range_bit(io_tree, offset, i_size_test - 1,
+			    EXTENT_DELALLOC, 0, NULL)) {
+		new_i_size = min_t(u64, i_size_test, i_size);
 	}
 	BTRFS_I(inode)->disk_i_size = new_i_size;
+	ret = 0;
 out:
+	/*
+	 * we need to remove the ordered extent with the tree lock held
+	 * so that other people calling this function don't find our fully
+	 * processed ordered entry and skip updating the i_size
+	 */
+	if (ordered)
+		__btrfs_remove_ordered_extent(inode, ordered);
 	mutex_unlock(&tree->mutex);
-	return 0;
+	if (ordered)
+		wake_up(&ordered->wait);
+	return ret;
 }
 
 /*
--- linux-ec2-2.6.32.orig/fs/btrfs/super.c
+++ linux-ec2-2.6.32/fs/btrfs/super.c
@@ -126,8 +126,9 @@
 {
 	struct btrfs_fs_info *info = root->fs_info;
 	substring_t args[MAX_OPT_ARGS];
-	char *p, *num;
+	char *p, *num, *orig;
 	int intarg;
+	int ret = 0;
 
 	if (!options)
 		return 0;
@@ -140,6 +141,7 @@
 	if (!options)
 		return -ENOMEM;
 
+	orig = options;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -262,12 +264,18 @@
 		case Opt_discard:
 			btrfs_set_opt(info->mount_opt, DISCARD);
 			break;
+		case Opt_err:
+			printk(KERN_INFO "btrfs: unrecognized mount option "
+			       "'%s'\n", p);
+			ret = -EINVAL;
+			goto out;
 		default:
 			break;
 		}
 	}
-	kfree(options);
-	return 0;
+out:
+	kfree(orig);
+	return ret;
 }
 
 /*
@@ -405,8 +413,8 @@
 		return 0;
 	}
 
-	btrfs_start_delalloc_inodes(root);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_start_delalloc_inodes(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	trans = btrfs_start_transaction(root, 1);
 	ret = btrfs_commit_transaction(trans, root);
@@ -450,6 +458,8 @@
 		seq_puts(seq, ",notreelog");
 	if (btrfs_test_opt(root, FLUSHONCOMMIT))
 		seq_puts(seq, ",flushoncommit");
+	if (btrfs_test_opt(root, DISCARD))
+		seq_puts(seq, ",discard");
 	if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
 		seq_puts(seq, ",noacl");
 	return 0;
--- linux-ec2-2.6.32.orig/fs/btrfs/transaction.c
+++ linux-ec2-2.6.32/fs/btrfs/transaction.c
@@ -333,6 +333,9 @@
 	memset(trans, 0, sizeof(*trans));
 	kmem_cache_free(btrfs_trans_handle_cachep, trans);
 
+	if (throttle)
+		btrfs_run_delayed_iputs(root);
+
 	return 0;
 }
 
@@ -354,7 +357,7 @@
  * those extents are sent to disk but does not wait on them
  */
 int btrfs_write_marked_extents(struct btrfs_root *root,
-			       struct extent_io_tree *dirty_pages)
+			       struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int err = 0;
@@ -367,7 +370,7 @@
 
 	while (1) {
 		ret = find_first_extent_bit(dirty_pages, start, &start, &end,
-					    EXTENT_DIRTY);
+					    mark);
 		if (ret)
 			break;
 		while (start <= end) {
@@ -413,7 +416,7 @@
  * on all the pages and clear them from the dirty pages state tree
  */
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-			      struct extent_io_tree *dirty_pages)
+			      struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int err = 0;
@@ -425,12 +428,12 @@
 	unsigned long index;
 
 	while (1) {
-		ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
-					    EXTENT_DIRTY);
+		ret = find_first_extent_bit(dirty_pages, start, &start, &end,
+					    mark);
 		if (ret)
 			break;
 
-		clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
+		clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS);
 		while (start <= end) {
 			index = start >> PAGE_CACHE_SHIFT;
 			start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
@@ -460,13 +463,13 @@
  * those extents are on disk for transaction or log commit
  */
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages)
+				struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int ret2;
 
-	ret = btrfs_write_marked_extents(root, dirty_pages);
-	ret2 = btrfs_wait_marked_extents(root, dirty_pages);
+	ret = btrfs_write_marked_extents(root, dirty_pages, mark);
+	ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark);
 	return ret || ret2;
 }
 
@@ -479,7 +482,8 @@
 		return filemap_write_and_wait(btree_inode->i_mapping);
 	}
 	return btrfs_write_and_wait_marked_extents(root,
-					   &trans->transaction->dirty_pages);
+					   &trans->transaction->dirty_pages,
+					   EXTENT_DIRTY);
 }
 
 /*
@@ -497,13 +501,16 @@
 {
 	int ret;
 	u64 old_root_bytenr;
+	u64 old_root_used;
 	struct btrfs_root *tree_root = root->fs_info->tree_root;
 
+	old_root_used = btrfs_root_used(&root->root_item);
 	btrfs_write_dirty_block_groups(trans, root);
 
 	while (1) {
 		old_root_bytenr = btrfs_root_bytenr(&root->root_item);
-		if (old_root_bytenr == root->node->start)
+		if (old_root_bytenr == root->node->start &&
+		    old_root_used == btrfs_root_used(&root->root_item))
 			break;
 
 		btrfs_set_root_node(&root->root_item, root->node);
@@ -512,6 +519,7 @@
 					&root->root_item);
 		BUG_ON(ret);
 
+		old_root_used = btrfs_root_used(&root->root_item);
 		ret = btrfs_write_dirty_block_groups(trans, root);
 		BUG_ON(ret);
 	}
@@ -769,6 +777,7 @@
 	record_root_in_trans(trans, root);
 	btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
 	memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
+	btrfs_check_and_init_root_item(new_root_item);
 
 	key.objectid = objectid;
 	/* record when the snapshot was created in key.offset */
@@ -795,7 +804,6 @@
 	memcpy(&pending->root_key, &key, sizeof(key));
 fail:
 	kfree(new_root_item);
-	btrfs_unreserve_metadata_space(root, 6);
 	return ret;
 }
 
@@ -807,7 +815,6 @@
 	u64 index = 0;
 	struct btrfs_trans_handle *trans;
 	struct inode *parent_inode;
-	struct inode *inode;
 	struct btrfs_root *parent_root;
 
 	parent_inode = pending->dentry->d_parent->d_inode;
@@ -839,8 +846,6 @@
 
 	BUG_ON(ret);
 
-	inode = btrfs_lookup_dentry(parent_inode, pending->dentry);
-	d_instantiate(pending->dentry, inode);
 fail:
 	btrfs_end_transaction(trans, fs_info->fs_root);
 	return ret;
@@ -994,11 +999,11 @@
 		mutex_unlock(&root->fs_info->trans_mutex);
 
 		if (flush_on_commit) {
-			btrfs_start_delalloc_inodes(root);
-			ret = btrfs_wait_ordered_extents(root, 0);
+			btrfs_start_delalloc_inodes(root, 1);
+			ret = btrfs_wait_ordered_extents(root, 0, 1);
 			BUG_ON(ret);
 		} else if (snap_pending) {
-			ret = btrfs_wait_ordered_extents(root, 1);
+			ret = btrfs_wait_ordered_extents(root, 0, 1);
 			BUG_ON(ret);
 		}
 
@@ -1116,6 +1121,10 @@
 		current->journal_info = NULL;
 
 	kmem_cache_free(btrfs_trans_handle_cachep, trans);
+
+	if (current != root->fs_info->transaction_kthread)
+		btrfs_run_delayed_iputs(root);
+
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/fs/btrfs/xattr.c
+++ linux-ec2-2.6.32/fs/btrfs/xattr.c
@@ -85,22 +85,23 @@
 	return ret;
 }
 
-int __btrfs_setxattr(struct inode *inode, const char *name,
-			    const void *value, size_t size, int flags)
+static int do_setxattr(struct btrfs_trans_handle *trans,
+		       struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
 {
 	struct btrfs_dir_item *di;
 	struct btrfs_root *root = BTRFS_I(inode)->root;
-	struct btrfs_trans_handle *trans;
 	struct btrfs_path *path;
-	int ret = 0, mod = 0;
+	size_t name_len = strlen(name);
+	int ret = 0;
+
+	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
+		return -ENOSPC;
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
 
-	trans = btrfs_join_transaction(root, 1);
-	btrfs_set_trans_block_group(trans, inode);
-
 	/* first lets see if we already have this xattr */
 	di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
 				strlen(name), -1);
@@ -118,15 +119,12 @@
 		}
 
 		ret = btrfs_delete_one_dir_name(trans, root, path, di);
-		if (ret)
-			goto out;
+		BUG_ON(ret);
 		btrfs_release_path(root, path);
 
 		/* if we don't have a value then we are removing the xattr */
-		if (!value) {
-			mod = 1;
+		if (!value)
 			goto out;
-		}
 	} else {
 		btrfs_release_path(root, path);
 
@@ -138,20 +136,45 @@
 	}
 
 	/* ok we have to create a completely new xattr */
-	ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
-				      value, size, inode->i_ino);
+	ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
+				      name, name_len, value, size);
+	BUG_ON(ret);
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
+int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+		     struct inode *inode, const char *name,
+		     const void *value, size_t size, int flags)
+{
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	int ret;
+
+	if (trans)
+		return do_setxattr(trans, inode, name, value, size, flags);
+
+	ret = btrfs_reserve_metadata_space(root, 2);
 	if (ret)
-		goto out;
-	mod = 1;
+		return ret;
 
-out:
-	if (mod) {
-		inode->i_ctime = CURRENT_TIME;
-		ret = btrfs_update_inode(trans, root, inode);
+	trans = btrfs_start_transaction(root, 1);
+	if (!trans) {
+		ret = -ENOMEM;
+		goto out;
 	}
+	btrfs_set_trans_block_group(trans, inode);
 
-	btrfs_end_transaction(trans, root);
-	btrfs_free_path(path);
+	ret = do_setxattr(trans, inode, name, value, size, flags);
+	if (ret)
+		goto out;
+
+	inode->i_ctime = CURRENT_TIME;
+	ret = btrfs_update_inode(trans, root, inode);
+	BUG_ON(ret);
+out:
+	btrfs_end_transaction_throttle(trans, root);
+	btrfs_unreserve_metadata_space(root, 2);
 	return ret;
 }
 
@@ -314,7 +337,9 @@
 
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
-	return __btrfs_setxattr(dentry->d_inode, name, value, size, flags);
+
+	return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+				flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
@@ -329,10 +354,13 @@
 
 	if (!btrfs_is_valid_xattr(name))
 		return -EOPNOTSUPP;
-	return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+
+	return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+				XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+			      struct inode *inode, struct inode *dir)
 {
 	int err;
 	size_t len;
@@ -354,7 +382,7 @@
 	} else {
 		strcpy(name, XATTR_SECURITY_PREFIX);
 		strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-		err = __btrfs_setxattr(inode, name, value, len, 0);
+		err = __btrfs_setxattr(trans, inode, name, value, len, 0);
 		kfree(name);
 	}
 
--- linux-ec2-2.6.32.orig/fs/btrfs/acl.c
+++ linux-ec2-2.6.32/fs/btrfs/acl.c
@@ -94,7 +94,8 @@
 /*
  * Needs to be called with fs_mutex held
  */
-static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+static int btrfs_set_acl(struct btrfs_trans_handle *trans,
+			 struct inode *inode, struct posix_acl *acl, int type)
 {
 	int ret, size = 0;
 	const char *name;
@@ -111,12 +112,14 @@
 	switch (type) {
 	case ACL_TYPE_ACCESS:
 		mode = inode->i_mode;
-		ret = posix_acl_equiv_mode(acl, &mode);
-		if (ret < 0)
-			return ret;
-		ret = 0;
-		inode->i_mode = mode;
 		name = POSIX_ACL_XATTR_ACCESS;
+		if (acl) {
+			ret = posix_acl_equiv_mode(acl, &mode);
+			if (ret < 0)
+				return ret;
+			inode->i_mode = mode;
+		}
+		ret = 0;
 		break;
 	case ACL_TYPE_DEFAULT:
 		if (!S_ISDIR(inode->i_mode))
@@ -140,8 +143,7 @@
 			goto out;
 	}
 
-	ret = __btrfs_setxattr(inode, name, value, size, 0);
-
+	ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
 out:
 	kfree(value);
 
@@ -154,9 +156,12 @@
 static int btrfs_xattr_set_acl(struct inode *inode, int type,
 			       const void *value, size_t size)
 {
-	int ret = 0;
+	int ret;
 	struct posix_acl *acl = NULL;
 
+	if (!is_owner_or_cap(inode))
+		return -EPERM;
+
 	if (value) {
 		acl = posix_acl_from_xattr(value, size);
 		if (acl == NULL) {
@@ -167,7 +172,7 @@
 		}
 	}
 
-	ret = btrfs_set_acl(inode, acl, type);
+	ret = btrfs_set_acl(NULL, inode, acl, type);
 
 	posix_acl_release(acl);
 
@@ -221,7 +226,8 @@
  * stuff has been fixed to work with that.  If the locking stuff changes, we
  * need to re-evaluate the acl locking stuff.
  */
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir)
 {
 	struct posix_acl *acl = NULL;
 	int ret = 0;
@@ -246,7 +252,8 @@
 		mode_t mode;
 
 		if (S_ISDIR(inode->i_mode)) {
-			ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
+			ret = btrfs_set_acl(trans, inode, acl,
+					    ACL_TYPE_DEFAULT);
 			if (ret)
 				goto failed;
 		}
@@ -261,10 +268,11 @@
 			inode->i_mode = mode;
 			if (ret > 0) {
 				/* we need an acl */
-				ret = btrfs_set_acl(inode, clone,
+				ret = btrfs_set_acl(trans, inode, clone,
 						    ACL_TYPE_ACCESS);
 			}
 		}
+		posix_acl_release(clone);
 	}
 failed:
 	posix_acl_release(acl);
@@ -294,7 +302,7 @@
 
 	ret = posix_acl_chmod_masq(clone, inode->i_mode);
 	if (!ret)
-		ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);
+		ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
 
 	posix_acl_release(clone);
 
@@ -320,7 +328,8 @@
 	return 0;
 }
 
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir)
 {
 	return 0;
 }
--- linux-ec2-2.6.32.orig/fs/btrfs/extent_io.c
+++ linux-ec2-2.6.32/fs/btrfs/extent_io.c
@@ -2574,7 +2574,6 @@
 		.sync_io = wbc->sync_mode == WB_SYNC_ALL,
 	};
 	struct writeback_control wbc_writepages = {
-		.bdi		= wbc->bdi,
 		.sync_mode	= wbc->sync_mode,
 		.older_than_this = NULL,
 		.nr_to_write	= 64,
@@ -2608,7 +2607,6 @@
 		.sync_io = mode == WB_SYNC_ALL,
 	};
 	struct writeback_control wbc_writepages = {
-		.bdi		= inode->i_mapping->backing_dev_info,
 		.sync_mode	= mode,
 		.older_than_this = NULL,
 		.nr_to_write	= nr_pages * 2,
@@ -3165,10 +3163,9 @@
 		spin_unlock(&tree->buffer_lock);
 		goto free_eb;
 	}
-	spin_unlock(&tree->buffer_lock);
-
 	/* add one reference for the tree */
 	atomic_inc(&eb->refs);
+	spin_unlock(&tree->buffer_lock);
 	return eb;
 
 free_eb:
--- linux-ec2-2.6.32.orig/fs/btrfs/tree-log.c
+++ linux-ec2-2.6.32/fs/btrfs/tree-log.c
@@ -542,8 +542,8 @@
 
 	saved_nbytes = inode_get_bytes(inode);
 	/* drop any overlapping extents */
-	ret = btrfs_drop_extents(trans, root, inode,
-			 start, extent_end, extent_end, start, &alloc_hint, 1);
+	ret = btrfs_drop_extents(trans, inode, start, extent_end,
+				 &alloc_hint, 1);
 	BUG_ON(ret);
 
 	if (found_type == BTRFS_FILE_EXTENT_REG ||
@@ -930,6 +930,17 @@
 	return 0;
 }
 
+static int insert_orphan_item(struct btrfs_trans_handle *trans,
+			      struct btrfs_root *root, u64 offset)
+{
+	int ret;
+	ret = btrfs_find_orphan_item(root, offset);
+	if (ret > 0)
+		ret = btrfs_insert_orphan_item(trans, root, offset);
+	return ret;
+}
+
+
 /*
  * There are a few corners where the link count of the file can't
  * be properly maintained during replay.  So, instead of adding
@@ -997,9 +1008,13 @@
 	}
 	BTRFS_I(inode)->index_cnt = (u64)-1;
 
-	if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) {
-		ret = replay_dir_deletes(trans, root, NULL, path,
-					 inode->i_ino, 1);
+	if (inode->i_nlink == 0) {
+		if (S_ISDIR(inode->i_mode)) {
+			ret = replay_dir_deletes(trans, root, NULL, path,
+						 inode->i_ino, 1);
+			BUG_ON(ret);
+		}
+		ret = insert_orphan_item(trans, root, inode->i_ino);
 		BUG_ON(ret);
 	}
 	btrfs_free_path(path);
@@ -1587,7 +1602,6 @@
 		/* inode keys are done during the first stage */
 		if (key.type == BTRFS_INODE_ITEM_KEY &&
 		    wc->stage == LOG_WALK_REPLAY_INODES) {
-			struct inode *inode;
 			struct btrfs_inode_item *inode_item;
 			u32 mode;
 
@@ -1603,31 +1617,16 @@
 					     eb, i, &key);
 			BUG_ON(ret);
 
-			/* for regular files, truncate away
-			 * extents past the new EOF
+			/* for regular files, make sure corresponding
+			 * orhpan item exist. extents past the new EOF
+			 * will be truncated later by orphan cleanup.
 			 */
 			if (S_ISREG(mode)) {
-				inode = read_one_inode(root,
-						       key.objectid);
-				BUG_ON(!inode);
-
-				ret = btrfs_truncate_inode_items(wc->trans,
-					root, inode, inode->i_size,
-					BTRFS_EXTENT_DATA_KEY);
+				ret = insert_orphan_item(wc->trans, root,
+							 key.objectid);
 				BUG_ON(ret);
-
-				/* if the nlink count is zero here, the iput
-				 * will free the inode.  We bump it to make
-				 * sure it doesn't get freed until the link
-				 * count fixup is done
-				 */
-				if (inode->i_nlink == 0) {
-					btrfs_inc_nlink(inode);
-					btrfs_update_inode(wc->trans,
-							   root, inode);
-				}
-				iput(inode);
 			}
+
 			ret = link_to_fixup_dir(wc->trans, root,
 						path, key.objectid);
 			BUG_ON(ret);
@@ -1977,10 +1976,11 @@
 {
 	int index1;
 	int index2;
+	int mark;
 	int ret;
 	struct btrfs_root *log = root->log_root;
 	struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
-	u64 log_transid = 0;
+	unsigned long log_transid = 0;
 
 	mutex_lock(&root->log_mutex);
 	index1 = root->log_transid % 2;
@@ -2014,24 +2014,29 @@
 		goto out;
 	}
 
+	log_transid = root->log_transid;
+	if (log_transid % 2 == 0)
+		mark = EXTENT_DIRTY;
+	else
+		mark = EXTENT_NEW;
+
 	/* we start IO on  all the marked extents here, but we don't actually
 	 * wait for them until later.
 	 */
-	ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
+	ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);
 	BUG_ON(ret);
 
 	btrfs_set_root_node(&log->root_item, log->node);
 
 	root->log_batch = 0;
-	log_transid = root->log_transid;
 	root->log_transid++;
 	log->log_transid = root->log_transid;
 	root->log_start_pid = 0;
 	smp_mb();
 	/*
-	 * log tree has been flushed to disk, new modifications of
-	 * the log will be written to new positions. so it's safe to
-	 * allow log writers to go in.
+	 * IO has been started, blocks of the log tree have WRITTEN flag set
+	 * in their headers. new modifications of the log will be written to
+	 * new positions. so it's safe to allow log writers to go in.
 	 */
 	mutex_unlock(&root->log_mutex);
 
@@ -2052,7 +2057,7 @@
 
 	index2 = log_root_tree->log_transid % 2;
 	if (atomic_read(&log_root_tree->log_commit[index2])) {
-		btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 		wait_log_commit(trans, log_root_tree,
 				log_root_tree->log_transid);
 		mutex_unlock(&log_root_tree->log_mutex);
@@ -2072,16 +2077,17 @@
 	 * check the full commit flag again
 	 */
 	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
-		btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 		mutex_unlock(&log_root_tree->log_mutex);
 		ret = -EAGAIN;
 		goto out_wake_log_root;
 	}
 
 	ret = btrfs_write_and_wait_marked_extents(log_root_tree,
-				&log_root_tree->dirty_log_pages);
+				&log_root_tree->dirty_log_pages,
+				EXTENT_DIRTY | EXTENT_NEW);
 	BUG_ON(ret);
-	btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+	btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 
 	btrfs_set_super_log_root(&root->fs_info->super_for_commit,
 				log_root_tree->node->start);
@@ -2147,12 +2153,12 @@
 
 	while (1) {
 		ret = find_first_extent_bit(&log->dirty_log_pages,
-				    0, &start, &end, EXTENT_DIRTY);
+				0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
 		if (ret)
 			break;
 
-		clear_extent_dirty(&log->dirty_log_pages,
-				   start, end, GFP_NOFS);
+		clear_extent_bits(&log->dirty_log_pages, start, end,
+				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
 	}
 
 	if (log->log_transid > 0) {
--- linux-ec2-2.6.32.orig/fs/btrfs/xattr.h
+++ linux-ec2-2.6.32/fs/btrfs/xattr.h
@@ -27,15 +27,16 @@
 
 extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
 		void *buffer, size_t size);
-extern int __btrfs_setxattr(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags);
-
+extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+			    struct inode *inode, const char *name,
+			    const void *value, size_t size, int flags);
 extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
 		void *buffer, size_t size);
 extern int btrfs_setxattr(struct dentry *dentry, const char *name,
 		const void *value, size_t size, int flags);
 extern int btrfs_removexattr(struct dentry *dentry, const char *name);
 
-extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir);
+extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+				     struct inode *inode, struct inode *dir);
 
 #endif /* __XATTR__ */
--- linux-ec2-2.6.32.orig/fs/btrfs/ctree.h
+++ linux-ec2-2.6.32/fs/btrfs/ctree.h
@@ -310,6 +310,9 @@
 #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
 					sizeof(struct btrfs_item) - \
 					sizeof(struct btrfs_file_extent_item))
+#define BTRFS_MAX_XATTR_SIZE(r)	(BTRFS_LEAF_DATA_SIZE(r) - \
+				 sizeof(struct btrfs_item) -\
+				 sizeof(struct btrfs_dir_item))
 
 
 /*
@@ -859,8 +862,9 @@
 	struct mutex ordered_operations_mutex;
 	struct rw_semaphore extent_commit_sem;
 
-	struct rw_semaphore subvol_sem;
+	struct rw_semaphore cleanup_work_sem;
 
+	struct rw_semaphore subvol_sem;
 	struct srcu_struct subvol_srcu;
 
 	struct list_head trans_list;
@@ -868,6 +872,9 @@
 	struct list_head dead_roots;
 	struct list_head caching_block_groups;
 
+	spinlock_t delayed_iput_lock;
+	struct list_head delayed_iputs;
+
 	atomic_t nr_async_submits;
 	atomic_t async_submit_draining;
 	atomic_t nr_async_bios;
@@ -1034,12 +1041,12 @@
 	int ref_cows;
 	int track_dirty;
 	int in_radix;
+	int clean_orphans;
 
 	u64 defrag_trans_start;
 	struct btrfs_key defrag_progress;
 	struct btrfs_key defrag_max;
 	int defrag_running;
-	int defrag_level;
 	char *name;
 	int in_sysfs;
 
@@ -1175,6 +1182,8 @@
 #define BTRFS_INODE_DIRSYNC		(1 << 10)
 
 
+#define BTRFS_INODE_ROOT_ITEM_INIT	(1 << 31)
+
 /* some macros to generate set/get funcs for the struct fields.  This
  * assumes there is a lefoo_to_cpu for every type, so lets make a simple
  * one for u8:
@@ -1975,6 +1984,10 @@
 					u64 parent, u64 root_objectid,
 					struct btrfs_disk_key *key, int level,
 					u64 hint, u64 empty_size);
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u32 blocksize,
+			  u64 parent, u64 root_objectid, int level);
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 					    struct btrfs_root *root,
 					    u64 bytenr, u32 blocksize,
@@ -2089,6 +2102,10 @@
 		     struct btrfs_path *path,
 		     struct btrfs_key *new_key,
 		     unsigned long split_offset);
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 struct btrfs_key *new_key);
 int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, struct btrfs_path *p, int
 		      ins_len, int cow);
@@ -2168,6 +2185,8 @@
 int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
 int btrfs_set_root_node(struct btrfs_root_item *item,
 			struct extent_buffer *node);
+void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
+
 /* dir-item.c */
 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root, const char *name,
@@ -2196,9 +2215,10 @@
 			      struct btrfs_path *path,
 			      struct btrfs_dir_item *di);
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-			    struct btrfs_root *root, const char *name,
-			    u16 name_len, const void *data, u16 data_len,
-			    u64 dir);
+			    struct btrfs_root *root,
+			    struct btrfs_path *path, u64 objectid,
+			    const char *name, u16 name_len,
+			    const void *data, u16 data_len);
 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
 					  struct btrfs_root *root,
 					  struct btrfs_path *path, u64 dir,
@@ -2292,7 +2312,7 @@
 			       struct inode *inode, u64 new_size,
 			       u32 min_type);
 
-int btrfs_start_delalloc_inodes(struct btrfs_root *root);
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
 int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
 int btrfs_writepages(struct address_space *mapping,
 		     struct writeback_control *wbc);
@@ -2332,6 +2352,8 @@
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
 int btrfs_invalidate_inodes(struct btrfs_root *root);
+void btrfs_add_delayed_iput(struct inode *inode);
+void btrfs_run_delayed_iputs(struct btrfs_root *root);
 extern const struct dentry_operations btrfs_dentry_operations;
 
 /* ioctl.c */
@@ -2345,12 +2367,9 @@
 			    int skip_pinned);
 int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 extern const struct file_operations btrfs_file_operations;
-int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 locked_end,
-		       u64 inline_limit, u64 *hint_block, int drop_cache);
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+		       u64 start, u64 end, u64 *hint_byte, int drop_cache);
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-			      struct btrfs_root *root,
 			      struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
 
@@ -2380,7 +2399,8 @@
 #else
 #define btrfs_check_acl NULL
 #endif
-int btrfs_init_acl(struct inode *inode, struct inode *dir);
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir);
 int btrfs_acl_chmod(struct inode *inode);
 
 /* relocation.c */
--- linux-ec2-2.6.32.orig/fs/btrfs/btrfs_inode.h
+++ linux-ec2-2.6.32/fs/btrfs/btrfs_inode.h
@@ -44,9 +44,6 @@
 	 */
 	struct extent_io_tree io_failure_tree;
 
-	/* held while inesrting or deleting extents from files */
-	struct mutex extent_mutex;
-
 	/* held while logging the inode in tree-log.c */
 	struct mutex log_mutex;
 
@@ -166,7 +163,7 @@
 
 static inline void btrfs_i_size_write(struct inode *inode, u64 size)
 {
-	inode->i_size = size;
+	i_size_write(inode, size);
 	BTRFS_I(inode)->disk_i_size = size;
 }
 
--- linux-ec2-2.6.32.orig/fs/btrfs/relocation.c
+++ linux-ec2-2.6.32/fs/btrfs/relocation.c
@@ -1561,6 +1561,20 @@
 	return 0;
 }
 
+static void put_inodes(struct list_head *list)
+{
+	struct inodevec *ivec;
+	while (!list_empty(list)) {
+		ivec = list_entry(list->next, struct inodevec, list);
+		list_del(&ivec->list);
+		while (ivec->nr > 0) {
+			ivec->nr--;
+			iput(ivec->inode[ivec->nr]);
+		}
+		kfree(ivec);
+	}
+}
+
 static int find_next_key(struct btrfs_path *path, int level,
 			 struct btrfs_key *key)
 
@@ -1723,6 +1737,11 @@
 
 		btrfs_btree_balance_dirty(root, nr);
 
+		/*
+		 * put inodes outside transaction, otherwise we may deadlock.
+		 */
+		put_inodes(&inode_list);
+
 		if (replaced && rc->stage == UPDATE_DATA_PTRS)
 			invalidate_extent_cache(root, &key, &next_key);
 	}
@@ -1752,19 +1771,7 @@
 
 	btrfs_btree_balance_dirty(root, nr);
 
-	/*
-	 * put inodes while we aren't holding the tree locks
-	 */
-	while (!list_empty(&inode_list)) {
-		struct inodevec *ivec;
-		ivec = list_entry(inode_list.next, struct inodevec, list);
-		list_del(&ivec->list);
-		while (ivec->nr > 0) {
-			ivec->nr--;
-			iput(ivec->inode[ivec->nr]);
-		}
-		kfree(ivec);
-	}
+	put_inodes(&inode_list);
 
 	if (replaced && rc->stage == UPDATE_DATA_PTRS)
 		invalidate_extent_cache(root, &key, &next_key);
@@ -3274,8 +3281,10 @@
 		return -ENOMEM;
 
 	path = btrfs_alloc_path();
-	if (!path)
+	if (!path) {
+		kfree(cluster);
 		return -ENOMEM;
+	}
 
 	rc->extents_found = 0;
 	rc->extents_skipped = 0;
@@ -3534,8 +3543,8 @@
 	       (unsigned long long)rc->block_group->key.objectid,
 	       (unsigned long long)rc->block_group->flags);
 
-	btrfs_start_delalloc_inodes(fs_info->tree_root);
-	btrfs_wait_ordered_extents(fs_info->tree_root, 0);
+	btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
+	btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0);
 
 	while (1) {
 		rc->extents_found = 0;
@@ -3755,6 +3764,8 @@
 				       BTRFS_DATA_RELOC_TREE_OBJECTID);
 		if (IS_ERR(fs_root))
 			err = PTR_ERR(fs_root);
+		else
+			btrfs_orphan_cleanup(fs_root);
 	}
 	return err;
 }
--- linux-ec2-2.6.32.orig/fs/btrfs/inode.c
+++ linux-ec2-2.6.32/fs/btrfs/inode.c
@@ -88,13 +88,14 @@
 				   u64 start, u64 end, int *page_started,
 				   unsigned long *nr_written, int unlock);
 
-static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
+static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
+				     struct inode *inode,  struct inode *dir)
 {
 	int err;
 
-	err = btrfs_init_acl(inode, dir);
+	err = btrfs_init_acl(trans, inode, dir);
 	if (!err)
-		err = btrfs_xattr_security_init(inode, dir);
+		err = btrfs_xattr_security_init(trans, inode, dir);
 	return err;
 }
 
@@ -188,8 +189,18 @@
 	btrfs_mark_buffer_dirty(leaf);
 	btrfs_free_path(path);
 
+	/*
+	 * we're an inline extent, so nobody can
+	 * extend the file past i_size without locking
+	 * a page we already have locked.
+	 *
+	 * We must do any isize and inode updates
+	 * before we unlock the pages.  Otherwise we
+	 * could end up racing with unlink.
+	 */
 	BTRFS_I(inode)->disk_i_size = inode->i_size;
 	btrfs_update_inode(trans, root, inode);
+
 	return 0;
 fail:
 	btrfs_free_path(path);
@@ -230,8 +241,7 @@
 		return 1;
 	}
 
-	ret = btrfs_drop_extents(trans, root, inode, start,
-				 aligned_end, aligned_end, start,
+	ret = btrfs_drop_extents(trans, inode, start, aligned_end,
 				 &hint_byte, 1);
 	BUG_ON(ret);
 
@@ -416,7 +426,6 @@
 						    start, end,
 						    total_compressed, pages);
 		}
-		btrfs_end_transaction(trans, root);
 		if (ret == 0) {
 			/*
 			 * inline extent creation worked, we don't need
@@ -430,9 +439,11 @@
 			     EXTENT_CLEAR_DELALLOC |
 			     EXTENT_CLEAR_ACCOUNTING |
 			     EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK);
-			ret = 0;
+
+			btrfs_end_transaction(trans, root);
 			goto free_pages_out;
 		}
+		btrfs_end_transaction(trans, root);
 	}
 
 	if (will_compress) {
@@ -543,7 +554,6 @@
 	if (list_empty(&async_cow->extents))
 		return 0;
 
-	trans = btrfs_join_transaction(root, 1);
 
 	while (!list_empty(&async_cow->extents)) {
 		async_extent = list_entry(async_cow->extents.next,
@@ -590,19 +600,15 @@
 		lock_extent(io_tree, async_extent->start,
 			    async_extent->start + async_extent->ram_size - 1,
 			    GFP_NOFS);
-		/*
-		 * here we're doing allocation and writeback of the
-		 * compressed pages
-		 */
-		btrfs_drop_extent_cache(inode, async_extent->start,
-					async_extent->start +
-					async_extent->ram_size - 1, 0);
 
+		trans = btrfs_join_transaction(root, 1);
 		ret = btrfs_reserve_extent(trans, root,
 					   async_extent->compressed_size,
 					   async_extent->compressed_size,
 					   0, alloc_hint,
 					   (u64)-1, &ins, 1);
+		btrfs_end_transaction(trans, root);
+
 		if (ret) {
 			int i;
 			for (i = 0; i < async_extent->nr_pages; i++) {
@@ -618,6 +624,14 @@
 			goto retry;
 		}
 
+		/*
+		 * here we're doing allocation and writeback of the
+		 * compressed pages
+		 */
+		btrfs_drop_extent_cache(inode, async_extent->start,
+					async_extent->start +
+					async_extent->ram_size - 1, 0);
+
 		em = alloc_extent_map(GFP_NOFS);
 		em->start = async_extent->start;
 		em->len = async_extent->ram_size;
@@ -649,8 +663,6 @@
 					       BTRFS_ORDERED_COMPRESSED);
 		BUG_ON(ret);
 
-		btrfs_end_transaction(trans, root);
-
 		/*
 		 * clear dirty, set writeback and unlock the pages.
 		 */
@@ -672,13 +684,11 @@
 				    async_extent->nr_pages);
 
 		BUG_ON(ret);
-		trans = btrfs_join_transaction(root, 1);
 		alloc_hint = ins.objectid + ins.offset;
 		kfree(async_extent);
 		cond_resched();
 	}
 
-	btrfs_end_transaction(trans, root);
 	return 0;
 }
 
@@ -742,6 +752,7 @@
 				     EXTENT_CLEAR_DIRTY |
 				     EXTENT_SET_WRITEBACK |
 				     EXTENT_END_WRITEBACK);
+
 			*nr_written = *nr_written +
 			     (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
 			*page_started = 1;
@@ -1596,7 +1607,6 @@
 				       struct inode *inode, u64 file_pos,
 				       u64 disk_bytenr, u64 disk_num_bytes,
 				       u64 num_bytes, u64 ram_bytes,
-				       u64 locked_end,
 				       u8 compression, u8 encryption,
 				       u16 other_encoding, int extent_type)
 {
@@ -1622,9 +1632,8 @@
 	 * the caller is expected to unpin it and allow it to be merged
 	 * with the others.
 	 */
-	ret = btrfs_drop_extents(trans, root, inode, file_pos,
-				 file_pos + num_bytes, locked_end,
-				 file_pos, &hint, 0);
+	ret = btrfs_drop_extents(trans, inode, file_pos, file_pos + num_bytes,
+				 &hint, 0);
 	BUG_ON(ret);
 
 	ins.objectid = inode->i_ino;
@@ -1671,24 +1680,6 @@
  * before we start the transaction.  It limits the amount of btree
  * reads required while inside the transaction.
  */
-static noinline void reada_csum(struct btrfs_root *root,
-				struct btrfs_path *path,
-				struct btrfs_ordered_extent *ordered_extent)
-{
-	struct btrfs_ordered_sum *sum;
-	u64 bytenr;
-
-	sum = list_entry(ordered_extent->list.next, struct btrfs_ordered_sum,
-			 list);
-	bytenr = sum->sums[0].bytenr;
-
-	/*
-	 * we don't care about the results, the point of this search is
-	 * just to get the btree leaves into ram
-	 */
-	btrfs_lookup_csum(NULL, root->fs_info->csum_root, path, bytenr, 0);
-}
-
 /* as ordered data IO finishes, this gets called so we can finish
  * an ordered extent if the range of bytes in the file it covers are
  * fully written.
@@ -1699,7 +1690,6 @@
 	struct btrfs_trans_handle *trans;
 	struct btrfs_ordered_extent *ordered_extent = NULL;
 	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
-	struct btrfs_path *path;
 	int compressed = 0;
 	int ret;
 
@@ -1707,46 +1697,32 @@
 	if (!ret)
 		return 0;
 
-	/*
-	 * before we join the transaction, try to do some of our IO.
-	 * This will limit the amount of IO that we have to do with
-	 * the transaction running.  We're unlikely to need to do any
-	 * IO if the file extents are new, the disk_i_size checks
-	 * covers the most common case.
-	 */
-	if (start < BTRFS_I(inode)->disk_i_size) {
-		path = btrfs_alloc_path();
-		if (path) {
-			ret = btrfs_lookup_file_extent(NULL, root, path,
-						       inode->i_ino,
-						       start, 0);
-			ordered_extent = btrfs_lookup_ordered_extent(inode,
-								     start);
-			if (!list_empty(&ordered_extent->list)) {
-				btrfs_release_path(root, path);
-				reada_csum(root, path, ordered_extent);
-			}
-			btrfs_free_path(path);
+	ordered_extent = btrfs_lookup_ordered_extent(inode, start);
+	BUG_ON(!ordered_extent);
+
+	if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
+		BUG_ON(!list_empty(&ordered_extent->list));
+		ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+		if (!ret) {
+			trans = btrfs_join_transaction(root, 1);
+			ret = btrfs_update_inode(trans, root, inode);
+			BUG_ON(ret);
+			btrfs_end_transaction(trans, root);
 		}
+		goto out;
 	}
 
-	trans = btrfs_join_transaction(root, 1);
-
-	if (!ordered_extent)
-		ordered_extent = btrfs_lookup_ordered_extent(inode, start);
-	BUG_ON(!ordered_extent);
-	if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags))
-		goto nocow;
-
 	lock_extent(io_tree, ordered_extent->file_offset,
 		    ordered_extent->file_offset + ordered_extent->len - 1,
 		    GFP_NOFS);
 
+	trans = btrfs_join_transaction(root, 1);
+
 	if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
 		compressed = 1;
 	if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
 		BUG_ON(compressed);
-		ret = btrfs_mark_extent_written(trans, root, inode,
+		ret = btrfs_mark_extent_written(trans, inode,
 						ordered_extent->file_offset,
 						ordered_extent->file_offset +
 						ordered_extent->len);
@@ -1758,8 +1734,6 @@
 						ordered_extent->disk_len,
 						ordered_extent->len,
 						ordered_extent->len,
-						ordered_extent->file_offset +
-						ordered_extent->len,
 						compressed, 0, 0,
 						BTRFS_FILE_EXTENT_REG);
 		unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
@@ -1770,22 +1744,20 @@
 	unlock_extent(io_tree, ordered_extent->file_offset,
 		    ordered_extent->file_offset + ordered_extent->len - 1,
 		    GFP_NOFS);
-nocow:
 	add_pending_csums(trans, inode, ordered_extent->file_offset,
 			  &ordered_extent->list);
 
-	mutex_lock(&BTRFS_I(inode)->extent_mutex);
-	btrfs_ordered_update_i_size(inode, ordered_extent);
-	btrfs_update_inode(trans, root, inode);
-	btrfs_remove_ordered_extent(inode, ordered_extent);
-	mutex_unlock(&BTRFS_I(inode)->extent_mutex);
-
+	/* this also removes the ordered extent from the tree */
+	btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+	ret = btrfs_update_inode(trans, root, inode);
+	BUG_ON(ret);
+	btrfs_end_transaction(trans, root);
+out:
 	/* once for us */
 	btrfs_put_ordered_extent(ordered_extent);
 	/* once for the tree */
 	btrfs_put_ordered_extent(ordered_extent);
 
-	btrfs_end_transaction(trans, root);
 	return 0;
 }
 
@@ -2008,6 +1980,54 @@
 	return -EIO;
 }
 
+struct delayed_iput {
+	struct list_head list;
+	struct inode *inode;
+};
+
+void btrfs_add_delayed_iput(struct inode *inode)
+{
+	struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
+	struct delayed_iput *delayed;
+
+	if (atomic_add_unless(&inode->i_count, -1, 1))
+		return;
+
+	delayed = kmalloc(sizeof(*delayed), GFP_NOFS | __GFP_NOFAIL);
+	delayed->inode = inode;
+
+	spin_lock(&fs_info->delayed_iput_lock);
+	list_add_tail(&delayed->list, &fs_info->delayed_iputs);
+	spin_unlock(&fs_info->delayed_iput_lock);
+}
+
+void btrfs_run_delayed_iputs(struct btrfs_root *root)
+{
+	LIST_HEAD(list);
+	struct btrfs_fs_info *fs_info = root->fs_info;
+	struct delayed_iput *delayed;
+	int empty;
+
+	spin_lock(&fs_info->delayed_iput_lock);
+	empty = list_empty(&fs_info->delayed_iputs);
+	spin_unlock(&fs_info->delayed_iput_lock);
+	if (empty)
+		return;
+
+	down_read(&root->fs_info->cleanup_work_sem);
+	spin_lock(&fs_info->delayed_iput_lock);
+	list_splice_init(&fs_info->delayed_iputs, &list);
+	spin_unlock(&fs_info->delayed_iput_lock);
+
+	while (!list_empty(&list)) {
+		delayed = list_entry(list.next, struct delayed_iput, list);
+		list_del(&delayed->list);
+		iput(delayed->inode);
+		kfree(delayed);
+	}
+	up_read(&root->fs_info->cleanup_work_sem);
+}
+
 /*
  * This creates an orphan entry for the given inode in case something goes
  * wrong in the middle of an unlink/truncate.
@@ -2080,16 +2100,17 @@
 	struct inode *inode;
 	int ret = 0, nr_unlink = 0, nr_truncate = 0;
 
-	path = btrfs_alloc_path();
-	if (!path)
+	if (!xchg(&root->clean_orphans, 0))
 		return;
+
+	path = btrfs_alloc_path();
+	BUG_ON(!path);
 	path->reada = -1;
 
 	key.objectid = BTRFS_ORPHAN_OBJECTID;
 	btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
 	key.offset = (u64)-1;
 
-
 	while (1) {
 		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 		if (ret < 0) {
@@ -2834,37 +2855,40 @@
  * min_type is the minimum key type to truncate down to.  If set to 0, this
  * will kill all the items on this inode, including the INODE_ITEM_KEY.
  */
-noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
-					struct btrfs_root *root,
-					struct inode *inode,
-					u64 new_size, u32 min_type)
+int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
+			       struct btrfs_root *root,
+			       struct inode *inode,
+			       u64 new_size, u32 min_type)
 {
-	int ret;
 	struct btrfs_path *path;
-	struct btrfs_key key;
-	struct btrfs_key found_key;
-	u32 found_type = (u8)-1;
 	struct extent_buffer *leaf;
 	struct btrfs_file_extent_item *fi;
+	struct btrfs_key key;
+	struct btrfs_key found_key;
 	u64 extent_start = 0;
 	u64 extent_num_bytes = 0;
 	u64 extent_offset = 0;
 	u64 item_end = 0;
+	u64 mask = root->sectorsize - 1;
+	u32 found_type = (u8)-1;
 	int found_extent;
 	int del_item;
 	int pending_del_nr = 0;
 	int pending_del_slot = 0;
 	int extent_type = -1;
 	int encoding;
-	u64 mask = root->sectorsize - 1;
+	int ret;
+	int err = 0;
+
+	BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
 	if (root->ref_cows)
 		btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
+
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 	path->reada = -1;
 
-	/* FIXME, add redo link to tree so we don't leak on crash */
 	key.objectid = inode->i_ino;
 	key.offset = (u64)-1;
 	key.type = (u8)-1;
@@ -2872,17 +2896,17 @@
 search_again:
 	path->leave_spinning = 1;
 	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-	if (ret < 0)
-		goto error;
+	if (ret < 0) {
+		err = ret;
+		goto out;
+	}
 
 	if (ret > 0) {
 		/* there are no items in the tree for us to truncate, we're
 		 * done
 		 */
-		if (path->slots[0] == 0) {
-			ret = 0;
-			goto error;
-		}
+		if (path->slots[0] == 0)
+			goto out;
 		path->slots[0]--;
 	}
 
@@ -2917,28 +2941,17 @@
 			}
 			item_end--;
 		}
-		if (item_end < new_size) {
-			if (found_type == BTRFS_DIR_ITEM_KEY)
-				found_type = BTRFS_INODE_ITEM_KEY;
-			else if (found_type == BTRFS_EXTENT_ITEM_KEY)
-				found_type = BTRFS_EXTENT_DATA_KEY;
-			else if (found_type == BTRFS_EXTENT_DATA_KEY)
-				found_type = BTRFS_XATTR_ITEM_KEY;
-			else if (found_type == BTRFS_XATTR_ITEM_KEY)
-				found_type = BTRFS_INODE_REF_KEY;
-			else if (found_type)
-				found_type--;
-			else
+		if (found_type > min_type) {
+			del_item = 1;
+		} else {
+			if (item_end < new_size)
 				break;
-			btrfs_set_key_type(&key, found_type);
-			goto next;
+			if (found_key.offset >= new_size)
+				del_item = 1;
+			else
+				del_item = 0;
 		}
-		if (found_key.offset >= new_size)
-			del_item = 1;
-		else
-			del_item = 0;
 		found_extent = 0;
-
 		/* FIXME, shrink the extent if the ref count is only 1 */
 		if (found_type != BTRFS_EXTENT_DATA_KEY)
 			goto delete;
@@ -3025,42 +3038,36 @@
 						inode->i_ino, extent_offset);
 			BUG_ON(ret);
 		}
-next:
-		if (path->slots[0] == 0) {
-			if (pending_del_nr)
-				goto del_pending;
-			btrfs_release_path(root, path);
-			if (found_type == BTRFS_INODE_ITEM_KEY)
-				break;
-			goto search_again;
-		}
 
-		path->slots[0]--;
-		if (pending_del_nr &&
-		    path->slots[0] + 1 != pending_del_slot) {
-			struct btrfs_key debug;
-del_pending:
-			btrfs_item_key_to_cpu(path->nodes[0], &debug,
-					      pending_del_slot);
-			ret = btrfs_del_items(trans, root, path,
-					      pending_del_slot,
-					      pending_del_nr);
-			BUG_ON(ret);
-			pending_del_nr = 0;
+		if (found_type == BTRFS_INODE_ITEM_KEY)
+			break;
+
+		if (path->slots[0] == 0 ||
+		    path->slots[0] != pending_del_slot) {
+			if (root->ref_cows) {
+				err = -EAGAIN;
+				goto out;
+			}
+			if (pending_del_nr) {
+				ret = btrfs_del_items(trans, root, path,
+						pending_del_slot,
+						pending_del_nr);
+				BUG_ON(ret);
+				pending_del_nr = 0;
+			}
 			btrfs_release_path(root, path);
-			if (found_type == BTRFS_INODE_ITEM_KEY)
-				break;
 			goto search_again;
+		} else {
+			path->slots[0]--;
 		}
 	}
-	ret = 0;
-error:
+out:
 	if (pending_del_nr) {
 		ret = btrfs_del_items(trans, root, path, pending_del_slot,
 				      pending_del_nr);
 	}
 	btrfs_free_path(path);
-	return ret;
+	return err;
 }
 
 /*
@@ -3180,10 +3187,6 @@
 	if (size <= hole_start)
 		return 0;
 
-	err = btrfs_truncate_page(inode->i_mapping, inode->i_size);
-	if (err)
-		return err;
-
 	while (1) {
 		struct btrfs_ordered_extent *ordered;
 		btrfs_wait_ordered_range(inode, hole_start,
@@ -3196,9 +3199,6 @@
 		btrfs_put_ordered_extent(ordered);
 	}
 
-	trans = btrfs_start_transaction(root, 1);
-	btrfs_set_trans_block_group(trans, inode);
-
 	cur_offset = hole_start;
 	while (1) {
 		em = btrfs_get_extent(inode, NULL, 0, cur_offset,
@@ -3206,40 +3206,120 @@
 		BUG_ON(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), block_end);
 		last_byte = (last_byte + mask) & ~mask;
-		if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
+		if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
 			u64 hint_byte = 0;
 			hole_size = last_byte - cur_offset;
-			err = btrfs_drop_extents(trans, root, inode,
-						 cur_offset,
-						 cur_offset + hole_size,
-						 block_end,
-						 cur_offset, &hint_byte, 1);
-			if (err)
-				break;
 
-			err = btrfs_reserve_metadata_space(root, 1);
+			err = btrfs_reserve_metadata_space(root, 2);
 			if (err)
 				break;
 
+			trans = btrfs_start_transaction(root, 1);
+			btrfs_set_trans_block_group(trans, inode);
+
+			err = btrfs_drop_extents(trans, inode, cur_offset,
+						 cur_offset + hole_size,
+						 &hint_byte, 1);
+			BUG_ON(err);
+
 			err = btrfs_insert_file_extent(trans, root,
 					inode->i_ino, cur_offset, 0,
 					0, hole_size, 0, hole_size,
 					0, 0, 0);
+			BUG_ON(err);
+
 			btrfs_drop_extent_cache(inode, hole_start,
 					last_byte - 1, 0);
-			btrfs_unreserve_metadata_space(root, 1);
+
+			btrfs_end_transaction(trans, root);
+			btrfs_unreserve_metadata_space(root, 2);
 		}
 		free_extent_map(em);
 		cur_offset = last_byte;
-		if (err || cur_offset >= block_end)
+		if (cur_offset >= block_end)
 			break;
 	}
 
-	btrfs_end_transaction(trans, root);
 	unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
 	return err;
 }
 
+static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
+{
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	struct btrfs_trans_handle *trans;
+	unsigned long nr;
+	int ret;
+
+	if (attr->ia_size == inode->i_size)
+		return 0;
+
+	if (attr->ia_size > inode->i_size) {
+		unsigned long limit;
+		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+		if (attr->ia_size > inode->i_sb->s_maxbytes)
+			return -EFBIG;
+		if (limit != RLIM_INFINITY && attr->ia_size > limit) {
+			send_sig(SIGXFSZ, current, 0);
+			return -EFBIG;
+		}
+	}
+
+	ret = btrfs_reserve_metadata_space(root, 1);
+	if (ret)
+		return ret;
+
+	trans = btrfs_start_transaction(root, 1);
+	btrfs_set_trans_block_group(trans, inode);
+
+	ret = btrfs_orphan_add(trans, inode);
+	BUG_ON(ret);
+
+	nr = trans->blocks_used;
+	btrfs_end_transaction(trans, root);
+	btrfs_unreserve_metadata_space(root, 1);
+	btrfs_btree_balance_dirty(root, nr);
+
+	if (attr->ia_size > inode->i_size) {
+		ret = btrfs_cont_expand(inode, attr->ia_size);
+		if (ret) {
+			btrfs_truncate(inode);
+			return ret;
+		}
+
+		i_size_write(inode, attr->ia_size);
+		btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
+
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+
+		ret = btrfs_update_inode(trans, root, inode);
+		BUG_ON(ret);
+		if (inode->i_nlink > 0) {
+			ret = btrfs_orphan_del(trans, inode);
+			BUG_ON(ret);
+		}
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		btrfs_btree_balance_dirty(root, nr);
+		return 0;
+	}
+
+	/*
+	 * We're truncating a file that used to have good data down to
+	 * zero. Make sure it gets into the ordered flush list so that
+	 * any new writes get down to disk quickly.
+	 */
+	if (attr->ia_size == 0)
+		BTRFS_I(inode)->ordered_data_close = 1;
+
+	/* we don't support swapfiles, so vmtruncate shouldn't fail */
+	ret = vmtruncate(inode, attr->ia_size);
+	BUG_ON(ret);
+
+	return 0;
+}
+
 static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
@@ -3250,23 +3330,14 @@
 		return err;
 
 	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-		if (attr->ia_size > inode->i_size) {
-			err = btrfs_cont_expand(inode, attr->ia_size);
-			if (err)
-				return err;
-		} else if (inode->i_size > 0 &&
-			   attr->ia_size == 0) {
-
-			/* we're truncating a file that used to have good
-			 * data down to zero.  Make sure it gets into
-			 * the ordered flush list so that any new writes
-			 * get down to disk quickly.
-			 */
-			BTRFS_I(inode)->ordered_data_close = 1;
-		}
+		err = btrfs_setattr_size(inode, attr);
+		if (err)
+			return err;
 	}
+	attr->ia_valid &= ~ATTR_SIZE;
 
-	err = inode_setattr(inode, attr);
+	if (attr->ia_valid)
+		err = inode_setattr(inode, attr);
 
 	if (!err && ((attr->ia_valid & ATTR_MODE)))
 		err = btrfs_acl_chmod(inode);
@@ -3287,36 +3358,43 @@
 	}
 	btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
+	if (root->fs_info->log_root_recovering) {
+		BUG_ON(!list_empty(&BTRFS_I(inode)->i_orphan));
+		goto no_delete;
+	}
+
 	if (inode->i_nlink > 0) {
 		BUG_ON(btrfs_root_refs(&root->root_item) != 0);
 		goto no_delete;
 	}
 
 	btrfs_i_size_write(inode, 0);
-	trans = btrfs_join_transaction(root, 1);
 
-	btrfs_set_trans_block_group(trans, inode);
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
-	if (ret) {
-		btrfs_orphan_del(NULL, inode);
-		goto no_delete_lock;
-	}
+	while (1) {
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+		ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
 
-	btrfs_orphan_del(trans, inode);
+		if (ret != -EAGAIN)
+			break;
 
-	nr = trans->blocks_used;
-	clear_inode(inode);
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		trans = NULL;
+		btrfs_btree_balance_dirty(root, nr);
+	}
 
-	btrfs_end_transaction(trans, root);
-	btrfs_btree_balance_dirty(root, nr);
-	return;
+	if (ret == 0) {
+		ret = btrfs_orphan_del(trans, inode);
+		BUG_ON(ret);
+	}
 
-no_delete_lock:
 	nr = trans->blocks_used;
 	btrfs_end_transaction(trans, root);
 	btrfs_btree_balance_dirty(root, nr);
 no_delete:
 	clear_inode(inode);
+	return;
 }
 
 /*
@@ -3569,7 +3647,6 @@
 	INIT_LIST_HEAD(&BTRFS_I(inode)->ordered_operations);
 	RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
 	btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
-	mutex_init(&BTRFS_I(inode)->extent_mutex);
 	mutex_init(&BTRFS_I(inode)->log_mutex);
 }
 
@@ -3695,6 +3772,13 @@
 	}
 	srcu_read_unlock(&root->fs_info->subvol_srcu, index);
 
+	if (root != sub_root) {
+		down_read(&root->fs_info->cleanup_work_sem);
+		if (!(inode->i_sb->s_flags & MS_RDONLY))
+			btrfs_orphan_cleanup(sub_root);
+		up_read(&root->fs_info->cleanup_work_sem);
+	}
+
 	return inode;
 }
 
@@ -3869,7 +3953,11 @@
 
 	/* Reached end of directory/root. Bump pos past the last item. */
 	if (key_type == BTRFS_DIR_INDEX_KEY)
-		filp->f_pos = INT_LIMIT(off_t);
+		/*
+		 * 32-bit glibc will use getdents64, but then strtol -
+		 * so the last number we can serve is this.
+		 */
+		filp->f_pos = 0x7fffffff;
 	else
 		filp->f_pos++;
 nopos:
@@ -4219,7 +4307,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4290,7 +4378,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4336,6 +4424,10 @@
 	if (inode->i_nlink == 0)
 		return -ENOENT;
 
+	/* do not allow sys_link's with other subvols of the same device */
+	if (root->objectid != BTRFS_I(inode)->root->objectid)
+		return -EPERM;
+
 	/*
 	 * 1 item for inode ref
 	 * 2 items for dir items
@@ -4423,7 +4515,7 @@
 
 	drop_on_err = 1;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err)
 		goto out_fail;
 
@@ -5074,17 +5166,20 @@
 	unsigned long nr;
 	u64 mask = root->sectorsize - 1;
 
-	if (!S_ISREG(inode->i_mode))
-		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+	if (!S_ISREG(inode->i_mode)) {
+		WARN_ON(1);
 		return;
+	}
 
 	ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
 	if (ret)
 		return;
+
 	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
+	btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
 
 	trans = btrfs_start_transaction(root, 1);
+	btrfs_set_trans_block_group(trans, inode);
 
 	/*
 	 * setattr is responsible for setting the ordered_data_close flag,
@@ -5106,21 +5201,32 @@
 	if (inode->i_size == 0 && BTRFS_I(inode)->ordered_data_close)
 		btrfs_add_ordered_operation(trans, root, inode);
 
-	btrfs_set_trans_block_group(trans, inode);
-	btrfs_i_size_write(inode, inode->i_size);
+	while (1) {
+		ret = btrfs_truncate_inode_items(trans, root, inode,
+						 inode->i_size,
+						 BTRFS_EXTENT_DATA_KEY);
+		if (ret != -EAGAIN)
+			break;
 
-	ret = btrfs_orphan_add(trans, inode);
-	if (ret)
-		goto out;
-	/* FIXME, add redo link to tree so we don't leak on crash */
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
-				      BTRFS_EXTENT_DATA_KEY);
-	btrfs_update_inode(trans, root, inode);
+		ret = btrfs_update_inode(trans, root, inode);
+		BUG_ON(ret);
 
-	ret = btrfs_orphan_del(trans, inode);
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		btrfs_btree_balance_dirty(root, nr);
+
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+	}
+
+	if (ret == 0 && inode->i_nlink > 0) {
+		ret = btrfs_orphan_del(trans, inode);
+		BUG_ON(ret);
+	}
+
+	ret = btrfs_update_inode(trans, root, inode);
 	BUG_ON(ret);
 
-out:
 	nr = trans->blocks_used;
 	ret = btrfs_end_transaction_throttle(trans, root);
 	BUG_ON(ret);
@@ -5217,9 +5323,9 @@
 
 	spin_lock(&root->list_lock);
 	if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
-		printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan"
-		       " list\n", inode->i_ino);
-		dump_stack();
+		printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n",
+		       inode->i_ino);
+		list_del_init(&BTRFS_I(inode)->i_orphan);
 	}
 	spin_unlock(&root->list_lock);
 
@@ -5476,7 +5582,7 @@
  * some fairly slow code that needs optimization. This walks the list
  * of all the inodes with pending delalloc and forces them to disk.
  */
-int btrfs_start_delalloc_inodes(struct btrfs_root *root)
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
 	struct list_head *head = &root->fs_info->delalloc_inodes;
 	struct btrfs_inode *binode;
@@ -5495,7 +5601,10 @@
 		spin_unlock(&root->fs_info->delalloc_lock);
 		if (inode) {
 			filemap_flush(inode->i_mapping);
-			iput(inode);
+			if (delay_iput)
+				btrfs_add_delayed_iput(inode);
+			else
+				iput(inode);
 		}
 		cond_resched();
 		spin_lock(&root->fs_info->delalloc_lock);
@@ -5569,7 +5678,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -5641,57 +5750,77 @@
 	return err;
 }
 
-static int prealloc_file_range(struct btrfs_trans_handle *trans,
-			       struct inode *inode, u64 start, u64 end,
-			       u64 locked_end, u64 alloc_hint, int mode)
+static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
+			u64 alloc_hint, int mode, loff_t actual_len)
 {
+	struct btrfs_trans_handle *trans;
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_key ins;
 	u64 alloc_size;
 	u64 cur_offset = start;
 	u64 num_bytes = end - start;
 	int ret = 0;
+	u64 i_size;
 
 	while (num_bytes > 0) {
 		alloc_size = min(num_bytes, root->fs_info->max_extent);
 
-		ret = btrfs_reserve_metadata_space(root, 1);
-		if (ret)
-			goto out;
+		trans = btrfs_start_transaction(root, 1);
 
 		ret = btrfs_reserve_extent(trans, root, alloc_size,
 					   root->sectorsize, 0, alloc_hint,
 					   (u64)-1, &ins, 1);
 		if (ret) {
 			WARN_ON(1);
-			goto out;
+			goto stop_trans;
 		}
+
+		ret = btrfs_reserve_metadata_space(root, 3);
+		if (ret) {
+			btrfs_free_reserved_extent(root, ins.objectid,
+						   ins.offset);
+			goto stop_trans;
+		}
+
 		ret = insert_reserved_file_extent(trans, inode,
 						  cur_offset, ins.objectid,
 						  ins.offset, ins.offset,
-						  ins.offset, locked_end,
-						  0, 0, 0,
+						  ins.offset, 0, 0, 0,
 						  BTRFS_FILE_EXTENT_PREALLOC);
 		BUG_ON(ret);
 		btrfs_drop_extent_cache(inode, cur_offset,
 					cur_offset + ins.offset -1, 0);
+
 		num_bytes -= ins.offset;
 		cur_offset += ins.offset;
 		alloc_hint = ins.objectid + ins.offset;
-		btrfs_unreserve_metadata_space(root, 1);
-	}
-out:
-	if (cur_offset > start) {
+
 		inode->i_ctime = CURRENT_TIME;
 		BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
 		if (!(mode & FALLOC_FL_KEEP_SIZE) &&
-		    cur_offset > i_size_read(inode))
-			btrfs_i_size_write(inode, cur_offset);
+			(actual_len > inode->i_size) &&
+			(cur_offset > inode->i_size)) {
+
+			if (cur_offset > actual_len)
+				i_size  = actual_len;
+			else
+				i_size = cur_offset;
+			i_size_write(inode, i_size);
+			btrfs_ordered_update_i_size(inode, i_size, NULL);
+		}
+
 		ret = btrfs_update_inode(trans, root, inode);
 		BUG_ON(ret);
+
+		btrfs_end_transaction(trans, root);
+		btrfs_unreserve_metadata_space(root, 3);
 	}
+	return ret;
 
+stop_trans:
+	btrfs_end_transaction(trans, root);
 	return ret;
+
 }
 
 static long btrfs_fallocate(struct inode *inode, int mode,
@@ -5705,8 +5834,6 @@
 	u64 locked_end;
 	u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
 	struct extent_map *em;
-	struct btrfs_trans_handle *trans;
-	struct btrfs_root *root;
 	int ret;
 
 	alloc_start = offset & ~mask;
@@ -5725,9 +5852,7 @@
 			goto out;
 	}
 
-	root = BTRFS_I(inode)->root;
-
-	ret = btrfs_check_data_free_space(root, inode,
+	ret = btrfs_check_data_free_space(BTRFS_I(inode)->root, inode,
 					  alloc_end - alloc_start);
 	if (ret)
 		goto out;
@@ -5736,12 +5861,6 @@
 	while (1) {
 		struct btrfs_ordered_extent *ordered;
 
-		trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
-		if (!trans) {
-			ret = -EIO;
-			goto out_free;
-		}
-
 		/* the extent lock is ordered inside the running
 		 * transaction
 		 */
@@ -5755,8 +5874,6 @@
 			btrfs_put_ordered_extent(ordered);
 			unlock_extent(&BTRFS_I(inode)->io_tree,
 				      alloc_start, locked_end, GFP_NOFS);
-			btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-
 			/*
 			 * we can't wait on the range with the transaction
 			 * running or with the extent lock held
@@ -5777,10 +5894,12 @@
 		BUG_ON(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), alloc_end);
 		last_byte = (last_byte + mask) & ~mask;
-		if (em->block_start == EXTENT_MAP_HOLE) {
-			ret = prealloc_file_range(trans, inode, cur_offset,
-					last_byte, locked_end + 1,
-					alloc_hint, mode);
+		if (em->block_start == EXTENT_MAP_HOLE ||
+		    (cur_offset >= inode->i_size &&
+		     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
+			ret = prealloc_file_range(inode,
+						  cur_offset, last_byte,
+						alloc_hint, mode, offset+len);
 			if (ret < 0) {
 				free_extent_map(em);
 				break;
@@ -5799,9 +5918,8 @@
 	unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
 		      GFP_NOFS);
 
-	btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-out_free:
-	btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
+	btrfs_free_reserved_data_space(BTRFS_I(inode)->root, inode,
+				       alloc_end - alloc_start);
 out:
 	mutex_unlock(&inode->i_mutex);
 	return ret;
--- linux-ec2-2.6.32.orig/fs/btrfs/volumes.c
+++ linux-ec2-2.6.32/fs/btrfs/volumes.c
@@ -21,6 +21,7 @@
 #include <linux/blkdev.h>
 #include <linux/random.h>
 #include <linux/iocontext.h>
+#include <linux/capability.h>
 #include <asm/div64.h>
 #include "compat.h"
 #include "ctree.h"
@@ -1135,7 +1136,7 @@
 		root->fs_info->avail_metadata_alloc_bits;
 
 	if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) &&
-	    root->fs_info->fs_devices->rw_devices <= 4) {
+	    root->fs_info->fs_devices->num_devices <= 4) {
 		printk(KERN_ERR "btrfs: unable to go below four devices "
 		       "on raid10\n");
 		ret = -EINVAL;
@@ -1143,7 +1144,7 @@
 	}
 
 	if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) &&
-	    root->fs_info->fs_devices->rw_devices <= 2) {
+	    root->fs_info->fs_devices->num_devices <= 2) {
 		printk(KERN_ERR "btrfs: unable to go below two "
 		       "devices on raid1\n");
 		ret = -EINVAL;
@@ -1434,8 +1435,8 @@
 		return -EINVAL;
 
 	bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder);
-	if (!bdev)
-		return -EIO;
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
 
 	if (root->fs_info->fs_devices->seeding) {
 		seeding_dev = 1;
@@ -1900,6 +1901,9 @@
 	if (dev_root->fs_info->sb->s_flags & MS_RDONLY)
 		return -EROFS;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	mutex_lock(&dev_root->fs_info->volume_mutex);
 	dev_root = dev_root->fs_info->dev_root;
 
@@ -2209,7 +2213,7 @@
 		max_chunk_size = 10 * calc_size;
 		min_stripe_size = 64 * 1024 * 1024;
 	} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-		max_chunk_size = 4 * calc_size;
+		max_chunk_size = 256 * 1024 * 1024;
 		min_stripe_size = 32 * 1024 * 1024;
 	} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
 		calc_size = 8 * 1024 * 1024;
@@ -2538,6 +2542,11 @@
 	if (!em)
 		return 1;
 
+	if (btrfs_test_opt(root, DEGRADED)) {
+		free_extent_map(em);
+		return 0;
+	}
+
 	map = (struct map_lookup *)em->bdev;
 	for (i = 0; i < map->num_stripes; i++) {
 		if (!map->stripes[i].dev->writeable) {
@@ -2649,8 +2658,10 @@
 	em = lookup_extent_mapping(em_tree, logical, *length);
 	read_unlock(&em_tree->lock);
 
-	if (!em && unplug_page)
+	if (!em && unplug_page) {
+		kfree(multi);
 		return 0;
+	}
 
 	if (!em) {
 		printk(KERN_CRIT "unable to find logical %llu len %llu\n",
--- linux-ec2-2.6.32.orig/fs/btrfs/transaction.h
+++ linux-ec2-2.6.32/fs/btrfs/transaction.h
@@ -107,10 +107,10 @@
 int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root);
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_write_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 #endif
--- linux-ec2-2.6.32.orig/fs/btrfs/dir-item.c
+++ linux-ec2-2.6.32/fs/btrfs/dir-item.c
@@ -68,12 +68,12 @@
  * into the tree
  */
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-			    struct btrfs_root *root, const char *name,
-			    u16 name_len, const void *data, u16 data_len,
-			    u64 dir)
+			    struct btrfs_root *root,
+			    struct btrfs_path *path, u64 objectid,
+			    const char *name, u16 name_len,
+			    const void *data, u16 data_len)
 {
 	int ret = 0;
-	struct btrfs_path *path;
 	struct btrfs_dir_item *dir_item;
 	unsigned long name_ptr, data_ptr;
 	struct btrfs_key key, location;
@@ -81,15 +81,11 @@
 	struct extent_buffer *leaf;
 	u32 data_size;
 
-	key.objectid = dir;
+	BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
+
+	key.objectid = objectid;
 	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
 	key.offset = btrfs_name_hash(name, name_len);
-	path = btrfs_alloc_path();
-	if (!path)
-		return -ENOMEM;
-	if (name_len + data_len + sizeof(struct btrfs_dir_item) >
-	    BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item))
-		return -ENOSPC;
 
 	data_size = sizeof(*dir_item) + name_len + data_len;
 	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
@@ -117,7 +113,6 @@
 	write_extent_buffer(leaf, data, data_ptr, data_len);
 	btrfs_mark_buffer_dirty(path->nodes[0]);
 
-	btrfs_free_path(path);
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/fs/btrfs/ioctl.c
+++ linux-ec2-2.6.32/fs/btrfs/ioctl.c
@@ -237,7 +237,6 @@
 	u64 objectid;
 	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
 	u64 index = 0;
-	unsigned long nr = 1;
 
 	/*
 	 * 1 - inode item
@@ -286,11 +285,15 @@
 	inode_item->nbytes = cpu_to_le64(root->leafsize);
 	inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
 
+	root_item.flags = 0;
+	root_item.byte_limit = 0;
+	inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT);
+
 	btrfs_set_root_bytenr(&root_item, leaf->start);
 	btrfs_set_root_generation(&root_item, trans->transid);
 	btrfs_set_root_level(&root_item, 0);
 	btrfs_set_root_refs(&root_item, 1);
-	btrfs_set_root_used(&root_item, 0);
+	btrfs_set_root_used(&root_item, leaf->len);
 	btrfs_set_root_last_snapshot(&root_item, 0);
 
 	memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
@@ -342,24 +345,21 @@
 
 	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
-	nr = trans->blocks_used;
 	err = btrfs_commit_transaction(trans, root);
 	if (err && !ret)
 		ret = err;
 
 	btrfs_unreserve_metadata_space(root, 6);
-	btrfs_btree_balance_dirty(root, nr);
 	return ret;
 }
 
 static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
 			   char *name, int namelen)
 {
+	struct inode *inode;
 	struct btrfs_pending_snapshot *pending_snapshot;
 	struct btrfs_trans_handle *trans;
-	int ret = 0;
-	int err;
-	unsigned long nr = 0;
+	int ret;
 
 	if (!root->ref_cows)
 		return -EINVAL;
@@ -372,20 +372,20 @@
 	 */
 	ret = btrfs_reserve_metadata_space(root, 6);
 	if (ret)
-		goto fail_unlock;
+		goto fail;
 
 	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
 	if (!pending_snapshot) {
 		ret = -ENOMEM;
 		btrfs_unreserve_metadata_space(root, 6);
-		goto fail_unlock;
+		goto fail;
 	}
 	pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
 	if (!pending_snapshot->name) {
 		ret = -ENOMEM;
 		kfree(pending_snapshot);
 		btrfs_unreserve_metadata_space(root, 6);
-		goto fail_unlock;
+		goto fail;
 	}
 	memcpy(pending_snapshot->name, name, namelen);
 	pending_snapshot->name[namelen] = '\0';
@@ -395,10 +395,19 @@
 	pending_snapshot->root = root;
 	list_add(&pending_snapshot->list,
 		 &trans->transaction->pending_snapshots);
-	err = btrfs_commit_transaction(trans, root);
+	ret = btrfs_commit_transaction(trans, root);
+	BUG_ON(ret);
+	btrfs_unreserve_metadata_space(root, 6);
 
-fail_unlock:
-	btrfs_btree_balance_dirty(root, nr);
+	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+	if (IS_ERR(inode)) {
+		ret = PTR_ERR(inode);
+		goto fail;
+	}
+	BUG_ON(!inode);
+	d_instantiate(dentry, inode);
+	ret = 0;
+fail:
 	return ret;
 }
 
@@ -947,7 +956,7 @@
 	 */
 
 	/* the destination must be opened for writing */
-	if (!(file->f_mode & FMODE_WRITE))
+	if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND))
 		return -EINVAL;
 
 	ret = mnt_want_write(file->f_path.mnt);
@@ -959,12 +968,17 @@
 		ret = -EBADF;
 		goto out_drop_write;
 	}
+
 	src = src_file->f_dentry->d_inode;
 
 	ret = -EINVAL;
 	if (src == inode)
 		goto out_fput;
 
+	/* the src must be open for reading */
+	if (!(src_file->f_mode & FMODE_READ))
+		goto out_fput;
+
 	ret = -EISDIR;
 	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
 		goto out_fput;
@@ -995,7 +1009,7 @@
 
 	/* determine range to clone */
 	ret = -EINVAL;
-	if (off >= src->i_size || off + len > src->i_size)
+	if (off + len > src->i_size || off + len < off)
 		goto out_unlock;
 	if (len == 0)
 		olen = len = src->i_size - off;
@@ -1027,8 +1041,7 @@
 	BUG_ON(!trans);
 
 	/* punch hole in destination first */
-	btrfs_drop_extents(trans, root, inode, off, off + len,
-			   off + len, 0, &hint_byte, 1);
+	btrfs_drop_extents(trans, inode, off, off + len, &hint_byte, 1);
 
 	/* clone data */
 	key.objectid = src->i_ino;
--- linux-ec2-2.6.32.orig/fs/btrfs/extent-tree.c
+++ linux-ec2-2.6.32/fs/btrfs/extent-tree.c
@@ -83,6 +83,17 @@
 	return (cache->flags & bits) == bits;
 }
 
+void btrfs_get_block_group(struct btrfs_block_group_cache *cache)
+{
+	atomic_inc(&cache->count);
+}
+
+void btrfs_put_block_group(struct btrfs_block_group_cache *cache)
+{
+	if (atomic_dec_and_test(&cache->count))
+		kfree(cache);
+}
+
 /*
  * this adds the block group to the fs_info rb tree for the block group
  * cache
@@ -156,7 +167,7 @@
 		}
 	}
 	if (ret)
-		atomic_inc(&ret->count);
+		btrfs_get_block_group(ret);
 	spin_unlock(&info->block_group_cache_lock);
 
 	return ret;
@@ -195,6 +206,14 @@
 	int stripe_len;
 	int i, nr, ret;
 
+	if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) {
+		stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid;
+		cache->bytes_super += stripe_len;
+		ret = add_excluded_extent(root, cache->key.objectid,
+					  stripe_len);
+		BUG_ON(ret);
+	}
+
 	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
 		bytenr = btrfs_sb_offset(i);
 		ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
@@ -255,7 +274,7 @@
 		if (ret)
 			break;
 
-		if (extent_start == start) {
+		if (extent_start <= start) {
 			start = extent_end + 1;
 		} else if (extent_start > start && extent_start < end) {
 			size = extent_start - start;
@@ -399,6 +418,8 @@
 
 	put_caching_control(caching_ctl);
 	atomic_dec(&block_group->space_info->caching_threads);
+	btrfs_put_block_group(block_group);
+
 	return 0;
 }
 
@@ -439,6 +460,7 @@
 	up_write(&fs_info->extent_commit_sem);
 
 	atomic_inc(&cache->space_info->caching_threads);
+	btrfs_get_block_group(cache);
 
 	tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n",
 			  cache->key.objectid);
@@ -478,12 +500,6 @@
 	return cache;
 }
 
-void btrfs_put_block_group(struct btrfs_block_group_cache *cache)
-{
-	if (atomic_dec_and_test(&cache->count))
-		kfree(cache);
-}
-
 static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
 						  u64 flags)
 {
@@ -2574,7 +2590,7 @@
 	if (node) {
 		cache = rb_entry(node, struct btrfs_block_group_cache,
 				 cache_node);
-		atomic_inc(&cache->count);
+		btrfs_get_block_group(cache);
 	} else
 		cache = NULL;
 	spin_unlock(&root->fs_info->block_group_cache_lock);
@@ -2880,9 +2896,9 @@
 	root = async->root;
 	info = async->info;
 
-	btrfs_start_delalloc_inodes(root);
+	btrfs_start_delalloc_inodes(root, 0);
 	wake_up(&info->flush_wait);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	spin_lock(&info->lock);
 	info->flushing = 0;
@@ -2956,8 +2972,8 @@
 	return;
 
 flush:
-	btrfs_start_delalloc_inodes(root);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_start_delalloc_inodes(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	spin_lock(&info->lock);
 	info->flushing = 0;
@@ -3454,14 +3470,6 @@
 	else
 		old_val -= num_bytes;
 	btrfs_set_super_bytes_used(&info->super_copy, old_val);
-
-	/* block accounting for root item */
-	old_val = btrfs_root_used(&root->root_item);
-	if (alloc)
-		old_val += num_bytes;
-	else
-		old_val -= num_bytes;
-	btrfs_set_root_used(&root->root_item, old_val);
 	spin_unlock(&info->delalloc_lock);
 
 	while (total) {
@@ -4049,6 +4057,21 @@
 	return ret;
 }
 
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u32 blocksize,
+			  u64 parent, u64 root_objectid, int level)
+{
+	u64 used;
+	spin_lock(&root->node_lock);
+	used = btrfs_root_used(&root->root_item) - blocksize;
+	btrfs_set_root_used(&root->root_item, used);
+	spin_unlock(&root->node_lock);
+
+	return btrfs_free_extent(trans, root, bytenr, blocksize,
+				 parent, root_objectid, level, 0);
+}
+
 static u64 stripe_align(struct btrfs_root *root, u64 val)
 {
 	u64 mask = ((u64)root->stripesize - 1);
@@ -4212,7 +4235,7 @@
 		u64 offset;
 		int cached;
 
-		atomic_inc(&block_group->count);
+		btrfs_get_block_group(block_group);
 		search_start = block_group->key.objectid;
 
 have_block_group:
@@ -4300,7 +4323,7 @@
 
 				btrfs_put_block_group(block_group);
 				block_group = last_ptr->block_group;
-				atomic_inc(&block_group->count);
+				btrfs_get_block_group(block_group);
 				spin_unlock(&last_ptr->lock);
 				spin_unlock(&last_ptr->refill_lock);
 
@@ -4578,7 +4601,6 @@
 {
 	int ret;
 	u64 search_start = 0;
-	struct btrfs_fs_info *info = root->fs_info;
 
 	data = btrfs_get_alloc_profile(root, data);
 again:
@@ -4586,17 +4608,9 @@
 	 * the only place that sets empty_size is btrfs_realloc_node, which
 	 * is not called recursively on allocations
 	 */
-	if (empty_size || root->ref_cows) {
-		if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
-			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-				     2 * 1024 * 1024,
-				     BTRFS_BLOCK_GROUP_METADATA |
-				     (info->metadata_alloc_profile &
-				      info->avail_metadata_alloc_bits), 0);
-		}
+	if (empty_size || root->ref_cows)
 		ret = do_chunk_alloc(trans, root->fs_info->extent_root,
 				     num_bytes + 2 * 1024 * 1024, data, 0);
-	}
 
 	WARN_ON(num_bytes < root->sectorsize);
 	ret = find_free_extent(trans, root, num_bytes, empty_size,
@@ -4897,6 +4911,14 @@
 					extent_op);
 		BUG_ON(ret);
 	}
+
+	if (root_objectid == root->root_key.objectid) {
+		u64 used;
+		spin_lock(&root->node_lock);
+		used = btrfs_root_used(&root->root_item) + num_bytes;
+		btrfs_set_root_used(&root->root_item, used);
+		spin_unlock(&root->node_lock);
+	}
 	return ret;
 }
 
@@ -4919,8 +4941,16 @@
 	btrfs_set_buffer_uptodate(buf);
 
 	if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
-		set_extent_dirty(&root->dirty_log_pages, buf->start,
-			 buf->start + buf->len - 1, GFP_NOFS);
+		/*
+		 * we allow two log transactions at a time, use different
+		 * EXENT bit to differentiate dirty pages.
+		 */
+		if (root->log_transid % 2 == 0)
+			set_extent_dirty(&root->dirty_log_pages, buf->start,
+					buf->start + buf->len - 1, GFP_NOFS);
+		else
+			set_extent_new(&root->dirty_log_pages, buf->start,
+					buf->start + buf->len - 1, GFP_NOFS);
 	} else {
 		set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
 			 buf->start + buf->len - 1, GFP_NOFS);
@@ -5372,10 +5402,6 @@
 	int ret;
 
 	while (level >= 0) {
-		if (path->slots[level] >=
-		    btrfs_header_nritems(path->nodes[level]))
-			break;
-
 		ret = walk_down_proc(trans, root, path, wc, lookup_info);
 		if (ret > 0)
 			break;
@@ -5383,6 +5409,10 @@
 		if (level == 0)
 			break;
 
+		if (path->slots[level] >=
+		    btrfs_header_nritems(path->nodes[level]))
+			break;
+
 		ret = do_walk_down(trans, root, path, wc, &lookup_info);
 		if (ret > 0) {
 			path->slots[level]++;
@@ -7373,9 +7403,7 @@
 			wait_block_group_cache_done(block_group);
 
 		btrfs_remove_free_space_cache(block_group);
-
-		WARN_ON(atomic_read(&block_group->count) != 1);
-		kfree(block_group);
+		btrfs_put_block_group(block_group);
 
 		spin_lock(&info->block_group_cache_lock);
 	}
--- linux-ec2-2.6.32.orig/fs/btrfs/disk-io.c
+++ linux-ec2-2.6.32/fs/btrfs/disk-io.c
@@ -892,6 +892,8 @@
 	root->stripesize = stripesize;
 	root->ref_cows = 0;
 	root->track_dirty = 0;
+	root->in_radix = 0;
+	root->clean_orphans = 0;
 
 	root->fs_info = fs_info;
 	root->objectid = objectid;
@@ -928,7 +930,6 @@
 	root->defrag_trans_start = fs_info->generation;
 	init_completion(&root->kobj_unregister);
 	root->defrag_running = 0;
-	root->defrag_level = 0;
 	root->root_key.objectid = objectid;
 	root->anon_super.s_root = NULL;
 	root->anon_super.s_dev = 0;
@@ -980,12 +981,12 @@
 
 	while (1) {
 		ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
-				    0, &start, &end, EXTENT_DIRTY);
+				0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
 		if (ret)
 			break;
 
-		clear_extent_dirty(&log_root_tree->dirty_log_pages,
-				   start, end, GFP_NOFS);
+		clear_extent_bits(&log_root_tree->dirty_log_pages, start, end,
+				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
 	}
 	eb = fs_info->log_root_tree->node;
 
@@ -1144,8 +1145,10 @@
 	root->commit_root = btrfs_root_node(root);
 	BUG_ON(!root->node);
 out:
-	if (location->objectid != BTRFS_TREE_LOG_OBJECTID)
+	if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
 		root->ref_cows = 1;
+		btrfs_check_and_init_root_item(&root->root_item);
+	}
 
 	return root;
 }
@@ -1210,8 +1213,10 @@
 	ret = radix_tree_insert(&fs_info->fs_roots_radix,
 				(unsigned long)root->root_key.objectid,
 				root);
-	if (ret == 0)
+	if (ret == 0) {
 		root->in_radix = 1;
+		root->clean_orphans = 1;
+	}
 	spin_unlock(&fs_info->fs_roots_radix_lock);
 	radix_tree_preload_end();
 	if (ret) {
@@ -1225,10 +1230,6 @@
 	ret = btrfs_find_dead_roots(fs_info->tree_root,
 				    root->root_key.objectid);
 	WARN_ON(ret);
-
-	if (!(fs_info->sb->s_flags & MS_RDONLY))
-		btrfs_orphan_cleanup(root);
-
 	return root;
 fail:
 	free_fs_root(root);
@@ -1477,6 +1478,7 @@
 
 		if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
 		    mutex_trylock(&root->fs_info->cleaner_mutex)) {
+			btrfs_run_delayed_iputs(root);
 			btrfs_clean_old_snapshots(root);
 			mutex_unlock(&root->fs_info->cleaner_mutex);
 		}
@@ -1606,6 +1608,7 @@
 	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
 	INIT_LIST_HEAD(&fs_info->trans_list);
 	INIT_LIST_HEAD(&fs_info->dead_roots);
+	INIT_LIST_HEAD(&fs_info->delayed_iputs);
 	INIT_LIST_HEAD(&fs_info->hashers);
 	INIT_LIST_HEAD(&fs_info->delalloc_inodes);
 	INIT_LIST_HEAD(&fs_info->ordered_operations);
@@ -1614,6 +1617,7 @@
 	spin_lock_init(&fs_info->new_trans_lock);
 	spin_lock_init(&fs_info->ref_cache_lock);
 	spin_lock_init(&fs_info->fs_roots_radix_lock);
+	spin_lock_init(&fs_info->delayed_iput_lock);
 
 	init_completion(&fs_info->kobj_unregister);
 	fs_info->tree_root = tree_root;
@@ -1689,6 +1693,7 @@
 	mutex_init(&fs_info->cleaner_mutex);
 	mutex_init(&fs_info->volume_mutex);
 	init_rwsem(&fs_info->extent_commit_sem);
+	init_rwsem(&fs_info->cleanup_work_sem);
 	init_rwsem(&fs_info->subvol_sem);
 
 	btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
@@ -1979,7 +1984,12 @@
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		ret = btrfs_recover_relocation(tree_root);
-		BUG_ON(ret);
+		if (ret < 0) {
+			printk(KERN_WARNING
+			       "btrfs: failed to recover relocation\n");
+			err = -EINVAL;
+			goto fail_trans_kthread;
+		}
 	}
 
 	location.objectid = BTRFS_FS_TREE_OBJECTID;
@@ -1990,6 +2000,12 @@
 	if (!fs_info->fs_root)
 		goto fail_trans_kthread;
 
+	if (!(sb->s_flags & MS_RDONLY)) {
+		down_read(&fs_info->cleanup_work_sem);
+		btrfs_orphan_cleanup(fs_info->fs_root);
+		up_read(&fs_info->cleanup_work_sem);
+	}
+
 	return tree_root;
 
 fail_trans_kthread:
@@ -2386,8 +2402,14 @@
 	int ret;
 
 	mutex_lock(&root->fs_info->cleaner_mutex);
+	btrfs_run_delayed_iputs(root);
 	btrfs_clean_old_snapshots(root);
 	mutex_unlock(&root->fs_info->cleaner_mutex);
+
+	/* wait until ongoing cleanup work done */
+	down_write(&root->fs_info->cleanup_work_sem);
+	up_write(&root->fs_info->cleanup_work_sem);
+
 	trans = btrfs_start_transaction(root, 1);
 	ret = btrfs_commit_transaction(trans, root);
 	BUG_ON(ret);
--- linux-ec2-2.6.32.orig/fs/btrfs/ordered-data.h
+++ linux-ec2-2.6.32/fs/btrfs/ordered-data.h
@@ -150,12 +150,13 @@
 int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len);
 struct btrfs_ordered_extent *
 btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset);
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 				struct btrfs_ordered_extent *ordered);
 int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only);
 int btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
 int btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
 				struct inode *inode);
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+			       int nocow_only, int delay_iput);
 #endif
--- linux-ec2-2.6.32.orig/fs/btrfs/file.c
+++ linux-ec2-2.6.32/fs/btrfs/file.c
@@ -179,18 +179,14 @@
 		}
 		flags = em->flags;
 		if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
-			if (em->start <= start &&
-			    (!testend || em->start + em->len >= start + len)) {
+			if (testend && em->start + em->len >= start + len) {
 				free_extent_map(em);
 				write_unlock(&em_tree->lock);
 				break;
 			}
-			if (start < em->start) {
-				len = em->start - start;
-			} else {
+			start = em->start + em->len;
+			if (testend)
 				len = start + len - (em->start + em->len);
-				start = em->start + em->len;
-			}
 			free_extent_map(em);
 			write_unlock(&em_tree->lock);
 			continue;
@@ -265,324 +261,253 @@
  * If an extent intersects the range but is not entirely inside the range
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
- *
- * inline_limit is used to tell this code which offsets in the file to keep
- * if they contain inline extents.
  */
-noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 locked_end,
-		       u64 inline_limit, u64 *hint_byte, int drop_cache)
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+		       u64 start, u64 end, u64 *hint_byte, int drop_cache)
 {
-	u64 extent_end = 0;
-	u64 search_start = start;
-	u64 ram_bytes = 0;
-	u64 disk_bytenr = 0;
-	u64 orig_locked_end = locked_end;
-	u8 compression;
-	u8 encryption;
-	u16 other_encoding = 0;
+	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_buffer *leaf;
-	struct btrfs_file_extent_item *extent;
+	struct btrfs_file_extent_item *fi;
 	struct btrfs_path *path;
 	struct btrfs_key key;
-	struct btrfs_file_extent_item old;
-	int keep;
-	int slot;
-	int bookend;
-	int found_type = 0;
-	int found_extent;
-	int found_inline;
+	struct btrfs_key new_key;
+	u64 search_start = start;
+	u64 disk_bytenr = 0;
+	u64 num_bytes = 0;
+	u64 extent_offset = 0;
+	u64 extent_end = 0;
+	int del_nr = 0;
+	int del_slot = 0;
+	int extent_type;
 	int recow;
 	int ret;
 
-	inline_limit = 0;
 	if (drop_cache)
 		btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
+
 	while (1) {
 		recow = 0;
-		btrfs_release_path(root, path);
 		ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
 					       search_start, -1);
 		if (ret < 0)
-			goto out;
-		if (ret > 0) {
-			if (path->slots[0] == 0) {
-				ret = 0;
-				goto out;
-			}
-			path->slots[0]--;
+			break;
+		if (ret > 0 && path->slots[0] > 0 && search_start == start) {
+			leaf = path->nodes[0];
+			btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
+			if (key.objectid == inode->i_ino &&
+			    key.type == BTRFS_EXTENT_DATA_KEY)
+				path->slots[0]--;
 		}
+		ret = 0;
 next_slot:
-		keep = 0;
-		bookend = 0;
-		found_extent = 0;
-		found_inline = 0;
-		compression = 0;
-		encryption = 0;
-		extent = NULL;
 		leaf = path->nodes[0];
-		slot = path->slots[0];
-		ret = 0;
-		btrfs_item_key_to_cpu(leaf, &key, slot);
-		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY &&
-		    key.offset >= end) {
-			goto out;
-		}
-		if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
-		    key.objectid != inode->i_ino) {
-			goto out;
-		}
-		if (recow) {
-			search_start = max(key.offset, start);
-			continue;
-		}
-		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
-			extent = btrfs_item_ptr(leaf, slot,
-						struct btrfs_file_extent_item);
-			found_type = btrfs_file_extent_type(leaf, extent);
-			compression = btrfs_file_extent_compression(leaf,
-								    extent);
-			encryption = btrfs_file_extent_encryption(leaf,
-								  extent);
-			other_encoding = btrfs_file_extent_other_encoding(leaf,
-								  extent);
-			if (found_type == BTRFS_FILE_EXTENT_REG ||
-			    found_type == BTRFS_FILE_EXTENT_PREALLOC) {
-				extent_end =
-				     btrfs_file_extent_disk_bytenr(leaf,
-								   extent);
-				if (extent_end)
-					*hint_byte = extent_end;
-
-				extent_end = key.offset +
-				     btrfs_file_extent_num_bytes(leaf, extent);
-				ram_bytes = btrfs_file_extent_ram_bytes(leaf,
-								extent);
-				found_extent = 1;
-			} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
-				found_inline = 1;
-				extent_end = key.offset +
-				     btrfs_file_extent_inline_len(leaf, extent);
+		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
+			BUG_ON(del_nr > 0);
+			ret = btrfs_next_leaf(root, path);
+			if (ret < 0)
+				break;
+			if (ret > 0) {
+				ret = 0;
+				break;
 			}
+			leaf = path->nodes[0];
+			recow = 1;
+		}
+
+		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+		if (key.objectid > inode->i_ino ||
+		    key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+			break;
+
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		extent_type = btrfs_file_extent_type(leaf, fi);
+
+		if (extent_type == BTRFS_FILE_EXTENT_REG ||
+		    extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
+			disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
+			num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
+			extent_offset = btrfs_file_extent_offset(leaf, fi);
+			extent_end = key.offset +
+				btrfs_file_extent_num_bytes(leaf, fi);
+		} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+			extent_end = key.offset +
+				btrfs_file_extent_inline_len(leaf, fi);
 		} else {
+			WARN_ON(1);
 			extent_end = search_start;
 		}
 
-		/* we found nothing we can drop */
-		if ((!found_extent && !found_inline) ||
-		    search_start >= extent_end) {
-			int nextret;
-			u32 nritems;
-			nritems = btrfs_header_nritems(leaf);
-			if (slot >= nritems - 1) {
-				nextret = btrfs_next_leaf(root, path);
-				if (nextret)
-					goto out;
-				recow = 1;
-			} else {
-				path->slots[0]++;
-			}
+		if (extent_end <= search_start) {
+			path->slots[0]++;
 			goto next_slot;
 		}
 
-		if (end <= extent_end && start >= key.offset && found_inline)
-			*hint_byte = EXTENT_MAP_INLINE;
+		search_start = max(key.offset, start);
+		if (recow) {
+			btrfs_release_path(root, path);
+			continue;
+		}
 
-		if (found_extent) {
-			read_extent_buffer(leaf, &old, (unsigned long)extent,
-					   sizeof(old));
-		}
-
-		if (end < extent_end && end >= key.offset) {
-			bookend = 1;
-			if (found_inline && start <= key.offset)
-				keep = 1;
-		}
-
-		if (bookend && found_extent) {
-			if (locked_end < extent_end) {
-				ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-						locked_end, extent_end - 1,
-						GFP_NOFS);
-				if (!ret) {
-					btrfs_release_path(root, path);
-					lock_extent(&BTRFS_I(inode)->io_tree,
-						locked_end, extent_end - 1,
-						GFP_NOFS);
-					locked_end = extent_end;
-					continue;
-				}
-				locked_end = extent_end;
+		/*
+		 *     | - range to drop - |
+		 *  | -------- extent -------- |
+		 */
+		if (start > key.offset && end < extent_end) {
+			BUG_ON(del_nr > 0);
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+			memcpy(&new_key, &key, sizeof(new_key));
+			new_key.offset = start;
+			ret = btrfs_duplicate_item(trans, root, path,
+						   &new_key);
+			if (ret == -EAGAIN) {
+				btrfs_release_path(root, path);
+				continue;
 			}
-			disk_bytenr = le64_to_cpu(old.disk_bytenr);
-			if (disk_bytenr != 0) {
+			if (ret < 0)
+				break;
+
+			leaf = path->nodes[0];
+			fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							start - key.offset);
+
+			fi = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
+
+			extent_offset += start - key.offset;
+			btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							extent_end - start);
+			btrfs_mark_buffer_dirty(leaf);
+
+			if (disk_bytenr > 0) {
 				ret = btrfs_inc_extent_ref(trans, root,
-					   disk_bytenr,
-					   le64_to_cpu(old.disk_num_bytes), 0,
-					   root->root_key.objectid,
-					   key.objectid, key.offset -
-					   le64_to_cpu(old.offset));
+						disk_bytenr, num_bytes, 0,
+						root->root_key.objectid,
+						new_key.objectid,
+						start - extent_offset);
 				BUG_ON(ret);
+				*hint_byte = disk_bytenr;
 			}
+			key.offset = start;
 		}
+		/*
+		 *  | ---- range to drop ----- |
+		 *      | -------- extent -------- |
+		 */
+		if (start <= key.offset && end < extent_end) {
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+			memcpy(&new_key, &key, sizeof(new_key));
+			new_key.offset = end;
+			btrfs_set_item_key_safe(trans, root, path, &new_key);
 
-		if (found_inline) {
-			u64 mask = root->sectorsize - 1;
-			search_start = (extent_end + mask) & ~mask;
-		} else
-			search_start = extent_end;
-
-		/* truncate existing extent */
-		if (start > key.offset) {
-			u64 new_num;
-			u64 old_num;
-			keep = 1;
-			WARN_ON(start & (root->sectorsize - 1));
-			if (found_extent) {
-				new_num = start - key.offset;
-				old_num = btrfs_file_extent_num_bytes(leaf,
-								      extent);
-				*hint_byte =
-					btrfs_file_extent_disk_bytenr(leaf,
-								      extent);
-				if (btrfs_file_extent_disk_bytenr(leaf,
-								  extent)) {
-					inode_sub_bytes(inode, old_num -
-							new_num);
-				}
-				btrfs_set_file_extent_num_bytes(leaf,
-							extent, new_num);
-				btrfs_mark_buffer_dirty(leaf);
-			} else if (key.offset < inline_limit &&
-				   (end > extent_end) &&
-				   (inline_limit < extent_end)) {
-				u32 new_size;
-				new_size = btrfs_file_extent_calc_inline_size(
-						   inline_limit - key.offset);
-				inode_sub_bytes(inode, extent_end -
-						inline_limit);
-				btrfs_set_file_extent_ram_bytes(leaf, extent,
-							new_size);
-				if (!compression && !encryption) {
-					btrfs_truncate_item(trans, root, path,
-							    new_size, 1);
-				}
-			}
-		}
-		/* delete the entire extent */
-		if (!keep) {
-			if (found_inline)
-				inode_sub_bytes(inode, extent_end -
-						key.offset);
-			ret = btrfs_del_item(trans, root, path);
-			/* TODO update progress marker and return */
-			BUG_ON(ret);
-			extent = NULL;
-			btrfs_release_path(root, path);
-			/* the extent will be freed later */
-		}
-		if (bookend && found_inline && start <= key.offset) {
-			u32 new_size;
-			new_size = btrfs_file_extent_calc_inline_size(
-						   extent_end - end);
-			inode_sub_bytes(inode, end - key.offset);
-			btrfs_set_file_extent_ram_bytes(leaf, extent,
-							new_size);
-			if (!compression && !encryption)
-				ret = btrfs_truncate_item(trans, root, path,
-							  new_size, 0);
-			BUG_ON(ret);
-		}
-		/* create bookend, splitting the extent in two */
-		if (bookend && found_extent) {
-			struct btrfs_key ins;
-			ins.objectid = inode->i_ino;
-			ins.offset = end;
-			btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
-
-			btrfs_release_path(root, path);
-			path->leave_spinning = 1;
-			ret = btrfs_insert_empty_item(trans, root, path, &ins,
-						      sizeof(*extent));
-			BUG_ON(ret);
-
-			leaf = path->nodes[0];
-			extent = btrfs_item_ptr(leaf, path->slots[0],
-						struct btrfs_file_extent_item);
-			write_extent_buffer(leaf, &old,
-					    (unsigned long)extent, sizeof(old));
-
-			btrfs_set_file_extent_compression(leaf, extent,
-							  compression);
-			btrfs_set_file_extent_encryption(leaf, extent,
-							 encryption);
-			btrfs_set_file_extent_other_encoding(leaf, extent,
-							     other_encoding);
-			btrfs_set_file_extent_offset(leaf, extent,
-				    le64_to_cpu(old.offset) + end - key.offset);
-			WARN_ON(le64_to_cpu(old.num_bytes) <
-				(extent_end - end));
-			btrfs_set_file_extent_num_bytes(leaf, extent,
+			extent_offset += end - key.offset;
+			btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
 							extent_end - end);
+			btrfs_mark_buffer_dirty(leaf);
+			if (disk_bytenr > 0) {
+				inode_sub_bytes(inode, end - key.offset);
+				*hint_byte = disk_bytenr;
+			}
+			break;
+		}
+
+		search_start = extent_end;
+		/*
+		 *       | ---- range to drop ----- |
+		 *  | -------- extent -------- |
+		 */
+		if (start > key.offset && end >= extent_end) {
+			BUG_ON(del_nr > 0);
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
 
-			/*
-			 * set the ram bytes to the size of the full extent
-			 * before splitting.  This is a worst case flag,
-			 * but its the best we can do because we don't know
-			 * how splitting affects compression
-			 */
-			btrfs_set_file_extent_ram_bytes(leaf, extent,
-							ram_bytes);
-			btrfs_set_file_extent_type(leaf, extent, found_type);
-
-			btrfs_unlock_up_safe(path, 1);
-			btrfs_mark_buffer_dirty(path->nodes[0]);
-			btrfs_set_lock_blocking(path->nodes[0]);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							start - key.offset);
+			btrfs_mark_buffer_dirty(leaf);
+			if (disk_bytenr > 0) {
+				inode_sub_bytes(inode, extent_end - start);
+				*hint_byte = disk_bytenr;
+			}
+			if (end == extent_end)
+				break;
 
-			path->leave_spinning = 0;
-			btrfs_release_path(root, path);
-			if (disk_bytenr != 0)
-				inode_add_bytes(inode, extent_end - end);
+			path->slots[0]++;
+			goto next_slot;
 		}
 
-		if (found_extent && !keep) {
-			u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr);
+		/*
+		 *  | ---- range to drop ----- |
+		 *    | ------ extent ------ |
+		 */
+		if (start <= key.offset && end >= extent_end) {
+			if (del_nr == 0) {
+				del_slot = path->slots[0];
+				del_nr = 1;
+			} else {
+				BUG_ON(del_slot + del_nr != path->slots[0]);
+				del_nr++;
+			}
 
-			if (old_disk_bytenr != 0) {
+			if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
 				inode_sub_bytes(inode,
-						le64_to_cpu(old.num_bytes));
+						extent_end - key.offset);
+				extent_end = ALIGN(extent_end,
+						   root->sectorsize);
+			} else if (disk_bytenr > 0) {
 				ret = btrfs_free_extent(trans, root,
-						old_disk_bytenr,
-						le64_to_cpu(old.disk_num_bytes),
-						0, root->root_key.objectid,
+						disk_bytenr, num_bytes, 0,
+						root->root_key.objectid,
 						key.objectid, key.offset -
-						le64_to_cpu(old.offset));
+						extent_offset);
 				BUG_ON(ret);
-				*hint_byte = old_disk_bytenr;
+				inode_sub_bytes(inode,
+						extent_end - key.offset);
+				*hint_byte = disk_bytenr;
 			}
-		}
 
-		if (search_start >= end) {
-			ret = 0;
-			goto out;
+			if (end == extent_end)
+				break;
+
+			if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
+				path->slots[0]++;
+				goto next_slot;
+			}
+
+			ret = btrfs_del_items(trans, root, path, del_slot,
+					      del_nr);
+			BUG_ON(ret);
+
+			del_nr = 0;
+			del_slot = 0;
+
+			btrfs_release_path(root, path);
+			continue;
 		}
+
+		BUG_ON(1);
 	}
-out:
-	btrfs_free_path(path);
-	if (locked_end > orig_locked_end) {
-		unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end,
-			      locked_end - 1, GFP_NOFS);
+
+	if (del_nr > 0) {
+		ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+		BUG_ON(ret);
 	}
+
+	btrfs_free_path(path);
 	return ret;
 }
 
 static int extent_mergeable(struct extent_buffer *leaf, int slot,
-			    u64 objectid, u64 bytenr, u64 *start, u64 *end)
+			    u64 objectid, u64 bytenr, u64 orig_offset,
+			    u64 *start, u64 *end)
 {
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_key key;
@@ -598,6 +523,7 @@
 	fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
 	if (btrfs_file_extent_type(leaf, fi) != BTRFS_FILE_EXTENT_REG ||
 	    btrfs_file_extent_disk_bytenr(leaf, fi) != bytenr ||
+	    btrfs_file_extent_offset(leaf, fi) != key.offset - orig_offset ||
 	    btrfs_file_extent_compression(leaf, fi) ||
 	    btrfs_file_extent_encryption(leaf, fi) ||
 	    btrfs_file_extent_other_encoding(leaf, fi))
@@ -620,23 +546,24 @@
  * two or three.
  */
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-			      struct btrfs_root *root,
 			      struct inode *inode, u64 start, u64 end)
 {
+	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_buffer *leaf;
 	struct btrfs_path *path;
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_key key;
+	struct btrfs_key new_key;
 	u64 bytenr;
 	u64 num_bytes;
 	u64 extent_end;
 	u64 orig_offset;
 	u64 other_start;
 	u64 other_end;
-	u64 split = start;
-	u64 locked_end = end;
-	int extent_type;
-	int split_end = 1;
+	u64 split;
+	int del_nr = 0;
+	int del_slot = 0;
+	int recow;
 	int ret;
 
 	btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -644,12 +571,11 @@
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 again:
+	recow = 0;
+	split = start;
 	key.objectid = inode->i_ino;
 	key.type = BTRFS_EXTENT_DATA_KEY;
-	if (split == start)
-		key.offset = split;
-	else
-		key.offset = split - 1;
+	key.offset = split;
 
 	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
 	if (ret > 0 && path->slots[0] > 0)
@@ -661,159 +587,158 @@
 	       key.type != BTRFS_EXTENT_DATA_KEY);
 	fi = btrfs_item_ptr(leaf, path->slots[0],
 			    struct btrfs_file_extent_item);
-	extent_type = btrfs_file_extent_type(leaf, fi);
-	BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC);
+	BUG_ON(btrfs_file_extent_type(leaf, fi) !=
+	       BTRFS_FILE_EXTENT_PREALLOC);
 	extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
 	BUG_ON(key.offset > start || extent_end < end);
 
 	bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
 	num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
 	orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi);
+	memcpy(&new_key, &key, sizeof(new_key));
 
-	if (key.offset == start)
-		split = end;
+	if (start == key.offset && end < extent_end) {
+		other_start = 0;
+		other_end = start;
+		if (extent_mergeable(leaf, path->slots[0] - 1,
+				     inode->i_ino, bytenr, orig_offset,
+				     &other_start, &other_end)) {
+			new_key.offset = end;
+			btrfs_set_item_key_safe(trans, root, path, &new_key);
+			fi = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							extent_end - end);
+			btrfs_set_file_extent_offset(leaf, fi,
+						     end - orig_offset);
+			fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							end - other_start);
+			btrfs_mark_buffer_dirty(leaf);
+			goto out;
+		}
+	}
 
-	if (key.offset == start && extent_end == end) {
-		int del_nr = 0;
-		int del_slot = 0;
+	if (start > key.offset && end == extent_end) {
 		other_start = end;
 		other_end = 0;
-		if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			extent_end = other_end;
-			del_slot = path->slots[0] + 1;
-			del_nr++;
-			ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-						0, root->root_key.objectid,
-						inode->i_ino, orig_offset);
-			BUG_ON(ret);
-		}
-		other_start = 0;
-		other_end = start;
-		if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			key.offset = other_start;
-			del_slot = path->slots[0];
-			del_nr++;
-			ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-						0, root->root_key.objectid,
-						inode->i_ino, orig_offset);
-			BUG_ON(ret);
+		if (extent_mergeable(leaf, path->slots[0] + 1,
+				     inode->i_ino, bytenr, orig_offset,
+				     &other_start, &other_end)) {
+			fi = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							start - key.offset);
+			path->slots[0]++;
+			new_key.offset = start;
+			btrfs_set_item_key_safe(trans, root, path, &new_key);
+
+			fi = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							other_end - start);
+			btrfs_set_file_extent_offset(leaf, fi,
+						     start - orig_offset);
+			btrfs_mark_buffer_dirty(leaf);
+			goto out;
 		}
-		split_end = 0;
-		if (del_nr == 0) {
-			btrfs_set_file_extent_type(leaf, fi,
-						   BTRFS_FILE_EXTENT_REG);
-			goto done;
+	}
+
+	while (start > key.offset || end < extent_end) {
+		if (key.offset == start)
+			split = end;
+
+		new_key.offset = split;
+		ret = btrfs_duplicate_item(trans, root, path, &new_key);
+		if (ret == -EAGAIN) {
+			btrfs_release_path(root, path);
+			goto again;
 		}
+		BUG_ON(ret < 0);
 
-		fi = btrfs_item_ptr(leaf, del_slot - 1,
+		leaf = path->nodes[0];
+		fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
 				    struct btrfs_file_extent_item);
-		btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
 		btrfs_set_file_extent_num_bytes(leaf, fi,
-						extent_end - key.offset);
+						split - key.offset);
+
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+
+		btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
+		btrfs_set_file_extent_num_bytes(leaf, fi,
+						extent_end - split);
 		btrfs_mark_buffer_dirty(leaf);
 
-		ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+		ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
+					   root->root_key.objectid,
+					   inode->i_ino, orig_offset);
 		BUG_ON(ret);
-		goto release;
-	} else if (split == start) {
-		if (locked_end < extent_end) {
-			ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-					locked_end, extent_end - 1, GFP_NOFS);
-			if (!ret) {
-				btrfs_release_path(root, path);
-				lock_extent(&BTRFS_I(inode)->io_tree,
-					locked_end, extent_end - 1, GFP_NOFS);
-				locked_end = extent_end;
-				goto again;
-			}
-			locked_end = extent_end;
+
+		if (split == start) {
+			key.offset = start;
+		} else {
+			BUG_ON(start != key.offset);
+			path->slots[0]--;
+			extent_end = end;
 		}
-		btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset);
-	} else  {
-		BUG_ON(key.offset != start);
-		key.offset = split;
-		btrfs_set_file_extent_offset(leaf, fi, key.offset -
-					     orig_offset);
-		btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split);
-		btrfs_set_item_key_safe(trans, root, path, &key);
-		extent_end = split;
-	}
-
-	if (extent_end == end) {
-		split_end = 0;
-		extent_type = BTRFS_FILE_EXTENT_REG;
+		recow = 1;
 	}
-	if (extent_end == end && split == start) {
-		other_start = end;
-		other_end = 0;
-		if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			path->slots[0]++;
-			fi = btrfs_item_ptr(leaf, path->slots[0],
-					    struct btrfs_file_extent_item);
-			key.offset = split;
-			btrfs_set_item_key_safe(trans, root, path, &key);
-			btrfs_set_file_extent_offset(leaf, fi, key.offset -
-						     orig_offset);
-			btrfs_set_file_extent_num_bytes(leaf, fi,
-							other_end - split);
-			goto done;
+
+	other_start = end;
+	other_end = 0;
+	if (extent_mergeable(leaf, path->slots[0] + 1,
+			     inode->i_ino, bytenr, orig_offset,
+			     &other_start, &other_end)) {
+		if (recow) {
+			btrfs_release_path(root, path);
+			goto again;
 		}
+		extent_end = other_end;
+		del_slot = path->slots[0] + 1;
+		del_nr++;
+		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+					0, root->root_key.objectid,
+					inode->i_ino, orig_offset);
+		BUG_ON(ret);
 	}
-	if (extent_end == end && split == end) {
-		other_start = 0;
-		other_end = start;
-		if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			path->slots[0]--;
-			fi = btrfs_item_ptr(leaf, path->slots[0],
-					    struct btrfs_file_extent_item);
-			btrfs_set_file_extent_num_bytes(leaf, fi, extent_end -
-							other_start);
-			goto done;
+	other_start = 0;
+	other_end = start;
+	if (extent_mergeable(leaf, path->slots[0] - 1,
+			     inode->i_ino, bytenr, orig_offset,
+			     &other_start, &other_end)) {
+		if (recow) {
+			btrfs_release_path(root, path);
+			goto again;
 		}
+		key.offset = other_start;
+		del_slot = path->slots[0];
+		del_nr++;
+		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+					0, root->root_key.objectid,
+					inode->i_ino, orig_offset);
+		BUG_ON(ret);
 	}
+	if (del_nr == 0) {
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+			   struct btrfs_file_extent_item);
+		btrfs_set_file_extent_type(leaf, fi,
+					   BTRFS_FILE_EXTENT_REG);
+		btrfs_mark_buffer_dirty(leaf);
+	} else {
+		fi = btrfs_item_ptr(leaf, del_slot - 1,
+			   struct btrfs_file_extent_item);
+		btrfs_set_file_extent_type(leaf, fi,
+					   BTRFS_FILE_EXTENT_REG);
+		btrfs_set_file_extent_num_bytes(leaf, fi,
+						extent_end - key.offset);
+		btrfs_mark_buffer_dirty(leaf);
 
-	btrfs_mark_buffer_dirty(leaf);
-
-	ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
-				   root->root_key.objectid,
-				   inode->i_ino, orig_offset);
-	BUG_ON(ret);
-	btrfs_release_path(root, path);
-
-	key.offset = start;
-	ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi));
-	BUG_ON(ret);
-
-	leaf = path->nodes[0];
-	fi = btrfs_item_ptr(leaf, path->slots[0],
-			    struct btrfs_file_extent_item);
-	btrfs_set_file_extent_generation(leaf, fi, trans->transid);
-	btrfs_set_file_extent_type(leaf, fi, extent_type);
-	btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr);
-	btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
-	btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset);
-	btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset);
-	btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
-	btrfs_set_file_extent_compression(leaf, fi, 0);
-	btrfs_set_file_extent_encryption(leaf, fi, 0);
-	btrfs_set_file_extent_other_encoding(leaf, fi, 0);
-done:
-	btrfs_mark_buffer_dirty(leaf);
-
-release:
-	btrfs_release_path(root, path);
-	if (split_end && split == start) {
-		split = end;
-		goto again;
-	}
-	if (locked_end > end) {
-		unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
-			      GFP_NOFS);
+		ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+		BUG_ON(ret);
 	}
+out:
 	btrfs_free_path(path);
 	return 0;
 }
@@ -1210,7 +1135,7 @@
 	}
 	mutex_lock(&dentry->d_inode->i_mutex);
 out:
-	return ret > 0 ? EIO : ret;
+	return ret > 0 ? -EIO : ret;
 }
 
 static const struct vm_operations_struct btrfs_file_vm_ops = {
--- linux-ec2-2.6.32.orig/fs/btrfs/ctree.c
+++ linux-ec2-2.6.32/fs/btrfs/ctree.c
@@ -37,6 +37,11 @@
 			      struct extent_buffer *src_buf);
 static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		   struct btrfs_path *path, int level, int slot);
+static int setup_items_for_insert(struct btrfs_trans_handle *trans,
+			struct btrfs_root *root, struct btrfs_path *path,
+			struct btrfs_key *cpu_key, u32 *data_size,
+			u32 total_data, u32 total_size, int nr);
+
 
 struct btrfs_path *btrfs_alloc_path(void)
 {
@@ -451,9 +456,8 @@
 		extent_buffer_get(cow);
 		spin_unlock(&root->node_lock);
 
-		btrfs_free_extent(trans, root, buf->start, buf->len,
-				  parent_start, root->root_key.objectid,
-				  level, 0);
+		btrfs_free_tree_block(trans, root, buf->start, buf->len,
+				parent_start, root->root_key.objectid, level);
 		free_extent_buffer(buf);
 		add_root_to_dirty_list(root);
 	} else {
@@ -468,9 +472,8 @@
 		btrfs_set_node_ptr_generation(parent, parent_slot,
 					      trans->transid);
 		btrfs_mark_buffer_dirty(parent);
-		btrfs_free_extent(trans, root, buf->start, buf->len,
-				  parent_start, root->root_key.objectid,
-				  level, 0);
+		btrfs_free_tree_block(trans, root, buf->start, buf->len,
+				parent_start, root->root_key.objectid, level);
 	}
 	if (unlock_orig)
 		btrfs_tree_unlock(buf);
@@ -1030,8 +1033,8 @@
 		btrfs_tree_unlock(mid);
 		/* once for the path */
 		free_extent_buffer(mid);
-		ret = btrfs_free_extent(trans, root, mid->start, mid->len,
-					0, root->root_key.objectid, level, 1);
+		ret = btrfs_free_tree_block(trans, root, mid->start, mid->len,
+					    0, root->root_key.objectid, level);
 		/* once for the root ptr */
 		free_extent_buffer(mid);
 		return ret;
@@ -1095,10 +1098,10 @@
 				       1);
 			if (wret)
 				ret = wret;
-			wret = btrfs_free_extent(trans, root, bytenr,
-						 blocksize, 0,
-						 root->root_key.objectid,
-						 level, 0);
+			wret = btrfs_free_tree_block(trans, root,
+						     bytenr, blocksize, 0,
+						     root->root_key.objectid,
+						     level);
 			if (wret)
 				ret = wret;
 		} else {
@@ -1143,9 +1146,8 @@
 		wret = del_ptr(trans, root, path, level + 1, pslot);
 		if (wret)
 			ret = wret;
-		wret = btrfs_free_extent(trans, root, bytenr, blocksize,
-					 0, root->root_key.objectid,
-					 level, 0);
+		wret = btrfs_free_tree_block(trans, root, bytenr, blocksize,
+					 0, root->root_key.objectid, level);
 		if (wret)
 			ret = wret;
 	} else {
@@ -2997,75 +2999,85 @@
 	return ret;
 }
 
-/*
- * This function splits a single item into two items,
- * giving 'new_key' to the new item and splitting the
- * old one at split_offset (from the start of the item).
- *
- * The path may be released by this operation.  After
- * the split, the path is pointing to the old item.  The
- * new item is going to be in the same node as the old one.
- *
- * Note, the item being split must be smaller enough to live alone on
- * a tree block with room for one extra struct btrfs_item
- *
- * This allows us to split the item in place, keeping a lock on the
- * leaf the entire time.
- */
-int btrfs_split_item(struct btrfs_trans_handle *trans,
-		     struct btrfs_root *root,
-		     struct btrfs_path *path,
-		     struct btrfs_key *new_key,
-		     unsigned long split_offset)
+static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
+					 struct btrfs_root *root,
+					 struct btrfs_path *path, int ins_len)
 {
-	u32 item_size;
+	struct btrfs_key key;
 	struct extent_buffer *leaf;
-	struct btrfs_key orig_key;
-	struct btrfs_item *item;
-	struct btrfs_item *new_item;
-	int ret = 0;
-	int slot;
-	u32 nritems;
-	u32 orig_offset;
-	struct btrfs_disk_key disk_key;
-	char *buf;
+	struct btrfs_file_extent_item *fi;
+	u64 extent_len = 0;
+	u32 item_size;
+	int ret;
 
 	leaf = path->nodes[0];
-	btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
-	if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item))
-		goto split;
+	btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+
+	BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY &&
+	       key.type != BTRFS_EXTENT_CSUM_KEY);
+
+	if (btrfs_leaf_free_space(root, leaf) >= ins_len)
+		return 0;
 
 	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+	if (key.type == BTRFS_EXTENT_DATA_KEY) {
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		extent_len = btrfs_file_extent_num_bytes(leaf, fi);
+	}
 	btrfs_release_path(root, path);
 
-	path->search_for_split = 1;
 	path->keep_locks = 1;
-
-	ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1);
+	path->search_for_split = 1;
+	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 	path->search_for_split = 0;
+	if (ret < 0)
+		goto err;
 
+	ret = -EAGAIN;
+	leaf = path->nodes[0];
 	/* if our item isn't there or got smaller, return now */
-	if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0],
-							path->slots[0])) {
-		path->keep_locks = 0;
-		return -EAGAIN;
+	if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
+		goto err;
+
+	if (key.type == BTRFS_EXTENT_DATA_KEY) {
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		if (extent_len != btrfs_file_extent_num_bytes(leaf, fi))
+			goto err;
 	}
 
 	btrfs_set_path_blocking(path);
-	ret = split_leaf(trans, root, &orig_key, path,
-			 sizeof(struct btrfs_item), 1);
-	path->keep_locks = 0;
+	ret = split_leaf(trans, root, &key, path, ins_len, 1);
 	BUG_ON(ret);
 
+	path->keep_locks = 0;
 	btrfs_unlock_up_safe(path, 1);
+	return 0;
+err:
+	path->keep_locks = 0;
+	return ret;
+}
+
+static noinline int split_item(struct btrfs_trans_handle *trans,
+			       struct btrfs_root *root,
+			       struct btrfs_path *path,
+			       struct btrfs_key *new_key,
+			       unsigned long split_offset)
+{
+	struct extent_buffer *leaf;
+	struct btrfs_item *item;
+	struct btrfs_item *new_item;
+	int slot;
+	char *buf;
+	u32 nritems;
+	u32 item_size;
+	u32 orig_offset;
+	struct btrfs_disk_key disk_key;
+
 	leaf = path->nodes[0];
 	BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 
-split:
-	/*
-	 * make sure any changes to the path from split_leaf leave it
-	 * in a blocking state
-	 */
 	btrfs_set_path_blocking(path);
 
 	item = btrfs_item_nr(leaf, path->slots[0]);
@@ -3073,19 +3085,19 @@
 	item_size = btrfs_item_size(leaf, item);
 
 	buf = kmalloc(item_size, GFP_NOFS);
+	if (!buf)
+		return -ENOMEM;
+
 	read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
 			    path->slots[0]), item_size);
-	slot = path->slots[0] + 1;
-	leaf = path->nodes[0];
 
+	slot = path->slots[0] + 1;
 	nritems = btrfs_header_nritems(leaf);
-
 	if (slot != nritems) {
 		/* shift the items */
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
-			      btrfs_item_nr_offset(slot),
-			      (nritems - slot) * sizeof(struct btrfs_item));
-
+				btrfs_item_nr_offset(slot),
+				(nritems - slot) * sizeof(struct btrfs_item));
 	}
 
 	btrfs_cpu_key_to_disk(&disk_key, new_key);
@@ -3113,16 +3125,81 @@
 			    item_size - split_offset);
 	btrfs_mark_buffer_dirty(leaf);
 
-	ret = 0;
-	if (btrfs_leaf_free_space(root, leaf) < 0) {
-		btrfs_print_leaf(root, leaf);
-		BUG();
-	}
+	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
 	kfree(buf);
+	return 0;
+}
+
+/*
+ * This function splits a single item into two items,
+ * giving 'new_key' to the new item and splitting the
+ * old one at split_offset (from the start of the item).
+ *
+ * The path may be released by this operation.  After
+ * the split, the path is pointing to the old item.  The
+ * new item is going to be in the same node as the old one.
+ *
+ * Note, the item being split must be smaller enough to live alone on
+ * a tree block with room for one extra struct btrfs_item
+ *
+ * This allows us to split the item in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_split_item(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     struct btrfs_path *path,
+		     struct btrfs_key *new_key,
+		     unsigned long split_offset)
+{
+	int ret;
+	ret = setup_leaf_for_split(trans, root, path,
+				   sizeof(struct btrfs_item));
+	if (ret)
+		return ret;
+
+	ret = split_item(trans, root, path, new_key, split_offset);
 	return ret;
 }
 
 /*
+ * This function duplicate a item, giving 'new_key' to the new item.
+ * It guarantees both items live in the same tree leaf and the new item
+ * is contiguous with the original item.
+ *
+ * This allows us to split file extent in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 struct btrfs_key *new_key)
+{
+	struct extent_buffer *leaf;
+	int ret;
+	u32 item_size;
+
+	leaf = path->nodes[0];
+	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+	ret = setup_leaf_for_split(trans, root, path,
+				   item_size + sizeof(struct btrfs_item));
+	if (ret)
+		return ret;
+
+	path->slots[0]++;
+	ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
+				     item_size, item_size +
+				     sizeof(struct btrfs_item), 1);
+	BUG_ON(ret);
+
+	leaf = path->nodes[0];
+	memcpy_extent_buffer(leaf,
+			     btrfs_item_ptr_offset(leaf, path->slots[0]),
+			     btrfs_item_ptr_offset(leaf, path->slots[0] - 1),
+			     item_size);
+	return 0;
+}
+
+/*
  * make the item pointed to by the path smaller.  new_size indicates
  * how small to make it, and from_end tells us if we just chop bytes
  * off the end of the item or if we shift the item to chop bytes off
@@ -3714,8 +3791,8 @@
 	 */
 	btrfs_unlock_up_safe(path, 0);
 
-	ret = btrfs_free_extent(trans, root, leaf->start, leaf->len,
-				0, root->root_key.objectid, 0, 0);
+	ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len,
+				    0, root->root_key.objectid, 0);
 	return ret;
 }
 /*
--- linux-ec2-2.6.32.orig/fs/btrfs/root-tree.c
+++ linux-ec2-2.6.32/fs/btrfs/root-tree.c
@@ -459,3 +459,21 @@
 	btrfs_free_path(path);
 	return 0;
 }
+
+/*
+ * Old btrfs forgets to init root_item->flags and root_item->byte_limit
+ * for subvolumes. To work around this problem, we steal a bit from
+ * root_item->inode_item->flags, and use it to indicate if those fields
+ * have been properly initialized.
+ */
+void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
+{
+	u64 inode_flags = le64_to_cpu(root_item->inode.flags);
+
+	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
+		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
+		root_item->inode.flags = cpu_to_le64(inode_flags);
+		root_item->flags = 0;
+		root_item->byte_limit = 0;
+	}
+}
--- linux-ec2-2.6.32.orig/fs/romfs/super.c
+++ linux-ec2-2.6.32/fs/romfs/super.c
@@ -544,6 +544,7 @@
 error_rsb_inval:
 	ret = -EINVAL;
 error_rsb:
+	kfree(rsb);
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/fs/nfs/super.c
+++ linux-ec2-2.6.32/fs/nfs/super.c
@@ -241,6 +241,7 @@
 static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
 static int nfs_xdev_get_sb(struct file_system_type *fs_type,
 		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static void nfs_put_super(struct super_block *);
 static void nfs_kill_super(struct super_block *);
 static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 
@@ -264,6 +265,7 @@
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
+	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -333,6 +335,7 @@
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
+	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs4_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -531,6 +534,22 @@
 	}
 }
 
+#ifdef CONFIG_NFS_V4
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+				    int showdefaults)
+{
+	struct nfs_client *clp = nfss->nfs_client;
+
+	seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
+	seq_printf(m, ",minorversion=%u", clp->cl_minorversion);
+}
+#else
+static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss,
+				    int showdefaults)
+{
+}
+#endif
+
 /*
  * Describe the mount options in force on this server representation
  */
@@ -592,13 +611,18 @@
 
 	if (version != 4)
 		nfs_show_mountd_options(m, nfss, showdefaults);
+	else
+		nfs_show_nfsv4_options(m, nfss, showdefaults);
 
-#ifdef CONFIG_NFS_V4
-	if (clp->rpc_ops->version == 4)
-		seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
-#endif
 	if (nfss->options & NFS_OPTION_FSCACHE)
 		seq_printf(m, ",fsc");
+
+	if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
+		if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
+			seq_printf(m, ",lookupcache=none");
+		else
+			seq_printf(m, ",lookupcache=pos");
+	}
 }
 
 /*
@@ -734,8 +758,6 @@
 
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (data) {
-		data->rsize		= NFS_MAX_FILE_IO_SIZE;
-		data->wsize		= NFS_MAX_FILE_IO_SIZE;
 		data->acregmin		= NFS_DEF_ACREGMIN;
 		data->acregmax		= NFS_DEF_ACREGMAX;
 		data->acdirmin		= NFS_DEF_ACDIRMIN;
@@ -1903,6 +1925,15 @@
 	if (error < 0)
 		goto out;
 
+	/*
+	 * noac is a special case. It implies -o sync, but that's not
+	 * necessarily reflected in the mtab options. do_remount_sb
+	 * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the
+	 * remount options, so we have to explicitly reset it.
+	 */
+	if (data->flags & NFS_MOUNT_NOAC)
+		*flags |= MS_SYNCHRONOUS;
+
 	/* compare new mount options with old ones */
 	error = nfs_compare_remount_data(nfss, data);
 out:
@@ -2198,6 +2229,17 @@
 }
 
 /*
+ * Ensure that we unregister the bdi before kill_anon_super
+ * releases the device name
+ */
+static void nfs_put_super(struct super_block *s)
+{
+	struct nfs_server *server = NFS_SB(s);
+
+	bdi_unregister(&server->backing_dev_info);
+}
+
+/*
  * Destroy an NFS2/3 superblock
  */
 static void nfs_kill_super(struct super_block *s)
@@ -2205,7 +2247,6 @@
 	struct nfs_server *server = NFS_SB(s);
 
 	kill_anon_super(s);
-	bdi_unregister(&server->backing_dev_info);
 	nfs_fscache_release_super_cookie(s);
 	nfs_free_server(server);
 }
--- linux-ec2-2.6.32.orig/fs/nfs/nfs4_fs.h
+++ linux-ec2-2.6.32/fs/nfs/nfs4_fs.h
@@ -141,6 +141,7 @@
 	NFS_O_RDWR_STATE,		/* OPEN stateid has read/write state */
 	NFS_STATE_RECLAIM_REBOOT,	/* OPEN stateid server rebooted */
 	NFS_STATE_RECLAIM_NOGRACE,	/* OPEN stateid needs to recover state */
+	NFS_STATE_POSIX_LOCKS,		/* Posix locks are supported */
 };
 
 struct nfs4_state {
--- linux-ec2-2.6.32.orig/fs/nfs/dir.c
+++ linux-ec2-2.6.32/fs/nfs/dir.c
@@ -837,6 +837,8 @@
 		/* If we have submounts, don't unhash ! */
 		if (have_submounts(dentry))
 			goto out_valid;
+		if (dentry->d_flags & DCACHE_DISCONNECTED)
+			goto out_valid;
 		shrink_dcache_parent(dentry);
 	}
 	d_drop(dentry);
@@ -1025,12 +1027,12 @@
 				res = NULL;
 				goto out;
 			/* This turned out not to be a regular file */
+			case -EISDIR:
 			case -ENOTDIR:
 				goto no_open;
 			case -ELOOP:
 				if (!(nd->intent.open.flags & O_NOFOLLOW))
 					goto no_open;
-			/* case -EISDIR: */
 			/* case -EINVAL: */
 			default:
 				goto out;
@@ -1797,7 +1799,7 @@
 	cache = nfs_access_search_rbtree(inode, cred);
 	if (cache == NULL)
 		goto out;
-	if (!nfs_have_delegation(inode, FMODE_READ) &&
+	if (!nfs_have_delegated_attributes(inode) &&
 	    !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
 		goto out_stale;
 	res->jiffies = cache->jiffies;
--- linux-ec2-2.6.32.orig/fs/nfs/delegation.h
+++ linux-ec2-2.6.32/fs/nfs/delegation.h
@@ -68,4 +68,10 @@
 }
 #endif
 
+static inline int nfs_have_delegated_attributes(struct inode *inode)
+{
+	return nfs_have_delegation(inode, FMODE_READ) &&
+		!(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED);
+}
+
 #endif
--- linux-ec2-2.6.32.orig/fs/nfs/pagelist.c
+++ linux-ec2-2.6.32/fs/nfs/pagelist.c
@@ -112,12 +112,10 @@
  */
 int nfs_set_page_tag_locked(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
-
 	if (!nfs_lock_request_dontget(req))
 		return 0;
 	if (req->wb_page != NULL)
-		radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+		radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
 	return 1;
 }
 
@@ -126,10 +124,10 @@
  */
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
-	struct nfs_inode *nfsi = NFS_I(inode);
-
 	if (req->wb_page != NULL) {
+		struct inode *inode = req->wb_context->path.dentry->d_inode;
+		struct nfs_inode *nfsi = NFS_I(inode);
+
 		spin_lock(&inode->i_lock);
 		radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
 		nfs_unlock_request(req);
@@ -142,16 +140,22 @@
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
- * Release page resources associated with a write request after it
- * has completed.
+ * Release page and open context resources associated with a read/write
+ * request after it has completed.
  */
 void nfs_clear_request(struct nfs_page *req)
 {
 	struct page *page = req->wb_page;
+	struct nfs_open_context *ctx = req->wb_context;
+
 	if (page != NULL) {
 		page_cache_release(page);
 		req->wb_page = NULL;
 	}
+	if (ctx != NULL) {
+		put_nfs_open_context(ctx);
+		req->wb_context = NULL;
+	}
 }
 
 
@@ -165,9 +169,8 @@
 {
 	struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
 
-	/* Release struct file or cached credential */
+	/* Release struct file and open context */
 	nfs_clear_request(req);
-	put_nfs_open_context(req->wb_context);
 	nfs_page_free(req);
 }
 
@@ -176,6 +179,12 @@
 	kref_put(&req->wb_kref, nfs_free_request);
 }
 
+static int nfs_wait_bit_uninterruptible(void *word)
+{
+	io_schedule();
+	return 0;
+}
+
 /**
  * nfs_wait_on_request - Wait for a request to complete.
  * @req: request to wait upon.
@@ -186,14 +195,9 @@
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-	int ret = 0;
-
-	if (!test_bit(PG_BUSY, &req->wb_flags))
-		goto out;
-	ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY,
-			nfs_wait_bit_killable, TASK_KILLABLE);
-out:
-	return ret;
+	return wait_on_bit(&req->wb_flags, PG_BUSY,
+			nfs_wait_bit_uninterruptible,
+			TASK_UNINTERRUPTIBLE);
 }
 
 /**
--- linux-ec2-2.6.32.orig/fs/nfs/nfs4xdr.c
+++ linux-ec2-2.6.32/fs/nfs/nfs4xdr.c
@@ -840,8 +840,8 @@
 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
 		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
 		*p++ = cpu_to_be32(0);
-		*p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
-		*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
+		*p++ = cpu_to_be32(iap->ia_atime.tv_sec);
+		*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
 	}
 	else if (iap->ia_valid & ATTR_ATIME) {
 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
@@ -2096,7 +2096,7 @@
 	encode_compound_hdr(&xdr, req, &hdr);
 	encode_sequence(&xdr, &args->seq_args, &hdr);
 	encode_putfh(&xdr, args->fh, &hdr);
-	replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1;
+	replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
 	encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
 
 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
@@ -4554,7 +4554,7 @@
 	 * If the server returns different values for sessionID, slotID or
 	 * sequence number, the server is looney tunes.
 	 */
-	status = -ESERVERFAULT;
+	status = -EREMOTEIO;
 
 	if (memcmp(id.data, res->sr_session->sess_id.data,
 		   NFS4_MAX_SESSIONID_LEN)) {
@@ -5678,7 +5678,7 @@
 	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
 	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
 	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
-	{ NFS4ERR_SERVERFAULT,	-ESERVERFAULT	},
+	{ NFS4ERR_SERVERFAULT,	-EREMOTEIO	},
 	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
 	{ NFS4ERR_LOCKED,	-EAGAIN		},
 	{ NFS4ERR_SYMLINK,	-ELOOP		},
@@ -5705,7 +5705,7 @@
 	}
 	if (stat <= 10000 || stat > 10100) {
 		/* The server is looney tunes. */
-		return -ESERVERFAULT;
+		return -EREMOTEIO;
 	}
 	/* If we cannot translate the error, the recovery routines should
 	 * handle it.
--- linux-ec2-2.6.32.orig/fs/nfs/write.c
+++ linux-ec2-2.6.32/fs/nfs/write.c
@@ -1485,7 +1485,6 @@
 static int nfs_write_mapping(struct address_space *mapping, int how)
 {
 	struct writeback_control wbc = {
-		.bdi = mapping->backing_dev_info,
 		.sync_mode = WB_SYNC_ALL,
 		.nr_to_write = LONG_MAX,
 		.range_start = 0,
@@ -1514,7 +1513,6 @@
 	loff_t range_start = page_offset(page);
 	loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
 	struct writeback_control wbc = {
-		.bdi = page->mapping->backing_dev_info,
 		.sync_mode = WB_SYNC_ALL,
 		.nr_to_write = LONG_MAX,
 		.range_start = range_start,
@@ -1542,6 +1540,7 @@
 			break;
 		}
 		ret = nfs_wait_on_request(req);
+		nfs_release_request(req);
 		if (ret < 0)
 			goto out;
 	}
@@ -1558,7 +1557,6 @@
 	loff_t range_start = page_offset(page);
 	loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
 	struct writeback_control wbc = {
-		.bdi = page->mapping->backing_dev_info,
 		.sync_mode = WB_SYNC_ALL,
 		.nr_to_write = LONG_MAX,
 		.range_start = range_start,
@@ -1612,15 +1610,16 @@
 	if (ret)
 		goto out_unlock;
 	page_cache_get(newpage);
+	spin_lock(&mapping->host->i_lock);
 	req->wb_page = newpage;
 	SetPagePrivate(newpage);
-	set_page_private(newpage, page_private(page));
+	set_page_private(newpage, (unsigned long)req);
 	ClearPagePrivate(page);
 	set_page_private(page, 0);
+	spin_unlock(&mapping->host->i_lock);
 	page_cache_release(page);
 out_unlock:
 	nfs_clear_page_tag_locked(req);
-	nfs_release_request(req);
 out:
 	return ret;
 }
--- linux-ec2-2.6.32.orig/fs/nfs/client.c
+++ linux-ec2-2.6.32/fs/nfs/client.c
@@ -273,7 +273,7 @@
 	    sin1->sin6_scope_id != sin2->sin6_scope_id)
 		return 0;
 
-	return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr);
+	return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr);
 }
 #else	/* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
 static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
@@ -965,6 +965,8 @@
 static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
 {
 	target->flags = source->flags;
+	target->rsize = source->rsize;
+	target->wsize = source->wsize;
 	target->acregmin = source->acregmin;
 	target->acregmax = source->acregmax;
 	target->acdirmin = source->acdirmin;
@@ -1283,7 +1285,8 @@
 
 	/* Initialise the client representation from the mount data */
 	server->flags = data->flags;
-	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR;
+	server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|
+		NFS_CAP_POSIX_LOCK;
 	server->options = data->options;
 
 	/* Get a client record */
--- linux-ec2-2.6.32.orig/fs/nfs/inode.c
+++ linux-ec2-2.6.32/fs/nfs/inode.c
@@ -759,7 +759,7 @@
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	if (nfs_have_delegation(inode, FMODE_READ))
+	if (nfs_have_delegated_attributes(inode))
 		return 0;
 	return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
 }
@@ -861,9 +861,10 @@
 	return ret;
 }
 
-static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
+	unsigned long ret = 0;
 
 	if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
 			&& (fattr->valid & NFS_ATTR_FATTR_CHANGE)
@@ -871,25 +872,32 @@
 		nfsi->change_attr = fattr->change_attr;
 		if (S_ISDIR(inode->i_mode))
 			nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+		ret |= NFS_INO_INVALID_ATTR;
 	}
 	/* If we have atomic WCC data, we may update some attributes */
 	if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
 			&& (fattr->valid & NFS_ATTR_FATTR_CTIME)
-			&& timespec_equal(&inode->i_ctime, &fattr->pre_ctime))
-			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+			&& timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
+		memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+		ret |= NFS_INO_INVALID_ATTR;
+	}
 
 	if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
 			&& (fattr->valid & NFS_ATTR_FATTR_MTIME)
 			&& timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
-			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
-			if (S_ISDIR(inode->i_mode))
-				nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+		if (S_ISDIR(inode->i_mode))
+			nfsi->cache_validity |= NFS_INO_INVALID_DATA;
+		ret |= NFS_INO_INVALID_ATTR;
 	}
 	if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE)
 			&& (fattr->valid & NFS_ATTR_FATTR_SIZE)
 			&& i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size)
-			&& nfsi->npages == 0)
-			i_size_write(inode, nfs_size_to_loff_t(fattr->size));
+			&& nfsi->npages == 0) {
+		i_size_write(inode, nfs_size_to_loff_t(fattr->size));
+		ret |= NFS_INO_INVALID_ATTR;
+	}
+	return ret;
 }
 
 /**
@@ -1183,7 +1191,7 @@
 			| NFS_INO_REVAL_PAGECACHE);
 
 	/* Do atomic weak cache consistency updates */
-	nfs_wcc_update_inode(inode, fattr);
+	invalid |= nfs_wcc_update_inode(inode, fattr);
 
 	/* More cache consistency checks */
 	if (fattr->valid & NFS_ATTR_FATTR_CHANGE) {
--- linux-ec2-2.6.32.orig/fs/nfs/dns_resolve.c
+++ linux-ec2-2.6.32/fs/nfs/dns_resolve.c
@@ -36,6 +36,19 @@
 };
 
 
+static void nfs_dns_ent_update(struct cache_head *cnew,
+		struct cache_head *ckey)
+{
+	struct nfs_dns_ent *new;
+	struct nfs_dns_ent *key;
+
+	new = container_of(cnew, struct nfs_dns_ent, h);
+	key = container_of(ckey, struct nfs_dns_ent, h);
+
+	memcpy(&new->addr, &key->addr, key->addrlen);
+	new->addrlen = key->addrlen;
+}
+
 static void nfs_dns_ent_init(struct cache_head *cnew,
 		struct cache_head *ckey)
 {
@@ -49,8 +62,7 @@
 	new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL);
 	if (new->hostname) {
 		new->namelen = key->namelen;
-		memcpy(&new->addr, &key->addr, key->addrlen);
-		new->addrlen = key->addrlen;
+		nfs_dns_ent_update(cnew, ckey);
 	} else {
 		new->namelen = 0;
 		new->addrlen = 0;
@@ -234,7 +246,7 @@
 	.cache_show = nfs_dns_show,
 	.match = nfs_dns_match,
 	.init = nfs_dns_ent_init,
-	.update = nfs_dns_ent_init,
+	.update = nfs_dns_ent_update,
 	.alloc = nfs_dns_ent_alloc,
 };
 
--- linux-ec2-2.6.32.orig/fs/nfs/nfs4state.c
+++ linux-ec2-2.6.32/fs/nfs/nfs4state.c
@@ -1228,7 +1228,7 @@
 	int status = 0;
 
 	/* Ensure exclusive access to NFSv4 state */
-	for(;;) {
+	do {
 		if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
 			/* We're going to have to re-establish a clientid */
 			status = nfs4_reclaim_lease(clp);
@@ -1304,7 +1304,7 @@
 			break;
 		if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
 			break;
-	}
+	} while (atomic_read(&clp->cl_count) > 1);
 	return;
 out_error:
 	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
--- linux-ec2-2.6.32.orig/fs/nfs/nfs2xdr.c
+++ linux-ec2-2.6.32/fs/nfs/nfs2xdr.c
@@ -699,7 +699,7 @@
 	{ NFSERR_BAD_COOKIE,	-EBADCOOKIE	},
 	{ NFSERR_NOTSUPP,	-ENOTSUPP	},
 	{ NFSERR_TOOSMALL,	-ETOOSMALL	},
-	{ NFSERR_SERVERFAULT,	-ESERVERFAULT	},
+	{ NFSERR_SERVERFAULT,	-EREMOTEIO	},
 	{ NFSERR_BADTYPE,	-EBADTYPE	},
 	{ NFSERR_JUKEBOX,	-EJUKEBOX	},
 	{ -1,			-EIO		}
--- linux-ec2-2.6.32.orig/fs/nfs/nfs4proc.c
+++ linux-ec2-2.6.32/fs/nfs/nfs4proc.c
@@ -1439,6 +1439,8 @@
 		nfs_post_op_update_inode(dir, o_res->dir_attr);
 	} else
 		nfs_refresh_inode(dir, o_res->dir_attr);
+	if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
+		server->caps &= ~NFS_CAP_POSIX_LOCK;
 	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
 		status = _nfs4_proc_open_confirm(data);
 		if (status != 0)
@@ -1573,6 +1575,8 @@
 	status = PTR_ERR(state);
 	if (IS_ERR(state))
 		goto err_opendata_put;
+	if (server->caps & NFS_CAP_POSIX_LOCK)
+		set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 	nfs4_opendata_put(opendata);
 	nfs4_put_state_owner(sp);
 	*res = state;
@@ -3129,6 +3133,35 @@
 	}
 }
 
+static int buf_to_pages_noslab(const void *buf, size_t buflen,
+		struct page **pages, unsigned int *pgbase)
+{
+	struct page *newpage, **spages;
+	int rc = 0;
+	size_t len;
+	spages = pages;
+
+	do {
+		len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
+		newpage = alloc_page(GFP_KERNEL);
+
+		if (newpage == NULL)
+			goto unwind;
+		memcpy(page_address(newpage), buf, len);
+                buf += len;
+                buflen -= len;
+		*pages++ = newpage;
+		rc++;
+	} while (buflen != 0);
+
+	return rc;
+
+unwind:
+	for(; rc > 0; rc--)
+		__free_page(spages[rc-1]);
+	return -ENOMEM;
+}
+
 struct nfs4_cached_acl {
 	int cached;
 	size_t len;
@@ -3295,13 +3328,23 @@
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 	};
-	int ret;
+	int ret, i;
 
 	if (!nfs4_server_supports_acls(server))
 		return -EOPNOTSUPP;
+	i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
+	if (i < 0)
+		return i;
 	nfs_inode_return_delegation(inode);
-	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
 	ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
+
+	/*
+	 * Free each page after tx, so the only ref left is
+	 * held by the network stack
+	 */
+	for (; i > 0; i--)
+		put_page(pages[i-1]);
+
 	nfs_access_zap_cache(inode);
 	nfs_zap_acl_cache(inode);
 	return ret;
@@ -3976,6 +4019,22 @@
 	.rpc_release = nfs4_lock_release,
 };
 
+static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct nfs4_state *state = lsp->ls_state;
+
+	switch (error) {
+	case -NFS4ERR_ADMIN_REVOKED:
+	case -NFS4ERR_BAD_STATEID:
+	case -NFS4ERR_EXPIRED:
+		if (new_lock_owner != 0 ||
+		   (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+			nfs4_state_mark_reclaim_nograce(clp, state);
+		lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED;
+	};
+}
+
 static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim)
 {
 	struct nfs4_lockdata *data;
@@ -4011,6 +4070,9 @@
 	ret = nfs4_wait_for_completion_rpc_task(task);
 	if (ret == 0) {
 		ret = data->rpc_status;
+		if (ret)
+			nfs4_handle_setlk_error(data->server, data->lsp,
+					data->arg.new_lock_owner, ret);
 	} else
 		data->cancelled = 1;
 	rpc_put_task(task);
@@ -4060,8 +4122,11 @@
 {
 	struct nfs_inode *nfsi = NFS_I(state->inode);
 	unsigned char fl_flags = request->fl_flags;
-	int status;
+	int status = -ENOLCK;
 
+	if ((fl_flags & FL_POSIX) &&
+			!test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
+		goto out;
 	/* Is this a delegated open? */
 	status = nfs4_set_lock_state(state, request);
 	if (status != 0)
--- linux-ec2-2.6.32.orig/fs/nfs/direct.c
+++ linux-ec2-2.6.32/fs/nfs/direct.c
@@ -342,6 +342,7 @@
 		data->res.fattr = &data->fattr;
 		data->res.eof = 0;
 		data->res.count = bytes;
+		nfs_fattr_init(&data->fattr);
 		msg.rpc_argp = &data->args;
 		msg.rpc_resp = &data->res;
 
@@ -400,15 +401,18 @@
 		pos += vec->iov_len;
 	}
 
+	/*
+	 * If no bytes were started, return the error, and let the
+	 * generic layer handle the completion.
+	 */
+	if (requested_bytes == 0) {
+		nfs_direct_req_release(dreq);
+		return result < 0 ? result : -EIO;
+	}
+
 	if (put_dreq(dreq))
 		nfs_direct_complete(dreq);
-
-	if (requested_bytes != 0)
-		return 0;
-
-	if (result < 0)
-		return result;
-	return -EIO;
+	return 0;
 }
 
 static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
@@ -575,6 +579,7 @@
 	data->res.count = 0;
 	data->res.fattr = &data->fattr;
 	data->res.verf = &data->verf;
+	nfs_fattr_init(&data->fattr);
 
 	NFS_PROTO(data->inode)->commit_setup(data, &msg);
 
@@ -766,6 +771,7 @@
 		data->res.fattr = &data->fattr;
 		data->res.count = bytes;
 		data->res.verf = &data->verf;
+		nfs_fattr_init(&data->fattr);
 
 		task_setup_data.task = &data->task;
 		task_setup_data.callback_data = data;
@@ -826,15 +832,18 @@
 		pos += vec->iov_len;
 	}
 
+	/*
+	 * If no bytes were started, return the error, and let the
+	 * generic layer handle the completion.
+	 */
+	if (requested_bytes == 0) {
+		nfs_direct_req_release(dreq);
+		return result < 0 ? result : -EIO;
+	}
+
 	if (put_dreq(dreq))
 		nfs_direct_write_complete(dreq, dreq->inode);
-
-	if (requested_bytes != 0)
-		return 0;
-
-	if (result < 0)
-		return result;
-	return -EIO;
+	return 0;
 }
 
 static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
--- linux-ec2-2.6.32.orig/fs/nfs/file.c
+++ linux-ec2-2.6.32/fs/nfs/file.c
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/aio.h>
+#include <linux/gfp.h>
+#include <linux/swap.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -218,7 +220,7 @@
 	have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags);
 	if (have_error)
 		ret = xchg(&ctx->error, 0);
-	if (!ret)
+	if (!ret && status < 0)
 		ret = status;
 	return ret;
 }
@@ -484,8 +486,19 @@
  */
 static int nfs_release_page(struct page *page, gfp_t gfp)
 {
+	struct address_space *mapping = page->mapping;
+
 	dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
 
+	/* Only do I/O if gfp is a superset of GFP_KERNEL */
+	if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
+		int how = FLUSH_SYNC;
+
+		/* Don't let kswapd deadlock waiting for OOM RPC calls */
+		if (current_is_kswapd())
+			how = 0;
+		nfs_commit_inode(mapping->host, how);
+	}
 	/* If PagePrivate() is set, then the page is not freeable */
 	if (PagePrivate(page))
 		return 0;
@@ -667,6 +680,7 @@
 {
 	struct inode *inode = filp->f_mapping->host;
 	int status = 0;
+	unsigned int saved_type = fl->fl_type;
 
 	/* Try local locking first */
 	posix_test_lock(filp, fl);
@@ -674,6 +688,7 @@
 		/* found a conflict */
 		goto out;
 	}
+	fl->fl_type = saved_type;
 
 	if (nfs_have_delegation(inode, FMODE_READ))
 		goto out_noconflict;
--- linux-ec2-2.6.32.orig/fs/nfs/mount_clnt.c
+++ linux-ec2-2.6.32/fs/nfs/mount_clnt.c
@@ -120,7 +120,7 @@
 	{ .status = MNT3ERR_INVAL,		.errno = -EINVAL,	},
 	{ .status = MNT3ERR_NAMETOOLONG,	.errno = -ENAMETOOLONG,	},
 	{ .status = MNT3ERR_NOTSUPP,		.errno = -ENOTSUPP,	},
-	{ .status = MNT3ERR_SERVERFAULT,	.errno = -ESERVERFAULT,	},
+	{ .status = MNT3ERR_SERVERFAULT,	.errno = -EREMOTEIO,	},
 };
 
 struct mountres {
@@ -503,13 +503,13 @@
 
 static struct rpc_version mnt_version1 = {
 	.number		= 1,
-	.nrprocs	= 2,
+	.nrprocs	= ARRAY_SIZE(mnt_procedures),
 	.procs		= mnt_procedures,
 };
 
 static struct rpc_version mnt_version3 = {
 	.number		= 3,
-	.nrprocs	= 2,
+	.nrprocs	= ARRAY_SIZE(mnt3_procedures),
 	.procs		= mnt3_procedures,
 };
 
--- linux-ec2-2.6.32.orig/fs/nfs/fscache.c
+++ linux-ec2-2.6.32/fs/nfs/fscache.c
@@ -354,12 +354,11 @@
  */
 int nfs_fscache_release_page(struct page *page, gfp_t gfp)
 {
-	struct nfs_inode *nfsi = NFS_I(page->mapping->host);
-	struct fscache_cookie *cookie = nfsi->fscache;
-
-	BUG_ON(!cookie);
-
 	if (PageFsCache(page)) {
+		struct nfs_inode *nfsi = NFS_I(page->mapping->host);
+		struct fscache_cookie *cookie = nfsi->fscache;
+
+		BUG_ON(!cookie);
 		dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
 			 cookie, page, nfsi);
 
--- linux-ec2-2.6.32.orig/fs/proc/array.c
+++ linux-ec2-2.6.32/fs/proc/array.c
@@ -82,7 +82,6 @@
 #include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/tracehook.h>
-#include <linux/swapops.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -173,7 +172,7 @@
 		if (tracer)
 			tpid = task_pid_nr_ns(tracer, ns);
 	}
-	cred = get_cred((struct cred *) __task_cred(p));
+	cred = get_task_cred(p);
 	seq_printf(m,
 		"State:\t%s\n"
 		"Tgid:\t%d\n"
@@ -322,94 +321,6 @@
 			p->nivcsw);
 }
 
-#ifdef CONFIG_MMU
-
-struct stack_stats {
-	struct vm_area_struct *vma;
-	unsigned long	startpage;
-	unsigned long	usage;
-};
-
-static int stack_usage_pte_range(pmd_t *pmd, unsigned long addr,
-				unsigned long end, struct mm_walk *walk)
-{
-	struct stack_stats *ss = walk->private;
-	struct vm_area_struct *vma = ss->vma;
-	pte_t *pte, ptent;
-	spinlock_t *ptl;
-	int ret = 0;
-
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	for (; addr != end; pte++, addr += PAGE_SIZE) {
-		ptent = *pte;
-
-#ifdef CONFIG_STACK_GROWSUP
-		if (pte_present(ptent) || is_swap_pte(ptent))
-			ss->usage = addr - ss->startpage + PAGE_SIZE;
-#else
-		if (pte_present(ptent) || is_swap_pte(ptent)) {
-			ss->usage = ss->startpage - addr + PAGE_SIZE;
-			pte++;
-			ret = 1;
-			break;
-		}
-#endif
-	}
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
-	return ret;
-}
-
-static inline unsigned long get_stack_usage_in_bytes(struct vm_area_struct *vma,
-				struct task_struct *task)
-{
-	struct stack_stats ss;
-	struct mm_walk stack_walk = {
-		.pmd_entry = stack_usage_pte_range,
-		.mm = vma->vm_mm,
-		.private = &ss,
-	};
-
-	if (!vma->vm_mm || is_vm_hugetlb_page(vma))
-		return 0;
-
-	ss.vma = vma;
-	ss.startpage = task->stack_start & PAGE_MASK;
-	ss.usage = 0;
-
-#ifdef CONFIG_STACK_GROWSUP
-	walk_page_range(KSTK_ESP(task) & PAGE_MASK, vma->vm_end,
-		&stack_walk);
-#else
-	walk_page_range(vma->vm_start, (KSTK_ESP(task) & PAGE_MASK) + PAGE_SIZE,
-		&stack_walk);
-#endif
-	return ss.usage;
-}
-
-static inline void task_show_stack_usage(struct seq_file *m,
-						struct task_struct *task)
-{
-	struct vm_area_struct	*vma;
-	struct mm_struct	*mm = get_task_mm(task);
-
-	if (mm) {
-		down_read(&mm->mmap_sem);
-		vma = find_vma(mm, task->stack_start);
-		if (vma)
-			seq_printf(m, "Stack usage:\t%lu kB\n",
-				get_stack_usage_in_bytes(vma, task) >> 10);
-
-		up_read(&mm->mmap_sem);
-		mmput(mm);
-	}
-}
-#else
-static void task_show_stack_usage(struct seq_file *m, struct task_struct *task)
-{
-}
-#endif		/* CONFIG_MMU */
-
 int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
 			struct pid *pid, struct task_struct *task)
 {
@@ -425,11 +336,7 @@
 	task_sig(m, task);
 	task_cap(m, task);
 	cpuset_task_status_allowed(m, task);
-#if defined(CONFIG_S390)
-	task_show_regs(m, task);
-#endif
 	task_context_switch_counts(m, task);
-	task_show_stack_usage(m, task);
 	return 0;
 }
 
@@ -495,7 +402,6 @@
 
 		/* add up live thread stats at the group level */
 		if (whole) {
-			struct task_cputime cputime;
 			struct task_struct *t = task;
 			do {
 				min_flt += t->min_flt;
@@ -506,9 +412,7 @@
 
 			min_flt += sig->min_flt;
 			maj_flt += sig->maj_flt;
-			thread_group_cputime(task, &cputime);
-			utime = cputime.utime;
-			stime = cputime.stime;
+			thread_group_times(task, &utime, &stime);
 			gtime = cputime_add(gtime, sig->gtime);
 		}
 
@@ -569,9 +473,9 @@
 		vsize,
 		mm ? get_mm_rss(mm) : 0,
 		rsslim,
-		mm ? mm->start_code : 0,
-		mm ? mm->end_code : 0,
-		(permitted && mm) ? task->stack_start : 0,
+		mm ? (permitted ? mm->start_code : 1) : 0,
+		mm ? (permitted ? mm->end_code : 1) : 0,
+		(permitted && mm) ? mm->start_stack : 0,
 		esp,
 		eip,
 		/* The signal information here is obsolete.
--- linux-ec2-2.6.32.orig/fs/proc/Makefile
+++ linux-ec2-2.6.32/fs/proc/Makefile
@@ -26,3 +26,4 @@
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
 proc-$(CONFIG_PRINTK)	+= kmsg.o
 proc-$(CONFIG_PROC_PAGE_MONITOR)	+= page.o
+proc-y	+= version_signature.o
--- linux-ec2-2.6.32.orig/fs/proc/version_signature.c
+++ linux-ec2-2.6.32/fs/proc/version_signature.c
@@ -0,0 +1,31 @@
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/utsname.h>
+
+static int version_signature_proc_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "%s\n", CONFIG_VERSION_SIGNATURE);
+	return 0;
+}
+
+static int version_signature_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, version_signature_proc_show, NULL);
+}
+
+static const struct file_operations version_signature_proc_fops = {
+	.open		= version_signature_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init proc_version_signature_init(void)
+{
+	proc_create("version_signature", 0, NULL, &version_signature_proc_fops);
+	return 0;
+}
+module_init(proc_version_signature_init);
--- linux-ec2-2.6.32.orig/fs/proc/task_mmu.c
+++ linux-ec2-2.6.32/fs/proc/task_mmu.c
@@ -206,6 +206,7 @@
 	int flags = vma->vm_flags;
 	unsigned long ino = 0;
 	unsigned long long pgoff = 0;
+	unsigned long start;
 	dev_t dev = 0;
 	int len;
 
@@ -216,8 +217,14 @@
 		pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
 	}
 
+	/* We don't show the stack guard page in /proc/maps */
+	start = vma->vm_start;
+	if (vma->vm_flags & VM_GROWSDOWN)
+		if (!vma_stack_continue(vma->vm_prev, vma->vm_start))
+			start += PAGE_SIZE;
+
 	seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
-			vma->vm_start,
+			start,
 			vma->vm_end,
 			flags & VM_READ ? 'r' : '-',
 			flags & VM_WRITE ? 'w' : '-',
@@ -237,31 +244,12 @@
 		const char *name = arch_vma_name(vma);
 		if (!name) {
 			if (mm) {
-				if (vma->vm_start <= mm->start_brk &&
-						vma->vm_end >= mm->brk) {
+				if (vma->vm_start <= mm->brk &&
+						vma->vm_end >= mm->start_brk) {
 					name = "[heap]";
 				} else if (vma->vm_start <= mm->start_stack &&
 					   vma->vm_end >= mm->start_stack) {
 					name = "[stack]";
-				} else {
-					unsigned long stack_start;
-					struct proc_maps_private *pmp;
-
-					pmp = m->private;
-					stack_start = pmp->task->stack_start;
-
-					if (vma->vm_start <= stack_start &&
-					    vma->vm_end >= stack_start) {
-						pad_len_spaces(m, len);
-						seq_printf(m,
-						 "[threadstack:%08lx]",
-#ifdef CONFIG_STACK_GROWSUP
-						 vma->vm_end - stack_start
-#else
-						 stack_start - vma->vm_start
-#endif
-						);
-					}
 				}
 			} else {
 				name = "[vdso]";
--- linux-ec2-2.6.32.orig/fs/proc/kmsg.c
+++ linux-ec2-2.6.32/fs/proc/kmsg.c
@@ -12,37 +12,37 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/fs.h>
+#include <linux/syslog.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern wait_queue_head_t log_wait;
 
-extern int do_syslog(int type, char __user *bug, int count);
-
 static int kmsg_open(struct inode * inode, struct file * file)
 {
-	return do_syslog(1,NULL,0);
+	return do_syslog(1, NULL, 0, SYSLOG_FROM_FILE);
 }
 
 static int kmsg_release(struct inode * inode, struct file * file)
 {
-	(void) do_syslog(0,NULL,0);
+	(void) do_syslog(0, NULL, 0, SYSLOG_FROM_FILE);
 	return 0;
 }
 
 static ssize_t kmsg_read(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-	if ((file->f_flags & O_NONBLOCK) && !do_syslog(9, NULL, 0))
+	if ((file->f_flags & O_NONBLOCK) &&
+	    !do_syslog(9, NULL, 0, SYSLOG_FROM_FILE))
 		return -EAGAIN;
-	return do_syslog(2, buf, count);
+	return do_syslog(2, buf, count, SYSLOG_FROM_FILE);
 }
 
 static unsigned int kmsg_poll(struct file *file, poll_table *wait)
 {
 	poll_wait(file, &log_wait, wait);
-	if (do_syslog(9, NULL, 0))
+	if (do_syslog(9, NULL, 0, SYSLOG_FROM_FILE))
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
--- linux-ec2-2.6.32.orig/fs/proc/base.c
+++ linux-ec2-2.6.32/fs/proc/base.c
@@ -442,12 +442,13 @@
 unsigned long badness(struct task_struct *p, unsigned long uptime);
 static int proc_oom_score(struct task_struct *task, char *buffer)
 {
-	unsigned long points;
+	unsigned long points = 0;
 	struct timespec uptime;
 
 	do_posix_clock_monotonic_gettime(&uptime);
 	read_lock(&tasklist_lock);
-	points = badness(task->group_leader, uptime.tv_sec);
+	if (pid_alive(task))
+		points = badness(task, uptime.tv_sec);
 	read_unlock(&tasklist_lock);
 	return sprintf(buffer, "%lu\n", points);
 }
@@ -2304,16 +2305,30 @@
 {
 	struct pid_namespace *ns = dentry->d_sb->s_fs_info;
 	pid_t tgid = task_tgid_nr_ns(current, ns);
-	char tmp[PROC_NUMBUF];
-	if (!tgid)
-		return ERR_PTR(-ENOENT);
-	sprintf(tmp, "%d", task_tgid_nr_ns(current, ns));
-	return ERR_PTR(vfs_follow_link(nd,tmp));
+	char *name = ERR_PTR(-ENOENT);
+	if (tgid) {
+		name = __getname();
+		if (!name)
+			name = ERR_PTR(-ENOMEM);
+		else
+			sprintf(name, "%d", tgid);
+	}
+	nd_set_link(nd, name);
+	return NULL;
+}
+
+static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
+				void *cookie)
+{
+	char *s = nd_get_link(nd);
+	if (!IS_ERR(s))
+		__putname(s);
 }
 
 static const struct inode_operations proc_self_inode_operations = {
 	.readlink	= proc_self_readlink,
 	.follow_link	= proc_self_follow_link,
+	.put_link	= proc_self_put_link,
 };
 
 /*
@@ -2791,11 +2806,16 @@
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-	struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
+	unsigned int nr;
+	struct task_struct *reaper;
 	struct tgid_iter iter;
 	struct pid_namespace *ns;
 
+	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+		goto out_no_task;
+	nr = filp->f_pos - FIRST_PROCESS_ENTRY;
+
+	reaper = get_proc_task(filp->f_path.dentry->d_inode);
 	if (!reaper)
 		goto out_no_task;
 
@@ -2829,7 +2849,7 @@
  */
 static const struct pid_entry tid_base_stuff[] = {
 	DIR("fd",        S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
-	DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fd_operations),
+	DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
 	REG("environ",   S_IRUSR, proc_environ_operations),
 	INF("auxv",      S_IRUSR, proc_pid_auxv),
 	ONE("status",    S_IRUGO, proc_pid_status),
--- linux-ec2-2.6.32.orig/fs/cifs/connect.c
+++ linux-ec2-2.6.32/fs/cifs/connect.c
@@ -799,8 +799,7 @@
 cifs_parse_mount_options(char *options, const char *devname,
 			 struct smb_vol *vol)
 {
-	char *value;
-	char *data;
+	char *value, *data, *end;
 	unsigned int  temp_len, i, j;
 	char separator[2];
 	short int override_uid = -1;
@@ -843,6 +842,7 @@
 	if (!options)
 		return 1;
 
+	end = options + strlen(options);
 	if (strncmp(options, "sep=", 4) == 0) {
 		if (options[4] != 0) {
 			separator[0] = options[4];
@@ -907,6 +907,7 @@
 			the only illegal character in a password is null */
 
 			if ((value[temp_len] == 0) &&
+			    (value + temp_len < end) &&
 			    (value[temp_len+1] == separator[0])) {
 				/* reinsert comma */
 				value[temp_len] = separator[0];
@@ -2230,6 +2231,11 @@
 			      0 /* not legacy */, cifs_sb->local_nls,
 			      cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+	if (rc == -EOPNOTSUPP || rc == -EINVAL)
+		rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
+				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+				  CIFS_MOUNT_MAP_SPECIAL_CHR);
 	kfree(pfile_info);
 	return rc;
 }
@@ -2287,12 +2293,12 @@
 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 		char *mount_data_global, const char *devname)
 {
-	int rc = 0;
+	int rc;
 	int xid;
 	struct smb_vol *volume_info;
-	struct cifsSesInfo *pSesInfo = NULL;
-	struct cifsTconInfo *tcon = NULL;
-	struct TCP_Server_Info *srvTcp = NULL;
+	struct cifsSesInfo *pSesInfo;
+	struct cifsTconInfo *tcon;
+	struct TCP_Server_Info *srvTcp;
 	char   *full_path;
 	char *mount_data = mount_data_global;
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -2301,6 +2307,10 @@
 	int referral_walks_count = 0;
 try_mount_again:
 #endif
+	rc = 0;
+	tcon = NULL;
+	pSesInfo = NULL;
+	srvTcp = NULL;
 	full_path = NULL;
 
 	xid = GetXid();
@@ -2528,7 +2538,7 @@
 
 remote_path_check:
 	/* check if a whole path (including prepath) is not remote */
-	if (!rc && cifs_sb->prepathlen && tcon) {
+	if (!rc && tcon) {
 		/* build_path_to_root works only when we have a valid tcon */
 		full_path = cifs_build_path_to_root(cifs_sb);
 		if (full_path == NULL) {
@@ -2597,6 +2607,7 @@
 
 			cleanup_volume_info(&volume_info);
 			referral_walks_count++;
+			FreeXid(xid);
 			goto try_mount_again;
 		}
 #else /* No DFS support, return error on mount */
--- linux-ec2-2.6.32.orig/fs/cifs/readdir.c
+++ linux-ec2-2.6.32/fs/cifs/readdir.c
@@ -666,6 +666,7 @@
 					   min(len, max_len), nlt,
 					   cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
+		pqst->len -= nls_nullsize(nlt);
 	} else {
 		pqst->name = filename;
 		pqst->len = len;
--- linux-ec2-2.6.32.orig/fs/cifs/sess.c
+++ linux-ec2-2.6.32/fs/cifs/sess.c
@@ -723,15 +723,7 @@
 
 		/* calculate session key */
 		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
-		if (first_time) /* should this be moved into common code
-				   with similar ntlmv2 path? */
-		/*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
-				response BB FIXME, v2_sess_key); */
-
-		/* copy session key */
-
-	/*	memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
-		bcc_ptr += LM2_SESS_KEY_SIZE; */
+		/* FIXME: calculate MAC key */
 		memcpy(bcc_ptr, (char *)v2_sess_key,
 		       sizeof(struct ntlmv2_resp));
 		bcc_ptr += sizeof(struct ntlmv2_resp);
@@ -914,7 +906,9 @@
 	}
 
 	/* BB check if Unicode and decode strings */
-	if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
+	if (bytes_remaining == 0) {
+		/* no string area to decode, do nothing */
+	} else if (smb_buf->Flags2 & SMBFLG2_UNICODE) {
 		/* unicode string area must be word-aligned */
 		if (((unsigned long) bcc_ptr - (unsigned long) smb_buf) % 2) {
 			++bcc_ptr;
--- linux-ec2-2.6.32.orig/fs/cifs/dir.c
+++ linux-ec2-2.6.32/fs/cifs/dir.c
@@ -183,13 +183,14 @@
 }
 
 int cifs_posix_open(char *full_path, struct inode **pinode,
-		    struct vfsmount *mnt, int mode, int oflags,
-		    __u32 *poplock, __u16 *pnetfid, int xid)
+			struct vfsmount *mnt, struct super_block *sb,
+			int mode, int oflags,
+			__u32 *poplock, __u16 *pnetfid, int xid)
 {
 	int rc;
 	FILE_UNIX_BASIC_INFO *presp_data;
 	__u32 posix_flags = 0;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	struct cifs_fattr fattr;
 
 	cFYI(1, ("posix open %s", full_path));
@@ -241,7 +242,7 @@
 
 	/* get new inode and set it up */
 	if (*pinode == NULL) {
-		*pinode = cifs_iget(mnt->mnt_sb, &fattr);
+		*pinode = cifs_iget(sb, &fattr);
 		if (!*pinode) {
 			rc = -ENOMEM;
 			goto posix_open_ret;
@@ -250,7 +251,8 @@
 		cifs_fattr_to_inode(*pinode, &fattr);
 	}
 
-	cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
+	if (mnt)
+		cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
 
 posix_open_ret:
 	kfree(presp_data);
@@ -314,13 +316,14 @@
 	if (nd && (nd->flags & LOOKUP_OPEN))
 		oflags = nd->intent.open.flags;
 	else
-		oflags = FMODE_READ;
+		oflags = FMODE_READ | SMB_O_CREAT;
 
 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-		rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
-				     mode, oflags, &oplock, &fileHandle, xid);
+		rc = cifs_posix_open(full_path, &newinode,
+			nd ? nd->path.mnt : NULL,
+			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
 		/* EIO could indicate that (posix open) operation is not
 		   supported, despite what server claimed in capability
 		   negotation.  EREMOTE indicates DFS junction, which is not
@@ -677,6 +680,7 @@
 		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
 		     (nd->intent.open.flags & O_CREAT)) {
 			rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
+					parent_dir_inode->i_sb,
 					nd->intent.open.create_mode,
 					nd->intent.open.flags, &oplock,
 					&fileHandle, xid);
--- linux-ec2-2.6.32.orig/fs/cifs/cifsfs.c
+++ linux-ec2-2.6.32/fs/cifs/cifsfs.c
@@ -1033,7 +1033,7 @@
 		goto out_unregister_filesystem;
 #endif
 #ifdef CONFIG_CIFS_DFS_UPCALL
-	rc = register_key_type(&key_type_dns_resolver);
+	rc = cifs_init_dns_resolver();
 	if (rc)
 		goto out_unregister_key_type;
 #endif
@@ -1045,7 +1045,7 @@
 
  out_unregister_resolver_key:
 #ifdef CONFIG_CIFS_DFS_UPCALL
-	unregister_key_type(&key_type_dns_resolver);
+	cifs_exit_dns_resolver();
  out_unregister_key_type:
 #endif
 #ifdef CONFIG_CIFS_UPCALL
@@ -1071,7 +1071,7 @@
 	cifs_proc_clean();
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	cifs_dfs_release_automount_timer();
-	unregister_key_type(&key_type_dns_resolver);
+	cifs_exit_dns_resolver();
 #endif
 #ifdef CONFIG_CIFS_UPCALL
 	unregister_key_type(&cifs_spnego_key_type);
--- linux-ec2-2.6.32.orig/fs/cifs/inode.c
+++ linux-ec2-2.6.32/fs/cifs/inode.c
@@ -610,6 +610,16 @@
 	if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
 		return 0;
 
+	/*
+	 * uh oh -- it's a directory. We can't use it since hardlinked dirs are
+	 * verboten. Disable serverino and return it as if it were found, the
+	 * caller can discard it, generate a uniqueid and retry the find
+	 */
+	if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
+		fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
+		cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
+	}
+
 	return 1;
 }
 
@@ -629,15 +639,22 @@
 	unsigned long hash;
 	struct inode *inode;
 
+retry_iget5_locked:
 	cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
 
 	/* hash down to 32-bits on 32-bit arch */
 	hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
 
 	inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
-
-	/* we have fattrs in hand, update the inode */
 	if (inode) {
+		/* was there a problematic inode number collision? */
+		if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
+			iput(inode);
+			fattr->cf_uniqueid = iunique(sb, ROOT_I);
+			fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
+			goto retry_iget5_locked;
+		}
+
 		cifs_fattr_to_inode(inode, fattr);
 		if (sb->s_flags & MS_NOATIME)
 			inode->i_flags |= S_NOATIME | S_NOCMTIME;
@@ -671,8 +688,10 @@
 		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
 						xid, NULL);
 
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
+	if (!inode) {
+		inode = ERR_PTR(rc);
+		goto out;
+	}
 
 	if (rc && cifs_sb->tcon->ipc) {
 		cFYI(1, ("ipc connection - fake read inode"));
@@ -683,13 +702,11 @@
 		inode->i_uid = cifs_sb->mnt_uid;
 		inode->i_gid = cifs_sb->mnt_gid;
 	} else if (rc) {
-		kfree(full_path);
-		_FreeXid(xid);
 		iget_failed(inode);
-		return ERR_PTR(rc);
+		inode = ERR_PTR(rc);
 	}
 
-
+out:
 	kfree(full_path);
 	/* can not call macro FreeXid here since in a void func
 	 * TODO: This is no longer true
@@ -1267,6 +1284,10 @@
 	if (rc == 0 || rc != -ETXTBSY)
 		return rc;
 
+	/* open-file renames don't work across directories */
+	if (to_dentry->d_parent != from_dentry->d_parent)
+		return rc;
+
 	/* open the file to be renamed -- we need DELETE perms */
 	rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
 			 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
--- linux-ec2-2.6.32.orig/fs/cifs/dns_resolve.h
+++ linux-ec2-2.6.32/fs/cifs/dns_resolve.h
@@ -24,8 +24,10 @@
 #define _DNS_RESOLVE_H
 
 #ifdef __KERNEL__
-#include <linux/key-type.h>
-extern struct key_type key_type_dns_resolver;
+#include <linux/module.h>
+
+extern int __init cifs_init_dns_resolver(void);
+extern void cifs_exit_dns_resolver(void);
 extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr);
 #endif /* KERNEL */
 
--- linux-ec2-2.6.32.orig/fs/cifs/cifsglob.h
+++ linux-ec2-2.6.32/fs/cifs/cifsglob.h
@@ -499,6 +499,7 @@
 #define CIFS_FATTR_DFS_REFERRAL		0x1
 #define CIFS_FATTR_DELETE_PENDING	0x2
 #define CIFS_FATTR_NEED_REVAL		0x4
+#define CIFS_FATTR_INO_COLLISION	0x8
 
 struct cifs_fattr {
 	u32		cf_flags;
--- linux-ec2-2.6.32.orig/fs/cifs/cifsproto.h
+++ linux-ec2-2.6.32/fs/cifs/cifsproto.h
@@ -95,8 +95,10 @@
 				__u16 fileHandle, struct file *file,
 				struct vfsmount *mnt, unsigned int oflags);
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
-			   struct vfsmount *mnt, int mode, int oflags,
-			   __u32 *poplock, __u16 *pnetfid, int xid);
+				struct vfsmount *mnt,
+				struct super_block *sb,
+				int mode, int oflags,
+				__u32 *poplock, __u16 *pnetfid, int xid);
 extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
 				     FILE_UNIX_BASIC_INFO *info,
 				     struct cifs_sb_info *cifs_sb);
@@ -321,7 +323,7 @@
 			const __u16 netfid, const __u64 len,
 			const __u64 offset, const __u32 numUnlock,
 			const __u32 numLock, const __u8 lockType,
-			const bool waitFlag);
+			const bool waitFlag, const __u8 oplock_level);
 extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 			const __u16 smb_file_id, const int get_flag,
 			const __u64 len, struct file_lock *,
--- linux-ec2-2.6.32.orig/fs/cifs/dns_resolve.c
+++ linux-ec2-2.6.32/fs/cifs/dns_resolve.c
@@ -23,12 +23,16 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
 #include <keys/user-type.h>
 #include "dns_resolve.h"
 #include "cifsglob.h"
 #include "cifsproto.h"
 #include "cifs_debug.h"
 
+static const struct cred *dns_resolver_cache;
+
 /* Checks if supplied name is IP address
  * returns:
  * 		1 - name is IP
@@ -93,6 +97,7 @@
 int
 dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
 {
+	const struct cred *saved_cred;
 	int rc = -EAGAIN;
 	struct key *rkey = ERR_PTR(-EAGAIN);
 	char *name;
@@ -132,8 +137,15 @@
 		goto skip_upcall;
 	}
 
+	saved_cred = override_creds(dns_resolver_cache);
 	rkey = request_key(&key_type_dns_resolver, name, "");
+	revert_creds(saved_cred);
 	if (!IS_ERR(rkey)) {
+		if (!(rkey->perm & KEY_USR_VIEW)) {
+			down_read(&rkey->sem);
+			rkey->perm |= KEY_USR_VIEW;
+			up_read(&rkey->sem);
+		}
 		len = rkey->type_data.x[0];
 		data = rkey->payload.data;
 	} else {
@@ -164,4 +176,61 @@
 	return rc;
 }
 
+int __init cifs_init_dns_resolver(void)
+{
+	struct cred *cred;
+	struct key *keyring;
+	int ret;
+
+	printk(KERN_NOTICE "Registering the %s key type\n",
+	       key_type_dns_resolver.name);
+
+	/* create an override credential set with a special thread keyring in
+	 * which DNS requests are cached
+	 *
+	 * this is used to prevent malicious redirections from being installed
+	 * with add_key().
+	 */
+	cred = prepare_kernel_cred(NULL);
+	if (!cred)
+		return -ENOMEM;
+
+	keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred,
+			    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+			    KEY_USR_VIEW | KEY_USR_READ,
+			    KEY_ALLOC_NOT_IN_QUOTA);
+	if (IS_ERR(keyring)) {
+		ret = PTR_ERR(keyring);
+		goto failed_put_cred;
+	}
+
+	ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
+	if (ret < 0)
+		goto failed_put_key;
+
+	ret = register_key_type(&key_type_dns_resolver);
+	if (ret < 0)
+		goto failed_put_key;
+
+	/* instruct request_key() to use this special keyring as a cache for
+	 * the results it looks up */
+	cred->thread_keyring = keyring;
+	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+	dns_resolver_cache = cred;
+	return 0;
+
+failed_put_key:
+	key_put(keyring);
+failed_put_cred:
+	put_cred(cred);
+	return ret;
+}
 
+void cifs_exit_dns_resolver(void)
+{
+	key_revoke(dns_resolver_cache->thread_keyring);
+	unregister_key_type(&key_type_dns_resolver);
+	put_cred(dns_resolver_cache);
+	printk(KERN_NOTICE "Unregistered %s key type\n",
+	       key_type_dns_resolver.name);
+}
--- linux-ec2-2.6.32.orig/fs/cifs/cifssmb.c
+++ linux-ec2-2.6.32/fs/cifs/cifssmb.c
@@ -1430,6 +1430,8 @@
 	__u32 bytes_sent;
 	__u16 byte_count;
 
+	*nbytes = 0;
+
 	/* cFYI(1, ("write at %lld %d bytes", offset, count));*/
 	if (tcon->ses == NULL)
 		return -ECONNABORTED;
@@ -1512,11 +1514,18 @@
 	cifs_stats_inc(&tcon->num_writes);
 	if (rc) {
 		cFYI(1, ("Send error in write = %d", rc));
-		*nbytes = 0;
 	} else {
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
+
+		/*
+		 * Mask off high 16 bits when bytes written as returned by the
+		 * server is greater than bytes requested by the client. Some
+		 * OS/2 servers are known to set incorrect CountHigh values.
+		 */
+		if (*nbytes > count)
+			*nbytes &= 0xFFFF;
 	}
 
 	cifs_buf_release(pSMB);
@@ -1605,6 +1614,14 @@
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
+
+		/*
+		 * Mask off high 16 bits when bytes written as returned by the
+		 * server is greater than bytes requested by the client. OS/2
+		 * servers are known to set incorrect CountHigh values.
+		 */
+		if (*nbytes > count)
+			*nbytes &= 0xFFFF;
 	}
 
 /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
@@ -1624,7 +1641,8 @@
 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 	    const __u16 smb_file_id, const __u64 len,
 	    const __u64 offset, const __u32 numUnlock,
-	    const __u32 numLock, const __u8 lockType, const bool waitFlag)
+	    const __u32 numLock, const __u8 lockType,
+	    const bool waitFlag, const __u8 oplock_level)
 {
 	int rc = 0;
 	LOCK_REQ *pSMB = NULL;
@@ -1652,6 +1670,7 @@
 	pSMB->NumberOfLocks = cpu_to_le16(numLock);
 	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
 	pSMB->LockType = lockType;
+	pSMB->OplockLevel = oplock_level;
 	pSMB->AndXCommand = 0xFF;	/* none */
 	pSMB->Fid = smb_file_id; /* netfid stays le */
 
--- linux-ec2-2.6.32.orig/fs/cifs/file.c
+++ linux-ec2-2.6.32/fs/cifs/file.c
@@ -295,10 +295,12 @@
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
 		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
+		oflags |= SMB_O_CREAT;
 		/* can not refresh inode info since size could be stale */
 		rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
-				     cifs_sb->mnt_file_mode /* ignored */,
-				     oflags, &oplock, &netfid, xid);
+				inode->i_sb,
+				cifs_sb->mnt_file_mode /* ignored */,
+				oflags, &oplock, &netfid, xid);
 		if (rc == 0) {
 			cFYI(1, ("posix open succeeded"));
 			/* no need for special case handling of setting mode
@@ -510,8 +512,9 @@
 		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
 		/* can not refresh inode info since size could be stale */
 		rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
-				     cifs_sb->mnt_file_mode /* ignored */,
-				     oflags, &oplock, &netfid, xid);
+				inode->i_sb,
+				cifs_sb->mnt_file_mode /* ignored */,
+				oflags, &oplock, &netfid, xid);
 		if (rc == 0) {
 			cFYI(1, ("posix reopen succeeded"));
 			goto reopen_success;
@@ -822,12 +825,12 @@
 
 		/* BB we could chain these into one lock request BB */
 		rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start,
-				 0, 1, lockType, 0 /* wait flag */ );
+				 0, 1, lockType, 0 /* wait flag */, 0);
 		if (rc == 0) {
 			rc = CIFSSMBLock(xid, tcon, netfid, length,
 					 pfLock->fl_start, 1 /* numUnlock */ ,
 					 0 /* numLock */ , lockType,
-					 0 /* wait flag */ );
+					 0 /* wait flag */, 0);
 			pfLock->fl_type = F_UNLCK;
 			if (rc != 0)
 				cERROR(1, ("Error unlocking previously locked "
@@ -870,8 +873,8 @@
 
 		if (numLock) {
 			rc = CIFSSMBLock(xid, tcon, netfid, length,
-					pfLock->fl_start,
-					0, numLock, lockType, wait_flag);
+					 pfLock->fl_start, 0, numLock, lockType,
+					 wait_flag, 0);
 
 			if (rc == 0) {
 				/* For Windows locks we must store them. */
@@ -891,9 +894,9 @@
 						(pfLock->fl_start + length) >=
 						(li->offset + li->length)) {
 					stored_rc = CIFSSMBLock(xid, tcon,
-							netfid,
-							li->length, li->offset,
-							1, 0, li->type, false);
+							netfid, li->length,
+							li->offset, 1, 0,
+							li->type, false, 0);
 					if (stored_rc)
 						rc = stored_rc;
 
@@ -2311,7 +2314,8 @@
 	 */
 	if (!cfile->closePend && !cfile->oplock_break_cancelled) {
 		rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
-				 LOCKING_ANDX_OPLOCK_RELEASE, false);
+				 LOCKING_ANDX_OPLOCK_RELEASE, false,
+				 cinode->clientCanCacheRead ? 1 : 0);
 		cFYI(1, ("Oplock release rc = %d", rc));
 	}
 }
--- linux-ec2-2.6.32.orig/fs/jbd2/journal.c
+++ linux-ec2-2.6.32/fs/jbd2/journal.c
@@ -78,6 +78,7 @@
 EXPORT_SYMBOL(jbd2_journal_ack_err);
 EXPORT_SYMBOL(jbd2_journal_clear_err);
 EXPORT_SYMBOL(jbd2_log_wait_commit);
+EXPORT_SYMBOL(jbd2_log_start_commit);
 EXPORT_SYMBOL(jbd2_journal_start_commit);
 EXPORT_SYMBOL(jbd2_journal_force_commit_nested);
 EXPORT_SYMBOL(jbd2_journal_wipe);
@@ -358,6 +359,10 @@
 
 		jbd_unlock_bh_state(bh_in);
 		tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
+		if (!tmp) {
+			jbd2_journal_put_journal_head(new_jh);
+			return -ENOMEM;
+		}
 		jbd_lock_bh_state(bh_in);
 		if (jh_in->b_frozen_data) {
 			jbd2_free(tmp, bh_in->b_size);
@@ -1248,6 +1253,13 @@
 	if (jbd2_journal_recover(journal))
 		goto recovery_error;
 
+	if (journal->j_failed_commit) {
+		printk(KERN_ERR "JBD2: journal transaction %u on %s "
+		       "is corrupt.\n", journal->j_failed_commit,
+		       journal->j_devname);
+		return -EIO;
+	}
+
 	/* OK, we've finished with the dynamic journal bits:
 	 * reinitialise the dynamic contents of the superblock in memory
 	 * and reset them on disk. */
@@ -2103,7 +2115,8 @@
 {
 	jbd2_debugfs_dir = debugfs_create_dir("jbd2", NULL);
 	if (jbd2_debugfs_dir)
-		jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME, S_IRUGO,
+		jbd2_debug = debugfs_create_u8(JBD2_DEBUG_NAME,
+					       S_IRUGO | S_IWUSR,
 					       jbd2_debugfs_dir,
 					       &jbd2_journal_enable_debug);
 }
--- linux-ec2-2.6.32.orig/fs/jbd2/checkpoint.c
+++ linux-ec2-2.6.32/fs/jbd2/checkpoint.c
@@ -22,6 +22,7 @@
 #include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/blkdev.h>
 #include <trace/events/jbd2.h>
 
 /*
@@ -515,6 +516,20 @@
 	journal->j_tail_sequence = first_tid;
 	journal->j_tail = blocknr;
 	spin_unlock(&journal->j_state_lock);
+
+	/*
+	 * If there is an external journal, we need to make sure that
+	 * any data blocks that were recently written out --- perhaps
+	 * by jbd2_log_do_checkpoint() --- are flushed out before we
+	 * drop the transactions from the external journal.  It's
+	 * unlikely this will be necessary, especially with a
+	 * appropriately sized journal, but we need this to guarantee
+	 * correctness.  Fortunately jbd2_cleanup_journal_tail()
+	 * doesn't get called all that often.
+	 */
+	if ((journal->j_fs_dev != journal->j_dev) &&
+	    (journal->j_flags & JBD2_BARRIER))
+		blkdev_issue_flush(journal->j_fs_dev, NULL);
 	if (!(journal->j_flags & JBD2_ABORT))
 		jbd2_journal_update_superblock(journal, 1);
 	return 0;
--- linux-ec2-2.6.32.orig/fs/jbd2/commit.c
+++ linux-ec2-2.6.32/fs/jbd2/commit.c
@@ -259,6 +259,7 @@
 			ret = err;
 		spin_lock(&journal->j_list_lock);
 		J_ASSERT(jinode->i_transaction == commit_transaction);
+		commit_transaction->t_flushed_data_blocks = 1;
 		jinode->i_flags &= ~JI_COMMIT_RUNNING;
 		wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
 	}
@@ -636,6 +637,10 @@
 		JBUFFER_TRACE(jh, "ph3: write metadata");
 		flags = jbd2_journal_write_metadata_buffer(commit_transaction,
 						      jh, &new_jh, blocknr);
+		if (flags < 0) {
+			jbd2_journal_abort(journal, flags);
+			continue;
+		}
 		set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
 		wbuf[bufs++] = jh2bh(new_jh);
 
@@ -704,8 +709,17 @@
 		}
 	}
 
-	/* Done it all: now write the commit record asynchronously. */
+	/*
+	 * If the journal is not located on the file system device,
+	 * then we must flush the file system device before we issue
+	 * the commit record
+	 */
+	if (commit_transaction->t_flushed_data_blocks &&
+	    (journal->j_fs_dev != journal->j_dev) &&
+	    (journal->j_flags & JBD2_BARRIER))
+		blkdev_issue_flush(journal->j_fs_dev, NULL);
 
+	/* Done it all: now write the commit record asynchronously. */
 	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
 				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
 		err = journal_submit_commit_record(journal, commit_transaction,
@@ -716,13 +730,6 @@
 			blkdev_issue_flush(journal->j_dev, NULL);
 	}
 
-	/*
-	 * This is the right place to wait for data buffers both for ASYNC
-	 * and !ASYNC commit. If commit is ASYNC, we need to wait only after
-	 * the commit block went to disk (which happens above). If commit is
-	 * SYNC, we need to wait for data buffers before we start writing
-	 * commit block, which happens below in such setting.
-	 */
 	err = journal_finish_inode_data_buffers(journal, commit_transaction);
 	if (err) {
 		printk(KERN_WARNING
--- linux-ec2-2.6.32.orig/tools/perf/builtin-timechart.c
+++ linux-ec2-2.6.32/tools/perf/builtin-timechart.c
@@ -275,7 +275,7 @@
 static int
 process_comm_event(event_t *event)
 {
-	pid_set_comm(event->comm.pid, event->comm.comm);
+	pid_set_comm(event->comm.tid, event->comm.comm);
 	return 0;
 }
 static int
--- linux-ec2-2.6.32.orig/tools/perf/Makefile
+++ linux-ec2-2.6.32/tools/perf/Makefile
@@ -2,6 +2,7 @@
 all::
 
 # Define V=1 to have a more verbose compile.
+# Define V=2 to have an even more verbose compile.
 #
 # Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
 # or vsnprintf() return -1 instead of number of characters which would
@@ -145,6 +146,10 @@
 # Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call
 # your external grep (e.g., if your system lacks grep, if its grep is
 # broken, or spawning external process is slower than built-in grep perf has).
+#
+# Define LDFLAGS=-static to build a static binary.
+#
+# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
 
 PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
 	@$(SHELL_PATH) util/PERF-VERSION-GEN
@@ -157,20 +162,6 @@
 uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
 uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
 
-#
-# Add -m32 for cross-builds:
-#
-ifdef NO_64BIT
-  MBITS := -m32
-else
-  #
-  # If we're on a 64-bit kernel, use -m64:
-  #
-  ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
-    MBITS := -m64
-  endif
-endif
-
 # CFLAGS and LDFLAGS are for the users to override from the command line.
 
 #
@@ -200,8 +191,15 @@
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
 
-CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
-LDFLAGS = -lpthread -lrt -lelf -lm
+ifeq ("$(origin DEBUG)", "command line")
+  PERF_DEBUG = $(DEBUG)
+endif
+ifndef PERF_DEBUG
+  CFLAGS_OPTIMIZE = -O6
+endif
+
+CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+EXTLIBS = -lpthread -lrt -lelf -lm
 ALL_CFLAGS = $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
@@ -218,7 +216,10 @@
 # runtime figures out where they are based on the path to the executable.
 # This can help installing the suite in a relocatable way.
 
+# Make the path relative to DESTDIR, not to prefix
+ifndef DESTDIR
 prefix = $(HOME)
+endif
 bindir_relative = bin
 bindir = $(prefix)/$(bindir_relative)
 mandir = share/man
@@ -235,7 +236,6 @@
 ETC_PERFCONFIG = etc/perfconfig
 endif
 lib = lib
-# DESTDIR=
 
 export prefix bindir sharedir sysconfdir
 
@@ -252,6 +252,21 @@
 # explicitly what architecture to check for. Fix this up for yours..
 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
+ifeq ($(V), 2)
+	QUIET_STDERR = ">/dev/null"
+else
+	QUIET_STDERR = ">/dev/null 2>&1"
+endif
+
+BITBUCKET = "/dev/null"
+
+ifneq ($(shell sh -c "(echo '\#include <stdio.h>'; echo 'int main(void) { return puts(\"hi\"); }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) "$(QUIET_STDERR)" && echo y"), y)
+	BITBUCKET = .perf.dev.null
+endif
+
+ifeq ($(shell sh -c "echo 'int foo(void) {char X[2]; return 3;}' | $(CC) -x c -c -Werror -fstack-protector-all - -o $(BITBUCKET) "$(QUIET_STDERR)" && echo y"), y)
+  CFLAGS := $(CFLAGS) -fstack-protector-all
+endif
 
 
 ### --- END CONFIGURATION SECTION ---
@@ -421,36 +436,43 @@
 	PTHREAD_LIBS =
 endif
 
-ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
-	ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+	msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
+endif
+
+ifeq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+	ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
 		BASIC_CFLAGS += -DLIBELF_NO_MMAP
 	endif
 else
-	msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
+	msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
 endif
 
 ifdef NO_DEMANGLE
 	BASIC_CFLAGS += -DNO_DEMANGLE
+else ifdef HAVE_CPLUS_DEMANGLE
+	EXTLIBS += -liberty
+	BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
 else
-	has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y")
+	has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y")
 
 	ifeq ($(has_bfd),y)
 		EXTLIBS += -lbfd
 	else
-		has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
+		has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty "$(QUIET_STDERR)" && echo y")
 		ifeq ($(has_bfd_iberty),y)
 			EXTLIBS += -lbfd -liberty
 		else
-			has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y")
+			has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd -liberty -lz "$(QUIET_STDERR)" && echo y")
 			ifeq ($(has_bfd_iberty_z),y)
 				EXTLIBS += -lbfd -liberty -lz
 			else
-				has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -liberty > /dev/null 2>&1 && echo y")
+				has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -liberty "$(QUIET_STDERR)" && echo y")
 				ifeq ($(has_cplus_demangle),y)
 					EXTLIBS += -liberty
 					BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
 				else
-					msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
+					msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
 					BASIC_CFLAGS += -DNO_DEMANGLE
 				endif
 			endif
@@ -693,7 +715,7 @@
 
 SHELL = $(SHELL_PATH)
 
-all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) PERF-BUILD-OPTIONS
+all:: .perf.dev.null shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) PERF-BUILD-OPTIONS
 ifneq (,$X)
 	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
 endif
@@ -996,6 +1018,11 @@
 .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
 .PHONY: .FORCE-PERF-BUILD-OPTIONS
 
+.perf.dev.null:
+		touch .perf.dev.null
+
+.INTERMEDIATE:	.perf.dev.null
+
 ### Make sure built-ins do not have dups and listed in perf.c
 #
 check-builtins::
--- linux-ec2-2.6.32.orig/tools/perf/Documentation/Makefile
+++ linux-ec2-2.6.32/tools/perf/Documentation/Makefile
@@ -24,7 +24,10 @@
 DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT))
 DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
 
+# Make the path relative to DESTDIR, not prefix
+ifndef DESTDIR
 prefix?=$(HOME)
+endif
 bindir?=$(prefix)/bin
 htmldir?=$(prefix)/share/doc/perf-doc
 pdfdir?=$(prefix)/share/doc/perf-doc
@@ -32,7 +35,6 @@
 man1dir=$(mandir)/man1
 man5dir=$(mandir)/man5
 man7dir=$(mandir)/man7
-# DESTDIR=
 
 ASCIIDOC=asciidoc
 ASCIIDOC_EXTRA = --unsafe
--- linux-ec2-2.6.32.orig/tools/perf/util/callchain.h
+++ linux-ec2-2.6.32/tools/perf/util/callchain.h
@@ -48,6 +48,10 @@
 	INIT_LIST_HEAD(&node->brothers);
 	INIT_LIST_HEAD(&node->children);
 	INIT_LIST_HEAD(&node->val);
+
+	node->children_hit = 0;
+	node->parent = NULL;
+	node->hit = 0;
 }
 
 static inline u64 cumul_hits(struct callchain_node *node)
--- linux-ec2-2.6.32.orig/Documentation/kernel-parameters.txt
+++ linux-ec2-2.6.32/Documentation/kernel-parameters.txt
@@ -241,7 +241,7 @@
 
 	acpi_sleep=	[HW,ACPI] Sleep options
 			Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
-				  old_ordering, s4_nonvs }
+				  old_ordering, s4_nonvs, sci_force_enable }
 			See Documentation/power/video.txt for information on
 			s3_bios and s3_mode.
 			s3_beep is for debugging; it makes the PC's speaker beep
@@ -254,6 +254,9 @@
 			of _PTS is used by default).
 			s4_nonvs prevents the kernel from saving/restoring the
 			ACPI NVS memory during hibernation.
+			sci_force_enable causes the kernel to set SCI_EN directly
+			on resume from S1/S3 (which is against the ACPI spec,
+			but some broken systems don't work without it).
 
 	acpi_use_timer_override [HW,ACPI]
 			Use timer override. For some broken Nvidia NF5 boards
@@ -803,6 +806,24 @@
 	gpt		[EFI] Forces disk with valid GPT signature but
 			invalid Protective MBR to be treated as GPT.
 
+	guestdev=	[PCI,ACPI,XEN]
+			Format: {<device path>|<sbdf>}][,{<device path>|<sbdf>}[,...]]
+			Format of device path: <hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]][+iomul]
+			Format of sbdf: [<segment>:]<bus>:<dev>.<func>[+iomul]
+			Specifies PCI device for guest domain.
+			If PCI-PCI bridge is specified, all PCI devices
+			behind PCI-PCI bridge are reserved.
+			+iomul means that this PCI function will share
+			IO ports with other +iomul functions under same
+			switch. NOTE: if +iomul is specfied, all the functions
+			of the device will share IO ports.
+
+	guestiomuldev=	[PCI,ACPI,XEN]
+			Format: [sbd][,<sbd>][,...]
+			Format of sbdf: [<segment>:]<bus>:<dev>
+			Note: function shouldn't be specified.
+			Specifies PCI device for IO port multiplexing driver.
+
 	gvp11=		[HW,SCSI]
 
 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
@@ -875,6 +896,7 @@
 	i8042.panicblink=
 			[HW] Frequency with which keyboard LEDs should blink
 			     when kernel panics (default is 0.5 sec)
+	i8042.notimeout	[HW] Ignore timeout condition signalled by conroller
 	i8042.reset	[HW] Reset the controller during init and cleanup
 	i8042.unlock	[HW] Unlock (ignore) the keylock
 
@@ -1622,7 +1644,7 @@
 
 	noclflush	[BUGS=X86] Don't use the CLFLUSH instruction
 
-	nodelayacct	[KNL] Disable per-task delay accounting
+	delayacct	[KNL] Enable per-task delay accounting
 
 	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
 
@@ -1960,6 +1982,13 @@
 				off: Turn ECRC off
 				on: Turn ECRC on.
 
+	pci_reserve=	[PCI]
+			Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
+			Format of sbdf: [<segment>:]<bus>:<dev>.<func>
+			Specifies the least reserved io size or memory size
+			which is assigned to PCI bridge even when no child
+			pci device exists. This is useful with PCI hotplug.
+
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.
 		off	Disable ASPM.
@@ -2114,6 +2143,10 @@
 			Run specified binary instead of /init from the ramdisk,
 			used for early userspace startup. See initrd.
 
+	reassign_resources	[PCI,ACPI,XEN]
+			Use guestdev= parameter to reassign device's
+			resources.
+
 	reboot=		[BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
 			Format: <reboot_mode>[,<reboot_mode2>[,...]]
 			See arch/*/kernel/reboot.c or arch/*/kernel/process.c
@@ -2574,6 +2607,10 @@
 			disables clocksource verification at runtime.
 			Used to enable high-resolution timer mode on older
 			hardware, and in virtualized environment.
+			[x86] noirqtime: Do not use TSC to do irq accounting.
+			Used to run time disable IRQ_TIME_ACCOUNTING on any
+			platforms where RDTSC is slow and this accounting
+			can add overhead.
 
 	turbografx.map[2|3]=	[HW,JOY]
 			TurboGraFX parallel port interface
@@ -2645,6 +2682,8 @@
 			to a common usb-storage quirk flag as follows:
 				a = SANE_SENSE (collect more than 18 bytes
 					of sense data);
+				b = BAD_SENSE (don't collect more than 18
+					bytes of sense data);
 				c = FIX_CAPACITY (decrease the reported
 					device capacity by one sector);
 				h = CAPACITY_HEURISTICS (decrease the
@@ -2666,6 +2705,13 @@
 					medium is write-protected).
 			Example: quirks=0419:aaf5:rl,0421:0433:rc
 
+	userpte=
+			[X86] Flags controlling user PTE allocations.
+
+				nohigh = do not allocate PTE pages in
+					HIGHMEM regardless of setting
+					of CONFIG_HIGHPTE.
+
 	vdso=		[X86,SH]
 			vdso=2: enable compat VDSO (default with COMPAT_VDSO)
 			vdso=1: enable VDSO (default)
--- linux-ec2-2.6.32.orig/Documentation/Changes
+++ linux-ec2-2.6.32/Documentation/Changes
@@ -49,6 +49,8 @@
 o  udev                   081                     # udevinfo -V
 o  grub                   0.93                    # grub --version
 o  mcelog		  0.6
+o  iptables               1.4.1                   # iptables -V
+
 
 Kernel compilation
 ==================
--- linux-ec2-2.6.32.orig/Documentation/i2c/instantiating-devices
+++ linux-ec2-2.6.32/Documentation/i2c/instantiating-devices
@@ -100,7 +100,7 @@
 	(...)
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c);
 	i2c_put_adapter(i2c_adap);
--- linux-ec2-2.6.32.orig/Documentation/i2c/busses/i2c-i801
+++ linux-ec2-2.6.32/Documentation/i2c/busses/i2c-i801
@@ -15,7 +15,8 @@
   * Intel 82801I (ICH9)
   * Intel EP80579 (Tolapai)
   * Intel 82801JI (ICH10)
-  * Intel PCH
+  * Intel 3400/5 Series (PCH)
+  * Intel Cougar Point (PCH)
    Datasheets: Publicly available at the Intel website
 
 Authors: 
--- linux-ec2-2.6.32.orig/Documentation/sound/alsa/HD-Audio-Models.txt
+++ linux-ec2-2.6.32/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -401,4 +401,5 @@
 Cirrus Logic CS4206/4207
 ========================
   mbp55		MacBook Pro 5,5
+  imac27	IMac 27 Inch
   auto		BIOS setup (default)
--- linux-ec2-2.6.32.orig/Documentation/filesystems/tmpfs.txt
+++ linux-ec2-2.6.32/Documentation/filesystems/tmpfs.txt
@@ -82,11 +82,13 @@
 all files in that instance (if CONFIG_NUMA is enabled) - which can be
 adjusted on the fly via 'mount -o remount ...'
 
-mpol=default             prefers to allocate memory from the local node
+mpol=default             use the process allocation policy
+                         (see set_mempolicy(2))
 mpol=prefer:Node         prefers to allocate memory from the given Node
 mpol=bind:NodeList       allocates memory only from nodes in NodeList
 mpol=interleave          prefers to allocate from each node in turn
 mpol=interleave:NodeList allocates from each node of NodeList in turn
+mpol=local		 prefers to allocate memory from the local node
 
 NodeList format is a comma-separated list of decimal numbers and ranges,
 a range being two hyphen-separated decimal numbers, the smallest and
@@ -134,3 +136,5 @@
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
    Hugh Dickins, 4 June 2007
+Updated:
+   KOSAKI Motohiro, 16 Mar 2010
--- linux-ec2-2.6.32.orig/Documentation/filesystems/ext4.txt
+++ linux-ec2-2.6.32/Documentation/filesystems/ext4.txt
@@ -153,8 +153,8 @@
 			identified through its new major/minor numbers encoded
 			in devnum.
 
-noload			Don't load the journal on mounting.  Note that
-                     	if the filesystem was not unmounted cleanly,
+norecovery		Don't load the journal on mounting.  Note that
+noload			if the filesystem was not unmounted cleanly,
                      	skipping the journal replay will lead to the
                      	filesystem containing inconsistencies that can
                      	lead to any number of problems.
@@ -196,7 +196,7 @@
 			also be used to enable or disable barriers, for
 			consistency with other ext4 mount options.
 
-inode_readahead=n	This tuning parameter controls the maximum
+inode_readahead_blks=n	This tuning parameter controls the maximum
 			number of inode table blocks that ext4's inode
 			table readahead algorithm will pre-read into
 			the buffer cache.  The default value is 32 blocks.
@@ -353,6 +353,12 @@
 			system crashes before the delayed allocation
 			blocks are forced to disk.
 
+discard		Controls whether ext4 should issue discard/TRIM
+nodiscard(*)		commands to the underlying block device when
+			blocks are freed.  This is useful for SSD devices
+			and sparse/thinly-provisioned LUNs, but it is off
+			by default until sufficient testing has been done.
+
 Data Mode
 =========
 There are 3 different data modes:
--- linux-ec2-2.6.32.orig/Documentation/filesystems/proc.txt
+++ linux-ec2-2.6.32/Documentation/filesystems/proc.txt
@@ -176,7 +176,6 @@
   CapBnd: ffffffffffffffff
   voluntary_ctxt_switches:        0
   nonvoluntary_ctxt_switches:     1
-  Stack usage:    12 kB
 
 This shows you nearly the same information you would get if you viewed it with
 the ps  command.  In  fact,  ps  uses  the  proc  file  system  to  obtain its
@@ -230,7 +229,6 @@
  Mems_allowed_list           Same as previous, but in "list format"
  voluntary_ctxt_switches     number of voluntary context switches
  nonvoluntary_ctxt_switches  number of non voluntary context switches
- Stack usage:                stack usage high water mark (round up to page size)
 ..............................................................................
 
 Table 1-3: Contents of the statm files (as of 2.6.8-rc3)
@@ -309,7 +307,7 @@
 08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
 0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
 a7cb1000-a7cb2000 ---p 00000000 00:00 0
-a7cb2000-a7eb2000 rw-p 00000000 00:00 0          [threadstack:001ff4b4]
+a7cb2000-a7eb2000 rw-p 00000000 00:00 0
 a7eb2000-a7eb3000 ---p 00000000 00:00 0
 a7eb3000-a7ed5000 rw-p 00000000 00:00 0
 a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
@@ -345,7 +343,6 @@
  [stack]                  = the stack of the main process
  [vdso]                   = the "virtual dynamic shared object",
                             the kernel system call handler
- [threadstack:xxxxxxxx]   = the stack of the thread, xxxxxxxx is the stack size
 
  or if empty, the mapping is anonymous.
 
--- linux-ec2-2.6.32.orig/Documentation/kvm/api.txt
+++ linux-ec2-2.6.32/Documentation/kvm/api.txt
@@ -593,6 +593,42 @@
 	} chip;
 };
 
+4.27 KVM_GET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (out)
+Returns: 0 on success, -1 on error
+
+Gets the current timestamp of kvmclock as seen by the current guest. In
+conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+struct kvm_clock_data {
+	__u64 clock;  /* kvmclock current value */
+	__u32 flags;
+	__u32 pad[9];
+};
+
+4.28 KVM_SET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (in)
+Returns: 0 on success, -1 on error
+
+Sets the current timestamp of kvmclock to the valued specific in its parameter.
+In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+struct kvm_clock_data {
+	__u64 clock;  /* kvmclock current value */
+	__u32 flags;
+	__u32 pad[9];
+};
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
--- linux-ec2-2.6.32.orig/Documentation/hwmon/ltc4245
+++ linux-ec2-2.6.32/Documentation/hwmon/ltc4245
@@ -72,9 +72,7 @@
 in7_min_alarm		3v  output undervoltage alarm
 in8_min_alarm		Vee (-12v) output undervoltage alarm
 
-in9_input		GPIO #1 voltage data
-in10_input		GPIO #2 voltage data
-in11_input		GPIO #3 voltage data
+in9_input		GPIO voltage data
 
 power1_input		12v power usage (mW)
 power2_input		5v  power usage (mW)
--- linux-ec2-2.6.32.orig/Documentation/usb/proc_usb_info.txt
+++ linux-ec2-2.6.32/Documentation/usb/proc_usb_info.txt
@@ -1,12 +1,17 @@
 /proc/bus/usb filesystem output
 ===============================
-(version 2003.05.30)
+(version 2010.09.13)
 
 
 The usbfs filesystem for USB devices is traditionally mounted at
 /proc/bus/usb.  It provides the /proc/bus/usb/devices file, as well as
 the /proc/bus/usb/BBB/DDD files.
 
+In many modern systems the usbfs filsystem isn't used at all.  Instead
+USB device nodes are created under /dev/usb/ or someplace similar.  The
+"devices" file is available in debugfs, typically as
+/sys/kernel/debug/usb/devices.
+
 
 **NOTE**: If /proc/bus/usb appears empty, and a host controller
 	  driver has been linked, then you need to mount the
@@ -106,8 +111,8 @@
 
 Topology info:
 
-T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
-|   |      |      |       |       |      |        |       |__MaxChildren
+T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
+|   |      |      |       |       |      |        |        |__MaxChildren
 |   |      |      |       |       |      |        |__Device Speed in Mbps
 |   |      |      |       |       |      |__DeviceNumber
 |   |      |      |       |       |__Count of devices at this level
@@ -120,8 +125,13 @@
     Speed may be:
     	1.5	Mbit/s for low speed USB
 	12	Mbit/s for full speed USB
-	480	Mbit/s for high speed USB (added for USB 2.0)
-
+	480	Mbit/s for high speed USB (added for USB 2.0);
+		  also used for Wireless USB, which has no fixed speed
+	5000	Mbit/s for SuperSpeed USB (added for USB 3.0)
+
+    For reasons lost in the mists of time, the Port number is always
+    too low by 1.  For example, a device plugged into port 4 will
+    show up with "Port=03".
 
 Bandwidth info:
 B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
@@ -291,7 +301,7 @@
 an external hub connected to the root hub, and a mouse and
 a serial converter connected to the external hub.
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
 B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0000 ProdID=0000 Rev= 0.00
@@ -301,21 +311,21 @@
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
 
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=04b4 ProdID=0001 Rev= 0.00
 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0565 ProdID=0001 Rev= 1.08
 S:  Manufacturer=Peracom Networks, Inc.
@@ -330,12 +340,12 @@
 Selecting only the "T:" and "I:" lines from this (for example, by using
 "procusb ti"), we have:
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
 
 
--- linux-ec2-2.6.32.orig/Documentation/video4linux/CARDLIST.saa7134
+++ linux-ec2-2.6.32/Documentation/video4linux/CARDLIST.saa7134
@@ -172,3 +172,4 @@
 171 -> Beholder BeholdTV X7                     [5ace:7595]
 172 -> RoverMedia TV Link Pro FM                [19d1:0138]
 173 -> Zolid Hybrid TV Tuner PCI                [1131:2004]
+174 -> Asus Europa Hybrid OEM                   [1043:4847]
--- linux-ec2-2.6.32.orig/Documentation/video4linux/gspca.txt
+++ linux-ec2-2.6.32/Documentation/video4linux/gspca.txt
@@ -37,6 +37,7 @@
 ov519		041e:4060	Creative Live! VISTA VF0350
 ov519		041e:4061	Creative Live! VISTA VF0400
 ov519		041e:4064	Creative Live! VISTA VF0420
+ov519		041e:4067	Creative Live! Cam Video IM (VF0350)
 ov519		041e:4068	Creative Live! VISTA VF0470
 spca561		0458:7004	Genius VideoCAM Express V2
 sunplus		0458:7006	Genius Dsc 1.3 Smart
--- linux-ec2-2.6.32.orig/Documentation/DocBook/Makefile
+++ linux-ec2-2.6.32/Documentation/DocBook/Makefile
@@ -32,28 +32,37 @@
 
 ###
 # The targets that may be used.
-PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs media
+PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
 
 BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
-xmldocs: $(BOOKS)
+xmldocs: xmldoclinks $(BOOKS)
 sgmldocs: xmldocs
 
 PS := $(patsubst %.xml, %.ps, $(BOOKS))
-psdocs: $(PS)
+psdocs: xmldoclinks $(PS)
 
 PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
-pdfdocs: $(PDF)
+pdfdocs: xmldoclinks $(PDF)
 
 HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
-htmldocs: media $(HTML)
+htmldocs: xmldoclinks $(HTML)
 	$(call build_main_index)
+	$(call build_images)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
 
-media:
-	mkdir -p $(srctree)/Documentation/DocBook/media/
-	cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(srctree)/Documentation/DocBook/media/
+build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
+	       cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
+
+xmldoclinks:
+ifneq ($(objtree),$(srctree))
+	for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \
+		rm -f $(objtree)/Documentation/DocBook/$$dep \
+		&& ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \
+		|| exit; \
+	done
+endif
 
 installmandocs: mandocs
 	mkdir -p /usr/local/man/man9/
--- linux-ec2-2.6.32.orig/Documentation/networking/3c509.txt
+++ linux-ec2-2.6.32/Documentation/networking/3c509.txt
@@ -48,11 +48,11 @@
 This configures the first found 3c509 card for IRQ 10, base I/O 0x310, and
 transceiver type 3 (10base2). The flag "0x3c509" must be set to avoid conflicts
 with other card types when overriding the I/O address. When the driver is
-loaded as a module, only the IRQ and transceiver setting may be overridden.
-For example, setting two cards to 10base2/IRQ10 and AUI/IRQ11 is done by using
-the xcvr and irq module options:
+loaded as a module, only the IRQ may be overridden. For example,
+setting two cards to IRQ10 and IRQ11 is done by using the irq module
+option:
 
-   options 3c509 xcvr=3,1 irq=10,11
+   options 3c509 irq=10,11
 
 
 (2) Full-duplex mode
@@ -77,6 +77,8 @@
 itself full-duplex capable. This is almost certainly one of two things: a full-
 duplex-capable  Ethernet switch (*not* a hub), or a full-duplex-capable NIC on
 another system that's connected directly to the 3c509B via a crossover cable.
+
+Full-duplex mode can be enabled using 'ethtool'.
  
 /////Extremely important caution concerning full-duplex mode/////
 Understand that the 3c509B's hardware's full-duplex support is much more
@@ -113,6 +115,8 @@
 never automatically enable full-duplex mode in an existing installation;
 it must always be explicitly enabled via one of these code in order to be
 activated.
+
+The transceiver type can be changed using 'ethtool'.
   
 
 (4a) Interpretation of error messages and common problems
--- linux-ec2-2.6.32.orig/Documentation/networking/README.ipw2200
+++ linux-ec2-2.6.32/Documentation/networking/README.ipw2200
@@ -171,7 +171,7 @@
   
   led
 	Can be used to turn on experimental LED code.
-	0 = Off, 1 = On.  Default is 0.
+	0 = Off, 1 = On.  Default is 1.
 
   mode
 	Can be used to set the default mode of the adapter.  
--- linux-ec2-2.6.32.orig/Documentation/kbuild/kconfig.txt
+++ linux-ec2-2.6.32/Documentation/kbuild/kconfig.txt
@@ -103,6 +103,11 @@
 This environment variable can be set to specify the path & name of the
 "auto.conf" file.  Its default value is "include/config/auto.conf".
 
+KCONFIG_TRISTATE
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"tristate.conf" file.  Its default value is "include/config/tristate.conf".
+
 KCONFIG_AUTOHEADER
 --------------------------------------------------
 This environment variable can be set to specify the path & name of the
--- linux-ec2-2.6.32.orig/Documentation/kbuild/kbuild.txt
+++ linux-ec2-2.6.32/Documentation/kbuild/kbuild.txt
@@ -1,3 +1,17 @@
+Output files
+
+modules.order
+--------------------------------------------------
+This file records the order in which modules appear in Makefiles. This
+is used by modprobe to deterministically resolve aliases that match
+multiple modules.
+
+modules.builtin
+--------------------------------------------------
+This file lists all modules that are built into the kernel. This is used
+by modprobe to not fail when trying to load something builtin.
+
+
 Environment variables
 
 KCPPFLAGS
--- linux-ec2-2.6.32.orig/debian.ec2/changelog
+++ linux-ec2-2.6.32/debian.ec2/changelog
@@ -0,0 +1,8971 @@
+linux-ec2 (2.6.32-317.36) lucid-proposed; urgency=low
+
+  [Stefan Bader]
+
+  * Release Tracking Bug
+    - LP: #807505
+
+  [ Stefan Bader ]
+
+  * Revert "XEN: x86: Flush TLB if PGD entry is changed in i386 PAE mode"
+    - LP: #805209
+  * Rebased to 2.6.32-33.70
+
+  [ Ubuntu: 2.6.32-33.70 ]
+
+  * Revert "x86: Flush TLB if PGD entry is changed in i386 PAE mode"
+    - LP: #805209
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 Jul 2011 09:57:36 +0000
+
+linux-ec2 (2.6.32-317.35) lucid-proposed; urgency=low
+
+  [Stefan Bader]
+
+  * Release Tracking Bug
+    - LP: #806968
+  * Rebased to 2.6.32-33.69
+
+  [ Ubuntu: 2.6.32-33.69 ]
+
+  * Revert "af_unix: Only allow recv on connected seqpacket sockets."
+
+  [ Ubuntu: 2.6.32-33.68 ]
+
+  * Fix abi directory
+
+  [ Ubuntu: 2.6.32-33.67 ]
+
+  * Revert "iwlagn: Support new 5000 microcode."
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 07 Jul 2011 15:09:59 +0200
+
+linux-ec2 (2.6.32-317.34) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Release Tracking Bug
+    - LP: #794420
+  * Rebased to 2.6.32-33.66
+
+  [ Ubuntu: 2.6.32-33.66 ]
+
+  * Revert "xhci: Fix full speed bInterval encoding."
+  * Revert "USB: xhci - fix math in xhci_get_endpoint_interval()"
+  * Revert "USB: xhci - fix unsafe macro definitions"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 08 Jun 2011 09:58:47 +0200
+
+linux-ec2 (2.6.32-317.33) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Release Tracking Bug
+    - LP: #793566
+  * Rebased to 2.6.32-33.65
+
+  [ Ubuntu: 2.6.32-33.65 ]
+
+  * xhci: Fix full speed bInterval encoding.
+    - LP: #792959
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 06 Jun 2011 14:06:42 +0000
+
+linux-ec2 (2.6.32-317.32) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * SAUCE: XEN: Sync with x86, cpu: AMD errata checking framework
+    - LP: #770050
+  * SAUCE: XEN: Sync with x86, cpu: Clean up AMD erratum 400 workaround
+    - LP: #770050
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-33.64
+
+  [ Ubuntu: 2.6.32-33.64 ]
+
+   * Release Tracking Bug
+     - LP: #789325
+  * SAUCE: (no-up) Fix up KVM: VMX: Fix host userspace gsbase corruption
+    - LP: #787675
+  * SAUCE: vesafb: mtrr module parameter is uint, not bool
+    - LP: #778043
+  * Revert "(pre-stable): input: Support Clickpad devices in ClickZone
+    mode"
+    - LP: #780588
+  * Revert "GFS2: Fix writing to non-page aligned gfs2_quota structures"
+    - LP: #780588
+  * Revert "mmc: build fix: mmc_pm_notify is only available with
+    CONFIG_PM=y"
+    - LP: #780588
+  * Revert "mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume"
+    - LP: #780588
+  * Revert "econet: fix CVE-2010-3848"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "xen: set max_pfn_mapped to the last pfn mapped"
+  * cifs: always do is_path_accessible check in cifs_mount
+    - LP: #770050
+  * video: sn9c102: world-wirtable sysfs files
+    - LP: #770050
+  * UBIFS: restrict world-writable debugfs files
+    - LP: #770050
+  * NET: cdc-phonet, handle empty phonet header
+    - LP: #770050
+  * x86: Fix a bogus unwind annotation in lib/semaphore_32.S
+    - LP: #770050
+  * tioca: Fix assignment from incompatible pointer warnings
+    - LP: #770050
+  * mca.c: Fix cast from integer to pointer warning
+    - LP: #770050
+  * ramfs: fix memleak on no-mmu arch
+    - LP: #770050
+  * MAINTAINERS: update STABLE BRANCH info
+    - LP: #770050
+  * UBIFS: fix oops when R/O file-system is fsync'ed
+    - LP: #770050
+  * x86, cpu: AMD errata checking framework
+    - LP: #770050
+  * x86, cpu: Clean up AMD erratum 400 workaround
+    - LP: #770050
+  * x86, AMD: Set ARAT feature on AMD processors
+    - LP: #770050
+  * x86, amd: Disable GartTlbWlkErr when BIOS forgets it
+    - LP: #770050
+  * USB: ftdi_sio: Added IDs for CTI USB Serial Devices
+    - LP: #770050
+  * USB: ftdi_sio: add PID for OCT DK201 docking station
+    - LP: #770050
+  * USB: ftdi_sio: add ids for Hameg HO720 and HO730
+    - LP: #770050
+  * USB: option: Add new ONDA vendor id and product id for ONDA MT825UP
+    - LP: #770050
+  * USB: option: Added support for Samsung GT-B3730/GT-B3710 LTE USB modem.
+    - LP: #770050
+  * next_pidmap: fix overflow condition
+    - LP: #770050
+  * proc: do proper range check on readdir offset
+    - LP: #770050
+  * USB: EHCI: unlink unused QHs when the controller is stopped
+    - LP: #770050
+  * USB: fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices
+    - LP: #770050
+  * USB: xhci - fix unsafe macro definitions
+    - LP: #770050
+  * USB: xhci - fix math in xhci_get_endpoint_interval()
+    - LP: #770050
+  * x86, cpu: Fix regression in AMD errata checking code
+    - LP: #770050
+  * Linux 2.6.32.39
+    - LP: #770050
+  * fs/partitions/ldm.c: fix oops caused by corrupted partition table,
+    CVE-2011-1017
+    - LP: #771382
+    - CVE-2011-1017
+  * drm/i915: set DIDL using the ACPI video output device _ADR method
+    return.
+    - LP: #775547
+  * drm/radeon/kms: MC vram map needs to be >= pci aperture size
+    - LP: #775547
+  * drm/radeon/kms: make sure blit addr masks are 64 bit
+    - LP: #775547
+  * drm/radeon/kms: fix handling of tex lookup disable in cs checker on
+    r2xx
+    - LP: #775547
+  * drm/i915: Free hardware status page on unload when physically mapped
+    - LP: #775547
+  * drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to
+    writing.
+    - LP: #775547
+  * drm/radeon/kms/atom: set sane defaults in atombios_get_encoder_mode()
+    - LP: #775547
+  * drm/radeon/kms: fix typos in disabled vbios code
+    - LP: #775547
+  * drm/radeon/kms: add workaround for dce3 ddc line vbios bug
+    - LP: #775547
+  * drm/radeon/kms: fix interlaced and doublescan handling
+    - LP: #775547
+  * drm/i915/sdvo: Always add a 30ms delay to make SDVO TV detection
+    reliable
+    - LP: #775547
+  * drm/radeon/kms: don't apply 7xx HDP flush workaround on AGP
+    - LP: #775547
+  * drm/ttm: Fix two race conditions + fix busy codepaths
+    - LP: #775547
+  * drm/i915: overlay on gen2 can't address above 1G
+    - LP: #775547
+  * drm/i915: fix memory corruption with GM965 and >4GB RAM
+    - LP: #775547
+  * drm/radeon: add quirk to make HP nx6125 laptop resume.
+    - LP: #775547
+  * drm/radeon/kms: add quirk to make HP DV5000 laptop resume
+    - LP: #775547
+  * ath: add missing regdomain pair 0x5c mapping
+    - LP: #780588
+  * block, blk-sysfs: Fix an err return path in blk_register_queue()
+    - LP: #780588
+  * p54: Initialize extra_len in p54_tx_80211
+    - LP: #780588
+  * intel-iommu: Unlink domain from iommu
+    - LP: #780588
+  * intel-iommu: Fix get_domain_for_dev() error path
+    - LP: #780588
+  * NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount
+    - LP: #780588
+  * serial/imx: read cts state only after acking cts change irq
+    - LP: #780588
+  * ASoC: Fix output PGA enabling in wm_hubs CODECs
+    - LP: #780588
+  * kconfig: Avoid buffer underrun in choice input
+    - LP: #780588
+  * UBIFS: fix master node recovery
+    - LP: #780588
+  * Remove extra struct page member from the buffer info structure
+    - LP: #780588
+  * dasd: correct device table
+    - LP: #780588
+  * iwlagn: Support new 5000 microcode.
+    - LP: #780588
+  * atl1c: duplicate atl1c_get_tpd
+    - LP: #780588
+  * udp: Fix bogus UFO packet generation
+    - LP: #780588
+  * slub: fix panic with DISCONTIGMEM
+    - LP: #780588
+  * set memory ranges in N_NORMAL_MEMORY when onlined
+    - LP: #780588
+  * FLEXCOP-PCI: fix __xlate_proc_name-warning for flexcop-pci
+    - LP: #780588
+  * m68k/mm: Set all online nodes in N_NORMAL_MEMORY
+    - LP: #780588
+  * nfs: don't lose MS_SYNCHRONOUS on remount of noac mount
+    - LP: #780588
+  * NFSv4.1: Ensure state manager thread dies on last umount
+    - LP: #780588
+  * agp: fix arbitrary kernel memory writes
+    - LP: #780588
+  * agp: fix OOM and buffer overflow
+    - LP: #780588
+  * Input: xen-kbdfront - fix mouse getting stuck after save/restore
+    - LP: #780588
+  * pmcraid: reject negative request size
+    - LP: #780588
+  * mpt2sas: prevent heap overflows and unchecked reads
+    - LP: #780588
+  * put stricter guards on queue dead checks
+    - LP: #780588
+  * mmc: sdhci-pci: Fix error case in sdhci_pci_probe_slot()
+    - LP: #780588
+  * mmc: sdhci: Check mrq->cmd in sdhci_tasklet_finish
+    - LP: #780588
+  * mmc: sdhci: Check mrq != NULL in sdhci_tasklet_finish
+    - LP: #780588
+  * USB: fix regression in usbip by setting has_tt flag
+    - LP: #780588
+  * af_unix: Only allow recv on connected seqpacket sockets.
+    - LP: #780588
+  * ARM: 6891/1: prevent heap corruption in OABI semtimedop
+    - LP: #780588
+  * i8k: Tell gcc that *regs gets clobbered
+    - LP: #780588
+  * Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again)
+    - LP: #780588
+  * Open with O_CREAT flag set fails to open existing files on non writable
+    directories
+    - LP: #780588
+  * can: Add missing socket check in can/bcm release.
+    - LP: #780588
+  * netxen: module firmware hints
+    - LP: #780588
+  * bnx2x: declare MODULE_FIRMWARE
+    - LP: #780588
+  * cxgb3: declare MODULE_FIRMWARE
+    - LP: #780588
+  * myri10ge: declare MODULE_FIRMWARE
+    - LP: #780588
+  * netx: declare MODULE_FIRMWARE
+    - LP: #780588
+  * pcnet-cs: declare MODULE_FIRMWARE
+    - LP: #780588
+  * spider-net: declare MODULE_FIRMWARE
+    - LP: #780588
+  * tms380tr: declare MODULE_FIRMWARE
+    - LP: #780588
+  * Input: Add support of Synaptics Clickpad device
+    - LP: #780588
+  * Input: elantech - do not advertise relative events
+    - LP: #780588
+  * Input: elantech - fix firmware version check
+    - LP: #780588
+  * Input: elantech - allow forcing Elantech protocol
+    - LP: #780588
+  * Input: elantech - ignore high bits in the position coordinates
+    - LP: #780588
+  * Input: elantech - use all 3 bytes when checking version
+    - LP: #780588
+  * Input: elantech - relax signature checks
+    - LP: #780588
+  * Input: elantech - discard the first 2 positions on some firmwares
+    - LP: #780588
+  * Staging: rtl8192su: check for skb == NULL
+    - LP: #780588
+  * Staging: rtl8192su: Clean up in case of an error in module
+    initialisation
+    - LP: #780588
+  * Staging: rtl8192su: Fix procfs code for interfaces not named wlan0
+    - LP: #780588
+  * Staging: rtl8192su: remove device ids
+    - LP: #780588
+  * Staging: rtl8192su: add device ids
+    - LP: #780588
+  * USB: retain USB device power/wakeup setting across reconfiguration
+    - LP: #780588
+  * USB: don't enable remote wakeup by default
+    - LP: #780588
+  * USB: teach "devices" file about Wireless and SuperSpeed USB
+    - LP: #780588
+  * GFS2: Clean up gfs2_adjust_quota() and do_glock()
+    - LP: #780588
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - LP: #780588
+  * GFS2: BUG in gfs2_adjust_quota
+    - LP: #780588
+  * SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494)
+    - LP: #780588
+  * nfs4: Ensure that ACL pages sent over NFS were not allocated from the
+    slab (v3)
+    - LP: #780588
+  * nfs: fix compilation warning
+    - LP: #780588
+  * Fix corrupted OSF partition table parsing
+    - LP: #780588
+  * Increase OSF partition limit from 8 to 18
+    - LP: #780588
+  * Please add support for Microsoft MN-120 PCMCIA network card
+    - LP: #780588
+  * hwmon: (applesmc) Add iMac9,1 and MacBookPro2,2 support
+    - LP: #780588
+  * hwmon: (applesmc) Add support for MacBook Pro 5,3 and 5,4
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 6
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 7
+    - LP: #780588
+  * hwmon: (applesmc) Add MacBookAir3,1(3,2) support
+    - LP: #780588
+  * ALSA: emux: Add trivial compat ioctl handler
+    - LP: #780588
+  * ALSA: powermac - Reverse HP detection on G4 DA
+    - LP: #780588
+  * ALSA: powermac - Lineout detection on G4 DA
+    - LP: #780588
+  * ALSA: hda - Add support for the new 27 inch IMacs
+    - LP: #780588
+  * ALSA: hda - MacBookPro 5,3 line-in support
+    - LP: #780588
+  * ALSA: hda - Add model=mbp55 entry for MacBookPro 7,1
+    - LP: #780588
+  * ALSA: hda - MacBookAir3,1(3,2) alsa support
+    - LP: #780588
+  * virtio_net: fix oom handling on tx
+    - LP: #780588
+  * mac80211: Add define for TX headroom reserved by mac80211 itself.
+    - LP: #780588
+  * rt2x00: Centralize setting of extra TX headroom requested by rt2x00.
+    - LP: #780588
+  * rt2x00: Properly request tx headroom for alignment operations.
+    - LP: #780588
+  * rt2x00: use correct headroom for transmission
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 6,2
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 7,1
+    - LP: #780588
+  * Bluetooth: Add MacBookAir3,1(2) support
+    - LP: #780588
+  * perf tools: Display better error messages on missing packages
+    - LP: #780588
+  * perf tools: Add 'make DEBUG=1' to remove the -O6 cflag
+    - LP: #780588
+  * perf tools: Test -fstack-protector-all compiler option for inclusion in
+    CFLAGS
+    - LP: #780588
+  * perf tools: Support static build
+    - LP: #780588
+  * perf tools: Add V=2 option to help debug config issues
+    - LP: #780588
+  * perf tools: Suggest static libraries as well
+    - LP: #780588
+  * perf: Use default compiler mode by default
+    - LP: #780588
+  * perf tools: Move QUIET_STDERR def to before first use
+    - LP: #780588
+  * perf tools: Check if /dev/null can be used as the -o gcc argument
+    - LP: #780588
+  * perf symbols: allow forcing use of cplus_demangle
+    - LP: #780588
+  * V4L/DVB: Add Elgato EyeTV Diversity to dibcom driver
+    - LP: #780588
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #780588
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #780588
+  * b43: Fix warning at drivers/mmc/core/core.c:237 in mmc_wait_for_cmd
+    - LP: #780588
+  * econet: Fix redeclaration of symbol len
+    - LP: #780588
+  * econet: fix CVE-2010-3848
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop to the DMI whitelist
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #780588
+  * scsi_dh_emc: fix mode select request setup
+    - LP: #780588
+  * scsi_dh_emc: request flag cleanup
+    - LP: #780588
+  * cifs: fix another memleak, in cifs_root_iget
+    - LP: #780588
+  * e1000e: Reset 82577/82578 PHY before first PHY register read
+    - LP: #780588
+  * e1000: fix Tx hangs by disabling 64-bit DMA
+    - LP: #780588
+  * btrfs: Require CAP_SYS_ADMIN for filesystem rebalance
+    - LP: #780588
+  * af_unix: limit recursion level
+    - LP: #780588
+  * init, sched: Fix race between init and kthreadd
+    - LP: #780588
+  * backlight: MacBookAir3,1(3,2) mbp-nvidia-bl support
+    - LP: #780588
+  * bonding: Ensure that we unshare skbs prior to calling pskb_may_pull
+    - LP: #780588
+  * HID: add MacBookAir 3,1 and 3,2 support
+    - LP: #780588
+  * intel-iommu: Force-disable IOMMU for iGFX on broken Cantiga revisions.
+    - LP: #780588
+  * ipg: Remove device claimed by dl2k from pci id table
+    - LP: #780588
+  * ipv6: Silence privacy extensions initialization
+    - LP: #780588
+  * l2tp: Fix UDP socket reference count bugs in the pppol2tp driver
+    - LP: #780588
+  * MIPS: DMA: Fix computation of DMA flags from device's
+    coherent_dma_mask.
+    - LP: #780588
+  * mpt2sas: fix the incorrect scsi_dma_map error checking
+    - LP: #780588
+  * Phonet: device notifier only runs on initial namespace
+    - LP: #780588
+  * powerpc/boot/dts: Install dts from the right directory
+    - LP: #780588
+  * rt2500usb: fallback to SW encryption for TKIP+AES
+    - LP: #780588
+  * sata_via: Delay on vt6420 when starting ATAPI DMA write
+    - LP: #780588
+  * tehuti: Firmware filename is tehuti/bdx.bin
+    - LP: #780588
+  * wireless: b43: fix error path in SDIO
+    - LP: #780588
+  * libata: set queue DMA alignment to sector size for ATAPI too
+    - LP: #780588
+  * usb: musb: core: set has_tt flag
+    - LP: #780588
+  * iwlwifi: fix skb usage after free
+    - LP: #780588
+  * can: add missing socket check in can/raw release
+    - LP: #780588
+  * fix oops in scsi_run_queue()
+    - LP: #780588
+  * Linux 2.6.32.40
+    - LP: #780588
+  * PCI: allow matching of prefetchable resources to non-prefetchable
+    windows
+    - LP: #424142
+  * cifs: check for bytes_remaining going to zero in CIFS_SessSetup
+    - LP: #788602
+  * Validate size of EFI GUID partition entries.
+    - LP: #788602
+  * dccp: handle invalid feature options length
+    - LP: #788602
+  * CIFS: Fix memory over bound bug in cifs_parse_mount_options
+    - LP: #788602
+  * Fix time() inconsistencies caused by intermediate xtime_cache values
+    being read
+    - LP: #788602
+  * ehea: fix wrongly reported speed and port
+    - LP: #788602
+  * NET: slip, fix ldisc->open retval
+    - LP: #788602
+  * ne-h8300: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * hydra: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * libertas: fix cmdpendingq locking
+    - LP: #788602
+  * zorro8390: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * cifs: add fallback in is_path_accessible for old servers
+    - LP: #788602
+  * x86, AMD: Fix ARAT feature setting again
+    - LP: #788602
+  * clocksource: Install completely before selecting
+    - LP: #788602
+  * tick: Clear broadcast active bit when switching to oneshot
+    - LP: #788602
+  * x86, apic: Fix spurious error interrupts triggering on all non-boot APs
+    - LP: #788602
+  * x86, mce, AMD: Fix leaving freed data in a list
+    - LP: #788602
+  * megaraid_sas: Sanity check user supplied length before passing it to
+    dma_alloc_coherent()
+    - LP: #788602
+  * vmxnet3: Fix inconsistent LRO state after initialization
+    - LP: #788602
+  * netxen: Remove references to unified firmware file
+    - LP: #788602
+  * Linux 2.6.32.41
+    - LP: #788602
+  * drm/radeon/kms: fix bad shift in atom iio table parser
+    - LP: #788602
+  * Linux 2.6.32.41+drm33.18
+    - LP: #788602
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 01 Jun 2011 16:22:08 +0200
+
+linux-ec2 (2.6.32-316.31) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * XEN: x86: Flush TLB if PGD entry is changed in i386 PAE mode
+    - LP: #742056
+  * XEN: x86: Emit "mem=nopentium ignored" warning when not supported
+    - LP: #742056
+  * XEN: x86: Fix panic when handling "mem={invalid}" param
+    - LP: #742056
+  * XEN: x86/mm: Handle mm_fault_error() in kernel space
+    - LP: #742056
+  * SAUCE: XEN: Do not force sched_clock_stable
+    - LP: #727459
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 02 May 2011 15:17:30 +0200
+
+linux-ec2 (2.6.32-316.30) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #767978
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-32.62
+
+  [ Ubuntu: 2.6.32-32.62 ]
+
+  * Release Tracking Bug
+    - LP: #767370
+  * (config) Disable CONFIG_NET_NS
+    - LP: #720095
+  * Revert "drm/radeon/kms: Fix retrying ttm_bo_init() after it failed
+    once."
+    - LP: #736234
+  * Revert "drm/radeon: fall back to GTT if bo creation/validation in VRAM
+    fails."
+    - LP: #736234
+  * x86: pvclock: Move scale_delta into common header
+  * KVM: x86: Fix a possible backwards warp of kvmclock
+  * KVM: x86: Fix kvmclock bug
+  * cpuset: add a missing unlock in cpuset_write_resmask()
+    - LP: #736234
+  * keyboard: integer underflow bug
+    - LP: #736234
+  * RxRPC: Fix v1 keys
+    - LP: #736234
+  * ixgbe: fix for 82599 erratum on Header Splitting
+    - LP: #736234
+  * mm: fix possible cause of a page_mapped BUG
+    - LP: #736234
+  * powerpc/kdump: CPUs assume the context of the oopsing CPU
+    - LP: #736234
+  * powerpc/kdump: Use chip->shutdown to disable IRQs
+    - LP: #736234
+  * powerpc: Use more accurate limit for first segment memory allocations
+    - LP: #736234
+  * powerpc/pseries: Add hcall to read 4 ptes at a time in real mode
+    - LP: #736234
+  * powerpc/kexec: Speedup kexec hash PTE tear down
+    - LP: #736234
+  * powerpc/crashdump: Do not fail on NULL pointer dereferencing
+    - LP: #736234
+  * powerpc/kexec: Fix orphaned offline CPUs across kexec
+    - LP: #736234
+  * netfilter: nf_log: avoid oops in (un)bind with invalid nfproto values
+    - LP: #736234
+  * nfsd: wrong index used in inner loop
+    - LP: #736234
+  * r8169: use RxFIFO overflow workaround for 8168c chipset.
+    - LP: #736234
+  * Staging: comedi: jr3_pci: Don't ioremap too much space. Check result.
+    - LP: #736234
+  * net: don't allow CAP_NET_ADMIN to load non-netdev kernel modules,
+    CVE-2011-1019
+    - LP: #736234
+    - CVE-2011-1019
+  * ip6ip6: autoload ip6 tunnel
+    - LP: #736234
+  * Linux 2.6.32.33
+    - LP: #736234
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934, #736234
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934, #736234
+  * drm: fix unsigned vs signed comparison issue in modeset ctl ioctl,
+    CVE-2011-1013
+    - LP: #736234
+    - CVE-2011-1013
+  * Linux 2.6.32.33+drm33.15
+    - LP: #736234
+  * econet: Fix crash in aun_incoming(). CVE-2010-4342
+    - LP: #736394
+    - CVE-2010-4342
+  * igb: only use vlan_gro_receive if vlans are registered, CVE-2010-4263
+    - LP: #737024
+    - CVE-2010-4263
+  * irda: prevent integer underflow in IRLMP_ENUMDEVICES, CVE-2010-4529
+    - LP: #737823
+    - CVE-2010-4529
+  * hwmon/f71882fg: Set platform drvdata to NULL later
+    - LP: #742056
+  * mtd: add "platform:" prefix for platform modalias
+    - LP: #742056
+  * libata: no special completion processing for EH commands
+    - LP: #742056
+  * MIPS: MTX-1: Make au1000_eth probe all PHY addresses
+    - LP: #742056
+  * x86/mm: Handle mm_fault_error() in kernel space
+    - LP: #742056
+  * ftrace: Fix memory leak with function graph and cpu hotplug
+    - LP: #742056
+  * x86: Fix panic when handling "mem={invalid}" param
+    - LP: #553464, #742056
+  * x86: Emit "mem=nopentium ignored" warning when not supported
+    - LP: #553464, #742056
+  * ahci: AHCI and RAID mode SATA patch for Intel Patsburg DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel DH89xxCC DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel Patsburg SATA RAID controller
+    - LP: #742056
+  * RDMA/cma: Fix crash in request handlers
+    - LP: #742056
+  * IB/cm: Bump reference count on cm_id before invoking callback
+    - LP: #742056
+  * ath9k_hw: Fix incorrect macversion and macrev checks
+    - LP: #742056
+  * USB: serial/kobil_sct, fix potential tty NULL dereference
+    - LP: #742056
+  * USB: serial: ch341: add new id
+    - LP: #742056
+  * xhci: Fix cycle bit calculation during stall handling.
+    - LP: #742056
+  * ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
+    - LP: #742056
+  * PCI: remove quirk for pre-production systems
+    - LP: #742056
+  * PCI: add more checking to ICH region quirks
+    - LP: #742056
+  * PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH
+    - LP: #742056
+  * PCI: sysfs: Fix failure path for addition of "vpd" attribute
+    - LP: #742056
+  * ALSA: ctxfi - Fix incorrect SPDIF status bit mask
+    - LP: #742056
+  * ALSA: ctxfi - Fix SPDIF status retrieval
+    - LP: #742056
+  * ALSA: ctxfi - Clear input settings before initialization
+    - LP: #742056
+  * SUNRPC: Ensure we always run the tk_callback before tk_action
+    - LP: #742056
+  * perf, powerpc: Handle events that raise an exception without
+    overflowing
+    - LP: #742056
+  * ext3: Always set dx_node's fake_dirent explicitly.
+    - LP: #742056
+  * call_function_many: fix list delete vs add race
+    - LP: #742056
+  * call_function_many: add missing ordering
+    - LP: #742056
+  * x86: Flush TLB if PGD entry is changed in i386 PAE mode
+    - LP: #742056
+  * isdn: avoid calling tty_ldisc_flush() in atomic context
+    - LP: #742056
+  * smp_call_function_many: handle concurrent clearing of mask
+    - LP: #742056
+  * fix per-cpu flag problem in the cpu affinity checkers
+    - LP: #742056
+  * i2c: Fix typo in instantiating-devices document
+    - LP: #742056
+  * mmc: sdio: remember new card RCA when redetecting card
+    - LP: #742056
+  * powerpc/kexec: Fix race in kexec shutdown
+    - LP: #742056
+  * powerpc/kdump: Fix race in kdump shutdown
+    - LP: #742056
+  * powerpc: rtas_flash needs to use rtas_data_buf
+    - LP: #742056
+  * x86, binutils, xen: Fix another wrong size directive
+    - LP: #742056
+  * hwmon: (sht15) Fix integer overflow in humidity calculation
+    - LP: #742056
+  * Linux 2.6.32.34
+    - LP: #742056
+  * Linux 2.6.32.35
+    - LP: #742056
+  * aio: wake all waiters when destroying ctx
+    - LP: #744921
+  * shmem: let shared anonymous be nonlinear again
+    - LP: #744921
+  * PCI hotplug: acpiphp: set current_state to D0 in register_slot
+    - LP: #744921
+  * xen: set max_pfn_mapped to the last pfn mapped
+    - LP: #744921
+  * PCI: return correct value when writing to the "reset" attribute
+    - LP: #744921
+  * Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal
+    code
+    - LP: #744921
+  * ext3: skip orphan cleanup on rocompat fs
+    - LP: #744921
+  * procfs: fix /proc/<pid>/maps heap check
+    - LP: #744921
+  * proc: protect mm start_code/end_code in /proc/pid/stat, CVE-2011-0726
+    - LP: #744921
+    - CVE-2011-0726
+  * fbcon: Bugfix soft cursor detection in Tile Blitting
+    - LP: #744921
+  * nfsd41: modify the members value of nfsd4_op_flags
+    - LP: #744921
+  * nfsd: wrong index used in inner loop
+    - LP: #744921
+  * uvcvideo: Fix uvc_fixup_video_ctrl() format search
+    - LP: #744921
+  * ehci-hcd: Bug fix: don't set a QH's Halt bit
+    - LP: #744921
+  * USB: uss720 fixup refcount position
+    - LP: #744921
+  * USB: cdc-acm: fix memory corruption / panic
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference on disconnect
+    - LP: #744921
+  * Input: xen-kbdfront - advertise either absolute or relative coordinates
+    - LP: #744921
+  * SUNRPC: Never reuse the socket port after an xs_close()
+    - LP: #744921
+  * fs: call security_d_instantiate in d_obtain_alias V2
+    - LP: #744921
+  * dcdbas: force SMI to happen when expected
+    - LP: #744921
+  * Linux 2.6.32.36
+    - LP: #744921
+  * drm/radeon/kms: check AA resolve registers on r300, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * drm/radeon: fix regression with AA resolve checking, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * xen: events: do not unmask event channels on resume
+    - LP: #681083
+  * drm/radeon/kms: check AA resolve registers on r300
+    - LP: #754584
+  * drm/radeon: fix regression with AA resolve checking
+    - LP: #754584
+  * Linux 2.6.32.36+drm33.16
+    - LP: #754584
+  * ALSA: hda - Fix SPDIF out regression on ALC889
+    - LP: #764685
+  * ALSA: Fix yet another race in disconnection
+    - LP: #764685
+  * perf: Better fit max unprivileged mlock pages for tools needs
+    - LP: #764685
+  * myri10ge: fix rmmod crash
+    - LP: #764685
+  * cciss: fix lost command issue
+    - LP: #764685
+  * sound/oss/opl3: validate voice and channel indexes
+    - LP: #764685
+  * mac80211: initialize sta->last_rx in sta_info_alloc
+    - LP: #764685
+  * ses: show devices for enclosures with no page 7
+    - LP: #764685
+  * ses: Avoid kernel panic when lun 0 is not mapped
+    - LP: #764685
+  * eCryptfs: Unlock page in write_begin error path
+    - LP: #764685
+  * eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix
+    - LP: #764685
+  * staging: usbip: bugfixes related to kthread conversion
+    - LP: #764685
+  * staging: usbip: bugfix add number of packets for isochronous frames
+    - LP: #764685
+  * staging: usbip: bugfix for isochronous packets and optimization
+    - LP: #764685
+  * staging: hv: Fix GARP not sent after Quick Migration
+    - LP: #764685
+  * staging: hv: use sync_bitops when interacting with the hypervisor
+    - LP: #764685
+  * Relax si_code check in rt_sigqueueinfo and rt_tgsigqueueinfo
+    - LP: #764685
+  * xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1
+    - LP: #764685
+  * irda: validate peer name and attribute lengths
+    - LP: #764685
+  * irda: prevent heap corruption on invalid nickname
+    - LP: #764685
+  * nilfs2: fix data loss in mmap page write for hole blocks
+    - LP: #764685
+  * ASoC: Explicitly say registerless widgets have no register
+    - LP: #764685
+  * ALSA: ens1371: fix Creative Ectiva support
+    - LP: #764685
+  * ROSE: prevent heap corruption with bad facilities
+    - LP: #764685
+  * Btrfs: Fix uninitialized root flags for subvolumes
+    - LP: #764685
+  * x86, mtrr, pat: Fix one cpu getting out of sync during resume
+    - LP: #764685
+  * ath9k: fix a chip wakeup related crash in ath9k_start
+    - LP: #764685
+  * UBIFS: do not read flash unnecessarily
+    - LP: #764685
+  * UBIFS: fix oops on error path in read_pnode
+    - LP: #764685
+  * UBIFS: fix debugging failure in dbg_check_space_info
+    - LP: #764685
+  * quota: Don't write quota info in dquot_commit()
+    - LP: #764685
+  * mm: avoid wrapping vm_pgoff in mremap()
+    - LP: #764685
+  * p54usb: IDs for two new devices
+    - LP: #764685
+  * b43: allocate receive buffers big enough for max frame len + offset
+    - LP: #764685
+  * Bluetooth: sco: fix information leak to userspace
+    - LP: #764685
+  * bridge: netfilter: fix information leak
+    - LP: #764685
+  * Bluetooth: bnep: fix buffer overflow
+    - LP: #764685
+  * Bluetooth: add support for Apple MacBook Pro 8,2
+    - LP: #764685
+  * Treat writes as new when holes span across page boundaries
+    - LP: #764685
+  * char/tpm: Fix unitialized usage of data buffer
+    - LP: #764685
+  * netfilter: ip_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: arp_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: ipt_CLUSTERIP: fix buffer overflow
+    - LP: #764685
+  * ipv6: netfilter: ip6_tables: fix infoleak to userspace
+    - LP: #764685
+  * mfd: ab3100: world-writable debugfs *_priv files
+    - LP: #764685
+  * drivers/rtc/rtc-ds1511.c: world-writable sysfs nvram file
+    - LP: #764685
+  * drivers/misc/ep93xx_pwm.c: world-writable sysfs files
+    - LP: #764685
+  * econet: 4 byte infoleak to the network
+    - LP: #764685
+  * sound/oss: remove offset from load_patch callbacks
+    - LP: #764685
+  * sound: oss: midi_synth: check get_user() return value
+    - LP: #764685
+  * repair gdbstub to match the gdbserial protocol specification
+    - LP: #764685
+  * gro: Reset dev pointer on reuse
+    - LP: #764685
+  * gro: reset skb_iif on reuse
+    - LP: #764685
+  * x86, amd-ucode: Remove needless log messages
+    - LP: #764685
+  * x86, microcode, AMD: Extend ucode size verification
+    - LP: #764685
+  * powerpc/kexec: Add ifdef CONFIG_PPC_STD_MMU_64 to PPC64 code
+    - LP: #764685
+  * powerpc: Fix default_machine_crash_shutdown #ifdef botch
+    - LP: #764685
+  * Squashfs: handle corruption of directory structure
+    - LP: #764685
+  * sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
+    - LP: #764685
+  * atm/solos-pci: Don't include frame pseudo-header on transmit hex-dump
+    - LP: #764685
+  * ext4: fix credits computing for indirect mapped files
+    - LP: #764685
+  * nfsd: fix auth_domain reference leak on nlm operations
+    - LP: #764685
+  * CAN: Use inode instead of kernel address for /proc file
+    - LP: #764685
+  * exec: make argv/envp memory visible to oom-killer
+    - LP: #764685
+  * exec: copy-and-paste the fixes into compat_do_execve() paths
+    - LP: #764685
+  * xfs: zero proper structure size for geometry calls
+    - LP: #764685
+  * Linux 2.6.32.37
+    - LP: #764685
+  * Linux 2.6.32.38
+    - LP: #764685
+
+ -- Brad Figg <brad.figg@canonical.com>  Wed, 20 Apr 2011 18:25:39 -0700
+
+linux-ec2 (2.6.32-315.29) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-31.61
+
+  [ Ubuntu: 2.6.32-31.61 ]
+
+  * Release Tracking Bug
+    - LP: #754842
+  * x86, quirk: Fix SB600 revision check
+    - LP: #742056
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 14 Apr 2011 18:28:11 +0200
+
+linux-ec2 (2.6.32-315.28) lucid-proposed; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-31.60
+
+  [ Ubuntu: 2.6.32-31.60 ]
+
+  * Release Tracking Bug
+    - LP: #734950
+  * SAUCE: Clear new_profile in error path
+    - LP: #732700
+  * [Config] CONFIG_BOOT_PRINTK_DELAY=y
+    - LP: #733191
+  * Revert "drm/radeon/bo: add some fallback placements for VRAM only
+    objects."
+    - LP: #652934
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934
+  * xfs: always use iget in bulkstat
+    - LP: #692848
+  * drm/radeon/kms: make the mac rv630 quirk generic
+    - LP: #728687
+  * drm/radeon/kms: add pll debugging output
+    - LP: #728687
+  * drm/radeon: remove 0x4243 pci id
+    - LP: #728687
+  * drm/radeon/kms: fix s/r issues with bios scratch regs
+    - LP: #728687
+  * drm/i915/lvds: Add AOpen i915GMm-HFS to the list of false-positive LVDS
+    - LP: #728687
+  * drm/i915: Add dependency on CONFIG_TMPFS
+    - LP: #728687
+  * Linux 2.6.32.29+drm33.14
+    - LP: #728687
+  * NFSD: memory corruption due to writing beyond the stat array
+    - LP: #728687
+  * mptfusion: mptctl_release is required in mptctl.c
+    - LP: #728687
+  * mptfusion: Fix Incorrect return value in mptscsih_dev_reset
+    - LP: #728687
+  * ocfs2_connection_find() returns pointer to bad structure
+    - LP: #728687
+  * x25: decrement netdev reference counts on unload
+    - LP: #728687
+  * x86, hpet: Disable per-cpu hpet timer if ARAT is supported
+    - LP: #728687
+  * OHCI: work around for nVidia shutdown problem
+    - LP: #728687
+  * x86/pvclock: Zero last_value on resume
+    - LP: #728687
+  * av7110: check for negative array offset
+    - LP: #728687
+  * CRED: Fix get_task_cred() and task_state() to not resurrect dead
+    credentials
+    - LP: #728687
+  * bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion
+    - LP: #728687
+  * CRED: Fix kernel panic upon security_file_alloc() failure.
+    - LP: #728687
+  * CRED: Fix BUG() upon security_cred_alloc_blank() failure
+    - LP: #728687
+  * CRED: Fix memory and refcount leaks upon security_prepare_creds()
+    failure
+    - LP: #728687
+  * sendfile(): check f_op.splice_write() rather than f_op.sendpage()
+    - LP: #728687
+  * isdn: hisax: Replace the bogus access to irq stats
+    - LP: #728687
+  * ixgbe: add support for 82599 based Express Module X520-P2
+    - LP: #728687
+  * ixgbe: prevent speculative processing of descriptors before ready
+    - LP: #728687
+  * scsi_dh_alua: add netapp to dev list
+    - LP: #728687
+  * scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list
+    - LP: #728687
+  * dm raid1: fail writes if errors are not handled and log fails
+    - LP: #728687
+  * GFS2: Fix bmap allocation corner-case bug
+    - LP: #728687
+  * dm raid1: fix null pointer dereference in suspend
+    - LP: #728687
+  * sunrpc/cache: fix module refcnt leak in a failure path
+    - LP: #728687
+  * be2net: Maintain tx and rx counters in driver
+    - LP: #728687
+  * tcp: Make TCP_MAXSEG minimum more correct.
+    - LP: #728687
+  * nfsd: correctly handle return value from nfsd_map_name_to_*
+    - LP: #728687
+  * s390: remove task_show_regs
+    - LP: #728687
+  * PM / Hibernate: Return error code when alloc_image_page() fails
+    - LP: #728687
+  * fs/partitions: Validate map_count in Mac partition tables
+    - LP: #728687
+  * ALSA: HDA: Add position_fix quirk for an Asus device
+    - LP: #718402, #728687
+  * ALSA: caiaq - Fix possible string-buffer overflow
+    - LP: #728687
+  * radio-aimslab.c needs #include <linux/delay.h>
+    - LP: #728687
+  * ARM: Ensure predictable endian state on signal handler entry
+    - LP: #728687
+  * acer-wmi: Fix capitalisation of GUID
+    - LP: #728687
+  * eCryptfs: Copy up lower inode attrs in getattr
+    - LP: #728687
+  * platform: x86: acer-wmi: world-writable sysfs threeg file
+    - LP: #728687
+  * platform: x86: asus_acpi: world-writable procfs files
+    - LP: #728687
+  * platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial
+    files
+    - LP: #728687
+  * genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now
+    - LP: #728687
+  * usb: musb: omap2430: fix kernel panic on reboot
+    - LP: #728687
+  * USB: add quirks entry for Keytouch QWERTY Panel
+    - LP: #728687
+  * USB: Add Samsung SGH-I500/Android modem ID switch to visor driver
+    - LP: #728687
+  * USB: Add quirk for Samsung Android phone modem
+    - LP: #728687
+  * p54pci: update receive dma buffers before and after processing
+    - LP: #728687
+  * sierra: add new ID for Airprime/Sierra USB IP modem
+    - LP: #728687
+  * staging: usbip: vhci: update reference count for usb_device
+    - LP: #728687
+  * staging: usbip: vhci: give back URBs from in-flight unlink requests
+    - LP: #728687
+  * staging: usbip: vhci: refuse to enqueue for dead connections
+    - LP: #728687
+  * staging: usbip: vhci: use urb->dev->portnum to find port
+    - LP: #728687
+  * epoll: prevent creating circular epoll structures
+    - LP: #728687
+  * ldm: corrupted partition table can cause kernel oops
+    - LP: #728687
+  * md: correctly handle probe of an 'mdp' device.
+    - LP: #728687
+  * x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems
+    - LP: #728687
+  * xhci: Avoid BUG() in interrupt context
+    - LP: #728687
+  * xhci: Clarify some expressions in the TRB math
+    - LP: #728687
+  * xhci: Fix errors in the running total calculations in the TRB math
+    - LP: #728687
+  * xhci: Fix an error in count_sg_trbs_needed()
+    - LP: #728687
+  * x25: Do not reference freed memory.
+    - LP: #728687
+  * Linux 2.6.32.30
+    - LP: #728687
+  * Linux 2.6.32.31
+    - LP: #728687
+  * Ocfs2/refcounttree: Fix a bug for refcounttree to writeback clusters in
+    a right number.
+    - LP: #731226
+  * mfd: Fix NULL pointer due to non-initialized ucb1x00-ts absinfo
+    - LP: #731226
+  * x86: Use u32 instead of long to set reset vector back to 0
+    - LP: #731226
+  * fuse: fix hang of single threaded fuseblk filesystem
+    - LP: #731226
+  * clockevents: Prevent oneshot mode when broadcast device is periodic
+    - LP: #731226
+  * ext2: Fix link count corruption under heavy link+rename load
+    - LP: #731226
+  * sctp: Fix oops when sending queued ASCONF chunks
+    - LP: #731226
+  * virtio: set pci bus master enable bit
+    - LP: #731226
+  * netxen: fix set mac addr
+    - LP: #731226
+  * HID: add support for Acan FG-8100 barcode reader
+    - LP: #731226
+  * p54usb: add Senao NUB-350 usbid
+    - LP: #731226
+  * dccp: fix oops on Reset after close
+    - LP: #731226
+  * e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup
+    instead
+    - LP: #731226
+  * r8169: disable ASPM
+    - LP: #731226
+  * usb: iowarrior: don't trust report_size for buffer size
+    - LP: #731226
+  * arp_notify: unconditionally send gratuitous ARP for
+    NETDEV_NOTIFY_PEERS.
+    - LP: #731226
+  * CIFS: Fix oplock break handling (try #2)
+    - LP: #731226
+  * Linux 2.6.32.32
+    - LP: #731226
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 18 Mar 2011 18:23:16 +0100
+
+linux-ec2 (2.6.32-314.27) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Release Tracking Bug
+    - LP: #728089
+
+  [ Stefan Bader ]
+
+  * SAUCE: XEN: Import f9dee15f07cc3e6625734f3cf667054a5ff5ac2b
+    - LP: #717177
+  * SAUCE: XEN: Import 65d64895d4ed4250448ac6906de25777470b5180
+    - LP: #717177
+  * SAUCE: XEN: Import cf383fb0c59287a81d6e71ebb7fafffd104a3983
+    - LP: #717177
+  * SAUCE: XEN: Import ffd91af58e011821332cc56019d1709f7d9a8a54
+    - LP: #717177
+  * SAUCE: XEN: Import 97a21d3ae6477ef00e39f21e47ce767a8ca1a22a
+    - LP: #717177
+  * SAUCE: XEN: Import b5d6492343e5897eba863ed1d08ca51552657d1f
+    - LP: #717177
+  * SAUCE: XEN: Import 9fb860778805809529f4c27b896370f2a945e945
+    - LP: #717177
+  * SAUCE: XEN: Import 20af80bf13116eb2d0d4bd6a307a4260cd277095
+    - LP: #717177
+  * SAUCE: XEN: Import 481710c9b5d154e81d388e9460fa2851a4ea7c94
+    - LP: #717177
+  * SAUCE: XEN: Import 9512754e274895426d5305d09a4c667d8621f420
+    - LP: #717177
+  * SAUCE: XEN: Update import 2444b629ee518745f54c2f7cf9e4de3d48e834cb
+    - LP: #717177
+  * SAUCE: XEN: Import 28995d0c0ef1958ecffdcc80091c46233daea29a
+    - LP: #717177
+  * SAUCE: XEN: Import fc04955bae3662eecaa8216694fd82b36256cfc6
+    - LP: #717177
+  * SAUCE: XEN: Import 4bbd3ea6754dc11fdb96a8ab9dfa13e24b1a6599
+    - LP: #717177
+  * SAUCE: XEN: Import 5a6ca212d5400dfcd8734da1f282b83a01a04d9e
+    - LP: #717177
+  * SAUCE: XEN: Import cde0c191416d1470a2aa30d893f7ea987363386b
+    - LP: #717177
+  * SAUCE: XEN: Import fe304738902627ec07c5195664ddb7a6f7750272
+    - LP: #717177
+  * SAUCE: XEN: Import 941f392437b3005d2d220a7254d48fbc342b6829
+    - LP: #717177
+  * SAUCE: XEN: Import 7ad50ac196fde9cf57a55b5908764227d9d7f8e6
+    - LP: #717177
+  * SAUCE: XEN: Import eeb31bcc98f8497dc83c5e7c8ef5c9a9438cb689
+    - LP: #717177
+  * SAUCE: XEN: Import d5324680becdc93bd37cbbc9581c727959c57ad9
+    - LP: #717177
+  * SAUCE: XEN: Import f2bb11b1573330fca6ddba33a5cff3695d1a690c
+    - LP: #717177
+  * SAUCE: XEN: Import 7e3ff59bf997c554ebd14b17b9ba4246448e80c7
+    - LP: #717177
+  * SAUCE: XEN: Import c19aaf77a85ba61de84de2bf6922e269d78223a0
+    - LP: #717177
+  * SAUCE: XEN: Import 77b49ffdcd22f66180778085716512d508ab2617
+    - LP: #717177
+  * SAUCE: XEN: Import 34ebf644aafc699db42a5c2d109b6f057ee6b4f3
+    - LP: #717177
+  * SAUCE: XEN: Import c4dad435c692830c634ab7001b62b6a90b5ae530
+    - LP: #717177
+  * SAUCE: XEN: Import 52c82b295371158c61f8b06d7a03daaaeedfea00
+    - LP: #717177
+  * SAUCE: XEN: Import f3a8bea7094f487ed6139a6b6254d0e4147a866d
+    - LP: #717177
+  * SAUCE: XEN: Import 2e911f0f7f1590fc8c4cb2a331ac1c1799a8385b
+    - LP: #717177
+  * SAUCE: XEN: Import 7aa0c2220a675805f38b43313228544a0cce7488
+    - LP: #717177
+  * SAUCE: XEN: Import a805c0009da4770f72dab3f3c71cd263f79894aa
+    - LP: #717177
+  * SAUCE: XEN: Import 26ab8408157fbbc669e1aab1f271bb3cb1c433d0
+    - LP: #717177
+  * SAUCE: XEN: Import ca51d9445c9b51d6b1c800c9c04e5472d55f0845
+    - LP: #717177
+  * SAUCE: XEN: Import 831d52bc153971b70e64eccfbed2b232394f22f8
+    - LP: #723819
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-30.59
+
+  [ Ubuntu: 2.6.32-30.59 ]
+
+  * Release Tracking Bug
+    - LP: #727336
+  * [Config] CONFIG_IRQ_TIME_ACCOUNTING=n
+    - LP: #723819
+  * virtio_net: Add schedule check to napi_enable call
+    - LP: #579276
+  * NFS: fix the return value of nfs_file_fsync()
+    - LP: #585657
+  * block: check for proper length of iov entries earlier in
+    blk_rq_map_user_iov(), CVE-2010-4163
+    - LP: #721504
+    - CVE-2010-4163
+  * filter: make sure filters dont read uninitialized memory
+    - LP: #721282
+    - CVE-2010-4158
+  * tty: Make tiocgicount a handler, CVE-2010-4076, CVE-2010-4077
+    - LP: #720189
+    - CVE-2010-4077
+  * staging: usbip: remove double giveback of URB
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD SB800
+    - LP: #723819
+  * rt2x00: add device id for windy31 usb device
+    - LP: #723819
+  * ALSA: snd-usb-us122l: Fix missing NULL checks
+    - LP: #723819
+  * hwmon: (via686a) Initialize fan_div values
+    - LP: #723819
+  * USB: serial: handle Data Carrier Detect changes
+    - LP: #723819
+  * USB: CP210x Add two device IDs
+    - LP: #723819
+  * USB: CP210x Removed incorrect device ID
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for Cypress ATACB
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for TrekStor DataStation maxi g.u
+    external hard drive enclosure
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for CamSport Evo
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for Coby MP3 player
+    - LP: #723819
+  * USB: serial: Updated support for ICOM devices
+    - LP: #723819
+  * USB: adding USB support for Cinterion's HC2x, EU3 and PH8 products
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD Hudson
+    - LP: #723819
+  * USB: EHCI: fix DMA deallocation bug
+    - LP: #723819
+  * USB: g_printer: fix bug in module parameter definitions
+    - LP: #723819
+  * USB: io_edgeport: fix the reported firmware major and minor
+    - LP: #723819
+  * USB: ti_usb: fix module removal
+    - LP: #723819
+  * USB: Storage: Add unusual_devs entry for VTech Kidizoom
+    - LP: #723819
+  * USB: ftdi_sio: add ST Micro Connect Lite uart support
+    - LP: #723819
+  * USB: cdc-acm: Adding second ACM channel support for Nokia N8
+    - LP: #723819
+  * USB: ftdi_sio: Add VID=0x0647, PID=0x0100 for Acton Research
+    spectrograph
+    - LP: #723819
+  * USB: prevent buggy hubs from crashing the USB stack
+    - LP: #723819
+  * staging: comedi: add support for newer jr3 1-channel pci board
+    - LP: #723819
+  * staging: comedi: ni_labpc: Use shared IRQ for PCMCIA card
+    - LP: #723819
+  * Staging: hv: fix sysfs symlink on hv block device
+    - LP: #723819
+  * staging: hv: Enable sending GARP packet after live migration
+    - LP: #723819
+  * hvc_iucv: allocate memory buffers for IUCV in zone DMA
+    - LP: #723819
+  * iwlagn: enable only rfkill interrupt when device is down
+    - LP: #723819
+  * ath9k: Fix bug in delimiter padding computation
+    - LP: #723819
+  * correct vdso version string
+    - LP: #723819
+  * fix medium error problems with some arrays which can cause data
+    corruption
+    - LP: #723819
+  * libsas: fix runaway error handler problem
+    - LP: #723819
+  * mpt2sas: Fix device removal handshake for zoned devices
+    - LP: #723819
+  * mpt2sas: Correct resizing calculation for max_queue_depth
+    - LP: #723819
+  * mpt2sas: Kernel Panic during Large Topology discovery
+    - LP: #723819
+  * radio-aimslab.c: Fix gcc 4.5+ bug
+    - LP: #723819
+  * em28xx: Fix audio input for Terratec Grabby
+    - LP: #723819
+  * ALSA : au88x0 - Limit number of channels to fix Oops via OSS emu
+    - LP: #723819
+  * ALSA: HDA: Fix dmesg output of HDMI supported bits
+    - LP: #723819
+  * ALSA: hda - Fix memory leaks in conexant jack arrays
+    - LP: #723819
+  * input: bcm5974: Add support for MacBookAir3
+    - LP: #723819
+  * ALSA: hrtimer: handle delayed timer interrupts
+    - LP: #723819
+  * ASoC: WM8990: msleep() takes milliseconds not jiffies
+    - LP: #723819
+  * ASoC: Blackfin AC97: fix build error after multi-component update
+    - LP: #723819
+  * NFS: Fix "kernel BUG at fs/aio.c:554!"
+    - LP: #723819
+  * rtc-cmos: fix suspend/resume
+    - LP: #723819
+  * iwlagn: Re-enable RF_KILL interrupt when down
+    - LP: #723819
+  * rapidio: fix hang on RapidIO doorbell queue full condition
+    - LP: #723819
+  * PCI: pci-stub: ignore zero-length id parameters
+    - LP: #723819
+  * virtio: remove virtio-pci root device
+    - LP: #723819
+  * ds2760_battery: Fix calculation of time_to_empty_now
+    - LP: #723819
+  * p54: fix sequence no. accounting off-by-one error
+    - LP: #723819
+  * i2c: Unregister dummy devices last on adapter removal
+    - LP: #723819
+  * serial: unbreak billionton CF card
+    - LP: #723819
+  * ptrace: use safer wake up on ptrace_detach()
+    - LP: #723819
+  * x86, mtrr: Avoid MTRR reprogramming on BP during boot on UP platforms
+    - LP: #723819
+  * fix jiffy calculations in calibrate_delay_direct to handle overflow
+    - LP: #723819
+  * USB: serial: pl2303: Hybrid reader Uniform HCR331
+    - LP: #723819
+  * drivers: update to pl2303 usb-serial to support Motorola cables
+    - LP: #723819
+  * klist: Fix object alignment on 64-bit.
+    - LP: #723819
+  * powerpc: Fix some 6xx/7xxx CPU setup functions
+    - LP: #723819
+  * parisc : Remove broken line wrapping handling pdc_iodc_print()
+    - LP: #723819
+  * kernel/smp.c: fix smp_call_function_many() SMP race
+    - LP: #723819
+  * hostap_cs: fix sleeping function called from invalid context
+    - LP: #723819
+  * md: fix regression with re-adding devices to arrays with no metadata
+    - LP: #723819
+  * pata_mpc52xx: inherit from ata_bmdma_port_ops
+    - LP: #723819
+  * TPM: Long default timeout fix
+    - LP: #723819
+  * tpm_tis: Use timeouts returned from TPM
+    - LP: #723819
+  * SELinux: define permissions for DCB netlink messages
+    - LP: #723819
+  * SELinux: do not compute transition labels on mountpoint labeled
+    filesystems
+    - LP: #723819
+  * ieee80211: correct IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK macro
+    - LP: #723819
+  * dm: dont take i_mutex to change device size
+    - LP: #723819
+  * dm mpath: disable blk_abort_queue
+    - LP: #723819
+  * x86, mm: avoid possible bogus tlb entries by clearing prev mm_cpumask
+    after switching mm
+    - LP: #723819
+  * usb: Realloc xHCI structures after a hub is verified.
+    - LP: #723819
+  * sched: Remove USER_SCHED
+    - LP: #723819
+  * sched: Remove remaining USER_SCHED code
+    - LP: #723819
+  * sched: Move sched_avg_update() to update_cpu_load()
+    - LP: #723819
+  * sched: Increment cache_nice_tries only on periodic lb
+    - LP: #723819
+  * sched: Try not to migrate higher priority RT tasks
+    - LP: #723819
+  * sched: Give CPU bound RT tasks preference
+    - LP: #723819
+  * sched: suppress RCU lockdep splat in task_fork_fair
+    - LP: #723819
+  * sched: fix RCU lockdep splat from task_group()
+    - LP: #723819
+  * sched: Do not consider SCHED_IDLE tasks to be cache hot
+    - LP: #723819
+  * sched: Set group_imb only a task can be pulled from the busiest cpu
+    - LP: #723819
+  * sched: Force balancing on newidle balance if local group has capacity
+    - LP: #723819
+  * sched: Drop group_capacity to 1 only if local group has extra capacity
+    - LP: #723819
+  * sched: Fix softirq time accounting
+    - LP: #723819
+  * sched: Consolidate account_system_vtime extern declaration
+    - LP: #723819
+  * sched: Remove unused PF_ALIGNWARN flag
+    - LP: #723819
+  * sched: Add a PF flag for ksoftirqd identification
+    - LP: #723819
+  * sched: Add IRQ_TIME_ACCOUNTING, finer accounting of irq time
+    - LP: #723819
+  * x86: Add IRQ_TIME_ACCOUNTING
+    - LP: #723819
+  * sched: Do not account irq time to current task
+    - LP: #723819
+  * sched: Remove irq time from available CPU power
+    - LP: #723819
+  * sched: Call tick_check_idle before __irq_enter
+    - LP: #723819
+  * sched: Export account_system_vtime()
+    - LP: #723819
+  * sched, cgroup: Fixup broken cgroup movement
+    - LP: #723819
+  * sched: Use group weight, idle cpu metrics to fix imbalances during idle
+    - LP: #723819
+  * sched: Fix cross-sched-class wakeup preemption
+    - LP: #723819
+  * sched: Fix volanomark performance regression
+    - LP: #723819
+  * sched: Fix idle balancing
+    - LP: #723819
+  * sched: Fix wake_affine() vs RT tasks
+    - LP: #723819
+  * sched: Remove some dead code
+    - LP: #723819
+  * kernel/user.c: add lock release annotation on free_user()
+    - LP: #723819
+  * Linux 2.6.32.29
+    - LP: #723819
+  * rds: Integer overflow in RDS cmsg handling, CVE-2010-4175
+    - LP: #721455
+    - CVE-2010-4175
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 02 Mar 2011 14:59:29 +0100
+
+linux-ec2 (2.6.32-313.26) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #716657
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #712864
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-29.58
+
+  [ Ubuntu: 2.6.32-29.58 ]
+
+  * Release Tracking Bug
+    - LP: #716551
+  * net: fix rds_iovec page count overflow, CVE-2010-3865
+    - LP: #709153
+    - CVE-2010-3865
+  * net: ax25: fix information leak to userland, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: ax25: fix information leak to userland harder, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: packet: fix information leak to userland, CVE-2010-3876
+    - LP: #710714
+    - CVE-2010-3876
+  * net: tipc: fix information leak to userland, CVE-2010-3877
+    - LP: #711291
+    - CVE-2010-3877
+  * inet_diag: Make sure we actually run the same bytecode we audited,
+    CVE-2010-3880
+    - LP: #711865
+    - CVE-2010-3880
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 10 Feb 2011 11:03:57 -0800
+
+linux-ec2 (2.6.32-313.25) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Tracking Bug
+    - LP: #708890
+
+  [ Andrew Dickinson ]
+
+  * SAUCE: sched: Prevent divide by zero when cpu_power is 0
+    - LP: #614853
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-29.57
+
+  [ Stefan Bader ]
+
+  * SAUCE: sched: Try tp catch cpu_power being set to 0
+    - LP: #614853
+
+  [ Upstream Kernel Changes ]
+
+  * SRU: xen: events: do not unmask event channels on resume
+    - LP: #681083
+
+  [ Ubuntu: 2.6.32-29.57 ]
+
+  * Tracking Bug
+    - LP: #708864
+  * [Config] Set CONFIG_NR_CPUS=256 for amd64 server
+    - LP: #706058
+  * Input: i8042 - introduce 'notimeout' blacklist for Dell Vostro V13
+    - LP: #380126
+  * tun: avoid BUG, dump packet on GSO errors
+    - LP: #698883
+  * TTY: Fix error return from tty_ldisc_open()
+    - LP: #705045
+  * x86, hotplug: Use mwait to offline a processor, fix the legacy case
+    - LP: #705045
+  * fuse: verify ioctl retries
+    - LP: #705045
+  * fuse: fix ioctl when server is 32bit
+    - LP: #705045
+  * ALSA: hda: Use model=lg quirk for LG P1 Express to enable playback and
+    capture
+    - LP: #595482, #705045
+  * nohz: Fix printk_needs_cpu() return value on offline cpus
+    - LP: #705045
+  * nohz: Fix get_next_timer_interrupt() vs cpu hotplug
+    - LP: #705045
+  * nfsd: Fix possible BUG_ON firing in set_change_info
+    - LP: #705045
+  * NFS: Fix fcntl F_GETLK not reporting some conflicts
+    - LP: #705045
+  * sunrpc: prevent use-after-free on clearing XPT_BUSY
+    - LP: #705045
+  * hwmon: (adm1026) Allow 1 as a valid divider value
+    - LP: #705045
+  * hwmon: (adm1026) Fix setting fan_div
+    - LP: #705045
+  * amd64_edac: Fix interleaving check
+    - LP: #705045
+  * IB/uverbs: Handle large number of entries in poll CQ
+    - LP: #705045
+  * PM / Hibernate: Fix PM_POST_* notification with user-space suspend
+    - LP: #705045
+  * ACPICA: Fix Scope() op in module level code
+    - LP: #705045
+  * ACPI: EC: Add another dmi match entry for MSI hardware
+    - LP: #705045
+  * orinoco: fix TKIP countermeasure behaviour
+    - LP: #705045
+  * orinoco: clear countermeasure setting on commit
+    - LP: #705045
+  * x86, amd: Fix panic on AMD CPU family 0x15
+    - LP: #705045
+  * md: fix bug with re-adding of partially recovered device.
+    - LP: #705045
+  * tracing: Fix panic when lseek() called on "trace" opened for writing
+    - LP: #705045
+  * x86, gcc-4.6: Use gcc -m options when building vdso
+    - LP: #705045
+  * x86: Enable the intr-remap fault handling after local APIC setup
+    - LP: #705045
+  * x86, vt-d: Handle previous faults after enabling fault handling
+    - LP: #705045
+  * x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode
+    - LP: #705045
+  * x86, vt-d: Quirk for masking vtd spec errors to platform error handling
+    logic
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove, again
+    - LP: #705045
+  * HID: hidraw: fix window in hidraw_release
+    - LP: #705045
+  * bfa: fix system crash when reading sysfs fc_host statistics
+    - LP: #705045
+  * net: release dst entry while cache-hot for GSO case too
+    - LP: #705045
+  * install_special_mapping skips security_file_mmap check.
+    - LP: #705045
+  * USB: misc: uss720.c: add another vendor/product ID
+    - LP: #705045
+  * USB: ftdi_sio: Add D.O.Tec PID
+    - LP: #705045
+  * USB: usb-storage: unusual_devs entry for the Samsung YP-CP3
+    - LP: #705045
+  * p54usb: add 5 more USBIDs
+    - LP: #705045
+  * p54usb: New USB ID for Gemtek WUBI-100GW
+    - LP: #705045
+  * sound: Prevent buffer overflow in OSS load_mixer_volumes
+    - LP: #705045
+  * mv_xor: fix race in tasklet function
+    - LP: #705045
+  * ima: fix add LSM rule bug
+    - LP: #705045
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #705045
+  * ALSA: hda: Use LPIB quirk for Dell Inspiron m101z/1120
+    - LP: #705045
+  * block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead
+    - LP: #705045
+  * sctp: Fix a race between ICMP protocol unreachable and connect()
+    - LP: #705045
+  * posix-cpu-timers: workaround to suppress the problems with mt exec
+    - LP: #705045
+  * Linux 2.6.32.28
+    - LP: #705045
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * drm/ttm: Clear the ghost cpu_writers flag on
+    ttm_buffer_object_transfer.
+    - LP: #708769
+  * drm/kms: remove spaces from connector names (v2)
+    - LP: #708769
+  * Linux 2.6.32.28+drm33.13
+    - LP: #708769
+
+  [ Ubuntu: 2.6.32-28.56 ]
+
+  * Tracking Bug
+    - LP: #705565
+  * Just a build number increment for a new upload. There was an issue
+    in the previous upload that prevented ARMEL from building. The
+    issue has been resolved in the PPA and a new upload should produce
+    the requisite images.
+
+  [ Ubuntu: 2.6.32-28.55 ]
+
+  * Another version bump because of abi check failure
+  * Tracking Bug
+    - LP: #699885
+
+  [ Ubuntu: 2.6.32-28.54 ]
+
+  * Another version bump because of upload failure
+
+  [ Ubuntu: 2.6.32-28.53 ]
+
+  * Another version bump because of upload failure
+
+ -- Brad Figg <brad.figg@canonical.com>  Wed, 19 Jan 2011 12:23:49 -0800
+
+linux-ec2 (2.6.32-312.24) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Tracking bug
+  - LP: #698345
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-28.52
+
+  [ Ubuntu: 2.6.32-28.52 ]
+
+
+  [ Ubuntu: 2.6.32-28.51 ]
+
+  * bumped version due to build fail
+
+  [ Ubuntu: 2.6.32-28.50 ]
+
+  * SAUCE: Change nodelayacct boot parameter polarity.
+    - LP: #493156
+  * [Config] CONFIG_TASK_DELAY_ACCT=y
+    - LP: #493156
+  * ipc: initialize structure memory to zero for compat functions
+  * tcp: Increase TCP_MAXSEG socket option minimum.
+    - CVE-2010-4165
+  * perf_events: Fix perf_counter_mmap() hook in mprotect()
+    - CVE-2010-4169
+  * af_unix: limit unix_tot_inflight
+    - CVE-2010-4249
+  * AppArmor: fix the upper bound check for the next/check table
+    - LP: #581525
+  * NFS: Fix panic after nfs_umount()
+    - LP: #683938
+  * block: Ensure physical block size is unsigned int
+    - LP: #688669
+  * block: limit vec count in bio_kmalloc() and bio_alloc_map_data()
+    - LP: #688669
+  * block: take care not to overflow when calculating total iov length
+    - LP: #688669
+  * block: check for proper length of iov entries in blk_rq_map_user_iov()
+    - LP: #688669
+  * jme: Fix PHY power-off error
+    - LP: #688669
+  * irda: Fix parameter extraction stack overflow
+    - LP: #688669
+  * irda: Fix heap memory corruption in iriap.c
+    - LP: #688669
+  * i2c-pca-platform: Change device name of request_irq
+    - LP: #688669
+  * microblaze: Fix build with make 3.82
+    - LP: #688669
+  * Staging: asus_oled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * Staging: asus_oled: fix up my fixup for some sysfs attribute
+    permissions
+    - LP: #688669
+  * Staging: line6: fix up some sysfs attribute permissions
+    - LP: #688669
+  * hpet: fix unwanted interrupt due to stale irq status bit
+    - LP: #688669
+  * hpet: unmap unused I/O space
+    - LP: #688669
+  * olpc_battery: Fix endian neutral breakage for s16 values
+    - LP: #688669
+  * percpu: fix list_head init bug in __percpu_counter_init()
+    - LP: #688669
+  * um: remove PAGE_SIZE alignment in linker script causing kernel
+    segfault.
+    - LP: #688669
+  * um: fix global timer issue when using CONFIG_NO_HZ
+    - LP: #688669
+  * numa: fix slab_node(MPOL_BIND)
+    - LP: #688669
+  * hwmon: (lm85) Fix ADT7468 frequency table
+    - LP: #688669
+  * mm: fix return value of scan_lru_pages in memory unplug
+    - LP: #688669
+  * mm: fix is_mem_section_removable() page_order BUG_ON check
+    - LP: #688669
+  * ssb: b43-pci-bridge: Add new vendor for BCM4318
+    - LP: #688669
+  * sgi-xpc: XPC fails to discover partitions with all nasids above 128
+    - LP: #688669
+  * xen: ensure that all event channels start off bound to VCPU 0
+    - LP: #688669
+  * xen: don't bother to stop other cpus on shutdown/reboot
+    - LP: #688669
+  * sys_semctl: fix kernel stack leakage
+    - LP: #688669
+  * net: NETIF_F_HW_CSUM does not imply FCoE CRC offload
+    - LP: #688669
+  * drivers/char/vt_ioctl.c: fix VT_OPENQRY error value
+    - LP: #688669
+  * viafb: use proper register for colour when doing fill ops
+    - LP: #688669
+  * eCryptfs: Clear LOOKUP_OPEN flag when creating lower file
+    - LP: #688669
+  * md/raid1: really fix recovery looping when single good device fails.
+    - LP: #688669
+  * md: fix return value of rdev_size_change()
+    - LP: #688669
+  * x86: AMD Northbridge: Verify NB's node is online
+    - LP: #688669
+  * tty: prevent DOS in the flush_to_ldisc
+    - LP: #688669
+  * TTY: restore tty_ldisc_wait_idle
+    - LP: #688669
+  * tty_ldisc: Fix BUG() on hangup
+    - LP: #688669
+  * TTY: ldisc, fix open flag handling
+    - LP: #688669
+  * KVM: VMX: fix vmx null pointer dereference on debug register access
+    - LP: #688669
+    - CVE-2010-0435
+  * KVM: x86: fix information leak to userland
+    - LP: #688669
+  * firewire: cdev: fix information leak
+    - LP: #688669
+  * firewire: core: fix an information leak
+    - LP: #688669
+  * firewire: ohci: fix buffer overflow in AR split packet handling
+    - LP: #688669
+  * firewire: ohci: fix race in AR split packet handling
+    - LP: #688669
+  * ALSA: ac97: Apply quirk for Dell Latitude D610 binding Master and
+    Headphone controls
+    - LP: #669279, #688669
+  * ALSA: HDA: Add an extra DAC for Realtek ALC887-VD
+    - LP: #688669
+  * ALSA: hda: Use "alienware" model quirk for another SSID
+    - LP: #683695, #688669
+  * netfilter: nf_conntrack: allow nf_ct_alloc_hashtable() to get highmem
+    pages
+    - LP: #688669
+  * latencytop: fix per task accumulator
+    - LP: #688669
+  * mm/vfs: revalidate page->mapping in do_generic_file_read()
+    - LP: #688669
+  * bio: take care not overflow page count when mapping/copying user data
+    - LP: #688669
+  * libata-scsi passthru: fix bug which truncated LBA48 return values
+    - LP: #688669
+  * libata: fix NULL sdev dereference race in atapi_qc_complete()
+    - LP: #688669
+  * PCI: fix size checks for mmap() on /proc/bus/pci files
+    - LP: #688669
+  * PCI: fix offset check for sysfs mmapped files
+    - LP: #688669
+  * efifb: check that the base address is plausible on pci systems
+    - LP: #688669
+  * USB: gadget: AT91: fix typo in atmel_usba_udc driver
+    - LP: #688669
+  * USB: ftdi_sio: add device IDs for Milkymist One JTAG/serial
+    - LP: #688669
+  * USB: option: fix when the driver is loaded incorrectly for some Huawei
+    devices.
+    - LP: #688669
+  * usb: misc: sisusbvga: fix information leak to userland
+    - LP: #688669
+  * usb: misc: iowarrior: fix information leak to userland
+    - LP: #688669
+  * usb: core: fix information leak to userland
+    - LP: #688669
+  * USB: EHCI: fix obscure race in ehci_endpoint_disable
+    - LP: #688669
+  * USB: storage: sierra_ms: fix sysfs file attribute
+    - LP: #688669
+  * USB: atm: ueagle-atm: fix up some permissions on the sysfs files
+    - LP: #688669
+  * USB: misc: cypress_cy7c63: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: misc: usbled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes"
+    - LP: #688669
+  * USB: misc: trancevibrator: fix up a sysfs attribute permission
+    - LP: #688669
+  * USB: misc: usbsevseg: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: Add ID for RT Systems USB-29B radio cable
+    - LP: #688669
+  * USB: serial: ftdi_sio: Vardaan USB RS422/485 converter PID added
+    - LP: #688669
+  * acpi-cpufreq: fix a memleak when unloading driver
+    - LP: #688669
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #688669
+  * fuse: fix attributes after open(O_TRUNC)
+    - LP: #688669
+  * do_exit(): make sure that we run with get_fs() == USER_DS
+    - LP: #688669
+  * uml: disable winch irq before freeing handler data
+    - LP: #688669
+  * backlight: grab ops_lock before testing bd->ops
+    - LP: #688669
+  * nommu: yield CPU while disposing VM
+    - LP: #688669
+  * DECnet: don't leak uninitialized stack byte
+    - LP: #688669
+  * ARM: 6489/1: thumb2: fix incorrect optimisation in usracc
+    - LP: #688669
+  * ARM: 6482/2: Fix find_next_zero_bit and related assembly
+    - LP: #688669
+  * Staging: frontier: fix up some sysfs attribute permissions
+    - LP: #688669
+  * staging: rtl8187se: Change panic to warn when RF switch turned off
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_ioctl
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_write
+    - LP: #688669
+  * gianfar: Fix crashes on RX path (Was Re: [Bugme-new] [Bug 19692] New:
+    linux-2.6.36-rc5 crash with gianfar ethernet at full line rate traffic)
+    - LP: #688669
+  * Limit sysctl_tcp_mem and sysctl_udp_mem initializers to prevent integer
+    overflows.
+    - LP: #688669
+  * sparc64: Fix race in signal instruction flushing.
+    - LP: #688669
+  * sparc: Don't mask signal when we can't setup signal frame.
+    - LP: #688669
+  * sparc: Prevent no-handler signal syscall restart recursion.
+    - LP: #688669
+  * x86, UV: Delete unneeded boot messages
+    - LP: #688669
+  * x86, UV: Fix initialization of max_pnode
+    - LP: #688669
+  * drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook
+    Pro 5,1
+    - LP: #688669
+  * efifb: support the EFI framebuffer on more Apple hardware
+    - LP: #688669
+  * V4L/DVB (13154): uvcvideo: Handle garbage at the end of streaming
+    interface descriptors
+    - LP: #688669
+  * Input: i8042 - add Sony VAIO VPCZ122GX to nomux list
+    - LP: #688669
+  * x25: Patch to fix bug 15678 - x25 accesses fields beyond end of packet.
+    - LP: #688669
+  * memory corruption in X.25 facilities parsing
+    - LP: #688669
+  * can-bcm: fix minor heap overflow
+    - LP: #688669
+  * V4L/DVB: ivtvfb: prevent reading uninitialized stack memory
+    - LP: #688669
+  * x25: Prevent crashing when parsing bad X.25 facilities
+    - LP: #688669
+  * crypto: padlock - Fix AES-CBC handling on odd-block-sized input
+    - LP: #688669
+  * x86-32: Separate 1:1 pagetables from swapper_pg_dir
+    - LP: #688669
+  * x86, mm: Fix CONFIG_VMSPLIT_1G and 2G_OPT trampoline
+    - LP: #688669
+  * x86-32: Fix dummy trampoline-related inline stubs
+    - LP: #688669
+  * rds: Integer overflow in RDS cmsg handling
+    - LP: #688669
+  * net: Truncate recvfrom and sendto length to INT_MAX.
+    - LP: #688669
+  * net: Limit socket I/O iovec total length to INT_MAX.
+    - LP: #688669
+  * nmi: fix clock comparator revalidation
+    - LP: #688669
+  * UV - XPC: pass nasid instead of nid to gru_create_message_queue
+    - LP: #688669
+  * x86: uv: XPC receive message reuse triggers invalid BUG_ON()
+    - LP: #688669
+  * X86: uv: xpc_make_first_contact hang due to not accepting ACTIVE state
+    - LP: #688669
+  * x86: uv: xpc NULL deref when mesq becomes empty
+    - LP: #688669
+  * Linux 2.6.32.27
+    - LP: #688669
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 06 Jan 2011 14:07:09 -0800
+
+linux-ec2 (2.6.32-311.23) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-27.49
+
+  [ Upstream Kernel Changes ]
+
+  * xen, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * xen, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * xen: Match cpu_get_cap() with upstream changes
+    - LP: #668380
+
+  [ Ubuntu: 2.6.32-27.49 ]
+
+  * Revert "SAUCE: AF_ECONET prevent kernel stack overflow"
+  * Revert "SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges"
+  * Revert "SAUCE: AF_ECONET saddr->cookie prevent NULL pointer
+    dereference"
+  * [Config] Added be2net, be2scsi to udebs
+    - LP: #628776
+  * [Config] Use correct be2iscsi module name in d-i/modules/scsi-modules
+    - LP: #628776
+  * Revert "(pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume"
+  * Revert "mm: (pre-stable) Move vma_stack_continue into mm.h"
+  * x86, cpu: After uncapping CPUID, re-run CPU feature detection
+    - LP: #668380
+  * ALSA: sound/pci/rme9652: prevent reading uninitialized stack memory
+    - LP: #668380
+  * ALSA: oxygen: fix analog capture on Claro halo cards
+    - LP: #668380
+  * ALSA: hda - Add Dell Latitude E6400 model quirk
+    - LP: #643891, #668380
+  * ALSA: rawmidi: fix oops (use after free) when unloading a driver module
+    - LP: #668380
+  * USB: fix bug in initialization of interface minor numbers
+    - LP: #668380
+  * usb: musb: gadget: fix kernel panic if using out ep with FIFO_TXRX
+    style
+    - LP: #668380
+  * usb: musb: gadget: restart request on clearing endpoint halt
+    - LP: #668380
+  * oprofile: Add Support for Intel CPU Family 6 / Model 29
+    - LP: #668380
+  * RDMA/cxgb3: Turn off RX coalescing for iWARP connections
+    - LP: #668380
+  * mmc: sdhci-s3c: fix NULL ptr access in sdhci_s3c_remove
+    - LP: #668380
+  * x86/amd-iommu: Set iommu configuration flags in enable-loop
+    - LP: #668380
+  * x86/amd-iommu: Fix rounding-bug in __unmap_single
+    - LP: #668380
+  * x86/amd-iommu: Work around S3 BIOS bug
+    - LP: #668380
+  * tracing/x86: Don't use mcount in pvclock.c
+    - LP: #668380
+  * tracing/x86: Don't use mcount in kvmclock.c
+    - LP: #668380
+  * v4l1: fix 32-bit compat microcode loading translation
+    - LP: #668380
+  * V4L/DVB: cx231xx: Avoid an OOPS when card is unknown (card=0)
+    - LP: #668380
+  * V4L/DVB (13966): DVB-T regression fix for saa7134 cards
+    - LP: #668380
+  * Input: joydev - fix JSIOCSAXMAP ioctl
+    - LP: #668380
+  * x86, hpet: Fix bogus error check in hpet_assign_irq()
+    - LP: #668380
+  * x86, irq: Plug memory leak in sparse irq
+    - LP: #668380
+  * ubd: fix incorrect sector handling during request restart
+    - LP: #668380
+  * ring-buffer: Fix typo of time extends per page
+    - LP: #668380
+  * dmaengine: fix interrupt clearing for mv_xor
+    - LP: #668380
+  * hrtimer: Preserve timer state in remove_hrtimer()
+    - LP: #668380
+  * i2c-pca: Fix waitforcompletion() return value
+    - LP: #668380
+  * wext: fix potential private ioctl memory content leak
+    - LP: #668380
+  * atl1: fix resume
+    - LP: #668380
+  * x86, AMD, MCE thresholding: Fix the MCi_MISCj iteration order
+    - LP: #668380
+  * De-pessimize rds_page_copy_user
+    - LP: #668380
+  * xfrm4: strip ECN and IP Precedence bits in policy lookup
+    - LP: #668380
+  * tcp: Fix >4GB writes on 64-bit.
+    - LP: #668380
+  * net: Fix the condition passed to sk_wait_event()
+    - LP: #668380
+  * Phonet: Correct header retrieval after pskb_may_pull
+    - LP: #668380
+  * net: Fix IPv6 PMTU disc. w/ asymmetric routes
+    - LP: #668380
+  * ip: fix truesize mismatch in ip fragmentation
+    - LP: #668380
+  * net: clear heap allocations for privileged ethtool actions
+    - LP: #668380
+  * tcp: Fix race in tcp_poll
+    - LP: #668380
+  * netxen: dont set skb->truesize
+    - LP: #668380
+  * net: blackhole route should always be recalculated
+    - LP: #668380
+  * skge: add quirk to limit DMA
+    - LP: #668380
+  * r8169: allocate with GFP_KERNEL flag when able to sleep
+    - LP: #668380
+  * bsg: fix incorrect device_status value
+    - LP: #668380
+  * r6040: fix r6040_multicast_list
+    - LP: #668380
+  * r6040: Fix multicast list iteration when hash filter is used
+    - LP: #668380
+  * powerpc: Initialise paca->kstack before early_setup_secondary
+    - LP: #668380
+  * powerpc: Don't use kernel stack with translation off
+    - LP: #668380
+  * b44: fix carrier detection on bind
+    - LP: #668380
+  * ACPI: enable repeated PCIEXP wakeup by clearing PCIEXP_WAKE_STS on
+    resume
+    - LP: #613381, #668380
+  * intel_idle: PCI quirk to prevent Lenovo Ideapad s10-3 boot hang
+    - LP: #668380
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #668380
+  * ACPI: delete ZEPTO idle=nomwait DMI quirk
+    - LP: #668380
+  * ACPI: Disable Windows Vista compatibility for Toshiba P305D
+    - LP: #668380
+  * x86: detect scattered cpuid features earlier
+    - LP: #668380
+  * fix 2.6.32.23 suspend regression caused by commit 6f6198a
+    - LP: #668380
+  * setup_arg_pages: diagnose excessive argument size
+    - LP: #668380
+  * execve: improve interactivity with large arguments
+    - LP: #668380
+  * execve: make responsive to SIGKILL with large arguments
+    - LP: #668380
+  * Phonet: disable network namespace support
+    - LP: #668380
+  * mm: Move vma_stack_continue into mm.h
+    - LP: #668380
+  * Linux 2.6.32.25
+    - LP: #668380
+  * xfs: validate untrusted inode numbers during lookup
+    - CVE-2010-2943
+  * xfs: rename XFS_IGET_BULKSTAT to XFS_IGET_UNTRUSTED
+    - CVE-2010-2943
+  * xfs: remove block number from inode lookup code
+    - CVE-2010-2943
+  * xfs: fix untrusted inode number lookup
+    - CVE-2010-2943
+  * drm/i915: Sanity check pread/pwrite
+    - CVE-2010-2962
+  * drm/i915: Rephrase pwrite bounds checking to avoid any potential
+    overflow
+    - CVE-2010-2962
+  * net: clear heap allocation for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3861
+  * ipc: shm: fix information leak to userland
+    - CVE-2010-4072
+  * staging: usbip: Notify usb core of port status changes
+    - LP: #681132
+  * staging: usbip: Process event flags without delay
+    - LP: #681132
+  * powerpc/perf: Fix sampling enable for PPC970
+    - LP: #681132
+  * pcmcia: synclink_cs: fix information leak to userland
+    - LP: #681132
+  * sched: Fix string comparison in /proc/sched_features
+    - LP: #681132
+  * bluetooth: Fix missing NULL check
+    - LP: #681132
+  * futex: Fix errors in nested key ref-counting
+    - LP: #681132
+  * mm, x86: Saving vmcore with non-lazy freeing of vmas
+    - LP: #681132
+  * x86, cpu: Fix renamed, not-yet-shipping AMD CPUID feature bit
+    - LP: #681132
+  * x86, kexec: Make sure to stop all CPUs before exiting the kernel
+    - LP: #681132
+  * x86, olpc: Don't retry EC commands forever
+    - LP: #681132
+  * x86, mtrr: Assume SYS_CFG[Tom2ForceMemTypeWB] exists on all future AMD
+    CPUs
+    - LP: #681132
+  * x86, intr-remap: Set redirection hint in the IRTE
+    - LP: #681132
+  * x86, kdump: Change copy_oldmem_page() to use cached addressing
+    - LP: #681132
+  * KVM: SVM: Fix wrong intercept masks on 32 bit
+    - LP: #681132
+  * KVM: MMU: fix direct sps access corrupted
+    - LP: #681132
+  * KVM: MMU: fix conflict access permissions in direct sp
+    - LP: #681132
+  * KVM: VMX: Fix host GDT.LIMIT corruption
+    - LP: #681132
+  * KVM: SVM: Adjust tsc_offset only if tsc_unstable
+    - LP: #681132
+  * KVM: x86: Fix SVM VMCB reset
+    - LP: #681132
+  * KVM: x86: Move TSC reset out of vmcb_init
+    - LP: #681132
+  * KVM: Fix fs/gs reload oops with invalid ldt
+    - LP: #681132
+  * KVM: Correct ordering of ldt reload wrt fs/gs reload
+  * KVM: VMX: Fix host userspace gsbase corruption
+  * pipe: fix failure to return error code on ->confirm()
+    - LP: #681132
+  * p54usb: fix off-by-one on !CONFIG_PM
+    - LP: #681132
+  * p54usb: add five more USBIDs
+    - LP: #681132
+  * drivers/net/wireless/p54/eeprom.c: Return -ENOMEM on memory allocation
+    failure
+    - LP: #681132
+  * USB: ftdi_sio: Add PID for accesio products
+    - LP: #681132
+  * USB: add PID for FTDI based OpenDCC hardware
+    - LP: #681132
+  * USB: ftdi_sio: new VID/PIDs for various Papouch devices
+    - LP: #681132
+  * USB: ftdi_sio: add device ids for ScienceScope
+    - LP: #681132
+  * usb: musb: blackfin: call gpio_free() on error path in
+    musb_platform_init()
+    - LP: #681132
+  * USB: option: Add more ZTE modem USB id's
+    - LP: #681132
+  * USB: cp210x: Add Renesas RX-Stick device ID
+    - LP: #681132
+  * USB: cp210x: Add WAGO 750-923 Service Cable device ID
+    - LP: #681132
+  * USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request
+    failled
+    - LP: #681132
+  * USB: disable endpoints after unbinding interfaces, not before
+    - LP: #681132
+  * USB: opticon: Fix long-standing bugs in opticon driver
+    - LP: #681132
+  * USB: accept some invalid ep0-maxpacket values
+    - LP: #681132
+  * sd name space exhaustion causes system hang
+    - LP: #681132
+  * libsas: fix NCQ mixing with non-NCQ
+    - LP: #681132
+  * gdth: integer overflow in ioctl
+    - LP: #681132
+  * Fix race when removing SCSI devices
+    - LP: #681132
+  * Fix regressions in scsi_internal_device_block
+    - LP: #681132
+  * sgi-xp: incoming XPC channel messages can come in after the channel's
+    partition structures have been torn down
+    - LP: #681132
+  * Linux 2.6.32.26
+    - LP: #681132
+  * drm/radeon: fix PCI ID 5657 to be an RV410
+    - LP: #683257
+  * Linux 2.6.32.26+drm33.12
+    - LP: #683257
+  * econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849
+    - CVE-2010-3849
+  * econet: fix CVE-2010-3850
+    - CVE-2010-3850
+  * econet: fix CVE-2010-3848
+    - CVE-2010-3848
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 01 Dec 2010 08:13:05 +0100
+
+linux-ec2 (2.6.32-310.21) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to 2.6.32-26.48
+
+  [ Ubuntu: 2.6.32-26.48 ]
+
+  * SAUCE: AF_ECONET prevent kernel stack overflow
+    - CVE-2010-3848
+  * SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges
+    - CVE-2010-3850
+  * SAUCE: AF_ECONET saddr->cookie prevent NULL pointer dereference
+    - CVE-2010-3849
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 24 Nov 2010 10:34:37 +0100
+
+linux-ec2 (2.6.32-310.20) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-26.47
+
+  [ Ubuntu: 2.6.32-26.47 ]
+
+  * Revert "SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell
+    E6510"
+  * Revert "[Config] Added be2net, be2scsi to udebs"
+  * Revert "(ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony
+    laptops with ALC269"
+  * Revert "(pre-stable) ALSA: HDA: Correctly apply position_fix quirks for
+    ATI and VIA controllers"
+  * Revert "ALSA: hda: Use LPIB for another mainboard"
+  * Revert "ALSA: hda: Use LPIB for ASUS M2V"
+  * Revert "ALSA: hda: Use LPIB for an ASUS device"
+  * Buglink Fixup for reverted unverified fixes
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 19 Nov 2010 17:03:52 +0100
+
+linux-ec2 (2.6.32-310.19) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-26.46
+
+  [ Ubuntu: 2.6.32-26.46 ]
+
+  * SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510
+    - See: #605047, #628961
+  * [Config] Added be2net, be2scsi to udebs
+    - See: #628776
+  * Revert "(pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure we shut off the panel in eDP
+    configs"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure eDP panel is turned on"
+    - LP: #645444
+  * Revert "(pre-stable) drm/radeon/kms: initialize set_surface_reg reg for
+    rs600 asic"
+    - LP: #645371
+  * Revert "drm/nouveau: Fix fbcon corruption with font width not divisible
+    by 8"
+    - LP: #663176
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #477106
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #477106
+  * hwmon: (k8temp) Differentiate between AM2 and ASB1
+    - LP: #644694
+  * xen: handle events as edge-triggered
+    - LP: #644694
+  * xen: use percpu interrupts for IPIs and VIRQs
+    - LP: #644694
+  * ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763
+    - LP: #605101, #644694
+  * sata_mv: fix broken DSM/TRIM support (v2)
+    - LP: #644694
+  * x86, tsc, sched: Recompute cyc2ns_offset's during resume from sleep
+    states
+    - LP: #644694
+  * PCI: MSI: Remove unsafe and unnecessary hardware access
+    - LP: #644694
+  * PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
+    - LP: #644694
+  * sched: kill migration thread in CPU_POST_DEAD instead of CPU_DEAD
+    - LP: #644694
+  * sched: revert stable c6fc81a sched: Fix a race between ttwu() and
+    migrate_task()
+    - LP: #644694
+  * staging: hv: Fix missing functions for net_device_ops
+    - LP: #644694
+  * staging: hv: Fixed bounce kmap problem by using correct index
+    - LP: #644694
+  * staging: hv: Fixed the value of the 64bit-hole inside ring buffer
+    - LP: #644694
+  * staging: hv: Increased storvsc ringbuffer and max_io_requests
+    - LP: #644694
+  * staging: hv: Fixed lockup problem with bounce_buffer scatter list
+    - LP: #644694
+  * fuse: flush background queue on connection close
+    - LP: #644694
+  * ath9k_hw: fix parsing of HT40 5 GHz CTLs
+    - LP: #644694
+  * ocfs2: Fix incorrect checksum validation error
+    - LP: #644694
+  * USB: ehci-ppc-of: problems in unwind
+    - LP: #644694
+  * USB: Fix kernel oops with g_ether and Windows
+    - LP: #644694
+  * USB: CP210x Add new device ID
+    - LP: #644694
+  * USB: cp210x: Add B&G H3000 link cable ID
+    - LP: #644694
+  * USB: ftdi_sio: Added custom PIDs for ChamSys products
+    - LP: #644694
+  * USB: serial: Extra device/vendor ID for mos7840 driver
+    - LP: #644694
+  * usb: serial: mos7840: Add USB ID to support the B&B Electronics
+    USOPTL4-2P.
+    - LP: #644694
+  * USB: mos7840: fix DMA buffers on stack and endianess bugs
+    - LP: #644694
+  * usb: serial: mos7840: Add USB IDs to support more B&B USB/RS485
+    converters.
+    - LP: #644694
+  * USB: Exposing second ACM channel as tty for Nokia S60 phones.
+    - LP: #644694
+  * USB: cdc-acm: add another device quirk
+    - LP: #644694
+  * USB: Expose vendor-specific ACM channel on Nokia 5230
+    - LP: #644694
+  * USB: cdc-acm: Adding second ACM channel support for various Nokia and
+    one Samsung phones
+    - LP: #644694
+  * USB: cdc-acm: Add pseudo modem without AT command capabilities
+    - LP: #644694
+  * USB: cdc-acm: Fixing crash when ACM probing interfaces with no endpoint
+    descriptors.
+    - LP: #644694
+  * ALSA: hda - Fix auto-parser of ALC269vb for HP pin NID 0x21
+    - LP: #644694
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - LP: #644694
+  * sysfs: checking for NULL instead of ERR_PTR
+    - LP: #644694
+  * tun: Don't add sysfs attributes to devices without sysfs directories
+    - LP: #644694
+  * oprofile: fix crash when accessing freed task structs
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs error handling
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs() function stub
+    - LP: #644694
+  * HID: usbhid: initialize interface pointers early enough
+    - LP: #644694
+  * HID: fix suspend crash by moving initializations earlier
+    - LP: #644694
+  * libata: skip EH autopsy and recovery during suspend
+    - LP: #644694
+  * tracing: Fix a race in function profile
+    - LP: #644694
+  * tracing: Do not allow llseek to set_ftrace_filter
+    - LP: #644694
+  * tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread
+    - LP: #644694
+  * irda: off by one
+    - LP: #644694
+  * gcov: fix null-pointer dereference for certain module types
+    - LP: #644694
+  * tmio_mmc: don't clear unhandled pending interrupts
+    - LP: #644694
+  * mmc: fix the use of kunmap_atomic() in tmio_mmc.h
+    - LP: #644694
+  * bounce: call flush_dcache_page() after bounce_copy_vec()
+    - LP: #644694
+  * kernel/groups.c: fix integer overflow in groups_search
+    - LP: #644694
+  * binfmt_misc: fix binfmt_misc priority
+    - LP: #644694
+  * Input: i8042 - fix device removal on unload
+    - LP: #644694
+  * memory hotplug: fix next block calculation in is_removable
+    - LP: #644694
+  * perf: Initialize callchains roots's childen hits
+    - LP: #644694
+  * p54: fix tx feedback status flag check
+    - LP: #644694
+  * ath5k: check return value of ieee80211_get_tx_rate
+    - LP: #644694
+  * wireless extensions: fix kernel heap content leak
+    - LP: #644694
+  * x86, tsc: Fix a preemption leak in restore_sched_clock_state()
+    - LP: #644694
+  * sched: Protect task->cpus_allowed access in sched_getaffinity()
+    - LP: #644694
+  * sched: Protect sched_rr_get_param() access to task->sched_class
+    - LP: #644694
+  * sched: Consolidate select_task_rq() callers
+    - LP: #644694
+  * sched: Remove unused cpu_nr_migrations()
+    - LP: #644694
+  * sched: Remove rq->clock coupling from set_task_cpu()
+    - LP: #644694
+  * sched: Clean up ttwu() rq locking
+    - LP: #644694
+  * sched: Sanitize fork() handling
+    - LP: #644694
+  * sched: Remove forced2_migrations stats
+    - LP: #644694
+  * sched: Make wakeup side and atomic variants of completion API irq safe
+    - LP: #644694
+  * sched: Use rcu in sys_sched_getscheduler/sys_sched_getparam()
+    - LP: #644694
+  * sched: Use rcu in sched_get/set_affinity()
+    - LP: #644694
+  * sched: Use rcu in sched_get_rr_param()
+    - LP: #644694
+  * sched: Fix set_cpu_active() in cpu_down()
+    - LP: #644694
+  * sched: Use TASK_WAKING for fork wakups
+    - LP: #644694
+  * sched: Ensure set_task_cpu() is never called on blocked tasks
+    - LP: #644694
+  * sched: Make warning less noisy
+    - LP: #644694
+  * sched: Fix broken assertion
+    - LP: #644694
+  * sched: Fix sched_exec() balancing
+    - LP: #644694
+  * sched: Fix select_task_rq() vs hotplug issues
+    - LP: #644694
+  * sched: Add pre and post wakeup hooks
+    - LP: #644694
+  * sched: Remove the cfs_rq dependency from set_task_cpu()
+    - LP: #644694
+  * sched: Fix hotplug hang
+    - LP: #644694
+  * sched: Fix fork vs hotplug vs cpuset namespaces
+    - LP: #644694
+  * sched: Fix incorrect sanity check
+    - LP: #644694
+  * sched: Fix race between ttwu() and task_rq_lock()
+    - LP: #644694
+  * sched: Extend enqueue_task to allow head queueing
+    - LP: #644694
+  * sched: Implement head queueing for sched_rt
+    - LP: #644694
+  * sched: Queue a deboosted task to the head of the RT prio queue
+    - LP: #644694
+  * sched: set_cpus_allowed_ptr(): Don't use rq->migration_thread after
+    unlock
+    - LP: #644694
+  * sched: Kill the broken and deadlockable
+    cpuset_lock/cpuset_cpus_allowed_locked code
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Take rq->lock around
+    select_fallback_rq()
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Remove retry logic
+    - LP: #644694
+  * sched: sched_exec(): Remove the select_fallback_rq() logic
+    - LP: #644694
+  * sched: _cpu_down(): Don't play with current->cpus_allowed
+    - LP: #644694
+  * sched: Make select_fallback_rq() cpuset friendly
+    - LP: #644694
+  * sched: Fix TASK_WAKING vs fork deadlock
+    - LP: #644694
+  * sched: Optimize task_rq_lock()
+    - LP: #644694
+  * sched: Fix nr_uninterruptible count
+    - LP: #644694
+  * sched: Fix rq->clock synchronization when migrating tasks
+    - LP: #644694
+  * sched: Remove unnecessary RCU exclusion
+    - LP: #644694
+  * sched: apply RCU protection to wake_affine()
+    - LP: #644694
+  * sched: Cleanup select_task_rq_fair()
+    - LP: #644694
+  * sched: More generic WAKE_AFFINE vs select_idle_sibling()
+    - LP: #644694
+  * sched: Fix vmark regression on big machines
+    - LP: #644694
+  * sched: Fix select_idle_sibling()
+    - LP: #644694
+  * sched: Pre-compute cpumask_weight(sched_domain_span(sd))
+    - LP: #644694
+  * sched: Fix select_idle_sibling() logic in select_task_rq_fair()
+    - LP: #644694
+  * sched: cpuacct: Use bigger percpu counter batch values for stats
+    counters
+    - LP: #644694
+  * ALSA: hda - Handle missing NID 0x1b on ALC259 codec
+    - LP: #644694
+  * ALSA: hda - Handle pin NID 0x1a on ALC259/269
+    - LP: #644694
+  * arm: fix really nasty sigreturn bug
+    - LP: #644694
+  * hwmon: (f75375s) Shift control mode to the correct bit position
+    - LP: #644694
+  * hwmon: (f75375s) Do not overwrite values read from registers
+    - LP: #644694
+  * apm_power: Add missing break statement
+    - LP: #644694
+  * NFS: Fix a typo in nfs_sockaddr_match_ipaddr6
+    - LP: #644694
+  * SUNRPC: Fix race corrupting rpc upcall
+    - LP: #644694
+  * Linux 2.6.32.22
+    - LP: #644694
+  * drm/i915: don't access FW_BLC_SELF on 965G
+    - LP: #645444
+  * drm/i915: gen3 page flipping fixes
+    - LP: #645444
+  * drm/i915: don't queue flips during a flip pending event
+    - LP: #645444
+  * drm/i915: Hold the spinlock whilst resetting unpin_work along error
+    path
+    - LP: #645444
+  * drm/i915: handle shared framebuffers when flipping
+    - LP: #645444
+  * drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #645444
+  * drm/i915: make sure eDP panel is turned on
+    - LP: #645444
+  * drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #645444
+  * Linux 2.6.32.22+drm33.9
+    - LP: #645444
+  * drm/radeon/kms/igp: sideport is AMD only
+    - LP: #645371
+  * drm/radeon/kms: flush HDP cache on GART table updates.
+    - LP: #645371
+  * drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush
+    - LP: #645371
+  * drm/i915: Check overlay stride errata for i830 and i845
+    - LP: #645371
+  * i915: fix ironlake edp panel setup (v4)
+    - LP: #645371
+  * drm/radeon/kms: add additional quirk for Acer rv620 laptop
+    - LP: #645371
+  * drm/i915: fixup pageflip ringbuffer commands for i8xx
+    - LP: #645371
+  * drm/i915: i8xx also doesn't like multiple oustanding pageflips
+    - LP: #645371
+  * drm/i915/edp: Flush the write before waiting for PLLs
+    - LP: #645371
+  * drm/radeon/kms: disable MSI on IGP chips
+    - LP: #645371
+  * drm/radeon/kms: don't enable MSIs on AGP boards
+    - LP: #645371
+  * drm/radeon/kms: fix typo in radeon_compute_pll_gain
+    - LP: #645371
+  * drm/radeon/kms/DCE3+: switch pads to ddc mode when going i2c
+    - LP: #645371
+  * drm/radeon/kms: fix sideport detection on newer rs880 boards
+    - LP: #645371
+  * drm/i915: Don't touch PORT_HOTPLUG_EN in intel_dp_detect()
+    - LP: #645371
+  * drm/i915: Kill dangerous pending-flip debugging
+    - LP: #645371
+  * drm/radeon/kms: release AGP bridge at suspend
+    - LP: #645371
+  * drm/radeon/kms: initialize set_surface_reg reg for rs600 asic
+    - LP: #645371
+  * drm/radeon/kms: fix a regression on r7xx AGP due to the HDP flush fix
+    - LP: #645371
+  * Linux 2.6.32.22+drm33.10
+    - LP: #645371
+  * USB: serial/mos*: prevent reading uninitialized stack memory
+    - LP: #649483
+  * sparc: Provide io{read,write}{16,32}be().
+    - LP: #649483
+  * gro: fix different skb headrooms
+    - LP: #649483
+  * gro: Re-fix different skb headrooms
+    - LP: #649483
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - LP: #649483
+  * tcp: select(writefds) don't hang up when a peer close connection
+    - LP: #649483
+  * tcp: Combat per-cpu skew in orphan tests.
+    - LP: #649483
+  * tcp: fix three tcp sysctls tuning
+    - LP: #649483
+  * bridge: Clear IPCB before possible entry into IP stack
+    - LP: #649483
+  * bridge: Clear INET control block of SKBs passed into ip_fragment().
+    - LP: #649483
+  * net: Fix oops from tcp_collapse() when using splice()
+    - LP: #649483
+  * rds: fix a leak of kernel memory
+    - LP: #649483
+  * tcp: Prevent overzealous packetization by SWS logic.
+    - LP: #649483
+  * UNIX: Do not loop forever at unix_autobind().
+    - LP: #649483
+  * r8169: fix random mdio_write failures
+    - LP: #649483
+  * r8169: fix mdio_read and update mdio_write according to hw specs
+    - LP: #649483
+  * sparc64: Get rid of indirect p1275 PROM call buffer.
+    - LP: #649483
+  * drivers/net/usb/hso.c: prevent reading uninitialized memory
+    - LP: #649483
+  * drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * drivers/net/eql.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * bonding: correctly process non-linear skbs
+    - LP: #649483
+  * Staging: vt6655: fix buffer overflow
+    - LP: #649483
+  * net/llc: make opt unsigned in llc_ui_setsockopt()
+    - LP: #649483
+  * pid: make setpgid() system call use RCU read-side critical section
+    - LP: #649483
+  * sched: Fix user time incorrectly accounted as system time on 32-bit
+    - LP: #649483
+  * oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron
+    540)
+    - LP: #649483
+  * char: Mark /dev/zero and /dev/kmem as not capable of writeback
+    - LP: #649483
+  * drivers/pci/intel-iommu.c: fix build with older gcc's
+    - LP: #649483
+  * drivers/video/sis/sis_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * percpu: fix pcpu_last_unit_cpu
+    - LP: #649483
+  * aio: check for multiplication overflow in do_io_submit
+    - LP: #649483
+  * inotify: send IN_UNMOUNT events
+    - LP: #649483
+  * SCSI: mptsas: fix hangs caused by ATA pass-through
+    - LP: #649483
+  * ext4: Fix remaining racy updates of EXT4_I(inode)->i_flags
+    - LP: #649483
+  * IA64: fix siglock
+    - LP: #649483
+  * IA64: Optimize ticket spinlocks in fsys_rt_sigprocmask
+    - LP: #649483
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - LP: #649483
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - LP: #649483
+  * xfs: prevent reading uninitialized stack memory
+    - LP: #649483
+  * drivers/video/via/ioctl.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * ACPI: disable _OSI(Windows 2009) on Asus K50IJ
+    - LP: #649483
+  * bnx2: Fix netpoll crash.
+    - LP: #649483
+  * bnx2: Fix hang during rmmod bnx2.
+    - LP: #649483
+  * AT91: change dma resource index
+    - LP: #649483
+  * cxgb3: fix hot plug removal crash
+    - LP: #649483
+  * mm: page allocator: drain per-cpu lists after direct reclaim allocation
+    fails
+    - LP: #649483
+  * mm: page allocator: calculate a better estimate of NR_FREE_PAGES when
+    memory is low and kswapd is awake
+    - LP: #649483
+  * mm: page allocator: update free page counters after pages are placed on
+    the free list
+    - LP: #649483
+  * guard page for stacks that grow upwards
+    - LP: #649483
+  * Fix unprotected access to task credentials in waitid()
+    - LP: #649483
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - LP: #649483
+  * 3c503: Fix IRQ probing
+    - LP: #649483
+  * asix: fix setting mac address for AX88772
+    - LP: #649483
+  * dasd: use correct label location for diag fba disks
+    - LP: #649483
+  * clocksource: sh_tmu: compute mult and shift before registration
+    - LP: #649483
+  * gro: Fix bogus gso_size on the first fraglist entry
+    - LP: #649483
+  * hostap_pci: set dev->base_addr during probe
+    - LP: #649483
+  * inotify: fix inotify oneshot support
+    - LP: #649483
+  * Input: add compat support for sysfs and /proc capabilities output
+    - LP: #649483
+  * MIPS: Quit using undefined behavior of ADDU in 64-bit atomic
+    operations.
+    - LP: #649483
+  * MIPS: Set io_map_base for several PCI bridges lacking it
+    - LP: #649483
+  * MIPS: uasm: Add OR instruction.
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for Promise UDMA33 cards
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for PDC2026x chipsets
+    - LP: #649483
+  * MIPS: Sibyte: Fix M3 TLB exception handler workaround.
+    - LP: #649483
+  * sis-agp: Remove SIS 760, handled by amd64-agp
+    - LP: #649483
+  * alpha: Fix printk format errors
+    - LP: #649483
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #649483
+  * Linux 2.6.32.23
+    - LP: #649483
+  * (pre-stable) [SCSI] megaraid_sas: Add new megaraid SAS 2 controller
+    support to the driver
+    - LP: #546091
+  * (pre-stable) [SCSI] megaraid_sas: allocate the application cmds to sas2
+    controller
+    - LP: #546091
+  * Xen: fix typo in previous patch
+    - LP: #655456
+  * Linux 2.6.32.24
+    - LP: #655456
+  * (ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony laptops
+    with ALC269
+    - See: #546769, #598938, #637291, #642892, #648871, #655386
+  * (pre-stable) ALSA: HDA: Correctly apply position_fix quirks for ATI and
+    VIA controllers
+    - See: #465942, #580749, #587546
+  * (pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume
+    - LP: #613381
+  * i915: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * i915_gem: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * drm/i915: Prevent double dpms on
+    - LP: #663176
+  * drm: Only decouple the old_fb from the crtc is we call mode_set*
+    - LP: #663176
+  * drm/radeon/kms: fix potential segfault in r600_ioctl_wait_idle
+    - LP: #663176
+  * drm/i915: Unset cursor if out-of-bounds upon mode change (v4)
+    - LP: #586325, #663176
+  * drm/i915: disable FBC when more than one pipe is active
+    - LP: #663176
+  * drm/radeon/kms: fix macbookpro connector quirk
+    - LP: #663176
+  * drm/nouveau: use ALIGN instead of open coding it
+    - LP: #663176
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #663176
+  * drm/i915,agp/intel: Add second set of PCI-IDs for B43
+    - LP: #640214, #663176
+  * Linux 2.6.32.24+drm33.11
+    - LP: #663176
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 26 Oct 2010 15:16:00 -0400
+
+linux-ec2 (2.6.32-309.18) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-25.45
+
+  [ Ubuntu: 2.6.32-25.45 ]
+
+  * v4l: disable dangerous buggy compat function
+    - CVE-2010-2963
+  * Local privilege escalation vulnerability in RDS sockets
+    - CVE-2010-3904
+  * mm: (pre-stable) Move vma_stack_continue into mm.h
+    - LP: #646114
+  * net sched: fix some kernel memory leaks
+    - CVE-2010-2942
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - CVE-2010-2954
+  * wireless extensions: fix kernel heap content leak
+    - CVE-2010-2955
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - CVE-2010-2960
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - CVE-2010-2960
+  * aio: check for multiplication overflow in do_io_submit
+    - CVE-2010-3067
+  * xfs: prevent reading uninitialized stack memory
+    - CVE-2010-3078
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - CVE-2010-3080
+  * niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3084
+  * rose: Fix signedness issues wrt. digi count.
+    - CVE-2010-3310
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - CVE-2010-3432
+  * Fix pktcdvd ioctl dev_minor range check
+    - CVE-2010-3437
+  * ALSA: prevent heap corruption in snd_ctl_new()
+    - CVE-2010-3442
+  * net sched: fix kernel leak in act_police
+    - CVE-2010-3477
+  * Fix out-of-bounds reading in sctp_asoc_get_hmac()
+    - CVE-2010-3705
+  * ocfs2: Don't walk off the end of fast symlinks.
+    - CVE-2010-NNN2
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 18 Oct 2010 10:01:36 +0200
+
+linux-ec2 (2.6.32-309.17) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Rebased to 2.6.32-25.44
+
+  [ John Johansen ]
+
+  * SAUCE: Revert "sched: update load count only once per cpu in 10 tick
+    update window"
+    - LP: #574910
+
+  [ Ubuntu: 2.6.32-25.44 ]
+
+  * SAUCE: (no-up) Modularize vesafb -- fix initialization
+    - LP: #611471
+  * Revert "SAUCE: sync before umount to reduce time taken by ext4 umount"
+    - LP: #543617, #585092
+  * Revert "SAUCE: tulip: Let dmfe handle davicom on non-sparc"
+    - LP: #607824
+  * [Config] Added ums-cypress to udeb
+    - LP: #576066
+  * Revert "PCI quirk: Disable MSI on VIA K8T890 systems"
+    - LP: #607824
+  * Revert "PCI quirks: disable msi on AMD rs4xx internal gfx bridges"
+    - LP: #607824
+  * Revert "(pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting"
+    - LP: #607824
+  * Revert "jbd: jbd-debug and jbd2-debug should be writable"
+    - LP: #607824
+  * Revert "ext4: Make fsync sync new parent directories in no-journal
+    mode"
+    - LP: #615548
+  * Revert "ext4: Fix compat EXT4_IOC_ADD_GROUP"
+    - LP: #615548
+  * Revert "ext4: Conditionally define compat ioctl numbers"
+    - LP: #615548
+  * Revert "ext4: restart ext4_ext_remove_space() after transaction
+    restart"
+    - LP: #615548
+  * Revert "ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted"
+    - LP: #615548
+  * Revert "ext4: Avoid crashing on NULL ptr dereference on a filesystem
+    error"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify i_flags in struct
+    ext4_inode_info"
+    - LP: #615548
+  * Revert "ext4: Show journal_checksum option"
+    - LP: #615548
+  * Revert "ext4: check for a good block group before loading buddy pages"
+    - LP: #615548
+  * Revert "ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate"
+    - LP: #615548
+  * Revert "ext4: Remove extraneous newlines in ext4_msg() calls"
+    - LP: #615548
+  * Revert "ext4: init statistics after journal recovery"
+    - LP: #615548
+  * Revert "ext4: clean up inode bitmaps manipulation in ext4_free_inode"
+    - LP: #615548
+  * Revert "ext4: Do not zero out uninitialized extents beyond i_size"
+    - LP: #615548
+  * Revert "ext4: don't scan/accumulate more pages than mballoc will
+    allocate"
+    - LP: #615548
+  * Revert "ext4: stop issuing discards if not supported by device"
+    - LP: #615548
+  * Revert "ext4: check s_log_groups_per_flex in online resize code"
+    - LP: #615548
+  * Revert "ext4: fix quota accounting in case of fallocate"
+    - LP: #615548
+  * Revert "ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode"
+    - LP: #615548
+  * Revert "ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()"
+    - LP: #615548
+  * Revert "ext4: Remove unnecessary call to ext4_get_group_desc() in
+    mballoc"
+    - LP: #615548
+  * Revert "ext4: fix memory leaks in error path handling of
+    ext4_ext_zeroout()"
+    - LP: #615548
+  * Revert "ext4: check missed return value in ext4_sync_file()"
+    - LP: #615548
+  * Revert "ext4: Issue the discard operation *before* releasing the blocks
+    to be reused"
+    - LP: #615548
+  * Revert "ext4: Fix buffer head leaks after calls to
+    ext4_get_inode_loc()"
+    - LP: #615548
+  * Revert "ext4: Fix possible lost inode write in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Fixed inode allocator to correctly track a flex_bg's
+    used_dirs"
+    - LP: #615548
+  * Revert "ext4: Fix estimate of # of blocks needed to write
+    indirect-mapped files"
+    - LP: #615548
+  * Revert "ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl"
+    - LP: #615548
+  * Revert "ext4: Fix the NULL reference in double_down_write_data_sem()"
+    - LP: #615548
+  * Revert "ext4: Fix insertion point of extent in
+    mext_insert_across_blocks()"
+    - LP: #615548
+  * Revert "ext4: make "offset" consistent in ext4_check_dir_entry()"
+    - LP: #615548
+  * Revert "ext4: Handle non empty on-disk orphan link"
+    - LP: #615548
+  * Revert "ext4: explicitly remove inode from orphan list after failed
+    direct io"
+    - LP: #615548
+  * Revert "ext4: fix error handling in migrate"
+    - LP: #615548
+  * Revert "ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation."
+    - LP: #615548
+  * Revert "ext4: Add flag to files with blocks intentionally past EOF"
+    - LP: #615548
+  * Revert "ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify EXT4_I(inode)->i_state"
+    - LP: #615548
+  * Revert "ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag"
+    - LP: #615548
+  * Revert "ext4: Fix quota accounting error with fallocate"
+    - LP: #615548
+  * Revert "ext4: Handle -EDQUOT error on write"
+    - LP: #615548
+  * Revert "ext4: Calculate metadata requirements more accurately"
+    - LP: #615548
+  * Revert "ext4: Fix accounting of reserved metadata blocks"
+    - LP: #615548
+  * Revert "ext4: Patch up how we claim metadata blocks for quota purposes"
+    - LP: #615548
+  * Revert "ext4: Ensure zeroout blocks have no dirty metadata"
+    - LP: #615548
+  * Revert "ext4: return correct wbc.nr_to_write in ext4_da_writepages"
+    - LP: #615548
+  * Revert "ext4: Eliminate potential double free on error path"
+    - LP: #615548
+  * Revert "ext4, jbd2: Add barriers for file systems with exernal
+    journals"
+    - LP: #615548
+  * Revert "ext4: replace BUG() with return -EIO in ext4_ext_get_blocks"
+    - LP: #615548
+  * Revert "ext4: Fix potential quota deadlock"
+    - LP: #615548
+  * Revert "ext4: don't return to userspace after freezing the fs with a
+    mutex held"
+    - LP: #615548
+  * ixgbe: Fix return of invalid txq
+    - LP: #607824
+  * oprofile/x86: fix uninitialized counter usage during cpu hotplug
+    - LP: #607824
+  * oprofile: remove double ring buffering
+    - LP: #607824
+  * cpumask: fix compat getaffinity
+    - LP: #607824
+  * NFSD: don't report compiled-out versions as present
+    - LP: #607824
+  * sata_nv: use ata_pci_sff_activate_host() instead of ata_host_activate()
+    - LP: #607824
+  * ARCNET: Limit com20020 PCI ID matches for SOHARD cards
+    - LP: #607824
+  * rtl8180: fix tx status reporting
+    - LP: #607824
+  * Staging: add Add Sitecom WL-349 to rtl8192su
+    - LP: #607824
+  * staging: vt6655: Fix kernel BUG on driver wpa initialization
+    - LP: #607824
+  * Fix racy use of anon_inode_getfd() in perf_event.c
+    - LP: #607824
+  * posix_timer: Fix error path in timer_create
+    - LP: #607824
+  * libata: disable ATAPI AN by default
+    - LP: #607824
+  * libata: don't flush dcache on slab pages
+    - LP: #607824
+  * mutex: Fix optimistic spinning vs. BKL
+    - LP: #607824
+  * ALSA: hda: Fix model quirk for Dell M1730
+    - LP: #576160, #607824
+  * ALSA: hda: Use LPIB for Toshiba A100-259
+    - LP: #549560, #607824
+  * ALSA: hda: Use LPIB for Acer Aspire 5110
+    - LP: #583983, #607824
+  * ALSA: hda: Use LPIB for Sony VPCS11V9E
+    - LP: #586347, #607824
+  * ALSA: hda: Use LPIB for a Shuttle device
+    - LP: #551949, #607824
+  * ACPI: video: fix acpi_backlight=video
+    - LP: #573120, #607824
+  * V4L/DVB: gspca - stv06xx: Remove the 046d:08da from the stv06xx driver
+    - LP: #607824
+  * HID: Add the GYR4101US USB ID to hid-gyration
+    - LP: #607824
+  * ar9170usb: add a couple more USB IDs
+    - LP: #607824
+  * ar9170usb: fix panic triggered by undersized rxstream buffer
+    - LP: #607824
+  * USB: visor: fix memory leak
+    - LP: #607824
+  * USB: CP210x New Device IDs 11 New device IDs
+    - LP: #607824
+  * USB: kobil: fix memory leak
+    - LP: #607824
+  * USB: option: add PID for ZTE product
+    - LP: #607824
+  * USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem
+    interface is 0xff
+    - LP: #607824
+  * USB: serial: option: add cinterion device id
+    - LP: #607824
+  * USB: option.c: OLIVETTI OLICARD100 support
+    - LP: #607824
+  * USB: ir-usb: fix double free
+    - LP: #607824
+  * USB: kl5usb105: fix memory leak
+    - LP: #607824
+  * USB: mxc: gadget: Fix bitfield for calculating maximum packet size
+    - LP: #607824
+  * USB: unusual-dev: Add bad sense flag for Appotech ax203 based picture
+    frames
+    - LP: #607824
+  * USB: EHCI: clear PHCD before resuming
+    - LP: #607824
+  * USB: xhci: Fix issue with set interface after stall.
+    - LP: #607824
+  * USB: xhci: Fix check for room on the ring.
+    - LP: #607824
+  * USB: xHCI: Fix wrong usage of macro TRB_TYPE
+    - LP: #607824
+  * mac80211: give warning if building w/out rate ctrl algorithm
+    - LP: #607824
+  * mac80211: Fix robust management frame handling (MFP)
+    - LP: #607824
+  * mac80211: fix rts threshold check
+    - LP: #607824
+  * drivers/base/cpu.c: fix the output from /sys/devices/system/cpu/offline
+    - LP: #607824
+  * can: Fix SJA1000 command register writes on SMP systems
+    - LP: #607824
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #607824
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #607824
+  * PCI: Disable MSI for MCP55 on P5N32-E SLI
+    - LP: #607824
+  * virtio_net: Make delayed refill more reliable
+    - LP: #607824
+  * mm: hugetlb: fix clear_huge_page()
+    - LP: #607824
+  * powerpc: Fix handling of strncmp with zero len
+    - LP: #607824
+  * powerpc/pseries: Only call start-cpu when a CPU is stopped
+    - LP: #607824
+  * powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu
+    - LP: #607824
+  * powerpc/oprofile: fix potential buffer overrun in op_model_cell.c
+    - LP: #607824
+  * writeback: disable periodic old data writeback for
+    !dirty_writeback_centisecs
+    - LP: #607824
+  * md/raid1: fix counting of write targets.
+    - LP: #607824
+  * md: Fix read balancing in RAID1 and RAID10 on drives > 2TB
+    - LP: #607824
+  * md: set mddev readonly flag on blkdev BLKROSET ioctl
+    - LP: #607824
+  * x86/amd-iommu: Fix suspend/resume with IOMMU
+    - LP: #607824
+  * exofs: confusion between kmap() and kmap_atomic() api
+    - LP: #607824
+  * mn10300: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * m68k: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * rtc-cmos: do dev_set_drvdata() earlier in the initialization
+    - LP: #607824
+  * rtc: s3c: initialize driver data before using it
+    - LP: #607824
+  * frv: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * xtensa: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * Blackfin: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * tmpfs: insert tmpfs cache pages to inactive list at first
+    - LP: #607824
+  * mlx4_core: Fix possible chunk sg list overflow in mlx4_alloc_icm()
+    - LP: #607824
+  * ARM: 6166/1: Proper prefetch abort handling on pre-ARMv6
+    - LP: #607824
+  * ARM: 6164/1: Add kto and kfrom to input operands list.
+    - LP: #607824
+  * ARM: 6146/1: sa1111: Prevent deadlock in resume path
+    - LP: #607824
+  * ARM: 6144/1: TCM memory bug freeing bug
+    - LP: #607824
+  * ARM: VFP: Fix vfp_put_double() for d16-d31
+    - LP: #607824
+  * ASoC: Fix dB scales for WM835x
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8400
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8990
+    - LP: #607824
+  * hwmon: (ltc4245) Read only one GPIO pin
+    - LP: #607824
+  * signals: check_kill_permission(): don't check creds if
+    same_thread_group()
+    - LP: #607824
+  * do_generic_file_read: clear page errors when issuing a fresh read of
+    the page
+    - LP: #607824
+  * ipmi: handle run_to_completion properly in deliver_recv_msg()
+    - LP: #607824
+  * x86, setup: Phoenix BIOS fixup is needed on Dell Inspiron Mini 1012
+    - LP: #607824
+  * xen: ensure timer tick is resumed even on CPU driving the resume
+    - LP: #607824
+  * xen: avoid allocation causing potential swap activity on the resume
+    path
+    - LP: #607824
+  * ALSA: hda: Use LPIB for an ASUS device
+    - See: #465942, #607824
+  * ALSA: hda: Use mb31 quirk for an iMac model
+    - LP: #542550, #607824
+  * ALSA: hda: Use LPIB for another mainboard
+    - See: #580749, #607824
+  * ALSA: hda: Use LPIB for ASUS M2V
+    - See: #587546, #607824
+  * Staging: comedi - correct parameter gainlkup for DAQCard-6024E in
+    driver ni_mio_cs.c
+    - LP: #607824
+  * clocksource: sh_cmt: compute mult and shift before registration
+    - LP: #607824
+  * ath5k: retain promiscuous setting
+    - LP: #607824
+  * ahci: add pci quirk for JMB362
+    - LP: #607824
+  * firewire: core: check for 1394a compliant IRM, fix inaccessibility of
+    Sony camcorder
+    - LP: #607824
+  * perf_events: Fix resource leak in x86 __hw_perf_event_init()
+    - LP: #607824
+  * sata_nv: don't diddle with nIEN on mcp55
+    - LP: #607824
+  * sata_via: magic vt6421 fix for transmission problems w/ WD drives
+    - LP: #422994, #607824
+  * USB: mos7840: fix null-pointer dereference
+    - LP: #607824
+  * USB: xhci: Wait for host to start running.
+    - LP: #607824
+  * USB: xhci: Wait for controller to be ready after reset.
+    - LP: #607824
+  * USB: ftdi_sio: fix DTR/RTS line modes
+    - LP: #607824
+  * USB: cdc-acm: fix resource reclaim in error path of acm_probe
+    - LP: #607824
+  * p54usb: Add device ID for Dell WLA3310 USB
+    - LP: #607824
+  * atl1e: Allow TX checksum offload and TSO to be disabled and reenabled
+    - LP: #607824
+  * via-velocity: Give RX descriptors to the NIC later on open or MTU
+    change
+    - LP: #607824
+  * dmfe/tulip: Let dmfe handle DM910x except for SPARC on-board chips
+    - LP: #607824
+  * Documentation/3c509: document ethtool support
+    - LP: #607824
+  * wireless: report reasonable bitrate for MCS rates through wext
+    - LP: #607824
+  * ath9k: add support for 802.11n bonded out AR2427
+    - LP: #607824
+  * wrong type for 'magic' argument in simple_fill_super()
+    - LP: #607824
+  * iwlwifi: check for aggregation frame and queue
+    - LP: #607824
+  * iwlwifi: recalculate average tpt if not current
+    - LP: #607824
+  * iwlwifi: update supported PCI_ID list for 5xx0 series
+    - LP: #607824
+  * wl1251: fix a memory leak in probe
+    - LP: #607824
+  * vfs: add NOFOLLOW flag to umount(2)
+    - LP: #607824
+  * l2tp: Fix oops in pppol2tp_xmit
+    - LP: #607824
+  * ucc_geth: Fix empty TX queue processing
+    - LP: #607824
+  * ucc_geth: Fix netdev watchdog triggering on link changes
+    - LP: #607824
+  * ucc_geth: Fix full TX queue processing
+    - LP: #607824
+  * Input: psmouse - reset all types of mice before reconnecting
+    - LP: #607824
+  * KVM: s390: Fix possible memory leak of in kvm_arch_vcpu_create()
+    - LP: #607824
+  * KVM: PPC: Do not create debugfs if fail to create vcpu
+    - LP: #607824
+  * x86, paravirt: Add a global synchronization point for pvclock
+    - LP: #607824
+  * KVM: Don't allow lmsw to clear cr0.pe
+    - LP: #607824
+  * KVM: x86: Check LMA bit before set_efer
+    - LP: #607824
+  * KVM: MMU: Segregate shadow pages with different cr0.wp
+    - LP: #607824
+  * KVM: VMX: enable VMXON check with SMX enabled (Intel TXT)
+    - LP: #607824
+  * KVM: MMU: Don't read pdptrs with mmu spinlock held in mmu_alloc_roots
+    - LP: #607824
+  * KVM: Fix wallclock version writing race
+    - LP: #607824
+  * KVM: x86: Add missing locking to arch specific vcpu ioctls
+    - LP: #607824
+  * KVM: x86: Inject #GP with the right rip on efer writes
+    - LP: #607824
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #607824
+  * parisc: clear floating point exception flag on SIGFPE signal
+    - LP: #607824
+  * dm snapshot: simplify sector_to_chunk expression
+    - LP: #607824
+  * KEYS: Return more accurate error codes
+    - LP: #607824
+  * qla2xxx: Disable MSI on qla24xx chips other than QLA2432.
+    - LP: #607824
+  * Linux 2.6.32.16
+    - LP: #607824
+  * drm/i915: Fix 82854 PCI ID, and treat it like other 85X
+    - LP: #607824
+  * drm/i915: Reject bind_to_gtt() early if object > aperture
+    - LP: #607824
+  * drm/edid: Fix 1024x768@85Hz
+    - LP: #607824
+  * drm/radeon/kms: reset ddc_bus in object header parsing
+    - LP: #607824
+  * drm/radeon/kms/atom: fix typo in LVDS panel info parsing
+    - LP: #607824
+  * drm/radeon: r100/r200 ums: block ability for userspace app to trash 0
+    page and beyond
+    - LP: #607824
+  * drm/radeon: fix the r100/r200 ums block 0 page fix
+    - LP: #607824
+  * drm/i915: Rebind bo if currently bound with incorrect alignment.
+    - LP: #607824
+  * Linux 2.6.32.16+drm33.6
+    - LP: #607824
+  * virtio-pci: disable msi at startup
+    - LP: #615548
+  * hwmon: (k8temp) Bypass core swapping on single-core processors
+    - LP: #615548
+  * hwmon: (k8temp) Fix temperature reporting for ASB1 processor revisions
+    - LP: #615548
+  * hwmon: (coretemp) Properly label the sensors
+    - LP: #615548
+  * hwmon: (coretemp) Skip duplicate CPU entries
+    - LP: #615548
+  * hwmon: (it87) Fix in7 on IT8720F
+    - LP: #615548
+  * cifs: remove bogus first_time check in NTLMv2 session setup code
+    - LP: #615548
+  * cifs: don't attempt busy-file rename unless it's in same directory
+    - LP: #615548
+  * CIFS: Fix a malicious redirect problem in the DNS lookup code
+    - LP: #615548
+  * ALSA: hda - Add Macbook 5,2 quirk
+    - LP: #463178, #615548
+  * cpmac: do not leak struct net_device on phy_connect errors
+    - LP: #615548
+  * sky2: enable rx/tx in sky2_phy_reinit()
+    - LP: #615548
+  * sparc: Fix use of uid16_t and gid16_t in asm/stat.h
+    - LP: #615548
+  * math-emu: correct test for downshifting fraction in _FP_FROM_INT()
+    - LP: #615548
+  * NFSv4: Fix an embarassing typo in encode_attrs()
+    - LP: #615548
+  * NFSv4: Ensure that /proc/self/mountinfo displays the minor version
+    number
+    - LP: #615548
+  * SUNRPC: Fix a re-entrancy bug in xs_tcp_read_calldir()
+    - LP: #615548
+  * ath5k: drop warning on jumbo frames
+    - LP: #615548
+  * ath9k: re-enable ps by default for new single chip families
+    - LP: #615548
+  * ath9k: Avoid corrupt frames being forwarded to mac80211.
+    - LP: #615548
+  * hostap: Protect against initialization interrupt
+    - LP: #615548
+  * TPM: ReadPubEK output struct fix
+    - LP: #615548
+  * fb: fix colliding defines for fb flags.
+    - LP: #615548
+  * iwlwifi: cancel scan watchdog in iwl_bg_abort_scan
+    - LP: #615548
+  * mac80211: do not wip out old supported rates
+    - LP: #615548
+  * mac80211: Handle mesh action frames in ieee80211_rx_h_action
+    - LP: #615548
+  * Btrfs: fix checks in BTRFS_IOC_CLONE_RANGE
+    - LP: #615548
+  * p54pci: add Symbol AP-300 minipci adapters pciid
+    - LP: #615548
+  * dynamic debug: move ddebug_remove_module() down into free_module()
+    - LP: #615548
+  * tpm_tis: fix subsequent suspend failures
+    - LP: #615548
+  * ipvs: Add missing locking during connection table hashing and unhashing
+    - LP: #615548
+  * netfilter: ip6t_REJECT: fix a dst leak in ipv6 REJECT
+    - LP: #615548
+  * SCSI: aacraid: Eliminate use after free
+    - LP: #615548
+  * amd64-agp: Probe unknown AGP devices the right way
+    - LP: #615548
+  * perf: Resurrect flat callchains
+    - LP: #615548
+  * x86: Fix vsyscall on gcc 4.5 with -Os
+    - LP: #615548
+  * x86, Calgary: Increase max PHB number
+    - LP: #615548
+  * x86, Calgary: Limit the max PHB number to 256
+    - LP: #615548
+  * sched: Prevent compiler from optimising the sched_avg_update() loop
+    - LP: #615548
+  * sched: Fix over-scheduling bug
+    - LP: #615548
+  * genirq: Deal with desc->set_type() changing desc->chip
+    - LP: #615548
+  * serial: cpm_uart: implement the cpm_uart_early_write() function for
+    console poll
+    - LP: #615548
+  * cmd640: fix kernel oops in test_irq() method
+    - LP: #615548
+  * ide: Fix IDE taskfile with cfq scheduler
+    - LP: #615548
+  * net/core: neighbour update Oops
+    - LP: #615548
+  * tcp: fix crash in tcp_xmit_retransmit_queue
+    - LP: #615548
+  * rtc: fix ds1388 time corruption
+    - LP: #615548
+  * ethtool: Fix potential kernel buffer overflow in ETHTOOL_GRXCLSRLALL
+    - LP: #615548
+  * sdhci-s3c: add missing remove function
+    - LP: #615548
+  * ASoC: Remove duplicate AUX definition from WM8776
+    - LP: #615548
+  * x86: Fix x2apic preenabled system with kexec
+    - LP: #615548
+  * IPoIB: Fix world-writable child interface control sysfs attributes
+    - LP: #615548
+  * Input: i8042 - add Gigabyte Spring Peak to dmi_noloop_table
+    - LP: #580664, #615548
+  * Input: twl40300-keypad - fix handling of "all ground" rows
+    - LP: #615548
+  * ARM: 6201/1: RealView: Do not use outer_sync() on ARM11MPCore boards
+    with L220
+    - LP: #615548
+  * ARM: 6226/1: fix kprobe bug in ldr instruction emulation
+    - LP: #615548
+  * x86: Do not try to disable hpet if it hasn't been initialized before
+    - LP: #615548
+  * staging: rtl8192su: add USB VID/PID for HWNUm-300
+    - LP: #615548
+  * Staging: rtl8192su: add USB ID for 0bda:8171
+    - LP: #615548
+  * USB: obey the sysfs power/wakeup setting
+    - LP: #615548
+  * USB: g_serial: don't set low_latency flag
+    - LP: #615548
+  * USB: g_serial: fix tty cleanup on unload
+    - LP: #615548
+  * USB: option: add support for 1da5:4518
+    - LP: #615548
+  * USB: Add PID for Sierra 250U to drivers/usb/serial/sierra.c
+    - LP: #599569, #615548
+  * USB: ftdi_sio: support for Signalyzer tools based on FTDI chips
+    - LP: #615548
+  * USB: option: Add support for AMOI Skypephone S2
+    - LP: #615548
+  * USB: adds Artisman USB dongle to list of quirky devices
+    - LP: #615548
+  * USB: sisusbvga: Fix for USB 3.0
+    - LP: #615548
+  * USB: add quirk for Broadcom BT dongle
+    - LP: #615548
+  * USB: FTDI: Add support for the RT System VX-7 radio programming cable
+    - LP: #615548
+  * ethtool: Fix potential user buffer overflow for ETHTOOL_{G, S}RXFH
+    - LP: #615548
+  * ext4: Fix potential quota deadlock
+    - LP: #615548
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #615548
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #615548
+  * ext4: Eliminate potential double free on error path
+    - LP: #615548
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #615548
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #615548
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #615548
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #615548
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #615548
+  * ext4: Handle -EDQUOT error on write
+    - LP: #615548
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #615548
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #615548
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #615548
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #615548
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #615548
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #615548
+  * ext4: fix error handling in migrate
+    - LP: #615548
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #615548
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #615548
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #615548
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #615548
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #615548
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #615548
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #615548
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #615548
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #615548
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #615548
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #615548
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #615548
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #615548
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #615548
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #615548
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #615548
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #615548
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #615548
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #615548
+  * ext4: stop issuing discards if not supported by device
+    - LP: #615548
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #615548
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #615548
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #615548
+  * ext4: init statistics after journal recovery
+    - LP: #615548
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #615548
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #615548
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #615548
+  * ext4: Show journal_checksum option
+    - LP: #615548
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #615548
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #615548
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #615548
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #615548
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #615548
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #615548
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #615548
+  * KVM: MMU: Remove user access when allowing kernel access to gpte.w=0
+    page
+    - LP: #615548
+  * KVM: SVM: Handle MCEs early in the vmexit process
+    - LP: #615548
+  * KVM: SVM: Implement workaround for Erratum 383
+    - LP: #615548
+  * KVM: MMU: invalidate and flush on spte small->large page size change
+    - LP: #615548
+  * futex: futex_find_get_task remove credentails check
+    - LP: #615548
+  * GFS2: Fix up system xattrs
+    - LP: #615548
+  * PM / x86: Save/restore MISC_ENABLE register
+    - LP: #615548
+  * ACPI: skip checking BM_STS if the BIOS doesn't ask for it
+    - LP: #615548
+  * ACPI: Unconditionally set SCI_EN on resume
+    - LP: #615548
+  * libertas/sdio: 8686: set ECSI bit for 1-bit transfers
+    - LP: #615548
+  * dm9000: fix "BUG: spinlock recursion"
+    - LP: #615548
+  * firmware_class: fix memory leak - free allocated pages
+    - LP: #615548
+  * revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second
+    call site)"
+    - LP: #615548
+  * ALSA: Echoaudio, fix Guru Meditation #00000005.48454C50
+    - LP: #615548
+  * V4L/DVB: dvb-core: Fix ULE decapsulation bug
+    - LP: #615548
+  * V4L/DVB: FusionHDTV: Use quick reads for I2C IR device probing
+    - LP: #615548
+  * forcedeth: fix tx limit2 flag check
+    - LP: #615548
+  * staging: rtl8192su: add Support for Belkin F5D8053 v6
+    - LP: #615548
+  * MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1
+    - LP: #615548
+  * V4L/DVB: budget: Select correct frontends
+    - LP: #615548
+  * cxgb3: fix linkup issue
+    - LP: #615548
+  * mac80211: fix supported rates IE if AP doesn't give us it's rates
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for unbranded Arkmicro 18ec:3290 webcams
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for Packard Bell EasyNote MX52
+    integrated webcam
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for V4L2_PIX_FMT_Y16
+    - LP: #615548
+  * iwlagn: verify flow id in compressed BA packet
+    - LP: #615548
+  * kbuild: Fix modpost segfault
+    - LP: #615548
+  * eeepc-laptop: check wireless hotplug events
+    - LP: #615548
+  * Fix spinaphore down_spin()
+    - LP: #615548
+  * ath5k: initialize ah->ah_current_channel
+    - LP: #615548
+  * Input: RX51 keymap - fix recent compile breakage
+    - LP: #615548
+  * V4L/DVB (13830): uvcvideo: add another YUYV format GUID for iSight
+    cameras
+    - LP: #615548
+  * Linux 2.6.32.17
+    - LP: #615548
+  * drm/i915: fix hibernation since i915 self-reclaim fixes
+    - LP: #615548
+  * drm/i915: add 'reclaimable' to i915 self-reclaimable page allocations
+    - LP: #615548
+  * i915: fix lock imbalance on error path...
+    - LP: #615548
+  * drm/i915: Define MI_ARB_STATE bits
+    - LP: #615548
+  * drm/i915: enable low power render writes on GEN3 hardware.
+    - LP: #615548
+  * drm/i915: Make G4X-style PLL search more permissive
+    - LP: #615548
+  * drm/radeon/r200: handle more hw tex coord types
+    - LP: #615548
+  * drm/radeon/r100/r200: fix calculation of compressed cube maps
+    - LP: #615548
+  * drm/radeon/kms: CS checker texture fixes for r1xx/r2xx/r3xx
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc handling
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc harder
+    - LP: #615548
+  * drm/radeon/kms: add quirk for ASUS HD 3600 board
+    - LP: #615548
+  * drm/radeon/kms: fix possible mis-detection of sideport on rs690/rs740
+    - LP: #615548
+  * drm/radeon/kms: fix legacy LVDS dpms sequence
+    - LP: #615548
+  * drm/radeon/kms: fix legacy tv-out pal mode
+    - LP: #615548
+  * Linux 2.6.32.17+drm33.7
+    - LP: #615548
+  * (pre-stable) writeback: remove the always false
+    bdi_cap_writeback_dirty() test
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove unused nonblocking and congestion checks
+    - LP: #543617, #585092
+  * (pre-stable) vfs: improve writeback_inodes_wb()
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing kernel-doc notation
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback completion notifications
+    - LP: #543617, #585092
+  * (pre-stable) writeback: queue work on stack in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: enforce s_umount locking in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback_inodes_wb from
+    writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify wakeup_flusher_threads
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify and split bdi_start_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing requeue_io in writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix pin_sb_for_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove writeback_inodes_wbc
+    - LP: #543617, #585092
+  * (pre-stable) writeback: split writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify the write back thread queue
+    - LP: #543617, #585092
+  * (pre-stable) Fix compiling NFS when backporting writeback
+    - LP: #543617, #585092
+  * sched: cgroup: Implement different treatment for idle shares
+    - LP: #620755
+  * mm: fix ia64 crash when gcore reads gate area
+    - LP: #620755
+  * acl trouble after upgrading ubuntu
+    - LP: #620755
+  * comedi: Uncripple 8255-based DIO subdevices
+    - LP: #620755
+  * NFS: kswapd must not block in nfs_release_page
+    - LP: #620755
+  * PARISC: led.c - fix potential stack overflow in led_proc_write()
+    - LP: #620755
+  * arm/imx/gpio: add spinlock protection
+    - LP: #620755
+  * parisc: pass through '\t' to early (iodc) console
+    - LP: #620755
+  * amd64_edac: Fix DCT base address selector
+    - LP: #620755
+  * amd64_edac: Correct scrub rate setting
+    - LP: #620755
+  * e1000e: don't inadvertently re-set INTX_DISABLE
+    - LP: #620755
+  * e1000e: 82577/82578 PHY register access issues
+    - LP: #620755
+  * 9p: strlen() doesn't count the terminator
+    - LP: #620755
+  * ath9k: enable serialize_regmode for non-PCIE AR9160
+    - LP: #620755
+  * ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation
+    - LP: #620755
+  * ath9k: fix TSF after reset on AR913x
+    - LP: #620755
+  * ath9k: fix yet another buffer leak in the tx aggregation code
+    - LP: #620755
+  * iwlwifi: fix scan abort
+    - LP: #620755
+  * cfg80211: ignore spurious deauth
+    - LP: #620755
+  * cfg80211: don't get expired BSSes
+    - LP: #620755
+  * xfs: prevent swapext from operating on write-only files
+    - LP: #620755
+  * SCSI: enclosure: fix error path - actually return ERR_PTR() on error
+    - LP: #620755
+  * GFS2: rename causes kernel Oops
+    - LP: #620755
+  * slow-work: use get_ref wrapper instead of directly calling get_ref
+    - LP: #620755
+  * CIFS: Remove __exit mark from cifs_exit_dns_resolver()
+    - LP: #620755
+  * CIFS: Fix compile error with __init in cifs_init_dns_resolver()
+    definition
+    - LP: #620755
+  * xen: drop xen_sched_clock in favour of using plain wallclock time
+    - LP: #620755
+  * ssb: do not read SPROM if it does not exist
+    - LP: #620755
+  * ssb: Look for SPROM at different offset on higher rev CC
+    - LP: #620755
+  * ssb: fix NULL ptr deref when pcihost_wrapper is used
+    - LP: #620755
+  * ssb: Handle alternate SSPROM location
+    - LP: #620755
+  * Linux 2.6.32.18
+    - LP: #620755
+  * ata_piix: fix locking around SIDPR access
+    - LP: #622877
+  * powerpc: fix build with make 3.82
+    - LP: #622877
+  * nvram: Fix write beyond end condition; prove to gcc copy is safe
+    - LP: #622877
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #622877
+  * x86, vmware: Preset lpj values when on VMware.
+    - LP: #622877
+  * Staging: line6: needs to select SND_PCM
+    - LP: #622877
+  * Staging: panel: Prevent double-calling of parport_release - fix oops.
+    - LP: #622877
+  * PCI: Do not run NVidia quirks related to MSI with MSI disabled
+    - LP: #622877
+  * PCI: disable MSI on VIA K8M800
+    - LP: #622877
+  * solos-pci: Fix race condition in tasklet RX handling
+    - LP: #622877
+  * splice: fix misuse of SPLICE_F_NONBLOCK
+    - LP: #622877
+  * drivers/video/w100fb.c: ignore void return value / fix build failure
+    - LP: #622877
+  * ide-cd: Do not access completed requests in the irq handler
+    - LP: #622877
+  * md/raid10: fix deadlock with unaligned read during resync
+    - LP: #622877
+  * blkdev: cgroup whitelist permission fix
+    - LP: #622877
+  * eCryptfs: Handle ioctl calls with unlocked and compat functions
+    - LP: #622877
+  * ecryptfs: release reference to lower mount if interpose fails
+    - LP: #622877
+  * fs/ecryptfs/file.c: introduce missing free
+    - LP: #622877
+  * bio, fs: update RWA_MASK, READA and SWRITE to match the corresponding
+    BIO_RW_* bits
+    - LP: #622877
+  * signalfd: fill in ssi_int for posix timers and message queues
+    - LP: #622877
+  * smsc911x: Add spinlocks around registers access
+    - LP: #622877
+  * ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast
+    a faulty ASID
+    - LP: #622877
+  * ARM: 6280/1: imx: Fix build failure when including <mach/gpio.h>
+    without <linux/spinlock.h>
+    - LP: #622877
+  * USB: resizing usbmon binary interface buffer causes protection faults
+    - LP: #622877
+  * USB delay init quirk for logitech Harmony 700-series devices
+    - LP: #622877
+  * USB: serial: enabling support for Segway RMP in ftdi_sio
+    - LP: #622877
+  * USB: option: Huawei ETS 1220 support added
+    - LP: #622877
+  * USB: option: add huawei k3765 k4505 devices to work properly
+    - LP: #622877
+  * USB: ftdi_sio: device id for Navitator
+    - LP: #622877
+  * USB: cp210x: Add four new device IDs
+    - LP: #622877
+  * USB: usbtest: avoid to free coherent buffer in atomic context
+    - LP: #622877
+  * USB: fix thread-unsafe anchor utiliy routines
+    - LP: #622877
+  * drm/edid: Fix the HDTV hack sync adjustment
+    - LP: #622877
+  * Bluetooth: Added support for controller shipped with iMac i5
+    - LP: #622877
+  * jfs: don't allow os2 xattr namespace overlap with others
+    - LP: #622877
+  * arp_notify: allow drivers to explicitly request a notification event.
+    - LP: #622877
+  * xen: netfront: explicitly generate arp_notify event after migration.
+    - LP: #622877
+  * net: Fix NETDEV_NOTIFY_PEERS to not conflict with
+    NETDEV_BONDING_DESLAVE.
+    - LP: #622877
+  * irq: Add new IRQ flag IRQF_NO_SUSPEND
+    - LP: #622877
+  * xen: Do not suspend IPI IRQs.
+    - LP: #622877
+  * drm/i915: Use RSEN instead of HTPLG for tfp410 monitor detection.
+    - LP: #622877
+  * Btrfs: Avoid superfluous tree-log writeout
+    - LP: #622877
+  * Btrfs: Add btrfs_duplicate_item
+    - LP: #622877
+  * Btrfs: Rewrite btrfs_drop_extents
+    - LP: #622877
+  * Btrfs: Fix disk_i_size update corner case
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup while replaying log
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup during committing transaction
+    - LP: #622877
+  * Btrfs: Make fallocate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Make truncate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Pass transaction handle to security and ACL initialization
+    functions
+    - LP: #622877
+  * Btrfs: Add delayed iput
+    - LP: #622877
+  * Btrfs: Fix btrfs_drop_extent_cache for skip pinned case
+    - LP: #622877
+  * Btrfs: Fix per root used space accounting
+    - LP: #622877
+  * Btrfs: don't add extent 0 to the free space cache v2
+    - LP: #622877
+  * Btrfs: fail mount on bad mount options
+    - LP: #622877
+  * Btrfs: deny sys_link across subvolumes.
+    - LP: #622877
+  * Btrfs: Show discard option in /proc/mounts
+    - LP: #622877
+  * Btrfs: make metadata chunks smaller
+    - LP: #622877
+  * Btrfs: make sure fallocate properly starts a transaction
+    - LP: #622877
+  * btrfs: fix missing last-entry in readdir(3)
+    - LP: #622877
+  * Btrfs: align offsets for btrfs_ordered_update_i_size
+    - LP: #622877
+  * Btrfs, fix memory leaks in error paths
+    - LP: #622877
+  * Btrfs: Fix race in btrfs_mark_extent_written
+    - LP: #622877
+  * Btrfs: fix regression in orphan cleanup
+    - LP: #622877
+  * Btrfs: deal with NULL acl sent to btrfs_set_acl
+    - LP: #622877
+  * Btrfs: fix possible panic on unmount
+    - LP: #622877
+  * Btrfs: Use correct values when updating inode i_size on fallocate
+    - LP: #622877
+  * Btrfs: fix a memory leak in btrfs_init_acl
+    - LP: #622877
+  * Btrfs: run orphan cleanup on default fs root
+    - LP: #622877
+  * Btrfs: do not mark the chunk as readonly if in degraded mode
+    - LP: #622877
+  * Btrfs: check return value of open_bdev_exclusive properly
+    - LP: #622877
+  * Btrfs: check total number of devices when removing missing
+    - LP: #622877
+  * Btrfs: fix race between allocate and release extent buffer.
+    - LP: #622877
+  * Btrfs: make error return negative in btrfs_sync_file()
+    - LP: #622877
+  * Btrfs: remove BUG_ON() due to mounting bad filesystem
+    - LP: #622877
+  * Btrfs: Fix oopsen when dropping empty tree.
+    - LP: #622877
+  * Btrfs: do not try and lookup the file extent when finishing ordered io
+    - LP: #622877
+  * Btrfs: apply updated fallocate i_size fix
+    - LP: #622877
+  * Btrfs: btrfs_mark_extent_written uses the wrong slot
+    - LP: #622877
+  * Btrfs: kfree correct pointer during mount option parsing
+    - LP: #622877
+  * nohz: Introduce arch_needs_cpu
+    - LP: #622877
+  * nohz: Reuse ktime in sub-functions of tick_check_idle.
+    - LP: #622877
+  * timekeeping: Fix clock_gettime vsyscall time warp
+    - LP: #622877
+  * sched: Fix granularity of task_u/stime()
+    - LP: #622877
+  * sched, cputime: Introduce thread_group_times()
+    - LP: #622877
+  * mutex: Don't spin when the owner CPU is offline or other weird cases
+    - LP: #622877
+  * fix SBA IOMMU to handle allocation failure properly
+    - LP: #622877
+  * crypto: testmgr - Fix complain about lack test for internal used
+    algorithm
+    - LP: #622877
+  * memory hotplug: fix a bug on /dev/mem for 64-bit kernels
+    - LP: #622877
+  * x86: Fix out of order of gsi
+    - LP: #622877
+  * HWPOISON: remove the anonymous entry
+    - LP: #622877
+  * HWPOISON: abort on failed unmap
+    - LP: #622877
+  * powerpc/eeh: Fix a bug when pci structure is null
+    - LP: #622877
+  * ACPI: Fix regression where _PPC is not read at boot even when
+    ignore_ppc=0
+    - LP: #622877
+  * ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files
+    - LP: #622877
+  * ext4: Fix optional-arg mount options
+    - LP: #622877
+  * reiserfs: properly honor read-only devices
+    - LP: #622877
+  * reiserfs: fix oops while creating privroot with selinux enabled
+    - LP: #622877
+  * dlm: always use GFP_NOFS
+    - LP: #622877
+  * dlm: fix ordering of bast and cast
+    - LP: #622877
+  * dlm: send reply before bast
+    - LP: #622877
+  * ocfs2: Find proper end cpos for a leaf refcount block.
+    - LP: #622877
+  * ocfs2: Set MS_POSIXACL on remount
+    - LP: #622877
+  * Skip check for mandatory locks when unlocking
+    - LP: #622877
+  * loop: Update mtime when writing using aops
+    - LP: #622877
+  * aic79xx: check for non-NULL scb in ahd_handle_nonpkt_busfree
+    - LP: #622877
+  * ibmvfc: Fix command completion handling
+    - LP: #622877
+  * ibmvfc: Reduce error recovery timeout
+    - LP: #622877
+  * md/raid1: delay reads that could overtake behind-writes.
+    - LP: #622877
+  * mm: fix corruption of hibernation caused by reusing swap during image
+    saving
+    - LP: #622877
+  * Linux 2.6.32.19
+    - LP: #622877
+  * Linux 2.6.32.20
+    - LP: #622882
+  * memstick: fix hangs on unexpected device removal in mspro_blk
+    - LP: #625392
+  * ASoC: Fix inverted mute controls for WM8580
+    - LP: #625392
+  * ASoC: Remove DSP mode support for WM8776
+    - LP: #625392
+  * ALSA: riptide - Fix detection / load of firmware files
+    - LP: #625392
+  * ALSA: emu10k1 - delay the PCM interrupts (add pcm_irq_delay parameter)
+    - LP: #625392
+  * ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA
+    codec
+    - LP: #625392
+  * ocfs2: do not overwrite error codes in ocfs2_init_acl
+    - LP: #625392
+  * ocfs2/dlm: fix a dead lock
+    - LP: #625392
+  * ocfs2 fix o2dlm dlm run purgelist (rev 3)
+    - LP: #625392
+  * ocfs2: Count more refcount records in file system fragmentation.
+    - LP: #625392
+  * ocfs2/dlm: avoid incorrect bit set in refmap on recovery master
+    - LP: #625392
+  * ocfs2/dlm: remove potential deadlock -V3
+    - LP: #625392
+  * x86, hotplug: Serialize CPU hotplug to avoid bringup concurrency issues
+    - LP: #625392
+  * x86, apic: Fix apic=debug boot crash
+    - LP: #625392
+  * Fix the nested PR lock calling issue in ACL
+    - LP: #625392
+  * hwmon: (pc87360) Fix device resource declaration
+    - LP: #625392
+  * ARM: Tighten check for allowable CPSR values
+    - LP: #625392
+  * nfs: Add "lookupcache" to displayed mount options
+    - LP: #625392
+  * ath5k: disable ASPM L0s for all cards
+    - LP: #625392
+  * pxa3xx: fix ns2cycle equation
+    - LP: #625392
+  * dm mpath: fix NULL pointer dereference when path parameters missing
+    - LP: #625392
+  * dm ioctl: release _hash_lock between devices in remove_all
+    - LP: #625392
+  * mm: make the vma list be doubly linked
+    - LP: #625392
+  * mm: make the mlock() stack guard page checks stricter
+    - LP: #625392
+  * mm: make stack guard page logic use vm_prev pointer
+    - LP: #625392
+  * slab: fix object alignment
+    - LP: #625392
+  * sunxvr500: Ignore secondary output PCI devices.
+    - LP: #625392
+  * sparc64: Add missing ID to parport probing code.
+    - LP: #625392
+  * sparc64: Fix rwsem constant bug leading to hangs.
+    - LP: #625392
+  * sparc64: Fix atomic64_t routine return values.
+    - LP: #625392
+  * net: Fix a memmove bug in dev_gro_receive()
+    - LP: #625392
+  * isdn: fix information leak
+    - LP: #625392
+  * act_nat: the checksum of ICMP doesn't have pseudo header
+    - LP: #625392
+  * vmscan: raise the bar to PAGEOUT_IO_SYNC stalls
+    - LP: #625392
+  * pcmcia: avoid buffer overflow in pcmcia_setup_isa_irq
+    - LP: #625392
+  * ext4: consolidate in_range() definitions
+    - LP: #625392
+  * Oprofile: Change CPUIDS from decimal to hex, and add some comments
+    - LP: #625392
+  * oprofile: add support for Intel processor model 30
+    - LP: #625392
+  * fixes for using make 3.82
+    - LP: #625392
+  * ALSA: intel8x0: Mute External Amplifier by default for ThinkPad X31
+    - LP: #619439, #625392
+  * netlink: fix compat recvmsg
+    - LP: #625392
+  * powerpc: Fix typo in uImage target
+    - LP: #625392
+  * USB: option: add Celot CT-650
+    - LP: #625392
+  * USB: add device IDs for igotu to navman
+    - LP: #625392
+  * USB: pl2303: New vendor and product id
+    - LP: #625392
+  * USB: CP210x Fix Break On/Off
+    - LP: #625392
+  * USB: ftdi_sio: fix endianess of max packet size
+    - LP: #625392
+  * USB: io_ti: check firmware version before updating
+    - LP: #625392
+  * USB: xhci: Remove buggy assignment in next_trb()
+    - LP: #625392
+  * USB: ftdi_sio: Add ID for Ionics PlugComputer
+    - LP: #625392
+  * USB: ftdi_sio: add product ID for Lenz LI-USB
+    - LP: #625392
+  * x86, apic: ack all pending irqs when crashed/on kexec
+    - LP: #625392
+  * Linux 2.6.32.21
+    - LP: #625392
+
+  [ Ubuntu: 2.6.32-24.43 ]
+
+  * x86-64, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * x86-64, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * compat: Make compat_alloc_user_space() incorporate the access_ok()
+    - CVE-2010-3081
+
+  [ Ubuntu: 2.6.32-24.42 ]
+
+  * (pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #561802, #578673
+  * (pre-stable) drm/i915: make sure eDP panel is turned on
+    - LP: #578673
+  * (pre-stable) drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #578673
+
+ -- Brad Figg <brad.figg@canonical.com>  Fri, 01 Oct 2010 10:39:03 -0700
+
+linux-ec2 (2.6.32-308.16) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.43
+
+  [ Ubuntu: 2.6.32-24.43 ]
+
+  * x86-64, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * x86-64, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * compat: Make compat_alloc_user_space() incorporate the access_ok()
+    - CVE-2010-3081
+
+  [ Ubuntu: 2.6.32-24.42 ]
+
+  * (pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #561802, #578673
+  * (pre-stable) drm/i915: make sure eDP panel is turned on
+    - LP: #578673
+  * (pre-stable) drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #578673
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 16 Sep 2010 10:39:18 +0200
+
+linux-ec2 (2.6.32-308.15) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.41
+
+  [ Ubuntu: 2.6.32-24.41 ]
+
+  * (pre-stable) ext4: fix freeze deadlock under IO
+    - LP: #595489
+  * drm: Initialize ioctl struct when no user data is present
+    - CVE-2010-2803
+  * can: add limit for nframes and clean up signed/unsigned variables
+    - CVE-2010-2959
+  * mm: keep a guard page below a grow-down stack segment
+    - CVE-2010-2240
+  * mm: fix missing page table unmap for stack guard page failure case
+    - CVE-2010-2240
+  * mm: fix page table unmap for stack guard page properly
+    - CVE-2010-2240
+  * mm: fix up some user-visible effects of the stack guard page
+    - CVE-2010-2240
+  * x86: don't send SIGBUS for kernel page faults
+    - CVE-2010-2240
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 18 Aug 2010 14:33:06 +0200
+
+linux-ec2 (2.6.32-308.14) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.39
+
+  [ Ubuntu: 2.6.32-24.39 ]
+
+  * sctp: Fix skb_over_panic resulting from multiple invalid parameter
+    errors (CVE-2010-1173) (v4)
+    - CVE-2010-1173
+  * sctp: fix append error cause to ERROR chunk correctly
+    - CVE-2010-1173
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - CVE-2010-1436
+  * KEYS: find_keyring_by_name() can gain access to a freed keyring
+    - CVE-2010-1437
+  * GFS2: Fix permissions checking for setflags ioctl()
+    - CVE-2010-1641
+  * Btrfs: should add a permission check for setfacl
+    - CVE-2010-2071
+  * ecryptfs: Bugfix for error related to ecryptfs_hash_buckets
+    - CVE-2010-2492
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 21 Jul 2010 10:58:47 +0200
+
+linux-ec2 (2.6.32-308.13) lucid-proposed; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebased to 2.6.32-24.38
+
+  [ Ubuntu: 2.6.32-24.38 ]
+
+  * SAUCE: dell-laptop: fire SMI when toggling hardware killswitch
+    (revised)
+    - LP: #590607
+  * sfc: Wait at most 10ms for the MC to finish reading out MAC statistics
+    - LP: #590783
+  * sfc: Always close net device at the end of a disabling reset
+    - LP: #590783
+  * sfc: Change falcon_probe_board() to fail for unsupported boards
+    - LP: #590783
+  * ext4: Fix potential quota deadlock
+    - LP: #588069
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #588069
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #588069
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #588069
+  * ext4: Eliminate potential double free on error path
+    - LP: #588069
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #588069
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #588069
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #588069
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #588069
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #588069
+  * ext4: Handle -EDQUOT error on write
+    - LP: #588069
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #588069
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #588069
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #588069
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #588069
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #588069
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #588069
+  * ext4: fix error handling in migrate
+    - LP: #588069
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #588069
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #588069
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #588069
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #588069
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #588069
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #588069
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #588069
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #588069
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #588069
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #588069
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #588069
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #588069
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #588069
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #588069
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #588069
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #588069
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #588069
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #588069
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #588069
+  * ext4: stop issuing discards if not supported by device
+    - LP: #588069
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #588069
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #588069
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #588069
+  * ext4: init statistics after journal recovery
+    - LP: #588069
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #588069
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #588069
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #588069
+  * ext4: Show journal_checksum option
+    - LP: #588069
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #588069
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #588069
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #588069
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #588069
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #588069
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #588069
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #588069
+  * (pre-stable) ahci,ata_generic: let ata_generic handle new MBP w/ MCP89
+    - LP: #576601
+  * (pre-stable) ata_generic: implement ATA_GEN_* flags and force enable
+    DMA on MBP 7,1
+    - LP: #576601
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 08 Jul 2010 10:53:59 +0200
+
+linux-ec2 (2.6.32-307.12) lucid-proposed; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-23.37
+  * update to ubuntu-debian:7e708d33054c373faf41da23b73e8b48c342d958
+    - LP: #570500, #576274
+  * xen: follow changes to smp headers adding wbinvd
+    - LP: #575853
+
+  [ Ubuntu: 2.6.32-23.37 ]
+
+  * SAUCE: drm/radeon/kms/atom: fix dual-link DVI on DCE3.2/4.0
+    - LP: #564559
+  * [Config] ports -- build in dm-mod to enable LVM boot
+    - LP: #560717
+  * tools -- fix perf version extraction for multi-part flavours
+    - LP: #555130
+  * [Config] enforce -- ensure dm_mod is built-in for LVM
+    - LP: #560717
+  * update to ubuntu-debian:7e708d33054c373faf41da23b73e8b48c342d958
+    - LP: #570500, #576274
+  * Revert "(pre-stable): input: ALPS - Add signature for HP Pavilion dm3
+    laptops"
+    - LP: #550625
+  * Enable ftrace function profiler
+    - LP: #570389
+  * enforce CONFIG_TMPFS_POSIX_ACL=y
+    - LP: #575940
+  * Revert "staging/comdi -- disable"
+    - LP: #563436
+  * [Config] Enable multicast routing for sparc
+    - LP: #416266
+  * [Config] Add ahci.ko to virtual sub-flavour
+    - LP: #570542
+  * Revert "SAUCE: drm/i915: Disable FBC on 915GM and 945GM"
+    - LP: #588832
+  * [Config] Add atl1c to nic-modules udeb
+    - LP: #557130
+  * Revert "(pre-stable) iwlwifi: fix nfreed--"
+    - LP: #575853
+  * Revert "backlight: mbp_nvidia_bl - add five more MacBook variants"
+    - LP: #575853
+  * Revert "(pre-stable) pata_via: Add VIA VX900 support"
+    - LP: #575853
+  * Revert "(pre-stable) x86-32, resume: do a global tlb flush in S4
+    resume"
+    - LP: #575853
+  * Revert "x86: disable IOMMUs on kernel crash"
+    - LP: #575853
+  * Revert "sunrpc: fix peername failed on closed listener"
+    - LP: #575853
+  * Revert "sunrpc: move the close processing after do recvfrom method"
+    - LP: #575853
+  * Revert "(pre-stable) drm/edid: allow certain bogus edids to hit a fixup
+    path rather than fail"
+    - LP: #575853
+  * Revert "drm/radeon/kms: don't print error on -ERESTARTSYS."
+    - LP: #575853
+  * Revert "ath9k: fix lockdep warning when unloading module" on stable
+    kernels
+    - LP: #588832
+  * Staging: comedi: removed "depricated" from COMEDI_CB_BLOCK
+    - LP: #483343
+  * fat: fix buffer overflow in vfat_create_shortname()
+    - LP: #575853
+  * xfs: simplify inode teardown
+    - LP: #575853
+  * xfs: fix mmap_sem/iolock inversion in xfs_free_eofblocks
+    - LP: #575853
+  * xfs: I/O completion handlers must use NOFS allocations
+    - LP: #575853
+  * xfs: Wrapped journal record corruption on read at recovery
+    - LP: #575853
+  * xfs: Fix error return for fallocate() on XFS
+    - LP: #575853
+  * xfs: check for not fully initialized inodes in xfs_ireclaim
+    - LP: #575853
+  * xfs: fix timestamp handling in xfs_setattr
+    - LP: #575853
+  * xfs: Don't flush stale inodes
+    - LP: #575853
+  * xfs: Ensure we force all busy extents in range to disk
+    - LP: #575853
+  * xfs: reclaim inodes under a write lock
+    - LP: #575853
+  * xfs: Avoid inodes in reclaim when flushing from inode cache
+    - LP: #575853
+  * xfs: reclaim all inodes by background tree walks
+    - LP: #575853
+  * xfs: fix stale inode flush avoidance
+    - LP: #575853
+  * xfs: xfs_swap_extents needs to handle dynamic fork offsets
+    - LP: #575853
+  * xfs: quota limit statvfs available blocks
+    - LP: #575853
+  * xfs: don't hold onto reserved blocks on remount, ro
+    - LP: #575853
+  * xfs: remove invalid barrier optimization from xfs_fsync
+    - LP: #575853
+  * xfs: Non-blocking inode locking in IO completion
+    - LP: #575853
+  * xfs: fix locking for inode cache radix tree tag updates
+    - LP: #575853
+  * sh: Enable the mmu in start_secondary()
+    - LP: #575853
+  * sh: Fix FDPIC binary loader
+    - LP: #575853
+  * libiscsi: Fix recovery slowdown regression
+    - LP: #575853
+  * Freezer: Fix buggy resume test for tasks frozen with cgroup freezer
+    - LP: #575853
+  * iwlwifi: counting number of tfds can be free for 4965
+    - LP: #575853
+  * iwlwifi: fix nfreed--
+    - LP: #575853
+  * iwlwifi: range checking issue
+    - LP: #575853
+  * setup correct int pipe type in ar9170_usb_exec_cmd
+    - LP: #575853
+  * mac80211: move netdev queue enabling to correct spot
+    - LP: #575853
+  * mac80211: tear down all agg queues when restart/reconfig hw
+    - LP: #575853
+  * WATCHDOG: hpwdt - fix lower timeout limit
+    - LP: #575853
+  * WATCHDOG: iTCO_wdt: TCO Watchdog patch for additional Intel Cougar
+    Point DeviceIDs
+    - LP: #575853
+  * genirq: Force MSI irq handlers to run with interrupts disabled
+    - LP: #575853
+  * lis3: fix show rate for 8 bits chips
+    - LP: #575853
+  * pata_ali: Fix regression with old devices
+    - LP: #575853
+  * HID: fix oops in gyration_event()
+    - LP: #575853
+  * raw: fsync method is now required
+    - LP: #575853
+  * readahead: fix NULL filp dereference
+    - LP: #575853
+  * ALSA: mixart: range checking proc file
+    - LP: #575853
+  * ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981
+    - LP: #551606, #575853
+  * x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config
+    space
+    - LP: #575853
+  * resource: move kernel function inside __KERNEL__
+    - LP: #575853
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #575853
+  * pata_via: Add VIA VX900 support
+    - LP: #575853
+  * ext3: Don't update the superblock in ext3_statfs()
+    - LP: #575853
+  * ext3: journal all modifications in ext3_xattr_set_handle
+    - LP: #575853
+  * eeepc-laptop: disable cpu speed control on EeePC 701
+    - LP: #575853
+  * eeepc-laptop: dmi blacklist to disable pci hotplug code
+    - LP: #575853
+  * eeepc-laptop: add hotplug_disable parameter
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1201N
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1005PE
+    - LP: #575853
+  * libata: disable NCQ on Crucial C300 SSD
+    - LP: #575853
+  * cifs: Fix a kernel BUG with remote OS/2 server (try #3)
+    - LP: #575853
+  * CIFS: initialize nbytes at the beginning of CIFSSMBWrite()
+    - LP: #575853
+  * iwlwifi: need check for valid qos packet before free
+    - LP: #575853
+  * ARM: 6031/1: fix Thumb-2 decompressor
+    - LP: #575853
+  * x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #575853
+  * x86: hpet: Make WARN_ON understandable
+    - LP: #575853
+  * x86, hpet: Erratum workaround for read after write of HPET comparator
+    - LP: #575853
+  * x86: Fix double enable_IR_x2apic() call on SMP kernel on !SMP boards
+    - LP: #575853
+  * sched: sched_getaffinity(): Allow less than NR_CPUS length
+    - LP: #575853
+  * sched: Fix sched_getaffinity()
+    - LP: #575853
+  * NFSv4: Fall back to ordinary lookup if nfs4_atomic_open() returns
+    EISDIR
+    - LP: #575853
+  * NFSv4: fix delegated locking
+    - LP: #575853
+  * ALSA: hda - add a quirk for Clevo M570U laptop
+    - LP: #575853
+  * ALSA: usb - Fix Oops after usb-midi disconnection
+    - LP: #575853
+  * hwmon: (sht15) Fix sht15_calc_temp interpolation function
+    - LP: #575853
+  * hwmon: (sht15) Properly handle the case CONFIG_REGULATOR=n
+    - LP: #575853
+  * x86/amd-iommu: Use helper function to destroy domain
+    - LP: #575853
+  * x86/amd-iommu: enable iommu before attaching devices
+    - LP: #575853
+  * x86, lib: Add wbinvd smp helpers
+    - LP: #575853
+  * x86, cacheinfo: Fix disabling of L3 cache indices
+    - LP: #575853
+  * intel-agp: Switch to wbinvd_on_all_cpus
+    - LP: #575853
+  * x86, cacheinfo: Add cache index disable sysfs attrs only to L3 caches
+    - LP: #575853
+  * x86, cacheinfo: Calculate L3 indices
+    - LP: #575853
+  * x86, cacheinfo: Remove NUMA dependency, fix for AMD Fam10h rev D1
+    - LP: #575853
+  * x86, cacheinfo: Enable L3 CID only on AMD
+    - LP: #575853
+  * vgaarb: fix "target=default" passing
+    - LP: #575853
+  * x86-32: clean up rwsem inline asm statements
+    - LP: #575853
+  * x86: clean up rwsem type system
+    - LP: #575853
+  * x86-64, rwsem: 64-bit xadd rwsem implementation
+    - LP: #575853
+  * x86-64: support native xadd rwsem implementation
+    - LP: #575853
+  * x86: Fix breakage of UML from the changes in the rwsem system
+    - LP: #575853
+  * x86-64, rwsem: Avoid store forwarding hazard in __downgrade_write
+    - LP: #575853
+  * fix NFS4 handling of mountpoint stat
+    - LP: #575853
+  * dm mpath: fix stall when requeueing io
+    - LP: #575853
+  * quota: Fix possible dq_flags corruption
+    - LP: #575853
+  * Staging: comedi: fix usbdux timeout bug
+    - LP: #483343, #575853
+  * Staging: comedi: usbdux.c: fix locking up of the driver when the comedi
+    ringbuffer runs empty
+    - LP: #483343, #575853
+  * ocfs2: set i_mode on disk during acl operations
+    - LP: #575853
+  * ocfs2: Change bg_chain check for ocfs2_validate_gd_parent.
+    - LP: #575853
+  * 9p: Skip check for mandatory locks when unlocking
+    - LP: #575853
+  * fc class: fail fast bsg requests
+    - LP: #575853
+  * SCSI: add scsi target reset support to scsi ioctl
+    - LP: #575853
+  * PCIe AER: prevent AER injection if hardware masks error reporting
+    - LP: #575853
+  * vgaarb: Fix VGA arbiter to accept PCI domains other than 0
+    - LP: #575853
+  * SCSI: fc-transport: Use packed modifier for fc_bsg_request structure.
+    - LP: #575853
+  * pci: Update pci_set_vga_state() to call arch functions
+    - LP: #575853
+  * PCI: kill off pci_register_set_vga_state() symbol export.
+    - LP: #575853
+  * PCI: fix nested spinlock hang in aer_inject
+    - LP: #575853
+  * IPoIB: Fix TX queue lockup with mixed UD/CM traffic
+    - LP: #575853
+  * x86/PCI: irq and pci_ids patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda_intel: ALSA HD Audio patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda - enable snoop for Intel Cougar Point
+    - LP: #575853
+  * ata_piix: IDE Mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ahci: AHCI and RAID mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * i2c-i801: Add Intel Cougar Point device IDs
+    - LP: #575853
+  * b43: Remove reset after fatal DMA error
+    - LP: #575853
+  * b43: Allow PIO mode to be selected at module load
+    - LP: #575853
+  * b43: fall back gracefully to PIO mode after fatal DMA errors
+    - LP: #575853
+  * ALSA: hda - Add position_fix quirk for Biostar mobo
+    - LP: #575853
+  * agp/hp: fixup hp agp after ACPI changes
+    - LP: #575853
+  * b43: Optimize PIO scratchbuffer usage
+    - LP: #575853
+  * ecryptfs: fix use with tmpfs by removing d_drop from
+    ecryptfs_destroy_inode
+    - LP: #575853
+  * eCryptfs: Decrypt symlink target for stat size
+    - LP: #575853
+  * ecryptfs: fix error code for missing xattrs in lower fs
+    - LP: #575853
+  * sched: Fix a race between ttwu() and migrate_task()
+    - LP: #575853
+  * USB: cdc-acm: Update to new autopm API
+    - LP: #575853
+  * USB: cdc-acm: Fix stupid NULL pointer in resume()
+    - LP: #575853
+  * iwlwifi: clear all tx queues when firmware ready
+    - LP: #575853
+  * iwlwifi: fix scan race
+    - LP: #575853
+  * e1000e: stop cleaning when we reach tx_ring->next_to_use
+    - LP: #575853
+  * tcp: fix ICMP-RTO war
+    - LP: #575853
+  * perf_events, x86: Implement Intel Westmere/Nehalem-EX support
+    - LP: #575853
+  * Input: wacom - switch mode upon system resume
+    - LP: #575853
+  * md: deal with merge_bvec_fn in component devices better.
+    - LP: #575853
+  * nfsd4: don't try to map gid's in generic rpc code
+    - LP: #575853
+  * nfsd: ensure sockets are closed on error
+    - LP: #575853
+  * ALSA: hda: Set Front Mic to input vref 50% for Lenovo 3000 Y410
+    - LP: #479373, #575853
+  * mac80211: fix deferred hardware scan requests
+    - LP: #575853
+  * fs-writeback: Add helper function to start writeback if idle
+    - LP: #575853
+  * ext4: flush delalloc blocks when space is low
+    - LP: #575853
+  * ext4: fix async i/o writes beyond 4GB to a sparse file
+    - LP: #575853
+  * tpm: autoload tpm_tis based on system PnP IDs
+    - LP: #575853
+  * IB/iser: Rewrite SG handling for RDMA logic
+    - LP: #575853
+  * mptctl : Remove printk which floods unnecessary messages to
+    var/log/message
+    - LP: #575853
+  * mptspi: Fix for incorrect data underrun errata
+    - LP: #575853
+  * sched: Use proper type in sched_getaffinity()
+    - LP: #575853
+  * KVM: SVM: Fix memory leaks that happen when svm_create_vcpu() fails
+    - LP: #575853
+  * KVM: Don't spam kernel log when injecting exceptions due to bad cr
+    writes
+    - LP: #575853
+  * KVM: allow bit 10 to be cleared in MSR_IA32_MC4_CTL
+    - LP: #575853
+  * KVM: VMX: Save/restore rflags.vm correctly in real mode
+    - LP: #575853
+  * KVM: MMU: fix kvm_mmu_zap_page() and its calling path
+    - LP: #575853
+  * KVM: fix the handling of dirty bitmaps to avoid overflows
+    - LP: #575853
+  * KVM: Increase NR_IOBUS_DEVS limit to 200
+    - LP: #575853
+  * KVM: x86: Fix TSS size check for 16-bit tasks
+    - LP: #575853
+  * x86/gart: Disable GART explicitly before initialization
+    - LP: #575853
+  * r8169: clean up my printk uglyness
+    - LP: #562742, #575853
+  * Linux 2.6.32.12
+    - LP: #575853
+  * drm/edid: allow certain bogus edids to hit a fixup path rather than
+    fail
+    - LP: #575853
+  * drm/radeon: add new RS880 pci id
+    - LP: #575853
+  * drm: remove the EDID blob stored in the EDID property when it is
+    disconnected
+    - LP: #575853
+  * drm/radeon/kms: never treat rs4xx as AGP
+    - LP: #575853
+  * drm/radeon/kms: Fix NULL pointer dereference if memory allocation
+    failed in a simple way
+    - LP: #575853
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #575853
+  * drm/radeon/kms: fix pal tv-out support on legacy IGP chips
+    - LP: #575853
+  * drm: Return ENODEV if the inode mapping changes
+    - LP: #575853
+  * drm/edid/quirks: Envision EN2028
+    - LP: #575853
+  * drm/radeon: R300 AD only has one quad pipe.
+    - LP: #575853
+  * drm/radeon/kms: fix washed out image on legacy tv dac
+    - LP: #575853
+  * drm/radeon/kms/combios: verify dac_adj values are valid
+    - LP: #575853
+  * drm/i915: Add no_lvds entry for the Clientron U800
+    - LP: #544671, #575853
+  * drm/radeon/kms: more atom parser fixes (v2)
+    - LP: #575853
+  * drm/radeon/kms: disable the tv encoder when tv/cv is not in use
+    - LP: #575853
+  * drm/radeon/kms: fix tv dac conflict resolver
+    - LP: #575853
+  * drm/radeon/kms: fix rs600 tlb flush
+    - LP: #575853
+  * drm/radeon/kms: add FireMV 2400 PCI ID.
+    - LP: #575853
+  * Linux 2.6.32.12+drm33.3
+    - LP: #575853
+  * USB: EHCI: defer reclamation of siTDs
+    - LP: #583414
+  * p54usb: Add usbid for Corega CG-WLUSB2GT.
+    - LP: #583414
+  * md/raid5: allow for more than 2^31 chunks.
+    - LP: #583414
+  * md/raid5: fix previous patch.
+    - LP: #583414
+  * libata: fix locking around blk_abort_request()
+    - LP: #583414
+  * libata: ensure NCQ error result taskfile is fully initialized before
+    returning it via qc->result_tf.
+    - LP: #583414
+  * w1: w1 temp: fix negative termperature calculation
+    - LP: #583414
+  * memcg: fix prepare migration
+    - LP: #583414
+  * mac80211: remove bogus TX agg state assignment
+    - LP: #583414
+  * flex_array: fix the panic when calling flex_array_alloc() without
+    __GFP_ZERO
+    - LP: #583414
+  * core, x86: make LIST_POISON less deadly
+    - LP: #583414
+  * hugetlb: fix infinite loop in get_futex_key() when backed by huge pages
+    - LP: #583414
+  * reiserfs: fix corruption during shrinking of xattrs
+    - LP: #583414
+  * nfsd4: bug in read_buf
+    - LP: #583414
+  * keys: the request_key() syscall should link an existing key to the dest
+    keyring
+    - LP: #583414
+  * staging: usbip: Fix deadlock
+    - LP: #583414
+  * USB: fix remote wakeup settings during system sleep
+    - LP: #583414
+  * USB: Add id for HP ev2210 a.k.a Sierra MC5725 miniPCI-e Cell Modem.
+    - LP: #511066, #583414
+  * USB: fix testing the wrong variable in fs_create_by_name()
+    - LP: #583414
+  * USB: don't choose configs with no interfaces
+    - LP: #583414
+  * USB: OHCI: don't look at the root hub to get the number of ports
+    - LP: #583414
+  * USB: xhci: properly set the "Mult" field of the endpoint context.
+    - LP: #583414
+  * USB: xhci: properly set endpoint context fields for periodic eps.
+    - LP: #583414
+  * procfs: fix tid fdinfo
+    - LP: #583414
+  * ocfs2: Update VFS inode's id info after reflink.
+    - LP: #583414
+  * ocfs2: potential ERR_PTR dereference on error paths
+    - LP: #583414
+  * ocfs2: Compute metaecc for superblocks during online resize.
+    - LP: #583414
+  * ocfs2_dlmfs: Fix math error when reading LVB.
+    - LP: #583414
+  * powernow-k8: Fix frequency reporting
+    - LP: #572348, #583414
+  * nfs d_revalidate() is too trigger-happy with d_drop()
+    - LP: #583414
+  * NFS: rsize and wsize settings ignored on v4 mounts
+    - LP: #583414
+  * Staging: hv: Fix a bug affecting IPv6
+    - LP: #583414
+  * Staging: hv: Fix up memory leak on HvCleanup
+    - LP: #583414
+  * Staging: hv: name network device ethX rather than sethX
+    - LP: #583414
+  * i2c: Fix probing of FSC hardware monitoring chips
+    - LP: #583414
+  * perf: Fix resource leak in failure path of perf_event_open()
+    - LP: #583414
+  * raid6: fix recovery performance regression
+    - LP: #583414
+  * serial: 8250_pnp - add Fujitsu Wacom device
+    - LP: #583414
+  * block: ensure jiffies wrap is handled correctly in
+    blk_rq_timed_out_timer
+    - LP: #583414
+  * dm9601: fix phy/eeprom write routine
+    - LP: #583414
+  * p54pci: fix bugs in p54p_check_tx_ring
+    - LP: #583414
+  * edac, mce: Fix wrong mask and macro usage
+    - LP: #583414
+  * x86-64: Clear a 64-bit FS/GS base on fork if selector is nonzero
+    - LP: #583414
+  * x86: Disable large pages on CPUs with Atom erratum AAE44
+    - LP: #583414
+  * x86, k8 nb: Fix boot crash: enable k8_northbridges unconditionally on
+    AMD systems
+    - LP: #583414
+  * x86, AMD: Fix stale cpuid4_info shared_map data in shared_cpu_map
+    cpumasks
+    - LP: #583414
+  * ALSA: hda: Use LPIB quirk for DG965OT board version AAD63733-203
+    - LP: #459083, #583414
+  * ALSA: hda - Add PCI quirk for HP dv6-1110ax.
+    - LP: #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio XPS 1645
+    - LP: #553002, #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio 1558
+    - LP: #568600, #583414
+  * ALSA: hda: Use ALC880_F1734 quirk for Fujitsu Siemens AMILO Xi 1526
+    - LP: #567494, #583414
+  * ALSA: snd-meastro3: Add amp_gpio quirk for Compaq EVO N600C
+    - LP: #583414
+  * ALSA: snd-meastro3: Ignore spurious HV interrupts during suspend /
+    resume
+    - LP: #583414
+  * ALSA: hda: Fix max PCM level to 0 dB for Fujitsu-Siemens laptops using
+    CX20549 (Venice)
+    - LP: #583414
+  * ALSA: hda: Fix 0 dB for Packard Bell models using Conexant CX20549
+    (Venice)
+    - LP: #541802, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite Pro T130-15F
+    - LP: #573284, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite
+    P500-PSPGSC-01800T
+    - LP: #549267, #583414
+  * libata: Fix accesses at LBA28 boundary (old bug, but nasty) (v2)
+    - LP: #583414
+  * ext4: correctly calculate number of blocks for fiemap
+    - LP: #474597, #583414
+  * initramfs: handle unrecognised decompressor when unpacking
+    - LP: #583414
+  * CRED: Fix a race in creds_are_invalid() in credentials debugging
+    - LP: #583414
+  * jfs: fix diAllocExt error in resizing filesystem
+    - LP: #583414
+  * ACPI: introduce kernel parameter acpi_sleep=sci_force_enable
+    - LP: #553498, #583414
+  * p54pci: rx frame length check
+    - LP: #583414
+  * drivers/net/wireless/p54/txrx.c Fix off by one error
+    - LP: #583414
+  * dccp_probe: Fix module load dependencies between dccp and dccp_probe
+    - LP: #583414
+  * KVM: remove unused load_segment_descriptor_to_kvm_desct
+    - LP: #583414
+  * kgdb: don't needlessly skip PAGE_USER test for Fsl booke
+    - LP: #583414
+  * r8169: use correct barrier between cacheable and non-cacheable memory
+    - LP: #562742, #583414
+  * r8169: fix broken register writes
+    - LP: #562742, #583414
+  * r8169: more broken register writes workaround
+    - LP: #562742, #583414
+  * PCI: Ensure we re-enable devices on resume
+    - LP: #566149, #583414
+  * skip sense logging for some ATA PASS-THROUGH cdbs
+    - LP: #583128, #583414
+  * tg3: Fix INTx fallback when MSI fails
+    - LP: #583414
+  * xfs: add a shrinker to background inode reclaim
+    - LP: #583414
+  * qla2xxx: Properly handle UNDERRUN completion statuses.
+    - LP: #583414
+  * bnx2: Fix lost MSI-X problem on 5709 NICs.
+    - LP: #583414
+  * tracing: Fix ftrace_event_call alignment for use with gcc 4.5
+    - LP: #583414
+  * security: testing the wrong variable in create_by_name()
+    - LP: #583414
+  * md: restore ability of spare drives to spin down.
+    - LP: #583414
+  * virtio: initialize earlier
+    - LP: #583414
+  * md/raid6: Fix raid-6 read-error correction in degraded state
+    - LP: #583414
+  * V4L/DVB: budget: Oops: "BUG: unable to handle kernel NULL pointer
+    dereference"
+    - LP: #583414
+  * ACPI: DMI init_set_sci_en_on_resume for multiple Lenovo ThinkPads
+    - LP: #583414
+  * power_meter: acpi_device_class "power_meter_resource" too long
+    - LP: #583414
+  * ACPI: sleep: init_set_sci_en_on_resume for Dell Studio 155x
+    - LP: #553498, #583414
+  * cpuidle: Fix incorrect optimization
+    - LP: #583414
+  * pxa/colibri: fix missing #include <mach/mfp.h> in colibri.h
+    - LP: #583414
+  * SCSI: fix locking around blk_abort_request()
+    - LP: #583414
+  * SCSI: libiscsi: regression: fix header digest errors
+    - LP: #583414
+  * scsi_debug: virtual_gb ignores sector_size
+    - LP: #583414
+  * Enable retries for SYNCRONIZE_CACHE commands to fix I/O error
+    - LP: #583414
+  * SCSI: Retry commands with UNIT_ATTENTION sense codes to fix ext3/ext4
+    I/O error
+    - LP: #583414
+  * MIPS: Sibyte: Apply M3 workaround only on affected chip types and
+    versions.
+    - LP: #583414
+  * Linux 2.6.32.13
+    - LP: #583414
+  * drm/i915: Add initial bits for VGA modesetting bringup on Sandybridge.
+    - LP: #583414
+  * drm/i915: fix tiling limits for i915 class hw v2
+    - LP: #583414
+  * Linux 2.6.32.13+drm33.4
+    - LP: #583414
+  * (pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting
+    - LP: #551234
+  * ipv4: udp: fix short packet and bad checksum logging
+    - LP: #588832
+  * hp_accel: fix race in device removal
+    - LP: #588832
+  * fbdev: bfin-t350mcqb-fb: fix fbmem allocation with blanking lines
+    - LP: #588832
+  * hugetlbfs: kill applications that use MAP_NORESERVE with SIGBUS instead
+    of OOM-killer
+    - LP: #588832
+  * dma-mapping: fix dma_sync_single_range_*
+    - LP: #588832
+  * ACPI: sleep: eliminate duplicate entries in acpisleep_dmi_table[]
+    - LP: #588832
+  * mmc: atmel-mci: fix two parameters swapped
+    - LP: #588832
+  * mmc: atmel-mci: prevent kernel oops while removing card
+    - LP: #588832
+  * mmc: atmel-mci: remove data error interrupt after xfer
+    - LP: #588832
+  * ptrace: fix return value of do_syscall_trace_enter()
+    - LP: #588832
+  * powerpc/perf_event: Fix oops due to perf_event_do_pending call
+    - LP: #588832
+  * cifs: guard against hardlinking directories
+    - LP: #588832
+  * serial: imx.c: fix CTS trigger level lower to avoid lost chars
+    - LP: #588832
+  * ALSA: ice1724 - Fix ESI Maya44 capture source control
+    - LP: #588832
+  * ALSA: hda: Fix 0 dB for Lenovo models using Conexant CX20549 (Venice)
+    - LP: #588832
+  * inotify: race use after free/double free in inotify inode marks
+    - LP: #588832
+  * inotify: don't leak user struct on inotify release
+    - LP: #588832
+  * profile: fix stats and data leakage
+    - LP: #588832
+  * x86, k8: Fix build error when K8_NB is disabled
+    - LP: #588832
+  * x86, cacheinfo: Turn off L3 cache index disable feature in virtualized
+    environments
+    - LP: #588832
+  * x86, amd: Check X86_FEATURE_OSVW bit before accessing OSVW MSRs
+    - LP: #588832
+  * Btrfs: check for read permission on src file in the clone ioctl
+    - LP: #588832
+  * ALSA: hda - New Intel HDA controller
+    - LP: #588832
+  * proc: partially revert "procfs: provide stack information for threads"
+    - LP: #588832
+  * revert "procfs: provide stack information for threads" and its fixup
+    commits
+    - LP: #588832
+  * iwlwifi: clear all the stop_queue flag after load firmware
+    - LP: #588832
+  * p54: disable channels with incomplete calibration data sets
+    - LP: #588832
+  * CacheFiles: Fix error handling in cachefiles_determine_cache_security()
+    - LP: #588832
+  * megaraid_sas: fix for 32bit apps
+    - LP: #588832
+  * mmap_min_addr check CAP_SYS_RAWIO only for write
+    - LP: #588832
+  * nilfs2: fix sync silent failure
+    - LP: #588832
+  * crypto: authenc - Add EINPROGRESS check
+    - LP: #588832
+  * Linux 2.6.32.14
+    - LP: #588832
+  * drm/i915: use PIPE_CONTROL instruction on Ironlake and Sandy Bridge
+    - LP: #588832
+  * drm/i915: fix non-Ironlake 965 class crashes
+    - LP: #588832
+  * drm/i915: Disable FBC on 915GM and 945GM.
+    - LP: #492392, #588832
+  * Linux 2.6.32.14+drm33.5
+    - LP: #588832
+  * Linux 2.6.32.15+drm33.5
+    - LP: #588832
+  * HID: remove MODULE_VERSION from new drivers
+    - LP: #583531
+  * HID: fix N-trig touch panel with recent firmware
+    - LP: #583531
+  * HID: ntrig: explain firmware quirk
+    - LP: #583531
+  * HID: ntrig: Emit TOUCH with DOUBLETAP for single touch
+    - LP: #583531
+  * HID: ntrig: TipSwitch for single touch mode touch.
+    - LP: #583531
+  * HID: ntrig: Remove unused macro, TripleTap and QuadTap
+    - LP: #583531
+  * (pre-stable) drm/radeon/kms: initialize set_surface_reg reg for rs600
+    asic
+    - LP: #544590
+
+  [ Ubuntu: 2.6.32-22.36 ]
+
+  * Revert "kvm: restrict writing of segment selectors to segment
+    registers"
+    - LP: #589223
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Sat, 12 Jun 2010 16:24:14 +0200
+
+linux-ec2 (2.6.32-306.11) lucid-security; urgency=low
+
+  [ Stefan Bader ]
+
+  * Rebase to 2.6.32-22.35
+  * [Config] EC2: Set CONFIG_BLK_DEV_DM=y to match enforcer settings
+
+  [ Ubuntu: 2.6.32-22.35 ]
+
+  * kvm: restrict writing of segment selectors to segment registers
+    - CVE-2010-0419
+  * tty: release_one_tty() forgets to put pids
+    - CVE-2010-1162
+  * oom: fix the unsafe usage of badness() in proc_oom_score()
+    - CVE-2010-1488
+  * Attempt #2 to handle null nameidata
+    - CVE-2010-1148
+  * reiserfs: fix permissions on .reiserfs_priv
+    - CVE-2010-1146
+  * r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)
+    - CVE-2009-4537
+
+  [ Ubuntu: 2.6.32-22.33 ]
+
+  * SAUCE: ACPI: EC: Allow multibyte access to EC (v3)
+    - LP: #526354
+  * ubuntu: rtl8192se -- update to version 0015.0127.2010
+    - LP: #567016
+
+  [ Ubuntu: 2.6.32-21.32 ]
+
+  * SAUCE: i915 KMS -- support disabling KMS for known broken devices
+    - LP: #563277
+  * SAUCE: i915 KMS -- blacklist i830
+    - LP: #542208, #563277
+  * SAUCE: i915 KMS -- blacklist i845g
+    - LP: #541492, #563277
+  * SAUCE: i915 KMS -- blacklist i855
+    - LP: #511001, #541511, #563277
+  * SAUCE: radeon KMS -- support disabling KMS for known broken devices
+    - LP: #546743
+  * SAUCE: radeon KMS -- blacklist ES1000
+    - LP: #546743
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 01 Jun 2010 12:14:05 +0200
+
+linux-ec2 (2.6.32-305.9) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-21.31
+  * SAUCE: xen -- TSC is not available under XEN
+
+  [ John Johansen ]
+
+  * [Config] enable NETFILTER_XT_MATCH_RECENT for ec2 kernels
+    - LP: #532553
+
+  [ Ubuntu: 2.6.32-21.31 ]
+
+  * allow modules.builtin to be optional
+  * d-i: add mpt2sas to the message-modules udeb
+    - LP: #530361
+  * SAUCE: Nouveau: Add quirk framework to disable acceleration
+    - LP: #544088, #546393
+  * SAUCE: Nouveau: Disable acceleration on MacBook Pros
+    - LP: #546393
+  * SAUCE: Nouveau: Disable acceleration on GeForce3 cards
+    - LP: #544088
+  * SAUCE: Nouveau: Disable acceleration on 6100 cards
+    - LP: #542950
+  * SAUCE: dma-mapping: Remove WARN_ON in dma_free_coherent
+    - LP: #458201
+  * SAUCE: sync before umount to reduce time taken by ext4 umount
+    - LP: #543617
+  * tipc: Fix oops on send prior to entering networked mode (v3)
+    - CVE-2010-1187
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - LP: #561425
+  * KVM: x86 emulator: fix memory access during x86 emulation
+    - LP: #561425
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - LP: #561425
+  * KVM: x86 emulator: Fix popf emulation
+    - LP: #561425
+  * KVM: Fix segment descriptor loading
+    - LP: #561425
+  * KVM: VMX: Update instruction length on intercepted BP
+    - LP: #561425
+  * KVM: VMX: Use macros instead of hex value on cr0 initialization
+    - LP: #561425
+  * KVM: SVM: Reset cr0 properly on vcpu reset
+    - LP: #561425
+  * KVM: VMX: Disable unrestricted guest when EPT disabled
+    - LP: #561425
+  * KVM: x86: disable paravirt mmu reporting
+    - LP: #561425
+  * AppArmor: Fix put of unassigned ns if aa_unpack fails
+  * AppArmor: Fix refcount bug when exec fails
+    - LP: #562063
+  * AppArmor: Take refcount on cxt->profile to ensure it remains a valid
+    reference
+    - LP: #367499
+  * AppArmor: fix typo in scrubbing environment variable warning
+    - LP: #562060
+  * AppArmor: fix regression by setting default to mediate deleted files
+    - LP: #562056
+  * AppArmor: fix refcount order bug that can trigger during replacement
+    - LP: #367499
+  * AppArmor: Make sure to unmap aliases for vmalloced dfas before they are
+    live
+    - LP: #529288
+  * AppArmor: address performance regression of replaced profile
+    - LP: #549428
+  * AppArmor: make the global side the correct type
+    - LP: #562047
+  * AppArmor: use the kernel shared workqueue to free vmalloc'ed dfas
+  * sky2: add register definitions for new chips
+    - LP: #537168
+  * sky2: 88E8059 support
+    - LP: #537168
+  * net: Fix Yukon-2 Optima TCP offload setup
+    - LP: #537168
+  * net: Add missing TST_CFG_WRITE bits around sky2_pci_write
+    - LP: #537168
+  * sky2: print Optima chip name
+    - LP: #537168
+  * (Upstream) dell-laptop: defer dell_rfkill_update to worker thread
+    - LP: #555261
+  * drm/nv40: add LVDS table quirk for Dell Latitude D620
+    - LP: #539730
+
+  [ Ubuntu: 2.6.32-20.30 ]
+
+  * Revert "(pre-stable) ACPI: EC: Allow multibyte access to EC"
+    - LP: #561151
+
+  [ Ubuntu: 2.6.32-20.29 ]
+
+  * Revert "SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915"
+    - LP: #542251
+  * add Breaks: against hardy lvm2
+    - LP: #528155
+  * d-i -- enable udebs for generic-pae
+    - LP: #160366
+  * [Config] Add xen netboot support
+    - LP: #160366
+  * (pre-stable): input: Support Clickpad devices in ClickZone mode
+    - LP: #516329
+  * Revert "(pre-stable) Bluetooth: Fix sleeping function in RFCOMM within
+    invalid context"
+    - LP: #553837
+  * Revert "(pre-stable) USB: fix usbfs regression"
+    - LP: #553837
+  * Revert "(pre-stable) softlockup: Stop spurious softlockup messages due
+    to overflow"
+    - LP: #553837
+  * Revert "(pre-stable) drm/nouveau: report unknown connector state if lid
+    closed"
+    - LP: #553837
+  * drivers/scsi/ses.c: eliminate double free
+    - LP: #553837
+  * decompress: fix new decompressor for PIC
+    - LP: #553837
+  * ARM: Fix decompressor's kernel size estimation for ROM=y
+    - LP: #553837
+  * MIPS: Cleanup forgotten label_module_alloc in tlbex.c
+    - LP: #553837
+  * tg3: Fix tg3_poll_controller() passing wrong pointer to tg3_interrupt()
+    - LP: #553837
+  * tg3: Fix 5906 transmit hangs
+    - LP: #553837
+  * ALSA: hda - Fix input source elements of secondary ADCs on Realtek
+    - LP: #553837
+  * ALSA: hda: enable MSI for Gateway M-6866
+    - LP: #538918, #553837
+  * timekeeping: Prevent oops when GENERIC_TIME=n
+    - LP: #553837
+  * Input: alps - add support for the touchpad on Toshiba Tecra A11-11L
+    - LP: #553837
+  * Input: i8042 - add ALDI/MEDION netbook E1222 to qurik reset table
+    - LP: #553837
+  * i2c-i801: Don't use the block buffer for I2C block writes
+    - LP: #553837
+  * ath5k: dont use external sleep clock in AP mode
+    - LP: #553837
+  * ath5k: fix setup for CAB queue
+    - LP: #553837
+  * ring-buffer: Move disabled check into preempt disable section
+    - LP: #553837
+  * function-graph: Init curr_ret_stack with ret_stack
+    - LP: #553837
+  * Bluetooth: Fix sleeping function in RFCOMM within invalid context
+    - LP: #553837
+  * tracing: Use same local variable when resetting the ring buffer
+    - LP: #553837
+  * tracing: Disable buffer switching when starting or stopping trace
+    - LP: #553837
+  * tracing: Do not record user stack trace from NMI context
+    - LP: #553837
+  * PCI: unconditionally clear AER uncorr status register during cleanup
+    - LP: #553837
+  * efifb: fix framebuffer handoff
+    - LP: #553837
+  * coredump: suppress uid comparison test if core output files are pipes
+    - LP: #553837
+  * V4L/DVB (13961): em28xx-dvb: fix memleak in dvb_fini()
+    - LP: #553837
+  * hrtimer: Tune hrtimer_interrupt hang logic
+    - LP: #553837
+  * x86, apic: Don't use logical-flat mode when CPU hotplug may exceed 8
+    CPUs
+    - LP: #553837
+  * mvsas: add support for Adaptec ASC-1045/1405 SAS/SATA HBA
+    - LP: #553837
+  * pci: add support for 82576NS serdes to existing SR-IOV quirk
+    - LP: #553837
+  * sched: Mark boot-cpu active before smp_init()
+    - LP: #553837
+  * sparc64: Make prom entry spinlock NMI safe.
+    - LP: #553837
+  * sysctl: require CAP_SYS_RAWIO to set mmap_min_addr
+    - LP: #553837
+  * e1000e: enable new 82567V-3 device
+    - LP: #553837
+  * ixgbe: add support for 82599 KR device 0x1517
+    - LP: #553837
+  * ath9k: fix lockdep warning when unloading module
+    - LP: #553837
+  * mqueue: fix mq_open() file descriptor leak on user-space processes
+    - LP: #553837
+  * virtio: fix out of range array access
+    - LP: #553837
+  * sched: Fix SCHED_MC regression caused by change in sched cpu_power
+    - LP: #553837
+  * readahead: add blk_run_backing_dev
+    - LP: #553837
+  * ALSA: hda: Use LPIB and 6stack-dig for eMachines T5212
+    - LP: #538895, #553837
+  * ALSA: hda - Disable MSI for Nvidia controller
+    - LP: #553837
+  * ALSA: hda - Fix secondary ADC of ALC260 basic model
+    - LP: #553837
+  * ALSA: hda: Fix 0 dB offset for HP laptops using CX20551 (Waikiki)
+    - LP: #420578, #553837
+  * ALSA: cmipci: work around invalid PCM pointer
+    - LP: #553837
+  * gigaset: correct clearing of at_state strings on RING
+    - LP: #553837
+  * gigaset: prune use of tty_buffer_request_room
+    - LP: #553837
+  * perf: Make the install relative to DESTDIR if specified
+    - LP: #553837
+  * perf_event: Fix oops triggered by cpu offline/online
+    - LP: #553837
+  * tmpfs: fix oops on mounts with mpol=default
+    - LP: #553837
+  * tmpfs: mpol=bind:0 don't cause mount error.
+    - LP: #553837
+  * tmpfs: handle MPOL_LOCAL mount option properly
+    - LP: #553837
+  * tmpfs: cleanup mpol_parse_str()
+    - LP: #553837
+  * doc: add the documentation for mpol=local
+    - LP: #553837
+  * SCSI: scsi_transport_fc: Fix synchronization issue while deleting vport
+    - LP: #553837
+  * NFSv4: Don't ignore the NFS_INO_REVAL_FORCED flag in
+    nfs_revalidate_inode()
+    - LP: #553837
+  * NFS: Avoid a deadlock in nfs_release_page
+    - LP: #553837
+  * NFS: Prevent another deadlock in nfs_release_page()
+    - LP: #553837
+  * tty: Keep the default buffering to sub-page units
+    - LP: #553837
+  * tty: Take a 256 byte padding into account when buffering below sub-page
+    units
+    - LP: #553837
+  * USB: fix usbfs regression
+    - LP: #553837
+  * USB: EHCI: fix ITD list order
+    - LP: #553837
+  * USB: EHCI: adjust ehci_iso_stream for changes in ehci_qh
+    - LP: #553837
+  * USB: qcserial: add new device ids
+    - LP: #553837
+  * USB: xHCI: re-initialize cmd_completion
+    - LP: #553837
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #553837
+  * USB: option: fix incorrect manufacturer name in usb/serial/option:
+    MAXON->CMOTECH
+    - LP: #553837
+  * USB: option: move hardcoded PID to a macro in usb/serial/option
+    - LP: #553837
+  * USB: option: add support for a new CMOTECH device to usb/serial/option
+    - LP: #553837
+  * usb: r8a66597-hcd: fix removed from an attached hub
+    - LP: #553837
+  * wl1251: fix potential crash
+    - LP: #553837
+  * jme: Fix VLAN memory leak
+    - LP: #553837
+  * jme: Protect vlgrp structure by pause RX actions.
+    - LP: #553837
+  * edac, mce: Filter out invalid values
+    - LP: #553837
+  * iwlwifi: use dma_alloc_coherent
+    - LP: #553837
+  * iwlwifi: Silence tfds_in_queue message
+    - LP: #553837
+  * SUNRPC: Fix a potential memory leak in auth_gss
+    - LP: #553837
+  * sunrpc: handle allocation errors from __rpc_lookup_create()
+    - LP: #553837
+  * if_tunnel.h: add missing ams/byteorder.h include
+    - LP: #553837
+  * fs/partitions/msdos: add support for large disks
+    - LP: #553837
+  * fs/partition/msdos: fix unusable extended partition for > 512B sector
+    - LP: #553837
+  * PCI: fix return value from pcix_get_max_mmrbc()
+    - LP: #553837
+  * PCI: fix access of PCI_X_CMD by pcix get and set mmrbc functions
+    - LP: #553837
+  * PCI: cleanup error return for pcix get and set mmrbc functions
+    - LP: #553837
+  * rt2860sta: Fix argument to linux_pci_unmap_single()
+    - LP: #553837
+  * ath9k: fix BUG_ON triggered by PAE frames
+    - LP: #553837
+  * cpuset: fix the problem that cpuset_mem_spread_node() returns an
+    offline node
+    - LP: #553837
+  * softlockup: Stop spurious softlockup messages due to overflow
+    - LP: #553837
+  * netfilter: xt_recent: fix regression in rules using a zero hit_count
+    - LP: #553837
+  * x86: Fix placement of FIX_OHCI1394_BASE
+    - LP: #553837
+  * x86, amd: Restrict usage of c1e_idle()
+    - LP: #553837
+  * hwmon: (coretemp) Add missing newline to dev_warn() message
+    - LP: #553837
+  * ALSA: hda: Use LPIB for ga-ma770-ud3 board
+    - LP: #553837
+  * ALSA: ac97: Add Toshiba P500 to ac97 jack sense blacklist
+    - LP: #481058, #553837
+  * ALSA: ac97: Add IBM ThinkPad R40e to Headphone/Line Jack Sense
+    blacklist
+    - LP: #303789, #553837
+  * ALSA: hda: Use ALC260_WILL quirk for another Acer model (0x1025007f)
+    - LP: #418627, #553837
+  * ath9k: Enable TIM timer interrupt only when needed.
+    - LP: #553837
+  * mac80211: Retry null data frame for power save
+    - LP: #553837
+  * ath9k: Enable IEEE80211_HW_REPORTS_TX_ACK_STATUS flag for ath9k
+    - LP: #553837
+  * mac80211: Reset dynamic ps timer in Rx path.
+    - LP: #553837
+  * leds-gpio: fix default state handling on OF platforms
+    - LP: #553837
+  * quota: manage reserved space when quota is not active [v2]
+    - LP: #553837
+  * quota: Fix warning when a delayed write happens before quota is enabled
+    - LP: #553837
+  * ahci: use BIOS date in broken_suspend list
+    - LP: #553837
+  * Bluetooth: Fix potential bad memory access with sysfs files
+    - LP: #553837
+  * Bluetooth: Fix kernel crash on L2CAP stress tests
+    - LP: #553837
+  * sh: Fix zImage boot using fixed PMB.
+    - LP: #553837
+  * b43: Workaround circular locking in hw-tkip key update callback
+    - LP: #553837
+  * block: Backport of various I/O topology fixes from 2.6.33 and 2.6.34
+    - LP: #553837
+  * s3cmci: initialize default platform data no_wprotect and no_detect with
+    1
+    - LP: #553837
+  * x86: Fix sched_clock_cpu for systems with unsynchronized TSC
+    - LP: #553837
+  * GFS2: Skip check for mandatory locks when unlocking
+    - LP: #553837
+  * Linux 2.6.32.11
+    - LP: #553837
+  * drm/i915: fix small leak on overlay error path
+    - LP: #553837
+  * drm/i915: Avoid NULL deref in get_pages() unwind after error.
+    - LP: #553837
+  * drm/nouveau: report unknown connector state if lid closed
+    - LP: #553837
+  * Linux-2.6.32.11+drm33.2
+    - LP: #553837
+  * mmc: add module parameter to set whether cards are assumed removable
+    - LP: #477106
+  * (pre-stable) ACPI: EC: Allow multibyte access to EC
+    - LP: #526354
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #509273
+  * drm/i915: Add dependency on the intel agp module
+    - LP: #542251
+  * (pre-stable) drm/edid: allow certain bogus edids to hit a fixup path
+    rather than fail
+    - LP: #540632
+  * drm/radeon/kms: rework pll algo selection
+    - LP: #538377
+  * drm/radeon/kms: update new pll algo
+    - LP: #538377
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #544741
+  * sched: update load count only once per cpu in 10 tick update window
+    - LP: #513848
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 14 Apr 2010 13:09:10 +0100
+
+linux-ec2 (2.6.32-304.8) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-19.28
+  * updateconfigs after rebase to Ubuntu-2.6.32-19.28
+
+  [ John Johansen ]
+
+  * [Config] fix EC2 config to remove soft lockup issue
+    - LP: #527208, #540378
+
+  [ Ubuntu: 2.6.32-19.28 ]
+
+  * [Config] enable various multitouch devices
+    - LP: #541453
+  * (pre-stable): input: ALPS - Add signature for HP Pavilion dm3 laptops
+    - LP: #545307
+  * SAUCE: Disable function tracing after hitting __schedule_bug
+  * SAUCE: Reduce ACPI resource conflict message to KERN_INFO, printf
+    cleanup
+    - LP: #440470
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+  * SAUCE: AppArmor: Remove null_profile's use of PFLAG_NO_LIST_REF
+    - LP: #539437
+  * SAUCE: AppArmor: Stop page allocation warnings that can occur on policy
+    load
+    - LP: #458299
+  * SAUCE: AppArmor: Return string len rather than the allocation size
+    - LP: #551844
+  * SAUCE: AppArmor: Fix oops in profile verification if profile unpack
+    fails.
+  * [Config] Enable Nouveau DRM module on powerpc
+  * SAUCE: Pull in thinkpad-acpi from v2.6.34-rc1
+    - LP: #357673
+  * [Config] Enable thinkpad-acpi ALSA volume control
+    - LP: #357673
+  * SAUCE: drm/i915: Disable FBC on 915GM and 945GM
+    - LP: #492392, #539609
+  * Revert "(pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP,
+    Dell Inspiron 700m"
+    - LP: #515246
+  * (pre-stable) softlockup: Stop spurious softlockup messages due to
+    overflow
+    - LP: #551068
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #511965
+  * drm/nv04-nv40: Fix up the programmed horizontal sync pulse delay.
+    - LP: #529130
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #544739
+  * (pre-stable) USB: fix usbfs regression
+  * drm/radeon/bo: add some fallback placements for VRAM only objects.
+    - LP: #507148
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #507148
+  * Input: add the ABS_MT_PRESSURE event
+    - LP: #541453
+  * HID: Support for 3M multitouch panel
+    - LP: #541453
+  * HID: make 3M PCT touchscreen driver standalone config option
+    - LP: #541453
+  * HID: add support for Stantum multitouch panel
+    - LP: #541453
+  * HID: make Stantum driver standalone config option
+    - LP: #541453
+  * HID: add support for Acer T230H multitouch
+    - LP: #541453
+  * HID: add support for Pixart Imaging Optical Touch Screen
+    - LP: #541453
+  * HID: fixed bug in single-touch emulation on the stantum panel
+    - LP: #541453
+  * HID: add pressure support for the Stantum multitouch panel
+    - LP: #541453
+  * HID: Support for MosArt multitouch panel
+    - LP: #541453
+  * HID: hid-ntrig add multi input quirk and clean up
+    - LP: #541453
+  * HID: n-trig: remove unnecessary tool switching
+    - LP: #541453
+  * HID: hid-ntrig: multitouch cleanup and fix
+    - LP: #541453
+  * HID: hid-ntrig: Single touch mode tap
+    - LP: #541453
+  * hid: ntrig touch events
+    - LP: #541453
+  * (pre-stable) x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #531309
+  * drm/i915: Part of: Add initial bits for VGA modesetting bringup on
+    Sandybridge.
+    - LP: #515246
+  * drm/i915: Stop trying to use ACPI lid status to determine LVDS
+    connection.
+    - LP: #515246
+
+  [ Ubuntu: 2.6.32-18.27 ]
+
+  * SAUCE: Don't register vga16fb framebuffer if other framebuffers are
+    present
+    - LP: #527369
+  * [Config] armel/versatile: Set CRAMFS=m
+    - LP: #524893
+  * [Config] armel: Reset default command-line
+    - LP: #524893
+  * build/modules: Update d-i to reflect recent config changes
+    - LP: #546929
+  * (pre-stable) drm/nouveau: report unknown connector state if lid closed
+    - LP: #523072
+  * (pre-stable) Staging: rt2870: Add USB ID for Buffalo Airstation
+    WLI-UC-GN
+    - LP: #441990
+  * (pre-stable) iwlwifi: fix nfreed--
+    - LP: #545585
+  * (pre-stable) pata_via: Add VIA VX900 support
+    - LP: #548675
+
+  [ Ubuntu: 2.6.32-17.26 ]
+
+  * [Config] SECURITY_FILE_CAPABILITIES dissapeared in 2.6.33
+  * rules -- allow architecture configurations to be missing
+  * SAUCE: cdrom -- default to not locking the tray when in use
+    - LP: #397734
+  * expose the kernel EXTRAVERSION in dmesg and /proc/version_signature
+  * record the drm version in EXTRAVERSION
+  * linux-tools -- pull out the perf binary into a binary package
+  * [Config] enable MMIOTRACE for graphics debugging
+  * [Config] enable BLK_DEV_BSG
+  * debian -- fix builds when tools are disabled
+  * allow us to build default configs for automated builds
+  * config -- allow locally specified configuration overrides
+  * [Config] de-modularise PATA disk controllers
+  * [Config] de-modularise SATA disk controllers
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow"
+    - LP: #540231
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix false match"
+    - LP: #540231
+  * [Config] Update configs for 2.6.32.10
+    - LP: #540231
+  * [Config] Add vmw_pvscsi and vmxnet3 to -virtual flavour
+    - LP: #531017
+  * SAUCE: igb: Supress an upstream compiler complaint
+  * [Config] Fix sub-flavours package conflicts
+    - LP: #454827
+  * Revert "tpm_tis: TPM_STS_DATA_EXPECT workaround"
+    - LP: #540231
+  * Revert "(pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()"
+    - LP: #540231
+  * (pre-stable) Bluetooth: Fix sleeping function in RFCOMM within invalid
+    context
+    - LP: #534549
+  * igb: remove unused temp variable from stats clearing path
+  * igb: update comments for serdes config and update to handle duplex
+  * igb: update the approach taken to acquiring and releasing the phy lock
+  * igb: add locking to reads of the i2c interface
+  * igb: add combined function for setting rar and pool bits
+  * igb: make use of the uta to allow for promiscous mode filter
+  * igb: add support for 82576NS SerDes adapter
+  * igb: add function to handle mailbox lock
+  * igb: fix a few items where weren't correctly setup for mbx timeout
+  * igb: change how we handle alternate mac addresses
+  * igb: remove microwire support from igb
+  * igb: move the generic copper link setup code into e1000_phy.c
+  * igb: add code to retry a phy read in the event of failure on link check
+  * igb: add additional error handling to the phy code
+  * igb: add flushes between RAR writes when setting mac address
+  * igb: Use the instance of net_device_stats from net_device.
+  * igb: Fix erroneous display of stats by ethtool -S
+  * igb: add new data structure for handling interrupts and NAPI
+  * igb: remove rx checksum good counter
+  * igb: increase minimum rx buffer size to 1K
+  * igb: move the tx and rx ring specific config into seperate functions
+  * igb: remove rx_ps_hdr_len
+  * igb: move SRRCTL register configuration into ring specific config
+  * igb: change the head and tail offsets into pointers
+  * igb: add pci device pointer to ring structure
+  * igb: move rx_buffer_len into the ring structure
+  * igb: move alloc_failed and csum_err stats into per rx-ring stat
+  * igb: add a flags value to the ring
+  * igb: place a pointer to the netdev struct in the ring itself
+  * igb: move the multiple receive queue configuration into seperate
+    function
+  * igb: delay VF reset notification until after interrupts are enabed
+  * igb: setup vlan tag replication stripping in igb_vmm_control
+  * igb: re-use ring configuration code in ethtool testing
+  * igb: make tx ring map and free functionality non-static
+  * igb: make ethtool use core xmit map and free functionality
+  * igb: add single vector msi-x testing to interrupt test
+  * igb: cleanup "todo" code found in igb_ethtool.c
+  * igb: add support for seperate tx-usecs setting in ethtool
+  * igb: cleanup some of the code related to hw timestamping
+  * igb: misc cleanups within igb_ethtool.c
+  * igb: use packet buffer sizes from RXPBS register
+  * igb: replace the VF clear_to_send with a flags value
+  * igb: rework use of VMOLR in regards to PF and VFs
+  * igb: rework handling of the vfta and vlvf registers in relation to
+    mng_vlan
+  * igb: move vf init into a seperate function
+  * igb: only process global stats in igb_update_stats
+  * igb: move global_quad_port_a from global into local static define
+  * igb: make tx hang check multiqueue, check eop descriptor
+  * igb: cleanup code related to ring resource allocation and free
+  * igb: change queue ordering for 82576 based adapters
+  * igb: cleanup interrupt enablement in regards to msix_other
+  * igb: Remove invalid stats counters
+  * igb: cleanup igb.h header whitespace and some structure formatting
+  * igb: cleanup igb xmit frame path
+  * igb: cleanup clean_rx_irq_adv and alloc_rx_buffers_adv
+  * igb: replace unecessary &adapter->hw with just hw where applicable
+  * igb: add pci_dev in few spots to clean up use of dev_err/info/warn
+  * igb: limit minimum mtu to 68 to keep ip bound to interface
+  * igb: open up SCTP checksum offloads to all MACs 82576 and newer
+  * igb: cleanup whitespace issues in igb_main.c
+  * igb: Fix warnings in igb_set_ringparam()
+  * igb: change type for ring sizes to u16 in igb_set_ring_param
+  * igb: move timesync init into a seperate function
+  * igb: when number of CPUs > 4 combine tx/rx queues to allow more queues
+  * igb: Rework how netdev->stats is handled
+  * igb: removed unused tx/rx total bytes/packets from adapter struct
+  * igb: check for packets on all tx rings when link is down
+  * igb: only recycle page if it is on our numa node
+  * igb: add support for the 82580 phy
+  * igb: add support for 82580 MAC
+  * igb: Add full support for 82580 devices
+  * igb: remove use of skb_dma_map from driver
+  * igb: fix handling of mailbox collisions between PF/VF
+  * igb: do not force pcs link when in KX mode
+  * igb: do not force retry count to 1 on 82580 phy
+  * igb: correctly offset 82575 flow control watermarks by 16 bytes
+  * igb: check both function bits in status register in wol exception
+  * igb: make certain to reassign legacy interrupt vectors after reset
+  * igb/igbvf: cleanup exception handling in tx_map_adv
+  * fix LOOKUP_FOLLOW on automount "symlinks"
+    - LP: #540231
+  * ARM: 5944/1: scsi: fix timer setup in fas216.c
+    - LP: #540231
+  * V4L/DVB: dvb: l64781.ko broken with gcc 4.5
+    - LP: #540231
+  * bfin: fix max timeout calculation
+    - LP: #540231
+  * V4L/DVB: Video : pwc : Fix regression in pwc_set_shutter_speed caused
+    by bad constant => sizeof conversion.
+    - LP: #540231
+  * V4L/DVB: bttv: Move I2C IR initialization
+    - LP: #540231
+  * V4L/DVB: cxusb: Select all required frontend and tuner modules
+    - LP: #540231
+  * memcg: fix oom killing a child process in an other cgroup
+    - LP: #540231
+  * fs/exec.c: fix initial stack reservation
+    - LP: #540231
+  * iwlwifi: error checking for number of tfds in queue
+    - LP: #540231
+  * iwlwifi: set HT flags after channel in rxon
+    - LP: #540231
+  * iwlwifi: sanity check before counting number of tfds can be free
+    - LP: #540231
+  * netlabel: fix export of SELinux categories > 127
+    - LP: #540231
+  * ahci: disable FPDMA auto-activate optimization on NVIDIA AHCI
+    - LP: #540231
+  * PCI hotplug: ibmphp: read the length of ebda and map entire ebda region
+    - LP: #540231
+  * PCI hotplug: check ioremap() return value in ibmphp_ebda.c
+    - LP: #540231
+  * ACPI: remove Asus P2B-DS from acpi=ht blacklist
+    - LP: #540231
+  * ACPI: fix "acpi=ht" boot option
+    - LP: #540231
+  * thinkpad-acpi: wrong thermal attribute_group removed in thermal_exit()
+    - LP: #540231
+  * ACPI: Be in TS_POLLING state during mwait based C-state entry
+    - LP: #540231
+  * mpt2sas: Delete volume before HBA detach.
+    - LP: #540231
+  * slab: initialize unused alien cache entry as NULL at
+    alloc_alien_cache().
+    - LP: #540231
+  * mac80211: quit addba_resp_timer if Tx BA session is torn down
+    - LP: #540231
+  * V4L/DVB (13991): gspca_mr973010a: Fix cif type 1 cameras not streaming
+    on UHCI controllers
+    - LP: #540231
+  * vfs: take f_lock on modifying f_mode after open time
+    - LP: #540231
+  * readahead: introduce FMODE_RANDOM for POSIX_FADV_RANDOM
+    - LP: #540231
+  * HID: remove TENX iBuddy from blacklist
+    - LP: #540231
+  * HID: add multi-input quirk for NextWindow Touchscreen.
+    - LP: #540231
+  * HID: usbhid: introduce timeout for stuck ctrl/out URBs
+    - LP: #540231
+  * airo: fix setting zero length WEP key
+    - LP: #540231
+  * idr: fix a critical misallocation bug, take#2
+    - LP: #540231
+  * Switch proc/self to nd_set_link()
+    - LP: #540231
+  * sparc: Align clone and signal stacks to 16 bytes.
+    - LP: #540231
+  * sparc32: Fix page_to_phys().
+    - LP: #540231
+  * sparc32: Fix struct stat uid/gid types.
+    - LP: #540231
+  * sparc: leds_resource.end assigned to itself in clock_board_probe()
+    - LP: #540231
+  * sparc64: Fix sun4u execute bit check in TSB I-TLB load.
+    - LP: #540231
+  * net: Fix sysctl restarts...
+    - LP: #540231
+  * net-sysfs: Use rtnl_trylock in wireless sysfs methods.
+    - LP: #540231
+  * net: bug fix for vlan + gro issue
+    - LP: #540231
+  * inet: Remove bogus IGMPv3 report handling
+    - LP: #540231
+  * ipv6: conntrack: Add member of user to nf_ct_frag6_queue structure
+    - LP: #540231
+  * drivers/net: ks8851_mll ethernet network driver
+    - LP: #540231
+  * sky2: fix transmit DMA map leakage
+    - LP: #540231
+  * SCSI: qla2xxx: Obtain proper host structure during response-queue
+    processing.
+    - LP: #540231
+  * rtc-core: fix memory leak
+    - LP: #540231
+  * offb: Add support for framebuffer handoff to offb.
+    - LP: #540231
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #540231
+  * rndis_wlan: handle NL80211_AUTHTYPE_AUTOMATIC
+    - LP: #540231
+  * rndis_wlan: fix buffer overflow in rndis_query_oid
+    - LP: #540231
+  * rndis_wlan: disable stall workaround
+    - LP: #540231
+  * net/via-rhine: Fix scheduling while atomic bugs
+    - LP: #540231
+  * clocksource: Fix up a registration/IRQ race in the sh drivers.
+    - LP: #540231
+  * SCSI: qla1280: Drop host_lock while requesting firmware
+    - LP: #540231
+  * Staging: hv: add a pci device table
+    - LP: #540231
+  * Staging: hv: match on DMI values to know if we should run.
+    - LP: #540231
+  * Staging: mimio: remove the mimio driver
+    - LP: #540231
+  * dvb-core: Fix DoS bug in ULE decapsulation code that can be triggered
+    by an invalid Payload Pointer
+    - LP: #540231
+  * V4L/DVB (13148): uvcvideo: Handle V4L2_CTRL_TYPE_BUTTON control type in
+    VIDIOC_QUERYCTRL
+    - LP: #540231
+  * PM / Hibernate: Fix preallocating of memory
+    - LP: #540231
+  * macintosh/therm_adt746x: Fix sysfs attributes lifetime
+    - LP: #540231
+  * macintosh/hwmon/ams: Fix device removal sequence
+    - LP: #540231
+  * oprofile/x86: fix perfctr nmi reservation for mulitplexing
+    - LP: #540231
+  * oprofile: remove tracing build dependency
+    - LP: #540231
+  * oprofile/x86: remove node check in AMD IBS initialization
+    - LP: #540231
+  * oprofile/x86: use kzalloc() instead of kmalloc()
+    - LP: #540231
+  * oprofile/x86: fix msr access to reserved counters
+    - LP: #540231
+  * ALSA: hda: Use 3stack quirk for Toshiba Satellite L40-10Q
+    - LP: #524948, #540231
+  * ALSA: via82xx: add quirk for D1289 motherboard
+    - LP: #540231
+  * ALSA: pcm core - fix fifo_size channels interval check
+    - LP: #540231
+  * ALSA: USB MIDI support for Access Music VirusTI
+    - LP: #540231
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #540231
+  * ALSA: hda: Use LPIB for a Biostar Microtech board
+    - LP: #523953, #540231
+  * ALSA: hda - Add a position_fix quirk for MSI Wind U115
+    - LP: #540231
+  * ALSA: hda - Add position_fix quirk for HP dv3
+    - LP: #540231
+  * ALSA: hda-intel: Add position_fix quirk for ASUS M2V-MX SE.
+    - LP: #540231
+  * ASoC: fix ak4104 register array access
+    - LP: #540231
+  * driver-core: fix race condition in get_device_parent()
+    - LP: #540231
+  * Driver-Core: devtmpfs - reset inode permissions before unlinking
+    - LP: #540231
+  * tty: Fix the ldisc hangup race
+    - LP: #540231
+  * serial: imx: fix NULL dereference Oops when pdata == NULL
+    - LP: #540231
+  * USB: serial: sierra driver indat_callback fix
+    - LP: #511157, #540231
+  * USB: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor
+    USB20SVGA-MB-PLUS
+    - LP: #540231
+  * USB: fix I2C API usage in ohci-pnx4008.
+    - LP: #540231
+  * p54usb: Add the USB ID for Belkin (Accton) FD7050E ver 1010ec
+    - LP: #540231
+  * p54pci: handle dma mapping errors
+    - LP: #540231
+  * gpiolib: Actually set output state in wm831x_gpio_direction_output()
+    - LP: #540231
+  * hwmon: (tmp421) Fix temperature conversions
+    - LP: #540231
+  * hwmon: (tmp421) Restore missing inputs
+    - LP: #540231
+  * pata_hpt3x2n: always stretch UltraDMA timing
+    - LP: #540231
+  * scm: Only support SCM_RIGHTS on unix domain sockets.
+    - LP: #540231
+  * ath9k: fix beacon timer restart after a card reset
+    - LP: #540231
+  * ath9k: fix rate control fallback rate selection
+    - LP: #540231
+  * ath9k: disable RIFS search for AR91xx based chips
+    - LP: #540231
+  * ath5k: use correct packet type when transmitting
+    - LP: #540231
+  * b43/b43legacy: Wake queues in wireless_core_start
+    - LP: #540231
+  * netfilter: xt_recent: fix buffer overflow
+    - LP: #540231
+  * netfilter: xt_recent: fix false match
+    - LP: #540231
+  * sunxvr500: Additional PCI id for sunxvr500 driver
+    - LP: #540231
+  * thinkpad-acpi: fix poll thread auto-start
+    - LP: #540231
+  * thinkpad-acpi: R52 brightness_mode has been confirmed
+    - LP: #540231
+  * thinkpad-acpi: document HKEY event 3006
+    - LP: #540231
+  * thinkpad-acpi: make driver events work in NVRAM poll mode
+    - LP: #540231
+  * thinkpad-acpi: fix bluetooth/wwan resume
+    - LP: #540231
+  * ocfs2: Only bug out in direct io write for reflinked extent.
+    - LP: #540231
+  * x86, ia32_aout: do not kill argument mapping
+    - LP: #540231
+  * x86: Add iMac9,1 to pci_reboot_dmi_table
+    - LP: #540231
+  * x86, xen: Disable highmem PTE allocation even when CONFIG_HIGHPTE=y
+    - LP: #540231
+  * x86: Avoid race condition in pci_enable_msix()
+    - LP: #540231
+  * x86: Fix SCI on IOAPIC != 0
+    - LP: #540231
+  * USB: xhci: Fix finding extended capabilities registers
+    - LP: #540231
+  * USB: fix the idProduct value for USB-3.0 root hubs
+    - LP: #540231
+  * USB: fix crash in uhci_scan_schedule
+    - LP: #540231
+  * USB: remove debugging message for uevent constructions
+    - LP: #540231
+  * USB: Move hcd free_dev call into usb_disconnect to fix oops
+    - LP: #540231
+  * USB: ftdi_sio: isolate all device IDs to new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: sort PID/VID entries in new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: new device id for papouch AD4USB
+    - LP: #540231
+  * USB: ftdi_sio: add device IDs (several ELV, one Mindstorms NXT)
+    - LP: #540231
+  * USB: add new ftdi_sio device ids
+    - LP: #540231
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #540231
+  * USB: cp210x: Add 81E8 (Zephyr Bioharness)
+    - LP: #540231
+  * USB: unusual_devs: Add support for multiple Option 3G sticks
+    - LP: #540231
+  * sunrpc: remove unnecessary svc_xprt_put
+    - LP: #540231
+  * SUNRPC: Handle EINVAL error returns from the TCP connect operation
+    - LP: #540231
+  * s3cmci: s3cmci_card_present: Use no_detect to decide whether there is a
+    card detect pin
+    - LP: #540231
+  * rtc-coh901331: fix braces in resume code
+    - LP: #540231
+  * NFS: Fix an allocation-under-spinlock bug
+    - LP: #540231
+  * dm: free dm_io before bio_endio not after
+    - LP: #540231
+  * KVM: x86 emulator: Add group8 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Forbid modifying CS segment register by mov
+    instruction
+    - LP: #540231
+  * KVM: x86 emulator: Add group9 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - LP: #540231
+  * sched: Fix sched_mv_power_savings for !SMT
+    - LP: #540231
+  * sched: Fix SMT scheduler regression in find_busiest_queue()
+    - LP: #540231
+  * sched: Don't use possibly stale sched_class
+    - LP: #540231
+  * x86, mm: Allow highmem user page tables to be disabled at boot time
+    - LP: #540231
+  * Linux 2.6.32.10
+    - LP: #540231
+  * drm/i915: give up on 8xx lid status
+    - LP: #540231
+  * drm/i915: Use a dmi quirk to skip a broken SDVO TV output.
+    - LP: #540231
+  * drm/ttm: handle OOM in ttm_tt_swapout
+    - LP: #540231
+  * drm/radeon/kms/atom: fix shr/shl ops
+    - LP: #540231
+  * Linux 2.6.32.10+drm33.1
+    - LP: #540231
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 31 Mar 2010 20:09:01 +0100
+
+linux-ec2 (2.6.32-303.7) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * sync with master abstraction cleanup
+  * rebase to Ubuntu-2.6.32-12.17
+  * [Config] fix MMAP_MIN_ADDR/DEV_KMEM/USB_DEVICEFS
+  * rebase to Ubuntu-2.6.32-15.22
+  * [Config] update configs following rebase to Ubuntu-2.6.32-15.22
+  * SAUCE: XEN -- drop references to TIF_ABI_PENDING
+  * [Config] updateconfigs following rebase to Ubuntu-2.6.32-15.22
+  * rename the debug packages to match archive standard
+    - LP: #527837
+  * [Config] cpu_debug module is no longer built
+  * updateconfigs following rebase to Ubuntu-2.6.32-16.24
+  * lintian -- update debhelper package version dependancy
+  * lintian -- fix ghostscript dependancy
+  * lintian -- add required misc:Depends
+  * update to standards version 3.8.4.0
+  * linux-tools -- disable linux-tools generation
+  * rebase to Ubuntu-2.6.32-16.25
+  * d-i -- do not generate any udebs
+  * disable linux-libc-dev for ec2
+
+  [ John Johansen ]
+
+  * rebase to Ubuntu-2.6.32-16.24
+
+  [ Upstream Kernel Changes ]
+
+  * Linux 2.6.32.4
+
+  [ Ubuntu: 2.6.32-16.25 ]
+
+  * linux-tools -- move to Suggests: with explicit seeding
+    - LP: #534635
+  * [Config] CONFIG_HID=m
+  * (pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()
+  * KVM: introduce kvm_vcpu_on_spin
+  * KVM: VMX: Add support for Pause-Loop Exiting
+
+  [ Ubuntu: 2.6.32-16.24 ]
+
+  * armel -- perf userspace does not support arm
+  * ia64 -- libelf-dev/binutils-dev to not provide necessary libraries
+
+  [ Ubuntu: 2.6.32-16.23 ]
+
+  * SAUCE: PM report driver and device suspend/resume times -- move config
+  * update to standards version 3.8.4.0
+  * printenv -- expose all of the package selectors
+  * source package -- cleanup source content control
+  * doc package -- ensure we do build package content on buildd
+  * lintian -- correct the address in the debian/copyright
+  * lintian -- update debhelper package version dependancy
+  * lintian -- fix ghostscript dependancy
+  * lintian -- add required misc:Depends
+  * lintian -- move our debhelper compat level to debian/compat
+  * perf -- build the kernel carried tools
+  * perf -- add linux-tools carrying the version switches and manuals
+  * SAUCE: fix up Kconfig for staging drivers
+  * [Config] enable NOUVEAU etc following drm backport
+  * update DRM to mainline v2.6.33
+  * [Config] Remove AppArmor config options that no longer exist (ports)
+  * [Config] updateportsconfigs following drm update
+  * ubuntu: AppArmor -- update to mainline 2010-03-04
+  * SAUCE: AppArmor: Reintroduce AppArmor 2.4 compatibility
+  * SAUCE: AppArmor: replace strim with strstrip for 2.6.32 kernels
+  * [Config] Remove AppArmor config options that no longer exist
+  * ubuntu: rtl8192se -- version 2010-0115,0014
+    - LP: #530275
+  * [Config] added CONFIG_RTL8192SE module.
+    - LP: #530275
+  * [Config] Added vmw_pvscsi to d-i/scsi-modules
+    - LP: #531017
+  * [Upstream] netfilter: xt_recent: Add an entry reaper
+  * Revert "KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Fix popf emulation"
+  * Revert "KVM: x86 emulator: Check IOPL level during io instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Add Virtual-8086 mode of emulation"
+  * Revert "KVM: fix memory access during x86 emulation."
+  * Add vlan (8021.Q) module package for d-i.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+  * [Upstream] docbook: need xmldoclinks for all doc types
+  * x86: set_personality_ia32() misses force_personality32
+  * lib: Introduce generic list_sort function
+  * drm/nv50: Implement ctxprog/state generation.
+  * drm/nv50: Remove redundant/incorrect ctxvals initialisation.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+
+  [ Ubuntu: 2.6.32-15.22 ]
+
+  * Revert "[Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT"
+  * Revert "SAUCE: PM report driver and device suspend/resume times."
+  * [Config] set CONFIG_SR_REPORT_TIME_LIMIT
+  * SAUCE: PM report driver and device suspend/resume times.
+
+  [ Ubuntu: 2.6.32-15.21 ]
+
+  * Revert "(pre-stable) drm/i915: Increase fb alignment to 64k"
+  * Revert "[Config] lenovo-sl-laptop -- enable"
+  * Revert "ubuntu: lenovo-sl-laptop -- git tip (b19a08f81f)"
+  * armel -- cramfs module will no longer be built
+  * d-i -- make all modules optional
+  * rename the debug packages to match archive standard
+    - LP: #527837
+  * lenovo-sl-laptop is no longer built
+  * Disable 4MB page tables for Atom, work around errata AAE44
+    - LP: #523112
+  * ubuntu: dm-raid4-5: Depend on XOR_BLOCKS
+  * ubuntu: fsam7400: Depend on CHECK_SIGNATURE
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+  * [Config] armel Update versatile initrd configs
+    - LP: #524893
+  * SAUCE: [um] Don't use nx_enabled under UML
+    - LP: #524849
+  * [Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT
+  * SAUCE: v3 - Add Dell Business Class Netbook LED driver
+  * SAUCE: PM report driver and device suspend/resume times.
+  * Revert "[Upstream] e1000e: enhance frame fragment detection"
+    - CVE-2009-4538
+  * Revert "[Upstream] e1000: enhance frame fragment detection"
+    - CVE-2009-4536
+  * [Config] Enabled CONFIG_LEDS_DELL_NETBOOKS=m
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix false match
+  * Revert "(pre-stable) eCryptfs: Add getattr function"
+  * Fix potential crash with sys_move_pages
+  * futex_lock_pi() key refcnt fix
+  * futex: Handle user space corruption gracefully
+  * futex: Handle futex value corruption gracefully
+  * Fix race in tty_fasync() properly
+  * hwmon: (w83781d) Request I/O ports individually for probing
+  * hwmon: (lm78) Request I/O ports individually for probing
+  * hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT
+  * ALSA: ctxfi - fix PTP address initialization
+  * drm/i915: disable hotplug detect before Ironlake CRT detect
+  * drm/i915: enable self-refresh on 965
+  * drm/i915: Disable SR when more than one pipe is enabled
+  * drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.
+  * drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list
+  * drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop
+  * drm/i915: Add MALATA PC-81005 to ACPI LID quirk list
+  * usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers.
+  * i2c-tiny-usb: Fix on big-endian systems
+  * drm/i915: handle FBC and self-refresh better
+  * drm/i915: Increase fb alignment to 64k
+  * drm/i915: Update write_domains on active list after flush.
+  * regulator: Fix display of null constraints for regulators
+  * ALSA: hda-intel: Avoid divide by zero crash
+  * CPUFREQ: Fix use after free of struct powernow_k8_data
+  * freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb
+  * cciss: Make cciss_seq_show handle holes in the h->drv[] array
+  * ioat: fix infinite timeout checking in ioat2_quiesce
+  * resource: add helpers for fetching rlimits
+  * fs/exec.c: restrict initial stack space expansion to rlimit
+  * cifs: fix length calculation for converted unicode readdir names
+  * NFS: Fix a reference leak in nfs_wb_cancel_page()
+  * NFS: Try to commit unstable writes in nfs_release_page()
+  * NFSv4: Don't allow posix locking against servers that don't support it
+  * NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
+  * NFS: Fix an Oops when truncating a file
+  * NFS: Fix a umount race
+  * NFS: Fix a bug in nfs_fscache_release_page()
+  * NFS: Fix the mapping of the NFSERR_SERVERFAULT error
+  * md: fix 'degraded' calculation when starting a reshape.
+  * V4L/DVB: dvb-core: fix initialization of feeds list in demux filter
+  * Export the symbol of getboottime and mmonotonic_to_bootbased
+  * kvmclock: count total_sleep_time when updating guest clock
+  * KVM: PIT: control word is write-only
+  * tpm_infineon: fix suspend/resume handler for pnp_driver
+  * amd64_edac: Do not falsely trigger kerneloops
+  * netfilter: nf_conntrack: fix memory corruption with multiple namespaces
+  * netfilter: nf_conntrack: per netns nf_conntrack_cachep
+  * netfilter: nf_conntrack: restrict runtime expect hashsize modifications
+  * netfilter: xtables: compat out of scope fix
+  * netfilter: nf_conntrack: fix hash resizing with namespaces
+  * drm/i915: remove full registers dump debug
+  * drm/i915: add i915_lp_ring_sync helper
+  * drm/i915: Don't wait interruptible for possible plane buffer flush
+  * dasd: remove strings from s390dbf
+  * crypto: padlock-sha - Add import/export support
+  * wmi: Free the allocated acpi objects through wmi_get_event_data
+  * dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value
+  * /dev/mem: introduce size_inside_page()
+  * devmem: check vmalloc address on kmem read/write
+  * devmem: fix kmem write bug on memory holes
+  * SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead
+    of value 0.
+  * sh: Couple kernel and user write page perm bits for CONFIG_X2TLB
+  * ALSA: hda - use WARN_ON_ONCE() for zero-division detection
+  * dst: call cond_resched() in dst_gc_task()
+  * ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support
+  * befs: fix leak
+  * rtc-fm3130: add missing braces
+  * Call flush_dcache_page after PIO data transfers in libata-sff.c
+  * ahci: add Acer G725 to broken suspend list
+  * pktgen: Fix freezing problem
+  * x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt
+  * x86/amd-iommu: Fix deassignment of a device from the pt_domain
+  * x86: Re-get cfg_new in case reuse/move irq_desc
+  * Staging: fix rtl8187se compilation errors with mac80211
+  * ALSA: usb-audio - Avoid Oops after disconnect
+  * serial: 8250: add serial transmitter fully empty test
+  * sysfs: sysfs_sd_setattr set iattrs unconditionally
+  * class: Free the class private data in class_release
+  * USB: usbfs: only copy the actual data received
+  * USB: usbfs: properly clean up the as structure on error paths
+  * rtl8187: Add new device ID
+  * ACPI: Add NULL pointer check in acpi_bus_start
+  * ACPI: fix High cpu temperature with 2.6.32
+  * drm/radeon/kms: use udelay for short delays
+  * NFS: Too many GETATTR and ACCESS calls after direct I/O
+  * eCryptfs: Add getattr function
+  * b43: Fix throughput regression
+  * ath9k: Fix sequence numbers for PAE frames
+  * mac80211: Fix probe request filtering in IBSS mode
+  * iwlwifi: Fix to set correct ht configuration
+  * dm stripe: avoid divide by zero with invalid stripe count
+  * dm log: userspace fix overhead_size calcuations
+  * Linux 2.6.32.9
+  * sfc: Fix SFE4002 initialisation
+  * sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
+  * sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances
+  * (pre-stable) HID: handle joysticks with large number of buttons
+    - LP: #492056
+  * (pre-stable) HID: extend mask for BUTTON usage page
+    - LP: #492056
+  * PM: Measure device suspend and resume times
+  * e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+  * KVM: fix memory access during x86 emulation.
+    - CVE-2010-0306
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Fix popf emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - CVE-2010-0306
+  * Input: wacom - ensure the device is initialized properly upon resume
+  * Input: wacom - add defines for packet lengths of various devices
+  * Input: wacom - add support for new LCD tablets
+    - LP: #516777
+
+  [ Ubuntu: 2.6.32-14.20 ]
+
+  * rebuild following the GCC update to match compiler for out of tree modules
+  * Revert "[Config] drbd -- enable"
+  * Revert "ubuntu: drbd -- version 8.3.1"
+  * SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU
+    - LP: #510937
+
+  [ Ubuntu: 2.6.32-14.19 ]
+
+  * ensure we build the source package contents when enabled
+    - LP: #522308
+  * [Config] enable CONFIG_X86_MCE_XEON75XX
+  * SAUCE: AppArmor -- add linux/kref.h for struct kref
+  * [Config] enable CONFIG_HID_ORTEK
+  * enable udeb generation for arm versatile flavour
+    - LP: #522515
+  * ubuntu: AppArmor -- update to mainline 2010-02-18
+    - LP: #439560, #496110, #507069
+  * SAUCE: HID: add support for Ortek WKB-2000
+    - LP: #405390
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #490487
+  * x86, mce: Xeon75xx specific interface to get corrected memory error
+    information
+  * x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll
+  * x86, mce: Make xeon75xx memory driver dependent on PCI
+  * drm/edid: Unify detailed block parsing between base and extension
+    blocks
+    - LP: #500999
+  * (pre-stable) eCryptfs: Add getattr function
+    - LP: #390833
+
+  [ Ubuntu: 2.6.32-13.18 ]
+
+  * Revert "enforcer -- make the enforcement configuration common"
+  * Revert "(pre-stable) Input: ALPS - add interleaved protocol support
+    (Dell E6x00 series)"
+  * Revert "(pre-stable) driver-core: fix devtmpfs crash on s390"
+  * Revert "(pre-stable) Driver-Core: devtmpfs - set root directory mode to
+    0755"
+  * Revert "SAUCE: Adds support for COMPAL JHL90 webcam"
+  * Revert "SAUCE: fix kernel oops in VirtualBox during paravirt patching"
+  * Revert "SAUCE: make fc transport removal of target configurable"
+  * enforcer -- make the enforcement configuration common
+  * getabis -- add preempt flavour to the list
+  * [Config] enforce DEVTMPFS options
+  * [Config] armel -- cleanup to-be builtin modules
+  * [Config] cleanup ports configs
+  * [Config] enable CRYPTO_GHASH_CLMUL_NI_INTEL
+    - LP: #485536
+  * add printdebian target to find branch target
+  * distclean -- do not remove debian.env
+  * [Config] generic-pae switch to M586TSC
+    - LP: #519448
+  * git-ubuntu-log -- commonise duplicated log handling
+  * git-ubuntu-log -- tighten up Bug: NNNN matching
+  * git-ubuntu-log -- sort the bug numbers
+  * (pre-stable) drm/i915: Increase fb alignment to 64k
+    - LP: #404064
+  * arm -- enable ubuntu/ directory
+  * SAUCE: crypto: ghash - Add PCLMULQDQ accelerated implementation
+  * SAUCE: crypto: ghash-intel - Fix building failure on x86_32
+  * [Config] cleanup preempt configuration
+  * [Config] versatile: Fix video output
+    - LP: #517594
+  * [Config] armel DEFAULT_MMAP_MIN_ADDR=32768
+  * [Config] Large update to armel/versatile
+  * [Config] versatile: Add RTC support
+  * [Config] armel: Enable NEON
+  * [Config] versatile: Builtin MMC support
+  * [Config] versatile Builtin SCSI controller
+  * [Config] armel Disable dma_cache_sync callers
+  * [Config] armel Disable asm/time.h users
+  * [Config] armel Disable out of range udelay()
+  * [Config] armel Disable flush_cache_range() users
+  * [Config] armel -- Enable ubuntu/ drivers
+  * SAUCE: drm/i915: Add display hotplug event on Ironlake
+  * SAUCE: drm/i915: Add ACPI OpRegion support for Ironlake
+  * Revert "[Upstream]: oprofile/x86: add Xeon 7500 series support"
+  * Revert "Revert "[Bluetooth] Eliminate checks for impossible conditions
+    in IRQ handler""
+  * clockevent: Don't remove broadcast device when cpu is dead
+  * clockevents: Add missing include to pacify sparse
+  * ACPI: don't cond_resched if irq is disabled
+  * be2net: Add support for next generation of BladeEngine device.
+  * be2net: Add the new PCI IDs to PCI_DEVICE_TABLE.
+  * mpt2sas: New device SAS2208 support is added
+  * ar9170: Add support for D-Link DWA 160 A2
+  * powerpc/fsl: Add PCI device ids for new QoirQ chips
+  * davinci: dm646x: Add support for 3.x silicon revision
+  * Input: ALPS - add interleaved protocol support (Dell E6x00 series)
+  * Driver-Core: devtmpfs - set root directory mode to 0755
+  * driver-core: fix devtmpfs crash on s390
+  * vfs: get_sb_single() - do not pass options twice
+  * ALSA: hda - Add PCI IDs for Nvidia G2xx-series
+  * V4L/DVB (13569): smsusb: add autodetection support for five additional
+    Hauppauge USB IDs
+  * USB: mos7840: add device IDs for B&B electronics devices
+  * USB: ftdi_sio: add USB device ID's for B&B Electronics line
+  * V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134
+    SubVendor ID: 0x1043 Device ID: 0x4847)
+  * iTCO_wdt: Add support for Intel Ibex Peak
+  * atl1c:use common_task instead of reset_task and link_chg_task
+  * atl1e:disable NETIF_F_TSO6 for hardware limit
+  * V4L/DVB (13680a): DocBook/media: copy images after building HTML
+  * V4L/DVB (13680b): DocBook/media: create links for included sources
+  * netfilter: xtables: fix conntrack match v1 ipt-save output
+  * partitions: read whole sector with EFI GPT header
+  * partitions: use sector size for EFI GPT
+  * ALSA: ice1724 - Patch for suspend/resume for ESI Juli@
+  * sched: Fix isolcpus boot option
+  * sched: Fix missing sched tunable recalculation on cpu add/remove
+  * nohz: Prevent clocksource wrapping during idle
+  * nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups
+  * timers, init: Limit the number of per cpu calibration bootup messages
+  * PCI: Always set prefetchable base/limit upper32 registers
+  * iscsi class: modify handling of replacement timeout
+  * NFS: Revert default r/wsize behavior
+  * HID: fixup quirk for NCR devices
+  * scsi_devinfo: update Hitachi entries (v2)
+  * scsi_dh: create sysfs file, dh_state for all SCSI disk devices
+  * scsi_transport_fc: remove invalid BUG_ON
+  * lpfc: fix hang on SGI ia64 platform
+  * libfc: fix typo in retry check on received PRLI
+  * libfc: fix ddp in fc_fcp for 0 xid
+  * fcoe: remove redundant checking of netdev->netdev_ops
+  * libfc: Fix wrong scsi return status under FC_DATA_UNDRUN
+  * libfc: lport: fix minor documentation errors
+  * libfc: don't WARN_ON in lport_timeout for RESET state
+  * fcoe: initialize return value in fcoe_destroy
+  * libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data
+  * libfc: fix memory corruption caused by double frees and bad error
+    handling
+  * libfc: fix free of fc_rport_priv with timer pending
+  * libfc: remote port gets stuck in restart state without really
+    restarting
+  * fcoe, libfc: fix an libfc issue with queue ramp down in libfc
+  * fcoe: Fix checking san mac address
+  * fcoe: Fix getting san mac for VLAN interface
+  * qlge: Remove explicit setting of PCI Dev CTL reg.
+  * qlge: Set PCIE max read request size.
+  * qlge: Don't fail open when port is not initialized.
+  * qlge: Add handler for DCBX firmware event.
+  * qlge: Bonding fix for mode 6.
+  * PCI: AER: fix aer inject result in kernel oops
+  * DMI: allow omitting ident strings in DMI tables
+  * Input: i8042 - remove identification strings from DMI tables
+  * Input: i8042 - add Gigabyte M1022M to the noloop list
+  * Input: i8042 - add Dritek quirk for Acer Aspire 5610.
+  * ALSA: hda - select IbexPeak handler for Calpella
+  * ALSA: hda - Fix quirk for Maxdata obook4-1
+  * ALSA: hda - Add missing Line-Out and PCM switches as slave
+  * iTCO_wdt.c - cleanup chipset documentation
+  * iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC
+  * iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs
+  * ahci: disable SNotification capability for ich8
+  * ata_piix: fix MWDMA handling on PIIX3
+  * md: fix small irregularity with start_ro module parameter
+  * V4L/DVB (13826): uvcvideo: Fix controls blacklisting
+  * cio: fix double free in case of probe failure
+  * cio: dont panic in non-fatal conditions
+  * netiucv: displayed TX bytes value much too high
+  * ipc ns: fix memory leak (idr)
+  * ALSA: hda - Fix HP T5735 automute
+  * hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog
+  * UBI: fix memory leak in update path
+  * UBI: initialise update marker
+  * ASoC: fix a memory-leak in wm8903
+  * mac80211: check that ieee80211_set_power_mgmt only handles STA
+    interfaces.
+  * cfg80211: fix channel setting for wext
+  * KVM: S390: fix potential array overrun in intercept handling
+  * KVM: only allow one gsi per fd
+  * KVM: Fix race between APIC TMR and IRR
+  * KVM: MMU: bail out pagewalk on kvm_read_guest error
+  * KVM: x86: Fix host_mapping_level()
+  * KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks
+  * KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init()
+  * KVM: fix lock imbalance in kvm_*_irq_source_id()
+  * KVM: only clear irq_source_id if irqchip is present
+  * IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc()
+  * x86: Reenable TSC sync check at boot, even with NONSTOP_TSC
+  * ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
+    - LP: #516325
+  * iwlwifi: Fix throughput stall issue in HT mode for 5000
+  * fnctl: f_modown should call write_lock_irqsave/restore
+  * x86, msr/cpuid: Pass the number of minors when unregistering MSR and
+    CPUID drivers.
+  * Linux 2.6.32.7
+  * scsi_lib: Fix bug in completion of bidi commands
+  * mptsas: Fix issue with chain pools allocation on katmai
+  * mm: add new 'read_cache_page_gfp()' helper function
+  * drm/i915: Selectively enable self-reclaim
+  * firewire: ohci: fix crashes with TSB43AB23 on 64bit systems
+  * S390: fix single stepped svcs with TRACE_IRQFLAGS=y
+  * x86: Set hotpluggable nodes in nodes_possible_map
+  * x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG)
+  * libata: retry FS IOs even if it has failed with AC_ERR_INVALID
+  * zcrypt: Do not remove coprocessor for error 8/72
+  * dasd: fix possible NULL pointer errors
+  * ACPI: Add a generic API for _OSC -v2
+  * ACPI: Add platform-wide _OSC support.
+  * ACPI: fix OSC regression that caused aer and pciehp not to load
+  * ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes
+  * UBI: fix volume creation input checking
+  * e1000/e1000e: don't use small hardware rx buffers
+  * drm/i915: Reload hangcheck timer too for Ironlake
+  * Fix a leak in affs_fill_super()
+  * Fix failure exits in bfs_fill_super()
+  * fix oops in fs/9p late mount failure
+  * fix leak in romfs_fill_super()
+  * Fix remount races with symlink handling in affs
+  * fix affs parse_options()
+  * Fix failure exit in ipathfs
+  * mm: fix migratetype bug which slowed swapping
+  * FDPIC: Respect PT_GNU_STACK exec protection markings when creating
+    NOMMU stack
+  * Split 'flush_old_exec' into two functions
+  * sparc: TIF_ABI_PENDING bit removal
+  * x86: get rid of the insane TIF_ABI_PENDING bit
+  * Input: winbond-cir - remove dmesg spam
+  * x86: Disable HPET MSI on ATI SB700/SB800
+  * iwlwifi: set default aggregation frame count limit to 31
+  * drm/i915: only enable hotplug for detected outputs
+  * firewire: core: add_descriptor size check
+  * SECURITY: selinux, fix update_rlimit_cpu parameter
+  * regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints
+  * x86: Add Dell OptiPlex 760 reboot quirk
+    - LP: #488319
+  * x86: Add quirk for Intel DG45FC board to avoid low memory corruption
+  * x86/amd-iommu: Fix possible integer overflow
+  * clocksource: fix compilation if no GENERIC_TIME
+  * tcp: update the netstamp_needed counter when cloning sockets
+  * sky2: Fix oops in sky2_xmit_frame() after TX timeout
+  * net: restore ip source validation
+  * af_packet: Don't use skb after dev_queue_xmit()
+  * ax25: netrom: rose: Fix timer oopses
+  * KVM: allow userspace to adjust kvmclock offset
+  * oprofile/x86: add Xeon 7500 series support
+  * oprofile/x86: fix crash when profiling more than 28 events
+  * libata: retry link resume if necessary
+  * mm: percpu-vmap fix RCU list walking
+  * mm: purge fragmented percpu vmap blocks
+  * block: fix bio_add_page for non trivial merge_bvec_fn case
+  * Fix 'flush_old_exec()/setup_new_exec()' split
+  * random: drop weird m_time/a_time manipulation
+  * random: Remove unused inode variable
+  * block: fix bugs in bio-integrity mempool usage
+  * usb: r8a66597-hdc disable interrupts fix
+  * connector: Delete buggy notification code.
+  * be2net: Bug fix to support newer generation of BE ASIC
+  * be2net: Fix memset() arg ordering.
+  * mm: flush dcache before writing into page to avoid alias
+  * mac80211: fix NULL pointer dereference when ftrace is enabled
+  * imxfb: correct location of callbacks in suspend and resume
+  * mx3fb: some debug and initialisation fixes
+  * starfire: clean up properly if firmware loading fails
+  * kernel/cred.c: use kmem_cache_free
+  * uartlite: fix crash when using as console
+  * pktcdvd: removing device does not remove its sysfs dir
+  * ath9k: fix eeprom INI values override for 2GHz-only cards
+  * ath9k: fix beacon slot/buffer leak
+  * powerpc: TIF_ABI_PENDING bit removal
+  * NET: fix oops at bootime in sysctl code
+  * Linux 2.6.32.8
+
+  [ Ubuntu: 2.6.32-12.17 ]
+
+  * restore linux-image prefix -- master
+  * enforce -- we require SELINUX enabled -- master
+  * enforce -- ensure APPARMOR is our default LSM -- master
+  * make doc package completely optional -- master
+  * make source package completely optional -- master
+  * make linux-libc-dev completly optional -- master
+  * convert package disable to a deps list -- master
+  * allow common headers to switch from indep to arch -- master
+  * convert binary package disable to a deps list -- master
+  * add configuration option for a full source build tree -- master
+  * add support for uImage kernels in package control scripts
+  * getabis -- cleanup and parameterise repository list -- master
+  * getabis -- move configuration to etc/getabi -- master
+  * kernelconfig -- move configuration to etc -- master
+  * rules -- make debian/debian.env master for branch name
+  * set the current branch name -- master
+  * pull back common debian.master files into debian -- master
+  * enforcer -- make the enforcement configuration common
+  * insert-changes -- correctly link to debian/rules in DROOT
+  * future-proof ddeb handling against buildd changes
+  * SAUCE: Make CONFIG_{OMNIBOOK, AVERATEC_5100P, PACKARDBELL_E5} depend on
+    X86
+  * Add modules.builtin.bin to prerm rm list
+    - LP: #516584
+  * [Config] Implement the amd64 preempt flavour
+  * syslog: distinguish between /proc/kmsg and syscalls
+    - LP: #515623
+  * sfc: Fix polling for slow MCDI operations
+  * sfc: Fix conditions for MDIO self-test
+  * sfc: QT202x: Remove unreliable MMD check at initialisation
+  * sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer
+  * sfc: Use fixed-size buffers for MCDI NVRAM requests
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 09 Mar 2010 16:09:44 +0000
+
+linux-ec2 (2.6.32-302.6) lucid; urgency=low
+
+  [ John Johansen ]
+
+  * rebase to Ubuntu-2.6.32-11.15
+  * import raw xen patchset
+  * import series file for the xen patchset
+  * rebase to Ubuntu-2.6.32-12.16
+  * [Config] update ec2 configs to make them closer to -server flavor
+    - LP: #510130
+
+  [ Ubuntu: 2.6.32-12.16 ]
+
+  * Revert "SAUCE: acpi battery -- delay first lookup of the battery until
+    first use"
+  * SAUCE: acpi battery -- move first lookup asynchronous
+    - LP: #507211
+  * [Config] update configs to cleanup generic configs
+  * [Config] disable CONFIG_X86_CPU_DEBUG for amd64
+  * [Config] enable USER_NS
+    - LP: #480739, #509808
+  * (pre-stable) driver-core: fix devtmpfs crash on s390
+    - LP: #512370
+  * [Config] for server and virtual flavours make CONFIG_SCSI_SYM53C8XX_2=y
+    - LP: #494565
+  * [Config] VIRTIO=y for server/virtual flavours
+    - LP: #494565
+  * (pre-stable) Driver-Core: devtmpfs - set root directory mode to 0755
+    - LP: #512370
+  * SAUCE: x86: brk away from exec rand area
+    - LP: #452175
+  * [Upstream] e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * [Upstream] e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+  * (pre-stable) Input: ALPS - add interleaved protocol support (Dell E6x00
+    series)
+    - LP: #296610
+  * inotify: do not reuse watch descriptors
+    - LP: #485556
+  * inotify: only warn once for inotify problems
+  * revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC
+    Framebuffer"
+  * memcg: ensure list is empty at rmdir
+  * drm/i915: remove loop in Ironlake interrupt handler
+  * block: Fix incorrect reporting of partition alignment
+  * x86, mce: Thermal monitoring depends on APIC being enabled
+  * futexes: Remove rw parameter from get_futex_key()
+  * page allocator: update NR_FREE_PAGES only when necessary
+  * x86, apic: use physical mode for IBM summit platforms
+  * edac: i5000_edac critical fix panic out of bounds
+  * x86: SGI UV: Fix mapping of MMIO registers
+  * mfd: WM835x GPIO direction register is not locked
+  * mfd: Correct WM835x ISINK ramp time defines
+  * ALSA: hda - Fix missing capture mixer for ALC861/660 codecs
+  * V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned.
+  * reiserfs: truncate blocks not used by a write
+  * HID: add device IDs for new model of Apple Wireless Keyboard
+  * PCI/cardbus: Add a fixup hook and fix powerpc
+  * Input: pmouse - move Sentelic probe down the list
+  * asus-laptop: add Lenovo SL hotkey support
+  * sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
+  * sparc64: Fix NMI programming when perf events are active.
+  * sparc64: Fix Niagara2 perf event handling.
+  * i2c: Do not use device name after device_unregister
+  * i2c/pca: Don't use *_interruptible
+  * serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device
+  * sched: Fix task priority bug
+  * vfs: Fix vmtruncate() regression
+  * Linux 2.6.32.5
+  * x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers
+  * V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges.
+  * Staging: asus_oled: fix oops in 2.6.32.2
+  * Staging: hv: fix smp problems in the hyperv core code
+  * tty: fix race in tty_fasync
+  * ecryptfs: use after free
+  * ecryptfs: initialize private persistent file before dereferencing
+    pointer
+  * nozomi: quick fix for the close/close bug
+  * serial: 8250_pnp: use wildcard for serial Wacom tablets
+  * usb: serial: fix memory leak in generic driver
+  * USB: fix bitmask merge error
+  * USB: Don't use GFP_KERNEL while we cannot reset a storage device
+  * USB: EHCI: fix handling of unusual interrupt intervals
+  * USB: EHCI & UHCI: fix race between root-hub suspend and port resume
+  * USB: add missing delay during remote wakeup
+  * USB: add speed values for USB 3.0 and wireless controllers
+  * ACPI: EC: Accelerate query execution
+  * ACPI: EC: Add wait for irq storm
+  * SCSI: enclosure: fix oops while iterating enclosure_status array
+  * drm/i915: Read the response after issuing DDC bus switch command
+  * drm/i915: try another possible DDC bus for the SDVO device with
+    multiple outputs
+  * block: bdev_stack_limits wrapper
+  * DM: Fix device mapper topology stacking
+  * x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled
+  * USB: fix usbstorage for 2770:915d delivers no FAT
+  * vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE
+  * perf timechart: Use tid not pid for COMM change
+  * perf events: Dont report side-band events on each cpu for
+    per-task-per-cpu events
+  * perf: Honour event state for aux stream data
+  * Linux 2.6.32.6
+
+  [ Ubuntu: 2.6.32-11.15 ]
+
+  * Revert "(pre-stable) drm/radeon/kms: fix crtc vblank update for r600"
+  * Revert "(pre-stable) sched: Fix balance vs hotplug race"
+  * Revert "[Upstream] acerhdf: Limit modalias matching to supported
+    boards"
+  * Revert "[Upstream] mmc: prevent dangling block device from accessing
+    stale queues"
+  * Revert "SAUCE: Fix nx_enable reporting"
+  * Revert "SAUCE: [x86] fix report of cs-limit nx-emulation"
+  * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32"
+  * SAUCE: i915 -- disable powersave by default
+    - LP: #492392
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+  * [Upstream] b43: Declare all possible firmware files.
+    - LP: #488636
+  * [Config] updateconfigs after adding pvscsi
+    - LP: #497156
+  * [Config] CONFIG_BT=m
+  * Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu
+    for pre-Pentium"
+  * SCSI: ipr: fix EEH recovery
+  * SCSI: qla2xxx: dpc thread can execute before scsi host has been added
+  * SCSI: st: fix mdata->page_order handling
+  * SCSI: fc class: fix fc_transport_init error handling
+  * sched: Fix task_hot() test order
+  * x86, cpuid: Add "volatile" to asm in native_cpuid()
+  * sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE
+  * clockevents: Prevent clockevent_devices list corruption on cpu hotplug
+  * pata_hpt3x2n: fix clock turnaround
+  * pata_cmd64x: fix overclocking of UDMA0-2 modes
+  * ASoC: wm8974: fix a wrong bit definition
+  * sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer
+  * ALSA: hda - Fix missing capsrc_nids for ALC88x
+  * acerhdf: limit modalias matching to supported
+    - LP: #435958
+  * ACPI: EC: Fix MSI DMI detection
+  * ACPI: Use the return result of ACPI lid notifier chain correctly
+  * powerpc: Handle VSX alignment faults correctly in little-endian mode
+  * ASoC: Do not write to invalid registers on the wm9712.
+  * drm/radeon: fix build on 64-bit with some compilers.
+  * USB: emi62: fix crash when trying to load EMI 6|2 firmware
+  * USB: option: support hi speed for modem Haier CE100
+  * USB: Fix a bug on appledisplay.c regarding signedness
+  * USB: musb: gadget_ep0: avoid SetupEnd interrupt
+  * Bluetooth: Prevent ill-timed autosuspend in USB driver
+  * USB: rename usb_configure_device
+  * USB: fix bugs in usb_(de)authorize_device
+  * drivers/net/usb: Correct code taking the size of a pointer
+  * x86: SGI UV: Fix writes to led registers on remote uv hubs
+  * md: Fix unfortunate interaction with evms
+  * dma: at_hdmac: correct incompatible type for argument 1 of
+    'spin_lock_bh'
+  * dma-debug: Do not add notifier when dma debugging is disabled.
+  * dma-debug: Fix bug causing build warning
+  * cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS
+    referrals
+  * x86/amd-iommu: Fix initialization failure panic
+  * ioat3: fix p-disabled q-continuation
+  * ioat2,3: put channel hardware in known state at init
+  * KVM: MMU: remove prefault from invlpg handler
+  * KVM: LAPIC: make sure IRR bitmap is scanned after vm load
+  * Libertas: fix buffer overflow in lbs_get_essid()
+  * iwmc3200wifi: fix array out-of-boundary access
+  * mac80211: fix propagation of failed hardware reconfigurations
+  * mac80211: fix WMM AP settings application
+  * mac80211: Fix IBSS merge
+  * cfg80211: fix race between deauth and assoc response
+  * ath5k: fix SWI calibration interrupt storm
+  * ath9k: wake hardware for interface IBSS/AP/Mesh removal
+  * ath9k: Fix TX queue draining
+  * ath9k: fix missed error codes in the tx status check
+  * ath9k: wake hardware during AMPDU TX actions
+  * ath9k: fix suspend by waking device prior to stop
+  * ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on
+    64-bit
+  * ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value
+    in 0x4054
+  * iwl3945: disable power save
+  * iwl3945: fix panic in iwl3945 driver
+  * iwlwifi: fix EEPROM/OTP reading endian annotations and a bug
+  * iwlwifi: fix more eeprom endian bugs
+  * iwlwifi: fix 40MHz operation setting on cards that do not allow it
+  * mac80211: fix race with suspend and dynamic_ps_disable_work
+  * NOMMU: Optimise away the {dac_,}mmap_min_addr tests
+  * 'sysctl_max_map_count' should be non-negative
+  * kernel/sysctl.c: fix the incomplete part of
+    sysctl_max_map_count-should-be-non-negative.patch
+  * V4L/DVB (13596): ov511.c typo: lock => unlock
+  * x86/ptrace: make genregs[32]_get/set more robust
+  * memcg: avoid oom-killing innocent task in case of use_hierarchy
+  * e100: Fix broken cbs accounting due to missing memset.
+  * ipv6: reassembly: use seperate reassembly queues for conntrack and
+    local delivery
+  * netfilter: fix crashes in bridge netfilter caused by fragment jumps
+  * hwmon: (sht15) Off-by-one error in array index + incorrect constants
+  * b43: avoid PPC fault during resume
+  * Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture
+    support
+  * sched: Fix balance vs hotplug race
+  * drm/radeon/kms: fix crtc vblank update for r600
+  * drm: disable all the possible outputs/crtcs before entering KMS mode
+  * S390: dasd: support DIAG access for read-only devices
+  * xen: fix is_disconnected_device/exists_disconnected_device
+  * xen: improvement to wait_for_devices()
+  * xen: wait up to 5 minutes for device connetion
+  * orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled
+  * udf: Try harder when looking for VAT inode
+  * Add unlocked version of inode_add_bytes() function
+  * quota: decouple fs reserved space from quota reservation
+  * ext4: Convert to generic reserved quota's space management.
+  * ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
+  * x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus
+  * cpumask: use modern cpumask style in drivers/edac/amd64_edac.c
+  * amd64_edac: unify MCGCTL ECC switching
+  * x86, msr: Add support for non-contiguous cpumasks
+  * x86, msr: msrs_alloc/free for CONFIG_SMP=n
+  * amd64_edac: fix driver instance freeing
+  * amd64_edac: make driver loading more robust
+  * amd64_edac: fix forcing module load/unload
+  * sched: Sched_rt_periodic_timer vs cpu hotplug
+  * ext4: Update documentation to correct the inode_readahead_blks option
+    name
+  * lguest: fix bug in setting guest GDT entry
+  * vmscan: do not evict inactive pages when skipping an active list scan
+  * ksm: fix mlockfreed to munlocked
+  * rt2x00: Disable powersaving for rt61pci and rt2800pci.
+  * generic_permission: MAY_OPEN is not write access
+  * Linux 2.6.32.3
+  * untangle the do_mremap() mess
+  * fasync: split 'fasync_helper()' into separate add/remove functions
+  * ASoC: fix params_rate() macro use in several codecs
+  * modules: Skip empty sections when exporting section notes
+  * exofs: simple_write_end does not mark_inode_dirty
+  * nfsd: make sure data is on disk before calling ->fsync
+  * sunrpc: fix peername failed on closed listener
+  * SUNRPC: Fix up an error return value in
+    gss_import_sec_context_kerberos()
+  * SUNRPC: Fix the return value in gss_import_sec_context()
+  * sunrpc: on successful gss error pipe write, don't return error
+  * drm/i915: Update LVDS connector status when receiving ACPI LID event
+  * drm/i915: fix order of fence release wrt flushing
+  * drm/i915: Permit pinning whilst the device is 'suspended'
+  * drm: remove address mask param for drm_pci_alloc()
+  * drm/i915: Enable/disable the dithering for LVDS based on VBT setting
+  * drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in
+    pipeconf on Ironlake
+  * drm/i915: Select the correct BPC for LVDS on Ironlake
+  * drm/i915: fix unused var
+  * rtc_cmos: convert shutdown to new pnp_driver->shutdown
+  * drivers/cpuidle/governors/menu.c: fix undefined reference to
+    `__udivdi3'
+  * cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput()
+  * lib/rational.c needs module.h
+  * dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with
+    DMA_FROM_DEVICE and
+  * kernel/signal.c: fix kernel information leak with print-fatal-signals=1
+  * mmc_block: add dev_t initialization check
+  * mmc_block: fix probe error cleanup bug
+  * mmc_block: fix queue cleanup
+  * ALSA: hda - Fix ALC861-VD capture source mixer
+  * ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense
+    blacklist
+  * ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2
+    - LP: #498863
+  * ASoC: Fix WM8350 DSP mode B configuration
+  * netfilter: ebtables: enforce CAP_NET_ADMIN
+  * netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq()
+  * hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs
+  * hwmon: (adt7462) Fix pin 28 monitoring
+  * quota: Fix dquot_transfer for filesystems different from ext4
+  * xen: fix hang on suspend.
+  * iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr
+  * ath5k: Fix eeprom checksum check for custom sized eeproms
+  * cfg80211: fix syntax error on user regulatory hints
+  * iwl: off by one bug
+  * mac80211: add missing sanity checks for action frames
+  * drm/i915: remove render reclock support
+  * libertas: Remove carrier signaling from the scan code
+  * kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr
+  * mac80211: fix skb buffering issue (and fixes to that)
+  * fix braindamage in audit_tree.c untag_chunk()
+  * fix more leaks in audit_tree.c tag_chunk()
+  * module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y
+  * ipv6: skb_dst() can be NULL in ipv6_hop_jumbo().
+  * agp/intel-agp: Clear entire GTT on startup
+  * Linux 2.6.32.4
+  * ethtool: Add reset operation
+  * gro: Name the GRO result enumeration type
+  * gro: Change all receive functions to return GRO result codes
+  * sfc: 10Xpress: Initialise pause advertising flags
+  * sfc: 10Xpress: Report support for pause frames
+  * sfc: Remove redundant header gmii.h
+  * sfc: Remove redundant hardware initialisation
+  * sfc: Rename Falcon-specific board code and types
+  * sfc: Remove boards.h, moving last remaining declaration to falcon.h
+  * sfc: Remove versioned bitfield macros
+  * sfc: Move RX data FIFO thresholds out of struct efx_nic_type
+  * sfc: Update hardware definitions for Siena
+  * sfc: Rename register I/O header and functions used by both Falcon and
+    Siena
+  * sfc: Eliminate indirect lookups of queue size constants
+  * sfc: Define DMA address mask explicitly in terms of descriptor field
+    width
+  * sfc: Move all TX DMA length limiting into tx.c
+  * sfc: Change order of device removal to reverse of probe order
+  * sfc: Remove declarations of nonexistent functions
+  * sfc: Move efx_xmit_done() declaration into correct stanza
+  * sfc: Move shared members of struct falcon_nic_data into struct efx_nic
+  * sfc: Maintain interrupt moderation values in ticks, not microseconds
+  * sfc: Removed kernel-doc for nonexistent member of efx_phy_operations
+  * sfc: Remove pointless abstraction of memory BAR number
+  * sfc: Remove incorrect assertion from efx_pci_remove_main()
+  * sfc: Remove unnecessary tests of efx->membase
+  * sfc: Move MTD probe after netdev registration and name allocation
+  * sfc: Remove unused code for non-autoneg speed/duplex switching
+  * sfc: Rename 'xfp' file and functions to reflect reality
+  * sfc: Really allow RX checksum offload to be disabled
+  * sfc: Feed GRO result into RX allocation policy and interrupt moderation
+  * sfc: Enable heuristic selection between page and skb RX buffers
+  * sfc: Remove pointless abstraction of memory BAR number (2)
+  * sfc: Remove redundant gotos from __efx_rx_packet()
+  * sfc: Remove ridiculously paranoid assertions
+  * sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro()
+  * sfc: Record RX queue number on GRO path
+  * sfc: SFT9001: Reset LED configuration correctly after blinking
+  * sfc: Use a single blink implementation
+  * sfc: Rename efx_board::init_leds to init_phy and use for SFN4111T
+  * sfc: Make board information explicitly Falcon-specific
+  * sfc: Move definition of struct falcon_nic_data into falcon.h
+  * sfc: Move struct falcon_board into struct falcon_nic_data
+  * sfc: Move all I2C stuff into struct falcon_board
+  * sfc: Gather link state fields in struct efx_nic into new struct
+    efx_link_state
+  * sfc: Remove unnecessary casts to struct sk_buff *
+  * sfc: Remove redundant efx_xmit() function
+  * sfc: Combine high-level header files
+  * sfc: Log interrupt and reset type names, not numbers
+  * sfc: Fix descriptor cache sizes
+  * sfc: Treat all MAC registers as 128-bit
+  * sfc: Strengthen EFX_ASSERT_RESET_SERIALISED
+  * sfc: Comment corrections
+  * sfc: Remove unused constant
+  * sfc: Clean up struct falcon_board and struct falcon_board_data
+  * sfc: Fix bugs in RX queue flushing
+  * sfc: Remove unused function efx_flush_queues()
+  * sfc: Only switch Falcon MAC clocks as necessary
+  * sfc: Hold MAC lock for longer in efx_init_port()
+  * sfc: Split MAC stats DMA initiation and completion
+  * sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c
+  * sfc: Simplify XMAC link polling
+  * sfc: Change MAC promiscuity and multicast hash at the same time
+  * sfc: Move inline comment into kernel-doc
+  * sfc: Do not set net_device::trans_start in self-test
+  * sfc: Simplify PHY polling
+  * sfc: QT202x: Reset before reading PHY id
+  * sfc: Replace MDIO spinlock with mutex
+  * sfc: Always start Falcon using the XMAC
+  * sfc: Limit some hardware workarounds to Falcon
+  * sfc: Remove EFX_WORKAROUND_9141 macro
+  * sfc: Remove another unused workaround macro
+  * sfc: Remove some redundant whitespace
+  * sfc: Decouple NIC revision number from Falcon PCI revision number
+  * sfc: Move descriptor cache base addresses to struct efx_nic_type
+  * sfc: Clean up RX event handling
+  * sfc: Remove redundant writes to INT_ADR_KER
+  * sfc: Remove duplicate hardware structure definitions
+  * sfc: Turn pause frame generation on and off at the MAC, not the RX FIFO
+  * sfc: Move Falcon NIC operations to efx_nic_type
+  * sfc: Refactor link configuration
+  * sfc: Generalise link state monitoring
+  * sfc: Add power-management and wake-on-LAN support
+  * sfc: Implement ethtool reset operation
+  * sfc: Add efx_nic_type operation for register self-test
+  * sfc: Add efx_nic_type operation for NVRAM self-test
+  * sfc: Add efx_nic_type operation for identity LED control
+  * sfc: Separate shared NIC code from Falcon-specific and rename
+    accordingly
+  * sfc: Fold falcon_probe_nic_variant() into falcon_probe_nic()
+  * sfc: Extend loopback mode enumeration
+  * sfc: Remove static PHY data and enumerations
+  * sfc: Extend MTD driver for use with new NICs
+  * sfc: Allow for additional checksum offload features
+  * sfc: Rename falcon.h to nic.h
+  * sfc: Move shared NIC code from falcon.c to new source file nic.c
+  * sfc: Add firmware protocol definitions (MCDI)
+  * sfc: Add support for SFC9000 family (1)
+  * sfc: Add support for SFC9000 family (2)
+  * sfc: Implement TSO for TCP/IPv6
+  * sfc: Update version, copyright dates, authors
+  * drivers/net/sfc: Correct code taking the size of a pointer
+  * sfc: Move PHY software state initialisation from init() into probe()
+  * sfc: Include XGXS in XMAC link status check except in XGMII loopback
+  * sfc: Fix DMA mapping cleanup in case of an error in TSO
+  * sfc: QT2025C: Work around PHY bug
+  * sfc: QT2025C: Switch into self-configure mode when not in loopback
+  * sfc: QT2025C: Work around PHY firmware initialisation bug
+  * sfc: QT2025C: Add error message for suspected bad SFP+ cables
+  * sfc: Disable TX descriptor prefetch watchdog
+  * [SCSI] vmw_pvscsi: SCSI driver for VMware's virtual HBA.
+    - LP: #497156
+
+  [ Ubuntu: 2.6.32-10.14 ]
+
+  * SAUCE: drm/radeon/kms: fix LVDS setup on r4xx
+    - LP: #493795
+  * Revert "(pre-stable) acpi: Use the ARB_DISABLE for the CPU which model
+    id is less than 0x0f."
+  * config-check -- ensure the checks get run at build time
+  * config-check -- check the processed config during updateconfigs
+  * config-check -- CONFIG_SECCOMP may not be present
+  * TUN is now built in ignore
+  * SAUCE: acpi battery -- delay first lookup of the battery until first
+    use
+  * SAUCE: async_populate_rootfs: move rootfs init earlier
+  * ubuntu: AppArmor -- update to mainline 2010-01-06
+  * SAUCE: move RLIMIT_CORE pipe dumper marker to 1
+    - LP: #498525
+  * (pre-stable) drm/radeon/kms: fix crtc vblank update for r600
+  * Add asix to nic-usb-modules file
+    - LP: #499785
+  * (pre-stable) sched: Fix balance vs hotplug race
+  * [Config] Enable CONFIG_FUNCTION_TRACER
+    - LP: #497989
+  * [Config] Drop lpia from getabis
+  * [Config] Build in TUN/TAP driver
+    - LP: #499491
+  * [Config] DH_COMPAT=5
+  * Revert "(pre-stable) drm/i915: Avoid NULL dereference with
+    component_only tv_modes"
+  * Revert "(pre-stable) drm/i915: Fix sync to vblank when VGA output is
+    turned off"
+  * USB: usb-storage: fix bug in fill_inquiry
+  * USB: option: add pid for ZTE
+  * firewire: ohci: handle receive packets with a data length of zero
+  * rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling
+    of ->completed counter
+  * rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed
+    counter
+  * rcu: Fix note_new_gpnum() uses of ->gpnum
+  * rcu: Remove inline from forward-referenced functions
+  * perf_event: Fix invalid type in ioctl definition
+  * perf_event: Initialize data.period in perf_swevent_hrtimer()
+  * perf: Don't free perf_mmap_data until work has been done
+  * PM / Runtime: Fix lockdep warning in __pm_runtime_set_status()
+  * sched: Check for an idle shared cache in select_task_rq_fair()
+  * sched: Fix affinity logic in select_task_rq_fair()
+  * sched: Rate-limit newidle
+  * sched: Fix and clean up rate-limit newidle code
+  * x86/amd-iommu: attach devices to pre-allocated domains early
+  * x86/amd-iommu: un__init iommu_setup_msi
+  * x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking
+    up the PCI tree
+  * x86: Fix iommu=nodac parameter handling
+  * x86: GART: pci-gart_64.c: Use correct length in strncmp
+  * x86: ASUS P4S800 reboot=bios quirk
+    - LP: #366682
+  * x86, apic: Enable lapic nmi watchdog on AMD Family 11h
+  * ssb: Fix range check in sprom write
+  * ath5k: allow setting txpower to 0
+  * ath5k: enable EEPROM checksum check
+  * hrtimer: Fix /proc/timer_list regression
+  * ALSA: hrtimer - Fix lock-up
+  * ALSA: hda - Terradici HDA controllers does not support 64-bit mode
+  * KVM: x86 emulator: limit instructions to 15 bytes
+  * KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c
+  * KVM: s390: Make psw available on all exits, not just a subset
+  * KVM: fix irq_source_id size verification
+  * KVM: x86: include pvclock MSRs in msrs_to_save
+  * x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage
+  * x86: Use -maccumulate-outgoing-args for sane mcount prologues
+  * x86, mce: don't restart timer if disabled
+  * x86/mce: Set up timer unconditionally
+  * x86: SGI UV: Fix BAU initialization
+  * x86: Fix duplicated UV BAU interrupt vector
+  * x86: Add new Intel CPU cache size descriptors
+  * x86: Fix typo in Intel CPU cache size descriptor
+  * pata_hpt{37x|3x2n}: fix timing register masks (take 2)
+  * s390: clear high-order bits of registers after sam64
+  * V4L/DVB: Fix test in copy_reg_bits()
+  * bsdacct: fix uid/gid misreporting
+  * UBI: flush wl before clearing update marker
+  * jbd2: don't wipe the journal on a failed journal checksum
+  * USB: xhci: Add correct email and files to MAINTAINERS entry.
+  * USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again
+  * USB: option.c: add support for D-Link DWM-162-U5
+  * USB: usbtmc: repeat usb_bulk_msg until whole message is transfered
+  * USB: usb-storage: add BAD_SENSE flag
+  * USB: Close usb_find_interface race v3
+  * pxa/em-x270: fix usb hub power up/reset sequence
+  * hfs: fix a potential buffer overflow
+  * SUNRPC: IS_ERR/PTR_ERR confusion
+  * NFS: Fix nfs_migrate_page()
+  * md/bitmap: protect against bitmap removal while being updated.
+  * futex: Take mmap_sem for get_user_pages in fault_in_user_writeable
+  * devpts_get_tty() should validate inode
+  * debugfs: fix create mutex racy fops and private data
+  * Driver core: fix race in dev_driver_string
+  * Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN
+  * mac80211: Fix bug in computing crc over dynamic IEs in beacon
+  * mac80211: Fixed bug in mesh portal paths
+  * mac80211: Revert 'Use correct sign for mesh active path refresh'
+  * mac80211: fix scan abort sanity checks
+  * wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC
+  * rtl8187: Fix wrong rfkill switch mask for some models
+  * x86: Fix bogus warning in apic_noop.apic_write()
+  * mm: hugetlb: fix hugepage memory leak in mincore()
+  * mm: hugetlb: fix hugepage memory leak in walk_page_range()
+  * powerpc/windfarm: Add detection for second cpu pump
+  * powerpc/therm_adt746x: Record pwm invert bit at module load time]
+  * powerpc: Fix usage of 64-bit instruction in 32-bit altivec code
+  * drm/radeon/kms: Add quirk for HIS X1300 board
+  * drm/radeon/kms: handle vblanks properly with dpms on
+  * drm/radeon/kms: fix legacy crtc2 dpms
+  * drm/radeon/kms: fix vram setup on rs600
+  * drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size
+  * drm/ttm: Fix build failure due to missing struct page
+  * drm/i915: Set the error code after failing to insert new offset into mm
+    ht.
+  * drm/i915: Add the missing clonemask for display port on Ironlake
+  * xen/xenbus: make DEVICE_ATTR()s static
+  * xen: re-register runstate area earlier on resume.
+  * xen: restore runstate_info even if !have_vcpu_info_placement
+  * xen: correctly restore pfn_to_mfn_list_list after resume
+  * xen: register timer interrupt with IRQF_TIMER
+  * xen: register runstate on secondary CPUs
+  * xen: don't call dpm_resume_noirq() with interrupts disabled.
+  * xen: register runstate info for boot CPU early
+  * xen: call clock resume notifier on all CPUs
+  * xen: improve error handling in do_suspend.
+  * xen: don't leak IRQs over suspend/resume.
+  * xen: use iret for return from 64b kernel to 32b usermode
+  * xen: explicitly create/destroy stop_machine workqueues outside
+    suspend/resume region.
+  * Xen balloon: fix totalram_pages counting.
+  * xen: try harder to balloon up under memory pressure.
+  * dm exception store: free tmp_store on persistent flag error
+  * dm snapshot: only take lock for statustype info not table
+  * dm crypt: move private iv fields to structs
+  * dm crypt: restructure essiv error path
+  * dm: avoid _hash_lock deadlock
+  * dm snapshot: cope with chunk size larger than origin
+  * dm crypt: separate essiv allocation from initialisation
+  * dm crypt: make wipe message also wipe essiv key
+  * slc90e66: fix UDMA handling
+  * tcp: Stalling connections: Fix timeout calculation routine
+  * ip_fragment: also adjust skb->truesize for packets not owned by a
+    socket
+  * b44 WOL setup: one-bit-off stack corruption kernel panic fix
+  * sparc64: Don't specify IRQF_SHARED for LDC interrupts.
+  * sparc64: Fix overly strict range type matching for PCI devices.
+  * sparc64: Fix stack debugging IRQ stack regression.
+  * sparc: Set UTS_MACHINE correctly.
+  * b43legacy: avoid PPC fault during resume
+  * tracing: Fix event format export
+  * ath9k: Fix TX hang poll routine
+  * ath9k: fix processing of TX PS null data frames
+  * ath9k: Fix maximum tx fifo settings for single stream devices
+  * ath9k: fix tx status reporting
+  * mac80211: Fix dynamic power save for scanning.
+  * drm/i915: Fix sync to vblank when VGA output is turned off
+  * memcg: fix memory.memsw.usage_in_bytes for root cgroup
+  * thinkpad-acpi: fix default brightness_mode for R50e/R51
+  * thinkpad-acpi: preserve rfkill state across suspend/resume
+  * ipw2100: fix rebooting hang with driver loaded
+  * matroxfb: fix problems with display stability
+  * acerhdf: add new BIOS versions
+  * asus-laptop: change light sens default values.
+  * vmalloc: conditionalize build of pcpu_get_vm_areas()
+  * ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f.
+  * net: Fix userspace RTM_NEWLINK notifications.
+  * ext3: Fix data / filesystem corruption when write fails to copy data
+  * V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added.
+  * bcm63xx_enet: fix compilation failure after get_stats_count removal
+  * x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value
+  * drm/i915: Avoid NULL dereference with component_only tv_modes
+  * drm/i915: PineView only has LVDS and CRT ports
+  * drm/i915: Fix LVDS stability issue on Ironlake
+  * mm: sigbus instead of abusing oom
+  * ipvs: zero usvc and udest
+  * jffs2: Fix long-standing bug with symlink garbage collection.
+  * intel-iommu: Detect DMAR in hyperspace at probe time.
+  * intel-iommu: Apply BIOS sanity checks for interrupt remapping too.
+  * intel-iommu: Check for an RMRR which ends before it starts.
+  * intel-iommu: Fix oops with intel_iommu=igfx_off
+  * intel-iommu: ignore page table validation in pass through mode
+  * netfilter: xtables: document minimal required version
+  * perf_event: Fix incorrect range check on cpu number
+  * implement early_io{re,un}map for ia64
+  * Linux 2.6.32.2
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 06 Feb 2010 18:04:10 +0000
+
+linux-ec2 (2.6.32-301.5) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-9.13
+  * [Config] update configs following rebase to Ubuntu-2.6.31-9.13
+
+  [ Ubuntu: 2.6.32-9.13 ]
+
+  * [Config] enable CONFIG_B43_PHY_LP
+    - LP: #493059
+  * include modules.builtin in the binary debs
+  * config-check -- add a configuration enforcer
+  * config-check -- add a unit-test suite to the checker
+  * [Config] Enable CONFIG_SYN_COOKIES for versatile
+  * [Config] Enable CONFIG_SECURITY_SMACK for ports
+  * [Config] Enable CONFIG_SECURITY_FILE_CAPABILITIES for ports
+  * [Config] Disable CONFIG_COMPAT_BRK for ports
+  * getabis -- add armel versatile to the list
+  * SAUCE: Increase the default prealloc buffer for HDA audio devices
+    (non-modem)
+  * ubuntu: onmibook -- Added missing BOM file
+  * ubuntu: fsam7400 -- Cleanup Makefile
+  * Revert "ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT"
+  * signal: Fix alternate signal stack check
+  * SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects
+  * SCSI: osd_protocol.h: Add missing #include
+  * SCSI: megaraid_sas: fix 64 bit sense pointer truncation
+  * ext4: fix potential buffer head leak when add_dirent_to_buf() returns
+    ENOSPC
+  * ext4: avoid divide by zero when trying to mount a corrupted file system
+  * ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails
+  * ext4: fix lock order problem in ext4_move_extents()
+  * ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT
+  * ext4: plug a buffer_head leak in an error path of ext4_iget()
+  * ext4: make sure directory and symlink blocks are revoked
+  * ext4: fix i_flags access in ext4_da_writepages_trans_blocks()
+  * ext4: journal all modifications in ext4_xattr_set_handle
+  * ext4: don't update the superblock in ext4_statfs()
+  * ext4: fix uninit block bitmap initialization when s_meta_first_bg is
+    non-zero
+  * ext4: fix block validity checks so they work correctly with meta_bg
+  * ext4: avoid issuing unnecessary barriers
+  * ext4: fix error handling in ext4_ind_get_blocks()
+  * ext4: make trim/discard optional (and off by default)
+  * ext4: make "norecovery" an alias for "noload"
+  * ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT
+  * ext4: initialize moved_len before calling ext4_move_extents()
+  * ext4: move_extent_per_page() cleanup
+  * jbd2: Add ENOMEM checking in and for
+    jbd2_journal_write_metadata_buffer()
+  * ext4: Return the PTR_ERR of the correct pointer in
+    setup_new_group_blocks()
+  * ext4: Avoid data / filesystem corruption when write fails to copy data
+  * ext4: wait for log to commit when umounting
+  * ext4: remove blocks from inode prealloc list on failure
+  * ext4: ext4_get_reserved_space() must return bytes instead of blocks
+  * ext4: quota macros cleanup
+  * ext4: fix incorrect block reservation on quota transfer.
+  * ext4: Wait for proper transaction commit on fsync
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+  * ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem)
+  * Linux 2.6.32.1
+  * kbuild: generate modules.builtin
+  * (pre-stable) drm/i915: Fix sync to vblank when VGA output is turned off
+    - LP: #494461
+  * (pre-stable) drm/i915: Avoid NULL dereference with component_only
+    tv_modes
+    - LP: #494045
+  * (pre-stable) acpi: Use the ARB_DISABLE for the CPU which model id is
+    less than 0x0f.
+    - LP: #481765
+
+  [ Ubuntu: 2.6.32-8.12 ]
+
+  * SAUCE: AppArmor -- add linux/err.h for ERR_PTR
+
+  [ Ubuntu: 2.6.32-8.11 ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches
+    up"
+  * Revert "SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition."
+  * Revert "SAUCE: AppArmor: Fix refcounting bug causing leak of creds"
+  * Revert "SAUCE: AppArmor: Fix cap audit_caching preemption disabling"
+  * Revert "SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds"
+  * Revert "SAUCE: AppArmor: Fix oops after profile removal"
+  * Revert "SAUCE: AppArmor: AppArmor disallows truncate of deleted files."
+  * Revert "SAUCE: AppArmor: AppArmor fails to audit change_hat correctly"
+  * Revert "SAUCE: AppArmor: Policy load and replacement can fail to alloc
+    mem"
+  * Revert "SAUCE: AppArmor: AppArmor wrongly reports allow perms as
+    denied"
+  * Revert "SAUCE: AppArmor: Fix mediation of "deleted" paths"
+  * Revert "SAUCE: AppArmor: Fix off by 2 error in getprocattr mem
+    allocation"
+  * Revert "SAUCE: AppArmor: Set error code after structure
+    initialization."
+  * Revert "AppArmor -- fix pstrace_may_access rename"
+  * Revert "ubuntu: AppArmor security module"
+  * Revert "SAUCE: Add config option to set a default LSM"
+  * Revert "ubuntu: fsam7400 -- sw kill switch driver"
+  * Revert "[Config] fsam7400 -- enable"
+  * Revert "[Config] AUFS -- enable"
+  * Revert "ubuntu: AUFS -- aufs2-30 20090727"
+  * Revert "ubuntu: AUFS -- export various core functions -- fixes"
+  * Revert "ubuntu: AUFS -- export various core functions"
+  * Revert "[Config] ubuntu/iscsitarget -- disable"
+  * Revert "[Config] iscsitarget -- enable"
+  * Revert "ubuntu: iscsitarget -- SVN revision r214"
+  * update Vcs-Git to point to the correct repository
+    - LP: #493589
+  * update build environment overrides to lucid
+    - LP: #493589
+  * [Config] enable CONFIG_DEVTMPFS
+  * [Config] update all configs following AppArmor 2009-12-08 update
+  * SAUCE: isapnp_init: make isa PNP scans occur async
+  * [Config] fsam7400 -- enable
+  * [Config] omnibook -- enable
+  * [Config] cleanup CONFIG_AUDIT
+  * ubuntu: AUFS -- export various core functions (aufs2-base.patch)
+  * ubuntu: AUFS -- export various core functions (aufs2-standalone.patch)
+  * ubuntu: AUFS -- aufs2 20091209
+  * [Config] AUFS -- enable
+  * [Config] iscsitarget -- enable
+  * SAUCE: KMS: cache the EDID information of the LVDS
+  * bnx2: update d-i firmware filenames
+    - LP: #494052
+  * add cdc_ether to nic-usb-modules udeb
+    - LP: #495060
+  * ubuntu: AppArmor -- mainline 2009-10-08
+  * ubuntu: fsam7400 -- kill switch for Fujitsu Siemens Amilo M 7400
+  * ubuntu: omnibook -- support Toshiba (HP) netbooks
+  * ubuntu: iscsitarget --- version 1.4.19
+    - LP: #494693
+  * SAUCE: Make populate_rootfs asynchronous
+  * Parallelize flavour builds and packaging
+  * [Config] Enable CONFIG_KSM
+  * Config option to set a default LSM
+  * LSM: Add security_path_chroot().
+  * LSM: Add security_path_chroot().
+  * LSM: Move security_path_chmod()/security_path_chown() to after
+    mutex_lock().
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 19:04:09 +0000
+
+linux-ec2 (2.6.32-301.4) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * sort out previous ABI files to fix FTBFS
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 15:00:05 +0000
+
+linux-ec2 (2.6.32-301.3) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * drop generated files to fix FTBFS
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 22 Dec 2009 13:36:44 +0000
+
+linux-ec2 (2.6.32-301.2) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to Ubuntu-2.6.32-7.9
+  * [Config] update configs following rebase to Ubuntu-2.6.32-7.9
+  * rebase to Ubuntu-2.6.32-7.10
+
+  [ Ubuntu: 2.6.32-7.10 ]
+
+  * [Config] disable CONFIG_THUMB2_KERNEL to fix arm FTBFS
+
+  [ Ubuntu: 2.6.32-7.9 ]
+
+  * SAUCE: set /proc/acpi/video/*/DOS to 4 by default
+    - LP: #458982
+  * SAUCE: ensure vga16fb loads if no other driver claims the VGA device
+  * [Config] update configs following versatile switch to V7
+  * rebased to v2.6.32
+  * [Config] update configs following rebase to v2.6.32
+  * [Config] update ports configs following rebase to v2.6.32
+  * SAUCE: vfs: Add a trace point in the mark_inode_dirty function
+  * [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable
+    permissions
+    - CVE-2009-3939
+  * SAUCE: select a v7 CPU for versatile
+  * SAUCE: ALSA: hda - Add power on/off counter
+  * rebased to v2.6.32
+
+  [ Ubuntu: 2.6.32-6.8 ]
+
+  * [Config] disable SSB devices for armel
+
+  [ Ubuntu: 2.6.32-6.7 ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches up"
+  * Revert "SAUCE: Dell XPS710 reboot quirk"
+  * Revert "SAUCE: Link acpi-cpufreq.o first"
+  * Revert "SAUCE: LPIA  Logical reset of USB port on resume"
+  * Revert "SAUCE: LPIA Reboot fix for Intel Crownbeach development boards"
+  * Revert "SAUCE: Enable HDMI audio codec on Studio XPS 1340"
+  * Revert "SAUCE: Dell laptop digital mic does not work, PCI 1028:0271"
+  * Revert "Add Dell Dimension 9200 reboot quirk"
+  * Revert "SAUCE: Correctly blacklist Thinkpad r40e in ACPI"
+  * Revert "SAUCE: tulip: Define ULI PCI ID's"
+  * Revert "SAUCE: Lower warning level of some PCI messages"
+  * Revert "mac80211: fix two issues in debugfs"
+    Drop a number of known redundant commits as identified in the Ubuntu
+    delta review blueprint.
+  * reenable armel versatile flavour
+  * [Config] disable CONFIG_USB_DEVICEFS
+  * [Config] udeb: Add squashfs to fs-core-modules
+    - LP: #352615
+  * [Config] Create a real squashfs udeb
+    - LP: #352615
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 07 Dec 2009 21:10:30 +0000
+
+linux-ec2 (2.6.32-300.1) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: fix nx-emulation when disabled by XEN
+  * SAUCE: fix disable of KERNEL_IMAGE_SIZE for i386 XEN builds
+
+  [ John Johansen ]
+
+  * Fix recursive include
+  * SAUCE: Fix build ASSERT for 3.0.2 compatibility
+  * SAUCE: ec2: Default domU console to tty.
+    - LP: #431103
+  * [Config] Setup EC2 commit
+  * update configs for 2.6.32
+  * rebase to Ubuntu-2.6.32-5.6
+
+  [ Ubuntu: 2.6.32-5.6 ]
+
+  * rebase to v2.6.32-rc8
+  * update configs following rebase to v2.6.32-rc8
+  * update ports configs since rebase to v2.6.32-rc8
+  * [Config] enable cgroup options
+    - LP: #480739
+  * rebase to v2.6.32-rc8
+
+  [ Ubuntu: 2.6.32-4.5 ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * rebase to v2.6.32-rc7
+  * resync with Karmic proposed
+  * SAUCE: AppArmor: Fix oops after profile removal
+    - LP: #475619
+  * SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds
+    - LP: #437258
+  * SAUCE: AppArmor: Fix cap audit_caching preemption disabling
+    - LP: #479102
+  * SAUCE: AppArmor: Fix refcounting bug causing leak of creds
+    - LP: #479115
+  * SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition.
+    - LP: #480112
+  * resync with Karmic proposed (ddbc670a86a3dee18541a3734149f250ff307adf)
+  * rebase to v2.6.32-rc7
+
+  [ Ubuntu: 2.6.32-3.4 ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * [Upstream] add local prefix to oss local change_bits
+  * mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/
+  * mtd/maps: gpio-addr-flash: depend on GPIO arch support
+
+  [ Ubuntu: 2.6.32-3.3 ]
+
+  * rebase to v2.6.32-rc6
+  * [Config] update configs following rebase to v2.6.32-rc6
+  * [Config] update ports configs following rebase to v2.6.32-rc6
+  * resync with Karmic Ubuntu-2.6.31-15.49
+  * [Config] add module ignores for broken drivers
+  * SAUCE: AppArmor: AppArmor wrongly reports allow perms as denied
+    - LP: #453335
+  * SAUCE: AppArmor: Policy load and replacement can fail to alloc mem
+    - LP: #458299
+  * SAUCE: AppArmor: AppArmor fails to audit change_hat correctly
+    - LP: #462824
+  * SAUCE: AppArmor: AppArmor disallows truncate of deleted files.
+    - LP: #451375
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+  * Revert "SAUCE: trace: add trace_event for the open() syscall"
+  * SAUCE: trace: add trace events for open(), exec() and uselib()
+    - LP: #462111
+  * SAUCE: Fix sub-flavour script to not stop on missing directories
+    - LP: #453073
+  * resync with Karmic Ubuntu-2.6.31-15.49
+  * rebase to v2.6.32-rc6
+    - LP: #464552
+
+  [ Ubuntu: 2.6.32-2.2 ]
+
+  * install the full changelog with the binary package
+  * changelog -- explicitly note rebases and clean history
+  * reinstate armel.mk with no flavours
+    - LP: #449637
+  * [Upstream] block: silently error unsupported empty barriers too
+    - LP: #420423
+  * [Config] udate configs following karmic resync
+  * [Config] update ports configs following karmic resync
+  * [Upstream] lirc -- follow removal of .id element
+  * Use section 'admin' rather than 'base'
+  * Add more e100 firmware to nic-modules
+    - LP: #451872
+  * Add qla1280 firmware to scsi-modules
+    - LP: #381037
+  * SAUCE: AppArmor: Set error code after structure initialization.
+    - LP: #427948
+  * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation
+    - LP: #446595
+  * SAUCE: AppArmor: Fix mediation of "deleted" paths
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+  * SAUCE: (drop after 2.6.31) input: Add support for filtering input
+    events
+    - LP: #430809
+  * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi
+    toggle switch press
+    - LP: #430809
+  * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc
+  * [Config] Add sd_mod to scsi-modules udeb for powerpc
+  * SAUCE: Update to LIRC 0.8.6
+    - LP: #432678
+  * SAUCE: dell-laptop: Store the HW switch status internally rather than
+    requerying every time
+    - LP: #430809
+  * SAUCE: dell-laptop: Blacklist machines not supporting dell-laptop
+    - LP: #430809
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    - LP: #435958
+  * [Upstream] i915: Fix i2c init message
+    - LP: #409361
+  * [Config] Add sym53c8xx.ko to virtual sub-flavour
+    - LP: #439415
+  * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules
+    - LP: #439456
+  * [Config] Set default I/O scheduler back to CFQ for desktop flavours
+    - LP: #381300
+  * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros
+    - LP: #430694
+  * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915
+    - LP: #430694
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT
+    - LP: #430694
+  * SAUCE: Raise the default console 'quiet' level to 2
+  * [Config] CONFIG_X86_PAT=y
+  * [Config] Add armel arch to linux-libc-dev arches.
+    - LP: #449637
+  * [Config] CONFIG_X86_MCE
+  * [Upstream] (drop after 2.6.31) Input: synaptics - add another Protege
+    M300 to rate blacklist
+    - LP: #433801
+  * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584
+  * drm/i915: Fix FDI M/N setting according with correct color depth
+    - LP: #416792
+
+  [ Ubuntu: 2.6.32-1.1 ]
+
+  * rebase to v2.6.32-rc3
+  * [Config] update configs following rebase to 2.6.32-rc3
+  * [Config] update ports configs following rebase to 2.6.32-rc3
+  * AppArmor -- fix pstrace_may_access rename
+  * staging/android -- disable
+  * ubuntu: dm-raid-45 -- update to compile with 2.6.32
+  * ubuntu: drbd -- disable
+  * staging/comdi -- disable
+  * staging/go7007 -- disable
+  * [Config] staging/winbond -- disable
+  * [Config] ubuntu/iscsitarget -- disable
+  * [d-i] cbc and ecb are builtin make them optional in udebs
+  * rebase to v2.6.32-rc5
+  * [Config] update configs following rebase to v2.6.32-rc5
+  * [Config] update ports configs following rebase to v2.6.31-rc5
+  * [Config] Add cpio as a build dependency.
+  * rebase to v2.6.32-rc3
+  * rebase to v2.6.32-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 30 Nov 2009 12:48:46 +0000
+
+linux-ec2 (2.6.31-302.7) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Updateconfigs after rebase to 2.6.31-14.46
+
+  * Rebased against linux (2.6.31-14.46)
+
+  [ Andy Whitcroft ]
+
+  * reinstate armel.mk with no flavours
+    - LP: #449637
+  * [Upstream] elevator: fix fastfail checks to allow merge of readahead
+    requests
+    - LP: #444915
+  * [Upstream] block: silently error unsupported empty barriers too
+    - LP: #420423
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix mediation of "deleted" paths
+    - LP: #415632
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_X86_MCE
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007584.html
+  * Revert "appletalk: Fix skb leak when ipddp interface is not loaded,
+    CVE-2009-2903" - Use patch from 2.6.31.4 which is slightly different.
+
+  [ Upstream Kernel Changes ]
+
+  * x86: fix csum_ipv6_magic asm memory clobber
+  * tty: Avoid dropping ldisc_mutex over hangup tty re-initialization
+  * x86: Don't leak 64-bit kernel register values to 32-bit processes
+  * tracing: correct module boundaries for ftrace_release
+  * ftrace: check for failure for all conversions
+  * futex: fix requeue_pi key imbalance
+  * futex: Move exit_pi_state() call to release_mm()
+  * futex: Nullify robust lists after cleanup
+  * futex: Fix locking imbalance
+  * NOHZ: update idle state also when NOHZ is inactive
+  * ima: ecryptfs fix imbalance message
+  * libata: fix incorrect link online check during probe
+  * sound: via82xx: move DXS volume controls to PCM interface
+  * ASoC: WM8350 capture PGA mutes are inverted
+  * KVM: Prevent overflow in KVM_GET_SUPPORTED_CPUID
+  * KVM: VMX: flush TLB with INVEPT on cpu migration
+  * KVM: fix LAPIC timer period overflow
+  * KVM: SVM: Fix tsc offset adjustment when running nested
+  * KVM: SVM: Handle tsc in svm_get_msr/svm_set_msr correctly
+  * net: Fix wrong sizeof
+  * mm: add_to_swap_cache() must not sleep
+  * sis5513: fix PIO setup for ATAPI devices
+  * PIT fixes to unbreak suspend/resume (bug #14222)
+  * IMA: open new file for read
+  * ACPI: Clarify resource conflict message
+  * ACPI: fix Compaq Evo N800c (Pentium 4m) boot hang regression
+  * net: restore tx timestamping for accelerated vlans
+  * net: unix: fix sending fds in multiple buffers
+  * tun: Return -EINVAL if neither IFF_TUN nor IFF_TAP is set.
+  * tcp: fix CONFIG_TCP_MD5SIG + CONFIG_PREEMPT timer BUG()
+  * net: Fix sock_wfree() race
+  * smsc95xx: fix transmission where ZLP is expected
+  * sky2: Set SKY2_HW_RAM_BUFFER in sky2_init
+  * appletalk: Fix skb leak when ipddp interface is not loaded
+  * ax25: Fix possible oops in ax25_make_new
+  * ax25: Fix SIOCAX25GETINFO ioctl
+  * sit: fix off-by-one in ipip6_tunnel_get_prl
+  * Linux 2.6.31.4
+  * drm/i915: Fix FDI M/N setting according with correct color depth
+    - LP: #416792
+
+  * linux (2.6.31-13.45)
+
+  [ Luke Yelavich ]
+
+  * [Config] Add sd_mod to scsi-modules udeb for powerpc
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Update to LIRC 0.8.6
+    - LP: #432678
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_X86_PAT=y
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007477.html
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007534.html
+
+  * [Config] Add armel arch to linux-libc-dev arches.
+    - LP: #449637
+
+  [ Upstream Kernel Changes ]
+
+  * e1000e: swap max hw supported frame size between 82574 and 82583
+  * drm/i915: Initialize HDMI outputs as HDMI connectors, not DVI.
+    - LP: #392017
+  * ALSA: hda - Add quirks for some HP laptops
+    - LP: #449742
+  * ALSA: hda - Add support for HP dv6
+    - LP: #449742
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 12 Oct 2009 11:27:10 -0600
+
+  * linux (2.6.31-13.44)
+
+  [ Upstream Kernel Changes ]
+
+  * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584
+  * appletalk: Fix skb leak when ipddp interface is not loaded,
+    CVE-2009-2903
+    Note - This patch causes an ABI change in the symbol aarp_send_ddp
+    which I'm ignoring.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 13 Oct 2009 12:00:22 -0600
+
+linux-ec2 (2.6.31-301.6) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Added cpio as a build dependency.
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * [Config] Disable CONFIG_UEVENT_HELPER_PATH
+  * [Config] Enable CONFIG_USB_GADGET_DUMMY_HCD
+  * [Config] Disable Intel AGP/DRM
+
+  * Rebased against linux (2.6.31-13.43) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Upstream] acerhdf: Limit modalias matching to supported
+    boards"
+
+  [ Colin Watson ]
+
+  * Use section 'admin' rather than 'base'
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Set error code after structure initialization.
+    - LP: #427948
+  * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation
+    - LP: #446595
+
+  [ Luke Yelavich ]
+
+  * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc
+
+  [ Stefan Bader ]
+
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    (supersedes previous revert made by Andy Whitcroft)
+    - LP: #435958
+
+  * Rebased against linux (2.6.31-13.42) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * SAUCE: (drop after 2.6.31) input: Add support for filtering input
+    events
+    - LP: #430809
+  * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi
+    toggle switch press
+    - LP: #430809
+
+  [ Tim Gardner ]
+
+  * SAUCE: Raise the default console 'quiet' level to 2
+    This supresses all but critical and emergency level messages.
+    https://lists.ubuntu.com/archives/kernel-team/2009-October/007476.html
+
+  [ Upstream Kernel Changes ]
+
+  * TTY: fix typos
+  * Linux 2.6.31.3
+  * V4L/DVB (12439): cx88: add support for WinFast DTV2000H rev. J
+    - LP: #433904
+
+  * Rebased against linux (2.6.31-12.41) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT
+    The original patch failed to work for amd64.
+    - LP: #430694
+
+  [ Upstream Kernel Changes ]
+
+  * ALSA: hda - Add a white-list for MSI option
+    Upstream cherry-pick: Infrastructure support for #445580
+  * ALSA: hda - Add HP Pavilion dv4t-1300 to MSI whitelist
+    - LP: #445580
+  * ALSA: intel8x0 - Mute External Amplifier by default for Sony VAIO
+    VGN-T350P
+    - LP: #410933
+  * ALSA: intel8x0 - Mute External Amplifier by default for Sony VAIO
+    VGN-B1VP
+    - LP: #410933
+
+  * Rebased against linux (2.6.31-12.40) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros
+    - LP: #430694
+  * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915
+    - LP: #430694
+
+  [ Upstream Kernel Changes ]
+
+  * V4L/DVB (12352): gspca - vc032x: Fix mi1310_soc preview and LED
+    - LP: #310760
+
+  * Rebased against linux (2.6.31-12.39) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * install the full changelog with the binary package
+  * changelog -- explicitly note rebases and clean history
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (drop after 2.6.31) Disable iwl-1000 series wireless
+    adapters"
+  * Revert "SAUCE: (drop after 2.6.31) eCryptfs: Prevent lower dentry from
+    going negative during unlink"
+  * Revert "SAUCE: (drop after 2.6.31) em28xx: ir-kbd-i2c init data needs a
+    persistent object"
+  * Revert "SAUCE: (drop after 2.6.31) saa7134: ir-kbd-i2c init data needs
+    a persistent object"
+  * Revert "drm/i915: Check that the relocation points to within the
+    target"
+  * Revert "drm/i915: fix tiling on IGDNG"
+  * Revert "Driver core: add new device to bus's list before probing"
+  * Revert "HID: completely remove apple mightymouse from blacklist"
+  * Revert "KVM: x86: check for cr3 validity in ioctl_set_sregs"
+
+    All reverts superseded by corresponding v2.6.31.2 patches
+
+  * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules
+    - LP: #439456
+  * [Config] Enabled CONFIG_SND_HDA_HWDEP
+    - LP: #443117
+  * [Config] Add cpio as a build dependency.
+  * [Config] Set default I/O scheduler back to CFQ for desktop flavours
+    - LP: #381300
+
+  [ Upstream Kernel Changes ]
+
+  * KVM: VMX: Fix EPT with WP bit change during paging
+  * pata_amd: do not filter out valid modes in nv_mode_filter
+  * p54usb: add Zcomax XG-705A usbid
+  * x86: Increase MIN_GAP to include randomized stack
+  * serial: bfin_5xx: fix building as module when early printk is enabled
+  * USB: option.c Add support for ZTE AC2726 EVDO modem
+  * USB: option: TELIT UC864G support
+  * video: s3c_fb.c: fix build with CONFIG_HOTPLUG=n
+  * kbuild: fix cc1 options check to ensure we do not use -fPIC when
+    compiling
+  * drivers/mfd/ab3100-core.c: fix powerpc build error
+  * thinkpad-acpi: don't ask about brightness_mode for fw. 1V and 1R
+  * ACPI: pci_slot.ko wants a 64-bit _SUN
+  * fbcon: only unbind from console if successfully registered
+  * kallsyms: fix segfault in prefix_underscores_count()
+  * sisfb: change SiS_DDC_Port type to SISIOADDRESS
+  * mmc_spi: fail gracefully if host or card do not support the switch
+    command
+  * alpha: AGP update (fixes compile failure)
+  * fs: make sure data stored into inode is properly seen before unlocking
+    new inode
+  * eCryptfs: Handle unrecognized tag 3 cipher codes
+  * eCryptfs: Check for O_RDONLY lower inodes when opening lower files
+  * eCryptfs: Filename encryption only supports password auth tokens
+  * eCryptfs: Validate global auth tok keys
+  * eCryptfs: Prevent lower dentry from going negative during unlink
+  * Re-enable Lanman security
+  * xen: make -fstack-protector work under Xen
+  * xen: only enable interrupts while actually blocking for spinlock
+  * xen: use stronger barrier after unlocking lock
+  * xen: check EFER for NX before setting up GDT mapping
+  * perf_counter: Fix perf_copy_attr() pointer arithmetic
+  * perf tools: Fix buffer allocation
+  * tty: serial/pcmcia: add ID for Advantech card
+  * PM / PCMCIA: Drop second argument of pcmcia_socket_dev_suspend()
+  * PM / yenta: Fix cardbus suspend/resume regression
+  * sony-laptop: check for rfkill hard block at load time
+  * nilfs2: fix missing zero-fill initialization of btree node cache
+  * ar9170usb: add usbid for TP-Link TL-WN821N v2
+  * mtd: nand: fix ECC Correction bug for SMC ordering for NDFC driver
+  * mtd: ofpart: Check availability of reg property instead of name
+    property
+  * mtd: cfi_cmdset_0002: add 0xFF intolerance for M29W128G
+  * USB: serial: ftdi_sio: new hardware support - hameg power supply
+  * USB: add PIDs for FTDI based OpenDCC hardware
+  * USB: serial: ftdi: handle gnICE+ JTAG adaptors
+  * USB: CDC WDM driver doesn't support non-blocking reads
+  * USB: fix cdc-acm regression in open
+  * cdc_acm: Fix to use modern speed interfaces
+  * tty: remove dtr/rts use from the driver open methods
+  * tty: gigaset: really fix chars_in_buffer
+  * kaweth: Fix memory leak in kaweth_control()
+  * x86: SGI UV: Fix IPI macros
+  * USB: serial: pl2303: new hardware support - sanwa multimeter
+  * USB: storage: fix a resume path GFP_NOIO must be used
+  * USB: usb-storage fails to attach to Huawei Datacard cdrom device
+  * USB: usbtmc: sanity checks for DEV_DEP_MSG_IN urbs
+  * USB: sl811-hcd: Fix device disconnect:
+  * drm/i915: remove restore in resume
+  * drm/i915: Only destroy a constructed mmap offset
+  * drm/i915: prevent FIFO calculation overflows on 32 bits with high
+    dotclocks
+  * drm/i915: Add buffer to inactive list immediately during fault
+  * drm/i915: Check that the relocation points to within the target
+  * drm/i915: Fix typo for wrong LVDS clock setting on IGDNG
+  * drm/i915: Fix SSC frequence for IGDNG
+  * drm/i915: Remove DAC disable in CRT force detect on IGDNG
+  * drm/i915: Fix LVDS panel fitting on Arrandale
+  * drm/I915: Use the CRT DDC to get the EDID for DVI-connector on Mac
+  * drm/i915: fix tiling on IGDNG
+  * agp/intel: Fix the pre-9xx chipset flush.
+  * nfsd4: fix null dereference creating nfsv4 callback client
+  * can: fix NOHZ local_softirq_pending 08 warning
+  * ahci: restore pci_intx() handling
+  * pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume
+  * net ax25: Fix signed comparison in the sockopt handler
+  * net: Make the copy length in af_packet sockopt handler unsigned
+  * pty_write: don't do a tty_wakeup() when the buffers are full
+  * KVM: fix cpuid E2BIG handling for extended request types
+  * KVM: MMU: fix missing locking in alloc_mmu_pages
+  * KVM: MMU: fix bogus alloc_mmu_pages assignment
+  * KVM: Protect update_cr8_intercept() when running without an apic
+  * Fix NULL ptr regression in powernow-k8
+  * perf tools: do not complain if root is owning perf.data
+  * netfilter: nf_nat: fix inverted logic for persistent NAT mappings
+  * netfilter: nf_conntrack: netns fix re reliable conntrack event delivery
+  * netfilter: bridge: refcount fix
+  * netfilter: ebt_ulog: fix checkentry return value
+  * ath5k: Wakeup fixes
+  * ath5k: do not release irq across suspend/resume
+  * Driver core: add new device to bus's list before probing
+  * tty: Add a full port_close function
+  * tty: USB hangup is racy
+  * tty: USB can now use the shutdown method for kref based freeing of
+    ports
+  * hwmon: (asus_atk0110) Add maintainer information
+  * tty: USB serial termios bits
+  * usb-serial: change referencing of port and serial structures
+  * usb-serial: put subroutines in logical order
+  * usb-serial: change logic of serial lookups
+  * usb-serial: acquire references when a new tty is installed
+  * usb-serial: fix termios initialization logic
+  * usb-serial: rename subroutines
+  * usb-serial: add missing tests and debug lines
+  * usb-serial: straighten out serial_open
+  * USB serial: update the console driver
+  * USB: xhci: Work around for chain bit in link TRBs.
+  * USB: xhci: Fix slot and endpoint context debugging.
+  * USB: xhci: Configure endpoint code refactoring.
+  * USB: xhci: Set correct max packet size for HS/FS control endpoints.
+  * USB: xhci: Support full speed devices.
+  * USB: xhci: Handle stalled control endpoints.
+  * USB: xhci: Add quirk for Fresco Logic xHCI hardware.
+  * USB: xhci: Make TRB completion code comparison readable.
+  * USB: xhci: Handle babbling endpoints correctly.
+  * USB: xhci: Don't touch xhci_td after it's freed.
+  * USB: xhci: Check URB's actual transfer buffer size.
+  * USB: xhci: Check URB_SHORT_NOT_OK before setting short packet status.
+  * USB: xhci: Set -EREMOTEIO when xHC gives bad transfer length.
+  * USB: xhci: Support interrupt transfers.
+  * USB: Fix SS endpoint companion descriptor parsing.
+  * /proc/kcore: work around a BUG()
+  * hugetlb: restore interleaving of bootmem huge pages (2.6.31)
+  * page-allocator: limit the number of MIGRATE_RESERVE pageblocks per zone
+  * mm: munlock use follow_page
+  * mm: fix anonymous dirtying
+  * mmap: avoid unnecessary anon_vma lock acquisition in vma_adjust()
+  * Fix idle time field in /proc/uptime
+  * drm/i915: Handle ERESTARTSYS during page fault
+  * em28xx: ir-kbd-i2c init data needs a persistent object
+  * saa7134: ir-kbd-i2c init data needs a persistent object
+  * powerpc/8xx: Fix regression introduced by cache coherency rewrite
+  * powerpc: Fix incorrect setting of __HAVE_ARCH_PTE_SPECIAL
+  * HID: completely remove apple mightymouse from blacklist
+  * mptsas : PAE Kernel more than 4 GB kernel panic
+  * NOMMU: Fix MAP_PRIVATE mmap() of objects where the data can be mapped
+    directly
+  * iwlwifi: Handle new firmware file with ucode build number in header
+  * iwlwifi: update 1000 series API version to match firmware
+  * iwlagn: modify digital SVR for 1000
+  * iwlwifi: traverse linklist to find the valid OTP block
+  * iwlwifi: fix unloading driver while scanning
+  * Linux 2.6.31.2
+
+  * Rebased against linux (2.6.31-11.38) karmic; urgency=low
+
+  [ Stefan Bader ]
+
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    - LP: #435958
+
+  [ Tim Gardner ]
+
+  * [Config] Added sata_via to d-i/modules/sata-modules
+    - LP: #434827
+  * SAUCE: (drop after 2.6.31) Disable iwl-1000 series wireless adapters
+    - LP: #439285
+  * [Upstream] i915: Fix i2c init message
+    - LP: #409361
+  * [Config] Add sym53c8xx.ko to virtual sub-flavour
+    - LP: #439415
+
+  [ Upstream Kernel Changes ]
+
+  * sched: Disable NEW_FAIR_SLEEPERS for now
+    - LP: #436342
+
+  * ACPI video: ignore buggy _BQC
+  * ACPI video: work-around BIOS AML bug in _BQC
+    - LP: #428910
+  * ALSA: hda - Added quirk to enable sound on Toshiba NB200
+    - LP: #438318
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 09 Oct 2009 10:42:15 -0600
+
+linux-ec2 (2.6.31-300.5) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Fix header package names and dependencies
+    - LP: #437784
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 30 Sep 2009 08:07:32 -0600
+
+linux-ec2 (2.6.31-300.4) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Disable Lenovo laptop config
+  * Rebase against master Ubuntu-2.6.31-11.37
+
+  [ Upstream Kernel Changes ]
+
+  * n_tty: honor opost flag for echoes
+  * n_tty: move echoctl check and clean up logic
+    - LP: #438310
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 28 Sep 2009 22:15:20 -0600
+
+linux-ec2 (2.6.31-300.3) karmic; urgency=low
+
+  [ Chuck Short ]
+
+  * SAUCE: ec2: Default domU console to tty.
+    - LP: #431103
+
+  [ Tim Gardner ]
+
+  * [Config] Remove dependency on wireless-crda
+    - LP: #434755
+  * [Config] Drop bootloaders as a recommendation
+    - LP: #434755
+  * [Config] Drop virtual sub flavours
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 25 Sep 2009 15:18:34 -0600
+
+linux-ec2 (2.6.31-300.2) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Use gawk in xen makefiles
+  * [Config] CONFIG_DMI=n for XEN_UNPRIVILEGED_GUEST
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 22:54:48 -0600
+
+linux-ec2 (2.6.31-300.1) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * Revert "[Config] Let lenovo-sl-laptop build"
+  * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32"
+  * [Config] Initial EC2 commit
+  * [Config] Removed ports
+  * [Config] Removed lpia
+  * [Config] Settled on the single EC2 flavour
+  * [Config] Disable udebs
+  * SAUCE: Prepare swap.h for Xen patches
+  * SAUCE: Xen 3.02
+  * [Config] Target vmlinuz
+  * [Config] Build with correct arch
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "PCI SR-IOV: correct broken resource alignment calculations"
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 20:31:57 -0600
+
+linux-ec2 (2.6.31-300.0) karmic; urgency=low
+
+  * Dummy entry
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 08 Sep 2009 20:31:57 -0600
+
+linux (2.6.31-10.30) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Enable CONFIG_USB_DEVICEFS
+    - LP: #417748
+  * [Config] Populate the config-update template a bit more
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.31-rc9
+  * [Config] update configs following rebase to v2.6.31-rc9
+  * [Config] update ports configs following rebase to v2.6.31-rc9
+
+  [ Colin Ian King ]
+
+  * SAUCE: wireless: hostap, fix oops due to early probing interrupt
+    - LP: #254837
+
+  [ Jerone Young ]
+
+  * [Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux)
+    white-list
+    - LP: #281732
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix profile attachment for regexp based profile names
+    - LP: #419308
+  * SAUCE: AppArmor: Return the correct error codes on profile
+    addition/removal
+    - LP: #408473
+  * SAUCE: AppArmor: Fix OOPS in profile listing, and display full list
+    - LP: #408454
+  * SAUCE: AppArmor: Fix mapping of pux to new internal permission format
+    - LP: #419222
+  * SAUCE: AppArmor: Fix change_profile failure
+    - LP: #401931
+  * SAUCE: AppArmor: Tell git to ignore generated include files
+    - LP: #419505
+
+  [ Stefan Bader ]
+
+  * [Upstream] acpi: video: Loosen strictness of video bus detection code
+    - LP: #333386
+  * SAUCE: Remove ov511 driver from ubuntu subdirectory
+
+  [ Tim Gardner ]
+
+  * [Config] Exclude char-modules from non-x86 udeb creation
+  * SAUCE: Notify the ACPI call chain of AC events
+  * [Config] CONFIG_SATA_VIA=m
+    - LP: #403385
+  * [Config] Build in all phylib support modules.
+  * [Config] Don't fail when sub-flavour files are missing
+    - LP: #423426
+  * [Config] Set CONFIG_LSM_MMAP_MIN_ADDR=0
+    - LP: #423513
+
+  [ Upstream ]
+
+  * Rebased against v2.6.31-rc9
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 07 Sep 2009 11:33:45 +0100
+
+linux (2.6.31-9.29) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] agp/intel: support for new chip variant of IGDNG mobile
+    - LP: #419993
+  * [Config] d-i/modules: Add new char-modules file, initialize with
+    intel-agp
+    - LP: #420605
+
+  [ Upstream ]
+
+  * Rebased against 2.6.31-rc8 plus some inotify regression patches:
+    up through git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+    adda766193ea1cf3137484a9521972d080d0b7af.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 28 Aug 2009 06:31:30 -0600
+
+linux (2.6.31-8.28) karmic; urgency=low
+
+  [ Ike Panhc ]
+
+  * [Config] Let nic-shared-modules depends on crypto-modules
+    - LP: #360966
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] (drop after 2.6.31) drm/i915: increase default latency
+    constant
+    - LP: #412492
+
+  [ Mario Limonciello ]
+
+  * [Upstream]: (drop after 2.6.31) dell-laptop: don't change softblock
+    status if HW switch is disabled
+    - LP: #418721
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Add support for known
+    Compal made Dell laptops
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Replace sysfs support
+    with rfkill support
+
+  [ Tim Gardner ]
+
+  * [Config] Add acpiphp to virtual sub-flavour
+    - LP: #364916
+  * Drop KSM patch set for now because of instabilities with encrypted swap.
+    - LP: #418781
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 26 Aug 2009 08:14:26 -0600
+
+linux (2.6.31-7.27) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] updateconfigs updateportsconfigs after 2.6.31-rc7 rebase
+  * SAUCE: (drop after 2.6.31) Added KSM from mmotm-2009-08-20-19-18
+    Replaces previous ksm patches from 2.6.31-6.25
+  * [Config] KSM=y
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 22 Aug 2009 20:32:11 -0600
+
+linux (2.6.31-6.26) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] enable CONFIG_AUFS_BR_RAMFS
+    - LP: #414738
+  * split out debian directory ready for abstraction
+  * add printdebian target to find branch target
+  * abstracted debian -- debian/files is not abstracted
+  * abstracted debian -- packages must be built in debian/<pkg>
+  * abstracted debian -- kernel-wedge needs to work in debian/
+  * abstracted debian -- ensure we install the copyright file
+  * abstracted-debian -- drop the debian directories from headers
+  * abstracted-debian -- drop the debian directories from headers part 2
+  * SAUCE: ubuntu-insert-changes -- follow abstracted debian
+  * [Upstream] aoe: ensure we initialise the request_queue correctly V2
+    - LP: #410198
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Disable CONFIG_CPU_FREQ_DEBUG on powerpc-smp
+  * [Config] Ports: Re-enable windfarm modules on powerpc64-smp
+    - LP: #413150
+  * [Config] Ports: Build all cpu frequency scaling governors into ports
+    kernels
+  * [Config] Ports: Build ext2 and ext3 modules into ports kernels
+  * [Config] Ports: CONFIG_PACKET=y for all ports kernels
+  * [Config] Ports: Enable PS3 network driver
+
+  [ Stefan Bader ]
+
+  * abstracted debian -- call $(DEBIAN)/rules using make
+
+  [ Tim Gardner ]
+
+  * [Config] Abstract the debian directory
+  * SAUCE: Improve error reporting in postinst
+    - LP: #358564
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 16 Aug 2009 20:33:28 -0600
+
+linux (2.6.31-6.25) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * script to generate Ubuntu changes from changelog
+  * [Config] standardise ANDROID options
+  * [Config] standardise CONFIG_ATM as module
+  * [Config] standardise CONFIG_LIB80211 as module
+  * [Config] disable CONFIG_PRINT_QUOTA_WARNING
+  * [Config] set CONFIG_CRAMFS as module
+  * [Config] enable CONFIG_DAB and modules
+  * [Config] set CONFIG_MAC80211_HWSIM as module
+  * [Config] set CONFIG_NET_CLS_FLOW as module
+  * [Config] set CONFIG_NF_CONNTRACK_SANE as module
+  * [Config] set CONFIG_NF_CT_PROTO_DCCP as module
+  * [Config] set CONFIG_RTC_DRV_DS1511 as module
+  * [Config] set CONFIG_RTC_DRV_R9701 as module
+  * [Config] set CONFIG_RTC_DRV_S35390A as module
+  * [Config] set CONFIG_TOIM3232_DONGLE as module
+  * [Config] standardise CONFIG_USB_MIDI_GADGET as module
+  * [Config] standardise CONFIG_USB_G_PRINTER as module
+  * [Config] standardise CONFIG_USB_SERIAL_IR as module
+  * [Config] set CONFIG_USB_SERIAL_IUU as module
+  * [Config] standardise CONFIG_USB_STORAGE_CYPRESS_ATACB as module
+  * [Config] standardise CONFIG_USB_STORAGE_ONETOUCH as module
+  * cleanup remains of dm-loop
+  * drop thinkpad ec and smapi support
+  * drop appleir
+  * [Config] update configs following rebase to v2.6.31-rc6
+
+  [ Hugh Dickins ]
+
+  * SAUCE: ksm patch 1, drop after 2.6.31
+  * SAUCE: ksm patch 2, drop after 2.6.31
+  * SAUCE: ksm patch 3, drop after 2.6.31
+  * SAUCE: ksm patch 4, drop after 2.6.31
+  * SAUCE: ksm patch 5, drop after 2.6.31
+  * SAUCE: ksm patch 7, drop after 2.6.31
+
+  [ Izik Eidus ]
+
+  * SAUCE: ksm patch 0, drop after 2.6.31
+  * SAUCE: ksm patch 6, drop after 2.6.31
+  * SAUCE: ksm patch 8, drop after 2.6.31
+  * SAUCE: ksm patch 9, drop after 2.6.31
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Re-add PS3 modules to udebs
+
+  [ Michael Casadevall ]
+
+  * [Config] Update SPARC config and d-i files to reflect what can be built
+
+  [ Tim Gardner ]
+
+  * [Config] Removed armel package support
+  * [Config] Enabled CONFIG_KSM=y
+
+  [ Upstream Kernel Changes ]
+
+  * ARM: Cleanup: Revert "ARM: Add more cache memory types macros"
+  * ARM: Cleanup: Revert "Do not use OOB with MLC NAND"
+  * ARM: Cleanup: Revert "ARM: Make ARM arch aware of ubuntu/ drivers"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make video capture drivers compile"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix isl29003 HWMON driver for i2c
+    changes"
+  * ARM: Cleanup: Revert "ARM: IMX51: IPU irq handler deadlock fix"
+  * ARM: Cleanup: Revert "ARM: IMX51: Babbage 2.5 needs a different system
+    revision"
+  * ARM: Cleanup: Revert "ARM: IMX51: Compile-in the IMX51 cpufreq driver
+    by default"
+  * ARM: Cleanup: Revert "ARM: IMX51: Enable ZONE_DMA for ARCH_MXC"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make ARCH_MXC auto-enable
+    ARCH_MXC_CANONICAL"
+  * ARM: Cleanup: Revert "ARM: IMX51: Unconditionally disable
+    CONFIG_GPIOLIB"
+  * ARM: Cleanup: Revert "ARM: IMX51: Minimal changes for USB to work on
+    2.6.31"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix plat-mxc/timer.c to handle imx51"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make it compile."
+  * ARM: Cleanup: Revert "ARM: IMX51: Clean-up the craziness of including
+    mxc_uart.h _everywhere_"
+  * ARM: Cleanup: Revert "ARM: IMX51: Move board-mx51* header files to the
+    correct location"
+  * ARM: Cleanup: Revert "ARM: IMX51: Changed from snd_card_new to
+    snd_card_create"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix up merge error in Kconfig"
+  * ARM: Cleanup: Revert "ARM: IMX51: mxc_timer_init prototype"
+  * ARM: Cleanup: Revert "ARM: IMX51: Removed the mxc_gpio_port structure."
+  * ARM: Cleanup: Revert "ARM: IMX51: Added external declaration for
+    mxc_map_io."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: snd_soc_machine structure replaced
+    with snd_soc_card."
+  * ARM: Cleanup: Revert "ARM: IMX51: codec structure was moved to the card
+    structure"
+  * ARM: Cleanup: Revert "ARM: IMX51: Hack to add defines for
+    DMA_MODE_READ/WRITE/MASK"
+  * ARM: Cleanup: Revert "ARM: IMX51: Add SoC and board support for
+    Freescale mx51 platform"
+  * Driver core: add new device to bus's list before probing
+  * [Upstream] (drop after 2.6.31) ALSA: hda - Reduce click noise at
+    power-saving
+    - LP: #381693, #399750, #380892
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 14 Aug 2009 11:32:23 +0100
+
+linux (2.6.31-5.24) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Make video capture drivers compile
+  * [Config] IMX51: Config updates
+
+  [ Andy Whitcroft ]
+
+  * remove leftovers of dm-bbr
+
+  [ Leann Ogasawara ]
+
+  * Add pata_cs5535 to pata-modules
+    - LP: #318805
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_PPC64=y for powerpc64-smp
+  * [Config] Set the maximum number of CPUs to 1024 for powerpc64-smp
+  * [Config] CONFIG_PPC_PS3=y for powerpc64-smp
+  * [Config] CONFIG_PPC_MAPLE=y on powerpc64-smp
+  * [Config] CONFIG_PPC_PASEMI=y on powerpc64-smp
+  * [Config] CONFIG_CPU_FREQ_PMAC64=y on powerpc64-smp
+  * [Config] Enable all PS3 drivers in powerpc64-smp
+
+  [ Mario Limonciello ]
+
+  * LIRC -- fix lirc-i2c 2.6.31 compilation
+
+  [ Matthew Garrett ]
+
+  * [Upstream] dell-laptop: Fix rfkill state queries
+
+  [ Tim Gardner ]
+
+  * [Config] Ignore armel ABI and module changes
+  * [Config] Update configs after rebase against 2.6.31-rc5
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 28 Jul 2009 10:10:09 +0100
+
+linux (2.6.31-4.23) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * AUFS -- update to aufs2-30 20090727
+  * [Config] enable AUFS FUSE support
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_JFS_FS=m on sparc
+
+  [ Tim Gardner ]
+
+  * [Upstream] dell-laptop: Fix rfkill state setting.
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 27 Jul 2009 11:11:47 +0100
+
+linux (2.6.31-4.22) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Add SoC and board support for Freescale mx51 platform
+  * ARM: IMX51: Move board-mx51* header files to the correct location
+  * ARM: IMX51: Clean-up the craziness of including mxc_uart.h _everywhere_
+  * ARM: IMX51: Make it compile.
+  * ARM: IMX51: Unconditionally disable CONFIG_GPIOLIB
+  * ARM: IMX51: Make ARCH_MXC auto-enable ARCH_MXC_CANONICAL
+  * ARM: IMX51: Enable ZONE_DMA for ARCH_MXC
+  * ARM: IMX51: Compile-in the IMX51 cpufreq driver by default
+  * ARM: IMX51: Fix isl29003 HWMON driver for i2c changes
+  * ARM: USB: musb: Refer to musb_otg_timer_func under correct #ifdef
+  * ARM: staging: udlfb: Add vmalloc.h include
+  * UBUNTU [Config]: Bring imx51 config upto date with other flavours
+
+  [ Brad Figg ]
+
+  * ARM: IMX51: Hack to add defines for DMA_MODE_READ/WRITE/MASK
+  * ARM: IMX51: codec structure was moved to the card structure
+  * ARM: IMX51: snd_soc_machine structure replaced with snd_soc_card.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Added external declaration for mxc_map_io.
+  * ARM: IMX51: Removed the mxc_gpio_port structure.
+  * ARM: IMX51: mxc_timer_init prototype
+  * ARM: IMX51: Fix up merge error in Kconfig
+  * ARM: IMX51: Changed from snd_card_new to snd_card_create
+
+  [ Dinh Nguyen ]
+
+  * ARM: IMX51: Fix plat-mxc/timer.c to handle imx51
+  * ARM: IMX51: Minimal changes for USB to work on 2.6.31
+  * ARM: IMX51: Babbage 2.5 needs a different system revision
+  * ARM: IMX51: IPU irq handler deadlock fix
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CONFIG_CAN=m
+    - LP: #327243
+  * [Config] Enabled CONFIG_SERIAL=m
+    - LP: #397189
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 24 Jul 2009 06:19:10 -0600
+
+linux (2.6.31-4.21) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * dm-raid-4-5: Add missing brackets around test_bit()
+
+  [ John Johansen ]
+
+  * AppArmor: Fix change_profile failing lpn401931
+  * AppArmor: Fix determination of forced AUDIT messages.
+  * AppArmor: Fix oops in auditing of the policy interface offset
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 19:18:30 +0100
+
+linux (2.6.31-4.20) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: iscsitarget -- update to SVN revision r214
+  * SAUCE: iscsitarget -- renable driver
+  * [Config] consolidate lpia/lpia and i386/generic configs
+  * [Config] enable CRYPTO modules for all architectures
+  * [Config] enable cryptoloop
+  * [Config] enable various filesystems for armel
+  * [Config] sync i386 generic and generic-pae
+  * [Config] add the 386 (486 processors and above) flavour
+  * [Config] re-set DEFAULT_MMAP_MIN_ADDR
+    - LP: #399914
+  * add genconfigs/genportsconfigs to extract the built configs
+  * updateconfigs -- alter concatenation order allow easier updates
+  * intelfb -- INTELFB now conflicts with DRM_I915
+  * printchanges -- rebase tree does not have stable tags use changelog
+  * AppArmor: fix argument size missmatch on 64 bit builds
+
+  [ Ike Panhc ]
+
+  * Ship bnx2x firmware in nic-modules udeb
+    - LP: #360966
+
+  [ Jeff Mahoney ]
+
+  * AppArmor: fix build failure on ia64
+
+  [ John Johansen ]
+
+  * AppArmour: ensure apparmor enabled parmater is off if AppArmor fails to
+    initialize.
+  * AppArmour: fix auditing of domain transitions to include target profile
+    information
+  * AppArmor: fix C99 violation
+  * AppArmor: revert reporting of create to write permission.
+  * SAUCE: Add config option to set a default LSM
+  * [Config] enable AppArmor by default
+  * AppArmor: Fix NULL pointer dereference oops in profile attachment.
+
+  [ Keith Packard ]
+
+  * SAUCE: drm/i915: Allow frame buffers up to 4096x4096 on 915/945 class
+    hardware
+    - LP: #351756
+
+  [ Luke Yelavich ]
+
+  * [Config] add .o files found in arch/powerpc/lib to all powerpc kernel
+    header packages
+    - LP: #355344
+
+  [ Michael Casadevall ]
+
+  * [Config] update SPARC config files to allow success build
+
+  [ Scott James Remnant ]
+
+  * SAUCE: trace: add trace_event for the open() syscall
+
+  [ Stefan Bader ]
+
+  * SAUCE: jfs: Fix early release of acl in jfs_get_acl
+    - LP: #396780
+
+  [ Tim Gardner ]
+
+  * [Upstream] Fix Soltech TA12 volume hotkeys not sending key release
+    - LP: #397499
+  * [Upstream] USB Option driver - Add USB ID for Novatel MC727/U727/USB727
+    refresh
+    - LP: #365291
+  * [Config] SSB/B44 are common across all arches/flavours.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc4
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 08:41:39 +0100
+
+linux (2.6.31-3.19) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Config] Disabled NDISWRAPPER"
+  * ndiswrapper -- fix i386 compilation failures on cmpxchg8b
+  * AUFS -- export various core functions
+  * AUFS -- export various core functions -- fixes
+  * AUFS -- core filesystem
+  * AUFS -- track changes in v2.6.31
+  * [Config] Enable AUFS
+  * droppped 'iwl3945: do not send scan command if channel count zero' as it
+    is already upstream but failed to auto-drop on rebase.
+
+  [ Eric Paris ]
+
+  * SAUCE: fsnotify: use def_bool in kconfig instead of letting the user
+    choose
+  * SAUCE: inotify: check filename before dropping repeat events
+  * SAUCE: fsnotify: fix inotify tail drop check with path entries
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 14 Jul 2009 12:52:55 +0100
+
+linux (2.6.31-3.18) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "Add splice-2.6.23.patch from AUFS to export a symbol needed by
+    AUFS"
+  * Revert "Add put_filp.patch from AUFS to export a symbol needed by AUFS"
+  * Revert "Add sec_perm-2.6.24.patch from AUFS - export
+    security_inode_permission"
+  * clear out left over AUFS files and modifications
+
+  [ Luke Yelavich ]
+
+  * [Config] Enable CONFIG_USB_ISP116X_HCD on sparc
+  * SAUCE: Explicitly include header files to allow apparmor to build on
+    powerpc
+  * [Config] Enable CONFIG_BLK_DEV_IDECD on powerpc
+
+  [ Tim Gardner ]
+
+  * [Config] Dropped ubuntu/misc/wireless/acx
+  * [Config] Disabled NDISWRAPPER until the compile issues are fixed.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc3
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 18:59:33 +0100
+
+linux (2.6.31-2.17) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_BLK_DEV_CRYPTOLOOP=m for sparc
+  * compcache -- remove redundant Kconfig entries part 2
+  * compcache -- clean up CCFLAGS declarations
+  * [Config] enable AppArmor
+  * AppArmor: fix operator precidence issue in as_path_link
+
+  [ John Johansen ]
+
+  * AppArmor security module
+  * AppArmor: Correct mapping of file permissions.
+  * AppArmor: Turn auditing of ptrace on
+
+  [ Luke Yelavich ]
+
+  * [Config] disable CONFIG_DM_RAID45 on powerpc
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 15:02:05 +0100
+
+linux (2.6.31-2.16) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * compcache -- remove redundant Kconfig entries
+    added ignore and ignore.modules for all arches since the compcache update
+    changes the modules names as well as some compcache ABI values.
+
+  [ Manoj Iyer ]
+
+  * SAUCE: updated dm-raid45 module version to 2009.04.24 (2.6.30-rc3)
+  * SAUCE: update compcache version to 0.5.3
+
+  [ Tim Gardner ]
+
+  * [Config]: Fix sparc FTBS by adding ignore.modules
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 06 Jul 2009 13:35:29 -0600
+
+linux (2.6.31-2.15) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: default ATI Radeon KMS to off until userspace catches up
+  * [Config] Update configs following rebase to 2.6.31-rc2
+  * [Config] update ports configs following update to 2.6.31-rc2
+
+  [ Luke Yelavich ]
+
+  * [Config] powerpc - Disable CONFIG_RDS
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to mainline 2.6.31-rc2
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 04 Jul 2009 17:39:13 +0100
+
+linux (2.6.31-1.14) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update ndiswrapper to 1.55
+  * remove leftovers of gfs
+  * [Config] powerpc: enable CONFIG_PPC_DISABLE_WERROR
+
+  [ Luke Yelavich ]
+
+  * [Config] re-enable and build the ide-pmac driver into powerpc kernels
+  * [Config] Build the ServerWorks Frodo / Apple K2 SATA driver into the
+    kernel
+
+  [ Manoj Iyer ]
+
+  * Remove snd-bt-sco ubuntu driver
+
+  [ Michael Casadevall ]
+
+  * [Config] updates ia64 config and d-i folders to allow succesful build
+  * [Config] Update powerpc and sparc for 2.6.31
+
+  [ Upstream Kernel Changes ]
+
+  * intel-iommu: fix Identity Mapping to be arch independent
+    - LP: #384695
+  * ACPI: video: prevent NULL deref in acpi_get_pci_dev()
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 30 Jun 2009 17:47:32 +0100
+
+linux (2.6.31-1.13) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * REBASE: rebased to mainline 2.6.31-rc1
+    - "UBUNTU: SAUCE: UHCI USB quirk for resume"
+      no longer applies, using deprecated interfaces, LPIA only, dropped
+    - "UBUNTU: SAUCE: Mask off garbage in Dell WMI scan code data"
+      changes now upstream, dropped
+  * [Config] Update configs following rebase to 2.6.31-rc1
+  * [Config] update ports configs following update to 2.6.31-rc1
+
+  * [Config] disable broken staging driver CONFIG_STLC45XX
+  * SAUCE: fix compcache to use updates accessors
+  * [Config] disable staging driver CONFIG_VT6655
+  * SAUCE: fix DRDB to use updates accessors
+  * [Disable] ndiswrapper needs update
+  * [Disable] LIRC I2C needs update
+  * [Disable] CONFIG_LENOVO_SL_LAPTOP needs update
+  * [Config] disable I2C_DESIGNWARE does not compile
+  * [Config] disable CONFIG_TLSUP for lpia
+  * [Config] disable CONFIG_FB_UDL for arm
+  * SAUCE: disable adding scsi headers to linux-libc-dev
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Add LIRC drivers
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 25 Jun 2009 12:06:22 +0100
+
+linux (2.6.30-10.12) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] split out the ports configs into their own family
+  * [Config] update configs following introduction of ports family
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "Rename linux-doc-PKGVER to linux-doc and clean up its
+    description". Fixes linux-doc package name conflicts for now.
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 22 Jun 2009 09:17:14 -0600
+
+linux (2.6.30-10.11) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Comment splitconfig.pl and misc cleanup
+  * [Config] Rename all configs to the new naming scheme
+  * [Config] Splitconfig rework
+  * [Config] Rename scripts/misc/oldconfig to kernelconfig
+  * [Config] Fix build system for new config split
+  * [Config] Run updateconfigs after the splitconfig rework
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: Default to i915.modeset=0 if CONFIG_DRM_I915_KMS=y"
+  * [Config] standardise CONFIG_STAGING=y
+  * [Config] standardise CONFIG_RD_LZMA=y
+  * [Config] CONFIG_PCI_IOV=y
+  * [Config] CONFIG_PCI_STUB=m
+  * [Config] merge kernel configs more agressively
+
+  [ Colin Watson ]
+
+  * [Config] Run kernel-wedge in $(builddir) rather than at the top level
+  * [Config] Add support for including firmware in udebs
+  * [Config] Ship bnx2 firmware in nic-modules udeb
+    - LP: #384861
+
+  [ Luke Yelavich ]
+
+  * [Config] ports - Import of ports architectures into kernel packaging
+    infrastructure
+  * [Config] ports - Do not update ports kernel configurations by default
+  * [Config] ports - Disable ABI checking for ports architectures
+  * [Config] ports - Build drivers in ubuntu sub-directory on powerpc
+  * [Config] ports - Add control.d/vars.* files for ports architectures
+  * [Config] ports - Add ports architectures for linux-libc-dev
+  * [Config] ports - Create powerpc specific message-modules and
+    block-modules udebs
+  * [Config] ports - Add configuration files for ports architectures
+
+  [ Manoj Iyer ]
+
+  * [Config] Enable CONFIG_BLK_DEV_AEC62XX=m for amd64 and i386
+    - LP: #329864
+
+  [ Michael Casadevall ]
+
+  * [Config] ports - Fix compression of kernels
+
+  [ Stefan Bader ]
+
+  * [Upstream] mmc: prevent dangling block device from accessing stale
+    queues
+    - LP: #383668
+
+  [ Tim Gardner ]
+
+  * [Config] Recommend grub-pc in linux-image
+    - LP: #385741
+  * [Config] Implement i386 generic and generic-pae flavours
+  * [Config] ports - Add control info after integrating ports arches
+  * [Config] Removed auto-generated files from git
+  * [Config] Added netxen_nic to nic-modules
+    - LP: #389603
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 15 Jun 2009 14:38:26 -0600
+
+linux (2.6.30-9.10) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_SECURITY_TOMOYO=y (amd64, i386, lpia)
+  * [Config] CONFIG_KEXEC_JUMP=y (amd64, lpia)
+  * [Config] CONFIG_LENOVO_SL_LAPTOP=m (amd64, lpia)
+  * [Config] CONFIG_POHMELFS_CRYPTO=y (i386, amd64)
+  * [Config] CONFIG_SERIAL_MAX3100=m (i386, amd64, lpia)
+  * [Config] CONFIG_VIDEO_GO7007=m (amd64, i386)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30 final
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 05 Jun 2009 11:42:53 +0100
+
+linux (2.6.30-8.9) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Config update removed the following options:
+        CONFIG_EDAC_AMD8111=m
+        CONFIG_EDAC_AMD8131=m
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc8
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 03 Jun 2009 09:21:13 +0100
+
+linux (2.6.30-7.8) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Enabled NEW configration options:
+      Paravirtualization layer for spinlocks (PARAVIRT_SPINLOCKS) [N/y/?] Y
+      Cisco FNIC Driver (FCOE_FNIC) [N/m/y/?] M
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc7
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 23 May 2009 23:47:24 +0100
+
+linux (2.6.30-6.7) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Dropped: UBUNTU: SAUCE: input: Blacklist digitizers from joydev.c (now
+    upstream)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc6
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 18 May 2009 18:05:54 +0100
+
+linux (2.6.30-5.6) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enable Keyspan USB serial device firmware in kernel module
+    - LP: #334285
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc5
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 11 May 2009 12:02:16 -0600
+
+linux (2.6.30-4.5) karmic; urgency=low
+
+  [ Colin Watson ]
+
+  * Build-Conflict with findutils (= 4.4.1-1ubuntu1), to avoid
+    /usr/include/asm/* going missing
+    - LP: #373214
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 May 2009 11:09:08 +0200
+
+linux (2.6.30-3.4) karmic; urgency=low
+
+  [ Kees Cook ]
+
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+
+  [ Stefan Bader ]
+
+  * SAUCE: input: Blacklist digitizers from joydev.c
+    - LP: #300143
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 01 May 2009 14:00:42 -0600
+
+linux (2.6.30-2.3) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CC_STACKPROTECTOR=y for all x86en
+    - LP: #369152
+  * SAUCE: Default to i915_modeset=0 if CONFIG_DRM_I915_KMS=y
+  * [Config] CONFIG_DRM_I915_KMS=y
+  * [Config] Set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR to appropriate ARCH
+    minimums
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc4
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 30 Apr 2009 09:17:05 -0600
+
+linux (2.6.30-1.2) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] armel: disable staging drivers, fixes FTBS
+  * [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS
+
+  [ Upstream Kernel Changes ]
+
+  * mpt2sas: Change reset_type enum to avoid namespace collision.
+    Submitted upstream.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 28 Apr 2009 16:54:41 -0600
+
+linux (2.6.30-1.1) karmic; urgency=low
+
+  * Initial release after rebasing against v2.6.30-rc3
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 12 Mar 2009 19:16:07 -0600
--- linux-ec2-2.6.32.orig/debian.ec2/rules
+++ linux-ec2-2.6.32/debian.ec2/rules
@@ -0,0 +1,222 @@
+#!/usr/bin/make -f
+#
+# $(DEBIAN)/rules for Ubuntu linux
+#
+# Use this however you want, just give credit where credit is due.
+#
+# Copyright (c) 2007 Ben Collins <bcollins@ubuntu.com>
+#
+
+ifeq ($(DEBIAN),)
+DEBIAN=debian.master
+endif
+
+# dpkg-buildpackage passes options that are incomptatible
+# with the kernel build.
+unexport CFLAGS
+unexport LDFLAGS
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=4
+export LC_ALL=C
+export SHELL=/bin/bash -e
+
+# Common variables for all architectures
+include $(DEBIAN)/rules.d/0-common-vars.mk
+
+# Pull in some arch specific stuff
+include $(DEBIAN)/rules.d/$(arch).mk
+
+# Maintainer targets
+include $(DEBIAN)/rules.d/1-maintainer.mk
+
+# Debian Build System targets
+binary: binary-indep binary-arch
+
+build: build-arch build-indep
+
+clean: debian/control
+	dh_testdir
+	dh_testroot
+	dh_clean
+
+	# d-i stuff
+	rm -rf $(DEBIAN)/d-i-$(arch)
+
+	# normal build junk
+	rm -rf $(DEBIAN)/abi/$(release)-$(revision)
+	rm -rf $(builddir)
+	rm -f $(stampdir)/stamp-*
+	rm -rf $(DEBIAN)/linux-*
+
+	# This gets rid of the d-i packages in control
+	cp -f $(DEBIAN)/control.stub $(DEBIAN)/control
+	cp $(DEBIAN)/changelog debian/changelog
+
+	# Install the copyright information.
+	cp $(DEBIAN)/copyright debian/copyright
+
+# Builds the image, arch headers and debug packages
+include $(DEBIAN)/rules.d/2-binary-arch.mk
+
+# Rules for building the udebs ($(DEBIAN)-installer)
+include $(DEBIAN)/rules.d/5-udebs.mk
+
+# Builds the source, doc and linux-headers indep packages
+include $(DEBIAN)/rules.d/3-binary-indep.mk
+
+# Various checks to be performed on builds
+include $(DEBIAN)/rules.d/4-checks.mk
+
+# Misc stuff
+$(DEBIAN)/control.stub: $(DEBIAN)/d-i/kernel-versions.in	\
+		$(DEBIAN)/scripts/control-create		\
+		$(DEBIAN)/control.stub.in			\
+		$(DEBIAN)/changelog			\
+		$(wildcard $(DEBIAN)/control.d/* $(DEBIAN)/sub-flavours/*.vars)
+	for i in $(DEBIAN)/d-i/kernel-versions.in $(DEBIAN)/control.stub.in; do	\
+	  new=`echo $$i | sed 's/\.in$$//'`;					\
+	  cat $$i | sed -e 's/PKGVER/$(release)/g'                              \
+	        -e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+	  > $$new;								\
+	done
+	flavours="$(wildcard $(DEBIAN)/control.d/vars.* $(DEBIAN)/sub-flavours/*.vars)";\
+	for i in $$flavours; do							\
+	  $(SHELL) $(DEBIAN)/scripts/control-create $$i |				\
+		sed -e 's/PKGVER/$(release)/g'                                  \
+		-e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+		>> $(DEBIAN)/control.stub;						\
+	done
+	cp $(DEBIAN)/control.stub $(DEBIAN)/control
+
+.PHONY: debian/control
+debian/control: $(DEBIAN)/control.stub
+	rm -rf $(builddir)/modules $(builddir)/firmware			\
+		$(builddir)/kernel-versions $(builddir)/package-list	\
+		$(builddir)/$(DEBIAN)
+	mkdir -p $(builddir)/modules/$(arch)/
+	cp $(DEBIAN)/d-i/modules/* $(builddir)/modules/$(arch)/
+	mkdir -p $(builddir)/firmware/$(arch)/
+	cp $(DEBIAN)/d-i/firmware/* $(builddir)/firmware/$(arch)/
+	cp $(DEBIAN)/d-i/package-list $(DEBIAN)/d-i/kernel-versions $(builddir)/
+	touch $(builddir)/modules/$(arch)/kernel-image
+	# kernel-wedge needs to poke around in $(DEBIAN)/
+	ln -nsf $(CURDIR)/debian $(builddir)/debian
+
+	# Some files may need to differ between architectures
+	if [ -d $(DEBIAN)/d-i/modules-$(arch) ]; then			\
+	    cp $(DEBIAN)/d-i/modules-$(arch)/* \
+		$(builddir)/modules/$(arch)/;				\
+	fi
+	if [ -d $(DEBIAN)/d-i/firmware-$(arch) ]; then			\
+	    cp $(DEBIAN)/d-i/firmware-$(arch)/* \
+		$(builddir)/firmware/$(arch)/;				\
+	fi
+
+	# Remove unwanted stuff for this architecture
+	if [ -r "$(DEBIAN)/d-i/exclude-modules.$(arch)" ]; then		\
+	    (cat $(DEBIAN)/d-i/exclude-modules.$(arch);			\
+	     ls $(builddir)/modules/$(arch)/) | sort | uniq -d |	\
+		(cd $(builddir)/modules/$(arch)/; xargs rm -f);		\
+	fi
+	if [ -r "$(DEBIAN)/d-i/exclude-firmware.$(arch)" ]; then		\
+	    (cat $(DEBIAN)/d-i/exclude-firmware.$(arch);			\
+	     ls $(builddir)/firmware/$(arch)/) | sort | uniq -d |	\
+		(cd $(builddir)/firmware/$(arch)/; xargs rm -f);	\
+	fi
+
+	# Per flavour module lists
+	flavour_modules=`ls $(DEBIAN)/d-i/modules.$(arch)-* 2>/dev/null`	\
+		|| true;						\
+	if [ "$$flavour_modules" != "" ]; then				\
+	    for flav in $$flavour_modules; do				\
+		name=`echo $$flav | sed 's/.*\/modules.$(arch)-//'`;	\
+		mkdir $(builddir)/modules/$(arch)-$$name;		\
+		(cd $(builddir)/modules/; tar cf - `cat ../$$flav`) |	\
+		    (cd $(builddir)/modules/$(arch)-$$name/; tar xf -);	\
+		touch $(builddir)/modules/$(arch)-$$name/kernel-image;	\
+	    done;							\
+	fi
+	flavour_firmware=`ls $(DEBIAN)/d-i/firmware.$(arch)-* 2>/dev/null`	\
+		|| true;						\
+	if [ "$$flavour_firmware" != "" ]; then				\
+	    for flav in $$flavour_firmware; do				\
+		name=`echo $$flav | sed 's/.*\/firmware.$(arch)-//'`;	\
+		mkdir $(builddir)/firmware/$(arch)-$$name;		\
+		(cd $(builddir)/firmware/; tar cf - `cat ../$$flav`) |	\
+		    (cd $(builddir)/firmware/$(arch)-$$name/; tar xf -);\
+		touch $(builddir)/firmware/$(arch)-$$name/kernel-image;	\
+	    done;							\
+	fi
+
+	# Some files may need to differ between flavours
+	flavour_module_dirs=`ls -d $(DEBIAN)/d-i/modules-$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_module_dirs" ]; then				\
+	    for flav in $$flavour_module_dirs; do			\
+		name=`echo $$flav | sed 's/.*\/modules-$(arch)-//'`;	\
+		[ -d $(builddir)/modules/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/modules/$(arch)			\
+			modules/$(arch)-$$name;				\
+		cp $$flav/* $(builddir)/modules/$(arch)-$$name/;	\
+	    done;							\
+	fi
+	flavour_firmware_dirs=`ls -d $(DEBIAN)/d-i/firmware-$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_firmware_dirs" ]; then				\
+	    for flav in $$flavour_firmware_dirs; do			\
+		name=`echo $$flav | sed 's/.*\/firmware-$(arch)-//'`;	\
+		[ -d $(builddir)/firmware/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/firmware/$(arch)			\
+			firmware/$(arch)-$$name;			\
+		cp $$flav/* $(builddir)/firmware/$(arch)-$$name/;	\
+	    done;							\
+	fi
+
+	# Remove unwanted stuff for each flavour
+	flavour_exclude=`ls $(DEBIAN)/d-i/exclude-modules.$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_exclude" ]; then				\
+	    for flav in $$flavour_exclude; do				\
+		name=`echo $$flav | sed 's/.*\/exclude-modules.$(arch)-//'`;\
+		[ -d $(builddir)/modules/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/modules/$(arch) 			\
+			$(builddir)/modules/$(arch)-$$name;		\
+		(cat $$flav;						\
+		 ls $(builddir)/modules/$(arch)-$$name) |		\
+		 sort |	uniq -d |					\
+		    (cd $(builddir)/modules/$(arch)-$$name/;		\
+		     xargs rm -f);					\
+	    done;							\
+	fi
+	flavour_exclude=`ls $(DEBIAN)/d-i/exclude-firmware.$(arch)-* 2>/dev/null`\
+		|| true;						\
+	if [ "$$flavour_exclude" ]; then				\
+	    for flav in $$flavour_exclude; do				\
+		name=`echo $$flav | sed 's/.*\/exclude-firmware.$(arch)-//'`;\
+		[ -d $(builddir)/firmware/$(arch)-$$name ] ||		\
+		    cp -a $(builddir)/firmware/$(arch) 			\
+			$(builddir)/firmware/$(arch)-$$name;		\
+		(cat $$flav;						\
+		 ls $(builddir)/firmware/$(arch)-$$name) |		\
+		 sort |	uniq -d |					\
+		    (cd $(builddir)/firmware/$(arch)-$$name/;		\
+		     xargs rm -f);					\
+	    done;							\
+	fi
+
+	if [ ! -d $(builddir)/modules/$(build_arch) ]; then		\
+		mkdir -p $(builddir)/modules/$(build_arch);		\
+		cp $(builddir)/modules/$(arch)/*			\
+			$(builddir)/modules/$(build_arch);		\
+	fi
+	if [ ! -d $(builddir)/firmware/$(build_arch) ]; then		\
+		mkdir -p $(builddir)/firmware/$(build_arch);		\
+		cp $(builddir)/firmware/$(arch)/*			\
+			$(builddir)/firmware/$(build_arch);		\
+	fi
+
+	cp $(DEBIAN)/control.stub debian/control.stub
+	cd $(builddir) && kernel-wedge gen-control > $(CURDIR)/debian/control
--- linux-ec2-2.6.32.orig/debian.ec2/changelog.historical
+++ linux-ec2-2.6.32/debian.ec2/changelog.historical
@@ -0,0 +1,4176 @@
+linux (2.6.30-1.1) karmic; urgency=low
+
+  * Initial release after rebasing against v2.6.30-rc3
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 12 Mar 2009 19:16:07 -0600
+
+linux (2.6.28-9.31) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: cpufreq-nforce2: probe failures are not errors
+    - LP: #332170
+  * SAUCE: mmc: add MODALIAS linkage for MMC/SD devices
+    - LP: #30335
+  * remove test-suspend script
+    - LP: #333856
+
+  [ Kees Cook ]
+
+  * handle relative paths in modules.dep
+    Fixes 2.6.28-9.30 FTBS.
+
+  [ Upstream Kernel Changes ]
+
+  * ricoh_mmc: Handle newer models of Ricoh controllers
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 11 Mar 2009 08:19:24 -0600
+
+linux (2.6.28-9.30) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM:mx51 Add SoC and board support for mx51 platforms
+  * ARM:mx51 Add CONFIG_ARCH_MXC_CANONICAL to disable parts of Freescale's
+    code
+  * MMC: Add support for 8-bit cards
+  * Add ARM:MX51 SoC support to the build system
+  * ARM: Make ARM arch aware of ubuntu/ drivers
+  * ARM: Add imx51 configuration
+  * Disable d-i modules for imx51 and mv78xx0
+  * Disable Apparmor on boot for ARM
+  * Updating imx51 config
+
+  [ Jason Liu ]
+
+  * Do not use OOB with MLC NAND
+
+  [ Richard Zhu ]
+
+  * Support the eMMC4.3 card
+
+  [ Rob Herring ]
+
+  * ARM: Add more cache memory types macros
+
+  [ Tim Gardner ]
+
+  * Set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y for i386/amd64/lpia
+
+  [ Manoj Iyer ]
+
+  * Enable CONFIG_RTL8187SE=m
+
+  [ Upstream Kernel Changes ]
+
+  * USB: EHCI: slow down ITD reuse
+    - LP: #329437
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 08 Mar 2009 14:14:15 -0600
+
+linux (2.6.28-9.29) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * link-headers -- only link directories which do not already exist
+    - LP: #315252
+
+  [ Daniel Marjamäki ]
+
+  * SAUCE: (drop after 2.6.28) netxen: fix memory leak in
+    drivers/net/netxen_nic_init.c
+    - LP: #330813
+
+  [ Dhananjay Phadke ]
+
+  * SAUCE: (drop after 2.6.28) netxen: fix endianness in firmware commands
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix ipv6 offload and tx cleanup
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix link speed reporting for some
+    boards
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: firmware init fix
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: cleanup mac list on driver unload
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: hold tx lock while sending firmware
+    commands
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: handle dma mapping failures
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: avoid invalid iounmap
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: include ipv6.h (fixes build failure)
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix vlan tso/checksum offload
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: reduce memory footprint
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: revert jumbo ringsize
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix msi-x interrupt handling
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: remove pcie workaround
+    - LP: #330813
+
+  [ Hannes Eder ]
+
+  * SAUCE: (drop after 2.6.28) drivers/net/netxen: fix sparse warnings: use
+    NULL pointer instead of plain integer
+    - LP: #330813
+
+  [ Huaxu Wan ]
+
+  * SAUCE: report rfkill changes event if interface is down
+    - LP: #193970
+
+  [ Tim Gardner ]
+
+  * MV78XX0 must specify a target in the vars definition.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "ext4: wait on all pending commits in ext4_sync_fs()"
+  * jbd2: Fix return value of jbd2_journal_start_commit()
+  * jbd2: Avoid possible NULL dereference in
+    jbd2_journal_begin_ordered_truncate()
+  * ext4: Fix to read empty directory blocks correctly in 64k
+  * ext4: Fix lockdep warning
+  * ext4: Initialize preallocation list_head's properly
+  * ext4: Implement range_cyclic in ext4_da_writepages instead of
+    write_cache_pages
+  * ext4: Fix NULL dereference in ext4_ext_migrate()'s error handling
+  * ext4: Add fallback for find_group_flex
+  * ext4: Fix deadlock in ext4_write_begin() and ext4_da_write_begin()
+  * Added mv78xx0 flavor
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 06 Mar 2009 06:13:31 -0700
+
+linux (2.6.28-8.28) jaunty; urgency=low
+
+  [ Alexey Starikovskiy ]
+
+  * SAUCE: ACPI: EC: Limit workaround for ASUS notebooks even more
+    - LP: #288385
+
+  [ Scott James Remnant ]
+
+  * SAUCE: Auto-load esp module when device opened.
+  * SAUCE: Auto-load bridge module when socket opened.
+  * SAUCE: Auto-load af_netlink module when socket opened.
+  * SAUCE: Auto-load wanrouter module when socket opened.
+  * SAUCE: Auto-load ip_queue module when socket opened.
+  * SAUCE: Auto-load ip6_queue module when socket opened.
+  * SAUCE: Auto-load cn module when socket opened.
+  * SAUCE: Auto-load scsi_transport_iscsi module when socket opened.
+  * SAUCE: Auto-load ftl module when device opened.
+  * SAUCE: Auto-load pcd module when device opened.
+  * SAUCE: Auto-load pf module when device opened.
+  * SAUCE: Auto-load nftl module when device opened.
+  * SAUCE: Auto-load mousedev module when psaux device opened.
+  * SAUCE: Auto-load mousedev module when /dev/input/mice opened.
+  * SAUCE: Auto-load rng-core module when device opened.
+  * SAUCE: Auto-load openprom module when device opened.
+  * SAUCE: Auto-load applicom module when device opened.
+  * SAUCE: Auto-load toshiba module when device opened.
+  * SAUCE: Auto-load cyclades module when device opened.
+  * SAUCE: Auto-load riscom8 module when device opened.
+  * SAUCE: Auto-load specialix module when device opened.
+  * SAUCE: Auto-load videodev module when device opened.
+  * SAUCE: Auto-load i2c_dev module when device opened.
+  * SAUCE: Auto-load mtdchar module when device opened.
+  * SAUCE: Auto-load pt module when device opened.
+  * SAUCE: Auto-load pg module when device opened.
+  * SAUCE: Auto-load cdc_acm module when device opened.
+  * SAUCE: Auto-load msr module when device opened.
+  * SAUCE: Auto-load cpuid module when device opened.
+  * SAUCE: quickcam: Enable double-buffering by default
+  * SAUCE: libata: Ignore HPA by default.
+  * SAUCE: hostap: Change initial operation mode to managed (infra)
+  * SAUCE: floppy: Provide a PnP device table in the module.
+    - LP: #255651
+  * SAUCE: Auto-load mwave module when device opened.
+  * Build CONFIG_FUSE_FS into kernel, not as module.
+
+  [ Stefan Bader ]
+
+  * Enable build of ext4 as a module on LPIA
+    - LP: #331848
+
+  [ Tim Gardner ]
+
+  * Update configs to fix LPIA FTBS
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 05 Mar 2009 10:43:24 -0700
+
+linux (2.6.28-8.27) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs (arm:ixp4xx)
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: enable Intel HDMI output
+
+  [ Manoj Iyer ]
+
+  * SAUCE: Added quirk for Linksys WUSB600N USB wifi-n networking adapter
+    - LP: #323473
+
+  [ Steve Beattie ]
+
+  * fix apparmor memory leak on unlinked file ops
+    - LP: #329489
+
+  [ Tim Gardner ]
+
+  * SAUCE: Dell XPS710 reboot quirk
+    - LP: #323592
+  * SAUCE: (drop after 2.6.28) ieee80211: Add infrastructure to obsolete
+    scan results
+    - LP: #336055
+  * Add modules.order to the linux-image package.
+
+  [ Upstream Kernel Changes ]
+
+  * iwlwifi: fix time interval misuse in iwl_poll_{direct_}bit
+  * x86: only scan the root bus in early PCI quirks
+    - LP: #267295
+  * ALSA: hda - Intel HDMI audio support
+  * ALSA: hda - Fix unused function in patch_intelhdmi.c
+  * ALSA: handle SiI1392 HDMI codec in patch_intelhdmi.c
+  * ALSA: hda-intel: reorder HDMI audio enabling sequence
+  * ALSA: introduce snd_print_pcm_rates()
+  * ALSA: create hda_eld.c for ELD routines and proc interface
+  * ALSA: ELD proc interface for HDMI sinks
+  * ALSA: hda: make standalone hdmi_fill_audio_infoframe()
+  * ALSA: hda: make global snd_print_channel_allocation()
+  * ALSA: hda: HDMI channel allocations for audio infoframe
+  * ALSA: hda: HDMI channel mapping cleanups
+  * ALSA: hda: minor code cleanups
+  * ALSA: hda: rename sink_eld to hdmi_eld
+  * ALSA: hda - Release ELD proc file
+  * ALSA: hda - minor HDMI code cleanups
+  * ALSA: hda - report selected CA index for Audio InfoFrame
+  * ALSA: hda - Add Intel vendor id string
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 25 Feb 2009 14:23:46 -0700
+
+linux (2.6.28-8.26) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs (armel:ixp4xx)
+    - LP: #331510
+
+  [ Tim Gardner ]
+
+  * Add more missing modules
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 24 Feb 2009 06:58:53 -0700
+
+linux (2.6.28-8.25) jaunty; urgency=low
+
+  [ Scott James Remnant ]
+
+  * SAUCE: Prefer powernow-k8 to acpi-cpufreq
+  * Change CONFIG_X86_P4_CLOCKMOD to be a module again.
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Initialize the new
+    group descriptor when resizing the filesystem"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add sanity check
+    to make_indexed_dir"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: only use
+    i_size_high for regular files"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add sanity checks
+    for the superblock before mounting the filesystem"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix
+    s_dirty_blocks_counter if block allocation failed with nodelalloc"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Init the complete
+    page while building buddy cache"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Don't allow new
+    groups to be added during block allocation"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: mark the
+    blocks/inode bitmap beyond end of group as used"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Use new
+    buffer_head flag to check uninit group bitmaps initialization"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix the race
+    between read_inode_bitmap() and ext4_new_inode()"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix race between
+    read_block_bitmap() and mark_diskspace_used()"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: don't use blocks
+    freed but not yet committed in buddy cache init"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: cleanup mballoc
+    header files"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Use
+    EXT4_GROUP_INFO_NEED_INIT_BIT during resize"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add blocks added
+    during resize to bitmap"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Don't overwrite
+    allocation_context ac_status"
+  * Revert "SAUCE: (revert before 2.6.28.y update) jbd2: Add barrier not
+    supported test to journal_wait_on_commit_record"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Widen type of
+    ext4_sb_info.s_mb_maxs[]"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: avoid ext4_error
+    when mounting a fs with a single bg"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix the delalloc
+    writepages to allocate blocks at the right offset."
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: tone down
+    ext4_da_writepages warnings"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add support for
+    non-native signed/unsigned htree hash algorithms"
+  * Enabled X86_ACPI_CPUFREQ=y
+
+  [ Upstream Kernel Changes ]
+
+  * ath9k: quiet harmless ForceXPAon messages
+    - LP: #321474
+  * [WATCHDOG] iTCO_wdt: fix SMI_EN regression 2
+    - LP: #314050
+  * pid: implement ns_of_pid
+  * mqueue: fix si_pid value in mqueue do_notify()
+  * powerpc/vsx: Fix VSX alignment handler for regs 32-63
+  * sata_nv: give up hardreset on nf2
+  * Fix Intel IOMMU write-buffer flushing
+  * SCSI: libiscsi: fix iscsi pool leak
+  * x86/cpa: make sure cpa is safe to call in lazy mmu mode
+  * sched: SCHED_OTHER vs SCHED_IDLE isolation
+  * x86, vm86: fix preemption bug
+  * Add support for VT6415 PCIE PATA IDE Host Controller
+  * ext2/xip: refuse to change xip flag during remount with busy inodes
+  * 3c505: do not set pcb->data.raw beyond its size
+  * Bluetooth: Fix TX error path in btsdio driver
+  * ext4: Add support for non-native signed/unsigned htree hash algorithms
+  * ext4: tone down ext4_da_writepages warnings
+  * ext4: Fix the delalloc writepages to allocate blocks at the right
+    offset.
+  * ext4: avoid ext4_error when mounting a fs with a single bg
+  * ext4: Widen type of ext4_sb_info.s_mb_maxs[]
+  * jbd2: Add barrier not supported test to journal_wait_on_commit_record
+  * ext4: Don't overwrite allocation_context ac_status
+  * ext4: Add blocks added during resize to bitmap
+  * ext4: Use EXT4_GROUP_INFO_NEED_INIT_BIT during resize
+  * ext4: cleanup mballoc header files
+  * ext4: don't use blocks freed but not yet committed in buddy cache init
+  * ext4: Fix race between read_block_bitmap() and mark_diskspace_used()
+  * ext4: Fix the race between read_inode_bitmap() and ext4_new_inode()
+  * ext4: Use new buffer_head flag to check uninit group bitmaps
+    initialization
+  * ext4: mark the blocks/inode bitmap beyond end of group as used
+  * ext4: Don't allow new groups to be added during block allocation
+  * ext4: Init the complete page while building buddy cache
+  * ext4: Fix s_dirty_blocks_counter if block allocation failed with
+    nodelalloc
+  * ext4: Add sanity checks for the superblock before mounting the
+    filesystem
+  * ext4: only use i_size_high for regular files
+  * ext4: Add sanity check to make_indexed_dir
+  * ext4: Initialize the new group descriptor when resizing the filesystem
+  * Fix longstanding "error: storage size of '__mod_dmi_device_table' isn't
+    known"
+  * Linux 2.6.28.7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 19 Feb 2009 06:45:55 -0700
+
+linux (2.6.28-8.24) jaunty; urgency=low
+
+  [ Scott James Remnant ]
+
+  * Change CPU_FREQ_DEFAULT_GOV_ONDEMAND to y
+  * SAUCE: Link acpi-cpufreq.o first
+
+  [ Tim Gardner ]
+
+  * Build in CPU Frequency scaling drivers
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 18 Feb 2009 06:12:24 -0700
+
+linux (2.6.28-8.23) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * include the kernel configuration in the sub-flavour images
+    - LP: #328859
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (drop after 2.6.28) [eCryptfs] Regression in unencrypted
+    filename symlinks" in favor of upstream commit.
+  * Fix compile issues with qc-usb
+  * SAUCE: (remove after 2.6.28) V4L/DVB (10216): saa7127: fix broken
+    S-Video with saa7129
+    - LP: #329267
+
+  [ Upstream Kernel Changes ]
+
+  * Subject:SAUCE: LP#193970 iwlagn: fix hw-rfkill while the interface is
+    down
+    - LP: #193970
+  * x86, vmi: put a missing paravirt_release_pmd in pgd_dtor
+  * nbd: fix I/O hang on disconnected nbds
+  * mac80211: restrict to AP in outgoing interface heuristic
+  * w1: w1 temp calculation overflow fix
+  * zd1211rw: adding 0ace:0xa211 as a ZD1211 device
+  * zd1211rw: treat MAXIM_NEW_RF(0x08) as UW2453_RF(0x09) for TP-Link
+    WN322/422G
+  * parport: parport_serial, don't bind netmos ibm 0299
+  * syscall define: fix uml compile bug
+  * kernel-doc: fix syscall wrapper processing
+  * Fix page writeback thinko, causing Berkeley DB slowdown
+  * write-back: fix nr_to_write counter
+  * writeback: fix break condition
+  * mm: rearrange exit_mmap() to unlock before arch_exit_mmap
+  * powerpc/fsl-booke: Fix mapping functions to use phys_addr_t
+  * lockd: fix regression in lockd's handling of blocked locks
+  * sctp: Fix crc32c calculations on big-endian arhes.
+  * sctp: Correctly start rtx timer on new packet transmissions.
+  * sctp: Properly timestamp outgoing data chunks for rtx purposes
+  * net: Fix frag_list handling in skb_seq_read
+  * net: Fix OOPS in skb_seq_read().
+  * drivers/net/skfp: if !capable(CAP_NET_ADMIN): inverted logic
+  * ipv4: fix infinite retry loop in IP-Config
+  * net: Fix userland breakage wrt. linux/if_tunnel.h
+  * net: packet socket packet_lookup_frame fix
+  * packet: Avoid lock_sock in mmap handler
+  * sungem: Soft lockup in sungem on Netra AC200 when switching interface
+    up
+  * udp: Fix UDP short packet false positive
+  * udp: increments sk_drops in __udp_queue_rcv_skb()
+  * ipv6: Disallow rediculious flowlabel option sizes.
+  * ipv6: Copy cork options in ip6_append_data
+  * net: 4 bytes kernel memory disclosure in SO_BSDCOMPAT gsopt try #2
+  * sky2: fix hard hang with netconsoling and iface going up
+  * tun: Add some missing TUN compat ioctl translations.
+  * tun: Fix unicast filter overflow
+  * virtio_net: Fix MAX_PACKET_LEN to support 802.1Q VLANs
+  * tcp: splice as many packets as possible at once
+  * tcp: Fix length tcp_splice_data_recv passes to skb_splice_bits.
+  * sparc: Enable syscall wrappers for 64-bit (CVE-2009-0029)
+  * sparc64: Annotate sparc64 specific syscalls with SYSCALL_DEFINEx()
+  * ALSA: hda - Add missing terminator in slave dig-out array
+  * ALSA: mtpav - Fix initial value for input hwport
+  * HID: adjust report descriptor fixup for MS 1028 receiver
+  * ide/libata: fix ata_id_is_cfa() (take 4)
+  * libata: fix EH device failure handling
+  * netfilter: fix tuple inversion for Node information request
+  * netfilter: xt_sctp: sctp chunk mapping doesn't work
+  * x86: microcode_amd: fix wrong handling of equivalent CPU id
+  * ide-cd: fix DMA for non bio-backed requests
+  * net: Fix data corruption when splicing from sockets.
+  * Linux 2.6.28.6
+  * eCryptfs: Regression in unencrypted filename symlinks
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 16 Feb 2009 06:43:51 -0700
+
+linux (2.6.28-8.22) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Remove perm-blacklist
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: psmouse/synaptics: ensure we reset the device on resume
+    - LP: #317270
+
+  [ Tim Gardner ]
+
+  * Add lpia to getabi script
+  * SAUCE: tracer for sreadahead
+
+ -- Amit Kucheria <amit.kucheria@ubuntu.com>  Fri, 13 Feb 2009 15:23:21 +0200
+
+linux (2.6.28-8.21) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: switch the Asus Pundit P1-AH2 to old acpi sleep ordering
+    - LP: #327267
+
+  [ Tim Gardner ]
+
+  * Added LPIA arch support
+  * Added libdrm-dev as a 'Replaces' to linux-libc-dev
+  * SAUCE: LPIA support for 9202 HDA Sigmatel codec
+  * SAUCE: Add an X86_LPIA Kconfig option
+  * SAUCE: UHCI USB quirk for resume
+  * SAUCE: LPIA Reboot fix for Intel Crownbeach development boards
+  * SAUCE: LPIA  Logical reset of USB port on resume
+  * Set CONFIG_WIRELESS_OLD_REGULATORY=n, added wireless-crda
+    as an install dependency.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "Revert "x86, early_ioremap: fix fencepost error""
+    - LP: #312554
+  * drm/i915: capture last_vblank count at IRQ uninstall time too
+    - LP: #320813
+  * drm/i915: add get_vblank_counter function for GM45
+    - LP: #320813
+  * Staging: comedi: fix Kbuild
+  * Staging: meilhaus: fix Kbuild
+  * Staging: android: binder: fix arm build errors
+  * Staging: android: timed_gpio: Fix build to build on kernels after
+    2.6.25.
+  * Staging: android: fix build error on 64bit boxes
+  * Staging: android: Add lowmemorykiller documentation.
+  * Staging: android: task_get_unused_fd_flags: fix the wrong usage of
+    tsk->signal
+  * staging: agnx: drivers/staging/agnx/agnx.h needs <linux/io.h>
+  * Staging: usbip: usbip_start_threads(): handle kernel_thread failure
+  * Staging: poch: fix verification of memory area
+  * Documentation: move DMA-mapping.txt to Doc/PCI/
+  * sgi-xp: fix writing past the end of kzalloc()'d space
+  * do_wp_page: fix regression with execute in place
+  * wait: prevent exclusive waiter starvation
+  * shm: fix shmctl(SHM_INFO) lockup with !CONFIG_SHMEM
+  * revert "rlimit: permit setting RLIMIT_NOFILE to RLIM_INFINITY"
+  * prevent kprobes from catching spurious page faults
+  * sound: usb-audio: handle wMaxPacketSize for FIXED_ENDPOINT devices
+  * md: Ensure an md array never has too many devices.
+  * md: Fix a bug in linear.c causing which_dev() to return the wrong
+    device.
+  * ACPI: Enable bit 11 in _PDC to advertise hw coord
+  * ACPI: dock: Don't eval _STA on every show_docked sysfs read
+  * ieee1394: ohci1394: increase AT req. retries, fix ack_busy_X from
+    Panasonic camcorders and others
+  * firewire: ohci: increase AT req. retries, fix ack_busy_X from Panasonic
+    camcorders and others
+  * firewire: sbp2: fix DMA mapping leak on the failure path
+  * firewire: sbp2: add workarounds for 2nd and 3rd generation iPods
+  * ieee1394: sbp2: add workarounds for 2nd and 3rd generation iPods
+  * module: remove over-zealous check in __module_get()
+  * x86: APIC: enable workaround on AMD Fam10h CPUs
+  * eeepc-laptop: fix oops when changing backlight brightness during
+    eeepc-laptop init
+  * eeepc-laptop: Add support for extended hotkeys
+  * e1000: fix bug with shared interrupt during reset
+  * e1000: Fix PCI enable to honor the need_ioport flag
+  * agp/intel: Fix broken ® symbol in device name.
+  * ALSA: hda - Add quirk for FSC Amilo Xi2550
+  * ALSA: hda - Add missing COEF initialization for ALC887
+  * ALSA: hda - Add missing initialization for ALC272
+  * asus_acpi: Add R1F support
+  * panasonic-laptop: fix X[ ARRAY_SIZE(X) ]
+  * ACPI: Skip the first two elements in the _BCL package
+  * ACPI: proc_dir_entry 'video/VGA' already registered
+  * ACPI: disable ACPI cleanly when bad RSDP found
+  * ACPICA: Fix table entry truncation calculation
+  * PCI: properly clean up ASPM link state on device remove
+  * PCI: return error on failure to read PCI ROMs
+  * seq_file: move traverse so it can be used from seq_read
+  * seq_file: fix big-enough lseek() + read()
+  * serial: set correct baud_base for Oxford Semiconductor Ltd EXSYS
+    EX-41092 Dual 16950 Serial adapter
+  * Add support for '8-port RS-232 MIC-3620 from advantech'
+  * mm: fix error case in mlock downgrade reversion
+  * elf core dump: fix get_user use
+  * ACPI: video: Fix reversed brightness behavior on ThinkPad SL series
+  * ipw2200: fix scanning while associated
+  * XFS: set b_error from bio error in xfs_buf_bio_end_io
+  * Revert USB: option: add Pantech cards
+  * USB: option: New mobile broadband modems to be supported
+  * USB: new id for ti_usb_3410_5052 driver
+  * USB: two more usb ids for ti_usb_3410_5052
+  * USB: usb-storage: add Pentax to the bad-vendor list
+  * sata_via: Add VT8261 support
+  * nbd: do not allow two clients at the same time
+  * sctp: Fix another socket race during accept/peeloff
+  * Linux 2.6.28.5
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 09 Feb 2009 16:11:28 -0700
+
+linux (2.6.28-7.20) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * SAUCE: Input: atkbd - Samsung NC10 key repeat fix
+
+  [ Upstream Kernel Changes ]
+
+  * Manually revert "mlock: downgrade mmap sem while populating mlocked
+    regions"
+  * xen: make sysfs files behave as their names suggest
+  * sata_mv: fix 8-port timeouts on 508x/6081 chips
+  * m68knommu: set NO_DMA
+  * PCI/MSI: bugfix/utilize for msi_capability_init()
+  * x86: use early clobbers in usercopy*.c
+  * netfilter: ctnetlink: fix scheduling while atomic
+  * orinoco: move kmalloc(..., GFP_KERNEL) outside spinlock in
+    orinoco_ioctl_set_genie
+  * fbdev/atyfb: Fix DSP config on some PowerMacs & PowerBooks
+  * kmalloc: return NULL instead of link failure
+  * sata_nv: rename nv_nf2_hardreset()
+  * sata_nv: fix MCP5x reset
+  * sata_nv: ck804 has borked hardreset too
+  * Fix memory corruption in console selection
+  * Add enable_ms to jsm driver
+  * nfsd: only set file_lock.fl_lmops in nfsd4_lockt if a stateowner is
+    found
+  * nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT
+  * iwlwifi: fix rs_get_rate WARN_ON()
+  * p54: fix lm87 checksum endianness
+  * p54: fix p54_read_eeprom to cope with tx_hdr_len
+  * p54usb: rewriting rx/tx routines to make use of usb_anchor's facilities
+  * minstrel: fix warning if lowest supported rate index is not 0
+  * PCI: irq and pci_ids patch for Intel Tigerpoint DeviceIDs
+  * cpuidle: Add decaying history logic to menu idle predictor
+  * ACPI: Avoid array address overflow when _CST MWAIT hint bits are set
+  * video: always update the brightness when poking "brightness"
+  * Newly inserted battery might differ from one just removed, so update of
+    battery info fields is required.
+  * ACPI: Do not modify SCI_EN directly
+  * dlm: initialize file_lock struct in GETLK before copying conflicting
+    lock
+  * sata_mv: Fix chip type for Hightpoint RocketRaid 1740/1742
+  * ACPICA: Allow multiple backslash prefix in namepaths
+  * Linux 2.6.28.4
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 07 Feb 2009 18:53:42 -0700
+
+linux (2.6.28-7.19) jaunty; urgency=low
+
+  * Fix missing modules FTBS
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 05 Feb 2009 15:28:15 -0700
+
+linux (2.6.28-7.18) jaunty; urgency=low
+
+  [ Alok Kataria ]
+
+  * SAUCE: (drop after 2.6.29) x86: add a synthetic TSC_RELIABLE feature
+    bit
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: add X86_FEATURE_HYPERVISOR feature bit
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Hypervisor detection and get tsc_freq
+    from hypervisor
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Add a synthetic TSC_RELIABLE feature
+    bit.
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Skip verification by the watchdog for
+    TSC clocksource.
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: VMware: Fix vmware_get_tsc code
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: vmware: look for DMI string in the
+    product serial key
+    - LP: #319945
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: toshiba_acpi -- pull in current -dev version of driver
+    - LP: #269831
+  * SAUCE: toshiba_acpi -- add acpi hotkey kernel thread
+    - LP: #269831
+  * move toshiba laptops back from tlsup to toshiba_acpi
+    - LP: #269831
+
+  [ Aneesh Kumar K.V ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix the delalloc
+    writepages to allocate blocks at the right offset.
+  * SAUCE: (revert before 2.6.28.y update) ext4: avoid ext4_error when
+    mounting a fs with a single bg
+  * SAUCE: (revert before 2.6.28.y update) ext4: Don't overwrite
+    allocation_context ac_status
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add blocks added during
+    resize to bitmap
+  * SAUCE: (revert before 2.6.28.y update) ext4: Use
+    EXT4_GROUP_INFO_NEED_INIT_BIT during resize
+  * SAUCE: (revert before 2.6.28.y update) ext4: cleanup mballoc header
+    files
+  * SAUCE: (revert before 2.6.28.y update) ext4: don't use blocks freed but
+    not yet committed in buddy cache init
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix race between
+    read_block_bitmap() and mark_diskspace_used()
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix the race between
+    read_inode_bitmap() and ext4_new_inode()
+  * SAUCE: (revert before 2.6.28.y update) ext4: Use new buffer_head flag
+    to check uninit group bitmaps initialization
+  * SAUCE: (revert before 2.6.28.y update) ext4: mark the blocks/inode
+    bitmap beyond end of group as used
+  * SAUCE: (revert before 2.6.28.y update) ext4: Don't allow new groups to
+    be added during block allocation
+  * SAUCE: (revert before 2.6.28.y update) ext4: Init the complete page
+    while building buddy cache
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix s_dirty_blocks_counter
+    if block allocation failed with nodelalloc
+
+  [ Hannes Eder ]
+
+  * SAUCE: (drop after 2.6.29) x86: vmware - fix sparse warnings
+    - LP: #319945
+
+  [ Luke Yelavich ]
+
+  * hid modules have hyphens instead of underscores in their names
+
+  [ Mark Fasheh ]
+
+  * SAUCE: (revert before 2.6.28.y update) jbd2: Add BH_JBDPrivateStart
+
+  [ Theodore Ts'o ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add support for non-native
+    signed/unsigned htree hash algorithms
+  * SAUCE: (revert before 2.6.28.y update) ext4: tone down
+    ext4_da_writepages warnings
+  * SAUCE: (revert before 2.6.28.y update) jbd2: Add barrier not supported
+    test to journal_wait_on_commit_record
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add sanity checks for the
+    superblock before mounting the filesystem
+  * SAUCE: (revert before 2.6.28.y update) ext4: only use i_size_high for
+    regular files
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add sanity check to
+    make_indexed_dir
+  * SAUCE: (revert before 2.6.28.y update) jbd2: On a __journal_expect()
+    assertion failure printk "JBD2", not "EXT3-fs"
+  * SAUCE: (revert before 2.6.28.y update) ext4: Initialize the new group
+    descriptor when resizing the filesystem
+
+  [ Tyler Hicks ]
+
+  * SAUCE: (drop after 2.6.28) [eCryptfs] Regression in unencrypted
+    filename symlinks
+    - LP: #322532
+
+  [ Upstream Kernel Changes ]
+
+  * Input: atkbd - broaden the Dell DMI signatures
+    - LP: #261721
+  * ti_usb_3410_5052: support alternate firmware
+  * ath5k: fix mesh point operation
+  * mac80211: decrement ref count to netdev after launching mesh discovery
+  * inotify: clean up inotify_read and fix locking problems
+  * fuse: destroy bdi on umount
+  * fuse: fix missing fput on error
+  * fuse: fix NULL deref in fuse_file_alloc()
+  * x86, mm: fix pte_free()
+  * klist.c: bit 0 in pointer can't be used as flag
+  * sysfs: fix problems with binary files
+  * x86: fix page attribute corruption with cpa()
+  * USB: fix toggle mismatch in disable_endpoint paths
+  * sound: virtuoso: enable UART on Xonar HDAV1.3
+  * USB: usbmon: Implement compat_ioctl
+  * USB: fix char-device disconnect handling
+  * USB: storage: add unusual devs entry
+  * alpha: nautilus - fix compile failure with gcc-4.3
+  * alpha: fix vmalloc breakage
+  * resources: skip sanity check of busy resources
+  * rtl8187: Add termination packet to prevent stall
+  * it821x: Add ultra_mask quirk for Vortex86SX
+  * libata: pata_via: support VX855, future chips whose IDE controller use
+    0x0571
+  * serial_8250: support for Sealevel Systems Model 7803 COMM+8
+  * drm: stash AGP include under the do-we-have-AGP ifdef
+  * Fix OOPS in mmap_region() when merging adjacent VM_LOCKED file segments
+  * bnx2x: Block nvram access when the device is inactive
+  * ext3: Add sanity check to make_indexed_dir
+  * rtl8187: Fix error in setting OFDM power settings for RTL8187L
+  * epoll: drop max_user_instances and rely only on max_user_watches
+  * gpiolib: fix request related issue
+  * sgi-xpc: Remove NULL pointer dereference.
+  * sgi-xpc: ensure flags are updated before bte_copy
+  * include/linux: Add bsg.h to the Kernel exported headers
+  * ALSA: hda - Fix PCM reference NID for STAC/IDT analog outputs
+  * ALSA: hda - add another MacBook Pro 4, 1 subsystem ID
+  * ALSA: hda - Add quirk for HP DV6700 laptop
+  * crypto: authenc - Fix zero-length IV crash
+  * crypto: ccm - Fix handling of null assoc data
+  * x86, pat: fix reserve_memtype() for legacy 1MB range
+  * x86, pat: fix PTE corruption issue while mapping RAM using /dev/mem
+  * PCI hotplug: fix lock imbalance in pciehp
+  * dmaengine: fix dependency chaining
+  * NET: net_namespace, fix lock imbalance
+  * relay: fix lock imbalance in relay_late_setup_files
+  * Linux 2.6.28.3
+  * ALSA: Enable SPDIF output on ALC655
+  * ALSA: hda - Add ASUS V1Sn support
+  * ALSA: hda - support detecting HD Audio devices with PCI class code
+  * ALSA: hda: alc883 model for ASUS P5Q-EM boards
+  * ALSA: hda - Add quirk for MSI 7260 mobo
+  * ALSA: hda - Add quirk for Sony VAIO VGN-SR19XN
+  * ALSA: oxygen: add Claro halo support
+  * ALSA: hda - Add a new function to seek for a codec ID
+  * ALSA: patch_sigmatel: Add missing Gateway entries and autodetection
+  * ALSA: hda - More fixes on Gateway entries
+  * ALSA: hda - Add MCP67 HDMI support
+  * ALSA: hda - fix name for ALC1200
+  * LSA: hda - Add HP Acacia detection
+  * ALSA: hda - Add quirk for HP 2230s
+  * ALSA: hda - Add quirk for Dell Inspiron Mini9
+  * ALSA: hda - add support for Intel DX58SO board
+  * ALSA: hda - Fix silent headphone output on Panasonic CF-74
+  * ALSA: USB quirk for Logitech Quickcam Pro 9000 name
+  * ALSA: hda - add quirks for some 82801H variants to use ALC883_MITAC
+
+  [ Yasunori Goto ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Widen type of
+    ext4_sb_info.s_mb_maxs[]
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 02 Feb 2009 23:07:13 -0700
+
+linux (2.6.28-6.17) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs: ARMEL/versatile
+
+ -- Amit Kucheria <amit.kucheria@ubuntu.com>  Fri, 30 Jan 2009 13:36:59 +0200
+
+linux (2.6.28-6.16) jaunty; urgency=low
+
+  [ Luke Yelavich ]
+
+  * Add hid quirks to input-modules udeb
+
+  [ Tim Gardner ]
+
+  * Revert "[arm] Fix kexec on ARM by properly calling the relocation
+    function". This patch was deemed 'bogus' by Russell King on the
+    ARM mailing list.
+
+  [ Upstream Kernel Changes ]
+
+  * PCI: keep ASPM link state consistent throughout PCIe hierarchy
+  * security: introduce missing kfree
+  * rt2x00: add USB ID for the Linksys WUSB200.
+  * p54usb: Add USB ID for Thomson Speedtouch 121g
+  * lib/idr.c: use kmem_cache_zalloc() for the idr_layer cache
+  * sgi-xp: eliminate false detection of no heartbeat
+  * sched: fix update_min_vruntime
+  * IA64: Turn on CONFIG_HAVE_UNSTABLE_CLOCK
+  * sound: virtuoso: do not overwrite EEPROM on Xonar D2/D2X
+  * ALSA: hda - Add quirk for another HP dv5
+  * ALSA: hda - Fix HP dv5 mic input
+  * ALSA: hda - Don't reset HP pinctl in patch_sigmatel.c
+  * ALSA: hda - make laptop-eapd model back for AD1986A
+  * drivers/net/irda/irda-usb.c: fix buffer overflow
+  * usb-storage: add last-sector hacks
+  * usb-storage: set CAPACITY_HEURISTICS flag for bad vendors
+  * pkt_sched: sch_htb: Fix deadlock in hrtimers triggered by HTB
+  * ipv6: Fix fib6_dump_table walker leak
+  * sctp: Avoid memory overflow while FWD-TSN chunk is received with bad
+    stream ID
+  * pkt_sched: cls_u32: Fix locking in u32_change()
+  * r6040: fix wrong logic in mdio code
+  * r6040: save and restore MIER correctly in the interrupt routine
+  * r6040: bump release number to 0.19
+  * tcp: don't mask EOF and socket errors on nonblocking splice receive
+  * p54usb: fix traffic stalls / packet drop
+  * netfilter: x_tables: fix match/target revision lookup
+  * netfilter: ebtables: fix inversion in match code
+  * netfilter: nf_conntrack: fix ICMP/ICMPv6 timeout sysctls on big-endian
+  * dell_rbu: use scnprintf() instead of less secure sprintf()
+  * powerpc: is_hugepage_only_range() must account for both 4kB and 64kB
+    slices
+  * hwmon: (abituguru3) Fix CONFIG_DMI=n fallback to probe
+  * mm: write_cache_pages cyclic fix
+  * mm: write_cache_pages early loop termination
+  * mm: write_cache_pages writepage error fix
+  * mm: write_cache_pages integrity fix
+  * mm: write_cache_pages cleanups
+  * mm: write_cache_pages optimise page cleaning
+  * mm: write_cache_pages terminate quickly
+  * mm: write_cache_pages more terminate quickly
+  * mm: do_sync_mapping_range integrity fix
+  * mm: direct IO starvation improvement
+  * fs: remove WB_SYNC_HOLD
+  * fs: sync_sb_inodes fix
+  * fs: sys_sync fix
+  * Linux 2.6.28.2
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 25 Jan 2009 13:36:16 -0700
+
+linux (2.6.28-5.15) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Revert "Enabled CONFIG_PID_NS=y for i386/amd64"
+    Somehow this commit also reverted the 7 prior commits (which is bad).
+  * Enabled CONFIG_PID_NS=y for i386/amd64 (version 2)
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 22 Jan 2009 13:48:34 -0700
+
+linux (2.6.28-5.14) jaunty; urgency=low
+
+  [ Ben Collins ]
+
+  * lirc_gpio: Forward ported to current kernel (jaunty)
+  * configs: Enable LIRC_GPIO on 64-bit/32-bit x86
+    - LP: #298791
+
+  [ Jeff Layton ]
+
+  * SAUCE: cifs: make sure we allocate enough storage for socket address
+    - LP: #318565
+
+  [ Tim Gardner ]
+
+  * check-abi: Return success when ABI skip is requested and no ABI files exist.
+    This ought to fix the armel FTBS.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 22 Jan 2009 06:42:49 -0700
+
+linux (2.6.28-5.13) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: don't use buggy _BCL/_BCM/_BQC for backlight control"
+
+  [ Tim Gardner ]
+
+  * Fix udeb generation breakage caused by the previous armel versatile
+    flavour config update.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 21 Jan 2009 12:38:35 -0700
+
+linux (2.6.28-5.12) jaunty; urgency=low
+
+  [ Ante ]
+
+  * Update drbd to 8.3.0
+
+  [ Dave Airlie ]
+
+  * i915/drm: provide compat defines for userspace for certain struct
+
+  [ Eric Anholt ]
+
+  * drm/i915: Don't double-unpin buffers if we take a signal in
+  * drm/i915: Don't complain when interrupted while pinning in execbuffers.
+  * drm/i915: Don't allow objects to get bound while VT switched.
+
+  [ Jani Monoses ]
+
+  * Fix webcam having USB ID 0ac8:303b
+    - LP: #292086
+
+  [ Jesse Barnes ]
+
+  * drm/i915: set vblank enabled flag correctly across IRQ
+  * drm/i915: don't enable vblanks on disabled pipes
+
+  [ Michael Casadevall ]
+
+  * [arm] Fix kexec on ARM by properly calling the relocation function
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_PID_NS=y for i386/amd64
+  * SAUCE: Increase ATA_TMOUT_PMP_SRST_WAIT to 5 seconds.
+    - LP: #318978
+  * Update armel versatile config
+    - LP: #314789
+  * Enabled CONFIG_RT2860=m for i386/amd64
+  * Enabled CONFIG_RT2870=m for i386/amd64
+
+  [ Upstream Kernel Changes ]
+
+  * Input: atkbd - add keyboard quirk for HP Pavilion ZV6100 laptop
+    - LP: #291878
+  * ALSA: hda - Add quirk for another HP dv7
+  * ALSA: hda - Add quirk for HP6730B laptop
+  * ALSA: caiaq - Fix Oops with MIDI
+  * ALSA: hda - Fix typos for AD1882 codecs
+  * x86: fix intel x86_64 llc_shared_map/cpu_llc_id anomolies
+  * x86: default to SWIOTLB=y on x86_64
+  * CIFS: make sure that DFS pathnames are properly formed
+  * ring-buffer: prevent false positive warning
+  * ring-buffer: fix dangling commit race
+  * iwlwifi: use GFP_KERNEL to allocate Rx SKB memory
+  * tx493[89]ide: Fix length for __ide_flush_dcache_range
+  * tx4939ide: Do not use zero count PRD entry
+  * SCSI: eata: fix the data buffer accessors conversion regression
+  * USB: emi26: fix oops on load
+  * x86, UV: remove erroneous BAU initialization
+  * x86: fix incorrect __read_mostly on _boot_cpu_pda
+  * vmalloc.c: fix flushing in vmap_page_range()
+  * fs: symlink write_begin allocation context fix
+  * cgroups: fix a race between cgroup_clone and umount
+  * dm raid1: fix error count
+  * dm log: fix dm_io_client leak on error paths
+  * minix: fix add link's wrong position calculation
+  * md: fix bitmap-on-external-file bug.
+  * sched_clock: prevent scd->clock from moving backwards, take #2
+  * devices cgroup: allow mkfifo
+  * SCSI: aha152x_cs: Fix regression that keeps driver from using shared
+    interrupts
+  * ioat: fix self test for multi-channel case
+  * USB: isp1760: use a specific PLX bridge instead of any bdridge
+  * USB: isp1760: Fix probe in PCI glue code
+  * USB: unusual_devs.h additions for Pentax K10D
+  * inotify: fix type errors in interfaces
+  * Move compat system call declarations to compat header file
+  * Convert all system calls to return a long
+  * Rename old_readdir to sys_old_readdir
+  * Remove __attribute__((weak)) from sys_pipe/sys_pipe2
+  * Make sys_pselect7 static
+  * Make sys_syslog a conditional system call
+  * System call wrapper infrastructure
+  * powerpc: Enable syscall wrappers for 64-bit
+  * s390: enable system call wrappers
+  * System call wrapper special cases
+  * System call wrappers part 01
+  * System call wrappers part 02
+  * System call wrappers part 03
+  * System call wrappers part 04
+  * System call wrappers part 05
+  * System call wrappers part 06
+  * System call wrappers part 07
+  * System call wrappers part 08
+  * System call wrappers part 09
+  * System call wrappers part 10
+  * System call wrappers part 11
+  * System call wrappers part 12
+  * System call wrappers part 13
+  * System call wrappers part 14
+  * System call wrappers part 15
+  * System call wrappers part 16
+  * System call wrappers part 17
+  * System call wrappers part 18
+  * System call wrappers part 19
+  * System call wrappers part 20
+  * System call wrappers part 21
+  * System call wrappers part 22
+  * System call wrappers part 23
+  * System call wrappers part 24
+  * System call wrappers part 25
+  * System call wrappers part 26
+  * System call wrappers part 27
+  * System call wrappers part 28
+  * System call wrappers part 29
+  * System call wrappers part 30
+  * System call wrappers part 31
+  * System call wrappers part 32
+  * System call wrappers part 33
+  * s390 specific system call wrappers
+  * x86: fix RIP printout in early_idt_handler
+  * Fix timeouts in sys_pselect7
+  * USB: another unusual_devs entry for another bad Argosy storage device
+  * USB: storage: extend unusual range for 067b:3507
+  * USB: storage: recognizing and enabling Nokia 5200 cell phoes
+  * HID: fix error condition propagation in hid-sony driver
+  * fix switch_names() breakage in short-to-short case
+  * nfs: remove redundant tests on reading new pages
+  * eCryptfs: check readlink result was not an error before using it
+  * mvsas: increase port type detection delay to suit Seagate's 10k6 drive ST3450856SS 0003
+  * x86: avoid theoretical vmalloc fault loop
+  * ath9k: enable RXing of beacons on STA/IBSS
+  * mm lockless pagecache barrier fix
+  * powerpc: Disable Collaborative Memory Manager for kdump
+  * ibmvfc: Delay NPIV login retry and add retries
+  * ibmvfc: Improve async event handling
+  * getrusage: RUSAGE_THREAD should return ru_utime and ru_stime
+  * ath5k: ignore the return value of ath5k_hw_noise_floor_calibration
+  * mm: fix assertion
+  * XFS: truncate readdir offsets to signed 32 bit values
+  * Linux 2.6.28.1
+  * eCryptfs: Filename Encryption: Tag 70 packets
+  * eCryptfs: Filename Encryption: Header updates
+  * eCryptfs: Filename Encryption: Encoding and encryption functions
+  * eCryptfs: Filename Encryption: filldir, lookup, and readlink
+  * eCryptfs: Filename Encryption: mount option
+  * eCryptfs: Replace %Z with %z
+  * eCryptfs: Fix data types (int/size_t)
+  * eCryptfs: kerneldoc for ecryptfs_parse_tag_70_packet()
+  * eCryptfs: Clean up ecryptfs_decode_from_filename()
+  * fs/ecryptfs/inode.c: cleanup kerneldoc
+  * staging-p80211: Kill directly reference of netdev->priv
+  * staging-slicoss: Kill directly reference of netdev->priv
+  * staging-winbond: Kill directly reference of netdev->priv
+  * Staging: go7007: fixes due to video_usercopy api change
+  * Staging: go7007: fixes due v4l2_file_operations api change
+  * staging: correct dubious use of !x & y
+  * Staging: w35und: make wb35_probe() and wb35_disconnect() funtions static
+  * Staging: w35und: remove unused wb35_open() and wb35_close() functions
+  * Staging: w35und: use msleep() and udelay()
+  * Staging: w35und: remove the no-op pa_stall_execution macro
+  * Staging: w35und: purb typedef removal
+  * Staging: w35und: reg queue struct typedef removal
+  * Staging: w35und: wb35reg struct typedef removal
+  * Staging: w35und: padapter struct typedef removal
+  * Staging: w35und: merge wblinux struct to adapter
+  * Staging: w35und: wb35_probe() cleanup
+  * Staging: w35und: remove usb_submit_urb wrapper function
+  * Staging: w35und: remove usb_alloc_urb wrapper function
+  * w35und: remove dead code from wbusb_f.h
+  * Staging: w35und: remove true/false boolean macros
+  * Staging: w35und: OS_MEMORY_ALLOC wrapper removal
+  * Staging: w35und: usb_put_dev() is missing from wb35_disconnect()
+  * Staging: w35und: remove macro magic from MLME_GetNextPacket()
+  * Staging: w35und: plug memory leak in wbsoft_tx()
+  * Staging: w35und: move supported band initialization out of wb35_probe()
+  * Staging: w35und: remove timer wrappers
+  * Staging: w35und: remove atomic op wrappers
+  * Staging: w35und: remove memcpy/memcmp wrappers
+  * Staging: w35und: remove abs() and BIT() macros
+  * Staging: w35und: remove unused macros from common.h
+  * Staging: w35und: remove unused link status code
+  * Staging: w35und: #include cleanup
+  * Staging: w35und: remove some dead code
+  * Staging: w35und: move source files to one directory
+  * Staging: w35und: move struct wbsoft_priv to core.h and use it
+  * Staging: w35und: remove ->adapter from struct _HW_DATA_T
+  * Staging: w35und: clean up adapter.h a bit
+  * Staging: w35und: merge struct wb35_adapter to struct wbsoft_priv
+  * Staging: w35und: remove global struct ieee80211_hw
+  * Staging: w35und: inline DRIVER_AUTHOR and DRIVER_DESC macros
+  * Staging: w35und: clean up wblinux.c a bit
+  * Staging: w35und: remove unused ->ShutDowned member from struct
+    LOCAL_PARA
+  * Staging: w35und: move global wbsoft_enabled to struct wbsoft_priv
+  * Staging: w35und: move packet_came() to wb35rx.c
+  * Staging: w35und: remove ->skb_array from struct wbsoft_priv
+  * Staging: w35und: remove ->shutdown from struct wbsoft_priv
+  * Staging: w35und: make functions local to mds.c static
+  * Staging: w35und: make functions local to mlmetxrx.c static
+  * Staging: w35und: remove dead code from mto.c
+  * Staging: w35und: make functions local to wb35rx.c static
+  * Staging: w35und: make functions local to wb35tx.c static
+  * Staging: w35und: remove dead code from wbhal.c
+  * Staging: w35und: remove rxisr.c as dead code
+  * Staging: w35und: fix Kconfig
+  * Staging: w35und: fix config build warnings
+  * Staging: wlan-ng: Remove PCI/PLX/PCMCIA files.
+  * Staging: wlan-ng: Update Help text to mention prism3 devices.
+  * Staging: wlan-ng: Delete PCI/PLX/PCMCIA-specific code.
+  * Staging: wlan-ng: Make wlan-ng use WEXT mode by default.
+  * Staging: wlan-ng: Eliminate more <2.6 kernel support.
+  * Staging: wlan-ng: Eliminate all backwards-compatibility for <2.6.13 kernels.
+  * Staging: wlan-ng: Eliminate a boatload of tertiaryAP-only code.
+  * Staging: wlan-ng: Remove AP-only code from MLME functions.
+  * Staging: wlan-ng: Get rid of the MTU tests in the rx conversion path.
+  * Staging: wlan-ng: Eliminate one more rx mtu test.
+  * Staging: wlan-ng: Eliminate local 'version.h'
+  * Staging: wlan-ng: Eliminate usage of procfs.
+  * Staging: wlan-ng: Use standard kernel integer (u32/s32/etc) types.
+  * Staging: wlan-ng: Eliminate all backwards-compatible kernel code.
+  * Staging: wlan-ng: Wireless Extension support is mandatory.
+  * Staging: wlan-ng: use WIRELESS_EXT, not CONFIG_WIRELESS_EXT
+  * Staging: wlan-ng: Delete a large pile of now-unused code.
+  * Staging: wlan-ng: Delete a pile of unused mibs. And fix WEXT SET_TXPOWER.
+  * Staging: wlan-ng: Consolidate wlan-ng into a single module.
+  * Staging: wlan-ng: Purge all MIBs not used internally.
+  * Staging: wlan-ng: p80211netdev.c fix netdev alloc to prevent oops on device start
+  * Staging: wlan-ng: prism2_usb.c always enable the card in probe_usb
+  * Staging: wlan-ng: hfa384x_usb.c use newest version of 384x_drvr_start
+  * Staging: wlan-ng: p80211wext.c add latest changes & remove extra nulls from wext_handlers
+  * Staging: wlan-ng: p80211wext don't set default key id twice
+  * Staging: wlan-ng: hfa384x_usbin_callback: check for hardware removed
+  * Staging: wlan-ng: p80211conv.c copy code from wlan-ng-devel branch to not drop packets
+  * Staging: wlan-ng: remove unused #include <version.h>
+  * Staging: wlan-ng: p80211wext.c: use ARRAY_SIZE
+  * Staging: wlan-ng: fix compiler warnings
+  * Staging: wlan-ng: skb_p80211_to_ether() - payload_length is unsigned, check before subtraction
+  * Staging: at76_usb: update drivers/staging/at76_usb w/ mac80211 port
+  * Staging: at76_usb: fix build breakage
+  * Staging: at76_usb: remove compiler warnings
+  * Staging: at76_usb: fix up all remaining checkpatch.pl warnings
+  * Staging: at76_usb: cleanup dma on stack issues
+  * Staging: poch: Block size bug fix
+  * Staging: poch: Update TODO list
+  * Staging: poch: Correct pages from bytes.
+  * Staging: poch: minor fixes
+  * Staging: poch: Fix build warnings
+  * Staging: poch: Rx control register init
+  * Staging: poch: Fix user space protocol syncing
+  * Staging: poch: Fine grained locking
+  * Staging: sxg: remove typedefs
+  * Staging: sxg: break the build in a cleaner way when !x86
+  * Staging: sxg: update README
+  * staging: struct device - replace bus_id with dev_name(), dev_set_name()
+  * Staging: echo: remove typedefs
+  * Staging: echo: Lindent drivers/staging/echo
+  * Staging: go7007: saa7134 updates
+  * Staging: go7007: add sensoray 2250/2251 support
+  * Staging: go7007: Convert driver to use video_ioctl2
+  * Staging: go7007: annotate code pointers
+  * Staging: go7007: fix minor build warnings
+  * Staging: go7007: small cleanup
+  * Staging: go7007: add some more v4l2 ioctls
+  * Staging: et131x: Cleanup et131x_debug.h defines
+  * Staging: et131x: fix build failure
+  * Staging: et131x: remove unused variable in et1310_tx.c
+  * Staging: usbip: cleanup kerneldoc
+  * Staging: slicoss: use kzalloc
+  * Staging: slicoss: use correct type for memory allcations
+  * Staging: slicoss: use request_firmware
+  * Staging: add agnx wireless driver
+  * Staging: agnx: fix build errors due to ssid removal
+  * Staging: agnx: fix build errors due to rate control API changes
+  * Staging: agnx: fix build warnings
+  * Staging: add otus Atheros wireless network driver
+  * Staging: otus: fix netdev->priv usage
+  * Staging: otus: fix name clash
+  * Staging: otus: fix urb callback function type
+  * Staging: otus: remove dependence on kernel version
+  * Staging: add rt2860 wireless driver
+  * Staging: rt2860: disable root hack for reading files
+  * Staging: rt2860: fix up netdev->priv usage
+  * Staging: rt2860: use standard bit-reverse function
+  * Staging: rt2860: Fix minor compiler warnings
+  * Staging: rt2860: enable WPA_SUPPLICANT support
+  * Staging: Add ServerEngines benet 10Gb ethernet driver
+  * Staging: benet: fix netif api breakage
+  * Staging: benet: fix up netdev->priv change
+  * Staging: benet: build is broken unless CONFIG_NETPOLL is enabled
+  * Staging: benet: patch to remove subdirectories
+  * Staging: benet: fix build errors when CONFIG_NETPOLL is off
+  * Staging: benet: fix build error.
+  * Staging: benet: patch to use offsetof() instead of AMAP_BYTE_OFFSET()
+  * Staging: benet: fix problems reported by checkpatch
+  * Staging: benet: cleanup a check while posting rx buffers
+  * Staging: add comedi core
+  * Staging: comedi: fix up a lot of checkpatch.pl warnings
+  * Staging: comedi: fix checkpatch.pl errors in comedi_fops.c
+  * Staging: comedi: fix build error in comedilib.h
+  * Staging: comedi: add kcomedilib to the tree
+  * Staging: comedi: set up infrastructure for individual drivers
+  * Staging: comedi: add local copy of interrupt.h
+  * Staging: comedi: add pci and usb wrapper header files
+  * Staging: comedi: comedi driver common function module
+  * Staging: comedi: add mite comedi pci driver
+  * Staging: comedi: add usb usbdux driver
+  * Staging: comedi: add usb usbduxfast driver
+  * Staging: comedi: add usb dt9812 driver
+  * Staging: comedi: add comedi_bond driver
+  * Staging: comedi: add comedi_test driver
+  * Staging: comedi: add comedi_parport driver
+  * Staging: comedi: dt9812: fix up a lot of coding style issues
+  * Staging: comedi: dt9812: remove dt9812.h
+  * Staging: comedi: dt9812: remove typedefs
+  * Staging: comedi: dt9812: fix sparse warnings
+  * Staging: comedi: usbdux: remove kernel version checks
+  * Staging: comedi: usbdux: code style cleanups
+  * Staging: comedi: usbdux: remove // comments
+  * Staging: comedi: usbdux: fix up printk calls
+  * Staging: comedi: usbdux: remove checkpatch.pl warnings
+  * Staging: comedi: usbdux: remove typedef
+  * Staging: comedi: usbdux: remove comedi usb wrappers
+  * Staging: comedi: usbduxfast: remove comedi usb wrappers
+  * Staging: comedi: dt9812: remove #ifdef that is not needed
+  * Staging: comedi: remove usb wrappers
+  * Staging: comedi: remove PCI wrappers
+  * Staging: comedi: add icp_multi driver
+  * Staging: comedi: add me4000 driver
+  * Staging: comedi: fix checkpatch.pl issues in comedi_bond.c
+  * Staging: comedi: fix checkpatch.pl issues in comedi_fc.c
+  * Staging: comedi: remove typedefs from comedi_bond.c
+  * Staging: comedi: fix sparse issues in comedi_bond.c
+  * Staging: comedi: fix checkpatch.pl issues in comedi_test.c
+  * Staging: comedi: fix sparse issues in comedi_test.c
+  * Staging: comedi: remove typedefs from comedi_test.c
+  * Staging: comedi: fix comedi_parport.c checkpatch.pl issues.
+  * Staging: comedi: fix comedi_fc.h checkpatch.pl issues.
+  * Staging: comedi: fix comedi_pci.h checkpatch.pl issues.
+  * Staging: comedi: comedi_pci.h: remove unneeded wrapper
+  * Staging: comedi: comedi_pci.h: remove comedi_pci_enable_no_regions
+  * Staging: comedi: comedi_pci.h: remove comedi_pci_disable_no_regions
+  * Staging: comedi: add s626 driver
+  * Staging: comedi: add rtd520 driver
+  * Staging: comedi: add me_daq driver
+  * Staging: comedi: me_daq: fix checkpatch.pl issues
+  * Staging: comedi: me_daq: remove typedefs
+  * Staging: comedi: me_daq: fix sparse issues
+  * Staging: comedi: fix checkpatch.pl warning in interrupt.h
+  * Staging: comedi: fix build if CONFIG_PROC_FS is not set
+  * Staging: add asus_oled driver
+  * Staging: asus_oled: fix build dependancy
+  * Staging: Add the Meilhaus ME-IDS driver package
+  * Staging: meilhaus: fix __symbol_get problems
+  * Staging: add lcd-panel driver
+  * Staging: panel: major checkpatch cleanup
+  * Staging: panel: remove ifdefs and code for pre-2.6 kernels
+  * Staging: panel: remove support for smartcards
+  * Staging: add Driver for Altera PCI Express Chaining DMA reference design
+  * Staging: add rtl8187se driver
+  * Staging: rtl8187se: remove unneeded files
+  * Staging: rtl8187se: make the built module be the proper name
+  * Staging: rtl8187se: remove duplicate pci ids
+  * Staging: me4000: switch to list_for_each*()
+  * Staging: usbip: switch to list_for_each_entry()
+  * Staging: add princeton instruments usb camera driver
+  * Staging: add mimio xi driver
+  * Staging: add rt2870 wireless driver
+  * Staging: rt2870: disable root hack for reading files
+  * Staging: rt2870: fix up netdev->priv usage
+  * Staging: add frontier tranzport and alphatrack drivers
+  * Staging: frontier: remove unused alphatrack_sysfs.c file
+  * Staging: frontier: fix compiler warnings
+  * Staging: add epl stack
+  * Staging: epl: run Lindent on all kernel/*.h files
+  * Staging: epl: run Lindent on all user/*.h files
+  * Staging: epl: run Lindent on *.h files
+  * Staging: epl: run Lindent on *.c files
+  * Staging: epl: hr timers all run in hard irq context now
+  * Staging: epl: fix netdev->priv b0rkage
+  * Staging: add android framework
+  * Staging: android: add binder driver
+  * Staging: android: binder: Fix gcc warnings about improper format specifiers for size_t in printk
+  * staging: android: binder: Fix use of euid
+  * Staging: android: add logging driver
+  * Staging: android: add ram_console driver
+  * Staging: android: add timed_gpio driver
+  * Staging: android: timed_gpio: Rename android_timed_gpio to timed_gpio
+  * Staging: android: remove dummy android.c driver
+  * Staging: android: add lowmemorykiller driver
+  * Staging: android: binder: fix build errors
+  * staging: __FUNCTION__ is gcc-specific, use __func__
+  * V4L/DVB (10176a): Switch remaining clear_user_page users over to
+    clear_user_highpage
+
+  [ Zhenyu Wang ]
+
+  * agp/intel: add support for G41 chipset
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 18 Jan 2009 20:22:54 -0700
+
+linux (2.6.28-4.11) jaunty; urgency=low
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Enable HDMI audio codec on Studio XPS 1340
+    - LP: #309508
+
+  [ Tim Gardner ]
+
+  * Fix armel d-i FTBSs
+
+  [ Upstream Kernel Changes ]
+
+  * USB: re-enable interface after driver unbinds
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 13 Jan 2009 16:33:08 -0700
+
+linux (2.6.28-4.10) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update kernel bootloader recommends: to prefer grub
+    - LP: #314004
+  * SAUCE: don't use buggy _BCL/_BCM/_BQC for backlight control
+    - LP: #311716
+  * SAUCE: test-suspend -- add the suspend test scripts
+    - LP: #316419
+
+  [ Colin Watson ]
+
+  * Enable udebs for armel
+
+  [ Tim Gardner ]
+
+  * SAUCE: Dell laptop digital mic does not work, PCI 1028:0271
+    - LP: #309508
+  * Enable CIFS_XATTR=y and CONFIG_CIFS_POSIX=y
+    - LP: #220658
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 08 Jan 2009 10:38:22 -0700
+
+linux (2.6.28-4.9) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Restore DM_CRYPT, AES, ECB, and CBC as modules. This fixes
+    some installer issues with encrypted /home and Private directories.
+  * Take one more stab at building armel without module or ABI errors.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 06 Jan 2009 08:38:23 -0700
+
+linux (2.6.28-4.8) jaunty; urgency=low
+
+  * Fix i386/amd64 FTBS by ignoring all module and ABI changes,
+    not something you would normally do, but I'm sure the ABI
+    has not changed. This will probably also allow the ARM builds to complete.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 05 Jan 2009 14:42:58 -0700
+
+linux (2.6.28-4.7) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Enable CONFIG_ATH5K=m for i386/amd64
+    - LP: #306719
+  * Build all i386/amd64 AGP/DRM components as modules.
+    - LP: #312721
+  * git commands are now installed outside the default $PATH
+    Use 'git  CMD' instead of 'git-CMD'.
+  * Build in most PATA/SATA drivers. This should allow most i386/amd64 systems to boot
+    without an initramfs, though some support work is still required in initramfs-tools
+    and grub.
+    - LP: #311730
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 02 Jan 2009 07:33:09 -0700
+
+linux (2.6.28-4.6) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Enable CONFIG_X86_E_POWERSAVER=m for i386 generic
+    - LP: #237405
+  * Build i386 AGP drivers as modules
+    - LP: #312721
+  * Build i386 DRM as a module
+    - LP: #312721
+
+  [ Upstream Kernel Changes ]
+
+  * drm/i915: Add missing userland definitions for gem init/execbuffer.
+    - LP: #308387
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 29 Dec 2008 09:16:47 -0700
+
+linux (2.6.28-4.5) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * clean up module dependancy information on package removal/purge
+    - LP: #300773
+
+  [ Tim Gardner ]
+
+  * Update iscsitarget to 0.4.17
+  * Build in ext{234}
+  * Build in Crypto modules AES, CBC, ECB
+  * Build in ACPI AC,BATTERY,BUTTON,FAN,PCI_SLOT,PROCESSOR,SBS,THERMAL,WMI
+  * Build in AGP intel,via,sis,ali,amd,amd64,efficeon,nvidia,sworks
+  * Build in ata,dev_dm,dev_loop,dev_md,dev_sd,dev_sr
+  * Build in BT l2cap,rfcomm,sco
+  * Reduce CONFIG_LEGACY_PTY_COUNT to 0
+  * Build in CDROM_PKTCDVD and CHR_DEV_SG
+  * Build in CPU_FREQ
+    GOV_CONSERVATIVE,GOV_ONDEMAND,GOV_POWERSAVE,GOV_USERSPACE,STAT,TABLE
+  * Build in DM CRYPT,MIRROR,MULTIPATH,SNAPSHOT
+  * Build in DRM
+  * Build in HID
+  * Build in HOTPLUG PCI,PCIE
+  * Build in I2C
+  * Build in IEEE1394 OHCI1394
+  * Build in INPUT EVDEV
+  * Build in IPV6
+  * Build in MMC
+  * Build in PACKET
+  * Enable both IEEE1394 (Firewire) stacks as modules
+    - LP: #276463
+  * Disable SUNRPC_REGISTER_V4
+    - LP: #306016
+  * Enable dm-raid4-5
+    - LP: #309378
+  * Build in PPP
+  * Build in RFKILL
+  * Build in USB SERIAL
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 18 Dec 2008 21:18:44 -0700
+
+linux (2.6.28-3.4) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Build ecryptfs into the kernel
+    - LP: #302870
+  * Deprecated gnbd
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28-rc8
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 10 Dec 2008 22:45:13 -0700
+
+linux (2.6.28-2.3) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update the templates so that we have spaces following the title line
+
+  [ Tim Gardner ]
+
+  * Add upload number to kernel version signature. This has the side effect
+    of renaming kernel packages back to the original way, e.g., without '-ub'
+    in the name.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 04 Dec 2008 12:18:31 -0700
+
+linux (2.6.28-2.2) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: (no-up) version: Implement version_signature proc file."
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: serial: RS485 ioctl structure uses __u32 include linux/types.h
+    - LP: #303711
+
+  [ Tim Gardner ]
+
+  * UBUNTU: Removed CONFIG_DRM_VIA_CHROME9 since it is upstream.
+  * UBUNTU: Removed ubuntu/via_chrome9
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28-rc7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 02 Dec 2008 07:33:32 -0700
+
+linux (2.6.28-1.1) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * SAUCE: make fc transport removal of target configurable
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+  * SAUCE: Adds support for COMPAL JHL90 webcam
+  * Map armel to arm to all editconfigs to work correctly
+  * Add armel to getabis for completeness sake
+  * Add -ub to our versioning to allow kerneloops.org to identify us
+
+  [ Andy Whitcroft ]
+
+  * Fix Vcs-Git path for the kernel repository.
+    - LP: #296915
+
+  [ Ben Collins ]
+
+  * SAUCE: Lower warning level of some PCI messages
+    - LP: #159241
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: (no-up) connector.h: Add idx/val for drbd
+  * SAUCE: (no-up) swap: Add notify_swap_entry_free callback for compcache
+  * SAUCE: drivers: Remove some duplicate device entries in various modules
+  * SAUCE: (no-up) [AppArmor] merge with upstream subversion r1291
+  * SAUCE: (no-up) Enable ubuntu extra subdirectory
+  * SAUCE: (no-up) ACPI: initramfs DSDT override support
+  * ubuntu: Add drbd module
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Add BOM for iscsitarget
+  * ubuntu: Add squashfs driver
+  * SAUCE: (no-up) Check for squashfs superblock in initramfs mounting.
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Added et131x driver
+  * ubuntu: Add dm-raid4-5 driver
+  * ubuntu: Add ndiswrapper driver
+  * ubuntu: Added ram backed compressed swap module (compcache)
+  * ubuntu: Add misc drivers from hardy lum
+  * ubuntu: Add heci driver 3.2.0.24
+  * ubuntu: Add ov511 and bt-sco drivers
+  * ubuntu: Add acx, prism2_usb wireless drivers
+  * ubuntu: Add at76 driver to build
+  * ubuntu: Add fsam7400 sw kill switch driver
+  * ubuntu: Added qc-usb driver
+  * ubuntu: e1000e: Upgraded module to 0.4.1.7
+  * ubuntu: Added rfkill drivers
+  * ubuntu: VIA - Add VIA DRM Chrome9 3D engine
+  * ubuntu: unionfs: Added v1.4 module from hardy
+  * ubuntu: Add LIRC driver
+  * ubuntu: Add GFS driver
+  * ubuntu: New tlsup driver for toshiba laptops
+  * SAUCE: (no-up) Export lookup_has for aufs
+  * SAUCE: (no-up) Modularize vesafb
+  * ubuntu: Config files
+  * Disable some modules that need porting to 2.6.28
+  * ubuntu: Fixup headers creation to include arch/*/include
+  * ubuntu/module-check: Ignore comment lines
+
+  [ Chuck Short ]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+
+  [ cking ]
+
+  * SAUCE: Enable speedstep for sonoma processors.
+
+  [ Colin Ian King ]
+
+  * ubuntu: Add dm-loop
+  * SAUCE: cx88: Support Leadtek WinFast DTV2000 H version J.
+  * SAUCE: fix kernel oops in VirtualBox during paravirt patching
+  * SAUCE: qc-usb: Enable Logitech QuickCam Messenger
+  * SAUCE: appleir: Enable driver for new MacBook Pro
+
+  [ Colin Watson ]
+
+  * Enable configfs, fuse, jfs, reiserfs, and xfs for armel
+  * Extend debian/d-i/ modules handling to make armel easier to support
+  * Create udebs for armel
+
+  [ Fabio M. Di Nitto ]
+
+  * ubuntu: update GFS Cluster File System
+
+  [ Kees Cook ]
+
+  * SAUCE: AppArmor: update to upstream subversion r1302
+
+  [ Leann Ogasawara ]
+
+  * Add automatic model setting for Samsung Q45
+  * Add Dell Dimension 9200 reboot quirk
+
+  [ Mackenzie Morgan ]
+
+  * SAUCE: Add quirk for ASUS Z37E to make sound audible after resume
+
+  [ Matthew Garrett ]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [ Michael Frey (Senior Manager, MID ]
+
+  * SAUCE: Send HCI_RESET for Broadcomm 2046
+
+  [ Michael Haas ]
+
+  * add proper aufs source tree from 20080922
+  * Fix AUFS compilation in vfsub.c
+  * Add splice-2.6.23.patch from AUFS to export a symbol needed by AUFS
+  * Add put_filp.patch from AUFS to export a symbol needed by AUFS
+  * Add deny_write_access.patch from AUFS - export deny_write_access
+  * Add sec_perm-2.6.24.patch from AUFS - export security_inode_permission
+  * make sure TMPFS_MAGIC is defined in AUFS Makefile
+  * SAUCE: Revert aufs changes from AppArmor merge
+
+  [ Mohamed Abbas ]
+
+  * SAUCE: iwlagn -- fix rfkill when on when driver loaded
+
+  [ Phillip Lougher ]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [ Stefan Bader ]
+
+  * SAUCE: (no-up) Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers
+  * gfs1: GFS1 can't create more than 4kb file
+  * uvcvideo: Commit streaming parameters when enabling the video stream.
+
+  [ Tim Gardner ]
+
+  * SAUCE: Add extra headers to linux-libc-dev
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: (no-up) Take care of orinoco_cs overlap with hostap_cs
+  * ubuntu: Add GNBD driver
+  * SAUCE: e1000e: Map NV RAM dynamically only when needed.
+  * SAUCE: Correctly blacklist Thinkpad r40e in ACPI
+  * SAUCE: Update Wacom tablet driver to 1.49
+  * SAUCE: Fix Wacom tablet 1.49 porting errors
+  * SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit controller
+  * SAUCE: Fix Oops in wlan_setup
+  * SAUCE: ipw2200: change default policy for auto-associate
+  * Dell Wireless 365 needs BTUSB_RESET quirk.
+  * ndiswrapper remote buffer overflows on long ESSIDs (CVE 2008-4395)
+  * Disabled ubuntu/e1000e config
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+  * Revert "x86, early_ioremap: fix fencepost error"
+  * mac80211: fix two issues in debugfs
+  * iwl3945: do not send scan command if channel count zero
+
+ --  Ben Collins <ben.collins@canonical.com>  Fri, 07 Nov 2008 09:37:42 -0700
+
+linux (2.6.27-8.17) intrepid-proposed; urgency=low
+
+  [ John W. Linville ]
+
+  * SAUCE: iwlagn: avoid sleep in softirq context
+    -LP: #286285
+
+  [ Tim Gardner ]
+
+  * Dell Wireless 365 needs BTUSB_RESET quirk.
+    - LP: #293670
+  * SAUCE: ALSA: hda: make a STAC_DELL_EQ option (version 2)
+    - LP: #293271
+
+  [ Upstream Kernel Changes ]
+
+  * iwlagn: downgrade BUG_ON in interrupt
+  * Input: atkbd - expand Latitude's force release quirk to other Dells
+  * fbcon_set_all_vcs: fix kernel crash when switching the rotated consoles
+  * modules: fix module "notes" kobject leak
+  * Driver core: Fix cleanup in device_create_vargs().
+  * Driver core: Clarify device cleanup.
+  * ath9k/mac80211: disallow fragmentation in ath9k, report to userspace
+  * md: Fix rdev_size_store with size == 0
+  * xfs: fix remount rw with unrecognized options
+  * OHCI: Allow broken controllers to auto-stop
+  * USB: OHCI: fix endless polling behavior
+  * USB: Fix s3c2410_udc usb speed handling
+  * USB: EHCI: log a warning if ehci-hcd is not loaded first
+  * usb gadget: cdc ethernet notification bugfix
+  * usb: musb_hdrc build fixes
+  * drm/i915: fix ioremap of a user address for non-root (CVE-2008-3831)
+  * DVB: au0828: add support for another USB id for Hauppauge HVR950Q
+  * DVB: sms1xxx: support two new revisions of the Hauppauge WinTV
+    MiniStick
+  * security: avoid calling a NULL function pointer in
+    drivers/video/tvaudio.c
+  * Linux 2.6.27.3
+    -LP: #294152
+
+  * gpiolib: fix oops in gpio_get_value_cansleep()
+  * edac cell: fix incorrect edac_mode
+  * x86 ACPI: fix breakage of resume on 64-bit UP systems with SMP kernel
+  * sched: fix the wrong mask_len
+  * USB: cdc-wdm: make module autoload work
+  * USB: don't rebind drivers after failed resume or reset
+  * USB: fix memory leak in cdc-acm
+  * USB: Speedtouch: add pre_reset and post_reset routines
+  * dm kcopyd: avoid queue shuffle
+  * dm snapshot: fix primary_pe race
+  * amd_iommu: fix nasty bug that caused ILLEGAL_DEVICE_TABLE_ENTRY errors
+  * CIFS: fix saving of resume key before CIFSFindNext
+  * netfilter: xt_iprange: fix range inversion match
+  * netfilter: snmp nat leaks memory in case of failure
+  * netfilter: restore lost ifdef guarding defrag exception
+  * anon_vma_prepare: properly lock even newly allocated entries
+  * hvc_console: Fix free_irq in spinlocked section
+  * ACPI Suspend: Enable ACPI during resume if SCI_EN is not set
+  * ACPI suspend: Blacklist HP xw4600 Workstation for old code ordering
+  * ACPI suspend: Always use the 32-bit waking vector
+  * proc: fix vma display mismatch between /proc/pid/{maps,smaps}
+  * SCSI: scsi_dh: add Dell product information into rdac device handler
+  * PCI hotplug: cpqphp: fix kernel NULL pointer dereference
+  * V4L/DVB (9300): pvrusb2: Fix deadlock problem
+  * Linux 2.6.27.4
+    -LP: #294155
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 04 Nov 2008 12:16:07 -0700
+
+linux (2.6.27-7.16) intrepid-security; urgency=low
+
+  [ Tim Gardner ]
+
+  * ndiswrapper remote buffer overflows on long ESSIDs (CVE 2008-4395)
+    - LP: #275860
+
+  [ Upstream Kernel Changes ]
+
+  * ext[234]: Avoid printk floods in the face of directory corruption
+    (CVE-2008-3528)
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 03 Nov 2008 13:34:42 -0700
+
+linux (2.6.27-7.15) intrepid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * tcp: Restore ordering of TCP options for the sake of inter-operability
+    - LP: #264019
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 27 Oct 2008 19:28:06 -0600
+
+linux (2.6.27-7.14) intrepid; urgency=low
+
+  [ Tim Gardner ]
+
+  * Disable ath5k in 2.6.27
+    - LP: #288148
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 23 Oct 2008 07:40:43 -0600
+
+linux (2.6.27-7.13) intrepid; urgency=low
+
+  [ Stefan Bader ]
+
+  * gfs1: GFS1 can't create more than 4kb file
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors
+    bitmap.". Use upstream commit to avoid future conflicts.
+  * Revert "STABLE queue: mac80211: fix two issues in debugfs".
+    Use upstream commit to avoid future conflicts.
+  * Revert "x86, early_ioremap: fix fencepost error"
+    Use upstream commit to avoid future conflicts.
+
+  [ Upstream Kernel Changes ]
+
+  * sched_rt.c: resch needed in rt_rq_enqueue() for the root rt_rq
+  * x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap.
+  * mac80211: fix two issues in debugfs
+  * Fix barrier fail detection in XFS
+  * tty: Termios locking - sort out real_tty confusions and lock reads
+  * CIFS: make sure we have the right resume info before calling
+    CIFSFindNext
+  * rfkill: update LEDs for all state changes
+  * libertas: clear current command on card removal
+  * b43legacy: Fix failure in rate-adjustment mechanism
+  * x86, early_ioremap: fix fencepost error
+  * x86: SB450: skip IRQ0 override if it is not routed to INT2 of IOAPIC
+  * x86: improve UP kernel when CPU-hotplug and SMP is enabled
+  * sky2: Fix WOL regression
+  * netdrvr: atl1e: Don't take the mdio_lock in atl1e_probe
+  * Linux 2.6.27.2
+
+  [ Amit Kucheria ]
+
+  * Ubuntu: agp: Fix stolen memory counting on G4X.
+    -LP: 285572
+
+  [ Scott Remnant ]
+
+  * add MODULE_ALIAS to load ipmi_devintf with ipmi_si
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 19 Oct 2008 10:06:21 -0600
+
+linux (2.6.27-7.12) intrepid; urgency=low
+
+  [ Chuck Short ]
+
+  * xen: Add xen modules to virtual flavours.
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Add back in lost commit for Apple BT Wireless Keyboard
+    - LP: #162083
+
+  [ Tim Gardner ]
+
+  * Remove depmod created files from packages.
+    - LP: #250511
+  *  Changed default TCP congestion algorithm to 'cubic' (again)
+    - LP: #278801
+  * Update configs for 'disable CONFIG_DYNAMIC_FTRACE'
+    - LP: #263555
+
+  [ Upstream Kernel Changes ]
+
+  * x86: register a platform RTC device if PNP doesn't describe it
+  * disable CONFIG_DYNAMIC_FTRACE due to possible memory corruption on
+    module unload
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 17 Oct 2008 11:25:39 -0600
+
+linux (2.6.27-7.11) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * STABLE queue: mac80211: fix two issues in debugfs
+    - LP: #275227
+  * SAUCE: Adds support for COMPAL JHL90 webcam
+
+  [ Ben Collins ]
+
+  * SAUCE: (no-up) x86: Quiet "Kernel alive" messages
+    - LP: #39985
+  * SAUCE: (no-up) Modularize vesafb
+  * build/config: Enable vesafb module
+  * build: Switch to vesafb as preferred.
+
+  [ Leann Ogasawara ]
+
+  * Add Dell Dimension 9200 reboot quirk
+    - LP: #271370
+
+  [ Michael Haas ]
+
+  * SAUCE: Revert aufs changes from AppArmor merge
+
+  [ Tim Gardner ]
+
+  * fix virtio udeb layout
+    - LP: #257739
+  * Enabled CONFIG_EXT4DEV_FS=m
+  * Changed default TCP congestion algorithm to 'cubic'
+    - LP: #278801
+  * SAUCE: ipw2200: change default policy for auto-associate
+    - LP: #264104
+
+  [ Upstream Kernel Changes ]
+
+  * x86, early_ioremap: fix fencepost error
+    - LP: #263543
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 11 Oct 2008 08:07:42 -0600
+
+linux (2.6.27-7.10) intrepid; urgency=low
+
+  [ Alexey Starikovskiy ]
+
+  * SAUCE: ACPI: EC: do transaction from interrupt context
+    - LP: #277802
+
+  [ Ben Collins ]
+
+  * build/d-i: Change virtio-modules udeb to prio standard
+
+  [ Colin Ian King ]
+
+  * SAUCE: Blacklist IBM 2656 in serio/i8042
+    - LP: #21558
+
+  [ Henrik Rydberg ]
+
+  * Revert "SAUCE: applesmc: Add MacBookAir"
+  * SAUCE: [PATCH 1/5] hwmon: applesmc: Specified number of bytes to read
+    should match actual
+  * SAUCE: [PATCH 2/5] hwmon: applesmc: Fix the 'wait status failed: c !=
+    8' problem
+  * SAUCE: [PATCH 3/5] hwmon: applesmc: Prolong status wait
+  * SAUCE: [PATCH 4/5] hwmon: applesmc: Allow for variable ALV0 and ALV1
+    package length
+  * SAUCE: [PATCH 5/5] hwmon: applesmc: Add support for Macbook Air
+  * SAUCE: hwmon: applesmc: Add support for Macbook Pro 4
+  * SAUCE: hwmon: applesmc: Add support for Macbook Pro 3
+  * SAUCE: hwmon: applesmc: Lighter wait mechanism, drastic improvement
+
+  [ Leann Ogasawara ]
+
+  * Add automatic model setting for Samsung Q45
+    - LP: #200210
+
+  [ Tim Gardner ]
+
+  * SAUCE: Correctly blacklist Thinkpad r40e in ACPI
+    - LP: #278794
+  * SAUCE: Update Wacom tablet driver to 1.49
+    - LP: #260675
+  * SAUCE: ALPS touchpad for Dell Latitude E6500/E6400
+    - LP: #270643
+  * SAUCE: Fix Wacom tablet 1.49 porting errors
+  * SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit controller
+  * SAUCE: Fix Oops in wlan_setup
+    - LP: #263309
+
+  [ Upstream Kernel Changes ]
+
+  * ath9k: fix oops on trying to hold the wrong spinlock
+  * [Bluetooth] Fix double frees on error paths of btusb and bpa10x drivers
+  * [Bluetooth] Add reset quirk for new Targus and Belkin dongles
+  * [Bluetooth] Add reset quirk for A-Link BlueUSB21 dongle
+  * Revert "ax25: Fix std timer socket destroy handling."
+  * ax25: Quick fix for making sure unaccepted sockets get destroyed.
+  * netrom: Fix sock_orphan() use in nr_release
+  * Revert "V4L/DVB (8904): cx88: add missing unlock_kernel"
+  * SLOB: fix bogus ksize calculation
+  * net: only invoke dev->change_rx_flags when device is UP
+  * tcp: Fix possible double-ack w/ user dma
+  * net: Fix netdev_run_todo dead-lock
+  * tcp: Fix tcp_hybla zero congestion window growth with small rho and large cwnd.
+  * [MIPS] Sibyte: Register PIO PATA device only for Swarm and Litte Sur
+  * eeepc-laptop: Fix hwmon interface
+  * hwmon: (it87) Prevent power-off on Shuttle SN68PT
+  * hwmon: Define sysfs interface for energy consumption register
+  * hwmon: (adt7473) Fix some bogosity in documentation file
+  * hwmon: (abituguru3) Enable reading from AUX3 fan on Abit AT8 32X
+  * hwmon: (abituguru3) Enable DMI probing feature on Abit AT8 32X
+  * [CPUFREQ] correct broken links and email addresses
+  * SLOB: fix bogus ksize calculation fix
+  * Don't allow splice() to files opened with O_APPEND
+  * Linux 2.6.27
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 08 Oct 2008 21:19:34 -0600
+
+linux (2.6.27-6.9) intrepid; urgency=low
+
+  [ Kees Cook ]
+
+  * SAUCE: AppArmor: update to upstream subversion r1302
+    - LP: #269921
+
+  [ Stefan Bader ]
+
+  * Update configuration files to be compliant to desktop specs
+    - LP: #279019
+
+  [ Tim Gardner ]
+
+  * Add support in e1000e for a couple of ICH10 PCI IDs
+  * Enable CONFIG_INPUT_PCSPKR=m
+    - LP: #275453
+
+  [ Upstream Kernel Changes ]
+
+  * V4L/DVB (8559a): Fix a merge conflict at gspca/sonixb
+  * V4L/DVB (8789): wm8739: remove wrong kfree
+  * V4L/DVB (8883): w9968cf: Fix order of usb_alloc_urb validation
+  * V4L/DVB (8884): em28xx-audio: fix memory leak
+  * V4L/DVB (8885): cpia2_usb: fix memory leak
+  * V4L/DVB (8886): ov511: fix memory leak
+  * V4L/DVB (8887): gspca: fix memory leak
+  * V4L/DVB (8892): pvrusb2: Handle USB ID 2040:2950 same as 2040:2900
+  * V4L/DVB (8904): cx88: add missing unlock_kernel
+  * V4L/DVB (8905): ov511: fix exposure sysfs attribute bug
+  * V4L/DVB (8909): gspca: PAC 7302 webcam 093a:262a added.
+  * hrtimer: migrate pending list on cpu offline
+  * hrtimer: fix migration of CB_IRQSAFE_NO_SOFTIRQ hrtimers
+  * hrtimer: mark migration state
+  * hrtimer: prevent migration of per CPU hrtimers
+  * [IA64] Put the space for cpu0 per-cpu area into .data section
+  * powerpc: Fix PCI in Holly device tree
+  * powerpc: Fix failure to shutdown with CPU hotplug
+  * mfd: Fix Kconfig accroding to the new gpiolib symbols
+  * mfd: Fix asic3 compilation
+  * x86: fix typo in enable_mtrr_cleanup early parameter
+  * ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space
+  * iucv: Fix mismerge again.
+  * ALSA: ASoC: Fix cs4270 error path
+  * ALSA: hda - Fix model for Dell Inspiron 1525
+  * sctp: Fix kernel panic while process protocol violation parameter
+  * x86: Fix broken LDT access in VMI
+  * x86, vmi: fix broken LDT access
+  * tcp: Fix NULL dereference in tcp_4_send_ack()
+  * ipv6: NULL pointer dereferrence in tcp_v6_send_ack
+  * XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep
+  * af_key: Free dumping state on socket close
+  * dm: always allow one page in dm_merge_bvec
+  * dm: cope with access beyond end of device in dm_merge_bvec
+  * dm mpath: add missing path switching locking
+  * MN10300: Fix IRQ handling
+  * pxa2xx_spi: fix build breakage
+  * e1000e: write protect ICHx NVM to prevent malicious write/erase
+  * powerpc: Fix boot hang regression on MPC8544DS
+  * ASoC: Set correct name for WM8753 rec mixer output
+  * ALSA: snd-powermac: mixers for PowerMac G4 AGP
+  * ALSA: snd-powermac: HP detection for 1st iMac G3 SL
+  * fbcon: fix monochrome color value calculation
+  * inotify: fix lock ordering wrt do_page_fault's mmap_sem
+  * braille_console: only register notifiers when the braille console is used
+  * fix error-path NULL deref in alloc_posix_timer()
+  * memory hotplug: missing zone->lock in test_pages_isolated()
+  * mm: tiny-shmem nommu fix
+  * mm: handle initialising compound pages at orders greater than MAX_ORDER
+  * e1000e: reset swflag after resetting hardware
+  * e1000e: do not ever sleep in interrupt context
+  * e1000e: remove phy read from inside spinlock
+  * e1000e: drop stats lock
+  * e1000e: debug contention on NVM SWFLAG
+  * e1000e: update version from k4 to k6
+  * Check mapped ranges on sysfs resource files
+  * e1000e: Fix incorrect debug warning
+  * [MIPS] Build fix: Fix irq flags type
+  * [MIPS] SMTC: Build fix: Fix filename in Makefile
+  * [MIPS] SMTC: Fix holes in SMTC and FPU affinity support.
+  * [MIPS] SMTC: Close tiny holes in the SMTC IPI replay system.
+  * [MIPS] SMTC: Fix SMTC dyntick support.
+  * [S390] nohz: Fix __udelay.
+  * [S390] qdio: prevent stack clobber
+  * Fix init/main.c to use regular printk with '%pF' for initcall fn
+  * x86 setup: correct segfault in generation of 32-bit reloc kernel
+  * selinux: Fix an uninitialized variable BUG/panic in selinux_secattr_to_sid()
+  * rtc: fix kernel panic on second use of SIGIO nofitication
+  * fbdev: fix recursive notifier and locking when fbdev console is blanked
+  * orion_spi: fix handling of default transfer speed
+  * include/linux/stacktrace.h: declare struct task_struct
+  * cpusets: remove pj from cpuset maintainers
+  * MAINTAINERS: add mailing list for man-pages
+  * SubmitChecklist: interfaces changes should CC linux-api@
+  * Documentation/HOWTO: info about interface changes should CC linux-api@vger
+  * dw_dmac: fix copy/paste bug in tasklet
+  * leds-fsg: change order of initialization and deinitialization
+  * leds-pca955x: add proper error handling and fix bogus memory handling
+  * ACPI: Make /proc/acpi/wakeup interface handle PCI devices (again)
+  * clockevents: check broadcast tick device not the clock events device
+  * V4L/DVB (8919): cx18: Fix tuner audio input for Compro H900 cards
+  * V4L/DVB (8926): gspca: Bad fix of leak memory (changeset 43d2ead315b1).
+  * V4L/DVB (8933): gspca: Disable light frquency for zc3xx cs2102 Kokom.
+  * V4L/DVB (8935): em28xx-cards: Remove duplicate entry (EM2800_BOARD_KWORLD_USB2800)
+  * V4L/DVB (8955): bttv: Prevent NULL pointer dereference in radio_open
+  * V4L/DVB (8957): zr36067: Restore the default pixel format
+  * V4L/DVB (8958): zr36067: Return proper bytes-per-line value
+  * V4L/DVB (8960): drivers/media/video/cafe_ccic.c needs mm.h
+  * V4L/DVB (8961): zr36067: Fix RGBR pixel format
+  * V4L/DVB (8963): s2255drv field count fix
+  * V4L/DVB (8967): Use correct XC3028L firmware for AMD ATI TV Wonder 600
+  * V4L/DVB (8978): sms1xxx: fix product name for Hauppauge WinTV MiniStick
+  * V4L/DVB (8979): sms1xxx: Add new USB product ID for Hauppauge WinTV MiniStick
+  * V4L/DVB (9029): Fix deadlock in demux code
+  * V4L/DVB (9037): Fix support for Hauppauge Nova-S SE
+  * V4L/DVB (9043): S5H1420: Fix size of shadow-array to avoid overflow
+  * V4L/DVB (9053): fix buffer overflow in uvc-video
+  * V4L/DVB (9075): gspca: Bad check of returned status in i2c_read() spca561.
+  * V4L/DVB (9080): gspca: Add a delay after writing to the sonixj sensors.
+  * V4L/DVB (9092): gspca: Bad init values for sonixj ov7660.
+  * V4L/DVB (9099): em28xx: Add detection for K-WORLD DVB-T 310U
+  * V4L/DVB (9103): em28xx: HVR-900 B3C0 - fix audio clicking issue
+  * x86: gart iommu have direct mapping when agp is present too
+  * ide-cd: temporary tray close fix
+  * ide-dma: fix ide_build_dmatable() for TRM290
+  * IDE: Fix platform device registration in Swarm IDE driver (v2)
+  * ide-cd: Optiarc DVD RW AD-7200A does play audio
+  * ide: workaround for bogus gcc warning in ide_sysfs_register_port()
+  * [MIPS] Fix CMP Kconfig configuration and mark as broken.
+  * [MIPS] IP27: Fix build errors if CONFIG_MAPPED_KERNEL=y
+  * x86 ACPI: Blacklist two HP machines with buggy BIOSes
+  * kgdb, x86: Avoid invoking kgdb_nmicallback twice per NMI
+  * kgdb: call touch_softlockup_watchdog on resume
+  * atmel-mci: Initialize BLKR before sending data transfer command
+  * Marker depmod fix core kernel list
+  * Linux 2.6.27-rc9
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 05 Oct 2008 21:27:49 -0600
+
+linux (2.6.27-5.8) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Update AUFS-related Kconfig
+    - LP: #264048
+
+  [ Michael Haas ]
+
+  * add proper aufs source tree from 20080922
+  * Fix AUFS compilation in vfsub.c
+  * Add splice-2.6.23.patch from AUFS to export a symbol needed by AUFS
+  * Add put_filp.patch from AUFS to export a symbol needed by AUFS
+  * apply (modified) lhash.patch from AUFS to export __lookup_hash()
+  * Add deny_write_access.patch from AUFS - export deny_write_access
+  * Add sec_perm-2.6.24.patch from AUFS - export security_inode_permission
+  * make sure TMPFS_MAGIC is defined in AUFS Makefile
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_IPWIRELESS
+    - LP: #274748
+  * Enabled CONFIG_E1000E, disabled CONFIG_E1000E_NEW
+    This takes advantage of the upstream NVM protection fix in
+    commit 4a7703582836f55a1cbad0e2c1c6ebbee3f9b3a7.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+  * [SCSI] qla2xxx: Defer enablement of RISC interrupts until ISP
+    initialization completes.
+  * PCI: Fix pcie_aspm=force
+  * PCI: fix compiler warnings in pci_get_subsys()
+  * UBIFS: create the name of the background thread in every case
+  * UBIFS: TNC / GC race fixes
+  * UBIFS: remove incorrect assert
+  * UBIFS: fix printk format warnings
+  * AMD IOMMU: set iommu sunc flag after command queuing
+  * AMD IOMMU: protect completion wait loop with iommu lock
+  * sparc64: Fix disappearing PCI devices on e3500.
+  * x86, oprofile: BUG scheduling while atomic
+  * ALSA: ASoC: Fix at32-pcm build breakage with PM enabled
+  * ath9k: connectivity is lost after Group rekeying is done
+  * wireless: zd1211rw: add device ID fix wifi dongle "trust nw-3100"
+  * [IA64] Ski simulator doesn't need check_sal_cache_flush
+  * [IA64] kexec fails on systems with blocks of uncached memory
+  * ath9k: Fix IRQ nobody cared issue with ath9k
+  * [Bluetooth] Fix I/O errors on MacBooks with Broadcom chips
+  * [Bluetooth] Fix wrong URB handling of btusb driver
+  * [Bluetooth] Fix USB disconnect handling of btusb driver
+  * sparc64: Fix missing devices due to PCI bridge test in
+    of_create_pci_dev().
+  * [WATCHDOG] ibmasr: remove unnecessary spin_unlock()
+  * [WATCHDOG] wdt285: fix sparse warnings
+  * [WATCHDOG] unlocked_ioctl changes
+  * x86: fix 27-rc crash on vsmp due to paravirt during module load
+  * sched: fix init_hrtick() section mismatch warning
+  * clockevents: prevent cpu online to interfere with nohz
+  * x86: prevent stale state of c1e_mask across CPU offline/online
+  * clockevents: prevent stale tick_next_period for onlining CPUs
+  * clockevents: check broadcast device not tick device
+  * clockevents: prevent mode mismatch on cpu online
+  * x86: prevent C-states hang on AMD C1E enabled machines
+  * x86: c1e_idle: don't mark TSC unstable if CPU has invariant TSC
+  * timers: fix build error in !oneshot case
+  * ALSA: ASoC: maintainers - update email address for Liam Girdwood
+  * ibmasr: remove unnecessary spin_unlock()
+  * smb.h: do not include linux/time.h in userspace
+  * kernel-doc: allow structs whose members are all private
+  * kexec: fix segmentation fault in kimage_add_entry
+  * Documentation/DMA-mapping.txt: update for pci_dma_mapping_error()
+    changes
+  * sys_paccept: disable paccept() until API design is resolved
+  * mm: tiny-shmem fix lock ordering: mmap_sem vs i_mutex
+  * Documentation/sysctl/kernel.txt: fix softlockup_thresh description
+  * memcg: check under limit at shrink_usage
+  * atmel_serial: update the powersave handler to match serial core
+  * [SCSI] Fix hang with split requests
+  * USB Storage: Sierra: Non-configurable TRU-Install
+  * USB Serial: Sierra: Device addition & version rev
+  * USB: ehci: fix some ehci hangs and crashes
+  * USB: Fix the Nokia 6300 storage-mode.
+  * USB: Correct Sierra Wireless USB EVDO Modem Device ID
+  * USB: fix hcd interrupt disabling
+  * USB: update of Documentation/usb/anchors.txt
+  * usb gadget: fix omap_udc DMA regression
+  * USB: Fixing Nokia 3310c in storage mode
+  * usb: musb: fix include path
+  * USB: fix EHCI periodic transfers
+  * usb-serial: Add Siemens EF81 to PL-2303 hack triggers
+  * USB: SERIAL CP2101 add device IDs
+  * USB: unusual_devs addition for RockChip MP3 player
+  * USB: fsl_usb2_udc: fix VDBG() format string
+  * usb serial: ti_usb_3410_5052 obviously broken by firmware changes
+  * USB: ftdi_sio: Add 0x5050/0x0900 USB IDs (Papouch Quido USB 4/4)
+  * USB: serial: add ZTE CDMA Tech id to option driver
+  * USB Serial: Sierra: Add MC8785 VID/PID
+  * USB: drivers/usb/musb/: disable it on SuperH
+  * usb: ftdi_sio: add support for Domintell devices
+  * usb: unusual devs patch for Nokia 5310 Music Xpress
+  * USB: revert recovery from transient errors
+  * [MIPS] au1000: Fix gpio direction
+  * [MIPS] Fixe the definition of PTRS_PER_PGD
+  * x86: prevent stale state of c1e_mask across CPU offline/online, fix
+  * x86: disable apm on the olpc
+  * i2c-powermac: Fix section for probe and remove functions
+  * i2c-dev: Return correct error code on class_create() failure
+  * i2c: Fix mailing lists in two MAINTAINERS entries
+  * ath9k: disable MIB interrupts to fix interrupt storm
+  * 9p: implement proper trans module refcounting and unregistration
+  * 9p-trans_fd: fix trans_fd::p9_conn_destroy()
+  * 9p-trans_fd: clean up p9_conn_create()
+  * 9p-trans_fd: don't do fs segment mangling in p9_fd_poll()
+  * 9p-trans_fd: fix and clean up module init/exit paths
+  * 9p: introduce missing kfree
+  * 9p: use an IS_ERR test rather than a NULL test
+  * 9p: fix put_data error handling
+  * netfilter: ip6t_{hbh,dst}: Rejects not-strict mode on rule insertion
+  * MN10300: Move asm-arm/cnt32_to_63.h to include/linux/
+  * MN10300: Make sched_clock() report time since boot
+  * ALSA: fix locking in snd_pcm_open*() and snd_rawmidi_open*()
+  * ALSA: remove unneeded power_mutex lock in snd_pcm_drop
+  * IPoIB: Fix crash when path record fails after path flush
+  * [XFS] Fix extent list corruption in xfs_iext_irec_compact_full().
+  * [XFS] Remove xfs_iext_irec_compact_full()
+  * kgdb: could not write to the last of valid memory with kgdb
+  * kgdb, x86, arm, mips, powerpc: ignore user space single stepping
+  * kgdb, x86_64: gdb serial has BX and DX reversed
+  * kgdb, x86_64: fix PS CS SS registers in gdb serial
+  * kgdboc,tty: Fix tty polling search to use name correctly
+  * ARM: Delete ARM's own cnt32_to_63.h
+  * m32r: remove the unused NOHIGHMEM option
+  * m32r: don't offer CONFIG_ISA
+  * m32r: export empty_zero_page
+  * m32r: export __ndelay
+  * m32r/kernel/: cleanups
+  * [MIPS] au1000: Make sure GPIO value is zero or one
+  * [MIPS] IP27: Switch to dynamic interrupt routing avoding panic on
+    error.
+  * [MIPS] BCM47xx: Fix build error due to missing PCI functions
+  * [SSB] Initialise dma_mask for SSB_BUSTYPE_SSB devices
+  * Swarm: Fix crash due to missing initialization
+  * ide-tape: fix vendor strings
+  * ide: note that IDE generic may prevent other drivers from attaching
+  * cdrom: update ioctl documentation
+  * [SCSI] qlogicpti: fix sg list traversal error in continuation entries
+  * sata_nv: reinstate nv_hardreset() for non generic controllers
+  * scsi: fix fall out of sg-chaining patch in qlogicpti
+  * ALSA: make the CS4270 driver a new-style I2C driver
+  * ALSA: ASoC: Fix another cs4270 error path
+  * Fix NULL pointer dereference in proc_sys_compare
+  * kconfig: fix silentoldconfig
+  * kconfig: readd lost change count
+  * mm owner: fix race between swapoff and exit
+  * Linux 2.6.27-rc8
+  * e1000e: write protect ICHx NVM to prevent malicious write/erase
+
+ -- Amit Kucheria <amit.kucheria@canonical.com>  Tue, 30 Sep 2008 18:22:35 +0300
+
+linux (2.6.27-4.7) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/abi: Add gfs1 to perm blacklist
+  * build/abi: Ignored changes in gfs2 symbols
+
+  [ Fabio M. Di Nitto ]
+
+  * Revert "SAUCE: Export gfs2 symbols required for gfs1 kernel module"
+  * ubuntu: update GFS Cluster File System
+
+  [ Stefan Bader ]
+
+  * SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap.
+    - LP: #276334
+
+  [ Tim Gardner ]
+
+  * Revert "Disable e1000e until the NVRAM corruption problem is found."
+  * Add atl1e and atl2 to Debian installer bits
+    - LP: #273904
+  * SAUCE: e1000e: Map NV RAM dynamically only when needed.
+    - LP: #263555
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 26 Sep 2008 20:51:22 -0600
+
+linux (2.6.27-4.6) intrepid; urgency=low
+
+  [ Tim Gardner ]
+
+  * Disable e1000e until the NVRAM corruption problem is found.
+    - LP: #263555
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+
+ -- Ben Collins <ben.collins@canonical.com>  Tue, 23 Sep 2008 09:53:57 -0400
+
+linux (2.6.27-4.5) intrepid; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support"
+  * udf: Fix lock inversion between iprune_mutex and alloc_mutex (v2)
+  * udf: Fix error paths in udf_new_inode()
+  * [SCSI] sd: select CRC_T10DIF only when necessary
+  * [SCSI] zfcp: Fix request queue locking
+  * [SCSI] zfcp: Correctly query end flag in gpn_ft response
+  * [SCSI] zfcp: Simplify ccw notify handler
+  * [SCSI] zfcp: Fix reference counter for remote ports
+  * [SCSI] zfcp: channel cannot be detached due to refcount imbalance
+  * [SCSI] zfcp: Remove duplicated unlikely() macros.
+  * [SCSI] scsi_dh: make check_sense return ADD_TO_MLQUEUE
+  * [SCSI] make scsi_check_sense HARDWARE_ERROR return ADD_TO_MLQUEUE on
+    retry
+  * [SCSI] fix check of PQ and PDT bits for WLUNs
+  * pcm037: add rts/cts support for serial port
+  * i.MX serial: fix init failure
+  * imx serial: set RXD mux bit on i.MX27 and i.MX31
+  * imx serial: fix rts handling for non imx1 based hardware
+  * mlx4_core: Set RAE and init mtt_sz field in FRMR MPT entries
+  * udf: add llseek method
+  * PCI/iommu: blacklist DMAR on Intel G31/G33 chipsets
+  * PCI: Fix printk warnings in probe.c
+  * PCI: Fix printk warnings in setup-bus.c
+  * PCI Hotplug: fakephp: fix deadlock... again
+  * clockevents: remove WARN_ON which was used to gather information
+  * ocfs2: Fix a bug in direct IO read.
+  * arch/x86/kernel/kdebugfs.c: introduce missing kfree
+  * [IA64] fix compile failure with non modular builds
+  * [IA64] fix up bte.h
+  * [IA64] arch/ia64/sn/pci/tioca_provider.c: introduce missing kfree
+  * PCI: fix pciehp_free_irq()
+  * [IA64] prevent ia64 from invoking irq handlers on offline CPUs
+  * ide: Fix pointer arithmetic in hpt3xx driver code (3rd try)
+  * add deprecated ide-scsi to feature-removal-schedule.txt
+  * swiotlb: fix back-off path when memory allocation fails
+  * sparc64: Fix interrupt register calculations on Psycho and Sabre.
+  * VIDEO_SH_MOBILE_CEU should depend on HAS_DMA
+  * m68k: Update defconfigs for 2.6.27-rc6
+  * sparc32: Fix function signature of of_bus_sbus_get_flags().
+  * sched: fix 2.6.27-rc5 couldn't boot on tulsa machine randomly
+  * sched: fix deadlock in setting scheduler parameter to zero
+  * KVM: SVM: fix random segfaults with NPT enabled
+  * KVM: SVM: fix guest global tlb flushes with NPT
+  * KVM: VMX: Always return old for clear_flush_young() when using EPT
+  * clocksource, acpi_pm.c: fix check for monotonicity
+  * [ARM] OMAP: Fix MMC device data
+  * block: disable sysfs parts of the disk command filter
+  * ath9k: Assign seq# when mac80211 requests this
+  * sg: disable interrupts inside sg_copy_buffer
+  * MN10300: Change the fault handler to check in_atomic() not
+    in_interrupt()
+  * [Bluetooth] Fix regression from using default link policy
+  * netlink: fix overrun in attribute iteration
+  * x86: fix possible x86_64 and EFI regression
+  * sparc64: Fix PCI error interrupt registry on PSYCHO.
+  * sparc: Fix user_regset 'n' field values.
+  * niu: panic on reset
+  * PCI: re-add debug prints for unmodified BARs
+  * [ARM] 5245/1: Fix warning about unused return value in drivers/pcmcia
+  * [ARM] 5246/1: tosa: add proper clock alias for tc6393xb clock
+  * [ARM] 5247/1: tosa: SW_EAR_IN support
+  * [ARM] Fix PCI_DMA_BUS_IS_PHYS for ARM
+  * ata: duplicate variable sparse warning
+  * sata_inic162x: enable LED blinking
+  * [libata] LBA28/LBA48 off-by-one bug in ata.h
+  * proc: more debugging for "already registered" case
+  * include/linux/ioport.h: add missing macro argument for devm_release_*
+    family
+  * cpuset: avoid changing cpuset's cpus when -errno returned
+  * cpuset: hotplug documentation fix
+  * coredump_filter: add description of bit 4
+  * bfs: fix Lockdep warning
+  * mm: ifdef Quicklists in /proc/meminfo
+  * spi_mpc83xx: fix clockrate calculation for low speed
+  * spi_mpc83xx: reject invalid transfer sizes
+  * pxa2xx_spi: chipselect bugfixes
+  * pxa2xx_spi: dma bugfixes
+  * mm: mark the correct zone as full when scanning zonelists
+  * Documentation/ABI: /sys/class/gpio
+  * MAINTAINERS: fix USB VIDEO CLASS mail list address
+  * ia64: fix panic during `modprobe -r xpc'
+  * atmel_lcdfb: disable LCD and DMA engines when suspending
+  * spi_s3c24xx: fix section warning
+  * rescan_partitions(): make device capacity errors non-fatal
+  * memstick: fix MSProHG 8-bit interface mode support
+  * Add Uwe Kleine-König to .mailmap
+  * xen: fix for xen guest with mem > 3.7G
+  * x86/paravirt: Remove duplicate paravirt_pagetable_setup_{start, done}()
+  * crypto: talitos - Avoid consecutive packets going out with same IV
+  * slub: fixed uninitialized counter in struct kmem_cache_node
+  * udp: Fix rcv socket locking
+  * IB/mlx4: Fix up fast register page list format
+  * [MIPS] VR41xx: unsigned irq cannot be negative
+  * x86: completely disable NOPL on 32 bits
+  * [S390] cio: Fix driver_data handling for ccwgroup devices.
+  * [S390] cio: fix orb initialization in cio_start_key
+  * sparc64: Fix OOPS in psycho_pcierr_intr_other().
+  * sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace.
+  * RDMA/nes: Fix client side QP destroy
+  * IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop()
+  * clockevents: make device shutdown robust
+  * powerpc: Fix interrupt values for DMA2 in MPC8610 HPCD device tree
+  * hpplus: fix build regression
+  * Fix PNP build failure, bugzilla #11276
+  * warn: Turn the netdev timeout WARN_ON() into a WARN()
+  * [XFS] Move memory allocations for log tracing out of the critical path
+  * [XFS] Fix regression introduced by remount fixup
+  * [XFS] Prevent direct I/O from mapping extents beyond eof
+  * [XFS] Fix barrier status change detection.
+  * [XFS] Prevent lockdep false positives when locking two inodes.
+  * [XFS] Fix use-after-free with buffers
+  * [XFS] Don't do I/O beyond eof when unreserving space
+  * powerpc: Holly board needs dtbImage target
+  * Fix compile failure with non modular builds
+  * [ARM] 5249/1: davinci: remove redundant check in davinci_psc_config()
+  * [ARM] omap: back out 'internal_clock' support
+  * sctp: set the skb->ip_summed correctly when sending over loopback.
+  * [ARM] 5255/1: Update jornada ssp to remove build errors/warnings
+  * sctp: do not enable peer features if we can't do them.
+  * sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH
+  * bnx2: Promote vector field in bnx2_irq structure from u16 to unsigned
+    int
+  * forcedeth: call restore mac addr in nv_shutdown path
+  * e1000: prevent corruption of EEPROM/NVM
+  * e100: Use pci_pme_active to clear PME_Status and disable PME#
+  * md: Don't wait UNINTERRUPTIBLE for other resync to finish
+  * atstk1000: fix build breakage with BOARD_ATSTK100X_SW2_CUSTOM=y
+  * avr32: add .gitignore files
+  * avr32: add generic_find_next_le_bit bit function
+  * avr32: fix sys_sync_file_range() call convention
+  * avr32: nmi_enter() without nmi_exit()
+  * KVM: ia64: 'struct fdesc' build fix
+  * hwmon: (atxp1) Fix device detection logic
+  * hwmon: (it87) Fix fan tachometer reading in IT8712F rev 0x7 (I)
+  * hwmon: (ad7414) Make ad7414_update_device() static
+  * tmio_mmc: fix compilation with debug enabled
+  * atmel-mci: debugfs: enable clock before dumping regs
+  * atmel-mci: Fix memory leak in atmci_regs_show
+  * atmel-mci: Fix bogus debugfs file size
+  * atmel-mci: Set MMC_CAP_NEEDS_POLL if no detect_pin
+  * mmc_block: handle error from mmc_register_driver()
+  * mmc_test: initialize mmc_test_lock statically
+  * [MIPS] Fix 64-bit IP checksum code
+  * [MIPS] SMTC: Clear TIF_FPUBOUND on clone / fork.
+  * [MIPS] Fix potential latency problem due to non-atomic cpu_wait.
+  * [MIPS] vmlinux.lds.S: handle .text.*
+  * MAINTAINERS: Trivial whitespace cleanups
+  * MAINTAINERS: Various fixes
+  * Linux 2.6.27-rc7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 21 Sep 2008 21:49:28 -0600
+
+linux (2.6.27-3.4) intrepid; urgency=low
+
+  [ Colin Ian King ]
+
+  * SAUCE: fix kernel oops in VirtualBox during paravirt patching
+    - LP: #246067
+  * SAUCE: qc-usb: Enable Logitech QuickCam Messenger
+    - LP: #209901
+  * SAUCE: appleir: Enable driver for new MacBook Pro
+    - LP: #157919
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_DEBUG_RODATA=y
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "ALSA: hda - Added model selection for iMac 24""
+  * Revert "x86: fix HPET regression in 2.6.26 versus 2.6.25, check hpet
+    against BAR, v3"
+  * Revert "[ARM] use the new byteorder headers"
+  * Revert "mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM"
+  * Revert "crypto: camellia - Use kernel-provided bitops, unaligned access
+    helpers"
+  * svcrdma: Fix race between svc_rdma_recvfrom thread and the dto_tasklet
+  * sched, cpuset: rework sched domains and CPU hotplug handling (v4)
+  * ACPI: Fix now signed module parameter.
+  * ACPI: Change package length error to warning
+  * ACPI: Fix now signed module parameter.
+  * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board"
+  * acpi: add checking for NULL early param
+  * UBIFS: fix zero-length truncations
+  * Input: bcm5974 - add maintainer entry
+  * sh64: re-add the __strnlen_user() prototype
+  * sh: fix ptrace_64.c:user_disable_single_step()
+  * PNPACPI: ignore the producer/consumer bit for extended IRQ descriptors
+  * UBIFS: always read hashed-key nodes under TNC mutex
+  * UBIFS: allow for racing between GC and TNC
+  * [CIFS] Fix plaintext authentication
+  * sparc32: Implement smp_call_function_single().
+  * sh: crash kernel resource fix
+  * sh: fix kexec entry point for crash kernels
+  * sh: fix platform_resource_setup_memory() section mismatch
+  * sh: update Migo-R defconfig
+  * sh: update AP325RXA defconfig
+  * sh: fix semtimedop syscall
+  * cifs: fix O_APPEND on directio mounts
+  * [CIFS] update cifs change log
+  * [CIFS] Turn off Unicode during session establishment for plaintext
+    authentication
+  * ACPI: thinkpad-acpi: wan radio control is not experimental
+  * sparc: Fix resource flags for PCI children in OF device tree.
+  * remove blk_register_filter and blk_unregister_filter in gendisk
+  * ALSA: oxygen: fix distorted output on AK4396-based cards
+  * ipv6: When we droped a packet, we should return NET_RX_DROP instead of
+    0
+  * pkt_sched: Fix locking of qdisc_root with qdisc_root_sleeping_lock()
+  * net: Unbreak userspace usage of linux/mroute.h
+  * Don't trigger softlockup detector on network fs blocked tasks
+  * Resource handling: add 'insert_resource_expand_to_fit()' function
+  * sparc64: setup_valid_addr_bitmap_from_pavail() should be __init
+  * UBIFS: do not update min_idx_lebs in stafs
+  * UBIFS: push empty flash hack down
+  * UBIFS: remove incorrect index space check
+  * UBIFS: improve statfs reporting
+  * UBIFS: fix assertion
+  * UBIFS: add forgotten gc_idx_lebs component
+  * UBIFS: introduce LEB overhead
+  * UBIFS: improve statfs reporting even more
+  * UBIFS: fill f_fsid
+  * drm/radeon: downgrade debug message from info to debug.
+  * Remove invalidate_partition call from do_md_stop.
+  * Fix problem with waiting while holding rcu read lock in md/bitmap.c
+  * ALSA: hda: Distortion fix for dell_m6_core_init
+  * ALSA: ASoC: fix pxa2xx-i2s clk_get call
+  * block: restore original behavior of /proc/partition when there's no
+    partition
+  * debugobjects: fix lockdep warning
+  * avr32: Fix lockup after Java stack underflow in user mode
+  * avr32: pm_standby low-power ram bug fix
+  * nfsd: fix compound state allocation error handling
+  * sunrpc: fix possible overrun on read of /proc/sys/sunrpc/transports
+  * nfsd: fix buffer overrun decoding NFSv4 acl
+  * audit: Moved variable declaration to beginning of function
+  * Fix modules_install on RO nfs-exported trees.
+  * Remove '#include <stddef.h>' from mm/page_isolation.c
+  * dabusb_fpga_download(): fix a memory leak
+  * [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl()
+  * ALSA: hda - Fix ALC663 auto-probe
+  * ALSA: hda - Add mic-boost controls to ALC662/663 auto configuration
+  * Un-break printk strings in x86 PCI probing code
+  * kernel/resource.c: fix new kernel-doc warning
+  * softlockup: minor cleanup, don't check task->state twice
+  * fix typo in arch/parisc/hpux/fs.c
+  * m68k: atari_keyb_init operator precedence fix
+  * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board"
+  * don't diff generated firmware files
+  * IDE: compile fix for sff_dma_ops
+  * IDE: palm_bk3710: fix compile warning for unused variable
+  * ide: fix hwif_to_node()
+  * palm_bk3710: improve IDE registration
+  * ide-disk: remove stale init_idedisk_capacity() documentation
+  * ide/Kconfig: mark ide-scsi as deprecated
+  * net/wireless/Kconfig: clarify the description for
+    CONFIG_WIRELESS_EXT_SYSFS
+  * iwlwifi: do not use GFP_DMA in iwl_tx_queue_init
+  * iwlwifi: workaround interrupt handling no some platforms
+  * iwlwifi: fix apm_stop (wrong bit polarity for FLAG_INIT_DONE)
+  * iwlwifi: fix 64bit platform firmware loading
+  * orinoco: Multicast to the specified addresses
+  * wireless/libertas/if_cs.c: fix memory leaks
+  * mac80211: Fix debugfs union misuse and pointer corruption
+  * rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON
+  * ath9k: Incorrect key used when group and pairwise ciphers are
+    different.
+  * ath9: Fix ath_rx_flush_tid() for IRQs disabled kernel warning message.
+  * net/xfrm: Use an IS_ERR test rather than a NULL test
+  * ipv: Re-enable IP when MTU > 68
+  * NTFS: update homepage
+  * mm: make setup_zone_migrate_reserve() aware of overlapping nodes
+  * VFS: fix dio write returning EIO when try_to_release_page fails
+  * acer-wmi: remove debugfs entries upon unloading
+  * mm/bootmem: silence section mismatch warning -
+    contig_page_data/bootmem_node_data
+  * MAINTAINERS: add a maintainer for the BCM5974 multitouch driver
+  * 8250: improve workaround for UARTs that don't re-assert THRE correctly
+  * mmc: at91_mci: don't use coherent dma buffers
+  * pid_ns: zap_pid_ns_processes: fix the ->child_reaper changing
+  * pid_ns: (BUG 11391) change ->child_reaper when init->group_leader exits
+  * cirrusfb: check_par fixes
+  * devcgroup: fix race against rmdir()
+  * mm: show quicklist usage in /proc/meminfo
+  * mm: size of quicklists shouldn't be proportional to the number of CPUs
+  * ipc: document the new auto_msgmni proc file
+  * hp-wmi: update to match current rfkill semantics
+  * hp-wmi: add proper hotkey support
+  * tdfxfb: fix SDRAM memory size detection
+  * tdfxfb: fix frame buffer name overrun
+  * rtc_time_to_tm: fix signed/unsigned arithmetic
+  * ibft: fix target info parsing in ibft module
+  * sysfs: document files in /sys/firmware/sgi_uv/
+  * rtc-cmos: wake again from S5
+  * pm_qos_requirement might sleep
+  * drivers/char/random.c: fix a race which can lead to a bogus BUG()
+  * ipsec: Fix deadlock in xfrm_state management.
+  * [x86] Fix TSC calibration issues
+  * tipc: Don't use structure names which easily globally conflict.
+  * sparc64: Fix IPI call locking.
+  * [ARM] omap: fix gpio.c build error
+  * sparc64: Prevent sparc64 from invoking irq handlers on offline CPUs
+  * powerpc: Fix uninitialised variable in VSX alignment code
+  * powerpc: Only make kernel text pages of linear mapping executable
+  * powerpc: Make sure _etext is after all kernel text
+  * powerpc: Work around gcc's -fno-omit-frame-pointer bug
+  * powerpc: Fix build error with 64K pages and !hugetlbfs
+  * powerpc: Fix for getting CPU number in power_save_ppc32_restore()
+  * UBIFS: amend f_fsid
+  * net/usb/pegasus: avoid hundreds of diagnostics
+  * ixgbe: initialize interrupt throttle rate
+  * pcnet-cs, axnet_cs: add new IDs, remove dup ID with less info
+  * netxen: Remove workaround for chipset quirk
+  * Split up PIT part of TSC calibration from native_calibrate_tsc
+  * iwlwifi: W/A for the TSF correction in IBSS
+  * iwlwifi: fix hidden ssid discovery in passive channels
+  * iwlwifi: remove false rxon if rx chain changes
+  * iwlwifi: fix station mimo power save values
+  * iwlwifi: fix rx_chain computation
+  * iwlwifi: fix Tx cmd memory allocation failure handling
+  * iwlwifi: call apm stop on exit
+  * iwlwifi: fix STATUS_EXIT_PENDING is not set on pci_remove
+  * ath9k: Fix TX status reporting
+  * ath9k: Fix TX control flag use for no ACK and RTS/CTS
+  * V4L/DVB (8555): au8522: add mechanism to configure IF frequency for vsb
+    and qam
+  * V4L/DVB (8556): au0828: add support for Hauppauge Woodbury
+  * V4L/DVB (8598): au8522: clean up function au8522_set_if
+  * V4L/DVB (8599): au8522: remove if frequency settings from vsb/qam
+    modulation tables
+  * V4L/DVB (8600): au0828: explicitly set 6 MHz IF frequency in
+    hauppauge_hvr950q_config
+  * V4L/DVB (8629): v4l2-ioctl: do not try to handle private V4L1 ioctls
+  * V4L/DVB (8633): ivtv: update ivtv version number
+  * V4L/DVB (8648): ivtv: improve CC support
+  * V4L/DVB (8660): gspca: Simplify the scan of URB packets in pac7311.
+  * V4L/DVB (8661): gspca: Bug in the previous changeset about pac7311.
+  * V4L/DVB (8663): gspca: Webcam 0c45:6128 added in sonixj.
+  * V4L/DVB (8664): gspca: The bridge/sensor of the webcam 093a:2621 is a
+    PAC 7302.
+  * V4L/DVB (8665): gspca: Fix the 640x480 resolution of the webcam
+    093a:2621.
+  * V4L/DVB (8666): gspca: Bad scanning of frames in pac7311.
+  * V4L/DVB (8667): gspca: Bad probe of Z-Star/Vimicro webcams with pas106
+    sensor.
+  * V4L/DVB (8668): gspca: Conflict GSPCA / ET61X251 for the webcam
+    102c:6251.
+  * V4L/DVB (8669): gspca: Add white balance control for spca561 rev 012A.
+  * V4L/DVB (8671): gspca: Remove the unused field 'dev_name' of the device
+    structure.
+  * V4L/DVB (8672): gspca: Big rewrite of spca561.
+  * V4L/DVB (8673): gspca: Bad frame scanning again and bad init in
+    pac7311.
+  * V4L/DVB (8674): gspca: Webcam 0c45:612e added in sonixj.
+  * V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated
+    by pac7311.
+  * V4L/DVB (8678): Remove the dead CONFIG_RADIO_MIROPCM20{,_RDS} code
+  * V4L/DVB (8681): v4l2-ioctl.c: fix warning
+  * V4L/DVB (8682): V4L: fix return value of register video func
+  * V4L/DVB (8701): cx18: Add missing lock for when the irq handler
+    manipulates the queues
+  * V4L/DVB (8703): gspca: Do controls work for spca561 revision 12a.
+  * V4L/DVB (8705): gspca: Adjust some control limits in spca561.
+  * V4L/DVB (8706): Make contrast and brightness work for pac7302.
+  * V4L/DVB (8707): gspca: Colors, hflip and vflip controls added for
+    pac7302.
+  * V4L/DVB (8709): gspca: Fix initialization and controls of sn9x110 -
+    ov7630.
+  * V4L/DVB (8710): gspca: Bad color control in sonixj.
+  * V4L/DVB (8711): gspca: Bad controls and quantization table of pac7311.
+  * V4L/DVB (8712): gspca: Bad start of sonixj webcams since changeset
+    a8779025e7e8.
+  * V4L/DVB (8713): gspca: Bad color control again in sonixj.
+  * V4L/DVB (8714): gspca: Bad start of sn9c110 and sensor om6802.
+  * V4L/DVB (8715): gspca: Change the name of some webcam in the gspca doc.
+  * V4L/DVB (8716): gspca: Bad start of sn9c110 and sensor ov7630.
+  * V4L/DVB (8717): gspca: Frame buffer too small for small resolutions
+    (sonixj and t613).
+  * V4L/DVB (8718): gspca: suspend/resume added.
+  * V4L/DVB (8719): gspca: Have VIDIOC_QUERYCTRL more compliant to the
+    spec.
+  * V4L/DVB (8720): gspca: V4L2_CAP_SENSOR_UPSIDE_DOWN added as a cap for
+    some webcams.
+  * V4L/DVB (8722): sms1xxx: fix typo in license header
+  * V4L/DVB (8726): link tuner before saa7134
+  * V4L/DVB (8727): V4L1: make PMS not autoprobe when builtin.
+  * V4L/DVB (8728): 1-make-pms-not-autoprobe-when-builtin update
+  * V4L/DVB (8749): Fix error code, when camera is not turned on by sonypi
+  * V4L/DVB (8750): V4L: check inval in video_register_device_index()
+  * V4L/DVB (8751): vivi: Fix some issues at vivi register routine
+  * V4L/DVB (8757): v4l-dvb: fix a bunch of sparse warnings
+  * V4L/DVB (8769): cx18: Simplify queue flush logic to prevent oops in
+    cx18_flush_queues()
+  * V4L/DVB (8778): radio: fix incorrect video_register_device result check
+  * V4L/DVB (8779): v4l: fix more incorrect video_register_device result
+    checks
+  * V4L/DVB (8790): saa7115: call i2c_set_clientdata only when state !=
+    NULL
+  * V4L/DVB (8803): s5h1409: Enable QAM_AUTO mode
+  * V4L/DVB (8804): s5h1411: Enable QAM_AUTO mode
+  * V4L/DVB (8805): Steven Toth email address change
+  * V4L/DVB (8809): gspca: Revert commit
+    9a9335776548d01525141c6e8f0c12e86bbde982
+  * V4L/DVB (8810): gspca: Compile error when CONFIG_PM not defined.
+  * V4L/DVB (8812): gspca: Do pac73xx webcams work.
+  * V4L/DVB (8813): gspca: Adjust SOF detection for pac73xx.
+  * V4L/DVB (8814): gspca: Set DISABLED the disabled controls at query
+    control time.
+  * V4L/DVB (8815): gspca: Fix problems with disabled controls.
+  * V4L/DVB (8816): gspca: Set disabled ctrls and fix a register pb with
+    ovxxxx in sonixb.
+  * V4L/DVB (8817): gspca: LED and proble changes in sonixb.
+  * V4L/DVB (8818): gspca: Reinitialize the device on resume.
+  * V4L/DVB (8819): gspca: Initialize the ov519 at open time and source
+    cleanup.
+  * V4L/DVB (8820): gspca: Change initialization and gamma of zc3xx -
+    pas106.
+  * V4L/DVB (8822): gspca: Change some subdriver functions for
+    suspend/resume.
+  * V4L/DVB (8823): gspca: H and V flips work for ov7670 only in ov519.
+  * V4L/DVB (8824): gspca: Too much code removed in the suspend/resume
+    changeset.
+  * V4L/DVB (8825): gspca: More controls for pac73xx and new webcam
+    093a:2624.
+  * V4L/DVB (8826): gspca: Webcam Labtec 2200 (093a:2626) added in pac7311.
+  * V4L/DVB (8827): gspca: Stop pac7302 autogain oscillation.
+  * V4L/DVB (8828): gspca: Set the clock at the end of initialization in
+    sonixj.
+  * V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB
+    exchanges.
+  * V4L/DVB (8830): gspca: Move some probe code to the new init function.
+  * V4L/DVB (8831): gspca: Resolve webcam conflicts between some drivers.
+  * V4L/DVB (8832): gspca: Bad pixelformat of vc0321 webcams.
+  * V4L/DVB (8833): gspca: Cleanup the sonixb code.
+  * V4L/DVB (8834): gspca: Have a bigger buffer for sn9c10x compressed
+    images.
+  * V4L/DVB (8835): gspca: Same pixfmt as the sn9c102 driver and raw Bayer
+    added in sonixb.
+  * V4L/DVB (8837): dvb: fix I2C adapters name size
+  * V4L/DVB (8839): dib0700: add comment to identify 35th USB id pair
+  * V4L/DVB (8840): dib0700: add basic support for Hauppauge Nova-TD-500
+    (84xxx)
+  * V4L/DVB (8842): vivi_release(): fix use-after-free
+  * V4L/DVB (8843): tda10048_firmware_upload(): fix a memory leak
+  * V4L/DVB (8844): dabusb_fpga_download(): fix a memory leak
+  * bnx2x: Accessing un-mapped page
+  * SELinux: memory leak in security_context_to_sid_core
+  * x86: add io delay quirk for Presario F700
+  * mmap: fix petty bug in anonymous shared mmap offset handling
+  * x86: Change warning message in TSC calibration.
+  * PCI: fix pbus_size_mem() resource alignment for CardBus controllers
+  * [ARM] omap: fix build error in ohci-omap.c
+  * [ARM] remove unused #include <version.h>
+  * ACPI: Make Len Brown the ACPI maintainer again
+  * fujitsu-laptop: fix regression for P8010 in 2.6.27-rc
+  * ACPI: Avoid bogus timeout about SMbus check
+  * acer-wmi: remove debugfs entries upon unloading
+  * forgotten refcount on sysctl root table
+  * V4L/DVB (8868): gspca: Support for vga modes with sif sensors in
+    sonixb.
+  * V4L/DVB (8869): gspca: Move the Sonix webcams with TAS5110C1B from
+    sn9c102 to gspca.
+  * V4L/DVB (8870): gspca: Fix dark room problem with sonixb.
+  * V4L/DVB (8872): gspca: Bad image format and offset with rev072a of
+    spca561.
+  * V4L/DVB (8873): gspca: Bad image offset with rev012a of spca561 and
+    adjust exposure.
+  * V4L/DVB (8874): gspca: Adjust hstart for sn9c103/ov7630 and update
+    usb-id's.
+  * [ARM] omap: fix virtual vs physical address space confusions
+  * V4L/DVB (8876): budget: udelay changed to mdelay
+  * V4L/DVB (8877): b2c2 and bt8xx: udelay to mdelay
+  * V4L/DVB (8880): PATCH: Fix parents on some webcam drivers
+  * V4L/DVB (8881): gspca: After 'while (retry--) {...}', retry will be -1
+    but not 0.
+  * powerpc/spufs: Fix multiple get_spu_context()
+  * powerpc/spufs: Fix race for a free SPU
+  * Input: bcm5974 - small formatting cleanup
+  * Input: bcm5974 - improve finger tracking and counting
+  * Input: bcm5974 - add BTN_TOUCH event for mousedev benefit
+  * Input: i8042 - make Lenovo 3000 N100 blacklist entry more specific
+  * sh: resume_kernel fix for kernel oops built with CONFIG_BKL_PREEMPT=y.
+  * sh64: resume_kernel fix for kernel oops built with
+    CONFIG_BKL_PREEMPT=y.
+  * i2c: fix i2c-sh_mobile timing issues
+  * clockevents: prevent clockevent event_handler ending up handler_noop
+  * clockevents: prevent endless loop in periodic broadcast handler
+  * clockevents: enforce reprogram in oneshot setup
+  * clockevents: prevent multiple init/shutdown
+  * clockevents: prevent endless loop lockup
+  * HPET: make minimum reprogramming delta useful
+  * [MTD] [NAND] tmio_nand: fix base address programming
+  * Fix conditional export of kvh.h and a.out.h to userspace.
+  * async_tx: fix the bug in async_tx_run_dependencies
+  * sched_clock: fix NOHZ interaction
+  * sched: fix process time monotonicity
+  * UBIFS: fix division by zero
+  * UBIFS: make minimum fanout 3
+  * [MIPS] Fix data bus error recovery
+  * [MIPS] Fix WARNING: at kernel/smp.c:290
+  * [MIPS] TXx9: Fix txx9_pcode initialization
+  * [MIPS] TX39xx: Add missing local_flush_icache_range initialization
+  * [MIPS] Probe initrd header only if explicitly specified
+  * res_counter: fix off-by-one bug in setting limit
+  * forcedeth: fix kexec regression
+  * atmel_lcdfb: fix oops in rmmod when framebuffer fails to register
+  * tracehook: comment pasto fixes
+  * drivers/mmc/card/block.c: fix refcount leak in mmc_block_open()
+  * x86: boot: stub out unimplemented CPU feature words
+  * x86: add NOPL as a synthetic CPU feature bit
+  * x86: use X86_FEATURE_NOPL in alternatives
+  * clockevents: broadcast fixup possible waiters
+  * x86: HPET fix moronic 32/64bit thinko
+  * x86: HPET: read back compare register before reading counter
+  * Fix CONFIG_AC97_BUS dependency
+  * [ARM] 5241/1: provide ioremap_wc()
+  * ntp: fix calculation of the next jiffie to trigger RTC sync
+  * clocksource, acpi_pm.c: use proper read function also in errata mode
+  * clocksource, acpi_pm.c: check for monotonicity
+  * x86: delay early cpu initialization until cpuid is done
+  * x86: move mtrr cpu cap setting early in early_init_xxxx
+  * sched: arch_reinit_sched_domains() must destroy domains to force
+    rebuild
+  * x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags
+  * x86: pda_init(): fix memory leak when using CPU hotplug
+  * x86: cpu_init(): fix memory leak when using CPU hotplug
+  * powerpc/spufs: Fix possible scheduling of a context to multiple SPEs
+  * netfilter: nf_conntrack_sip: de-static helper pointers
+  * netfilter: nf_conntrack_gre: more locking around keymap list
+  * netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet
+  * netfilter: nf_conntrack_irc: make sure string is terminated before
+    calling simple_strtoul
+  * pkt_sched: Fix qdisc state in net_tx_action()
+  * powerpc: Fix rare boot build breakage
+  * ahci, pata_marvell: play nicely together
+  * sata_mv: add RocketRaid 1720 PCI ID to driver
+  * ahci: disable PMP for marvell ahcis
+  * sata_nv: disable hardreset for generic
+  * libata-sff: kill spurious WARN_ON() in ata_hsm_move()
+  * pata_sil680: remove duplicate pcim_enable_device
+  * ahci: RAID mode SATA patch for Intel Ibex Peak DeviceIDs
+  * [MIPS] IP22: Fix detection of second HPC3 on Challenge S
+  * xen: fix 2.6.27-rc5 xen balloon driver warnings
+  * x86: disable static NOPLs on 32 bits
+  * netns : fix kernel panic in timewait socket destruction
+  * bridge: don't allow setting hello time to zero
+  * NFS: Restore missing hunk in NFS mount option parser
+  * usb: fix null deferences in low level usb serial
+  * Fix format of MAINTAINERS
+  * sparc64: Disable timer interrupts in fixup_irqs().
+  * [Bluetooth] Fix reference counting during ACL config stage
+  * [Bluetooth] Enforce correct authentication requirements
+  * [Bluetooth] Reject L2CAP connections on an insecure ACL link
+  * [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit
+    mode
+  * [S390] cio: Correct cleanup on error.
+  * [S390] cio: handle ssch() return codes correctly.
+  * [S390] cio: allow offline processing for disconnected devices
+  * ipsec: Restore larval states and socket policies in dump
+  * update Documentation/filesystems/Locking for 2.6.27 changes
+  * MAINTAINERS: add Atheros maintainer for atlx
+  * lib: Correct printk %pF to work on all architectures
+  * x86: fix memmap=exactmap boot argument
+  * clockevents: remove WARN_ON which was used to gather information
+  * ipv6: Fix OOPS in ip6_dst_lookup_tail().
+  * Linux 2.6.27-rc6
+
+ -- Ben Collins <ben.collins@canonical.com>  Tue, 02 Sep 2008 12:45:56 -0400
+
+linux (2.6.27-2.3) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/retag: Make script save .orig of tags for later use
+  * ubuntu/lirc: Fix device_create call
+  * build/firmware: Put in-kernel firmware into version specific subdir
+    - LP: #262115
+  * Rebase on linux-2.6 git.
+  * ABI bump
+
+  [ Herton Ronaldo Krzesinski ]
+
+  * SAUCE: (no-up) Apparmor warning fixes
+
+  [ John Johansen ]
+
+  * SAUCE: (no-up) Proper AppArmor ptrace updates for newer lsm API
+
+  [ Mackenzie Morgan ]
+
+  * SAUCE: Add quirk for ASUS Z37E to make sound audible after resume
+    - LP: #25896
+
+ -- Ben Collins <ben.collins@canonical.com>  Wed, 27 Aug 2008 14:03:05 -0400
+
+linux (2.6.27-1.2) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * SAUCE: make fc transport removal of target configurable
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+
+  [ Ben Collins ]
+
+  * SAUCE: Lower warning level of some PCI messages
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: (no-up) connector.h: Add idx/val for drbd
+  * SAUCE: (no-up) swap: Add notify_swap_entry_free callback for compcache
+  * SAUCE: drivers: Remove some duplicate device entries in various modules
+  * SAUCE: (no-up) [AppArmor] merge with upstream subversion r1291
+  * SAUCE: apparmor: Update for changes to ptrace lsm hooks
+  * SAUCE: (no-up) Enable ubuntu extra subdirectory
+  * SAUCE: applesmc: Add MacBookAir
+  * SAUCE: (no-up) ACPI: initramfs DSDT override support
+  * ubuntu: Add drbd module
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Add BOM for iscsitarget
+  * ubuntu: Add squashfs driver
+  * SAUCE: (no-up) Check for squashfs superblock in initramfs mounting.
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Added et131x driver
+  * ubuntu: Add dm-raid4-5 driver
+  * ubuntu: Add ndiswrapper driver
+  * ubuntu: Added ram backed compressed swap module (compcache)
+  * ubuntu: Add misc drivers from hardy lum
+  * ubuntu: Add heci driver 3.2.0.24
+  * ubuntu: Add ov511 and bt-sco drivers
+  * ubuntu: Add acx, prism2_usb wireless drivers
+  * ubuntu: Add at76 driver to build
+  * ubuntu: Add fsam7400 sw kill switch driver
+  * ubuntu: Added qc-usb driver
+  * ubuntu: e1000e: Upgraded module to 0.4.1.7
+  * ubuntu: Added rfkill drivers
+  * ubuntu: VIA - Add VIA DRM Chrome9 3D engine
+  * ubuntu: unionfs: Added v1.4 module from hardy
+  * ubuntu: Add LIRC driver
+  * ubuntu: Add GFS driver
+  * ubuntu: New tlsup driver for toshiba laptops
+  * Update config files
+  * build/d-i: Remove obsolete dm modules
+
+  [ Chuck Short ]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+
+  [ Colin Ian King ]
+
+  * ubuntu: Add dm-loop
+  * SAUCE: Enable speedstep for sonoma processors.
+
+  [ Dennis Noordsij ]
+
+  * SAUCE: Work around ACPI corruption upon suspend on some Dell machines.
+
+  [ Fabio M. Di Nitto ]
+
+  * SAUCE: Export gfs2 symbols required for gfs1 kernel module
+
+  [ Matthew Garrett ]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [ Michael Frey (Senior Manager, MID ]
+
+  * SAUCE: Send HCI_RESET for Broadcomm 2046
+
+  [ Phillip Lougher ]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [ Stefan Bader ]
+
+  * SAUCE: (no-up) Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers
+
+  [ Tim Gardner ]
+
+  * SAUCE: Add extra headers to linux-libc-dev
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: (no-up) Take care of orinoco_cs overlap with hostap_cs
+  * ubuntu: Add GNBD driver
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 23 Aug 2008 15:48:35 -0400
+
+linux (2.6.27-0.0) intrepid; urgency=low
+
+  * Not uploaded, placeholder for new release
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 23 Aug 2008 15:48:35 -0400
+
+linux (2.6.26-5.17) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/abi: Add tosh_smm symbol to blacklist
+
+ -- Ben Collins <ben.collins@canonical.com>  Fri, 15 Aug 2008 09:29:34 -0400
+
+linux (2.6.26-5.16) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * Revert "SAUCE: toshiba_acpi: Rewrote most of the proc entry bits."
+  * Revert "SAUCE: Update toshiba_acpi.c to version 0.19a"
+  * build/config: Disable in-kernel toshiba driver(s)
+  * ubuntu/tlsup: New driver for toshiba laptops
+  * build/config: Enable TLSUP driver
+  * SAUCE: e1000e: Fix E1000E_ENABLED logic to check for our E1000E_NEW
+    driver as well
+  * ubuntu/e1000e: Remove E1000E_ENABLED option in local config
+  * build/config: Update configs to have E1000E_ENABLED set
+  * ubuntu/prism2: Remove duplicate device
+
+  [ Fabio M. Di Nitto ]
+
+  * SAUCE: Export gfs2 symbols required for gfs1 kernel module
+
+  [ Stefan Bader ]
+
+  * SAUCE: x86: HPET rework for SB700
+    - LP: #255910
+
+  [ Tim Gardner ]
+
+  * Add GNBD driver
+  * Enable GNBD driver
+  * SAUCE: Add GFS driver
+  * SAUCE: Enable gfs driver configs
+  * b43: Linksys WMP54G (BCM4306/3) card in a PCI format has an SPROM
+    coding
+
+  [ Upstream Kernel Changes ]
+
+  * KVM: x86 emulator: emulate clflush
+  * USB: quirk PLL power down mode
+
+ -- Ben Collins <ben.collins@canonical.com>  Mon, 11 Aug 2008 13:19:28 -0400
+
+linux (2.6.26-5.15) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * Revert "SAUCE: Add blacklist support to fix Belkin bluetooth dongle."
+    - Superceded by upstream changes.
+  * build/config: New option enabled for uvcvideo
+  * build/control: Add Vcs-Git meta data to control file
+  * SAUCE: toshiba_acpi: Rewrote most of the new code
+  * abi/perm-blacklist: Add emu10k1 driver to blacklist
+
+  [ Upstream Kernel Changes ]
+
+  * pxamci: trivial fix of DMA alignment register bit clearing
+  * udplite: Protection against coverage value wrap-around
+  * ipv6: use timer pending
+  * ipv6: __KERNEL__ ifdef struct ipv6_devconf
+  * hdlcdrv: Fix CRC calculation.
+  * quota: fix possible infinite loop in quota code
+  * isofs: fix minor filesystem corruption
+  * KVM: VMX: Fix a wrong usage of vmcs_config
+  * KVM: SVM: fix suspend/resume support
+  * KVM: mmu_shrink: kvm_mmu_zap_page requires slots_lock to be held
+  * KVM: VMX: Add ept_sync_context in flush_tlb
+  * KVM: x86 emulator: Fix HLT instruction
+  * KVM: MMU: nuke shadowed pgtable pages and ptes on memslot destruction
+  * KVM: MMU: Fix potential race setting upper shadow ptes on nonpae hosts
+  * Patch Upstream: x86 ptrace: fix PTRACE_GETFPXREGS error
+  * rcu: fix rcu_try_flip_waitack_needed() to prevent grace-period stall
+  * Fix typos from signal_32/64.h merge
+  * x86 reboot quirks: add Dell Precision WorkStation T5400
+  * USB: fix usb serial pm counter decrement for disconnected interfaces
+  * x86, suspend, acpi: enter Big Real Mode
+  * markers: fix duplicate modpost entry
+  * Fix build on COMPAT platforms when CONFIG_EPOLL is disabled
+  * proc: fix /proc/*/pagemap some more
+  * cpusets: fix wrong domain attr updates
+  * x86: fix crash due to missing debugctlmsr on AMD K6-3
+  * ide-cd: fix oops when using growisofs
+  * rtc-at91rm9200: avoid spurious irqs
+  * vmlinux.lds: move __attribute__((__cold__)) functions back into final
+    .text section
+  * ARM: fix fls() for 64-bit arguments
+  * tcp: Clear probes_out more aggressively in tcp_ack().
+  * sparc64: Fix lockdep issues in LDC protocol layer.
+  * sparc64: Fix cpufreq notifier registry.
+  * sparc64: Do not define BIO_VMERGE_BOUNDARY.
+  * iop-adma: fix platform driver hotplug/coldplug
+  * myri10ge: do not forget to setup the single slice pointers
+  * myri10ge: do not use mgp->max_intr_slots before loading the firmware
+  * ALSA: trident - pause s/pdif output
+  * V4L: cx18: Upgrade to newer firmware & update documentation
+  * DVB: dib0700: add support for Hauppauge Nova-TD Stick 52009
+  * V4L: uvcvideo: Fix a buffer overflow in format descriptor parsing
+  * V4L: uvcvideo: Use GFP_NOIO when allocating memory during resume
+  * V4L: uvcvideo: Don't free URB buffers on suspend
+  * V4L: uvcvideo: Make input device support optional
+  * V4L: uvcvideo: Add support for Medion Akoya Mini E1210 integrated
+    webcam
+  * V4L: saa7134: Copy tuner data earlier to avoid overwriting manual tuner
+    type
+  * V4L: cx23885: Bugfix for concurrent use of /dev/video0 and /dev/video1
+  * DVB: cx23885: Ensure PAD_CTRL is always reset to a sensible default
+  * DVB: cx23885: DVB Transport cards using DVB port VIDB/TS1 did not
+    stream
+  * DVB: cx23885: Reallocated the sram to avoid concurrent VIDB/C issues
+  * DVB: cx23885: SRAM changes for the 885 and 887 silicon parts
+  * x86: fix kernel_physical_mapping_init() for large x86 systems
+  * eCryptfs: use page_alloc not kmalloc to get a page of memory
+  * UML - Fix boot crash
+  * ixgbe: remove device ID for unsupported device
+  * mpc52xx_psc_spi: fix block transfer
+  * tmpfs: fix kernel BUG in shmem_delete_inode
+  * markers: fix markers read barrier for multiple probes
+  * VFS: increase pseudo-filesystem block size to PAGE_SIZE
+  * cpufreq acpi: only call _PPC after cpufreq ACPI init funcs got called
+    already
+  * b43legacy: Release mutex in error handling code
+  * ath5k: don't enable MSI, we cannot handle it yet
+  * Fix off-by-one error in iov_iter_advance()
+  * Linux 2.6.26.1
+  * ftrace: remove unneeded documentation
+  * romfs_readpage: don't report errors for pages beyond i_size
+  * netfilter: nf_nat_sip: c= is optional for session
+  * SCSI: bsg: fix bsg_mutex hang with device removal
+  * x86: idle process - add checking for NULL early param
+  * x86: io delay - add checking for NULL early param
+  * Close race in md_probe
+  * Kprobe smoke test lockdep warning
+  * netfilter: xt_time: fix time's time_mt()'s use of do_div()
+  * linear: correct disk numbering error check
+  * SCSI: ch: fix ch_remove oops
+  * NFS: Ensure we zap only the access and acl caches when setting new acls
+  * jbd: fix race between free buffer and commit transaction
+  * Input: i8042 - add Intel D845PESV to nopnp list
+  * Input: i8042 - add Gericom Bellagio to nomux blacklist
+  * Input: i8042 - add Acer Aspire 1360 to nomux blacklist
+  * Bluetooth: Signal user-space for HIDP and BNEP socket errors
+  * Add compat handler for PTRACE_GETSIGINFO
+  * ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode
+  * ALSA: hda - Fix DMA position inaccuracy
+  * ALSA: hda - Add missing Thinkpad Z60m support
+  * ALSA: emu10k1 - Fix inverted Analog/Digital mixer switch on Audigy2
+  * vfs: fix lookup on deleted directory
+  * Ath5k: fix memory corruption
+  * Ath5k: kill tasklets on shutdown
+  * sound: ensure device number is valid in snd_seq_oss_synth_make_info
+  * Linux 2.6.26.2
+
+ -- Ben Collins <ben.collins@canonical.com>  Sun, 03 Aug 2008 13:25:02 -0400
+
+linux (2.6.26-5.14) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * SAUCE: applesmc: Add MacBookAir
+  * build: Do not build ddeb unless we are on the buildd
+  * build: control: Consistency in arch fields.
+  * SAUCE: Update toshiba_acpi.c to version 0.19a
+    - LP: #77026
+  * build: Added perm blacklist support and per-module support to abi-check
+    - Blacklist p80211 module from abi checks
+  * ubuntu/lirc: Get rid of drivers symlink and use real include stuff
+
+
+  [ Colin Ian King ]
+
+  * SAUCE: acerhk module - add support for Amilo A1650g keyboard
+    - LP: #84159
+  * SAUCE: rt2x00: Fix OOPS on failed creation of rt2x00lib workqueue
+    - LP: #249242
+
+  [ Mario Limonciello ]
+
+  * Add LIRC back in
+
+  [ Tim Gardner ]
+
+  * Makefile race condition can lead to ndiswrapper build failure
+    - LP: #241547
+  * update linux-wlan-ng (prism2_usb) to upstream version 1861
+    - LP: #245026
+
+  [ Upstream Kernel Changes ]
+
+  * Fix typos from signal_32/64.h merge
+
+ -- Ben Collins <ben.collins@canonical.com>  Fri, 01 Aug 2008 00:05:01 -0400
+
+linux (2.6.26-5.13) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build: Make makedumpfile an amd64/i386 only build-dep
+  * ubuntu/acerhk: Fixup assembly to compile with newer binutils
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 26 Jul 2008 16:41:50 -0400
+
+linux (2.6.26-4.12) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * e1000e: Upgraded module to 0.4.1.7 upstream. Placed in ubuntu/,
+    in-kernel driver disabled
+  * config: Disable e1000e in-kernel, and enable newer driver in ubuntu/
+  * rfkill: Update to 1.3 drivers, and move to common location
+  * ubuntu: Actually link kconfig/kbuild into rfkill subdir
+  * config: Enable loading dsdt from initramfs
+    - LP: #246222
+  * ubuntu: [compcache] Update to fix crashes in improper BUG()
+  * build: Create a retag scripts to recover tags from rebases
+  * build: Updates for dbg pkg
+  * build: Make sure no empty lines show up in debian/files
+  * ubuntu: atl1e: Add new driver from 2.6.27-pre-rc1
+    - LP: #243894
+  * sys_getcwd: Fix some brokeness introduced by AppArmor __d_path
+    changes
+    - LP: #251223
+  * ubuntu: unionfs: Added v1.4 module from hardy
+  * build: Add sub-flavour infrastructure, and virtual subflav
+
+  [ Eric Piel ]
+
+  * ACPI: Allow custom DSDT tables to be loaded from initramfs
+
+  [ Kees Cook ]
+
+  * AppArmor: Smack VFS patches
+
+  [ Mario Limonciello ]
+
+  * Work around ACPI corruption upon suspend on some Dell machines.
+    - LP: #183033
+
+  [ Tim Gardner ]
+
+  * Export usbhid_modify_dquirk for LBM module bcm5974
+    - LP: #250838
+  * VIA - Add VIA DRM Chrome9 3D engine
+    - LP: #251862
+  * Define TRUE/FALSE for VIA DRM driver.
+
+ -- Ben Collins <ben.collins@canonical.com>  Tue, 15 Jul 2008 12:51:39 -0400
+
+linux (2.6.26-4.11) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * config: Enable bcm5974 driver in all configs
+
+  [ 2.6.26-4.10 ]
+
+  [ Amit Kucheria ]
+
+  * Fix typo in GSPCA Makefile and make it compile
+
+  [ Ben Collins ]
+
+  * ubuntu: Remove UVC driver in favor of in-kernel one (-rc9)
+  * config: Updates for -rc9
+  * ubuntu: Add acx, prism2_usb wireless drivers
+  * config: Enable prism2_usb and acx drivers.
+  * ubuntu: Add at76 driver to build
+  * config: Enable at76_usb driver.
+  * iscsitarget: Fix prototype for bi_end_io callback.
+  * acx: Fix section type mismatch warnings
+  * fsam7400: Add sw kill switch driver
+  * config: Enable fsam7400 driver
+  * qc-usb: Added new driver
+  * config: Enable qc-usb driver
+  * drbd: Remove built-in connector usage
+  * drbd: Do not define idx/val for connector here
+  * connector.h: Add idx/val for drbd
+  * bcm5974: Added new driver
+
+  [ Kees Cook ]
+
+  * SAUCE: [AppArmor] merge with upstream subversion r1291
+  * SAUCE: [AppArmor] fix typo in selinux_inode_link
+  * SAUCE: [AppArmor] aufs patches
+
+  [ Michael Frey (Senior Manager, MID ]
+
+  * SAUCE: Send HCI_RESET for Broadcomm 2046
+    - LP: #241749
+
+  [ Tim Gardner ]
+
+  * SAUCE: Medion Akoya Mini E1210
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "BAST: Remove old IDE driver"
+  * ARM: OMAP: DMA: Don't mark channel active in omap_enable_channel_irq
+  * ARM: OMAP: Correcting the gpmc prefetch control register address
+  * debugobjects: fix lockdep warning
+  * [ARM] 5115/1: pxafb: fix ifdef for command line option handling
+  * [ARM] 5116/1: pxafb: cleanup and fix order of failure handling
+  * [ARM] 5109/1: Mark rtc sa1100 driver as wakeup source before
+    registering it
+  * [ARM] Export dma_sync_sg_for_device()
+  * fix cgroup-inflicted breakage in block_dev.c
+  * [patch for 2.6.26 2/4] vfs: utimensat(): be consistent with utime() for
+    immutable and append-only files
+  * [patch for 2.6.26 1/4] vfs: utimensat(): ignore tv_sec if tv_nsec ==
+    UTIME_OMIT or UTIME_NOW
+  * [patch for 2.6.26 3/4] vfs: utimensat(): fix error checking for
+    {UTIME_NOW,UTIME_OMIT} case
+  * [patch for 2.6.26 4/4] vfs: utimensat(): fix write access check for
+    futimens()
+  * [patch 1/4] vfs: path_{get,put}() cleanups
+  * [patch 2/4] fs: make struct file arg to d_path const
+  * [patch 3/4] vfs: fix ERR_PTR abuse in generic_readlink
+  * [patch 4/4] flock: remove unused fields from file_lock_operations
+  * [patch 3/3] vfs: make d_path() consistent across mount operations
+  * [patch 1/3] vfs: dcache sparse fixes
+  * [patch 2/3] vfs: dcache cleanups
+  * udf: Fix regression in UDF anchor block detection
+  * [SCSI] ses: Fix timeout
+  * netfilter: ip6table_mangle: don't reroute in LOCAL_IN
+  * [SCSI] esp: Fix OOPS in esp_reset_cleanup().
+  * kernel/audit.c: nlh->nlmsg_type is gotten more than once
+  * audit: fix kernel-doc parameter notation
+  * remove useless argument type in audit_filter_user()
+  * Blackfin arch: fix bug - kernel boot fails when Spinlock and rw-lock
+    debugging enabled
+  * Blackfin arch: fix up section mismatch warning
+  * mac80211: implement EU regulatory domain
+  * b43: Do not return TX_BUSY from op_tx
+  * b43legacy: Do not return TX_BUSY from op_tx
+  * b43: Fix possible MMIO access while device is down
+  * b43legacy: Fix possible NULL pointer dereference in DMA code
+  * rt2x00: Fix unbalanced mutex locking
+  * iwlwifi: improve scanning band selection management
+  * [SCSI] esp: tidy up target reference counting
+  * [ARM] 5117/1: pxafb: fix __devinit/exit annotations
+  * thermal: Create CONFIG_THERMAL_HWMON=n
+  * ACPI: don't walk tables if ACPI was disabled
+  * dock: bay: Don't call acpi_walk_namespace() when ACPI is disabled.
+  * x86: shift bits the right way in native_read_tscp
+  * x86: section/warning fixes
+  * V4L/DVB (8004): Fix INPUT dependency at budget-ci
+  * V4L/DVB (8005): Fix OOPS if frontend is null
+  * V4L/DVB (8007): cx18/cx25840: the S-Video LUMA input can use all
+    In1-In8 inputs
+  * V4L/DVB (8008): cx18: remove duplicate audio and video input enums
+  * V4L/DVB (8010): em28xx: Properly register extensions for already
+    attached devices
+  * V4L/DVB (8011): em28xx: enable DVB for HVR-900
+  * V4L/DVB (8012): gl861: sleep a little to avoid I2C errors
+  * V4L/DVB (8013): gl861: remove useless identify_state
+  * V4L/DVB (8015): gl861: replace non critical msleep(0) with msleep(1) to
+    be on the safe side
+  * V4L/DVB (8017): Ensure em28xx extensions only get run against devs that
+    support them
+  * V4L/DVB (8018): Add em2860 chip ID
+  * V4L/DVB (8020): Fix callbacks functions of saa7134_empress
+  * V4L/DVB (8022): saa7134: fix race between opening and closing the
+    device
+  * V4L/DVB (8026): Avoids an OOPS if dev struct can't be successfully
+    recovered
+  * V4L/DVB (8027): saa7134: Avermedia A700: only s-video and composite
+    input are working
+  * V4L/DVB (8028): Improve error messages for tda1004x attach
+  * V4L/DVB (8029): Improve error message at tda1004x_attach
+  * V4L/DVB (8034): tda18271: fix IF notch frequency handling
+  * V4L/DVB (8035): tda18271: dont touch EB14 if rf_cal lookup is out of
+    range
+  * V4L/DVB (8036): tda18271: toggle rf agc speed mode on TDA18271HD/C2
+    only
+  * V4L/DVB (8037): tda18271: ensure that the thermometer is off during
+    channel configuration
+  * V4L/DVB (8039): pxa-camera: fix platform_get_irq() error handling.
+  * V4L/DVB (8040): soc-camera: remove soc_camera_host_class class
+  * V4L/DVB (8042): DVB-USB UMT-010 channel scan oops
+  * V4L/DVB (8043): au0828: add support for additional USB device id's
+  * V4L/DVB (8044): au8522: tuning optimizations
+  * V4L/DVB (8048): saa7134: Fix entries for Avermedia A16d and Avermedia
+    E506
+  * V4L/DVB (8061): cx18: only select tuner / frontend modules if
+    !DVB_FE_CUSTOMISE
+  * V4L/DVB (8063): cx18: Fix unintended auto configurations in
+    cx18-av-core
+  * V4L/DVB (8066): cx18: Fix audio mux input definitions for HVR-1600 Line
+    In 2 and FM radio
+  * V4L/DVB (8067): cx18: Fix firmware load for case when digital capture
+    happens first
+  * V4L/DVB (8068): cx18: Add I2C slave reset via GPIO upon initialization
+  * V4L/DVB (8069): cx18: Fix S-Video and Compsite inputs for the Yuan
+    MPC718 and enable card entry
+  * V4L/DVB (8071): tda10023: Fix possible kernel oops during
+    initialisation
+  * V4L/DVB (8073): av7110: Catch another type of ARM crash
+  * V4L/DVB (8074): av7110: OSD transfers should not be interrupted
+  * V4L/DVB (8075): stv0299: Uncorrected block count and bit error rate
+    fixed
+  * V4L/DVB (8092): videodev: simplify and fix standard enumeration
+  * V4L/DVB (8096): au8522: prevent false-positive lock status
+  * V4L/DVB (8097): xc5000: check device hardware state to determine if
+    firmware download is needed
+  * V4L/DVB (8100): V4L/vivi: fix possible memory leak in vivi_fillbuff
+  * V4L/DVB (8108): Fix open/close race in saa7134
+  * s2io: fix documentation about intr_type
+  * tc35815: Mark carrier-off before starting PHY
+  * tc35815: Fix receiver hangup on Rx FIFO overflow
+  * ixgbe: fix EEH recovery during reset on PPC
+  * igb: fix EEH recovery during reset on PPC
+  * e1000e: fix EEH recovery during reset on PPC
+  * pcnet_cs, axnet_cs: clear bogus interrupt before request_irq
+  * drivers/net/r6040.c: Eliminate double sizeof
+  * ipg: fix jumbo frame compilation
+  * ipg: use NULL, not zero, for pointers
+  * [netdrvr] 3c59x: remove irqs_disabled warning from local_bh_enable
+  * [netdrvr] netxen: fix netxen_pci_tbl[] breakage
+  * e100: Do pci_dma_sync after skb_alloc for proper operation on ixp4xx
+  * e1000: only enable TSO6 via ethtool when using correct hardware
+  * [netdrvr] Fix IOMMU overflow checking in s2io.c
+  * qla3xxx: Hold RTNL while calling dev_close()
+  * Hold RTNL while calling dev_close()
+  * sata_uli: hardreset is broken
+  * rt2x00: Fix lock dependency errror
+  * prism: islpci_eth.c endianness fix
+  * mac80211: fix an oops in several failure paths in key allocation
+  * firewire: fw-sbp2: fix parsing of logical unit directories
+  * kbuild: fix a.out.h export to userspace with O= build.
+  * Ensure interrupted recovery completed properly (v1 metadata plus
+    bitmap)
+  * Don't acknowlege that stripe-expand is complete until it really is.
+  * Fix error paths if md_probe fails.
+  * hamradio: remove unused variable
+  * tcp: calculate tcp_mem based on low memory instead of all memory
+  * tcp: fix for splice receive when used with software LRO
+  * af_unix: fix 'poll for write'/connected DGRAM sockets
+  * netdevice: Fix typo of dev_unicast_add() comment
+  * pkt_sched: ERR_PTR() ususally encodes an negative errno, not positive.
+  * pkt_sched: Remove CONFIG_NET_SCH_RR
+  * include/linux/netdevice.h: don't export MAX_HEADER to userspace
+  * tcp: /proc/net/tcp rto,ato values not scaled properly (v2)
+  * netlink: Fix some doc comments in net/netlink/attr.c
+  * CONNECTOR: add a proc entry to list connectors
+  * inet fragments: fix race between inet_frag_find and
+    inet_frag_secret_rebuild
+  * net/inet_lro: remove setting skb->ip_summed when not LRO-able
+  * netlabel: Fix a problem when dumping the default IPv6 static labels
+  * ipv6 route: Convert rt6_device_match() to use RT6_LOOKUP_F_xxx flags.
+  * sched: fix cpu hotplug
+  * Fix and clean top .gitignore
+  * x86: fix cpu hotplug crash
+  * ptrace GET/SET FPXREGS broken
+  * Input: add KEY_MEDIA_REPEAT definition
+  * Input: fix locking in force-feedback core
+  * [ARM] 5131/1: Annotate platform_secondary_init with trace_hardirqs_off
+  * ide: fix /proc/ide/ide?/mate reporting
+  * netfilter: nf_conntrack_tcp: fixing to check the lower bound of valid
+    ACK
+  * textsearch: fix Boyer-Moore text search bug
+  * hostap: don't report useless WDS frames by default
+  * hostap: fix sparse warnings
+  * mac80211: don't accept WEP keys other than WEP40 and WEP104
+  * V4L/DVB (8145a): USB Video Class driver
+  * [IA64] Bugfix for system with 32 cpus
+  * [IA64] export account_system_vtime
+  * sched: fix divide error when trying to configure rt_period to zero
+  * x86: fix NODES_SHIFT Kconfig range
+  * block: Fix the starving writes bug in the anticipatory IO scheduler
+  * Properly notify block layer of sync writes
+  * rcu: fix hotplug vs rcu race
+  * I2C: S3C2410: Check ACK on byte transmission
+  * I2C: S3C2410: Fixup error codes returned rom a transfer.
+  * I2C: S3C2410: Add MODULE_ALIAS() for s3c2440 device.
+  * PCI: Restrict VPD read permission to root
+  * powerpc/bootwrapper: update for initrd with simpleImage
+  * i2c: Documentation: fix device matching description
+  * i2c: Fix bad hint about irqs in i2c.h
+  * powerpc/legacy_serial: Bail if reg-offset/shift properties are present
+  * powerpc/mpc5200: Fix lite5200b suspend/resume
+  * ipv4: fix sysctl documentation of time related values
+  * net-sched: change tcf_destroy_chain() to clear start of filter list
+  * net-sched: fix filter destruction in atm/hfsc qdisc destruction
+  * netlink: Unneeded local variable
+  * net: Tyop of sk_filter() comment
+  * netdevice: Fix wrong string handle in kernel command line parsing
+  * net: fib_rules: fix error code for unsupported families
+  * dm crypt: use cond_resched
+  * V4L/DVB (8178): uvc: Fix compilation breakage for the other drivers, if
+    uvc is selected
+  * PCI: Limit VPD read/write lengths for Broadcom 5706, 5708, 5709 rev.
+  * PCI: acpiphp: cleanup notify handler on all root bridges
+  * drivers/input/ff-core.c needs <linux/sched.h>
+  * DRM/i915: only use tiled blits on 965+
+  * tty: Fix inverted logic in send_break
+  * x86: fix Intel Mac booting with EFI
+  * arch/x86/mm/init_64.c: early_memtest(): fix types
+  * 9p: fix O_APPEND in legacy mode
+  * slub: Do not use 192 byte sized cache if minimum alignment is 128 byte
+  * Do not overwrite nr_zones on !NUMA when initialising zlcache_ptr
+  * [MIPS] IP32: Fix unexpected irq 71
+  * [MIPS] IP22: Fix crashes due to wrong L1_CACHE_BYTES
+  * [MIPS] cevt-txx9: Reset timer counter on initialization
+  * hrtimer: prevent migration for raising softirq
+  * svcrpc: fix handling of garbage args
+  * OHCI: Fix problem if SM501 and another platform driver is selected
+  * USB: fix cdc-acm resume()
+  * USB: ehci - fix timer regression
+  * USB: ohci - record data toggle after unlink
+  * USB: mass storage: new id for US_SC_CYP_ATACB
+  * sisusbvga: Fix oops on disconnect.
+  * USB: New device ID for ftdi_sio driver
+  * USB: fix interrupt disabling for HCDs with shared interrupt handlers
+  * USB: don't lose disconnections during suspend
+  * USB: another option device id
+  * USB: add a pl2303 device id
+  * USB: fix Oops on loading ipaq module since 2.6.26
+  * USB: adding comment for ipaq forcing number of ports
+  * [MIPS] Fix bug in atomic_sub_if_positive.
+  * xen: fix address truncation in pte mfn<->pfn conversion
+  * sata_sil24: add DID for another adaptec flavor
+  * ahci: always clear all bits in irq_stat
+  * libata-sff: improve HSM violation reporting
+  * sata_mv: safer logic for limit_warnings
+  * Update maintainers for powerpc
+  * Christoph has moved
+  * mm: dirty page accounting vs VM_MIXEDMAP
+  * rtc: rtc_read_alarm() handles wraparound
+  * firmware: fix the request_firmware() dummy
+  * serial: fix serial_match_port() for dynamic major tty-device numbers
+  * get_user_pages(): fix possible page leak on oom
+  * rtc-x1205: Fix alarm set
+  * rtc: fix CMOS time error after writing /proc/acpi/alarm
+  * pci: VT3336 can't do MSI either
+  * Miguel Ojeda has moved
+  * ext3: add missing unlock to error path in ext3_quota_write()
+  * ext4: add missing unlock to an error path in ext4_quota_write()
+  * reiserfs: add missing unlock to an error path in reiserfs_quota_write()
+  * ecryptfs: remove unnecessary mux from ecryptfs_init_ecryptfs_miscdev()
+  * lib: taint kernel in common report_bug() WARN path.
+  * gpio: pca953x (i2c) handles max7310 too
+  * fsl_diu_fb: fix build with CONFIG_PM=y, plus fix some warnings
+  * Update taskstats-struct document for scaled time accounting
+  * cciss: fix regression that no device nodes are created if no logical
+    drives are configured.
+  * delay accounting: maintainer update
+  * Doc*/kernel-parameters.txt: fix stale references
+  * hdaps: add support for various newer Lenovo thinkpads
+  * mn10300: export certain arch symbols required to build allmodconfig
+  * mn10300: provide __ucmpdi2() for MN10300
+  * Introduce rculist.h
+  * man-pages is supported
+  * ntfs: update help text
+  * add kernel-doc for simple_read_from_buffer and memory_read_from_buffer
+  * w100fb: do not depend on SHARPSL
+  * w100fb: add 80 MHz modeline
+  * MFD maintainer
+  * cgroups: document the effect of attaching PID 0 to a cgroup
+  * spi: fix the read path in spidev
+  * doc: doc maintainers
+  * security: filesystem capabilities: fix fragile setuid fixup code
+  * security: filesystem capabilities: fix CAP_SETPCAP handling
+  * Alpha Linux kernel fails with inconsistent kallsyms data
+  * cpusets: document proc status cpus and mems allowed lists
+  * MAINTAINERS: update the email address of Andreas Dilger
+  * cciss: read config to obtain max outstanding commands per controller
+  * olpc: sdhci: add quirk for the Marvell CaFe's vdd/powerup issue
+  * olpc: sdhci: add quirk for the Marvell CaFe's interrupt timeout
+  * cpumask: introduce new APIs
+  * mm: switch node meminfo Active & Inactive pages to Kbytes
+  * Update MAINTAINERS file for the TPM device driver
+  * devcgroup: fix odd behaviour when writing 'a' to devices.allow
+  * doc: document the relax_domain_level kernel boot argument
+  * mmc: don't use DMA on newer ENE controllers
+  * mempolicy: mask off internal flags for userspace API
+  * x86 ACPI: normalize segment descriptor register on resume
+  * x86 ACPI: fix resume from suspend to RAM on uniprocessor x86-64
+  * softlockup: print a module list on being stuck
+  * ide: fix hwif->gendev refcounting
+  * ide: ide_unregister() warm-plug bugfix
+  * ide: ide_unregister() locking bugfix
+  * ahci: give another shot at clearing all bits in irq_stat
+  * Fix clear_refs_write() use of struct mm_walk
+  * Move _RET_IP_ and _THIS_IP_ to include/linux/kernel.h
+  * Fix pagemap_read() use of struct mm_walk
+  * Linux 2.6.26-rc9
+  * Revert "USB: don't explicitly reenable root-hub status interrupts"
+  * Revert "PCI: Correct last two HP entries in the bfsort whitelist"
+  * iwlwifi: fix incorrect 5GHz rates reported in monitor mode
+  * iwlwifi: drop skb silently for Tx request in monitor mode
+  * libertas: support USB persistence on suspend/resume (resend)
+  * tcp: net/ipv4/tcp.c needs linux/scatterlist.h
+  * tcp: fix a size_t < 0 comparison in tcp_read_sock
+  * bridge: fix use-after-free in br_cleanup_bridges()
+  * Add missing skb->dev assignment in Frame Relay RX code
+  * forcedeth: fix lockdep warning on ethtool -s
+  * ehea: fix might sleep problem
+  * ehea: add MODULE_DEVICE_TABLE
+  * ehea: fix race condition
+  * ehea: Access iph->tot_len with correct endianness
+  * pasemi_mac: Access iph->tot_len with correct endianness
+  * ibm_newemac: Fixes kernel crashes when speed of cable connected changes
+  * ibm_newemac: Fixes entry of short packets
+  * fs_enet: restore promiscuous and multicast settings in restart()
+  * can: add sanity checks
+  * x86: KVM guest: Add memory clobber to hypercalls
+  * KVM: IOAPIC: Fix level-triggered irq injection hang
+  * [SCSI] erase invalid data returned by device
+  * pxamci: fix byte aligned DMA transfers
+  * vsprintf: split out '%s' handling logic
+  * vsprintf: split out '%p' handling logic
+  * vsprintf: add infrastructure support for extended '%p' specifiers
+  * vsprintf: add support for '%pS' and '%pF' pointer formats
+  * powerpc: Fix unterminated of_device_id array in legacy_serial.c
+  * [UML] fix gcc ICEs and unresolved externs
+  * ocfs2/dlm: Fixes oops in dlm_new_lockres()
+  * hostap_cs: correct poor NULL checks in suspend/resume routines
+  * drivers/net/wireless/iwlwifi/iwl-3945.c Fix type issue on 64bit
+  * mac80211: move netif_carrier_on to after
+    ieee80211_bss_info_change_notify
+  * mac80211: Only flush workqueue when last interface was removed
+  * zd1211rw: add ID for AirTies WUS-201
+  * ssb-pcicore: Fix IRQ-vector init on embedded devices
+  * mac80211: don't report selected IBSS when not found
+  * crypto: tcrypt - Fix memory leak in test_cipher
+  * sctp: Mark the tsn as received after all allocations finish
+  * [S390] protect _PAGE_SPECIAL bit against mprotect
+  * irda: via-ircc proper dma freeing
+  * irda: New device ID for nsc-ircc
+  * irda: Fix netlink error path return value
+  * [SCSI] mptspi: fix oops in mptspi_dv_renegotiate_work()
+  * Correct hash flushing from huge_ptep_set_wrprotect()
+  * ide: add __ide_default_irq() inline helper
+  * palm_bk3710: fix IDECLK period calculation
+  * it8213: fix return value in it8213_init_one()
+  * [MIPS] Atlas, decstation: Fix section mismatches triggered by
+    defconfigs
+  * [MIPS] Fix 32bit kernels on R4k with 128 byte cache line size
+  * NFS: Fix readdir cache invalidation
+  * SUNRPC: Fix a double-free in rpcbind
+  * SUNRPC: Fix an rpcbind breakage for the case of IPv6 lookups
+  * reiserfs: discard prealloc in reiserfs_delete_inode
+  * Fix broken fix for fsl-diu-db
+  * RDMA/cxgb3: Fix regression caused by class_device -> device conversion
+  * ipv6: fix race between ipv6_del_addr and DAD timer
+  * sctp: Add documentation for sctp sysctl variable
+  * kernel/printk.c: Made printk_recursion_bug_msg static.
+  * powerpc: Add missing reference to coherent_dma_mask
+  * rc80211_pid: Fix fast_start parameter handling
+  * rt2x00: Disable synchronization during initialization
+  * zd1211rw: stop beacons on remove_interface
+  * libertas: fix memory alignment problems on the blackfin
+  * netfilter: nf_conntrack_tcp: fix endless loop
+  * netfilter: nf_nat_snmp_basic: fix a range check in NAT for SNMP
+  * md: ensure all blocks are uptodate or locked when syncing
+  * sched: fix cpu hotplug
+  * x86: fix /dev/mem compatibility under PAT
+  * crypto: chainiv - Invoke completion function
+  * ocfs2: Fix flags in ocfs2_file_lock
+  * kernel/kprobes.c: Made kprobe_blacklist static.
+  * arch/x86/kernel/.gitignore: Added vmlinux.lds to .gitignore file
+    because it shouldn't be tracked.
+  * ftrace: Documentation
+  * Fix PREEMPT_RCU without HOTPLUG_CPU
+  * sched: fix cpu hotplug, cleanup
+  * exec: fix stack excutability without PT_GNU_STACK
+  * slub: Fix use-after-preempt of per-CPU data structure
+  * Documentation: clarify tcp_{r,w}mem sysctl docs
+  * ip: sysctl documentation cleanup
+  * tcp: correct kcalloc usage
+  * ipv4: fib_trie: Fix lookup error return
+  * netlabel: netlink_unicast calls kfree_skb on error path by itself
+  * ipv6: missed namespace context in ipv6_rthdr_rcv
+  * xfrm: Add a XFRM_STATE_AF_UNSPEC flag to xfrm_usersa_info
+  * tun: Persistent devices can get stuck in xoff state
+  * tpm: add Intel TPM TIS device HID
+  * rapidio: fix device reference counting
+  * Fix name of Russell King in various comments
+  * rtc: fix reported IRQ rate for when HPET is enabled
+  * libata-acpi: filter out DIPM enable
+  * Added Targa Visionary 1000 IDE adapter to pata_sis.c
+  * libata-acpi: don't call sleeping function from invalid context
+  * Fix reference counting race on log buffers
+  * [SCSI] ipr: Fix HDIO_GET_IDENTITY oops for SATA devices
+  * IPMI: return correct value from ipmi_write
+  * x86: fix ldt limit for 64 bit
+  * [SCSI] fusion: default MSI to disabled for SPI and FC controllers
+  * [SCSI] bsg: fix oops on remove
+  * drivers/char/pcmcia/ipwireless/hardware.c fix resource leak
+  * drivers/isdn/i4l/isdn_common.c fix small resource leak
+  * fbdev: bugfix for multiprocess defio
+  * serial8250: sanity check nr_uarts on all paths.
+  * ov7670: clean up ov7670_read semantics
+  * rtc-fm3130: fix chip naming
+  * rtc-pcf8563: add chip id
+  * OProfile kernel maintainership changes
+  * frv: fix irqs_disabled() to return an int, not an unsigned long
+  * cifs: fix inode leak in cifs_get_inode_info_unix
+  * cifs: fix wksidarr declaration to be big-endian friendly
+  * cpusets, hotplug, scheduler: fix scheduler domain breakage
+  * Documentation/HOWTO: correct wrong kernel bugzilla FAQ URL
+  * devcgroup: always show positive major/minor num
+  * devcgroup: fix permission check when adding entry to child cgroup
+  * Linux 2.6.26
+
+ -- Ben Collins <ben.collins@canonical.com>  Mon, 14 Jul 2008 13:41:50 -0400
+
+linux (2.6.26-3.9) intrepid; urgency=low
+
+  * abi: Add dca and ioatdma to modules.ignore
+
+  [ 2.6.26-3.8 ]
+
+  [ Ben Collins ]
+
+  * ubuntu: Add heci driver 3.2.0.24
+  * ubuntu: Add heci to kconfig/kbuild
+  * config: Enable heci module on all flavours
+  * dm-bbr: Update to get it to compile with 2.6.26
+  * config: Enable dm-bbr
+  * ubuntu: Add some media drivers
+  * config: Enable misc media drivers
+  * udeb: Switch to uvesafb in fb-modules
+  * abi: Add more modules to ignore (known)
+
+  [ 2.6.26-3.7 ]
+
+  [Amit Kucheria]
+
+  * SAUCE: make fc transport removal of target configurable
+     - LP: #163075
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+
+  [Ben Collins]
+
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: irda: Default to dongle type 9 on IBM hardware
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: version: Implement version_signature proc file.
+  * build: Cleanup arches
+  * build: Remove remnants of unused binary-custom infrastructure
+  * build: Remove disable_d_i (not needed) and cleanup ppa build stuff
+  * ubuntu: New modules, acer-acpi
+  * build: Remove -virtual, and rebuild configs
+  * ubuntu: Add drbd module
+  * acer-acpi: Fix makefile
+  * x86/Kconfig: Fix missing quote for ubuntu Kconfig source
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Added Amiga FS driver
+  * ubuntu: Add squashfs driver
+  * ubuntu: Remove asfs (Amiga FS). Need to be in linux-ports instead
+  * squashfs: Move headers to real include directory
+  * build/configs: The Great Config Consistency Check of 2008
+  * ubuntu: Move third-party includes to ubuntu/include
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Add dm-radi4-5 driver
+  * build: Add CONFIG_DEBUG_SECTION_MISMATCH=y to get old style warnings
+    from build
+  * ubuntu/Makefile: Fixup dm-raid4-5 and add kludge for kbuild
+  * squashfs: Fixes for VFS changes
+  * ubuntu/dm-raid4-5: Fixups for moved/renamed headers/functions in core
+    md
+  * ubuntu: Add ndiswrapper driver
+  * d-i: Update module listings
+  * build: Disable xd block device (ancient)
+  * ndiswrapper: Fixup makefile
+  * d-i: Remove efi-modules. The only module, efivars, is built-in
+  * build: Remove install-source, obsolete and caused build failure
+  * Ubuntu-2.6.26-1.3
+  * build: linux-doc rules got broken when disabling html side. Fixed now.
+  * Ubuntu-2.6.26-1.4
+  * x86: Update to -rc6 allows CONFIG_PCI_OLPC to work with PCI_GOANY
+  * d-i: Make virtio-ring optional (it's built-in on i386)
+  * Ubuntu-2.6.26-1.4
+  * Ubuntu-2.6.26-1.5
+  * config: Enable DVB devices
+  * ubuntu/aufs: Make aufs a bool config, since it needs to be built-in
+  * config: Build aufs into the kernels
+  * build: Fix arguments passed to link-headers script
+  * config: Disable early printk
+  * d-i: Move isofs to storage-core and kill st (scsi tape) from list
+  * config: Enable non-promiscuous access to /dev/mem
+  * x86: Add option to disable decompression info messages
+  * config: Enable no-bz-chatter config options
+  * build: Re-add linux-source package
+  * d-i: Re-add socket-modules. Accidentally removed
+    - LP: #241295
+  * Ubuntu-2.6.26-2.6
+  * Use makedumpfile to generate a vmcoreinfo file.
+  * build: Build-Depend on makedumpfile for vmcoreinfo generation
+  * build: Remove debug print from git-ubuntu-log
+  * Updated configs for -rc7
+  * build: postinst, do not call depmod with -F
+  * config: Enable rtc-cmos as a built-in driver.
+  * control: Provide ndiswrapper-modules-1.9
+  * build: Generate vmcoreinfo in image build for crashdumps without debug
+    image
+  * config: Disable vesafb, since we'll prefer uvesafb
+  * build: Copy uvesafb module to initrd mod directory
+  * abi-check: New, more robust script
+  * config: Enable heap randomization by default
+  * abi-check: Cleanup output and call with perl (not $SHELL)
+  * abi: Ignore missing vesafb (known)
+  * config: Disable pcspkr (in favor of snd-pcsp)
+  * swap: Add notify_swap_entry_free callback for compcache
+  * compcache: Added ram backed compressed swap module
+  * ubuntu: Enable kbuild and kconfig for compcache
+  * config: Enable compcache and tlsf allocator as modules
+  * config: Updated for -rc8. Disables XEN on i386
+  * config: Switch i386-server to 64G, enable PAE, 64-bit res, and XEN
+  * ubuntu: Add misc drivers from hardy lum
+  * ubuntu: Enable build of misc/ subdir
+  * config: Enable misc drivers
+  * aufs: Fix warning about single non-string-literal arg to printf style
+    function
+  * drivers: Remove some duplicate device entries in various modules
+  * config: Disable some duplicate drivers
+  * keyspan: Remove duplicate device ID's
+  * check-aliases: Cleanup output, and fix rolling checks
+  * ubuntu: Disable dm-bbr for now
+  * dm-bbr: First cut at forward portiong. Still needs work.
+  * ubuntu: Disable dm-bbr in kbuild/kconfig
+
+  [Chuck Short]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+     - LP: #175834
+  * SAUCE: [USB]: add ASUS LCM to the blacklist
+
+  [Colin Ian King]
+
+  * SAUCE: airprime.c supports more devices
+    - LP: #208250
+  * SAUCE: Enable speedstep for sonoma processors. 
+     - LP: #132271
+  * Add dm-loop
+  * Add dm-loop BOM
+
+  [Kyle McMartin]
+
+  * SAUCE: fix orinoco_cs oops
+
+  [Mario Limonciello]
+
+  * SAUCE: Enable Reset and SCO workaround on Dell 410 BT adapter
+
+  [Matthew Garrett]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [Phillip Lougher]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [Stefan Bader]
+
+  * SAUCE: Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: Always use SCO protocol (disable eSCO support) Bug: #39414
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers OriginalAuthor:
+    Pascal Terjan <pterjan@mandriva.com> Bug: #137686
+  * SAUCE: Add blacklist support to fix Belkin bluetooth dongle. Bug:
+    #140511
+  * SAUCE: Lower warning level of pci resource allocation messages. Bug:
+    159241
+  * SAUCE: Lower message level for PCI memory and I/O allocation.
+    - LP: #159241
+  * Modify log generation to catch bug numbers when adding with git-am.
+
+  [Tim Gardner]
+
+  * Added the debian directory. Ignore: yes
+  * Add support for UBUNTUINCLUDE Ignore: yes
+  * LUM headers go in /usr/src Ignore: yes
+  * First pass at 2.6.25 configs Ignore: yes
+  * i386 -generic builds. Ignore: yes
+  * SAUCE: Increase CONFIG_IDE_MAX_HWIFS to 8 (from 4)
+  * SAUCE: Add extra headers to linux-libc-dev OriginalAuthor: Soren Hansen
+    OriginalLocation:
+    https://lists.ubuntu.com/archives/kernel-team/2007-November/001891.html
+  * Set CONFIG_DEVKMEM=n Ignore: yes
+  * Enabled ALSA and CGROUPS for i386 Ignore: yes
+  * Enabled amd64 configs. Ignore: yes
+  * CONFIG_STANDALONE=n Ignore: yes
+  * CONFIG_BLK_DEV_4DRIVES=n for i386 Ignore: yes
+  * CONFIG: CONFIG_DEFAULT_RELATIME=y for all flavours. Ignore: yes
+  * Set CONFIG_EDD_OFF=y Ignore: yes
+  * SAUCE: Blacklist Bluetooth Dell Wireless 370 for SCO MTU
+    OriginalAuthor: Mario Limonciello <Mario_Limonciello@Dell.com> Bug:
+    #209715
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: frame buffer regression - screen blank except for blinking
+    cursor after fbcon vtswitch OriginalAuthor: Matthew Garrett
+    <mjg59@srcf.ucam.org> Bug: #201591
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+    OriginalAuthor: Klaus S. Madsen <ubuntu@hjernemadsen.org>
+    OriginalAuthor: Chuck Short <zulcss@ubuntu.com>
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: orinoco_cs.ko missing
+  * Set CONFIG_FB_VESA=m for i386/amd64 Ignore: yes
+  * Set CONFIG_PM_DISABLE_CONSOLE=y for all flavours Ignore: yes
+  * Thorough review of amd64 -generic config Ignore: yes
+  * Build PPA packages for Hardy until the Intrepid archive is opened.
+  * Deleted obsolete flavours Ignore: yes
+  * Don't build docs for PPA Ignore: yes
+  * Build all standard packages in PPA. Ignore: yes
+  * Remove duplicate USB ids
+  * SAUCE: DVB-USB UMT-010 driver oops on install Bug: #115284
+  * Update configs after rebase to 2.6.26-rc1 Ignore: yes
+  * Update configs after rebase Ignore: yes
+  * Disable V4L until the build issues get ironed out. Ignore: yes
+  * Update configs after rebase. Ignore: yes
+  * Another device enable pass Ignore: yes
+  * Update configs after merge. Ignore: yes
+  * SAUCE: fn key doesn't work in hardy with macbook pro fourth generation
+    (4,1)
+    - LP: #207127
+  * Enabled CONFIG_CIFS_DFS_UPCALL=y and CONFIG_CIFS_UPCALL=y
+    - LP: #236830
+
+  [Upstream Kernel Changes]
+
+  * Revert "[WATCHDOG] hpwdt: Add CFLAGS to get driver working"
+  * mac80211: detect driver tx bugs
+  * hwmon: (lm85) Fix function RANGE_TO_REG()
+  * hwmon: (adt7473) Initialize max_duty_at_overheat before use
+  * hwmon: Update the sysfs interface documentation
+  * hwmon: (abituguru3) Identify Abit AW8D board as such
+  * hwmon: (w83791d) new maintainer
+  * hwmon: (abituguru3) update driver detection
+  * hwmon: (lm75) sensor reading bugfix
+  * ipv6: Remove options header when setsockopt's optlen is 0
+  * ipv6: Drop packets for loopback address from outside of the box.
+  * sched: rt: dont stop the period timer when there are tasks wanting to
+    run
+  * sched: fix wait_for_completion_timeout() spurious failure under heavy
+    load
+  * x86: fix NULL pointer deref in __switch_to
+  * xen: Use wmb instead of rmb in xen_evtchn_do_upcall().
+  * xen: mask unwanted pte bits in __supported_pte_mask
+  * xen: don't drop NX bit
+  * sched: refactor wait_for_completion_timeout()
+  * Ext4: Fix online resize block group descriptor corruption
+  * [IA64] SN2: security hole in sn2_ptc_proc_write
+  * alpha: fix module load failures on smp (bug #10926)
+  * alpha: link failure fix
+  * alpha: fix compile failures with gcc-4.3 (bug #10438)
+  * alpha: resurrect Cypress IDE quirk
+  * pppoe: warning fix
+  * sctp: Make sure N * sizeof(union sctp_addr) does not overflow.
+  * netns: Don't receive new packets in a dead network namespace.
+  * Add return value to reserve_bootmem_node()
+  * Slab: Fix memory leak in fallback_alloc()
+  * Fix performance regression on lmbench select benchmark
+  * ALSA: aw2 - Fix Oops at initialization
+  * ALSA: sb - Fix wrong assertions
+  * futexes: fix fault handling in futex_lock_pi
+  * IB/mthca: Clear ICM pages before handing to FW
+  * tty_driver: Update required method documentation
+  * removed unused var real_tty on n_tty_ioctl()
+  * Fix ZERO_PAGE breakage with vmware
+  * mm: fix race in COW logic
+  * NFS: Reduce the NFS mount code stack usage.
+  * NFS: Fix filehandle size comparisons in the mount code
+  * NFS: nfs_updatepage(): don't mark page as dirty if an error occurred
+  * alpha: fix compile error in arch/alpha/mm/init.c
+  * KVM: Fix race between timer migration and vcpu migration
+  * KVM: close timer injection race window in __vcpu_run
+  * KVM: MMU: Fix rmap_write_protect() hugepage iteration bug
+  * KVM: MMU: large page update_pte issue with non-PAE 32-bit guests
+    (resend)
+  * KVM: MMU: Fix oops on guest userspace access to guest pagetable
+  * KVM: ioapic: fix lost interrupt when changing a device's irq
+  * KVM: VMX: Fix host msr corruption with preemption enabled
+  * [GFS2] BUG: unable to handle kernel paging request at ffff81002690e000
+  * xen: remove support for non-PAE 32-bit
+  * kgdb: documentation update - remove kgdboe
+  * kgdb: sparse fix
+  * [IA64] Fix boot failure on ia64/sn2
+  * [IA64] Handle count==0 in sn2_ptc_proc_write()
+  * [IA64] Eliminate NULL test after alloc_bootmem in iosapic_alloc_rte()
+  * [GFS2] fix gfs2 block allocation (cleaned up)
+  * x86: Add structs and functions for paravirt clocksource
+  * x86: Make xen use the paravirt clocksource structs and functions
+  * KVM: Make kvm host use the paravirt clocksource structs
+  * x86: KVM guest: Use the paravirt clocksource structs and functions
+  * KVM: Remove now unused structs from kvm_para.h
+  * enable bus mastering on i915 at resume time
+  * Linux 2.6.26-rc8
+  * # Ubuntu external driver commit.
+  * # Ubuntu commit template.
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 21 Jun 2008 09:05:15 -0400
+
+linux (2.6.26-2.6) intrepid; urgency=low
+
+  [Ben Collins]
+
+  * Revert "SAUCE: Export symbols for aufs (in lum) (not needed)
+  * config: Enable DVB devices
+  * ubuntu/aufs: Make aufs a bool config, since it needs to be built-in
+  * config: Build aufs into the kernels
+  * build: Fix arguments passed to link-headers script
+  * config: Disable early printk
+  * d-i: Move isofs to storage-core and kill st (scsi tape) from list
+  * config: Enable non-promiscuous access to /dev/mem
+  * x86: Add option to disable decompression info messages
+  * config: Enable no-bz-chatter config options
+  * build: Re-add linux-source package
+  * d-i: Re-add socket-modules. Accidentally removed
+    - LP: #241295
+
+  [Colin Ian King]
+
+  * Add dm-loop
+
+  [Tim Gardner]
+
+  * Revert "SAUCE: USB bluetooth device 0x0e5e:0x6622 floods errors to
+    syslog (merged upstream)
+
+ -- Ben Collins <ben.collins@canonical.com>  Mon, 16 Jun 2008 10:56:01 -0400
+
+linux (2.6.26-1.5) intrepid; urgency=low
+
+  * d-i: Make virtio-ring optional (it's built-in on i386)
+  * Rebased on 2.6.26-rc6
+
+  [Ubuntu-2.6.26-1.4 Changes below]
+
+  * build: linux-doc rules got broken when disabling html side. Fixed now.
+
+  [Ubuntu-2.6.26-1.3 Changes below]
+
+  * build: Remove install-source, obsolete and caused build failure
+
+  [Ubuntu-2.6.26-1.2 Changes below]
+
+  * Remove efi-modules from d-i module list (efivars is built-in). Caused a
+    build failure.
+  * Patch to arch/x86/xen/time.c to remove __divdi3 usage (build failure on
+    i386).
+
+  [Ubuntu-2.6.26-1.1 Changes below]
+
+  [Amit Kucheria]
+
+  * SAUCE: make fc transport removal of target configurable
+  * SAUCE: Add AGP support for Radeon Mobility 9000 chipset
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+
+  [Ben Collins]
+
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: irda: Default to dongle type 9 on IBM hardware
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: version: Implement version_signature proc file.
+  * build: Remove remnants of unused binary-custom infrastructure
+  * mmc_block: Fix bad allocation on 64-bit (zero len array)
+  * ubuntu: New modules, acer-acpi
+  * build: Remove -virtual, and rebuild configs
+  * ubuntu: Add drbd module
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Add squashfs driver
+  * build/configs: The Great Config Consistency Check of 2008
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Add dm-radi4-5 driver
+  * build: Add CONFIG_DEBUG_SECTION_MISMATCH=y to get old style warnings
+    from build
+  * squashfs: Fixes for VFS changes
+  * ubuntu/dm-raid4-5: Fixups for moved/renamed headers/functions in core
+    md
+  * ubuntu: Add ndiswrapper driver
+  * d-i: Update module listings
+
+  [Chuck Short]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+  * SAUCE: [USB]: add ASUS LCM to the blacklist
+
+  [Colin Ian King]
+
+  * SAUCE: Enable speedstep for sonoma processors.
+  * SAUCE: airprime.c supports more devices
+
+  [Kyle McMartin]
+
+  * SAUCE: fix orinoco_cs oops
+
+  [Mario Limonciello]
+
+  * SAUCE: Enable Reset and SCO workaround on Dell 410 BT adapter
+
+  [Matthew Garrett]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [Phillip Lougher]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [Stefan Bader]
+
+  * SAUCE: Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: Always use SCO protocol (disable eSCO support) Bug: #39414
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers
+  * SAUCE: Add blacklist support to fix Belkin bluetooth dongle.
+  * SAUCE: Lower warning level of pci resource allocation messages.
+  * SAUCE: Lower message level for PCI memory and I/O allocation.
+    - LP: #159241
+  * Modify log generation to catch bug numbers when adding with git-am.
+
+  [Tim Gardner]
+
+  * SAUCE: hdaps module does not load on Thinkpad T61P
+  * SAUCE: Add extra headers to linux-libc-dev
+  * SAUCE: Export symbols for aufs (in lum).
+  * SAUCE: USB bluetooth device 0x0e5e:0x6622 floods errors to syslog
+  * SAUCE: Blacklist Bluetooth Dell Wireless 370 for SCO MTU
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: frame buffer regression - screen blank except for blinking
+    cursor after fbcon vtswitch
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: Modualrize vesafb
+  * SAUCE: DVB-USB UMT-010 driver oops on install
+  * SAUCE: fn key doesn't work in hardy with macbook pro fourth generation
+    (4,1)
+    - LP: #207127
+
+ -- Ben Collins <ben.collins@canonical.com>  Wed, 11 Jun 2008 05:28:35 -0400
--- linux-ec2-2.6.32.orig/debian.ec2/deviations.txt
+++ linux-ec2-2.6.32/debian.ec2/deviations.txt
@@ -0,0 +1,96 @@
+XEN PATCHSET
+F:	drivers/pci/msi.c
+F:	drivers/hwmon/coretemp.c
+F:	lib/swiotlb.c
+F:	arch/x86/kernel/pci-dma.c
+F:	arch/x86/kernel/ioport.c
+F:	arch/x86/kernel/smp.c
+F:	arch/x86/kernel/process_32.c
+F:	arch/x86/kernel/setup.c
+F:	arch/x86/kernel/msr.c
+F:	arch/x86/kernel/quirks.c
+F:	arch/x86/kernel/entry_64.S
+F:	arch/x86/kernel/process.c
+F:	arch/x86/kernel/pci-nommu.c
+F:	arch/x86/kernel/head64.c
+F:	arch/x86/kernel/head.c
+F:	arch/x86/kernel/head_32.S
+F:	arch/x86/kernel/irq.c
+F:	arch/x86/kernel/early_printk.c
+F:	arch/x86/kernel/process_64.c
+F:	arch/x86/kernel/mpparse.c
+F:	arch/x86/kernel/acpi/sleep.c
+F:	arch/x86/kernel/entry_32.S
+F:	arch/x86/kernel/traps.c
+F:	arch/x86/kernel/apic/ipi.c
+F:	arch/x86/kernel/apic/probe_32.c
+F:	arch/x86/kernel/apic/io_apic.c
+F:	arch/x86/kernel/apic/apic.c
+F:	arch/x86/kernel/microcode_core.c
+F:	arch/x86/kernel/head_64.S
+F:	arch/x86/kernel/x86_init.c
+F:	arch/x86/kernel/ldt.c
+F:	arch/x86/kernel/head32.c
+F:	arch/x86/kernel/vsyscall_64.c
+F:	arch/x86/kernel/cpu/common.c
+F:	arch/x86/kernel/cpu/mtrr/main.c
+F:	arch/x86/kernel/e820.c
+F:	arch/x86/kernel/time.c
+F:	arch/x86/pci/irq.c
+F:	arch/x86/mm/init.c
+F:	arch/x86/mm/iomap_32.c
+F:	arch/x86/mm/highmem_32.c
+F:	arch/x86/mm/init_32.c
+F:	arch/x86/mm/pgtable.c
+F:	arch/x86/mm/pgtable_32.c
+F:	arch/x86/mm/ioremap.c
+F:	arch/x86/mm/pageattr.c
+F:	arch/x86/mm/pat.c
+F:	arch/x86/mm/init_64.c
+F:	arch/x86/mm/fault.c
+F:	arch/x86/vdso/vdso32-setup.c
+F:	arch/x86/ia32/ia32entry.S
+F:	mm/tmem.c
+F:	arch/x86/include/asm/agp.h
+F:	arch/x86/include/asm/desc.h
+F:	arch/x86/include/asm/dma-mapping.h
+F:	arch/x86/include/asm/fixmap.h
+F:	arch/x86/include/asm/gnttab_dma.h
+F:	arch/x86/include/asm/highmem.h
+F:	arch/x86/include/asm/hypercall_32.h
+F:	arch/x86/include/asm/hypercall_64.h
+F:	arch/x86/include/asm/hypercall.h
+F:	arch/x86/include/asm/hypervisor.h
+F:	arch/x86/include/asm/io.h
+F:	arch/x86/include/asm/ipi.h
+F:	arch/x86/include/asm/irqflags.h
+F:	arch/x86/include/asm/irq_vectors.h
+F:	arch/x86/include/asm/mach_traps.h
+F:	arch/x86/include/asm/maddr_32.h
+F:	arch/x86/include/asm/maddr_64.h
+F:	arch/x86/include/asm/maddr.h
+F:	arch/x86/include/asm/mmu_context.h
+F:	arch/x86/include/asm/pci.h
+F:	arch/x86/include/asm/pgalloc.h
+F:	arch/x86/include/asm/pgtable_32.h
+F:	arch/x86/include/asm/pgtable-3level.h
+F:	arch/x86/include/asm/pgtable-3level_types.h
+F:	arch/x86/include/asm/pgtable_64.h
+F:	arch/x86/include/asm/pgtable_64_types.h
+F:	arch/x86/include/asm/pgtable.h
+F:	arch/x86/include/asm/pgtable_types.h
+F:	arch/x86/include/asm/processor.h
+F:	arch/x86/include/asm/setup.h
+F:	arch/x86/include/asm/smp.h
+F:	arch/x86/include/asm/smp-processor-id.h
+F:	arch/x86/include/asm/spinlock.h
+F:	arch/x86/include/asm/swiotlb.h
+F:	arch/x86/include/asm/synch_bitops.h
+F:	arch/x86/include/asm/system_64.h
+F:	arch/x86/include/asm/system.h
+F:	arch/x86/include/asm/tlbflush.h
+F:	arch/x86/include/asm/vga.h
+F:	arch/x86/include/asm/xenoprof.h
+F:	arch/x86/include/asm/xor_64.h
+F:	arch/x86/include/asm/xor.h
+F:	drivers/xen/*
--- linux-ec2-2.6.32.orig/debian.ec2/control
+++ linux-ec2-2.6.32/debian.ec2/control
@@ -0,0 +1,112 @@
+Source: linux-ec2
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.8.4.0
+Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], gawk
+Build-Depends-Indep: xmlto, docbook-utils, ghostscript, transfig, bzip2, sharutils
+Build-Conflicts: findutils (= 4.4.1-1ubuntu1)
+Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-karmic.git
+
+Package: linux-ec2-source-2.6.32
+Architecture: all
+Section: devel
+Priority: optional
+Provides: linux-ec2-source, linux-ec2-source-2.6
+Depends: ${misc:Depends}, binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version 2.6.32 with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ 2.6.32.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: linux-ec2-doc
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Conflicts: linux-ec2-doc-2.6
+Replaces: linux-ec2-doc-2.6
+Description: Linux kernel specific documentation for version 2.6.32
+ This package provides the various documents in the 2.6.32 kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/linux-ec2-doc/00-INDEX for a list of what is
+ contained in each file.
+
+Package: linux-headers-2.6.32-317
+Architecture: all
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0)
+#Provides: linux-headers, linux-headers-2.6
+Description: Header files related to Linux kernel version 2.6.32
+ This package provides kernel header files for version 2.6.32, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details
+
+
+Package: linux-image-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9
+Depends: ${misc:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1)
+Recommends: 
+Suggests: fdutils, linux-ec2-doc-2.6.32 | linux-ec2-source-2.6.32
+Description: Linux kernel image for version 2.6.32 on x86/x86_64
+ This package contains the Linux kernel image for version 2.6.32 on
+ x86/x86_64.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Generic processors.
+ .
+ Geared toward desktop systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-ec2 meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.32-317, ${shlibs:Depends}
+Description: Linux kernel headers for version 2.6.32 on x86/x86_64
+ This package provides kernel header files for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details.
+
+Package: linux-image-2.6.32-317-ec2-dbgsym
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version 2.6.32 on x86/x86_64
+ This package provides a kernel debug image for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
--- linux-ec2-2.6.32.orig/debian.ec2/NOTES
+++ linux-ec2-2.6.32/debian.ec2/NOTES
@@ -0,0 +1,4 @@
+eSCO patch removed. Replaced upstream with a disable_esco module parm.
+airprime: Module gone, use option driver instead
+AppArmor: Patch is all there and ported. Ooops when enabled, so default
+	off (still can be enabled apparmor=1)
--- linux-ec2-2.6.32.orig/debian.ec2/control.stub.in
+++ linux-ec2-2.6.32/debian.ec2/control.stub.in
@@ -0,0 +1,58 @@
+Source: SRCPKGNAME
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.8.4.0
+Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], gawk
+Build-Depends-Indep: xmlto, docbook-utils, ghostscript, transfig, bzip2, sharutils
+Build-Conflicts: findutils (= 4.4.1-1ubuntu1)
+Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-karmic.git
+
+Package: SRCPKGNAME-source-PKGVER
+Architecture: all
+Section: devel
+Priority: optional
+Provides: SRCPKGNAME-source, SRCPKGNAME-source-2.6
+Depends: ${misc:Depends}, binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version PKGVER with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ PKGVER.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: SRCPKGNAME-doc
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Conflicts: SRCPKGNAME-doc-2.6
+Replaces: SRCPKGNAME-doc-2.6
+Description: Linux kernel specific documentation for version PKGVER
+ This package provides the various documents in the PKGVER kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/SRCPKGNAME-doc/00-INDEX for a list of what is
+ contained in each file.
+
+Package: linux-headers-PKGVER-ABINUM
+Architecture: all
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0)
+#Provides: linux-headers, linux-headers-2.6
+Description: Header files related to Linux kernel version PKGVER
+ This package provides kernel header files for version PKGVER, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details
+
--- linux-ec2-2.6.32.orig/debian.ec2/control.stub
+++ linux-ec2-2.6.32/debian.ec2/control.stub
@@ -0,0 +1,112 @@
+Source: linux-ec2
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.8.4.0
+Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], gawk
+Build-Depends-Indep: xmlto, docbook-utils, ghostscript, transfig, bzip2, sharutils
+Build-Conflicts: findutils (= 4.4.1-1ubuntu1)
+Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-karmic.git
+
+Package: linux-ec2-source-2.6.32
+Architecture: all
+Section: devel
+Priority: optional
+Provides: linux-ec2-source, linux-ec2-source-2.6
+Depends: ${misc:Depends}, binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version 2.6.32 with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ 2.6.32.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: linux-ec2-doc
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Conflicts: linux-ec2-doc-2.6
+Replaces: linux-ec2-doc-2.6
+Description: Linux kernel specific documentation for version 2.6.32
+ This package provides the various documents in the 2.6.32 kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/linux-ec2-doc/00-INDEX for a list of what is
+ contained in each file.
+
+Package: linux-headers-2.6.32-317
+Architecture: all
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0)
+#Provides: linux-headers, linux-headers-2.6
+Description: Header files related to Linux kernel version 2.6.32
+ This package provides kernel header files for version 2.6.32, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details
+
+
+Package: linux-image-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9
+Depends: ${misc:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1)
+Recommends: 
+Suggests: fdutils, linux-ec2-doc-2.6.32 | linux-ec2-source-2.6.32
+Description: Linux kernel image for version 2.6.32 on x86/x86_64
+ This package contains the Linux kernel image for version 2.6.32 on
+ x86/x86_64.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Generic processors.
+ .
+ Geared toward desktop systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-ec2 meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-2.6.32-317-ec2
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.32-317, ${shlibs:Depends}
+Description: Linux kernel headers for version 2.6.32 on x86/x86_64
+ This package provides kernel header files for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-2.6.32-317/debian.README.gz for details.
+
+Package: linux-image-2.6.32-317-ec2-dbgsym
+Architecture: i386 amd64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version 2.6.32 on x86/x86_64
+ This package provides a kernel debug image for version 2.6.32 on
+ x86/x86_64.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
--- linux-ec2-2.6.32.orig/debian.ec2/copyright
+++ linux-ec2-2.6.32/debian.ec2/copyright
@@ -0,0 +1,30 @@
+This is the Ubuntu prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
+and others.
+
+This package was put together by the Ubuntu Kernel Team, from
+sources retrieved from upstream linux git.
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package is currently maintained by the
+Ubuntu Kernel Team <ubuntu-kernel@lists.ubuntu.com>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   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.
+
+On Ubuntu Linux systems, the complete text of the GNU General
+Public License v2 can be found in `/usr/share/common-licenses/GPL-2'.
--- linux-ec2-2.6.32.orig/debian.ec2/rules.d/i386.mk
+++ linux-ec2-2.6.32/debian.ec2/rules.d/i386.mk
@@ -0,0 +1,12 @@
+build_arch	= x86
+header_arch	= x86
+asm_link	= x86
+defconfig	= defconfig
+flavours        = ec2
+build_image	= vmlinuz
+kernel_file	= arch/$(build_arch)/boot/vmlinuz
+install_file	= vmlinuz
+loader		= grub
+
+do_libc_dev_package	= false
+do_tools		= false
--- linux-ec2-2.6.32.orig/debian.ec2/rules.d/amd64.mk
+++ linux-ec2-2.6.32/debian.ec2/rules.d/amd64.mk
@@ -0,0 +1,12 @@
+build_arch	= x86_64
+header_arch	= $(build_arch)
+asm_link	= $(build_arch)
+defconfig	= defconfig
+flavours	= ec2
+build_image	= vmlinuz
+kernel_file	= arch/$(build_arch)/boot/vmlinuz
+install_file	= vmlinuz
+loader		= grub
+
+do_libc_dev_package	= false
+do_tools		= false
--- linux-ec2-2.6.32.orig/debian.ec2/abi/2.6.32-317.35/abiname
+++ linux-ec2-2.6.32/debian.ec2/abi/2.6.32-317.35/abiname
@@ -0,0 +1 @@
+317
--- linux-ec2-2.6.32.orig/debian.ec2/abi/2.6.32-317.35/i386/ec2
+++ linux-ec2-2.6.32/debian.ec2/abi/2.6.32-317.35/i386/ec2
@@ -0,0 +1,7900 @@
+EXPORT_SYMBOL arch/x86/kernel/scx200 0x254e5667	scx200_gpio_base
+EXPORT_SYMBOL arch/x86/kernel/scx200 0x35a3c008	scx200_gpio_configure
+EXPORT_SYMBOL arch/x86/kernel/scx200 0x8cfa375c	scx200_gpio_shadow
+EXPORT_SYMBOL arch/x86/kernel/scx200 0x907665bd	scx200_cb_base
+EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f	gf128mul_4k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x1068004b	gf128mul_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0	gf128mul_init_64k_lle
+EXPORT_SYMBOL crypto/gf128mul 0x3755f990	gf128mul_init_64k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce	gf128mul_64k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd	gf128mul_x_ble
+EXPORT_SYMBOL crypto/gf128mul 0x83581089	gf128mul_init_4k_lle
+EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9	gf128mul_init_4k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6	gf128mul_lle
+EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df	gf128mul_4k_lle
+EXPORT_SYMBOL crypto/gf128mul 0xc0890413	gf128mul_64k_lle
+EXPORT_SYMBOL crypto/gf128mul 0xd60736ec	gf128mul_free_64k
+EXPORT_SYMBOL crypto/xor 0x5b6c00e6	xor_blocks
+EXPORT_SYMBOL drivers/atm/suni 0xcb9a5d89	suni_init
+EXPORT_SYMBOL drivers/atm/uPD98402 0xc22107ce	uPD98402_init
+EXPORT_SYMBOL drivers/block/paride/paride 0x2d5fdbf7	pi_release
+EXPORT_SYMBOL drivers/block/paride/paride 0x3ff3de3d	pi_disconnect
+EXPORT_SYMBOL drivers/block/paride/paride 0x5091cd89	paride_register
+EXPORT_SYMBOL drivers/block/paride/paride 0x821f531a	pi_write_regr
+EXPORT_SYMBOL drivers/block/paride/paride 0xc0a62ce2	pi_read_block
+EXPORT_SYMBOL drivers/block/paride/paride 0xd584016e	pi_connect
+EXPORT_SYMBOL drivers/block/paride/paride 0xd667a3f2	paride_unregister
+EXPORT_SYMBOL drivers/block/paride/paride 0xd6c32ceb	pi_read_regr
+EXPORT_SYMBOL drivers/block/paride/paride 0xd93d48b0	pi_schedule_claimed
+EXPORT_SYMBOL drivers/block/paride/paride 0xdc0470b9	pi_do_claimed
+EXPORT_SYMBOL drivers/block/paride/paride 0xe34bede7	pi_init
+EXPORT_SYMBOL drivers/block/paride/paride 0xf4b79cef	pi_write_block
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x082ae731	agp_generic_remove_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x0d68611d	agp_bind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x0d9f9b1a	agp_allocate_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x0de8c355	agp_flush_chipset
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x10588fbb	agp_free_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x175958e3	agp_backend_acquire
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x30226ddf	agp_device_command
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x360dd730	agp_generic_alloc_user
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x4117cb5c	agp_find_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x4b085dbf	agp3_generic_configure
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x4ca9537d	agp_generic_create_gatt_table
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x5a44bcba	agp3_generic_tlbflush
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x646c0cb2	agp_alloc_page_array
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x673f815e	agp_bridges
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x6d7b6936	agp_enable
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x6fc70f57	agp_free_page_array
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x733aa5b2	agp_generic_alloc_by_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x73e05d58	agp_generic_free_by_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x7538b132	agp_off
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x79e6757e	agp_create_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x81a80f46	agp_generic_destroy_page
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x8390332d	agp_collect_device_status
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x8490f709	agp_copy_info
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x8670bea2	agp_generic_insert_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x8a3f2786	agp_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x9131432a	agp_alloc_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x985e715f	agp_generic_destroy_pages
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xa4d4f0e6	global_cache_flush
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xa4dd98be	agp_put_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xaba69ef6	get_agp_version
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xade809e1	agp_generic_mask_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xb04ea8f0	agp_rebind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xb5dd694a	agp_generic_alloc_page
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xbb78ecca	agp_generic_alloc_pages
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc2424641	agp3_generic_cleanup
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc5d9c46c	agp_try_unsupported_boot
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc65abeb7	agp3_generic_sizes
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc662e391	agp_backend_release
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd05da03d	agp_generic_free_gatt_table
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd0fef3b2	agp_free_key
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd1d04b6b	agp_generic_enable
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd5bf7dfb	agp_generic_type_to_mask_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd5d76898	agp_unbind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xde9b17ed	agp3_generic_fetch_size
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x00b823f2	ipmi_set_gets_events
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x01d14532	ipmi_free_recv_msg
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0da99428	ipmi_set_maintenance_mode
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x19ce986a	ipmi_smi_watchdog_pretimeout
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x26aadd42	ipmi_smi_watcher_unregister
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x2c8d4d5a	ipmi_set_my_address
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c	ipmi_alloc_smi_msg
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x58490a2f	ipmi_set_my_LUN
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x5ae3eeae	ipmi_request_settime
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x5e278278	ipmi_smi_watcher_register
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x612a6f3b	ipmi_unregister_for_cmd
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6c894b85	ipmi_register_for_cmd
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x7f355d55	ipmi_register_smi
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a	ipmi_addr_length
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x8d11ad27	ipmi_create_user
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x92e88433	ipmi_poll_interface
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xaabe5897	ipmi_smi_add_proc_entry
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xafe905e3	ipmi_get_maintenance_mode
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb8366b2d	ipmi_get_my_address
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc1a6dca7	ipmi_get_version
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd91b7289	ipmi_unregister_smi
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xdd5e359f	ipmi_get_my_LUN
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b	ipmi_validate_addr
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf60361ed	ipmi_destroy_user
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xfb8c9247	ipmi_request_supply_msgs
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xfe52bb94	ipmi_smi_msg_received
+EXPORT_SYMBOL drivers/char/nsc_gpio 0x368e0399	nsc_gpio_read
+EXPORT_SYMBOL drivers/char/nsc_gpio 0x54a1fee0	nsc_gpio_write
+EXPORT_SYMBOL drivers/char/nsc_gpio 0x6206c558	nsc_gpio_dump
+EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91	nvram_read_byte
+EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d	__nvram_read_byte
+EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0	__nvram_check_checksum
+EXPORT_SYMBOL drivers/char/nvram 0x7da28f12	nvram_check_checksum
+EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f	nvram_write_byte
+EXPORT_SYMBOL drivers/char/nvram 0xa8813189	__nvram_write_byte
+EXPORT_SYMBOL drivers/edac/edac_core 0x3b21e786	edac_mc_handle_fbd_ce
+EXPORT_SYMBOL drivers/edac/edac_core 0xd556385d	edac_mc_find
+EXPORT_SYMBOL drivers/edac/edac_core 0xd7bb0d50	edac_mc_handle_fbd_ue
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0012d3a8	drm_sysfs_connector_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0508145d	drm_free_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0753e03d	drm_debugfs_remove_files
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x076b04aa	drm_mm_takedown
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c	drm_sman_takedown
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x08950b9d	drm_mode_detachmode_crtc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x089cda91	drm_do_probe_ddc_edid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0a6c8e0e	drm_mode_config_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0c3a5f2f	drm_irq_uninstall
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0f6b7c7f	drm_mode_create_dirty_info_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x122d7045	drm_mode_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x12e9d179	drm_core_reclaim_buffers
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x13ef6abe	drm_mode_create_scaling_mode_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x14d32a0c	drm_i_have_hw_lock
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x15b7941c	drm_agp_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x18180b55	drm_framebuffer_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x19846e71	drm_master_put
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1d11b55a	drm_mode_duplicate
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1ed00073	drm_sysfs_hotplug_event
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1f072c59	drm_property_add_enum
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642	drm_debug
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4	drm_sman_owner_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x216bc374	drm_handle_vblank
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x22a62c70	drm_rmmap_locked
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x24bb5a4f	drm_agp_bind_pages
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x24dae939	drm_ati_pcigart_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x24f41009	drm_connector_attach_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x257ad01b	drm_mode_create_dithering_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2672a6ca	drm_vblank_post_modeset
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x27186831	drm_i2c_encoder_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63	drm_sman_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x29ac34e9	drm_framebuffer_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2d5b5148	drm_get_resource_len
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2e5aa62a	drm_mode_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903	drm_sman_free_key
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033	drm_order
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x34a77b1d	drm_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x35cb0cd1	drm_agp_acquire
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x389105d5	drm_agp_bind
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3a0a7794	drm_vblank_count
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3c9a1409	drm_ht_just_insert_please
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3d88d4eb	drm_crtc_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4048327a	drm_debugfs_create_files
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x408c1c94	drm_get_drawable_info
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x409d5c47	drm_property_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x430aedda	drm_mm_search_free_in_range
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x449be971	drm_addbufs_pci
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x47b37f71	drm_vblank_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4a21055b	drm_sg_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4bf4804c	drm_mode_probed_add
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4f41da13	drm_mode_connector_attach_encoder
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x51f26d95	drm_get_dev
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x55358747	drm_clflush_pages
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee	drm_sman_set_range
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5722d86b	drm_mm_get_block_range_generic
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x580830f0	drm_mode_set_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5999c3a4	drm_mm_clean
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5afc7cc3	drm_vblank_pre_modeset
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5bdb38eb	drm_idlelock_release
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5e845236	drm_put_dev
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5f06a9f9	drm_irq_install
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x60a7d2b3	drm_fasync
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x66b6c3b3	drm_gem_object_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6d2e5837	drm_ut_debug_printk
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6d562e50	drm_mode_object_find
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6f546720	drm_mm_get_block_generic
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6fc30481	drm_mode_hsync
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x70c6b3fa	drm_property_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x73d54154	drm_encoder_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x74a80b35	drm_mode_create_dvi_i_properties
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x76f4cc01	drm_rmmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x77bed803	drm_mm_debug_table
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x784915eb	drm_mode_vrefresh
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7a09b1c1	drm_ioctl
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7ae9fe50	drm_ati_pcigart_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7becf9f2	drm_gem_object_handle_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7c1fd6c8	drm_mode_equal
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7d8383d7	drm_get_connector_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7e0116a8	drm_master_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x85de09f5	drm_mode_width
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8671768b	drm_sysfs_connector_add
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x87d6e7ef	drm_detect_hdmi_monitor
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8847c9b2	drm_agp_unbind
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8872f50c	drm_idlelock_take
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8c43ce39	drm_gem_handle_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8c5c145f	drm_mode_prune_invalid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8d272f59	drm_connector_property_get_value
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x91878403	drm_getsarea
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x972401dc	drm_mm_search_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x99d794e5	drm_exit
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9cc1206d	drm_mode_attachmode_crtc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9d492086	drm_core_ioremapfree
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9e0c5530	drm_core_ioremap_wc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa0909e2d	drm_agp_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa1b2c162	drm_poll
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa1eabd87	drm_mode_list_concat
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa4504ee8	drm_agp_release
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa462f87d	drm_mmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa50ca064	drm_vblank_off
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa725430e	drm_mode_config_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaa33d719	drm_read
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e	drm_sman_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaffaf5f3	drm_core_get_reg_ofs
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb22141e0	drm_gem_object_lookup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb55f45c7	drm_lock_take
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb6d02950	drm_open
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb8b23b86	drm_connector_property_set_value
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbb6fc1e7	drm_lock_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbc4a8543	drm_mode_connector_detach_encoder
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbc6f8acf	drm_get_edid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbd937560	drm_gem_vm_open
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xc15ceb98	drm_mode_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xcb4551b5	drm_core_ioremap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xcdf2eff4	drm_mode_height
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd02f4ec5	drm_gem_vm_close
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd08fa3f0	drm_mode_set_crtcinfo
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd0cef153	drm_add_modes_noedid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75	drm_sman_set_manager
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd393d5c8	drm_agp_enable
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3ffab51	drm_ht_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd49bdfb4	drm_crtc_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd52703de	drm_mode_crtc_set_gamma_size
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd62fe2a7	drm_agp_info
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd63d6819	drm_core_get_map_ofs
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd9c506b0	drm_gtf_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xda6c967e	drm_pci_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdb173201	drm_mode_connector_list_update
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdbd3a19d	drm_connector_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdd3febe2	drm_gem_object_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdd49095c	drm_ht_insert_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xddb608ac	drm_encoder_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdee0b01d	drm_get_encoder_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe015fdea	drm_mode_validate_clocks
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe1457735	drm_ht_remove_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe14a61be	drm_connector_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe206b96e	drm_mm_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe24a7b88	drm_ht_find_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe307800f	drm_vblank_put
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe3eaf635	drm_addbufs_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe4703948	drm_addmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe5bdce7e	drm_mode_debug_printmodeline
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe5ebe930	drm_mode_connector_update_edid_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe72e6436	drm_mm_put_block
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe7c35aa6	drm_mm_pre_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe8dd5ac9	drm_gem_mmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c	drm_sman_owner_clean
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe9d53900	drm_pci_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xeb660c10	drm_mode_create_tv_properties
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xef040730	drm_add_edid_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xef437b9f	drm_agp_chipset_flush
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xef6a35c4	drm_mode_validate_size
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xef6b876c	drm_i2c_encoder_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf1421d13	drm_mode_sort
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf42a2b26	drm_ht_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf70bf695	drm_get_resource_start
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf86aad9e	drm_mm_dump_table
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf98c3267	drm_unbind_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xfb1ad410	drm_cvt_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xfc56da77	drm_vblank_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xfde1ea99	drm_vblank_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19	drm_sman_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xffe452a2	drm_release
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x01075920	drm_fb_helper_fill_var
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x0124bff1	drm_fb_helper_setcmap
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x05432fe4	drm_helper_connector_dpms
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x22b26327	drm_crtc_helper_set_config
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x486c0a92	drm_helper_encoder_in_use
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x9691a2ab	drm_fb_helper_add_connector
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x9d251144	drm_fb_helper_panic
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x9f4dc129	drm_helper_initial_config
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x9f8fa3a4	drm_fb_helper_check_var
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xa4d803bd	drm_fb_helper_pan_display
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xa7d09e43	drm_helper_mode_fill_fb_struct
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xac5b2940	drm_fb_helper_free
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb0136394	drm_helper_disable_unused_functions
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb2ac5725	drm_helper_hotplug_stage_two
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb6734780	drm_helper_resume_force_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xbda84400	drm_fb_helper_init_crtc_count
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xc469c244	drm_fb_helper_restore
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xc9543e47	drm_fb_helper_blank
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xcda20ec7	drm_helper_crtc_in_use
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xd4194a05	drm_fb_helper_fill_fix
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xdc488029	drm_helper_probe_connector_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xe3aaae87	drm_crtc_helper_set_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xe67d8118	drm_fb_helper_setcolreg
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xeaee1e09	drm_helper_probe_single_connector_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xedad2910	drm_fb_helper_single_fb_probe
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xfead7e7d	i2c_dp_aux_add_bus
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xff323bed	drm_fb_helper_set_par
+EXPORT_SYMBOL drivers/gpu/drm/radeon/radeon 0x0a3991ea	radeonfb_remove
+EXPORT_SYMBOL drivers/gpu/drm/radeon/radeon 0x406778ba	radeonfb_resize
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x01c99cb0	ttm_write_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x07787990	ttm_bo_global_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x0f8632d1	ttm_ref_object_add
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x132b05be	ttm_round_pot
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x13e4b09d	ttm_fbdev_mmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x18ce32a2	ttm_bo_wait
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x1a21e07b	ttm_object_file_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x1ba8c0ef	ttm_lock_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x1e6432b5	ttm_base_object_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x1fb2c159	ttm_mem_global_alloc
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x23e649a0	ttm_bo_move_accel_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x27cfc650	ttm_mem_global_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x2a9d31ff	ttm_bo_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x2b658408	ttm_ref_object_base_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x2ba03707	ttm_bo_mmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x2d673efd	ttm_vt_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x34704ea7	ttm_global_item_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x365feb2e	ttm_eu_reserve_buffers
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x3b755abf	ttm_bo_mem_space
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x3c3c3af1	ttm_bo_global_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x4f439554	ttm_bo_kunmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x508f9e07	ttm_bo_unmap_virtual
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5259558e	ttm_bo_move_ttm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x56c42d22	ttm_suspend_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5a408359	ttm_base_object_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5d24c24b	ttm_bo_clean_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x61bdb34f	ttm_eu_fence_buffer_objects
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x66666d70	ttm_global_item_ref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x675728c8	ttm_bo_wait_unreserved
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x6dc3c4c4	ttm_tt_set_placement_caching
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x765cbc82	ttm_read_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x76e4d9b5	ttm_bo_device_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x7737d8f6	ttm_bo_swapout_all
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x7f607f2d	ttm_bo_wait_cpu
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x7f8879de	ttm_vt_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x817ae444	ttm_base_object_lookup
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x86a4066d	ttm_eu_backoff_reservation
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8b7081a6	ttm_bo_synccpu_write_grab
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8bed5cd8	ttm_bo_move_memcpy
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8db796d4	ttm_write_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9011e87d	ttm_bo_kmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9068bd43	ttm_bo_init_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9a374b5c	ttm_object_file_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xb110f4e5	ttm_bo_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xb2a69f49	ttm_tt_bind
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xb5cf2fe9	ttm_suspend_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xba3c7f56	ttm_object_device_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xbb717290	ttm_bo_synccpu_write_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xbba2ecf9	ttm_read_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xbe675918	ttm_object_device_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xbfd4a86a	ttm_agp_backend_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xc4b7ebaa	ttm_bo_reserve
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xcba46a5f	ttm_bo_device_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xd486973b	ttm_mem_global_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xe9841902	ttm_bo_evict_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xf006e40c	ttm_bo_unreserve
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xf5a38e4b	ttm_mem_global_free
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xf60c4915	ttm_io_prot
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xf8bc7f43	ttm_tt_populate
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xfb2113b3	ttm_bo_validate
+EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239	vid_from_reg
+EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c	vid_which_vrm
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x235f8dea	i2c_bit_add_numbered_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x9d59fe43	i2c_bit_add_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x31371d43	i2c_pca_add_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0x9b574945	i2c_pca_add_numbered_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0xd2adf151	i2c_pcf_add_bus
+EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0xcbbdf465	amd756_smbus
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x00606733	i2c_smbus_read_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x09014df8	i2c_smbus_read_byte
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x0c45b2de	i2c_master_recv
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x171ad428	i2c_use_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x1be7ee82	i2c_smbus_read_i2c_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x25cd48a2	i2c_smbus_write_byte_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x2b4d5d6b	i2c_register_driver
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x410ef9cc	i2c_master_send
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x48245808	i2c_del_driver
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x55bc7410	i2c_smbus_read_word_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x5e5538cd	i2c_smbus_write_i2c_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x616366dc	i2c_del_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x70a0e05a	i2c_add_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x75ceb631	i2c_smbus_process_call
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x7b5b6f36	i2c_smbus_write_byte
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x805b5799	i2c_smbus_xfer
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x805c1cce	i2c_release_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x81b8c479	i2c_verify_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x877e7068	i2c_smbus_write_word_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x936a5f4d	i2c_smbus_write_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xac722498	i2c_transfer
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xb04f0604	i2c_clients_command
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xb2dd1ff9	i2c_smbus_read_byte_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xb9afadfe	i2c_put_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xcf0a3cb2	i2c_get_adapter
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0b234c4e	dma_prog_region_alloc
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0bf7b0b1	hpsb_allocate_and_register_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x111bcbdd	hpsb_selfid_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1270cdac	hpsb_iso_recv_release_packets
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x14ec8f9b	hpsb_iso_xmit_queue_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x158ac548	dma_region_offset_to_bus
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1a200e5a	csr1212_release_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1acb7666	hpsb_make_writepacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1be74a49	hpsb_iso_recv_unlisten_channel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x29d8f7e9	hpsb_set_packet_complete_task
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2a4cc36b	csr1212_attach_keyval_to_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ac20314	hpsb_free_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2e0e9434	hpsb_unregister_protocol
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ebf6e5a	dma_prog_region_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x35f8e646	hpsb_packet_success
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x38508b87	hpsb_destroy_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x38c1cc77	hpsb_iso_packet_sent
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x395964dc	hpsb_unregister_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3aac6892	hpsb_add_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3b442bc0	hpsb_make_streampacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3c6be7a1	hpsb_iso_recv_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3e784d8b	hpsb_set_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x40c5afa4	hpsb_read_cycle_timer
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x450db3c2	__hpsb_register_protocol
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x452a5107	hpsb_get_hostinfo_bykey
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x49155659	hpsb_get_tlabel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4bbfc8b3	hpsb_iso_xmit_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4fe12178	hpsb_reset_bus
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x503f91bf	hpsb_read
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x51e2874c	hpsb_register_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x54520420	hpsb_packet_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5678ff58	hpsb_iso_xmit_sync
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x59b67c6d	hpsb_set_hostinfo_key
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5f5fdd2f	csr1212_new_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5f9ac210	hpsb_alloc_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x63fb36bd	hpsb_update_config_rom
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148	dma_region_sync_for_device
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x67bfece9	hpsb_iso_recv_set_channel_mask
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6a8c1c2d	hpsb_lock
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7232cc41	hpsb_iso_n_ready
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c	dma_region_free
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x79486853	hpsb_iso_packet_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7d037e1f	hpsb_create_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7fea9d78	hpsb_write
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0	dma_region_sync_for_cpu
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312	dma_region_alloc
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x94bce230	csr1212_get_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x990c500c	hpsb_make_readpacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9ea5d264	hpsb_remove_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9ea65868	hpsb_iso_recv_start
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa4a08135	hpsb_iso_recv_flush
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa6ea1312	hpsb_node_write
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa80133a5	hpsb_iso_shutdown
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa92c9e64	hpsb_iso_xmit_start
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaa77ac06	hpsb_resume_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaef57bb5	csr1212_detach_keyval_from_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaefbd374	csr1212_parse_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb14056fd	hpsb_node_fill_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb17a9ef5	hpsb_bus_reset
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb4b8643c	hpsb_unregister_highlevel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb89608e7	hpsb_make_lock64packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb986189f	hpsb_alloc_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xbe18469a	hpsb_iso_wake
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc939891f	hpsb_iso_stop
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd9e772b	dma_prog_region_free
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcf9dcdb1	hpsb_make_lockpacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd14b27ae	hpsb_iso_recv_listen_channel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd40ae0fd	hpsb_update_config_rom_image
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd4fb1926	hpsb_send_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd6952797	dma_region_mmap
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd92691d7	hpsb_packet_sent
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe01ad515	hpsb_make_phypacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe7fe23ba	hpsb_protocol_class
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff	dma_region_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfab27536	csr1212_read
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfb94c6b3	hpsb_selfid_complete
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51	hpsb_speedto_str
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfc88c4bc	hpsb_register_highlevel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfe5e1123	hpsb_get_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfefc3343	hpsb_free_tlabel
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x016937c3	ohci1394_register_iso_tasklet
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x1d5aeebc	ohci1394_init_iso_tasklet
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x81223484	ohci1394_unregister_iso_tasklet
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xa0ed39c6	ohci1394_stop_context
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x463650d5	rdma_translate_ip
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x8a721ed9	rdma_addr_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x96a74d97	rdma_resolve_ip
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xb11df1d0	rdma_addr_cancel
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xc91bb9d3	rdma_addr_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xfd886531	rdma_copy_addr
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x065a7d69	ib_send_cm_dreq
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x0b078665	ib_send_cm_req
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x111be005	ib_destroy_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x554a1e7b	ib_create_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x57f4459a	cm_class
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x5d5a9517	ib_cm_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x6fe313fc	ib_send_cm_drep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x877ccd25	ib_cm_notify
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8a085b39	ib_send_cm_rep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x903e6c7c	ib_send_cm_rej
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xb68d8597	ib_send_cm_rtu
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xcf8f506e	ib_send_cm_sidr_req
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xd4d20d4c	ib_send_cm_apr
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xdfcdcef3	ib_send_cm_lap
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xe4c0296b	ib_send_cm_mra
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xf12b0f15	ib_send_cm_sidr_rep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xf32aada4	ib_cm_listen
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x00baf461	ib_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0143a4dd	ib_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x019a004c	ib_get_client_data
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x047234f4	ib_dealloc_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x055fd554	ib_alloc_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06a16dd1	ib_modify_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x07e7f8ae	ib_dealloc_mw
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0a5b6edc	ib_find_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x10a37729	ib_flush_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x11211b42	ib_umem_get
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1301ef85	ib_dereg_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x15677c6f	ib_attach_mcast
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x16cc0896	ib_register_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04	ib_unmap_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x209332a5	ib_modify_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x24d62fb9	ib_query_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2aacee76	ib_modify_port
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2d77030b	ib_alloc_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3086cdf1	ib_umem_release
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3470db61	ib_unregister_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x374f9a60	ib_alloc_fast_reg_page_list
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x39b9dbf5	ib_query_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd	ib_rate_to_mult
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x46c68a6e	ib_modify_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x520b2638	ib_pack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x52aca7d6	ib_init_ah_from_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x53aed0da	ib_register_event_handler
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x59658ab5	ib_dealloc_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x605d6904	ib_alloc_mw
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x63b5657c	ib_modify_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x674cda0c	ib_query_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x676b36ae	ib_create_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6819edb7	ib_rereg_phys_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6c835b88	ib_modify_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6ea0498f	ib_query_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x71bad921	ib_alloc_pd
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x76d829bb	ib_query_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7d0d29a3	ib_alloc_fast_reg_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x83e882a3	ib_create_ah_from_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb	ib_modify_qp_is_ok
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8	ib_ud_header_pack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8c3c9d2f	ib_umem_page_count
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x91996a73	ib_create_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ae5c8e	ib_fmr_pool_unmap
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46	rdma_node_get_transport
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x98842973	ib_get_cached_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9c0252ea	ib_query_port
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9ca9c5c4	ib_destroy_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1	mult_to_ib_rate
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9f875620	ib_destroy_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa47456f5	ib_resize_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa90f2490	ib_destroy_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xabeab121	ib_detach_mcast
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xae8ad21d	ib_get_dma_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb1009492	ib_find_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb1a312e1	ib_unpack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb2116df5	ib_query_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb6cc47f1	ib_dispatch_event
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb73d7242	ib_fmr_pool_map_phys
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb9ae9800	ib_get_cached_lmc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xbefa0feb	ib_unregister_event_handler
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc0416c67	ib_get_cached_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1	ib_ud_header_init
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd7afcb36	ib_destroy_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd8dc5e6a	ib_find_cached_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd9a0f225	ib_create_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdcf0828c	ib_query_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xde290f05	ib_destroy_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xeb0032a5	ib_create_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xede2cdad	ib_set_client_data
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xeea90978	ib_dealloc_pd
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf013fb5f	ib_find_cached_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9	ib_ud_header_unpack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf9a03708	ib_free_fast_reg_page_list
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf9f88111	ib_reg_phys_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfefc282c	ib_create_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x00bae0d9	ib_modify_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x19e6ee03	ib_register_mad_snoop
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x22aebbdf	ib_redirect_mad_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x237403f5	ib_register_mad_agent
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x54cc228e	ib_unregister_mad_agent
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6e3f54f5	ib_free_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed	ib_response_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf	ib_get_mad_data_offset
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a	ib_is_mad_class_rmpp
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x8efe5d21	ib_create_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x8fad5b8d	ib_process_mad_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xae7bd9e9	ib_post_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xbb8b1ad3	ib_free_recv_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xbfce06c8	ib_get_rmpp_segment
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xc8a3ae67	ib_cancel_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x41ab0d11	ib_init_ah_from_path
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac	ib_sa_free_multicast
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x8495a9c1	ib_sa_join_multicast
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x8ece50e4	ib_sa_path_rec_get
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x9c56fd34	ib_sa_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xd950cfea	ib_sa_get_mcmember_rec
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xdd3421de	ib_sa_service_rec_query
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xf04c21ce	ib_init_ah_from_mcmember
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xf520d09e	ib_sa_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xfd47a3da	ib_sa_cancel_query
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc	ib_copy_path_rec_from_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51	ib_copy_ah_attr_to_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a	ib_copy_path_rec_to_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575	ib_copy_qp_attr_to_user
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x0c2b2b83	iw_destroy_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x2931d571	iw_cm_listen
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x6903a1bd	iw_cm_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x837946ca	iw_cm_disconnect
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x9495f661	iw_cm_connect
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xbad734e2	iw_cm_reject
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xcb599eae	iw_create_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xf2cce6c6	iw_cm_accept
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x0375ce55	rdma_set_ib_paths
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x271a957a	rdma_bind_addr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x39894ae3	rdma_disconnect
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x3bb07d3e	rdma_resolve_route
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x479435c3	rdma_resolve_addr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x59a25de1	rdma_create_qp
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x7090f5c7	rdma_accept
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x8942168e	rdma_connect
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9e968d0e	rdma_create_id
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xa0ea2b66	rdma_set_service_type
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xaefd1b75	rdma_reject
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb831c942	rdma_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xbecbbce1	rdma_destroy_qp
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xc8addc3a	rdma_join_multicast
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd6c85806	rdma_listen
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd94e66f9	rdma_leave_multicast
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xe76c65e7	rdma_notify
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xe8e7547c	rdma_destroy_id
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x09d9da1f	gameport_start_polling
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x12ad05c5	gameport_set_phys
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x4194b995	gameport_unregister_driver
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x48887155	gameport_stop_polling
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x86c37d32	gameport_close
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xc2e094a5	gameport_unregister_port
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xe1d16ed5	gameport_open
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xe9e677a0	__gameport_register_driver
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xf4359230	__gameport_register_port
+EXPORT_SYMBOL drivers/input/input-polldev 0x28bb22f8	input_register_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0x79c0e54c	input_allocate_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0x899b44df	input_unregister_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0xc37d0fba	input_free_polled_device
+EXPORT_SYMBOL drivers/md/dm-log 0x397ee003	dm_dirty_log_destroy
+EXPORT_SYMBOL drivers/md/dm-log 0x442170aa	dm_dirty_log_type_register
+EXPORT_SYMBOL drivers/md/dm-log 0x869b2d52	dm_dirty_log_create
+EXPORT_SYMBOL drivers/md/dm-log 0xd9382309	dm_dirty_log_type_unregister
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x4277c803	dm_exception_store_type_unregister
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x75f51570	dm_exception_store_type_register
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x775784c2	dm_exception_store_create
+EXPORT_SYMBOL drivers/md/dm-snapshot 0xb9c97a93	dm_exception_store_destroy
+EXPORT_SYMBOL drivers/md/md-mod 0x05672cbe	register_md_personality
+EXPORT_SYMBOL drivers/md/md-mod 0x26ab27d6	mddev_congested
+EXPORT_SYMBOL drivers/md/md-mod 0x3534c8e5	bitmap_start_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x3785838a	bitmap_startwrite
+EXPORT_SYMBOL drivers/md/md-mod 0x43f99cff	md_error
+EXPORT_SYMBOL drivers/md/md-mod 0x53c106a6	md_write_start
+EXPORT_SYMBOL drivers/md/md-mod 0x5414b56f	md_wakeup_thread
+EXPORT_SYMBOL drivers/md/md-mod 0x5cb17716	bitmap_end_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x67455501	md_done_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x691acffc	md_unregister_thread
+EXPORT_SYMBOL drivers/md/md-mod 0x6c40ae41	md_wait_for_blocked_rdev
+EXPORT_SYMBOL drivers/md/md-mod 0x6cb0d916	md_integrity_add_rdev
+EXPORT_SYMBOL drivers/md/md-mod 0x869174d4	bitmap_cond_end_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x8aefa968	md_set_array_sectors
+EXPORT_SYMBOL drivers/md/md-mod 0xa7ce6aad	bitmap_endwrite
+EXPORT_SYMBOL drivers/md/md-mod 0xaa6fd9e4	md_write_end
+EXPORT_SYMBOL drivers/md/md-mod 0xae32ca3e	md_register_thread
+EXPORT_SYMBOL drivers/md/md-mod 0xb89c3c66	bitmap_close_sync
+EXPORT_SYMBOL drivers/md/md-mod 0xb95996ad	unregister_md_personality
+EXPORT_SYMBOL drivers/md/md-mod 0xd45e62bc	md_check_recovery
+EXPORT_SYMBOL drivers/md/md-mod 0xf2bcd1de	md_integrity_register
+EXPORT_SYMBOL drivers/md/md-mod 0xfd4e1446	bitmap_unplug
+EXPORT_SYMBOL drivers/md/md-mod 0xfd6a9f92	md_check_no_bitmap
+EXPORT_SYMBOL drivers/md/raid6_pq 0x0bd662f6	raid6_gfmul
+EXPORT_SYMBOL drivers/md/raid6_pq 0x15fe0cd3	raid6_gfexp
+EXPORT_SYMBOL drivers/md/raid6_pq 0x5ba93f9d	raid6_gfinv
+EXPORT_SYMBOL drivers/md/raid6_pq 0xb0d904b7	raid6_empty_zero_page
+EXPORT_SYMBOL drivers/md/raid6_pq 0xce45a6f1	raid6_gfexi
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x04da5e10	mpt_device_driver_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0a03d25d	mpt_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x124d2dec	mpt_send_handshake_request
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x1a3753a1	mpt_put_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x1eb7eaa0	mptbase_sas_persist_operation
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2bc1d1fe	mpt_print_ioc_summary
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3061d6ac	mpt_set_taskmgmt_in_progress_flag
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x396dbac5	mpt_detach
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x3c97de18	mpt_put_msg_frame_hi_pri
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b	mpt_event_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x47850b92	mpt_halt_firmware
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4c26c35e	mpt_resume
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x502108d0	mpt_fwfault_debug
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x53cba5eb	mpt_event_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6eba7d66	mpt_config
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7ac79aaa	mpt_findImVolumes
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x947453a1	mpt_verify_adapter
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa525c753	mpt_alloc_fw_memory
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xa711cf0c	mpt_attach
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xab861552	mpt_raid_phys_disk_get_num_paths
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xac77c726	mpt_suspend
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xbc4dcbbc	mpt_raid_phys_disk_pg0
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82	mpt_device_driver_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8	mpt_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc5ac79eb	mpt_raid_phys_disk_pg1
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd3bcfce0	mpt_GetIocState
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd3f6f0b9	mpt_free_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75	mpt_reset_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdace417d	mpt_clear_taskmgmt_in_progress_flag
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159	ioc_list
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe0234dac	mpt_reset_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe498bef1	mpt_get_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xeb581c16	mpt_free_fw_memory
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf0a20eb1	mpt_HardResetHandler
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x05b68d02	mptscsih_ioc_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x140369ff	mptscsih_shutdown
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x15260bf2	mptscsih_abort
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x18a901ee	mptscsih_proc_info
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1a10515f	mptscsih_suspend
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1ccd03fa	mptscsih_dev_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x1fbc4809	mptscsih_host_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x219364ec	mptscsih_raid_id_to_num
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x45a235e1	mptscsih_taskmgmt_response_code
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x4ba977b6	mptscsih_resume
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x5675aae1	mptscsih_slave_destroy
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x56e944b0	mptscsih_remove
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x572a86bf	mptscsih_bios_param
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x60f1cc60	mptscsih_is_phys_disk
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6704403c	mptscsih_event_process
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6e9dc52d	mptscsih_qcmd
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x70ef998b	mptscsih_slave_configure
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x752686f9	mptscsih_bus_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x88245b8d	mptscsih_info
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x99fba214	mptscsih_IssueTaskMgmt
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x9d245ffc	mptscsih_change_queue_depth
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xa446ad4d	mptscsih_get_scsi_lookup
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xc0630b63	mptscsih_taskmgmt_complete
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe5032fd0	mptscsih_scandv_complete
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xeab875cf	mptscsih_host_attrs
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xeb25abf5	mptscsih_io_done
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x09bb6f22	i2o_parm_issue
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x0b78c541	i2o_driver_register
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a1bb15c	i2o_device_claim
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef	i2o_dump_message
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x387cb9d0	i2o_msg_get_wait
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x610ba8a1	i2o_driver_notify_device_add_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x651f4405	i2o_parm_field_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x6a0623b5	i2o_driver_notify_device_remove_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x6c1ec023	i2o_device_claim_release
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x6f4332a1	i2o_driver_notify_controller_remove_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x820c9932	i2o_find_iop
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xa9fdb297	i2o_driver_notify_controller_add_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf	i2o_controllers
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xc146fde0	i2o_status_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xcf15531a	i2o_parm_table_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xe059b46f	i2o_event_register
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xeba03ba6	i2o_iop_find_device
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xed18bff0	i2o_exec_lct_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xed28eae1	i2o_driver_unregister
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf0b626c1	i2o_msg_post_wait_mem
+EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x67322761	pasic3_write_register
+EXPORT_SYMBOL drivers/mfd/htc-pasic3 0xbb1f80fe	pasic3_read_register
+EXPORT_SYMBOL drivers/mfd/mfd-core 0x944c9709	mfd_remove_devices
+EXPORT_SYMBOL drivers/mfd/mfd-core 0xf9308a40	mfd_add_devices
+EXPORT_SYMBOL drivers/mfd/tps65010 0x02d4ad0f	tps65013_set_low_pwr
+EXPORT_SYMBOL drivers/mfd/tps65010 0x28485130	tps65010_config_vregs1
+EXPORT_SYMBOL drivers/mfd/tps65010 0x33739de7	tps65010_set_vib
+EXPORT_SYMBOL drivers/mfd/tps65010 0x9fd44c69	tps65010_set_led
+EXPORT_SYMBOL drivers/mfd/tps65010 0xb14080cc	tps65010_set_low_pwr
+EXPORT_SYMBOL drivers/mfd/tps65010 0xd5bb106d	tps65010_set_vbus_draw
+EXPORT_SYMBOL drivers/mfd/tps65010 0xe99b3f36	tps65010_set_gpio_out_value
+EXPORT_SYMBOL drivers/misc/ioc4 0xb00cacd2	ioc4_register_submodule
+EXPORT_SYMBOL drivers/misc/ioc4 0xe00500bd	ioc4_unregister_submodule
+EXPORT_SYMBOL drivers/misc/tifm_core 0x17d421ca	tifm_queue_work
+EXPORT_SYMBOL drivers/misc/tifm_core 0x2285ba0a	tifm_free_device
+EXPORT_SYMBOL drivers/misc/tifm_core 0x269b4d8e	tifm_unregister_driver
+EXPORT_SYMBOL drivers/misc/tifm_core 0x32da6490	tifm_remove_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0x3625c03d	tifm_alloc_device
+EXPORT_SYMBOL drivers/misc/tifm_core 0x54b34077	tifm_eject
+EXPORT_SYMBOL drivers/misc/tifm_core 0x62241469	tifm_unmap_sg
+EXPORT_SYMBOL drivers/misc/tifm_core 0x80ba0c7d	tifm_alloc_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0x8a270ed1	tifm_register_driver
+EXPORT_SYMBOL drivers/misc/tifm_core 0x9c7dfe79	tifm_has_ms_pif
+EXPORT_SYMBOL drivers/misc/tifm_core 0xb5cbe0a1	tifm_add_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0xd064e214	tifm_map_sg
+EXPORT_SYMBOL drivers/misc/tifm_core 0xfe168dfa	tifm_free_adapter
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x091a8814	cfi_read_pri
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x526e13fc	cfi_fixup
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xed165246	cfi_varsize_frob
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x85f2a3c8	map_destroy
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xe2634ade	unregister_mtd_chip_driver
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xe2733947	register_mtd_chip_driver
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xf47ad75c	do_map_probe
+EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0x6aa1a5d0	mtd_do_chip_probe
+EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0x574969fc	simple_map_init
+EXPORT_SYMBOL drivers/mtd/mtd 0x3c1eb894	add_mtd_partitions
+EXPORT_SYMBOL drivers/mtd/mtd 0xd6f7e1cc	del_mtd_partitions
+EXPORT_SYMBOL drivers/mtd/mtdconcat 0x17f86b02	mtd_concat_create
+EXPORT_SYMBOL drivers/mtd/mtdconcat 0x1f4dcffb	mtd_concat_destroy
+EXPORT_SYMBOL drivers/mtd/nand/nand 0xc2f5b4e1	nand_scan_bbt
+EXPORT_SYMBOL drivers/mtd/nand/nand 0xdec7d514	nand_default_bbt
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0x3cb55f88	nand_calculate_ecc
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0xb4b94377	__nand_correct_data
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0xbd27b86f	nand_correct_data
+EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72	nand_flash_ids
+EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7	nand_manuf_ids
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x6cecf7f2	flexonenand_region
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xa581e1cd	onenand_addr
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xb4af4d9d	onenand_default_bbt
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xca4f50b8	onenand_scan_bbt
+EXPORT_SYMBOL drivers/net/8390 0x0b2f5dd9	ei_poll
+EXPORT_SYMBOL drivers/net/8390 0x34621ffe	ei_set_multicast_list
+EXPORT_SYMBOL drivers/net/8390 0x569c954f	ei_tx_timeout
+EXPORT_SYMBOL drivers/net/8390 0x748c7fde	NS8390_init
+EXPORT_SYMBOL drivers/net/8390 0x7c742dfb	ei_netdev_ops
+EXPORT_SYMBOL drivers/net/8390 0x7fc04c30	__alloc_ei_netdev
+EXPORT_SYMBOL drivers/net/8390 0xa335ff1a	ei_close
+EXPORT_SYMBOL drivers/net/8390 0xa8383461	ei_start_xmit
+EXPORT_SYMBOL drivers/net/8390 0xbb8ecd8c	ei_open
+EXPORT_SYMBOL drivers/net/8390 0xd5d4a6d2	ei_get_stats
+EXPORT_SYMBOL drivers/net/8390 0xdd365790	ei_interrupt
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x0dc499cd	arcnet_send_packet
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x226d1bb0	arc_proto_map
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x23f86078	arcnet_interrupt
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x24959200	arc_bcast_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x48c4303f	arcnet_timeout
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4d4f74d0	arc_proto_default
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x4fee3fe4	arcnet_unregister_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a	arcnet_debug
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x835b6e3f	arcnet_close
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x9911c12b	arc_raw_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xb3df502c	alloc_arcdev
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xb60021ae	arcnet_open
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0x9c9f3f9c	com20020_check
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0xafe1db82	com20020_found
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0xee556201	com20020_netdev_ops
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x1c2f208c	cxgb3_alloc_atid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x20d07113	t3_register_cpl_handler
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x29c1d00d	cxgb3_free_atid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x2f32b284	cxgb3_queue_tid_release
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x37ed55d2	cxgb3_register_client
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x4a0787f6	t3_l2t_send_event
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x604f7b89	cxgb3_free_stid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x75d0d31d	cxgb3_ofld_send
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x780fdb1d	cxgb3_alloc_stid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8bf2f858	cxgb3_remove_tid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xbfac46b0	cxgb3_insert_tid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc4d7791a	t3_l2e_free
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd4d703bf	t3_l2t_get
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xdd3c89fc	t3_l2t_send_slow
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xe12e3de9	dev2t3cdev
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xeba5eff9	cxgb3_unregister_client
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x08c40801	hdlcdrv_transmitter
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x0e1c7cb2	hdlcdrv_unregister
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x64439b3f	hdlcdrv_register
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x9cf6302d	hdlcdrv_arbitrate
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xf7fb1fff	hdlcdrv_receiver
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x1c7a3e19	sirdev_raw_write
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x6764163f	sirdev_raw_read
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x67a0bff6	irda_unregister_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x6d5c894a	sirdev_write_complete
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x7de2037a	sirdev_put_instance
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xb6a33fcb	irda_register_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xbf838d34	sirdev_set_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xc48c8d6c	sirdev_set_dtr_rts
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xc542ccf4	sirdev_get_instance
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf5d3d1f5	sirdev_receive
+EXPORT_SYMBOL drivers/net/mdio 0x0f934475	mdio45_ethtool_gset_npage
+EXPORT_SYMBOL drivers/net/mdio 0x22bce513	mdio_mii_ioctl
+EXPORT_SYMBOL drivers/net/mdio 0x43e4defc	mdio45_nway_restart
+EXPORT_SYMBOL drivers/net/mdio 0x7577f992	mdio_set_flag
+EXPORT_SYMBOL drivers/net/mdio 0xa1a29548	mdio45_probe
+EXPORT_SYMBOL drivers/net/mdio 0xb34a7575	mdio45_ethtool_spauseparam_an
+EXPORT_SYMBOL drivers/net/mdio 0xc6b1163f	mdio45_links_ok
+EXPORT_SYMBOL drivers/net/mii 0x0a2227ce	mii_check_media
+EXPORT_SYMBOL drivers/net/mii 0x12024737	mii_link_ok
+EXPORT_SYMBOL drivers/net/mii 0x1e87436e	generic_mii_ioctl
+EXPORT_SYMBOL drivers/net/mii 0x1f4dc878	mii_check_link
+EXPORT_SYMBOL drivers/net/mii 0x2fe64bdc	mii_ethtool_sset
+EXPORT_SYMBOL drivers/net/mii 0x76ca60e3	mii_ethtool_gset
+EXPORT_SYMBOL drivers/net/mii 0xd5c52a4d	mii_check_gmii_support
+EXPORT_SYMBOL drivers/net/mii 0xe64408bf	mii_nway_restart
+EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x2f410d41	alloc_mdio_bitbang
+EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x7dbc6800	free_mdio_bitbang
+EXPORT_SYMBOL drivers/net/pppox 0x0b1dbf5b	pppox_ioctl
+EXPORT_SYMBOL drivers/net/pppox 0x1b2bcf5a	register_pppox_proto
+EXPORT_SYMBOL drivers/net/pppox 0x803e1d8c	pppox_unbind_sock
+EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18	unregister_pppox_proto
+EXPORT_SYMBOL drivers/net/sungem_phy 0xf06849c4	mii_phy_probe
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x3cf2eb7c	tms380tr_netdev_ops
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x5815fc07	tmsdev_init
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xa3203679	tms380tr_close
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xae47ae8c	tms380tr_open
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xbb37c801	tmsdev_term
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794	tms380tr_wait
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd49af46e	tms380tr_interrupt
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725	cycx_intr
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea	cycx_setup
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6	cycx_down
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6	cycx_peek
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de	cycx_poke
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576	cycx_exec
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x0f9720bc	detach_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x12c42b3a	unregister_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x23cdf243	unregister_hdlc_device
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x267b7162	hdlc_close
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x336ec3dd	attach_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x5eddaa62	hdlc_start_xmit
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x73512001	register_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x8de01629	alloc_hdlcdev
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xba3e1def	hdlc_open
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xe62f292c	hdlc_ioctl
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xef1dc598	hdlc_change_mtu
+EXPORT_SYMBOL drivers/parport/parport 0x02dd3d50	parport_set_timeout
+EXPORT_SYMBOL drivers/parport/parport 0x0446c21d	parport_register_driver
+EXPORT_SYMBOL drivers/parport/parport 0x048a79bd	parport_claim
+EXPORT_SYMBOL drivers/parport/parport 0x0dc4f855	parport_find_number
+EXPORT_SYMBOL drivers/parport/parport 0x1c60588b	parport_ieee1284_read_byte
+EXPORT_SYMBOL drivers/parport/parport 0x2ac9f133	parport_remove_port
+EXPORT_SYMBOL drivers/parport/parport 0x2ae5593c	parport_wait_event
+EXPORT_SYMBOL drivers/parport/parport 0x2c4081e4	parport_release
+EXPORT_SYMBOL drivers/parport/parport 0x2ce3e083	parport_ieee1284_ecp_write_addr
+EXPORT_SYMBOL drivers/parport/parport 0x2f2491a4	parport_announce_port
+EXPORT_SYMBOL drivers/parport/parport 0x2f91fc4f	parport_read
+EXPORT_SYMBOL drivers/parport/parport 0x3f7f6b06	parport_unregister_driver
+EXPORT_SYMBOL drivers/parport/parport 0x42a494f4	parport_claim_or_block
+EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b	parport_ieee1284_interrupt
+EXPORT_SYMBOL drivers/parport/parport 0x57bb013d	parport_register_device
+EXPORT_SYMBOL drivers/parport/parport 0x702d6d68	parport_ieee1284_ecp_read_data
+EXPORT_SYMBOL drivers/parport/parport 0x72cb265c	parport_ieee1284_ecp_write_data
+EXPORT_SYMBOL drivers/parport/parport 0x7810727f	parport_find_base
+EXPORT_SYMBOL drivers/parport/parport 0x89c05a7c	parport_write
+EXPORT_SYMBOL drivers/parport/parport 0x924b8742	parport_ieee1284_epp_read_data
+EXPORT_SYMBOL drivers/parport/parport 0x9af5b5eb	parport_ieee1284_epp_write_addr
+EXPORT_SYMBOL drivers/parport/parport 0x9c9320be	parport_ieee1284_read_nibble
+EXPORT_SYMBOL drivers/parport/parport 0x9d5eff70	parport_irq_handler
+EXPORT_SYMBOL drivers/parport/parport 0xa2740ba4	parport_register_port
+EXPORT_SYMBOL drivers/parport/parport 0xad1107c0	parport_put_port
+EXPORT_SYMBOL drivers/parport/parport 0xaf1f8a7f	parport_negotiate
+EXPORT_SYMBOL drivers/parport/parport 0xafeeb5fc	parport_get_port
+EXPORT_SYMBOL drivers/parport/parport 0xb1152c6e	parport_wait_peripheral
+EXPORT_SYMBOL drivers/parport/parport 0xbf531bcd	parport_ieee1284_epp_read_addr
+EXPORT_SYMBOL drivers/parport/parport 0xc27a9f32	parport_unregister_device
+EXPORT_SYMBOL drivers/parport/parport 0xc4dd7334	parport_ieee1284_epp_write_data
+EXPORT_SYMBOL drivers/parport/parport 0xf3e11ec7	parport_ieee1284_write_compat
+EXPORT_SYMBOL drivers/parport/parport_pc 0x547e00ca	parport_pc_probe_port
+EXPORT_SYMBOL drivers/parport/parport_pc 0x793e7ca7	parport_pc_unregister_port
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x24e68399	pcmcia_request_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x24f9390e	pcmcia_release_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x318be85c	pcmcia_request_irq
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x47bcace5	pcmcia_request_io
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x4fd033a0	pcmcia_error_func
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x71e70532	pcmcia_access_configuration_register
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x744fc3ea	pcmcia_disable_device
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x7562db18	pcmcia_dev_present
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x7919ef80	pcmcia_request_configuration
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x8bc1bd8a	pcmcia_modify_configuration
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa3e1d75b	pcmcia_loop_config
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xbaac5c5c	pcmcia_unregister_driver
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xe476622c	pcmcia_register_driver
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xe6ececbb	pcmcia_map_mem_page
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf021d77e	pcmcia_get_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf0a25e12	pcmcia_error_ret
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf6ee7377	pcmcia_get_mem_page
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0e97e50b	pccard_static_ops
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x14f9f056	pcmcia_socket_dev_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1c46301c	pccard_register_pcmcia
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1e203f64	pcmcia_put_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2	pcmcia_socket_list
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x251e74f6	pcmcia_unregister_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x296e8ddc	destroy_cis_cache
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2ed5cf83	pcmcia_insert_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x30b2d75b	pccard_get_first_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x4b672e9a	pcmcia_replace_cis
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x55dfe47b	pccard_read_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5aa4e4e1	pcmcia_reset_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5f42a69d	pcmcia_socket_list_rwsem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5f7913f9	pcmcia_get_socket_by_nr
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x61a94dd7	pccard_validate_cis
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x77e308b8	pcmcia_suspend_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x8ff345a2	pcmcia_register_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa04ef904	pcmcia_parse_events
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa08edb6d	release_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa1169f77	pcmcia_socket_dev_suspend
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa811ac44	pcmcia_read_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xab366960	pcmcia_get_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xafa774a9	pcmcia_write_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xb7d3d69c	pccard_get_next_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xbb3fec13	pcmcia_socket_dev_late_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xbea6920d	pcmcia_socket_class
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc02ef2c8	pcmcia_parse_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc1831381	pcmcia_socket_dev_early_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc3192a0f	pcmcia_eject_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd	dead_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xd6648d01	pcmcia_find_mem_region
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xddf0a517	pcmcia_adjust_io_region
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xe14f24cf	pcmcia_resume_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xe152db15	pcmcia_validate_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xece199ce	pccard_get_tuple_data
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xf7ccb040	pcmcia_find_io_region
+EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0xf6305e51	pccard_nonstatic_ops
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x0890b466	mraid_mm_register_adp
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e	mraid_mm_adapter_app_handle
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d	mraid_mm_unregister_adp
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x0c2b934a	qlogicfas408_abort
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x12bba6c2	qlogicfas408_disable_ints
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3ae53afd	qlogicfas408_biosparam
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71	qlogicfas408_detect
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x6aed9078	qlogicfas408_bus_reset
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x75bd504b	qlogicfas408_queuecommand
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xae43a6c6	qlogicfas408_info
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xdc310b12	qlogicfas408_ihandl
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20	qlogicfas408_get_chip_type
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199	qlogicfas408_setup
+EXPORT_SYMBOL drivers/scsi/raid_class 0x15b108c7	raid_class_attach
+EXPORT_SYMBOL drivers/scsi/raid_class 0x807fa53e	raid_class_release
+EXPORT_SYMBOL drivers/scsi/raid_class 0xace0c35d	raid_component_add
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x00f95bfc	scsi_device_get
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x07c67125	starget_for_each_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x07d9b783	scsi_nl_send_vendor_msg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0a5ff779	scsi_dma_map
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c	scsi_normalize_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99	scsi_show_extd_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0da968ca	scsi_eh_restore_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875	scsi_extd_sense_format
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1887c894	scsi_execute
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1	scsilun_to_int
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1c2178c6	scsi_setup_blk_pc_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1d3bfd73	scsi_cmd_print_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2131ca2d	scsi_test_unit_ready
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2148ddb8	scsi_report_bus_reset
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x260055b9	scsi_mode_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02	scsi_build_sense_buffer
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2a379925	scsi_unregister
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0	scsi_sense_desc_find
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a	scsi_show_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x30233d2f	scsi_release_buffers
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x323b9956	scsi_get_device_flags_keyed
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3cee70da	scsi_scan_host
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3f5173b0	scsi_add_host_with_dma
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x40a27c37	scsi_dev_info_remove_list
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x46616b0d	scsi_eh_finish_cmd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77	scsi_partsize
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4beb09e0	scsi_calculate_bounce_limit
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4dba61f1	scsi_track_queue_full
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4dd86b59	scsi_print_result
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e6fff68	scsi_device_quiesce
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5307975a	scsi_command_normalize_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x53333884	scsi_get_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x54c0688c	scsi_adjust_queue_depth
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d	scsi_kunmap_atomic_sg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56d47cf1	scsi_host_put
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x576f708f	scsi_remove_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x60abd151	scsi_report_device_reset
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x654c23e8	scsi_nonblockable_ioctl
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6565d33f	scsi_kmap_atomic_sg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9	__scsi_print_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6b11ba07	scsicam_bios_param
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6bef71b5	scsi_print_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6c33736f	scsi_device_put
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6e47eebd	scsi_host_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6e4fe76b	scsi_register
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x70d2024d	scsi_rescan_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d	scsi_device_type
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7327222b	scsi_setup_fs_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7598fc48	scsi_put_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x75b3bfe3	scsi_bios_ptable
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x75cd1379	scsi_init_io
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x77696a51	scsi_is_host_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x77bf25ef	scsi_block_when_processing_errors
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7965acfb	scsi_device_set_state
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce	scsi_get_sense_info_fld
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7b33c6ba	__scsi_device_lookup_by_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7b7999a2	scsi_add_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8266786a	scsi_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x84adbabc	scsi_eh_prep_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x84d628dc	scsi_finish_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8a24e56d	scsi_free_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8f8ed664	scsi_prep_fn
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8fddeddf	scsi_device_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9340db08	scsi_dma_unmap
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9461c65d	scsi_host_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04	scsi_sense_key_string
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5	scsi_print_status
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa06a2f89	__scsi_device_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa6d8522a	scsi_host_set_state
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc	scsi_logging_level
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb1337f75	scsi_host_get
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb1dab4bf	scsi_device_resume
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb4709322	scsi_dev_info_add_list
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb5d8a750	__scsi_iterate_devices
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973	scsi_show_result
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb8f4e059	scsi_register_driver
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xba429807	scsi_execute_req
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbd92e1ca	scsi_prep_return
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbe87c2a2	scsi_reset_provider
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc34cbe8b	scsi_remove_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc6bb4c80	scsi_allocate_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc7139eb2	scsi_ioctl
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc8c92012	scsi_device_lookup_by_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50	scsi_print_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd189692e	__scsi_alloc_queue
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd97b1c11	scsi_register_interface
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd9c210d8	scsi_target_resume
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xdc047fc4	scsi_dev_info_list_add_keyed
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe08e8487	scsi_free_host_dev
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe14c82ea	scsi_is_sdev_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe49d7832	__scsi_add_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe704376e	scsi_set_medium_removal
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a	int_to_scsilun
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xec755115	scsi_prep_state_check
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xeef20a73	__scsi_put_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xefeb5629	scsi_scan_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf1bb55ea	scsi_print_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf51d2ce1	__starget_for_each_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf59330e6	scsi_block_requests
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d	scsi_eh_flush_done_q
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfa685510	scsi_get_host_dev
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfdbec4c2	scsi_target_quiesce
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfddb3e10	scsi_unblock_requests
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfee29935	scsi_is_target_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23	__scsi_print_command
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x0216ac2a	fc_vport_terminate
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x090da5b5	fc_host_post_vendor_event
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x0f0389e6	scsi_is_fc_rport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x256d2f43	fc_host_post_event
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x3adb21ba	fc_attach_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4cd2d616	fc_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4f6a57d0	fc_vport_create
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x75b2200e	fc_remote_port_rolechg
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea	fc_get_event_number
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7cea0d35	scsi_is_fc_vport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x817ba540	fc_remote_port_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x93642237	fc_remote_port_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xa4dc0ae4	fc_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x08bbcc3b	sas_phy_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x187bd5a6	sas_rphy_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x2668402c	sas_rphy_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x47deb979	sas_port_alloc_num
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x4c7dbd1a	sas_end_device_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x508024a8	sas_port_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x53a5f342	sas_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x86a303db	sas_rphy_remove
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8afe589e	sas_rphy_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x8bac6e7b	sas_expander_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x91dc38eb	sas_phy_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9254687a	scsi_is_sas_port
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x932e1eb2	sas_port_delete_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x9bb51f5b	sas_port_add_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xb04aef5b	sas_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xbbe98814	sas_phy_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc126cf13	sas_attach_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc5301be2	sas_read_port_mode_page
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xdce62567	scsi_is_sas_rphy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xdecf0b30	sas_port_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xdf9a30e6	sas_port_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xe1401777	sas_remove_children
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xebba598d	sas_port_mark_backlink
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xec78509d	sas_phy_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf2b0e250	sas_port_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xf3de4f3e	scsi_is_sas_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x1d609775	spi_schedule_dv_device
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09	spi_print_msg
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3afd84f8	spi_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x5b0dc9f5	spi_display_xfer_agreement
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x83aeca4f	spi_attach_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x92dc3e82	spi_dv_device
+EXPORT_SYMBOL drivers/ssb/ssb 0x00c63b34	ssb_dma_translation
+EXPORT_SYMBOL drivers/ssb/ssb 0x09e80715	ssb_dma_alloc_consistent
+EXPORT_SYMBOL drivers/ssb/ssb 0x10437562	ssb_pmu_set_ldo_voltage
+EXPORT_SYMBOL drivers/ssb/ssb 0x1888257f	ssb_bus_unregister
+EXPORT_SYMBOL drivers/ssb/ssb 0x1c99294d	ssb_driver_unregister
+EXPORT_SYMBOL drivers/ssb/ssb 0x2aca7233	ssb_set_devtypedata
+EXPORT_SYMBOL drivers/ssb/ssb 0x2cd30e8d	ssb_bus_powerup
+EXPORT_SYMBOL drivers/ssb/ssb 0x5f0d977a	ssb_pcicore_dev_irqvecs_enable
+EXPORT_SYMBOL drivers/ssb/ssb 0x7272142e	ssb_dma_set_mask
+EXPORT_SYMBOL drivers/ssb/ssb 0x886ce92d	ssb_pmu_set_ldo_paref
+EXPORT_SYMBOL drivers/ssb/ssb 0x9b4e8590	ssb_device_disable
+EXPORT_SYMBOL drivers/ssb/ssb 0x9bf54c43	ssb_dma_free_consistent
+EXPORT_SYMBOL drivers/ssb/ssb 0xa92bb8a0	ssb_bus_may_powerdown
+EXPORT_SYMBOL drivers/ssb/ssb 0xac0511e0	__ssb_driver_register
+EXPORT_SYMBOL drivers/ssb/ssb 0xb8e1ffe2	ssb_bus_suspend
+EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f	ssb_admatch_base
+EXPORT_SYMBOL drivers/ssb/ssb 0xd1bf65ac	ssb_bus_resume
+EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b	ssb_admatch_size
+EXPORT_SYMBOL drivers/ssb/ssb 0xd988f998	ssb_device_enable
+EXPORT_SYMBOL drivers/ssb/ssb 0xdb215551	ssb_pcihost_register
+EXPORT_SYMBOL drivers/ssb/ssb 0xe20b0c10	ssb_bus_pcibus_register
+EXPORT_SYMBOL drivers/ssb/ssb 0xfe249e32	ssb_device_is_enabled
+EXPORT_SYMBOL drivers/ssb/ssb 0xfe40456a	ssb_clockspeed
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0x135637ff	net2280_set_fifo_mode
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0x511e9356	usb_gadget_register_driver
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0xd0a1d344	usb_gadget_unregister_driver
+EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0x53c94a44	sl811h_driver
+EXPORT_SYMBOL drivers/usb/serial/usbserial 0x16f19c76	usb_serial_suspend
+EXPORT_SYMBOL drivers/usb/serial/usbserial 0x37fa6307	usb_serial_resume
+EXPORT_SYMBOL drivers/video/backlight/lcd 0x31982afd	lcd_device_unregister
+EXPORT_SYMBOL drivers/video/backlight/lcd 0x3e5f66f8	lcd_device_register
+EXPORT_SYMBOL drivers/video/console/bitblit 0x235864b8	fbcon_set_bitops
+EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55	font_vga_8x16
+EXPORT_SYMBOL drivers/video/console/font 0xbb99125c	get_default_font
+EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c	find_font
+EXPORT_SYMBOL drivers/video/console/softcursor 0x0cb8dabe	soft_cursor
+EXPORT_SYMBOL drivers/video/console/tileblit 0x2343e6ce	fbcon_set_tileops
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x0a96741a	cyber2000fb_disable_extregs
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5	cyber2000fb_detach
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x413fe49c	cyber2000fb_attach
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x73d80b00	cyber2000fb_enable_extregs
+EXPORT_SYMBOL drivers/video/cyber2000fb 0xabf52ce8	cyber2000fb_get_fb_var
+EXPORT_SYMBOL drivers/video/display/display 0x3712b9ea	display_device_register
+EXPORT_SYMBOL drivers/video/display/display 0x61cc0a2a	display_device_unregister
+EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62	mac_vmode_to_var
+EXPORT_SYMBOL drivers/video/macmodes 0xa0ec7837	mac_find_mode
+EXPORT_SYMBOL drivers/video/macmodes 0xe2304303	mac_map_monitor_sense
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x1fd247b2	matroxfb_g450_setclk
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x3739a60f	matroxfb_g450_setpll_cond
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x8fec48a8	g450_mnp2f
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x4dbd3c60	matrox_mystique
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x647935cf	DAC1064_global_init
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x8241d1db	matrox_G100
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xc47ca2ce	DAC1064_global_restore
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0x194e74dc	matrox_millennium
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0xb5f1b629	matrox_cfbX_init
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x2524de40	matroxfb_enable_irq
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x6b2ae50c	matroxfb_register_driver
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x880c30de	matroxfb_wait_for_sync
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xb923660d	matroxfb_unregister_driver
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x2ad59cc4	matroxfb_g450_connect
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0xc783802d	matroxfb_g450_shutdown
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049	matroxfb_PLL_calcclock
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x50091441	matroxfb_vgaHWinit
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xa2aad3e4	matroxfb_DAC_out
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xa8c0c4a6	matroxfb_read_pins
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427	matroxfb_var2my
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xb8d17c62	matroxfb_DAC_in
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xdf1ee9c9	matroxfb_vgaHWrestore
+EXPORT_SYMBOL drivers/video/output 0x15c2b513	video_output_unregister
+EXPORT_SYMBOL drivers/video/output 0x921d1779	video_output_register
+EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e	sis_malloc
+EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0	sis_free
+EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9	svga_set_default_seq_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30	svga_wseq_multi
+EXPORT_SYMBOL drivers/video/svgalib 0x0f66e7c0	svga_get_tilemax
+EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a	svga_check_timings
+EXPORT_SYMBOL drivers/video/svgalib 0x3175203e	svga_settile
+EXPORT_SYMBOL drivers/video/svgalib 0x53cba7f5	svga_tileblit
+EXPORT_SYMBOL drivers/video/svgalib 0x5fd56da1	svga_tilefill
+EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1	svga_set_default_crt_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959	svga_wcrt_multi
+EXPORT_SYMBOL drivers/video/svgalib 0x80408443	svga_set_timings
+EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b	svga_set_textmode_vga_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x973089be	svga_tilecopy
+EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad	svga_set_default_gfx_regs
+EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1	svga_set_default_atc_regs
+EXPORT_SYMBOL drivers/video/svgalib 0xec83c473	svga_match_format
+EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d	svga_compute_pll
+EXPORT_SYMBOL drivers/video/svgalib 0xf0d98c47	svga_tilecursor
+EXPORT_SYMBOL drivers/video/svgalib 0xf1b3db2a	svga_get_caps
+EXPORT_SYMBOL drivers/video/syscopyarea 0xc30f1d67	sys_copyarea
+EXPORT_SYMBOL drivers/video/sysfillrect 0xee5ac714	sys_fillrect
+EXPORT_SYMBOL drivers/video/sysimgblt 0x2e08a386	sys_imageblit
+EXPORT_SYMBOL drivers/video/vgastate 0x686de290	restore_vga
+EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e	save_vga
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x0bb1e92c	w1_ds2760_read
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x33dd4558	w1_ds2760_write
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x9a8ef05a	w1_ds2760_store_eeprom
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0xa0e2267e	w1_ds2760_recall_eeprom
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc	iTCO_vendor_check_noreboot_on
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44	iTCO_vendor_pre_keepalive
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894	iTCO_vendor_pre_set_heartbeat
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac	iTCO_vendor_pre_start
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320	iTCO_vendor_pre_stop
+EXPORT_SYMBOL fs/nfsd/nfsd 0x0e195c1c	nfs4_acl_nfsv4_to_posix
+EXPORT_SYMBOL fs/nfsd/nfsd 0x2095976a	nfs4_acl_new
+EXPORT_SYMBOL fs/nfsd/nfsd 0x28fb929b	nfs4_acl_posix_to_nfsv4
+EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e	nfs4_acl_write_who
+EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4	nfs4_acl_get_whotype
+EXPORT_SYMBOL fs/quota/quota_tree 0x148bb3f8	qtree_entry_unused
+EXPORT_SYMBOL fs/quota/quota_tree 0x4aa44d9b	qtree_release_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0x888137bd	qtree_read_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0xb4b1505d	qtree_delete_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0xc4930ded	qtree_write_dquot
+EXPORT_SYMBOL lib/crc-ccitt 0x3771b461	crc_ccitt
+EXPORT_SYMBOL lib/crc-ccitt 0x75811312	crc_ccitt_table
+EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f	crc_itu_t_table
+EXPORT_SYMBOL lib/crc-itu-t 0xf5b4a948	crc_itu_t
+EXPORT_SYMBOL lib/crc-t10dif 0xb6896671	crc_t10dif
+EXPORT_SYMBOL lib/crc7 0xa7587646	crc7
+EXPORT_SYMBOL lib/crc7 0xd80c3603	crc7_syndrome_table
+EXPORT_SYMBOL lib/libcrc32c 0x27000b29	crc32c
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd	zlib_deflateInit2
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724	zlib_deflateReset
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d	zlib_deflate
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b	zlib_deflate_workspacesize
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793	zlib_deflateEnd
+EXPORT_SYMBOL net/802/p8023 0x29399483	make_8023_client
+EXPORT_SYMBOL net/802/p8023 0xabc2f008	destroy_8023_client
+EXPORT_SYMBOL net/9p/9pnet 0x11a600c9	p9_client_attach
+EXPORT_SYMBOL net/9p/9pnet 0x11b66704	v9fs_get_default_trans
+EXPORT_SYMBOL net/9p/9pnet 0x1511ea75	p9_client_cb
+EXPORT_SYMBOL net/9p/9pnet 0x1b56994e	v9fs_register_trans
+EXPORT_SYMBOL net/9p/9pnet 0x2318cdd0	p9_client_auth
+EXPORT_SYMBOL net/9p/9pnet 0x23b6f6d5	p9_tag_lookup
+EXPORT_SYMBOL net/9p/9pnet 0x2b913f05	p9_client_disconnect
+EXPORT_SYMBOL net/9p/9pnet 0x32ca985e	v9fs_get_trans_by_name
+EXPORT_SYMBOL net/9p/9pnet 0x3455711e	p9_idpool_destroy
+EXPORT_SYMBOL net/9p/9pnet 0x35421571	p9_client_walk
+EXPORT_SYMBOL net/9p/9pnet 0x3b250757	p9_client_remove
+EXPORT_SYMBOL net/9p/9pnet 0x3d73a797	p9_errstr2errno
+EXPORT_SYMBOL net/9p/9pnet 0x3e3e5416	p9_client_stat
+EXPORT_SYMBOL net/9p/9pnet 0x3f0de585	p9_client_destroy
+EXPORT_SYMBOL net/9p/9pnet 0x408cda8d	p9_client_clunk
+EXPORT_SYMBOL net/9p/9pnet 0x4b221f14	p9_client_open
+EXPORT_SYMBOL net/9p/9pnet 0x50c67040	p9_client_write
+EXPORT_SYMBOL net/9p/9pnet 0x50d106ce	p9_client_fcreate
+EXPORT_SYMBOL net/9p/9pnet 0x60a35acb	v9fs_unregister_trans
+EXPORT_SYMBOL net/9p/9pnet 0x6b754e6f	p9_parse_header
+EXPORT_SYMBOL net/9p/9pnet 0x76b79bf1	p9stat_read
+EXPORT_SYMBOL net/9p/9pnet 0x849db6ba	p9_client_wstat
+EXPORT_SYMBOL net/9p/9pnet 0x9c964743	p9stat_free
+EXPORT_SYMBOL net/9p/9pnet 0xaab8671a	p9_idpool_get
+EXPORT_SYMBOL net/9p/9pnet 0xcae61af3	p9_idpool_create
+EXPORT_SYMBOL net/9p/9pnet 0xd0faf92e	p9_idpool_check
+EXPORT_SYMBOL net/9p/9pnet 0xd331fc1d	p9pdu_dump
+EXPORT_SYMBOL net/9p/9pnet 0xe58a3360	p9_error_init
+EXPORT_SYMBOL net/9p/9pnet 0xef1e8e0e	p9_client_version
+EXPORT_SYMBOL net/9p/9pnet 0xef7127b0	p9_idpool_put
+EXPORT_SYMBOL net/9p/9pnet 0xf20eeddd	p9_client_read
+EXPORT_SYMBOL net/9p/9pnet 0xf8b538a4	p9_client_create
+EXPORT_SYMBOL net/appletalk/appletalk 0x154d589d	atrtr_get_dev
+EXPORT_SYMBOL net/appletalk/appletalk 0x44e88d02	atalk_find_dev_addr
+EXPORT_SYMBOL net/appletalk/appletalk 0x71809b43	aarp_send_ddp
+EXPORT_SYMBOL net/appletalk/appletalk 0x9466bcd2	alloc_ltalkdev
+EXPORT_SYMBOL net/ax25/ax25 0x13d2a234	ax25_hard_header
+EXPORT_SYMBOL net/ax25/ax25 0x242852b9	ax25_uid_policy
+EXPORT_SYMBOL net/ax25/ax25 0x24f95e31	ax25_send_frame
+EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec	ax25_display_timer
+EXPORT_SYMBOL net/ax25/ax25 0x4502c65a	asc2ax
+EXPORT_SYMBOL net/ax25/ax25 0x498a3706	ax25_listen_release
+EXPORT_SYMBOL net/ax25/ax25 0x51be4b89	ax25_linkfail_register
+EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff	ax2asc
+EXPORT_SYMBOL net/ax25/ax25 0x564d9f14	ax25_findbyuid
+EXPORT_SYMBOL net/ax25/ax25 0x76f78fcb	ax25_header_ops
+EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26	ax25_protocol_release
+EXPORT_SYMBOL net/ax25/ax25 0x91a71241	ax25_rebuild_header
+EXPORT_SYMBOL net/ax25/ax25 0x9b46f22c	ax25_listen_register
+EXPORT_SYMBOL net/ax25/ax25 0xc1444946	ax25cmp
+EXPORT_SYMBOL net/ax25/ax25 0xc9ad7cfb	ax25_linkfail_release
+EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1	null_ax25_address
+EXPORT_SYMBOL net/ax25/ax25 0xf006161c	ax25_find_cb
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x03e5fc5b	hci_send_sco
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x061efd28	bt_sock_link
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x0c4336d5	hci_unregister_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x14133412	bt_sock_wait_state
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x149429ca	bt_sock_unlink
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x18cd6a3b	hci_conn_put_device
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x1eb45327	hci_free_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x213e51ce	hci_conn_hold_device
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x22d8295d	bt_sock_ioctl
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x3da95a37	hci_register_proto
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x6e2afbe0	hci_conn_change_link_key
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae	bt_err
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x70bb4be2	hci_register_cb
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x7542e842	hci_conn_security
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x76599cc0	hci_resume_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x76649f1a	hci_conn_check_link_mode
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x7aa2f770	hci_unregister_proto
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x8555dbd6	hci_connect
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x85bdf890	bt_accept_dequeue
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x9a1ed6f2	bt_sock_register
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x9acae68b	hci_register_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xa7a9f9e4	hci_unregister_cb
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xac25964b	bt_accept_enqueue
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xba1f4c5c	bt_sock_poll
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0	batostr
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551	baswap
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xd2fd9635	hci_suspend_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xdf1e7940	bt_accept_unlink
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xdf611c0f	hci_alloc_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xe023b3dc	hci_conn_switch_role
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xe39f6630	hci_send_acl
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xec9a1efa	hci_recv_fragment
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xecc6763d	hci_get_route
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xf13a5c55	bt_sock_recvmsg
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db	bt_sock_unregister
+EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88	l2cap_load
+EXPORT_SYMBOL net/bridge/bridge 0x24fbfeec	br_should_route_hook
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0x27a3fc4d	ebt_unregister_table
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xa224d79e	ebt_do_table
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xe3c54415	ebt_register_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x11dbc7b4	arpt_do_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x217ef65b	arpt_register_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0xfc4d50d5	arpt_unregister_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x4455324f	ipt_register_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x9bd24a22	ipt_do_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0xa6ed80f5	ipt_unregister_table
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x0820846c	nf_nat_protocol_register
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x452c737b	nf_nat_setup_info
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x6ae53aea	nf_nat_used_tuple
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x743ae458	nf_nat_protocol_unregister
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x7d7fe95f	nf_nat_mangle_tcp_packet
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xe25f7b95	nf_nat_mangle_udp_packet
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xee9d3380	nf_nat_follow_master
+EXPORT_SYMBOL net/ipv4/tunnel4 0xa1461ca6	xfrm4_tunnel_deregister
+EXPORT_SYMBOL net/ipv4/tunnel4 0xddbc189c	xfrm4_tunnel_register
+EXPORT_SYMBOL net/ipv6/ipv6 0x0508c19c	ndisc_send_skb
+EXPORT_SYMBOL net/ipv6/ipv6 0x0b0d888b	icmpv6_err_convert
+EXPORT_SYMBOL net/ipv6/ipv6 0x0e14abb1	xfrm6_prepare_output
+EXPORT_SYMBOL net/ipv6/ipv6 0x0e207d15	ipv6_setsockopt
+EXPORT_SYMBOL net/ipv6/ipv6 0x2933ff67	ndisc_build_skb
+EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5	icmpv6_statistics
+EXPORT_SYMBOL net/ipv6/ipv6 0x3055080b	xfrm6_input_addr
+EXPORT_SYMBOL net/ipv6/ipv6 0x3b4584ea	ipv6_chk_prefix
+EXPORT_SYMBOL net/ipv6/ipv6 0x3f912536	inet6_release
+EXPORT_SYMBOL net/ipv6/ipv6 0x4449d8ce	ip6_route_output
+EXPORT_SYMBOL net/ipv6/ipv6 0x450d145b	xfrm6_find_1stfragopt
+EXPORT_SYMBOL net/ipv6/ipv6 0x4cdb9b6d	inet6_del_protocol
+EXPORT_SYMBOL net/ipv6/ipv6 0x4d81e6f4	inet6_register_protosw
+EXPORT_SYMBOL net/ipv6/ipv6 0x529410ed	ipv6_dev_get_saddr
+EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0	unregister_inet6addr_notifier
+EXPORT_SYMBOL net/ipv6/ipv6 0x5941d4c6	xfrm6_rcv
+EXPORT_SYMBOL net/ipv6/ipv6 0x64d93cf8	icmpv6_send
+EXPORT_SYMBOL net/ipv6/ipv6 0x6ee22ebb	xfrm6_rcv_spi
+EXPORT_SYMBOL net/ipv6/ipv6 0x6fb1661e	nf_ip6_checksum
+EXPORT_SYMBOL net/ipv6/ipv6 0x7bed9b38	ipv6_push_nfrag_opts
+EXPORT_SYMBOL net/ipv6/ipv6 0x8ec99114	in6_dev_finish_destroy
+EXPORT_SYMBOL net/ipv6/ipv6 0x97174deb	ip6_route_me_harder
+EXPORT_SYMBOL net/ipv6/ipv6 0x9898c99d	inet6_getname
+EXPORT_SYMBOL net/ipv6/ipv6 0xa5aea02c	ipv6_chk_addr
+EXPORT_SYMBOL net/ipv6/ipv6 0xb0bcc0ee	ip6_xmit
+EXPORT_SYMBOL net/ipv6/ipv6 0xb778742b	ndisc_mc_map
+EXPORT_SYMBOL net/ipv6/ipv6 0xc596bcd7	inet6_unregister_protosw
+EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5	register_inet6addr_notifier
+EXPORT_SYMBOL net/ipv6/ipv6 0xd61601bf	ip6_frag_match
+EXPORT_SYMBOL net/ipv6/ipv6 0xd9d81193	inet6_add_protocol
+EXPORT_SYMBOL net/ipv6/ipv6 0xdff81261	rt6_lookup
+EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a	icmpv6msg_statistics
+EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd	__ipv6_isatap_ifid
+EXPORT_SYMBOL net/ipv6/ipv6 0xeb6b9cd6	ip6_frag_init
+EXPORT_SYMBOL net/ipv6/ipv6 0xebb4a688	inet6_ioctl
+EXPORT_SYMBOL net/ipv6/ipv6 0xf98651a3	ipv6_getsockopt
+EXPORT_SYMBOL net/ipv6/ipv6 0xfc896178	inet6_bind
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x01f62948	ip6t_unregister_table
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x178320e1	ipv6_find_hdr
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x1b646ea7	ip6t_register_table
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x3ea0e17f	ip6t_do_table
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33	ip6t_ext_hdr
+EXPORT_SYMBOL net/ipv6/tunnel6 0x45476187	xfrm6_tunnel_register
+EXPORT_SYMBOL net/ipv6/tunnel6 0x7129a3aa	xfrm6_tunnel_deregister
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2	xfrm6_tunnel_alloc_spi
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193	xfrm6_tunnel_free_spi
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1	xfrm6_tunnel_spi_lookup
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x10052f0e	ircomm_connect_response
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x5e6875b6	ircomm_data_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x638355ed	ircomm_close
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x70ee4078	ircomm_connect_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x931e94a0	ircomm_flow_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xa2bf9ebf	ircomm_control_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xc3a5e734	ircomm_disconnect_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xccd6d04b	ircomm_open
+EXPORT_SYMBOL net/irda/irda 0x01d1fcdb	hashbin_delete
+EXPORT_SYMBOL net/irda/irda 0x06a3ee58	irias_new_integer_value
+EXPORT_SYMBOL net/irda/irda 0x072e026f	irias_add_octseq_attrib
+EXPORT_SYMBOL net/irda/irda 0x07d3647c	irlmp_register_service
+EXPORT_SYMBOL net/irda/irda 0x08ded61f	irda_notify_init
+EXPORT_SYMBOL net/irda/irda 0x09c785d4	iriap_getvaluebyclass_request
+EXPORT_SYMBOL net/irda/irda 0x10f884a8	irlmp_connect_response
+EXPORT_SYMBOL net/irda/irda 0x17f179e2	irda_device_set_media_busy
+EXPORT_SYMBOL net/irda/irda 0x2036ad06	irda_param_insert
+EXPORT_SYMBOL net/irda/irda 0x22fc1b10	irttp_connect_request
+EXPORT_SYMBOL net/irda/irda 0x3462950f	hashbin_remove
+EXPORT_SYMBOL net/irda/irda 0x38a20e5b	irda_debug
+EXPORT_SYMBOL net/irda/irda 0x3df9c826	proc_irda
+EXPORT_SYMBOL net/irda/irda 0x42b497a1	iriap_open
+EXPORT_SYMBOL net/irda/irda 0x442a0aa0	irlmp_open_lsap
+EXPORT_SYMBOL net/irda/irda 0x448b8aaa	irda_qos_bits_to_value
+EXPORT_SYMBOL net/irda/irda 0x46c1c4a2	irlmp_unregister_service
+EXPORT_SYMBOL net/irda/irda 0x4e8c1741	irlmp_disconnect_request
+EXPORT_SYMBOL net/irda/irda 0x5b0bb102	irlap_close
+EXPORT_SYMBOL net/irda/irda 0x6758f8ac	irias_new_object
+EXPORT_SYMBOL net/irda/irda 0x68b7447c	hashbin_find
+EXPORT_SYMBOL net/irda/irda 0x6b043eba	irda_init_max_qos_capabilies
+EXPORT_SYMBOL net/irda/irda 0x6c3de872	irttp_udata_request
+EXPORT_SYMBOL net/irda/irda 0x6faa3a9a	irttp_connect_response
+EXPORT_SYMBOL net/irda/irda 0x7042bc54	irlmp_register_client
+EXPORT_SYMBOL net/irda/irda 0x747d6779	irias_delete_object
+EXPORT_SYMBOL net/irda/irda 0x7621e908	hashbin_insert
+EXPORT_SYMBOL net/irda/irda 0x76243bc9	irias_insert_object
+EXPORT_SYMBOL net/irda/irda 0x763e54a4	irlmp_unregister_client
+EXPORT_SYMBOL net/irda/irda 0x781e2db5	irias_find_object
+EXPORT_SYMBOL net/irda/irda 0x7957f728	irlmp_update_client
+EXPORT_SYMBOL net/irda/irda 0x7a57b6f3	hashbin_remove_this
+EXPORT_SYMBOL net/irda/irda 0x8f9b6500	async_unwrap_char
+EXPORT_SYMBOL net/irda/irda 0x91815586	irda_param_pack
+EXPORT_SYMBOL net/irda/irda 0x993ad14b	irda_param_extract_all
+EXPORT_SYMBOL net/irda/irda 0x9f7abe26	irttp_open_tsap
+EXPORT_SYMBOL net/irda/irda 0xa776c2ad	iriap_close
+EXPORT_SYMBOL net/irda/irda 0xb9394173	irias_delete_value
+EXPORT_SYMBOL net/irda/irda 0xbcd3ef13	irias_object_change_attribute
+EXPORT_SYMBOL net/irda/irda 0xbe40ace9	irlmp_discovery_request
+EXPORT_SYMBOL net/irda/irda 0xbf353d2e	irlmp_data_request
+EXPORT_SYMBOL net/irda/irda 0xbf9f79e2	irttp_data_request
+EXPORT_SYMBOL net/irda/irda 0xc14e9b6a	hashbin_get_next
+EXPORT_SYMBOL net/irda/irda 0xc5b1d8c3	irttp_disconnect_request
+EXPORT_SYMBOL net/irda/irda 0xcd41236c	hashbin_new
+EXPORT_SYMBOL net/irda/irda 0xd59fe8cd	alloc_irdadev
+EXPORT_SYMBOL net/irda/irda 0xd6deeaae	irda_setup_dma
+EXPORT_SYMBOL net/irda/irda 0xd7172ff4	hashbin_get_first
+EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4	hashbin_lock_find
+EXPORT_SYMBOL net/irda/irda 0xde4c6b3c	irlmp_service_to_hint
+EXPORT_SYMBOL net/irda/irda 0xe3637152	irlmp_connect_request
+EXPORT_SYMBOL net/irda/irda 0xe3f2c148	async_wrap_skb
+EXPORT_SYMBOL net/irda/irda 0xe5260e0e	irias_add_integer_attrib
+EXPORT_SYMBOL net/irda/irda 0xec41fe7f	irias_add_string_attrib
+EXPORT_SYMBOL net/irda/irda 0xedd521c2	irlmp_get_discoveries
+EXPORT_SYMBOL net/irda/irda 0xf0344b74	irlap_open
+EXPORT_SYMBOL net/irda/irda 0xf0aeed0c	irttp_flow_request
+EXPORT_SYMBOL net/irda/irda 0xf3b21cf9	irttp_close_tsap
+EXPORT_SYMBOL net/irda/irda 0xf76a7ab6	irlmp_close_lsap
+EXPORT_SYMBOL net/irda/irda 0xfd8725d4	irttp_dup
+EXPORT_SYMBOL net/lapb/lapb 0x24aa4eef	lapb_getparms
+EXPORT_SYMBOL net/lapb/lapb 0x3d2d64d2	lapb_disconnect_request
+EXPORT_SYMBOL net/lapb/lapb 0x61262c74	lapb_unregister
+EXPORT_SYMBOL net/lapb/lapb 0x845d3fc1	lapb_setparms
+EXPORT_SYMBOL net/lapb/lapb 0xc4d7b964	lapb_data_received
+EXPORT_SYMBOL net/lapb/lapb 0xcfd7c2ae	lapb_connect_request
+EXPORT_SYMBOL net/lapb/lapb 0xe58b3c50	lapb_data_request
+EXPORT_SYMBOL net/lapb/lapb 0xfcb325e5	lapb_register
+EXPORT_SYMBOL net/mac80211/mac80211 0x0be3d7a1	ieee80211_ctstoself_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x10c8145c	ieee80211_get_buffered_bc
+EXPORT_SYMBOL net/mac80211/mac80211 0x17e3523c	ieee80211_wake_queues
+EXPORT_SYMBOL net/mac80211/mac80211 0x26418432	ieee80211_alloc_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x2c036994	wiphy_to_ieee80211_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x365b88af	ieee80211_queue_work
+EXPORT_SYMBOL net/mac80211/mac80211 0x3b8c09dd	ieee80211_unregister_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x3d74106e	ieee80211_rts_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x4f508242	__ieee80211_get_tx_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0x52301d83	ieee80211_free_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x53ba0996	ieee80211_scan_completed
+EXPORT_SYMBOL net/mac80211/mac80211 0x5e675a0b	ieee80211_ctstoself_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0x5fe80476	ieee80211_queue_delayed_work
+EXPORT_SYMBOL net/mac80211/mac80211 0x73c4b330	ieee80211_start_tx_ba_cb
+EXPORT_SYMBOL net/mac80211/mac80211 0x782e9caf	__ieee80211_get_radio_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0x791fb0bb	ieee80211_queue_stopped
+EXPORT_SYMBOL net/mac80211/mac80211 0x7e593818	ieee80211_rx
+EXPORT_SYMBOL net/mac80211/mac80211 0x82767693	ieee80211_rx_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0x88117eff	ieee80211_get_tkip_key
+EXPORT_SYMBOL net/mac80211/mac80211 0x8dfca079	ieee80211_beacon_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x8f6e78a3	ieee80211_find_sta
+EXPORT_SYMBOL net/mac80211/mac80211 0x92204fb7	ieee80211_wake_queue
+EXPORT_SYMBOL net/mac80211/mac80211 0x99484521	ieee80211_restart_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0xa0e68532	__ieee80211_get_rx_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0xa67c386e	ieee80211_start_tx_ba_cb_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0xabf80c5f	ieee80211_stop_tx_ba_session
+EXPORT_SYMBOL net/mac80211/mac80211 0xc5d9b073	ieee80211_stop_queue
+EXPORT_SYMBOL net/mac80211/mac80211 0xcbeb0d1d	ieee80211_start_tx_ba_session
+EXPORT_SYMBOL net/mac80211/mac80211 0xceeffdb6	ieee80211_stop_tx_ba_cb_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0xd15da69d	ieee80211_tx_status_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0xd3df91bc	ieee80211_stop_queues
+EXPORT_SYMBOL net/mac80211/mac80211 0xd5619e7b	ieee80211_rts_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0xd5828491	ieee80211_rate_control_unregister
+EXPORT_SYMBOL net/mac80211/mac80211 0xd72068d3	rate_control_send_low
+EXPORT_SYMBOL net/mac80211/mac80211 0xd9da4ddc	ieee80211_stop_tx_ba_cb
+EXPORT_SYMBOL net/mac80211/mac80211 0xe8abe42d	ieee80211_beacon_loss
+EXPORT_SYMBOL net/mac80211/mac80211 0xebd3b1ba	ieee80211_tx_status
+EXPORT_SYMBOL net/mac80211/mac80211 0xf1d49493	__ieee80211_get_assoc_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0xf2246716	ieee80211_generic_frame_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0xf25450a3	ieee80211_register_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0xfea85474	ieee80211_rate_control_register
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x080b288a	unregister_ip_vs_scheduler
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x27dc8050	ip_vs_skb_replace
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x2fd1f7ed	ip_vs_conn_in_get
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x5986fd2c	ip_vs_conn_out_get
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x79c87f2d	register_ip_vs_app_inc
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x91f75d54	ip_vs_conn_new
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x9c0cce11	register_ip_vs_scheduler
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xa0e6e5fc	register_ip_vs_app
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xa1dbc2d8	ip_vs_proto_name
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xad74756a	unregister_ip_vs_app
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xcef5b182	ip_vs_tcp_conn_listen
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xf4ddb9b5	ip_vs_conn_put
+EXPORT_SYMBOL net/netfilter/nf_conntrack 0x158257c3	__nf_ct_ext_destroy
+EXPORT_SYMBOL net/netfilter/nf_conntrack 0xc0c5133f	__nf_ct_ext_add
+EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x07713ecd	nf_ct_gre_keymap_flush
+EXPORT_SYMBOL net/netfilter/x_tables 0x0c286e70	xt_unregister_match
+EXPORT_SYMBOL net/netfilter/x_tables 0x16a5e826	xt_free_table_info
+EXPORT_SYMBOL net/netfilter/x_tables 0x2f047aa0	xt_find_match
+EXPORT_SYMBOL net/netfilter/x_tables 0x341712ef	xt_find_target
+EXPORT_SYMBOL net/netfilter/x_tables 0x3db1fe03	xt_unregister_target
+EXPORT_SYMBOL net/netfilter/x_tables 0x49825039	xt_register_targets
+EXPORT_SYMBOL net/netfilter/x_tables 0x665db725	xt_register_matches
+EXPORT_SYMBOL net/netfilter/x_tables 0x76cb3883	xt_unregister_targets
+EXPORT_SYMBOL net/netfilter/x_tables 0x8239d876	xt_register_target
+EXPORT_SYMBOL net/netfilter/x_tables 0x85a98d2e	xt_register_match
+EXPORT_SYMBOL net/netfilter/x_tables 0xc3ff5dff	xt_alloc_table_info
+EXPORT_SYMBOL net/netfilter/x_tables 0xfb435c4a	xt_unregister_matches
+EXPORT_SYMBOL net/rfkill/rfkill 0x04ac4d1f	rfkill_set_hw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0x0f9f033b	rfkill_pause_polling
+EXPORT_SYMBOL net/rfkill/rfkill 0x383edc9e	rfkill_init_sw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0x50321299	rfkill_set_sw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0x64e32984	rfkill_unregister
+EXPORT_SYMBOL net/rfkill/rfkill 0x6d33d00b	rfkill_register
+EXPORT_SYMBOL net/rfkill/rfkill 0x7745f555	rfkill_destroy
+EXPORT_SYMBOL net/rfkill/rfkill 0x8147c47d	rfkill_set_states
+EXPORT_SYMBOL net/rfkill/rfkill 0x9fc4f7eb	rfkill_set_led_trigger_name
+EXPORT_SYMBOL net/rfkill/rfkill 0xa050005f	rfkill_alloc
+EXPORT_SYMBOL net/rfkill/rfkill 0xa78c78ae	rfkill_resume_polling
+EXPORT_SYMBOL net/rfkill/rfkill 0xa90ba0ca	rfkill_blocked
+EXPORT_SYMBOL net/rfkill/rfkill 0xb64cfe7d	rfkill_get_led_trigger_name
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x007002ce	rxrpc_kernel_data_delivered
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x01aa11f9	rxrpc_kernel_get_abort_code
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x0bc31b9e	rxrpc_kernel_reject_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x1210f57c	rxrpc_kernel_abort_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x463d5eaa	rxrpc_kernel_intercept_rx_messages
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x5b8403cd	rxrpc_kernel_send_data
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x709d3299	rxrpc_kernel_begin_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x80ed459b	rxrpc_kernel_is_data_last
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x930fa21a	rxrpc_get_null_key
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x94a5e594	rxrpc_kernel_accept_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xa59f0ea4	rxrpc_kernel_get_error_number
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xcd95db25	rxrpc_kernel_end_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xd20cc867	rxrpc_kernel_free_skb
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xd3427fe0	key_type_rxrpc
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xdae7a8f3	rxrpc_get_server_data_key
+EXPORT_SYMBOL net/sunrpc/sunrpc 0x3f2bfb88	svc_pool_stats_open
+EXPORT_SYMBOL net/tipc/tipc 0x08acf310	tipc_available_nodes
+EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd	tipc_isconnected
+EXPORT_SYMBOL net/tipc/tipc 0x1472b270	tipc_disconnect
+EXPORT_SYMBOL net/tipc/tipc 0x1479cb03	tipc_deleteport
+EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde	tipc_set_portunreliable
+EXPORT_SYMBOL net/tipc/tipc 0x16f27683	tipc_block_bearer
+EXPORT_SYMBOL net/tipc/tipc 0x1f94217c	tipc_recv_msg
+EXPORT_SYMBOL net/tipc/tipc 0x259b74f9	tipc_acknowledge
+EXPORT_SYMBOL net/tipc/tipc 0x27d8bb58	tipc_send2port
+EXPORT_SYMBOL net/tipc/tipc 0x2cefa201	tipc_createport
+EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9	tipc_detach
+EXPORT_SYMBOL net/tipc/tipc 0x3712e340	tipc_portunreliable
+EXPORT_SYMBOL net/tipc/tipc 0x3976041f	tipc_set_portimportance
+EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6	tipc_portimportance
+EXPORT_SYMBOL net/tipc/tipc 0x4b6c40cc	tipc_send_buf
+EXPORT_SYMBOL net/tipc/tipc 0x4ba3cfc8	tipc_send2name
+EXPORT_SYMBOL net/tipc/tipc 0x538b228a	tipc_withdraw
+EXPORT_SYMBOL net/tipc/tipc 0x5637ed44	tipc_get_mode
+EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1	tipc_continue
+EXPORT_SYMBOL net/tipc/tipc 0x5be7e993	tipc_forward_buf2port
+EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c	tipc_ref_valid
+EXPORT_SYMBOL net/tipc/tipc 0x62a681a3	tipc_portunreturnable
+EXPORT_SYMBOL net/tipc/tipc 0x64357d3c	tipc_multicast
+EXPORT_SYMBOL net/tipc/tipc 0x8001e3d7	tipc_forward2port
+EXPORT_SYMBOL net/tipc/tipc 0x824ab58c	tipc_send_buf2port
+EXPORT_SYMBOL net/tipc/tipc 0x88b73627	tipc_get_addr
+EXPORT_SYMBOL net/tipc/tipc 0x9c45558e	tipc_enable_bearer
+EXPORT_SYMBOL net/tipc/tipc 0xa36e3060	tipc_createport_raw
+EXPORT_SYMBOL net/tipc/tipc 0xa936a24b	tipc_get_port
+EXPORT_SYMBOL net/tipc/tipc 0xadd203d0	tipc_connect2port
+EXPORT_SYMBOL net/tipc/tipc 0xae0103c3	tipc_shutdown
+EXPORT_SYMBOL net/tipc/tipc 0xb01ffc2c	tipc_forward2name
+EXPORT_SYMBOL net/tipc/tipc 0xb35b672c	tipc_publish
+EXPORT_SYMBOL net/tipc/tipc 0xbb2b2504	tipc_send
+EXPORT_SYMBOL net/tipc/tipc 0xc6ab123f	tipc_reject_msg
+EXPORT_SYMBOL net/tipc/tipc 0xcec8514a	tipc_set_portunreturnable
+EXPORT_SYMBOL net/tipc/tipc 0xd3578706	tipc_forward_buf2name
+EXPORT_SYMBOL net/tipc/tipc 0xd44731e5	tipc_ownidentity
+EXPORT_SYMBOL net/tipc/tipc 0xd8ed45eb	tipc_register_media
+EXPORT_SYMBOL net/tipc/tipc 0xd9eac7b0	tipc_send_buf2name
+EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f	tipc_attach
+EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc	tipc_peer
+EXPORT_SYMBOL net/tipc/tipc 0xe7aece47	tipc_ispublished
+EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3	tipc_get_handle
+EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef	tipc_disable_bearer
+EXPORT_SYMBOL net/tipc/tipc 0xf5bc0d37	tipc_send_buf_fast
+EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1	unregister_wan_device
+EXPORT_SYMBOL net/wanrouter/wanrouter 0x6137e3a8	register_wan_device
+EXPORT_SYMBOL net/wireless/cfg80211 0x024ffe2c	wiphy_unregister
+EXPORT_SYMBOL net/wireless/cfg80211 0x03866065	cfg80211_unlink_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a	ieee80211_radiotap_iterator_init
+EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd	ieee80211_frequency_to_channel
+EXPORT_SYMBOL net/wireless/cfg80211 0x1879fcbd	bridge_tunnel_header
+EXPORT_SYMBOL net/wireless/cfg80211 0x1d3f9a33	ieee80211_data_from_8023
+EXPORT_SYMBOL net/wireless/cfg80211 0x2110da33	wiphy_register
+EXPORT_SYMBOL net/wireless/cfg80211 0x2182f890	cfg80211_classify8021d
+EXPORT_SYMBOL net/wireless/cfg80211 0x2a22b097	cfg80211_inform_bss_frame
+EXPORT_SYMBOL net/wireless/cfg80211 0x30f6b905	cfg80211_disconnected
+EXPORT_SYMBOL net/wireless/cfg80211 0x33271643	__ieee80211_get_channel
+EXPORT_SYMBOL net/wireless/cfg80211 0x3361695d	wiphy_rfkill_set_hw_state
+EXPORT_SYMBOL net/wireless/cfg80211 0x37ac8d05	ieee80211_get_response_rate
+EXPORT_SYMBOL net/wireless/cfg80211 0x3e418364	cfg80211_send_disassoc
+EXPORT_SYMBOL net/wireless/cfg80211 0x5923fe55	cfg80211_get_mesh
+EXPORT_SYMBOL net/wireless/cfg80211 0x5d5933c7	regulatory_hint
+EXPORT_SYMBOL net/wireless/cfg80211 0x629e0fcf	cfg80211_send_deauth
+EXPORT_SYMBOL net/wireless/cfg80211 0x69b18f43	rfc1042_header
+EXPORT_SYMBOL net/wireless/cfg80211 0x6b1201f7	cfg80211_connect_result
+EXPORT_SYMBOL net/wireless/cfg80211 0x799e19ac	ieee80211_get_hdrlen_from_skb
+EXPORT_SYMBOL net/wireless/cfg80211 0x7fc6e084	wiphy_rfkill_start_polling
+EXPORT_SYMBOL net/wireless/cfg80211 0x8c35d732	ieee80211_hdrlen
+EXPORT_SYMBOL net/wireless/cfg80211 0x90eb5e02	cfg80211_put_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0x96551c97	cfg80211_ibss_joined
+EXPORT_SYMBOL net/wireless/cfg80211 0x9a7e8922	cfg80211_inform_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0x9b5e6ae0	wiphy_rfkill_stop_polling
+EXPORT_SYMBOL net/wireless/cfg80211 0x9b77d5a5	cfg80211_send_assoc_timeout
+EXPORT_SYMBOL net/wireless/cfg80211 0x9d806996	cfg80211_scan_done
+EXPORT_SYMBOL net/wireless/cfg80211 0xb5af6432	ieee80211_data_to_8023
+EXPORT_SYMBOL net/wireless/cfg80211 0xb69e3cad	freq_reg_info
+EXPORT_SYMBOL net/wireless/cfg80211 0xb78708db	cfg80211_send_rx_auth
+EXPORT_SYMBOL net/wireless/cfg80211 0xb88d5bed	cfg80211_michael_mic_failure
+EXPORT_SYMBOL net/wireless/cfg80211 0xbf58c3fc	cfg80211_send_auth_timeout
+EXPORT_SYMBOL net/wireless/cfg80211 0xc0d81bf6	wiphy_free
+EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5	ieee80211_radiotap_iterator_next
+EXPORT_SYMBOL net/wireless/cfg80211 0xc92a1d4c	wiphy_new
+EXPORT_SYMBOL net/wireless/cfg80211 0xc931a03d	ieee80211_bss_get_ie
+EXPORT_SYMBOL net/wireless/cfg80211 0xcad66075	cfg80211_roamed
+EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3	ieee80211_channel_to_frequency
+EXPORT_SYMBOL net/wireless/cfg80211 0xe3a55fd5	cfg80211_get_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0xeac3338b	wiphy_apply_custom_regulatory
+EXPORT_SYMBOL net/wireless/cfg80211 0xfb469da2	cfg80211_send_rx_assoc
+EXPORT_SYMBOL sound/ac97_bus 0x1e4fa261	ac97_bus_type
+EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0x19b67b5e	snd_mixer_oss_ioctl_card
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc	snd_seq_kernel_client_ctl
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161	snd_seq_kernel_client_dispatch
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x4c48ebdd	snd_seq_create_kernel_client
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x4eaf1281	snd_seq_kernel_client_enqueue_blocking
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038	snd_seq_delete_kernel_client
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x6da537e5	snd_seq_kernel_client_write_poll
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329	snd_seq_expand_var_event
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb	snd_seq_event_port_detach
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x89947013	snd_use_lock_sync_helper
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0	snd_seq_set_queue_tempo
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be	snd_seq_kernel_client_enqueue
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xdf731789	snd_seq_event_port_attach
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d	snd_seq_dump_var_event
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235	snd_seq_autoload_unlock
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x5c362c3d	snd_seq_device_register_driver
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0	snd_seq_device_load_drivers
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x672a29d0	snd_seq_device_new
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2	snd_seq_autoload_lock
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29	snd_seq_device_unregister_driver
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972	snd_midi_channel_alloc_set
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07	snd_midi_channel_set_clear
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c	snd_midi_channel_free_set
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3	snd_midi_process_event
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809	snd_midi_event_decode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518	snd_midi_event_reset_decode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a	snd_midi_event_encode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811	snd_midi_event_reset_encode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b	snd_midi_event_free
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d	snd_midi_event_new
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a	snd_midi_event_no_status
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7	snd_midi_event_encode_byte
+EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0xbe969f6d	snd_virmidi_new
+EXPORT_SYMBOL sound/core/snd 0x0b0468fe	snd_card_file_remove
+EXPORT_SYMBOL sound/core/snd 0x16172ffd	snd_info_create_module_entry
+EXPORT_SYMBOL sound/core/snd 0x1697a4a1	_snd_ctl_add_slave
+EXPORT_SYMBOL sound/core/snd 0x18e1683f	snd_dma_program
+EXPORT_SYMBOL sound/core/snd 0x191e88cf	snd_dma_pointer
+EXPORT_SYMBOL sound/core/snd 0x198788b4	snd_lookup_oss_minor_data
+EXPORT_SYMBOL sound/core/snd 0x19b2be34	snd_component_add
+EXPORT_SYMBOL sound/core/snd 0x24a94b26	snd_info_get_line
+EXPORT_SYMBOL sound/core/snd 0x25cf899d	snd_ctl_make_virtual_master
+EXPORT_SYMBOL sound/core/snd 0x2ae3deaa	release_and_free_resource
+EXPORT_SYMBOL sound/core/snd 0x2aed64e3	snd_ctl_find_id
+EXPORT_SYMBOL sound/core/snd 0x2b4211d8	snd_card_create
+EXPORT_SYMBOL sound/core/snd 0x31af69db	snd_cards
+EXPORT_SYMBOL sound/core/snd 0x3971b4df	snd_ecards_limit
+EXPORT_SYMBOL sound/core/snd 0x39bd2622	snd_pci_quirk_lookup
+EXPORT_SYMBOL sound/core/snd 0x3f4cfbfb	snd_info_create_card_entry
+EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0	snd_request_card
+EXPORT_SYMBOL sound/core/snd 0x58ac4ac2	snd_ctl_notify
+EXPORT_SYMBOL sound/core/snd 0x602c96f0	copy_to_user_fromio
+EXPORT_SYMBOL sound/core/snd 0x62dfd03d	snd_ctl_new1
+EXPORT_SYMBOL sound/core/snd 0x639a8977	snd_mixer_oss_notify_callback
+EXPORT_SYMBOL sound/core/snd 0x6644065d	snd_jack_new
+EXPORT_SYMBOL sound/core/snd 0x70a1d482	snd_register_oss_device
+EXPORT_SYMBOL sound/core/snd 0x70c15ac1	snd_dma_disable
+EXPORT_SYMBOL sound/core/snd 0x7d5add63	snd_ctl_unregister_ioctl
+EXPORT_SYMBOL sound/core/snd 0x84ad8097	snd_card_set_id
+EXPORT_SYMBOL sound/core/snd 0x89d4c963	snd_power_wait
+EXPORT_SYMBOL sound/core/snd 0x89d9a4df	snd_ctl_find_numid
+EXPORT_SYMBOL sound/core/snd 0x8ce059fb	snd_register_device_for_dev
+EXPORT_SYMBOL sound/core/snd 0x8ddbf150	snd_ctl_boolean_stereo_info
+EXPORT_SYMBOL sound/core/snd 0x8df3789f	snd_oss_info_register
+EXPORT_SYMBOL sound/core/snd 0x8f595b11	snd_major
+EXPORT_SYMBOL sound/core/snd 0x91c644eb	snd_ctl_boolean_mono_info
+EXPORT_SYMBOL sound/core/snd 0x927b0393	snd_card_free_when_closed
+EXPORT_SYMBOL sound/core/snd 0x97feaea0	snd_ctl_remove
+EXPORT_SYMBOL sound/core/snd 0x9910b73c	snd_seq_root
+EXPORT_SYMBOL sound/core/snd 0x9e6d79f8	snd_info_get_str
+EXPORT_SYMBOL sound/core/snd 0xa189e240	snd_card_free
+EXPORT_SYMBOL sound/core/snd 0xb2272426	snd_jack_set_parent
+EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a	snd_lookup_minor_data
+EXPORT_SYMBOL sound/core/snd 0xb2e5b6fe	snd_device_free
+EXPORT_SYMBOL sound/core/snd 0xb4756d67	snd_card_register
+EXPORT_SYMBOL sound/core/snd 0xb49c2647	snd_card_proc_new
+EXPORT_SYMBOL sound/core/snd 0xb5ba2b3a	snd_card_file_add
+EXPORT_SYMBOL sound/core/snd 0xc0a8bddb	snd_ctl_remove_id
+EXPORT_SYMBOL sound/core/snd 0xc76b33d3	snd_card_disconnect
+EXPORT_SYMBOL sound/core/snd 0xcbb2734a	snd_ctl_register_ioctl
+EXPORT_SYMBOL sound/core/snd 0xce3ca308	copy_from_user_toio
+EXPORT_SYMBOL sound/core/snd 0xceca0929	snd_device_new
+EXPORT_SYMBOL sound/core/snd 0xd06b8f89	snd_info_register
+EXPORT_SYMBOL sound/core/snd 0xd3a5b3ae	snd_info_free_entry
+EXPORT_SYMBOL sound/core/snd 0xd672ba2f	snd_ctl_rename_id
+EXPORT_SYMBOL sound/core/snd 0xddddd576	snd_unregister_device
+EXPORT_SYMBOL sound/core/snd 0xe20c9214	snd_iprintf
+EXPORT_SYMBOL sound/core/snd 0xe586e1c4	snd_ctl_add
+EXPORT_SYMBOL sound/core/snd 0xe5e4ec0a	snd_ctl_free_one
+EXPORT_SYMBOL sound/core/snd 0xe7f219e0	snd_unregister_oss_device
+EXPORT_SYMBOL sound/core/snd 0xe84f77e7	snd_device_register
+EXPORT_SYMBOL sound/core/snd 0xee8f82b3	snd_add_device_sysfs_file
+EXPORT_SYMBOL sound/core/snd 0xf96477fd	snd_jack_report
+EXPORT_SYMBOL sound/core/snd-hwdep 0x965cfb09	snd_hwdep_new
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x3b91f3af	snd_free_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x63a64925	snd_dma_get_reserved_buf
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x9c12a4d0	snd_dma_alloc_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xa49596dd	snd_dma_alloc_pages_fallback
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xade88e76	snd_malloc_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xb9ed1bf8	snd_dma_free_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xbb6eb79a	snd_dma_reserve_buf
+EXPORT_SYMBOL sound/core/snd-pcm 0x0283dfe3	_snd_pcm_hw_params_any
+EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566	snd_interval_refine
+EXPORT_SYMBOL sound/core/snd-pcm 0x089d816d	snd_pcm_hw_constraint_ratnums
+EXPORT_SYMBOL sound/core/snd-pcm 0x0c66986a	snd_pcm_lib_preallocate_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0x17813754	snd_pcm_lib_preallocate_pages_for_all
+EXPORT_SYMBOL sound/core/snd-pcm 0x193db66e	snd_pcm_lib_writev
+EXPORT_SYMBOL sound/core/snd-pcm 0x1a7fe93d	snd_pcm_hw_rule_add
+EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b	snd_pcm_format_signed
+EXPORT_SYMBOL sound/core/snd-pcm 0x29980811	snd_pcm_lib_readv
+EXPORT_SYMBOL sound/core/snd-pcm 0x29a0ac31	snd_pcm_hw_constraint_pow2
+EXPORT_SYMBOL sound/core/snd-pcm 0x2bb8612d	snd_pcm_lib_mmap_iomem
+EXPORT_SYMBOL sound/core/snd-pcm 0x361545ef	snd_pcm_hw_param_first
+EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc	snd_pcm_format_little_endian
+EXPORT_SYMBOL sound/core/snd-pcm 0x387022f0	snd_pcm_period_elapsed
+EXPORT_SYMBOL sound/core/snd-pcm 0x39bf9301	_snd_pcm_hw_param_setempty
+EXPORT_SYMBOL sound/core/snd-pcm 0x40f553a0	snd_pcm_hw_constraint_minmax
+EXPORT_SYMBOL sound/core/snd-pcm 0x433482ac	snd_pcm_mmap_data
+EXPORT_SYMBOL sound/core/snd-pcm 0x4d9b6d35	snd_pcm_format_size
+EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b	snd_pcm_format_big_endian
+EXPORT_SYMBOL sound/core/snd-pcm 0x52a95a90	snd_pcm_hw_constraint_step
+EXPORT_SYMBOL sound/core/snd-pcm 0x52e3e4a5	snd_pcm_hw_param_value
+EXPORT_SYMBOL sound/core/snd-pcm 0x52f5295b	snd_pcm_hw_constraint_list
+EXPORT_SYMBOL sound/core/snd-pcm 0x544b6a77	snd_pcm_set_ops
+EXPORT_SYMBOL sound/core/snd-pcm 0x5c8f544d	snd_pcm_new
+EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920	snd_pcm_format_set_silence
+EXPORT_SYMBOL sound/core/snd-pcm 0x610d10db	snd_pcm_hw_constraint_integer
+EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603	snd_pcm_format_silence_64
+EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153	snd_pcm_format_physical_width
+EXPORT_SYMBOL sound/core/snd-pcm 0x69604cf5	snd_pcm_sgbuf_ops_page
+EXPORT_SYMBOL sound/core/snd-pcm 0x6b5d312a	snd_pcm_lib_preallocate_free_for_all
+EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8	snd_pcm_format_linear
+EXPORT_SYMBOL sound/core/snd-pcm 0x715e3b03	snd_pcm_notify
+EXPORT_SYMBOL sound/core/snd-pcm 0x7aa4be2a	snd_pcm_lib_free_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0x7bac8b8f	snd_pcm_kernel_ioctl
+EXPORT_SYMBOL sound/core/snd-pcm 0x7c753ccb	snd_pcm_lib_ioctl
+EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc	snd_pcm_link_rwlock
+EXPORT_SYMBOL sound/core/snd-pcm 0x8d1530e6	snd_pcm_sgbuf_get_chunk_size
+EXPORT_SYMBOL sound/core/snd-pcm 0x9f139abe	snd_pcm_suspend_all
+EXPORT_SYMBOL sound/core/snd-pcm 0xa1132668	snd_pcm_new_stream
+EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028	snd_pcm_format_unsigned
+EXPORT_SYMBOL sound/core/snd-pcm 0xa99eca79	snd_pcm_lib_write
+EXPORT_SYMBOL sound/core/snd-pcm 0xb36d23ab	snd_pcm_hw_constraint_ratdens
+EXPORT_SYMBOL sound/core/snd-pcm 0xb42139d5	snd_pcm_hw_constraint_msbits
+EXPORT_SYMBOL sound/core/snd-pcm 0xb645aa60	snd_pcm_hw_param_last
+EXPORT_SYMBOL sound/core/snd-pcm 0xb6a14523	snd_pcm_open_substream
+EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4	snd_pcm_rate_to_rate_bit
+EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8	snd_interval_list
+EXPORT_SYMBOL sound/core/snd-pcm 0xd1531a09	snd_pcm_lib_read
+EXPORT_SYMBOL sound/core/snd-pcm 0xde635cda	snd_pcm_limit_hw_rates
+EXPORT_SYMBOL sound/core/snd-pcm 0xe413170c	snd_pcm_stop
+EXPORT_SYMBOL sound/core/snd-pcm 0xe4654956	snd_pcm_lib_malloc_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0xe4b28c3c	snd_pcm_hw_refine
+EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336	snd_pcm_format_width
+EXPORT_SYMBOL sound/core/snd-pcm 0xea43e4fc	snd_pcm_set_sync
+EXPORT_SYMBOL sound/core/snd-pcm 0xece54cd2	snd_pcm_suspend
+EXPORT_SYMBOL sound/core/snd-pcm 0xed584c55	snd_pcm_release_substream
+EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152	snd_interval_ratnum
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x0395376c	snd_rawmidi_new
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x10bae19d	snd_rawmidi_drain_input
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x254a5ea3	snd_rawmidi_kernel_release
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x45ae946d	snd_rawmidi_kernel_open
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x4b9cbadb	snd_rawmidi_drain_output
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x53531785	snd_rawmidi_transmit_ack
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x6fb5326a	snd_rawmidi_output_params
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x76a1a6ff	snd_rawmidi_receive
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x7e253ed7	snd_rawmidi_kernel_write
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x8ced7979	snd_rawmidi_transmit_empty
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x91affae1	snd_rawmidi_transmit
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x95e0a2a8	snd_rawmidi_transmit_peek
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xb5d67fdc	snd_rawmidi_kernel_read
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xb69cb8ed	snd_rawmidi_info_select
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xcfa86a8f	snd_rawmidi_set_ops
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xd008193f	snd_rawmidi_input_params
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xeb23a226	snd_rawmidi_drop_output
+EXPORT_SYMBOL sound/core/snd-timer 0x153ba825	snd_timer_open
+EXPORT_SYMBOL sound/core/snd-timer 0x25ba5ab0	snd_timer_start
+EXPORT_SYMBOL sound/core/snd-timer 0x39d73f35	snd_timer_interrupt
+EXPORT_SYMBOL sound/core/snd-timer 0x3d710951	snd_timer_continue
+EXPORT_SYMBOL sound/core/snd-timer 0x4bcba1a8	snd_timer_global_free
+EXPORT_SYMBOL sound/core/snd-timer 0x7c306dcd	snd_timer_notify
+EXPORT_SYMBOL sound/core/snd-timer 0x7eaf9785	snd_timer_close
+EXPORT_SYMBOL sound/core/snd-timer 0x94180a60	snd_timer_new
+EXPORT_SYMBOL sound/core/snd-timer 0xb3b25552	snd_timer_stop
+EXPORT_SYMBOL sound/core/snd-timer 0xc957cc07	snd_timer_resolution
+EXPORT_SYMBOL sound/core/snd-timer 0xca674115	snd_timer_global_new
+EXPORT_SYMBOL sound/core/snd-timer 0xce115312	snd_timer_pause
+EXPORT_SYMBOL sound/core/snd-timer 0xff10beb7	snd_timer_global_register
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x4bbb7f27	snd_mpu401_uart_interrupt_tx
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x86bee77a	snd_mpu401_uart_new
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xc43a3940	snd_mpu401_uart_interrupt
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19	snd_opl3_regmap
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x15e348c9	snd_opl3_reset
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x2fa182b3	snd_opl3_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x31b3d838	snd_opl3_init
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x3c8a580e	snd_opl3_hwdep_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x4e35e1f6	snd_opl3_load_patch
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x4f88d091	snd_opl3_timer_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x543fe890	snd_opl3_interrupt
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x57410c10	snd_opl3_find_patch
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xbeedf124	snd_opl3_create
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x019d0d3e	snd_vx_load_boot_image
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x0909a54a	snd_vx_dsp_boot
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1f0e2147	snd_vx_create
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x462b1c71	snd_vx_check_reg_bit
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x5c875552	snd_vx_dsp_load
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x88a53f34	snd_vx_free_firmware
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x958e0971	snd_vx_setup_firmware
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x99b88ede	snd_vx_irq_handler
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xbd8a77e1	snd_vx_resume
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xcc50b725	snd_vx_suspend
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x1d40dc5d	snd_ak4114_check_rate_and_errors
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x311d5697	snd_ak4114_reinit
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xa2b60308	snd_ak4114_reg_write
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xaa90305e	snd_ak4114_external_rate
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xbd005687	snd_ak4114_create
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0xbea84827	snd_ak4114_build
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x2cbc499e	snd_ak4117_reg_write
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x40a5a36b	snd_ak4117_build
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x4e295f08	snd_ak4117_create
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x5a9c7b5a	snd_ak4117_reinit
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xdbca6af4	snd_ak4117_check_rate_and_errors
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xfada6fce	snd_ak4117_external_rate
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x44cc261d	snd_akm4xxx_build_controls
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x8a131a60	snd_akm4xxx_init
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xbb7d466d	snd_akm4xxx_reset
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xbcc08000	snd_akm4xxx_write
+EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x71f2c981	snd_pt2258_reset
+EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x8a7be343	snd_pt2258_build_controls
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x2d0f89ba	snd_cs8427_create
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x68bd869c	snd_cs8427_iec958_active
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x77a785f2	snd_cs8427_iec958_pcm
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x97b6a148	snd_cs8427_reg_write
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd870acf9	snd_cs8427_iec958_build
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x0dcd3510	snd_i2c_bus_create
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x340f6f35	snd_i2c_readbytes
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x62a6d2d4	snd_i2c_sendbytes
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x81e455c9	snd_i2c_probeaddr
+EXPORT_SYMBOL sound/i2c/snd-i2c 0xa5cde3c4	snd_i2c_device_free
+EXPORT_SYMBOL sound/i2c/snd-i2c 0xac095696	snd_i2c_device_create
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x07b2191e	snd_sbmixer_new
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x1287b8e1	snd_sbdsp_reset
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x20b6452b	snd_sbmixer_resume
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x62d1fa0e	snd_sbdsp_get_byte
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x6a985a67	snd_sbdsp_command
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x9fdc677d	snd_sbmixer_suspend
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xaa58aa32	snd_sbdsp_create
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xb7c7dbc2	snd_sbmixer_read
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xcbafb53d	snd_sbmixer_add_ctl
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xdd062773	snd_sbmixer_write
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x39a44d80	snd_sb16dsp_pcm
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x8de6d508	snd_sb16dsp_get_pcm_ops
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x93035d17	snd_sb16dsp_configure
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xc57f5b54	snd_sb16dsp_interrupt
+EXPORT_SYMBOL sound/oss/ad1848 0x26c427ee	ad1848_detect
+EXPORT_SYMBOL sound/oss/ad1848 0x538043d3	attach_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0x55262c70	probe_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0x996ea529	ad1848_init
+EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62	ad1848_unload
+EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148	unload_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67	ad1848_control
+EXPORT_SYMBOL sound/oss/mpu401 0x5febf284	unload_mpu401
+EXPORT_SYMBOL sound/oss/mpu401 0xb3607f88	attach_mpu401
+EXPORT_SYMBOL sound/oss/mpu401 0xd9ec5db4	probe_mpu401
+EXPORT_SYMBOL sound/oss/sb_lib 0x42424109	sb_be_quiet
+EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea	smw_free
+EXPORT_SYMBOL sound/oss/sb_lib 0x67d26a93	probe_sbmpu
+EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c	unload_sbmpu
+EXPORT_SYMBOL sound/oss/sb_lib 0x9129eaa0	sb_dsp_init
+EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969	sb_dsp_unload
+EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c	sb_dsp_detect
+EXPORT_SYMBOL sound/oss/sound 0x04c87ec8	compute_finetune
+EXPORT_SYMBOL sound/oss/sound 0x06339815	sound_unload_synthdev
+EXPORT_SYMBOL sound/oss/sound 0x0f280035	conf_printf
+EXPORT_SYMBOL sound/oss/sound 0x17ba231d	seq_input_event
+EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf	sound_alloc_mixerdev
+EXPORT_SYMBOL sound/oss/sound 0x1f395686	MIDIbuf_avail
+EXPORT_SYMBOL sound/oss/sound 0x2161d5e8	sound_timer_init
+EXPORT_SYMBOL sound/oss/sound 0x2aa31695	midi_synth_kill_note
+EXPORT_SYMBOL sound/oss/sound 0x349ab5c0	audio_devs
+EXPORT_SYMBOL sound/oss/sound 0x368f11d8	mixer_devs
+EXPORT_SYMBOL sound/oss/sound 0x394cb088	sound_free_dma
+EXPORT_SYMBOL sound/oss/sound 0x418f5fbe	sound_close_dma
+EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd	num_audiodevs
+EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d	midi_synth_setup_voice
+EXPORT_SYMBOL sound/oss/sound 0x51e354b2	sound_alloc_timerdev
+EXPORT_SYMBOL sound/oss/sound 0x56504ca2	midi_synth_reset
+EXPORT_SYMBOL sound/oss/sound 0x5d986fc9	note_to_freq
+EXPORT_SYMBOL sound/oss/sound 0x702f9ca9	midi_devs
+EXPORT_SYMBOL sound/oss/sound 0x7679ee76	seq_copy_to_input
+EXPORT_SYMBOL sound/oss/sound 0x7bdf0907	conf_printf2
+EXPORT_SYMBOL sound/oss/sound 0x892093e0	midi_synth_controller
+EXPORT_SYMBOL sound/oss/sound 0x90bd9714	sequencer_timer
+EXPORT_SYMBOL sound/oss/sound 0x987bcf12	DMAbuf_outputintr
+EXPORT_SYMBOL sound/oss/sound 0x9a95733f	sound_alloc_dma
+EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d	midi_synth_start_note
+EXPORT_SYMBOL sound/oss/sound 0x9d845b18	num_mixers
+EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f	load_mixer_volumes
+EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf	num_midis
+EXPORT_SYMBOL sound/oss/sound 0xa41ead5f	sound_unload_timerdev
+EXPORT_SYMBOL sound/oss/sound 0xa51c913b	sound_unload_mixerdev
+EXPORT_SYMBOL sound/oss/sound 0xa55f694f	synth_devs
+EXPORT_SYMBOL sound/oss/sound 0xa6bb414c	sound_unload_mididev
+EXPORT_SYMBOL sound/oss/sound 0xa7c42225	sound_timer_devs
+EXPORT_SYMBOL sound/oss/sound 0xa948751e	sound_unload_audiodev
+EXPORT_SYMBOL sound/oss/sound 0xad45df73	midi_synth_close
+EXPORT_SYMBOL sound/oss/sound 0xaef743b2	midi_synth_ioctl
+EXPORT_SYMBOL sound/oss/sound 0xb14b22cd	midi_synth_hw_control
+EXPORT_SYMBOL sound/oss/sound 0xb51587f6	do_midi_msg
+EXPORT_SYMBOL sound/oss/sound 0xba413f87	sound_alloc_mididev
+EXPORT_SYMBOL sound/oss/sound 0xba7dd041	midi_synth_bender
+EXPORT_SYMBOL sound/oss/sound 0xc748d109	sound_alloc_synthdev
+EXPORT_SYMBOL sound/oss/sound 0xcab4d5bf	midi_synth_load_patch
+EXPORT_SYMBOL sound/oss/sound 0xcc4b8797	sound_open_dma
+EXPORT_SYMBOL sound/oss/sound 0xd06b60f3	sound_install_mixer
+EXPORT_SYMBOL sound/oss/sound 0xd85be938	midi_synth_set_instr
+EXPORT_SYMBOL sound/oss/sound 0xdb400afa	midi_synth_panning
+EXPORT_SYMBOL sound/oss/sound 0xe056b71c	DMAbuf_start_dma
+EXPORT_SYMBOL sound/oss/sound 0xe2675a79	sound_timer_interrupt
+EXPORT_SYMBOL sound/oss/sound 0xeb315d99	DMAbuf_inputintr
+EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20	midi_synth_aftertouch
+EXPORT_SYMBOL sound/oss/sound 0xf5318259	sound_install_audiodrv
+EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb	midi_synth_open
+EXPORT_SYMBOL sound/oss/sound 0xf78f6363	sequencer_init
+EXPORT_SYMBOL sound/oss/sound 0xfa6871be	sound_timer_syncinterval
+EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3	midi_synth_send_sysex
+EXPORT_SYMBOL sound/oss/uart401 0x049cd8b7	uart401intr
+EXPORT_SYMBOL sound/oss/uart401 0x3a83763f	probe_uart401
+EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9	unload_uart401
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x1f057ced	snd_ac97_pcm_double_rate_rules
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x25a477b4	snd_ac97_bus
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x29dbc228	snd_ac97_update_bits
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3253c1fc	snd_ac97_set_rate
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x36118725	snd_ac97_update
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3ec16be1	snd_ac97_get_short_name
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3f612982	snd_ac97_tune_hardware
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x4bdd62c8	snd_ac97_pcm_open
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x4be0bd07	snd_ac97_resume
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x5a848b1b	snd_ac97_write
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x619ea2aa	snd_ac97_pcm_close
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x6af97483	snd_ac97_write_cache
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x7105fad2	snd_ac97_update_power
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xbf31040f	snd_ac97_pcm_assign
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xc1ae9fc3	snd_ac97_suspend
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xc812f5e2	snd_ac97_read
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xcd57d7ff	snd_ac97_mixer
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x41d97bcc	snd_emu10k1_synth_alloc
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x42628cc7	snd_emu10k1_ptr_read
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x49289623	snd_emu10k1_synth_copy_from_user
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x5c685f9a	snd_emu10k1_ptr_write
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x604958f1	snd_emu10k1_synth_bzero
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xa62a33b6	snd_emu10k1_memblk_map
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xb154a6ce	snd_emu10k1_voice_alloc
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xe96cabc8	snd_emu10k1_voice_free
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xf2b31cb1	snd_emu10k1_synth_free
+EXPORT_SYMBOL sound/pci/hda/snd-hda-codec 0x5613a4b0	snd_hda_parse_generic_codec
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x8ed92593	snd_ice1712_akm4xxx_init
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xcabd53c5	snd_ice1712_akm4xxx_build_controls
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xd6f1853a	snd_ice1712_akm4xxx_free
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x04d7b8b6	oxygen_write32_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x365a3a88	oxygen_write32
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x38609b78	oxygen_read_ac97
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x4104fbf1	oxygen_read8
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x48107316	oxygen_read32
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x485fcee1	oxygen_pci_resume
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x58f32abc	oxygen_pci_suspend
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x65f2e577	oxygen_reset_uart
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x661063d5	oxygen_write8
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7cf417df	oxygen_pci_probe
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7f5e9b9f	oxygen_pci_remove
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x9829ee44	oxygen_write16
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa2c1469a	oxygen_write_ac97_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xba8fc0af	oxygen_write_uart
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xbc276121	oxygen_write_spi
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xc3cc6f58	oxygen_read16
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xcd06ccab	oxygen_write_ac97
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xce609645	oxygen_write_i2c
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xde982432	oxygen_write16_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xeb65286b	oxygen_write8_masked
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x27cd6d98	snd_trident_alloc_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x2afa7fc4	snd_trident_start_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x5101d47e	snd_trident_write_voice_regs
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0xae404b0b	snd_trident_stop_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0xbb77364c	snd_trident_free_voice
+EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23	mod_firmware_load
+EXPORT_SYMBOL sound/soundcore 0x597a6aac	register_sound_dsp
+EXPORT_SYMBOL sound/soundcore 0x5d080b98	register_sound_special
+EXPORT_SYMBOL sound/soundcore 0x7afc9d8a	unregister_sound_mixer
+EXPORT_SYMBOL sound/soundcore 0x7edff1b1	sound_class
+EXPORT_SYMBOL sound/soundcore 0x99c95fa5	unregister_sound_special
+EXPORT_SYMBOL sound/soundcore 0xa33fa8da	register_sound_midi
+EXPORT_SYMBOL sound/soundcore 0xc83cf191	register_sound_mixer
+EXPORT_SYMBOL sound/soundcore 0xcd083b10	unregister_sound_dsp
+EXPORT_SYMBOL sound/soundcore 0xded4c63b	register_sound_special_device
+EXPORT_SYMBOL sound/soundcore 0xfdab6de3	unregister_sound_midi
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x20075eeb	snd_emux_unlock_voice
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x4e77b1db	snd_emux_free
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x5d63e139	snd_emux_register
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202	snd_sf_linear_to_log
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x802518b3	snd_emux_terminate_all
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xa168ac93	snd_emux_lock_voice
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xde77a473	snd_emux_new
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x24c7c446	__snd_util_memblk_new
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x4cb269d5	snd_util_mem_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x5fea5a13	snd_util_memhdr_new
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x78e16659	snd_util_mem_alloc
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x820c3a18	__snd_util_mem_alloc
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x88f06dac	snd_util_mem_avail
+EXPORT_SYMBOL sound/synth/snd-util-mem 0xa4fbbbb0	snd_util_memhdr_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0xb87c582d	__snd_util_mem_free
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0	snd_usbmidi_input_start
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d	snd_usbmidi_input_stop
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0x98ce834a	snd_usb_create_midi_interface
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03	snd_usbmidi_disconnect
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x08587cdd	dm_mem_cache_client_create
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x1d667f6c	dm_mem_cache_client_destroy
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x27ceed57	dm_mem_cache_free
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x4dcdebce	dm_mem_cache_alloc
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x920a7a41	dm_message_parse
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0xd5309ca2	dm_mem_cache_shrink
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0xe29e92ef	dm_mem_cache_grow
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x04dca738	lirc_unregister_driver
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x127a436a	lirc_get_pdata
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xfd2f5f45	lirc_register_driver
+EXPORT_SYMBOL vmlinux 0x00000000	per_cpu__softirq_work_list
+EXPORT_SYMBOL vmlinux 0x002b9426	inode_permission
+EXPORT_SYMBOL vmlinux 0x0038e33b	dentry_open
+EXPORT_SYMBOL vmlinux 0x00546468	put_io_context
+EXPORT_SYMBOL vmlinux 0x00801678	flush_scheduled_work
+EXPORT_SYMBOL vmlinux 0x009d258f	_write_lock
+EXPORT_SYMBOL vmlinux 0x00aaaefa	__xfrm_decode_session
+EXPORT_SYMBOL vmlinux 0x00bcc87d	blk_start_queue
+EXPORT_SYMBOL vmlinux 0x00c4dc87	timecounter_init
+EXPORT_SYMBOL vmlinux 0x00ca54a2	xfrm4_rcv_encap
+EXPORT_SYMBOL vmlinux 0x00e8097b	csum_partial_copy_fromiovecend
+EXPORT_SYMBOL vmlinux 0x00e95a42	registered_fb
+EXPORT_SYMBOL vmlinux 0x0109cbb6	inet_frags_init
+EXPORT_SYMBOL vmlinux 0x01139ffc	max_mapnr
+EXPORT_SYMBOL vmlinux 0x0118bdb2	elv_queue_empty
+EXPORT_SYMBOL vmlinux 0x0132186f	xfrm_register_km
+EXPORT_SYMBOL vmlinux 0x013705f0	__nla_reserve_nohdr
+EXPORT_SYMBOL vmlinux 0x015098ee	ip_generic_getfrag
+EXPORT_SYMBOL vmlinux 0x016a08fd	rdmsr_on_cpus
+EXPORT_SYMBOL vmlinux 0x016afbaf	dm_table_put
+EXPORT_SYMBOL vmlinux 0x01802e4e	blk_alloc_queue_node
+EXPORT_SYMBOL vmlinux 0x0186d073	percpu_counter_set
+EXPORT_SYMBOL vmlinux 0x01902adf	netpoll_trap
+EXPORT_SYMBOL vmlinux 0x019b267c	tty_free_termios
+EXPORT_SYMBOL vmlinux 0x019e7a51	get_write_access
+EXPORT_SYMBOL vmlinux 0x01a4aab6	set_irq_chip_data
+EXPORT_SYMBOL vmlinux 0x01a91356	d_instantiate
+EXPORT_SYMBOL vmlinux 0x01befa7e	__break_lease
+EXPORT_SYMBOL vmlinux 0x01da2142	register_qdisc
+EXPORT_SYMBOL vmlinux 0x02077280	security_d_instantiate
+EXPORT_SYMBOL vmlinux 0x02124474	ip_send_check
+EXPORT_SYMBOL vmlinux 0x0216f43c	netdev_class_remove_file
+EXPORT_SYMBOL vmlinux 0x0237b57a	arch_unregister_cpu
+EXPORT_SYMBOL vmlinux 0x0256389f	bit_waitqueue
+EXPORT_SYMBOL vmlinux 0x025a77fa	write_inode_now
+EXPORT_SYMBOL vmlinux 0x02649054	security_sock_rcv_skb
+EXPORT_SYMBOL vmlinux 0x0281eec6	blk_rq_map_integrity_sg
+EXPORT_SYMBOL vmlinux 0x029444f0	native_read_tsc
+EXPORT_SYMBOL vmlinux 0x02a6ce5a	crc16_table
+EXPORT_SYMBOL vmlinux 0x02d81845	audit_log_task_context
+EXPORT_SYMBOL vmlinux 0x02e8db9e	bio_put
+EXPORT_SYMBOL vmlinux 0x02ee26c1	free_pages_exact
+EXPORT_SYMBOL vmlinux 0x02ff3ef3	journal_load
+EXPORT_SYMBOL vmlinux 0x0334da4e	scsi_command_size_tbl
+EXPORT_SYMBOL vmlinux 0x03419146	gnet_stats_finish_copy
+EXPORT_SYMBOL vmlinux 0x0354c94a	xfrm_state_insert
+EXPORT_SYMBOL vmlinux 0x0356bf15	inet_frags_exit_net
+EXPORT_SYMBOL vmlinux 0x035b8b1a	bd_set_size
+EXPORT_SYMBOL vmlinux 0x036db377	ip_route_output_key
+EXPORT_SYMBOL vmlinux 0x037a0cba	kfree
+EXPORT_SYMBOL vmlinux 0x03a75ffc	try_to_release_page
+EXPORT_SYMBOL vmlinux 0x03a8cf26	__skb_warn_lro_forwarding
+EXPORT_SYMBOL vmlinux 0x03c06156	bitmap_fold
+EXPORT_SYMBOL vmlinux 0x03c6a510	flush_old_exec
+EXPORT_SYMBOL vmlinux 0x03e90968	tcp_gro_receive
+EXPORT_SYMBOL vmlinux 0x03fd2571	vm_unmap_ram
+EXPORT_SYMBOL vmlinux 0x0422fe4a	inet_csk_timer_bug_msg
+EXPORT_SYMBOL vmlinux 0x042c5d9c	gnttab_post_map_adjust
+EXPORT_SYMBOL vmlinux 0x0487f831	fb_find_best_display
+EXPORT_SYMBOL vmlinux 0x048b94ea	pci_get_device
+EXPORT_SYMBOL vmlinux 0x04b3d1a0	vfs_link
+EXPORT_SYMBOL vmlinux 0x04e153bc	dmam_alloc_noncoherent
+EXPORT_SYMBOL vmlinux 0x04ec3900	ps2_begin_command
+EXPORT_SYMBOL vmlinux 0x04f9e1f6	gnet_stats_copy_app
+EXPORT_SYMBOL vmlinux 0x05182f6e	ip_route_me_harder
+EXPORT_SYMBOL vmlinux 0x05240ee7	percpu_counter_batch
+EXPORT_SYMBOL vmlinux 0x0535f329	inode_init_once
+EXPORT_SYMBOL vmlinux 0x0536d637	llc_build_and_send_ui_pkt
+EXPORT_SYMBOL vmlinux 0x055fd22f	config_item_init
+EXPORT_SYMBOL vmlinux 0x057ce975	hex_dump_to_buffer
+EXPORT_SYMBOL vmlinux 0x05aacd42	devm_ioport_map
+EXPORT_SYMBOL vmlinux 0x05ae66c0	mb_cache_entry_free
+EXPORT_SYMBOL vmlinux 0x05e28d43	__first_cpu
+EXPORT_SYMBOL vmlinux 0x05eabf5c	lro_receive_skb
+EXPORT_SYMBOL vmlinux 0x061651be	strcat
+EXPORT_SYMBOL vmlinux 0x06187962	pci_map_rom
+EXPORT_SYMBOL vmlinux 0x06466d4c	input_open_device
+EXPORT_SYMBOL vmlinux 0x067d8d35	security_release_secctx
+EXPORT_SYMBOL vmlinux 0x068c7263	ioremap_cache
+EXPORT_SYMBOL vmlinux 0x06a04ddb	bio_integrity_alloc
+EXPORT_SYMBOL vmlinux 0x06a365ed	generic_setxattr
+EXPORT_SYMBOL vmlinux 0x06bf9482	clear_inode
+EXPORT_SYMBOL vmlinux 0x06d728b1	tcp_parse_md5sig_option
+EXPORT_SYMBOL vmlinux 0x06eca37d	neigh_table_clear
+EXPORT_SYMBOL vmlinux 0x06fe3b14	default_grn
+EXPORT_SYMBOL vmlinux 0x0727c4f3	iowrite8
+EXPORT_SYMBOL vmlinux 0x075574ce	mdiobus_alloc
+EXPORT_SYMBOL vmlinux 0x078c3ee0	__elv_add_request
+EXPORT_SYMBOL vmlinux 0x0799aca4	local_bh_enable
+EXPORT_SYMBOL vmlinux 0x0799c50a	param_set_ulong
+EXPORT_SYMBOL vmlinux 0x07a55e29	mark_buffer_dirty
+EXPORT_SYMBOL vmlinux 0x07a890c8	fb_alloc_cmap
+EXPORT_SYMBOL vmlinux 0x07b9796e	pci_read_vpd
+EXPORT_SYMBOL vmlinux 0x07c55189	do_SAK
+EXPORT_SYMBOL vmlinux 0x07cc4a5d	printk_timed_ratelimit
+EXPORT_SYMBOL vmlinux 0x07d50a24	csum_partial
+EXPORT_SYMBOL vmlinux 0x07e7e601	__sk_dst_check
+EXPORT_SYMBOL vmlinux 0x07f23e1b	tty_driver_kref_put
+EXPORT_SYMBOL vmlinux 0x081cf743	qdisc_reset
+EXPORT_SYMBOL vmlinux 0x082c3213	pci_root_buses
+EXPORT_SYMBOL vmlinux 0x08634249	ethtool_op_get_ufo
+EXPORT_SYMBOL vmlinux 0x0867ed19	register_snap_client
+EXPORT_SYMBOL vmlinux 0x08c3a057	pci_scan_slot
+EXPORT_SYMBOL vmlinux 0x08d15837	blk_rq_map_kern
+EXPORT_SYMBOL vmlinux 0x08d66a3a	warn_slowpath_fmt
+EXPORT_SYMBOL vmlinux 0x08dd69f5	jbd2_journal_ack_err
+EXPORT_SYMBOL vmlinux 0x08fc7963	nf_setsockopt
+EXPORT_SYMBOL vmlinux 0x09144253	sysctl_string
+EXPORT_SYMBOL vmlinux 0x091c824a	machine_power_off
+EXPORT_SYMBOL vmlinux 0x0932539a	netdev_rx_csum_fault
+EXPORT_SYMBOL vmlinux 0x0948cde9	num_physpages
+EXPORT_SYMBOL vmlinux 0x0949836d	block_truncate_page
+EXPORT_SYMBOL vmlinux 0x098b71c6	fb_dealloc_cmap
+EXPORT_SYMBOL vmlinux 0x098febc8	pci_bus_read_config_byte
+EXPORT_SYMBOL vmlinux 0x09b4eb02	blk_end_request_all
+EXPORT_SYMBOL vmlinux 0x09c55cec	schedule_timeout_interruptible
+EXPORT_SYMBOL vmlinux 0x09d0da65	get_sb_nodev
+EXPORT_SYMBOL vmlinux 0x09d44df9	in_lock_functions
+EXPORT_SYMBOL vmlinux 0x09e15bd1	simple_fill_super
+EXPORT_SYMBOL vmlinux 0x0a1e87f9	atomic64_add_negative
+EXPORT_SYMBOL vmlinux 0x0a2487e0	unblock_all_signals
+EXPORT_SYMBOL vmlinux 0x0a3131f6	strnchr
+EXPORT_SYMBOL vmlinux 0x0a4ad270	sock_no_ioctl
+EXPORT_SYMBOL vmlinux 0x0a51d219	brioctl_set
+EXPORT_SYMBOL vmlinux 0x0a532668	cdrom_number_of_slots
+EXPORT_SYMBOL vmlinux 0x0a64d3c5	serio_unregister_driver
+EXPORT_SYMBOL vmlinux 0x0a7414c0	dev_unicast_sync
+EXPORT_SYMBOL vmlinux 0x0a86e978	end_buffer_read_sync
+EXPORT_SYMBOL vmlinux 0x0a872159	tty_unregister_device
+EXPORT_SYMBOL vmlinux 0x0ac1de79	pci_scan_bridge
+EXPORT_SYMBOL vmlinux 0x0acb1a3c	__bitmap_shift_right
+EXPORT_SYMBOL vmlinux 0x0b166c4e	tcp_md5_hash_key
+EXPORT_SYMBOL vmlinux 0x0b182eb2	inet_ioctl
+EXPORT_SYMBOL vmlinux 0x0b1beb31	vmalloc_32_user
+EXPORT_SYMBOL vmlinux 0x0b3f8b5f	blk_queue_invalidate_tags
+EXPORT_SYMBOL vmlinux 0x0b58d64e	netlink_unicast
+EXPORT_SYMBOL vmlinux 0x0b680b22	vfs_readdir
+EXPORT_SYMBOL vmlinux 0x0b721bdd	tcf_hash_check
+EXPORT_SYMBOL vmlinux 0x0b742fd7	simple_strtol
+EXPORT_SYMBOL vmlinux 0x0b9dcd85	sg_miter_start
+EXPORT_SYMBOL vmlinux 0x0c44747e	alloc_netdev_mq
+EXPORT_SYMBOL vmlinux 0x0c47994b	__module_put_and_exit
+EXPORT_SYMBOL vmlinux 0x0c4c3128	pci_release_selected_regions
+EXPORT_SYMBOL vmlinux 0x0c5a15ea	follow_up
+EXPORT_SYMBOL vmlinux 0x0cae232b	utf16s_to_utf8s
+EXPORT_SYMBOL vmlinux 0x0caf8d13	jbd2_journal_force_commit
+EXPORT_SYMBOL vmlinux 0x0d26a76d	_write_lock_irq
+EXPORT_SYMBOL vmlinux 0x0d433ad4	ppp_unit_number
+EXPORT_SYMBOL vmlinux 0x0d4b77b7	gen_pool_add
+EXPORT_SYMBOL vmlinux 0x0d542439	__ipv6_addr_type
+EXPORT_SYMBOL vmlinux 0x0d656169	napi_gro_receive
+EXPORT_SYMBOL vmlinux 0x0d6c963c	copy_from_user
+EXPORT_SYMBOL vmlinux 0x0d88d57c	xfrm_policy_alloc
+EXPORT_SYMBOL vmlinux 0x0d88f092	mpage_readpage
+EXPORT_SYMBOL vmlinux 0x0d9376ff	xfrm_policy_destroy
+EXPORT_SYMBOL vmlinux 0x0da10ec3	security_sock_graft
+EXPORT_SYMBOL vmlinux 0x0db7a158	inet_csk_destroy_sock
+EXPORT_SYMBOL vmlinux 0x0df205c3	skb_dequeue
+EXPORT_SYMBOL vmlinux 0x0e0f778d	n_tty_ioctl_helper
+EXPORT_SYMBOL vmlinux 0x0e2cde27	proc_dostring
+EXPORT_SYMBOL vmlinux 0x0e4f4084	pcim_iounmap
+EXPORT_SYMBOL vmlinux 0x0e52592a	panic
+EXPORT_SYMBOL vmlinux 0x0e760890	skb_queue_tail
+EXPORT_SYMBOL vmlinux 0x0e78eca2	tcf_hash_search
+EXPORT_SYMBOL vmlinux 0x0e79bb82	dm_table_unplug_all
+EXPORT_SYMBOL vmlinux 0x0e83fea1	del_timer_sync
+EXPORT_SYMBOL vmlinux 0x0ebc9885	proc_doulongvec_ms_jiffies_minmax
+EXPORT_SYMBOL vmlinux 0x0ed6a1a6	dev_kfree_skb_any
+EXPORT_SYMBOL vmlinux 0x0ed885ba	vlan_gro_receive
+EXPORT_SYMBOL vmlinux 0x0eeffce9	security_path_mkdir
+EXPORT_SYMBOL vmlinux 0x0f005351	pci_request_region
+EXPORT_SYMBOL vmlinux 0x0f1ef871	posix_acl_alloc
+EXPORT_SYMBOL vmlinux 0x0f3d52dd	pci_enable_wake
+EXPORT_SYMBOL vmlinux 0x0f412b9d	generic_error_remove_page
+EXPORT_SYMBOL vmlinux 0x0f41f884	generic_setlease
+EXPORT_SYMBOL vmlinux 0x0fc2f8b5	gnet_stats_start_copy_compat
+EXPORT_SYMBOL vmlinux 0x0feee89a	per_cpu__current_task
+EXPORT_SYMBOL vmlinux 0x0ff2b602	slhc_compress
+EXPORT_SYMBOL vmlinux 0x0ff722f4	shrink_dcache_sb
+EXPORT_SYMBOL vmlinux 0x1024442e	pci_select_bars
+EXPORT_SYMBOL vmlinux 0x105e2727	__tracepoint_kmalloc
+EXPORT_SYMBOL vmlinux 0x106ea969	generic_file_buffered_write
+EXPORT_SYMBOL vmlinux 0x108e8985	param_get_uint
+EXPORT_SYMBOL vmlinux 0x10ac7b0a	dev_addr_del
+EXPORT_SYMBOL vmlinux 0x10b7784a	blk_integrity_compare
+EXPORT_SYMBOL vmlinux 0x10b8bc3f	bio_clone
+EXPORT_SYMBOL vmlinux 0x10b8cb31	unregister_nls
+EXPORT_SYMBOL vmlinux 0x10c29e90	blk_alloc_queue
+EXPORT_SYMBOL vmlinux 0x10ee20bb	default_blu
+EXPORT_SYMBOL vmlinux 0x10ef6c68	generic_write_sync
+EXPORT_SYMBOL vmlinux 0x10f7010b	d_obtain_alias
+EXPORT_SYMBOL vmlinux 0x112986da	xfrm_state_flush
+EXPORT_SYMBOL vmlinux 0x113eefda	wait_for_key_construction
+EXPORT_SYMBOL vmlinux 0x1150a64f	devm_ioport_unmap
+EXPORT_SYMBOL vmlinux 0x115acde4	con_set_default_unimap
+EXPORT_SYMBOL vmlinux 0x1163f0a7	blk_max_low_pfn
+EXPORT_SYMBOL vmlinux 0x117093be	qdisc_class_hash_init
+EXPORT_SYMBOL vmlinux 0x1182f5fc	generic_file_mmap
+EXPORT_SYMBOL vmlinux 0x118f01ea	putname
+EXPORT_SYMBOL vmlinux 0x11a18b14	__wake_up_bit
+EXPORT_SYMBOL vmlinux 0x11c444a0	dmam_pool_destroy
+EXPORT_SYMBOL vmlinux 0x11d0c38a	pci_bus_alloc_resource
+EXPORT_SYMBOL vmlinux 0x11d3030a	xfrm_state_alloc
+EXPORT_SYMBOL vmlinux 0x11f78ebb	pci_bus_type
+EXPORT_SYMBOL vmlinux 0x11f87c52	do_sync_write
+EXPORT_SYMBOL vmlinux 0x11ff7c5f	jbd2_journal_try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0x120507ac	idr_get_new
+EXPORT_SYMBOL vmlinux 0x1234328b	serio_rescan
+EXPORT_SYMBOL vmlinux 0x1239f5e3	config_group_find_item
+EXPORT_SYMBOL vmlinux 0x124d7233	journal_dirty_metadata
+EXPORT_SYMBOL vmlinux 0x12539012	journal_stop
+EXPORT_SYMBOL vmlinux 0x126cc4bd	pci_setup_cardbus
+EXPORT_SYMBOL vmlinux 0x12baa081	configfs_undepend_item
+EXPORT_SYMBOL vmlinux 0x12d3432d	invalidate_inodes
+EXPORT_SYMBOL vmlinux 0x12da5bb2	__kmalloc
+EXPORT_SYMBOL vmlinux 0x12ef8a95	netlink_kernel_create
+EXPORT_SYMBOL vmlinux 0x12f10736	udplite_table
+EXPORT_SYMBOL vmlinux 0x12fc7b5e	ps2_end_command
+EXPORT_SYMBOL vmlinux 0x12feef44	xfrm_bundle_ok
+EXPORT_SYMBOL vmlinux 0x12ff531f	security_sb_set_mnt_opts
+EXPORT_SYMBOL vmlinux 0x1384487a	ps2_handle_ack
+EXPORT_SYMBOL vmlinux 0x13c1da84	mutex_lock_interruptible
+EXPORT_SYMBOL vmlinux 0x13d8b829	cdrom_mode_select
+EXPORT_SYMBOL vmlinux 0x13e3c6da	get_user_pages
+EXPORT_SYMBOL vmlinux 0x141178d0	serio_reconnect
+EXPORT_SYMBOL vmlinux 0x141c57ed	inode_sub_rsv_space
+EXPORT_SYMBOL vmlinux 0x141e425f	jbd2_journal_destroy
+EXPORT_SYMBOL vmlinux 0x1426e459	kernel_sock_ioctl
+EXPORT_SYMBOL vmlinux 0x1437cdc2	jbd2_journal_init_dev
+EXPORT_SYMBOL vmlinux 0x145414e9	skb_gro_reset_offset
+EXPORT_SYMBOL vmlinux 0x1454e639	mutex_lock
+EXPORT_SYMBOL vmlinux 0x14718805	netlink_dump_start
+EXPORT_SYMBOL vmlinux 0x14778cad	proc_dointvec
+EXPORT_SYMBOL vmlinux 0x149901b6	mnt_unpin
+EXPORT_SYMBOL vmlinux 0x14af0cf7	gen_pool_destroy
+EXPORT_SYMBOL vmlinux 0x14b7b972	__pskb_pull_tail
+EXPORT_SYMBOL vmlinux 0x14c86296	config_group_init
+EXPORT_SYMBOL vmlinux 0x14fc9289	pci_bus_set_ops
+EXPORT_SYMBOL vmlinux 0x150e3f75	inode_claim_rsv_space
+EXPORT_SYMBOL vmlinux 0x1512e55e	elv_dispatch_sort
+EXPORT_SYMBOL vmlinux 0x15174a6c	ppp_unregister_compressor
+EXPORT_SYMBOL vmlinux 0x1518925e	clear_highpage
+EXPORT_SYMBOL vmlinux 0x152330c2	nla_put
+EXPORT_SYMBOL vmlinux 0x1523e40d	gnet_stats_start_copy
+EXPORT_SYMBOL vmlinux 0x15355884	fddi_type_trans
+EXPORT_SYMBOL vmlinux 0x1551dc51	bitmap_find_free_region
+EXPORT_SYMBOL vmlinux 0x156ae433	bio_init
+EXPORT_SYMBOL vmlinux 0x15ef2dd9	kfifo_free
+EXPORT_SYMBOL vmlinux 0x16043e6b	lock_rename
+EXPORT_SYMBOL vmlinux 0x160b3e40	splice_from_pipe_end
+EXPORT_SYMBOL vmlinux 0x161dd6d2	__find_get_block
+EXPORT_SYMBOL vmlinux 0x16305289	warn_slowpath_null
+EXPORT_SYMBOL vmlinux 0x163accf2	tcp_splice_read
+EXPORT_SYMBOL vmlinux 0x1647ddf1	sock_no_bind
+EXPORT_SYMBOL vmlinux 0x164d2f4e	ethtool_op_get_rx_csum
+EXPORT_SYMBOL vmlinux 0x165982f3	tcf_em_register
+EXPORT_SYMBOL vmlinux 0x1675606f	bad_dma_address
+EXPORT_SYMBOL vmlinux 0x167e7f9d	__get_user_1
+EXPORT_SYMBOL vmlinux 0x1691a461	pci_bus_write_config_byte
+EXPORT_SYMBOL vmlinux 0x16e0e087	nf_log_unregister
+EXPORT_SYMBOL vmlinux 0x1739b98a	pci_bus_size_bridges
+EXPORT_SYMBOL vmlinux 0x1754cf8c	kernel_connect
+EXPORT_SYMBOL vmlinux 0x1754d39f	d_alloc
+EXPORT_SYMBOL vmlinux 0x177ef33b	sock_wmalloc
+EXPORT_SYMBOL vmlinux 0x17a5e052	sget
+EXPORT_SYMBOL vmlinux 0x17c0f1a4	set_blocksize
+EXPORT_SYMBOL vmlinux 0x17d12897	neigh_sysctl_unregister
+EXPORT_SYMBOL vmlinux 0x17df17bc	sysctl_tcp_ecn
+EXPORT_SYMBOL vmlinux 0x17f341a0	i8042_lock_chip
+EXPORT_SYMBOL vmlinux 0x181790d3	consume_skb
+EXPORT_SYMBOL vmlinux 0x181b6ff2	mempool_resize
+EXPORT_SYMBOL vmlinux 0x181fcdcb	do_truncate
+EXPORT_SYMBOL vmlinux 0x1833f039	blk_queue_start_tag
+EXPORT_SYMBOL vmlinux 0x18375951	inet_put_port
+EXPORT_SYMBOL vmlinux 0x183fa88b	mempool_alloc_slab
+EXPORT_SYMBOL vmlinux 0x184b45a4	ppp_register_compressor
+EXPORT_SYMBOL vmlinux 0x1861d0db	rtnl_notify
+EXPORT_SYMBOL vmlinux 0x186898dd	read_cache_page_gfp
+EXPORT_SYMBOL vmlinux 0x186cad20	posix_acl_permission
+EXPORT_SYMBOL vmlinux 0x1879642a	blk_queue_max_hw_sectors
+EXPORT_SYMBOL vmlinux 0x18bfeff9	dev_addr_add
+EXPORT_SYMBOL vmlinux 0x19166fb1	ethtool_op_set_tso
+EXPORT_SYMBOL vmlinux 0x192f3718	security_path_symlink
+EXPORT_SYMBOL vmlinux 0x195c270f	bdput
+EXPORT_SYMBOL vmlinux 0x1976bc16	__tracepoint_kmem_cache_free
+EXPORT_SYMBOL vmlinux 0x1985ed3c	prepare_to_wait_exclusive
+EXPORT_SYMBOL vmlinux 0x199ed0cd	net_disable_timestamp
+EXPORT_SYMBOL vmlinux 0x19b929b4	dev_get_stats
+EXPORT_SYMBOL vmlinux 0x19e48c48	vfs_mkdir
+EXPORT_SYMBOL vmlinux 0x1a04c098	bio_sector_offset
+EXPORT_SYMBOL vmlinux 0x1a1def21	input_unfilter_device
+EXPORT_SYMBOL vmlinux 0x1a24e5e2	sonet_subtract_stats
+EXPORT_SYMBOL vmlinux 0x1a5ef3d2	phys_to_machine_mapping
+EXPORT_SYMBOL vmlinux 0x1a6b76f3	blk_integrity_register
+EXPORT_SYMBOL vmlinux 0x1a73be83	xfrm_policy_bysel_ctx
+EXPORT_SYMBOL vmlinux 0x1a75caa3	_read_lock
+EXPORT_SYMBOL vmlinux 0x1a8a845e	idle_nomwait
+EXPORT_SYMBOL vmlinux 0x1aca90ba	set_groups
+EXPORT_SYMBOL vmlinux 0x1ace138d	bitmap_allocate_region
+EXPORT_SYMBOL vmlinux 0x1afbdee7	__blk_run_queue
+EXPORT_SYMBOL vmlinux 0x1b015d25	bitmap_parselist
+EXPORT_SYMBOL vmlinux 0x1b400a47	bioset_integrity_create
+EXPORT_SYMBOL vmlinux 0x1b6314fd	in_aton
+EXPORT_SYMBOL vmlinux 0x1b89419f	add_wait_queue_exclusive
+EXPORT_SYMBOL vmlinux 0x1b8b95ad	i8042_unlock_chip
+EXPORT_SYMBOL vmlinux 0x1b9981cc	set_irq_wake
+EXPORT_SYMBOL vmlinux 0x1b9c5c66	tcp_close
+EXPORT_SYMBOL vmlinux 0x1bc31cb6	dev_unicast_add
+EXPORT_SYMBOL vmlinux 0x1c1af916	set_normalized_timespec
+EXPORT_SYMBOL vmlinux 0x1c52dc89	mb_cache_entry_release
+EXPORT_SYMBOL vmlinux 0x1c798d96	inet_accept
+EXPORT_SYMBOL vmlinux 0x1cb06ae0	genl_unregister_ops
+EXPORT_SYMBOL vmlinux 0x1cc6719a	register_reboot_notifier
+EXPORT_SYMBOL vmlinux 0x1ce7ec4c	rwsem_wake
+EXPORT_SYMBOL vmlinux 0x1cefe352	wait_for_completion
+EXPORT_SYMBOL vmlinux 0x1d21c252	llc_sap_close
+EXPORT_SYMBOL vmlinux 0x1d2e87c6	do_gettimeofday
+EXPORT_SYMBOL vmlinux 0x1d3aa425	pci_choose_state
+EXPORT_SYMBOL vmlinux 0x1d6eb962	neigh_resolve_output
+EXPORT_SYMBOL vmlinux 0x1d753975	direct_remap_pfn_range
+EXPORT_SYMBOL vmlinux 0x1d76f129	kobject_add
+EXPORT_SYMBOL vmlinux 0x1d87451a	cancel_dirty_page
+EXPORT_SYMBOL vmlinux 0x1da423ef	mnt_pin
+EXPORT_SYMBOL vmlinux 0x1dc36131	fb_destroy_modedb
+EXPORT_SYMBOL vmlinux 0x1dce19ab	__devm_release_region
+EXPORT_SYMBOL vmlinux 0x1dd571e6	fb_copy_cmap
+EXPORT_SYMBOL vmlinux 0x1df213be	vfs_quota_on
+EXPORT_SYMBOL vmlinux 0x1dff0f51	journal_lock_updates
+EXPORT_SYMBOL vmlinux 0x1e0c2be4	ioremap_wc
+EXPORT_SYMBOL vmlinux 0x1e0e1b4d	k8_northbridges
+EXPORT_SYMBOL vmlinux 0x1e1c0193	check_disk_size_change
+EXPORT_SYMBOL vmlinux 0x1e225588	xfrm_stateonly_find
+EXPORT_SYMBOL vmlinux 0x1e2e427f	cpumask_next_and
+EXPORT_SYMBOL vmlinux 0x1e393ff6	tcp_v4_destroy_sock
+EXPORT_SYMBOL vmlinux 0x1e6d26a8	strstr
+EXPORT_SYMBOL vmlinux 0x1e803291	blk_rq_count_integrity_sg
+EXPORT_SYMBOL vmlinux 0x1e8b3ac1	dma_mark_declared_memory_occupied
+EXPORT_SYMBOL vmlinux 0x1eacdb62	dst_alloc
+EXPORT_SYMBOL vmlinux 0x1ebabb03	elv_rb_latter_request
+EXPORT_SYMBOL vmlinux 0x1ecb9943	posix_acl_to_xattr
+EXPORT_SYMBOL vmlinux 0x1efe283f	__cap_full_set
+EXPORT_SYMBOL vmlinux 0x1f47cbaa	sock_no_mmap
+EXPORT_SYMBOL vmlinux 0x1f7680fa	write_one_page
+EXPORT_SYMBOL vmlinux 0x1f7d042f	jbd2_journal_init_inode
+EXPORT_SYMBOL vmlinux 0x1f801124	filemap_write_and_wait_range
+EXPORT_SYMBOL vmlinux 0x1fbfadc1	dev_set_mtu
+EXPORT_SYMBOL vmlinux 0x1fdb9458	sk_stream_kill_queues
+EXPORT_SYMBOL vmlinux 0x1feb83ec	mem_map
+EXPORT_SYMBOL vmlinux 0x1fedf0f4	__request_region
+EXPORT_SYMBOL vmlinux 0x1ff69dd8	vfs_fstatat
+EXPORT_SYMBOL vmlinux 0x1fff1af2	xfrm_state_add
+EXPORT_SYMBOL vmlinux 0x20000329	simple_strtoul
+EXPORT_SYMBOL vmlinux 0x2024f21c	disk_stack_limits
+EXPORT_SYMBOL vmlinux 0x20385c58	genl_register_mc_group
+EXPORT_SYMBOL vmlinux 0x203e84d3	end_buffer_async_write
+EXPORT_SYMBOL vmlinux 0x20488532	clocksource_change_rating
+EXPORT_SYMBOL vmlinux 0x20a51761	pci_remove_bus_device
+EXPORT_SYMBOL vmlinux 0x20bd0c64	dma_pool_destroy
+EXPORT_SYMBOL vmlinux 0x20c69f08	netif_rx_ni
+EXPORT_SYMBOL vmlinux 0x20ca1dca	gnet_stats_copy_rate_est
+EXPORT_SYMBOL vmlinux 0x20ff661e	zero_fill_bio
+EXPORT_SYMBOL vmlinux 0x2115ecc5	simple_transaction_read
+EXPORT_SYMBOL vmlinux 0x2121dde6	copy_highpage
+EXPORT_SYMBOL vmlinux 0x213caf69	skb_append
+EXPORT_SYMBOL vmlinux 0x213f1599	destroy_EII_client
+EXPORT_SYMBOL vmlinux 0x2140115f	netdev_state_change
+EXPORT_SYMBOL vmlinux 0x215ebd78	bitrev16
+EXPORT_SYMBOL vmlinux 0x21631c33	tcf_exts_change
+EXPORT_SYMBOL vmlinux 0x2173f299	override_creds
+EXPORT_SYMBOL vmlinux 0x217527a7	generic_make_request
+EXPORT_SYMBOL vmlinux 0x21a979fc	register_framebuffer
+EXPORT_SYMBOL vmlinux 0x21bcf783	get_phy_id
+EXPORT_SYMBOL vmlinux 0x21d2d305	tcf_exts_validate
+EXPORT_SYMBOL vmlinux 0x21d50a51	tcf_hash_release
+EXPORT_SYMBOL vmlinux 0x22281ce0	locks_init_lock
+EXPORT_SYMBOL vmlinux 0x222e7ce2	sysfs_streq
+EXPORT_SYMBOL vmlinux 0x222fcd4e	dev_add_pack
+EXPORT_SYMBOL vmlinux 0x224e49f9	__vlan_hwaccel_rx
+EXPORT_SYMBOL vmlinux 0x22515ed1	fddi_change_mtu
+EXPORT_SYMBOL vmlinux 0x226e86a9	audit_log
+EXPORT_SYMBOL vmlinux 0x2270ed5e	uart_remove_one_port
+EXPORT_SYMBOL vmlinux 0x22762ff1	__xfrm_route_forward
+EXPORT_SYMBOL vmlinux 0x2288378f	system_state
+EXPORT_SYMBOL vmlinux 0x22a62f72	jbd2_log_start_commit
+EXPORT_SYMBOL vmlinux 0x22a73912	__tcp_put_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x22b067d8	xfrm4_prepare_output
+EXPORT_SYMBOL vmlinux 0x22b325d5	kd_mksound
+EXPORT_SYMBOL vmlinux 0x22b6533b	xfrm_sad_getinfo
+EXPORT_SYMBOL vmlinux 0x22e913ad	page_zero_new_buffers
+EXPORT_SYMBOL vmlinux 0x231b6984	cdrom_get_last_written
+EXPORT_SYMBOL vmlinux 0x232001bc	netif_carrier_on
+EXPORT_SYMBOL vmlinux 0x23269a13	strict_strtoul
+EXPORT_SYMBOL vmlinux 0x2359a3d6	blkdev_put
+EXPORT_SYMBOL vmlinux 0x2371b2b4	blk_queue_max_sectors
+EXPORT_SYMBOL vmlinux 0x238b38a8	mapping_tagged
+EXPORT_SYMBOL vmlinux 0x23c8f257	slhc_uncompress
+EXPORT_SYMBOL vmlinux 0x23e0c9a3	__bread
+EXPORT_SYMBOL vmlinux 0x23fd3028	vmalloc_node
+EXPORT_SYMBOL vmlinux 0x240059d6	inet_unregister_protosw
+EXPORT_SYMBOL vmlinux 0x240facb1	set_pages_array_uc
+EXPORT_SYMBOL vmlinux 0x24188dc2	elv_rb_former_request
+EXPORT_SYMBOL vmlinux 0x243ffddc	idr_destroy
+EXPORT_SYMBOL vmlinux 0x24428be5	strncpy_from_user
+EXPORT_SYMBOL vmlinux 0x244daeb9	filp_open
+EXPORT_SYMBOL vmlinux 0x24555945	ip4_datagram_connect
+EXPORT_SYMBOL vmlinux 0x2459bbcc	console_set_on_cmdline
+EXPORT_SYMBOL vmlinux 0x24624544	ftrace_print_flags_seq
+EXPORT_SYMBOL vmlinux 0x24681f4b	__mod_zone_page_state
+EXPORT_SYMBOL vmlinux 0x246cba89	fb_class
+EXPORT_SYMBOL vmlinux 0x24bd7218	neigh_connected_output
+EXPORT_SYMBOL vmlinux 0x24be4d48	dst_discard
+EXPORT_SYMBOL vmlinux 0x24e4bb01	down_write_trylock
+EXPORT_SYMBOL vmlinux 0x24f15d0b	mb_cache_entry_find_first
+EXPORT_SYMBOL vmlinux 0x24fb12ae	vm_insert_mixed
+EXPORT_SYMBOL vmlinux 0x24fdac79	wake_bit_function
+EXPORT_SYMBOL vmlinux 0x250113b4	memory_read_from_buffer
+EXPORT_SYMBOL vmlinux 0x254a641e	ipv6_skip_exthdr
+EXPORT_SYMBOL vmlinux 0x2556bc8a	swiotlb_sync_sg_for_cpu
+EXPORT_SYMBOL vmlinux 0x255c1cde	log_wait_commit
+EXPORT_SYMBOL vmlinux 0x25665c96	xen_safe_halt
+EXPORT_SYMBOL vmlinux 0x256ba285	skb_copy_and_csum_bits
+EXPORT_SYMBOL vmlinux 0x25820c64	fs_overflowuid
+EXPORT_SYMBOL vmlinux 0x258355b4	fb_find_best_mode
+EXPORT_SYMBOL vmlinux 0x25d3e2a3	atomic64_dec_return
+EXPORT_SYMBOL vmlinux 0x25e6a597	dev_get_flags
+EXPORT_SYMBOL vmlinux 0x25f011a1	input_register_handle
+EXPORT_SYMBOL vmlinux 0x26003892	fb_validate_mode
+EXPORT_SYMBOL vmlinux 0x262465cc	dma_alloc_from_coherent
+EXPORT_SYMBOL vmlinux 0x263eefa3	end_page_writeback
+EXPORT_SYMBOL vmlinux 0x26790008	tty_unthrottle
+EXPORT_SYMBOL vmlinux 0x267fc65b	__tasklet_hi_schedule
+EXPORT_SYMBOL vmlinux 0x2685c3d7	__sg_alloc_table
+EXPORT_SYMBOL vmlinux 0x268cc6a2	sys_close
+EXPORT_SYMBOL vmlinux 0x26e23495	pci_request_selected_regions_exclusive
+EXPORT_SYMBOL vmlinux 0x26e76fb8	sysctl_udp_wmem_min
+EXPORT_SYMBOL vmlinux 0x270a284b	vfs_readv
+EXPORT_SYMBOL vmlinux 0x270bcfd9	skb_split
+EXPORT_SYMBOL vmlinux 0x2727da5d	_atomic_dec_and_lock
+EXPORT_SYMBOL vmlinux 0x272a08b2	mb_cache_create
+EXPORT_SYMBOL vmlinux 0x274bd724	devcgroup_inode_permission
+EXPORT_SYMBOL vmlinux 0x2755c2d8	pci_bus_read_config_word
+EXPORT_SYMBOL vmlinux 0x275854f2	textsearch_prepare
+EXPORT_SYMBOL vmlinux 0x276e880d	hippi_change_mtu
+EXPORT_SYMBOL vmlinux 0x27864d57	memparse
+EXPORT_SYMBOL vmlinux 0x27b35c51	tcp_sockets_allocated
+EXPORT_SYMBOL vmlinux 0x27bbf221	disable_irq_nosync
+EXPORT_SYMBOL vmlinux 0x27c61ece	qdisc_put_stab
+EXPORT_SYMBOL vmlinux 0x285ac517	strict_strtoll
+EXPORT_SYMBOL vmlinux 0x287068ab	cdrom_open
+EXPORT_SYMBOL vmlinux 0x287cc45d	nf_ct_attach
+EXPORT_SYMBOL vmlinux 0x28ab3a1b	start_tty
+EXPORT_SYMBOL vmlinux 0x28adec06	blk_queue_prep_rq
+EXPORT_SYMBOL vmlinux 0x29113a4b	read_cache_page
+EXPORT_SYMBOL vmlinux 0x29176179	mntput_no_expire
+EXPORT_SYMBOL vmlinux 0x292093f4	native_rdmsr_safe_regs
+EXPORT_SYMBOL vmlinux 0x292d31d0	prepare_kernel_cred
+EXPORT_SYMBOL vmlinux 0x2934cd98	thermal_zone_device_update
+EXPORT_SYMBOL vmlinux 0x294278a9	atm_alloc_charge
+EXPORT_SYMBOL vmlinux 0x294c96f1	sock_common_getsockopt
+EXPORT_SYMBOL vmlinux 0x29537c9e	alloc_chrdev_region
+EXPORT_SYMBOL vmlinux 0x2968df2b	con_is_bound
+EXPORT_SYMBOL vmlinux 0x29afdabc	thermal_zone_device_unregister
+EXPORT_SYMBOL vmlinux 0x29b6a4fd	set_pages_wb
+EXPORT_SYMBOL vmlinux 0x29bd4c46	__cap_init_eff_set
+EXPORT_SYMBOL vmlinux 0x2a303d4d	check_signature
+EXPORT_SYMBOL vmlinux 0x2a652f3b	alloc_etherdev_mq
+EXPORT_SYMBOL vmlinux 0x2a7b4d56	journal_destroy
+EXPORT_SYMBOL vmlinux 0x2a8e75dd	sg_miter_next
+EXPORT_SYMBOL vmlinux 0x2aa0e4fc	strncasecmp
+EXPORT_SYMBOL vmlinux 0x2ab32d14	tcp_v4_md5_lookup
+EXPORT_SYMBOL vmlinux 0x2abcbe53	inet_csk_reset_keepalive_timer
+EXPORT_SYMBOL vmlinux 0x2ad35f2d	journal_clear_err
+EXPORT_SYMBOL vmlinux 0x2ae1996a	generic_cont_expand_simple
+EXPORT_SYMBOL vmlinux 0x2aeb2800	mempool_create_node
+EXPORT_SYMBOL vmlinux 0x2b0806f8	vfs_create
+EXPORT_SYMBOL vmlinux 0x2b17ae11	misc_deregister
+EXPORT_SYMBOL vmlinux 0x2b3c1f12	sk_filter
+EXPORT_SYMBOL vmlinux 0x2ba707a8	sysctl_tcp_low_latency
+EXPORT_SYMBOL vmlinux 0x2ba73d5f	uart_update_timeout
+EXPORT_SYMBOL vmlinux 0x2bb6fde2	__kfifo_put
+EXPORT_SYMBOL vmlinux 0x2bc95bd4	memset
+EXPORT_SYMBOL vmlinux 0x2bcbab12	pci_bus_assign_resources
+EXPORT_SYMBOL vmlinux 0x2bd09241	inet_stream_ops
+EXPORT_SYMBOL vmlinux 0x2be8d624	generic_file_aio_read
+EXPORT_SYMBOL vmlinux 0x2c03ee58	dquot_initialize
+EXPORT_SYMBOL vmlinux 0x2c35e751	cdrom_get_media_event
+EXPORT_SYMBOL vmlinux 0x2c4e13dc	sock_kmalloc
+EXPORT_SYMBOL vmlinux 0x2c56ecdf	per_cpu__irq_stat
+EXPORT_SYMBOL vmlinux 0x2c5f4db9	vm_insert_pfn
+EXPORT_SYMBOL vmlinux 0x2c78e080	netlink_set_err
+EXPORT_SYMBOL vmlinux 0x2c8ef3e9	module_layout
+EXPORT_SYMBOL vmlinux 0x2c97e881	dst_release
+EXPORT_SYMBOL vmlinux 0x2c9874fe	ida_remove
+EXPORT_SYMBOL vmlinux 0x2ca95936	input_grab_device
+EXPORT_SYMBOL vmlinux 0x2cc2d52d	vcc_hash
+EXPORT_SYMBOL vmlinux 0x2cc8ee2f	swiotlb_dma_mapping_error
+EXPORT_SYMBOL vmlinux 0x2d04a66a	kernel_getpeername
+EXPORT_SYMBOL vmlinux 0x2d39b195	journal_update_format
+EXPORT_SYMBOL vmlinux 0x2d4109e3	call_usermodehelper_pipe
+EXPORT_SYMBOL vmlinux 0x2d4f1755	mpage_readpages
+EXPORT_SYMBOL vmlinux 0x2d66bd13	security_inode_readlink
+EXPORT_SYMBOL vmlinux 0x2d96c44e	security_inode_permission
+EXPORT_SYMBOL vmlinux 0x2daa3e2e	ip_defrag
+EXPORT_SYMBOL vmlinux 0x2dbafbe3	pcibios_align_resource
+EXPORT_SYMBOL vmlinux 0x2dcb0123	schedule_delayed_work_on
+EXPORT_SYMBOL vmlinux 0x2dd16564	arch_register_cpu
+EXPORT_SYMBOL vmlinux 0x2de4600f	jbd2_journal_unlock_updates
+EXPORT_SYMBOL vmlinux 0x2de58d79	module_refcount
+EXPORT_SYMBOL vmlinux 0x2def7f76	rtc_cmos_write
+EXPORT_SYMBOL vmlinux 0x2df7cbac	simple_sync_file
+EXPORT_SYMBOL vmlinux 0x2e06111d	cpu_present_mask
+EXPORT_SYMBOL vmlinux 0x2e06dc47	fb_set_var
+EXPORT_SYMBOL vmlinux 0x2e2ce9e0	sysctl_tcp_syncookies
+EXPORT_SYMBOL vmlinux 0x2e32cfc3	bio_integrity_get_tag
+EXPORT_SYMBOL vmlinux 0x2e4a39f8	sysctl_udp_mem
+EXPORT_SYMBOL vmlinux 0x2e60bace	memcpy
+EXPORT_SYMBOL vmlinux 0x2ea0592c	filemap_fdatawait_range
+EXPORT_SYMBOL vmlinux 0x2eb9a0e8	_read_lock_irq
+EXPORT_SYMBOL vmlinux 0x2ebec69e	__napi_schedule
+EXPORT_SYMBOL vmlinux 0x2ee10615	sk_run_filter
+EXPORT_SYMBOL vmlinux 0x2ee3899d	dev_mc_add
+EXPORT_SYMBOL vmlinux 0x2ee527b1	journal_abort
+EXPORT_SYMBOL vmlinux 0x2ee70314	udp_lib_get_port
+EXPORT_SYMBOL vmlinux 0x2ef86f10	flock_lock_file_wait
+EXPORT_SYMBOL vmlinux 0x2efe5e09	atomic64_xchg
+EXPORT_SYMBOL vmlinux 0x2f085467	cdrom_ioctl
+EXPORT_SYMBOL vmlinux 0x2f287f0d	copy_to_user
+EXPORT_SYMBOL vmlinux 0x2f2ba0e9	shrink_dcache_parent
+EXPORT_SYMBOL vmlinux 0x2f44a153	udp_lib_getsockopt
+EXPORT_SYMBOL vmlinux 0x2f4858a5	__rta_fill
+EXPORT_SYMBOL vmlinux 0x2f74b01c	phy_enable_interrupts
+EXPORT_SYMBOL vmlinux 0x2f9f8903	dquot_free_inode
+EXPORT_SYMBOL vmlinux 0x2fac722f	bio_integrity_enabled
+EXPORT_SYMBOL vmlinux 0x2fb5efff	create_lookup_pte_addr
+EXPORT_SYMBOL vmlinux 0x2fd2b5be	tcp_make_synack
+EXPORT_SYMBOL vmlinux 0x301f8bb0	sock_no_listen
+EXPORT_SYMBOL vmlinux 0x30333d80	per_cpu__softnet_data
+EXPORT_SYMBOL vmlinux 0x303a8724	configfs_depend_item
+EXPORT_SYMBOL vmlinux 0x304197c8	dquot_alloc_space
+EXPORT_SYMBOL vmlinux 0x3051c1fa	pci_dev_put
+EXPORT_SYMBOL vmlinux 0x307b9553	pci_get_bus_and_slot
+EXPORT_SYMBOL vmlinux 0x307f7776	timecompare_offset
+EXPORT_SYMBOL vmlinux 0x30d07c33	llc_sap_open
+EXPORT_SYMBOL vmlinux 0x30d8d519	___pskb_trim
+EXPORT_SYMBOL vmlinux 0x30e74134	tty_termios_copy_hw
+EXPORT_SYMBOL vmlinux 0x310917fe	sort
+EXPORT_SYMBOL vmlinux 0x31121fe1	genl_unregister_mc_group
+EXPORT_SYMBOL vmlinux 0x31298059	unregister_exec_domain
+EXPORT_SYMBOL vmlinux 0x3145216f	pci_dev_present
+EXPORT_SYMBOL vmlinux 0x3147857d	default_red
+EXPORT_SYMBOL vmlinux 0x3154deec	clocksource_unregister
+EXPORT_SYMBOL vmlinux 0x315c913b	mark_info_dirty
+EXPORT_SYMBOL vmlinux 0x3191f109	__krealloc
+EXPORT_SYMBOL vmlinux 0x31f6ef69	qdisc_destroy
+EXPORT_SYMBOL vmlinux 0x32024835	tcp_v4_remember_stamp
+EXPORT_SYMBOL vmlinux 0x32204f21	ps2_command
+EXPORT_SYMBOL vmlinux 0x3249b55e	journal_errno
+EXPORT_SYMBOL vmlinux 0x326df9e1	vfs_stat
+EXPORT_SYMBOL vmlinux 0x3285cc48	param_set_uint
+EXPORT_SYMBOL vmlinux 0x3287cf74	mb_cache_entry_find_next
+EXPORT_SYMBOL vmlinux 0x32b85e43	sock_wake_async
+EXPORT_SYMBOL vmlinux 0x33167c80	journal_set_features
+EXPORT_SYMBOL vmlinux 0x334b51f5	prepare_binprm
+EXPORT_SYMBOL vmlinux 0x33940319	configfs_register_subsystem
+EXPORT_SYMBOL vmlinux 0x33a0741c	generic_shutdown_super
+EXPORT_SYMBOL vmlinux 0x33bcaf17	bio_integrity_add_page
+EXPORT_SYMBOL vmlinux 0x33d92f9a	prepare_to_wait
+EXPORT_SYMBOL vmlinux 0x33fddecf	ip_dev_find
+EXPORT_SYMBOL vmlinux 0x3421d018	w1_remove_master_device
+EXPORT_SYMBOL vmlinux 0x342acca2	request_key_async_with_auxdata
+EXPORT_SYMBOL vmlinux 0x344b667d	kernel_getsockopt
+EXPORT_SYMBOL vmlinux 0x344ce315	nf_unregister_queue_handler
+EXPORT_SYMBOL vmlinux 0x344f8591	bio_get_nr_vecs
+EXPORT_SYMBOL vmlinux 0x3457cb68	param_set_long
+EXPORT_SYMBOL vmlinux 0x34908c14	print_hex_dump_bytes
+EXPORT_SYMBOL vmlinux 0x349cba85	strchr
+EXPORT_SYMBOL vmlinux 0x34ad4c34	alloc_trdev
+EXPORT_SYMBOL vmlinux 0x34b942c4	blk_dump_rq_flags
+EXPORT_SYMBOL vmlinux 0x34ce6646	inode_sub_bytes
+EXPORT_SYMBOL vmlinux 0x34eac704	thermal_zone_bind_cooling_device
+EXPORT_SYMBOL vmlinux 0x3512d7fd	ip_cmsg_recv
+EXPORT_SYMBOL vmlinux 0x3543b2dd	dev_get_by_name
+EXPORT_SYMBOL vmlinux 0x35757d97	xfrm_policy_unregister_afinfo
+EXPORT_SYMBOL vmlinux 0x35a231e9	jbd2_journal_dirty_metadata
+EXPORT_SYMBOL vmlinux 0x35b20c5a	mb_cache_entry_alloc
+EXPORT_SYMBOL vmlinux 0x35c2ba9e	refrigerator
+EXPORT_SYMBOL vmlinux 0x35da2e61	radix_tree_tag_get
+EXPORT_SYMBOL vmlinux 0x360b1afe	probe_irq_mask
+EXPORT_SYMBOL vmlinux 0x360bd676	key_instantiate_and_link
+EXPORT_SYMBOL vmlinux 0x361cd923	filemap_fdatawrite_range
+EXPORT_SYMBOL vmlinux 0x362363a1	f_setown
+EXPORT_SYMBOL vmlinux 0x3656bf5a	lock_kernel
+EXPORT_SYMBOL vmlinux 0x3674b824	devm_free_irq
+EXPORT_SYMBOL vmlinux 0x36875389	__timecompare_update
+EXPORT_SYMBOL vmlinux 0x36893fef	bio_copy_user
+EXPORT_SYMBOL vmlinux 0x36d6db14	nf_log_register
+EXPORT_SYMBOL vmlinux 0x36df613c	vm_insert_page
+EXPORT_SYMBOL vmlinux 0x3744cf36	vmalloc_to_pfn
+EXPORT_SYMBOL vmlinux 0x374ed073	scnprintf
+EXPORT_SYMBOL vmlinux 0x375ba4a5	__locks_copy_lock
+EXPORT_SYMBOL vmlinux 0x37715abe	journal_flush
+EXPORT_SYMBOL vmlinux 0x379d65f5	gen_pool_alloc
+EXPORT_SYMBOL vmlinux 0x37ac6388	napi_skb_finish
+EXPORT_SYMBOL vmlinux 0x37b55a94	proc_create_data
+EXPORT_SYMBOL vmlinux 0x37baecb2	dev_queue_xmit
+EXPORT_SYMBOL vmlinux 0x37befc70	jiffies_to_msecs
+EXPORT_SYMBOL vmlinux 0x37e74642	get_jiffies_64
+EXPORT_SYMBOL vmlinux 0x37ffcc87	jbd2_journal_check_available_features
+EXPORT_SYMBOL vmlinux 0x380171a5	jbd2_journal_blocks_per_page
+EXPORT_SYMBOL vmlinux 0x380ce4fc	hippi_mac_addr
+EXPORT_SYMBOL vmlinux 0x38136638	ethtool_op_set_tx_ipv6_csum
+EXPORT_SYMBOL vmlinux 0x381c4bb1	cancel_delayed_work_sync
+EXPORT_SYMBOL vmlinux 0x384af199	bd_release
+EXPORT_SYMBOL vmlinux 0x38692381	find_get_pages_tag
+EXPORT_SYMBOL vmlinux 0x386fb60a	dev_unicast_delete
+EXPORT_SYMBOL vmlinux 0x388f9128	xfrm_state_walk_done
+EXPORT_SYMBOL vmlinux 0x38b92846	llc_remove_pack
+EXPORT_SYMBOL vmlinux 0x38c8c95a	may_umount
+EXPORT_SYMBOL vmlinux 0x38cab31c	init_timer_deferrable_key
+EXPORT_SYMBOL vmlinux 0x38cf400b	net_accel_map_iomem_page
+EXPORT_SYMBOL vmlinux 0x3910e4a3	dmam_release_declared_memory
+EXPORT_SYMBOL vmlinux 0x39588ca2	bdi_register_dev
+EXPORT_SYMBOL vmlinux 0x3962e1ca	skb_make_writable
+EXPORT_SYMBOL vmlinux 0x397a3921	thermal_zone_device_register
+EXPORT_SYMBOL vmlinux 0x39808ba4	balance_dirty_pages_ratelimited_nr
+EXPORT_SYMBOL vmlinux 0x3980aac1	unregister_reboot_notifier
+EXPORT_SYMBOL vmlinux 0x39979109	key_revoke
+EXPORT_SYMBOL vmlinux 0x39986506	filemap_flush
+EXPORT_SYMBOL vmlinux 0x39a43dcc	path_get
+EXPORT_SYMBOL vmlinux 0x39b69354	audit_log_end
+EXPORT_SYMBOL vmlinux 0x39b97def	bdget
+EXPORT_SYMBOL vmlinux 0x39cc24ca	inode_change_ok
+EXPORT_SYMBOL vmlinux 0x39dfbaa7	net_accel_unmap_iomem_page
+EXPORT_SYMBOL vmlinux 0x3a18ee00	pci_unmap_rom
+EXPORT_SYMBOL vmlinux 0x3a2204c6	security_netlink_recv
+EXPORT_SYMBOL vmlinux 0x3a531522	eth_header_cache
+EXPORT_SYMBOL vmlinux 0x3a5a2ca5	pcim_pin_device
+EXPORT_SYMBOL vmlinux 0x3a96f076	ppp_register_net_channel
+EXPORT_SYMBOL vmlinux 0x3a9b6fb9	blk_unregister_region
+EXPORT_SYMBOL vmlinux 0x3aa1dbcf	_spin_unlock_bh
+EXPORT_SYMBOL vmlinux 0x3ab1eabd	phy_scan_fixups
+EXPORT_SYMBOL vmlinux 0x3abc8ebb	bio_copy_kern
+EXPORT_SYMBOL vmlinux 0x3ac77ae6	open_by_devnum
+EXPORT_SYMBOL vmlinux 0x3adc15b9	posix_acl_from_mode
+EXPORT_SYMBOL vmlinux 0x3ae831b6	kref_init
+EXPORT_SYMBOL vmlinux 0x3afd8553	atm_proc_root
+EXPORT_SYMBOL vmlinux 0x3b0da87b	pcix_get_mmrbc
+EXPORT_SYMBOL vmlinux 0x3b40937d	clear_bdi_congested
+EXPORT_SYMBOL vmlinux 0x3b91df29	pci_bus_write_config_word
+EXPORT_SYMBOL vmlinux 0x3bb78130	set_current_groups
+EXPORT_SYMBOL vmlinux 0x3bca637f	bfifo_qdisc_ops
+EXPORT_SYMBOL vmlinux 0x3bd1b1f6	msecs_to_jiffies
+EXPORT_SYMBOL vmlinux 0x3c2c5af5	sprintf
+EXPORT_SYMBOL vmlinux 0x3c46df02	vfs_readlink
+EXPORT_SYMBOL vmlinux 0x3c4b5ccb	remove_inode_hash
+EXPORT_SYMBOL vmlinux 0x3c55849d	xfrm_policy_flush
+EXPORT_SYMBOL vmlinux 0x3c7227bf	complete_all
+EXPORT_SYMBOL vmlinux 0x3c9d1211	string_get_size
+EXPORT_SYMBOL vmlinux 0x3ca02967	elevator_exit
+EXPORT_SYMBOL vmlinux 0x3ca474c2	generic_file_readonly_mmap
+EXPORT_SYMBOL vmlinux 0x3cae383c	vlan_gro_frags
+EXPORT_SYMBOL vmlinux 0x3cb3931b	sg_copy_to_buffer
+EXPORT_SYMBOL vmlinux 0x3cbd3dad	blk_fetch_request
+EXPORT_SYMBOL vmlinux 0x3cc0a3bb	xfrm_spd_getinfo
+EXPORT_SYMBOL vmlinux 0x3cdfd972	open_exec
+EXPORT_SYMBOL vmlinux 0x3ce4ca6f	disable_irq
+EXPORT_SYMBOL vmlinux 0x3ce98dd6	skb_checksum_setup
+EXPORT_SYMBOL vmlinux 0x3cea9262	atm_init_aal5
+EXPORT_SYMBOL vmlinux 0x3cf6a820	tty_hangup
+EXPORT_SYMBOL vmlinux 0x3d0f0e4f	dmam_declare_coherent_memory
+EXPORT_SYMBOL vmlinux 0x3d2510b1	journal_force_commit_nested
+EXPORT_SYMBOL vmlinux 0x3d2959c2	neigh_update
+EXPORT_SYMBOL vmlinux 0x3d2f90d1	register_console
+EXPORT_SYMBOL vmlinux 0x3d4557cb	pci_set_dma_mask
+EXPORT_SYMBOL vmlinux 0x3d4ed225	dst_destroy
+EXPORT_SYMBOL vmlinux 0x3d58ab36	find_lock_page
+EXPORT_SYMBOL vmlinux 0x3d68bd4b	flow_cache_genid
+EXPORT_SYMBOL vmlinux 0x3d7c1ed7	msrs_alloc
+EXPORT_SYMBOL vmlinux 0x3d856c8a	dentry_unhash
+EXPORT_SYMBOL vmlinux 0x3da171f9	pci_mem_start
+EXPORT_SYMBOL vmlinux 0x3da5eb6d	kfifo_alloc
+EXPORT_SYMBOL vmlinux 0x3daa69da	vfs_lstat
+EXPORT_SYMBOL vmlinux 0x3df5a6d9	blk_rq_map_user
+EXPORT_SYMBOL vmlinux 0x3dfc216a	jbd2_journal_restart
+EXPORT_SYMBOL vmlinux 0x3e04bd1f	nf_ip_checksum
+EXPORT_SYMBOL vmlinux 0x3e06407d	inode_init_always
+EXPORT_SYMBOL vmlinux 0x3e1415b6	__blk_end_request_all
+EXPORT_SYMBOL vmlinux 0x3e1f073d	wait_for_completion_timeout
+EXPORT_SYMBOL vmlinux 0x3e219de6	try_wait_for_completion
+EXPORT_SYMBOL vmlinux 0x3e349dc2	tty_port_hangup
+EXPORT_SYMBOL vmlinux 0x3e383385	nf_hooks
+EXPORT_SYMBOL vmlinux 0x3e45e9ff	register_inetaddr_notifier
+EXPORT_SYMBOL vmlinux 0x3e4b296c	input_unregister_handler
+EXPORT_SYMBOL vmlinux 0x3e603e81	dev_set_allmulti
+EXPORT_SYMBOL vmlinux 0x3e7c51a5	kernel_sendpage
+EXPORT_SYMBOL vmlinux 0x3e84ae46	vmap
+EXPORT_SYMBOL vmlinux 0x3e899c9d	blk_limits_io_min
+EXPORT_SYMBOL vmlinux 0x3eb6cb1f	neigh_seq_stop
+EXPORT_SYMBOL vmlinux 0x3ec1d14e	tcf_hash_destroy
+EXPORT_SYMBOL vmlinux 0x3ec25907	file_fsync
+EXPORT_SYMBOL vmlinux 0x3ed63055	zlib_inflateReset
+EXPORT_SYMBOL vmlinux 0x3ee11db5	xfrm_register_mode
+EXPORT_SYMBOL vmlinux 0x3ee649bc	machine_to_phys_order
+EXPORT_SYMBOL vmlinux 0x3eef6816	bio_integrity_prep
+EXPORT_SYMBOL vmlinux 0x3ef62388	cont_write_begin
+EXPORT_SYMBOL vmlinux 0x3ef78d80	vm_get_page_prot
+EXPORT_SYMBOL vmlinux 0x3efc1b23	tty_port_close_start
+EXPORT_SYMBOL vmlinux 0x3f0546a8	ioread32_rep
+EXPORT_SYMBOL vmlinux 0x3f1899f1	up
+EXPORT_SYMBOL vmlinux 0x3f36a3bc	key_unlink
+EXPORT_SYMBOL vmlinux 0x3f3e0063	posix_lock_file
+EXPORT_SYMBOL vmlinux 0x3f4547a7	put_unused_fd
+EXPORT_SYMBOL vmlinux 0x3f5ea381	dev_load
+EXPORT_SYMBOL vmlinux 0x3f8bc7ed	netpoll_parse_options
+EXPORT_SYMBOL vmlinux 0x3f8d7e69	generic_file_direct_write
+EXPORT_SYMBOL vmlinux 0x3f98d0ff	dev_change_flags
+EXPORT_SYMBOL vmlinux 0x3fa8b8ee	tcf_em_tree_destroy
+EXPORT_SYMBOL vmlinux 0x3fea6118	save_mount_options
+EXPORT_SYMBOL vmlinux 0x3feb8322	sock_init_data
+EXPORT_SYMBOL vmlinux 0x3fec048f	sg_next
+EXPORT_SYMBOL vmlinux 0x3fec8341	skb_pull
+EXPORT_SYMBOL vmlinux 0x3ff62317	local_bh_disable
+EXPORT_SYMBOL vmlinux 0x400c4a34	free_buffer_head
+EXPORT_SYMBOL vmlinux 0x4034e66e	tcp_md5_hash_header
+EXPORT_SYMBOL vmlinux 0x40484826	dev_kfree_skb_irq
+EXPORT_SYMBOL vmlinux 0x40532ea5	phy_mii_ioctl
+EXPORT_SYMBOL vmlinux 0x4059792f	print_hex_dump
+EXPORT_SYMBOL vmlinux 0x405c1144	get_seconds
+EXPORT_SYMBOL vmlinux 0x406590db	pneigh_enqueue
+EXPORT_SYMBOL vmlinux 0x40661369	ppp_unregister_channel
+EXPORT_SYMBOL vmlinux 0x409873e3	tty_termios_baud_rate
+EXPORT_SYMBOL vmlinux 0x40b768f2	input_allocate_device
+EXPORT_SYMBOL vmlinux 0x40ba65c2	call_usermodehelper_setkeys
+EXPORT_SYMBOL vmlinux 0x40bbb4d6	skb_copy_datagram_from_iovec
+EXPORT_SYMBOL vmlinux 0x40ccd1b5	dqget
+EXPORT_SYMBOL vmlinux 0x40e3a9ac	wireless_send_event
+EXPORT_SYMBOL vmlinux 0x4101bbde	param_set_copystring
+EXPORT_SYMBOL vmlinux 0x4108e69a	fb_match_mode
+EXPORT_SYMBOL vmlinux 0x410f750d	tcp_md5_hash_skb_data
+EXPORT_SYMBOL vmlinux 0x41166725	inet_frags_init_net
+EXPORT_SYMBOL vmlinux 0x412963ad	pci_find_capability
+EXPORT_SYMBOL vmlinux 0x41344088	param_get_charp
+EXPORT_SYMBOL vmlinux 0x413f1244	security_path_truncate
+EXPORT_SYMBOL vmlinux 0x413f6be7	serio_interrupt
+EXPORT_SYMBOL vmlinux 0x41482d8b	strndup_user
+EXPORT_SYMBOL vmlinux 0x415b7448	copy_strings_kernel
+EXPORT_SYMBOL vmlinux 0x416983d9	netdev_fix_features
+EXPORT_SYMBOL vmlinux 0x4185cf4b	radix_tree_lookup_slot
+EXPORT_SYMBOL vmlinux 0x4188d439	neigh_rand_reach_time
+EXPORT_SYMBOL vmlinux 0x41a9c68d	_spin_trylock_bh
+EXPORT_SYMBOL vmlinux 0x41c14ad3	vfs_quota_off
+EXPORT_SYMBOL vmlinux 0x41c5474d	tcp_read_sock
+EXPORT_SYMBOL vmlinux 0x41de1899	delayed_slow_work_enqueue
+EXPORT_SYMBOL vmlinux 0x41ebe42a	udp_disconnect
+EXPORT_SYMBOL vmlinux 0x4211c3c1	zlib_inflateInit2
+EXPORT_SYMBOL vmlinux 0x4211f9c0	input_set_capability
+EXPORT_SYMBOL vmlinux 0x421a81c5	x86_dma_fallback_dev
+EXPORT_SYMBOL vmlinux 0x42224298	sscanf
+EXPORT_SYMBOL vmlinux 0x42595e58	vgacon_text_force
+EXPORT_SYMBOL vmlinux 0x4292364c	schedule
+EXPORT_SYMBOL vmlinux 0x4298e307	tcp_ioctl
+EXPORT_SYMBOL vmlinux 0x42c2c709	kset_register
+EXPORT_SYMBOL vmlinux 0x42c8de35	ioremap_nocache
+EXPORT_SYMBOL vmlinux 0x42f9a99c	rtc_dev_update_irq_enable_emul
+EXPORT_SYMBOL vmlinux 0x4302d0eb	free_pages
+EXPORT_SYMBOL vmlinux 0x431cff0b	nobh_writepage
+EXPORT_SYMBOL vmlinux 0x4323610d	block_is_partially_uptodate
+EXPORT_SYMBOL vmlinux 0x4333eadb	param_set_short
+EXPORT_SYMBOL vmlinux 0x43356acc	kfree_skb
+EXPORT_SYMBOL vmlinux 0x433a00e5	vlan_dev_real_dev
+EXPORT_SYMBOL vmlinux 0x434fa55c	release_console_sem
+EXPORT_SYMBOL vmlinux 0x4354013d	ip_fragment
+EXPORT_SYMBOL vmlinux 0x436c2179	iowrite32
+EXPORT_SYMBOL vmlinux 0x4384ae1d	bio_map_user
+EXPORT_SYMBOL vmlinux 0x4386b7d5	pcim_enable_device
+EXPORT_SYMBOL vmlinux 0x43ab66c3	param_array_get
+EXPORT_SYMBOL vmlinux 0x43b084dd	eth_header_cache_update
+EXPORT_SYMBOL vmlinux 0x43c11fc1	dcache_dir_open
+EXPORT_SYMBOL vmlinux 0x43f41135	sock_get_timestamp
+EXPORT_SYMBOL vmlinux 0x43f9844f	dma_ops
+EXPORT_SYMBOL vmlinux 0x43fbde82	bio_integrity_set_tag
+EXPORT_SYMBOL vmlinux 0x44093545	xfrm_unregister_km
+EXPORT_SYMBOL vmlinux 0x44096a94	swiotlb_sync_single_for_cpu
+EXPORT_SYMBOL vmlinux 0x440afe0a	vfs_dq_transfer
+EXPORT_SYMBOL vmlinux 0x4415ca9e	pci_unregister_driver
+EXPORT_SYMBOL vmlinux 0x44161c19	unregister_shrinker
+EXPORT_SYMBOL vmlinux 0x44314efb	radix_tree_gang_lookup_tag_slot
+EXPORT_SYMBOL vmlinux 0x444779c4	nla_find
+EXPORT_SYMBOL vmlinux 0x446ae793	unlock_buffer
+EXPORT_SYMBOL vmlinux 0x448a24a8	xfrm_state_delete
+EXPORT_SYMBOL vmlinux 0x44b694f9	skb_clone
+EXPORT_SYMBOL vmlinux 0x44b911c3	rb_replace_node
+EXPORT_SYMBOL vmlinux 0x44d66f9c	mpage_writepages
+EXPORT_SYMBOL vmlinux 0x44e9a829	match_token
+EXPORT_SYMBOL vmlinux 0x44f21bea	idr_for_each
+EXPORT_SYMBOL vmlinux 0x45088dcc	send_sig_info
+EXPORT_SYMBOL vmlinux 0x4514196c	find_or_create_page
+EXPORT_SYMBOL vmlinux 0x45215fec	uart_suspend_port
+EXPORT_SYMBOL vmlinux 0x453c8403	pci_msi_enabled
+EXPORT_SYMBOL vmlinux 0x45450063	mod_timer
+EXPORT_SYMBOL vmlinux 0x4550ba8a	register_cpu_notifier
+EXPORT_SYMBOL vmlinux 0x455e19f4	tcp_shutdown
+EXPORT_SYMBOL vmlinux 0x456c03a0	pipe_to_file
+EXPORT_SYMBOL vmlinux 0x4575315d	utf8s_to_utf16s
+EXPORT_SYMBOL vmlinux 0x4588103e	__secpath_destroy
+EXPORT_SYMBOL vmlinux 0x45947727	param_array_set
+EXPORT_SYMBOL vmlinux 0x45d11c43	down_interruptible
+EXPORT_SYMBOL vmlinux 0x45d55543	down_write
+EXPORT_SYMBOL vmlinux 0x45e29319	backlight_device_register
+EXPORT_SYMBOL vmlinux 0x46085e4f	add_timer
+EXPORT_SYMBOL vmlinux 0x462a2e75	match_strlcpy
+EXPORT_SYMBOL vmlinux 0x466c14a7	__delay
+EXPORT_SYMBOL vmlinux 0x46715b03	dmam_alloc_coherent
+EXPORT_SYMBOL vmlinux 0x46acb06a	register_cdrom
+EXPORT_SYMBOL vmlinux 0x46c28962	unregister_sysctl_table
+EXPORT_SYMBOL vmlinux 0x470170a9	unregister_netdevice
+EXPORT_SYMBOL vmlinux 0x4712dc73	__dev_get_by_index
+EXPORT_SYMBOL vmlinux 0x4717e5df	tcp_rcv_state_process
+EXPORT_SYMBOL vmlinux 0x472d2a9a	radix_tree_lookup
+EXPORT_SYMBOL vmlinux 0x4737051b	unregister_netdev
+EXPORT_SYMBOL vmlinux 0x47395298	rtnl_unicast
+EXPORT_SYMBOL vmlinux 0x475100c2	inet_get_local_port_range
+EXPORT_SYMBOL vmlinux 0x479c3c86	find_next_zero_bit
+EXPORT_SYMBOL vmlinux 0x47f3bf8f	input_release_device
+EXPORT_SYMBOL vmlinux 0x485314af	xfrm_state_lookup
+EXPORT_SYMBOL vmlinux 0x4859b8bb	rtc_year_days
+EXPORT_SYMBOL vmlinux 0x486b6407	hweight64
+EXPORT_SYMBOL vmlinux 0x487db209	dma_pool_free
+EXPORT_SYMBOL vmlinux 0x48ecee57	generic_write_checks
+EXPORT_SYMBOL vmlinux 0x493cc075	uart_add_one_port
+EXPORT_SYMBOL vmlinux 0x494058f2	remove_arg_zero
+EXPORT_SYMBOL vmlinux 0x49439411	genl_unregister_family
+EXPORT_SYMBOL vmlinux 0x49444d90	sk_stream_wait_connect
+EXPORT_SYMBOL vmlinux 0x49603fb8	security_sb_copy_data
+EXPORT_SYMBOL vmlinux 0x496da9fe	__register_chrdev
+EXPORT_SYMBOL vmlinux 0x4971553a	tcf_exts_dump_stats
+EXPORT_SYMBOL vmlinux 0x49b2242b	keyring_clear
+EXPORT_SYMBOL vmlinux 0x49b2d395	simple_fsync
+EXPORT_SYMBOL vmlinux 0x49da9a9a	_read_unlock_bh
+EXPORT_SYMBOL vmlinux 0x49e182c0	param_get_string
+EXPORT_SYMBOL vmlinux 0x4a21b983	skb_add_rx_frag
+EXPORT_SYMBOL vmlinux 0x4a26b03f	revert_creds
+EXPORT_SYMBOL vmlinux 0x4a3482fe	vfs_read
+EXPORT_SYMBOL vmlinux 0x4a358252	__bitmap_subset
+EXPORT_SYMBOL vmlinux 0x4a3e8ef9	udp_ioctl
+EXPORT_SYMBOL vmlinux 0x4a73fef1	mdiobus_scan
+EXPORT_SYMBOL vmlinux 0x4a971ec7	radix_tree_delete
+EXPORT_SYMBOL vmlinux 0x4a99248b	pci_find_parent_resource
+EXPORT_SYMBOL vmlinux 0x4aa0fa9d	dm_io_client_destroy
+EXPORT_SYMBOL vmlinux 0x4ab4bf86	skb_queue_head
+EXPORT_SYMBOL vmlinux 0x4acd93d3	release_resource
+EXPORT_SYMBOL vmlinux 0x4ada7de0	dev_get_by_flags
+EXPORT_SYMBOL vmlinux 0x4af3033e	tcf_action_exec
+EXPORT_SYMBOL vmlinux 0x4af89996	phy_stop
+EXPORT_SYMBOL vmlinux 0x4b025501	elv_dispatch_add_tail
+EXPORT_SYMBOL vmlinux 0x4b07e779	_spin_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x4b34fbf5	block_all_signals
+EXPORT_SYMBOL vmlinux 0x4b55a225	d_genocide
+EXPORT_SYMBOL vmlinux 0x4b676228	skb_push
+EXPORT_SYMBOL vmlinux 0x4b6ec757	netlink_kernel_release
+EXPORT_SYMBOL vmlinux 0x4b8d21ee	tcf_hash_lookup
+EXPORT_SYMBOL vmlinux 0x4b93ce79	blk_queue_max_segment_size
+EXPORT_SYMBOL vmlinux 0x4bad2e13	ps2_cmd_aborted
+EXPORT_SYMBOL vmlinux 0x4bbc3e5f	pm_flags
+EXPORT_SYMBOL vmlinux 0x4bc27280	grab_cache_page_nowait
+EXPORT_SYMBOL vmlinux 0x4bcf9090	bdi_init
+EXPORT_SYMBOL vmlinux 0x4be9ef1b	log_start_commit
+EXPORT_SYMBOL vmlinux 0x4bfee15a	atomic64_set
+EXPORT_SYMBOL vmlinux 0x4c04afdc	submit_bio
+EXPORT_SYMBOL vmlinux 0x4c1182cb	bitmap_scnprintf
+EXPORT_SYMBOL vmlinux 0x4c1ab8c8	serial8250_register_port
+EXPORT_SYMBOL vmlinux 0x4c1b965c	gen_replace_estimator
+EXPORT_SYMBOL vmlinux 0x4c1da808	ps2_sendbyte
+EXPORT_SYMBOL vmlinux 0x4c201418	__task_pid_nr_ns
+EXPORT_SYMBOL vmlinux 0x4c489bdc	netlink_rcv_skb
+EXPORT_SYMBOL vmlinux 0x4cb1d02c	inetdev_by_index
+EXPORT_SYMBOL vmlinux 0x4cba2e02	block_invalidatepage
+EXPORT_SYMBOL vmlinux 0x4cbbd171	__bitmap_weight
+EXPORT_SYMBOL vmlinux 0x4d3c153f	sigprocmask
+EXPORT_SYMBOL vmlinux 0x4d45b8b3	phy_connect
+EXPORT_SYMBOL vmlinux 0x4d88ff6a	dmam_pool_create
+EXPORT_SYMBOL vmlinux 0x4d9c564f	put_mnt_ns
+EXPORT_SYMBOL vmlinux 0x4db389ad	dev_disable_lro
+EXPORT_SYMBOL vmlinux 0x4dc45be9	nf_log_unbind_pf
+EXPORT_SYMBOL vmlinux 0x4deaf5ee	sock_alloc_send_skb
+EXPORT_SYMBOL vmlinux 0x4df119fa	__bitmap_parse
+EXPORT_SYMBOL vmlinux 0x4df5a399	init_file
+EXPORT_SYMBOL vmlinux 0x4dfc564b	textsearch_find_continuous
+EXPORT_SYMBOL vmlinux 0x4e069249	security_tun_dev_post_create
+EXPORT_SYMBOL vmlinux 0x4e3567f7	match_int
+EXPORT_SYMBOL vmlinux 0x4e6e8ea7	fg_console
+EXPORT_SYMBOL vmlinux 0x4e717d0d	set_security_override
+EXPORT_SYMBOL vmlinux 0x4e830a3e	strnicmp
+EXPORT_SYMBOL vmlinux 0x4ea3c643	__netif_schedule
+EXPORT_SYMBOL vmlinux 0x4eae8f03	skb_copy
+EXPORT_SYMBOL vmlinux 0x4ee270dc	journal_start_commit
+EXPORT_SYMBOL vmlinux 0x4ef511c6	i8042_check_port_owner
+EXPORT_SYMBOL vmlinux 0x4f128ce5	alloc_disk
+EXPORT_SYMBOL vmlinux 0x4f1cd128	security_tun_dev_create
+EXPORT_SYMBOL vmlinux 0x4f2bc09b	sk_alloc
+EXPORT_SYMBOL vmlinux 0x4f2ca718	mutex_unlock
+EXPORT_SYMBOL vmlinux 0x4f476e96	init_cdrom_command
+EXPORT_SYMBOL vmlinux 0x4f5438c1	idle_halt
+EXPORT_SYMBOL vmlinux 0x4f7c74ef	set_user_nice
+EXPORT_SYMBOL vmlinux 0x4f88e931	fb_find_mode
+EXPORT_SYMBOL vmlinux 0x4fa0c8d9	pci_restore_state
+EXPORT_SYMBOL vmlinux 0x4fadacb0	w1_register_family
+EXPORT_SYMBOL vmlinux 0x4fdee897	i8042_command
+EXPORT_SYMBOL vmlinux 0x501b778b	create_proc_entry
+EXPORT_SYMBOL vmlinux 0x50211ee3	tcp_free_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x5021baf9	update_region
+EXPORT_SYMBOL vmlinux 0x5024ef1b	ip_queue_xmit
+EXPORT_SYMBOL vmlinux 0x502c8d93	dma_pool_alloc
+EXPORT_SYMBOL vmlinux 0x503e86ac	dm_table_get_mode
+EXPORT_SYMBOL vmlinux 0x505d1be5	sk_receive_skb
+EXPORT_SYMBOL vmlinux 0x506746b6	getrawmonotonic
+EXPORT_SYMBOL vmlinux 0x509ed1c4	set_bdi_congested
+EXPORT_SYMBOL vmlinux 0x50b058f8	ip_ct_attach
+EXPORT_SYMBOL vmlinux 0x51063f85	sock_map_fd
+EXPORT_SYMBOL vmlinux 0x510babd4	sg_miter_stop
+EXPORT_SYMBOL vmlinux 0x51183b94	vfs_symlink
+EXPORT_SYMBOL vmlinux 0x5118c382	secure_dccp_sequence_number
+EXPORT_SYMBOL vmlinux 0x513f8469	dev_unicast_unsync
+EXPORT_SYMBOL vmlinux 0x5152e605	memcmp
+EXPORT_SYMBOL vmlinux 0x5161af2d	no_llseek
+EXPORT_SYMBOL vmlinux 0x517dd732	km_new_mapping
+EXPORT_SYMBOL vmlinux 0x51836be1	jbd2_journal_forget
+EXPORT_SYMBOL vmlinux 0x5186518f	profile_pc
+EXPORT_SYMBOL vmlinux 0x519c9204	pci_pme_capable
+EXPORT_SYMBOL vmlinux 0x51b87d2e	security_task_getsecid
+EXPORT_SYMBOL vmlinux 0x51dce73b	xfrm_state_walk_init
+EXPORT_SYMBOL vmlinux 0x51e1e5b3	pcim_iomap_regions
+EXPORT_SYMBOL vmlinux 0x51ef33b8	kstrndup
+EXPORT_SYMBOL vmlinux 0x52026cdf	security_sb_parse_opts_str
+EXPORT_SYMBOL vmlinux 0x520f0e60	pci_dev_driver
+EXPORT_SYMBOL vmlinux 0x521fa455	get_phy_device
+EXPORT_SYMBOL vmlinux 0x5233b17f	genl_register_ops
+EXPORT_SYMBOL vmlinux 0x526956a0	cad_pid
+EXPORT_SYMBOL vmlinux 0x526ce999	blk_insert_request
+EXPORT_SYMBOL vmlinux 0x52760ca9	getnstimeofday
+EXPORT_SYMBOL vmlinux 0x5285d6e7	llc_mac_hdr_init
+EXPORT_SYMBOL vmlinux 0x528c709d	simple_read_from_buffer
+EXPORT_SYMBOL vmlinux 0x52a58c24	ifla_policy
+EXPORT_SYMBOL vmlinux 0x52bea267	sk_stop_timer
+EXPORT_SYMBOL vmlinux 0x52d7b2fd	llc_sap_list
+EXPORT_SYMBOL vmlinux 0x52ebb126	param_get_ushort
+EXPORT_SYMBOL vmlinux 0x52f98cf9	do_munmap
+EXPORT_SYMBOL vmlinux 0x530df5ce	unlock_rename
+EXPORT_SYMBOL vmlinux 0x531b604e	__virt_addr_valid
+EXPORT_SYMBOL vmlinux 0x53284136	jbd2_journal_start
+EXPORT_SYMBOL vmlinux 0x53326531	mempool_alloc_pages
+EXPORT_SYMBOL vmlinux 0x5369eaa0	mdiobus_read
+EXPORT_SYMBOL vmlinux 0x536e2839	noop_qdisc
+EXPORT_SYMBOL vmlinux 0x537650ab	neigh_parms_alloc
+EXPORT_SYMBOL vmlinux 0x537f6779	blk_rq_init
+EXPORT_SYMBOL vmlinux 0x53a6a414	filemap_fdatawrite
+EXPORT_SYMBOL vmlinux 0x53af4ae0	pipe_lock
+EXPORT_SYMBOL vmlinux 0x53c0767c	sk_chk_filter
+EXPORT_SYMBOL vmlinux 0x53c1d122	thermal_zone_unbind_cooling_device
+EXPORT_SYMBOL vmlinux 0x53cb1c77	security_file_permission
+EXPORT_SYMBOL vmlinux 0x53f00341	get_empty_filp
+EXPORT_SYMBOL vmlinux 0x53f81c63	fget
+EXPORT_SYMBOL vmlinux 0x54093c3e	iw_handler_set_spy
+EXPORT_SYMBOL vmlinux 0x5409c7b0	simple_lookup
+EXPORT_SYMBOL vmlinux 0x5416b58c	blk_queue_update_dma_pad
+EXPORT_SYMBOL vmlinux 0x541dfef4	atomic64_inc
+EXPORT_SYMBOL vmlinux 0x54290dc9	nla_validate
+EXPORT_SYMBOL vmlinux 0x54682498	tcp_setsockopt
+EXPORT_SYMBOL vmlinux 0x54820bde	dquot_commit_info
+EXPORT_SYMBOL vmlinux 0x54a6d074	atomic64_dec
+EXPORT_SYMBOL vmlinux 0x54e6fcdd	net_enable_timestamp
+EXPORT_SYMBOL vmlinux 0x550de00a	set_pages_nx
+EXPORT_SYMBOL vmlinux 0x5521ce14	dev_get_by_index
+EXPORT_SYMBOL vmlinux 0x55631890	pci_request_regions_exclusive
+EXPORT_SYMBOL vmlinux 0x556e52c1	register_netdevice
+EXPORT_SYMBOL vmlinux 0x5585da95	tcp_parse_options
+EXPORT_SYMBOL vmlinux 0x55872342	km_state_expired
+EXPORT_SYMBOL vmlinux 0x5594be03	bitmap_remap
+EXPORT_SYMBOL vmlinux 0x5598aabc	sock_create_lite
+EXPORT_SYMBOL vmlinux 0x559f8481	eth_validate_addr
+EXPORT_SYMBOL vmlinux 0x55c0148d	take_over_console
+EXPORT_SYMBOL vmlinux 0x55ea333c	pci_find_next_bus
+EXPORT_SYMBOL vmlinux 0x55f3d7d7	iov_iter_copy_from_user
+EXPORT_SYMBOL vmlinux 0x5600904f	fb_get_color_depth
+EXPORT_SYMBOL vmlinux 0x5603cf43	do_settimeofday
+EXPORT_SYMBOL vmlinux 0x5610247c	pci_try_set_mwi
+EXPORT_SYMBOL vmlinux 0x5614022e	pci_claim_resource
+EXPORT_SYMBOL vmlinux 0x5614b010	xfrm_policy_walk_done
+EXPORT_SYMBOL vmlinux 0x5635a60a	vmalloc_user
+EXPORT_SYMBOL vmlinux 0x5656777c	fb_firmware_edid
+EXPORT_SYMBOL vmlinux 0x56851ba2	bh_uptodate_or_lock
+EXPORT_SYMBOL vmlinux 0x56908aea	dquot_reserve_space
+EXPORT_SYMBOL vmlinux 0x56aa6b41	ilookup5
+EXPORT_SYMBOL vmlinux 0x56af16f6	netlink_broadcast
+EXPORT_SYMBOL vmlinux 0x56c83939	elv_rb_find
+EXPORT_SYMBOL vmlinux 0x56cc4ead	ip_nat_decode_session
+EXPORT_SYMBOL vmlinux 0x56ccb61e	audit_log_format
+EXPORT_SYMBOL vmlinux 0x56d818d5	tcf_exts_dump
+EXPORT_SYMBOL vmlinux 0x56ec4cf6	pci_set_mwi
+EXPORT_SYMBOL vmlinux 0x56f494e0	smp_call_function
+EXPORT_SYMBOL vmlinux 0x5705088a	__vmalloc
+EXPORT_SYMBOL vmlinux 0x572e85d4	blk_lookup_devt
+EXPORT_SYMBOL vmlinux 0x578d313d	generic_read_dir
+EXPORT_SYMBOL vmlinux 0x57a6504e	vsnprintf
+EXPORT_SYMBOL vmlinux 0x57adf756	per_cpu__this_cpu_off
+EXPORT_SYMBOL vmlinux 0x57b57ebe	jiffies_to_timespec
+EXPORT_SYMBOL vmlinux 0x57b83c5a	udp_poll
+EXPORT_SYMBOL vmlinux 0x57d24e95	pci_set_dma_max_seg_size
+EXPORT_SYMBOL vmlinux 0x57d92b8d	pci_add_new_bus
+EXPORT_SYMBOL vmlinux 0x57db7242	mangle_path
+EXPORT_SYMBOL vmlinux 0x580ba6cb	neigh_sysctl_register
+EXPORT_SYMBOL vmlinux 0x5816956b	tcp_v4_conn_request
+EXPORT_SYMBOL vmlinux 0x582e7e32	free_netdev
+EXPORT_SYMBOL vmlinux 0x5838f6c9	rtc_valid_tm
+EXPORT_SYMBOL vmlinux 0x584738f9	rdmsr_safe_on_cpu
+EXPORT_SYMBOL vmlinux 0x5857b225	ioread16_rep
+EXPORT_SYMBOL vmlinux 0x5857e434	groups_free
+EXPORT_SYMBOL vmlinux 0x585d961a	__inc_zone_page_state
+EXPORT_SYMBOL vmlinux 0x586a0c73	get_fs_type
+EXPORT_SYMBOL vmlinux 0x586d1f21	register_netdev
+EXPORT_SYMBOL vmlinux 0x58780e9c	pci_back_from_sleep
+EXPORT_SYMBOL vmlinux 0x588bfbf6	aio_put_req
+EXPORT_SYMBOL vmlinux 0x58e36b12	dev_get_drvdata
+EXPORT_SYMBOL vmlinux 0x58f208fc	ppp_register_channel
+EXPORT_SYMBOL vmlinux 0x591f6dc3	tcp_alloc_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x5934392b	fb_register_client
+EXPORT_SYMBOL vmlinux 0x594bf15b	ioport_map
+EXPORT_SYMBOL vmlinux 0x595e1be1	inet_frag_kill
+EXPORT_SYMBOL vmlinux 0x59afed11	seq_path
+EXPORT_SYMBOL vmlinux 0x59bd2118	lro_flush_all
+EXPORT_SYMBOL vmlinux 0x59c32e62	pcie_port_service_register
+EXPORT_SYMBOL vmlinux 0x59d696b6	register_module_notifier
+EXPORT_SYMBOL vmlinux 0x59df717d	simple_transaction_release
+EXPORT_SYMBOL vmlinux 0x59e97720	phy_ethtool_gset
+EXPORT_SYMBOL vmlinux 0x59f37c4d	get_disk
+EXPORT_SYMBOL vmlinux 0x59f70302	pci_release_regions
+EXPORT_SYMBOL vmlinux 0x5a2811e9	__inet6_hash
+EXPORT_SYMBOL vmlinux 0x5a316b73	jbd2_journal_flush
+EXPORT_SYMBOL vmlinux 0x5a4896a8	__put_user_2
+EXPORT_SYMBOL vmlinux 0x5a4d7882	pfifo_qdisc_ops
+EXPORT_SYMBOL vmlinux 0x5a57d155	__percpu_counter_init
+EXPORT_SYMBOL vmlinux 0x5a744b86	netlink_set_nonroot
+EXPORT_SYMBOL vmlinux 0x5a89b886	posix_test_lock
+EXPORT_SYMBOL vmlinux 0x5a96f566	fb_set_suspend
+EXPORT_SYMBOL vmlinux 0x5aa806b4	pci_wake_from_d3
+EXPORT_SYMBOL vmlinux 0x5b19634d	div_s64_rem
+EXPORT_SYMBOL vmlinux 0x5b4e1e9f	vfs_writev
+EXPORT_SYMBOL vmlinux 0x5b558760	__brelse
+EXPORT_SYMBOL vmlinux 0x5b570f3f	jbd2_journal_start_commit
+EXPORT_SYMBOL vmlinux 0x5b5a2a32	smp_call_function_many
+EXPORT_SYMBOL vmlinux 0x5b6e5589	input_filter_device
+EXPORT_SYMBOL vmlinux 0x5b78ff08	pagecache_write_end
+EXPORT_SYMBOL vmlinux 0x5b9af64c	lookup_hash
+EXPORT_SYMBOL vmlinux 0x5bba1715	seq_open_private
+EXPORT_SYMBOL vmlinux 0x5bbae23a	unregister_snap_client
+EXPORT_SYMBOL vmlinux 0x5bc74779	input_event
+EXPORT_SYMBOL vmlinux 0x5be25bb5	pci_request_regions
+EXPORT_SYMBOL vmlinux 0x5bf0005b	dev_remove_pack
+EXPORT_SYMBOL vmlinux 0x5bfd9a61	dcache_dir_close
+EXPORT_SYMBOL vmlinux 0x5c0ad5de	dm_kcopyd_client_destroy
+EXPORT_SYMBOL vmlinux 0x5c611c0c	tty_driver_flush_buffer
+EXPORT_SYMBOL vmlinux 0x5c7697e1	eth_change_mtu
+EXPORT_SYMBOL vmlinux 0x5c860b59	xfrm_dst_ifdown
+EXPORT_SYMBOL vmlinux 0x5c86bde7	sock_create
+EXPORT_SYMBOL vmlinux 0x5c91f0e6	inode_add_rsv_space
+EXPORT_SYMBOL vmlinux 0x5c95b6a1	security_path_rmdir
+EXPORT_SYMBOL vmlinux 0x5d28e159	invalidate_bdev
+EXPORT_SYMBOL vmlinux 0x5d5c81d9	pci_release_region
+EXPORT_SYMBOL vmlinux 0x5d7f841e	tcp_v4_md5_do_del
+EXPORT_SYMBOL vmlinux 0x5def0776	inet_dgram_ops
+EXPORT_SYMBOL vmlinux 0x5e0e1696	blk_recount_segments
+EXPORT_SYMBOL vmlinux 0x5e6160b5	page_readlink
+EXPORT_SYMBOL vmlinux 0x5e8532b4	w1_add_master_device
+EXPORT_SYMBOL vmlinux 0x5e911dc5	skb_find_text
+EXPORT_SYMBOL vmlinux 0x5e95b1cd	current_umask
+EXPORT_SYMBOL vmlinux 0x5ea520c5	tcp_select_initial_window
+EXPORT_SYMBOL vmlinux 0x5ed040b0	pm_set_vt_switch
+EXPORT_SYMBOL vmlinux 0x5edd0762	bin2bcd
+EXPORT_SYMBOL vmlinux 0x5efeb640	ethtool_op_set_sg
+EXPORT_SYMBOL vmlinux 0x5f2708b3	inet_shutdown
+EXPORT_SYMBOL vmlinux 0x5f270de4	eth_mac_addr
+EXPORT_SYMBOL vmlinux 0x5f46ce93	inet_proto_csum_replace4
+EXPORT_SYMBOL vmlinux 0x5f499f6a	put_tty_driver
+EXPORT_SYMBOL vmlinux 0x5f5393a1	request_key
+EXPORT_SYMBOL vmlinux 0x5f56db66	per_cpu__ftrace_event_seq
+EXPORT_SYMBOL vmlinux 0x5f684171	mdiobus_register
+EXPORT_SYMBOL vmlinux 0x5f8b8cef	tty_schedule_flip
+EXPORT_SYMBOL vmlinux 0x5fb5a96a	dm_put_device
+EXPORT_SYMBOL vmlinux 0x5fb60ac6	dquot_free_space
+EXPORT_SYMBOL vmlinux 0x600683d3	do_unblank_screen
+EXPORT_SYMBOL vmlinux 0x60282bf4	journal_check_available_features
+EXPORT_SYMBOL vmlinux 0x6039f711	dm_io
+EXPORT_SYMBOL vmlinux 0x6043092c	atomic64_dec_and_test
+EXPORT_SYMBOL vmlinux 0x609f1c7e	synchronize_net
+EXPORT_SYMBOL vmlinux 0x60a0ebad	__tracepoint_kmem_cache_alloc_node
+EXPORT_SYMBOL vmlinux 0x60a32ea9	pm_power_off
+EXPORT_SYMBOL vmlinux 0x60ce41ba	journal_check_used_features
+EXPORT_SYMBOL vmlinux 0x60d1a037	blk_register_region
+EXPORT_SYMBOL vmlinux 0x61138cb5	blkdev_issue_discard
+EXPORT_SYMBOL vmlinux 0x612390ad	netpoll_set_trap
+EXPORT_SYMBOL vmlinux 0x615b7153	journal_forget
+EXPORT_SYMBOL vmlinux 0x618d8299	set_notify_swap_entry_free
+EXPORT_SYMBOL vmlinux 0x6194fedf	del_gendisk
+EXPORT_SYMBOL vmlinux 0x61b7b126	simple_strtoull
+EXPORT_SYMBOL vmlinux 0x61e6041b	fb_blank
+EXPORT_SYMBOL vmlinux 0x62134063	d_alloc_name
+EXPORT_SYMBOL vmlinux 0x6223d4f2	__pci_register_driver
+EXPORT_SYMBOL vmlinux 0x6226b9fa	machine_to_phys_mapping
+EXPORT_SYMBOL vmlinux 0x622ff6d8	jbd2_journal_begin_ordered_truncate
+EXPORT_SYMBOL vmlinux 0x6241a2ab	__copy_from_user_ll_nocache
+EXPORT_SYMBOL vmlinux 0x625abf76	__generic_block_fiemap
+EXPORT_SYMBOL vmlinux 0x62645ade	insert_inode_locked
+EXPORT_SYMBOL vmlinux 0x62737e1d	sock_unregister
+EXPORT_SYMBOL vmlinux 0x62827bec	security_secctx_to_secid
+EXPORT_SYMBOL vmlinux 0x62abd06c	pci_get_slot
+EXPORT_SYMBOL vmlinux 0x62d0802b	drop_super
+EXPORT_SYMBOL vmlinux 0x62dbfbfc	sync_mapping_buffers
+EXPORT_SYMBOL vmlinux 0x62fc37cc	default_file_splice_read
+EXPORT_SYMBOL vmlinux 0x6307fc98	del_timer
+EXPORT_SYMBOL vmlinux 0x6331d18d	eth_header
+EXPORT_SYMBOL vmlinux 0x63505f2a	locks_copy_lock
+EXPORT_SYMBOL vmlinux 0x6357085d	__set_page_dirty_nobuffers
+EXPORT_SYMBOL vmlinux 0x63ecad53	register_netdevice_notifier
+EXPORT_SYMBOL vmlinux 0x63efc536	radix_tree_prev_hole
+EXPORT_SYMBOL vmlinux 0x6403e338	tcp_memory_pressure
+EXPORT_SYMBOL vmlinux 0x640a7078	posix_acl_create_masq
+EXPORT_SYMBOL vmlinux 0x642e54ac	__wake_up
+EXPORT_SYMBOL vmlinux 0x644eca94	netdev_class_create_file
+EXPORT_SYMBOL vmlinux 0x64526a93	atomic64_sub_return
+EXPORT_SYMBOL vmlinux 0x6466a1e6	mempool_alloc
+EXPORT_SYMBOL vmlinux 0x646a0911	simple_transaction_set
+EXPORT_SYMBOL vmlinux 0x647e991a	dm_get_device
+EXPORT_SYMBOL vmlinux 0x6486a901	revalidate_disk
+EXPORT_SYMBOL vmlinux 0x64978b56	block_commit_write
+EXPORT_SYMBOL vmlinux 0x6498035f	do_sync_read
+EXPORT_SYMBOL vmlinux 0x64999478	congestion_wait
+EXPORT_SYMBOL vmlinux 0x64b40d90	__generic_file_aio_write
+EXPORT_SYMBOL vmlinux 0x64be3ecd	alloc_fddidev
+EXPORT_SYMBOL vmlinux 0x64eae7ad	set_memory_array_wb
+EXPORT_SYMBOL vmlinux 0x64eecf44	security_inode_notifysecctx
+EXPORT_SYMBOL vmlinux 0x650fb346	add_wait_queue
+EXPORT_SYMBOL vmlinux 0x65165bde	pcie_get_readrq
+EXPORT_SYMBOL vmlinux 0x65171b0c	register_gifconf
+EXPORT_SYMBOL vmlinux 0x651a4139	test_taint
+EXPORT_SYMBOL vmlinux 0x651b3526	user_revoke
+EXPORT_SYMBOL vmlinux 0x652db5bf	ps2_drain
+EXPORT_SYMBOL vmlinux 0x6537917e	__mutex_init
+EXPORT_SYMBOL vmlinux 0x65408378	zlib_inflate_blob
+EXPORT_SYMBOL vmlinux 0x65414e67	dev_valid_name
+EXPORT_SYMBOL vmlinux 0x654c8d77	bio_pair_release
+EXPORT_SYMBOL vmlinux 0x6571ccce	vfs_fsync
+EXPORT_SYMBOL vmlinux 0x659d213a	vc_cons
+EXPORT_SYMBOL vmlinux 0x65e86824	ppp_channel_index
+EXPORT_SYMBOL vmlinux 0x66065aa9	d_rehash
+EXPORT_SYMBOL vmlinux 0x6652aded	vcc_insert_socket
+EXPORT_SYMBOL vmlinux 0x667c8a0f	ip_mc_join_group
+EXPORT_SYMBOL vmlinux 0x66855745	freeze_bdev
+EXPORT_SYMBOL vmlinux 0x6687c8a0	get_sb_pseudo
+EXPORT_SYMBOL vmlinux 0x668da8d5	zlib_inflateIncomp
+EXPORT_SYMBOL vmlinux 0x6691bf99	__bio_clone
+EXPORT_SYMBOL vmlinux 0x6697a874	ethtool_op_get_tso
+EXPORT_SYMBOL vmlinux 0x669e1587	pci_find_bus
+EXPORT_SYMBOL vmlinux 0x66a4ced3	register_sysrq_key
+EXPORT_SYMBOL vmlinux 0x66ea40ee	kernel_read
+EXPORT_SYMBOL vmlinux 0x67053080	current_kernel_time
+EXPORT_SYMBOL vmlinux 0x6729d3df	__get_user_4
+EXPORT_SYMBOL vmlinux 0x67547925	slow_work_cancel
+EXPORT_SYMBOL vmlinux 0x67590234	blk_get_backing_dev_info
+EXPORT_SYMBOL vmlinux 0x676e4573	kunmap_high
+EXPORT_SYMBOL vmlinux 0x67ae0027	thermal_cooling_device_unregister
+EXPORT_SYMBOL vmlinux 0x67b05489	dm_register_target
+EXPORT_SYMBOL vmlinux 0x67b27ec1	tty_std_termios
+EXPORT_SYMBOL vmlinux 0x67f16499	tcp_v4_do_rcv
+EXPORT_SYMBOL vmlinux 0x681dd6bb	sock_setsockopt
+EXPORT_SYMBOL vmlinux 0x683d7a55	dquot_commit
+EXPORT_SYMBOL vmlinux 0x68506209	netlink_ack
+EXPORT_SYMBOL vmlinux 0x6866d012	release_sock
+EXPORT_SYMBOL vmlinux 0x689a3ca1	input_unregister_handle
+EXPORT_SYMBOL vmlinux 0x68a60e76	jbd2_journal_lock_updates
+EXPORT_SYMBOL vmlinux 0x68c6d430	bio_kmalloc
+EXPORT_SYMBOL vmlinux 0x68fd96d1	jbd2_journal_update_format
+EXPORT_SYMBOL vmlinux 0x6900b7cf	init_buffer
+EXPORT_SYMBOL vmlinux 0x690e970e	pci_find_device
+EXPORT_SYMBOL vmlinux 0x691e0b0b	skb_put
+EXPORT_SYMBOL vmlinux 0x691f2edc	bio_map_kern
+EXPORT_SYMBOL vmlinux 0x69374a84	complete_request_key
+EXPORT_SYMBOL vmlinux 0x69514509	__seq_open_private
+EXPORT_SYMBOL vmlinux 0x69534025	stop_tty
+EXPORT_SYMBOL vmlinux 0x6971447a	rtc_month_days
+EXPORT_SYMBOL vmlinux 0x6980d968	swiotlb_sync_sg_for_device
+EXPORT_SYMBOL vmlinux 0x6980fe91	param_get_int
+EXPORT_SYMBOL vmlinux 0x698928c5	poll_schedule_timeout
+EXPORT_SYMBOL vmlinux 0x69927dff	try_acquire_console_sem
+EXPORT_SYMBOL vmlinux 0x69a0ca7d	iowrite16be
+EXPORT_SYMBOL vmlinux 0x69a358a6	iomem_resource
+EXPORT_SYMBOL vmlinux 0x69a6f70f	tc_classify_compat
+EXPORT_SYMBOL vmlinux 0x69af9213	dcache_dir_lseek
+EXPORT_SYMBOL vmlinux 0x69c8c1d5	security_req_classify_flow
+EXPORT_SYMBOL vmlinux 0x69e27c7a	bitmap_copy_le
+EXPORT_SYMBOL vmlinux 0x6a037cf1	mempool_kfree
+EXPORT_SYMBOL vmlinux 0x6a27bfce	csum_partial_copy_generic
+EXPORT_SYMBOL vmlinux 0x6a47571d	__set_personality
+EXPORT_SYMBOL vmlinux 0x6a76f3ac	blk_iopoll_enable
+EXPORT_SYMBOL vmlinux 0x6a8b3c22	pci_do_scan_bus
+EXPORT_SYMBOL vmlinux 0x6a8d2318	tcf_hash_create
+EXPORT_SYMBOL vmlinux 0x6a9f26c9	init_timer_key
+EXPORT_SYMBOL vmlinux 0x6a9f5c90	tty_insert_flip_string_flags
+EXPORT_SYMBOL vmlinux 0x6acb973d	iowrite32be
+EXPORT_SYMBOL vmlinux 0x6acee908	sock_kfree_s
+EXPORT_SYMBOL vmlinux 0x6ad065f4	param_set_charp
+EXPORT_SYMBOL vmlinux 0x6ae4ff45	nla_reserve_nohdr
+EXPORT_SYMBOL vmlinux 0x6b1b67d3	__bdevname
+EXPORT_SYMBOL vmlinux 0x6b1d97d7	simple_unlink
+EXPORT_SYMBOL vmlinux 0x6b217acf	pci_request_region_exclusive
+EXPORT_SYMBOL vmlinux 0x6b28395b	sysctl_jiffies
+EXPORT_SYMBOL vmlinux 0x6b2dc060	dump_stack
+EXPORT_SYMBOL vmlinux 0x6b579d73	devm_ioremap_nocache
+EXPORT_SYMBOL vmlinux 0x6b5f2787	posix_lock_file_wait
+EXPORT_SYMBOL vmlinux 0x6b6bff03	udp_sendmsg
+EXPORT_SYMBOL vmlinux 0x6b7b8546	pskb_copy
+EXPORT_SYMBOL vmlinux 0x6b986711	fd_install
+EXPORT_SYMBOL vmlinux 0x6b9b88f3	sleep_on
+EXPORT_SYMBOL vmlinux 0x6b9bf345	bio_integrity_advance
+EXPORT_SYMBOL vmlinux 0x6bac8529	__serio_register_port
+EXPORT_SYMBOL vmlinux 0x6bb812e7	atomic64_add_return
+EXPORT_SYMBOL vmlinux 0x6bb8b62a	journal_wipe
+EXPORT_SYMBOL vmlinux 0x6bc3fbc0	__unregister_chrdev
+EXPORT_SYMBOL vmlinux 0x6bdcfd99	qdisc_class_hash_remove
+EXPORT_SYMBOL vmlinux 0x6be6e969	kill_pid
+EXPORT_SYMBOL vmlinux 0x6c133d12	rtnl_create_link
+EXPORT_SYMBOL vmlinux 0x6c15ade2	tty_port_carrier_raised
+EXPORT_SYMBOL vmlinux 0x6c1ce5ce	strcspn
+EXPORT_SYMBOL vmlinux 0x6c28f310	jbd2_journal_invalidatepage
+EXPORT_SYMBOL vmlinux 0x6c2e3320	strncmp
+EXPORT_SYMBOL vmlinux 0x6c2fc60c	tcp_check_req
+EXPORT_SYMBOL vmlinux 0x6c420e13	unlock_super
+EXPORT_SYMBOL vmlinux 0x6c47d685	generic_block_fiemap
+EXPORT_SYMBOL vmlinux 0x6c61ce70	num_registered_fb
+EXPORT_SYMBOL vmlinux 0x6c702af7	sysctl_udp_rmem_min
+EXPORT_SYMBOL vmlinux 0x6c7e3910	blk_put_request
+EXPORT_SYMBOL vmlinux 0x6caf1d8b	pci_save_state
+EXPORT_SYMBOL vmlinux 0x6cdc5c6b	nla_strlcpy
+EXPORT_SYMBOL vmlinux 0x6d1ced27	vcc_sklist_lock
+EXPORT_SYMBOL vmlinux 0x6d27ef64	__bitmap_empty
+EXPORT_SYMBOL vmlinux 0x6d288375	radix_tree_next_hole
+EXPORT_SYMBOL vmlinux 0x6d294e43	clock_t_to_jiffies
+EXPORT_SYMBOL vmlinux 0x6d340f64	tty_termios_input_baud_rate
+EXPORT_SYMBOL vmlinux 0x6d4adfaf	simple_link
+EXPORT_SYMBOL vmlinux 0x6d6cbadc	rb_last
+EXPORT_SYMBOL vmlinux 0x6d6f4c59	phy_stop_interrupts
+EXPORT_SYMBOL vmlinux 0x6d7424c3	nf_getsockopt
+EXPORT_SYMBOL vmlinux 0x6dc0c24b	complete_and_exit
+EXPORT_SYMBOL vmlinux 0x6dd9fcc8	tcp4_gro_receive
+EXPORT_SYMBOL vmlinux 0x6def2db2	half_md4_transform
+EXPORT_SYMBOL vmlinux 0x6dfc1020	security_path_unlink
+EXPORT_SYMBOL vmlinux 0x6e40444c	tcp_poll
+EXPORT_SYMBOL vmlinux 0x6e62b26a	blk_rq_map_sg
+EXPORT_SYMBOL vmlinux 0x6e720ff2	rtnl_unlock
+EXPORT_SYMBOL vmlinux 0x6e774c63	pci_iomap
+EXPORT_SYMBOL vmlinux 0x6e9dd606	__symbol_put
+EXPORT_SYMBOL vmlinux 0x6eb0fdf3	__cond_resched_lock
+EXPORT_SYMBOL vmlinux 0x6eeeb4f8	skb_copy_datagram_iovec
+EXPORT_SYMBOL vmlinux 0x6f3180b1	__dst_free
+EXPORT_SYMBOL vmlinux 0x6f81c062	netpoll_print_options
+EXPORT_SYMBOL vmlinux 0x6fc36ed5	dev_gro_receive
+EXPORT_SYMBOL vmlinux 0x6fcb87a1	touch_softlockup_watchdog
+EXPORT_SYMBOL vmlinux 0x6fcf6e1d	pci_enable_msix
+EXPORT_SYMBOL vmlinux 0x6ff912d1	proc_symlink
+EXPORT_SYMBOL vmlinux 0x6fff393f	time_to_tm
+EXPORT_SYMBOL vmlinux 0x701d0ebd	snprintf
+EXPORT_SYMBOL vmlinux 0x70445279	blk_queue_max_discard_sectors
+EXPORT_SYMBOL vmlinux 0x704fa5c6	dev_trans_start
+EXPORT_SYMBOL vmlinux 0x70523a7a	__cond_resched_softirq
+EXPORT_SYMBOL vmlinux 0x7054a3e4	request_dma
+EXPORT_SYMBOL vmlinux 0x7083514a	alloc_hippi_dev
+EXPORT_SYMBOL vmlinux 0x708741e2	d_prune_aliases
+EXPORT_SYMBOL vmlinux 0x709e440c	submit_bh
+EXPORT_SYMBOL vmlinux 0x70b6d8b7	skb_copy_bits
+EXPORT_SYMBOL vmlinux 0x70bc17d7	inode_wait
+EXPORT_SYMBOL vmlinux 0x70c0bedc	eth_rebuild_header
+EXPORT_SYMBOL vmlinux 0x70cb4b86	pci_iounmap
+EXPORT_SYMBOL vmlinux 0x70d1f8f3	strncat
+EXPORT_SYMBOL vmlinux 0x70d22cb6	tty_register_device
+EXPORT_SYMBOL vmlinux 0x70d5b593	dquot_release
+EXPORT_SYMBOL vmlinux 0x70e0d61f	cpu_all_bits
+EXPORT_SYMBOL vmlinux 0x70e4437e	tcp_getsockopt
+EXPORT_SYMBOL vmlinux 0x71175463	dev_addr_add_multiple
+EXPORT_SYMBOL vmlinux 0x7129e5f8	hex_asc
+EXPORT_SYMBOL vmlinux 0x712aa29b	_spin_lock_irqsave
+EXPORT_SYMBOL vmlinux 0x71356fba	remove_wait_queue
+EXPORT_SYMBOL vmlinux 0x715ffb3f	config_group_init_type_name
+EXPORT_SYMBOL vmlinux 0x7171121c	overflowgid
+EXPORT_SYMBOL vmlinux 0x71879528	kthread_stop
+EXPORT_SYMBOL vmlinux 0x71a50dbc	register_blkdev
+EXPORT_SYMBOL vmlinux 0x71a777c7	vfs_dq_drop
+EXPORT_SYMBOL vmlinux 0x71bb41e4	wrmsr_on_cpus
+EXPORT_SYMBOL vmlinux 0x720a10a6	sk_stream_wait_memory
+EXPORT_SYMBOL vmlinux 0x722946b1	cpu_sysdev_class
+EXPORT_SYMBOL vmlinux 0x72329e0d	jbd2_log_wait_commit
+EXPORT_SYMBOL vmlinux 0x723e0484	zap_page_range
+EXPORT_SYMBOL vmlinux 0x72658af8	cdev_init
+EXPORT_SYMBOL vmlinux 0x727d3a6a	kill_fasync
+EXPORT_SYMBOL vmlinux 0x72870ff9	vfs_path_lookup
+EXPORT_SYMBOL vmlinux 0x72b243d4	free_dma
+EXPORT_SYMBOL vmlinux 0x72b91e6d	tty_port_init
+EXPORT_SYMBOL vmlinux 0x72c3be87	param_set_byte
+EXPORT_SYMBOL vmlinux 0x72e656e8	thermal_cooling_device_register
+EXPORT_SYMBOL vmlinux 0x732ca464	sock_create_kern
+EXPORT_SYMBOL vmlinux 0x73467acd	bioset_create
+EXPORT_SYMBOL vmlinux 0x734b6e63	__netdev_alloc_skb
+EXPORT_SYMBOL vmlinux 0x7362dd1e	vfs_fstat
+EXPORT_SYMBOL vmlinux 0x73677c9f	journal_blocks_per_page
+EXPORT_SYMBOL vmlinux 0x736b103b	__skb_recv_datagram
+EXPORT_SYMBOL vmlinux 0x738803e6	strnlen
+EXPORT_SYMBOL vmlinux 0x738acc64	kobject_put
+EXPORT_SYMBOL vmlinux 0x73e20c1c	strlcpy
+EXPORT_SYMBOL vmlinux 0x73e6d6dd	uart_resume_port
+EXPORT_SYMBOL vmlinux 0x73f92425	wireless_spy_update
+EXPORT_SYMBOL vmlinux 0x7437b87b	__dec_zone_page_state
+EXPORT_SYMBOL vmlinux 0x744c0c68	param_get_byte
+EXPORT_SYMBOL vmlinux 0x7475ff36	d_splice_alias
+EXPORT_SYMBOL vmlinux 0x7485e15e	unregister_chrdev_region
+EXPORT_SYMBOL vmlinux 0x748caf40	down
+EXPORT_SYMBOL vmlinux 0x74954462	timecounter_read
+EXPORT_SYMBOL vmlinux 0x74a6459d	set_page_dirty_lock
+EXPORT_SYMBOL vmlinux 0x74bfc369	__tracepoint_kmem_cache_alloc
+EXPORT_SYMBOL vmlinux 0x74cc1cbe	unregister_cpu_notifier
+EXPORT_SYMBOL vmlinux 0x74e1870c	load_nls_default
+EXPORT_SYMBOL vmlinux 0x74e3b4bf	mpage_writepage
+EXPORT_SYMBOL vmlinux 0x74ead6f3	kill_pgrp
+EXPORT_SYMBOL vmlinux 0x74ef05d2	blk_run_queue
+EXPORT_SYMBOL vmlinux 0x7503d086	scm_detach_fds
+EXPORT_SYMBOL vmlinux 0x7505d147	netif_napi_add
+EXPORT_SYMBOL vmlinux 0x7515ca9e	pci_enable_msi_block
+EXPORT_SYMBOL vmlinux 0x751bdd59	register_filesystem
+EXPORT_SYMBOL vmlinux 0x75207cef	release_firmware
+EXPORT_SYMBOL vmlinux 0x753f02eb	neigh_table_init
+EXPORT_SYMBOL vmlinux 0x755292ed	phy_register_fixup
+EXPORT_SYMBOL vmlinux 0x75632dba	register_msi_get_owner
+EXPORT_SYMBOL vmlinux 0x75702327	skb_copy_and_csum_datagram_iovec
+EXPORT_SYMBOL vmlinux 0x759499b1	tty_kref_put
+EXPORT_SYMBOL vmlinux 0x75bdea12	iommu_area_alloc
+EXPORT_SYMBOL vmlinux 0x760a0f4f	yield
+EXPORT_SYMBOL vmlinux 0x760b437a	unregister_inetaddr_notifier
+EXPORT_SYMBOL vmlinux 0x764bd77c	request_resource
+EXPORT_SYMBOL vmlinux 0x764fe948	tcf_action_dump_1
+EXPORT_SYMBOL vmlinux 0x7671d950	bio_unmap_user
+EXPORT_SYMBOL vmlinux 0x767ddb02	set_memory_wc
+EXPORT_SYMBOL vmlinux 0x76b023f9	llc_sap_find
+EXPORT_SYMBOL vmlinux 0x76bf656d	__bitmap_shift_left
+EXPORT_SYMBOL vmlinux 0x76c30120	ipv4_specific
+EXPORT_SYMBOL vmlinux 0x76c72f4e	tcp_sendmsg
+EXPORT_SYMBOL vmlinux 0x76d3cd60	laptop_mode
+EXPORT_SYMBOL vmlinux 0x76f3f8a5	num_k8_northbridges
+EXPORT_SYMBOL vmlinux 0x77298909	ethtool_op_set_tx_hw_csum
+EXPORT_SYMBOL vmlinux 0x773a9c94	blk_iopoll_enabled
+EXPORT_SYMBOL vmlinux 0x7760d1a6	ip_setsockopt
+EXPORT_SYMBOL vmlinux 0x777f7c6a	unregister_key_type
+EXPORT_SYMBOL vmlinux 0x777fe864	pci_fixup_device
+EXPORT_SYMBOL vmlinux 0x7785e3b2	nf_unregister_hook
+EXPORT_SYMBOL vmlinux 0x778c8f0e	eth_type_trans
+EXPORT_SYMBOL vmlinux 0x779139a6	phy_disconnect
+EXPORT_SYMBOL vmlinux 0x77a108df	_write_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x77b18b5c	iw_handler_get_spy
+EXPORT_SYMBOL vmlinux 0x77cfcfde	__tracepoint_kmalloc_node
+EXPORT_SYMBOL vmlinux 0x77e54c22	inode_newsize_ok
+EXPORT_SYMBOL vmlinux 0x77ecac9f	zlib_inflateEnd
+EXPORT_SYMBOL vmlinux 0x77f1810b	proc_mkdir
+EXPORT_SYMBOL vmlinux 0x77f9713e	unregister_msi_get_owner
+EXPORT_SYMBOL vmlinux 0x77fa5d1f	ns_to_timespec
+EXPORT_SYMBOL vmlinux 0x780d334f	lock_super
+EXPORT_SYMBOL vmlinux 0x781a1037	dm_io_client_resize
+EXPORT_SYMBOL vmlinux 0x782f5e90	kobject_get
+EXPORT_SYMBOL vmlinux 0x783c8167	phy_start_interrupts
+EXPORT_SYMBOL vmlinux 0x784bf88c	fb_get_buffer_offset
+EXPORT_SYMBOL vmlinux 0x787d3ed9	tcp_tso_segment
+EXPORT_SYMBOL vmlinux 0x789dc337	netdev_bonding_change
+EXPORT_SYMBOL vmlinux 0x78a484c9	_read_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x78c4d3e9	udplite_prot
+EXPORT_SYMBOL vmlinux 0x78df6bd7	no_pci_devices
+EXPORT_SYMBOL vmlinux 0x78f1fc2a	__ps2_command
+EXPORT_SYMBOL vmlinux 0x792bc11c	journal_restart
+EXPORT_SYMBOL vmlinux 0x794487ee	disable_hlt
+EXPORT_SYMBOL vmlinux 0x79948d88	tcp_v4_send_check
+EXPORT_SYMBOL vmlinux 0x79aa04a2	get_random_bytes
+EXPORT_SYMBOL vmlinux 0x79ac27fb	__sk_mem_schedule
+EXPORT_SYMBOL vmlinux 0x79ad224b	tasklet_kill
+EXPORT_SYMBOL vmlinux 0x79ae99dd	seq_bitmap
+EXPORT_SYMBOL vmlinux 0x79ba72ef	read_cache_page_async
+EXPORT_SYMBOL vmlinux 0x79d2e54a	simple_readpage
+EXPORT_SYMBOL vmlinux 0x7a2a837d	strict_strtol
+EXPORT_SYMBOL vmlinux 0x7a4497db	kzfree
+EXPORT_SYMBOL vmlinux 0x7a5ba42b	nla_reserve
+EXPORT_SYMBOL vmlinux 0x7a848702	_read_lock_irqsave
+EXPORT_SYMBOL vmlinux 0x7a856669	generic_ro_fops
+EXPORT_SYMBOL vmlinux 0x7a9059a9	touch_atime
+EXPORT_SYMBOL vmlinux 0x7ab5c740	blk_queue_softirq_done
+EXPORT_SYMBOL vmlinux 0x7ae1b887	dev_getbyhwaddr
+EXPORT_SYMBOL vmlinux 0x7ae80355	d_path
+EXPORT_SYMBOL vmlinux 0x7aec9089	clear_user
+EXPORT_SYMBOL vmlinux 0x7af32a3a	unload_nls
+EXPORT_SYMBOL vmlinux 0x7afdea27	add_to_page_cache_locked
+EXPORT_SYMBOL vmlinux 0x7b17a47c	sock_recvmsg
+EXPORT_SYMBOL vmlinux 0x7b2e6a85	swiotlb_map_sg_attrs
+EXPORT_SYMBOL vmlinux 0x7b3f086b	sb_set_blocksize
+EXPORT_SYMBOL vmlinux 0x7b52a859	wrmsr_safe_on_cpu
+EXPORT_SYMBOL vmlinux 0x7b5e46b3	vfs_mknod
+EXPORT_SYMBOL vmlinux 0x7b6b1424	qdisc_create_dflt
+EXPORT_SYMBOL vmlinux 0x7b8d9127	security_path_link
+EXPORT_SYMBOL vmlinux 0x7b943873	input_register_handler
+EXPORT_SYMBOL vmlinux 0x7bc08b57	dm_io_client_create
+EXPORT_SYMBOL vmlinux 0x7bcbabdc	sock_no_sendpage
+EXPORT_SYMBOL vmlinux 0x7be28e8e	netif_receive_skb
+EXPORT_SYMBOL vmlinux 0x7c26dcc8	journal_extend
+EXPORT_SYMBOL vmlinux 0x7c44a005	__nla_put_nohdr
+EXPORT_SYMBOL vmlinux 0x7c5c2a72	xfrm_state_check_expire
+EXPORT_SYMBOL vmlinux 0x7c60d66e	getname
+EXPORT_SYMBOL vmlinux 0x7c61340c	__release_region
+EXPORT_SYMBOL vmlinux 0x7c7df3d9	seq_open
+EXPORT_SYMBOL vmlinux 0x7c83a3b8	security_inode_getsecctx
+EXPORT_SYMBOL vmlinux 0x7c904ded	unregister_module_notifier
+EXPORT_SYMBOL vmlinux 0x7cab02d9	invalidate_mapping_pages
+EXPORT_SYMBOL vmlinux 0x7cad37df	get_unmapped_area_prot
+EXPORT_SYMBOL vmlinux 0x7cb1ae69	cpu_down
+EXPORT_SYMBOL vmlinux 0x7cdde857	call_usermodehelper_freeinfo
+EXPORT_SYMBOL vmlinux 0x7cf01e77	generic_show_options
+EXPORT_SYMBOL vmlinux 0x7cf0cff5	tty_port_close
+EXPORT_SYMBOL vmlinux 0x7d075a9b	netif_device_attach
+EXPORT_SYMBOL vmlinux 0x7d11c268	jiffies
+EXPORT_SYMBOL vmlinux 0x7d32b4e8	ethtool_op_get_link
+EXPORT_SYMBOL vmlinux 0x7d4baa2a	arp_find
+EXPORT_SYMBOL vmlinux 0x7d5fdc49	call_usermodehelper_exec
+EXPORT_SYMBOL vmlinux 0x7d6bb587	cpu_online_mask
+EXPORT_SYMBOL vmlinux 0x7d77872b	simple_statfs
+EXPORT_SYMBOL vmlinux 0x7d9913cb	tcp_v4_md5_do_add
+EXPORT_SYMBOL vmlinux 0x7dc90468	read_cache_pages
+EXPORT_SYMBOL vmlinux 0x7dceceac	capable
+EXPORT_SYMBOL vmlinux 0x7ddf7fb0	sk_wait_data
+EXPORT_SYMBOL vmlinux 0x7df96286	tcp_proc_unregister
+EXPORT_SYMBOL vmlinux 0x7dfe6817	alloc_disk_node
+EXPORT_SYMBOL vmlinux 0x7e017a81	register_atm_ioctl
+EXPORT_SYMBOL vmlinux 0x7e02a860	tcp_enter_memory_pressure
+EXPORT_SYMBOL vmlinux 0x7e316052	blk_peek_request
+EXPORT_SYMBOL vmlinux 0x7e437d67	pci_clear_master
+EXPORT_SYMBOL vmlinux 0x7e59dc80	rwsem_down_read_failed
+EXPORT_SYMBOL vmlinux 0x7e9ebb05	kernel_thread
+EXPORT_SYMBOL vmlinux 0x7ec3be9e	vfs_dq_quota_on_remount
+EXPORT_SYMBOL vmlinux 0x7ee16474	sock_no_accept
+EXPORT_SYMBOL vmlinux 0x7ee91c1d	_spin_trylock
+EXPORT_SYMBOL vmlinux 0x7ef8e1cf	blk_unplug
+EXPORT_SYMBOL vmlinux 0x7f06f267	ip_mc_rejoin_group
+EXPORT_SYMBOL vmlinux 0x7f24de73	jiffies_to_usecs
+EXPORT_SYMBOL vmlinux 0x7f89c373	sk_common_release
+EXPORT_SYMBOL vmlinux 0x7fb19233	blk_integrity_unregister
+EXPORT_SYMBOL vmlinux 0x7fc9656c	prepare_creds
+EXPORT_SYMBOL vmlinux 0x7fe10246	linkwatch_fire_event
+EXPORT_SYMBOL vmlinux 0x7ffbd780	vlan_dev_vlan_id
+EXPORT_SYMBOL vmlinux 0x7fff0893	module_put
+EXPORT_SYMBOL vmlinux 0x8027d6c4	fib_default_rule_add
+EXPORT_SYMBOL vmlinux 0x804c77d4	wake_up_process
+EXPORT_SYMBOL vmlinux 0x8063f83d	radix_tree_gang_lookup
+EXPORT_SYMBOL vmlinux 0x807da753	bd_claim
+EXPORT_SYMBOL vmlinux 0x809be499	unmap_underlying_metadata
+EXPORT_SYMBOL vmlinux 0x80aacf1d	dm_table_event
+EXPORT_SYMBOL vmlinux 0x80e155b0	inet_sock_destruct
+EXPORT_SYMBOL vmlinux 0x8103a348	tcf_register_action
+EXPORT_SYMBOL vmlinux 0x811d1caa	napi_get_frags
+EXPORT_SYMBOL vmlinux 0x814ee28a	inet_csk_accept
+EXPORT_SYMBOL vmlinux 0x8150dbca	add_disk
+EXPORT_SYMBOL vmlinux 0x815b5dd4	match_octal
+EXPORT_SYMBOL vmlinux 0x815e468f	clear_page_dirty_for_io
+EXPORT_SYMBOL vmlinux 0x815f2897	empty_zero_page
+EXPORT_SYMBOL vmlinux 0x81799cee	vscnprintf
+EXPORT_SYMBOL vmlinux 0x81b2fece	call_usermodehelper_setup
+EXPORT_SYMBOL vmlinux 0x81b6fe78	xfrm_prepare_input
+EXPORT_SYMBOL vmlinux 0x81fead70	udp_flush_pending_frames
+EXPORT_SYMBOL vmlinux 0x82010712	pskb_expand_head
+EXPORT_SYMBOL vmlinux 0x8204a1f5	skb_append_datato_frags
+EXPORT_SYMBOL vmlinux 0x820d225f	print_mac
+EXPORT_SYMBOL vmlinux 0x820fc63c	vfsmount_lock
+EXPORT_SYMBOL vmlinux 0x821c5496	sock_no_poll
+EXPORT_SYMBOL vmlinux 0x8222855f	task_nice
+EXPORT_SYMBOL vmlinux 0x8235805b	memmove
+EXPORT_SYMBOL vmlinux 0x823d34aa	vfs_fsync_range
+EXPORT_SYMBOL vmlinux 0x823f1bf0	vm_map_ram
+EXPORT_SYMBOL vmlinux 0x82516cdc	configfs_unregister_subsystem
+EXPORT_SYMBOL vmlinux 0x8251bcc3	bitmap_release_region
+EXPORT_SYMBOL vmlinux 0x825354c7	make_bad_inode
+EXPORT_SYMBOL vmlinux 0x82692209	kref_set
+EXPORT_SYMBOL vmlinux 0x828e6a9a	tty_vhangup
+EXPORT_SYMBOL vmlinux 0x82acfb70	blk_iopoll_sched
+EXPORT_SYMBOL vmlinux 0x82ad397b	pci_remove_bus
+EXPORT_SYMBOL vmlinux 0x82b28e22	slow_work_register_user
+EXPORT_SYMBOL vmlinux 0x82db9035	path_put
+EXPORT_SYMBOL vmlinux 0x82efcbaf	keyring_search
+EXPORT_SYMBOL vmlinux 0x830e547b	ioremap_prot
+EXPORT_SYMBOL vmlinux 0x8317e20a	completion_done
+EXPORT_SYMBOL vmlinux 0x83236ac5	lookup_one_len
+EXPORT_SYMBOL vmlinux 0x8352c52e	open_bdev_exclusive
+EXPORT_SYMBOL vmlinux 0x836143a7	writeback_inodes_sb_if_idle
+EXPORT_SYMBOL vmlinux 0x8386160c	xfrm_init_state
+EXPORT_SYMBOL vmlinux 0x83904ad4	per_cpu__irq_regs
+EXPORT_SYMBOL vmlinux 0x83a03088	dm_table_get_size
+EXPORT_SYMBOL vmlinux 0x83a476ce	bitmap_scnlistprintf
+EXPORT_SYMBOL vmlinux 0x83aaa4be	blk_execute_rq
+EXPORT_SYMBOL vmlinux 0x83cafc56	phy_disable_interrupts
+EXPORT_SYMBOL vmlinux 0x83cb404b	lease_get_mtime
+EXPORT_SYMBOL vmlinux 0x83dbb6b7	__sk_mem_reclaim
+EXPORT_SYMBOL vmlinux 0x83e3569b	kernel_setsockopt
+EXPORT_SYMBOL vmlinux 0x83fd3d04	block_write_full_page_endio
+EXPORT_SYMBOL vmlinux 0x83feed65	qdisc_tree_decrease_qlen
+EXPORT_SYMBOL vmlinux 0x84153ca6	inet_frags_fini
+EXPORT_SYMBOL vmlinux 0x84163bda	neigh_seq_start
+EXPORT_SYMBOL vmlinux 0x843b3f02	skb_trim
+EXPORT_SYMBOL vmlinux 0x8467e73d	nf_hook_slow
+EXPORT_SYMBOL vmlinux 0x84a56619	__skb_checksum_complete
+EXPORT_SYMBOL vmlinux 0x84c017c4	jbd2_journal_release_buffer
+EXPORT_SYMBOL vmlinux 0x84fc09b5	skb_unlink
+EXPORT_SYMBOL vmlinux 0x850b90da	page_symlink
+EXPORT_SYMBOL vmlinux 0x8517fc14	xfrm_cfg_mutex
+EXPORT_SYMBOL vmlinux 0x8522ab94	dev_set_mac_address
+EXPORT_SYMBOL vmlinux 0x852ff398	km_policy_notify
+EXPORT_SYMBOL vmlinux 0x8531ceec	eth_header_parse
+EXPORT_SYMBOL vmlinux 0x85504720	dquot_release_reserved_space
+EXPORT_SYMBOL vmlinux 0x85670f1d	rtnl_is_locked
+EXPORT_SYMBOL vmlinux 0x857d1354	cfb_imageblit
+EXPORT_SYMBOL vmlinux 0x858d2ed4	register_sysctl_table
+EXPORT_SYMBOL vmlinux 0x85ac7f10	posix_acl_from_xattr
+EXPORT_SYMBOL vmlinux 0x85df9b6c	strsep
+EXPORT_SYMBOL vmlinux 0x85e1a9c7	kernel_sock_shutdown
+EXPORT_SYMBOL vmlinux 0x85e31706	qdisc_watchdog_init
+EXPORT_SYMBOL vmlinux 0x85e7deb2	iov_iter_fault_in_readable
+EXPORT_SYMBOL vmlinux 0x86151470	slow_work_sleep_till_thread_needed
+EXPORT_SYMBOL vmlinux 0x8677320d	tcf_em_unregister
+EXPORT_SYMBOL vmlinux 0x868acba5	get_options
+EXPORT_SYMBOL vmlinux 0x86c19184	kmem_cache_free
+EXPORT_SYMBOL vmlinux 0x86c7523b	tr_type_trans
+EXPORT_SYMBOL vmlinux 0x86fb9b05	bitmap_parse_user
+EXPORT_SYMBOL vmlinux 0x871c0a7e	fiemap_check_flags
+EXPORT_SYMBOL vmlinux 0x871e1807	nla_append
+EXPORT_SYMBOL vmlinux 0x872730b8	__insert_inode_hash
+EXPORT_SYMBOL vmlinux 0x8733e9a3	sleep_on_timeout
+EXPORT_SYMBOL vmlinux 0x874cbeca	tty_set_operations
+EXPORT_SYMBOL vmlinux 0x878ab12c	input_set_keycode
+EXPORT_SYMBOL vmlinux 0x878ab3ce	sysctl_tcp_adv_win_scale
+EXPORT_SYMBOL vmlinux 0x87aaddf8	wrmsr_safe_regs_on_cpu
+EXPORT_SYMBOL vmlinux 0x87d80768	dma_release_declared_memory
+EXPORT_SYMBOL vmlinux 0x87e22779	__dev_get_by_name
+EXPORT_SYMBOL vmlinux 0x87f438a2	sysctl_intvec
+EXPORT_SYMBOL vmlinux 0x87f9d7c3	framebuffer_release
+EXPORT_SYMBOL vmlinux 0x881039d0	zlib_inflate
+EXPORT_SYMBOL vmlinux 0x8816213b	fb_pan_display
+EXPORT_SYMBOL vmlinux 0x886ad555	seq_release_private
+EXPORT_SYMBOL vmlinux 0x8881e104	swiotlb_dma_supported
+EXPORT_SYMBOL vmlinux 0x88863a0d	block_write_end
+EXPORT_SYMBOL vmlinux 0x88a6ba10	atm_dev_register
+EXPORT_SYMBOL vmlinux 0x88c88a8a	bio_add_page
+EXPORT_SYMBOL vmlinux 0x89160650	call_usermodehelper_setcleanup
+EXPORT_SYMBOL vmlinux 0x89195dc3	sonet_copy_stats
+EXPORT_SYMBOL vmlinux 0x892b26a0	set_memory_nx
+EXPORT_SYMBOL vmlinux 0x895d2627	blk_start_request
+EXPORT_SYMBOL vmlinux 0x8969b997	ida_get_new
+EXPORT_SYMBOL vmlinux 0x897473df	mktime
+EXPORT_SYMBOL vmlinux 0x89949018	down_timeout
+EXPORT_SYMBOL vmlinux 0x89c99703	generic_fillattr
+EXPORT_SYMBOL vmlinux 0x89d5538d	fb_pad_aligned_buffer
+EXPORT_SYMBOL vmlinux 0x89d66811	build_ehash_secret
+EXPORT_SYMBOL vmlinux 0x89f6d130	simple_dir_inode_operations
+EXPORT_SYMBOL vmlinux 0x89f78ea7	contig_page_data
+EXPORT_SYMBOL vmlinux 0x89fb5d2a	set_disk_ro
+EXPORT_SYMBOL vmlinux 0x8a1203a9	kref_get
+EXPORT_SYMBOL vmlinux 0x8a2090f1	lock_sock_nested
+EXPORT_SYMBOL vmlinux 0x8a26d8cf	sk_dst_check
+EXPORT_SYMBOL vmlinux 0x8a389923	arch_debugfs_dir
+EXPORT_SYMBOL vmlinux 0x8a3eabf0	__wait_on_bit
+EXPORT_SYMBOL vmlinux 0x8a7d1c31	high_memory
+EXPORT_SYMBOL vmlinux 0x8a99a016	mempool_free_slab
+EXPORT_SYMBOL vmlinux 0x8a9a805a	xfrm_input_resume
+EXPORT_SYMBOL vmlinux 0x8ab28e67	skb_checksum
+EXPORT_SYMBOL vmlinux 0x8ac40297	iommu_area_free
+EXPORT_SYMBOL vmlinux 0x8acd1b7f	bio_phys_segments
+EXPORT_SYMBOL vmlinux 0x8ad4fc36	dev_mc_sync
+EXPORT_SYMBOL vmlinux 0x8ae77528	proc_dointvec_minmax
+EXPORT_SYMBOL vmlinux 0x8b18496f	__copy_to_user_ll
+EXPORT_SYMBOL vmlinux 0x8b35e873	sg_last
+EXPORT_SYMBOL vmlinux 0x8b618d08	overflowuid
+EXPORT_SYMBOL vmlinux 0x8b6fac89	kmem_cache_alloc
+EXPORT_SYMBOL vmlinux 0x8b8fd087	tty_port_free_xmit_buf
+EXPORT_SYMBOL vmlinux 0x8bd313b8	__tracepoint_kfree
+EXPORT_SYMBOL vmlinux 0x8bd5b603	param_get_long
+EXPORT_SYMBOL vmlinux 0x8be75f90	bio_integrity_split
+EXPORT_SYMBOL vmlinux 0x8c0826a0	nlmsg_notify
+EXPORT_SYMBOL vmlinux 0x8c177887	xfrm_find_acq
+EXPORT_SYMBOL vmlinux 0x8c183cbe	iowrite16
+EXPORT_SYMBOL vmlinux 0x8c2734a4	tcp_proc_register
+EXPORT_SYMBOL vmlinux 0x8c465314	kmap_high
+EXPORT_SYMBOL vmlinux 0x8c92bd0a	deregister_atm_ioctl
+EXPORT_SYMBOL vmlinux 0x8c939e64	d_delete
+EXPORT_SYMBOL vmlinux 0x8c95e342	neigh_parms_release
+EXPORT_SYMBOL vmlinux 0x8c96dec3	skb_dequeue_tail
+EXPORT_SYMBOL vmlinux 0x8ca64ddd	tc_classify
+EXPORT_SYMBOL vmlinux 0x8cc79cab	iowrite16_rep
+EXPORT_SYMBOL vmlinux 0x8cd33449	sk_stream_error
+EXPORT_SYMBOL vmlinux 0x8cd68f0c	dmam_free_noncoherent
+EXPORT_SYMBOL vmlinux 0x8ce690c0	blk_rq_unmap_user
+EXPORT_SYMBOL vmlinux 0x8cefe602	jbd2_journal_clear_features
+EXPORT_SYMBOL vmlinux 0x8d11db48	dmam_free_coherent
+EXPORT_SYMBOL vmlinux 0x8d174682	kthread_create
+EXPORT_SYMBOL vmlinux 0x8d3894f2	_ctype
+EXPORT_SYMBOL vmlinux 0x8d551bef	sysctl_tcp_rmem
+EXPORT_SYMBOL vmlinux 0x8d574ea3	journal_revoke
+EXPORT_SYMBOL vmlinux 0x8d6c9169	nf_log_bind_pf
+EXPORT_SYMBOL vmlinux 0x8d6f81b4	__div64_32
+EXPORT_SYMBOL vmlinux 0x8db3ed1b	set_pages_array_wb
+EXPORT_SYMBOL vmlinux 0x8dc4e5be	put_disk
+EXPORT_SYMBOL vmlinux 0x8dc5019a	xfrm_state_unregister_afinfo
+EXPORT_SYMBOL vmlinux 0x8dca832f	__percpu_counter_sum
+EXPORT_SYMBOL vmlinux 0x8e0637ba	i8253_lock
+EXPORT_SYMBOL vmlinux 0x8e0b7743	ipv6_ext_hdr
+EXPORT_SYMBOL vmlinux 0x8e0be763	nobh_write_end
+EXPORT_SYMBOL vmlinux 0x8e313191	tcp_v4_md5_hash_skb
+EXPORT_SYMBOL vmlinux 0x8e380e0b	block_write_begin
+EXPORT_SYMBOL vmlinux 0x8e75f836	insert_inode_locked4
+EXPORT_SYMBOL vmlinux 0x8e763ae1	send_remote_softirq
+EXPORT_SYMBOL vmlinux 0x8ea95d69	netpoll_poll
+EXPORT_SYMBOL vmlinux 0x8ec22c68	generic_delete_inode
+EXPORT_SYMBOL vmlinux 0x8ec57ef9	__blk_end_request
+EXPORT_SYMBOL vmlinux 0x8ec6a9ca	tty_register_driver
+EXPORT_SYMBOL vmlinux 0x8ee69235	timeval_to_jiffies
+EXPORT_SYMBOL vmlinux 0x8ee7c1b1	ps2_handle_response
+EXPORT_SYMBOL vmlinux 0x8f028171	kernel_bind
+EXPORT_SYMBOL vmlinux 0x8f24ca9a	register_key_type
+EXPORT_SYMBOL vmlinux 0x8f2703b7	wbinvd_on_all_cpus
+EXPORT_SYMBOL vmlinux 0x8f3c5993	__scm_destroy
+EXPORT_SYMBOL vmlinux 0x8f48679a	rb_prev
+EXPORT_SYMBOL vmlinux 0x8f5b8f37	blk_queue_stack_limits
+EXPORT_SYMBOL vmlinux 0x8f6b7950	set_irq_data
+EXPORT_SYMBOL vmlinux 0x8f9c199c	__get_user_2
+EXPORT_SYMBOL vmlinux 0x8fa87032	mark_page_accessed
+EXPORT_SYMBOL vmlinux 0x8faf8ec7	remap_vmalloc_range
+EXPORT_SYMBOL vmlinux 0x8fb824e2	jbd2_journal_get_write_access
+EXPORT_SYMBOL vmlinux 0x8fbf536e	inode_get_bytes
+EXPORT_SYMBOL vmlinux 0x8fbf794a	skb_copy_expand
+EXPORT_SYMBOL vmlinux 0x8fc52c82	find_get_page
+EXPORT_SYMBOL vmlinux 0x8ffdb3b8	crc16
+EXPORT_SYMBOL vmlinux 0x90035333	secure_tcpv6_sequence_number
+EXPORT_SYMBOL vmlinux 0x9019ee5a	ilookup
+EXPORT_SYMBOL vmlinux 0x90638755	nf_register_hook
+EXPORT_SYMBOL vmlinux 0x90a15568	bioset_integrity_free
+EXPORT_SYMBOL vmlinux 0x90d4220f	block_read_full_page
+EXPORT_SYMBOL vmlinux 0x90d61b95	journal_init_inode
+EXPORT_SYMBOL vmlinux 0x91009452	schedule_delayed_work
+EXPORT_SYMBOL vmlinux 0x912ee7b7	simple_getattr
+EXPORT_SYMBOL vmlinux 0x91481982	__ratelimit
+EXPORT_SYMBOL vmlinux 0x91607d95	set_memory_wb
+EXPORT_SYMBOL vmlinux 0x917550a2	__tcf_em_tree_match
+EXPORT_SYMBOL vmlinux 0x91766c09	param_get_ulong
+EXPORT_SYMBOL vmlinux 0x9199c204	dquot_acquire
+EXPORT_SYMBOL vmlinux 0x91af8892	xfrm_register_type
+EXPORT_SYMBOL vmlinux 0x91b004ad	neigh_compat_output
+EXPORT_SYMBOL vmlinux 0x91b133c6	kmap_atomic
+EXPORT_SYMBOL vmlinux 0x9214ed8a	param_get_bool
+EXPORT_SYMBOL vmlinux 0x921544f5	check_disk_change
+EXPORT_SYMBOL vmlinux 0x9217f36f	dump_trace
+EXPORT_SYMBOL vmlinux 0x9223cca3	__alloc_pages_nodemask
+EXPORT_SYMBOL vmlinux 0x922cb2f0	thaw_bdev
+EXPORT_SYMBOL vmlinux 0x929f1710	tcp_connect
+EXPORT_SYMBOL vmlinux 0x92a9fc42	sock_release
+EXPORT_SYMBOL vmlinux 0x92e9397e	xen_halt
+EXPORT_SYMBOL vmlinux 0x92ec11aa	udp_lib_setsockopt
+EXPORT_SYMBOL vmlinux 0x93175ab0	jbd2_journal_get_create_access
+EXPORT_SYMBOL vmlinux 0x932b9103	blk_stop_queue
+EXPORT_SYMBOL vmlinux 0x93559167	__kfree_skb
+EXPORT_SYMBOL vmlinux 0x935c9ccc	xfrm_unregister_type
+EXPORT_SYMBOL vmlinux 0x9374bf2f	do_mmap_pgoff
+EXPORT_SYMBOL vmlinux 0x937fdc1b	deactivate_super
+EXPORT_SYMBOL vmlinux 0x9385667d	down_read_trylock
+EXPORT_SYMBOL vmlinux 0x93a6e0b2	io_schedule
+EXPORT_SYMBOL vmlinux 0x93cbd1ec	_spin_lock_bh
+EXPORT_SYMBOL vmlinux 0x93fca811	__get_free_pages
+EXPORT_SYMBOL vmlinux 0x94041b64	init_task
+EXPORT_SYMBOL vmlinux 0x940e88ea	qdisc_warn_nonwc
+EXPORT_SYMBOL vmlinux 0x94274301	fb_show_logo
+EXPORT_SYMBOL vmlinux 0x942bfe16	input_unregister_device
+EXPORT_SYMBOL vmlinux 0x94356c51	____pagevec_lru_add
+EXPORT_SYMBOL vmlinux 0x943bbb4d	iw_handler_set_thrspy
+EXPORT_SYMBOL vmlinux 0x943e8fcb	kmem_cache_size
+EXPORT_SYMBOL vmlinux 0x944832d6	ftrace_print_symbols_seq
+EXPORT_SYMBOL vmlinux 0x945e8a97	uart_write_wakeup
+EXPORT_SYMBOL vmlinux 0x9460e424	pci_assign_resource
+EXPORT_SYMBOL vmlinux 0x946dc857	ip_mc_inc_group
+EXPORT_SYMBOL vmlinux 0x9481e333	blk_queue_resize_tags
+EXPORT_SYMBOL vmlinux 0x94847b23	nf_ct_destroy
+EXPORT_SYMBOL vmlinux 0x948e05b5	arp_broken_ops
+EXPORT_SYMBOL vmlinux 0x94961283	vunmap
+EXPORT_SYMBOL vmlinux 0x94a15887	register_con_driver
+EXPORT_SYMBOL vmlinux 0x94a28116	serio_close
+EXPORT_SYMBOL vmlinux 0x94c7775a	uart_get_baud_rate
+EXPORT_SYMBOL vmlinux 0x94d22c09	tcf_em_tree_validate
+EXPORT_SYMBOL vmlinux 0x950d3950	uart_unregister_driver
+EXPORT_SYMBOL vmlinux 0x951d6972	filp_close
+EXPORT_SYMBOL vmlinux 0x95414bdc	tty_port_raise_dtr_rts
+EXPORT_SYMBOL vmlinux 0x954488a4	syncookie_secret
+EXPORT_SYMBOL vmlinux 0x954cbb26	vsprintf
+EXPORT_SYMBOL vmlinux 0x9564984b	sock_get_timestampns
+EXPORT_SYMBOL vmlinux 0x956505f3	install_exec_creds
+EXPORT_SYMBOL vmlinux 0x959150fa	notify_change
+EXPORT_SYMBOL vmlinux 0x95b18846	dev_mc_delete
+EXPORT_SYMBOL vmlinux 0x9629486a	per_cpu__cpu_number
+EXPORT_SYMBOL vmlinux 0x96357870	cfb_fillrect
+EXPORT_SYMBOL vmlinux 0x963e309d	xen_io_delay
+EXPORT_SYMBOL vmlinux 0x96409c07	lock_fb_info
+EXPORT_SYMBOL vmlinux 0x965d0870	xfrm_user_policy
+EXPORT_SYMBOL vmlinux 0x967427ac	kunmap
+EXPORT_SYMBOL vmlinux 0x9679d041	truncate_inode_pages
+EXPORT_SYMBOL vmlinux 0x96898769	sysfs_format_mac
+EXPORT_SYMBOL vmlinux 0x96972e70	tty_register_ldisc
+EXPORT_SYMBOL vmlinux 0x96bdf581	dma_pool_create
+EXPORT_SYMBOL vmlinux 0x96f52549	pci_remove_behind_bridge
+EXPORT_SYMBOL vmlinux 0x9727a7ae	kernel_listen
+EXPORT_SYMBOL vmlinux 0x973873ab	_spin_lock
+EXPORT_SYMBOL vmlinux 0x9754ec10	radix_tree_preload
+EXPORT_SYMBOL vmlinux 0x97604084	key_validate
+EXPORT_SYMBOL vmlinux 0x97725489	dquot_claim_space
+EXPORT_SYMBOL vmlinux 0x9772e6a7	simple_write_end
+EXPORT_SYMBOL vmlinux 0x9797c644	atomic_dec_and_mutex_lock
+EXPORT_SYMBOL vmlinux 0x97ca89a4	__breadahead
+EXPORT_SYMBOL vmlinux 0x9800f13e	gnet_stats_copy_queue
+EXPORT_SYMBOL vmlinux 0x980b0b4e	iget5_locked
+EXPORT_SYMBOL vmlinux 0x98111843	sock_queue_rcv_skb
+EXPORT_SYMBOL vmlinux 0x981ad605	vfs_quota_enable
+EXPORT_SYMBOL vmlinux 0x984dbf2d	config_item_get
+EXPORT_SYMBOL vmlinux 0x986e6135	fb_pad_unaligned_buffer
+EXPORT_SYMBOL vmlinux 0x988ed85d	set_memory_x
+EXPORT_SYMBOL vmlinux 0x989b7dd9	tty_chars_in_buffer
+EXPORT_SYMBOL vmlinux 0x98a6a916	tcp_simple_retransmit
+EXPORT_SYMBOL vmlinux 0x98b61711	pci_target_state
+EXPORT_SYMBOL vmlinux 0x98ba3b81	tcf_hash_new_index
+EXPORT_SYMBOL vmlinux 0x98f82ac3	inet_getname
+EXPORT_SYMBOL vmlinux 0x98f88f9b	d_alloc_root
+EXPORT_SYMBOL vmlinux 0x993c024f	proto_unregister
+EXPORT_SYMBOL vmlinux 0x99461bf6	unregister_qdisc
+EXPORT_SYMBOL vmlinux 0x99493c8b	block_write_full_page
+EXPORT_SYMBOL vmlinux 0x996090c7	sock_no_recvmsg
+EXPORT_SYMBOL vmlinux 0x9972b43f	register_sysctl_paths
+EXPORT_SYMBOL vmlinux 0x99911ece	tcp_prot
+EXPORT_SYMBOL vmlinux 0x9994c0ca	ps2_is_keyboard_id
+EXPORT_SYMBOL vmlinux 0x999c533b	splice_direct_to_actor
+EXPORT_SYMBOL vmlinux 0x999e8297	vfree
+EXPORT_SYMBOL vmlinux 0x99acec63	init_net
+EXPORT_SYMBOL vmlinux 0x99b922ea	inet_stream_connect
+EXPORT_SYMBOL vmlinux 0x99bfbe39	get_unused_fd
+EXPORT_SYMBOL vmlinux 0x99c77b2b	sock_tx_timestamp
+EXPORT_SYMBOL vmlinux 0x99c7a8b8	jbd2_dev_to_name
+EXPORT_SYMBOL vmlinux 0x99cb26c1	ether_setup
+EXPORT_SYMBOL vmlinux 0x99cdc86b	sysctl_tcp_reordering
+EXPORT_SYMBOL vmlinux 0x99db04b2	dma_release_from_coherent
+EXPORT_SYMBOL vmlinux 0x99ea12ce	panic_blink
+EXPORT_SYMBOL vmlinux 0x9a08b761	phy_driver_register
+EXPORT_SYMBOL vmlinux 0x9a1dfd65	strpbrk
+EXPORT_SYMBOL vmlinux 0x9a64d1cf	cdev_alloc
+EXPORT_SYMBOL vmlinux 0x9a6a83f9	cmos_lock
+EXPORT_SYMBOL vmlinux 0x9a7cc107	blk_make_request
+EXPORT_SYMBOL vmlinux 0x9a946cc2	follow_down
+EXPORT_SYMBOL vmlinux 0x9a960cbc	tty_pair_get_pty
+EXPORT_SYMBOL vmlinux 0x9a9985be	percpu_counter_destroy
+EXPORT_SYMBOL vmlinux 0x9aa32630	machine_halt
+EXPORT_SYMBOL vmlinux 0x9ad6d09d	sock_no_setsockopt
+EXPORT_SYMBOL vmlinux 0x9ad9057c	sock_wfree
+EXPORT_SYMBOL vmlinux 0x9adb1bb7	request_firmware_nowait
+EXPORT_SYMBOL vmlinux 0x9ae5b3bd	vfs_follow_link
+EXPORT_SYMBOL vmlinux 0x9b388444	get_zeroed_page
+EXPORT_SYMBOL vmlinux 0x9b4de8eb	idr_replace
+EXPORT_SYMBOL vmlinux 0x9b6272ce	dev_open
+EXPORT_SYMBOL vmlinux 0x9b6cd508	deny_write_access
+EXPORT_SYMBOL vmlinux 0x9b6eb137	ksize
+EXPORT_SYMBOL vmlinux 0x9b87f3dc	igrab
+EXPORT_SYMBOL vmlinux 0x9b9c65fa	qdisc_watchdog_schedule
+EXPORT_SYMBOL vmlinux 0x9ba7089d	argv_split
+EXPORT_SYMBOL vmlinux 0x9c012508	fb_parse_edid
+EXPORT_SYMBOL vmlinux 0x9c23d5eb	seq_bitmap_list
+EXPORT_SYMBOL vmlinux 0x9c2c944a	__copy_from_user_ll_nocache_nozero
+EXPORT_SYMBOL vmlinux 0x9c35b693	vga_set_legacy_decoding
+EXPORT_SYMBOL vmlinux 0x9c3c10ad	dev_alloc_name
+EXPORT_SYMBOL vmlinux 0x9c41f8c8	tty_pair_get_tty
+EXPORT_SYMBOL vmlinux 0x9c491f60	sg_alloc_table
+EXPORT_SYMBOL vmlinux 0x9c52bbf0	register_exec_domain
+EXPORT_SYMBOL vmlinux 0x9c7077bd	enable_hlt
+EXPORT_SYMBOL vmlinux 0x9c71e738	per_cpu__vm_event_states
+EXPORT_SYMBOL vmlinux 0x9c792887	nobh_write_begin
+EXPORT_SYMBOL vmlinux 0x9c990b11	neigh_table_init_no_netlink
+EXPORT_SYMBOL vmlinux 0x9c9f7ca7	simple_write_begin
+EXPORT_SYMBOL vmlinux 0x9ca3259a	get_sb_ns
+EXPORT_SYMBOL vmlinux 0x9cb4bbe3	__splice_from_pipe
+EXPORT_SYMBOL vmlinux 0x9cb96e92	qdisc_put_rtab
+EXPORT_SYMBOL vmlinux 0x9cc8e94a	jbd2_journal_revoke
+EXPORT_SYMBOL vmlinux 0x9ccb2622	finish_wait
+EXPORT_SYMBOL vmlinux 0x9ce80908	truncate_inode_pages_range
+EXPORT_SYMBOL vmlinux 0x9ceb163c	memcpy_toiovec
+EXPORT_SYMBOL vmlinux 0x9ced38aa	down_trylock
+EXPORT_SYMBOL vmlinux 0x9d0a2e62	dma_set_mask
+EXPORT_SYMBOL vmlinux 0x9d223b35	dm_kcopyd_copy
+EXPORT_SYMBOL vmlinux 0x9d3aa376	blk_iopoll_init
+EXPORT_SYMBOL vmlinux 0x9d3f25c9	block_page_mkwrite
+EXPORT_SYMBOL vmlinux 0x9d4e6abf	sk_stream_wait_close
+EXPORT_SYMBOL vmlinux 0x9d593a63	dev_addr_del_multiple
+EXPORT_SYMBOL vmlinux 0x9d5d32c3	security_path_rename
+EXPORT_SYMBOL vmlinux 0x9d80c823	skb_dma_unmap
+EXPORT_SYMBOL vmlinux 0x9d984de0	fsync_bdev
+EXPORT_SYMBOL vmlinux 0x9d9da3ad	alloc_buffer_head
+EXPORT_SYMBOL vmlinux 0x9da7fe99	genlmsg_multicast_allns
+EXPORT_SYMBOL vmlinux 0x9db8ef2f	pci_scan_bus_parented
+EXPORT_SYMBOL vmlinux 0x9e1a65d4	splice_from_pipe_feed
+EXPORT_SYMBOL vmlinux 0x9e2000a7	memcpy_toiovecend
+EXPORT_SYMBOL vmlinux 0x9e2e06c3	vfs_unlink
+EXPORT_SYMBOL vmlinux 0x9e42452c	__nla_put
+EXPORT_SYMBOL vmlinux 0x9e4b3747	sg_copy_from_buffer
+EXPORT_SYMBOL vmlinux 0x9e64fbfe	rtc_cmos_read
+EXPORT_SYMBOL vmlinux 0x9e7d6bd0	__udelay
+EXPORT_SYMBOL vmlinux 0x9e9f1714	__bitmap_andnot
+EXPORT_SYMBOL vmlinux 0x9ea0ad49	__sg_free_table
+EXPORT_SYMBOL vmlinux 0x9eb935e9	load_nls
+EXPORT_SYMBOL vmlinux 0x9ebd4c04	adjust_resource
+EXPORT_SYMBOL vmlinux 0x9ec57579	dquot_alloc_inode
+EXPORT_SYMBOL vmlinux 0x9ed07bc7	vga_tryget
+EXPORT_SYMBOL vmlinux 0x9ed685ee	iov_iter_advance
+EXPORT_SYMBOL vmlinux 0x9eecde16	do_brk
+EXPORT_SYMBOL vmlinux 0x9ef2d2a3	journal_get_undo_access
+EXPORT_SYMBOL vmlinux 0x9efef863	bio_uncopy_user
+EXPORT_SYMBOL vmlinux 0x9f100139	jiffies_to_clock_t
+EXPORT_SYMBOL vmlinux 0x9f1701a6	pcim_iounmap_regions
+EXPORT_SYMBOL vmlinux 0x9f26fd94	inet_sendmsg
+EXPORT_SYMBOL vmlinux 0x9f2bdaac	__bitmap_or
+EXPORT_SYMBOL vmlinux 0x9f2d613e	param_set_bool
+EXPORT_SYMBOL vmlinux 0x9f326dd0	tcp_sendpage
+EXPORT_SYMBOL vmlinux 0x9f39d786	rtnl_set_sk_err
+EXPORT_SYMBOL vmlinux 0x9f768885	neigh_destroy
+EXPORT_SYMBOL vmlinux 0x9f816d76	__nla_reserve
+EXPORT_SYMBOL vmlinux 0x9f86a623	textsearch_unregister
+EXPORT_SYMBOL vmlinux 0x9f936ae8	sock_i_uid
+EXPORT_SYMBOL vmlinux 0x9f984513	strrchr
+EXPORT_SYMBOL vmlinux 0x9f9bd6ca	inet_listen
+EXPORT_SYMBOL vmlinux 0x9fa274b4	dq_data_lock
+EXPORT_SYMBOL vmlinux 0x9fb3dd30	memcpy_fromiovec
+EXPORT_SYMBOL vmlinux 0x9fe6c608	kmem_cache_shrink
+EXPORT_SYMBOL vmlinux 0xa03523d5	security_unix_stream_connect
+EXPORT_SYMBOL vmlinux 0xa04a01bd	qdisc_class_hash_insert
+EXPORT_SYMBOL vmlinux 0xa05c03df	mempool_kmalloc
+EXPORT_SYMBOL vmlinux 0xa0689838	blk_queue_dma_alignment
+EXPORT_SYMBOL vmlinux 0xa0a4ac21	tcf_hash_insert
+EXPORT_SYMBOL vmlinux 0xa0a60a63	skb_free_datagram_locked
+EXPORT_SYMBOL vmlinux 0xa0a8fab3	__dev_remove_pack
+EXPORT_SYMBOL vmlinux 0xa0b04675	vmalloc_32
+EXPORT_SYMBOL vmlinux 0xa0bb6ab0	pci_set_dma_seg_boundary
+EXPORT_SYMBOL vmlinux 0xa0bc75f9	test_set_page_writeback
+EXPORT_SYMBOL vmlinux 0xa0c834bd	unmap_mapping_range
+EXPORT_SYMBOL vmlinux 0xa0ceef51	out_of_line_wait_on_bit
+EXPORT_SYMBOL vmlinux 0xa0dd54b4	tty_throttle
+EXPORT_SYMBOL vmlinux 0xa0fbac79	wake_up_bit
+EXPORT_SYMBOL vmlinux 0xa1041361	__mark_inode_dirty
+EXPORT_SYMBOL vmlinux 0xa108eb4d	sysctl_optmem_max
+EXPORT_SYMBOL vmlinux 0xa113294a	ilookup5_nowait
+EXPORT_SYMBOL vmlinux 0xa120d33c	tty_unregister_ldisc
+EXPORT_SYMBOL vmlinux 0xa13798f8	printk_ratelimit
+EXPORT_SYMBOL vmlinux 0xa13de384	pagevec_lookup_tag
+EXPORT_SYMBOL vmlinux 0xa15cafac	xfrm_policy_byid
+EXPORT_SYMBOL vmlinux 0xa16d6201	ip_xfrm_me_harder
+EXPORT_SYMBOL vmlinux 0xa1b759ce	fb_add_videomode
+EXPORT_SYMBOL vmlinux 0xa1c76e0a	_cond_resched
+EXPORT_SYMBOL vmlinux 0xa1de8f11	tty_wait_until_sent
+EXPORT_SYMBOL vmlinux 0xa20ce1b8	net_msg_warn
+EXPORT_SYMBOL vmlinux 0xa21844fe	set_binfmt
+EXPORT_SYMBOL vmlinux 0xa27e34ed	netpoll_cleanup
+EXPORT_SYMBOL vmlinux 0xa290f4ff	journal_force_commit
+EXPORT_SYMBOL vmlinux 0xa2937b06	inet_csk_init_xmit_timers
+EXPORT_SYMBOL vmlinux 0xa29b1708	tcp_memory_allocated
+EXPORT_SYMBOL vmlinux 0xa2a1e5c9	_write_lock_bh
+EXPORT_SYMBOL vmlinux 0xa2a5fd77	inet_ehash_secret
+EXPORT_SYMBOL vmlinux 0xa2b8a2ba	__init_rwsem
+EXPORT_SYMBOL vmlinux 0xa307b714	kthread_bind
+EXPORT_SYMBOL vmlinux 0xa31b9156	mdiobus_unregister
+EXPORT_SYMBOL vmlinux 0xa329f07e	register_shrinker
+EXPORT_SYMBOL vmlinux 0xa332cdd1	security_tun_dev_attach
+EXPORT_SYMBOL vmlinux 0xa33fa63e	vga_client_register
+EXPORT_SYMBOL vmlinux 0xa34f1ef5	crc32_le
+EXPORT_SYMBOL vmlinux 0xa350a8f8	set_memory_array_uc
+EXPORT_SYMBOL vmlinux 0xa35de80f	ipv4_config
+EXPORT_SYMBOL vmlinux 0xa3b1539f	security_inode_setsecctx
+EXPORT_SYMBOL vmlinux 0xa3bc3a16	sb_min_blocksize
+EXPORT_SYMBOL vmlinux 0xa3ce7c0a	nobh_truncate_page
+EXPORT_SYMBOL vmlinux 0xa3e8fa5e	vmtruncate
+EXPORT_SYMBOL vmlinux 0xa3f98a48	neigh_event_ns
+EXPORT_SYMBOL vmlinux 0xa415b384	try_to_del_timer_sync
+EXPORT_SYMBOL vmlinux 0xa41ac95a	__invalidate_device
+EXPORT_SYMBOL vmlinux 0xa4384269	xfrm_state_delete_tunnel
+EXPORT_SYMBOL vmlinux 0xa43b9539	memcpy_fromiovecend
+EXPORT_SYMBOL vmlinux 0xa44ad274	wait_for_completion_interruptible_timeout
+EXPORT_SYMBOL vmlinux 0xa44c1443	tcp_v4_connect
+EXPORT_SYMBOL vmlinux 0xa45df4ee	rwsem_down_write_failed
+EXPORT_SYMBOL vmlinux 0xa4a4022a	ps2_init
+EXPORT_SYMBOL vmlinux 0xa4b384ee	neigh_lookup_nodev
+EXPORT_SYMBOL vmlinux 0xa4b94fea	iowrite8_rep
+EXPORT_SYMBOL vmlinux 0xa4c2a6ce	seq_putc
+EXPORT_SYMBOL vmlinux 0xa506bc8a	jbd2_journal_wipe
+EXPORT_SYMBOL vmlinux 0xa51bd25e	vga_get
+EXPORT_SYMBOL vmlinux 0xa51cdfe8	__FIXADDR_TOP
+EXPORT_SYMBOL vmlinux 0xa5675432	tty_flip_buffer_push
+EXPORT_SYMBOL vmlinux 0xa56f1315	mempool_free
+EXPORT_SYMBOL vmlinux 0xa5808bbf	tasklet_init
+EXPORT_SYMBOL vmlinux 0xa582f749	dcache_readdir
+EXPORT_SYMBOL vmlinux 0xa58b6804	nla_parse
+EXPORT_SYMBOL vmlinux 0xa5922bb1	kfifo_init
+EXPORT_SYMBOL vmlinux 0xa598e29c	vesa_modes
+EXPORT_SYMBOL vmlinux 0xa5ab31a4	nf_unregister_hooks
+EXPORT_SYMBOL vmlinux 0xa5b765ae	set_anon_super
+EXPORT_SYMBOL vmlinux 0xa5bbb17e	proc_dointvec_userhz_jiffies
+EXPORT_SYMBOL vmlinux 0xa6054446	pci_lost_interrupt
+EXPORT_SYMBOL vmlinux 0xa63a92fe	splice_from_pipe_begin
+EXPORT_SYMBOL vmlinux 0xa63d85ab	slhc_remember
+EXPORT_SYMBOL vmlinux 0xa658b098	bio_integrity_tag_size
+EXPORT_SYMBOL vmlinux 0xa658d559	blk_queue_end_tag
+EXPORT_SYMBOL vmlinux 0xa6632766	blk_rq_map_user_iov
+EXPORT_SYMBOL vmlinux 0xa68124fa	hweight8
+EXPORT_SYMBOL vmlinux 0xa681fe88	generate_random_uuid
+EXPORT_SYMBOL vmlinux 0xa689f072	pci_pme_active
+EXPORT_SYMBOL vmlinux 0xa6a74f89	may_umount_tree
+EXPORT_SYMBOL vmlinux 0xa6c0d638	cdev_del
+EXPORT_SYMBOL vmlinux 0xa6dcc773	rb_insert_color
+EXPORT_SYMBOL vmlinux 0xa7046549	vprintk
+EXPORT_SYMBOL vmlinux 0xa71dcb9e	tty_mutex
+EXPORT_SYMBOL vmlinux 0xa750be18	should_remove_suid
+EXPORT_SYMBOL vmlinux 0xa7599958	serio_open
+EXPORT_SYMBOL vmlinux 0xa785f169	tty_name
+EXPORT_SYMBOL vmlinux 0xa792eacb	generic_getxattr
+EXPORT_SYMBOL vmlinux 0xa7b60139	__free_pages
+EXPORT_SYMBOL vmlinux 0xa7c95edb	jbd2_journal_errno
+EXPORT_SYMBOL vmlinux 0xa7cd974f	create_empty_buffers
+EXPORT_SYMBOL vmlinux 0xa7f210ce	ip_route_input
+EXPORT_SYMBOL vmlinux 0xa819fa8e	elv_rb_add
+EXPORT_SYMBOL vmlinux 0xa8437611	blk_get_request
+EXPORT_SYMBOL vmlinux 0xa84982ff	__getblk
+EXPORT_SYMBOL vmlinux 0xa84d9f39	blk_init_queue_node
+EXPORT_SYMBOL vmlinux 0xa8535674	grab_cache_page_write_begin
+EXPORT_SYMBOL vmlinux 0xa85ef359	dget_locked
+EXPORT_SYMBOL vmlinux 0xa8851b37	lock_may_read
+EXPORT_SYMBOL vmlinux 0xa88709b1	kill_block_super
+EXPORT_SYMBOL vmlinux 0xa8a6f639	__check_region
+EXPORT_SYMBOL vmlinux 0xa8aacd30	have_submounts
+EXPORT_SYMBOL vmlinux 0xa8e82d95	vfs_set_dqinfo
+EXPORT_SYMBOL vmlinux 0xa8f11bad	netdev_features_change
+EXPORT_SYMBOL vmlinux 0xa8fef7bb	security_unix_may_send
+EXPORT_SYMBOL vmlinux 0xa941f6ee	ethtool_op_set_tx_csum
+EXPORT_SYMBOL vmlinux 0xa96a5e34	journal_release_buffer
+EXPORT_SYMBOL vmlinux 0xa96e2513	netpoll_setup
+EXPORT_SYMBOL vmlinux 0xa9d9beba	setup_arg_pages
+EXPORT_SYMBOL vmlinux 0xa9e733f8	write_cache_pages
+EXPORT_SYMBOL vmlinux 0xa9fcf31d	wait_for_completion_interruptible
+EXPORT_SYMBOL vmlinux 0xaa25282a	textsearch_register
+EXPORT_SYMBOL vmlinux 0xaa253631	serio_unregister_child_port
+EXPORT_SYMBOL vmlinux 0xaa28b9a3	__skb_checksum_complete_head
+EXPORT_SYMBOL vmlinux 0xaa3577a2	llc_set_station_handler
+EXPORT_SYMBOL vmlinux 0xaa59df73	neigh_changeaddr
+EXPORT_SYMBOL vmlinux 0xaa5df19b	mark_buffer_dirty_inode
+EXPORT_SYMBOL vmlinux 0xaa7752df	kern_path
+EXPORT_SYMBOL vmlinux 0xaa96d1cd	blkdev_get
+EXPORT_SYMBOL vmlinux 0xaaa61617	flush_signals
+EXPORT_SYMBOL vmlinux 0xaaa683f6	lock_may_write
+EXPORT_SYMBOL vmlinux 0xaab06af8	_write_lock_irqsave
+EXPORT_SYMBOL vmlinux 0xaabc82dd	boot_cpu_data
+EXPORT_SYMBOL vmlinux 0xaae5d4c8	kblockd_schedule_work
+EXPORT_SYMBOL vmlinux 0xaafdc258	strcasecmp
+EXPORT_SYMBOL vmlinux 0xab4c1058	inet_add_protocol
+EXPORT_SYMBOL vmlinux 0xab51ce39	vfs_get_dqblk
+EXPORT_SYMBOL vmlinux 0xab600421	probe_irq_off
+EXPORT_SYMBOL vmlinux 0xab61a71d	find_get_pages_contig
+EXPORT_SYMBOL vmlinux 0xab65ed80	set_memory_uc
+EXPORT_SYMBOL vmlinux 0xab68e079	skb_recycle_check
+EXPORT_SYMBOL vmlinux 0xab770678	rdmsr_safe_regs_on_cpu
+EXPORT_SYMBOL vmlinux 0xaba9ff34	allocate_resource
+EXPORT_SYMBOL vmlinux 0xabc28976	force_evtchn_callback
+EXPORT_SYMBOL vmlinux 0xabc4c428	__f_setown
+EXPORT_SYMBOL vmlinux 0xabd0c91c	rtc_time_to_tm
+EXPORT_SYMBOL vmlinux 0xabdf887a	sock_common_setsockopt
+EXPORT_SYMBOL vmlinux 0xabef7f01	key_task_permission
+EXPORT_SYMBOL vmlinux 0xabf262a1	skb_prepare_seq_read
+EXPORT_SYMBOL vmlinux 0xac0ba8c1	blk_iopoll_disable
+EXPORT_SYMBOL vmlinux 0xac3a5c39	pci_fixup_cardbus
+EXPORT_SYMBOL vmlinux 0xac63bc72	sync_inodes_sb
+EXPORT_SYMBOL vmlinux 0xac68504b	blk_queue_find_tag
+EXPORT_SYMBOL vmlinux 0xac6855b0	gen_kill_estimator
+EXPORT_SYMBOL vmlinux 0xac806219	key_put
+EXPORT_SYMBOL vmlinux 0xac8382c6	phy_connect_direct
+EXPORT_SYMBOL vmlinux 0xac8d481e	wait_on_page_bit
+EXPORT_SYMBOL vmlinux 0xacb95e3c	udp_lib_unhash
+EXPORT_SYMBOL vmlinux 0xacc63416	vc_resize
+EXPORT_SYMBOL vmlinux 0xaccabc6a	in4_pton
+EXPORT_SYMBOL vmlinux 0xacdcc1a8	netdev_set_master
+EXPORT_SYMBOL vmlinux 0xacdeb154	__tracepoint_module_get
+EXPORT_SYMBOL vmlinux 0xacdf8b53	alloc_tty_driver
+EXPORT_SYMBOL vmlinux 0xacf4d843	match_strdup
+EXPORT_SYMBOL vmlinux 0xad0413d4	match_hex
+EXPORT_SYMBOL vmlinux 0xad1329e1	blk_queue_bounce_limit
+EXPORT_SYMBOL vmlinux 0xad2d81dd	__serio_register_driver
+EXPORT_SYMBOL vmlinux 0xadac2a28	pagecache_write_begin
+EXPORT_SYMBOL vmlinux 0xadc2ac27	simple_set_mnt
+EXPORT_SYMBOL vmlinux 0xade7e9f9	set_bh_page
+EXPORT_SYMBOL vmlinux 0xae2989eb	phy_device_register
+EXPORT_SYMBOL vmlinux 0xae4293a2	writeback_inodes_sb
+EXPORT_SYMBOL vmlinux 0xae75f004	ida_destroy
+EXPORT_SYMBOL vmlinux 0xaea528ac	kmem_cache_destroy
+EXPORT_SYMBOL vmlinux 0xaeace10a	xfrm_policy_delete
+EXPORT_SYMBOL vmlinux 0xaec655c7	alloc_pages_exact
+EXPORT_SYMBOL vmlinux 0xaed013b9	posix_acl_valid
+EXPORT_SYMBOL vmlinux 0xaef01255	kernel_getsockname
+EXPORT_SYMBOL vmlinux 0xaf0e80af	bdevname
+EXPORT_SYMBOL vmlinux 0xaf7af4e7	page_address
+EXPORT_SYMBOL vmlinux 0xafb1835e	pci_disable_msi
+EXPORT_SYMBOL vmlinux 0xafc42bc1	vfs_rmdir
+EXPORT_SYMBOL vmlinux 0xaff94fa1	ethtool_op_get_tx_csum
+EXPORT_SYMBOL vmlinux 0xb006220e	ethtool_op_set_flags
+EXPORT_SYMBOL vmlinux 0xb023f37d	inet_sk_rebuild_header
+EXPORT_SYMBOL vmlinux 0xb024538b	hippi_neigh_setup_dev
+EXPORT_SYMBOL vmlinux 0xb02c2b6c	set_create_files_as
+EXPORT_SYMBOL vmlinux 0xb08f76ad	gen_pool_free
+EXPORT_SYMBOL vmlinux 0xb0b847ac	__bitmap_full
+EXPORT_SYMBOL vmlinux 0xb0e10781	get_option
+EXPORT_SYMBOL vmlinux 0xb0e275d2	ll_rw_block
+EXPORT_SYMBOL vmlinux 0xb121390a	probe_irq_on
+EXPORT_SYMBOL vmlinux 0xb155a231	touch_pte_range
+EXPORT_SYMBOL vmlinux 0xb156a7e1	iw_handler_get_thrspy
+EXPORT_SYMBOL vmlinux 0xb15d7400	end_buffer_write_sync
+EXPORT_SYMBOL vmlinux 0xb1645a2e	sg_free_table
+EXPORT_SYMBOL vmlinux 0xb166fe7f	lro_vlan_hwaccel_receive_skb
+EXPORT_SYMBOL vmlinux 0xb19760c3	bitmap_onto
+EXPORT_SYMBOL vmlinux 0xb1a71bfd	pci_bus_add_devices
+EXPORT_SYMBOL vmlinux 0xb1c3a01a	oops_in_progress
+EXPORT_SYMBOL vmlinux 0xb1cfad22	rdmsr_on_cpu
+EXPORT_SYMBOL vmlinux 0xb1f975aa	unlock_kernel
+EXPORT_SYMBOL vmlinux 0xb20c6096	km_state_notify
+EXPORT_SYMBOL vmlinux 0xb2191f8e	arp_create
+EXPORT_SYMBOL vmlinux 0xb224fbe2	param_get_short
+EXPORT_SYMBOL vmlinux 0xb22fe6a3	netdev_increment_features
+EXPORT_SYMBOL vmlinux 0xb24e2d5a	put_page
+EXPORT_SYMBOL vmlinux 0xb25e75ca	generic_file_open
+EXPORT_SYMBOL vmlinux 0xb2682405	utf8_to_utf32
+EXPORT_SYMBOL vmlinux 0xb26ae335	free_task
+EXPORT_SYMBOL vmlinux 0xb272fd2a	proc_dointvec_jiffies
+EXPORT_SYMBOL vmlinux 0xb27510ef	atomic64_inc_return
+EXPORT_SYMBOL vmlinux 0xb28b2b70	inet_dev_addr_type
+EXPORT_SYMBOL vmlinux 0xb28e9dc8	phy_device_create
+EXPORT_SYMBOL vmlinux 0xb28fd8e4	gnet_stats_copy_basic
+EXPORT_SYMBOL vmlinux 0xb29bc8bd	idr_remove
+EXPORT_SYMBOL vmlinux 0xb2ab46b8	__netdev_alloc_page
+EXPORT_SYMBOL vmlinux 0xb2c81848	bioset_free
+EXPORT_SYMBOL vmlinux 0xb2e55898	cpu_possible_mask
+EXPORT_SYMBOL vmlinux 0xb2eb3610	phy_start_aneg
+EXPORT_SYMBOL vmlinux 0xb2ef6970	console_stop
+EXPORT_SYMBOL vmlinux 0xb2f400f9	vfs_quota_on_mount
+EXPORT_SYMBOL vmlinux 0xb2f9017b	blk_queue_bounce
+EXPORT_SYMBOL vmlinux 0xb2fd5ceb	__put_user_4
+EXPORT_SYMBOL vmlinux 0xb30abf8d	idr_get_new_above
+EXPORT_SYMBOL vmlinux 0xb3205415	wait_for_completion_killable
+EXPORT_SYMBOL vmlinux 0xb352177e	find_first_bit
+EXPORT_SYMBOL vmlinux 0xb375caf6	file_update_time
+EXPORT_SYMBOL vmlinux 0xb376d79d	radix_tree_tagged
+EXPORT_SYMBOL vmlinux 0xb386a826	inode_needs_sync
+EXPORT_SYMBOL vmlinux 0xb38abf22	send_sig
+EXPORT_SYMBOL vmlinux 0xb396868d	pci_enable_device_mem
+EXPORT_SYMBOL vmlinux 0xb3994c7a	per_cpu__kstat
+EXPORT_SYMBOL vmlinux 0xb3a307c6	si_meminfo
+EXPORT_SYMBOL vmlinux 0xb3adf679	gnttab_pre_map_adjust
+EXPORT_SYMBOL vmlinux 0xb3b0254f	phy_device_free
+EXPORT_SYMBOL vmlinux 0xb3bb1608	swiotlb_sync_single_for_device
+EXPORT_SYMBOL vmlinux 0xb3c6d32a	unregister_con_driver
+EXPORT_SYMBOL vmlinux 0xb3ca5275	tcp_init_xmit_timers
+EXPORT_SYMBOL vmlinux 0xb3d06d73	audit_log_start
+EXPORT_SYMBOL vmlinux 0xb3e5211a	ppp_input
+EXPORT_SYMBOL vmlinux 0xb3f9e131	pci_bus_find_capability
+EXPORT_SYMBOL vmlinux 0xb4096496	skb_store_bits
+EXPORT_SYMBOL vmlinux 0xb423dba1	console_blanked
+EXPORT_SYMBOL vmlinux 0xb42453d3	param_get_invbool
+EXPORT_SYMBOL vmlinux 0xb4279ab7	downgrade_write
+EXPORT_SYMBOL vmlinux 0xb43a20fe	pci_set_master
+EXPORT_SYMBOL vmlinux 0xb440a795	datagram_poll
+EXPORT_SYMBOL vmlinux 0xb440dc17	nonseekable_open
+EXPORT_SYMBOL vmlinux 0xb443ae24	udp_proc_unregister
+EXPORT_SYMBOL vmlinux 0xb44e2ec3	pneigh_lookup
+EXPORT_SYMBOL vmlinux 0xb45578b8	memscan
+EXPORT_SYMBOL vmlinux 0xb45b24f6	k8_nb_ids
+EXPORT_SYMBOL vmlinux 0xb472a799	fb_get_mode
+EXPORT_SYMBOL vmlinux 0xb4b0ee4e	down_read
+EXPORT_SYMBOL vmlinux 0xb4ca9447	__kfifo_get
+EXPORT_SYMBOL vmlinux 0xb5044271	vsscanf
+EXPORT_SYMBOL vmlinux 0xb510c65f	scm_fp_dup
+EXPORT_SYMBOL vmlinux 0xb526150e	kill_litter_super
+EXPORT_SYMBOL vmlinux 0xb5418861	atomic64_add
+EXPORT_SYMBOL vmlinux 0xb54533f7	usecs_to_jiffies
+EXPORT_SYMBOL vmlinux 0xb55b5121	search_binary_handler
+EXPORT_SYMBOL vmlinux 0xb57ea60a	file_remove_suid
+EXPORT_SYMBOL vmlinux 0xb58ede41	do_splice_to
+EXPORT_SYMBOL vmlinux 0xb597abb2	read_dev_sector
+EXPORT_SYMBOL vmlinux 0xb5a459dc	unregister_blkdev
+EXPORT_SYMBOL vmlinux 0xb5ae180a	tcp_sync_mss
+EXPORT_SYMBOL vmlinux 0xb5ca1c46	slhc_free
+EXPORT_SYMBOL vmlinux 0xb5e61e2f	jbd2_journal_set_triggers
+EXPORT_SYMBOL vmlinux 0xb5f28b5f	__any_online_cpu
+EXPORT_SYMBOL vmlinux 0xb613dde7	clip_tbl_hook
+EXPORT_SYMBOL vmlinux 0xb6244511	sg_init_one
+EXPORT_SYMBOL vmlinux 0xb635536b	tcp_rcv_established
+EXPORT_SYMBOL vmlinux 0xb637a29d	unlock_page
+EXPORT_SYMBOL vmlinux 0xb64a4c96	dev_close
+EXPORT_SYMBOL vmlinux 0xb64f6715	blkdev_issue_flush
+EXPORT_SYMBOL vmlinux 0xb6604341	kmap_atomic_prot
+EXPORT_SYMBOL vmlinux 0xb66b5a23	elv_abort_queue
+EXPORT_SYMBOL vmlinux 0xb678366f	int_sqrt
+EXPORT_SYMBOL vmlinux 0xb6823b21	skb_copy_and_csum_dev
+EXPORT_SYMBOL vmlinux 0xb6a61a86	qdisc_get_rtab
+EXPORT_SYMBOL vmlinux 0xb6a68816	find_last_bit
+EXPORT_SYMBOL vmlinux 0xb6bffb99	kstat_irqs_cpu
+EXPORT_SYMBOL vmlinux 0xb6debe00	journal_ack_err
+EXPORT_SYMBOL vmlinux 0xb6e227aa	rtc_lock
+EXPORT_SYMBOL vmlinux 0xb6ed1e53	strncpy
+EXPORT_SYMBOL vmlinux 0xb72397d5	printk
+EXPORT_SYMBOL vmlinux 0xb76d89de	jiffies_to_st
+EXPORT_SYMBOL vmlinux 0xb798b8e4	flow_cache_lookup
+EXPORT_SYMBOL vmlinux 0xb79a870e	__xfrm_lookup
+EXPORT_SYMBOL vmlinux 0xb7b61546	crc32_be
+EXPORT_SYMBOL vmlinux 0xb7c4fd19	generic_writepages
+EXPORT_SYMBOL vmlinux 0xb7db2179	xfrm_alloc_spi
+EXPORT_SYMBOL vmlinux 0xb7dd0512	km_query
+EXPORT_SYMBOL vmlinux 0xb7ef2ae6	bdev_read_only
+EXPORT_SYMBOL vmlinux 0xb80fa05c	generic_removexattr
+EXPORT_SYMBOL vmlinux 0xb813ce5a	timecompare_transform
+EXPORT_SYMBOL vmlinux 0xb81528e2	sync_blockdev
+EXPORT_SYMBOL vmlinux 0xb8238c42	cdev_add
+EXPORT_SYMBOL vmlinux 0xb8251588	bdi_register
+EXPORT_SYMBOL vmlinux 0xb84071d0	netif_carrier_off
+EXPORT_SYMBOL vmlinux 0xb84ed32f	proc_doulongvec_minmax
+EXPORT_SYMBOL vmlinux 0xb86e4ab9	random32
+EXPORT_SYMBOL vmlinux 0xb88d21f7	bio_free
+EXPORT_SYMBOL vmlinux 0xb88df48d	fput
+EXPORT_SYMBOL vmlinux 0xb89af9bf	srandom32
+EXPORT_SYMBOL vmlinux 0xb8e7ce2c	__put_user_8
+EXPORT_SYMBOL vmlinux 0xb8e848d3	icmp_send
+EXPORT_SYMBOL vmlinux 0xb8e97c1f	inet_release
+EXPORT_SYMBOL vmlinux 0xb8fc1861	ioctl_by_bdev
+EXPORT_SYMBOL vmlinux 0xb8fe2fe4	tty_port_lower_dtr_rts
+EXPORT_SYMBOL vmlinux 0xb8feddcb	dquot_mark_dquot_dirty
+EXPORT_SYMBOL vmlinux 0xb91c8e67	cap_netlink_recv
+EXPORT_SYMBOL vmlinux 0xb946cb9e	simple_transaction_get
+EXPORT_SYMBOL vmlinux 0xb96aad6a	mark_buffer_async_write
+EXPORT_SYMBOL vmlinux 0xb97b1bd2	skb_copy_datagram_const_iovec
+EXPORT_SYMBOL vmlinux 0xb98a0185	rtc_tm_to_time
+EXPORT_SYMBOL vmlinux 0xb98ef804	vm_stat
+EXPORT_SYMBOL vmlinux 0xb99cc2bc	blk_init_queue
+EXPORT_SYMBOL vmlinux 0xb9a6d4d0	bdi_set_max_ratio
+EXPORT_SYMBOL vmlinux 0xb9ced621	find_inode_number
+EXPORT_SYMBOL vmlinux 0xb9d3ea1c	pci_reenable_device
+EXPORT_SYMBOL vmlinux 0xba0445a2	journal_invalidatepage
+EXPORT_SYMBOL vmlinux 0xba075502	mutex_lock_killable
+EXPORT_SYMBOL vmlinux 0xba497f13	loops_per_jiffy
+EXPORT_SYMBOL vmlinux 0xba535108	xfrm_policy_walk
+EXPORT_SYMBOL vmlinux 0xba54204d	jbd2_journal_get_undo_access
+EXPORT_SYMBOL vmlinux 0xba91a224	sock_rfree
+EXPORT_SYMBOL vmlinux 0xbaaab8ae	timespec_to_jiffies
+EXPORT_SYMBOL vmlinux 0xbabbdc69	generic_write_end
+EXPORT_SYMBOL vmlinux 0xbabbe382	bio_add_pc_page
+EXPORT_SYMBOL vmlinux 0xbaec6f6a	xfrm_state_walk
+EXPORT_SYMBOL vmlinux 0xbb025a28	generic_permission
+EXPORT_SYMBOL vmlinux 0xbb150715	tcf_generic_walker
+EXPORT_SYMBOL vmlinux 0xbb15b939	tty_port_alloc_xmit_buf
+EXPORT_SYMBOL vmlinux 0xbb167766	fb_var_to_videomode
+EXPORT_SYMBOL vmlinux 0xbb189cad	disallow_signal
+EXPORT_SYMBOL vmlinux 0xbb1b16bd	tcp_recvmsg
+EXPORT_SYMBOL vmlinux 0xbb1beac9	get_sb_bdev
+EXPORT_SYMBOL vmlinux 0xbb243235	block_prepare_write
+EXPORT_SYMBOL vmlinux 0xbb334a87	jbd2_journal_set_features
+EXPORT_SYMBOL vmlinux 0xbb3b5ffa	hippi_type_trans
+EXPORT_SYMBOL vmlinux 0xbb5d343d	xfrm_get_acqseq
+EXPORT_SYMBOL vmlinux 0xbb60a203	cfb_copyarea
+EXPORT_SYMBOL vmlinux 0xbb89de17	ida_init
+EXPORT_SYMBOL vmlinux 0xbb90c11b	tcf_destroy_chain
+EXPORT_SYMBOL vmlinux 0xbbe3d666	direct_kernel_remap_pfn_range
+EXPORT_SYMBOL vmlinux 0xbc1b61ca	skb_gso_segment
+EXPORT_SYMBOL vmlinux 0xbc710008	__xfrm_state_destroy
+EXPORT_SYMBOL vmlinux 0xbcc308bb	strnlen_user
+EXPORT_SYMBOL vmlinux 0xbcec2486	phy_sanitize_settings
+EXPORT_SYMBOL vmlinux 0xbcf81bb2	__tcp_get_md5sig_pool
+EXPORT_SYMBOL vmlinux 0xbd146f65	config_item_put
+EXPORT_SYMBOL vmlinux 0xbd5bbb7e	swiotlb_unmap_sg_attrs
+EXPORT_SYMBOL vmlinux 0xbd859be2	phy_attach
+EXPORT_SYMBOL vmlinux 0xbdb2d7a3	sock_i_ino
+EXPORT_SYMBOL vmlinux 0xbdca8fd3	xfrm_policy_insert
+EXPORT_SYMBOL vmlinux 0xbddda75f	task_tgid_nr_ns
+EXPORT_SYMBOL vmlinux 0xbdeaf105	phy_ethtool_sset
+EXPORT_SYMBOL vmlinux 0xbdf5c25c	rb_next
+EXPORT_SYMBOL vmlinux 0xbdf669a8	register_tcf_proto_ops
+EXPORT_SYMBOL vmlinux 0xbe0e5118	nla_memcmp
+EXPORT_SYMBOL vmlinux 0xbe534782	elevator_init
+EXPORT_SYMBOL vmlinux 0xbe64b9c0	dquot_scan_active
+EXPORT_SYMBOL vmlinux 0xbeaaf954	pci_match_id
+EXPORT_SYMBOL vmlinux 0xbeae0bb2	pcie_port_service_unregister
+EXPORT_SYMBOL vmlinux 0xbec9d045	vfs_quota_sync
+EXPORT_SYMBOL vmlinux 0xbee3b50b	per_cpu__cpu_info
+EXPORT_SYMBOL vmlinux 0xbee5d719	pci_enable_bridges
+EXPORT_SYMBOL vmlinux 0xbee9b893	atm_dev_lookup
+EXPORT_SYMBOL vmlinux 0xbef43296	console_conditional_schedule
+EXPORT_SYMBOL vmlinux 0xbf05aeac	tcp_initialize_rcv_mss
+EXPORT_SYMBOL vmlinux 0xbf513db7	blk_queue_max_phys_segments
+EXPORT_SYMBOL vmlinux 0xbf7624f3	d_lookup
+EXPORT_SYMBOL vmlinux 0xbf7fd2f5	schedule_timeout_killable
+EXPORT_SYMBOL vmlinux 0xbf9bcc8d	__cap_empty_set
+EXPORT_SYMBOL vmlinux 0xbf9ea3e4	simple_pin_fs
+EXPORT_SYMBOL vmlinux 0xbfc177bc	iowrite32_rep
+EXPORT_SYMBOL vmlinux 0xbfd563f5	qdisc_list_del
+EXPORT_SYMBOL vmlinux 0xbfed6c1e	iget_locked
+EXPORT_SYMBOL vmlinux 0xbfee3ad5	loop_unregister_transfer
+EXPORT_SYMBOL vmlinux 0xc000f425	tcp4_gro_complete
+EXPORT_SYMBOL vmlinux 0xc003c637	__strncpy_from_user
+EXPORT_SYMBOL vmlinux 0xc0044724	blk_set_default_limits
+EXPORT_SYMBOL vmlinux 0xc006ea28	seq_puts
+EXPORT_SYMBOL vmlinux 0xc0159acd	phy_detach
+EXPORT_SYMBOL vmlinux 0xc01eed33	__copy_from_user_ll_nozero
+EXPORT_SYMBOL vmlinux 0xc0580937	rb_erase
+EXPORT_SYMBOL vmlinux 0xc0a3d105	find_next_bit
+EXPORT_SYMBOL vmlinux 0xc0ba7ec1	__bforget
+EXPORT_SYMBOL vmlinux 0xc0bf6ead	timecounter_cyc2time
+EXPORT_SYMBOL vmlinux 0xc11d8093	iov_shorten
+EXPORT_SYMBOL vmlinux 0xc1262c2f	input_inject_event
+EXPORT_SYMBOL vmlinux 0xc12838d5	key_payload_reserve
+EXPORT_SYMBOL vmlinux 0xc1328a11	skb_realloc_headroom
+EXPORT_SYMBOL vmlinux 0xc14366c5	unregister_filesystem
+EXPORT_SYMBOL vmlinux 0xc150fb46	net_accel_shutdown_remote
+EXPORT_SYMBOL vmlinux 0xc15f2261	dquot_alloc
+EXPORT_SYMBOL vmlinux 0xc19c8163	atomic64_cmpxchg
+EXPORT_SYMBOL vmlinux 0xc1fd5e20	nf_afinfo
+EXPORT_SYMBOL vmlinux 0xc21138db	is_bad_inode
+EXPORT_SYMBOL vmlinux 0xc2222f25	unregister_quota_format
+EXPORT_SYMBOL vmlinux 0xc237736b	vcc_release_async
+EXPORT_SYMBOL vmlinux 0xc254af48	dcache_lock
+EXPORT_SYMBOL vmlinux 0xc256e762	__bitmap_equal
+EXPORT_SYMBOL vmlinux 0xc27bdb05	do_splice_from
+EXPORT_SYMBOL vmlinux 0xc280a525	__copy_from_user_ll
+EXPORT_SYMBOL vmlinux 0xc2858aeb	bio_integrity_endio
+EXPORT_SYMBOL vmlinux 0xc2bb2a11	phy_register_fixup_for_uid
+EXPORT_SYMBOL vmlinux 0xc2c295c0	qdisc_calculate_pkt_len
+EXPORT_SYMBOL vmlinux 0xc2d711e1	krealloc
+EXPORT_SYMBOL vmlinux 0xc2e587d1	reset_devices
+EXPORT_SYMBOL vmlinux 0xc2fbc0a4	tcp_v4_syn_recv_sock
+EXPORT_SYMBOL vmlinux 0xc30f49b3	napi_reuse_skb
+EXPORT_SYMBOL vmlinux 0xc33f6f4c	on_each_cpu
+EXPORT_SYMBOL vmlinux 0xc33ff450	ethtool_op_get_flags
+EXPORT_SYMBOL vmlinux 0xc359a71e	__alloc_skb
+EXPORT_SYMBOL vmlinux 0xc3a5ca48	d_validate
+EXPORT_SYMBOL vmlinux 0xc3aaf0a9	__put_user_1
+EXPORT_SYMBOL vmlinux 0xc3cf1128	in_group_p
+EXPORT_SYMBOL vmlinux 0xc3fa6a59	memchr
+EXPORT_SYMBOL vmlinux 0xc419655f	blk_remove_plug
+EXPORT_SYMBOL vmlinux 0xc44fe9d6	pci_bus_read_config_dword
+EXPORT_SYMBOL vmlinux 0xc456b0ef	__put_cred
+EXPORT_SYMBOL vmlinux 0xc4587c1a	single_open
+EXPORT_SYMBOL vmlinux 0xc4611f5e	lookup_bdev
+EXPORT_SYMBOL vmlinux 0xc46306da	pipe_unlock
+EXPORT_SYMBOL vmlinux 0xc499ae1e	kstrdup
+EXPORT_SYMBOL vmlinux 0xc4cda469	xfrm_input
+EXPORT_SYMBOL vmlinux 0xc4e9c01c	cpu_active_mask
+EXPORT_SYMBOL vmlinux 0xc5212623	tty_hung_up_p
+EXPORT_SYMBOL vmlinux 0xc52f5714	fb_videomode_to_var
+EXPORT_SYMBOL vmlinux 0xc5445ca8	cdrom_mode_sense
+EXPORT_SYMBOL vmlinux 0xc5534d64	ioread16
+EXPORT_SYMBOL vmlinux 0xc55f7dc7	_write_trylock
+EXPORT_SYMBOL vmlinux 0xc582fbd8	elv_rq_merge_ok
+EXPORT_SYMBOL vmlinux 0xc5844fb8	__per_cpu_offset
+EXPORT_SYMBOL vmlinux 0xc5a1ce14	pci_request_selected_regions
+EXPORT_SYMBOL vmlinux 0xc5c8b380	sk_free
+EXPORT_SYMBOL vmlinux 0xc6215384	dma_declare_coherent_memory
+EXPORT_SYMBOL vmlinux 0xc633495b	schedule_work
+EXPORT_SYMBOL vmlinux 0xc63c9857	napi_gro_flush
+EXPORT_SYMBOL vmlinux 0xc64b8442	copy_io_context
+EXPORT_SYMBOL vmlinux 0xc64f48fd	set_pages_uc
+EXPORT_SYMBOL vmlinux 0xc6ab5acc	__destroy_inode
+EXPORT_SYMBOL vmlinux 0xc6b03d69	unregister_sysrq_key
+EXPORT_SYMBOL vmlinux 0xc6cf6dc3	tcp_hashinfo
+EXPORT_SYMBOL vmlinux 0xc7208c3a	serial8250_resume_port
+EXPORT_SYMBOL vmlinux 0xc722227e	posix_acl_clone
+EXPORT_SYMBOL vmlinux 0xc73a5af4	vfs_get_dqinfo
+EXPORT_SYMBOL vmlinux 0xc7853156	blk_queue_init_tags
+EXPORT_SYMBOL vmlinux 0xc795e111	proto_register
+EXPORT_SYMBOL vmlinux 0xc79bcd36	dm_vcalloc
+EXPORT_SYMBOL vmlinux 0xc7a4fbed	rtnl_lock
+EXPORT_SYMBOL vmlinux 0xc7a6a6df	blk_queue_dma_pad
+EXPORT_SYMBOL vmlinux 0xc7ec6c27	strspn
+EXPORT_SYMBOL vmlinux 0xc7f2fc77	is_container_init
+EXPORT_SYMBOL vmlinux 0xc80bb4a9	unregister_cdrom
+EXPORT_SYMBOL vmlinux 0xc80d9084	kmem_cache_create
+EXPORT_SYMBOL vmlinux 0xc8114a7e	jbd2_journal_abort
+EXPORT_SYMBOL vmlinux 0xc81bd937	clocksource_register
+EXPORT_SYMBOL vmlinux 0xc8457be3	iov_iter_copy_from_user_atomic
+EXPORT_SYMBOL vmlinux 0xc84cae7f	close_bdev_exclusive
+EXPORT_SYMBOL vmlinux 0xc84d331e	sock_register
+EXPORT_SYMBOL vmlinux 0xc86baa7c	corgibl_limit_intensity
+EXPORT_SYMBOL vmlinux 0xc897c382	sg_init_table
+EXPORT_SYMBOL vmlinux 0xc898625d	atomic64_inc_and_test
+EXPORT_SYMBOL vmlinux 0xc8b57c27	autoremove_wake_function
+EXPORT_SYMBOL vmlinux 0xc8e6e26c	seq_printf
+EXPORT_SYMBOL vmlinux 0xc8e9e090	__lock_buffer
+EXPORT_SYMBOL vmlinux 0xc8ea956d	generic_splice_sendpage
+EXPORT_SYMBOL vmlinux 0xc8f20da9	skb_queue_purge
+EXPORT_SYMBOL vmlinux 0xc8fa493a	create_mnt_ns
+EXPORT_SYMBOL vmlinux 0xc908a4b8	lro_vlan_hwaccel_receive_frags
+EXPORT_SYMBOL vmlinux 0xc9155805	lease_modify
+EXPORT_SYMBOL vmlinux 0xc9668797	mdio_bus_type
+EXPORT_SYMBOL vmlinux 0xc96bd503	blk_complete_request
+EXPORT_SYMBOL vmlinux 0xc976f645	xen_invlpg
+EXPORT_SYMBOL vmlinux 0xc984e90a	devm_ioremap
+EXPORT_SYMBOL vmlinux 0xc998d641	icmp_err_convert
+EXPORT_SYMBOL vmlinux 0xc9d6094d	sock_sendmsg
+EXPORT_SYMBOL vmlinux 0xc9e2937a	skb_free_datagram
+EXPORT_SYMBOL vmlinux 0xc9ec8704	udp_table
+EXPORT_SYMBOL vmlinux 0xca00c503	generic_file_aio_write
+EXPORT_SYMBOL vmlinux 0xca9b374a	thaw_process
+EXPORT_SYMBOL vmlinux 0xcaca5d0e	nf_register_queue_handler
+EXPORT_SYMBOL vmlinux 0xcadb4646	generic_readlink
+EXPORT_SYMBOL vmlinux 0xcaf6ff2d	inode_add_bytes
+EXPORT_SYMBOL vmlinux 0xcb054904	framebuffer_alloc
+EXPORT_SYMBOL vmlinux 0xcb146006	slow_work_enqueue
+EXPORT_SYMBOL vmlinux 0xcb31521d	alloc_pci_dev
+EXPORT_SYMBOL vmlinux 0xcb502b03	default_llseek
+EXPORT_SYMBOL vmlinux 0xcb607e79	bio_integrity_clone
+EXPORT_SYMBOL vmlinux 0xcb6beb40	hweight32
+EXPORT_SYMBOL vmlinux 0xcb7131fb	fb_get_options
+EXPORT_SYMBOL vmlinux 0xcb9c547b	journal_unlock_updates
+EXPORT_SYMBOL vmlinux 0xcbaa2c02	mdiobus_free
+EXPORT_SYMBOL vmlinux 0xcbbf8e59	blk_queue_io_min
+EXPORT_SYMBOL vmlinux 0xcbc591b2	blk_queue_ordered
+EXPORT_SYMBOL vmlinux 0xcc032464	simple_rename
+EXPORT_SYMBOL vmlinux 0xcc16dd6e	iput
+EXPORT_SYMBOL vmlinux 0xcc248d26	serial8250_suspend_port
+EXPORT_SYMBOL vmlinux 0xcc2a5140	inet_register_protosw
+EXPORT_SYMBOL vmlinux 0xcc316874	file_permission
+EXPORT_SYMBOL vmlinux 0xcc36f32e	fb_unregister_client
+EXPORT_SYMBOL vmlinux 0xcc5005fe	msleep_interruptible
+EXPORT_SYMBOL vmlinux 0xcc51ee50	dma_spin_lock
+EXPORT_SYMBOL vmlinux 0xcc533b2b	genphy_restart_aneg
+EXPORT_SYMBOL vmlinux 0xcc564d0c	skb_under_panic
+EXPORT_SYMBOL vmlinux 0xcc693cbe	replace_mount_options
+EXPORT_SYMBOL vmlinux 0xcc7fa952	local_bh_enable_ip
+EXPORT_SYMBOL vmlinux 0xcc939723	loop_register_transfer
+EXPORT_SYMBOL vmlinux 0xcca4b4ce	pci_dev_get
+EXPORT_SYMBOL vmlinux 0xcccd5f3e	genphy_config_advert
+EXPORT_SYMBOL vmlinux 0xccd9c35c	d_find_alias
+EXPORT_SYMBOL vmlinux 0xccee4d68	xen_multicall_flush
+EXPORT_SYMBOL vmlinux 0xcd2194e0	sk_release_kernel
+EXPORT_SYMBOL vmlinux 0xcd4aa44a	abort_creds
+EXPORT_SYMBOL vmlinux 0xcd72f545	devm_request_threaded_irq
+EXPORT_SYMBOL vmlinux 0xcd7f03df	key_type_keyring
+EXPORT_SYMBOL vmlinux 0xcdd46e47	sock_alloc_send_pskb
+EXPORT_SYMBOL vmlinux 0xce0220c5	unregister_binfmt
+EXPORT_SYMBOL vmlinux 0xce1b636a	tcf_unregister_action
+EXPORT_SYMBOL vmlinux 0xce351770	serio_unregister_port
+EXPORT_SYMBOL vmlinux 0xce36ded6	sysctl_tcp_mem
+EXPORT_SYMBOL vmlinux 0xce5ac24f	zlib_inflate_workspacesize
+EXPORT_SYMBOL vmlinux 0xce67857a	dqput
+EXPORT_SYMBOL vmlinux 0xceb27100	skb_pad
+EXPORT_SYMBOL vmlinux 0xced5fa8e	unbind_con_driver
+EXPORT_SYMBOL vmlinux 0xcefcd99a	serial8250_unregister_port
+EXPORT_SYMBOL vmlinux 0xcf50125c	misc_register
+EXPORT_SYMBOL vmlinux 0xcf6cfe1f	msrs_free
+EXPORT_SYMBOL vmlinux 0xcf7892a7	ethtool_op_get_sg
+EXPORT_SYMBOL vmlinux 0xcf9da793	deactivate_locked_super
+EXPORT_SYMBOL vmlinux 0xcfadd723	__percpu_counter_add
+EXPORT_SYMBOL vmlinux 0xcfb9006e	jiffies_to_timeval
+EXPORT_SYMBOL vmlinux 0xcfc83c67	blk_cleanup_queue
+EXPORT_SYMBOL vmlinux 0xcfd6c829	devm_iounmap
+EXPORT_SYMBOL vmlinux 0xcff53400	kref_put
+EXPORT_SYMBOL vmlinux 0xcff7c9c3	__pagevec_release
+EXPORT_SYMBOL vmlinux 0xd0181f4f	__bitmap_xor
+EXPORT_SYMBOL vmlinux 0xd0556f26	remove_proc_entry
+EXPORT_SYMBOL vmlinux 0xd0d3a949	page_symlink_inode_operations
+EXPORT_SYMBOL vmlinux 0xd0d3d4e2	bio_integrity_free
+EXPORT_SYMBOL vmlinux 0xd0d4aea4	ethtool_op_set_ufo
+EXPORT_SYMBOL vmlinux 0xd0d8621b	strlen
+EXPORT_SYMBOL vmlinux 0xd0ee38b8	schedule_timeout_uninterruptible
+EXPORT_SYMBOL vmlinux 0xd0f2c96f	vfs_write
+EXPORT_SYMBOL vmlinux 0xd11c42cb	dec_zone_page_state
+EXPORT_SYMBOL vmlinux 0xd12a5b4e	nf_register_hooks
+EXPORT_SYMBOL vmlinux 0xd138e756	jbd2_journal_extend
+EXPORT_SYMBOL vmlinux 0xd139acaf	__xfrm_state_delete
+EXPORT_SYMBOL vmlinux 0xd13bab84	pci_bus_write_config_dword
+EXPORT_SYMBOL vmlinux 0xd13c064d	pcim_iomap_table
+EXPORT_SYMBOL vmlinux 0xd15a0b56	napi_complete
+EXPORT_SYMBOL vmlinux 0xd179dc5a	single_release
+EXPORT_SYMBOL vmlinux 0xd1cfbaba	input_flush_device
+EXPORT_SYMBOL vmlinux 0xd1e890f9	kunmap_atomic
+EXPORT_SYMBOL vmlinux 0xd1eb8ebf	sock_no_shutdown
+EXPORT_SYMBOL vmlinux 0xd1f91bcd	dev_base_lock
+EXPORT_SYMBOL vmlinux 0xd1fb24d1	sysctl_ms_jiffies
+EXPORT_SYMBOL vmlinux 0xd1fc2426	generic_file_splice_write
+EXPORT_SYMBOL vmlinux 0xd20356ca	d_move
+EXPORT_SYMBOL vmlinux 0xd251d7b0	security_socket_getpeersec_dgram
+EXPORT_SYMBOL vmlinux 0xd2555f19	jiffies_64_to_clock_t
+EXPORT_SYMBOL vmlinux 0xd25b9e35	invalidate_inode_buffers
+EXPORT_SYMBOL vmlinux 0xd25d4f74	console_blank_hook
+EXPORT_SYMBOL vmlinux 0xd267d42c	down_killable
+EXPORT_SYMBOL vmlinux 0xd27d1497	bio_endio
+EXPORT_SYMBOL vmlinux 0xd2965f6f	kthread_should_stop
+EXPORT_SYMBOL vmlinux 0xd29c608c	cdev_index
+EXPORT_SYMBOL vmlinux 0xd2a68761	proc_dointvec_ms_jiffies
+EXPORT_SYMBOL vmlinux 0xd2f6177d	km_report
+EXPORT_SYMBOL vmlinux 0xd32e52c7	posix_acl_chmod_masq
+EXPORT_SYMBOL vmlinux 0xd348bfdc	w1_unregister_family
+EXPORT_SYMBOL vmlinux 0xd34f0c62	gen_pool_create
+EXPORT_SYMBOL vmlinux 0xd3500876	key_negate_and_link
+EXPORT_SYMBOL vmlinux 0xd35f23ba	qdisc_class_hash_grow
+EXPORT_SYMBOL vmlinux 0xd3739972	mdiobus_write
+EXPORT_SYMBOL vmlinux 0xd38031ea	inet_select_addr
+EXPORT_SYMBOL vmlinux 0xd38f99be	genphy_suspend
+EXPORT_SYMBOL vmlinux 0xd3bbcf33	xfrm_lookup
+EXPORT_SYMBOL vmlinux 0xd3cefb26	kernel_accept
+EXPORT_SYMBOL vmlinux 0xd3d281e7	uart_match_port
+EXPORT_SYMBOL vmlinux 0xd3d95705	kobject_del
+EXPORT_SYMBOL vmlinux 0xd3dcf57e	neigh_create
+EXPORT_SYMBOL vmlinux 0xd3f74cf1	interruptible_sleep_on_timeout
+EXPORT_SYMBOL vmlinux 0xd42b7232	_write_unlock_bh
+EXPORT_SYMBOL vmlinux 0xd474dee4	set_pages_x
+EXPORT_SYMBOL vmlinux 0xd4d07276	dm_table_get
+EXPORT_SYMBOL vmlinux 0xd4d85958	new_inode
+EXPORT_SYMBOL vmlinux 0xd4eb96bd	ip_mc_dec_group
+EXPORT_SYMBOL vmlinux 0xd51ef181	generic_file_llseek
+EXPORT_SYMBOL vmlinux 0xd5263820	mb_cache_destroy
+EXPORT_SYMBOL vmlinux 0xd537cbb8	swiotlb_unmap_sg
+EXPORT_SYMBOL vmlinux 0xd54173e1	force_sig
+EXPORT_SYMBOL vmlinux 0xd54c716b	redraw_screen
+EXPORT_SYMBOL vmlinux 0xd5688a7a	radix_tree_insert
+EXPORT_SYMBOL vmlinux 0xd57f8789	iommu_num_pages
+EXPORT_SYMBOL vmlinux 0xd59a41a1	tcp_disconnect
+EXPORT_SYMBOL vmlinux 0xd5cc056f	bdi_unregister
+EXPORT_SYMBOL vmlinux 0xd5d1f643	neigh_seq_next
+EXPORT_SYMBOL vmlinux 0xd5da0917	vfs_quota_disable
+EXPORT_SYMBOL vmlinux 0xd5ffb681	pci_enable_device_io
+EXPORT_SYMBOL vmlinux 0xd60f6fcf	bmap
+EXPORT_SYMBOL vmlinux 0xd61d4903	__page_symlink
+EXPORT_SYMBOL vmlinux 0xd62c833f	schedule_timeout
+EXPORT_SYMBOL vmlinux 0xd63f79e8	pagevec_lookup
+EXPORT_SYMBOL vmlinux 0xd6630eba	invalidate_partition
+EXPORT_SYMBOL vmlinux 0xd6a78d08	smp_call_function_single
+EXPORT_SYMBOL vmlinux 0xd6b33026	cpu_khz
+EXPORT_SYMBOL vmlinux 0xd6ee688f	vmalloc
+EXPORT_SYMBOL vmlinux 0xd6fcebd6	blk_queue_logical_block_size
+EXPORT_SYMBOL vmlinux 0xd7195a7c	dev_set_drvdata
+EXPORT_SYMBOL vmlinux 0xd71c465e	tcf_em_tree_dump
+EXPORT_SYMBOL vmlinux 0xd72e9093	sync_inode
+EXPORT_SYMBOL vmlinux 0xd75ade88	journal_get_write_access
+EXPORT_SYMBOL vmlinux 0xd77a5aa5	__bitmap_and
+EXPORT_SYMBOL vmlinux 0xd79b5a02	allow_signal
+EXPORT_SYMBOL vmlinux 0xd7a6fafa	panic_notifier_list
+EXPORT_SYMBOL vmlinux 0xd7a737fa	try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0xd7c83594	__kill_fasync
+EXPORT_SYMBOL vmlinux 0xd7cbd225	dm_unregister_target
+EXPORT_SYMBOL vmlinux 0xd7d36d1a	idr_find
+EXPORT_SYMBOL vmlinux 0xd7d67687	get_io_context
+EXPORT_SYMBOL vmlinux 0xd7f09ced	xfrm_unregister_mode
+EXPORT_SYMBOL vmlinux 0xd80d57d2	call_usermodehelper_stdinpipe
+EXPORT_SYMBOL vmlinux 0xd82613c0	atomic64_sub_and_test
+EXPORT_SYMBOL vmlinux 0xd8282ff0	posix_acl_equiv_mode
+EXPORT_SYMBOL vmlinux 0xd83791bc	nf_conntrack_destroy
+EXPORT_SYMBOL vmlinux 0xd846056f	xen_spin_kick
+EXPORT_SYMBOL vmlinux 0xd84cfc22	inet_frag_evictor
+EXPORT_SYMBOL vmlinux 0xd851af78	up_write
+EXPORT_SYMBOL vmlinux 0xd8656093	generic_file_llseek_unlocked
+EXPORT_SYMBOL vmlinux 0xd86905e7	sock_common_recvmsg
+EXPORT_SYMBOL vmlinux 0xd86e8da1	mb_cache_shrink
+EXPORT_SYMBOL vmlinux 0xd89da37f	movable_zone
+EXPORT_SYMBOL vmlinux 0xd8a2ab95	in_egroup_p
+EXPORT_SYMBOL vmlinux 0xd8a334c1	netif_napi_del
+EXPORT_SYMBOL vmlinux 0xd8a4a5d1	dquot_destroy
+EXPORT_SYMBOL vmlinux 0xd8a65c38	atomic64_sub
+EXPORT_SYMBOL vmlinux 0xd8a78522	iget_failed
+EXPORT_SYMBOL vmlinux 0xd8e484f0	register_chrdev_region
+EXPORT_SYMBOL vmlinux 0xd8f0c116	__lock_page
+EXPORT_SYMBOL vmlinux 0xd8f9b046	nf_register_sockopt
+EXPORT_SYMBOL vmlinux 0xd9039cf5	unregister_console
+EXPORT_SYMBOL vmlinux 0xd905f55d	blk_requeue_request
+EXPORT_SYMBOL vmlinux 0xd9083d91	kobject_set_name
+EXPORT_SYMBOL vmlinux 0xd91bfc6e	ip_getsockopt
+EXPORT_SYMBOL vmlinux 0xd92e3d96	set_irq_chip
+EXPORT_SYMBOL vmlinux 0xd963a74a	flush_delayed_work
+EXPORT_SYMBOL vmlinux 0xd974fe25	inet_dgram_connect
+EXPORT_SYMBOL vmlinux 0xd985dc99	mempool_free_pages
+EXPORT_SYMBOL vmlinux 0xd996d859	idr_pre_get
+EXPORT_SYMBOL vmlinux 0xd99ddbf7	input_free_device
+EXPORT_SYMBOL vmlinux 0xd9bbb7c3	jbd2_journal_clear_err
+EXPORT_SYMBOL vmlinux 0xd9ec405c	lro_flush_pkt
+EXPORT_SYMBOL vmlinux 0xda1a7335	kasprintf
+EXPORT_SYMBOL vmlinux 0xda322e3b	neigh_lookup
+EXPORT_SYMBOL vmlinux 0xda44b807	blk_plug_device_unlocked
+EXPORT_SYMBOL vmlinux 0xda78220d	tty_port_tty_set
+EXPORT_SYMBOL vmlinux 0xda7ca6cb	fb_mode_is_equal
+EXPORT_SYMBOL vmlinux 0xda8af7ad	fb_find_nearest_mode
+EXPORT_SYMBOL vmlinux 0xda99cfe5	tty_shutdown
+EXPORT_SYMBOL vmlinux 0xdaa57ec3	totalhigh_pages
+EXPORT_SYMBOL vmlinux 0xdac73c70	simple_dir_operations
+EXPORT_SYMBOL vmlinux 0xdac9f412	blk_end_request_cur
+EXPORT_SYMBOL vmlinux 0xdad6d862	blk_end_request
+EXPORT_SYMBOL vmlinux 0xdae0cbaa	alloc_fcdev
+EXPORT_SYMBOL vmlinux 0xdae84be2	blk_plug_device
+EXPORT_SYMBOL vmlinux 0xdb0b48f9	xfrm_find_acq_byseq
+EXPORT_SYMBOL vmlinux 0xdb23a721	generic_unplug_device
+EXPORT_SYMBOL vmlinux 0xdb325242	simple_empty
+EXPORT_SYMBOL vmlinux 0xdb4c88b4	groups_alloc
+EXPORT_SYMBOL vmlinux 0xdb57dd24	generic_listxattr
+EXPORT_SYMBOL vmlinux 0xdb590f2a	__napi_complete
+EXPORT_SYMBOL vmlinux 0xdb75edc4	blk_queue_max_hw_segments
+EXPORT_SYMBOL vmlinux 0xdb864d65	iov_iter_single_seg_count
+EXPORT_SYMBOL vmlinux 0xdbb4b134	blk_queue_physical_block_size
+EXPORT_SYMBOL vmlinux 0xdbc23998	blk_queue_segment_boundary
+EXPORT_SYMBOL vmlinux 0xdbcd416e	sysctl_ip_nonlocal_bind
+EXPORT_SYMBOL vmlinux 0xdbcf6b38	nf_reinject
+EXPORT_SYMBOL vmlinux 0xdbe65a88	seq_escape
+EXPORT_SYMBOL vmlinux 0xdbf7f3dd	filemap_write_and_wait
+EXPORT_SYMBOL vmlinux 0xdc053205	udp_memory_allocated
+EXPORT_SYMBOL vmlinux 0xdc12ccc7	inet_addr_type
+EXPORT_SYMBOL vmlinux 0xdc14eda7	pci_pci_problems
+EXPORT_SYMBOL vmlinux 0xdc2adb35	add_taint
+EXPORT_SYMBOL vmlinux 0xdc37be63	journal_create
+EXPORT_SYMBOL vmlinux 0xdc43a9c8	daemonize
+EXPORT_SYMBOL vmlinux 0xdc64eb35	inet_twsk_deschedule
+EXPORT_SYMBOL vmlinux 0xdc7fe0c9	skb_tx_hash
+EXPORT_SYMBOL vmlinux 0xdc873a70	screen_info
+EXPORT_SYMBOL vmlinux 0xdca0e950	genl_register_family
+EXPORT_SYMBOL vmlinux 0xdcaf1e20	bh_submit_read
+EXPORT_SYMBOL vmlinux 0xdcb6369a	config_item_set_name
+EXPORT_SYMBOL vmlinux 0xdcd66a38	vfs_quota_on_path
+EXPORT_SYMBOL vmlinux 0xdcf230ed	blk_init_tags
+EXPORT_SYMBOL vmlinux 0xdd0a2ba2	strlcat
+EXPORT_SYMBOL vmlinux 0xdd0b651b	journal_init_dev
+EXPORT_SYMBOL vmlinux 0xdd2e5451	generic_block_bmap
+EXPORT_SYMBOL vmlinux 0xdd3f42cd	qdisc_watchdog_cancel
+EXPORT_SYMBOL vmlinux 0xdd43dc4b	uart_register_driver
+EXPORT_SYMBOL vmlinux 0xdd446642	xfrm_state_lookup_byaddr
+EXPORT_SYMBOL vmlinux 0xdd621066	pci_clear_mwi
+EXPORT_SYMBOL vmlinux 0xdd6bfccd	radix_tree_tag_set
+EXPORT_SYMBOL vmlinux 0xdd7f1393	dm_kcopyd_client_create
+EXPORT_SYMBOL vmlinux 0xddb273d4	make_EII_client
+EXPORT_SYMBOL vmlinux 0xddd20cbf	locks_remove_posix
+EXPORT_SYMBOL vmlinux 0xddd8fbe0	simple_release_fs
+EXPORT_SYMBOL vmlinux 0xde1c8c99	path_lookup
+EXPORT_SYMBOL vmlinux 0xde2f3135	pci_vpd_truncate
+EXPORT_SYMBOL vmlinux 0xde2f4d5c	journal_get_create_access
+EXPORT_SYMBOL vmlinux 0xde31b902	blk_limits_io_opt
+EXPORT_SYMBOL vmlinux 0xde53c41c	llc_add_pack
+EXPORT_SYMBOL vmlinux 0xde75b689	set_irq_type
+EXPORT_SYMBOL vmlinux 0xde80c4e6	__neigh_for_each_release
+EXPORT_SYMBOL vmlinux 0xde88668f	sk_send_sigurg
+EXPORT_SYMBOL vmlinux 0xde9360ba	totalram_pages
+EXPORT_SYMBOL vmlinux 0xdea7e3fa	page_follow_link_light
+EXPORT_SYMBOL vmlinux 0xdec43a5a	in_dev_finish_destroy
+EXPORT_SYMBOL vmlinux 0xdedb5577	netdev_boot_setup_check
+EXPORT_SYMBOL vmlinux 0xdef18217	vfs_llseek
+EXPORT_SYMBOL vmlinux 0xdf250223	blk_queue_update_dma_alignment
+EXPORT_SYMBOL vmlinux 0xdf4c8767	ns_to_timeval
+EXPORT_SYMBOL vmlinux 0xdf501627	genphy_resume
+EXPORT_SYMBOL vmlinux 0xdf5292ad	unregister_framebuffer
+EXPORT_SYMBOL vmlinux 0xdf59d81a	block_sync_page
+EXPORT_SYMBOL vmlinux 0xdf60cc27	__print_symbol
+EXPORT_SYMBOL vmlinux 0xdf681ff0	dm_get_mapinfo
+EXPORT_SYMBOL vmlinux 0xdf8c695a	__ndelay
+EXPORT_SYMBOL vmlinux 0xdf929370	fs_overflowgid
+EXPORT_SYMBOL vmlinux 0xdfc5169b	slhc_init
+EXPORT_SYMBOL vmlinux 0xdfd3cdfd	d_add_ci
+EXPORT_SYMBOL vmlinux 0xe0323dd9	jbd2_journal_load
+EXPORT_SYMBOL vmlinux 0xe03386ef	proc_net_netfilter
+EXPORT_SYMBOL vmlinux 0xe0582030	__inet6_lookup_established
+EXPORT_SYMBOL vmlinux 0xe067bd4b	vfs_getattr
+EXPORT_SYMBOL vmlinux 0xe06bc708	xfrm_state_update
+EXPORT_SYMBOL vmlinux 0xe075d6eb	iter_div_u64_rem
+EXPORT_SYMBOL vmlinux 0xe0a20d06	tty_port_tty_get
+EXPORT_SYMBOL vmlinux 0xe0a501e3	idr_remove_all
+EXPORT_SYMBOL vmlinux 0xe0b13336	argv_free
+EXPORT_SYMBOL vmlinux 0xe0bc24a1	param_set_ushort
+EXPORT_SYMBOL vmlinux 0xe0cfefc1	blk_queue_make_request
+EXPORT_SYMBOL vmlinux 0xe0dccb73	__wait_on_buffer
+EXPORT_SYMBOL vmlinux 0xe137a492	__neigh_event_send
+EXPORT_SYMBOL vmlinux 0xe1761617	security_inet_conn_request
+EXPORT_SYMBOL vmlinux 0xe183ad5e	skb_abort_seq_read
+EXPORT_SYMBOL vmlinux 0xe1a15ee9	unregister_tcf_proto_ops
+EXPORT_SYMBOL vmlinux 0xe1a37ec7	handle_sysrq
+EXPORT_SYMBOL vmlinux 0xe1ca5462	get_sb_single
+EXPORT_SYMBOL vmlinux 0xe1d830ef	genphy_config_aneg
+EXPORT_SYMBOL vmlinux 0xe1dc1988	seq_release
+EXPORT_SYMBOL vmlinux 0xe1ee530f	dev_getfirstbyhwtype
+EXPORT_SYMBOL vmlinux 0xe2135506	skb_kill_datagram
+EXPORT_SYMBOL vmlinux 0xe23ae481	blk_iopoll_complete
+EXPORT_SYMBOL vmlinux 0xe23d7acb	up_read
+EXPORT_SYMBOL vmlinux 0xe24d3a97	jiffies_64
+EXPORT_SYMBOL vmlinux 0xe25068fc	get_super
+EXPORT_SYMBOL vmlinux 0xe27f856b	current_fs_time
+EXPORT_SYMBOL vmlinux 0xe288b2fb	genphy_update_link
+EXPORT_SYMBOL vmlinux 0xe28c3a9d	inode_set_bytes
+EXPORT_SYMBOL vmlinux 0xe2ca3700	inet_frag_destroy
+EXPORT_SYMBOL vmlinux 0xe2d5255a	strcmp
+EXPORT_SYMBOL vmlinux 0xe2e8065e	memdup_user
+EXPORT_SYMBOL vmlinux 0xe2ede855	input_get_keycode
+EXPORT_SYMBOL vmlinux 0xe2f01d03	nf_log_packet
+EXPORT_SYMBOL vmlinux 0xe2f5d071	kset_unregister
+EXPORT_SYMBOL vmlinux 0xe2fae716	kmemdup
+EXPORT_SYMBOL vmlinux 0xe34af614	names_cachep
+EXPORT_SYMBOL vmlinux 0xe385ddc3	give_up_console
+EXPORT_SYMBOL vmlinux 0xe38e34c9	rtnetlink_put_metrics
+EXPORT_SYMBOL vmlinux 0xe39a584b	vmalloc_to_page
+EXPORT_SYMBOL vmlinux 0xe3e7fd4c	napi_frags_skb
+EXPORT_SYMBOL vmlinux 0xe3eb36bd	input_register_device
+EXPORT_SYMBOL vmlinux 0xe43948d9	phy_driver_unregister
+EXPORT_SYMBOL vmlinux 0xe456bd3a	complete
+EXPORT_SYMBOL vmlinux 0xe4687a53	unlock_new_inode
+EXPORT_SYMBOL vmlinux 0xe484e35f	ioread32
+EXPORT_SYMBOL vmlinux 0xe4870354	_read_trylock
+EXPORT_SYMBOL vmlinux 0xe48f3039	ida_get_new_above
+EXPORT_SYMBOL vmlinux 0xe4b24b8c	__next_cpu
+EXPORT_SYMBOL vmlinux 0xe4b3de83	blk_queue_io_opt
+EXPORT_SYMBOL vmlinux 0xe4c1df3e	_read_lock_bh
+EXPORT_SYMBOL vmlinux 0xe4c500d3	jbd2_journal_release_jbd_inode
+EXPORT_SYMBOL vmlinux 0xe4dd4a39	sysctl_data
+EXPORT_SYMBOL vmlinux 0xe4f1695e	cookie_check_timestamp
+EXPORT_SYMBOL vmlinux 0xe517a765	aio_complete
+EXPORT_SYMBOL vmlinux 0xe523ad75	synchronize_irq
+EXPORT_SYMBOL vmlinux 0xe5399e7e	pid_task
+EXPORT_SYMBOL vmlinux 0xe5752249	kernel_recvmsg
+EXPORT_SYMBOL vmlinux 0xe57878a1	in6_pton
+EXPORT_SYMBOL vmlinux 0xe57f1739	setup_new_exec
+EXPORT_SYMBOL vmlinux 0xe5867808	dlci_ioctl_set
+EXPORT_SYMBOL vmlinux 0xe59d13b5	__dev_getfirstbyhwtype
+EXPORT_SYMBOL vmlinux 0xe5a00d01	posix_unblock_lock
+EXPORT_SYMBOL vmlinux 0xe5aa103b	tty_port_block_til_ready
+EXPORT_SYMBOL vmlinux 0xe5c78a99	do_blank_screen
+EXPORT_SYMBOL vmlinux 0xe5da1dfd	mb_cache_entry_insert
+EXPORT_SYMBOL vmlinux 0xe5da7895	jbd2_journal_file_inode
+EXPORT_SYMBOL vmlinux 0xe5ed5467	xfrm_policy_walk_init
+EXPORT_SYMBOL vmlinux 0xe5f8d87d	filemap_fault
+EXPORT_SYMBOL vmlinux 0xe5fb5f64	pcie_set_readrq
+EXPORT_SYMBOL vmlinux 0xe5ff2c12	vfs_rename
+EXPORT_SYMBOL vmlinux 0xe616a752	default_unplug_io_fn
+EXPORT_SYMBOL vmlinux 0xe6248748	mod_zone_page_state
+EXPORT_SYMBOL vmlinux 0xe6569fd0	follow_pfn
+EXPORT_SYMBOL vmlinux 0xe66232ff	xrlim_allow
+EXPORT_SYMBOL vmlinux 0xe683db98	init_special_inode
+EXPORT_SYMBOL vmlinux 0xe686e1cd	pci_get_class
+EXPORT_SYMBOL vmlinux 0xe697d108	__blk_iopoll_complete
+EXPORT_SYMBOL vmlinux 0xe6c2a247	blk_queue_free_tags
+EXPORT_SYMBOL vmlinux 0xe6e3ef70	machine_restart
+EXPORT_SYMBOL vmlinux 0xe6ebc016	key_create_or_update
+EXPORT_SYMBOL vmlinux 0xe6fbe430	can_do_mlock
+EXPORT_SYMBOL vmlinux 0xe70ae751	redirty_page_for_writepage
+EXPORT_SYMBOL vmlinux 0xe714375c	__tasklet_hi_schedule_first
+EXPORT_SYMBOL vmlinux 0xe77e6b8b	blk_queue_merge_bvec
+EXPORT_SYMBOL vmlinux 0xe78253aa	tty_devnum
+EXPORT_SYMBOL vmlinux 0xe7d2aca1	security_sk_classify_flow
+EXPORT_SYMBOL vmlinux 0xe7d4daac	seq_list_next
+EXPORT_SYMBOL vmlinux 0xe7f7115e	xen_tlb_flush
+EXPORT_SYMBOL vmlinux 0xe80fea6f	dev_driver_string
+EXPORT_SYMBOL vmlinux 0xe81219d3	dquot_transfer
+EXPORT_SYMBOL vmlinux 0xe825056b	dev_alloc_skb
+EXPORT_SYMBOL vmlinux 0xe85fe07a	fb_is_primary_device
+EXPORT_SYMBOL vmlinux 0xe8794ce1	slhc_toss
+EXPORT_SYMBOL vmlinux 0xe87cd0ed	bdev_stack_limits
+EXPORT_SYMBOL vmlinux 0xe89231e7	skb_insert
+EXPORT_SYMBOL vmlinux 0xe8959398	set_security_override_from_ctx
+EXPORT_SYMBOL vmlinux 0xe89fbce3	input_close_device
+EXPORT_SYMBOL vmlinux 0xe8aa45b8	nf_unregister_sockopt
+EXPORT_SYMBOL vmlinux 0xe8abd232	register_quota_format
+EXPORT_SYMBOL vmlinux 0xe8ac2248	net_accel_map_grants_contig
+EXPORT_SYMBOL vmlinux 0xe8b1982e	vga_put
+EXPORT_SYMBOL vmlinux 0xe8c2ce8c	user_path_at
+EXPORT_SYMBOL vmlinux 0xe8cd902e	hweight16
+EXPORT_SYMBOL vmlinux 0xe8e9d7e9	sock_no_connect
+EXPORT_SYMBOL vmlinux 0xe90dcae0	__request_module
+EXPORT_SYMBOL vmlinux 0xe914e41e	strcpy
+EXPORT_SYMBOL vmlinux 0xe92aa6f9	phy_attach_direct
+EXPORT_SYMBOL vmlinux 0xe989c738	set_device_ro
+EXPORT_SYMBOL vmlinux 0xe997667b	wrmsr_on_cpu
+EXPORT_SYMBOL vmlinux 0xe9ba61f7	bio_alloc
+EXPORT_SYMBOL vmlinux 0xe9cb43e8	console_start
+EXPORT_SYMBOL vmlinux 0xe9d28282	bio_split
+EXPORT_SYMBOL vmlinux 0xe9d4ef94	I_BDEV
+EXPORT_SYMBOL vmlinux 0xea054b22	nla_policy_len
+EXPORT_SYMBOL vmlinux 0xea0d19d3	simple_rmdir
+EXPORT_SYMBOL vmlinux 0xea10655a	__bitmap_intersects
+EXPORT_SYMBOL vmlinux 0xea2d33a2	radix_tree_gang_lookup_slot
+EXPORT_SYMBOL vmlinux 0xea506f15	pcim_iomap_regions_request_all
+EXPORT_SYMBOL vmlinux 0xea5a4dc9	net_accel_unmap_grants_contig
+EXPORT_SYMBOL vmlinux 0xea7987f1	key_update
+EXPORT_SYMBOL vmlinux 0xea852925	rwsem_downgrade_wake
+EXPORT_SYMBOL vmlinux 0xea858cb5	radix_tree_gang_lookup_tag
+EXPORT_SYMBOL vmlinux 0xeaa37da7	neigh_for_each
+EXPORT_SYMBOL vmlinux 0xeae33115	jbd2_journal_stop
+EXPORT_SYMBOL vmlinux 0xeae3dfd6	__const_udelay
+EXPORT_SYMBOL vmlinux 0xeaf35d94	xfrm_policy_register_afinfo
+EXPORT_SYMBOL vmlinux 0xeb19a2bb	skb_recv_datagram
+EXPORT_SYMBOL vmlinux 0xeb1fabf6	interruptible_sleep_on
+EXPORT_SYMBOL vmlinux 0xeb4db93b	blk_free_tags
+EXPORT_SYMBOL vmlinux 0xeb873a80	dev_mc_unsync
+EXPORT_SYMBOL vmlinux 0xeb87be73	tty_port_close_end
+EXPORT_SYMBOL vmlinux 0xeb8f54b3	strstrip
+EXPORT_SYMBOL vmlinux 0xeb926835	backlight_force_update
+EXPORT_SYMBOL vmlinux 0xeb9f57a3	iunique
+EXPORT_SYMBOL vmlinux 0xebb96c41	skb_dma_map
+EXPORT_SYMBOL vmlinux 0xebd273a6	strict_strtoull
+EXPORT_SYMBOL vmlinux 0xec00a83c	tty_get_baud_rate
+EXPORT_SYMBOL vmlinux 0xec1419c0	truncate_pagecache
+EXPORT_SYMBOL vmlinux 0xec221f08	tty_write_room
+EXPORT_SYMBOL vmlinux 0xec794ba0	__send_remote_softirq
+EXPORT_SYMBOL vmlinux 0xec83a7c2	seq_lseek
+EXPORT_SYMBOL vmlinux 0xecb37841	genphy_read_status
+EXPORT_SYMBOL vmlinux 0xecc314fa	__ip_select_ident
+EXPORT_SYMBOL vmlinux 0xecd7d3e8	config_item_init_type_name
+EXPORT_SYMBOL vmlinux 0xecddd316	vfs_set_dqblk
+EXPORT_SYMBOL vmlinux 0xecde1418	_spin_lock_irq
+EXPORT_SYMBOL vmlinux 0xecf69b0d	sk_stream_write_space
+EXPORT_SYMBOL vmlinux 0xed2a4ce2	skb_over_panic
+EXPORT_SYMBOL vmlinux 0xed432627	netif_rx
+EXPORT_SYMBOL vmlinux 0xed4917c0	mutex_trylock
+EXPORT_SYMBOL vmlinux 0xed5780f1	__lookup_one_len
+EXPORT_SYMBOL vmlinux 0xed8b8158	fasync_helper
+EXPORT_SYMBOL vmlinux 0xeda0d76e	gen_estimator_active
+EXPORT_SYMBOL vmlinux 0xedbaee5e	nla_strcmp
+EXPORT_SYMBOL vmlinux 0xedc03953	iounmap
+EXPORT_SYMBOL vmlinux 0xedc93383	dma_supported
+EXPORT_SYMBOL vmlinux 0xedd8832e	splice_from_pipe_next
+EXPORT_SYMBOL vmlinux 0xee21bbcd	block_fsync
+EXPORT_SYMBOL vmlinux 0xee2d0fc7	_local_bh_enable
+EXPORT_SYMBOL vmlinux 0xee3b1fc7	atm_charge
+EXPORT_SYMBOL vmlinux 0xee3dd55c	inet_bind
+EXPORT_SYMBOL vmlinux 0xee40c1d7	bdget_disk
+EXPORT_SYMBOL vmlinux 0xee7fbd96	__devm_request_region
+EXPORT_SYMBOL vmlinux 0xee999969	inode_setattr
+EXPORT_SYMBOL vmlinux 0xee9b3215	inet_csk_delete_keepalive_timer
+EXPORT_SYMBOL vmlinux 0xee9b6e5f	sync_dirty_buffer
+EXPORT_SYMBOL vmlinux 0xeea9dbaf	bitmap_bitremap
+EXPORT_SYMBOL vmlinux 0xeec983c6	slow_work_unregister_user
+EXPORT_SYMBOL vmlinux 0xeeca3306	seq_write
+EXPORT_SYMBOL vmlinux 0xeedd1720	locks_mandatory_area
+EXPORT_SYMBOL vmlinux 0xef3fdbc5	kobject_init
+EXPORT_SYMBOL vmlinux 0xef6ed1ba	param_set_invbool
+EXPORT_SYMBOL vmlinux 0xef8298d6	malloc_sizes
+EXPORT_SYMBOL vmlinux 0xef9aedfc	boot_option_idle_override
+EXPORT_SYMBOL vmlinux 0xefa5f189	dput
+EXPORT_SYMBOL vmlinux 0xefb4b1d5	vfs_statfs
+EXPORT_SYMBOL vmlinux 0xefb6b5a6	phy_register_fixup_for_id
+EXPORT_SYMBOL vmlinux 0xefdd70ce	security_secid_to_secctx
+EXPORT_SYMBOL vmlinux 0xf0009fee	put_pages_list
+EXPORT_SYMBOL vmlinux 0xf06263b6	request_key_with_auxdata
+EXPORT_SYMBOL vmlinux 0xf065f629	ioread16be
+EXPORT_SYMBOL vmlinux 0xf09a3988	napi_frags_finish
+EXPORT_SYMBOL vmlinux 0xf0de6941	lro_receive_frags
+EXPORT_SYMBOL vmlinux 0xf0ef15b4	list_sort
+EXPORT_SYMBOL vmlinux 0xf0f1246c	kvasprintf
+EXPORT_SYMBOL vmlinux 0xf0fdf6cb	__stack_chk_fail
+EXPORT_SYMBOL vmlinux 0xf1046bc1	commit_creds
+EXPORT_SYMBOL vmlinux 0xf10b3b47	request_key_async
+EXPORT_SYMBOL vmlinux 0xf10de535	ioread8
+EXPORT_SYMBOL vmlinux 0xf114c6e3	kernel_sendmsg
+EXPORT_SYMBOL vmlinux 0xf11543ff	find_first_zero_bit
+EXPORT_SYMBOL vmlinux 0xf159efa7	ppp_input_error
+EXPORT_SYMBOL vmlinux 0xf174ed48	acquire_console_sem
+EXPORT_SYMBOL vmlinux 0xf17a9390	tcp_create_openreq_child
+EXPORT_SYMBOL vmlinux 0xf1835c6c	journal_try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0xf195c682	fb_invert_cmaps
+EXPORT_SYMBOL vmlinux 0xf1b06b87	scsi_cmd_ioctl
+EXPORT_SYMBOL vmlinux 0xf1b1ca03	generic_file_splice_read
+EXPORT_SYMBOL vmlinux 0xf1c2ad70	inet_del_protocol
+EXPORT_SYMBOL vmlinux 0xf1d64416	gen_new_estimator
+EXPORT_SYMBOL vmlinux 0xf1db1704	nla_memcpy
+EXPORT_SYMBOL vmlinux 0xf1deabf2	div64_u64
+EXPORT_SYMBOL vmlinux 0xf1e98c74	avenrun
+EXPORT_SYMBOL vmlinux 0xf1ef5d86	jbd2_journal_init_jbd_inode
+EXPORT_SYMBOL vmlinux 0xf20dabd8	free_irq
+EXPORT_SYMBOL vmlinux 0xf2260f53	blk_sync_queue
+EXPORT_SYMBOL vmlinux 0xf27e7c08	bio_integrity_alloc_bioset
+EXPORT_SYMBOL vmlinux 0xf28a0a7a	pci_disable_device
+EXPORT_SYMBOL vmlinux 0xf28b3a15	vlan_ioctl_set
+EXPORT_SYMBOL vmlinux 0xf2997713	tty_termios_hw_change
+EXPORT_SYMBOL vmlinux 0xf29e8f52	d_invalidate
+EXPORT_SYMBOL vmlinux 0xf2a96f5b	register_nls
+EXPORT_SYMBOL vmlinux 0xf2c6a6b3	netif_notify_peers
+EXPORT_SYMBOL vmlinux 0xf2d47d15	dquot_drop
+EXPORT_SYMBOL vmlinux 0xf2dc2407	per_cpu__xen_lazy_mmu
+EXPORT_SYMBOL vmlinux 0xf3014456	__scm_send
+EXPORT_SYMBOL vmlinux 0xf311794b	register_8022_client
+EXPORT_SYMBOL vmlinux 0xf313da4e	sha_transform
+EXPORT_SYMBOL vmlinux 0xf31dc801	pci_scan_single_device
+EXPORT_SYMBOL vmlinux 0xf32d8a15	kmap_atomic_to_page
+EXPORT_SYMBOL vmlinux 0xf3341268	__clear_user
+EXPORT_SYMBOL vmlinux 0xf33615c1	pci_set_power_state
+EXPORT_SYMBOL vmlinux 0xf338d4c3	netlink_unregister_notifier
+EXPORT_SYMBOL vmlinux 0xf346231f	seq_list_start_head
+EXPORT_SYMBOL vmlinux 0xf38ab544	atm_dev_deregister
+EXPORT_SYMBOL vmlinux 0xf396d072	fb_set_cmap
+EXPORT_SYMBOL vmlinux 0xf397b9aa	__tasklet_schedule
+EXPORT_SYMBOL vmlinux 0xf39bf4d9	put_cmsg
+EXPORT_SYMBOL vmlinux 0xf3ba8ddf	seq_read
+EXPORT_SYMBOL vmlinux 0xf3bd43ed	cdrom_release
+EXPORT_SYMBOL vmlinux 0xf3bf0bce	__bitmap_complement
+EXPORT_SYMBOL vmlinux 0xf3e44608	inet_frag_find
+EXPORT_SYMBOL vmlinux 0xf40177d6	genl_register_family_with_ops
+EXPORT_SYMBOL vmlinux 0xf40b2e6f	directly_mappable_cdev_bdi
+EXPORT_SYMBOL vmlinux 0xf41ad0f5	skb_seq_read
+EXPORT_SYMBOL vmlinux 0xf441ac43	ioread8_rep
+EXPORT_SYMBOL vmlinux 0xf44c8942	phy_print_status
+EXPORT_SYMBOL vmlinux 0xf460f2ac	udp_proc_register
+EXPORT_SYMBOL vmlinux 0xf46a93ff	dm_table_get_md
+EXPORT_SYMBOL vmlinux 0xf46c85d0	pcim_iomap
+EXPORT_SYMBOL vmlinux 0xf49bc67a	atm_pcr_goal
+EXPORT_SYMBOL vmlinux 0xf4ae9d51	ida_pre_get
+EXPORT_SYMBOL vmlinux 0xf4b195fd	uart_get_divisor
+EXPORT_SYMBOL vmlinux 0xf4bd3015	tcp_gro_complete
+EXPORT_SYMBOL vmlinux 0xf4c631dc	inet_csk_clear_xmit_timers
+EXPORT_SYMBOL vmlinux 0xf4e08b57	poll_initwait
+EXPORT_SYMBOL vmlinux 0xf4f14de6	rtnl_trylock
+EXPORT_SYMBOL vmlinux 0xf4f52f93	dqstats
+EXPORT_SYMBOL vmlinux 0xf51aeef8	unregister_8022_client
+EXPORT_SYMBOL vmlinux 0xf53d4c26	qdisc_class_hash_destroy
+EXPORT_SYMBOL vmlinux 0xf53fd262	xfrm4_rcv
+EXPORT_SYMBOL vmlinux 0xf542159e	pci_set_consistent_dma_mask
+EXPORT_SYMBOL vmlinux 0xf542bd97	secpath_dup
+EXPORT_SYMBOL vmlinux 0xf55cf463	sock_no_getsockopt
+EXPORT_SYMBOL vmlinux 0xf57d02bb	pci_enable_device
+EXPORT_SYMBOL vmlinux 0xf599d3e4	sock_no_sendmsg
+EXPORT_SYMBOL vmlinux 0xf5c05914	generic_segment_checks
+EXPORT_SYMBOL vmlinux 0xf5c9012e	timespec_trunc
+EXPORT_SYMBOL vmlinux 0xf5ccdffd	blk_stack_limits
+EXPORT_SYMBOL vmlinux 0xf5eb86ea	blk_verify_command
+EXPORT_SYMBOL vmlinux 0xf61bd6a2	jbd2_journal_check_used_features
+EXPORT_SYMBOL vmlinux 0xf62413a0	pci_get_subsys
+EXPORT_SYMBOL vmlinux 0xf6436155	journal_start
+EXPORT_SYMBOL vmlinux 0xf654a7bd	netpoll_send_udp
+EXPORT_SYMBOL vmlinux 0xf6596bb2	bio_integrity_trim
+EXPORT_SYMBOL vmlinux 0xf66c01ff	skb_checksum_help
+EXPORT_SYMBOL vmlinux 0xf684e7f9	ppp_output_wakeup
+EXPORT_SYMBOL vmlinux 0xf686af60	set_page_dirty
+EXPORT_SYMBOL vmlinux 0xf6b8a04e	__blockdev_direct_IO
+EXPORT_SYMBOL vmlinux 0xf6bb4729	color_table
+EXPORT_SYMBOL vmlinux 0xf6ebc03b	net_ratelimit
+EXPORT_SYMBOL vmlinux 0xf6eedcb9	security_inode_init_security
+EXPORT_SYMBOL vmlinux 0xf6ef2b6b	request_firmware
+EXPORT_SYMBOL vmlinux 0xf6f8d47a	netif_device_detach
+EXPORT_SYMBOL vmlinux 0xf70f1614	arp_xmit
+EXPORT_SYMBOL vmlinux 0xf7220e46	neigh_ifdown
+EXPORT_SYMBOL vmlinux 0xf725d5eb	nla_put_nohdr
+EXPORT_SYMBOL vmlinux 0xf72cdf94	udp_prot
+EXPORT_SYMBOL vmlinux 0xf744222e	backlight_device_unregister
+EXPORT_SYMBOL vmlinux 0xf760000b	alloc_file
+EXPORT_SYMBOL vmlinux 0xf7623914	radix_tree_tag_clear
+EXPORT_SYMBOL vmlinux 0xf76a4ab8	hypercall_page
+EXPORT_SYMBOL vmlinux 0xf786ef5e	idr_init
+EXPORT_SYMBOL vmlinux 0xf78d04ab	netlink_register_notifier
+EXPORT_SYMBOL vmlinux 0xf7af010e	d_instantiate_unique
+EXPORT_SYMBOL vmlinux 0xf7cf7f49	__blk_end_request_cur
+EXPORT_SYMBOL vmlinux 0xf7dc6805	page_put_link
+EXPORT_SYMBOL vmlinux 0xf7f76ded	journal_dirty_data
+EXPORT_SYMBOL vmlinux 0xf82abc1d	isa_dma_bridge_buggy
+EXPORT_SYMBOL vmlinux 0xf842d204	security_path_mknod
+EXPORT_SYMBOL vmlinux 0xf84c8be0	__xfrm_policy_check
+EXPORT_SYMBOL vmlinux 0xf85bc61c	swiotlb_map_sg
+EXPORT_SYMBOL vmlinux 0xf85c81c7	jbd2_journal_force_commit_nested
+EXPORT_SYMBOL vmlinux 0xf8609479	remap_pfn_range
+EXPORT_SYMBOL vmlinux 0xf88450a4	__register_binfmt
+EXPORT_SYMBOL vmlinux 0xf889a27a	blk_queue_alignment_offset
+EXPORT_SYMBOL vmlinux 0xf890fe7f	pm_idle
+EXPORT_SYMBOL vmlinux 0xf8b30e93	mempool_create
+EXPORT_SYMBOL vmlinux 0xf8cb1965	cdrom_media_changed
+EXPORT_SYMBOL vmlinux 0xf8cf9ee5	abort_exclusive_wait
+EXPORT_SYMBOL vmlinux 0xf8f99abc	find_vma
+EXPORT_SYMBOL vmlinux 0xf90a81ae	HYPERVISOR_shared_info
+EXPORT_SYMBOL vmlinux 0xf9567985	tcf_exts_destroy
+EXPORT_SYMBOL vmlinux 0xf9899664	mod_timer_pinned
+EXPORT_SYMBOL vmlinux 0xf9a482f9	msleep
+EXPORT_SYMBOL vmlinux 0xf9be3523	netfront_check_queue_ready
+EXPORT_SYMBOL vmlinux 0xf9d8cafb	pci_write_vpd
+EXPORT_SYMBOL vmlinux 0xf9db0531	sock_no_getname
+EXPORT_SYMBOL vmlinux 0xfa0564fc	__wait_on_bit_lock
+EXPORT_SYMBOL vmlinux 0xfa336717	pci_disable_msix
+EXPORT_SYMBOL vmlinux 0xfa5c3706	key_alloc
+EXPORT_SYMBOL vmlinux 0xfaafbdb4	pci_prepare_to_sleep
+EXPORT_SYMBOL vmlinux 0xfab1e1d3	arp_tbl
+EXPORT_SYMBOL vmlinux 0xfac7c112	key_link
+EXPORT_SYMBOL vmlinux 0xfaf98462	bitrev32
+EXPORT_SYMBOL vmlinux 0xfb0095d8	tty_check_change
+EXPORT_SYMBOL vmlinux 0xfb0cf2e9	touch_all_softlockup_watchdogs
+EXPORT_SYMBOL vmlinux 0xfb17e280	tty_unregister_driver
+EXPORT_SYMBOL vmlinux 0xfb21c9f8	filemap_fdatawait
+EXPORT_SYMBOL vmlinux 0xfb2dc0f3	fifo_create_dflt
+EXPORT_SYMBOL vmlinux 0xfb6af58d	recalc_sigpending
+EXPORT_SYMBOL vmlinux 0xfb77ca4f	xen_start_info
+EXPORT_SYMBOL vmlinux 0xfba0c2e0	llc_sap_list_lock
+EXPORT_SYMBOL vmlinux 0xfbaabe9a	bio_alloc_bioset
+EXPORT_SYMBOL vmlinux 0xfbc2ab98	sockfd_lookup
+EXPORT_SYMBOL vmlinux 0xfbd89948	kick_iocb
+EXPORT_SYMBOL vmlinux 0xfbe27a1c	rb_first
+EXPORT_SYMBOL vmlinux 0xfbe31866	wait_on_sync_kiocb
+EXPORT_SYMBOL vmlinux 0xfc02b7ad	sysctl_tcp_wmem
+EXPORT_SYMBOL vmlinux 0xfc39e32f	ioport_unmap
+EXPORT_SYMBOL vmlinux 0xfc47aad0	phy_start
+EXPORT_SYMBOL vmlinux 0xfc48f3ae	xfrm_state_register_afinfo
+EXPORT_SYMBOL vmlinux 0xfc533f85	schedule_work_on
+EXPORT_SYMBOL vmlinux 0xfc6256b9	boot_tvec_bases
+EXPORT_SYMBOL vmlinux 0xfc681818	elv_rb_del
+EXPORT_SYMBOL vmlinux 0xfc692c0c	pcix_set_mmrbc
+EXPORT_SYMBOL vmlinux 0xfca1d572	poll_freewait
+EXPORT_SYMBOL vmlinux 0xfcaa04a0	out_of_line_wait_on_bit_lock
+EXPORT_SYMBOL vmlinux 0xfcc2a43c	utf32_to_utf8
+EXPORT_SYMBOL vmlinux 0xfcc4d4e4	mod_timer_pending
+EXPORT_SYMBOL vmlinux 0xfccdc700	elv_add_request
+EXPORT_SYMBOL vmlinux 0xfcda63a3	node_states
+EXPORT_SYMBOL vmlinux 0xfcec0987	enable_irq
+EXPORT_SYMBOL vmlinux 0xfcfa03ff	fb_videomode_to_modelist
+EXPORT_SYMBOL vmlinux 0xfd0d3c86	napi_gro_frags
+EXPORT_SYMBOL vmlinux 0xfd2839f6	arp_send
+EXPORT_SYMBOL vmlinux 0xfd353f03	con_copy_unimap
+EXPORT_SYMBOL vmlinux 0xfd3aa11d	kmap
+EXPORT_SYMBOL vmlinux 0xfd3d9adf	dev_set_promiscuity
+EXPORT_SYMBOL vmlinux 0xfd41ede3	tcp_child_process
+EXPORT_SYMBOL vmlinux 0xfd6f4850	native_wrmsr_safe_regs
+EXPORT_SYMBOL vmlinux 0xfd766caa	inc_zone_page_state
+EXPORT_SYMBOL vmlinux 0xfd887777	tcp_timewait_state_process
+EXPORT_SYMBOL vmlinux 0xfda85a7d	request_threaded_irq
+EXPORT_SYMBOL vmlinux 0xfdb9b629	ioread32be
+EXPORT_SYMBOL vmlinux 0xfddc71bf	tty_insert_flip_string
+EXPORT_SYMBOL vmlinux 0xfde2bdf3	textsearch_destroy
+EXPORT_SYMBOL vmlinux 0xfdfc0b3b	fiemap_fill_next_extent
+EXPORT_SYMBOL vmlinux 0xfe45de8d	mb_cache_entry_get
+EXPORT_SYMBOL vmlinux 0xfe4d9f39	fifo_set_limit
+EXPORT_SYMBOL vmlinux 0xfe51f893	pcix_get_max_mmrbc
+EXPORT_SYMBOL vmlinux 0xfe5d4bb2	sys_tz
+EXPORT_SYMBOL vmlinux 0xfe769456	unregister_netdevice_notifier
+EXPORT_SYMBOL vmlinux 0xfe7c4287	nr_cpu_ids
+EXPORT_SYMBOL vmlinux 0xfe8e753e	tcp_mtup_init
+EXPORT_SYMBOL vmlinux 0xfe99e710	bdi_destroy
+EXPORT_SYMBOL vmlinux 0xfeb60875	sk_reset_timer
+EXPORT_SYMBOL vmlinux 0xfec20d9e	km_policy_expired
+EXPORT_SYMBOL vmlinux 0xfec3c2f2	bcd2bin
+EXPORT_SYMBOL vmlinux 0xfedd35fc	console_suspend_enabled
+EXPORT_SYMBOL vmlinux 0xff10f660	kill_anon_super
+EXPORT_SYMBOL vmlinux 0xff1e9dd8	seq_list_start
+EXPORT_SYMBOL vmlinux 0xff2d0f2b	sock_no_socketpair
+EXPORT_SYMBOL vmlinux 0xff480992	dump_fpu
+EXPORT_SYMBOL vmlinux 0xff6878cf	fb_default_cmap
+EXPORT_SYMBOL vmlinux 0xff708fd3	mempool_destroy
+EXPORT_SYMBOL vmlinux 0xff7559e4	ioport_resource
+EXPORT_SYMBOL vmlinux 0xff818142	__set_page_dirty_buffers
+EXPORT_SYMBOL vmlinux 0xff8fd62e	security_sb_clone_mnt_opts
+EXPORT_SYMBOL vmlinux 0xff964b25	param_set_int
+EXPORT_SYMBOL vmlinux 0xff9ca065	fb_edid_to_monspecs
+EXPORT_SYMBOL vmlinux 0xffc7c184	__init_waitqueue_head
+EXPORT_SYMBOL vmlinux 0xffd5a395	default_wake_function
+EXPORT_SYMBOL_GPL arch/x86/crypto/aes-i586 0x7060bf0a	crypto_aes_encrypt_x86
+EXPORT_SYMBOL_GPL arch/x86/crypto/aes-i586 0xe409b491	crypto_aes_decrypt_x86
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x0cc1e40f	crypto_it_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x24aac4d9	crypto_aes_expand_key
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x3dc916b6	crypto_fl_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x40d46b21	crypto_ft_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x49246679	crypto_aes_set_key
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x71dc9998	crypto_il_tab
+EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x7f431542	async_memcpy
+EXPORT_SYMBOL_GPL crypto/async_tx/async_pq 0x0e708855	async_gen_syndrome
+EXPORT_SYMBOL_GPL crypto/async_tx/async_pq 0x7a8b2358	async_syndrome_val
+EXPORT_SYMBOL_GPL crypto/async_tx/async_raid6_recov 0x2ebc894f	async_raid6_2data_recov
+EXPORT_SYMBOL_GPL crypto/async_tx/async_raid6_recov 0x613660ef	async_raid6_datap_recov
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x539dc7c2	async_tx_quiesce
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xf13c01b2	async_tx_submit
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xfc05c133	async_trigger_callback
+EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x61033bd1	async_xor_val
+EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0xcde77816	async_xor
+EXPORT_SYMBOL_GPL crypto/cryptd 0x0e80195e	cryptd_free_ahash
+EXPORT_SYMBOL_GPL crypto/cryptd 0x6f268a41	cryptd_shash_desc
+EXPORT_SYMBOL_GPL crypto/cryptd 0x911697aa	cryptd_ablkcipher_child
+EXPORT_SYMBOL_GPL crypto/cryptd 0x993fa5ca	cryptd_ahash_child
+EXPORT_SYMBOL_GPL crypto/cryptd 0xbf0a25aa	cryptd_alloc_ahash
+EXPORT_SYMBOL_GPL crypto/cryptd 0xfea387a1	cryptd_alloc_ablkcipher
+EXPORT_SYMBOL_GPL crypto/cryptd 0xff540cb7	cryptd_free_ablkcipher
+EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0	des_ekey
+EXPORT_SYMBOL_GPL crypto/twofish_common 0x327361e0	twofish_setkey
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0022d407	ata_sff_wait_ready
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75	ata_tf_from_fis
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d	ata_id_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x01484e23	ata_sas_slave_configure
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x01679f48	sata_link_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x01a86f4c	ata_host_detach
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x029a5f5f	ata_bmdma32_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c	ata_timing_cycle2mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8	ata_dev_classify
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x06070e85	ata_sff_pause
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0837ee6c	ata_cable_unknown
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0ed0e124	ata_dev_disable
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x137fbff4	ata_sff_exec_command
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x177b1bb3	sata_scr_write
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1953f503	ata_link_next
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x19f7c365	ata_sff_dma_pause
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1c55ffe6	ata_sff_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1e76f96e	ata_sff_freeze
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1eb949ba	ata_do_dev_read_id
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1ede7dea	ata_port_schedule_eh
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2043d6db	ata_wait_after_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2362e5f4	ata_pci_bmdma_clear_simplex
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2a33b7e5	sata_sff_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2ddc4609	ata_sff_dev_classify
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2ebc3fbb	sata_scr_valid
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2f328b37	ata_sff_qc_fill_rtf
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x340923f4	ata_pci_device_do_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3b614a86	ata_port_freeze
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3e6b14a2	sata_set_spd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3f571609	ata_qc_complete
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x408c0032	ata_sff_prereset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec	ata_xfer_mode2mask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82	ata_xfer_mode2shift
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x454579e0	ata_sff_busy_sleep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x45fa71c1	ata_sff_host_intr
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x45fac6fa	ata_sff_irq_clear
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4e0e0d6b	ata_host_register
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4ed52afa	ata_port_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d	sata_deb_timing_normal
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4ff8b7f3	ata_cable_sata
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5074772c	ata_bmdma_setup
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x509f442b	ata_pio_need_iordy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x518d6151	ata_host_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x529896c0	sata_pmp_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x56829df8	ata_host_activate
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x583cc6a4	sata_scr_read
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5d123787	ata_link_offline
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5e4b8171	ata_sff_wait_after_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6478dd61	ata_sff_irq_on
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6638c16c	ata_pci_bmdma_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x68b85706	ata_pci_remove_one
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6965e77b	ata_sas_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb	ata_scsi_slave_config
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6aa3dcd5	ata_sas_port_destroy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6b4c1fd3	ata_scsi_simulate
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6fb9f0bc	ata_scsi_queuecmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb	ata_xfer_mask2mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7086f5e9	dev_attr_em_message_type
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7104d3c6	ata_qc_complete_multiple
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7110620c	ata_do_eh
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x716a5a92	sata_link_debounce
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x720bb99e	dev_attr_sw_activity
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x72759ba6	ata_port_disable
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x732c4006	ata_ehi_push_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x739679c2	ata_sas_scsi_ioctl
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a	ata_sff_std_ports
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x74290a19	ata_link_online
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e	ata_pack_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x74d50cc7	ata_bus_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x75d26d90	ata_dev_next
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x786ffb8d	ata_sff_postreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x793fb7b8	sata_pmp_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7c6dbfc7	ata_dummy_port_info
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7c9ce8ad	ata_sff_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7db84da2	dev_attr_link_power_management_policy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8149ea54	ata_timing_find_mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x84f48868	ata_scsi_ioctl
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x85db65f6	ata_host_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x861ffa07	ata_sff_data_xfer
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x896731a0	ata_pci_sff_prepare_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8aa501aa	sata_std_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b5995a4	ata_bmdma_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1	ata_tf_to_fis
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9246d735	ata_sff_softreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x93d4e324	ata_host_alloc_pinfo
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723	ata_scsi_slave_destroy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x954f3773	ata_sas_port_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x96069a9a	ata_cable_80wire
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x99cc38a7	ata_bmdma_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9be0a7bb	ata_eh_qc_complete
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9d432f04	ata_cable_ignore
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e818180	ata_sff_port_start32
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9f686ecc	ata_std_postreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa2a8c81c	ata_port_pbar_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa35a4ce6	ata_host_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa4133859	ata_sff_dev_select
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa4c98355	ata_pci_device_do_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa607f76d	ata_std_qc_defer
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa817e019	__ata_ehi_push_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa8fa8c0b	ata_sff_hsm_move
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa9bb909a	ata_sff_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaeb0bf3f	ata_sff_post_internal_cmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaf3e40e7	ata_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaf3f6fe0	ata_sff_interrupt
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb0ec3707	ata_eh_analyze_ncq_error
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb19c3669	sata_link_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb2d04f71	ata_link_abort
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb4179264	ata_sas_port_stop
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb4e4716b	sata_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661	ata_id_c_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb8e6024c	ata_pci_sff_init_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb598df5	ata_port_probe
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbb823461	ata_ehi_clear_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbcc187d6	ata_bmdma_status
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbd30a890	ata_sff_dumb_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbd3afd63	ata_std_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbde2755d	ata_sff_drain_fifo
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4	ata_unpack_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1d7015	ata_common_sdev_attrs
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc1a822e7	ata_sff_tf_load
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc2eaa8b2	ata_sff_qc_issue
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d	sata_deb_timing_long
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf	ata_mode_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc5fab11c	ata_sas_queuecmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc6295fd4	ata_sff_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e	ata_scsi_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc74c6e6b	ata_sff_data_xfer32
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc81fab14	ata_host_alloc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc8bf6e0f	ata_dev_pair
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xca59d00b	ata_pci_device_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xccc2dd90	ata_sff_lost_interrupt
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa	sata_deb_timing_hotplug
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xcd694615	ata_eh_freeze_port
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xce211f29	ata_slave_link_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd153bb0b	ata_sff_check_status
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd28f9652	ata_noop_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd3b01936	ata_dummy_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd6841ee9	ata_pci_device_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd88294b9	ata_cable_40wire
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd8f02b8b	ata_do_set_mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd919f440	ata_sff_thaw
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd97a459f	ata_timing_compute
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdd627103	ata_eh_qc_retry
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdf0d7507	ata_sas_port_alloc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdfa3c1f1	ata_std_bios_param
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe041e78e	ata_std_prereset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe1f0fd6f	ata_port_abort
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe493c662	ata_pci_sff_activate_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0	ata_wait_register
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe7c1f197	dev_attr_unload_heads
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe890b413	ata_sg_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe9ad635a	ata_eh_thaw_port
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f	atapi_cmd_type
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xea825304	ata_sff_tf_read
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xedc9eb22	pci_test_config_bits
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xef6566f0	sata_async_notification
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf034400f	ata_host_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf06f63eb	dev_attr_em_message
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf32ba8e5	ata_base_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf381d59b	ata_sff_data_xfer_noirq
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf3eed1d5	sata_pmp_qc_defer_cmd_switch
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf5496b1f	ata_bmdma_stop
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6004d13	ata_pci_sff_init_one
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6e874f5	ata_timing_merge
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb	ata_ratelimit
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf97c66e9	ata_bmdma_mode_filter
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160	ata_id_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xfd2bdfc5	sata_scr_write_flush
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xff87ab83	ata_pio_queue_task
+EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0x08f229e0	sis_info133_for_sata
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464	cfag12864b_isinited
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d	cfag12864b_disable
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6	cfag12864b_isenabled
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926	cfag12864b_enable
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342	cfag12864b_getrate
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95	cfag12864b_buffer
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23	ks0108_displaystate
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518	ks0108_writedata
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333	ks0108_startline
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968	ks0108_isinited
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db	ks0108_writecontrol
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2	ks0108_page
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b	ks0108_address
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0x9e2a0d70	agp_remove_bridge
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xb8dc0953	agp_add_bridge
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xd6feefa5	agp_num_entries
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xe089cfcc	agp_memory_reserved
+EXPORT_SYMBOL_GPL drivers/char/scx200_gpio 0x0e7a011c	scx200_gpio_ops
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x11e3b699	tpm_show_caps
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x26f74c13	tpm_write
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x28ae8370	tpm_pm_resume
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x2e627383	tpm_register_hardware
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x37497536	tpm_dev_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x4a3ebfdc	tpm_show_pcrs
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x5d995e3d	tpm_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x606eb812	tpm_dev_vendor_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x60f1defd	tpm_show_owned
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x6327661e	tpm_read
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x69865cb6	tpm_open
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x77c6fcef	tpm_gen_interrupt
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x79af2662	tpm_show_caps_1_2
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x801efdd8	tpm_show_pubek
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x86dd6247	tpm_calc_ordinal_duration
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9b59dd9a	tpm_store_cancel
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xa503a998	tpm_get_timeouts
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xaa10be4d	tpm_show_active
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xadf6aa4d	tpm_pcr_read
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xbe58157b	tpm_continue_selftest
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc29ff4a4	tpm_pm_suspend
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc37226a5	tpm_pcr_extend
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc3df51bb	tpm_show_enabled
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xd72d0e9a	tpm_remove_hardware
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xfc001b6c	tpm_show_temp_deactivated
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xfe9acdad	tpm_show_timeouts
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0a7eb2d9	edac_pci_del_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0c32ff8a	edac_pci_alloc_index
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0f4cd64d	edac_mc_add_mc
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1f3c6e6f	edac_mc_find_csrow_by_page
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x302a1d2d	edac_device_handle_ue
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x3c366f49	edac_pci_release_generic_ctl
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x54d3764f	edac_pci_add_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5da1f965	edac_device_free_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5fe32c5d	edac_device_alloc_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x681b4644	edac_pci_handle_npe
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6e3ff83a	edac_device_alloc_index
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x802f5515	edac_mc_del_mc
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x83bebaf3	edac_mc_free
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x84ceed00	edac_device_handle_ce
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x88850f58	edac_mc_handle_ue_no_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x9f380e38	edac_pci_handle_pe
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa8fc1f2b	edac_pci_alloc_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xc169bc4c	edac_device_add_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xc7316af4	edac_pci_reset_delay_period
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xcf708f6d	edac_mc_handle_ce
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xdc7384e0	edac_pci_create_generic_ctl
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xdd31af59	edac_device_del_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xe7fba404	edac_mc_handle_ce_no_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf448a447	edac_mc_handle_ue
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xf871df0d	edac_pci_free_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xff782570	edac_mc_alloc
+EXPORT_SYMBOL_GPL drivers/gpu/drm/drm 0x27399f06	drm_class_device_register
+EXPORT_SYMBOL_GPL drivers/gpu/drm/drm 0x8943d008	drm_class_device_unregister
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x05495392	hid_debug
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x18b864c8	hidraw_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x2cdea1e1	hid_check_keys_pressed
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x41a199b1	hid_dump_input
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x455121b3	hid_input_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x475bd051	hid_destroy_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x4bc8cb8d	hid_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x55facdee	hidinput_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x56fa21fb	hidraw_report_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x59b8a882	hid_output_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x5a96d949	hid_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x6a840bf5	hid_parse_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x6bbaf979	hid_allocate_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x7bc85448	hidraw_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xb16a6c12	hidinput_report_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xbdef6913	hid_add_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xc69aa128	hid_report_raw_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xc75f875c	hid_dump_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xda56e31f	__hid_register_driver
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xdac404e7	hid_debug_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xdd02cde7	hid_resolv_usage
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xe22bbe6e	hid_unregister_driver
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xe8ac31ee	hidinput_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xee4398c9	hid_set_field
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xfaad0891	hidinput_find_field
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xfe36af7b	hid_dump_field
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e	usbhid_lookup_quirk
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x3cf382cd	usbhid_set_leds
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x6ccbdc45	hiddev_hid_event
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x71d678fe	usbhid_submit_report
+EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x3d8e8578	nforce2_smbus
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x1b6b4d19	i2c_bus_type
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x34d6fc9e	i2c_new_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x6aa8578a	i2c_add_numbered_adapter
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x767793ee	i2c_unregister_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xa335215c	i2c_new_probed_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xe0cdd22b	i2c_new_dummy
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x5f195b27	hpsb_config_rom_ip1394_add
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x62c14f18	hpsb_config_rom_ip1394_remove
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf	hpsb_disable_irm
+EXPORT_SYMBOL_GPL drivers/input/ff-memless 0x2c843d31	input_ff_create_memless
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x14dc3560	wm97xx_config_gpio
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x20762ee3	wm97xx_reg_write
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x48800d04	wm9712_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x4cd52364	wm97xx_set_gpio
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x553e105e	wm9705_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x6643cffa	wm97xx_read_aux_adc
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x76983bd4	wm97xx_get_gpio
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x787d70ae	wm97xx_reg_read
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x842a0d9a	wm9713_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xb19a3ceb	wm97xx_unregister_mach_ops
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xc632bfb9	wm97xx_register_mach_ops
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xcb88c597	wm97xx_set_suspend_mode
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0x4655e050	led_classdev_suspend
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0xaa9d5433	led_classdev_resume
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0xdc1ead11	led_classdev_unregister
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0xece71002	led_classdev_register
+EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xa226f7ba	dm_unregister_path_selector
+EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xe50f4adc	dm_register_path_selector
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x14563ff4	dm_rh_dirty_log
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x1565c29f	dm_region_hash_create
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x34fc589e	dm_rh_get_state
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x3c7bdb87	dm_region_hash_destroy
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x439473e6	dm_rh_mark_nosync
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x5bd2743c	dm_rh_inc_pending
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x5f5b6ca9	dm_rh_dec
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x5fce6ed6	dm_rh_region_to_sector
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x6fdf68cc	dm_rh_recovery_start
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x770e69bc	dm_rh_get_region_key
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x7999eee8	dm_rh_start_recovery
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x7d00ae88	dm_rh_flush
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x7ec8a9b4	dm_rh_recovery_in_flight
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x868cc3e1	dm_rh_recovery_prepare
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xa4f5b770	dm_rh_stop_recovery
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xb4814627	dm_rh_get_region_size
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xc4b39b4c	dm_rh_delay
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xc62601db	dm_rh_region_context
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xe312c8b5	dm_rh_bio_to_region
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xe646b80b	dm_rh_recovery_end
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xf274b7ce	dm_rh_update_states
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0x2ea85eb2	sync_page_io
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0x6f7a79f5	md_allow_write
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0xc6e45b4c	md_new_event
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0xd878bff2	md_do_sync
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0x05513b71	raid6_call
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0x0b8ef590	raid6_2data_recov
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0x4a48d81c	raid6_datap_recov
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x2a29109e	i2o_pool_free
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x8b4651f8	i2o_dma_realloc
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x93448e77	i2o_dma_free
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x9ef88d14	i2o_dma_map_single
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xa4ddeaa1	i2o_dma_map_sg
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xb3e3b10c	i2o_pool_alloc
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xb7b45fc5	i2o_sg_tablesize
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xb80e5977	i2o_dma_alloc
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x07731c7e	sm501_modify_reg
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x0afe2343	sm501_misc_control
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x265f7456	sm501_unit_power
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x5ff5cee8	sm501_set_clock
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xce4512be	sm501_find_clock
+EXPORT_SYMBOL_GPL drivers/misc/eeprom/eeprom_93cx6 0x2df115d4	eeprom_93cx6_multiread
+EXPORT_SYMBOL_GPL drivers/misc/eeprom/eeprom_93cx6 0x63d14d2f	eeprom_93cx6_read
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x1637e472	enclosure_component_register
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x21b0c7e1	enclosure_find
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x315565ac	enclosure_for_each_device
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xa439af54	enclosure_remove_device
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xb2af00e5	enclosure_unregister
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xd3e49a8b	enclosure_register
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xd5617e01	enclosure_add_device
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x03cfb2a6	cfi_cmdset_0001
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x2ad54905	cfi_cmdset_0003
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x55bfa1f3	cfi_cmdset_0200
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0xd3e0b7f4	cfi_cmdset_0002
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0xb50ca4fe	cfi_cmdset_0020
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0x94375d2e	cfi_qry_mode_off
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0xeec87c54	cfi_qry_mode_on
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0xfb837893	cfi_qry_present
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0xe1d27623	DoC2k_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0xeb18d38d	DoCMil_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0xe3f700b2	DoCMilPlus_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659	doc_decode_ecc
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x008b9c4c	mtd_table
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x03a8c131	mtd_erase_callback
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x3195babd	put_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x3cf75f55	get_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x4d424a81	get_mtd_device_nm
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x57db52c4	mtd_table_mutex
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x5ae0bbeb	unregister_mtd_user
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x70203355	register_mtd_parser
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8a09ff46	default_mtd_writev
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8e02bb80	parse_mtd_partitions
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xba7a182a	register_mtd_user
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xbdc9cd49	get_sb_mtd
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xce4e291a	del_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xd6519389	add_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xdda03bb2	deregister_mtd_parser
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xfea0c0e8	kill_mtd_super
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x170f04a4	add_mtd_blktrans_dev
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x3fdab5ce	deregister_mtd_blktrans
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xf03cc840	del_mtd_blktrans_dev
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xfa16a74d	register_mtd_blktrans
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x258aae88	nand_scan
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x69624c64	nand_scan_tail
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x9e4dbaa6	nand_scan_ident
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xf6c65513	nand_wait_ready
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xf71b1dbe	nand_release
+EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x2106e18b	onenand_release
+EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0xadfad120	onenand_scan
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x13ce563f	ubi_close_volume
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x2f2009b1	ubi_leb_map
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x396673bf	ubi_leb_unmap
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20	ubi_sync
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x6f09ba8a	ubi_register_volume_notifier
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x7a678d3e	ubi_leb_read
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa34f701e	ubi_get_volume_info
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xaaae145e	ubi_leb_write
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4	ubi_get_device_info
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc5bef7c	ubi_open_volume
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xd05f688a	ubi_leb_change
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xdc66abc3	ubi_is_mapped
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xe3ac0b0b	ubi_open_volume_nm
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xea38c162	ubi_leb_erase
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xfd6f0ef9	ubi_unregister_volume_notifier
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xfe581364	ubi_do_get_device_info
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0530976a	mlx4_qp_to_ready
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x07f79b35	mlx4_mtt_cleanup
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0b9ce306	mlx4_db_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0d2035d7	mlx4_buf_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0fb2fcbf	mlx4_uar_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x11af9100	mlx4_unregister_interface
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1d1b014f	mlx4_register_mac
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x212d6363	mlx4_buf_write_mtt
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2401a011	mlx4_srq_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x271af80a	mlx4_uar_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x353252b0	mlx4_cq_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x40a46565	mlx4_srq_arm
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x442cde29	mlx4_cq_resize
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4475578f	mlx4_buf_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x45d82a1f	mlx4_fmr_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x45f79445	mlx4_unregister_mac
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4ca536eb	mlx4_qp_remove
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4de7f602	mlx4_fmr_unmap
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5475e4e5	mlx4_map_phys_fmr
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x56675d32	mlx4_alloc_cmd_mailbox
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5806fcdc	mlx4_srq_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x59f3f096	__mlx4_cmd
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5c8b7e5f	mlx4_SYNC_TPT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x62072af8	mlx4_INIT_PORT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6856d6b2	mlx4_qp_query
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6a8471fb	mlx4_multicast_attach
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6c3c45df	mlx4_unregister_vlan
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6ce80b2f	mlx4_qp_modify
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6e3094a6	mlx4_pd_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7397efae	mlx4_pd_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x75f90d9e	mlx4_cq_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7a6e47d3	mlx4_qp_release_range
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x7fb7fffe	mlx4_register_vlan
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8725d7a0	mlx4_srq_query
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x87b84f5d	mlx4_write_mtt
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x891331fa	mlx4_mr_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x89e5ea0a	mlx4_free_hwq_res
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8c3175f3	mlx4_qp_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9de697f9	mlx4_mtt_addr
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9f29f3b1	mlx4_fmr_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb077f23b	mlx4_CLOSE_PORT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb9defa43	mlx4_cq_modify
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbbec4ae0	mlx4_mr_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbcc11d2c	mlx4_alloc_hwq_res
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xbd0b5d75	mlx4_fmr_enable
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc13a5059	mlx4_multicast_detach
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc73013c4	mlx4_db_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xd57244bb	mlx4_mr_enable
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe41c46d1	mlx4_qp_reserve_range
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe7b33bd8	mlx4_register_interface
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf08b41d9	mlx4_mtt_init
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf5d4b589	mlx4_qp_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xfe171dcc	mlx4_free_cmd_mailbox
+EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0x3669c46a	usbnet_generic_cdc_bind
+EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xac023fb6	usbnet_cdc_unbind
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x3e6d4e81	rndis_command
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x54644840	rndis_unbind
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x981a8a81	generic_rndis_bind
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xcb692b2f	rndis_rx_fixup
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xd48a88bc	rndis_tx_fixup
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xf3209789	rndis_status
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x043cedc2	usbnet_purge_paused_rxq
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0c5ac323	usbnet_open
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0d3e1591	usbnet_defer_kevent
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0e6d196c	usbnet_probe
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x1144ece6	usbnet_change_mtu
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x1d50e7ef	usbnet_set_msglevel
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x32f62669	usbnet_stop
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x400c021b	usbnet_pause_rx
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x52afe440	usbnet_get_settings
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x6cc1c78b	usbnet_disconnect
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x702ada33	usbnet_resume
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x73d70f08	usbnet_tx_timeout
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x7f4c3561	usbnet_suspend
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x83fa1492	usbnet_get_msglevel
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x907d2792	usbnet_get_ethernet_addr
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x96e6b1d3	usbnet_start_xmit
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xb1f9c9af	usbnet_skb_return
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xb20d35e4	usbnet_resume_rx
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xba69a89e	usbnet_get_endpoints
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xbb601a1c	usbnet_get_drvinfo
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xcd809594	usbnet_nway_reset
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xd9c9ea9b	usbnet_unlink_rx_urbs
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xddee3bf8	usbnet_get_link
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xe44f735a	usbnet_set_settings
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x172e22a9	cpci_hp_register_bus
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x1a66d37f	cpci_hp_unregister_controller
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x5c3e3e2d	pci_hp_change_slot_info
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be	cpci_hp_start
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x93521431	cpci_hp_unregister_bus
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05	cpci_hp_stop
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xb24bc584	cpci_hp_register_controller
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xbb8c60bb	pci_hp_deregister
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xc6cd0d48	__pci_hp_register
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xd406ae3b	pci_configure_slot
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x055a0099	scsi_dh_detach
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x1d4365a1	scsi_register_device_handler
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x3a6eea22	scsi_dh_activate
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x523dd2fa	scsi_dh_set_params
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2	scsi_dh_handler_exist
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x8048b3e7	scsi_dh_attach
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0xabcc1cad	scsi_unregister_device_handler
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349	iscsi_pool_init
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0eaf6173	iscsi_complete_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0f7f1709	iscsi_eh_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1a8b554c	iscsi_host_remove
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1d1a1d84	iscsi_complete_scsi_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x246b99d7	iscsi_conn_stop
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x29127219	iscsi_queuecommand
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x34f85af1	iscsi_requeue_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x38aa7619	iscsi_host_add
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3b1b3222	iscsi_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14	iscsi_pool_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4a9fd4db	iscsi_session_failure
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4c2ffb51	iscsi_session_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x50b17199	iscsi_conn_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x53ec4494	iscsi_conn_queue_work
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x57578e06	iscsi_host_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x5d25fdfb	iscsi_set_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x5e360995	iscsi_conn_bind
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x61581c2e	iscsi_suspend_queue
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x6f17a1fa	iscsi_suspend_tx
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x71422c72	iscsi_conn_failure
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9a512da0	__iscsi_get_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa422367e	iscsi_host_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa6315ee1	iscsi_eh_target_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xa89950f3	iscsi_conn_start
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xafa713b6	iscsi_conn_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb0b6a552	iscsi_itt_to_ctask
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb56e2c47	iscsi_session_recovery_timedout
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb7b378c2	iscsi_prep_data_out_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc1263ec4	iscsi_itt_to_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc1905dae	iscsi_update_cmdsn
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc74d9f15	iscsi_conn_send_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xcf3652f3	iscsi_put_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xdf940656	iscsi_host_set_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe2ffb27f	__iscsi_complete_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xe530c5d5	iscsi_verify_itt
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xea911caf	iscsi_session_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xed45ecbd	iscsi_host_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf269e33d	iscsi_conn_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf3bfa71c	iscsi_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf70b167e	iscsi_session_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf75b544f	iscsi_eh_device_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x008594be	iscsi_tcp_recv_skb
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x15108254	iscsi_tcp_recv_segment_is_hdr
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x1d76a082	iscsi_tcp_hdr_recv_prep
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x2308b6b3	iscsi_tcp_cleanup_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x4d6b3aaa	iscsi_tcp_conn_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x520f3d29	iscsi_tcp_task_xmit
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x6a5dee96	iscsi_segment_init_linear
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x7420bce4	iscsi_tcp_segment_unmap
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x75862a21	iscsi_segment_seek_sg
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x7782bed5	iscsi_tcp_segment_done
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x7ddf7e32	iscsi_tcp_conn_get_stats
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x964d66ad	iscsi_tcp_r2tpool_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xa7ea384d	iscsi_tcp_dgst_header
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xb9e525a3	iscsi_tcp_r2tpool_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xe2aec996	iscsi_tcp_task_init
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xf919a910	iscsi_tcp_conn_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x0c847262	sas_request_addr
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x0d802b87	__sas_task_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x10755766	sas_eh_bus_reset_handler
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x2693309b	sas_ssp_task_response
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x334cb367	sas_register_ha
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x3c33c2c0	sas_queuecommand
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x4c53a31b	sas_slave_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x5d9ec1b1	sas_change_queue_type
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x6849e048	sas_slave_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x70303abc	sas_find_local_phy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x7d2e0532	sas_unregister_ha
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x851b60d7	sas_target_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x896443d3	sas_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8a0ac3c1	sas_phy_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x9999fe31	sas_slave_configure
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x9ebb3c32	sas_bios_param
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xabbadacc	sas_eh_device_reset_handler
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb9f00e89	sas_task_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xc7568aa5	sas_phy_enable
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xd65e1a17	sas_domain_release_transport
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdc75fdd2	sas_domain_attach_transport
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xe5f7da65	sas_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xe8698662	sas_ioctl
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x1da5b007	srp_iu_get
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x366e5e5e	srp_cmd_queue
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x68aedd5c	srp_iu_put
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xb97019a9	srp_transfer_data
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xc851ba91	srp_target_free
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xe92635f1	srp_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1f1913b0	scsi_get_vpd_page
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x24e052e8	scsi_target_unblock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4	scsi_eh_get_sense
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x2cbffe98	sdev_evt_send
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x2f5e6de3	scsi_target_block
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a	sdev_evt_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x452b885f	scsi_flush_work
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x5055130b	scsi_internal_device_block
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x6d0fcc00	scsi_queue_work
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8	scsi_complete_async_scans
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa035e521	sdev_evt_send_simple
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa152051a	scsi_nl_add_driver
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa31ca392	scsi_nl_sock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xb19ce940	scsi_bus_type
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xb8302f43	scsi_mode_select
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xba378653	scsi_eh_ready_devs
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xbae34c27	scsi_nl_remove_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xc399468f	scsi_nl_remove_driver
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd0efd48c	scsi_nl_add_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd15dac3b	scsi_schedule_eh
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd82cfe8c	scsi_internal_device_unblock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xeae74760	scsi_nl_send_transport_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xee4a615c	__scsi_get_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x59a183ca	scsi_tgt_alloc_queue
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x80959b03	scsi_tgt_it_nexus_create
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x8115e385	scsi_tgt_tsk_mgmt_request
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x92d9ff73	scsi_tgt_queue_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xb274adad	scsi_host_get_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xb2da9d42	scsi_tgt_cmd_to_host
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xbd4a9c77	scsi_host_put_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xe0330fe7	scsi_tgt_free_queue
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xe30ada0b	scsi_tgt_it_nexus_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x0b607ed1	iscsi_recv_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x15cbea08	iscsi_unregister_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x19cadcbd	iscsi_destroy_conn
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x2d78bfe3	iscsi_remove_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x35869c4f	iscsi_scan_finished
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3d399049	iscsi_session_chkready
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3ff0404a	iscsi_free_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x46c2d10f	iscsi_offload_mesg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x633e7962	iscsi_destroy_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x668765d6	iscsi_create_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x672bbdee	iscsi_alloc_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x703b3872	iscsi_host_for_each_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x78b7956a	iscsi_lookup_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x8cb74d1e	iscsi_unblock_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xafce5d3d	iscsi_session_event
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xba600db8	iscsi_register_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xc52698e2	iscsi_conn_error_event
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xce038170	iscsi_create_conn
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xead6f28b	iscsi_destroy_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf099cbb6	iscsi_add_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf8af6424	iscsi_create_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xfd68022b	iscsi_block_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974	spi_populate_ppr_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac	spi_populate_sync_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff	spi_populate_width_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x2b63b0e2	srp_release_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x32002cc8	srp_attach_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x42116da4	srp_remove_host
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xdf3f7607	srp_rport_add
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xf9a80374	srp_rport_del
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x31244df6	spi_bitbang_start
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x53a81795	spi_bitbang_cleanup
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x569a7820	spi_bitbang_setup
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x6c4a46d3	spi_bitbang_transfer
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x6f169504	spi_bitbang_stop
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xe43cdac4	spi_bitbang_setup_transfer
+EXPORT_SYMBOL_GPL drivers/uio/uio 0x533e0db7	__uio_register_device
+EXPORT_SYMBOL_GPL drivers/uio/uio 0x641faba6	uio_unregister_device
+EXPORT_SYMBOL_GPL drivers/uio/uio 0xff660464	uio_event_notify
+EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x520b750f	usbatm_usb_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x7b54b47e	usbatm_usb_probe
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x001306b8	usb_altnum_to_altsetting
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x015b4c09	usb_mon_register
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x023a2ca9	usb_kill_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0604f1fd	usb_queue_reset_device
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0b190a39	usb_register_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0de6620b	usb_set_device_state
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0f770002	usb_hcd_check_unlink_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0f95e0d3	usb_unpoison_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x100c13c6	usb_kill_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x113d747e	usb_add_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x15c7918a	usb_put_intf
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba	usb_disabled
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1a9b538e	ehci_cf_port_reset_rwsem
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1c74f7e0	usb_autopm_get_interface_async
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1de977ef	usb_remove_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x22ae1a40	usb_buffer_free
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x22bc7dcc	usb_hcd_link_urb_to_ep
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x23aae284	usb_buffer_map_sg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x296b3cb1	usb_driver_set_configuration
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x29c04b00	usb_hc_died
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2a21a8ab	usb_ifnum_to_if
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x38b0263b	usb_set_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x39459080	usb_match_one_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3ab7937e	usb_reset_configuration
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c	usb_register_notify
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3cf4bb43	usb_hcd_platform_shutdown
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x40009fc8	usb_sg_cancel
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x43347d40	usb_hcd_pci_probe
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x44846041	usb_hub_clear_tt_buffer
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4ae72ace	usb_get_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4b2f6f9c	usb_get_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x527261ae	usb_store_new_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x56b456ef	usb_reset_device
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5d2b685a	usb_get_from_anchor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5fbbf2b3	usb_control_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5ff35d48	usb_get_current_frame_number
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x60d97391	usb_lock_device_for_reset
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x628686f7	usb_hcd_pci_shutdown
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x65545edf	usb_hcd_resume_root_hub
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6d145966	usb_autopm_get_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x722c4f65	usb_scuttle_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x731daa24	usb_driver_claim_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x77c30bf4	usb_register_device_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d	usb_calc_bus_time
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x80b22255	usb_driver_release_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x89ccadda	usb_deregister
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x91482eef	usb_anchor_empty
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9507d9f4	usb_init_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x96b54698	usb_get_intf
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x97a44677	usb_buffer_alloc
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496	__usb_get_extra_descriptor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9984c858	usb_unpoison_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9bfb7831	usb_unlink_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9ec9de2b	usb_get_status
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa28d8527	usb_poison_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa3f7cf77	usb_hcd_poll_rh_status
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa52682ca	usb_hcd_pci_pm_ops
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa5370281	usb_deregister_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa54af0ab	usb_put_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa67298dc	usb_clear_halt
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa73836b3	usb_root_hub_lost_power
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa857b427	usb_bulk_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa9c3095f	usb_buffer_unmap_sg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaa1a49b5	usb_sg_wait
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xaa55f271	usb_register_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc	usb_bus_list
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xafc7c996	usb_unlink_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb0eedea9	usb_wait_anchor_empty_timeout
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb261c0c1	usb_submit_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb3a6bbfa	usb_autopm_put_interface_async
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb6446831	usb_bus_list_lock
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb7fa8b1a	usb_put_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbcbd987d	usb_alloc_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbd99bdf8	usb_debug_root
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbff39ab7	usb_unanchor_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7	usb_hcds_loaded
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc4efa969	usb_deregister_device_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc5fa630b	usb_sg_init
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc99b2267	usb_get_descriptor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcd1c1716	usb_autopm_set_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd36f8729	usb_hcd_pci_remove
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd45e9cea	usb_string
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdd382f49	usb_autopm_put_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe48bd056	usb_interrupt_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe5d58946	usb_ep0_reinit
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe77e8b99	usb_match_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909	usb_unregister_notify
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xed3f6c02	usb_anchor_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xef23abc2	usb_find_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf51e7613	usb_hcd_unlink_urb_from_ep
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf617d3f8	usb_reset_endpoint
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf636816c	usb_free_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf73e3cf2	usb_create_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf78ad2d8	usb_hcd_giveback_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfdc00dca	usb_poison_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1	usb_mon_deregister
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xffd9776d	usb_get_urb
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x061b0066	usb_ftdi_elan_edset_setup
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x11a7f97c	usb_ftdi_elan_edset_output
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x1a69d5a8	usb_ftdi_elan_edset_empty
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x7347b540	usb_ftdi_elan_edset_single
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x77af0f28	usb_ftdi_elan_write_pcimem
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x8857a8c5	usb_ftdi_elan_edset_input
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x9b58886d	usb_ftdi_elan_edset_flush
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xb77dd2e2	ftdi_elan_gone_away
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe95b2ec1	usb_ftdi_elan_read_pcimem
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x0f4b10be	ezusb_set_reset
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1c34e42a	usb_serial_generic_open
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1ead89b3	usb_serial_register
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x356fed28	usb_serial_generic_read_bulk_callback
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x395e6260	usb_serial_generic_resubmit_read_urb
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x4e1ca71f	usb_serial_generic_resume
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x58b39022	usb_serial_probe
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x6da0ec95	usb_serial_handle_dcd_change
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x7740743c	usb_serial_port_softint
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x9ddcbae6	usb_serial_handle_break
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xac70ca7a	usb_serial_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xb4c1377b	ezusb_writememory
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xcb44368b	usb_serial_generic_write
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xd1b50405	usb_serial_handle_sysrq_char
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xd7873cad	usb_serial_deregister
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xddc9cd0e	usb_serial_generic_write_bulk_callback
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x0be13004	usb_storage_usb_ids
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x3edad223	usb_usual_clear_present
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x5640b35b	usb_usual_ignore_device
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x89d4dbaf	usb_usual_check_type
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0xcd9991a9	usb_usual_set_present
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x0ba3779c	usb_stor_bulk_transfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x0d197f96	usb_stor_post_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x1bc3edc2	usb_stor_sense_invalidCDB
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x1d62fd22	usb_stor_control_msg
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x23382a41	usb_stor_Bulk_transport
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x278b5888	usb_stor_pre_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x3f01f625	usb_stor_clear_halt
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x484e3bca	usb_stor_access_xfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x64c2e565	usb_stor_bulk_transfer_sg
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x74af6c1b	usb_stor_transparent_scsi_command
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x76282d4b	usb_stor_ctrl_transfer
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x86e5c816	usb_stor_probe1
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x97bbf59b	fill_inquiry_response
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x990f46fa	usb_stor_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x9cd399c5	usb_stor_suspend
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xa71dd8f3	usb_stor_resume
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xa8166c4b	usb_stor_bulk_srb
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xa8984e33	usb_stor_CB_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xabed89e2	usb_stor_set_xfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xb9046135	usb_stor_Bulk_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xd2949b0c	usb_stor_reset_resume
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xe1fccb4c	usb_stor_CB_transport
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xffb1303f	usb_stor_probe2
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x2e033f0c	ili9320_write
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xad589501	ili9320_write_regs
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xb0bee7f5	ili9320_remove
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xb442fc60	ili9320_probe_spi
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xcb25b0f0	ili9320_resume
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xebfadf7b	ili9320_suspend
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xec653ea3	ili9320_shutdown
+EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0x9e9e48a9	fb_ddc_read
+EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x81eabf99	fb_sys_write
+EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0xabc7cfa7	fb_sys_read
+EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x3cc6d3f3	sis_malloc_new
+EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x960e2c17	sis_free_new
+EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20	vmlfb_unregister_subsys
+EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6	vmlfb_register_subsys
+EXPORT_SYMBOL_GPL fs/fat/fat 0x098b7a9c	fat_free_clusters
+EXPORT_SYMBOL_GPL fs/fat/fat 0x241f61f2	fat_add_entries
+EXPORT_SYMBOL_GPL fs/fat/fat 0x263cd6ff	fat_fs_error
+EXPORT_SYMBOL_GPL fs/fat/fat 0x2cc1016d	fat_getattr
+EXPORT_SYMBOL_GPL fs/fat/fat 0x2cd03dfb	fat_fill_super
+EXPORT_SYMBOL_GPL fs/fat/fat 0x34580521	fat_flush_inodes
+EXPORT_SYMBOL_GPL fs/fat/fat 0x36361e37	fat_search_long
+EXPORT_SYMBOL_GPL fs/fat/fat 0x69f3fd5c	fat_alloc_new_dir
+EXPORT_SYMBOL_GPL fs/fat/fat 0x7185f669	fat_detach
+EXPORT_SYMBOL_GPL fs/fat/fat 0x80d487dd	fat_attach
+EXPORT_SYMBOL_GPL fs/fat/fat 0x8cb5d65d	fat_build_inode
+EXPORT_SYMBOL_GPL fs/fat/fat 0x8cb7c3f0	fat_dir_empty
+EXPORT_SYMBOL_GPL fs/fat/fat 0xb613ff15	fat_remove_entries
+EXPORT_SYMBOL_GPL fs/fat/fat 0xc9c55279	fat_sync_inode
+EXPORT_SYMBOL_GPL fs/fat/fat 0xebf87f80	fat_scan
+EXPORT_SYMBOL_GPL fs/fat/fat 0xf0a950e9	fat_time_unix2fat
+EXPORT_SYMBOL_GPL fs/fat/fat 0xf44531d9	fat_setattr
+EXPORT_SYMBOL_GPL fs/fat/fat 0xfae02ba7	fat_get_dotdot_entry
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x2055a49a	fuse_request_send
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x272e621f	fuse_do_open
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x3a4f7542	fuse_conn_get
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x41758614	fuse_dev_operations
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x49b22a89	fuse_request_alloc
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x4bd02dfd	fuse_request_send_background
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x5fa38313	fuse_conn_kill
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x697916fb	fuse_direct_io
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x7c54b09b	fuse_put_request
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x7dd70feb	fuse_conn_init
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x977c9708	fuse_conn_put
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xa38eaea7	fuse_do_ioctl
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xa5323da2	fuse_dev_release
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xc3288918	fuse_sync_release
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xceada115	fuse_file_poll
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xf6f0f3fa	fuse_get_req
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xf723da9a	fuse_abort_conn
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x0894eb7a	nlmclnt_done
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x17ce645d	locks_end_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932	nlmsvc_unlock_all_by_ip
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x682b1ef8	nlmsvc_unlock_all_by_sb
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x6f959b35	locks_in_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x96877ac4	locks_start_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x9e87aade	nlmclnt_proc
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xa7b91a7b	lockd_down
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xc9b22890	nlmsvc_ops
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xf6933c48	lockd_up
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xfba62e5e	nlmclnt_init
+EXPORT_SYMBOL_GPL fs/nfs_common/nfs_acl 0xd183df67	nfsacl_decode
+EXPORT_SYMBOL_GPL fs/nfs_common/nfs_acl 0xe0e41fc0	nfsacl_encode
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x06526e1b	o2nm_node_get
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee	o2hb_fill_node_map
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1cb231d0	mlog_not_bits
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3	o2hb_check_node_heartbeating
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553	o2net_send_message
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b	o2hb_stop_all_regions
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x5a54d3d7	o2hb_unregister_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x5f032d02	o2nm_node_put
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x687f6251	mlog_and_bits
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x6ed7df6d	o2nm_get_node_by_num
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x85d77447	o2hb_register_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645	o2nm_this_node
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7	o2nm_configured_node_map
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa9f5379a	o2net_send_message_vec
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac	o2net_register_handler
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700	o2hb_check_node_heartbeating_from_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c	o2hb_check_local_node_heartbeating
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd6daa79c	o2nm_get_node_by_ip
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xdbb59f5e	o2hb_setup_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d	o2net_unregister_handler_list
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x04392718	dlm_print_one_lock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x1483fefd	dlmlock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x67b6c761	dlmunlock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x751e1e37	dlm_unregister_domain
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8	dlm_setup_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd72dd430	dlm_register_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e	dlm_errmsg
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6	dlm_unregister_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xf24757e9	dlm_register_domain
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f	dlm_errname
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415	ocfs2_cluster_this_node
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x06379db6	ocfs2_dlm_lvb_valid
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0b3d6461	ocfs2_stack_glue_unregister
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909	ocfs2_dlm_lock
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88	ocfs2_cluster_disconnect
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9	ocfs2_cluster_connect
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa	ocfs2_cluster_hangup
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68	ocfs2_dlm_lock_status
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x83ce7c56	ocfs2_stack_glue_register
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465	ocfs2_dlm_lvb
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3	ocfs2_stack_glue_set_locking_protocol
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0	ocfs2_dlm_unlock
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xbbc4ef97	ocfs2_stack_supports_plocks
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e	ocfs2_dlm_dump_lksb
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xf88eae22	ocfs2_plock
+EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x56b63670	lzo1x_1_compress
+EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0xf30fda27	lzo1x_decompress_safe
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57	free_rs
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9	init_rs_non_canonical
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e	decode_rs16
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329	init_rs
+EXPORT_SYMBOL_GPL net/802/garp 0x11ea11f8	garp_unregister_application
+EXPORT_SYMBOL_GPL net/802/garp 0x4d5955f8	garp_init_applicant
+EXPORT_SYMBOL_GPL net/802/garp 0x7f7b4b7a	garp_register_application
+EXPORT_SYMBOL_GPL net/802/garp 0xa6c1b50c	garp_request_join
+EXPORT_SYMBOL_GPL net/802/garp 0xc2311198	garp_request_leave
+EXPORT_SYMBOL_GPL net/802/garp 0xf349e05d	garp_uninit_applicant
+EXPORT_SYMBOL_GPL net/802/stp 0x54c609fc	stp_proto_register
+EXPORT_SYMBOL_GPL net/802/stp 0x920c599b	stp_proto_unregister
+EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05	ax25_bcast
+EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e	ax25_defaddr
+EXPORT_SYMBOL_GPL net/ax25/ax25 0xf8f8e3e4	ax25_register_pid
+EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0x810c4cd1	bt_class
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x0f9fab42	dccp_death_row
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a	dccp_timestamp
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x1e68c8cb	dccp_reqsk_init
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x3306409c	dccp_init_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x3479d122	inet_dccp_listen
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x44d12364	dccp_set_state
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x4cdd391d	dccp_feat_list_purge
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x4f2d56ab	dccp_poll
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x56b865cd	dccp_check_req
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a	dccp_state_name
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x5aa47534	dccp_hashinfo
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x5fbe0e0d	dccp_recvmsg
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x6316e8b8	dccp_reqsk_send_ack
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x6f3ba272	dccp_send_sync
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x70b1d967	dccp_orphan_count
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x7d47a11b	dccp_parse_options
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x84a7baa0	dccp_insert_option
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924	dccp_packet_name
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x89cc371d	dccp_rcv_state_process
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf	dccp_statistics
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8e34ca2e	dccp_make_response
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x92d642f7	dccp_destroy_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x9662eb4d	dccp_rcv_established
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x97187bfd	dccp_sendmsg
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x9b58863a	dccp_disconnect
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x9c53c129	dccp_setsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xa3ccbbf4	dccp_child_process
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xa3ff0966	dccp_close
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xab9ad066	dccp_create_openreq_child
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xaf1ff336	dccp_ioctl
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xb100b3e9	dccp_insert_option_timestamp
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xb2903c53	dccp_insert_option_elapsed_time
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xd1f20ff9	dccp_ctl_make_reset
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xd2dea6eb	dccp_getsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xd87fdb1a	dccp_connect
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xdf1f9a3a	dccp_sync_mss
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xe1430665	dccp_send_ack
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xe7f7d654	dccp_done
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xeb1647c9	dccp_shutdown
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x2e3cd730	dccp_v4_do_rcv
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x8d1a97bf	dccp_v4_send_check
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xad56699c	dccp_invalid_packet
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xca0e271d	dccp_v4_conn_request
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xd70dfbd0	dccp_v4_request_recv_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xf8468a8b	dccp_v4_connect
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921	need_ipv4_conntrack
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x822e5b64	nf_nat_seq_adjust_hook
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_defrag_ipv4 0x6b6c3d10	nf_defrag_ipv4_enable
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x01f20ada	nf_nat_proto_find_get
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6	nf_nat_proto_in_range
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x19eb172d	nf_nat_packet
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x44b3bec8	nf_nat_proto_put
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134	nf_nat_proto_nlattr_to_range
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xd7ae41d3	nf_nat_get_offset
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xdaeb989f	nf_nat_proto_unique_tuple
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xe6f651b4	nf_nat_proto_range_to_nlattr
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xffe6f7d1	nf_nat_icmp_reply_translation
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8	nf_nat_need_gre
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x7133c7a4	tcp_vegas_cwnd_event
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x89140fa3	tcp_vegas_get_info
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xaada98bb	tcp_vegas_pkts_acked
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xc2537cd4	tcp_vegas_state
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0xc74e442b	tcp_vegas_init
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1	net_ipv6_ctl_path
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x115c4e68	inet6_csk_bind_conflict
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1d77f6e1	ip6_dst_blackhole
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x2b18e71d	ipv6_dup_options
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x2d5c0cb6	ip6_dst_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3a65a1b6	inet6_csk_search_req
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3c797987	ip6_sk_dst_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3fe72dd6	ipv6_opt_accepted
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x45ee9d12	inet6_csk_addr2sockaddr
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x4604dd48	inet6_sk_rebuild_header
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x552a8721	inet6_csk_xmit
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x597d982c	inet6_destroy_sock
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x606c4fb7	fl6_sock_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x61ddb159	ip6_local_out
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x69b53a92	ipv6_find_tlv
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x85478a0b	inet6_hash_frag
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x9767eeaa	inet6_csk_reqsk_queue_hash_add
+EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x9162978c	ieee80211_iterate_active_interfaces
+EXPORT_SYMBOL_GPL net/mac80211/mac80211 0xc12acd5e	ieee80211_iterate_active_interfaces_atomic
+EXPORT_SYMBOL_GPL net/netfilter/ipvs/ip_vs 0xe6476b4a	net_vs_ctl_path
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd	nf_conntrack_lock
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd	nf_ct_port_nla_policy
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x091c0fd0	nf_conntrack_l4proto_tcp6
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1599ce86	nf_conntrack_l3proto_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1acfebe5	nf_conntrack_tuple_taken
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1eb3f826	nf_conntrack_in
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x20586eb4	__nf_conntrack_confirm
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2109b8f6	nf_conntrack_l3proto_generic
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x2e8343ab	nf_ct_get_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x31d88ea5	__nf_ct_try_assign_helper
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x372521c6	nf_ct_expect_init
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3a562f5d	nf_ct_extend_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3b2a6d52	nf_conntrack_l4proto_tcp4
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3b412650	nf_ct_expect_register_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3ed18669	__nf_ct_l4proto_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415	nf_ct_port_nlattr_to_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4223930a	nf_ct_unexpect_related
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4b9065a9	nf_ct_alloc_hashtable
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x509067a5	nf_ct_extend_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x50bb513e	nf_ct_delete_from_lists
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x50e39f0f	__nf_ct_refresh_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x56cc213c	nf_conntrack_event_cb
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5882ba33	nf_conntrack_set_hashsize
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5a8c9c40	nf_ct_nat_offset
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x60a72b7e	nf_conntrack_alter_reply
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x62813e5c	nf_ct_port_nlattr_tuple_size
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a	need_conntrack
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6fb63f4a	nf_ct_port_tuple_to_nlattr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x72d440c9	nf_conntrack_free
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7893937a	nf_conntrack_hash_insert
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710	nf_ct_l3proto_try_module_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x79fdb9f9	nf_ct_expect_unregister_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7d15a171	seq_print_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x81511fad	nf_conntrack_register_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x84e884be	nf_ct_insert_dying_list
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x853bce99	__nf_ct_kill_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8854a1da	nf_conntrack_untracked
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x88f3f962	nf_ct_l3proto_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89	nf_conntrack_htable_size
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f	nf_ct_invert_tuplepr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x93c40602	__nf_conntrack_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x972152c7	nf_ct_l3proto_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x989422dd	nf_conntrack_l4proto_udp6
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x99d899dc	nf_conntrack_helper_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9af3f6c1	nf_ct_free_hashtable
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9ef38c12	nf_ct_deliver_cached_events
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9f88456f	nf_conntrack_l4proto_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa6e76017	nf_ct_expect_related_report
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa88612a4	nf_conntrack_helper_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaa19085b	nf_ct_invert_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaa78018c	nf_conntrack_l4proto_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaaa2405f	nf_conntrack_l4proto_udp4
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xad73dfd1	print_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xae11156a	nf_ct_unlink_expect
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb205a082	nf_conntrack_unregister_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb3bf6613	nf_conntrack_flush_report
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb4f0be70	nf_ct_helper_ext_add
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e	nf_ct_l3proto_module_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb7672d84	nf_conntrack_l3proto_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbe6b85ae	nfnetlink_parse_nat_setup_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d	nf_ct_expect_hsize
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc3462142	nf_ct_expect_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc79022fb	nf_ct_expect_alloc
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcc9b0264	nf_ct_remove_expectations
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd3143153	nf_conntrack_alloc
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd3c759ea	nf_ct_iterate_cleanup
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd3e0260d	nf_conntrack_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd9412549	nf_expect_event_cb
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdbf133fe	nf_ct_get_tuplepr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe12d64c6	nf_ct_expect_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe2eebb0c	nf_ct_l3protos
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe39a1d7b	__nf_ct_expect_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf38bcdf3	nf_conntrack_max
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfa7275d6	__nf_conntrack_helper_find_byname
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0xfee20ef6	nf_nat_amanda_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0x8381cd27	nf_nat_ftp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x0d5396d0	get_h225_addr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x2f3246a8	set_h245_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x3b4184f4	set_ras_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x6d7ff374	nat_t120_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xadc9b632	nat_rtp_rtcp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xb83b36f0	nat_q931_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xc03fcd14	set_sig_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xd4e25d90	set_h225_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xeab17607	nat_callforwarding_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xfe766f80	nat_h245_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0x15750bda	nf_nat_irc_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x00db13f1	nf_nat_pptp_hook_exp_gre
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x5a3e8361	nf_nat_pptp_hook_inbound
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x95e54cf2	nf_nat_pptp_hook_outbound
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xc4d8880c	nf_nat_pptp_hook_expectfn
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0xcc7ac4a4	nf_ct_gre_keymap_add
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0xda78d355	nf_ct_gre_keymap_destroy
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x04fbf8b9	ct_sip_get_header
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x115f4200	nf_nat_sdp_port_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x27690ebb	nf_nat_sdp_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3141442a	ct_sip_parse_numerical_param
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x56102ebe	nf_nat_sip_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x58b2f4c8	nf_nat_sip_expect_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x6a03d233	ct_sip_get_sdp_header
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x8fefe35b	ct_sip_parse_address_param
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xafa74c64	nf_nat_sdp_media_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xdd48aa4e	ct_sip_parse_request
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xe3e875bd	nf_nat_sdp_session_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xe6e1b4c8	ct_sip_parse_header_uri
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x2e6465f1	nf_nat_tftp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x1f58e71b	nfnl_lock
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x3895cd7a	nfnl_unlock
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x9eb813bd	nfnetlink_subsys_register
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xc47a4b10	nfnetlink_unicast
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xe3a68979	nfnetlink_send
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xe3b351c7	nfnetlink_subsys_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329	nfnetlink_has_listeners
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xef9b4bbd	nfnetlink_set_err
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink_log 0xd27543d0	nfulnl_log_packet
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x03a6afb9	xt_replace_table
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x22aa56e1	xt_proto_fini
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2ac49d15	xt_unregister_table
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x3d30a29e	xt_proto_init
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x40728a63	xt_find_revision
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x4f432b51	per_cpu__xt_info_locks
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7f2ad082	xt_find_table_lock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7f738b8a	xt_check_target
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xbe810a1d	xt_table_unlock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xcefea9c2	xt_check_match
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xd19d7a2b	xt_request_find_target
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xeadb6542	xt_register_table
+EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc2429b63	xt_rateest_lookup
+EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xfc852663	xt_rateest_put
+EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x3a47b3fd	rxrpc_unregister_security
+EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0xb614f54e	rxrpc_register_security
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x008bf404	gss_pseudoflavor_to_service
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5	g_make_token_header
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x01f86d27	svc_gss_principal
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x39ad5eb9	gss_service_to_auth_domain_name
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x4fd9c655	gss_mech_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x51c7eb24	gss_mech_get_by_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x5a5c4657	gss_mech_register
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x6450a415	gss_mech_get
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x8675f1a6	gss_mech_put
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e	svcauth_gss_register_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x95a305c2	gss_svc_to_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef	g_token_size
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xedc80d12	gss_mech_get_by_name
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xefd43fe6	svcauth_gss_flavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e	g_verify_token_header
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0203f19e	unix_domain_find
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x025db6af	svc_close_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0392593d	rpcauth_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x03f95d3f	xdr_encode_word
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x05e807a9	xdr_encode_string
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x065994f1	xdr_encode_opaque_fixed
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0670921d	rpc_run_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0ba3e56f	xdr_buf_read_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0bc6cb4c	svc_wake_up
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0c82b09f	xdr_buf_subsegment
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0f668ba9	svc_auth_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0f9fd9c0	rpc_ntop
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x12962940	xdr_decode_word
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x12b750d8	xdr_shift_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x12df38c4	svc_reserve
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x12e280e3	svc_proc_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1310e40d	svc_find_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1386fc93	__rpc_wait_for_completion_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x138bbf4b	xprt_release_rqst_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x141cdd05	xprt_set_retrans_timeout_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1bf9919d	xdr_reserve_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1e65ae1d	rpcauth_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1f476e55	sunrpc_cache_register_pipefs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1fc910f5	svc_reg_xprt_class
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x228e6d40	rpc_print_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x26288aec	auth_domain_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x27f3dbc9	svc_drop
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x28ab31f3	rpcauth_init_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2919b156	xdr_decode_string_inplace
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774	rpc_free_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2e860d3f	xdr_decode_array2
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2eec63c9	xdr_encode_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59	rpc_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3407cd2e	xprt_release_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x34892290	rpc_setbufsize
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3685456a	rpc_bind_new_program
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x36abe0a2	rpc_alloc_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x409eb163	rpc_lookup_machine_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4303d9cc	rpc_restart_call
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x43b6c6ac	svc_print_addr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x468d7768	rpc_unlink
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x476d8ca3	xprt_disconnect_done
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a21d7e9	xdr_read_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a61dc72	xdr_init_encode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4c375bea	cache_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4c93b70a	rpc_call_sync
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x50929e56	xdr_partial_copy_from_skb
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5189fbc5	svc_auth_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5325008c	rpc_malloc
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68	nlm_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3	rpc_destroy_wait_queue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5a00f890	rpc_killall_tasks
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5a2b31ac	svc_create_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5b14ec1a	rpc_put_mount
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000	rpc_proc_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bdacb07	svc_xprt_names
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6065c457	xprt_adjust_cwnd
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6337bf28	rpc_mkpipe
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x65a40c79	rpc_sleep_on
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x660535e1	rpc_call_null
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x667fe1c4	xprt_write_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x675524ec	rpc_sockaddr2uaddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6882f156	xprt_reserve_xprt_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x68af7c12	rpc_proc_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5	rpcb_getport_sync
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6eea229d	svcauth_unix_purge
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6f0f15bd	rpc_wake_up_next
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6f0fdc51	rpc_get_mount
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x71fa908a	cache_flush
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7275fd05	xdr_encode_array2
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x73dfe9f4	cache_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x76c514c0	svc_sock_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7a4e80e7	rpc_peeraddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7d0f88dd	svc_sock_names
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7dc08974	auth_unix_forget_old
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067	rpc_init_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x85ceb3be	rpc_call_async
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x861e1dd6	xdr_encode_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x861ee641	rpc_exit_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x86ed282a	rpc_uaddr2sockaddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x88129930	sunrpc_cache_update
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8cdec43f	cache_purge
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8d8d7420	put_rpccred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8f0966e6	rpc_max_payload
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8f24b40f	xdr_enter_page
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8ff112d6	svc_xprt_copy_addrs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x905e1b21	auth_domain_find
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x94f3ad58	auth_unix_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9524b4dc	svc_xprt_put
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x969b46f1	svcauth_unix_set_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x97a5bd95	svc_exit_thread
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9865b131	svc_recv
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9919d9ea	svc_max_payload
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9c26dd13	xdr_process_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa0042ba2	svc_destroy
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa07bd31f	auth_unix_add_addr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa3ac1047	xdr_buf_from_iov
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa3f52ef1	rpcauth_destroy_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa3fd7ed9	cache_check
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa46e65bd	xprt_complete_rqst
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa7d50ca6	rpc_put_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xae0e8c00	xprt_wait_for_buffer_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xae80175a	svc_xprt_enqueue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef	nfs_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb019b4ec	rpc_clone_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0ae056a	rpc_call_start
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb0e6bed8	svc_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb1f47437	svc_addsock
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb20a96f3	xprt_set_retrans_timeout_def
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb2f57fd5	rpcauth_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb36439e2	xdr_inline_decode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246	rpc_wake_up_status
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb4f68567	auth_domain_put
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb6278926	sunrpc_cache_unregister_pipefs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb94833c2	xdr_init_decode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xba665213	rpc_restart_call_prepare
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbd2fdd34	sunrpc_cache_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbe1972d7	svc_create_pooled
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbed65da0	rpc_lookup_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96	nfsd_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc0180b55	xdr_skb_read_bits
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc0640f47	svc_prepare_thread
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc0fc7a59	xprt_register_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3	rpc_calc_rto
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc23be090	xprt_update_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc34978cb	svc_xprt_init
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc3880471	xdr_decode_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc392f80f	svc_set_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc5fd31ea	svc_unreg_xprt_class
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc7e2dd77	rpc_wake_up_queued_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc8e96dea	qword_addhex
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc9b7bd11	svc_process
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc9ceffc8	svc_sock_destroy
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xccc2372e	rpc_pton
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcdafc7da	xprt_lookup_rqst
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcee467f3	xprt_load_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcef25c60	rpc_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd30d8528	rpcauth_generic_bind_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd353480f	svc_set_num_threads
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e	rpc_init_wait_queue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xda7e8051	rpcauth_init_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdad0d38f	svc_xprt_received
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdc8ffa44	xprt_reserve_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdd3a7b5c	xdr_write_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdd49467d	rpc_peeraddr2str
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xddf6794b	rpc_shutdown_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xde2712e1	svc_authenticate
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xde637c5a	read_bytes_from_xdr_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdf77c98c	svc_proc_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe00e99d9	svc_sock_update_bufs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe3e75245	svc_seq_show
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe3ef2e0c	rpc_force_rebind
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe4a78cea	csum_partial_copy_to_xdr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe5227371	xprt_unregister_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe5919cb1	xdr_encode_opaque
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe9082079	xprt_release_xprt_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe94ddef5	xdr_inline_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe97f4ce5	qword_get
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedcf6be4	qword_add
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52	rpc_wake_up
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69	rpc_update_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf15fe1a9	rpc_delay
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf3dae1c8	rpc_queue_upcall
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf4317780	xprt_wake_pending_tasks
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf74979a7	rpcauth_lookup_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c	rpc_free
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9f7bcc3	sunrpc_cache_pipe_upcall
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfb429886	rpcb_getport_async
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x073b942a	cfg80211_wext_siwscan
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x08137654	cfg80211_wext_siwap
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x0d68551c	cfg80211_wext_siwmlme
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x260417e8	cfg80211_wext_siwmode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x27b5d521	cfg80211_wext_giwap
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x2bc8222e	cfg80211_wext_siwencode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x45f0f24d	cfg80211_wext_siwpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x54842053	cfg80211_wext_giwtxpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x5710322e	cfg80211_wext_giwscan
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x5a588654	cfg80211_wext_siwencodeext
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x63fd1e63	cfg80211_wext_siwtxpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x73a928f3	cfg80211_wext_siwretry
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x7c92f0aa	cfg80211_wext_siwessid
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x81122b5d	cfg80211_wext_giwrts
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x825b86b6	cfg80211_wext_siwrate
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x89aaac05	cfg80211_wext_giwfrag
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x8a902c75	cfg80211_wext_giwauth
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x8f375624	cfg80211_wext_giwname
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x9437b3c9	cfg80211_wext_giwessid
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x943dfc42	cfg80211_wext_siwfrag
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x96501919	cfg80211_wext_siwgenie
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x97077c32	cfg80211_wext_siwauth
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x97639332	cfg80211_wext_giwmode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x9b0c6b90	cfg80211_wext_giwretry
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x9f42ed45	cfg80211_wext_siwfreq
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x9fccd6f1	cfg80211_wext_giwrate
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xa152084d	cfg80211_wext_siwrts
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xad55b12e	cfg80211_wext_giwpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xbf02ce55	cfg80211_wext_giwfreq
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xec462108	cfg80211_wireless_stats
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xf60845a7	cfg80211_wext_giwrange
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xff9bb78f	cfg80211_wext_giwencode
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xa924ea22	ipcomp_input
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xabed124d	ipcomp_destroy
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xc71531e9	ipcomp_output
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xcdb14365	ipcomp_init_state
+EXPORT_SYMBOL_GPL sound/core/snd-pcm 0xa286a234	snd_pcm_format_name
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x0b5a437e	snd_hda_codec_cleanup_stream
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x0df7cd76	snd_hda_queue_unsol_event
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x11662429	snd_hda_codec_read
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x1fc4ed6a	snd_hda_mixer_bind_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x22b25d7a	snd_hda_create_spdif_out_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x241ad341	snd_hda_query_pin_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x2c3010e7	snd_hda_parse_pin_def_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x31df168b	snd_hda_mixer_bind_switch_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x32f18cfe	snd_hda_suspend
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x34e4b81b	snd_hda_mixer_amp_switch_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x37f0dd64	snd_hda_bus_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x39b83a24	snd_hda_find_mixer_ctl
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x3c40ff80	snd_hda_add_vmaster
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x3db6dd17	snd_hda_codec_set_pincfg
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x40929b59	snd_hda_codec_amp_read
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4233006e	snd_hda_multi_out_analog_open
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x44a28820	snd_hda_build_controls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x45465740	snd_hda_sequence_write
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x46471194	snd_hda_multi_out_dig_prepare
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4ee6f6b5	snd_hda_ch_mode_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x514130d4	snd_hda_codec_resume_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x52b0d54c	snd_hda_ctl_add
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x578af727	snd_hda_codec_write
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x5ae76f73	auto_pin_cfg_labels
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x5eed7e89	snd_hda_mixer_bind_ctls_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x73a38dc2	snd_hda_mixer_amp_volume_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x76e16d8a	snd_hda_mixer_amp_switch_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x789d57aa	snd_hda_mixer_amp_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x79fb1437	snd_hda_codec_setup_stream
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x7dd5bd67	snd_hda_codec_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x800c0331	snd_hda_bind_sw
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x845c1e73	snd_hda_set_vmaster_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x84e42789	snd_hda_check_board_codec_sid_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9160e023	snd_hda_check_amp_list_power
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x94dd0f3f	snd_hda_create_spdif_share_sw
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x969ed84f	snd_hda_input_mux_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x982e9620	query_amp_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9955d264	snd_hda_power_up
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9a8e1877	snd_array_free
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9d230913	snd_hda_mixer_bind_ctls_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa028efd6	snd_hda_multi_out_dig_close
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa0d77fd9	snd_hda_multi_out_analog_prepare
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa2827d76	snd_hda_get_jack_location
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa6e2df23	snd_hda_multi_out_dig_cleanup
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xab5db013	snd_hda_delete_codec_preset
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xad87613e	snd_print_pcm_rates
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xaebdce10	snd_hda_codec_get_pincfg
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb06dfa58	snd_hda_mixer_amp_volume_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb2b5b622	snd_hda_sequence_write_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb5102416	snd_hda_resume
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb52f1a10	snd_hda_mixer_amp_switch_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb64f83a2	snd_hda_multi_out_analog_cleanup
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xba96f040	snd_hda_check_board_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbbd637a0	snd_hda_add_new_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbe7dd7dc	snd_array_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbf3cd4c4	snd_hda_codec_resume_amp
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc115c18f	snd_hda_bind_vol
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc1b4aad0	snd_hda_codec_amp_update
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc34a54c6	snd_hda_calc_stream_format
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc652fd69	snd_hda_get_jack_connectivity
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcb301b6e	snd_hda_get_jack_type
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcb7f84bc	snd_hda_multi_out_dig_open
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcc989778	snd_hda_codec_configure
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcce27eb0	snd_hda_input_mux_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcd8abced	snd_hda_build_pcms
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xd0ab6e81	snd_hda_codec_write_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xd0ac446b	snd_hda_ch_mode_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xd2c90eaf	snd_hda_add_codec_preset
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xd7c0d241	snd_hda_power_down
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xda1842e6	snd_hda_get_connections
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xde115057	snd_hda_create_spdif_in_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xdf26dc82	snd_hda_mixer_bind_ctls_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xe0bfaadf	snd_hda_is_supported_format
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xe13e6b14	snd_hda_ch_mode_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xe5ecf9e9	snd_hda_override_amp_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xeda3a721	snd_print_pcm_bits
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xf2116111	snd_hda_mixer_bind_switch_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xf2682fc9	snd_hda_mixer_amp_volume_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xf2a2cce8	snd_hda_codec_amp_stereo
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xfa987571	snd_hda_get_sub_nodes
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0014aa86	snd_soc_info_enum_ext
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x04a3ca55	snd_soc_get_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0a9ca5b8	snd_soc_put_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1223f726	snd_soc_dai_set_sysclk
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x13acfd37	snd_soc_dapm_get_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1bf5a281	snd_soc_info_volsw_ext
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1cf4e224	snd_soc_dapm_get_pin_status
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1d9392da	snd_soc_dapm_put_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1ea67d4c	snd_soc_register_dais
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x22079f63	snd_soc_dapm_get_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x25093107	snd_soc_dapm_get_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x265edd3a	snd_soc_put_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x304e945a	snd_soc_resume_device
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x312fd03f	snd_soc_info_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3169b25e	snd_soc_dapm_put_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x34473069	snd_soc_info_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3530f007	snd_soc_get_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x398762bf	snd_soc_dai_set_clkdiv
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x3affe2dd	dapm_reg_event
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x401d04bf	snd_soc_dapm_put_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x40c70a66	snd_soc_unregister_dai
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4a860299	snd_soc_register_platform
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4c9e44b8	snd_soc_dapm_new_controls
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4cbbce8a	snd_soc_dapm_nc_pin
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5562621e	snd_soc_free_ac97_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5c3b2f48	snd_soc_new_pcms
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6060109a	snd_soc_dapm_new_widgets
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6093824e	snd_soc_register_dai
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x616fdd2b	snd_soc_jack_free_gpios
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6601a6a3	snd_soc_dai_digital_mute
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6e61c727	snd_soc_dapm_free
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6ff3ab85	snd_soc_dapm_get_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x70c4efb6	snd_soc_init_card
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x79c168d7	snd_soc_update_bits
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x7a669d23	snd_soc_jack_report
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x81331ba7	snd_soc_codec_volatile_register
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8170589f	snd_soc_unregister_dais
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x83f16f54	snd_soc_free_pcms
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x89d84d0b	snd_soc_dapm_info_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8b14748d	snd_soc_dapm_put_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8c00a436	snd_soc_new_ac97_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8c64da05	snd_soc_info_volsw_2r
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x920b5e66	snd_soc_test_bits
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x959abf99	snd_soc_jack_add_gpios
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x96197612	snd_soc_dai_set_pll
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x96abcb03	snd_soc_get_volsw_2r
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x97982c22	snd_soc_register_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x9be00e89	snd_soc_dapm_add_routes
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa0e02118	snd_soc_dapm_new_control
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa1b17c9c	snd_soc_put_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa6e2e78a	snd_soc_dapm_stream_event
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xabc3be23	snd_soc_set_runtime_hwparams
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb3bd8919	snd_soc_jack_new
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xb9cf8fc7	snd_soc_put_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xbbb7b293	snd_soc_codec_set_cache_io
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc07e3a80	snd_soc_info_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc8085f60	snd_soc_dai_set_fmt
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xcd187c6b	snd_soc_jack_add_pins
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xce05667b	snd_soc_cnew
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd217c59a	snd_soc_get_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd550274a	snd_soc_unregister_platform
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd91ad95c	snd_soc_suspend_device
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xda03c045	snd_soc_dai_set_tdm_slot
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdcdbba7f	snd_soc_get_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xde068a56	snd_soc_dai_set_tristate
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe50d7205	snd_soc_put_volsw_2r
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf35ce495	snd_soc_dapm_disable_pin
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf3e9c208	snd_soc_dapm_sync
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf5cffdec	snd_soc_add_controls
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf8815953	snd_soc_unregister_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfac4f5be	snd_soc_dapm_enable_pin
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x2e0a0be5	xv_destroy_pool
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x51958fac	xv_malloc
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x7e80b9f6	xv_create_pool
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x9a79aa81	xv_free
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0xaf69699e	xv_get_object_size
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0xc1f55d16	xv_get_total_size_bytes
+EXPORT_SYMBOL_GPL vmlinux 0x003f052f	spi_write_then_read
+EXPORT_SYMBOL_GPL vmlinux 0x00566d8f	inotify_get_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x006a3cef	rt_mutex_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x00901435	rtc_irq_set_state
+EXPORT_SYMBOL_GPL vmlinux 0x010b180b	crypto_alg_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x016b9869	xfrm_calg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0x016f9214	anon_inode_getfd
+EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d	unregister_die_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x01c4b5c6	class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x021ef314	__lock_page_killable
+EXPORT_SYMBOL_GPL vmlinux 0x027d3d74	trace_define_field
+EXPORT_SYMBOL_GPL vmlinux 0x02ae9f45	get_device
+EXPORT_SYMBOL_GPL vmlinux 0x031f1cb1	led_trigger_register
+EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1	__i2c_board_list
+EXPORT_SYMBOL_GPL vmlinux 0x037ceb83	mnt_clone_write
+EXPORT_SYMBOL_GPL vmlinux 0x03820e73	blk_execute_rq_nowait
+EXPORT_SYMBOL_GPL vmlinux 0x03bc864f	bind_virq_to_irqaction
+EXPORT_SYMBOL_GPL vmlinux 0x04069b1d	set_irq_nested_thread
+EXPORT_SYMBOL_GPL vmlinux 0x0417fbbb	device_remove_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x04486e88	rcu_batches_completed
+EXPORT_SYMBOL_GPL vmlinux 0x047c0e8e	__inet_twsk_hashdance
+EXPORT_SYMBOL_GPL vmlinux 0x04a6371d	power_supply_get_by_name
+EXPORT_SYMBOL_GPL vmlinux 0x04c3f2c1	gnttab_empty_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0x04ef0986	w1_touch_block
+EXPORT_SYMBOL_GPL vmlinux 0x054e550b	kernel_halt
+EXPORT_SYMBOL_GPL vmlinux 0x05984b11	spi_register_master
+EXPORT_SYMBOL_GPL vmlinux 0x05c88348	crypto_init_ahash_spawn
+EXPORT_SYMBOL_GPL vmlinux 0x060d1064	set_memory_ro
+EXPORT_SYMBOL_GPL vmlinux 0x0619ca8a	getboottime
+EXPORT_SYMBOL_GPL vmlinux 0x064db9a5	mark_mounts_for_expiry
+EXPORT_SYMBOL_GPL vmlinux 0x06d3903e	kmem_cache_name
+EXPORT_SYMBOL_GPL vmlinux 0x076ab8bb	crypto_ablkcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0x07a7e704	single_open_net
+EXPORT_SYMBOL_GPL vmlinux 0x07b52e38	rtnl_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x07ce7344	trace_seq_vprintf
+EXPORT_SYMBOL_GPL vmlinux 0x07ff4aea	xenbus_scanf
+EXPORT_SYMBOL_GPL vmlinux 0x0812b5a0	tcp_set_state
+EXPORT_SYMBOL_GPL vmlinux 0x0825dd9b	w1_reset_bus
+EXPORT_SYMBOL_GPL vmlinux 0x082ef9de	blk_trace_remove
+EXPORT_SYMBOL_GPL vmlinux 0x0864c4a4	dlm_new_lockspace
+EXPORT_SYMBOL_GPL vmlinux 0x0905b85a	inet_csk_route_req
+EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4	round_jiffies
+EXPORT_SYMBOL_GPL vmlinux 0x09598f02	kick_process
+EXPORT_SYMBOL_GPL vmlinux 0x0960c638	register_kretprobe
+EXPORT_SYMBOL_GPL vmlinux 0x09aaf004	transport_configure_device
+EXPORT_SYMBOL_GPL vmlinux 0x09bcad41	device_reprobe
+EXPORT_SYMBOL_GPL vmlinux 0x09cef910	rtnl_link_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x0a201d85	key_type_user
+EXPORT_SYMBOL_GPL vmlinux 0x0a9a8577	hwmon_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x0abc0ad4	security_inode_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0x0afa62c5	class_find_device
+EXPORT_SYMBOL_GPL vmlinux 0x0b07abe2	unshare_fs_struct
+EXPORT_SYMBOL_GPL vmlinux 0x0b5baac4	tcp_twsk_destructor
+EXPORT_SYMBOL_GPL vmlinux 0x0b89cd2b	devm_kzalloc
+EXPORT_SYMBOL_GPL vmlinux 0x0b97f849	dm_get_rq_mapinfo
+EXPORT_SYMBOL_GPL vmlinux 0x0be61734	rt_mutex_lock
+EXPORT_SYMBOL_GPL vmlinux 0x0c2cdbf1	synchronize_sched
+EXPORT_SYMBOL_GPL vmlinux 0x0c48fe95	net_accel_xen_net_read_mac
+EXPORT_SYMBOL_GPL vmlinux 0x0c4d3bdf	inet_twsk_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x0c805f93	clflush_cache_range
+EXPORT_SYMBOL_GPL vmlinux 0x0cb88680	__tracepoint_block_rq_remap
+EXPORT_SYMBOL_GPL vmlinux 0x0cc26f99	crypto_register_alg
+EXPORT_SYMBOL_GPL vmlinux 0x0cd10b73	exportfs_encode_fh
+EXPORT_SYMBOL_GPL vmlinux 0x0d19ec24	rtc_irq_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x0d1a2e3d	blk_trace_setup
+EXPORT_SYMBOL_GPL vmlinux 0x0d644c56	bus_register
+EXPORT_SYMBOL_GPL vmlinux 0x0d7c576a	swiotlb_sync_single_range_for_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x0deb0ade	register_timer_hook
+EXPORT_SYMBOL_GPL vmlinux 0x0e39b869	skcipher_geniv_exit
+EXPORT_SYMBOL_GPL vmlinux 0x0e3e4366	relay_open
+EXPORT_SYMBOL_GPL vmlinux 0x0e44a6b6	netlink_has_listeners
+EXPORT_SYMBOL_GPL vmlinux 0x0e501091	input_ff_create
+EXPORT_SYMBOL_GPL vmlinux 0x0e80ca59	__xenbus_register_frontend
+EXPORT_SYMBOL_GPL vmlinux 0x0f077bc3	dlm_posix_lock
+EXPORT_SYMBOL_GPL vmlinux 0x0f73520f	klist_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x0f8fe2dd	sysfs_get
+EXPORT_SYMBOL_GPL vmlinux 0x0fba5d81	blkcipher_walk_done
+EXPORT_SYMBOL_GPL vmlinux 0x0fe2d570	xenbus_directory
+EXPORT_SYMBOL_GPL vmlinux 0x0ffd74c9	ring_buffer_read
+EXPORT_SYMBOL_GPL vmlinux 0x10138352	tracing_on
+EXPORT_SYMBOL_GPL vmlinux 0x101c923e	__tracepoint_power_start
+EXPORT_SYMBOL_GPL vmlinux 0x1036780c	disk_part_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x109d0cc5	tty_ldisc_ref
+EXPORT_SYMBOL_GPL vmlinux 0x10af2d98	rt_mutex_unlock
+EXPORT_SYMBOL_GPL vmlinux 0x11007e38	remove_xen_proc_entry
+EXPORT_SYMBOL_GPL vmlinux 0x11583589	sysfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x116ded40	device_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x11ae5828	platform_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0x11bb257a	crypto_rng_type
+EXPORT_SYMBOL_GPL vmlinux 0x11f447ce	__gpio_to_irq
+EXPORT_SYMBOL_GPL vmlinux 0x1229f894	nf_unregister_queue_handlers
+EXPORT_SYMBOL_GPL vmlinux 0x12387658	bus_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x12446d89	fs_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x124f2056	crypto_get_attr_type
+EXPORT_SYMBOL_GPL vmlinux 0x1251d30f	call_rcu
+EXPORT_SYMBOL_GPL vmlinux 0x125a23f6	fsstack_copy_inode_size
+EXPORT_SYMBOL_GPL vmlinux 0x1268f357	resume_device_irqs
+EXPORT_SYMBOL_GPL vmlinux 0x1295bf31	ring_buffer_normalize_time_stamp
+EXPORT_SYMBOL_GPL vmlinux 0x136d57ed	tracepoint_iter_reset
+EXPORT_SYMBOL_GPL vmlinux 0x1376221d	crypto_create_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x13b2a946	register_keyboard_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x14187411	__set_irq_handler
+EXPORT_SYMBOL_GPL vmlinux 0x14269e27	sysfs_create_link
+EXPORT_SYMBOL_GPL vmlinux 0x14335f29	net_accel_msg_peek
+EXPORT_SYMBOL_GPL vmlinux 0x1435483e	tracepoint_iter_stop
+EXPORT_SYMBOL_GPL vmlinux 0x143b707c	unregister_net_sysctl_table
+EXPORT_SYMBOL_GPL vmlinux 0x149db923	selinux_string_to_sid
+EXPORT_SYMBOL_GPL vmlinux 0x14a866cb	skcipher_geniv_init
+EXPORT_SYMBOL_GPL vmlinux 0x14ce4100	rt_mutex_trylock
+EXPORT_SYMBOL_GPL vmlinux 0x14f2dd1f	ring_buffer_reset
+EXPORT_SYMBOL_GPL vmlinux 0x1505c1f7	dm_kill_unmapped_request
+EXPORT_SYMBOL_GPL vmlinux 0x15568631	lookup_address
+EXPORT_SYMBOL_GPL vmlinux 0x15714570	setup_irq
+EXPORT_SYMBOL_GPL vmlinux 0x15892417	async_synchronize_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x158c0c75	device_create_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d	unregister_netevent_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x15abce39	relay_file_operations
+EXPORT_SYMBOL_GPL vmlinux 0x15b0606e	e820_any_mapped
+EXPORT_SYMBOL_GPL vmlinux 0x15d8d6e7	pciserial_resume_ports
+EXPORT_SYMBOL_GPL vmlinux 0x16621cb1	sg_scsi_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0x1686bbcd	ring_buffer_read_page
+EXPORT_SYMBOL_GPL vmlinux 0x16c57b0c	unregister_jprobes
+EXPORT_SYMBOL_GPL vmlinux 0x16e6277d	device_for_each_child
+EXPORT_SYMBOL_GPL vmlinux 0x16f76869	probe_kernel_read
+EXPORT_SYMBOL_GPL vmlinux 0x171b577b	unregister_kprobes
+EXPORT_SYMBOL_GPL vmlinux 0x172b6690	cuckoo_hash_init
+EXPORT_SYMBOL_GPL vmlinux 0x172e72d4	vdso_enabled
+EXPORT_SYMBOL_GPL vmlinux 0x17bcf546	kernel_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x17dae83a	transport_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x17f41ccf	tty_mode_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0x18006815	pci_stop_bus_device
+EXPORT_SYMBOL_GPL vmlinux 0x186d31c4	xen_limit_pages_to_max_mfn
+EXPORT_SYMBOL_GPL vmlinux 0x1878f62b	edac_err_assert
+EXPORT_SYMBOL_GPL vmlinux 0x18b395c7	net_accel_map_device_page
+EXPORT_SYMBOL_GPL vmlinux 0x18f83fab	gnttab_grant_foreign_access_ref
+EXPORT_SYMBOL_GPL vmlinux 0x1a322649	pci_find_next_capability
+EXPORT_SYMBOL_GPL vmlinux 0x1a323362	__ftrace_vbprintk
+EXPORT_SYMBOL_GPL vmlinux 0x1a474901	tracepoint_probe_unregister_noupdate
+EXPORT_SYMBOL_GPL vmlinux 0x1a659d70	inet_hash_connect
+EXPORT_SYMBOL_GPL vmlinux 0x1a89e9cc	xenbus_free_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0x1a938737	atomic_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x1aaa771a	inotify_find_update_watch
+EXPORT_SYMBOL_GPL vmlinux 0x1abc877c	blk_lld_busy
+EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2	atomic_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x1acf5230	tty_ldisc_deref
+EXPORT_SYMBOL_GPL vmlinux 0x1aed763e	sysdev_class_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f	jprobe_return
+EXPORT_SYMBOL_GPL vmlinux 0x1be08f4f	crypto_dequeue_request
+EXPORT_SYMBOL_GPL vmlinux 0x1c4f3b96	debugfs_create_u16
+EXPORT_SYMBOL_GPL vmlinux 0x1c7b6c2a	eventfd_ctx_fdget
+EXPORT_SYMBOL_GPL vmlinux 0x1c852e7c	xfrm_calg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x1c87a811	__round_jiffies_up
+EXPORT_SYMBOL_GPL vmlinux 0x1cd81589	driver_find
+EXPORT_SYMBOL_GPL vmlinux 0x1ce0d57d	user_match
+EXPORT_SYMBOL_GPL vmlinux 0x1d2648ed	pciserial_suspend_ports
+EXPORT_SYMBOL_GPL vmlinux 0x1d47fcba	raw_unhash_sk
+EXPORT_SYMBOL_GPL vmlinux 0x1d7121c1	file_ra_state_init
+EXPORT_SYMBOL_GPL vmlinux 0x1d8f8059	__tracepoint_power_end
+EXPORT_SYMBOL_GPL vmlinux 0x1da5551e	nf_unregister_afinfo
+EXPORT_SYMBOL_GPL vmlinux 0x1db21d74	__tracepoint_kfree_skb
+EXPORT_SYMBOL_GPL vmlinux 0x1dee2629	trace_current_buffer_lock_reserve
+EXPORT_SYMBOL_GPL vmlinux 0x1df04e97	sysdev_store_ulong
+EXPORT_SYMBOL_GPL vmlinux 0x1e203db6	transport_setup_device
+EXPORT_SYMBOL_GPL vmlinux 0x1e7177c9	__audit_inode_child
+EXPORT_SYMBOL_GPL vmlinux 0x1e784a91	blk_rq_unprep_clone
+EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3	kernel_restart
+EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e	round_jiffies_relative
+EXPORT_SYMBOL_GPL vmlinux 0x1eba269f	relay_reset
+EXPORT_SYMBOL_GPL vmlinux 0x1ebf6c2a	pci_power_names
+EXPORT_SYMBOL_GPL vmlinux 0x1eea651e	driver_register
+EXPORT_SYMBOL_GPL vmlinux 0x1efda0eb	ring_buffer_peek
+EXPORT_SYMBOL_GPL vmlinux 0x1f346d34	bind_interdomain_evtchn_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x1f3d1b77	crypto_alg_sem
+EXPORT_SYMBOL_GPL vmlinux 0x1f431edc	tcp_reno_ssthresh
+EXPORT_SYMBOL_GPL vmlinux 0x1f51910e	proc_net_remove
+EXPORT_SYMBOL_GPL vmlinux 0x1f6346be	hypervisor_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x1f732e7d	free_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x1fcece42	inet_twdr_twcal_tick
+EXPORT_SYMBOL_GPL vmlinux 0x201b5258	xfrm_audit_state_replay_overflow
+EXPORT_SYMBOL_GPL vmlinux 0x205dcd7a	klist_add_tail
+EXPORT_SYMBOL_GPL vmlinux 0x20bc3470	orderly_poweroff
+EXPORT_SYMBOL_GPL vmlinux 0x20c0da95	crypto_hash_walk_first
+EXPORT_SYMBOL_GPL vmlinux 0x215db6e9	tracepoint_probe_register_noupdate
+EXPORT_SYMBOL_GPL vmlinux 0x2187d940	inet6_lookup_listener
+EXPORT_SYMBOL_GPL vmlinux 0x21c99e94	tcp_reno_cong_avoid
+EXPORT_SYMBOL_GPL vmlinux 0x2237614e	mnt_want_write_file
+EXPORT_SYMBOL_GPL vmlinux 0x223cc009	class_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x22762935	tty_init_termios
+EXPORT_SYMBOL_GPL vmlinux 0x2296c00d	crypto_attr_u32
+EXPORT_SYMBOL_GPL vmlinux 0x22abf2f4	fib_rules_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x231d4197	generic_fh_to_parent
+EXPORT_SYMBOL_GPL vmlinux 0x23679939	__iowrite32_copy
+EXPORT_SYMBOL_GPL vmlinux 0x23864ce7	cpuset_mem_spread_node
+EXPORT_SYMBOL_GPL vmlinux 0x23869dc7	cancel_work_sync
+EXPORT_SYMBOL_GPL vmlinux 0x2447533c	ktime_get_real
+EXPORT_SYMBOL_GPL vmlinux 0x24c7698a	xenbus_write
+EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32	leds_list
+EXPORT_SYMBOL_GPL vmlinux 0x24f71e95	dlm_posix_get
+EXPORT_SYMBOL_GPL vmlinux 0x251d5c87	relay_flush
+EXPORT_SYMBOL_GPL vmlinux 0x25f2d8ca	vfs_listxattr
+EXPORT_SYMBOL_GPL vmlinux 0x26024603	devres_open_group
+EXPORT_SYMBOL_GPL vmlinux 0x26151340	ring_buffer_iter_empty
+EXPORT_SYMBOL_GPL vmlinux 0x2641906c	hrtimer_get_remaining
+EXPORT_SYMBOL_GPL vmlinux 0x264e742a	drop_file_write_access
+EXPORT_SYMBOL_GPL vmlinux 0x2672e17d	dm_device_name
+EXPORT_SYMBOL_GPL vmlinux 0x268d20ae	bind_listening_port_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x26e4e4bf	net_accel_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0x2787db00	vbin_printf
+EXPORT_SYMBOL_GPL vmlinux 0x27a8d6ee	sysfs_get_dirent
+EXPORT_SYMBOL_GPL vmlinux 0x27adf232	tracing_generic_entry_update
+EXPORT_SYMBOL_GPL vmlinux 0x27fdd3e4	inet_hashinfo_init
+EXPORT_SYMBOL_GPL vmlinux 0x288de21c	iomap_atomic_prot_pfn
+EXPORT_SYMBOL_GPL vmlinux 0x28b9a0c5	device_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x28d178f1	crypto_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x28d664ff	__raw_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x28e23139	xfrm_probe_algs
+EXPORT_SYMBOL_GPL vmlinux 0x294283ba	tty_ldisc_ref_wait
+EXPORT_SYMBOL_GPL vmlinux 0x29501527	klist_iter_init_node
+EXPORT_SYMBOL_GPL vmlinux 0x2960ca0f	unmask_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0x29c35841	platform_bus
+EXPORT_SYMBOL_GPL vmlinux 0x2a678a13	__suspend_report_result
+EXPORT_SYMBOL_GPL vmlinux 0x2b161cce	bdi_writeout_inc
+EXPORT_SYMBOL_GPL vmlinux 0x2b443eca	crypto_register_shash
+EXPORT_SYMBOL_GPL vmlinux 0x2b47cde8	cuckoo_hash_remove
+EXPORT_SYMBOL_GPL vmlinux 0x2b52d62e	ring_buffer_overrun_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x2b6f6c5b	k_handler
+EXPORT_SYMBOL_GPL vmlinux 0x2b7e0e7e	__trace_note_message
+EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23	nf_net_ipv4_netfilter_sysctl_path
+EXPORT_SYMBOL_GPL vmlinux 0x2bc504c3	blk_insert_cloned_request
+EXPORT_SYMBOL_GPL vmlinux 0x2be7fb8e	disable_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x2bfc4d7f	tracepoint_get_iter_range
+EXPORT_SYMBOL_GPL vmlinux 0x2c0d820b	rtc_class_close
+EXPORT_SYMBOL_GPL vmlinux 0x2c208607	power_supply_is_system_supplied
+EXPORT_SYMBOL_GPL vmlinux 0x2c5b92b6	input_ff_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x2c6a008a	hrtimer_start_range_ns
+EXPORT_SYMBOL_GPL vmlinux 0x2cb6f1d6	xen_invlpg_mask
+EXPORT_SYMBOL_GPL vmlinux 0x2cb8c570	br_fdb_test_addr_hook
+EXPORT_SYMBOL_GPL vmlinux 0x2cd0d974	ring_buffer_read_finish
+EXPORT_SYMBOL_GPL vmlinux 0x2ce98559	kcrypto_wq
+EXPORT_SYMBOL_GPL vmlinux 0x2d08bf34	platform_device_add_resources
+EXPORT_SYMBOL_GPL vmlinux 0x2d14c020	cuckoo_hash_add_check
+EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3	sched_clock_idle_wakeup_event
+EXPORT_SYMBOL_GPL vmlinux 0x2dd8444c	trace_seq_printf
+EXPORT_SYMBOL_GPL vmlinux 0x2e47f677	xfrm_aalg_get_byidx
+EXPORT_SYMBOL_GPL vmlinux 0x2e4e8667	inotify_rm_watch
+EXPORT_SYMBOL_GPL vmlinux 0x2e641268	led_trigger_remove
+EXPORT_SYMBOL_GPL vmlinux 0x2e773ae0	d_materialise_unique
+EXPORT_SYMBOL_GPL vmlinux 0x2e782568	power_supply_am_i_supplied
+EXPORT_SYMBOL_GPL vmlinux 0x2e81a831	init_user_ns
+EXPORT_SYMBOL_GPL vmlinux 0x2e97a619	__sock_recv_timestamp
+EXPORT_SYMBOL_GPL vmlinux 0x2ed28931	gpiochip_add
+EXPORT_SYMBOL_GPL vmlinux 0x2ed7ab89	rtc_read_time
+EXPORT_SYMBOL_GPL vmlinux 0x2ee3e269	bus_find_device_by_name
+EXPORT_SYMBOL_GPL vmlinux 0x2efc619d	dm_path_uevent
+EXPORT_SYMBOL_GPL vmlinux 0x2f13264e	filter_current_check_discard
+EXPORT_SYMBOL_GPL vmlinux 0x2f2724bc	screen_glyph
+EXPORT_SYMBOL_GPL vmlinux 0x2f8d2218	crypto_tfm_in_queue
+EXPORT_SYMBOL_GPL vmlinux 0x2faa780f	crypto_ahash_setkey
+EXPORT_SYMBOL_GPL vmlinux 0x2fcd9e17	dpm_resume_noirq
+EXPORT_SYMBOL_GPL vmlinux 0x2fdc36b1	raw_seq_open
+EXPORT_SYMBOL_GPL vmlinux 0x3033b01f	unregister_kretprobe
+EXPORT_SYMBOL_GPL vmlinux 0x30a4f4ca	bstr_printf
+EXPORT_SYMBOL_GPL vmlinux 0x30b869c9	w1_read_8
+EXPORT_SYMBOL_GPL vmlinux 0x31a8fd0b	crypto_larval_kill
+EXPORT_SYMBOL_GPL vmlinux 0x3244a0f7	invalidate_inode_pages2_range
+EXPORT_SYMBOL_GPL vmlinux 0x32551ad7	seq_release_net
+EXPORT_SYMBOL_GPL vmlinux 0x325e677c	gnttab_grant_foreign_transfer_ref
+EXPORT_SYMBOL_GPL vmlinux 0x32924a4d	scatterwalk_copychunks
+EXPORT_SYMBOL_GPL vmlinux 0x329c85ea	cuckoo_hash_update
+EXPORT_SYMBOL_GPL vmlinux 0x32d5e7fc	xfrm_aalg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x32f17454	ring_buffer_event_data
+EXPORT_SYMBOL_GPL vmlinux 0x3319c8ef	unregister_pernet_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x33429d1a	ahash_free_instance
+EXPORT_SYMBOL_GPL vmlinux 0x33609ec8	shash_attr_alg
+EXPORT_SYMBOL_GPL vmlinux 0x33785e32	net_accel_msg_recv_next
+EXPORT_SYMBOL_GPL vmlinux 0x33794ad4	led_trigger_unregister_simple
+EXPORT_SYMBOL_GPL vmlinux 0x34275124	trace_current_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0x342881d8	device_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6	gpio_set_value_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x34498714	__inet_lookup_listener
+EXPORT_SYMBOL_GPL vmlinux 0x346d4073	inet6_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x3472cba1	device_register
+EXPORT_SYMBOL_GPL vmlinux 0x34992ca9	kobject_create_and_add
+EXPORT_SYMBOL_GPL vmlinux 0x34d91d10	pci_destroy_slot
+EXPORT_SYMBOL_GPL vmlinux 0x34f6da60	debugfs_remove_recursive
+EXPORT_SYMBOL_GPL vmlinux 0x352ea1af	debugfs_create_symlink
+EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc	save_stack_trace
+EXPORT_SYMBOL_GPL vmlinux 0x362e23ec	call_rcu_bh
+EXPORT_SYMBOL_GPL vmlinux 0x3667d379	tty_prepare_flip_string_flags
+EXPORT_SYMBOL_GPL vmlinux 0x37ad4176	__tracepoint_block_bio_complete
+EXPORT_SYMBOL_GPL vmlinux 0x37c8068f	sysdev_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x381af84f	pci_block_user_cfg_access
+EXPORT_SYMBOL_GPL vmlinux 0x3837b3bd	bus_for_each_dev
+EXPORT_SYMBOL_GPL vmlinux 0x3841ab01	unregister_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x38556f06	led_trigger_store
+EXPORT_SYMBOL_GPL vmlinux 0x38a9c2c7	input_ff_effect_from_user
+EXPORT_SYMBOL_GPL vmlinux 0x38de98ef	ring_buffer_record_disable
+EXPORT_SYMBOL_GPL vmlinux 0x3911f994	inverse_translate
+EXPORT_SYMBOL_GPL vmlinux 0x39405d4f	sk_setup_caps
+EXPORT_SYMBOL_GPL vmlinux 0x39df419d	platform_device_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x3a235881	crypto_alloc_ablkcipher
+EXPORT_SYMBOL_GPL vmlinux 0x3a4900a8	inotify_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x3a6453fd	xenbus_switch_state
+EXPORT_SYMBOL_GPL vmlinux 0x3ae35ad5	gnttab_end_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0x3b0cd6e5	platform_add_devices
+EXPORT_SYMBOL_GPL vmlinux 0x3b28b6be	led_trigger_register_simple
+EXPORT_SYMBOL_GPL vmlinux 0x3b6b96e5	crypto_givcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0x3b98e995	shash_ahash_update
+EXPORT_SYMBOL_GPL vmlinux 0x3bdf5f07	hrtimer_init
+EXPORT_SYMBOL_GPL vmlinux 0x3be7af02	get_max_files
+EXPORT_SYMBOL_GPL vmlinux 0x3bf1cc40	driver_find_device
+EXPORT_SYMBOL_GPL vmlinux 0x3c1735d5	find_get_pid
+EXPORT_SYMBOL_GPL vmlinux 0x3c4d8088	pci_rescan_bus
+EXPORT_SYMBOL_GPL vmlinux 0x3c6c45ca	__tracepoint_power_frequency
+EXPORT_SYMBOL_GPL vmlinux 0x3c942368	profile_event_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x3ca628f3	ring_buffer_size
+EXPORT_SYMBOL_GPL vmlinux 0x3cd06035	add_input_randomness
+EXPORT_SYMBOL_GPL vmlinux 0x3cfdfae5	trace_current_buffer_discard_commit
+EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f	register_pm_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x3d0ea15f	security_inode_create
+EXPORT_SYMBOL_GPL vmlinux 0x3d224614	inet_twsk_schedule
+EXPORT_SYMBOL_GPL vmlinux 0x3d388324	dpm_resume_end
+EXPORT_SYMBOL_GPL vmlinux 0x3d45b0ed	inotify_remove_watch_locked
+EXPORT_SYMBOL_GPL vmlinux 0x3d7ea99a	gnttab_grant_foreign_transfer
+EXPORT_SYMBOL_GPL vmlinux 0x3d87f969	nf_register_afinfo
+EXPORT_SYMBOL_GPL vmlinux 0x3dd4d3a7	bprintf
+EXPORT_SYMBOL_GPL vmlinux 0x3dd5d829	add_timer_on
+EXPORT_SYMBOL_GPL vmlinux 0x3dde0e07	amd_get_nb_id
+EXPORT_SYMBOL_GPL vmlinux 0x3df739c3	hrtimer_try_to_cancel
+EXPORT_SYMBOL_GPL vmlinux 0x3e12968d	debugfs_rename
+EXPORT_SYMBOL_GPL vmlinux 0x3e3bea89	sysdev_show_int
+EXPORT_SYMBOL_GPL vmlinux 0x3e9df189	fb_deferred_io_open
+EXPORT_SYMBOL_GPL vmlinux 0x3eabd844	dm_set_device_limits
+EXPORT_SYMBOL_GPL vmlinux 0x3eba61df	rtc_set_alarm
+EXPORT_SYMBOL_GPL vmlinux 0x3ef10c51	net_accel_msg_init_page
+EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9	get_online_cpus
+EXPORT_SYMBOL_GPL vmlinux 0x3eff454d	get_dcookie
+EXPORT_SYMBOL_GPL vmlinux 0x3f01570a	probe_kernel_write
+EXPORT_SYMBOL_GPL vmlinux 0x3f091ba7	xenbus_dev_error
+EXPORT_SYMBOL_GPL vmlinux 0x3f238101	dcookie_register
+EXPORT_SYMBOL_GPL vmlinux 0x3f5402a6	xfrm_audit_state_icvfail
+EXPORT_SYMBOL_GPL vmlinux 0x3f84d4c9	gnttab_release_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x3f90162a	raw_seq_start
+EXPORT_SYMBOL_GPL vmlinux 0x3fa51a63	ring_buffer_read_start
+EXPORT_SYMBOL_GPL vmlinux 0x400f292e	xfrm_inner_extract_output
+EXPORT_SYMBOL_GPL vmlinux 0x40348e83	rtc_alarm_irq_enable
+EXPORT_SYMBOL_GPL vmlinux 0x40607954	__pci_reset_function
+EXPORT_SYMBOL_GPL vmlinux 0x4091bcbf	netfront_accelerator_stop
+EXPORT_SYMBOL_GPL vmlinux 0x409d060e	crypto_attr_alg2
+EXPORT_SYMBOL_GPL vmlinux 0x40be2c41	blocking_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x40f1b4ea	spi_get_device_id
+EXPORT_SYMBOL_GPL vmlinux 0x4129c17b	__ip_route_output_key
+EXPORT_SYMBOL_GPL vmlinux 0x41da0557	tcp_unregister_congestion_control
+EXPORT_SYMBOL_GPL vmlinux 0x42055c51	crypto_shash_update
+EXPORT_SYMBOL_GPL vmlinux 0x42447a76	skb_morph
+EXPORT_SYMBOL_GPL vmlinux 0x42494cea	ring_buffer_event_length
+EXPORT_SYMBOL_GPL vmlinux 0x424acc6d	scatterwalk_done
+EXPORT_SYMBOL_GPL vmlinux 0x42eee679	stop_machine
+EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6	__gpio_set_value
+EXPORT_SYMBOL_GPL vmlinux 0x434b9644	sysfs_create_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x439375eb	inet_csk_bind_conflict
+EXPORT_SYMBOL_GPL vmlinux 0x43992167	__fsnotify_inode_delete
+EXPORT_SYMBOL_GPL vmlinux 0x43ec355c	device_rename
+EXPORT_SYMBOL_GPL vmlinux 0x43ed2f59	pid_vnr
+EXPORT_SYMBOL_GPL vmlinux 0x441957fb	xfrm_audit_state_delete
+EXPORT_SYMBOL_GPL vmlinux 0x4431c755	dm_send_uevents
+EXPORT_SYMBOL_GPL vmlinux 0x443a6af4	crypto_shash_digest
+EXPORT_SYMBOL_GPL vmlinux 0x4484a5a4	wait_for_device_probe
+EXPORT_SYMBOL_GPL vmlinux 0x4496f1ac	inet_csk_listen_start
+EXPORT_SYMBOL_GPL vmlinux 0x44ce25da	pcie_port_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0x44e35c31	class_compat_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x4507533b	rtc_update_irq
+EXPORT_SYMBOL_GPL vmlinux 0x454d5c01	blocking_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x45565b0a	driver_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x4568e3f1	vfs_getxattr
+EXPORT_SYMBOL_GPL vmlinux 0x457594fa	crypto_alg_list
+EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3	crypto_inc
+EXPORT_SYMBOL_GPL vmlinux 0x45ea83f3	skcipher_geniv_free
+EXPORT_SYMBOL_GPL vmlinux 0x4601bd93	default_backing_dev_info
+EXPORT_SYMBOL_GPL vmlinux 0x460f31aa	rodata_test_data
+EXPORT_SYMBOL_GPL vmlinux 0x4672e88b	__crypto_dequeue_request
+EXPORT_SYMBOL_GPL vmlinux 0x4695c518	w1_write_block
+EXPORT_SYMBOL_GPL vmlinux 0x46a2a001	crypto_init_spawn
+EXPORT_SYMBOL_GPL vmlinux 0x47229b5c	gpio_request
+EXPORT_SYMBOL_GPL vmlinux 0x4731d3f9	platform_device_add_data
+EXPORT_SYMBOL_GPL vmlinux 0x479379ce	xfrm_audit_state_notfound_simple
+EXPORT_SYMBOL_GPL vmlinux 0x47a8852e	crypto_larval_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x47b601bc	ring_buffer_lock_reserve
+EXPORT_SYMBOL_GPL vmlinux 0x47e5eba7	rtc_update_irq_enable
+EXPORT_SYMBOL_GPL vmlinux 0x48922abe	get_xen_class
+EXPORT_SYMBOL_GPL vmlinux 0x48a1bc5c	kset_create_and_add
+EXPORT_SYMBOL_GPL vmlinux 0x48a50a8d	__blk_end_request_err
+EXPORT_SYMBOL_GPL vmlinux 0x49136c4c	__module_text_address
+EXPORT_SYMBOL_GPL vmlinux 0x4933a98e	pci_disable_rom
+EXPORT_SYMBOL_GPL vmlinux 0x49366944	device_move
+EXPORT_SYMBOL_GPL vmlinux 0x496ae8c6	map_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x497f98bb	crypto_alloc_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0x499043d3	crypto_init_queue
+EXPORT_SYMBOL_GPL vmlinux 0x49db8db4	register_jprobes
+EXPORT_SYMBOL_GPL vmlinux 0x4a0bbfaf	ring_buffer_reset_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x4a9dc65b	__rtnl_link_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x4aa0078f	ring_buffer_entries
+EXPORT_SYMBOL_GPL vmlinux 0x4b0cb958	__inet_inherit_port
+EXPORT_SYMBOL_GPL vmlinux 0x4b4f3098	crypto_enqueue_request
+EXPORT_SYMBOL_GPL vmlinux 0x4c15dc24	pci_slots_kset
+EXPORT_SYMBOL_GPL vmlinux 0x4c2fab08	fsnotify
+EXPORT_SYMBOL_GPL vmlinux 0x4c759827	byte_rev_table
+EXPORT_SYMBOL_GPL vmlinux 0x4c7c3866	sysfs_remove_file_from_group
+EXPORT_SYMBOL_GPL vmlinux 0x4cc8ac8c	spi_unregister_master
+EXPORT_SYMBOL_GPL vmlinux 0x4cec82ee	crypto_chain
+EXPORT_SYMBOL_GPL vmlinux 0x4d662cdd	get_cpu_sysdev
+EXPORT_SYMBOL_GPL vmlinux 0x4d8f4c15	klist_add_before
+EXPORT_SYMBOL_GPL vmlinux 0x4db25928	tty_put_char
+EXPORT_SYMBOL_GPL vmlinux 0x4f0d523f	power_supply_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x4f34cbec	xattr_getsecurity
+EXPORT_SYMBOL_GPL vmlinux 0x4f572a8e	net_accel_msg_send
+EXPORT_SYMBOL_GPL vmlinux 0x5086ac3a	alg_test
+EXPORT_SYMBOL_GPL vmlinux 0x50c89f23	__alloc_percpu
+EXPORT_SYMBOL_GPL vmlinux 0x50e553ac	bus_register_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x50e7193a	__i2c_first_dynamic_bus_num
+EXPORT_SYMBOL_GPL vmlinux 0x50f5e532	call_rcu_sched
+EXPORT_SYMBOL_GPL vmlinux 0x50fad434	round_jiffies_up
+EXPORT_SYMBOL_GPL vmlinux 0x51c58466	pci_set_pcie_reset_state
+EXPORT_SYMBOL_GPL vmlinux 0x526bda53	cuckoo_hash_iterate
+EXPORT_SYMBOL_GPL vmlinux 0x52999e16	register_xenbus_watch
+EXPORT_SYMBOL_GPL vmlinux 0x52d0a851	debugfs_create_u32
+EXPORT_SYMBOL_GPL vmlinux 0x52d111ea	pm_qos_update_requirement
+EXPORT_SYMBOL_GPL vmlinux 0x53069a63	input_ff_upload
+EXPORT_SYMBOL_GPL vmlinux 0x530d99e8	save_stack_trace_tsk
+EXPORT_SYMBOL_GPL vmlinux 0x535d4061	class_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x538647e1	set_cpus_allowed_ptr
+EXPORT_SYMBOL_GPL vmlinux 0x53986488	register_die_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x53c12228	rtc_set_time
+EXPORT_SYMBOL_GPL vmlinux 0x53f8dd2f	device_create
+EXPORT_SYMBOL_GPL vmlinux 0x53fdedf9	__rt_mutex_init
+EXPORT_SYMBOL_GPL vmlinux 0x540d5283	net_accel_msg_send_notify
+EXPORT_SYMBOL_GPL vmlinux 0x5417a99d	balloon_update_driver_allowance
+EXPORT_SYMBOL_GPL vmlinux 0x54195500	eventfd_ctx_fileget
+EXPORT_SYMBOL_GPL vmlinux 0x5460c8d8	fsnotify_get_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x549525ef	handle_nested_irq
+EXPORT_SYMBOL_GPL vmlinux 0x54c9fcff	ring_buffer_iter_reset
+EXPORT_SYMBOL_GPL vmlinux 0x550c4228	tty_prepare_flip_string
+EXPORT_SYMBOL_GPL vmlinux 0x551df858	unregister_xenbus_watch
+EXPORT_SYMBOL_GPL vmlinux 0x551ebf1d	dm_dispatch_request
+EXPORT_SYMBOL_GPL vmlinux 0x553885be	sched_setscheduler
+EXPORT_SYMBOL_GPL vmlinux 0x55526907	xen_features
+EXPORT_SYMBOL_GPL vmlinux 0x556ef10c	security_inode_setattr
+EXPORT_SYMBOL_GPL vmlinux 0x56398615	mark_tsc_unstable
+EXPORT_SYMBOL_GPL vmlinux 0x563fb5c8	__trace_bprintk
+EXPORT_SYMBOL_GPL vmlinux 0x5641485b	tty_termios_encode_baud_rate
+EXPORT_SYMBOL_GPL vmlinux 0x566b7cb3	ring_buffer_empty_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x568e55bd	net_accel_msg_reply_notify
+EXPORT_SYMBOL_GPL vmlinux 0x56fb6dc9	register_pernet_device
+EXPORT_SYMBOL_GPL vmlinux 0x575c457a	sysdev_class_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x5779d445	xenbus_exists
+EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5	rtnl_unregister_all
+EXPORT_SYMBOL_GPL vmlinux 0x5900163f	shmem_file_setup
+EXPORT_SYMBOL_GPL vmlinux 0x591d09a2	swiotlb_sync_single_range_for_device
+EXPORT_SYMBOL_GPL vmlinux 0x5955601f	kobject_uevent_env
+EXPORT_SYMBOL_GPL vmlinux 0x59a581fb	sk_clone
+EXPORT_SYMBOL_GPL vmlinux 0x59b5b5a6	crypto_alloc_shash
+EXPORT_SYMBOL_GPL vmlinux 0x59ca3224	inet_twdr_twkill_work
+EXPORT_SYMBOL_GPL vmlinux 0x5a1f2a2d	pci_renumber_slot
+EXPORT_SYMBOL_GPL vmlinux 0x5a2b1b67	gnttab_free_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x5a627fa8	crypto_mod_get
+EXPORT_SYMBOL_GPL vmlinux 0x5a73cb36	transport_remove_device
+EXPORT_SYMBOL_GPL vmlinux 0x5a7bfe41	crypto_probing_notify
+EXPORT_SYMBOL_GPL vmlinux 0x5ae94eab	find_symbol
+EXPORT_SYMBOL_GPL vmlinux 0x5aebca67	tcp_slow_start
+EXPORT_SYMBOL_GPL vmlinux 0x5af03a28	gnttab_claim_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x5af661c8	bus_unregister_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x5b0a124e	tasklet_hrtimer_init
+EXPORT_SYMBOL_GPL vmlinux 0x5b74f70a	get_task_mm
+EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3	unregister_keyboard_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x5c0848bc	find_vpid
+EXPORT_SYMBOL_GPL vmlinux 0x5c5b10da	bd_release_from_disk
+EXPORT_SYMBOL_GPL vmlinux 0x5c720e2f	cuckoo_hash_iterate_reset
+EXPORT_SYMBOL_GPL vmlinux 0x5c72faa5	bus_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x5c85edf5	crypto_ahash_digest
+EXPORT_SYMBOL_GPL vmlinux 0x5cba1a2f	blkcipher_walk_phys
+EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57	kbd_table
+EXPORT_SYMBOL_GPL vmlinux 0x5d2af1b9	crypto_ahash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x5d3e873a	kobject_get_path
+EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b	raw_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x5dd67618	register_netevent_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x5df71a56	platform_get_resource_byname
+EXPORT_SYMBOL_GPL vmlinux 0x5e40e9ad	ip_build_and_send_pkt
+EXPORT_SYMBOL_GPL vmlinux 0x5e559c55	sysfs_notify_dirent
+EXPORT_SYMBOL_GPL vmlinux 0x5f3b28a6	sysfs_remove_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x5fcdec5d	xfrm_ealg_get_byidx
+EXPORT_SYMBOL_GPL vmlinux 0x5ffe9a7b	skb_partial_csum_set
+EXPORT_SYMBOL_GPL vmlinux 0x603ee96b	crypto_mod_put
+EXPORT_SYMBOL_GPL vmlinux 0x60949e1e	srcu_init_notifier_head
+EXPORT_SYMBOL_GPL vmlinux 0x60a13e90	rcu_barrier
+EXPORT_SYMBOL_GPL vmlinux 0x60aff648	queue_work
+EXPORT_SYMBOL_GPL vmlinux 0x60ea39be	xfrm_output
+EXPORT_SYMBOL_GPL vmlinux 0x61053d07	transport_add_device
+EXPORT_SYMBOL_GPL vmlinux 0x61161ed1	pci_hp_create_module_link
+EXPORT_SYMBOL_GPL vmlinux 0x6134dbba	debugfs_create_x8
+EXPORT_SYMBOL_GPL vmlinux 0x61747e09	blocking_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x6197c1d8	pci_unblock_user_cfg_access
+EXPORT_SYMBOL_GPL vmlinux 0x61c0706e	mnt_drop_write
+EXPORT_SYMBOL_GPL vmlinux 0x621c5fe1	exportfs_decode_fh
+EXPORT_SYMBOL_GPL vmlinux 0x629a7f6e	do_posix_clock_nonanosleep
+EXPORT_SYMBOL_GPL vmlinux 0x62ad6a36	ip_route_output_flow
+EXPORT_SYMBOL_GPL vmlinux 0x63cfc049	crypto_grab_skcipher
+EXPORT_SYMBOL_GPL vmlinux 0x63e06743	ring_buffer_write
+EXPORT_SYMBOL_GPL vmlinux 0x63f41ee0	spi_add_device
+EXPORT_SYMBOL_GPL vmlinux 0x654c49e2	aer_irq
+EXPORT_SYMBOL_GPL vmlinux 0x65871268	net_accel_msg_complete_send
+EXPORT_SYMBOL_GPL vmlinux 0x65892b29	led_trigger_set
+EXPORT_SYMBOL_GPL vmlinux 0x65a381d6	blk_end_request_err
+EXPORT_SYMBOL_GPL vmlinux 0x65af76aa	sysfs_notify
+EXPORT_SYMBOL_GPL vmlinux 0x65bbbc78	schedule_hrtimeout_range
+EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0	call_netevent_notifiers
+EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0	gpio_direction_input
+EXPORT_SYMBOL_GPL vmlinux 0x65db5591	init_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0x661601de	sprint_symbol
+EXPORT_SYMBOL_GPL vmlinux 0x665070a6	hrtimer_start
+EXPORT_SYMBOL_GPL vmlinux 0x667a105f	shash_ahash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x668402aa	crypto_put_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x669a9140	pci_bus_max_busnr
+EXPORT_SYMBOL_GPL vmlinux 0x66a5cbdb	ring_buffer_swap_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x66b2a859	nr_free_buffer_pages
+EXPORT_SYMBOL_GPL vmlinux 0x66c4ff25	__mmdrop
+EXPORT_SYMBOL_GPL vmlinux 0x66d87d38	symbol_put_addr
+EXPORT_SYMBOL_GPL vmlinux 0x6709451b	__inet_lookup_established
+EXPORT_SYMBOL_GPL vmlinux 0x67258bc5	aead_geniv_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x675ae3a0	vfs_test_lock
+EXPORT_SYMBOL_GPL vmlinux 0x677a60cb	__pci_complete_power_transition
+EXPORT_SYMBOL_GPL vmlinux 0x67955ce6	profile_hits
+EXPORT_SYMBOL_GPL vmlinux 0x67de59b3	crypto_unregister_template
+EXPORT_SYMBOL_GPL vmlinux 0x67e894b6	shash_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0x6840c127	anon_inode_getfile
+EXPORT_SYMBOL_GPL vmlinux 0x686c703f	xfrm_count_auth_supported
+EXPORT_SYMBOL_GPL vmlinux 0x6886518f	ring_buffer_record_disable_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x6892088c	unregister_pm_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x68bdc318	xenbus_watch_path2
+EXPORT_SYMBOL_GPL vmlinux 0x68e24da4	use_module
+EXPORT_SYMBOL_GPL vmlinux 0x68f936bc	swiotlb_map_page
+EXPORT_SYMBOL_GPL vmlinux 0x6901119a	trace_nowake_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0x6924b9a7	tty_wakeup
+EXPORT_SYMBOL_GPL vmlinux 0x694edf77	debugfs_create_bool
+EXPORT_SYMBOL_GPL vmlinux 0x69be70b2	pci_scan_child_bus
+EXPORT_SYMBOL_GPL vmlinux 0x69dc6d69	cuckoo_hash_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x6a086820	dm_requeue_unmapped_request
+EXPORT_SYMBOL_GPL vmlinux 0x6a620a99	driver_attach
+EXPORT_SYMBOL_GPL vmlinux 0x6b117da1	class_interface_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x6b2a9964	debugfs_create_u8
+EXPORT_SYMBOL_GPL vmlinux 0x6b76283e	sock_prot_inuse_get
+EXPORT_SYMBOL_GPL vmlinux 0x6b94c408	enable_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x6b97a17d	page_cache_sync_readahead
+EXPORT_SYMBOL_GPL vmlinux 0x6bd8817c	crypto_unregister_ahash
+EXPORT_SYMBOL_GPL vmlinux 0x6bd8c93e	do_sync_mapping_range
+EXPORT_SYMBOL_GPL vmlinux 0x6c2deb52	disk_get_part
+EXPORT_SYMBOL_GPL vmlinux 0x6c6755d4	unregister_pernet_gen_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8	__gpio_get_value
+EXPORT_SYMBOL_GPL vmlinux 0x6c8eb98f	xfrm_aalg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0x6cb6d9a1	srcu_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x6d2fc5a6	net_namespace_list
+EXPORT_SYMBOL_GPL vmlinux 0x6d3356db	tcp_get_info
+EXPORT_SYMBOL_GPL vmlinux 0x6d72e259	net_accel_ungrant_page
+EXPORT_SYMBOL_GPL vmlinux 0x6dc6f44a	task_active_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0x6dc99392	sysfs_update_group
+EXPORT_SYMBOL_GPL vmlinux 0x6df9b8d3	__crypto_alloc_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x6e58ddf0	gnttab_end_foreign_transfer_ref
+EXPORT_SYMBOL_GPL vmlinux 0x6e609ab0	ring_buffer_entries_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x6e7474fc	xfrm_ealg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x6e782c23	iomap_create_wc
+EXPORT_SYMBOL_GPL vmlinux 0x6ea8d269	aead_geniv_exit
+EXPORT_SYMBOL_GPL vmlinux 0x6eb787ee	klist_add_head
+EXPORT_SYMBOL_GPL vmlinux 0x6fe3d8cf	ktime_add_safe
+EXPORT_SYMBOL_GPL vmlinux 0x6ff607b6	crypto_get_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x7034a202	ring_buffer_record_enable
+EXPORT_SYMBOL_GPL vmlinux 0x7037d79d	k8_flush_garts
+EXPORT_SYMBOL_GPL vmlinux 0x70397e86	sysdev_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x709908ca	fb_deferred_io_fsync
+EXPORT_SYMBOL_GPL vmlinux 0x70b259e5	register_net_sysctl_table
+EXPORT_SYMBOL_GPL vmlinux 0x70d23a96	part_round_stats
+EXPORT_SYMBOL_GPL vmlinux 0x7157d4df	sysdev_driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x716265c7	debugfs_initialized
+EXPORT_SYMBOL_GPL vmlinux 0x71e2b66d	crypto_register_template
+EXPORT_SYMBOL_GPL vmlinux 0x7206ad80	aead_geniv_free
+EXPORT_SYMBOL_GPL vmlinux 0x72741f25	trace_vbprintk
+EXPORT_SYMBOL_GPL vmlinux 0x7278d328	all_vm_events
+EXPORT_SYMBOL_GPL vmlinux 0x7285f84f	unregister_jprobe
+EXPORT_SYMBOL_GPL vmlinux 0x728f02f8	platform_device_register
+EXPORT_SYMBOL_GPL vmlinux 0x72a05e54	pci_intx
+EXPORT_SYMBOL_GPL vmlinux 0x72b4701e	each_symbol
+EXPORT_SYMBOL_GPL vmlinux 0x72bd2862	crypto_aead_type
+EXPORT_SYMBOL_GPL vmlinux 0x72e03bae	stop_machine_create
+EXPORT_SYMBOL_GPL vmlinux 0x73288b10	blkcipher_walk_virt_block
+EXPORT_SYMBOL_GPL vmlinux 0x733c747f	platform_device_add
+EXPORT_SYMBOL_GPL vmlinux 0x7342f72d	get_driver
+EXPORT_SYMBOL_GPL vmlinux 0x73e960b9	__inet_hash_nolisten
+EXPORT_SYMBOL_GPL vmlinux 0x74578871	xenbus_grant_ring
+EXPORT_SYMBOL_GPL vmlinux 0x74719fb5	ring_buffer_record_enable_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x74abdafa	task_handoff_register
+EXPORT_SYMBOL_GPL vmlinux 0x74baf17a	tracing_is_on
+EXPORT_SYMBOL_GPL vmlinux 0x74db7f7e	device_add
+EXPORT_SYMBOL_GPL vmlinux 0x753ca303	sysfs_remove_group
+EXPORT_SYMBOL_GPL vmlinux 0x75b789fd	pci_disable_pcie_error_reporting
+EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3	crypto_register_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x75f5d271	transport_class_register
+EXPORT_SYMBOL_GPL vmlinux 0x761188fd	dpm_suspend_noirq
+EXPORT_SYMBOL_GPL vmlinux 0x76161916	crypto_alloc_instance2
+EXPORT_SYMBOL_GPL vmlinux 0x766e6285	xfrm_audit_state_add
+EXPORT_SYMBOL_GPL vmlinux 0x77064b80	invalidate_inode_pages2
+EXPORT_SYMBOL_GPL vmlinux 0x7712771a	unbind_from_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x771d3e24	dev_set_name
+EXPORT_SYMBOL_GPL vmlinux 0x7730c98d	gnttab_copy_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0x773ca527	init_uts_ns
+EXPORT_SYMBOL_GPL vmlinux 0x77b9f4f2	spi_alloc_master
+EXPORT_SYMBOL_GPL vmlinux 0x77d5fe3e	pci_find_ext_capability
+EXPORT_SYMBOL_GPL vmlinux 0x77fe2e81	crypto_alloc_instance
+EXPORT_SYMBOL_GPL vmlinux 0x78105c6a	put_pid
+EXPORT_SYMBOL_GPL vmlinux 0x787bc4ab	rt_mutex_timed_lock
+EXPORT_SYMBOL_GPL vmlinux 0x78a8abaa	xenbus_alloc_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0x78e4a4ee	klist_add_after
+EXPORT_SYMBOL_GPL vmlinux 0x7944e0fc	tracing_off
+EXPORT_SYMBOL_GPL vmlinux 0x7961ee0f	debugfs_create_u64
+EXPORT_SYMBOL_GPL vmlinux 0x79900730	root_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x7a5c541a	elv_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x7a88be62	input_ff_event
+EXPORT_SYMBOL_GPL vmlinux 0x7ab3c122	edac_handlers
+EXPORT_SYMBOL_GPL vmlinux 0x7b00bfc4	crypto_alg_mod_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d	edac_handler_set
+EXPORT_SYMBOL_GPL vmlinux 0x7b4b9e19	power_supply_class
+EXPORT_SYMBOL_GPL vmlinux 0x7bcd2ded	klist_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0x7be09794	devres_remove_group
+EXPORT_SYMBOL_GPL vmlinux 0x7c07a414	register_pernet_gen_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x7c2f2afb	w1_calc_crc8
+EXPORT_SYMBOL_GPL vmlinux 0x7c5e214e	blk_abort_request
+EXPORT_SYMBOL_GPL vmlinux 0x7ca59b5f	power_supply_changed
+EXPORT_SYMBOL_GPL vmlinux 0x7cabbc81	mmput
+EXPORT_SYMBOL_GPL vmlinux 0x7cd5af72	register_kretprobes
+EXPORT_SYMBOL_GPL vmlinux 0x7d1feffb	sysfs_schedule_callback
+EXPORT_SYMBOL_GPL vmlinux 0x7d624579	tcp_register_congestion_control
+EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6	crypto_unregister_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x7e1183c9	async_schedule
+EXPORT_SYMBOL_GPL vmlinux 0x7e5f1045	spi_sync
+EXPORT_SYMBOL_GPL vmlinux 0x7e6919a8	class_dev_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x7e9ac335	spi_new_device
+EXPORT_SYMBOL_GPL vmlinux 0x7efda618	rt_mutex_lock_interruptible
+EXPORT_SYMBOL_GPL vmlinux 0x7f33748d	power_supply_set_battery_charged
+EXPORT_SYMBOL_GPL vmlinux 0x7f6480a7	crypto_blkcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0x7f726f39	put_inotify_watch
+EXPORT_SYMBOL_GPL vmlinux 0x7f7bd3e0	srcu_read_unlock
+EXPORT_SYMBOL_GPL vmlinux 0x7fd419c5	__ring_buffer_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x7feaa2bd	dev_change_net_namespace
+EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf	raw_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x8014b6af	input_event_from_user
+EXPORT_SYMBOL_GPL vmlinux 0x8039d043	selinux_secmark_relabel_packet_permission
+EXPORT_SYMBOL_GPL vmlinux 0x808ec1a3	crypto_alg_tested
+EXPORT_SYMBOL_GPL vmlinux 0x80de03bb	ring_buffer_free_read_page
+EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3	selinux_secmark_refcount_inc
+EXPORT_SYMBOL_GPL vmlinux 0x81318ac7	net_accel_msg_start_send
+EXPORT_SYMBOL_GPL vmlinux 0x8131d4a6	pci_enable_pcie_error_reporting
+EXPORT_SYMBOL_GPL vmlinux 0x81f01c2e	unregister_pernet_gen_device
+EXPORT_SYMBOL_GPL vmlinux 0x8226642f	__gpio_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x8253f8dc	power_supply_register
+EXPORT_SYMBOL_GPL vmlinux 0x82939ebd	rcu_batches_completed_sched
+EXPORT_SYMBOL_GPL vmlinux 0x82cd19f3	register_xenstore_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x82d79b51	sysctl_vfs_cache_pressure
+EXPORT_SYMBOL_GPL vmlinux 0x82f776b7	gpio_export
+EXPORT_SYMBOL_GPL vmlinux 0x83559efc	device_del
+EXPORT_SYMBOL_GPL vmlinux 0x837b39ae	generic_fh_to_dentry
+EXPORT_SYMBOL_GPL vmlinux 0x83808e86	mnt_want_write
+EXPORT_SYMBOL_GPL vmlinux 0x83d8c04e	skb_tstamp_tx
+EXPORT_SYMBOL_GPL vmlinux 0x844b940d	crypto_alloc_aead
+EXPORT_SYMBOL_GPL vmlinux 0x854c7b23	console_drivers
+EXPORT_SYMBOL_GPL vmlinux 0x854fd185	xen_ptep_get_and_clear_full
+EXPORT_SYMBOL_GPL vmlinux 0x856d3332	inotify_init
+EXPORT_SYMBOL_GPL vmlinux 0x8578b8ca	uhci_reset_hc
+EXPORT_SYMBOL_GPL vmlinux 0x85bc471a	inotify_dentry_parent_queue_event
+EXPORT_SYMBOL_GPL vmlinux 0x85c10896	rcu_batches_completed_bh
+EXPORT_SYMBOL_GPL vmlinux 0x861a7a74	put_device
+EXPORT_SYMBOL_GPL vmlinux 0x862f98a3	xen_create_contiguous_region
+EXPORT_SYMBOL_GPL vmlinux 0x86623fd7	notify_remote_via_irq
+EXPORT_SYMBOL_GPL vmlinux 0x868784cb	__symbol_get
+EXPORT_SYMBOL_GPL vmlinux 0x86a51007	gnttab_end_foreign_transfer
+EXPORT_SYMBOL_GPL vmlinux 0x86b1667d	hwrng_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x86d6ca0a	handle_level_irq
+EXPORT_SYMBOL_GPL vmlinux 0x86f6b99d	synchronize_rcu_expedited
+EXPORT_SYMBOL_GPL vmlinux 0x873fbaea	edac_atomic_assert_error
+EXPORT_SYMBOL_GPL vmlinux 0x8752cebb	crypto_alloc_base
+EXPORT_SYMBOL_GPL vmlinux 0x87754115	raw_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x87a848c5	crypto_lookup_template
+EXPORT_SYMBOL_GPL vmlinux 0x88024aba	proc_net_fops_create
+EXPORT_SYMBOL_GPL vmlinux 0x880b189a	__atomic_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e	crypto_xor
+EXPORT_SYMBOL_GPL vmlinux 0x885142a6	nf_net_netfilter_sysctl_path
+EXPORT_SYMBOL_GPL vmlinux 0x886736fc	olpc_platform_info
+EXPORT_SYMBOL_GPL vmlinux 0x8936629b	pci_cleanup_aer_uncorrect_error_status
+EXPORT_SYMBOL_GPL vmlinux 0x89802853	multi_notify_remote_via_irq
+EXPORT_SYMBOL_GPL vmlinux 0x8992a336	cuckoo_hash_rehash
+EXPORT_SYMBOL_GPL vmlinux 0x89b55825	gpiochip_is_requested
+EXPORT_SYMBOL_GPL vmlinux 0x89fb2e95	blk_add_driver_data
+EXPORT_SYMBOL_GPL vmlinux 0x8a309f76	crypto_aead_setauthsize
+EXPORT_SYMBOL_GPL vmlinux 0x8af59707	pciserial_init_ports
+EXPORT_SYMBOL_GPL vmlinux 0x8af9ed46	rtnl_kill_links
+EXPORT_SYMBOL_GPL vmlinux 0x8afa3fe6	inotify_inode_queue_event
+EXPORT_SYMBOL_GPL vmlinux 0x8b718ddb	disk_map_sector_rcu
+EXPORT_SYMBOL_GPL vmlinux 0x8ba1e77d	ip_local_out
+EXPORT_SYMBOL_GPL vmlinux 0x8c06a108	xenbus_transaction_start
+EXPORT_SYMBOL_GPL vmlinux 0x8c38074a	unregister_xenstore_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x8c9d686d	__wake_up_sync_key
+EXPORT_SYMBOL_GPL vmlinux 0x8ca2bf6e	__create_workqueue_key
+EXPORT_SYMBOL_GPL vmlinux 0x8d033df4	klist_node_attached
+EXPORT_SYMBOL_GPL vmlinux 0x8d399a46	inet_twsk_purge
+EXPORT_SYMBOL_GPL vmlinux 0x8db13995	sysfs_add_file_to_group
+EXPORT_SYMBOL_GPL vmlinux 0x8df14aca	crypto_drop_spawn
+EXPORT_SYMBOL_GPL vmlinux 0x8e40f882	crypto_register_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0x8ea92116	dm_disk
+EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e	__wake_up_sync
+EXPORT_SYMBOL_GPL vmlinux 0x8ee8dfdf	gnttab_reset_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0x8f0927f9	xfrm_audit_policy_delete
+EXPORT_SYMBOL_GPL vmlinux 0x8f187c6a	ring_buffer_empty
+EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77	__round_jiffies_relative
+EXPORT_SYMBOL_GPL vmlinux 0x8fa74514	sysdev_suspend
+EXPORT_SYMBOL_GPL vmlinux 0x90075e6e	securityfs_create_dir
+EXPORT_SYMBOL_GPL vmlinux 0x907f92fc	device_initialize
+EXPORT_SYMBOL_GPL vmlinux 0x90a1004a	crypto_has_alg
+EXPORT_SYMBOL_GPL vmlinux 0x91497ec9	vfs_cancel_lock
+EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6	profile_event_register
+EXPORT_SYMBOL_GPL vmlinux 0x92096425	cleanup_srcu_struct
+EXPORT_SYMBOL_GPL vmlinux 0x925872c5	crypto_shash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x927358f3	inet_csk_addr2sockaddr
+EXPORT_SYMBOL_GPL vmlinux 0x92e4a850	vfs_kern_mount
+EXPORT_SYMBOL_GPL vmlinux 0x92e98343	class_for_each_device
+EXPORT_SYMBOL_GPL vmlinux 0x92fb217b	dcookie_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x9321df95	dlm_lock
+EXPORT_SYMBOL_GPL vmlinux 0x932cf867	inet_ctl_sock_create
+EXPORT_SYMBOL_GPL vmlinux 0x93d2422d	snmp_mib_free
+EXPORT_SYMBOL_GPL vmlinux 0x93d5da49	fb_deferred_io_cleanup
+EXPORT_SYMBOL_GPL vmlinux 0x943d8c83	fsstack_copy_attr_all
+EXPORT_SYMBOL_GPL vmlinux 0x944bec57	user_read
+EXPORT_SYMBOL_GPL vmlinux 0x94846e7c	ring_buffer_discard_commit
+EXPORT_SYMBOL_GPL vmlinux 0x94e0c537	platform_device_del
+EXPORT_SYMBOL_GPL vmlinux 0x952664c5	do_exit
+EXPORT_SYMBOL_GPL vmlinux 0x953b3b1c	xenbus_dev_fatal
+EXPORT_SYMBOL_GPL vmlinux 0x956a91ba	gpio_get_value_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x95758050	__blocking_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x9577edba	irq_to_evtchn_port
+EXPORT_SYMBOL_GPL vmlinux 0x95a22898	fib_rules_cleanup_ops
+EXPORT_SYMBOL_GPL vmlinux 0x95ca30f8	ring_buffer_consume
+EXPORT_SYMBOL_GPL vmlinux 0x95e958d4	generic_drop_inode
+EXPORT_SYMBOL_GPL vmlinux 0x96068860	sysdev_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x96a69fbe	platform_get_irq_byname
+EXPORT_SYMBOL_GPL vmlinux 0x96af7463	xfrm_audit_policy_add
+EXPORT_SYMBOL_GPL vmlinux 0x96b33ced	class_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x96b60d2f	pci_restore_bars
+EXPORT_SYMBOL_GPL vmlinux 0x96c3835b	synchronize_srcu
+EXPORT_SYMBOL_GPL vmlinux 0x96c74232	platform_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31	pm_qos_add_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x96eb2e5e	shash_ahash_digest
+EXPORT_SYMBOL_GPL vmlinux 0x9701910f	firmware_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x971f838d	attribute_container_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x97846efa	inet_csk_reqsk_queue_hash_add
+EXPORT_SYMBOL_GPL vmlinux 0x98924c74	user_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x989c5a67	flush_workqueue
+EXPORT_SYMBOL_GPL vmlinux 0x995d1071	prof_on
+EXPORT_SYMBOL_GPL vmlinux 0x996b9c97	sysfs_chmod_file
+EXPORT_SYMBOL_GPL vmlinux 0x99c3775c	kmap_atomic_pfn
+EXPORT_SYMBOL_GPL vmlinux 0x99f84c77	bus_sort_breadthfirst
+EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc	crypto_attr_alg_name
+EXPORT_SYMBOL_GPL vmlinux 0x9a6f2e26	class_compat_create_link
+EXPORT_SYMBOL_GPL vmlinux 0x9a7e86d2	devm_kfree
+EXPORT_SYMBOL_GPL vmlinux 0x9acb4c7e	uhci_check_and_reset_hc
+EXPORT_SYMBOL_GPL vmlinux 0x9ad4bd6e	skb_pull_rcsum
+EXPORT_SYMBOL_GPL vmlinux 0x9af8ed92	destroy_workqueue
+EXPORT_SYMBOL_GPL vmlinux 0x9b26f9a5	debugfs_create_x16
+EXPORT_SYMBOL_GPL vmlinux 0x9b4220a6	devres_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e	unregister_vt_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x9bae5c1d	swiotlb_unmap_page
+EXPORT_SYMBOL_GPL vmlinux 0x9be0a66f	devres_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x9bfe5d76	devres_get
+EXPORT_SYMBOL_GPL vmlinux 0x9c3f8caf	rtnl_register
+EXPORT_SYMBOL_GPL vmlinux 0x9ca88870	__rtnl_register
+EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b	xfrm_count_enc_supported
+EXPORT_SYMBOL_GPL vmlinux 0x9d3850e1	gnttab_alloc_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0x9d54b980	register_pernet_gen_device
+EXPORT_SYMBOL_GPL vmlinux 0x9d69f35a	__mnt_is_readonly
+EXPORT_SYMBOL_GPL vmlinux 0x9dc07141	__get_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x9e01f6d4	eventfd_signal
+EXPORT_SYMBOL_GPL vmlinux 0x9e684ab6	add_to_page_cache_lru
+EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2	pm_qos_requirement
+EXPORT_SYMBOL_GPL vmlinux 0x9e7d3442	xenbus_resume
+EXPORT_SYMBOL_GPL vmlinux 0x9ebff902	start_thread
+EXPORT_SYMBOL_GPL vmlinux 0x9edad954	gpiochip_remove
+EXPORT_SYMBOL_GPL vmlinux 0x9f0116e2	class_dev_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0x9f40a6d6	async_synchronize_full_domain
+EXPORT_SYMBOL_GPL vmlinux 0x9f6311c3	tty_buffer_request_room
+EXPORT_SYMBOL_GPL vmlinux 0x9f85c57f	input_ff_erase
+EXPORT_SYMBOL_GPL vmlinux 0x9f85ed90	klist_remove
+EXPORT_SYMBOL_GPL vmlinux 0x9fa17abe	bd_claim_by_disk
+EXPORT_SYMBOL_GPL vmlinux 0x9fc531d7	page_cache_async_readahead
+EXPORT_SYMBOL_GPL vmlinux 0x9fce80db	fb_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x9fe5c9b9	inet_hash
+EXPORT_SYMBOL_GPL vmlinux 0x9fe86905	dma_get_required_mask
+EXPORT_SYMBOL_GPL vmlinux 0xa0255440	net_ipv4_ctl_path
+EXPORT_SYMBOL_GPL vmlinux 0xa0abac4e	led_trigger_event
+EXPORT_SYMBOL_GPL vmlinux 0xa115bdc2	pci_reset_function
+EXPORT_SYMBOL_GPL vmlinux 0xa11ce81a	rtc_set_mmss
+EXPORT_SYMBOL_GPL vmlinux 0xa1303f24	pci_create_slot
+EXPORT_SYMBOL_GPL vmlinux 0xa13151c9	uart_console_write
+EXPORT_SYMBOL_GPL vmlinux 0xa150100d	spi_async
+EXPORT_SYMBOL_GPL vmlinux 0xa18f3d5c	iounmap_atomic
+EXPORT_SYMBOL_GPL vmlinux 0xa1df7bfc	bus_find_device
+EXPORT_SYMBOL_GPL vmlinux 0xa1f6e30d	skb_segment
+EXPORT_SYMBOL_GPL vmlinux 0xa26b0e5a	crypto_unregister_alg
+EXPORT_SYMBOL_GPL vmlinux 0xa2edb1c7	inotify_add_watch
+EXPORT_SYMBOL_GPL vmlinux 0xa353fffc	xenbus_rm
+EXPORT_SYMBOL_GPL vmlinux 0xa37017a0	skb_cow_data
+EXPORT_SYMBOL_GPL vmlinux 0xa3d5102e	crypto_shash_final
+EXPORT_SYMBOL_GPL vmlinux 0xa40a8590	input_event_to_user
+EXPORT_SYMBOL_GPL vmlinux 0xa42ef01c	find_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0xa43e4d25	task_current_syscall
+EXPORT_SYMBOL_GPL vmlinux 0xa45104a2	__pneigh_lookup
+EXPORT_SYMBOL_GPL vmlinux 0xa46998e8	device_create_vargs
+EXPORT_SYMBOL_GPL vmlinux 0xa49a5f96	alloc_empty_pages_and_pagevec
+EXPORT_SYMBOL_GPL vmlinux 0xa58798bd	attribute_container_classdev_to_container
+EXPORT_SYMBOL_GPL vmlinux 0xa596f12a	__blkdev_driver_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0xa5b1a2e4	sysfs_create_group
+EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e	pm_qos_add_requirement
+EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec	inotify_unmount_inodes
+EXPORT_SYMBOL_GPL vmlinux 0xa5e13de0	xfrm_output_resume
+EXPORT_SYMBOL_GPL vmlinux 0xa5efbf4c	async_synchronize_full
+EXPORT_SYMBOL_GPL vmlinux 0xa60077e0	w1_write_8
+EXPORT_SYMBOL_GPL vmlinux 0xa6097bff	gnttab_request_free_callback
+EXPORT_SYMBOL_GPL vmlinux 0xa6735eb8	tcp_cong_avoid_ai
+EXPORT_SYMBOL_GPL vmlinux 0xa6d93a49	get_net_ns_by_pid
+EXPORT_SYMBOL_GPL vmlinux 0xa6fbc9a6	register_ftrace_event
+EXPORT_SYMBOL_GPL vmlinux 0xa779f574	inet_csk_reqsk_queue_prune
+EXPORT_SYMBOL_GPL vmlinux 0xa7ab285f	xenbus_unregister_driver
+EXPORT_SYMBOL_GPL vmlinux 0xa7f51a5b	inet6_hash_connect
+EXPORT_SYMBOL_GPL vmlinux 0xa8753ac3	tcp_is_cwnd_limited
+EXPORT_SYMBOL_GPL vmlinux 0xa8b82a53	xen_destroy_contiguous_region
+EXPORT_SYMBOL_GPL vmlinux 0xa8d6b0ec	udp4_lib_lookup
+EXPORT_SYMBOL_GPL vmlinux 0xa8f59416	gpio_direction_output
+EXPORT_SYMBOL_GPL vmlinux 0xa9165a53	kobject_uevent
+EXPORT_SYMBOL_GPL vmlinux 0xa971a0eb	inet_csk_search_req
+EXPORT_SYMBOL_GPL vmlinux 0xa9a56f2d	inotify_rm_wd
+EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8	unregister_oom_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xa9d73bfc	__class_register
+EXPORT_SYMBOL_GPL vmlinux 0xaa2a72bf	__iowrite64_copy
+EXPORT_SYMBOL_GPL vmlinux 0xaa3e3aea	__i2c_board_lock
+EXPORT_SYMBOL_GPL vmlinux 0xaa45c5ea	device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xaa5310f9	__tracepoint_napi_poll
+EXPORT_SYMBOL_GPL vmlinux 0xaa66a87a	do_kern_mount
+EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696	cpu_clock
+EXPORT_SYMBOL_GPL vmlinux 0xaa8d2c75	driver_add_kobj
+EXPORT_SYMBOL_GPL vmlinux 0xaab60997	bus_for_each_drv
+EXPORT_SYMBOL_GPL vmlinux 0xaaddf6ca	blocking_notifier_chain_cond_register
+EXPORT_SYMBOL_GPL vmlinux 0xaaf7f157	gnttab_cancel_free_callback
+EXPORT_SYMBOL_GPL vmlinux 0xab57e311	tracepoint_probe_register
+EXPORT_SYMBOL_GPL vmlinux 0xab983be6	cuckoo_hash_add
+EXPORT_SYMBOL_GPL vmlinux 0xac256fe9	platform_driver_register
+EXPORT_SYMBOL_GPL vmlinux 0xac306cd9	macvlan_handle_frame_hook
+EXPORT_SYMBOL_GPL vmlinux 0xac83caf5	create_xen_proc_entry
+EXPORT_SYMBOL_GPL vmlinux 0xaccfc678	cpu_bit_bitmap
+EXPORT_SYMBOL_GPL vmlinux 0xad096363	xenbus_printf
+EXPORT_SYMBOL_GPL vmlinux 0xad185347	rtc_class_open
+EXPORT_SYMBOL_GPL vmlinux 0xad9c83ed	page_mkclean
+EXPORT_SYMBOL_GPL vmlinux 0xadebe818	platform_get_irq
+EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee	pm_qos_remove_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xae43f918	proc_net_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0xae5389fe	tcp_reno_min_cwnd
+EXPORT_SYMBOL_GPL vmlinux 0xae71b024	relay_close
+EXPORT_SYMBOL_GPL vmlinux 0xaeec4b58	__class_create
+EXPORT_SYMBOL_GPL vmlinux 0xaf7ec8c3	class_compat_remove_link
+EXPORT_SYMBOL_GPL vmlinux 0xaf9eaefc	anon_transport_class_register
+EXPORT_SYMBOL_GPL vmlinux 0xafb9eb9a	pci_msi_off
+EXPORT_SYMBOL_GPL vmlinux 0xb00a6811	raw_seq_next
+EXPORT_SYMBOL_GPL vmlinux 0xb00cfbeb	apply_to_page_range
+EXPORT_SYMBOL_GPL vmlinux 0xb010968b	blk_rq_err_bytes
+EXPORT_SYMBOL_GPL vmlinux 0xb0223109	klist_next
+EXPORT_SYMBOL_GPL vmlinux 0xb027135b	rtc_irq_set_freq
+EXPORT_SYMBOL_GPL vmlinux 0xb075d972	inode_add_to_lists
+EXPORT_SYMBOL_GPL vmlinux 0xb090175c	vfs_setlease
+EXPORT_SYMBOL_GPL vmlinux 0xb0b201dd	attribute_container_find_class_device
+EXPORT_SYMBOL_GPL vmlinux 0xb0bd3c23	dm_put
+EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc	cn_netlink_send
+EXPORT_SYMBOL_GPL vmlinux 0xb18429eb	suspend_device_irqs
+EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce	rcu_barrier_sched
+EXPORT_SYMBOL_GPL vmlinux 0xb1e03a54	lookup_instantiate_filp
+EXPORT_SYMBOL_GPL vmlinux 0xb2033b82	net_accel_msg_recv
+EXPORT_SYMBOL_GPL vmlinux 0xb244aedd	pskb_put
+EXPORT_SYMBOL_GPL vmlinux 0xb2b2701b	inet_csk_listen_stop
+EXPORT_SYMBOL_GPL vmlinux 0xb2ceb537	blkdev_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0xb3419d19	ring_buffer_resize
+EXPORT_SYMBOL_GPL vmlinux 0xb384c659	sync_filesystem
+EXPORT_SYMBOL_GPL vmlinux 0xb3d17c59	spi_register_driver
+EXPORT_SYMBOL_GPL vmlinux 0xb434251e	simple_attr_read
+EXPORT_SYMBOL_GPL vmlinux 0xb441bdce	crypto_larval_alloc
+EXPORT_SYMBOL_GPL vmlinux 0xb4bc1c27	net_accel_update_state
+EXPORT_SYMBOL_GPL vmlinux 0xb4e14553	gnttab_query_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0xb4f7aaf8	queue_work_on
+EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64	edac_op_state
+EXPORT_SYMBOL_GPL vmlinux 0xb53ae573	cpu_idle_wait
+EXPORT_SYMBOL_GPL vmlinux 0xb5589739	transport_destroy_device
+EXPORT_SYMBOL_GPL vmlinux 0xb57972a5	device_bind_driver
+EXPORT_SYMBOL_GPL vmlinux 0xb58dcfa2	synchronize_sched_expedited
+EXPORT_SYMBOL_GPL vmlinux 0xb5b2b1d2	relay_switch_subbuf
+EXPORT_SYMBOL_GPL vmlinux 0xb5c174c7	sysdev_show_ulong
+EXPORT_SYMBOL_GPL vmlinux 0xb5d6d495	skb_to_sgvec
+EXPORT_SYMBOL_GPL vmlinux 0xb5d8913d	register_jprobe
+EXPORT_SYMBOL_GPL vmlinux 0xb5dfab52	inet_csk_get_port
+EXPORT_SYMBOL_GPL vmlinux 0xb61eb77b	crypto_alloc_ahash
+EXPORT_SYMBOL_GPL vmlinux 0xb6230f1f	gnttab_grant_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0xb65091b3	selinux_secmark_refcount_dec
+EXPORT_SYMBOL_GPL vmlinux 0xb679f553	blk_trace_startstop
+EXPORT_SYMBOL_GPL vmlinux 0xb68dc6ea	unregister_ftrace_event
+EXPORT_SYMBOL_GPL vmlinux 0xb6a35c2d	unregister_pernet_device
+EXPORT_SYMBOL_GPL vmlinux 0xb6bc49a9	__supported_pte_mask
+EXPORT_SYMBOL_GPL vmlinux 0xb7138ee2	init_srcu_struct
+EXPORT_SYMBOL_GPL vmlinux 0xb7237333	crypto_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0xb744fa43	xfrm_ealg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0xb7686dd8	sysdev_register
+EXPORT_SYMBOL_GPL vmlinux 0xb798e556	posix_timer_event
+EXPORT_SYMBOL_GPL vmlinux 0xb7ba64a7	net_accel_msg_reply
+EXPORT_SYMBOL_GPL vmlinux 0xb7f86ca5	kern_mount_data
+EXPORT_SYMBOL_GPL vmlinux 0xb7fdd0df	eventfd_ctx_put
+EXPORT_SYMBOL_GPL vmlinux 0xb87e93ac	hwmon_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xb897072f	hrtimer_forward
+EXPORT_SYMBOL_GPL vmlinux 0xb8982695	srcu_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xb8a25dc5	br_handle_frame_hook
+EXPORT_SYMBOL_GPL vmlinux 0xb903674c	scatterwalk_map_and_copy
+EXPORT_SYMBOL_GPL vmlinux 0xb91269da	net_accel_msg_init_queue
+EXPORT_SYMBOL_GPL vmlinux 0xb93f51f2	uart_set_options
+EXPORT_SYMBOL_GPL vmlinux 0xb97b8588	xen_tlb_flush_all
+EXPORT_SYMBOL_GPL vmlinux 0xb97e1868	blk_queue_rq_timed_out
+EXPORT_SYMBOL_GPL vmlinux 0xb99d5837	xenbus_read
+EXPORT_SYMBOL_GPL vmlinux 0xb9a37d7b	spi_busnum_to_master
+EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9	add_uevent_var
+EXPORT_SYMBOL_GPL vmlinux 0xba94649e	ring_buffer_free
+EXPORT_SYMBOL_GPL vmlinux 0xbb085ac6	pci_find_next_ht_capability
+EXPORT_SYMBOL_GPL vmlinux 0xbb4a1408	klist_init
+EXPORT_SYMBOL_GPL vmlinux 0xbb58b814	iomap_free
+EXPORT_SYMBOL_GPL vmlinux 0xbba2d258	skb_gro_receive
+EXPORT_SYMBOL_GPL vmlinux 0xbbb98859	edid_info
+EXPORT_SYMBOL_GPL vmlinux 0xbbba36fa	sysfs_remove_link
+EXPORT_SYMBOL_GPL vmlinux 0xbbdd6b04	ring_buffer_overruns
+EXPORT_SYMBOL_GPL vmlinux 0xbc1d8daf	xenbus_for_each_frontend
+EXPORT_SYMBOL_GPL vmlinux 0xbc7085c6	srcu_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xbc7428ce	crypto_register_ahash
+EXPORT_SYMBOL_GPL vmlinux 0xbc8c8210	net_assign_generic
+EXPORT_SYMBOL_GPL vmlinux 0xbd050a9a	devres_add
+EXPORT_SYMBOL_GPL vmlinux 0xbd67876b	net_accel_msg_notify
+EXPORT_SYMBOL_GPL vmlinux 0xbd6bab7b	xen_invlpg_all
+EXPORT_SYMBOL_GPL vmlinux 0xbd8c0817	free_empty_pages_and_pagevec
+EXPORT_SYMBOL_GPL vmlinux 0xbdd295f0	trace_vprintk
+EXPORT_SYMBOL_GPL vmlinux 0xbe115a6b	tracepoint_iter_start
+EXPORT_SYMBOL_GPL vmlinux 0xbe116723	do_posix_clock_nosettime
+EXPORT_SYMBOL_GPL vmlinux 0xbe256d24	pci_enable_rom
+EXPORT_SYMBOL_GPL vmlinux 0xbe9b146d	tcp_twsk_unique
+EXPORT_SYMBOL_GPL vmlinux 0xbe9e501f	device_release_driver
+EXPORT_SYMBOL_GPL vmlinux 0xbead5e5f	find_module
+EXPORT_SYMBOL_GPL vmlinux 0xbf247b93	w1_next_pullup
+EXPORT_SYMBOL_GPL vmlinux 0xbfcd2dc0	sysfs_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xbfd94bb0	bind_virq_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0xc06fd79b	fb_deferred_io_init
+EXPORT_SYMBOL_GPL vmlinux 0xc0ce8c1d	crypto_shash_setkey
+EXPORT_SYMBOL_GPL vmlinux 0xc126e890	klist_del
+EXPORT_SYMBOL_GPL vmlinux 0xc1327d40	unregister_kretprobes
+EXPORT_SYMBOL_GPL vmlinux 0xc22a3091	vm_unmap_aliases
+EXPORT_SYMBOL_GPL vmlinux 0xc269b53a	input_class
+EXPORT_SYMBOL_GPL vmlinux 0xc26f0d35	kill_pid_info_as_uid
+EXPORT_SYMBOL_GPL vmlinux 0xc270aa9c	pci_find_ht_capability
+EXPORT_SYMBOL_GPL vmlinux 0xc2839357	get_inotify_watch
+EXPORT_SYMBOL_GPL vmlinux 0xc2c08d5e	lookup_create
+EXPORT_SYMBOL_GPL vmlinux 0xc2d5e4d0	platform_get_resource
+EXPORT_SYMBOL_GPL vmlinux 0xc2e18388	debugfs_remove
+EXPORT_SYMBOL_GPL vmlinux 0xc3301f02	rcu_expedited_torture_stats
+EXPORT_SYMBOL_GPL vmlinux 0xc3498f35	rtc_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc34efe27	snmp_fold_field
+EXPORT_SYMBOL_GPL vmlinux 0xc3c84335	spi_setup
+EXPORT_SYMBOL_GPL vmlinux 0xc44a27e0	sysdev_driver_register
+EXPORT_SYMBOL_GPL vmlinux 0xc44f57cc	dequeue_signal
+EXPORT_SYMBOL_GPL vmlinux 0xc45206de	skcipher_geniv_alloc
+EXPORT_SYMBOL_GPL vmlinux 0xc4a340ac	set_task_ioprio
+EXPORT_SYMBOL_GPL vmlinux 0xc4b33aa6	tracepoint_probe_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc4c44f9a	crypto_shoot_alg
+EXPORT_SYMBOL_GPL vmlinux 0xc4cbd3fd	queue_delayed_work_on
+EXPORT_SYMBOL_GPL vmlinux 0xc4e717fb	bus_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc5397da6	xenbus_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0xc54efbeb	inotify_find_watch
+EXPORT_SYMBOL_GPL vmlinux 0xc60f75ec	__ftrace_vprintk
+EXPORT_SYMBOL_GPL vmlinux 0xc6478aa9	eventfd_fget
+EXPORT_SYMBOL_GPL vmlinux 0xc6ebecfb	tty_perform_flush
+EXPORT_SYMBOL_GPL vmlinux 0xc6f39ca0	seq_open_net
+EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6	atomic_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xc8339c77	driver_create_file
+EXPORT_SYMBOL_GPL vmlinux 0xc853da58	trace_define_common_fields
+EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84	ktime_get
+EXPORT_SYMBOL_GPL vmlinux 0xc87e487a	sched_clock_idle_sleep_event
+EXPORT_SYMBOL_GPL vmlinux 0xc937bd8a	crypto_init_spawn2
+EXPORT_SYMBOL_GPL vmlinux 0xc948532f	bus_get_kset
+EXPORT_SYMBOL_GPL vmlinux 0xc9561772	fb_destroy_modelist
+EXPORT_SYMBOL_GPL vmlinux 0xc9a9c913	dlm_posix_unlock
+EXPORT_SYMBOL_GPL vmlinux 0xc9ec4e21	free_percpu
+EXPORT_SYMBOL_GPL vmlinux 0xca01f51c	tcp_orphan_count
+EXPORT_SYMBOL_GPL vmlinux 0xca432b73	inet_csk_clone
+EXPORT_SYMBOL_GPL vmlinux 0xca81ea9a	xenbus_transaction_end
+EXPORT_SYMBOL_GPL vmlinux 0xca85d8cf	tracepoint_probe_update_all
+EXPORT_SYMBOL_GPL vmlinux 0xcb20ff69	xen_tlb_flush_mask
+EXPORT_SYMBOL_GPL vmlinux 0xcb719181	device_schedule_callback_owner
+EXPORT_SYMBOL_GPL vmlinux 0xcbcbecb0	pci_restore_msi_state
+EXPORT_SYMBOL_GPL vmlinux 0xcbdb674c	alloc_page_buffers
+EXPORT_SYMBOL_GPL vmlinux 0xcbf97a42	debugfs_create_dir
+EXPORT_SYMBOL_GPL vmlinux 0xcc195048	blk_queue_dma_drain
+EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d	inet_twdr_hangman
+EXPORT_SYMBOL_GPL vmlinux 0xcc3fa466	relay_buf_full
+EXPORT_SYMBOL_GPL vmlinux 0xcc66f774	srcu_read_lock
+EXPORT_SYMBOL_GPL vmlinux 0xccc51ff5	tty_ldisc_flush
+EXPORT_SYMBOL_GPL vmlinux 0xcd4f3fe9	get_user_pages_fast
+EXPORT_SYMBOL_GPL vmlinux 0xcd5f8ff3	bind_caller_port_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0xcd65d4fa	inet_diag_register
+EXPORT_SYMBOL_GPL vmlinux 0xcd9e9cc7	crypto_find_alg
+EXPORT_SYMBOL_GPL vmlinux 0xcdca3691	nr_irqs
+EXPORT_SYMBOL_GPL vmlinux 0xcde3d5de	vfs_setxattr
+EXPORT_SYMBOL_GPL vmlinux 0xce0c4d44	srcu_batches_completed
+EXPORT_SYMBOL_GPL vmlinux 0xce757be4	devres_remove
+EXPORT_SYMBOL_GPL vmlinux 0xcea9b653	led_trigger_set_default
+EXPORT_SYMBOL_GPL vmlinux 0xcecbdae0	netfront_accelerator_loaded
+EXPORT_SYMBOL_GPL vmlinux 0xceee2cbc	sock_prot_inuse_add
+EXPORT_SYMBOL_GPL vmlinux 0xcf0e8af6	kallsyms_on_each_symbol
+EXPORT_SYMBOL_GPL vmlinux 0xcf114751	tcp_done
+EXPORT_SYMBOL_GPL vmlinux 0xcf184578	simple_attr_write
+EXPORT_SYMBOL_GPL vmlinux 0xcf7a962e	cn_add_callback
+EXPORT_SYMBOL_GPL vmlinux 0xcf84bfcf	blk_rq_check_limits
+EXPORT_SYMBOL_GPL vmlinux 0xcf9f3328	dlm_release_lockspace
+EXPORT_SYMBOL_GPL vmlinux 0xcfc68341	synchronize_rcu_bh
+EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad	register_vt_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xcfdf6f71	led_trigger_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xd0110fc7	add_page_wait_queue
+EXPORT_SYMBOL_GPL vmlinux 0xd03c7700	secure_ipv4_port_ephemeral
+EXPORT_SYMBOL_GPL vmlinux 0xd0458ccb	xenbus_strstate
+EXPORT_SYMBOL_GPL vmlinux 0xd073129a	mm_kobj
+EXPORT_SYMBOL_GPL vmlinux 0xd08e6a56	vfs_removexattr
+EXPORT_SYMBOL_GPL vmlinux 0xd0c05159	emergency_restart
+EXPORT_SYMBOL_GPL vmlinux 0xd0d9168a	crypto_ahash_type
+EXPORT_SYMBOL_GPL vmlinux 0xd12ac59b	olpc_ec_cmd
+EXPORT_SYMBOL_GPL vmlinux 0xd16712f3	crypto_check_attr_type
+EXPORT_SYMBOL_GPL vmlinux 0xd1677c93	platform_device_put
+EXPORT_SYMBOL_GPL vmlinux 0xd1c7d688	devres_release_group
+EXPORT_SYMBOL_GPL vmlinux 0xd2535fa5	w1_reset_select_slave
+EXPORT_SYMBOL_GPL vmlinux 0xd26201b3	securityfs_remove
+EXPORT_SYMBOL_GPL vmlinux 0xd268b45a	__rtnl_link_register
+EXPORT_SYMBOL_GPL vmlinux 0xd273b1b1	__round_jiffies_up_relative
+EXPORT_SYMBOL_GPL vmlinux 0xd2a8caf0	work_on_cpu
+EXPORT_SYMBOL_GPL vmlinux 0xd2d9139f	securityfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0xd30e702a	user_describe
+EXPORT_SYMBOL_GPL vmlinux 0xd341f90b	register_pernet_subsys
+EXPORT_SYMBOL_GPL vmlinux 0xd3999f4d	raw_hash_sk
+EXPORT_SYMBOL_GPL vmlinux 0xd3b78da3	xenbus_suspend_cancel
+EXPORT_SYMBOL_GPL vmlinux 0xd3d60277	ring_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0xd45807ac	net_accel_msg_complete_send_notify
+EXPORT_SYMBOL_GPL vmlinux 0xd46a2519	xfrm_audit_state_notfound
+EXPORT_SYMBOL_GPL vmlinux 0xd4efae13	debugfs_create_size_t
+EXPORT_SYMBOL_GPL vmlinux 0xd544e902	pgprot_writecombine
+EXPORT_SYMBOL_GPL vmlinux 0xd59ea10b	class_interface_register
+EXPORT_SYMBOL_GPL vmlinux 0xd5b96a62	debugfs_create_x32
+EXPORT_SYMBOL_GPL vmlinux 0xd61e8f44	__blk_put_request
+EXPORT_SYMBOL_GPL vmlinux 0xd6c4990e	spi_alloc_device
+EXPORT_SYMBOL_GPL vmlinux 0xd6f82b99	module_mutex
+EXPORT_SYMBOL_GPL vmlinux 0xd6fdcec5	blk_queue_lld_busy
+EXPORT_SYMBOL_GPL vmlinux 0xd705b4c7	schedule_hrtimeout
+EXPORT_SYMBOL_GPL vmlinux 0xd70624f4	queue_delayed_work
+EXPORT_SYMBOL_GPL vmlinux 0xd7080868	inet_twsk_put
+EXPORT_SYMBOL_GPL vmlinux 0xd72feba2	xenbus_read_driver_state
+EXPORT_SYMBOL_GPL vmlinux 0xd73ef534	sysdev_resume
+EXPORT_SYMBOL_GPL vmlinux 0xd7d79132	put_online_cpus
+EXPORT_SYMBOL_GPL vmlinux 0xd7f91ef3	mask_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0xd813da4d	led_trigger_show
+EXPORT_SYMBOL_GPL vmlinux 0xd8e35140	tracepoint_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0xd8f5a561	xen_l1_entry_update
+EXPORT_SYMBOL_GPL vmlinux 0xd8ff53a9	cuckoo_hash_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xd9042fa8	scatterwalk_map
+EXPORT_SYMBOL_GPL vmlinux 0xda135436	get_current_tty
+EXPORT_SYMBOL_GPL vmlinux 0xda1be8e1	async_synchronize_cookie_domain
+EXPORT_SYMBOL_GPL vmlinux 0xda41a590	sysdev_class_register
+EXPORT_SYMBOL_GPL vmlinux 0xda479767	rtnl_put_cacheinfo
+EXPORT_SYMBOL_GPL vmlinux 0xda4a79d2	blkdev_aio_write
+EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3	fb_mode_option
+EXPORT_SYMBOL_GPL vmlinux 0xdb274e52	monotonic_to_bootbased
+EXPORT_SYMBOL_GPL vmlinux 0xdb52fed5	pci_ioremap_bar
+EXPORT_SYMBOL_GPL vmlinux 0xdb8853db	relay_subbufs_consumed
+EXPORT_SYMBOL_GPL vmlinux 0xdba64f1c	eventfd_ctx_get
+EXPORT_SYMBOL_GPL vmlinux 0xdc251d32	bus_rescan_devices
+EXPORT_SYMBOL_GPL vmlinux 0xdc583c08	dlm_unlock
+EXPORT_SYMBOL_GPL vmlinux 0xdc5fec5a	fib_rules_register
+EXPORT_SYMBOL_GPL vmlinux 0xdc714560	register_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0xdca42d0c	simple_attr_open
+EXPORT_SYMBOL_GPL vmlinux 0xddd1d850	gnttab_end_foreign_access_ref
+EXPORT_SYMBOL_GPL vmlinux 0xddfce5d4	blkcipher_walk_virt
+EXPORT_SYMBOL_GPL vmlinux 0xde165cc4	single_release_net
+EXPORT_SYMBOL_GPL vmlinux 0xde417b81	async_schedule_domain
+EXPORT_SYMBOL_GPL vmlinux 0xdea8854e	anon_transport_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xdeff4be0	fib_rules_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xdf219034	raw_seq_stop
+EXPORT_SYMBOL_GPL vmlinux 0xdf6ff4c8	crypto_spawn_tfm2
+EXPORT_SYMBOL_GPL vmlinux 0xdfafb983	per_cpu__gdt_page
+EXPORT_SYMBOL_GPL vmlinux 0xdfbff4d8	rtc_irq_register
+EXPORT_SYMBOL_GPL vmlinux 0xdfc5bc48	spi_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0xdfc6a4d9	driver_for_each_device
+EXPORT_SYMBOL_GPL vmlinux 0xdfda4526	gpio_export_link
+EXPORT_SYMBOL_GPL vmlinux 0xe0446470	disk_part_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0xe0630094	generic_detach_inode
+EXPORT_SYMBOL_GPL vmlinux 0xe06c3428	__module_address
+EXPORT_SYMBOL_GPL vmlinux 0xe0793b98	pci_hp_remove_module_link
+EXPORT_SYMBOL_GPL vmlinux 0xe08d21e8	platform_driver_probe
+EXPORT_SYMBOL_GPL vmlinux 0xe0bb5f08	blk_abort_queue
+EXPORT_SYMBOL_GPL vmlinux 0xe0cca33e	xfrm_aead_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0xe10d7408	inotify_inode_is_dead
+EXPORT_SYMBOL_GPL vmlinux 0xe20e1252	__put_net
+EXPORT_SYMBOL_GPL vmlinux 0xe23e3317	dm_underlying_device_busy
+EXPORT_SYMBOL_GPL vmlinux 0xe28e2129	user_update
+EXPORT_SYMBOL_GPL vmlinux 0xe35c1b8a	remove_irq
+EXPORT_SYMBOL_GPL vmlinux 0xe35d572a	ring_buffer_commit_overrun_cpu
+EXPORT_SYMBOL_GPL vmlinux 0xe389fee8	disk_part_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0xe3f53d18	class_compat_register
+EXPORT_SYMBOL_GPL vmlinux 0xe438bb61	do_add_mount
+EXPORT_SYMBOL_GPL vmlinux 0xe4731dde	crypto_alloc_tfm
+EXPORT_SYMBOL_GPL vmlinux 0xe4bf75d4	inet_unhash
+EXPORT_SYMBOL_GPL vmlinux 0xe513afc0	cache_k8_northbridges
+EXPORT_SYMBOL_GPL vmlinux 0xe530071c	pm_qos_remove_requirement
+EXPORT_SYMBOL_GPL vmlinux 0xe56918b0	crypto_unregister_shash
+EXPORT_SYMBOL_GPL vmlinux 0xe5f8e9bc	register_posix_clock
+EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f	gpio_unexport
+EXPORT_SYMBOL_GPL vmlinux 0xe63c12ed	tty_encode_baud_rate
+EXPORT_SYMBOL_GPL vmlinux 0xe651f76e	selinux_is_enabled
+EXPORT_SYMBOL_GPL vmlinux 0xe664dd17	net_accel_unmap_device_page
+EXPORT_SYMBOL_GPL vmlinux 0xe67dac9d	driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xe6c6d1b6	skb_icv_walk
+EXPORT_SYMBOL_GPL vmlinux 0xe7131f04	dm_noflush_suspending
+EXPORT_SYMBOL_GPL vmlinux 0xe71789b2	filter_match_preds
+EXPORT_SYMBOL_GPL vmlinux 0xe722b7fa	crypto_destroy_tfm
+EXPORT_SYMBOL_GPL vmlinux 0xe7246674	vfs_lock_file
+EXPORT_SYMBOL_GPL vmlinux 0xe73658b8	pci_add_dynid
+EXPORT_SYMBOL_GPL vmlinux 0xe745bbbe	elv_register
+EXPORT_SYMBOL_GPL vmlinux 0xe7d76475	blk_rq_prep_clone
+EXPORT_SYMBOL_GPL vmlinux 0xe7f1f8d9	aead_geniv_init
+EXPORT_SYMBOL_GPL vmlinux 0xe7ffe877	pcpu_base_addr
+EXPORT_SYMBOL_GPL vmlinux 0xe859f284	shash_free_instance
+EXPORT_SYMBOL_GPL vmlinux 0xe862c4b7	dpm_suspend_start
+EXPORT_SYMBOL_GPL vmlinux 0xe8b37058	sysdev_store_int
+EXPORT_SYMBOL_GPL vmlinux 0xe901175f	__dev_addr_unsync
+EXPORT_SYMBOL_GPL vmlinux 0xe91836ea	pciserial_remove_ports
+EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3	devres_free
+EXPORT_SYMBOL_GPL vmlinux 0xea065e01	task_handoff_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xea124bd1	gcd
+EXPORT_SYMBOL_GPL vmlinux 0xead38f69	rtc_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xeb4c1fc8	__tracepoint_block_remap
+EXPORT_SYMBOL_GPL vmlinux 0xeb63bbbf	ahash_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0xec1a75a9	__dev_addr_sync
+EXPORT_SYMBOL_GPL vmlinux 0xec2e4b2e	platform_device_register_simple
+EXPORT_SYMBOL_GPL vmlinux 0xec4857ba	inet_diag_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xec767840	xenbus_watch_path
+EXPORT_SYMBOL_GPL vmlinux 0xece8ac0f	balloon_release_driver_page
+EXPORT_SYMBOL_GPL vmlinux 0xed7a62ef	zap_vma_ptes
+EXPORT_SYMBOL_GPL vmlinux 0xed7ea375	devres_find
+EXPORT_SYMBOL_GPL vmlinux 0xedbf56ed	fb_bl_default_curve
+EXPORT_SYMBOL_GPL vmlinux 0xedf32538	crypto_init_shash_spawn
+EXPORT_SYMBOL_GPL vmlinux 0xee6cdd16	attribute_container_register
+EXPORT_SYMBOL_GPL vmlinux 0xef6c3f70	round_jiffies_up_relative
+EXPORT_SYMBOL_GPL vmlinux 0xef9c588e	ring_buffer_iter_peek
+EXPORT_SYMBOL_GPL vmlinux 0xefc6409c	bus_get_device_klist
+EXPORT_SYMBOL_GPL vmlinux 0xefdd5a63	ktime_get_ts
+EXPORT_SYMBOL_GPL vmlinux 0xefe21106	snmp_mib_init
+EXPORT_SYMBOL_GPL vmlinux 0xefef0909	register_kprobes
+EXPORT_SYMBOL_GPL vmlinux 0xf06c1cc7	unregister_timer_hook
+EXPORT_SYMBOL_GPL vmlinux 0xf1463412	execute_in_process_context
+EXPORT_SYMBOL_GPL vmlinux 0xf184d189	kernel_power_off
+EXPORT_SYMBOL_GPL vmlinux 0xf18c5ecf	devres_close_group
+EXPORT_SYMBOL_GPL vmlinux 0xf1d853ca	hrtimer_init_sleeper
+EXPORT_SYMBOL_GPL vmlinux 0xf1edf54e	__fsnotify_parent
+EXPORT_SYMBOL_GPL vmlinux 0xf236df1f	w1_read_block
+EXPORT_SYMBOL_GPL vmlinux 0xf23c75ec	ahash_attr_alg
+EXPORT_SYMBOL_GPL vmlinux 0xf23d19d6	ring_buffer_alloc_read_page
+EXPORT_SYMBOL_GPL vmlinux 0xf2fca922	uart_parse_options
+EXPORT_SYMBOL_GPL vmlinux 0xf32d855a	debugfs_create_blob
+EXPORT_SYMBOL_GPL vmlinux 0xf34806ec	hrtimer_get_res
+EXPORT_SYMBOL_GPL vmlinux 0xf3c1c0a0	leds_list_lock
+EXPORT_SYMBOL_GPL vmlinux 0xf42ef339	__srcu_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xf4525005	crypto_grab_aead
+EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2	rcu_barrier_bh
+EXPORT_SYMBOL_GPL vmlinux 0xf4aebdc3	xenbus_suspend
+EXPORT_SYMBOL_GPL vmlinux 0xf4e0dce7	blk_update_request
+EXPORT_SYMBOL_GPL vmlinux 0xf5384ac1	__trace_printk
+EXPORT_SYMBOL_GPL vmlinux 0xf53a67b4	alloc_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0xf54bd49b	lcm
+EXPORT_SYMBOL_GPL vmlinux 0xf55962fa	class_dev_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0xf56a6cc9	pci_bus_add_device
+EXPORT_SYMBOL_GPL vmlinux 0xf5799f7a	stop_machine_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xf5945bac	gnttab_free_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd	invalidate_bh_lrus
+EXPORT_SYMBOL_GPL vmlinux 0xf5e1c575	ring_buffer_time_stamp
+EXPORT_SYMBOL_GPL vmlinux 0xf5e4e6f1	tcp_init_congestion_ops
+EXPORT_SYMBOL_GPL vmlinux 0xf602c0ba	sysdev_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xf6397626	init_dummy_netdev
+EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73	hwrng_register
+EXPORT_SYMBOL_GPL vmlinux 0xf6fc5cb7	inotify_init_watch
+EXPORT_SYMBOL_GPL vmlinux 0xf7016530	xenbus_gather
+EXPORT_SYMBOL_GPL vmlinux 0xf7135aa0	crypto_ahash_final
+EXPORT_SYMBOL_GPL vmlinux 0xf7ba4962	rtnl_link_register
+EXPORT_SYMBOL_GPL vmlinux 0xf80b1399	tcp_death_row
+EXPORT_SYMBOL_GPL vmlinux 0xf81061d5	register_net_sysctl_rotable
+EXPORT_SYMBOL_GPL vmlinux 0xf82e6456	kobject_rename
+EXPORT_SYMBOL_GPL vmlinux 0xf863e82a	flush_work
+EXPORT_SYMBOL_GPL vmlinux 0xf864fa02	user_instantiate
+EXPORT_SYMBOL_GPL vmlinux 0xf8802492	print_stack_trace
+EXPORT_SYMBOL_GPL vmlinux 0xf895c0a6	rtc_read_alarm
+EXPORT_SYMBOL_GPL vmlinux 0xf940cf8d	device_attach
+EXPORT_SYMBOL_GPL vmlinux 0xf9711bab	__root_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xf97666a0	set_memory_rw
+EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5	__round_jiffies
+EXPORT_SYMBOL_GPL vmlinux 0xfa1f4662	scatterwalk_start
+EXPORT_SYMBOL_GPL vmlinux 0xfa72846a	kobject_init_and_add
+EXPORT_SYMBOL_GPL vmlinux 0xfaaf845d	blk_queue_rq_timeout
+EXPORT_SYMBOL_GPL vmlinux 0xfb17c0db	xenbus_frontend_closed
+EXPORT_SYMBOL_GPL vmlinux 0xfb2a3293	math_state_restore
+EXPORT_SYMBOL_GPL vmlinux 0xfb5292ce	platform_driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xfb788089	unbind_from_per_cpu_irq
+EXPORT_SYMBOL_GPL vmlinux 0xfb8ce4a1	crypto_unregister_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0xfbf3b09d	locks_release_private
+EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d	register_oom_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xfc263383	crypto_nivaead_type
+EXPORT_SYMBOL_GPL vmlinux 0xfcd6a5c4	crypto_hash_walk_done
+EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c	crypto_larval_error
+EXPORT_SYMBOL_GPL vmlinux 0xfe084306	device_find_child
+EXPORT_SYMBOL_GPL vmlinux 0xfe0bf21a	tty_get_pgrp
+EXPORT_SYMBOL_GPL vmlinux 0xfe0c12ec	put_driver
+EXPORT_SYMBOL_GPL vmlinux 0xfe1b953e	simple_attr_release
+EXPORT_SYMBOL_GPL vmlinux 0xfe990052	gpio_free
+EXPORT_SYMBOL_GPL vmlinux 0xff45550d	sysfs_put
+EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe	cn_del_callback
+EXPORT_SYMBOL_GPL vmlinux 0xff8ec3a2	debugfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0xffc1c023	crypto_spawn_tfm
+EXPORT_SYMBOL_GPL vmlinux 0xffe2538f	hrtimer_cancel
+EXPORT_UNUSED_SYMBOL vmlinux 0x00000000	simple_prepare_write
--- linux-ec2-2.6.32.orig/debian.ec2/abi/2.6.32-317.35/i386/ec2.modules
+++ linux-ec2-2.6.32/debian.ec2/abi/2.6.32-317.35/i386/ec2.modules
@@ -0,0 +1,1660 @@
+3c359
+3c574_cs
+3c589_cs
+3c59x
+3w-9xxx
+3w-xxxx
+6pack
+8021q
+8139cp
+8139too
+8390
+9p
+9pnet
+a100u2w
+a3d
+aacraid
+abituguru
+abituguru3
+abyss
+ac97_bus
+acecad
+acenic
+acquirewdt
+act200l-sir
+act_gact
+act_ipt
+actisys-sir
+act_mirred
+act_nat
+act_pedit
+act_police
+act_simple
+ad1848
+ad7414
+ad7418
+adcxx
+adfs
+adi
+adm1021
+adm1025
+adm1026
+adm1029
+adm1031
+adm9240
+ads7828
+ads7846
+adt7470
+adt7473
+adutux
+advansys
+advantechwdt
+aedsp16
+aes_generic
+aes-i586
+affs
+af_key
+af-rxrpc
+agpgart
+ah4
+ah6
+aha152x_cs
+ahci
+aic79xx
+aic7xxx
+aic94xx
+aiptek
+aircable
+alauda
+ali-agp
+ali-ircc
+alim1535_wdt
+alim7101_wdt
+ambassador
+amd64-agp
+amd76x_edac
+amd76xrom
+amd8111e
+amd-k7-agp
+amd-rng
+analog
+anubis
+aoe
+appledisplay
+applesmc
+appletalk
+appletouch
+applicom
+ar7part
+arc4
+arcfb
+arcmsr
+arcnet
+arc-rawmode
+arc-rimi
+ark3116
+arkfb
+arptable_filter
+arp_tables
+arpt_mangle
+asb100
+asix
+async_memcpy
+async_pq
+async_raid6_recov
+async_tx
+async_xor
+ata_generic
+ata_piix
+aten
+ati-agp
+ati_remote
+ati_remote2
+atl1
+atl1e
+atl2
+atmtcp
+atp
+atp870u
+atxp1
+aty128fb
+atyfb
+aufs
+authenc
+auth_rpcgss
+autofs
+autofs4
+av5100
+ax25
+axnet_cs
+b44
+baycom_epp
+baycom_par
+baycom_ser_fdx
+baycom_ser_hdx
+bcm203x
+bcm5974
+befs
+belkin_sa
+berry_charge
+bfs
+bfusb
+binfmt_aout
+binfmt_misc
+bitblit
+block2mtd
+blowfish
+bluecard_cs
+bluetooth
+bnep
+bnx2
+bnx2x
+bonding
+bpa10x
+bpck
+bpck6
+bpqether
+br2684
+bridge
+broadcom
+bsd_comp
+bt3c_cs
+btrfs
+btuart_cs
+btusb
+BusLogic
+c67x00
+cafe_nand
+camellia
+capmode
+carminefb
+cassini
+cast5
+cast6
+catc
+cbc
+cciss
+ccm
+cdc-acm
+cdc_ether
+cdc_subset
+cdc-wdm
+cfag12864b
+cfag12864bfb
+cfg80211
+cfi_cmdset_0001
+cfi_cmdset_0002
+cfi_cmdset_0020
+cfi_probe
+cfi_util
+ch
+ch341
+chipreg
+cicada
+cifs
+cirrusfb
+ck804xrom
+cls_basic
+cls_fw
+cls_route
+cls_rsvp
+cls_rsvp6
+cls_tcindex
+cls_u32
+cm4000_cs
+cm4040_cs
+cobra
+coda
+com20020
+com20020_cs
+com20020-pci
+com90io
+com90xx
+comm
+coretemp
+cpcihp_generic
+cpcihp_zt5550
+cpqarray
+cpu5wdt
+cpuid
+cr_bllcd
+crc32c
+crc7
+crc-ccitt
+crc-itu-t
+crc-t10dif
+crvml
+cryptd
+cryptoloop
+crypto_null
+cs5535_gpio
+ct82c710
+ctr
+cts
+cxacru
+cxgb
+cxgb3
+cyber2000fb
+cyberjack
+cyclades
+cyclomx
+cycx_drv
+cypress_cy7c63
+cypress_m8
+cytherm
+DAC960
+davicom
+db9
+dc395x
+dccp
+dccp_diag
+dccp_ipv4
+dccp_ipv6
+dccp_probe
+de2104x
+de4x5
+de600
+de620
+decnet
+deflate
+defxx
+des_generic
+digi_acceleport
+diskonchip
+display
+dlci
+dm9601
+dm-crypt
+dme1737
+dmfe
+dm-log
+dm-mirror
+dm-multipath
+dm-raid45
+dm-region-hash
+dm-round-robin
+dm-snapshot
+dmx3191d
+dm-zero
+dn_rtmsg
+doc2000
+doc2001
+doc2001plus
+docecc
+docprobe
+donauboe
+dpt_i2o
+drm
+drm_kms_helper
+ds1621
+ds1682
+ds2482
+ds2490
+ds2760_battery
+dscc4
+dstr
+dtl1_cs
+dummy_hcd
+dv1394
+e100
+e1000
+e1000e
+e752x_edac
+e7xxx_edac
+eata
+ebt_802_3
+ebtable_broute
+ebtable_filter
+ebtable_nat
+ebtables
+ebt_among
+ebt_arp
+ebt_arpreply
+ebt_dnat
+ebt_ip
+ebt_ip6
+ebt_limit
+ebt_log
+ebt_mark
+ebt_mark_m
+ebt_nflog
+ebt_pkttype
+ebt_redirect
+ebt_snat
+ebt_stp
+ebt_ulog
+ebt_vlan
+ecb
+econet
+ecryptfs
+edac_core
+eeprom_93cx6
+efficeon-agp
+efs
+ehci-hcd
+elo
+em_cmp
+emi26
+emi62
+em_meta
+em_nbyte
+empeg
+em_text
+emu10k1-gp
+em_u32
+enclosure
+eni
+epat
+epca
+epia
+epic100
+esb2rom
+esi-sir
+esp4
+esp6
+eth1394
+eurotechwdt
+evbug
+evdev
+f71805f
+f71882fg
+f75375s
+fakephp
+farsync
+fat
+faulty
+fbcon
+fb_ddc
+fb_sys_fops
+fcrypt
+fdomain
+fdomain_cs
+fealnx
+ff-memless
+firestream
+fit2
+fit3
+floppy
+fm801-gp
+fmvj18x_cs
+font
+forcedeth
+fore_200e
+freevxfs
+friq
+frpw
+fsam7400
+fschmd
+ftdi-elan
+ftdi_sio
+ftl
+fujitsu_ts
+funsoft
+fuse
+g450_pll
+gadgetfs
+gamecon
+gameport
+garmin_gps
+garp
+g_cdc
+gcm
+gdth
+gen_probe
+geode-aes
+geode-rng
+g_ether
+gf128mul
+gf2k
+g_file_storage
+ghash-generic
+girbil-sir
+gl518sm
+gl520sm
+gl620a
+gluebi
+gpio_keys
+gpio_mouse
+grip
+grip_mp
+g_serial
+gtco
+guillemot
+gunze
+gx1fb
+gxfb
+g_zero
+hamachi
+hangcheck-timer
+hci_uart
+hci_vhci
+hdaps
+hdlc
+hdlc_cisco
+hdlcdrv
+hdlc_fr
+hdlc_ppp
+hdlc_raw
+hdlc_raw_eth
+hdlc_x25
+he
+hecubafb
+hfs
+hfsplus
+hgafb
+hid
+hid-a4tech
+hid-apple
+hid-belkin
+hid-cherry
+hid-chicony
+hid-cypress
+hid-drff
+hid-ezkey
+hid-gaff
+hid-gyration
+hid-kensington
+hid-kye
+hid-logitech
+hid-microsoft
+hid-monterey
+hid-ntrig
+hid-ortek
+hidp
+hid-petalynx
+hid-pl
+hid-samsung
+hid-sjoy
+hid-sony
+hid-sunplus
+hid-tmff
+hid-topseed
+hid-twinhan
+hid-wacom
+hid-zpff
+hifn_795x
+horizon
+hp100
+hp4x
+hpfs
+hpilo
+hptiop
+hso
+htc-pasic3
+hwmon-vid
+i2c-algo-bit
+i2c-algo-pca
+i2c-algo-pcf
+i2c-ali1535
+i2c-ali1563
+i2c-ali15x3
+i2c-amd756
+i2c-amd756-s4882
+i2c-amd8111
+i2c-core
+i2c-dev
+i2c-gpio
+i2c-i801
+i2c-isch
+i2c-matroxfb
+i2c-nforce2
+i2c-nforce2-s4985
+i2c-ocores
+i2c-parport
+i2c-parport-light
+i2c-pca-platform
+i2c-piix4
+i2c-simtec
+i2c-sis5595
+i2c-sis630
+i2c-sis96x
+i2c-stub
+i2c-taos-evm
+i2c-tiny-usb
+i2c-via
+i2c-viapro
+i2c-voodoo3
+i2o_block
+i2o_bus
+i2o_config
+i2o_core
+i2o_proc
+i2o_scsi
+i3000_edac
+i5000_edac
+i5100_edac
+i5k_amb
+i6300esb
+i82092
+i82860_edac
+i82875p_edac
+i82975x_edac
+i8k
+ib700wdt
+ib_addr
+ib_cm
+ib_core
+ib_ipoib
+ib_iser
+ib_mad
+ibmaem
+ibmasm
+ibmasr
+ibmpex
+ib_mthca
+ibmtr_cs
+ib_sa
+ib_srp
+ib_ucm
+ib_umad
+ib_uverbs
+ichxrom
+icplus
+idmouse
+idt77252
+ieee1394
+iforce
+igb
+ili9320
+imm
+inexio
+inftl
+initio
+input-polldev
+intel-rng
+intel_vr_nor
+interact
+ioc4
+io_edgeport
+io_ti
+iowarrior
+ip2
+ip6_queue
+ip6table_filter
+ip6table_mangle
+ip6table_raw
+ip6_tables
+ip6table_security
+ip6t_ah
+ip6t_eui64
+ip6t_frag
+ip6t_hbh
+ip6t_ipv6header
+ip6t_LOG
+ip6t_mh
+ip6t_REJECT
+ip6t_rt
+ip6_tunnel
+ipaq
+ipcomp
+ipcomp6
+ipddp
+ipg
+ip_gre
+iphase
+ipip
+ipmi_devintf
+ipmi_msghandler
+ipmi_poweroff
+ipmi_si
+ipmi_watchdog
+ip_queue
+ipr
+ips
+iptable_filter
+iptable_mangle
+iptable_nat
+iptable_raw
+ip_tables
+iptable_security
+ipt_addrtype
+ipt_ah
+ipt_CLUSTERIP
+ipt_ecn
+ipt_ECN
+ipt_LOG
+ipt_MASQUERADE
+ipt_NETMAP
+ipt_REDIRECT
+ipt_REJECT
+ipt_ULOG
+ipv6
+ip_vs
+ip_vs_dh
+ip_vs_ftp
+ip_vs_lblc
+ip_vs_lblcr
+ip_vs_lc
+ip_vs_nq
+ip_vs_rr
+ip_vs_sed
+ip_vs_sh
+ip_vs_wlc
+ip_vs_wrr
+ipw
+ipwireless
+ipx
+ircomm
+ircomm-tty
+irda
+irda-usb
+irlan
+irnet
+irtty-sir
+iscsi_tcp
+iscsi_trgt
+isight_firmware
+isofs
+isp116x-hcd
+isp1760
+it87
+it8712f_wdt
+iTCO_vendor_support
+iTCO_wdt
+iw_c2
+iw_cm
+iw_cxgb3
+ixgb
+ixgbe
+jedec_probe
+jffs2
+joydev
+joydump
+jsm
+k8temp
+kafs
+kahlua
+kaweth
+kbic
+kbtab
+keyspan
+keyspan_pda
+keyspan_remote
+khazad
+kingsun-sir
+kl5kusb105
+kobil_sct
+ks0108
+ks959-sir
+ksdazzle-sir
+ktti
+kyrofb
+l2cap
+l440gx
+lanai
+lanstreamer
+lapb
+lapbether
+lcd
+ldusb
+lec
+led-class
+leds-gpio
+leds-net48xx
+leds-pca9532
+leds-pca955x
+leds-wrap
+ledtrig-default-on
+ledtrig-heartbeat
+ledtrig-timer
+legousbtower
+libata
+libcrc32c
+libiscsi
+libiscsi_tcp
+libsas
+libsrp
+lightning
+linear
+lirc_atiusb
+lirc_bt829
+lirc_dev
+lirc_i2c
+lirc_igorplugusb
+lirc_imon
+lirc_it87
+lirc_ite8709
+lirc_mceusb
+lirc_sasem
+lirc_serial
+lirc_sir
+lirc_streamzap
+lirc_ttusbir
+litelink-sir
+lkkbd
+llc2
+lm63
+lm70
+lm75
+lm77
+lm78
+lm80
+lm83
+lm85
+lm87
+lm90
+lm92
+lm93
+lmc
+lockd
+lp
+lpfc
+lrw
+ltv350qv
+lxfb
+lxt
+lzo
+lzo_compress
+lzo_decompress
+m25p80
+ma600-sir
+mac80211
+machzwd
+macmodes
+magellan
+map_absent
+map_funcs
+map_ram
+map_rom
+marvell
+matroxfb_accel
+matroxfb_base
+matroxfb_crtc2
+matroxfb_DAC1064
+matroxfb_g450
+matroxfb_maven
+matroxfb_misc
+matroxfb_Ti3026
+matrox_w1
+max1619
+max6650
+max7301
+max732x
+mbp_nvidia_bl
+mcp2120-sir
+mcp23s08
+mcs7780
+mcs7830
+mct_u232
+md4
+mdc800
+mdio
+mdio-bitbang
+md-mod
+megaraid
+megaraid_mbox
+megaraid_mm
+megaraid_sas
+mfd-core
+mga
+michael_mic
+microtek
+mii
+minix
+mk712
+mkiss
+mlx4_core
+mlx4_ib
+mos7720
+mos7840
+moto_modem
+moxa
+mpoa
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
+mpu401
+msdos
+msr
+mtd
+mtd_blkdevs
+mtdblock
+mtdblock_ro
+mtdchar
+mtdconcat
+mtd_dataflash
+mtdoops
+mtdram
+mtouch
+multipath
+mwave
+mxser
+myri10ge
+n411
+nand
+nand_ecc
+nand_ids
+nandsim
+natsemi
+navman
+nbd
+ncpfs
+ndiswrapper
+ne2k-pci
+neofb
+net1080
+netconsole
+netrom
+netsc520
+nettel
+netxen_nic
+newtonkbd
+nf_conntrack
+nf_conntrack_amanda
+nf_conntrack_ftp
+nf_conntrack_h323
+nf_conntrack_ipv4
+nf_conntrack_ipv6
+nf_conntrack_irc
+nf_conntrack_netbios_ns
+nf_conntrack_netlink
+nf_conntrack_pptp
+nf_conntrack_proto_gre
+nf_conntrack_proto_sctp
+nf_conntrack_proto_udplite
+nf_conntrack_sip
+nf_conntrack_tftp
+nf_defrag_ipv4
+nf_nat
+nf_nat_amanda
+nf_nat_ftp
+nf_nat_h323
+nf_nat_irc
+nf_nat_pptp
+nf_nat_proto_gre
+nf_nat_proto_sctp
+nf_nat_proto_udplite
+nf_nat_sip
+nf_nat_snmp_basic
+nf_nat_tftp
+nfnetlink
+nfnetlink_log
+nfnetlink_queue
+nfs
+nfs_acl
+nfsd
+nftl
+n_hdlc
+nicstar
+niu
+nls_ascii
+nls_cp1250
+nls_cp1251
+nls_cp1255
+nls_cp437
+nls_cp737
+nls_cp775
+nls_cp850
+nls_cp852
+nls_cp855
+nls_cp857
+nls_cp860
+nls_cp861
+nls_cp862
+nls_cp863
+nls_cp864
+nls_cp865
+nls_cp866
+nls_cp869
+nls_cp874
+nls_cp932
+nls_cp936
+nls_cp949
+nls_cp950
+nls_euc-jp
+nls_iso8859-1
+nls_iso8859-13
+nls_iso8859-14
+nls_iso8859-15
+nls_iso8859-2
+nls_iso8859-3
+nls_iso8859-4
+nls_iso8859-5
+nls_iso8859-6
+nls_iso8859-7
+nls_iso8859-9
+nls_koi8-r
+nls_koi8-ru
+nls_koi8-u
+nls_utf8
+nmclan_cs
+nozomi
+n_r3964
+ns558
+ns83820
+nsc_gpio
+nsc-ircc
+nsp32
+nsp_cs
+ntfs
+nvidia-agp
+nvidiafb
+nvram
+ocfs2
+ocfs2_dlm
+ocfs2_dlmfs
+ocfs2_nodemanager
+ocfs2_stackglue
+ocfs2_stack_o2cb
+ocfs2_stack_user
+ohci1394
+ohci-hcd
+old_belkin-sir
+olpc_battery
+olympic
+omfs
+omnibook
+omninet
+on20
+on26
+onenand
+onenand_sim
+opl3
+oprofile
+option
+osst
+oti6858
+output
+p8023
+padlock-aes
+padlock-sha
+paride
+parkbd
+parport
+parport_ax88796
+parport_cs
+parport_pc
+parport_serial
+pas2
+pata_ali
+pata_amd
+pata_artop
+pata_atiixp
+pata_cmd64x
+pata_cs5520
+pata_cs5530
+pata_cs5535
+pata_cs5536
+pata_efar
+pata_hpt366
+pata_hpt37x
+pata_hpt3x3
+pata_it8213
+pata_it821x
+pata_jmicron
+pata_marvell
+pata_mpiix
+pata_netcell
+pata_ninja32
+pata_ns87410
+pata_ns87415
+pata_oldpiix
+pata_pcmcia
+pata_pdc2027x
+pata_pdc202xx_old
+pata_rz1000
+pata_sch
+pata_serverworks
+pata_sil680
+pata_sis
+pata_sl82c105
+pata_triflex
+pata_via
+pbe5
+pc87360
+pc8736x_gpio
+pc87413_wdt
+pc87427
+pca953x
+pcbc
+pcd
+pcf857x
+pcf8591
+pci
+pci200syn
+pciehp
+pci_hotplug
+pcilynx
+pcips2
+pcmcia
+pcmcia_core
+pcnet32
+pcnet_cs
+pcspkr
+pcwd_pci
+pcwd_usb
+pd
+pd6729
+pda_power
+pdc_adma
+pegasus
+penmount
+pf
+pg
+phantom
+phram
+physmap
+pktcdvd
+pktgen
+pl2303
+platform_lcd
+plat_nand
+plat-ram
+plip
+plusb
+pm2fb
+pm3fb
+pmc551
+powermate
+ppa
+ppdev
+ppp_async
+ppp_deflate
+ppp_mppe
+pppoatm
+pppoe
+pppol2tp
+pppox
+ppp_synctty
+progear_bl
+psmouse
+pss
+pt
+qla1280
+qla2xxx
+qla3xxx
+qla4xxx
+qlogic_cs
+qlogicfas408
+qnx4
+qsemi
+quota_tree
+quota_v1
+quota_v2
+r128
+r8169
+r8192se_pci
+r82600_edac
+r8a66597-hcd
+radeon
+radeonfb
+raid0
+raid1
+raid10
+raid456
+raid6_pq
+raid_class
+ramzswap
+raw
+raw1394
+rdma_cm
+rdma_ucm
+redboot
+reed_solomon
+rfc1051
+rfc1201
+rfcomm
+rfd_ftl
+rfkill
+rio500
+riscom8
+rivafb
+rmd128
+rmd160
+rmd256
+rmd320
+rndis_host
+rocket
+romfs
+rose
+rpcsec_gss_krb5
+rpcsec_gss_spkm3
+rrunner
+rsrc_nonstatic
+rtc-ds1305
+rtc-ds1307
+rtc-ds1374
+rtc-ds1553
+rtc-ds1672
+rtc-ds1742
+rtc-fm3130
+rtc-isl1208
+rtc-m41t80
+rtc-m41t94
+rtc-m48t59
+rtc-m48t86
+rtc-max6900
+rtc-max6902
+rtc-pcf8563
+rtc-pcf8583
+rtc-rs5c348
+rtc-rs5c372
+rtc-stk17ta8
+rtc-test
+rtc-v3020
+rtc-x1205
+rtl8150
+rxkad
+s1d13xxxfb
+s2io
+s3fb
+safe_serial
+salsa20_generic
+salsa20-i586
+sata_inic162x
+sata_mv
+sata_nv
+sata_promise
+sata_qstor
+sata_sil
+sata_sil24
+sata_sis
+sata_svw
+sata_sx4
+sata_uli
+sata_via
+sata_vsc
+savage
+savagefb
+sb
+sbc60xxwdt
+sbc7240_wdt
+sbc8360
+sbc_epx_c3
+sbc_gxx
+sb_lib
+sbni
+sbp2
+sc1200wdt
+sc520cdp
+sc520_wdt
+sc92031
+scb2_flash
+sch_atm
+sch_cbq
+sch_dsmark
+sch_gred
+sch_hfsc
+sch_htb
+sch_ingress
+sch_netem
+sch_prio
+sch_red
+sch_sfq
+sch_tbf
+sch_teql
+sco
+scsi_debug
+scsi_dh
+scsi_dh_alua
+scsi_dh_emc
+scsi_dh_hp_sw
+scsi_dh_rdac
+scsi_mod
+scsi_tgt
+scsi_transport_fc
+scsi_transport_iscsi
+scsi_transport_sas
+scsi_transport_spi
+scsi_transport_srp
+scsi_wait_scan
+sctp
+scx200
+scx200_acb
+scx200_docflash
+scx200_gpio
+scx200_hrt
+scx200_i2c
+scx200_wdt
+sd_mod
+seed
+seqiv
+serial_cs
+serio_raw
+sermouse
+serpent
+serport
+ses
+sfc
+sg
+sha1_generic
+sha256_generic
+sha512_generic
+shpchp
+sidewinder
+sierra
+sir-dev
+sis
+sis190
+sis5595
+sis900
+sis-agp
+sisfb
+sisusbvga
+sit
+skfp
+skge
+sky2
+sl811_cs
+sl811-hcd
+slip
+slram
+sm501
+sm501fb
+smbfs
+smc91c92_cs
+smsc
+smsc37b787_wdt
+smsc47b397
+smsc47m1
+smsc47m192
+smsc-ircc2
+snd
+snd-ac97-codec
+snd-ad1889
+snd-ak4114
+snd-ak4117
+snd-ak4xxx-adda
+snd-ali5451
+snd-als300
+snd-als4000
+snd-atiixp
+snd-atiixp-modem
+snd-au8810
+snd-au8820
+snd-au8830
+snd-aw2
+snd-azt3328
+snd-bt87x
+snd-ca0106
+snd-cmipci
+snd-cs4281
+snd-cs46xx
+snd-cs5530
+snd-cs5535audio
+snd-cs8427
+snd-darla20
+snd-darla24
+snd-dummy
+snd-echo3g
+snd-emu10k1
+snd-emu10k1-synth
+snd-emu10k1x
+snd-emux-synth
+snd-ens1370
+snd-ens1371
+snd-es1938
+snd-es1968
+snd-fm801
+snd-gina20
+snd-gina24
+snd-hda-codec
+snd-hda-codec-analog
+snd-hda-codec-atihdmi
+snd-hda-codec-ca0110
+snd-hda-codec-cirrus
+snd-hda-codec-cmedia
+snd-hda-codec-conexant
+snd-hda-codec-idt
+snd-hda-codec-intelhdmi
+snd-hda-codec-nvhdmi
+snd-hda-codec-realtek
+snd-hda-codec-si3054
+snd-hda-codec-via
+snd-hda-intel
+snd-hdsp
+snd-hdspm
+snd-hifier
+snd-hwdep
+snd-i2c
+snd-ice1712
+snd-ice1724
+snd-ice17xx-ak4xxx
+snd-indigo
+snd-indigodj
+snd-indigoio
+snd-intel8x0
+snd-intel8x0m
+snd-korg1212
+snd-layla20
+snd-layla24
+snd-maestro3
+snd-mia
+snd-mixart
+snd-mixer-oss
+snd-mona
+snd-mpu401
+snd-mpu401-uart
+snd-mtpav
+snd-mts64
+snd-nm256
+snd-opl3-lib
+snd-opl3-synth
+snd-oxygen
+snd-oxygen-lib
+snd-page-alloc
+snd-pcm
+snd-pcm-oss
+snd-pcxhr
+snd-pdaudiocf
+snd-portman2x4
+snd-pt2258
+snd-rawmidi
+snd-riptide
+snd-rme32
+snd-rme96
+snd-rme9652
+snd-sb16-dsp
+snd-sb-common
+snd-seq
+snd-seq-device
+snd-seq-dummy
+snd-seq-midi
+snd-seq-midi-emul
+snd-seq-midi-event
+snd-seq-oss
+snd-seq-virmidi
+snd-serial-u16550
+snd-sis7019
+snd-soc-core
+snd-sonicvibes
+snd-timer
+snd-trident
+snd-usb-audio
+snd-usb-caiaq
+snd-usb-lib
+snd-usb-usx2y
+snd-util-mem
+snd-via82xx
+snd-via82xx-modem
+snd-virmidi
+snd-virtuoso
+snd-vx222
+snd-vx-lib
+snd-vxpocket
+snd-ymfpci
+softcursor
+softdog
+sonypi
+sound
+soundcore
+sound_firmware
+spaceball
+spaceorb
+spcp8x5
+specialix
+speedtch
+spi_bitbang
+spi_butterfly
+spidev
+spi_lm70llp
+sr_mod
+ssb
+sscape
+ssfdc
+sstfb
+st
+starfire
+stex
+stinger
+stir4200
+stowaway
+stp
+sundance
+sungem
+sungem_phy
+sunhme
+suni
+sunkbd
+sunrpc
+svcrdma
+svgalib
+sworks-agp
+sx8
+sym53c500_cs
+sym53c8xx
+synclink
+synclink_cs
+synclink_gt
+synclinkmp
+syscopyarea
+sysfillrect
+sysimgblt
+sysv
+tcp_bic
+tcp_cubic
+tcp_highspeed
+tcp_htcp
+tcp_hybla
+tcp_illinois
+tcp_lp
+tcp_probe
+tcp_scalable
+tcp_vegas
+tcp_veno
+tcp_westwood
+tcp_yeah
+tcrypt
+tdfx
+tdfxfb
+tea
+tehuti
+tekram-sir
+tg3
+tgr192
+thmc50
+tifm_7xx1
+tifm_core
+tileblit
+tipc
+ti_usb_3410_5052
+tlan
+tlclk
+tle62x0
+tmdc
+tms380tr
+tmscsim
+tmspci
+touchit213
+touchright
+touchwin
+tpm
+tpm_atmel
+tpm_nsc
+tps65010
+trancevibrator
+tridentfb
+trix
+ts5500_flash
+ts_bm
+ts_fsm
+ts_kmp
+tsl2550
+ttm
+tulip
+tunnel4
+tunnel6
+turbografx
+twidjoy
+twofish
+twofish_common
+twofish-i586
+typhoon
+u132-hcd
+uart401
+uart6850
+ub
+ubi
+ubifs
+udf
+ueagle-atm
+ufs
+uhci-hcd
+uinput
+uio
+uio_cif
+uio_pdrv
+uio_pdrv_genirq
+uio_smx
+uli526x
+umem
+ums-alauda
+ums-datafab
+ums-freecom
+ums-isd200
+ums-jumpshot
+ums-karma
+ums-sddr09
+ums-sddr55
+ums-usbat
+uPD98402
+usbatm
+usbcore
+usb_debug
+usbhid
+usblcd
+usbled
+usb-libusual
+usblp
+usbmon
+usbnet
+usbserial
+usb-storage
+usbtouchscreen
+uss720
+uvesafb
+veth
+vfat
+vga16fb
+vgastate
+vgg2432a4
+via
+via686a
+via-agp
+via-ircc
+via-rhine
+via-rng
+via-velocity
+video1394
+visor
+vitesse
+vlsi_ir
+v_midi
+vmlfb
+vsxxxaa
+vt1211
+vt8231
+vt8623fb
+w1_ds2433
+w1_ds2760
+w1-gpio
+w1_smem
+w1_therm
+w83627ehf
+w83627hf
+w83627hf_wdt
+w83697hf_wdt
+w83781d
+w83791d
+w83792d
+w83793
+w83877f_wdt
+w83977af_ir
+w83977f_wdt
+w83l785ts
+w83l786ng
+wacom
+wafer5823wdt
+wanrouter
+wanxl
+warrior
+wdt_pci
+whiteheat
+winbond-840
+wistron_btns
+wm97xx-ts
+wp512
+x25
+x25_asy
+xcbc
+xen-hcd
+xenscsi
+xfrm4_mode_beet
+xfrm4_mode_transport
+xfrm4_mode_tunnel
+xfrm4_tunnel
+xfrm6_mode_beet
+xfrm6_mode_ro
+xfrm6_mode_transport
+xfrm6_mode_tunnel
+xfrm6_tunnel
+xfrm_ipcomp
+xfrm_user
+xirc2ps_cs
+xircom_cb
+xor
+xpad
+xprtrdma
+x_tables
+xt_CLASSIFY
+xt_comment
+xt_connbytes
+xt_connlimit
+xt_connmark
+xt_CONNMARK
+xt_CONNSECMARK
+xt_conntrack
+xt_dccp
+xt_dscp
+xt_DSCP
+xt_esp
+xt_hashlimit
+xt_helper
+xt_hl
+xt_HL
+xt_iprange
+xtkbd
+xt_length
+xt_limit
+xt_mac
+xt_mark
+xt_MARK
+xt_multiport
+xt_NFLOG
+xt_NFQUEUE
+xt_NOTRACK
+xt_owner
+xt_physdev
+xt_pkttype
+xt_policy
+xt_quota
+xt_rateest
+xt_RATEEST
+xt_realm
+xt_recent
+xts
+xt_sctp
+xt_SECMARK
+xt_state
+xt_statistic
+xt_string
+xt_tcpmss
+xt_TCPMSS
+xt_tcpudp
+xt_time
+xt_TRACE
+xt_u32
+xusbatm
+xvmalloc
+yam
+yealink
+yellowfin
+yenta_socket
+zatm
+zaurus
+zhenhua
+zlib_deflate
--- linux-ec2-2.6.32.orig/debian.ec2/abi/2.6.32-317.35/amd64/ec2
+++ linux-ec2-2.6.32/debian.ec2/abi/2.6.32-317.35/amd64/ec2
@@ -0,0 +1,7934 @@
+EXPORT_SYMBOL crypto/gf128mul 0x0c2f123f	gf128mul_4k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x1068004b	gf128mul_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x2f2889a0	gf128mul_init_64k_lle
+EXPORT_SYMBOL crypto/gf128mul 0x3755f990	gf128mul_init_64k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x384ef9ce	gf128mul_64k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x56af0dbd	gf128mul_x_ble
+EXPORT_SYMBOL crypto/gf128mul 0x83581089	gf128mul_init_4k_lle
+EXPORT_SYMBOL crypto/gf128mul 0x9b2560b9	gf128mul_init_4k_bbe
+EXPORT_SYMBOL crypto/gf128mul 0x9e13f6f6	gf128mul_lle
+EXPORT_SYMBOL crypto/gf128mul 0xbd17a0df	gf128mul_4k_lle
+EXPORT_SYMBOL crypto/gf128mul 0xc0890413	gf128mul_64k_lle
+EXPORT_SYMBOL crypto/gf128mul 0xd60736ec	gf128mul_free_64k
+EXPORT_SYMBOL crypto/xor 0x5b6c00e6	xor_blocks
+EXPORT_SYMBOL drivers/atm/suni 0x3aa2fced	suni_init
+EXPORT_SYMBOL drivers/atm/uPD98402 0xb43b0da5	uPD98402_init
+EXPORT_SYMBOL drivers/block/paride/paride 0x132bb672	pi_init
+EXPORT_SYMBOL drivers/block/paride/paride 0x345607d6	pi_disconnect
+EXPORT_SYMBOL drivers/block/paride/paride 0x388f4f61	paride_unregister
+EXPORT_SYMBOL drivers/block/paride/paride 0x38d0a253	pi_schedule_claimed
+EXPORT_SYMBOL drivers/block/paride/paride 0x513b67ad	paride_register
+EXPORT_SYMBOL drivers/block/paride/paride 0x66eb7c53	pi_release
+EXPORT_SYMBOL drivers/block/paride/paride 0x6b82c3e6	pi_write_regr
+EXPORT_SYMBOL drivers/block/paride/paride 0x7d5451c1	pi_connect
+EXPORT_SYMBOL drivers/block/paride/paride 0x87dee549	pi_read_regr
+EXPORT_SYMBOL drivers/block/paride/paride 0x87f87cbe	pi_write_block
+EXPORT_SYMBOL drivers/block/paride/paride 0xb3438f1b	pi_read_block
+EXPORT_SYMBOL drivers/block/paride/paride 0xc25b4084	pi_do_claimed
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x06844855	agp_create_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x0bb00448	agp_collect_device_status
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x15001fc8	agp_generic_destroy_page
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x1554fa44	agp_generic_insert_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x1e422d64	agp_alloc_page_array
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x25f1d650	agp_put_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x2cce7319	agp_flush_chipset
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x30226ddf	agp_device_command
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x3286e73f	agp_unbind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x3717b54f	agp_enable
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x39f3564d	agp_generic_free_by_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x3ffc103c	agp_alloc_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x46027729	agp_generic_alloc_by_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x4b085dbf	agp3_generic_configure
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x589849b7	agp_generic_create_gatt_table
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x5db74df6	agp_generic_alloc_user
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x5db9ac1c	agp_generic_destroy_pages
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x5f63bbfc	agp_generic_alloc_page
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x673f815e	agp_bridges
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x68b82fc4	agp_free_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x73968511	agp_copy_info
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x7538b132	agp_off
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x7847b894	get_agp_version
+EXPORT_SYMBOL drivers/char/agp/agpgart 0x8c827aa7	agp_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xa10a72fa	agp_generic_free_gatt_table
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xa3d3247b	agp_bind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xa4d4f0e6	global_cache_flush
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xaea730fe	agp_generic_remove_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xb04ea8f0	agp_rebind_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xb3885361	agp_generic_enable
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xbedbd5a6	agp_generic_type_to_mask_type
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc2424641	agp3_generic_cleanup
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc5d9c46c	agp_try_unsupported_boot
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc65abeb7	agp3_generic_sizes
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xc83221a3	agp_free_page_array
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xd0fef3b2	agp_free_key
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xda3c698c	agp3_generic_tlbflush
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xdd090923	agp_generic_mask_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xde9b17ed	agp3_generic_fetch_size
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xe1a74edc	agp_backend_acquire
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xe3123dbf	agp_generic_alloc_pages
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xed1da2cf	agp_find_bridge
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xf55d7707	agp_allocate_memory
+EXPORT_SYMBOL drivers/char/agp/agpgart 0xff194e9f	agp_backend_release
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x0a1176c3	ipmi_destroy_user
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x152e46e5	ipmi_smi_add_proc_entry
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x16070519	ipmi_set_my_address
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x40f2b10c	ipmi_alloc_smi_msg
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x5b70477e	ipmi_request_settime
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6ce61c89	ipmi_set_maintenance_mode
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6e063e2a	ipmi_smi_msg_received
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x6fdecf2c	ipmi_request_supply_msgs
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x804f922a	ipmi_addr_length
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0x90e6fb0d	ipmi_set_my_LUN
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xa9f90d9e	ipmi_get_my_address
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb64798ac	ipmi_get_version
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb6713ca6	ipmi_smi_watchdog_pretimeout
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xb68fa467	ipmi_create_user
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xbec9138d	ipmi_register_for_cmd
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc7704297	ipmi_set_gets_events
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xc7e3acd6	ipmi_register_smi
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd34d82bf	ipmi_smi_watcher_unregister
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd45abbe2	ipmi_smi_watcher_register
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xd9608890	ipmi_poll_interface
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xe4f4665b	ipmi_validate_addr
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf19ac27e	ipmi_unregister_smi
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf1a19f7a	ipmi_get_maintenance_mode
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf28daa2a	ipmi_free_recv_msg
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xf3e852e8	ipmi_unregister_for_cmd
+EXPORT_SYMBOL drivers/char/ipmi/ipmi_msghandler 0xfe6012cc	ipmi_get_my_LUN
+EXPORT_SYMBOL drivers/char/nsc_gpio 0x0cac7f0a	nsc_gpio_read
+EXPORT_SYMBOL drivers/char/nsc_gpio 0x9a670cf4	nsc_gpio_write
+EXPORT_SYMBOL drivers/char/nsc_gpio 0xc756ae7b	nsc_gpio_dump
+EXPORT_SYMBOL drivers/char/nvram 0x0f28cb91	nvram_read_byte
+EXPORT_SYMBOL drivers/char/nvram 0x17ff2c1d	__nvram_read_byte
+EXPORT_SYMBOL drivers/char/nvram 0x2adec1e0	__nvram_check_checksum
+EXPORT_SYMBOL drivers/char/nvram 0x7da28f12	nvram_check_checksum
+EXPORT_SYMBOL drivers/char/nvram 0x9ce3f83f	nvram_write_byte
+EXPORT_SYMBOL drivers/char/nvram 0xa8813189	__nvram_write_byte
+EXPORT_SYMBOL drivers/edac/edac_core 0xab51d9db	edac_mc_find
+EXPORT_SYMBOL drivers/edac/edac_core 0xb9dcef55	edac_mc_handle_fbd_ce
+EXPORT_SYMBOL drivers/edac/edac_core 0xdf0943d4	edac_mc_handle_fbd_ue
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x02762bf5	drm_gem_vm_open
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0512605d	drm_get_edid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x05358ea1	drm_compat_ioctl
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x06dbea5c	drm_exit
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x076b04aa	drm_mm_takedown
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0820dacb	drm_unbind_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x0836695c	drm_sman_takedown
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x08d9f8f6	drm_gem_object_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x11b004e3	drm_vblank_post_modeset
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x135a333d	drm_connector_property_get_value
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x17bb7e69	drm_mode_create_tv_properties
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x190ba0c5	drm_master_put
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1a230ff3	drm_mode_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1bb63c05	drm_mode_create_dirty_info_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1bcf5ef4	drm_mode_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1bd8579e	drm_vblank_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1cc4416b	drm_gem_mmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1e114f27	drm_vblank_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x1f072c59	drm_property_add_enum
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x20645642	drm_debug
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x21451ac4	drm_sman_owner_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x238449ec	drm_ioctl
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x257bd599	drm_mm_dump_table
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x26dde9e0	drm_get_resource_start
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x28cd994b	drm_i2c_encoder_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2916bf63	drm_sman_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x29589444	drm_pci_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x29fd2761	drm_ati_pcigart_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2bc3e780	drm_get_dev
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2eb2f903	drm_sman_free_key
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x2f6c9e5e	drm_addmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x30138004	drm_mode_connector_list_update
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3074f033	drm_order
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x30911423	drm_rmmap_locked
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x34369ad1	drm_mode_config_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x370b2c06	drm_framebuffer_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3735c560	drm_mode_probed_add
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x382df143	drm_read
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x383cd870	drm_mode_connector_update_edid_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x38919da1	drm_sysfs_connector_add
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x3c9a1409	drm_ht_just_insert_please
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x40e4e77c	drm_agp_release
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x430aedda	drm_mm_search_free_in_range
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x45cc66a3	drm_clflush_pages
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4690a590	drm_agp_enable
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x46bf87d0	drm_irq_install
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x47b99a0a	drm_mode_create_dvi_i_properties
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x4e2008f0	drm_core_ioremap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x507f65b0	drm_idlelock_release
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x519cfb2b	drm_agp_info
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x51ab57ec	drm_sysfs_connector_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x52c0d724	drm_mode_attachmode_crtc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x545d2754	drm_mode_create_scaling_mode_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x55f060ee	drm_sman_set_range
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x56f4ffc7	drm_release
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5722d86b	drm_mm_get_block_range_generic
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x580830f0	drm_mode_set_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5999c3a4	drm_mm_clean
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x59cadfd8	drm_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5a4488f3	drm_mode_create_dithering_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5aef6544	drm_agp_chipset_flush
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5be7661c	drm_getsarea
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5efa0657	drm_mode_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5f090192	drm_vblank_put
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x5f2ce3d6	drm_mode_validate_clocks
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6022ba79	drm_i2c_encoder_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x61fc9e75	drm_mode_config_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x64cf0a35	drm_fasync
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x66dc3f3f	drm_connector_attach_property
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6a6f332f	drm_debugfs_create_files
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6ac0d8b1	drm_agp_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6c4d854b	drm_addbufs_pci
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6c851fe5	drm_sg_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6d2e5837	drm_ut_debug_printk
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6e0e0f87	drm_core_ioremapfree
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6f546720	drm_mm_get_block_generic
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x6fc30481	drm_mode_hsync
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x706ca0c1	drm_pci_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7485094f	drm_mode_detachmode_crtc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7677c5ec	drm_put_dev
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x76adb191	drm_idlelock_take
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x772bb8f3	drm_handle_vblank
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x77bed803	drm_mm_debug_table
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x784915eb	drm_mode_vrefresh
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x78c858d1	drm_gem_object_lookup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7becf9f2	drm_gem_object_handle_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7c1fd6c8	drm_mode_equal
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7c2d5fcf	drm_encoder_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7e168b59	drm_connector_property_set_value
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x7e5084df	drm_sysfs_hotplug_event
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x85de09f5	drm_mode_width
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8605e3a1	drm_cvt_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x87d6e7ef	drm_detect_hdmi_monitor
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x88b386ef	drm_get_resource_len
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8974745a	drm_vblank_count
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x8e42cc8c	drm_get_encoder_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x92c16cc6	drm_vblank_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9378793a	drm_ati_pcigart_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x972401dc	drm_mm_search_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9861eeeb	drm_core_get_reg_ofs
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x99151e45	drm_agp_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9ddca1a8	drm_master_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0x9f4e7ab0	drm_irq_uninstall
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa1eabd87	drm_mode_list_concat
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa2103063	drm_vblank_pre_modeset
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa3ae80b6	drm_gtf_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa6bb7fd7	drm_property_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa7595534	drm_free_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xa8c75304	drm_mmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaa26c372	drm_get_drawable_info
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaab41d5c	drm_debugfs_remove_files
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xaf29788e	drm_sman_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb48563c0	drm_mode_duplicate
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb4c9b849	drm_agp_acquire
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb54a2054	drm_mode_validate_size
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb8637274	drm_crtc_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xb9d0548b	drm_lock_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xba833dcb	drm_connector_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xba91d10c	drm_agp_unbind
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbbf2b426	drm_core_ioremap_wc
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbd3b675b	drm_mode_connector_detach_encoder
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xbd814e12	drm_gem_handle_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xc0f2833e	drm_i_have_hw_lock
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xc4b8afe9	drm_encoder_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xc9133a28	drm_do_probe_ddc_edid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xc9c3130e	drm_lock_take
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xca1cfd72	drm_vblank_off
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xcdf2eff4	drm_mode_height
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xce073267	drm_gem_vm_close
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd08fa3f0	drm_mode_set_crtcinfo
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd2d3d916	drm_mode_crtc_set_gamma_size
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3028e75	drm_sman_set_manager
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3a9aea7	drm_mode_object_find
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd3ffab51	drm_ht_remove
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd63d6819	drm_core_get_map_ofs
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd640cdff	drm_framebuffer_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd88ead46	drm_agp_bind_pages
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xd8bae3c3	drm_rmmap
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdafccb80	drm_poll
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdd3febe2	drm_gem_object_free
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xdd49095c	drm_ht_insert_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe1457735	drm_ht_remove_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe1fb5a95	drm_core_reclaim_buffers
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe206b96e	drm_mm_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe24a7b88	drm_ht_find_item
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe3044353	drm_get_connector_name
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe5bdce7e	drm_mode_debug_printmodeline
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe72e6436	drm_mm_put_block
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe7c35aa6	drm_mm_pre_get
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xe919dd5c	drm_sman_owner_clean
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xea1e8b69	drm_crtc_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xeeb29cd6	drm_connector_init
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xef10473b	drm_open
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xefa8e71c	drm_agp_bind
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf0df145e	drm_mode_connector_attach_encoder
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf1421d13	drm_mode_sort
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf2989f23	drm_property_destroy
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf41bb881	drm_addbufs_agp
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf42a2b26	drm_ht_create
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf4fca42c	drm_add_edid_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf794f325	drm_mode_prune_invalid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xf7f31003	drm_add_modes_noedid
+EXPORT_SYMBOL drivers/gpu/drm/drm 0xfdfbad19	drm_sman_alloc
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x0ab5fc79	drm_fb_helper_fill_fix
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x11b9960c	drm_helper_disable_unused_functions
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x1d1b3a62	drm_fb_helper_blank
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x2e7512c6	drm_crtc_helper_set_config
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x38920a2a	drm_fb_helper_pan_display
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x3c4916ca	drm_helper_initial_config
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x41a62e58	i2c_dp_aux_add_bus
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x61d1efc4	drm_helper_connector_dpms
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x67350db5	drm_fb_helper_init_crtc_count
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x6c872960	drm_helper_resume_force_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x7e5e8278	drm_helper_probe_connector_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x805ab19a	drm_fb_helper_fill_var
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x8774398f	drm_fb_helper_free
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x892306d7	drm_fb_helper_set_par
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0x9d251144	drm_fb_helper_panic
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xabcc908f	drm_helper_encoder_in_use
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb2244236	drm_helper_mode_fill_fb_struct
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb4a106be	drm_fb_helper_single_fb_probe
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xb57e01b1	drm_fb_helper_setcmap
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xbc67be7a	drm_crtc_helper_set_mode
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xc469c244	drm_fb_helper_restore
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xe031f461	drm_helper_crtc_in_use
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xe209e87a	drm_helper_probe_single_connector_modes
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xea48529b	drm_fb_helper_setcolreg
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xf901606d	drm_fb_helper_add_connector
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xfa2e6c68	drm_helper_hotplug_stage_two
+EXPORT_SYMBOL drivers/gpu/drm/drm_kms_helper 0xfc5a76b9	drm_fb_helper_check_var
+EXPORT_SYMBOL drivers/gpu/drm/radeon/radeon 0x05e43a65	radeonfb_remove
+EXPORT_SYMBOL drivers/gpu/drm/radeon/radeon 0x1ff71192	radeonfb_resize
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x01c99cb0	ttm_write_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x0453c040	ttm_bo_unreserve
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x06cf4036	ttm_bo_mem_space
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x0c694316	ttm_bo_unmap_virtual
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x0edfddc5	ttm_tt_set_placement_caching
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x17451077	ttm_bo_synccpu_write_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x18dd40e2	ttm_bo_init_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x1ba8c0ef	ttm_lock_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x274c09f9	ttm_object_file_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x2d673efd	ttm_vt_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x315ff0d0	ttm_bo_device_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x365feb2e	ttm_eu_reserve_buffers
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x3a09a2e5	ttm_base_object_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x3df73441	ttm_bo_device_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x3efcdef2	ttm_mem_global_free
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x42565e9c	ttm_bo_clean_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x42cf87d2	ttm_bo_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x441aacff	ttm_bo_move_memcpy
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x44409a13	ttm_global_item_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x4d5c7a58	ttm_tt_bind
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x56ab57fb	ttm_bo_synccpu_write_grab
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x56c42d22	ttm_suspend_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5860fedd	ttm_base_object_lookup
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5b11be9d	ttm_bo_kunmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5b2bb237	ttm_bo_move_accel_cleanup
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x5ca5cb47	ttm_global_item_ref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x61bdb34f	ttm_eu_fence_buffer_objects
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x6cea2439	ttm_tt_populate
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x75fa492d	ttm_bo_wait_unreserved
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x765cbc82	ttm_read_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x77ef7bc9	ttm_bo_swapout_all
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x7cdb21aa	ttm_bo_reserve
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x7f8879de	ttm_vt_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x808421c7	ttm_mem_global_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8386be4c	ttm_mem_global_alloc
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x86a4066d	ttm_eu_backoff_reservation
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8983bd6a	ttm_bo_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8a1b8ece	ttm_ref_object_base_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8db796d4	ttm_write_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x8f557b9e	ttm_bo_evict_mm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x93795148	ttm_object_device_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x97220c1c	ttm_object_device_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9b1ec083	ttm_bo_move_ttm
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9cc3391b	ttm_bo_validate
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0x9fb69ab0	ttm_fbdev_mmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xa0b66c78	ttm_agp_backend_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xac0e50d1	ttm_round_pot
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xac9a33e8	ttm_object_file_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xadf7b487	ttm_bo_mmap
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xaf82ada4	ttm_ref_object_add
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xb5cf2fe9	ttm_suspend_unlock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xb6f07537	ttm_bo_wait_cpu
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xbba2ecf9	ttm_read_lock
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xc2058ac0	ttm_io_prot
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xc64022a6	ttm_bo_global_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xda345beb	ttm_base_object_unref
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xedca56e3	ttm_mem_global_init
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xf7c7cce9	ttm_bo_wait
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xfcce372b	ttm_bo_global_release
+EXPORT_SYMBOL drivers/gpu/drm/ttm/ttm 0xffc77de0	ttm_bo_kmap
+EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0x0903c239	vid_from_reg
+EXPORT_SYMBOL drivers/hwmon/hwmon-vid 0xef1c781c	vid_which_vrm
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x15ce7b7f	i2c_bit_add_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-bit 0x87c3a550	i2c_bit_add_numbered_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xb54d8fa7	i2c_pca_add_numbered_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pca 0xe02ae50a	i2c_pca_add_bus
+EXPORT_SYMBOL drivers/i2c/algos/i2c-algo-pcf 0xdf1af1d4	i2c_pcf_add_bus
+EXPORT_SYMBOL drivers/i2c/busses/i2c-amd756 0xa75421b2	amd756_smbus
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x01758851	i2c_release_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x07de382a	i2c_smbus_write_byte_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x0b3b5f7e	i2c_smbus_write_i2c_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x0c15c1c7	i2c_put_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x1c6a352e	i2c_get_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x36147dfa	i2c_add_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x3ed33f5d	i2c_smbus_process_call
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x404c9123	i2c_master_recv
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x40dfe0f3	i2c_smbus_xfer
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x5786b291	i2c_del_adapter
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x580b71f0	i2c_smbus_read_byte
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x6182f9b8	i2c_master_send
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x6d7b09bd	i2c_verify_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x7e000aaf	i2c_transfer
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x7e2ea7d9	i2c_smbus_write_byte
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x87f3156d	i2c_del_driver
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x8bff114c	i2c_use_client
+EXPORT_SYMBOL drivers/i2c/i2c-core 0x93e6efd7	i2c_smbus_write_word_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xa4b0793e	i2c_clients_command
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xafbc7269	i2c_smbus_read_i2c_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xc68623ce	i2c_smbus_read_byte_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xcfb41b6d	i2c_register_driver
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xd20ae210	i2c_smbus_write_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xea299a46	i2c_smbus_read_block_data
+EXPORT_SYMBOL drivers/i2c/i2c-core 0xf6a9c034	i2c_smbus_read_word_data
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x00ef426b	hpsb_make_readpacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x00f22206	hpsb_register_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x04c40825	hpsb_packet_success
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x09e11df1	hpsb_iso_wake
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x0b234c4e	dma_prog_region_alloc
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x108e27dc	hpsb_protocol_class
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x11b84f1e	hpsb_iso_packet_sent
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x139b727c	hpsb_free_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x158ac548	dma_region_offset_to_bus
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x17a877b4	hpsb_make_lock64packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1a200e5a	csr1212_release_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x1de4695a	hpsb_free_tlabel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2234d608	hpsb_send_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x253926f2	dma_region_mmap
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x27932efd	hpsb_set_packet_complete_task
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x28d627ef	hpsb_update_config_rom
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x296f00a6	hpsb_iso_recv_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2a4cc36b	csr1212_attach_keyval_to_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2aaddfbe	hpsb_register_highlevel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ced4af9	hpsb_iso_xmit_start
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2e282816	hpsb_read
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ebf6e5a	dma_prog_region_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x2ed55575	hpsb_iso_packet_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x31f899cb	hpsb_iso_recv_set_channel_mask
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x37b402bf	hpsb_remove_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x3885776a	hpsb_iso_shutdown
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x49a95dc4	csr1212_get_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x4a9cd770	csr1212_parse_keyval
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x58356e96	hpsb_iso_xmit_sync
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x59b62d42	hpsb_node_write
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5cf6fe61	hpsb_read_cycle_timer
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5ebb2fb4	hpsb_iso_xmit_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x5f5fdd2f	csr1212_new_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x60a3b2e2	hpsb_make_lockpacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x62f5a035	hpsb_selfid_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x634f135f	hpsb_unregister_protocol
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x672ad148	dma_region_sync_for_device
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x68b51e47	csr1212_read
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x6a640651	hpsb_allocate_and_register_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x76bc1a5c	dma_region_free
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7769a2ff	hpsb_iso_recv_release_packets
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7b1e5adb	hpsb_node_fill_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x7d23de2c	hpsb_iso_n_ready
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8879f8f0	dma_region_sync_for_cpu
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8adc1fab	hpsb_selfid_complete
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x8ec2b312	dma_region_alloc
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9477e91a	hpsb_make_streampacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9b1f9876	hpsb_iso_xmit_queue_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0x9e6239d8	hpsb_write
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa3bd75ba	hpsb_iso_recv_unlisten_channel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa60def54	hpsb_make_writepacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xa8518b2d	hpsb_destroy_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaa313591	hpsb_set_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaed49919	hpsb_bus_reset
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaef57bb5	csr1212_detach_keyval_from_directory
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaf55ab4f	hpsb_create_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xaf868c6c	hpsb_reset_bus
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb1e8f461	hpsb_add_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb2900ba5	hpsb_get_hostinfo
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xb567965c	hpsb_alloc_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc27ba749	hpsb_iso_recv_start
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xc76492cf	hpsb_set_hostinfo_key
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xcd9e772b	dma_prog_region_free
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd0525bd0	__hpsb_register_protocol
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd33b5b80	hpsb_unregister_addrspace
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd3633cc3	hpsb_get_hostinfo_bykey
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd879f906	hpsb_packet_sent
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xd8e1f9bb	hpsb_iso_recv_flush
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xda63c8eb	hpsb_lock
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xdec84b71	hpsb_get_tlabel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe157c56c	hpsb_unregister_highlevel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe227eec6	hpsb_make_phypacket
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xe2f6e1c7	hpsb_resume_host
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xea4152ff	dma_region_init
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xed8c4411	hpsb_packet_received
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf0cca345	hpsb_iso_recv_listen_channel
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf450c5c1	hpsb_alloc_packet
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xf9dc9455	hpsb_iso_stop
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfba57f51	hpsb_speedto_str
+EXPORT_SYMBOL drivers/ieee1394/ieee1394 0xfe467790	hpsb_update_config_rom_image
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x1d5aeebc	ohci1394_init_iso_tasklet
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0x5a72001a	ohci1394_register_iso_tasklet
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xb4939974	ohci1394_stop_context
+EXPORT_SYMBOL drivers/ieee1394/ohci1394 0xd74ee87d	ohci1394_unregister_iso_tasklet
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x274038db	rdma_resolve_ip
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x5eb722d8	rdma_copy_addr
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0x8a721ed9	rdma_addr_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xc91bb9d3	rdma_addr_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xcb8d01b8	rdma_addr_cancel
+EXPORT_SYMBOL drivers/infiniband/core/ib_addr 0xfa6809a5	rdma_translate_ip
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x124cd411	ib_send_cm_dreq
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x18f4f116	ib_cm_listen
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x2e9f0705	cm_class
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x3877b939	ib_send_cm_rep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x3e32a738	ib_send_cm_sidr_rep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x4052682d	ib_send_cm_req
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x46644a7b	ib_send_cm_sidr_req
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x49161b03	ib_send_cm_rtu
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x6682a95f	ib_send_cm_mra
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x66aa8e94	ib_cm_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x7b3ba003	ib_cm_notify
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x8abb7ef0	ib_send_cm_apr
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x9029928d	ib_send_cm_drep
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0x90b7cc5a	ib_send_cm_rej
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xbaeeffaf	ib_create_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xe7279099	ib_destroy_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/ib_cm 0xe7412fb4	ib_send_cm_lap
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x03492a2e	ib_detach_mcast
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x041c93e9	ib_alloc_fast_reg_page_list
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06830b9a	ib_pack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x06a9e001	ib_dealloc_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x07cca55a	ib_get_dma_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x09f781d1	ib_create_ah_from_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0aa9d139	ib_query_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0af72c35	ib_register_event_handler
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0d56a44b	ib_alloc_fast_reg_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x0ecddb10	ib_dispatch_event
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x175534c2	ib_modify_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e15ad39	ib_fmr_pool_unmap
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x1e491a04	ib_unmap_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x29029dec	ib_flush_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x2d12c59e	ib_create_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x34ee0ba5	ib_find_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x398b056f	ib_modify_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3f7567fd	ib_rate_to_mult
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3fe94b4d	ib_dereg_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3ff548ea	ib_query_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x3ff7dcbc	ib_destroy_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x40878b33	ib_modify_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x4a6b356c	ib_rereg_phys_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x500d7acb	ib_get_cached_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x57158222	ib_alloc_pd
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5ba43c2c	ib_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x5ba87116	ib_create_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x62c69f4e	ib_dealloc_pd
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6817399e	ib_resize_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x6d79deae	ib_init_ah_from_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7b2c0b61	ib_modify_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7bafd02c	ib_query_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7e064300	ib_fmr_pool_map_phys
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x7e34b8b1	ib_query_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8592ac3a	ib_umem_page_count
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8640eaeb	ib_modify_qp_is_ok
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x87b614d8	ib_ud_header_pack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8b688e79	ib_create_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8dd6bff9	ib_query_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x8e08dad4	ib_unregister_event_handler
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x95991a77	ib_umem_get
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x96ce6c46	rdma_node_get_transport
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9d804fa1	mult_to_ib_rate
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9dbecf44	ib_dealloc_mw
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0x9fe55e9c	ib_destroy_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa1096aaf	ib_modify_port
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa1635f70	ib_attach_mcast
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xa3fca328	ib_find_cached_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xab778466	ib_set_client_data
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb020ff2e	ib_alloc_fmr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xb7ad6ea7	ib_dealloc_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xbfd914e8	ib_alloc_mw
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc10bd64c	ib_create_ah
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc514f931	ib_destroy_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xc5445b10	ib_query_port
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xce911578	ib_destroy_cq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd17ba9d1	ib_ud_header_init
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd5c1d3e8	ib_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd81488a1	ib_register_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xd8c99c59	ib_get_cached_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdcc6ef60	ib_find_cached_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdd30f1e0	ib_create_fmr_pool
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xdece5d0c	ib_query_pkey
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe58c55ee	ib_find_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe7472729	ib_reg_phys_mr
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe7f4de31	ib_alloc_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xe87eaa13	ib_query_gid
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xedeb5e55	ib_umem_release
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xefdb0570	ib_destroy_srq
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xeffe0e48	ib_modify_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf124864b	ib_free_fast_reg_page_list
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf16f67d6	ib_get_cached_lmc
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf36498b9	ib_ud_header_unpack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf729ab76	ib_unregister_device
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xf96fc9de	ib_unpack
+EXPORT_SYMBOL drivers/infiniband/core/ib_core 0xfd2805f3	ib_get_client_data
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x17bf23da	ib_register_mad_snoop
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x1bd20a64	ib_post_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x504cf395	ib_process_mad_wc
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x55ae4fdb	ib_register_mad_agent
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x5a4bf9b5	ib_get_rmpp_segment
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x683f4dce	ib_cancel_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6ef787ed	ib_response_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x6f077fcf	ib_get_mad_data_offset
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x73832acd	ib_unregister_mad_agent
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0x7b5d4b7a	ib_is_mad_class_rmpp
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xda99fb8f	ib_free_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe7323f16	ib_free_recv_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xe93c1a2f	ib_create_send_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xeca4d795	ib_redirect_mad_qp
+EXPORT_SYMBOL drivers/infiniband/core/ib_mad 0xf2fbfed4	ib_modify_mad
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x0eb803b3	ib_init_ah_from_path
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x576fdbac	ib_sa_free_multicast
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x5b47a00c	ib_sa_cancel_query
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x677f0b62	ib_sa_get_mcmember_rec
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x798799bb	ib_sa_service_rec_query
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x7f690ca3	ib_init_ah_from_mcmember
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x85b8c973	ib_sa_path_rec_get
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0x9c56fd34	ib_sa_unregister_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xa0a7a4f9	ib_sa_join_multicast
+EXPORT_SYMBOL drivers/infiniband/core/ib_sa 0xf520d09e	ib_sa_register_client
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x02f847bc	ib_copy_path_rec_from_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x07cf5a51	ib_copy_ah_attr_to_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x18382f6a	ib_copy_path_rec_to_user
+EXPORT_SYMBOL drivers/infiniband/core/ib_uverbs 0x184f3575	ib_copy_qp_attr_to_user
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x46576b81	iw_cm_listen
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x7babca40	iw_cm_connect
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x90c016f7	iw_cm_accept
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0x957a480c	iw_cm_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xa609c1dc	iw_cm_disconnect
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xc545aa33	iw_destroy_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xc657bccf	iw_cm_reject
+EXPORT_SYMBOL drivers/infiniband/core/iw_cm 0xe6b3d7c5	iw_create_cm_id
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x28cc5bb2	rdma_notify
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x29592cfb	rdma_listen
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x2e6c3748	rdma_bind_addr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x304d50fe	rdma_leave_multicast
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x3ebaec5a	rdma_connect
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x4916ef91	rdma_set_ib_paths
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x61e59bf1	rdma_resolve_route
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x63d6e0ae	rdma_set_service_type
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x6db3fcfb	rdma_resolve_addr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x70c84826	rdma_join_multicast
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x987a823f	rdma_create_qp
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0x9990990c	rdma_reject
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xb46bcb95	rdma_accept
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd833b872	rdma_create_id
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xd925fc04	rdma_destroy_id
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xe058ffb0	rdma_init_qp_attr
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xf58cf369	rdma_disconnect
+EXPORT_SYMBOL drivers/infiniband/core/rdma_cm 0xfaa52033	rdma_destroy_qp
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x11b7bd78	gameport_open
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x2a3197fa	gameport_stop_polling
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x2c3c181d	__gameport_register_driver
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x5cc434ae	gameport_unregister_driver
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x6756b108	gameport_close
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x711e43dc	gameport_start_polling
+EXPORT_SYMBOL drivers/input/gameport/gameport 0x8a834957	gameport_unregister_port
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xa4e112bf	gameport_set_phys
+EXPORT_SYMBOL drivers/input/gameport/gameport 0xb28d1cfd	__gameport_register_port
+EXPORT_SYMBOL drivers/input/input-polldev 0x141d753c	input_free_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0x416701ff	input_register_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0x6919bc9e	input_allocate_polled_device
+EXPORT_SYMBOL drivers/input/input-polldev 0xa251bd53	input_unregister_polled_device
+EXPORT_SYMBOL drivers/md/dm-log 0x5e7bf01c	dm_dirty_log_type_register
+EXPORT_SYMBOL drivers/md/dm-log 0xc8b657a6	dm_dirty_log_type_unregister
+EXPORT_SYMBOL drivers/md/dm-log 0xd4f32b8e	dm_dirty_log_destroy
+EXPORT_SYMBOL drivers/md/dm-log 0xda65f9b9	dm_dirty_log_create
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x52adcd35	dm_exception_store_create
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x538d1c24	dm_exception_store_type_unregister
+EXPORT_SYMBOL drivers/md/dm-snapshot 0x904d1f08	dm_exception_store_destroy
+EXPORT_SYMBOL drivers/md/dm-snapshot 0xf0e49c14	dm_exception_store_type_register
+EXPORT_SYMBOL drivers/md/md-mod 0x1ad360e3	bitmap_start_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x1c0829b7	bitmap_end_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x251901d1	bitmap_endwrite
+EXPORT_SYMBOL drivers/md/md-mod 0x3293f829	md_integrity_register
+EXPORT_SYMBOL drivers/md/md-mod 0x43e966fe	bitmap_cond_end_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x48326f81	md_error
+EXPORT_SYMBOL drivers/md/md-mod 0x4fff1c50	md_write_start
+EXPORT_SYMBOL drivers/md/md-mod 0x651aa9ba	bitmap_startwrite
+EXPORT_SYMBOL drivers/md/md-mod 0x677e0f66	md_check_recovery
+EXPORT_SYMBOL drivers/md/md-mod 0x67a1e14f	md_wakeup_thread
+EXPORT_SYMBOL drivers/md/md-mod 0x7124987e	mddev_congested
+EXPORT_SYMBOL drivers/md/md-mod 0x7b81a2b4	bitmap_unplug
+EXPORT_SYMBOL drivers/md/md-mod 0x7ec222ae	md_register_thread
+EXPORT_SYMBOL drivers/md/md-mod 0x811615ca	md_check_no_bitmap
+EXPORT_SYMBOL drivers/md/md-mod 0x858892ec	bitmap_close_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x898cef16	md_done_sync
+EXPORT_SYMBOL drivers/md/md-mod 0x92546271	md_unregister_thread
+EXPORT_SYMBOL drivers/md/md-mod 0x995bd5a0	register_md_personality
+EXPORT_SYMBOL drivers/md/md-mod 0xa7406f52	unregister_md_personality
+EXPORT_SYMBOL drivers/md/md-mod 0xc43418e1	md_wait_for_blocked_rdev
+EXPORT_SYMBOL drivers/md/md-mod 0xc80118e8	md_integrity_add_rdev
+EXPORT_SYMBOL drivers/md/md-mod 0xe248e5e3	md_write_end
+EXPORT_SYMBOL drivers/md/md-mod 0xe59e5ebf	md_set_array_sectors
+EXPORT_SYMBOL drivers/md/raid6_pq 0x0bd662f6	raid6_gfmul
+EXPORT_SYMBOL drivers/md/raid6_pq 0x15fe0cd3	raid6_gfexp
+EXPORT_SYMBOL drivers/md/raid6_pq 0x5ba93f9d	raid6_gfinv
+EXPORT_SYMBOL drivers/md/raid6_pq 0xb0d904b7	raid6_empty_zero_page
+EXPORT_SYMBOL drivers/md/raid6_pq 0xce45a6f1	raid6_gfexi
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x0197b44e	mpt_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x14492cd7	mpt_raid_phys_disk_pg1
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x144f4155	mpt_free_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x19d67510	mpt_detach
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x2cff1325	mpt_findImVolumes
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x42a3ee2d	mpt_attach
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4526289b	mpt_event_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x4a0733bb	mpt_put_msg_frame_hi_pri
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x502108d0	mpt_fwfault_debug
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6bb8251f	mpt_clear_taskmgmt_in_progress_flag
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6cb42f7f	mpt_config
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x6d905d06	mpt_halt_firmware
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7425b411	mpt_raid_phys_disk_pg0
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x7ce019c9	mpt_raid_phys_disk_get_num_paths
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x87968a61	mpt_print_ioc_summary
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x8e61b64e	mpt_get_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x944fd931	mpt_suspend
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0x964d84ae	mpt_alloc_fw_memory
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xad58f745	mpt_GetIocState
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xb5b17326	mpt_free_fw_memory
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc0e69f82	mpt_device_driver_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc2aa198d	mpt_HardResetHandler
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xc47c22e8	mpt_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xcfee3926	mpt_verify_adapter
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd05992c8	mpt_resume
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xd9a92a75	mpt_reset_deregister
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdc068187	mptbase_sas_persist_operation
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xdd805159	ioc_list
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xe9a55fed	mpt_device_driver_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xead350fb	mpt_put_msg_frame
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xec3dfcba	mpt_send_handshake_request
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf2e56d13	mpt_set_taskmgmt_in_progress_flag
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xf9cf8ff2	mpt_event_register
+EXPORT_SYMBOL drivers/message/fusion/mptbase 0xfd2ee882	mpt_reset_register
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x01549a9a	mptscsih_get_scsi_lookup
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x05645d6e	mptscsih_suspend
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x0e09f0a4	mptscsih_scandv_complete
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x206db511	mptscsih_remove
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x3daf4eb8	mptscsih_slave_destroy
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x3dc384b6	mptscsih_IssueTaskMgmt
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x45b6a369	mptscsih_qcmd
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x4d96fc19	mptscsih_info
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x52442143	mptscsih_ioc_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x5bd5d0e1	mptscsih_taskmgmt_response_code
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6718d4a1	mptscsih_proc_info
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6f9afa8c	mptscsih_io_done
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x6ff99330	mptscsih_event_process
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x85f436c2	mptscsih_is_phys_disk
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x8a55517c	mptscsih_host_attrs
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x8be164bf	mptscsih_slave_configure
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x8ce7a6cc	mptscsih_shutdown
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x93e3e846	mptscsih_raid_id_to_num
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0x98494c5a	mptscsih_resume
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xa531d161	mptscsih_bus_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xa9573cef	mptscsih_bios_param
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xd2fa013a	mptscsih_taskmgmt_complete
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe18a878a	mptscsih_dev_reset
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe2611b4d	mptscsih_change_queue_depth
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xe408877b	mptscsih_abort
+EXPORT_SYMBOL drivers/message/fusion/mptscsih 0xefee178e	mptscsih_host_reset
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x0027d62b	i2o_parm_table_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x016e962c	i2o_msg_post_wait_mem
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2a843bef	i2o_dump_message
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2d9a9b14	i2o_cntxt_list_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x2de14019	i2o_status_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x362db287	i2o_find_iop
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x392fec0a	i2o_cntxt_list_get_ptr
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x39ff7c94	i2o_driver_notify_device_add_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x433ad2ce	i2o_iop_find_device
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x637932ab	i2o_driver_notify_controller_add_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x66b54a1d	i2o_driver_notify_controller_remove_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x751e345c	i2o_msg_get_wait
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x798da892	i2o_device_claim_release
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x7bfba033	i2o_driver_unregister
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x89d6e597	i2o_device_claim
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x8eccec44	i2o_driver_notify_device_remove_all
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x8fbd8c2d	i2o_driver_register
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0x9c1426f3	i2o_event_register
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xafa55b4e	i2o_cntxt_list_remove
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb16030c1	i2o_parm_field_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xb4c00dcf	i2o_controllers
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xd7f656c1	i2o_parm_issue
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf36571b2	i2o_exec_lct_get
+EXPORT_SYMBOL drivers/message/i2o/i2o_core 0xf666e881	i2o_cntxt_list_add
+EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x27bc7e95	pasic3_read_register
+EXPORT_SYMBOL drivers/mfd/htc-pasic3 0x49f2771c	pasic3_write_register
+EXPORT_SYMBOL drivers/mfd/mfd-core 0xc4f06d41	mfd_add_devices
+EXPORT_SYMBOL drivers/mfd/mfd-core 0xf2435a03	mfd_remove_devices
+EXPORT_SYMBOL drivers/mfd/tps65010 0x02d4ad0f	tps65013_set_low_pwr
+EXPORT_SYMBOL drivers/mfd/tps65010 0x28485130	tps65010_config_vregs1
+EXPORT_SYMBOL drivers/mfd/tps65010 0x33739de7	tps65010_set_vib
+EXPORT_SYMBOL drivers/mfd/tps65010 0x9fd44c69	tps65010_set_led
+EXPORT_SYMBOL drivers/mfd/tps65010 0xb14080cc	tps65010_set_low_pwr
+EXPORT_SYMBOL drivers/mfd/tps65010 0xd5bb106d	tps65010_set_vbus_draw
+EXPORT_SYMBOL drivers/mfd/tps65010 0xe99b3f36	tps65010_set_gpio_out_value
+EXPORT_SYMBOL drivers/misc/ioc4 0x3ef9cc48	ioc4_unregister_submodule
+EXPORT_SYMBOL drivers/misc/ioc4 0xbd37f77a	ioc4_register_submodule
+EXPORT_SYMBOL drivers/misc/tifm_core 0x09546442	tifm_unmap_sg
+EXPORT_SYMBOL drivers/misc/tifm_core 0x15ef914e	tifm_map_sg
+EXPORT_SYMBOL drivers/misc/tifm_core 0x167a7b53	tifm_register_driver
+EXPORT_SYMBOL drivers/misc/tifm_core 0x2a84dddc	tifm_unregister_driver
+EXPORT_SYMBOL drivers/misc/tifm_core 0x2a98aa96	tifm_remove_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0x4228ac8b	tifm_add_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0x53dd7fb8	tifm_has_ms_pif
+EXPORT_SYMBOL drivers/misc/tifm_core 0x6e8c7f2f	tifm_free_adapter
+EXPORT_SYMBOL drivers/misc/tifm_core 0x86210098	tifm_free_device
+EXPORT_SYMBOL drivers/misc/tifm_core 0xaa529f25	tifm_eject
+EXPORT_SYMBOL drivers/misc/tifm_core 0xafbf2848	tifm_alloc_device
+EXPORT_SYMBOL drivers/misc/tifm_core 0xcd153284	tifm_queue_work
+EXPORT_SYMBOL drivers/misc/tifm_core 0xdeb41939	tifm_alloc_adapter
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x71992368	cfi_read_pri
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0x978cf6c2	cfi_varsize_frob
+EXPORT_SYMBOL drivers/mtd/chips/cfi_util 0xe0a0158d	cfi_fixup
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x165e03b4	register_mtd_chip_driver
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x374e8a5e	unregister_mtd_chip_driver
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0x75beff0a	do_map_probe
+EXPORT_SYMBOL drivers/mtd/chips/chipreg 0xe89c50b4	map_destroy
+EXPORT_SYMBOL drivers/mtd/chips/gen_probe 0x759f95d3	mtd_do_chip_probe
+EXPORT_SYMBOL drivers/mtd/maps/map_funcs 0x80758ab8	simple_map_init
+EXPORT_SYMBOL drivers/mtd/mtd 0x2772ba16	del_mtd_partitions
+EXPORT_SYMBOL drivers/mtd/mtd 0xaf8e24b0	add_mtd_partitions
+EXPORT_SYMBOL drivers/mtd/mtdconcat 0x3ef26749	mtd_concat_create
+EXPORT_SYMBOL drivers/mtd/mtdconcat 0x4c7a1c01	mtd_concat_destroy
+EXPORT_SYMBOL drivers/mtd/nand/nand 0x09e46359	nand_default_bbt
+EXPORT_SYMBOL drivers/mtd/nand/nand 0x5778b67d	nand_scan_bbt
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0xb4b94377	__nand_correct_data
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0xd9ce5ef6	nand_calculate_ecc
+EXPORT_SYMBOL drivers/mtd/nand/nand_ecc 0xf4491c07	nand_correct_data
+EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0x836bdb72	nand_flash_ids
+EXPORT_SYMBOL drivers/mtd/nand/nand_ids 0xa336feb7	nand_manuf_ids
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x12b5508c	onenand_addr
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0x2739ffd3	flexonenand_region
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xa9c3d95a	onenand_default_bbt
+EXPORT_SYMBOL drivers/mtd/onenand/onenand 0xf5cb7b4a	onenand_scan_bbt
+EXPORT_SYMBOL drivers/net/8390 0x0dcc78a2	ei_get_stats
+EXPORT_SYMBOL drivers/net/8390 0x33fd24b0	NS8390_init
+EXPORT_SYMBOL drivers/net/8390 0x5733dcfc	ei_poll
+EXPORT_SYMBOL drivers/net/8390 0x5b5979e9	ei_netdev_ops
+EXPORT_SYMBOL drivers/net/8390 0x684f3d4b	ei_open
+EXPORT_SYMBOL drivers/net/8390 0x8511df2b	ei_tx_timeout
+EXPORT_SYMBOL drivers/net/8390 0x855941b7	ei_close
+EXPORT_SYMBOL drivers/net/8390 0x8fc1356b	ei_set_multicast_list
+EXPORT_SYMBOL drivers/net/8390 0xa8f06791	__alloc_ei_netdev
+EXPORT_SYMBOL drivers/net/8390 0xdd365790	ei_interrupt
+EXPORT_SYMBOL drivers/net/8390 0xee55fa11	ei_start_xmit
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x0fa38789	alloc_arcdev
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x23f86078	arcnet_interrupt
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x2f3bc9f1	arc_proto_map
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x5d89db6c	arc_raw_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x6534792a	arcnet_debug
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x66cf7620	arc_bcast_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0x7fac3449	arc_proto_default
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xaeb77416	arcnet_send_packet
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xc80e7d9f	arcnet_unregister_proto
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xcd912472	arcnet_open
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xcf67da48	arcnet_timeout
+EXPORT_SYMBOL drivers/net/arcnet/arcnet 0xfb250426	arcnet_close
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0x02828f1c	com20020_netdev_ops
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0xcffaa518	com20020_check
+EXPORT_SYMBOL drivers/net/arcnet/com20020 0xe998a512	com20020_found
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x1efd0539	t3_l2t_get
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x34bd4c54	cxgb3_ofld_send
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x42c4bf6c	cxgb3_queue_tid_release
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x5732ece7	cxgb3_alloc_stid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x579c8c79	t3_l2e_free
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x5da456b8	t3_l2t_send_slow
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8a2a2d21	cxgb3_free_atid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8cda8fcf	cxgb3_free_stid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x8cddc55c	cxgb3_remove_tid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x90be80b0	cxgb3_alloc_atid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0x90d1ffb0	t3_register_cpl_handler
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xb4b7d78b	cxgb3_register_client
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc03e2fc0	cxgb3_unregister_client
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xc8d0d843	cxgb3_insert_tid
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xd70dbe9f	t3_l2t_send_event
+EXPORT_SYMBOL drivers/net/cxgb3/cxgb3 0xe2a22239	dev2t3cdev
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0x2bf4f93d	hdlcdrv_receiver
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xa48511ec	hdlcdrv_register
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xbedd3fd7	hdlcdrv_unregister
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xd84ec94a	hdlcdrv_arbitrate
+EXPORT_SYMBOL drivers/net/hamradio/hdlcdrv 0xead2b079	hdlcdrv_transmitter
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x4ade2ff8	sirdev_get_instance
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x587a0a5b	sirdev_raw_write
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x59f19ebc	sirdev_receive
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x977c713a	irda_register_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0x9b07842a	sirdev_write_complete
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xaab5b72d	sirdev_set_dtr_rts
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xc322997a	sirdev_set_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xc976dbee	irda_unregister_dongle
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf8c903a7	sirdev_put_instance
+EXPORT_SYMBOL drivers/net/irda/sir-dev 0xf95fe357	sirdev_raw_read
+EXPORT_SYMBOL drivers/net/mdio 0x0f934475	mdio45_ethtool_gset_npage
+EXPORT_SYMBOL drivers/net/mdio 0x22bce513	mdio_mii_ioctl
+EXPORT_SYMBOL drivers/net/mdio 0x43e4defc	mdio45_nway_restart
+EXPORT_SYMBOL drivers/net/mdio 0x7577f992	mdio_set_flag
+EXPORT_SYMBOL drivers/net/mdio 0xa1a29548	mdio45_probe
+EXPORT_SYMBOL drivers/net/mdio 0xb34a7575	mdio45_ethtool_spauseparam_an
+EXPORT_SYMBOL drivers/net/mdio 0xc6b1163f	mdio45_links_ok
+EXPORT_SYMBOL drivers/net/mii 0x3cf542d2	mii_nway_restart
+EXPORT_SYMBOL drivers/net/mii 0x45e763f5	mii_check_media
+EXPORT_SYMBOL drivers/net/mii 0x4671cfa8	generic_mii_ioctl
+EXPORT_SYMBOL drivers/net/mii 0x71826929	mii_check_link
+EXPORT_SYMBOL drivers/net/mii 0x8abf5574	mii_link_ok
+EXPORT_SYMBOL drivers/net/mii 0xc6f48c5e	mii_ethtool_gset
+EXPORT_SYMBOL drivers/net/mii 0xc7a9fa8c	mii_ethtool_sset
+EXPORT_SYMBOL drivers/net/mii 0xc7b4fc80	mii_check_gmii_support
+EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x292162f1	free_mdio_bitbang
+EXPORT_SYMBOL drivers/net/phy/mdio-bitbang 0x3d7b3e84	alloc_mdio_bitbang
+EXPORT_SYMBOL drivers/net/pppox 0x056b8958	pppox_ioctl
+EXPORT_SYMBOL drivers/net/pppox 0x2b86c4a9	pppox_unbind_sock
+EXPORT_SYMBOL drivers/net/pppox 0xc01781ae	register_pppox_proto
+EXPORT_SYMBOL drivers/net/pppox 0xe0ff7a18	unregister_pppox_proto
+EXPORT_SYMBOL drivers/net/sungem_phy 0x5e38c1e1	mii_phy_probe
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x4d120085	tms380tr_close
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0x943f1be5	tmsdev_init
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd0250661	tms380tr_netdev_ops
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd2328794	tms380tr_wait
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xd49af46e	tms380tr_interrupt
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xe54cb22d	tmsdev_term
+EXPORT_SYMBOL drivers/net/tokenring/tms380tr 0xf45f8f79	tms380tr_open
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x38da4725	cycx_intr
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x62be23ea	cycx_setup
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x66a4c4e6	cycx_down
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0x968458a6	cycx_peek
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xb6f383de	cycx_poke
+EXPORT_SYMBOL drivers/net/wan/cycx_drv 0xfe7cd576	cycx_exec
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x323bf6e9	hdlc_ioctl
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x34cda33b	unregister_hdlc_device
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x5275da51	unregister_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x641559dc	register_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x67fa5664	attach_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x6c862018	hdlc_close
+EXPORT_SYMBOL drivers/net/wan/hdlc 0x7409bb8e	hdlc_change_mtu
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xa94ab215	hdlc_open
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xb5e64d08	alloc_hdlcdev
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xe7e3ca6b	detach_hdlc_protocol
+EXPORT_SYMBOL drivers/net/wan/hdlc 0xf99b00c3	hdlc_start_xmit
+EXPORT_SYMBOL drivers/parport/parport 0x077cae7f	parport_ieee1284_epp_read_addr
+EXPORT_SYMBOL drivers/parport/parport 0x0b81c69f	parport_release
+EXPORT_SYMBOL drivers/parport/parport 0x12837ddf	parport_get_port
+EXPORT_SYMBOL drivers/parport/parport 0x2239759a	parport_find_base
+EXPORT_SYMBOL drivers/parport/parport 0x250d65c4	parport_set_timeout
+EXPORT_SYMBOL drivers/parport/parport 0x342d75e2	parport_ieee1284_write_compat
+EXPORT_SYMBOL drivers/parport/parport 0x3bd9c6f9	parport_ieee1284_epp_write_data
+EXPORT_SYMBOL drivers/parport/parport 0x3dcd4129	parport_unregister_device
+EXPORT_SYMBOL drivers/parport/parport 0x3eb29c3e	parport_ieee1284_epp_read_data
+EXPORT_SYMBOL drivers/parport/parport 0x43e4b7eb	parport_write
+EXPORT_SYMBOL drivers/parport/parport 0x44fff96a	parport_ieee1284_read_byte
+EXPORT_SYMBOL drivers/parport/parport 0x48037e05	parport_put_port
+EXPORT_SYMBOL drivers/parport/parport 0x4d2a941b	parport_ieee1284_interrupt
+EXPORT_SYMBOL drivers/parport/parport 0x5901f249	parport_ieee1284_ecp_read_data
+EXPORT_SYMBOL drivers/parport/parport 0x5fc31a5f	parport_find_number
+EXPORT_SYMBOL drivers/parport/parport 0x6acb4bbd	parport_remove_port
+EXPORT_SYMBOL drivers/parport/parport 0x718fdaba	parport_register_device
+EXPORT_SYMBOL drivers/parport/parport 0x73b38e0d	parport_ieee1284_ecp_write_addr
+EXPORT_SYMBOL drivers/parport/parport 0x947c96eb	parport_ieee1284_read_nibble
+EXPORT_SYMBOL drivers/parport/parport 0x9914b3fc	parport_ieee1284_epp_write_addr
+EXPORT_SYMBOL drivers/parport/parport 0x9d5eff70	parport_irq_handler
+EXPORT_SYMBOL drivers/parport/parport 0xa02a98c9	parport_read
+EXPORT_SYMBOL drivers/parport/parport 0xa2a5f153	parport_wait_peripheral
+EXPORT_SYMBOL drivers/parport/parport 0xa9aaf470	parport_announce_port
+EXPORT_SYMBOL drivers/parport/parport 0xbcfd74bd	parport_claim_or_block
+EXPORT_SYMBOL drivers/parport/parport 0xd17efb08	parport_ieee1284_ecp_write_data
+EXPORT_SYMBOL drivers/parport/parport 0xd27341ef	parport_register_driver
+EXPORT_SYMBOL drivers/parport/parport 0xde0ab984	parport_unregister_driver
+EXPORT_SYMBOL drivers/parport/parport 0xe5e937c7	parport_wait_event
+EXPORT_SYMBOL drivers/parport/parport 0xe807c490	parport_negotiate
+EXPORT_SYMBOL drivers/parport/parport 0xf29571bb	parport_claim
+EXPORT_SYMBOL drivers/parport/parport 0xf482df34	parport_register_port
+EXPORT_SYMBOL drivers/parport/parport_pc 0x0f701423	parport_pc_unregister_port
+EXPORT_SYMBOL drivers/parport/parport_pc 0xae995fb0	parport_pc_probe_port
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x366a6501	pcmcia_disable_device
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x3b83747b	pcmcia_request_irq
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x3bf0c2a5	pcmcia_get_mem_page
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x44246fb0	pcmcia_modify_configuration
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x4fd033a0	pcmcia_error_func
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x53d80f84	pcmcia_dev_present
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x67411a0b	pcmcia_access_configuration_register
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0x8abfeb9a	pcmcia_request_configuration
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa7982b8f	pcmcia_map_mem_page
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xa8abea5f	pcmcia_release_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xacd45b58	pcmcia_register_driver
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xca49ff1c	pcmcia_unregister_driver
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xcabf8b33	pcmcia_request_io
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xde9070ee	pcmcia_loop_config
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xeff778e2	pcmcia_request_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf0a25e12	pcmcia_error_ret
+EXPORT_SYMBOL drivers/pcmcia/pcmcia 0xf56e710f	pcmcia_get_window
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x008c5815	pccard_static_ops
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x0d0c0193	pcmcia_reset_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x1ae83286	pcmcia_socket_dev_suspend
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x212db8d2	pcmcia_socket_list
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x256fa53e	pcmcia_insert_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x27f5ef12	pcmcia_get_socket_by_nr
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x2ed563e5	pcmcia_find_mem_region
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x31f068a5	pccard_get_first_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x3ce85206	pcmcia_write_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x3d742bb1	pcmcia_put_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x3e55c63c	pcmcia_validate_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x47afd377	pcmcia_socket_class
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x530b6e21	pcmcia_register_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x53934f74	pcmcia_unregister_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x5f42a69d	pcmcia_socket_list_rwsem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x62f7dca7	pccard_register_pcmcia
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x6f3559ba	pcmcia_resume_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x740dde82	pcmcia_socket_dev_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x744d2e9a	pccard_validate_cis
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0x7c404117	pcmcia_eject_card
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa190a2e1	pcmcia_parse_events
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xa99c0714	pccard_get_next_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xab06c33b	destroy_cis_cache
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xae8140d0	pccard_get_tuple_data
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc02ef2c8	pcmcia_parse_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc2b695b6	pcmcia_replace_cis
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xc5c1c02f	pcmcia_read_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xceaa1fbc	pccard_read_tuple
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xcf97f3bd	dead_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xd7eacebc	release_cis_mem
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xdaa723ce	pcmcia_socket_dev_late_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xdf7e0ba4	pcmcia_get_socket
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xeca62665	pcmcia_find_io_region
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xedf43689	pcmcia_adjust_io_region
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xee7ce35f	pcmcia_socket_dev_early_resume
+EXPORT_SYMBOL drivers/pcmcia/pcmcia_core 0xf83fc726	pcmcia_suspend_card
+EXPORT_SYMBOL drivers/pcmcia/rsrc_nonstatic 0x0d50ef54	pccard_nonstatic_ops
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x2250c66e	mraid_mm_adapter_app_handle
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x512c956d	mraid_mm_unregister_adp
+EXPORT_SYMBOL drivers/scsi/megaraid/megaraid_mm 0x9750a4ad	mraid_mm_register_adp
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x3fd8cd71	qlogicfas408_detect
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x4fabe6c2	qlogicfas408_biosparam
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x57cfb687	qlogicfas408_bus_reset
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x6db1fa63	qlogicfas408_abort
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x772b7eff	qlogicfas408_disable_ints
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x7955c067	qlogicfas408_info
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0x9e423179	qlogicfas408_queuecommand
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xdc310b12	qlogicfas408_ihandl
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xe76b3b20	qlogicfas408_get_chip_type
+EXPORT_SYMBOL drivers/scsi/qlogicfas408 0xf2b95199	qlogicfas408_setup
+EXPORT_SYMBOL drivers/scsi/raid_class 0x0310d374	raid_component_add
+EXPORT_SYMBOL drivers/scsi/raid_class 0xc59c93aa	raid_class_attach
+EXPORT_SYMBOL drivers/scsi/raid_class 0xea511aeb	raid_class_release
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x007abefc	starget_for_each_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x018459f5	scsi_execute
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x027d1306	scsi_command_normalize_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x05d5922b	scsi_target_quiesce
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x072885c9	scsi_rescan_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x07d9b783	scsi_nl_send_vendor_msg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0971d40c	scsi_track_queue_full
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0a4863b9	__scsi_device_lookup_by_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c65e73c	scsi_normalize_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0c8c9e99	scsi_show_extd_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0f4796ef	scsi_is_host_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0fd4e19c	scsi_register_driver
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x0fdd4faa	scsi_allocate_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x11267875	scsi_extd_sense_format
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x171138a0	scsi_setup_fs_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1aa380c9	scsi_report_device_reset
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1b9e0ff1	scsilun_to_int
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1dbe617e	scsi_device_set_state
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x1e04d07a	scsi_print_result
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x20a27b36	scsi_scan_host
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x20a65ecb	scsi_register_interface
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2289f901	__starget_for_each_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x25b9b908	scsi_execute_req
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x285603e1	scsi_target_resume
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28a2ed02	scsi_build_sense_buffer
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x28cf5ac3	scsi_ioctl
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2a392698	scsi_mode_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2b0ba2b0	scsi_sense_desc_find
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2d89342a	scsi_show_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2dfb5a56	__scsi_device_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x2e96cda1	scsi_prep_state_check
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x3012bad5	scsi_adjust_queue_depth
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x388b1fa0	scsi_block_when_processing_errors
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x40a27c37	scsi_dev_info_remove_list
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x42ed475a	__scsi_put_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x48951edb	scsi_nonblockable_ioctl
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x49817fb3	scsi_dma_unmap
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4afe9a77	scsi_partsize
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x4e36d53e	scsi_report_bus_reset
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5281eee3	scsi_device_lookup_by_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x53a0dc82	scsi_print_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x56c8799d	scsi_kunmap_atomic_sg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x5bf8a9e7	scsi_host_get
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6000b6a9	scsi_calculate_bounce_limit
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x61f00421	scsi_is_target_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x64c983df	scsi_add_host_with_dma
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x69d38ed9	__scsi_print_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6b6e5931	scsi_free_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x6e4208b2	scsi_setup_blk_pc_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x70d64539	scsi_host_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x70fc9531	scsi_host_set_state
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72e7eed9	scsi_release_buffers
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x72ea7b2d	scsi_device_type
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x74cf91ce	scsi_prep_fn
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7739f4f2	scsi_eh_finish_cmd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x775a1a21	scsi_scan_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x785ec9f6	__scsi_add_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x78f11711	scsi_remove_target
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x796fc5ce	scsi_get_sense_info_fld
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7a93ac75	scsi_remove_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7b5f663a	scsi_eh_prep_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x7d7d7ddd	scsi_test_unit_ready
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8a6aad3d	scsicam_bios_param
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x8fd66939	scsi_unregister
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x93de43e1	scsi_unblock_requests
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x96cd2b04	scsi_sense_key_string
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0x9cfd56c5	scsi_print_status
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa18b9d07	scsi_put_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa5bb38a3	scsi_print_sense
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xa720b039	scsi_dma_map
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaa7a42b6	scsi_block_requests
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xada4df13	scsi_host_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xaf3dd7dc	scsi_logging_level
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb042d654	scsi_init_io
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb4709322	scsi_dev_info_add_list
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xb6c5a973	scsi_show_result
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbe4109fd	scsi_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbeba76ae	scsi_free_host_dev
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xbfe9d558	scsi_device_get
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc39074a0	scsi_reset_provider
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xc81ab651	scsi_register
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xca5dbc50	scsi_print_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xcc30d506	scsi_prep_return
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd25cfb75	scsi_bios_ptable
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd48d1b60	scsi_host_put
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd4ec8322	scsi_set_medium_removal
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd5ba3e03	scsi_get_host_dev
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xd7b46675	scsi_get_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xdc047fc4	scsi_dev_info_list_add_keyed
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xdfe8a14d	scsi_add_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe01ce4b1	scsi_finish_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe8698763	scsi_get_device_flags_keyed
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe953a1de	scsi_eh_restore_cmnd
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe9992774	scsi_is_sdev_device
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xe9aa39ef	scsi_device_quiesce
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xea10212a	int_to_scsilun
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf0cd6815	__scsi_alloc_queue
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf151911d	__scsi_iterate_devices
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf2ebb8a2	scsi_device_resume
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf4528073	scsi_kmap_atomic_sg
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf811e69d	scsi_eh_flush_done_q
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xf82eacb8	scsi_device_put
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfea648dc	scsi_device_lookup
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xfef96e23	__scsi_print_command
+EXPORT_SYMBOL drivers/scsi/scsi_mod 0xff3d51aa	scsi_cmd_print_sense_hdr
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x06649ef6	fc_vport_terminate
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x07223ca1	fc_remote_port_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x44355ca5	fc_remote_port_rolechg
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x47418c33	fc_host_post_event
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x4a05c4ed	fc_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x51655940	fc_host_post_vendor_event
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x53333249	fc_vport_create
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x53b45c1f	scsi_is_fc_vport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x6d64d756	fc_remote_port_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x7954b1ea	fc_get_event_number
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x92e79dc2	fc_attach_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0x9f4f402d	fc_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_transport_fc 0xdf9e3db8	scsi_is_fc_rport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x0324687b	sas_phy_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x0c0e53ab	scsi_is_sas_rphy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x13661f41	sas_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x1dab7cc8	sas_port_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x20857b76	sas_rphy_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x27db7dd8	sas_rphy_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x343de880	scsi_is_sas_port
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x41726c11	sas_end_device_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x455050f3	sas_remove_children
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x562055f4	sas_attach_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x5afefec6	sas_port_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x68d1dec7	sas_phy_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x6aeba41e	sas_rphy_remove
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x742fb2dd	sas_port_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x77fed90b	sas_phy_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x7a75b5ec	scsi_is_sas_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x82eb8a74	sas_port_alloc_num
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x90ca0db3	sas_port_mark_backlink
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0x91e9b91c	sas_phy_delete
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa4a6b875	sas_port_add_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa6ca9c3c	sas_rphy_free
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xa96a9cda	sas_port_add
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xbedccc92	sas_expander_alloc
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xc0a90f98	sas_port_delete_phy
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xcdf35c95	sas_read_port_mode_page
+EXPORT_SYMBOL drivers/scsi/scsi_transport_sas 0xe097cea1	sas_remove_host
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x18cf854e	spi_release_transport
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x27d4f5ad	spi_dv_device
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x3686ea09	spi_print_msg
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0x550396b4	spi_schedule_dv_device
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xbc84979a	spi_display_xfer_agreement
+EXPORT_SYMBOL drivers/scsi/scsi_transport_spi 0xe2c7d088	spi_attach_transport
+EXPORT_SYMBOL drivers/ssb/ssb 0x06935461	ssb_device_is_enabled
+EXPORT_SYMBOL drivers/ssb/ssb 0x174e4ec3	ssb_dma_set_mask
+EXPORT_SYMBOL drivers/ssb/ssb 0x1a9f4b29	ssb_bus_resume
+EXPORT_SYMBOL drivers/ssb/ssb 0x32eaaa5a	ssb_bus_pcibus_register
+EXPORT_SYMBOL drivers/ssb/ssb 0x4c048ae9	ssb_clockspeed
+EXPORT_SYMBOL drivers/ssb/ssb 0x4f349459	__ssb_driver_register
+EXPORT_SYMBOL drivers/ssb/ssb 0x5124542c	ssb_dma_free_consistent
+EXPORT_SYMBOL drivers/ssb/ssb 0x55388f49	ssb_bus_powerup
+EXPORT_SYMBOL drivers/ssb/ssb 0x5b1948e9	ssb_driver_unregister
+EXPORT_SYMBOL drivers/ssb/ssb 0x5b8770b6	ssb_bus_unregister
+EXPORT_SYMBOL drivers/ssb/ssb 0x66140b60	ssb_pcicore_dev_irqvecs_enable
+EXPORT_SYMBOL drivers/ssb/ssb 0x78f00487	ssb_pcihost_register
+EXPORT_SYMBOL drivers/ssb/ssb 0x8d5d2b88	ssb_set_devtypedata
+EXPORT_SYMBOL drivers/ssb/ssb 0xa6899841	ssb_dma_translation
+EXPORT_SYMBOL drivers/ssb/ssb 0xb2c75621	ssb_device_enable
+EXPORT_SYMBOL drivers/ssb/ssb 0xb4aabeb9	ssb_bus_suspend
+EXPORT_SYMBOL drivers/ssb/ssb 0xb7f939b2	ssb_dma_alloc_consistent
+EXPORT_SYMBOL drivers/ssb/ssb 0xc0512e0f	ssb_admatch_base
+EXPORT_SYMBOL drivers/ssb/ssb 0xc19ab73e	ssb_pmu_set_ldo_paref
+EXPORT_SYMBOL drivers/ssb/ssb 0xd481192b	ssb_admatch_size
+EXPORT_SYMBOL drivers/ssb/ssb 0xed6353b1	ssb_pmu_set_ldo_voltage
+EXPORT_SYMBOL drivers/ssb/ssb 0xf4da3ff1	ssb_device_disable
+EXPORT_SYMBOL drivers/ssb/ssb 0xf61a9866	ssb_bus_may_powerdown
+EXPORT_SYMBOL drivers/telephony/phonedev 0x89cd96b9	phone_unregister_device
+EXPORT_SYMBOL drivers/telephony/phonedev 0xb9803f7e	phone_register_device
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0x08a708fe	net2280_set_fifo_mode
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0x5315da43	usb_gadget_register_driver
+EXPORT_SYMBOL drivers/usb/gadget/dummy_hcd 0xbefe3e8d	usb_gadget_unregister_driver
+EXPORT_SYMBOL drivers/usb/host/sl811-hcd 0x703daeaf	sl811h_driver
+EXPORT_SYMBOL drivers/usb/serial/usbserial 0x679ca4ef	usb_serial_resume
+EXPORT_SYMBOL drivers/usb/serial/usbserial 0x7d4fb12e	usb_serial_suspend
+EXPORT_SYMBOL drivers/video/backlight/lcd 0x0ff5c2f5	lcd_device_unregister
+EXPORT_SYMBOL drivers/video/backlight/lcd 0x7c5b4d0e	lcd_device_register
+EXPORT_SYMBOL drivers/video/console/bitblit 0xab9bb8d4	fbcon_set_bitops
+EXPORT_SYMBOL drivers/video/console/font 0x09c8eb55	font_vga_8x16
+EXPORT_SYMBOL drivers/video/console/font 0xbb99125c	get_default_font
+EXPORT_SYMBOL drivers/video/console/font 0xf7584a9c	find_font
+EXPORT_SYMBOL drivers/video/console/softcursor 0xd4ce7164	soft_cursor
+EXPORT_SYMBOL drivers/video/console/tileblit 0x44ea603c	fbcon_set_tileops
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x0cc3ede5	cyber2000fb_detach
+EXPORT_SYMBOL drivers/video/cyber2000fb 0x3e03572d	cyber2000fb_enable_extregs
+EXPORT_SYMBOL drivers/video/cyber2000fb 0xabdf5a97	cyber2000fb_get_fb_var
+EXPORT_SYMBOL drivers/video/cyber2000fb 0xdf333fb3	cyber2000fb_disable_extregs
+EXPORT_SYMBOL drivers/video/cyber2000fb 0xf16de009	cyber2000fb_attach
+EXPORT_SYMBOL drivers/video/display/display 0x29417638	display_device_register
+EXPORT_SYMBOL drivers/video/display/display 0xa6e27882	display_device_unregister
+EXPORT_SYMBOL drivers/video/macmodes 0x08ed0b62	mac_vmode_to_var
+EXPORT_SYMBOL drivers/video/macmodes 0x5c0abbf5	mac_find_mode
+EXPORT_SYMBOL drivers/video/macmodes 0xe2304303	mac_map_monitor_sense
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x0429fd94	matroxfb_g450_setclk
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0x860ccd9c	g450_mnp2f
+EXPORT_SYMBOL drivers/video/matrox/g450_pll 0xc1de4764	matroxfb_g450_setpll_cond
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x0cc14d36	matrox_G100
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x395d5c94	DAC1064_global_restore
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0x568813f0	DAC1064_global_init
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_DAC1064 0xac22d27d	matrox_mystique
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_Ti3026 0xa1903620	matrox_millennium
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_accel 0xa857b20b	matrox_cfbX_init
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x44e79303	matroxfb_register_driver
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0x9bee5c53	matroxfb_wait_for_sync
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xa8abf93a	matroxfb_unregister_driver
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_base 0xe8a145b9	matroxfb_enable_irq
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x3a3b631d	matroxfb_g450_shutdown
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_g450 0x62c635f9	matroxfb_g450_connect
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x25cf8049	matroxfb_PLL_calcclock
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x4328c264	matroxfb_vgaHWinit
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x61b81348	matroxfb_DAC_out
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0x840e4814	matroxfb_read_pins
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xaabd8e9e	matroxfb_DAC_in
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xabd8e427	matroxfb_var2my
+EXPORT_SYMBOL drivers/video/matrox/matroxfb_misc 0xe50a29ac	matroxfb_vgaHWrestore
+EXPORT_SYMBOL drivers/video/output 0x600b437a	video_output_register
+EXPORT_SYMBOL drivers/video/output 0x679e484c	video_output_unregister
+EXPORT_SYMBOL drivers/video/sis/sisfb 0x3037658e	sis_malloc
+EXPORT_SYMBOL drivers/video/sis/sisfb 0x454a3cf0	sis_free
+EXPORT_SYMBOL drivers/video/svgalib 0x00d1fce9	svga_set_default_seq_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x07b3da30	svga_wseq_multi
+EXPORT_SYMBOL drivers/video/svgalib 0x1b95c56a	svga_check_timings
+EXPORT_SYMBOL drivers/video/svgalib 0x592e1569	svga_tilefill
+EXPORT_SYMBOL drivers/video/svgalib 0x5dc8d1b9	svga_tileblit
+EXPORT_SYMBOL drivers/video/svgalib 0x63e898d1	svga_set_default_crt_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x7a3ae959	svga_wcrt_multi
+EXPORT_SYMBOL drivers/video/svgalib 0x80408443	svga_set_timings
+EXPORT_SYMBOL drivers/video/svgalib 0x8fa8438b	svga_set_textmode_vga_regs
+EXPORT_SYMBOL drivers/video/svgalib 0x97e4c39e	svga_get_tilemax
+EXPORT_SYMBOL drivers/video/svgalib 0xa0340370	svga_settile
+EXPORT_SYMBOL drivers/video/svgalib 0xa590851e	svga_tilecursor
+EXPORT_SYMBOL drivers/video/svgalib 0xab3b22ad	svga_set_default_gfx_regs
+EXPORT_SYMBOL drivers/video/svgalib 0xac7d189b	svga_tilecopy
+EXPORT_SYMBOL drivers/video/svgalib 0xdad682b1	svga_set_default_atc_regs
+EXPORT_SYMBOL drivers/video/svgalib 0xe8cf9a3c	svga_get_caps
+EXPORT_SYMBOL drivers/video/svgalib 0xec83c473	svga_match_format
+EXPORT_SYMBOL drivers/video/svgalib 0xef774f5d	svga_compute_pll
+EXPORT_SYMBOL drivers/video/syscopyarea 0xe8e01485	sys_copyarea
+EXPORT_SYMBOL drivers/video/sysfillrect 0xf2029a16	sys_fillrect
+EXPORT_SYMBOL drivers/video/sysimgblt 0x8338a6e7	sys_imageblit
+EXPORT_SYMBOL drivers/video/vgastate 0x686de290	restore_vga
+EXPORT_SYMBOL drivers/video/vgastate 0xe7a2620e	save_vga
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x3b90b04f	w1_ds2760_store_eeprom
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x503fe19e	w1_ds2760_recall_eeprom
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x60ec1ea4	w1_ds2760_read
+EXPORT_SYMBOL drivers/w1/slaves/w1_ds2760 0x6f7632ca	w1_ds2760_write
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x04e133fc	iTCO_vendor_check_noreboot_on
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0x672c9d44	iTCO_vendor_pre_keepalive
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa78bd894	iTCO_vendor_pre_set_heartbeat
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xa8d6daac	iTCO_vendor_pre_start
+EXPORT_SYMBOL drivers/watchdog/iTCO_vendor_support 0xd0efe320	iTCO_vendor_pre_stop
+EXPORT_SYMBOL fs/fscache/fscache 0x07d9b576	fscache_wait_bit_interruptible
+EXPORT_SYMBOL fs/fscache/fscache 0x0ad76a98	__fscache_read_or_alloc_pages
+EXPORT_SYMBOL fs/fscache/fscache 0x0da29788	__fscache_alloc_page
+EXPORT_SYMBOL fs/fscache/fscache 0x14da9bb3	__fscache_check_page_write
+EXPORT_SYMBOL fs/fscache/fscache 0x2596bb8a	fscache_put_operation
+EXPORT_SYMBOL fs/fscache/fscache 0x2d939c2c	fscache_object_lookup_negative
+EXPORT_SYMBOL fs/fscache/fscache 0x3aded416	fscache_enqueue_operation
+EXPORT_SYMBOL fs/fscache/fscache 0x3fc23318	fscache_wait_bit
+EXPORT_SYMBOL fs/fscache/fscache 0x4757ffbf	__fscache_wait_on_page_write
+EXPORT_SYMBOL fs/fscache/fscache 0x496932b9	fscache_op_debug_id
+EXPORT_SYMBOL fs/fscache/fscache 0x4f381d67	fscache_obtained_object
+EXPORT_SYMBOL fs/fscache/fscache 0x5061e282	__fscache_acquire_cookie
+EXPORT_SYMBOL fs/fscache/fscache 0x5a0e4107	__fscache_update_cookie
+EXPORT_SYMBOL fs/fscache/fscache 0x5a712f1f	__fscache_unregister_netfs
+EXPORT_SYMBOL fs/fscache/fscache 0x5ec5dc0c	fscache_add_cache
+EXPORT_SYMBOL fs/fscache/fscache 0x6125a9af	fscache_mark_pages_cached
+EXPORT_SYMBOL fs/fscache/fscache 0x63f96884	fscache_cache_cleared_wq
+EXPORT_SYMBOL fs/fscache/fscache 0x74d6844b	__fscache_relinquish_cookie
+EXPORT_SYMBOL fs/fscache/fscache 0x7bc88f5a	__fscache_read_or_alloc_page
+EXPORT_SYMBOL fs/fscache/fscache 0x86f8894f	fscache_object_states
+EXPORT_SYMBOL fs/fscache/fscache 0xa160b6e2	__fscache_attr_changed
+EXPORT_SYMBOL fs/fscache/fscache 0xae06386c	__fscache_write_page
+EXPORT_SYMBOL fs/fscache/fscache 0xb024896b	fscache_fsdef_index
+EXPORT_SYMBOL fs/fscache/fscache 0xba4c90d0	fscache_withdraw_cache
+EXPORT_SYMBOL fs/fscache/fscache 0xc837e1f1	fscache_init_cache
+EXPORT_SYMBOL fs/fscache/fscache 0xd18b2710	fscache_check_aux
+EXPORT_SYMBOL fs/fscache/fscache 0xd4cc3857	fscache_object_slow_work_ops
+EXPORT_SYMBOL fs/fscache/fscache 0xd649c0d1	__fscache_maybe_release_page
+EXPORT_SYMBOL fs/fscache/fscache 0xfb17bed9	__fscache_uncache_page
+EXPORT_SYMBOL fs/fscache/fscache 0xfb8e4052	__fscache_register_netfs
+EXPORT_SYMBOL fs/fscache/fscache 0xff830364	fscache_io_error
+EXPORT_SYMBOL fs/nfsd/nfsd 0x1f573533	nfs4_acl_posix_to_nfsv4
+EXPORT_SYMBOL fs/nfsd/nfsd 0x35e33c1e	nfs4_acl_write_who
+EXPORT_SYMBOL fs/nfsd/nfsd 0x5a157ae4	nfs4_acl_get_whotype
+EXPORT_SYMBOL fs/nfsd/nfsd 0x96ce9bb4	nfs4_acl_new
+EXPORT_SYMBOL fs/nfsd/nfsd 0xdb389aec	nfs4_acl_nfsv4_to_posix
+EXPORT_SYMBOL fs/quota/quota_tree 0x14026177	qtree_read_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0x41ae22b6	qtree_entry_unused
+EXPORT_SYMBOL fs/quota/quota_tree 0xc41b9fa3	qtree_release_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0xe22a172c	qtree_delete_dquot
+EXPORT_SYMBOL fs/quota/quota_tree 0xe3850e18	qtree_write_dquot
+EXPORT_SYMBOL lib/crc-ccitt 0x651c2313	crc_ccitt
+EXPORT_SYMBOL lib/crc-ccitt 0x75811312	crc_ccitt_table
+EXPORT_SYMBOL lib/crc-itu-t 0x276c7e62	crc_itu_t
+EXPORT_SYMBOL lib/crc-itu-t 0xd29b009f	crc_itu_t_table
+EXPORT_SYMBOL lib/crc-t10dif 0x782acba5	crc_t10dif
+EXPORT_SYMBOL lib/crc7 0xc086bfba	crc7
+EXPORT_SYMBOL lib/crc7 0xd80c3603	crc7_syndrome_table
+EXPORT_SYMBOL lib/libcrc32c 0x27000b29	crc32c
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x315c65fd	zlib_deflateInit2
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0x48034724	zlib_deflateReset
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xaf64ad0d	zlib_deflate
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf0caf44b	zlib_deflate_workspacesize
+EXPORT_SYMBOL lib/zlib_deflate/zlib_deflate 0xf741c793	zlib_deflateEnd
+EXPORT_SYMBOL net/802/p8023 0xb79f7a1e	destroy_8023_client
+EXPORT_SYMBOL net/802/p8023 0xe7f34d01	make_8023_client
+EXPORT_SYMBOL net/9p/9pnet 0x0b3ac49a	p9pdu_dump
+EXPORT_SYMBOL net/9p/9pnet 0x0fce4fce	p9_client_disconnect
+EXPORT_SYMBOL net/9p/9pnet 0x1133997a	p9_client_open
+EXPORT_SYMBOL net/9p/9pnet 0x244c6d40	p9_idpool_get
+EXPORT_SYMBOL net/9p/9pnet 0x29ad2994	p9_client_wstat
+EXPORT_SYMBOL net/9p/9pnet 0x3cc0fc1c	p9_client_read
+EXPORT_SYMBOL net/9p/9pnet 0x3d73a797	p9_errstr2errno
+EXPORT_SYMBOL net/9p/9pnet 0x3d783885	p9_client_version
+EXPORT_SYMBOL net/9p/9pnet 0x41e6bc51	p9_parse_header
+EXPORT_SYMBOL net/9p/9pnet 0x42dc0330	p9_client_fcreate
+EXPORT_SYMBOL net/9p/9pnet 0x4a403616	p9_client_remove
+EXPORT_SYMBOL net/9p/9pnet 0x56e2f884	v9fs_get_trans_by_name
+EXPORT_SYMBOL net/9p/9pnet 0x58d853d2	p9_client_destroy
+EXPORT_SYMBOL net/9p/9pnet 0x5ba182de	v9fs_register_trans
+EXPORT_SYMBOL net/9p/9pnet 0x5e0ef374	p9_idpool_check
+EXPORT_SYMBOL net/9p/9pnet 0x61852dea	p9_idpool_put
+EXPORT_SYMBOL net/9p/9pnet 0x66881019	v9fs_get_default_trans
+EXPORT_SYMBOL net/9p/9pnet 0x6c5e479c	p9_idpool_create
+EXPORT_SYMBOL net/9p/9pnet 0x6eda056f	p9_client_create
+EXPORT_SYMBOL net/9p/9pnet 0x6fdf1b64	p9_tag_lookup
+EXPORT_SYMBOL net/9p/9pnet 0x76b79bf1	p9stat_read
+EXPORT_SYMBOL net/9p/9pnet 0x7f337fef	p9_client_clunk
+EXPORT_SYMBOL net/9p/9pnet 0x9c964743	p9stat_free
+EXPORT_SYMBOL net/9p/9pnet 0xa897275f	p9_client_stat
+EXPORT_SYMBOL net/9p/9pnet 0xa9b8c3ef	p9_client_attach
+EXPORT_SYMBOL net/9p/9pnet 0xac831304	v9fs_unregister_trans
+EXPORT_SYMBOL net/9p/9pnet 0xb28348a6	p9_client_auth
+EXPORT_SYMBOL net/9p/9pnet 0xbaa17b44	p9_idpool_destroy
+EXPORT_SYMBOL net/9p/9pnet 0xd785ed1a	p9_client_cb
+EXPORT_SYMBOL net/9p/9pnet 0xe58a3360	p9_error_init
+EXPORT_SYMBOL net/9p/9pnet 0xef4e6936	p9_client_walk
+EXPORT_SYMBOL net/9p/9pnet 0xff1b520e	p9_client_write
+EXPORT_SYMBOL net/appletalk/appletalk 0x534397a2	aarp_send_ddp
+EXPORT_SYMBOL net/appletalk/appletalk 0x55d72870	atalk_find_dev_addr
+EXPORT_SYMBOL net/appletalk/appletalk 0xc686b1ab	atrtr_get_dev
+EXPORT_SYMBOL net/appletalk/appletalk 0xfaa46ce6	alloc_ltalkdev
+EXPORT_SYMBOL net/ax25/ax25 0x242852b9	ax25_uid_policy
+EXPORT_SYMBOL net/ax25/ax25 0x3d2d82ec	ax25_display_timer
+EXPORT_SYMBOL net/ax25/ax25 0x4502c65a	asc2ax
+EXPORT_SYMBOL net/ax25/ax25 0x53dea1ff	ax2asc
+EXPORT_SYMBOL net/ax25/ax25 0x5fc6280f	ax25_findbyuid
+EXPORT_SYMBOL net/ax25/ax25 0x61efaf6a	ax25_linkfail_register
+EXPORT_SYMBOL net/ax25/ax25 0x8df9cc7c	ax25_find_cb
+EXPORT_SYMBOL net/ax25/ax25 0x8ede9e26	ax25_protocol_release
+EXPORT_SYMBOL net/ax25/ax25 0xc1444946	ax25cmp
+EXPORT_SYMBOL net/ax25/ax25 0xd43ecbf1	null_ax25_address
+EXPORT_SYMBOL net/ax25/ax25 0xdf644f25	ax25_rebuild_header
+EXPORT_SYMBOL net/ax25/ax25 0xe3da41ff	ax25_header_ops
+EXPORT_SYMBOL net/ax25/ax25 0xf45c5ea1	ax25_listen_register
+EXPORT_SYMBOL net/ax25/ax25 0xfabf8376	ax25_listen_release
+EXPORT_SYMBOL net/ax25/ax25 0xfb28b818	ax25_linkfail_release
+EXPORT_SYMBOL net/ax25/ax25 0xfc36a1c7	ax25_send_frame
+EXPORT_SYMBOL net/ax25/ax25 0xff42a150	ax25_hard_header
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x0e9c4bfc	hci_send_acl
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x284db8cd	hci_conn_switch_role
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x2a666f24	bt_sock_recvmsg
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x5011c27f	bt_sock_register
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x508568ef	hci_unregister_cb
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x615338de	hci_conn_security
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x68e9bd01	bt_sock_ioctl
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x697e569c	hci_unregister_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x7094f8ae	bt_err
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x78e2c1f8	hci_send_sco
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x82eece49	hci_suspend_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x83ec81b5	bt_accept_unlink
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x915c962d	hci_register_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x94a8e613	hci_unregister_proto
+EXPORT_SYMBOL net/bluetooth/bluetooth 0x95c47adf	bt_sock_poll
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xa0fac268	hci_conn_change_link_key
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xb06ca4a4	hci_free_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xb58f6024	hci_resume_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xb6608892	hci_conn_put_device
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xb908dbc9	bt_sock_wait_state
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xbebaa770	hci_connect
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xc1e24167	hci_alloc_dev
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xc2066af0	batostr
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xc6dd4a4e	hci_get_route
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xc84af049	hci_conn_check_link_mode
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xcc1fb551	baswap
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xd163c662	hci_register_proto
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xd7597c96	hci_conn_hold_device
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xd94b6b3c	bt_accept_dequeue
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xdc5c0381	bt_sock_unlink
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xdca3c0d2	bt_accept_enqueue
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xe4c99302	hci_recv_fragment
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xf19294db	bt_sock_unregister
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xf1e6ad89	bt_sock_link
+EXPORT_SYMBOL net/bluetooth/bluetooth 0xf5c636dc	hci_register_cb
+EXPORT_SYMBOL net/bluetooth/l2cap 0xfc31fe88	l2cap_load
+EXPORT_SYMBOL net/bridge/bridge 0xff5950fc	br_should_route_hook
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xaae33706	ebt_register_table
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xf1220b2a	ebt_do_table
+EXPORT_SYMBOL net/bridge/netfilter/ebtables 0xf307df07	ebt_unregister_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x1c93235e	arpt_register_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0x5254650b	arpt_unregister_table
+EXPORT_SYMBOL net/ipv4/netfilter/arp_tables 0xab4d91ec	arpt_do_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x4be40836	ipt_do_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0x6e6c62ed	ipt_unregister_table
+EXPORT_SYMBOL net/ipv4/netfilter/ip_tables 0xe49de13e	ipt_register_table
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x0aa4e2ee	nf_nat_protocol_register
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x255157a1	nf_nat_mangle_tcp_packet
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x7822b571	nf_nat_used_tuple
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x7bc3ead6	nf_nat_protocol_unregister
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x7d1db1cf	nf_nat_mangle_udp_packet
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0x9f82f47f	nf_nat_follow_master
+EXPORT_SYMBOL net/ipv4/netfilter/nf_nat 0xfea1afad	nf_nat_setup_info
+EXPORT_SYMBOL net/ipv4/tunnel4 0x559397b7	xfrm4_tunnel_register
+EXPORT_SYMBOL net/ipv4/tunnel4 0xba6ced7b	xfrm4_tunnel_deregister
+EXPORT_SYMBOL net/ipv6/ipv6 0x0b0d888b	icmpv6_err_convert
+EXPORT_SYMBOL net/ipv6/ipv6 0x0b68b209	ndisc_build_skb
+EXPORT_SYMBOL net/ipv6/ipv6 0x10c75e7b	ipv6_chk_prefix
+EXPORT_SYMBOL net/ipv6/ipv6 0x1ab221d6	xfrm6_rcv
+EXPORT_SYMBOL net/ipv6/ipv6 0x1d4f5eb7	inet6_add_protocol
+EXPORT_SYMBOL net/ipv6/ipv6 0x20ab5aab	ip6_route_output
+EXPORT_SYMBOL net/ipv6/ipv6 0x2dcadfad	inet6_ioctl
+EXPORT_SYMBOL net/ipv6/ipv6 0x30123eb5	icmpv6_statistics
+EXPORT_SYMBOL net/ipv6/ipv6 0x357baa29	ip6_frag_init
+EXPORT_SYMBOL net/ipv6/ipv6 0x45a6b8bc	in6_dev_finish_destroy
+EXPORT_SYMBOL net/ipv6/ipv6 0x4626ea92	xfrm6_prepare_output
+EXPORT_SYMBOL net/ipv6/ipv6 0x4d8a6a0f	rt6_lookup
+EXPORT_SYMBOL net/ipv6/ipv6 0x4e38507e	ip6_route_me_harder
+EXPORT_SYMBOL net/ipv6/ipv6 0x52ca3594	inet6_unregister_protosw
+EXPORT_SYMBOL net/ipv6/ipv6 0x538383c0	unregister_inet6addr_notifier
+EXPORT_SYMBOL net/ipv6/ipv6 0x5818d4cf	ndisc_send_skb
+EXPORT_SYMBOL net/ipv6/ipv6 0x6b4999ae	ipv6_push_nfrag_opts
+EXPORT_SYMBOL net/ipv6/ipv6 0x6f30eef9	ip6_frag_match
+EXPORT_SYMBOL net/ipv6/ipv6 0x7437323b	xfrm6_find_1stfragopt
+EXPORT_SYMBOL net/ipv6/ipv6 0x8b63586a	xfrm6_rcv_spi
+EXPORT_SYMBOL net/ipv6/ipv6 0x987306ce	compat_ipv6_setsockopt
+EXPORT_SYMBOL net/ipv6/ipv6 0x9ce4dd54	ip6_xmit
+EXPORT_SYMBOL net/ipv6/ipv6 0x9f42f57f	ndisc_mc_map
+EXPORT_SYMBOL net/ipv6/ipv6 0xa899a4c7	inet6_release
+EXPORT_SYMBOL net/ipv6/ipv6 0xa8fac972	inet6_register_protosw
+EXPORT_SYMBOL net/ipv6/ipv6 0xbc648453	compat_ipv6_getsockopt
+EXPORT_SYMBOL net/ipv6/ipv6 0xc562e448	ipv6_dev_get_saddr
+EXPORT_SYMBOL net/ipv6/ipv6 0xccdafc32	nf_ip6_checksum
+EXPORT_SYMBOL net/ipv6/ipv6 0xce19bac5	register_inet6addr_notifier
+EXPORT_SYMBOL net/ipv6/ipv6 0xd72a30ab	ipv6_setsockopt
+EXPORT_SYMBOL net/ipv6/ipv6 0xd9a0552b	ipv6_chk_addr
+EXPORT_SYMBOL net/ipv6/ipv6 0xdbc1f154	inet6_getname
+EXPORT_SYMBOL net/ipv6/ipv6 0xe1a81c3a	icmpv6msg_statistics
+EXPORT_SYMBOL net/ipv6/ipv6 0xe51657f4	inet6_bind
+EXPORT_SYMBOL net/ipv6/ipv6 0xe690b8fd	__ipv6_isatap_ifid
+EXPORT_SYMBOL net/ipv6/ipv6 0xe9f5a91a	inet6_del_protocol
+EXPORT_SYMBOL net/ipv6/ipv6 0xf546ae97	xfrm6_input_addr
+EXPORT_SYMBOL net/ipv6/ipv6 0xf7b47e2d	icmpv6_send
+EXPORT_SYMBOL net/ipv6/ipv6 0xfd338bfd	ipv6_getsockopt
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x2e2a3988	ip6t_unregister_table
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x3202d2cd	ipv6_find_hdr
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0x45da8cda	ip6t_do_table
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xb8bddf33	ip6t_ext_hdr
+EXPORT_SYMBOL net/ipv6/netfilter/ip6_tables 0xc2ea8a23	ip6t_register_table
+EXPORT_SYMBOL net/ipv6/tunnel6 0x866220a2	xfrm6_tunnel_deregister
+EXPORT_SYMBOL net/ipv6/tunnel6 0xb1aa025e	xfrm6_tunnel_register
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0x9cd013f2	xfrm6_tunnel_alloc_spi
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xab14e193	xfrm6_tunnel_free_spi
+EXPORT_SYMBOL net/ipv6/xfrm6_tunnel 0xdb1b42d1	xfrm6_tunnel_spi_lookup
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x3145a000	ircomm_data_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x535ff6c7	ircomm_close
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x69ba44d3	ircomm_open
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x75dc6d48	ircomm_connect_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0x8afb8e54	ircomm_control_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xa181b85b	ircomm_disconnect_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xb26035db	ircomm_flow_request
+EXPORT_SYMBOL net/irda/ircomm/ircomm 0xfa42e4c5	ircomm_connect_response
+EXPORT_SYMBOL net/irda/irda 0x01d1fcdb	hashbin_delete
+EXPORT_SYMBOL net/irda/irda 0x06a3ee58	irias_new_integer_value
+EXPORT_SYMBOL net/irda/irda 0x072e026f	irias_add_octseq_attrib
+EXPORT_SYMBOL net/irda/irda 0x07d3647c	irlmp_register_service
+EXPORT_SYMBOL net/irda/irda 0x1446dec1	async_wrap_skb
+EXPORT_SYMBOL net/irda/irda 0x1951a4f3	irda_notify_init
+EXPORT_SYMBOL net/irda/irda 0x1cf6bf7e	proc_irda
+EXPORT_SYMBOL net/irda/irda 0x2036ad06	irda_param_insert
+EXPORT_SYMBOL net/irda/irda 0x2777ef03	irttp_close_tsap
+EXPORT_SYMBOL net/irda/irda 0x2c8f5477	irttp_connect_response
+EXPORT_SYMBOL net/irda/irda 0x2ed07d9a	irttp_open_tsap
+EXPORT_SYMBOL net/irda/irda 0x2f5ec5eb	irlmp_connect_response
+EXPORT_SYMBOL net/irda/irda 0x3462950f	hashbin_remove
+EXPORT_SYMBOL net/irda/irda 0x37d5b241	irda_device_set_media_busy
+EXPORT_SYMBOL net/irda/irda 0x38a20e5b	irda_debug
+EXPORT_SYMBOL net/irda/irda 0x396081ca	irlap_close
+EXPORT_SYMBOL net/irda/irda 0x448b8aaa	irda_qos_bits_to_value
+EXPORT_SYMBOL net/irda/irda 0x46c1c4a2	irlmp_unregister_service
+EXPORT_SYMBOL net/irda/irda 0x48e2aa11	irlmp_data_request
+EXPORT_SYMBOL net/irda/irda 0x587e01c4	iriap_open
+EXPORT_SYMBOL net/irda/irda 0x5cb604b0	irlmp_connect_request
+EXPORT_SYMBOL net/irda/irda 0x6758f8ac	irias_new_object
+EXPORT_SYMBOL net/irda/irda 0x67de61d0	irttp_flow_request
+EXPORT_SYMBOL net/irda/irda 0x68b7447c	hashbin_find
+EXPORT_SYMBOL net/irda/irda 0x6b043eba	irda_init_max_qos_capabilies
+EXPORT_SYMBOL net/irda/irda 0x7042bc54	irlmp_register_client
+EXPORT_SYMBOL net/irda/irda 0x747d6779	irias_delete_object
+EXPORT_SYMBOL net/irda/irda 0x7621e908	hashbin_insert
+EXPORT_SYMBOL net/irda/irda 0x76243bc9	irias_insert_object
+EXPORT_SYMBOL net/irda/irda 0x763e54a4	irlmp_unregister_client
+EXPORT_SYMBOL net/irda/irda 0x781e2db5	irias_find_object
+EXPORT_SYMBOL net/irda/irda 0x7957f728	irlmp_update_client
+EXPORT_SYMBOL net/irda/irda 0x7a57b6f3	hashbin_remove_this
+EXPORT_SYMBOL net/irda/irda 0x7bfb9a5b	iriap_close
+EXPORT_SYMBOL net/irda/irda 0x82629732	irttp_connect_request
+EXPORT_SYMBOL net/irda/irda 0x83f3d9b6	irttp_udata_request
+EXPORT_SYMBOL net/irda/irda 0x91815586	irda_param_pack
+EXPORT_SYMBOL net/irda/irda 0x94acb978	irttp_dup
+EXPORT_SYMBOL net/irda/irda 0x96680660	async_unwrap_char
+EXPORT_SYMBOL net/irda/irda 0x993ad14b	irda_param_extract_all
+EXPORT_SYMBOL net/irda/irda 0x9982813d	irttp_data_request
+EXPORT_SYMBOL net/irda/irda 0xa3101159	irttp_disconnect_request
+EXPORT_SYMBOL net/irda/irda 0xa6623b71	irlmp_disconnect_request
+EXPORT_SYMBOL net/irda/irda 0xb198eac1	irlmp_close_lsap
+EXPORT_SYMBOL net/irda/irda 0xb9394173	irias_delete_value
+EXPORT_SYMBOL net/irda/irda 0xbc84bf17	iriap_getvaluebyclass_request
+EXPORT_SYMBOL net/irda/irda 0xbcd3ef13	irias_object_change_attribute
+EXPORT_SYMBOL net/irda/irda 0xbe40ace9	irlmp_discovery_request
+EXPORT_SYMBOL net/irda/irda 0xbfb47efd	irlmp_open_lsap
+EXPORT_SYMBOL net/irda/irda 0xc14e9b6a	hashbin_get_next
+EXPORT_SYMBOL net/irda/irda 0xc8f52ecc	alloc_irdadev
+EXPORT_SYMBOL net/irda/irda 0xcd41236c	hashbin_new
+EXPORT_SYMBOL net/irda/irda 0xd066605a	irlap_open
+EXPORT_SYMBOL net/irda/irda 0xd6deeaae	irda_setup_dma
+EXPORT_SYMBOL net/irda/irda 0xd7172ff4	hashbin_get_first
+EXPORT_SYMBOL net/irda/irda 0xd8bfb6d4	hashbin_lock_find
+EXPORT_SYMBOL net/irda/irda 0xde4c6b3c	irlmp_service_to_hint
+EXPORT_SYMBOL net/irda/irda 0xe5260e0e	irias_add_integer_attrib
+EXPORT_SYMBOL net/irda/irda 0xec41fe7f	irias_add_string_attrib
+EXPORT_SYMBOL net/irda/irda 0xedd521c2	irlmp_get_discoveries
+EXPORT_SYMBOL net/lapb/lapb 0x0d96e320	lapb_data_request
+EXPORT_SYMBOL net/lapb/lapb 0x1aeff914	lapb_unregister
+EXPORT_SYMBOL net/lapb/lapb 0x1fd30b8d	lapb_register
+EXPORT_SYMBOL net/lapb/lapb 0x45be695c	lapb_getparms
+EXPORT_SYMBOL net/lapb/lapb 0x6756622d	lapb_connect_request
+EXPORT_SYMBOL net/lapb/lapb 0xdae95d1c	lapb_setparms
+EXPORT_SYMBOL net/lapb/lapb 0xdc9a8fe4	lapb_data_received
+EXPORT_SYMBOL net/lapb/lapb 0xf6f9cf0d	lapb_disconnect_request
+EXPORT_SYMBOL net/mac80211/mac80211 0x01ddf8f7	ieee80211_stop_tx_ba_cb_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0x021b2907	ieee80211_find_sta
+EXPORT_SYMBOL net/mac80211/mac80211 0x046668e2	ieee80211_start_tx_ba_session
+EXPORT_SYMBOL net/mac80211/mac80211 0x06835a86	ieee80211_free_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x108c37ad	ieee80211_rts_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x15fff3bf	ieee80211_queue_stopped
+EXPORT_SYMBOL net/mac80211/mac80211 0x18516e52	ieee80211_get_buffered_bc
+EXPORT_SYMBOL net/mac80211/mac80211 0x25185c80	ieee80211_scan_completed
+EXPORT_SYMBOL net/mac80211/mac80211 0x269dbada	__ieee80211_get_radio_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0x28f8cc0f	ieee80211_ctstoself_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x2d049616	wiphy_to_ieee80211_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x4d2813a1	ieee80211_generic_frame_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0x4f2c477d	ieee80211_queue_delayed_work
+EXPORT_SYMBOL net/mac80211/mac80211 0x51bee2c2	ieee80211_beacon_get
+EXPORT_SYMBOL net/mac80211/mac80211 0x5f419e31	ieee80211_stop_tx_ba_cb
+EXPORT_SYMBOL net/mac80211/mac80211 0x60436ebd	ieee80211_rx_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0x681cac0c	ieee80211_stop_tx_ba_session
+EXPORT_SYMBOL net/mac80211/mac80211 0x6cce1b2e	ieee80211_tx_status
+EXPORT_SYMBOL net/mac80211/mac80211 0x6f094140	__ieee80211_get_tx_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0x744ff543	ieee80211_register_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0x7b2133d5	ieee80211_get_tkip_key
+EXPORT_SYMBOL net/mac80211/mac80211 0x8585648e	ieee80211_stop_queues
+EXPORT_SYMBOL net/mac80211/mac80211 0x9d8e5a09	ieee80211_restart_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0xa1024100	__ieee80211_get_rx_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0xa243a964	__ieee80211_get_assoc_led_name
+EXPORT_SYMBOL net/mac80211/mac80211 0xb13695b4	ieee80211_queue_work
+EXPORT_SYMBOL net/mac80211/mac80211 0xb934ee61	ieee80211_rate_control_unregister
+EXPORT_SYMBOL net/mac80211/mac80211 0xbe00d8ae	ieee80211_tx_status_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0xc2cccf20	ieee80211_rts_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0xc898f7bc	ieee80211_ctstoself_duration
+EXPORT_SYMBOL net/mac80211/mac80211 0xccbf16dd	ieee80211_wake_queue
+EXPORT_SYMBOL net/mac80211/mac80211 0xcd3c11b9	ieee80211_rate_control_register
+EXPORT_SYMBOL net/mac80211/mac80211 0xd108127d	ieee80211_alloc_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0xd7fc39d2	ieee80211_rx
+EXPORT_SYMBOL net/mac80211/mac80211 0xd90e5864	ieee80211_start_tx_ba_cb
+EXPORT_SYMBOL net/mac80211/mac80211 0xe308db60	ieee80211_start_tx_ba_cb_irqsafe
+EXPORT_SYMBOL net/mac80211/mac80211 0xe7150b14	rate_control_send_low
+EXPORT_SYMBOL net/mac80211/mac80211 0xe8abe42d	ieee80211_beacon_loss
+EXPORT_SYMBOL net/mac80211/mac80211 0xe97613ee	ieee80211_unregister_hw
+EXPORT_SYMBOL net/mac80211/mac80211 0xf260277f	ieee80211_wake_queues
+EXPORT_SYMBOL net/mac80211/mac80211 0xff1d6599	ieee80211_stop_queue
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x1db14b7d	unregister_ip_vs_scheduler
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x2c494081	register_ip_vs_app_inc
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x42c34eed	ip_vs_tcp_conn_listen
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x4ede410e	ip_vs_skb_replace
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x5262a224	ip_vs_conn_put
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x7dc5b892	ip_vs_conn_out_get
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0x9c60ff93	register_ip_vs_scheduler
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xa1dbc2d8	ip_vs_proto_name
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xa1eb7430	ip_vs_conn_new
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xab502b92	register_ip_vs_app
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xb53f3bcb	unregister_ip_vs_app
+EXPORT_SYMBOL net/netfilter/ipvs/ip_vs 0xd837ef1e	ip_vs_conn_in_get
+EXPORT_SYMBOL net/netfilter/nf_conntrack 0x0cda38e3	__nf_ct_ext_destroy
+EXPORT_SYMBOL net/netfilter/nf_conntrack 0xe8eea0f6	__nf_ct_ext_add
+EXPORT_SYMBOL net/netfilter/nf_conntrack_proto_gre 0x307a768c	nf_ct_gre_keymap_flush
+EXPORT_SYMBOL net/netfilter/x_tables 0x16a5e826	xt_free_table_info
+EXPORT_SYMBOL net/netfilter/x_tables 0x2321af5d	xt_register_match
+EXPORT_SYMBOL net/netfilter/x_tables 0x4bda22ba	xt_unregister_match
+EXPORT_SYMBOL net/netfilter/x_tables 0x58e8e9b7	xt_find_match
+EXPORT_SYMBOL net/netfilter/x_tables 0x60cf91e9	xt_unregister_targets
+EXPORT_SYMBOL net/netfilter/x_tables 0x65ea0659	xt_unregister_target
+EXPORT_SYMBOL net/netfilter/x_tables 0x72053d78	xt_unregister_matches
+EXPORT_SYMBOL net/netfilter/x_tables 0x88def9d5	xt_register_targets
+EXPORT_SYMBOL net/netfilter/x_tables 0x90f87a23	xt_register_target
+EXPORT_SYMBOL net/netfilter/x_tables 0xc3ff5dff	xt_alloc_table_info
+EXPORT_SYMBOL net/netfilter/x_tables 0xd3ad7a9f	xt_find_target
+EXPORT_SYMBOL net/netfilter/x_tables 0xe7e26f8e	xt_register_matches
+EXPORT_SYMBOL net/rfkill/rfkill 0x2d7c4b84	rfkill_set_states
+EXPORT_SYMBOL net/rfkill/rfkill 0x2f4e129a	rfkill_init_sw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0x4355dbb8	rfkill_alloc
+EXPORT_SYMBOL net/rfkill/rfkill 0x44391527	rfkill_pause_polling
+EXPORT_SYMBOL net/rfkill/rfkill 0x460d3a70	rfkill_unregister
+EXPORT_SYMBOL net/rfkill/rfkill 0x614343ca	rfkill_destroy
+EXPORT_SYMBOL net/rfkill/rfkill 0x6e70e8a1	rfkill_resume_polling
+EXPORT_SYMBOL net/rfkill/rfkill 0x87f8bb44	rfkill_get_led_trigger_name
+EXPORT_SYMBOL net/rfkill/rfkill 0xaad71b75	rfkill_set_sw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0xc958dc37	rfkill_set_led_trigger_name
+EXPORT_SYMBOL net/rfkill/rfkill 0xd4e5d7a4	rfkill_blocked
+EXPORT_SYMBOL net/rfkill/rfkill 0xe5626bc7	rfkill_set_hw_state
+EXPORT_SYMBOL net/rfkill/rfkill 0xeeb87751	rfkill_register
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x05d957f4	rxrpc_kernel_reject_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x204a0189	key_type_rxrpc
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x2fab2b7d	rxrpc_get_server_data_key
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x36445312	rxrpc_kernel_get_abort_code
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x447c1124	rxrpc_kernel_get_error_number
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x565e18e6	rxrpc_kernel_end_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x6a9ba1de	rxrpc_kernel_begin_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x6e77540d	rxrpc_kernel_is_data_last
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x78bf8265	rxrpc_kernel_accept_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x79ff5187	rxrpc_kernel_abort_call
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0x966232ac	rxrpc_kernel_free_skb
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xcccc4dff	rxrpc_kernel_intercept_rx_messages
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xd3d91064	rxrpc_get_null_key
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xdb241cb6	rxrpc_kernel_data_delivered
+EXPORT_SYMBOL net/rxrpc/af-rxrpc 0xe0f185c9	rxrpc_kernel_send_data
+EXPORT_SYMBOL net/sunrpc/sunrpc 0x3ad58491	svc_pool_stats_open
+EXPORT_SYMBOL net/tipc/tipc 0x08acf310	tipc_available_nodes
+EXPORT_SYMBOL net/tipc/tipc 0x0b074a7b	tipc_multicast
+EXPORT_SYMBOL net/tipc/tipc 0x0ec76439	tipc_createport_raw
+EXPORT_SYMBOL net/tipc/tipc 0x10d40fcd	tipc_isconnected
+EXPORT_SYMBOL net/tipc/tipc 0x1472b270	tipc_disconnect
+EXPORT_SYMBOL net/tipc/tipc 0x1479cb03	tipc_deleteport
+EXPORT_SYMBOL net/tipc/tipc 0x15b5ecde	tipc_set_portunreliable
+EXPORT_SYMBOL net/tipc/tipc 0x16f27683	tipc_block_bearer
+EXPORT_SYMBOL net/tipc/tipc 0x23daecbd	tipc_send
+EXPORT_SYMBOL net/tipc/tipc 0x259b74f9	tipc_acknowledge
+EXPORT_SYMBOL net/tipc/tipc 0x310d1bc9	tipc_detach
+EXPORT_SYMBOL net/tipc/tipc 0x34623560	tipc_reject_msg
+EXPORT_SYMBOL net/tipc/tipc 0x3712e340	tipc_portunreliable
+EXPORT_SYMBOL net/tipc/tipc 0x3976041f	tipc_set_portimportance
+EXPORT_SYMBOL net/tipc/tipc 0x419b02fc	tipc_send2port
+EXPORT_SYMBOL net/tipc/tipc 0x4355703b	tipc_recv_msg
+EXPORT_SYMBOL net/tipc/tipc 0x49097632	tipc_send_buf_fast
+EXPORT_SYMBOL net/tipc/tipc 0x4b2243c6	tipc_portimportance
+EXPORT_SYMBOL net/tipc/tipc 0x4b48f1b2	tipc_send_buf
+EXPORT_SYMBOL net/tipc/tipc 0x53023754	tipc_send_buf2port
+EXPORT_SYMBOL net/tipc/tipc 0x538b228a	tipc_withdraw
+EXPORT_SYMBOL net/tipc/tipc 0x5637ed44	tipc_get_mode
+EXPORT_SYMBOL net/tipc/tipc 0x56e52bc1	tipc_continue
+EXPORT_SYMBOL net/tipc/tipc 0x5c0d4b5c	tipc_ref_valid
+EXPORT_SYMBOL net/tipc/tipc 0x61ac381f	tipc_forward_buf2name
+EXPORT_SYMBOL net/tipc/tipc 0x62a681a3	tipc_portunreturnable
+EXPORT_SYMBOL net/tipc/tipc 0x876309b1	tipc_register_media
+EXPORT_SYMBOL net/tipc/tipc 0x88b73627	tipc_get_addr
+EXPORT_SYMBOL net/tipc/tipc 0x9c45558e	tipc_enable_bearer
+EXPORT_SYMBOL net/tipc/tipc 0xa1b42d32	tipc_forward2port
+EXPORT_SYMBOL net/tipc/tipc 0xa936a24b	tipc_get_port
+EXPORT_SYMBOL net/tipc/tipc 0xa986ba3b	tipc_send_buf2name
+EXPORT_SYMBOL net/tipc/tipc 0xadd203d0	tipc_connect2port
+EXPORT_SYMBOL net/tipc/tipc 0xae0103c3	tipc_shutdown
+EXPORT_SYMBOL net/tipc/tipc 0xb1f8eacc	tipc_send2name
+EXPORT_SYMBOL net/tipc/tipc 0xb35b672c	tipc_publish
+EXPORT_SYMBOL net/tipc/tipc 0xcec8514a	tipc_set_portunreturnable
+EXPORT_SYMBOL net/tipc/tipc 0xcee290be	tipc_forward2name
+EXPORT_SYMBOL net/tipc/tipc 0xd44731e5	tipc_ownidentity
+EXPORT_SYMBOL net/tipc/tipc 0xda7f9d3f	tipc_attach
+EXPORT_SYMBOL net/tipc/tipc 0xdf5008fc	tipc_peer
+EXPORT_SYMBOL net/tipc/tipc 0xe7aece47	tipc_ispublished
+EXPORT_SYMBOL net/tipc/tipc 0xeefd49b3	tipc_get_handle
+EXPORT_SYMBOL net/tipc/tipc 0xef50a1ef	tipc_disable_bearer
+EXPORT_SYMBOL net/tipc/tipc 0xf0842d56	tipc_createport
+EXPORT_SYMBOL net/tipc/tipc 0xf0d6cbae	tipc_forward_buf2port
+EXPORT_SYMBOL net/wanrouter/wanrouter 0x0ebe03d1	unregister_wan_device
+EXPORT_SYMBOL net/wanrouter/wanrouter 0xa386d8b7	register_wan_device
+EXPORT_SYMBOL net/wireless/cfg80211 0x02c44a0a	cfg80211_inform_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0x07e7ac5a	ieee80211_radiotap_iterator_init
+EXPORT_SYMBOL net/wireless/cfg80211 0x09c64fbd	ieee80211_frequency_to_channel
+EXPORT_SYMBOL net/wireless/cfg80211 0x0f7b4e31	wiphy_new
+EXPORT_SYMBOL net/wireless/cfg80211 0x1626878c	wiphy_unregister
+EXPORT_SYMBOL net/wireless/cfg80211 0x1879fcbd	bridge_tunnel_header
+EXPORT_SYMBOL net/wireless/cfg80211 0x1a9da447	cfg80211_michael_mic_failure
+EXPORT_SYMBOL net/wireless/cfg80211 0x1ff1ceb6	wiphy_apply_custom_regulatory
+EXPORT_SYMBOL net/wireless/cfg80211 0x222549a7	regulatory_hint
+EXPORT_SYMBOL net/wireless/cfg80211 0x37ac8d05	ieee80211_get_response_rate
+EXPORT_SYMBOL net/wireless/cfg80211 0x37dd21b0	cfg80211_send_deauth
+EXPORT_SYMBOL net/wireless/cfg80211 0x63a14cbf	cfg80211_send_rx_auth
+EXPORT_SYMBOL net/wireless/cfg80211 0x64a1edfe	cfg80211_roamed
+EXPORT_SYMBOL net/wireless/cfg80211 0x67bfbd92	ieee80211_get_hdrlen_from_skb
+EXPORT_SYMBOL net/wireless/cfg80211 0x69b18f43	rfc1042_header
+EXPORT_SYMBOL net/wireless/cfg80211 0x7a3c3397	cfg80211_connect_result
+EXPORT_SYMBOL net/wireless/cfg80211 0x7b00aa9c	cfg80211_unlink_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0x7c3fddc1	ieee80211_bss_get_ie
+EXPORT_SYMBOL net/wireless/cfg80211 0x7e42873e	wiphy_free
+EXPORT_SYMBOL net/wireless/cfg80211 0x8508669f	wiphy_register
+EXPORT_SYMBOL net/wireless/cfg80211 0x864a2c25	cfg80211_send_disassoc
+EXPORT_SYMBOL net/wireless/cfg80211 0x8b0cfc78	cfg80211_send_assoc_timeout
+EXPORT_SYMBOL net/wireless/cfg80211 0x8c35d732	ieee80211_hdrlen
+EXPORT_SYMBOL net/wireless/cfg80211 0x98f09a3e	wiphy_rfkill_start_polling
+EXPORT_SYMBOL net/wireless/cfg80211 0x9f519895	__ieee80211_get_channel
+EXPORT_SYMBOL net/wireless/cfg80211 0x9fbd4b1d	cfg80211_scan_done
+EXPORT_SYMBOL net/wireless/cfg80211 0xaba5ae30	wiphy_rfkill_set_hw_state
+EXPORT_SYMBOL net/wireless/cfg80211 0xb34f8c78	ieee80211_data_to_8023
+EXPORT_SYMBOL net/wireless/cfg80211 0xb381a524	cfg80211_send_auth_timeout
+EXPORT_SYMBOL net/wireless/cfg80211 0xb9c38ad3	freq_reg_info
+EXPORT_SYMBOL net/wireless/cfg80211 0xbeb59493	cfg80211_inform_bss_frame
+EXPORT_SYMBOL net/wireless/cfg80211 0xc019eed6	cfg80211_get_mesh
+EXPORT_SYMBOL net/wireless/cfg80211 0xc4e85ec5	ieee80211_radiotap_iterator_next
+EXPORT_SYMBOL net/wireless/cfg80211 0xc756ce53	ieee80211_data_from_8023
+EXPORT_SYMBOL net/wireless/cfg80211 0xc92b5db0	wiphy_rfkill_stop_polling
+EXPORT_SYMBOL net/wireless/cfg80211 0xccc291b3	ieee80211_channel_to_frequency
+EXPORT_SYMBOL net/wireless/cfg80211 0xe49f8244	cfg80211_put_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0xea5888c8	cfg80211_disconnected
+EXPORT_SYMBOL net/wireless/cfg80211 0xee0a7f04	cfg80211_get_bss
+EXPORT_SYMBOL net/wireless/cfg80211 0xf129b2ed	cfg80211_ibss_joined
+EXPORT_SYMBOL net/wireless/cfg80211 0xfc343be0	cfg80211_classify8021d
+EXPORT_SYMBOL net/wireless/cfg80211 0xff5725eb	cfg80211_send_rx_assoc
+EXPORT_SYMBOL sound/ac97_bus 0x2af21703	ac97_bus_type
+EXPORT_SYMBOL sound/core/oss/snd-mixer-oss 0xa1a894b4	snd_mixer_oss_ioctl_card
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x1a724fcc	snd_seq_kernel_client_ctl
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x1e24c505	snd_seq_kernel_client_write_poll
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x254f4ee6	snd_seq_create_kernel_client
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x3fb4d161	snd_seq_kernel_client_dispatch
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x6bb71038	snd_seq_delete_kernel_client
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x7ac2f329	snd_seq_expand_var_event
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x7b8699eb	snd_seq_event_port_detach
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x89947013	snd_use_lock_sync_helper
+EXPORT_SYMBOL sound/core/seq/snd-seq 0x9f041a02	snd_seq_kernel_client_enqueue_blocking
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xb8e448a0	snd_seq_set_queue_tempo
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xcac0a3be	snd_seq_kernel_client_enqueue
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xe934da1d	snd_seq_dump_var_event
+EXPORT_SYMBOL sound/core/seq/snd-seq 0xfad06a03	snd_seq_event_port_attach
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x3a57f235	snd_seq_autoload_unlock
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0x6339b6d0	snd_seq_device_load_drivers
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xb90668b2	snd_seq_autoload_lock
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xc622fb29	snd_seq_device_unregister_driver
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xdcaddf0b	snd_seq_device_new
+EXPORT_SYMBOL sound/core/seq/snd-seq-device 0xdfc74412	snd_seq_device_register_driver
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x6ea09972	snd_midi_channel_alloc_set
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0x833a3e07	snd_midi_channel_set_clear
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xb9948d2c	snd_midi_channel_free_set
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-emul 0xf0a1fdb3	snd_midi_process_event
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x17c15809	snd_midi_event_decode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x4ad3f518	snd_midi_event_reset_decode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x62384d3a	snd_midi_event_encode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x8a348811	snd_midi_event_reset_encode
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0x9df7af8b	snd_midi_event_free
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xc482499d	snd_midi_event_new
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xd9072e1a	snd_midi_event_no_status
+EXPORT_SYMBOL sound/core/seq/snd-seq-midi-event 0xe6df29c7	snd_midi_event_encode_byte
+EXPORT_SYMBOL sound/core/seq/snd-seq-virmidi 0xac6f4732	snd_virmidi_new
+EXPORT_SYMBOL sound/core/snd 0x03b86a59	snd_ctl_notify
+EXPORT_SYMBOL sound/core/snd 0x04b08667	snd_ctl_remove
+EXPORT_SYMBOL sound/core/snd 0x07a7f679	snd_device_free
+EXPORT_SYMBOL sound/core/snd 0x09917180	snd_jack_report
+EXPORT_SYMBOL sound/core/snd 0x09e75748	snd_ctl_boolean_stereo_info
+EXPORT_SYMBOL sound/core/snd 0x18e1683f	snd_dma_program
+EXPORT_SYMBOL sound/core/snd 0x191e88cf	snd_dma_pointer
+EXPORT_SYMBOL sound/core/snd 0x198788b4	snd_lookup_oss_minor_data
+EXPORT_SYMBOL sound/core/snd 0x1ab593ed	snd_info_register
+EXPORT_SYMBOL sound/core/snd 0x24a94b26	snd_info_get_line
+EXPORT_SYMBOL sound/core/snd 0x24f6ea2f	snd_card_set_id
+EXPORT_SYMBOL sound/core/snd 0x25b11c51	snd_component_add
+EXPORT_SYMBOL sound/core/snd 0x25e1ac86	snd_jack_set_parent
+EXPORT_SYMBOL sound/core/snd 0x2ae3deaa	release_and_free_resource
+EXPORT_SYMBOL sound/core/snd 0x2ae50461	snd_device_register
+EXPORT_SYMBOL sound/core/snd 0x2b1ecce7	snd_ctl_unregister_ioctl_compat
+EXPORT_SYMBOL sound/core/snd 0x31bf9958	snd_device_new
+EXPORT_SYMBOL sound/core/snd 0x3971b4df	snd_ecards_limit
+EXPORT_SYMBOL sound/core/snd 0x3c844b72	snd_card_free_when_closed
+EXPORT_SYMBOL sound/core/snd 0x484b974f	snd_info_create_card_entry
+EXPORT_SYMBOL sound/core/snd 0x493572fb	snd_ctl_new1
+EXPORT_SYMBOL sound/core/snd 0x4a3ea5c0	snd_request_card
+EXPORT_SYMBOL sound/core/snd 0x4ecb50d9	snd_card_file_add
+EXPORT_SYMBOL sound/core/snd 0x518bb7f8	copy_from_user_toio
+EXPORT_SYMBOL sound/core/snd 0x5e29e1e9	snd_ctl_register_ioctl
+EXPORT_SYMBOL sound/core/snd 0x5f26bdc9	snd_ctl_remove_id
+EXPORT_SYMBOL sound/core/snd 0x61104349	snd_info_create_module_entry
+EXPORT_SYMBOL sound/core/snd 0x643d0ba1	snd_seq_root
+EXPORT_SYMBOL sound/core/snd 0x655e6e47	_snd_ctl_add_slave
+EXPORT_SYMBOL sound/core/snd 0x683cd25e	snd_card_proc_new
+EXPORT_SYMBOL sound/core/snd 0x6bf45350	snd_ctl_find_numid
+EXPORT_SYMBOL sound/core/snd 0x70c15ac1	snd_dma_disable
+EXPORT_SYMBOL sound/core/snd 0x717dacd3	snd_ctl_make_virtual_master
+EXPORT_SYMBOL sound/core/snd 0x72c63ea7	snd_card_disconnect
+EXPORT_SYMBOL sound/core/snd 0x73fe3259	snd_ctl_boolean_mono_info
+EXPORT_SYMBOL sound/core/snd 0x852f8c6b	snd_ctl_register_ioctl_compat
+EXPORT_SYMBOL sound/core/snd 0x8785858c	snd_pci_quirk_lookup
+EXPORT_SYMBOL sound/core/snd 0x8df3789f	snd_oss_info_register
+EXPORT_SYMBOL sound/core/snd 0x8f595b11	snd_major
+EXPORT_SYMBOL sound/core/snd 0x934954fb	snd_ctl_find_id
+EXPORT_SYMBOL sound/core/snd 0x94c09f1f	snd_mixer_oss_notify_callback
+EXPORT_SYMBOL sound/core/snd 0x99abe355	snd_card_file_remove
+EXPORT_SYMBOL sound/core/snd 0x9e6d79f8	snd_info_get_str
+EXPORT_SYMBOL sound/core/snd 0xa97edc3c	snd_add_device_sysfs_file
+EXPORT_SYMBOL sound/core/snd 0xb2e5ae4a	snd_lookup_minor_data
+EXPORT_SYMBOL sound/core/snd 0xb7b2a454	snd_card_free
+EXPORT_SYMBOL sound/core/snd 0xbefb6d3c	snd_unregister_oss_device
+EXPORT_SYMBOL sound/core/snd 0xc6ec6f4e	snd_card_create
+EXPORT_SYMBOL sound/core/snd 0xcbb9fff5	snd_info_free_entry
+EXPORT_SYMBOL sound/core/snd 0xd4520090	snd_ctl_rename_id
+EXPORT_SYMBOL sound/core/snd 0xd7758667	snd_jack_new
+EXPORT_SYMBOL sound/core/snd 0xda25cb2f	snd_ctl_unregister_ioctl
+EXPORT_SYMBOL sound/core/snd 0xdd5814de	snd_cards
+EXPORT_SYMBOL sound/core/snd 0xe20c9214	snd_iprintf
+EXPORT_SYMBOL sound/core/snd 0xe243dde3	copy_to_user_fromio
+EXPORT_SYMBOL sound/core/snd 0xe5aa27c0	snd_card_register
+EXPORT_SYMBOL sound/core/snd 0xe5bf757b	snd_power_wait
+EXPORT_SYMBOL sound/core/snd 0xe647019d	snd_register_oss_device
+EXPORT_SYMBOL sound/core/snd 0xf43139e1	snd_ctl_free_one
+EXPORT_SYMBOL sound/core/snd 0xfaffae25	snd_unregister_device
+EXPORT_SYMBOL sound/core/snd 0xfb0cadaf	snd_register_device_for_dev
+EXPORT_SYMBOL sound/core/snd 0xfd57f6d4	snd_ctl_add
+EXPORT_SYMBOL sound/core/snd-hwdep 0x58b4e545	snd_hwdep_new
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x19cc2ce3	snd_free_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x2e36572c	snd_dma_alloc_pages_fallback
+EXPORT_SYMBOL sound/core/snd-page-alloc 0x8762f053	snd_dma_reserve_buf
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xa9f3e96f	snd_dma_alloc_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xc6829020	snd_malloc_pages
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xc8dc5ff3	snd_dma_get_reserved_buf
+EXPORT_SYMBOL sound/core/snd-page-alloc 0xeabb8f89	snd_dma_free_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0x0283dfe3	_snd_pcm_hw_params_any
+EXPORT_SYMBOL sound/core/snd-pcm 0x04cda566	snd_interval_refine
+EXPORT_SYMBOL sound/core/snd-pcm 0x08bd3a0d	snd_pcm_period_elapsed
+EXPORT_SYMBOL sound/core/snd-pcm 0x0f30ffd1	snd_pcm_limit_hw_rates
+EXPORT_SYMBOL sound/core/snd-pcm 0x12d6b0dc	snd_pcm_lib_write
+EXPORT_SYMBOL sound/core/snd-pcm 0x1d027e4b	snd_pcm_format_signed
+EXPORT_SYMBOL sound/core/snd-pcm 0x231fcd4e	snd_pcm_lib_preallocate_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0x24b81be2	snd_pcm_sgbuf_get_chunk_size
+EXPORT_SYMBOL sound/core/snd-pcm 0x2580264b	snd_pcm_hw_constraint_msbits
+EXPORT_SYMBOL sound/core/snd-pcm 0x33507536	snd_pcm_suspend
+EXPORT_SYMBOL sound/core/snd-pcm 0x3796bdcc	snd_pcm_format_little_endian
+EXPORT_SYMBOL sound/core/snd-pcm 0x39bf9301	_snd_pcm_hw_param_setempty
+EXPORT_SYMBOL sound/core/snd-pcm 0x483db034	snd_pcm_hw_param_last
+EXPORT_SYMBOL sound/core/snd-pcm 0x4deaf99f	snd_pcm_hw_constraint_ratdens
+EXPORT_SYMBOL sound/core/snd-pcm 0x4f816e9b	snd_pcm_format_big_endian
+EXPORT_SYMBOL sound/core/snd-pcm 0x520bd5e5	snd_pcm_set_ops
+EXPORT_SYMBOL sound/core/snd-pcm 0x52e3e4a5	snd_pcm_hw_param_value
+EXPORT_SYMBOL sound/core/snd-pcm 0x53f64321	snd_pcm_hw_param_first
+EXPORT_SYMBOL sound/core/snd-pcm 0x53fc0551	snd_pcm_lib_mmap_iomem
+EXPORT_SYMBOL sound/core/snd-pcm 0x579e237f	snd_pcm_new_stream
+EXPORT_SYMBOL sound/core/snd-pcm 0x5b502ced	snd_pcm_mmap_data
+EXPORT_SYMBOL sound/core/snd-pcm 0x5ba4c38e	snd_pcm_kernel_ioctl
+EXPORT_SYMBOL sound/core/snd-pcm 0x5e7f4920	snd_pcm_format_set_silence
+EXPORT_SYMBOL sound/core/snd-pcm 0x650f8603	snd_pcm_format_silence_64
+EXPORT_SYMBOL sound/core/snd-pcm 0x68a24153	snd_pcm_format_physical_width
+EXPORT_SYMBOL sound/core/snd-pcm 0x6ef8fcd8	snd_pcm_format_linear
+EXPORT_SYMBOL sound/core/snd-pcm 0x7d362f6c	snd_pcm_lib_read
+EXPORT_SYMBOL sound/core/snd-pcm 0x7ee8a65e	snd_pcm_stop
+EXPORT_SYMBOL sound/core/snd-pcm 0x88cc66cc	snd_pcm_link_rwlock
+EXPORT_SYMBOL sound/core/snd-pcm 0x88d641bd	snd_pcm_suspend_all
+EXPORT_SYMBOL sound/core/snd-pcm 0x90739a2a	snd_pcm_set_sync
+EXPORT_SYMBOL sound/core/snd-pcm 0x91da9ab0	snd_pcm_hw_constraint_list
+EXPORT_SYMBOL sound/core/snd-pcm 0x942be89e	snd_pcm_notify
+EXPORT_SYMBOL sound/core/snd-pcm 0x9ffd6616	snd_pcm_lib_malloc_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0xa45add8c	snd_pcm_lib_ioctl
+EXPORT_SYMBOL sound/core/snd-pcm 0xa61aa028	snd_pcm_format_unsigned
+EXPORT_SYMBOL sound/core/snd-pcm 0xa6a3733c	snd_pcm_open_substream
+EXPORT_SYMBOL sound/core/snd-pcm 0xab8e9cf5	snd_pcm_hw_constraint_ratnums
+EXPORT_SYMBOL sound/core/snd-pcm 0xb2499562	snd_pcm_hw_constraint_integer
+EXPORT_SYMBOL sound/core/snd-pcm 0xb62c5b1c	snd_pcm_lib_preallocate_pages_for_all
+EXPORT_SYMBOL sound/core/snd-pcm 0xb8bd2c18	snd_pcm_hw_refine
+EXPORT_SYMBOL sound/core/snd-pcm 0xb9638db4	snd_pcm_rate_to_rate_bit
+EXPORT_SYMBOL sound/core/snd-pcm 0xbb99921b	snd_pcm_lib_readv
+EXPORT_SYMBOL sound/core/snd-pcm 0xc784d2f0	snd_pcm_lib_free_pages
+EXPORT_SYMBOL sound/core/snd-pcm 0xcb413394	snd_pcm_lib_writev
+EXPORT_SYMBOL sound/core/snd-pcm 0xd0b9b8b8	snd_interval_list
+EXPORT_SYMBOL sound/core/snd-pcm 0xdb4af5af	snd_pcm_hw_constraint_pow2
+EXPORT_SYMBOL sound/core/snd-pcm 0xe51a1c64	snd_pcm_format_size
+EXPORT_SYMBOL sound/core/snd-pcm 0xe56a9336	snd_pcm_format_width
+EXPORT_SYMBOL sound/core/snd-pcm 0xe5ad8ce3	snd_pcm_hw_rule_add
+EXPORT_SYMBOL sound/core/snd-pcm 0xe67bb3d9	snd_pcm_new
+EXPORT_SYMBOL sound/core/snd-pcm 0xe6c7bc5c	snd_pcm_hw_constraint_step
+EXPORT_SYMBOL sound/core/snd-pcm 0xee35bd70	snd_pcm_release_substream
+EXPORT_SYMBOL sound/core/snd-pcm 0xf3797152	snd_interval_ratnum
+EXPORT_SYMBOL sound/core/snd-pcm 0xf6f21b4f	snd_pcm_hw_constraint_minmax
+EXPORT_SYMBOL sound/core/snd-pcm 0xfae73bee	snd_pcm_lib_preallocate_free_for_all
+EXPORT_SYMBOL sound/core/snd-pcm 0xfdb637d8	snd_pcm_sgbuf_ops_page
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x1d2eb1aa	snd_rawmidi_receive
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x26dc2f92	snd_rawmidi_new
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x2845707c	snd_rawmidi_drain_output
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x47434144	snd_rawmidi_transmit_peek
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x51859a20	snd_rawmidi_kernel_read
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x5bc10f0b	snd_rawmidi_kernel_write
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x61858da2	snd_rawmidi_drain_input
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x622f3239	snd_rawmidi_kernel_release
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x93a63067	snd_rawmidi_transmit_ack
+EXPORT_SYMBOL sound/core/snd-rawmidi 0x99f8c6ef	snd_rawmidi_info_select
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xa0c84658	snd_rawmidi_drop_output
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xa16442a8	snd_rawmidi_input_params
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xa6b4e100	snd_rawmidi_kernel_open
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xb94217d5	snd_rawmidi_output_params
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xc91216e7	snd_rawmidi_set_ops
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xce300771	snd_rawmidi_transmit_empty
+EXPORT_SYMBOL sound/core/snd-rawmidi 0xe9543205	snd_rawmidi_transmit
+EXPORT_SYMBOL sound/core/snd-timer 0x04ad3036	snd_timer_global_register
+EXPORT_SYMBOL sound/core/snd-timer 0x3af7d49f	snd_timer_global_free
+EXPORT_SYMBOL sound/core/snd-timer 0x4163c1b8	snd_timer_notify
+EXPORT_SYMBOL sound/core/snd-timer 0x44aa22a7	snd_timer_start
+EXPORT_SYMBOL sound/core/snd-timer 0x54ae2336	snd_timer_pause
+EXPORT_SYMBOL sound/core/snd-timer 0x9c47d2ff	snd_timer_close
+EXPORT_SYMBOL sound/core/snd-timer 0x9fa0c8ab	snd_timer_interrupt
+EXPORT_SYMBOL sound/core/snd-timer 0xafe62b95	snd_timer_new
+EXPORT_SYMBOL sound/core/snd-timer 0xb8a14c3e	snd_timer_open
+EXPORT_SYMBOL sound/core/snd-timer 0xcb3cdb1c	snd_timer_resolution
+EXPORT_SYMBOL sound/core/snd-timer 0xda3335e3	snd_timer_continue
+EXPORT_SYMBOL sound/core/snd-timer 0xe508aa08	snd_timer_stop
+EXPORT_SYMBOL sound/core/snd-timer 0xeaf404a5	snd_timer_global_new
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x4bbb7f27	snd_mpu401_uart_interrupt_tx
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0x6e0ffda9	snd_mpu401_uart_new
+EXPORT_SYMBOL sound/drivers/mpu401/snd-mpu401-uart 0xc43a3940	snd_mpu401_uart_interrupt
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x05060a19	snd_opl3_regmap
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x197f3901	snd_opl3_reset
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x1b358e30	snd_opl3_interrupt
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x29170618	snd_opl3_timer_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x36216327	snd_opl3_init
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x5c940b38	snd_opl3_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0x745c901a	snd_opl3_load_patch
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xbc6fb4d3	snd_opl3_hwdep_new
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xcbf92d84	snd_opl3_create
+EXPORT_SYMBOL sound/drivers/opl3/snd-opl3-lib 0xe4d798b1	snd_opl3_find_patch
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x1dbaf7e0	snd_vx_setup_firmware
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x5467c437	snd_vx_suspend
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x5a2df4a4	snd_vx_load_boot_image
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x8fc838ce	snd_vx_free_firmware
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x920ec957	snd_vx_create
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0x99b88ede	snd_vx_irq_handler
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xb770f6fd	snd_vx_dsp_boot
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xc75faf33	snd_vx_check_reg_bit
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xd8deae45	snd_vx_dsp_load
+EXPORT_SYMBOL sound/drivers/vx/snd-vx-lib 0xe80aca55	snd_vx_resume
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x05585cf4	snd_ak4114_external_rate
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x144b9ce8	snd_ak4114_build
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x24ea9a85	snd_ak4114_create
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x43430215	snd_ak4114_reg_write
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x53034077	snd_ak4114_reinit
+EXPORT_SYMBOL sound/i2c/other/snd-ak4114 0x7b80d525	snd_ak4114_check_rate_and_errors
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x6e9468cd	snd_ak4117_reg_write
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0x8dea179e	snd_ak4117_check_rate_and_errors
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xb5a1b305	snd_ak4117_create
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xcec8eb59	snd_ak4117_reinit
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xe2c46a72	snd_ak4117_build
+EXPORT_SYMBOL sound/i2c/other/snd-ak4117 0xe66f10c9	snd_ak4117_external_rate
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x171cb51f	snd_akm4xxx_init
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0x8c67b439	snd_akm4xxx_write
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xba6d3830	snd_akm4xxx_build_controls
+EXPORT_SYMBOL sound/i2c/other/snd-ak4xxx-adda 0xd875e571	snd_akm4xxx_reset
+EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0x07767dc1	snd_pt2258_build_controls
+EXPORT_SYMBOL sound/i2c/other/snd-pt2258 0xaba7fdc3	snd_pt2258_reset
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x07488fd5	snd_cs8427_iec958_build
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0x8484080d	snd_cs8427_create
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0xcb40874f	snd_cs8427_iec958_pcm
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0xd2591da4	snd_cs8427_reg_write
+EXPORT_SYMBOL sound/i2c/snd-cs8427 0xf3d08d4d	snd_cs8427_iec958_active
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x348faa7b	snd_i2c_readbytes
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x48ebdb6c	snd_i2c_sendbytes
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x5417f0f1	snd_i2c_bus_create
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x69c88493	snd_i2c_device_free
+EXPORT_SYMBOL sound/i2c/snd-i2c 0x8e666b4f	snd_i2c_probeaddr
+EXPORT_SYMBOL sound/i2c/snd-i2c 0xba7d2e01	snd_i2c_device_create
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x15108f22	snd_sbmixer_read
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x1a6697f5	snd_sbmixer_new
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x2582146f	snd_sbdsp_reset
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x57313b53	snd_sbmixer_suspend
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x71c700a9	snd_sbdsp_get_byte
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x83f73c96	snd_sbmixer_resume
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0x87fd3cc4	snd_sbmixer_write
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xaf1afe04	snd_sbdsp_command
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xc60b0a09	snd_sbmixer_add_ctl
+EXPORT_SYMBOL sound/isa/sb/snd-sb-common 0xd7ec34e4	snd_sbdsp_create
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x3c96d856	snd_sb16dsp_get_pcm_ops
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0x6f3eff73	snd_sb16dsp_configure
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xc57f5b54	snd_sb16dsp_interrupt
+EXPORT_SYMBOL sound/isa/sb/snd-sb16-dsp 0xf6ec697a	snd_sb16dsp_pcm
+EXPORT_SYMBOL sound/oss/ad1848 0x26c427ee	ad1848_detect
+EXPORT_SYMBOL sound/oss/ad1848 0x55262c70	probe_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0x9bf1cc62	ad1848_unload
+EXPORT_SYMBOL sound/oss/ad1848 0xa3d3f474	ad1848_init
+EXPORT_SYMBOL sound/oss/ad1848 0xb29a9148	unload_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0xb79f6983	attach_ms_sound
+EXPORT_SYMBOL sound/oss/ad1848 0xc04f6f67	ad1848_control
+EXPORT_SYMBOL sound/oss/mpu401 0x55e1a032	attach_mpu401
+EXPORT_SYMBOL sound/oss/mpu401 0x5febf284	unload_mpu401
+EXPORT_SYMBOL sound/oss/mpu401 0xd9ec5db4	probe_mpu401
+EXPORT_SYMBOL sound/oss/sb_lib 0x42424109	sb_be_quiet
+EXPORT_SYMBOL sound/oss/sb_lib 0x450f9aea	smw_free
+EXPORT_SYMBOL sound/oss/sb_lib 0x74afd69c	unload_sbmpu
+EXPORT_SYMBOL sound/oss/sb_lib 0x9787c556	probe_sbmpu
+EXPORT_SYMBOL sound/oss/sb_lib 0xc4884969	sb_dsp_unload
+EXPORT_SYMBOL sound/oss/sb_lib 0xd8a2731c	sb_dsp_detect
+EXPORT_SYMBOL sound/oss/sb_lib 0xde611935	sb_dsp_init
+EXPORT_SYMBOL sound/oss/sound 0x01a7a338	sound_timer_devs
+EXPORT_SYMBOL sound/oss/sound 0x04c87ec8	compute_finetune
+EXPORT_SYMBOL sound/oss/sound 0x06339815	sound_unload_synthdev
+EXPORT_SYMBOL sound/oss/sound 0x0f280035	conf_printf
+EXPORT_SYMBOL sound/oss/sound 0x17ba231d	seq_input_event
+EXPORT_SYMBOL sound/oss/sound 0x1b3df3cf	sound_alloc_mixerdev
+EXPORT_SYMBOL sound/oss/sound 0x1f395686	MIDIbuf_avail
+EXPORT_SYMBOL sound/oss/sound 0x2161d5e8	sound_timer_init
+EXPORT_SYMBOL sound/oss/sound 0x2aa31695	midi_synth_kill_note
+EXPORT_SYMBOL sound/oss/sound 0x2edea165	mixer_devs
+EXPORT_SYMBOL sound/oss/sound 0x330a9074	audio_devs
+EXPORT_SYMBOL sound/oss/sound 0x394cb088	sound_free_dma
+EXPORT_SYMBOL sound/oss/sound 0x418f5fbe	sound_close_dma
+EXPORT_SYMBOL sound/oss/sound 0x4cd01bdd	num_audiodevs
+EXPORT_SYMBOL sound/oss/sound 0x4ff47e9d	midi_synth_setup_voice
+EXPORT_SYMBOL sound/oss/sound 0x514151d9	sound_install_mixer
+EXPORT_SYMBOL sound/oss/sound 0x51e354b2	sound_alloc_timerdev
+EXPORT_SYMBOL sound/oss/sound 0x56504ca2	midi_synth_reset
+EXPORT_SYMBOL sound/oss/sound 0x5d986fc9	note_to_freq
+EXPORT_SYMBOL sound/oss/sound 0x70af15d9	synth_devs
+EXPORT_SYMBOL sound/oss/sound 0x7679ee76	seq_copy_to_input
+EXPORT_SYMBOL sound/oss/sound 0x7bdf0907	conf_printf2
+EXPORT_SYMBOL sound/oss/sound 0x892093e0	midi_synth_controller
+EXPORT_SYMBOL sound/oss/sound 0x90bd9714	sequencer_timer
+EXPORT_SYMBOL sound/oss/sound 0x987bcf12	DMAbuf_outputintr
+EXPORT_SYMBOL sound/oss/sound 0x9a95733f	sound_alloc_dma
+EXPORT_SYMBOL sound/oss/sound 0x9bdaf24d	midi_synth_start_note
+EXPORT_SYMBOL sound/oss/sound 0x9d845b18	num_mixers
+EXPORT_SYMBOL sound/oss/sound 0xa1d5f04f	load_mixer_volumes
+EXPORT_SYMBOL sound/oss/sound 0xa1eae7cf	num_midis
+EXPORT_SYMBOL sound/oss/sound 0xa41ead5f	sound_unload_timerdev
+EXPORT_SYMBOL sound/oss/sound 0xa51c913b	sound_unload_mixerdev
+EXPORT_SYMBOL sound/oss/sound 0xa6bb414c	sound_unload_mididev
+EXPORT_SYMBOL sound/oss/sound 0xa948751e	sound_unload_audiodev
+EXPORT_SYMBOL sound/oss/sound 0xad45df73	midi_synth_close
+EXPORT_SYMBOL sound/oss/sound 0xaef743b2	midi_synth_ioctl
+EXPORT_SYMBOL sound/oss/sound 0xb14b22cd	midi_synth_hw_control
+EXPORT_SYMBOL sound/oss/sound 0xb51587f6	do_midi_msg
+EXPORT_SYMBOL sound/oss/sound 0xba413f87	sound_alloc_mididev
+EXPORT_SYMBOL sound/oss/sound 0xba7dd041	midi_synth_bender
+EXPORT_SYMBOL sound/oss/sound 0xbafcb775	sound_install_audiodrv
+EXPORT_SYMBOL sound/oss/sound 0xc748d109	sound_alloc_synthdev
+EXPORT_SYMBOL sound/oss/sound 0xcab4d5bf	midi_synth_load_patch
+EXPORT_SYMBOL sound/oss/sound 0xcc4b8797	sound_open_dma
+EXPORT_SYMBOL sound/oss/sound 0xd85be938	midi_synth_set_instr
+EXPORT_SYMBOL sound/oss/sound 0xdb400afa	midi_synth_panning
+EXPORT_SYMBOL sound/oss/sound 0xe056b71c	DMAbuf_start_dma
+EXPORT_SYMBOL sound/oss/sound 0xe2675a79	sound_timer_interrupt
+EXPORT_SYMBOL sound/oss/sound 0xeb315d99	DMAbuf_inputintr
+EXPORT_SYMBOL sound/oss/sound 0xf1ea8a20	midi_synth_aftertouch
+EXPORT_SYMBOL sound/oss/sound 0xf6b3a2fb	midi_synth_open
+EXPORT_SYMBOL sound/oss/sound 0xf78f6363	sequencer_init
+EXPORT_SYMBOL sound/oss/sound 0xf82e52fb	midi_devs
+EXPORT_SYMBOL sound/oss/sound 0xfa6871be	sound_timer_syncinterval
+EXPORT_SYMBOL sound/oss/sound 0xfddcbfb3	midi_synth_send_sysex
+EXPORT_SYMBOL sound/oss/uart401 0x049cd8b7	uart401intr
+EXPORT_SYMBOL sound/oss/uart401 0x18e17a91	probe_uart401
+EXPORT_SYMBOL sound/oss/uart401 0xecfdd9c9	unload_uart401
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x134c8f67	snd_ac97_pcm_open
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x23316534	snd_ac97_pcm_close
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x24dbcf59	snd_ac97_resume
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3a886194	snd_ac97_update_bits
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x3b1c8c11	snd_ac97_update_power
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x5e38e80c	snd_ac97_set_rate
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x62a7033f	snd_ac97_bus
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x6ae5fddb	snd_ac97_read
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x6d2717de	snd_ac97_get_short_name
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x76a52dc7	snd_ac97_update
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x77e37999	snd_ac97_pcm_double_rate_rules
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0x819376f0	snd_ac97_write
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xaca171bd	snd_ac97_write_cache
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xb71d2eed	snd_ac97_suspend
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xcfa20890	snd_ac97_pcm_assign
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xe2dad34e	snd_ac97_mixer
+EXPORT_SYMBOL sound/pci/ac97/snd-ac97-codec 0xf9884fa3	snd_ac97_tune_hardware
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x240f4baa	snd_emu10k1_ptr_write
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x2523b554	snd_emu10k1_ptr_read
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x2886ac2b	snd_emu10k1_voice_free
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x560ad904	snd_emu10k1_synth_bzero
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x72b45202	snd_emu10k1_memblk_map
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0x74616faa	snd_emu10k1_voice_alloc
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xa816b14f	snd_emu10k1_synth_free
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xc4fb3a7f	snd_emu10k1_synth_copy_from_user
+EXPORT_SYMBOL sound/pci/emu10k1/snd-emu10k1 0xeccc18af	snd_emu10k1_synth_alloc
+EXPORT_SYMBOL sound/pci/hda/snd-hda-codec 0xac243c9b	snd_hda_parse_generic_codec
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0x850245e2	snd_ice1712_akm4xxx_build_controls
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xe3f6b712	snd_ice1712_akm4xxx_free
+EXPORT_SYMBOL sound/pci/ice1712/snd-ice17xx-ak4xxx 0xf34ec9a6	snd_ice1712_akm4xxx_init
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x01283d88	oxygen_write8
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x0b48813e	oxygen_write_ac97
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x0deaf76f	oxygen_read16
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x1cd72a2b	oxygen_read32
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x32f65b4c	oxygen_write_uart
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x40075efc	oxygen_write8_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x5dfbae1e	oxygen_read8
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x71250dc9	oxygen_write32_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x755a09d4	oxygen_read_ac97
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x78f9f95f	oxygen_write16_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7a91e8a2	oxygen_pci_probe
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x7bbdcfe0	oxygen_write_spi
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x867ccf03	oxygen_write_i2c
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x940d1e14	oxygen_reset_uart
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x972d93d1	oxygen_write32
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x9d1f1db3	oxygen_pci_resume
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0x9ed9494f	oxygen_pci_remove
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xa060cd46	oxygen_pci_suspend
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xb9d31aa1	oxygen_write_ac97_masked
+EXPORT_SYMBOL sound/pci/oxygen/snd-oxygen-lib 0xff7c012b	oxygen_write16
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x272f4f62	snd_trident_free_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x5a428e4a	snd_trident_start_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x5ade1a5a	snd_trident_write_voice_regs
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0x8abe943e	snd_trident_stop_voice
+EXPORT_SYMBOL sound/pci/trident/snd-trident 0xefdff209	snd_trident_alloc_voice
+EXPORT_SYMBOL sound/sound_firmware 0x39e3dd23	mod_firmware_load
+EXPORT_SYMBOL sound/soundcore 0x026f802b	register_sound_special_device
+EXPORT_SYMBOL sound/soundcore 0x4cafef24	register_sound_mixer
+EXPORT_SYMBOL sound/soundcore 0x7afc9d8a	unregister_sound_mixer
+EXPORT_SYMBOL sound/soundcore 0x88da6915	register_sound_dsp
+EXPORT_SYMBOL sound/soundcore 0x99c95fa5	unregister_sound_special
+EXPORT_SYMBOL sound/soundcore 0xc042d0de	register_sound_special
+EXPORT_SYMBOL sound/soundcore 0xcacfce59	sound_class
+EXPORT_SYMBOL sound/soundcore 0xcd083b10	unregister_sound_dsp
+EXPORT_SYMBOL sound/soundcore 0xfa15723a	register_sound_midi
+EXPORT_SYMBOL sound/soundcore 0xfdab6de3	unregister_sound_midi
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x14aec48b	snd_emux_new
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x33473b35	snd_emux_lock_voice
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x37a1a704	snd_emux_terminate_all
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x655cb202	snd_sf_linear_to_log
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0x8ee6f3af	snd_emux_register
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xcc1eb526	snd_emux_unlock_voice
+EXPORT_SYMBOL sound/synth/emux/snd-emux-synth 0xdea01907	snd_emux_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x20a92357	snd_util_memhdr_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x2428a33a	__snd_util_mem_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x341541ca	snd_util_mem_alloc
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x93411883	snd_util_mem_free
+EXPORT_SYMBOL sound/synth/snd-util-mem 0x940d3d3b	snd_util_memhdr_new
+EXPORT_SYMBOL sound/synth/snd-util-mem 0xd3efa1a8	__snd_util_memblk_new
+EXPORT_SYMBOL sound/synth/snd-util-mem 0xda893279	__snd_util_mem_alloc
+EXPORT_SYMBOL sound/synth/snd-util-mem 0xfa651f66	snd_util_mem_avail
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0x16756dc0	snd_usbmidi_input_start
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0x63343b1d	snd_usbmidi_input_stop
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0xb065f46e	snd_usb_create_midi_interface
+EXPORT_SYMBOL sound/usb/snd-usb-lib 0xd9d2bb03	snd_usbmidi_disconnect
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x0b9f871b	dm_mem_cache_grow
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x8eb29a60	dm_mem_cache_free
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x920a7a41	dm_message_parse
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0x9b90d856	dm_mem_cache_alloc
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0xbdb3751c	dm_mem_cache_client_destroy
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0xd9095fef	dm_mem_cache_client_create
+EXPORT_SYMBOL ubuntu/dm-raid4-5/dm-raid45 0xea0356bd	dm_mem_cache_shrink
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x04dca738	lirc_unregister_driver
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0x3700a82e	lirc_get_pdata
+EXPORT_SYMBOL ubuntu/lirc/lirc_dev/lirc_dev 0xd18bdf96	lirc_register_driver
+EXPORT_SYMBOL vmlinux 0x00000000	per_cpu__softirq_work_list
+EXPORT_SYMBOL vmlinux 0x003fd79e	__inc_zone_page_state
+EXPORT_SYMBOL vmlinux 0x004a4f86	mutex_lock
+EXPORT_SYMBOL vmlinux 0x00801678	flush_scheduled_work
+EXPORT_SYMBOL vmlinux 0x0097d429	neigh_event_ns
+EXPORT_SYMBOL vmlinux 0x009d258f	_write_lock
+EXPORT_SYMBOL vmlinux 0x00c4dc87	timecounter_init
+EXPORT_SYMBOL vmlinux 0x00f8bde6	cdrom_get_last_written
+EXPORT_SYMBOL vmlinux 0x01000e51	schedule
+EXPORT_SYMBOL vmlinux 0x010efd0c	poll_freewait
+EXPORT_SYMBOL vmlinux 0x01139ffc	max_mapnr
+EXPORT_SYMBOL vmlinux 0x0117957f	bio_integrity_get_tag
+EXPORT_SYMBOL vmlinux 0x0137a726	journal_get_create_access
+EXPORT_SYMBOL vmlinux 0x01439b0f	skb_gso_segment
+EXPORT_SYMBOL vmlinux 0x01599002	netif_napi_add
+EXPORT_SYMBOL vmlinux 0x016a08fd	rdmsr_on_cpus
+EXPORT_SYMBOL vmlinux 0x0186d073	percpu_counter_set
+EXPORT_SYMBOL vmlinux 0x01902adf	netpoll_trap
+EXPORT_SYMBOL vmlinux 0x0199199d	dquot_free_inode
+EXPORT_SYMBOL vmlinux 0x01a4aab6	set_irq_chip_data
+EXPORT_SYMBOL vmlinux 0x01ac98d7	unregister_tcf_proto_ops
+EXPORT_SYMBOL vmlinux 0x01c64827	handle_sysrq
+EXPORT_SYMBOL vmlinux 0x01e0fadb	compat_ip_setsockopt
+EXPORT_SYMBOL vmlinux 0x01f788fb	kernel_recvmsg
+EXPORT_SYMBOL vmlinux 0x01f9fcba	blk_end_request
+EXPORT_SYMBOL vmlinux 0x0209a58f	pcim_iomap_table
+EXPORT_SYMBOL vmlinux 0x020d0584	ip_dev_find
+EXPORT_SYMBOL vmlinux 0x02124474	ip_send_check
+EXPORT_SYMBOL vmlinux 0x02165a2d	nf_unregister_sockopt
+EXPORT_SYMBOL vmlinux 0x0237b57a	arch_unregister_cpu
+EXPORT_SYMBOL vmlinux 0x0256389f	bit_waitqueue
+EXPORT_SYMBOL vmlinux 0x02649054	security_sock_rcv_skb
+EXPORT_SYMBOL vmlinux 0x0269f201	neigh_update
+EXPORT_SYMBOL vmlinux 0x029444f0	native_read_tsc
+EXPORT_SYMBOL vmlinux 0x02a6ce5a	crc16_table
+EXPORT_SYMBOL vmlinux 0x02d81845	audit_log_task_context
+EXPORT_SYMBOL vmlinux 0x02de9981	wake_up_process
+EXPORT_SYMBOL vmlinux 0x0307ec1a	qdisc_reset
+EXPORT_SYMBOL vmlinux 0x03247cd3	dquot_alloc_space
+EXPORT_SYMBOL vmlinux 0x0334da4e	scsi_command_size_tbl
+EXPORT_SYMBOL vmlinux 0x033d0c3e	vfs_set_dqblk
+EXPORT_SYMBOL vmlinux 0x0340e0ae	schedule_delayed_work
+EXPORT_SYMBOL vmlinux 0x037a0cba	kfree
+EXPORT_SYMBOL vmlinux 0x03aafda8	__wait_on_buffer
+EXPORT_SYMBOL vmlinux 0x03c06156	bitmap_fold
+EXPORT_SYMBOL vmlinux 0x03fd2571	vm_unmap_ram
+EXPORT_SYMBOL vmlinux 0x0422fe4a	inet_csk_timer_bug_msg
+EXPORT_SYMBOL vmlinux 0x042c5d9c	gnttab_post_map_adjust
+EXPORT_SYMBOL vmlinux 0x0487f831	fb_find_best_display
+EXPORT_SYMBOL vmlinux 0x048e17d0	napi_reuse_skb
+EXPORT_SYMBOL vmlinux 0x04a71410	alloc_etherdev_mq
+EXPORT_SYMBOL vmlinux 0x04b8daee	blk_queue_update_dma_pad
+EXPORT_SYMBOL vmlinux 0x04d073c5	get_io_context
+EXPORT_SYMBOL vmlinux 0x050a3b82	pci_find_parent_resource
+EXPORT_SYMBOL vmlinux 0x05120889	inet_csk_accept
+EXPORT_SYMBOL vmlinux 0x05139e8a	splice_from_pipe_next
+EXPORT_SYMBOL vmlinux 0x05240ee7	percpu_counter_batch
+EXPORT_SYMBOL vmlinux 0x0528c8c4	mutex_trylock
+EXPORT_SYMBOL vmlinux 0x0530c750	kick_iocb
+EXPORT_SYMBOL vmlinux 0x057a477d	register_gifconf
+EXPORT_SYMBOL vmlinux 0x059c7c41	tty_vhangup
+EXPORT_SYMBOL vmlinux 0x05e210fa	sk_alloc
+EXPORT_SYMBOL vmlinux 0x05e28d43	__first_cpu
+EXPORT_SYMBOL vmlinux 0x05e683e0	netpoll_cleanup
+EXPORT_SYMBOL vmlinux 0x05e8b505	posix_lock_file_wait
+EXPORT_SYMBOL vmlinux 0x05f3be28	xfrm_unregister_km
+EXPORT_SYMBOL vmlinux 0x05f8e5d3	setup_new_exec
+EXPORT_SYMBOL vmlinux 0x061651be	strcat
+EXPORT_SYMBOL vmlinux 0x06410a6d	jbd2_journal_set_triggers
+EXPORT_SYMBOL vmlinux 0x06459dc3	kernel_bind
+EXPORT_SYMBOL vmlinux 0x0649341c	netpoll_setup
+EXPORT_SYMBOL vmlinux 0x064bec75	blk_queue_prep_rq
+EXPORT_SYMBOL vmlinux 0x06632587	netlink_rcv_skb
+EXPORT_SYMBOL vmlinux 0x066f9fd1	path_get
+EXPORT_SYMBOL vmlinux 0x067d8d35	security_release_secctx
+EXPORT_SYMBOL vmlinux 0x068c7263	ioremap_cache
+EXPORT_SYMBOL vmlinux 0x06a485f2	__krealloc
+EXPORT_SYMBOL vmlinux 0x06cbe839	pci_write_vpd
+EXPORT_SYMBOL vmlinux 0x06d728b1	tcp_parse_md5sig_option
+EXPORT_SYMBOL vmlinux 0x06efc83a	security_path_link
+EXPORT_SYMBOL vmlinux 0x06fe3b14	default_grn
+EXPORT_SYMBOL vmlinux 0x07046902	mdiobus_read
+EXPORT_SYMBOL vmlinux 0x070cd110	tty_port_lower_dtr_rts
+EXPORT_SYMBOL vmlinux 0x0727c4f3	iowrite8
+EXPORT_SYMBOL vmlinux 0x0799aca4	local_bh_enable
+EXPORT_SYMBOL vmlinux 0x0799c50a	param_set_ulong
+EXPORT_SYMBOL vmlinux 0x079ec038	slow_work_unregister_user
+EXPORT_SYMBOL vmlinux 0x07a890c8	fb_alloc_cmap
+EXPORT_SYMBOL vmlinux 0x07cc4a5d	printk_timed_ratelimit
+EXPORT_SYMBOL vmlinux 0x07d63312	set_pages_wb
+EXPORT_SYMBOL vmlinux 0x07e5ab77	sg_miter_start
+EXPORT_SYMBOL vmlinux 0x07ec8d07	dquot_drop
+EXPORT_SYMBOL vmlinux 0x07f0bbd7	per_cpu__current_task
+EXPORT_SYMBOL vmlinux 0x082c3213	pci_root_buses
+EXPORT_SYMBOL vmlinux 0x0851e1e5	dentry_unhash
+EXPORT_SYMBOL vmlinux 0x085fa49c	eth_header_cache
+EXPORT_SYMBOL vmlinux 0x08730e4d	start_tty
+EXPORT_SYMBOL vmlinux 0x089698bc	tcf_em_tree_dump
+EXPORT_SYMBOL vmlinux 0x08988f27	vm_insert_page
+EXPORT_SYMBOL vmlinux 0x089f7957	flock_lock_file_wait
+EXPORT_SYMBOL vmlinux 0x08d66a3a	warn_slowpath_fmt
+EXPORT_SYMBOL vmlinux 0x08e6d389	netif_notify_peers
+EXPORT_SYMBOL vmlinux 0x091c824a	machine_power_off
+EXPORT_SYMBOL vmlinux 0x0929113e	pci_match_id
+EXPORT_SYMBOL vmlinux 0x09431b6b	xrlim_allow
+EXPORT_SYMBOL vmlinux 0x0948cde9	num_physpages
+EXPORT_SYMBOL vmlinux 0x098b71c6	fb_dealloc_cmap
+EXPORT_SYMBOL vmlinux 0x09af4efe	blk_stop_queue
+EXPORT_SYMBOL vmlinux 0x09c55cec	schedule_timeout_interruptible
+EXPORT_SYMBOL vmlinux 0x09d44df9	in_lock_functions
+EXPORT_SYMBOL vmlinux 0x0a0ce38d	kernel_getsockopt
+EXPORT_SYMBOL vmlinux 0x0a0dc1cf	misc_deregister
+EXPORT_SYMBOL vmlinux 0x0a2487e0	unblock_all_signals
+EXPORT_SYMBOL vmlinux 0x0a377599	xfrm_register_mode
+EXPORT_SYMBOL vmlinux 0x0a500ea7	bio_map_kern
+EXPORT_SYMBOL vmlinux 0x0a67b009	proc_symlink
+EXPORT_SYMBOL vmlinux 0x0a795817	simple_rmdir
+EXPORT_SYMBOL vmlinux 0x0ab57553	dm_register_target
+EXPORT_SYMBOL vmlinux 0x0abc6ad4	thermal_cooling_device_unregister
+EXPORT_SYMBOL vmlinux 0x0acae3ad	inet_proto_csum_replace4
+EXPORT_SYMBOL vmlinux 0x0acb1a3c	__bitmap_shift_right
+EXPORT_SYMBOL vmlinux 0x0acf5feb	net_accel_unmap_grants_contig
+EXPORT_SYMBOL vmlinux 0x0ae1d6f2	nf_unregister_queue_handler
+EXPORT_SYMBOL vmlinux 0x0ae45ff4	bio_unmap_user
+EXPORT_SYMBOL vmlinux 0x0af644c1	vfs_unlink
+EXPORT_SYMBOL vmlinux 0x0b05e7da	blk_get_backing_dev_info
+EXPORT_SYMBOL vmlinux 0x0b1beb31	vmalloc_32_user
+EXPORT_SYMBOL vmlinux 0x0b1fcc0f	pci_set_mwi
+EXPORT_SYMBOL vmlinux 0x0b6531f1	unlock_page
+EXPORT_SYMBOL vmlinux 0x0b742fd7	simple_strtol
+EXPORT_SYMBOL vmlinux 0x0b744755	tcf_em_register
+EXPORT_SYMBOL vmlinux 0x0b79aaf5	input_unregister_handle
+EXPORT_SYMBOL vmlinux 0x0ba26316	llc_sap_find
+EXPORT_SYMBOL vmlinux 0x0bca876a	kill_pgrp
+EXPORT_SYMBOL vmlinux 0x0bced426	__lookup_one_len
+EXPORT_SYMBOL vmlinux 0x0c08c99b	vfs_create
+EXPORT_SYMBOL vmlinux 0x0c17e9b7	redirty_page_for_writepage
+EXPORT_SYMBOL vmlinux 0x0c19d496	security_inode_notifysecctx
+EXPORT_SYMBOL vmlinux 0x0c502002	rwsem_wake
+EXPORT_SYMBOL vmlinux 0x0c9fd8e5	ps2_command
+EXPORT_SYMBOL vmlinux 0x0cae232b	utf16s_to_utf8s
+EXPORT_SYMBOL vmlinux 0x0cb2c1d4	thermal_zone_device_unregister
+EXPORT_SYMBOL vmlinux 0x0cc62e87	input_free_device
+EXPORT_SYMBOL vmlinux 0x0d0bfb4d	skb_over_panic
+EXPORT_SYMBOL vmlinux 0x0d26a76d	_write_lock_irq
+EXPORT_SYMBOL vmlinux 0x0d542439	__ipv6_addr_type
+EXPORT_SYMBOL vmlinux 0x0d6990ed	generic_unplug_device
+EXPORT_SYMBOL vmlinux 0x0d867d12	__insert_inode_hash
+EXPORT_SYMBOL vmlinux 0x0da10ec3	security_sock_graft
+EXPORT_SYMBOL vmlinux 0x0df3933f	net_accel_unmap_iomem_page
+EXPORT_SYMBOL vmlinux 0x0e1f4d96	bmap
+EXPORT_SYMBOL vmlinux 0x0e320272	fib_default_rule_add
+EXPORT_SYMBOL vmlinux 0x0e3a133b	seq_open_private
+EXPORT_SYMBOL vmlinux 0x0e52592a	panic
+EXPORT_SYMBOL vmlinux 0x0e83fea1	del_timer_sync
+EXPORT_SYMBOL vmlinux 0x0ed46259	vfs_fsync_range
+EXPORT_SYMBOL vmlinux 0x0f1a2fe9	swiotlb_unmap_sg_attrs
+EXPORT_SYMBOL vmlinux 0x0f1ef871	posix_acl_alloc
+EXPORT_SYMBOL vmlinux 0x0f38b41d	mutex_lock_interruptible
+EXPORT_SYMBOL vmlinux 0x0f399457	remove_proc_entry
+EXPORT_SYMBOL vmlinux 0x0f6925ee	simple_write_end
+EXPORT_SYMBOL vmlinux 0x0f7f2b34	blk_register_region
+EXPORT_SYMBOL vmlinux 0x0f9e1fab	vfs_get_dqblk
+EXPORT_SYMBOL vmlinux 0x0fc5e8eb	radix_tree_gang_lookup_slot
+EXPORT_SYMBOL vmlinux 0x0fe50cfe	journal_force_commit_nested
+EXPORT_SYMBOL vmlinux 0x0ff2b602	slhc_compress
+EXPORT_SYMBOL vmlinux 0x0ff96015	inet_twsk_deschedule
+EXPORT_SYMBOL vmlinux 0x0fff670c	dm_get_mapinfo
+EXPORT_SYMBOL vmlinux 0x10316296	cdrom_media_changed
+EXPORT_SYMBOL vmlinux 0x1031d549	inet_stream_connect
+EXPORT_SYMBOL vmlinux 0x10434992	tcp_ioctl
+EXPORT_SYMBOL vmlinux 0x1046f507	lro_receive_skb
+EXPORT_SYMBOL vmlinux 0x105e2727	__tracepoint_kmalloc
+EXPORT_SYMBOL vmlinux 0x1072a394	csum_partial_copy_from_user
+EXPORT_SYMBOL vmlinux 0x1073f200	__elv_add_request
+EXPORT_SYMBOL vmlinux 0x108e8985	param_get_uint
+EXPORT_SYMBOL vmlinux 0x10ee20bb	default_blu
+EXPORT_SYMBOL vmlinux 0x1124a515	open_bdev_exclusive
+EXPORT_SYMBOL vmlinux 0x114b35f4	__mark_inode_dirty
+EXPORT_SYMBOL vmlinux 0x114ed1ce	schedule_work_on
+EXPORT_SYMBOL vmlinux 0x115ef988	qdisc_create_dflt
+EXPORT_SYMBOL vmlinux 0x1162acdf	tcp_v4_send_check
+EXPORT_SYMBOL vmlinux 0x1163f0a7	blk_max_low_pfn
+EXPORT_SYMBOL vmlinux 0x117093be	qdisc_class_hash_init
+EXPORT_SYMBOL vmlinux 0x1171a6fc	__blk_end_request_all
+EXPORT_SYMBOL vmlinux 0x118f01ea	putname
+EXPORT_SYMBOL vmlinux 0x119b3289	bdput
+EXPORT_SYMBOL vmlinux 0x11a18b14	__wake_up_bit
+EXPORT_SYMBOL vmlinux 0x11c12bc9	skb_copy_expand
+EXPORT_SYMBOL vmlinux 0x11e8d38e	fb_class
+EXPORT_SYMBOL vmlinux 0x1214007d	open_by_devnum
+EXPORT_SYMBOL vmlinux 0x12203141	__generic_file_aio_write
+EXPORT_SYMBOL vmlinux 0x12221b90	slow_work_enqueue
+EXPORT_SYMBOL vmlinux 0x1240e0a1	jbd2_journal_stop
+EXPORT_SYMBOL vmlinux 0x12512f89	ethtool_op_get_link
+EXPORT_SYMBOL vmlinux 0x125f23bc	security_path_truncate
+EXPORT_SYMBOL vmlinux 0x1280063c	__napi_schedule
+EXPORT_SYMBOL vmlinux 0x12cac380	jbd2_journal_wipe
+EXPORT_SYMBOL vmlinux 0x12f10736	udplite_table
+EXPORT_SYMBOL vmlinux 0x12ff5c2f	block_write_full_page
+EXPORT_SYMBOL vmlinux 0x134526af	force_sig
+EXPORT_SYMBOL vmlinux 0x134cac1d	blk_integrity_unregister
+EXPORT_SYMBOL vmlinux 0x1388aa6e	inet_frags_init
+EXPORT_SYMBOL vmlinux 0x138a78d1	set_current_groups
+EXPORT_SYMBOL vmlinux 0x140f4b6e	skb_copy_datagram_const_iovec
+EXPORT_SYMBOL vmlinux 0x1422a2b2	blk_rq_map_integrity_sg
+EXPORT_SYMBOL vmlinux 0x1425182c	prepare_kernel_cred
+EXPORT_SYMBOL vmlinux 0x1457e166	tcp_proc_unregister
+EXPORT_SYMBOL vmlinux 0x147561f4	tty_port_tty_set
+EXPORT_SYMBOL vmlinux 0x1490d539	input_set_capability
+EXPORT_SYMBOL vmlinux 0x14a20e2b	pci_set_consistent_dma_mask
+EXPORT_SYMBOL vmlinux 0x14af0cf7	gen_pool_destroy
+EXPORT_SYMBOL vmlinux 0x14b827e5	skb_insert
+EXPORT_SYMBOL vmlinux 0x14cba441	d_invalidate
+EXPORT_SYMBOL vmlinux 0x14dc4324	init_file
+EXPORT_SYMBOL vmlinux 0x15460572	remap_pfn_range
+EXPORT_SYMBOL vmlinux 0x1548d6b3	d_validate
+EXPORT_SYMBOL vmlinux 0x154e7b6b	__kernel_page_user
+EXPORT_SYMBOL vmlinux 0x1551dc51	bitmap_find_free_region
+EXPORT_SYMBOL vmlinux 0x1552355f	pci_find_bus
+EXPORT_SYMBOL vmlinux 0x15636304	journal_forget
+EXPORT_SYMBOL vmlinux 0x156c0aad	prepare_creds
+EXPORT_SYMBOL vmlinux 0x1587d521	dev_add_pack
+EXPORT_SYMBOL vmlinux 0x15b1c2f7	security_inode_getsecctx
+EXPORT_SYMBOL vmlinux 0x15ca725b	ip_fragment
+EXPORT_SYMBOL vmlinux 0x15e3d291	tty_driver_flush_buffer
+EXPORT_SYMBOL vmlinux 0x15ec3a8f	tcp_init_xmit_timers
+EXPORT_SYMBOL vmlinux 0x15ef2dd9	kfifo_free
+EXPORT_SYMBOL vmlinux 0x16126f92	sk_send_sigurg
+EXPORT_SYMBOL vmlinux 0x16257342	blk_queue_io_opt
+EXPORT_SYMBOL vmlinux 0x16297766	tty_mutex
+EXPORT_SYMBOL vmlinux 0x16305289	warn_slowpath_null
+EXPORT_SYMBOL vmlinux 0x163ee905	inet_listen
+EXPORT_SYMBOL vmlinux 0x16737c4b	pci_bus_assign_resources
+EXPORT_SYMBOL vmlinux 0x1675606f	bad_dma_address
+EXPORT_SYMBOL vmlinux 0x167e7f9d	__get_user_1
+EXPORT_SYMBOL vmlinux 0x16b4edcf	atomic_dec_and_mutex_lock
+EXPORT_SYMBOL vmlinux 0x16d733a8	unlock_rename
+EXPORT_SYMBOL vmlinux 0x16edd94b	genphy_config_advert
+EXPORT_SYMBOL vmlinux 0x16f0323c	page_symlink_inode_operations
+EXPORT_SYMBOL vmlinux 0x16f1cb27	bio_free
+EXPORT_SYMBOL vmlinux 0x170c7c02	udp_lib_setsockopt
+EXPORT_SYMBOL vmlinux 0x178f4f0f	fget
+EXPORT_SYMBOL vmlinux 0x179d85df	cdrom_get_media_event
+EXPORT_SYMBOL vmlinux 0x17a72541	page_readlink
+EXPORT_SYMBOL vmlinux 0x17b573f1	dquot_transfer
+EXPORT_SYMBOL vmlinux 0x17c85a66	radix_tree_tagged
+EXPORT_SYMBOL vmlinux 0x17d0bb9c	__page_symlink
+EXPORT_SYMBOL vmlinux 0x17d3040e	ethtool_op_set_tso
+EXPORT_SYMBOL vmlinux 0x17df17bc	sysctl_tcp_ecn
+EXPORT_SYMBOL vmlinux 0x17e35f1f	sk_stream_wait_close
+EXPORT_SYMBOL vmlinux 0x17f341a0	i8042_lock_chip
+EXPORT_SYMBOL vmlinux 0x180dc9b7	dquot_alloc_inode
+EXPORT_SYMBOL vmlinux 0x180ea8aa	devcgroup_inode_permission
+EXPORT_SYMBOL vmlinux 0x181b6ff2	mempool_resize
+EXPORT_SYMBOL vmlinux 0x181c00c0	vfs_fsync
+EXPORT_SYMBOL vmlinux 0x1829bd39	single_open
+EXPORT_SYMBOL vmlinux 0x183fa88b	mempool_alloc_slab
+EXPORT_SYMBOL vmlinux 0x18896369	bh_uptodate_or_lock
+EXPORT_SYMBOL vmlinux 0x189b6bac	memory_read_from_buffer
+EXPORT_SYMBOL vmlinux 0x18a29a4d	alloc_trdev
+EXPORT_SYMBOL vmlinux 0x18a43227	d_genocide
+EXPORT_SYMBOL vmlinux 0x18ba45c2	blk_queue_merge_bvec
+EXPORT_SYMBOL vmlinux 0x18c60fed	qdisc_calculate_pkt_len
+EXPORT_SYMBOL vmlinux 0x18e8401d	proc_dointvec_jiffies
+EXPORT_SYMBOL vmlinux 0x18f183cd	pci_remove_behind_bridge
+EXPORT_SYMBOL vmlinux 0x1919b0f3	put_disk
+EXPORT_SYMBOL vmlinux 0x191e6161	write_cache_pages
+EXPORT_SYMBOL vmlinux 0x19391763	iov_iter_fault_in_readable
+EXPORT_SYMBOL vmlinux 0x1956beb4	dev_mc_unsync
+EXPORT_SYMBOL vmlinux 0x195d546e	tty_flip_buffer_push
+EXPORT_SYMBOL vmlinux 0x196b0616	thermal_zone_device_register
+EXPORT_SYMBOL vmlinux 0x19747902	udp_proc_register
+EXPORT_SYMBOL vmlinux 0x1976bc16	__tracepoint_kmem_cache_free
+EXPORT_SYMBOL vmlinux 0x1985ed3c	prepare_to_wait_exclusive
+EXPORT_SYMBOL vmlinux 0x199ed0cd	net_disable_timestamp
+EXPORT_SYMBOL vmlinux 0x19a5f7f4	iput
+EXPORT_SYMBOL vmlinux 0x19b77e42	have_submounts
+EXPORT_SYMBOL vmlinux 0x19e37a99	pci_scan_single_device
+EXPORT_SYMBOL vmlinux 0x19f8b042	pci_vpd_truncate
+EXPORT_SYMBOL vmlinux 0x1a13abdf	bdget_disk
+EXPORT_SYMBOL vmlinux 0x1a158fd0	blk_peek_request
+EXPORT_SYMBOL vmlinux 0x1a197790	rtc_dev_update_irq_enable_emul
+EXPORT_SYMBOL vmlinux 0x1a1d3d20	dev_get_stats
+EXPORT_SYMBOL vmlinux 0x1a1e74cd	pci_request_region
+EXPORT_SYMBOL vmlinux 0x1a1fa95a	inode_get_bytes
+EXPORT_SYMBOL vmlinux 0x1a24e5e2	sonet_subtract_stats
+EXPORT_SYMBOL vmlinux 0x1a5e17cd	skb_split
+EXPORT_SYMBOL vmlinux 0x1a5ef3d2	phys_to_machine_mapping
+EXPORT_SYMBOL vmlinux 0x1a6e391a	clear_inode
+EXPORT_SYMBOL vmlinux 0x1a75caa3	_read_lock
+EXPORT_SYMBOL vmlinux 0x1a8a845e	idle_nomwait
+EXPORT_SYMBOL vmlinux 0x1ab12653	skb_copy_datagram_from_iovec
+EXPORT_SYMBOL vmlinux 0x1ace138d	bitmap_allocate_region
+EXPORT_SYMBOL vmlinux 0x1adb58cc	pci_request_regions
+EXPORT_SYMBOL vmlinux 0x1ae16736	pci_enable_wake
+EXPORT_SYMBOL vmlinux 0x1ae54b14	___pskb_trim
+EXPORT_SYMBOL vmlinux 0x1b015d25	bitmap_parselist
+EXPORT_SYMBOL vmlinux 0x1b1702a8	inet_csk_init_xmit_timers
+EXPORT_SYMBOL vmlinux 0x1b2fbfd6	pid_task
+EXPORT_SYMBOL vmlinux 0x1b3b3e6b	jbd2_journal_init_dev
+EXPORT_SYMBOL vmlinux 0x1b3c9e73	mpage_writepage
+EXPORT_SYMBOL vmlinux 0x1b6314fd	in_aton
+EXPORT_SYMBOL vmlinux 0x1b80bcc1	revert_creds
+EXPORT_SYMBOL vmlinux 0x1b81bf2c	generic_removexattr
+EXPORT_SYMBOL vmlinux 0x1b89419f	add_wait_queue_exclusive
+EXPORT_SYMBOL vmlinux 0x1b8b95ad	i8042_unlock_chip
+EXPORT_SYMBOL vmlinux 0x1b9981cc	set_irq_wake
+EXPORT_SYMBOL vmlinux 0x1bbf9ca8	tty_port_init
+EXPORT_SYMBOL vmlinux 0x1beb58d1	ip4_datagram_connect
+EXPORT_SYMBOL vmlinux 0x1bfe0f24	skb_gro_reset_offset
+EXPORT_SYMBOL vmlinux 0x1c1af916	set_normalized_timespec
+EXPORT_SYMBOL vmlinux 0x1cb41582	config_item_init
+EXPORT_SYMBOL vmlinux 0x1cc6719a	register_reboot_notifier
+EXPORT_SYMBOL vmlinux 0x1cefe352	wait_for_completion
+EXPORT_SYMBOL vmlinux 0x1cfc21c5	open_exec
+EXPORT_SYMBOL vmlinux 0x1d1b8e4a	tty_port_hangup
+EXPORT_SYMBOL vmlinux 0x1d1cc9d8	blk_queue_alignment_offset
+EXPORT_SYMBOL vmlinux 0x1d233307	dev_get_by_name
+EXPORT_SYMBOL vmlinux 0x1d2636a0	arp_tbl
+EXPORT_SYMBOL vmlinux 0x1d2e87c6	do_gettimeofday
+EXPORT_SYMBOL vmlinux 0x1d491943	tcp_make_synack
+EXPORT_SYMBOL vmlinux 0x1d6f4de1	serio_unregister_driver
+EXPORT_SYMBOL vmlinux 0x1d921938	default_file_splice_read
+EXPORT_SYMBOL vmlinux 0x1d9be706	ethtool_op_set_tx_ipv6_csum
+EXPORT_SYMBOL vmlinux 0x1db7706b	__copy_user_nocache
+EXPORT_SYMBOL vmlinux 0x1dba1716	register_nls
+EXPORT_SYMBOL vmlinux 0x1dc36131	fb_destroy_modedb
+EXPORT_SYMBOL vmlinux 0x1dd571e6	fb_copy_cmap
+EXPORT_SYMBOL vmlinux 0x1df0b4e3	llc_set_station_handler
+EXPORT_SYMBOL vmlinux 0x1df28d78	dev_addr_add_multiple
+EXPORT_SYMBOL vmlinux 0x1df297f4	blkdev_put
+EXPORT_SYMBOL vmlinux 0x1e0c2be4	ioremap_wc
+EXPORT_SYMBOL vmlinux 0x1e2e427f	cpumask_next_and
+EXPORT_SYMBOL vmlinux 0x1e3b91a5	xfrm_state_flush
+EXPORT_SYMBOL vmlinux 0x1e43707d	ip_getsockopt
+EXPORT_SYMBOL vmlinux 0x1e4bd7a7	netpoll_parse_options
+EXPORT_SYMBOL vmlinux 0x1e573c52	__bread
+EXPORT_SYMBOL vmlinux 0x1e628c86	pcim_iounmap_regions
+EXPORT_SYMBOL vmlinux 0x1e6ce7c3	thermal_zone_bind_cooling_device
+EXPORT_SYMBOL vmlinux 0x1e6d26a8	strstr
+EXPORT_SYMBOL vmlinux 0x1e7deab6	ip_nat_decode_session
+EXPORT_SYMBOL vmlinux 0x1e8686d5	set_pages_uc
+EXPORT_SYMBOL vmlinux 0x1e8739ce	bdevname
+EXPORT_SYMBOL vmlinux 0x1e975c0b	sock_wmalloc
+EXPORT_SYMBOL vmlinux 0x1e9ec117	dev_mc_sync
+EXPORT_SYMBOL vmlinux 0x1ea20b0e	fddi_change_mtu
+EXPORT_SYMBOL vmlinux 0x1eb53961	phy_stop_interrupts
+EXPORT_SYMBOL vmlinux 0x1eb79996	mark_info_dirty
+EXPORT_SYMBOL vmlinux 0x1efe283f	__cap_full_set
+EXPORT_SYMBOL vmlinux 0x1f4fa3ed	security_path_mkdir
+EXPORT_SYMBOL vmlinux 0x1fcf2722	tr_type_trans
+EXPORT_SYMBOL vmlinux 0x1fd1887c	__scm_send
+EXPORT_SYMBOL vmlinux 0x1fdf200c	pci_disable_msix
+EXPORT_SYMBOL vmlinux 0x1fedf0f4	__request_region
+EXPORT_SYMBOL vmlinux 0x20000329	simple_strtoul
+EXPORT_SYMBOL vmlinux 0x2012d4c0	init_buffer
+EXPORT_SYMBOL vmlinux 0x2034b712	serio_close
+EXPORT_SYMBOL vmlinux 0x20385c58	genl_register_mc_group
+EXPORT_SYMBOL vmlinux 0x204857ac	proc_dostring
+EXPORT_SYMBOL vmlinux 0x204f9829	bio_copy_kern
+EXPORT_SYMBOL vmlinux 0x20633db2	find_get_pages_tag
+EXPORT_SYMBOL vmlinux 0x2072976c	elv_dispatch_add_tail
+EXPORT_SYMBOL vmlinux 0x207aca92	kernel_sendpage
+EXPORT_SYMBOL vmlinux 0x2082aaef	xfrm_find_acq_byseq
+EXPORT_SYMBOL vmlinux 0x208caf35	pci_disable_device
+EXPORT_SYMBOL vmlinux 0x209da61a	xfrm4_prepare_output
+EXPORT_SYMBOL vmlinux 0x20a3f82b	blk_queue_max_hw_sectors
+EXPORT_SYMBOL vmlinux 0x20b26ab0	km_report
+EXPORT_SYMBOL vmlinux 0x20b3a55b	skb_kill_datagram
+EXPORT_SYMBOL vmlinux 0x20cc5de2	__nla_reserve
+EXPORT_SYMBOL vmlinux 0x20cc9b6c	__serio_register_driver
+EXPORT_SYMBOL vmlinux 0x20eadeb6	ip_compute_csum
+EXPORT_SYMBOL vmlinux 0x20f06d2c	fb_pan_display
+EXPORT_SYMBOL vmlinux 0x20f413ad	skb_free_datagram_locked
+EXPORT_SYMBOL vmlinux 0x20f9322a	idr_pre_get
+EXPORT_SYMBOL vmlinux 0x212784c6	sock_kfree_s
+EXPORT_SYMBOL vmlinux 0x215023a3	pcim_iounmap
+EXPORT_SYMBOL vmlinux 0x215ebd78	bitrev16
+EXPORT_SYMBOL vmlinux 0x21bf7341	dev_trans_start
+EXPORT_SYMBOL vmlinux 0x21c09541	genphy_read_status
+EXPORT_SYMBOL vmlinux 0x21d50a51	tcf_hash_release
+EXPORT_SYMBOL vmlinux 0x21e5679c	copy_user_generic
+EXPORT_SYMBOL vmlinux 0x21edafae	dquot_release
+EXPORT_SYMBOL vmlinux 0x222149b9	ethtool_op_get_tso
+EXPORT_SYMBOL vmlinux 0x2222c14d	pci_enable_device
+EXPORT_SYMBOL vmlinux 0x222e7ce2	sysfs_streq
+EXPORT_SYMBOL vmlinux 0x223029ed	__set_page_dirty_buffers
+EXPORT_SYMBOL vmlinux 0x223a92fd	tcp_v4_md5_do_del
+EXPORT_SYMBOL vmlinux 0x224cb457	vga_put
+EXPORT_SYMBOL vmlinux 0x224dd498	devm_ioport_unmap
+EXPORT_SYMBOL vmlinux 0x226e86a9	audit_log
+EXPORT_SYMBOL vmlinux 0x2288378f	system_state
+EXPORT_SYMBOL vmlinux 0x22a73912	__tcp_put_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x22aa2561	pci_request_regions_exclusive
+EXPORT_SYMBOL vmlinux 0x22b325d5	kd_mksound
+EXPORT_SYMBOL vmlinux 0x22b6533b	xfrm_sad_getinfo
+EXPORT_SYMBOL vmlinux 0x22bccc0c	atm_alloc_charge
+EXPORT_SYMBOL vmlinux 0x22d30b85	mdio_bus_type
+EXPORT_SYMBOL vmlinux 0x22edfc1c	__alloc_skb
+EXPORT_SYMBOL vmlinux 0x22fc72b8	unregister_netdev
+EXPORT_SYMBOL vmlinux 0x2325f3e6	sock_get_timestamp
+EXPORT_SYMBOL vmlinux 0x23269a13	strict_strtoul
+EXPORT_SYMBOL vmlinux 0x232c197b	vfs_symlink
+EXPORT_SYMBOL vmlinux 0x234509f3	strncat
+EXPORT_SYMBOL vmlinux 0x236c8c64	memcpy
+EXPORT_SYMBOL vmlinux 0x23a2007b	netlink_unicast
+EXPORT_SYMBOL vmlinux 0x23c8f257	slhc_uncompress
+EXPORT_SYMBOL vmlinux 0x23cb33ad	splice_from_pipe_feed
+EXPORT_SYMBOL vmlinux 0x23fd3028	vmalloc_node
+EXPORT_SYMBOL vmlinux 0x2406d237	genphy_suspend
+EXPORT_SYMBOL vmlinux 0x24428be5	strncpy_from_user
+EXPORT_SYMBOL vmlinux 0x24486022	shrink_dcache_parent
+EXPORT_SYMBOL vmlinux 0x245745e8	keyring_clear
+EXPORT_SYMBOL vmlinux 0x2459bbcc	console_set_on_cmdline
+EXPORT_SYMBOL vmlinux 0x245b1c0c	skb_copy_datagram_iovec
+EXPORT_SYMBOL vmlinux 0x24624544	ftrace_print_flags_seq
+EXPORT_SYMBOL vmlinux 0x24686293	proc_doulongvec_minmax
+EXPORT_SYMBOL vmlinux 0x2479f690	jbd2_journal_restart
+EXPORT_SYMBOL vmlinux 0x24ba0c47	ppp_unit_number
+EXPORT_SYMBOL vmlinux 0x24cea1e2	bioset_create
+EXPORT_SYMBOL vmlinux 0x24d293e2	jbd2_journal_unlock_updates
+EXPORT_SYMBOL vmlinux 0x24e4bb01	down_write_trylock
+EXPORT_SYMBOL vmlinux 0x24ea4c92	bh_submit_read
+EXPORT_SYMBOL vmlinux 0x24f0615f	dcache_readdir
+EXPORT_SYMBOL vmlinux 0x24fdac79	wake_bit_function
+EXPORT_SYMBOL vmlinux 0x25098c4f	mb_cache_entry_alloc
+EXPORT_SYMBOL vmlinux 0x251370b4	tcf_em_unregister
+EXPORT_SYMBOL vmlinux 0x25665c96	xen_safe_halt
+EXPORT_SYMBOL vmlinux 0x257d90d4	redraw_screen
+EXPORT_SYMBOL vmlinux 0x25820c64	fs_overflowuid
+EXPORT_SYMBOL vmlinux 0x258355b4	fb_find_best_mode
+EXPORT_SYMBOL vmlinux 0x258fcb27	jbd2_journal_init_jbd_inode
+EXPORT_SYMBOL vmlinux 0x25a91894	elv_rb_del
+EXPORT_SYMBOL vmlinux 0x25aa6647	touch_atime
+EXPORT_SYMBOL vmlinux 0x25baac74	inet_csk_clear_xmit_timers
+EXPORT_SYMBOL vmlinux 0x25bc7a2a	end_buffer_read_sync
+EXPORT_SYMBOL vmlinux 0x25ec1b28	strlen
+EXPORT_SYMBOL vmlinux 0x2606700f	gnet_stats_copy_rate_est
+EXPORT_SYMBOL vmlinux 0x2609a0d4	netlink_set_err
+EXPORT_SYMBOL vmlinux 0x264b92d0	neigh_sysctl_unregister
+EXPORT_SYMBOL vmlinux 0x266ff024	jbd2_journal_ack_err
+EXPORT_SYMBOL vmlinux 0x267da477	fb_validate_mode
+EXPORT_SYMBOL vmlinux 0x267fc65b	__tasklet_hi_schedule
+EXPORT_SYMBOL vmlinux 0x2685c3d7	__sg_alloc_table
+EXPORT_SYMBOL vmlinux 0x2698386d	sock_common_setsockopt
+EXPORT_SYMBOL vmlinux 0x26cb8d7a	d_find_alias
+EXPORT_SYMBOL vmlinux 0x26d6ce16	__devm_release_region
+EXPORT_SYMBOL vmlinux 0x26e76fb8	sysctl_udp_wmem_min
+EXPORT_SYMBOL vmlinux 0x26f83e9d	dm_table_put
+EXPORT_SYMBOL vmlinux 0x26f90ae6	datagram_poll
+EXPORT_SYMBOL vmlinux 0x27163673	nf_register_hooks
+EXPORT_SYMBOL vmlinux 0x2724483c	compat_mc_setsockopt
+EXPORT_SYMBOL vmlinux 0x2727da5d	_atomic_dec_and_lock
+EXPORT_SYMBOL vmlinux 0x275222de	atm_dev_deregister
+EXPORT_SYMBOL vmlinux 0x27802d98	tcp_rcv_established
+EXPORT_SYMBOL vmlinux 0x27864d57	memparse
+EXPORT_SYMBOL vmlinux 0x27b35c51	tcp_sockets_allocated
+EXPORT_SYMBOL vmlinux 0x27bbf221	disable_irq_nosync
+EXPORT_SYMBOL vmlinux 0x27c33efe	csum_ipv6_magic
+EXPORT_SYMBOL vmlinux 0x27c61ece	qdisc_put_stab
+EXPORT_SYMBOL vmlinux 0x27c9e759	tcp_splice_read
+EXPORT_SYMBOL vmlinux 0x27cd8a2e	blk_rq_map_user
+EXPORT_SYMBOL vmlinux 0x27ef0e31	kernel_sock_shutdown
+EXPORT_SYMBOL vmlinux 0x285ac517	strict_strtoll
+EXPORT_SYMBOL vmlinux 0x2876a6d3	memcpy_toiovec
+EXPORT_SYMBOL vmlinux 0x288f7795	file_update_time
+EXPORT_SYMBOL vmlinux 0x28cff05a	cfb_copyarea
+EXPORT_SYMBOL vmlinux 0x28da1efe	tty_wait_until_sent
+EXPORT_SYMBOL vmlinux 0x28e2dde1	ip_route_output_key
+EXPORT_SYMBOL vmlinux 0x28f1664a	key_negate_and_link
+EXPORT_SYMBOL vmlinux 0x28f3ca9b	tcp_proc_register
+EXPORT_SYMBOL vmlinux 0x292093f4	native_rdmsr_safe_regs
+EXPORT_SYMBOL vmlinux 0x292d1ac5	lock_fb_info
+EXPORT_SYMBOL vmlinux 0x293837c8	inet_frag_find
+EXPORT_SYMBOL vmlinux 0x293ae296	__vlan_hwaccel_rx
+EXPORT_SYMBOL vmlinux 0x294dd3c6	nobh_truncate_page
+EXPORT_SYMBOL vmlinux 0x29536aae	clear_page_dirty_for_io
+EXPORT_SYMBOL vmlinux 0x29537c9e	alloc_chrdev_region
+EXPORT_SYMBOL vmlinux 0x29726cf8	blk_rq_unmap_user
+EXPORT_SYMBOL vmlinux 0x29bd4c46	__cap_init_eff_set
+EXPORT_SYMBOL vmlinux 0x2a2308d7	swiotlb_dma_mapping_error
+EXPORT_SYMBOL vmlinux 0x2a268ddb	register_netdev
+EXPORT_SYMBOL vmlinux 0x2a303d4d	check_signature
+EXPORT_SYMBOL vmlinux 0x2a3887ec	pci_reenable_device
+EXPORT_SYMBOL vmlinux 0x2a48455f	jbd2_journal_load
+EXPORT_SYMBOL vmlinux 0x2a4996f9	sock_i_uid
+EXPORT_SYMBOL vmlinux 0x2a568a00	con_set_default_unimap
+EXPORT_SYMBOL vmlinux 0x2a673293	sock_alloc_send_pskb
+EXPORT_SYMBOL vmlinux 0x2a6b97ed	pci_bus_find_capability
+EXPORT_SYMBOL vmlinux 0x2a87bce7	unregister_cdrom
+EXPORT_SYMBOL vmlinux 0x2aeb2800	mempool_create_node
+EXPORT_SYMBOL vmlinux 0x2aecb0de	kblockd_schedule_work
+EXPORT_SYMBOL vmlinux 0x2b0c84fa	bdev_read_only
+EXPORT_SYMBOL vmlinux 0x2b1c7640	nf_register_queue_handler
+EXPORT_SYMBOL vmlinux 0x2b7b13f1	generic_make_request
+EXPORT_SYMBOL vmlinux 0x2b7e2c88	udp_lib_get_port
+EXPORT_SYMBOL vmlinux 0x2ba707a8	sysctl_tcp_low_latency
+EXPORT_SYMBOL vmlinux 0x2bae23d9	generic_show_options
+EXPORT_SYMBOL vmlinux 0x2bb6448d	xfrm4_rcv
+EXPORT_SYMBOL vmlinux 0x2bb6fde2	__kfifo_put
+EXPORT_SYMBOL vmlinux 0x2c0092b6	slow_work_sleep_till_thread_needed
+EXPORT_SYMBOL vmlinux 0x2c7cb998	__neigh_for_each_release
+EXPORT_SYMBOL vmlinux 0x2ca124aa	dev_load
+EXPORT_SYMBOL vmlinux 0x2cb03920	sb_set_blocksize
+EXPORT_SYMBOL vmlinux 0x2cc2d52d	vcc_hash
+EXPORT_SYMBOL vmlinux 0x2d111c0e	sock_tx_timestamp
+EXPORT_SYMBOL vmlinux 0x2d1fc7b0	pci_request_selected_regions
+EXPORT_SYMBOL vmlinux 0x2d38583a	nla_reserve
+EXPORT_SYMBOL vmlinux 0x2d5528c9	sg_copy_to_buffer
+EXPORT_SYMBOL vmlinux 0x2d603e10	task_tgid_nr_ns
+EXPORT_SYMBOL vmlinux 0x2d6a1287	save_mount_options
+EXPORT_SYMBOL vmlinux 0x2d6a65a6	inode_change_ok
+EXPORT_SYMBOL vmlinux 0x2d8c4bc2	blk_queue_softirq_done
+EXPORT_SYMBOL vmlinux 0x2da69603	dentry_open
+EXPORT_SYMBOL vmlinux 0x2dba001e	mpage_readpage
+EXPORT_SYMBOL vmlinux 0x2dbafbe3	pcibios_align_resource
+EXPORT_SYMBOL vmlinux 0x2dc9b08d	__tcf_em_tree_match
+EXPORT_SYMBOL vmlinux 0x2dcabcda	zap_page_range
+EXPORT_SYMBOL vmlinux 0x2dd16564	arch_register_cpu
+EXPORT_SYMBOL vmlinux 0x2def7f76	rtc_cmos_write
+EXPORT_SYMBOL vmlinux 0x2e06111d	cpu_present_mask
+EXPORT_SYMBOL vmlinux 0x2e276deb	security_sb_clone_mnt_opts
+EXPORT_SYMBOL vmlinux 0x2e2ce9e0	sysctl_tcp_syncookies
+EXPORT_SYMBOL vmlinux 0x2e4a39f8	sysctl_udp_mem
+EXPORT_SYMBOL vmlinux 0x2e557cf2	dst_alloc
+EXPORT_SYMBOL vmlinux 0x2e8173fd	block_invalidatepage
+EXPORT_SYMBOL vmlinux 0x2e97a729	idr_remove
+EXPORT_SYMBOL vmlinux 0x2eb9a0e8	_read_lock_irq
+EXPORT_SYMBOL vmlinux 0x2ee6aa32	posix_lock_file
+EXPORT_SYMBOL vmlinux 0x2ef2c620	skb_copy_and_csum_datagram_iovec
+EXPORT_SYMBOL vmlinux 0x2f28dfd8	journal_extend
+EXPORT_SYMBOL vmlinux 0x2f6c98ff	input_unregister_handler
+EXPORT_SYMBOL vmlinux 0x2fa5a500	memcmp
+EXPORT_SYMBOL vmlinux 0x2fa5fda4	bdi_unregister
+EXPORT_SYMBOL vmlinux 0x2fb5e433	icmp_send
+EXPORT_SYMBOL vmlinux 0x2fd82f4d	get_fs_type
+EXPORT_SYMBOL vmlinux 0x2fde2082	tcp_alloc_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x2ff611e6	do_splice_to
+EXPORT_SYMBOL vmlinux 0x2ff6f513	pci_fixup_cardbus
+EXPORT_SYMBOL vmlinux 0x303f406c	request_firmware
+EXPORT_SYMBOL vmlinux 0x304b0bba	xfrm_policy_alloc
+EXPORT_SYMBOL vmlinux 0x307b0379	pci_release_regions
+EXPORT_SYMBOL vmlinux 0x307f7776	timecompare_offset
+EXPORT_SYMBOL vmlinux 0x30a63a63	pci_back_from_sleep
+EXPORT_SYMBOL vmlinux 0x30b4c272	key_payload_reserve
+EXPORT_SYMBOL vmlinux 0x30c57369	slow_work_cancel
+EXPORT_SYMBOL vmlinux 0x30d4e42c	nla_append
+EXPORT_SYMBOL vmlinux 0x30e74134	tty_termios_copy_hw
+EXPORT_SYMBOL vmlinux 0x30e90721	dma_pool_free
+EXPORT_SYMBOL vmlinux 0x30ffe1f7	cancel_delayed_work_sync
+EXPORT_SYMBOL vmlinux 0x310f80c6	uart_suspend_port
+EXPORT_SYMBOL vmlinux 0x31121fe1	genl_unregister_mc_group
+EXPORT_SYMBOL vmlinux 0x312c5036	truncate_inode_pages_range
+EXPORT_SYMBOL vmlinux 0x31332bc6	blk_rq_map_user_iov
+EXPORT_SYMBOL vmlinux 0x3139329e	touch_pte_range
+EXPORT_SYMBOL vmlinux 0x313e34f2	generic_file_llseek
+EXPORT_SYMBOL vmlinux 0x3140e309	skb_trim
+EXPORT_SYMBOL vmlinux 0x3145216f	pci_dev_present
+EXPORT_SYMBOL vmlinux 0x3145db96	nf_ip_checksum
+EXPORT_SYMBOL vmlinux 0x3147857d	default_red
+EXPORT_SYMBOL vmlinux 0x318c8996	neigh_changeaddr
+EXPORT_SYMBOL vmlinux 0x319d6f51	register_con_driver
+EXPORT_SYMBOL vmlinux 0x31b31f5c	csum_partial_copy_nocheck
+EXPORT_SYMBOL vmlinux 0x31ebadcd	in_group_p
+EXPORT_SYMBOL vmlinux 0x31f2eeda	elv_abort_queue
+EXPORT_SYMBOL vmlinux 0x321431d9	register_quota_format
+EXPORT_SYMBOL vmlinux 0x322b4ee7	tcp4_gro_complete
+EXPORT_SYMBOL vmlinux 0x322d7ec9	cfb_fillrect
+EXPORT_SYMBOL vmlinux 0x324ee140	find_inode_number
+EXPORT_SYMBOL vmlinux 0x3259f918	register_framebuffer
+EXPORT_SYMBOL vmlinux 0x327dd1f6	qdisc_watchdog_init
+EXPORT_SYMBOL vmlinux 0x3285cc48	param_set_uint
+EXPORT_SYMBOL vmlinux 0x32d5b545	direct_kernel_remap_pfn_range
+EXPORT_SYMBOL vmlinux 0x32f7570d	compat_sock_get_timestamp
+EXPORT_SYMBOL vmlinux 0x32fa0ae5	kill_litter_super
+EXPORT_SYMBOL vmlinux 0x3302a0d1	neigh_parms_release
+EXPORT_SYMBOL vmlinux 0x33049d23	blk_queue_end_tag
+EXPORT_SYMBOL vmlinux 0x33524e97	dm_put_device
+EXPORT_SYMBOL vmlinux 0x336ab72a	pci_get_class
+EXPORT_SYMBOL vmlinux 0x336fa867	journal_start
+EXPORT_SYMBOL vmlinux 0x33aaa3b3	blk_queue_io_min
+EXPORT_SYMBOL vmlinux 0x33b84f74	copy_page
+EXPORT_SYMBOL vmlinux 0x33c0022b	filemap_fault
+EXPORT_SYMBOL vmlinux 0x33d5fdb7	jbd2_journal_clear_err
+EXPORT_SYMBOL vmlinux 0x33d92f9a	prepare_to_wait
+EXPORT_SYMBOL vmlinux 0x34207c5c	config_item_set_name
+EXPORT_SYMBOL vmlinux 0x342fcb33	pci_pme_capable
+EXPORT_SYMBOL vmlinux 0x344062c5	generic_listxattr
+EXPORT_SYMBOL vmlinux 0x3457cb68	param_set_long
+EXPORT_SYMBOL vmlinux 0x34583eef	tcp_enter_memory_pressure
+EXPORT_SYMBOL vmlinux 0x3458b856	blk_queue_logical_block_size
+EXPORT_SYMBOL vmlinux 0x346585c4	jbd2_journal_start
+EXPORT_SYMBOL vmlinux 0x346eeace	atm_dev_register
+EXPORT_SYMBOL vmlinux 0x348d0dff	tcp_simple_retransmit
+EXPORT_SYMBOL vmlinux 0x34949a6f	aio_put_req
+EXPORT_SYMBOL vmlinux 0x349cba85	strchr
+EXPORT_SYMBOL vmlinux 0x349f8e33	genphy_config_aneg
+EXPORT_SYMBOL vmlinux 0x34b262ec	seq_puts
+EXPORT_SYMBOL vmlinux 0x34d319f2	tty_port_close_end
+EXPORT_SYMBOL vmlinux 0x34dab9b9	invalidate_inodes
+EXPORT_SYMBOL vmlinux 0x352f6d04	dev_set_drvdata
+EXPORT_SYMBOL vmlinux 0x355c2491	inode_needs_sync
+EXPORT_SYMBOL vmlinux 0x3561977b	vfs_dq_transfer
+EXPORT_SYMBOL vmlinux 0x3582ed17	vfs_stat
+EXPORT_SYMBOL vmlinux 0x35b0650f	vsnprintf
+EXPORT_SYMBOL vmlinux 0x35b0849f	filemap_fdatawait_range
+EXPORT_SYMBOL vmlinux 0x35c2ba9e	refrigerator
+EXPORT_SYMBOL vmlinux 0x360b1afe	probe_irq_mask
+EXPORT_SYMBOL vmlinux 0x36139a51	memcpy_fromiovec
+EXPORT_SYMBOL vmlinux 0x361d847a	generic_block_bmap
+EXPORT_SYMBOL vmlinux 0x3627beb1	find_get_page
+EXPORT_SYMBOL vmlinux 0x362a8f2d	skb_realloc_headroom
+EXPORT_SYMBOL vmlinux 0x36373e0e	load_nls
+EXPORT_SYMBOL vmlinux 0x363c6ac2	serio_unregister_port
+EXPORT_SYMBOL vmlinux 0x36438899	swiotlb_map_sg
+EXPORT_SYMBOL vmlinux 0x36482da3	nobh_writepage
+EXPORT_SYMBOL vmlinux 0x3649e197	bio_integrity_prep
+EXPORT_SYMBOL vmlinux 0x3652d3bd	unregister_8022_client
+EXPORT_SYMBOL vmlinux 0x3656bf5a	lock_kernel
+EXPORT_SYMBOL vmlinux 0x366083ad	configfs_undepend_item
+EXPORT_SYMBOL vmlinux 0x3664192c	pagevec_lookup_tag
+EXPORT_SYMBOL vmlinux 0x368041e2	lock_sock_nested
+EXPORT_SYMBOL vmlinux 0x36875389	__timecompare_update
+EXPORT_SYMBOL vmlinux 0x36b59d61	neigh_compat_output
+EXPORT_SYMBOL vmlinux 0x36d9a6a7	phy_disconnect
+EXPORT_SYMBOL vmlinux 0x3701a196	csum_partial_copy_to_user
+EXPORT_SYMBOL vmlinux 0x3708c54a	tcf_register_action
+EXPORT_SYMBOL vmlinux 0x3744cf36	vmalloc_to_pfn
+EXPORT_SYMBOL vmlinux 0x374ead9d	__rta_fill
+EXPORT_SYMBOL vmlinux 0x375465a7	radix_tree_gang_lookup_tag_slot
+EXPORT_SYMBOL vmlinux 0x37556bdf	page_symlink
+EXPORT_SYMBOL vmlinux 0x375aa993	tty_throttle
+EXPORT_SYMBOL vmlinux 0x3780ef12	init_special_inode
+EXPORT_SYMBOL vmlinux 0x378274ac	uart_remove_one_port
+EXPORT_SYMBOL vmlinux 0x37befc70	jiffies_to_msecs
+EXPORT_SYMBOL vmlinux 0x37d3e849	security_inode_init_security
+EXPORT_SYMBOL vmlinux 0x37d5b439	journal_update_format
+EXPORT_SYMBOL vmlinux 0x3839d47c	simple_fsync
+EXPORT_SYMBOL vmlinux 0x383e44b2	input_grab_device
+EXPORT_SYMBOL vmlinux 0x384e639d	commit_creds
+EXPORT_SYMBOL vmlinux 0x387ad439	tcp_sendmsg
+EXPORT_SYMBOL vmlinux 0x387c90d9	make_bad_inode
+EXPORT_SYMBOL vmlinux 0x388f9128	xfrm_state_walk_done
+EXPORT_SYMBOL vmlinux 0x38b92846	llc_remove_pack
+EXPORT_SYMBOL vmlinux 0x38cab31c	init_timer_deferrable_key
+EXPORT_SYMBOL vmlinux 0x38f33bed	dump_fpu
+EXPORT_SYMBOL vmlinux 0x39018e6f	security_path_unlink
+EXPORT_SYMBOL vmlinux 0x3910b3c7	tty_hung_up_p
+EXPORT_SYMBOL vmlinux 0x3911e779	__inet6_lookup_established
+EXPORT_SYMBOL vmlinux 0x39201555	blk_end_request_cur
+EXPORT_SYMBOL vmlinux 0x392a6144	dev_disable_lro
+EXPORT_SYMBOL vmlinux 0x392ecb1e	configfs_register_subsystem
+EXPORT_SYMBOL vmlinux 0x3963b5e6	journal_restart
+EXPORT_SYMBOL vmlinux 0x3980aac1	unregister_reboot_notifier
+EXPORT_SYMBOL vmlinux 0x39efaa55	__lock_buffer
+EXPORT_SYMBOL vmlinux 0x39fefcc2	splice_from_pipe_end
+EXPORT_SYMBOL vmlinux 0x3a0c7816	unregister_netdevice
+EXPORT_SYMBOL vmlinux 0x3a2204c6	security_netlink_recv
+EXPORT_SYMBOL vmlinux 0x3a2df328	blk_init_tags
+EXPORT_SYMBOL vmlinux 0x3a91c35e	dev_mc_delete
+EXPORT_SYMBOL vmlinux 0x3a9b6fb9	blk_unregister_region
+EXPORT_SYMBOL vmlinux 0x3aa1dbcf	_spin_unlock_bh
+EXPORT_SYMBOL vmlinux 0x3ac3fa89	pci_set_master
+EXPORT_SYMBOL vmlinux 0x3ae831b6	kref_init
+EXPORT_SYMBOL vmlinux 0x3b2cbc9e	ip_route_input
+EXPORT_SYMBOL vmlinux 0x3b66cb82	scsi_cmd_ioctl
+EXPORT_SYMBOL vmlinux 0x3b861245	read_cache_page_gfp
+EXPORT_SYMBOL vmlinux 0x3bd1b1f6	msecs_to_jiffies
+EXPORT_SYMBOL vmlinux 0x3c2c5af5	sprintf
+EXPORT_SYMBOL vmlinux 0x3c62784a	dquot_mark_dquot_dirty
+EXPORT_SYMBOL vmlinux 0x3c7227bf	complete_all
+EXPORT_SYMBOL vmlinux 0x3c9cc0f1	sk_dst_check
+EXPORT_SYMBOL vmlinux 0x3c9d1211	string_get_size
+EXPORT_SYMBOL vmlinux 0x3cba97cb	inet_sk_rebuild_header
+EXPORT_SYMBOL vmlinux 0x3cbda21a	truncate_inode_pages
+EXPORT_SYMBOL vmlinux 0x3cc0a3bb	xfrm_spd_getinfo
+EXPORT_SYMBOL vmlinux 0x3ce4ca6f	disable_irq
+EXPORT_SYMBOL vmlinux 0x3d003bec	inode_init_once
+EXPORT_SYMBOL vmlinux 0x3d60f48f	dquot_acquire
+EXPORT_SYMBOL vmlinux 0x3d68bd4b	flow_cache_genid
+EXPORT_SYMBOL vmlinux 0x3d6a247a	tcf_exts_destroy
+EXPORT_SYMBOL vmlinux 0x3d7c1ed7	msrs_alloc
+EXPORT_SYMBOL vmlinux 0x3d8728bb	memcpy_toiovecend
+EXPORT_SYMBOL vmlinux 0x3d95e116	__dev_get_by_index
+EXPORT_SYMBOL vmlinux 0x3d9ee9f0	clear_page
+EXPORT_SYMBOL vmlinux 0x3da171f9	pci_mem_start
+EXPORT_SYMBOL vmlinux 0x3da5eb6d	kfifo_alloc
+EXPORT_SYMBOL vmlinux 0x3db2e258	radix_tree_gang_lookup
+EXPORT_SYMBOL vmlinux 0x3dc07394	ip_defrag
+EXPORT_SYMBOL vmlinux 0x3e1f073d	wait_for_completion_timeout
+EXPORT_SYMBOL vmlinux 0x3e219de6	try_wait_for_completion
+EXPORT_SYMBOL vmlinux 0x3e25eb46	read_cache_page_async
+EXPORT_SYMBOL vmlinux 0x3e383385	nf_hooks
+EXPORT_SYMBOL vmlinux 0x3e3876bb	simple_release_fs
+EXPORT_SYMBOL vmlinux 0x3e38b596	unregister_nls
+EXPORT_SYMBOL vmlinux 0x3e45e9ff	register_inetaddr_notifier
+EXPORT_SYMBOL vmlinux 0x3e4e95bb	dev_unicast_unsync
+EXPORT_SYMBOL vmlinux 0x3e899c9d	blk_limits_io_min
+EXPORT_SYMBOL vmlinux 0x3e8fec5e	nf_unregister_hooks
+EXPORT_SYMBOL vmlinux 0x3eb6542c	tcp_gro_complete
+EXPORT_SYMBOL vmlinux 0x3ec1d14e	tcf_hash_destroy
+EXPORT_SYMBOL vmlinux 0x3ed63055	zlib_inflateReset
+EXPORT_SYMBOL vmlinux 0x3ed79a07	generic_write_end
+EXPORT_SYMBOL vmlinux 0x3ee649bc	machine_to_phys_order
+EXPORT_SYMBOL vmlinux 0x3ee8a814	balance_dirty_pages_ratelimited_nr
+EXPORT_SYMBOL vmlinux 0x3f0546a8	ioread32_rep
+EXPORT_SYMBOL vmlinux 0x3f06d499	dma_pool_alloc
+EXPORT_SYMBOL vmlinux 0x3f1899f1	up
+EXPORT_SYMBOL vmlinux 0x3f3a9e4f	pci_set_dma_seg_boundary
+EXPORT_SYMBOL vmlinux 0x3f4547a7	put_unused_fd
+EXPORT_SYMBOL vmlinux 0x3f45e25d	journal_get_write_access
+EXPORT_SYMBOL vmlinux 0x3f6ffb4e	blk_fetch_request
+EXPORT_SYMBOL vmlinux 0x3f75ca48	dquot_initialize
+EXPORT_SYMBOL vmlinux 0x3fa913da	strspn
+EXPORT_SYMBOL vmlinux 0x3fab53dd	dm_table_get_mode
+EXPORT_SYMBOL vmlinux 0x3fe4674b	pci_iomap
+EXPORT_SYMBOL vmlinux 0x3fec048f	sg_next
+EXPORT_SYMBOL vmlinux 0x3ff62317	local_bh_disable
+EXPORT_SYMBOL vmlinux 0x405c1144	get_seconds
+EXPORT_SYMBOL vmlinux 0x406f72c8	cap_netlink_recv
+EXPORT_SYMBOL vmlinux 0x406f8187	uart_get_divisor
+EXPORT_SYMBOL vmlinux 0x4086e977	udp_lib_unhash
+EXPORT_SYMBOL vmlinux 0x409873e3	tty_termios_baud_rate
+EXPORT_SYMBOL vmlinux 0x40b3613d	filp_close
+EXPORT_SYMBOL vmlinux 0x40d33bb9	put_tty_driver
+EXPORT_SYMBOL vmlinux 0x40e7f14b	__module_put_and_exit
+EXPORT_SYMBOL vmlinux 0x40f7a92d	serio_rescan
+EXPORT_SYMBOL vmlinux 0x4101bbde	param_set_copystring
+EXPORT_SYMBOL vmlinux 0x41083ef8	neigh_parms_alloc
+EXPORT_SYMBOL vmlinux 0x4108bdcf	pci_unregister_driver
+EXPORT_SYMBOL vmlinux 0x4108e69a	fb_match_mode
+EXPORT_SYMBOL vmlinux 0x41166725	inet_frags_init_net
+EXPORT_SYMBOL vmlinux 0x411bc3cf	try_to_release_page
+EXPORT_SYMBOL vmlinux 0x41344088	param_get_charp
+EXPORT_SYMBOL vmlinux 0x413a7685	swiotlb_sync_sg_for_cpu
+EXPORT_SYMBOL vmlinux 0x41482d8b	strndup_user
+EXPORT_SYMBOL vmlinux 0x414b1a61	gnet_stats_finish_copy
+EXPORT_SYMBOL vmlinux 0x415851eb	journal_flush
+EXPORT_SYMBOL vmlinux 0x416983d9	netdev_fix_features
+EXPORT_SYMBOL vmlinux 0x416cc14e	journal_init_dev
+EXPORT_SYMBOL vmlinux 0x4188d439	neigh_rand_reach_time
+EXPORT_SYMBOL vmlinux 0x41a9c68d	_spin_trylock_bh
+EXPORT_SYMBOL vmlinux 0x41e62b71	proc_mkdir
+EXPORT_SYMBOL vmlinux 0x42011542	take_over_console
+EXPORT_SYMBOL vmlinux 0x4211c3c1	zlib_inflateInit2
+EXPORT_SYMBOL vmlinux 0x42224298	sscanf
+EXPORT_SYMBOL vmlinux 0x424cbd7f	dget_locked
+EXPORT_SYMBOL vmlinux 0x424d04aa	d_obtain_alias
+EXPORT_SYMBOL vmlinux 0x424dfac4	cdev_index
+EXPORT_SYMBOL vmlinux 0x42595e58	vgacon_text_force
+EXPORT_SYMBOL vmlinux 0x42a4bdf2	in_egroup_p
+EXPORT_SYMBOL vmlinux 0x42acbf72	posix_acl_from_xattr
+EXPORT_SYMBOL vmlinux 0x42c8de35	ioremap_nocache
+EXPORT_SYMBOL vmlinux 0x42cfd37c	ip_setsockopt
+EXPORT_SYMBOL vmlinux 0x42d8c74b	flush_old_exec
+EXPORT_SYMBOL vmlinux 0x42e68303	input_set_keycode
+EXPORT_SYMBOL vmlinux 0x4302d0eb	free_pages
+EXPORT_SYMBOL vmlinux 0x4305e24e	current_fs_time
+EXPORT_SYMBOL vmlinux 0x43266b90	inet_dev_addr_type
+EXPORT_SYMBOL vmlinux 0x4327f0d5	memset_io
+EXPORT_SYMBOL vmlinux 0x4333eadb	param_set_short
+EXPORT_SYMBOL vmlinux 0x4335f8ce	set_create_files_as
+EXPORT_SYMBOL vmlinux 0x434fa55c	release_console_sem
+EXPORT_SYMBOL vmlinux 0x436c2179	iowrite32
+EXPORT_SYMBOL vmlinux 0x43ab61de	tcf_generic_walker
+EXPORT_SYMBOL vmlinux 0x43ab66c3	param_array_get
+EXPORT_SYMBOL vmlinux 0x43b5490c	ps2_drain
+EXPORT_SYMBOL vmlinux 0x43ec913a	put_cmsg
+EXPORT_SYMBOL vmlinux 0x43f1ed8a	nf_register_hook
+EXPORT_SYMBOL vmlinux 0x44161c19	unregister_shrinker
+EXPORT_SYMBOL vmlinux 0x4432bb4f	block_fsync
+EXPORT_SYMBOL vmlinux 0x444779c4	nla_find
+EXPORT_SYMBOL vmlinux 0x44551cf9	dm_io_client_destroy
+EXPORT_SYMBOL vmlinux 0x4458975a	wait_on_page_bit
+EXPORT_SYMBOL vmlinux 0x4462e96a	eth_type_trans
+EXPORT_SYMBOL vmlinux 0x44a69a57	kernel_sendmsg
+EXPORT_SYMBOL vmlinux 0x44b911c3	rb_replace_node
+EXPORT_SYMBOL vmlinux 0x44d560e3	init_level4_pgt
+EXPORT_SYMBOL vmlinux 0x44e9a829	match_token
+EXPORT_SYMBOL vmlinux 0x44f20aa8	skb_checksum
+EXPORT_SYMBOL vmlinux 0x4534b587	generic_file_splice_write
+EXPORT_SYMBOL vmlinux 0x453c8403	pci_msi_enabled
+EXPORT_SYMBOL vmlinux 0x45450063	mod_timer
+EXPORT_SYMBOL vmlinux 0x4546232e	hippi_mac_addr
+EXPORT_SYMBOL vmlinux 0x4550ba8a	register_cpu_notifier
+EXPORT_SYMBOL vmlinux 0x4563d1ad	__splice_from_pipe
+EXPORT_SYMBOL vmlinux 0x45704798	print_hex_dump_bytes
+EXPORT_SYMBOL vmlinux 0x4575315d	utf8s_to_utf16s
+EXPORT_SYMBOL vmlinux 0x45947727	param_array_set
+EXPORT_SYMBOL vmlinux 0x45a6a978	dm_io_client_create
+EXPORT_SYMBOL vmlinux 0x45afb208	free_buffer_head
+EXPORT_SYMBOL vmlinux 0x45d11c43	down_interruptible
+EXPORT_SYMBOL vmlinux 0x45d18dd3	tcf_action_dump_1
+EXPORT_SYMBOL vmlinux 0x45d55543	down_write
+EXPORT_SYMBOL vmlinux 0x45dcc6ce	vcc_release_async
+EXPORT_SYMBOL vmlinux 0x45e6d70a	generic_file_buffered_write
+EXPORT_SYMBOL vmlinux 0x46085e4f	add_timer
+EXPORT_SYMBOL vmlinux 0x46417634	pci_disable_msi
+EXPORT_SYMBOL vmlinux 0x464ad98d	invalidate_bdev
+EXPORT_SYMBOL vmlinux 0x4659b894	security_inode_permission
+EXPORT_SYMBOL vmlinux 0x466c14a7	__delay
+EXPORT_SYMBOL vmlinux 0x46cd2f0b	compat_nf_setsockopt
+EXPORT_SYMBOL vmlinux 0x46d88d07	end_buffer_write_sync
+EXPORT_SYMBOL vmlinux 0x46e5ca4d	phy_driver_register
+EXPORT_SYMBOL vmlinux 0x4704c18d	sock_no_accept
+EXPORT_SYMBOL vmlinux 0x471b6a7c	register_snap_client
+EXPORT_SYMBOL vmlinux 0x4721b588	tcf_exts_change
+EXPORT_SYMBOL vmlinux 0x4740b112	seq_release
+EXPORT_SYMBOL vmlinux 0x47431e25	phy_ethtool_gset
+EXPORT_SYMBOL vmlinux 0x475100c2	inet_get_local_port_range
+EXPORT_SYMBOL vmlinux 0x4755d100	ethtool_op_set_tx_csum
+EXPORT_SYMBOL vmlinux 0x47739ada	tcp_prot
+EXPORT_SYMBOL vmlinux 0x4774b075	skb_checksum_help
+EXPORT_SYMBOL vmlinux 0x4779d296	pagecache_write_end
+EXPORT_SYMBOL vmlinux 0x479c3c86	find_next_zero_bit
+EXPORT_SYMBOL vmlinux 0x47b2b6d1	set_security_override
+EXPORT_SYMBOL vmlinux 0x4801c6e6	call_usermodehelper_setkeys
+EXPORT_SYMBOL vmlinux 0x4830f235	nf_afinfo
+EXPORT_SYMBOL vmlinux 0x4859b8bb	rtc_year_days
+EXPORT_SYMBOL vmlinux 0x4861bd55	submit_bh
+EXPORT_SYMBOL vmlinux 0x486b6407	hweight64
+EXPORT_SYMBOL vmlinux 0x4883fdc0	sock_wfree
+EXPORT_SYMBOL vmlinux 0x48cca91d	in_dev_finish_destroy
+EXPORT_SYMBOL vmlinux 0x4900f222	blk_make_request
+EXPORT_SYMBOL vmlinux 0x49439411	genl_unregister_family
+EXPORT_SYMBOL vmlinux 0x4948d8b2	posix_test_lock
+EXPORT_SYMBOL vmlinux 0x494e3393	vm_get_page_prot
+EXPORT_SYMBOL vmlinux 0x4951f85a	pci_enable_device_io
+EXPORT_SYMBOL vmlinux 0x49603fb8	security_sb_copy_data
+EXPORT_SYMBOL vmlinux 0x4964c289	mb_cache_create
+EXPORT_SYMBOL vmlinux 0x496cdf45	jbd2_journal_revoke
+EXPORT_SYMBOL vmlinux 0x49ab1a77	tty_unregister_device
+EXPORT_SYMBOL vmlinux 0x49ba663d	hippi_neigh_setup_dev
+EXPORT_SYMBOL vmlinux 0x49da9a9a	_read_unlock_bh
+EXPORT_SYMBOL vmlinux 0x49e182c0	param_get_string
+EXPORT_SYMBOL vmlinux 0x49e83047	simple_sync_file
+EXPORT_SYMBOL vmlinux 0x49ea6952	inode_setattr
+EXPORT_SYMBOL vmlinux 0x49fa7449	compat_nf_getsockopt
+EXPORT_SYMBOL vmlinux 0x4a138123	xfrm_bundle_ok
+EXPORT_SYMBOL vmlinux 0x4a358252	__bitmap_subset
+EXPORT_SYMBOL vmlinux 0x4a3a54e8	kmem_cache_alloc
+EXPORT_SYMBOL vmlinux 0x4a575bf7	configfs_unregister_subsystem
+EXPORT_SYMBOL vmlinux 0x4a5bc9f5	nla_reserve_nohdr
+EXPORT_SYMBOL vmlinux 0x4abdce39	pci_bus_read_config_byte
+EXPORT_SYMBOL vmlinux 0x4acd93d3	release_resource
+EXPORT_SYMBOL vmlinux 0x4b07e779	_spin_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x4b17e9af	inet_del_protocol
+EXPORT_SYMBOL vmlinux 0x4b4262c0	ethtool_op_get_flags
+EXPORT_SYMBOL vmlinux 0x4b74758c	sock_create_kern
+EXPORT_SYMBOL vmlinux 0x4b8d21ee	tcf_hash_lookup
+EXPORT_SYMBOL vmlinux 0x4b97c981	qdisc_watchdog_cancel
+EXPORT_SYMBOL vmlinux 0x4ba96044	eth_validate_addr
+EXPORT_SYMBOL vmlinux 0x4bbb1235	pcim_enable_device
+EXPORT_SYMBOL vmlinux 0x4bbb87b4	seq_escape
+EXPORT_SYMBOL vmlinux 0x4bbc3e5f	pm_flags
+EXPORT_SYMBOL vmlinux 0x4bdf028e	idr_find
+EXPORT_SYMBOL vmlinux 0x4c1182cb	bitmap_scnprintf
+EXPORT_SYMBOL vmlinux 0x4c1b965c	gen_replace_estimator
+EXPORT_SYMBOL vmlinux 0x4c1fc9c7	vfs_quota_on
+EXPORT_SYMBOL vmlinux 0x4c22403c	audit_log_format
+EXPORT_SYMBOL vmlinux 0x4c2395e6	writeback_inodes_sb
+EXPORT_SYMBOL vmlinux 0x4c282ab3	give_up_console
+EXPORT_SYMBOL vmlinux 0x4c30c5bd	blk_rq_map_sg
+EXPORT_SYMBOL vmlinux 0x4c4c956e	nla_memcmp
+EXPORT_SYMBOL vmlinux 0x4c761044	textsearch_prepare
+EXPORT_SYMBOL vmlinux 0x4c949199	jbd2_journal_forget
+EXPORT_SYMBOL vmlinux 0x4cbbd171	__bitmap_weight
+EXPORT_SYMBOL vmlinux 0x4cccb116	kmem_cache_size
+EXPORT_SYMBOL vmlinux 0x4d8b7eef	w1_add_master_device
+EXPORT_SYMBOL vmlinux 0x4d9e74ff	bdi_init
+EXPORT_SYMBOL vmlinux 0x4dc45be9	nf_log_unbind_pf
+EXPORT_SYMBOL vmlinux 0x4dd9458e	compat_ip_getsockopt
+EXPORT_SYMBOL vmlinux 0x4dda726b	match_strlcpy
+EXPORT_SYMBOL vmlinux 0x4ddae281	tcf_exts_dump_stats
+EXPORT_SYMBOL vmlinux 0x4de857fe	sock_no_setsockopt
+EXPORT_SYMBOL vmlinux 0x4df119fa	__bitmap_parse
+EXPORT_SYMBOL vmlinux 0x4e069249	security_tun_dev_post_create
+EXPORT_SYMBOL vmlinux 0x4e3567f7	match_int
+EXPORT_SYMBOL vmlinux 0x4e6e8ea7	fg_console
+EXPORT_SYMBOL vmlinux 0x4e7c3189	netdev_class_create_file
+EXPORT_SYMBOL vmlinux 0x4e9b411f	bio_integrity_split
+EXPORT_SYMBOL vmlinux 0x4eaafa55	kmem_cache_shrink
+EXPORT_SYMBOL vmlinux 0x4ead5a5e	seq_path
+EXPORT_SYMBOL vmlinux 0x4edb0135	phy_device_register
+EXPORT_SYMBOL vmlinux 0x4edd72f7	block_all_signals
+EXPORT_SYMBOL vmlinux 0x4eec6d31	sg_miter_next
+EXPORT_SYMBOL vmlinux 0x4ef4fa60	journal_release_buffer
+EXPORT_SYMBOL vmlinux 0x4f1cd128	security_tun_dev_create
+EXPORT_SYMBOL vmlinux 0x4f361043	__xfrm_lookup
+EXPORT_SYMBOL vmlinux 0x4f476e96	init_cdrom_command
+EXPORT_SYMBOL vmlinux 0x4f5438c1	idle_halt
+EXPORT_SYMBOL vmlinux 0x4f5754ce	bio_integrity_tag_size
+EXPORT_SYMBOL vmlinux 0x4f60c34f	__blk_run_queue
+EXPORT_SYMBOL vmlinux 0x4fdee897	i8042_command
+EXPORT_SYMBOL vmlinux 0x4fecef57	ip_ct_attach
+EXPORT_SYMBOL vmlinux 0x4ff9a064	xfrm_cfg_mutex
+EXPORT_SYMBOL vmlinux 0x5003ce94	generic_file_aio_write
+EXPORT_SYMBOL vmlinux 0x5015a0b6	config_group_init
+EXPORT_SYMBOL vmlinux 0x50211ee3	tcp_free_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x50256365	brioctl_set
+EXPORT_SYMBOL vmlinux 0x503eda71	input_filter_device
+EXPORT_SYMBOL vmlinux 0x5044ce84	ipv6_skip_exthdr
+EXPORT_SYMBOL vmlinux 0x5048da06	xfrm_unregister_type
+EXPORT_SYMBOL vmlinux 0x50571834	fasync_helper
+EXPORT_SYMBOL vmlinux 0x506746b6	getrawmonotonic
+EXPORT_SYMBOL vmlinux 0x506e1807	blk_queue_invalidate_tags
+EXPORT_SYMBOL vmlinux 0x507f833b	tty_pair_get_tty
+EXPORT_SYMBOL vmlinux 0x50803632	vga_client_register
+EXPORT_SYMBOL vmlinux 0x5084c72a	blk_complete_request
+EXPORT_SYMBOL vmlinux 0x5095d271	lock_may_write
+EXPORT_SYMBOL vmlinux 0x50b5cb2d	idr_get_new_above
+EXPORT_SYMBOL vmlinux 0x50ccb6bf	simple_unlink
+EXPORT_SYMBOL vmlinux 0x50d1f79a	find_vma
+EXPORT_SYMBOL vmlinux 0x50d56018	posix_acl_equiv_mode
+EXPORT_SYMBOL vmlinux 0x50da351b	deactivate_super
+EXPORT_SYMBOL vmlinux 0x50f12610	swiotlb_sync_single_for_device
+EXPORT_SYMBOL vmlinux 0x5118c382	secure_dccp_sequence_number
+EXPORT_SYMBOL vmlinux 0x51282178	alloc_pci_dev
+EXPORT_SYMBOL vmlinux 0x515cc42f	send_sig
+EXPORT_SYMBOL vmlinux 0x51628472	xfrm_state_check_expire
+EXPORT_SYMBOL vmlinux 0x519c4e0f	skb_copy
+EXPORT_SYMBOL vmlinux 0x51abb568	sock_no_sendmsg
+EXPORT_SYMBOL vmlinux 0x51b27768	xfrm_policy_walk
+EXPORT_SYMBOL vmlinux 0x51bdd914	seq_read
+EXPORT_SYMBOL vmlinux 0x51dce73b	xfrm_state_walk_init
+EXPORT_SYMBOL vmlinux 0x51e40120	__inet6_hash
+EXPORT_SYMBOL vmlinux 0x51e541bc	lock_may_read
+EXPORT_SYMBOL vmlinux 0x51fea253	register_console
+EXPORT_SYMBOL vmlinux 0x52026cdf	security_sb_parse_opts_str
+EXPORT_SYMBOL vmlinux 0x5214722d	jbd2_journal_set_features
+EXPORT_SYMBOL vmlinux 0x523d99fb	d_alloc
+EXPORT_SYMBOL vmlinux 0x5252f304	__memcpy_toio
+EXPORT_SYMBOL vmlinux 0x526beec7	vlan_dev_real_dev
+EXPORT_SYMBOL vmlinux 0x52760ca9	getnstimeofday
+EXPORT_SYMBOL vmlinux 0x52a58c24	ifla_policy
+EXPORT_SYMBOL vmlinux 0x52cb7c19	security_task_getsecid
+EXPORT_SYMBOL vmlinux 0x52d7b2fd	llc_sap_list
+EXPORT_SYMBOL vmlinux 0x52ebb126	param_get_ushort
+EXPORT_SYMBOL vmlinux 0x52f05778	tcp_shutdown
+EXPORT_SYMBOL vmlinux 0x52fac5b1	phy_disable_interrupts
+EXPORT_SYMBOL vmlinux 0x52fffebe	ethtool_op_set_flags
+EXPORT_SYMBOL vmlinux 0x531b604e	__virt_addr_valid
+EXPORT_SYMBOL vmlinux 0x531d4300	dquot_claim_space
+EXPORT_SYMBOL vmlinux 0x5329b67e	unregister_binfmt
+EXPORT_SYMBOL vmlinux 0x53326531	mempool_alloc_pages
+EXPORT_SYMBOL vmlinux 0x5343835a	ppp_register_compressor
+EXPORT_SYMBOL vmlinux 0x535bbc05	pneigh_enqueue
+EXPORT_SYMBOL vmlinux 0x537577f3	con_is_bound
+EXPORT_SYMBOL vmlinux 0x5377c402	xfrm_lookup
+EXPORT_SYMBOL vmlinux 0x53c0767c	sk_chk_filter
+EXPORT_SYMBOL vmlinux 0x53ec649a	sock_no_getsockopt
+EXPORT_SYMBOL vmlinux 0x53f72782	inet_frag_kill
+EXPORT_SYMBOL vmlinux 0x53f9a247	writeback_inodes_sb_if_idle
+EXPORT_SYMBOL vmlinux 0x5408f929	gnet_stats_start_copy_compat
+EXPORT_SYMBOL vmlinux 0x5425ad0e	end_page_writeback
+EXPORT_SYMBOL vmlinux 0x54290dc9	nla_validate
+EXPORT_SYMBOL vmlinux 0x54809310	thermal_zone_unbind_cooling_device
+EXPORT_SYMBOL vmlinux 0x54a2a2f2	pci_scan_bridge
+EXPORT_SYMBOL vmlinux 0x54a41c48	simple_link
+EXPORT_SYMBOL vmlinux 0x54b2423d	dput
+EXPORT_SYMBOL vmlinux 0x54b6a6c5	vfs_follow_link
+EXPORT_SYMBOL vmlinux 0x54b828e7	kernel_getsockname
+EXPORT_SYMBOL vmlinux 0x54b932c8	netlink_broadcast
+EXPORT_SYMBOL vmlinux 0x54be4976	vlan_gro_frags
+EXPORT_SYMBOL vmlinux 0x54d78327	alloc_disk
+EXPORT_SYMBOL vmlinux 0x54dd5bac	fb_set_var
+EXPORT_SYMBOL vmlinux 0x54e6fcdd	net_enable_timestamp
+EXPORT_SYMBOL vmlinux 0x5501b79a	__skb_warn_lro_forwarding
+EXPORT_SYMBOL vmlinux 0x550f19a3	sock_alloc_send_skb
+EXPORT_SYMBOL vmlinux 0x551e6138	unregister_sysrq_key
+EXPORT_SYMBOL vmlinux 0x55286cb4	xfrm_find_acq
+EXPORT_SYMBOL vmlinux 0x554ed390	__sk_dst_check
+EXPORT_SYMBOL vmlinux 0x554f0a48	groups_alloc
+EXPORT_SYMBOL vmlinux 0x5594be03	bitmap_remap
+EXPORT_SYMBOL vmlinux 0x55a286bf	proc_dointvec_minmax
+EXPORT_SYMBOL vmlinux 0x55ec88ba	xfrm_state_walk
+EXPORT_SYMBOL vmlinux 0x5600904f	fb_get_color_depth
+EXPORT_SYMBOL vmlinux 0x5603cf43	do_settimeofday
+EXPORT_SYMBOL vmlinux 0x5614b010	xfrm_policy_walk_done
+EXPORT_SYMBOL vmlinux 0x5635a60a	vmalloc_user
+EXPORT_SYMBOL vmlinux 0x5640fb36	module_refcount
+EXPORT_SYMBOL vmlinux 0x566e98d6	devm_ioport_map
+EXPORT_SYMBOL vmlinux 0x56755388	security_d_instantiate
+EXPORT_SYMBOL vmlinux 0x567a1c75	pci_remove_bus
+EXPORT_SYMBOL vmlinux 0x569f281f	ip_mc_join_group
+EXPORT_SYMBOL vmlinux 0x56a17bef	bio_integrity_endio
+EXPORT_SYMBOL vmlinux 0x56a8774f	tty_pair_get_pty
+EXPORT_SYMBOL vmlinux 0x56e39038	__ps2_command
+EXPORT_SYMBOL vmlinux 0x56e88418	inc_zone_page_state
+EXPORT_SYMBOL vmlinux 0x56f1cf05	ip_cmsg_recv
+EXPORT_SYMBOL vmlinux 0x56f38712	schedule_delayed_work_on
+EXPORT_SYMBOL vmlinux 0x56f494e0	smp_call_function
+EXPORT_SYMBOL vmlinux 0x570bbf20	dev_addr_del
+EXPORT_SYMBOL vmlinux 0x5722cc82	tcp_sync_mss
+EXPORT_SYMBOL vmlinux 0x5725cb1e	nf_log_register
+EXPORT_SYMBOL vmlinux 0x572c4c45	kobject_get
+EXPORT_SYMBOL vmlinux 0x572e85d4	blk_lookup_devt
+EXPORT_SYMBOL vmlinux 0x57adf756	per_cpu__this_cpu_off
+EXPORT_SYMBOL vmlinux 0x57b57ebe	jiffies_to_timespec
+EXPORT_SYMBOL vmlinux 0x57c2bd17	dqput
+EXPORT_SYMBOL vmlinux 0x57c7697c	inode_sub_bytes
+EXPORT_SYMBOL vmlinux 0x57db7242	mangle_path
+EXPORT_SYMBOL vmlinux 0x57df7986	blk_rq_map_kern
+EXPORT_SYMBOL vmlinux 0x57e2d61f	neigh_connected_output
+EXPORT_SYMBOL vmlinux 0x580e898c	journal_wipe
+EXPORT_SYMBOL vmlinux 0x5838f6c9	rtc_valid_tm
+EXPORT_SYMBOL vmlinux 0x583bba83	filemap_fdatawait
+EXPORT_SYMBOL vmlinux 0x5844ee60	blk_queue_find_tag
+EXPORT_SYMBOL vmlinux 0x584738f9	rdmsr_safe_on_cpu
+EXPORT_SYMBOL vmlinux 0x5847dbcb	phy_driver_unregister
+EXPORT_SYMBOL vmlinux 0x5854559d	iov_iter_copy_from_user_atomic
+EXPORT_SYMBOL vmlinux 0x5854a4c8	journal_destroy
+EXPORT_SYMBOL vmlinux 0x5857b225	ioread16_rep
+EXPORT_SYMBOL vmlinux 0x589e6686	set_device_ro
+EXPORT_SYMBOL vmlinux 0x58c08ee7	pci_claim_resource
+EXPORT_SYMBOL vmlinux 0x58d24429	sock_no_shutdown
+EXPORT_SYMBOL vmlinux 0x58d67f5c	generic_file_open
+EXPORT_SYMBOL vmlinux 0x58e323f7	jbd2_journal_lock_updates
+EXPORT_SYMBOL vmlinux 0x591acdb7	follow_up
+EXPORT_SYMBOL vmlinux 0x5927f42a	bio_pair_release
+EXPORT_SYMBOL vmlinux 0x5934392b	fb_register_client
+EXPORT_SYMBOL vmlinux 0x594bf15b	ioport_map
+EXPORT_SYMBOL vmlinux 0x59567732	netif_device_detach
+EXPORT_SYMBOL vmlinux 0x595ee1d7	page_put_link
+EXPORT_SYMBOL vmlinux 0x5985e431	swiotlb_sync_sg_for_device
+EXPORT_SYMBOL vmlinux 0x598ecf6c	skb_store_bits
+EXPORT_SYMBOL vmlinux 0x59ad42f8	dquot_commit
+EXPORT_SYMBOL vmlinux 0x59adf30b	tcp_v4_destroy_sock
+EXPORT_SYMBOL vmlinux 0x59d696b6	register_module_notifier
+EXPORT_SYMBOL vmlinux 0x5a02755a	copy_strings_kernel
+EXPORT_SYMBOL vmlinux 0x5a26152a	tty_port_block_til_ready
+EXPORT_SYMBOL vmlinux 0x5a34a45c	__kmalloc
+EXPORT_SYMBOL vmlinux 0x5a4896a8	__put_user_2
+EXPORT_SYMBOL vmlinux 0x5a4a5422	input_unregister_device
+EXPORT_SYMBOL vmlinux 0x5a57d155	__percpu_counter_init
+EXPORT_SYMBOL vmlinux 0x5a5e7ea3	simple_read_from_buffer
+EXPORT_SYMBOL vmlinux 0x5a744b86	netlink_set_nonroot
+EXPORT_SYMBOL vmlinux 0x5a939841	set_pages_x
+EXPORT_SYMBOL vmlinux 0x5b1689da	ll_rw_block
+EXPORT_SYMBOL vmlinux 0x5b1d2915	bd_release
+EXPORT_SYMBOL vmlinux 0x5b27bcec	sysctl_intvec
+EXPORT_SYMBOL vmlinux 0x5b397116	netif_rx
+EXPORT_SYMBOL vmlinux 0x5b4712c8	mdiobus_alloc
+EXPORT_SYMBOL vmlinux 0x5b4cd923	per_cpu__cpu_info
+EXPORT_SYMBOL vmlinux 0x5b5a2a32	smp_call_function_many
+EXPORT_SYMBOL vmlinux 0x5b5d7ac9	pcie_port_service_unregister
+EXPORT_SYMBOL vmlinux 0x5b6ef2c8	kobject_del
+EXPORT_SYMBOL vmlinux 0x5baf585d	rtnetlink_put_metrics
+EXPORT_SYMBOL vmlinux 0x5bd73f69	dev_open
+EXPORT_SYMBOL vmlinux 0x5be865f4	sock_recvmsg
+EXPORT_SYMBOL vmlinux 0x5bf7a78c	udp_lib_getsockopt
+EXPORT_SYMBOL vmlinux 0x5c11290f	dev_unicast_sync
+EXPORT_SYMBOL vmlinux 0x5c45f8b0	filemap_write_and_wait_range
+EXPORT_SYMBOL vmlinux 0x5c7e08f2	dm_unregister_target
+EXPORT_SYMBOL vmlinux 0x5cc8e015	iov_iter_single_seg_count
+EXPORT_SYMBOL vmlinux 0x5d1cdc16	inet_release
+EXPORT_SYMBOL vmlinux 0x5d26d556	tty_insert_flip_string_flags
+EXPORT_SYMBOL vmlinux 0x5d459a9a	phy_attach
+EXPORT_SYMBOL vmlinux 0x5d6c8089	lookup_hash
+EXPORT_SYMBOL vmlinux 0x5d8347f6	vfs_mknod
+EXPORT_SYMBOL vmlinux 0x5d864953	dm_io
+EXPORT_SYMBOL vmlinux 0x5d95ba0f	iunique
+EXPORT_SYMBOL vmlinux 0x5da3addc	tcp_v4_syn_recv_sock
+EXPORT_SYMBOL vmlinux 0x5daebe2f	thaw_process
+EXPORT_SYMBOL vmlinux 0x5dcbdce5	km_new_mapping
+EXPORT_SYMBOL vmlinux 0x5ddf8702	tcp_check_req
+EXPORT_SYMBOL vmlinux 0x5e0da20e	xfrm_state_delete
+EXPORT_SYMBOL vmlinux 0x5e6ef6fa	ip_xfrm_me_harder
+EXPORT_SYMBOL vmlinux 0x5e74fee7	rtnl_notify
+EXPORT_SYMBOL vmlinux 0x5e8a2229	kill_fasync
+EXPORT_SYMBOL vmlinux 0x5e95b1cd	current_umask
+EXPORT_SYMBOL vmlinux 0x5ea520c5	tcp_select_initial_window
+EXPORT_SYMBOL vmlinux 0x5ec351e0	module_layout
+EXPORT_SYMBOL vmlinux 0x5ed040b0	pm_set_vt_switch
+EXPORT_SYMBOL vmlinux 0x5edd0762	bin2bcd
+EXPORT_SYMBOL vmlinux 0x5edd4023	invalidate_partition
+EXPORT_SYMBOL vmlinux 0x5f0707f8	kernel_getpeername
+EXPORT_SYMBOL vmlinux 0x5f279b9f	generic_write_sync
+EXPORT_SYMBOL vmlinux 0x5f2e955e	journal_blocks_per_page
+EXPORT_SYMBOL vmlinux 0x5f309e64	default_llseek
+EXPORT_SYMBOL vmlinux 0x5f56db66	per_cpu__ftrace_event_seq
+EXPORT_SYMBOL vmlinux 0x5f5f2824	neigh_sysctl_register
+EXPORT_SYMBOL vmlinux 0x5f733af2	cdrom_open
+EXPORT_SYMBOL vmlinux 0x5f99dbfb	register_sysctl_table
+EXPORT_SYMBOL vmlinux 0x5fbeab67	block_commit_write
+EXPORT_SYMBOL vmlinux 0x5feec4b7	genphy_resume
+EXPORT_SYMBOL vmlinux 0x600683d3	do_unblank_screen
+EXPORT_SYMBOL vmlinux 0x600bf182	tcp_v4_md5_do_add
+EXPORT_SYMBOL vmlinux 0x603f4b6b	clip_tbl_hook
+EXPORT_SYMBOL vmlinux 0x605c8bde	radix_tree_delete
+EXPORT_SYMBOL vmlinux 0x609f1c7e	synchronize_net
+EXPORT_SYMBOL vmlinux 0x60a0ebad	__tracepoint_kmem_cache_alloc_node
+EXPORT_SYMBOL vmlinux 0x60a32ea9	pm_power_off
+EXPORT_SYMBOL vmlinux 0x61226334	seq_lseek
+EXPORT_SYMBOL vmlinux 0x612390ad	netpoll_set_trap
+EXPORT_SYMBOL vmlinux 0x612828e9	pci_lost_interrupt
+EXPORT_SYMBOL vmlinux 0x613d8d18	generic_permission
+EXPORT_SYMBOL vmlinux 0x618d8299	set_notify_swap_entry_free
+EXPORT_SYMBOL vmlinux 0x619b5b4c	sk_stream_wait_connect
+EXPORT_SYMBOL vmlinux 0x61b7b126	simple_strtoull
+EXPORT_SYMBOL vmlinux 0x61c00471	netdev_rx_csum_fault
+EXPORT_SYMBOL vmlinux 0x61c7197e	sock_no_getname
+EXPORT_SYMBOL vmlinux 0x61cda816	blk_plug_device_unlocked
+EXPORT_SYMBOL vmlinux 0x61f0a8d4	freeze_bdev
+EXPORT_SYMBOL vmlinux 0x61f487d3	bio_phys_segments
+EXPORT_SYMBOL vmlinux 0x61f7fdbe	lock_super
+EXPORT_SYMBOL vmlinux 0x6204e82a	phy_detach
+EXPORT_SYMBOL vmlinux 0x6226b9fa	machine_to_phys_mapping
+EXPORT_SYMBOL vmlinux 0x623c82ab	dquot_free_space
+EXPORT_SYMBOL vmlinux 0x623e60a4	blk_queue_bounce_limit
+EXPORT_SYMBOL vmlinux 0x62737e1d	sock_unregister
+EXPORT_SYMBOL vmlinux 0x62755e92	mb_cache_entry_get
+EXPORT_SYMBOL vmlinux 0x62827bec	security_secctx_to_secid
+EXPORT_SYMBOL vmlinux 0x62cef780	__getblk
+EXPORT_SYMBOL vmlinux 0x62dbd83b	inet_frags_fini
+EXPORT_SYMBOL vmlinux 0x62dcb1cc	netlink_dump_start
+EXPORT_SYMBOL vmlinux 0x62df27ae	pci_dev_driver
+EXPORT_SYMBOL vmlinux 0x62e3e9e7	tty_port_free_xmit_buf
+EXPORT_SYMBOL vmlinux 0x62e81996	pci_scan_slot
+EXPORT_SYMBOL vmlinux 0x6307fc98	del_timer
+EXPORT_SYMBOL vmlinux 0x630982c1	block_read_full_page
+EXPORT_SYMBOL vmlinux 0x6320af6c	dquot_release_reserved_space
+EXPORT_SYMBOL vmlinux 0x633466aa	security_inode_setsecctx
+EXPORT_SYMBOL vmlinux 0x63385502	kernel_accept
+EXPORT_SYMBOL vmlinux 0x634c3aa1	ethtool_op_get_sg
+EXPORT_SYMBOL vmlinux 0x635907b8	km_state_expired
+EXPORT_SYMBOL vmlinux 0x63709ef8	inet_sendmsg
+EXPORT_SYMBOL vmlinux 0x638e2ab1	generic_fillattr
+EXPORT_SYMBOL vmlinux 0x63ae5bc8	inet_frags_exit_net
+EXPORT_SYMBOL vmlinux 0x63e4a16a	pci_dev_put
+EXPORT_SYMBOL vmlinux 0x63ecad53	register_netdevice_notifier
+EXPORT_SYMBOL vmlinux 0x63f9904b	framebuffer_alloc
+EXPORT_SYMBOL vmlinux 0x63fc232f	strlen_user
+EXPORT_SYMBOL vmlinux 0x6403e338	tcp_memory_pressure
+EXPORT_SYMBOL vmlinux 0x642e54ac	__wake_up
+EXPORT_SYMBOL vmlinux 0x643053f8	tcp4_gro_receive
+EXPORT_SYMBOL vmlinux 0x6466a1e6	mempool_alloc
+EXPORT_SYMBOL vmlinux 0x647a568f	phy_register_fixup_for_uid
+EXPORT_SYMBOL vmlinux 0x64999478	congestion_wait
+EXPORT_SYMBOL vmlinux 0x64af9059	ilookup
+EXPORT_SYMBOL vmlinux 0x64afade1	set_disk_ro
+EXPORT_SYMBOL vmlinux 0x64d1b3ce	put_page
+EXPORT_SYMBOL vmlinux 0x64d4bc10	skb_dequeue_tail
+EXPORT_SYMBOL vmlinux 0x64eae7ad	set_memory_array_wb
+EXPORT_SYMBOL vmlinux 0x65022a24	radix_tree_prev_hole
+EXPORT_SYMBOL vmlinux 0x65066474	generic_file_readonly_mmap
+EXPORT_SYMBOL vmlinux 0x650fb346	add_wait_queue
+EXPORT_SYMBOL vmlinux 0x65197428	security_path_rename
+EXPORT_SYMBOL vmlinux 0x651a4139	test_taint
+EXPORT_SYMBOL vmlinux 0x65408378	zlib_inflate_blob
+EXPORT_SYMBOL vmlinux 0x65414e67	dev_valid_name
+EXPORT_SYMBOL vmlinux 0x6555ec3b	xfrm_state_add
+EXPORT_SYMBOL vmlinux 0x6587c80f	xfrm_register_type
+EXPORT_SYMBOL vmlinux 0x659e6c6c	skb_free_datagram
+EXPORT_SYMBOL vmlinux 0x65d62740	jbd2_journal_destroy
+EXPORT_SYMBOL vmlinux 0x65d67625	ethtool_op_get_ufo
+EXPORT_SYMBOL vmlinux 0x66152ee3	register_msi_get_owner
+EXPORT_SYMBOL vmlinux 0x661a5783	proc_dointvec_userhz_jiffies
+EXPORT_SYMBOL vmlinux 0x661e6f4e	seq_bitmap_list
+EXPORT_SYMBOL vmlinux 0x6621a718	ip_mc_dec_group
+EXPORT_SYMBOL vmlinux 0x663e62f6	noop_qdisc
+EXPORT_SYMBOL vmlinux 0x668a913a	__dev_get_by_name
+EXPORT_SYMBOL vmlinux 0x668d1aea	journal_ack_err
+EXPORT_SYMBOL vmlinux 0x668da8d5	zlib_inflateIncomp
+EXPORT_SYMBOL vmlinux 0x668dceba	input_inject_event
+EXPORT_SYMBOL vmlinux 0x669e20a1	prepare_binprm
+EXPORT_SYMBOL vmlinux 0x66cbb54d	pci_map_rom
+EXPORT_SYMBOL vmlinux 0x66df58b3	udp_disconnect
+EXPORT_SYMBOL vmlinux 0x66fa93f4	find_or_create_page
+EXPORT_SYMBOL vmlinux 0x67053080	current_kernel_time
+EXPORT_SYMBOL vmlinux 0x672144bd	strlcpy
+EXPORT_SYMBOL vmlinux 0x67257087	tcf_em_tree_destroy
+EXPORT_SYMBOL vmlinux 0x6729d3df	__get_user_4
+EXPORT_SYMBOL vmlinux 0x67342bca	pci_pme_active
+EXPORT_SYMBOL vmlinux 0x673765fd	neigh_seq_stop
+EXPORT_SYMBOL vmlinux 0x6746b939	pci_fixup_device
+EXPORT_SYMBOL vmlinux 0x678cf024	__xfrm_state_destroy
+EXPORT_SYMBOL vmlinux 0x67928521	file_permission
+EXPORT_SYMBOL vmlinux 0x67b27ec1	tty_std_termios
+EXPORT_SYMBOL vmlinux 0x67b294fd	clocksource_register
+EXPORT_SYMBOL vmlinux 0x67fd266a	pipe_lock
+EXPORT_SYMBOL vmlinux 0x684be4fc	blk_remove_plug
+EXPORT_SYMBOL vmlinux 0x687fdf8f	bio_integrity_set_tag
+EXPORT_SYMBOL vmlinux 0x68bfe4ea	ps2_begin_command
+EXPORT_SYMBOL vmlinux 0x68cb8a68	xfrm_state_delete_tunnel
+EXPORT_SYMBOL vmlinux 0x68da63d3	get_empty_filp
+EXPORT_SYMBOL vmlinux 0x68fdcfa2	simple_transaction_read
+EXPORT_SYMBOL vmlinux 0x6907d4e9	idr_for_each
+EXPORT_SYMBOL vmlinux 0x69221331	block_write_full_page_endio
+EXPORT_SYMBOL vmlinux 0x693cd1cb	config_group_find_item
+EXPORT_SYMBOL vmlinux 0x6971447a	rtc_month_days
+EXPORT_SYMBOL vmlinux 0x6975c20f	neigh_table_init
+EXPORT_SYMBOL vmlinux 0x697cb0a0	sysctl_ms_jiffies
+EXPORT_SYMBOL vmlinux 0x6980fe91	param_get_int
+EXPORT_SYMBOL vmlinux 0x6983b855	tty_port_carrier_raised
+EXPORT_SYMBOL vmlinux 0x69927dff	try_acquire_console_sem
+EXPORT_SYMBOL vmlinux 0x69a0ca7d	iowrite16be
+EXPORT_SYMBOL vmlinux 0x69a358a6	iomem_resource
+EXPORT_SYMBOL vmlinux 0x69c8c1d5	security_req_classify_flow
+EXPORT_SYMBOL vmlinux 0x69e27c7a	bitmap_copy_le
+EXPORT_SYMBOL vmlinux 0x69ea0cfc	vfs_link
+EXPORT_SYMBOL vmlinux 0x6a037cf1	mempool_kfree
+EXPORT_SYMBOL vmlinux 0x6a06e67d	bio_add_pc_page
+EXPORT_SYMBOL vmlinux 0x6a47571d	__set_personality
+EXPORT_SYMBOL vmlinux 0x6a54039e	bio_split
+EXPORT_SYMBOL vmlinux 0x6a5f98a0	ida_get_new_above
+EXPORT_SYMBOL vmlinux 0x6a5fa363	sigprocmask
+EXPORT_SYMBOL vmlinux 0x6a68d75c	km_state_notify
+EXPORT_SYMBOL vmlinux 0x6a76f3ac	blk_iopoll_enable
+EXPORT_SYMBOL vmlinux 0x6a9f26c9	init_timer_key
+EXPORT_SYMBOL vmlinux 0x6aa72708	file_fsync
+EXPORT_SYMBOL vmlinux 0x6acb973d	iowrite32be
+EXPORT_SYMBOL vmlinux 0x6ad065f4	param_set_charp
+EXPORT_SYMBOL vmlinux 0x6ade71bc	neigh_seq_next
+EXPORT_SYMBOL vmlinux 0x6afe8ea5	blk_start_request
+EXPORT_SYMBOL vmlinux 0x6b07348c	cdev_del
+EXPORT_SYMBOL vmlinux 0x6b07f4ed	cont_write_begin
+EXPORT_SYMBOL vmlinux 0x6b0c99b4	uart_match_port
+EXPORT_SYMBOL vmlinux 0x6b1b67d3	__bdevname
+EXPORT_SYMBOL vmlinux 0x6b27df9d	do_mmap_pgoff
+EXPORT_SYMBOL vmlinux 0x6b2dc060	dump_stack
+EXPORT_SYMBOL vmlinux 0x6b35c50e	kset_unregister
+EXPORT_SYMBOL vmlinux 0x6b4d4459	serio_reconnect
+EXPORT_SYMBOL vmlinux 0x6b4e5a52	radix_tree_lookup_slot
+EXPORT_SYMBOL vmlinux 0x6b60709f	journal_dirty_data
+EXPORT_SYMBOL vmlinux 0x6b8ff8bf	bio_init
+EXPORT_SYMBOL vmlinux 0x6b9b88f3	sleep_on
+EXPORT_SYMBOL vmlinux 0x6ba5a424	call_usermodehelper_freeinfo
+EXPORT_SYMBOL vmlinux 0x6baf7a38	qdisc_destroy
+EXPORT_SYMBOL vmlinux 0x6bc3fbc0	__unregister_chrdev
+EXPORT_SYMBOL vmlinux 0x6bc56c67	radix_tree_next_hole
+EXPORT_SYMBOL vmlinux 0x6bdcfd99	qdisc_class_hash_remove
+EXPORT_SYMBOL vmlinux 0x6c34fc86	skb_seq_read
+EXPORT_SYMBOL vmlinux 0x6c61ce70	num_registered_fb
+EXPORT_SYMBOL vmlinux 0x6c702af7	sysctl_udp_rmem_min
+EXPORT_SYMBOL vmlinux 0x6cb4d9e6	lease_get_mtime
+EXPORT_SYMBOL vmlinux 0x6ce07542	simple_readpage
+EXPORT_SYMBOL vmlinux 0x6d0b77fe	sysctl_data
+EXPORT_SYMBOL vmlinux 0x6d0e3039	vfs_fstatat
+EXPORT_SYMBOL vmlinux 0x6d1ced27	vcc_sklist_lock
+EXPORT_SYMBOL vmlinux 0x6d27ef64	__bitmap_empty
+EXPORT_SYMBOL vmlinux 0x6d294e43	clock_t_to_jiffies
+EXPORT_SYMBOL vmlinux 0x6d334118	__get_user_8
+EXPORT_SYMBOL vmlinux 0x6d340f64	tty_termios_input_baud_rate
+EXPORT_SYMBOL vmlinux 0x6d3eb374	do_SAK
+EXPORT_SYMBOL vmlinux 0x6d418044	del_gendisk
+EXPORT_SYMBOL vmlinux 0x6d4c683d	skb_add_rx_frag
+EXPORT_SYMBOL vmlinux 0x6d5c7b61	lro_flush_pkt
+EXPORT_SYMBOL vmlinux 0x6d5dce8e	dmam_pool_destroy
+EXPORT_SYMBOL vmlinux 0x6d6cbadc	rb_last
+EXPORT_SYMBOL vmlinux 0x6da7d664	tcp_tso_segment
+EXPORT_SYMBOL vmlinux 0x6db38ec0	config_item_init_type_name
+EXPORT_SYMBOL vmlinux 0x6dc0c24b	complete_and_exit
+EXPORT_SYMBOL vmlinux 0x6dcaeb88	per_cpu__kernel_stack
+EXPORT_SYMBOL vmlinux 0x6de6bf83	radix_tree_lookup
+EXPORT_SYMBOL vmlinux 0x6def2db2	half_md4_transform
+EXPORT_SYMBOL vmlinux 0x6e0d5b09	pcix_set_mmrbc
+EXPORT_SYMBOL vmlinux 0x6e23ad94	kernel_sock_ioctl
+EXPORT_SYMBOL vmlinux 0x6e41a616	wireless_send_event
+EXPORT_SYMBOL vmlinux 0x6e525243	thermal_zone_device_update
+EXPORT_SYMBOL vmlinux 0x6e622c9f	dma_pool_destroy
+EXPORT_SYMBOL vmlinux 0x6e720ff2	rtnl_unlock
+EXPORT_SYMBOL vmlinux 0x6e738976	vmalloc_to_page
+EXPORT_SYMBOL vmlinux 0x6e7f4c14	thaw_bdev
+EXPORT_SYMBOL vmlinux 0x6e802324	radix_tree_tag_get
+EXPORT_SYMBOL vmlinux 0x6e814893	deregister_atm_ioctl
+EXPORT_SYMBOL vmlinux 0x6e8f357b	pipe_to_file
+EXPORT_SYMBOL vmlinux 0x6e9dd606	__symbol_put
+EXPORT_SYMBOL vmlinux 0x6eb0fdf3	__cond_resched_lock
+EXPORT_SYMBOL vmlinux 0x6ed4b5b8	skb_recv_datagram
+EXPORT_SYMBOL vmlinux 0x6ee19edf	sk_filter
+EXPORT_SYMBOL vmlinux 0x6ef8d340	vmtruncate
+EXPORT_SYMBOL vmlinux 0x6f17a3cd	jbd2_journal_check_available_features
+EXPORT_SYMBOL vmlinux 0x6f48d9d9	gnet_stats_copy_queue
+EXPORT_SYMBOL vmlinux 0x6f4f6a09	pci_clear_master
+EXPORT_SYMBOL vmlinux 0x6f5dcc4e	w1_unregister_family
+EXPORT_SYMBOL vmlinux 0x6f719bbd	register_key_type
+EXPORT_SYMBOL vmlinux 0x6f8109db	write_one_page
+EXPORT_SYMBOL vmlinux 0x6f8e6346	sock_queue_rcv_skb
+EXPORT_SYMBOL vmlinux 0x6fc4e430	xen_load_gs_index
+EXPORT_SYMBOL vmlinux 0x6fcb87a1	touch_softlockup_watchdog
+EXPORT_SYMBOL vmlinux 0x6ff7b436	tcp_md5_hash_header
+EXPORT_SYMBOL vmlinux 0x6fff393f	time_to_tm
+EXPORT_SYMBOL vmlinux 0x704ef7c7	dma_pool_create
+EXPORT_SYMBOL vmlinux 0x70523a7a	__cond_resched_softirq
+EXPORT_SYMBOL vmlinux 0x70545bf3	d_path
+EXPORT_SYMBOL vmlinux 0x7054a3e4	request_dma
+EXPORT_SYMBOL vmlinux 0x70765d1c	vfs_lstat
+EXPORT_SYMBOL vmlinux 0x7085f248	x86_dma_fallback_dev
+EXPORT_SYMBOL vmlinux 0x7097f456	xfrm_state_register_afinfo
+EXPORT_SYMBOL vmlinux 0x70a907d8	journal_force_commit
+EXPORT_SYMBOL vmlinux 0x70baf30d	dump_trace
+EXPORT_SYMBOL vmlinux 0x70bc17d7	inode_wait
+EXPORT_SYMBOL vmlinux 0x70dea170	netdev_boot_setup_check
+EXPORT_SYMBOL vmlinux 0x70e0d61f	cpu_all_bits
+EXPORT_SYMBOL vmlinux 0x7120dfd7	dm_get_device
+EXPORT_SYMBOL vmlinux 0x71239540	blk_insert_request
+EXPORT_SYMBOL vmlinux 0x71249216	sock_register
+EXPORT_SYMBOL vmlinux 0x7129e5f8	hex_asc
+EXPORT_SYMBOL vmlinux 0x712aa29b	_spin_lock_irqsave
+EXPORT_SYMBOL vmlinux 0x71356fba	remove_wait_queue
+EXPORT_SYMBOL vmlinux 0x7160d352	bio_uncopy_user
+EXPORT_SYMBOL vmlinux 0x7171121c	overflowgid
+EXPORT_SYMBOL vmlinux 0x717893cc	eth_header_cache_update
+EXPORT_SYMBOL vmlinux 0x7197c2d6	uart_get_baud_rate
+EXPORT_SYMBOL vmlinux 0x71a50dbc	register_blkdev
+EXPORT_SYMBOL vmlinux 0x71ac3ac9	loop_register_transfer
+EXPORT_SYMBOL vmlinux 0x71bb41e4	wrmsr_on_cpus
+EXPORT_SYMBOL vmlinux 0x71c2c919	neigh_lookup_nodev
+EXPORT_SYMBOL vmlinux 0x71c38281	stop_tty
+EXPORT_SYMBOL vmlinux 0x71e10bfc	skb_queue_tail
+EXPORT_SYMBOL vmlinux 0x71f6eb38	sg_copy_from_buffer
+EXPORT_SYMBOL vmlinux 0x72100978	remap_vmalloc_range
+EXPORT_SYMBOL vmlinux 0x72389e86	netlink_kernel_release
+EXPORT_SYMBOL vmlinux 0x7242e96d	strnchr
+EXPORT_SYMBOL vmlinux 0x725fb314	log_wait_commit
+EXPORT_SYMBOL vmlinux 0x7264ece5	dm_io_client_resize
+EXPORT_SYMBOL vmlinux 0x7272954b	nf_getsockopt
+EXPORT_SYMBOL vmlinux 0x7289d0f7	close_bdev_exclusive
+EXPORT_SYMBOL vmlinux 0x72926e51	inet_sock_destruct
+EXPORT_SYMBOL vmlinux 0x72a73a04	ppp_register_net_channel
+EXPORT_SYMBOL vmlinux 0x72aa808d	pci_find_device
+EXPORT_SYMBOL vmlinux 0x72b243d4	free_dma
+EXPORT_SYMBOL vmlinux 0x72be4936	pci_request_selected_regions_exclusive
+EXPORT_SYMBOL vmlinux 0x72c3be87	param_set_byte
+EXPORT_SYMBOL vmlinux 0x72c76536	locks_mandatory_area
+EXPORT_SYMBOL vmlinux 0x72ca8c94	skb_dma_unmap
+EXPORT_SYMBOL vmlinux 0x72cdf359	ethtool_op_set_tx_hw_csum
+EXPORT_SYMBOL vmlinux 0x72d9b285	xfrm_unregister_mode
+EXPORT_SYMBOL vmlinux 0x72da97ee	iget_failed
+EXPORT_SYMBOL vmlinux 0x72eac1bd	d_alloc_root
+EXPORT_SYMBOL vmlinux 0x72f0863b	bio_integrity_free
+EXPORT_SYMBOL vmlinux 0x72f1134b	genphy_update_link
+EXPORT_SYMBOL vmlinux 0x72fa5fc9	tcf_em_tree_validate
+EXPORT_SYMBOL vmlinux 0x731ad09d	__sk_mem_reclaim
+EXPORT_SYMBOL vmlinux 0x73374e47	dev_unicast_add
+EXPORT_SYMBOL vmlinux 0x7340d9cf	pci_remove_bus_device
+EXPORT_SYMBOL vmlinux 0x73729025	elv_rb_find
+EXPORT_SYMBOL vmlinux 0x7387e263	complete_request_key
+EXPORT_SYMBOL vmlinux 0x739ee22d	gen_pool_add
+EXPORT_SYMBOL vmlinux 0x73a5df46	mem_map
+EXPORT_SYMBOL vmlinux 0x73a6934d	nf_reinject
+EXPORT_SYMBOL vmlinux 0x73bfbcd4	lease_modify
+EXPORT_SYMBOL vmlinux 0x73c9b49c	block_write_begin
+EXPORT_SYMBOL vmlinux 0x7424f0cd	qdisc_warn_nonwc
+EXPORT_SYMBOL vmlinux 0x7445fefc	jbd2_journal_file_inode
+EXPORT_SYMBOL vmlinux 0x7449c263	create_lookup_pte_addr
+EXPORT_SYMBOL vmlinux 0x744c0c68	param_get_byte
+EXPORT_SYMBOL vmlinux 0x7454a40d	__kill_fasync
+EXPORT_SYMBOL vmlinux 0x745c9f7d	pcix_get_mmrbc
+EXPORT_SYMBOL vmlinux 0x74634f79	mntput_no_expire
+EXPORT_SYMBOL vmlinux 0x74793c5d	splice_from_pipe_begin
+EXPORT_SYMBOL vmlinux 0x7485e15e	unregister_chrdev_region
+EXPORT_SYMBOL vmlinux 0x74871893	bio_add_page
+EXPORT_SYMBOL vmlinux 0x748784e8	I_BDEV
+EXPORT_SYMBOL vmlinux 0x748caf40	down
+EXPORT_SYMBOL vmlinux 0x74954462	timecounter_read
+EXPORT_SYMBOL vmlinux 0x74a652ee	pci_bus_type
+EXPORT_SYMBOL vmlinux 0x74bfc369	__tracepoint_kmem_cache_alloc
+EXPORT_SYMBOL vmlinux 0x74cc1cbe	unregister_cpu_notifier
+EXPORT_SYMBOL vmlinux 0x74ed44c2	input_register_device
+EXPORT_SYMBOL vmlinux 0x75644dab	tcp_v4_conn_request
+EXPORT_SYMBOL vmlinux 0x756e6992	strnicmp
+EXPORT_SYMBOL vmlinux 0x75bdea12	iommu_area_alloc
+EXPORT_SYMBOL vmlinux 0x75d45c2d	hippi_type_trans
+EXPORT_SYMBOL vmlinux 0x75e021d7	call_usermodehelper_setup
+EXPORT_SYMBOL vmlinux 0x75e5bfce	k8_northbridges
+EXPORT_SYMBOL vmlinux 0x760a0f4f	yield
+EXPORT_SYMBOL vmlinux 0x760b437a	unregister_inetaddr_notifier
+EXPORT_SYMBOL vmlinux 0x7610936a	bio_integrity_advance
+EXPORT_SYMBOL vmlinux 0x76253a37	mutex_lock_killable
+EXPORT_SYMBOL vmlinux 0x764bd77c	request_resource
+EXPORT_SYMBOL vmlinux 0x764f3c92	phy_start_interrupts
+EXPORT_SYMBOL vmlinux 0x767ddb02	set_memory_wc
+EXPORT_SYMBOL vmlinux 0x768f6ea3	make_EII_client
+EXPORT_SYMBOL vmlinux 0x76bf656d	__bitmap_shift_left
+EXPORT_SYMBOL vmlinux 0x76c4b990	block_page_mkwrite
+EXPORT_SYMBOL vmlinux 0x76d3cd60	laptop_mode
+EXPORT_SYMBOL vmlinux 0x76f35a32	sockfd_lookup
+EXPORT_SYMBOL vmlinux 0x76f3f8a5	num_k8_northbridges
+EXPORT_SYMBOL vmlinux 0x771112aa	vfs_writev
+EXPORT_SYMBOL vmlinux 0x77275779	__mutex_init
+EXPORT_SYMBOL vmlinux 0x7728c1e8	devm_request_threaded_irq
+EXPORT_SYMBOL vmlinux 0x77322311	blk_alloc_queue_node
+EXPORT_SYMBOL vmlinux 0x773a9c94	blk_iopoll_enabled
+EXPORT_SYMBOL vmlinux 0x77a108df	_write_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x77cde088	dev_set_mtu
+EXPORT_SYMBOL vmlinux 0x77cfcfde	__tracepoint_kmalloc_node
+EXPORT_SYMBOL vmlinux 0x77ecac9f	zlib_inflateEnd
+EXPORT_SYMBOL vmlinux 0x77ed4829	journal_dirty_metadata
+EXPORT_SYMBOL vmlinux 0x77fa5d1f	ns_to_timespec
+EXPORT_SYMBOL vmlinux 0x780b9288	uart_resume_port
+EXPORT_SYMBOL vmlinux 0x7813c3c9	inet_bind
+EXPORT_SYMBOL vmlinux 0x7836c045	sock_common_getsockopt
+EXPORT_SYMBOL vmlinux 0x784c85a5	jbd2_journal_get_undo_access
+EXPORT_SYMBOL vmlinux 0x785148a3	idr_destroy
+EXPORT_SYMBOL vmlinux 0x786e0fe5	simple_rename
+EXPORT_SYMBOL vmlinux 0x78775f61	blkdev_issue_discard
+EXPORT_SYMBOL vmlinux 0x787a7d05	mb_cache_entry_free
+EXPORT_SYMBOL vmlinux 0x7883f3f1	skb_copy_and_csum_dev
+EXPORT_SYMBOL vmlinux 0x7891282c	do_sync_write
+EXPORT_SYMBOL vmlinux 0x78a484c9	_read_unlock_irqrestore
+EXPORT_SYMBOL vmlinux 0x78b22a8e	ip_queue_xmit
+EXPORT_SYMBOL vmlinux 0x78ccddfc	HYPERVISOR_shared_info
+EXPORT_SYMBOL vmlinux 0x78df6bd7	no_pci_devices
+EXPORT_SYMBOL vmlinux 0x78e80b3f	alloc_hippi_dev
+EXPORT_SYMBOL vmlinux 0x79344b2f	block_prepare_write
+EXPORT_SYMBOL vmlinux 0x7997b213	d_add_ci
+EXPORT_SYMBOL vmlinux 0x79aa04a2	get_random_bytes
+EXPORT_SYMBOL vmlinux 0x79ad224b	tasklet_kill
+EXPORT_SYMBOL vmlinux 0x79bfd9fd	read_dev_sector
+EXPORT_SYMBOL vmlinux 0x79c204e6	__destroy_inode
+EXPORT_SYMBOL vmlinux 0x79d1e1fa	dev_alloc_name
+EXPORT_SYMBOL vmlinux 0x79ee774d	sock_no_poll
+EXPORT_SYMBOL vmlinux 0x7a052d0f	init_task
+EXPORT_SYMBOL vmlinux 0x7a0d0874	skb_checksum_setup
+EXPORT_SYMBOL vmlinux 0x7a2a837d	strict_strtol
+EXPORT_SYMBOL vmlinux 0x7a4497db	kzfree
+EXPORT_SYMBOL vmlinux 0x7a49179e	napi_frags_finish
+EXPORT_SYMBOL vmlinux 0x7a4bbcb3	filp_open
+EXPORT_SYMBOL vmlinux 0x7a57f1e4	tcp_initialize_rcv_mss
+EXPORT_SYMBOL vmlinux 0x7a848702	_read_lock_irqsave
+EXPORT_SYMBOL vmlinux 0x7ac5d25a	tcp_md5_hash_key
+EXPORT_SYMBOL vmlinux 0x7accab1c	skb_copy_bits
+EXPORT_SYMBOL vmlinux 0x7ad74231	inet_add_protocol
+EXPORT_SYMBOL vmlinux 0x7ae73de1	alloc_pages_exact
+EXPORT_SYMBOL vmlinux 0x7aec9089	clear_user
+EXPORT_SYMBOL vmlinux 0x7af5e71e	inode_set_bytes
+EXPORT_SYMBOL vmlinux 0x7b3fa677	pcim_iomap_regions_request_all
+EXPORT_SYMBOL vmlinux 0x7b4c992a	bdget
+EXPORT_SYMBOL vmlinux 0x7b52a859	wrmsr_safe_on_cpu
+EXPORT_SYMBOL vmlinux 0x7b568343	dev_get_drvdata
+EXPORT_SYMBOL vmlinux 0x7b8f4c40	key_create_or_update
+EXPORT_SYMBOL vmlinux 0x7bafaf75	inode_claim_rsv_space
+EXPORT_SYMBOL vmlinux 0x7bb0eb2e	journal_start_commit
+EXPORT_SYMBOL vmlinux 0x7befc80d	console_start
+EXPORT_SYMBOL vmlinux 0x7bff3be7	iov_iter_advance
+EXPORT_SYMBOL vmlinux 0x7c1307ad	generic_delete_inode
+EXPORT_SYMBOL vmlinux 0x7c1cde82	proc_dointvec_ms_jiffies
+EXPORT_SYMBOL vmlinux 0x7c32f5ab	bdev_stack_limits
+EXPORT_SYMBOL vmlinux 0x7c346ea5	pci_bus_write_config_byte
+EXPORT_SYMBOL vmlinux 0x7c4c8c80	elv_add_request
+EXPORT_SYMBOL vmlinux 0x7c60d66e	getname
+EXPORT_SYMBOL vmlinux 0x7c61340c	__release_region
+EXPORT_SYMBOL vmlinux 0x7c6ecd6a	journal_errno
+EXPORT_SYMBOL vmlinux 0x7c904ded	unregister_module_notifier
+EXPORT_SYMBOL vmlinux 0x7c9214e8	km_policy_expired
+EXPORT_SYMBOL vmlinux 0x7ca25c4b	generic_shutdown_super
+EXPORT_SYMBOL vmlinux 0x7ca66879	key_task_permission
+EXPORT_SYMBOL vmlinux 0x7cb1ae69	cpu_down
+EXPORT_SYMBOL vmlinux 0x7cc297a0	sock_i_ino
+EXPORT_SYMBOL vmlinux 0x7cd7b0da	put_mnt_ns
+EXPORT_SYMBOL vmlinux 0x7cee796d	xfrm_state_unregister_afinfo
+EXPORT_SYMBOL vmlinux 0x7d11c268	jiffies
+EXPORT_SYMBOL vmlinux 0x7d2d7e78	__find_get_block
+EXPORT_SYMBOL vmlinux 0x7d4b99cc	tcp_close
+EXPORT_SYMBOL vmlinux 0x7d56cf1d	journal_check_available_features
+EXPORT_SYMBOL vmlinux 0x7d5d005c	arp_broken_ops
+EXPORT_SYMBOL vmlinux 0x7d6bb587	cpu_online_mask
+EXPORT_SYMBOL vmlinux 0x7d74a09a	fb_show_logo
+EXPORT_SYMBOL vmlinux 0x7d776f9f	blk_queue_bounce
+EXPORT_SYMBOL vmlinux 0x7dcb15b4	wait_for_key_construction
+EXPORT_SYMBOL vmlinux 0x7dceceac	capable
+EXPORT_SYMBOL vmlinux 0x7dcfecdb	bio_alloc
+EXPORT_SYMBOL vmlinux 0x7de4352d	nf_hook_slow
+EXPORT_SYMBOL vmlinux 0x7e1b377d	bio_integrity_add_page
+EXPORT_SYMBOL vmlinux 0x7e1eb581	mdiobus_scan
+EXPORT_SYMBOL vmlinux 0x7e27e07e	serio_interrupt
+EXPORT_SYMBOL vmlinux 0x7e403d13	elevator_exit
+EXPORT_SYMBOL vmlinux 0x7e6069d3	create_proc_entry
+EXPORT_SYMBOL vmlinux 0x7e9ebb05	kernel_thread
+EXPORT_SYMBOL vmlinux 0x7ec9bfbc	strncpy
+EXPORT_SYMBOL vmlinux 0x7ecd10e2	set_security_override_from_ctx
+EXPORT_SYMBOL vmlinux 0x7ee91c1d	_spin_trylock
+EXPORT_SYMBOL vmlinux 0x7f24de73	jiffies_to_usecs
+EXPORT_SYMBOL vmlinux 0x7f4b911c	__dst_free
+EXPORT_SYMBOL vmlinux 0x7f94957a	pci_bus_set_ops
+EXPORT_SYMBOL vmlinux 0x7f9948aa	sock_no_listen
+EXPORT_SYMBOL vmlinux 0x7fa25e8b	pci_bus_write_config_word
+EXPORT_SYMBOL vmlinux 0x7fe96816	bio_integrity_alloc
+EXPORT_SYMBOL vmlinux 0x7febb457	simple_lookup
+EXPORT_SYMBOL vmlinux 0x800d3453	mnt_unpin
+EXPORT_SYMBOL vmlinux 0x8058098a	netif_carrier_off
+EXPORT_SYMBOL vmlinux 0x8063d071	serial8250_register_port
+EXPORT_SYMBOL vmlinux 0x80914a76	input_register_handler
+EXPORT_SYMBOL vmlinux 0x80d5cff0	per_cpu__irq_regs
+EXPORT_SYMBOL vmlinux 0x80dec536	xfrm_init_state
+EXPORT_SYMBOL vmlinux 0x80e807c3	mark_buffer_dirty_inode
+EXPORT_SYMBOL vmlinux 0x8142f48f	kobject_add
+EXPORT_SYMBOL vmlinux 0x814b71af	generic_cont_expand_simple
+EXPORT_SYMBOL vmlinux 0x814bc556	sock_map_fd
+EXPORT_SYMBOL vmlinux 0x815b5dd4	match_octal
+EXPORT_SYMBOL vmlinux 0x815f2897	empty_zero_page
+EXPORT_SYMBOL vmlinux 0x818d3373	xfrm_policy_bysel_ctx
+EXPORT_SYMBOL vmlinux 0x819429ed	vfs_statfs
+EXPORT_SYMBOL vmlinux 0x81f71b52	unlock_buffer
+EXPORT_SYMBOL vmlinux 0x820d225f	print_mac
+EXPORT_SYMBOL vmlinux 0x820fc63c	vfsmount_lock
+EXPORT_SYMBOL vmlinux 0x8214a343	pskb_expand_head
+EXPORT_SYMBOL vmlinux 0x821fc0e9	nf_log_unregister
+EXPORT_SYMBOL vmlinux 0x823128b2	find_lock_page
+EXPORT_SYMBOL vmlinux 0x8243c129	journal_create
+EXPORT_SYMBOL vmlinux 0x8251bcc3	bitmap_release_region
+EXPORT_SYMBOL vmlinux 0x82692209	kref_set
+EXPORT_SYMBOL vmlinux 0x8288caa5	flush_signals
+EXPORT_SYMBOL vmlinux 0x828ca9a5	generic_error_remove_page
+EXPORT_SYMBOL vmlinux 0x8295f247	uart_unregister_driver
+EXPORT_SYMBOL vmlinux 0x82acfb70	blk_iopoll_sched
+EXPORT_SYMBOL vmlinux 0x82b7be49	sk_stream_error
+EXPORT_SYMBOL vmlinux 0x82c4c919	sk_receive_skb
+EXPORT_SYMBOL vmlinux 0x82d9888b	fddi_type_trans
+EXPORT_SYMBOL vmlinux 0x82e10eb6	mdiobus_write
+EXPORT_SYMBOL vmlinux 0x82e9c083	csum_partial_copy_fromiovecend
+EXPORT_SYMBOL vmlinux 0x82edc07c	add_disk
+EXPORT_SYMBOL vmlinux 0x82f3c96e	proc_net_netfilter
+EXPORT_SYMBOL vmlinux 0x830e547b	ioremap_prot
+EXPORT_SYMBOL vmlinux 0x83112efd	jbd2_journal_init_inode
+EXPORT_SYMBOL vmlinux 0x8317e20a	completion_done
+EXPORT_SYMBOL vmlinux 0x834675be	pci_find_capability
+EXPORT_SYMBOL vmlinux 0x836be0dc	__blk_end_request
+EXPORT_SYMBOL vmlinux 0x838a61b8	sk_stream_wait_memory
+EXPORT_SYMBOL vmlinux 0x839f52ef	sync_mapping_buffers
+EXPORT_SYMBOL vmlinux 0x83a476ce	bitmap_scnlistprintf
+EXPORT_SYMBOL vmlinux 0x83c1aa3b	input_get_keycode
+EXPORT_SYMBOL vmlinux 0x83c43dc1	posix_acl_chmod_masq
+EXPORT_SYMBOL vmlinux 0x83db435a	xfrm_input
+EXPORT_SYMBOL vmlinux 0x83eaa946	unregister_framebuffer
+EXPORT_SYMBOL vmlinux 0x84053636	sync_inodes_sb
+EXPORT_SYMBOL vmlinux 0x8429da81	mb_cache_entry_release
+EXPORT_SYMBOL vmlinux 0x844284a6	tcp_read_sock
+EXPORT_SYMBOL vmlinux 0x846626e9	blk_queue_resize_tags
+EXPORT_SYMBOL vmlinux 0x8494caf9	bio_copy_user
+EXPORT_SYMBOL vmlinux 0x84b416fa	ip_route_me_harder
+EXPORT_SYMBOL vmlinux 0x84b50d11	backlight_force_update
+EXPORT_SYMBOL vmlinux 0x84c4c9e5	dm_table_event
+EXPORT_SYMBOL vmlinux 0x84cc2f72	do_splice_from
+EXPORT_SYMBOL vmlinux 0x84ccfef4	tcf_action_exec
+EXPORT_SYMBOL vmlinux 0x84d488b9	blk_execute_rq
+EXPORT_SYMBOL vmlinux 0x84e4f65a	bio_clone
+EXPORT_SYMBOL vmlinux 0x852b20a8	devm_ioremap
+EXPORT_SYMBOL vmlinux 0x8539e742	phy_sanitize_settings
+EXPORT_SYMBOL vmlinux 0x854f5cd8	__skb_checksum_complete_head
+EXPORT_SYMBOL vmlinux 0x85670f1d	rtnl_is_locked
+EXPORT_SYMBOL vmlinux 0x85abc85f	strncmp
+EXPORT_SYMBOL vmlinux 0x85aefafa	sk_run_filter
+EXPORT_SYMBOL vmlinux 0x85bfcbdf	register_netdevice
+EXPORT_SYMBOL vmlinux 0x85df9b6c	strsep
+EXPORT_SYMBOL vmlinux 0x861de984	pfifo_qdisc_ops
+EXPORT_SYMBOL vmlinux 0x8631f188	radix_tree_tag_set
+EXPORT_SYMBOL vmlinux 0x865d0818	phy_device_create
+EXPORT_SYMBOL vmlinux 0x865d6db9	get_sb_nodev
+EXPORT_SYMBOL vmlinux 0x867e015a	clear_bdi_congested
+EXPORT_SYMBOL vmlinux 0x868acba5	get_options
+EXPORT_SYMBOL vmlinux 0x86beb414	ethtool_op_set_sg
+EXPORT_SYMBOL vmlinux 0x86c48cf9	user_revoke
+EXPORT_SYMBOL vmlinux 0x86c7146d	vfs_fstat
+EXPORT_SYMBOL vmlinux 0x86ee31f5	blk_queue_max_discard_sectors
+EXPORT_SYMBOL vmlinux 0x86f14ab6	dev_set_mac_address
+EXPORT_SYMBOL vmlinux 0x86fb9b05	bitmap_parse_user
+EXPORT_SYMBOL vmlinux 0x87127137	kill_anon_super
+EXPORT_SYMBOL vmlinux 0x871c0a7e	fiemap_check_flags
+EXPORT_SYMBOL vmlinux 0x871e5d37	dev_addr_del_multiple
+EXPORT_SYMBOL vmlinux 0x87247b86	sock_no_bind
+EXPORT_SYMBOL vmlinux 0x8733e9a3	sleep_on_timeout
+EXPORT_SYMBOL vmlinux 0x875777b9	inet_csk_destroy_sock
+EXPORT_SYMBOL vmlinux 0x87734b2b	tty_shutdown
+EXPORT_SYMBOL vmlinux 0x8780a283	tty_kref_put
+EXPORT_SYMBOL vmlinux 0x878ab3ce	sysctl_tcp_adv_win_scale
+EXPORT_SYMBOL vmlinux 0x87aaddf8	wrmsr_safe_regs_on_cpu
+EXPORT_SYMBOL vmlinux 0x87b6c553	locks_copy_lock
+EXPORT_SYMBOL vmlinux 0x8802e236	config_item_put
+EXPORT_SYMBOL vmlinux 0x881039d0	zlib_inflate
+EXPORT_SYMBOL vmlinux 0x883cfc15	rtnl_unicast
+EXPORT_SYMBOL vmlinux 0x88444c14	cdrom_mode_select
+EXPORT_SYMBOL vmlinux 0x8851ec27	pci_enable_device_mem
+EXPORT_SYMBOL vmlinux 0x8863f7ee	journal_get_undo_access
+EXPORT_SYMBOL vmlinux 0x886aa274	posix_acl_create_masq
+EXPORT_SYMBOL vmlinux 0x88e18643	journal_revoke
+EXPORT_SYMBOL vmlinux 0x89195dc3	sonet_copy_stats
+EXPORT_SYMBOL vmlinux 0x892b26a0	set_memory_nx
+EXPORT_SYMBOL vmlinux 0x8973380f	call_usermodehelper_pipe
+EXPORT_SYMBOL vmlinux 0x897473df	mktime
+EXPORT_SYMBOL vmlinux 0x89949018	down_timeout
+EXPORT_SYMBOL vmlinux 0x89b08946	cdev_add
+EXPORT_SYMBOL vmlinux 0x89cbd59c	skb_dequeue
+EXPORT_SYMBOL vmlinux 0x89d5538d	fb_pad_aligned_buffer
+EXPORT_SYMBOL vmlinux 0x89d66811	build_ehash_secret
+EXPORT_SYMBOL vmlinux 0x89edc06c	serio_open
+EXPORT_SYMBOL vmlinux 0x8a033c23	blk_rq_init
+EXPORT_SYMBOL vmlinux 0x8a1203a9	kref_get
+EXPORT_SYMBOL vmlinux 0x8a3eabf0	__wait_on_bit
+EXPORT_SYMBOL vmlinux 0x8a4855be	page_zero_new_buffers
+EXPORT_SYMBOL vmlinux 0x8a65aa5c	cancel_dirty_page
+EXPORT_SYMBOL vmlinux 0x8a6f6594	dev_get_by_index
+EXPORT_SYMBOL vmlinux 0x8a79c912	vfs_set_dqinfo
+EXPORT_SYMBOL vmlinux 0x8a7d1c31	high_memory
+EXPORT_SYMBOL vmlinux 0x8a82ca3e	seq_open
+EXPORT_SYMBOL vmlinux 0x8a8d4dba	nla_put_nohdr
+EXPORT_SYMBOL vmlinux 0x8a99a016	mempool_free_slab
+EXPORT_SYMBOL vmlinux 0x8ac40297	iommu_area_free
+EXPORT_SYMBOL vmlinux 0x8ad0477d	tcp_create_openreq_child
+EXPORT_SYMBOL vmlinux 0x8b18731b	pci_enable_bridges
+EXPORT_SYMBOL vmlinux 0x8b35e873	sg_last
+EXPORT_SYMBOL vmlinux 0x8b618d08	overflowuid
+EXPORT_SYMBOL vmlinux 0x8b779b62	inet_frag_destroy
+EXPORT_SYMBOL vmlinux 0x8b7fe311	kmemdup
+EXPORT_SYMBOL vmlinux 0x8b812ef4	inet_dgram_connect
+EXPORT_SYMBOL vmlinux 0x8b922c0f	__strnlen_user
+EXPORT_SYMBOL vmlinux 0x8ba2c358	bdi_destroy
+EXPORT_SYMBOL vmlinux 0x8ba51a57	ether_setup
+EXPORT_SYMBOL vmlinux 0x8bc8c74a	__bforget
+EXPORT_SYMBOL vmlinux 0x8bd313b8	__tracepoint_kfree
+EXPORT_SYMBOL vmlinux 0x8bd5b603	param_get_long
+EXPORT_SYMBOL vmlinux 0x8bfe41f9	do_truncate
+EXPORT_SYMBOL vmlinux 0x8c183cbe	iowrite16
+EXPORT_SYMBOL vmlinux 0x8c2e9dc3	__devm_request_region
+EXPORT_SYMBOL vmlinux 0x8c537c45	posix_acl_from_mode
+EXPORT_SYMBOL vmlinux 0x8c7f044e	mod_zone_page_state
+EXPORT_SYMBOL vmlinux 0x8c8fca2d	fb_set_cmap
+EXPORT_SYMBOL vmlinux 0x8cc79cab	iowrite16_rep
+EXPORT_SYMBOL vmlinux 0x8ce5d159	invalidate_inode_buffers
+EXPORT_SYMBOL vmlinux 0x8cf829a6	iget5_locked
+EXPORT_SYMBOL vmlinux 0x8d0159ed	deny_write_access
+EXPORT_SYMBOL vmlinux 0x8d090a87	netdev_bonding_change
+EXPORT_SYMBOL vmlinux 0x8d0b777d	tcf_exts_dump
+EXPORT_SYMBOL vmlinux 0x8d3894f2	_ctype
+EXPORT_SYMBOL vmlinux 0x8d551bef	sysctl_tcp_rmem
+EXPORT_SYMBOL vmlinux 0x8db1193b	netif_carrier_on
+EXPORT_SYMBOL vmlinux 0x8dc9d5a3	napi_gro_flush
+EXPORT_SYMBOL vmlinux 0x8dca832f	__percpu_counter_sum
+EXPORT_SYMBOL vmlinux 0x8dfd9e50	compat_tcp_getsockopt
+EXPORT_SYMBOL vmlinux 0x8e0637ba	i8253_lock
+EXPORT_SYMBOL vmlinux 0x8e0b7743	ipv6_ext_hdr
+EXPORT_SYMBOL vmlinux 0x8e27d66b	ipv4_specific
+EXPORT_SYMBOL vmlinux 0x8e36e19f	unregister_msi_get_owner
+EXPORT_SYMBOL vmlinux 0x8e3c9cc3	vprintk
+EXPORT_SYMBOL vmlinux 0x8e596f9e	journal_lock_updates
+EXPORT_SYMBOL vmlinux 0x8e763ae1	send_remote_softirq
+EXPORT_SYMBOL vmlinux 0x8eb92539	blk_recount_segments
+EXPORT_SYMBOL vmlinux 0x8ec97a00	swiotlb_dma_supported
+EXPORT_SYMBOL vmlinux 0x8ee4fd3b	igrab
+EXPORT_SYMBOL vmlinux 0x8ee69235	timeval_to_jiffies
+EXPORT_SYMBOL vmlinux 0x8ee9b93b	__register_binfmt
+EXPORT_SYMBOL vmlinux 0x8f08ca25	blk_cleanup_queue
+EXPORT_SYMBOL vmlinux 0x8f12c7f0	tcp_setsockopt
+EXPORT_SYMBOL vmlinux 0x8f182bcf	inet_select_addr
+EXPORT_SYMBOL vmlinux 0x8f19f631	generic_readlink
+EXPORT_SYMBOL vmlinux 0x8f2703b7	wbinvd_on_all_cpus
+EXPORT_SYMBOL vmlinux 0x8f30de3d	keyring_search
+EXPORT_SYMBOL vmlinux 0x8f3a3ab2	kthread_stop
+EXPORT_SYMBOL vmlinux 0x8f48679a	rb_prev
+EXPORT_SYMBOL vmlinux 0x8f4b6d10	phy_scan_fixups
+EXPORT_SYMBOL vmlinux 0x8f641c72	cdrom_release
+EXPORT_SYMBOL vmlinux 0x8f6b7950	set_irq_data
+EXPORT_SYMBOL vmlinux 0x8f9c199c	__get_user_2
+EXPORT_SYMBOL vmlinux 0x8fb24a78	lro_flush_all
+EXPORT_SYMBOL vmlinux 0x8fb28643	serio_unregister_child_port
+EXPORT_SYMBOL vmlinux 0x8fbaa384	tcf_destroy_chain
+EXPORT_SYMBOL vmlinux 0x8fdbcea0	shrink_dcache_sb
+EXPORT_SYMBOL vmlinux 0x8fe176e4	pci_release_region
+EXPORT_SYMBOL vmlinux 0x8fe8ad1a	rwsem_downgrade_wake
+EXPORT_SYMBOL vmlinux 0x8ff2d785	blk_queue_dma_alignment
+EXPORT_SYMBOL vmlinux 0x90035333	secure_tcpv6_sequence_number
+EXPORT_SYMBOL vmlinux 0x900b533d	__task_pid_nr_ns
+EXPORT_SYMBOL vmlinux 0x900fa887	textsearch_find_continuous
+EXPORT_SYMBOL vmlinux 0x902bf0f3	pskb_copy
+EXPORT_SYMBOL vmlinux 0x903dcfe2	sg_miter_stop
+EXPORT_SYMBOL vmlinux 0x90425514	vga_tryget
+EXPORT_SYMBOL vmlinux 0x9062447b	dmam_alloc_coherent
+EXPORT_SYMBOL vmlinux 0x907a4855	dev_queue_xmit
+EXPORT_SYMBOL vmlinux 0x90e3e98d	is_bad_inode
+EXPORT_SYMBOL vmlinux 0x90e7a9ca	dev_kfree_skb_irq
+EXPORT_SYMBOL vmlinux 0x91255fab	unmap_underlying_metadata
+EXPORT_SYMBOL vmlinux 0x9128f8fd	request_firmware_nowait
+EXPORT_SYMBOL vmlinux 0x913b6532	blk_queue_max_hw_segments
+EXPORT_SYMBOL vmlinux 0x91481982	__ratelimit
+EXPORT_SYMBOL vmlinux 0x91607d95	set_memory_wb
+EXPORT_SYMBOL vmlinux 0x9171fbe2	backlight_device_register
+EXPORT_SYMBOL vmlinux 0x91766c09	param_get_ulong
+EXPORT_SYMBOL vmlinux 0x9183c29e	iw_handler_get_spy
+EXPORT_SYMBOL vmlinux 0x91854e60	jbd2_journal_blocks_per_page
+EXPORT_SYMBOL vmlinux 0x918c506f	udp_flush_pending_frames
+EXPORT_SYMBOL vmlinux 0x918d7ffd	slow_work_register_user
+EXPORT_SYMBOL vmlinux 0x919dc126	drop_super
+EXPORT_SYMBOL vmlinux 0x91a1ef83	phy_stop
+EXPORT_SYMBOL vmlinux 0x91a4cfaf	pci_clear_mwi
+EXPORT_SYMBOL vmlinux 0x91b1adda	tcp_rcv_state_process
+EXPORT_SYMBOL vmlinux 0x91bc5878	pci_set_dma_max_seg_size
+EXPORT_SYMBOL vmlinux 0x91be1324	elv_rb_former_request
+EXPORT_SYMBOL vmlinux 0x91cb3e91	vfs_readdir
+EXPORT_SYMBOL vmlinux 0x91eeaec4	call_usermodehelper_exec
+EXPORT_SYMBOL vmlinux 0x9211cbec	sock_init_data
+EXPORT_SYMBOL vmlinux 0x9214ed8a	param_get_bool
+EXPORT_SYMBOL vmlinux 0x92392cd9	iov_shorten
+EXPORT_SYMBOL vmlinux 0x923a5990	napi_gro_frags
+EXPORT_SYMBOL vmlinux 0x923b3027	simple_empty
+EXPORT_SYMBOL vmlinux 0x9266259a	skb_copy_and_csum_bits
+EXPORT_SYMBOL vmlinux 0x927e989f	gen_pool_alloc
+EXPORT_SYMBOL vmlinux 0x92875a03	pcim_iomap
+EXPORT_SYMBOL vmlinux 0x92d47bb2	insert_inode_locked4
+EXPORT_SYMBOL vmlinux 0x92df8474	cdev_init
+EXPORT_SYMBOL vmlinux 0x92e9397e	xen_halt
+EXPORT_SYMBOL vmlinux 0x92ea4ae4	crc32_le
+EXPORT_SYMBOL vmlinux 0x930f14e2	netdev_set_master
+EXPORT_SYMBOL vmlinux 0x932acffd	unmap_mapping_range
+EXPORT_SYMBOL vmlinux 0x93349c63	tcf_hash_search
+EXPORT_SYMBOL vmlinux 0x933c66ba	config_item_get
+EXPORT_SYMBOL vmlinux 0x9385667d	down_read_trylock
+EXPORT_SYMBOL vmlinux 0x93a6e0b2	io_schedule
+EXPORT_SYMBOL vmlinux 0x93acd4ff	__free_pages
+EXPORT_SYMBOL vmlinux 0x93af1b90	nf_log_packet
+EXPORT_SYMBOL vmlinux 0x93bd6922	qdisc_watchdog_schedule
+EXPORT_SYMBOL vmlinux 0x93cbd1ec	_spin_lock_bh
+EXPORT_SYMBOL vmlinux 0x93d2165a	filemap_fdatawrite_range
+EXPORT_SYMBOL vmlinux 0x93d454dc	thermal_cooling_device_register
+EXPORT_SYMBOL vmlinux 0x93f40620	pcie_set_readrq
+EXPORT_SYMBOL vmlinux 0x93fca811	__get_free_pages
+EXPORT_SYMBOL vmlinux 0x940bdde7	sock_no_connect
+EXPORT_SYMBOL vmlinux 0x9421df88	mapping_tagged
+EXPORT_SYMBOL vmlinux 0x943e868f	ida_get_new
+EXPORT_SYMBOL vmlinux 0x944832d6	ftrace_print_symbols_seq
+EXPORT_SYMBOL vmlinux 0x9454cd8a	dquot_alloc
+EXPORT_SYMBOL vmlinux 0x945bc6a7	copy_from_user
+EXPORT_SYMBOL vmlinux 0x9480455f	dev_close
+EXPORT_SYMBOL vmlinux 0x94847b23	nf_ct_destroy
+EXPORT_SYMBOL vmlinux 0x94919d70	tc_classify_compat
+EXPORT_SYMBOL vmlinux 0x94961283	vunmap
+EXPORT_SYMBOL vmlinux 0x94a33438	atm_proc_root
+EXPORT_SYMBOL vmlinux 0x94b0d6a8	blk_requeue_request
+EXPORT_SYMBOL vmlinux 0x94dc9a49	pci_read_vpd
+EXPORT_SYMBOL vmlinux 0x94dd1d20	pci_find_next_bus
+EXPORT_SYMBOL vmlinux 0x94e4aad6	swiotlb_unmap_sg
+EXPORT_SYMBOL vmlinux 0x9526097d	__tcp_get_md5sig_pool
+EXPORT_SYMBOL vmlinux 0x954488a4	syncookie_secret
+EXPORT_SYMBOL vmlinux 0x954cbb26	vsprintf
+EXPORT_SYMBOL vmlinux 0x9579ce66	dev_driver_string
+EXPORT_SYMBOL vmlinux 0x95cb23c6	dquot_reserve_space
+EXPORT_SYMBOL vmlinux 0x95ceb864	key_update
+EXPORT_SYMBOL vmlinux 0x95e079cf	elevator_init
+EXPORT_SYMBOL vmlinux 0x95eceb19	pci_save_state
+EXPORT_SYMBOL vmlinux 0x95edf52a	jbd2_journal_abort
+EXPORT_SYMBOL vmlinux 0x961419c9	dm_table_unplug_all
+EXPORT_SYMBOL vmlinux 0x9629486a	per_cpu__cpu_number
+EXPORT_SYMBOL vmlinux 0x96331600	dev_mc_add
+EXPORT_SYMBOL vmlinux 0x963e309d	xen_io_delay
+EXPORT_SYMBOL vmlinux 0x964530c7	names_cachep
+EXPORT_SYMBOL vmlinux 0x964f7d99	xfrm_state_lookup
+EXPORT_SYMBOL vmlinux 0x96603858	skb_tx_hash
+EXPORT_SYMBOL vmlinux 0x96c61d44	backlight_device_unregister
+EXPORT_SYMBOL vmlinux 0x9710c39f	blk_stack_limits
+EXPORT_SYMBOL vmlinux 0x9718d1c5	ppp_input
+EXPORT_SYMBOL vmlinux 0x973873ab	_spin_lock
+EXPORT_SYMBOL vmlinux 0x9754ec10	radix_tree_preload
+EXPORT_SYMBOL vmlinux 0x975f130f	vm_map_ram
+EXPORT_SYMBOL vmlinux 0x978abc05	skb_dma_map
+EXPORT_SYMBOL vmlinux 0x979c61c9	notify_change
+EXPORT_SYMBOL vmlinux 0x97b4ec41	__brelse
+EXPORT_SYMBOL vmlinux 0x97bd9a77	sock_kmalloc
+EXPORT_SYMBOL vmlinux 0x97c164e6	directly_mappable_cdev_bdi
+EXPORT_SYMBOL vmlinux 0x97e96f34	vfs_llseek
+EXPORT_SYMBOL vmlinux 0x981bafeb	try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0x9821c898	grab_cache_page_nowait
+EXPORT_SYMBOL vmlinux 0x983f67da	sb_min_blocksize
+EXPORT_SYMBOL vmlinux 0x98612071	register_sysctl_paths
+EXPORT_SYMBOL vmlinux 0x986e6135	fb_pad_unaligned_buffer
+EXPORT_SYMBOL vmlinux 0x987a1caa	phy_enable_interrupts
+EXPORT_SYMBOL vmlinux 0x988ed85d	set_memory_x
+EXPORT_SYMBOL vmlinux 0x989492e6	textsearch_register
+EXPORT_SYMBOL vmlinux 0x98a207ff	contig_page_data
+EXPORT_SYMBOL vmlinux 0x98a8c45f	generic_file_llseek_unlocked
+EXPORT_SYMBOL vmlinux 0x98ba3b81	tcf_hash_new_index
+EXPORT_SYMBOL vmlinux 0x99000dcb	get_sb_bdev
+EXPORT_SYMBOL vmlinux 0x994269e7	journal_set_features
+EXPORT_SYMBOL vmlinux 0x9947d764	read_cache_pages
+EXPORT_SYMBOL vmlinux 0x994bf3af	search_binary_handler
+EXPORT_SYMBOL vmlinux 0x99921c53	__locks_copy_lock
+EXPORT_SYMBOL vmlinux 0x999284b4	blk_integrity_compare
+EXPORT_SYMBOL vmlinux 0x9994c0ca	ps2_is_keyboard_id
+EXPORT_SYMBOL vmlinux 0x999e8297	vfree
+EXPORT_SYMBOL vmlinux 0x99a6b46b	vfs_mkdir
+EXPORT_SYMBOL vmlinux 0x99bfbe39	get_unused_fd
+EXPORT_SYMBOL vmlinux 0x99c7a8b8	jbd2_dev_to_name
+EXPORT_SYMBOL vmlinux 0x99cdc86b	sysctl_tcp_reordering
+EXPORT_SYMBOL vmlinux 0x99ea12ce	panic_blink
+EXPORT_SYMBOL vmlinux 0x99edb4d3	get_phy_id
+EXPORT_SYMBOL vmlinux 0x9a0f25a0	blk_unplug
+EXPORT_SYMBOL vmlinux 0x9a1dfd65	strpbrk
+EXPORT_SYMBOL vmlinux 0x9a305cfe	arp_find
+EXPORT_SYMBOL vmlinux 0x9a30d3e0	mdiobus_free
+EXPORT_SYMBOL vmlinux 0x9a3c8632	dm_table_get
+EXPORT_SYMBOL vmlinux 0x9a9985be	percpu_counter_destroy
+EXPORT_SYMBOL vmlinux 0x9aa32630	machine_halt
+EXPORT_SYMBOL vmlinux 0x9aabc564	crc16
+EXPORT_SYMBOL vmlinux 0x9ab3dcba	kill_block_super
+EXPORT_SYMBOL vmlinux 0x9adb4bce	ps2_sendbyte
+EXPORT_SYMBOL vmlinux 0x9b283a81	xfrm_alloc_spi
+EXPORT_SYMBOL vmlinux 0x9b31d48c	__skb_recv_datagram
+EXPORT_SYMBOL vmlinux 0x9b388444	get_zeroed_page
+EXPORT_SYMBOL vmlinux 0x9b406041	vlan_ioctl_set
+EXPORT_SYMBOL vmlinux 0x9b596524	netif_receive_skb
+EXPORT_SYMBOL vmlinux 0x9b6c96e8	__dev_getfirstbyhwtype
+EXPORT_SYMBOL vmlinux 0x9b8c048c	tty_unregister_driver
+EXPORT_SYMBOL vmlinux 0x9ba7089d	argv_split
+EXPORT_SYMBOL vmlinux 0x9ba8d240	vlan_dev_vlan_id
+EXPORT_SYMBOL vmlinux 0x9baab629	locks_init_lock
+EXPORT_SYMBOL vmlinux 0x9bc7e4b9	unregister_con_driver
+EXPORT_SYMBOL vmlinux 0x9bc848bb	no_llseek
+EXPORT_SYMBOL vmlinux 0x9bc84aa8	net_accel_map_grants_contig
+EXPORT_SYMBOL vmlinux 0x9bcc02a6	simple_transaction_release
+EXPORT_SYMBOL vmlinux 0x9c012508	fb_parse_edid
+EXPORT_SYMBOL vmlinux 0x9c0ea3cd	memscan
+EXPORT_SYMBOL vmlinux 0x9c122d10	cdrom_number_of_slots
+EXPORT_SYMBOL vmlinux 0x9c1aa490	tty_write_room
+EXPORT_SYMBOL vmlinux 0x9c1d0061	tcf_unregister_action
+EXPORT_SYMBOL vmlinux 0x9c2e71d6	get_phy_device
+EXPORT_SYMBOL vmlinux 0x9c362195	tty_name
+EXPORT_SYMBOL vmlinux 0x9c491f60	sg_alloc_table
+EXPORT_SYMBOL vmlinux 0x9c4b7fb8	follow_pfn
+EXPORT_SYMBOL vmlinux 0x9c63b53f	proto_register
+EXPORT_SYMBOL vmlinux 0x9c6c61c4	tcp_parse_options
+EXPORT_SYMBOL vmlinux 0x9c6d9cf5	cdrom_ioctl
+EXPORT_SYMBOL vmlinux 0x9c71e738	per_cpu__vm_event_states
+EXPORT_SYMBOL vmlinux 0x9ca95a0e	sort
+EXPORT_SYMBOL vmlinux 0x9cabc165	tty_set_operations
+EXPORT_SYMBOL vmlinux 0x9caf02ed	put_io_context
+EXPORT_SYMBOL vmlinux 0x9cb96e92	qdisc_put_rtab
+EXPORT_SYMBOL vmlinux 0x9cbcdb37	proto_unregister
+EXPORT_SYMBOL vmlinux 0x9ccb2622	finish_wait
+EXPORT_SYMBOL vmlinux 0x9ced38aa	down_trylock
+EXPORT_SYMBOL vmlinux 0x9d0da704	alloc_netdev_mq
+EXPORT_SYMBOL vmlinux 0x9d3aa376	blk_iopoll_init
+EXPORT_SYMBOL vmlinux 0x9d3c5f5b	pci_scan_bus_parented
+EXPORT_SYMBOL vmlinux 0x9d9d24e5	simple_write_begin
+EXPORT_SYMBOL vmlinux 0x9db21624	hex_dump_to_buffer
+EXPORT_SYMBOL vmlinux 0x9dbadae7	register_qdisc
+EXPORT_SYMBOL vmlinux 0x9df56daf	unlock_new_inode
+EXPORT_SYMBOL vmlinux 0x9df81d6a	ip_mc_inc_group
+EXPORT_SYMBOL vmlinux 0x9e005097	sk_release_kernel
+EXPORT_SYMBOL vmlinux 0x9e2b3d65	seq_bitmap
+EXPORT_SYMBOL vmlinux 0x9e36f76b	tty_schedule_flip
+EXPORT_SYMBOL vmlinux 0x9e63ceab	d_rehash
+EXPORT_SYMBOL vmlinux 0x9e64fbfe	rtc_cmos_read
+EXPORT_SYMBOL vmlinux 0x9e7d6bd0	__udelay
+EXPORT_SYMBOL vmlinux 0x9e8a6c5a	check_disk_size_change
+EXPORT_SYMBOL vmlinux 0x9e8ec939	netdev_features_change
+EXPORT_SYMBOL vmlinux 0x9e9f1714	__bitmap_andnot
+EXPORT_SYMBOL vmlinux 0x9ea0ad49	__sg_free_table
+EXPORT_SYMBOL vmlinux 0x9ea9432c	fd_install
+EXPORT_SYMBOL vmlinux 0x9ebd4c04	adjust_resource
+EXPORT_SYMBOL vmlinux 0x9ec34395	blk_sync_queue
+EXPORT_SYMBOL vmlinux 0x9ec52f8c	alloc_file
+EXPORT_SYMBOL vmlinux 0x9ec830ab	compat_mc_getsockopt
+EXPORT_SYMBOL vmlinux 0x9ed7b967	journal_invalidatepage
+EXPORT_SYMBOL vmlinux 0x9edbecae	snprintf
+EXPORT_SYMBOL vmlinux 0x9eecde16	do_brk
+EXPORT_SYMBOL vmlinux 0x9eecfc47	setup_arg_pages
+EXPORT_SYMBOL vmlinux 0x9ef215e4	__put_cred
+EXPORT_SYMBOL vmlinux 0x9efd9326	clocksource_unregister
+EXPORT_SYMBOL vmlinux 0x9f100139	jiffies_to_clock_t
+EXPORT_SYMBOL vmlinux 0x9f1a7653	vm_insert_mixed
+EXPORT_SYMBOL vmlinux 0x9f20de4a	kmem_cache_destroy
+EXPORT_SYMBOL vmlinux 0x9f2bdaac	__bitmap_or
+EXPORT_SYMBOL vmlinux 0x9f2d613e	param_set_bool
+EXPORT_SYMBOL vmlinux 0x9f4703e2	nf_ct_attach
+EXPORT_SYMBOL vmlinux 0x9f984513	strrchr
+EXPORT_SYMBOL vmlinux 0x9fa274b4	dq_data_lock
+EXPORT_SYMBOL vmlinux 0x9fb36881	w1_remove_master_device
+EXPORT_SYMBOL vmlinux 0xa010989b	sock_setsockopt
+EXPORT_SYMBOL vmlinux 0xa025c418	vfs_quota_disable
+EXPORT_SYMBOL vmlinux 0xa03523d5	security_unix_stream_connect
+EXPORT_SYMBOL vmlinux 0xa03f71c6	nf_register_sockopt
+EXPORT_SYMBOL vmlinux 0xa045f66e	dev_remove_pack
+EXPORT_SYMBOL vmlinux 0xa04a01bd	qdisc_class_hash_insert
+EXPORT_SYMBOL vmlinux 0xa04ea3ac	netpoll_poll
+EXPORT_SYMBOL vmlinux 0xa05c03df	mempool_kmalloc
+EXPORT_SYMBOL vmlinux 0xa082583d	netpoll_print_options
+EXPORT_SYMBOL vmlinux 0xa0a4ac21	tcf_hash_insert
+EXPORT_SYMBOL vmlinux 0xa0b04675	vmalloc_32
+EXPORT_SYMBOL vmlinux 0xa0ceef51	out_of_line_wait_on_bit
+EXPORT_SYMBOL vmlinux 0xa0d3994a	iw_handler_set_thrspy
+EXPORT_SYMBOL vmlinux 0xa0d3d560	ksize
+EXPORT_SYMBOL vmlinux 0xa0eb5e61	input_register_handle
+EXPORT_SYMBOL vmlinux 0xa0f64fcd	__xfrm_route_forward
+EXPORT_SYMBOL vmlinux 0xa0fbac79	wake_up_bit
+EXPORT_SYMBOL vmlinux 0xa108eb4d	sysctl_optmem_max
+EXPORT_SYMBOL vmlinux 0xa10ac06f	ps2_init
+EXPORT_SYMBOL vmlinux 0xa116b917	udp_proc_unregister
+EXPORT_SYMBOL vmlinux 0xa120d33c	tty_unregister_ldisc
+EXPORT_SYMBOL vmlinux 0xa1353448	tty_unthrottle
+EXPORT_SYMBOL vmlinux 0xa13798f8	printk_ratelimit
+EXPORT_SYMBOL vmlinux 0xa13821d9	__seq_open_private
+EXPORT_SYMBOL vmlinux 0xa1396cbf	pci_get_device
+EXPORT_SYMBOL vmlinux 0xa146522b	dm_kcopyd_client_destroy
+EXPORT_SYMBOL vmlinux 0xa15ad034	input_release_device
+EXPORT_SYMBOL vmlinux 0xa16351b4	blk_plug_device
+EXPORT_SYMBOL vmlinux 0xa16f2bbd	xfrm_state_alloc
+EXPORT_SYMBOL vmlinux 0xa18e2004	pci_request_region_exclusive
+EXPORT_SYMBOL vmlinux 0xa1b759ce	fb_add_videomode
+EXPORT_SYMBOL vmlinux 0xa1b7f707	gnet_stats_copy_basic
+EXPORT_SYMBOL vmlinux 0xa1ba4b95	memcpy_fromiovecend
+EXPORT_SYMBOL vmlinux 0xa1c76e0a	_cond_resched
+EXPORT_SYMBOL vmlinux 0xa1cea0b8	proc_dointvec
+EXPORT_SYMBOL vmlinux 0xa1f2eb6e	inode_add_rsv_space
+EXPORT_SYMBOL vmlinux 0xa1ffe569	pci_enable_msi_block
+EXPORT_SYMBOL vmlinux 0xa20ce1b8	net_msg_warn
+EXPORT_SYMBOL vmlinux 0xa20d5e15	replace_mount_options
+EXPORT_SYMBOL vmlinux 0xa21b0124	add_to_page_cache_locked
+EXPORT_SYMBOL vmlinux 0xa24e0958	journal_try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0xa27cdc93	aio_complete
+EXPORT_SYMBOL vmlinux 0xa28e76e6	schedule_work
+EXPORT_SYMBOL vmlinux 0xa29b1708	tcp_memory_allocated
+EXPORT_SYMBOL vmlinux 0xa2a1e5c9	_write_lock_bh
+EXPORT_SYMBOL vmlinux 0xa2a5fd77	inet_ehash_secret
+EXPORT_SYMBOL vmlinux 0xa2a680f3	new_inode
+EXPORT_SYMBOL vmlinux 0xa2aa0504	ip_mc_rejoin_group
+EXPORT_SYMBOL vmlinux 0xa2af8d38	get_super
+EXPORT_SYMBOL vmlinux 0xa2b8a2ba	__init_rwsem
+EXPORT_SYMBOL vmlinux 0xa2dca9dd	pci_bus_size_bridges
+EXPORT_SYMBOL vmlinux 0xa2f58a3d	pcix_get_max_mmrbc
+EXPORT_SYMBOL vmlinux 0xa303f072	sk_stop_timer
+EXPORT_SYMBOL vmlinux 0xa3062d72	__lock_page
+EXPORT_SYMBOL vmlinux 0xa31f172d	__copy_from_user_inatomic
+EXPORT_SYMBOL vmlinux 0xa329f07e	register_shrinker
+EXPORT_SYMBOL vmlinux 0xa32b299b	__xfrm_state_delete
+EXPORT_SYMBOL vmlinux 0xa32c6f48	km_policy_notify
+EXPORT_SYMBOL vmlinux 0xa332cdd1	security_tun_dev_attach
+EXPORT_SYMBOL vmlinux 0xa33f7c7c	nla_strlcpy
+EXPORT_SYMBOL vmlinux 0xa350a8f8	set_memory_array_uc
+EXPORT_SYMBOL vmlinux 0xa35de80f	ipv4_config
+EXPORT_SYMBOL vmlinux 0xa3a1614d	poll_schedule_timeout
+EXPORT_SYMBOL vmlinux 0xa3a5be95	memmove
+EXPORT_SYMBOL vmlinux 0xa3ae7149	request_key_async
+EXPORT_SYMBOL vmlinux 0xa3e53487	d_lookup
+EXPORT_SYMBOL vmlinux 0xa415b384	try_to_del_timer_sync
+EXPORT_SYMBOL vmlinux 0xa437a1aa	audit_log_start
+EXPORT_SYMBOL vmlinux 0xa44a7abe	simple_statfs
+EXPORT_SYMBOL vmlinux 0xa44ad274	wait_for_completion_interruptible_timeout
+EXPORT_SYMBOL vmlinux 0xa44b6a58	generic_file_splice_read
+EXPORT_SYMBOL vmlinux 0xa44b8726	set_blocksize
+EXPORT_SYMBOL vmlinux 0xa48b051b	devm_free_irq
+EXPORT_SYMBOL vmlinux 0xa4b94fea	iowrite8_rep
+EXPORT_SYMBOL vmlinux 0xa5351ff8	inet_getname
+EXPORT_SYMBOL vmlinux 0xa565277f	block_is_partially_uptodate
+EXPORT_SYMBOL vmlinux 0xa56f1315	mempool_free
+EXPORT_SYMBOL vmlinux 0xa5808bbf	tasklet_init
+EXPORT_SYMBOL vmlinux 0xa58b6804	nla_parse
+EXPORT_SYMBOL vmlinux 0xa5922bb1	kfifo_init
+EXPORT_SYMBOL vmlinux 0xa597685d	lro_vlan_hwaccel_receive_skb
+EXPORT_SYMBOL vmlinux 0xa598e29c	vesa_modes
+EXPORT_SYMBOL vmlinux 0xa5adbe8c	ida_destroy
+EXPORT_SYMBOL vmlinux 0xa5b21c30	generic_setxattr
+EXPORT_SYMBOL vmlinux 0xa5ca95dd	wait_on_sync_kiocb
+EXPORT_SYMBOL vmlinux 0xa609c528	tcp_child_process
+EXPORT_SYMBOL vmlinux 0xa6119b70	simple_getattr
+EXPORT_SYMBOL vmlinux 0xa616f4e1	tcp_v4_connect
+EXPORT_SYMBOL vmlinux 0xa63909e3	skb_append_datato_frags
+EXPORT_SYMBOL vmlinux 0xa63d85ab	slhc_remember
+EXPORT_SYMBOL vmlinux 0xa654fa73	read_cache_page
+EXPORT_SYMBOL vmlinux 0xa68124fa	hweight8
+EXPORT_SYMBOL vmlinux 0xa681fe88	generate_random_uuid
+EXPORT_SYMBOL vmlinux 0xa6a6b901	blk_queue_max_segment_size
+EXPORT_SYMBOL vmlinux 0xa6b1cd51	alloc_disk_node
+EXPORT_SYMBOL vmlinux 0xa6b81b66	netdev_state_change
+EXPORT_SYMBOL vmlinux 0xa6dcc773	rb_insert_color
+EXPORT_SYMBOL vmlinux 0xa6de5b24	call_usermodehelper_setcleanup
+EXPORT_SYMBOL vmlinux 0xa6e15f58	pci_target_state
+EXPORT_SYMBOL vmlinux 0xa7042294	blk_queue_init_tags
+EXPORT_SYMBOL vmlinux 0xa758d50a	vmap
+EXPORT_SYMBOL vmlinux 0xa7751180	sock_create_lite
+EXPORT_SYMBOL vmlinux 0xa845bc19	input_close_device
+EXPORT_SYMBOL vmlinux 0xa846ccc6	d_delete
+EXPORT_SYMBOL vmlinux 0xa86803ab	tcp_v4_md5_lookup
+EXPORT_SYMBOL vmlinux 0xa87ac803	generic_block_fiemap
+EXPORT_SYMBOL vmlinux 0xa886a958	krealloc
+EXPORT_SYMBOL vmlinux 0xa8984a24	jbd2_journal_invalidatepage
+EXPORT_SYMBOL vmlinux 0xa89f20f2	skb_abort_seq_read
+EXPORT_SYMBOL vmlinux 0xa8a6f639	__check_region
+EXPORT_SYMBOL vmlinux 0xa8eb4db6	__f_setown
+EXPORT_SYMBOL vmlinux 0xa8fbf582	idr_replace
+EXPORT_SYMBOL vmlinux 0xa8fef7bb	security_unix_may_send
+EXPORT_SYMBOL vmlinux 0xa922ef98	tty_port_alloc_xmit_buf
+EXPORT_SYMBOL vmlinux 0xa951cf2d	destroy_EII_client
+EXPORT_SYMBOL vmlinux 0xa9598e4d	tty_get_baud_rate
+EXPORT_SYMBOL vmlinux 0xa95a45bf	eth_mac_addr
+EXPORT_SYMBOL vmlinux 0xa96d7383	neigh_seq_start
+EXPORT_SYMBOL vmlinux 0xa98f785c	sock_no_recvmsg
+EXPORT_SYMBOL vmlinux 0xa9b7590a	pcie_port_service_register
+EXPORT_SYMBOL vmlinux 0xa9bd2676	__vmalloc
+EXPORT_SYMBOL vmlinux 0xa9d7186b	mb_cache_shrink
+EXPORT_SYMBOL vmlinux 0xa9e0122f	pci_restore_state
+EXPORT_SYMBOL vmlinux 0xa9fcf31d	wait_for_completion_interruptible
+EXPORT_SYMBOL vmlinux 0xaa29cc1d	set_page_dirty_lock
+EXPORT_SYMBOL vmlinux 0xaa4cf925	mb_cache_entry_find_first
+EXPORT_SYMBOL vmlinux 0xaa71e132	kfree_skb
+EXPORT_SYMBOL vmlinux 0xaa75b6f8	blk_run_queue
+EXPORT_SYMBOL vmlinux 0xaa9b1b05	follow_down
+EXPORT_SYMBOL vmlinux 0xaa9f99d7	framebuffer_release
+EXPORT_SYMBOL vmlinux 0xaab06af8	_write_lock_irqsave
+EXPORT_SYMBOL vmlinux 0xaaf672f6	nf_setsockopt
+EXPORT_SYMBOL vmlinux 0xaafdc258	strcasecmp
+EXPORT_SYMBOL vmlinux 0xab1c25e5	elv_rb_latter_request
+EXPORT_SYMBOL vmlinux 0xab1e9463	__register_chrdev
+EXPORT_SYMBOL vmlinux 0xab4ec816	devm_ioremap_nocache
+EXPORT_SYMBOL vmlinux 0xab50a694	simple_transaction_get
+EXPORT_SYMBOL vmlinux 0xab600421	probe_irq_off
+EXPORT_SYMBOL vmlinux 0xab65ed80	set_memory_uc
+EXPORT_SYMBOL vmlinux 0xab770678	rdmsr_safe_regs_on_cpu
+EXPORT_SYMBOL vmlinux 0xab8cb150	mark_page_accessed
+EXPORT_SYMBOL vmlinux 0xaba9ff34	allocate_resource
+EXPORT_SYMBOL vmlinux 0xabc0e61c	unregister_snap_client
+EXPORT_SYMBOL vmlinux 0xabc28976	force_evtchn_callback
+EXPORT_SYMBOL vmlinux 0xabd0c91c	rtc_time_to_tm
+EXPORT_SYMBOL vmlinux 0xabe85a21	idr_init
+EXPORT_SYMBOL vmlinux 0xabf6465d	tcp_recvmsg
+EXPORT_SYMBOL vmlinux 0xac0ba8c1	blk_iopoll_disable
+EXPORT_SYMBOL vmlinux 0xac0c406a	per_cpu__irq_stat
+EXPORT_SYMBOL vmlinux 0xac2fdeb3	pci_select_bars
+EXPORT_SYMBOL vmlinux 0xac363bda	seq_printf
+EXPORT_SYMBOL vmlinux 0xac383451	radix_tree_tag_clear
+EXPORT_SYMBOL vmlinux 0xac6855b0	gen_kill_estimator
+EXPORT_SYMBOL vmlinux 0xac8ef956	generic_getxattr
+EXPORT_SYMBOL vmlinux 0xac99d743	bdi_register
+EXPORT_SYMBOL vmlinux 0xacb4fadc	dev_set_allmulti
+EXPORT_SYMBOL vmlinux 0xacb73b67	tcp_poll
+EXPORT_SYMBOL vmlinux 0xacc410ed	phy_print_status
+EXPORT_SYMBOL vmlinux 0xaccabc6a	in4_pton
+EXPORT_SYMBOL vmlinux 0xacdeb154	__tracepoint_module_get
+EXPORT_SYMBOL vmlinux 0xace0c4d6	unregister_exec_domain
+EXPORT_SYMBOL vmlinux 0xacf0467a	release_sock
+EXPORT_SYMBOL vmlinux 0xacf201cb	fb_firmware_edid
+EXPORT_SYMBOL vmlinux 0xacf4d843	match_strdup
+EXPORT_SYMBOL vmlinux 0xad0413d4	match_hex
+EXPORT_SYMBOL vmlinux 0xad253ec5	key_type_keyring
+EXPORT_SYMBOL vmlinux 0xad25fb12	__memcpy
+EXPORT_SYMBOL vmlinux 0xad435cc2	skb_recycle_check
+EXPORT_SYMBOL vmlinux 0xad67376d	simple_transaction_set
+EXPORT_SYMBOL vmlinux 0xadaf5247	generic_splice_sendpage
+EXPORT_SYMBOL vmlinux 0xadb97470	sock_no_socketpair
+EXPORT_SYMBOL vmlinux 0xae0eaa73	security_path_symlink
+EXPORT_SYMBOL vmlinux 0xae3e873d	ilookup5_nowait
+EXPORT_SYMBOL vmlinux 0xae3f3f91	__skb_checksum_complete
+EXPORT_SYMBOL vmlinux 0xae924f2e	tcf_hash_check
+EXPORT_SYMBOL vmlinux 0xae99bcb7	journal_load
+EXPORT_SYMBOL vmlinux 0xae9e4f02	neigh_for_each
+EXPORT_SYMBOL vmlinux 0xaecde111	uart_write_wakeup
+EXPORT_SYMBOL vmlinux 0xaed013b9	posix_acl_valid
+EXPORT_SYMBOL vmlinux 0xaee9fbfd	i8042_check_port_owner
+EXPORT_SYMBOL vmlinux 0xaef5c46c	check_disk_change
+EXPORT_SYMBOL vmlinux 0xaef63854	__pagevec_release
+EXPORT_SYMBOL vmlinux 0xaefc6e25	eth_change_mtu
+EXPORT_SYMBOL vmlinux 0xaf02a427	__blk_end_request_cur
+EXPORT_SYMBOL vmlinux 0xaf08a8c9	__netdev_alloc_skb
+EXPORT_SYMBOL vmlinux 0xaf104e1e	fb_get_mode
+EXPORT_SYMBOL vmlinux 0xaf17aa5d	net_accel_map_iomem_page
+EXPORT_SYMBOL vmlinux 0xaf25d90a	sock_create
+EXPORT_SYMBOL vmlinux 0xaf53aa69	free_netdev
+EXPORT_SYMBOL vmlinux 0xaf5496a4	jbd2_journal_force_commit_nested
+EXPORT_SYMBOL vmlinux 0xafa267c1	bdi_set_max_ratio
+EXPORT_SYMBOL vmlinux 0xafabcd1c	jbd2_journal_try_to_free_buffers
+EXPORT_SYMBOL vmlinux 0xafae3729	vfs_quota_enable
+EXPORT_SYMBOL vmlinux 0xafce153e	vfs_readlink
+EXPORT_SYMBOL vmlinux 0xafe7f69e	boot_cpu_data
+EXPORT_SYMBOL vmlinux 0xafe82e10	strcspn
+EXPORT_SYMBOL vmlinux 0xaff773ee	register_atm_ioctl
+EXPORT_SYMBOL vmlinux 0xb00ef5ac	proc_doulongvec_ms_jiffies_minmax
+EXPORT_SYMBOL vmlinux 0xb03c59b9	write_inode_now
+EXPORT_SYMBOL vmlinux 0xb051909f	ida_init
+EXPORT_SYMBOL vmlinux 0xb055d8da	posix_acl_to_xattr
+EXPORT_SYMBOL vmlinux 0xb060f8ec	input_event
+EXPORT_SYMBOL vmlinux 0xb079d637	fb_find_mode
+EXPORT_SYMBOL vmlinux 0xb0b847ac	__bitmap_full
+EXPORT_SYMBOL vmlinux 0xb0e10781	get_option
+EXPORT_SYMBOL vmlinux 0xb0f88756	inet_put_port
+EXPORT_SYMBOL vmlinux 0xb11019f8	km_query
+EXPORT_SYMBOL vmlinux 0xb11fa1ce	strlcat
+EXPORT_SYMBOL vmlinux 0xb121390a	probe_irq_on
+EXPORT_SYMBOL vmlinux 0xb12f4660	skb_queue_purge
+EXPORT_SYMBOL vmlinux 0xb15f2eb4	mpage_writepages
+EXPORT_SYMBOL vmlinux 0xb1645a2e	sg_free_table
+EXPORT_SYMBOL vmlinux 0xb18e02c3	radix_tree_gang_lookup_tag
+EXPORT_SYMBOL vmlinux 0xb193bd1d	sock_wake_async
+EXPORT_SYMBOL vmlinux 0xb19760c3	bitmap_onto
+EXPORT_SYMBOL vmlinux 0xb1c3a01a	oops_in_progress
+EXPORT_SYMBOL vmlinux 0xb1cfad22	rdmsr_on_cpu
+EXPORT_SYMBOL vmlinux 0xb1f975aa	unlock_kernel
+EXPORT_SYMBOL vmlinux 0xb224fbe2	param_get_short
+EXPORT_SYMBOL vmlinux 0xb22fe6a3	netdev_increment_features
+EXPORT_SYMBOL vmlinux 0xb2516126	generic_ro_fops
+EXPORT_SYMBOL vmlinux 0xb25c3772	unregister_sysctl_table
+EXPORT_SYMBOL vmlinux 0xb2682405	utf8_to_utf32
+EXPORT_SYMBOL vmlinux 0xb2a3dcf3	jbd2_journal_release_jbd_inode
+EXPORT_SYMBOL vmlinux 0xb2e55898	cpu_possible_mask
+EXPORT_SYMBOL vmlinux 0xb2fd5ceb	__put_user_4
+EXPORT_SYMBOL vmlinux 0xb306cba8	ps2_handle_ack
+EXPORT_SYMBOL vmlinux 0xb31e9bd4	netlink_ack
+EXPORT_SYMBOL vmlinux 0xb3205415	wait_for_completion_killable
+EXPORT_SYMBOL vmlinux 0xb32346a5	tty_free_termios
+EXPORT_SYMBOL vmlinux 0xb352177e	find_first_bit
+EXPORT_SYMBOL vmlinux 0xb35bedac	udplite_prot
+EXPORT_SYMBOL vmlinux 0xb37f4237	generic_setlease
+EXPORT_SYMBOL vmlinux 0xb3936e6a	generic_file_direct_write
+EXPORT_SYMBOL vmlinux 0xb3994c7a	per_cpu__kstat
+EXPORT_SYMBOL vmlinux 0xb3a307c6	si_meminfo
+EXPORT_SYMBOL vmlinux 0xb3adf679	gnttab_pre_map_adjust
+EXPORT_SYMBOL vmlinux 0xb3b782d1	netif_rx_ni
+EXPORT_SYMBOL vmlinux 0xb3e2435d	pci_do_scan_bus
+EXPORT_SYMBOL vmlinux 0xb3ff1f69	free_pages_exact
+EXPORT_SYMBOL vmlinux 0xb4005b2f	cfb_imageblit
+EXPORT_SYMBOL vmlinux 0xb416b053	__ip_select_ident
+EXPORT_SYMBOL vmlinux 0xb423dba1	console_blanked
+EXPORT_SYMBOL vmlinux 0xb42453d3	param_get_invbool
+EXPORT_SYMBOL vmlinux 0xb4279ab7	downgrade_write
+EXPORT_SYMBOL vmlinux 0xb42e6021	kobject_init
+EXPORT_SYMBOL vmlinux 0xb4386947	__xfrm_decode_session
+EXPORT_SYMBOL vmlinux 0xb45b24f6	k8_nb_ids
+EXPORT_SYMBOL vmlinux 0xb47afadf	xfrm_input_resume
+EXPORT_SYMBOL vmlinux 0xb4b0ee4e	down_read
+EXPORT_SYMBOL vmlinux 0xb4b4cfcc	sock_common_recvmsg
+EXPORT_SYMBOL vmlinux 0xb4b6bbcb	unlock_super
+EXPORT_SYMBOL vmlinux 0xb4ca9447	__kfifo_get
+EXPORT_SYMBOL vmlinux 0xb4cfc68f	sget
+EXPORT_SYMBOL vmlinux 0xb4d0ec51	xfrm_policy_destroy
+EXPORT_SYMBOL vmlinux 0xb4d212cb	bio_map_user
+EXPORT_SYMBOL vmlinux 0xb4e6e690	create_mnt_ns
+EXPORT_SYMBOL vmlinux 0xb5044271	vsscanf
+EXPORT_SYMBOL vmlinux 0xb53c0b99	jbd2_journal_get_write_access
+EXPORT_SYMBOL vmlinux 0xb54533f7	usecs_to_jiffies
+EXPORT_SYMBOL vmlinux 0xb5536c88	alloc_fddidev
+EXPORT_SYMBOL vmlinux 0xb5608aed	dmam_alloc_noncoherent
+EXPORT_SYMBOL vmlinux 0xb5861f21	security_path_rmdir
+EXPORT_SYMBOL vmlinux 0xb59283f5	neigh_destroy
+EXPORT_SYMBOL vmlinux 0xb5a3e57d	register_sysrq_key
+EXPORT_SYMBOL vmlinux 0xb5a459dc	unregister_blkdev
+EXPORT_SYMBOL vmlinux 0xb5ab2fc1	compat_sock_get_timestampns
+EXPORT_SYMBOL vmlinux 0xb5b3c8b9	skb_append
+EXPORT_SYMBOL vmlinux 0xb5b5eaec	inode_newsize_ok
+EXPORT_SYMBOL vmlinux 0xb5bea43d	kmem_cache_create
+EXPORT_SYMBOL vmlinux 0xb5ca1c46	slhc_free
+EXPORT_SYMBOL vmlinux 0xb5e2f920	__dec_zone_page_state
+EXPORT_SYMBOL vmlinux 0xb5f15bcf	eth_header
+EXPORT_SYMBOL vmlinux 0xb5f28b5f	__any_online_cpu
+EXPORT_SYMBOL vmlinux 0xb5f43858	ioctl_by_bdev
+EXPORT_SYMBOL vmlinux 0xb5f6416e	abort_creds
+EXPORT_SYMBOL vmlinux 0xb6149475	ppp_output_wakeup
+EXPORT_SYMBOL vmlinux 0xb6244511	sg_init_one
+EXPORT_SYMBOL vmlinux 0xb626d7f3	____pagevec_lru_add
+EXPORT_SYMBOL vmlinux 0xb6519d04	module_put
+EXPORT_SYMBOL vmlinux 0xb66a1934	set_binfmt
+EXPORT_SYMBOL vmlinux 0xb67499df	pci_wake_from_d3
+EXPORT_SYMBOL vmlinux 0xb678366f	int_sqrt
+EXPORT_SYMBOL vmlinux 0xb68ecfda	pneigh_lookup
+EXPORT_SYMBOL vmlinux 0xb6a61a86	qdisc_get_rtab
+EXPORT_SYMBOL vmlinux 0xb6a68816	find_last_bit
+EXPORT_SYMBOL vmlinux 0xb6abb112	dev_change_flags
+EXPORT_SYMBOL vmlinux 0xb6beed27	arp_create
+EXPORT_SYMBOL vmlinux 0xb6bffb99	kstat_irqs_cpu
+EXPORT_SYMBOL vmlinux 0xb6e227aa	rtc_lock
+EXPORT_SYMBOL vmlinux 0xb71286db	vc_resize
+EXPORT_SYMBOL vmlinux 0xb7167d87	kobject_put
+EXPORT_SYMBOL vmlinux 0xb76d89de	jiffies_to_st
+EXPORT_SYMBOL vmlinux 0xb76db330	skb_unlink
+EXPORT_SYMBOL vmlinux 0xb7966aa3	xfrm_policy_unregister_afinfo
+EXPORT_SYMBOL vmlinux 0xb798b8e4	flow_cache_lookup
+EXPORT_SYMBOL vmlinux 0xb7a738d0	end_buffer_async_write
+EXPORT_SYMBOL vmlinux 0xb7d09eb9	pci_set_dma_mask
+EXPORT_SYMBOL vmlinux 0xb7e48297	pci_iounmap
+EXPORT_SYMBOL vmlinux 0xb7e4d3ab	atm_init_aal5
+EXPORT_SYMBOL vmlinux 0xb7eca995	nobh_write_begin
+EXPORT_SYMBOL vmlinux 0xb813ce5a	timecompare_transform
+EXPORT_SYMBOL vmlinux 0xb83d3c6d	inode_permission
+EXPORT_SYMBOL vmlinux 0xb86e4ab9	random32
+EXPORT_SYMBOL vmlinux 0xb87552cb	__invalidate_device
+EXPORT_SYMBOL vmlinux 0xb896eb90	nlmsg_notify
+EXPORT_SYMBOL vmlinux 0xb89af9bf	srandom32
+EXPORT_SYMBOL vmlinux 0xb8a61d17	do_munmap
+EXPORT_SYMBOL vmlinux 0xb8af52c7	sk_common_release
+EXPORT_SYMBOL vmlinux 0xb8bb4e1d	dm_kcopyd_copy
+EXPORT_SYMBOL vmlinux 0xb8c14a59	dcache_dir_open
+EXPORT_SYMBOL vmlinux 0xb8d48087	kobject_set_name
+EXPORT_SYMBOL vmlinux 0xb8e7ce2c	__put_user_8
+EXPORT_SYMBOL vmlinux 0xb9109550	blk_integrity_register
+EXPORT_SYMBOL vmlinux 0xb98a0185	rtc_tm_to_time
+EXPORT_SYMBOL vmlinux 0xb9948f42	nla_put
+EXPORT_SYMBOL vmlinux 0xb9a16700	dev_unicast_delete
+EXPORT_SYMBOL vmlinux 0xb9a16b8c	sync_blockdev
+EXPORT_SYMBOL vmlinux 0xb9c2a584	input_flush_device
+EXPORT_SYMBOL vmlinux 0xb9dc1c69	scm_detach_fds
+EXPORT_SYMBOL vmlinux 0xb9dc6845	xfrm_register_km
+EXPORT_SYMBOL vmlinux 0xb9e310ee	bd_claim
+EXPORT_SYMBOL vmlinux 0xba044cd8	key_put
+EXPORT_SYMBOL vmlinux 0xba36e433	request_key_async_with_auxdata
+EXPORT_SYMBOL vmlinux 0xba497f13	loops_per_jiffy
+EXPORT_SYMBOL vmlinux 0xba76b86d	default_unplug_io_fn
+EXPORT_SYMBOL vmlinux 0xbaa2782a	kstrndup
+EXPORT_SYMBOL vmlinux 0xbaa8e4dc	journal_unlock_updates
+EXPORT_SYMBOL vmlinux 0xbaaab8ae	timespec_to_jiffies
+EXPORT_SYMBOL vmlinux 0xbadd378b	cdev_alloc
+EXPORT_SYMBOL vmlinux 0xbae62793	user_path_at
+EXPORT_SYMBOL vmlinux 0xbb167766	fb_var_to_videomode
+EXPORT_SYMBOL vmlinux 0xbb189cad	disallow_signal
+EXPORT_SYMBOL vmlinux 0xbb1fad6a	flush_delayed_work
+EXPORT_SYMBOL vmlinux 0xbb5d343d	xfrm_get_acqseq
+EXPORT_SYMBOL vmlinux 0xbb88ac8f	xfrm_policy_flush
+EXPORT_SYMBOL vmlinux 0xbb8f90b2	vfs_dq_quota_on_remount
+EXPORT_SYMBOL vmlinux 0xbb98ab05	pcie_get_readrq
+EXPORT_SYMBOL vmlinux 0xbbb72168	__dev_remove_pack
+EXPORT_SYMBOL vmlinux 0xbbbfaebe	napi_get_frags
+EXPORT_SYMBOL vmlinux 0xbbf894d7	dma_ops
+EXPORT_SYMBOL vmlinux 0xbc1859c7	input_open_device
+EXPORT_SYMBOL vmlinux 0xbc3d228b	blk_get_request
+EXPORT_SYMBOL vmlinux 0xbc4222e7	dmam_free_coherent
+EXPORT_SYMBOL vmlinux 0xbc562ac2	tcp_v4_do_rcv
+EXPORT_SYMBOL vmlinux 0xbc5a5f91	get_sb_pseudo
+EXPORT_SYMBOL vmlinux 0xbc66c41a	fb_blank
+EXPORT_SYMBOL vmlinux 0xbc9d7fea	tty_devnum
+EXPORT_SYMBOL vmlinux 0xbca0eb15	dquot_commit_info
+EXPORT_SYMBOL vmlinux 0xbcb255cb	unregister_filesystem
+EXPORT_SYMBOL vmlinux 0xbcc308bb	strnlen_user
+EXPORT_SYMBOL vmlinux 0xbccbb49c	idr_remove_all
+EXPORT_SYMBOL vmlinux 0xbce4a974	set_bh_page
+EXPORT_SYMBOL vmlinux 0xbd0dde30	set_pages_nx
+EXPORT_SYMBOL vmlinux 0xbd2637bb	inet_register_protosw
+EXPORT_SYMBOL vmlinux 0xbd616ab1	tty_port_close_start
+EXPORT_SYMBOL vmlinux 0xbd9213a3	inet_dgram_ops
+EXPORT_SYMBOL vmlinux 0xbdeb4917	genl_register_ops
+EXPORT_SYMBOL vmlinux 0xbdf5c25c	rb_next
+EXPORT_SYMBOL vmlinux 0xbe14ea19	udp_prot
+EXPORT_SYMBOL vmlinux 0xbe499d81	copy_to_user
+EXPORT_SYMBOL vmlinux 0xbe4af9fd	register_exec_domain
+EXPORT_SYMBOL vmlinux 0xbe7232f7	pci_enable_msix
+EXPORT_SYMBOL vmlinux 0xbeaeb45b	tty_driver_kref_put
+EXPORT_SYMBOL vmlinux 0xbec8077d	inet_accept
+EXPORT_SYMBOL vmlinux 0xbecdce74	ida_pre_get
+EXPORT_SYMBOL vmlinux 0xbee317b5	journal_abort
+EXPORT_SYMBOL vmlinux 0xbee85c80	security_path_mknod
+EXPORT_SYMBOL vmlinux 0xbee91440	get_sb_ns
+EXPORT_SYMBOL vmlinux 0xbef43296	console_conditional_schedule
+EXPORT_SYMBOL vmlinux 0xbef7645a	rtnl_set_sk_err
+EXPORT_SYMBOL vmlinux 0xbeff9edd	unregister_qdisc
+EXPORT_SYMBOL vmlinux 0xbf09e72f	invalidate_mapping_pages
+EXPORT_SYMBOL vmlinux 0xbf19a427	jbd2_journal_errno
+EXPORT_SYMBOL vmlinux 0xbf28d69e	neigh_table_clear
+EXPORT_SYMBOL vmlinux 0xbf36888f	netif_device_attach
+EXPORT_SYMBOL vmlinux 0xbf5935d2	uart_register_driver
+EXPORT_SYMBOL vmlinux 0xbf69d273	key_link
+EXPORT_SYMBOL vmlinux 0xbf75799f	may_umount_tree
+EXPORT_SYMBOL vmlinux 0xbf7fd2f5	schedule_timeout_killable
+EXPORT_SYMBOL vmlinux 0xbf9bcc8d	__cap_empty_set
+EXPORT_SYMBOL vmlinux 0xbfa3527b	create_empty_buffers
+EXPORT_SYMBOL vmlinux 0xbfab8a03	sock_no_mmap
+EXPORT_SYMBOL vmlinux 0xbfade061	grab_cache_page_write_begin
+EXPORT_SYMBOL vmlinux 0xbfc177bc	iowrite32_rep
+EXPORT_SYMBOL vmlinux 0xbfdddbb6	jbd2_journal_get_create_access
+EXPORT_SYMBOL vmlinux 0xbfe41320	tty_hangup
+EXPORT_SYMBOL vmlinux 0xbfe6e14c	skb_clone
+EXPORT_SYMBOL vmlinux 0xbfed0301	do_sync_read
+EXPORT_SYMBOL vmlinux 0xbfee3ad5	loop_unregister_transfer
+EXPORT_SYMBOL vmlinux 0xc003be97	blk_queue_make_request
+EXPORT_SYMBOL vmlinux 0xc003c637	__strncpy_from_user
+EXPORT_SYMBOL vmlinux 0xc0044724	blk_set_default_limits
+EXPORT_SYMBOL vmlinux 0xc004d0e0	elv_dispatch_sort
+EXPORT_SYMBOL vmlinux 0xc005d252	fifo_set_limit
+EXPORT_SYMBOL vmlinux 0xc00a0e0a	compat_tcp_setsockopt
+EXPORT_SYMBOL vmlinux 0xc0580937	rb_erase
+EXPORT_SYMBOL vmlinux 0xc0954e4a	tcp_v4_md5_hash_skb
+EXPORT_SYMBOL vmlinux 0xc09651d9	crc32_be
+EXPORT_SYMBOL vmlinux 0xc098abba	bio_put
+EXPORT_SYMBOL vmlinux 0xc09ba5c8	tty_port_close
+EXPORT_SYMBOL vmlinux 0xc0a3d105	find_next_bit
+EXPORT_SYMBOL vmlinux 0xc0b0a336	udp_ioctl
+EXPORT_SYMBOL vmlinux 0xc0bb7625	get_user_pages
+EXPORT_SYMBOL vmlinux 0xc0bf6ead	timecounter_cyc2time
+EXPORT_SYMBOL vmlinux 0xc150fb46	net_accel_shutdown_remote
+EXPORT_SYMBOL vmlinux 0xc1551f74	deactivate_locked_super
+EXPORT_SYMBOL vmlinux 0xc15e06bf	ppp_channel_index
+EXPORT_SYMBOL vmlinux 0xc15ee4e2	skb_make_writable
+EXPORT_SYMBOL vmlinux 0xc1658392	vfs_quota_sync
+EXPORT_SYMBOL vmlinux 0xc1860eb7	tcp_gro_receive
+EXPORT_SYMBOL vmlinux 0xc18b7bfd	dev_get_by_flags
+EXPORT_SYMBOL vmlinux 0xc1c3ad54	vfs_read
+EXPORT_SYMBOL vmlinux 0xc1e248a1	skb_under_panic
+EXPORT_SYMBOL vmlinux 0xc1ee1d57	filemap_fdatawrite
+EXPORT_SYMBOL vmlinux 0xc20dadba	key_validate
+EXPORT_SYMBOL vmlinux 0xc23fb44d	nonseekable_open
+EXPORT_SYMBOL vmlinux 0xc254af48	dcache_lock
+EXPORT_SYMBOL vmlinux 0xc256e762	__bitmap_equal
+EXPORT_SYMBOL vmlinux 0xc2aa42a4	xfrm_dst_ifdown
+EXPORT_SYMBOL vmlinux 0xc2be9086	copy_io_context
+EXPORT_SYMBOL vmlinux 0xc2d36a6f	netdev_class_remove_file
+EXPORT_SYMBOL vmlinux 0xc2e587d1	reset_devices
+EXPORT_SYMBOL vmlinux 0xc2ec36f1	block_sync_page
+EXPORT_SYMBOL vmlinux 0xc2fca59b	sock_get_timestampns
+EXPORT_SYMBOL vmlinux 0xc2fed476	bio_kmalloc
+EXPORT_SYMBOL vmlinux 0xc32f57f6	blkdev_issue_flush
+EXPORT_SYMBOL vmlinux 0xc33f6f4c	on_each_cpu
+EXPORT_SYMBOL vmlinux 0xc36c86b1	swiotlb_sync_single_for_cpu
+EXPORT_SYMBOL vmlinux 0xc3819e22	truncate_pagecache
+EXPORT_SYMBOL vmlinux 0xc38fcb76	kset_register
+EXPORT_SYMBOL vmlinux 0xc3aaf0a9	__put_user_1
+EXPORT_SYMBOL vmlinux 0xc4147f10	blk_dump_rq_flags
+EXPORT_SYMBOL vmlinux 0xc434edbf	dst_discard
+EXPORT_SYMBOL vmlinux 0xc43e54ee	jbd2_journal_update_format
+EXPORT_SYMBOL vmlinux 0xc45b1884	generic_writepages
+EXPORT_SYMBOL vmlinux 0xc48ea484	vc_cons
+EXPORT_SYMBOL vmlinux 0xc499ae1e	kstrdup
+EXPORT_SYMBOL vmlinux 0xc4cf024b	inetdev_by_index
+EXPORT_SYMBOL vmlinux 0xc4d15436	sock_no_sendpage
+EXPORT_SYMBOL vmlinux 0xc4e9c01c	cpu_active_mask
+EXPORT_SYMBOL vmlinux 0xc52f5714	fb_videomode_to_var
+EXPORT_SYMBOL vmlinux 0xc53c882d	idr_get_new
+EXPORT_SYMBOL vmlinux 0xc5534d64	ioread16
+EXPORT_SYMBOL vmlinux 0xc558530d	profile_pc
+EXPORT_SYMBOL vmlinux 0xc55f7dc7	_write_trylock
+EXPORT_SYMBOL vmlinux 0xc5844fb8	__per_cpu_offset
+EXPORT_SYMBOL vmlinux 0xc596fd62	sk_free
+EXPORT_SYMBOL vmlinux 0xc5c1a753	dst_release
+EXPORT_SYMBOL vmlinux 0xc5e4713e	dm_table_get_md
+EXPORT_SYMBOL vmlinux 0xc5ffb2dc	xfrm_policy_delete
+EXPORT_SYMBOL vmlinux 0xc60c8ade	compat_sock_common_setsockopt
+EXPORT_SYMBOL vmlinux 0xc67457fa	atm_charge
+EXPORT_SYMBOL vmlinux 0xc68a9f2a	qdisc_tree_decrease_qlen
+EXPORT_SYMBOL vmlinux 0xc69a258f	__pskb_pull_tail
+EXPORT_SYMBOL vmlinux 0xc69a64c8	jbd2_journal_check_used_features
+EXPORT_SYMBOL vmlinux 0xc6dbf062	unregister_key_type
+EXPORT_SYMBOL vmlinux 0xc70538e5	dev_getfirstbyhwtype
+EXPORT_SYMBOL vmlinux 0xc71d41bb	xfrm_stateonly_find
+EXPORT_SYMBOL vmlinux 0xc7208c3a	serial8250_resume_port
+EXPORT_SYMBOL vmlinux 0xc722227e	posix_acl_clone
+EXPORT_SYMBOL vmlinux 0xc72e033e	delayed_slow_work_enqueue
+EXPORT_SYMBOL vmlinux 0xc7325bb3	dev_alloc_skb
+EXPORT_SYMBOL vmlinux 0xc740c64a	memchr
+EXPORT_SYMBOL vmlinux 0xc745debb	configfs_depend_item
+EXPORT_SYMBOL vmlinux 0xc79bcd36	dm_vcalloc
+EXPORT_SYMBOL vmlinux 0xc7a24d76	sysfs_format_mac
+EXPORT_SYMBOL vmlinux 0xc7a4fbed	rtnl_lock
+EXPORT_SYMBOL vmlinux 0xc7b27497	fb_get_buffer_offset
+EXPORT_SYMBOL vmlinux 0xc7baae88	__pci_register_driver
+EXPORT_SYMBOL vmlinux 0xc7bae506	blk_init_queue_node
+EXPORT_SYMBOL vmlinux 0xc7c13881	__napi_complete
+EXPORT_SYMBOL vmlinux 0xc7dac678	vfs_get_dqinfo
+EXPORT_SYMBOL vmlinux 0xc7f4610f	should_remove_suid
+EXPORT_SYMBOL vmlinux 0xc86baa7c	corgibl_limit_intensity
+EXPORT_SYMBOL vmlinux 0xc87478fc	jbd2_journal_begin_ordered_truncate
+EXPORT_SYMBOL vmlinux 0xc897c382	sg_init_table
+EXPORT_SYMBOL vmlinux 0xc89d842f	eth_rebuild_header
+EXPORT_SYMBOL vmlinux 0xc8b57c27	autoremove_wake_function
+EXPORT_SYMBOL vmlinux 0xc8ba225c	unload_nls
+EXPORT_SYMBOL vmlinux 0xc8c8ba85	lro_vlan_hwaccel_receive_frags
+EXPORT_SYMBOL vmlinux 0xc8f62e38	blk_queue_ordered
+EXPORT_SYMBOL vmlinux 0xc93b5c38	pci_bus_add_devices
+EXPORT_SYMBOL vmlinux 0xc9500e9d	tty_register_device
+EXPORT_SYMBOL vmlinux 0xc960b848	vfs_getattr
+EXPORT_SYMBOL vmlinux 0xc976f645	xen_invlpg
+EXPORT_SYMBOL vmlinux 0xc9877882	skb_queue_head
+EXPORT_SYMBOL vmlinux 0xc98b3d2b	napi_skb_finish
+EXPORT_SYMBOL vmlinux 0xc998d641	icmp_err_convert
+EXPORT_SYMBOL vmlinux 0xc9ccbec0	xfrm_state_lookup_byaddr
+EXPORT_SYMBOL vmlinux 0xc9df1de7	dmam_free_noncoherent
+EXPORT_SYMBOL vmlinux 0xc9ec8704	udp_table
+EXPORT_SYMBOL vmlinux 0xca7fb124	fb_set_suspend
+EXPORT_SYMBOL vmlinux 0xca8ef8aa	__generic_block_fiemap
+EXPORT_SYMBOL vmlinux 0xcabf70e8	xfrm4_rcv_encap
+EXPORT_SYMBOL vmlinux 0xcaffd48f	kernel_setsockopt
+EXPORT_SYMBOL vmlinux 0xcb3f481b	neigh_ifdown
+EXPORT_SYMBOL vmlinux 0xcb4693f7	gnet_stats_copy_app
+EXPORT_SYMBOL vmlinux 0xcb6beb40	hweight32
+EXPORT_SYMBOL vmlinux 0xcb7131fb	fb_get_options
+EXPORT_SYMBOL vmlinux 0xcba65843	rtnl_create_link
+EXPORT_SYMBOL vmlinux 0xcbb9d7db	groups_free
+EXPORT_SYMBOL vmlinux 0xcbe3f1c2	inet_ioctl
+EXPORT_SYMBOL vmlinux 0xcbfc18db	phy_mii_ioctl
+EXPORT_SYMBOL vmlinux 0xcc07af75	strnlen
+EXPORT_SYMBOL vmlinux 0xcc1a9967	netif_napi_del
+EXPORT_SYMBOL vmlinux 0xcc209072	log_start_commit
+EXPORT_SYMBOL vmlinux 0xcc248d26	serial8250_suspend_port
+EXPORT_SYMBOL vmlinux 0xcc36f32e	fb_unregister_client
+EXPORT_SYMBOL vmlinux 0xcc5005fe	msleep_interruptible
+EXPORT_SYMBOL vmlinux 0xcc51ee50	dma_spin_lock
+EXPORT_SYMBOL vmlinux 0xcc52d4e8	rwsem_down_read_failed
+EXPORT_SYMBOL vmlinux 0xcc7fa952	local_bh_enable_ip
+EXPORT_SYMBOL vmlinux 0xcca8d428	bioset_free
+EXPORT_SYMBOL vmlinux 0xccb15855	__kfree_skb
+EXPORT_SYMBOL vmlinux 0xccee4d68	xen_multicall_flush
+EXPORT_SYMBOL vmlinux 0xcd145b3e	dst_destroy
+EXPORT_SYMBOL vmlinux 0xcd19e8ab	cad_pid
+EXPORT_SYMBOL vmlinux 0xcd223e0f	xfrm_state_insert
+EXPORT_SYMBOL vmlinux 0xcd255d5e	kernel_read
+EXPORT_SYMBOL vmlinux 0xcd77289f	__break_lease
+EXPORT_SYMBOL vmlinux 0xcd86cd8e	test_set_page_writeback
+EXPORT_SYMBOL vmlinux 0xcdbc5d1e	cpu_sysdev_class
+EXPORT_SYMBOL vmlinux 0xcde29d34	tcp_disconnect
+EXPORT_SYMBOL vmlinux 0xce36ded6	sysctl_tcp_mem
+EXPORT_SYMBOL vmlinux 0xce5ac24f	zlib_inflate_workspacesize
+EXPORT_SYMBOL vmlinux 0xceae0354	mark_buffer_dirty
+EXPORT_SYMBOL vmlinux 0xcec5f692	set_page_dirty
+EXPORT_SYMBOL vmlinux 0xcef740c7	pagevec_lookup
+EXPORT_SYMBOL vmlinux 0xcefcd99a	serial8250_unregister_port
+EXPORT_SYMBOL vmlinux 0xcf0e3e2e	bio_integrity_enabled
+EXPORT_SYMBOL vmlinux 0xcf13604b	direct_remap_pfn_range
+EXPORT_SYMBOL vmlinux 0xcf1973f6	__neigh_event_send
+EXPORT_SYMBOL vmlinux 0xcf46aa7b	kill_pid
+EXPORT_SYMBOL vmlinux 0xcf4b1887	xfrm_policy_insert
+EXPORT_SYMBOL vmlinux 0xcf54e777	inet_frag_evictor
+EXPORT_SYMBOL vmlinux 0xcf5c909a	skb_find_text
+EXPORT_SYMBOL vmlinux 0xcf6cfe1f	msrs_free
+EXPORT_SYMBOL vmlinux 0xcfadd723	__percpu_counter_add
+EXPORT_SYMBOL vmlinux 0xcfb9006e	jiffies_to_timeval
+EXPORT_SYMBOL vmlinux 0xcfdd2ed1	register_filesystem
+EXPORT_SYMBOL vmlinux 0xcff53400	kref_put
+EXPORT_SYMBOL vmlinux 0xd0181f4f	__bitmap_xor
+EXPORT_SYMBOL vmlinux 0xd03c7ffd	revalidate_disk
+EXPORT_SYMBOL vmlinux 0xd05d03b7	swiotlb_map_sg_attrs
+EXPORT_SYMBOL vmlinux 0xd0749716	release_firmware
+EXPORT_SYMBOL vmlinux 0xd0bcd175	submit_bio
+EXPORT_SYMBOL vmlinux 0xd0d05b68	vlan_gro_receive
+EXPORT_SYMBOL vmlinux 0xd0e9cf26	insert_inode_locked
+EXPORT_SYMBOL vmlinux 0xd0ee38b8	schedule_timeout_uninterruptible
+EXPORT_SYMBOL vmlinux 0xd1103eb7	d_instantiate
+EXPORT_SYMBOL vmlinux 0xd168839a	tcp_getsockopt
+EXPORT_SYMBOL vmlinux 0xd19c77cc	pcim_iomap_regions
+EXPORT_SYMBOL vmlinux 0xd1a79a1b	bio_integrity_alloc_bioset
+EXPORT_SYMBOL vmlinux 0xd1f91bcd	dev_base_lock
+EXPORT_SYMBOL vmlinux 0xd21d2cec	inet_csk_delete_keepalive_timer
+EXPORT_SYMBOL vmlinux 0xd21f68ca	clocksource_change_rating
+EXPORT_SYMBOL vmlinux 0xd251d7b0	security_socket_getpeersec_dgram
+EXPORT_SYMBOL vmlinux 0xd2555f19	jiffies_64_to_clock_t
+EXPORT_SYMBOL vmlinux 0xd259d08b	pci_release_selected_regions
+EXPORT_SYMBOL vmlinux 0xd25d4f74	console_blank_hook
+EXPORT_SYMBOL vmlinux 0xd267d42c	down_killable
+EXPORT_SYMBOL vmlinux 0xd2705c01	blk_queue_max_sectors
+EXPORT_SYMBOL vmlinux 0xd2919a9c	init_net
+EXPORT_SYMBOL vmlinux 0xd2965f6f	kthread_should_stop
+EXPORT_SYMBOL vmlinux 0xd29d50f7	load_nls_default
+EXPORT_SYMBOL vmlinux 0xd2a639d4	posix_unblock_lock
+EXPORT_SYMBOL vmlinux 0xd2d1e8cd	dmam_pool_create
+EXPORT_SYMBOL vmlinux 0xd2ecc463	skb_pad
+EXPORT_SYMBOL vmlinux 0xd3196d52	blk_queue_stack_limits
+EXPORT_SYMBOL vmlinux 0xd32c9bb0	sock_release
+EXPORT_SYMBOL vmlinux 0xd34f0c62	gen_pool_create
+EXPORT_SYMBOL vmlinux 0xd3657dc0	qdisc_list_del
+EXPORT_SYMBOL vmlinux 0xd3776e22	disk_stack_limits
+EXPORT_SYMBOL vmlinux 0xd3af979c	memdup_user
+EXPORT_SYMBOL vmlinux 0xd3c8bdad	tcp_timewait_state_process
+EXPORT_SYMBOL vmlinux 0xd3f74cf1	interruptible_sleep_on_timeout
+EXPORT_SYMBOL vmlinux 0xd42b7232	_write_unlock_bh
+EXPORT_SYMBOL vmlinux 0xd42bf722	llc_sap_close
+EXPORT_SYMBOL vmlinux 0xd44cc2fa	__nla_reserve_nohdr
+EXPORT_SYMBOL vmlinux 0xd454b256	__scm_destroy
+EXPORT_SYMBOL vmlinux 0xd4752347	sock_no_ioctl
+EXPORT_SYMBOL vmlinux 0xd48d49ac	vm_insert_pfn
+EXPORT_SYMBOL vmlinux 0xd4cab1ec	uart_add_one_port
+EXPORT_SYMBOL vmlinux 0xd4dbddb1	__nla_put
+EXPORT_SYMBOL vmlinux 0xd4edd8d5	arp_send
+EXPORT_SYMBOL vmlinux 0xd5027718	ppp_unregister_channel
+EXPORT_SYMBOL vmlinux 0xd5153082	console_stop
+EXPORT_SYMBOL vmlinux 0xd518f820	tty_port_raise_dtr_rts
+EXPORT_SYMBOL vmlinux 0xd5263820	mb_cache_destroy
+EXPORT_SYMBOL vmlinux 0xd5401557	sync_inode
+EXPORT_SYMBOL vmlinux 0xd569b4fd	tcp_mtup_init
+EXPORT_SYMBOL vmlinux 0xd57f8789	iommu_num_pages
+EXPORT_SYMBOL vmlinux 0xd5869593	pci_dev_get
+EXPORT_SYMBOL vmlinux 0xd5a93ed2	simple_set_mnt
+EXPORT_SYMBOL vmlinux 0xd5c7c61d	sysctl_string
+EXPORT_SYMBOL vmlinux 0xd5cfe779	nf_unregister_hook
+EXPORT_SYMBOL vmlinux 0xd60c08b0	bio_integrity_clone
+EXPORT_SYMBOL vmlinux 0xd60d7af4	ida_remove
+EXPORT_SYMBOL vmlinux 0xd62c833f	schedule_timeout
+EXPORT_SYMBOL vmlinux 0xd62ca79b	set_pages_array_uc
+EXPORT_SYMBOL vmlinux 0xd66555d8	jbd2_journal_release_buffer
+EXPORT_SYMBOL vmlinux 0xd66f2a6f	__breadahead
+EXPORT_SYMBOL vmlinux 0xd6890237	dquot_scan_active
+EXPORT_SYMBOL vmlinux 0xd6a78d08	smp_call_function_single
+EXPORT_SYMBOL vmlinux 0xd6adcb94	find_get_pages_contig
+EXPORT_SYMBOL vmlinux 0xd6b33026	cpu_khz
+EXPORT_SYMBOL vmlinux 0xd6b39dad	pagecache_write_begin
+EXPORT_SYMBOL vmlinux 0xd6ce6a6e	genl_register_family_with_ops
+EXPORT_SYMBOL vmlinux 0xd6d68c6b	vm_stat
+EXPORT_SYMBOL vmlinux 0xd6ee688f	vmalloc
+EXPORT_SYMBOL vmlinux 0xd70881a6	bdi_register_dev
+EXPORT_SYMBOL vmlinux 0xd710e687	blk_queue_segment_boundary
+EXPORT_SYMBOL vmlinux 0xd736a40b	tty_register_ldisc
+EXPORT_SYMBOL vmlinux 0xd74a9e08	journal_init_inode
+EXPORT_SYMBOL vmlinux 0xd75a233e	override_creds
+EXPORT_SYMBOL vmlinux 0xd7759dde	llc_sap_open
+EXPORT_SYMBOL vmlinux 0xd77a5aa5	__bitmap_and
+EXPORT_SYMBOL vmlinux 0xd79b5a02	allow_signal
+EXPORT_SYMBOL vmlinux 0xd7a6fafa	panic_notifier_list
+EXPORT_SYMBOL vmlinux 0xd7a86780	generic_file_aio_read
+EXPORT_SYMBOL vmlinux 0xd7cc84c8	dma_supported
+EXPORT_SYMBOL vmlinux 0xd82c2ef9	set_anon_super
+EXPORT_SYMBOL vmlinux 0xd83791bc	nf_conntrack_destroy
+EXPORT_SYMBOL vmlinux 0xd846056f	xen_spin_kick
+EXPORT_SYMBOL vmlinux 0xd84fcc2f	blk_init_queue
+EXPORT_SYMBOL vmlinux 0xd851af78	up_write
+EXPORT_SYMBOL vmlinux 0xd87da739	linkwatch_fire_event
+EXPORT_SYMBOL vmlinux 0xd89da37f	movable_zone
+EXPORT_SYMBOL vmlinux 0xd8ab3c96	vfs_quota_on_mount
+EXPORT_SYMBOL vmlinux 0xd8c14c2e	kmem_cache_free
+EXPORT_SYMBOL vmlinux 0xd8d93950	compat_sock_common_getsockopt
+EXPORT_SYMBOL vmlinux 0xd8dd6a57	__set_page_dirty_nobuffers
+EXPORT_SYMBOL vmlinux 0xd8e484f0	register_chrdev_region
+EXPORT_SYMBOL vmlinux 0xd92e3d96	set_irq_chip
+EXPORT_SYMBOL vmlinux 0xd9454f58	napi_frags_skb
+EXPORT_SYMBOL vmlinux 0xd985dc99	mempool_free_pages
+EXPORT_SYMBOL vmlinux 0xd98b0722	pci_get_bus_and_slot
+EXPORT_SYMBOL vmlinux 0xd98ead4d	pci_try_set_mwi
+EXPORT_SYMBOL vmlinux 0xd9b0736f	hippi_change_mtu
+EXPORT_SYMBOL vmlinux 0xd9ff8b32	phy_connect_direct
+EXPORT_SYMBOL vmlinux 0xda1463e1	kern_path
+EXPORT_SYMBOL vmlinux 0xda1a7335	kasprintf
+EXPORT_SYMBOL vmlinux 0xda27e12e	uart_update_timeout
+EXPORT_SYMBOL vmlinux 0xda4629e4	radix_tree_insert
+EXPORT_SYMBOL vmlinux 0xda520178	vga_get
+EXPORT_SYMBOL vmlinux 0xda7ca6cb	fb_mode_is_equal
+EXPORT_SYMBOL vmlinux 0xda8af7ad	fb_find_nearest_mode
+EXPORT_SYMBOL vmlinux 0xdae0e018	simple_dir_inode_operations
+EXPORT_SYMBOL vmlinux 0xdb140367	__secpath_destroy
+EXPORT_SYMBOL vmlinux 0xdb8b25b8	mutex_unlock
+EXPORT_SYMBOL vmlinux 0xdb92018a	page_follow_link_light
+EXPORT_SYMBOL vmlinux 0xdb9aa476	skb_pull
+EXPORT_SYMBOL vmlinux 0xdbcd416e	sysctl_ip_nonlocal_bind
+EXPORT_SYMBOL vmlinux 0xdbf3dea2	jbd2_journal_flush
+EXPORT_SYMBOL vmlinux 0xdc053205	udp_memory_allocated
+EXPORT_SYMBOL vmlinux 0xdc14eda7	pci_pci_problems
+EXPORT_SYMBOL vmlinux 0xdc22801f	seq_putc
+EXPORT_SYMBOL vmlinux 0xdc2adb35	add_taint
+EXPORT_SYMBOL vmlinux 0xdc39686b	llc_add_pack
+EXPORT_SYMBOL vmlinux 0xdc43a9c8	daemonize
+EXPORT_SYMBOL vmlinux 0xdc873a70	screen_info
+EXPORT_SYMBOL vmlinux 0xdca0e950	genl_register_family
+EXPORT_SYMBOL vmlinux 0xdcb0349b	sys_close
+EXPORT_SYMBOL vmlinux 0xdcb54aad	udp_poll
+EXPORT_SYMBOL vmlinux 0xdcc97c97	config_group_init_type_name
+EXPORT_SYMBOL vmlinux 0xdcca62b3	pci_unmap_rom
+EXPORT_SYMBOL vmlinux 0xdd7370c6	f_setown
+EXPORT_SYMBOL vmlinux 0xdd89c90e	inet_stream_ops
+EXPORT_SYMBOL vmlinux 0xdd9d7f09	phy_attach_direct
+EXPORT_SYMBOL vmlinux 0xdda68476	iw_handler_set_spy
+EXPORT_SYMBOL vmlinux 0xddd542fa	tcf_exts_validate
+EXPORT_SYMBOL vmlinux 0xddf0f809	register_cdrom
+EXPORT_SYMBOL vmlinux 0xddff53a9	alloc_buffer_head
+EXPORT_SYMBOL vmlinux 0xde0bdcff	memset
+EXPORT_SYMBOL vmlinux 0xde0c852e	key_alloc
+EXPORT_SYMBOL vmlinux 0xde2c2009	jbd2_journal_extend
+EXPORT_SYMBOL vmlinux 0xde31b902	blk_limits_io_opt
+EXPORT_SYMBOL vmlinux 0xde75b689	set_irq_type
+EXPORT_SYMBOL vmlinux 0xde76e81b	request_key_with_auxdata
+EXPORT_SYMBOL vmlinux 0xde9360ba	totalram_pages
+EXPORT_SYMBOL vmlinux 0xdedf7655	pci_bus_write_config_dword
+EXPORT_SYMBOL vmlinux 0xdf02ce6d	input_allocate_device
+EXPORT_SYMBOL vmlinux 0xdf4c8767	ns_to_timeval
+EXPORT_SYMBOL vmlinux 0xdf60cc27	__print_symbol
+EXPORT_SYMBOL vmlinux 0xdf670fec	block_write_end
+EXPORT_SYMBOL vmlinux 0xdf7bd868	vfs_write
+EXPORT_SYMBOL vmlinux 0xdf857733	skb_push
+EXPORT_SYMBOL vmlinux 0xdf8c695a	__ndelay
+EXPORT_SYMBOL vmlinux 0xdf90990b	path_put
+EXPORT_SYMBOL vmlinux 0xdf929370	fs_overflowgid
+EXPORT_SYMBOL vmlinux 0xdf9fae65	pci_choose_state
+EXPORT_SYMBOL vmlinux 0xdfa95a27	textsearch_unregister
+EXPORT_SYMBOL vmlinux 0xdfc5169b	slhc_init
+EXPORT_SYMBOL vmlinux 0xdfc6defd	ethtool_op_get_tx_csum
+EXPORT_SYMBOL vmlinux 0xe007bb43	napi_complete
+EXPORT_SYMBOL vmlinux 0xe075d6eb	iter_div_u64_rem
+EXPORT_SYMBOL vmlinux 0xe07e7e53	skb_prepare_seq_read
+EXPORT_SYMBOL vmlinux 0xe09c95d0	bio_get_nr_vecs
+EXPORT_SYMBOL vmlinux 0xe0b13336	argv_free
+EXPORT_SYMBOL vmlinux 0xe0bc24a1	param_set_ushort
+EXPORT_SYMBOL vmlinux 0xe0dc58f6	mnt_pin
+EXPORT_SYMBOL vmlinux 0xe0fa3add	filemap_write_and_wait
+EXPORT_SYMBOL vmlinux 0xe10ecae5	per_cpu__softnet_data
+EXPORT_SYMBOL vmlinux 0xe113bbbc	csum_partial
+EXPORT_SYMBOL vmlinux 0xe114c8df	ilookup5
+EXPORT_SYMBOL vmlinux 0xe11a72bc	dcache_dir_close
+EXPORT_SYMBOL vmlinux 0xe11f4983	netfront_check_queue_ready
+EXPORT_SYMBOL vmlinux 0xe124fb43	dev_get_flags
+EXPORT_SYMBOL vmlinux 0xe1405ad9	journal_stop
+EXPORT_SYMBOL vmlinux 0xe1476695	netlink_kernel_create
+EXPORT_SYMBOL vmlinux 0xe1761617	security_inet_conn_request
+EXPORT_SYMBOL vmlinux 0xe1953444	jbd2_log_wait_commit
+EXPORT_SYMBOL vmlinux 0xe1e06479	gnet_stats_start_copy
+EXPORT_SYMBOL vmlinux 0xe1e7e43e	security_file_permission
+EXPORT_SYMBOL vmlinux 0xe1fd57b6	ps2_end_command
+EXPORT_SYMBOL vmlinux 0xe23539a2	blkdev_get
+EXPORT_SYMBOL vmlinux 0xe23ae481	blk_iopoll_complete
+EXPORT_SYMBOL vmlinux 0xe23d7acb	up_read
+EXPORT_SYMBOL vmlinux 0xe24050c7	scnprintf
+EXPORT_SYMBOL vmlinux 0xe24d3a97	jiffies_64
+EXPORT_SYMBOL vmlinux 0xe2715dbd	kernel_connect
+EXPORT_SYMBOL vmlinux 0xe2947db7	generic_read_dir
+EXPORT_SYMBOL vmlinux 0xe2a25a02	qdisc_class_hash_grow
+EXPORT_SYMBOL vmlinux 0xe2d5255a	strcmp
+EXPORT_SYMBOL vmlinux 0xe2f6bca1	arch_debugfs_dir
+EXPORT_SYMBOL vmlinux 0xe30ae705	bd_set_size
+EXPORT_SYMBOL vmlinux 0xe31de36f	n_tty_ioctl_helper
+EXPORT_SYMBOL vmlinux 0xe3227ffc	jbd2_journal_clear_features
+EXPORT_SYMBOL vmlinux 0xe335aaa6	dec_zone_page_state
+EXPORT_SYMBOL vmlinux 0xe38e8646	iov_iter_copy_from_user
+EXPORT_SYMBOL vmlinux 0xe3b0192b	vscnprintf
+EXPORT_SYMBOL vmlinux 0xe3b194e2	neigh_resolve_output
+EXPORT_SYMBOL vmlinux 0xe3df4fda	vfs_rename
+EXPORT_SYMBOL vmlinux 0xe3ea7846	xfrm_user_policy
+EXPORT_SYMBOL vmlinux 0xe3edbc72	d_splice_alias
+EXPORT_SYMBOL vmlinux 0xe3fc2516	d_move
+EXPORT_SYMBOL vmlinux 0xe4495244	registered_fb
+EXPORT_SYMBOL vmlinux 0xe44e62f9	xfrm_prepare_input
+EXPORT_SYMBOL vmlinux 0xe456bd3a	complete
+EXPORT_SYMBOL vmlinux 0xe484e35f	ioread32
+EXPORT_SYMBOL vmlinux 0xe4870354	_read_trylock
+EXPORT_SYMBOL vmlinux 0xe4913fa3	pci_set_power_state
+EXPORT_SYMBOL vmlinux 0xe4ab5cf9	simple_fill_super
+EXPORT_SYMBOL vmlinux 0xe4b24b8c	__next_cpu
+EXPORT_SYMBOL vmlinux 0xe4bfbe84	get_disk
+EXPORT_SYMBOL vmlinux 0xe4c1df3e	_read_lock_bh
+EXPORT_SYMBOL vmlinux 0xe4ddd810	audit_log_end
+EXPORT_SYMBOL vmlinux 0xe4ea2f2b	ppp_input_error
+EXPORT_SYMBOL vmlinux 0xe4f1695e	cookie_check_timestamp
+EXPORT_SYMBOL vmlinux 0xe4fe3441	journal_check_used_features
+EXPORT_SYMBOL vmlinux 0xe5179c3b	path_lookup
+EXPORT_SYMBOL vmlinux 0xe51c44c7	bio_endio
+EXPORT_SYMBOL vmlinux 0xe523ad75	synchronize_irq
+EXPORT_SYMBOL vmlinux 0xe52947e7	__phys_addr
+EXPORT_SYMBOL vmlinux 0xe53b6006	atm_dev_lookup
+EXPORT_SYMBOL vmlinux 0xe57878a1	in6_pton
+EXPORT_SYMBOL vmlinux 0xe58366ab	blk_alloc_queue
+EXPORT_SYMBOL vmlinux 0xe5867808	dlci_ioctl_set
+EXPORT_SYMBOL vmlinux 0xe58b7e5c	cdrom_mode_sense
+EXPORT_SYMBOL vmlinux 0xe5a60609	ppp_unregister_compressor
+EXPORT_SYMBOL vmlinux 0xe5c78a99	do_blank_screen
+EXPORT_SYMBOL vmlinux 0xe5ed5467	xfrm_policy_walk_init
+EXPORT_SYMBOL vmlinux 0xe5f0311e	alloc_tty_driver
+EXPORT_SYMBOL vmlinux 0xe5fbd3fa	call_usermodehelper_stdinpipe
+EXPORT_SYMBOL vmlinux 0xe614d07b	lock_rename
+EXPORT_SYMBOL vmlinux 0xe62ae546	d_alloc_name
+EXPORT_SYMBOL vmlinux 0xe630603a	dm_table_get_size
+EXPORT_SYMBOL vmlinux 0xe63c2f24	mdiobus_unregister
+EXPORT_SYMBOL vmlinux 0xe64be8cc	install_exec_creds
+EXPORT_SYMBOL vmlinux 0xe697d108	__blk_iopoll_complete
+EXPORT_SYMBOL vmlinux 0xe6ab3577	remove_inode_hash
+EXPORT_SYMBOL vmlinux 0xe6e3ef70	machine_restart
+EXPORT_SYMBOL vmlinux 0xe6f908c5	mb_cache_entry_find_next
+EXPORT_SYMBOL vmlinux 0xe6fbe430	can_do_mlock
+EXPORT_SYMBOL vmlinux 0xe70ad31b	nobh_write_end
+EXPORT_SYMBOL vmlinux 0xe714375c	__tasklet_hi_schedule_first
+EXPORT_SYMBOL vmlinux 0xe780e761	proc_create_data
+EXPORT_SYMBOL vmlinux 0xe786168c	rwsem_down_write_failed
+EXPORT_SYMBOL vmlinux 0xe79af279	bfifo_qdisc_ops
+EXPORT_SYMBOL vmlinux 0xe7a36a49	dma_set_mask
+EXPORT_SYMBOL vmlinux 0xe7b04781	pci_setup_cardbus
+EXPORT_SYMBOL vmlinux 0xe7c21f49	__nla_put_nohdr
+EXPORT_SYMBOL vmlinux 0xe7d2aca1	security_sk_classify_flow
+EXPORT_SYMBOL vmlinux 0xe7d4daac	seq_list_next
+EXPORT_SYMBOL vmlinux 0xe7d71b60	generic_file_mmap
+EXPORT_SYMBOL vmlinux 0xe7f7115e	xen_tlb_flush
+EXPORT_SYMBOL vmlinux 0xe8091096	phy_register_fixup_for_id
+EXPORT_SYMBOL vmlinux 0xe817e88f	phy_device_free
+EXPORT_SYMBOL vmlinux 0xe82692c0	dev_getbyhwaddr
+EXPORT_SYMBOL vmlinux 0xe868511d	xfrm_policy_register_afinfo
+EXPORT_SYMBOL vmlinux 0xe86c6af8	get_unmapped_area_prot
+EXPORT_SYMBOL vmlinux 0xe8794ce1	slhc_toss
+EXPORT_SYMBOL vmlinux 0xe8930dac	udp_sendmsg
+EXPORT_SYMBOL vmlinux 0xe8cd902e	hweight16
+EXPORT_SYMBOL vmlinux 0xe8dc664b	napi_gro_receive
+EXPORT_SYMBOL vmlinux 0xe8e0145b	get_write_access
+EXPORT_SYMBOL vmlinux 0xe90dcae0	__request_module
+EXPORT_SYMBOL vmlinux 0xe914e41e	strcpy
+EXPORT_SYMBOL vmlinux 0xe9266926	request_key
+EXPORT_SYMBOL vmlinux 0xe940cebd	filemap_flush
+EXPORT_SYMBOL vmlinux 0xe9477932	phy_register_fixup
+EXPORT_SYMBOL vmlinux 0xe997667b	wrmsr_on_cpu
+EXPORT_SYMBOL vmlinux 0xe99cb841	set_pages_array_wb
+EXPORT_SYMBOL vmlinux 0xe9b6234b	ip_generic_getfrag
+EXPORT_SYMBOL vmlinux 0xea01e81c	tty_insert_flip_string
+EXPORT_SYMBOL vmlinux 0xea0524da	iw_handler_get_thrspy
+EXPORT_SYMBOL vmlinux 0xea054b22	nla_policy_len
+EXPORT_SYMBOL vmlinux 0xea093f4c	splice_direct_to_actor
+EXPORT_SYMBOL vmlinux 0xea10655a	__bitmap_intersects
+EXPORT_SYMBOL vmlinux 0xea147363	printk
+EXPORT_SYMBOL vmlinux 0xea2d4dcc	pci_bus_read_config_word
+EXPORT_SYMBOL vmlinux 0xea50a498	textsearch_destroy
+EXPORT_SYMBOL vmlinux 0xea69cde6	inet_shutdown
+EXPORT_SYMBOL vmlinux 0xea6f62d2	genphy_restart_aneg
+EXPORT_SYMBOL vmlinux 0xea96bba2	dquot_destroy
+EXPORT_SYMBOL vmlinux 0xead58fb9	print_hex_dump
+EXPORT_SYMBOL vmlinux 0xeae3dfd6	__const_udelay
+EXPORT_SYMBOL vmlinux 0xeaeb6185	tcp_md5_hash_skb_data
+EXPORT_SYMBOL vmlinux 0xeafe7c5e	inet_unregister_protosw
+EXPORT_SYMBOL vmlinux 0xeb1fabf6	interruptible_sleep_on
+EXPORT_SYMBOL vmlinux 0xeb36ceca	con_copy_unimap
+EXPORT_SYMBOL vmlinux 0xeb41a70e	simple_pin_fs
+EXPORT_SYMBOL vmlinux 0xeb8b0aa2	register_tcf_proto_ops
+EXPORT_SYMBOL vmlinux 0xeb8f54b3	strstrip
+EXPORT_SYMBOL vmlinux 0xebbf1dba	strncasecmp
+EXPORT_SYMBOL vmlinux 0xebca6257	pipe_unlock
+EXPORT_SYMBOL vmlinux 0xebd273a6	strict_strtoull
+EXPORT_SYMBOL vmlinux 0xec17caff	simple_dir_operations
+EXPORT_SYMBOL vmlinux 0xec4fc939	pci_add_new_bus
+EXPORT_SYMBOL vmlinux 0xec5208ba	dev_set_promiscuity
+EXPORT_SYMBOL vmlinux 0xec681b61	kernel_listen
+EXPORT_SYMBOL vmlinux 0xec794ba0	__send_remote_softirq
+EXPORT_SYMBOL vmlinux 0xec883eff	jbd2_journal_force_commit
+EXPORT_SYMBOL vmlinux 0xecc3d892	secpath_dup
+EXPORT_SYMBOL vmlinux 0xecc5e223	fifo_create_dflt
+EXPORT_SYMBOL vmlinux 0xecd661f6	genl_unregister_ops
+EXPORT_SYMBOL vmlinux 0xecdc8e10	sock_sendmsg
+EXPORT_SYMBOL vmlinux 0xecde1418	_spin_lock_irq
+EXPORT_SYMBOL vmlinux 0xed009db2	get_sb_single
+EXPORT_SYMBOL vmlinux 0xed5bee2a	task_nice
+EXPORT_SYMBOL vmlinux 0xed6e62a0	lro_receive_frags
+EXPORT_SYMBOL vmlinux 0xed8e5efb	bioset_integrity_create
+EXPORT_SYMBOL vmlinux 0xeda0d76e	gen_estimator_active
+EXPORT_SYMBOL vmlinux 0xedbaee5e	nla_strcmp
+EXPORT_SYMBOL vmlinux 0xedc03953	iounmap
+EXPORT_SYMBOL vmlinux 0xeddf5cb3	sk_reset_timer
+EXPORT_SYMBOL vmlinux 0xede0ca26	tty_check_change
+EXPORT_SYMBOL vmlinux 0xede13cd5	lookup_bdev
+EXPORT_SYMBOL vmlinux 0xedf38662	wireless_spy_update
+EXPORT_SYMBOL vmlinux 0xee2d0fc7	_local_bh_enable
+EXPORT_SYMBOL vmlinux 0xee3eb8c9	jbd2_journal_start_commit
+EXPORT_SYMBOL vmlinux 0xee3f093d	send_sig_info
+EXPORT_SYMBOL vmlinux 0xee53aded	bio_alloc_bioset
+EXPORT_SYMBOL vmlinux 0xeea9dbaf	bitmap_bitremap
+EXPORT_SYMBOL vmlinux 0xeead0c6c	arp_xmit
+EXPORT_SYMBOL vmlinux 0xeebcd34e	pci_get_slot
+EXPORT_SYMBOL vmlinux 0xeecfc7ab	locks_remove_posix
+EXPORT_SYMBOL vmlinux 0xeeddf002	misc_register
+EXPORT_SYMBOL vmlinux 0xeeef07a3	tcp_sendpage
+EXPORT_SYMBOL vmlinux 0xef060a13	pci_bus_alloc_resource
+EXPORT_SYMBOL vmlinux 0xef390532	scm_fp_dup
+EXPORT_SYMBOL vmlinux 0xef625f68	blk_end_request_all
+EXPORT_SYMBOL vmlinux 0xef6cc213	blk_queue_dma_pad
+EXPORT_SYMBOL vmlinux 0xef6ed1ba	param_set_invbool
+EXPORT_SYMBOL vmlinux 0xef82287f	mpage_readpages
+EXPORT_SYMBOL vmlinux 0xef9aedfc	boot_option_idle_override
+EXPORT_SYMBOL vmlinux 0xefaad159	pci_get_subsys
+EXPORT_SYMBOL vmlinux 0xefd51414	xfrm_state_update
+EXPORT_SYMBOL vmlinux 0xefdd70ce	security_secid_to_secctx
+EXPORT_SYMBOL vmlinux 0xefefecbb	single_release
+EXPORT_SYMBOL vmlinux 0xf0009fee	put_pages_list
+EXPORT_SYMBOL vmlinux 0xf0141002	blk_queue_start_tag
+EXPORT_SYMBOL vmlinux 0xf01a9f19	input_unfilter_device
+EXPORT_SYMBOL vmlinux 0xf0221e2c	ps2_handle_response
+EXPORT_SYMBOL vmlinux 0xf029ba14	vfs_quota_off
+EXPORT_SYMBOL vmlinux 0xf0347ba2	seq_write
+EXPORT_SYMBOL vmlinux 0xf05c87e2	inode_init_always
+EXPORT_SYMBOL vmlinux 0xf065f629	ioread16be
+EXPORT_SYMBOL vmlinux 0xf0af5883	blk_queue_physical_block_size
+EXPORT_SYMBOL vmlinux 0xf0d0e38c	neigh_create
+EXPORT_SYMBOL vmlinux 0xf0edefc8	fsync_bdev
+EXPORT_SYMBOL vmlinux 0xf0ef15b4	list_sort
+EXPORT_SYMBOL vmlinux 0xf0f1246c	kvasprintf
+EXPORT_SYMBOL vmlinux 0xf0fdf6cb	__stack_chk_fail
+EXPORT_SYMBOL vmlinux 0xf10de535	ioread8
+EXPORT_SYMBOL vmlinux 0xf11543ff	find_first_zero_bit
+EXPORT_SYMBOL vmlinux 0xf116d4b5	copy_in_user
+EXPORT_SYMBOL vmlinux 0xf1376c2a	skb_put
+EXPORT_SYMBOL vmlinux 0xf164e867	blk_queue_update_dma_alignment
+EXPORT_SYMBOL vmlinux 0xf174ed48	acquire_console_sem
+EXPORT_SYMBOL vmlinux 0xf17daa0f	fput
+EXPORT_SYMBOL vmlinux 0xf195c682	fb_invert_cmaps
+EXPORT_SYMBOL vmlinux 0xf1add801	zero_fill_bio
+EXPORT_SYMBOL vmlinux 0xf1b52a67	__alloc_pages_nodemask
+EXPORT_SYMBOL vmlinux 0xf1c0d9d5	may_umount
+EXPORT_SYMBOL vmlinux 0xf1d64416	gen_new_estimator
+EXPORT_SYMBOL vmlinux 0xf1db1704	nla_memcpy
+EXPORT_SYMBOL vmlinux 0xf1e98c74	avenrun
+EXPORT_SYMBOL vmlinux 0xf1f604ac	tcp_hashinfo
+EXPORT_SYMBOL vmlinux 0xf1ff2b2a	phy_ethtool_sset
+EXPORT_SYMBOL vmlinux 0xf20dabd8	free_irq
+EXPORT_SYMBOL vmlinux 0xf21e6f27	register_8022_client
+EXPORT_SYMBOL vmlinux 0xf2568eb3	netpoll_send_udp
+EXPORT_SYMBOL vmlinux 0xf2716ffc	mb_cache_entry_insert
+EXPORT_SYMBOL vmlinux 0xf2997713	tty_termios_hw_change
+EXPORT_SYMBOL vmlinux 0xf2a7743d	tty_port_tty_get
+EXPORT_SYMBOL vmlinux 0xf2cc35af	lookup_one_len
+EXPORT_SYMBOL vmlinux 0xf2d0f562	phy_start
+EXPORT_SYMBOL vmlinux 0xf2dc2407	per_cpu__xen_lazy_mmu
+EXPORT_SYMBOL vmlinux 0xf302bca2	__netif_schedule
+EXPORT_SYMBOL vmlinux 0xf313da4e	sha_transform
+EXPORT_SYMBOL vmlinux 0xf31f226b	key_unlink
+EXPORT_SYMBOL vmlinux 0xf32d8d41	consume_skb
+EXPORT_SYMBOL vmlinux 0xf3341268	__clear_user
+EXPORT_SYMBOL vmlinux 0xf338d4c3	netlink_unregister_notifier
+EXPORT_SYMBOL vmlinux 0xf346231f	seq_list_start_head
+EXPORT_SYMBOL vmlinux 0xf350afad	pci_assign_resource
+EXPORT_SYMBOL vmlinux 0xf37555e4	kthread_create
+EXPORT_SYMBOL vmlinux 0xf3915735	tty_register_driver
+EXPORT_SYMBOL vmlinux 0xf397b9aa	__tasklet_schedule
+EXPORT_SYMBOL vmlinux 0xf3af6e67	w1_register_family
+EXPORT_SYMBOL vmlinux 0xf3b8f830	free_task
+EXPORT_SYMBOL vmlinux 0xf3bc9a9b	file_remove_suid
+EXPORT_SYMBOL vmlinux 0xf3bf0bce	__bitmap_complement
+EXPORT_SYMBOL vmlinux 0xf3e31b65	vfs_quota_on_path
+EXPORT_SYMBOL vmlinux 0xf3fff232	dcache_dir_lseek
+EXPORT_SYMBOL vmlinux 0xf441ac43	ioread8_rep
+EXPORT_SYMBOL vmlinux 0xf44715d7	sk_stream_kill_queues
+EXPORT_SYMBOL vmlinux 0xf464430d	llc_mac_hdr_init
+EXPORT_SYMBOL vmlinux 0xf49bc67a	atm_pcr_goal
+EXPORT_SYMBOL vmlinux 0xf4a5efeb	phy_start_aneg
+EXPORT_SYMBOL vmlinux 0xf4b28a23	block_truncate_page
+EXPORT_SYMBOL vmlinux 0xf4dc97ef	dev_gro_receive
+EXPORT_SYMBOL vmlinux 0xf4de4f00	key_revoke
+EXPORT_SYMBOL vmlinux 0xf4f14de6	rtnl_trylock
+EXPORT_SYMBOL vmlinux 0xf4f52f93	dqstats
+EXPORT_SYMBOL vmlinux 0xf4fa8f84	eth_header_parse
+EXPORT_SYMBOL vmlinux 0xf4fccc71	sync_dirty_buffer
+EXPORT_SYMBOL vmlinux 0xf529dad4	set_user_nice
+EXPORT_SYMBOL vmlinux 0xf53d4c26	qdisc_class_hash_destroy
+EXPORT_SYMBOL vmlinux 0xf546e169	remove_arg_zero
+EXPORT_SYMBOL vmlinux 0xf58220f3	__xfrm_policy_check
+EXPORT_SYMBOL vmlinux 0xf5c9012e	timespec_trunc
+EXPORT_SYMBOL vmlinux 0xf5eb86ea	blk_verify_command
+EXPORT_SYMBOL vmlinux 0xf618af42	blk_put_request
+EXPORT_SYMBOL vmlinux 0xf630478d	key_instantiate_and_link
+EXPORT_SYMBOL vmlinux 0xf666cbb3	__memcpy_fromio
+EXPORT_SYMBOL vmlinux 0xf688619c	tcf_hash_create
+EXPORT_SYMBOL vmlinux 0xf6949cd2	tty_chars_in_buffer
+EXPORT_SYMBOL vmlinux 0xf69af2aa	bio_integrity_trim
+EXPORT_SYMBOL vmlinux 0xf6ae2d16	bio_sector_offset
+EXPORT_SYMBOL vmlinux 0xf6b4c8cf	journal_clear_err
+EXPORT_SYMBOL vmlinux 0xf6bb4729	color_table
+EXPORT_SYMBOL vmlinux 0xf6d93fce	ppp_register_channel
+EXPORT_SYMBOL vmlinux 0xf6da5e14	blk_free_tags
+EXPORT_SYMBOL vmlinux 0xf6ebc03b	net_ratelimit
+EXPORT_SYMBOL vmlinux 0xf6ece5f6	__blockdev_direct_IO
+EXPORT_SYMBOL vmlinux 0xf6ef1dd3	alloc_fcdev
+EXPORT_SYMBOL vmlinux 0xf6efe56a	ethtool_op_get_rx_csum
+EXPORT_SYMBOL vmlinux 0xf6f696a4	update_region
+EXPORT_SYMBOL vmlinux 0xf71ed0f4	blk_queue_free_tags
+EXPORT_SYMBOL vmlinux 0xf749534a	gen_pool_free
+EXPORT_SYMBOL vmlinux 0xf76a4ab8	hypercall_page
+EXPORT_SYMBOL vmlinux 0xf76c7887	dev_addr_add
+EXPORT_SYMBOL vmlinux 0xf78d04ab	netlink_register_notifier
+EXPORT_SYMBOL vmlinux 0xf7e49dad	bioset_integrity_free
+EXPORT_SYMBOL vmlinux 0xf7e7e51d	dm_kcopyd_client_create
+EXPORT_SYMBOL vmlinux 0xf7f72df4	blk_queue_max_phys_segments
+EXPORT_SYMBOL vmlinux 0xf82abc1d	isa_dma_bridge_buggy
+EXPORT_SYMBOL vmlinux 0xf8846e76	jbd2_journal_dirty_metadata
+EXPORT_SYMBOL vmlinux 0xf885af11	vfs_rmdir
+EXPORT_SYMBOL vmlinux 0xf890fe7f	pm_idle
+EXPORT_SYMBOL vmlinux 0xf8b30e93	mempool_create
+EXPORT_SYMBOL vmlinux 0xf8cf9ee5	abort_exclusive_wait
+EXPORT_SYMBOL vmlinux 0xf8e089a8	devm_iounmap
+EXPORT_SYMBOL vmlinux 0xf8fd11d3	neigh_table_init_no_netlink
+EXPORT_SYMBOL vmlinux 0xf90209a3	set_bdi_congested
+EXPORT_SYMBOL vmlinux 0xf92fb8cd	phy_connect
+EXPORT_SYMBOL vmlinux 0xf93ad43c	__mod_zone_page_state
+EXPORT_SYMBOL vmlinux 0xf93e38c9	neigh_lookup
+EXPORT_SYMBOL vmlinux 0xf95c1a9a	blk_rq_count_integrity_sg
+EXPORT_SYMBOL vmlinux 0xf96027aa	sk_wait_data
+EXPORT_SYMBOL vmlinux 0xf9899664	mod_timer_pinned
+EXPORT_SYMBOL vmlinux 0xf9a482f9	msleep
+EXPORT_SYMBOL vmlinux 0xf9ad51a1	pci_bus_read_config_dword
+EXPORT_SYMBOL vmlinux 0xf9cd58e6	inet_csk_reset_keepalive_timer
+EXPORT_SYMBOL vmlinux 0xf9d7db3a	elv_queue_empty
+EXPORT_SYMBOL vmlinux 0xf9fd41b6	unregister_console
+EXPORT_SYMBOL vmlinux 0xfa0564fc	__wait_on_bit_lock
+EXPORT_SYMBOL vmlinux 0xfa152580	seq_release_private
+EXPORT_SYMBOL vmlinux 0xfa1a1154	generic_write_checks
+EXPORT_SYMBOL vmlinux 0xfa1c8c04	vfs_path_lookup
+EXPORT_SYMBOL vmlinux 0xfa35e837	dev_kfree_skb_any
+EXPORT_SYMBOL vmlinux 0xfa63eacd	posix_acl_permission
+EXPORT_SYMBOL vmlinux 0xfa6eca9d	d_prune_aliases
+EXPORT_SYMBOL vmlinux 0xfa77928e	set_groups
+EXPORT_SYMBOL vmlinux 0xfa897091	llc_build_and_send_ui_pkt
+EXPORT_SYMBOL vmlinux 0xfa908648	sysctl_jiffies
+EXPORT_SYMBOL vmlinux 0xfaa1ffa6	vfs_dq_drop
+EXPORT_SYMBOL vmlinux 0xfacad8dc	is_container_init
+EXPORT_SYMBOL vmlinux 0xfad1b779	__netdev_alloc_page
+EXPORT_SYMBOL vmlinux 0xfaf98462	bitrev32
+EXPORT_SYMBOL vmlinux 0xfb0cf2e9	touch_all_softlockup_watchdogs
+EXPORT_SYMBOL vmlinux 0xfb225c7a	mark_buffer_async_write
+EXPORT_SYMBOL vmlinux 0xfb3a29fb	xfrm_policy_byid
+EXPORT_SYMBOL vmlinux 0xfb6af58d	recalc_sigpending
+EXPORT_SYMBOL vmlinux 0xfb77ca4f	xen_start_info
+EXPORT_SYMBOL vmlinux 0xfb78b991	iget_locked
+EXPORT_SYMBOL vmlinux 0xfb950d3e	ethtool_op_set_ufo
+EXPORT_SYMBOL vmlinux 0xfba0c2e0	llc_sap_list_lock
+EXPORT_SYMBOL vmlinux 0xfbe27a1c	rb_first
+EXPORT_SYMBOL vmlinux 0xfbef03ab	elv_rb_add
+EXPORT_SYMBOL vmlinux 0xfbfd9187	__sk_mem_schedule
+EXPORT_SYMBOL vmlinux 0xfc02b7ad	sysctl_tcp_wmem
+EXPORT_SYMBOL vmlinux 0xfc1b34f0	dqget
+EXPORT_SYMBOL vmlinux 0xfc2b0ebc	jbd2_log_start_commit
+EXPORT_SYMBOL vmlinux 0xfc331b06	unbind_con_driver
+EXPORT_SYMBOL vmlinux 0xfc39e32f	ioport_unmap
+EXPORT_SYMBOL vmlinux 0xfc46e492	inode_sub_rsv_space
+EXPORT_SYMBOL vmlinux 0xfc6256b9	boot_tvec_bases
+EXPORT_SYMBOL vmlinux 0xfc9d0cd3	d_instantiate_unique
+EXPORT_SYMBOL vmlinux 0xfcaa04a0	out_of_line_wait_on_bit_lock
+EXPORT_SYMBOL vmlinux 0xfcb9b3dc	mdiobus_register
+EXPORT_SYMBOL vmlinux 0xfcc2a43c	utf32_to_utf8
+EXPORT_SYMBOL vmlinux 0xfcc459f5	sock_rfree
+EXPORT_SYMBOL vmlinux 0xfcc4d4e4	mod_timer_pending
+EXPORT_SYMBOL vmlinux 0xfcc9df93	security_inode_readlink
+EXPORT_SYMBOL vmlinux 0xfccb02f2	vcc_insert_socket
+EXPORT_SYMBOL vmlinux 0xfcda63a3	node_states
+EXPORT_SYMBOL vmlinux 0xfcec0987	enable_irq
+EXPORT_SYMBOL vmlinux 0xfcf4d028	pcim_pin_device
+EXPORT_SYMBOL vmlinux 0xfcfa03ff	fb_videomode_to_modelist
+EXPORT_SYMBOL vmlinux 0xfd090d10	poll_initwait
+EXPORT_SYMBOL vmlinux 0xfd27776c	vga_set_legacy_decoding
+EXPORT_SYMBOL vmlinux 0xfd5f9e1a	__bio_clone
+EXPORT_SYMBOL vmlinux 0xfd6f4850	native_wrmsr_safe_regs
+EXPORT_SYMBOL vmlinux 0xfd9b9ecd	ps2_cmd_aborted
+EXPORT_SYMBOL vmlinux 0xfda85a7d	request_threaded_irq
+EXPORT_SYMBOL vmlinux 0xfdb9b629	ioread32be
+EXPORT_SYMBOL vmlinux 0xfdc28a83	__serio_register_port
+EXPORT_SYMBOL vmlinux 0xfdfc0b3b	fiemap_fill_next_extent
+EXPORT_SYMBOL vmlinux 0xfdffe265	inode_add_bytes
+EXPORT_SYMBOL vmlinux 0xfe18cdf4	genlmsg_multicast_allns
+EXPORT_SYMBOL vmlinux 0xfe392bcd	generic_segment_checks
+EXPORT_SYMBOL vmlinux 0xfe5d4bb2	sys_tz
+EXPORT_SYMBOL vmlinux 0xfe769456	unregister_netdevice_notifier
+EXPORT_SYMBOL vmlinux 0xfe7c3180	pci_prepare_to_sleep
+EXPORT_SYMBOL vmlinux 0xfe7c4287	nr_cpu_ids
+EXPORT_SYMBOL vmlinux 0xfe8c8c16	tc_classify
+EXPORT_SYMBOL vmlinux 0xfe8dafd5	unregister_quota_format
+EXPORT_SYMBOL vmlinux 0xfe911c4d	elv_rq_merge_ok
+EXPORT_SYMBOL vmlinux 0xfe9ce292	nf_log_bind_pf
+EXPORT_SYMBOL vmlinux 0xfe9e8e0e	kthread_bind
+EXPORT_SYMBOL vmlinux 0xfea6bdce	security_sb_set_mnt_opts
+EXPORT_SYMBOL vmlinux 0xfeb7a49b	malloc_sizes
+EXPORT_SYMBOL vmlinux 0xfec3c2f2	bcd2bin
+EXPORT_SYMBOL vmlinux 0xfedd35fc	console_suspend_enabled
+EXPORT_SYMBOL vmlinux 0xff1e9dd8	seq_list_start
+EXPORT_SYMBOL vmlinux 0xff4d35ba	vfs_readv
+EXPORT_SYMBOL vmlinux 0xff6878cf	fb_default_cmap
+EXPORT_SYMBOL vmlinux 0xff6ca919	inet_addr_type
+EXPORT_SYMBOL vmlinux 0xff708fd3	mempool_destroy
+EXPORT_SYMBOL vmlinux 0xff7559e4	ioport_resource
+EXPORT_SYMBOL vmlinux 0xff964b25	param_set_int
+EXPORT_SYMBOL vmlinux 0xff9ca065	fb_edid_to_monspecs
+EXPORT_SYMBOL vmlinux 0xffa8f2d2	blk_start_queue
+EXPORT_SYMBOL vmlinux 0xffa963d1	tcp_connect
+EXPORT_SYMBOL vmlinux 0xffc7c184	__init_waitqueue_head
+EXPORT_SYMBOL vmlinux 0xffd5a395	default_wake_function
+EXPORT_SYMBOL vmlinux 0xffe1da6b	sk_stream_write_space
+EXPORT_SYMBOL vmlinux 0xfffdb951	tcp_v4_remember_stamp
+EXPORT_SYMBOL_GPL arch/x86/crypto/aes-x86_64 0x7060bf0a	crypto_aes_encrypt_x86
+EXPORT_SYMBOL_GPL arch/x86/crypto/aes-x86_64 0xe409b491	crypto_aes_decrypt_x86
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x0cc1e40f	crypto_it_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x24aac4d9	crypto_aes_expand_key
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x3dc916b6	crypto_fl_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x40d46b21	crypto_ft_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0x71dc9998	crypto_il_tab
+EXPORT_SYMBOL_GPL crypto/aes_generic 0xc8dbaf9f	crypto_aes_set_key
+EXPORT_SYMBOL_GPL crypto/async_tx/async_memcpy 0x09d1dd38	async_memcpy
+EXPORT_SYMBOL_GPL crypto/async_tx/async_pq 0x75dc0a00	async_syndrome_val
+EXPORT_SYMBOL_GPL crypto/async_tx/async_pq 0xa6c357b5	async_gen_syndrome
+EXPORT_SYMBOL_GPL crypto/async_tx/async_raid6_recov 0x66ae1d55	async_raid6_2data_recov
+EXPORT_SYMBOL_GPL crypto/async_tx/async_raid6_recov 0xd7b92c72	async_raid6_datap_recov
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0x227abd87	async_tx_quiesce
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xd4debe7a	async_trigger_callback
+EXPORT_SYMBOL_GPL crypto/async_tx/async_tx 0xfaa8e5e9	async_tx_submit
+EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x0f4de244	async_xor_val
+EXPORT_SYMBOL_GPL crypto/async_tx/async_xor 0x22252217	async_xor
+EXPORT_SYMBOL_GPL crypto/cryptd 0x1b21fded	cryptd_free_ablkcipher
+EXPORT_SYMBOL_GPL crypto/cryptd 0x38b5c96a	cryptd_alloc_ahash
+EXPORT_SYMBOL_GPL crypto/cryptd 0x8546cd5d	cryptd_alloc_ablkcipher
+EXPORT_SYMBOL_GPL crypto/cryptd 0xc314c3b6	cryptd_ablkcipher_child
+EXPORT_SYMBOL_GPL crypto/cryptd 0xc6a829ce	cryptd_shash_desc
+EXPORT_SYMBOL_GPL crypto/cryptd 0xdba6742e	cryptd_ahash_child
+EXPORT_SYMBOL_GPL crypto/cryptd 0xec229813	cryptd_free_ahash
+EXPORT_SYMBOL_GPL crypto/des_generic 0xcfd9a2c0	des_ekey
+EXPORT_SYMBOL_GPL crypto/twofish_common 0xc46d9049	twofish_setkey
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0067df75	ata_tf_from_fis
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x00ebcb5d	ata_id_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x03e3686c	ata_timing_cycle2mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x04313946	ata_sff_data_xfer32
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x052ad975	ata_qc_complete_multiple
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0531dcb8	ata_dev_classify
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0bbbfe81	ata_port_freeze
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x0cac04b7	ata_sff_pause
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x10673a12	ata_scsi_ioctl
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x12454e0f	ata_bmdma32_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x14b28558	ata_host_detach
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1785f770	ata_dev_disable
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x179c74da	ata_bmdma_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1843431f	ata_bmdma_mode_filter
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x18e50afc	ata_do_set_mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1aa621d5	ata_port_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1b4cfb22	ata_sff_drain_fifo
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1be0b5ad	ata_host_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1d5923c0	sata_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1f564de3	ata_sff_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1fca564c	ata_pci_sff_init_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x1fd47168	ata_port_abort
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x25721272	ata_sff_data_xfer_noirq
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2bd27702	ata_do_dev_read_id
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2c59b87f	sata_sff_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2c7177d5	ata_host_activate
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2d0d8ef9	sata_pmp_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2d781c77	ata_sas_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x2ef0b768	ata_sff_qc_issue
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x31bad107	ata_eh_freeze_port
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x31f572b7	dev_attr_em_message_type
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x32bbdb71	ata_bmdma_status
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x33e52982	ata_pci_device_do_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x35d359db	ata_pci_sff_prepare_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x35f3e2a7	sata_scr_valid
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x37ab25cd	ata_sff_tf_read
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3868962a	ata_sff_postreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x387f90f4	ata_host_register
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3a08fed1	ata_sff_softreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3b173a47	sata_std_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3bc556d4	sata_link_debounce
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x3bcad033	ata_bmdma_setup
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4038cc27	sata_pmp_qc_defer_cmd_switch
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x40af0dec	ata_xfer_mode2mask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4105122d	ata_eh_qc_retry
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x43f56e82	ata_xfer_mode2shift
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4bcb61dc	ata_std_prereset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4dc31d97	ata_sff_dev_classify
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4e546ba5	ata_pci_bmdma_clear_simplex
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4f0d3523	ata_sff_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x4fdc945d	sata_deb_timing_normal
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x51e04470	ata_port_pbar_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5297d6df	sata_scr_read
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x53c619d1	ata_sff_check_status
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x554ddbf7	ata_sff_post_internal_cmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x55b631b0	sata_scr_write_flush
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x55dfadbc	sata_pmp_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x587a853e	ata_std_bios_param
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x589e0862	ata_eh_qc_complete
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x58bef4c1	dev_attr_em_message
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5c5be5e7	ata_link_next
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x5e43d7ba	ata_sas_port_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x605cca19	ata_scsi_queuecmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x60b9754a	ata_sff_lost_interrupt
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x631db2a8	ata_sas_scsi_ioctl
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x64dea13e	ata_sas_slave_configure
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x65f15de4	ata_common_sdev_attrs
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x678ac357	ata_sff_irq_on
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6808c830	ata_sff_prereset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x69c55de0	ata_link_offline
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x69e9a2cb	ata_scsi_slave_config
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6b16e9fe	ata_ehi_clear_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6d69b4de	ata_bus_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x6d7113c7	ata_dev_next
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x707ff1bb	ata_xfer_mask2mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x71bc12bf	pci_test_config_bits
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x72b9c74d	ata_sff_busy_sleep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x73a48b4a	ata_sff_std_ports
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x743a165e	ata_pack_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x744435a0	ata_pci_device_do_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x745703e6	ata_host_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x767c611e	ata_cable_40wire
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x78116ea7	ata_sff_tf_load
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7a859224	ata_link_online
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7ce2cc1c	ata_port_probe
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x7fd7b11a	ata_sff_thaw
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x80033013	ata_std_qc_defer
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8149ea54	ata_timing_find_mode
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x838de1a7	ata_sff_host_intr
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8556f19b	ata_link_abort
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x87f8c628	ata_bmdma_stop
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8a4ccb2d	ata_scsi_simulate
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b1f40f9	ata_sff_exec_command
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8b752ac1	ata_tf_to_fis
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x8c33a860	dev_attr_link_power_management_policy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x92ff8010	ata_sff_wait_after_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9448197c	ata_sff_dumb_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x94a68723	ata_scsi_slave_destroy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x95a9f590	ata_pci_bmdma_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x996bec49	ata_sff_port_start32
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9da05775	ata_std_error_handler
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e29bf5b	ata_timing_compute
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9e9c8022	ata_cable_unknown
+EXPORT_SYMBOL_GPL drivers/ata/libata 0x9f9c8574	ata_sff_dma_pause
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa169bd62	ata_pci_device_suspend
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa1ad0202	ata_cable_ignore
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa1ee6072	sata_link_hardreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa30ceaf8	ata_dummy_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa3682e64	ata_host_alloc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa3880dde	ata_sff_dev_select
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa6e9af3c	ata_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa918a1df	dev_attr_sw_activity
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xa91ddcb1	ata_sas_port_alloc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaa18d270	sata_link_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaa3a0ee5	ata_pci_sff_activate_host
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xad88570b	__ata_ehi_push_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xaf3f6fe0	ata_sff_interrupt
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb1b2a9ac	ata_sff_hsm_move
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb1e70cbd	ata_noop_qc_prep
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb31cbf87	ata_qc_complete
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb53f4fac	ata_sas_port_destroy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb6aeb661	ata_id_c_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xb9145ae1	ata_host_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbbb28316	ata_sas_queuecmd
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbdf7c85e	ata_sas_port_stop
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe1887e4	ata_unpack_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbe8b0dfe	ata_pci_sff_init_one
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbf167fc1	ata_cable_80wire
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xbf45e6c0	ata_pci_device_resume
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc0dc3c85	ata_sff_qc_fill_rtf
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc18d3026	ata_sff_wait_ready
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc3a4652b	ata_pci_remove_one
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc428068d	sata_deb_timing_long
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc48b7ccf	ata_mode_string
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc57d9a57	ata_do_eh
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc5e68722	ata_ehi_push_desc
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc673e23e	ata_scsi_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xc72c594c	ata_sff_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xcccfb2fa	sata_deb_timing_hotplug
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xcfcf4bd3	ata_wait_after_reset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd1098878	ata_host_alloc_pinfo
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd44909d4	ata_cable_sata
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xd95db074	ata_sff_irq_clear
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdaadbc26	ata_std_postreset
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdd08bc70	ata_sff_freeze
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xdd7d1815	ata_sg_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe0041c63	ata_bmdma_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe1b6ce61	ata_eh_analyze_ncq_error
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe2112e3f	ata_sff_port_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe49ff3b0	ata_wait_register
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe59f73d8	ata_pio_queue_task
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe67f2a94	ata_eh_thaw_port
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe6c19389	dev_attr_unload_heads
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xe80e1f9d	sata_async_notification
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xea418e0f	atapi_cmd_type
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xec1c0892	ata_host_start
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xef874f59	ata_dummy_port_info
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0acf0f9	ata_port_schedule_eh
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf0b47fdb	ata_slave_link_init
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf36bc513	ata_pio_need_iordy
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf6e874f5	ata_timing_merge
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf7069e61	ata_sff_data_xfer
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf73b60c0	ata_port_disable
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8180786	ata_base_port_ops
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf8f3a0fb	ata_ratelimit
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xf9ca3160	ata_id_xfermask
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xfbdc37b6	sata_scr_write
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xfc13498c	ata_dev_pair
+EXPORT_SYMBOL_GPL drivers/ata/libata 0xfdf93333	sata_set_spd
+EXPORT_SYMBOL_GPL drivers/ata/pata_sis 0x70ed7a74	sis_info133_for_sata
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x02ff9464	cfag12864b_isinited
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x0ecb2e5d	cfag12864b_disable
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x305dc3c6	cfag12864b_isenabled
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x3389f926	cfag12864b_enable
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0x9522a342	cfag12864b_getrate
+EXPORT_SYMBOL_GPL drivers/auxdisplay/cfag12864b 0xc48e9d95	cfag12864b_buffer
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x14102f23	ks0108_displaystate
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x48a70518	ks0108_writedata
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x4f506333	ks0108_startline
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0x6edae968	ks0108_isinited
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xbf4774db	ks0108_writecontrol
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xedde6df2	ks0108_page
+EXPORT_SYMBOL_GPL drivers/auxdisplay/ks0108 0xfee8ef7b	ks0108_address
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0x4163b375	agp_add_bridge
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0x6fbb019c	agp_remove_bridge
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xd6feefa5	agp_num_entries
+EXPORT_SYMBOL_GPL drivers/char/agp/agpgart 0xe089cfcc	agp_memory_reserved
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x06594623	tpm_get_timeouts
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x0733c739	tpm_store_cancel
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x12a6325d	tpm_continue_selftest
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x12aa66e1	tpm_calc_ordinal_duration
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x1e6bb590	tpm_show_timeouts
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x21703539	tpm_show_enabled
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3054a043	tpm_show_pcrs
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x3917ff67	tpm_pm_suspend
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x514fe2db	tpm_open
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x648d971f	tpm_pm_resume
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x664420bf	tpm_read
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x747a5704	tpm_gen_interrupt
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x7c1bd2f3	tpm_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x84c1ac22	tpm_show_owned
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x90b1bef5	tpm_dev_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x99a71927	tpm_show_pubek
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0x9e2d509f	tpm_dev_vendor_release
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xab36dcf4	tpm_register_hardware
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xadf6aa4d	tpm_pcr_read
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xb263fdb0	tpm_write
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xbafa6fce	tpm_show_caps
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc37226a5	tpm_pcr_extend
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xc47311e3	tpm_remove_hardware
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xd04ee249	tpm_show_caps_1_2
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xead5ab6f	tpm_show_temp_deactivated
+EXPORT_SYMBOL_GPL drivers/char/tpm/tpm 0xf58c0116	tpm_show_active
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x080d5ec8	edac_device_add_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x0c32ff8a	edac_pci_alloc_index
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x10c4be76	edac_mc_find_csrow_by_page
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x1a185f50	edac_mc_free
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x2a92169c	edac_mc_alloc
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x2a9d5853	edac_pci_handle_pe
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x489c3eb5	edac_mc_add_mc
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x4e5bd383	edac_mc_handle_ce_no_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x505d47f7	edac_mc_del_mc
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x5ecd7c6b	edac_device_handle_ue
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x61f17c70	edac_device_alloc_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x692d04d9	edac_mc_handle_ue
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6d7f0bc3	edac_pci_del_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x6e3ff83a	edac_device_alloc_index
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x72210cd6	edac_device_del_device
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x739dd47a	edac_pci_release_generic_ctl
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x74c25408	edac_mc_handle_ce
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x78f81fc4	edac_mc_handle_ue_no_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x8c044e50	edac_device_handle_ce
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x928b07f1	edac_pci_handle_npe
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0x9385c7fe	edac_device_free_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa0b5e0ec	edac_pci_alloc_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa15a9cfe	edac_pci_create_generic_ctl
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xa2ce417f	edac_pci_reset_delay_period
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xbe047472	edac_pci_free_ctl_info
+EXPORT_SYMBOL_GPL drivers/edac/edac_core 0xdae1dfa1	edac_pci_add_device
+EXPORT_SYMBOL_GPL drivers/gpu/drm/drm 0x1ca09263	drm_class_device_register
+EXPORT_SYMBOL_GPL drivers/gpu/drm/drm 0xd85611de	drm_class_device_unregister
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x05495392	hid_debug
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x18800bd9	hidinput_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x1d2d7c0d	hidinput_find_field
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x23239970	hid_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x286d11ef	hid_input_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x3de902d4	hid_debug_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x4fdeb423	hid_dump_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x54f66d28	hidraw_disconnect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x5df55f57	hidraw_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x5f9ed0a1	hid_output_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x60de54a3	hid_parse_report
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x6831f9cc	hid_allocate_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x72dd704b	hidinput_report_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x75449f67	hid_destroy_device
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x8314e9d8	hid_set_field
+EXPORT_SYMBOL_GPL drivers/hid/hid 0x8625d80a	hid_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xaf65a5b5	hid_resolv_usage
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xb08beace	__hid_register_driver
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xb453cbc1	hidinput_connect
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xc3b36e50	hidraw_report_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xc85aefed	hid_check_keys_pressed
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xcb238bdf	hid_dump_field
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xd2bcf3c4	hid_dump_input
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xd42dff61	hid_unregister_driver
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xe06be63d	hid_report_raw_event
+EXPORT_SYMBOL_GPL drivers/hid/hid 0xe5e397e4	hid_add_device
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x01fd453e	usbhid_lookup_quirk
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x12c883b0	usbhid_submit_report
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x191ecee1	usbhid_set_leds
+EXPORT_SYMBOL_GPL drivers/hid/usbhid/usbhid 0x695d86eb	hiddev_hid_event
+EXPORT_SYMBOL_GPL drivers/i2c/busses/i2c-nforce2 0x90d1cd27	nforce2_smbus
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x47f50852	i2c_new_dummy
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0x8f893f37	i2c_new_probed_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xb59df195	i2c_bus_type
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xcea1a070	i2c_unregister_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xe28d3352	i2c_new_device
+EXPORT_SYMBOL_GPL drivers/i2c/i2c-core 0xeba79168	i2c_add_numbered_adapter
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x915ff8b5	hpsb_config_rom_ip1394_remove
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0x95a8bd0f	hpsb_config_rom_ip1394_add
+EXPORT_SYMBOL_GPL drivers/ieee1394/ieee1394 0xec8d18cf	hpsb_disable_irm
+EXPORT_SYMBOL_GPL drivers/infiniband/hw/ipath/ib_ipath 0x1514b2b2	ipath_debug
+EXPORT_SYMBOL_GPL drivers/input/ff-memless 0x948cafc1	input_ff_create_memless
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x3fd3bcff	wm9713_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x497af973	wm97xx_unregister_mach_ops
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x54e3ce87	wm97xx_reg_write
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x70050323	wm97xx_config_gpio
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x77cd22f2	wm97xx_get_gpio
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x818977c2	wm97xx_register_mach_ops
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0x8c584aa8	wm97xx_read_aux_adc
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xb879c3db	wm97xx_set_suspend_mode
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xd831d585	wm97xx_reg_read
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xeec7a13b	wm9705_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xf379bc61	wm9712_codec
+EXPORT_SYMBOL_GPL drivers/input/touchscreen/wm97xx-ts 0xf3e24171	wm97xx_set_gpio
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0x11981364	led_classdev_suspend
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0x529b2486	led_classdev_resume
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0x65261aee	led_classdev_unregister
+EXPORT_SYMBOL_GPL drivers/leds/led-class 0x6eb84a6c	led_classdev_register
+EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0x4983dde7	dm_unregister_path_selector
+EXPORT_SYMBOL_GPL drivers/md/dm-multipath 0xb8a5f988	dm_register_path_selector
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x0ae000cf	dm_rh_recovery_prepare
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x14045afb	dm_rh_bio_to_region
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x23e71050	dm_rh_dirty_log
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x292fa4f4	dm_rh_recovery_in_flight
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x3383e4f4	dm_rh_flush
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x4f728321	dm_rh_get_region_size
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x529a34e6	dm_rh_inc_pending
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x553b83bb	dm_rh_delay
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x60c9e52f	dm_rh_get_region_key
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x634a6221	dm_rh_mark_nosync
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x667661b6	dm_rh_get_state
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x682e6224	dm_rh_update_states
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x7a9901ac	dm_region_hash_create
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x91a7cefa	dm_rh_start_recovery
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x9afd827b	dm_rh_region_context
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0x9f887d7f	dm_region_hash_destroy
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xad9de26f	dm_rh_recovery_end
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xb7f9c269	dm_rh_recovery_start
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xbc430647	dm_rh_dec
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xbdab93d0	dm_rh_stop_recovery
+EXPORT_SYMBOL_GPL drivers/md/dm-region-hash 0xe9271561	dm_rh_region_to_sector
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0x723a6dfc	md_new_event
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0x73b61d26	sync_page_io
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0xa7fc0ed2	md_do_sync
+EXPORT_SYMBOL_GPL drivers/md/md-mod 0xc168a180	md_allow_write
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0x24935f26	raid6_call
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0xcdc24ab5	raid6_2data_recov
+EXPORT_SYMBOL_GPL drivers/md/raid6_pq 0xdbab0c01	raid6_datap_recov
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x31bd7d23	i2o_dma_realloc
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x3f05ac2c	i2o_dma_map_single
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0x9cc3e6cf	i2o_dma_alloc
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xa83908e6	i2o_dma_map_sg
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xc1ef8ae2	i2o_pool_alloc
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xd8430bf1	i2o_dma_free
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xdf28b56b	i2o_sg_tablesize
+EXPORT_SYMBOL_GPL drivers/message/i2o/i2o_core 0xfa09b150	i2o_pool_free
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x1edf0892	sm501_unit_power
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x3a61b00d	sm501_modify_reg
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0x967be746	sm501_misc_control
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xa841f767	sm501_set_clock
+EXPORT_SYMBOL_GPL drivers/mfd/sm501 0xce706510	sm501_find_clock
+EXPORT_SYMBOL_GPL drivers/misc/eeprom/eeprom_93cx6 0x2df115d4	eeprom_93cx6_multiread
+EXPORT_SYMBOL_GPL drivers/misc/eeprom/eeprom_93cx6 0x63d14d2f	eeprom_93cx6_read
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x05393976	enclosure_unregister
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x102547c6	enclosure_find
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x67b212da	enclosure_component_register
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x7fb78644	enclosure_remove_device
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0x99626f48	enclosure_add_device
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xe69650f9	enclosure_register
+EXPORT_SYMBOL_GPL drivers/misc/enclosure 0xfddee4bd	enclosure_for_each_device
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0x9f6c07f4	cfi_cmdset_0003
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xb676fc57	cfi_cmdset_0001
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0001 0xe006ef02	cfi_cmdset_0200
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0002 0x6659f905	cfi_cmdset_0002
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_cmdset_0020 0x00b5ea0f	cfi_cmdset_0020
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0x041500f9	cfi_qry_mode_off
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0xccf58383	cfi_qry_mode_on
+EXPORT_SYMBOL_GPL drivers/mtd/chips/cfi_util 0xd82a175a	cfi_qry_present
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2000 0xaeac9bd0	DoC2k_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001 0x05dea78c	DoCMil_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/doc2001plus 0xd651f2e8	DoCMilPlus_init
+EXPORT_SYMBOL_GPL drivers/mtd/devices/docecc 0x45937659	doc_decode_ecc
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x199ca164	unregister_mtd_user
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x3434071c	mtd_erase_callback
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x5866efd4	get_sb_mtd
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x74062723	parse_mtd_partitions
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x7fbe4ef6	add_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x86300691	deregister_mtd_parser
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x866203b4	get_mtd_device_nm
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0x8a00daff	kill_mtd_super
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xb920ee1a	get_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xbd60a006	mtd_table_mutex
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xc087d58f	default_mtd_writev
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xc4ba721b	put_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xcaed9862	del_mtd_device
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xcf1b3afa	register_mtd_parser
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xe53e2b71	mtd_table
+EXPORT_SYMBOL_GPL drivers/mtd/mtd 0xf23c98c2	register_mtd_user
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x118ab4c2	register_mtd_blktrans
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x2371af37	del_mtd_blktrans_dev
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0x92c9738b	deregister_mtd_blktrans
+EXPORT_SYMBOL_GPL drivers/mtd/mtd_blkdevs 0xcec88b5c	add_mtd_blktrans_dev
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x0b8f3acb	nand_release
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x31c3eacf	nand_scan
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0x77dc640c	nand_scan_tail
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xa50e372b	nand_wait_ready
+EXPORT_SYMBOL_GPL drivers/mtd/nand/nand 0xeaa5b607	nand_scan_ident
+EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x341332c7	onenand_scan
+EXPORT_SYMBOL_GPL drivers/mtd/onenand/onenand 0x5db0184d	onenand_release
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x0fc7ed44	ubi_leb_erase
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x17019ecc	ubi_leb_change
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x3d283fd3	ubi_leb_read
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x42801d20	ubi_sync
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x6f09ba8a	ubi_register_volume_notifier
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0x9ded4407	ubi_leb_write
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa1498201	ubi_open_volume_nm
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa15ca71e	ubi_leb_unmap
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xa59919a8	ubi_open_volume
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbc505df4	ubi_get_device_info
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xbd158e5b	ubi_is_mapped
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xc776b952	ubi_close_volume
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xdc222f50	ubi_do_get_device_info
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xdd195330	ubi_leb_map
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xf3c8f335	ubi_get_volume_info
+EXPORT_SYMBOL_GPL drivers/mtd/ubi/ubi 0xfd6f0ef9	ubi_unregister_volume_notifier
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x08565ed7	mlx4_fmr_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x0fb529cd	mlx4_buf_write_mtt
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x13c00301	mlx4_srq_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x14302f27	mlx4_buf_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1a05bbe8	mlx4_pd_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1bdca5fe	mlx4_mtt_init
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1f5efff5	mlx4_mr_enable
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x1f5f85e9	mlx4_uar_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x25c5496c	mlx4_CLOSE_PORT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x27e1e657	mlx4_mtt_cleanup
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x2d2cc3fd	mlx4_INIT_PORT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x34461d1b	mlx4_multicast_detach
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x349cb305	mlx4_unregister_mac
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x3e502b0b	mlx4_free_hwq_res
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x482d74a1	mlx4_srq_query
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x4cc3d644	mlx4_cq_resize
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5851d470	mlx4_mtt_addr
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5cf31042	mlx4_alloc_hwq_res
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x5fe4f453	__mlx4_cmd
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x63d2b679	mlx4_cq_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x64953e54	mlx4_fmr_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x654376bf	mlx4_buf_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x67c4e5e7	mlx4_register_interface
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x67ecd615	mlx4_register_mac
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6bf730c5	mlx4_qp_release_range
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6d1974d2	mlx4_pd_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6d6bee48	mlx4_map_phys_fmr
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x6da54b49	mlx4_qp_remove
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x744e265a	mlx4_qp_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x8dae8c6a	mlx4_free_cmd_mailbox
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9e12276e	mlx4_qp_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0x9e307f14	mlx4_qp_reserve_range
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa1506eef	mlx4_db_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa2f989a7	mlx4_srq_arm
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa673a05e	mlx4_multicast_attach
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xa8d74410	mlx4_uar_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xaa22dde5	mlx4_cq_modify
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xac533ae5	mlx4_qp_modify
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xad86e5c8	mlx4_fmr_unmap
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xb246e506	mlx4_register_vlan
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc16cc007	mlx4_qp_to_ready
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xc8d8e0fd	mlx4_SYNC_TPT
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xdeb14b8d	mlx4_qp_query
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe306d563	mlx4_cq_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xe7ad5737	mlx4_mr_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xeb77da26	mlx4_write_mtt
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xec7442a6	mlx4_unregister_interface
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf2b4291e	mlx4_fmr_enable
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf49f9ad8	mlx4_db_alloc
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf56ff977	mlx4_alloc_cmd_mailbox
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf5db3a88	mlx4_srq_free
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xf6f66c5f	mlx4_unregister_vlan
+EXPORT_SYMBOL_GPL drivers/net/mlx4/mlx4_core 0xfbfde91c	mlx4_mr_alloc
+EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0x9097d004	usbnet_cdc_unbind
+EXPORT_SYMBOL_GPL drivers/net/usb/cdc_ether 0xc31648ca	usbnet_generic_cdc_bind
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x219c5452	rndis_status
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x23feef13	generic_rndis_bind
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x2f7fdfd4	rndis_tx_fixup
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x76e7f8ce	rndis_command
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0x87aeafdb	rndis_rx_fixup
+EXPORT_SYMBOL_GPL drivers/net/usb/rndis_host 0xe164c805	rndis_unbind
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x0b4ffdf7	usbnet_get_drvinfo
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x12c91705	usbnet_resume
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x19a2b71c	usbnet_unlink_rx_urbs
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x1a61bdbb	usbnet_set_msglevel
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x47ff9527	usbnet_skb_return
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x4b2c9e41	usbnet_get_msglevel
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x4f8214bc	usbnet_pause_rx
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x51eb0c69	usbnet_change_mtu
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x60c12585	usbnet_resume_rx
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x7090f365	usbnet_get_endpoints
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x75f16661	usbnet_probe
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x7a2e8696	usbnet_stop
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x7ddaa2cf	usbnet_defer_kevent
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x86615c0e	usbnet_nway_reset
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x893a63ef	usbnet_start_xmit
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0x8e4663dc	usbnet_open
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xa2fdab24	usbnet_set_settings
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xb32d4f93	usbnet_tx_timeout
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xc80e2b7f	usbnet_disconnect
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xdf427a2c	usbnet_suspend
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xe6e7fdef	usbnet_purge_paused_rxq
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xf24766ba	usbnet_get_link
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xf3a881fd	usbnet_get_ethernet_addr
+EXPORT_SYMBOL_GPL drivers/net/usb/usbnet 0xf6e8aa81	usbnet_get_settings
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x2ffc2732	pci_hp_deregister
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x3a885f3d	cpci_hp_unregister_bus
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x4d58b307	cpci_hp_register_controller
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x52497bb2	pci_configure_slot
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x6a8441be	cpci_hp_start
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x8798bf7f	__pci_hp_register
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0x94ef4d05	cpci_hp_stop
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xa06e74e0	pci_hp_change_slot_info
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xa5a12f07	cpci_hp_unregister_controller
+EXPORT_SYMBOL_GPL drivers/pci/hotplug/pci_hotplug 0xe203aab8	cpci_hp_register_bus
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x0366b810	scsi_dh_activate
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x0d3a9332	scsi_register_device_handler
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x0daeb7aa	scsi_dh_set_params
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x0fee8f38	scsi_dh_detach
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x593a36c2	scsi_dh_handler_exist
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x7d99b900	scsi_unregister_device_handler
+EXPORT_SYMBOL_GPL drivers/scsi/device_handler/scsi_dh 0x90e3a2d9	scsi_dh_attach
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0233f349	iscsi_pool_init
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x07ac71e5	iscsi_session_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x0e07d2a5	iscsi_session_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x101ffa4b	iscsi_host_set_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x109b9329	iscsi_complete_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x13ca6dd8	iscsi_complete_scsi_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x15f93429	iscsi_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x1d6a44f3	iscsi_conn_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x222221ce	iscsi_prep_data_out_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x2a1ffe83	iscsi_conn_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x2ce4efcb	iscsi_host_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x34f37699	iscsi_conn_send_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3c49d785	iscsi_suspend_tx
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x3c6f6913	iscsi_conn_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x40c43ac9	iscsi_conn_bind
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x415ad66e	iscsi_verify_itt
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x41ba1d14	iscsi_pool_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x47f9a8c0	iscsi_conn_failure
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x489ad681	iscsi_itt_to_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x4d0a5c4b	iscsi_conn_queue_work
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x530d51a8	iscsi_session_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x575e8907	iscsi_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x5ac92610	iscsi_requeue_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x61c2a770	iscsi_conn_stop
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x628d3c2a	iscsi_set_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x70a3c51a	iscsi_session_failure
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x784b1e28	__iscsi_complete_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x8f73c264	iscsi_queuecommand
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x922e48b9	iscsi_conn_start
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x9895fbd6	iscsi_eh_device_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0x99b6472d	iscsi_host_get_param
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xaf69b610	iscsi_session_recovery_timedout
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb6657fde	iscsi_put_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb689aca5	iscsi_itt_to_ctask
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb8be154e	iscsi_host_remove
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xb8f99426	__iscsi_get_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc0467887	iscsi_host_add
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xc4e29eeb	iscsi_host_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xcd82b982	iscsi_update_cmdsn
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xd07a9faf	iscsi_eh_target_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xdfe173a9	iscsi_eh_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi 0xf255b6bd	iscsi_suspend_queue
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x1208d5b7	iscsi_tcp_r2tpool_free
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x250f900f	iscsi_tcp_r2tpool_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x48645a28	iscsi_tcp_cleanup_task
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x4f58b331	iscsi_tcp_task_xmit
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x5866c731	iscsi_tcp_dgst_header
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x5b965a42	iscsi_tcp_task_init
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x68c54493	iscsi_tcp_hdr_recv_prep
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x6ecddde1	iscsi_tcp_conn_get_stats
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x898b4065	iscsi_tcp_recv_skb
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x8e0267ba	iscsi_tcp_segment_done
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x95190ca7	iscsi_tcp_segment_unmap
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0x992c6477	iscsi_segment_seek_sg
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xbd4d42d7	iscsi_tcp_recv_segment_is_hdr
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xbe26dc74	iscsi_segment_init_linear
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xc59dc9b2	iscsi_tcp_conn_setup
+EXPORT_SYMBOL_GPL drivers/scsi/libiscsi_tcp 0xf7e4b7ba	iscsi_tcp_conn_teardown
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x04abff76	sas_target_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x08c54f8f	sas_ioctl
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x0ac0f3bc	sas_bios_param
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x10e03edb	sas_domain_attach_transport
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x16078fae	sas_register_ha
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x18001545	sas_queuecommand
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x1f698c0a	sas_slave_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x4742a6fe	sas_eh_device_reset_handler
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x479b280b	sas_change_queue_type
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x4f0888f8	sas_domain_release_transport
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x599bd993	sas_change_queue_depth
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x78015ff8	sas_task_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x79446487	sas_request_addr
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x814704cd	__sas_task_abort
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8cc6cac3	sas_ssp_task_response
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x8e5dfe3a	sas_slave_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0x90f45cf9	sas_slave_configure
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xb0225fc0	sas_eh_bus_reset_handler
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xc10a92be	sas_find_local_phy
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdc3aa50a	sas_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xdda70249	sas_phy_reset
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xe2db9c76	sas_phy_enable
+EXPORT_SYMBOL_GPL drivers/scsi/libsas/libsas 0xffffb39b	sas_unregister_ha
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x309c5d9f	srp_transfer_data
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x474cb7a1	srp_target_free
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x4c5e1cdb	srp_target_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x64e97817	srp_iu_put
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0x766a5080	srp_iu_get
+EXPORT_SYMBOL_GPL drivers/scsi/libsrp 0xf1fc137a	srp_cmd_queue
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x1cc19ceb	scsi_flush_work
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x26c90ea4	scsi_eh_get_sense
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x35d8c94a	sdev_evt_alloc
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x520d4bc5	sdev_evt_send_simple
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x535feedc	scsi_bus_type
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x53656b1f	scsi_nl_add_driver
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x5d4b2591	scsi_eh_ready_devs
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x6acd3fad	__scsi_get_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x6c852956	scsi_target_block
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7508e8e0	sdev_evt_send
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x7e275ea8	scsi_complete_async_scans
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x8cf129f3	scsi_internal_device_block
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x951fbdab	scsi_nl_add_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0x9f0125c1	scsi_queue_work
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xa9432547	scsi_get_vpd_page
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xb3ef98bb	scsi_nl_sock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xbae34c27	scsi_nl_remove_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xc08c5b35	scsi_internal_device_unblock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xc399468f	scsi_nl_remove_driver
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xd4fe26f2	scsi_mode_select
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xdef8cbcb	scsi_schedule_eh
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xdf203822	scsi_target_unblock
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_mod 0xeae74760	scsi_nl_send_transport_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x36dfab09	scsi_tgt_queue_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x391266be	scsi_tgt_it_nexus_create
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x6800d95a	scsi_host_get_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x733b5570	scsi_tgt_it_nexus_destroy
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x7fb4a4a1	scsi_host_put_command
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x91a28eed	scsi_tgt_cmd_to_host
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0x958a6c4b	scsi_tgt_alloc_queue
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xabc84495	scsi_tgt_tsk_mgmt_request
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_tgt 0xcf9b0dbb	scsi_tgt_free_queue
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x04020792	iscsi_add_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x25cdde73	iscsi_session_chkready
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x2772c101	iscsi_create_conn
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x30c19515	iscsi_conn_error_event
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x3e28620d	iscsi_create_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x5130d0dd	iscsi_remove_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x557ff6b7	iscsi_alloc_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x5bde85bb	iscsi_unblock_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x650b1a88	iscsi_register_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x7af26e83	iscsi_session_event
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x7dcfa419	iscsi_create_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x88effb40	iscsi_offload_mesg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0x8e8a58ca	iscsi_scan_finished
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xa9e5cea2	iscsi_host_for_each_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xb89096e9	iscsi_free_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xcb197139	iscsi_destroy_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xd23ec8c5	iscsi_recv_pdu
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xd2c91a96	iscsi_unregister_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xd9d79949	iscsi_destroy_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xeb908691	iscsi_block_session
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xf0b1cbfb	iscsi_destroy_conn
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_iscsi 0xfdd75557	iscsi_lookup_endpoint
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0x0ef06974	spi_populate_ppr_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xa0c71dac	spi_populate_sync_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_spi 0xcffa2aff	spi_populate_width_msg
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x0b376561	srp_attach_transport
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x2820239a	srp_remove_host
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0x7648ff67	srp_rport_del
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xc7ef00bb	srp_rport_add
+EXPORT_SYMBOL_GPL drivers/scsi/scsi_transport_srp 0xf1419c1b	srp_release_transport
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x0b61ff1d	spi_bitbang_stop
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x2138ce2f	spi_bitbang_setup
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x302b1986	spi_bitbang_setup_transfer
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x4f42ee42	spi_bitbang_start
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0x5a64848e	spi_bitbang_cleanup
+EXPORT_SYMBOL_GPL drivers/spi/spi_bitbang 0xffb87e30	spi_bitbang_transfer
+EXPORT_SYMBOL_GPL drivers/uio/uio 0x8ed13dbf	uio_event_notify
+EXPORT_SYMBOL_GPL drivers/uio/uio 0xa0f94229	__uio_register_device
+EXPORT_SYMBOL_GPL drivers/uio/uio 0xae5c7bd6	uio_unregister_device
+EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x25a0210c	usbatm_usb_probe
+EXPORT_SYMBOL_GPL drivers/usb/atm/usbatm 0x2e3e35a6	usbatm_usb_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x02797cf4	usb_alloc_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x032f4aa0	usb_set_device_state
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x06f17256	usb_match_one_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x098d3a6f	usb_hub_clear_tt_buffer
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0e4382ce	usb_buffer_unmap_sg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x0f06455a	usb_get_status
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x100c13c6	usb_kill_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x18157b4b	usb_buffer_map_sg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1966fe2e	usb_unpoison_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x19a304ba	usb_disabled
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1a9b538e	ehci_cf_port_reset_rwsem
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1afbd166	usb_buffer_free
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1db291e3	usb_hc_died
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1ddbf8a8	usb_store_new_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1e9afe5d	usb_hcd_unlink_urb_from_ep
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x1ef9b5e8	usb_mon_register
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x2446382c	usb_hcd_pci_remove
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x25899441	usb_hcd_pci_shutdown
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x302dee1f	usb_get_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x326d2ee8	usb_register_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x334eeb87	usb_poison_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x34243707	usb_buffer_alloc
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x356cb6f0	usb_lock_device_for_reset
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x360700fd	usb_queue_reset_device
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x366c7814	usb_get_current_frame_number
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x37854e2e	usb_match_id
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x37b071c6	usb_bus_list_lock
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3be89d3c	usb_register_notify
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x3f740f09	usb_autopm_put_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x40715bcd	usb_get_from_anchor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x421cbc48	usb_find_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x429bcc55	usb_register_device_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4604b723	usb_altnum_to_altsetting
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x46d23286	usb_deregister_device_driver
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4a11ea50	usb_driver_claim_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4c2cea5a	usb_get_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4db28a15	usb_reset_configuration
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x4f304d0d	usb_reset_endpoint
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5220711b	usb_create_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5483f333	usb_get_descriptor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x563a7bc3	usb_root_hub_lost_power
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x582d5f04	usb_string
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x594a2277	usb_hcd_check_unlink_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5bdd73ae	usb_put_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5db9c477	usb_put_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5e9b0ad7	usb_hcd_giveback_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x5fdcad59	usb_ep0_reinit
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x653d8604	usb_hcd_pci_pm_ops
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x67e13c3e	usb_kill_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x691d0d4a	usb_unlink_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x6a1cc92d	usb_bulk_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x702f9988	usb_sg_cancel
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x71b0168d	usb_interrupt_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x722c4f65	usb_scuttle_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x777e8999	usb_free_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x77f32285	usb_deregister
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7d21ff60	usb_init_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x7e64181d	usb_calc_bus_time
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x81025107	usb_autopm_set_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x829c8151	usb_submit_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8401915f	usb_debug_root
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x844f52bf	usb_sg_init
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x85896b9c	usb_add_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x8b72be43	usb_clear_halt
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x91482eef	usb_anchor_empty
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x93995c44	usb_deregister_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x961ab892	usb_control_msg
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x97969a0b	usb_hcd_link_urb_to_ep
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9924c496	__usb_get_extra_descriptor
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9984c858	usb_unpoison_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0x9a960f9e	usb_hcd_resume_root_hub
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa0f27808	usb_register_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa28d8527	usb_poison_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xa5160f03	usb_driver_release_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xace5c0fc	usb_bus_list
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xafc7c996	usb_unlink_anchored_urbs
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb006c562	usb_set_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xb0eedea9	usb_wait_anchor_empty_timeout
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xba548428	usb_remove_hcd
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbc8ae4dd	usb_autopm_get_interface
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xbcb9a777	usb_autopm_put_interface_async
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc17515d7	usb_hcds_loaded
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc6111311	usb_anchor_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xc8a6853e	usb_driver_set_configuration
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcc72744a	usb_hcd_poll_rh_status
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcc81f8ac	usb_get_intf
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xcd2a8e7c	usb_get_dev
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd37062a6	usb_unanchor_urb
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xd4cf7d83	usb_hcd_platform_shutdown
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xdb2da516	usb_put_intf
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xe9587909	usb_unregister_notify
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xefd8cbcd	usb_autopm_get_interface_async
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf4228166	usb_sg_wait
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xf94541f9	usb_ifnum_to_if
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfa8a37f7	usb_hcd_pci_probe
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfaa3f46a	usb_reset_device
+EXPORT_SYMBOL_GPL drivers/usb/core/usbcore 0xfed11ed1	usb_mon_deregister
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x0123e6a9	usb_ftdi_elan_read_pcimem
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x3820bc8f	usb_ftdi_elan_edset_single
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x384e9a01	usb_ftdi_elan_write_pcimem
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x6f9e484f	usb_ftdi_elan_edset_setup
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x750308cd	usb_ftdi_elan_edset_empty
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x7fd86e28	ftdi_elan_gone_away
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0x91ba9fa0	usb_ftdi_elan_edset_input
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xc38948f6	usb_ftdi_elan_edset_output
+EXPORT_SYMBOL_GPL drivers/usb/misc/ftdi-elan 0xe6c91e41	usb_ftdi_elan_edset_flush
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x10a5923a	usb_serial_register
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x13e74049	usb_serial_probe
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1afcaf4f	usb_serial_handle_sysrq_char
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x1e939011	ezusb_writememory
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x343b6e7a	ezusb_set_reset
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x60d02ff4	usb_serial_generic_resume
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x6e77843f	usb_serial_deregister
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x727287d7	usb_serial_port_softint
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x81f2aa4a	usb_serial_generic_open
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x85e49ca8	usb_serial_handle_dcd_change
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x88baff07	usb_serial_generic_write_bulk_callback
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x899043cd	usb_serial_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x8a17cf60	usb_serial_handle_break
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x921f4b51	usb_serial_generic_read_bulk_callback
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0x9588e3c9	usb_serial_generic_resubmit_read_urb
+EXPORT_SYMBOL_GPL drivers/usb/serial/usbserial 0xceea5dce	usb_serial_generic_write
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x0be13004	usb_storage_usb_ids
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x3edad223	usb_usual_clear_present
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x3f9e9b4b	usb_usual_ignore_device
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0x89d4dbaf	usb_usual_check_type
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-libusual 0xcd9991a9	usb_usual_set_present
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x0a0d1e19	usb_stor_bulk_transfer_sg
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x1663c2f8	usb_stor_Bulk_transport
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x1bc3edc2	usb_stor_sense_invalidCDB
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x25f49ceb	usb_stor_set_xfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x3ecb9c08	usb_stor_disconnect
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x4aa8f097	usb_stor_probe1
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x4f839454	usb_stor_resume
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x53147032	usb_stor_bulk_transfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x657bca99	usb_stor_Bulk_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x71a41add	usb_stor_ctrl_transfer
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x775c452b	usb_stor_post_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x841bbe87	fill_inquiry_response
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x88b06717	usb_stor_CB_transport
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0x9685f9e1	usb_stor_reset_resume
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xb1268510	usb_stor_access_xfer_buf
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xc54c844f	usb_stor_clear_halt
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xc7c5b6a9	usb_stor_suspend
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xcc77d1dc	usb_stor_pre_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xcc87411b	usb_stor_CB_reset
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xccad227d	usb_stor_probe2
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xd7ff52f7	usb_stor_bulk_srb
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xf343ee0a	usb_stor_transparent_scsi_command
+EXPORT_SYMBOL_GPL drivers/usb/storage/usb-storage 0xfd8ec5ea	usb_stor_control_msg
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x4fe9d096	ili9320_write_regs
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x7365b8e0	ili9320_write
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x7ed89938	ili9320_remove
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0x9b2a24c7	ili9320_resume
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xc17fa5ba	ili9320_probe_spi
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd68d0752	ili9320_shutdown
+EXPORT_SYMBOL_GPL drivers/video/backlight/ili9320 0xd97cb3f7	ili9320_suspend
+EXPORT_SYMBOL_GPL drivers/video/fb_ddc 0x8bc91637	fb_ddc_read
+EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0x6ed0af17	fb_sys_read
+EXPORT_SYMBOL_GPL drivers/video/fb_sys_fops 0xb4eaa432	fb_sys_write
+EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x4055e944	sis_malloc_new
+EXPORT_SYMBOL_GPL drivers/video/sis/sisfb 0x4a07554d	sis_free_new
+EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x016e6c20	vmlfb_unregister_subsys
+EXPORT_SYMBOL_GPL drivers/video/vermilion/vmlfb 0x90c018c6	vmlfb_register_subsys
+EXPORT_SYMBOL_GPL fs/fat/fat 0x01ecfbae	fat_fs_error
+EXPORT_SYMBOL_GPL fs/fat/fat 0x0bb4977c	fat_setattr
+EXPORT_SYMBOL_GPL fs/fat/fat 0x1ec81eb0	fat_attach
+EXPORT_SYMBOL_GPL fs/fat/fat 0x2b2f1eb2	fat_flush_inodes
+EXPORT_SYMBOL_GPL fs/fat/fat 0x488cf285	fat_alloc_new_dir
+EXPORT_SYMBOL_GPL fs/fat/fat 0x64b1ac38	fat_build_inode
+EXPORT_SYMBOL_GPL fs/fat/fat 0x7f6fa472	fat_free_clusters
+EXPORT_SYMBOL_GPL fs/fat/fat 0x82f03143	fat_time_unix2fat
+EXPORT_SYMBOL_GPL fs/fat/fat 0x92599a93	fat_fill_super
+EXPORT_SYMBOL_GPL fs/fat/fat 0xb86d2f6b	fat_add_entries
+EXPORT_SYMBOL_GPL fs/fat/fat 0xbc80c85a	fat_detach
+EXPORT_SYMBOL_GPL fs/fat/fat 0xbeebd363	fat_search_long
+EXPORT_SYMBOL_GPL fs/fat/fat 0xc787b6aa	fat_getattr
+EXPORT_SYMBOL_GPL fs/fat/fat 0xcae819e6	fat_scan
+EXPORT_SYMBOL_GPL fs/fat/fat 0xcb141849	fat_get_dotdot_entry
+EXPORT_SYMBOL_GPL fs/fat/fat 0xe00be19e	fat_remove_entries
+EXPORT_SYMBOL_GPL fs/fat/fat 0xf2c25658	fat_sync_inode
+EXPORT_SYMBOL_GPL fs/fat/fat 0xff5f43b2	fat_dir_empty
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x0d966842	fuse_conn_init
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x1127422f	fuse_get_req
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x1983ffcf	fuse_request_send
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x3ed001ce	fuse_dev_operations
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x40af8a65	fuse_do_open
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x4c243e3e	fuse_do_ioctl
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x6650be50	fuse_conn_put
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x6ec4847b	fuse_conn_get
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x8818a72d	fuse_direct_io
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x8820d5f2	fuse_request_alloc
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0x8bac02f1	fuse_sync_release
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xa939917c	fuse_dev_release
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xaae79e63	fuse_put_request
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xc3d4a492	fuse_request_send_background
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xc522d7ae	fuse_file_poll
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xce8bda54	fuse_abort_conn
+EXPORT_SYMBOL_GPL fs/fuse/fuse 0xddcc6785	fuse_conn_kill
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x17ce645d	locks_end_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x1a618932	nlmsvc_unlock_all_by_ip
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x39bd2333	nlmclnt_done
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x6f959b35	locks_in_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0x96877ac4	locks_start_grace
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xa7b91a7b	lockd_down
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xcb7f0150	nlmclnt_proc
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xe7749c85	nlmclnt_init
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xeb9ed8d0	nlmsvc_ops
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xf07efc4a	nlmsvc_unlock_all_by_sb
+EXPORT_SYMBOL_GPL fs/lockd/lockd 0xf6933c48	lockd_up
+EXPORT_SYMBOL_GPL fs/nfs_common/nfs_acl 0x0ad691bf	nfsacl_encode
+EXPORT_SYMBOL_GPL fs/nfs_common/nfs_acl 0x141c4911	nfsacl_decode
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x19c01110	o2nm_get_node_by_ip
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1b89c6ee	o2hb_fill_node_map
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x1d747ce3	o2hb_check_node_heartbeating
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x235529c8	o2hb_register_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x36418553	o2net_send_message
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4050a714	o2nm_get_node_by_num
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x4900035b	o2hb_stop_all_regions
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x521e0726	o2net_send_message_vec
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x81a17396	mlog_and_bits
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x81e7e9b1	o2nm_node_put
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0x838e7dc0	o2hb_unregister_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa82a8645	o2nm_this_node
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xa87bc9e7	o2nm_configured_node_map
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xaca40c5c	o2nm_node_get
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xae808bac	o2net_register_handler
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xbaeb4700	o2hb_check_node_heartbeating_from_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xcc024067	o2hb_setup_callback
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xd60f2c6c	o2hb_check_local_node_heartbeating
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf1a5611d	o2net_unregister_handler_list
+EXPORT_SYMBOL_GPL fs/ocfs2/cluster/ocfs2_nodemanager 0xf56c2017	mlog_not_bits
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x0a51bf5c	dlm_unregister_domain
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x1f03eace	dlm_register_domain
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x207d776e	dlmlock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0x7a1211f8	dlm_setup_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xaf5731c8	dlm_print_one_lock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd7ba575e	dlm_errmsg
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xd8fa57a6	dlm_unregister_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xeb47d5f3	dlmunlock
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xee5e85b0	dlm_register_eviction_cb
+EXPORT_SYMBOL_GPL fs/ocfs2/dlm/ocfs2_dlm 0xfb86b96f	dlm_errname
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0562c415	ocfs2_cluster_this_node
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x06379db6	ocfs2_dlm_lvb_valid
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0dd8a92e	ocfs2_plock
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x0e27f909	ocfs2_dlm_lock
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x21db5b88	ocfs2_cluster_disconnect
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4281e740	ocfs2_stack_glue_register
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4a1f6fe9	ocfs2_cluster_connect
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x4d3af7fa	ocfs2_cluster_hangup
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x73e3b557	ocfs2_stack_glue_unregister
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x81c85a68	ocfs2_dlm_lock_status
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x91fab465	ocfs2_dlm_lvb
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0x963932a3	ocfs2_stack_glue_set_locking_protocol
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xa7d5c1c0	ocfs2_dlm_unlock
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xbbc4ef97	ocfs2_stack_supports_plocks
+EXPORT_SYMBOL_GPL fs/ocfs2/ocfs2_stackglue 0xd066711e	ocfs2_dlm_dump_lksb
+EXPORT_SYMBOL_GPL lib/lzo/lzo_compress 0x2e1d43cf	lzo1x_1_compress
+EXPORT_SYMBOL_GPL lib/lzo/lzo_decompress 0x2a1538ca	lzo1x_decompress_safe
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x300d7e57	free_rs
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0x6fbb3bd9	init_rs_non_canonical
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xabda1e2e	decode_rs16
+EXPORT_SYMBOL_GPL lib/reed_solomon/reed_solomon 0xb050f329	init_rs
+EXPORT_SYMBOL_GPL net/802/garp 0x20837c60	garp_uninit_applicant
+EXPORT_SYMBOL_GPL net/802/garp 0x5655e552	garp_request_join
+EXPORT_SYMBOL_GPL net/802/garp 0x7e7f6ae6	garp_init_applicant
+EXPORT_SYMBOL_GPL net/802/garp 0xc478a291	garp_register_application
+EXPORT_SYMBOL_GPL net/802/garp 0xe483f7a3	garp_unregister_application
+EXPORT_SYMBOL_GPL net/802/garp 0xf4d21f9a	garp_request_leave
+EXPORT_SYMBOL_GPL net/802/stp 0xa399408b	stp_proto_unregister
+EXPORT_SYMBOL_GPL net/802/stp 0xa7a2b56a	stp_proto_register
+EXPORT_SYMBOL_GPL net/ax25/ax25 0x320a834b	ax25_register_pid
+EXPORT_SYMBOL_GPL net/ax25/ax25 0xac93ae05	ax25_bcast
+EXPORT_SYMBOL_GPL net/ax25/ax25 0xaeb7451e	ax25_defaddr
+EXPORT_SYMBOL_GPL net/bluetooth/bluetooth 0xfcf30d75	bt_class
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x00eedd61	dccp_create_openreq_child
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x1cf59b8c	inet_dccp_listen
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x1d99d49a	dccp_timestamp
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x20444bd7	dccp_reqsk_send_ack
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x25704936	dccp_sendmsg
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x2e6e3422	dccp_close
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x34ba38ee	dccp_parse_options
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x35c987ba	dccp_poll
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x37758079	dccp_shutdown
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x42fbd3ec	dccp_done
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x4cdd391d	dccp_feat_list_purge
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x52cb5534	dccp_ctl_make_reset
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x53bdc1e4	dccp_reqsk_init
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x564793b6	dccp_make_response
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x56ea266a	dccp_state_name
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x5a80e9f3	dccp_connect
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x5bf0184b	compat_dccp_setsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x6120495e	dccp_sync_mss
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x65cb21fa	dccp_insert_option_elapsed_time
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x6e291193	dccp_insert_option
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x70b1d967	dccp_orphan_count
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x71ab7e1f	dccp_ioctl
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x86be7924	dccp_packet_name
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x879e3094	dccp_hashinfo
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b23d73b	dccp_insert_option_timestamp
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b65bbee	dccp_child_process
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8b7d8caf	dccp_statistics
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x8c2c5227	dccp_disconnect
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x90124d35	dccp_getsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0x9523f586	dccp_setsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xa530bf90	dccp_init_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xab50c8f3	dccp_rcv_established
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xb131b88b	dccp_check_req
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xb222fa45	dccp_rcv_state_process
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xbde91f62	dccp_destroy_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xcc13919b	compat_dccp_getsockopt
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xd2540afc	dccp_set_state
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xe1c9eec1	dccp_recvmsg
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xe22a6733	dccp_send_sync
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xe71d826a	dccp_death_row
+EXPORT_SYMBOL_GPL net/dccp/dccp 0xffb11c17	dccp_send_ack
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x133d0d4e	dccp_invalid_packet
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x15fe73af	dccp_v4_send_check
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x29875f99	dccp_v4_do_rcv
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x439596dd	dccp_v4_request_recv_sock
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0x472f7ec7	dccp_v4_conn_request
+EXPORT_SYMBOL_GPL net/dccp/dccp_ipv4 0xd08e8317	dccp_v4_connect
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0x6d40a921	need_ipv4_conntrack
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_conntrack_ipv4 0xf819f4b2	nf_nat_seq_adjust_hook
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_defrag_ipv4 0x6b6c3d10	nf_defrag_ipv4_enable
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x07ae60b6	nf_nat_proto_in_range
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x2a274faa	nf_nat_icmp_reply_translation
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x431eb616	nf_nat_packet
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x493a5516	nf_nat_proto_find_get
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x559bc348	nf_nat_proto_range_to_nlattr
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x7236f08f	nf_nat_get_offset
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x912ea4f4	nf_nat_proto_unique_tuple
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0x94a08134	nf_nat_proto_nlattr_to_range
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat 0xfa778b64	nf_nat_proto_put
+EXPORT_SYMBOL_GPL net/ipv4/netfilter/nf_nat_proto_gre 0x636b12c8	nf_nat_need_gre
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x0ae04cfb	tcp_vegas_get_info
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x0b019bfb	tcp_vegas_cwnd_event
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x6678cc30	tcp_vegas_state
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x95c8610f	tcp_vegas_pkts_acked
+EXPORT_SYMBOL_GPL net/ipv4/tcp_vegas 0x9f44b9c7	tcp_vegas_init
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x08a3e5d1	net_ipv6_ctl_path
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1460ef4b	ip6_dst_blackhole
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1a4f96ff	fl6_sock_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x1bcc3e4d	inet6_csk_xmit
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x396d892c	inet6_destroy_sock
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x3a90f170	ipv6_dup_options
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x54be1bf0	inet6_sk_rebuild_header
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x576f720a	inet6_csk_reqsk_queue_hash_add
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x814b616e	ip6_sk_dst_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x85478a0b	inet6_hash_frag
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0x9cde42ce	ipv6_opt_accepted
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xc3a83877	inet6_csk_search_req
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xce1cfda1	ip6_local_out
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xd746a100	ip6_dst_lookup
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xe3c9f625	inet6_csk_addr2sockaddr
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xe5d4c290	ipv6_find_tlv
+EXPORT_SYMBOL_GPL net/ipv6/ipv6 0xf5ee4ce2	inet6_csk_bind_conflict
+EXPORT_SYMBOL_GPL net/mac80211/mac80211 0x5d385daf	ieee80211_iterate_active_interfaces_atomic
+EXPORT_SYMBOL_GPL net/mac80211/mac80211 0xa6b88230	ieee80211_iterate_active_interfaces
+EXPORT_SYMBOL_GPL net/netfilter/ipvs/ip_vs 0xe6476b4a	net_vs_ctl_path
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x014762f6	nf_conntrack_tuple_taken
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x041013fd	nf_conntrack_lock
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x045072cd	nf_ct_port_nla_policy
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x04cea8c9	nf_ct_expect_related_report
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x05d66a41	nf_ct_unexpect_related
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x1452b9b8	seq_print_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x16461165	print_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x21a07059	nf_ct_expect_unregister_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x26564482	nf_ct_iterate_cleanup
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x31bdbf55	nf_ct_expect_init
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x35cb1434	nf_ct_helper_ext_add
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3647d78f	nf_conntrack_alter_reply
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x39822f64	nf_ct_expect_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f41615b	__nf_conntrack_helper_find_byname
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3f5b1415	nf_ct_port_nlattr_to_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x3fcbd504	nf_conntrack_free
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x484f9cc3	nf_ct_extend_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4b9065a9	nf_ct_alloc_hashtable
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x4c4b60ff	nfnetlink_parse_nat_setup_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x55c2e6e9	nf_ct_remove_expectations
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5882ba33	nf_conntrack_set_hashsize
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x59f81224	nf_ct_deliver_cached_events
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5bbd229d	nf_ct_l3proto_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5f310c9b	nf_conntrack_l3proto_generic
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x5f97e07d	__nf_ct_l4proto_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x60200e0b	__nf_ct_try_assign_helper
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6158e3ff	__nf_conntrack_confirm
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x62813e5c	nf_ct_port_nlattr_tuple_size
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x64719e92	nf_conntrack_l3proto_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x661fdf53	nf_conntrack_event_cb
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6c696452	nf_ct_get_tuplepr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x6e224a7a	need_conntrack
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x70a34978	nf_ct_invert_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x78f9b710	nf_ct_l3proto_try_module_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x7db00c81	nf_conntrack_hash_insert
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x81adbe05	nf_ct_l3proto_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8227c491	nf_ct_port_tuple_to_nlattr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8898889b	nf_conntrack_alloc
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8e5ff91b	nf_conntrack_in
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x8ffe7e89	nf_conntrack_htable_size
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x90ff6c9f	nf_ct_invert_tuplepr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x92910e40	nf_conntrack_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x958ec75e	nf_ct_delete_from_lists
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x98722023	nf_ct_nat_offset
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9a46e497	nf_ct_extend_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9af3f6c1	nf_ct_free_hashtable
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0x9d47fe2a	nf_conntrack_l4proto_udp6
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa18fb62f	nf_conntrack_l4proto_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa25aa026	nf_conntrack_unregister_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xa4c56259	nf_conntrack_flush_report
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaa54c1d8	__nf_conntrack_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xaf719ca8	nf_conntrack_l4proto_udp4
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb22c1e2d	nf_ct_get_tuple
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb2a18cc9	nf_ct_expect_alloc
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb2e86fb7	nf_ct_unlink_expect
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb574b093	nf_conntrack_l4proto_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb602c57e	nf_ct_l3proto_module_put
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb6470c26	nf_ct_l3protos
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb80f54f1	nf_expect_event_cb
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb82b4d25	__nf_ct_refresh_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xb9ad95eb	nf_ct_expect_find_get
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xbc590bf1	nf_ct_expect_register_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xc18ac88d	nf_ct_expect_hsize
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xcb18d1d1	nf_conntrack_helper_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xd06b07b8	nf_conntrack_l4proto_tcp6
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xdd49d0e4	nf_conntrack_helper_register
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe25d653a	nf_conntrack_l4proto_tcp4
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe56e6ced	nf_conntrack_untracked
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xe672133c	__nf_ct_expect_find
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf38bcdf3	nf_conntrack_max
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf3a0f636	nf_conntrack_register_notifier
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf52cc003	nf_ct_insert_dying_list
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xf742e8d3	nf_conntrack_l3proto_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack 0xfe1f7f33	__nf_ct_kill_acct
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_amanda 0x2574f0c6	nf_nat_amanda_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_ftp 0xe7e83213	nf_nat_ftp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x0d9e7820	set_ras_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x214c443f	nat_q931_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x58e353f3	nat_rtp_rtcp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x7d2c68e0	nat_callforwarding_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0x92d549d7	nat_h245_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xa4a1fad2	get_h225_addr
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xbdcdb5b1	nat_t120_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xc41c1929	set_h225_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xca499a1b	set_sig_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_h323 0xf6e786e4	set_h245_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_irc 0x978de3e2	nf_nat_irc_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0x73743c6c	nf_nat_pptp_hook_outbound
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xa937bd71	nf_nat_pptp_hook_inbound
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xb512f398	nf_nat_pptp_hook_exp_gre
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_pptp 0xd602ce71	nf_nat_pptp_hook_expectfn
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x34df3b78	nf_ct_gre_keymap_add
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_proto_gre 0x771368be	nf_ct_gre_keymap_destroy
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x083966bd	nf_nat_sdp_port_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x294c2f49	nf_nat_sdp_addr_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x3b8899eb	nf_nat_sdp_media_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x499c94f8	nf_nat_sip_expect_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x51e4792f	ct_sip_get_sdp_header
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x53aa6cc6	ct_sip_get_header
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x87449455	ct_sip_parse_numerical_param
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0x8f27642b	ct_sip_parse_header_uri
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xa9cd9e08	ct_sip_parse_address_param
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xea7158da	nf_nat_sip_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xf633939d	nf_nat_sdp_session_hook
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_sip 0xffe0e691	ct_sip_parse_request
+EXPORT_SYMBOL_GPL net/netfilter/nf_conntrack_tftp 0x00dbea9e	nf_nat_tftp_hook
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x1f58e71b	nfnl_lock
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x2453d787	nfnetlink_subsys_unregister
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x26fa137f	nfnetlink_send
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x3895cd7a	nfnl_unlock
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0x7a91f055	nfnetlink_unicast
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xce5d768d	nfnetlink_subsys_register
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xeca95329	nfnetlink_has_listeners
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink 0xef9b4bbd	nfnetlink_set_err
+EXPORT_SYMBOL_GPL net/netfilter/nfnetlink_log 0xa6bcc35c	nfulnl_log_packet
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x161d1417	xt_compat_unlock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x170080a4	xt_compat_target_from_user
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x1f4b4ba2	xt_compat_target_offset
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x26c53259	xt_replace_table
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x2ddb6035	xt_proto_init
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x40728a63	xt_find_revision
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x4f432b51	per_cpu__xt_info_locks
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x5f82f1f7	xt_compat_flush_offsets
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x6090ea29	xt_check_target
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x684694c5	xt_compat_add_offset
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x6f9aa2fb	xt_compat_calc_jump
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x74748203	xt_unregister_table
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x7db5400e	xt_proto_fini
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x8061cbd8	xt_compat_match_offset
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x9777a112	xt_compat_match_to_user
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0x9a40df37	xt_register_table
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xaa17236b	xt_check_match
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xb5965e48	xt_compat_match_from_user
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xbc16cdf9	xt_find_table_lock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xd9f8072c	xt_table_unlock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe0b4971b	xt_compat_lock
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe431c2e5	xt_request_find_target
+EXPORT_SYMBOL_GPL net/netfilter/x_tables 0xe67e21c5	xt_compat_target_to_user
+EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xc2429b63	xt_rateest_lookup
+EXPORT_SYMBOL_GPL net/netfilter/xt_RATEEST 0xfc852663	xt_rateest_put
+EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0x99e3a3a4	rxrpc_unregister_security
+EXPORT_SYMBOL_GPL net/rxrpc/af-rxrpc 0xa9518ea9	rxrpc_register_security
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x00c52ef5	g_make_token_header
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x065d3baa	svc_gss_principal
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x26bea7f1	gss_mech_get
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x299a1133	gss_mech_register
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x7925c69f	gss_mech_get_by_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x79a60f04	gss_service_to_auth_domain_name
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0x8d1a827e	svcauth_gss_register_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xa78afb05	svcauth_gss_flavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xb1212b36	gss_pseudoflavor_to_service
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xb153853b	gss_mech_get_by_name
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xb5dea7ef	g_token_size
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xd3a5d00e	gss_mech_put
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xe3fc6968	gss_mech_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xe8ca3fbf	gss_svc_to_pseudoflavor
+EXPORT_SYMBOL_GPL net/sunrpc/auth_gss/auth_rpcgss 0xf8b2ff6e	g_verify_token_header
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x027061dc	svc_xprt_enqueue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x04aaaf79	svc_exit_thread
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x05e807a9	xdr_encode_string
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x065994f1	xdr_encode_opaque_fixed
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0882802e	svc_reg_xprt_class
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0a462cb0	svc_set_num_threads
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0ab71ebf	xdr_write_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0b9220f4	rpc_alloc_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0c1302d3	rpc_peeraddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0c2f290f	sunrpc_cache_unregister_pipefs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0db0c0c3	xprt_adjust_cwnd
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0efcda21	rpc_pton
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0f668ba9	svc_auth_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x0f6d1c40	xdr_buf_from_iov
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x105563bb	xdr_inline_decode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x12e280e3	svc_proc_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x13000da9	xdr_encode_array2
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x1f02b597	xdr_reserve_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x244d31e5	rpc_mkpipe
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2532d02a	svc_print_addr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x25e3d55e	rpc_queue_upcall
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x28b38747	svc_unreg_xprt_class
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2919b156	xdr_decode_string_inplace
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2a04d730	rpcauth_init_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2a129233	xdr_shift_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2a6d8e57	rpc_bind_new_program
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2aa17774	rpc_free_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2b334195	xdr_partial_copy_from_skb
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2c1c9b9d	auth_domain_find
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x2eec63c9	xdr_encode_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x31a89d59	rpc_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x32abeeba	xprt_reserve_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x344fe370	svc_wake_up
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3675e76e	rpc_delay
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3a6650bf	xprt_reserve_xprt_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3a7ad032	rpc_print_iostats
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3b2b774f	auth_unix_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3bc1a288	xdr_init_decode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3e735724	svc_sock_destroy
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3f69647d	svc_sock_names
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x3fa4d811	svc_drop
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x42238a74	svc_find_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x44533326	rpc_sleep_on
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x44b8abb3	svc_addsock
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4870ecf4	rpc_proc_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x49c3aab7	sunrpc_cache_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4a219ef3	svc_xprt_copy_addrs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x4c9d20b7	rpc_unlink
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x53445f68	nlm_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5420a2af	auth_unix_add_addr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x54a9aaf3	xdr_init_encode
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x54e72e29	__rpc_wait_for_completion_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x550547a3	rpc_destroy_wait_queue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x552b6d02	xdr_decode_word
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5566a5c7	svc_close_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x57c23f50	xdr_process_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5b14ec1a	rpc_put_mount
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5b670c89	rpc_malloc
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bb9e6d6	xprt_release_xprt_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5bd26000	rpc_proc_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5e842f95	rpcb_getport_async
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x5eba3736	rpc_restart_call
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x61e47a33	xdr_buf_subsegment
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x63696ffd	svc_create_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x637474ff	rpc_wake_up_next
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x64100e68	rpc_peeraddr2str
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x66b48e05	rpcauth_generic_bind_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x675524ec	rpc_sockaddr2uaddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x68b636da	xprt_wait_for_buffer_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x69ef4c4e	auth_unix_forget_old
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6ae5a11f	svc_recv
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6c5304c5	rpcb_getport_sync
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6da32c1c	put_rpccred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x6eea229d	svcauth_unix_purge
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x71fa908a	cache_flush
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7231219c	rpc_ntop
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x75aa045a	svc_auth_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x761cae29	svc_xprt_init
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x76ba5ccf	rpc_call_sync
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x775adaf6	rpc_uaddr2sockaddr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7dbf244b	svc_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7de53067	rpc_init_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7e4c98bc	sunrpc_cache_update
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x7e5cc12a	xdr_read_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x803fa8c7	csum_partial_copy_to_xdr
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8089901f	read_bytes_from_xdr_buf
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x858ee9aa	cache_purge
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x880be36d	rpcauth_lookup_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x899f99c3	rpc_exit_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x89dbf87c	rpc_lookup_machine_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x8ff0fa29	svc_proc_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x900a4218	sunrpc_cache_register_pipefs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x905bdb2d	xdr_inline_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x92bab90e	rpcauth_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x94a44ae0	xprt_register_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9580c01f	rpc_wake_up_queued_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x959d8156	cache_check
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9a0f185f	auth_domain_lookup
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9bbc4fe1	rpc_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9bf74f8b	rpcauth_destroy_credcache
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0x9d3e2f58	rpc_force_rebind
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa0abe5ac	xprt_write_space
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa1028871	rpc_call_start
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa1d46bdf	svc_create_pooled
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa2ad367d	xprt_release_rqst_cong
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa521d752	rpc_get_mount
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa55379d5	svc_destroy
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa676e343	rpc_call_async
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa6ef8c5d	rpc_clone_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xa72a222c	svc_xprt_received
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaa3ce2e8	xprt_wake_pending_tasks
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xaf5bf6ef	nfs_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb00a7729	svc_seq_show
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb26ffa65	xprt_release_xprt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb387b246	rpc_wake_up_status
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xb6eaccc5	cache_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbcfa34ca	unix_domain_find
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf991cc3	rpc_put_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xbf9d1b96	nfsd_debug
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc02c6728	xprt_disconnect_done
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc0a57240	svc_xprt_names
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc1130f36	svc_process
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc12435e3	rpc_calc_rto
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc273fcab	rpc_lookup_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc3880471	xdr_decode_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc3ff6ed4	auth_domain_put
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc4ee94f8	svc_reserve
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc65648f8	rpc_killall_tasks
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc6fbd985	xprt_set_retrans_timeout_def
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc706630a	xdr_decode_array2
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc7ea76df	xprt_complete_rqst
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc8e96dea	qword_addhex
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xc920f4ee	rpc_restart_call_prepare
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcd61dc2a	rpcauth_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xcee467f3	xprt_load_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd1154b66	rpc_shutdown_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd14ca3b7	cache_register
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd2925de9	xprt_lookup_rqst
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xd82c728e	rpc_init_wait_queue
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xda40a2b3	xdr_buf_read_netobj
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdd766c99	xdr_encode_word
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xddfd0bcc	svc_xprt_put
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xde4bcfd1	svc_max_payload
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xde9b309f	xdr_enter_page
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdf8bde27	rpcauth_unregister
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xdfe3a24d	svc_authenticate
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe3beada7	sunrpc_cache_pipe_upcall
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe425bd9e	xprt_set_retrans_timeout_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe4ec5477	rpc_setbufsize
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe5919cb1	xdr_encode_opaque
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xe97f4ce5	qword_get
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeac05ab5	svcauth_unix_set_client
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xecdc6b69	xprt_unregister_transport
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedcf6be4	qword_add
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xedd1ba52	rpc_wake_up
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xeeacab69	rpc_update_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf0095506	svc_sock_update_bufs
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf1b8bb41	svc_sock_create
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf1be666f	rpc_max_payload
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf717feb7	xprt_update_rtt
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf727891f	rpc_run_task
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf7397696	xdr_encode_pages
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf74f4d48	rpcauth_init_cred
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf7939207	svc_prepare_thread
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf7b5d7f8	rpc_call_null
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xf9d1164c	rpc_free
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfa86f60d	xdr_skb_read_bits
+EXPORT_SYMBOL_GPL net/sunrpc/sunrpc 0xfc04f575	svc_set_client
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x07afd178	cfg80211_wext_giwencode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x0fc8db45	cfg80211_wext_siwfreq
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x1636f03b	cfg80211_wext_siwfrag
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x1663f910	cfg80211_wext_giwauth
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x256ba2cc	cfg80211_wireless_stats
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x28324a2f	cfg80211_wext_siwmode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x31843720	cfg80211_wext_siwscan
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x3271d41b	cfg80211_wext_siwmlme
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x36d1dbaa	cfg80211_wext_giwname
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x3e785cfa	cfg80211_wext_giwfreq
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x4d8558d8	cfg80211_wext_giwtxpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x4d8ce78a	cfg80211_wext_siwauth
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x4dd9eea1	cfg80211_wext_giwfrag
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x5514a101	cfg80211_wext_giwap
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x760ed564	cfg80211_wext_siwencode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x7ac42f8a	cfg80211_wext_giwscan
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x85f24a69	cfg80211_wext_giwessid
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x8b1df1af	cfg80211_wext_siwap
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x8c61e736	cfg80211_wext_siwgenie
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0x9573df2d	cfg80211_wext_siwessid
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xac9fb03d	cfg80211_wext_siwtxpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xbacc83f7	cfg80211_wext_giwrate
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xbb37034f	cfg80211_wext_siwencodeext
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xbc4d7be0	cfg80211_wext_giwmode
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xcacce80a	cfg80211_wext_giwrange
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xcb6b5ffd	cfg80211_wext_giwpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xdbeacab9	cfg80211_wext_siwpower
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xdc64afc7	cfg80211_wext_siwrts
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xe1239d6d	cfg80211_wext_siwrate
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xebdecaac	cfg80211_wext_giwretry
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xedd42878	cfg80211_wext_giwrts
+EXPORT_SYMBOL_GPL net/wireless/cfg80211 0xfb5f5fe8	cfg80211_wext_siwretry
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x06f4dc55	ipcomp_input
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x14acc6e2	ipcomp_destroy
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0x44f46d94	ipcomp_init_state
+EXPORT_SYMBOL_GPL net/xfrm/xfrm_ipcomp 0xcd48c6c8	ipcomp_output
+EXPORT_SYMBOL_GPL sound/core/snd-pcm 0xa286a234	snd_pcm_format_name
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x043d6c90	snd_hda_mixer_amp_volume_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x0554e3a9	snd_hda_bind_sw
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x09f1f80f	snd_hda_power_down
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x171fcbff	snd_hda_set_vmaster_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x19c6ca61	snd_hda_ch_mode_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x1a37aa3a	snd_hda_sequence_write
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x1a996b1a	snd_hda_get_sub_nodes
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x1c47569d	snd_hda_multi_out_dig_open
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x201b8164	snd_hda_mixer_amp_volume_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x29bd8f5b	snd_hda_multi_out_dig_prepare
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x2c63a37d	query_amp_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x31a4e97b	snd_hda_suspend
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x356c94a9	snd_hda_multi_out_dig_cleanup
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x36a69b21	snd_hda_check_board_codec_sid_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x37d6266c	snd_hda_mixer_bind_ctls_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x3f448219	snd_hda_bind_vol
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4096112b	snd_hda_multi_out_dig_close
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x421c4496	snd_hda_codec_write_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4430e583	snd_hda_codec_amp_stereo
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x47a0a26f	snd_hda_mixer_amp_switch_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4af70174	snd_hda_create_spdif_out_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x4ef49942	snd_hda_build_controls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x52bcfa5d	snd_hda_queue_unsol_event
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x546930c9	snd_hda_add_codec_preset
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x575a712c	snd_hda_codec_setup_stream
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x5760ac11	snd_hda_codec_read
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x58c31db5	snd_hda_create_spdif_share_sw
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x5a90c0c9	snd_hda_find_mixer_ctl
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x5ae76f73	auto_pin_cfg_labels
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x63864f9b	snd_hda_mixer_amp_switch_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x67fdd1f8	snd_hda_create_spdif_in_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x76616c93	snd_hda_codec_cleanup_stream
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x7d1dfb84	snd_hda_override_amp_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x7fb17f32	snd_hda_mixer_bind_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x813418c1	snd_hda_multi_out_analog_cleanup
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x823ccd16	snd_hda_ch_mode_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x83916440	snd_hda_codec_write
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x864ee99b	snd_hda_ch_mode_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x87e9bdd4	snd_hda_input_mux_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x8be10862	snd_hda_mixer_bind_ctls_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x8fb234b9	snd_hda_codec_get_pincfg
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9a8e1877	snd_array_free
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9c047108	snd_hda_mixer_bind_switch_put
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9c9025f5	snd_hda_codec_resume_amp
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0x9d2af91b	snd_hda_codec_resume_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa2827d76	snd_hda_get_jack_location
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xa860e4e0	snd_hda_add_new_ctls
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xaa6ef20f	snd_hda_get_connections
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xacbc2f1a	snd_hda_mixer_amp_tlv
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xad87613e	snd_print_pcm_rates
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xafc7e596	snd_hda_mixer_bind_ctls_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb0f3917d	snd_hda_delete_codec_preset
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb22b912b	snd_hda_build_pcms
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb26a9d4a	snd_hda_power_up
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb62de428	snd_hda_multi_out_analog_prepare
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb7402939	snd_hda_parse_pin_def_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb80a429e	snd_hda_mixer_amp_volume_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xb8229cfc	snd_hda_mixer_bind_switch_get
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbaa7a5e0	snd_hda_bus_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbb8d9fe0	snd_hda_multi_out_analog_open
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbdbb46b8	snd_hda_codec_amp_update
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbe7dd7dc	snd_array_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xbee045ec	snd_hda_check_board_config
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc2799544	snd_hda_codec_configure
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc34a54c6	snd_hda_calc_stream_format
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc5abd9ac	snd_hda_ctl_add
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xc652fd69	snd_hda_get_jack_connectivity
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcb0ac16b	snd_hda_add_vmaster
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcb1ae32f	snd_hda_resume
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcb301b6e	snd_hda_get_jack_type
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xcce27eb0	snd_hda_input_mux_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xd6766a82	snd_hda_codec_amp_read
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xde88e41d	snd_hda_codec_new
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xe972200a	snd_hda_sequence_write_cache
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xeb20e985	snd_hda_query_pin_caps
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xeda3a721	snd_print_pcm_bits
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xf2f365f6	snd_hda_codec_set_pincfg
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xfaff5796	snd_hda_is_supported_format
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xfb978c61	snd_hda_mixer_amp_switch_info
+EXPORT_SYMBOL_GPL sound/pci/hda/snd-hda-codec 0xfddfedf9	snd_hda_check_amp_list_power
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x008dc1e0	snd_soc_unregister_dai
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x05316225	snd_soc_info_volsw_ext
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x054226ee	snd_soc_unregister_platform
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0ac8ae0e	snd_soc_dapm_get_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0aff84a5	snd_soc_unregister_dais
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0c154e85	snd_soc_dapm_sync
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x0de33174	snd_soc_dapm_nc_pin
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1865459c	snd_soc_dapm_put_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x18d0d2ca	snd_soc_info_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x1c05b473	snd_soc_dapm_new_controls
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x22b01164	snd_soc_dapm_new_control
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x25d6127a	snd_soc_put_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x2cc8020d	snd_soc_register_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x2dd2b046	snd_soc_dai_set_fmt
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x2fa2c57b	snd_soc_dapm_get_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x361efc58	snd_soc_get_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x36cdd73a	snd_soc_dai_set_tristate
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x370564d0	snd_soc_add_controls
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x382fe0a4	snd_soc_info_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x46decf31	snd_soc_dai_set_clkdiv
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x478ac9c0	snd_soc_jack_add_gpios
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x4d986295	snd_soc_dapm_get_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x52c06f4a	snd_soc_unregister_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x5c50f848	snd_soc_dai_digital_mute
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x61a2b983	snd_soc_put_volsw_2r
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x633fd63b	snd_soc_cnew
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6340a361	snd_soc_free_ac97_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6695fd13	snd_soc_dapm_stream_event
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x6865439b	snd_soc_dai_set_tdm_slot
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x68929f39	snd_soc_suspend_device
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x79132113	snd_soc_jack_report
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x798a2c5e	snd_soc_codec_volatile_register
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x7c743f36	snd_soc_get_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x7f96a883	snd_soc_dai_set_pll
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x82309cc9	snd_soc_get_volsw_2r
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x83e94e46	snd_soc_put_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x8fa8556d	snd_soc_info_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x92321d06	snd_soc_dapm_put_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0x960e5f5d	snd_soc_new_ac97_codec
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa45def01	snd_soc_dapm_put_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xa4efa535	snd_soc_dapm_add_routes
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xaa3b2de4	snd_soc_resume_device
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xaae6834d	snd_soc_dapm_get_pin_status
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xabb052b4	snd_soc_dapm_free
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xaf2c4714	snd_soc_dai_set_sysclk
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc12c1716	snd_soc_dapm_new_widgets
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc4e2627e	snd_soc_put_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc5974ef6	snd_soc_init_card
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xc6443730	snd_soc_get_volsw_s8
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd3a08d5c	snd_soc_dapm_get_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd55232a5	snd_soc_free_pcms
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xd64f89ec	snd_soc_get_value_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xdd10b7b5	snd_soc_codec_set_cache_io
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe011edd1	snd_soc_new_pcms
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe2db6038	snd_soc_register_dais
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe31e8581	snd_soc_dapm_info_pin_switch
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe8e4d95d	dapm_reg_event
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xe9c609e7	snd_soc_dapm_enable_pin
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xecb82a97	snd_soc_update_bits
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xed66c273	snd_soc_register_platform
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xeda45899	snd_soc_register_dai
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xedb31c79	snd_soc_info_enum_ext
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf0dc5fa0	snd_soc_set_runtime_hwparams
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf1bbb365	snd_soc_jack_add_pins
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf78b154c	snd_soc_put_enum_double
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf80b95c3	snd_soc_test_bits
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xf86fd08b	snd_soc_dapm_put_volsw
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfa428396	snd_soc_jack_free_gpios
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfb3671af	snd_soc_jack_new
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xfb56fdd8	snd_soc_dapm_disable_pin
+EXPORT_SYMBOL_GPL sound/soc/snd-soc-core 0xff2edf01	snd_soc_info_volsw_2r
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x15e0620c	xv_destroy_pool
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x4803223f	xv_malloc
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x57e771ba	xv_get_total_size_bytes
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0x88072f01	xv_create_pool
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0xaf69699e	xv_get_object_size
+EXPORT_SYMBOL_GPL ubuntu/compcache/xvmalloc 0xe878f8f2	xv_free
+EXPORT_SYMBOL_GPL vmlinux 0x002321be	crypto_alloc_instance
+EXPORT_SYMBOL_GPL vmlinux 0x003371d6	tracepoint_iter_reset
+EXPORT_SYMBOL_GPL vmlinux 0x00566d8f	inotify_get_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x008eab69	__srcu_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x00b85260	device_for_each_child
+EXPORT_SYMBOL_GPL vmlinux 0x00b8ecf8	__iowrite32_copy
+EXPORT_SYMBOL_GPL vmlinux 0x00cd845e	tcp_reno_min_cwnd
+EXPORT_SYMBOL_GPL vmlinux 0x00f356c2	led_trigger_set
+EXPORT_SYMBOL_GPL vmlinux 0x00f94fde	register_jprobes
+EXPORT_SYMBOL_GPL vmlinux 0x0157b7a9	platform_device_put
+EXPORT_SYMBOL_GPL vmlinux 0x016b9869	xfrm_calg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0x01a4ea6d	unregister_die_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x01c270bd	device_del
+EXPORT_SYMBOL_GPL vmlinux 0x024e5e3c	inet_twsk_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x0343bdf1	__i2c_board_list
+EXPORT_SYMBOL_GPL vmlinux 0x039445e0	class_dev_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0x03a3f86d	unregister_jprobe
+EXPORT_SYMBOL_GPL vmlinux 0x03a48a1e	user_describe
+EXPORT_SYMBOL_GPL vmlinux 0x03cb9d1e	alloc_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x04069b1d	set_irq_nested_thread
+EXPORT_SYMBOL_GPL vmlinux 0x04486e88	rcu_batches_completed
+EXPORT_SYMBOL_GPL vmlinux 0x04823c7b	pci_slots_kset
+EXPORT_SYMBOL_GPL vmlinux 0x04a08b67	tty_prepare_flip_string_flags
+EXPORT_SYMBOL_GPL vmlinux 0x04ad974d	ring_buffer_iter_peek
+EXPORT_SYMBOL_GPL vmlinux 0x04c3f2c1	gnttab_empty_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0x04ea8706	__iowrite64_copy
+EXPORT_SYMBOL_GPL vmlinux 0x0507d130	xenbus_grant_ring
+EXPORT_SYMBOL_GPL vmlinux 0x053573a9	kobject_uevent
+EXPORT_SYMBOL_GPL vmlinux 0x054e550b	kernel_halt
+EXPORT_SYMBOL_GPL vmlinux 0x05625a54	dm_kill_unmapped_request
+EXPORT_SYMBOL_GPL vmlinux 0x060d1064	set_memory_ro
+EXPORT_SYMBOL_GPL vmlinux 0x0619ca8a	getboottime
+EXPORT_SYMBOL_GPL vmlinux 0x064db9a5	mark_mounts_for_expiry
+EXPORT_SYMBOL_GPL vmlinux 0x069b2421	crypto_ahash_digest
+EXPORT_SYMBOL_GPL vmlinux 0x07591cac	tty_mode_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0x079fb955	xfrm_audit_state_add
+EXPORT_SYMBOL_GPL vmlinux 0x07a0052a	locks_release_private
+EXPORT_SYMBOL_GPL vmlinux 0x07b52e38	rtnl_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x07ce7344	trace_seq_vprintf
+EXPORT_SYMBOL_GPL vmlinux 0x07f9cde6	rtnl_link_register
+EXPORT_SYMBOL_GPL vmlinux 0x07ff4aea	xenbus_scanf
+EXPORT_SYMBOL_GPL vmlinux 0x08071042	xfrm_audit_state_notfound
+EXPORT_SYMBOL_GPL vmlinux 0x08083909	__pneigh_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x0826e049	crypto_mod_put
+EXPORT_SYMBOL_GPL vmlinux 0x0864c4a4	dlm_new_lockspace
+EXPORT_SYMBOL_GPL vmlinux 0x08c91ea3	securityfs_create_dir
+EXPORT_SYMBOL_GPL vmlinux 0x08d8708f	cancel_work_sync
+EXPORT_SYMBOL_GPL vmlinux 0x09164094	raw_seq_stop
+EXPORT_SYMBOL_GPL vmlinux 0x091eb9b4	round_jiffies
+EXPORT_SYMBOL_GPL vmlinux 0x096061b9	crypto_register_alg
+EXPORT_SYMBOL_GPL vmlinux 0x0982c6b0	generic_fh_to_parent
+EXPORT_SYMBOL_GPL vmlinux 0x09fda3d1	blkcipher_walk_virt
+EXPORT_SYMBOL_GPL vmlinux 0x0aa3eb9c	xen_l1_entry_update
+EXPORT_SYMBOL_GPL vmlinux 0x0b07abe2	unshare_fs_struct
+EXPORT_SYMBOL_GPL vmlinux 0x0b475458	crypto_larval_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x0bb295bb	rt_mutex_trylock
+EXPORT_SYMBOL_GPL vmlinux 0x0c066a56	net_accel_xen_net_read_mac
+EXPORT_SYMBOL_GPL vmlinux 0x0c27a80a	crypto_rng_type
+EXPORT_SYMBOL_GPL vmlinux 0x0c2cdbf1	synchronize_sched
+EXPORT_SYMBOL_GPL vmlinux 0x0c648626	xfrm_audit_state_replay_overflow
+EXPORT_SYMBOL_GPL vmlinux 0x0c805f93	clflush_cache_range
+EXPORT_SYMBOL_GPL vmlinux 0x0c993cfe	devres_get
+EXPORT_SYMBOL_GPL vmlinux 0x0ca1af7c	queue_work_on
+EXPORT_SYMBOL_GPL vmlinux 0x0cb88680	__tracepoint_block_rq_remap
+EXPORT_SYMBOL_GPL vmlinux 0x0cbeede9	tty_put_char
+EXPORT_SYMBOL_GPL vmlinux 0x0d711151	blkcipher_walk_virt_block
+EXPORT_SYMBOL_GPL vmlinux 0x0d75fe5e	tty_prepare_flip_string
+EXPORT_SYMBOL_GPL vmlinux 0x0d7f9a05	gpiochip_remove
+EXPORT_SYMBOL_GPL vmlinux 0x0dc6e3c2	led_trigger_event
+EXPORT_SYMBOL_GPL vmlinux 0x0dd77309	rtnl_put_cacheinfo
+EXPORT_SYMBOL_GPL vmlinux 0x0e391b16	kill_pid_info_as_uid
+EXPORT_SYMBOL_GPL vmlinux 0x0e5aebe4	blkdev_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0x0f73520f	klist_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x0fe2d570	xenbus_directory
+EXPORT_SYMBOL_GPL vmlinux 0x10138352	tracing_on
+EXPORT_SYMBOL_GPL vmlinux 0x101c923e	__tracepoint_power_start
+EXPORT_SYMBOL_GPL vmlinux 0x1031fa57	inet_csk_reqsk_queue_hash_add
+EXPORT_SYMBOL_GPL vmlinux 0x1047ad67	kernel_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x1099799b	crypto_attr_alg2
+EXPORT_SYMBOL_GPL vmlinux 0x109f38d6	spi_setup
+EXPORT_SYMBOL_GPL vmlinux 0x10d00766	ring_buffer_swap_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x10d40e97	debugfs_create_x32
+EXPORT_SYMBOL_GPL vmlinux 0x11007e38	remove_xen_proc_entry
+EXPORT_SYMBOL_GPL vmlinux 0x110aaeac	sysdev_driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x11391c75	sock_prot_inuse_add
+EXPORT_SYMBOL_GPL vmlinux 0x118aa0bd	skcipher_geniv_free
+EXPORT_SYMBOL_GPL vmlinux 0x11a56612	bus_unregister_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x11f447ce	__gpio_to_irq
+EXPORT_SYMBOL_GPL vmlinux 0x124f2056	crypto_get_attr_type
+EXPORT_SYMBOL_GPL vmlinux 0x1251d30f	call_rcu
+EXPORT_SYMBOL_GPL vmlinux 0x1268f357	resume_device_irqs
+EXPORT_SYMBOL_GPL vmlinux 0x1282ae35	sysfs_get_dirent
+EXPORT_SYMBOL_GPL vmlinux 0x12a3fbf3	crypto_dequeue_request
+EXPORT_SYMBOL_GPL vmlinux 0x12f7c084	sysdev_driver_register
+EXPORT_SYMBOL_GPL vmlinux 0x134fb098	ring_buffer_lock_reserve
+EXPORT_SYMBOL_GPL vmlinux 0x13b2a946	register_keyboard_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x13c2ed4d	dm_underlying_device_busy
+EXPORT_SYMBOL_GPL vmlinux 0x13f52035	sysdev_register
+EXPORT_SYMBOL_GPL vmlinux 0x14335f29	net_accel_msg_peek
+EXPORT_SYMBOL_GPL vmlinux 0x14368c71	__fsnotify_parent
+EXPORT_SYMBOL_GPL vmlinux 0x14499d57	get_task_mm
+EXPORT_SYMBOL_GPL vmlinux 0x149db923	selinux_string_to_sid
+EXPORT_SYMBOL_GPL vmlinux 0x14aedb31	raw_seq_start
+EXPORT_SYMBOL_GPL vmlinux 0x15173dd6	ring_buffer_entries
+EXPORT_SYMBOL_GPL vmlinux 0x15892417	async_synchronize_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x1598dc9d	unregister_netevent_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x159aeaf6	blk_trace_remove
+EXPORT_SYMBOL_GPL vmlinux 0x15b0606e	e820_any_mapped
+EXPORT_SYMBOL_GPL vmlinux 0x15d18912	platform_device_add_data
+EXPORT_SYMBOL_GPL vmlinux 0x15e991fd	power_supply_register
+EXPORT_SYMBOL_GPL vmlinux 0x162b9858	spi_sync
+EXPORT_SYMBOL_GPL vmlinux 0x16d775af	xfrm_inner_extract_output
+EXPORT_SYMBOL_GPL vmlinux 0x16e8c28a	aead_geniv_exit
+EXPORT_SYMBOL_GPL vmlinux 0x16e90a0d	drop_file_write_access
+EXPORT_SYMBOL_GPL vmlinux 0x172b6690	cuckoo_hash_init
+EXPORT_SYMBOL_GPL vmlinux 0x17987a0d	fb_deferred_io_init
+EXPORT_SYMBOL_GPL vmlinux 0x17a052f5	crypto_init_spawn2
+EXPORT_SYMBOL_GPL vmlinux 0x17b1bb12	kobject_uevent_env
+EXPORT_SYMBOL_GPL vmlinux 0x181a5777	net_accel_update_state
+EXPORT_SYMBOL_GPL vmlinux 0x1849f5de	w1_read_block
+EXPORT_SYMBOL_GPL vmlinux 0x1861869d	device_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x1878f62b	edac_err_assert
+EXPORT_SYMBOL_GPL vmlinux 0x187c6401	device_bind_driver
+EXPORT_SYMBOL_GPL vmlinux 0x18db8a8f	platform_device_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x18ecc97d	vfs_listxattr
+EXPORT_SYMBOL_GPL vmlinux 0x18f83fab	gnttab_grant_foreign_access_ref
+EXPORT_SYMBOL_GPL vmlinux 0x191cdb9c	rtc_irq_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x19430ea5	crypto_unregister_template
+EXPORT_SYMBOL_GPL vmlinux 0x1a0c37ca	power_supply_class
+EXPORT_SYMBOL_GPL vmlinux 0x1a323362	__ftrace_vbprintk
+EXPORT_SYMBOL_GPL vmlinux 0x1a474901	tracepoint_probe_unregister_noupdate
+EXPORT_SYMBOL_GPL vmlinux 0x1a83b9a0	lookup_instantiate_filp
+EXPORT_SYMBOL_GPL vmlinux 0x1a938737	atomic_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x1ab067ea	get_driver
+EXPORT_SYMBOL_GPL vmlinux 0x1acda5b2	atomic_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x1b9aca3f	jprobe_return
+EXPORT_SYMBOL_GPL vmlinux 0x1c3af716	execute_in_process_context
+EXPORT_SYMBOL_GPL vmlinux 0x1c7b6c2a	eventfd_ctx_fdget
+EXPORT_SYMBOL_GPL vmlinux 0x1c8375b6	driver_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x1c852e7c	xfrm_calg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x1c87a811	__round_jiffies_up
+EXPORT_SYMBOL_GPL vmlinux 0x1d126028	srcu_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x1d7380bf	bus_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x1d8f8059	__tracepoint_power_end
+EXPORT_SYMBOL_GPL vmlinux 0x1db21d74	__tracepoint_kfree_skb
+EXPORT_SYMBOL_GPL vmlinux 0x1de592a9	driver_add_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x1dee2629	trace_current_buffer_lock_reserve
+EXPORT_SYMBOL_GPL vmlinux 0x1e38fd2e	raw_unhash_sk
+EXPORT_SYMBOL_GPL vmlinux 0x1e7bbcb3	kernel_restart
+EXPORT_SYMBOL_GPL vmlinux 0x1eb9516e	round_jiffies_relative
+EXPORT_SYMBOL_GPL vmlinux 0x1ebf6c2a	pci_power_names
+EXPORT_SYMBOL_GPL vmlinux 0x1ec7065b	__sock_recv_timestamp
+EXPORT_SYMBOL_GPL vmlinux 0x1ec7c5e7	sysfs_remove_group
+EXPORT_SYMBOL_GPL vmlinux 0x1ed14db5	debugfs_create_symlink
+EXPORT_SYMBOL_GPL vmlinux 0x1f02e1ab	sysdev_class_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x1f346d34	bind_interdomain_evtchn_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x1f3d1b77	crypto_alg_sem
+EXPORT_SYMBOL_GPL vmlinux 0x1f427c7b	__class_create
+EXPORT_SYMBOL_GPL vmlinux 0x1f77ffbf	per_cpu__gdt_page
+EXPORT_SYMBOL_GPL vmlinux 0x1fcece42	inet_twdr_twcal_tick
+EXPORT_SYMBOL_GPL vmlinux 0x205dcd7a	klist_add_tail
+EXPORT_SYMBOL_GPL vmlinux 0x20bc3470	orderly_poweroff
+EXPORT_SYMBOL_GPL vmlinux 0x2127d593	bus_rescan_devices
+EXPORT_SYMBOL_GPL vmlinux 0x2134a87d	class_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x213a62f1	find_get_pid
+EXPORT_SYMBOL_GPL vmlinux 0x215db6e9	tracepoint_probe_register_noupdate
+EXPORT_SYMBOL_GPL vmlinux 0x21d797b7	kobject_create_and_add
+EXPORT_SYMBOL_GPL vmlinux 0x2219ba6b	rtc_irq_set_state
+EXPORT_SYMBOL_GPL vmlinux 0x2245f41f	driver_find
+EXPORT_SYMBOL_GPL vmlinux 0x2251f326	debugfs_create_blob
+EXPORT_SYMBOL_GPL vmlinux 0x226c0e41	crypto_alg_mod_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x2296c00d	crypto_attr_u32
+EXPORT_SYMBOL_GPL vmlinux 0x235d2a4d	driver_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x2365bca6	devres_add
+EXPORT_SYMBOL_GPL vmlinux 0x23864ce7	cpuset_mem_spread_node
+EXPORT_SYMBOL_GPL vmlinux 0x2386d981	devres_remove
+EXPORT_SYMBOL_GPL vmlinux 0x23b38fa8	spi_async
+EXPORT_SYMBOL_GPL vmlinux 0x2447533c	ktime_get_real
+EXPORT_SYMBOL_GPL vmlinux 0x245a9751	crypto_init_shash_spawn
+EXPORT_SYMBOL_GPL vmlinux 0x24c7698a	xenbus_write
+EXPORT_SYMBOL_GPL vmlinux 0x24d43b60	rt_mutex_lock
+EXPORT_SYMBOL_GPL vmlinux 0x24e88875	dm_send_uevents
+EXPORT_SYMBOL_GPL vmlinux 0x24eb7e32	leds_list
+EXPORT_SYMBOL_GPL vmlinux 0x2510581d	ring_buffer_reset_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x2545373d	d_materialise_unique
+EXPORT_SYMBOL_GPL vmlinux 0x25974452	udp4_lib_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x25b41493	inotify_rm_watch
+EXPORT_SYMBOL_GPL vmlinux 0x25bec68a	inotify_add_watch
+EXPORT_SYMBOL_GPL vmlinux 0x25c0b701	rtc_set_mmss
+EXPORT_SYMBOL_GPL vmlinux 0x25cfacf8	skb_partial_csum_set
+EXPORT_SYMBOL_GPL vmlinux 0x25f97737	device_move
+EXPORT_SYMBOL_GPL vmlinux 0x2641906c	hrtimer_get_remaining
+EXPORT_SYMBOL_GPL vmlinux 0x2667710a	pci_find_ht_capability
+EXPORT_SYMBOL_GPL vmlinux 0x268d20ae	bind_listening_port_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x26ec5cb8	dlm_posix_lock
+EXPORT_SYMBOL_GPL vmlinux 0x273ae0f4	console_drivers
+EXPORT_SYMBOL_GPL vmlinux 0x27adf232	tracing_generic_entry_update
+EXPORT_SYMBOL_GPL vmlinux 0x27dac87c	ring_buffer_normalize_time_stamp
+EXPORT_SYMBOL_GPL vmlinux 0x285320d3	rtc_update_irq
+EXPORT_SYMBOL_GPL vmlinux 0x285daf2f	spi_write_then_read
+EXPORT_SYMBOL_GPL vmlinux 0x28646818	bus_find_device_by_name
+EXPORT_SYMBOL_GPL vmlinux 0x2880aebf	bus_sort_breadthfirst
+EXPORT_SYMBOL_GPL vmlinux 0x28811532	inet6_lookup_listener
+EXPORT_SYMBOL_GPL vmlinux 0x2882ee26	securityfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x28d664ff	__raw_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x28e23139	xfrm_probe_algs
+EXPORT_SYMBOL_GPL vmlinux 0x28ee80fe	alloc_empty_pages_and_pagevec
+EXPORT_SYMBOL_GPL vmlinux 0x28fc3dcb	security_inode_setattr
+EXPORT_SYMBOL_GPL vmlinux 0x291bf19f	mnt_drop_write
+EXPORT_SYMBOL_GPL vmlinux 0x29501527	klist_iter_init_node
+EXPORT_SYMBOL_GPL vmlinux 0x2960ca0f	unmask_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0x297fac1a	register_pernet_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x2a678a13	__suspend_report_result
+EXPORT_SYMBOL_GPL vmlinux 0x2a9a18fa	debugfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x2b47cde8	cuckoo_hash_remove
+EXPORT_SYMBOL_GPL vmlinux 0x2b898e85	sysdev_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x2b9f8e23	nf_net_ipv4_netfilter_sysctl_path
+EXPORT_SYMBOL_GPL vmlinux 0x2bcaa8e3	flush_work
+EXPORT_SYMBOL_GPL vmlinux 0x2bfc4d7f	tracepoint_get_iter_range
+EXPORT_SYMBOL_GPL vmlinux 0x2c208607	power_supply_is_system_supplied
+EXPORT_SYMBOL_GPL vmlinux 0x2c2a7c09	inet_twsk_schedule
+EXPORT_SYMBOL_GPL vmlinux 0x2c34576e	xen_limit_pages_to_max_mfn
+EXPORT_SYMBOL_GPL vmlinux 0x2c6a008a	hrtimer_start_range_ns
+EXPORT_SYMBOL_GPL vmlinux 0x2cb6f1d6	xen_invlpg_mask
+EXPORT_SYMBOL_GPL vmlinux 0x2ce98559	kcrypto_wq
+EXPORT_SYMBOL_GPL vmlinux 0x2d14c020	cuckoo_hash_add_check
+EXPORT_SYMBOL_GPL vmlinux 0x2d2a8871	pci_add_dynid
+EXPORT_SYMBOL_GPL vmlinux 0x2d9f2ce3	sched_clock_idle_wakeup_event
+EXPORT_SYMBOL_GPL vmlinux 0x2db66abc	generic_drop_inode
+EXPORT_SYMBOL_GPL vmlinux 0x2dbee512	bus_register
+EXPORT_SYMBOL_GPL vmlinux 0x2dd8444c	trace_seq_printf
+EXPORT_SYMBOL_GPL vmlinux 0x2dfda8c3	create_xen_proc_entry
+EXPORT_SYMBOL_GPL vmlinux 0x2e1a4db3	__trace_note_message
+EXPORT_SYMBOL_GPL vmlinux 0x2e27b3b2	input_ff_create
+EXPORT_SYMBOL_GPL vmlinux 0x2e47f677	xfrm_aalg_get_byidx
+EXPORT_SYMBOL_GPL vmlinux 0x2e903dbe	skcipher_geniv_exit
+EXPORT_SYMBOL_GPL vmlinux 0x2ec92012	scatterwalk_copychunks
+EXPORT_SYMBOL_GPL vmlinux 0x2f016780	sysdev_show_int
+EXPORT_SYMBOL_GPL vmlinux 0x2f203468	gpio_export_link
+EXPORT_SYMBOL_GPL vmlinux 0x2f57d22a	get_xen_class
+EXPORT_SYMBOL_GPL vmlinux 0x2f7068e5	tcp_reno_cong_avoid
+EXPORT_SYMBOL_GPL vmlinux 0x2fc84809	dm_path_uevent
+EXPORT_SYMBOL_GPL vmlinux 0x2fcd9e17	dpm_resume_noirq
+EXPORT_SYMBOL_GPL vmlinux 0x301719e3	crypto_ahash_final
+EXPORT_SYMBOL_GPL vmlinux 0x305a4ca5	bus_for_each_dev
+EXPORT_SYMBOL_GPL vmlinux 0x308eb636	sock_prot_inuse_get
+EXPORT_SYMBOL_GPL vmlinux 0x312001cf	driver_find_device
+EXPORT_SYMBOL_GPL vmlinux 0x313aecdc	register_kretprobe
+EXPORT_SYMBOL_GPL vmlinux 0x31869b65	devres_find
+EXPORT_SYMBOL_GPL vmlinux 0x31fb6f5e	sysfs_remove_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x325e677c	gnttab_grant_foreign_transfer_ref
+EXPORT_SYMBOL_GPL vmlinux 0x329c85ea	cuckoo_hash_update
+EXPORT_SYMBOL_GPL vmlinux 0x32a19562	pci_enable_rom
+EXPORT_SYMBOL_GPL vmlinux 0x32addda6	transport_setup_device
+EXPORT_SYMBOL_GPL vmlinux 0x32d5e7fc	xfrm_aalg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x32eec86b	disk_part_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x32f17454	ring_buffer_event_data
+EXPORT_SYMBOL_GPL vmlinux 0x33010bc1	__mnt_is_readonly
+EXPORT_SYMBOL_GPL vmlinux 0x33465c6f	register_pernet_device
+EXPORT_SYMBOL_GPL vmlinux 0x33785e32	net_accel_msg_recv_next
+EXPORT_SYMBOL_GPL vmlinux 0x338bd35e	sysfs_add_file_to_group
+EXPORT_SYMBOL_GPL vmlinux 0x33995fd2	__rtnl_register
+EXPORT_SYMBOL_GPL vmlinux 0x33ad8d5b	debugfs_create_x8
+EXPORT_SYMBOL_GPL vmlinux 0x33b52eb8	lookup_create
+EXPORT_SYMBOL_GPL vmlinux 0x33d6e412	skb_to_sgvec
+EXPORT_SYMBOL_GPL vmlinux 0x34271030	mnt_want_write
+EXPORT_SYMBOL_GPL vmlinux 0x34275124	trace_current_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0x3441c3d6	gpio_set_value_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x353cc95a	crypto_shash_final
+EXPORT_SYMBOL_GPL vmlinux 0x35ef2ef9	xfrm_audit_state_delete
+EXPORT_SYMBOL_GPL vmlinux 0x361e2bcc	save_stack_trace
+EXPORT_SYMBOL_GPL vmlinux 0x36219f4e	tracepoint_iter_stop
+EXPORT_SYMBOL_GPL vmlinux 0x362e23ec	call_rcu_bh
+EXPORT_SYMBOL_GPL vmlinux 0x363771e9	pci_scan_child_bus
+EXPORT_SYMBOL_GPL vmlinux 0x365b979d	ring_buffer_entries_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x36fddb88	power_supply_set_battery_charged
+EXPORT_SYMBOL_GPL vmlinux 0x3737a69c	rtnl_link_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x3772963e	led_trigger_show
+EXPORT_SYMBOL_GPL vmlinux 0x37ad4176	__tracepoint_block_bio_complete
+EXPORT_SYMBOL_GPL vmlinux 0x3803d904	kobject_init_and_add
+EXPORT_SYMBOL_GPL vmlinux 0x38094444	crypto_spawn_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x3809ed26	xenbus_frontend_closed
+EXPORT_SYMBOL_GPL vmlinux 0x3839febb	inet_csk_route_req
+EXPORT_SYMBOL_GPL vmlinux 0x389536a4	srcu_batches_completed
+EXPORT_SYMBOL_GPL vmlinux 0x390e931e	ring_buffer_consume
+EXPORT_SYMBOL_GPL vmlinux 0x397d4a6d	remove_irq
+EXPORT_SYMBOL_GPL vmlinux 0x39b3cf85	debugfs_create_u8
+EXPORT_SYMBOL_GPL vmlinux 0x3adcc810	crypto_alloc_ablkcipher
+EXPORT_SYMBOL_GPL vmlinux 0x3ae35ad5	gnttab_end_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0x3ae5a1a8	xenbus_dev_error
+EXPORT_SYMBOL_GPL vmlinux 0x3b8e80c1	crypto_ablkcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0x3bb224b5	class_interface_register
+EXPORT_SYMBOL_GPL vmlinux 0x3bdf5f07	hrtimer_init
+EXPORT_SYMBOL_GPL vmlinux 0x3be7af02	get_max_files
+EXPORT_SYMBOL_GPL vmlinux 0x3c29cf30	sysfs_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x3c2fa98f	crypto_init_spawn
+EXPORT_SYMBOL_GPL vmlinux 0x3c580e66	crypto_register_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0x3c639d5a	unregister_ftrace_event
+EXPORT_SYMBOL_GPL vmlinux 0x3c6c45ca	__tracepoint_power_frequency
+EXPORT_SYMBOL_GPL vmlinux 0x3c6fbc54	fs_kobj
+EXPORT_SYMBOL_GPL vmlinux 0x3c8a54da	crypto_unregister_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0x3c942368	profile_event_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x3cd06035	add_input_randomness
+EXPORT_SYMBOL_GPL vmlinux 0x3cedd960	sysfs_create_group
+EXPORT_SYMBOL_GPL vmlinux 0x3cfdfae5	trace_current_buffer_discard_commit
+EXPORT_SYMBOL_GPL vmlinux 0x3cfedb3f	register_pm_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x3d0d81ab	xfrm_audit_policy_add
+EXPORT_SYMBOL_GPL vmlinux 0x3d109ab4	fsnotify
+EXPORT_SYMBOL_GPL vmlinux 0x3d388324	dpm_resume_end
+EXPORT_SYMBOL_GPL vmlinux 0x3d51e43d	proc_net_fops_create
+EXPORT_SYMBOL_GPL vmlinux 0x3d73d3a6	crypto_destroy_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x3d7ea99a	gnttab_grant_foreign_transfer
+EXPORT_SYMBOL_GPL vmlinux 0x3dd5d829	add_timer_on
+EXPORT_SYMBOL_GPL vmlinux 0x3dde0e07	amd_get_nb_id
+EXPORT_SYMBOL_GPL vmlinux 0x3df739c3	hrtimer_try_to_cancel
+EXPORT_SYMBOL_GPL vmlinux 0x3e30fd67	fb_deferred_io_fsync
+EXPORT_SYMBOL_GPL vmlinux 0x3e3a7e99	class_compat_remove_link
+EXPORT_SYMBOL_GPL vmlinux 0x3eb53766	inet_csk_listen_stop
+EXPORT_SYMBOL_GPL vmlinux 0x3ef10c51	net_accel_msg_init_page
+EXPORT_SYMBOL_GPL vmlinux 0x3ef16299	__rtnl_link_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x3efb35c9	get_online_cpus
+EXPORT_SYMBOL_GPL vmlinux 0x3f238101	dcookie_register
+EXPORT_SYMBOL_GPL vmlinux 0x3f713b1e	inet_hashinfo_init
+EXPORT_SYMBOL_GPL vmlinux 0x3f84d4c9	gnttab_release_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x3fbdb08c	blk_queue_lld_busy
+EXPORT_SYMBOL_GPL vmlinux 0x4058f7fb	unregister_pernet_gen_device
+EXPORT_SYMBOL_GPL vmlinux 0x4082e16f	proc_net_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0x408a911f	page_cache_sync_readahead
+EXPORT_SYMBOL_GPL vmlinux 0x4091bcbf	netfront_accelerator_stop
+EXPORT_SYMBOL_GPL vmlinux 0x40ae3245	pci_renumber_slot
+EXPORT_SYMBOL_GPL vmlinux 0x40be2c41	blocking_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x4114a3e3	securityfs_remove
+EXPORT_SYMBOL_GPL vmlinux 0x415a7cd1	blk_trace_setup
+EXPORT_SYMBOL_GPL vmlinux 0x4173ed31	__inet_hash_nolisten
+EXPORT_SYMBOL_GPL vmlinux 0x41cf4105	__mmdrop
+EXPORT_SYMBOL_GPL vmlinux 0x42494cea	ring_buffer_event_length
+EXPORT_SYMBOL_GPL vmlinux 0x424acc6d	scatterwalk_done
+EXPORT_SYMBOL_GPL vmlinux 0x4275a555	crypto_alloc_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x4290e88a	rtc_update_irq_enable
+EXPORT_SYMBOL_GPL vmlinux 0x42d28749	br_handle_frame_hook
+EXPORT_SYMBOL_GPL vmlinux 0x42eee679	stop_machine
+EXPORT_SYMBOL_GPL vmlinux 0x43134d41	alloc_page_buffers
+EXPORT_SYMBOL_GPL vmlinux 0x432fd7f6	__gpio_set_value
+EXPORT_SYMBOL_GPL vmlinux 0x43f44f30	sysfs_chmod_file
+EXPORT_SYMBOL_GPL vmlinux 0x44243280	ring_buffer_free_read_page
+EXPORT_SYMBOL_GPL vmlinux 0x44398f8b	inotify_inode_queue_event
+EXPORT_SYMBOL_GPL vmlinux 0x445c71bf	tty_buffer_request_room
+EXPORT_SYMBOL_GPL vmlinux 0x445d871b	class_dev_iter_exit
+EXPORT_SYMBOL_GPL vmlinux 0x44758d20	device_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x447d1253	elv_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x4484a5a4	wait_for_device_probe
+EXPORT_SYMBOL_GPL vmlinux 0x4486ff18	dm_noflush_suspending
+EXPORT_SYMBOL_GPL vmlinux 0x44fd6f18	pci_restore_bars
+EXPORT_SYMBOL_GPL vmlinux 0x454443f4	inet_unhash
+EXPORT_SYMBOL_GPL vmlinux 0x454d5c01	blocking_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x457594fa	crypto_alg_list
+EXPORT_SYMBOL_GPL vmlinux 0x45bf1ff3	crypto_inc
+EXPORT_SYMBOL_GPL vmlinux 0x460f31aa	rodata_test_data
+EXPORT_SYMBOL_GPL vmlinux 0x4672e88b	__crypto_dequeue_request
+EXPORT_SYMBOL_GPL vmlinux 0x46a29650	platform_driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x46bd570a	pci_disable_rom
+EXPORT_SYMBOL_GPL vmlinux 0x47229b5c	gpio_request
+EXPORT_SYMBOL_GPL vmlinux 0x4743d761	single_release_net
+EXPORT_SYMBOL_GPL vmlinux 0x475648d4	dlm_posix_unlock
+EXPORT_SYMBOL_GPL vmlinux 0x479e5f20	class_interface_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x47abcc64	gpiochip_is_requested
+EXPORT_SYMBOL_GPL vmlinux 0x47bde37b	ring_buffer_overruns
+EXPORT_SYMBOL_GPL vmlinux 0x483e737f	led_trigger_set_default
+EXPORT_SYMBOL_GPL vmlinux 0x485b828f	rtc_read_time
+EXPORT_SYMBOL_GPL vmlinux 0x4892bc2d	user_instantiate
+EXPORT_SYMBOL_GPL vmlinux 0x492b42e0	gnttab_reset_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0x49749f76	set_task_ioprio
+EXPORT_SYMBOL_GPL vmlinux 0x499043d3	crypto_init_queue
+EXPORT_SYMBOL_GPL vmlinux 0x499e6685	blk_lld_busy
+EXPORT_SYMBOL_GPL vmlinux 0x49de7ed4	sysdev_store_ulong
+EXPORT_SYMBOL_GPL vmlinux 0x4a7f6258	tracepoint_iter_start
+EXPORT_SYMBOL_GPL vmlinux 0x4aa6aa47	__inet_twsk_hashdance
+EXPORT_SYMBOL_GPL vmlinux 0x4b762828	start_thread
+EXPORT_SYMBOL_GPL vmlinux 0x4bbc2141	shash_free_instance
+EXPORT_SYMBOL_GPL vmlinux 0x4c055708	put_pid
+EXPORT_SYMBOL_GPL vmlinux 0x4c08974e	kobject_get_path
+EXPORT_SYMBOL_GPL vmlinux 0x4c3f4e53	gpiochip_add
+EXPORT_SYMBOL_GPL vmlinux 0x4c5542c6	__ring_buffer_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x4c73f062	device_attach
+EXPORT_SYMBOL_GPL vmlinux 0x4c759827	byte_rev_table
+EXPORT_SYMBOL_GPL vmlinux 0x4c839854	led_trigger_register
+EXPORT_SYMBOL_GPL vmlinux 0x4c940f7d	uhci_reset_hc
+EXPORT_SYMBOL_GPL vmlinux 0x4cec82ee	crypto_chain
+EXPORT_SYMBOL_GPL vmlinux 0x4d73b199	crypto_alg_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x4d8f4c15	klist_add_before
+EXPORT_SYMBOL_GPL vmlinux 0x4db7c981	init_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0x4de613f1	ring_buffer_size
+EXPORT_SYMBOL_GPL vmlinux 0x4e59d94b	inet_csk_listen_start
+EXPORT_SYMBOL_GPL vmlinux 0x4e8c07c8	bus_find_device
+EXPORT_SYMBOL_GPL vmlinux 0x4f572a8e	net_accel_msg_send
+EXPORT_SYMBOL_GPL vmlinux 0x4f882763	ring_buffer_iter_empty
+EXPORT_SYMBOL_GPL vmlinux 0x4fd5a03d	screen_glyph
+EXPORT_SYMBOL_GPL vmlinux 0x4ffa029f	rtc_irq_register
+EXPORT_SYMBOL_GPL vmlinux 0x5030afd9	device_register
+EXPORT_SYMBOL_GPL vmlinux 0x50537395	debugfs_rename
+EXPORT_SYMBOL_GPL vmlinux 0x5066c6c7	set_cpus_allowed_ptr
+EXPORT_SYMBOL_GPL vmlinux 0x5086ac3a	alg_test
+EXPORT_SYMBOL_GPL vmlinux 0x50b319ce	cpu_bit_bitmap
+EXPORT_SYMBOL_GPL vmlinux 0x50d1f870	pgprot_writecombine
+EXPORT_SYMBOL_GPL vmlinux 0x50e7193a	__i2c_first_dynamic_bus_num
+EXPORT_SYMBOL_GPL vmlinux 0x50f5e532	call_rcu_sched
+EXPORT_SYMBOL_GPL vmlinux 0x50fad434	round_jiffies_up
+EXPORT_SYMBOL_GPL vmlinux 0x514cae9b	led_trigger_store
+EXPORT_SYMBOL_GPL vmlinux 0x526bda53	cuckoo_hash_iterate
+EXPORT_SYMBOL_GPL vmlinux 0x52701902	crypto_create_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x52999e16	register_xenbus_watch
+EXPORT_SYMBOL_GPL vmlinux 0x52d111ea	pm_qos_update_requirement
+EXPORT_SYMBOL_GPL vmlinux 0x5324d04f	bstr_printf
+EXPORT_SYMBOL_GPL vmlinux 0x53271c2e	unregister_kretprobe
+EXPORT_SYMBOL_GPL vmlinux 0x53986488	register_die_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x540d5283	net_accel_msg_send_notify
+EXPORT_SYMBOL_GPL vmlinux 0x54157acd	device_create
+EXPORT_SYMBOL_GPL vmlinux 0x5417a99d	balloon_update_driver_allowance
+EXPORT_SYMBOL_GPL vmlinux 0x5446c633	trace_define_common_fields
+EXPORT_SYMBOL_GPL vmlinux 0x5460c8d8	fsnotify_get_cookie
+EXPORT_SYMBOL_GPL vmlinux 0x549525ef	handle_nested_irq
+EXPORT_SYMBOL_GPL vmlinux 0x549546df	zap_vma_ptes
+EXPORT_SYMBOL_GPL vmlinux 0x551df858	unregister_xenbus_watch
+EXPORT_SYMBOL_GPL vmlinux 0x554dd64e	rtnl_register
+EXPORT_SYMBOL_GPL vmlinux 0x55526907	xen_features
+EXPORT_SYMBOL_GPL vmlinux 0x5565c25a	driver_attach
+EXPORT_SYMBOL_GPL vmlinux 0x557cf2e4	trace_define_field
+EXPORT_SYMBOL_GPL vmlinux 0x558d3ef3	sysdev_create_file
+EXPORT_SYMBOL_GPL vmlinux 0x55cf95e7	rtc_device_register
+EXPORT_SYMBOL_GPL vmlinux 0x55f2580b	__alloc_percpu
+EXPORT_SYMBOL_GPL vmlinux 0x56267988	free_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x56398615	mark_tsc_unstable
+EXPORT_SYMBOL_GPL vmlinux 0x563fb5c8	__trace_bprintk
+EXPORT_SYMBOL_GPL vmlinux 0x5641485b	tty_termios_encode_baud_rate
+EXPORT_SYMBOL_GPL vmlinux 0x564aa46a	anon_inode_getfile
+EXPORT_SYMBOL_GPL vmlinux 0x5664c9dc	single_open_net
+EXPORT_SYMBOL_GPL vmlinux 0x56744bb3	inotify_find_update_watch
+EXPORT_SYMBOL_GPL vmlinux 0x567dec67	raw_hash_sk
+EXPORT_SYMBOL_GPL vmlinux 0x568e55bd	net_accel_msg_reply_notify
+EXPORT_SYMBOL_GPL vmlinux 0x5779d445	xenbus_exists
+EXPORT_SYMBOL_GPL vmlinux 0x579e0bf5	rtnl_unregister_all
+EXPORT_SYMBOL_GPL vmlinux 0x584d182e	bdi_writeout_inc
+EXPORT_SYMBOL_GPL vmlinux 0x589a5ef9	pci_find_next_ht_capability
+EXPORT_SYMBOL_GPL vmlinux 0x58b1da4b	w1_read_8
+EXPORT_SYMBOL_GPL vmlinux 0x598c5470	blk_abort_request
+EXPORT_SYMBOL_GPL vmlinux 0x59d5979f	tcp_twsk_unique
+EXPORT_SYMBOL_GPL vmlinux 0x5a2b1b67	gnttab_free_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x5a48fba2	disable_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x5a7b2c6a	ring_buffer_read
+EXPORT_SYMBOL_GPL vmlinux 0x5a7bfe41	crypto_probing_notify
+EXPORT_SYMBOL_GPL vmlinux 0x5a8d6daa	device_initialize
+EXPORT_SYMBOL_GPL vmlinux 0x5a9a554d	mnt_clone_write
+EXPORT_SYMBOL_GPL vmlinux 0x5aa696b8	skb_segment
+EXPORT_SYMBOL_GPL vmlinux 0x5af03a28	gnttab_claim_grant_reference
+EXPORT_SYMBOL_GPL vmlinux 0x5b0a124e	tasklet_hrtimer_init
+EXPORT_SYMBOL_GPL vmlinux 0x5b435139	unregister_jprobes
+EXPORT_SYMBOL_GPL vmlinux 0x5bcc45b3	tcp_cong_avoid_ai
+EXPORT_SYMBOL_GPL vmlinux 0x5bfc03c3	unregister_keyboard_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x5c533bd1	default_backing_dev_info
+EXPORT_SYMBOL_GPL vmlinux 0x5c720e2f	cuckoo_hash_iterate_reset
+EXPORT_SYMBOL_GPL vmlinux 0x5d0f6f57	kbd_table
+EXPORT_SYMBOL_GPL vmlinux 0x5d289b4e	crypto_find_alg
+EXPORT_SYMBOL_GPL vmlinux 0x5d5e27c4	crypto_hash_walk_first
+EXPORT_SYMBOL_GPL vmlinux 0x5d730e7b	raw_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x5dc80172	crypto_alloc_shash
+EXPORT_SYMBOL_GPL vmlinux 0x5dd67618	register_netevent_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x5df2adc4	sysdev_class_register
+EXPORT_SYMBOL_GPL vmlinux 0x5e129978	pci_msi_off
+EXPORT_SYMBOL_GPL vmlinux 0x5e4b9d50	debugfs_create_x16
+EXPORT_SYMBOL_GPL vmlinux 0x5e69da48	register_ftrace_event
+EXPORT_SYMBOL_GPL vmlinux 0x5e9025c2	swiotlb_sync_single_range_for_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x5eab5ddc	spi_unregister_master
+EXPORT_SYMBOL_GPL vmlinux 0x5eb75420	hrtimer_init_sleeper
+EXPORT_SYMBOL_GPL vmlinux 0x5fcdec5d	xfrm_ealg_get_byidx
+EXPORT_SYMBOL_GPL vmlinux 0x600a2912	devres_close_group
+EXPORT_SYMBOL_GPL vmlinux 0x60167947	vfs_removexattr
+EXPORT_SYMBOL_GPL vmlinux 0x603c9af8	platform_device_del
+EXPORT_SYMBOL_GPL vmlinux 0x609de0f7	spi_new_device
+EXPORT_SYMBOL_GPL vmlinux 0x60a13e90	rcu_barrier
+EXPORT_SYMBOL_GPL vmlinux 0x6114d5e0	tcp_get_info
+EXPORT_SYMBOL_GPL vmlinux 0x6149570c	sync_filesystem
+EXPORT_SYMBOL_GPL vmlinux 0x6164858e	ring_buffer_record_disable_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x61747e09	blocking_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x6215cf4e	disk_get_part
+EXPORT_SYMBOL_GPL vmlinux 0x624374aa	dm_device_name
+EXPORT_SYMBOL_GPL vmlinux 0x6246a137	spi_register_master
+EXPORT_SYMBOL_GPL vmlinux 0x629a7f6e	do_posix_clock_nonanosleep
+EXPORT_SYMBOL_GPL vmlinux 0x62efd3ed	add_to_page_cache_lru
+EXPORT_SYMBOL_GPL vmlinux 0x62f3c1bb	aead_geniv_init
+EXPORT_SYMBOL_GPL vmlinux 0x634333f1	blkdev_aio_write
+EXPORT_SYMBOL_GPL vmlinux 0x63f4dc09	bprintf
+EXPORT_SYMBOL_GPL vmlinux 0x63fea108	crypto_unregister_alg
+EXPORT_SYMBOL_GPL vmlinux 0x654c49e2	aer_irq
+EXPORT_SYMBOL_GPL vmlinux 0x65871268	net_accel_msg_complete_send
+EXPORT_SYMBOL_GPL vmlinux 0x65957463	sysfs_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0x65bbbc78	schedule_hrtimeout_range
+EXPORT_SYMBOL_GPL vmlinux 0x65ccb6f0	call_netevent_notifiers
+EXPORT_SYMBOL_GPL vmlinux 0x65d6d0f0	gpio_direction_input
+EXPORT_SYMBOL_GPL vmlinux 0x6605ddae	tcp_twsk_destructor
+EXPORT_SYMBOL_GPL vmlinux 0x661601de	sprint_symbol
+EXPORT_SYMBOL_GPL vmlinux 0x665070a6	hrtimer_start
+EXPORT_SYMBOL_GPL vmlinux 0x668402aa	crypto_put_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x66b2a859	nr_free_buffer_pages
+EXPORT_SYMBOL_GPL vmlinux 0x66d87d38	symbol_put_addr
+EXPORT_SYMBOL_GPL vmlinux 0x671328af	register_pernet_gen_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x674cb444	tcp_is_cwnd_limited
+EXPORT_SYMBOL_GPL vmlinux 0x675176ea	pci_bus_max_busnr
+EXPORT_SYMBOL_GPL vmlinux 0x6785b6b9	dequeue_signal
+EXPORT_SYMBOL_GPL vmlinux 0x6792b819	add_page_wait_queue
+EXPORT_SYMBOL_GPL vmlinux 0x67955ce6	profile_hits
+EXPORT_SYMBOL_GPL vmlinux 0x67eb8463	simple_attr_read
+EXPORT_SYMBOL_GPL vmlinux 0x67f27962	rtc_class_close
+EXPORT_SYMBOL_GPL vmlinux 0x686c703f	xfrm_count_auth_supported
+EXPORT_SYMBOL_GPL vmlinux 0x688c9ada	rt_mutex_unlock
+EXPORT_SYMBOL_GPL vmlinux 0x6892088c	unregister_pm_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x68f2fd9f	tty_ldisc_flush
+EXPORT_SYMBOL_GPL vmlinux 0x6901119a	trace_nowake_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0x693aa612	ring_buffer_record_enable_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x69494666	xenbus_watch_path
+EXPORT_SYMBOL_GPL vmlinux 0x69dc6d69	cuckoo_hash_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x69f4eb1b	sysfs_put
+EXPORT_SYMBOL_GPL vmlinux 0x6a62b1d3	elv_register
+EXPORT_SYMBOL_GPL vmlinux 0x6aaafbb5	blk_trace_startstop
+EXPORT_SYMBOL_GPL vmlinux 0x6ac4fa45	blk_insert_cloned_request
+EXPORT_SYMBOL_GPL vmlinux 0x6b01fa55	sysdev_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x6b58aa4d	vfs_test_lock
+EXPORT_SYMBOL_GPL vmlinux 0x6b61fd99	uart_set_options
+EXPORT_SYMBOL_GPL vmlinux 0x6b7d98e9	__crypto_alloc_tfm
+EXPORT_SYMBOL_GPL vmlinux 0x6ba7f27a	handle_level_irq
+EXPORT_SYMBOL_GPL vmlinux 0x6bad7404	__audit_inode_child
+EXPORT_SYMBOL_GPL vmlinux 0x6be62dfd	probe_kernel_read
+EXPORT_SYMBOL_GPL vmlinux 0x6bea98f4	dm_put
+EXPORT_SYMBOL_GPL vmlinux 0x6bfb4fce	crypto_shash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x6c254d73	dev_change_net_namespace
+EXPORT_SYMBOL_GPL vmlinux 0x6c297a51	attribute_container_register
+EXPORT_SYMBOL_GPL vmlinux 0x6c776575	bus_get_kset
+EXPORT_SYMBOL_GPL vmlinux 0x6c8d5ae8	__gpio_get_value
+EXPORT_SYMBOL_GPL vmlinux 0x6c8eb98f	xfrm_aalg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0x6cad8a38	crypto_register_shash
+EXPORT_SYMBOL_GPL vmlinux 0x6d2fc5a6	net_namespace_list
+EXPORT_SYMBOL_GPL vmlinux 0x6d72e259	net_accel_ungrant_page
+EXPORT_SYMBOL_GPL vmlinux 0x6d8147d8	device_rename
+EXPORT_SYMBOL_GPL vmlinux 0x6dacbbca	crypto_alloc_instance2
+EXPORT_SYMBOL_GPL vmlinux 0x6dc431d8	fb_deferred_io_open
+EXPORT_SYMBOL_GPL vmlinux 0x6e07e94d	rtc_set_time
+EXPORT_SYMBOL_GPL vmlinux 0x6e58ddf0	gnttab_end_foreign_transfer_ref
+EXPORT_SYMBOL_GPL vmlinux 0x6e7474fc	xfrm_ealg_get_byid
+EXPORT_SYMBOL_GPL vmlinux 0x6e83cd18	crypto_register_template
+EXPORT_SYMBOL_GPL vmlinux 0x6e8644ba	unregister_pernet_subsys
+EXPORT_SYMBOL_GPL vmlinux 0x6eb22ca7	fb_deferred_io_cleanup
+EXPORT_SYMBOL_GPL vmlinux 0x6eb787ee	klist_add_head
+EXPORT_SYMBOL_GPL vmlinux 0x6fdb55b1	xenbus_free_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0x6fe3d8cf	ktime_add_safe
+EXPORT_SYMBOL_GPL vmlinux 0x6ff607b6	crypto_get_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x7037d79d	k8_flush_garts
+EXPORT_SYMBOL_GPL vmlinux 0x704eb318	inet_twsk_put
+EXPORT_SYMBOL_GPL vmlinux 0x70770ede	aead_geniv_alloc
+EXPORT_SYMBOL_GPL vmlinux 0x7082f022	class_find_device
+EXPORT_SYMBOL_GPL vmlinux 0x70ca9f63	xfrm_audit_policy_delete
+EXPORT_SYMBOL_GPL vmlinux 0x70cacfa0	platform_get_resource_byname
+EXPORT_SYMBOL_GPL vmlinux 0x70e75dd7	tcp_unregister_congestion_control
+EXPORT_SYMBOL_GPL vmlinux 0x7130eb98	bind_virq_to_irqaction
+EXPORT_SYMBOL_GPL vmlinux 0x716265c7	debugfs_initialized
+EXPORT_SYMBOL_GPL vmlinux 0x7216fb38	device_remove_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x7248aace	cleanup_srcu_struct
+EXPORT_SYMBOL_GPL vmlinux 0x72741f25	trace_vbprintk
+EXPORT_SYMBOL_GPL vmlinux 0x7278d328	all_vm_events
+EXPORT_SYMBOL_GPL vmlinux 0x727f6ec5	xfrm_output_resume
+EXPORT_SYMBOL_GPL vmlinux 0x728fd7e5	__get_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0x72e03bae	stop_machine_create
+EXPORT_SYMBOL_GPL vmlinux 0x731433ee	unregister_timer_hook
+EXPORT_SYMBOL_GPL vmlinux 0x7349e242	driver_register
+EXPORT_SYMBOL_GPL vmlinux 0x73e6f656	spi_alloc_master
+EXPORT_SYMBOL_GPL vmlinux 0x74abdafa	task_handoff_register
+EXPORT_SYMBOL_GPL vmlinux 0x74baf17a	tracing_is_on
+EXPORT_SYMBOL_GPL vmlinux 0x74bfb4cf	unregister_pernet_device
+EXPORT_SYMBOL_GPL vmlinux 0x75306c42	vfs_setxattr
+EXPORT_SYMBOL_GPL vmlinux 0x754afd68	ahash_free_instance
+EXPORT_SYMBOL_GPL vmlinux 0x7550a64c	fib_rules_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x75865ab0	crypto_ahash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x75e8f3c3	crypto_register_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x75feeafa	pciserial_remove_ports
+EXPORT_SYMBOL_GPL vmlinux 0x761188fd	dpm_suspend_noirq
+EXPORT_SYMBOL_GPL vmlinux 0x767cd56a	vfs_cancel_lock
+EXPORT_SYMBOL_GPL vmlinux 0x768888dd	pci_find_next_capability
+EXPORT_SYMBOL_GPL vmlinux 0x768e8e36	device_create_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0x7712771a	unbind_from_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0x7713fd44	sysdev_store_int
+EXPORT_SYMBOL_GPL vmlinux 0x771b093f	devres_remove_group
+EXPORT_SYMBOL_GPL vmlinux 0x773ca527	init_uts_ns
+EXPORT_SYMBOL_GPL vmlinux 0x7746a235	power_supply_changed
+EXPORT_SYMBOL_GPL vmlinux 0x77bb0316	disk_part_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0x783f1fdc	__xenbus_register_frontend
+EXPORT_SYMBOL_GPL vmlinux 0x786482b8	posix_timer_event
+EXPORT_SYMBOL_GPL vmlinux 0x786dfffb	get_user_pages_fast
+EXPORT_SYMBOL_GPL vmlinux 0x789f2b22	inet_csk_compat_getsockopt
+EXPORT_SYMBOL_GPL vmlinux 0x78e4a4ee	klist_add_after
+EXPORT_SYMBOL_GPL vmlinux 0x78f028ea	pciserial_resume_ports
+EXPORT_SYMBOL_GPL vmlinux 0x7944e0fc	tracing_off
+EXPORT_SYMBOL_GPL vmlinux 0x795e4d56	crypto_shash_setkey
+EXPORT_SYMBOL_GPL vmlinux 0x79bf7f43	blk_end_request_err
+EXPORT_SYMBOL_GPL vmlinux 0x7a939201	inet_diag_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x7aa36f2e	mnt_want_write_file
+EXPORT_SYMBOL_GPL vmlinux 0x7aaa8913	blk_update_request
+EXPORT_SYMBOL_GPL vmlinux 0x7ab3c122	edac_handlers
+EXPORT_SYMBOL_GPL vmlinux 0x7abfbb60	net_accel_unmap_device_page
+EXPORT_SYMBOL_GPL vmlinux 0x7b1d544d	edac_handler_set
+EXPORT_SYMBOL_GPL vmlinux 0x7b6c0100	pciserial_init_ports
+EXPORT_SYMBOL_GPL vmlinux 0x7bcd2ded	klist_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0x7c2f2afb	w1_calc_crc8
+EXPORT_SYMBOL_GPL vmlinux 0x7c33c2ad	device_add
+EXPORT_SYMBOL_GPL vmlinux 0x7ccbeb1c	rt_mutex_lock_interruptible
+EXPORT_SYMBOL_GPL vmlinux 0x7dc5d0b6	crypto_unregister_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x7dfd396b	tty_init_termios
+EXPORT_SYMBOL_GPL vmlinux 0x7e0023cc	shash_ahash_digest
+EXPORT_SYMBOL_GPL vmlinux 0x7e089533	page_mkclean
+EXPORT_SYMBOL_GPL vmlinux 0x7e1183c9	async_schedule
+EXPORT_SYMBOL_GPL vmlinux 0x7e1fe766	shash_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0x7e448bd6	pci_ioremap_bar
+EXPORT_SYMBOL_GPL vmlinux 0x7e5e301f	unregister_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x7e6bb802	device_find_child
+EXPORT_SYMBOL_GPL vmlinux 0x7ef24e5d	netlink_has_listeners
+EXPORT_SYMBOL_GPL vmlinux 0x7f36d7ef	spi_register_driver
+EXPORT_SYMBOL_GPL vmlinux 0x7f487f72	ahash_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0x7f8c2144	hwmon_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x7fb006ad	srcu_init_notifier_head
+EXPORT_SYMBOL_GPL vmlinux 0x7ff10ccf	raw_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x8014b6af	input_event_from_user
+EXPORT_SYMBOL_GPL vmlinux 0x8039d043	selinux_secmark_relabel_packet_permission
+EXPORT_SYMBOL_GPL vmlinux 0x805f3f23	pci_hp_remove_module_link
+EXPORT_SYMBOL_GPL vmlinux 0x808c223d	crypto_unregister_ahash
+EXPORT_SYMBOL_GPL vmlinux 0x808ec1a3	crypto_alg_tested
+EXPORT_SYMBOL_GPL vmlinux 0x80c45ccd	balloon_release_driver_page
+EXPORT_SYMBOL_GPL vmlinux 0x80ee55c3	selinux_secmark_refcount_inc
+EXPORT_SYMBOL_GPL vmlinux 0x81318ac7	net_accel_msg_start_send
+EXPORT_SYMBOL_GPL vmlinux 0x81763af2	platform_get_irq
+EXPORT_SYMBOL_GPL vmlinux 0x81895a9a	kmem_cache_name
+EXPORT_SYMBOL_GPL vmlinux 0x8226642f	__gpio_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x825fd98a	save_stack_trace_tsk
+EXPORT_SYMBOL_GPL vmlinux 0x827aceaa	dm_requeue_unmapped_request
+EXPORT_SYMBOL_GPL vmlinux 0x82939ebd	rcu_batches_completed_sched
+EXPORT_SYMBOL_GPL vmlinux 0x82c2d9a4	crypto_spawn_tfm2
+EXPORT_SYMBOL_GPL vmlinux 0x82cd19f3	register_xenstore_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x82d79b51	sysctl_vfs_cache_pressure
+EXPORT_SYMBOL_GPL vmlinux 0x82f776b7	gpio_export
+EXPORT_SYMBOL_GPL vmlinux 0x84133f10	setup_irq
+EXPORT_SYMBOL_GPL vmlinux 0x843d18ed	crypto_hash_walk_done
+EXPORT_SYMBOL_GPL vmlinux 0x84f02538	platform_bus
+EXPORT_SYMBOL_GPL vmlinux 0x85119b16	inet_csk_addr2sockaddr
+EXPORT_SYMBOL_GPL vmlinux 0x851733d5	unbind_from_per_cpu_irq
+EXPORT_SYMBOL_GPL vmlinux 0x854d3a48	ip_local_out
+EXPORT_SYMBOL_GPL vmlinux 0x8561dd39	class_for_each_device
+EXPORT_SYMBOL_GPL vmlinux 0x85625fee	simple_attr_release
+EXPORT_SYMBOL_GPL vmlinux 0x8566c479	simple_attr_write
+EXPORT_SYMBOL_GPL vmlinux 0x85c10896	rcu_batches_completed_bh
+EXPORT_SYMBOL_GPL vmlinux 0x8620e024	inotify_inode_is_dead
+EXPORT_SYMBOL_GPL vmlinux 0x862f98a3	xen_create_contiguous_region
+EXPORT_SYMBOL_GPL vmlinux 0x86623fd7	notify_remote_via_irq
+EXPORT_SYMBOL_GPL vmlinux 0x868784cb	__symbol_get
+EXPORT_SYMBOL_GPL vmlinux 0x86a51007	gnttab_end_foreign_transfer
+EXPORT_SYMBOL_GPL vmlinux 0x86b1667d	hwrng_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x86d5af44	skcipher_geniv_init
+EXPORT_SYMBOL_GPL vmlinux 0x86f6b99d	synchronize_rcu_expedited
+EXPORT_SYMBOL_GPL vmlinux 0x8712e07e	attribute_container_find_class_device
+EXPORT_SYMBOL_GPL vmlinux 0x87317b93	ring_buffer_iter_reset
+EXPORT_SYMBOL_GPL vmlinux 0x873fbaea	edac_atomic_assert_error
+EXPORT_SYMBOL_GPL vmlinux 0x87754115	raw_notifier_chain_register
+EXPORT_SYMBOL_GPL vmlinux 0x877572a2	crypto_aead_type
+EXPORT_SYMBOL_GPL vmlinux 0x87b710d8	vfs_setlease
+EXPORT_SYMBOL_GPL vmlinux 0x87f55650	crypto_alloc_base
+EXPORT_SYMBOL_GPL vmlinux 0x880b189a	__atomic_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x8810ad5e	crypto_xor
+EXPORT_SYMBOL_GPL vmlinux 0x881eb53f	led_trigger_unregister_simple
+EXPORT_SYMBOL_GPL vmlinux 0x8822c65a	w1_reset_select_slave
+EXPORT_SYMBOL_GPL vmlinux 0x8830dad5	__module_text_address
+EXPORT_SYMBOL_GPL vmlinux 0x885142a6	nf_net_netfilter_sysctl_path
+EXPORT_SYMBOL_GPL vmlinux 0x895f6cd4	proc_net_remove
+EXPORT_SYMBOL_GPL vmlinux 0x896b0fb1	simple_attr_open
+EXPORT_SYMBOL_GPL vmlinux 0x8975e2b0	dm_set_device_limits
+EXPORT_SYMBOL_GPL vmlinux 0x89802853	multi_notify_remote_via_irq
+EXPORT_SYMBOL_GPL vmlinux 0x898332fe	pci_cleanup_aer_uncorrect_error_status
+EXPORT_SYMBOL_GPL vmlinux 0x89877190	devm_kzalloc
+EXPORT_SYMBOL_GPL vmlinux 0x8992a336	cuckoo_hash_rehash
+EXPORT_SYMBOL_GPL vmlinux 0x899a4cb8	tcp_init_congestion_ops
+EXPORT_SYMBOL_GPL vmlinux 0x8a65440c	pci_find_ext_capability
+EXPORT_SYMBOL_GPL vmlinux 0x8a66495b	transport_destroy_device
+EXPORT_SYMBOL_GPL vmlinux 0x8aa4a822	crypto_register_instance
+EXPORT_SYMBOL_GPL vmlinux 0x8ade0bf4	pciserial_suspend_ports
+EXPORT_SYMBOL_GPL vmlinux 0x8b09dee0	tracepoint_iter_next
+EXPORT_SYMBOL_GPL vmlinux 0x8b3229db	net_accel_map_device_page
+EXPORT_SYMBOL_GPL vmlinux 0x8b39cf9d	unregister_kprobes
+EXPORT_SYMBOL_GPL vmlinux 0x8b40d6d4	pcie_port_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0x8b70cc08	blk_add_driver_data
+EXPORT_SYMBOL_GPL vmlinux 0x8b7e3cea	input_ff_event
+EXPORT_SYMBOL_GPL vmlinux 0x8b890c41	device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x8bd0dd9c	relay_flush
+EXPORT_SYMBOL_GPL vmlinux 0x8bd37515	inet_diag_register
+EXPORT_SYMBOL_GPL vmlinux 0x8c06a108	xenbus_transaction_start
+EXPORT_SYMBOL_GPL vmlinux 0x8c17a62c	fib_rules_register
+EXPORT_SYMBOL_GPL vmlinux 0x8c38074a	unregister_xenstore_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x8c38e425	inet6_hash_connect
+EXPORT_SYMBOL_GPL vmlinux 0x8c55ee03	inet6_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x8c9d686d	__wake_up_sync_key
+EXPORT_SYMBOL_GPL vmlinux 0x8d033df4	klist_node_attached
+EXPORT_SYMBOL_GPL vmlinux 0x8d18976d	device_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x8d942da1	crypto_default_rng
+EXPORT_SYMBOL_GPL vmlinux 0x8e4403df	__rtnl_link_register
+EXPORT_SYMBOL_GPL vmlinux 0x8e8c6425	__rt_mutex_init
+EXPORT_SYMBOL_GPL vmlinux 0x8eb58c6e	__wake_up_sync
+EXPORT_SYMBOL_GPL vmlinux 0x8ef610da	rtc_irq_set_freq
+EXPORT_SYMBOL_GPL vmlinux 0x8f03bfa6	inotify_find_watch
+EXPORT_SYMBOL_GPL vmlinux 0x8f6cee77	__round_jiffies_relative
+EXPORT_SYMBOL_GPL vmlinux 0x8fa74514	sysdev_suspend
+EXPORT_SYMBOL_GPL vmlinux 0x8face470	do_add_mount
+EXPORT_SYMBOL_GPL vmlinux 0x9065eabc	destroy_workqueue
+EXPORT_SYMBOL_GPL vmlinux 0x90770826	tty_get_pgrp
+EXPORT_SYMBOL_GPL vmlinux 0x90a1004a	crypto_has_alg
+EXPORT_SYMBOL_GPL vmlinux 0x90d5dab6	blk_abort_queue
+EXPORT_SYMBOL_GPL vmlinux 0x913d1149	rtc_set_alarm
+EXPORT_SYMBOL_GPL vmlinux 0x9159b9d6	profile_event_register
+EXPORT_SYMBOL_GPL vmlinux 0x92fb217b	dcookie_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x9321df95	dlm_lock
+EXPORT_SYMBOL_GPL vmlinux 0x93260715	register_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0x93bf6140	invalidate_inode_pages2_range
+EXPORT_SYMBOL_GPL vmlinux 0x93d2422d	snmp_mib_free
+EXPORT_SYMBOL_GPL vmlinux 0x94248f2a	relay_file_operations
+EXPORT_SYMBOL_GPL vmlinux 0x94f4b666	spi_add_device
+EXPORT_SYMBOL_GPL vmlinux 0x952664c5	do_exit
+EXPORT_SYMBOL_GPL vmlinux 0x95439aa3	exportfs_encode_fh
+EXPORT_SYMBOL_GPL vmlinux 0x956a91ba	gpio_get_value_cansleep
+EXPORT_SYMBOL_GPL vmlinux 0x95758050	__blocking_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0x9577edba	irq_to_evtchn_port
+EXPORT_SYMBOL_GPL vmlinux 0x959c67da	class_destroy
+EXPORT_SYMBOL_GPL vmlinux 0x95cb0445	relay_reset
+EXPORT_SYMBOL_GPL vmlinux 0x95f5c376	tcp_register_congestion_control
+EXPORT_SYMBOL_GPL vmlinux 0x95f64fbb	anon_transport_class_register
+EXPORT_SYMBOL_GPL vmlinux 0x95fa43fd	get_current_tty
+EXPORT_SYMBOL_GPL vmlinux 0x95fcde51	relay_switch_subbuf
+EXPORT_SYMBOL_GPL vmlinux 0x96cbcf31	pm_qos_add_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x975b7144	put_driver
+EXPORT_SYMBOL_GPL vmlinux 0x97bdcca4	debugfs_create_u32
+EXPORT_SYMBOL_GPL vmlinux 0x9807c8b8	ip_route_output_flow
+EXPORT_SYMBOL_GPL vmlinux 0x9816af8b	inotify_init
+EXPORT_SYMBOL_GPL vmlinux 0x98241752	crypto_larval_lookup
+EXPORT_SYMBOL_GPL vmlinux 0x986ce6ef	led_trigger_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x986d9f09	inet_hash_connect
+EXPORT_SYMBOL_GPL vmlinux 0x987260cc	part_round_stats
+EXPORT_SYMBOL_GPL vmlinux 0x98b82b83	crypto_blkcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0x99404563	shash_ahash_finup
+EXPORT_SYMBOL_GPL vmlinux 0x995d1071	prof_on
+EXPORT_SYMBOL_GPL vmlinux 0x998da43e	raw_seq_next
+EXPORT_SYMBOL_GPL vmlinux 0x99a26bcb	sysfs_remove_file_from_group
+EXPORT_SYMBOL_GPL vmlinux 0x9a11a0fc	crypto_attr_alg_name
+EXPORT_SYMBOL_GPL vmlinux 0x9a13389b	tty_ldisc_ref
+EXPORT_SYMBOL_GPL vmlinux 0x9a4d1034	idle_notifier_register
+EXPORT_SYMBOL_GPL vmlinux 0x9a8f5fe0	rtnl_kill_links
+EXPORT_SYMBOL_GPL vmlinux 0x9b440d03	tty_ldisc_deref
+EXPORT_SYMBOL_GPL vmlinux 0x9ba0501e	unregister_vt_notifier
+EXPORT_SYMBOL_GPL vmlinux 0x9c1ff611	platform_device_add
+EXPORT_SYMBOL_GPL vmlinux 0x9cb8037b	xfrm_count_enc_supported
+EXPORT_SYMBOL_GPL vmlinux 0x9cc714f3	each_symbol
+EXPORT_SYMBOL_GPL vmlinux 0x9cd9b420	get_cpu_sysdev
+EXPORT_SYMBOL_GPL vmlinux 0x9cf4ed94	class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0x9d3850e1	gnttab_alloc_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0x9d476175	ring_buffer_commit_overrun_cpu
+EXPORT_SYMBOL_GPL vmlinux 0x9d47a543	crypto_ahash_type
+EXPORT_SYMBOL_GPL vmlinux 0x9e01f6d4	eventfd_signal
+EXPORT_SYMBOL_GPL vmlinux 0x9e192fc2	bd_release_from_disk
+EXPORT_SYMBOL_GPL vmlinux 0x9e4e0173	crypto_grab_skcipher
+EXPORT_SYMBOL_GPL vmlinux 0x9e711ad2	pm_qos_requirement
+EXPORT_SYMBOL_GPL vmlinux 0x9e7d3442	xenbus_resume
+EXPORT_SYMBOL_GPL vmlinux 0x9f40a6d6	async_synchronize_full_domain
+EXPORT_SYMBOL_GPL vmlinux 0x9f85ed90	klist_remove
+EXPORT_SYMBOL_GPL vmlinux 0x9f973a5a	inotify_init_watch
+EXPORT_SYMBOL_GPL vmlinux 0x9fc98386	gnttab_copy_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0x9fce80db	fb_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xa007859e	get_device
+EXPORT_SYMBOL_GPL vmlinux 0xa00cf100	tty_perform_flush
+EXPORT_SYMBOL_GPL vmlinux 0xa0255440	net_ipv4_ctl_path
+EXPORT_SYMBOL_GPL vmlinux 0xa02fdc2a	srcu_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xa033ae83	tcp_done
+EXPORT_SYMBOL_GPL vmlinux 0xa071807c	w1_write_8
+EXPORT_SYMBOL_GPL vmlinux 0xa07312a6	unregister_net_sysctl_table
+EXPORT_SYMBOL_GPL vmlinux 0xa0850157	attribute_container_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xa0b9b996	led_trigger_register_simple
+EXPORT_SYMBOL_GPL vmlinux 0xa0ca4033	pci_destroy_slot
+EXPORT_SYMBOL_GPL vmlinux 0xa1493895	crypto_lookup_template
+EXPORT_SYMBOL_GPL vmlinux 0xa165ecc7	ring_buffer_discard_commit
+EXPORT_SYMBOL_GPL vmlinux 0xa16853ff	bus_for_each_drv
+EXPORT_SYMBOL_GPL vmlinux 0xa16cd72d	w1_reset_bus
+EXPORT_SYMBOL_GPL vmlinux 0xa17428e2	queue_delayed_work
+EXPORT_SYMBOL_GPL vmlinux 0xa19740e3	w1_write_block
+EXPORT_SYMBOL_GPL vmlinux 0xa1d2214e	pci_block_user_cfg_access
+EXPORT_SYMBOL_GPL vmlinux 0xa2592919	unregister_kretprobes
+EXPORT_SYMBOL_GPL vmlinux 0xa2c605a1	kallsyms_on_each_symbol
+EXPORT_SYMBOL_GPL vmlinux 0xa2c85eac	sysdev_class_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xa32a8c41	debugfs_create_size_t
+EXPORT_SYMBOL_GPL vmlinux 0xa353fffc	xenbus_rm
+EXPORT_SYMBOL_GPL vmlinux 0xa3b59851	xenbus_for_each_frontend
+EXPORT_SYMBOL_GPL vmlinux 0xa3b94d08	xenbus_switch_state
+EXPORT_SYMBOL_GPL vmlinux 0xa40a8590	input_event_to_user
+EXPORT_SYMBOL_GPL vmlinux 0xa45cb480	debugfs_create_bool
+EXPORT_SYMBOL_GPL vmlinux 0xa465aab2	sched_setscheduler
+EXPORT_SYMBOL_GPL vmlinux 0xa4a42813	vbin_printf
+EXPORT_SYMBOL_GPL vmlinux 0xa4ccf7c9	crypto_register_ahash
+EXPORT_SYMBOL_GPL vmlinux 0xa4d58669	math_state_restore
+EXPORT_SYMBOL_GPL vmlinux 0xa554bcfb	crypto_grab_aead
+EXPORT_SYMBOL_GPL vmlinux 0xa57622db	__inet_lookup_established
+EXPORT_SYMBOL_GPL vmlinux 0xa5a7a080	blkcipher_walk_done
+EXPORT_SYMBOL_GPL vmlinux 0xa5bf5c3e	pm_qos_add_requirement
+EXPORT_SYMBOL_GPL vmlinux 0xa5c36cec	inotify_unmount_inodes
+EXPORT_SYMBOL_GPL vmlinux 0xa5efbf4c	async_synchronize_full
+EXPORT_SYMBOL_GPL vmlinux 0xa5fdb519	uart_console_write
+EXPORT_SYMBOL_GPL vmlinux 0xa6078510	register_kretprobes
+EXPORT_SYMBOL_GPL vmlinux 0xa6097bff	gnttab_request_free_callback
+EXPORT_SYMBOL_GPL vmlinux 0xa612d378	page_cache_async_readahead
+EXPORT_SYMBOL_GPL vmlinux 0xa6b9aa77	fb_bl_default_curve
+EXPORT_SYMBOL_GPL vmlinux 0xa6bc3ec8	fib_rules_cleanup_ops
+EXPORT_SYMBOL_GPL vmlinux 0xa6fd5d96	spi_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0xa7b20543	anon_inode_getfd
+EXPORT_SYMBOL_GPL vmlinux 0xa804f140	tcp_slow_start
+EXPORT_SYMBOL_GPL vmlinux 0xa830362f	mm_kobj
+EXPORT_SYMBOL_GPL vmlinux 0xa8b82a53	xen_destroy_contiguous_region
+EXPORT_SYMBOL_GPL vmlinux 0xa8f59416	gpio_direction_output
+EXPORT_SYMBOL_GPL vmlinux 0xa9176daf	sysdev_show_ulong
+EXPORT_SYMBOL_GPL vmlinux 0xa927e6c3	skb_pull_rcsum
+EXPORT_SYMBOL_GPL vmlinux 0xa9340369	pci_rescan_bus
+EXPORT_SYMBOL_GPL vmlinux 0xa96119bc	__blkdev_driver_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0xa9b9f629	ring_buffer_free
+EXPORT_SYMBOL_GPL vmlinux 0xa9c530b8	unregister_oom_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xa9e4be89	generic_fh_to_dentry
+EXPORT_SYMBOL_GPL vmlinux 0xaa3279d2	tty_encode_baud_rate
+EXPORT_SYMBOL_GPL vmlinux 0xaa3b3a05	crypto_aead_setauthsize
+EXPORT_SYMBOL_GPL vmlinux 0xaa3e3aea	__i2c_board_lock
+EXPORT_SYMBOL_GPL vmlinux 0xaa5310f9	__tracepoint_napi_poll
+EXPORT_SYMBOL_GPL vmlinux 0xaa5d4024	use_module
+EXPORT_SYMBOL_GPL vmlinux 0xaa6def67	init_dummy_netdev
+EXPORT_SYMBOL_GPL vmlinux 0xaa755778	xen_ptep_get_and_clear_full
+EXPORT_SYMBOL_GPL vmlinux 0xaa7cf3b9	crypto_ahash_setkey
+EXPORT_SYMBOL_GPL vmlinux 0xaa8c4696	cpu_clock
+EXPORT_SYMBOL_GPL vmlinux 0xaaddf6ca	blocking_notifier_chain_cond_register
+EXPORT_SYMBOL_GPL vmlinux 0xaae117f0	srcu_notifier_chain_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xaae93e20	ring_buffer_unlock_commit
+EXPORT_SYMBOL_GPL vmlinux 0xaaeac208	uhci_check_and_reset_hc
+EXPORT_SYMBOL_GPL vmlinux 0xaaf7f157	gnttab_cancel_free_callback
+EXPORT_SYMBOL_GPL vmlinux 0xab57e311	tracepoint_probe_register
+EXPORT_SYMBOL_GPL vmlinux 0xab665fbf	__pci_complete_power_transition
+EXPORT_SYMBOL_GPL vmlinux 0xab983be6	cuckoo_hash_add
+EXPORT_SYMBOL_GPL vmlinux 0xabd3cd18	class_dev_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0xac50fbe3	queue_work
+EXPORT_SYMBOL_GPL vmlinux 0xacabaf01	skb_morph
+EXPORT_SYMBOL_GPL vmlinux 0xad096363	xenbus_printf
+EXPORT_SYMBOL_GPL vmlinux 0xadb7d6b0	led_trigger_remove
+EXPORT_SYMBOL_GPL vmlinux 0xadeb8da6	device_reprobe
+EXPORT_SYMBOL_GPL vmlinux 0xae0c87ee	pm_qos_remove_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xae93b064	shash_ahash_update
+EXPORT_SYMBOL_GPL vmlinux 0xaea0541d	transport_remove_device
+EXPORT_SYMBOL_GPL vmlinux 0xaea81a80	exportfs_decode_fh
+EXPORT_SYMBOL_GPL vmlinux 0xaeef7b8e	debugfs_create_dir
+EXPORT_SYMBOL_GPL vmlinux 0xaf272f67	sysfs_notify_dirent
+EXPORT_SYMBOL_GPL vmlinux 0xaf794337	blk_rq_prep_clone
+EXPORT_SYMBOL_GPL vmlinux 0xaf798d4b	pci_intx
+EXPORT_SYMBOL_GPL vmlinux 0xb0223109	klist_next
+EXPORT_SYMBOL_GPL vmlinux 0xb03d6bc1	devres_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xb06cb4e4	net_assign_generic
+EXPORT_SYMBOL_GPL vmlinux 0xb0afa009	dma_get_required_mask
+EXPORT_SYMBOL_GPL vmlinux 0xb0fe394f	kobject_rename
+EXPORT_SYMBOL_GPL vmlinux 0xb10d55bc	cn_netlink_send
+EXPORT_SYMBOL_GPL vmlinux 0xb1710391	module_mutex
+EXPORT_SYMBOL_GPL vmlinux 0xb18429eb	suspend_device_irqs
+EXPORT_SYMBOL_GPL vmlinux 0xb1854866	invalidate_inode_pages2
+EXPORT_SYMBOL_GPL vmlinux 0xb1acbcce	rcu_barrier_sched
+EXPORT_SYMBOL_GPL vmlinux 0xb2033b82	net_accel_msg_recv
+EXPORT_SYMBOL_GPL vmlinux 0xb24429a3	power_supply_am_i_supplied
+EXPORT_SYMBOL_GPL vmlinux 0xb2c4cb5a	ring_buffer_reset
+EXPORT_SYMBOL_GPL vmlinux 0xb2d579fe	vfs_getxattr
+EXPORT_SYMBOL_GPL vmlinux 0xb31b1a06	do_sync_mapping_range
+EXPORT_SYMBOL_GPL vmlinux 0xb333238b	relay_open
+EXPORT_SYMBOL_GPL vmlinux 0xb34aa675	inet_csk_compat_setsockopt
+EXPORT_SYMBOL_GPL vmlinux 0xb34d20bd	swiotlb_unmap_page
+EXPORT_SYMBOL_GPL vmlinux 0xb381fb15	pid_vnr
+EXPORT_SYMBOL_GPL vmlinux 0xb3ffd17e	__lock_page_killable
+EXPORT_SYMBOL_GPL vmlinux 0xb46bf43a	security_inode_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0xb4e14553	gnttab_query_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0xb4ee45ed	skb_gro_receive
+EXPORT_SYMBOL_GPL vmlinux 0xb51fbd64	edac_op_state
+EXPORT_SYMBOL_GPL vmlinux 0xb53ae573	cpu_idle_wait
+EXPORT_SYMBOL_GPL vmlinux 0xb543ebb6	init_srcu_struct
+EXPORT_SYMBOL_GPL vmlinux 0xb55993f5	sysfs_get
+EXPORT_SYMBOL_GPL vmlinux 0xb57ed228	sysfs_notify
+EXPORT_SYMBOL_GPL vmlinux 0xb58dcfa2	synchronize_sched_expedited
+EXPORT_SYMBOL_GPL vmlinux 0xb612444d	snmp_mib_init
+EXPORT_SYMBOL_GPL vmlinux 0xb6230f1f	gnttab_grant_foreign_access
+EXPORT_SYMBOL_GPL vmlinux 0xb6255a00	raw_seq_open
+EXPORT_SYMBOL_GPL vmlinux 0xb64cd74c	filter_match_preds
+EXPORT_SYMBOL_GPL vmlinux 0xb65091b3	selinux_secmark_refcount_dec
+EXPORT_SYMBOL_GPL vmlinux 0xb6b4c13c	ring_buffer_write
+EXPORT_SYMBOL_GPL vmlinux 0xb6e47581	platform_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xb744fa43	xfrm_ealg_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0xb7ba64a7	net_accel_msg_reply
+EXPORT_SYMBOL_GPL vmlinux 0xb7fdd0df	eventfd_ctx_put
+EXPORT_SYMBOL_GPL vmlinux 0xb8625a6a	crypto_nivaead_type
+EXPORT_SYMBOL_GPL vmlinux 0xb897072f	hrtimer_forward
+EXPORT_SYMBOL_GPL vmlinux 0xb903674c	scatterwalk_map_and_copy
+EXPORT_SYMBOL_GPL vmlinux 0xb90dff82	platform_device_register_simple
+EXPORT_SYMBOL_GPL vmlinux 0xb91269da	net_accel_msg_init_queue
+EXPORT_SYMBOL_GPL vmlinux 0xb94db510	register_jprobe
+EXPORT_SYMBOL_GPL vmlinux 0xb97b8588	xen_tlb_flush_all
+EXPORT_SYMBOL_GPL vmlinux 0xb98d8543	fsstack_copy_inode_size
+EXPORT_SYMBOL_GPL vmlinux 0xb99d5837	xenbus_read
+EXPORT_SYMBOL_GPL vmlinux 0xb9d9fae8	register_net_sysctl_table
+EXPORT_SYMBOL_GPL vmlinux 0xb9eb3aa9	add_uevent_var
+EXPORT_SYMBOL_GPL vmlinux 0xba0a18ad	crypto_tfm_in_queue
+EXPORT_SYMBOL_GPL vmlinux 0xba70f58e	attribute_container_classdev_to_container
+EXPORT_SYMBOL_GPL vmlinux 0xbae40c53	xattr_getsecurity
+EXPORT_SYMBOL_GPL vmlinux 0xbae41ccf	mmput
+EXPORT_SYMBOL_GPL vmlinux 0xbb0e5ce8	sk_clone
+EXPORT_SYMBOL_GPL vmlinux 0xbb134e16	input_ff_upload
+EXPORT_SYMBOL_GPL vmlinux 0xbb24a930	dev_set_name
+EXPORT_SYMBOL_GPL vmlinux 0xbb4a1408	klist_init
+EXPORT_SYMBOL_GPL vmlinux 0xbb8ee95e	shmem_file_setup
+EXPORT_SYMBOL_GPL vmlinux 0xbbb98859	edid_info
+EXPORT_SYMBOL_GPL vmlinux 0xbc0c8afa	debugfs_create_u64
+EXPORT_SYMBOL_GPL vmlinux 0xbc139da4	root_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xbc13ba98	transport_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xbc28f01f	class_compat_create_link
+EXPORT_SYMBOL_GPL vmlinux 0xbc29d720	ring_buffer_read_page
+EXPORT_SYMBOL_GPL vmlinux 0xbc380248	ring_buffer_overrun_cpu
+EXPORT_SYMBOL_GPL vmlinux 0xbc4106cb	devres_alloc
+EXPORT_SYMBOL_GPL vmlinux 0xbcfbf6fa	__module_address
+EXPORT_SYMBOL_GPL vmlinux 0xbd67876b	net_accel_msg_notify
+EXPORT_SYMBOL_GPL vmlinux 0xbd6bab7b	xen_invlpg_all
+EXPORT_SYMBOL_GPL vmlinux 0xbd76aeab	flush_workqueue
+EXPORT_SYMBOL_GPL vmlinux 0xbda38776	ring_buffer_read_finish
+EXPORT_SYMBOL_GPL vmlinux 0xbdd295f0	trace_vprintk
+EXPORT_SYMBOL_GPL vmlinux 0xbe116723	do_posix_clock_nosettime
+EXPORT_SYMBOL_GPL vmlinux 0xbea498c6	spi_get_device_id
+EXPORT_SYMBOL_GPL vmlinux 0xbeff3935	crypto_shoot_alg
+EXPORT_SYMBOL_GPL vmlinux 0xbf74eb20	probe_kernel_write
+EXPORT_SYMBOL_GPL vmlinux 0xbf7558a7	register_posix_clock
+EXPORT_SYMBOL_GPL vmlinux 0xbf7590ae	__inet_lookup_listener
+EXPORT_SYMBOL_GPL vmlinux 0xbf80d547	get_dcookie
+EXPORT_SYMBOL_GPL vmlinux 0xbfd94bb0	bind_virq_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0xbffde8ec	compat_alloc_user_space
+EXPORT_SYMBOL_GPL vmlinux 0xc03d6431	net_accel_grant_page
+EXPORT_SYMBOL_GPL vmlinux 0xc058f46e	swiotlb_map_page
+EXPORT_SYMBOL_GPL vmlinux 0xc05c6048	debugfs_remove
+EXPORT_SYMBOL_GPL vmlinux 0xc091e529	nf_register_afinfo
+EXPORT_SYMBOL_GPL vmlinux 0xc09b8ec0	lookup_address
+EXPORT_SYMBOL_GPL vmlinux 0xc0be5392	crypto_unregister_shash
+EXPORT_SYMBOL_GPL vmlinux 0xc126e890	klist_del
+EXPORT_SYMBOL_GPL vmlinux 0xc12c9b26	get_inotify_watch
+EXPORT_SYMBOL_GPL vmlinux 0xc1eaaa5e	__inet_inherit_port
+EXPORT_SYMBOL_GPL vmlinux 0xc22a3091	vm_unmap_aliases
+EXPORT_SYMBOL_GPL vmlinux 0xc239a7d1	pci_stop_bus_device
+EXPORT_SYMBOL_GPL vmlinux 0xc28b030e	inotify_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xc2df584f	blk_queue_rq_timed_out
+EXPORT_SYMBOL_GPL vmlinux 0xc2df868e	user_update
+EXPORT_SYMBOL_GPL vmlinux 0xc2f608de	tcp_death_row
+EXPORT_SYMBOL_GPL vmlinux 0xc3301f02	rcu_expedited_torture_stats
+EXPORT_SYMBOL_GPL vmlinux 0xc34efe27	snmp_fold_field
+EXPORT_SYMBOL_GPL vmlinux 0xc39aa898	xenbus_unregister_driver
+EXPORT_SYMBOL_GPL vmlinux 0xc3d72168	user_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xc4034caa	enable_kprobe
+EXPORT_SYMBOL_GPL vmlinux 0xc419d1c5	register_net_sysctl_rotable
+EXPORT_SYMBOL_GPL vmlinux 0xc4b33aa6	tracepoint_probe_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc4ce6189	idle_notifier_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc512626a	__supported_pte_mask
+EXPORT_SYMBOL_GPL vmlinux 0xc5267f34	crypto_alloc_pcomp
+EXPORT_SYMBOL_GPL vmlinux 0xc5397da6	xenbus_mkdir
+EXPORT_SYMBOL_GPL vmlinux 0xc54b80ba	dm_disk
+EXPORT_SYMBOL_GPL vmlinux 0xc563a632	disk_part_iter_init
+EXPORT_SYMBOL_GPL vmlinux 0xc5a01a2f	sk_setup_caps
+EXPORT_SYMBOL_GPL vmlinux 0xc5a9457c	sysfs_schedule_callback
+EXPORT_SYMBOL_GPL vmlinux 0xc5ba751a	bd_claim_by_disk
+EXPORT_SYMBOL_GPL vmlinux 0xc5f5008c	pci_reset_function
+EXPORT_SYMBOL_GPL vmlinux 0xc60f75ec	__ftrace_vprintk
+EXPORT_SYMBOL_GPL vmlinux 0xc6192dea	tcp_reno_ssthresh
+EXPORT_SYMBOL_GPL vmlinux 0xc6195b99	ring_buffer_empty_cpu
+EXPORT_SYMBOL_GPL vmlinux 0xc63bc722	relay_subbufs_consumed
+EXPORT_SYMBOL_GPL vmlinux 0xc733d5bc	skb_tstamp_tx
+EXPORT_SYMBOL_GPL vmlinux 0xc7548765	crypto_shash_update
+EXPORT_SYMBOL_GPL vmlinux 0xc7ec11f6	atomic_notifier_call_chain
+EXPORT_SYMBOL_GPL vmlinux 0xc7f4dbfb	inet_csk_clone
+EXPORT_SYMBOL_GPL vmlinux 0xc87c1f84	ktime_get
+EXPORT_SYMBOL_GPL vmlinux 0xc87cd7fb	platform_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xc87e487a	sched_clock_idle_sleep_event
+EXPORT_SYMBOL_GPL vmlinux 0xc8fd4891	__class_register
+EXPORT_SYMBOL_GPL vmlinux 0xc9561772	fb_destroy_modelist
+EXPORT_SYMBOL_GPL vmlinux 0xc9964d8f	file_ra_state_init
+EXPORT_SYMBOL_GPL vmlinux 0xc9bb8de3	ring_buffer_record_disable
+EXPORT_SYMBOL_GPL vmlinux 0xc9ec4e21	free_percpu
+EXPORT_SYMBOL_GPL vmlinux 0xca01f51c	tcp_orphan_count
+EXPORT_SYMBOL_GPL vmlinux 0xca81ea9a	xenbus_transaction_end
+EXPORT_SYMBOL_GPL vmlinux 0xca85d8cf	tracepoint_probe_update_all
+EXPORT_SYMBOL_GPL vmlinux 0xcb20ff69	xen_tlb_flush_mask
+EXPORT_SYMBOL_GPL vmlinux 0xcb49d064	inet_hash
+EXPORT_SYMBOL_GPL vmlinux 0xcb56d2d0	find_symbol
+EXPORT_SYMBOL_GPL vmlinux 0xcc1f1c3d	inet_twdr_hangman
+EXPORT_SYMBOL_GPL vmlinux 0xcc437026	kset_create_and_add
+EXPORT_SYMBOL_GPL vmlinux 0xcc5a03d0	inet_csk_reqsk_queue_prune
+EXPORT_SYMBOL_GPL vmlinux 0xcc8b07d8	sysfs_create_link
+EXPORT_SYMBOL_GPL vmlinux 0xccc527f6	w1_next_pullup
+EXPORT_SYMBOL_GPL vmlinux 0xcd00a061	find_vpid
+EXPORT_SYMBOL_GPL vmlinux 0xcd5f8ff3	bind_caller_port_to_irqhandler
+EXPORT_SYMBOL_GPL vmlinux 0xcdca3691	nr_irqs
+EXPORT_SYMBOL_GPL vmlinux 0xcdf26214	platform_get_resource
+EXPORT_SYMBOL_GPL vmlinux 0xce873518	platform_driver_register
+EXPORT_SYMBOL_GPL vmlinux 0xce8e1da7	pci_disable_pcie_error_reporting
+EXPORT_SYMBOL_GPL vmlinux 0xcea5862e	driver_for_each_device
+EXPORT_SYMBOL_GPL vmlinux 0xcf11aa59	unregister_pernet_gen_subsys
+EXPORT_SYMBOL_GPL vmlinux 0xcf7a962e	cn_add_callback
+EXPORT_SYMBOL_GPL vmlinux 0xcf8c4f99	hypervisor_kobj
+EXPORT_SYMBOL_GPL vmlinux 0xcf9f3328	dlm_release_lockspace
+EXPORT_SYMBOL_GPL vmlinux 0xcfc68341	synchronize_rcu_bh
+EXPORT_SYMBOL_GPL vmlinux 0xcfcc83ad	register_vt_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xd03c7700	secure_ipv4_port_ephemeral
+EXPORT_SYMBOL_GPL vmlinux 0xd0458ccb	xenbus_strstate
+EXPORT_SYMBOL_GPL vmlinux 0xd0bdf237	sysfs_create_bin_file
+EXPORT_SYMBOL_GPL vmlinux 0xd0c05159	emergency_restart
+EXPORT_SYMBOL_GPL vmlinux 0xd11b6b93	inverse_translate
+EXPORT_SYMBOL_GPL vmlinux 0xd11e6194	inet_ctl_sock_create
+EXPORT_SYMBOL_GPL vmlinux 0xd16712f3	crypto_check_attr_type
+EXPORT_SYMBOL_GPL vmlinux 0xd18eb65d	inet_csk_search_req
+EXPORT_SYMBOL_GPL vmlinux 0xd1c5c56b	blk_queue_rq_timeout
+EXPORT_SYMBOL_GPL vmlinux 0xd273b1b1	__round_jiffies_up_relative
+EXPORT_SYMBOL_GPL vmlinux 0xd2a8caf0	work_on_cpu
+EXPORT_SYMBOL_GPL vmlinux 0xd3051146	pci_hp_create_module_link
+EXPORT_SYMBOL_GPL vmlinux 0xd3b78da3	xenbus_suspend_cancel
+EXPORT_SYMBOL_GPL vmlinux 0xd3cac676	rtc_class_open
+EXPORT_SYMBOL_GPL vmlinux 0xd401eb20	debugfs_remove_recursive
+EXPORT_SYMBOL_GPL vmlinux 0xd4287c1f	pci_restore_msi_state
+EXPORT_SYMBOL_GPL vmlinux 0xd429e5ca	platform_bus_type
+EXPORT_SYMBOL_GPL vmlinux 0xd45807ac	net_accel_msg_complete_send_notify
+EXPORT_SYMBOL_GPL vmlinux 0xd461fd7d	input_class
+EXPORT_SYMBOL_GPL vmlinux 0xd480b149	spi_busnum_to_master
+EXPORT_SYMBOL_GPL vmlinux 0xd493b83e	relay_buf_full
+EXPORT_SYMBOL_GPL vmlinux 0xd64fef94	bus_create_file
+EXPORT_SYMBOL_GPL vmlinux 0xd6a98565	platform_get_irq_byname
+EXPORT_SYMBOL_GPL vmlinux 0xd705b4c7	schedule_hrtimeout
+EXPORT_SYMBOL_GPL vmlinux 0xd72feba2	xenbus_read_driver_state
+EXPORT_SYMBOL_GPL vmlinux 0xd73ef534	sysdev_resume
+EXPORT_SYMBOL_GPL vmlinux 0xd7822b06	crypto_shash_digest
+EXPORT_SYMBOL_GPL vmlinux 0xd7938070	transport_configure_device
+EXPORT_SYMBOL_GPL vmlinux 0xd7a230b7	bus_register_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xd7d79132	put_online_cpus
+EXPORT_SYMBOL_GPL vmlinux 0xd7f91ef3	mask_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0xd81e5cb4	crypto_alloc_aead
+EXPORT_SYMBOL_GPL vmlinux 0xd89f4857	find_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0xd8f79938	netfront_accelerator_loaded
+EXPORT_SYMBOL_GPL vmlinux 0xd8ff53a9	cuckoo_hash_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xd9042fa8	scatterwalk_map
+EXPORT_SYMBOL_GPL vmlinux 0xd91299fc	crypto_mod_get
+EXPORT_SYMBOL_GPL vmlinux 0xd9217a8c	input_ff_erase
+EXPORT_SYMBOL_GPL vmlinux 0xd9225f63	debugfs_create_u16
+EXPORT_SYMBOL_GPL vmlinux 0xd9319d7d	device_release_driver
+EXPORT_SYMBOL_GPL vmlinux 0xd93dd96f	crypto_init_ahash_spawn
+EXPORT_SYMBOL_GPL vmlinux 0xd98d80b0	filter_current_check_discard
+EXPORT_SYMBOL_GPL vmlinux 0xd9f381a6	map_vm_area
+EXPORT_SYMBOL_GPL vmlinux 0xda1be8e1	async_synchronize_cookie_domain
+EXPORT_SYMBOL_GPL vmlinux 0xda698fad	init_user_ns
+EXPORT_SYMBOL_GPL vmlinux 0xda706142	platform_add_devices
+EXPORT_SYMBOL_GPL vmlinux 0xda7f2ab0	pci_set_pcie_reset_state
+EXPORT_SYMBOL_GPL vmlinux 0xda8c459b	inotify_rm_wd
+EXPORT_SYMBOL_GPL vmlinux 0xdaed23f6	sysdev_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xdaf4dfb3	fb_mode_option
+EXPORT_SYMBOL_GPL vmlinux 0xdb274e52	monotonic_to_bootbased
+EXPORT_SYMBOL_GPL vmlinux 0xdb2902d6	ring_buffer_alloc_read_page
+EXPORT_SYMBOL_GPL vmlinux 0xdba61bed	kick_process
+EXPORT_SYMBOL_GPL vmlinux 0xdba64f1c	eventfd_ctx_get
+EXPORT_SYMBOL_GPL vmlinux 0xdbcb0420	platform_driver_probe
+EXPORT_SYMBOL_GPL vmlinux 0xdc1f8f2e	register_timer_hook
+EXPORT_SYMBOL_GPL vmlinux 0xdc583c08	dlm_unlock
+EXPORT_SYMBOL_GPL vmlinux 0xdc74e790	synchronize_srcu
+EXPORT_SYMBOL_GPL vmlinux 0xdc760ab5	xfrm_output
+EXPORT_SYMBOL_GPL vmlinux 0xdc8253a9	security_inode_create
+EXPORT_SYMBOL_GPL vmlinux 0xdcb73dc1	crypto_givcipher_type
+EXPORT_SYMBOL_GPL vmlinux 0xdd2cf44e	__fsnotify_inode_delete
+EXPORT_SYMBOL_GPL vmlinux 0xdda7fcce	dm_dispatch_request
+EXPORT_SYMBOL_GPL vmlinux 0xddc05502	w1_touch_block
+EXPORT_SYMBOL_GPL vmlinux 0xddd1d850	gnttab_end_foreign_access_ref
+EXPORT_SYMBOL_GPL vmlinux 0xddee4435	put_inotify_watch
+EXPORT_SYMBOL_GPL vmlinux 0xde110a0f	device_create_vargs
+EXPORT_SYMBOL_GPL vmlinux 0xde354530	ring_buffer_time_stamp
+EXPORT_SYMBOL_GPL vmlinux 0xde417b81	async_schedule_domain
+EXPORT_SYMBOL_GPL vmlinux 0xdf2dfaa6	sg_scsi_ioctl
+EXPORT_SYMBOL_GPL vmlinux 0xdf571a06	inet_csk_get_port
+EXPORT_SYMBOL_GPL vmlinux 0xe04cb463	fib_rules_lookup
+EXPORT_SYMBOL_GPL vmlinux 0xe0cca33e	xfrm_aead_get_byname
+EXPORT_SYMBOL_GPL vmlinux 0xe0f06252	seq_release_net
+EXPORT_SYMBOL_GPL vmlinux 0xe14ffbbf	generic_detach_inode
+EXPORT_SYMBOL_GPL vmlinux 0xe155db02	queue_delayed_work_on
+EXPORT_SYMBOL_GPL vmlinux 0xe16b4824	free_empty_pages_and_pagevec
+EXPORT_SYMBOL_GPL vmlinux 0xe194208f	devres_open_group
+EXPORT_SYMBOL_GPL vmlinux 0xe1cad262	relay_close
+EXPORT_SYMBOL_GPL vmlinux 0xe26d049c	do_kern_mount
+EXPORT_SYMBOL_GPL vmlinux 0xe3536124	devm_kfree
+EXPORT_SYMBOL_GPL vmlinux 0xe37efaac	driver_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xe3913745	bus_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xe3c9d9b2	xfrm_audit_state_icvfail
+EXPORT_SYMBOL_GPL vmlinux 0xe3ff75d0	find_module
+EXPORT_SYMBOL_GPL vmlinux 0xe4428977	register_kprobes
+EXPORT_SYMBOL_GPL vmlinux 0xe4ef80a2	power_supply_get_by_name
+EXPORT_SYMBOL_GPL vmlinux 0xe513afc0	cache_k8_northbridges
+EXPORT_SYMBOL_GPL vmlinux 0xe530071c	pm_qos_remove_requirement
+EXPORT_SYMBOL_GPL vmlinux 0xe531d8c8	skb_cow_data
+EXPORT_SYMBOL_GPL vmlinux 0xe594a13b	__pci_reset_function
+EXPORT_SYMBOL_GPL vmlinux 0xe61a6d2f	gpio_unexport
+EXPORT_SYMBOL_GPL vmlinux 0xe651f76e	selinux_is_enabled
+EXPORT_SYMBOL_GPL vmlinux 0xe6ad46f9	fsstack_copy_attr_all
+EXPORT_SYMBOL_GPL vmlinux 0xe72da50e	task_current_syscall
+EXPORT_SYMBOL_GPL vmlinux 0xe7c2fcf2	rtc_read_alarm
+EXPORT_SYMBOL_GPL vmlinux 0xe7ffe877	pcpu_base_addr
+EXPORT_SYMBOL_GPL vmlinux 0xe80b03eb	pci_create_slot
+EXPORT_SYMBOL_GPL vmlinux 0xe84ed7d6	__ip_route_output_key
+EXPORT_SYMBOL_GPL vmlinux 0xe862c4b7	dpm_suspend_start
+EXPORT_SYMBOL_GPL vmlinux 0xe8f9b84b	inotify_dentry_parent_queue_event
+EXPORT_SYMBOL_GPL vmlinux 0xe901175f	__dev_addr_unsync
+EXPORT_SYMBOL_GPL vmlinux 0xe906c812	inotify_remove_watch_locked
+EXPORT_SYMBOL_GPL vmlinux 0xe92e3005	sysfs_remove_link
+EXPORT_SYMBOL_GPL vmlinux 0xe93e49c3	devres_free
+EXPORT_SYMBOL_GPL vmlinux 0xe9480885	disk_map_sector_rcu
+EXPORT_SYMBOL_GPL vmlinux 0xea065e01	task_handoff_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xea124bd1	gcd
+EXPORT_SYMBOL_GPL vmlinux 0xea3889ea	devres_release_group
+EXPORT_SYMBOL_GPL vmlinux 0xea74af12	__put_net
+EXPORT_SYMBOL_GPL vmlinux 0xeb3a8db0	rtc_alarm_irq_enable
+EXPORT_SYMBOL_GPL vmlinux 0xeb43ead9	put_device
+EXPORT_SYMBOL_GPL vmlinux 0xeb4c1fc8	__tracepoint_block_remap
+EXPORT_SYMBOL_GPL vmlinux 0xeb9e1026	srcu_read_lock
+EXPORT_SYMBOL_GPL vmlinux 0xec1a75a9	__dev_addr_sync
+EXPORT_SYMBOL_GPL vmlinux 0xec6cc680	pci_unblock_user_cfg_access
+EXPORT_SYMBOL_GPL vmlinux 0xec717d6f	dlm_posix_get
+EXPORT_SYMBOL_GPL vmlinux 0xeca103f3	__blk_put_request
+EXPORT_SYMBOL_GPL vmlinux 0xeca774e3	blk_queue_dma_drain
+EXPORT_SYMBOL_GPL vmlinux 0xece67c75	power_supply_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xed1928f6	apply_to_page_range
+EXPORT_SYMBOL_GPL vmlinux 0xed4f8bd3	firmware_kobj
+EXPORT_SYMBOL_GPL vmlinux 0xeee8dcad	device_schedule_callback_owner
+EXPORT_SYMBOL_GPL vmlinux 0xeef854c4	register_pernet_gen_device
+EXPORT_SYMBOL_GPL vmlinux 0xef232816	ring_buffer_record_enable
+EXPORT_SYMBOL_GPL vmlinux 0xef2cfcc3	vfs_lock_file
+EXPORT_SYMBOL_GPL vmlinux 0xef66065e	blk_execute_rq_nowait
+EXPORT_SYMBOL_GPL vmlinux 0xef6c3f70	round_jiffies_up_relative
+EXPORT_SYMBOL_GPL vmlinux 0xef886a14	ahash_attr_alg
+EXPORT_SYMBOL_GPL vmlinux 0xef9dce31	__blk_end_request_err
+EXPORT_SYMBOL_GPL vmlinux 0xeface7f5	swiotlb_sync_single_range_for_device
+EXPORT_SYMBOL_GPL vmlinux 0xefada294	aead_geniv_free
+EXPORT_SYMBOL_GPL vmlinux 0xefc0137e	nf_unregister_afinfo
+EXPORT_SYMBOL_GPL vmlinux 0xefdd5a63	ktime_get_ts
+EXPORT_SYMBOL_GPL vmlinux 0xefe821da	ring_buffer_resize
+EXPORT_SYMBOL_GPL vmlinux 0xf03ed124	blk_rq_unprep_clone
+EXPORT_SYMBOL_GPL vmlinux 0xf0aa54c4	pskb_put
+EXPORT_SYMBOL_GPL vmlinux 0xf0b625a9	dm_get_rq_mapinfo
+EXPORT_SYMBOL_GPL vmlinux 0xf1290996	class_compat_register
+EXPORT_SYMBOL_GPL vmlinux 0xf13f0890	vfs_kern_mount
+EXPORT_SYMBOL_GPL vmlinux 0xf13fdfae	srcu_read_unlock
+EXPORT_SYMBOL_GPL vmlinux 0xf184d189	kernel_power_off
+EXPORT_SYMBOL_GPL vmlinux 0xf1d1e2f1	rtc_device_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xf2158149	rt_mutex_timed_lock
+EXPORT_SYMBOL_GPL vmlinux 0xf2338de7	blk_rq_err_bytes
+EXPORT_SYMBOL_GPL vmlinux 0xf2362172	blkcipher_walk_phys
+EXPORT_SYMBOL_GPL vmlinux 0xf2b0502c	eventfd_ctx_fileget
+EXPORT_SYMBOL_GPL vmlinux 0xf2d1af20	rt_mutex_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xf2f96307	inet_twsk_purge
+EXPORT_SYMBOL_GPL vmlinux 0xf2fca922	uart_parse_options
+EXPORT_SYMBOL_GPL vmlinux 0xf33ebce6	__set_irq_handler
+EXPORT_SYMBOL_GPL vmlinux 0xf34806ec	hrtimer_get_res
+EXPORT_SYMBOL_GPL vmlinux 0xf3706b5e	crypto_drop_spawn
+EXPORT_SYMBOL_GPL vmlinux 0xf3833c7a	task_active_pid_ns
+EXPORT_SYMBOL_GPL vmlinux 0xf3c1c0a0	leds_list_lock
+EXPORT_SYMBOL_GPL vmlinux 0xf4136b66	blk_rq_check_limits
+EXPORT_SYMBOL_GPL vmlinux 0xf499fdb2	rcu_barrier_bh
+EXPORT_SYMBOL_GPL vmlinux 0xf4aebdc3	xenbus_suspend
+EXPORT_SYMBOL_GPL vmlinux 0xf533f381	ip_build_and_send_pkt
+EXPORT_SYMBOL_GPL vmlinux 0xf5384ac1	__trace_printk
+EXPORT_SYMBOL_GPL vmlinux 0xf5469b42	input_ff_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xf547995c	xfrm_audit_state_notfound_simple
+EXPORT_SYMBOL_GPL vmlinux 0xf54bd49b	lcm
+EXPORT_SYMBOL_GPL vmlinux 0xf5799f7a	stop_machine_destroy
+EXPORT_SYMBOL_GPL vmlinux 0xf589b391	inet_twdr_twkill_work
+EXPORT_SYMBOL_GPL vmlinux 0xf5945bac	gnttab_free_grant_references
+EXPORT_SYMBOL_GPL vmlinux 0xf5a691cd	invalidate_bh_lrus
+EXPORT_SYMBOL_GPL vmlinux 0xf5fa587b	nf_unregister_queue_handlers
+EXPORT_SYMBOL_GPL vmlinux 0xf61f262b	macvlan_handle_frame_hook
+EXPORT_SYMBOL_GPL vmlinux 0xf64a081f	platform_device_add_resources
+EXPORT_SYMBOL_GPL vmlinux 0xf67e03ca	pci_enable_pcie_error_reporting
+EXPORT_SYMBOL_GPL vmlinux 0xf68eff30	k_handler
+EXPORT_SYMBOL_GPL vmlinux 0xf69ab8bf	skcipher_geniv_alloc
+EXPORT_SYMBOL_GPL vmlinux 0xf6bcbd73	hwrng_register
+EXPORT_SYMBOL_GPL vmlinux 0xf7016530	xenbus_gather
+EXPORT_SYMBOL_GPL vmlinux 0xf7594973	kern_mount_data
+EXPORT_SYMBOL_GPL vmlinux 0xf7dc2fc3	ring_buffer_empty
+EXPORT_SYMBOL_GPL vmlinux 0xf7fb4639	transport_class_register
+EXPORT_SYMBOL_GPL vmlinux 0xf80afb00	class_remove_file
+EXPORT_SYMBOL_GPL vmlinux 0xf83d3b00	__create_workqueue_key
+EXPORT_SYMBOL_GPL vmlinux 0xf84f5373	inet_csk_bind_conflict
+EXPORT_SYMBOL_GPL vmlinux 0xf8802492	print_stack_trace
+EXPORT_SYMBOL_GPL vmlinux 0xf8a36541	inode_add_to_lists
+EXPORT_SYMBOL_GPL vmlinux 0xf8c8770d	eventfd_fget
+EXPORT_SYMBOL_GPL vmlinux 0xf8fcd88e	anon_transport_class_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xf9739b2a	crypto_larval_kill
+EXPORT_SYMBOL_GPL vmlinux 0xf97666a0	set_memory_rw
+EXPORT_SYMBOL_GPL vmlinux 0xf98e7286	sysfs_update_group
+EXPORT_SYMBOL_GPL vmlinux 0xf9a054b5	__round_jiffies
+EXPORT_SYMBOL_GPL vmlinux 0xfa1f4662	scatterwalk_start
+EXPORT_SYMBOL_GPL vmlinux 0xfaf4d213	user_match
+EXPORT_SYMBOL_GPL vmlinux 0xfb0aeb89	shash_attr_alg
+EXPORT_SYMBOL_GPL vmlinux 0xfb534dfe	seq_open_net
+EXPORT_SYMBOL_GPL vmlinux 0xfb815e7f	spi_alloc_device
+EXPORT_SYMBOL_GPL vmlinux 0xfb9a765b	tcp_set_state
+EXPORT_SYMBOL_GPL vmlinux 0xfbb032a5	br_fdb_test_addr_hook
+EXPORT_SYMBOL_GPL vmlinux 0xfbbbaf44	crypto_enqueue_request
+EXPORT_SYMBOL_GPL vmlinux 0xfbe1ed15	xenbus_watch_path2
+EXPORT_SYMBOL_GPL vmlinux 0xfbefdbad	tty_ldisc_ref_wait
+EXPORT_SYMBOL_GPL vmlinux 0xfbf9be5d	register_oom_notifier
+EXPORT_SYMBOL_GPL vmlinux 0xfc0c97d9	pci_bus_add_device
+EXPORT_SYMBOL_GPL vmlinux 0xfc80b0c8	transport_add_device
+EXPORT_SYMBOL_GPL vmlinux 0xfc8f51eb	xenbus_alloc_evtchn
+EXPORT_SYMBOL_GPL vmlinux 0xfd052b34	tty_wakeup
+EXPORT_SYMBOL_GPL vmlinux 0xfd17ea4a	user_read
+EXPORT_SYMBOL_GPL vmlinux 0xfde0b92c	crypto_larval_error
+EXPORT_SYMBOL_GPL vmlinux 0xfdf8d929	crypto_alloc_ahash
+EXPORT_SYMBOL_GPL vmlinux 0xfdfb9c58	ring_buffer_read_start
+EXPORT_SYMBOL_GPL vmlinux 0xfdfeb551	skb_icv_walk
+EXPORT_SYMBOL_GPL vmlinux 0xfe112768	bus_get_device_klist
+EXPORT_SYMBOL_GPL vmlinux 0xfe6736ab	__root_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xfe990052	gpio_free
+EXPORT_SYMBOL_GPL vmlinux 0xfebc5212	class_compat_unregister
+EXPORT_SYMBOL_GPL vmlinux 0xfed12ac5	ring_buffer_peek
+EXPORT_SYMBOL_GPL vmlinux 0xfee44ac3	get_net_ns_by_pid
+EXPORT_SYMBOL_GPL vmlinux 0xfefa2adb	input_ff_effect_from_user
+EXPORT_SYMBOL_GPL vmlinux 0xff5a8cfe	cn_del_callback
+EXPORT_SYMBOL_GPL vmlinux 0xff94726b	hwmon_device_register
+EXPORT_SYMBOL_GPL vmlinux 0xffe2538f	hrtimer_cancel
+EXPORT_SYMBOL_GPL vmlinux 0xfff4a22a	key_type_user
+EXPORT_SYMBOL_GPL vmlinux 0xfffb5a97	xenbus_dev_fatal
+EXPORT_UNUSED_SYMBOL vmlinux 0x00000000	simple_prepare_write
--- linux-ec2-2.6.32.orig/debian.ec2/abi/2.6.32-317.35/amd64/ec2.modules
+++ linux-ec2-2.6.32/debian.ec2/abi/2.6.32-317.35/amd64/ec2.modules
@@ -0,0 +1,1627 @@
+3c359
+3c574_cs
+3c589_cs
+3c59x
+3w-9xxx
+3w-xxxx
+6pack
+8021q
+8139cp
+8139too
+8390
+9p
+9pnet
+a100u2w
+a3d
+aacraid
+abituguru
+abituguru3
+abyss
+ac97_bus
+acecad
+acenic
+acquirewdt
+act200l-sir
+act_gact
+act_ipt
+actisys-sir
+act_mirred
+act_nat
+act_pedit
+act_police
+act_simple
+ad1848
+ad7414
+ad7418
+adcxx
+adfs
+adi
+adm1021
+adm1025
+adm1026
+adm1029
+adm1031
+adm9240
+ads7828
+ads7846
+adt7470
+adt7473
+adutux
+advansys
+advantechwdt
+aedsp16
+aes_generic
+aesni-intel
+aes-x86_64
+affs
+af_key
+af-rxrpc
+agpgart
+ah4
+ah6
+ahci
+aic79xx
+aic7xxx
+aic94xx
+aiptek
+aircable
+alauda
+ali-ircc
+alim1535_wdt
+alim7101_wdt
+ambassador
+amd64-agp
+amd76xrom
+amd8111e
+amd-rng
+analog
+anubis
+aoe
+appledisplay
+applesmc
+appletalk
+appletouch
+applicom
+ar7part
+arc4
+arcfb
+arcmsr
+arcnet
+arc-rawmode
+arc-rimi
+ark3116
+arkfb
+arptable_filter
+arp_tables
+arpt_mangle
+asb100
+asix
+async_memcpy
+async_pq
+async_raid6_recov
+async_tx
+async_xor
+ata_generic
+ata_piix
+aten
+ati_remote
+ati_remote2
+atl1
+atl1e
+atl2
+atmtcp
+atp
+atp870u
+atxp1
+aty128fb
+atyfb
+aufs
+authenc
+auth_rpcgss
+autofs
+autofs4
+av5100
+ax25
+axnet_cs
+b44
+baycom_par
+baycom_ser_fdx
+baycom_ser_hdx
+bcm203x
+bcm5974
+befs
+belkin_sa
+berry_charge
+bfs
+bfusb
+binfmt_misc
+bitblit
+block2mtd
+blowfish
+bluecard_cs
+bluetooth
+bnep
+bnx2
+bnx2x
+bonding
+bpa10x
+bpck
+bpqether
+br2684
+bridge
+broadcom
+bsd_comp
+bt3c_cs
+btrfs
+btuart_cs
+btusb
+BusLogic
+c67x00
+cafe_nand
+camellia
+capmode
+carminefb
+cassini
+cast5
+cast6
+catc
+cbc
+cciss
+ccm
+cdc-acm
+cdc_ether
+cdc_subset
+cdc-wdm
+cfag12864b
+cfag12864bfb
+cfg80211
+cfi_cmdset_0001
+cfi_cmdset_0002
+cfi_cmdset_0020
+cfi_probe
+cfi_util
+ch
+ch341
+chipreg
+cicada
+cifs
+cirrusfb
+ck804xrom
+cls_basic
+cls_fw
+cls_route
+cls_rsvp
+cls_rsvp6
+cls_tcindex
+cls_u32
+cm4000_cs
+cm4040_cs
+cobra
+coda
+com20020
+com20020_cs
+com20020-pci
+com90io
+com90xx
+comm
+coretemp
+cpcihp_generic
+cpcihp_zt5550
+cpqarray
+cpu5wdt
+cpuid
+cr_bllcd
+crc32c
+crc7
+crc-ccitt
+crc-itu-t
+crc-t10dif
+crvml
+cryptd
+cryptoloop
+crypto_null
+ct82c710
+ctr
+cts
+cxacru
+cxgb
+cxgb3
+cyber2000fb
+cyberjack
+cyclades
+cyclomx
+cycx_drv
+cypress_cy7c63
+cypress_m8
+cytherm
+DAC960
+davicom
+db9
+dc395x
+dccp
+dccp_diag
+dccp_ipv4
+dccp_ipv6
+dccp_probe
+de2104x
+de4x5
+de600
+de620
+decnet
+deflate
+defxx
+des_generic
+digi_acceleport
+diskonchip
+display
+dlci
+dm9601
+dm-crypt
+dme1737
+dmfe
+dm-log
+dm-mirror
+dm-multipath
+dm-raid45
+dm-region-hash
+dm-round-robin
+dm-snapshot
+dmx3191d
+dm-zero
+dn_rtmsg
+doc2000
+doc2001
+doc2001plus
+docecc
+docprobe
+dpt_i2o
+drm
+drm_kms_helper
+ds1621
+ds1682
+ds2482
+ds2490
+ds2760_battery
+dscc4
+dstr
+dtl1_cs
+dummy_hcd
+dv1394
+e100
+e1000
+e1000e
+e752x_edac
+eata
+ebt_802_3
+ebtable_broute
+ebtable_filter
+ebtable_nat
+ebtables
+ebt_among
+ebt_arp
+ebt_arpreply
+ebt_dnat
+ebt_ip
+ebt_ip6
+ebt_limit
+ebt_log
+ebt_mark
+ebt_mark_m
+ebt_nflog
+ebt_pkttype
+ebt_redirect
+ebt_snat
+ebt_stp
+ebt_ulog
+ebt_vlan
+ecb
+econet
+ecryptfs
+edac_core
+eeprom_93cx6
+efs
+ehci-hcd
+elo
+em_cmp
+emi26
+emi62
+em_meta
+em_nbyte
+empeg
+em_text
+emu10k1-gp
+em_u32
+enclosure
+eni
+epat
+epca
+epia
+epic100
+esb2rom
+esi-sir
+esp4
+esp6
+eth1394
+eurotechwdt
+evbug
+evdev
+f71805f
+f71882fg
+f75375s
+fakephp
+farsync
+fat
+faulty
+fbcon
+fb_ddc
+fb_sys_fops
+fcrypt
+fdomain
+fdomain_cs
+fealnx
+ff-memless
+firestream
+fit2
+fit3
+floppy
+fm801-gp
+fmvj18x_cs
+font
+forcedeth
+fore_200e
+fpu
+freevxfs
+friq
+frpw
+fsam7400
+fscache
+fschmd
+ftdi-elan
+ftdi_sio
+ftl
+fujitsu_ts
+funsoft
+fuse
+g450_pll
+gadgetfs
+gamecon
+gameport
+garmin_gps
+garp
+g_cdc
+gcm
+gdth
+gen_probe
+g_ether
+gf128mul
+gf2k
+g_file_storage
+ghash-clmulni-intel
+ghash-generic
+girbil-sir
+gl518sm
+gl520sm
+gl620a
+gluebi
+gpio_keys
+gpio_mouse
+grip
+grip_mp
+g_serial
+gtco
+guillemot
+gunze
+gx1fb
+gxfb
+g_zero
+hamachi
+hangcheck-timer
+hci_uart
+hci_vhci
+hdaps
+hdlc
+hdlc_cisco
+hdlcdrv
+hdlc_fr
+hdlc_ppp
+hdlc_raw
+hdlc_raw_eth
+hdlc_x25
+he
+hecubafb
+hfs
+hfsplus
+hgafb
+hid
+hid-a4tech
+hid-apple
+hid-belkin
+hid-cherry
+hid-chicony
+hid-cypress
+hid-drff
+hid-ezkey
+hid-gaff
+hid-gyration
+hid-kensington
+hid-kye
+hid-logitech
+hid-microsoft
+hid-monterey
+hid-ntrig
+hid-ortek
+hidp
+hid-petalynx
+hid-pl
+hid-samsung
+hid-sjoy
+hid-sony
+hid-sunplus
+hid-tmff
+hid-topseed
+hid-twinhan
+hid-wacom
+hid-zpff
+hifn_795x
+horizon
+hp100
+hp4x
+hpfs
+hpilo
+hptiop
+hso
+htc-pasic3
+hwmon-vid
+i2c-algo-bit
+i2c-algo-pca
+i2c-algo-pcf
+i2c-ali1535
+i2c-ali1563
+i2c-ali15x3
+i2c-amd756
+i2c-amd756-s4882
+i2c-amd8111
+i2c-core
+i2c-dev
+i2c-gpio
+i2c-i801
+i2c-isch
+i2c-matroxfb
+i2c-nforce2
+i2c-nforce2-s4985
+i2c-ocores
+i2c-parport
+i2c-parport-light
+i2c-pca-platform
+i2c-piix4
+i2c-simtec
+i2c-sis5595
+i2c-sis630
+i2c-sis96x
+i2c-stub
+i2c-taos-evm
+i2c-tiny-usb
+i2c-via
+i2c-viapro
+i2c-voodoo3
+i2o_block
+i2o_bus
+i2o_config
+i2o_core
+i2o_proc
+i2o_scsi
+i3000_edac
+i5000_edac
+i5100_edac
+i5k_amb
+i6300esb
+i82092
+i82975x_edac
+i8k
+ib700wdt
+ib_addr
+ib_cm
+ib_core
+ib_ipath
+ib_ipoib
+ib_iser
+ib_mad
+ibmaem
+ibmasm
+ibmasr
+ibmpex
+ib_mthca
+ibmtr_cs
+ib_sa
+ib_srp
+ib_ucm
+ib_umad
+ib_uverbs
+ichxrom
+icplus
+idmouse
+idt77252
+ieee1394
+iforce
+igb
+ili9320
+imm
+inexio
+inftl
+initio
+input-polldev
+intel-rng
+intel_vr_nor
+interact
+ioc4
+io_edgeport
+io_ti
+iowarrior
+ip2
+ip6_queue
+ip6table_filter
+ip6table_mangle
+ip6table_raw
+ip6_tables
+ip6table_security
+ip6t_ah
+ip6t_eui64
+ip6t_frag
+ip6t_hbh
+ip6t_ipv6header
+ip6t_LOG
+ip6t_mh
+ip6t_REJECT
+ip6t_rt
+ip6_tunnel
+ipaq
+ipcomp
+ipcomp6
+ipddp
+ipg
+ip_gre
+iphase
+ipip
+ipmi_devintf
+ipmi_msghandler
+ipmi_poweroff
+ipmi_si
+ipmi_watchdog
+ip_queue
+ipr
+ips
+iptable_filter
+iptable_mangle
+iptable_nat
+iptable_raw
+ip_tables
+iptable_security
+ipt_addrtype
+ipt_ah
+ipt_CLUSTERIP
+ipt_ecn
+ipt_ECN
+ipt_LOG
+ipt_MASQUERADE
+ipt_NETMAP
+ipt_REDIRECT
+ipt_REJECT
+ipt_ULOG
+ipv6
+ip_vs
+ip_vs_dh
+ip_vs_ftp
+ip_vs_lblc
+ip_vs_lblcr
+ip_vs_lc
+ip_vs_nq
+ip_vs_rr
+ip_vs_sed
+ip_vs_sh
+ip_vs_wlc
+ip_vs_wrr
+ipw
+ipwireless
+ipx
+ircomm
+ircomm-tty
+irda
+irda-usb
+irlan
+irnet
+irtty-sir
+iscsi_tcp
+iscsi_trgt
+isight_firmware
+isofs
+isp116x-hcd
+isp1760
+it87
+it8712f_wdt
+iTCO_vendor_support
+iTCO_wdt
+iw_c2
+iw_cm
+iw_cxgb3
+ixgb
+ixgbe
+jedec_probe
+jffs2
+joydev
+joydump
+jsm
+k8temp
+kafs
+kahlua
+kaweth
+kbic
+kbtab
+keyspan
+keyspan_pda
+keyspan_remote
+khazad
+kingsun-sir
+kl5kusb105
+kobil_sct
+ks0108
+ks959-sir
+ksdazzle-sir
+ktti
+kyrofb
+l2cap
+l440gx
+lanai
+lapb
+lapbether
+lcd
+ldusb
+lec
+led-class
+leds-gpio
+leds-pca9532
+leds-pca955x
+ledtrig-default-on
+ledtrig-heartbeat
+ledtrig-timer
+legousbtower
+libata
+libcrc32c
+libiscsi
+libiscsi_tcp
+libsas
+libsrp
+lightning
+linear
+lirc_atiusb
+lirc_bt829
+lirc_dev
+lirc_i2c
+lirc_igorplugusb
+lirc_imon
+lirc_it87
+lirc_ite8709
+lirc_mceusb
+lirc_sasem
+lirc_serial
+lirc_sir
+lirc_streamzap
+lirc_ttusbir
+litelink-sir
+lkkbd
+llc2
+lm63
+lm70
+lm75
+lm77
+lm78
+lm80
+lm83
+lm85
+lm87
+lm90
+lm92
+lm93
+lmc
+lockd
+lp
+lpfc
+lrw
+ltv350qv
+lxfb
+lxt
+lzo
+lzo_compress
+lzo_decompress
+m25p80
+ma600-sir
+mac80211
+machzwd
+macmodes
+magellan
+map_absent
+map_funcs
+map_ram
+map_rom
+marvell
+matroxfb_accel
+matroxfb_base
+matroxfb_crtc2
+matroxfb_DAC1064
+matroxfb_g450
+matroxfb_maven
+matroxfb_misc
+matroxfb_Ti3026
+matrox_w1
+max1619
+max6650
+max7301
+max732x
+mbp_nvidia_bl
+mcp2120-sir
+mcp23s08
+mcs7780
+mcs7830
+mct_u232
+md4
+mdc800
+mdio
+mdio-bitbang
+md-mod
+megaraid
+megaraid_mbox
+megaraid_mm
+megaraid_sas
+mfd-core
+mga
+michael_mic
+microtek
+mii
+minix
+mk712
+mkiss
+mlx4_core
+mlx4_ib
+mos7720
+mos7840
+moto_modem
+moxa
+mpoa
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
+mpu401
+msdos
+msr
+mtd
+mtd_blkdevs
+mtdblock
+mtdblock_ro
+mtdchar
+mtdconcat
+mtd_dataflash
+mtdoops
+mtdram
+mtouch
+multipath
+mwave
+mxser
+myri10ge
+n411
+nand
+nand_ecc
+nand_ids
+nandsim
+natsemi
+navman
+nbd
+ncpfs
+ndiswrapper
+ne2k-pci
+neofb
+net1080
+netconsole
+netrom
+netsc520
+nettel
+netxen_nic
+newtonkbd
+nf_conntrack
+nf_conntrack_amanda
+nf_conntrack_ftp
+nf_conntrack_h323
+nf_conntrack_ipv4
+nf_conntrack_ipv6
+nf_conntrack_irc
+nf_conntrack_netbios_ns
+nf_conntrack_netlink
+nf_conntrack_pptp
+nf_conntrack_proto_gre
+nf_conntrack_proto_sctp
+nf_conntrack_proto_udplite
+nf_conntrack_sip
+nf_conntrack_tftp
+nf_defrag_ipv4
+nf_nat
+nf_nat_amanda
+nf_nat_ftp
+nf_nat_h323
+nf_nat_irc
+nf_nat_pptp
+nf_nat_proto_gre
+nf_nat_proto_sctp
+nf_nat_proto_udplite
+nf_nat_sip
+nf_nat_snmp_basic
+nf_nat_tftp
+nfnetlink
+nfnetlink_log
+nfnetlink_queue
+nfs
+nfs_acl
+nfsd
+nftl
+n_hdlc
+niu
+nls_ascii
+nls_cp1250
+nls_cp1251
+nls_cp1255
+nls_cp437
+nls_cp737
+nls_cp775
+nls_cp850
+nls_cp852
+nls_cp855
+nls_cp857
+nls_cp860
+nls_cp861
+nls_cp862
+nls_cp863
+nls_cp864
+nls_cp865
+nls_cp866
+nls_cp869
+nls_cp874
+nls_cp932
+nls_cp936
+nls_cp949
+nls_cp950
+nls_euc-jp
+nls_iso8859-1
+nls_iso8859-13
+nls_iso8859-14
+nls_iso8859-15
+nls_iso8859-2
+nls_iso8859-3
+nls_iso8859-4
+nls_iso8859-5
+nls_iso8859-6
+nls_iso8859-7
+nls_iso8859-9
+nls_koi8-r
+nls_koi8-ru
+nls_koi8-u
+nls_utf8
+nmclan_cs
+nozomi
+n_r3964
+ns558
+ns83820
+nsc_gpio
+nsc-ircc
+ntfs
+nvidiafb
+nvram
+ocfs2
+ocfs2_dlm
+ocfs2_dlmfs
+ocfs2_nodemanager
+ocfs2_stackglue
+ocfs2_stack_o2cb
+ocfs2_stack_user
+ohci1394
+ohci-hcd
+old_belkin-sir
+olympic
+omfs
+omnibook
+omninet
+on20
+on26
+onenand
+onenand_sim
+opl3
+oprofile
+option
+osst
+oti6858
+output
+p8023
+padlock-aes
+padlock-sha
+paride
+parkbd
+parport
+parport_ax88796
+parport_cs
+parport_pc
+parport_serial
+pas2
+pata_ali
+pata_amd
+pata_artop
+pata_atiixp
+pata_cmd64x
+pata_cs5520
+pata_cs5530
+pata_efar
+pata_hpt366
+pata_hpt37x
+pata_hpt3x3
+pata_it8213
+pata_it821x
+pata_jmicron
+pata_marvell
+pata_mpiix
+pata_netcell
+pata_ninja32
+pata_ns87410
+pata_ns87415
+pata_oldpiix
+pata_pcmcia
+pata_pdc2027x
+pata_pdc202xx_old
+pata_rz1000
+pata_sch
+pata_serverworks
+pata_sil680
+pata_sis
+pata_sl82c105
+pata_triflex
+pata_via
+pbe5
+pc87360
+pc8736x_gpio
+pc87413_wdt
+pc87427
+pca953x
+pcbc
+pcd
+pcf857x
+pcf8591
+pci
+pci200syn
+pciehp
+pci_hotplug
+pcilynx
+pcips2
+pcmcia
+pcmcia_core
+pcnet32
+pcnet_cs
+pcspkr
+pcwd_pci
+pcwd_usb
+pd
+pd6729
+pda_power
+pdc_adma
+pegasus
+penmount
+pf
+pg
+phantom
+phonedev
+phram
+physmap
+pktcdvd
+pktgen
+pl2303
+platform_lcd
+plat_nand
+plat-ram
+plip
+plusb
+pm2fb
+pm3fb
+pmc551
+powermate
+ppa
+ppdev
+ppp_async
+ppp_deflate
+ppp_mppe
+pppoatm
+pppoe
+pppol2tp
+pppox
+ppp_synctty
+progear_bl
+psmouse
+pss
+pt
+qla1280
+qla2xxx
+qla3xxx
+qla4xxx
+qlogic_cs
+qlogicfas408
+qnx4
+qsemi
+quota_tree
+quota_v1
+quota_v2
+r128
+r8169
+r8192se_pci
+r8a66597-hcd
+radeon
+radeonfb
+raid0
+raid1
+raid10
+raid456
+raid6_pq
+raid_class
+ramzswap
+raw
+raw1394
+rdma_cm
+rdma_ucm
+redboot
+reed_solomon
+rfc1051
+rfc1201
+rfcomm
+rfd_ftl
+rfkill
+rio500
+riscom8
+rivafb
+rmd128
+rmd160
+rmd256
+rmd320
+rndis_host
+rocket
+romfs
+rose
+rpcsec_gss_krb5
+rpcsec_gss_spkm3
+rrunner
+rsrc_nonstatic
+rtc-ds1305
+rtc-ds1307
+rtc-ds1374
+rtc-ds1553
+rtc-ds1672
+rtc-ds1742
+rtc-fm3130
+rtc-isl1208
+rtc-m41t80
+rtc-m41t94
+rtc-m48t59
+rtc-m48t86
+rtc-max6900
+rtc-max6902
+rtc-pcf8563
+rtc-pcf8583
+rtc-rs5c348
+rtc-rs5c372
+rtc-stk17ta8
+rtc-test
+rtc-v3020
+rtc-x1205
+rtl8150
+rxkad
+s1d13xxxfb
+s2io
+s3fb
+safe_serial
+salsa20_generic
+salsa20-x86_64
+sata_inic162x
+sata_mv
+sata_nv
+sata_promise
+sata_qstor
+sata_sil
+sata_sil24
+sata_sis
+sata_svw
+sata_sx4
+sata_uli
+sata_via
+sata_vsc
+savage
+savagefb
+sb
+sbc60xxwdt
+sbc8360
+sbc_epx_c3
+sbc_gxx
+sb_lib
+sbni
+sbp2
+sc1200wdt
+sc520cdp
+sc520_wdt
+sc92031
+scb2_flash
+sch_atm
+sch_cbq
+sch_dsmark
+sch_gred
+sch_hfsc
+sch_htb
+sch_ingress
+sch_netem
+sch_prio
+sch_red
+sch_sfq
+sch_tbf
+sch_teql
+sco
+scsi_debug
+scsi_dh
+scsi_dh_alua
+scsi_dh_emc
+scsi_dh_hp_sw
+scsi_dh_rdac
+scsi_mod
+scsi_tgt
+scsi_transport_fc
+scsi_transport_iscsi
+scsi_transport_sas
+scsi_transport_spi
+scsi_transport_srp
+scsi_wait_scan
+sctp
+sd_mod
+seed
+seqiv
+serial_cs
+serio_raw
+sermouse
+serpent
+serport
+ses
+sfc
+sg
+sha1_generic
+sha256_generic
+sha512_generic
+shpchp
+sidewinder
+sierra
+sir-dev
+sis
+sis190
+sis5595
+sis900
+sis-agp
+sisfb
+sisusbvga
+sit
+skfp
+skge
+sky2
+sl811_cs
+sl811-hcd
+slip
+slram
+sm501
+sm501fb
+smbfs
+smc91c92_cs
+smsc
+smsc37b787_wdt
+smsc47b397
+smsc47m1
+smsc47m192
+smsc-ircc2
+snd
+snd-ac97-codec
+snd-ad1889
+snd-ak4114
+snd-ak4117
+snd-ak4xxx-adda
+snd-ali5451
+snd-als300
+snd-als4000
+snd-atiixp
+snd-atiixp-modem
+snd-au8810
+snd-au8820
+snd-au8830
+snd-aw2
+snd-azt3328
+snd-bt87x
+snd-ca0106
+snd-cmipci
+snd-cs4281
+snd-cs46xx
+snd-cs5530
+snd-cs5535audio
+snd-cs8427
+snd-darla20
+snd-darla24
+snd-dummy
+snd-echo3g
+snd-emu10k1
+snd-emu10k1-synth
+snd-emu10k1x
+snd-emux-synth
+snd-ens1370
+snd-ens1371
+snd-es1938
+snd-es1968
+snd-fm801
+snd-gina20
+snd-gina24
+snd-hda-codec
+snd-hda-codec-analog
+snd-hda-codec-atihdmi
+snd-hda-codec-ca0110
+snd-hda-codec-cirrus
+snd-hda-codec-cmedia
+snd-hda-codec-conexant
+snd-hda-codec-idt
+snd-hda-codec-intelhdmi
+snd-hda-codec-nvhdmi
+snd-hda-codec-realtek
+snd-hda-codec-si3054
+snd-hda-codec-via
+snd-hda-intel
+snd-hdsp
+snd-hdspm
+snd-hifier
+snd-hwdep
+snd-i2c
+snd-ice1712
+snd-ice1724
+snd-ice17xx-ak4xxx
+snd-indigo
+snd-indigodj
+snd-indigoio
+snd-intel8x0
+snd-intel8x0m
+snd-korg1212
+snd-layla20
+snd-layla24
+snd-maestro3
+snd-mia
+snd-mixart
+snd-mixer-oss
+snd-mona
+snd-mpu401
+snd-mpu401-uart
+snd-mtpav
+snd-mts64
+snd-nm256
+snd-opl3-lib
+snd-opl3-synth
+snd-oxygen
+snd-oxygen-lib
+snd-page-alloc
+snd-pcm
+snd-pcm-oss
+snd-pcxhr
+snd-pdaudiocf
+snd-portman2x4
+snd-pt2258
+snd-rawmidi
+snd-riptide
+snd-rme32
+snd-rme96
+snd-rme9652
+snd-sb16-dsp
+snd-sb-common
+snd-seq
+snd-seq-device
+snd-seq-dummy
+snd-seq-midi
+snd-seq-midi-emul
+snd-seq-midi-event
+snd-seq-oss
+snd-seq-virmidi
+snd-serial-u16550
+snd-soc-core
+snd-sonicvibes
+snd-timer
+snd-trident
+snd-usb-audio
+snd-usb-caiaq
+snd-usb-lib
+snd-usb-usx2y
+snd-util-mem
+snd-via82xx
+snd-via82xx-modem
+snd-virmidi
+snd-virtuoso
+snd-vx222
+snd-vx-lib
+snd-vxpocket
+snd-ymfpci
+softcursor
+softdog
+sound
+soundcore
+sound_firmware
+spaceball
+spaceorb
+spcp8x5
+specialix
+speedtch
+spi_bitbang
+spi_butterfly
+spidev
+spi_lm70llp
+sr_mod
+ssb
+sscape
+ssfdc
+sstfb
+st
+starfire
+stex
+stinger
+stir4200
+stowaway
+stp
+sundance
+sungem
+sungem_phy
+sunhme
+suni
+sunkbd
+sunrpc
+svcrdma
+svgalib
+sx8
+sym53c500_cs
+sym53c8xx
+synclink
+synclink_cs
+synclink_gt
+synclinkmp
+syscopyarea
+sysfillrect
+sysimgblt
+sysv
+tcp_bic
+tcp_cubic
+tcp_highspeed
+tcp_htcp
+tcp_hybla
+tcp_illinois
+tcp_lp
+tcp_probe
+tcp_scalable
+tcp_vegas
+tcp_veno
+tcp_westwood
+tcp_yeah
+tcrypt
+tdfx
+tdfxfb
+tea
+tehuti
+tekram-sir
+tg3
+tgr192
+thmc50
+tifm_7xx1
+tifm_core
+tileblit
+tipc
+ti_usb_3410_5052
+tlan
+tlclk
+tle62x0
+tmdc
+tms380tr
+tmscsim
+tmspci
+touchit213
+touchright
+touchwin
+tpm
+tpm_atmel
+tpm_nsc
+tps65010
+trancevibrator
+tridentfb
+trix
+ts5500_flash
+ts_bm
+ts_fsm
+ts_kmp
+tsl2550
+ttm
+tulip
+tunnel4
+tunnel6
+turbografx
+twidjoy
+twofish
+twofish_common
+twofish-x86_64
+typhoon
+u132-hcd
+uart401
+uart6850
+ub
+ubi
+ubifs
+udf
+ueagle-atm
+ufs
+uhci-hcd
+uinput
+uio
+uio_cif
+uio_pdrv
+uio_pdrv_genirq
+uio_smx
+uli526x
+umem
+ums-alauda
+ums-datafab
+ums-freecom
+ums-isd200
+ums-jumpshot
+ums-karma
+ums-sddr09
+ums-sddr55
+ums-usbat
+uPD98402
+usbatm
+usbcore
+usb_debug
+usbhid
+usblcd
+usbled
+usb-libusual
+usblp
+usbmon
+usbnet
+usbserial
+usb-storage
+usbtouchscreen
+uss720
+uvesafb
+veth
+vfat
+vga16fb
+vgastate
+vgg2432a4
+via
+via686a
+via-agp
+via-ircc
+via-rhine
+via-rng
+via-velocity
+video1394
+visor
+vitesse
+vlsi_ir
+v_midi
+vmlfb
+vsxxxaa
+vt1211
+vt8231
+vt8623fb
+w1_ds2433
+w1_ds2760
+w1-gpio
+w1_smem
+w1_therm
+w83627ehf
+w83627hf
+w83627hf_wdt
+w83697hf_wdt
+w83781d
+w83791d
+w83792d
+w83793
+w83877f_wdt
+w83977af_ir
+w83977f_wdt
+w83l785ts
+w83l786ng
+wacom
+wafer5823wdt
+wanrouter
+wanxl
+warrior
+wdt_pci
+whiteheat
+winbond-840
+wm97xx-ts
+wp512
+x25
+x25_asy
+xcbc
+xen-hcd
+xenscsi
+xfrm4_mode_beet
+xfrm4_mode_transport
+xfrm4_mode_tunnel
+xfrm4_tunnel
+xfrm6_mode_beet
+xfrm6_mode_ro
+xfrm6_mode_transport
+xfrm6_mode_tunnel
+xfrm6_tunnel
+xfrm_ipcomp
+xfrm_user
+xirc2ps_cs
+xircom_cb
+xor
+xpad
+xprtrdma
+x_tables
+xt_CLASSIFY
+xt_comment
+xt_connbytes
+xt_connlimit
+xt_connmark
+xt_CONNMARK
+xt_CONNSECMARK
+xt_conntrack
+xt_dccp
+xt_dscp
+xt_DSCP
+xt_esp
+xt_hashlimit
+xt_helper
+xt_hl
+xt_HL
+xt_iprange
+xtkbd
+xt_length
+xt_limit
+xt_mac
+xt_mark
+xt_MARK
+xt_multiport
+xt_NFLOG
+xt_NFQUEUE
+xt_NOTRACK
+xt_owner
+xt_physdev
+xt_pkttype
+xt_policy
+xt_quota
+xt_rateest
+xt_RATEEST
+xt_realm
+xt_recent
+xts
+xt_sctp
+xt_SECMARK
+xt_state
+xt_statistic
+xt_string
+xt_tcpmss
+xt_TCPMSS
+xt_tcpudp
+xt_time
+xt_TRACE
+xt_u32
+xusbatm
+xvmalloc
+yam
+yealink
+yellowfin
+yenta_socket
+zatm
+zaurus
+zhenhua
+zlib_deflate
--- linux-ec2-2.6.32.orig/debian.ec2/config/config.common.ubuntu
+++ linux-ec2-2.6.32/debian.ec2/config/config.common.ubuntu
@@ -0,0 +1,3243 @@
+#
+# Common config options automatically generated by splitconfig.pl
+#
+CONFIG_3C359=m
+# CONFIG_4KSTACKS is not set
+CONFIG_60XX_WDT=m
+CONFIG_6PACK=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+CONFIG_8139TOO_8129=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_9P_FS=m
+# CONFIG_9P_FSCACHE is not set
+# CONFIG_AB3100_CORE is not set
+CONFIG_ABYSS=m
+CONFIG_AC97_BUS=m
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_ADFS is not set
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
+CONFIG_ACORN_PARTITION_ICS=y
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_ADVANTECH_WDT=m
+CONFIG_AFFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_AFS_FS=m
+# CONFIG_AFS_FSCACHE is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_AGP=m
+CONFIG_AGP_ALI=m
+CONFIG_AGP_AMD=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_ATI=m
+CONFIG_AGP_EFFICEON=m
+# CONFIG_AGP_INTEL is not set
+CONFIG_AGP_NVIDIA=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_SWORKS=m
+CONFIG_AGP_VIA=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_AIO=y
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_ALI_FIR=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ANON_INODES=y
+CONFIG_APPLICOM=m
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM20020=m
+CONFIG_ARCNET_COM20020_CS=m
+CONFIG_ARCNET_COM20020_PCI=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_RIM_I=m
+# CONFIG_ARPD is not set
+CONFIG_ASK_IP_FIB_HASH=y
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+# CONFIG_ASYNC_RAID6_TEST is not set
+CONFIG_ASYNC_XOR=m
+CONFIG_ATA=m
+CONFIG_ATALK=m
+CONFIG_ATARI_PARTITION=y
+CONFIG_ATA_GENERIC=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_OVER_ETH=m
+CONFIG_ATA_PIIX=m
+CONFIG_ATA_SFF=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATL1=m
+# CONFIG_ATL1C is not set
+CONFIG_ATL1E=m
+CONFIG_ATL2=m
+CONFIG_ATM=y
+CONFIG_ATM_AMBASSADOR=m
+# CONFIG_ATM_AMBASSADOR_DEBUG is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_ATM_CLIP=y
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_FORE200E_TX_RETRY=16
+# CONFIG_ATM_FORE200E_USE_TASKLET is not set
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_SOLOS is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATP=m
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_GENERIC=y
+CONFIG_AUDIT_TREE=y
+CONFIG_AUFS_BDEV_LOOP=y
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+CONFIG_AUFS_BR_FUSE=y
+CONFIG_AUFS_BR_RAMFS=y
+# CONFIG_AUFS_DEBUG is not set
+# CONFIG_AUFS_EXPORT is not set
+CONFIG_AUFS_FS=m
+CONFIG_AUFS_HINOTIFY=y
+CONFIG_AUFS_POLL=y
+# CONFIG_AUFS_RDU is not set
+# CONFIG_AUFS_SHWH is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
+CONFIG_AUXDISPLAY=y
+CONFIG_AVERATEC_5100P=m
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_B44=m
+CONFIG_B44_PCI=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_PROGEAR=m
+# CONFIG_BACKLIGHT_SAHARA is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+CONFIG_BASE_FULL=y
+CONFIG_BASE_SMALL=0
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_BATTERY_DS2760=m
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+CONFIG_BATTERY_OLPC=m
+CONFIG_BAYCOM_EPP=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BE2NET is not set
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BEFS_FS=m
+CONFIG_BFS_FS=m
+CONFIG_BINARY_PRINTF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+CONFIG_BITREVERSE=y
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_COMPCACHE=m
+# CONFIG_BLK_DEV_COMPCACHE_DEBUG is not set
+# CONFIG_BLK_DEV_COMPCACHE_STATS is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_DM=y
+CONFIG_BLK_DEV_FD=m
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_BLOCK=y
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BNX2=m
+CONFIG_BNX2X=m
+CONFIG_BONDING=m
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BOUNCE=y
+CONFIG_BPQETHER=m
+CONFIG_BRANCH_PROFILE_NONE=y
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_BSD_DISKLABEL=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_BT=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_HIDP=m
+CONFIG_BT_L2CAP=m
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_SCO=m
+CONFIG_BUG=y
+# CONFIG_C2PORT is not set
+# CONFIG_CACHEFILES is not set
+# CONFIG_CAN is not set
+CONFIG_CARDBUS=y
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_CASSINI=m
+# CONFIG_CB710_CORE is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_MEM_RES_CTLR=y
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T3_DEPENDS=y
+CONFIG_CHR_DEV_OSST=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CICADA_PHY=m
+CONFIG_CIFS=m
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+# CONFIG_CIFS_XATTR is not set
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_CLS_U32_MARK=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_CNIC is not set
+CONFIG_CODA_FS=m
+CONFIG_COMPAT=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_COMPUTONE=m
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONNECTOR=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_CONSTRUCTORS=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_CPA_DEBUG is not set
+CONFIG_CPU5_WDT=m
+CONFIG_CPUSETS=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CRAMFS=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_DEV_GEODE=m
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_CRYPTO_DEV_PADLOCK=y
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_FPU=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SALSA20_586=m
+CONFIG_CRYPTO_SALSA20_X86_64=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_586=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_X86_64=m
+# CONFIG_CRYPTO_VMAC is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_XTS=m
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CS5535_GPIO=m
+# CONFIG_CUSE is not set
+CONFIG_CYCLADES=m
+CONFIG_CYCLADES_SYNC=m
+CONFIG_CYCLOMX_X25=y
+# CONFIG_CYZ_INTR is not set
+CONFIG_DAVICOM_PHY=m
+# CONFIG_DCB is not set
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_DE4X5=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_NX_TEST is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_NF_GRABULATOR=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZMA=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_CUBIC is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_HTCP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_DEFAULT_IO_DELAY_TYPE=1
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_SECURITY="apparmor"
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+# CONFIG_DEFAULT_SECURITY_DAC is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DEVKMEM is not set
+CONFIG_DEVPORT=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DEV_APPLETALK=m
+CONFIG_DIGIEPCA=m
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_DISPLAY_SUPPORT=m
+# CONFIG_DL2K is not set
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_DLM=y
+# CONFIG_DLM_DEBUG is not set
+CONFIG_DM9102=m
+# CONFIG_DMADEVICES is not set
+# CONFIG_DMA_API_DEBUG is not set
+CONFIG_DM_CRYPT=m
+# CONFIG_DM_DEBUG is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_MIRROR=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_QL is not set
+# CONFIG_DM_MULTIPATH_ST is not set
+CONFIG_DM_RAID45=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_ZERO=m
+# CONFIG_DNET is not set
+CONFIG_DNOTIFY=y
+CONFIG_DONGLE=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_DRM=m
+CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_TTM=m
+CONFIG_DRM_VIA=m
+CONFIG_DS1682=m
+CONFIG_DSCC4=m
+CONFIG_DSCC4_PCISYNC=y
+CONFIG_DSCC4_PCI_RST=y
+CONFIG_DUMMY=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_DYNAMIC_DEBUG is not set
+CONFIG_E100=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_ECRYPT_FS=m
+CONFIG_EDAC=y
+CONFIG_EDAC_AMD76X=m
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_E752X=m
+CONFIG_EDAC_E7XXX=m
+CONFIG_EDAC_I3000=m
+# CONFIG_EDAC_I3200 is not set
+CONFIG_EDAC_I5000=m
+CONFIG_EDAC_I5100=m
+# CONFIG_EDAC_I5400 is not set
+CONFIG_EDAC_I82860=m
+CONFIG_EDAC_I82875P=m
+CONFIG_EDAC_I82975X=m
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_EDAC_R82600=m
+# CONFIG_EDAC_X38 is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EFI_PARTITION=y
+CONFIG_EFS_FS=m
+CONFIG_ELF_CORE=y
+# CONFIG_EMBEDDED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENC28J60 is not set
+CONFIG_ENCLOSURE_SERVICES=m
+# CONFIG_ENIC is not set
+CONFIG_EPIC100=m
+CONFIG_EPOLL=y
+CONFIG_EQUALIZER=y
+CONFIG_ESI_DONGLE=m
+# CONFIG_ETHOC is not set
+CONFIG_EUROTECH_WDT=m
+CONFIG_EVENTFD=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_EXPORTFS=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_EZX_PCAP is not set
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_FARSYNC=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_FAT_FS=m
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_FB=y
+CONFIG_FB_3DFX=m
+# CONFIG_FB_3DFX_ACCEL is not set
+CONFIG_FB_3DFX_I2C=y
+CONFIG_FB_ARC=m
+CONFIG_FB_ARK=m
+CONFIG_FB_ASILIANT=y
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY128=m
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_BACKLIGHT=y
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_DDC=m
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_HECUBA=m
+CONFIG_FB_HGA=m
+# CONFIG_FB_HGA_ACCEL is not set
+CONFIG_FB_IMSTT=y
+CONFIG_FB_KYRO=m
+CONFIG_FB_LE80578=m
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_METRONOME is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_N411=m
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_PM3=m
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_BACKLIGHT=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_I2C=y
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_SM501=m
+CONFIG_FB_SVGALIB=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_TMIO is not set
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_UVESA=m
+# CONFIG_FB_VESA is not set
+CONFIG_FB_VGA16=m
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_VOODOO1=m
+CONFIG_FB_VT8623=m
+# CONFIG_FCOE is not set
+# CONFIG_FCOE_FNIC is not set
+CONFIG_FDDI=y
+CONFIG_FEALNX=m
+CONFIG_FIB_RULES=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_FIREWIRE is not set
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FLATMEM=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FORCEDETH=m
+# CONFIG_FORCEDETH_NAPI is not set
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FRAME_WARN=1024
+CONFIG_FREEZER=y
+CONFIG_FSAM7400=m
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_HISTOGRAM is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+# CONFIG_FSCACHE_STATS is not set
+CONFIG_FSNOTIFY=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FTL=m
+CONFIG_FTRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_FUNCTION_TRACER is not set
+CONFIG_FUSE_FS=m
+CONFIG_FUSION=y
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_LAN=m
+CONFIG_FUSION_LOGGING=y
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_SPI=m
+CONFIG_FUTEX=y
+CONFIG_FW_LOADER=y
+CONFIG_GACT_PROB=y
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GARP=m
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_GENERIC_ACL=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_GFS2_FS=y
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_LANGWELL is not set
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MAX732X=m
+# CONFIG_GPIO_MC33880 is not set
+CONFIG_GPIO_MCP23S08=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HAMACHI=m
+CONFIG_HAMRADIO=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_HAPPYMEAL=m
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_HDLC=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_X25=m
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_HFSPLUS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+# CONFIG_HID_3M_PCT is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_KYE=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_MOSART is not set
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+# CONFIG_HID_PID is not set
+# CONFIG_HID_QUANTA is not set
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_SONY=m
+# CONFIG_HID_STANTUM is not set
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HIPPI=y
+CONFIG_HOTPLUG=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_PCIE=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+CONFIG_HP100=m
+CONFIG_HPFS_FS=m
+CONFIG_HP_ILO=m
+# CONFIG_HP_WATCHDOG is not set
+CONFIG_HTC_PASIC3=m
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_HWMON_VID=m
+CONFIG_HW_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_INTEL=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HZ=100
+CONFIG_HZ_100=y
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_I2C=m
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_COMPAT=y
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+CONFIG_I2C_GPIO=m
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2O=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_BUS=m
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_PROC=m
+CONFIG_I2O_SCSI=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_I82092=m
+CONFIG_I8K=m
+# CONFIG_IA32_AOUT is not set
+CONFIG_IA32_EMULATION=y
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_IBMLS=m
+CONFIG_IBMOL=m
+CONFIG_IBM_ASM=m
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+CONFIG_ICPLUS_PHY=m
+# CONFIG_ICS932S401 is not set
+# CONFIG_IDE is not set
+CONFIG_IEEE1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
+CONFIG_IEEE1394_OHCI1394=m
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_IEEE1394_VIDEO1394=m
+# CONFIG_IEEE802154 is not set
+CONFIG_IFB=y
+CONFIG_IGB=m
+# CONFIG_IGBVF is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INET=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET_AH=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_LRO=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_AMSO1100=m
+CONFIG_INFINIBAND_AMSO1100_DEBUG=y
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_IPATH=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_CM=y
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_ISER=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_NES is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFTL=m
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_INPUT=y
+# CONFIG_INPUT_APANEL is not set
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_EVBUG=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_POLLDEV=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_TABLET=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_YEALINK=m
+# CONFIG_IOMMU_API is not set
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IO_DELAY_0X80 is not set
+CONFIG_IO_DELAY_0XED=y
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+# CONFIG_IO_DELAY_UDELAY is not set
+CONFIG_IP1000=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IPC_NS=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_DECAP=y
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_POWEROFF=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPV6=m
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_IPV6_MROUTE is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SUBTREES is not set
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPWIRELESS=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_DCCP=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_DCCP_TFRC_LIB=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_IP_PNP is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_SCTP=m
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_FTP=m
+# CONFIG_IP_VS_IPV6 is not set
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_TAB_BITS=12
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA=m
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_DEBUG=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+# CONFIG_IRQSOFF_TRACER is not set
+CONFIG_IRQ_PER_CPU=y
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_IRTTY_SIR=m
+CONFIG_ISA_DMA_API=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_ISDN is not set
+# CONFIG_ISI is not set
+# CONFIG_ISL29003 is not set
+CONFIG_ISO9660_FS=m
+# CONFIG_ISTALLION is not set
+CONFIG_IT8712F_WDT=m
+# CONFIG_IT87_WDT is not set
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_ITCO_WDT=m
+CONFIG_IXGB=m
+CONFIG_IXGBE=m
+CONFIG_JBD=y
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_FS=y
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+# CONFIG_JME is not set
+CONFIG_JOLIET=y
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_K8_NB=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_KARMA_PARTITION=y
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_LKKBD=m
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+CONFIG_KEYBOARD_NEWTON=m
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+CONFIG_KINGSUN_DONGLE=m
+# CONFIG_KMEMCHECK is not set
+# CONFIG_KMEMTRACE is not set
+CONFIG_KPROBES=y
+# CONFIG_KPROBES_SANITY_TEST is not set
+CONFIG_KRETPROBES=y
+CONFIG_KS0108=m
+CONFIG_KS0108_DELAY=2
+CONFIG_KS0108_PORT=0x378
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+CONFIG_KS959_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+# CONFIG_KSM is not set
+CONFIG_LANMEDIA=m
+CONFIG_LAPB=m
+CONFIG_LAPBETHER=m
+CONFIG_LATENCYTOP=y
+CONFIG_LBDAF=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_ILI9320=m
+# CONFIG_LCD_LMS283GF05 is not set
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_PLATFORM=m
+# CONFIG_LCD_TDO24M is not set
+CONFIG_LCD_VGG2432A4=m
+# CONFIG_LDM_DEBUG is not set
+CONFIG_LDM_PARTITION=y
+# CONFIG_LEDS_ALIX2 is not set
+# CONFIG_LEDS_BD2802 is not set
+CONFIG_LEDS_CLASS=m
+# CONFIG_LEDS_DAC124S085 is not set
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+CONFIG_LEDS_NET48XX=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_WRAP=m
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LIB80211 is not set
+CONFIG_LIBCRC32C=m
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+CONFIG_LIRC_ATIUSB=m
+CONFIG_LIRC_BT829=m
+CONFIG_LIRC_CONFIG_LIRC_WPC8769L=m
+CONFIG_LIRC_DEV=m
+# CONFIG_LIRC_ENE0100 is not set
+# CONFIG_LIRC_GPIO is not set
+CONFIG_LIRC_I2C=m
+CONFIG_LIRC_IGORPLUGUSB=m
+CONFIG_LIRC_IMON=m
+CONFIG_LIRC_IT87=m
+CONFIG_LIRC_ITE8709=m
+CONFIG_LIRC_MCEUSB=m
+# CONFIG_LIRC_PARALLEL is not set
+CONFIG_LIRC_SASEM=m
+CONFIG_LIRC_SERIAL=m
+CONFIG_LIRC_SIR=m
+CONFIG_LIRC_STREAMZAP=m
+CONFIG_LIRC_TTUSBIR=m
+CONFIG_LITELINK_DONGLE=m
+# CONFIG_LKDTM is not set
+CONFIG_LLC=y
+CONFIG_LLC2=m
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_LOCKD_V4=y
+CONFIG_LOCK_KERNEL=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGO is not set
+CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_LSM_MMAP_MIN_ADDR=0
+CONFIG_LXT_PHY=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M586TSC is not set
+CONFIG_MA600_DONGLE=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MACHZ_WDT=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_MACVLAN=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MARVELL_PHY=m
+# CONFIG_MATOM is not set
+# CONFIG_MAXSMP is not set
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_MCORE2 is not set
+CONFIG_MCP2120_DONGLE=m
+# CONFIG_MCRUSOE is not set
+CONFIG_MCS_FIR=m
+# CONFIG_MCYRIXIII is not set
+CONFIG_MD=y
+CONFIG_MDIO=m
+CONFIG_MDIO_BITBANG=m
+# CONFIG_MDIO_GPIO is not set
+CONFIG_MD_FAULTY=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID6_PQ=m
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_MEFFICEON is not set
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_SAS=m
+# CONFIG_MEMSTICK is not set
+CONFIG_MFD_CORE=m
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_MFD_PCF50633 is not set
+CONFIG_MFD_SM501=m
+# CONFIG_MFD_SM501_GPIO is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+CONFIG_MII=m
+CONFIG_MINIX_FS=m
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_MISC_DEVICES=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+CONFIG_MKISS=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+# CONFIG_MLX4_EN is not set
+CONFIG_MLX4_INFINIBAND=m
+# CONFIG_MMC is not set
+CONFIG_MMU=y
+CONFIG_MM_OWNER=y
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_GPIO=m
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+# CONFIG_MOUSE_PS2_OLPC is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_SERIAL=m
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPSC is not set
+CONFIG_MSDOS_FS=m
+CONFIG_MSDOS_PARTITION=y
+CONFIG_MTD=m
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTD_ABSENT=m
+CONFIG_MTD_ALAUDA=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_AR7_PARTS=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK2MTD=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_OTP is not set
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_INTEL_VR_NOR=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_L440GX=m
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_M25P80=m
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_CAFE=m
+# CONFIG_MTD_NAND_CS553X is not set
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_ONENAND=m
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+# CONFIG_MTD_ONENAND_OTP is not set
+CONFIG_MTD_ONENAND_SIM=m
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+CONFIG_MTD_OOPS=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_PCI=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+CONFIG_MTD_PLATRAM=m
+CONFIG_MTD_PMC551=m
+# CONFIG_MTD_PMC551_BUGFIX is not set
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_RAM=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+CONFIG_MTD_REDBOOT_PARTS=m
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+CONFIG_MTD_ROM=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+CONFIG_MTD_SLRAM=m
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_MTD_UBI_GLUEBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+# CONFIG_MULTICORE_RAID456 is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+CONFIG_MWAVE=m
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MWINCHIPC6 is not set
+CONFIG_MYRI10GE=m
+CONFIG_NAMESPACES=y
+# CONFIG_NATIONAL_PHY is not set
+CONFIG_NATSEMI=m
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_PACKET_SIGNING=y
+# CONFIG_NCPFS_SMALLDOS is not set
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCP_FS=m
+CONFIG_NDISWRAPPER=m
+CONFIG_NE2K_PCI=m
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_NET=y
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETDEVICES=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETLABEL=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NETROM=m
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_NET_9P_RDMA is not set
+CONFIG_NET_ACT_GACT=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_SIMP=m
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_BASIC=m
+# CONFIG_NET_CLS_CGROUP is not set
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_CLS_FW=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_DCCPPROBE=m
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_NET_DSA is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_ETHERNET=y
+CONFIG_NET_FC=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_NET_NS=y
+CONFIG_NET_PCI=y
+CONFIG_NET_PCMCIA=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_POCKET=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_CBQ=m
+# CONFIG_NET_SCH_DRR is not set
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_FIFO=y
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_INGRESS=m
+# CONFIG_NET_SCH_MULTIQ is not set
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_TCPPROBE=m
+CONFIG_NET_TULIP=y
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_NEW_LEDS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_NFS_FS=m
+# CONFIG_NFS_FSCACHE is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_CONNTRACK_SANE is not set
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NILFS2_FS is not set
+CONFIG_NIU=m
+# CONFIG_NL80211_TESTMODE is not set
+CONFIG_NLATTR=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_CODEPAGE_437=m
+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_874=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=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_8=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_NOHIGHMEM is not set
+CONFIG_NOP_TRACER=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_NOZOMI=m
+CONFIG_NO_IDLE_HZ=y
+CONFIG_NR_CPUS=64
+CONFIG_NS83820=m
+CONFIG_NSC_FIR=m
+CONFIG_NSC_GPIO=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_RW is not set
+CONFIG_NVRAM=m
+CONFIG_N_HDLC=m
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_POSIX_ACL=y
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_OLPC=y
+CONFIG_OMFS_FS=m
+CONFIG_OMNIBOOK=m
+CONFIG_OPROFILE=m
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_OPTIMIZE_INLINING=y
+CONFIG_OSF_PARTITION=y
+CONFIG_PACKARDBELL_E5=m
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_PARIDE=m
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PG=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARPORT=m
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_AX88796=m
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_SERIAL=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD640_PCI is not set
+CONFIG_PATA_CMD64X=m
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+CONFIG_PATA_CS5535=m
+CONFIG_PATA_CS5536=m
+# CONFIG_PATA_CYPRESS is not set
+CONFIG_PATA_EFAR=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+# CONFIG_PATA_HPT3X2N is not set
+CONFIG_PATA_HPT3X3=m
+# CONFIG_PATA_HPT3X3_DMA is not set
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_NS87415=m
+CONFIG_PATA_OLDPIIX=m
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_PDC_OLD=m
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+CONFIG_PATA_RZ1000=m
+# CONFIG_PATA_SC1200 is not set
+CONFIG_PATA_SCH=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+# CONFIG_PC300TOO is not set
+CONFIG_PC8736x_GPIO=m
+CONFIG_PC87413_WDT=m
+CONFIG_PCCARD=m
+CONFIG_PCCARD_NONSTATIC=m
+CONFIG_PCI=y
+CONFIG_PCI200SYN=m
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIEASPM is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIPCWATCHDOG=m
+# CONFIG_PCI_DEBUG is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_GOANY is not set
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GOOLPC is not set
+CONFIG_PCI_GOXEN_FE=y
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_LEGACY=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_STUB is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_AXNET=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_IBMTR=m
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_PCNET32=m
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_PD6729=m
+CONFIG_PDA_POWER=m
+CONFIG_PDC_ADMA=m
+CONFIG_PHANTOM=m
+# CONFIG_PHONET is not set
+# CONFIG_PHONE_IXJ is not set
+CONFIG_PHYLIB=y
+CONFIG_PHYSICAL_ALIGN=0x2000
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PID_NS=y
+CONFIG_PLIP=m
+CONFIG_PM=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_POWER_TRACER is not set
+CONFIG_PPDEV=m
+CONFIG_PPP=y
+CONFIG_PPPOATM=m
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_PPS is not set
+# CONFIG_PRECACHE is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PRESWAP is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_PRINTER=m
+CONFIG_PRINTK=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_PROC_EVENTS=y
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+CONFIG_PROFILING=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_PSS_HAVE_BOOT is not set
+CONFIG_PSS_MIXER=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QLA3XXX=m
+# CONFIG_QLGE is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_QSEMI_PHY=m
+# CONFIG_QT2160 is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=m
+CONFIG_R3964=m
+# CONFIG_R6040 is not set
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_RAID_ATTRS=m
+CONFIG_RAW_DRIVER=m
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RDS is not set
+CONFIG_RD_BZIP2=y
+CONFIG_RD_GZIP=y
+CONFIG_RD_LZMA=y
+# CONFIG_REALTEK_PHY is not set
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+# CONFIG_REGULATOR is not set
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_FS=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_RELAY=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_RFD_FTL=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_LEDS=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+CONFIG_RISCOM8=m
+CONFIG_ROADRUNNER=m
+# CONFIG_ROADRUNNER_LARGE_RINGS is not set
+CONFIG_ROCKETPORT=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_ON_BLOCK=y
+CONFIG_ROSE=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DEBUG is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS1742=m
+# CONFIG_RTC_DRV_DS3234 is not set
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_M41T94=m
+# CONFIG_RTC_DRV_M48T35 is not set
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_MAX6902=m
+# CONFIG_RTC_DRV_PCF2123 is not set
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+# CONFIG_RTC_DRV_R9701 is not set
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_RS5C372=m
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_TEST=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_LIB=y
+CONFIG_RTL8192SE=m
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_RXKAD=m
+CONFIG_S2IO=m
+# CONFIG_SAMPLES is not set
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_INIC162X=m
+CONFIG_SATA_MV=m
+CONFIG_SATA_NV=m
+CONFIG_SATA_PMP=y
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIL24=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_SX4=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+CONFIG_SBC7240_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+# CONFIG_SBC_FITPC2_WATCHDOG is not set
+CONFIG_SBNI=m
+# CONFIG_SBNI_MULTILINE is not set
+CONFIG_SC1200_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_SC6600=y
+CONFIG_SC6600_CDROM=4
+CONFIG_SC6600_CDROMBASE=0
+CONFIG_SC6600_JOY=y
+CONFIG_SC92031=m
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_SCHED_TRACER is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_SCSI_AIC7XXX=m
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+CONFIG_SCSI_AIC94XX=m
+CONFIG_SCSI_ARCMSR=m
+CONFIG_SCSI_ARCMSR_AER=y
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_EATA=m
+CONFIG_SCSI_EATA_LINKED_COMMANDS=y
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_EATA_TAGGED_QUEUE=y
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_TGT_ATTRS=y
+# CONFIG_SCSI_FLASHPOINT is not set
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_IMM=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_IPR=m
+# CONFIG_SCSI_IPR_DUMP is not set
+# CONFIG_SCSI_IPR_TRACE is not set
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_ISCSITARGET=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_MVSAS is not set
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_NSP32=m
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_SCSI_PMCRAID is not set
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_PROC_FS=y
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_SRP=m
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCx200=m
+CONFIG_SCx200HR_TIMER=m
+CONFIG_SCx200_ACB=m
+CONFIG_SCx200_GPIO=m
+CONFIG_SCx200_I2C=m
+CONFIG_SCx200_I2C_SCL=12
+CONFIG_SCx200_I2C_SDA=13
+CONFIG_SCx200_WDT=m
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_APPARMOR_COMPAT_24=y
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_PATH=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_DISABLE=y
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADS7828=m
+# CONFIG_SENSORS_ADT7462 is not set
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7473=m
+# CONFIG_SENSORS_ADT7475 is not set
+CONFIG_SENSORS_APPLESMC=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHMD=m
+# CONFIG_SENSORS_G760A is not set
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_HDAPS=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_K8TEMP=m
+# CONFIG_SENSORS_LIS3_SPI is not set
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_SENSORS_SHT15 is not set
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_THMC50=m
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_NR_UARTS=48
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_SERIO=y
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+# CONFIG_SFC_RESOURCE is not set
+CONFIG_SGI_IOC4=m
+CONFIG_SGI_PARTITION=y
+CONFIG_SHMEM=y
+CONFIG_SIGMATEL_FIR=m
+CONFIG_SIGNALFD=y
+CONFIG_SIS190=m
+CONFIG_SIS900=m
+CONFIG_SKFP=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_SLAB=y
+CONFIG_SLABINFO=y
+CONFIG_SLHC=y
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLOB is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_SLOW_WORK_DEBUG is not set
+# CONFIG_SLUB is not set
+# CONFIG_SMARTJOYPLUS_FF is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_SMP=y
+CONFIG_SMSC37B787_WDT=m
+# CONFIG_SMSC9420 is not set
+CONFIG_SMSC_PHY=m
+# CONFIG_SMSC_SCH311X_WDT is not set
+CONFIG_SND=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+# CONFIG_SND_CTXFI is not set
+CONFIG_SND_DARLA20=m
+CONFIG_SND_DARLA24=m
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=m
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_EMU10K1_SEQ=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_ATIHDMI=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_INTELHDMI=y
+CONFIG_SND_HDA_CODEC_NVHDMI=y
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_ELD=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_HWDEP is not set
+# CONFIG_SND_HDA_INPUT_BEEP is not set
+# CONFIG_SND_HDA_INPUT_JACK is not set
+CONFIG_SND_HDA_INTEL=m
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_POWER_SAVE=y
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGODJ=m
+# CONFIG_SND_INDIGODJX is not set
+CONFIG_SND_INDIGOIO=m
+# CONFIG_SND_INDIGOIOX is not set
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_JACK=y
+CONFIG_SND_KORG1212=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_LAYLA24=m
+# CONFIG_SND_LX6464ES is not set
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIA=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_NM256=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL3_LIB_SEQ=m
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_PCI=y
+CONFIG_SND_PCM=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCXHR=m
+CONFIG_SND_PDAUDIOCF=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_RAWMIDI_SEQ=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SB16_DSP=m
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_SIS7019=m
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_SPI=y
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_TIMER=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+# CONFIG_SND_USB_US122L is not set
+CONFIG_SND_USB_USX2Y=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VMASTER=y
+CONFIG_SND_VX222=m
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_SONYPI=m
+CONFIG_SOUND=m
+CONFIG_SOUND_AEDSP16=m
+CONFIG_SOUND_DMAP=y
+CONFIG_SOUND_KAHLUA=m
+CONFIG_SOUND_MPU401=m
+CONFIG_SOUND_MSS=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SOUND_PAS=m
+CONFIG_SOUND_PRIME=m
+CONFIG_SOUND_PSS=m
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_SSCAPE=m
+# CONFIG_SOUND_TRACEINIT is not set
+CONFIG_SOUND_TRIX=m
+CONFIG_SOUND_UART6850=m
+CONFIG_SOUND_VMIDI=m
+CONFIG_SOUND_YM3812=m
+# CONFIG_SPARSEMEM_MANUAL is not set
+# CONFIG_SPARSE_IRQ is not set
+CONFIG_SPECIALIX=m
+CONFIG_SPI=y
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_BUTTERFLY=m
+# CONFIG_SPI_DEBUG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_LM70_LLP=m
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_SQUASHFS is not set
+CONFIG_SR_REPORT_TIME_LIMIT=100
+CONFIG_SSB=m
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+# CONFIG_SSB_PCMCIAHOST is not set
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB_SPROM=y
+CONFIG_SSFDC=m
+CONFIG_STACKTRACE=y
+CONFIG_STACKTRACE_SUPPORT=y
+# CONFIG_STACK_TRACER is not set
+# CONFIG_STAGING is not set
+CONFIG_STALDRV=y
+# CONFIG_STALLION is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_STE10XP is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_STP=m
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_SUNGEM=m
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_XPRT_RDMA=m
+CONFIG_SUN_PARTITION=y
+CONFIG_SWAP=y
+CONFIG_SWIOTLB=y
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_CS=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_SYN_COOKIES=y
+CONFIG_SYSCTL=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_SYSFS=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_SYSPROF_TRACER is not set
+CONFIG_SYSV68_PARTITION=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_SYSV_FS=m
+CONFIG_SYS_HYPERVISOR=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_WACOM=m
+CONFIG_TASKSTATS=y
+# CONFIG_TASK_DELAY_ACCT is not set
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_TASK_XACCT=y
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_TPM=m
+# CONFIG_TCG_XEN is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_MD5SIG=y
+CONFIG_TEHUTI=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TELCLOCK=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+# CONFIG_THRUSTMASTER_FF is not set
+CONFIG_TIFM_7XX1=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIGON3=m
+CONFIG_TIMERFD=y
+CONFIG_TIMER_STATS=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_TLAN=m
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+# CONFIG_TOIM3232_DONGLE is not set
+# CONFIG_TOSHIBA is not set
+CONFIG_TOSHIBA_FIR=m
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+CONFIG_TOUCHSCREEN_ADS7846=m
+# CONFIG_TOUCHSCREEN_EETI is not set
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TPS65010=m
+CONFIG_TR=y
+CONFIG_TRACEPOINTS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_NAPI is not set
+CONFIG_TUN=y
+CONFIG_TYPHOON=m
+CONFIG_UBIFS_FS=m
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UCB1400_CORE is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UFS_DEBUG is not set
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+CONFIG_UID16=y
+CONFIG_UIO=m
+# CONFIG_UIO_AEC is not set
+CONFIG_UIO_CIF=m
+# CONFIG_UIO_PCI_GENERIC is not set
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_UIO_SMX=m
+CONFIG_ULI526X=m
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_UNIX=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_USB=m
+CONFIG_USBPCWATCHDOG=m
+CONFIG_USB_ACM=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_ATM=m
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_CATC=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_DUMMY_HCD=m
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EMI26=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_ETH=m
+# CONFIG_USB_ETH_EEM is not set
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_EZUSB=y
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_GADGET=m
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_GADGET_DUMMY_HCD=y
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_HID=m
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_HSO=m
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_IRDA=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_ISP116X_HCD=m
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_KC2190=y
+CONFIG_USB_LCD=m
+CONFIG_USB_LD=m
+CONFIG_USB_LED=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_MON=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+# CONFIG_USB_NET_INT51X1 is not set
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_RNDIS_HOST=m
+# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_SSB is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+# CONFIG_USB_SERIAL_CP210X is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IPW=m
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_IUU is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_OPTICON is not set
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+# CONFIG_USB_SERIAL_SYMBOL is not set
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SEVSEG is not set
+CONFIG_USB_SISUSBVGA=m
+# CONFIG_USB_SISUSBVGA_CON is not set
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_ALAUDA=m
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_KARMA=m
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_TMC is not set
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_USS720=m
+# CONFIG_USB_VST is not set
+CONFIG_USB_WDM=m
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_ZERO=m
+# CONFIG_USER_NS is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_UTS_NS=y
+# CONFIG_UWB is not set
+CONFIG_VERSION_SIGNATURE=""
+CONFIG_VETH=m
+CONFIG_VFAT_FS=m
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_VGASTATE=m
+CONFIG_VGA_ARB=y
+CONFIG_VGA_CONSOLE=y
+CONFIG_VIA_FIR=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_VELOCITY=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_VIRT_TO_BUS=y
+CONFIG_VITESSE_PHY=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLSI_FIR=m
+CONFIG_VM86=y
+# CONFIG_VMWARE_PVSCSI is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_VORTEX=m
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_VXFS_FS=m
+# CONFIG_VXGE is not set
+CONFIG_W1=y
+CONFIG_W1_CON=y
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_MASTER_MATROX=m
+# CONFIG_W1_SLAVE_BQ27000 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+# CONFIG_W83697UG_WDT is not set
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_WAFER_WDT=m
+CONFIG_WAN=y
+CONFIG_WANXL=m
+CONFIG_WAN_ROUTER=m
+CONFIG_WAN_ROUTER_DRIVERS=m
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_WDTPCI=m
+# CONFIG_WIMAX is not set
+CONFIG_WINBOND_840=m
+CONFIG_WINBOND_FIR=m
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WLAN=y
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_X25=m
+CONFIG_X25_ASY=m
+CONFIG_X86=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_64_XEN=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CPU=y
+CONFIG_X86_CPUID=m
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_X86_GENERIC=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_INTERNODE_CACHE_BYTES=64
+CONFIG_X86_INVLPG=y
+CONFIG_X86_L1_CACHE_BYTES=64
+CONFIG_X86_MSR=m
+CONFIG_X86_NO_IDT=y
+CONFIG_X86_NO_TSS=y
+CONFIG_X86_PAE=y
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_PPRO_FENCE=y
+# CONFIG_X86_PTDUMP is not set
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_XADD=y
+CONFIG_X86_XEN=y
+CONFIG_XEN=y
+# CONFIG_XEN_BACKEND is not set
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_COMPAT=0x030002
+CONFIG_XEN_COMPAT_030002_AND_LATER=y
+# CONFIG_XEN_COMPAT_030004_AND_LATER is not set
+# CONFIG_XEN_COMPAT_030100_AND_LATER is not set
+# CONFIG_XEN_COMPAT_030200_AND_LATER is not set
+# CONFIG_XEN_COMPAT_030300_AND_LATER is not set
+# CONFIG_XEN_COMPAT_030400_AND_LATER is not set
+# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
+CONFIG_XEN_DEVMEM=y
+# CONFIG_XEN_DISABLE_SERIAL is not set
+CONFIG_XEN_FRAMEBUFFER=y
+# CONFIG_XEN_GRANT_DEV is not set
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
+CONFIG_XEN_KEYBOARD=y
+CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND=y
+CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_NR_GUEST_DEVICES=16
+# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
+CONFIG_XEN_PCIDEV_FRONTEND=y
+CONFIG_XEN_PRIVCMD=y
+# CONFIG_XEN_PRIVILEGED_GUEST is not set
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_SMPBOOT=y
+CONFIG_XEN_SYSFS=y
+CONFIG_XEN_UNPRIVILEGED_GUEST=y
+CONFIG_XEN_USB_FRONTEND=m
+# CONFIG_XEN_USB_FRONTEND_HCD_PM is not set
+CONFIG_XEN_USB_FRONTEND_HCD_STATS=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XFRM=y
+CONFIG_XFRM_IPCOMP=m
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_USER=m
+# CONFIG_XFS_DEBUG is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_RT=y
+CONFIG_XOR_BLOCKS=m
+CONFIG_YAM=m
+CONFIG_YELLOWFIN=m
+CONFIG_YENTA=m
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_TOSHIBA=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_ZISOFS=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA=y
+CONFIG_ZONE_DMA_FLAG=1
--- linux-ec2-2.6.32.orig/debian.ec2/config/i386/config.flavour.ec2
+++ linux-ec2-2.6.32/debian.ec2/config/i386/config.flavour.ec2
@@ -0,0 +1,3 @@
+#
+# Config options for config.flavour.ec2 automatically generated by splitconfig.pl
+#
--- linux-ec2-2.6.32.orig/debian.ec2/config/i386/config.common.i386
+++ linux-ec2-2.6.32/debian.ec2/config/i386/config.common.i386
@@ -0,0 +1,31 @@
+#
+# Config options for config.common.i386 automatically generated by splitconfig.pl
+#
+# CONFIG_64BIT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=2000
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_ASYNC_TX_DMA=y
+# CONFIG_AUDIT_ARCH is not set
+# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set
+# CONFIG_DRM_RADEON_KMS is not set
+# CONFIG_FSCACHE is not set
+# CONFIG_GENERIC_CPU is not set
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_KTIME_SCALAR=y
+CONFIG_M686=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+# CONFIG_PHONE is not set
+CONFIG_PHYSICAL_START=0x100000
+CONFIG_RCU_FANOUT=32
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_X86_32=y
+# CONFIG_X86_64 is not set
+# CONFIG_X86_CPU_DEBUG is not set
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+CONFIG_X86_SPEEDSTEP_LIB=y
+# CONFIG_ZONE_DMA32 is not set
--- linux-ec2-2.6.32.orig/debian.ec2/config/amd64/config.common.amd64
+++ linux-ec2-2.6.32/debian.ec2/config/amd64/config.common.amd64
@@ -0,0 +1,31 @@
+#
+# Config options for config.common.amd64 automatically generated by splitconfig.pl
+#
+CONFIG_64BIT=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+CONFIG_DRM_RADEON_KMS=y
+CONFIG_FSCACHE=m
+CONFIG_GENERIC_CPU=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+# CONFIG_HAVE_AOUT is not set
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+# CONFIG_KTIME_SCALAR is not set
+# CONFIG_M686 is not set
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_PHONE=m
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RCU_FANOUT=64
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86_CPU_DEBUG=m
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_ZONE_DMA32=y
--- linux-ec2-2.6.32.orig/debian.ec2/config/amd64/config.flavour.ec2
+++ linux-ec2-2.6.32/debian.ec2/config/amd64/config.flavour.ec2
@@ -0,0 +1,3 @@
+#
+# Config options for config.flavour.ec2 automatically generated by splitconfig.pl
+#
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/kernel-versions
+++ linux-ec2-2.6.32/debian.ec2/d-i/kernel-versions
@@ -0,0 +1,4 @@
+# arch	version		flavour		installedname			suffix	bdep
+#amd64	2.6.32-317	ec2		2.6.32-317-ec2		-	
+
+#i386	2.6.32-317	ec2		2.6.32-317-ec2		-	
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/package-list
+++ linux-ec2-2.6.32/debian.ec2/d-i/package-list
@@ -0,0 +1,177 @@
+Package: kernel-image
+
+Package: char-modules
+Depends: kernel-image
+Priority: standard
+Description: Character module support
+
+Package: fat-modules
+Depends: kernel-image
+Priority: standard
+Description: FAT filesystem support
+ This includes Windows FAT and VFAT support.
+
+Package: fb-modules
+Depends: kernel-image
+Priority: standard
+Description: Framebuffer modules
+
+Package: firewire-core-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Firewire (IEEE-1394) Support
+
+Package: floppy-modules
+Depends: kernel-image
+Priority: standard
+Description: Floppy driver support
+
+Package: fs-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: jfs-modules, reiserfs-modules, xfs-modules
+Description: Base filesystem modules
+ This includes jfs, reiserfs and xfs.
+
+Package: fs-secondary-modules
+Depends: kernel-image, fat-modules
+Priority: standard
+Provides: ntfs-modules, hfs-modules
+Description: Extra filesystem modules
+ This includes support for Windows NTFS and MacOS HFS/HFSPlus
+
+Package: input-modules
+Depends: kernel-image, usb-modules
+Priority: standard
+Description: Support for various input methods
+
+Package: irda-modules
+Depends: kernel-image, nic-shared-modules
+Priority: standard
+Description: Support for Infrared protocols
+
+Package: md-modules
+Depends: kernel-image
+Priority: standard
+Description: Multi-device support (raid, device-mapper, lvm)
+
+Package: nic-modules
+Depends: kernel-image, nic-shared-modules, virtio-modules
+Priority: standard
+Description: Network interface support
+
+Package: nic-pcmcia-modules
+Depends: kernel-image, nic-shared-modules, nic-modules
+Priority: standard
+Description: PCMCIA network interface support
+
+Package: nic-usb-modules
+Depends: kernel-image, nic-shared-modules, usb-modules
+Priority: standard
+Description: USB network interface support
+
+Package: nic-shared-modules
+Depends: kernel-image, crypto-modules
+Priority: standard
+Description: nic shared modules
+  This package contains modules which support nic modules
+
+Package: parport-modules
+Depends: kernel-image
+Priority: standard
+Description: Parallel port support
+
+Package: pata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: PATA support modules
+
+Package: pcmcia-modules
+Depends: kernel-image
+Priority: standard
+Description: PCMCIA Modules
+
+Package: pcmcia-storage-modules
+Depends: kernel-image, scsi-modules
+Priority: standard
+Description: PCMCIA storage support
+
+Package: plip-modules
+Depends: kernel-image, nic-shared-modules, parport-modules
+Priority: standard
+Description: PLIP (parallel port) networking support
+
+Package: ppp-modules
+Depends: kernel-image, nic-shared-modules, serial-modules
+Priority: standard
+Description: PPP (serial port) networking support
+
+Package: sata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SATA storage support
+
+Package: scsi-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SCSI storage support
+
+Package: serial-modules
+Depends: kernel-image
+Priority: standard
+Description: Serial port support
+
+Package: storage-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: loop-modules
+Description: Core storage support
+ Includes core SCSI, LibATA, USB-Storage. Also includes related block
+ devices for CD, Disk and Tape medium (and IDE Floppy).
+
+Package: usb-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Core USB support
+
+Package: nfs-modules
+Priority: standard
+Depends: kernel-image
+Description: NFS filesystem drivers
+ Includes the NFS client driver, and supporting modules.
+
+Package: block-modules
+Priority: standard
+Depends: kernel-image, storage-core-modules, parport-modules, virtio-modules
+Description: Block storage devices
+ This package contains the block storage devices, including DAC960 and
+ paraide.
+
+Package: message-modules
+Priority: standard
+Depends: kernel-image, storage-core-modules, scsi-modules
+Description: Fusion and i2o storage modules
+ This package containes the fusion and i2o storage modules.
+
+Package: crypto-modules
+Priority: extra
+Depends: kernel-image
+Description: crypto modules
+ This package contains crypto modules.
+
+Package: virtio-modules
+Priority: standard
+Depends: kernel-image
+Description: VirtIO Modules
+ Includes modules for VirtIO (virtual machine, generally kvm guests)
+
+Package: socket-modules
+Depends: kernel-image
+Priority: standard
+Description: Unix socket support
+
+Package: mouse-modules
+Depends: kernel-image, input-modules, usb-modules
+Priority: extra
+Description: Mouse support
+ This package contains mouse drivers for the Linux kernel.
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/exclude-modules.powerpc
+++ linux-ec2-2.6.32/debian.ec2/d-i/exclude-modules.powerpc
@@ -0,0 +1,5 @@
+efi-modules
+fb-modules
+acpi-modules
+virtio-modules
+char-modules
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/kernel-versions.in
+++ linux-ec2-2.6.32/debian.ec2/d-i/kernel-versions.in
@@ -0,0 +1,4 @@
+# arch	version		flavour		installedname			suffix	bdep
+#amd64	PKGVER-ABINUM	ec2		PKGVER-ABINUM-ec2		-	
+
+#i386	PKGVER-ABINUM	ec2		PKGVER-ABINUM-ec2		-	
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/exclude-modules.sparc
+++ linux-ec2-2.6.32/debian.ec2/d-i/exclude-modules.sparc
@@ -0,0 +1,10 @@
+efi-modules
+nic-pcmcia-modules
+pcmcia-modules
+pcmcia-storage-modules
+irda-modules
+floppy-modules
+fb-modules
+acpi-modules
+virtio-modules
+char-modules
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/exclude-modules.ia64
+++ linux-ec2-2.6.32/debian.ec2/d-i/exclude-modules.ia64
@@ -0,0 +1,5 @@
+irda-modules
+floppy-modules
+fb-modules
+virtio-modules
+char-modules
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/firmware/nic-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/firmware/nic-modules
@@ -0,0 +1,6 @@
+bnx2/bnx2-mips-06-4.6.16.fw ?
+bnx2/bnx2-mips-09-4.6.17.fw ?
+bnx2/bnx2-rv2p-06-4.6.16.fw ?
+bnx2/bnx2-rv2p-09-4.6.15.fw ?
+bnx2x-e1-4.8.53.0.fw ?
+bnx2x-e1h-4.8.53.0.fw ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/firmware/README.txt
+++ linux-ec2-2.6.32/debian.ec2/d-i/firmware/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/fs-secondary-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/fs-secondary-modules
@@ -0,0 +1,4 @@
+fuse ?
+ntfs ?
+hfs ?
+hfsplus ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/ppp-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/ppp-modules
@@ -0,0 +1,6 @@
+ppp_async
+ppp_deflate
+ppp_mppe
+pppoe
+pppox
+ppp_synctty
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/md-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/md-modules
@@ -0,0 +1,13 @@
+dm-crypt
+dm-zero
+faulty
+linear
+multipath
+raid0
+raid1
+raid10
+raid456
+
+# Extras
+dm-raid4-5 ?
+dm-loop ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/fb-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/fb-modules
@@ -0,0 +1,3 @@
+fbcon
+vesafb
+vga16fb
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/storage-core-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/storage-core-modules
@@ -0,0 +1,10 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+
+# Loop modules
+cryptoloop
+
+# Needs to be here for better cdrom initrd layout
+isofs
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/nic-shared-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/nic-shared-modules
@@ -0,0 +1,22 @@
+# PHY
+8390
+mii
+
+# CRC modules
+crc-ccitt
+crc-itu-t
+libcrc32c
+
+# mac80211 stuff
+mac80211
+cfg80211
+
+# rt2x00 lib (since rt2x00 is split across usb/pci/cb
+rt2x00lib
+
+# Wireless 802.11 modules
+lib80211
+cfg80211
+lib80211_crypt_ccmp
+lib80211_crypt_tkip
+lib80211_crypt_wep
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/char-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/char-modules
@@ -0,0 +1 @@
+intel-agp
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/mouse-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/mouse-modules
@@ -0,0 +1,2 @@
+psmouse
+usbmouse ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/message-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/message-modules
@@ -0,0 +1,13 @@
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
+i2o_block
+i2o_bus
+i2o_config
+i2o_core
+i2o_proc
+i2o_scsi
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/scsi-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/scsi-modules
@@ -0,0 +1,114 @@
+# SCSI
+raid_class ?
+scsi_transport_spi ?
+scsi_transport_fc ?
+scsi_transport_iscsi ?
+scsi_transport_sas ?
+iscsi_tcp ?
+libiscsi ?
+amiga7xx ?
+a3000 ?
+a2091 ?
+gvp11 ?
+mvme147 ?
+sgiwd93 ?
+cyberstorm ?
+cyberstormII ?
+blz2060 ?
+blz1230 ?
+fastlane ?
+oktagon_esp_mod ?
+atari_scsi ?
+mac_scsi ?
+mac_esp ?
+sun3_scsi ?
+mvme16x ?
+bvme6000 ?
+sim710 ?
+advansys ?
+psi240i ?
+BusLogic ?
+dpt_i2o ?
+u14-34f ?
+ultrastor ?
+aha152x ?
+aha1542 ?
+aha1740 ?
+aic7xxx_old ?
+ips ?
+fd_mcs ?
+fdomain ?
+in2000 ?
+g_NCR5380 ?
+g_NCR5380_mmio ?
+NCR53c406a ?
+NCR_D700 ?
+NCR_Q720_mod ?
+sym53c416 ?
+qlogicfas408 ?
+qla1280 ?
+pas16 ?
+seagate ?
+seagate ?
+t128 ?
+dmx3191d ?
+dtc ?
+zalon7xx ?
+eata_pio ?
+wd7000 ?
+mca_53c9x ?
+ibmmca ?
+eata ?
+dc395x ?
+tmscsim ?
+megaraid ?
+atp870u ?
+esp ?
+gdth ?
+initio ?
+a100u2w ?
+qlogicpti ?
+ide-scsi ?
+mesh ?
+mac53c94 ?
+pluto ?
+dec_esp ?
+3w-xxxx ?
+3w-9xxx ?
+ppa ?
+imm ?
+jazz_esp ?
+sun3x_esp ?
+fcal ?
+lasi700 ?
+nsp32 ?
+ipr ?
+hptiop ?
+stex ?
+osst ?
+sg ?
+ch ?
+scsi_debug ?
+aacraid ?
+aic7xxx ?
+aic79xx ?
+aic94xx ?
+arcmsr ?
+acornscsi_mod ?
+arxescsi ?
+cumana_1 ?
+cumana_2 ?
+ecoscsi ?
+oak ?
+powertec ?
+eesox ?
+ibmvscsic ?
+libsas ?
+lpfc ?
+megaraid_mm ?
+megaraid_mbox ?
+megaraid_sas ?
+qla2xxx ?
+sym53c8xx ?
+qla4xxx ?
+mvsas ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/sata-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/sata-modules
@@ -0,0 +1,2 @@
+
+sata_mv
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/serial-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/serial-modules
@@ -0,0 +1,3 @@
+generic_serial
+serial_cs
+synclink_cs
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/virtio-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/virtio-modules
@@ -0,0 +1,4 @@
+virtio_balloon
+virtio_pci
+virtio_ring ?
+virtio-rng
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/crypto-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/crypto-modules
@@ -0,0 +1,8 @@
+aes_generic
+blowfish
+twofish
+serpent
+sha256_generic
+cbc
+ecb
+crc32c
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/plip-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/plip-modules
@@ -0,0 +1 @@
+plip
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/usb-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/usb-modules
@@ -0,0 +1,9 @@
+ehci-hcd ?
+isp116x-hcd
+isp1760
+ohci-hcd ?
+r8a66597-hcd
+sl811_cs
+sl811-hcd
+u132-hcd
+uhci-hcd ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/nic-pcmcia-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/nic-pcmcia-modules
@@ -0,0 +1,19 @@
+3c574_cs ?
+3c589_cs ?
+airo_cs ?
+atmel_cs ?
+axnet_cs ?
+com20020_cs ?
+fmvj18x_cs ?
+ibmtr_cs ?
+netwave_cs ?
+nmclan_cs ?
+orinoco_cs ?
+pcnet_cs ?
+ray_cs ?
+smc91c92_cs ?
+wavelan_cs ?
+wl3501_cs ?
+xirc2ps_cs ?
+xircom_cb ?
+xircom_tulip_cb ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/pcmcia-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/pcmcia-modules
@@ -0,0 +1,8 @@
+i82092
+i82365 ?
+pcmcia
+pcmcia_core
+pd6729
+rsrc_nonstatic
+tcic ?
+yenta_socket
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/pcmcia-storage-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/pcmcia-storage-modules
@@ -0,0 +1,6 @@
+pata_pcmcia
+qlogic_cs
+fdomain_cs
+aha152x_cs ?
+nsp_cs ?
+sym53c500_cs
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/fat-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/fat-modules
@@ -0,0 +1,7 @@
+fat
+vfat
+
+# Supporting modules ?
+nls_cp437 ?
+nls_iso8859-1 ?
+nls_utf8 ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/floppy-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/floppy-modules
@@ -0,0 +1 @@
+floppy
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/irda-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/irda-modules
@@ -0,0 +1,30 @@
+act200l-sir
+actisys-sir
+ali-ircc
+donauboe ?
+esi-sir
+girbil-sir
+ircomm
+ircomm-tty
+irda
+irda-usb
+irlan
+irnet
+irport ?
+irtty-sir
+kingsun-sir
+ks959-sir
+ksdazzle-sir
+litelink-sir
+ma600-sir
+mcp2120-sir
+mcs7780
+nsc-ircc
+old_belkin-sir
+sir-dev
+smsc-ircc2
+stir4200
+tekram-sir
+via-ircc
+vlsi_ir
+w83977af_ir
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/parport-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/parport-modules
@@ -0,0 +1,2 @@
+parport
+parport_pc
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/firewire-core-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/firewire-core-modules
@@ -0,0 +1,4 @@
+ieee1394
+ohci1394
+sbp2
+eth1394
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/nic-usb-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/nic-usb-modules
@@ -0,0 +1,11 @@
+catc ?
+kaweth ?
+pegasus ?
+prism2_usb ?
+rtl8150 ?
+usbnet ?
+zd1211rw ?
+zd1201 ?
+rt2500usb ?
+rt73usb ?
+rt2570 ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/nic-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/nic-modules
@@ -0,0 +1,152 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+amd8111e ?
+arc4 ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+atl1 ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm43xx ?
+bcm43xx-mac80211 ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bonding ?
+cassini ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+igb ?
+ps3_gelic ?
+hamachi ?
+hermes ?
+hp ?
+hp100 ?
+hp-plus ?
+ibmtr ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+ipw3945 ?
+ixgb ?
+lance ?
+lanstreamer ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+prism54 ?
+r8169 ?
+rate_control ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2500 ?
+rt61pci ?
+s2io ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/input-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/input-modules
@@ -0,0 +1,21 @@
+hid-a4tech ?
+hid-apple ?
+hid-belkin ?
+hid-bright ?
+hid-cherry ?
+hid-chicony ?
+hid-cypress ?
+hid-dell ?
+hid-ezkey ?
+hid-gyration ?
+hid-logitech ?
+hid-microsoft ?
+hid-monterey ?
+hid-petalynx ?
+hid-pl ?
+hid-samsung ?
+hid-sony ?
+hid-sunplus ?
+hid-tmff ?
+hid-zpff ?
+usbhid
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/nfs-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/nfs-modules
@@ -0,0 +1,4 @@
+nfs
+nfs_acl ?
+lockd
+sunrpc
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/pata-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/pata-modules
@@ -0,0 +1,3 @@
+pata_cs5535 ?
+pata_it8213
+pata_ninja32
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/block-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/block-modules
@@ -0,0 +1,29 @@
+aoe
+aten
+bpck
+bpck6 ?
+cciss
+comm
+cpqarray
+DAC960
+dstr
+epat
+epia
+fit2
+fit3
+friq
+frpw
+kbic
+ktti
+nbd
+on20
+on26
+paride
+pcd
+pd
+pf
+pg
+pt
+sx8
+umem
+virtio_blk ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules/fs-core-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules/fs-core-modules
@@ -0,0 +1,3 @@
+jfs
+reiserfs
+xfs
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-sparc/message-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-sparc/message-modules
@@ -0,0 +1,13 @@
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
+i2o_block
+i2o_bus
+i2o_config ?
+i2o_core
+i2o_proc
+i2o_scsi
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-sparc/block-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-sparc/block-modules
@@ -0,0 +1,9 @@
+aoe
+cciss
+comm
+cpqarray ?
+DAC960
+nbd
+sx8
+umem
+virtio_blk ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-powerpc/storage-core-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-powerpc/storage-core-modules
@@ -0,0 +1,13 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+
+# Loop modules
+cryptoloop
+
+# Needs to be here for better cdrom initrd layout
+isofs
+
+ps3stor_lib ?
+ps3rom ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-powerpc/message-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-powerpc/message-modules
@@ -0,0 +1,13 @@
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
+i2o_block
+i2o_bus
+i2o_config ?
+i2o_core
+i2o_proc
+i2o_scsi
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-powerpc/nic-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-powerpc/nic-modules
@@ -0,0 +1,152 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+amd8111e ?
+arc4 ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+atl1 ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm43xx ?
+bcm43xx-mac80211 ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bonding ?
+cassini ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+igb ?
+hamachi ?
+hermes ?
+hp ?
+hp100 ?
+hp-plus ?
+ibmtr ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+ipw3945 ?
+ixgb ?
+lance ?
+lanstreamer ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+prism54 ?
+ps3_gelic ?
+r8169 ?
+rate_control ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2500 ?
+rt61pci ?
+s2io ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
--- linux-ec2-2.6.32.orig/debian.ec2/d-i/modules-powerpc/block-modules
+++ linux-ec2-2.6.32/debian.ec2/d-i/modules-powerpc/block-modules
@@ -0,0 +1,31 @@
+aoe
+aten
+bpck
+bpck6 ?
+cciss
+comm
+cpqarray ?
+DAC960
+dstr
+epat
+epia
+fit2
+fit3
+friq
+frpw
+kbic
+ktti
+nbd
+on20
+on26
+paride
+pcd
+pd
+pf
+pg
+ps3disk ?
+ps3vram ?
+pt
+sx8
+umem
+virtio_blk ?
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-kdb-x86
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-kdb-x86
@@ -0,0 +1,42 @@
+From: SGI KDB Development <kdb@oss.sgi.com>
+Subject: kdb-v4.4-2.6.27-rc8-x86-1
+References: FATE#303971
+X-URL: ftp://oss.sgi.com/www/projects/kdb/download/v4.4/
+
+The KDB x86 code.
+
+Acked-by: Bernhard Walle <bwalle@suse.de>
+
+Automatically created from "patches.suse/kdb-x86" by xen-port-patches.py
+
+--- head-2009-10-12.orig/arch/x86/kdb/kdba_bt.c	2009-10-12 15:43:36.000000000 +0200
++++ head-2009-10-12/arch/x86/kdb/kdba_bt.c	2009-10-13 17:01:44.000000000 +0200
+@@ -721,7 +721,7 @@ static const char *bb_spurious[] = {
+ 				/* relocate_kernel */
+ 	"relocate_new_kernel",
+ #endif	/* CONFIG_KEXEC */
+-#ifdef	CONFIG_XEN
++#ifdef	CONFIG_PARAVIRT_XEN
+ 				/* arch/i386/xen/xen-asm.S */
+ 	"xen_irq_enable_direct_end",
+ 	"xen_irq_disable_direct_end",
+@@ -4873,7 +4873,7 @@ kdb_bb_all(int argc, const char **argv)
+ #ifdef	CONFIG_MATH_EMULATION
+ 		   " CONFIG_MATH_EMULATION"
+ #endif
+-#ifdef	CONFIG_XEN
++#ifdef	CONFIG_PARAVIRT_XEN
+ 		   " CONFIG_XEN"
+ #endif
+ #ifdef	CONFIG_DEBUG_INFO
+--- head-2009-10-12.orig/arch/x86/kdb/kdba_support.c	2009-10-12 11:47:00.000000000 +0200
++++ head-2009-10-12/arch/x86/kdb/kdba_support.c	2009-10-13 17:01:44.000000000 +0200
+@@ -1528,7 +1528,7 @@ extern void halt_current_cpu(struct pt_r
+ 
+ void kdba_kdump_shutdown_slave(struct pt_regs *regs)
+ {
+-#ifndef CONFIG_XEN
++#ifndef CONFIG_PARAVIRT_XEN
+ 	halt_current_cpu(regs);
+ #endif /* CONFIG_XEN */
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86_64-pgd-alloc-order
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86_64-pgd-alloc-order
@@ -0,0 +1,337 @@
+From: jbeulich@novell.com
+Subject: don't require order-1 allocations for pgd-s
+Patch-mainline: obsolete
+
+At the same time remove the useless user mode pair of init_level4_pgt.
+
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:55:40.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-12-04 12:11:43.000000000 +0100
+@@ -104,8 +104,8 @@ void do_hypervisor_callback(struct pt_re
+  * be MACHINE addresses.
+  */
+ 
+-void xen_pt_switch(unsigned long ptr);
+-void xen_new_user_pt(unsigned long ptr); /* x86_64 only */
++void xen_pt_switch(pgd_t *);
++void xen_new_user_pt(pgd_t *); /* x86_64 only */
+ void xen_load_gs(unsigned int selector); /* x86_64 only */
+ void xen_tlb_flush(void);
+ void xen_invlpg(unsigned long ptr);
+@@ -113,7 +113,7 @@ void xen_invlpg(unsigned long ptr);
+ void xen_l1_entry_update(pte_t *ptr, pte_t val);
+ void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
+ void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
+-void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */
++void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
+ void xen_pgd_pin(pgd_t *);
+ void xen_pgd_unpin(pgd_t *);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:52:22.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-12-04 12:11:43.000000000 +0100
+@@ -82,6 +82,9 @@ static inline void switch_mm(struct mm_s
+ {
+ 	unsigned cpu = smp_processor_id();
+ 	struct mmuext_op _op[2 + (sizeof(long) > 4)], *op = _op;
++#ifdef CONFIG_X86_64
++	pgd_t *upgd;
++#endif
+ 
+ 	if (likely(prev != next)) {
+ 		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+@@ -100,10 +103,11 @@ static inline void switch_mm(struct mm_s
+ 		op->arg1.mfn = virt_to_mfn(next->pgd);
+ 		op++;
+ 
+-		/* xen_new_user_pt(__pa(__user_pgd(next->pgd))) */
++		/* xen_new_user_pt(next->pgd) */
+ #ifdef CONFIG_X86_64
+ 		op->cmd = MMUEXT_NEW_USER_BASEPTR;
+-		op->arg1.mfn = virt_to_mfn(__user_pgd(next->pgd));
++		upgd = __user_pgd(next->pgd);
++		op->arg1.mfn = likely(upgd) ? virt_to_mfn(upgd) : 0;
+ 		op++;
+ #endif
+ 
+@@ -131,7 +135,7 @@ static inline void switch_mm(struct mm_s
+ 			 * to make sure to use no freed page tables.
+ 			 */
+ 			load_cr3(next->pgd);
+-			xen_new_user_pt(__pa(__user_pgd(next->pgd)));
++			xen_new_user_pt(next->pgd);
+ 			load_LDT_nolock(&next->context);
+ 		}
+ 	}
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-10-13 17:22:09.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc.h	2009-12-04 12:11:43.000000000 +0100
+@@ -118,15 +118,13 @@ static inline void pud_populate(struct m
+ #endif	/* CONFIG_X86_PAE */
+ 
+ #if PAGETABLE_LEVELS > 3
+-#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+-
+ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+ {
+ 	pgd_t ent = __pgd(_PAGE_TABLE | __pa(pud));
+ 
+ 	paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
+ 	if (unlikely(PagePinned(virt_to_page(pgd))))
+-		xen_l4_entry_update(pgd, 1, ent);
++		xen_l4_entry_update(pgd, ent);
+ 	else
+ 		*__user_pgd(pgd) = *pgd = ent;
+ }
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 11:12:01.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-12-04 12:11:43.000000000 +0100
+@@ -100,18 +100,25 @@ static inline void xen_set_pud(pud_t *pu
+ 	: (void)(*__pudp = xen_make_pud(0));	\
+ })
+ 
+-#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
++static inline pgd_t *__user_pgd(pgd_t *pgd)
++{
++	if (unlikely(((unsigned long)pgd & PAGE_MASK)
++		     == (unsigned long)init_level4_pgt))
++		return NULL;
++	return (pgd_t *)(virt_to_page(pgd)->index
++			 + ((unsigned long)pgd & ~PAGE_MASK));
++}
+ 
+ static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ {
+-	xen_l4_entry_update(pgdp, 0, pgd);
++	xen_l4_entry_update(pgdp, pgd);
+ }
+ 
+ #define xen_pgd_clear(pgd)			\
+ ({						\
+ 	pgd_t *__pgdp = (pgd);			\
+ 	PagePinned(virt_to_page(__pgdp))	\
+-	? xen_l4_entry_update(__pgdp, 1, xen_make_pgd(0)) \
++	? xen_l4_entry_update(__pgdp, xen_make_pgd(0)) \
+ 	: (void)(*__user_pgd(__pgdp) = *__pgdp = xen_make_pgd(0)); \
+ })
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 11:12:01.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2010-01-18 17:14:45.000000000 +0100
+@@ -1026,8 +1026,7 @@ DEFINE_PER_CPU_FIRST(union irq_stack_uni
+ void xen_switch_pt(void)
+ {
+ #ifdef CONFIG_XEN
+-	xen_pt_switch(__pa_symbol(init_level4_pgt));
+-	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
++	xen_pt_switch(init_level4_pgt);
+ #endif
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-12-04 14:37:14.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-12-04 14:37:53.000000000 +0100
+@@ -56,14 +56,6 @@ ENTRY(name)
+ 	__PAGE_ALIGNED_BSS
+ NEXT_PAGE(init_level4_pgt)
+ 	.fill	512,8,0
+-        /*
+-         * We update two pgd entries to make kernel and user pgd consistent
+-         * at pgd_populate(). It can be used for kernel modules. So we place 
+-         * this page here for those cases to avoid memory corruption.
+-         * We also use this page to establish the initial mapping for the
+-         * vsyscall area.
+-         */
+-	.fill	512,8,0
+ 
+ NEXT_PAGE(level3_kernel_pgt)
+ 	.fill	512,8,0
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2010-01-05 16:47:51.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2010-01-05 16:47:55.000000000 +0100
+@@ -525,7 +525,7 @@ void xen_l3_entry_update(pud_t *ptr, pud
+ #endif
+ 
+ #ifdef CONFIG_X86_64
+-void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val)
++void xen_l4_entry_update(pgd_t *ptr, pgd_t val)
+ {
+ 	mmu_update_t u[2];
+ 	struct page *page = NULL;
+@@ -538,8 +538,11 @@ void xen_l4_entry_update(pgd_t *ptr, int
+ 	}
+ 	u[0].ptr = virt_to_machine(ptr);
+ 	u[0].val = __pgd_val(val);
+-	if (user) {
+-		u[1].ptr = virt_to_machine(__user_pgd(ptr));
++	if (((unsigned long)ptr & ~PAGE_MASK)
++	    <= pgd_index(TASK_SIZE_MAX) * sizeof(*ptr)) {
++		ptr = __user_pgd(ptr);
++		BUG_ON(!ptr);
++		u[1].ptr = virt_to_machine(ptr);
+ 		u[1].val = __pgd_val(val);
+ 		do_lN_entry_update(u, 2, page);
+ 	} else
+@@ -547,21 +550,25 @@ void xen_l4_entry_update(pgd_t *ptr, int
+ }
+ #endif /* CONFIG_X86_64 */
+ 
+-void xen_pt_switch(unsigned long ptr)
++#ifdef CONFIG_X86_64
++void xen_pt_switch(pgd_t *pgd)
+ {
+ 	struct mmuext_op op;
+ 	op.cmd = MMUEXT_NEW_BASEPTR;
+-	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	op.arg1.mfn = virt_to_mfn(pgd);
+ 	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
+ 
+-void xen_new_user_pt(unsigned long ptr)
++void xen_new_user_pt(pgd_t *pgd)
+ {
+ 	struct mmuext_op op;
++
++	pgd = __user_pgd(pgd);
+ 	op.cmd = MMUEXT_NEW_USER_BASEPTR;
+-	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	op.arg1.mfn = pgd ? virt_to_mfn(pgd) : 0;
+ 	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
++#endif
+ 
+ void xen_tlb_flush(void)
+ {
+@@ -638,7 +645,14 @@ void xen_pgd_pin(pgd_t *pgd)
+ 	op[0].arg1.mfn = virt_to_mfn(pgd);
+ #ifdef CONFIG_X86_64
+ 	op[1].cmd = op[0].cmd = MMUEXT_PIN_L4_TABLE;
+-	op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd));
++	pgd = __user_pgd(pgd);
++	if (pgd)
++		op[1].arg1.mfn = virt_to_mfn(pgd);
++	else {
++		op[1].cmd = MMUEXT_PIN_L3_TABLE;
++		op[1].arg1.mfn = pfn_to_mfn(__pa_symbol(level3_user_pgt)
++					    >> PAGE_SHIFT);
++	}
+ #endif
+ 	if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0)
+ 		BUG();
+@@ -651,8 +665,10 @@ void xen_pgd_unpin(pgd_t *pgd)
+ 	op[0].cmd = MMUEXT_UNPIN_TABLE;
+ 	op[0].arg1.mfn = virt_to_mfn(pgd);
+ #ifdef CONFIG_X86_64
++	pgd = __user_pgd(pgd);
++	BUG_ON(!pgd);
+ 	op[1].cmd = MMUEXT_UNPIN_TABLE;
+-	op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd));
++	op[1].arg1.mfn = virt_to_mfn(pgd);
+ #endif
+ 	if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0)
+ 		BUG();
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-10-13 17:25:37.000000000 +0200
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-12-04 12:11:43.000000000 +0100
+@@ -718,9 +718,6 @@ void __init xen_init_pt(void)
+ 	       (PTRS_PER_PUD - pud_index(__START_KERNEL_map))
+ 	       * sizeof(*level3_kernel_pgt));
+ 
+-	__user_pgd(init_level4_pgt)[pgd_index(VSYSCALL_START)] =
+-		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
+-
+ 	/* Do an early initialization of the fixmap area. */
+ 	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ 	if (pud_present(level3_kernel_pgt[pud_index(addr)])) {
+@@ -736,8 +733,6 @@ void __init xen_init_pt(void)
+ 
+ 	early_make_page_readonly(init_level4_pgt,
+ 				 XENFEAT_writable_page_tables);
+-	early_make_page_readonly(__user_pgd(init_level4_pgt),
+-				 XENFEAT_writable_page_tables);
+ 	early_make_page_readonly(level3_kernel_pgt,
+ 				 XENFEAT_writable_page_tables);
+ 	early_make_page_readonly(level3_user_pgt,
+--- head-2010-01-18.orig/arch/x86/mm/pgtable-xen.c	2009-10-14 14:20:47.000000000 +0200
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-12-04 12:11:43.000000000 +0100
+@@ -269,9 +269,11 @@ static void pgd_walk(pgd_t *pgd_base, pg
+ 			BUG();
+ 		seq = 0;
+ 	}
++	pgd = __user_pgd(pgd_base);
++	BUG_ON(!pgd);
+ 	MULTI_update_va_mapping(mcl + seq,
+-	       (unsigned long)__user_pgd(pgd_base),
+-	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
++	       (unsigned long)pgd,
++	       pfn_pte(virt_to_phys(pgd)>>PAGE_SHIFT, flags),
+ 	       0);
+ 	MULTI_update_va_mapping(mcl + seq + 1,
+ 	       (unsigned long)pgd_base,
+@@ -659,12 +661,29 @@ static void pgd_prepopulate_pmd(struct m
+ 	}
+ }
+ 
++static inline pgd_t *user_pgd_alloc(pgd_t *pgd)
++{
+ #ifdef CONFIG_X86_64
+-/* We allocate two contiguous pages for kernel and user. */
+-#define PGD_ORDER 1
+-#else
+-#define PGD_ORDER 0
++	if (pgd) {
++		pgd_t *upgd = (void *)__get_free_page(PGALLOC_GFP);
++
++		if (upgd)
++			virt_to_page(pgd)->index = (long)upgd;
++		else {
++			free_page((unsigned long)pgd);
++			pgd = NULL;
++		}
++	}
++#endif
++	return pgd;
++}
++
++static inline void user_pgd_free(pgd_t *pgd)
++{
++#ifdef CONFIG_X86_64
++	free_page(virt_to_page(pgd)->index);
+ #endif
++}
+ 
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+@@ -672,7 +691,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	pmd_t *pmds[PREALLOCATED_PMDS];
+ 	unsigned long flags;
+ 
+-	pgd = (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ORDER);
++	pgd = user_pgd_alloc((void *)__get_free_page(PGALLOC_GFP));
+ 
+ 	if (pgd == NULL)
+ 		goto out;
+@@ -711,7 +730,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ out_free_pmds:
+ 	free_pmds(pmds, mm, !xen_feature(XENFEAT_pae_pgdir_above_4gb));
+ out_free_pgd:
+-	free_pages((unsigned long)pgd, PGD_ORDER);
++	user_pgd_free(pgd);
++	free_page((unsigned long)pgd);
+ out:
+ 	return NULL;
+ }
+@@ -730,7 +750,8 @@ void pgd_free(struct mm_struct *mm, pgd_
+ 
+ 	pgd_mop_up_pmds(mm, pgd);
+ 	paravirt_pgd_free(mm, pgd);
+-	free_pages((unsigned long)pgd, PGD_ORDER);
++	user_pgd_free(pgd);
++	free_page((unsigned long)pgd);
+ }
+ 
+ /* blktap and gntdev need this, as otherwise they would implicitly (and
+--- head-2010-01-18.orig/drivers/xen/core/machine_reboot.c	2009-12-18 14:15:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/machine_reboot.c	2009-12-18 14:15:58.000000000 +0100
+@@ -188,8 +188,7 @@ static int take_machine_down(void *_susp
+ 		 * in fast-suspend mode as that implies a new enough Xen.
+ 		 */
+ 		if (!suspend->fast_suspend)
+-			xen_new_user_pt(__pa(__user_pgd(
+-				current->active_mm->pgd)));
++			xen_new_user_pt(current->active_mm->pgd);
+ #endif
+ 	}
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.30
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.30
@@ -0,0 +1,18468 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: Linux 2.6.30
+Patch-mainline: 2.6.30
+
+ This patch contains the differences between 2.6.29 and 2.6.30.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.30" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/ia64/include/asm/xen/hypervisor.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/ia64/include/asm/xen/hypervisor.h	2009-11-06 10:52:02.000000000 +0100
+@@ -34,10 +34,12 @@
+ #define _ASM_IA64_XEN_HYPERVISOR_H
+ 
+ #include <linux/err.h>
++#ifdef CONFIG_PARAVIRT_XEN
+ #include <xen/interface/xen.h>
+ #include <xen/interface/version.h>	/* to compile feature.c */
+ #include <xen/features.h>		/* to comiple xen-netfront.c */
+ #include <asm/xen/hypercall.h>
++#endif
+ 
+ /* xen_domain_type is set before executing any C code by early_xen_setup */
+ enum xen_domain_type {
+--- head-2010-01-18.orig/arch/ia64/kernel/vmlinux.lds.S	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/ia64/kernel/vmlinux.lds.S	2009-11-06 10:52:02.000000000 +0100
+@@ -176,7 +176,7 @@ SECTIONS
+ 	  __start_gate_section = .;
+ 	  *(.data.gate)
+ 	  __stop_gate_section = .;
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ 	  . = ALIGN(PAGE_SIZE);
+ 	  __xen_start_gate_section = .;
+ 	  *(.data.gate.xen)
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:02:51.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:03:01.000000000 +0100
+@@ -47,8 +47,8 @@ config X86
+ 	select USER_STACKTRACE_SUPPORT
+ 	select HAVE_DMA_API_DEBUG
+ 	select HAVE_KERNEL_GZIP
+-	select HAVE_KERNEL_BZIP2
+-	select HAVE_KERNEL_LZMA
++	select HAVE_KERNEL_BZIP2 if !XEN
++	select HAVE_KERNEL_LZMA if !XEN
+ 	select HAVE_ARCH_KMEMCHECK
+ 
+ config OUTPUT_FORMAT
+@@ -325,11 +325,11 @@ config X86_XEN
+ 
+ config X86_BIGSMP
+ 	bool "Support for big SMP systems with more than 8 CPUs"
+-	depends on X86_32 && SMP
++	depends on X86_32 && SMP && !XEN
+ 	---help---
+ 	  This option is needed for the systems that have more than 8 CPUs
+ 
+-if X86_32
++if X86_32 && !XEN
+ config X86_EXTENDED_PLATFORM
+ 	bool "Support for extended (non-PC) x86 platforms"
+ 	default y
+@@ -360,7 +360,7 @@ config X86_64_XEN
+ 	help
+ 	  This option will compile a kernel compatible with Xen hypervisor
+ 
+-if X86_64
++if X86_64 && !XEN
+ config X86_EXTENDED_PLATFORM
+ 	bool "Support for extended (non-PC) x86 platforms"
+ 	default y
+@@ -804,7 +804,7 @@ config MAXSMP
+ 
+ config NR_CPUS
+ 	int "Maximum number of CPUs" if SMP && !MAXSMP
+-	range 2 8 if SMP && X86_32 && !X86_BIGSMP
++	range 2 8 if SMP && X86_32 && !X86_BIGSMP && !X86_XEN
+ 	range 2 512 if SMP && !MAXSMP
+ 	default "1" if !SMP
+ 	default "4096" if MAXSMP
+@@ -878,10 +878,6 @@ config X86_VISWS_APIC
+ 	def_bool y
+ 	depends on X86_32 && X86_VISWS
+ 
+-config X86_XEN_GENAPIC
+-	def_bool y
+-	depends on X86_64_XEN
+-
+ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 	bool "Reroute for broken boot IRQs"
+ 	default n
+--- head-2010-01-18.orig/arch/x86/Makefile	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -111,10 +111,6 @@ endif
+ # prevent gcc from generating any FP code by mistake
+ KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+ 
+-# Xen subarch support
+-mflags-$(CONFIG_XEN)		:= -Iarch/x86/include/mach-xen
+-mcore-$(CONFIG_XEN)		:= arch/x86/mach-xen/
+-
+ KBUILD_CFLAGS += $(mflags-y)
+ KBUILD_AFLAGS += $(mflags-y)
+ 
+@@ -186,10 +182,10 @@ bzImage: vmlinux
+ 	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
+ 	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
+ 	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@
++endif
+ 
+ $(BOOT_TARGETS): vmlinux
+ 	$(Q)$(MAKE) $(build)=$(boot) $@
+-endif
+ 
+ PHONY += install
+ install:
+--- head-2010-01-18.orig/arch/x86/boot/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/boot/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -204,6 +204,12 @@ $(obj)/vmlinux-stripped: OBJCOPYFLAGS :=
+ $(obj)/vmlinux-stripped: vmlinux FORCE
+ 	$(call if_changed,objcopy)
+ 
++ifndef CONFIG_XEN
++bzImage := bzImage
++else
++bzImage := vmlinuz
++endif
++
+ install:
+-	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
++	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/$(bzImage) \
+ 		System.map "$(INSTALL_PATH)"
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:52:02.000000000 +0100
+@@ -502,7 +502,7 @@ ia32_sys_call_table:
+ 	.quad sys32_olduname
+ 	.quad sys_umask		/* 60 */
+ 	.quad sys_chroot
+-	.quad sys32_ustat
++	.quad compat_sys_ustat
+ 	.quad sys_dup2
+ 	.quad sys_getppid
+ 	.quad sys_getpgrp		/* 65 */
+@@ -773,4 +773,6 @@ ia32_sys_call_table:
+ 	.quad sys_dup3			/* 330 */
+ 	.quad sys_pipe2
+ 	.quad sys_inotify_init1
++	.quad compat_sys_preadv
++	.quad compat_sys_pwritev
+ ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/include/asm/kexec.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/kexec.h	2009-11-06 10:52:02.000000000 +0100
+@@ -21,8 +21,14 @@
+ # define PA_CONTROL_PAGE	0
+ # define VA_CONTROL_PAGE	1
+ # define PA_TABLE_PAGE		2
++# ifndef CONFIG_XEN
+ # define PA_SWAP_PAGE		3
+ # define PAGES_NR		4
++# else /* CONFIG_XEN, see comment above
++#  define VA_TABLE_PAGE		3 */
++#  define PA_SWAP_PAGE		4
++#  define PAGES_NR		5
++# endif /* CONFIG_XEN */
+ #endif
+ 
+ # define KEXEC_CONTROL_CODE_MAX_SIZE	2048
+--- head-2010-01-18.orig/arch/x86/include/asm/page_64_types.h	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/page_64_types.h	2009-11-06 10:52:02.000000000 +0100
+@@ -69,7 +69,15 @@ extern void init_extra_mapping_wb(unsign
+ #endif	/* !__ASSEMBLY__ */
+ 
+ #ifdef CONFIG_FLATMEM
++/*
++ * While max_pfn is not exported, max_mapnr never gets initialized for non-Xen
++ * other than for hotplugged memory.
++ */
++#ifndef CONFIG_XEN
+ #define pfn_valid(pfn)          ((pfn) < max_pfn)
++#else
++#define pfn_valid(pfn)          ((pfn) < max_mapnr)
++#endif
+ #endif
+ 
+ #endif /* _ASM_X86_PAGE_64_DEFS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:52:02.000000000 +0100
+@@ -39,7 +39,7 @@ extern gate_desc idt_table[];
+ struct gdt_page {
+ 	struct desc_struct gdt[GDT_ENTRIES];
+ } __attribute__((aligned(PAGE_SIZE)));
+-DECLARE_PER_CPU(struct gdt_page, gdt_page);
++DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
+ 
+ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ {
+@@ -91,7 +91,6 @@ static inline int desc_empty(const void 
+ #define store_gdt(dtr) native_store_gdt(dtr)
+ #define store_idt(dtr) native_store_idt(dtr)
+ #define store_tr(tr) (tr = native_store_tr())
+-#define store_ldt(ldt) asm("sldt %0":"=m" (ldt))
+ 
+ #define load_TLS(t, cpu) native_load_tls(t, cpu)
+ #define set_ldt native_set_ldt
+@@ -111,6 +110,8 @@ static inline void paravirt_free_ldt(str
+ {
+ }
+ 
++#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
++
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ 					  const gate_desc *gate)
+ {
+@@ -251,6 +252,8 @@ static inline void native_load_tls(struc
+ 		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+ }
+ #else
++#include <asm/pgtable.h>
++
+ #define load_TLS(t, cpu) xen_load_tls(t, cpu)
+ #define set_ldt xen_set_ldt
+ 
+@@ -265,8 +268,9 @@ static inline void xen_load_tls(struct t
+ 	struct desc_struct *gdt = get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN;
+ 
+ 	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+-		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
+-						 *(u64 *)&t->tls_array[i]))
++		if (HYPERVISOR_update_descriptor(
++				arbitrary_virt_to_machine(&gdt[i]),
++				*(u64 *)&t->tls_array[i]))
+ 			BUG();
+ }
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:02.000000000 +0100
+@@ -1,11 +1,154 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1998 Ingo Molnar
++ *
++ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ * x86_32 and x86_64 integration by Gustavo F. Padovan, February 2009
++ */
++
+ #ifndef _ASM_X86_FIXMAP_H
+ #define _ASM_X86_FIXMAP_H
+ 
++#ifndef __ASSEMBLY__
++#include <linux/kernel.h>
++#include <asm/acpi.h>
++#include <asm/apicdef.h>
++#include <asm/page.h>
++#ifdef CONFIG_X86_32
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#else
++#include <asm/vsyscall.h>
++#endif
++
++/*
++ * We can't declare FIXADDR_TOP as variable for x86_64 because vsyscall
++ * uses fixmaps that relies on FIXADDR_TOP for proper address calculation.
++ * Because of this, FIXADDR_TOP x86 integration was left as later work.
++ */
++#ifdef CONFIG_X86_32
++/* used by vmalloc.c, vsyscall.lds.S.
++ *
++ * Leave one empty page between vmalloc'ed areas and
++ * the start of the fixmap.
++ */
++extern unsigned long __FIXADDR_TOP;
++#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
++
++#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
++#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
++#else
++#define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
++
++/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
++#define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
++#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
++#endif
++
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process.
++ * for x86_32: We allocate these special addresses
++ * from the end of virtual memory (0xfffff000) backwards.
++ * Also this lets us do fail-safe vmalloc(), we
++ * can guarantee that these special addresses and
++ * vmalloc()-ed addresses never overlap.
++ *
++ * These 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages (or larger if used with an increment
++ * higher than 1). Use set_fixmap(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++enum fixed_addresses {
+ #ifdef CONFIG_X86_32
+-# include "fixmap_32.h"
++	FIX_HOLE,
++	FIX_VDSO,
+ #else
+-# include "fixmap_64.h"
++	VSYSCALL_LAST_PAGE,
++	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
++			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
++	VSYSCALL_HPET,
++#endif
++	FIX_DBGP_BASE,
++	FIX_EARLYCON_MEM_BASE,
++#ifdef CONFIG_X86_LOCAL_APIC
++	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_IO_APIC
++	FIX_IO_APIC_BASE_0,
++	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
++#endif
++#else
++	FIX_SHARED_INFO,
++#define NR_FIX_ISAMAPS	256
++	FIX_ISAMAP_END,
++	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
++#endif
++#ifdef CONFIG_X86_VISWS_APIC
++	FIX_CO_CPU,	/* Cobalt timer */
++	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
++	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
++	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
++#endif
++#ifdef CONFIG_X86_F00F_BUG
++	FIX_F00F_IDT,	/* Virtual mapping for IDT */
++#endif
++#ifdef CONFIG_X86_CYCLONE_TIMER
++	FIX_CYCLONE_TIMER, /*cyclone timer register*/
++#endif
++#ifdef CONFIG_X86_32
++	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
++	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
++#ifdef CONFIG_PCI_MMCONFIG
++	FIX_PCIE_MCFG,
++#endif
++#endif
++#ifdef CONFIG_PARAVIRT
++	FIX_PARAVIRT_BOOTMAP,
++#endif
++	FIX_TEXT_POKE0,	/* reserve 2 pages for text_poke() */
++	FIX_TEXT_POKE1,
++	__end_of_permanent_fixed_addresses,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
++	/*
++	 * 256 temporary boot-time mappings, used by early_ioremap(),
++	 * before ioremap() is functional.
++	 *
++	 * We round it up to the next 256 pages boundary so that we
++	 * can have a single pgd entry and a single pte table:
++	 */
++#define NR_FIX_BTMAPS		64
++#define FIX_BTMAPS_SLOTS	4
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
++			(__end_of_permanent_fixed_addresses & 255),
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
++#ifdef CONFIG_X86_32
++	FIX_WP_TEST,
++#endif
++	__end_of_fixed_addresses
++};
++
++
++extern void reserve_top_address(unsigned long reserve);
++
++#define FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_BOOT_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_START		(FIXADDR_TOP - FIXADDR_SIZE)
++#define FIXADDR_BOOT_START	(FIXADDR_TOP - FIXADDR_BOOT_SIZE)
+ 
+ extern int fixmaps_set;
+ 
+@@ -13,10 +156,10 @@ extern pte_t *kmap_pte;
+ extern pgprot_t kmap_prot;
+ extern pte_t *pkmap_page_table;
+ 
+-void xen_set_fixmap(enum fixed_addresses, maddr_t, pgprot_t);
++void xen_set_fixmap(enum fixed_addresses, phys_addr_t, pgprot_t);
+ 
+ static inline void __set_fixmap(enum fixed_addresses idx,
+-				maddr_t phys, pgprot_t flags)
++				phys_addr_t phys, pgprot_t flags)
+ {
+ 	xen_set_fixmap(idx, phys, flags);
+ }
+@@ -65,4 +208,5 @@ static inline unsigned long virt_to_fix(
+ 	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ 	return __virt_to_fix(vaddr);
+ }
++#endif /* !__ASSEMBLY__ */
+ #endif /* _ASM_X86_FIXMAP_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:47.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,125 +0,0 @@
+-/*
+- * fixmap.h: compile-time virtual memory allocation
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 1998 Ingo Molnar
+- *
+- * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+- */
+-
+-#ifndef _ASM_X86_FIXMAP_32_H
+-#define _ASM_X86_FIXMAP_32_H
+-
+-/* used by vmalloc.c, vsyscall.lds.S.
+- *
+- * Leave one empty page between vmalloc'ed areas and
+- * the start of the fixmap.
+- */
+-extern unsigned long __FIXADDR_TOP;
+-#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
+-#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
+-
+-#ifndef __ASSEMBLY__
+-#include <linux/kernel.h>
+-#include <asm/acpi.h>
+-#include <asm/apicdef.h>
+-#include <asm/page.h>
+-#include <linux/threads.h>
+-#include <asm/kmap_types.h>
+-
+-/*
+- * Here we define all the compile-time 'special' virtual
+- * addresses. The point is to have a constant address at
+- * compile time, but to set the physical address only
+- * in the boot process. We allocate these special addresses
+- * from the end of virtual memory (0xfffff000) backwards.
+- * Also this lets us do fail-safe vmalloc(), we
+- * can guarantee that these special addresses and
+- * vmalloc()-ed addresses never overlap.
+- *
+- * these 'compile-time allocated' memory buffers are
+- * fixed-size 4k pages. (or larger if used with an increment
+- * highger than 1) use fixmap_set(idx,phys) to associate
+- * physical memory with fixmap indices.
+- *
+- * TLB entries of such buffers will not be flushed across
+- * task switches.
+- */
+-enum fixed_addresses {
+-	FIX_HOLE,
+-	FIX_VDSO,
+-	FIX_DBGP_BASE,
+-	FIX_EARLYCON_MEM_BASE,
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+-#endif
+-#ifndef CONFIG_XEN
+-#ifdef CONFIG_X86_IO_APIC
+-	FIX_IO_APIC_BASE_0,
+-	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+-#endif
+-#else
+-	FIX_SHARED_INFO,
+-#define NR_FIX_ISAMAPS	256
+-	FIX_ISAMAP_END,
+-	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+-#endif
+-#ifdef CONFIG_X86_VISWS_APIC
+-	FIX_CO_CPU,	/* Cobalt timer */
+-	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
+-	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
+-	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
+-#endif
+-#ifdef CONFIG_X86_F00F_BUG
+-	FIX_F00F_IDT,	/* Virtual mapping for IDT */
+-#endif
+-#ifdef CONFIG_X86_CYCLONE_TIMER
+-	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+-#endif
+-	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+-	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+-#ifdef CONFIG_PCI_MMCONFIG
+-	FIX_PCIE_MCFG,
+-#endif
+-#ifdef CONFIG_PARAVIRT
+-	FIX_PARAVIRT_BOOTMAP,
+-#endif
+-	__end_of_permanent_fixed_addresses,
+-	/*
+-	 * 256 temporary boot-time mappings, used by early_ioremap(),
+-	 * before ioremap() is functional.
+-	 *
+-	 * We round it up to the next 256 pages boundary so that we
+-	 * can have a single pgd entry and a single pte table:
+-	 */
+-#define NR_FIX_BTMAPS		64
+-#define FIX_BTMAPS_SLOTS	4
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+-			(__end_of_permanent_fixed_addresses & 255),
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+-	FIX_WP_TEST,
+-#ifdef CONFIG_ACPI
+-	FIX_ACPI_BEGIN,
+-	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+-#endif
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	FIX_OHCI1394_BASE,
+-#endif
+-	__end_of_fixed_addresses
+-};
+-
+-extern void reserve_top_address(unsigned long reserve);
+-
+-
+-#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+-
+-#define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+-#define __FIXADDR_BOOT_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+-#define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
+-#define FIXADDR_BOOT_START	(FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
+-
+-#endif /* !__ASSEMBLY__ */
+-#endif /* _ASM_X86_FIXMAP_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:55.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,90 +0,0 @@
+-/*
+- * fixmap.h: compile-time virtual memory allocation
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- *
+- * Copyright (C) 1998 Ingo Molnar
+- */
+-
+-#ifndef _ASM_X86_FIXMAP_64_H
+-#define _ASM_X86_FIXMAP_64_H
+-
+-#include <linux/kernel.h>
+-#include <asm/acpi.h>
+-#include <asm/apicdef.h>
+-#include <asm/page.h>
+-#include <asm/vsyscall.h>
+-#include <asm/acpi.h>
+-
+-/*
+- * Here we define all the compile-time 'special' virtual
+- * addresses. The point is to have a constant address at
+- * compile time, but to set the physical address only
+- * in the boot process.
+- *
+- * These 'compile-time allocated' memory buffers are
+- * fixed-size 4k pages (or larger if used with an increment
+- * higher than 1). Use set_fixmap(idx,phys) to associate
+- * physical memory with fixmap indices.
+- *
+- * TLB entries of such buffers will not be flushed across
+- * task switches.
+- */
+-
+-enum fixed_addresses {
+-	VSYSCALL_LAST_PAGE,
+-	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+-			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+-	VSYSCALL_HPET,
+-	FIX_DBGP_BASE,
+-	FIX_EARLYCON_MEM_BASE,
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+-#endif
+-#ifndef CONFIG_XEN
+-	FIX_IO_APIC_BASE_0,
+-	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+-#else
+-#define NR_FIX_ISAMAPS	256
+-	FIX_ISAMAP_END,
+-	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+-#endif
+-#ifdef CONFIG_PARAVIRT
+-	FIX_PARAVIRT_BOOTMAP,
+-#else
+-	FIX_SHARED_INFO,
+-#endif
+-	__end_of_permanent_fixed_addresses,
+-#ifdef CONFIG_ACPI
+-	FIX_ACPI_BEGIN,
+-	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+-#endif
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	FIX_OHCI1394_BASE,
+-#endif
+-	/*
+-	 * 256 temporary boot-time mappings, used by early_ioremap(),
+-	 * before ioremap() is functional.
+-	 *
+-	 * We round it up to the next 256 pages boundary so that we
+-	 * can have a single pgd entry and a single pte table:
+-	 */
+-#define NR_FIX_BTMAPS		64
+-#define FIX_BTMAPS_SLOTS	4
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+-			(__end_of_permanent_fixed_addresses & 255),
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+-	__end_of_fixed_addresses
+-};
+-
+-#define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
+-#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+-#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+-
+-/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
+-#define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
+-#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+-
+-#endif /* _ASM_X86_FIXMAP_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:52:02.000000000 +0100
+@@ -63,6 +63,7 @@ void *kmap_atomic(struct page *page, enu
+ void *kmap_atomic_pte(struct page *page, enum km_type type);
+ void kunmap_atomic(void *kvaddr, enum km_type type);
+ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
++void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+ struct page *kmap_atomic_to_page(void *ptr);
+ 
+ #define kmap_atomic_pte(page, type) \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:42:20.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:43:12.000000000 +0100
+@@ -46,7 +46,7 @@
+ #include <xen/interface/arch-x86/xen-mca.h>
+ #include <asm/percpu.h>
+ #include <asm/ptrace.h>
+-#include <asm/page.h>
++#include <asm/pgtable_types.h>
+ 
+ extern shared_info_t *HYPERVISOR_shared_info;
+ 
+@@ -153,20 +153,16 @@ int __must_check xen_multi_mmuext_op(str
+ #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+ static inline void arch_enter_lazy_mmu_mode(void)
+ {
+-	__get_cpu_var(xen_lazy_mmu) = true;
++	percpu_write(xen_lazy_mmu, true);
+ }
+ 
+ static inline void arch_leave_lazy_mmu_mode(void)
+ {
+-	__get_cpu_var(xen_lazy_mmu) = false;
++	percpu_write(xen_lazy_mmu, false);
+ 	xen_multicall_flush(false);
+ }
+ 
+-#if defined(CONFIG_X86_32)
+-#define arch_use_lazy_mmu_mode() unlikely(x86_read_percpu(xen_lazy_mmu))
+-#elif !defined(arch_use_lazy_mmu_mode)
+-#define arch_use_lazy_mmu_mode() unlikely(__get_cpu_var(xen_lazy_mmu))
+-#endif
++#define arch_use_lazy_mmu_mode() unlikely(percpu_read(xen_lazy_mmu))
+ 
+ #if 0 /* All uses are in places potentially called asynchronously, but
+        * asynchronous code should rather not make use of lazy mode at all.
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:52:02.000000000 +0100
+@@ -5,6 +5,10 @@
+ 
+ #include <linux/compiler.h>
+ #include <asm-generic/int-ll64.h>
++#include <asm/page.h>
++#ifdef __KERNEL__
++#include <asm/fixmap.h>
++#endif
+ 
+ #define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void __iomem *addr) \
+@@ -82,6 +86,101 @@ static inline void writeq(__u64 val, vol
+ 
+ #define native_io_delay xen_io_delay
+ 
++/**
++ *	virt_to_phys	-	map virtual addresses to physical
++ *	@address: address to remap
++ *
++ *	The returned physical address is the physical (CPU) mapping for
++ *	the memory address given. It is only valid to use this function on
++ *	addresses directly mapped or allocated via kmalloc.
++ *
++ *	This function does not give bus mappings for DMA transfers. In
++ *	almost all conceivable cases a device driver should not be using
++ *	this function
++ */
++
++static inline phys_addr_t virt_to_phys(volatile void *address)
++{
++	return __pa(address);
++}
++
++/**
++ *	phys_to_virt	-	map physical address to virtual
++ *	@address: address to remap
++ *
++ *	The returned virtual address is a current CPU mapping for
++ *	the memory address given. It is only valid to use this function on
++ *	addresses that have a kernel mapping
++ *
++ *	This function does not handle bus mappings for DMA transfers. In
++ *	almost all conceivable cases a device driver should not be using
++ *	this function
++ */
++
++static inline void *phys_to_virt(phys_addr_t address)
++{
++	return __va(address);
++}
++
++/*
++ * Change "struct page" to physical address.
++ */
++#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
++#undef page_to_phys
++#define page_to_phys(page)	 (phys_to_machine(page_to_pseudophys(page)))
++#define page_to_bus(page)	 (phys_to_machine(page_to_pseudophys(page)))
++
++/*
++ * ISA I/O bus memory addresses are 1:1 with the physical address.
++ * However, we truncate the address to unsigned int to avoid undesirable
++ * promitions in legacy drivers.
++ */
++#define isa_virt_to_bus(_x) ({ \
++	unsigned long _va_ = (unsigned long)(_x); \
++	_va_ - fix_to_virt(FIX_ISAMAP_BEGIN) < (NR_FIX_ISAMAPS << PAGE_SHIFT) \
++	? _va_ - fix_to_virt(FIX_ISAMAP_BEGIN) \
++	: ({ BUG(); (unsigned long)virt_to_bus(_va_); }); })
++#define isa_bus_to_virt(_x) ((void *)fix_to_virt(FIX_ISAMAP_BEGIN) + (_x))
++
++/*
++ * However PCI ones are not necessarily 1:1 and therefore these interfaces
++ * are forbidden in portable PCI drivers.
++ *
++ * Allow them on x86 for legacy drivers, though.
++ */
++#define virt_to_bus(_x) phys_to_machine(__pa(_x))
++#define bus_to_virt(_x) __va(machine_to_phys(_x))
++
++/**
++ * ioremap     -   map bus memory into CPU space
++ * @offset:    bus address of the memory
++ * @size:      size of the resource to map
++ *
++ * ioremap performs a platform specific sequence of operations to
++ * make bus memory CPU accessible via the readb/readw/readl/writeb/
++ * writew/writel functions and the other mmio helpers. The returned
++ * address is not guaranteed to be usable directly as a virtual
++ * address.
++ *
++ * If the area you are trying to map is a PCI BAR you should have a
++ * look at pci_iomap().
++ */
++extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
++extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
++extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
++				unsigned long prot_val);
++
++/*
++ * The default ioremap() behavior is non-cached:
++ */
++static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
++{
++	return ioremap_nocache(offset, size);
++}
++
++extern void iounmap(volatile void __iomem *addr);
++
++
+ #ifdef CONFIG_X86_32
+ # include "../../asm/io_32.h"
+ #else
+@@ -93,11 +192,6 @@ static inline void writeq(__u64 val, vol
+ /* We will be supplying our own /dev/mem implementation */
+ #define ARCH_HAS_DEV_MEM
+ 
+-#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
+-#undef page_to_phys
+-#define page_to_phys(page)	 (phys_to_machine(page_to_pseudophys(page)))
+-#define page_to_bus(page)	 (phys_to_machine(page_to_pseudophys(page)))
+-
+ #define bvec_to_pseudophys(bv)	 (page_to_pseudophys((bv)->bv_page) + \
+ 				  (unsigned long)(bv)->bv_offset)
+ 
+@@ -106,23 +200,7 @@ static inline void writeq(__u64 val, vol
+ 	 && bvec_to_pseudophys(vec1) + (vec1)->bv_len \
+ 	    == bvec_to_pseudophys(vec2))
+ 
+-#undef virt_to_bus
+-#undef bus_to_virt
+-#define virt_to_bus(_x) phys_to_machine(__pa(_x))
+-#define bus_to_virt(_x) __va(machine_to_phys(_x))
+-
+-#include <asm/fixmap.h>
+-
+ #undef __ISA_IO_base
+-#undef isa_virt_to_bus
+-#undef isa_page_to_bus
+-#undef isa_bus_to_virt
+-#define isa_virt_to_bus(_x) ({ \
+-	unsigned long _va_ = (unsigned long)(_x); \
+-	_va_ - fix_to_virt(FIX_ISAMAP_BEGIN) < (NR_FIX_ISAMAPS << PAGE_SHIFT) \
+-	? _va_ - fix_to_virt(FIX_ISAMAP_BEGIN) \
+-	: ({ BUG(); (unsigned long)virt_to_bus(_va_); }); })
+-#define isa_bus_to_virt(_x) ((void *)fix_to_virt(FIX_ISAMAP_BEGIN) + (_x))
+ 
+ #endif
+ 
+@@ -131,7 +209,7 @@ extern void unxlate_dev_mem_ptr(unsigned
+ 
+ extern int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
+ 				     unsigned long prot_val);
+-extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
++extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size);
+ 
+ /*
+  * early_ioremap() and early_iounmap() are for temporary early boot-time
+@@ -140,10 +218,12 @@ extern void __iomem *ioremap_wc(unsigned
+  */
+ extern void early_ioremap_init(void);
+ extern void early_ioremap_reset(void);
+-extern void __iomem *early_ioremap(unsigned long offset, unsigned long size);
+-extern void __iomem *early_memremap(unsigned long offset, unsigned long size);
++extern void __iomem *early_ioremap(resource_size_t phys_addr,
++				   unsigned long size);
++extern void __iomem *early_memremap(resource_size_t phys_addr,
++				    unsigned long size);
+ extern void early_iounmap(void __iomem *addr, unsigned long size);
+-extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
+ 
++#define IO_SPACE_LIMIT 0xffff
+ 
+ #endif /* _ASM_X86_IO_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/ipi.h	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,13 @@
++#ifndef _ASM_X86_IPI_H
++#define _ASM_X86_IPI_H
++
++#include <asm/hw_irq.h>
++#include <asm/smp.h>
++
++void xen_send_IPI_mask(const struct cpumask *, int vector);
++void xen_send_IPI_mask_allbutself(const struct cpumask *, int vector);
++void xen_send_IPI_allbutself(int vector);
++void xen_send_IPI_all(int vector);
++void xen_send_IPI_self(int vector);
++
++#endif /* _ASM_X86_IPI_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:52:02.000000000 +0100
+@@ -94,7 +94,7 @@ static inline void halt(void)
+ 
+ #ifdef CONFIG_X86_64
+ # define __REG_si %rsi
+-# define __CPU_num %gs:pda_cpunumber
++# define __CPU_num PER_CPU_VAR(cpu_number)
+ #else
+ # define __REG_si %esi
+ # define __CPU_num TI_cpu(%ebp)
+@@ -130,6 +130,7 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ 	mov  $__KERNEL_PERCPU, %ecx					; \
+ 	push %esp							; \
+ 	mov  %ecx, %fs							; \
++	SET_KERNEL_GS %ecx						; \
+ 	call evtchn_do_upcall						; \
+ 	add  $4,%esp							; \
+ 	jmp  ret_from_intr
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-12-22 13:20:34.000000000 +0100
+@@ -2,29 +2,46 @@
+ #define _ASM_X86_IRQ_VECTORS_H
+ 
+ #ifdef CONFIG_X86_32
+-# define SYSCALL_VECTOR		0x80
++# define SYSCALL_VECTOR			0x80
+ #else
+-# define IA32_SYSCALL_VECTOR	0x80
++# define IA32_SYSCALL_VECTOR		0x80
+ #endif
+ 
+-#define RESCHEDULE_VECTOR	0
+-#define CALL_FUNCTION_VECTOR	1
+-#define CALL_FUNC_SINGLE_VECTOR 2
+-#define SPIN_UNLOCK_VECTOR	3
+-#define NR_IPIS			4
++#define RESCHEDULE_VECTOR		0
++#define CALL_FUNCTION_VECTOR		1
++#define CALL_FUNC_SINGLE_VECTOR		2
++#define SPIN_UNLOCK_VECTOR		3
++#define NR_IPIS				4
+ 
+ /*
+  * The maximum number of vectors supported by i386 processors
+  * is limited to 256. For processors other than i386, NR_VECTORS
+  * should be changed accordingly.
+  */
+-#define NR_VECTORS		256
++#define NR_VECTORS			 256
+ 
+-#define	FIRST_VM86_IRQ		3
+-#define LAST_VM86_IRQ		15
+-#define invalid_vm86_irq(irq)	((irq) < 3 || (irq) > 15)
++#define	FIRST_VM86_IRQ			   3
++#define LAST_VM86_IRQ			  15
+ 
+-#define NR_IRQS_LEGACY		16
++#ifndef __ASSEMBLY__
++static inline int invalid_vm86_irq(int irq)
++{
++	return irq < FIRST_VM86_IRQ || irq > LAST_VM86_IRQ;
++}
++#endif
++
++/*
++ * Size the maximum number of interrupts.
++ *
++ * If the irq_desc[] array has a sparse layout, we can size things
++ * generously - it scales up linearly with the maximum number of CPUs,
++ * and the maximum number of IO-APICs, whichever is higher.
++ *
++ * In other cases we size more conservatively, to not create too large
++ * static arrays.
++ */
++
++#define NR_IRQS_LEGACY			  16
+ 
+ /*
+  * The flat IRQ space is divided into two regions:
+@@ -35,21 +52,41 @@
+  *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+  *     are bound using the provided bind/unbind functions.
+  */
++#define PIRQ_BASE			0
+ 
+-#define PIRQ_BASE		0
+-#if defined(NR_CPUS) && defined(MAX_IO_APICS)
+-# if !defined(CONFIG_SPARSE_IRQ) && NR_CPUS < MAX_IO_APICS
+-#  define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
+-# elif defined(CONFIG_SPARSE_IRQ) && 8 * NR_CPUS > 32 * MAX_IO_APICS
+-#  define NR_PIRQS		(NR_VECTORS + 8 * NR_CPUS)
++#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
++#define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
++
++#ifdef CONFIG_X86_IO_APIC
++# if !defined(NR_CPUS) || !defined(MAX_IO_APICS)
++/* nothing */
++# elif defined(CONFIG_SPARSE_IRQ)
++#  define NR_PIRQS					\
++	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
++		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
++		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
++# elif NR_CPUS < MAX_IO_APICS
++#  define NR_PIRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
+ # else
+-#  define NR_PIRQS		(NR_VECTORS + 32 * MAX_IO_APICS)
++#  define NR_PIRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
+ # endif
++#elif defined(CONFIG_XEN_PCIDEV_FRONTEND)
++# define NR_PIRQS			(NR_VECTORS + CPU_VECTOR_LIMIT)
++#else /* !CONFIG_X86_IO_APIC: */
++# define NR_PIRQS			NR_IRQS_LEGACY
++#endif
++
++#ifndef __ASSEMBLY__
++#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SPARSE_IRQ)
++extern int nr_pirqs;
++#else
++# define nr_pirqs			NR_PIRQS
++#endif
+ #endif
+ 
+-#define DYNIRQ_BASE		(PIRQ_BASE + NR_PIRQS)
+-#define NR_DYNIRQS		256
++#define DYNIRQ_BASE			(PIRQ_BASE + nr_pirqs)
++#define NR_DYNIRQS			256
+ 
+-#define NR_IRQS			(NR_PIRQS + NR_DYNIRQS)
++#define NR_IRQS				(NR_PIRQS + NR_DYNIRQS)
+ 
+ #endif /* _ASM_X86_IRQ_VECTORS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:52:02.000000000 +0100
+@@ -26,11 +26,117 @@ static inline void xen_activate_mm(struc
+ int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+ void destroy_context(struct mm_struct *mm);
+ 
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
++	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
++		percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
++#endif
++}
++
++#define prepare_arch_switch(next)	__prepare_arch_switch()
++
++static inline void __prepare_arch_switch(void)
++{
+ #ifdef CONFIG_X86_32
+-# include "mmu_context_32.h"
++	/*
++	 * Save away %gs. No need to save %fs, as it was saved on the
++	 * stack on entry.  No need to save %es and %ds, as those are
++	 * always kernel segments while inside the kernel.
++	 */
++	lazy_save_gs(current->thread.gs);
++	lazy_load_gs(__KERNEL_STACK_CANARY);
+ #else
+-# include "mmu_context_64.h"
++	/*
++	 * Save away %es, %ds, %fs and %gs. Must happen before reload
++	 * of cr3/ldt (i.e., not in __switch_to).
++	 */
++	__asm__ __volatile__ (
++		"mov %%es,%0 ; mov %%ds,%1 ; mov %%fs,%2 ; mov %%gs,%3"
++		: "=m" (current->thread.es),
++		  "=m" (current->thread.ds),
++		  "=m" (current->thread.fsindex),
++		  "=m" (current->thread.gsindex) );
++
++	if (current->thread.ds)
++		__asm__ __volatile__ ( "movl %0,%%ds" : : "r" (0) );
++
++	if (current->thread.es)
++		__asm__ __volatile__ ( "movl %0,%%es" : : "r" (0) );
++
++	if (current->thread.fsindex) {
++		__asm__ __volatile__ ( "movl %0,%%fs" : : "r" (0) );
++		current->thread.fs = 0;
++	}
++
++	if (current->thread.gsindex) {
++		load_gs_index(0);
++		current->thread.gs = 0;
++	}
++#endif
++}
++
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
++			     struct task_struct *tsk)
++{
++	unsigned cpu = smp_processor_id();
++	struct mmuext_op _op[2 + (sizeof(long) > 4)], *op = _op;
++
++	if (likely(prev != next)) {
++		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
++		       !PagePinned(virt_to_page(next->pgd)));
++
++		/* stop flush ipis for the previous mm */
++		cpu_clear(cpu, prev->cpu_vm_mask);
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
++		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
++		percpu_write(cpu_tlbstate.active_mm, next);
+ #endif
++		cpu_set(cpu, next->cpu_vm_mask);
++
++		/* Re-load page tables: load_cr3(next->pgd) */
++		op->cmd = MMUEXT_NEW_BASEPTR;
++		op->arg1.mfn = virt_to_mfn(next->pgd);
++		op++;
++
++		/* xen_new_user_pt(__pa(__user_pgd(next->pgd))) */
++#ifdef CONFIG_X86_64
++		op->cmd = MMUEXT_NEW_USER_BASEPTR;
++		op->arg1.mfn = virt_to_mfn(__user_pgd(next->pgd));
++		op++;
++#endif
++
++		/*
++		 * load the LDT, if the LDT is different:
++		 */
++		if (unlikely(prev->context.ldt != next->context.ldt)) {
++			/* load_LDT_nolock(&next->context) */
++			op->cmd = MMUEXT_SET_LDT;
++			op->arg1.linear_addr = (unsigned long)next->context.ldt;
++			op->arg2.nr_ents     = next->context.size;
++			op++;
++		}
++
++		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
++	}
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
++	else {
++		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
++		BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
++
++		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
++			/* We were in lazy tlb mode and leave_mm disabled
++			 * tlb flush IPI delivery. We must reload CR3
++			 * to make sure to use no freed page tables.
++			 */
++			load_cr3(next->pgd);
++			xen_new_user_pt(__pa(__user_pgd(next->pgd)));
++			load_LDT_nolock(&next->context);
++		}
++	}
++#endif
++}
+ 
+ #define activate_mm(prev, next)			\
+ do {						\
+@@ -38,5 +144,17 @@ do {						\
+ 	switch_mm((prev), (next), NULL);	\
+ } while (0);
+ 
++#ifdef CONFIG_X86_32
++#define deactivate_mm(tsk, mm)			\
++do {						\
++	lazy_load_gs(0);			\
++} while (0)
++#else
++#define deactivate_mm(tsk, mm)			\
++do {						\
++	load_gs_index(0);			\
++	loadsegment(fs, 0);			\
++} while (0)
++#endif
+ 
+ #endif /* _ASM_X86_MMU_CONTEXT_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:55.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,83 +0,0 @@
+-#ifndef _ASM_X86_MMU_CONTEXT_32_H
+-#define _ASM_X86_MMU_CONTEXT_32_H
+-
+-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+-{
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+-	if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK)
+-		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_LAZY);
+-#endif
+-}
+-
+-#define prepare_arch_switch(next)	__prepare_arch_switch()
+-
+-static inline void __prepare_arch_switch(void)
+-{
+-	/*
+-	 * Save away %gs. No need to save %fs, as it was saved on the
+-	 * stack on entry.  No need to save %es and %ds, as those are
+-	 * always kernel segments while inside the kernel.
+-	 */
+-	asm volatile ( "mov %%gs,%0"
+-		: "=m" (current->thread.gs));
+-	asm volatile ( "movl %0,%%gs"
+-		: : "r" (0) );
+-}
+-
+-static inline void switch_mm(struct mm_struct *prev,
+-			     struct mm_struct *next,
+-			     struct task_struct *tsk)
+-{
+-	int cpu = smp_processor_id();
+-	struct mmuext_op _op[2], *op = _op;
+-
+-	if (likely(prev != next)) {
+-		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+-		       !PagePinned(virt_to_page(next->pgd)));
+-
+-		/* stop flush ipis for the previous mm */
+-		cpu_clear(cpu, prev->cpu_vm_mask);
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+-		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK);
+-		x86_write_percpu(cpu_tlbstate.active_mm, next);
+-#endif
+-		cpu_set(cpu, next->cpu_vm_mask);
+-
+-		/* Re-load page tables: load_cr3(next->pgd) */
+-		op->cmd = MMUEXT_NEW_BASEPTR;
+-		op->arg1.mfn = pfn_to_mfn(__pa(next->pgd) >> PAGE_SHIFT);
+-		op++;
+-
+-		/*
+-		 * load the LDT, if the LDT is different:
+-		 */
+-		if (unlikely(prev->context.ldt != next->context.ldt)) {
+-			/* load_LDT_nolock(&next->context, cpu) */
+-			op->cmd = MMUEXT_SET_LDT;
+-			op->arg1.linear_addr = (unsigned long)next->context.ldt;
+-			op->arg2.nr_ents     = next->context.size;
+-			op++;
+-		}
+-
+-		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
+-	}
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+-	else {
+-		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK);
+-		BUG_ON(x86_read_percpu(cpu_tlbstate.active_mm) != next);
+-
+-		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled
+-			 * tlb flush IPI delivery. We must reload %cr3.
+-			 */
+-			load_cr3(next->pgd);
+-			load_LDT_nolock(&next->context);
+-		}
+-	}
+-#endif
+-}
+-
+-#define deactivate_mm(tsk, mm)			\
+-	asm("movl %0,%%gs": :"r" (0));
+-
+-#endif /* _ASM_X86_MMU_CONTEXT_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:47.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,106 +0,0 @@
+-#ifndef _ASM_X86_MMU_CONTEXT_64_H
+-#define _ASM_X86_MMU_CONTEXT_64_H
+-
+-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+-{
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-	if (read_pda(mmu_state) == TLBSTATE_OK)
+-		write_pda(mmu_state, TLBSTATE_LAZY);
+-#endif
+-}
+-
+-#define prepare_arch_switch(next)	__prepare_arch_switch()
+-
+-static inline void __prepare_arch_switch(void)
+-{
+-	/*
+-	 * Save away %es, %ds, %fs and %gs. Must happen before reload
+-	 * of cr3/ldt (i.e., not in __switch_to).
+-	 */
+-	__asm__ __volatile__ (
+-		"mov %%es,%0 ; mov %%ds,%1 ; mov %%fs,%2 ; mov %%gs,%3"
+-		: "=m" (current->thread.es),
+-		  "=m" (current->thread.ds),
+-		  "=m" (current->thread.fsindex),
+-		  "=m" (current->thread.gsindex) );
+-
+-	if (current->thread.ds)
+-		__asm__ __volatile__ ( "movl %0,%%ds" : : "r" (0) );
+-
+-	if (current->thread.es)
+-		__asm__ __volatile__ ( "movl %0,%%es" : : "r" (0) );
+-
+-	if (current->thread.fsindex) {
+-		__asm__ __volatile__ ( "movl %0,%%fs" : : "r" (0) );
+-		current->thread.fs = 0;
+-	}
+-
+-	if (current->thread.gsindex) {
+-		load_gs_index(0);
+-		current->thread.gs = 0;
+-	}
+-}
+-
+-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+-			     struct task_struct *tsk)
+-{
+-	unsigned cpu = smp_processor_id();
+-	struct mmuext_op _op[3], *op = _op;
+-
+-	if (likely(prev != next)) {
+-		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+-		       !PagePinned(virt_to_page(next->pgd)));
+-
+-		/* stop flush ipis for the previous mm */
+-		cpu_clear(cpu, prev->cpu_vm_mask);
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-		write_pda(mmu_state, TLBSTATE_OK);
+-		write_pda(active_mm, next);
+-#endif
+-		cpu_set(cpu, next->cpu_vm_mask);
+-
+-		/* load_cr3(next->pgd) */
+-		op->cmd = MMUEXT_NEW_BASEPTR;
+-		op->arg1.mfn = pfn_to_mfn(__pa(next->pgd) >> PAGE_SHIFT);
+-		op++;
+-
+-		/* xen_new_user_pt(__pa(__user_pgd(next->pgd))) */
+-		op->cmd = MMUEXT_NEW_USER_BASEPTR;
+-		op->arg1.mfn = pfn_to_mfn(__pa(__user_pgd(next->pgd)) >> PAGE_SHIFT);
+-		op++;
+-		
+-		if (unlikely(next->context.ldt != prev->context.ldt)) {
+-			/* load_LDT_nolock(&next->context) */
+-			op->cmd = MMUEXT_SET_LDT;
+-			op->arg1.linear_addr = (unsigned long)next->context.ldt;
+-			op->arg2.nr_ents     = next->context.size;
+-			op++;
+-		}
+-
+-		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
+-	}
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-	else {
+-		write_pda(mmu_state, TLBSTATE_OK);
+-		if (read_pda(active_mm) != next)
+-			BUG();
+-		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled
+-			 * tlb flush IPI delivery. We must reload CR3
+-			 * to make sure to use no freed page tables.
+-			 */
+-                        load_cr3(next->pgd);
+-                        xen_new_user_pt(__pa(__user_pgd(next->pgd)));		
+-			load_LDT_nolock(&next->context);
+-		}
+-	}
+-#endif
+-}
+-
+-#define deactivate_mm(tsk, mm)			\
+-do {						\
+-	load_gs_index(0);			\
+-	asm volatile("movl %0,%%fs"::"r"(0));	\
+-} while (0)
+-
+-#endif /* _ASM_X86_MMU_CONTEXT_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:52:02.000000000 +0100
+@@ -41,7 +41,6 @@ static inline int pci_proc_domain(struct
+ 	return pci_domain_nr(bus);
+ }
+ 
+-extern void pci_iommu_alloc(void);
+ 
+ /* Can be used to override the logic in pci_scan_bus for skipping
+    already-configured bus numbers - to be used for buggy BIOSes
+@@ -92,12 +91,44 @@ static inline void early_quirks(void) { 
+ 
+ extern void pci_iommu_alloc(void);
+ 
+-#endif  /* __KERNEL__ */
++/* MSI arch hooks */
++#define arch_setup_msi_irqs arch_setup_msi_irqs
++#define arch_teardown_msi_irqs arch_teardown_msi_irqs
++
++#define PCI_DMA_BUS_IS_PHYS 0
++
++#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG) || defined(CONFIG_SWIOTLB)
++
++#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
++	        dma_addr_t ADDR_NAME;
++#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)         \
++	        __u32 LEN_NAME;
++#define pci_unmap_addr(PTR, ADDR_NAME)                  \
++	        ((PTR)->ADDR_NAME)
++#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)         \
++	        (((PTR)->ADDR_NAME) = (VAL))
++#define pci_unmap_len(PTR, LEN_NAME)                    \
++	        ((PTR)->LEN_NAME)
++#define pci_unmap_len_set(PTR, LEN_NAME, VAL)           \
++	        (((PTR)->LEN_NAME) = (VAL))
+ 
+-#ifdef CONFIG_X86_32
+-# include "pci_32.h"
+ #else
+-# include "../../asm/pci_64.h"
++
++#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       dma_addr_t ADDR_NAME[0];
++#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0];
++#define pci_unmap_addr(PTR, ADDR_NAME)  sizeof((PTR)->ADDR_NAME)
++#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
++	        do { break; } while (pci_unmap_addr(PTR, ADDR_NAME))
++#define pci_unmap_len(PTR, LEN_NAME)            sizeof((PTR)->LEN_NAME)
++#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
++	        do { break; } while (pci_unmap_len(PTR, LEN_NAME))
++
++#endif
++
++#endif  /* __KERNEL__ */
++
++#ifdef CONFIG_X86_64
++#include "../../asm/pci_64.h"
+ #endif
+ 
+ /* implement the pci_ DMA API in terms of the generic device dma_ one */
+@@ -115,11 +146,6 @@ static inline int __pcibus_to_node(const
+ 	return sd->node;
+ }
+ 
+-static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus)
+-{
+-	return node_to_cpumask(__pcibus_to_node(bus));
+-}
+-
+ static inline const struct cpumask *
+ cpumask_of_pcibus(const struct pci_bus *bus)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-20 11:15:54.000000000 +0100
+@@ -1,178 +1,9 @@
+ #ifndef _ASM_X86_PGTABLE_H
+ #define _ASM_X86_PGTABLE_H
+ 
+-#define FIRST_USER_ADDRESS	0
++#include <asm/page.h>
+ 
+-#define _PAGE_BIT_PRESENT	0	/* is present */
+-#define _PAGE_BIT_RW		1	/* writeable */
+-#define _PAGE_BIT_USER		2	/* userspace addressable */
+-#define _PAGE_BIT_PWT		3	/* page write through */
+-#define _PAGE_BIT_PCD		4	/* page cache disabled */
+-#define _PAGE_BIT_ACCESSED	5	/* was accessed (raised by CPU) */
+-#define _PAGE_BIT_DIRTY		6	/* was written to (raised by CPU) */
+-#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+-#define _PAGE_BIT_PAT		7	/* on 4KB pages */
+-#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+-#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
+-#define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
+-#define _PAGE_BIT_UNUSED3	11
+-#define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
+-#define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
+-#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
+-#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+-
+-/* If _PAGE_BIT_PRESENT is clear, we use these: */
+-/* - if the user mapped it with PROT_NONE; pte_present gives true */
+-#define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
+-/* - set: nonlinear file mapping, saved PTE; unset:swap */
+-#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
+-
+-#define _PAGE_PRESENT	(_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
+-#define _PAGE_RW	(_AT(pteval_t, 1) << _PAGE_BIT_RW)
+-#define _PAGE_USER	(_AT(pteval_t, 1) << _PAGE_BIT_USER)
+-#define _PAGE_PWT	(_AT(pteval_t, 1) << _PAGE_BIT_PWT)
+-#define _PAGE_PCD	(_AT(pteval_t, 1) << _PAGE_BIT_PCD)
+-#define _PAGE_ACCESSED	(_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED)
+-#define _PAGE_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
+-#define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
+-#define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
+-#define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
+-#define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
+-#define _PAGE_UNUSED3	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
+-#define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
+-#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+-#define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
+-#define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
+-#define __HAVE_ARCH_PTE_SPECIAL
+-
+-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+-#define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
+-#else
+-#define _PAGE_NX	(_AT(pteval_t, 0))
+-#endif
+-
+-#define _PAGE_FILE	(_AT(pteval_t, 1) << _PAGE_BIT_FILE)
+-#define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
+-
+-#ifndef __ASSEMBLY__
+-#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
+-extern unsigned int __kernel_page_user;
+-#else
+-#define __kernel_page_user 0
+-#endif
+-#endif
+-
+-#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)
+-
+-/* Set of bits not changed in pte_modify */
+-#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IOMAP | \
+-			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+-
+-/*
+- * PAT settings are part of the hypervisor interface, which sets the
+- * MSR to 0x050100070406 (i.e. WB, WT, UC-, UC, WC, WP [, UC, UC]).
+- */
+-#define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT | _PAGE_PAT)
+-#define _PAGE_CACHE_WB		(0)
+-#define _PAGE_CACHE_WT		(_PAGE_PWT)
+-#define _PAGE_CACHE_WC		(_PAGE_PAT)
+-#define _PAGE_CACHE_WP		(_PAGE_PAT | _PAGE_PWT)
+-#define _PAGE_CACHE_UC_MINUS	(_PAGE_PCD)
+-#define _PAGE_CACHE_UC		(_PAGE_PCD | _PAGE_PWT)
+-
+-#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
+-				 _PAGE_ACCESSED | _PAGE_NX)
+-
+-#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW |	\
+-					 _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+-					 _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+-					 _PAGE_ACCESSED)
+-#define PAGE_COPY		PAGE_COPY_NOEXEC
+-#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+-					 _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+-					 _PAGE_ACCESSED)
+-
+-#define __PAGE_KERNEL_EXEC						\
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
+-#define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
+-
+-#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+-#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+-#define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
+-#define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
+-#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+-#define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
+-#define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+-#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+-#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
+-#define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+-#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+-
+-#define __PAGE_KERNEL_IO		(__PAGE_KERNEL | _PAGE_IOMAP)
+-#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
+-#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
+-#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC | _PAGE_IOMAP)
+-
+-#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
+-#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
+-#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
+-#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
+-#define PAGE_KERNEL_WC			__pgprot(__PAGE_KERNEL_WC)
+-#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
+-#define PAGE_KERNEL_UC_MINUS		__pgprot(__PAGE_KERNEL_UC_MINUS)
+-#define PAGE_KERNEL_EXEC_NOCACHE	__pgprot(__PAGE_KERNEL_EXEC_NOCACHE)
+-#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
+-#define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
+-#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+-#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
+-#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+-
+-#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
+-#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+-#define PAGE_KERNEL_IO_UC_MINUS		__pgprot(__PAGE_KERNEL_IO_UC_MINUS)
+-#define PAGE_KERNEL_IO_WC		__pgprot(__PAGE_KERNEL_IO_WC)
+-
+-/*         xwr */
+-#define __P000	PAGE_NONE
+-#define __P001	PAGE_READONLY
+-#define __P010	PAGE_COPY
+-#define __P011	PAGE_COPY
+-#define __P100	PAGE_READONLY_EXEC
+-#define __P101	PAGE_READONLY_EXEC
+-#define __P110	PAGE_COPY_EXEC
+-#define __P111	PAGE_COPY_EXEC
+-
+-#define __S000	PAGE_NONE
+-#define __S001	PAGE_READONLY
+-#define __S010	PAGE_SHARED
+-#define __S011	PAGE_SHARED
+-#define __S100	PAGE_READONLY_EXEC
+-#define __S101	PAGE_READONLY_EXEC
+-#define __S110	PAGE_SHARED_EXEC
+-#define __S111	PAGE_SHARED_EXEC
+-
+-/*
+- * early identity mapping  pte attrib macros.
+- */
+-#ifdef CONFIG_X86_64
+-#define __PAGE_KERNEL_IDENT_LARGE_EXEC	__PAGE_KERNEL_LARGE_EXEC
+-#else
+-/*
+- * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
+- * bits are combined, this will alow user to access the high address mapped
+- * VDSO in the presence of CONFIG_COMPAT_VDSO
+- */
+-#define PTE_IDENT_ATTR	 0x003		/* PRESENT+RW */
+-#define PDE_IDENT_ATTR	 0x067		/* PRESENT+RW+USER+DIRTY+ACCESSED */
+-#define PGD_IDENT_ATTR	 0x001		/* PRESENT (no other attributes) */
+-#endif
++#include <asm/pgtable_types.h>
+ 
+ /*
+  * Macro to mark a page protection value as UC-
+@@ -184,9 +15,6 @@ extern unsigned int __kernel_page_user;
+ 
+ #ifndef __ASSEMBLY__
+ 
+-#define pgprot_writecombine	pgprot_writecombine
+-extern pgprot_t pgprot_writecombine(pgprot_t prot);
+-
+ /*
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+@@ -197,6 +25,59 @@ extern unsigned long empty_zero_page[PAG
+ extern spinlock_t pgd_lock;
+ extern struct list_head pgd_list;
+ 
++#define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
++#define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
++
++#define set_pte_atomic(ptep, pte)					\
++	xen_set_pte_atomic(ptep, pte)
++
++#define set_pmd(pmdp, pmd)		xen_set_pmd(pmdp, pmd)
++
++#ifndef __PAGETABLE_PUD_FOLDED
++#define set_pgd(pgdp, pgd)		xen_set_pgd(pgdp, pgd)
++#define pgd_clear(pgd)			xen_pgd_clear(pgd)
++#endif
++
++#ifndef set_pud
++# define set_pud(pudp, pud)		xen_set_pud(pudp, pud)
++#endif
++
++#ifndef __PAGETABLE_PMD_FOLDED
++#define pud_clear(pud)			xen_pud_clear(pud)
++#endif
++
++#define pte_clear(mm, addr, ptep)	xen_pte_clear(mm, addr, ptep)
++#define pmd_clear(pmd)			xen_pmd_clear(pmd)
++
++#define pte_update(mm, addr, ptep)              do { } while (0)
++#define pte_update_defer(mm, addr, ptep)        do { } while (0)
++
++static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
++{
++	xen_pagetable_setup_start(base);
++}
++
++static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
++{
++	xen_pagetable_setup_done(base);
++}
++
++#define pgd_val(x)	xen_pgd_val(x)
++#define __pgd(x)	xen_make_pgd(x)
++
++#ifndef __PAGETABLE_PUD_FOLDED
++#define pud_val(x)	xen_pud_val(x)
++#define __pud(x)	xen_make_pud(x)
++#endif
++
++#ifndef __PAGETABLE_PMD_FOLDED
++#define pmd_val(x)	xen_pmd_val(x)
++#define __pmd(x)	xen_make_pmd(x)
++#endif
++
++#define pte_val(x)	xen_pte_val(x)
++#define __pte(x)	xen_make_pte(x)
++
+ /*
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+@@ -252,53 +133,67 @@ static inline int pte_special(pte_t pte)
+ 
+ static inline int pmd_large(pmd_t pte)
+ {
+-	return (__pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++	return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+ 		(_PAGE_PSE | _PAGE_PRESENT);
+ }
+ 
++static inline pte_t pte_set_flags(pte_t pte, pteval_t set)
++{
++	pteval_t v = __pte_val(pte);
++
++	return __pte_ma(v | set);
++}
++
++static inline pte_t pte_clear_flags(pte_t pte, pteval_t clear)
++{
++	pteval_t v = __pte_val(pte);
++
++	return __pte_ma(v & ~clear);
++}
++
+ static inline pte_t pte_mkclean(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~_PAGE_DIRTY);
++	return pte_clear_flags(pte, _PAGE_DIRTY);
+ }
+ 
+ static inline pte_t pte_mkold(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~_PAGE_ACCESSED);
++	return pte_clear_flags(pte, _PAGE_ACCESSED);
+ }
+ 
+ static inline pte_t pte_wrprotect(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~_PAGE_RW);
++	return pte_clear_flags(pte, _PAGE_RW);
+ }
+ 
+ static inline pte_t pte_mkexec(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~_PAGE_NX);
++	return pte_clear_flags(pte, _PAGE_NX);
+ }
+ 
+ static inline pte_t pte_mkdirty(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) | _PAGE_DIRTY);
++	return pte_set_flags(pte, _PAGE_DIRTY);
+ }
+ 
+ static inline pte_t pte_mkyoung(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) | _PAGE_ACCESSED);
++	return pte_set_flags(pte, _PAGE_ACCESSED);
+ }
+ 
+ static inline pte_t pte_mkwrite(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) | _PAGE_RW);
++	return pte_set_flags(pte, _PAGE_RW);
+ }
+ 
+ static inline pte_t pte_mkhuge(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) | _PAGE_PSE);
++	return pte_set_flags(pte, _PAGE_PSE);
+ }
+ 
+ static inline pte_t pte_clrhuge(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~_PAGE_PSE);
++	return pte_clear_flags(pte, _PAGE_PSE);
+ }
+ 
+ static inline pte_t pte_mkglobal(pte_t pte)
+@@ -313,11 +208,9 @@ static inline pte_t pte_clrglobal(pte_t 
+ 
+ static inline pte_t pte_mkspecial(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) | _PAGE_SPECIAL);
++	return pte_set_flags(pte, _PAGE_SPECIAL);
+ }
+ 
+-extern pteval_t __supported_pte_mask;
+-
+ /*
+  * Mask out unsupported bits in a present pgprot.  Non-present pgprots
+  * can use those bits for other purposes, so leave them be.
+@@ -391,68 +284,208 @@ static inline int is_new_memtype_allowed
+ 	return 1;
+ }
+ 
+-#ifndef __ASSEMBLY__
+-#ifndef CONFIG_XEN
+-/* Indicate that x86 has its own track and untrack pfn vma functions */
+-#define __HAVE_PFNMAP_TRACKING
+-#endif
++pmd_t *populate_extra_pmd(unsigned long vaddr);
++pte_t *populate_extra_pte(unsigned long vaddr);
++#endif	/* __ASSEMBLY__ */
+ 
+-#define __HAVE_PHYS_MEM_ACCESS_PROT
+-struct file;
+-pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+-                              unsigned long size, pgprot_t vma_prot);
+-int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+-                              unsigned long size, pgprot_t *vma_prot);
++#ifdef CONFIG_X86_32
++# include "pgtable_32.h"
++#else
++# include "pgtable_64.h"
+ #endif
+ 
+-/* Install a pte for a particular vaddr in kernel space. */
+-void set_pte_vaddr(unsigned long vaddr, pte_t pte);
++#ifndef __ASSEMBLY__
++#include <linux/mm_types.h>
+ 
+-#ifndef CONFIG_XEN
+-extern void native_pagetable_setup_start(pgd_t *base);
+-extern void native_pagetable_setup_done(pgd_t *base);
++static inline int pte_none(pte_t pte)
++{
++	return !pte.pte;
++}
++
++#define __HAVE_ARCH_PTE_SAME
++static inline int pte_same(pte_t a, pte_t b)
++{
++	return a.pte == b.pte;
++}
++
++static inline int pte_present(pte_t a)
++{
++	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
++}
++
++static inline int pmd_present(pmd_t pmd)
++{
++#if CONFIG_XEN_COMPAT <= 0x030002
++/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
++   can temporarily clear it. */
++	return __pmd_val(pmd) != 0;
+ #else
+-static inline void xen_pagetable_setup_start(pgd_t *base) {}
+-static inline void xen_pagetable_setup_done(pgd_t *base) {}
++	return pmd_flags(pmd) & _PAGE_PRESENT;
+ #endif
++}
+ 
+-struct seq_file;
+-extern void arch_report_meminfo(struct seq_file *m);
++static inline int pmd_none(pmd_t pmd)
++{
++	/* Only check low word on 32-bit platforms, since it might be
++	   out of sync with upper half. */
++	return (unsigned long)__pmd_val(pmd) == 0;
++}
+ 
+-#define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
+-#define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
++static inline unsigned long pmd_page_vaddr(pmd_t pmd)
++{
++	return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK);
++}
+ 
+-#define set_pte_atomic(ptep, pte)					\
+-	xen_set_pte_atomic(ptep, pte)
++/*
++ * Currently stuck as a macro due to indirect forward reference to
++ * linux/mmzone.h's __section_mem_map_addr() definition:
++ */
++#define pmd_page(pmd)	pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+ 
+-#define set_pmd(pmdp, pmd)		xen_set_pmd(pmdp, pmd)
++/*
++ * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
++ *
++ * this macro returns the index of the entry in the pmd page which would
++ * control the given virtual address
++ */
++static inline unsigned pmd_index(unsigned long address)
++{
++	return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
++}
+ 
+-#ifndef __PAGETABLE_PUD_FOLDED
+-#define set_pgd(pgdp, pgd)		xen_set_pgd(pgdp, pgd)
+-#define pgd_clear(pgd)			xen_pgd_clear(pgd)
+-#endif
++/*
++ * Conversion functions: convert a page and protection to a page entry,
++ * and a page entry and page directory to the page they refer to.
++ *
++ * (Currently stuck as a macro because of indirect forward reference
++ * to linux/mm.h:page_to_nid())
++ */
++#define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
+ 
+-#ifndef set_pud
+-# define set_pud(pudp, pud)		xen_set_pud(pudp, pud)
+-#endif
++/*
++ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
++ *
++ * this function returns the index of the entry in the pte page which would
++ * control the given virtual address
++ */
++static inline unsigned pte_index(unsigned long address)
++{
++	return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
++}
+ 
+-#ifndef __PAGETABLE_PMD_FOLDED
+-#define pud_clear(pud)			xen_pud_clear(pud)
++static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
++{
++	return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address);
++}
++
++static inline int pmd_bad(pmd_t pmd)
++{
++#if CONFIG_XEN_COMPAT <= 0x030002
++	return (pmd_flags(pmd) & ~_PAGE_USER & ~_PAGE_PRESENT)
++	       != (_KERNPG_TABLE & ~_PAGE_PRESENT);
++#else
++	return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE;
+ #endif
++}
+ 
+-#define pte_clear(mm, addr, ptep)	xen_pte_clear(mm, addr, ptep)
+-#define pmd_clear(pmd)			xen_pmd_clear(pmd)
++static inline unsigned long pages_to_mb(unsigned long npg)
++{
++	return npg >> (20 - PAGE_SHIFT);
++}
+ 
+-#define pte_update(mm, addr, ptep)              do { } while (0)
+-#define pte_update_defer(mm, addr, ptep)        do { } while (0)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
++	direct_remap_pfn_range(vma, vaddr, pfn, size, prot, DOMID_IO)
+ 
+-#endif	/* __ASSEMBLY__ */
++#if PAGETABLE_LEVELS > 2
++static inline int pud_none(pud_t pud)
++{
++	return __pud_val(pud) == 0;
++}
+ 
+-#ifdef CONFIG_X86_32
+-# include "pgtable_32.h"
++static inline int pud_present(pud_t pud)
++{
++	return pud_flags(pud) & _PAGE_PRESENT;
++}
++
++static inline unsigned long pud_page_vaddr(pud_t pud)
++{
++	return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK);
++}
++
++/*
++ * Currently stuck as a macro due to indirect forward reference to
++ * linux/mmzone.h's __section_mem_map_addr() definition:
++ */
++#define pud_page(pud)		pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
++
++/* Find an entry in the second-level page table.. */
++static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
++{
++	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
++}
++
++static inline unsigned long pmd_pfn(pmd_t pmd)
++{
++	return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
++}
++
++static inline int pud_large(pud_t pud)
++{
++	return (__pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++		(_PAGE_PSE | _PAGE_PRESENT);
++}
++
++static inline int pud_bad(pud_t pud)
++{
++	return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0;
++}
+ #else
+-# include "pgtable_64.h"
+-#endif
++static inline int pud_large(pud_t pud)
++{
++	return 0;
++}
++#endif	/* PAGETABLE_LEVELS > 2 */
++
++#if PAGETABLE_LEVELS > 3
++static inline int pgd_present(pgd_t pgd)
++{
++	return pgd_flags(pgd) & _PAGE_PRESENT;
++}
++
++static inline unsigned long pgd_page_vaddr(pgd_t pgd)
++{
++	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
++}
++
++/*
++ * Currently stuck as a macro due to indirect forward reference to
++ * linux/mmzone.h's __section_mem_map_addr() definition:
++ */
++#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
++
++/* to find an entry in a page-table-directory. */
++static inline unsigned pud_index(unsigned long address)
++{
++	return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
++}
++
++static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
++{
++	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address);
++}
++
++static inline int pgd_bad(pgd_t pgd)
++{
++	return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE;
++}
++
++static inline int pgd_none(pgd_t pgd)
++{
++	return !__pgd_val(pgd);
++}
++#endif	/* PAGETABLE_LEVELS > 3 */
++
++#endif	/* __ASSEMBLY__ */
+ 
+ /*
+  * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+@@ -479,28 +512,6 @@ extern void arch_report_meminfo(struct s
+ 
+ #ifndef __ASSEMBLY__
+ 
+-enum {
+-	PG_LEVEL_NONE,
+-	PG_LEVEL_4K,
+-	PG_LEVEL_2M,
+-	PG_LEVEL_1G,
+-	PG_LEVEL_NUM
+-};
+-
+-#ifdef CONFIG_PROC_FS
+-extern void update_page_count(int level, unsigned long pages);
+-#else
+-static inline void update_page_count(int level, unsigned long pages) { }
+-#endif
+-
+-/*
+- * Helper function that returns the kernel pagetable entry controlling
+- * the virtual address 'address'. NULL means no pagetable entry present.
+- * NOTE: the return type is pte_t but if the pmd is PSE then we return it
+- * as a pte too.
+- */
+-extern pte_t *lookup_address(unsigned long address, unsigned int *level);
+-
+ /* local pte updates need not use xchg for locking */
+ static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+@@ -633,15 +644,18 @@ static inline void clone_pgd_range(pgd_t
+        memcpy(dst, src, count * sizeof(pgd_t));
+ }
+ 
+-#define arbitrary_virt_to_machine(va)					\
++#define arbitrary_virt_to_mfn(va)					\
+ ({									\
+ 	unsigned int __lvl;						\
+ 	pte_t *__ptep = lookup_address((unsigned long)(va), &__lvl);	\
+ 	BUG_ON(!__ptep || __lvl != PG_LEVEL_4K || !pte_present(*__ptep));\
+-	(((maddr_t)pte_mfn(*__ptep) << PAGE_SHIFT)			\
+-	 | ((unsigned long)(va) & (PAGE_SIZE - 1)));			\
++	pte_mfn(*__ptep);						\
+ })
+ 
++#define arbitrary_virt_to_machine(va)					\
++	(((maddr_t)arbitrary_virt_to_mfn(va) << PAGE_SHIFT)		\
++	 | ((unsigned long)(va) & (PAGE_SIZE - 1)))
++
+ #ifdef CONFIG_HIGHPTE
+ #include <asm/io.h>
+ struct page *kmap_atomic_to_page(void *);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:52:02.000000000 +0100
+@@ -20,21 +20,6 @@
+ 	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+ 	       (pgd_val(e) & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
+-static inline int pud_none(pud_t pud)
+-{
+-	return __pud_val(pud) == 0;
+-
+-}
+-static inline int pud_bad(pud_t pud)
+-{
+-	return (__pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+-}
+-
+-static inline int pud_present(pud_t pud)
+-{
+-	return __pud_val(pud) & _PAGE_PRESENT;
+-}
+-
+ /* Rules for using set_pte: the pte being assigned *must* be
+  * either not present or in a state where the hardware will
+  * not attempt to update the pte.  In places where this is
+@@ -102,15 +87,6 @@ static inline void pud_clear(pud_t *pudp
+ 		xen_tlb_flush();
+ }
+ 
+-#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
+-
+-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK))
+-
+-
+-/* Find an entry in the second-level page table.. */
+-#define pmd_offset(pud, address) ((pmd_t *)pud_page_vaddr(*(pud)) +	\
+-				  pmd_index(address))
+-
+ #ifdef CONFIG_SMP
+ static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+@@ -127,17 +103,6 @@ static inline pte_t xen_ptep_get_and_cle
+ #define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
+ #endif
+ 
+-#define __HAVE_ARCH_PTE_SAME
+-static inline int pte_same(pte_t a, pte_t b)
+-{
+-	return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
+-}
+-
+-static inline int pte_none(pte_t pte)
+-{
+-	return !(pte.pte_low | pte.pte_high);
+-}
+-
+ #define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+ 			 ((_pte).pte_high << (32-PAGE_SHIFT)))
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2009-11-06 10:51:47.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,24 +0,0 @@
+-#ifndef _ASM_X86_PGTABLE_3LEVEL_DEFS_H
+-#define _ASM_X86_PGTABLE_3LEVEL_DEFS_H
+-
+-#define SHARED_KERNEL_PMD	0
+-
+-/*
+- * PGDIR_SHIFT determines what a top-level page table entry can map
+- */
+-#define PGDIR_SHIFT	30
+-#define PTRS_PER_PGD	4
+-
+-/*
+- * PMD_SHIFT determines the size of the area a middle-level
+- * page table can map
+- */
+-#define PMD_SHIFT	21
+-#define PTRS_PER_PMD	512
+-
+-/*
+- * entries per page directory level
+- */
+-#define PTRS_PER_PTE	512
+-
+-#endif /* _ASM_X86_PGTABLE_3LEVEL_DEFS_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level_types.h	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,44 @@
++#ifndef _ASM_X86_PGTABLE_3LEVEL_DEFS_H
++#define _ASM_X86_PGTABLE_3LEVEL_DEFS_H
++
++#ifndef __ASSEMBLY__
++#include <linux/types.h>
++
++typedef u64	pteval_t;
++typedef u64	pmdval_t;
++typedef u64	pudval_t;
++typedef u64	pgdval_t;
++typedef u64	pgprotval_t;
++
++typedef union {
++	struct {
++		unsigned long pte_low, pte_high;
++	};
++	pteval_t pte;
++} pte_t;
++#endif	/* !__ASSEMBLY__ */
++
++#define SHARED_KERNEL_PMD	0
++
++#define PAGETABLE_LEVELS	3
++
++/*
++ * PGDIR_SHIFT determines what a top-level page table entry can map
++ */
++#define PGDIR_SHIFT	30
++#define PTRS_PER_PGD	4
++
++/*
++ * PMD_SHIFT determines the size of the area a middle-level
++ * page table can map
++ */
++#define PMD_SHIFT	21
++#define PTRS_PER_PMD	512
++
++/*
++ * entries per page directory level
++ */
++#define PTRS_PER_PTE	512
++
++
++#endif /* _ASM_X86_PGTABLE_3LEVEL_DEFS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:52:02.000000000 +0100
+@@ -1,6 +1,8 @@
+ #ifndef _ASM_X86_PGTABLE_32_H
+ #define _ASM_X86_PGTABLE_32_H
+ 
++#include <asm/pgtable_32_types.h>
++
+ /*
+  * The Linux memory management assumes a three-level page table setup. On
+  * the i386, we use that, but "fold" the mid level into the top-level page
+@@ -31,47 +33,6 @@ void paging_init(void);
+ 
+ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t);
+ 
+-/*
+- * The Linux x86 paging architecture is 'compile-time dual-mode', it
+- * implements both the traditional 2-level x86 page tables and the
+- * newer 3-level PAE-mode page tables.
+- */
+-#ifdef CONFIG_X86_PAE
+-# include <asm/pgtable-3level-defs.h>
+-# define PMD_SIZE	(1UL << PMD_SHIFT)
+-# define PMD_MASK	(~(PMD_SIZE - 1))
+-#else
+-# include <asm/pgtable-2level-defs.h>
+-#endif
+-
+-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+-
+-/* Just any arbitrary offset to the start of the vmalloc VM area: the
+- * current 8MB value just means that there will be a 8MB "hole" after the
+- * physical memory until the kernel virtual memory starts.  That means that
+- * any out-of-bounds memory accesses will hopefully be caught.
+- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+- * area for the same reason. ;)
+- */
+-#define VMALLOC_OFFSET	(8 * 1024 * 1024)
+-#define VMALLOC_START	((unsigned long)high_memory + VMALLOC_OFFSET)
+-#ifdef CONFIG_X86_PAE
+-#define LAST_PKMAP 512
+-#else
+-#define LAST_PKMAP 1024
+-#endif
+-
+-#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1))	\
+-		    & PMD_MASK)
+-
+-#ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END	(PKMAP_BASE - 2 * PAGE_SIZE)
+-#else
+-# define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
+-#endif
+-
+-#define MAXMEM	(VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE)
+ 
+ /*
+  * Define this if things work differently on an i386 and an i486:
+@@ -80,66 +41,12 @@ extern void set_pmd_pfn(unsigned long, u
+  */
+ #undef TEST_ACCESS_OK
+ 
+-/* The boot page tables (all created as a single array) */
+-extern unsigned long pg0[];
+-
+-#define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
+-
+-/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
+-#define pmd_none(x)	(!(unsigned long)__pmd_val(x))
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+-   can temporarily clear it. */
+-#define pmd_present(x)	(__pmd_val(x))
+-#define pmd_bad(x)	((__pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
+-#else
+-#define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+-#define pmd_bad(x)	((__pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+-#endif
+-
+-
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+-
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level.h>
+ #else
+ # include <asm/pgtable-2level.h>
+ #endif
+ 
+-/*
+- * Conversion functions: convert a page and protection to a page entry,
+- * and a page entry and page directory to the page they refer to.
+- */
+-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+-
+-
+-static inline int pud_large(pud_t pud) { return 0; }
+-
+-/*
+- * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+- *
+- * this macro returns the index of the entry in the pmd page which would
+- * control the given virtual address
+- */
+-#define pmd_index(address)				\
+-	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+-
+-/*
+- * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+- *
+- * this macro returns the index of the entry in the pte page which would
+- * control the given virtual address
+- */
+-#define pte_index(address)					\
+-	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address)				\
+-	((pte_t *)pmd_page_vaddr(*(dir)) +  pte_index((address)))
+-
+-#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+-
+-#define pmd_page_vaddr(pmd)					\
+-	((unsigned long)__va(pmd_val((pmd)) & PTE_PFN_MASK))
+-
+ #if defined(CONFIG_HIGHPTE)
+ #define pte_offset_map(dir, address)					\
+ 	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) +		\
+@@ -185,7 +92,4 @@ void make_lowmem_page_writable(void *va,
+ #define kern_addr_valid(kaddr)	(0)
+ #endif
+ 
+-#define io_remap_pfn_range(vma, from, pfn, size, prot)			\
+-	direct_remap_pfn_range(vma, from, pfn, size, prot, DOMID_IO)
+-
+ #endif /* _ASM_X86_PGTABLE_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:52:02.000000000 +0100
+@@ -2,6 +2,8 @@
+ #define _ASM_X86_PGTABLE_64_H
+ 
+ #include <linux/const.h>
++#include <asm/pgtable_64_types.h>
++
+ #ifndef __ASSEMBLY__
+ 
+ /*
+@@ -12,12 +14,12 @@
+ #include <linux/bitops.h>
+ #include <linux/threads.h>
+ #include <linux/sched.h>
+-#include <asm/pda.h>
+ 
+ #ifdef CONFIG_XEN
+ extern pud_t level3_user_pgt[512];
+ 
+ extern void xen_init_pt(void);
++extern void xen_switch_pt(void);
+ #endif
+ 
+ extern pud_t level3_kernel_pgt[512];
+@@ -33,39 +35,13 @@ extern void paging_init(void);
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+-#define SHARED_KERNEL_PMD	0
+-
+-/*
+- * PGDIR_SHIFT determines what a top-level page table entry can map
+- */
+-#define PGDIR_SHIFT	39
+-#define PTRS_PER_PGD	512
+-
+-/*
+- * 3rd level page
+- */
+-#define PUD_SHIFT	30
+-#define PTRS_PER_PUD	512
+-
+-/*
+- * PMD_SHIFT determines the size of the area a middle-level
+- * page table can map
+- */
+-#define PMD_SHIFT	21
+-#define PTRS_PER_PMD	512
+-
+-/*
+- * entries per page directory level
+- */
+-#define PTRS_PER_PTE	512
+-
+ #ifndef __ASSEMBLY__
+ 
+ #define pte_ERROR(e)							\
+ 	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
+ #define pmd_ERROR(e)							\
+-	printk("%s:%d: bad pmd %p(%016lx pfn %010Lx).\n",		\
++	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pmd_val(e), pmd_pfn(e))
+ #define pud_ERROR(e)							\
+ 	printk("%s:%d: bad pud %p(%016lx pfn %010Lx).\n",		\
+@@ -76,9 +52,6 @@ extern void paging_init(void);
+ 	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+ 	       (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+-#define pgd_none(x)	(!__pgd_val(x))
+-#define pud_none(x)	(!__pud_val(x))
+-
+ struct mm_struct;
+ 
+ void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte);
+@@ -138,48 +111,6 @@ static inline void xen_pgd_clear(pgd_t *
+ 	xen_set_pgd(__user_pgd(pgd), xen_make_pgd(0));
+ }
+ 
+-#define pte_same(a, b)		((a).pte == (b).pte)
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
+-#define PMD_MASK	(~(PMD_SIZE - 1))
+-#define PUD_SIZE	(_AC(1, UL) << PUD_SHIFT)
+-#define PUD_MASK	(~(PUD_SIZE - 1))
+-#define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+-
+-#define MAX_PHYSMEM_BITS 43
+-#define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
+-#define VMALLOC_START    _AC(0xffffc20000000000, UL)
+-#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+-#define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+-#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+-#define MODULES_END      _AC(0xffffffffff000000, UL)
+-#define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+-
+-#ifndef __ASSEMBLY__
+-
+-static inline int pgd_bad(pgd_t pgd)
+-{
+-	return (__pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+-}
+-
+-static inline int pud_bad(pud_t pud)
+-{
+-	return (__pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+-}
+-
+-static inline int pmd_bad(pmd_t pmd)
+-{
+-	return (__pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+-}
+-
+-#define pte_none(x)	(!(x).pte)
+-#define pte_present(x)	((x).pte & (_PAGE_PRESENT | _PAGE_PROTNONE))
+-
+-#define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))   /* FIXME: is this right? */
+-
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
+ /*
+@@ -190,47 +121,12 @@ static inline int pmd_bad(pmd_t pmd)
+ /*
+  * Level 4 access.
+  */
+-#define pgd_page_vaddr(pgd)						\
+-	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK))
+-#define pgd_page(pgd)		(pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
+-#define pgd_present(pgd) (__pgd_val(pgd) & _PAGE_PRESENT)
+ static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
+ 
+ /* PUD - Level3 access */
+-/* to find an entry in a page-table-directory. */
+-#define pud_page_vaddr(pud)						\
+-	((unsigned long)__va(pud_val((pud)) & PHYSICAL_PAGE_MASK))
+-#define pud_page(pud)	(pfn_to_page(pud_val((pud)) >> PAGE_SHIFT))
+-#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+-#define pud_offset(pgd, address)					\
+-	((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address)))
+-#define pud_present(pud) (__pud_val(pud) & _PAGE_PRESENT)
+-
+-static inline int pud_large(pud_t pte)
+-{
+-	return (__pud_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+-		(_PAGE_PSE | _PAGE_PRESENT);
+-}
+ 
+ /* PMD  - Level 2 access */
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_PFN_MASK))
+-#define pmd_page(pmd)		(pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+-
+-#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+-#define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \
+-				  pmd_index(address))
+-#define pmd_none(x)	(!__pmd_val(x))
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+-   can temporarily clear it. */
+-#define pmd_present(x)	(__pmd_val(x))
+-#else
+-#define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+-#endif
+-#define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot))))
+-#define pmd_pfn(x)  ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+-
+ #define pte_to_pgoff(pte) ((__pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+ #define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) |	\
+ 					    _PAGE_FILE })
+@@ -238,13 +134,6 @@ static inline int pud_large(pud_t pte)
+ 
+ /* PTE - Level 1 access. */
+ 
+-/* page, protection -> pte */
+-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn((page)), (pgprot))
+-
+-#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+-					 pte_index((address)))
+-
+ /* x86-64 always has all page tables mapped. */
+ #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
+ #define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
+@@ -278,9 +167,6 @@ static inline int pud_large(pud_t pte)
+ extern int kern_addr_valid(unsigned long addr);
+ extern void cleanup_highmap(void);
+ 
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
+-	direct_remap_pfn_range(vma, vaddr, pfn, size, prot, DOMID_IO)
+-
+ #define HAVE_ARCH_UNMAPPED_AREA
+ #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64_types.h	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,63 @@
++#ifndef _ASM_X86_PGTABLE_64_DEFS_H
++#define _ASM_X86_PGTABLE_64_DEFS_H
++
++#ifndef __ASSEMBLY__
++#include <linux/types.h>
++
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef unsigned long	pteval_t;
++typedef unsigned long	pmdval_t;
++typedef unsigned long	pudval_t;
++typedef unsigned long	pgdval_t;
++typedef unsigned long	pgprotval_t;
++
++typedef union { pteval_t pte; unsigned int pte_low; } pte_t;
++
++#endif	/* !__ASSEMBLY__ */
++
++#define SHARED_KERNEL_PMD	0
++#define PAGETABLE_LEVELS	4
++
++/*
++ * PGDIR_SHIFT determines what a top-level page table entry can map
++ */
++#define PGDIR_SHIFT	39
++#define PTRS_PER_PGD	512
++
++/*
++ * 3rd level page
++ */
++#define PUD_SHIFT	30
++#define PTRS_PER_PUD	512
++
++/*
++ * PMD_SHIFT determines the size of the area a middle-level
++ * page table can map
++ */
++#define PMD_SHIFT	21
++#define PTRS_PER_PMD	512
++
++/*
++ * entries per page directory level
++ */
++#define PTRS_PER_PTE	512
++
++#define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
++#define PMD_MASK	(~(PMD_SIZE - 1))
++#define PUD_SIZE	(_AC(1, UL) << PUD_SHIFT)
++#define PUD_MASK	(~(PUD_SIZE - 1))
++#define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
++#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
++
++#define MAX_PHYSMEM_BITS 43
++#define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
++#define VMALLOC_START    _AC(0xffffc20000000000, UL)
++#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
++#define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
++#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
++#define MODULES_END      _AC(0xffffffffff000000, UL)
++#define MODULES_LEN   (MODULES_END - MODULES_VADDR)
++
++#endif /* _ASM_X86_PGTABLE_64_DEFS_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,388 @@
++#ifndef _ASM_X86_PGTABLE_DEFS_H
++#define _ASM_X86_PGTABLE_DEFS_H
++
++#include <linux/const.h>
++#include <asm/page_types.h>
++
++#define FIRST_USER_ADDRESS	0
++
++#define _PAGE_BIT_PRESENT	0	/* is present */
++#define _PAGE_BIT_RW		1	/* writeable */
++#define _PAGE_BIT_USER		2	/* userspace addressable */
++#define _PAGE_BIT_PWT		3	/* page write through */
++#define _PAGE_BIT_PCD		4	/* page cache disabled */
++#define _PAGE_BIT_ACCESSED	5	/* was accessed (raised by CPU) */
++#define _PAGE_BIT_DIRTY		6	/* was written to (raised by CPU) */
++#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
++#define _PAGE_BIT_PAT		7	/* on 4KB pages */
++#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
++#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
++#define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
++#define _PAGE_BIT_UNUSED3	11
++#define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
++#define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
++#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
++#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
++
++/* If _PAGE_BIT_PRESENT is clear, we use these: */
++/* - if the user mapped it with PROT_NONE; pte_present gives true */
++#define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
++/* - set: nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
++
++#define _PAGE_PRESENT	(_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
++#define _PAGE_RW	(_AT(pteval_t, 1) << _PAGE_BIT_RW)
++#define _PAGE_USER	(_AT(pteval_t, 1) << _PAGE_BIT_USER)
++#define _PAGE_PWT	(_AT(pteval_t, 1) << _PAGE_BIT_PWT)
++#define _PAGE_PCD	(_AT(pteval_t, 1) << _PAGE_BIT_PCD)
++#define _PAGE_ACCESSED	(_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED)
++#define _PAGE_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
++#define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
++#define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
++#define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
++#define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
++#define _PAGE_UNUSED3	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
++#define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
++#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
++#define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
++#define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
++#define __HAVE_ARCH_PTE_SPECIAL
++
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++#define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
++#else
++#define _PAGE_NX	(_AT(pteval_t, 0))
++#endif
++
++#define _PAGE_FILE	(_AT(pteval_t, 1) << _PAGE_BIT_FILE)
++#define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
++
++#ifndef __ASSEMBLY__
++#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
++extern unsigned int __kernel_page_user;
++#else
++#define __kernel_page_user 0
++#endif
++#endif
++
++#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)
++
++/* Set of bits not changed in pte_modify */
++#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IOMAP | \
++			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
++
++/*
++ * PAT settings are part of the hypervisor interface, which sets the
++ * MSR to 0x050100070406 (i.e. WB, WT, UC-, UC, WC, WP [, UC, UC]).
++ */
++#define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT | _PAGE_PAT)
++#define _PAGE_CACHE_WB		(0)
++#define _PAGE_CACHE_WT		(_PAGE_PWT)
++#define _PAGE_CACHE_WC		(_PAGE_PAT)
++#define _PAGE_CACHE_WP		(_PAGE_PAT | _PAGE_PWT)
++#define _PAGE_CACHE_UC_MINUS	(_PAGE_PCD)
++#define _PAGE_CACHE_UC		(_PAGE_PCD | _PAGE_PWT)
++
++#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
++				 _PAGE_ACCESSED | _PAGE_NX)
++
++#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW |	\
++					 _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
++#define PAGE_COPY		PAGE_COPY_NOEXEC
++#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
++
++#define __PAGE_KERNEL_EXEC						\
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
++#define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
++
++#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
++#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
++#define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
++#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
++#define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
++#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
++
++#define __PAGE_KERNEL_IO		(__PAGE_KERNEL | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC | _PAGE_IOMAP)
++
++#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
++#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
++#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_WC			__pgprot(__PAGE_KERNEL_WC)
++#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
++#define PAGE_KERNEL_UC_MINUS		__pgprot(__PAGE_KERNEL_UC_MINUS)
++#define PAGE_KERNEL_EXEC_NOCACHE	__pgprot(__PAGE_KERNEL_EXEC_NOCACHE)
++#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
++#define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
++#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
++#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
++#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
++
++#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
++#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
++#define PAGE_KERNEL_IO_UC_MINUS		__pgprot(__PAGE_KERNEL_IO_UC_MINUS)
++#define PAGE_KERNEL_IO_WC		__pgprot(__PAGE_KERNEL_IO_WC)
++
++/*         xwr */
++#define __P000	PAGE_NONE
++#define __P001	PAGE_READONLY
++#define __P010	PAGE_COPY
++#define __P011	PAGE_COPY
++#define __P100	PAGE_READONLY_EXEC
++#define __P101	PAGE_READONLY_EXEC
++#define __P110	PAGE_COPY_EXEC
++#define __P111	PAGE_COPY_EXEC
++
++#define __S000	PAGE_NONE
++#define __S001	PAGE_READONLY
++#define __S010	PAGE_SHARED
++#define __S011	PAGE_SHARED
++#define __S100	PAGE_READONLY_EXEC
++#define __S101	PAGE_READONLY_EXEC
++#define __S110	PAGE_SHARED_EXEC
++#define __S111	PAGE_SHARED_EXEC
++
++/*
++ * early identity mapping  pte attrib macros.
++ */
++#ifdef CONFIG_X86_64
++#define __PAGE_KERNEL_IDENT_LARGE_EXEC	__PAGE_KERNEL_LARGE_EXEC
++#else
++/*
++ * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
++ * bits are combined, this will alow user to access the high address mapped
++ * VDSO in the presence of CONFIG_COMPAT_VDSO
++ */
++#define PTE_IDENT_ATTR	 0x003		/* PRESENT+RW */
++#define PDE_IDENT_ATTR	 0x067		/* PRESENT+RW+USER+DIRTY+ACCESSED */
++#define PGD_IDENT_ATTR	 0x001		/* PRESENT (no other attributes) */
++#endif
++
++#ifdef CONFIG_X86_32
++# include <asm/pgtable_32_types.h>
++#else
++# include "pgtable_64_types.h"
++#endif
++
++#ifndef __ASSEMBLY__
++
++#include <linux/types.h>
++
++/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
++#define PTE_PFN_MASK		((pteval_t)PHYSICAL_PAGE_MASK)
++
++/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
++#define PTE_FLAGS_MASK		(~PTE_PFN_MASK)
++
++typedef struct pgprot { pgprotval_t pgprot; } pgprot_t;
++
++#include <asm/maddr.h>
++
++typedef struct { pgdval_t pgd; } pgd_t;
++
++#define __pgd_ma(x) ((pgd_t) { (x) } )
++static inline pgd_t xen_make_pgd(pgdval_t val)
++{
++	if (val & _PAGE_PRESENT)
++		val = pte_phys_to_machine(val);
++	return (pgd_t) { val };
++}
++
++#define __pgd_val(x) ((x).pgd)
++static inline pgdval_t xen_pgd_val(pgd_t pgd)
++{
++	pgdval_t ret = __pgd_val(pgd);
++#if PAGETABLE_LEVELS == 2 && CONFIG_XEN_COMPAT <= 0x030002
++	if (ret)
++		ret = machine_to_phys(ret) | _PAGE_PRESENT;
++#else
++	if (ret & _PAGE_PRESENT)
++		ret = pte_machine_to_phys(ret);
++#endif
++	return ret;
++}
++
++static inline pgdval_t pgd_flags(pgd_t pgd)
++{
++	return __pgd_val(pgd) & PTE_FLAGS_MASK;
++}
++
++#if PAGETABLE_LEVELS > 3
++typedef struct { pudval_t pud; } pud_t;
++
++#define __pud_ma(x) ((pud_t) { (x) } )
++static inline pud_t xen_make_pud(pudval_t val)
++{
++	if (val & _PAGE_PRESENT)
++		val = pte_phys_to_machine(val);
++	return (pud_t) { val };
++}
++
++#define __pud_val(x) ((x).pud)
++static inline pudval_t xen_pud_val(pud_t pud)
++{
++	pudval_t ret = __pud_val(pud);
++	if (ret & _PAGE_PRESENT)
++		ret = pte_machine_to_phys(ret);
++	return ret;
++}
++#else
++#include <asm-generic/pgtable-nopud.h>
++
++#define __pud_val(x) __pgd_val((x).pgd)
++static inline pudval_t xen_pud_val(pud_t pud)
++{
++	return xen_pgd_val(pud.pgd);
++}
++#endif
++
++#if PAGETABLE_LEVELS > 2
++typedef struct { pmdval_t pmd; } pmd_t;
++
++#define __pmd_ma(x)	((pmd_t) { (x) } )
++static inline pmd_t xen_make_pmd(pmdval_t val)
++{
++	if (val & _PAGE_PRESENT)
++		val = pte_phys_to_machine(val);
++	return (pmd_t) { val };
++}
++
++#define __pmd_val(x) ((x).pmd)
++static inline pmdval_t xen_pmd_val(pmd_t pmd)
++{
++	pmdval_t ret = __pmd_val(pmd);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret)
++		ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
++#else
++	if (ret & _PAGE_PRESENT)
++		ret = pte_machine_to_phys(ret);
++#endif
++	return ret;
++}
++#else
++#include <asm-generic/pgtable-nopmd.h>
++
++#define __pmd_ma(x) ((pmd_t) { .pud.pgd = __pgd_ma(x) } )
++#define __pmd_val(x) __pgd_val((x).pud.pgd)
++static inline pmdval_t xen_pmd_val(pmd_t pmd)
++{
++	return xen_pgd_val(pmd.pud.pgd);
++}
++#endif
++
++static inline pudval_t pud_flags(pud_t pud)
++{
++	return __pud_val(pud) & PTE_FLAGS_MASK;
++}
++
++static inline pmdval_t pmd_flags(pmd_t pmd)
++{
++	return __pmd_val(pmd) & PTE_FLAGS_MASK;
++}
++
++#define __pte_ma(x) ((pte_t) { .pte = (x) } )
++static inline pte_t xen_make_pte(pteval_t val)
++{
++	if ((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)
++		val = pte_phys_to_machine(val);
++	return (pte_t) { .pte = val };
++}
++
++#define __pte_val(x) ((x).pte)
++static inline pteval_t xen_pte_val(pte_t pte)
++{
++	pteval_t ret = __pte_val(pte);
++	if ((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)
++		ret = pte_machine_to_phys(ret);
++	return ret;
++}
++
++static inline pteval_t pte_flags(pte_t pte)
++{
++	return __pte_val(pte) & PTE_FLAGS_MASK;
++}
++
++#define pgprot_val(x)	((x).pgprot)
++#define __pgprot(x)	((pgprot_t) { (x) } )
++
++
++typedef struct page *pgtable_t;
++
++extern pteval_t __supported_pte_mask;
++extern int nx_enabled;
++extern void set_nx(void);
++
++#define pgprot_writecombine	pgprot_writecombine
++extern pgprot_t pgprot_writecombine(pgprot_t prot);
++
++#ifndef CONFIG_XEN
++/* Indicate that x86 has its own track and untrack pfn vma functions */
++#define __HAVE_PFNMAP_TRACKING
++#endif
++
++#define __HAVE_PHYS_MEM_ACCESS_PROT
++struct file;
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t vma_prot);
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t *vma_prot);
++
++/* Install a pte for a particular vaddr in kernel space. */
++void set_pte_vaddr(unsigned long vaddr, pte_t pte);
++
++#ifndef CONFIG_XEN
++extern void native_pagetable_setup_start(pgd_t *base);
++extern void native_pagetable_setup_done(pgd_t *base);
++#else
++static inline void xen_pagetable_setup_start(pgd_t *base) {}
++static inline void xen_pagetable_setup_done(pgd_t *base) {}
++#endif
++
++struct seq_file;
++extern void arch_report_meminfo(struct seq_file *m);
++
++enum {
++	PG_LEVEL_NONE,
++	PG_LEVEL_4K,
++	PG_LEVEL_2M,
++	PG_LEVEL_1G,
++	PG_LEVEL_NUM
++};
++
++#ifdef CONFIG_PROC_FS
++extern void update_page_count(int level, unsigned long pages);
++#else
++static inline void update_page_count(int level, unsigned long pages) { }
++#endif
++
++/*
++ * Helper function that returns the kernel pagetable entry controlling
++ * the virtual address 'address'. NULL means no pagetable entry present.
++ * NOTE: the return type is pte_t but if the pmd is PSE then we return it
++ * as a pte too.
++ */
++extern pte_t *lookup_address(unsigned long address, unsigned int *level);
++
++#endif	/* !__ASSEMBLY__ */
++
++#endif /* _ASM_X86_PGTABLE_DEFS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:52:02.000000000 +0100
+@@ -16,6 +16,7 @@ struct mm_struct;
+ #include <asm/cpufeature.h>
+ #include <asm/system.h>
+ #include <asm/page.h>
++#include <asm/pgtable_types.h>
+ #include <asm/percpu.h>
+ #include <asm/msr.h>
+ #include <asm/desc_defs.h>
+@@ -74,10 +75,10 @@ struct cpuinfo_x86 {
+ 	char			pad0;
+ #else
+ 	/* Number of 4K pages in DTLB/ITLB combined(in pages): */
+-	int			 x86_tlbsize;
++	int			x86_tlbsize;
++#endif
+ 	__u8			x86_virt_bits;
+ 	__u8			x86_phys_bits;
+-#endif
+ 	/* CPUID returned core id bits: */
+ 	__u8			x86_coreid_bits;
+ 	/* Max extended CPUID function supported: */
+@@ -92,9 +93,9 @@ struct cpuinfo_x86 {
+ 	int			x86_cache_alignment;	/* In bytes */
+ 	int			x86_power;
+ 	unsigned long		loops_per_jiffy;
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ 	/* cpus sharing the last level cache: */
+-	cpumask_t		llc_shared_map;
++	cpumask_var_t		llc_shared_map;
+ #endif
+ 	/* cpuid returned max cores value: */
+ 	u16			 x86_max_cores;
+@@ -138,7 +139,7 @@ extern struct cpuinfo_x86	new_cpu_data;
+ extern __u32			cleared_cpu_caps[NCAPINTS];
+ 
+ #ifdef CONFIG_SMP
+-DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
++DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+ #define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+ #define current_cpu_data	__get_cpu_var(cpu_info)
+ #else
+@@ -251,7 +252,6 @@ struct x86_hw_tss {
+ #define IO_BITMAP_LONGS			(IO_BITMAP_BYTES/sizeof(long))
+ #define IO_BITMAP_OFFSET		offsetof(struct tss_struct, io_bitmap)
+ #define INVALID_IO_BITMAP_OFFSET	0x8000
+-#define INVALID_IO_BITMAP_OFFSET_LAZY	0x9000
+ 
+ #ifndef CONFIG_X86_NO_TSS
+ struct tss_struct {
+@@ -267,11 +267,6 @@ struct tss_struct {
+ 	 * be within the limit.
+ 	 */
+ 	unsigned long		io_bitmap[IO_BITMAP_LONGS + 1];
+-	/*
+-	 * Cache the current maximum and the last task that used the bitmap:
+-	 */
+-	unsigned long		io_bitmap_max;
+-	struct thread_struct	*io_bitmap_owner;
+ 
+ 	/*
+ 	 * .. and then another 0x100 bytes for the emergency kernel stack:
+@@ -280,7 +275,7 @@ struct tss_struct {
+ 
+ } ____cacheline_aligned;
+ 
+-DECLARE_PER_CPU(struct tss_struct, init_tss);
++DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss);
+ 
+ /*
+  * Save the original ist values for checking stack pointers during debugging
+@@ -363,6 +358,11 @@ struct i387_soft_struct {
+ 	u32			entry_eip;
+ };
+ 
++struct ymmh_struct {
++	/* 16 * 16 bytes for each YMMH-reg = 256 bytes */
++	u32 ymmh_space[64];
++};
++
+ struct xsave_hdr_struct {
+ 	u64 xstate_bv;
+ 	u64 reserved1[2];
+@@ -372,6 +372,7 @@ struct xsave_hdr_struct {
+ struct xsave_struct {
+ 	struct i387_fxsave_struct i387;
+ 	struct xsave_hdr_struct xsave_hdr;
++	struct ymmh_struct ymmh;
+ 	/* new processor state extensions will go here */
+ } __attribute__ ((packed, aligned (64)));
+ 
+@@ -382,11 +383,37 @@ union thread_xstate {
+ 	struct xsave_struct		xsave;
+ };
+ 
+-#if defined(CONFIG_X86_64) && !defined(CONFIG_X86_NO_TSS)
++#ifdef CONFIG_X86_64
++#ifndef CONFIG_X86_NO_TSS
+ DECLARE_PER_CPU(struct orig_ist, orig_ist);
+ #endif
+ 
+-extern void print_cpu_info(struct cpuinfo_x86 *);
++union irq_stack_union {
++	char irq_stack[IRQ_STACK_SIZE];
++	/*
++	 * GCC hardcodes the stack canary as %gs:40.  Since the
++	 * irq_stack is the object at %gs:0, we reserve the bottom
++	 * 48 bytes of the irq stack for the canary.
++	 */
++	struct {
++		char gs_base[40];
++		unsigned long stack_canary;
++	};
++};
++
++DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union);
++DECLARE_INIT_PER_CPU(irq_stack_union);
++
++DECLARE_PER_CPU(char *, irq_stack_ptr);
++DECLARE_PER_CPU(unsigned int, irq_count);
++extern unsigned long kernel_eflags;
++extern asmlinkage void ignore_sysret(void);
++#else	/* X86_64 */
++#ifdef CONFIG_CC_STACKPROTECTOR
++DECLARE_PER_CPU(unsigned long, stack_canary);
++#endif
++#endif	/* X86_64 */
++
+ extern unsigned int xstate_size;
+ extern void free_thread_xstate(struct task_struct *);
+ extern struct kmem_cache *task_xstate_cachep;
+@@ -660,6 +687,7 @@ static inline void __sti_mwait(unsigned 
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+ 
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
++extern void init_c1e_mask(void);
+ 
+ extern unsigned long		boot_option_idle_override;
+ extern unsigned long		idle_halt;
+@@ -697,9 +725,9 @@ extern int sysenter_setup(void);
+ extern struct desc_ptr		early_gdt_descr;
+ 
+ extern void cpu_set_gdt(int);
+-extern void switch_to_new_gdt(void);
++extern void switch_to_new_gdt(int);
++extern void load_percpu_segment(int);
+ extern void cpu_init(void);
+-extern void init_gdt(int cpu);
+ 
+ static inline unsigned long get_debugctlmsr(void)
+ {
+@@ -784,6 +812,7 @@ static inline void spin_lock_prefetch(co
+  * User space process size: 3GB (default).
+  */
+ #define TASK_SIZE		PAGE_OFFSET
++#define TASK_SIZE_MAX		TASK_SIZE
+ #define STACK_TOP		TASK_SIZE
+ #define STACK_TOP_MAX		STACK_TOP
+ 
+@@ -843,7 +872,7 @@ extern unsigned long thread_saved_pc(str
+ /*
+  * User space process size. 47bits minus one guard page.
+  */
+-#define TASK_SIZE64	((1UL << 47) - PAGE_SIZE)
++#define TASK_SIZE_MAX	((1UL << 47) - PAGE_SIZE)
+ 
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+@@ -852,12 +881,12 @@ extern unsigned long thread_saved_pc(str
+ 					0xc0000000 : 0xFFFFe000)
+ 
+ #define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \
+-					IA32_PAGE_OFFSET : TASK_SIZE64)
++					IA32_PAGE_OFFSET : TASK_SIZE_MAX)
+ #define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \
+-					IA32_PAGE_OFFSET : TASK_SIZE64)
++					IA32_PAGE_OFFSET : TASK_SIZE_MAX)
+ 
+ #define STACK_TOP		TASK_SIZE
+-#define STACK_TOP_MAX		TASK_SIZE64
++#define STACK_TOP_MAX		TASK_SIZE_MAX
+ 
+ #define INIT_THREAD  { \
+ 	.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:58.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:15:20.000000000 +0100
+@@ -15,53 +15,25 @@
+ #  include <asm/io_apic.h>
+ # endif
+ #endif
+-#include <asm/pda.h>
+ #include <asm/thread_info.h>
+-
+-#ifdef CONFIG_X86_64
+-
+-#define cpu_callin_mask cpu_possible_mask
+-#define cpu_callout_mask cpu_possible_mask
+-extern cpumask_var_t cpu_initialized_mask;
+-extern cpumask_var_t cpu_sibling_setup_mask;
+-
+-#else /* CONFIG_X86_32 */
+-
+-#define cpu_callin_map cpu_possible_map
+-#define cpu_callout_map cpu_possible_map
+-extern cpumask_t cpu_initialized;
+-extern cpumask_t cpu_sibling_setup_map;
+-
+-#define cpu_callin_mask		((struct cpumask *)&cpu_callin_map)
+-#define cpu_callout_mask	((struct cpumask *)&cpu_callout_map)
+-#define cpu_initialized_mask	((struct cpumask *)&cpu_initialized)
+-#define cpu_sibling_setup_mask	((struct cpumask *)&cpu_sibling_setup_map)
+-
+-#endif /* CONFIG_X86_32 */
+-
+-extern void (*mtrr_hook)(void);
+-extern void zap_low_mappings(void);
+-
+-extern int __cpuinit get_local_pda(int cpu);
++#include <asm/cpumask.h>
+ 
+ extern int smp_num_siblings;
+ extern unsigned int num_processors;
+ 
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
+ DECLARE_PER_CPU(u16, cpu_llc_id);
+-#ifdef CONFIG_X86_32
+ DECLARE_PER_CPU(int, cpu_number);
+-#endif
+ 
+ static inline struct cpumask *cpu_sibling_mask(int cpu)
+ {
+-	return &per_cpu(cpu_sibling_map, cpu);
++	return per_cpu(cpu_sibling_map, cpu);
+ }
+ 
+ static inline struct cpumask *cpu_core_mask(int cpu)
+ {
+-	return &per_cpu(cpu_core_map, cpu);
++	return per_cpu(cpu_core_map, cpu);
+ }
+ 
+ DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+@@ -149,9 +121,10 @@ static inline void arch_send_call_functi
+ 	smp_ops.send_call_func_single_ipi(cpu);
+ }
+ 
+-static inline void arch_send_call_function_ipi(cpumask_t mask)
++#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
++static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+ {
+-	smp_ops.send_call_func_ipi(&mask);
++	smp_ops.send_call_func_ipi(mask);
+ }
+ 
+ void cpu_disable_common(void);
+@@ -176,14 +149,12 @@ void xen_send_call_func_single_ipi(int c
+ #define smp_send_stop		xen_smp_send_stop
+ #define smp_send_reschedule	xen_smp_send_reschedule
+ #define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
+-#define arch_send_call_function_ipi(m)		xen_send_call_func_ipi(&(m))
++#define arch_send_call_function_ipi_mask	xen_send_call_func_ipi
+ 
+ void play_dead(void);
+ 
+ #endif /* CONFIG_XEN */
+ 
+-extern void prefill_possible_map(void);
+-
+ void smp_store_cpu_info(int id);
+ #define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+ 
+@@ -192,10 +163,6 @@ static inline int num_booting_cpus(void)
+ {
+ 	return cpumask_weight(cpu_callout_mask);
+ }
+-#else
+-static inline void prefill_possible_map(void)
+-{
+-}
+ #endif /* CONFIG_SMP */
+ 
+ extern unsigned disabled_cpus __cpuinitdata;
+@@ -206,11 +173,11 @@ extern unsigned disabled_cpus __cpuinitd
+  * from the initial startup. We map APIC_BASE very early in page_setup(),
+  * so this is correct in the x86 case.
+  */
+-#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
++#define raw_smp_processor_id() (percpu_read(cpu_number))
+ #define safe_smp_processor_id() smp_processor_id()
+ 
+ #elif defined(CONFIG_X86_64_SMP)
+-#define raw_smp_processor_id()	read_pda(cpunumber)
++#define raw_smp_processor_id() (percpu_read(cpu_number))
+ 
+ #define stack_smp_processor_id()					\
+ ({								\
+@@ -220,10 +187,6 @@ extern unsigned disabled_cpus __cpuinitd
+ })
+ #define safe_smp_processor_id()		smp_processor_id()
+ 
+-#else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */
+-#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
+-#define safe_smp_processor_id()		0
+-#define stack_smp_processor_id() 	0
+ #endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -235,28 +198,9 @@ static inline int logical_smp_processor_
+ 	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+ }
+ 
+-#include <mach_apicdef.h>
+-static inline unsigned int read_apic_id(void)
+-{
+-	unsigned int reg;
+-
+-	reg = *(u32 *)(APIC_BASE + APIC_ID);
+-
+-	return GET_APIC_ID(reg);
+-}
+ #endif
+ 
+-
+-# if defined(APIC_DEFINITION) || defined(CONFIG_X86_64)
+ extern int hard_smp_processor_id(void);
+-# else
+-#include <mach_apicdef.h>
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return read_apic_id();
+-}
+-# endif /* APIC_DEFINITION */
+ 
+ #else /* CONFIG_X86_LOCAL_APIC */
+ 
+@@ -266,11 +210,5 @@ static inline int hard_smp_processor_id(
+ 
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ 
+-#ifdef CONFIG_X86_HAS_BOOT_CPU_ID
+-extern unsigned char boot_cpu_id;
+-#else
+-#define boot_cpu_id	0
+-#endif
+-
+ #endif /* __ASSEMBLY__ */
+ #endif /* _ASM_X86_SMP_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:53.000000000 +0100
+@@ -250,40 +250,18 @@ static __always_inline void __ticket_spi
+ static inline int xen_spinlock_init(unsigned int cpu) { return 0; }
+ static inline void xen_spinlock_cleanup(unsigned int cpu) {}
+ 
+-/*
+- * Define virtualization-friendly old-style lock byte lock, for use in
+- * pv_lock_ops if desired.
+- *
+- * This differs from the pre-2.6.24 spinlock by always using xchgb
+- * rather than decb to take the lock; this allows it to use a
+- * zero-initialized lock structure.  It also maintains a 1-byte
+- * contention counter, so that we can implement
+- * __byte_spin_is_contended.
+- */
+-struct __byte_spinlock {
+-	s8 lock;
+-#if NR_CPUS < 256
+-	s8 spinners;
+-#else
+-#error NR_CPUS >= 256 support not implemented
+-#endif
+-};
+-
+ static inline int __byte_spin_is_locked(raw_spinlock_t *lock)
+ {
+-	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+-	return bl->lock != 0;
++	return lock->lock != 0;
+ }
+ 
+ static inline int __byte_spin_is_contended(raw_spinlock_t *lock)
+ {
+-	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+-	return bl->spinners != 0;
++	return lock->spinners != 0;
+ }
+ 
+ static inline void __byte_spin_lock(raw_spinlock_t *lock)
+ {
+-	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+ 	s8 val = 1;
+ 
+ 	asm("1: xchgb %1, %0\n"
+@@ -296,27 +274,25 @@ static inline void __byte_spin_lock(raw_
+ 	    "   " LOCK_PREFIX "decb %2\n"
+ 	    "   jmp 1b\n"
+ 	    "3:"
+-	    : "+m" (bl->lock), "+q" (val), "+m" (bl->spinners): : "memory");
++	    : "+m" (lock->lock), "+q" (val), "+m" (lock->spinners): : "memory");
+ }
+ 
+ #define __byte_spin_lock_flags(lock, flags) __byte_spin_lock(lock)
+ 
+ static inline int __byte_spin_trylock(raw_spinlock_t *lock)
+ {
+-	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+ 	u8 old = 1;
+ 
+ 	asm("xchgb %1,%0"
+-	    : "+m" (bl->lock), "+q" (old) : : "memory");
++	    : "+m" (lock->lock), "+q" (old) : : "memory");
+ 
+ 	return old == 0;
+ }
+ 
+ static inline void __byte_spin_unlock(raw_spinlock_t *lock)
+ {
+-	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+ 	smp_wmb();
+-	bl->lock = 0;
++	lock->lock = 0;
+ }
+ 
+ #define __raw_spin(n) __byte_spin_##n
+@@ -417,8 +393,7 @@ static inline int __raw_read_trylock(raw
+ {
+ 	atomic_t *count = (atomic_t *)lock;
+ 
+-	atomic_dec(count);
+-	if (atomic_read(count) >= 0)
++	if (atomic_dec_return(count) >= 0)
+ 		return 1;
+ 	atomic_inc(count);
+ 	return 0;
+@@ -445,6 +420,9 @@ static inline void __raw_write_unlock(ra
+ 		     : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
+ }
+ 
++#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
++#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
++
+ #define _raw_spin_relax(lock)	cpu_relax()
+ #define _raw_read_relax(lock)	cpu_relax()
+ #define _raw_write_relax(lock)	cpu_relax()
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:48:59.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:52:32.000000000 +0100
+@@ -24,6 +24,20 @@ typedef union {
+ # define TICKET_SHIFT 16
+ 		u16 cur, seq;
+ #endif
++#else
++/*
++ * This differs from the pre-2.6.24 spinlock by always using xchgb
++ * rather than decb to take the lock; this allows it to use a
++ * zero-initialized lock structure.  It also maintains a 1-byte
++ * contention counter, so that we can implement
++ * __byte_spin_is_contended.
++ */
++		u8 lock;
++#if CONFIG_NR_CPUS < 256
++		u8 spinners;
++#else
++# error NR_CPUS >= 256 not implemented
++#endif
+ #endif
+ 	};
+ } raw_spinlock_t;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:52:02.000000000 +0100
+@@ -21,9 +21,24 @@
+ struct task_struct; /* one of the stranger aspects of C forward declarations */
+ struct task_struct *__switch_to(struct task_struct *prev,
+ 				struct task_struct *next);
++void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
+ 
+ #ifdef CONFIG_X86_32
+ 
++#ifdef CONFIG_CC_STACKPROTECTOR
++#define __switch_canary							\
++	"movl %P[task_canary](%[next]), %%ebx\n\t"			\
++	"movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
++#define __switch_canary_oparam						\
++	, [stack_canary] "=m" (per_cpu_var(stack_canary))
++#define __switch_canary_iparam						\
++	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
++#else	/* CC_STACKPROTECTOR */
++#define __switch_canary
++#define __switch_canary_oparam
++#define __switch_canary_iparam
++#endif	/* CC_STACKPROTECTOR */
++
+ /*
+  * Saving eflags is important. It switches not only IOPL between tasks,
+  * it also protects other tasks from NT leaking through sysenter etc.
+@@ -45,6 +60,7 @@ do {									\
+ 		     "movl %[next_sp],%%esp\n\t"	/* restore ESP   */ \
+ 		     "movl $1f,%[prev_ip]\n\t"	/* save    EIP   */	\
+ 		     "pushl %[next_ip]\n\t"	/* restore EIP   */	\
++		     __switch_canary					\
+ 		     "jmp __switch_to\n"	/* regparm call  */	\
+ 		     "1:\t"						\
+ 		     "popl %%ebp\n\t"		/* restore EBP   */	\
+@@ -59,6 +75,8 @@ do {									\
+ 		       "=b" (ebx), "=c" (ecx), "=d" (edx),		\
+ 		       "=S" (esi), "=D" (edi)				\
+ 		       							\
++		       __switch_canary_oparam				\
++									\
+ 		       /* input parameters: */				\
+ 		     : [next_sp]  "m" (next->thread.sp),		\
+ 		       [next_ip]  "m" (next->thread.ip),		\
+@@ -67,6 +85,8 @@ do {									\
+ 		       [prev]     "a" (prev),				\
+ 		       [next]     "d" (next)				\
+ 									\
++		       __switch_canary_iparam				\
++									\
+ 		     : /* reloaded segment registers */			\
+ 			"memory");					\
+ } while (0)
+@@ -87,27 +107,44 @@ do {									\
+ 	, "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
+ 	  "r12", "r13", "r14", "r15"
+ 
++#ifdef CONFIG_CC_STACKPROTECTOR
++#define __switch_canary							  \
++	"movq %P[task_canary](%%rsi),%%r8\n\t"				  \
++	"movq %%r8,"__percpu_arg([gs_canary])"\n\t"
++#define __switch_canary_oparam						  \
++	, [gs_canary] "=m" (per_cpu_var(irq_stack_union.stack_canary))
++#define __switch_canary_iparam						  \
++	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
++#else	/* CC_STACKPROTECTOR */
++#define __switch_canary
++#define __switch_canary_oparam
++#define __switch_canary_iparam
++#endif	/* CC_STACKPROTECTOR */
++
+ /* Save restore flags to clear handle leaking NT */
+ #define switch_to(prev, next, last) \
+-	asm volatile(SAVE_CONTEXT						    \
++	asm volatile(SAVE_CONTEXT					  \
+ 	     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
+ 	     "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */	  \
+ 	     "call __switch_to\n\t"					  \
+ 	     ".globl thread_return\n"					  \
+ 	     "thread_return:\n\t"					  \
+-	     "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"			  \
++	     "movq "__percpu_arg([current_task])",%%rsi\n\t"		  \
++	     __switch_canary						  \
+ 	     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
+-	     LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"	  \
+ 	     "movq %%rax,%%rdi\n\t" 					  \
+-	     "jc   ret_from_fork\n\t"					  \
++	     "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"	  \
++	     "jnz   ret_from_fork\n\t"					  \
+ 	     RESTORE_CONTEXT						  \
+ 	     : "=a" (last)					  	  \
++	       __switch_canary_oparam					  \
+ 	     : [next] "S" (next), [prev] "D" (prev),			  \
+ 	       [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+ 	       [ti_flags] "i" (offsetof(struct thread_info, flags)),	  \
+-	       [tif_fork] "i" (TIF_FORK),			  	  \
++	       [_tif_fork] "i" (_TIF_FORK),			  	  \
+ 	       [thread_info] "i" (offsetof(struct task_struct, stack)),   \
+-	       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))  \
++	       [current_task] "m" (per_cpu_var(current_task))		  \
++	       __switch_canary_iparam					  \
+ 	     : "memory", "cc" __EXTRA_CLOBBER)
+ #endif
+ 
+@@ -166,6 +203,25 @@ extern void xen_load_gs_index(unsigned);
+ #define savesegment(seg, value)				\
+ 	asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+ 
++/*
++ * x86_32 user gs accessors.
++ */
++#ifdef CONFIG_X86_32
++#ifdef CONFIG_X86_32_LAZY_GS
++#define get_user_gs(regs)	(u16)({unsigned long v; savesegment(gs, v); v;})
++#define set_user_gs(regs, v)	loadsegment(gs, (unsigned long)(v))
++#define task_user_gs(tsk)	((tsk)->thread.gs)
++#define lazy_save_gs(v)		savesegment(gs, (v))
++#define lazy_load_gs(v)		loadsegment(gs, (v))
++#else	/* X86_32_LAZY_GS */
++#define get_user_gs(regs)	(u16)((regs)->gs)
++#define set_user_gs(regs, v)	do { (regs)->gs = (v); } while (0)
++#define task_user_gs(tsk)	(task_pt_regs(tsk)->gs)
++#define lazy_save_gs(v)		do { } while (0)
++#define lazy_load_gs(v)		do { } while (0)
++#endif	/* X86_32_LAZY_GS */
++#endif	/* X86_32 */
++
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ 	unsigned long __limit;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:52:02.000000000 +0100
+@@ -86,21 +86,20 @@ static inline void flush_tlb_range(struc
+ 	flush_tlb_mm(vma->vm_mm);
+ }
+ 
++#ifndef CONFIG_XEN
+ #define TLBSTATE_OK	1
+ #define TLBSTATE_LAZY	2
+ 
+-#ifdef CONFIG_X86_32
+ struct tlb_state {
+ 	struct mm_struct *active_mm;
+ 	int state;
+-	char __cacheline_padding[L1_CACHE_BYTES-8];
+ };
+-DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
++DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
+ 
+-void reset_lazy_tlbstate(void);
+-#else
+ static inline void reset_lazy_tlbstate(void)
+ {
++	percpu_write(cpu_tlbstate.state, 0);
++	percpu_write(cpu_tlbstate.active_mm, &init_mm);
+ }
+ #endif
+ 
+@@ -112,4 +111,6 @@ static inline void flush_tlb_kernel_rang
+ 	flush_tlb_all();
+ }
+ 
++extern void zap_low_mappings(void);
++
+ #endif /* _ASM_X86_TLBFLUSH_H */
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -122,7 +122,6 @@ obj-$(CONFIG_X86_XEN)		+= fixup.o
+ ###
+ # 64 bit specific files
+ ifeq ($(CONFIG_X86_64),y)
+-	obj-$(CONFIG_X86_XEN_GENAPIC)	+= genapic_64.o genapic_xen_64.o
+ 	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+ 	obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
+ 	obj-$(CONFIG_AUDIT)		+= audit_64.o
+@@ -134,11 +133,10 @@ ifeq ($(CONFIG_X86_64),y)
+ 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+ 	obj-y				+= vsmp_64.o
+ 
+-	obj-$(CONFIG_XEN)		+= nmi.o
+ 	time_64-$(CONFIG_XEN)		+= time_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o genx2apic_%.o \
+-	hpet.o i8253.o i8259.o irqinit_$(BITS).o pci-swiotlb_64.o reboot.o \
+-	smpboot.o tlb_$(BITS).o tsc.o tsc_sync.o uv_%.o vsmp_64.o
++disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
++	i8259.o irqinit_$(BITS).o pci-swiotlb.o reboot.o smpboot.o tsc.o \
++	tsc_sync.o uv_%.o vsmp_64.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/boot.c	2009-11-06 10:52:02.000000000 +0100
+@@ -112,11 +112,6 @@ char *__init __acpi_map_table(unsigned l
+ 	if (!phys || !size)
+ 		return NULL;
+ 
+-#ifdef CONFIG_XEN
+-	if (phys + size <= (NR_FIX_ISAMAPS << PAGE_SHIFT))
+-		return isa_bus_to_virt(phys);
+-#endif
+-
+ 	return early_ioremap(phys, size);
+ }
+ void __init __acpi_unmap_table(char *map, unsigned long size)
+@@ -148,8 +143,10 @@ static int __init acpi_parse_madt(struct
+ 		       madt->address);
+ 	}
+ 
++#ifndef CONFIG_XEN
+ 	default_acpi_madt_oem_check(madt->header.oem_id,
+ 				    madt->header.oem_table_id);
++#endif
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -104,6 +104,7 @@ int acpi_save_state_mem(void)
+ 	stack_start.sp = temp_stack + sizeof(temp_stack);
+ 	early_gdt_descr.address =
+ 			(unsigned long)get_cpu_gdt_table(smp_processor_id());
++	initial_gs = per_cpu_offset(smp_processor_id());
+ #endif
+ 	initial_code = (unsigned long)wakeup_long64;
+ 	saved_magic = 0x123456789abcdef0;
+--- head-2010-01-18.orig/arch/x86/kernel/apic/Makefile	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -17,3 +17,10 @@ obj-$(CONFIG_X86_BIGSMP)	+= bigsmp_32.o
+ obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
+ obj-$(CONFIG_X86_ES7000)	+= es7000_32.o
+ obj-$(CONFIG_X86_SUMMIT)	+= summit_32.o
++
++obj-$(CONFIG_XEN)		+= nmi.o
++
++probe_64-$(CONFIG_XEN)		:= probe_32.o
++
++disabled-obj-$(CONFIG_XEN)	:= apic_flat_$(BITS).o
++disabled-obj-$(filter-out $(CONFIG_SMP),$(CONFIG_XEN)) += ipi.o
+--- head-2010-01-18.orig/arch/x86/kernel/apic/apic-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/apic-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -4,11 +4,20 @@
+ 
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
++#include <linux/module.h>
+ 
+ #include <asm/smp.h>
+ #include <asm/proto.h>
+ #include <asm/apic.h>
+ 
++unsigned int num_processors;
++
++/*
++ * Map cpu index to physical APIC ID
++ */
++DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++
+ /*
+  * Debug level, exported for io_apic.c
+  */
+--- head-2010-01-18.orig/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,7 +1,7 @@
+ /*
+  *	Intel IO-APIC support for multi-Pentium hosts.
+  *
+- *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
++ *	Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
+  *
+  *	Many thanks to Stig Venaas for trying out countless experimental
+  *	patches and reporting/debugging problems patiently!
+@@ -46,6 +46,7 @@
+ #include <asm/idle.h>
+ #include <asm/io.h>
+ #include <asm/smp.h>
++#include <asm/cpu.h>
+ #include <asm/desc.h>
+ #include <asm/proto.h>
+ #include <asm/acpi.h>
+@@ -61,9 +62,7 @@
+ #include <asm/uv/uv_hub.h>
+ #include <asm/uv/uv_irq.h>
+ 
+-#include <mach_ipi.h>
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
++#include <asm/apic.h>
+ 
+ #ifdef CONFIG_XEN
+ #include <xen/interface/xen.h>
+@@ -97,11 +96,11 @@ static DEFINE_SPINLOCK(vector_lock);
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
+ /* I/O APIC entries */
+-struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
++struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
+ int nr_ioapics;
+ 
+ /* MP IRQ source entries */
+-struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ 
+ /* # of MP IRQ source entries */
+ int mp_irq_entries;
+@@ -114,10 +113,19 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BU
+ 
+ int skip_ioapic_setup;
+ 
++void arch_disable_smp_support(void)
++{
++#ifdef CONFIG_PCI
++	noioapicquirk = 1;
++	noioapicreroute = -1;
++#endif
++	skip_ioapic_setup = 1;
++}
++
+ static int __init parse_noapic(char *str)
+ {
+ 	/* disable IO-APIC */
+-	disable_ioapic_setup();
++	arch_disable_smp_support();
+ 	return 0;
+ }
+ early_param("noapic", parse_noapic);
+@@ -372,7 +380,7 @@ set_extra_move_desc(struct irq_desc *des
+ 
+ 	if (!cfg->move_in_progress) {
+ 		/* it means that domain is not changed */
+-		if (!cpumask_intersects(&desc->affinity, mask))
++		if (!cpumask_intersects(desc->affinity, mask))
+ 			cfg->move_desc_pending = 1;
+ 	}
+ }
+@@ -397,12 +405,20 @@ struct io_apic {
+ 	unsigned int index;
+ 	unsigned int unused[3];
+ 	unsigned int data;
++	unsigned int unused2[11];
++	unsigned int eoi;
+ };
+ 
+ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+ {
+ 	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+-		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
++		+ (mp_ioapics[idx].apicaddr & ~PAGE_MASK);
++}
++
++static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
++{
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(vector, &io_apic->eoi);
+ }
+ #endif /* CONFIG_XEN */
+ 
+@@ -416,7 +432,7 @@ static inline unsigned int io_apic_read(
+ 	struct physdev_apic apic_op;
+ 	int ret;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].apicaddr;
+ 	apic_op.reg = reg;
+ 	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+ 	if (ret)
+@@ -434,7 +450,7 @@ static inline void io_apic_write(unsigne
+ #else
+ 	struct physdev_apic apic_op;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].apicaddr;
+ 	apic_op.reg = reg;
+ 	apic_op.value = value;
+ 	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+@@ -522,7 +538,7 @@ __ioapic_write_entry(int apic, int pin, 
+ 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+ }
+ 
+-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+ {
+ 	unsigned long flags;
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+@@ -558,11 +574,11 @@ static void send_cleanup_vector(struct i
+ 		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ 			cfg->move_cleanup_count++;
+ 		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+-			send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
++			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+ 	} else {
+ 		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+ 		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+ 		free_cpumask_var(cleanup_mask);
+ 	}
+ 	cfg->move_in_progress = 0;
+@@ -583,16 +599,12 @@ static void __target_IO_APIC_irq(unsigne
+ 
+ 		apic = entry->apic;
+ 		pin = entry->pin;
+-#ifdef CONFIG_INTR_REMAP
+ 		/*
+ 		 * With interrupt-remapping, destination information comes
+ 		 * from interrupt-remapping table entry.
+ 		 */
+ 		if (!irq_remapped(irq))
+ 			io_apic_write(apic, 0x11 + pin*2, dest);
+-#else
+-		io_apic_write(apic, 0x11 + pin*2, dest);
+-#endif
+ 		reg = io_apic_read(apic, 0x10 + pin*2);
+ 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+ 		reg |= vector;
+@@ -607,8 +619,9 @@ static int
+ assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+ 
+ /*
+- * Either sets desc->affinity to a valid value, and returns cpu_mask_to_apicid
+- * of that, or returns BAD_APICID and leaves desc->affinity untouched.
++ * Either sets desc->affinity to a valid value, and returns
++ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
++ * leaves desc->affinity untouched.
+  */
+ static unsigned int
+ set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+@@ -624,9 +637,12 @@ set_desc_affinity(struct irq_desc *desc,
+ 	if (assign_irq_vector(irq, cfg, mask))
+ 		return BAD_APICID;
+ 
+-	cpumask_and(&desc->affinity, cfg->domain, mask);
++	/* check that before desc->addinity get updated */
+ 	set_extra_move_desc(desc, mask);
+-	return cpu_mask_to_apicid_and(&desc->affinity, cpu_online_mask);
++
++	cpumask_copy(desc->affinity, mask);
++
++	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+ }
+ 
+ static void
+@@ -840,23 +856,6 @@ static void clear_IO_APIC (void)
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+ 			clear_IO_APIC_pin(apic, pin);
+ }
+-
+-#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
+-void send_IPI_self(int vector)
+-{
+-	unsigned int cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	apic_wait_icr_idle();
+-	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write(APIC_ICR, cfg);
+-}
+-#endif /* !CONFIG_SMP && CONFIG_X86_32*/
+ #else
+ #define add_pin_to_irq_cpu(cfg, cpu, apic, pin)
+ #endif /* CONFIG_XEN */
+@@ -868,8 +867,9 @@ void send_IPI_self(int vector)
+  */
+ 
+ #define MAX_PIRQS 8
+-static int pirq_entries [MAX_PIRQS];
+-static int pirqs_enabled;
++static int pirq_entries[MAX_PIRQS] = {
++	[0 ... MAX_PIRQS - 1] = -1
++};
+ 
+ static int __init ioapic_pirq_setup(char *str)
+ {
+@@ -878,10 +878,6 @@ static int __init ioapic_pirq_setup(char
+ 
+ 	get_options(str, ARRAY_SIZE(ints), ints);
+ 
+-	for (i = 0; i < MAX_PIRQS; i++)
+-		pirq_entries[i] = -1;
+-
+-	pirqs_enabled = 1;
+ 	apic_printk(APIC_VERBOSE, KERN_INFO
+ 			"PIRQ redirection, working around broken MP-BIOS.\n");
+ 	max = MAX_PIRQS;
+@@ -903,75 +899,106 @@ __setup("pirq=", ioapic_pirq_setup);
+ #endif /* CONFIG_X86_32 */
+ 
+ #ifdef CONFIG_INTR_REMAP
+-/* I/O APIC RTE contents at the OS boot up */
+-static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
++struct IO_APIC_route_entry **alloc_ioapic_entries(void)
++{
++	int apic;
++	struct IO_APIC_route_entry **ioapic_entries;
++
++	ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
++				GFP_ATOMIC);
++	if (!ioapic_entries)
++		return 0;
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		ioapic_entries[apic] =
++			kzalloc(sizeof(struct IO_APIC_route_entry) *
++				nr_ioapic_registers[apic], GFP_ATOMIC);
++		if (!ioapic_entries[apic])
++			goto nomem;
++	}
++
++	return ioapic_entries;
++
++nomem:
++	while (--apic >= 0)
++		kfree(ioapic_entries[apic]);
++	kfree(ioapic_entries);
++
++	return 0;
++}
+ 
+ /*
+- * Saves and masks all the unmasked IO-APIC RTE's
++ * Saves all the IO-APIC RTE's
+  */
+-int save_mask_IO_APIC_setup(void)
++int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+ {
+-	union IO_APIC_reg_01 reg_01;
+-	unsigned long flags;
+ 	int apic, pin;
+ 
+-	/*
+-	 * The number of IO-APIC IRQ registers (== #pins):
+-	 */
++	if (!ioapic_entries)
++		return -ENOMEM;
++
+ 	for (apic = 0; apic < nr_ioapics; apic++) {
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_01.raw = io_apic_read(apic, 1);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
++		if (!ioapic_entries[apic])
++			return -ENOMEM;
++
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
++			ioapic_entries[apic][pin] =
++				ioapic_read_entry(apic, pin);
+ 	}
+ 
++	return 0;
++}
++
++/*
++ * Mask all IO APIC entries.
++ */
++void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
++{
++	int apic, pin;
++
++	if (!ioapic_entries)
++		return;
++
+ 	for (apic = 0; apic < nr_ioapics; apic++) {
+-		early_ioapic_entries[apic] =
+-			kzalloc(sizeof(struct IO_APIC_route_entry) *
+-				nr_ioapic_registers[apic], GFP_KERNEL);
+-		if (!early_ioapic_entries[apic])
+-			goto nomem;
+-	}
++		if (!ioapic_entries[apic])
++			break;
+ 
+-	for (apic = 0; apic < nr_ioapics; apic++)
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ 			struct IO_APIC_route_entry entry;
+ 
+-			entry = early_ioapic_entries[apic][pin] =
+-				ioapic_read_entry(apic, pin);
++			entry = ioapic_entries[apic][pin];
+ 			if (!entry.mask) {
+ 				entry.mask = 1;
+ 				ioapic_write_entry(apic, pin, entry);
+ 			}
+ 		}
+-
+-	return 0;
+-
+-nomem:
+-	while (apic >= 0)
+-		kfree(early_ioapic_entries[apic--]);
+-	memset(early_ioapic_entries, 0,
+-		ARRAY_SIZE(early_ioapic_entries));
+-
+-	return -ENOMEM;
++	}
+ }
+ 
+-void restore_IO_APIC_setup(void)
++/*
++ * Restore IO APIC entries which was saved in ioapic_entries.
++ */
++int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+ {
+ 	int apic, pin;
+ 
++	if (!ioapic_entries)
++		return -ENOMEM;
++
+ 	for (apic = 0; apic < nr_ioapics; apic++) {
+-		if (!early_ioapic_entries[apic])
+-			break;
++		if (!ioapic_entries[apic])
++			return -ENOMEM;
++
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+ 			ioapic_write_entry(apic, pin,
+-					   early_ioapic_entries[apic][pin]);
+-		kfree(early_ioapic_entries[apic]);
+-		early_ioapic_entries[apic] = NULL;
++					ioapic_entries[apic][pin]);
+ 	}
++	return 0;
+ }
+ 
+-void reinit_intr_remapped_IO_APIC(int intr_remapping)
++void reinit_intr_remapped_IO_APIC(int intr_remapping,
++	struct IO_APIC_route_entry **ioapic_entries)
++
+ {
+ 	/*
+ 	 * for now plain restore of previous settings.
+@@ -980,7 +1007,17 @@ void reinit_intr_remapped_IO_APIC(int in
+ 	 * table entries. for now, do a plain restore, and wait for
+ 	 * the setup_IO_APIC_irqs() to do proper initialization.
+ 	 */
+-	restore_IO_APIC_setup();
++	restore_IO_APIC_setup(ioapic_entries);
++}
++
++void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
++{
++	int apic;
++
++	for (apic = 0; apic < nr_ioapics; apic++)
++		kfree(ioapic_entries[apic]);
++
++	kfree(ioapic_entries);
+ }
+ #endif
+ 
+@@ -992,10 +1029,10 @@ static int find_irq_entry(int apic, int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == type &&
+-		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
+-		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
+-		    mp_irqs[i].mp_dstirq == pin)
++		if (mp_irqs[i].irqtype == type &&
++		    (mp_irqs[i].dstapic == mp_ioapics[apic].apicid ||
++		     mp_irqs[i].dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].dstirq == pin)
+ 			return i;
+ 
+ 	return -1;
+@@ -1010,13 +1047,13 @@ static int __init find_isa_irq_pin(int i
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
++		int lbus = mp_irqs[i].srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
++		    (mp_irqs[i].irqtype == type) &&
++		    (mp_irqs[i].srcbusirq == irq))
+ 
+-			return mp_irqs[i].mp_dstirq;
++			return mp_irqs[i].dstirq;
+ 	}
+ 	return -1;
+ }
+@@ -1026,17 +1063,17 @@ static int __init find_isa_irq_apic(int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
++		int lbus = mp_irqs[i].srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
++		    (mp_irqs[i].irqtype == type) &&
++		    (mp_irqs[i].srcbusirq == irq))
+ 			break;
+ 	}
+ 	if (i < mp_irq_entries) {
+ 		int apic;
+ 		for(apic = 0; apic < nr_ioapics; apic++) {
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
++			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic)
+ 				return apic;
+ 		}
+ 	}
+@@ -1062,23 +1099,23 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 		return -1;
+ 	}
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
++		int lbus = mp_irqs[i].srcbus;
+ 
+ 		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
+-			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
++			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
++			    mp_irqs[i].dstapic == MP_APIC_ALL)
+ 				break;
+ 
+ 		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].mp_irqtype &&
++		    !mp_irqs[i].irqtype &&
+ 		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
++		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+ 
+ 			if (!(apic || IO_APIC_IRQ(irq)))
+ 				continue;
+ 
+-			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
++			if (pin == (mp_irqs[i].srcbusirq & 3))
+ 				return irq;
+ 			/*
+ 			 * Use the first all-but-pin matching entry as a
+@@ -1121,7 +1158,7 @@ static int EISA_ELCR(unsigned int irq)
+  * EISA conforming in the MP table, that means its trigger type must
+  * be read in from the ELCR */
+ 
+-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
++#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].srcbusirq))
+ #define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ /* PCI interrupts are always polarity one level triggered,
+@@ -1138,13 +1175,13 @@ static int EISA_ELCR(unsigned int irq)
+ 
+ static int MPBIOS_polarity(int idx)
+ {
+-	int bus = mp_irqs[idx].mp_srcbus;
++	int bus = mp_irqs[idx].srcbus;
+ 	int polarity;
+ 
+ 	/*
+ 	 * Determine IRQ line polarity (high active or low active):
+ 	 */
+-	switch (mp_irqs[idx].mp_irqflag & 3)
++	switch (mp_irqs[idx].irqflag & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent polarity */
+ 			if (test_bit(bus, mp_bus_not_pci))
+@@ -1180,13 +1217,13 @@ static int MPBIOS_polarity(int idx)
+ 
+ static int MPBIOS_trigger(int idx)
+ {
+-	int bus = mp_irqs[idx].mp_srcbus;
++	int bus = mp_irqs[idx].srcbus;
+ 	int trigger;
+ 
+ 	/*
+ 	 * Determine IRQ trigger mode (edge or level sensitive):
+ 	 */
+-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
++	switch ((mp_irqs[idx].irqflag>>2) & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent */
+ 			if (test_bit(bus, mp_bus_not_pci))
+@@ -1264,16 +1301,16 @@ int (*ioapic_renumber_irq)(int ioapic, i
+ static int pin_2_irq(int idx, int apic, int pin)
+ {
+ 	int irq, i;
+-	int bus = mp_irqs[idx].mp_srcbus;
++	int bus = mp_irqs[idx].srcbus;
+ 
+ 	/*
+ 	 * Debugging check, we are in big trouble if this message pops up!
+ 	 */
+-	if (mp_irqs[idx].mp_dstirq != pin)
++	if (mp_irqs[idx].dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+ 	if (test_bit(bus, mp_bus_not_pci)) {
+-		irq = mp_irqs[idx].mp_srcbusirq;
++		irq = mp_irqs[idx].srcbusirq;
+ 	} else {
+ 		/*
+ 		 * PCI IRQs are mapped in order
+@@ -1366,7 +1403,7 @@ __assign_irq_vector(int irq, struct irq_
+ 		int new_cpu;
+ 		int vector, offset;
+ 
+-		vector_allocation_domain(cpu, tmp_mask);
++		apic->vector_allocation_domain(cpu, tmp_mask);
+ 
+ 		vector = current_vector;
+ 		offset = current_offset;
+@@ -1476,9 +1513,7 @@ void __setup_vector_irq(int cpu)
+ }
+ 
+ static struct irq_chip ioapic_chip;
+-#ifdef CONFIG_INTR_REMAP
+ static struct irq_chip ir_ioapic_chip;
+-#endif
+ 
+ #define IOAPIC_AUTO     -1
+ #define IOAPIC_EDGE     0
+@@ -1517,7 +1552,6 @@ static void ioapic_register_intr(int irq
+ 	else
+ 		desc->status &= ~IRQ_LEVEL;
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	if (irq_remapped(irq)) {
+ 		desc->status |= IRQ_MOVE_PCNTXT;
+ 		if (trigger)
+@@ -1529,7 +1563,7 @@ static void ioapic_register_intr(int irq
+ 						      handle_edge_irq, "edge");
+ 		return;
+ 	}
+-#endif
++
+ 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ 	    trigger == IOAPIC_LEVEL)
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+@@ -1544,37 +1578,44 @@ static void ioapic_register_intr(int irq
+ #define ioapic_register_intr(irq, desc, trigger) evtchn_register_pirq(irq)
+ #endif
+ 
+-static int setup_ioapic_entry(int apic, int irq,
+-			      struct IO_APIC_route_entry *entry,
+-			      unsigned int destination, int trigger,
+-			      int polarity, int vector)
++int setup_ioapic_entry(int apic_id, int irq,
++		       struct IO_APIC_route_entry *entry,
++		       unsigned int destination, int trigger,
++		       int polarity, int vector, int pin)
+ {
+ 	/*
+ 	 * add it to the IO-APIC irq-routing table:
+ 	 */
+ 	memset(entry,0,sizeof(*entry));
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	if (intr_remapping_enabled) {
+-		struct intel_iommu *iommu = map_ioapic_to_ir(apic);
++#ifndef CONFIG_XEN
++		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
+ 		struct irte irte;
+ 		struct IR_IO_APIC_route_entry *ir_entry =
+ 			(struct IR_IO_APIC_route_entry *) entry;
+ 		int index;
+ 
+ 		if (!iommu)
+-			panic("No mapping iommu for ioapic %d\n", apic);
++			panic("No mapping iommu for ioapic %d\n", apic_id);
+ 
+ 		index = alloc_irte(iommu, irq, 1);
+ 		if (index < 0)
+-			panic("Failed to allocate IRTE for ioapic %d\n", apic);
++			panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
+ 
+ 		memset(&irte, 0, sizeof(irte));
+ 
+ 		irte.present = 1;
+-		irte.dst_mode = INT_DEST_MODE;
+-		irte.trigger_mode = trigger;
+-		irte.dlvry_mode = INT_DELIVERY_MODE;
++		irte.dst_mode = apic->irq_dest_mode;
++		/*
++		 * Trigger mode in the IRTE will always be edge, and the
++		 * actual level or edge trigger will be setup in the IO-APIC
++		 * RTE. This will help simplify level triggered irq migration.
++		 * For more details, see the comments above explainig IO-APIC
++		 * irq migration in the presence of interrupt-remapping.
++		 */
++		irte.trigger_mode = 0;
++		irte.dlvry_mode = apic->irq_delivery_mode;
+ 		irte.vector = vector;
+ 		irte.dest_id = IRTE_DEST(destination);
+ 
+@@ -1584,18 +1625,22 @@ static int setup_ioapic_entry(int apic, 
+ 		ir_entry->zero = 0;
+ 		ir_entry->format = 1;
+ 		ir_entry->index = (index & 0x7fff);
+-	} else
++		/*
++		 * IO-APIC RTE will be configured with virtual vector.
++		 * irq handler will do the explicit EOI to the io-apic.
++		 */
++		ir_entry->vector = pin;
+ #endif
+-	{
+-		entry->delivery_mode = INT_DELIVERY_MODE;
+-		entry->dest_mode = INT_DEST_MODE;
++	} else {
++		entry->delivery_mode = apic->irq_delivery_mode;
++		entry->dest_mode = apic->irq_dest_mode;
+ 		entry->dest = destination;
++		entry->vector = vector;
+ 	}
+ 
+ 	entry->mask = 0;				/* enable IRQ */
+ 	entry->trigger = trigger;
+ 	entry->polarity = polarity;
+-	entry->vector = vector;
+ 
+ 	/* Mask level triggered irqs.
+ 	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+@@ -1605,7 +1650,7 @@ static int setup_ioapic_entry(int apic, 
+ 	return 0;
+ }
+ 
+-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc,
++static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc,
+ 			      int trigger, int polarity)
+ {
+ 	struct irq_cfg *cfg;
+@@ -1617,26 +1662,26 @@ static void setup_IO_APIC_irq(int apic, 
+ 
+ 	cfg = desc->chip_data;
+ 
+-	if (assign_irq_vector(irq, cfg, TARGET_CPUS))
++	if (assign_irq_vector(irq, cfg, apic->target_cpus()))
+ 		return;
+ 
+ #ifndef CONFIG_XEN
+-	dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
++	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+ #else
+-	dest = cpu_mask_to_apicid(TARGET_CPUS);
++	dest = 0; /* meaningless */
+ #endif
+ 
+ 	apic_printk(APIC_VERBOSE,KERN_DEBUG
+ 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+ 		    "IRQ %d Mode:%i Active:%i)\n",
+-		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
++		    apic_id, mp_ioapics[apic_id].apicid, pin, cfg->vector,
+ 		    irq, trigger, polarity);
+ 
+ 
+-	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
+-			       dest, trigger, polarity, cfg->vector)) {
++	if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry,
++			       dest, trigger, polarity, cfg->vector, pin)) {
+ 		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+-		       mp_ioapics[apic].mp_apicid, pin);
++		       mp_ioapics[apic_id].apicid, pin);
+ 		__clear_irq_vector(irq, cfg);
+ 		return;
+ 	}
+@@ -1645,12 +1690,12 @@ static void setup_IO_APIC_irq(int apic, 
+ 	if (irq < NR_IRQS_LEGACY)
+ 		disable_8259A_irq(irq);
+ 
+-	ioapic_write_entry(apic, pin, entry);
++	ioapic_write_entry(apic_id, pin, entry);
+ }
+ 
+ static void __init setup_IO_APIC_irqs(void)
+ {
+-	int apic, pin, idx, irq;
++	int apic_id, pin, idx, irq;
+ 	int notcon = 0;
+ 	struct irq_desc *desc;
+ 	struct irq_cfg *cfg;
+@@ -1658,21 +1703,19 @@ static void __init setup_IO_APIC_irqs(vo
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
++		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+ 
+-			idx = find_irq_entry(apic, pin, mp_INT);
++			idx = find_irq_entry(apic_id, pin, mp_INT);
+ 			if (idx == -1) {
+ 				if (!notcon) {
+ 					notcon = 1;
+ 					apic_printk(APIC_VERBOSE,
+ 						KERN_DEBUG " %d-%d",
+-						mp_ioapics[apic].mp_apicid,
+-						pin);
++						mp_ioapics[apic_id].apicid, pin);
+ 				} else
+ 					apic_printk(APIC_VERBOSE, " %d-%d",
+-						mp_ioapics[apic].mp_apicid,
+-						pin);
++						mp_ioapics[apic_id].apicid, pin);
+ 				continue;
+ 			}
+ 			if (notcon) {
+@@ -1681,23 +1724,30 @@ static void __init setup_IO_APIC_irqs(vo
+ 				notcon = 0;
+ 			}
+ 
+-			irq = pin_2_irq(idx, apic, pin);
++			irq = pin_2_irq(idx, apic_id, pin);
++
+ #if defined(CONFIG_XEN)
+-			if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS)
++			if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+ 				continue;
+-#elif defined(CONFIG_X86_32)
+-			if (multi_timer_check(apic, irq))
++#else
++			/*
++			 * Skip the timer IRQ if there's a quirk handler
++			 * installed and if it returns 1:
++			 */
++			if (apic->multi_timer_check &&
++					apic->multi_timer_check(apic_id, irq))
+ 				continue;
+ #endif
++
+ 			desc = irq_to_desc_alloc_cpu(irq, cpu);
+ 			if (!desc) {
+ 				printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+ 				continue;
+ 			}
+ 			cfg = desc->chip_data;
+-			add_pin_to_irq_cpu(cfg, cpu, apic, pin);
++			add_pin_to_irq_cpu(cfg, cpu, apic_id, pin);
+ 
+-			setup_IO_APIC_irq(apic, pin, irq, desc,
++			setup_IO_APIC_irq(apic_id, pin, irq, desc,
+ 					irq_trigger(idx), irq_polarity(idx));
+ 		}
+ 	}
+@@ -1711,15 +1761,13 @@ static void __init setup_IO_APIC_irqs(vo
+ /*
+  * Set up the timer pin, possibly with the 8259A-master behind.
+  */
+-static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
++static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
+ 					int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	if (intr_remapping_enabled)
+ 		return;
+-#endif
+ 
+ 	memset(&entry, 0, sizeof(entry));
+ 
+@@ -1727,10 +1775,10 @@ static void __init setup_timer_IRQ0_pin(
+ 	 * We use logical delivery to get the timer IRQ
+ 	 * to the first CPU.
+ 	 */
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.mask = 1;					/* mask IRQ now */
+-	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
+-	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.dest_mode = apic->irq_dest_mode;
++	entry.mask = 0;			/* don't mask IRQ for edge */
++	entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus());
++	entry.delivery_mode = apic->irq_delivery_mode;
+ 	entry.polarity = 0;
+ 	entry.trigger = 0;
+ 	entry.vector = vector;
+@@ -1744,7 +1792,7 @@ static void __init setup_timer_IRQ0_pin(
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+-	ioapic_write_entry(apic, pin, entry);
++	ioapic_write_entry(apic_id, pin, entry);
+ }
+ 
+ 
+@@ -1766,7 +1814,7 @@ __apicdebuginit(void) print_IO_APIC(void
+ 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+ 	for (i = 0; i < nr_ioapics; i++)
+ 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+-		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
++		       mp_ioapics[i].apicid, nr_ioapic_registers[i]);
+ 
+ 	/*
+ 	 * We are a bit conservative about what we expect.  We have to
+@@ -1786,7 +1834,7 @@ __apicdebuginit(void) print_IO_APIC(void
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	printk("\n");
+-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid);
+ 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+ 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+@@ -2050,13 +2098,6 @@ void __init enable_IO_APIC(void)
+ 	int apic;
+ 	unsigned long flags;
+ 
+-#ifdef CONFIG_X86_32
+-	int i;
+-	if (!pirqs_enabled)
+-		for (i = 0; i < MAX_PIRQS; i++)
+-			pirq_entries[i] = -1;
+-#endif
+-
+ 	/*
+ 	 * The number of IO-APIC IRQ registers (== #pins):
+ 	 */
+@@ -2129,8 +2170,13 @@ void disable_IO_APIC(void)
+ 	 * If the i8259 is routed through an IOAPIC
+ 	 * Put that IOAPIC in virtual wire mode
+ 	 * so legacy interrupts can be delivered.
++	 *
++	 * With interrupt-remapping, for now we will use virtual wire A mode,
++	 * as virtual wire B is little complex (need to configure both
++	 * IOAPIC RTE aswell as interrupt-remapping table entry).
++	 * As this gets called during crash dump, keep this simple for now.
+ 	 */
+-	if (ioapic_i8259.pin != -1) {
++	if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
+ 		struct IO_APIC_route_entry entry;
+ 
+ 		memset(&entry, 0, sizeof(entry));
+@@ -2150,7 +2196,10 @@ void disable_IO_APIC(void)
+ 		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+ 	}
+ 
+-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
++	/*
++	 * Use virtual wire A mode when interrupt remapping is enabled.
++	 */
++	disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
+ }
+ 
+ #ifdef CONFIG_X86_32
+@@ -2165,7 +2214,7 @@ static void __init setup_ioapic_ids_from
+ {
+ 	union IO_APIC_reg_00 reg_00;
+ 	physid_mask_t phys_id_present_map;
+-	int apic;
++	int apic_id;
+ 	int i;
+ 	unsigned char old_id;
+ 	unsigned long flags;
+@@ -2184,26 +2233,26 @@ static void __init setup_ioapic_ids_from
+ 	 * This is broken; anything with a real cpu count has to
+ 	 * circumvent this idiocy regardless.
+ 	 */
+-	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
++	phys_id_present_map = apic->ioapic_phys_id_map(phys_cpu_present_map);
+ 
+ 	/*
+ 	 * Set the IOAPIC ID to the value stored in the MPC table.
+ 	 */
+-	for (apic = 0; apic < nr_ioapics; apic++) {
++	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
+ 
+ 		/* Read the register 0 value */
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
++		reg_00.raw = io_apic_read(apic_id, 0);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+-		old_id = mp_ioapics[apic].mp_apicid;
++		old_id = mp_ioapics[apic_id].apicid;
+ 
+-		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
++		if (mp_ioapics[apic_id].apicid >= get_physical_broadcast()) {
+ 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+-				apic, mp_ioapics[apic].mp_apicid);
++				apic_id, mp_ioapics[apic_id].apicid);
+ 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ 				reg_00.bits.ID);
+-			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
++			mp_ioapics[apic_id].apicid = reg_00.bits.ID;
+ 		}
+ 
+ 		/*
+@@ -2211,10 +2260,10 @@ static void __init setup_ioapic_ids_from
+ 		 * system must have a unique ID or we get lots of nice
+ 		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+ 		 */
+-		if (check_apicid_used(phys_id_present_map,
+-					mp_ioapics[apic].mp_apicid)) {
++		if (apic->check_apicid_used(phys_id_present_map,
++					mp_ioapics[apic_id].apicid)) {
+ 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+-				apic, mp_ioapics[apic].mp_apicid);
++				apic_id, mp_ioapics[apic_id].apicid);
+ 			for (i = 0; i < get_physical_broadcast(); i++)
+ 				if (!physid_isset(i, phys_id_present_map))
+ 					break;
+@@ -2223,13 +2272,13 @@ static void __init setup_ioapic_ids_from
+ 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ 				i);
+ 			physid_set(i, phys_id_present_map);
+-			mp_ioapics[apic].mp_apicid = i;
++			mp_ioapics[apic_id].apicid = i;
+ 		} else {
+ 			physid_mask_t tmp;
+-			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
++			tmp = apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid);
+ 			apic_printk(APIC_VERBOSE, "Setting %d in the "
+ 					"phys_id_present_map\n",
+-					mp_ioapics[apic].mp_apicid);
++					mp_ioapics[apic_id].apicid);
+ 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+ 		}
+ 
+@@ -2238,11 +2287,11 @@ static void __init setup_ioapic_ids_from
+ 		 * We need to adjust the IRQ routing table
+ 		 * if the ID changed.
+ 		 */
+-		if (old_id != mp_ioapics[apic].mp_apicid)
++		if (old_id != mp_ioapics[apic_id].apicid)
+ 			for (i = 0; i < mp_irq_entries; i++)
+-				if (mp_irqs[i].mp_dstapic == old_id)
+-					mp_irqs[i].mp_dstapic
+-						= mp_ioapics[apic].mp_apicid;
++				if (mp_irqs[i].dstapic == old_id)
++					mp_irqs[i].dstapic
++						= mp_ioapics[apic_id].apicid;
+ 
+ 		/*
+ 		 * Read the right value from the MPC table and
+@@ -2250,20 +2299,20 @@ static void __init setup_ioapic_ids_from
+ 		 */
+ 		apic_printk(APIC_VERBOSE, KERN_INFO
+ 			"...changing IO-APIC physical APIC ID to %d ...",
+-			mp_ioapics[apic].mp_apicid);
++			mp_ioapics[apic_id].apicid);
+ 
+-		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
++		reg_00.bits.ID = mp_ioapics[apic_id].apicid;
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(apic, 0, reg_00.raw);
++		io_apic_write(apic_id, 0, reg_00.raw);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 		/*
+ 		 * Sanity check
+ 		 */
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
++		reg_00.raw = io_apic_read(apic_id, 0);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
++		if (reg_00.bits.ID != mp_ioapics[apic_id].apicid)
+ 			printk("could not set ID!\n");
+ 		else
+ 			apic_printk(APIC_VERBOSE, " ok.\n");
+@@ -2366,7 +2415,7 @@ static int ioapic_retrigger_irq(unsigned
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
++	apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return 1;
+@@ -2374,7 +2423,7 @@ static int ioapic_retrigger_irq(unsigned
+ #else
+ static int ioapic_retrigger_irq(unsigned int irq)
+ {
+-	send_IPI_self(irq_cfg(irq)->vector);
++	apic->send_IPI_self(irq_cfg(irq)->vector);
+ 
+ 	return 1;
+ }
+@@ -2392,37 +2441,24 @@ static int ioapic_retrigger_irq(unsigned
+ #ifdef CONFIG_SMP
+ 
+ #ifdef CONFIG_INTR_REMAP
+-static void ir_irq_migration(struct work_struct *work);
+-
+-static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
+ 
+ /*
+  * Migrate the IO-APIC irq in the presence of intr-remapping.
+  *
+- * For edge triggered, irq migration is a simple atomic update(of vector
+- * and cpu destination) of IRTE and flush the hardware cache.
+- *
+- * For level triggered, we need to modify the io-apic RTE aswell with the update
+- * vector information, along with modifying IRTE with vector and destination.
+- * So irq migration for level triggered is little  bit more complex compared to
+- * edge triggered migration. But the good news is, we use the same algorithm
+- * for level triggered migration as we have today, only difference being,
+- * we now initiate the irq migration from process context instead of the
+- * interrupt context.
++ * For both level and edge triggered, irq migration is a simple atomic
++ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
+  *
+- * In future, when we do a directed EOI (combined with cpu EOI broadcast
+- * suppression) to the IO-APIC, level triggered irq migration will also be
+- * as simple as edge triggered migration and we can do the irq migration
+- * with a simple atomic update to IO-APIC RTE.
++ * For level triggered, we eliminate the io-apic RTE modification (with the
++ * updated vector information), by using a virtual vector (io-apic pin number).
++ * Real vector that is used for interrupting cpu will be coming from
++ * the interrupt-remapping table entry.
+  */
+ static void
+ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ {
+ 	struct irq_cfg *cfg;
+ 	struct irte irte;
+-	int modify_ioapic_rte;
+ 	unsigned int dest;
+-	unsigned long flags;
+ 	unsigned int irq;
+ 
+ 	if (!cpumask_intersects(mask, cpu_online_mask))
+@@ -2438,14 +2474,7 @@ migrate_ioapic_irq_desc(struct irq_desc 
+ 
+ 	set_extra_move_desc(desc, mask);
+ 
+-	dest = cpu_mask_to_apicid_and(cfg->domain, mask);
+-
+-	modify_ioapic_rte = desc->status & IRQ_LEVEL;
+-	if (modify_ioapic_rte) {
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		__target_IO_APIC_irq(irq, dest, cfg);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-	}
++	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+ 
+ 	irte.vector = cfg->vector;
+ 	irte.dest_id = IRTE_DEST(dest);
+@@ -2458,61 +2487,7 @@ migrate_ioapic_irq_desc(struct irq_desc 
+ 	if (cfg->move_in_progress)
+ 		send_cleanup_vector(cfg);
+ 
+-	cpumask_copy(&desc->affinity, mask);
+-}
+-
+-static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
+-{
+-	int ret = -1;
+-	struct irq_cfg *cfg = desc->chip_data;
+-
+-	mask_IO_APIC_irq_desc(desc);
+-
+-	if (io_apic_level_ack_pending(cfg)) {
+-		/*
+-		 * Interrupt in progress. Migrating irq now will change the
+-		 * vector information in the IO-APIC RTE and that will confuse
+-		 * the EOI broadcast performed by cpu.
+-		 * So, delay the irq migration to the next instance.
+-		 */
+-		schedule_delayed_work(&ir_migration_work, 1);
+-		goto unmask;
+-	}
+-
+-	/* everthing is clear. we have right of way */
+-	migrate_ioapic_irq_desc(desc, &desc->pending_mask);
+-
+-	ret = 0;
+-	desc->status &= ~IRQ_MOVE_PENDING;
+-	cpumask_clear(&desc->pending_mask);
+-
+-unmask:
+-	unmask_IO_APIC_irq_desc(desc);
+-
+-	return ret;
+-}
+-
+-static void ir_irq_migration(struct work_struct *work)
+-{
+-	unsigned int irq;
+-	struct irq_desc *desc;
+-
+-	for_each_irq_desc(irq, desc) {
+-		if (desc->status & IRQ_MOVE_PENDING) {
+-			unsigned long flags;
+-
+-			spin_lock_irqsave(&desc->lock, flags);
+-			if (!desc->chip->set_affinity ||
+-			    !(desc->status & IRQ_MOVE_PENDING)) {
+-				desc->status &= ~IRQ_MOVE_PENDING;
+-				spin_unlock_irqrestore(&desc->lock, flags);
+-				continue;
+-			}
+-
+-			desc->chip->set_affinity(irq, &desc->pending_mask);
+-			spin_unlock_irqrestore(&desc->lock, flags);
+-		}
+-	}
++	cpumask_copy(desc->affinity, mask);
+ }
+ 
+ /*
+@@ -2521,13 +2496,6 @@ static void ir_irq_migration(struct work
+ static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+ 					    const struct cpumask *mask)
+ {
+-	if (desc->status & IRQ_LEVEL) {
+-		desc->status |= IRQ_MOVE_PENDING;
+-		cpumask_copy(&desc->pending_mask, mask);
+-		migrate_irq_remapped_level_desc(desc);
+-		return;
+-	}
+-
+ 	migrate_ioapic_irq_desc(desc, mask);
+ }
+ static void set_ir_ioapic_affinity_irq(unsigned int irq,
+@@ -2537,6 +2505,11 @@ static void set_ir_ioapic_affinity_irq(u
+ 
+ 	set_ir_ioapic_affinity_irq_desc(desc, mask);
+ }
++#else
++static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
++						   const struct cpumask *mask)
++{
++}
+ #endif
+ 
+ asmlinkage void smp_irq_move_cleanup_interrupt(void)
+@@ -2550,6 +2523,7 @@ asmlinkage void smp_irq_move_cleanup_int
+ 	me = smp_processor_id();
+ 	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+ 		unsigned int irq;
++		unsigned int irr;
+ 		struct irq_desc *desc;
+ 		struct irq_cfg *cfg;
+ 		irq = __get_cpu_var(vector_irq)[vector];
+@@ -2569,6 +2543,18 @@ asmlinkage void smp_irq_move_cleanup_int
+ 		if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
+ 			goto unlock;
+ 
++		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
++		/*
++		 * Check if the vector that needs to be cleanedup is
++		 * registered at the cpu's IRR. If so, then this is not
++		 * the best time to clean it up. Lets clean it up in the
++		 * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
++		 * to myself.
++		 */
++		if (irr  & (1 << (vector % 32))) {
++			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
++			goto unlock;
++		}
+ 		__get_cpu_var(vector_irq)[vector] = -1;
+ 		cfg->move_cleanup_count--;
+ unlock:
+@@ -2591,7 +2577,7 @@ static void irq_complete_move(struct irq
+ 
+ 		/* domain has not changed, but affinity did */
+ 		me = smp_processor_id();
+-		if (cpu_isset(me, desc->affinity)) {
++		if (cpumask_test_cpu(me, desc->affinity)) {
+ 			*descp = desc = move_irq_desc(desc, me);
+ 			/* get the new one */
+ 			cfg = desc->chip_data;
+@@ -2617,17 +2603,51 @@ static void irq_complete_move(struct irq
+ static inline void irq_complete_move(struct irq_desc **descp) {}
+ #endif
+ 
+-#ifdef CONFIG_INTR_REMAP
++static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
++{
++	int apic, pin;
++	struct irq_pin_list *entry;
++
++	entry = cfg->irq_2_pin;
++	for (;;) {
++
++		if (!entry)
++			break;
++
++		apic = entry->apic;
++		pin = entry->pin;
++		io_apic_eoi(apic, pin);
++		entry = entry->next;
++	}
++}
++
++static void
++eoi_ioapic_irq(struct irq_desc *desc)
++{
++	struct irq_cfg *cfg;
++	unsigned long flags;
++	unsigned int irq;
++
++	irq = desc->irq;
++	cfg = desc->chip_data;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__eoi_ioapic_irq(irq, cfg);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#ifdef CONFIG_X86_X2APIC
+ static void ack_x2apic_level(unsigned int irq)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
+ 	ack_x2APIC_irq();
++	eoi_ioapic_irq(desc);
+ }
+ 
+ static void ack_x2apic_edge(unsigned int irq)
+ {
+ 	ack_x2APIC_irq();
+ }
+-
+ #endif
+ 
+ static void ack_apic_edge(unsigned int irq)
+@@ -2693,6 +2713,9 @@ static void ack_apic_level(unsigned int 
+ 	 */
+ 	ack_APIC_irq();
+ 
++	if (irq_remapped(irq))
++		eoi_ioapic_irq(desc);
++
+ 	/* Now we can move and renable the irq */
+ 	if (unlikely(do_unmask_irq)) {
+ 		/* Only migrate the irq if the ack has been received.
+@@ -2738,6 +2761,26 @@ static void ack_apic_level(unsigned int 
+ #endif
+ }
+ 
++#ifdef CONFIG_INTR_REMAP
++static void ir_ack_apic_edge(unsigned int irq)
++{
++#ifdef CONFIG_X86_X2APIC
++       if (x2apic_enabled())
++               return ack_x2apic_edge(irq);
++#endif
++       return ack_apic_edge(irq);
++}
++
++static void ir_ack_apic_level(unsigned int irq)
++{
++#ifdef CONFIG_X86_X2APIC
++       if (x2apic_enabled())
++               return ack_x2apic_level(irq);
++#endif
++       return ack_apic_level(irq);
++}
++#endif /* CONFIG_INTR_REMAP */
++
+ static struct irq_chip ioapic_chip __read_mostly = {
+ 	.name		= "IO-APIC",
+ 	.startup	= startup_ioapic_irq,
+@@ -2751,20 +2794,20 @@ static struct irq_chip ioapic_chip __rea
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+ 
+-#ifdef CONFIG_INTR_REMAP
+ static struct irq_chip ir_ioapic_chip __read_mostly = {
+ 	.name		= "IR-IO-APIC",
+ 	.startup	= startup_ioapic_irq,
+ 	.mask		= mask_IO_APIC_irq,
+ 	.unmask		= unmask_IO_APIC_irq,
+-	.ack		= ack_x2apic_edge,
+-	.eoi		= ack_x2apic_level,
++#ifdef CONFIG_INTR_REMAP
++	.ack		= ir_ack_apic_edge,
++	.eoi		= ir_ack_apic_level,
+ #ifdef CONFIG_SMP
+ 	.set_affinity	= set_ir_ioapic_affinity_irq,
+ #endif
++#endif
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+-#endif
+ #endif /* CONFIG_XEN */
+ 
+ static inline void init_IO_APIC_traps(void)
+@@ -2786,7 +2829,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 */
+ 	for_each_irq_desc(irq, desc) {
+ #ifdef CONFIG_XEN
+-		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS)
++		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+ 			continue;
+ #endif
+ 		cfg = desc->chip_data;
+@@ -2948,19 +2991,15 @@ static inline void __init check_timer(vo
+ 	int cpu = boot_cpu_id;
+ 	int apic1, pin1, apic2, pin2;
+ 	unsigned long flags;
+-	unsigned int ver;
+ 	int no_pin1 = 0;
+ 
+ 	local_irq_save(flags);
+ 
+-	ver = apic_read(APIC_LVR);
+-	ver = GET_APIC_VERSION(ver);
+-
+ 	/*
+ 	 * get/set the timer IRQ vector:
+ 	 */
+ 	disable_8259A_irq(0);
+-	assign_irq_vector(0, cfg, TARGET_CPUS);
++	assign_irq_vector(0, cfg, apic->target_cpus());
+ 
+ 	/*
+ 	 * As IRQ0 is to be enabled in the 8259A, the virtual
+@@ -2974,7 +3013,13 @@ static inline void __init check_timer(vo
+ 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ 	init_8259A(1);
+ #ifdef CONFIG_X86_32
+-	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
++	{
++		unsigned int ver;
++
++		ver = apic_read(APIC_LVR);
++		ver = GET_APIC_VERSION(ver);
++		timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
++	}
+ #endif
+ 
+ 	pin1  = find_isa_irq_pin(0, mp_INT);
+@@ -2994,10 +3039,8 @@ static inline void __init check_timer(vo
+ 	 * 8259A.
+ 	 */
+ 	if (pin1 == -1) {
+-#ifdef CONFIG_INTR_REMAP
+ 		if (intr_remapping_enabled)
+ 			panic("BIOS bug: timer not connected to IO-APIC");
+-#endif
+ 		pin1 = pin2;
+ 		apic1 = apic2;
+ 		no_pin1 = 1;
+@@ -3013,8 +3056,17 @@ static inline void __init check_timer(vo
+ 		if (no_pin1) {
+ 			add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
+ 			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
++		} else {
++			/* for edge trigger, setup_IO_APIC_irq already
++			 * leave it unmasked.
++			 * so only need to unmask if it is level-trigger
++			 * do we really have level trigger timer?
++			 */
++			int idx;
++			idx = find_irq_entry(apic1, pin1, mp_INT);
++			if (idx != -1 && irq_trigger(idx))
++				unmask_IO_APIC_irq_desc(desc);
+ 		}
+-		unmask_IO_APIC_irq_desc(desc);
+ 		if (timer_irq_works()) {
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+ 				setup_nmi();
+@@ -3024,10 +3076,9 @@ static inline void __init check_timer(vo
+ 				clear_IO_APIC_pin(0, pin1);
+ 			goto out;
+ 		}
+-#ifdef CONFIG_INTR_REMAP
+ 		if (intr_remapping_enabled)
+ 			panic("timer doesn't work through Interrupt-remapped IO-APIC");
+-#endif
++		local_irq_disable();
+ 		clear_IO_APIC_pin(apic1, pin1);
+ 		if (!no_pin1)
+ 			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+@@ -3042,7 +3093,6 @@ static inline void __init check_timer(vo
+ 		 */
+ 		replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
+ 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+-		unmask_IO_APIC_irq_desc(desc);
+ 		enable_8259A_irq(0);
+ 		if (timer_irq_works()) {
+ 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+@@ -3057,6 +3107,7 @@ static inline void __init check_timer(vo
+ 		/*
+ 		 * Cleanup, just in case ...
+ 		 */
++		local_irq_disable();
+ 		disable_8259A_irq(0);
+ 		clear_IO_APIC_pin(apic2, pin2);
+ 		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+@@ -3082,6 +3133,7 @@ static inline void __init check_timer(vo
+ 		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
++	local_irq_disable();
+ 	disable_8259A_irq(0);
+ 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+ 	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+@@ -3099,6 +3151,7 @@ static inline void __init check_timer(vo
+ 		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
++	local_irq_disable();
+ 	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+ 	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+ 		"report.  Then try booting with the 'noapic' option.\n");
+@@ -3131,7 +3184,7 @@ out:
+ void __init setup_IO_APIC(void)
+ {
+ 
+-#if defined(CONFIG_X86_32) || defined(CONFIG_XEN)
++#ifdef CONFIG_XEN
+ 	enable_IO_APIC();
+ #else
+ 	/*
+@@ -3213,8 +3266,8 @@ static int ioapic_resume(struct sys_devi
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	reg_00.raw = io_apic_read(dev->id, 0);
+-	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
+-		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
++	if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].apicid;
+ 		io_apic_write(dev->id, 0, reg_00.raw);
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+@@ -3264,6 +3317,7 @@ static int __init ioapic_init_sysfs(void
+ 
+ device_initcall(ioapic_init_sysfs);
+ 
++static int nr_irqs_gsi = NR_IRQS_LEGACY;
+ /*
+  * Dynamic irq allocate and deallocation
+  */
+@@ -3278,11 +3332,11 @@ unsigned int create_irq_nr(unsigned int 
+ 	struct irq_desc *desc_new = NULL;
+ 
+ 	irq = 0;
+-	spin_lock_irqsave(&vector_lock, flags);
+-	for (new = irq_want; new < NR_IRQS; new++) {
+-		if (platform_legacy_irq(new))
+-			continue;
++	if (irq_want < nr_irqs_gsi)
++		irq_want = nr_irqs_gsi;
+ 
++	spin_lock_irqsave(&vector_lock, flags);
++	for (new = irq_want; new < nr_irqs; new++) {
+ 		desc_new = irq_to_desc_alloc_cpu(new, cpu);
+ 		if (!desc_new) {
+ 			printk(KERN_INFO "can not get irq_desc for %d\n", new);
+@@ -3292,7 +3346,7 @@ unsigned int create_irq_nr(unsigned int 
+ 
+ 		if (cfg_new->vector != 0)
+ 			continue;
+-		if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0)
++		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
+ 			irq = new;
+ 		break;
+ 	}
+@@ -3307,7 +3361,6 @@ unsigned int create_irq_nr(unsigned int 
+ 	return irq;
+ }
+ 
+-static int nr_irqs_gsi = NR_IRQS_LEGACY;
+ int create_irq(void)
+ {
+ 	unsigned int irq_want;
+@@ -3336,9 +3389,7 @@ void destroy_irq(unsigned int irq)
+ 	if (desc)
+ 		desc->chip_data = cfg;
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	free_irte(irq);
+-#endif
+ 	spin_lock_irqsave(&vector_lock, flags);
+ 	__clear_irq_vector(irq, cfg);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+@@ -3355,14 +3406,16 @@ static int msi_compose_msg(struct pci_de
+ 	int err;
+ 	unsigned dest;
+ 
++	if (disable_apic)
++		return -ENXIO;
++
+ 	cfg = irq_cfg(irq);
+-	err = assign_irq_vector(irq, cfg, TARGET_CPUS);
++	err = assign_irq_vector(irq, cfg, apic->target_cpus());
+ 	if (err)
+ 		return err;
+ 
+-	dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
++	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	if (irq_remapped(irq)) {
+ 		struct irte irte;
+ 		int ir_index;
+@@ -3374,9 +3427,9 @@ static int msi_compose_msg(struct pci_de
+ 		memset (&irte, 0, sizeof(irte));
+ 
+ 		irte.present = 1;
+-		irte.dst_mode = INT_DEST_MODE;
++		irte.dst_mode = apic->irq_dest_mode;
+ 		irte.trigger_mode = 0; /* edge */
+-		irte.dlvry_mode = INT_DELIVERY_MODE;
++		irte.dlvry_mode = apic->irq_delivery_mode;
+ 		irte.vector = cfg->vector;
+ 		irte.dest_id = IRTE_DEST(dest);
+ 
+@@ -3388,16 +3441,19 @@ static int msi_compose_msg(struct pci_de
+ 				  MSI_ADDR_IR_SHV |
+ 				  MSI_ADDR_IR_INDEX1(ir_index) |
+ 				  MSI_ADDR_IR_INDEX2(ir_index);
+-	} else
+-#endif
+-	{
+-		msg->address_hi = MSI_ADDR_BASE_HI;
++	} else {
++		if (x2apic_enabled())
++			msg->address_hi = MSI_ADDR_BASE_HI |
++					  MSI_ADDR_EXT_DEST_ID(dest);
++		else
++			msg->address_hi = MSI_ADDR_BASE_HI;
++
+ 		msg->address_lo =
+ 			MSI_ADDR_BASE_LO |
+-			((INT_DEST_MODE == 0) ?
++			((apic->irq_dest_mode == 0) ?
+ 				MSI_ADDR_DEST_MODE_PHYSICAL:
+ 				MSI_ADDR_DEST_MODE_LOGICAL) |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++			((apic->irq_delivery_mode != dest_LowestPrio) ?
+ 				MSI_ADDR_REDIRECTION_CPU:
+ 				MSI_ADDR_REDIRECTION_LOWPRI) |
+ 			MSI_ADDR_DEST_ID(dest);
+@@ -3405,7 +3461,7 @@ static int msi_compose_msg(struct pci_de
+ 		msg->data =
+ 			MSI_DATA_TRIGGER_EDGE |
+ 			MSI_DATA_LEVEL_ASSERT |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++			((apic->irq_delivery_mode != dest_LowestPrio) ?
+ 				MSI_DATA_DELIVERY_FIXED:
+ 				MSI_DATA_DELIVERY_LOWPRI) |
+ 			MSI_DATA_VECTOR(cfg->vector);
+@@ -3491,15 +3547,16 @@ static struct irq_chip msi_chip = {
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+ 
+-#ifdef CONFIG_INTR_REMAP
+ static struct irq_chip msi_ir_chip = {
+ 	.name		= "IR-PCI-MSI",
+ 	.unmask		= unmask_msi_irq,
+ 	.mask		= mask_msi_irq,
+-	.ack		= ack_x2apic_edge,
++#ifdef CONFIG_INTR_REMAP
++	.ack		= ir_ack_apic_edge,
+ #ifdef CONFIG_SMP
+ 	.set_affinity	= ir_set_msi_irq_affinity,
+ #endif
++#endif
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+ 
+@@ -3529,7 +3586,6 @@ static int msi_alloc_irte(struct pci_dev
+ 	}
+ 	return index;
+ }
+-#endif
+ 
+ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
+ {
+@@ -3543,7 +3599,6 @@ static int setup_msi_irq(struct pci_dev 
+ 	set_irq_msi(irq, msidesc);
+ 	write_msi_msg(irq, &msg);
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 	if (irq_remapped(irq)) {
+ 		struct irq_desc *desc = irq_to_desc(irq);
+ 		/*
+@@ -3552,7 +3607,6 @@ static int setup_msi_irq(struct pci_dev 
+ 		desc->status |= IRQ_MOVE_PCNTXT;
+ 		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
+ 	} else
+-#endif
+ 		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+ 
+ 	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
+@@ -3560,60 +3614,26 @@ static int setup_msi_irq(struct pci_dev 
+ 	return 0;
+ }
+ 
+-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc)
+-{
+-	unsigned int irq;
+-	int ret;
+-	unsigned int irq_want;
+-
+-	irq_want = nr_irqs_gsi;
+-	irq = create_irq_nr(irq_want);
+-	if (irq == 0)
+-		return -1;
+-
+-#ifdef CONFIG_INTR_REMAP
+-	if (!intr_remapping_enabled)
+-		goto no_ir;
+-
+-	ret = msi_alloc_irte(dev, irq, 1);
+-	if (ret < 0)
+-		goto error;
+-no_ir:
+-#endif
+-	ret = setup_msi_irq(dev, msidesc, irq);
+-	if (ret < 0) {
+-		destroy_irq(irq);
+-		return ret;
+-	}
+-	return 0;
+-
+-#ifdef CONFIG_INTR_REMAP
+-error:
+-	destroy_irq(irq);
+-	return ret;
+-#endif
+-}
+-
+ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+ {
+ 	unsigned int irq;
+ 	int ret, sub_handle;
+ 	struct msi_desc *msidesc;
+ 	unsigned int irq_want;
+-
+-#ifdef CONFIG_INTR_REMAP
+-	struct intel_iommu *iommu = 0;
++	struct intel_iommu *iommu = NULL;
+ 	int index = 0;
+-#endif
++
++	/* x86 doesn't support multiple MSI yet */
++	if (type == PCI_CAP_ID_MSI && nvec > 1)
++		return 1;
+ 
+ 	irq_want = nr_irqs_gsi;
+ 	sub_handle = 0;
+ 	list_for_each_entry(msidesc, &dev->msi_list, list) {
+ 		irq = create_irq_nr(irq_want);
+-		irq_want++;
+ 		if (irq == 0)
+ 			return -1;
+-#ifdef CONFIG_INTR_REMAP
++		irq_want = irq + 1;
+ 		if (!intr_remapping_enabled)
+ 			goto no_ir;
+ 
+@@ -3641,7 +3661,6 @@ int arch_setup_msi_irqs(struct pci_dev *
+ 			set_irte_irq(irq, iommu, index, sub_handle);
+ 		}
+ no_ir:
+-#endif
+ 		ret = setup_msi_irq(dev, msidesc, irq);
+ 		if (ret < 0)
+ 			goto error;
+@@ -3659,7 +3678,7 @@ void arch_teardown_msi_irq(unsigned int 
+ 	destroy_irq(irq);
+ }
+ 
+-#ifdef CONFIG_DMAR
++#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+ #ifdef CONFIG_SMP
+ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+@@ -3740,7 +3759,7 @@ static void hpet_msi_set_affinity(unsign
+ 
+ #endif /* CONFIG_SMP */
+ 
+-struct irq_chip hpet_msi_type = {
++static struct irq_chip hpet_msi_type = {
+ 	.name = "HPET_MSI",
+ 	.unmask = hpet_msi_unmask,
+ 	.mask = hpet_msi_mask,
+@@ -3755,12 +3774,14 @@ int arch_setup_hpet_msi(unsigned int irq
+ {
+ 	int ret;
+ 	struct msi_msg msg;
++	struct irq_desc *desc = irq_to_desc(irq);
+ 
+ 	ret = msi_compose_msg(NULL, irq, &msg);
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	hpet_msi_write(irq, &msg);
++	desc->status |= IRQ_MOVE_PCNTXT;
+ 	set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq,
+ 		"edge");
+ 
+@@ -3823,13 +3844,17 @@ int arch_setup_ht_irq(unsigned int irq, 
+ 	struct irq_cfg *cfg;
+ 	int err;
+ 
++	if (disable_apic)
++		return -ENXIO;
++
+ 	cfg = irq_cfg(irq);
+-	err = assign_irq_vector(irq, cfg, TARGET_CPUS);
++	err = assign_irq_vector(irq, cfg, apic->target_cpus());
+ 	if (!err) {
+ 		struct ht_irq_msg msg;
+ 		unsigned dest;
+ 
+-		dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
++		dest = apic->cpu_mask_to_apicid_and(cfg->domain,
++						    apic->target_cpus());
+ 
+ 		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+ 
+@@ -3837,11 +3862,11 @@ int arch_setup_ht_irq(unsigned int irq, 
+ 			HT_IRQ_LOW_BASE |
+ 			HT_IRQ_LOW_DEST_ID(dest) |
+ 			HT_IRQ_LOW_VECTOR(cfg->vector) |
+-			((INT_DEST_MODE == 0) ?
++			((apic->irq_dest_mode == 0) ?
+ 				HT_IRQ_LOW_DM_PHYSICAL :
+ 				HT_IRQ_LOW_DM_LOGICAL) |
+ 			HT_IRQ_LOW_RQEOI_EDGE |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++			((apic->irq_delivery_mode != dest_LowestPrio) ?
+ 				HT_IRQ_LOW_MT_FIXED :
+ 				HT_IRQ_LOW_MT_ARBITRATED) |
+ 			HT_IRQ_LOW_IRQ_MASKED;
+@@ -3857,7 +3882,7 @@ int arch_setup_ht_irq(unsigned int irq, 
+ }
+ #endif /* CONFIG_HT_IRQ */
+ 
+-#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++#ifdef CONFIG_X86_UV
+ /*
+  * Re-target the irq to the specified CPU and enable the specified MMR located
+  * on the specified blade to allow the sending of MSIs to the specified CPU.
+@@ -3889,12 +3914,12 @@ int arch_enable_uv_irq(char *irq_name, u
+ 	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+ 
+ 	entry->vector = cfg->vector;
+-	entry->delivery_mode = INT_DELIVERY_MODE;
+-	entry->dest_mode = INT_DEST_MODE;
++	entry->delivery_mode = apic->irq_delivery_mode;
++	entry->dest_mode = apic->irq_dest_mode;
+ 	entry->polarity = 0;
+ 	entry->trigger = 0;
+ 	entry->mask = 0;
+-	entry->dest = cpu_mask_to_apicid(eligible_cpu);
++	entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
+ 
+ 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+ 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+@@ -3957,7 +3982,29 @@ void __init probe_nr_irqs_gsi(void)
+ 
+ 	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
+ }
++
++#ifdef CONFIG_SPARSE_IRQ
++int __init arch_probe_nr_irqs(void)
++{
++	int nr;
++
++	if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
++		nr_irqs = NR_VECTORS * nr_cpu_ids;
++
++	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
++#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
++	/*
++	 * for MSI and HT dyn irq
++	 */
++	nr += nr_irqs_gsi * 16;
+ #endif
++	if (nr < nr_irqs)
++		nr_irqs = nr;
++
++	return 0;
++}
++#endif
++#endif /* CONFIG_XEN */
+ 
+ /* --------------------------------------------------------------------------
+                           ACPI-based IOAPIC Configuration
+@@ -3985,7 +4032,7 @@ int __init io_apic_get_unique_id(int ioa
+ 	 */
+ 
+ 	if (physids_empty(apic_id_map))
+-		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
++		apic_id_map = apic->ioapic_phys_id_map(phys_cpu_present_map);
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	reg_00.raw = io_apic_read(ioapic, 0);
+@@ -4001,10 +4048,10 @@ int __init io_apic_get_unique_id(int ioa
+ 	 * Every APIC in a system must have a unique ID or we get lots of nice
+ 	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+ 	 */
+-	if (check_apicid_used(apic_id_map, apic_id)) {
++	if (apic->check_apicid_used(apic_id_map, apic_id)) {
+ 
+ 		for (i = 0; i < get_physical_broadcast(); i++) {
+-			if (!check_apicid_used(apic_id_map, i))
++			if (!apic->check_apicid_used(apic_id_map, i))
+ 				break;
+ 		}
+ 
+@@ -4017,7 +4064,7 @@ int __init io_apic_get_unique_id(int ioa
+ 		apic_id = i;
+ 	}
+ 
+-	tmp = apicid_to_cpu_present(apic_id);
++	tmp = apic->apicid_to_cpu_present(apic_id);
+ 	physids_or(apic_id_map, apic_id_map, tmp);
+ 
+ 	if (reg_00.bits.ID != apic_id) {
+@@ -4062,7 +4109,7 @@ int io_apic_set_pci_routing (int ioapic,
+ 	int cpu = boot_cpu_id;
+ 
+ #ifdef CONFIG_XEN
+-	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS) {
++	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
+ 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
+ 			    ioapic, irq);
+ 		return -EINVAL;
+@@ -4103,8 +4150,8 @@ int acpi_get_override_irq(int bus_irq, i
+ 		return -1;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == mp_INT &&
+-		    mp_irqs[i].mp_srcbusirq == bus_irq)
++		if (mp_irqs[i].irqtype == mp_INT &&
++		    mp_irqs[i].srcbusirq == bus_irq)
+ 			break;
+ 	if (i >= mp_irq_entries)
+ 		return -1;
+@@ -4120,7 +4167,7 @@ int acpi_get_override_irq(int bus_irq, i
+ /*
+  * This function currently is only a helper for the i386 smp boot process where
+  * we need to reprogram the ioredtbls to cater for the cpus which have come online
+- * so mask in all cases should simply be TARGET_CPUS
++ * so mask in all cases should simply be apic->target_cpus()
+  */
+ #ifdef CONFIG_SMP
+ void __init setup_ioapic_dest(void)
+@@ -4159,15 +4206,13 @@ void __init setup_ioapic_dest(void)
+ 			 */
+ 			if (desc->status &
+ 			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+-				mask = &desc->affinity;
++				mask = desc->affinity;
+ 			else
+-				mask = TARGET_CPUS;
++				mask = apic->target_cpus();
+ 
+-#ifdef CONFIG_INTR_REMAP
+ 			if (intr_remapping_enabled)
+ 				set_ir_ioapic_affinity_irq_desc(desc, mask);
+ 			else
+-#endif
+ 				set_ioapic_affinity_irq_desc(desc, mask);
+ 		}
+ 
+@@ -4220,7 +4265,7 @@ void __init ioapic_init_mappings(void)
+ 	ioapic_res = ioapic_setup_resources();
+ 	for (i = 0; i < nr_ioapics; i++) {
+ 		if (smp_found_config) {
+-			ioapic_phys = mp_ioapics[i].mp_apicaddr;
++			ioapic_phys = mp_ioapics[i].apicaddr;
+ #ifdef CONFIG_X86_32
+ 			if (!ioapic_phys) {
+ 				printk(KERN_ERR
+@@ -4260,9 +4305,12 @@ static int __init ioapic_insert_resource
+ 	struct resource *r = ioapic_resources;
+ 
+ 	if (!r) {
+-		printk(KERN_ERR
+-		       "IO APIC resources could be not be allocated.\n");
+-		return -1;
++		if (nr_ioapics > 0) {
++			printk(KERN_ERR
++				"IO APIC resources couldn't be allocated.\n");
++			return -1;
++		}
++		return 0;
+ 	}
+ 
+ 	for (i = 0; i < nr_ioapics; i++) {
+--- head-2010-01-18.orig/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -17,38 +17,8 @@
+ #include <asm/mmu_context.h>
+ #include <asm/apic.h>
+ #include <asm/proto.h>
++#include <asm/ipi.h>
+ 
+-#ifdef CONFIG_X86_32
+-#ifndef CONFIG_XEN
+-#include <mach_apic.h>
+-#include <mach_ipi.h>
+-
+-/*
+- * the following functions deal with sending IPIs between CPUs.
+- *
+- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+- */
+-
+-static inline int __prepare_ICR(unsigned int shortcut, int vector)
+-{
+-	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
+-
+-	switch (vector) {
+-	default:
+-		icr |= APIC_DM_FIXED | vector;
+-		break;
+-	case NMI_VECTOR:
+-		icr |= APIC_DM_NMI;
+-		break;
+-	}
+-	return icr;
+-}
+-
+-static inline int __prepare_ICR2(unsigned int mask)
+-{
+-	return SET_APIC_DEST_FIELD(mask);
+-}
+-#else
+ #include <xen/evtchn.h>
+ 
+ DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
+@@ -59,36 +29,10 @@ static inline void __send_IPI_one(unsign
+ 	BUG_ON(irq < 0);
+ 	notify_remote_via_irq(irq);
+ }
+-#endif
+ 
+-void __send_IPI_shortcut(unsigned int shortcut, int vector)
++static void __send_IPI_shortcut(unsigned int shortcut, int vector)
+ {
+-#ifndef CONFIG_XEN
+-	/*
+-	 * Subtle. In the case of the 'never do double writes' workaround
+-	 * we have to lock out interrupts to be safe.  As we don't care
+-	 * of the value read we use an atomic rmw access to avoid costly
+-	 * cli/sti.  Otherwise we use an even cheaper single atomic write
+-	 * to the APIC.
+-	 */
+-	unsigned int cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	apic_wait_icr_idle();
+-
+-	/*
+-	 * No need to touch the target chip field
+-	 */
+-	cfg = __prepare_ICR(shortcut, vector);
+-
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write(APIC_ICR, cfg);
+-#else
+-	int cpu;
++	unsigned int cpu;
+ 
+ 	switch (shortcut) {
+ 	case APIC_DEST_SELF:
+@@ -99,149 +43,53 @@ void __send_IPI_shortcut(unsigned int sh
+ 			if (cpu != smp_processor_id())
+ 				__send_IPI_one(cpu, vector);
+ 		break;
++	case APIC_DEST_ALLINC:
++		for_each_online_cpu(cpu)
++			__send_IPI_one(cpu, vector);
++		break;
+ 	default:
+ 		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
+ 		       vector);
+ 		break;
+ 	}
+-#endif
+ }
+ 
+-void send_IPI_self(int vector)
++void xen_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
+ {
+-	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * This is used to send an IPI with no shorthand notation (the destination is
+- * specified in bits 56 to 63 of the ICR).
+- */
+-static inline void __send_IPI_dest_field(unsigned long mask, int vector)
+-{
+-	unsigned long cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	if (unlikely(vector == NMI_VECTOR))
+-		safe_apic_wait_icr_idle();
+-	else
+-		apic_wait_icr_idle();
+-
+-	/*
+-	 * prepare target chip field
+-	 */
+-	cfg = __prepare_ICR2(mask);
+-	apic_write(APIC_ICR2, cfg);
+-
+-	/*
+-	 * program the ICR
+-	 */
+-	cfg = __prepare_ICR(0, vector);
+-
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write(APIC_ICR, cfg);
+-}
+-#endif
+-
+-/*
+- * This is only used on smaller machines.
+- */
+-void send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector)
+-{
+-#ifndef CONFIG_XEN
+-	unsigned long mask = cpumask_bits(cpumask)[0];
+-#else
+ 	unsigned int cpu;
+-#endif
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+-#ifndef CONFIG_XEN
+-	WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
+-	__send_IPI_dest_field(mask, vector);
+-#else
+ 	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
+ 	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
+-		__send_IPI_one(cpu, vector);
+-#endif
++		if (cpu != smp_processor_id())
++			__send_IPI_one(cpu, vector);
+ 	local_irq_restore(flags);
+ }
+ 
+-void send_IPI_mask_sequence(const struct cpumask *mask, int vector)
++void xen_send_IPI_mask(const struct cpumask *cpumask, int vector)
+ {
+-#ifndef CONFIG_XEN
++	unsigned int cpu;
+ 	unsigned long flags;
+-	unsigned int query_cpu;
+-
+-	/*
+-	 * Hack. The clustered APIC addressing mode doesn't allow us to send
+-	 * to an arbitrary mask, so I do a unicasts to each CPU instead. This
+-	 * should be modified to do 1 message per cluster ID - mbligh
+-	 */
+ 
+ 	local_irq_save(flags);
+-	for_each_cpu(query_cpu, mask)
+-		__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu), vector);
++	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
++	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
++		__send_IPI_one(cpu, vector);
+ 	local_irq_restore(flags);
+-#else
+-	send_IPI_mask_bitmask(mask, vector);
+-#endif
+ }
+ 
+-void send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
++void xen_send_IPI_allbutself(int vector)
+ {
+-	unsigned long flags;
+-	unsigned int query_cpu;
+-	unsigned int this_cpu = smp_processor_id();
+-
+-	/* See Hack comment above */
+-
+-	local_irq_save(flags);
+-#ifndef CONFIG_XEN
+-	for_each_cpu(query_cpu, mask)
+-		if (query_cpu != this_cpu)
+-			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
+-					      vector);
+-#else
+-	WARN_ON(!cpumask_subset(mask, cpu_online_mask));
+-	for_each_cpu_and(query_cpu, mask, cpu_online_mask)
+-		if (query_cpu != this_cpu)
+-			__send_IPI_one(query_cpu, vector);
+-#endif
+-	local_irq_restore(flags);
++	__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+ }
+ 
+-#ifndef CONFIG_XEN
+-/* must come after the send_IPI functions above for inlining */
+-static int convert_apicid_to_cpu(int apic_id)
+-{
+-	int i;
+-
+-	for_each_possible_cpu(i) {
+-		if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
+-			return i;
+-	}
+-	return -1;
++void xen_send_IPI_all(int vector)
++{
++	__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+ }
+ 
+-int safe_smp_processor_id(void)
++void xen_send_IPI_self(int vector)
+ {
+-	int apicid, cpuid;
+-
+-	if (!boot_cpu_has(X86_FEATURE_APIC))
+-		return 0;
+-
+-	apicid = hard_smp_processor_id();
+-	if (apicid == BAD_APICID)
+-		return 0;
+-
+-	cpuid = convert_apicid_to_cpu(apicid);
+-
+-	return cpuid >= 0 ? cpuid : 0;
++	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+ }
+-#endif
+-#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic/probe_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,69 @@
++/*
++ * Default generic APIC driver. This handles up to 8 CPUs.
++ *
++ * Copyright 2003 Andi Kleen, SuSE Labs.
++ * Subject to the GNU Public License, v.2
++ *
++ * Generic x86 APIC driver probe layer.
++ */
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <asm/fixmap.h>
++#include <asm/mpspec.h>
++#include <asm/apicdef.h>
++#include <asm/apic.h>
++#include <asm/setup.h>
++
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <asm/mpspec.h>
++#include <asm/fixmap.h>
++#include <asm/apicdef.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/smp.h>
++#include <linux/init.h>
++#include <asm/ipi.h>
++
++#include <linux/smp.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <asm/acpi.h>
++#include <asm/e820.h>
++#include <asm/setup.h>
++
++static int xen_phys_pkg_id(int cpuid_apic, int index_msb)
++{
++	return cpuid_apic;
++}
++
++static struct apic apic_xen = {
++
++	.name				= "default",
++
++	.irq_delivery_mode		= dest_LowestPrio,
++	/* logical delivery broadcast to all CPUs: */
++	.irq_dest_mode			= 1,
++
++	.target_cpus			= default_target_cpus,
++
++	.phys_pkg_id			= xen_phys_pkg_id,
++	.mps_oem_check			= NULL,
++
++#ifdef CONFIG_SMP
++	.send_IPI_mask			= xen_send_IPI_mask,
++	.send_IPI_mask_allbutself	= xen_send_IPI_mask_allbutself,
++	.send_IPI_allbutself		= xen_send_IPI_allbutself,
++	.send_IPI_all			= xen_send_IPI_all,
++	.send_IPI_self			= xen_send_IPI_self,
++#endif
++};
++
++struct apic *apic = &apic_xen;
++EXPORT_SYMBOL_GPL(apic);
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:52:02.000000000 +0100
+@@ -115,6 +115,11 @@ void foo(void)
+ 
+ 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+ 
++#ifdef CONFIG_XEN
++	BLANK();
++	OFFSET(XEN_START_mfn_list, start_info, mfn_list);
++#endif
++
+ #ifdef CONFIG_PARAVIRT
+ 	BLANK();
+ 	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,101 +1,94 @@
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+ #include <linux/bootmem.h>
++#include <linux/linkage.h>
+ #include <linux/bitops.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <linux/kgdb.h>
+-#include <linux/topology.h>
++#include <linux/percpu.h>
++#include <linux/string.h>
+ #include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
+ #include <linux/smp.h>
+-#include <linux/percpu.h>
+-#include <asm/i387.h>
+-#include <asm/msr.h>
+-#include <asm/io.h>
+-#include <asm/linkage.h>
++#include <linux/io.h>
++
++#include <asm/stackprotector.h>
+ #include <asm/mmu_context.h>
++#include <asm/hypervisor.h>
++#include <asm/processor.h>
++#include <asm/sections.h>
++#include <asm/topology.h>
++#include <asm/cpumask.h>
++#include <asm/pgtable.h>
++#include <asm/atomic.h>
++#include <asm/proto.h>
++#include <asm/setup.h>
++#include <asm/apic.h>
++#include <asm/desc.h>
++#include <asm/i387.h>
+ #include <asm/mtrr.h>
++#include <asm/numa.h>
++#include <asm/asm.h>
++#include <asm/cpu.h>
+ #include <asm/mce.h>
++#include <asm/msr.h>
+ #include <asm/pat.h>
+-#include <asm/asm.h>
+-#include <asm/numa.h>
+ #include <asm/smp.h>
++
+ #ifdef CONFIG_X86_LOCAL_APIC
+-#include <asm/mpspec.h>
+-#include <asm/apic.h>
+-#include <mach_apic.h>
+-#include <asm/genapic.h>
+-#elif defined(CONFIG_X86_64_XEN)
+-#include <mach_apic.h>
++#include <asm/uv/uv.h>
+ #endif
+ 
+-#include <asm/pda.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/desc.h>
+-#include <asm/atomic.h>
+-#include <asm/proto.h>
+-#include <asm/sections.h>
+-#include <asm/setup.h>
+-#include <asm/hypervisor.h>
+-
+ #ifdef CONFIG_XEN
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_LOCAL_APIC)
+-#define phys_pkg_id(a,b) a
+-#endif
+ #include <xen/interface/callback.h>
+ #endif
+ 
+ #include "cpu.h"
+ 
+-#ifdef CONFIG_X86_64
+-
+ /* all of these masks are initialized in setup_cpu_local_masks() */
++cpumask_var_t cpu_initialized_mask;
+ #ifndef CONFIG_XEN
+-cpumask_var_t cpu_callin_mask;
+ cpumask_var_t cpu_callout_mask;
++cpumask_var_t cpu_callin_mask;
+ #endif
+-cpumask_var_t cpu_initialized_mask;
+ 
+ /* representing cpus for which sibling maps can be computed */
+ cpumask_var_t cpu_sibling_setup_mask;
+ 
+-#else /* CONFIG_X86_32 */
+-
++/* correctly size the local cpu masks */
++void __init setup_cpu_local_masks(void)
++{
++	alloc_bootmem_cpumask_var(&cpu_initialized_mask);
+ #ifndef CONFIG_XEN
+-cpumask_t cpu_callin_map;
+-cpumask_t cpu_callout_map;
++	alloc_bootmem_cpumask_var(&cpu_callin_mask);
++	alloc_bootmem_cpumask_var(&cpu_callout_mask);
+ #endif
+-cpumask_t cpu_initialized;
+-cpumask_t cpu_sibling_setup_map;
+-
+-#endif /* CONFIG_X86_32 */
+-
++	alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
++}
+ 
+-static struct cpu_dev *this_cpu __cpuinitdata;
++static const struct cpu_dev *this_cpu __cpuinitdata;
+ 
++DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+ #ifdef CONFIG_X86_64
+-/* We need valid kernel segments for data and code in long mode too
+- * IRET will check the segment types  kkeil 2000/10/28
+- * Also sysret mandates a special GDT layout
+- */
+-/* The TLS descriptors are currently at a different place compared to i386.
+-   Hopefully nobody expects them at a fixed place (Wine?) */
+-DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+-	[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
+-	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
+-	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
+-	[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
+-	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
+-	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
+-} };
++	/*
++	 * We need valid kernel segments for data and code in long mode too
++	 * IRET will check the segment types  kkeil 2000/10/28
++	 * Also sysret mandates a special GDT layout
++	 *
++	 * TLS descriptors are currently at a different place compared to i386.
++	 * Hopefully nobody expects them at a fixed place (Wine?)
++	 */
++	[GDT_ENTRY_KERNEL32_CS]		= { { { 0x0000ffff, 0x00cf9b00 } } },
++	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00af9b00 } } },
++	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9300 } } },
++	[GDT_ENTRY_DEFAULT_USER32_CS]	= { { { 0x0000ffff, 0x00cffb00 } } },
++	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff300 } } },
++	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00affb00 } } },
+ #else
+-DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+-	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
+-	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
+-	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
+-	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
++	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00cf9a00 } } },
++	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9200 } } },
++	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00cffa00 } } },
++	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff200 } } },
+ #ifndef CONFIG_XEN
+ 	/*
+ 	 * Segments used for calling PnP BIOS have byte granularity.
+@@ -103,33 +96,41 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_p
+ 	 * the transfer segment sizes are set at run time.
+ 	 */
+ 	/* 32-bit code */
+-	[GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } },
++	[GDT_ENTRY_PNPBIOS_CS32]	= { { { 0x0000ffff, 0x00409a00 } } },
+ 	/* 16-bit code */
+-	[GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
++	[GDT_ENTRY_PNPBIOS_CS16]	= { { { 0x0000ffff, 0x00009a00 } } },
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_DS]		= { { { 0x0000ffff, 0x00009200 } } },
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_TS1]		= { { { 0x00000000, 0x00009200 } } },
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_TS2]		= { { { 0x00000000, 0x00009200 } } },
+ 	/*
+ 	 * The APM segments have byte granularity and their bases
+ 	 * are set at run time.  All have 64k limits.
+ 	 */
+ 	/* 32-bit code */
+-	[GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } },
++	[GDT_ENTRY_APMBIOS_BASE]	= { { { 0x0000ffff, 0x00409a00 } } },
+ 	/* 16-bit code */
+-	[GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
++	[GDT_ENTRY_APMBIOS_BASE+1]	= { { { 0x0000ffff, 0x00009a00 } } },
+ 	/* data */
+-	[GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },
++	[GDT_ENTRY_APMBIOS_BASE+2]	= { { { 0x0000ffff, 0x00409200 } } },
+ 
+-	[GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
++	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x00000000, 0x00c09200 } } },
+ #endif
+-	[GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
+-} };
++	[GDT_ENTRY_PERCPU]		= { { { 0x0000ffff, 0x00cf9200 } } },
++	GDT_STACK_CANARY_INIT
+ #endif
++} };
+ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+ 
++static int __init x86_xsave_setup(char *s)
++{
++	setup_clear_cpu_cap(X86_FEATURE_XSAVE);
++	return 1;
++}
++__setup("noxsave", x86_xsave_setup);
++
+ #ifdef CONFIG_X86_32
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+@@ -168,16 +169,17 @@ static inline int flag_is_changeable_p(u
+ 	 * the CPUID. Add "volatile" to not allow gcc to
+ 	 * optimize the subsequent calls to this function.
+ 	 */
+-	asm volatile ("pushfl\n\t"
+-		      "pushfl\n\t"
+-		      "popl %0\n\t"
+-		      "movl %0,%1\n\t"
+-		      "xorl %2,%0\n\t"
+-		      "pushl %0\n\t"
+-		      "popfl\n\t"
+-		      "pushfl\n\t"
+-		      "popl %0\n\t"
+-		      "popfl\n\t"
++	asm volatile ("pushfl		\n\t"
++		      "pushfl		\n\t"
++		      "popl %0		\n\t"
++		      "movl %0, %1	\n\t"
++		      "xorl %2, %0	\n\t"
++		      "pushl %0		\n\t"
++		      "popfl		\n\t"
++		      "pushfl		\n\t"
++		      "popl %0		\n\t"
++		      "popfl		\n\t"
++
+ 		      : "=&r" (f1), "=&r" (f2)
+ 		      : "ir" (flag));
+ 
+@@ -192,18 +194,22 @@ static int __cpuinit have_cpuid_p(void)
+ 
+ static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+ {
+-	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
+-		/* Disable processor serial number */
+-		unsigned long lo, hi;
+-		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+-		lo |= 0x200000;
+-		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+-		printk(KERN_NOTICE "CPU serial number disabled.\n");
+-		clear_cpu_cap(c, X86_FEATURE_PN);
++	unsigned long lo, hi;
+ 
+-		/* Disabling the serial number may affect the cpuid level */
+-		c->cpuid_level = cpuid_eax(0);
+-	}
++	if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr)
++		return;
++
++	/* Disable processor serial number: */
++
++	rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
++	lo |= 0x200000;
++	wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
++
++	printk(KERN_NOTICE "CPU serial number disabled.\n");
++	clear_cpu_cap(c, X86_FEATURE_PN);
++
++	/* Disabling the serial number may affect the cpuid level */
++	c->cpuid_level = cpuid_eax(0);
+ }
+ 
+ static int __init x86_serial_nr_setup(char *s)
+@@ -228,16 +234,64 @@ static inline void squash_the_stupid_ser
+ #endif
+ 
+ /*
++ * Some CPU features depend on higher CPUID levels, which may not always
++ * be available due to CPUID level capping or broken virtualization
++ * software.  Add those features to this table to auto-disable them.
++ */
++struct cpuid_dependent_feature {
++	u32 feature;
++	u32 level;
++};
++
++static const struct cpuid_dependent_feature __cpuinitconst
++cpuid_dependent_features[] = {
++	{ X86_FEATURE_MWAIT,		0x00000005 },
++	{ X86_FEATURE_DCA,		0x00000009 },
++	{ X86_FEATURE_XSAVE,		0x0000000d },
++	{ 0, 0 }
++};
++
++static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
++{
++	const struct cpuid_dependent_feature *df;
++
++	for (df = cpuid_dependent_features; df->feature; df++) {
++
++		if (!cpu_has(c, df->feature))
++			continue;
++		/*
++		 * Note: cpuid_level is set to -1 if unavailable, but
++		 * extended_extended_level is set to 0 if unavailable
++		 * and the legitimate extended levels are all negative
++		 * when signed; hence the weird messing around with
++		 * signs here...
++		 */
++		if (!((s32)df->level < 0 ?
++		     (u32)df->level > (u32)c->extended_cpuid_level :
++		     (s32)df->level > (s32)c->cpuid_level))
++			continue;
++
++		clear_cpu_cap(c, df->feature);
++		if (!warn)
++			continue;
++
++		printk(KERN_WARNING
++		       "CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
++				x86_cap_flags[df->feature], df->level);
++	}
++}
++
++/*
+  * Naming convention should be: <Name> [(<Codename>)]
+  * This table only is used unless init_<vendor>() below doesn't set it;
+- * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
+- *
++ * in particular, if CPUID levels 0x80000002..4 are supported, this
++ * isn't used
+  */
+ 
+ /* Look up CPU names by table lookup. */
+-static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
++static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c)
+ {
+-	struct cpu_model_info *info;
++	const struct cpu_model_info *info;
+ 
+ 	if (c->x86_model >= 16)
+ 		return NULL;	/* Range check */
+@@ -257,32 +311,52 @@ static char __cpuinit *table_lookup_mode
+ 
+ __u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+ 
+-/* Current gdt points %fs at the "master" per-cpu area: after this,
+- * it's on the real one. */
+-void switch_to_new_gdt(void)
++void load_percpu_segment(int cpu)
++{
++#ifdef CONFIG_X86_32
++	loadsegment(fs, __KERNEL_PERCPU);
++#else
++	loadsegment(gs, 0);
++#ifndef CONFIG_XEN
++	wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));
++#else
++	if (HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL,
++			(unsigned long)per_cpu(irq_stack_union.gs_base, cpu)))
++		BUG();
++#endif
++#endif
++	load_stack_canary_segment();
++}
++
++/*
++ * Current gdt points %fs at the "master" per-cpu area: after this,
++ * it's on the real one.
++ */
++void switch_to_new_gdt(int cpu)
+ {
+ 	struct desc_ptr gdt_descr;
+ 	unsigned long va, frames[16];
+ 	int f;
+ 
+-	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
++	gdt_descr.address = (long)get_cpu_gdt_table(cpu);
+ 	gdt_descr.size = GDT_SIZE - 1;
+ 
+ 	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_lowmem_page_readonly(
+-			(void *)va, XENFEAT_writable_descriptor_tables);
++		frames[f] = arbitrary_virt_to_mfn(va);
++		make_page_readonly((void *)va,
++				   XENFEAT_writable_descriptor_tables);
+ 	}
+ 	if (HYPERVISOR_set_gdt(frames, (gdt_descr.size + 1) / 8))
+ 		BUG();
+-#ifdef CONFIG_X86_32
+-	asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
+-#endif
++
++	/* Reload the per-cpu base */
++
++	load_percpu_segment(cpu);
+ }
+ 
+-static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
++static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
+ 
+ static void __cpuinit default_init(struct cpuinfo_x86 *c)
+ {
+@@ -301,7 +375,7 @@ static void __cpuinit default_init(struc
+ #endif
+ }
+ 
+-static struct cpu_dev __cpuinitdata default_cpu = {
++static const struct cpu_dev __cpuinitconst default_cpu = {
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
+ 	.c_x86_vendor = X86_VENDOR_UNKNOWN,
+@@ -315,22 +389,24 @@ static void __cpuinit get_model_name(str
+ 	if (c->extended_cpuid_level < 0x80000004)
+ 		return;
+ 
+-	v = (unsigned int *) c->x86_model_id;
++	v = (unsigned int *)c->x86_model_id;
+ 	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+ 	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+ 	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+ 	c->x86_model_id[48] = 0;
+ 
+-	/* Intel chips right-justify this string for some dumb reason;
+-	   undo that brain damage */
++	/*
++	 * Intel chips right-justify this string for some dumb reason;
++	 * undo that brain damage:
++	 */
+ 	p = q = &c->x86_model_id[0];
+ 	while (*p == ' ')
+-	     p++;
++		p++;
+ 	if (p != q) {
+-	     while (*p)
+-		  *q++ = *p++;
+-	     while (q <= &c->x86_model_id[48])
+-		  *q++ = '\0';	/* Zero-pad the rest */
++		while (*p)
++			*q++ = *p++;
++		while (q <= &c->x86_model_id[48])
++			*q++ = '\0';	/* Zero-pad the rest */
+ 	}
+ }
+ 
+@@ -399,36 +475,30 @@ void __cpuinit detect_ht(struct cpuinfo_
+ 
+ 	if (smp_num_siblings == 1) {
+ 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1) {
++		goto out;
++	}
+ 
+-		if (smp_num_siblings > nr_cpu_ids) {
+-			printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
+-					smp_num_siblings);
+-			smp_num_siblings = 1;
+-			return;
+-		}
++	if (smp_num_siblings <= 1)
++		goto out;
+ 
+-		index_msb = get_count_order(smp_num_siblings);
+-#ifdef CONFIG_X86_64
+-		c->phys_proc_id = phys_pkg_id(index_msb);
+-#else
+-		c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
+-#endif
++	if (smp_num_siblings > nr_cpu_ids) {
++		pr_warning("CPU: Unsupported number of siblings %d",
++			   smp_num_siblings);
++		smp_num_siblings = 1;
++		return;
++	}
+ 
+-		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
++	index_msb = get_count_order(smp_num_siblings);
++	c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
+ 
+-		index_msb = get_count_order(smp_num_siblings);
++	smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+ 
+-		core_bits = get_count_order(c->x86_max_cores);
++	index_msb = get_count_order(smp_num_siblings);
+ 
+-#ifdef CONFIG_X86_64
+-		c->cpu_core_id = phys_pkg_id(index_msb) &
+-					       ((1 << core_bits) - 1);
+-#else
+-		c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+-					       ((1 << core_bits) - 1);
+-#endif
+-	}
++	core_bits = get_count_order(c->x86_max_cores);
++
++	c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
++				       ((1 << core_bits) - 1);
+ 
+ out:
+ 	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+@@ -443,8 +513,8 @@ out:
+ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ 	char *v = c->x86_vendor_id;
+-	int i;
+ 	static int printed;
++	int i;
+ 
+ 	for (i = 0; i < X86_VENDOR_NUM; i++) {
+ 		if (!cpu_devs[i])
+@@ -453,6 +523,7 @@ static void __cpuinit get_cpu_vendor(str
+ 		if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+ 		    (cpu_devs[i]->c_ident[1] &&
+ 		     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
++
+ 			this_cpu = cpu_devs[i];
+ 			c->x86_vendor = this_cpu->c_x86_vendor;
+ 			return;
+@@ -461,7 +532,9 @@ static void __cpuinit get_cpu_vendor(str
+ 
+ 	if (!printed) {
+ 		printed++;
+-		printk(KERN_ERR "CPU: vendor_id '%s' unknown, using generic init.\n", v);
++		printk(KERN_ERR
++		    "CPU: vendor_id '%s' unknown, using generic init.\n", v);
++
+ 		printk(KERN_ERR "CPU: Your system may be unstable.\n");
+ 	}
+ 
+@@ -481,14 +554,17 @@ void __cpuinit cpu_detect(struct cpuinfo
+ 	/* Intel-defined flags: level 0x00000001 */
+ 	if (c->cpuid_level >= 0x00000001) {
+ 		u32 junk, tfms, cap0, misc;
++
+ 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+ 		c->x86 = (tfms >> 8) & 0xf;
+ 		c->x86_model = (tfms >> 4) & 0xf;
+ 		c->x86_mask = tfms & 0xf;
++
+ 		if (c->x86 == 0xf)
+ 			c->x86 += (tfms >> 20) & 0xff;
+ 		if (c->x86 >= 0x6)
+ 			c->x86_model += ((tfms >> 16) & 0xf) << 4;
++
+ 		if (cap0 & (1<<19)) {
+ 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ 			c->x86_cache_alignment = c->x86_clflush_size;
+@@ -504,6 +580,7 @@ static void __cpuinit get_cpu_cap(struct
+ 	/* Intel-defined flags: level 0x00000001 */
+ 	if (c->cpuid_level >= 0x00000001) {
+ 		u32 capability, excap;
++
+ 		cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+ 		c->x86_capability[0] = capability;
+ 		c->x86_capability[4] = excap;
+@@ -512,6 +589,7 @@ static void __cpuinit get_cpu_cap(struct
+ 	/* AMD-defined flags: level 0x80000001 */
+ 	xlvl = cpuid_eax(0x80000000);
+ 	c->extended_cpuid_level = xlvl;
++
+ 	if ((xlvl & 0xffff0000) == 0x80000000) {
+ 		if (xlvl >= 0x80000001) {
+ 			c->x86_capability[1] = cpuid_edx(0x80000001);
+@@ -519,13 +597,15 @@ static void __cpuinit get_cpu_cap(struct
+ 		}
+ 	}
+ 
+-#ifdef CONFIG_X86_64
+ 	if (c->extended_cpuid_level >= 0x80000008) {
+ 		u32 eax = cpuid_eax(0x80000008);
+ 
+ 		c->x86_virt_bits = (eax >> 8) & 0xff;
+ 		c->x86_phys_bits = eax & 0xff;
+ 	}
++#ifdef CONFIG_X86_32
++	else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
++		c->x86_phys_bits = 36;
+ #endif
+ 
+ 	if (c->extended_cpuid_level >= 0x80000007)
+@@ -572,8 +652,12 @@ static void __init early_identify_cpu(st
+ {
+ #ifdef CONFIG_X86_64
+ 	c->x86_clflush_size = 64;
++	c->x86_phys_bits = 36;
++	c->x86_virt_bits = 48;
+ #else
+ 	c->x86_clflush_size = 32;
++	c->x86_phys_bits = 32;
++	c->x86_virt_bits = 32;
+ #endif
+ 	c->x86_cache_alignment = c->x86_clflush_size;
+ 
+@@ -596,21 +680,20 @@ static void __init early_identify_cpu(st
+ 	if (this_cpu->c_early_init)
+ 		this_cpu->c_early_init(c);
+ 
+-	validate_pat_support(c);
+-
+ #ifdef CONFIG_SMP
+ 	c->cpu_index = boot_cpu_id;
+ #endif
++	filter_cpuid_features(c, false);
+ }
+ 
+ void __init early_cpu_init(void)
+ {
+-	struct cpu_dev **cdev;
++	const struct cpu_dev *const *cdev;
+ 	int count = 0;
+ 
+-	printk("KERNEL supported cpus:\n");
++	printk(KERN_INFO "KERNEL supported cpus:\n");
+ 	for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
+-		struct cpu_dev *cpudev = *cdev;
++		const struct cpu_dev *cpudev = *cdev;
+ 		unsigned int j;
+ 
+ 		if (count >= X86_VENDOR_NUM)
+@@ -621,7 +704,7 @@ void __init early_cpu_init(void)
+ 		for (j = 0; j < 2; j++) {
+ 			if (!cpudev->c_ident[j])
+ 				continue;
+-			printk("  %s %s\n", cpudev->c_vendor,
++			printk(KERN_INFO "  %s %s\n", cpudev->c_vendor,
+ 				cpudev->c_ident[j]);
+ 		}
+ 	}
+@@ -663,7 +746,7 @@ static void __cpuinit generic_identify(s
+ 		c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ # ifdef CONFIG_X86_HT
+-		c->apicid = phys_pkg_id(c->initial_apicid, 0);
++		c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ # else
+ 		c->apicid = c->initial_apicid;
+ # endif
+@@ -697,9 +780,13 @@ static void __cpuinit identify_cpu(struc
+ 	c->x86_coreid_bits = 0;
+ #ifdef CONFIG_X86_64
+ 	c->x86_clflush_size = 64;
++	c->x86_phys_bits = 36;
++	c->x86_virt_bits = 48;
+ #else
+ 	c->cpuid_level = -1;	/* CPUID not detected */
+ 	c->x86_clflush_size = 32;
++	c->x86_phys_bits = 32;
++	c->x86_virt_bits = 32;
+ #endif
+ 	c->x86_cache_alignment = c->x86_clflush_size;
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+@@ -712,7 +799,7 @@ static void __cpuinit identify_cpu(struc
+ 		this_cpu->c_identify(c);
+ 
+ #if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+-	c->apicid = phys_pkg_id(0);
++	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ #endif
+ 
+ 	/*
+@@ -732,13 +819,16 @@ static void __cpuinit identify_cpu(struc
+ 	squash_the_stupid_serial_number(c);
+ 
+ 	/*
+-	 * The vendor-specific functions might have changed features.  Now
+-	 * we do "generic changes."
++	 * The vendor-specific functions might have changed features.
++	 * Now we do "generic changes."
+ 	 */
+ 
++	/* Filter out anything that depends on CPUID levels we don't have */
++	filter_cpuid_features(c, true);
++
+ 	/* If the model name is still unset, do table lookup. */
+ 	if (!c->x86_model_id[0]) {
+-		char *p;
++		const char *p;
+ 		p = table_lookup_model(c);
+ 		if (p)
+ 			strcpy(c->x86_model_id, p);
+@@ -794,6 +884,7 @@ static void vgetcpu_set_mode(void)
+ void __init identify_boot_cpu(void)
+ {
+ 	identify_cpu(&boot_cpu_data);
++	init_c1e_mask();
+ #ifdef CONFIG_X86_32
+ 	sysenter_setup();
+ 	enable_sep_cpu();
+@@ -813,11 +904,11 @@ void __cpuinit identify_secondary_cpu(st
+ }
+ 
+ struct msr_range {
+-	unsigned min;
+-	unsigned max;
++	unsigned	min;
++	unsigned	max;
+ };
+ 
+-static struct msr_range msr_range_array[] __cpuinitdata = {
++static const struct msr_range msr_range_array[] __cpuinitconst = {
+ 	{ 0x00000000, 0x00000418},
+ 	{ 0xc0000000, 0xc000040b},
+ 	{ 0xc0010000, 0xc0010142},
+@@ -826,14 +917,15 @@ static struct msr_range msr_range_array[
+ 
+ static void __cpuinit print_cpu_msr(void)
+ {
++	unsigned index_min, index_max;
+ 	unsigned index;
+ 	u64 val;
+ 	int i;
+-	unsigned index_min, index_max;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
+ 		index_min = msr_range_array[i].min;
+ 		index_max = msr_range_array[i].max;
++
+ 		for (index = index_min; index < index_max; index++) {
+ 			if (rdmsrl_amd_safe(index, &val))
+ 				continue;
+@@ -843,6 +935,7 @@ static void __cpuinit print_cpu_msr(void
+ }
+ 
+ static int show_msr __cpuinitdata;
++
+ static __init int setup_show_msr(char *arg)
+ {
+ 	int num;
+@@ -864,12 +957,14 @@ __setup("noclflush", setup_noclflush);
+ 
+ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+ {
+-	char *vendor = NULL;
++	const char *vendor = NULL;
+ 
+-	if (c->x86_vendor < X86_VENDOR_NUM)
++	if (c->x86_vendor < X86_VENDOR_NUM) {
+ 		vendor = this_cpu->c_vendor;
+-	else if (c->cpuid_level >= 0)
+-		vendor = c->x86_vendor_id;
++	} else {
++		if (c->cpuid_level >= 0)
++			vendor = c->x86_vendor_id;
++	}
+ 
+ 	if (vendor && !strstr(c->x86_model_id, vendor))
+ 		printk(KERN_CONT "%s ", vendor);
+@@ -896,87 +991,57 @@ void __cpuinit print_cpu_info(struct cpu
+ static __init int setup_disablecpuid(char *arg)
+ {
+ 	int bit;
++
+ 	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+ 		setup_clear_cpu_cap(bit);
+ 	else
+ 		return 0;
++
+ 	return 1;
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+ 
+ #ifdef CONFIG_X86_64
+-struct x8664_pda **_cpu_pda __read_mostly;
+-EXPORT_SYMBOL(_cpu_pda);
+-
+ #ifndef CONFIG_X86_NO_IDT
+ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
+ #endif
+ 
+-static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
++DEFINE_PER_CPU_FIRST(union irq_stack_union,
++		     irq_stack_union) __aligned(PAGE_SIZE);
+ 
+-static void __ref switch_pt(int cpu)
++void xen_switch_pt(void)
+ {
+ #ifdef CONFIG_XEN
+-	if (cpu == 0)
+-		xen_init_pt();
+ 	xen_pt_switch(__pa_symbol(init_level4_pgt));
+ 	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
+ #endif
+ }
+ 
+-void __cpuinit pda_init(int cpu)
+-{
+-	struct x8664_pda *pda = cpu_pda(cpu);
++DEFINE_PER_CPU(char *, irq_stack_ptr) =
++	init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
+ 
+-	/* Setup up data that may be needed in __get_free_pages early */
+-	loadsegment(fs, 0);
+-	loadsegment(gs, 0);
+-#ifndef CONFIG_XEN
+-	/* Memory clobbers used to order PDA accessed */
+-	mb();
+-	wrmsrl(MSR_GS_BASE, pda);
+-	mb();
+-#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) {
+-		/* others are initialized in smpboot.c */
+-		pda->pcurrent = &init_task;
+-		pda->irqstackptr = boot_cpu_stack;
+-		pda->irqstackptr += IRQSTACKSIZE - 64;
+-	} else {
+-		if (!pda->irqstackptr) {
+-			pda->irqstackptr = (char *)
+-				__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
+-			if (!pda->irqstackptr)
+-				panic("cannot allocate irqstack for cpu %d",
+-				      cpu);
+-			pda->irqstackptr += IRQSTACKSIZE - 64;
+-		}
++DEFINE_PER_CPU(unsigned long, kernel_stack) =
++	(unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
++EXPORT_PER_CPU_SYMBOL(kernel_stack);
+ 
+-		if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
+-			pda->nodenumber = cpu_to_node(cpu);
+-	}
+-
+-	switch_pt(cpu);
+-}
++DEFINE_PER_CPU(unsigned int, irq_count) = -1;
+ 
+ #ifndef CONFIG_X86_NO_TSS
+-static char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
+-				  DEBUG_STKSZ] __page_aligned_bss;
+-#endif
++/*
++ * Special IST stacks which the CPU switches to when it calls
++ * an IST-marked descriptor entry. Up to 7 stacks (hardware
++ * limit), all of them are 4K, except the debug stack which
++ * is 8K.
++ */
++static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
++	  [0 ... N_EXCEPTION_STACKS - 1]	= EXCEPTION_STKSZ,
++	  [DEBUG_STACK - 1]			= DEBUG_STKSZ
++};
+ 
+-extern asmlinkage void ignore_sysret(void);
++static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
++	[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ])
++	__aligned(PAGE_SIZE);
++#endif
+ 
+ void __cpuinit syscall_init(void)
+ {
+@@ -1020,16 +1085,38 @@ unsigned long kernel_eflags;
+ DEFINE_PER_CPU(struct orig_ist, orig_ist);
+ #endif
+ 
+-#else
++#else	/* CONFIG_X86_64 */
+ 
+-/* Make sure %fs is initialized properly in idle threads */
++#ifdef CONFIG_CC_STACKPROTECTOR
++DEFINE_PER_CPU(unsigned long, stack_canary);
++#endif
++
++/* Make sure %fs and %gs are initialized properly in idle threads */
+ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+ {
+ 	memset(regs, 0, sizeof(struct pt_regs));
+ 	regs->fs = __KERNEL_PERCPU;
++	regs->gs = __KERNEL_STACK_CANARY;
++
+ 	return regs;
+ }
+-#endif
++#endif	/* CONFIG_X86_64 */
++
++/*
++ * Clear all 6 debug registers:
++ */
++static void clear_all_debug_regs(void)
++{
++	int i;
++
++	for (i = 0; i < 8; i++) {
++		/* Ignore db4, db5 */
++		if ((i == 4) || (i == 5))
++			continue;
++
++		set_debugreg(0, i);
++	}
++}
+ 
+ /*
+  * cpu_init() initializes state that is per-CPU. Some data is already
+@@ -1039,24 +1126,31 @@ struct pt_regs * __cpuinit idle_regs(str
+  * A lot of state is already set up in PDA init for 64 bit
+  */
+ #ifdef CONFIG_X86_64
++
+ 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);
++	struct orig_ist *orig_ist;
++	struct tss_struct *t;
+ 	unsigned long v;
+-	char *estacks = NULL;
+ 	int i;
+ #endif
+ 	struct task_struct *me;
++	int cpu;
+ 
++	cpu = stack_smp_processor_id();
+ 	/* CPU 0 is initialised in head64.c */
+ 	if (cpu != 0)
+-		pda_init(cpu);
++		xen_switch_pt();
+ #ifndef CONFIG_X86_NO_TSS
+-	else
+-		estacks = boot_exception_stacks;
++	t = &per_cpu(init_tss, cpu);
++	orig_ist = &per_cpu(orig_ist, cpu);
++#endif
++
++#ifdef CONFIG_NUMA
++	if (cpu != 0 && percpu_read(node_number) == 0 &&
++	    cpu_to_node(cpu) != NUMA_NO_NODE)
++		percpu_write(node_number, cpu_to_node(cpu));
+ #endif
+ 
+ 	me = current;
+@@ -1073,7 +1167,9 @@ void __cpuinit cpu_init(void)
+ 	 * and set up the GDT descriptor:
+ 	 */
+ 
+-	switch_to_new_gdt();
++	switch_to_new_gdt(cpu);
++	loadsegment(fs, 0);
++
+ #ifndef CONFIG_X86_NO_IDT
+ 	load_idt((const struct desc_ptr *)&idt_descr);
+ #endif
+@@ -1086,8 +1182,8 @@ void __cpuinit cpu_init(void)
+ 	barrier();
+ 
+ 	check_efer();
+-#ifndef CONFIG_XEN
+-	if (cpu != 0 && x2apic)
++#ifdef CONFIG_X86_LOCAL_APIC
++	if (cpu != 0)
+ 		enable_x2apic();
+ #endif
+ 
+@@ -1096,24 +1192,17 @@ void __cpuinit cpu_init(void)
+ 	 * set up and load the per-CPU TSS
+ 	 */
+ 	if (!orig_ist->ist[0]) {
+-		static const unsigned int order[N_EXCEPTION_STACKS] = {
+-		  [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+-		  [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+-		};
++		char *estacks = per_cpu(exception_stacks, cpu);
++
+ 		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+-			if (cpu) {
+-				estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+-				if (!estacks)
+-					panic("Cannot allocate exception "
+-					      "stack %ld %d\n", v, cpu);
+-			}
+-			estacks += PAGE_SIZE << order[v];
++			estacks += exception_stack_sizes[v];
+ 			orig_ist->ist[v] = t->x86_tss.ist[v] =
+ 					(unsigned long)estacks;
+ 		}
+ 	}
+ 
+ 	t->x86_tss.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.
+@@ -1124,8 +1213,7 @@ void __cpuinit cpu_init(void)
+ 
+ 	atomic_inc(&init_mm.mm_count);
+ 	me->active_mm = &init_mm;
+-	if (me->mm)
+-		BUG();
++	BUG_ON(me->mm);
+ 	enter_lazy_tlb(&init_mm, me);
+ 
+ 	load_sp0(t, &current->thread);
+@@ -1144,22 +1232,9 @@ void __cpuinit cpu_init(void)
+ 	 */
+ 	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
+ 		arch_kgdb_ops.correct_hw_break();
+-	else {
+-#endif
+-	/*
+-	 * 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);
+-#ifdef CONFIG_KGDB
+-	/* If the kgdb is connected no debug regs should be altered. */
+-	}
++	else
+ #endif
++		clear_all_debug_regs();
+ 
+ 	fpu_init();
+ 
+@@ -1171,8 +1246,10 @@ void __cpuinit cpu_init(void)
+ 		kernel_eflags &= ~X86_EFLAGS_IF;
+ #endif
+ 
++#ifdef CONFIG_X86_LOCAL_APIC
+ 	if (is_uv_system())
+ 		uv_cpu_init();
++#endif
+ }
+ 
+ #else
+@@ -1188,7 +1265,8 @@ void __cpuinit cpu_init(void)
+ 
+ 	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
+ 		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+-		for (;;) local_irq_enable();
++		for (;;)
++			local_irq_enable();
+ 	}
+ 
+ 	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+@@ -1196,36 +1274,30 @@ void __cpuinit cpu_init(void)
+ 	if (cpu_has_vme || cpu_has_de)
+ 		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+ 
+-	switch_to_new_gdt();
++	switch_to_new_gdt(cpu);
+ 
+ 	/*
+ 	 * Set up and load the per-CPU TSS and LDT
+ 	 */
+ 	atomic_inc(&init_mm.mm_count);
+ 	curr->active_mm = &init_mm;
+-	if (curr->mm)
+-		BUG();
++	BUG_ON(curr->mm);
+ 	enter_lazy_tlb(&init_mm, curr);
+ 
+ 	load_sp0(t, thread);
+ 
+ 	load_LDT(&init_mm.context);
+ 
++#ifndef CONFIG_X86_NO_TSS
++	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
++#endif
++
+ #ifdef CONFIG_DOUBLEFAULT
+ 	/* Set up doublefault TSS pointer in the GDT */
+ 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+ #endif
+ 
+-	/* Clear %gs. */
+-	asm volatile ("mov %0, %%gs" : : "r" (0));
+-
+-	/* Clear all 6 debug registers: */
+-	set_debugreg(0, 0);
+-	set_debugreg(0, 1);
+-	set_debugreg(0, 2);
+-	set_debugreg(0, 3);
+-	set_debugreg(0, 6);
+-	set_debugreg(0, 7);
++	clear_all_debug_regs();
+ 
+ 	/*
+ 	 * Force FPU initialization:
+@@ -1245,6 +1317,4 @@ void __cpuinit cpu_init(void)
+ 
+ 	xsave_init();
+ }
+-
+-
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/cpu_debug.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/cpu_debug.c	2009-11-06 10:52:02.000000000 +0100
+@@ -59,17 +59,23 @@ static struct cpu_debug_base cpu_base[] 
+ 	{ "misc",	CPU_MISC,	0	},
+ 	{ "debug",	CPU_DEBUG,	0	},
+ 	{ "pat",	CPU_PAT,	0	},
++#ifndef CONFIG_XEN
+ 	{ "vmx",	CPU_VMX,	0	},
++#endif
+ 	{ "call",	CPU_CALL,	0	},
+ 	{ "base",	CPU_BASE,	0	},
+ 	{ "ver",	CPU_VER,	0	},
+ 	{ "conf",	CPU_CONF,	0	},
+ 	{ "smm",	CPU_SMM,	0	},
++#ifndef CONFIG_XEN
+ 	{ "svm",	CPU_SVM,	0	},
+ 	{ "osvm",	CPU_OSVM,	0	},
++#endif
+ 	{ "tss",	CPU_TSS,	0	},
+ 	{ "cr",		CPU_CR,		0	},
++#ifndef CONFIG_XEN
+ 	{ "dt",		CPU_DT,		0	},
++#endif
+ 	{ "registers",	CPU_REG_ALL,	0	},
+ };
+ 
+@@ -298,6 +304,7 @@ static void print_cr(void *arg)
+ #endif
+ }
+ 
++#ifndef CONFIG_XEN
+ static void print_desc_ptr(char *str, struct seq_file *seq, struct desc_ptr dt)
+ {
+ 	seq_printf(seq, " %s\t: %016llx\n", str, (u64)(dt.address | dt.size));
+@@ -324,6 +331,7 @@ static void print_dt(void *seq)
+ 	store_tr(ldt);
+ 	seq_printf(seq, " TR\t: %016lx\n", ldt);
+ }
++#endif /* CONFIG_XEN */
+ 
+ static void print_dr(void *arg)
+ {
+@@ -346,7 +354,7 @@ static void print_apic(void *arg)
+ {
+ 	struct seq_file *seq = arg;
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	seq_printf(seq, " LAPIC\t:\n");
+ 	seq_printf(seq, " ID\t\t: %08x\n",  apic_read(APIC_ID) >> 24);
+ 	seq_printf(seq, " LVR\t\t: %08x\n",  apic_read(APIC_LVR));
+@@ -400,9 +408,11 @@ static int cpu_seq_show(struct seq_file 
+ 	case CPU_CR:
+ 		smp_call_function_single(priv->cpu, print_cr, seq, 1);
+ 		break;
++#ifndef CONFIG_XEN
+ 	case CPU_DT:
+ 		smp_call_function_single(priv->cpu, print_dt, seq, 1);
+ 		break;
++#endif
+ 	case CPU_DEBUG:
+ 		if (priv->file == CPU_INDEX_BIT)
+ 			smp_call_function_single(priv->cpu, print_dr, seq, 1);
+@@ -487,7 +497,11 @@ static int write_cpu_register(struct cpu
+ 		return ret;
+ 
+ 	/* Supporting only MSRs */
++#ifndef CONFIG_XEN
+ 	if (priv->type < CPU_TSS_BIT)
++#else
++	if (cpu_base[priv->type].flag < CPU_TSS)
++#endif
+ 		return write_msr(priv, val);
+ 
+ 	return ret;
+@@ -617,7 +631,11 @@ static int cpu_init_allreg(unsigned cpu,
+ 		cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry);
+ 		per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry;
+ 
++#ifndef CONFIG_XEN
+ 		if (type < CPU_TSS_BIT)
++#else
++		if (cpu_base[type].flag < CPU_TSS)
++#endif
+ 			err = cpu_init_msr(cpu, type, cpu_dentry);
+ 		else
+ 			err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT,
+--- head-2010-01-18.orig/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -129,19 +129,50 @@ int __init e820_all_mapped(u64 start, u6
+ /*
+  * Add a memory region to the kernel e820 map.
+  */
+-void __init e820_add_region(u64 start, u64 size, int type)
++static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
++					 int type)
+ {
+-	int x = e820.nr_map;
++	int x = e820x->nr_map;
+ 
+-	if (x == ARRAY_SIZE(e820.map)) {
++	if (x == ARRAY_SIZE(e820x->map)) {
+ 		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+ 		return;
+ 	}
+ 
+-	e820.map[x].addr = start;
+-	e820.map[x].size = size;
+-	e820.map[x].type = type;
+-	e820.nr_map++;
++	e820x->map[x].addr = start;
++	e820x->map[x].size = size;
++	e820x->map[x].type = type;
++	e820x->nr_map++;
++}
++
++void __init e820_add_region(u64 start, u64 size, int type)
++{
++	__e820_add_region(&e820, start, size, type);
++}
++
++static void __init e820_print_type(u32 type)
++{
++	switch (type) {
++	case E820_RAM:
++	case E820_RESERVED_KERN:
++		printk(KERN_CONT "(usable)");
++		break;
++	case E820_RESERVED:
++		printk(KERN_CONT "(reserved)");
++		break;
++	case E820_ACPI:
++		printk(KERN_CONT "(ACPI data)");
++		break;
++	case E820_NVS:
++		printk(KERN_CONT "(ACPI NVS)");
++		break;
++	case E820_UNUSABLE:
++		printk(KERN_CONT "(unusable)");
++		break;
++	default:
++		printk(KERN_CONT "type %u", type);
++		break;
++	}
+ }
+ 
+ static void __init _e820_print_map(const struct e820map *e820, const char *who)
+@@ -153,27 +184,8 @@ static void __init _e820_print_map(const
+ 		       (unsigned long long) e820->map[i].addr,
+ 		       (unsigned long long)
+ 		       (e820->map[i].addr + e820->map[i].size));
+-		switch (e820->map[i].type) {
+-		case E820_RAM:
+-		case E820_RESERVED_KERN:
+-			printk(KERN_CONT "(usable)\n");
+-			break;
+-		case E820_RESERVED:
+-			printk(KERN_CONT "(reserved)\n");
+-			break;
+-		case E820_ACPI:
+-			printk(KERN_CONT "(ACPI data)\n");
+-			break;
+-		case E820_NVS:
+-			printk(KERN_CONT "(ACPI NVS)\n");
+-			break;
+-		case E820_UNUSABLE:
+-			printk("(unusable)\n");
+-			break;
+-		default:
+-			printk(KERN_CONT "type %u\n", e820->map[i].type);
+-			break;
+-		}
++		e820_print_type(e820->map[i].type);
++		printk(KERN_CONT "\n");
+ 	}
+ }
+ 
+@@ -240,7 +252,7 @@ static void __init _e820_print_map(const
+  */
+ 
+ int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
+-				int *pnr_map)
++			     u32 *pnr_map)
+ {
+ 	struct change_member {
+ 		struct e820entry *pbios; /* pointer to original bios entry */
+@@ -444,11 +456,12 @@ static int __init append_e820_map(struct
+ 	return __append_e820_map(biosmap, nr_map);
+ }
+ 
+-static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
++static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
+ 					u64 size, unsigned old_type,
+ 					unsigned new_type)
+ {
+-	unsigned int i, x;
++	u64 end;
++	unsigned int i;
+ 	u64 real_updated_size = 0;
+ 
+ 	BUG_ON(old_type == new_type);
+@@ -456,40 +469,59 @@ static u64 __init e820_update_range_map(
+ 	if (size > (ULLONG_MAX - start))
+ 		size = ULLONG_MAX - start;
+ 
++	end = start + size;
++	printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
++		       (unsigned long long) start,
++		       (unsigned long long) end);
++	e820_print_type(old_type);
++	printk(KERN_CONT " ==> ");
++	e820_print_type(new_type);
++	printk(KERN_CONT "\n");
++
+ 	for (i = 0; i < e820x->nr_map; i++) {
+ 		struct e820entry *ei = &e820x->map[i];
+ 		u64 final_start, final_end;
++		u64 ei_end;
++
+ 		if (ei->type != old_type)
+ 			continue;
+-		/* totally covered? */
+-		if (ei->addr >= start &&
+-		    (ei->addr + ei->size) <= (start + size)) {
++
++		ei_end = ei->addr + ei->size;
++		/* totally covered by new range? */
++		if (ei->addr >= start && ei_end <= end) {
+ 			ei->type = new_type;
+ 			real_updated_size += ei->size;
+ 			continue;
+ 		}
++
++		/* new range is totally covered? */
++		if (ei->addr < start && ei_end > end) {
++			__e820_add_region(e820x, start, size, new_type);
++			__e820_add_region(e820x, end, ei_end - end, ei->type);
++			ei->size = start - ei->addr;
++			real_updated_size += size;
++			continue;
++		}
++
+ 		/* partially covered */
+ 		final_start = max(start, ei->addr);
+-		final_end = min(start + size, ei->addr + ei->size);
++		final_end = min(end, ei_end);
+ 		if (final_start >= final_end)
+ 			continue;
+ 
+-		x = e820x->nr_map;
+-		if (x == ARRAY_SIZE(e820x->map)) {
+-			printk(KERN_ERR "Too many memory map entries!\n");
+-			break;
+-		}
+-		e820x->map[x].addr = final_start;
+-		e820x->map[x].size = final_end - final_start;
+-		e820x->map[x].type = new_type;
+-		e820x->nr_map++;
++		__e820_add_region(e820x, final_start, final_end - final_start,
++				  new_type);
+ 
+ 		real_updated_size += final_end - final_start;
+ 
++		/*
++		 * left range could be head or tail, so need to update
++		 * size at first.
++		 */
++		ei->size -= final_end - final_start;
+ 		if (ei->addr < final_start)
+ 			continue;
+ 		ei->addr = final_end;
+-		ei->size -= final_end - final_start;
+ 	}
+ 	return real_updated_size;
+ }
+@@ -497,7 +529,7 @@ static u64 __init e820_update_range_map(
+ u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
+ 			     unsigned new_type)
+ {
+-	return e820_update_range_map(&e820, start, size, old_type, new_type);
++	return __e820_update_range(&e820, start, size, old_type, new_type);
+ }
+ 
+ static u64 __init e820_update_range_saved(u64 start, u64 size,
+@@ -505,11 +537,11 @@ static u64 __init e820_update_range_save
+ {
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain())
+-		return e820_update_range_map(&machine_e820,
+-					     phys_to_machine(start), size,
+-					     old_type, new_type);
++		return __e820_update_range(&machine_e820,
++					   phys_to_machine(start), size,
++					   old_type, new_type);
+ #endif
+-	return e820_update_range_map(&e820_saved, start, size, old_type,
++	return __e820_update_range(&e820_saved, start, size, old_type,
+ 				     new_type);
+ }
+ 
+@@ -553,7 +585,7 @@ u64 __init e820_remove_range(u64 start, 
+ 
+ void __init update_e820(void)
+ {
+-	int nr_map;
++	u32 nr_map;
+ 
+ 	nr_map = e820.nr_map;
+ 	if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
+@@ -564,7 +596,7 @@ void __init update_e820(void)
+ }
+ static void __init update_e820_saved(void)
+ {
+-	int nr_map;
++	u32 nr_map;
+ 
+ 	nr_map = e820_saved.nr_map;
+ 	if (sanitize_e820_map(e820_saved.map, ARRAY_SIZE(e820_saved.map), &nr_map))
+@@ -916,6 +948,9 @@ void __init reserve_early_overlap_ok(u64
+  */
+ void __init reserve_early(u64 start, u64 end, char *name)
+ {
++	if (start >= end)
++		return;
++
+ 	drop_overlaps_that_are_ok(start, end);
+ 	__reserve_early(start, end, name, 0);
+ }
+@@ -1389,7 +1424,7 @@ early_param("memmap", parse_memmap_opt);
+ void __init finish_e820_parsing(void)
+ {
+ 	if (userdef) {
+-		int nr = e820.nr_map;
++		u32 nr = e820.nr_map;
+ 
+ 		if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr) < 0)
+ 			early_panic("Invalid user supplied memory map");
+@@ -1479,7 +1514,7 @@ void __init e820_reserve_resources_late(
+ char *__init default_machine_specific_memory_setup(void)
+ {
+ 	char *who = "BIOS-e820";
+-	int new_nr;
++	u32 new_nr;
+ 	/*
+ 	 * Try to copy the BIOS-supplied E820-map.
+ 	 *
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -12,8 +12,8 @@
+ #include <asm/fcntl.h>
+ #include <asm/setup.h>
+ #include <asm/pci-direct.h>
+-#include <asm/pgtable.h>
+ #include <asm/fixmap.h>
++#include <asm/pgtable.h>
+ #include <linux/usb/ehci_def.h>
+ 
+ #ifndef CONFIG_XEN
+@@ -279,7 +279,7 @@ static int dbgp_wait_until_complete(void
+ 	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
+ }
+ 
+-static void dbgp_mdelay(int ms)
++static void __init dbgp_mdelay(int ms)
+ {
+ 	int i;
+ 
+@@ -340,7 +340,7 @@ static void dbgp_set_data(const void *bu
+ 	writel(hi, &ehci_debug->data47);
+ }
+ 
+-static void dbgp_get_data(void *buf, int size)
++static void __init dbgp_get_data(void *buf, int size)
+ {
+ 	unsigned char *bytes = buf;
+ 	u32 lo, hi;
+@@ -384,7 +384,7 @@ static int dbgp_bulk_write(unsigned devn
+ 	return ret;
+ }
+ 
+-static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
++static int __init dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
+ 				 int size)
+ {
+ 	u32 pids, addr, ctrl;
+@@ -415,8 +415,8 @@ static int dbgp_bulk_read(unsigned devnu
+ 	return ret;
+ }
+ 
+-static int dbgp_control_msg(unsigned devnum, int requesttype, int request,
+-	int value, int index, void *data, int size)
++static int __init dbgp_control_msg(unsigned devnum, int requesttype,
++	int request, int value, int index, void *data, int size)
+ {
+ 	u32 pids, addr, ctrl;
+ 	struct usb_ctrlrequest req;
+@@ -518,7 +518,7 @@ static u32 __init find_dbgp(int ehci_num
+ 	return 0;
+ }
+ 
+-static int ehci_reset_port(int port)
++static int __init ehci_reset_port(int port)
+ {
+ 	u32 portsc;
+ 	u32 delay_time, delay;
+@@ -561,7 +561,7 @@ static int ehci_reset_port(int port)
+ 	return -EBUSY;
+ }
+ 
+-static int ehci_wait_for_port(int port)
++static int __init ehci_wait_for_port(int port)
+ {
+ 	u32 status;
+ 	int ret, reps;
+@@ -586,13 +586,13 @@ static inline void dbgp_printk(const cha
+ 
+ typedef void (*set_debug_port_t)(int port);
+ 
+-static void default_set_debug_port(int port)
++static void __init default_set_debug_port(int port)
+ {
+ }
+ 
+-static set_debug_port_t set_debug_port = default_set_debug_port;
++static set_debug_port_t __initdata set_debug_port = default_set_debug_port;
+ 
+-static void nvidia_set_debug_port(int port)
++static void __init nvidia_set_debug_port(int port)
+ {
+ 	u32 dword;
+ 	dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:52:02.000000000 +0100
+@@ -30,12 +30,13 @@
+  *	1C(%esp) - %ds
+  *	20(%esp) - %es
+  *	24(%esp) - %fs
+- *	28(%esp) - orig_eax
+- *	2C(%esp) - %eip
+- *	30(%esp) - %cs
+- *	34(%esp) - %eflags
+- *	38(%esp) - %oldesp
+- *	3C(%esp) - %oldss
++ *	28(%esp) - %gs		saved iff !CONFIG_X86_32_LAZY_GS
++ *	2C(%esp) - orig_eax
++ *	30(%esp) - %eip
++ *	34(%esp) - %cs
++ *	38(%esp) - %eflags
++ *	3C(%esp) - %oldesp
++ *	40(%esp) - %oldss
+  *
+  * "current" is in register %ebx during any slow entries.
+  */
+@@ -46,7 +47,7 @@
+ #include <asm/errno.h>
+ #include <asm/segment.h>
+ #include <asm/smp.h>
+-#include <asm/page.h>
++#include <asm/page_types.h>
+ #include <asm/desc.h>
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
+@@ -105,121 +106,221 @@ NMI_MASK	= 0x80000000
+ #define resume_userspace_sig	resume_userspace
+ #endif
+ 
+-#define SAVE_ALL \
+-	cld; \
+-	pushl %fs; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	/*CFI_REL_OFFSET fs, 0;*/\
+-	pushl %es; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	/*CFI_REL_OFFSET es, 0;*/\
+-	pushl %ds; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	/*CFI_REL_OFFSET ds, 0;*/\
+-	pushl %eax; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET eax, 0;\
+-	pushl %ebp; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET ebp, 0;\
+-	pushl %edi; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET edi, 0;\
+-	pushl %esi; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET esi, 0;\
+-	pushl %edx; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET edx, 0;\
+-	pushl %ecx; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET ecx, 0;\
+-	pushl %ebx; \
+-	CFI_ADJUST_CFA_OFFSET 4;\
+-	CFI_REL_OFFSET ebx, 0;\
+-	movl $(__USER_DS), %edx; \
+-	movl %edx, %ds; \
+-	movl %edx, %es; \
+-	movl $(__KERNEL_PERCPU), %edx; \
++/*
++ * User gs save/restore
++ *
++ * %gs is used for userland TLS and kernel only uses it for stack
++ * canary which is required to be at %gs:20 by gcc.  Read the comment
++ * at the top of stackprotector.h for more info.
++ *
++ * Local labels 98 and 99 are used.
++ */
++#ifdef CONFIG_X86_32_LAZY_GS
++
++ /* unfortunately push/pop can't be no-op */
++.macro PUSH_GS
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++.endm
++.macro POP_GS pop=0
++	addl $(4 + \pop), %esp
++	CFI_ADJUST_CFA_OFFSET -(4 + \pop)
++.endm
++.macro POP_GS_EX
++.endm
++
++ /* all the rest are no-op */
++.macro PTGS_TO_GS
++.endm
++.macro PTGS_TO_GS_EX
++.endm
++.macro GS_TO_REG reg
++.endm
++.macro REG_TO_PTGS reg
++.endm
++.macro SET_KERNEL_GS reg
++.endm
++
++#else	/* CONFIG_X86_32_LAZY_GS */
++
++.macro PUSH_GS
++	pushl %gs
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET gs, 0*/
++.endm
++
++.macro POP_GS pop=0
++98:	popl %gs
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_RESTORE gs*/
++  .if \pop <> 0
++	add $\pop, %esp
++	CFI_ADJUST_CFA_OFFSET -\pop
++  .endif
++.endm
++.macro POP_GS_EX
++.pushsection .fixup, "ax"
++99:	movl $0, (%esp)
++	jmp 98b
++.section __ex_table, "a"
++	.align 4
++	.long 98b, 99b
++.popsection
++.endm
++
++.macro PTGS_TO_GS
++98:	mov PT_GS(%esp), %gs
++.endm
++.macro PTGS_TO_GS_EX
++.pushsection .fixup, "ax"
++99:	movl $0, PT_GS(%esp)
++	jmp 98b
++.section __ex_table, "a"
++	.align 4
++	.long 98b, 99b
++.popsection
++.endm
++
++.macro GS_TO_REG reg
++	movl %gs, \reg
++	/*CFI_REGISTER gs, \reg*/
++.endm
++.macro REG_TO_PTGS reg
++	movl \reg, PT_GS(%esp)
++	/*CFI_REL_OFFSET gs, PT_GS*/
++.endm
++.macro SET_KERNEL_GS reg
++	movl $(__KERNEL_STACK_CANARY), \reg
++	movl \reg, %gs
++.endm
++
++#endif	/* CONFIG_X86_32_LAZY_GS */
++
++.macro SAVE_ALL
++	cld
++	PUSH_GS
++	pushl %fs
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET fs, 0;*/
++	pushl %es
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET es, 0;*/
++	pushl %ds
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET ds, 0;*/
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET eax, 0
++	pushl %ebp
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebp, 0
++	pushl %edi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edi, 0
++	pushl %esi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET esi, 0
++	pushl %edx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edx, 0
++	pushl %ecx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ecx, 0
++	pushl %ebx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebx, 0
++	movl $(__USER_DS), %edx
++	movl %edx, %ds
++	movl %edx, %es
++	movl $(__KERNEL_PERCPU), %edx
+ 	movl %edx, %fs
++	SET_KERNEL_GS %edx
++.endm
+ 
+-#define RESTORE_INT_REGS \
+-	popl %ebx;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE ebx;\
+-	popl %ecx;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE ecx;\
+-	popl %edx;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE edx;\
+-	popl %esi;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE esi;\
+-	popl %edi;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE edi;\
+-	popl %ebp;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	CFI_RESTORE ebp;\
+-	popl %eax;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
++.macro RESTORE_INT_REGS
++	popl %ebx
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE ebx
++	popl %ecx
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE ecx
++	popl %edx
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE edx
++	popl %esi
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE esi
++	popl %edi
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE edi
++	popl %ebp
++	CFI_ADJUST_CFA_OFFSET -4
++	CFI_RESTORE ebp
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
+ 	CFI_RESTORE eax
++.endm
+ 
+-#define RESTORE_REGS	\
+-	RESTORE_INT_REGS; \
+-1:	popl %ds;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	/*CFI_RESTORE ds;*/\
+-2:	popl %es;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	/*CFI_RESTORE es;*/\
+-3:	popl %fs;	\
+-	CFI_ADJUST_CFA_OFFSET -4;\
+-	/*CFI_RESTORE fs;*/\
+-.pushsection .fixup,"ax";	\
+-4:	movl $0,(%esp);	\
+-	jmp 1b;		\
+-5:	movl $0,(%esp);	\
+-	jmp 2b;		\
+-6:	movl $0,(%esp);	\
+-	jmp 3b;		\
+-.section __ex_table,"a";\
+-	.align 4;	\
+-	.long 1b,4b;	\
+-	.long 2b,5b;	\
+-	.long 3b,6b;	\
++.macro RESTORE_REGS pop=0
++	RESTORE_INT_REGS
++1:	popl %ds
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_RESTORE ds;*/
++2:	popl %es
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_RESTORE es;*/
++3:	popl %fs
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_RESTORE fs;*/
++	POP_GS \pop
++.pushsection .fixup, "ax"
++4:	movl $0, (%esp)
++	jmp 1b
++5:	movl $0, (%esp)
++	jmp 2b
++6:	movl $0, (%esp)
++	jmp 3b
++.section __ex_table, "a"
++	.align 4
++	.long 1b, 4b
++	.long 2b, 5b
++	.long 3b, 6b
+ .popsection
++	POP_GS_EX
++.endm
+ 
+-#define RING0_INT_FRAME \
+-	CFI_STARTPROC simple;\
+-	CFI_SIGNAL_FRAME;\
+-	CFI_DEF_CFA esp, 3*4;\
+-	/*CFI_OFFSET cs, -2*4;*/\
++.macro RING0_INT_FRAME
++	CFI_STARTPROC simple
++	CFI_SIGNAL_FRAME
++	CFI_DEF_CFA esp, 3*4
++	/*CFI_OFFSET cs, -2*4;*/
+ 	CFI_OFFSET eip, -3*4
++.endm
+ 
+-#define RING0_EC_FRAME \
+-	CFI_STARTPROC simple;\
+-	CFI_SIGNAL_FRAME;\
+-	CFI_DEF_CFA esp, 4*4;\
+-	/*CFI_OFFSET cs, -2*4;*/\
++.macro RING0_EC_FRAME
++	CFI_STARTPROC simple
++	CFI_SIGNAL_FRAME
++	CFI_DEF_CFA esp, 4*4
++	/*CFI_OFFSET cs, -2*4;*/
+ 	CFI_OFFSET eip, -3*4
++.endm
+ 
+-#define RING0_PTREGS_FRAME \
+-	CFI_STARTPROC simple;\
+-	CFI_SIGNAL_FRAME;\
+-	CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\
+-	/*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\
+-	CFI_OFFSET eip, PT_EIP-PT_OLDESP;\
+-	/*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\
+-	/*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\
+-	CFI_OFFSET eax, PT_EAX-PT_OLDESP;\
+-	CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\
+-	CFI_OFFSET edi, PT_EDI-PT_OLDESP;\
+-	CFI_OFFSET esi, PT_ESI-PT_OLDESP;\
+-	CFI_OFFSET edx, PT_EDX-PT_OLDESP;\
+-	CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\
++.macro RING0_PTREGS_FRAME
++	CFI_STARTPROC simple
++	CFI_SIGNAL_FRAME
++	CFI_DEF_CFA esp, PT_OLDESP-PT_EBX
++	/*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/
++	CFI_OFFSET eip, PT_EIP-PT_OLDESP
++	/*CFI_OFFSET es, PT_ES-PT_OLDESP;*/
++	/*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/
++	CFI_OFFSET eax, PT_EAX-PT_OLDESP
++	CFI_OFFSET ebp, PT_EBP-PT_OLDESP
++	CFI_OFFSET edi, PT_EDI-PT_OLDESP
++	CFI_OFFSET esi, PT_ESI-PT_OLDESP
++	CFI_OFFSET edx, PT_EDX-PT_OLDESP
++	CFI_OFFSET ecx, PT_ECX-PT_OLDESP
+ 	CFI_OFFSET ebx, PT_EBX-PT_OLDESP
++.endm
+ 
+ ENTRY(ret_from_fork)
+ 	CFI_STARTPROC
+@@ -344,7 +445,8 @@ sysenter_past_esp:
+ .previous
+ 
+ 	GET_THREAD_INFO(%ebp)
+-	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
++
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ 	jnz sysenter_audit
+ sysenter_do_call:
+ 	cmpl $(nr_syscalls), %eax
+@@ -355,7 +457,7 @@ sysenter_do_call:
+ 	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+-	testw $_TIF_ALLWORK_MASK, %cx
++	testl $_TIF_ALLWORK_MASK, %ecx
+ 	jne sysexit_audit
+ sysenter_exit:
+ /* if something modifies registers it must also disable sysexit */
+@@ -364,11 +466,12 @@ sysenter_exit:
+ 	xorl %ebp,%ebp
+ 	TRACE_IRQS_ON
+ 1:	mov  PT_FS(%esp), %fs
++	PTGS_TO_GS
+ 	ENABLE_INTERRUPTS_SYSEXIT
+ 
+ #ifdef CONFIG_AUDITSYSCALL
+ sysenter_audit:
+-	testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ 	jnz syscall_trace_entry
+ 	addl $4,%esp
+ 	CFI_ADJUST_CFA_OFFSET -4
+@@ -385,7 +488,7 @@ sysenter_audit:
+ 	jmp sysenter_do_call
+ 
+ sysexit_audit:
+-	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
++	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
+ 	jne syscall_exit_work
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_ANY)
+@@ -398,7 +501,7 @@ sysexit_audit:
+ 	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+-	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
++	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
+ 	jne syscall_exit_work
+ 	movl PT_EAX(%esp),%eax	/* reload syscall return value */
+ 	jmp sysenter_exit
+@@ -412,6 +515,7 @@ sysexit_audit:
+ 	.align 4
+ 	.long 1b,2b
+ .popsection
++	PTGS_TO_GS_EX
+ ENDPROC(ia32_sysenter_target)
+ 
+ 	# pv sysenter call handler stub
+@@ -447,7 +551,7 @@ ENTRY(system_call)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ 	jnz syscall_trace_entry
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+@@ -461,7 +565,7 @@ syscall_exit:
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+-	testw $_TIF_ALLWORK_MASK, %cx	# current->work
++	testl $_TIF_ALLWORK_MASK, %ecx	# current->work
+ 	jne syscall_exit_work
+ 
+ restore_all:
+@@ -492,8 +596,7 @@ restore_nocheck:
+ #endif
+ 	TRACE_IRQS_IRET
+ restore_nocheck_notrace:
+-	RESTORE_REGS
+-	addl $4, %esp			# skip orig_eax/error_code
++	RESTORE_REGS 4			# skip orig_eax/error_code
+ 	CFI_ADJUST_CFA_OFFSET -4
+ irq_return:
+ 	INTERRUPT_RETURN
+@@ -555,9 +658,7 @@ restore_all_enable_events:
+ scrit:	/**** START OF CRITICAL REGION ****/
+ 	__TEST_PENDING
+ 	jnz  14f			# process more events if necessary...
+-	RESTORE_REGS
+-	addl $4, %esp
+-	CFI_ADJUST_CFA_OFFSET -4
++	RESTORE_REGS 4
+ 1:	INTERRUPT_RETURN
+ .section __ex_table,"a"
+ 	.align 4
+@@ -571,9 +672,7 @@ ecrit:  /**** END OF CRITICAL REGION ***
+ 	CFI_RESTORE_STATE
+ hypervisor_iret:
+ 	andl $~NMI_MASK, PT_EFLAGS(%esp)
+-	RESTORE_REGS
+-	addl $4, %esp
+-	CFI_ADJUST_CFA_OFFSET -4
++	RESTORE_REGS 4
+ 	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+ #endif
+ 	CFI_ENDPROC
+@@ -641,7 +740,7 @@ END(syscall_trace_entry)
+ 	# perform syscall exit tracing
+ 	ALIGN
+ syscall_exit_work:
+-	testb $_TIF_WORK_SYSCALL_EXIT, %cl
++	testl $_TIF_WORK_SYSCALL_EXIT, %ecx
+ 	jz work_pending
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
+@@ -665,29 +764,51 @@ syscall_badsys:
+ END(syscall_badsys)
+ 	CFI_ENDPROC
+ 
++/*
++ * System calls that need a pt_regs pointer.
++ */
++#define PTREGSCALL(name) \
++	ALIGN; \
++ptregs_##name: \
++	leal 4(%esp),%eax; \
++	jmp sys_##name;
++
++PTREGSCALL(iopl)
++PTREGSCALL(fork)
++PTREGSCALL(clone)
++PTREGSCALL(vfork)
++PTREGSCALL(execve)
++PTREGSCALL(sigaltstack)
++PTREGSCALL(sigreturn)
++PTREGSCALL(rt_sigreturn)
++PTREGSCALL(vm86)
++PTREGSCALL(vm86old)
++
+ #ifndef CONFIG_XEN
+-#define FIXUP_ESPFIX_STACK \
+-	/* since we are on a wrong stack, we cant make it a C code :( */ \
+-	PER_CPU(gdt_page, %ebx); \
+-	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
+-	addl %esp, %eax; \
+-	pushl $__KERNEL_DS; \
+-	CFI_ADJUST_CFA_OFFSET 4; \
+-	pushl %eax; \
+-	CFI_ADJUST_CFA_OFFSET 4; \
+-	lss (%esp), %esp; \
+-	CFI_ADJUST_CFA_OFFSET -8;
+-#define UNWIND_ESPFIX_STACK \
+-	movl %ss, %eax; \
+-	/* see if on espfix stack */ \
+-	cmpw $__ESPFIX_SS, %ax; \
+-	jne 27f; \
+-	movl $__KERNEL_DS, %eax; \
+-	movl %eax, %ds; \
+-	movl %eax, %es; \
+-	/* switch to normal stack */ \
+-	FIXUP_ESPFIX_STACK; \
+-27:;
++.macro FIXUP_ESPFIX_STACK
++	/* since we are on a wrong stack, we cant make it a C code :( */
++	PER_CPU(gdt_page, %ebx)
++	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
++	addl %esp, %eax
++	pushl $__KERNEL_DS
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	lss (%esp), %esp
++	CFI_ADJUST_CFA_OFFSET -8
++.endm
++.macro UNWIND_ESPFIX_STACK
++	movl %ss, %eax
++	/* see if on espfix stack */
++	cmpw $__ESPFIX_SS, %ax
++	jne 27f
++	movl $__KERNEL_DS, %eax
++	movl %eax, %ds
++	movl %eax, %es
++	/* switch to normal stack */
++	FIXUP_ESPFIX_STACK
++27:
++.endm
+ 
+ /*
+  * Build the entry stubs and pointer table with some assembler magic.
+@@ -743,7 +864,7 @@ common_interrupt:
+ ENDPROC(common_interrupt)
+ 	CFI_ENDPROC
+ 
+-#define BUILD_INTERRUPT(name, nr)	\
++#define BUILD_INTERRUPT3(name, nr, fn)	\
+ ENTRY(name)				\
+ 	RING0_INT_FRAME;		\
+ 	pushl $~(nr);			\
+@@ -751,13 +872,15 @@ ENTRY(name)				\
+ 	SAVE_ALL;			\
+ 	TRACE_IRQS_OFF			\
+ 	movl %esp,%eax;			\
+-	call smp_##name;		\
++	call fn;			\
+ 	jmp ret_from_intr;		\
+ 	CFI_ENDPROC;			\
+ ENDPROC(name)
+ 
++#define BUILD_INTERRUPT(name, nr)	BUILD_INTERRUPT3(name, nr, smp_##name)
++
+ /* The include is where all of the SMP etc. interrupts come from */
+-#include "entry_arch.h"
++#include <asm/entry_arch.h>
+ 
+ #else
+ #define UNWIND_ESPFIX_STACK
+@@ -844,8 +967,13 @@ critical_fixup_table:
+ 	.byte 7				# pop  %ds
+ 	.byte 8				# pop  %es
+ 	.byte 9,9			# pop  %fs
+-	.byte 10,10,10			# add  $4,%esp
+-	.byte 11			# iret
++#ifndef CONFIG_X86_32_LAZY_GS
++	.byte 10,10			# pop  %gs
++	.byte 11,11,11			# add  $4,%esp
++#else
++	.byte 10,10,10			# add  $8,%esp
++#endif
++	.byte 12			# iret
+ 	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
+ .previous
+ 
+@@ -1203,7 +1331,7 @@ ENTRY(ia32pv_cstar_target)
+ .previous
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ 	jnz cstar_trace_entry
+ 	cmpl $nr_syscalls,%eax
+ 	jae cstar_badsys
+@@ -1323,7 +1451,10 @@ ENTRY(page_fault)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	ALIGN
+ error_code:
+-	/* the function address is in %fs's slot on the stack */
++	/* the function address is in %gs's slot on the stack */
++	pushl %fs
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET fs, 0*/
+ 	pushl %es
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET es, 0*/
+@@ -1352,20 +1483,15 @@ error_code:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET ebx, 0
+ 	cld
+-	pushl %fs
+-	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET fs, 0*/
+ 	movl $(__KERNEL_PERCPU), %ecx
+ 	movl %ecx, %fs
+ 	UNWIND_ESPFIX_STACK
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	/*CFI_REGISTER es, ecx*/
+-	movl PT_FS(%esp), %edi		# get the function address
++	GS_TO_REG %ecx
++	movl PT_GS(%esp), %edi		# get the function address
+ 	movl PT_ORIG_EAX(%esp), %edx	# get the error code
+ 	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
+-	mov  %ecx, PT_FS(%esp)
+-	/*CFI_REL_OFFSET fs, ES*/
++	REG_TO_PTGS %ecx
++	SET_KERNEL_GS %ecx
+ 	movl $(__USER_DS), %ecx
+ 	movl %ecx, %ds
+ 	movl %ecx, %es
+@@ -1390,20 +1516,21 @@ END(page_fault)
+  * by hand onto the new stack - while updating the return eip past
+  * the instruction that would have done it for sysenter.
+  */
+-#define FIX_STACK(offset, ok, label)		\
+-	cmpw $__KERNEL_CS,4(%esp);		\
+-	jne ok;					\
+-label:						\
+-	movl TSS_sysenter_sp0+offset(%esp),%esp;	\
+-	CFI_DEF_CFA esp, 0;			\
+-	CFI_UNDEFINED eip;			\
+-	pushfl;					\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
+-	pushl $__KERNEL_CS;			\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
+-	pushl $sysenter_past_esp;		\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
++.macro FIX_STACK offset ok label
++	cmpw $__KERNEL_CS, 4(%esp)
++	jne \ok
++\label:
++	movl TSS_sysenter_sp0 + \offset(%esp), %esp
++	CFI_DEF_CFA esp, 0
++	CFI_UNDEFINED eip
++	pushfl
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $__KERNEL_CS
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $sysenter_past_esp
++	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eip, 0
++.endm
+ #endif /* CONFIG_XEN */
+ 
+ ENTRY(debug)
+@@ -1411,7 +1538,7 @@ ENTRY(debug)
+ #ifndef CONFIG_XEN
+ 	cmpl $ia32_sysenter_target,(%esp)
+ 	jne debug_stack_correct
+-	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
++	FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
+ debug_stack_correct:
+ #endif /* !CONFIG_XEN */
+ 	pushl $-1			# mark this as an int
+@@ -1471,7 +1598,7 @@ nmi_stack_correct:
+ 
+ nmi_stack_fixup:
+ 	RING0_INT_FRAME
+-	FIX_STACK(12,nmi_stack_correct, 1)
++	FIX_STACK 12, nmi_stack_correct, 1
+ 	jmp nmi_stack_correct
+ 
+ nmi_debug_stack_check:
+@@ -1482,7 +1609,7 @@ nmi_debug_stack_check:
+ 	jb nmi_stack_correct
+ 	cmpl $debug_esp_fix_insn,(%esp)
+ 	ja nmi_stack_correct
+-	FIX_STACK(24,nmi_stack_correct, 1)
++	FIX_STACK 24, nmi_stack_correct, 1
+ 	jmp nmi_stack_correct
+ 
+ nmi_espfix_stack:
+@@ -1494,7 +1621,7 @@ nmi_espfix_stack:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl %esp
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	addw $4, (%esp)
++	addl $4, (%esp)
+ 	/* copy the iret frame of 12 bytes */
+ 	.rept 3
+ 	pushl 16(%esp)
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:52:02.000000000 +0100
+@@ -51,10 +51,10 @@
+ #include <asm/unistd.h>
+ #include <asm/thread_info.h>
+ #include <asm/hw_irq.h>
+-#include <asm/page.h>
++#include <asm/page_types.h>
+ #include <asm/irqflags.h>
+ #include <asm/ftrace.h>
+-#include <asm/errno.h>
++#include <asm/percpu.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/features.h>
+ 
+@@ -81,20 +81,17 @@ ENTRY(ftrace_caller)
+ 	movq 8(%rbp), %rsi
+ 	subq $MCOUNT_INSN_SIZE, %rdi
+ 
+-.globl ftrace_call
+-ftrace_call:
++GLOBAL(ftrace_call)
+ 	call ftrace_stub
+ 
+ 	MCOUNT_RESTORE_FRAME
+ 
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+-.globl ftrace_graph_call
+-ftrace_graph_call:
++GLOBAL(ftrace_graph_call)
+ 	jmp ftrace_stub
+ #endif
+ 
+-.globl ftrace_stub
+-ftrace_stub:
++GLOBAL(ftrace_stub)
+ 	retq
+ END(ftrace_caller)
+ 
+@@ -114,8 +111,7 @@ ENTRY(mcount)
+ 	jnz ftrace_graph_caller
+ #endif
+ 
+-.globl ftrace_stub
+-ftrace_stub:
++GLOBAL(ftrace_stub)
+ 	retq
+ 
+ trace:
+@@ -152,9 +148,7 @@ ENTRY(ftrace_graph_caller)
+ 	retq
+ END(ftrace_graph_caller)
+ 
+-
+-.globl return_to_handler
+-return_to_handler:
++GLOBAL(return_to_handler)
+ 	subq  $80, %rsp
+ 
+ 	movq %rax, (%rsp)
+@@ -192,6 +186,7 @@ return_to_handler:
+ ENTRY(native_usergs_sysret64)
+ 	swapgs
+ 	sysretq
++ENDPROC(native_usergs_sysret64)
+ #endif /* CONFIG_PARAVIRT */
+ 
+ 
+@@ -375,15 +370,15 @@ ENTRY(save_args)
+ 	je 1f
+ 	SWAPGS
+ 	/*
+-	 * irqcount is used to check if a CPU is already on an interrupt stack
++	 * irq_count is used to check if a CPU is already on an interrupt stack
+ 	 * or not. While this is essentially redundant with preempt_count it is
+ 	 * a little cheaper to use a separate counter in the PDA (short of
+ 	 * moving irq_enter into assembly, which would be too much work)
+ 	 */
+-1:	incl %gs:pda_irqcount
++1:	incl PER_CPU_VAR(irq_count)
+ 	jne 2f
+ 	popq_cfi %rax			/* move return address... */
+-	mov %gs:pda_irqstackptr,%rsp
++	mov PER_CPU_VAR(irq_stack_ptr),%rsp
+ 	EMPTY_FRAME 0
+ 	pushq_cfi %rbp			/* backlink for unwinder */
+ 	pushq_cfi %rax			/* ... to the new stack */
+@@ -413,6 +408,7 @@ END(save_rest)
+ 
+ #ifndef CONFIG_XEN
+ /* save complete stack frame */
++	.pushsection .kprobes.text, "ax"
+ ENTRY(save_paranoid)
+ 	XCPT_FRAME 1 RDI+8
+ 	cld
+@@ -441,6 +437,7 @@ ENTRY(save_paranoid)
+ 1:	ret
+ 	CFI_ENDPROC
+ END(save_paranoid)
++	.popsection
+ #endif
+ 
+ /*
+@@ -451,6 +448,8 @@ END(save_paranoid)
+ ENTRY(ret_from_fork)
+ 	DEFAULT_FRAME
+ 
++	LOCK ; btr $TIF_FORK,TI_flags(%r8)
++
+ 	push kernel_eflags(%rip)
+ 	CFI_ADJUST_CFA_OFFSET 8
+ 	popf					# reset kernel eflags
+@@ -460,7 +459,6 @@ ENTRY(ret_from_fork)
+ 
+ 	GET_THREAD_INFO(%rcx)
+ 
+-	CFI_REMEMBER_STATE
+ 	RESTORE_REST
+ 
+ 	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
+@@ -472,7 +470,6 @@ ENTRY(ret_from_fork)
+ 	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
+ 	jmp ret_from_sys_call			# go to the SYSRET fastpath
+ 
+-	CFI_RESTORE_STATE
+ 	CFI_ENDPROC
+ END(ret_from_fork)
+ 
+@@ -648,9 +645,7 @@ tracesys:
+  * Syscall return path ending with IRET.
+  * Has correct top of stack, but partial stack frame.
+  */
+-	.globl int_ret_from_sys_call
+-	.globl int_with_check
+-int_ret_from_sys_call:
++GLOBAL(int_ret_from_sys_call)
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	testb $3,CS-ARGOFFSET(%rsp)
+@@ -661,7 +656,7 @@ int_ret_from_sys_call:
+ 1:              
+ 	movl $_TIF_ALLWORK_MASK,%edi
+ 	/* edi:	mask to check */
+-int_with_check:
++GLOBAL(int_with_check)
+ 	LOCKDEP_SYS_EXIT_IRQ
+ 	GET_THREAD_INFO(%rcx)
+ 	movl TI_flags(%rcx),%edx
+@@ -883,10 +878,14 @@ apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
+ 	irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
+ #endif
+ 
++#ifdef CONFIG_X86_UV
+ apicinterrupt UV_BAU_MESSAGE \
+ 	uv_bau_message_intr1 uv_bau_message_interrupt
++#endif
+ apicinterrupt LOCAL_TIMER_VECTOR \
+ 	apic_timer_interrupt smp_apic_timer_interrupt
++apicinterrupt GENERIC_INTERRUPT_VECTOR \
++	generic_interrupt smp_generic_interrupt
+ 
+ #ifdef CONFIG_SMP
+ apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
+@@ -1004,15 +1003,15 @@ ENTRY(do_hypervisor_callback)   # do_hyp
+ 	movq %rdi, %rsp            # we don't return, adjust the stack frame
+ 	CFI_ENDPROC
+ 	DEFAULT_FRAME
+-11:	incl %gs:pda_irqcount
++11:	incl PER_CPU_VAR(irq_count)
+ 	movq %rsp,%rbp
+ 	CFI_DEF_CFA_REGISTER rbp
+-	cmovzq %gs:pda_irqstackptr,%rsp
++	cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp
+ 	pushq %rbp			# backlink for old unwinder
+ 	call evtchn_do_upcall
+ 	popq %rsp
+ 	CFI_DEF_CFA_REGISTER rsp
+-	decl %gs:pda_irqcount
++	decl PER_CPU_VAR(irq_count)
+ 	jmp  error_exit
+ 	CFI_ENDPROC
+ END(do_hypervisor_callback)
+@@ -1203,14 +1202,14 @@ ENTRY(call_softirq)
+ 	CFI_REL_OFFSET rbp,0
+ 	mov  %rsp,%rbp
+ 	CFI_DEF_CFA_REGISTER rbp
+-	incl %gs:pda_irqcount
+-	cmove %gs:pda_irqstackptr,%rsp
++	incl PER_CPU_VAR(irq_count)
++	cmove PER_CPU_VAR(irq_stack_ptr),%rsp
+ 	push  %rbp			# backlink for old unwinder
+ 	call __do_softirq
+ 	leaveq
+ 	CFI_DEF_CFA_REGISTER	rsp
+ 	CFI_ADJUST_CFA_OFFSET   -8
+-	decl %gs:pda_irqcount
++	decl PER_CPU_VAR(irq_count)
+ 	ret
+ 	CFI_ENDPROC
+ END(call_softirq)
+@@ -1256,7 +1255,10 @@ ENTRY(paranoid_exit)
+ paranoid_swapgs:
+ 	TRACE_IRQS_IRETQ 0
+ 	SWAPGS_UNSAFE_STACK
++	RESTORE_ALL 8
++	jmp irq_return
+ paranoid_restore:
++	TRACE_IRQS_IRETQ 0
+ 	RESTORE_ALL 8
+ 	jmp irq_return
+ paranoid_userspace:
+--- head-2010-01-18.orig/arch/x86/kernel/head-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -2,6 +2,7 @@
+ #include <linux/init.h>
+ 
+ #include <asm/setup.h>
++#ifndef CONFIG_XEN
+ #include <asm/bios_ebda.h>
+ 
+ #define BIOS_LOWMEM_KILOBYTES 0x413
+@@ -18,7 +19,6 @@
+  */
+ void __init reserve_ebda_region(void)
+ {
+-#ifndef CONFIG_XEN
+ 	unsigned int lowmem, ebda_addr;
+ 
+ 	/* To determine the position of the EBDA and the */
+@@ -53,5 +53,173 @@ void __init reserve_ebda_region(void)
+ 
+ 	/* reserve all memory between lowmem and the 1MB mark */
+ 	reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
++}
++#else /* CONFIG_XEN */
++#include <linux/module.h>
++#include <asm/fixmap.h>
++#include <asm/pgtable.h>
++#include <asm/sections.h>
++#include <asm/setup_arch.h>
++#include <xen/interface/callback.h>
++#include <xen/interface/memory.h>
++
++extern void hypervisor_callback(void);
++extern void failsafe_callback(void);
++extern void nmi(void);
++
++#ifdef CONFIG_X86_64
++#include <asm/proto.h>
++#define CALLBACK_ADDR(fn) ((unsigned long)(fn))
++#else
++#define CALLBACK_ADDR(fn) { __KERNEL_CS, (unsigned long)(fn) }
++#endif
++
++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 xen_start_kernel(void)
++{
++	unsigned int i;
++	struct xen_machphys_mapping mapping;
++	unsigned long machine_to_phys_nr_ents;
++#ifdef CONFIG_X86_32
++	struct xen_platform_parameters pp;
++	extern pte_t swapper_pg_fixmap[PTRS_PER_PTE];
++	unsigned long addr;
++#endif
++
++	xen_setup_features();
++
++	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;
++	while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
++		machine_to_phys_order++;
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap))
++		phys_to_machine_mapping =
++			(unsigned long *)xen_start_info->mfn_list;
++
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_writable_pagetables));
++
++	reserve_early(ALIGN(__pa_symbol(&_end), PAGE_SIZE),
++		      __pa(xen_start_info->pt_base)
++		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
++		      "Xen provided");
++
++#ifdef CONFIG_X86_32
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_4gb_segments));
++
++	init_mm.pgd = swapper_pg_dir = (pgd_t *)xen_start_info->pt_base;
++
++	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) {
++		hypervisor_virt_start = pp.virt_start;
++		reserve_top_address(0UL - pp.virt_start);
++	}
++
++	BUG_ON(pte_index(hypervisor_virt_start));
++
++	/* Do an early initialization of the fixmap area */
++	make_lowmem_page_readonly(swapper_pg_fixmap, XENFEAT_writable_page_tables);
++	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
++	set_pmd(pmd_offset(pud_offset(swapper_pg_dir + pgd_index(addr),
++				      addr),
++			   addr),
++		__pmd(__pa_symbol(swapper_pg_fixmap) | _PAGE_TABLE));
++#else
++	check_efer();
++	xen_init_pt();
++#endif
++
++#define __FIXADDR_TOP (-PAGE_SIZE)
++#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
++#define FIX_BUG_ON(fix) BUILD_BUG_ON(pmd_index(__fix_to_virt(FIX_##fix)) \
++			!= pmd_index(__fix_to_virt(FIX_EARLYCON_MEM_BASE)))
++	FIX_BUG_ON(SHARED_INFO);
++	FIX_BUG_ON(ISAMAP_BEGIN);
++	FIX_BUG_ON(ISAMAP_END);
++#undef pmd_index
++#undef __FIXADDR_TOP
++
++	/* Switch to the real shared_info page, and clear the dummy page. */
++	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++	memset(empty_zero_page, 0, sizeof(empty_zero_page));
++
++	/* Set up mapping of lowest 1MB of physical memory. */
++	for (i = 0; i < NR_FIX_ISAMAPS; i++)
++		if (is_initial_xendomain())
++			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
++		else
++			__set_fixmap(FIX_ISAMAP_BEGIN - i,
++				     virt_to_machine(empty_zero_page),
++				     PAGE_KERNEL_RO);
++
++}
++
++void __init machine_specific_arch_setup(void)
++{
++	int ret;
++	static const struct callback_register __initconst event = {
++		.type = CALLBACKTYPE_event,
++		.address = CALLBACK_ADDR(hypervisor_callback)
++	};
++	static const struct callback_register __initconst failsafe = {
++		.type = CALLBACKTYPE_failsafe,
++		.address = CALLBACK_ADDR(failsafe_callback)
++	};
++#ifdef CONFIG_X86_64
++	static const struct callback_register __initconst syscall = {
++		.type = CALLBACKTYPE_syscall,
++		.address = CALLBACK_ADDR(system_call)
++	};
++#endif
++#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
++	static const struct callback_register __initconst nmi_cb = {
++		.type = CALLBACKTYPE_nmi,
++		.address = CALLBACK_ADDR(nmi)
++	};
++#endif
++
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
++#ifdef CONFIG_X86_64
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
++#endif
++#if CONFIG_XEN_COMPAT <= 0x030002
++#ifdef CONFIG_X86_32
++	if (ret == -ENOSYS)
++		ret = HYPERVISOR_set_callbacks(
++			event.address.cs, event.address.eip,
++			failsafe.address.cs, failsafe.address.eip);
++#else
++		ret = HYPERVISOR_set_callbacks(
++			event.address,
++			failsafe.address,
++			syscall.address);
++#endif
++#endif
++	BUG_ON(ret);
++
++#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret == -ENOSYS) {
++		static struct xennmi_callback __initdata cb = {
++			.handler_address = (unsigned long)nmi
++		};
++
++		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
++	}
++#endif
+ #endif
+ }
++#endif /* CONFIG_XEN */
+--- head-2010-01-18.orig/arch/x86/kernel/head32-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -9,6 +9,7 @@
+ #include <linux/start_kernel.h>
+ 
+ #include <asm/setup.h>
++#include <asm/setup_arch.h>
+ #include <asm/sections.h>
+ #include <asm/e820.h>
+ #include <asm/bios_ebda.h>
+@@ -18,7 +19,7 @@ void __init i386_start_kernel(void)
+ {
+ 	reserve_trampoline_memory();
+ 
+-	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
++	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+ 
+ #ifndef CONFIG_XEN
+ #ifdef CONFIG_BLK_DEV_INITRD
+@@ -30,14 +31,8 @@ void __init i386_start_kernel(void)
+ 		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ 	}
+ #endif
+-	reserve_early(init_pg_tables_start, init_pg_tables_end,
+-			"INIT_PG_TABLE");
++	reserve_ebda_region();
+ #else
+-	reserve_early(ALIGN(__pa_symbol(&_end), PAGE_SIZE),
+-		      __pa(xen_start_info->pt_base)
+-		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
+-		      "Xen provided");
+-
+ 	{
+ 		int max_cmdline;
+ 
+@@ -46,9 +41,9 @@ void __init i386_start_kernel(void)
+ 		memcpy(boot_command_line, xen_start_info->cmd_line, max_cmdline);
+ 		boot_command_line[max_cmdline-1] = '\0';
+ 	}
+-#endif
+ 
+-	reserve_ebda_region();
++	xen_start_kernel();
++#endif
+ 
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -7,9 +7,6 @@
+  *	Modified for Xen.
+  */
+ 
+-/* PDA is not ready to be used until the end of x86_64_start_kernel(). */
+-#define arch_use_lazy_mmu_mode() false
+-
+ #include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <linux/types.h>
+@@ -18,12 +15,12 @@
+ #include <linux/percpu.h>
+ #include <linux/start_kernel.h>
+ #include <linux/io.h>
+-#include <linux/module.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/proto.h>
+ #include <asm/smp.h>
+ #include <asm/setup.h>
++#include <asm/setup_arch.h>
+ #include <asm/desc.h>
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+@@ -33,27 +30,6 @@
+ #include <asm/bios_ebda.h>
+ #include <asm/trampoline.h>
+ 
+-/* boot cpu pda */
+-static struct x8664_pda _boot_cpu_pda;
+-
+-#ifdef CONFIG_SMP
+-/*
+- * We install an empty cpu_pda pointer table to indicate to early users
+- * (numa_set_node) that the cpu_pda pointer table for cpus other than
+- * the boot cpu is not yet setup.
+- */
+-static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata;
+-#else
+-static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
+-#endif
+-
+-void __init x86_64_init_pda(void)
+-{
+-	_cpu_pda = __cpu_pda;
+-	cpu_pda(0) = &_boot_cpu_pda;
+-	pda_init(0);
+-}
+-
+ #ifndef CONFIG_XEN
+ static void __init zap_identity_mappings(void)
+ {
+@@ -92,16 +68,9 @@ static void __init copy_bootdata(char *r
+ }
+ 
+ #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;
+-
+ 	/*
+ 	 * Build-time sanity checks on the kernel image and module
+ 	 * area mappings. (these are purely build-time and produce no code)
+@@ -116,21 +85,8 @@ void __init x86_64_start_kernel(char * r
+ 				(__START_KERNEL & PGDIR_MASK)));
+ 	BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END);
+ 
+-	xen_setup_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;
+-
+-	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++;
++	xen_start_kernel();
+ 
+ #ifndef CONFIG_XEN
+ 	/* clear bss before set_intr_gate with early_idt_handler */
+@@ -155,7 +111,7 @@ void __init x86_64_start_kernel(char * r
+ 	if (console_loglevel == 10)
+ 		early_printk("Kernel alive\n");
+ 
+-	x86_64_init_pda();
++	xen_switch_pt();
+ 
+ 	x86_64_start_reservations(real_mode_data);
+ }
+@@ -166,12 +122,7 @@ void __init x86_64_start_reservations(ch
+ 
+ 	reserve_trampoline_memory();
+ 
+-	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+-
+-	reserve_early(round_up(__pa_symbol(&_end), PAGE_SIZE),
+-		      __pa(xen_start_info->pt_base)
+-		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
+-		      "Xen provided");
++	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+ 
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:52:02.000000000 +0100
+@@ -6,12 +6,14 @@
+ #include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+-#include <asm/page.h>
++#include <asm/page_types.h>
++#include <asm/pgtable_types.h>
+ #include <asm/cache.h>
+ #include <asm/thread_info.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/boot.h>
+ #include <asm/dwarf2.h>
++#include <asm/percpu.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/elfnote.h>
+ 
+@@ -38,9 +40,6 @@ ENTRY(startup_32)
+ 	/* Set up the stack pointer */
+ 	movl $(init_thread_union+THREAD_SIZE),%esp
+ 
+-	movl %ss,%eax
+-	movl %eax,%fs			# gets reset once there's real percpu
+-
+ 	/* get vendor info */
+ 	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
+ 	XEN_CPUID
+@@ -63,7 +62,49 @@ ENTRY(startup_32)
+ 
+ 	movb $1,X86_HARD_MATH
+ 
+-	xorl %eax,%eax		# Clear GS
++#ifdef CONFIG_CC_STACKPROTECTOR
++	/*
++	 * The linker can't handle this by relocation.  Manually set
++	 * base address in stack canary segment descriptor.
++	 */
++	movl $per_cpu__gdt_page,%eax
++	movl $per_cpu__stack_canary,%ecx
++	subl $20, %ecx
++	movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
++	shrl $16, %ecx
++	movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
++	movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
++#endif
++
++	# %esi still points to start_info, and no registers
++	# need to be preserved.
++
++	movl XEN_START_mfn_list(%esi), %ebx
++	movl $(per_cpu__gdt_page - __PAGE_OFFSET), %eax
++	shrl $PAGE_SHIFT, %eax
++	movl (%ebx,%eax,4), %ecx
++	pushl %ecx			# frame number for set_gdt below
++
++	xorl %esi, %esi
++	xorl %edx, %edx
++	shldl $PAGE_SHIFT, %ecx, %edx
++	shll $PAGE_SHIFT, %ecx
++	orl $_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY, %ecx
++	movl $per_cpu__gdt_page, %ebx
++	movl $__HYPERVISOR_update_va_mapping, %eax
++	int $0x82
++
++	movl $(PAGE_SIZE_asm / 8), %ecx
++	movl %esp, %ebx
++	movl $__HYPERVISOR_set_gdt, %eax
++	int $0x82
++
++	popl %ecx
++
++	movl $(__KERNEL_PERCPU), %eax
++	movl %eax,%fs			# set this cpu's percpu
++
++	movl $(__KERNEL_STACK_CANARY),%eax
+ 	movl %eax,%gs
+ 
+ 	cld			# gcc2 wants the direction flag cleared at all times
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:02.000000000 +0100
+@@ -21,6 +21,7 @@
+ #include <asm/msr.h>
+ #include <asm/cache.h>
+ #include <asm/dwarf2.h>
++#include <asm/percpu.h>
+ #include <xen/interface/elfnote.h>
+ 
+ 	.section .text.head, "ax", @progbits
+@@ -32,11 +33,23 @@ startup_64:
+ 	/* rsi is pointer to startup info structure.
+ 	   pass it to C */
+ 	movq %rsi,%rdi
++
++	/* Set up %gs.
++	 *
++	 * The base of %gs always points to the bottom of the irqstack
++	 * union.  If the stack protector canary is enabled, it is
++	 * located at %gs:40.  Note that, on SMP, the boot cpu uses
++	 * init data section till per cpu areas are set up.
++	 */
++	movl	$MSR_GS_BASE,%ecx
++	movq	$INIT_PER_CPU_VAR(irq_stack_union),%rax
++	movq    %rax,%rdx
++	shrq	$32,%rdx
++	wrmsr
++
+ 	pushq $0		# fake return address
+ 	jmp x86_64_start_kernel
+ 
+-.balign PAGE_SIZE
+-
+ #define NEXT_PAGE(name) \
+ 	.balign	PAGE_SIZE; \
+ 	phys_##name = . - .text.head; \
+--- head-2010-01-18.orig/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -91,9 +91,8 @@ static int do_iopl(unsigned int level, s
+ }
+ 
+ #ifdef CONFIG_X86_32
+-asmlinkage long sys_iopl(unsigned long regsp)
++long sys_iopl(struct pt_regs *regs)
+ {
+-	struct pt_regs *regs = (struct pt_regs *)&regsp;
+ 	unsigned int level = regs->bx;
+ #else
+ asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
+--- head-2010-01-18.orig/arch/x86/kernel/irq-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq-xen.c	2009-12-18 09:57:23.000000000 +0100
+@@ -6,13 +6,20 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/seq_file.h>
+ #include <linux/smp.h>
++#include <linux/ftrace.h>
+ 
+ #include <asm/apic.h>
+ #include <asm/io_apic.h>
+ #include <asm/irq.h>
++#include <asm/idle.h>
+ 
+ atomic_t irq_err_count;
+ 
++#ifndef CONFIG_XEN
++/* Function pointer for generic interrupt vector handling */
++void (*generic_interrupt_extension)(void) = NULL;
++#endif
++
+ /*
+  * 'what should we do if we get a hw irq event on an illegal vector'.
+  * each architecture has to answer this themselves.
+@@ -36,11 +43,7 @@ void ack_bad_irq(unsigned int irq)
+ #endif
+ }
+ 
+-#ifdef CONFIG_X86_32
+-# define irq_stats(x)		(&per_cpu(irq_stat, x))
+-#else
+-# define irq_stats(x)		cpu_pda(x)
+-#endif
++#define irq_stats(x)		(&per_cpu(irq_stat, x))
+ /*
+  * /proc/interrupts printing:
+  */
+@@ -57,6 +60,19 @@ static int show_other_interrupts(struct 
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
+ 	seq_printf(p, "  Local timer interrupts\n");
++
++	seq_printf(p, "%*s: ", prec, "SPU");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
++	seq_printf(p, "  Spurious interrupts\n");
++#endif
++#ifndef CONFIG_XEN
++	if (generic_interrupt_extension) {
++		seq_printf(p, "%*s: ", prec, "PLT");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
++		seq_printf(p, "  Platform interrupts\n");
++	}
+ #endif
+ #ifdef CONFIG_SMP
+ 	seq_printf(p, "%*s: ", prec, "RES");
+@@ -86,12 +102,6 @@ static int show_other_interrupts(struct 
+ 	seq_printf(p, "  Threshold APIC interrupts\n");
+ # endif
+ #endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	seq_printf(p, "%*s: ", prec, "SPU");
+-	for_each_online_cpu(j)
+-		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+-	seq_printf(p, "  Spurious interrupts\n");
+-#endif
+ 	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+ 	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
+@@ -128,23 +138,15 @@ int show_interrupts(struct seq_file *p, 
+ 		return 0;
+ 
+ 	spin_lock_irqsave(&desc->lock, flags);
+-#ifndef CONFIG_SMP
+-	any_count = kstat_irqs(i);
+-#else
+ 	for_each_online_cpu(j)
+ 		any_count |= kstat_irqs_cpu(i, j);
+-#endif
+ 	action = desc->action;
+ 	if (!action && !any_count)
+ 		goto out;
+ 
+ 	seq_printf(p, "%*d: ", prec, i);
+-#ifndef CONFIG_SMP
+-	seq_printf(p, "%10u ", kstat_irqs(i));
+-#else
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+-#endif
+ 	seq_printf(p, " %8s", desc->chip->name);
+ 	seq_printf(p, "-%-8s", desc->name);
+ 
+@@ -169,6 +171,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	sum += irq_stats(cpu)->apic_timer_irqs;
++	sum += irq_stats(cpu)->irq_spurious_count;
++#endif
++#ifndef CONFIG_XEN
++	if (generic_interrupt_extension)
++		sum += irq_stats(cpu)->generic_irqs;
+ #endif
+ #ifdef CONFIG_SMP
+ 	sum += irq_stats(cpu)->irq_resched_count;
+@@ -183,9 +190,6 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ 	sum += irq_stats(cpu)->irq_threshold_count;
+ #endif
+ #endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	sum += irq_stats(cpu)->irq_spurious_count;
+-#endif
+ 	return sum;
+ }
+ 
+@@ -198,3 +202,64 @@ u64 arch_irq_stat(void)
+ #endif
+ 	return sum;
+ }
++
++
++#ifndef CONFIG_XEN
++/*
++ * do_IRQ handles all normal device IRQ's (the special
++ * SMP cross-CPU interrupts have their own specific
++ * handlers).
++ */
++unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
++{
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
++	/* high bit used in ret_from_ code  */
++	unsigned vector = ~regs->orig_ax;
++	unsigned irq;
++
++	exit_idle();
++	irq_enter();
++
++	irq = __get_cpu_var(vector_irq)[vector];
++
++	if (!handle_irq(irq, regs)) {
++#ifdef CONFIG_X86_64
++		if (!disable_apic)
++			ack_APIC_irq();
++#endif
++
++		if (printk_ratelimit())
++			printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
++			       __func__, smp_processor_id(), vector, irq);
++	}
++
++	irq_exit();
++
++	set_irq_regs(old_regs);
++	return 1;
++}
++
++/*
++ * Handler for GENERIC_INTERRUPT_VECTOR.
++ */
++void smp_generic_interrupt(struct pt_regs *regs)
++{
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
++	ack_APIC_irq();
++
++	exit_idle();
++
++	irq_enter();
++
++	inc_irq_stat(generic_irqs);
++
++	if (generic_interrupt_extension)
++		generic_interrupt_extension();
++
++	irq_exit();
++
++	set_irq_regs(old_regs);
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -16,6 +16,7 @@
+ #include <linux/cpu.h>
+ #include <linux/delay.h>
+ #include <linux/uaccess.h>
++#include <linux/percpu.h>
+ 
+ #include <asm/apic.h>
+ 
+@@ -55,13 +56,13 @@ static inline void print_stack_overflow(
+ union irq_ctx {
+ 	struct thread_info      tinfo;
+ 	u32                     stack[THREAD_SIZE/sizeof(u32)];
+-};
++} __attribute__((aligned(PAGE_SIZE)));
+ 
+-static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+-static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
++static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
++static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
+ 
+-static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
+-static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
++static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
++static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+ 
+ static void call_on_stack(void *func, void *stack)
+ {
+@@ -81,7 +82,7 @@ execute_on_irq_stack(int overflow, struc
+ 	u32 *isp, arg1, arg2;
+ 
+ 	curctx = (union irq_ctx *) current_thread_info();
+-	irqctx = hardirq_ctx[smp_processor_id()];
++	irqctx = __get_cpu_var(hardirq_ctx);
+ 
+ 	/*
+ 	 * this is where we switch to the IRQ stack. However, if we are
+@@ -125,34 +126,34 @@ void __cpuinit irq_ctx_init(int cpu)
+ {
+ 	union irq_ctx *irqctx;
+ 
+-	if (hardirq_ctx[cpu])
++	if (per_cpu(hardirq_ctx, cpu))
+ 		return;
+ 
+-	irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
++	irqctx = &per_cpu(hardirq_stack, cpu);
+ 	irqctx->tinfo.task		= NULL;
+ 	irqctx->tinfo.exec_domain	= NULL;
+ 	irqctx->tinfo.cpu		= cpu;
+ 	irqctx->tinfo.preempt_count	= HARDIRQ_OFFSET;
+ 	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+ 
+-	hardirq_ctx[cpu] = irqctx;
++	per_cpu(hardirq_ctx, cpu) = irqctx;
+ 
+-	irqctx = (union irq_ctx *) &softirq_stack[cpu*THREAD_SIZE];
++	irqctx = &per_cpu(softirq_stack, cpu);
+ 	irqctx->tinfo.task		= NULL;
+ 	irqctx->tinfo.exec_domain	= NULL;
+ 	irqctx->tinfo.cpu		= cpu;
+ 	irqctx->tinfo.preempt_count	= 0;
+ 	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+ 
+-	softirq_ctx[cpu] = irqctx;
++	per_cpu(softirq_ctx, cpu) = irqctx;
+ 
+ 	printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
+-	       cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
++	       cpu, per_cpu(hardirq_ctx, cpu),  per_cpu(softirq_ctx, cpu));
+ }
+ 
+ void irq_ctx_exit(int cpu)
+ {
+-	hardirq_ctx[cpu] = NULL;
++	per_cpu(hardirq_ctx, cpu) = NULL;
+ }
+ 
+ asmlinkage void do_softirq(void)
+@@ -169,7 +170,7 @@ asmlinkage void do_softirq(void)
+ 
+ 	if (local_softirq_pending()) {
+ 		curctx = current_thread_info();
+-		irqctx = softirq_ctx[smp_processor_id()];
++		irqctx = __get_cpu_var(softirq_ctx);
+ 		irqctx->tinfo.task = curctx->task;
+ 		irqctx->tinfo.previous_esp = current_stack_pointer;
+ 
+@@ -191,30 +192,16 @@ static inline int
+ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
+ #endif
+ 
+-/*
+- * do_IRQ handles all normal device IRQ's (the special
+- * SMP cross-CPU interrupts have their own specific
+- * handlers).
+- */
+-unsigned int do_IRQ(struct pt_regs *regs)
++bool handle_irq(unsigned irq, struct pt_regs *regs)
+ {
+-	struct pt_regs *old_regs;
+-	/* high bit used in ret_from_ code */
+-	int overflow;
+-	unsigned irq = ~regs->orig_ax;
+ 	struct irq_desc *desc;
+-
+-	old_regs = set_irq_regs(regs);
+-	/*irq_enter();*/
++	int overflow;
+ 
+ 	overflow = check_stack_overflow();
+ 
+ 	desc = irq_to_desc(irq);
+-	if (unlikely(!desc)) {
+-		printk(KERN_EMERG "%s: cannot handle IRQ %d cpu %d\n",
+-					__func__, irq, smp_processor_id());
+-		BUG();
+-	}
++	if (unlikely(!desc))
++		return false;
+ 
+ 	if (!execute_on_irq_stack(overflow, desc, irq)) {
+ 		if (unlikely(overflow))
+@@ -222,9 +209,7 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 		desc->handle_irq(irq, desc);
+ 	}
+ 
+-	/*irq_exit();*/
+-	set_irq_regs(old_regs);
+-	return 1;
++	return true;
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+@@ -244,7 +229,7 @@ void fixup_irqs(void)
+ 		if (irq == 2)
+ 			continue;
+ 
+-		affinity = &desc->affinity;
++		affinity = desc->affinity;
+ 		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ 			/*printk("Breaking affinity for irq %i\n", irq);*/
+ 			affinity = cpu_all_mask;
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -18,6 +18,13 @@
+ #include <linux/smp.h>
+ #include <asm/io_apic.h>
+ #include <asm/idle.h>
++#include <asm/apic.h>
++
++DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
++EXPORT_PER_CPU_SYMBOL(irq_stat);
++
++DEFINE_PER_CPU(struct pt_regs *, irq_regs);
++EXPORT_PER_CPU_SYMBOL(irq_regs);
+ 
+ /*
+  * Probabilistic stack overflow check:
+@@ -41,41 +48,18 @@ static inline void stack_overflow_check(
+ #endif
+ }
+ 
+-/*
+- * do_IRQ handles all normal device IRQ's (the special
+- * SMP cross-CPU interrupts have their own specific
+- * handlers).
+- */
+-asmlinkage unsigned int /*__irq_entry*/ do_IRQ(struct pt_regs *regs)
++bool handle_irq(unsigned irq, struct pt_regs *regs)
+ {
+-	struct pt_regs *old_regs = set_irq_regs(regs);
+ 	struct irq_desc *desc;
+ 
+-	/* high bit used in ret_from_ code  */
+-	unsigned irq = ~regs->orig_ax;
+-
+-	/*exit_idle();*/
+-	/*irq_enter();*/
+-
+ 	stack_overflow_check(regs);
+ 
+ 	desc = irq_to_desc(irq);
+-	if (likely(desc))
+-		generic_handle_irq_desc(irq, desc);
+-	else {
+-#ifndef CONFIG_XEN
+-		if (!disable_apic)
+-			ack_APIC_irq();
+-#endif
+-		if (printk_ratelimit())
+-			printk(KERN_EMERG "%s: %d.%d No irq handler for irq\n",
+-				__func__, smp_processor_id(), irq);
+-	}
+-
+-	/*irq_exit();*/
++	if (unlikely(!desc))
++		return false;
+ 
+-	set_irq_regs(old_regs);
+-	return 1;
++	generic_handle_irq_desc(irq, desc);
++	return true;
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+@@ -99,7 +83,7 @@ void fixup_irqs(void)
+ 		/* interrupt's are disabled at this point */
+ 		spin_lock(&desc->lock);
+ 
+-		affinity = &desc->affinity;
++		affinity = desc->affinity;
+ 		if (!irq_has_action(irq) ||
+ 		    cpumask_equal(affinity, cpu_online_mask)) {
+ 			spin_unlock(&desc->lock);
+--- head-2010-01-18.orig/arch/x86/kernel/machine_kexec_64.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/machine_kexec_64.c	2009-11-06 10:52:02.000000000 +0100
+@@ -90,13 +90,8 @@ void machine_kexec_setup_load_arg(xen_ke
+ 	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
+ 	xki->page_list[PA_TABLE_PAGE] = __ma(table_page);
+ 
+-	xki->page_list[PA_PGD] = __ma(kexec_pgd);
+-	xki->page_list[PA_PUD_0] = __ma(kexec_pud0);
+-	xki->page_list[PA_PUD_1] = __ma(kexec_pud1);
+-	xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
+-	xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
+-	xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
+-	xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
++	if (image->type == KEXEC_TYPE_DEFAULT)
++		xki->page_list[PA_SWAP_PAGE] = page_to_phys(image->swap_page);
+ }
+ 
+ int __init machine_kexec_setup_resources(struct resource *hypervisor,
+@@ -159,7 +154,7 @@ static int init_one_level2_page(struct k
+ 	}
+ 	pmd = pmd_offset(pud, addr);
+ 	if (!pmd_present(*pmd))
+-		set_pmd(pmd, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
++		x_set_pmd(pmd, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
+ 	result = 0;
+ out:
+ 	return result;
+--- head-2010-01-18.orig/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -21,28 +21,28 @@
+  *	as published by the Free Software Foundation; either version
+  *	2 of the License, or (at your option) any later version.
+  */
++#include <linux/platform_device.h>
+ #include <linux/capability.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/firmware.h>
+ #include <linux/smp_lock.h>
++#include <linux/spinlock.h>
+ #include <linux/cpumask.h>
+-#include <linux/module.h>
+-#include <linux/slab.h>
++#include <linux/uaccess.h>
+ #include <linux/vmalloc.h>
+-#include <linux/miscdevice.h>
+-#include <linux/spinlock.h>
+-#include <linux/mm.h>
+-#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/mutex.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/slab.h>
+ #include <linux/cpu.h>
+-#include <linux/firmware.h>
+-#include <linux/platform_device.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
+ 
+-#include <asm/msr.h>
+-#include <asm/uaccess.h>
+-#include <asm/processor.h>
+ #include <asm/microcode.h>
++#include <asm/processor.h>
++#include <asm/msr.h>
+ 
+ MODULE_DESCRIPTION("Microcode Update Driver");
+ MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+@@ -51,7 +51,7 @@ MODULE_LICENSE("GPL");
+ static int verbose;
+ module_param(verbose, int, 0644);
+ 
+-#define MICROCODE_VERSION 	"2.00-xen"
++#define MICROCODE_VERSION	"2.00-xen"
+ 
+ /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+ static DEFINE_MUTEX(microcode_mutex);
+@@ -143,12 +143,12 @@ static void microcode_dev_exit(void)
+ 
+ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+ #else
+-#define microcode_dev_init() 0
+-#define microcode_dev_exit() do { } while (0)
++#define microcode_dev_init()	0
++#define microcode_dev_exit()	do { } while (0)
+ #endif
+ 
+ /* fake device for request_firmware */
+-static struct platform_device *microcode_pdev;
++static struct platform_device	*microcode_pdev;
+ 
+ static int request_microcode(const char *name)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -3,7 +3,7 @@
+  *	compliant MP-table parsing routines.
+  *
+  *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *	(c) 1998, 1999, 2000, 2009 Ingo Molnar <mingo@redhat.com>
+  *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
+  */
+ 
+@@ -29,11 +29,7 @@
+ #include <asm/setup.h>
+ #include <asm/smp.h>
+ 
+-#include <mach_apic.h>
+-#ifdef CONFIG_X86_32
+-#include <mach_apicdef.h>
+-#include <mach_mpparse.h>
+-#endif
++#include <asm/apic.h>
+ 
+ static void *_bus_to_virt(unsigned long ma)
+ {
+@@ -123,9 +119,6 @@ static void __init MP_bus_info(struct mp
+ 	} else
+ 		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ }
+-#endif
+-
+-#ifdef CONFIG_X86_IO_APIC
+ 
+ static int bad_ioapic(unsigned long address)
+ {
+@@ -153,11 +146,11 @@ static void __init MP_ioapic_info(struct
+ 	if (bad_ioapic(m->apicaddr))
+ 		return;
+ 
+-	mp_ioapics[nr_ioapics].mp_apicaddr = m->apicaddr;
+-	mp_ioapics[nr_ioapics].mp_apicid = m->apicid;
+-	mp_ioapics[nr_ioapics].mp_type = m->type;
+-	mp_ioapics[nr_ioapics].mp_apicver = m->apicver;
+-	mp_ioapics[nr_ioapics].mp_flags = m->flags;
++	mp_ioapics[nr_ioapics].apicaddr = m->apicaddr;
++	mp_ioapics[nr_ioapics].apicid = m->apicid;
++	mp_ioapics[nr_ioapics].type = m->type;
++	mp_ioapics[nr_ioapics].apicver = m->apicver;
++	mp_ioapics[nr_ioapics].flags = m->flags;
+ 	nr_ioapics++;
+ }
+ 
+@@ -169,55 +162,55 @@ static void print_MP_intsrc_info(struct 
+ 		m->srcbusirq, m->dstapic, m->dstirq);
+ }
+ 
+-static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
++static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
+ {
+ 	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+ 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-		mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+-		(mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+-		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
++		mp_irq->irqtype, mp_irq->irqflag & 3,
++		(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
++		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
+ }
+ 
+ static void __init assign_to_mp_irq(struct mpc_intsrc *m,
+-				    struct mp_config_intsrc *mp_irq)
++				    struct mpc_intsrc *mp_irq)
+ {
+-	mp_irq->mp_dstapic = m->dstapic;
+-	mp_irq->mp_type = m->type;
+-	mp_irq->mp_irqtype = m->irqtype;
+-	mp_irq->mp_irqflag = m->irqflag;
+-	mp_irq->mp_srcbus = m->srcbus;
+-	mp_irq->mp_srcbusirq = m->srcbusirq;
+-	mp_irq->mp_dstirq = m->dstirq;
++	mp_irq->dstapic = m->dstapic;
++	mp_irq->type = m->type;
++	mp_irq->irqtype = m->irqtype;
++	mp_irq->irqflag = m->irqflag;
++	mp_irq->srcbus = m->srcbus;
++	mp_irq->srcbusirq = m->srcbusirq;
++	mp_irq->dstirq = m->dstirq;
+ }
+ 
+-static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
++static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
+ 					struct mpc_intsrc *m)
+ {
+-	m->dstapic = mp_irq->mp_dstapic;
+-	m->type = mp_irq->mp_type;
+-	m->irqtype = mp_irq->mp_irqtype;
+-	m->irqflag = mp_irq->mp_irqflag;
+-	m->srcbus = mp_irq->mp_srcbus;
+-	m->srcbusirq = mp_irq->mp_srcbusirq;
+-	m->dstirq = mp_irq->mp_dstirq;
++	m->dstapic = mp_irq->dstapic;
++	m->type = mp_irq->type;
++	m->irqtype = mp_irq->irqtype;
++	m->irqflag = mp_irq->irqflag;
++	m->srcbus = mp_irq->srcbus;
++	m->srcbusirq = mp_irq->srcbusirq;
++	m->dstirq = mp_irq->dstirq;
+ }
+ 
+-static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
++static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
+ 					struct mpc_intsrc *m)
+ {
+-	if (mp_irq->mp_dstapic != m->dstapic)
++	if (mp_irq->dstapic != m->dstapic)
+ 		return 1;
+-	if (mp_irq->mp_type != m->type)
++	if (mp_irq->type != m->type)
+ 		return 2;
+-	if (mp_irq->mp_irqtype != m->irqtype)
++	if (mp_irq->irqtype != m->irqtype)
+ 		return 3;
+-	if (mp_irq->mp_irqflag != m->irqflag)
++	if (mp_irq->irqflag != m->irqflag)
+ 		return 4;
+-	if (mp_irq->mp_srcbus != m->srcbus)
++	if (mp_irq->srcbus != m->srcbus)
+ 		return 5;
+-	if (mp_irq->mp_srcbusirq != m->srcbusirq)
++	if (mp_irq->srcbusirq != m->srcbusirq)
+ 		return 6;
+-	if (mp_irq->mp_dstirq != m->dstirq)
++	if (mp_irq->dstirq != m->dstirq)
+ 		return 7;
+ 
+ 	return 0;
+@@ -238,8 +231,12 @@ static void __init MP_intsrc_info(struct
+ 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ 		panic("Max # of irq sources exceeded!!\n");
+ }
++#else /* CONFIG_X86_IO_APIC */
++static inline void __init MP_bus_info(struct mpc_bus *m) {}
++static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
++static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
++#endif /* CONFIG_X86_IO_APIC */
+ 
+-#endif
+ 
+ static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
+ {
+@@ -289,6 +286,20 @@ static int __init smp_check_mpc(struct m
+ 	return 1;
+ }
+ 
++static void skip_entry(unsigned char **ptr, int *count, int size)
++{
++	*ptr += size;
++	*count += size;
++}
++
++static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
++{
++	printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
++		"type %x\n", *mpt);
++	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
++			1, mpc, mpc->length, 1);
++}
++
+ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+ {
+ 	char str[16];
+@@ -300,17 +311,8 @@ static int __init smp_read_mpc(struct mp
+ 	if (!smp_check_mpc(mpc, oem, str))
+ 		return 0;
+ 
+-#ifdef CONFIG_X86_32
+-	/*
+-	 * need to make sure summit and es7000's mps_oem_check is safe to be
+-	 * called early via genericarch 's mps_oem_check
+-	 */
+-	if (early) {
+-#ifdef CONFIG_X86_NUMAQ
+-		numaq_mps_oem_check(mpc, oem, str);
+-#endif
+-	} else
+-		mps_oem_check(mpc, oem, str);
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++	generic_mps_oem_check(mpc, oem, str);
+ #endif
+ 	/* save the local APIC address, it might be non-default */
+ 	if (!acpi_lapic)
+@@ -333,61 +335,30 @@ static int __init smp_read_mpc(struct mp
+ 	while (count < mpc->length) {
+ 		switch (*mpt) {
+ 		case MP_PROCESSOR:
+-			{
+-				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
+-				/* ACPI may have already provided this data */
+-				if (!acpi_lapic)
+-					MP_processor_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			/* ACPI may have already provided this data */
++			if (!acpi_lapic)
++				MP_processor_info((struct mpc_cpu *)mpt);
++			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
++			break;
+ 		case MP_BUS:
+-			{
+-				struct mpc_bus *m = (struct mpc_bus *)mpt;
+-#ifdef CONFIG_X86_IO_APIC
+-				MP_bus_info(m);
+-#endif
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			MP_bus_info((struct mpc_bus *)mpt);
++			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
++			break;
+ 		case MP_IOAPIC:
+-			{
+-#ifdef CONFIG_X86_IO_APIC
+-				struct mpc_ioapic *m = (struct mpc_ioapic *)mpt;
+-				MP_ioapic_info(m);
+-#endif
+-				mpt += sizeof(struct mpc_ioapic);
+-				count += sizeof(struct mpc_ioapic);
+-				break;
+-			}
++			MP_ioapic_info((struct mpc_ioapic *)mpt);
++			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
++			break;
+ 		case MP_INTSRC:
+-			{
+-#ifdef CONFIG_X86_IO_APIC
+-				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+-
+-				MP_intsrc_info(m);
+-#endif
+-				mpt += sizeof(struct mpc_intsrc);
+-				count += sizeof(struct mpc_intsrc);
+-				break;
+-			}
++			MP_intsrc_info((struct mpc_intsrc *)mpt);
++			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
++			break;
+ 		case MP_LINTSRC:
+-			{
+-				struct mpc_lintsrc *m =
+-				    (struct mpc_lintsrc *)mpt;
+-				MP_lintsrc_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			MP_lintsrc_info((struct mpc_lintsrc *)mpt);
++			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
++			break;
+ 		default:
+ 			/* wrong mptable */
+-			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+-			printk(KERN_ERR "type %x\n", *mpt);
+-			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+-					1, mpc, mpc->length, 1);
++			smp_dump_mptable(mpc, mpt);
+ 			count = mpc->length;
+ 			break;
+ 		}
+@@ -395,13 +366,13 @@ static int __init smp_read_mpc(struct mp
+ 			(*x86_quirks->mpc_record)++;
+ 	}
+ 
+-#ifdef CONFIG_X86_GENERICARCH
+-       generic_bigsmp_probe();
++#ifdef CONFIG_X86_BIGSMP
++	generic_bigsmp_probe();
+ #endif
+ 
+-#ifdef CONFIG_X86_32
+-	setup_apic_routing();
+-#endif
++	if (apic->setup_apic_routing)
++		apic->setup_apic_routing();
++
+ 	if (!num_processors)
+ 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ 	return num_processors;
+@@ -426,7 +397,7 @@ static void __init construct_default_ioi
+ 	intsrc.type = MP_INTSRC;
+ 	intsrc.irqflag = 0;	/* conforming */
+ 	intsrc.srcbus = 0;
+-	intsrc.dstapic = mp_ioapics[0].mp_apicid;
++	intsrc.dstapic = mp_ioapics[0].apicid;
+ 
+ 	intsrc.irqtype = mp_INT;
+ 
+@@ -579,14 +550,76 @@ static inline void __init construct_defa
+ 	}
+ }
+ 
+-static struct intel_mp_floating *mpf_found;
++static struct mpf_intel *mpf_found;
++
++static unsigned long __init get_mpc_size(unsigned long physptr)
++{
++	struct mpc_table *mpc;
++	unsigned long size;
++
++	mpc = early_ioremap(physptr, PAGE_SIZE);
++	size = mpc->length;
++	early_iounmap(mpc, PAGE_SIZE);
++	apic_printk(APIC_VERBOSE, "  mpc: %lx-%lx\n", physptr, physptr + size);
++
++	return size;
++}
++
++static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
++{
++	struct mpc_table *mpc;
++	unsigned long size;
++
++	size = get_mpc_size(mpf->physptr);
++	mpc = early_ioremap(mpf->physptr, size);
++	/*
++	 * Read the physical hardware table.  Anything here will
++	 * override the defaults.
++	 */
++	if (!smp_read_mpc(mpc, early)) {
++#ifdef CONFIG_X86_LOCAL_APIC
++		smp_found_config = 0;
++#endif
++		printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
++			"... disabling SMP support. (tell your hw vendor)\n");
++		early_iounmap(mpc, size);
++		return -1;
++	}
++	early_iounmap(mpc, size);
++
++	if (early)
++		return -1;
++
++#ifdef CONFIG_X86_IO_APIC
++	/*
++	 * If there are no explicit MP IRQ entries, then we are
++	 * broken.  We set up most of the low 16 IO-APIC pins to
++	 * ISA defaults and hope it will work.
++	 */
++	if (!mp_irq_entries) {
++		struct mpc_bus bus;
++
++		printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
++		       "using default mptable. (tell your hw vendor)\n");
++
++		bus.type = MP_BUS;
++		bus.busid = 0;
++		memcpy(bus.bustype, "ISA   ", 6);
++		MP_bus_info(&bus);
++
++		construct_default_ioirq_mptable(0);
++	}
++#endif
++
++	return 0;
++}
+ 
+ /*
+  * Scan the memory blocks for an SMP configuration block.
+  */
+ static void __init __get_smp_config(unsigned int early)
+ {
+-	struct intel_mp_floating *mpf = mpf_found;
++	struct mpf_intel *mpf = mpf_found;
+ 
+ 	if (!mpf)
+ 		return;
+@@ -607,9 +640,9 @@ static void __init __get_smp_config(unsi
+ 	}
+ 
+ 	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+-	       mpf->mpf_specification);
++	       mpf->specification);
+ #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+-	if (mpf->mpf_feature2 & (1 << 7)) {
++	if (mpf->feature2 & (1 << 7)) {
+ 		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+ 		pic_mode = 1;
+ 	} else {
+@@ -620,7 +653,7 @@ static void __init __get_smp_config(unsi
+ 	/*
+ 	 * Now see if we need to read further.
+ 	 */
+-	if (mpf->mpf_feature1 != 0) {
++	if (mpf->feature1 != 0) {
+ 		if (early) {
+ 			/*
+ 			 * local APIC has default address
+@@ -630,49 +663,12 @@ static void __init __get_smp_config(unsi
+ 		}
+ 
+ 		printk(KERN_INFO "Default MP configuration #%d\n",
+-		       mpf->mpf_feature1);
+-		construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+-	} else if (mpf->mpf_physptr) {
+-
+-		/*
+-		 * Read the physical hardware table.  Anything here will
+-		 * override the defaults.
+-		 */
+-		if (!smp_read_mpc(_bus_to_virt(mpf->mpf_physptr), early)) {
+-#ifdef CONFIG_X86_LOCAL_APIC
+-			smp_found_config = 0;
+-#endif
+-			printk(KERN_ERR
+-			       "BIOS bug, MP table errors detected!...\n");
+-			printk(KERN_ERR "... disabling SMP support. "
+-			       "(tell your hw vendor)\n");
+-			return;
+-		}
++		       mpf->feature1);
++		construct_default_ISA_mptable(mpf->feature1);
+ 
+-		if (early)
++	} else if (mpf->physptr) {
++		if (check_physptr(mpf, early))
+ 			return;
+-#ifdef CONFIG_X86_IO_APIC
+-		/*
+-		 * If there are no explicit MP IRQ entries, then we are
+-		 * broken.  We set up most of the low 16 IO-APIC pins to
+-		 * ISA defaults and hope it will work.
+-		 */
+-		if (!mp_irq_entries) {
+-			struct mpc_bus bus;
+-
+-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
+-			       "using default mptable. "
+-			       "(tell your hw vendor)\n");
+-
+-			bus.type = MP_BUS;
+-			bus.busid = 0;
+-			memcpy(bus.bustype, "ISA   ", 6);
+-			MP_bus_info(&bus);
+-
+-			construct_default_ioirq_mptable(0);
+-		}
+-#endif
+ 	} else
+ 		BUG();
+ 
+@@ -693,58 +689,68 @@ void __init get_smp_config(void)
+ 	__get_smp_config(0);
+ }
+ 
++#ifndef CONFIG_XEN
++static void __init smp_reserve_bootmem(struct mpf_intel *mpf)
++{
++	unsigned long size = get_mpc_size(mpf->physptr);
++#ifdef CONFIG_X86_32
++	/*
++	 * We cannot access to MPC table to compute table size yet,
++	 * as only few megabytes from the bottom is mapped now.
++	 * PC-9800's MPC table places on the very last of physical
++	 * memory; so that simply reserving PAGE_SIZE from mpf->physptr
++	 * yields BUG() in reserve_bootmem.
++	 * also need to make sure physptr is below than max_low_pfn
++	 * we don't need reserve the area above max_low_pfn
++	 */
++	unsigned long end = max_low_pfn * PAGE_SIZE;
++
++	if (mpf->physptr < end) {
++		if (mpf->physptr + size > end)
++			size = end - mpf->physptr;
++		reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
++	}
++#else
++	reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
++#endif
++}
++#endif
++
+ static int __init smp_scan_config(unsigned long base, unsigned long length,
+ 				  unsigned reserve)
+ {
+ 	unsigned int *bp = _bus_to_virt(base);
+-	struct intel_mp_floating *mpf;
++	struct mpf_intel *mpf;
+ 
+ 	apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
+ 			bp, length);
+ 	BUILD_BUG_ON(sizeof(*mpf) != 16);
+ 
+ 	while (length > 0) {
+-		mpf = (struct intel_mp_floating *)bp;
++		mpf = (struct mpf_intel *)bp;
+ 		if ((*bp == SMP_MAGIC_IDENT) &&
+-		    (mpf->mpf_length == 1) &&
++		    (mpf->length == 1) &&
+ 		    !mpf_checksum((unsigned char *)bp, 16) &&
+-		    ((mpf->mpf_specification == 1)
+-		     || (mpf->mpf_specification == 4))) {
++		    ((mpf->specification == 1)
++		     || (mpf->specification == 4))) {
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 			smp_found_config = 1;
+ #endif
+ 			mpf_found = mpf;
+ 
+ #ifndef CONFIG_XEN
+-			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-			       mpf, virt_to_phys(mpf));
++			printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
++			       mpf, (u64)virt_to_phys(mpf));
+ 
+ 			if (!reserve)
+ 				return 1;
+-			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE,
+-					BOOTMEM_DEFAULT);
+-			if (mpf->mpf_physptr) {
+-				unsigned long size = PAGE_SIZE;
+-#ifdef CONFIG_X86_32
+-				/*
+-				 * We cannot access to MPC table to compute
+-				 * table size yet, as only few megabytes from
+-				 * the bottom is mapped now.
+-				 * PC-9800's MPC table places on the very last
+-				 * of physical memory; so that simply reserving
+-				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+-				 * in reserve_bootmem.
+-				 */
+-				unsigned long end = max_low_pfn * PAGE_SIZE;
+-				if (mpf->mpf_physptr + size > end)
+-					size = end - mpf->mpf_physptr;
+-#endif
+-				reserve_bootmem_generic(mpf->mpf_physptr, size,
++			reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf),
+ 						BOOTMEM_DEFAULT);
+-			}
++			if (mpf->physptr)
++				smp_reserve_bootmem(mpf);
+ #else
+ 			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-				mpf, ((void *)bp - _bus_to_virt(base)) + base);
++			       mpf, ((void *)bp - _bus_to_virt(base)) + base);
+ #endif
+ 			return 1;
+ 		}
+@@ -826,15 +832,15 @@ static int  __init get_MP_intsrc_index(s
+ 	/* not legacy */
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		if (mp_irqs[i].mp_irqtype != mp_INT)
++		if (mp_irqs[i].irqtype != mp_INT)
+ 			continue;
+ 
+-		if (mp_irqs[i].mp_irqflag != 0x0f)
++		if (mp_irqs[i].irqflag != 0x0f)
+ 			continue;
+ 
+-		if (mp_irqs[i].mp_srcbus != m->srcbus)
++		if (mp_irqs[i].srcbus != m->srcbus)
+ 			continue;
+-		if (mp_irqs[i].mp_srcbusirq != m->srcbusirq)
++		if (mp_irqs[i].srcbusirq != m->srcbusirq)
+ 			continue;
+ 		if (irq_used[i]) {
+ 			/* already claimed */
+@@ -851,7 +857,58 @@ static int  __init get_MP_intsrc_index(s
+ #define SPARE_SLOT_NUM 20
+ 
+ static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+-#endif
++
++static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
++{
++	int i;
++
++	apic_printk(APIC_VERBOSE, "OLD ");
++	print_MP_intsrc_info(m);
++
++	i = get_MP_intsrc_index(m);
++	if (i > 0) {
++		assign_to_mpc_intsrc(&mp_irqs[i], m);
++		apic_printk(APIC_VERBOSE, "NEW ");
++		print_mp_irq_info(&mp_irqs[i]);
++		return;
++	}
++	if (!i) {
++		/* legacy, do nothing */
++		return;
++	}
++	if (*nr_m_spare < SPARE_SLOT_NUM) {
++		/*
++		 * not found (-1), or duplicated (-2) are invalid entries,
++		 * we need to use the slot later
++		 */
++		m_spare[*nr_m_spare] = m;
++		*nr_m_spare += 1;
++	}
++}
++#else /* CONFIG_X86_IO_APIC */
++static
++inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
++#endif /* CONFIG_X86_IO_APIC */
++
++static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
++		      int count)
++{
++	if (!mpc_new_phys) {
++		pr_info("No spare slots, try to append...take your risk, "
++			"new mpc_length %x\n", count);
++	} else {
++		if (count <= mpc_new_length)
++			pr_info("No spare slots, try to append..., "
++				"new mpc_length %x\n", count);
++		else {
++			pr_err("mpc_new_length %lx is too small\n",
++				mpc_new_length);
++			return -1;
++		}
++	}
++
++	return 0;
++}
+ 
+ static int  __init replace_intsrc_all(struct mpc_table *mpc,
+ 					unsigned long mpc_new_phys,
+@@ -859,77 +916,33 @@ static int  __init replace_intsrc_all(st
+ {
+ #ifdef CONFIG_X86_IO_APIC
+ 	int i;
+-	int nr_m_spare = 0;
+ #endif
+-
+ 	int count = sizeof(*mpc);
++	int nr_m_spare = 0;
+ 	unsigned char *mpt = ((unsigned char *)mpc) + count;
+ 
+ 	printk(KERN_INFO "mpc_length %x\n", mpc->length);
+ 	while (count < mpc->length) {
+ 		switch (*mpt) {
+ 		case MP_PROCESSOR:
+-			{
+-				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
++			break;
+ 		case MP_BUS:
+-			{
+-				struct mpc_bus *m = (struct mpc_bus *)mpt;
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
++			break;
+ 		case MP_IOAPIC:
+-			{
+-				mpt += sizeof(struct mpc_ioapic);
+-				count += sizeof(struct mpc_ioapic);
+-				break;
+-			}
++			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
++			break;
+ 		case MP_INTSRC:
+-			{
+-#ifdef CONFIG_X86_IO_APIC
+-				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+-
+-				apic_printk(APIC_VERBOSE, "OLD ");
+-				print_MP_intsrc_info(m);
+-				i = get_MP_intsrc_index(m);
+-				if (i > 0) {
+-					assign_to_mpc_intsrc(&mp_irqs[i], m);
+-					apic_printk(APIC_VERBOSE, "NEW ");
+-					print_mp_irq_info(&mp_irqs[i]);
+-				} else if (!i) {
+-					/* legacy, do nothing */
+-				} else if (nr_m_spare < SPARE_SLOT_NUM) {
+-					/*
+-					 * not found (-1), or duplicated (-2)
+-					 * are invalid entries,
+-					 * we need to use the slot  later
+-					 */
+-					m_spare[nr_m_spare] = m;
+-					nr_m_spare++;
+-				}
+-#endif
+-				mpt += sizeof(struct mpc_intsrc);
+-				count += sizeof(struct mpc_intsrc);
+-				break;
+-			}
++			check_irq_src((struct mpc_intsrc *)mpt, &nr_m_spare);
++			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
++			break;
+ 		case MP_LINTSRC:
+-			{
+-				struct mpc_lintsrc *m =
+-				    (struct mpc_lintsrc *)mpt;
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
++			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
++			break;
+ 		default:
+ 			/* wrong mptable */
+-			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+-			printk(KERN_ERR "type %x\n", *mpt);
+-			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+-					1, mpc, mpc->length, 1);
++			smp_dump_mptable(mpc, mpt);
+ 			goto out;
+ 		}
+ 	}
+@@ -939,10 +952,10 @@ static int  __init replace_intsrc_all(st
+ 		if (irq_used[i])
+ 			continue;
+ 
+-		if (mp_irqs[i].mp_irqtype != mp_INT)
++		if (mp_irqs[i].irqtype != mp_INT)
+ 			continue;
+ 
+-		if (mp_irqs[i].mp_irqflag != 0x0f)
++		if (mp_irqs[i].irqflag != 0x0f)
+ 			continue;
+ 
+ 		if (nr_m_spare > 0) {
+@@ -953,16 +966,8 @@ static int  __init replace_intsrc_all(st
+ 		} else {
+ 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+ 			count += sizeof(struct mpc_intsrc);
+-			if (!mpc_new_phys) {
+-				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+-			} else {
+-				if (count <= mpc_new_length)
+-					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+-				else {
+-					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+-					goto out;
+-				}
+-			}
++			if (!check_slot(mpc_new_phys, mpc_new_length, count))
++				goto out;
+ 			assign_to_mpc_intsrc(&mp_irqs[i], m);
+ 			mpc->length = count;
+ 			mpt += sizeof(struct mpc_intsrc);
+@@ -1018,7 +1023,7 @@ static int __init update_mp_table(void)
+ {
+ 	char str[16];
+ 	char oem[10];
+-	struct intel_mp_floating *mpf;
++	struct mpf_intel *mpf;
+ 	struct mpc_table *mpc, *mpc_new;
+ 
+ 	if (!enable_update_mptable)
+@@ -1031,19 +1036,19 @@ static int __init update_mp_table(void)
+ 	/*
+ 	 * Now see if we need to go further.
+ 	 */
+-	if (mpf->mpf_feature1 != 0)
++	if (mpf->feature1 != 0)
+ 		return 0;
+ 
+-	if (!mpf->mpf_physptr)
++	if (!mpf->physptr)
+ 		return 0;
+ 
+-	mpc = _bus_to_virt(mpf->mpf_physptr);
++	mpc = _bus_to_virt(mpf->physptr);
+ 
+ 	if (!smp_check_mpc(mpc, oem, str))
+ 		return 0;
+ 
+-	printk(KERN_INFO "mpf: %lx\n", (long)arbitrary_virt_to_machine(mpf));
+-	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
++	printk(KERN_INFO "mpf: %llx\n", (u64)arbitrary_virt_to_machine(mpf));
++	printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+ 
+ 	if (mpc_new_phys && mpc->length > mpc_new_length) {
+ 		mpc_new_phys = 0;
+@@ -1067,23 +1072,23 @@ static int __init update_mp_table(void)
+ 		maddr_t mpc_new_bus;
+ 
+ 		mpc_new_bus = phys_to_machine(mpc_new_phys);
+-		mpf->mpf_physptr = mpc_new_bus;
++		mpf->physptr = mpc_new_bus;
+ 		mpc_new = phys_to_virt(mpc_new_phys);
+ 		memcpy(mpc_new, mpc, mpc->length);
+ 		mpc = mpc_new;
+ 		/* check if we can modify that */
+-		if (mpc_new_bus - mpf->mpf_physptr) {
+-			struct intel_mp_floating *mpf_new;
++		if (mpc_new_bus - mpf->physptr) {
++			struct mpf_intel *mpf_new;
+ 			/* steal 16 bytes from [0, 1k) */
+ 			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ 			mpf_new = isa_bus_to_virt(0x400 - 16);
+ 			memcpy(mpf_new, mpf, 16);
+ 			mpf = mpf_new;
+-			mpf->mpf_physptr = mpc_new_bus;
++			mpf->physptr = mpc_new_bus;
+ 		}
+-		mpf->mpf_checksum = 0;
+-		mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+-		printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
++		mpf->checksum = 0;
++		mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
++		printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+ 	}
+ 
+ 	/*
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,4 +1,5 @@
+ #include <linux/dma-mapping.h>
++#include <linux/dma-debug.h>
+ #include <linux/dmar.h>
+ #include <linux/bootmem.h>
+ #include <linux/pci.h>
+@@ -12,7 +13,7 @@
+ 
+ static int forbid_dac __read_mostly;
+ 
+-struct dma_mapping_ops *dma_ops;
++struct dma_map_ops *dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+ 
+ static int iommu_sac_force __read_mostly;
+@@ -39,11 +40,14 @@ EXPORT_SYMBOL(bad_dma_address);
+    to older i386. */
+ struct device x86_dma_fallback_dev = {
+ 	.init_name = "fallback device",
+-	.coherent_dma_mask = DMA_32BIT_MASK,
++	.coherent_dma_mask = DMA_BIT_MASK(32),
+ 	.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
+ };
+ EXPORT_SYMBOL(x86_dma_fallback_dev);
+ 
++/* Number of entries preallocated for DMA-API debugging */
++#define PREALLOC_DMA_DEBUG_ENTRIES       32768
++
+ int dma_set_mask(struct device *dev, u64 mask)
+ {
+ 	if (!dev->dma_mask || !dma_supported(dev, mask))
+@@ -103,20 +107,20 @@ static void __init dma32_free_bootmem(vo
+ }
+ #endif
+ 
+-static struct dma_mapping_ops swiotlb_dma_ops = {
++static struct dma_map_ops swiotlb_dma_ops = {
+ 	.alloc_coherent = dma_generic_alloc_coherent,
+ 	.free_coherent = dma_generic_free_coherent,
+ 	.mapping_error = swiotlb_dma_mapping_error,
+-	.map_single = swiotlb_map_single_phys,
+-	.unmap_single = swiotlb_unmap_single,
++	.map_page = swiotlb_map_page,
++	.unmap_page = swiotlb_unmap_page,
+ 	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ 	.sync_single_for_device = swiotlb_sync_single_for_device,
+ 	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+ 	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+ 	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ 	.sync_sg_for_device = swiotlb_sync_sg_for_device,
+-	.map_sg = swiotlb_map_sg,
+-	.unmap_sg = swiotlb_unmap_sg,
++	.map_sg = swiotlb_map_sg_attrs,
++	.unmap_sg = swiotlb_unmap_sg_attrs,
+ 	.dma_supported = swiotlb_dma_supported
+ };
+ 
+@@ -175,7 +179,7 @@ again:
+ 	if (!is_buffer_dma_capable(dma_mask, addr, size)) {
+ 		__free_pages(page, order);
+ 
+-		if (dma_mask < DMA_32BIT_MASK && !(flag & GFP_DMA)) {
++		if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
+ 			flag = (flag & ~GFP_DMA32) | GFP_DMA;
+ 			goto again;
+ 		}
+@@ -305,7 +309,7 @@ int range_straddles_page_boundary(paddr_
+ 
+ int dma_supported(struct device *dev, u64 mask)
+ {
+-	struct dma_mapping_ops *ops = get_dma_ops(dev);
++	struct dma_map_ops *ops = get_dma_ops(dev);
+ 
+ #ifdef CONFIG_PCI
+ 	if (mask > 0xffffffff && forbid_dac > 0) {
+@@ -320,7 +324,7 @@ int dma_supported(struct device *dev, u6
+ 	/* Copied from i386. Doesn't make much sense, because it will
+ 	   only work for pci_alloc_coherent.
+ 	   The caller just has to use GFP_DMA in this case. */
+-	if (mask < DMA_24BIT_MASK)
++	if (mask < DMA_BIT_MASK(24))
+ 		return 0;
+ 
+ 	/* Tell the device to use SAC when IOMMU force is on.  This
+@@ -335,7 +339,7 @@ int dma_supported(struct device *dev, u6
+ 	   SAC for these.  Assume all masks <= 40 bits are of this
+ 	   type. Normally this doesn't make any difference, but gives
+ 	   more gentle handling of IOMMU overflow. */
+-	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
++	if (iommu_sac_force && (mask >= DMA_BIT_MASK(40))) {
+ 		dev_info(dev, "Force SAC with mask %Lx\n", mask);
+ 		return 0;
+ 	}
+@@ -346,6 +350,12 @@ EXPORT_SYMBOL(dma_supported);
+ 
+ static int __init pci_iommu_init(void)
+ {
++	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
++
++#ifdef CONFIG_PCI
++	dma_debug_add_bus(&pci_bus_type);
++#endif
++
+ 	calgary_iommu_init();
+ 
+ 	intel_iommu_init();
+@@ -371,8 +381,7 @@ fs_initcall(pci_iommu_init);
+ static __devinit void via_no_dac(struct pci_dev *dev)
+ {
+ 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+-		printk(KERN_INFO
+-			"PCI: VIA PCI bridge detected. Disabling DAC.\n");
++		dev_info(&dev->dev, "disabling DAC on VIA PCI bridge\n");
+ 		forbid_dac = 1;
+ 	}
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -24,7 +24,7 @@ do {							\
+ 
+ static int
+ gnttab_map_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+-	      int direction)
++	      enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+ 	unsigned int i;
+ 	struct scatterlist *sg;
+@@ -48,7 +48,7 @@ gnttab_map_sg(struct device *hwdev, stru
+ 
+ static void
+ gnttab_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+-		int direction)
++		enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+ 	unsigned int i;
+ 	struct scatterlist *sg;
+@@ -58,36 +58,36 @@ gnttab_unmap_sg(struct device *hwdev, st
+ }
+ 
+ static dma_addr_t
+-gnttab_map_single(struct device *dev, phys_addr_t paddr, size_t size,
+-		  int direction)
++gnttab_map_page(struct device *dev, struct page *page, unsigned long offset,
++		size_t size, enum dma_data_direction dir,
++		struct dma_attrs *attrs)
+ {
+ 	dma_addr_t dma;
+ 
+ 	WARN_ON(size == 0);
+ 
+-	dma = gnttab_dma_map_page(pfn_to_page(paddr >> PAGE_SHIFT)) +
+-	      offset_in_page(paddr);
+-	IOMMU_BUG_ON(range_straddles_page_boundary(paddr, size));
++	dma = gnttab_dma_map_page(page) + offset;
++	IOMMU_BUG_ON(range_straddles_page_boundary(offset, size));
+ 	IOMMU_BUG_ON(address_needs_mapping(dev, dma, size));
+ 
+ 	return dma;
+ }
+ 
+ static void
+-gnttab_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+-		    int direction)
++gnttab_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
++		  enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+ 	gnttab_dma_unmap_page(dma_addr);
+ }
+ 
+-struct dma_mapping_ops nommu_dma_ops = {
+-	.alloc_coherent = dma_generic_alloc_coherent,
+-	.free_coherent = dma_generic_free_coherent,
+-	.map_single = gnttab_map_single,
+-	.unmap_single = gnttab_unmap_single,
+-	.map_sg = gnttab_map_sg,
+-	.unmap_sg = gnttab_unmap_sg,
+-	.dma_supported = swiotlb_dma_supported,
++struct dma_map_ops nommu_dma_ops = {
++	.alloc_coherent	= dma_generic_alloc_coherent,
++	.free_coherent	= dma_generic_free_coherent,
++	.map_page	= gnttab_map_page,
++	.unmap_page	= gnttab_unmap_page,
++	.map_sg		= gnttab_map_sg,
++	.unmap_sg	= gnttab_unmap_sg,
++	.dma_supported	= swiotlb_dma_supported,
+ };
+ 
+ void __init no_iommu_init(void)
+--- head-2010-01-18.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,16 +1,19 @@
+ #include <linux/errno.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+-#include <asm/idle.h>
+ #include <linux/smp.h>
++#include <linux/prctl.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
+ #include <linux/clockchips.h>
+-#include <linux/ftrace.h>
++#include <trace/power.h>
+ #include <asm/system.h>
+ #include <asm/apic.h>
++#include <asm/idle.h>
++#include <asm/uaccess.h>
++#include <asm/i387.h>
+ #include <xen/evtchn.h>
+ 
+ unsigned long idle_halt;
+@@ -20,6 +23,9 @@ EXPORT_SYMBOL(idle_nomwait);
+ 
+ struct kmem_cache *task_xstate_cachep;
+ 
++DEFINE_TRACE(power_start);
++DEFINE_TRACE(power_end);
++
+ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+ {
+ 	*dst = *src;
+@@ -57,6 +63,179 @@ void arch_task_cache_init(void)
+ }
+ 
+ /*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++	struct task_struct *me = current;
++	struct thread_struct *t = &me->thread;
++	unsigned long *bp = t->io_bitmap_ptr;
++
++	if (bp) {
++		struct physdev_set_iobitmap set_iobitmap;
++
++		t->io_bitmap_ptr = NULL;
++		clear_thread_flag(TIF_IO_BITMAP);
++		/*
++		 * Careful, clear this in the TSS too:
++		 */
++		memset(&set_iobitmap, 0, sizeof(set_iobitmap));
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &set_iobitmap));
++		t->io_bitmap_max = 0;
++		kfree(bp);
++	}
++
++	ds_exit_thread(current);
++}
++
++void flush_thread(void)
++{
++	struct task_struct *tsk = current;
++
++#ifdef CONFIG_X86_64
++	if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
++		clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
++		if (test_tsk_thread_flag(tsk, TIF_IA32)) {
++			clear_tsk_thread_flag(tsk, TIF_IA32);
++		} else {
++			set_tsk_thread_flag(tsk, TIF_IA32);
++			current_thread_info()->status |= TS_COMPAT;
++		}
++	}
++#endif
++
++	clear_tsk_thread_flag(tsk, TIF_DEBUG);
++
++	tsk->thread.debugreg0 = 0;
++	tsk->thread.debugreg1 = 0;
++	tsk->thread.debugreg2 = 0;
++	tsk->thread.debugreg3 = 0;
++	tsk->thread.debugreg6 = 0;
++	tsk->thread.debugreg7 = 0;
++	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
++	/*
++	 * Forget coprocessor state..
++	 */
++	tsk->fpu_counter = 0;
++	clear_fpu(tsk);
++	clear_used_math();
++}
++
++static void hard_disable_TSC(void)
++{
++	write_cr4(read_cr4() | X86_CR4_TSD);
++}
++
++void disable_TSC(void)
++{
++	preempt_disable();
++	if (!test_and_set_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_disable_TSC();
++	preempt_enable();
++}
++
++static void hard_enable_TSC(void)
++{
++	write_cr4(read_cr4() & ~X86_CR4_TSD);
++}
++
++static void enable_TSC(void)
++{
++	preempt_disable();
++	if (test_and_clear_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_enable_TSC();
++	preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++	unsigned int val;
++
++	if (test_thread_flag(TIF_NOTSC))
++		val = PR_TSC_SIGSEGV;
++	else
++		val = PR_TSC_ENABLE;
++
++	return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++	if (val == PR_TSC_SIGSEGV)
++		disable_TSC();
++	else if (val == PR_TSC_ENABLE)
++		enable_TSC();
++	else
++		return -EINVAL;
++
++	return 0;
++}
++
++void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
++{
++	struct thread_struct *prev, *next;
++
++	prev = &prev_p->thread;
++	next = &next_p->thread;
++
++	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
++	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
++		ds_switch_to(prev_p, next_p);
++	else if (next->debugctlmsr != prev->debugctlmsr)
++		update_debugctlmsr(next->debugctlmsr);
++
++	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
++		set_debugreg(next->debugreg0, 0);
++		set_debugreg(next->debugreg1, 1);
++		set_debugreg(next->debugreg2, 2);
++		set_debugreg(next->debugreg3, 3);
++		/* no 4 and 5 */
++		set_debugreg(next->debugreg6, 6);
++		set_debugreg(next->debugreg7, 7);
++	}
++
++	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
++	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
++		/* prev and next are different */
++		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
++			hard_disable_TSC();
++		else
++			hard_enable_TSC();
++	}
++}
++
++int sys_fork(struct pt_regs *regs)
++{
++	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
++}
++
++/*
++ * This is trivial, and on the face of it looks like it
++ * could equally well be done in user mode.
++ *
++ * Not so, for quite unobvious reasons - register pressure.
++ * In user mode vfork() cannot have a stack frame, and if
++ * done by calling the "clone()" system call directly, you
++ * do not have enough call-clobbered registers to hold all
++ * the information you need.
++ */
++int sys_vfork(struct pt_regs *regs)
++{
++	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
++		       NULL, NULL);
++}
++
++
++/*
+  * Idle related variables and functions
+  */
+ unsigned long boot_option_idle_override = 0;
+@@ -130,7 +309,7 @@ void stop_this_cpu(void *dummy)
+ 	/*
+ 	 * Remove this CPU:
+ 	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
++	set_cpu_online(smp_processor_id(), false);
+ 	disable_all_local_evtchn();
+ 
+ 	for (;;) {
+@@ -283,12 +462,13 @@ static int __cpuinit check_c1e_idle(cons
+ 	return 1;
+ }
+ 
+-static cpumask_t c1e_mask = CPU_MASK_NONE;
++static cpumask_var_t c1e_mask;
+ static int c1e_detected;
+ 
+ void c1e_remove_cpu(int cpu)
+ {
+-	cpu_clear(cpu, c1e_mask);
++	if (c1e_mask != NULL)
++		cpumask_clear_cpu(cpu, c1e_mask);
+ }
+ 
+ /*
+@@ -317,8 +497,8 @@ static void c1e_idle(void)
+ 	if (c1e_detected) {
+ 		int cpu = smp_processor_id();
+ 
+-		if (!cpu_isset(cpu, c1e_mask)) {
+-			cpu_set(cpu, c1e_mask);
++		if (!cpumask_test_cpu(cpu, c1e_mask)) {
++			cpumask_set_cpu(cpu, c1e_mask);
+ 			/*
+ 			 * Force broadcast so ACPI can not interfere. Needs
+ 			 * to run with interrupts enabled as it uses
+@@ -350,7 +530,7 @@ static void c1e_idle(void)
+ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+ {
+ #ifndef CONFIG_XEN
+-#ifdef CONFIG_X86_SMP
++#ifdef CONFIG_SMP
+ 	if (pm_idle == poll_idle && smp_num_siblings > 1) {
+ 		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+ 			" performance may degrade.\n");
+@@ -373,6 +553,17 @@ void __cpuinit select_idle_routine(const
+ #endif
+ }
+ 
++void __init init_c1e_mask(void)
++{
++#ifndef CONFIG_XEN
++	/* If we're using c1e_idle, we need to allocate c1e_mask. */
++	if (pm_idle == c1e_idle) {
++		alloc_cpumask_var(&c1e_mask, GFP_KERNEL);
++		cpumask_clear(c1e_mask);
++	}
++#endif
++}
++
+ static int __init idle_setup(char *str)
+ {
+ 	if (!str)
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -11,6 +11,7 @@
+ 
+ #include <stdarg.h>
+ 
++#include <linux/stackprotector.h>
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+@@ -71,9 +72,6 @@ asmlinkage void cstar_ret_from_fork(void
+ DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+ EXPORT_PER_CPU_SYMBOL(current_task);
+ 
+-DEFINE_PER_CPU(int, cpu_number);
+-EXPORT_PER_CPU_SYMBOL(cpu_number);
+-
+ /*
+  * Return saved PC of a blocked thread.
+  */
+@@ -99,6 +97,15 @@ void cpu_idle(void)
+ {
+ 	int cpu = smp_processor_id();
+ 
++	/*
++	 * If we're the non-boot CPU, nothing set the stack canary up
++	 * for us.  CPU0 already has it initialized but no harm in
++	 * doing it again.  This is a good place for updating it, as
++	 * we wont ever return from this function (so the invalid
++	 * canaries already on the stack wont ever trigger).
++	 */
++	boot_init_stack_canary();
++
+ 	current_thread_info()->status |= TS_POLLING;
+ 
+ 	/* endless idle loop with no priority at all */
+@@ -113,7 +120,6 @@ void cpu_idle(void)
+ 				play_dead();
+ 
+ 			local_irq_disable();
+-			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
+ 			/* Don't trace irqs off for idle */
+ 			stop_critical_timings();
+ 			xen_idle();
+@@ -137,7 +143,7 @@ void __show_regs(struct pt_regs *regs, i
+ 	if (user_mode_vm(regs)) {
+ 		sp = regs->sp;
+ 		ss = regs->ss & 0xffff;
+-		savesegment(gs, gs);
++		gs = get_user_gs(regs);
+ 	} else {
+ 		sp = (unsigned long) (&regs->sp);
+ 		savesegment(ss, ss);
+@@ -218,6 +224,7 @@ int kernel_thread(int (*fn)(void *), voi
+ 	regs.ds = __USER_DS;
+ 	regs.es = __USER_DS;
+ 	regs.fs = __KERNEL_PERCPU;
++	regs.gs = __KERNEL_STACK_CANARY;
+ 	regs.orig_ax = -1;
+ 	regs.ip = (unsigned long) kernel_thread_helper;
+ 	regs.cs = __KERNEL_CS | get_kernel_rpl();
+@@ -228,47 +235,6 @@ int kernel_thread(int (*fn)(void *), voi
+ }
+ EXPORT_SYMBOL(kernel_thread);
+ 
+-/*
+- * Free current thread data structures etc..
+- */
+-void exit_thread(void)
+-{
+-	/* The process may have allocated an io port bitmap... nuke it. */
+-	if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
+-		struct task_struct *tsk = current;
+-		struct thread_struct *t = &tsk->thread;
+-		struct physdev_set_iobitmap set_iobitmap;
+-		memset(&set_iobitmap, 0, sizeof(set_iobitmap));
+-		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+-					      &set_iobitmap));
+-		kfree(t->io_bitmap_ptr);
+-		t->io_bitmap_ptr = NULL;
+-		clear_thread_flag(TIF_IO_BITMAP);
+-	}
+-
+-	ds_exit_thread(current);
+-}
+-
+-void flush_thread(void)
+-{
+-	struct task_struct *tsk = current;
+-
+-	tsk->thread.debugreg0 = 0;
+-	tsk->thread.debugreg1 = 0;
+-	tsk->thread.debugreg2 = 0;
+-	tsk->thread.debugreg3 = 0;
+-	tsk->thread.debugreg6 = 0;
+-	tsk->thread.debugreg7 = 0;
+-	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+-	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+-	/*
+-	 * Forget coprocessor state..
+-	 */
+-	tsk->fpu_counter = 0;
+-	clear_fpu(tsk);
+-	clear_used_math();
+-}
+-
+ void release_thread(struct task_struct *dead_task)
+ {
+ 	BUG_ON(dead_task->mm);
+@@ -284,7 +250,7 @@ void prepare_to_copy(struct task_struct 
+ 	unlazy_fpu(tsk);
+ }
+ 
+-int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
++int copy_thread(unsigned long clone_flags, unsigned long sp,
+ 	unsigned long unused,
+ 	struct task_struct *p, struct pt_regs *regs)
+ {
+@@ -302,7 +268,7 @@ int copy_thread(int nr, unsigned long cl
+ 
+ 	p->thread.ip = (unsigned long) ret_from_fork;
+ 
+-	savesegment(gs, p->thread.gs);
++	task_user_gs(p) = get_user_gs(regs);
+ 
+ 	tsk = current;
+ 	if (test_tsk_thread_flag(tsk, TIF_CSTAR))
+@@ -344,7 +310,7 @@ int copy_thread(int nr, unsigned long cl
+ void
+ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+ {
+-	__asm__("movl %0, %%gs" : : "r"(0));
++	set_user_gs(regs, 0);
+ 	regs->fs		= 0;
+ 	set_fs(USER_DS);
+ 	regs->ds		= __USER_DS;
+@@ -360,98 +326,6 @@ start_thread(struct pt_regs *regs, unsig
+ }
+ EXPORT_SYMBOL_GPL(start_thread);
+ 
+-static void hard_disable_TSC(void)
+-{
+-	write_cr4(read_cr4() | X86_CR4_TSD);
+-}
+-
+-void disable_TSC(void)
+-{
+-	preempt_disable();
+-	if (!test_and_set_thread_flag(TIF_NOTSC))
+-		/*
+-		 * Must flip the CPU state synchronously with
+-		 * TIF_NOTSC in the current running context.
+-		 */
+-		hard_disable_TSC();
+-	preempt_enable();
+-}
+-
+-static void hard_enable_TSC(void)
+-{
+-	write_cr4(read_cr4() & ~X86_CR4_TSD);
+-}
+-
+-static void enable_TSC(void)
+-{
+-	preempt_disable();
+-	if (test_and_clear_thread_flag(TIF_NOTSC))
+-		/*
+-		 * Must flip the CPU state synchronously with
+-		 * TIF_NOTSC in the current running context.
+-		 */
+-		hard_enable_TSC();
+-	preempt_enable();
+-}
+-
+-int get_tsc_mode(unsigned long adr)
+-{
+-	unsigned int val;
+-
+-	if (test_thread_flag(TIF_NOTSC))
+-		val = PR_TSC_SIGSEGV;
+-	else
+-		val = PR_TSC_ENABLE;
+-
+-	return put_user(val, (unsigned int __user *)adr);
+-}
+-
+-int set_tsc_mode(unsigned int val)
+-{
+-	if (val == PR_TSC_SIGSEGV)
+-		disable_TSC();
+-	else if (val == PR_TSC_ENABLE)
+-		enable_TSC();
+-	else
+-		return -EINVAL;
+-
+-	return 0;
+-}
+-
+-static noinline void
+-__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+-{
+-	struct thread_struct *prev, *next;
+-
+-	prev = &prev_p->thread;
+-	next = &next_p->thread;
+-
+-	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
+-	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
+-		ds_switch_to(prev_p, next_p);
+-	else if (next->debugctlmsr != prev->debugctlmsr)
+-		update_debugctlmsr(next->debugctlmsr);
+-
+-	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+-		set_debugreg(next->debugreg0, 0);
+-		set_debugreg(next->debugreg1, 1);
+-		set_debugreg(next->debugreg2, 2);
+-		set_debugreg(next->debugreg3, 3);
+-		/* no 4 and 5 */
+-		set_debugreg(next->debugreg6, 6);
+-		set_debugreg(next->debugreg7, 7);
+-	}
+-
+-	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+-	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+-		/* prev and next are different */
+-		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+-			hard_disable_TSC();
+-		else
+-			hard_enable_TSC();
+-	}
+-}
+-
+ /*
+  *	switch_to(x,yn) should switch tasks from x to y.
+  *
+@@ -532,7 +406,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
+ 		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
+ 		mcl->op = __HYPERVISOR_update_descriptor;		\
+-		*(u64 *)&mcl->args[0] =	virt_to_machine(		\
++		*(u64 *)&mcl->args[0] =	arbitrary_virt_to_machine(	\
+ 			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
+ 		*(u64 *)&mcl->args[2] = *(u64 *)&next->tls_array[i];	\
+ 		mcl++;							\
+@@ -612,64 +486,44 @@ __switch_to(struct task_struct *prev_p, 
+ 	 * Restore %gs if needed (which is common)
+ 	 */
+ 	if (prev->gs | next->gs)
+-		loadsegment(gs, next->gs);
++		lazy_load_gs(next->gs);
+ 
+-	x86_write_percpu(current_task, next_p);
++	percpu_write(current_task, next_p);
+ 
+ 	return prev_p;
+ }
+ 
+-asmlinkage int sys_fork(struct pt_regs regs)
+-{
+-	return do_fork(SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
+-}
+-
+-asmlinkage int sys_clone(struct pt_regs regs)
++int sys_clone(struct pt_regs *regs)
+ {
+ 	unsigned long clone_flags;
+ 	unsigned long newsp;
+ 	int __user *parent_tidptr, *child_tidptr;
+ 
+-	clone_flags = regs.bx;
+-	newsp = regs.cx;
+-	parent_tidptr = (int __user *)regs.dx;
+-	child_tidptr = (int __user *)regs.di;
++	clone_flags = regs->bx;
++	newsp = regs->cx;
++	parent_tidptr = (int __user *)regs->dx;
++	child_tidptr = (int __user *)regs->di;
+ 	if (!newsp)
+-		newsp = regs.sp;
+-	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
+-}
+-
+-/*
+- * This is trivial, and on the face of it looks like it
+- * could equally well be done in user mode.
+- *
+- * Not so, for quite unobvious reasons - register pressure.
+- * In user mode vfork() cannot have a stack frame, and if
+- * done by calling the "clone()" system call directly, you
+- * do not have enough call-clobbered registers to hold all
+- * the information you need.
+- */
+-asmlinkage int sys_vfork(struct pt_regs regs)
+-{
+-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
++		newsp = regs->sp;
++	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
+ }
+ 
+ /*
+  * sys_execve() executes a new program.
+  */
+-asmlinkage int sys_execve(struct pt_regs regs)
++int sys_execve(struct pt_regs *regs)
+ {
+ 	int error;
+ 	char *filename;
+ 
+-	filename = getname((char __user *) regs.bx);
++	filename = getname((char __user *) regs->bx);
+ 	error = PTR_ERR(filename);
+ 	if (IS_ERR(filename))
+ 		goto out;
+ 	error = do_execve(filename,
+-			(char __user * __user *) regs.cx,
+-			(char __user * __user *) regs.dx,
+-			&regs);
++			(char __user * __user *) regs->cx,
++			(char __user * __user *) regs->dx,
++			regs);
+ 	if (error == 0) {
+ 		/* Make sure we don't return using sysenter.. */
+ 		set_thread_flag(TIF_IRET);
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -19,6 +19,7 @@
+ 
+ #include <stdarg.h>
+ 
++#include <linux/stackprotector.h>
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+@@ -50,7 +51,6 @@
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/mmu_context.h>
+-#include <asm/pda.h>
+ #include <asm/prctl.h>
+ #include <xen/interface/platform.h>
+ #include <xen/interface/physdev.h>
+@@ -67,6 +67,12 @@
+ 
+ asmlinkage extern void ret_from_fork(void);
+ 
++DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
++EXPORT_PER_CPU_SYMBOL(current_task);
++
++DEFINE_PER_CPU(unsigned long, old_rsp);
++static DEFINE_PER_CPU(unsigned char, is_idle);
++
+ unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
+ 
+ static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+@@ -85,13 +91,13 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregist
+ 
+ void enter_idle(void)
+ {
+-	write_pda(isidle, 1);
++	percpu_write(is_idle, 1);
+ 	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ }
+ 
+ static void __exit_idle(void)
+ {
+-	if (test_and_clear_bit_pda(0, isidle) == 0)
++	if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
+ 		return;
+ 	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ }
+@@ -121,6 +127,16 @@ static inline void play_dead(void)
+ void cpu_idle(void)
+ {
+ 	current_thread_info()->status |= TS_POLLING;
++
++	/*
++	 * If we're the non-boot CPU, nothing set the stack canary up
++	 * for us.  CPU0 already has it initialized but no harm in
++	 * doing it again.  This is a good place for updating it, as
++	 * we wont ever return from this function (so the invalid
++	 * canaries already on the stack wont ever trigger).
++	 */
++	boot_init_stack_canary();
++
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
+ 		tick_nohz_stop_sched_tick(1);
+@@ -230,78 +246,11 @@ void show_regs(struct pt_regs *regs)
+ 	show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
+ }
+ 
+-/*
+- * Free current thread data structures etc..
+- */
+-void exit_thread(void)
+-{
+-	struct task_struct *me = current;
+-	struct thread_struct *t = &me->thread;
+-
+-	if (me->thread.io_bitmap_ptr) {
+-#ifndef CONFIG_X86_NO_TSS
+-		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
+-#endif
+-#ifdef CONFIG_XEN
+-		struct physdev_set_iobitmap iobmp_op;
+-		memset(&iobmp_op, 0, sizeof(iobmp_op));
+-#endif
+-
+-		kfree(t->io_bitmap_ptr);
+-		t->io_bitmap_ptr = NULL;
+-		clear_thread_flag(TIF_IO_BITMAP);
+-		/*
+-		 * Careful, clear this in the TSS too:
+-		 */
+-#ifndef CONFIG_X86_NO_TSS
+-		memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
+-		put_cpu();
+-#endif
+-#ifdef CONFIG_XEN
+-		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+-					      &iobmp_op));
+-#endif
+-		t->io_bitmap_max = 0;
+-	}
+-
+-	ds_exit_thread(current);
+-}
+-
+ void xen_load_gs_index(unsigned gs)
+ {
+ 	WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gs));
+ }
+ 
+-void flush_thread(void)
+-{
+-	struct task_struct *tsk = current;
+-
+-	if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
+-		clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
+-		if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+-			clear_tsk_thread_flag(tsk, TIF_IA32);
+-		} else {
+-			set_tsk_thread_flag(tsk, TIF_IA32);
+-			current_thread_info()->status |= TS_COMPAT;
+-		}
+-	}
+-	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+-
+-	tsk->thread.debugreg0 = 0;
+-	tsk->thread.debugreg1 = 0;
+-	tsk->thread.debugreg2 = 0;
+-	tsk->thread.debugreg3 = 0;
+-	tsk->thread.debugreg6 = 0;
+-	tsk->thread.debugreg7 = 0;
+-	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+-	/*
+-	 * Forget coprocessor state..
+-	 */
+-	tsk->fpu_counter = 0;
+-	clear_fpu(tsk);
+-	clear_used_math();
+-}
+-
+ void release_thread(struct task_struct *dead_task)
+ {
+ 	if (dead_task->mm) {
+@@ -343,7 +292,7 @@ void prepare_to_copy(struct task_struct 
+ 	unlazy_fpu(tsk);
+ }
+ 
+-int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
++int copy_thread(unsigned long clone_flags, unsigned long sp,
+ 		unsigned long unused,
+ 	struct task_struct *p, struct pt_regs *regs)
+ {
+@@ -424,7 +373,7 @@ start_thread(struct pt_regs *regs, unsig
+ 	load_gs_index(0);
+ 	regs->ip		= new_ip;
+ 	regs->sp		= new_sp;
+-	write_pda(oldrsp, new_sp);
++	percpu_write(old_rsp, new_sp);
+ 	regs->cs		= __USER_CS;
+ 	regs->ss		= __USER_DS;
+ 	regs->flags		= 0x200;
+@@ -436,103 +385,6 @@ start_thread(struct pt_regs *regs, unsig
+ }
+ EXPORT_SYMBOL_GPL(start_thread);
+ 
+-static void hard_disable_TSC(void)
+-{
+-	write_cr4(read_cr4() | X86_CR4_TSD);
+-}
+-
+-void disable_TSC(void)
+-{
+-	preempt_disable();
+-	if (!test_and_set_thread_flag(TIF_NOTSC))
+-		/*
+-		 * Must flip the CPU state synchronously with
+-		 * TIF_NOTSC in the current running context.
+-		 */
+-		hard_disable_TSC();
+-	preempt_enable();
+-}
+-
+-static void hard_enable_TSC(void)
+-{
+-	write_cr4(read_cr4() & ~X86_CR4_TSD);
+-}
+-
+-static void enable_TSC(void)
+-{
+-	preempt_disable();
+-	if (test_and_clear_thread_flag(TIF_NOTSC))
+-		/*
+-		 * Must flip the CPU state synchronously with
+-		 * TIF_NOTSC in the current running context.
+-		 */
+-		hard_enable_TSC();
+-	preempt_enable();
+-}
+-
+-int get_tsc_mode(unsigned long adr)
+-{
+-	unsigned int val;
+-
+-	if (test_thread_flag(TIF_NOTSC))
+-		val = PR_TSC_SIGSEGV;
+-	else
+-		val = PR_TSC_ENABLE;
+-
+-	return put_user(val, (unsigned int __user *)adr);
+-}
+-
+-int set_tsc_mode(unsigned int val)
+-{
+-	if (val == PR_TSC_SIGSEGV)
+-		disable_TSC();
+-	else if (val == PR_TSC_ENABLE)
+-		enable_TSC();
+-	else
+-		return -EINVAL;
+-
+-	return 0;
+-}
+-
+-/*
+- * This special macro can be used to load a debugging register
+- */
+-#define loaddebug(thread, r) set_debugreg(thread->debugreg ## r, r)
+-
+-static inline void __switch_to_xtra(struct task_struct *prev_p,
+-				    struct task_struct *next_p)
+-{
+-	struct thread_struct *prev, *next;
+-
+-	prev = &prev_p->thread,
+-	next = &next_p->thread;
+-
+-	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
+-	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
+-		ds_switch_to(prev_p, next_p);
+-	else if (next->debugctlmsr != prev->debugctlmsr)
+-		update_debugctlmsr(next->debugctlmsr);
+-
+-	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+-		loaddebug(next, 0);
+-		loaddebug(next, 1);
+-		loaddebug(next, 2);
+-		loaddebug(next, 3);
+-		/* no 4 and 5 */
+-		loaddebug(next, 6);
+-		loaddebug(next, 7);
+-	}
+-
+-	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+-	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+-		/* prev and next are different */
+-		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+-			hard_disable_TSC();
+-		else
+-			hard_enable_TSC();
+-	}
+-}
+-
+ /*
+  *	switch_to(x,y) should switch tasks from x to y.
+  *
+@@ -598,7 +450,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
+ 		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
+ 		mcl->op      = __HYPERVISOR_update_descriptor;		\
+-		mcl->args[0] = virt_to_machine(				\
++		mcl->args[0] = arbitrary_virt_to_machine(		\
+ 			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
+ 		mcl->args[1] = *(u64 *)&next->tls_array[i];		\
+ 		mcl++;							\
+@@ -685,21 +537,13 @@ __switch_to(struct task_struct *prev_p, 
+ 	/*
+ 	 * Switch the PDA context.
+ 	 */
+-	prev->usersp = read_pda(oldrsp);
+-	write_pda(oldrsp, next->usersp);
+-	write_pda(pcurrent, next_p);
+-	write_pda(kernelstack,
+-		  (unsigned long)task_stack_page(next_p) +
+-		  THREAD_SIZE - PDA_STACKOFFSET);
+-#ifdef CONFIG_CC_STACKPROTECTOR
+-	write_pda(stack_canary, next_p->stack_canary);
++	prev->usersp = percpu_read(old_rsp);
++	percpu_write(old_rsp, next->usersp);
++	percpu_write(current_task, next_p);
+ 
+-	/*
+-	 * Build time only check to make sure the stack_canary is at
+-	 * offset 40 in the pda; this is a gcc ABI requirement
+-	 */
+-	BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40);
+-#endif
++	percpu_write(kernel_stack,
++		  (unsigned long)task_stack_page(next_p) +
++		  THREAD_SIZE - KERNEL_STACK_OFFSET);
+ 
+ 	/*
+ 	 * Now maybe reload the debug registers
+@@ -753,11 +597,6 @@ void set_personality_64bit(void)
+ 	current->personality &= ~READ_IMPLIES_EXEC;
+ }
+ 
+-asmlinkage long sys_fork(struct pt_regs *regs)
+-{
+-	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+-}
+-
+ asmlinkage long
+ sys_clone(unsigned long clone_flags, unsigned long newsp,
+ 	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
+@@ -767,22 +606,6 @@ sys_clone(unsigned long clone_flags, uns
+ 	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+ }
+ 
+-/*
+- * This is trivial, and on the face of it looks like it
+- * could equally well be done in user mode.
+- *
+- * Not so, for quite unobvious reasons - register pressure.
+- * In user mode vfork() cannot have a stack frame, and if
+- * done by calling the "clone()" system call directly, you
+- * do not have enough call-clobbered registers to hold all
+- * the information you need.
+- */
+-asmlinkage long sys_vfork(struct pt_regs *regs)
+-{
+-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
+-		    NULL, NULL);
+-}
+-
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ 	unsigned long stack;
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -75,8 +75,7 @@ static void ich_force_hpet_resume(void)
+ 	if (!force_hpet_address)
+ 		return;
+ 
+-	if (rcba_base == NULL)
+-		BUG();
++	BUG_ON(rcba_base == NULL);
+ 
+ 	/* read the Function Disable register, dword mode only */
+ 	val = readl(rcba_base + 0x3404);
+@@ -173,7 +172,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
+ 			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
+ 			 ich_force_enable_hpet);
+-
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x3a16,	/* ICH10 */
++			 ich_force_enable_hpet);
+ 
+ static struct pci_dev *cached_dev;
+ 
+@@ -262,8 +262,6 @@ static void old_ich_force_enable_hpet_us
+ {
+ 	if (hpet_force_user)
+ 		old_ich_force_enable_hpet(dev);
+-	else
+-		hpet_print_force_info();
+ }
+ 
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
+--- head-2010-01-18.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -74,14 +74,15 @@
+ #include <asm/e820.h>
+ #include <asm/mpspec.h>
+ #include <asm/setup.h>
+-#include <asm/arch_hooks.h>
+ #include <asm/efi.h>
++#include <asm/timer.h>
++#include <asm/i8259.h>
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
+ #include <asm/io_apic.h>
+ #include <asm/ist.h>
+ #include <asm/vmi.h>
+-#include <setup_arch.h>
++#include <asm/setup_arch.h>
+ #include <asm/bios_ebda.h>
+ #include <asm/cacheflush.h>
+ #include <asm/processor.h>
+@@ -89,7 +90,7 @@
+ 
+ #include <asm/system.h>
+ #include <asm/vsyscall.h>
+-#include <asm/smp.h>
++#include <asm/cpu.h>
+ #include <asm/desc.h>
+ #include <asm/dma.h>
+ #include <asm/iommu.h>
+@@ -97,7 +98,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+ 
+-#include <mach_apic.h>
+ #include <asm/paravirt.h>
+ #include <asm/hypervisor.h>
+ 
+@@ -118,9 +118,6 @@
+ #include <xen/firmware.h>
+ #include <xen/xencons.h>
+ 
+-shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+-EXPORT_SYMBOL(HYPERVISOR_shared_info);
+-
+ static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+ static struct notifier_block xen_panic_block = {
+ 	xen_panic_event, NULL, 0 /* try to go last */
+@@ -145,7 +142,26 @@ EXPORT_SYMBOL(xen_start_info);
+ #define ARCH_SETUP
+ #endif
+ 
++RESERVE_BRK(dmi_alloc, 65536);
++
++unsigned int boot_cpu_id __read_mostly;
++
++static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
++unsigned long _brk_end = (unsigned long)__brk_base;
++
+ #ifndef CONFIG_XEN
++#ifdef CONFIG_X86_64
++int default_cpu_present_to_apicid(int mps_cpu)
++{
++	return __default_cpu_present_to_apicid(mps_cpu);
++}
++
++int default_check_phys_apicid_present(int boot_cpu_physical_apicid)
++{
++	return __default_check_phys_apicid_present(boot_cpu_physical_apicid);
++}
++#endif
++
+ #ifndef CONFIG_DEBUG_BOOT_PARAMS
+ struct boot_params __initdata boot_params;
+ #else
+@@ -179,14 +195,6 @@ static struct resource bss_resource = {
+ 
+ 
+ #ifdef CONFIG_X86_32
+-#ifndef CONFIG_XEN
+-/* This value is set up by the early boot code to point to the value
+-   immediately after the boot time page tables.  It contains a *physical*
+-   address, and must not be in the .bss segment! */
+-unsigned long init_pg_tables_start __initdata = ~0UL;
+-unsigned long init_pg_tables_end __initdata = ~0UL;
+-#endif
+-
+ static struct resource video_ram_resource = {
+ 	.name	= "Video RAM area",
+ 	.start	= 0xa0000,
+@@ -226,7 +234,9 @@ struct ist_info ist_info;
+ #endif
+ 
+ #else
+-struct cpuinfo_x86 boot_cpu_data __read_mostly;
++struct cpuinfo_x86 boot_cpu_data __read_mostly = {
++	.x86_phys_bits = MAX_PHYSMEM_BITS,
++};
+ EXPORT_SYMBOL(boot_cpu_data);
+ #endif
+ 
+@@ -241,12 +251,6 @@ unsigned long mmu_cr4_features = X86_CR4
+ int bootloader_type;
+ 
+ /*
+- * Early DMI memory
+- */
+-int dmi_alloc_index;
+-char dmi_alloc_data[DMI_MAX_DATA];
+-
+-/*
+  * Setup options
+  */
+ struct screen_info screen_info;
+@@ -293,6 +297,35 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
++void * __init extend_brk(size_t size, size_t align)
++{
++	size_t mask = align - 1;
++	void *ret;
++
++	BUG_ON(_brk_start == 0);
++	BUG_ON(align & mask);
++
++	_brk_end = (_brk_end + mask) & ~mask;
++	BUG_ON((char *)(_brk_end + size) > __brk_limit);
++
++	ret = (void *)_brk_end;
++	_brk_end += size;
++
++	memset(ret, 0, size);
++
++	return ret;
++}
++
++static void __init reserve_brk(void)
++{
++	if (_brk_end > _brk_start)
++		reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
++
++	/* Mark brk area as locked down and no longer taking any
++	   new allocations */
++	_brk_start = 0;
++}
++
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+@@ -653,24 +686,7 @@ static int __init setup_elfcorehdr(char 
+ early_param("elfcorehdr", setup_elfcorehdr);
+ #endif
+ 
+-#ifndef CONFIG_XEN
+-static int __init default_update_genapic(void)
+-{
+-#ifdef CONFIG_X86_SMP
+-# if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64)
+-	genapic->wakeup_cpu = wakeup_secondary_cpu_via_init;
+-# endif
+-#endif
+-
+-	return 0;
+-}
+-#else
+-#define default_update_genapic NULL
+-#endif
+-
+-static struct x86_quirks default_x86_quirks __initdata = {
+-	.update_genapic         = default_update_genapic,
+-};
++static struct x86_quirks default_x86_quirks __initdata;
+ 
+ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+ 
+@@ -738,19 +754,11 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	/* Register a call for panic conditions. */
+ 	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+-
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_writable_pagetables));
+-#ifdef CONFIG_X86_32
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_4gb_segments));
+-#endif
+ #endif /* CONFIG_XEN */
+ 
+ #ifdef CONFIG_X86_32
+ 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+ 	visws_early_detect();
+-	pre_setup_arch_hook();
+ #else
+ 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ #endif
+@@ -834,16 +842,7 @@ void __init setup_arch(char **cmdline_p)
+ 	init_mm.start_code = (unsigned long) _text;
+ 	init_mm.end_code = (unsigned long) _etext;
+ 	init_mm.end_data = (unsigned long) _edata;
+-#ifdef CONFIG_X86_32
+-#ifndef CONFIG_XEN
+-	init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
+-#else
+-	init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
+-		       xen_start_info->nr_pt_frames) << PAGE_SHIFT;
+-#endif
+-#else
+-	init_mm.brk = (unsigned long) &_end;
+-#endif
++	init_mm.brk = _brk_end;
+ 
+ 	code_resource.start = virt_to_phys(_text);
+ 	code_resource.end = virt_to_phys(_etext)-1;
+@@ -956,9 +955,8 @@ void __init setup_arch(char **cmdline_p)
+ 	num_physpages = max_pfn;
+ 	max_mapnr = max_pfn;
+ 
+-#ifndef CONFIG_XEN
+- 	if (cpu_has_x2apic)
+- 		check_x2apic();
++#ifdef CONFIG_X86_LOCAL_APIC
++	check_x2apic();
+ #endif
+ 
+ 	/* How many end-of-memory variables you have, grandma! */
+@@ -975,6 +973,8 @@ void __init setup_arch(char **cmdline_p)
+ 	setup_bios_corruption_check();
+ #endif
+ 
++	reserve_brk();
++
+ 	/* max_pfn_mapped is updated here */
+ 	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
+ 	max_pfn_mapped = max_low_pfn_mapped;
+@@ -999,7 +999,7 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	reserve_initrd();
+ 
+-#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
+ 	vsmp_init();
+ #endif
+ 
+@@ -1034,12 +1034,11 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ 	acpi_reserve_bootmem();
+ #endif
+-#ifdef CONFIG_X86_FIND_SMP_CONFIG
+ 	/*
+ 	 * Find and reserve possible boot-time SMP configuration:
+ 	 */
+ 	find_smp_config();
+-#endif
++
+ 	reserve_crashkernel();
+ 
+ #if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+@@ -1140,13 +1139,9 @@ void __init setup_arch(char **cmdline_p)
+ 	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
+ 		if (i != 4 && request_dma(i, "xen") != 0)
+ 			BUG();
+-#endif /* CONFIG_XEN */
+-
+-#ifdef CONFIG_X86_GENERICARCH
++#else /* CONFIG_XEN */
+ 	generic_apic_probe();
+-#endif
+ 
+-#ifndef CONFIG_XEN
+ 	early_quirks();
+ #endif
+ 
+@@ -1221,6 +1216,98 @@ void __init setup_arch(char **cmdline_p)
+ #endif /* CONFIG_XEN */
+ }
+ 
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++
++/**
++ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
++ *
++ * Description:
++ *	Perform any necessary interrupt initialisation prior to setting up
++ *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
++ *	interrupts should be initialised here if the machine emulates a PC
++ *	in any way.
++ **/
++void __init x86_quirk_pre_intr_init(void)
++{
++	if (x86_quirks->arch_pre_intr_init) {
++		if (x86_quirks->arch_pre_intr_init())
++			return;
++	}
++	init_ISA_irqs();
++}
++
++/**
++ * x86_quirk_intr_init - post gate setup interrupt initialisation
++ *
++ * Description:
++ *	Fill in any interrupts that may have been left out by the general
++ *	init_IRQ() routine.  interrupts having to do with the machine rather
++ *	than the devices on the I/O bus (like APIC interrupts in intel MP
++ *	systems) are started here.
++ **/
++void __init x86_quirk_intr_init(void)
++{
++	if (x86_quirks->arch_intr_init) {
++		if (x86_quirks->arch_intr_init())
++			return;
++	}
++}
++
++/**
++ * x86_quirk_trap_init - initialise system specific traps
++ *
++ * Description:
++ *	Called as the final act of trap_init().  Used in VISWS to initialise
++ *	the various board specific APIC traps.
++ **/
++void __init x86_quirk_trap_init(void)
++{
++	if (x86_quirks->arch_trap_init) {
++		if (x86_quirks->arch_trap_init())
++			return;
++	}
++}
++
++static struct irqaction irq0  = {
++	.handler = timer_interrupt,
++	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
++	.name = "timer"
++};
++
++/**
++ * x86_quirk_pre_time_init - do any specific initialisations before.
++ *
++ **/
++void __init x86_quirk_pre_time_init(void)
++{
++	if (x86_quirks->arch_pre_time_init)
++		x86_quirks->arch_pre_time_init();
++}
++
++/**
++ * x86_quirk_time_init - do any specific initialisations for the system timer.
++ *
++ * Description:
++ *	Must plug the system timer interrupt source at HZ into the IRQ listed
++ *	in irq_vectors.h:TIMER_IRQ
++ **/
++void __init x86_quirk_time_init(void)
++{
++	if (x86_quirks->arch_time_init) {
++		/*
++		 * A nonzero return code does not mean failure, it means
++		 * that the architecture quirk does not want any
++		 * generic (timer) setup to be performed after this:
++		 */
++		if (x86_quirks->arch_time_init())
++			return;
++	}
++
++	irq0.mask = cpumask_of_cpu(0);
++	setup_irq(0, &irq0);
++}
++#endif /* CONFIG_X86_32 */
++
+ #ifdef CONFIG_XEN
+ static int
+ xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+--- head-2010-01-18.orig/arch/x86/kernel/setup_percpu.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_percpu.c	2009-11-06 10:52:02.000000000 +0100
+@@ -224,7 +224,7 @@ void __init setup_per_cpu_areas(void)
+ 		 * are zeroed indicating that the static arrays are
+ 		 * gone.
+ 		 */
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 		per_cpu(x86_cpu_to_apicid, cpu) =
+ 			early_per_cpu_map(x86_cpu_to_apicid, cpu);
+ 		per_cpu(x86_bios_cpu_apicid, cpu) =
+@@ -248,7 +248,7 @@ void __init setup_per_cpu_areas(void)
+ 	}
+ 
+ 	/* indicate the early static arrays will soon be gone */
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	early_per_cpu_ptr(x86_cpu_to_apicid) = NULL;
+ 	early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL;
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -2,7 +2,7 @@
+  *	Intel SMP support routines.
+  *
+  *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+- *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
++ *	(c) 1998-99, 2000, 2009 Ingo Molnar <mingo@redhat.com>
+  *      (c) 2002,2003 Andi Kleen, SuSE Labs.
+  *
+  *	i386 and x86_64 integration by Glauber Costa <gcosta@redhat.com>
+@@ -26,7 +26,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+-#include <mach_ipi.h>
++#include <asm/ipi.h>
+ #include <xen/evtchn.h>
+ /*
+  *	Some notes on x86 processor bugs affecting SMP operation:
+@@ -118,17 +118,17 @@ void xen_smp_send_reschedule(int cpu)
+ 		WARN_ON(1);
+ 		return;
+ 	}
+-	send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
++	xen_send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
+ }
+ 
+ void xen_send_call_func_single_ipi(int cpu)
+ {
+-	send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_VECTOR);
++	xen_send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_VECTOR);
+ }
+ 
+ void xen_send_call_func_ipi(const struct cpumask *mask)
+ {
+-	send_IPI_mask_allbutself(mask, CALL_FUNCTION_VECTOR);
++	xen_send_IPI_mask_allbutself(mask, CALL_FUNCTION_VECTOR);
+ }
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:41:53.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:43:22.000000000 +0100
+@@ -577,7 +577,7 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+ 
+ static cycle_t cs_last;
+ 
+-static cycle_t xen_clocksource_read(void)
++static cycle_t xen_clocksource_read(struct clocksource *cs)
+ {
+ #ifdef CONFIG_SMP
+ 	cycle_t last = get64(&cs_last);
+--- head-2010-01-18.orig/arch/x86/kernel/traps-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -54,15 +54,14 @@
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ 
+-#include <mach_traps.h>
++#include <asm/mach_traps.h>
+ 
+ #ifdef CONFIG_X86_64
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
+-#include <asm/pda.h>
+ #else
+ #include <asm/processor-flags.h>
+-#include <asm/arch_hooks.h>
++#include <asm/setup.h>
+ #include <asm/traps.h>
+ 
+ #include "cpu/mcheck/mce.h"
+@@ -123,49 +122,6 @@ die_if_kernel(const char *str, struct pt
+ 	if (!user_mode_vm(regs))
+ 		die(str, regs, err);
+ }
+-
+-/*
+- * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+- * invalid offset set (the LAZY one) and the faulting thread has
+- * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS,
+- * we set the offset field correctly and return 1.
+- */
+-static int lazy_iobitmap_copy(void)
+-{
+-#ifndef CONFIG_XEN
+-	struct thread_struct *thread;
+-	struct tss_struct *tss;
+-	int cpu;
+-
+-	cpu = get_cpu();
+-	tss = &per_cpu(init_tss, cpu);
+-	thread = &current->thread;
+-
+-	if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+-	    thread->io_bitmap_ptr) {
+-		memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
+-		       thread->io_bitmap_max);
+-		/*
+-		 * If the previously set map was extending to higher ports
+-		 * than the current one, pad extra space with 0xff (no access).
+-		 */
+-		if (thread->io_bitmap_max < tss->io_bitmap_max) {
+-			memset((char *) tss->io_bitmap +
+-				thread->io_bitmap_max, 0xff,
+-				tss->io_bitmap_max - thread->io_bitmap_max);
+-		}
+-		tss->io_bitmap_max = thread->io_bitmap_max;
+-		tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
+-		tss->io_bitmap_owner = thread;
+-		put_cpu();
+-
+-		return 1;
+-	}
+-	put_cpu();
+-#endif
+-
+-	return 0;
+-}
+ #endif
+ 
+ static void __kprobes
+@@ -316,11 +272,6 @@ do_general_protection(struct pt_regs *re
+ 	conditional_sti(regs);
+ 
+ #ifdef CONFIG_X86_32
+-	if (lazy_iobitmap_copy()) {
+-		/* restart the faulting instruction */
+-		return;
+-	}
+-
+ 	if (regs->flags & X86_VM_MASK)
+ 		goto gp_in_vm86;
+ #endif
+@@ -911,19 +862,20 @@ void math_emulate(struct math_emu_info *
+ }
+ #endif /* CONFIG_MATH_EMULATION */
+ 
+-dotraplinkage void __kprobes do_device_not_available(struct pt_regs regs)
++dotraplinkage void __kprobes
++do_device_not_available(struct pt_regs *regs, long error_code)
+ {
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	if (read_cr0() & X86_CR0_EM) {
+ 		struct math_emu_info info = { };
+ 
+-		conditional_sti(&regs);
++		conditional_sti(regs);
+ 
+-		info.regs = &regs;
++		info.regs = regs;
+ 		math_emulate(&info);
+ 	} else {
+ 		math_state_restore(); /* interrupts still off */
+-		conditional_sti(&regs);
++		conditional_sti(regs);
+ 	}
+ #else
+ 	math_state_restore();
+@@ -939,7 +891,7 @@ dotraplinkage void do_iret_error(struct 
+ 	info.si_signo = SIGILL;
+ 	info.si_errno = 0;
+ 	info.si_code = ILL_BADSTK;
+-	info.si_addr = 0;
++	info.si_addr = NULL;
+ 	if (notify_die(DIE_TRAP, "iret exception",
+ 			regs, error_code, 32, SIGILL) == NOTIFY_STOP)
+ 		return;
+--- head-2010-01-18.orig/arch/x86/kernel/vmlinux.lds.S	2009-12-04 10:51:06.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vmlinux.lds.S	2009-11-06 10:52:02.000000000 +0100
+@@ -16,8 +16,10 @@
+ 
+ #ifdef CONFIG_X86_32
+ #define LOAD_OFFSET __PAGE_OFFSET
+-#else
++#elif !defined(CONFIG_XEN) || CONFIG_XEN_COMPAT > 0x030002
+ #define LOAD_OFFSET __START_KERNEL_map
++#else
++#define LOAD_OFFSET 0
+ #endif
+ 
+ #include <asm-generic/vmlinux.lds.h>
+--- head-2010-01-18.orig/arch/x86/mach-xen/Makefile	2007-06-12 13:12:48.000000000 +0200
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,5 +0,0 @@
+-#
+-# Makefile for the linux kernel.
+-#
+-
+-obj-y				:= setup.o
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2009-12-04 11:23:33.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,190 +0,0 @@
+-/*
+- *	Machine specific setup for generic
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/module.h>
+-#include <asm/acpi.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/e820.h>
+-#include <asm/setup.h>
+-#include <asm/fixmap.h>
+-#include <asm/pgtable.h>
+-
+-#include <xen/interface/callback.h>
+-#include <xen/interface/memory.h>
+-
+-#ifdef CONFIG_X86_32
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-#define DEFAULT_SEND_IPI	(1)
+-#else
+-#define DEFAULT_SEND_IPI	(0)
+-#endif
+-
+-int no_broadcast=DEFAULT_SEND_IPI;
+-
+-static __init int no_ipi_broadcast(char *str)
+-{
+-	get_option(&str, &no_broadcast);
+-	printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
+-											"IPI Broadcast");
+-	return 1;
+-}
+-
+-__setup("no_ipi_broadcast", no_ipi_broadcast);
+-
+-static int __init print_ipi_mode(void)
+-{
+-	printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
+-											"Shortcut");
+-	return 0;
+-}
+-
+-late_initcall(print_ipi_mode);
+-
+-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 pre_setup_arch_hook(void)
+-{
+-	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;
+-
+-	xen_setup_features();
+-
+-	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) {
+-		hypervisor_virt_start = pp.virt_start;
+-		reserve_top_address(0UL - 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;
+-}
+-
+-#endif /* CONFIG_X86_32 */
+-
+-extern void hypervisor_callback(void);
+-extern void failsafe_callback(void);
+-extern void nmi(void);
+-
+-#ifdef CONFIG_X86_64
+-#include <asm/proto.h>
+-#define CALLBACK_ADDR(fn) ((unsigned long)(fn))
+-#else
+-#define CALLBACK_ADDR(fn) { __KERNEL_CS, (unsigned long)(fn) }
+-#endif
+-
+-void __init machine_specific_arch_setup(void)
+-{
+-	int ret;
+-	static struct callback_register __initdata event = {
+-		.type = CALLBACKTYPE_event,
+-		.address = CALLBACK_ADDR(hypervisor_callback)
+-	};
+-	static struct callback_register __initdata failsafe = {
+-		.type = CALLBACKTYPE_failsafe,
+-		.address = CALLBACK_ADDR(failsafe_callback)
+-	};
+-#ifdef CONFIG_X86_64
+-	static struct callback_register __initdata syscall = {
+-		.type = CALLBACKTYPE_syscall,
+-		.address = CALLBACK_ADDR(system_call)
+-	};
+-#endif
+-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+-	static struct callback_register __initdata nmi_cb = {
+-		.type = CALLBACKTYPE_nmi,
+-		.address = CALLBACK_ADDR(nmi)
+-	};
+-#endif
+-
+-	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+-	if (ret == 0)
+-		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
+-#ifdef CONFIG_X86_64
+-	if (ret == 0)
+-		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
+-#endif
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-#ifdef CONFIG_X86_32
+-	if (ret == -ENOSYS)
+-		ret = HYPERVISOR_set_callbacks(
+-			event.address.cs, event.address.eip,
+-			failsafe.address.cs, failsafe.address.eip);
+-#else
+-		ret = HYPERVISOR_set_callbacks(
+-			event.address,
+-			failsafe.address,
+-			syscall.address);
+-#endif
+-#endif
+-	BUG_ON(ret);
+-
+-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+-	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (ret == -ENOSYS) {
+-		static struct xennmi_callback __initdata cb = {
+-			.handler_address = (unsigned long)nmi
+-		};
+-
+-		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+-	}
+-#endif
+-#endif
+-
+-#ifdef CONFIG_X86_32
+-	/* Do an early initialization of the fixmap area */
+-	{
+-		extern pte_t swapper_pg_fixmap[PTRS_PER_PTE];
+-		unsigned long addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+-		pud_t *pud = pud_offset(swapper_pg_dir + pgd_index(addr), addr);
+-		pmd_t *pmd = pmd_offset(pud, addr);
+-		unsigned int i;
+-
+-		make_lowmem_page_readonly(swapper_pg_fixmap, XENFEAT_writable_page_tables);
+-		set_pmd(pmd, __pmd(__pa_symbol(swapper_pg_fixmap) | _PAGE_TABLE));
+-
+-#define __FIXADDR_TOP (-PAGE_SIZE)
+-#define FIX_BUG_ON(fix) BUILD_BUG_ON(pmd_index(__fix_to_virt(FIX_##fix)) \
+-			!= pmd_index(__fix_to_virt(FIX_EARLYCON_MEM_BASE)))
+-		FIX_BUG_ON(SHARED_INFO);
+-		FIX_BUG_ON(ISAMAP_BEGIN);
+-		FIX_BUG_ON(ISAMAP_END);
+-#undef __FIXADDR_TOP
+-		BUG_ON(pte_index(hypervisor_virt_start));
+-
+-		/* Switch to the real shared_info page, and clear the
+-		 * dummy page. */
+-		set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+-		HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+-		memset(empty_zero_page, 0, sizeof(empty_zero_page));
+-
+-		/* Setup mapping of lower 1st MB */
+-		for (i = 0; i < NR_FIX_ISAMAPS; i++)
+-			if (is_initial_xendomain())
+-				set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
+-			else
+-				__set_fixmap(FIX_ISAMAP_BEGIN - i,
+-					     virt_to_machine(empty_zero_page),
+-					     PAGE_KERNEL_RO);
+-	}
+-#endif
+-}
+--- head-2010-01-18.orig/arch/x86/mm/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -26,5 +26,6 @@ obj-$(CONFIG_K8_NUMA)		+= k8topology_64.
+ obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
+ 
+ obj-$(CONFIG_XEN)		+= hypervisor.o
++disabled-obj-$(CONFIG_XEN)	:= tlb.o
+ 
+ obj-$(CONFIG_MEMTEST)		+= memtest.o
+--- head-2010-01-18.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,73 +1,79 @@
+ /*
+  *  Copyright (C) 1995  Linus Torvalds
+- *  Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
++ *  Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
++ *  Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
+  */
+-
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+-#include <linux/ptrace.h>
+-#include <linux/mmiotrace.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+ #include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/tty.h>
+-#include <linux/vt_kern.h>		/* For unblank_screen() */
++#include <linux/mmiotrace.h>
++#include <linux/bootmem.h>
+ #include <linux/compiler.h>
+ #include <linux/highmem.h>
+-#include <linux/bootmem.h>		/* for max_low_pfn */
+-#include <linux/vmalloc.h>
+-#include <linux/module.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
++#include <linux/vmalloc.h>
++#include <linux/vt_kern.h>
++#include <linux/signal.h>
++#include <linux/kernel.h>
++#include <linux/ptrace.h>
++#include <linux/string.h>
++#include <linux/module.h>
+ #include <linux/kdebug.h>
++#include <linux/errno.h>
++#include <linux/magic.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/mman.h>
++#include <linux/tty.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++
++#include <asm-generic/sections.h>
+ 
+-#include <asm/system.h>
+-#include <asm/desc.h>
+-#include <asm/segment.h>
+-#include <asm/pgalloc.h>
+-#include <asm/smp.h>
+ #include <asm/tlbflush.h>
++#include <asm/pgalloc.h>
++#include <asm/segment.h>
++#include <asm/system.h>
+ #include <asm/proto.h>
+-#include <asm-generic/sections.h>
+ #include <asm/traps.h>
++#include <asm/desc.h>
+ 
+ /*
+- * Page fault error code bits
+- *	bit 0 == 0 means no page found, 1 means protection fault
+- *	bit 1 == 0 means read, 1 means write
+- *	bit 2 == 0 means kernel, 1 means user-mode
+- *	bit 3 == 1 means use of reserved bit detected
+- *	bit 4 == 1 means fault was an instruction fetch
+- */
+-#define PF_PROT		(1<<0)
+-#define PF_WRITE	(1<<1)
+-#define PF_USER		(1<<2)
+-#define PF_RSVD		(1<<3)
+-#define PF_INSTR	(1<<4)
++ * Page fault error code bits:
++ *
++ *   bit 0 ==	 0: no page found	1: protection fault
++ *   bit 1 ==	 0: read access		1: write access
++ *   bit 2 ==	 0: kernel-mode access	1: user-mode access
++ *   bit 3 ==				1: use of reserved bit detected
++ *   bit 4 ==				1: fault was an instruction fetch
++ */
++enum x86_pf_error_code {
+ 
++	PF_PROT		=		1 << 0,
++	PF_WRITE	=		1 << 1,
++	PF_USER		=		1 << 2,
++	PF_RSVD		=		1 << 3,
++	PF_INSTR	=		1 << 4,
++};
++
++/*
++ * Returns 0 if mmiotrace is disabled, or if the fault is not
++ * handled by mmiotrace:
++ */
+ static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
+ {
+-#ifdef CONFIG_MMIOTRACE
+ 	if (unlikely(is_kmmio_active()))
+ 		if (kmmio_handler(regs, addr) == 1)
+ 			return -1;
+-#endif
+ 	return 0;
+ }
+ 
+ static inline int notify_page_fault(struct pt_regs *regs)
+ {
+-#ifdef CONFIG_KPROBES
+ 	int ret = 0;
+ 
+ 	/* kprobe_running() needs smp_processor_id() */
+-	if (!user_mode_vm(regs)) {
++	if (kprobes_built_in() && !user_mode_vm(regs)) {
+ 		preempt_disable();
+ 		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ 			ret = 1;
+@@ -75,29 +81,76 @@ static inline int notify_page_fault(stru
+ 	}
+ 
+ 	return ret;
+-#else
+-	return 0;
+-#endif
+ }
+ 
+ /*
+- * X86_32
+- * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
+- * Check that here and ignore it.
+- *
+- * X86_64
+- * Sometimes the CPU reports invalid exceptions on prefetch.
+- * Check that here and ignore it.
++ * Prefetch quirks:
++ *
++ * 32-bit mode:
+  *
+- * Opcode checker based on code by Richard Brunner
++ *   Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
++ *   Check that here and ignore it.
++ *
++ * 64-bit mode:
++ *
++ *   Sometimes the CPU reports invalid exceptions on prefetch.
++ *   Check that here and ignore it.
++ *
++ * Opcode checker based on code by Richard Brunner.
+  */
+-static int is_prefetch(struct pt_regs *regs, unsigned long addr,
+-		       unsigned long error_code)
++static inline int
++check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
++		      unsigned char opcode, int *prefetch)
+ {
++	unsigned char instr_hi = opcode & 0xf0;
++	unsigned char instr_lo = opcode & 0x0f;
++
++	switch (instr_hi) {
++	case 0x20:
++	case 0x30:
++		/*
++		 * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
++		 * In X86_64 long mode, the CPU will signal invalid
++		 * opcode if some of these prefixes are present so
++		 * X86_64 will never get here anyway
++		 */
++		return ((instr_lo & 7) == 0x6);
++#ifdef CONFIG_X86_64
++	case 0x40:
++		/*
++		 * In AMD64 long mode 0x40..0x4F are valid REX prefixes
++		 * Need to figure out under what instruction mode the
++		 * instruction was issued. Could check the LDT for lm,
++		 * but for now it's good enough to assume that long
++		 * mode only uses well known segments or kernel.
++		 */
++		return (!user_mode(regs)) || (regs->cs == __USER_CS);
++#endif
++	case 0x60:
++		/* 0x64 thru 0x67 are valid prefixes in all modes. */
++		return (instr_lo & 0xC) == 0x4;
++	case 0xF0:
++		/* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
++		return !instr_lo || (instr_lo>>1) == 1;
++	case 0x00:
++		/* Prefetch instruction is 0x0F0D or 0x0F18 */
++		if (probe_kernel_address(instr, opcode))
++			return 0;
++
++		*prefetch = (instr_lo == 0xF) &&
++			(opcode == 0x0D || opcode == 0x18);
++		return 0;
++	default:
++		return 0;
++	}
++}
++
++static int
++is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
++{
++	unsigned char *max_instr;
+ 	unsigned char *instr;
+-	int scan_more = 1;
+ 	int prefetch = 0;
+-	unsigned char *max_instr;
+ 
+ 	/*
+ 	 * If it was a exec (instruction fetch) fault on NX page, then
+@@ -106,99 +159,174 @@ static int is_prefetch(struct pt_regs *r
+ 	if (error_code & PF_INSTR)
+ 		return 0;
+ 
+-	instr = (unsigned char *)convert_ip_to_linear(current, regs);
++	instr = (void *)convert_ip_to_linear(current, regs);
+ 	max_instr = instr + 15;
+ 
+ 	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+ 		return 0;
+ 
+-	while (scan_more && instr < max_instr) {
++	while (instr < max_instr) {
+ 		unsigned char opcode;
+-		unsigned char instr_hi;
+-		unsigned char instr_lo;
+ 
+ 		if (probe_kernel_address(instr, opcode))
+ 			break;
+ 
+-		instr_hi = opcode & 0xf0;
+-		instr_lo = opcode & 0x0f;
+ 		instr++;
+ 
+-		switch (instr_hi) {
+-		case 0x20:
+-		case 0x30:
+-			/*
+-			 * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
+-			 * In X86_64 long mode, the CPU will signal invalid
+-			 * opcode if some of these prefixes are present so
+-			 * X86_64 will never get here anyway
+-			 */
+-			scan_more = ((instr_lo & 7) == 0x6);
+-			break;
+-#ifdef CONFIG_X86_64
+-		case 0x40:
+-			/*
+-			 * In AMD64 long mode 0x40..0x4F are valid REX prefixes
+-			 * Need to figure out under what instruction mode the
+-			 * instruction was issued. Could check the LDT for lm,
+-			 * but for now it's good enough to assume that long
+-			 * mode only uses well known segments or kernel.
+-			 */
+-			scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
++		if (!check_prefetch_opcode(regs, instr, opcode, &prefetch))
+ 			break;
++	}
++	return prefetch;
++}
++
++static void
++force_sig_info_fault(int si_signo, int si_code, unsigned long address,
++		     struct task_struct *tsk)
++{
++	siginfo_t info;
++
++	info.si_signo	= si_signo;
++	info.si_errno	= 0;
++	info.si_code	= si_code;
++	info.si_addr	= (void __user *)address;
++
++	force_sig_info(si_signo, &info, tsk);
++}
++
++DEFINE_SPINLOCK(pgd_lock);
++LIST_HEAD(pgd_list);
++
++#ifdef CONFIG_X86_32
++static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
++{
++	unsigned index = pgd_index(address);
++	pgd_t *pgd_k;
++	pud_t *pud, *pud_k;
++	pmd_t *pmd, *pmd_k;
++
++	pgd += index;
++	pgd_k = init_mm.pgd + index;
++
++	if (!pgd_present(*pgd_k))
++		return NULL;
++
++	/*
++	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
++	 * and redundant with the set_pmd() on non-PAE. As would
++	 * set_pud.
++	 */
++	pud = pud_offset(pgd, address);
++	pud_k = pud_offset(pgd_k, address);
++	if (!pud_present(*pud_k))
++		return NULL;
++
++	pmd = pmd_offset(pud, address);
++	pmd_k = pmd_offset(pud_k, address);
++	if (!pmd_present(*pmd_k))
++		return NULL;
++
++	if (!pmd_present(*pmd)) {
++		bool lazy = percpu_read(xen_lazy_mmu);
++
++		percpu_write(xen_lazy_mmu, false);
++#if CONFIG_XEN_COMPAT > 0x030002
++		set_pmd(pmd, *pmd_k);
++#else
++		/*
++		 * When running on older Xen we must launder *pmd_k through
++		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
++		 */
++		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+ #endif
+-		case 0x60:
+-			/* 0x64 thru 0x67 are valid prefixes in all modes. */
+-			scan_more = (instr_lo & 0xC) == 0x4;
+-			break;
+-		case 0xF0:
+-			/* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
+-			scan_more = !instr_lo || (instr_lo>>1) == 1;
+-			break;
+-		case 0x00:
+-			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+-			scan_more = 0;
++		percpu_write(xen_lazy_mmu, lazy);
++	} else {
++		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
++	}
++
++	return pmd_k;
++}
++
++void vmalloc_sync_all(void)
++{
++	unsigned long address;
++
++	if (SHARED_KERNEL_PMD)
++		return;
++
++	for (address = VMALLOC_START & PMD_MASK;
++	     address >= TASK_SIZE && address < FIXADDR_TOP;
++	     address += PMD_SIZE) {
++
++		unsigned long flags;
++		struct page *page;
+ 
+-			if (probe_kernel_address(instr, opcode))
++		spin_lock_irqsave(&pgd_lock, flags);
++		list_for_each_entry(page, &pgd_list, lru) {
++			if (!vmalloc_sync_one(page_address(page), address))
+ 				break;
+-			prefetch = (instr_lo == 0xF) &&
+-				(opcode == 0x0D || opcode == 0x18);
+-			break;
+-		default:
+-			scan_more = 0;
+-			break;
+ 		}
++		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+-	return prefetch;
+ }
+ 
+-static void force_sig_info_fault(int si_signo, int si_code,
+-	unsigned long address, struct task_struct *tsk)
++/*
++ * 32-bit:
++ *
++ *   Handle a fault on the vmalloc or module mapping area
++ */
++static noinline int vmalloc_fault(unsigned long address)
+ {
+-	siginfo_t info;
++	unsigned long pgd_paddr;
++	pmd_t *pmd_k;
++	pte_t *pte_k;
+ 
+-	info.si_signo = si_signo;
+-	info.si_errno = 0;
+-	info.si_code = si_code;
+-	info.si_addr = (void __user *)address;
+-	force_sig_info(si_signo, &info, tsk);
++	/* Make sure we are in vmalloc area: */
++	if (!(address >= VMALLOC_START && address < VMALLOC_END))
++		return -1;
++
++	/*
++	 * Synchronize this task's top level page-table
++	 * with the 'reference' page table.
++	 *
++	 * Do _not_ use "current" here. We might be inside
++	 * an interrupt in the middle of a task switch..
++	 */
++	pgd_paddr = read_cr3();
++	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
++	if (!pmd_k)
++		return -1;
++
++	pte_k = pte_offset_kernel(pmd_k, address);
++	if (!pte_present(*pte_k))
++		return -1;
++
++	return 0;
+ }
+ 
+-#ifdef CONFIG_X86_64
+-static int bad_address(void *p)
++/*
++ * Did it hit the DOS screen memory VA from vm86 mode?
++ */
++static inline void
++check_v8086_mode(struct pt_regs *regs, unsigned long address,
++		 struct task_struct *tsk)
+ {
+-	unsigned long dummy;
+-	return probe_kernel_address((unsigned long *)p, dummy);
++	unsigned long bit;
++
++	if (!v8086_mode(regs))
++		return;
++
++	bit = (address - 0xA0000) >> PAGE_SHIFT;
++	if (bit < 32)
++		tsk->thread.screen_bitmap |= 1 << bit;
+ }
+-#endif
+ 
+ static void dump_pagetable(unsigned long address)
+ {
+-#ifdef CONFIG_X86_32
+ 	__typeof__(pte_val(__pte(0))) page;
+ 
+ 	page = read_cr3();
+ 	page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
++
+ #ifdef CONFIG_X86_PAE
+ 	printk("*pdpt = %016Lx ", page);
+ 	if ((page & _PAGE_PRESENT)
+@@ -206,7 +334,7 @@ static void dump_pagetable(unsigned long
+ 		page = mfn_to_pfn(page >> PAGE_SHIFT);
+ 		page <<= PAGE_SHIFT;
+ 		page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
+-		                                         & (PTRS_PER_PMD - 1)];
++							& (PTRS_PER_PMD - 1)];
+ 		printk(KERN_CONT "*pde = %016Lx ", page);
+ 		page &= ~_PAGE_NX;
+ 	}
+@@ -218,20 +346,146 @@ static void dump_pagetable(unsigned long
+ 	 * We must not directly access the pte in the highpte
+ 	 * case if the page table is located in highmem.
+ 	 * And let's rather not kmap-atomic the pte, just in case
+-	 * it's allocated already.
++	 * it's allocated already:
+ 	 */
+ 	if ((page & _PAGE_PRESENT)
+ 	    && mfn_to_local_pfn(page >> PAGE_SHIFT) < max_low_pfn
+ 	    && !(page & _PAGE_PSE)) {
++
+ 		page = mfn_to_pfn(page >> PAGE_SHIFT);
+ 		page <<= PAGE_SHIFT;
+ 		page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
+-		                                         & (PTRS_PER_PTE - 1)];
++							& (PTRS_PER_PTE - 1)];
+ 		printk(KERN_CONT "*pte = %0*Lx ", sizeof(page)*2, (u64)page);
+ 	}
+ 
+ 	printk(KERN_CONT "\n");
+-#else /* CONFIG_X86_64 */
++}
++
++#else /* CONFIG_X86_64: */
++
++void vmalloc_sync_all(void)
++{
++	unsigned long address;
++
++	for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
++	     address += PGDIR_SIZE) {
++
++		const pgd_t *pgd_ref = pgd_offset_k(address);
++		unsigned long flags;
++		struct page *page;
++
++		if (pgd_none(*pgd_ref))
++			continue;
++
++		spin_lock_irqsave(&pgd_lock, flags);
++		list_for_each_entry(page, &pgd_list, lru) {
++			pgd_t *pgd;
++			pgd = (pgd_t *)page_address(page) + pgd_index(address);
++			if (pgd_none(*pgd))
++				set_pgd(pgd, *pgd_ref);
++			else
++				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
++		}
++		spin_unlock_irqrestore(&pgd_lock, flags);
++	}
++}
++
++/*
++ * 64-bit:
++ *
++ *   Handle a fault on the vmalloc area
++ *
++ * This assumes no large pages in there.
++ */
++static noinline int vmalloc_fault(unsigned long address)
++{
++	pgd_t *pgd, *pgd_ref;
++	pud_t *pud, *pud_ref;
++	pmd_t *pmd, *pmd_ref;
++	pte_t *pte, *pte_ref;
++
++	/* Make sure we are in vmalloc area: */
++	if (!(address >= VMALLOC_START && address < VMALLOC_END))
++		return -1;
++
++	/*
++	 * Copy kernel mappings over when needed. This can also
++	 * happen within a race in page table update. In the later
++	 * case just flush:
++	 */
++	pgd = pgd_offset(current->active_mm, address);
++	pgd_ref = pgd_offset_k(address);
++	if (pgd_none(*pgd_ref))
++		return -1;
++
++	if (pgd_none(*pgd))
++		set_pgd(pgd, *pgd_ref);
++	else
++		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
++
++	/*
++	 * Below here mismatches are bugs because these lower tables
++	 * are shared:
++	 */
++
++	pud = pud_offset(pgd, address);
++	pud_ref = pud_offset(pgd_ref, address);
++	if (pud_none(*pud_ref))
++		return -1;
++
++	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
++		BUG();
++
++	pmd = pmd_offset(pud, address);
++	pmd_ref = pmd_offset(pud_ref, address);
++	if (pmd_none(*pmd_ref))
++		return -1;
++
++	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
++		BUG();
++
++	pte_ref = pte_offset_kernel(pmd_ref, address);
++	if (!pte_present(*pte_ref))
++		return -1;
++
++	pte = pte_offset_kernel(pmd, address);
++
++	/*
++	 * Don't use pte_page here, because the mappings can point
++	 * outside mem_map, and the NUMA hash lookup cannot handle
++	 * that:
++	 */
++	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
++		BUG();
++
++	return 0;
++}
++
++static const char errata93_warning[] =
++KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
++KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
++KERN_ERR "******* Please consider a BIOS update.\n"
++KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
++
++/*
++ * No vm86 mode in 64-bit mode:
++ */
++static inline void
++check_v8086_mode(struct pt_regs *regs, unsigned long address,
++		 struct task_struct *tsk)
++{
++}
++
++static int bad_address(void *p)
++{
++	unsigned long dummy;
++
++	return probe_kernel_address((unsigned long *)p, dummy);
++}
++
++static void dump_pagetable(unsigned long address)
++{
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+@@ -240,113 +494,77 @@ static void dump_pagetable(unsigned long
+ 	pgd = (pgd_t *)read_cr3();
+ 
+ 	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
++
+ 	pgd += pgd_index(address);
+-	if (bad_address(pgd)) goto bad;
++	if (bad_address(pgd))
++		goto bad;
++
+ 	printk("PGD %lx ", pgd_val(*pgd));
+-	if (!pgd_present(*pgd)) goto ret;
++
++	if (!pgd_present(*pgd))
++		goto out;
+ 
+ 	pud = pud_offset(pgd, address);
+-	if (bad_address(pud)) goto bad;
++	if (bad_address(pud))
++		goto bad;
++
+ 	printk(KERN_CONT "PUD %lx ", pud_val(*pud));
+ 	if (!pud_present(*pud) || pud_large(*pud))
+-		goto ret;
++		goto out;
+ 
+ 	pmd = pmd_offset(pud, address);
+-	if (bad_address(pmd)) goto bad;
++	if (bad_address(pmd))
++		goto bad;
++
+ 	printk(KERN_CONT "PMD %lx ", pmd_val(*pmd));
+-	if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
++	if (!pmd_present(*pmd) || pmd_large(*pmd))
++		goto out;
+ 
+ 	pte = pte_offset_kernel(pmd, address);
+-	if (bad_address(pte)) goto bad;
++	if (bad_address(pte))
++		goto bad;
++
+ 	printk(KERN_CONT "PTE %lx", pte_val(*pte));
+-ret:
++out:
+ 	printk(KERN_CONT "\n");
+ 	return;
+ bad:
+ 	printk("BAD\n");
+-#endif
+-}
+-
+-#ifdef CONFIG_X86_32
+-static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+-{
+-	unsigned index = pgd_index(address);
+-	pgd_t *pgd_k;
+-	pud_t *pud, *pud_k;
+-	pmd_t *pmd, *pmd_k;
+-
+-	pgd += index;
+-	pgd_k = init_mm.pgd + index;
+-
+-	if (!pgd_present(*pgd_k))
+-		return NULL;
+-
+-	/*
+-	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
+-	 * and redundant with the set_pmd() on non-PAE. As would
+-	 * set_pud.
+-	 */
+-
+-	pud = pud_offset(pgd, address);
+-	pud_k = pud_offset(pgd_k, address);
+-	if (!pud_present(*pud_k))
+-		return NULL;
+-
+-	pmd = pmd_offset(pud, address);
+-	pmd_k = pmd_offset(pud_k, address);
+-	if (!pmd_present(*pmd_k))
+-		return NULL;
+-	if (!pmd_present(*pmd)) {
+-		bool lazy = x86_read_percpu(xen_lazy_mmu);
+-
+-		x86_write_percpu(xen_lazy_mmu, false);
+-#if CONFIG_XEN_COMPAT > 0x030002
+-		set_pmd(pmd, *pmd_k);
+-#else
+-		/*
+-		 * When running on older Xen we must launder *pmd_k through
+-		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
+-		 */
+-		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+-#endif
+-		x86_write_percpu(xen_lazy_mmu, lazy);
+-	} else
+-		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+-	return pmd_k;
+ }
+-#endif
+ 
+-#ifdef CONFIG_X86_64
+-static const char errata93_warning[] =
+-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
+-KERN_ERR "******* Please consider a BIOS update.\n"
+-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+-#endif
++#endif /* CONFIG_X86_64 */
+ 
+-/* Workaround for K8 erratum #93 & buggy BIOS.
+-   BIOS SMM functions are required to use a specific workaround
+-   to avoid corruption of the 64bit RIP register on C stepping K8.
+-   A lot of BIOS that didn't get tested properly miss this.
+-   The OS sees this as a page fault with the upper 32bits of RIP cleared.
+-   Try to work around it here.
+-   Note we only handle faults in kernel here.
+-   Does nothing for X86_32
++/*
++ * Workaround for K8 erratum #93 & buggy BIOS.
++ *
++ * BIOS SMM functions are required to use a specific workaround
++ * to avoid corruption of the 64bit RIP register on C stepping K8.
++ *
++ * A lot of BIOS that didn't get tested properly miss this.
++ *
++ * The OS sees this as a page fault with the upper 32bits of RIP cleared.
++ * Try to work around it here.
++ *
++ * Note we only handle faults in kernel here.
++ * Does nothing on 32-bit.
+  */
+ static int is_errata93(struct pt_regs *regs, unsigned long address)
+ {
+ #ifdef CONFIG_X86_64
+-	static int warned;
++	static int once;
++
+ 	if (address != regs->ip)
+ 		return 0;
++
+ 	if ((address >> 32) != 0)
+ 		return 0;
++
+ 	address |= 0xffffffffUL << 32;
+ 	if ((address >= (u64)_stext && address <= (u64)_etext) ||
+ 	    (address >= MODULES_VADDR && address <= MODULES_END)) {
+-		if (!warned) {
++		if (!once) {
+ 			printk(errata93_warning);
+-			warned = 1;
++			once = 1;
+ 		}
+ 		regs->ip = address;
+ 		return 1;
+@@ -356,16 +574,17 @@ static int is_errata93(struct pt_regs *r
+ }
+ 
+ /*
+- * Work around K8 erratum #100 K8 in compat mode occasionally jumps to illegal
+- * addresses >4GB.  We catch this in the page fault handler because these
+- * addresses are not reachable. Just detect this case and return.  Any code
++ * Work around K8 erratum #100 K8 in compat mode occasionally jumps
++ * to illegal addresses >4GB.
++ *
++ * We catch this in the page fault handler because these addresses
++ * are not reachable. Just detect this case and return.  Any code
+  * segment in LDT is compatibility mode.
+  */
+ static int is_errata100(struct pt_regs *regs, unsigned long address)
+ {
+ #ifdef CONFIG_X86_64
+-	if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
+-	    (address >> 32))
++	if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32))
+ 		return 1;
+ #endif
+ 	return 0;
+@@ -375,8 +594,9 @@ static int is_f00f_bug(struct pt_regs *r
+ {
+ #ifdef CONFIG_X86_F00F_BUG
+ 	unsigned long nr;
++
+ 	/*
+-	 * Pentium F0 0F C7 C8 bug workaround.
++	 * Pentium F0 0F C7 C8 bug workaround:
+ 	 */
+ 	if (boot_cpu_data.f00f_bug) {
+ 		nr = (address - idt_descr.address) >> 3;
+@@ -390,62 +610,277 @@ static int is_f00f_bug(struct pt_regs *r
+ 	return 0;
+ }
+ 
+-static void show_fault_oops(struct pt_regs *regs, unsigned long error_code,
+-			    unsigned long address)
++static const char nx_warning[] = KERN_CRIT
++"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
++
++static void
++show_fault_oops(struct pt_regs *regs, unsigned long error_code,
++		unsigned long address)
+ {
+-#ifdef CONFIG_X86_32
+ 	if (!oops_may_print())
+ 		return;
+-#endif
+ 
+-#ifdef CONFIG_X86_PAE
+ 	if (error_code & PF_INSTR) {
+ 		unsigned int level;
++
+ 		pte_t *pte = lookup_address(address, &level);
+ 
+ 		if (pte && pte_present(*pte) && !pte_exec(*pte))
+-			printk(KERN_CRIT "kernel tried to execute "
+-				"NX-protected page - exploit attempt? "
+-				"(uid: %d)\n", current_uid());
++			printk(nx_warning, current_uid());
+ 	}
+-#endif
+ 
+ 	printk(KERN_ALERT "BUG: unable to handle kernel ");
+ 	if (address < PAGE_SIZE)
+ 		printk(KERN_CONT "NULL pointer dereference");
+ 	else
+ 		printk(KERN_CONT "paging request");
++
+ 	printk(KERN_CONT " at %p\n", (void *) address);
+ 	printk(KERN_ALERT "IP:");
+ 	printk_address(regs->ip, 1);
++
+ 	dump_pagetable(address);
+ }
+ 
+-#ifdef CONFIG_X86_64
+-static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
+-				 unsigned long error_code)
++static noinline void
++pgtable_bad(struct pt_regs *regs, unsigned long error_code,
++	    unsigned long address)
+ {
+-	unsigned long flags = oops_begin();
+-	int sig = SIGKILL;
+ 	struct task_struct *tsk;
++	unsigned long flags;
++	int sig;
++
++	flags = oops_begin();
++	tsk = current;
++	sig = SIGKILL;
+ 
+ 	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+-	       current->comm, address);
++	       tsk->comm, address);
+ 	dump_pagetable(address);
+-	tsk = current;
+-	tsk->thread.cr2 = address;
+-	tsk->thread.trap_no = 14;
+-	tsk->thread.error_code = error_code;
++
++	tsk->thread.cr2		= address;
++	tsk->thread.trap_no	= 14;
++	tsk->thread.error_code	= error_code;
++
+ 	if (__die("Bad pagetable", regs, error_code))
+ 		sig = 0;
++
+ 	oops_end(flags, regs, sig);
+ }
+-#endif
++
++static noinline void
++no_context(struct pt_regs *regs, unsigned long error_code,
++	   unsigned long address)
++{
++	struct task_struct *tsk = current;
++	unsigned long *stackend;
++	unsigned long flags;
++	int sig;
++
++	/* Are we prepared to handle this kernel fault? */
++	if (fixup_exception(regs))
++		return;
++
++	/*
++	 * 32-bit:
++	 *
++	 *   Valid to do another page fault here, because if this fault
++	 *   had been triggered by is_prefetch fixup_exception would have
++	 *   handled it.
++	 *
++	 * 64-bit:
++	 *
++	 *   Hall of shame of CPU/BIOS bugs.
++	 */
++	if (is_prefetch(regs, error_code, address))
++		return;
++
++	if (is_errata93(regs, address))
++		return;
++
++	/*
++	 * Oops. The kernel tried to access some bad page. We'll have to
++	 * terminate things with extreme prejudice:
++	 */
++	flags = oops_begin();
++
++	show_fault_oops(regs, error_code, address);
++
++	stackend = end_of_stack(tsk);
++	if (*stackend != STACK_END_MAGIC)
++		printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
++
++	tsk->thread.cr2		= address;
++	tsk->thread.trap_no	= 14;
++	tsk->thread.error_code	= error_code;
++
++	sig = SIGKILL;
++	if (__die("Oops", regs, error_code))
++		sig = 0;
++
++	/* Executive summary in case the body of the oops scrolled away */
++	printk(KERN_EMERG "CR2: %016lx\n", address);
++
++	oops_end(flags, regs, sig);
++}
++
++/*
++ * Print out info about fatal segfaults, if the show_unhandled_signals
++ * sysctl is set:
++ */
++static inline void
++show_signal_msg(struct pt_regs *regs, unsigned long error_code,
++		unsigned long address, struct task_struct *tsk)
++{
++	if (!unhandled_signal(tsk, SIGSEGV))
++		return;
++
++	if (!printk_ratelimit())
++		return;
++
++	printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
++		task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
++		tsk->comm, task_pid_nr(tsk), address,
++		(void *)regs->ip, (void *)regs->sp, error_code);
++
++	print_vma_addr(KERN_CONT " in ", regs->ip);
++
++	printk(KERN_CONT "\n");
++}
++
++static void
++__bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
++		       unsigned long address, int si_code)
++{
++	struct task_struct *tsk = current;
++
++	/* User mode accesses just cause a SIGSEGV */
++	if (error_code & PF_USER) {
++		/*
++		 * It's possible to have interrupts off here:
++		 */
++		local_irq_enable();
++
++		/*
++		 * Valid to do another page fault here because this one came
++		 * from user space:
++		 */
++		if (is_prefetch(regs, error_code, address))
++			return;
++
++		if (is_errata100(regs, address))
++			return;
++
++		if (unlikely(show_unhandled_signals))
++			show_signal_msg(regs, error_code, address, tsk);
++
++		/* Kernel addresses are always protection faults: */
++		tsk->thread.cr2		= address;
++		tsk->thread.error_code	= error_code | (address >= TASK_SIZE);
++		tsk->thread.trap_no	= 14;
++
++		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
++
++		return;
++	}
++
++	if (is_f00f_bug(regs, address))
++		return;
++
++	no_context(regs, error_code, address);
++}
++
++static noinline void
++bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
++		     unsigned long address)
++{
++	__bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR);
++}
++
++static void
++__bad_area(struct pt_regs *regs, unsigned long error_code,
++	   unsigned long address, int si_code)
++{
++	struct mm_struct *mm = current->mm;
++
++	/*
++	 * Something tried to access memory that isn't in our memory map..
++	 * Fix it, but check if it's kernel or user first..
++	 */
++	up_read(&mm->mmap_sem);
++
++	__bad_area_nosemaphore(regs, error_code, address, si_code);
++}
++
++static noinline void
++bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address)
++{
++	__bad_area(regs, error_code, address, SEGV_MAPERR);
++}
++
++static noinline void
++bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
++		      unsigned long address)
++{
++	__bad_area(regs, error_code, address, SEGV_ACCERR);
++}
++
++/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
++static void
++out_of_memory(struct pt_regs *regs, unsigned long error_code,
++	      unsigned long address)
++{
++	/*
++	 * We ran out of memory, call the OOM killer, and return the userspace
++	 * (which will retry the fault, or kill us if we got oom-killed):
++	 */
++	up_read(&current->mm->mmap_sem);
++
++	pagefault_out_of_memory();
++}
++
++static void
++do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
++{
++	struct task_struct *tsk = current;
++	struct mm_struct *mm = tsk->mm;
++
++	up_read(&mm->mmap_sem);
++
++	/* Kernel mode? Handle exceptions or die: */
++	if (!(error_code & PF_USER))
++		no_context(regs, error_code, address);
++
++	/* User-space => ok to do another page fault: */
++	if (is_prefetch(regs, error_code, address))
++		return;
++
++	tsk->thread.cr2		= address;
++	tsk->thread.error_code	= error_code;
++	tsk->thread.trap_no	= 14;
++
++	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
++}
++
++static noinline void
++mm_fault_error(struct pt_regs *regs, unsigned long error_code,
++	       unsigned long address, unsigned int fault)
++{
++	if (fault & VM_FAULT_OOM) {
++		out_of_memory(regs, error_code, address);
++	} else {
++		if (fault & VM_FAULT_SIGBUS)
++			do_sigbus(regs, error_code, address);
++		else
++			BUG();
++	}
++}
+ 
+ static int spurious_fault_check(unsigned long error_code, pte_t *pte)
+ {
+ 	if ((error_code & PF_WRITE) && !pte_write(*pte))
+ 		return 0;
++
+ 	if ((error_code & PF_INSTR) && !pte_exec(*pte))
+ 		return 0;
+ 
+@@ -453,21 +888,25 @@ static int spurious_fault_check(unsigned
+ }
+ 
+ /*
+- * Handle a spurious fault caused by a stale TLB entry.  This allows
+- * us to lazily refresh the TLB when increasing the permissions of a
+- * kernel page (RO -> RW or NX -> X).  Doing it eagerly is very
+- * expensive since that implies doing a full cross-processor TLB
+- * flush, even if no stale TLB entries exist on other processors.
++ * Handle a spurious fault caused by a stale TLB entry.
++ *
++ * This allows us to lazily refresh the TLB when increasing the
++ * permissions of a kernel page (RO -> RW or NX -> X).  Doing it
++ * eagerly is very expensive since that implies doing a full
++ * cross-processor TLB flush, even if no stale TLB entries exist
++ * on other processors.
++ *
+  * There are no security implications to leaving a stale TLB when
+  * increasing the permissions on a page.
+  */
+-static int spurious_fault(unsigned long address,
+-			  unsigned long error_code)
++static noinline int
++spurious_fault(unsigned long error_code, unsigned long address)
+ {
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
++	int ret;
+ 
+ 	/* Reserved-bit violation or user access to kernel space? */
+ 	if (error_code & (PF_USER | PF_RSVD))
+@@ -495,117 +934,62 @@ static int spurious_fault(unsigned long 
+ 	if (!pte_present(*pte))
+ 		return 0;
+ 
+-	return spurious_fault_check(error_code, pte);
+-}
+-
+-/*
+- * X86_32
+- * Handle a fault on the vmalloc or module mapping area
+- *
+- * X86_64
+- * Handle a fault on the vmalloc area
+- *
+- * This assumes no large pages in there.
+- */
+-static int vmalloc_fault(unsigned long address)
+-{
+-#ifdef CONFIG_X86_32
+-	unsigned long pgd_paddr;
+-	pmd_t *pmd_k;
+-	pte_t *pte_k;
+-
+-	/* Make sure we are in vmalloc area */
+-	if (!(address >= VMALLOC_START && address < VMALLOC_END))
+-		return -1;
++	ret = spurious_fault_check(error_code, pte);
++	if (!ret)
++		return 0;
+ 
+ 	/*
+-	 * Synchronize this task's top level page-table
+-	 * with the 'reference' page table.
+-	 *
+-	 * Do _not_ use "current" here. We might be inside
+-	 * an interrupt in the middle of a task switch..
++	 * Make sure we have permissions in PMD.
++	 * If not, then there's a bug in the page tables:
+ 	 */
+-	pgd_paddr = read_cr3();
+-	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
+-	if (!pmd_k)
+-		return -1;
+-	pte_k = pte_offset_kernel(pmd_k, address);
+-	if (!pte_present(*pte_k))
+-		return -1;
+-	return 0;
+-#else
+-	pgd_t *pgd, *pgd_ref;
+-	pud_t *pud, *pud_ref;
+-	pmd_t *pmd, *pmd_ref;
+-	pte_t *pte, *pte_ref;
++	ret = spurious_fault_check(error_code, (pte_t *) pmd);
++	WARN_ONCE(!ret, "PMD has incorrect permission bits\n");
+ 
+-	/* Make sure we are in vmalloc area */
+-	if (!(address >= VMALLOC_START && address < VMALLOC_END))
+-		return -1;
++	return ret;
++}
+ 
+-	/* Copy kernel mappings over when needed. This can also
+-	   happen within a race in page table update. In the later
+-	   case just flush. */
++int show_unhandled_signals = 1;
+ 
+-	pgd = pgd_offset(current->active_mm, address);
+-	pgd_ref = pgd_offset_k(address);
+-	if (pgd_none(*pgd_ref))
+-		return -1;
+-	if (pgd_none(*pgd))
+-		set_pgd(pgd, *pgd_ref);
+-	else
+-		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
++static inline int
++access_error(unsigned long error_code, int write, struct vm_area_struct *vma)
++{
++	if (write) {
++		/* write, present and write, not present: */
++		if (unlikely(!(vma->vm_flags & VM_WRITE)))
++			return 1;
++		return 0;
++	}
+ 
+-	/* Below here mismatches are bugs because these lower tables
+-	   are shared */
++	/* read, present: */
++	if (unlikely(error_code & PF_PROT))
++		return 1;
++
++	/* read, not present: */
++	if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
++		return 1;
+ 
+-	pud = pud_offset(pgd, address);
+-	pud_ref = pud_offset(pgd_ref, address);
+-	if (pud_none(*pud_ref))
+-		return -1;
+-	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+-		BUG();
+-	pmd = pmd_offset(pud, address);
+-	pmd_ref = pmd_offset(pud_ref, address);
+-	if (pmd_none(*pmd_ref))
+-		return -1;
+-	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
+-		BUG();
+-	pte_ref = pte_offset_kernel(pmd_ref, address);
+-	if (!pte_present(*pte_ref))
+-		return -1;
+-	pte = pte_offset_kernel(pmd, address);
+-	/* Don't use pte_page here, because the mappings can point
+-	   outside mem_map, and the NUMA hash lookup cannot handle
+-	   that. */
+-	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
+-		BUG();
+ 	return 0;
+-#endif
+ }
+ 
+-int show_unhandled_signals = 1;
++static int fault_in_kernel_space(unsigned long address)
++{
++	return address >= TASK_SIZE_MAX;
++}
+ 
+ /*
+  * This routine handles page faults.  It determines the address,
+  * and the problem, and then passes it off to one of the appropriate
+  * routines.
+  */
+-#ifdef CONFIG_X86_64
+-asmlinkage
+-#endif
+-void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
++dotraplinkage void __kprobes
++do_page_fault(struct pt_regs *regs, unsigned long error_code)
+ {
+-	struct task_struct *tsk;
+-	struct mm_struct *mm;
+ 	struct vm_area_struct *vma;
++	struct task_struct *tsk;
+ 	unsigned long address;
+-	int write, si_code;
++	struct mm_struct *mm;
++	int write;
+ 	int fault;
+-#ifdef CONFIG_X86_64
+-	unsigned long flags;
+-	int sig;
+-#endif
+ 
+ 	/* Set the "privileged fault" bit to something sane. */
+ 	if (user_mode_vm(regs))
+@@ -615,13 +999,12 @@ void __kprobes do_page_fault(struct pt_r
+ 
+ 	tsk = current;
+ 	mm = tsk->mm;
++
+ 	prefetchw(&mm->mmap_sem);
+ 
+-	/* get the address */
++	/* Get the faulting address: */
+ 	address = read_cr2();
+ 
+-	si_code = SEGV_MAPERR;
+-
+ 	if (unlikely(kmmio_fault(regs, address)))
+ 		return;
+ 
+@@ -638,328 +1021,158 @@ void __kprobes do_page_fault(struct pt_r
+ 	 * (error_code & 4) == 0, and that the fault was not a
+ 	 * protection error (error_code & 9) == 0.
+ 	 */
+-#ifdef CONFIG_X86_32
+-	if (unlikely(address >= TASK_SIZE)) {
+-#else
+-	if (unlikely(address >= TASK_SIZE64)) {
+-#endif
++	if (unlikely(fault_in_kernel_space(address))) {
+ 		/* Faults in hypervisor area can never be patched up. */
+ #if defined(CONFIG_X86_XEN)
+-		if (address >= hypervisor_virt_start)
+-			goto bad_area_nosemaphore;
++		if (address >= hypervisor_virt_start) {
+ #elif defined(CONFIG_X86_64_XEN)
+ 		if (address >= HYPERVISOR_VIRT_START
+-		    && address < HYPERVISOR_VIRT_END)
+-			goto bad_area_nosemaphore;
++		    && address < HYPERVISOR_VIRT_END) {
+ #endif
++			bad_area_nosemaphore(regs, error_code, address);
++			return;
++		}
++
+ 		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
+ 		    vmalloc_fault(address) >= 0)
+ 			return;
+ 
+-		/* Can handle a stale RO->RW TLB */
+-		if (spurious_fault(address, error_code))
++		/* Can handle a stale RO->RW TLB: */
++		if (spurious_fault(error_code, address))
+ 			return;
+ 
+-		/* kprobes don't want to hook the spurious faults. */
++		/* kprobes don't want to hook the spurious faults: */
+ 		if (notify_page_fault(regs))
+ 			return;
+ 		/*
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+-		 * fault we could otherwise deadlock.
++		 * fault we could otherwise deadlock:
+ 		 */
+-		goto bad_area_nosemaphore;
+-	}
++		bad_area_nosemaphore(regs, error_code, address);
+ 
+-	/* kprobes don't want to hook the spurious faults. */
+-	if (notify_page_fault(regs))
+ 		return;
++	}
+ 
++	/* kprobes don't want to hook the spurious faults: */
++	if (unlikely(notify_page_fault(regs)))
++		return;
+ 	/*
+ 	 * It's safe to allow irq's after cr2 has been saved and the
+ 	 * vmalloc fault has been handled.
+ 	 *
+ 	 * User-mode registers count as a user access even for any
+-	 * potential system fault or CPU buglet.
++	 * potential system fault or CPU buglet:
+ 	 */
+ 	if (user_mode_vm(regs)) {
+ 		local_irq_enable();
+ 		error_code |= PF_USER;
+-	} else if (regs->flags & X86_EFLAGS_IF)
+-		local_irq_enable();
++	} else {
++		if (regs->flags & X86_EFLAGS_IF)
++			local_irq_enable();
++	}
+ 
+-#ifdef CONFIG_X86_64
+ 	if (unlikely(error_code & PF_RSVD))
+-		pgtable_bad(address, regs, error_code);
+-#endif
++		pgtable_bad(regs, error_code, address);
+ 
+ 	/*
+-	 * If we're in an interrupt, have no user context or are running in an
+-	 * atomic region then we must not take the fault.
++	 * If we're in an interrupt, have no user context or are running
++	 * in an atomic region then we must not take the fault:
+ 	 */
+-	if (unlikely(in_atomic() || !mm))
+-		goto bad_area_nosemaphore;
++	if (unlikely(in_atomic() || !mm)) {
++		bad_area_nosemaphore(regs, error_code, address);
++		return;
++	}
+ 
+ 	/*
+ 	 * When running in the kernel we expect faults to occur only to
+-	 * addresses in user space.  All other faults represent errors in the
+-	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+-	 * erroneous fault occurring in a code path which already holds mmap_sem
+-	 * we will deadlock attempting to validate the fault against the
+-	 * address space.  Luckily the kernel only validly references user
+-	 * space from well defined areas of code, which are listed in the
+-	 * exceptions table.
++	 * addresses in user space.  All other faults represent errors in
++	 * the kernel and should generate an OOPS.  Unfortunately, in the
++	 * case of an erroneous fault occurring in a code path which already
++	 * holds mmap_sem we will deadlock attempting to validate the fault
++	 * against the address space.  Luckily the kernel only validly
++	 * references user space from well defined areas of code, which are
++	 * listed in the exceptions table.
+ 	 *
+ 	 * As the vast majority of faults will be valid we will only perform
+-	 * the source reference check when there is a possibility of a deadlock.
+-	 * Attempt to lock the address space, if we cannot we then validate the
+-	 * source.  If this is invalid we can skip the address space check,
+-	 * thus avoiding the deadlock.
++	 * the source reference check when there is a possibility of a
++	 * deadlock. Attempt to lock the address space, if we cannot we then
++	 * validate the source. If this is invalid we can skip the address
++	 * space check, thus avoiding the deadlock:
+ 	 */
+-	if (!down_read_trylock(&mm->mmap_sem)) {
++	if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
+ 		if ((error_code & PF_USER) == 0 &&
+-		    !search_exception_tables(regs->ip))
+-			goto bad_area_nosemaphore;
++		    !search_exception_tables(regs->ip)) {
++			bad_area_nosemaphore(regs, error_code, address);
++			return;
++		}
+ 		down_read(&mm->mmap_sem);
++	} else {
++		/*
++		 * The above down_read_trylock() might have succeeded in
++		 * which case we'll have missed the might_sleep() from
++		 * down_read():
++		 */
++		might_sleep();
+ 	}
+ 
+ 	vma = find_vma(mm, address);
+-	if (!vma)
+-		goto bad_area;
+-	if (vma->vm_start <= address)
++	if (unlikely(!vma)) {
++		bad_area(regs, error_code, address);
++		return;
++	}
++	if (likely(vma->vm_start <= address))
+ 		goto good_area;
+-	if (!(vma->vm_flags & VM_GROWSDOWN))
+-		goto bad_area;
++	if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
++		bad_area(regs, error_code, address);
++		return;
++	}
+ 	if (error_code & PF_USER) {
+ 		/*
+ 		 * Accessing the stack below %sp is always a bug.
+ 		 * The large cushion allows instructions like enter
+-		 * and pusha to work.  ("enter $65535,$31" pushes
++		 * and pusha to work. ("enter $65535, $31" pushes
+ 		 * 32 pointers and then decrements %sp by 65535.)
+ 		 */
+-		if (address + 65536 + 32 * sizeof(unsigned long) < regs->sp)
+-			goto bad_area;
++		if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
++			bad_area(regs, error_code, address);
++			return;
++		}
+ 	}
+-	if (expand_stack(vma, address))
+-		goto bad_area;
+-/*
+- * Ok, we have a good vm_area for this memory access, so
+- * we can handle it..
+- */
++	if (unlikely(expand_stack(vma, address))) {
++		bad_area(regs, error_code, address);
++		return;
++	}
++
++	/*
++	 * Ok, we have a good vm_area for this memory access, so
++	 * we can handle it..
++	 */
+ good_area:
+-	si_code = SEGV_ACCERR;
+-	write = 0;
+-	switch (error_code & (PF_PROT|PF_WRITE)) {
+-	default:	/* 3: write, present */
+-		/* fall through */
+-	case PF_WRITE:		/* write, not present */
+-		if (!(vma->vm_flags & VM_WRITE))
+-			goto bad_area;
+-		write++;
+-		break;
+-	case PF_PROT:		/* read, present */
+-		goto bad_area;
+-	case 0:			/* read, not present */
+-		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+-			goto bad_area;
++	write = error_code & PF_WRITE;
++
++	if (unlikely(access_error(error_code, write, vma))) {
++		bad_area_access_error(regs, error_code, address);
++		return;
+ 	}
+ 
+ 	/*
+ 	 * If for any reason at all we couldn't handle the fault,
+ 	 * make sure we exit gracefully rather than endlessly redo
+-	 * the fault.
++	 * the fault:
+ 	 */
+ 	fault = handle_mm_fault(mm, vma, address, write);
++
+ 	if (unlikely(fault & VM_FAULT_ERROR)) {
+-		if (fault & VM_FAULT_OOM)
+-			goto out_of_memory;
+-		else if (fault & VM_FAULT_SIGBUS)
+-			goto do_sigbus;
+-		BUG();
++		mm_fault_error(regs, error_code, address, fault);
++		return;
+ 	}
++
+ 	if (fault & VM_FAULT_MAJOR)
+ 		tsk->maj_flt++;
+ 	else
+ 		tsk->min_flt++;
+ 
+-#ifdef CONFIG_X86_32
+-	/*
+-	 * Did it hit the DOS screen memory VA from vm86 mode?
+-	 */
+-	if (v8086_mode(regs)) {
+-		unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
+-		if (bit < 32)
+-			tsk->thread.screen_bitmap |= 1 << bit;
+-	}
+-#endif
+-	up_read(&mm->mmap_sem);
+-	return;
+-
+-/*
+- * Something tried to access memory that isn't in our memory map..
+- * Fix it, but check if it's kernel or user first..
+- */
+-bad_area:
+-	up_read(&mm->mmap_sem);
+-
+-bad_area_nosemaphore:
+-	/* User mode accesses just cause a SIGSEGV */
+-	if (error_code & PF_USER) {
+-		/*
+-		 * It's possible to have interrupts off here.
+-		 */
+-		local_irq_enable();
+-
+-		/*
+-		 * Valid to do another page fault here because this one came
+-		 * from user space.
+-		 */
+-		if (is_prefetch(regs, address, error_code))
+-			return;
+-
+-		if (is_errata100(regs, address))
+-			return;
+-
+-		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-		    printk_ratelimit()) {
+-			printk(
+-			"%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+-			task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+-			tsk->comm, task_pid_nr(tsk), address,
+-			(void *) regs->ip, (void *) regs->sp, error_code);
+-			print_vma_addr(" in ", regs->ip);
+-			printk("\n");
+-		}
+-
+-		tsk->thread.cr2 = address;
+-		/* Kernel addresses are always protection faults */
+-		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+-		tsk->thread.trap_no = 14;
+-		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+-		return;
+-	}
+-
+-	if (is_f00f_bug(regs, address))
+-		return;
+-
+-no_context:
+-	/* Are we prepared to handle this kernel fault?  */
+-	if (fixup_exception(regs))
+-		return;
+-
+-	/*
+-	 * X86_32
+-	 * Valid to do another page fault here, because if this fault
+-	 * had been triggered by is_prefetch fixup_exception would have
+-	 * handled it.
+-	 *
+-	 * X86_64
+-	 * Hall of shame of CPU/BIOS bugs.
+-	 */
+-	if (is_prefetch(regs, address, error_code))
+-		return;
+-
+-	if (is_errata93(regs, address))
+-		return;
+-
+-/*
+- * Oops. The kernel tried to access some bad page. We'll have to
+- * terminate things with extreme prejudice.
+- */
+-#ifdef CONFIG_X86_32
+-	bust_spinlocks(1);
+-#else
+-	flags = oops_begin();
+-#endif
+-
+-	show_fault_oops(regs, error_code, address);
+-
+-	tsk->thread.cr2 = address;
+-	tsk->thread.trap_no = 14;
+-	tsk->thread.error_code = error_code;
+-
+-#ifdef CONFIG_X86_32
+-	die("Oops", regs, error_code);
+-	bust_spinlocks(0);
+-	do_exit(SIGKILL);
+-#else
+-	sig = SIGKILL;
+-	if (__die("Oops", regs, error_code))
+-		sig = 0;
+-	/* Executive summary in case the body of the oops scrolled away */
+-	printk(KERN_EMERG "CR2: %016lx\n", address);
+-	oops_end(flags, regs, sig);
+-#endif
+-
+-out_of_memory:
+-	/*
+-	 * We ran out of memory, call the OOM killer, and return the userspace
+-	 * (which will retry the fault, or kill us if we got oom-killed).
+-	 */
+-	up_read(&mm->mmap_sem);
+-	pagefault_out_of_memory();
+-	return;
++	check_v8086_mode(regs, address, tsk);
+ 
+-do_sigbus:
+ 	up_read(&mm->mmap_sem);
+-
+-	/* Kernel mode? Handle exceptions or die */
+-	if (!(error_code & PF_USER))
+-		goto no_context;
+-#ifdef CONFIG_X86_32
+-	/* User space => ok to do another page fault */
+-	if (is_prefetch(regs, address, error_code))
+-		return;
+-#endif
+-	tsk->thread.cr2 = address;
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 14;
+-	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
+-}
+-
+-DEFINE_SPINLOCK(pgd_lock);
+-LIST_HEAD(pgd_list);
+-
+-void vmalloc_sync_all(void)
+-{
+-	unsigned long address;
+-
+-#ifdef CONFIG_X86_32
+-	if (SHARED_KERNEL_PMD)
+-		return;
+-
+-	for (address = VMALLOC_START & PMD_MASK;
+-	     address >= TASK_SIZE && address < FIXADDR_TOP;
+-	     address += PMD_SIZE) {
+-		unsigned long flags;
+-		struct page *page;
+-
+-		spin_lock_irqsave(&pgd_lock, flags);
+-		list_for_each_entry(page, &pgd_list, lru) {
+-			if (!vmalloc_sync_one(page_address(page),
+-					      address))
+-				break;
+-		}
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-	}
+-#else /* CONFIG_X86_64 */
+-	for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
+-	     address += PGDIR_SIZE) {
+-		const pgd_t *pgd_ref = pgd_offset_k(address);
+-		unsigned long flags;
+-		struct page *page;
+-
+-		if (pgd_none(*pgd_ref))
+-			continue;
+-		spin_lock_irqsave(&pgd_lock, flags);
+-		list_for_each_entry(page, &pgd_list, lru) {
+-			pgd_t *pgd;
+-			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+-			if (pgd_none(*pgd))
+-				set_pgd(pgd, *pgd_ref);
+-			else
+-				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+-		}
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-	}
+-#endif
+ }
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -1,5 +1,6 @@
+ #include <linux/highmem.h>
+ #include <linux/module.h>
++#include <linux/swap.h> /* for totalram_pages */
+ 
+ void *kmap(struct page *page)
+ {
+@@ -18,49 +19,6 @@ void kunmap(struct page *page)
+ 	kunmap_high(page);
+ }
+ 
+-static void debug_kmap_atomic_prot(enum km_type type)
+-{
+-#ifdef CONFIG_DEBUG_HIGHMEM
+-	static unsigned warn_count = 10;
+-
+-	if (unlikely(warn_count == 0))
+-		return;
+-
+-	if (unlikely(in_interrupt())) {
+-		if (in_irq()) {
+-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
+-			    type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ &&
+-			    type != KM_BOUNCE_READ) {
+-				WARN_ON(1);
+-				warn_count--;
+-			}
+-		} else if (!irqs_disabled()) {	/* softirq */
+-			if (type != KM_IRQ0 && type != KM_IRQ1 &&
+-			    type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
+-			    type != KM_SKB_SUNRPC_DATA &&
+-			    type != KM_SKB_DATA_SOFTIRQ &&
+-			    type != KM_BOUNCE_READ) {
+-				WARN_ON(1);
+-				warn_count--;
+-			}
+-		}
+-	}
+-
+-	if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
+-			type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ) {
+-		if (!irqs_disabled()) {
+-			WARN_ON(1);
+-			warn_count--;
+-		}
+-	} else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
+-		if (irq_count() == 0 && !irqs_disabled()) {
+-			WARN_ON(1);
+-			warn_count--;
+-		}
+-	}
+-#endif
+-}
+-
+ /*
+  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+  * no global lock is needed and because the kmap code must perform a global TLB
+@@ -80,7 +38,7 @@ void *kmap_atomic_prot(struct page *page
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
+-	debug_kmap_atomic_prot(type);
++	debug_kmap_atomic(type);
+ 
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+@@ -120,22 +78,13 @@ void kunmap_atomic(void *kvaddr, enum km
+ 	pagefault_enable();
+ }
+ 
+-/* This is the same as kmap_atomic() but can map memory that doesn't
++/*
++ * This is the same as kmap_atomic() but can map memory that doesn't
+  * have a struct page associated with it.
+  */
+ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+ {
+-	enum fixed_addresses idx;
+-	unsigned long vaddr;
+-
+-	pagefault_disable();
+-
+-	idx = type + KM_TYPE_NR*smp_processor_id();
+-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+-	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+-	/*arch_flush_lazy_mmu_mode();*/
+-
+-	return (void*) vaddr;
++	return kmap_atomic_prot_pfn(pfn, type, kmap_prot);
+ }
+ EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
+ 
+@@ -206,3 +155,35 @@ EXPORT_SYMBOL(kmap_atomic_to_page);
+ #endif
+ EXPORT_SYMBOL(clear_highpage);
+ EXPORT_SYMBOL(copy_highpage);
++
++void __init set_highmem_pages_init(void)
++{
++	struct zone *zone;
++	int nid;
++
++	for_each_zone(zone) {
++		unsigned long zone_start_pfn, zone_end_pfn;
++
++		if (!is_highmem(zone))
++			continue;
++
++		zone_start_pfn = zone->zone_start_pfn;
++		zone_end_pfn = zone_start_pfn + zone->spanned_pages;
++
++		nid = zone_to_nid(zone);
++		printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",
++				zone->name, nid, zone_start_pfn, zone_end_pfn);
++
++		add_highpages_with_active_regions(nid, zone_start_pfn,
++				 zone_end_pfn);
++
++		/* XEN: init high-mem pages outside initial allocation. */
++		if (zone_start_pfn < xen_start_info->nr_pages)
++			zone_start_pfn = xen_start_info->nr_pages;
++		for (; zone_start_pfn < zone_end_pfn; zone_start_pfn++) {
++			ClearPageReserved(pfn_to_page(zone_start_pfn));
++			init_page_count(pfn_to_page(zone_start_pfn));
++		}
++	}
++	totalram_pages += totalhigh_pages;
++}
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:52:02.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <linux/vmalloc.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
++#include <asm/setup.h>
+ #include <asm/hypervisor.h>
+ #include <xen/balloon.h>
+ #include <xen/features.h>
+@@ -47,6 +48,9 @@
+ 
+ EXPORT_SYMBOL(hypercall_page);
+ 
++shared_info_t *__read_mostly HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++EXPORT_SYMBOL(HYPERVISOR_shared_info);
++
+ #define NR_MC     BITS_PER_LONG
+ #define NR_MMU    BITS_PER_LONG
+ #define NR_MMUEXT (BITS_PER_LONG / 4)
+@@ -538,7 +542,7 @@ int xen_create_contiguous_region(
+ 		unsigned int level;
+ 
+ 		if (vstart < __START_KERNEL_map
+-		    || vstart + (PAGE_SIZE << order) > (unsigned long)_end)
++		    || vstart + (PAGE_SIZE << order) > _brk_end)
+ 			return -EINVAL;
+ 		ptep = lookup_address((unsigned long)__va(__pa(vstart)),
+ 				      &level);
+@@ -953,6 +957,6 @@ int write_ldt_entry(struct desc_struct *
+ int write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc,
+ 		    int type)
+ {
+-	maddr_t mach_gp = virt_to_machine(gdt + entry);
++	maddr_t mach_gp = arbitrary_virt_to_machine(gdt + entry);
+ 	return HYPERVISOR_update_descriptor(mach_gp, *(const u64*)desc);
+ }
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/init-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -0,0 +1,459 @@
++#include <linux/ioport.h>
++#include <linux/swap.h>
++#include <linux/bootmem.h>
++
++#include <asm/cacheflush.h>
++#include <asm/e820.h>
++#include <asm/init.h>
++#include <asm/page.h>
++#include <asm/page_types.h>
++#include <asm/sections.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/tlbflush.h>
++
++unsigned long __meminitdata e820_table_start;
++unsigned long __meminitdata e820_table_end;
++unsigned long __meminitdata e820_table_top;
++
++int after_bootmem;
++
++#if !defined(CONFIG_XEN)
++int direct_gbpages
++#ifdef CONFIG_DIRECT_GBPAGES
++				= 1
++#endif
++;
++#elif defined(CONFIG_X86_32)
++#define direct_gbpages 0
++extern unsigned long extend_init_mapping(unsigned long tables_space);
++#else
++extern void xen_finish_init_mapping(void);
++#endif
++
++static void __init find_early_table_space(unsigned long end, int use_pse,
++					  int use_gbpages)
++{
++	unsigned long puds, pmds, ptes, tables;
++
++	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
++	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
++
++	if (use_gbpages) {
++		unsigned long extra;
++
++		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
++		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
++	} else
++		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
++
++	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
++
++	if (use_pse) {
++		unsigned long extra;
++
++		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
++#ifdef CONFIG_X86_32
++		extra += PMD_SIZE;
++#endif
++		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	} else
++		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
++
++#ifdef CONFIG_X86_32
++	/* for fixmap */
++	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
++#endif
++
++	/*
++	 * RED-PEN putting page tables only on node 0 could
++	 * cause a hotspot and fill up ZONE_DMA. The page tables
++	 * need roughly 0.5KB per GB.
++	 */
++#ifdef CONFIG_X86_32
++	e820_table_start = extend_init_mapping(tables);
++	e820_table_end = e820_table_start;
++#else /* CONFIG_X86_64 */
++	if (!e820_table_top) {
++		e820_table_start = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
++			xen_start_info->nr_pt_frames;
++		e820_table_end = e820_table_start;
++	} else {
++		/*
++		 * [table_start, table_top) gets passed to reserve_early(),
++		 * so we must not use table_end here, despite continuing
++		 * to allocate from there. table_end possibly being below
++		 * table_start is otoh not a problem.
++		 */
++		e820_table_start = e820_table_top;
++	}
++#endif
++	if (e820_table_start == -1UL)
++		panic("Cannot find space for the kernel page tables");
++
++	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
++
++	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
++		end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
++}
++
++struct map_range {
++	unsigned long start;
++	unsigned long end;
++	unsigned page_size_mask;
++};
++
++#ifdef CONFIG_X86_32
++#define NR_RANGE_MR 3
++#else /* CONFIG_X86_64 */
++#define NR_RANGE_MR 5
++#endif
++
++static int __meminit save_mr(struct map_range *mr, int nr_range,
++			     unsigned long start_pfn, unsigned long end_pfn,
++			     unsigned long page_size_mask)
++{
++	if (start_pfn < end_pfn) {
++		if (nr_range >= NR_RANGE_MR)
++			panic("run out of range for init_memory_mapping\n");
++		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
++		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
++		mr[nr_range].page_size_mask = page_size_mask;
++		nr_range++;
++	}
++
++	return nr_range;
++}
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++static void __init init_gbpages(void)
++{
++	if (direct_gbpages && cpu_has_gbpages)
++		printk(KERN_INFO "Using GB pages for direct mapping\n");
++	else
++		direct_gbpages = 0;
++}
++#else
++static inline void init_gbpages(void)
++{
++}
++#endif
++
++/*
++ * Setup the direct mapping of the physical memory at PAGE_OFFSET.
++ * This runs before bootmem is initialized and gets pages directly from
++ * the physical memory. To access them they are temporarily mapped.
++ */
++unsigned long __init_refok init_memory_mapping(unsigned long start,
++					       unsigned long end)
++{
++	unsigned long page_size_mask = 0;
++	unsigned long start_pfn, end_pfn;
++	unsigned long ret = 0;
++	unsigned long pos;
++
++	struct map_range mr[NR_RANGE_MR];
++	int nr_range, i;
++	int use_pse, use_gbpages;
++
++	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
++
++	if (!after_bootmem)
++		init_gbpages();
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/*
++	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
++	 * This will simplify cpa(), which otherwise needs to support splitting
++	 * large pages into small in interrupt context, etc.
++	 */
++	use_pse = use_gbpages = 0;
++#else
++	use_pse = cpu_has_pse;
++	use_gbpages = direct_gbpages;
++#endif
++
++#ifdef CONFIG_X86_32
++#ifdef CONFIG_X86_PAE
++	set_nx();
++	if (nx_enabled)
++		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
++#endif
++
++	/* Enable PSE if available */
++	if (cpu_has_pse)
++		set_in_cr4(X86_CR4_PSE);
++
++	/* Enable PGE if available */
++	if (cpu_has_pge) {
++		set_in_cr4(X86_CR4_PGE);
++		__supported_pte_mask |= _PAGE_GLOBAL;
++	}
++#endif
++
++	if (use_gbpages)
++		page_size_mask |= 1 << PG_LEVEL_1G;
++	if (use_pse)
++		page_size_mask |= 1 << PG_LEVEL_2M;
++
++	memset(mr, 0, sizeof(mr));
++	nr_range = 0;
++
++	/* head if not big page alignment ? */
++	start_pfn = start >> PAGE_SHIFT;
++	pos = start_pfn << PAGE_SHIFT;
++#ifdef CONFIG_X86_32
++	/*
++	 * Don't use a large page for the first 2/4MB of memory
++	 * because there are often fixed size MTRRs in there
++	 * and overlapping MTRRs into large pages can cause
++	 * slowdowns.
++	 */
++	if (pos == 0)
++		end_pfn = 1<<(PMD_SHIFT - PAGE_SHIFT);
++	else
++		end_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
++				 << (PMD_SHIFT - PAGE_SHIFT);
++#else /* CONFIG_X86_64 */
++	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
++			<< (PMD_SHIFT - PAGE_SHIFT);
++#endif
++	if (end_pfn > (end >> PAGE_SHIFT))
++		end_pfn = end >> PAGE_SHIFT;
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++		pos = end_pfn << PAGE_SHIFT;
++	}
++
++	/* big page (2M) range */
++	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
++			 << (PMD_SHIFT - PAGE_SHIFT);
++#ifdef CONFIG_X86_32
++	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
++#else /* CONFIG_X86_64 */
++	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
++			 << (PUD_SHIFT - PAGE_SHIFT);
++	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
++		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
++#endif
++
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask & (1<<PG_LEVEL_2M));
++		pos = end_pfn << PAGE_SHIFT;
++	}
++
++#ifdef CONFIG_X86_64
++	/* big page (1G) range */
++	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
++			 << (PUD_SHIFT - PAGE_SHIFT);
++	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask &
++				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
++		pos = end_pfn << PAGE_SHIFT;
++	}
++
++	/* tail is not big page (1G) alignment */
++	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
++			 << (PMD_SHIFT - PAGE_SHIFT);
++	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask & (1<<PG_LEVEL_2M));
++		pos = end_pfn << PAGE_SHIFT;
++	}
++#endif
++
++	/* tail is not big page (2M) alignment */
++	start_pfn = pos>>PAGE_SHIFT;
++	end_pfn = end>>PAGE_SHIFT;
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++
++	/* try to merge same page size and continuous */
++	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
++		unsigned long old_start;
++		if (mr[i].end != mr[i+1].start ||
++		    mr[i].page_size_mask != mr[i+1].page_size_mask)
++			continue;
++		/* move it */
++		old_start = mr[i].start;
++		memmove(&mr[i], &mr[i+1],
++			(nr_range - 1 - i) * sizeof(struct map_range));
++		mr[i--].start = old_start;
++		nr_range--;
++	}
++
++	for (i = 0; i < nr_range; i++)
++		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
++				mr[i].start, mr[i].end,
++			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
++			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
++
++	/*
++	 * Find space for the kernel direct mapping tables.
++	 *
++	 * Later we should allocate these tables in the local node of the
++	 * memory mapped. Unfortunately this is done currently before the
++	 * nodes are discovered.
++	 */
++	if (!after_bootmem)
++		find_early_table_space(end, use_pse, use_gbpages);
++
++#ifdef CONFIG_X86_32
++	for (i = 0; i < nr_range; i++)
++		kernel_physical_mapping_init(mr[i].start, mr[i].end,
++					     mr[i].page_size_mask);
++	ret = end;
++#else /* CONFIG_X86_64 */
++#define addr_to_page(addr)						\
++	((unsigned long *)						\
++	 ((mfn_to_pfn(((addr) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)	\
++	   << PAGE_SHIFT) + __START_KERNEL_map))
++
++	if (!start) {
++		unsigned long addr, va = __START_KERNEL_map;
++		unsigned long *page = (unsigned long *)init_level4_pgt;
++
++		/* Kill mapping of memory below _text. */
++		while (va < (unsigned long)&_text) {
++			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++				BUG();
++			va += PAGE_SIZE;
++		}
++
++		/* Blow away any spurious initial mappings. */
++		va = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT);
++
++		addr = page[pgd_index(va)];
++		page = addr_to_page(addr);
++		addr = page[pud_index(va)];
++		page = addr_to_page(addr);
++		while (pmd_index(va) | pte_index(va)) {
++			if (pmd_none(*(pmd_t *)&page[pmd_index(va)]))
++				break;
++			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++				BUG();
++			va += PAGE_SIZE;
++		}
++	}
++
++	for (i = 0; i < nr_range; i++)
++		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
++						   mr[i].page_size_mask);
++#undef addr_to_page
++#endif
++
++#ifdef CONFIG_X86_32
++	early_ioremap_page_table_range_init();
++#endif
++
++#ifdef CONFIG_X86_64
++	BUG_ON(e820_table_end > e820_table_top);
++	if (!start)
++		xen_finish_init_mapping();
++	else
++#endif
++	if (e820_table_end < e820_table_top)
++		/* Disable the 'table_end' allocator. */
++		e820_table_top = e820_table_end;
++
++	__flush_tlb_all();
++
++	if (!after_bootmem && e820_table_top > e820_table_start)
++		reserve_early(e820_table_start << PAGE_SHIFT,
++			      e820_table_top << PAGE_SHIFT, "PGTABLE");
++
++	if (!after_bootmem)
++		early_memtest(start, end);
++
++	return ret >> PAGE_SHIFT;
++}
++
++
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++	if (pagenr <= 256)
++		return 1;
++	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
++		return 0;
++	if (mfn_to_local_pfn(pagenr) >= max_pfn)
++		return 1;
++	return 0;
++}
++
++void free_init_pages(char *what, unsigned long begin, unsigned long end)
++{
++	unsigned long addr = begin;
++
++	if (addr >= end)
++		return;
++
++	/*
++	 * If debugging page accesses then do not free this memory but
++	 * mark them not present - any buggy init-section access will
++	 * create a kernel page fault:
++	 */
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
++		begin, PAGE_ALIGN(end));
++	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
++#else
++	/*
++	 * We just marked the kernel text read only above, now that
++	 * we are going to free part of that, we need to make that
++	 * writeable first.
++	 */
++	set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
++
++	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
++
++	for (; addr < end; addr += PAGE_SIZE) {
++		ClearPageReserved(virt_to_page(addr));
++		init_page_count(virt_to_page(addr));
++		memset((void *)(addr & ~(PAGE_SIZE-1)),
++			POISON_FREE_INITMEM, PAGE_SIZE);
++#ifdef CONFIG_X86_64
++		if (addr >= __START_KERNEL_map) {
++			/* make_readonly() reports all kernel addresses. */
++			if (HYPERVISOR_update_va_mapping((unsigned long)__va(__pa(addr)),
++							 pfn_pte(__pa(addr) >> PAGE_SHIFT,
++								 PAGE_KERNEL),
++							 0))
++				BUG();
++			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
++				BUG();
++		}
++#endif
++		free_page(addr);
++		totalram_pages++;
++	}
++#endif
++}
++
++void free_initmem(void)
++{
++	free_init_pages("unused kernel memory",
++			(unsigned long)(&__init_begin),
++			(unsigned long)(&__init_end));
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++	free_init_pages("initrd memory", start, end);
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -52,9 +52,7 @@
+ #include <asm/swiotlb.h>
+ #include <asm/setup.h>
+ #include <asm/cacheflush.h>
+-#include <asm/smp.h>
+-
+-unsigned int __VMALLOC_RESERVE = 128 << 20;
++#include <asm/init.h>
+ 
+ unsigned long max_low_pfn_mapped;
+ unsigned long max_pfn_mapped;
+@@ -64,19 +62,14 @@ unsigned long highstart_pfn, highend_pfn
+ 
+ static noinline int do_test_wp_bit(void);
+ 
+-
+-static unsigned long __initdata table_start;
+-static unsigned long __initdata table_end;
+-static unsigned long __initdata table_top;
+-
+-static int __initdata after_init_bootmem;
++bool __read_mostly __vmalloc_start_set = false;
+ 
+ static __init void *alloc_low_page(void)
+ {
+-	unsigned long pfn = table_end++;
++	unsigned long pfn = e820_table_end++;
+ 	void *adr;
+ 
+-	if (pfn >= table_top)
++	if (pfn >= e820_table_top)
+ 		panic("alloc_low_page: ran out of memory");
+ 
+ 	adr = __va(pfn * PAGE_SIZE);
+@@ -96,7 +89,7 @@ static pmd_t * __init one_md_table_init(
+ 
+ #ifdef CONFIG_X86_PAE
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+-		if (after_init_bootmem)
++		if (after_bootmem)
+ 			pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ 		else
+ 			pmd_table = (pmd_t *)alloc_low_page();
+@@ -128,7 +121,7 @@ static pte_t * __init one_page_table_ini
+ #endif
+ 		pte_t *page_table = NULL;
+ 
+-		if (after_init_bootmem) {
++		if (after_bootmem) {
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+ 			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+ #endif
+@@ -148,6 +141,23 @@ static pte_t * __init one_page_table_ini
+ 	return pte_offset_kernel(pmd, 0);
+ }
+ 
++pmd_t * __init populate_extra_pmd(unsigned long vaddr)
++{
++	int pgd_idx = pgd_index(vaddr);
++	int pmd_idx = pmd_index(vaddr);
++
++	return one_md_table_init(swapper_pg_dir + pgd_idx) + pmd_idx;
++}
++
++pte_t * __init populate_extra_pte(unsigned long vaddr)
++{
++	int pte_idx = pte_index(vaddr);
++	pmd_t *pmd;
++
++	pmd = populate_extra_pmd(vaddr);
++	return one_page_table_init(pmd) + pte_idx;
++}
++
+ static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
+ 					   unsigned long vaddr, pte_t *lastpte)
+ {
+@@ -164,12 +174,12 @@ static pte_t *__init page_table_kmap_che
+ 	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
+ 	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
+ 	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
+-	    && ((__pa(pte) >> PAGE_SHIFT) < table_start
+-		|| (__pa(pte) >> PAGE_SHIFT) >= table_end)) {
++	    && ((__pa(pte) >> PAGE_SHIFT) < e820_table_start
++		|| (__pa(pte) >> PAGE_SHIFT) >= e820_table_end)) {
+ 		pte_t *newpte;
+ 		int i;
+ 
+-		BUG_ON(after_init_bootmem);
++		BUG_ON(after_bootmem);
+ 		newpte = alloc_low_page();
+ 		for (i = 0; i < PTRS_PER_PTE; i++)
+ 			set_pte(newpte + i, pte[i]);
+@@ -244,11 +254,14 @@ static inline int is_kernel_text(unsigne
+  * of max_low_pfn pages, by creating page tables starting from address
+  * PAGE_OFFSET:
+  */
+-static void __init kernel_physical_mapping_init(pgd_t *pgd_base,
+-						unsigned long start_pfn,
+-						unsigned long end_pfn,
+-						int use_pse)
++unsigned long __init
++kernel_physical_mapping_init(unsigned long start,
++			     unsigned long end,
++			     unsigned long page_size_mask)
+ {
++	int use_pse = page_size_mask == (1<<PG_LEVEL_2M);
++	unsigned long start_pfn, end_pfn;
++	pgd_t *pgd_base = swapper_pg_dir;
+ 	int pgd_idx, pmd_idx, pte_ofs;
+ 	unsigned long pfn;
+ 	pgd_t *pgd;
+@@ -257,6 +270,9 @@ static void __init kernel_physical_mappi
+ 	unsigned pages_2m, pages_4k;
+ 	int mapping_iter;
+ 
++	start_pfn = start >> PAGE_SHIFT;
++	end_pfn = end >> PAGE_SHIFT;
++
+ 	/*
+ 	 * First iteration will setup identity mapping using large/small pages
+ 	 * based on use_pse, with other attributes same as set by
+@@ -391,26 +407,6 @@ repeat:
+ 		mapping_iter = 2;
+ 		goto repeat;
+ 	}
+-}
+-
+-/*
+- * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+- * is valid. The argument is a physical page number.
+- *
+- *
+- * On x86, access has to be given to the first megabyte of ram because that area
+- * contains bios code and data regions used by X and dosemu and similar apps.
+- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+- * mmio resources as well as potential bios/acpi data regions.
+- */
+-int devmem_is_allowed(unsigned long pagenr)
+-{
+-	if (pagenr <= 256)
+-		return 1;
+-	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+-		return 0;
+-	if (mfn_to_local_pfn(pagenr) >= max_pfn)
+-		return 1;
+ 	return 0;
+ }
+ 
+@@ -506,30 +502,10 @@ void __init add_highpages_with_active_re
+ 	work_with_active_regions(nid, add_highpages_work_fn, &data);
+ }
+ 
+-#ifndef CONFIG_NUMA
+-static void __init set_highmem_pages_init(void)
+-{
+-	int pfn;
+-
+-	add_highpages_with_active_regions(0, highstart_pfn, highend_pfn);
+-
+-	/* XEN: init high-mem pages outside initial allocation. */
+-	for (pfn = xen_start_info->nr_pages; pfn < highend_pfn; pfn++) {
+-		ClearPageReserved(pfn_to_page(pfn));
+-		init_page_count(pfn_to_page(pfn));
+-	}
+-
+-	totalram_pages += totalhigh_pages;
+-}
+-#endif /* !CONFIG_NUMA */
+-
+ #else
+ static inline void permanent_kmaps_init(pgd_t *pgd_base)
+ {
+ }
+-static inline void set_highmem_pages_init(void)
+-{
+-}
+ #endif /* CONFIG_HIGHMEM */
+ 
+ pgd_t *swapper_pg_dir;
+@@ -553,8 +529,9 @@ pgd_t *swapper_pg_dir;
+  * be partially populated, and so it avoids stomping on any existing
+  * mappings.
+  */
+-static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base)
++void __init early_ioremap_page_table_range_init(void)
+ {
++	pgd_t *pgd_base = swapper_pg_dir;
+ 	unsigned long vaddr, end;
+ 
+ 	/*
+@@ -649,7 +626,7 @@ static int __init noexec_setup(char *str
+ }
+ early_param("noexec", noexec_setup);
+ 
+-static void __init set_nx(void)
++void __init set_nx(void)
+ {
+ 	unsigned int v[4], l, h;
+ 
+@@ -685,75 +662,97 @@ static int __init parse_highmem(char *ar
+ }
+ early_param("highmem", parse_highmem);
+ 
++#define MSG_HIGHMEM_TOO_BIG \
++	"highmem size (%luMB) is bigger than pages available (%luMB)!\n"
++
++#define MSG_LOWMEM_TOO_SMALL \
++	"highmem size (%luMB) results in <64MB lowmem, ignoring it!\n"
+ /*
+- * Determine low and high memory ranges:
++ * All of RAM fits into lowmem - but if user wants highmem
++ * artificially via the highmem=x boot parameter then create
++ * it:
+  */
+-void __init find_low_pfn_range(void)
++void __init lowmem_pfn_init(void)
+ {
+-	/* it could update max_pfn */
+-
+ 	/* max_low_pfn is 0, we already have early_res support */
+-
+ 	max_low_pfn = max_pfn;
+-	if (max_low_pfn > MAXMEM_PFN) {
+-		if (highmem_pages == -1)
+-			highmem_pages = max_pfn - MAXMEM_PFN;
+-		if (highmem_pages + MAXMEM_PFN < max_pfn)
+-			max_pfn = MAXMEM_PFN + highmem_pages;
+-		if (highmem_pages + MAXMEM_PFN > max_pfn) {
+-			printk(KERN_WARNING "only %luMB highmem pages "
+-				"available, ignoring highmem size of %uMB.\n",
+-				pages_to_mb(max_pfn - MAXMEM_PFN),
++
++	if (highmem_pages == -1)
++		highmem_pages = 0;
++#ifdef CONFIG_HIGHMEM
++	if (highmem_pages >= max_pfn) {
++		printk(KERN_ERR MSG_HIGHMEM_TOO_BIG,
++			pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
++		highmem_pages = 0;
++	}
++	if (highmem_pages) {
++		if (max_low_pfn - highmem_pages < 64*1024*1024/PAGE_SIZE) {
++			printk(KERN_ERR MSG_LOWMEM_TOO_SMALL,
+ 				pages_to_mb(highmem_pages));
+ 			highmem_pages = 0;
+ 		}
+-		max_low_pfn = MAXMEM_PFN;
++		max_low_pfn -= highmem_pages;
++	}
++#else
++	if (highmem_pages)
++		printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
++#endif
++}
++
++#define MSG_HIGHMEM_TOO_SMALL \
++	"only %luMB highmem pages available, ignoring highmem size of %luMB!\n"
++
++#define MSG_HIGHMEM_TRIMMED \
++	"Warning: only 4GB will be used. Use a HIGHMEM64G enabled kernel!\n"
++/*
++ * We have more RAM than fits into lowmem - we try to put it into
++ * highmem, also taking the highmem=x boot parameter into account:
++ */
++void __init highmem_pfn_init(void)
++{
++	max_low_pfn = MAXMEM_PFN;
++
++	if (highmem_pages == -1)
++		highmem_pages = max_pfn - MAXMEM_PFN;
++
++	if (highmem_pages + MAXMEM_PFN < max_pfn)
++		max_pfn = MAXMEM_PFN + highmem_pages;
++
++	if (highmem_pages + MAXMEM_PFN > max_pfn) {
++		printk(KERN_WARNING MSG_HIGHMEM_TOO_SMALL,
++			pages_to_mb(max_pfn - MAXMEM_PFN),
++			pages_to_mb(highmem_pages));
++		highmem_pages = 0;
++	}
+ #ifndef CONFIG_HIGHMEM
+-		/* Maximum memory usable is what is directly addressable */
+-		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+-					MAXMEM>>20);
+-		if (max_pfn > MAX_NONPAE_PFN)
+-			printk(KERN_WARNING
+-				 "Use a HIGHMEM64G enabled kernel.\n");
+-		else
+-			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+-		max_pfn = MAXMEM_PFN;
++	/* Maximum memory usable is what is directly addressable */
++	printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20);
++	if (max_pfn > MAX_NONPAE_PFN)
++		printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
++	else
++		printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
++	max_pfn = MAXMEM_PFN;
+ #else /* !CONFIG_HIGHMEM */
+ #ifndef CONFIG_HIGHMEM64G
+-		if (max_pfn > MAX_NONPAE_PFN) {
+-			max_pfn = MAX_NONPAE_PFN;
+-			printk(KERN_WARNING "Warning only 4GB will be used."
+-				"Use a HIGHMEM64G enabled kernel.\n");
+-		}
++	if (max_pfn > MAX_NONPAE_PFN) {
++		max_pfn = MAX_NONPAE_PFN;
++		printk(KERN_WARNING MSG_HIGHMEM_TRIMMED);
++	}
+ #endif /* !CONFIG_HIGHMEM64G */
+ #endif /* !CONFIG_HIGHMEM */
+-	} else {
+-		if (highmem_pages == -1)
+-			highmem_pages = 0;
+-#ifdef CONFIG_HIGHMEM
+-		if (highmem_pages >= max_pfn) {
+-			printk(KERN_ERR "highmem size specified (%uMB) is "
+-				"bigger than pages available (%luMB)!.\n",
+-				pages_to_mb(highmem_pages),
+-				pages_to_mb(max_pfn));
+-			highmem_pages = 0;
+-		}
+-		if (highmem_pages) {
+-			if (max_low_pfn - highmem_pages <
+-			    64*1024*1024/PAGE_SIZE){
+-				printk(KERN_ERR "highmem size %uMB results in "
+-				"smaller than 64MB lowmem, ignoring it.\n"
+-					, pages_to_mb(highmem_pages));
+-				highmem_pages = 0;
+-			}
+-			max_low_pfn -= highmem_pages;
+-		}
+-#else
+-		if (highmem_pages)
+-			printk(KERN_ERR "ignoring highmem size on non-highmem"
+-					" kernel!\n");
+-#endif
+-	}
++}
++
++/*
++ * Determine low and high memory ranges:
++ */
++void __init find_low_pfn_range(void)
++{
++	/* it could update max_pfn */
++
++	if (max_pfn <= MAXMEM_PFN)
++		lowmem_pfn_init();
++	else
++		highmem_pfn_init();
+ }
+ 
+ #ifndef CONFIG_NEED_MULTIPLE_NODES
+@@ -779,6 +778,8 @@ void __init initmem_init(unsigned long s
+ #ifdef CONFIG_FLATMEM
+ 	max_mapnr = num_physpages;
+ #endif
++	__vmalloc_start_set = true;
++
+ 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+ 			pages_to_mb(max_low_pfn));
+ 
+@@ -800,40 +801,70 @@ static void __init zone_sizes_init(void)
+ 	free_area_init_nodes(max_zone_pfns);
+ }
+ 
++static unsigned long __init setup_node_bootmem(int nodeid,
++				 unsigned long start_pfn,
++				 unsigned long end_pfn,
++				 unsigned long bootmap)
++{
++	unsigned long bootmap_size;
++
++	/* don't touch min_low_pfn */
++	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
++					 bootmap >> PAGE_SHIFT,
++					 start_pfn, end_pfn);
++	printk(KERN_INFO "  node %d low ram: %08lx - %08lx\n",
++		nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
++	printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
++		 nodeid, bootmap, bootmap + bootmap_size);
++	free_bootmem_with_active_regions(nodeid, end_pfn);
++	early_res_to_bootmem(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
++
++	return bootmap + bootmap_size;
++}
++
+ void __init setup_bootmem_allocator(void)
+ {
+-	int i;
++	int nodeid;
+ 	unsigned long bootmap_size, bootmap;
+-	unsigned long end_pfn = min(max_low_pfn, xen_start_info->nr_pages);
++	unsigned long end_xen_pfn = min(max_low_pfn, xen_start_info->nr_pages);
+ 
+ 	/*
+ 	 * Initialize the boot-time allocator (with low memory only):
+ 	 */
+-	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+-	bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT,
+-				 min(max_pfn_mapped, xen_start_info->nr_pages)<<PAGE_SHIFT,
++	bootmap_size = bootmem_bootmap_pages(end_xen_pfn)<<PAGE_SHIFT;
++	bootmap = find_e820_area(0, min(max_pfn_mapped,
++				        xen_start_info->nr_pages)<<PAGE_SHIFT,
+ 				 bootmap_size, PAGE_SIZE);
+ 	if (bootmap == -1L)
+ 		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+ 	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
+ 
+-	/* don't touch min_low_pfn */
+-	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
+-					 min_low_pfn, end_pfn);
+ 	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
+ 		 max_pfn_mapped<<PAGE_SHIFT);
+-	printk(KERN_INFO "  low ram: %08lx - %08lx\n",
+-		 min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT);
+-	printk(KERN_INFO "  bootmap %08lx - %08lx\n",
+-		 bootmap, bootmap + bootmap_size);
+-	for_each_online_node(i)
+-		free_bootmem_with_active_regions(i, end_pfn);
+-	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
++	printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
+ 
+-	after_init_bootmem = 1;
++	for_each_online_node(nodeid) {
++		 unsigned long start_pfn, end_pfn;
++
++#ifdef CONFIG_NEED_MULTIPLE_NODES
++		start_pfn = node_start_pfn[nodeid];
++		end_pfn = node_end_pfn[nodeid];
++		if (start_pfn > end_xen_pfn)
++			continue;
++		if (end_pfn > end_xen_pfn)
++			end_pfn = end_xen_pfn;
++#else
++		start_pfn = 0;
++		end_pfn = end_xen_pfn;
++#endif
++		bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
++						 bootmap);
++	}
++
++	after_bootmem = 1;
+ }
+ 
+-static unsigned long __init extend_init_mapping(unsigned long tables_space)
++unsigned long __init extend_init_mapping(unsigned long tables_space)
+ {
+ 	unsigned long start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT)
+ 				  + xen_start_info->nr_pt_frames;
+@@ -885,133 +916,6 @@ static unsigned long __init extend_init_
+ 	return start_pfn;
+ }
+ 
+-static void __init find_early_table_space(unsigned long end, int use_pse)
+-{
+-	unsigned long puds, pmds, ptes, tables;
+-
+-	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+-	tables = PAGE_ALIGN(puds * sizeof(pud_t));
+-
+-	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+-	tables += PAGE_ALIGN(pmds * sizeof(pmd_t));
+-
+-	if (use_pse) {
+-		unsigned long extra;
+-
+-		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+-		extra += PMD_SIZE;
+-		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-	} else
+-		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-
+-	tables += PAGE_ALIGN(ptes * sizeof(pte_t));
+-
+-	/* for fixmap */
+-	tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t));
+-
+-	table_start = extend_init_mapping(tables);
+-
+-	table_end = table_start;
+-	table_top = table_start + (tables>>PAGE_SHIFT);
+-
+-	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
+-		end, table_start << PAGE_SHIFT,
+-		(table_start << PAGE_SHIFT) + tables);
+-}
+-
+-unsigned long __init_refok init_memory_mapping(unsigned long start,
+-						unsigned long end)
+-{
+-	pgd_t *pgd_base = swapper_pg_dir;
+-	unsigned long start_pfn, end_pfn;
+-	unsigned long big_page_start;
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	/*
+-	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+-	 * This will simplify cpa(), which otherwise needs to support splitting
+-	 * large pages into small in interrupt context, etc.
+-	 */
+-	int use_pse = 0;
+-#else
+-	int use_pse = cpu_has_pse;
+-#endif
+-
+-	/*
+-	 * Find space for the kernel direct mapping tables.
+-	 */
+-	if (!after_init_bootmem)
+-		find_early_table_space(end, use_pse);
+-
+-#ifdef CONFIG_X86_PAE
+-	set_nx();
+-	if (nx_enabled)
+-		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+-#endif
+-
+-	/* Enable PSE if available */
+-	if (cpu_has_pse)
+-		set_in_cr4(X86_CR4_PSE);
+-
+-	/* Enable PGE if available */
+-	if (cpu_has_pge) {
+-		set_in_cr4(X86_CR4_PGE);
+-		__supported_pte_mask |= _PAGE_GLOBAL;
+-	}
+-
+-	/*
+-	 * Don't use a large page for the first 2/4MB of memory
+-	 * because there are often fixed size MTRRs in there
+-	 * and overlapping MTRRs into large pages can cause
+-	 * slowdowns.
+-	 */
+-	big_page_start = PMD_SIZE;
+-
+-	if (start < big_page_start) {
+-		start_pfn = start >> PAGE_SHIFT;
+-		end_pfn = min(big_page_start>>PAGE_SHIFT, end>>PAGE_SHIFT);
+-	} else {
+-		/* head is not big page alignment ? */
+-		start_pfn = start >> PAGE_SHIFT;
+-		end_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
+-				 << (PMD_SHIFT - PAGE_SHIFT);
+-	}
+-	if (start_pfn < end_pfn)
+-		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, 0);
+-
+-	/* big page range */
+-	start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
+-			 << (PMD_SHIFT - PAGE_SHIFT);
+-	if (start_pfn < (big_page_start >> PAGE_SHIFT))
+-		start_pfn =  big_page_start >> PAGE_SHIFT;
+-	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+-	if (start_pfn < end_pfn)
+-		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn,
+-					     use_pse);
+-
+-	/* tail is not big page alignment ? */
+-	start_pfn = end_pfn;
+-	if (start_pfn > (big_page_start>>PAGE_SHIFT)) {
+-		end_pfn = end >> PAGE_SHIFT;
+-		if (start_pfn < end_pfn)
+-			kernel_physical_mapping_init(pgd_base, start_pfn,
+-							 end_pfn, 0);
+-	}
+-
+-	early_ioremap_page_table_range_init(pgd_base);
+-
+-	__flush_tlb_all();
+-
+-	if (!after_init_bootmem)
+-		reserve_early(table_start << PAGE_SHIFT,
+-			      table_end << PAGE_SHIFT, "PGTABLE");
+-
+-	if (!after_init_bootmem)
+-		early_memtest(start, end);
+-
+-	return end >> PAGE_SHIFT;
+-}
+-
+-
+ /*
+  * paging_init() sets up the page tables - note that the first 8MB are
+  * already mapped by head.S.
+@@ -1215,17 +1119,47 @@ static noinline int do_test_wp_bit(void)
+ const int rodata_test_data = 0xC3;
+ EXPORT_SYMBOL_GPL(rodata_test_data);
+ 
++static int kernel_set_to_readonly;
++
++void set_kernel_text_rw(void)
++{
++	unsigned long start = PFN_ALIGN(_text);
++	unsigned long size = PFN_ALIGN(_etext) - start;
++
++	if (!kernel_set_to_readonly)
++		return;
++
++	pr_debug("Set kernel text: %lx - %lx for read write\n",
++		 start, start+size);
++
++	set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
++}
++
++void set_kernel_text_ro(void)
++{
++	unsigned long start = PFN_ALIGN(_text);
++	unsigned long size = PFN_ALIGN(_etext) - start;
++
++	if (!kernel_set_to_readonly)
++		return;
++
++	pr_debug("Set kernel text: %lx - %lx for read only\n",
++		 start, start+size);
++
++	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++}
++
+ void mark_rodata_ro(void)
+ {
+ 	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long size = PFN_ALIGN(_etext) - start;
+ 
+-#ifndef CONFIG_DYNAMIC_FTRACE
+-	/* Dynamic tracing modifies the kernel text section */
+ 	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+ 	printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+ 		size >> 10);
+ 
++	kernel_set_to_readonly = 1;
++
+ #ifdef CONFIG_CPA_DEBUG
+ 	printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
+ 		start, start+size);
+@@ -1234,7 +1168,6 @@ void mark_rodata_ro(void)
+ 	printk(KERN_INFO "Testing CPA: write protecting again\n");
+ 	set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+ #endif
+-#endif /* CONFIG_DYNAMIC_FTRACE */
+ 
+ 	start += size;
+ 	size = (unsigned long)__end_rodata - start;
+@@ -1253,52 +1186,6 @@ void mark_rodata_ro(void)
+ }
+ #endif
+ 
+-void free_init_pages(char *what, unsigned long begin, unsigned long end)
+-{
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	/*
+-	 * If debugging page accesses then do not free this memory but
+-	 * mark them not present - any buggy init-section access will
+-	 * create a kernel page fault:
+-	 */
+-	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
+-		begin, PAGE_ALIGN(end));
+-	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
+-#else
+-	unsigned long addr;
+-
+-	/*
+-	 * We just marked the kernel text read only above, now that
+-	 * we are going to free part of that, we need to make that
+-	 * writeable first.
+-	 */
+-	set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
+-
+-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+-		ClearPageReserved(virt_to_page(addr));
+-		init_page_count(virt_to_page(addr));
+-		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
+-		free_page(addr);
+-		totalram_pages++;
+-	}
+-	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
+-#endif
+-}
+-
+-void free_initmem(void)
+-{
+-	free_init_pages("unused kernel memory",
+-			(unsigned long)(&__init_begin),
+-			(unsigned long)(&__init_end));
+-}
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-void free_initrd_mem(unsigned long start, unsigned long end)
+-{
+-	free_init_pages("initrd memory", start, end);
+-}
+-#endif
+-
+ int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+ 				   int flags)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -51,6 +51,8 @@
+ #include <asm/kdebug.h>
+ #include <asm/numa.h>
+ #include <asm/cacheflush.h>
++#include <asm/init.h>
++#include <asm/setup.h>
+ 
+ #include <xen/features.h>
+ 
+@@ -67,8 +69,6 @@ unsigned int __kernel_page_user;
+ EXPORT_SYMBOL(__kernel_page_user);
+ #endif
+ 
+-int after_bootmem;
+-
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ 
+ extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
+@@ -127,12 +127,6 @@ void __meminit early_make_page_readonly(
+ }
+ 
+ #ifndef CONFIG_XEN
+-int direct_gbpages
+-#ifdef CONFIG_DIRECT_GBPAGES
+-				= 1
+-#endif
+-;
+-
+ static int __init parse_direct_gbpages_off(char *arg)
+ {
+ 	direct_gbpages = 0;
+@@ -154,14 +148,10 @@ early_param("gbpages", parse_direct_gbpa
+  * around without checking the pgd every time.
+  */
+ 
+-static unsigned long __meminitdata table_start;
+-static unsigned long __meminitdata table_cur;
+-static unsigned long __meminitdata table_top;
+-
+ pteval_t __supported_pte_mask __read_mostly = ~0UL;
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+-static int do_not_nx __cpuinitdata;
++static int disable_nx __cpuinitdata;
+ 
+ /*
+  * noexec=on|off
+@@ -176,9 +166,9 @@ static int __init nonx_setup(char *str)
+ 		return -EINVAL;
+ 	if (!strncmp(str, "on", 2)) {
+ 		__supported_pte_mask |= _PAGE_NX;
+-		do_not_nx = 0;
++		disable_nx = 0;
+ 	} else if (!strncmp(str, "off", 3)) {
+-		do_not_nx = 1;
++		disable_nx = 1;
+ 		__supported_pte_mask &= ~_PAGE_NX;
+ 	}
+ 	return 0;
+@@ -190,7 +180,7 @@ void __cpuinit check_efer(void)
+ 	unsigned long efer;
+ 
+ 	rdmsrl(MSR_EFER, efer);
+-	if (!(efer & EFER_NX) || do_not_nx)
++	if (!(efer & EFER_NX) || disable_nx)
+ 		__supported_pte_mask &= ~_PAGE_NX;
+ }
+ 
+@@ -224,9 +214,9 @@ static __ref void *spp_getpage(void)
+ 
+ 	if (after_bootmem)
+ 		ptr = (void *) get_zeroed_page(GFP_ATOMIC);
+-	else if (table_cur < table_top) {
+-		ptr = __va(table_cur << PAGE_SHIFT);
+-		table_cur++;
++	else if (e820_table_end < e820_table_top) {
++		ptr = __va(e820_table_end << PAGE_SHIFT);
++		e820_table_end++;
+ 		memset(ptr, 0, PAGE_SIZE);
+ 	} else
+ 		ptr = alloc_bootmem_pages(PAGE_SIZE);
+@@ -241,36 +231,54 @@ static __ref void *spp_getpage(void)
+ 	return ptr;
+ }
+ 
+-void
+-set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte)
++static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr)
+ {
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
++	if (pgd_none(*pgd)) {
++		pud_t *pud = (pud_t *)spp_getpage();
++		make_page_readonly(pud, XENFEAT_writable_page_tables);
++		pgd_populate(&init_mm, pgd, pud);
++		if (pud != pud_offset(pgd, 0))
++			printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n",
++			       pud, pud_offset(pgd, 0));
++	}
++	return pud_offset(pgd, vaddr);
++}
+ 
+-	pud = pud_page + pud_index(vaddr);
++static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr)
++{
+ 	if (pud_none(*pud)) {
+-		pmd = (pmd_t *) spp_getpage();
++		pmd_t *pmd = (pmd_t *) spp_getpage();
+ 		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 		pud_populate(&init_mm, pud, pmd);
+-		if (pmd != pmd_offset(pud, 0)) {
++		if (pmd != pmd_offset(pud, 0))
+ 			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
+-				pmd, pmd_offset(pud, 0));
+-			return;
+-		}
++			       pmd, pmd_offset(pud, 0));
+ 	}
+-	pmd = pmd_offset(pud, vaddr);
++	return pmd_offset(pud, vaddr);
++}
++
++static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr)
++{
+ 	if (pmd_none(*pmd)) {
+-		pte = (pte_t *) spp_getpage();
++		pte_t *pte = (pte_t *) spp_getpage();
+ 		make_page_readonly(pte, XENFEAT_writable_page_tables);
+ 		pmd_populate_kernel(&init_mm, pmd, pte);
+-		if (pte != pte_offset_kernel(pmd, 0)) {
++		if (pte != pte_offset_kernel(pmd, 0))
+ 			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+-			return;
+-		}
+ 	}
++	return pte_offset_kernel(pmd, vaddr);
++}
++
++void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte)
++{
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	pud = pud_page + pud_index(vaddr);
++	pmd = fill_pmd(pud, vaddr);
++	pte = fill_pte(pmd, vaddr);
+ 
+-	pte = pte_offset_kernel(pmd, vaddr);
+ 	set_pte(pte, new_pte);
+ 
+ 	/*
+@@ -280,8 +288,7 @@ set_pte_vaddr_pud(pud_t *pud_page, unsig
+ 	__flush_tlb_one(vaddr);
+ }
+ 
+-void
+-set_pte_vaddr(unsigned long vaddr, pte_t pteval)
++void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
+ {
+ 	pgd_t *pgd;
+ 	pud_t *pud_page;
+@@ -298,6 +305,24 @@ set_pte_vaddr(unsigned long vaddr, pte_t
+ 	set_pte_vaddr_pud(pud_page, vaddr, pteval);
+ }
+ 
++pmd_t * __init populate_extra_pmd(unsigned long vaddr)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++
++	pgd = pgd_offset_k(vaddr);
++	pud = fill_pud(pgd, vaddr);
++	return fill_pmd(pud, vaddr);
++}
++
++pte_t * __init populate_extra_pte(unsigned long vaddr)
++{
++	pmd_t *pmd;
++
++	pmd = populate_extra_pmd(vaddr);
++	return fill_pte(pmd, vaddr);
++}
++
+ #ifndef CONFIG_XEN
+ /*
+  * Create large page table mappings for a range of physical addresses.
+@@ -380,9 +405,9 @@ static __ref void *alloc_low_page(unsign
+ 		return adr;
+ 	}
+ 
+-	BUG_ON(!table_cur);
+-	pfn = table_cur++;
+-	if (pfn >= table_top)
++	BUG_ON(!e820_table_end);
++	pfn = e820_table_end++;
++	if (pfn >= e820_table_top)
+ 		panic("alloc_low_page: ran out of memory");
+ 
+ 	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
+@@ -407,13 +432,13 @@ static inline int __meminit make_readonl
+ 	/* Make new page tables read-only on the first pass. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
+ 	    && !max_pfn_mapped
+-	    && (paddr >= (table_start << PAGE_SHIFT))
+-	    && (paddr < (table_top << PAGE_SHIFT)))
++	    && (paddr >= (e820_table_start << PAGE_SHIFT))
++	    && (paddr < (e820_table_top << PAGE_SHIFT)))
+ 		readonly = 1;
+ 	/* Make old page tables read-only. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
+ 	    && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+-	    && (paddr < (table_cur << PAGE_SHIFT)))
++	    && (paddr < (e820_table_end << PAGE_SHIFT)))
+ 		readonly = 1;
+ 
+ 	/*
+@@ -422,7 +447,7 @@ static inline int __meminit make_readonl
+ 	 * mappings. Exclude the vsyscall area here, allowing alternative
+ 	 * instruction patching to work.
+ 	 */
+-	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end))
++	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa(_brk_end))
+ 	    && !(paddr >= __pa_symbol(&__vsyscall_0)
+ 	         && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE))
+ 		readonly = 1;
+@@ -747,43 +772,9 @@ void __init xen_init_pt(void)
+ 	}
+ }
+ 
+-static void __init find_early_table_space(unsigned long end, int use_pse,
+-					  int use_gbpages)
+-{
+-	unsigned long puds, pmds, ptes, tables;
+-
+-	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+-	tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
+-	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+-	tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
+-
+-	ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+-	tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE);
+-
+-	if (!table_top) {
+-		table_start = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
+-			xen_start_info->nr_pt_frames;
+-		table_cur = table_start;
+-	} else {
+-		/*
+-		 * [table_start, table_top) gets passed to reserve_early(),
+-		 * so we must not use table_cur here, despite continuing
+-		 * to allocate from there. table_cur possibly being below
+-		 * table_start is otoh not a problem.
+-		 */
+-		table_start = table_top;
+-	}
+-	__flush_tlb_all();
+-
+-	table_top = table_cur + (tables >> PAGE_SHIFT);
+-
+-	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
+-		end, table_cur << PAGE_SHIFT, table_top << PAGE_SHIFT);
+-}
+-
+-static void __init xen_finish_init_mapping(void)
++void __init xen_finish_init_mapping(void)
+ {
+-	unsigned long i, start, end;
++	unsigned long start, end;
+ 
+ 	/* Re-vector virtual addresses pointing into the initial
+ 	   mapping to the just-established permanent ones. */
+@@ -801,49 +792,22 @@ static void __init xen_finish_init_mappi
+ 			__va(__pa(xen_start_info->mod_start));
+ 
+ 	/* Destroy the Xen-created mappings beyond the kernel image. */
+-	start = PAGE_ALIGN((unsigned long)_end);
+-	end   = __START_KERNEL_map + (table_start << PAGE_SHIFT);
++	start = PAGE_ALIGN(_brk_end);
++	end   = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT);
+ 	for (; start < end; start += PAGE_SIZE)
+ 		if (HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0))
+ 			BUG();
+ 
+-	/* Allocate pte's for initial fixmaps from 'table_cur' allocator. */
+-	start = table_top;
+-	WARN(table_cur != start, "start=%lx cur=%lx top=%lx\n",
+-	     table_start, table_cur, start);
+-	table_top = ~0UL;
+-
+-	/* Switch to the real shared_info page, and clear the dummy page. */
+-	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+-	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+-	memset(empty_zero_page, 0, sizeof(empty_zero_page));
+-
+-	/* Set up mapping of lowest 1MB of physical memory. */
+-	for (i = 0; i < NR_FIX_ISAMAPS; i++)
+-		if (is_initial_xendomain())
+-			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
+-		else
+-			__set_fixmap(FIX_ISAMAP_BEGIN - i,
+-				     virt_to_mfn(empty_zero_page)
+-				     << PAGE_SHIFT,
+-				     PAGE_KERNEL_RO);
+-
+-	table_top = max(table_cur, start);
+-}
+-
+-static void __init init_gbpages(void)
+-{
+-#ifndef CONFIG_XEN
+-	if (direct_gbpages && cpu_has_gbpages)
+-		printk(KERN_INFO "Using GB pages for direct mapping\n");
+-	else
+-		direct_gbpages = 0;
+-#endif
++	WARN(e820_table_end != e820_table_top, "start=%lx cur=%lx top=%lx\n",
++	     e820_table_start, e820_table_end, e820_table_top);
++	if (e820_table_end > e820_table_top)
++		e820_table_top = e820_table_end;
+ }
+ 
+-static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
+-						unsigned long end,
+-						unsigned long page_size_mask)
++unsigned long __init
++kernel_physical_mapping_init(unsigned long start,
++			     unsigned long end,
++			     unsigned long page_size_mask)
+ {
+ 
+ 	unsigned long next, last_map_addr = end;
+@@ -887,207 +851,6 @@ static unsigned long __meminit kernel_ph
+ 	return last_map_addr;
+ }
+ 
+-struct map_range {
+-	unsigned long start;
+-	unsigned long end;
+-	unsigned page_size_mask;
+-};
+-
+-#define NR_RANGE_MR 5
+-
+-static int save_mr(struct map_range *mr, int nr_range,
+-		   unsigned long start_pfn, unsigned long end_pfn,
+-		   unsigned long page_size_mask)
+-{
+-
+-	if (start_pfn < end_pfn) {
+-		if (nr_range >= NR_RANGE_MR)
+-			panic("run out of range for init_memory_mapping\n");
+-		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
+-		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
+-		mr[nr_range].page_size_mask = page_size_mask;
+-		nr_range++;
+-	}
+-
+-	return nr_range;
+-}
+-
+-/*
+- * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+- * This runs before bootmem is initialized and gets pages directly from
+- * the physical memory. To access them they are temporarily mapped.
+- */
+-unsigned long __init_refok init_memory_mapping(unsigned long start,
+-					       unsigned long end)
+-{
+-	unsigned long last_map_addr = 0;
+-	unsigned long page_size_mask = 0;
+-	unsigned long start_pfn, end_pfn;
+-	unsigned long pos;
+-
+-	struct map_range mr[NR_RANGE_MR];
+-	int nr_range, i;
+-	int use_pse, use_gbpages;
+-
+-	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
+-
+-	/*
+-	 * Find space for the kernel direct mapping tables.
+-	 *
+-	 * Later we should allocate these tables in the local node of the
+-	 * memory mapped. Unfortunately this is done currently before the
+-	 * nodes are discovered.
+-	 */
+-	if (!after_bootmem)
+-		init_gbpages();
+-
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	/*
+-	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+-	 * This will simplify cpa(), which otherwise needs to support splitting
+-	 * large pages into small in interrupt context, etc.
+-	 */
+-	use_pse = use_gbpages = 0;
+-#else
+-	use_pse = cpu_has_pse;
+-	use_gbpages = direct_gbpages;
+-#endif
+-
+-	if (use_gbpages)
+-		page_size_mask |= 1 << PG_LEVEL_1G;
+-	if (use_pse)
+-		page_size_mask |= 1 << PG_LEVEL_2M;
+-
+-	memset(mr, 0, sizeof(mr));
+-	nr_range = 0;
+-
+-	/* head if not big page alignment ?*/
+-	start_pfn = start >> PAGE_SHIFT;
+-	pos = start_pfn << PAGE_SHIFT;
+-	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
+-			<< (PMD_SHIFT - PAGE_SHIFT);
+-	if (end_pfn > (end >> PAGE_SHIFT))
+-		end_pfn = end >> PAGE_SHIFT;
+-	if (start_pfn < end_pfn) {
+-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+-		pos = end_pfn << PAGE_SHIFT;
+-	}
+-
+-	/* big page (2M) range*/
+-	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+-			 << (PMD_SHIFT - PAGE_SHIFT);
+-	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+-			 << (PUD_SHIFT - PAGE_SHIFT);
+-	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
+-		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
+-	if (start_pfn < end_pfn) {
+-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+-				page_size_mask & (1<<PG_LEVEL_2M));
+-		pos = end_pfn << PAGE_SHIFT;
+-	}
+-
+-	/* big page (1G) range */
+-	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+-			 << (PUD_SHIFT - PAGE_SHIFT);
+-	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
+-	if (start_pfn < end_pfn) {
+-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+-				page_size_mask &
+-				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
+-		pos = end_pfn << PAGE_SHIFT;
+-	}
+-
+-	/* tail is not big page (1G) alignment */
+-	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+-			 << (PMD_SHIFT - PAGE_SHIFT);
+-	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+-	if (start_pfn < end_pfn) {
+-		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+-				page_size_mask & (1<<PG_LEVEL_2M));
+-		pos = end_pfn << PAGE_SHIFT;
+-	}
+-
+-	/* tail is not big page (2M) alignment */
+-	start_pfn = pos>>PAGE_SHIFT;
+-	end_pfn = end>>PAGE_SHIFT;
+-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+-
+-	/* try to merge same page size and continuous */
+-	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
+-		unsigned long old_start;
+-		if (mr[i].end != mr[i+1].start ||
+-		    mr[i].page_size_mask != mr[i+1].page_size_mask)
+-			continue;
+-		/* move it */
+-		old_start = mr[i].start;
+-		memmove(&mr[i], &mr[i+1],
+-			 (nr_range - 1 - i) * sizeof (struct map_range));
+-		mr[i--].start = old_start;
+-		nr_range--;
+-	}
+-
+-	for (i = 0; i < nr_range; i++)
+-		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
+-				mr[i].start, mr[i].end,
+-			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
+-			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
+-
+-	if (!after_bootmem)
+-		find_early_table_space(end, use_pse, use_gbpages);
+-
+-	if (!start) {
+-		unsigned long addr, va = __START_KERNEL_map;
+-		unsigned long *page = (unsigned long *)init_level4_pgt;
+-
+-		/* Kill mapping of memory below _text. */
+-		while (va < (unsigned long)&_text) {
+-			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+-				BUG();
+-			va += PAGE_SIZE;
+-		}
+-
+-		/* Blow away any spurious initial mappings. */
+-		va = __START_KERNEL_map + (table_start << PAGE_SHIFT);
+-		addr = page[pgd_index(va)];
+-		addr_to_page(addr, page);
+-		addr = page[pud_index(va)];
+-		addr_to_page(addr, page);
+-		while (pmd_index(va) | pte_index(va)) {
+-			if (pmd_none(*(pmd_t *)&page[pmd_index(va)]))
+-				break;
+-			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+-				BUG();
+-			va += PAGE_SIZE;
+-		}
+-	}
+-
+-	for (i = 0; i < nr_range; i++)
+-		last_map_addr = kernel_physical_mapping_init(
+-					mr[i].start, mr[i].end,
+-					mr[i].page_size_mask);
+-
+-	BUG_ON(table_cur > table_top);
+-	if (!start)
+-		xen_finish_init_mapping();
+-	else if (table_cur < table_top)
+-		/* Disable the 'table_cur' allocator. */
+-		table_top = table_cur;
+-
+-	__flush_tlb_all();
+-
+-	if (!after_bootmem && table_top > table_start)
+-		reserve_early(table_start << PAGE_SHIFT,
+-			      table_top << PAGE_SHIFT, "PGTABLE");
+-
+-	printk(KERN_INFO "last_map_addr: %lx end: %lx\n",
+-			 last_map_addr, end);
+-
+-	if (!after_bootmem)
+-		early_memtest(start, end);
+-
+-	return last_map_addr >> PAGE_SHIFT;
+-}
+-
+ #ifndef CONFIG_NUMA
+ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+ {
+@@ -1165,28 +928,6 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
+ 
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
+-/*
+- * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+- * is valid. The argument is a physical page number.
+- *
+- *
+- * On x86, access has to be given to the first megabyte of ram because that area
+- * contains bios code and data regions used by X and dosemu and similar apps.
+- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+- * mmio resources as well as potential bios/acpi data regions.
+- */
+-int devmem_is_allowed(unsigned long pagenr)
+-{
+-	if (pagenr <= 256)
+-		return 1;
+-	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+-		return 0;
+-	if (mfn_to_local_pfn(pagenr) >= max_pfn)
+-		return 1;
+-	return 0;
+-}
+-
+-
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
+ 			 kcore_modules, kcore_vsyscall;
+ 
+@@ -1243,56 +984,39 @@ void __init mem_init(void)
+ 		initsize >> 10);
+ }
+ 
+-void free_init_pages(char *what, unsigned long begin, unsigned long end)
++#ifdef CONFIG_DEBUG_RODATA
++const int rodata_test_data = 0xC3;
++EXPORT_SYMBOL_GPL(rodata_test_data);
++
++static int kernel_set_to_readonly;
++
++void set_kernel_text_rw(void)
+ {
+-	unsigned long addr = begin;
++	unsigned long start = PFN_ALIGN(_stext);
++	unsigned long end = PFN_ALIGN(__start_rodata);
+ 
+-	if (addr >= end)
++	if (!kernel_set_to_readonly)
+ 		return;
+ 
+-	/*
+-	 * If debugging page accesses then do not free this memory but
+-	 * mark them not present - any buggy init-section access will
+-	 * create a kernel page fault:
+-	 */
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
+-		begin, PAGE_ALIGN(end));
+-	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
+-#else
+-	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
++	pr_debug("Set kernel text: %lx - %lx for read write\n",
++		 start, end);
+ 
+-	for (; addr < end; addr += PAGE_SIZE) {
+-		ClearPageReserved(virt_to_page(addr));
+-		init_page_count(virt_to_page(addr));
+-		memset((void *)(addr & ~(PAGE_SIZE-1)),
+-		       POISON_FREE_INITMEM, PAGE_SIZE); 
+-		if (addr >= __START_KERNEL_map) {
+-			/* make_readonly() reports all kernel addresses. */
+-			if (HYPERVISOR_update_va_mapping((unsigned long)__va(__pa(addr)),
+-							 pfn_pte(__pa(addr) >> PAGE_SHIFT,
+-								 PAGE_KERNEL),
+-							 0))
+-				BUG();
+-			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
+-				BUG();
+-		}
+-		free_page(addr);
+-		totalram_pages++;
+-	}
+-#endif
++	set_memory_rw(start, (end - start) >> PAGE_SHIFT);
+ }
+ 
+-void free_initmem(void)
++void set_kernel_text_ro(void)
+ {
+-	free_init_pages("unused kernel memory",
+-			(unsigned long)(&__init_begin),
+-			(unsigned long)(&__init_end));
+-}
++	unsigned long start = PFN_ALIGN(_stext);
++	unsigned long end = PFN_ALIGN(__start_rodata);
+ 
+-#ifdef CONFIG_DEBUG_RODATA
+-const int rodata_test_data = 0xC3;
+-EXPORT_SYMBOL_GPL(rodata_test_data);
++	if (!kernel_set_to_readonly)
++		return;
++
++	pr_debug("Set kernel text: %lx - %lx for read only\n",
++		 start, end);
++
++	set_memory_ro(start, (end - start) >> PAGE_SHIFT);
++}
+ 
+ void mark_rodata_ro(void)
+ {
+@@ -1300,15 +1024,12 @@ void mark_rodata_ro(void)
+ 	unsigned long rodata_start =
+ 		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+ 
+-#ifdef CONFIG_DYNAMIC_FTRACE
+-	/* Dynamic tracing modifies the kernel text section */
+-	start = rodata_start;
+-#endif
+-
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
+ 	set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+ 
++	kernel_set_to_readonly = 1;
++
+ 	/*
+ 	 * The rodata section (but not the kernel text!) should also be
+ 	 * not-executable.
+@@ -1328,13 +1049,6 @@ void mark_rodata_ro(void)
+ 
+ #endif
+ 
+-#ifdef CONFIG_BLK_DEV_INITRD
+-void free_initrd_mem(unsigned long start, unsigned long end)
+-{
+-	free_init_pages("initrd memory", start, end);
+-}
+-#endif
+-
+ int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+ 				   int flags)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -20,10 +20,11 @@
+ #include <asm/pat.h>
+ #include <linux/bitops.h>
+ #include <linux/module.h>
++#include <linux/highmem.h>
+ 
+ int is_io_mapping_possible(resource_size_t base, unsigned long size)
+ {
+-#ifndef CONFIG_X86_PAE
++#if !defined(CONFIG_X86_PAE) && defined(CONFIG_PHYS_ADDR_T_64BIT)
+ 	/* There is no way to map greater than 1 << 32 address without PAE */
+ 	if (base + size > 0x100000000ULL)
+ 		return 0;
+@@ -32,16 +33,28 @@ int is_io_mapping_possible(resource_size
+ }
+ EXPORT_SYMBOL_GPL(is_io_mapping_possible);
+ 
+-/* Map 'mfn' using fixed map 'type' and protections 'prot'
+- */
+-void *
+-iomap_atomic_prot_pfn(unsigned long mfn, enum km_type type, pgprot_t prot)
++void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+ {
+ 	enum fixed_addresses idx;
+ 	unsigned long vaddr;
+ 
+ 	pagefault_disable();
+ 
++	debug_kmap_atomic(type);
++	idx = type + KM_TYPE_NR * smp_processor_id();
++	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++	set_pte_at(&init_mm, vaddr, kmap_pte - idx, pfn_pte(pfn, prot));
++	/*arch_flush_lazy_mmu_mode();*/
++
++	return (void *)vaddr;
++}
++
++/*
++ * Map 'mfn' using fixed map 'type' and protections 'prot'
++ */
++void *
++iomap_atomic_prot_pfn(unsigned long mfn, enum km_type type, pgprot_t prot)
++{
+ 	/*
+ 	 * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
+ 	 * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
+@@ -51,13 +64,8 @@ iomap_atomic_prot_pfn(unsigned long mfn,
+ 	if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
+ 		prot = PAGE_KERNEL_UC_MINUS;
+ 
+-	idx = type + KM_TYPE_NR*smp_processor_id();
+-	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	pgprot_val(prot) |= _PAGE_IOMAP;
+-	set_pte_at(&init_mm, vaddr, kmap_pte-idx, pfn_pte_ma(mfn, prot));
+-	/*arch_flush_lazy_mmu_mode()*/;
+-
+-	return (void*) vaddr;
++	return kmap_atomic_prot_pfn(mfn, type, prot);
+ }
+ EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
+ 
+--- head-2010-01-18.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -23,13 +23,17 @@
+ #include <asm/pgalloc.h>
+ #include <asm/pat.h>
+ 
+-#ifdef CONFIG_X86_64
+-
+-static inline int phys_addr_valid(unsigned long addr)
++static inline int phys_addr_valid(resource_size_t addr)
+ {
+-	return addr < (1UL << boot_cpu_data.x86_phys_bits);
++#ifdef CONFIG_PHYS_ADDR_T_64BIT
++	return !(addr >> boot_cpu_data.x86_phys_bits);
++#else
++	return 1;
++#endif
+ }
+ 
++#ifdef CONFIG_X86_64
++
+ #define phys_base 0
+ 
+ unsigned long __phys_addr(unsigned long x)
+@@ -41,8 +45,7 @@ unsigned long __phys_addr(unsigned long 
+ 	} else {
+ 		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
+ 		x -= PAGE_OFFSET;
+-		VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM :
+-					!phys_addr_valid(x));
++		VIRTUAL_BUG_ON(!phys_addr_valid(x));
+ 	}
+ 	return x;
+ }
+@@ -59,10 +62,8 @@ bool __virt_addr_valid(unsigned long x)
+ 		if (x < PAGE_OFFSET)
+ 			return false;
+ 		x -= PAGE_OFFSET;
+-		if (system_state == SYSTEM_BOOTING ?
+-				x > MAXMEM : !phys_addr_valid(x)) {
++		if (!phys_addr_valid(x))
+ 			return false;
+-		}
+ 	}
+ 
+ 	return pfn_valid(x >> PAGE_SHIFT);
+@@ -73,18 +74,12 @@ EXPORT_SYMBOL(__virt_addr_valid);
+ 
+ #else
+ 
+-static inline int phys_addr_valid(unsigned long addr)
+-{
+-	return 1;
+-}
+-
+ #ifdef CONFIG_DEBUG_VIRTUAL
+ unsigned long __phys_addr(unsigned long x)
+ {
+-	/* VMALLOC_* aren't constants; not available at the boot time */
++	/* VMALLOC_* aren't constants  */
+ 	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
+-	VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING &&
+-		is_vmalloc_addr((void *) x));
++	VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
+ 	return x - PAGE_OFFSET;
+ }
+ EXPORT_SYMBOL(__phys_addr);
+@@ -94,7 +89,9 @@ bool __virt_addr_valid(unsigned long x)
+ {
+ 	if (x < PAGE_OFFSET)
+ 		return false;
+-	if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x))
++	if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
++		return false;
++	if (x >= FIXADDR_START)
+ 		return false;
+ 	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
+ }
+@@ -462,16 +459,17 @@ static void __iomem *__ioremap_caller(re
+ 		return NULL;
+ 	area->phys_addr = phys_addr;
+ 	vaddr = (unsigned long) area->addr;
+-	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
+-				     size, prot, domid)) {
++
++	if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
+ 		free_memtype(phys_addr, phys_addr + size);
+ 		free_vm_area(area);
+ 		return NULL;
+ 	}
+ 
+-	if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
++	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
++				     size, prot, domid)) {
+ 		free_memtype(phys_addr, phys_addr + size);
+-		vunmap(area->addr);
++		free_vm_area(area);
+ 		return NULL;
+ 	}
+ 
+@@ -528,7 +526,7 @@ EXPORT_SYMBOL(ioremap_nocache);
+  *
+  * Must be freed with iounmap.
+  */
+-void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
++void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size)
+ {
+ 	if (pat_enabled)
+ 		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
+@@ -558,7 +556,8 @@ static void __iomem *ioremap_default(res
+ 	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+ 	 * - Inherit from confliting mappings otherwise
+ 	 */
+-	err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
++	err = reserve_memtype(phys_addr, phys_addr + size,
++				_PAGE_CACHE_WB, &flags);
+ 	if (err < 0)
+ 		return NULL;
+ 
+@@ -697,13 +696,19 @@ static inline pte_t * __init early_iorem
+ 	return &bm_pte[pte_index(addr)];
+ }
+ 
++static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
++
+ void __init early_ioremap_init(void)
+ {
+ 	pmd_t *pmd;
++	int i;
+ 
+ 	if (early_ioremap_debug)
+ 		printk(KERN_INFO "early_ioremap_init()\n");
+ 
++	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
++		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
++
+ 	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+ 	memset(bm_pte, 0, sizeof(bm_pte));
+ 	make_lowmem_page_readonly(bm_pte, XENFEAT_writable_page_tables);
+@@ -734,7 +739,7 @@ void __init early_ioremap_reset(void)
+ }
+ 
+ static void __init __early_set_fixmap(enum fixed_addresses idx,
+-				   unsigned long phys, pgprot_t flags)
++				      phys_addr_t phys, pgprot_t flags)
+ {
+ 	unsigned long addr = __fix_to_virt(idx);
+ 	pte_t *pte;
+@@ -753,7 +758,7 @@ static void __init __early_set_fixmap(en
+ }
+ 
+ static inline void __init early_set_fixmap(enum fixed_addresses idx,
+-					   unsigned long phys, pgprot_t prot)
++					   phys_addr_t phys, pgprot_t prot)
+ {
+ 	if (after_paging_init)
+ 		__set_fixmap(idx, phys, prot);
+@@ -771,6 +776,7 @@ static inline void __init early_clear_fi
+ 
+ static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+ static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
++
+ static int __init check_early_ioremap_leak(void)
+ {
+ 	int count = 0;
+@@ -792,9 +798,11 @@ static int __init check_early_ioremap_le
+ }
+ late_initcall(check_early_ioremap_leak);
+ 
+-static void __init __iomem *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
++static void __init __iomem *
++__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
+ {
+-	unsigned long offset, last_addr;
++	unsigned long offset;
++	resource_size_t last_addr;
+ 	unsigned int nrpages;
+ 	enum fixed_addresses idx0, idx;
+ 	int i, slot;
+@@ -810,15 +818,15 @@ static void __init __iomem *__early_iore
+ 	}
+ 
+ 	if (slot < 0) {
+-		printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n",
+-			 phys_addr, size);
++		printk(KERN_INFO "early_iomap(%08llx, %08lx) not found slot\n",
++			 (u64)phys_addr, size);
+ 		WARN_ON(1);
+ 		return NULL;
+ 	}
+ 
+ 	if (early_ioremap_debug) {
+-		printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
+-		       phys_addr, size, slot);
++		printk(KERN_INFO "early_ioremap(%08llx, %08lx) [%d] => ",
++		       (u64)phys_addr, size, slot);
+ 		dump_stack();
+ 	}
+ 
+@@ -858,20 +866,28 @@ static void __init __iomem *__early_iore
+ 		--nrpages;
+ 	}
+ 	if (early_ioremap_debug)
+-		printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
++		printk(KERN_CONT "%08lx + %08lx\n", offset, slot_virt[slot]);
+ 
+-	prev_map[slot] = (void __iomem *)(offset + fix_to_virt(idx0));
++	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
+ 	return prev_map[slot];
+ }
+ 
+ /* Remap an IO device */
+-void __init __iomem *early_ioremap(unsigned long phys_addr, unsigned long size)
++void __init __iomem *
++early_ioremap(resource_size_t phys_addr, unsigned long size)
+ {
++	/*
++	 * Don't remap the low PCI/ISA area, it's always mapped.
++	 */
++	if (is_initial_xendomain() && is_ISA_range(phys_addr, phys_addr + size - 1))
++		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
++
+ 	return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
+ }
+ 
+ /* Remap memory */
+-void __init __iomem *early_memremap(unsigned long phys_addr, unsigned long size)
++void __init __iomem *
++early_memremap(resource_size_t phys_addr, unsigned long size)
+ {
+ 	return __early_ioremap(phys_to_machine(phys_addr), size, PAGE_KERNEL);
+ }
+@@ -884,6 +900,15 @@ void __init early_iounmap(void __iomem *
+ 	enum fixed_addresses idx;
+ 	int i, slot;
+ 
++	/*
++	 * early_ioremap special-cases the PCI/ISA range by not instantiating a
++	 * vm_area and by simply returning an address into the kernel mapping
++	 * of ISA space.   So handle that here.
++	 */
++	if ((unsigned long)addr >= fix_to_virt(FIX_ISAMAP_BEGIN)
++	    && (unsigned long)addr < fix_to_virt(FIX_ISAMAP_END - 1))
++		return;
++
+ 	slot = -1;
+ 	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+ 		if (prev_map[i] == addr) {
+@@ -928,8 +953,3 @@ void __init early_iounmap(void __iomem *
+ 	}
+ 	prev_map[slot] = NULL;
+ }
+-
+-void __this_fixmap_does_not_exist(void)
+-{
+-	WARN_ON(1);
+-}
+--- head-2010-01-18.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -16,6 +16,7 @@
+ #include <asm/processor.h>
+ #include <asm/tlbflush.h>
+ #include <asm/sections.h>
++#include <asm/setup.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
+@@ -33,6 +34,7 @@ struct cpa_data {
+ 	unsigned long	pfn;
+ 	unsigned	force_split : 1;
+ 	int		curpage;
++	struct page	**pages;
+ };
+ 
+ /*
+@@ -45,6 +47,7 @@ static DEFINE_SPINLOCK(cpa_lock);
+ 
+ #define CPA_FLUSHTLB 1
+ #define CPA_ARRAY 2
++#define CPA_PAGES_ARRAY 4
+ 
+ #ifdef CONFIG_PROC_FS
+ static unsigned long direct_pages_count[PG_LEVEL_NUM];
+@@ -95,7 +98,7 @@ static inline unsigned long highmap_star
+ 
+ static inline unsigned long highmap_end_pfn(void)
+ {
+-	return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
++	return __pa(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
+ }
+ 
+ #endif
+@@ -150,7 +153,7 @@ static void __cpa_flush_all(void *arg)
+ 	 */
+ 	__flush_tlb_all();
+ 
+-	if (cache && boot_cpu_data.x86_model >= 4)
++	if (cache && boot_cpu_data.x86 >= 4)
+ 		wbinvd();
+ }
+ 
+@@ -201,38 +204,41 @@ static void cpa_flush_range(unsigned lon
+ 	}
+ }
+ 
+-static void cpa_flush_array(unsigned long *start, int numpages, int cache)
++static void cpa_flush_array(unsigned long *start, int numpages, int cache,
++			    int in_flags, struct page **pages)
+ {
+ 	unsigned int i, level;
+-	unsigned long *addr;
++	unsigned long do_wbinvd = cache && numpages >= 1024; /* 4M threshold */
+ 
+ 	BUG_ON(irqs_disabled());
+ 
+-	on_each_cpu(__cpa_flush_range, NULL, 1);
++	on_each_cpu(__cpa_flush_all, (void *) do_wbinvd, 1);
+ 
+-	if (!cache)
++	if (!cache || do_wbinvd)
+ 		return;
+ 
+-	/* 4M threshold */
+-	if (numpages >= 1024) {
+-		if (boot_cpu_data.x86_model >= 4)
+-			wbinvd();
+-		return;
+-	}
+ 	/*
+ 	 * We only need to flush on one CPU,
+ 	 * clflush is a MESI-coherent instruction that
+ 	 * will cause all other CPUs to flush the same
+ 	 * cachelines:
+ 	 */
+-	for (i = 0, addr = start; i < numpages; i++, addr++) {
+-		pte_t *pte = lookup_address(*addr, &level);
++	for (i = 0; i < numpages; i++) {
++		unsigned long addr;
++		pte_t *pte;
++
++		if (in_flags & CPA_PAGES_ARRAY)
++			addr = (unsigned long)page_address(pages[i]);
++		else
++			addr = start[i];
++
++		pte = lookup_address(addr, &level);
+ 
+ 		/*
+ 		 * Only flush present addresses:
+ 		 */
+ 		if (pte && (__pte_val(*pte) & _PAGE_PRESENT))
+-			clflush_cache_range((void *) *addr, PAGE_SIZE);
++			clflush_cache_range((void *)addr, PAGE_SIZE);
+ 	}
+ }
+ 
+@@ -498,6 +504,13 @@ static int split_large_page(pte_t *kpte,
+ 	pbase = (pte_t *)page_address(base);
+ 	paravirt_alloc_pte(&init_mm, page_to_pfn(base));
+ 	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
++	/*
++	 * If we ever want to utilize the PAT bit, we need to
++	 * update this function to make sure it's converted from
++	 * bit 12 to bit 7 when we cross from the 2MB level to
++	 * the 4K level:
++	 */
++	WARN_ON_ONCE(pgprot_val(ref_prot) & _PAGE_PAT_LARGE);
+ 
+ #ifdef CONFIG_X86_64
+ 	if (level == PG_LEVEL_1G) {
+@@ -597,7 +610,9 @@ static int __change_page_attr(struct cpa
+ 	unsigned int level;
+ 	pte_t *kpte, old_pte;
+ 
+-	if (cpa->flags & CPA_ARRAY)
++	if (cpa->flags & CPA_PAGES_ARRAY)
++		address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
++	else if (cpa->flags & CPA_ARRAY)
+ 		address = cpa->vaddr[cpa->curpage];
+ 	else
+ 		address = *cpa->vaddr;
+@@ -701,7 +716,9 @@ static int cpa_process_alias(struct cpa_
+ 	 * No need to redo, when the primary call touched the direct
+ 	 * mapping already:
+ 	 */
+-	if (cpa->flags & CPA_ARRAY)
++	if (cpa->flags & CPA_PAGES_ARRAY)
++		vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
++	else if (cpa->flags & CPA_ARRAY)
+ 		vaddr = cpa->vaddr[cpa->curpage];
+ 	else
+ 		vaddr = *cpa->vaddr;
+@@ -712,7 +729,7 @@ static int cpa_process_alias(struct cpa_
+ 		alias_cpa = *cpa;
+ 		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
+ 		alias_cpa.vaddr = &temp_cpa_vaddr;
+-		alias_cpa.flags &= ~CPA_ARRAY;
++		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ 
+ 
+ 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+@@ -725,7 +742,7 @@ static int cpa_process_alias(struct cpa_
+ 	 * No need to redo, when the primary call touched the high
+ 	 * mapping already:
+ 	 */
+-	if (within(vaddr, (unsigned long) _text, (unsigned long) _end))
++	if (within(vaddr, (unsigned long) _text, _brk_end))
+ 		return 0;
+ 
+ 	/*
+@@ -738,7 +755,7 @@ static int cpa_process_alias(struct cpa_
+ 	alias_cpa = *cpa;
+ 	temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
+ 	alias_cpa.vaddr = &temp_cpa_vaddr;
+-	alias_cpa.flags &= ~CPA_ARRAY;
++	alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ 
+ 	/*
+ 	 * The high mapping range is imprecise, so ignore the return value.
+@@ -759,7 +776,7 @@ static int __change_page_attr_set_clr(st
+ 		 */
+ 		cpa->numpages = numpages;
+ 		/* for array changes, we can't use large page */
+-		if (cpa->flags & CPA_ARRAY)
++		if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
+ 			cpa->numpages = 1;
+ 
+ 		if (!debug_pagealloc)
+@@ -783,7 +800,7 @@ static int __change_page_attr_set_clr(st
+ 		 */
+ 		BUG_ON(cpa->numpages > numpages);
+ 		numpages -= cpa->numpages;
+-		if (cpa->flags & CPA_ARRAY)
++		if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
+ 			cpa->curpage++;
+ 		else
+ 			*cpa->vaddr += cpa->numpages * PAGE_SIZE;
+@@ -800,7 +817,8 @@ static inline int cache_attr(pgprot_t at
+ 
+ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
+ 				    pgprot_t mask_set, pgprot_t mask_clr,
+-				    int force_split, int array)
++				    int force_split, int in_flag,
++				    struct page **pages)
+ {
+ 	struct cpa_data cpa;
+ 	int ret, cache, checkalias;
+@@ -815,15 +833,7 @@ static int change_page_attr_set_clr(unsi
+ 		return 0;
+ 
+ 	/* Ensure we are PAGE_SIZE aligned */
+-	if (!array) {
+-		if (*addr & ~PAGE_MASK) {
+-			*addr &= PAGE_MASK;
+-			/*
+-			 * People should not be passing in unaligned addresses:
+-			 */
+-			WARN_ON_ONCE(1);
+-		}
+-	} else {
++	if (in_flag & CPA_ARRAY) {
+ 		int i;
+ 		for (i = 0; i < numpages; i++) {
+ 			if (addr[i] & ~PAGE_MASK) {
+@@ -831,6 +841,18 @@ static int change_page_attr_set_clr(unsi
+ 				WARN_ON_ONCE(1);
+ 			}
+ 		}
++	} else if (!(in_flag & CPA_PAGES_ARRAY)) {
++		/*
++		 * in_flag of CPA_PAGES_ARRAY implies it is aligned.
++		 * No need to cehck in that case
++		 */
++		if (*addr & ~PAGE_MASK) {
++			*addr &= PAGE_MASK;
++			/*
++			 * People should not be passing in unaligned addresses:
++			 */
++			WARN_ON_ONCE(1);
++		}
+ 	}
+ 
+ 	/* Must avoid aliasing mappings in the highmem code */
+@@ -848,6 +870,7 @@ static int change_page_attr_set_clr(unsi
+ 		xen_multicall_flush(true);
+ 
+ 	cpa.vaddr = addr;
++	cpa.pages = pages;
+ 	cpa.numpages = numpages;
+ 	cpa.mask_set = mask_set;
+ 	cpa.mask_clr = mask_clr;
+@@ -855,8 +878,8 @@ static int change_page_attr_set_clr(unsi
+ 	cpa.curpage = 0;
+ 	cpa.force_split = force_split;
+ 
+-	if (array)
+-		cpa.flags |= CPA_ARRAY;
++	if (in_flag & (CPA_ARRAY | CPA_PAGES_ARRAY))
++		cpa.flags |= in_flag;
+ 
+ 	/* No alias checking for _NX bit modifications */
+ 	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+@@ -882,9 +905,10 @@ static int change_page_attr_set_clr(unsi
+ 	 * wbindv):
+ 	 */
+ 	if (!ret && cpu_has_clflush) {
+-		if (cpa.flags & CPA_ARRAY)
+-			cpa_flush_array(addr, numpages, cache);
+-		else
++		if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
++			cpa_flush_array(addr, numpages, cache,
++					cpa.flags, pages);
++		} else
+ 			cpa_flush_range(*addr, numpages, cache);
+ 	} else
+ 		cpa_flush_all(cache);
+@@ -905,14 +929,28 @@ static inline int change_page_attr_set(u
+ 				       pgprot_t mask, int array)
+ {
+ 	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0,
+-		array);
++		(array ? CPA_ARRAY : 0), NULL);
+ }
+ 
+ static inline int change_page_attr_clear(unsigned long *addr, int numpages,
+ 					 pgprot_t mask, int array)
+ {
+ 	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0,
+-		array);
++		(array ? CPA_ARRAY : 0), NULL);
++}
++
++static inline int cpa_set_pages_array(struct page **pages, int numpages,
++				       pgprot_t mask)
++{
++	return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0,
++		CPA_PAGES_ARRAY, pages);
++}
++
++static inline int cpa_clear_pages_array(struct page **pages, int numpages,
++					 pgprot_t mask)
++{
++	return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0,
++		CPA_PAGES_ARRAY, pages);
+ }
+ 
+ #ifdef CONFIG_XEN
+@@ -971,71 +1009,94 @@ int _set_memory_uc(unsigned long addr, i
+ 
+ int set_memory_uc(unsigned long addr, int numpages)
+ {
++	int ret;
++
+ 	/*
+ 	 * for now UC MINUS. see comments in ioremap_nocache()
+ 	 */
+-	if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+-			    _PAGE_CACHE_UC_MINUS, NULL))
+-		return -EINVAL;
++	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
++			    _PAGE_CACHE_UC_MINUS, NULL);
++	if (ret)
++		goto out_err;
++
++	ret = _set_memory_uc(addr, numpages);
++	if (ret)
++		goto out_free;
+ 
+-	return _set_memory_uc(addr, numpages);
++	return 0;
++
++out_free:
++	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
++out_err:
++	return ret;
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+ 
+ int set_memory_array_uc(unsigned long *addr, int addrinarray)
+ {
+-	unsigned long start;
+-	unsigned long end;
+-	int i;
++	int i, j;
++	int ret;
++
+ 	/*
+ 	 * for now UC MINUS. see comments in ioremap_nocache()
+ 	 */
+ 	for (i = 0; i < addrinarray; i++) {
+-		start = __pa(addr[i]);
+-		for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
+-			if (end != __pa(addr[i + 1]))
+-				break;
+-			i++;
+-		}
+-		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
+-			goto out;
++		ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE,
++					_PAGE_CACHE_UC_MINUS, NULL);
++		if (ret)
++			goto out_free;
+ 	}
+ 
+-	return change_page_attr_set(addr, addrinarray,
++	ret = change_page_attr_set(addr, addrinarray,
+ 				    __pgprot(_PAGE_CACHE_UC_MINUS), 1);
+-out:
+-	for (i = 0; i < addrinarray; i++) {
+-		unsigned long tmp = __pa(addr[i]);
++	if (ret)
++		goto out_free;
+ 
+-		if (tmp == start)
+-			break;
+-		for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
+-			if (end != __pa(addr[i + 1]))
+-				break;
+-			i++;
+-		}
+-		free_memtype(tmp, end);
+-	}
+-	return -EINVAL;
++	return 0;
++
++out_free:
++	for (j = 0; j < i; j++)
++		free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE);
++
++	return ret;
+ }
+ EXPORT_SYMBOL(set_memory_array_uc);
+ 
+ int _set_memory_wc(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_set(&addr, numpages,
++	int ret;
++	ret = change_page_attr_set(&addr, numpages,
++				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
++
++	if (!ret) {
++		ret = change_page_attr_set(&addr, numpages,
+ 				    __pgprot(_PAGE_CACHE_WC), 0);
++	}
++	return ret;
+ }
+ 
+ int set_memory_wc(unsigned long addr, int numpages)
+ {
++	int ret;
++
+ 	if (!pat_enabled)
+ 		return set_memory_uc(addr, numpages);
+ 
+-	if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+-		_PAGE_CACHE_WC, NULL))
+-		return -EINVAL;
++	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
++		_PAGE_CACHE_WC, NULL);
++	if (ret)
++		goto out_err;
+ 
+-	return _set_memory_wc(addr, numpages);
++	ret = _set_memory_wc(addr, numpages);
++	if (ret)
++		goto out_free;
++
++	return 0;
++
++out_free:
++	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
++out_err:
++	return ret;
+ }
+ EXPORT_SYMBOL(set_memory_wc);
+ 
+@@ -1047,29 +1108,31 @@ int _set_memory_wb(unsigned long addr, i
+ 
+ int set_memory_wb(unsigned long addr, int numpages)
+ {
+-	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
++	int ret;
+ 
+-	return _set_memory_wb(addr, numpages);
++	ret = _set_memory_wb(addr, numpages);
++	if (ret)
++		return ret;
++
++	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
++	return 0;
+ }
+ EXPORT_SYMBOL(set_memory_wb);
+ 
+ int set_memory_array_wb(unsigned long *addr, int addrinarray)
+ {
+ 	int i;
++	int ret;
+ 
+-	for (i = 0; i < addrinarray; i++) {
+-		unsigned long start = __pa(addr[i]);
+-		unsigned long end;
+-
+-		for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
+-			if (end != __pa(addr[i + 1]))
+-				break;
+-			i++;
+-		}
+-		free_memtype(start, end);
+-	}
+-	return change_page_attr_clear(addr, addrinarray,
++	ret = change_page_attr_clear(addr, addrinarray,
+ 				      __pgprot(_PAGE_CACHE_MASK), 1);
++	if (ret)
++		return ret;
++
++	for (i = 0; i < addrinarray; i++)
++		free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE);
++
++	return 0;
+ }
+ EXPORT_SYMBOL(set_memory_array_wb);
+ 
+@@ -1105,7 +1168,7 @@ int set_memory_np(unsigned long addr, in
+ int set_memory_4k(unsigned long addr, int numpages)
+ {
+ 	return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
+-					__pgprot(0), 1, 0);
++					__pgprot(0), 1, 0, NULL);
+ }
+ 
+ int set_pages_uc(struct page *page, int numpages)
+@@ -1116,6 +1179,35 @@ int set_pages_uc(struct page *page, int 
+ }
+ EXPORT_SYMBOL(set_pages_uc);
+ 
++int set_pages_array_uc(struct page **pages, int addrinarray)
++{
++	unsigned long start;
++	unsigned long end;
++	int i;
++	int free_idx;
++
++	for (i = 0; i < addrinarray; i++) {
++		start = (unsigned long)page_address(pages[i]);
++		end = start + PAGE_SIZE;
++		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
++			goto err_out;
++	}
++
++	if (cpa_set_pages_array(pages, addrinarray,
++			__pgprot(_PAGE_CACHE_UC_MINUS)) == 0) {
++		return 0; /* Success */
++	}
++err_out:
++	free_idx = i;
++	for (i = 0; i < free_idx; i++) {
++		start = (unsigned long)page_address(pages[i]);
++		end = start + PAGE_SIZE;
++		free_memtype(start, end);
++	}
++	return -EINVAL;
++}
++EXPORT_SYMBOL(set_pages_array_uc);
++
+ int set_pages_wb(struct page *page, int numpages)
+ {
+ 	unsigned long addr = (unsigned long)page_address(page);
+@@ -1124,6 +1216,28 @@ int set_pages_wb(struct page *page, int 
+ }
+ EXPORT_SYMBOL(set_pages_wb);
+ 
++int set_pages_array_wb(struct page **pages, int addrinarray)
++{
++	int retval;
++	unsigned long start;
++	unsigned long end;
++	int i;
++
++	retval = cpa_clear_pages_array(pages, addrinarray,
++			__pgprot(_PAGE_CACHE_MASK));
++	if (retval)
++		return retval;
++
++	for (i = 0; i < addrinarray; i++) {
++		start = (unsigned long)page_address(pages[i]);
++		end = start + PAGE_SIZE;
++		free_memtype(start, end);
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(set_pages_array_wb);
++
+ int set_pages_x(struct page *page, int numpages)
+ {
+ 	unsigned long addr = (unsigned long)page_address(page);
+--- head-2010-01-18.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pat-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -31,7 +31,7 @@
+ #ifdef CONFIG_X86_PAT
+ int __read_mostly pat_enabled = 1;
+ 
+-void __cpuinit pat_disable(char *reason)
++static inline void pat_disable(const char *reason)
+ {
+ 	pat_enabled = 0;
+ 	printk(KERN_INFO "%s\n", reason);
+@@ -43,6 +43,11 @@ static int __init nopat(char *str)
+ 	return 0;
+ }
+ early_param("nopat", nopat);
++#else
++static inline void pat_disable(const char *reason)
++{
++	(void)reason;
++}
+ #endif
+ 
+ 
+@@ -79,16 +84,20 @@ void pat_init(void)
+ 	if (!pat_enabled)
+ 		return;
+ 
+-	/* Paranoia check. */
+-	if (!cpu_has_pat && boot_pat_state) {
+-		/*
+-		 * If this happens we are on a secondary CPU, but
+-		 * switched to PAT on the boot CPU. We have no way to
+-		 * undo PAT.
+-		 */
+-		printk(KERN_ERR "PAT enabled, "
+-		       "but not supported by secondary CPU\n");
+-		BUG();
++	if (!cpu_has_pat) {
++		if (!boot_pat_state) {
++			pat_disable("PAT not supported by CPU.");
++			return;
++		} else {
++			/*
++			 * If this happens we are on a secondary CPU, but
++			 * switched to PAT on the boot CPU. We have no way to
++			 * undo PAT.
++			 */
++			printk(KERN_ERR "PAT enabled, "
++			       "but not supported by secondary CPU\n");
++			BUG();
++		}
+ 	}
+ 
+ #ifndef CONFIG_XEN
+@@ -185,10 +194,10 @@ static unsigned long pat_x_mtrr_type(u64
+ 		u8 mtrr_type;
+ 
+ 		mtrr_type = mtrr_type_lookup(start, end);
+-		if (mtrr_type == MTRR_TYPE_UNCACHABLE)
+-			return _PAGE_CACHE_UC;
+-		if (mtrr_type == MTRR_TYPE_WRCOMB)
+-			return _PAGE_CACHE_WC;
++		if (mtrr_type != MTRR_TYPE_WRBACK)
++			return _PAGE_CACHE_UC_MINUS;
++
++		return _PAGE_CACHE_WB;
+ 	}
+ 
+ 	return req_type;
+@@ -355,23 +364,13 @@ int reserve_memtype(u64 start, u64 end, 
+ 		return 0;
+ 	}
+ 
+-	if (req_type == -1) {
+-		/*
+-		 * Call mtrr_lookup to get the type hint. This is an
+-		 * optimization for /dev/mem mmap'ers into WB memory (BIOS
+-		 * tools and ACPI tools). Use WB request for WB memory and use
+-		 * UC_MINUS otherwise.
+-		 */
+-		u8 mtrr_type = mtrr_type_lookup(start, end);
+-
+-		if (mtrr_type == MTRR_TYPE_WRBACK)
+-			actual_type = _PAGE_CACHE_WB;
+-		else
+-			actual_type = _PAGE_CACHE_UC_MINUS;
+-	} else {
+-		actual_type = pat_x_mtrr_type(start, end,
+-					      req_type & _PAGE_CACHE_MASK);
+-	}
++	/*
++	 * Call mtrr_lookup to get the type hint. This is an
++	 * optimization for /dev/mem mmap'ers into WB memory (BIOS
++	 * tools and ACPI tools). Use WB request for WB memory and use
++	 * UC_MINUS otherwise.
++	 */
++	actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK);
+ 
+ 	if (new_type)
+ 		*new_type = actual_type;
+@@ -549,9 +548,7 @@ static inline int range_is_allowed(unsig
+ int phys_mem_access_prot_allowed(struct file *file, unsigned long mfn,
+ 				unsigned long size, pgprot_t *vma_prot)
+ {
+-	u64 addr = (u64)mfn << PAGE_SHIFT;
+-	unsigned long flags = -1;
+-	int retval;
++	unsigned long flags = _PAGE_CACHE_WB;
+ 
+ 	if (!range_is_allowed(mfn, size))
+ 		return 0;
+@@ -581,60 +578,21 @@ int phys_mem_access_prot_allowed(struct 
+ #endif
+ #endif
+ 
+-	/*
+-	 * With O_SYNC, we can only take UC_MINUS mapping. Fail if we cannot.
+-	 *
+-	 * Without O_SYNC, we want to get
+-	 * - WB for WB-able memory and no other conflicting mappings
+-	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+-	 * - Inherit from confliting mappings otherwise
+-	 */
+-	if (flags != -1) {
+-		retval = reserve_memtype(addr, addr + size, flags, NULL);
+-	} else {
+-		retval = reserve_memtype(addr, addr + size, -1, &flags);
+-	}
+-
+-	if (retval < 0)
+-		return 0;
+-
+-	if (ioremap_check_change_attr(mfn, size, flags) < 0) {
+-		free_memtype(addr, addr + size);
+-		printk(KERN_INFO
+-		"%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
+-			current->comm, current->pid,
+-			cattr_name(flags),
+-			addr, addr + size);
+-		return 0;
+-	}
+-
+ 	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
+ 			     flags);
+ 	return 1;
+ }
+ 
+-void map_devmem(unsigned long mfn, unsigned long size, pgprot_t vma_prot)
+-{
+-	unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
+-	u64 addr = (u64)mfn << PAGE_SHIFT;
+-	unsigned long flags;
+-
+-	reserve_memtype(addr, addr + size, want_flags, &flags);
+-	if (flags != want_flags) {
+-		printk(KERN_INFO
+-		"%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
+-			current->comm, current->pid,
+-			cattr_name(want_flags),
+-			addr, (unsigned long long)(addr + size),
+-			cattr_name(flags));
+-	}
+-}
+-
+-void unmap_devmem(unsigned long mfn, unsigned long size, pgprot_t vma_prot)
++/*
++ * Change the memory type for the physial address range in kernel identity
++ * mapping space if that range is a part of identity map.
++ */
++int kernel_map_sync_memtype(u64 ma, unsigned long size, unsigned long flags)
+ {
+-	u64 addr = (u64)mfn << PAGE_SHIFT;
++	if (!pat_enabled)
++		return 0;
+ 
+-	free_memtype(addr, addr + size);
++	return ioremap_check_change_attr(ma >> PAGE_SHIFT, size, flags);
+ }
+ 
+ #ifndef CONFIG_XEN
+@@ -647,17 +605,18 @@ static int reserve_pfn_range(u64 paddr, 
+ 				int strict_prot)
+ {
+ 	int is_ram = 0;
+-	int id_sz, ret;
+-	unsigned long flags;
++	int ret;
+ 	unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
++	unsigned long flags = want_flags;
+ 
+ 	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
+ 
+ 	/*
+-	 * reserve_pfn_range() doesn't support RAM pages.
++	 * reserve_pfn_range() doesn't support RAM pages. Maintain the current
++	 * behavior with RAM pages by returning success.
+ 	 */
+ 	if (is_ram != 0)
+-		return -EINVAL;
++		return 0;
+ 
+ 	ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
+ 	if (ret)
+@@ -684,23 +643,8 @@ static int reserve_pfn_range(u64 paddr, 
+ 				     flags);
+ 	}
+ 
+-	/* Need to keep identity mapping in sync */
+-	if (paddr >= __pa(high_memory))
+-		return 0;
+-
+-	id_sz = (__pa(high_memory) < paddr + size) ?
+-				__pa(high_memory) - paddr :
+-				size;
+-
+-	if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
++	if (kernel_map_sync_memtype(paddr, size, flags) < 0) {
+ 		free_memtype(paddr, paddr + size);
+-		printk(KERN_ERR
+-			"%s:%d reserve_pfn_range ioremap_change_attr failed %s "
+-			"for %Lx-%Lx\n",
+-			current->comm, current->pid,
+-			cattr_name(flags),
+-			(unsigned long long)paddr,
+-			(unsigned long long)(paddr + size));
+ 		return -EINVAL;
+ 	}
+ 	return 0;
+@@ -725,29 +669,28 @@ static void free_pfn_range(u64 paddr, un
+  *
+  * If the vma has a linear pfn mapping for the entire range, we get the prot
+  * from pte and reserve the entire vma range with single reserve_pfn_range call.
+- * Otherwise, we reserve the entire vma range, my ging through the PTEs page
+- * by page to get physical address and protection.
+  */
+ int track_pfn_vma_copy(struct vm_area_struct *vma)
+ {
+-	int retval = 0;
+-	unsigned long i, j;
+ 	resource_size_t paddr;
+ 	unsigned long prot;
+-	unsigned long vma_start = vma->vm_start;
+-	unsigned long vma_end = vma->vm_end;
+-	unsigned long vma_size = vma_end - vma_start;
++	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 	pgprot_t pgprot;
+ 
+ 	if (!pat_enabled)
+ 		return 0;
+ 
++	/*
++	 * For now, only handle remap_pfn_range() vmas where
++	 * is_linear_pfn_mapping() == TRUE. Handling of
++	 * vm_insert_pfn() is TBD.
++	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/*
+ 		 * reserve the whole chunk covered by vma. We need the
+ 		 * starting address and protection from pte.
+ 		 */
+-		if (follow_phys(vma, vma_start, 0, &prot, &paddr)) {
++		if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
+ 			WARN_ON_ONCE(1);
+ 			return -EINVAL;
+ 		}
+@@ -755,28 +698,7 @@ int track_pfn_vma_copy(struct vm_area_st
+ 		return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
+ 	}
+ 
+-	/* reserve entire vma page by page, using pfn and prot from pte */
+-	for (i = 0; i < vma_size; i += PAGE_SIZE) {
+-		if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
+-			continue;
+-
+-		pgprot = __pgprot(prot);
+-		retval = reserve_pfn_range(paddr, PAGE_SIZE, &pgprot, 1);
+-		if (retval)
+-			goto cleanup_ret;
+-	}
+ 	return 0;
+-
+-cleanup_ret:
+-	/* Reserve error: Cleanup partial reservation and return error */
+-	for (j = 0; j < i; j += PAGE_SIZE) {
+-		if (follow_phys(vma, vma_start + j, 0, &prot, &paddr))
+-			continue;
+-
+-		free_pfn_range(paddr, PAGE_SIZE);
+-	}
+-
+-	return retval;
+ }
+ 
+ /*
+@@ -786,50 +708,28 @@ cleanup_ret:
+  * prot is passed in as a parameter for the new mapping. If the vma has a
+  * linear pfn mapping for the entire range reserve the entire vma range with
+  * single reserve_pfn_range call.
+- * Otherwise, we look t the pfn and size and reserve only the specified range
+- * page by page.
+- *
+- * Note that this function can be called with caller trying to map only a
+- * subrange/page inside the vma.
+  */
+ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
+ 			unsigned long pfn, unsigned long size)
+ {
+-	int retval = 0;
+-	unsigned long i, j;
+-	resource_size_t base_paddr;
+ 	resource_size_t paddr;
+-	unsigned long vma_start = vma->vm_start;
+-	unsigned long vma_end = vma->vm_end;
+-	unsigned long vma_size = vma_end - vma_start;
++	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 
+ 	if (!pat_enabled)
+ 		return 0;
+ 
++	/*
++	 * For now, only handle remap_pfn_range() vmas where
++	 * is_linear_pfn_mapping() == TRUE. Handling of
++	 * vm_insert_pfn() is TBD.
++	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/* reserve the whole chunk starting from vm_pgoff */
+ 		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+ 		return reserve_pfn_range(paddr, vma_size, prot, 0);
+ 	}
+ 
+-	/* reserve page by page using pfn and size */
+-	base_paddr = (resource_size_t)pfn << PAGE_SHIFT;
+-	for (i = 0; i < size; i += PAGE_SIZE) {
+-		paddr = base_paddr + i;
+-		retval = reserve_pfn_range(paddr, PAGE_SIZE, prot, 0);
+-		if (retval)
+-			goto cleanup_ret;
+-	}
+ 	return 0;
+-
+-cleanup_ret:
+-	/* Reserve error: Cleanup partial reservation and return error */
+-	for (j = 0; j < i; j += PAGE_SIZE) {
+-		paddr = base_paddr + j;
+-		free_pfn_range(paddr, PAGE_SIZE);
+-	}
+-
+-	return retval;
+ }
+ 
+ /*
+@@ -840,39 +740,23 @@ cleanup_ret:
+ void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
+ 			unsigned long size)
+ {
+-	unsigned long i;
+ 	resource_size_t paddr;
+-	unsigned long prot;
+-	unsigned long vma_start = vma->vm_start;
+-	unsigned long vma_end = vma->vm_end;
+-	unsigned long vma_size = vma_end - vma_start;
++	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 
+ 	if (!pat_enabled)
+ 		return;
+ 
++	/*
++	 * For now, only handle remap_pfn_range() vmas where
++	 * is_linear_pfn_mapping() == TRUE. Handling of
++	 * vm_insert_pfn() is TBD.
++	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/* free the whole chunk starting from vm_pgoff */
+ 		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+ 		free_pfn_range(paddr, vma_size);
+ 		return;
+ 	}
+-
+-	if (size != 0 && size != vma_size) {
+-		/* free page by page, using pfn and size */
+-		paddr = (resource_size_t)pfn << PAGE_SHIFT;
+-		for (i = 0; i < size; i += PAGE_SIZE) {
+-			paddr = paddr + i;
+-			free_pfn_range(paddr, PAGE_SIZE);
+-		}
+-	} else {
+-		/* free entire vma, page by page, using the pfn from pte */
+-		for (i = 0; i < vma_size; i += PAGE_SIZE) {
+-			if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
+-				continue;
+-
+-			free_pfn_range(paddr, PAGE_SIZE);
+-		}
+-	}
+ }
+ #endif /* CONFIG_XEN */
+ 
+--- head-2010-01-18.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -122,10 +122,6 @@ void __pud_free_tlb(struct mmu_gather *t
+ #endif	/* PAGETABLE_LEVELS > 3 */
+ #endif	/* PAGETABLE_LEVELS > 2 */
+ 
+-#ifndef CONFIG_X86_64
+-#define TASK_SIZE64 TASK_SIZE
+-#endif
+-
+ static void _pin_lock(struct mm_struct *mm, int lock) {
+ 	if (lock)
+ 		spin_lock(&mm->page_table_lock);
+@@ -149,7 +145,7 @@ static void _pin_lock(struct mm_struct *
+ 		pgd_t *pgd = mm->pgd;
+ 		unsigned g;
+ 
+-		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++		for (g = 0; g <= ((TASK_SIZE_MAX-1) / PGDIR_SIZE); g++, pgd++) {
+ 			pud_t *pud;
+ 			unsigned u;
+ 
+@@ -230,10 +226,10 @@ static void pgd_walk(pgd_t *pgd_base, pg
+ 	 * Cannot iterate up to USER_PTRS_PER_PGD on x86-64 as these pagetables
+ 	 * may not be the 'current' task's pagetables (e.g., current may be
+ 	 * 32-bit, but the pagetables may be for a 64-bit task).
+-	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
+-	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
++	 * Subtracting 1 from TASK_SIZE_MAX means the loop limit is correct
++	 * regardless of whether TASK_SIZE_MAX is a multiple of PGDIR_SIZE.
+ 	 */
+-	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++	for (g = 0, seq = 0; g <= ((TASK_SIZE_MAX-1) / PGDIR_SIZE); g++, pgd++) {
+ 		if (pgd_none(*pgd))
+ 			continue;
+ 		pud = pud_offset(pgd, 0);
+@@ -736,9 +732,26 @@ int ptep_clear_flush_young(struct vm_are
+ 	return young;
+ }
+ 
++/**
++ * reserve_top_address - reserves a hole in the top of kernel address space
++ * @reserve - size of hole to reserve
++ *
++ * Can be used to relocate the fixmap area and poke a hole in the top
++ * of kernel address space to make room for a hypervisor.
++ */
++void __init reserve_top_address(unsigned long reserve)
++{
++#ifdef CONFIG_X86_32
++	BUG_ON(fixmaps_set > 0);
++	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
++	       (int)-reserve);
++	__FIXADDR_TOP = -reserve - PAGE_SIZE;
++#endif
++}
++
+ int fixmaps_set;
+ 
+-void xen_set_fixmap(enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
++void xen_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
+ {
+ 	unsigned long address = __fix_to_virt(idx);
+ 	pte_t pte;
+@@ -757,6 +770,8 @@ void xen_set_fixmap(enum fixed_addresses
+ 		set_pte_vaddr_pud(level3_user_pgt, address, pte);
+ 		break;
+ 	case FIX_EARLYCON_MEM_BASE:
++	case FIX_SHARED_INFO:
++	case FIX_ISAMAP_END ... FIX_ISAMAP_BEGIN:
+ 		xen_l1_entry_update(level1_fixmap_pgt + pte_index(address),
+ 				    pfn_pte_ma(phys >> PAGE_SHIFT, flags));
+ 		fixmaps_set++;
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:52:02.000000000 +0100
+@@ -25,6 +25,8 @@
+ #include <xen/features.h>
+ #include <asm/hypervisor.h>
+ 
++unsigned int __VMALLOC_RESERVE = 128 << 20;
++
+ /*
+  * Associate a virtual page frame with a given physical page frame
+  * and protection flags for that frame.
+@@ -54,7 +56,7 @@ void set_pte_vaddr(unsigned long vaddr, 
+ 	}
+ 	pte = pte_offset_kernel(pmd, vaddr);
+ 	if (pte_val(pteval))
+-		set_pte_present(&init_mm, vaddr, pte, pteval);
++		set_pte_at(&init_mm, vaddr, pte, pteval);
+ 	else
+ 		pte_clear(&init_mm, vaddr, pte);
+ 
+@@ -109,21 +111,6 @@ unsigned long hypervisor_virt_start = HY
+ unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - PAGE_SIZE);
+ EXPORT_SYMBOL(__FIXADDR_TOP);
+ 
+-/**
+- * reserve_top_address - reserves a hole in the top of kernel address space
+- * @reserve - size of hole to reserve
+- *
+- * Can be used to relocate the fixmap area and poke a hole in the top
+- * of kernel address space to make room for a hypervisor.
+- */
+-void __init reserve_top_address(unsigned long reserve)
+-{
+-	BUG_ON(fixmaps_set > 0);
+-	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+-	       (int)-reserve);
+-	__FIXADDR_TOP = -reserve - PAGE_SIZE;
+-}
+-
+ /*
+  * vmalloc=size forces the vmalloc area to be exactly 'size'
+  * bytes. This can be used to increase (or decrease) the
+--- head-2010-01-18.orig/drivers/acpi/Makefile	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/acpi/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -62,8 +62,6 @@ obj-$(CONFIG_ACPI_POWER_METER)	+= power_
+ processor-y			:= processor_core.o processor_throttling.o
+ processor-y			+= processor_idle.o processor_thermal.o
+ processor-$(CONFIG_CPU_FREQ)	+= processor_perflib.o
+-ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+-processor-objs	+= processor_perflib.o processor_extcntl.o
+-endif
++processor-$(CONFIG_PROCESSOR_EXTERNAL_CONTROL) += processor_perflib.o processor_extcntl.o
+ 
+ obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
+--- head-2010-01-18.orig/drivers/acpi/acpica/hwsleep.c	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/drivers/acpi/acpica/hwsleep.c	2009-11-06 10:52:02.000000000 +0100
+@@ -394,7 +394,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+ #else
+ 	/* PV ACPI just need check hypercall return value */
+ 	err = acpi_notify_hypervisor_state(sleep_state,
+-			PM1Acontrol, PM1Bcontrol);
++			pm1a_control, pm1b_control);
+ 	if (err) {
+ 		printk(KERN_ERR "ACPI: Hypervisor failure [%d]\n", err);
+ 		return_ACPI_STATUS(AE_ERROR);
+--- head-2010-01-18.orig/drivers/acpi/processor_idle.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_idle.c	2009-11-06 10:52:02.000000000 +0100
+@@ -523,7 +523,7 @@ static void acpi_processor_power_verify_
+ #ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ 	cx->latency_ticks = cx->latency;
+ #else
+-	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
++	cx->latency_ticks = us_to_pm_timer_ticks(cx->latency);
+ #endif
+ 
+ 	return;
+@@ -610,7 +610,7 @@ static void acpi_processor_power_verify_
+ #ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ 	cx->latency_ticks = cx->latency;
+ #else
+-	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
++	cx->latency_ticks = us_to_pm_timer_ticks(cx->latency);
+ #endif
+ 	/*
+ 	 * On older chipsets, BM_RLD needs to be set
+--- head-2010-01-18.orig/drivers/oprofile/oprofile_files.c	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/drivers/oprofile/oprofile_files.c	2009-11-06 10:52:02.000000000 +0100
+@@ -172,6 +172,7 @@ static const struct file_operations dump
+ };
+ 
+ #ifdef CONFIG_XEN
++#include <linux/slab.h>
+ 
+ #define TMPBUFSIZE 512
+ 
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:28:44.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:29:54.000000000 +0100
+@@ -47,47 +47,50 @@ struct msi_pirq_entry {
+ 
+ /* Arch hooks */
+ 
+-int __attribute__ ((weak))
+-arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+-{
+-	return 0;
+-}
+-
+-#ifndef CONFIG_XEN
+-int __attribute__ ((weak))
+-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
++#ifndef arch_msi_check_device
++int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+ {
+ 	return 0;
+ }
++#endif
+ 
+-int __attribute__ ((weak))
+-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
++#ifndef arch_setup_msi_irqs
++int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+ {
+ 	struct msi_desc *entry;
+ 	int ret;
+ 
++	/*
++	 * If an architecture wants to support multiple MSI, it needs to
++	 * override arch_setup_msi_irqs()
++	 */
++	if (type == PCI_CAP_ID_MSI && nvec > 1)
++		return 1;
++
+ 	list_for_each_entry(entry, &dev->msi_list, list) {
+ 		ret = arch_setup_msi_irq(dev, entry);
+-		if (ret)
++		if (ret < 0)
+ 			return ret;
++		if (ret > 0)
++			return -ENOSPC;
+ 	}
+ 
+ 	return 0;
+ }
++#endif
+ 
+-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+-{
+-	return;
+-}
+-
+-void __attribute__ ((weak))
+-arch_teardown_msi_irqs(struct pci_dev *dev)
++#ifndef arch_teardown_msi_irqs
++void arch_teardown_msi_irqs(struct pci_dev *dev)
+ {
+ 	struct msi_desc *entry;
+ 
+ 	list_for_each_entry(entry, &dev->msi_list, list) {
+-		if (entry->irq != 0)
+-			arch_teardown_msi_irq(entry->irq);
++		int i, nvec;
++		if (entry->irq == 0)
++			continue;
++		nvec = 1 << entry->msi_attrib.multiple;
++		for (i = 0; i < nvec; i++)
++			arch_teardown_msi_irq(entry->irq + i);
+ 	}
+ }
+ #endif
+@@ -347,13 +350,15 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state)
+ /**
+  * msi_capability_init - configure device's MSI capability structure
+  * @dev: pointer to the pci_dev data structure of MSI device function
++ * @nvec: number of interrupts to allocate
+  *
+- * Setup the MSI capability structure of device function with a single
+- * MSI irq, 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 irq or non-zero for otherwise.
+- **/
+-static int msi_capability_init(struct pci_dev *dev)
++ * Setup the MSI capability structure of the device with the requested
++ * number of interrupts.  A return value of zero indicates the successful
++ * setup of an entry with the new MSI irq.  A negative return value indicates
++ * an error, and a positive return value indicates the number of interrupts
++ * which could have been allocated.
++ */
++static int msi_capability_init(struct pci_dev *dev, int nvec)
+ {
+ 	int pos, pirq;
+ 	u16 control;
+@@ -363,6 +368,7 @@ static int msi_capability_init(struct pc
+ 	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ 	pci_read_config_word(dev, msi_control_reg(pos), &control);
+ 
++	WARN_ON(nvec > 1); /* XXX */
+ 	pirq = msi_map_vector(dev, 0, 0);
+ 	if (pirq < 0)
+ 		return -EBUSY;
+@@ -496,22 +502,34 @@ static int pci_msi_check_device(struct p
+ }
+ 
+ /**
+- * pci_enable_msi - configure device's MSI capability structure
+- * @dev: pointer to the pci_dev data structure of MSI device function
++ * pci_enable_msi_block - configure device's MSI capability structure
++ * @dev: device to configure
++ * @nvec: number of interrupts to configure
+  *
+- * Setup the MSI capability structure of device function with
+- * a single MSI irq 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.
+- **/
++ * Allocate IRQs for a device with the MSI capability.
++ * This function returns a negative errno if an error occurs.  If it
++ * is unable to allocate the number of interrupts requested, it returns
++ * the number of interrupts it might be able to allocate.  If it successfully
++ * allocates at least the number of interrupts requested, it returns 0 and
++ * updates the @dev's irq member to the lowest new interrupt number; the
++ * other interrupt numbers allocated to this device are consecutive.
++ */
+ extern int pci_frontend_enable_msi(struct pci_dev *dev);
+-int pci_enable_msi(struct pci_dev* dev)
++int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
+ {
+-	int temp, status;
++	int temp, status, pos, maxvec;
++	u16 msgctl;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	if (!pos)
++		return -EINVAL;
++	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
++	maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
++	if (nvec > maxvec)
++		return maxvec;
++
++	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
+ 	if (status)
+  		return status;
+ 
+@@ -521,6 +539,7 @@ int pci_enable_msi(struct pci_dev* dev)
+ 		int ret;
+ 
+ 		temp = dev->irq;
++		WARN_ON(nvec > 1); /* XXX */
+ 		ret = pci_frontend_enable_msi(dev);
+ 		if (ret)
+ 			return ret;
+@@ -535,23 +554,23 @@ int pci_enable_msi(struct pci_dev* dev)
+ 
+ 	temp = dev->irq;
+ 
+-	/* Check whether driver already requested for MSI-X irqs */
++	/* Check whether driver already requested MSI-X irqs */
+ 	if (dev->msix_enabled) {
+ 		dev_info(&dev->dev, "can't enable MSI "
+ 			 "(MSI-X already enabled)\n");
+ 		return -EINVAL;
+ 	}
+ 
+-	status = msi_capability_init(dev);
++	status = msi_capability_init(dev, nvec);
+ 	if ( !status )
+ 		msi_dev_entry->default_irq = temp;
+ 
+ 	return status;
+ }
+-EXPORT_SYMBOL(pci_enable_msi);
++EXPORT_SYMBOL(pci_enable_msi_block);
+ 
+ extern void pci_frontend_disable_msi(struct pci_dev* dev);
+-void pci_msi_shutdown(struct pci_dev* dev)
++void pci_msi_shutdown(struct pci_dev *dev)
+ {
+ 	int pirq;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+@@ -579,6 +598,7 @@ void pci_msi_shutdown(struct pci_dev* de
+ 	pci_intx_for_msi(dev, 1);
+ 	dev->msi_enabled = 0;
+ }
++
+ void pci_disable_msi(struct pci_dev* dev)
+ {
+ 	pci_msi_shutdown(dev);
+@@ -586,6 +606,23 @@ void pci_disable_msi(struct pci_dev* dev
+ EXPORT_SYMBOL(pci_disable_msi);
+ 
+ /**
++ * pci_msix_table_size - return the number of device's MSI-X table entries
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ */
++int pci_msix_table_size(struct pci_dev *dev)
++{
++	int pos;
++	u16 control;
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++	if (!pos)
++		return 0;
++
++	pci_read_config_word(dev, msi_control_reg(pos), &control);
++	return multi_msix_capable(control);
++}
++
++/**
+  * 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
+@@ -604,9 +641,8 @@ extern int pci_frontend_enable_msix(stru
+ 		struct msix_entry *entries, int nvec);
+ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
+ {
+-	int status, pos, nr_entries;
++	int status, nr_entries;
+ 	int i, j, temp;
+-	u16 control;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+ 	if (!entries)
+@@ -653,9 +689,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ 	if (status)
+ 		return status;
+ 
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+-	pci_read_config_word(dev, msi_control_reg(pos), &control);
+-	nr_entries = multi_msix_capable(control);
++	nr_entries = pci_msix_table_size(dev);
+ 	if (nvec > nr_entries)
+ 		return -EINVAL;
+ 
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:27:38.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-18 12:27:45.000000000 +0100
+@@ -14,7 +14,6 @@ menu "XEN"
+ 
+ config XEN_PRIVILEGED_GUEST
+ 	bool "Privileged Guest (domain 0)"
+-	select PCI_REASSIGN if PCI
+ 	help
+ 	  Support for privileged operation (domain 0)
+ 
+@@ -333,10 +332,6 @@ endmenu
+ config HAVE_IRQ_IGNORE_UNHANDLED
+ 	def_bool y
+ 
+-config GENERIC_HARDIRQS_NO__DO_IRQ
+-	def_bool y
+-	depends on X86
+-
+ config NO_IDLE_HZ
+ 	def_bool y
+ 
+--- head-2010-01-18.orig/drivers/xen/char/mem.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/char/mem.c	2009-11-06 10:52:02.000000000 +0100
+@@ -158,21 +158,7 @@ static ssize_t write_mem(struct file * f
+ }
+ 
+ #ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
+-static void mmap_mem_open(struct vm_area_struct *vma)
+-{
+-	map_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
+-			vma->vm_page_prot);
+-}
+-
+-static void mmap_mem_close(struct vm_area_struct *vma)
+-{
+-	unmap_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
+-			vma->vm_page_prot);
+-}
+-
+ static struct vm_operations_struct mmap_mem_ops = {
+-	.open  = mmap_mem_open,
+-	.close = mmap_mem_close,
+ #ifdef CONFIG_HAVE_IOREMAP_PROT
+ 	.access = generic_access_phys
+ #endif
+--- head-2010-01-18.orig/drivers/xen/core/Makefile	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/Makefile	2009-11-06 10:52:02.000000000 +0100
+@@ -10,6 +10,6 @@ obj-$(CONFIG_SYS_HYPERVISOR)	+= hypervis
+ obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
+ obj-$(CONFIG_XEN_SYSFS)		+= xen_sysfs.o
+ obj-$(CONFIG_XEN_SMPBOOT)	+= smpboot.o
+-obj-$(CONFIG_X86_SMP)		+= spinlock.o
++obj-$(CONFIG_SMP)		+= spinlock.o
+ obj-$(CONFIG_KEXEC)		+= machine_kexec.o
+ obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:52:02.000000000 +0100
+@@ -150,13 +150,15 @@ DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS])
+ #ifdef CONFIG_SMP
+ 
+ static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+-static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
++static DEFINE_PER_CPU(unsigned long[BITS_TO_LONGS(NR_EVENT_CHANNELS)],
++		      cpu_evtchn_mask);
+ 
+-static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
+-					   unsigned int idx)
++static inline unsigned long active_evtchns(unsigned int idx)
+ {
++	shared_info_t *sh = HYPERVISOR_shared_info;
++
+ 	return (sh->evtchn_pending[idx] &
+-		cpu_evtchn_mask[cpu][idx] &
++		percpu_read(cpu_evtchn_mask[idx]) &
+ 		~sh->evtchn_mask[idx]);
+ }
+ 
+@@ -168,10 +170,10 @@ static void bind_evtchn_to_cpu(unsigned 
+ 	BUG_ON(!test_bit(chn, s->evtchn_mask));
+ 
+ 	if (irq != -1)
+-		irq_to_desc(irq)->affinity = cpumask_of_cpu(cpu);
++		cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
+ 
+-	clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
+-	set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
++	clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_evtchn[chn]));
++	set_bit(chn, per_cpu(cpu_evtchn_mask, cpu));
+ 	cpu_evtchn[chn] = cpu;
+ }
+ 
+@@ -184,11 +186,11 @@ static void init_evtchn_cpu_bindings(voi
+ 		struct irq_desc *desc = irq_to_desc(i);
+ 
+ 		if (desc)
+-			desc->affinity = cpumask_of_cpu(0);
++			cpumask_copy(desc->affinity, cpumask_of(0));
+ 	}
+ 
+ 	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+-	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
++	memset(per_cpu(cpu_evtchn_mask, 0), ~0, sizeof(per_cpu(cpu_evtchn_mask, 0)));
+ }
+ 
+ static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
+@@ -198,9 +200,10 @@ static inline unsigned int cpu_from_evtc
+ 
+ #else
+ 
+-static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
+-					   unsigned int idx)
++static inline unsigned long active_evtchns(unsigned int idx)
+ {
++	shared_info_t *sh = HYPERVISOR_shared_info;
++
+ 	return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
+ }
+ 
+@@ -219,25 +222,15 @@ static inline unsigned int cpu_from_evtc
+ 
+ #endif
+ 
+-/* Upcall to generic IRQ layer. */
+ #ifdef CONFIG_X86
+-extern unsigned int do_IRQ(struct pt_regs *regs);
+ void __init xen_init_IRQ(void);
+ void __init init_IRQ(void)
+ {
+ 	irq_ctx_init(0);
+ 	xen_init_IRQ();
+ }
+-#if defined (__i386__)
+-static inline void exit_idle(void) {}
+-#elif defined (__x86_64__)
+ #include <asm/idle.h>
+ #endif
+-#define do_IRQ(irq, regs) do {		\
+-	(regs)->orig_ax = ~(irq);	\
+-	do_IRQ((regs));			\
+-} while (0)
+-#endif
+ 
+ /* Xen will never allocate port zero for any purpose. */
+ #define VALID_EVTCHN(chn)	((chn) != 0)
+@@ -261,13 +254,12 @@ static DEFINE_PER_CPU(unsigned int, last
+ /* NB. Interrupts are disabled on entry. */
+ asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs)
+ {
++	struct pt_regs     *old_regs = set_irq_regs(regs);
+ 	unsigned long       l1, l2;
+ 	unsigned long       masked_l1, masked_l2;
+ 	unsigned int        l1i, l2i, port, count;
+ 	int                 irq;
+-	unsigned int        cpu = smp_processor_id();
+-	shared_info_t      *s = HYPERVISOR_shared_info;
+-	vcpu_info_t        *vcpu_info = &s->vcpu_info[cpu];
++	vcpu_info_t        *vcpu_info = current_vcpu_info();
+ 
+ 	exit_idle();
+ 	irq_enter();
+@@ -277,7 +269,8 @@ asmlinkage void __irq_entry evtchn_do_up
+ 		vcpu_info->evtchn_upcall_pending = 0;
+ 
+ 		/* Nested invocations bail immediately. */
+-		if (unlikely(per_cpu(upcall_count, cpu)++))
++		percpu_add(upcall_count, 1);
++		if (unlikely(percpu_read(upcall_count) != 1))
+ 			break;
+ 
+ #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+@@ -286,8 +279,8 @@ asmlinkage void __irq_entry evtchn_do_up
+ #endif
+ 		l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+ 
+-		l1i = per_cpu(last_processed_l1i, cpu);
+-		l2i = per_cpu(last_processed_l2i, cpu);
++		l1i = percpu_read(last_processed_l1i);
++		l2i = percpu_read(last_processed_l2i);
+ 
+ 		while (l1 != 0) {
+ 
+@@ -302,7 +295,7 @@ asmlinkage void __irq_entry evtchn_do_up
+ 			l1i = __ffs(masked_l1);
+ 
+ 			do {
+-				l2 = active_evtchns(cpu, s, l1i);
++				l2 = active_evtchns(l1i);
+ 
+ 				l2i = (l2i + 1) % BITS_PER_LONG;
+ 				masked_l2 = l2 & ((~0UL) << l2i);
+@@ -316,29 +309,31 @@ asmlinkage void __irq_entry evtchn_do_up
+ 
+ 				/* process port */
+ 				port = (l1i * BITS_PER_LONG) + l2i;
+-				if ((irq = evtchn_to_irq[port]) != -1)
+-					do_IRQ(irq, regs);
+-				else
++				if (unlikely((irq = evtchn_to_irq[port]) == -1))
+ 					evtchn_device_upcall(port);
++				else if (!handle_irq(irq, regs) && printk_ratelimit())
++					printk(KERN_EMERG "%s(%d): No handler for irq %d\n",
++					       __func__, smp_processor_id(), irq);
+ 
+ 				/* if this is the final port processed, we'll pick up here+1 next time */
+-				per_cpu(last_processed_l1i, cpu) = l1i;
+-				per_cpu(last_processed_l2i, cpu) = l2i;
++				percpu_write(last_processed_l1i, l1i);
++				percpu_write(last_processed_l2i, l2i);
+ 
+ 			} while (l2i != BITS_PER_LONG - 1);
+ 
+-			l2 = active_evtchns(cpu, s, l1i);
++			l2 = active_evtchns(l1i);
+ 			if (l2 == 0) /* we handled all ports, so we can clear the selector bit */
+ 				l1 &= ~(1UL << l1i);
+ 
+ 		}
+ 
+ 		/* If there were nested callbacks then we have more to do. */
+-		count = per_cpu(upcall_count, cpu);
+-		per_cpu(upcall_count, cpu) = 0;
++		count = percpu_read(upcall_count);
++		percpu_write(upcall_count, 0);
+ 	} while (unlikely(count != 1));
+ 
+ 	irq_exit();
++	set_irq_regs(old_regs);
+ }
+ 
+ static struct irq_chip dynirq_chip;
+@@ -545,7 +540,7 @@ static void unbind_from_irq(unsigned int
+ 
+ 		/* Zap stats across IRQ changes of use. */
+ 		for_each_possible_cpu(cpu)
+-#ifdef CONFIG_SPARSE_IRQ
++#ifdef CONFIG_GENERIC_HARDIRQS
+ 			irq_to_desc(irq)->kstat_irqs[cpu] = 0;
+ #else
+ 			kstat_cpu(cpu).irqs[irq] = 0;
+@@ -663,7 +658,8 @@ int bind_ipi_to_irqhandler(
+ 	if (irq < 0)
+ 		return irq;
+ 
+-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	retval = request_irq(irq, handler, irqflags | IRQF_NO_SUSPEND,
++			     devname, dev_id);
+ 	if (retval != 0) {
+ 		unbind_from_irq(irq);
+ 		return retval;
+@@ -1132,7 +1128,7 @@ void irq_resume(void)
+ 		mask_evtchn(evtchn);
+ 
+ 	/* Check that no PIRQs are still bound. */
+-	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + NR_PIRQS); irq++) {
++	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + nr_pirqs); irq++) {
+ 		cfg = irq_cfg(irq);
+ 		BUG_ON(cfg && cfg->info != IRQ_UNBOUND);
+ 	}
+@@ -1169,7 +1165,7 @@ int arch_init_chip_data(struct irq_desc 
+ {
+ 	if (!desc->chip_data) {
+ 		/* By default all event channels notify CPU#0. */
+-		desc->affinity = cpumask_of_cpu(0);
++		cpumask_copy(desc->affinity, cpumask_of(0));
+ 
+ 		desc->chip_data = kzalloc(sizeof(struct irq_cfg), GFP_ATOMIC);
+ 	}
+@@ -1183,11 +1179,44 @@ int arch_init_chip_data(struct irq_desc 
+ #endif
+ 
+ #if defined(CONFIG_X86_IO_APIC)
++#ifdef CONFIG_SPARSE_IRQ
++int nr_pirqs = NR_PIRQS;
++EXPORT_SYMBOL_GPL(nr_pirqs);
++
++int __init arch_probe_nr_irqs(void)
++{
++	int nr_irqs_gsi, nr = acpi_probe_gsi();
++
++	if (nr <= NR_IRQS_LEGACY) {
++		/* for acpi=off or acpi not compiled in */
++		int idx;
++
++		for (nr = idx = 0; idx < nr_ioapics; idx++)
++			nr += io_apic_get_redir_entries(idx) + 1;
++	}
++	nr_irqs_gsi = max(nr, NR_IRQS_LEGACY);
++
++	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
++#ifdef CONFIG_PCI_MSI
++	nr += nr_irqs_gsi * 16;
++#endif
++	if (nr_pirqs > nr) {
++		nr_pirqs = nr;
++		nr_irqs = nr + NR_DYNIRQS;
++	}
++
++	printk(KERN_DEBUG "nr_irqs_gsi=%d nr_pirqs=%d\n",
++	       nr_irqs_gsi, nr_pirqs);
++
++	return 0;
++}
++#endif
++
+ int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
+ {
+ 	struct physdev_irq irq_op;
+ 
+-	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
++	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= nr_pirqs)
+ 		return -EINVAL;
+ 
+ 	if (cfg->vector)
+@@ -1210,7 +1239,7 @@ int assign_irq_vector(int irq, struct ir
+ 
+ void evtchn_register_pirq(int irq)
+ {
+-	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS);
++	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE >= nr_pirqs);
+ 	if (identity_mapped_irq(irq) || type_from_irq(irq) != IRQT_UNBOUND)
+ 		return;
+ 	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, irq, 0);
+@@ -1223,7 +1252,7 @@ int evtchn_map_pirq(int irq, int xen_pir
+ 	if (irq < 0) {
+ 		static DEFINE_SPINLOCK(irq_alloc_lock);
+ 
+-		irq = PIRQ_BASE + NR_PIRQS - 1;
++		irq = PIRQ_BASE + nr_pirqs - 1;
+ 		spin_lock(&irq_alloc_lock);
+ 		do {
+ 			struct irq_desc *desc;
+@@ -1283,7 +1312,7 @@ void __init xen_init_IRQ(void)
+ 	init_evtchn_cpu_bindings();
+ 
+ 	pirq_needs_eoi = alloc_bootmem_pages(sizeof(unsigned long)
+-		* BITS_TO_LONGS(ALIGN(NR_PIRQS, PAGE_SIZE * 8)));
++		* BITS_TO_LONGS(ALIGN(nr_pirqs, PAGE_SIZE * 8)));
+  	eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
+ 	if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
+ 		pirq_eoi_does_unmask = true;
+@@ -1299,7 +1328,7 @@ void __init xen_init_IRQ(void)
+ 					      handle_level_irq, "level");
+ 	}
+ 
+-	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
++	for (i = PIRQ_BASE; i < (PIRQ_BASE + nr_pirqs); i++) {
+ #else
+ 	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_IRQS_LEGACY); i++) {
+ #endif
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:52:02.000000000 +0100
+@@ -18,7 +18,6 @@
+ #include <linux/cpu.h>
+ #include <linux/percpu.h>
+ #include <asm/desc.h>
+-#include <asm/arch_hooks.h>
+ #include <asm/pgalloc.h>
+ #include <xen/evtchn.h>
+ #include <xen/interface/vcpu.h>
+@@ -54,8 +53,8 @@ static char call1func_name[NR_CPUS][15];
+ #define set_cpu_to_apicid(cpu, apicid)
+ #endif
+ 
+-DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DEFINE_PER_CPU(cpumask_t, cpu_core_map);
++DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
++DEFINE_PER_CPU(cpumask_var_t, cpu_core_map);
+ 
+ void __init prefill_possible_map(void)
+ {
+@@ -80,8 +79,8 @@ set_cpu_sibling_map(unsigned int cpu)
+ 	cpu_data(cpu).phys_proc_id = cpu;
+ 	cpu_data(cpu).cpu_core_id  = 0;
+ 
+-	per_cpu(cpu_sibling_map, cpu) = cpumask_of_cpu(cpu);
+-	per_cpu(cpu_core_map, cpu) = cpumask_of_cpu(cpu);
++	cpumask_copy(cpu_sibling_mask(cpu), cpumask_of(cpu));
++	cpumask_copy(cpu_core_mask(cpu), cpumask_of(cpu));
+ 
+ 	cpu_data(cpu).booted_cores = 1;
+ }
+@@ -92,8 +91,8 @@ remove_siblinginfo(unsigned int cpu)
+ 	cpu_data(cpu).phys_proc_id = BAD_APICID;
+ 	cpu_data(cpu).cpu_core_id  = BAD_APICID;
+ 
+-	cpus_clear(per_cpu(cpu_sibling_map, cpu));
+-	cpus_clear(per_cpu(cpu_core_map, cpu));
++	cpumask_clear(cpu_sibling_mask(cpu));
++	cpumask_clear(cpu_core_mask(cpu));
+ 
+ 	cpu_data(cpu).booted_cores = 0;
+ }
+@@ -216,7 +215,7 @@ static void __cpuinit cpu_initialize_con
+ 	smp_trap_init(ctxt.trap_ctxt);
+ 
+ 	ctxt.ldt_ents = 0;
+-	ctxt.gdt_frames[0] = virt_to_mfn(get_cpu_gdt_table(cpu));
++	ctxt.gdt_frames[0] = arbitrary_virt_to_mfn(get_cpu_gdt_table(cpu));
+ 	ctxt.gdt_ents = GDT_SIZE / 8;
+ 
+ 	ctxt.user_regs.cs = __KERNEL_CS;
+@@ -234,12 +233,13 @@ static void __cpuinit cpu_initialize_con
+ 	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
+ 
+ 	ctxt.user_regs.fs = __KERNEL_PERCPU;
++	ctxt.user_regs.gs = __KERNEL_STACK_CANARY;
+ #else /* __x86_64__ */
+ 	ctxt.syscall_callback_eip  = (unsigned long)system_call;
+ 
+ 	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
+ 
+-	ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu));
++	ctxt.gs_base_kernel = per_cpu_offset(cpu);
+ #endif
+ 
+ 	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt))
+@@ -267,8 +267,10 @@ void __init smp_prepare_cpus(unsigned in
+ 	current_thread_info()->cpu = 0;
+ 
+ 	for_each_possible_cpu (cpu) {
+-		cpus_clear(per_cpu(cpu_sibling_map, cpu));
+-		cpus_clear(per_cpu(cpu_core_map, cpu));
++		alloc_cpumask_var(&per_cpu(cpu_sibling_map, cpu), GFP_KERNEL);
++		alloc_cpumask_var(&per_cpu(cpu_core_map, cpu), GFP_KERNEL);
++		cpumask_clear(cpu_sibling_mask(cpu));
++		cpumask_clear(cpu_core_mask(cpu));
+ 	}
+ 
+ 	set_cpu_sibling_map(0);
+@@ -295,9 +297,6 @@ void __init smp_prepare_cpus(unsigned in
+ 		if (IS_ERR(idle))
+ 			panic("failed fork for CPU %d", cpu);
+ 
+-#ifdef __i386__
+-		init_gdt(cpu);
+-#endif
+ 		gdt_addr = get_cpu_gdt_table(cpu);
+ 		make_page_readonly(gdt_addr, XENFEAT_writable_descriptor_tables);
+ 
+@@ -311,12 +310,12 @@ void __init smp_prepare_cpus(unsigned in
+ 		set_cpu_to_apicid(cpu, apicid);
+ 
+ #ifdef __x86_64__
+-		cpu_pda(cpu)->pcurrent = idle;
+-		cpu_pda(cpu)->cpunumber = cpu;
+ 		clear_tsk_thread_flag(idle, TIF_FORK);
+-#else
+-	 	per_cpu(current_task, cpu) = idle;
++		per_cpu(kernel_stack, cpu) =
++			(unsigned long)task_stack_page(idle) -
++			KERNEL_STACK_OFFSET + THREAD_SIZE;
+ #endif
++	 	per_cpu(current_task, cpu) = idle;
+ 
+ 		irq_ctx_init(cpu);
+ 
+@@ -340,10 +339,7 @@ void __init smp_prepare_cpus(unsigned in
+ 
+ void __init smp_prepare_boot_cpu(void)
+ {
+-#ifdef __i386__
+-	init_gdt(smp_processor_id());
+-#endif
+-	switch_to_new_gdt();
++	switch_to_new_gdt(smp_processor_id());
+ 	prefill_possible_map();
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/spinlock.c	2009-11-17 14:57:38.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/spinlock.c	2010-01-18 16:53:32.000000000 +0100
+@@ -59,7 +59,7 @@ void __cpuinit xen_spinlock_cleanup(unsi
+ 
+ int xen_spin_wait(raw_spinlock_t *lock, unsigned int token)
+ {
+-	int rc = 0, irq = __get_cpu_var(spinlock_irq);
++	int rc = 0, irq = percpu_read(spinlock_irq);
+ 	raw_rwlock_t *rm_lock;
+ 	unsigned long flags;
+ 	struct spinning spinning;
+@@ -73,9 +73,9 @@ int xen_spin_wait(raw_spinlock_t *lock, 
+ 	/* announce we're spinning */
+ 	spinning.ticket = token;
+ 	spinning.lock = lock;
+-	spinning.prev = x86_read_percpu(spinning);
++	spinning.prev = percpu_read(spinning);
+ 	smp_wmb();
+-	x86_write_percpu(spinning, &spinning);
++	percpu_write(spinning, &spinning);
+ 
+ 	/* clear pending */
+ 	xen_clear_irq_pending(irq);
+@@ -103,7 +103,7 @@ int xen_spin_wait(raw_spinlock_t *lock, 
+ 		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ 
+ 	/* announce we're done */
+-	x86_write_percpu(spinning, spinning.prev);
++	percpu_write(spinning, spinning.prev);
+ 	rm_lock = &__get_cpu_var(spinning_rm_lock);
+ 	raw_local_irq_save(flags);
+ 	__raw_write_lock(rm_lock);
+@@ -117,7 +117,7 @@ unsigned int xen_spin_adjust(raw_spinloc
+ {
+ 	struct spinning *spinning;
+ 
+-	for (spinning = x86_read_percpu(spinning); spinning; spinning = spinning->prev)
++	for (spinning = percpu_read(spinning); spinning; spinning = spinning->prev)
+ 		if (spinning->lock == lock) {
+ 			unsigned int ticket = spinning->ticket;
+ 
+@@ -144,9 +144,9 @@ int xen_spin_wait_flags(raw_spinlock_t *
+ 	/* announce we're spinning */
+ 	spinning.ticket = *ptok >> TICKET_SHIFT;
+ 	spinning.lock = lock;
+-	spinning.prev = x86_read_percpu(spinning);
++	spinning.prev = percpu_read(spinning);
+ 	smp_wmb();
+-	x86_write_percpu(spinning, &spinning);
++	percpu_write(spinning, &spinning);
+ 
+ 	for (nested = spinning.prev; nested; nested = nested->prev)
+ 		if (nested->lock == lock)
+@@ -185,7 +185,7 @@ int xen_spin_wait_flags(raw_spinlock_t *
+ 		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ 
+ 	/* announce we're done */
+-	x86_write_percpu(spinning, spinning.prev);
++	percpu_write(spinning, spinning.prev);
+ 	rm_lock = &__get_cpu_var(spinning_rm_lock);
+ 	__raw_write_lock(rm_lock);
+ 	__raw_write_unlock(rm_lock);
+--- head-2010-01-18.orig/drivers/xen/netback/interface.c	2010-01-04 12:40:36.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/interface.c	2010-01-04 12:40:53.000000000 +0100
+@@ -121,7 +121,7 @@ static void netbk_get_drvinfo(struct net
+ 			      struct ethtool_drvinfo *info)
+ {
+ 	strcpy(info->driver, "netbk");
+-	strcpy(info->bus_info, dev->dev.parent->bus_id);
++	strcpy(info->bus_info, dev_name(dev->dev.parent));
+ }
+ 
+ static const struct netif_stat {
+--- head-2010-01-18.orig/drivers/xen/netback/netback.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/netback.c	2010-01-04 12:40:57.000000000 +0100
+@@ -333,7 +333,7 @@ int netif_be_start_xmit(struct sk_buff *
+ 			 */
+ 			netif->tx_queue_timeout.data = (unsigned long)netif;
+ 			netif->tx_queue_timeout.function = tx_queue_callback;
+-			__mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
++			mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
+ 		}
+ 	}
+ 
+@@ -354,7 +354,7 @@ static void xen_network_done_notify(void
+ 	static struct net_device *eth0_dev = NULL;
+ 	if (unlikely(eth0_dev == NULL))
+ 		eth0_dev = __dev_get_by_name(&init_net, "eth0");
+-	netif_rx_schedule(???);
++	napi_schedule(???);
+ }
+ /* 
+  * Add following to poll() function in NAPI driver (Tigon3 is example):
+@@ -1308,8 +1308,7 @@ static void net_tx_action(unsigned long 
+ 					(unsigned long)netif;
+ 				netif->credit_timeout.function =
+ 					tx_credit_callback;
+-				__mod_timer(&netif->credit_timeout,
+-					    next_credit);
++				mod_timer(&netif->credit_timeout, next_credit);
+ 				netif_put(netif);
+ 				continue;
+ 			}
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:52:02.000000000 +0100
+@@ -102,7 +102,7 @@ static const int MODPARM_rx_flip = 0;
+ static inline void dev_disable_gso_features(struct net_device *dev)
+ {
+ 	/* Turn off all GSO bits except ROBUST. */
+-	dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
++	dev->features &= ~NETIF_F_GSO_MASK;
+ 	dev->features |= NETIF_F_GSO_ROBUST;
+ }
+ #elif defined(NETIF_F_TSO)
+@@ -635,7 +635,7 @@ static int network_open(struct net_devic
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(&np->napi);
++			napi_schedule(&np->napi);
+ 		}
+ 	}
+ 	spin_unlock_bh(&np->rx_lock);
+@@ -707,7 +707,7 @@ static void rx_refill_timeout(unsigned l
+ 
+ 	netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-	netif_rx_schedule(&np->napi);
++	napi_schedule(&np->napi);
+ }
+ 
+ static void network_alloc_rx_buffers(struct net_device *dev)
+@@ -1064,7 +1064,7 @@ static irqreturn_t netif_int(int irq, vo
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(&np->napi);
++			napi_schedule(&np->napi);
+ 		}
+ 	}
+ 
+@@ -1521,7 +1521,7 @@ err:	
+ 		}
+ 
+ 		if (!more_to_do && !accel_more_to_do)
+-			__netif_rx_complete(napi);
++			__napi_complete(napi);
+ 
+ 		local_irq_restore(flags);
+ 	}
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:52:02.000000000 +0100
+@@ -47,7 +47,7 @@ static void vnic_start_interrupts(netfro
+ 		netfront_accel_disable_net_interrupts(vnic);
+ 		vnic->irq_enabled = 0;
+ 		NETFRONT_ACCEL_STATS_OP(vnic->stats.poll_schedule_count++);
+-		netif_rx_schedule(&np->napi);
++		napi_schedule(&np->napi);
+ 	} else {
+ 		/*
+ 		 * Nothing yet, make sure we get interrupts through
+@@ -532,7 +532,7 @@ irqreturn_t netfront_accel_net_channel_i
+ 				vnic->stats.event_count_since_irq;
+ 		vnic->stats.event_count_since_irq = 0;
+ #endif
+-		netif_rx_schedule(&np->napi);
++		napi_schedule(&np->napi);
+ 	}
+ 	else {
+ 		spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
+--- head-2010-01-18.orig/drivers/xen/usbback/usbstub.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/usbstub.c	2009-11-06 10:52:02.000000000 +0100
+@@ -188,7 +188,7 @@ static int usbstub_probe(struct usb_inte
+ 		const struct usb_device_id *id)
+ {
+ 	struct usb_device *udev = interface_to_usbdev(intf);
+-	char *busid = intf->dev.parent->bus_id;
++	const char *busid = dev_name(intf->dev.parent);
+ 	struct vusb_port_id *portid = NULL;
+ 	struct usbstub *stub = NULL;
+ 	usbif_t *usbif = NULL;
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-dbg.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-dbg.c	2009-11-06 10:52:02.000000000 +0100
+@@ -64,7 +64,7 @@ static ssize_t show_statistics(struct de
+ 			"%s\n"
+ 			"xenhcd, hcd state %d\n",
+ 			hcd->self.controller->bus->name,
+-			hcd->self.controller->bus_id,
++			dev_name(hcd->self.controller),
+ 			hcd->product_desc,
+ 			hcd->state);
+ 	size -= temp;
+--- head-2010-01-18.orig/drivers/xen/usbfront/xenbus.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/xenbus.c	2009-11-06 10:52:02.000000000 +0100
+@@ -240,10 +240,10 @@ static struct usb_hcd *create_hcd(struct
+ 	}
+ 	switch (usb_ver) {
+ 	case USB_VER_USB11:
+-		hcd = usb_create_hcd(&xen_usb11_hc_driver, &dev->dev, dev->dev.bus_id);
++		hcd = usb_create_hcd(&xen_usb11_hc_driver, &dev->dev, dev_name(&dev->dev));
+ 		break;
+ 	case USB_VER_USB20:
+-		hcd = usb_create_hcd(&xen_usb20_hc_driver, &dev->dev, dev->dev.bus_id);
++		hcd = usb_create_hcd(&xen_usb20_hc_driver, &dev->dev, dev_name(&dev->dev));
+ 		break;
+ 	default:
+ 		xenbus_dev_fatal(dev, err, "invalid usb-ver");
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:28:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:52:02.000000000 +0100
+@@ -230,7 +230,7 @@ static struct xen_bus_type xenbus_fronte
+ 	},
+ #if defined(CONFIG_XEN) || defined(MODULE)
+ 	.dev = {
+-		.bus_id = "xen",
++		.init_name = "xen",
+ 	},
+ #endif
+ };
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:52:02.000000000 +0100
+@@ -129,7 +129,7 @@ static struct xen_bus_type xenbus_backen
+ 		.dev_attrs = xenbus_backend_attrs,
+ 	},
+ 	.dev = {
+-		.bus_id = "xen-backend",
++		.init_name = "xen-backend",
+ 	},
+ };
+ 
+--- head-2010-01-18.orig/include/linux/interrupt.h	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/include/linux/interrupt.h	2009-11-06 10:52:02.000000000 +0100
+@@ -52,6 +52,7 @@
+  * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
+  *                Used by threaded interrupts which need to keep the
+  *                irq line disabled until the threaded handler has been run.
++ * IRQF_NO_SUSPEND - Prevent this interrupt from being disabled during suspend.
+  */
+ #define IRQF_DISABLED		0x00000020
+ #define IRQF_SAMPLE_RANDOM	0x00000040
+@@ -62,6 +63,7 @@
+ #define IRQF_NOBALANCING	0x00000800
+ #define IRQF_IRQPOLL		0x00001000
+ #define IRQF_ONESHOT		0x00002000
++#define IRQF_NO_SUSPEND		0x00008000
+ 
+ /*
+  * Bits used by threaded handlers:
+--- head-2010-01-18.orig/kernel/irq/manage.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/kernel/irq/manage.c	2009-11-06 10:52:02.000000000 +0100
+@@ -200,7 +200,8 @@ static inline int setup_affinity(unsigne
+ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
+ {
+ 	if (suspend) {
+-		if (!desc->action || (desc->action->flags & IRQF_TIMER))
++		if (!desc->action ||
++		    (desc->action->flags & (IRQF_TIMER | IRQF_NO_SUSPEND)))
+ 			return;
+ 		desc->status |= IRQ_SUSPENDED;
+ 	}
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-12-14 17:27:59.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-12-14 17:28:34.000000000 +0100
+@@ -175,7 +175,7 @@ static void *swiotlb_bus_to_virt(dma_add
+ 	return phys_to_virt(swiotlb_bus_to_phys(address));
+ }
+ 
+-int __weak swiotlb_arch_range_needs_mapping(void *ptr, size_t size)
++int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
+ {
+ 	return 0;
+ }
+@@ -523,13 +523,13 @@ swiotlb_full(struct device *dev, size_t 
+  * Once the device is given the dma address, the device owns this memory until
+  * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
+  */
+-static dma_addr_t
+-_swiotlb_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
+-			 int dir, struct dma_attrs *attrs)
+-{
+-	struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
+-	dma_addr_t dev_addr = gnttab_dma_map_page(page) +
+-			      offset_in_page(paddr);
++dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
++			    unsigned long offset, size_t size,
++			    enum dma_data_direction dir,
++			    struct dma_attrs *attrs)
++{
++	phys_addr_t phys = page_to_pseudophys(page) + offset;
++	dma_addr_t dev_addr = gnttab_dma_map_page(page) + offset;
+ 	void *map;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+@@ -539,44 +539,24 @@ _swiotlb_map_single(struct device *hwdev
+ 	 * we can safely return the device addr and not worry about bounce
+ 	 * buffering it.
+ 	 */
+-	if (!address_needs_mapping(hwdev, dev_addr, size) &&
+-	    !range_needs_mapping(paddr, size))
++	if (!address_needs_mapping(dev, dev_addr, size) &&
++	    !range_needs_mapping(phys, size))
+ 		return dev_addr;
+ 
+ 	/*
+ 	 * Oh well, have to allocate and map a bounce buffer.
+ 	 */
+ 	gnttab_dma_unmap_page(dev_addr);
+-	map = map_single(hwdev, paddr, size, dir);
++	map = map_single(dev, phys, size, dir);
+ 	if (!map) {
+-		swiotlb_full(hwdev, size, dir, 1);
++		swiotlb_full(dev, size, dir, 1);
+ 		map = io_tlb_overflow_buffer;
+ 	}
+ 
+-	dev_addr = swiotlb_virt_to_bus(hwdev, map);
++	dev_addr = swiotlb_virt_to_bus(dev, map);
+ 	return dev_addr;
+ }
+-
+-dma_addr_t
+-swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
+-			 int dir, struct dma_attrs *attrs)
+-{
+-	return _swiotlb_map_single(hwdev, virt_to_phys(ptr), size, dir, attrs);
+-}
+-EXPORT_SYMBOL(swiotlb_map_single_attrs);
+-
+-dma_addr_t
+-swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+-{
+-	return _swiotlb_map_single(hwdev, virt_to_phys(ptr), size, dir, NULL);
+-}
+-EXPORT_SYMBOL(swiotlb_map_single);
+-
+-dma_addr_t
+-swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
+-{
+-	return _swiotlb_map_single(hwdev, paddr, size, dir, NULL);
+-}
++EXPORT_SYMBOL_GPL(swiotlb_map_page);
+ 
+ /*
+  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
+@@ -586,9 +566,9 @@ swiotlb_map_single_phys(struct device *h
+  * After this call, reads by the cpu to the buffer are guaranteed to see
+  * whatever the device wrote there.
+  */
+-void
+-swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
+-			   size_t size, int dir, struct dma_attrs *attrs)
++void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
++			size_t size, enum dma_data_direction dir,
++			struct dma_attrs *attrs)
+ {
+ 	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+@@ -598,15 +578,7 @@ swiotlb_unmap_single_attrs(struct device
+ 	else
+ 		gnttab_dma_unmap_page(dev_addr);
+ }
+-EXPORT_SYMBOL(swiotlb_unmap_single_attrs);
+-
+-void
+-swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
+-		     int dir)
+-{
+-	return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
+-}
+-EXPORT_SYMBOL(swiotlb_unmap_single);
++EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
+ 
+ /*
+  * Make physical memory consistent for a single streaming mode DMA translation
+@@ -620,7 +592,7 @@ EXPORT_SYMBOL(swiotlb_unmap_single);
+  */
+ void
+ swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+-			    size_t size, int dir)
++			    size_t size, enum dma_data_direction dir)
+ {
+ 	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+@@ -632,7 +604,7 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_cp
+ 
+ void
+ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+-			       size_t size, int dir)
++			       size_t size, enum dma_data_direction dir)
+ {
+ 	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+@@ -644,7 +616,8 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_de
+ 
+ void
+ swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+-				  unsigned long offset, size_t size, int dir)
++				  unsigned long offset, size_t size,
++				  enum dma_data_direction dir)
+ {
+ 	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+@@ -656,7 +629,8 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_ra
+ 
+ void
+ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+-				     unsigned long offset, size_t size, int dir)
++				     unsigned long offset, size_t size,
++				     enum dma_data_direction dir)
+ {
+ 	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+@@ -684,7 +658,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_ra
+  */
+ int
+ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
+-		     int dir, struct dma_attrs *attrs)
++		     enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+ 	struct scatterlist *sg;
+ 	int i;
+@@ -736,7 +710,7 @@ EXPORT_SYMBOL(swiotlb_map_sg);
+  */
+ void
+ swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
+-		       int nelems, int dir, struct dma_attrs *attrs)
++		       int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+ 	struct scatterlist *sg;
+ 	int i;
+@@ -770,7 +744,7 @@ EXPORT_SYMBOL(swiotlb_unmap_sg);
+  */
+ void
+ swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sgl,
+-			int nelems, int dir)
++			int nelems, enum dma_data_direction dir)
+ {
+ 	struct scatterlist *sg;
+ 	int i;
+@@ -787,7 +761,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
+ 
+ void
+ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sgl,
+-			   int nelems, int dir)
++			   int nelems, enum dma_data_direction dir)
+ {
+ 	struct scatterlist *sg;
+ 	int i;
+--- head-2010-01-18.orig/mm/page_alloc.c	2009-12-04 10:49:40.000000000 +0100
++++ head-2010-01-18/mm/page_alloc.c	2009-12-04 11:30:00.000000000 +0100
+@@ -4662,11 +4662,9 @@ static void __setup_per_zone_wmarks(void
+ 	}
+ 
+ #ifdef CONFIG_XEN
+-	for_each_zone(zone) {
++	for_each_populated_zone(zone) {
+ 		unsigned int cpu;
+ 
+-		if (!populated_zone(zone))
+-			continue;
+ 		for_each_online_cpu(cpu) {
+ 			unsigned long high;
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-sysdev-suspend
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-sysdev-suspend
@@ -0,0 +1,506 @@
+From: jbeulich@novell.com
+Subject: use base kernel suspend/resume infrastructure
+Patch-mainline: obsolete
+
+... rather than calling just a few functions explicitly.
+
+--- head-2009-12-16.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:44:50.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/time-xen.c	2009-11-23 10:48:29.000000000 +0100
+@@ -70,6 +70,10 @@ static DEFINE_PER_CPU(struct vcpu_runsta
+ /* Must be signed, as it's compared with s64 quantities which can be -ve. */
+ #define NS_PER_TICK (1000000000LL/HZ)
+ 
++static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
++	.period_ns = NS_PER_TICK
++};
++
+ static void __clock_was_set(struct work_struct *unused)
+ {
+ 	clock_was_set();
+@@ -550,6 +554,17 @@ void mark_tsc_unstable(char *reason)
+ }
+ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+ 
++static void init_missing_ticks_accounting(unsigned int cpu)
++{
++	struct vcpu_runstate_info *runstate = setup_runstate_area(cpu);
++
++	per_cpu(processed_blocked_time, cpu) =
++		runstate->time[RUNSTATE_blocked];
++	per_cpu(processed_stolen_time, cpu) =
++		runstate->time[RUNSTATE_runnable] +
++		runstate->time[RUNSTATE_offline];
++}
++
+ static cycle_t cs_last;
+ 
+ static cycle_t xen_clocksource_read(struct clocksource *cs)
+@@ -586,11 +601,32 @@ static cycle_t xen_clocksource_read(stru
+ #endif
+ }
+ 
++/* No locking required. Interrupts are disabled on all CPUs. */
+ static void xen_clocksource_resume(void)
+ {
+-	extern void time_resume(void);
++	unsigned int cpu;
++
++	init_cpu_khz();
++
++	for_each_online_cpu(cpu) {
++		switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
++					   &xen_set_periodic_tick)) {
++		case 0:
++#if CONFIG_XEN_COMPAT <= 0x030004
++		case -ENOSYS:
++#endif
++			break;
++		default:
++			BUG();
++		}
++		get_time_values_from_xen(cpu);
++		per_cpu(processed_system_time, cpu) =
++			per_cpu(shadow_time, 0).system_timestamp;
++		init_missing_ticks_accounting(cpu);
++	}
++
++	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
+ 
+-	time_resume();
+ 	cs_last = local_clock();
+ }
+ 
+@@ -622,17 +658,6 @@ struct vcpu_runstate_info *setup_runstat
+ 	return runstate;
+ }
+ 
+-static void init_missing_ticks_accounting(unsigned int cpu)
+-{
+-	struct vcpu_runstate_info *runstate = setup_runstate_area(cpu);
+-
+-	per_cpu(processed_blocked_time, cpu) =
+-		runstate->time[RUNSTATE_blocked];
+-	per_cpu(processed_stolen_time, cpu) =
+-		runstate->time[RUNSTATE_runnable] +
+-		runstate->time[RUNSTATE_offline];
+-}
+-
+ void xen_read_persistent_clock(struct timespec *ts)
+ {
+ 	const shared_info_t *s = HYPERVISOR_shared_info;
+@@ -678,10 +703,6 @@ static void __init setup_cpu0_timer_irq(
+ 	BUG_ON(per_cpu(timer_irq, 0) < 0);
+ }
+ 
+-static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
+-	.period_ns = NS_PER_TICK
+-};
+-
+ void __init time_init(void)
+ {
+ 	init_cpu_khz();
+@@ -806,35 +827,6 @@ void xen_halt(void)
+ }
+ EXPORT_SYMBOL(xen_halt);
+ 
+-/* No locking required. Interrupts are disabled on all CPUs. */
+-void time_resume(void)
+-{
+-	unsigned int cpu;
+-
+-	init_cpu_khz();
+-
+-	for_each_online_cpu(cpu) {
+-		switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+-					   &xen_set_periodic_tick)) {
+-		case 0:
+-#if CONFIG_XEN_COMPAT <= 0x030004
+-		case -ENOSYS:
+-#endif
+-			break;
+-		default:
+-			BUG();
+-		}
+-		get_time_values_from_xen(cpu);
+-		per_cpu(processed_system_time, cpu) =
+-			per_cpu(shadow_time, 0).system_timestamp;
+-		init_missing_ticks_accounting(cpu);
+-	}
+-
+-	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
+-
+-	update_wallclock();
+-}
+-
+ #ifdef CONFIG_SMP
+ static char timer_name[NR_CPUS][15];
+ 
+--- head-2009-12-16.orig/drivers/xen/core/evtchn.c	2009-11-06 11:04:38.000000000 +0100
++++ head-2009-12-16/drivers/xen/core/evtchn.c	2009-11-06 11:10:15.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
++#include <linux/sysdev.h>
+ #include <linux/ftrace.h>
+ #include <linux/version.h>
+ #include <asm/atomic.h>
+@@ -1109,10 +1110,21 @@ static void restore_cpu_ipis(unsigned in
+ 	}
+ }
+ 
+-void irq_resume(void)
++static int evtchn_resume(struct sys_device *dev)
+ {
+ 	unsigned int cpu, irq, evtchn;
+ 	struct irq_cfg *cfg;
++	struct evtchn_status status;
++
++	/* Avoid doing anything in the 'suspend cancelled' case. */
++	status.dom = DOMID_SELF;
++	status.port = evtchn_from_irq(percpu_read(virq_to_irq[VIRQ_TIMER]));
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status))
++		BUG();
++	if (status.status == EVTCHNSTAT_virq
++	    && status.vcpu == smp_processor_id()
++	    && status.u.virq == VIRQ_TIMER)
++		return 0;
+ 
+ 	init_evtchn_cpu_bindings();
+ 
+@@ -1148,7 +1160,32 @@ void irq_resume(void)
+ 		restore_cpu_ipis(cpu);
+ 	}
+ 
++	return 0;
++}
++
++static struct sysdev_class evtchn_sysclass = {
++	.name		= "evtchn",
++	.resume		= evtchn_resume,
++};
++
++static struct sys_device device_evtchn = {
++	.id		= 0,
++	.cls		= &evtchn_sysclass,
++};
++
++static int __init evtchn_register(void)
++{
++	int err;
++
++	if (is_initial_xendomain())
++		return 0;
++
++	err = sysdev_class_register(&evtchn_sysclass);
++	if (!err)
++		err = sysdev_register(&device_evtchn);
++	return err;
+ }
++core_initcall(evtchn_register);
+ #endif
+ 
+ int __init arch_early_irq_init(void)
+--- head-2009-12-16.orig/drivers/xen/core/gnttab.c	2009-12-15 09:24:56.000000000 +0100
++++ head-2009-12-16/drivers/xen/core/gnttab.c	2009-12-15 09:28:00.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/seqlock.h>
++#include <linux/sysdev.h>
+ #include <xen/interface/xen.h>
+ #include <xen/gnttab.h>
+ #include <asm/pgtable.h>
+@@ -707,23 +708,37 @@ EXPORT_SYMBOL(gnttab_post_map_adjust);
+ 
+ #endif /* __HAVE_ARCH_PTE_SPECIAL */
+ 
+-int gnttab_resume(void)
++static int gnttab_resume(struct sys_device *dev)
+ {
+ 	if (max_nr_grant_frames() < nr_grant_frames)
+ 		return -ENOSYS;
+ 	return gnttab_map(0, nr_grant_frames - 1);
+ }
++#define gnttab_resume() gnttab_resume(NULL)
+ 
+ #ifdef CONFIG_PM_SLEEP
+-int gnttab_suspend(void)
+-{
+ #ifdef CONFIG_X86
++static int gnttab_suspend(struct sys_device *dev, pm_message_t state)
++{
+ 	apply_to_page_range(&init_mm, (unsigned long)shared,
+ 			    PAGE_SIZE * nr_grant_frames,
+ 			    unmap_pte_fn, NULL);
+-#endif
+ 	return 0;
+ }
++#else
++#define gnttab_suspend NULL
++#endif
++
++static struct sysdev_class gnttab_sysclass = {
++	.name		= "gnttab",
++	.resume		= gnttab_resume,
++	.suspend	= gnttab_suspend,
++};
++
++static struct sys_device device_gnttab = {
++	.id		= 0,
++	.cls		= &gnttab_sysclass,
++};
+ #endif
+ 
+ #else /* !CONFIG_XEN */
+@@ -803,6 +818,17 @@ int __devinit gnttab_init(void)
+ 	if (!is_running_on_xen())
+ 		return -ENODEV;
+ 
++#if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP)
++	if (!is_initial_xendomain()) {
++		int err = sysdev_class_register(&gnttab_sysclass);
++
++		if (!err)
++			err = sysdev_register(&device_gnttab);
++		if (err)
++			return err;
++	}
++#endif
++
+ 	nr_grant_frames = 1;
+ 	boot_max_nr_grant_frames = __max_nr_grant_frames();
+ 
+--- head-2009-12-16.orig/drivers/xen/core/machine_reboot.c	2009-12-18 13:34:27.000000000 +0100
++++ head-2009-12-16/drivers/xen/core/machine_reboot.c	2009-12-18 14:19:13.000000000 +0100
+@@ -17,6 +17,7 @@
+ #include <xen/xencons.h>
+ #include <xen/cpu_hotplug.h>
+ #include <xen/interface/vcpu.h>
++#include "../../base/base.h"
+ 
+ #if defined(__i386__) || defined(__x86_64__)
+ #include <asm/pci_x86.h>
+@@ -145,47 +146,28 @@ struct suspend {
+ static int take_machine_down(void *_suspend)
+ {
+ 	struct suspend *suspend = _suspend;
+-	int suspend_cancelled, err;
+-	extern void time_resume(void);
++	int suspend_cancelled;
+ 
+-	if (suspend->fast_suspend) {
+-		BUG_ON(!irqs_disabled());
+-	} else {
+-		BUG_ON(irqs_disabled());
+-
+-		for (;;) {
+-			err = smp_suspend();
+-			if (err)
+-				return err;
+-
+-			xenbus_suspend();
+-			preempt_disable();
+-
+-			if (num_online_cpus() == 1)
+-				break;
+-
+-			preempt_enable();
+-			xenbus_suspend_cancel();
+-		}
+-
+-		local_irq_disable();
+-	}
++	BUG_ON(!irqs_disabled());
+ 
+ 	mm_pin_all();
+-	gnttab_suspend();
+-	pre_suspend();
+-
+-	/*
+-	 * This hypercall returns 1 if suspend was cancelled or the domain was
+-	 * merely checkpointed, and 0 if it is resuming in a new domain.
+-	 */
+-	suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
++	suspend_cancelled = sysdev_suspend(PMSG_SUSPEND);
++	if (!suspend_cancelled) {
++		pre_suspend();
+ 
++		/*
++		 * This hypercall returns 1 if suspend was cancelled or the domain was
++		 * merely checkpointed, and 0 if it is resuming in a new domain.
++		 */
++		suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
++	} else
++		BUG_ON(suspend_cancelled > 0);
+ 	suspend->resume_notifier(suspend_cancelled);
+-	post_suspend(suspend_cancelled);
+-	gnttab_resume();
++	if (suspend_cancelled >= 0) {
++		post_suspend(suspend_cancelled);
++		sysdev_resume();
++	}
+ 	if (!suspend_cancelled) {
+-		irq_resume();
+ #ifdef __x86_64__
+ 		/*
+ 		 * Older versions of Xen do not save/restore the user %cr3.
+@@ -197,10 +179,6 @@ static int take_machine_down(void *_susp
+ 				current->active_mm->pgd)));
+ #endif
+ 	}
+-	time_resume();
+-
+-	if (!suspend->fast_suspend)
+-		local_irq_enable();
+ 
+ 	return suspend_cancelled;
+ }
+@@ -208,8 +186,14 @@ static int take_machine_down(void *_susp
+ int __xen_suspend(int fast_suspend, void (*resume_notifier)(int))
+ {
+ 	int err, suspend_cancelled;
++	const char *what;
+ 	struct suspend suspend;
+ 
++#define _check(fn, args...) ({ \
++	what = #fn; \
++	err = (fn)(args); \
++})
++
+ 	BUG_ON(smp_processor_id() != 0);
+ 	BUG_ON(in_interrupt());
+ 
+@@ -225,41 +209,91 @@ int __xen_suspend(int fast_suspend, void
+ 	if (num_possible_cpus() == 1)
+ 		fast_suspend = 0;
+ 
+-	if (fast_suspend) {
+-		err = stop_machine_create();
+-		if (err)
+-			return err;
++	if (fast_suspend && _check(stop_machine_create)) {
++		printk(KERN_ERR "%s() failed: %d\n", what, err);
++		return err;
+ 	}
+ 
+ 	suspend.fast_suspend = fast_suspend;
+ 	suspend.resume_notifier = resume_notifier;
+ 
++	if (_check(dpm_suspend_start, PMSG_SUSPEND)) {
++		if (fast_suspend)
++			stop_machine_destroy();
++		printk(KERN_ERR "%s() failed: %d\n", what, err);
++		return err;
++	}
++
+ 	if (fast_suspend) {
+ 		xenbus_suspend();
++
++		if (_check(dpm_suspend_noirq, PMSG_SUSPEND)) {
++			xenbus_suspend_cancel();
++			dpm_resume_end(PMSG_RESUME);
++			stop_machine_destroy();
++			printk(KERN_ERR "%s() failed: %d\n", what, err);
++			return err;
++		}
++
+ 		err = stop_machine(take_machine_down, &suspend,
+ 				   &cpumask_of_cpu(0));
+ 		if (err < 0)
+ 			xenbus_suspend_cancel();
+ 	} else {
++		BUG_ON(irqs_disabled());
++
++		for (;;) {
++			xenbus_suspend();
++
++			if (!_check(dpm_suspend_noirq, PMSG_SUSPEND)
++			    && _check(smp_suspend))
++				dpm_resume_noirq(PMSG_RESUME);
++			if (err) {
++				xenbus_suspend_cancel();
++				dpm_resume_end(PMSG_RESUME);
++				printk(KERN_ERR "%s() failed: %d\n",
++				       what, err);
++				return err;
++			}
++
++			preempt_disable();
++
++			if (num_online_cpus() == 1)
++				break;
++
++			preempt_enable();
++
++			dpm_resume_noirq(PMSG_RESUME);
++
++			xenbus_suspend_cancel();
++		}
++
++		local_irq_disable();
+ 		err = take_machine_down(&suspend);
++		local_irq_enable();
+ 	}
+ 
+-	if (err < 0)
+-		return err;
++	dpm_resume_noirq(PMSG_RESUME);
+ 
+-	suspend_cancelled = err;
+-	if (!suspend_cancelled) {
+-		xencons_resume();
+-		xenbus_resume();
+-	} else {
+-		xenbus_suspend_cancel();
++	if (err >= 0) {
++		suspend_cancelled = err;
++		if (!suspend_cancelled) {
++			xencons_resume();
++			xenbus_resume();
++		} else {
++			xenbus_suspend_cancel();
++			err = 0;
++		}
++
++		if (!fast_suspend)
++			smp_resume();
+ 	}
+ 
+-	if (!fast_suspend)
+-		smp_resume();
+-	else
++	dpm_resume_end(PMSG_RESUME);
++
++	if (fast_suspend)
+ 		stop_machine_destroy();
+ 
+-	return 0;
++	return err;
+ }
+ #endif
+--- head-2009-12-16.orig/include/xen/evtchn.h	2009-12-18 10:10:04.000000000 +0100
++++ head-2009-12-16/include/xen/evtchn.h	2009-12-18 10:13:12.000000000 +0100
+@@ -107,7 +107,9 @@ int bind_ipi_to_irqhandler(
+  */
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+ 
++#ifndef CONFIG_XEN
+ void irq_resume(void);
++#endif
+ 
+ /* Entry point for notifications into Linux subsystems. */
+ asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
+--- head-2009-12-16.orig/include/xen/gnttab.h	2008-11-04 11:13:10.000000000 +0100
++++ head-2009-12-16/include/xen/gnttab.h	2009-11-06 11:10:15.000000000 +0100
+@@ -110,8 +110,9 @@ static inline void __gnttab_dma_unmap_pa
+ 
+ void gnttab_reset_grant_page(struct page *page);
+ 
+-int gnttab_suspend(void);
++#ifndef CONFIG_XEN
+ int gnttab_resume(void);
++#endif
+ 
+ void *arch_gnttab_alloc_shared(unsigned long *frames);
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.3-4
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.3-4
@@ -0,0 +1,61 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.4
+Patch-mainline: 2.6.32.4
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.3-4" by xen-port-patches.py
+
+--- sle11sp1-2010-10-26.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 14:53:39.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/ia32/ia32entry-xen.S	2010-01-20 10:28:42.000000000 +0100
+@@ -589,7 +589,7 @@ ia32_sys_call_table:
+ 	.quad quiet_ni_syscall		/* streams2 */
+ 	.quad stub32_vfork            /* 190 */
+ 	.quad compat_sys_getrlimit
+-	.quad sys32_mmap2
++	.quad sys_mmap_pgoff
+ 	.quad sys32_truncate64
+ 	.quad sys32_ftruncate64
+ 	.quad sys32_stat64		/* 195 */
+--- sle11sp1-2010-10-26.orig/drivers/hwmon/coretemp-xen.c	2010-10-26 09:19:16.000000000 +0200
++++ sle11sp1-2010-10-26/drivers/hwmon/coretemp-xen.c	2010-10-26 09:19:30.000000000 +0200
+@@ -31,6 +31,7 @@
+ #include <linux/mutex.h>
+ #include <linux/list.h>
+ #include <linux/platform_device.h>
++#include <linux/pci.h>
+ #include <asm/msr.h>
+ #include <xen/pcpu.h>
+ #include "../xen/core/domctl.h"
+@@ -166,6 +167,7 @@ static int adjust_tjmax(struct coretemp_
+ 	int usemsr_ee = 1;
+ 	int err;
+ 	u32 eax, edx;
++	struct pci_dev *host_bridge;
+ 
+ 	/* Early chips have no MSR for TjMax */
+ 
+@@ -173,11 +175,21 @@ static int adjust_tjmax(struct coretemp_
+ 		usemsr_ee = 0;
+ 	}
+ 
+-	/* Atoms seems to have TjMax at 90C */
++	/* Atom CPUs */
+ 
+ 	if (c->x86_model == 0x1c) {
+ 		usemsr_ee = 0;
+-		tjmax = 90000;
++
++		host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
++
++		if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
++		    && (host_bridge->device == 0xa000	/* NM10 based nettop */
++		    || host_bridge->device == 0xa010))	/* NM10 based netbook */
++			tjmax = 100000;
++		else
++			tjmax = 90000;
++
++		pci_dev_put(host_bridge);
+ 	}
+ 
+ 	if ((c->x86_model > 0xe) && (usemsr_ee)) {
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.12-13
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.12-13
@@ -0,0 +1,47 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.13
+Patch-mainline: 2.6.32.13
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.12-13" by xen-port-patches.py
+
+--- sle11sp1-2010-11-04.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ sle11sp1-2010-11-04/arch/x86/kernel/acpi/sleep-xen.c	2010-05-20 11:32:32.000000000 +0200
+@@ -169,6 +169,8 @@ static int __init acpi_sleep_setup(char 
+ #endif
+ 		if (strncmp(str, "old_ordering", 12) == 0)
+ 			acpi_old_suspend_ordering();
++		if (strncmp(str, "sci_force_enable", 16) == 0)
++			acpi_set_sci_en_on_resume();
+ 		str = strchr(str, ',');
+ 		if (str != NULL)
+ 			str += strspn(str, ", \t");
+--- sle11sp1-2010-11-04.orig/arch/x86/kernel/cpu/intel.c	2010-11-04 13:14:33.000000000 +0100
++++ sle11sp1-2010-11-04/arch/x86/kernel/cpu/intel.c	2010-11-04 13:15:26.000000000 +0100
+@@ -61,6 +61,9 @@ static void __cpuinit early_init_intel(s
+ 	 * need the microcode to have already been loaded... so if it is
+ 	 * not, recommend a BIOS update and disable large pages.
+ 	 */
++#ifdef CONFIG_XEN
++	if (cpu_has(c, X86_FEATURE_PSE))
++#endif
+ 	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) {
+ 		u32 ucode, junk;
+ 
+--- sle11sp1-2010-11-04.orig/arch/x86/kernel/process_64-xen.c	2010-04-12 14:52:38.000000000 +0200
++++ sle11sp1-2010-11-04/arch/x86/kernel/process_64-xen.c	2010-05-20 11:32:32.000000000 +0200
+@@ -309,11 +309,10 @@ int copy_thread(unsigned long clone_flag
+ 
+ 	set_tsk_thread_flag(p, TIF_FORK);
+ 
+-	p->thread.fs = me->thread.fs;
+-	p->thread.gs = me->thread.gs;
+-
+ 	savesegment(gs, p->thread.gsindex);
++	p->thread.gs = p->thread.gsindex ? 0 : me->thread.gs;
+ 	savesegment(fs, p->thread.fsindex);
++	p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
+ 	savesegment(es, p->thread.es);
+ 	savesegment(ds, p->thread.ds);
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/tmem
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/tmem
@@ -0,0 +1,1241 @@
+Subject: Transcendent memory ("tmem") for Linux
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 908:baeb818cd2dc)
+Patch-mainline: obsolete
+
+Tmem, when called from a tmem-capable (paravirtualized) guest, makes
+use of otherwise unutilized ("fallow") memory to create and manage
+pools of pages that can be accessed from the guest either as
+"ephemeral" pages or as "persistent" pages. In either case, the pages
+are not directly addressible by the guest, only copied to and fro via
+the tmem interface. Ephemeral pages are a nice place for a guest to
+put recently evicted clean pages that it might need again; these pages
+can be reclaimed synchronously by Xen for other guests or other uses.
+Persistent pages are a nice place for a guest to put "swap" pages to
+avoid sending them to disk. These pages retain data as long as the
+guest lives, but count against the guest memory allocation.
+
+This patch contains the Linux paravirtualization changes to
+complement the tmem Xen patch (xen-unstable c/s 19646). It
+implements "precache" (ext3 only as of now), "preswap",
+and limited "shared precache" (ocfs2 only as of now) support.
+CONFIG options are required to turn on
+the support (but in this patch they default to "y"). If
+the underlying Xen does not have tmem support or has it
+turned off, this is sensed early to avoid nearly all
+hypercalls.
+
+Lots of useful prose about tmem can be found at
+http://oss.oracle.com/projects/tmem
+
+Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/fs/btrfs/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/btrfs/super.c	2009-12-17 21:50:16.000000000 +0100
+@@ -38,6 +38,7 @@
+ #include <linux/namei.h>
+ #include <linux/miscdevice.h>
+ #include <linux/magic.h>
++#include <linux/precache.h>
+ #include "compat.h"
+ #include "ctree.h"
+ #include "disk-io.h"
+@@ -387,6 +388,7 @@ static int btrfs_fill_super(struct super
+ 	sb->s_root = root_dentry;
+ 
+ 	save_mount_options(sb, data);
++	precache_init(sb);
+ 	return 0;
+ 
+ fail_close:
+--- head-2010-01-18.orig/fs/btrfs/extent_io.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/btrfs/extent_io.c	2009-12-17 23:28:33.000000000 +0100
+@@ -11,6 +11,7 @@
+ #include <linux/swap.h>
+ #include <linux/writeback.h>
+ #include <linux/pagevec.h>
++#include <linux/precache.h>
+ #include "extent_io.h"
+ #include "extent_map.h"
+ #include "compat.h"
+@@ -2015,6 +2016,13 @@ static int __extent_read_full_page(struc
+ 
+ 	set_page_extent_mapped(page);
+ 
++	if (!PageUptodate(page)) {
++		if (precache_get(page->mapping, page->index, page) == 1) {
++			BUG_ON(blocksize != PAGE_SIZE);
++			goto out;
++		}
++	}
++
+ 	end = page_end;
+ 	lock_extent(tree, start, end, GFP_NOFS);
+ 
+@@ -2131,6 +2139,7 @@ static int __extent_read_full_page(struc
+ 		cur = cur + iosize;
+ 		page_offset += iosize;
+ 	}
++out:
+ 	if (!nr) {
+ 		if (!PageError(page))
+ 			SetPageUptodate(page);
+--- head-2010-01-18.orig/fs/buffer.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/buffer.c	2009-12-04 10:29:25.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include <linux/mpage.h>
+ #include <linux/bit_spinlock.h>
+ #include <trace/fs.h>
++#include <linux/precache.h>
+ 
+ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
+ 
+@@ -282,6 +283,11 @@ void invalidate_bdev(struct block_device
+ 
+ 	invalidate_bh_lrus();
+ 	invalidate_mapping_pages(mapping, 0, -1);
++
++	/* 99% of the time, we don't need to flush the precache on the bdev.
++	 * But, for the strange corners, lets be cautious
++	 */
++	precache_flush_inode(mapping);
+ }
+ EXPORT_SYMBOL(invalidate_bdev);
+ 
+--- head-2010-01-18.orig/fs/ext3/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/ext3/super.c	2009-12-04 10:29:25.000000000 +0100
+@@ -38,6 +38,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/nfs4acl.h>
+ #include <linux/log2.h>
++#include <linux/precache.h>
+ 
+ #include <asm/uaccess.h>
+ 
+@@ -1334,6 +1335,7 @@ static int ext3_setup_super(struct super
+ 	} else {
+ 		printk("internal journal\n");
+ 	}
++	precache_init(sb);
+ 	return res;
+ }
+ 
+--- head-2010-01-18.orig/fs/ext4/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/ext4/super.c	2010-01-07 09:36:31.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/ctype.h>
+ #include <linux/log2.h>
+ #include <linux/crc16.h>
++#include <linux/precache.h>
+ #include <asm/uaccess.h>
+ 
+ #include "ext4.h"
+@@ -1685,6 +1686,8 @@ static int ext4_setup_super(struct super
+ 			EXT4_INODES_PER_GROUP(sb),
+ 			sbi->s_mount_opt);
+ 
++	precache_init(sb);
++
+ 	return res;
+ }
+ 
+--- head-2010-01-18.orig/fs/mpage.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/mpage.c	2009-12-04 10:29:25.000000000 +0100
+@@ -26,6 +26,7 @@
+ #include <linux/writeback.h>
+ #include <linux/backing-dev.h>
+ #include <linux/pagevec.h>
++#include <linux/precache.h>
+ 
+ /*
+  * I/O completion handler for multipage BIOs.
+@@ -285,6 +286,13 @@ do_mpage_readpage(struct bio *bio, struc
+ 		SetPageMappedToDisk(page);
+ 	}
+ 
++	if (fully_mapped &&
++	    blocks_per_page == 1 && !PageUptodate(page) &&
++	    precache_get(page->mapping, page->index, page) == 1) {
++		SetPageUptodate(page);
++		goto confused;
++	}
++
+ 	/*
+ 	 * This page will go to BIO.  Do we need to send this BIO off first?
+ 	 */
+--- head-2010-01-18.orig/fs/ocfs2/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/ocfs2/super.c	2010-01-18 15:40:59.000000000 +0100
+@@ -41,6 +41,7 @@
+ #include <linux/mount.h>
+ #include <linux/seq_file.h>
+ #include <linux/quotaops.h>
++#include <linux/precache.h>
+ #include <linux/smp_lock.h>
+ 
+ #define MLOG_MASK_PREFIX ML_SUPER
+@@ -2257,6 +2258,7 @@ static int ocfs2_initialize_super(struct
+ 		mlog_errno(status);
+ 		goto bail;
+ 	}
++	shared_precache_init(sb, &di->id2.i_super.s_uuid[0]);
+ 
+ bail:
+ 	mlog_exit(status);
+--- head-2010-01-18.orig/fs/reiserfs/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/reiserfs/super.c	2009-12-04 10:29:25.000000000 +0100
+@@ -26,6 +26,7 @@
+ #include <linux/vfs.h>
+ #include <linux/mount.h>
+ #include <linux/namei.h>
++#include <linux/precache.h>
+ #include <linux/crc32.h>
+ #include <linux/smp_lock.h>
+ 
+@@ -1854,6 +1855,7 @@ static int reiserfs_fill_super(struct su
+ 
+ 	init_waitqueue_head(&(sbi->s_wait));
+ 	spin_lock_init(&sbi->bitmap_lock);
++	precache_init(s);
+ 
+ 	return (0);
+ 
+--- head-2010-01-18.orig/fs/super.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/fs/super.c	2009-12-04 10:29:25.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include <linux/kobject.h>
+ #include <linux/mutex.h>
+ #include <linux/file.h>
++#include <linux/precache.h>
+ #include <asm/uaccess.h>
+ #include "internal.h"
+ 
+@@ -104,6 +105,9 @@ static struct super_block *alloc_super(s
+ 		s->s_qcop = sb_quotactl_ops;
+ 		s->s_op = &default_op;
+ 		s->s_time_gran = 1000000000;
++#ifdef CONFIG_PRECACHE
++		s->precache_poolid = -1;
++#endif
+ 	}
+ out:
+ 	return s;
+@@ -194,6 +198,7 @@ void deactivate_super(struct super_block
+ 		vfs_dq_off(s, 0);
+ 		down_write(&s->s_umount);
+ 		fs->kill_sb(s);
++		precache_flush_filesystem(s);
+ 		put_filesystem(fs);
+ 		put_super(s);
+ 	}
+@@ -881,6 +886,9 @@ int get_sb_nodev(struct file_system_type
+ 		return error;
+ 	}
+ 	s->s_flags |= MS_ACTIVE;
++#ifdef CONFIG_PRECACHE
++	s->precache_poolid = -2;
++#endif
+ 	simple_set_mnt(mnt, s);
+ 	return 0;
+ }
+--- head-2010-01-18.orig/include/linux/fs.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/include/linux/fs.h	2009-12-04 10:29:25.000000000 +0100
+@@ -1397,6 +1397,9 @@ struct super_block {
+ 	/* Granularity of c/m/atime in ns.
+ 	   Cannot be worse than a second */
+ 	u32		   s_time_gran;
++#ifdef CONFIG_PRECACHE
++	u32                precache_poolid;
++#endif
+ 
+ 	/*
+ 	 * Filesystem subtype.  If non-empty the filesystem type field
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/linux/precache.h	2009-12-04 10:29:25.000000000 +0100
+@@ -0,0 +1,55 @@
++#ifndef _LINUX_PRECACHE_H
++
++#include <linux/fs.h>
++#include <linux/mm.h>
++
++#ifdef CONFIG_PRECACHE
++extern void precache_init(struct super_block *sb);
++extern void shared_precache_init(struct super_block *sb, char *uuid);
++extern int precache_get(struct address_space *mapping, unsigned long index,
++	       struct page *empty_page);
++extern int precache_put(struct address_space *mapping, unsigned long index,
++		struct page *page);
++extern int precache_flush(struct address_space *mapping, unsigned long index);
++extern int precache_flush_inode(struct address_space *mapping);
++extern int precache_flush_filesystem(struct super_block *s);
++#else
++static inline void precache_init(struct super_block *sb)
++{
++}
++
++static inline void shared_precache_init(struct super_block *sb, char *uuid)
++{
++}
++
++static inline int precache_get(struct address_space *mapping,
++		unsigned long index, struct page *empty_page)
++{
++	return 0;
++}
++
++static inline int precache_put(struct address_space *mapping,
++		unsigned long index, struct page *page)
++{
++	return 0;
++}
++
++static inline int precache_flush(struct address_space *mapping,
++		unsigned long index)
++{
++	return 0;
++}
++
++static inline int precache_flush_inode(struct address_space *mapping)
++{
++	return 0;
++}
++
++static inline int precache_flush_filesystem(struct super_block *s)
++{
++	return 0;
++}
++#endif
++
++#define _LINUX_PRECACHE_H
++#endif /* _LINUX_PRECACHE_H */
+--- head-2010-01-18.orig/include/linux/swap.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/include/linux/swap.h	2009-12-04 10:29:25.000000000 +0100
+@@ -178,8 +178,59 @@ struct swap_info_struct {
+ 	unsigned int max;
+ 	unsigned int inuse_pages;
+ 	unsigned int old_block_size;
++#ifdef CONFIG_PRESWAP
++	unsigned long *preswap_map;
++	unsigned int preswap_pages;
++#endif
+ };
+ 
++#ifdef CONFIG_PRESWAP
++
++#include <linux/sysctl.h>
++extern int preswap_sysctl_handler(struct ctl_table *, int, void __user *,
++	size_t *, loff_t *);
++extern const unsigned long preswap_zero, preswap_infinity;
++
++extern void preswap_shrink(unsigned long);
++extern int preswap_test(struct swap_info_struct *, unsigned long);
++extern void preswap_init(unsigned);
++extern int preswap_put(struct page *);
++extern int preswap_get(struct page *);
++extern void preswap_flush(unsigned, unsigned long);
++extern void preswap_flush_area(unsigned);
++#else
++static inline void preswap_shrink(unsigned long target_pages)
++{
++}
++
++static inline int preswap_test(struct swap_info_struct *sis, unsigned long offset)
++{
++	return 0;
++}
++
++static inline void preswap_init(unsigned type)
++{
++}
++
++static inline int preswap_put(struct page *page)
++{
++	return 0;
++}
++
++static inline int preswap_get(struct page *get)
++{
++	return 0;
++}
++
++static inline void preswap_flush(unsigned type, unsigned long offset)
++{
++}
++
++static inline void preswap_flush_area(unsigned type)
++{
++}
++#endif /* CONFIG_PRESWAP */
++
+ struct swap_list_t {
+ 	int head;	/* head of priority-ordered swapfile list */
+ 	int next;	/* swapfile to be used next */
+--- head-2010-01-18.orig/kernel/sysctl.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/kernel/sysctl.c	2010-01-07 09:36:42.000000000 +0100
+@@ -1444,6 +1444,18 @@ static struct ctl_table vm_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec,
+ 	},
++#ifdef CONFIG_PRESWAP
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "preswap",
++		.data		= NULL,
++		.maxlen		= sizeof(unsigned long),
++		.mode		= 0644,
++		.proc_handler	= &preswap_sysctl_handler,
++		.extra1		= (void *)&preswap_zero,
++		.extra2		= (void *)&preswap_infinity,
++	},
++#endif
+ #ifdef CONFIG_MEMORY_FAILURE
+ 	{
+ 		.ctl_name	= CTL_UNNUMBERED,
+--- head-2010-01-18.orig/mm/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/Kconfig	2010-01-07 09:36:51.000000000 +0100
+@@ -288,3 +288,31 @@ config NOMMU_INITIAL_TRIM_EXCESS
+ 	  of 1 says that all excess pages should be trimmed.
+ 
+ 	  See Documentation/nommu-mmap.txt for more information.
++
++#
++# support for transcendent memory
++#
++config TMEM
++	bool
++	help
++	  In a virtualized environment, allows unused and underutilized
++	  system physical memory to be made accessible through a narrow
++	  well-defined page-copy-based API.  If unsure, say Y.
++
++config PRECACHE
++	bool "Cache clean pages in transcendent memory"
++	depends on XEN
++	select TMEM
++	help
++	  Allows the transcendent memory pool to be used to store clean
++	  page-cache pages which, under some circumstances, will greatly
++	  reduce paging and thus improve performance.  If unsure, say Y.
++
++config PRESWAP
++	bool "Swap pages to transcendent memory"
++	depends on XEN
++	select TMEM
++	help
++	  Allows the transcendent memory pool to be used as a pseudo-swap
++	  device which, under some circumstances, will greatly reduce
++	  swapping and thus improve performance.  If unsure, say Y.
+--- head-2010-01-18.orig/mm/Makefile	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/Makefile	2009-12-04 10:29:25.000000000 +0100
+@@ -17,6 +17,9 @@ obj-y += init-mm.o
+ 
+ obj-$(CONFIG_BOUNCE)	+= bounce.o
+ obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
++obj-$(CONFIG_TMEM)	+= tmem.o
++obj-$(CONFIG_PRESWAP)	+= preswap.o
++obj-$(CONFIG_PRECACHE)	+= precache.o
+ obj-$(CONFIG_HAS_DMA)	+= dmapool.o
+ obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
+ obj-$(CONFIG_NUMA) 	+= mempolicy.o
+--- head-2010-01-18.orig/mm/filemap.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/filemap.c	2009-12-04 10:29:25.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include <linux/cpuset.h>
+ #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
+ #include <linux/memcontrol.h>
++#include <linux/precache.h>
+ #include <linux/mm_inline.h> /* for page_is_file_cache() */
+ #include <trace/filemap.h>
+ #include "internal.h"
+@@ -123,6 +124,16 @@ void __remove_from_page_cache(struct pag
+ {
+ 	struct address_space *mapping = page->mapping;
+ 
++	/*
++	 * if we're uptodate, flush out into the precache, otherwise
++	 * invalidate any existing precache entries.  We can't leave
++	 * stale data around in the precache once our page is gone
++	 */
++	if (PageUptodate(page))
++		precache_put(page->mapping, page->index, page);
++	else
++		precache_flush(page->mapping, page->index);
++
+ 	radix_tree_delete(&mapping->page_tree, page->index);
+ 	page->mapping = NULL;
+ 	mapping->nrpages--;
+--- head-2010-01-18.orig/mm/page_io.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/page_io.c	2009-12-07 12:08:42.000000000 +0100
+@@ -126,10 +126,23 @@ int swap_writepage(struct page *page, st
+ 		ret = -ENOMEM;
+ 		goto out;
+ 	}
++
++#ifdef CONFIG_PRECACHE
++	set_page_writeback(page);
++	if (preswap_put(page) == 1) {
++		unlock_page(page);
++		end_page_writeback(page);
++		bio_put(bio);
++		goto out;
++	}
++#endif
++
+ 	if (wbc->sync_mode == WB_SYNC_ALL)
+ 		rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
+ 	count_vm_event(PSWPOUT);
++#ifndef CONFIG_PRECACHE
+ 	set_page_writeback(page);
++#endif
+ 	trace_swap_out(page);
+ 	unlock_page(page);
+ 	submit_bio(rw, bio);
+@@ -188,6 +201,12 @@ int swap_readpage(struct page *page)
+ 		return ret;
+ 	}
+ 
++	if (preswap_get(page) == 1) {
++		SetPageUptodate(page);
++		unlock_page(page);
++		goto out;
++	}
++
+ 	bio = get_swap_bio(GFP_KERNEL, page_private(page), page,
+ 				end_swap_bio_read);
+ 	if (bio == NULL) {
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/mm/precache.c	2009-12-04 10:29:25.000000000 +0100
+@@ -0,0 +1,140 @@
++/*
++ * linux/mm/precache.c
++ *
++ * Implements "precache" for filesystems/pagecache on top of transcendent
++ * memory ("tmem") API.  A filesystem creates an "ephemeral tmem pool"
++ * and retains the returned pool_id in its superblock.  Clean pages evicted
++ * from pagecache may be "put" into the pool and associated with a "handle"
++ * consisting of the pool_id, an object (inode) id, and an index (page offset).
++ * Note that the page is copied to tmem; no kernel mappings are changed.
++ * If the page is later needed, the filesystem (or VFS) issues a "get", passing
++ * the same handle and an empty pageframe.  If successful, the page is copied
++ * into the pageframe and a disk read is avoided.  But since the tmem pool
++ * is of indeterminate size, a "put" page has indeterminate longevity
++ * ("ephemeral"), and the "get" may fail, in which case the filesystem must
++ * read the page from disk as before.  Note that the filesystem/pagecache are
++ * responsible for maintaining coherency between the pagecache, precache,
++ * and the disk, for which "flush page" and "flush object" actions are
++ * provided.  And when a filesystem is unmounted, it must "destroy" the pool.
++ *
++ * Two types of pools may be created for a precache: "private" or "shared".
++ * For a private pool, a successful "get" always flushes, implementing
++ * exclusive semantics; for a "shared" pool (which is intended for use by
++ * co-resident nodes of a cluster filesystem), the "flush" is not guaranteed.
++ * In either case, a failed "duplicate" put (overwrite) always guarantee
++ * the old data is flushed.
++ *
++ * Note also that multiple accesses to a tmem pool may be concurrent and any
++ * ordering must be guaranteed by the caller.
++ *
++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
++ */
++
++#include <linux/precache.h>
++#include <linux/module.h>
++#include "tmem.h"
++
++static int precache_auto_allocate; /* set to 1 to auto_allocate */
++
++int precache_put(struct address_space *mapping, unsigned long index,
++ struct page *page)
++{
++	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
++	u64 obj = (unsigned long) mapping->host->i_ino;
++	u32 ind = (u32) index;
++	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
++	int ret;
++
++	if ((s32)tmem_pool < 0) {
++		if (!precache_auto_allocate)
++			return 0;
++		/* a put on a non-existent precache may auto-allocate one */
++		ret = tmem_new_pool(0, 0, 0);
++		if (ret < 0)
++			return 0;
++		printk(KERN_INFO
++			"Mapping superblock for s_id=%s to precache_id=%d\n",
++			mapping->host->i_sb->s_id, tmem_pool);
++		mapping->host->i_sb->precache_poolid = tmem_pool;
++	}
++	if (ind != index)
++		return 0;
++	mb(); /* ensure page is quiescent; tmem may address it with an alias */
++	return tmem_put_page(tmem_pool, obj, ind, mfn);
++}
++
++int precache_get(struct address_space *mapping, unsigned long index,
++ struct page *empty_page)
++{
++	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
++	u64 obj = (unsigned long) mapping->host->i_ino;
++	u32 ind = (u32) index;
++	unsigned long mfn = pfn_to_mfn(page_to_pfn(empty_page));
++
++	if ((s32)tmem_pool < 0)
++		return 0;
++	if (ind != index)
++		return 0;
++
++	return tmem_get_page(tmem_pool, obj, ind, mfn);
++}
++EXPORT_SYMBOL(precache_get);
++
++int precache_flush(struct address_space *mapping, unsigned long index)
++{
++	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
++	u64 obj = (unsigned long) mapping->host->i_ino;
++	u32 ind = (u32) index;
++
++	if ((s32)tmem_pool < 0)
++		return 0;
++	if (ind != index)
++		return 0;
++
++	return tmem_flush_page(tmem_pool, obj, ind);
++}
++EXPORT_SYMBOL(precache_flush);
++
++int precache_flush_inode(struct address_space *mapping)
++{
++	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
++	u64 obj = (unsigned long) mapping->host->i_ino;
++
++	if ((s32)tmem_pool < 0)
++		return 0;
++
++	return tmem_flush_object(tmem_pool, obj);
++}
++EXPORT_SYMBOL(precache_flush_inode);
++
++int precache_flush_filesystem(struct super_block *sb)
++{
++	u32 tmem_pool = sb->precache_poolid;
++	int ret;
++
++	if ((s32)tmem_pool < 0)
++		return 0;
++	ret = tmem_destroy_pool(tmem_pool);
++	if (!ret)
++		return 0;
++	printk(KERN_INFO
++		"Unmapping superblock for s_id=%s from precache_id=%d\n",
++		sb->s_id, ret);
++	sb->precache_poolid = 0;
++	return 1;
++}
++EXPORT_SYMBOL(precache_flush_filesystem);
++
++void precache_init(struct super_block *sb)
++{
++	sb->precache_poolid = tmem_new_pool(0, 0, 0);
++}
++EXPORT_SYMBOL(precache_init);
++
++void shared_precache_init(struct super_block *sb, char *uuid)
++{
++	u64 uuid_lo = *(u64 *)uuid;
++	u64 uuid_hi = *(u64 *)(&uuid[8]);
++	sb->precache_poolid = tmem_new_pool(uuid_lo, uuid_hi, TMEM_POOL_SHARED);
++}
++EXPORT_SYMBOL(shared_precache_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/mm/preswap.c	2009-12-04 10:29:25.000000000 +0100
+@@ -0,0 +1,184 @@
++/*
++ * linux/mm/preswap.c
++ *
++ * Implements a fast "preswap" on top of the transcendent memory ("tmem") API.
++ * When a swapdisk is enabled (with swapon), a "private persistent tmem pool"
++ * is created along with a bit-per-page preswap_map.  When swapping occurs
++ * and a page is about to be written to disk, a "put" into the pool may first
++ * be attempted by passing the pageframe to be swapped, along with a "handle"
++ * consisting of a pool_id, an object id, and an index.  Since the pool is of
++ * indeterminate size, the "put" may be rejected, in which case the page
++ * is swapped to disk as normal.  If the "put" is successful, the page is
++ * copied to tmem and the preswap_map records the success.  Later, when
++ * the page needs to be swapped in, the preswap_map is checked and, if set,
++ * the page may be obtained with a "get" operation.  Note that the swap
++ * subsystem is responsible for: maintaining coherency between the swapcache,
++ * preswap, and the swapdisk; for evicting stale pages from preswap; and for
++ * emptying preswap when swapoff is performed. The "flush page" and "flush
++ * object" actions are provided for this.
++ *
++ * Note that if a "duplicate put" is performed to overwrite a page and
++ * the "put" operation fails, the page (and old data) is flushed and lost.
++ * Also note that multiple accesses to a tmem pool may be concurrent and
++ * any ordering must be guaranteed by the caller.
++ *
++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
++ */
++
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/sysctl.h>
++#include <linux/swap.h>
++#include <linux/swapops.h>
++#include <linux/proc_fs.h>
++#include <linux/security.h>
++#include <linux/capability.h>
++#include <linux/uaccess.h>
++#include "tmem.h"
++
++static u32 preswap_poolid = -1; /* if negative, preswap will never call tmem */
++
++const unsigned long preswap_zero = 0, preswap_infinity = ~0UL; /* for sysctl */
++
++/*
++ * Swizzling increases objects per swaptype, increasing tmem concurrency
++ * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
++ */
++#define SWIZ_BITS		4
++#define SWIZ_MASK		((1 << SWIZ_BITS) - 1)
++#define oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
++#define iswiz(_ind)		(_ind >> SWIZ_BITS)
++
++/*
++ * preswap_map test/set/clear operations (must be atomic)
++ */
++
++int preswap_test(struct swap_info_struct *sis, unsigned long offset)
++{
++	if (!sis->preswap_map)
++		return 0;
++	return test_bit(offset % BITS_PER_LONG,
++		&sis->preswap_map[offset/BITS_PER_LONG]);
++}
++
++static inline void preswap_set(struct swap_info_struct *sis,
++				unsigned long offset)
++{
++	if (!sis->preswap_map)
++		return;
++	set_bit(offset % BITS_PER_LONG,
++		&sis->preswap_map[offset/BITS_PER_LONG]);
++}
++
++static inline void preswap_clear(struct swap_info_struct *sis,
++				unsigned long offset)
++{
++	if (!sis->preswap_map)
++		return;
++	clear_bit(offset % BITS_PER_LONG,
++		&sis->preswap_map[offset/BITS_PER_LONG]);
++}
++
++/*
++ * preswap tmem operations
++ */
++
++/* returns 1 if the page was successfully put into preswap, 0 if the page
++ * was declined, and -ERRNO for a specific error */
++int preswap_put(struct page *page)
++{
++	swp_entry_t entry = { .val = page_private(page), };
++	unsigned type = swp_type(entry);
++	pgoff_t offset = swp_offset(entry);
++	u64 ind64 = (u64)offset;
++	u32 ind = (u32)offset;
++	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
++	struct swap_info_struct *sis = get_swap_info_struct(type);
++	int dup = 0, ret;
++
++	if ((s32)preswap_poolid < 0)
++		return 0;
++	if (ind64 != ind)
++		return 0;
++	if (preswap_test(sis, offset))
++		dup = 1;
++	mb(); /* ensure page is quiescent; tmem may address it with an alias */
++	ret = tmem_put_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn);
++	if (ret == 1) {
++		preswap_set(sis, offset);
++		if (!dup)
++			sis->preswap_pages++;
++	} else if (dup) {
++		/* failed dup put always results in an automatic flush of
++		 * the (older) page from preswap */
++		preswap_clear(sis, offset);
++		sis->preswap_pages--;
++	}
++	return ret;
++}
++
++/* returns 1 if the page was successfully gotten from preswap, 0 if the page
++ * was not present (should never happen!), and -ERRNO for a specific error */
++int preswap_get(struct page *page)
++{
++	swp_entry_t entry = { .val = page_private(page), };
++	unsigned type = swp_type(entry);
++	pgoff_t offset = swp_offset(entry);
++	u64 ind64 = (u64)offset;
++	u32 ind = (u32)offset;
++	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
++	struct swap_info_struct *sis = get_swap_info_struct(type);
++	int ret;
++
++	if ((s32)preswap_poolid < 0)
++		return 0;
++	if (ind64 != ind)
++		return 0;
++	if (!preswap_test(sis, offset))
++		return 0;
++	ret = tmem_get_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn);
++	return ret;
++}
++
++/* flush a single page from preswap */
++void preswap_flush(unsigned type, unsigned long offset)
++{
++	u64 ind64 = (u64)offset;
++	u32 ind = (u32)offset;
++	struct swap_info_struct *sis = get_swap_info_struct(type);
++	int ret = 1;
++
++	if ((s32)preswap_poolid < 0)
++		return;
++	if (ind64 != ind)
++		return;
++	if (preswap_test(sis, offset)) {
++		ret = tmem_flush_page(preswap_poolid,
++					oswiz(type, ind), iswiz(ind));
++		sis->preswap_pages--;
++		preswap_clear(sis, offset);
++	}
++}
++
++/* flush all pages from the passed swaptype */
++void preswap_flush_area(unsigned type)
++{
++	struct swap_info_struct *sis = get_swap_info_struct(type);
++	int ind;
++
++	if ((s32)preswap_poolid < 0)
++		return;
++	for (ind = SWIZ_MASK; ind >= 0; ind--)
++		(void)tmem_flush_object(preswap_poolid, oswiz(type, ind));
++	sis->preswap_pages = 0;
++}
++
++void preswap_init(unsigned type)
++{
++	/* only need one tmem pool for all swap types */
++	if ((s32)preswap_poolid >= 0)
++		return;
++	preswap_poolid = tmem_new_pool(0, 0, TMEM_POOL_PERSIST);
++	if (preswap_poolid < 0)
++		return;
++}
+--- head-2010-01-18.orig/mm/swapfile.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/swapfile.c	2009-12-04 10:29:25.000000000 +0100
+@@ -593,6 +593,7 @@ static int swap_entry_free(struct swap_i
+ 			swap_list.next = p - swap_info;
+ 		nr_swap_pages++;
+ 		p->inuse_pages--;
++		preswap_flush(p - swap_info, offset);
+ 	}
+ 	if (!swap_count(count))
+ 		mem_cgroup_uncharge_swap(ent);
+@@ -992,7 +993,7 @@ static int unuse_mm(struct mm_struct *mm
+  * Recycle to start on reaching the end, returning 0 when empty.
+  */
+ static unsigned int find_next_to_unuse(struct swap_info_struct *si,
+-					unsigned int prev)
++				unsigned int prev, unsigned int preswap)
+ {
+ 	unsigned int max = si->max;
+ 	unsigned int i = prev;
+@@ -1018,6 +1019,12 @@ static unsigned int find_next_to_unuse(s
+ 			prev = 0;
+ 			i = 1;
+ 		}
++		if (preswap) {
++			if (preswap_test(si, i))
++				break;
++			else
++				continue;
++		}
+ 		count = si->swap_map[i];
+ 		if (count && swap_count(count) != SWAP_MAP_BAD)
+ 			break;
+@@ -1029,8 +1036,12 @@ static unsigned int find_next_to_unuse(s
+  * We completely avoid races by reading each swap page in advance,
+  * and then search for the process using it.  All the necessary
+  * page table adjustments can then be made atomically.
++ *
++ * if the boolean preswap is true, only unuse pages_to_unuse pages;
++ * pages_to_unuse==0 means all pages
+  */
+-static int try_to_unuse(unsigned int type)
++static int try_to_unuse(unsigned int type, unsigned int preswap,
++		unsigned long pages_to_unuse)
+ {
+ 	struct swap_info_struct * si = &swap_info[type];
+ 	struct mm_struct *start_mm;
+@@ -1066,7 +1077,7 @@ static int try_to_unuse(unsigned int typ
+ 	 * one pass through swap_map is enough, but not necessarily:
+ 	 * there are races when an instance of an entry might be missed.
+ 	 */
+-	while ((i = find_next_to_unuse(si, i)) != 0) {
++	while ((i = find_next_to_unuse(si, i, preswap)) != 0) {
+ 		if (signal_pending(current)) {
+ 			retval = -EINTR;
+ 			break;
+@@ -1259,6 +1270,8 @@ retry:
+ 		 * interactive performance.
+ 		 */
+ 		cond_resched();
++		if (preswap && pages_to_unuse && !--pages_to_unuse)
++			break;
+ 	}
+ 
+ 	mmput(start_mm);
+@@ -1602,7 +1615,7 @@ SYSCALL_DEFINE1(swapoff, const char __us
+ 	spin_unlock(&swap_lock);
+ 
+ 	current->flags |= PF_OOM_ORIGIN;
+-	err = try_to_unuse(type);
++	err = try_to_unuse(type, 0, 0);
+ 	current->flags &= ~PF_OOM_ORIGIN;
+ 
+ 	if (err) {
+@@ -1652,9 +1665,14 @@ SYSCALL_DEFINE1(swapoff, const char __us
+ 	p->swap_map = NULL;
+ 	p->flags = 0;
+ 	trace_swap_file_close(swap_file);
++	preswap_flush_area(p - swap_info);
+ 	spin_unlock(&swap_lock);
+ 	mutex_unlock(&swapon_mutex);
+ 	vfree(swap_map);
++#ifdef CONFIG_PRESWAP
++	if (p->preswap_map)
++		vfree(p->preswap_map);
++#endif
+ 	/* Destroy swap account informatin */
+ 	swap_cgroup_swapoff(type);
+ 
+@@ -1808,6 +1826,7 @@ SYSCALL_DEFINE2(swapon, const char __use
+ 	unsigned long maxpages = 1;
+ 	unsigned long swapfilepages;
+ 	unsigned short *swap_map = NULL;
++	unsigned long *preswap_map = NULL;
+ 	struct page *page = NULL;
+ 	struct inode *inode = NULL;
+ 	int did_down = 0;
+@@ -1976,6 +1995,12 @@ SYSCALL_DEFINE2(swapon, const char __use
+ 		swap_map[page_nr] = SWAP_MAP_BAD;
+ 	}
+ 
++#ifdef CONFIG_PRESWAP
++	preswap_map = vmalloc(maxpages / sizeof(long));
++	if (preswap_map)
++		memset(preswap_map, 0, maxpages / sizeof(long));
++#endif
++
+ 	error = swap_cgroup_swapon(type, maxpages);
+ 	if (error)
+ 		goto bad_swap;
+@@ -2018,6 +2043,9 @@ SYSCALL_DEFINE2(swapon, const char __use
+ 	else
+ 		p->prio = --least_priority;
+ 	p->swap_map = swap_map;
++#ifdef CONFIG_PRESWAP
++	p->preswap_map = preswap_map;
++#endif
+ 	p->flags |= SWP_WRITEOK;
+ 	nr_swap_pages += nr_good_pages;
+ 	total_swap_pages += nr_good_pages;
+@@ -2044,6 +2072,7 @@ SYSCALL_DEFINE2(swapon, const char __use
+ 		swap_info[prev].next = p - swap_info;
+ 	}
+ 	trace_swap_file_open(swap_file, name);
++	preswap_init(p - swap_info);
+ 	spin_unlock(&swap_lock);
+ 	mutex_unlock(&swapon_mutex);
+ 	error = 0;
+@@ -2060,6 +2089,7 @@ bad_swap_2:
+ 	p->swap_file = NULL;
+ 	p->flags = 0;
+ 	spin_unlock(&swap_lock);
++	vfree(preswap_map);
+ 	vfree(swap_map);
+ 	if (swap_file)
+ 		filp_close(swap_file, NULL);
+@@ -2268,6 +2298,10 @@ int valid_swaphandles(swp_entry_t entry,
+ 		base++;
+ 
+ 	spin_lock(&swap_lock);
++	if (preswap_test(si, target)) {
++		spin_unlock(&swap_lock);
++		return 0;
++	}
+ 	if (end > si->max)	/* don't go beyond end of map */
+ 		end = si->max;
+ 
+@@ -2278,6 +2312,9 @@ int valid_swaphandles(swp_entry_t entry,
+ 			break;
+ 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
+ 			break;
++		/* Don't read in preswap pages */
++		if (preswap_test(si, toff))
++			break;
+ 	}
+ 	/* Count contiguous allocated slots below our target */
+ 	for (toff = target; --toff >= base; nr_pages++) {
+@@ -2286,6 +2323,9 @@ int valid_swaphandles(swp_entry_t entry,
+ 			break;
+ 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
+ 			break;
++		/* Don't read in preswap pages */
++		if (preswap_test(si, toff))
++			break;
+ 	}
+ 	spin_unlock(&swap_lock);
+ 
+@@ -2296,3 +2336,92 @@ int valid_swaphandles(swp_entry_t entry,
+ 	*offset = ++toff;
+ 	return nr_pages? ++nr_pages: 0;
+ }
++
++#ifdef CONFIG_PRESWAP
++/*
++ * preswap infrastructure functions
++ */
++
++/* code structure leveraged from sys_swapoff */
++void preswap_shrink(unsigned long target_pages)
++{
++	struct swap_info_struct *si = NULL;
++	unsigned long total_pages = 0, total_pages_to_unuse;
++	unsigned long pages = 0, unuse_pages = 0;
++	int type;
++	int wrapped = 0;
++
++	do {
++		/*
++		 * we don't want to hold swap_lock while doing a very
++		 * lengthy try_to_unuse, but swap_list may change
++		 * so restart scan from swap_list.head each time
++		 */
++		spin_lock(&swap_lock);
++		total_pages = 0;
++		for (type = swap_list.head; type >= 0; type = si->next) {
++			si = get_swap_info_struct(type);
++			total_pages += si->preswap_pages;
++		}
++		if (total_pages <= target_pages) {
++			spin_unlock(&swap_lock);
++			return;
++		}
++		total_pages_to_unuse = total_pages - target_pages;
++		for (type = swap_list.head; type >= 0; type = si->next) {
++			si = get_swap_info_struct(type);
++			if (total_pages_to_unuse < si->preswap_pages)
++				pages = unuse_pages = total_pages_to_unuse;
++			else {
++				pages = si->preswap_pages;
++				unuse_pages = 0; /* unuse all */
++			}
++			if (security_vm_enough_memory(pages))
++				continue;
++			vm_unacct_memory(pages);
++			break;
++		}
++		spin_unlock(&swap_lock);
++		if (type < 0)
++			return;
++		current->flags |= PF_OOM_ORIGIN;
++		(void)try_to_unuse(type, 1, unuse_pages);
++		current->flags &= ~PF_OOM_ORIGIN;
++		wrapped++;
++	} while (wrapped <= 3);
++}
++
++
++#ifdef CONFIG_SYSCTL
++/* cat /sys/proc/vm/preswap provides total number of pages in preswap
++ * across all swaptypes.  echo N > /sys/proc/vm/preswap attempts to shrink
++ * preswap page usage to N (usually 0) */
++int preswap_sysctl_handler(ctl_table *table, int write,
++	void __user *buffer, size_t *length, loff_t *ppos)
++{
++	unsigned long npages;
++	int type;
++	unsigned long totalpages = 0;
++	struct swap_info_struct *si = NULL;
++
++	/* modeled after hugetlb_sysctl_handler in mm/hugetlb.c */
++	if (!write) {
++		spin_lock(&swap_lock);
++		for (type = swap_list.head; type >= 0; type = si->next) {
++			si = get_swap_info_struct(type);
++			totalpages += si->preswap_pages;
++		}
++		spin_unlock(&swap_lock);
++		npages = totalpages;
++	}
++	table->data = &npages;
++	table->maxlen = sizeof(unsigned long);
++	proc_doulongvec_minmax(table, write, buffer, length, ppos);
++
++	if (write)
++		preswap_shrink(npages);
++
++	return 0;
++}
++#endif
++#endif /* CONFIG_PRESWAP */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/mm/tmem.h	2009-12-04 10:29:25.000000000 +0100
+@@ -0,0 +1,84 @@
++/*
++ * linux/mm/tmem.h
++ *
++ * Interface to transcendent memory, used by mm/precache.c and mm/preswap.c
++ * Currently implemented on XEN, but may be implemented elsewhere in future.
++ *
++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
++ */
++
++#ifdef CONFIG_XEN
++#include <xen/interface/xen.h>
++
++/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
++#define TMEM_POOL_MIN_PAGESHIFT   12
++#define TMEM_POOL_PAGEORDER       (PAGE_SHIFT - TMEM_POOL_MIN_PAGESHIFT)
++
++extern int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
++	unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len);
++extern int xen_tmem_new_pool(u32 tmem_cmd, u64 uuid_lo, u64 uuid_hi, u32 flags);
++
++static inline int tmem_put_page(u32 pool_id, u64 object, u32 index,
++	unsigned long gmfn)
++{
++	return xen_tmem_op(TMEM_PUT_PAGE, pool_id, object, index,
++		gmfn, 0, 0, 0);
++}
++
++static inline int tmem_get_page(u32 pool_id, u64 object, u32 index,
++	unsigned long gmfn)
++{
++	return xen_tmem_op(TMEM_GET_PAGE, pool_id, object, index,
++		gmfn, 0, 0, 0);
++}
++
++static inline int tmem_flush_page(u32 pool_id, u64 object, u32 index)
++{
++	return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, object, index,
++		0, 0, 0, 0);
++}
++
++static inline int tmem_flush_object(u32 pool_id, u64 object)
++{
++	return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, object, 0, 0, 0, 0, 0);
++}
++
++static inline int tmem_new_pool(u64 uuid_lo, u64 uuid_hi, u32 flags)
++{
++	BUILD_BUG_ON((TMEM_POOL_PAGEORDER < 0) ||
++		(TMEM_POOL_PAGEORDER >= TMEM_POOL_PAGESIZE_MASK));
++	flags |= TMEM_POOL_PAGEORDER << TMEM_POOL_PAGESIZE_SHIFT;
++	return xen_tmem_new_pool(TMEM_NEW_POOL, uuid_lo, uuid_hi, flags);
++}
++
++static inline int tmem_destroy_pool(u32 pool_id)
++{
++	return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, 0, 0, 0, 0, 0, 0);
++}
++#else
++struct tmem_op {
++	u32 cmd;
++	s32 pool_id; /* private > 0; shared < 0; 0 is invalid */
++	union {
++		struct {  /* for cmd == TMEM_NEW_POOL */
++			u64 uuid[2];
++			u32 flags;
++		} new;
++		struct {  /* for cmd == TMEM_CONTROL */
++			u32 subop;
++			u32 cli_id;
++			u32 arg1;
++			u32 arg2;
++			void *buf;
++		} ctrl;
++		struct {
++			u64 object;
++			u32 index;
++			u32 tmem_offset;
++			u32 pfn_offset;
++			u32 len;
++			unsigned long pfn;  /* page frame */
++		} gen;
++	} u;
++};
++#endif
+--- head-2010-01-18.orig/mm/truncate.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/truncate.c	2009-12-04 10:29:25.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/pagemap.h>
+ #include <linux/highmem.h>
+ #include <linux/pagevec.h>
++#include <linux/precache.h>
+ #include <linux/task_io_accounting_ops.h>
+ #include <linux/buffer_head.h>	/* grr. try_to_release_page,
+ 				   do_invalidatepage */
+@@ -50,6 +51,7 @@ void do_invalidatepage(struct page *page
+ static inline void truncate_partial_page(struct page *page, unsigned partial)
+ {
+ 	zero_user_segment(page, partial, PAGE_CACHE_SIZE);
++	precache_flush(page->mapping, page->index);
+ 	if (page_has_private(page))
+ 		do_invalidatepage(page, partial);
+ }
+@@ -107,6 +109,10 @@ truncate_complete_page(struct address_sp
+ 	clear_page_mlock(page);
+ 	remove_from_page_cache(page);
+ 	ClearPageMappedToDisk(page);
++	/* this must be after the remove_from_page_cache which
++	 * calls precache_put
++	 */
++	precache_flush(mapping, page->index);
+ 	page_cache_release(page);	/* pagecache ref */
+ 	return 0;
+ }
+@@ -214,6 +220,7 @@ void truncate_inode_pages_range(struct a
+ 	pgoff_t next;
+ 	int i;
+ 
++	precache_flush_inode(mapping);
+ 	if (mapping->nrpages == 0)
+ 		return;
+ 
+@@ -287,6 +294,7 @@ void truncate_inode_pages_range(struct a
+ 		}
+ 		pagevec_release(&pvec);
+ 	}
++	precache_flush_inode(mapping);
+ }
+ EXPORT_SYMBOL(truncate_inode_pages_range);
+ 
+@@ -423,6 +431,7 @@ int invalidate_inode_pages2_range(struct
+ 	int did_range_unmap = 0;
+ 	int wrapped = 0;
+ 
++	precache_flush_inode(mapping);
+ 	pagevec_init(&pvec, 0);
+ 	next = start;
+ 	while (next <= end && !wrapped &&
+@@ -479,6 +488,7 @@ int invalidate_inode_pages2_range(struct
+ 		pagevec_release(&pvec);
+ 		cond_resched();
+ 	}
++	precache_flush_inode(mapping);
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-seccomp-disable-tsc-option
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-seccomp-disable-tsc-option
@@ -0,0 +1,33 @@
+From: Andrea Arcangeli <andrea@cpushare.com>
+Subject: [PATCH seccomp: make tsc disabling optional
+Patch-mainline: unknown
+References: 191123
+
+Make the TSC disable purely paranoid feature optional, so by default seccomp
+returns absolutely zerocost.
+
+Ported from 2.6.19 to 2.6.24-rc7 by Jeff Mahoney.
+Addition of x86-64 by Jan Beulich.
+
+Signed-off-by: Andrea Arcangeli <andrea@cpushare.com>
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.fixes/seccomp-disable-tsc-option" by xen-port-patches.py
+
+--- head-2009-10-12.orig/arch/x86/kernel/process-xen.c	2009-10-13 11:49:03.000000000 +0200
++++ head-2009-10-12/arch/x86/kernel/process-xen.c	2009-10-13 17:01:41.000000000 +0200
+@@ -129,6 +129,7 @@ static void hard_disable_TSC(void)
+ 
+ void disable_TSC(void)
+ {
++#ifdef CONFIG_SECCOMP_DISABLE_TSC
+ 	preempt_disable();
+ 	if (!test_and_set_thread_flag(TIF_NOTSC))
+ 		/*
+@@ -137,6 +138,7 @@ void disable_TSC(void)
+ 		 */
+ 		hard_disable_TSC();
+ 	preempt_enable();
++#endif
+ }
+ 
+ static void hard_enable_TSC(void)
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-stack-unwind
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-stack-unwind
@@ -0,0 +1,99 @@
+Subject: DWARF2 EH-frame based stack unwinding
+From: jbeulich@novell.com
+Patch-mainline: no
+
+This includes reverting f1883f86dea84fe47a71a39fc1afccc005915ed8.
+
+Update Jan 17 2009 jeffm:
+- Something in 2.6.29-rc1 tweaked the frame pointer code somehow, so I fixed
+  that up.
+
+Automatically created from "patches.suse/stack-unwind" by xen-port-patches.py
+
+--- head-2009-10-12.orig/arch/x86/kernel/entry_32-xen.S	2009-10-12 16:39:40.000000000 +0200
++++ head-2009-10-12/arch/x86/kernel/entry_32-xen.S	2009-10-13 17:01:47.000000000 +0200
+@@ -1206,6 +1206,41 @@ ENTRY(fixup_4gb_segment)
+ 	CFI_ENDPROC
+ END(spurious_interrupt_bug)
+ 
++#ifdef CONFIG_STACK_UNWIND
++ENTRY(arch_unwind_init_running)
++	CFI_STARTPROC
++	movl	4(%esp), %edx
++	movl	(%esp), %ecx
++	leal	4(%esp), %eax
++	movl	%ebx, PT_EBX(%edx)
++	xorl	%ebx, %ebx
++	movl	%ebx, PT_ECX(%edx)
++	movl	%ebx, PT_EDX(%edx)
++	movl	%esi, PT_ESI(%edx)
++	movl	%edi, PT_EDI(%edx)
++	movl	%ebp, PT_EBP(%edx)
++	movl	%ebx, PT_EAX(%edx)
++	movl	$__USER_DS, PT_DS(%edx)
++	movl	$__USER_DS, PT_ES(%edx)
++	movl	$__KERNEL_PERCPU, PT_FS(%edx)
++	movl	$__KERNEL_STACK_CANARY, PT_GS(%edx)
++	movl	%eax, PT_OLDESP(%edx)
++	movl	16(%esp), %eax
++	movl	%ebx, PT_ORIG_EAX(%edx)
++	movl	%ecx, PT_EIP(%edx)
++	movl	12(%esp), %ecx
++	movl	$__KERNEL_CS, PT_CS(%edx)
++	movl	%eax, 12(%esp)
++	movl	8(%esp), %eax
++	movl	%ecx, 8(%esp)
++	movl	%ebx, PT_EFLAGS(%edx)
++	movl	PT_EBX(%edx), %ebx
++	movl	$__KERNEL_DS, PT_OLDSS(%edx)
++	jmpl	*%eax
++	CFI_ENDPROC
++ENDPROC(arch_unwind_init_running)
++#endif
++
+ ENTRY(kernel_thread_helper)
+ 	pushl $0		# fake return address for unwinder
+ 	CFI_STARTPROC
+--- head-2009-10-12.orig/arch/x86/kernel/entry_64-xen.S	2009-10-14 18:34:53.000000000 +0200
++++ head-2009-10-12/arch/x86/kernel/entry_64-xen.S	2009-10-14 18:35:25.000000000 +0200
+@@ -1210,6 +1210,40 @@ ENTRY(call_softirq)
+ 	CFI_ENDPROC
+ END(call_softirq)
+ 
++#ifdef CONFIG_STACK_UNWIND
++ENTRY(arch_unwind_init_running)
++	CFI_STARTPROC
++	movq	%r15, R15(%rdi)
++	movq	%r14, R14(%rdi)
++	xchgq	%rsi, %rdx
++	movq	%r13, R13(%rdi)
++	movq	%r12, R12(%rdi)
++	xorl	%eax, %eax
++	movq	%rbp, RBP(%rdi)
++	movq	%rbx, RBX(%rdi)
++	movq	(%rsp), %r9
++	xchgq	%rdx, %rcx
++	movq	%rax, R11(%rdi)
++	movq	%rax, R10(%rdi)
++	movq	%rax, R9(%rdi)
++	movq	%rax, R8(%rdi)
++	movq	%rax, RAX(%rdi)
++	movq	%rax, RCX(%rdi)
++	movq	%rax, RDX(%rdi)
++	movq	%rax, RSI(%rdi)
++	movq	%rax, RDI(%rdi)
++	movq	%rax, ORIG_RAX(%rdi)
++	movq	%r9, RIP(%rdi)
++	leaq	8(%rsp), %r9
++	movq	$__KERNEL_CS, CS(%rdi)
++	movq	%rax, EFLAGS(%rdi)
++	movq	%r9, RSP(%rdi)
++	movq	$__KERNEL_DS, SS(%rdi)
++	jmpq	*%rcx
++	CFI_ENDPROC
++END(arch_unwind_init_running)
++#endif
++
+ /*
+  * Some functions should be protected against kprobes
+  */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.26
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.26
@@ -0,0 +1,20836 @@
+From: kernel.org
+Subject: 2.6.26
+Patch-mainline: 2.6.26
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.26" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:01:53.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:02:02.000000000 +0100
+@@ -40,7 +40,7 @@ config X86
+ 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
+ 	select HAVE_SYSCALL_TRACEPOINTS
+ 	select HAVE_KVM if !XEN
+-	select HAVE_ARCH_KGDB
++	select HAVE_ARCH_KGDB if !XEN
+ 	select HAVE_ARCH_TRACEHOOK
+ 	select HAVE_GENERIC_DMA_COHERENT if X86_32
+ 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+@@ -651,6 +651,7 @@ config PARAVIRT_DEBUG
+ 
+ config MEMTEST
+ 	bool "Memtest"
++	depends on !XEN
+ 	---help---
+ 	  This option adds a kernel parameter 'memtest', which allows memtest
+ 	  to be set.
+@@ -1213,7 +1214,7 @@ config ARCH_PHYS_ADDR_T_64BIT
+ config DIRECT_GBPAGES
+ 	bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
+ 	default y
+-	depends on X86_64
++	depends on X86_64 && !XEN
+ 	---help---
+ 	  Allow the kernel linear mapping to use 1GB pages on CPUs that
+ 	  support it. This can improve the kernel's performance a tiny bit by
+@@ -2238,6 +2239,4 @@ source "crypto/Kconfig"
+ 
+ source "arch/x86/kvm/Kconfig"
+ 
+-source "drivers/xen/Kconfig"
+-
+ source "lib/Kconfig"
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:32.000000000 +0100
+@@ -129,12 +129,14 @@ sysenter_tracesys:
+ 	SAVE_REST
+ 	CLEAR_RREGS
+ 	movq	%r9,R9(%rsp)
+-	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq	$-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+ 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call	syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl	%ebp,%r9d
++	cmpl	$(IA32_NR_syscalls-1),%eax
++	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+ 	jmp	sysenter_do_call
+ 	CFI_ENDPROC
+ ENDPROC(ia32_sysenter_target)
+@@ -200,13 +202,15 @@ cstar_tracesys:	
+ 	SAVE_REST
+ 	CLEAR_RREGS
+ 	movq %r9,R9(%rsp)
+-	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl %ebp,%r9d
+ 	movl RSP-ARGOFFSET(%rsp), %r8d
++	cmpl $(IA32_NR_syscalls-1),%eax
++	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+ 	jmp cstar_do_call
+ END(ia32_cstar_target)
+ 				
+@@ -264,7 +268,7 @@ ENTRY(ia32_syscall)
+ 	jnz ia32_tracesys
+ ia32_do_syscall:	
+ 	cmpl $(IA32_NR_syscalls-1),%eax
+-	ja  ia32_badsys
++	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+ 	IA32_ARG_FIXUP
+ 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ ia32_sysret:
+@@ -274,7 +278,7 @@ ia32_sysret:
+ ia32_tracesys:			 
+ 	SAVE_REST
+ 	CLEAR_RREGS
+-	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+@@ -365,7 +369,7 @@ ia32_sys_call_table:
+ 	.quad sys_setuid16
+ 	.quad sys_getuid16
+ 	.quad compat_sys_stime	/* stime */		/* 25 */
+-	.quad sys32_ptrace	/* ptrace */
++	.quad compat_sys_ptrace	/* ptrace */
+ 	.quad sys_alarm
+ 	.quad sys_fstat	/* (old)fstat */
+ 	.quad sys_pause
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:51:32.000000000 +0100
+@@ -136,8 +136,7 @@ ifeq ($(CONFIG_X86_64),y)
+ 
+ 	obj-$(CONFIG_XEN)		+= nmi_64.o
+ 	time_64-$(CONFIG_XEN)		+= time_32.o
+-	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := early-quirks.o hpet.o i8253.o i8259_$(BITS).o reboot.o \
+-	smpboot_$(BITS).o tsc_$(BITS).o tsc_sync.o
++disabled-obj-$(CONFIG_XEN) := crash.o early-quirks.o hpet.o i8253.o i8259_$(BITS).o \
++	pci-swiotlb_64.o reboot.o smpboot.o tlb_$(BITS).o tsc_$(BITS).o tsc_sync.o vsmp_64.o
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/Makefile	2009-11-06 10:51:32.000000000 +0100
+@@ -15,4 +15,4 @@ $(obj)/wakeup_rm.o:    $(obj)/realmode/w
+ $(obj)/realmode/wakeup.bin: FORCE
+ 	$(Q)$(MAKE) $(build)=$(obj)/realmode
+ 
+-disabled-obj-$(CONFIG_XEN)	:= cstate.o wakeup_$(BITS).o
++disabled-obj-$(CONFIG_XEN)	:= cstate.o wakeup_%.o
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:32.000000000 +0100
+@@ -156,6 +156,7 @@ static int __init acpi_parse_madt(struct
+ 
+ static void __cpuinit acpi_register_lapic(int id, u8 enabled)
+ {
++#ifndef CONFIG_XEN
+ 	unsigned int ver = 0;
+ 
+ 	if (!enabled) {
+@@ -167,6 +168,7 @@ static void __cpuinit acpi_register_lapi
+ 		ver = apic_version[boot_cpu_physical_apicid];
+ 
+ 	generic_processor_info(id, ver);
++#endif
+ }
+ 
+ static int __init
+@@ -741,6 +743,7 @@ static int __init acpi_parse_fadt(struct
+  * returns 0 on success, < 0 on error
+  */
+ 
++#ifndef CONFIG_XEN
+ static void __init acpi_register_lapic_address(unsigned long address)
+ {
+ 	mp_lapic_addr = address;
+@@ -752,6 +755,9 @@ static void __init acpi_register_lapic_a
+ 			 GET_APIC_VERSION(apic_read(APIC_LVR));
+ 	}
+ }
++#else
++#define acpi_register_lapic_address(address)
++#endif
+ 
+ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -10,15 +10,19 @@
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
+ 
+-#include <asm/smp.h>
++#include "realmode/wakeup.h"
++#include "sleep.h"
+ 
+ #ifndef CONFIG_ACPI_PV_SLEEP
+-/* address in low memory of the wakeup routine. */
+-unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_wakeup_address;
+ unsigned long acpi_realmode_flags;
+-extern char wakeup_start, wakeup_end;
+ 
+-extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++/* address in low memory of the wakeup routine. */
++static unsigned long acpi_realmode;
++
++#ifdef CONFIG_64BIT
++static char temp_stack[10240];
++#endif
+ #endif
+ 
+ /**
+@@ -26,17 +30,69 @@ extern unsigned long acpi_copy_wakeup_ro
+  *
+  * Create an identity mapped page table and copy the wakeup routine to
+  * low memory.
++ *
++ * Note that this is too late to change acpi_wakeup_address.
+  */
+ int acpi_save_state_mem(void)
+ {
+ #ifndef CONFIG_ACPI_PV_SLEEP
+-	if (!acpi_wakeup_address) {
+-		printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
++	struct wakeup_header *header;
++
++	if (!acpi_realmode) {
++		printk(KERN_ERR "Could not allocate memory during boot, "
++		       "S3 disabled\n");
+ 		return -ENOMEM;
+ 	}
+-	memcpy((void *)acpi_wakeup_address, &wakeup_start,
+-	       &wakeup_end - &wakeup_start);
+-	acpi_copy_wakeup_routine(acpi_wakeup_address);
++	memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
++
++	header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
++	if (header->signature != 0x51ee1111) {
++		printk(KERN_ERR "wakeup header does not match\n");
++		return -EINVAL;
++	}
++
++	header->video_mode = saved_video_mode;
++
++	header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
++	/* GDT[0]: GDT self-pointer */
++	header->wakeup_gdt[0] =
++		(u64)(sizeof(header->wakeup_gdt) - 1) +
++		((u64)(acpi_wakeup_address +
++			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
++				<< 16);
++	/* GDT[1]: real-mode-like code segment */
++	header->wakeup_gdt[1] = (0x009bULL << 40) +
++		((u64)acpi_wakeup_address << 16) + 0xffff;
++	/* GDT[2]: real-mode-like data segment */
++	header->wakeup_gdt[2] = (0x0093ULL << 40) +
++		((u64)acpi_wakeup_address << 16) + 0xffff;
++
++#ifndef CONFIG_64BIT
++	store_gdt((struct desc_ptr *)&header->pmode_gdt);
++
++	header->pmode_efer_low = nx_enabled;
++	if (header->pmode_efer_low & 1) {
++		/* This is strange, why not save efer, always? */
++		rdmsr(MSR_EFER, header->pmode_efer_low,
++			header->pmode_efer_high);
++	}
++#endif /* !CONFIG_64BIT */
++
++	header->pmode_cr0 = read_cr0();
++	header->pmode_cr4 = read_cr4();
++	header->realmode_flags = acpi_realmode_flags;
++	header->real_magic = 0x12345678;
++
++#ifndef CONFIG_64BIT
++	header->pmode_entry = (u32)&wakeup_pmode_return;
++	header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
++	saved_magic = 0x12345678;
++#else /* CONFIG_64BIT */
++	header->trampoline_segment = setup_trampoline() >> 4;
++	init_rsp = (unsigned long)temp_stack + 4096;
++	initial_code = (unsigned long)wakeup_long64;
++	saved_magic = 0x123456789abcdef0;
++#endif /* CONFIG_64BIT */
+ #endif
+ 
+ 	return 0;
+@@ -61,15 +117,20 @@ void acpi_restore_state_mem(void)
+ void __init acpi_reserve_bootmem(void)
+ {
+ #ifndef CONFIG_ACPI_PV_SLEEP
+-	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) {
++	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
+ 		printk(KERN_ERR
+ 		       "ACPI: Wakeup code way too big, S3 disabled.\n");
+ 		return;
+ 	}
+ 
+-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
+-	if (!acpi_wakeup_address)
++	acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
++
++	if (!acpi_realmode) {
+ 		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
++		return;
++	}
++
++	acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
+ #endif
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -5,7 +5,6 @@
+ #include <linux/module.h>
+ #include <linux/percpu.h>
+ #include <linux/bootmem.h>
+-#include <asm/semaphore.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+@@ -13,6 +12,7 @@
+ #include <asm/mmu_context.h>
+ #include <asm/mtrr.h>
+ #include <asm/mce.h>
++#include <asm/pat.h>
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #include <asm/mpspec.h>
+ #include <asm/apic.h>
+@@ -69,9 +69,9 @@ __u32 cleared_cpu_caps[NCAPINTS] __cpuin
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+ 
+-struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
++struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+ 
+-static void __cpuinit default_init(struct cpuinfo_x86 * c)
++static void __cpuinit default_init(struct cpuinfo_x86 *c)
+ {
+ 	/* Not much we can do here... */
+ 	/* Check if at least it has cpuid */
+@@ -88,11 +88,11 @@ static struct cpu_dev __cpuinitdata defa
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
+ };
+-static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
++static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+ 
+ static int __init cachesize_setup(char *str)
+ {
+-	get_option (&str, &cachesize_override);
++	get_option(&str, &cachesize_override);
+ 	return 1;
+ }
+ __setup("cachesize=", cachesize_setup);
+@@ -114,12 +114,12 @@ int __cpuinit get_model_name(struct cpui
+ 	/* Intel chips right-justify this string for some dumb reason;
+ 	   undo that brain damage */
+ 	p = q = &c->x86_model_id[0];
+-	while ( *p == ' ' )
++	while (*p == ' ')
+ 	     p++;
+-	if ( p != q ) {
+-	     while ( *p )
++	if (p != q) {
++	     while (*p)
+ 		  *q++ = *p++;
+-	     while ( q <= &c->x86_model_id[48] )
++	     while (q <= &c->x86_model_id[48])
+ 		  *q++ = '\0';	/* Zero-pad the rest */
+ 	}
+ 
+@@ -137,7 +137,7 @@ void __cpuinit display_cacheinfo(struct 
+ 		cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ 		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+ 			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size=(ecx>>24)+(edx>>24);	
++		c->x86_cache_size = (ecx>>24)+(edx>>24);
+ 	}
+ 
+ 	if (n < 0x80000006)	/* Some chips just has a large L1. */
+@@ -145,16 +145,16 @@ void __cpuinit display_cacheinfo(struct 
+ 
+ 	ecx = cpuid_ecx(0x80000006);
+ 	l2size = ecx >> 16;
+-	
++
+ 	/* do processor-specific cache resizing */
+ 	if (this_cpu->c_size_cache)
+-		l2size = this_cpu->c_size_cache(c,l2size);
++		l2size = this_cpu->c_size_cache(c, l2size);
+ 
+ 	/* Allow user to override all this if necessary. */
+ 	if (cachesize_override != -1)
+ 		l2size = cachesize_override;
+ 
+-	if ( l2size == 0 )
++	if (l2size == 0)
+ 		return;		/* Again, no L2 cache is possible */
+ 
+ 	c->x86_cache_size = l2size;
+@@ -163,16 +163,19 @@ void __cpuinit display_cacheinfo(struct 
+ 	       l2size, ecx & 0xFF);
+ }
+ 
+-/* Naming convention should be: <Name> [(<Codename>)] */
+-/* This table only is used unless init_<vendor>() below doesn't set it; */
+-/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
++/*
++ * Naming convention should be: <Name> [(<Codename>)]
++ * This table only is used unless init_<vendor>() below doesn't set it;
++ * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
++ *
++ */
+ 
+ /* Look up CPU names by table lookup. */
+ static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
+ {
+ 	struct cpu_model_info *info;
+ 
+-	if ( c->x86_model >= 16 )
++	if (c->x86_model >= 16)
+ 		return NULL;	/* Range check */
+ 
+ 	if (!this_cpu)
+@@ -197,9 +200,9 @@ static void __cpuinit get_cpu_vendor(str
+ 
+ 	for (i = 0; i < X86_VENDOR_NUM; i++) {
+ 		if (cpu_devs[i]) {
+-			if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
+-			    (cpu_devs[i]->c_ident[1] && 
+-			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {
++			if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
++			    (cpu_devs[i]->c_ident[1] &&
++			     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+ 				c->x86_vendor = i;
+ 				if (!early)
+ 					this_cpu = cpu_devs[i];
+@@ -217,7 +220,7 @@ static void __cpuinit get_cpu_vendor(str
+ }
+ 
+ 
+-static int __init x86_fxsr_setup(char * s)
++static int __init x86_fxsr_setup(char *s)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_FXSR);
+ 	setup_clear_cpu_cap(X86_FEATURE_XMM);
+@@ -226,7 +229,7 @@ static int __init x86_fxsr_setup(char * 
+ __setup("nofxsr", x86_fxsr_setup);
+ 
+ 
+-static int __init x86_sep_setup(char * s)
++static int __init x86_sep_setup(char *s)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_SEP);
+ 	return 1;
+@@ -315,12 +318,15 @@ static void __cpuinit early_get_cap(stru
+ 
+ }
+ 
+-/* Do minimum CPU detection early.
+-   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+-   The others are not touched to avoid unwanted side effects.
+-
+-   WARNING: this function is only called on the BP.  Don't add code here
+-   that is supposed to run on all CPUs. */
++/*
++ * Do minimum CPU detection early.
++ * Fields really needed: vendor, cpuid_level, family, model, mask,
++ * cache alignment.
++ * The others are not touched to avoid unwanted side effects.
++ *
++ * WARNING: this function is only called on the BP.  Don't add code here
++ * that is supposed to run on all CPUs.
++ */
+ static void __init early_cpu_detect(void)
+ {
+ 	struct cpuinfo_x86 *c = &boot_cpu_data;
+@@ -335,19 +341,14 @@ static void __init early_cpu_detect(void
+ 
+ 	get_cpu_vendor(c, 1);
+ 
+-	switch (c->x86_vendor) {
+-	case X86_VENDOR_AMD:
+-		early_init_amd(c);
+-		break;
+-	case X86_VENDOR_INTEL:
+-		early_init_intel(c);
+-		break;
+-	}
++	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
++	    cpu_devs[c->x86_vendor]->c_early_init)
++		cpu_devs[c->x86_vendor]->c_early_init(c);
+ 
+ 	early_get_cap(c);
+ }
+ 
+-static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
++static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+ {
+ 	u32 tfms, xlvl;
+ 	unsigned int ebx;
+@@ -358,13 +359,12 @@ static void __cpuinit generic_identify(s
+ 		      (unsigned int *)&c->x86_vendor_id[0],
+ 		      (unsigned int *)&c->x86_vendor_id[8],
+ 		      (unsigned int *)&c->x86_vendor_id[4]);
+-		
++
+ 		get_cpu_vendor(c, 0);
+ 		/* Initialize the standard set of capabilities */
+ 		/* Note that the vendor-specific code below might override */
+-	
+ 		/* Intel-defined flags: level 0x00000001 */
+-		if ( c->cpuid_level >= 0x00000001 ) {
++		if (c->cpuid_level >= 0x00000001) {
+ 			u32 capability, excap;
+ 			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+ 			c->x86_capability[0] = capability;
+@@ -376,14 +376,16 @@ static void __cpuinit generic_identify(s
+ 			if (c->x86 >= 0x6)
+ 				c->x86_model += ((tfms >> 16) & 0xF) << 4;
+ 			c->x86_mask = tfms & 15;
++			c->initial_apicid = (ebx >> 24) & 0xFF;
+ #ifndef CONFIG_XEN
+ #ifdef CONFIG_X86_HT
+-			c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
++			c->apicid = phys_pkg_id(c->initial_apicid, 0);
++			c->phys_proc_id = c->initial_apicid;
+ #else
+-			c->apicid = (ebx >> 24) & 0xFF;
++			c->apicid = c->initial_apicid;
+ #endif
+ #endif
+-			if (c->x86_capability[0] & (1<<19))
++			if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ 				c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+ 		} else {
+ 			/* Have CPUID level 0 only - unheard of */
+@@ -392,33 +394,30 @@ static void __cpuinit generic_identify(s
+ 
+ 		/* AMD-defined flags: level 0x80000001 */
+ 		xlvl = cpuid_eax(0x80000000);
+-		if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+-			if ( xlvl >= 0x80000001 ) {
++		if ((xlvl & 0xffff0000) == 0x80000000) {
++			if (xlvl >= 0x80000001) {
+ 				c->x86_capability[1] = cpuid_edx(0x80000001);
+ 				c->x86_capability[6] = cpuid_ecx(0x80000001);
+ 			}
+-			if ( xlvl >= 0x80000004 )
++			if (xlvl >= 0x80000004)
+ 				get_model_name(c); /* Default name */
+ 		}
+ 
+ 		init_scattered_cpuid_features(c);
+ 	}
+ 
+-#ifdef CONFIG_X86_HT
+-	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+-#endif
+ }
+ 
+ static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+ {
+-	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
++	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
+ 		/* Disable processor serial number */
+-		unsigned long lo,hi;
+-		rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		unsigned long lo, hi;
++		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ 		lo |= 0x200000;
+-		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+ 		printk(KERN_NOTICE "CPU serial number disabled.\n");
+-		clear_bit(X86_FEATURE_PN, c->x86_capability);
++		clear_cpu_cap(c, X86_FEATURE_PN);
+ 
+ 		/* Disabling the serial number may affect the cpuid level */
+ 		c->cpuid_level = cpuid_eax(0);
+@@ -453,9 +452,11 @@ void __cpuinit identify_cpu(struct cpuin
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ 
+ 	if (!have_cpuid_p()) {
+-		/* First of all, decide if this is a 486 or higher */
+-		/* It's a 486 if we can modify the AC flag */
+-		if ( flag_is_changeable_p(X86_EFLAGS_AC) )
++		/*
++		 * First of all, decide if this is a 486 or higher
++		 * It's a 486 if we can modify the AC flag
++		 */
++		if (flag_is_changeable_p(X86_EFLAGS_AC))
+ 			c->x86 = 4;
+ 		else
+ 			c->x86 = 3;
+@@ -488,10 +489,10 @@ void __cpuinit identify_cpu(struct cpuin
+ 	 */
+ 
+ 	/* If the model name is still unset, do table lookup. */
+-	if ( !c->x86_model_id[0] ) {
++	if (!c->x86_model_id[0]) {
+ 		char *p;
+ 		p = table_lookup_model(c);
+-		if ( p )
++		if (p)
+ 			strcpy(c->x86_model_id, p);
+ 		else
+ 			/* Last resort... */
+@@ -505,9 +506,9 @@ void __cpuinit identify_cpu(struct cpuin
+ 	 * common between the CPUs.  The first time this routine gets
+ 	 * executed, c == &boot_cpu_data.
+ 	 */
+-	if ( c != &boot_cpu_data ) {
++	if (c != &boot_cpu_data) {
+ 		/* AND the already accumulated flags with these */
+-		for ( i = 0 ; i < NCAPINTS ; i++ )
++		for (i = 0 ; i < NCAPINTS ; i++)
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
+@@ -551,7 +552,7 @@ void __cpuinit detect_ht(struct cpuinfo_
+ 
+ 	if (smp_num_siblings == 1) {
+ 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1 ) {
++	} else if (smp_num_siblings > 1) {
+ 
+ 		if (smp_num_siblings > NR_CPUS) {
+ 			printk(KERN_WARNING "CPU: Unsupported number of the "
+@@ -561,7 +562,7 @@ void __cpuinit detect_ht(struct cpuinfo_
+ 		}
+ 
+ 		index_msb = get_count_order(smp_num_siblings);
+-		c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
++		c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
+ 
+ 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+ 		       c->phys_proc_id);
+@@ -572,7 +573,7 @@ void __cpuinit detect_ht(struct cpuinfo_
+ 
+ 		core_bits = get_count_order(c->x86_max_cores);
+ 
+-		c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
++		c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+ 					       ((1 << core_bits) - 1);
+ 
+ 		if (c->x86_max_cores > 1)
+@@ -606,7 +607,7 @@ void __cpuinit print_cpu_info(struct cpu
+ 	else
+ 		printk("%s", c->x86_model_id);
+ 
+-	if (c->x86_mask || c->cpuid_level >= 0) 
++	if (c->x86_mask || c->cpuid_level >= 0)
+ 		printk(" stepping %02x\n", c->x86_mask);
+ 	else
+ 		printk("\n");
+@@ -625,24 +626,17 @@ __setup("clearcpuid=", setup_disablecpui
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+-/* This is hacky. :)
+- * We're emulating future behavior.
+- * In the future, the cpu-specific init functions will be called implicitly
+- * via the magic of initcalls.
+- * They will insert themselves into the cpu_devs structure.
+- * Then, when cpu_init() is called, we can just iterate over that array.
+- */
+ void __init early_cpu_init(void)
+ {
+-	intel_cpu_init();
+-	cyrix_init_cpu();
+-	nsc_init_cpu();
+-	amd_init_cpu();
+-	centaur_init_cpu();
+-	transmeta_init_cpu();
+-	nexgen_init_cpu();
+-	umc_init_cpu();
++	struct cpu_vendor_dev *cvdev;
++
++	for (cvdev = __x86cpuvendor_start ;
++	     cvdev < __x86cpuvendor_end   ;
++	     cvdev++)
++		cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
++
+ 	early_cpu_detect();
++	validate_pat_support(&boot_cpu_data);
+ }
+ 
+ /* Make sure %fs is initialized properly in idle threads */
+@@ -687,7 +681,7 @@ void __cpuinit cpu_init(void)
+ 	int cpu = smp_processor_id();
+ 	struct task_struct *curr = current;
+ #ifndef CONFIG_X86_NO_TSS
+-	struct tss_struct * t = &per_cpu(init_tss, cpu);
++	struct tss_struct *t = &per_cpu(init_tss, cpu);
+ #endif
+ 	struct thread_struct *thread = &curr->thread;
+ 
+@@ -740,7 +734,7 @@ void __cpuinit cpu_init(void)
+ 	mxcsr_feature_mask_init();
+ }
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
++#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_XEN)
+ void __cpuinit cpu_uninit(void)
+ {
+ 	int cpu = raw_smp_processor_id();
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -35,6 +35,8 @@ struct mtrr_ops *mtrr_if = &generic_mtrr
+ unsigned int num_var_ranges;
+ unsigned int mtrr_usage_table[MAX_VAR_RANGES];
+ 
++static u64 tom2;
++
+ static void __init set_num_var_ranges(void)
+ {
+ 	struct xen_platform_op op;
+@@ -162,8 +164,144 @@ mtrr_del(int reg, unsigned long base, un
+ EXPORT_SYMBOL(mtrr_add);
+ EXPORT_SYMBOL(mtrr_del);
+ 
++/*
++ * Returns the effective MTRR type for the region
++ * Error returns:
++ * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
++ * - 0xFF - when MTRR is not enabled
++ */
++u8 mtrr_type_lookup(u64 start, u64 end)
++{
++	int i, error;
++	u64 start_mfn, end_mfn, base_mfn, top_mfn;
++	u8 prev_match, curr_match;
++	struct xen_platform_op op;
++
++	if (!is_initial_xendomain())
++		return MTRR_TYPE_WRBACK;
++
++	if (!num_var_ranges)
++		return 0xFF;
++
++	start_mfn = start >> PAGE_SHIFT;
++	/* Make end inclusive end, instead of exclusive */
++	end_mfn = --end >> PAGE_SHIFT;
++
++	/* Look in fixed ranges. Just return the type as per start */
++	if (start_mfn < 0x100) {
++#if 0//todo
++		op.cmd = XENPF_read_memtype;
++		op.u.read_memtype.reg = ???;
++		error = HYPERVISOR_platform_op(&op);
++		if (!error)
++			return op.u.read_memtype.type;
++#endif
++		return MTRR_TYPE_UNCACHABLE;
++	}
++
++	/*
++	 * Look in variable ranges
++	 * Look of multiple ranges matching this address and pick type
++	 * as per MTRR precedence
++	 */
++	prev_match = 0xFF;
++	for (i = 0; i < num_var_ranges; ++i) {
++		op.cmd = XENPF_read_memtype;
++		op.u.read_memtype.reg = i;
++		error = HYPERVISOR_platform_op(&op);
++
++		if (error || !op.u.read_memtype.nr_mfns)
++			continue;
++
++		base_mfn = op.u.read_memtype.mfn;
++		top_mfn = base_mfn + op.u.read_memtype.nr_mfns - 1;
++
++		if (base_mfn > end_mfn || start_mfn > top_mfn) {
++			continue;
++		}
++
++		if (base_mfn > start_mfn || end_mfn > top_mfn) {
++			return 0xFE;
++		}
++
++		curr_match = op.u.read_memtype.type;
++		if (prev_match == 0xFF) {
++			prev_match = curr_match;
++			continue;
++		}
++
++		if (prev_match == MTRR_TYPE_UNCACHABLE ||
++		    curr_match == MTRR_TYPE_UNCACHABLE) {
++			return MTRR_TYPE_UNCACHABLE;
++		}
++
++		if ((prev_match == MTRR_TYPE_WRBACK &&
++		     curr_match == MTRR_TYPE_WRTHROUGH) ||
++		    (prev_match == MTRR_TYPE_WRTHROUGH &&
++		     curr_match == MTRR_TYPE_WRBACK)) {
++			prev_match = MTRR_TYPE_WRTHROUGH;
++			curr_match = MTRR_TYPE_WRTHROUGH;
++		}
++
++		if (prev_match != curr_match) {
++			return MTRR_TYPE_UNCACHABLE;
++		}
++	}
++
++	if (tom2) {
++		if (start >= (1ULL<<32) && (end < tom2))
++			return MTRR_TYPE_WRBACK;
++	}
++
++	if (prev_match != 0xFF)
++		return prev_match;
++
++#if 0//todo
++	op.cmd = XENPF_read_def_memtype;
++	error = HYPERVISOR_platform_op(&op);
++	if (!error)
++		return op.u.read_def_memtype.type;
++#endif
++	return MTRR_TYPE_UNCACHABLE;
++}
++
++/*
++ * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
++ * for memory >4GB. Check for that here.
++ * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
++ * apply to are wrong, but so far we don't know of any such case in the wild.
++ */
++#define Tom2Enabled (1U << 21)
++#define Tom2ForceMemTypeWB (1U << 22)
++
++int __init amd_special_default_mtrr(void)
++{
++	u32 l, h;
++
++	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
++		return 0;
++	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
++		return 0;
++	/* In case some hypervisor doesn't pass SYSCFG through */
++	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
++		return 0;
++	/*
++	 * Memory between 4GB and top of mem is forced WB by this magic bit.
++	 * Reserved before K8RevF, but should be zero there.
++	 */
++	if ((l & (Tom2Enabled | Tom2ForceMemTypeWB)) ==
++		 (Tom2Enabled | Tom2ForceMemTypeWB))
++		return 1;
++	return 0;
++}
++
+ void __init mtrr_bp_init(void)
+ {
++	if (amd_special_default_mtrr()) {
++		/* TOP_MEM2 */
++		rdmsrl(MSR_K8_TOP_MEM2, tom2);
++		tom2 &= 0xffffff8000000ULL;
++	}
+ }
+ 
+ void mtrr_ap_init(void)
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -469,7 +469,7 @@ int __init sanitize_e820_map(struct e820
+  * thinkpad 560x, for example, does not cooperate with the memory
+  * detection code.)
+  */
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ {
+ #ifndef CONFIG_XEN
+ 	/* Only one memory region (or negative)? Ignore it */
+@@ -480,33 +480,17 @@ int __init copy_e820_map(struct e820entr
+ #endif
+ 
+ 	do {
+-		unsigned long long start = biosmap->addr;
+-		unsigned long long size = biosmap->size;
+-		unsigned long long end = start + size;
+-		unsigned long type = biosmap->type;
++		u64 start = biosmap->addr;
++		u64 size = biosmap->size;
++		u64 end = start + size;
++		u32 type = biosmap->type;
+ 
+ 		/* Overflow in 64 bits? Ignore the memory map. */
+ 		if (start > end)
+ 			return -1;
+ 
+-#ifndef CONFIG_XEN
+-		/*
+-		 * Some BIOSes claim RAM in the 640k - 1M region.
+-		 * Not right. Fix it up.
+-		 */
+-		if (type == E820_RAM) {
+-			if (start < 0x100000ULL && end > 0xA0000ULL) {
+-				if (start < 0xA0000ULL)
+-					add_memory_region(start, 0xA0000ULL-start, type);
+-				if (end <= 0x100000ULL)
+-					continue;
+-				start = 0x100000ULL;
+-				size = end - start;
+-			}
+-		}
+-#endif
+ 		add_memory_region(start, size, type);
+-	} while (biosmap++,--nr_map);
++	} while (biosmap++, --nr_map);
+ 
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain()) {
+@@ -528,7 +512,7 @@ int __init copy_e820_map(struct e820entr
+ /*
+  * Find the highest page frame number we have available
+  */
+-void __init find_max_pfn(void)
++void __init propagate_e820_map(void)
+ {
+ 	int i;
+ 
+@@ -801,7 +785,7 @@ static int __init parse_memmap(char *arg
+ 		 * size before original memory map is
+ 		 * reset.
+ 		 */
+-		find_max_pfn();
++		propagate_e820_map();
+ 		saved_max_pfn = max_pfn;
+ #endif
+ 		e820.nr_map = 0;
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:03:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:09:25.000000000 +0100
+@@ -41,11 +41,11 @@ unsigned long end_pfn;
+ 
+ #ifndef CONFIG_XEN
+ /*
+- * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
+- * The direct mapping extends to end_pfn_map, so that we can directly access
++ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
++ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+  * apertures, ACPI and other tables without having to play with fixmaps.
+  */
+-unsigned long end_pfn_map;
++unsigned long max_pfn_mapped;
+ #endif
+ 
+ /*
+@@ -65,8 +65,8 @@ struct early_res {
+ static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ #ifndef CONFIG_XEN
+ 	{ 0, PAGE_SIZE, "BIOS data page" },			/* BIOS data page */
+-#ifdef CONFIG_SMP
+-	{ SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" },
++#ifdef CONFIG_X86_TRAMPOLINE
++	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
+ #endif
+ #endif
+ 	{}
+@@ -91,19 +91,47 @@ void __init reserve_early(unsigned long 
+ 		strncpy(r->name, name, sizeof(r->name) - 1);
+ }
+ 
+-void __init early_res_to_bootmem(void)
++void __init free_early(unsigned long start, unsigned long end)
++{
++	struct early_res *r;
++	int i, j;
++
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		r = &early_res[i];
++		if (start == r->start && end == r->end)
++			break;
++	}
++	if (i >= MAX_EARLY_RES || !early_res[i].end)
++		panic("free_early on not reserved area: %lx-%lx!", start, end);
++
++	for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
++		;
++
++	memmove(&early_res[i], &early_res[i + 1],
++	       (j - 1 - i) * sizeof(struct early_res));
++
++	early_res[j - 1].end = 0;
++}
++
++void __init early_res_to_bootmem(unsigned long start, unsigned long end)
+ {
+ 	int i;
++	unsigned long final_start, final_end;
+ 	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+ 		struct early_res *r = &early_res[i];
+-		printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i,
+-			r->start, r->end - 1, r->name);
+-		reserve_bootmem_generic(r->start, r->end - r->start);
++		final_start = max(start, r->start);
++		final_end = min(end, r->end);
++		if (final_start >= final_end)
++			continue;
++		printk(KERN_INFO "  early res: %d [%lx-%lx] %s\n", i,
++			final_start, final_end - 1, r->name);
++		reserve_bootmem_generic(final_start, final_end - final_start);
+ 	}
+ }
+ 
+ /* Check for already reserved areas */
+-static inline int bad_addr(unsigned long *addrp, unsigned long size)
++static inline int __init
++bad_addr(unsigned long *addrp, unsigned long size, unsigned long align)
+ {
+ 	int i;
+ 	unsigned long addr = *addrp, last;
+@@ -113,7 +141,7 @@ again:
+ 	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+ 		struct early_res *r = &early_res[i];
+ 		if (last >= r->start && addr < r->end) {
+-			*addrp = addr = r->end;
++			*addrp = addr = round_up(r->end, align);
+ 			changed = 1;
+ 			goto again;
+ 		}
+@@ -121,6 +149,40 @@ again:
+ 	return changed;
+ }
+ 
++/* Check for already reserved areas */
++static inline int __init
++bad_addr_size(unsigned long *addrp, unsigned long *sizep, unsigned long align)
++{
++	int i;
++	unsigned long addr = *addrp, last;
++	unsigned long size = *sizep;
++	int changed = 0;
++again:
++	last = addr + size;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		struct early_res *r = &early_res[i];
++		if (last > r->start && addr < r->start) {
++			size = r->start - addr;
++			changed = 1;
++			goto again;
++		}
++		if (last > r->end && addr < r->end) {
++			addr = round_up(r->end, align);
++			size = last - addr;
++			changed = 1;
++			goto again;
++		}
++		if (last <= r->end && addr >= r->start) {
++			(*sizep)++;
++			return 0;
++		}
++	}
++	if (changed) {
++		*addrp = addr;
++		*sizep = size;
++	}
++	return changed;
++}
+ /*
+  * This function checks if any part of the range <start,end> is mapped
+  * with type.
+@@ -196,26 +258,27 @@ int __init e820_all_mapped(unsigned long
+  * Find a free area with specified alignment in a specific range.
+  */
+ unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+-				    unsigned size, unsigned long align)
++				    unsigned long size, unsigned long align)
+ {
+ 	int i;
+-	unsigned long mask = ~(align - 1);
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		struct e820entry *ei = &e820.map[i];
+-		unsigned long addr = ei->addr, last;
++		unsigned long addr, last;
++		unsigned long ei_last;
+ 
+ 		if (ei->type != E820_RAM)
+ 			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
+ 		if (addr < start)
+-			addr = start;
+-		if (addr > ei->addr + ei->size)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
+ 			continue;
+-		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
++		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+ 			;
+-		addr = (addr + align - 1) & mask;
+ 		last = addr + size;
+-		if (last > ei->addr + ei->size)
++		if (last > ei_last)
+ 			continue;
+ 		if (last > end)
+ 			continue;
+@@ -225,6 +288,40 @@ unsigned long __init find_e820_area(unsi
+ }
+ 
+ /*
++ * Find next free range after *start
++ */
++unsigned long __init find_e820_area_size(unsigned long start,
++					 unsigned long *sizep,
++					 unsigned long align)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long addr, last;
++		unsigned long ei_last;
++
++		if (ei->type != E820_RAM)
++			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
++		if (addr < start)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
++			continue;
++		*sizep = ei_last - addr;
++		while (bad_addr_size(&addr, sizep, align) &&
++			addr + *sizep <= ei_last)
++			;
++		last = addr + *sizep;
++		if (last > ei_last)
++			continue;
++		return addr;
++	}
++	return -1UL;
++
++}
++/*
+  * Find the highest page frame number we have available
+  */
+ unsigned long __init e820_end_of_ram(void)
+@@ -233,31 +330,29 @@ unsigned long __init e820_end_of_ram(voi
+ 
+ 	end_pfn = find_max_pfn_with_active_regions();
+ 
+-	if (end_pfn > end_pfn_map)
+-		end_pfn_map = end_pfn;
+-	if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
+-		end_pfn_map = MAXMEM>>PAGE_SHIFT;
++	if (end_pfn > max_pfn_mapped)
++		max_pfn_mapped = end_pfn;
++	if (max_pfn_mapped > MAXMEM>>PAGE_SHIFT)
++		max_pfn_mapped = MAXMEM>>PAGE_SHIFT;
+ 	if (end_pfn > end_user_pfn)
+ 		end_pfn = end_user_pfn;
+-	if (end_pfn > end_pfn_map)
+-		end_pfn = end_pfn_map;
++	if (end_pfn > max_pfn_mapped)
++		end_pfn = max_pfn_mapped;
+ 
+-	printk(KERN_INFO "end_pfn_map = %lu\n", end_pfn_map);
++	printk(KERN_INFO "max_pfn_mapped = %lu\n", max_pfn_mapped);
+ 	return end_pfn;
+ }
+ 
+ /*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+-void __init e820_reserve_resources(struct e820entry *e820, int nr_map,
+-				   struct resource *code_resource,
+-				   struct resource *data_resource,
+-				   struct resource *bss_resource)
++void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
+ {
+ 	int i;
++	struct resource *res;
++
++	res = alloc_bootmem_low(sizeof(struct resource) * nr_map);
+ 	for (i = 0; i < nr_map; i++) {
+-		struct resource *res;
+-		res = alloc_bootmem_low(sizeof(struct resource));
+ 		switch (e820[i].type) {
+ 		case E820_RAM:	res->name = "System RAM"; break;
+ 		case E820_ACPI:	res->name = "ACPI Tables"; break;
+@@ -267,26 +362,8 @@ void __init e820_reserve_resources(struc
+ 		res->start = e820[i].addr;
+ 		res->end = res->start + e820[i].size - 1;
+ 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		request_resource(&iomem_resource, res);
+-		if (e820[i].type == E820_RAM) {
+-			/*
+-			 * We don't know which RAM region contains kernel data,
+-			 * so we try it repeatedly and let the resource manager
+-			 * test it.
+-			 */
+-#ifndef CONFIG_XEN
+-			request_resource(res, code_resource);
+-			request_resource(res, data_resource);
+-			request_resource(res, bss_resource);
+-#endif
+-#ifdef CONFIG_KEXEC
+-			if (crashk_res.start != crashk_res.end)
+-				request_resource(res, &crashk_res);
+-#ifdef CONFIG_XEN
+-			xen_machine_kexec_register_resources(res);
+-#endif
+-#endif
+-		}
++		insert_resource(&iomem_resource, res);
++		res++;
+ 	}
+ }
+ 
+@@ -345,9 +422,9 @@ static int __init e820_find_active_regio
+ 	if (*ei_startpfn >= *ei_endpfn)
+ 		return 0;
+ 
+-	/* Check if end_pfn_map should be updated */
+-	if (ei->type != E820_RAM && *ei_endpfn > end_pfn_map)
+-		end_pfn_map = *ei_endpfn;
++	/* Check if max_pfn_mapped should be updated */
++	if (ei->type != E820_RAM && *ei_endpfn > max_pfn_mapped)
++		max_pfn_mapped = *ei_endpfn;
+ 
+ 	/* Skip if map is outside the node */
+ 	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
+@@ -678,10 +755,10 @@ static int __init copy_e820_map(struct e
+ #endif
+ 
+ 	do {
+-		unsigned long start = biosmap->addr;
+-		unsigned long size = biosmap->size;
+-		unsigned long end = start + size;
+-		unsigned long type = biosmap->type;
++		u64 start = biosmap->addr;
++		u64 size = biosmap->size;
++		u64 end = start + size;
++		u32 type = biosmap->type;
+ 
+ 		/* Overflow in 64 bits? Ignore the memory map. */
+ 		if (start > end)
+@@ -731,11 +808,7 @@ char * __init machine_specific_memory_se
+ 	char *who = "Xen";
+ 	int rc;
+ 	struct xen_memory_map memmap;
+-	/*
+-	 * This is rather large for a stack variable but this early in
+-	 * the boot process we know we have plenty slack space.
+-	 */
+-	struct e820entry map[E820MAX];
++	static struct e820entry __initdata map[E820MAX];
+ 
+ 	memmap.nr_entries = E820MAX;
+ 	set_xen_guest_handle(memmap.buffer, map);
+@@ -812,7 +885,7 @@ static int __init parse_memmap_opt(char 
+ 		saved_max_pfn = e820_end_of_ram();
+ 		remove_all_active_ranges();
+ #endif
+-		end_pfn_map = 0;
++		max_pfn_mapped = 0;
+ 		e820.nr_map = 0;
+ 		userdef = 1;
+ 		return 0;
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -13,7 +13,7 @@
+ #define VGABASE		(__ISA_IO_base + 0xb8000)
+ 
+ static int max_ypos = 25, max_xpos = 80;
+-static int current_ypos = 25, current_xpos = 0; 
++static int current_ypos = 25, current_xpos;
+ 
+ static void early_vga_write(struct console *con, const char *str, unsigned n)
+ {
+@@ -108,12 +108,12 @@ static __init void early_serial_init(cha
+ 
+ 	if (*s) {
+ 		unsigned port;
+-		if (!strncmp(s,"0x",2)) {
++		if (!strncmp(s, "0x", 2)) {
+ 			early_serial_base = simple_strtoul(s, &e, 16);
+ 		} else {
+ 			static int bases[] = { 0x3f8, 0x2f8 };
+ 
+-			if (!strncmp(s,"ttyS",4))
++			if (!strncmp(s, "ttyS", 4))
+ 				s += 4;
+ 			port = simple_strtoul(s, &e, 10);
+ 			if (port > 1 || s == e)
+@@ -223,7 +223,7 @@ static struct console simnow_console = {
+ 
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+-static int early_console_initialized = 0;
++static int early_console_initialized;
+ 
+ void early_printk(const char *fmt, ...)
+ {
+@@ -231,9 +231,9 @@ void early_printk(const char *fmt, ...)
+ 	int n;
+ 	va_list ap;
+ 
+-	va_start(ap,fmt);
+-	n = vscnprintf(buf,512,fmt,ap);
+-	early_console->write(early_console,buf,n);
++	va_start(ap, fmt);
++	n = vscnprintf(buf, 512, fmt, ap);
++	early_console->write(early_console, buf, n);
+ 	va_end(ap);
+ }
+ 
+@@ -259,16 +259,16 @@ static int __init setup_early_printk(cha
+ 		early_console = &early_serial_console;
+ 	} else if (!strncmp(buf, "vga", 3)) {
+ #ifndef CONFIG_XEN
+-	           && boot_params.screen_info.orig_video_isVGA == 1) {
++		&& boot_params.screen_info.orig_video_isVGA == 1) {
+ 		max_xpos = boot_params.screen_info.orig_video_cols;
+ 		max_ypos = boot_params.screen_info.orig_video_lines;
+ 		current_ypos = boot_params.screen_info.orig_y;
+ #endif
+ 		early_console = &early_vga_console;
+- 	} else if (!strncmp(buf, "simnow", 6)) {
+- 		simnow_init(buf + 6);
+- 		early_console = &simnow_console;
+- 		keep_early = 1;
++	} else if (!strncmp(buf, "simnow", 6)) {
++		simnow_init(buf + 6);
++		early_console = &simnow_console;
++		keep_early = 1;
+ #ifdef CONFIG_XEN
+ 	} else if (!strncmp(buf, "xen", 3)) {
+ 		early_console = &xenboot_console;
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,4 @@
+ /*
+- *  linux/arch/i386/entry.S
+  *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  */
+@@ -51,6 +50,7 @@
+ #include <asm/desc.h>
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
++#include <asm/processor-flags.h>
+ #include "irq_vectors.h"
+ #include <xen/interface/xen.h>
+ 
+@@ -69,12 +69,6 @@
+ 
+ #define nr_syscalls ((syscall_table_size)/4)
+ 
+-CF_MASK		= 0x00000001
+-TF_MASK		= 0x00000100
+-IF_MASK		= 0x00000200
+-DF_MASK		= 0x00000400 
+-NT_MASK		= 0x00004000
+-VM_MASK		= 0x00020000
+ /* Pseudo-eflags. */
+ NMI_MASK	= 0x80000000
+ 
+@@ -87,7 +81,7 @@ NMI_MASK	= 0x80000000
+ 
+ .macro TRACE_IRQS_IRET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+-	testl $IF_MASK,PT_EFLAGS(%esp)     # interrupts off?
++	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)     # interrupts off?
+ 	jz 1f
+ 	TRACE_IRQS_ON
+ 1:
+@@ -249,7 +243,7 @@ ret_from_intr:
+ check_userspace:
+ 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+ 	movb PT_CS(%esp), %al
+-	andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
++	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+ 	cmpl $USER_RPL, %eax
+ 	jb resume_kernel		# not returning to v8086 or userspace
+ 
+@@ -258,6 +252,7 @@ ENTRY(resume_userspace)
+  	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
++	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+ 	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done on
+ 					# int/exception return?
+@@ -274,7 +269,7 @@ need_resched:
+ 	movl TI_flags(%ebp), %ecx	# need_resched set ?
+ 	testb $_TIF_NEED_RESCHED, %cl
+ 	jz restore_all
+-	testl $IF_MASK,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
++	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
+ 	jz restore_all
+ 	call preempt_schedule_irq
+ 	jmp need_resched
+@@ -299,10 +294,10 @@ ENTRY(ia32_sysenter_target)
+ 	movl SYSENTER_stack_sp0(%esp),%esp
+ sysenter_past_esp:
+ 	/*
+-	 * No need to follow this irqs on/off section: the syscall
+-	 * disabled irqs and here we enable it straight after entry:
++	 * Interrupts are disabled here, but we can't trace it until
++	 * enough kernel state to call TRACE_IRQS_OFF can be called - but
++	 * we immediately enable interrupts at that point anyway.
+ 	 */
+-	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushl $(__USER_DS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET ss, 0*/
+@@ -310,6 +305,7 @@ sysenter_past_esp:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET esp, 0
+ 	pushfl
++	orl $X86_EFLAGS_IF, (%esp)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl $(__USER_CS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+@@ -323,6 +319,11 @@ sysenter_past_esp:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eip, 0
+ 
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	ENABLE_INTERRUPTS(CLBR_NONE)
++
+ /*
+  * Load the potential sixth argument from user stack.
+  * Careful about security.
+@@ -330,14 +331,12 @@ sysenter_past_esp:
+ 	cmpl $__PAGE_OFFSET-3,%ebp
+ 	jae syscall_fault
+ 1:	movl (%ebp),%ebp
++	movl %ebp,PT_EBP(%esp)
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,syscall_fault
+ .previous
+ 
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+ 	test_tif %ebp
+ 	jnz syscall_trace_entry
+@@ -414,7 +413,7 @@ syscall_exit:
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+-	testl $TF_MASK,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
++	testl $X86_EFLAGS_TF,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
+ 	jz no_singlestep
+ 	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+ no_singlestep:
+@@ -430,7 +429,7 @@ restore_all:
+ 	# See comments in process.c:copy_thread() for details.
+ 	movb PT_OLDSS(%esp), %ah
+ 	movb PT_CS(%esp), %al
+-	andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
++	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+ 	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+ 	CFI_REMEMBER_STATE
+ 	je ldt_ss			# returning to user-space with LDT SS
+@@ -438,7 +437,7 @@ restore_nocheck:
+ #else
+ restore_nocheck:
+ 	movl PT_EFLAGS(%esp), %eax
+-	testl $(VM_MASK|NMI_MASK), %eax
++	testl $(X86_EFLAGS_VM|NMI_MASK), %eax
+ 	CFI_REMEMBER_STATE
+ 	jnz hypervisor_iret
+ 	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
+@@ -456,7 +455,7 @@ restore_nocheck_notrace:
+ irq_return:
+ 	INTERRUPT_RETURN
+ .section .fixup,"ax"
+-iret_exc:
++ENTRY(iret_exc)
+ 	pushl $0			# no error code
+ 	pushl $do_iret_error
+ 	jmp error_code
+@@ -560,7 +559,7 @@ work_resched:
+ work_notifysig:				# deal with pending signals and
+ 					# notify-resume requests
+ #ifdef CONFIG_VM86
+-	testl $VM_MASK, PT_EFLAGS(%esp)
++	testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
+ 	movl %esp, %eax
+ 	jne work_notifysig_v86		# returning to kernel-space or
+ 					# vm86-space
+@@ -617,9 +616,6 @@ END(syscall_exit_work)
+ 
+ 	RING0_INT_FRAME			# can't unwind into user space anyway
+ syscall_fault:
+-	pushl %eax			# save orig_eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+ 	movl $-EFAULT,PT_EAX(%esp)
+ 	jmp resume_userspace
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:32.000000000 +0100
+@@ -338,19 +338,17 @@ badsys:
+ 	/* Do syscall tracing */
+ tracesys:			 
+ 	SAVE_REST
+-	movq $-ENOSYS,RAX(%rsp)
++	movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ 	FIXUP_TOP_OF_STACK %rdi
+ 	movq %rsp,%rdi
+ 	call syscall_trace_enter
+ 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	cmpq $__NR_syscall_max,%rax
+-	movq $-ENOSYS,%rcx
+-	cmova %rcx,%rax
+-	ja  1f
++	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
+ 	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 */
+ 		
+ /* 
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -17,6 +17,7 @@
+ #include <linux/string.h>
+ #include <linux/percpu.h>
+ #include <linux/start_kernel.h>
++#include <linux/io.h>
+ #include <linux/module.h>
+ 
+ #include <asm/processor.h>
+@@ -29,6 +30,7 @@
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
+ #include <asm/e820.h>
++#include <asm/bios_ebda.h>
+ 
+ unsigned long start_pfn;
+ 
+@@ -75,34 +77,75 @@ EXPORT_SYMBOL(machine_to_phys_mapping);
+ unsigned int machine_to_phys_order;
+ EXPORT_SYMBOL(machine_to_phys_order);
+ 
+-#define EBDA_ADDR_POINTER 0x40E
++#define BIOS_LOWMEM_KILOBYTES 0x413
+ 
+-static __init void reserve_ebda(void)
++/*
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
++ */
++static void __init reserve_ebda_region(void)
+ {
+ #ifndef CONFIG_XEN
+-	unsigned ebda_addr, ebda_size;
++	unsigned int lowmem, ebda_addr;
+ 
+-	/*
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E
+-	 */
+-	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
+-	ebda_addr <<= 4;
+-
+-	if (!ebda_addr)
++	/* To determine the position of the EBDA and the */
++	/* end of conventional memory, we need to look at */
++	/* the BIOS data area. In a paravirtual environment */
++	/* that area is absent. We'll just have to assume */
++	/* that the paravirt case can handle memory setup */
++	/* correctly, without our help. */
++	if (paravirt_enabled())
+ 		return;
+ 
+-	ebda_size = *(unsigned short *)__va(ebda_addr);
++	/* end of low (conventional) memory */
++	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++	lowmem <<= 10;
++
++	/* start of EBDA area */
++	ebda_addr = get_bios_ebda();
++
++	/* Fixup: bios puts an EBDA in the top 64K segment */
++	/* of conventional memory, but does not adjust lowmem. */
++	if ((lowmem - ebda_addr) <= 0x10000)
++		lowmem = ebda_addr;
++
++	/* Fixup: bios does not report an EBDA at all. */
++	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++		lowmem = 0x9f000;
++
++	/* Paranoia: should never happen, but... */
++	if ((lowmem == 0) || (lowmem >= 0x100000))
++		lowmem = 0x9f000;
+ 
+-	/* Round EBDA up to pages */
+-	if (ebda_size == 0)
+-		ebda_size = 1;
+-	ebda_size <<= 10;
+-	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+-	if (ebda_size > 64*1024)
+-		ebda_size = 64*1024;
++	/* reserve all memory between lowmem and the 1MB mark */
++	reserve_early(lowmem, 0x100000, "BIOS reserved");
++#endif
++}
+ 
+-	reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
++static void __init reserve_setup_data(void)
++{
++#ifndef CONFIG_XEN
++	struct setup_data *data;
++	unsigned long pa_data;
++	char buf[32];
++
++	if (boot_params.hdr.version < 0x0209)
++		return;
++	pa_data = boot_params.hdr.setup_data;
++	while (pa_data) {
++		data = early_ioremap(pa_data, sizeof(*data));
++		sprintf(buf, "setup data %x", data->type);
++		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
++		pa_data = data->next;
++		early_iounmap(data, sizeof(*data));
++	}
+ #endif
+ }
+ 
+@@ -112,6 +155,19 @@ void __init x86_64_start_kernel(char * r
+ 	unsigned long machine_to_phys_nr_ents;
+ 	int i;
+ 
++	/*
++	 * Build-time sanity checks on the kernel image and module
++	 * area mappings. (these are purely build-time and produce no code)
++	 */
++	BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START);
++	BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE);
++	BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE);
++	BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0);
++	BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0);
++	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
++	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
++				(__START_KERNEL & PGDIR_MASK)));
++
+ 	xen_setup_features();
+ 
+ 	xen_start_info = (struct start_info *)real_mode_data;
+@@ -140,7 +196,7 @@ void __init x86_64_start_kernel(char * r
+ 	/* Cleanup the over mapped high alias */
+ 	cleanup_highmap();
+ 
+-	for (i = 0; i < IDT_ENTRIES; i++) {
++	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
+ #ifdef CONFIG_EARLY_PRINTK
+ 		set_intr_gate(i, &early_idt_handlers[i]);
+ #else
+@@ -163,7 +219,8 @@ void __init x86_64_start_kernel(char * r
+ 	reserve_early(round_up(__pa_symbol(&_end), PAGE_SIZE),
+ 		      start_pfn << PAGE_SHIFT, "Xen provided");
+ 
+-	reserve_ebda();
++	reserve_ebda_region();
++	reserve_setup_data();
+ 
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:32.000000000 +0100
+@@ -69,7 +69,7 @@ ENTRY(startup_32)
+ 	cld			# gcc2 wants the direction flag cleared at all times
+ 
+ 	pushl $0		# fake return address for unwinder
+-	jmp start_kernel
++	jmp i386_start_kernel
+ 
+ #define HYPERCALL_PAGE_OFFSET 0x1000
+ .org HYPERCALL_PAGE_OFFSET
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -88,6 +88,16 @@ int sis_apic_bug = -1;
+  */
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ static int disable_timer_pin_1 __initdata;
+ 
+ /*
+@@ -863,10 +873,7 @@ static int __init find_isa_irq_pin(int i
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+-		    ) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 
+@@ -882,10 +889,7 @@ static int __init find_isa_irq_apic(int 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+-		    ) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 			break;
+@@ -926,7 +930,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
+ 				break;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++		if (!test_bit(lbus, mp_bus_not_pci) &&
+ 		    !mp_irqs[i].mpc_irqtype &&
+ 		    (bus == lbus) &&
+ 		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+@@ -977,6 +981,7 @@ void __init setup_ioapic_dest(void)
+ #endif /* !CONFIG_XEN */
+ #endif
+ 
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /*
+  * EISA Edge/Level control register, ELCR
+  */
+@@ -990,6 +995,13 @@ static int EISA_ELCR(unsigned int irq)
+ 			"Broken MPtable reports ISA irq %d\n", irq);
+ 	return 0;
+ }
++#endif
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx)	(0)
++#define default_ISA_polarity(idx)	(0)
+ 
+ /* EISA interrupts are always polarity zero and can be edge or level
+  * trigger depending on the ELCR value.  If an interrupt is listed as
+@@ -997,13 +1009,7 @@ static int EISA_ELCR(unsigned int irq)
+  * be read in from the ELCR */
+ 
+ #define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
+-#define default_EISA_polarity(idx)	(0)
+-
+-/* ISA interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_ISA_trigger(idx)	(0)
+-#define default_ISA_polarity(idx)	(0)
++#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ /* PCI interrupts are always polarity one level triggered,
+  * when listed as conforming in the MP table. */
+@@ -1015,7 +1021,7 @@ static int EISA_ELCR(unsigned int irq)
+  * when listed as conforming in the MP table. */
+ 
+ #define default_MCA_trigger(idx)	(1)
+-#define default_MCA_polarity(idx)	(0)
++#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ static int MPBIOS_polarity(int idx)
+ {
+@@ -1029,35 +1035,9 @@ static int MPBIOS_polarity(int idx)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent polarity */
+ 		{
+-			switch (mp_bus_id_to_type[bus])
+-			{
+-				case MP_BUS_ISA: /* ISA pin */
+-				{
+-					polarity = default_ISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_EISA: /* EISA pin */
+-				{
+-					polarity = default_EISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_PCI: /* PCI pin */
+-				{
+-					polarity = default_PCI_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_MCA: /* MCA pin */
+-				{
+-					polarity = default_MCA_polarity(idx);
+-					break;
+-				}
+-				default:
+-				{
+-					printk(KERN_WARNING "broken BIOS!!\n");
+-					polarity = 1;
+-					break;
+-				}
+-			}
++			polarity = test_bit(bus, mp_bus_not_pci)?
++				default_ISA_polarity(idx):
++				default_PCI_polarity(idx);
+ 			break;
+ 		}
+ 		case 1: /* high active */
+@@ -1098,11 +1078,15 @@ static int MPBIOS_trigger(int idx)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent */
+ 		{
++			trigger = test_bit(bus, mp_bus_not_pci)?
++					default_ISA_trigger(idx):
++					default_PCI_trigger(idx);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ 			switch (mp_bus_id_to_type[bus])
+ 			{
+ 				case MP_BUS_ISA: /* ISA pin */
+ 				{
+-					trigger = default_ISA_trigger(idx);
++					/* set before the switch */
+ 					break;
+ 				}
+ 				case MP_BUS_EISA: /* EISA pin */
+@@ -1112,7 +1096,7 @@ static int MPBIOS_trigger(int idx)
+ 				}
+ 				case MP_BUS_PCI: /* PCI pin */
+ 				{
+-					trigger = default_PCI_trigger(idx);
++					/* set before the switch */
+ 					break;
+ 				}
+ 				case MP_BUS_MCA: /* MCA pin */
+@@ -1127,6 +1111,7 @@ static int MPBIOS_trigger(int idx)
+ 					break;
+ 				}
+ 			}
++#endif
+ 			break;
+ 		}
+ 		case 1: /* edge */
+@@ -1176,39 +1161,22 @@ static int pin_2_irq(int idx, int apic, 
+ 	if (mp_irqs[idx].mpc_dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+-	switch (mp_bus_id_to_type[bus])
+-	{
+-		case MP_BUS_ISA: /* ISA pin */
+-		case MP_BUS_EISA:
+-		case MP_BUS_MCA:
+-		{
+-			irq = mp_irqs[idx].mpc_srcbusirq;
+-			break;
+-		}
+-		case MP_BUS_PCI: /* PCI pin */
+-		{
+-			/*
+-			 * PCI IRQs are mapped in order
+-			 */
+-			i = irq = 0;
+-			while (i < apic)
+-				irq += nr_ioapic_registers[i++];
+-			irq += pin;
+-
+-			/*
+-			 * For MPS mode, so far only needed by ES7000 platform
+-			 */
+-			if (ioapic_renumber_irq)
+-				irq = ioapic_renumber_irq(apic, irq);
++	if (test_bit(bus, mp_bus_not_pci))
++		irq = mp_irqs[idx].mpc_srcbusirq;
++	else {
++		/*
++		 * PCI IRQs are mapped in order
++		 */
++		i = irq = 0;
++		while (i < apic)
++			irq += nr_ioapic_registers[i++];
++		irq += pin;
+ 
+-			break;
+-		}
+-		default:
+-		{
+-			printk(KERN_ERR "unknown bus type %d.\n",bus); 
+-			irq = 0;
+-			break;
+-		}
++		/*
++		 * For MPS mode, so far only needed by ES7000 platform
++		 */
++		if (ioapic_renumber_irq)
++			irq = ioapic_renumber_irq(apic, irq);
+ 	}
+ 
+ 	/*
+@@ -1314,7 +1282,6 @@ static void __init setup_IO_APIC_irqs(vo
+ {
+ 	struct IO_APIC_route_entry entry;
+ 	int apic, pin, idx, irq, first_notcon = 1, vector;
+-	unsigned long flags;
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+@@ -1380,9 +1347,7 @@ static void __init setup_IO_APIC_irqs(vo
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		__ioapic_write_entry(apic, pin, entry);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		ioapic_write_entry(apic, pin, entry);
+ 	}
+ 	}
+ 
+@@ -1577,8 +1542,8 @@ void /*__init*/ print_local_APIC(void * 
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
++			GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+@@ -1791,7 +1756,7 @@ void disable_IO_APIC(void)
+ 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+ 		entry.vector          = 0;
+ 		entry.dest.physical.physical_dest =
+-					GET_APIC_ID(apic_read(APIC_ID));
++					GET_APIC_ID(read_apic_id());
+ 
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+@@ -2090,8 +2055,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		int tmp = irq;
+-		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
++		if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -2166,7 +2130,7 @@ static void __init setup_nmi(void)
+  * cycles as some i82489DX-based boards have glue logic that keeps the
+  * 8259A interrupt line asserted until INTA.  --macro
+  */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ 	int apic, pin, i;
+ 	struct IO_APIC_route_entry entry0, entry1;
+@@ -2218,8 +2182,6 @@ static inline void unlock_ExtINT_logic(v
+ 	ioapic_write_entry(apic, pin, entry0);
+ }
+ 
+-int timer_uses_ioapic_pin_0;
+-
+ /*
+  * This code may look a bit paranoid, but it's supposed to cooperate with
+  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+@@ -2259,9 +2221,6 @@ static inline void __init check_timer(vo
+ 	pin2  = ioapic_i8259.pin;
+ 	apic2 = ioapic_i8259.apic;
+ 
+-	if (pin1 == 0)
+-		timer_uses_ioapic_pin_0 = 1;
+-
+ 	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ 		vector, apic1, pin1, apic2, pin2);
+ 
+@@ -2555,6 +2514,7 @@ void destroy_irq(unsigned int irq)
+ 	dynamic_irq_cleanup(irq);
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
++	clear_bit(irq_vector[irq], used_vectors);
+ 	irq_vector[irq] = 0;
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ }
+@@ -2871,7 +2831,6 @@ int __init io_apic_get_redir_entries (in
+ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+ 	if (!IO_APIC_IRQ(irq)) {
+ 		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+@@ -2912,9 +2871,7 @@ int io_apic_set_pci_routing (int ioapic,
+ 	if (!ioapic && (irq < 16))
+ 		disable_8259A_irq(irq);
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__ioapic_write_entry(ioapic, pin, entry);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(ioapic, pin, entry);
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -43,13 +43,15 @@
+ #include <asm/smp.h>
+ #include <asm/desc.h>
+ #include <asm/proto.h>
+-#include <asm/mach_apic.h>
+ #include <asm/acpi.h>
+ #include <asm/dma.h>
+ #include <asm/nmi.h>
+ #include <asm/msidef.h>
+ #include <asm/hypertransport.h>
+ 
++#include <mach_ipi.h>
++#include <mach_apic.h>
++
+ struct irq_cfg {
+ #ifndef CONFIG_XEN
+ 	cpumask_t domain;
+@@ -101,6 +103,16 @@ DEFINE_SPINLOCK(vector_lock);
+  */
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
+ /*
+  * Rough estimation of how many shared IRQs there are, can
+  * be changed anytime.
+@@ -181,11 +193,10 @@ static inline void io_apic_modify(unsign
+ 	writel(value, &io_apic->data);
+ }
+ 
+-static int io_apic_level_ack_pending(unsigned int irq)
++static bool io_apic_level_ack_pending(unsigned int irq)
+ {
+ 	struct irq_pin_list *entry;
+ 	unsigned long flags;
+-	int pending = 0;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	entry = irq_2_pin + irq;
+@@ -198,13 +209,17 @@ static int io_apic_level_ack_pending(uns
+ 			break;
+ 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ 		/* Is the remote IRR bit set? */
+-		pending |= (reg >> 14) & 1;
++		if ((reg >> 14) & 1) {
++			spin_unlock_irqrestore(&ioapic_lock, flags);
++			return true;
++		}
+ 		if (!entry->next)
+ 			break;
+ 		entry = irq_2_pin + entry->next;
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	return pending;
++
++	return false;
+ }
+ #endif
+ 
+@@ -762,7 +777,7 @@ static void __clear_irq_vector(int irq)
+ 		per_cpu(vector_irq, cpu)[vector] = -1;
+ 
+ 	cfg->vector = 0;
+-	cfg->domain = CPU_MASK_NONE;
++	cpus_clear(cfg->domain);
+ }
+ 
+ void __setup_vector_irq(int cpu)
+@@ -899,9 +914,8 @@ static void __init setup_IO_APIC_irqs(vo
+ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+-	memset(&entry,0,sizeof(entry));
++	memset(&entry, 0, sizeof(entry));
+ 
+ 	disable_8259A_irq(0);
+ 
+@@ -929,10 +943,7 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+-	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry);
+ 
+ 	enable_8259A_irq(0);
+ }
+@@ -1061,8 +1072,7 @@ void __apicdebuginit print_local_APIC(vo
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+@@ -1260,7 +1270,7 @@ void disable_IO_APIC(void)
+ 		entry.dest_mode       = 0; /* Physical */
+ 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+ 		entry.vector          = 0;
+-		entry.dest          = GET_APIC_ID(apic_read(APIC_ID));
++		entry.dest          = GET_APIC_ID(read_apic_id());
+ 
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+@@ -1353,9 +1363,7 @@ static int ioapic_retrigger_irq(unsigned
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	cpus_clear(mask);
+-	cpu_set(first_cpu(cfg->domain), mask);
+-
++	mask = cpumask_of_cpu(first_cpu(cfg->domain));
+ 	send_IPI_mask(mask, cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+@@ -1519,8 +1527,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		int tmp = irq;
+-		if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
++		if (IO_APIC_IRQ(irq) && !irq_cfg[irq].vector) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -1597,22 +1604,19 @@ static void __init setup_nmi(void)
+  * cycles as some i82489DX-based boards have glue logic that keeps the
+  * 8259A interrupt line asserted until INTA.  --macro
+  */
+-static inline void unlock_ExtINT_logic(void)
++static inline void __init unlock_ExtINT_logic(void)
+ {
+ 	int apic, pin, i;
+ 	struct IO_APIC_route_entry entry0, entry1;
+ 	unsigned char save_control, save_freq_select;
+-	unsigned long flags;
+ 
+ 	pin  = find_isa_irq_pin(8, mp_INT);
+ 	apic = find_isa_irq_apic(8, mp_INT);
+ 	if (pin == -1)
+ 		return;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	entry0 = ioapic_read_entry(apic, pin);
++
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+ 	memset(&entry1, 0, sizeof(entry1));
+@@ -1625,10 +1629,7 @@ static inline void unlock_ExtINT_logic(v
+ 	entry1.trigger = 0;
+ 	entry1.vector = 0;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry1);
+ 
+ 	save_control = CMOS_READ(RTC_CONTROL);
+ 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+@@ -1647,10 +1648,7 @@ static inline void unlock_ExtINT_logic(v
+ 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry0);
+ }
+ 
+ /*
+@@ -2327,7 +2325,6 @@ static struct resource * __init ioapic_s
+ 	res = (void *)mem;
+ 
+ 	if (mem != NULL) {
+-		memset(mem, 0, n);
+ 		mem += sizeof(struct resource) * nr_ioapics;
+ 
+ 		for (i = 0; i < nr_ioapics; i++) {
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,232 @@
++#include <linux/cpumask.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/apic.h>
++#include <asm/proto.h>
++
++#ifdef CONFIG_X86_32
++#ifndef CONFIG_XEN
++#include <mach_apic.h>
++/*
++ * the following functions deal with sending IPIs between CPUs.
++ *
++ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
++ */
++
++static inline int __prepare_ICR(unsigned int shortcut, int vector)
++{
++	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
++
++	switch (vector) {
++	default:
++		icr |= APIC_DM_FIXED | vector;
++		break;
++	case NMI_VECTOR:
++		icr |= APIC_DM_NMI;
++		break;
++	}
++	return icr;
++}
++
++static inline int __prepare_ICR2(unsigned int mask)
++{
++	return SET_APIC_DEST_FIELD(mask);
++}
++#else
++#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);
++}
++#endif
++
++void __send_IPI_shortcut(unsigned int shortcut, int vector)
++{
++#ifndef CONFIG_XEN
++	/*
++	 * Subtle. In the case of the 'never do double writes' workaround
++	 * we have to lock out interrupts to be safe.  As we don't care
++	 * of the value read we use an atomic rmw access to avoid costly
++	 * cli/sti.  Otherwise we use an even cheaper single atomic write
++	 * to the APIC.
++	 */
++	unsigned int cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	apic_wait_icr_idle();
++
++	/*
++	 * No need to touch the target chip field
++	 */
++	cfg = __prepare_ICR(shortcut, vector);
++
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write_around(APIC_ICR, cfg);
++#else
++	int cpu;
++
++	switch (shortcut) {
++	case APIC_DEST_SELF:
++		__send_IPI_one(smp_processor_id(), vector);
++		break;
++	case APIC_DEST_ALLBUT:
++		for_each_online_cpu(cpu)
++			if (cpu != smp_processor_id())
++				__send_IPI_one(cpu, vector);
++		break;
++	default:
++		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
++		       vector);
++		break;
++	}
++#endif
++}
++
++void send_IPI_self(int vector)
++{
++	__send_IPI_shortcut(APIC_DEST_SELF, vector);
++}
++
++#ifndef CONFIG_XEN
++/*
++ * This is used to send an IPI with no shorthand notation (the destination is
++ * specified in bits 56 to 63 of the ICR).
++ */
++static inline void __send_IPI_dest_field(unsigned long mask, int vector)
++{
++	unsigned long cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	if (unlikely(vector == NMI_VECTOR))
++		safe_apic_wait_icr_idle();
++	else
++		apic_wait_icr_idle();
++
++	/*
++	 * prepare target chip field
++	 */
++	cfg = __prepare_ICR2(mask);
++	apic_write_around(APIC_ICR2, cfg);
++
++	/*
++	 * program the ICR
++	 */
++	cfg = __prepare_ICR(0, vector);
++
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write_around(APIC_ICR, cfg);
++}
++#endif
++
++/*
++ * This is only used on smaller machines.
++ */
++void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
++{
++#ifndef CONFIG_XEN
++	unsigned long mask = cpus_addr(cpumask)[0];
++#else
++	cpumask_t mask;
++	unsigned int cpu;
++#endif
++	unsigned long flags;
++
++	local_irq_save(flags);
++#ifndef CONFIG_XEN
++	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++	__send_IPI_dest_field(mask, vector);
++#else
++	cpus_andnot(mask, cpumask, cpu_online_map);
++	WARN_ON(!cpus_empty(mask));
++	for_each_online_cpu(cpu)
++		if (cpu_isset(cpu, cpumask))
++			__send_IPI_one(cpu, vector);
++#endif
++	local_irq_restore(flags);
++}
++
++void send_IPI_mask_sequence(cpumask_t mask, int vector)
++{
++#ifndef CONFIG_XEN
++	unsigned long flags;
++	unsigned int query_cpu;
++
++	/*
++	 * Hack. The clustered APIC addressing mode doesn't allow us to send
++	 * to an arbitrary mask, so I do a unicasts to each CPU instead. This
++	 * should be modified to do 1 message per cluster ID - mbligh
++	 */
++
++	local_irq_save(flags);
++	for_each_possible_cpu(query_cpu) {
++		if (cpu_isset(query_cpu, mask)) {
++			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
++					      vector);
++		}
++	}
++	local_irq_restore(flags);
++#else
++	send_IPI_mask_bitmask(mask, vector);
++#endif
++}
++
++/* must come after the send_IPI functions above for inlining */
++#include <mach_ipi.h>
++
++#ifndef CONFIG_XEN
++static int convert_apicid_to_cpu(int apic_id)
++{
++	int i;
++
++	for_each_possible_cpu(i) {
++		if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
++			return i;
++	}
++	return -1;
++}
++
++int safe_smp_processor_id(void)
++{
++	int apicid, cpuid;
++
++	if (!boot_cpu_has(X86_FEATURE_APIC))
++		return 0;
++
++	apicid = hard_smp_processor_id();
++	if (apicid == BAD_APICID)
++		return 0;
++
++	cpuid = convert_apicid_to_cpu(apicid);
++
++	return cpuid >= 0 ? cpuid : 0;
++}
++#endif
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -79,7 +79,7 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 
+ 	if (unlikely((unsigned)irq >= NR_IRQS)) {
+ 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+-					__FUNCTION__, irq);
++					__func__, irq);
+ 		BUG();
+ 	}
+ 
+@@ -134,7 +134,7 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 			: "=a" (arg1), "=d" (arg2), "=b" (bx)
+ 			:  "0" (irq),   "1" (desc),  "2" (isp),
+ 			   "D" (desc->handle_irq)
+-			: "memory", "cc"
++			: "memory", "cc", "ecx"
+ 		);
+ 	} else
+ #endif
+@@ -190,8 +190,6 @@ void irq_ctx_exit(int cpu)
+ 	hardirq_ctx[cpu] = NULL;
+ }
+ 
+-extern asmlinkage void __do_softirq(void);
+-
+ asmlinkage void do_softirq(void)
+ {
+ 	unsigned long flags;
+--- head-2010-01-18.orig/arch/x86/kernel/machine_kexec_64.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/machine_kexec_64.c	2009-11-06 10:51:32.000000000 +0100
+@@ -112,8 +112,6 @@ int __init machine_kexec_setup_resources
+ 	return 0;
+ }
+ 
+-void machine_kexec_register_resources(struct resource *res) { ; }
+-
+ #else /* CONFIG_XEN */
+ 
+ #define x__pmd(x) __pmd(x)
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -162,7 +162,7 @@ static int request_microcode(void)
+ 		c->x86, c->x86_model, c->x86_mask);
+ 	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+ 	if (error) {
+-		pr_debug("ucode data file %s load failed\n", name);
++		pr_debug("microcode: ucode data file %s load failed\n", name);
+ 		return error;
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mmconf-fam10h_64.c	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mmconf-fam10h_64.c	2009-11-06 10:51:32.000000000 +0100
+@@ -218,6 +218,16 @@ void __cpuinit fam10h_check_enable_mmcfg
+ 	val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
+ 	       FAM10H_MMIO_CONF_ENABLE;
+ 	wrmsrl(address, val);
++
++#ifdef CONFIG_XEN
++	{
++		u64 val2;
++
++		rdmsrl(address, val2);
++		if (val2 != val)
++			pci_probe &= ~PCI_CHECK_ENABLE_AMD_MMCONF;
++	}
++#endif
+ }
+ 
+ static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,1101 @@
++/*
++ *	Intel Multiprocessor Specification 1.1 and 1.4
++ *	compliant MP-table parsing routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
++ */
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/bitops.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/pgalloc.h>
++#include <asm/io_apic.h>
++#include <asm/proto.h>
++#include <asm/acpi.h>
++#include <asm/bios_ebda.h>
++
++#include <mach_apic.h>
++#ifdef CONFIG_X86_32
++#include <mach_apicdef.h>
++#include <mach_mpparse.h>
++#endif
++
++/* Have we found an MP table */
++int smp_found_config;
++
++/*
++ * Various Linux-internal data structures created from the
++ * MP-table.
++ */
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 };
++
++static int mp_current_pci_id;
++
++int pic_mode;
++
++/*
++ * Intel MP BIOS table parsing routines:
++ */
++
++/*
++ * Checksum an MP configuration block.
++ */
++
++static int __init mpf_checksum(unsigned char *mp, int len)
++{
++	int sum = 0;
++
++	while (len--)
++		sum += *mp++;
++
++	return sum & 0xFF;
++}
++
++#ifdef CONFIG_X86_NUMAQ
++/*
++ * Have to match translation table entries to main table entries by counter
++ * hence the mpc_record variable .... can't see a less disgusting way of
++ * doing this ....
++ */
++
++static int mpc_record;
++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
++    __cpuinitdata;
++#endif
++
++static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
++{
++#ifndef CONFIG_XEN
++	int apicid;
++	char *bootup_cpu = "";
++
++	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
++		disabled_cpus++;
++		return;
++	}
++#ifdef CONFIG_X86_NUMAQ
++	apicid = mpc_apic_id(m, translation_table[mpc_record]);
++#else
++	apicid = m->mpc_apicid;
++#endif
++	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++		bootup_cpu = " (Bootup-CPU)";
++		boot_cpu_physical_apicid = m->mpc_apicid;
++	}
++
++	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
++	generic_processor_info(apicid, m->mpc_apicver);
++#else /* CONFIG_XEN */
++	num_processors++;
++#endif
++}
++
++static void __init MP_bus_info(struct mpc_config_bus *m)
++{
++	char str[7];
++
++	memcpy(str, m->mpc_bustype, 6);
++	str[6] = 0;
++
++#ifdef CONFIG_X86_NUMAQ
++	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
++#else
++	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
++#endif
++
++#if MAX_MP_BUSSES < 256
++	if (m->mpc_busid >= MAX_MP_BUSSES) {
++		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
++		       " is too large, max. supported is %d\n",
++		       m->mpc_busid, str, MAX_MP_BUSSES - 1);
++		return;
++	}
++#endif
++
++	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
++		 set_bit(m->mpc_busid, mp_bus_not_pci);
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++#endif
++	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
++#ifdef CONFIG_X86_NUMAQ
++		mpc_oem_pci_bus(m, translation_table[mpc_record]);
++#endif
++		clear_bit(m->mpc_busid, mp_bus_not_pci);
++		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
++		mp_current_pci_id++;
++#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++#endif
++	} else
++		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int bad_ioapic(unsigned long address)
++{
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++		       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++	}
++	if (!address) {
++		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++		       " found in table, skipping!\n");
++		return 1;
++	}
++	return 0;
++}
++
++static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
++{
++	if (!(m->mpc_flags & MPC_APIC_USABLE))
++		return;
++
++	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
++	       m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++
++	if (bad_ioapic(m->mpc_apicaddr))
++		return;
++
++	mp_ioapics[nr_ioapics] = *m;
++	nr_ioapics++;
++}
++
++static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
++{
++	mp_irqs[mp_irq_entries] = *m;
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
++		m->mpc_irqtype, m->mpc_irqflag & 3,
++		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
++		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!!\n");
++}
++
++#endif
++
++static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
++{
++	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++		m->mpc_irqtype, m->mpc_irqflag & 3,
++		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
++		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++}
++
++#ifdef CONFIG_X86_NUMAQ
++static void __init MP_translation_info(struct mpc_config_translation *m)
++{
++	printk(KERN_INFO
++	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
++	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
++	       m->trans_local);
++
++	if (mpc_record >= MAX_MPC_ENTRY)
++		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
++	else
++		translation_table[mpc_record] = m;	/* stash this for later */
++	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
++		node_set_online(m->trans_quad);
++}
++
++/*
++ * Read/parse the MPC oem tables
++ */
++
++static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
++				    unsigned short oemsize)
++{
++	int count = sizeof(*oemtable);	/* the header size */
++	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
++
++	mpc_record = 0;
++	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
++	       oemtable);
++	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
++		printk(KERN_WARNING
++		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
++		       oemtable->oem_signature[0], oemtable->oem_signature[1],
++		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
++		return;
++	}
++	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
++		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
++		return;
++	}
++	while (count < oemtable->oem_length) {
++		switch (*oemptr) {
++		case MP_TRANSLATION:
++			{
++				struct mpc_config_translation *m =
++				    (struct mpc_config_translation *)oemptr;
++				MP_translation_info(m);
++				oemptr += sizeof(*m);
++				count += sizeof(*m);
++				++mpc_record;
++				break;
++			}
++		default:
++			{
++				printk(KERN_WARNING
++				       "Unrecognised OEM table entry type! - %d\n",
++				       (int)*oemptr);
++				return;
++			}
++		}
++	}
++}
++
++static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
++				 char *productid)
++{
++	if (strncmp(oem, "IBM NUMA", 8))
++		printk("Warning!  May not be a NUMA-Q system!\n");
++	if (mpc->mpc_oemptr)
++		smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
++				 mpc->mpc_oemsize);
++}
++#endif /* CONFIG_X86_NUMAQ */
++
++/*
++ * Read/parse the MPC
++ */
++
++static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++{
++	char str[16];
++	char oem[10];
++	int count = sizeof(*mpc);
++	unsigned char *mpt = ((unsigned char *)mpc) + count;
++
++	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
++		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
++		       mpc->mpc_signature[0], mpc->mpc_signature[1],
++		       mpc->mpc_signature[2], mpc->mpc_signature[3]);
++		return 0;
++	}
++	if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
++		printk(KERN_ERR "MPTABLE: checksum error!\n");
++		return 0;
++	}
++	if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
++		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
++		       mpc->mpc_spec);
++		return 0;
++	}
++	if (!mpc->mpc_lapic) {
++		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
++		return 0;
++	}
++	memcpy(oem, mpc->mpc_oem, 8);
++	oem[8] = 0;
++	printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem);
++
++	memcpy(str, mpc->mpc_productid, 12);
++	str[12] = 0;
++	printk("Product ID: %s ", str);
++
++#ifdef CONFIG_X86_32
++	mps_oem_check(mpc, oem, str);
++#endif
++	printk(KERN_INFO "MPTABLE: Product ID: %s ", str);
++
++	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
++
++	/* save the local APIC address, it might be non-default */
++	if (!acpi_lapic)
++		mp_lapic_addr = mpc->mpc_lapic;
++
++	if (early)
++		return 1;
++
++	/*
++	 *      Now process the configuration blocks.
++	 */
++#ifdef CONFIG_X86_NUMAQ
++	mpc_record = 0;
++#endif
++	while (count < mpc->mpc_length) {
++		switch (*mpt) {
++		case MP_PROCESSOR:
++			{
++				struct mpc_config_processor *m =
++				    (struct mpc_config_processor *)mpt;
++				/* ACPI may have already provided this data */
++				if (!acpi_lapic)
++					MP_processor_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_BUS:
++			{
++				struct mpc_config_bus *m =
++				    (struct mpc_config_bus *)mpt;
++				MP_bus_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_IOAPIC:
++			{
++#ifdef CONFIG_X86_IO_APIC
++				struct mpc_config_ioapic *m =
++				    (struct mpc_config_ioapic *)mpt;
++				MP_ioapic_info(m);
++#endif
++				mpt += sizeof(struct mpc_config_ioapic);
++				count += sizeof(struct mpc_config_ioapic);
++				break;
++			}
++		case MP_INTSRC:
++			{
++#ifdef CONFIG_X86_IO_APIC
++				struct mpc_config_intsrc *m =
++				    (struct mpc_config_intsrc *)mpt;
++
++				MP_intsrc_info(m);
++#endif
++				mpt += sizeof(struct mpc_config_intsrc);
++				count += sizeof(struct mpc_config_intsrc);
++				break;
++			}
++		case MP_LINTSRC:
++			{
++				struct mpc_config_lintsrc *m =
++				    (struct mpc_config_lintsrc *)mpt;
++				MP_lintsrc_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		default:
++			/* wrong mptable */
++			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
++			printk(KERN_ERR "type %x\n", *mpt);
++			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
++					1, mpc, mpc->mpc_length, 1);
++			count = mpc->mpc_length;
++			break;
++		}
++#ifdef CONFIG_X86_NUMAQ
++		++mpc_record;
++#endif
++	}
++	setup_apic_routing();
++	if (!num_processors)
++		printk(KERN_ERR "MPTABLE: no processors registered!\n");
++	return num_processors;
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++static int __init ELCR_trigger(unsigned int irq)
++{
++	unsigned int port;
++
++	port = 0x4d0 + (irq >> 3);
++	return (inb(port) >> (irq & 7)) & 1;
++}
++
++static void __init construct_default_ioirq_mptable(int mpc_default_type)
++{
++	struct mpc_config_intsrc intsrc;
++	int i;
++	int ELCR_fallback = 0;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;	/* conforming */
++	intsrc.mpc_srcbus = 0;
++	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++
++	intsrc.mpc_irqtype = mp_INT;
++
++	/*
++	 *  If true, we have an ISA/PCI system with no IRQ entries
++	 *  in the MP table. To prevent the PCI interrupts from being set up
++	 *  incorrectly, we try to use the ELCR. The sanity check to see if
++	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
++	 *  never be level sensitive, so we simply see if the ELCR agrees.
++	 *  If it does, we assume it's valid.
++	 */
++	if (mpc_default_type == 5) {
++		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
++		       "falling back to ELCR\n");
++
++		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
++		    ELCR_trigger(13))
++			printk(KERN_ERR "ELCR contains invalid data... "
++			       "not using ELCR\n");
++		else {
++			printk(KERN_INFO
++			       "Using ELCR to identify PCI interrupts\n");
++			ELCR_fallback = 1;
++		}
++	}
++
++	for (i = 0; i < 16; i++) {
++		switch (mpc_default_type) {
++		case 2:
++			if (i == 0 || i == 13)
++				continue;	/* IRQ0 & IRQ13 not connected */
++			/* fall through */
++		default:
++			if (i == 2)
++				continue;	/* IRQ2 is never connected */
++		}
++
++		if (ELCR_fallback) {
++			/*
++			 *  If the ELCR indicates a level-sensitive interrupt, we
++			 *  copy that information over to the MP table in the
++			 *  irqflag field (level sensitive, active high polarity).
++			 */
++			if (ELCR_trigger(i))
++				intsrc.mpc_irqflag = 13;
++			else
++				intsrc.mpc_irqflag = 0;
++		}
++
++		intsrc.mpc_srcbusirq = i;
++		intsrc.mpc_dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
++		MP_intsrc_info(&intsrc);
++	}
++
++	intsrc.mpc_irqtype = mp_ExtINT;
++	intsrc.mpc_srcbusirq = 0;
++	intsrc.mpc_dstirq = 0;	/* 8259A to INTIN0 */
++	MP_intsrc_info(&intsrc);
++}
++
++#endif
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++	struct mpc_config_processor processor;
++	struct mpc_config_bus bus;
++#ifdef CONFIG_X86_IO_APIC
++	struct mpc_config_ioapic ioapic;
++#endif
++	struct mpc_config_lintsrc lintsrc;
++	int linttypes[2] = { mp_ExtINT, mp_NMI };
++	int i;
++
++	/*
++	 * local APIC has default address
++	 */
++	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++	/*
++	 * 2 CPUs, numbered 0 & 1.
++	 */
++	processor.mpc_type = MP_PROCESSOR;
++	/* Either an integrated APIC or a discrete 82489DX. */
++	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_cpuflag = CPU_ENABLED;
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++	for (i = 0; i < 2; i++) {
++		processor.mpc_apicid = i;
++		MP_processor_info(&processor);
++	}
++
++	bus.mpc_type = MP_BUS;
++	bus.mpc_busid = 0;
++	switch (mpc_default_type) {
++	default:
++		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
++		       mpc_default_type);
++		/* fall through */
++	case 1:
++	case 5:
++		memcpy(bus.mpc_bustype, "ISA   ", 6);
++		break;
++	case 2:
++	case 6:
++	case 3:
++		memcpy(bus.mpc_bustype, "EISA  ", 6);
++		break;
++	case 4:
++	case 7:
++		memcpy(bus.mpc_bustype, "MCA   ", 6);
++	}
++	MP_bus_info(&bus);
++	if (mpc_default_type > 4) {
++		bus.mpc_busid = 1;
++		memcpy(bus.mpc_bustype, "PCI   ", 6);
++		MP_bus_info(&bus);
++	}
++
++#ifdef CONFIG_X86_IO_APIC
++	ioapic.mpc_type = MP_IOAPIC;
++	ioapic.mpc_apicid = 2;
++	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.mpc_flags = MPC_APIC_USABLE;
++	ioapic.mpc_apicaddr = 0xFEC00000;
++	MP_ioapic_info(&ioapic);
++
++	/*
++	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
++	 */
++	construct_default_ioirq_mptable(mpc_default_type);
++#endif
++	lintsrc.mpc_type = MP_LINTSRC;
++	lintsrc.mpc_irqflag = 0;	/* conforming */
++	lintsrc.mpc_srcbusid = 0;
++	lintsrc.mpc_srcbusirq = 0;
++	lintsrc.mpc_destapic = MP_APIC_ALL;
++	for (i = 0; i < 2; i++) {
++		lintsrc.mpc_irqtype = linttypes[i];
++		lintsrc.mpc_destapiclint = i;
++		MP_lintsrc_info(&lintsrc);
++	}
++}
++
++static struct intel_mp_floating *mpf_found;
++
++/*
++ * Scan the memory blocks for an SMP configuration block.
++ */
++static void __init __get_smp_config(unsigned early)
++{
++	struct intel_mp_floating *mpf = mpf_found;
++
++	if (acpi_lapic && early)
++		return;
++	/*
++	 * ACPI supports both logical (e.g. Hyper-Threading) and physical
++	 * processors, where MPS only supports physical.
++	 */
++	if (acpi_lapic && acpi_ioapic) {
++		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
++		       "information\n");
++		return;
++	} else if (acpi_lapic)
++		printk(KERN_INFO "Using ACPI for processor (LAPIC) "
++		       "configuration information\n");
++
++	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
++	       mpf->mpf_specification);
++#ifdef CONFIG_X86_32
++	if (mpf->mpf_feature2 & (1 << 7)) {
++		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
++		pic_mode = 1;
++	} else {
++		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
++		pic_mode = 0;
++	}
++#endif
++	/*
++	 * Now see if we need to read further.
++	 */
++	if (mpf->mpf_feature1 != 0) {
++		if (early) {
++			/*
++			 * local APIC has default address
++			 */
++			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++			return;
++		}
++
++		printk(KERN_INFO "Default MP configuration #%d\n",
++		       mpf->mpf_feature1);
++		construct_default_ISA_mptable(mpf->mpf_feature1);
++
++	} else if (mpf->mpf_physptr) {
++
++		/*
++		 * Read the physical hardware table.  Anything here will
++		 * override the defaults.
++		 */
++		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr), early)) {
++			smp_found_config = 0;
++			printk(KERN_ERR
++			       "BIOS bug, MP table errors detected!...\n");
++			printk(KERN_ERR "... disabling SMP support. "
++			       "(tell your hw vendor)\n");
++			return;
++		}
++
++		if (early)
++			return;
++#ifdef CONFIG_X86_IO_APIC
++		/*
++		 * If there are no explicit MP IRQ entries, then we are
++		 * broken.  We set up most of the low 16 IO-APIC pins to
++		 * ISA defaults and hope it will work.
++		 */
++		if (!mp_irq_entries) {
++			struct mpc_config_bus bus;
++
++			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
++			       "using default mptable. "
++			       "(tell your hw vendor)\n");
++
++			bus.mpc_type = MP_BUS;
++			bus.mpc_busid = 0;
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			MP_bus_info(&bus);
++
++			construct_default_ioirq_mptable(0);
++		}
++#endif
++	} else
++		BUG();
++
++	if (!early)
++		printk(KERN_INFO "Processors: %d\n", num_processors);
++	/*
++	 * Only use the first configuration found.
++	 */
++}
++
++void __init early_get_smp_config(void)
++{
++	__get_smp_config(1);
++}
++
++void __init get_smp_config(void)
++{
++	__get_smp_config(0);
++}
++
++static int __init smp_scan_config(unsigned long base, unsigned long length,
++				  unsigned reserve)
++{
++	unsigned int *bp = isa_bus_to_virt(base);
++	struct intel_mp_floating *mpf;
++
++	Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
++	BUILD_BUG_ON(sizeof(*mpf) != 16);
++
++	while (length > 0) {
++		mpf = (struct intel_mp_floating *)bp;
++		if ((*bp == SMP_MAGIC_IDENT) &&
++		    (mpf->mpf_length == 1) &&
++		    !mpf_checksum((unsigned char *)bp, 16) &&
++		    ((mpf->mpf_specification == 1)
++		     || (mpf->mpf_specification == 4))) {
++
++			smp_found_config = 1;
++			mpf_found = mpf;
++#ifdef CONFIG_X86_32
++#ifndef CONFIG_XEN
++			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++			       mpf, virt_to_phys(mpf));
++			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
++					BOOTMEM_DEFAULT);
++			if (mpf->mpf_physptr) {
++				/*
++				 * We cannot access to MPC table to compute
++				 * table size yet, as only few megabytes from
++				 * the bottom is mapped now.
++				 * PC-9800's MPC table places on the very last
++				 * of physical memory; so that simply reserving
++				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
++				 * in reserve_bootmem.
++				 */
++				unsigned long size = PAGE_SIZE;
++				unsigned long end = max_low_pfn * PAGE_SIZE;
++				if (mpf->mpf_physptr + size > end)
++					size = end - mpf->mpf_physptr;
++				reserve_bootmem(mpf->mpf_physptr, size,
++						BOOTMEM_DEFAULT);
++			}
++#else
++			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++				mpf, ((void *)bp - isa_bus_to_virt(base)) + base);
++#endif
++#elif !defined(CONFIG_XEN)
++			if (!reserve)
++				return 1;
++
++			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
++			if (mpf->mpf_physptr)
++				reserve_bootmem_generic(mpf->mpf_physptr,
++							PAGE_SIZE);
++#endif
++		return 1;
++		}
++		bp += 4;
++		length -= 16;
++	}
++	return 0;
++}
++
++static void __init __find_smp_config(unsigned reserve)
++{
++#ifndef CONFIG_XEN
++	unsigned int address;
++#endif
++
++	/*
++	 * FIXME: Linux assumes you have 640K of base ram..
++	 * this continues the error...
++	 *
++	 * 1) Scan the bottom 1K for a signature
++	 * 2) Scan the top 1K of base RAM
++	 * 3) Scan the 64K of bios
++	 */
++	if (smp_scan_config(0x0, 0x400, reserve) ||
++	    smp_scan_config(639 * 0x400, 0x400, reserve) ||
++	    smp_scan_config(0xF0000, 0x10000, reserve))
++		return;
++	/*
++	 * If it is an SMP machine we should know now, unless the
++	 * configuration is in an EISA/MCA bus machine with an
++	 * extended bios data area.
++	 *
++	 * there is a real-mode segmented pointer pointing to the
++	 * 4K EBDA area at 0x40E, calculate and scan it here.
++	 *
++	 * NOTE! There are Linux loaders that will corrupt the EBDA
++	 * area, and as such this kind of SMP config may be less
++	 * trustworthy, simply because the SMP table may have been
++	 * stomped on during early boot. These loaders are buggy and
++	 * should be fixed.
++	 *
++	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
++	 */
++
++#ifndef CONFIG_XEN
++	address = get_bios_ebda();
++	if (address)
++		smp_scan_config(address, 0x400, reserve);
++#endif
++}
++
++void __init early_find_smp_config(void)
++{
++	__find_smp_config(0);
++}
++
++void __init find_smp_config(void)
++{
++	__find_smp_config(1);
++}
++
++/* --------------------------------------------------------------------------
++                            ACPI-based MP Configuration
++   -------------------------------------------------------------------------- */
++
++/*
++ * Keep this outside and initialized to 0, for !CONFIG_ACPI builds:
++ */
++int es7000_plat;
++
++#ifdef CONFIG_ACPI
++
++#ifdef	CONFIG_X86_IO_APIC
++
++#define MP_ISA_BUS		0
++
++extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++
++static int mp_find_ioapic(int gsi)
++{
++	int i = 0;
++
++	/* Find the IOAPIC that manages this GSI. */
++	for (i = 0; i < nr_ioapics; i++) {
++		if ((gsi >= mp_ioapic_routing[i].gsi_base)
++		    && (gsi <= mp_ioapic_routing[i].gsi_end))
++			return i;
++	}
++
++	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++	return -1;
++}
++
++static u8 __init uniq_ioapic_id(u8 id)
++{
++#ifdef CONFIG_X86_32
++	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
++	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		return io_apic_get_unique_id(nr_ioapics, id);
++	else
++		return id;
++#else
++	int i;
++	DECLARE_BITMAP(used, 256);
++	bitmap_zero(used, 256);
++	for (i = 0; i < nr_ioapics; i++) {
++		struct mpc_config_ioapic *ia = &mp_ioapics[i];
++		__set_bit(ia->mpc_apicid, used);
++	}
++	if (!test_bit(id, used))
++		return id;
++	return find_first_zero_bit(used, 256);
++#endif
++}
++
++void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
++{
++	int idx = 0;
++
++	if (bad_ioapic(address))
++		return;
++
++	idx = nr_ioapics;
++
++	mp_ioapics[idx].mpc_type = MP_IOAPIC;
++	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
++	mp_ioapics[idx].mpc_apicaddr = address;
++
++#ifndef CONFIG_XEN
++	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++#endif
++	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
++#ifdef CONFIG_X86_32
++	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++#else
++	mp_ioapics[idx].mpc_apicver = 0;
++#endif
++	/*
++	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
++	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
++	 */
++	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
++	mp_ioapic_routing[idx].gsi_base = gsi_base;
++	mp_ioapic_routing[idx].gsi_end = gsi_base +
++	    io_apic_get_redir_entries(idx);
++
++	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
++	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++	       mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
++
++	nr_ioapics++;
++}
++
++void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
++{
++	struct mpc_config_intsrc intsrc;
++	int ioapic = -1;
++	int pin = -1;
++
++	/*
++	 * Convert 'gsi' to 'ioapic.pin'.
++	 */
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0)
++		return;
++	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++	/*
++	 * TBD: This check is for faulty timer entries, where the override
++	 *      erroneously sets the trigger to level, resulting in a HUGE
++	 *      increase of timer interrupts!
++	 */
++	if ((bus_irq == 0) && (trigger == 3))
++		trigger = 1;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqtype = mp_INT;
++	intsrc.mpc_irqflag = (trigger << 2) | polarity;
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_srcbusirq = bus_irq;	/* IRQ */
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	/* APIC ID */
++	intsrc.mpc_dstirq = pin;	/* INTIN# */
++
++	MP_intsrc_info(&intsrc);
++}
++
++void __init mp_config_acpi_legacy_irqs(void)
++{
++	struct mpc_config_intsrc intsrc;
++	int i = 0;
++	int ioapic = -1;
++
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++	/*
++	 * Fabricate the legacy ISA bus (bus #31).
++	 */
++	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++#endif
++	set_bit(MP_ISA_BUS, mp_bus_not_pci);
++	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++
++	/*
++	 * Older generations of ES7000 have no legacy identity mappings
++	 */
++	if (es7000_plat == 1)
++		return;
++
++	/*
++	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
++	 */
++	ioapic = mp_find_ioapic(0);
++	if (ioapic < 0)
++		return;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;	/* Conforming */
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++#ifdef CONFIG_X86_IO_APIC
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
++#endif
++	/*
++	 * Use the default configuration for the IRQs 0-15.  Unless
++	 * overridden by (MADT) interrupt source override entries.
++	 */
++	for (i = 0; i < 16; i++) {
++		int idx;
++
++		for (idx = 0; idx < mp_irq_entries; idx++) {
++			struct mpc_config_intsrc *irq = mp_irqs + idx;
++
++			/* Do we already have a mapping for this ISA IRQ? */
++			if (irq->mpc_srcbus == MP_ISA_BUS
++			    && irq->mpc_srcbusirq == i)
++				break;
++
++			/* Do we already have a mapping for this IOAPIC pin */
++			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
++			    (irq->mpc_dstirq == i))
++				break;
++		}
++
++		if (idx != mp_irq_entries) {
++			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
++			continue;	/* IRQ already used */
++		}
++
++		intsrc.mpc_irqtype = mp_INT;
++		intsrc.mpc_srcbusirq = i;	/* Identity mapped */
++		intsrc.mpc_dstirq = i;
++
++		MP_intsrc_info(&intsrc);
++	}
++}
++
++int mp_register_gsi(u32 gsi, int triggering, int polarity)
++{
++	int ioapic;
++	int ioapic_pin;
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++#define MAX_GSI_NUM	4096
++#define IRQ_COMPRESSION_START	64
++
++	static int pci_irq = IRQ_COMPRESSION_START;
++	/*
++	 * Mapping between Global System Interrupts, which
++	 * represent all possible interrupts, and IRQs
++	 * assigned to actual devices.
++	 */
++	static int gsi_to_irq[MAX_GSI_NUM];
++#else
++
++	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
++		return gsi;
++#endif
++
++	/* Don't set up the ACPI SCI because it's already set up */
++	if (acpi_gbl_FADT.sci_interrupt == gsi)
++		return gsi;
++
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0) {
++		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
++		return gsi;
++	}
++
++	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++#ifndef CONFIG_X86_32
++	if (ioapic_renumber_irq)
++		gsi = ioapic_renumber_irq(ioapic, gsi);
++#endif
++
++	/*
++	 * Avoid pin reprogramming.  PRTs typically include entries
++	 * with redundant pin->gsi mappings (but unique PCI devices);
++	 * we only program the IOAPIC on the first.
++	 */
++	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
++		printk(KERN_ERR "Invalid reference to IOAPIC pin "
++		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
++		       ioapic_pin);
++		return gsi;
++	}
++	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
++		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
++			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
++#else
++		return gsi;
++#endif
++	}
++
++	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++	/*
++	 * For GSI >= 64, use IRQ compression
++	 */
++	if ((gsi >= IRQ_COMPRESSION_START)
++	    && (triggering == ACPI_LEVEL_SENSITIVE)) {
++		/*
++		 * For PCI devices assign IRQs in order, avoiding gaps
++		 * due to unused I/O APIC pins.
++		 */
++		int irq = gsi;
++		if (gsi < MAX_GSI_NUM) {
++			/*
++			 * Retain the VIA chipset work-around (gsi > 15), but
++			 * avoid a problem where the 8254 timer (IRQ0) is setup
++			 * via an override (so it's not on pin 0 of the ioapic),
++			 * and at the same time, the pin 0 interrupt is a PCI
++			 * type.  The gsi > 15 test could cause these two pins
++			 * to be shared as IRQ0, and they are not shareable.
++			 * So test for this condition, and if necessary, avoid
++			 * the pin collision.
++			 */
++			gsi = pci_irq++;
++			/*
++			 * Don't assign IRQ used by ACPI SCI
++			 */
++			if (gsi == acpi_gbl_FADT.sci_interrupt)
++				gsi = pci_irq++;
++			gsi_to_irq[irq] = gsi;
++		} else {
++			printk(KERN_ERR "GSI %u is too high\n", gsi);
++			return gsi;
++		}
++	}
++#endif
++	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
++				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
++				polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
++	return gsi;
++}
++
++#endif /* CONFIG_X86_IO_APIC */
++#endif /* CONFIG_ACPI */
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1161 +0,0 @@
+-/*
+- *	Intel Multiprocessor Specification 1.1 and 1.4
+- *	compliant MP-table parsing routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *		Alan Cox	:	Added EBDA scanning
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Maciej W. Rozycki:	Bits for default MP configurations
+- *		Paul Diefenbaugh:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/acpi.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/bitops.h>
+-
+-#include <asm/smp.h>
+-#include <asm/acpi.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/io_apic.h>
+-
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
+-#include <mach_mpparse.h>
+-#include <bios_ebda.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-unsigned int __cpuinitdata maxcpus = NR_CPUS;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-int apic_version [MAX_APICS];
+-int mp_bus_id_to_type [MAX_MP_BUSSES];
+-int mp_bus_id_to_node [MAX_MP_BUSSES];
+-int mp_bus_id_to_local [MAX_MP_BUSSES];
+-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-static int mp_current_pci_id;
+-
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-
+-int pic_mode;
+-unsigned long mp_lapic_addr;
+-
+-unsigned int def_to_bigsmp = 0;
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
+-
+-u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+-	int sum = 0;
+-
+-	while (len--)
+-		sum += *mp++;
+-
+-	return sum & 0xFF;
+-}
+-
+-/*
+- * Have to match translation table entries to main table entries by counter
+- * hence the mpc_record variable .... can't see a less disgusting way of
+- * doing this ....
+- */
+-
+-static int mpc_record; 
+-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
+-
+-#ifndef CONFIG_XEN
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+-{
+- 	int ver, apicid;
+-	physid_mask_t phys_cpu;
+- 	
+-	if (!(m->mpc_cpuflag & CPU_ENABLED))
+-		return;
+-
+-	apicid = mpc_apic_id(m, translation_table[mpc_record]);
+-
+-	if (m->mpc_featureflag&(1<<0))
+-		Dprintk("    Floating point unit present.\n");
+-	if (m->mpc_featureflag&(1<<7))
+-		Dprintk("    Machine Exception supported.\n");
+-	if (m->mpc_featureflag&(1<<8))
+-		Dprintk("    64 bit compare & exchange supported.\n");
+-	if (m->mpc_featureflag&(1<<9))
+-		Dprintk("    Internal APIC present.\n");
+-	if (m->mpc_featureflag&(1<<11))
+-		Dprintk("    SEP present.\n");
+-	if (m->mpc_featureflag&(1<<12))
+-		Dprintk("    MTRR  present.\n");
+-	if (m->mpc_featureflag&(1<<13))
+-		Dprintk("    PGE  present.\n");
+-	if (m->mpc_featureflag&(1<<14))
+-		Dprintk("    MCA  present.\n");
+-	if (m->mpc_featureflag&(1<<15))
+-		Dprintk("    CMOV  present.\n");
+-	if (m->mpc_featureflag&(1<<16))
+-		Dprintk("    PAT  present.\n");
+-	if (m->mpc_featureflag&(1<<17))
+-		Dprintk("    PSE  present.\n");
+-	if (m->mpc_featureflag&(1<<18))
+-		Dprintk("    PSN  present.\n");
+-	if (m->mpc_featureflag&(1<<19))
+-		Dprintk("    Cache Line Flush Instruction present.\n");
+-	/* 20 Reserved */
+-	if (m->mpc_featureflag&(1<<21))
+-		Dprintk("    Debug Trace and EMON Store present.\n");
+-	if (m->mpc_featureflag&(1<<22))
+-		Dprintk("    ACPI Thermal Throttle Registers  present.\n");
+-	if (m->mpc_featureflag&(1<<23))
+-		Dprintk("    MMX  present.\n");
+-	if (m->mpc_featureflag&(1<<24))
+-		Dprintk("    FXSR  present.\n");
+-	if (m->mpc_featureflag&(1<<25))
+-		Dprintk("    XMM  present.\n");
+-	if (m->mpc_featureflag&(1<<26))
+-		Dprintk("    Willamette New Instructions  present.\n");
+-	if (m->mpc_featureflag&(1<<27))
+-		Dprintk("    Self Snoop  present.\n");
+-	if (m->mpc_featureflag&(1<<28))
+-		Dprintk("    HT  present.\n");
+-	if (m->mpc_featureflag&(1<<29))
+-		Dprintk("    Thermal Monitor present.\n");
+-	/* 30, 31 Reserved */
+-
+-
+-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+-		Dprintk("    Bootup CPU\n");
+-		boot_cpu_physical_apicid = m->mpc_apicid;
+-	}
+-
+-	ver = m->mpc_apicver;
+-
+-	/*
+-	 * Validate version
+-	 */
+-	if (ver == 0x0) {
+-		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+-				"fixing up to 0x10. (tell your hw vendor)\n",
+-				m->mpc_apicid);
+-		ver = 0x10;
+-	}
+-	apic_version[m->mpc_apicid] = ver;
+-
+-	phys_cpu = apicid_to_cpu_present(apicid);
+-	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+-
+-	if (num_processors >= NR_CPUS) {
+-		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+-			"  Processor ignored.\n", NR_CPUS);
+-		return;
+-	}
+-
+-	if (num_processors >= maxcpus) {
+-		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
+-			" Processor ignored.\n", maxcpus);
+-		return;
+-	}
+-
+-	cpu_set(num_processors, cpu_possible_map);
+-	num_processors++;
+-
+-	/*
+-	 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+-	 * but we need to work other dependencies like SMP_SUSPEND etc
+-	 * before this can be done without some confusion.
+-	 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+-	 *       - Ashok Raj <ashok.raj@intel.com>
+-	 */
+-	if (num_processors > 8) {
+-		switch (boot_cpu_data.x86_vendor) {
+-		case X86_VENDOR_INTEL:
+-			if (!APIC_XAPIC(ver)) {
+-				def_to_bigsmp = 0;
+-				break;
+-			}
+-			/* If P4 and above fall through */
+-		case X86_VENDOR_AMD:
+-			def_to_bigsmp = 1;
+-		}
+-	}
+-	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+-}
+-#else
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+-{
+-	num_processors++;
+-}
+-#endif /* CONFIG_XEN */
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+-	char str[7];
+-
+-	memcpy(str, m->mpc_bustype, 6);
+-	str[6] = 0;
+-
+-	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+-
+-#if MAX_MP_BUSSES < 256
+-	if (m->mpc_busid >= MAX_MP_BUSSES) {
+-		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+-			" is too large, max. supported is %d\n",
+-			m->mpc_busid, str, MAX_MP_BUSSES - 1);
+-		return;
+-	}
+-#endif
+-
+-	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+-	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+-	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
+-		mpc_oem_pci_bus(m, translation_table[mpc_record]);
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+-		mp_current_pci_id++;
+-	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+-	} else {
+-		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+-	}
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+-	if (!(m->mpc_flags & MPC_APIC_USABLE))
+-		return;
+-
+-	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+-		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
+-			MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
+-	}
+-	if (!m->mpc_apicaddr) {
+-		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
+-			" found in MP table, skipping!\n");
+-		return;
+-	}
+-	mp_ioapics[nr_ioapics] = *m;
+-	nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+-	mp_irqs [mp_irq_entries] = *m;
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+-			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+-	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+-			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-#ifdef CONFIG_X86_NUMAQ
+-static void __init MP_translation_info (struct mpc_config_translation *m)
+-{
+-	printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+-
+-	if (mpc_record >= MAX_MPC_ENTRY) 
+-		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+-	else
+-		translation_table[mpc_record] = m; /* stash this for later */
+-	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+-		node_set_online(m->trans_quad);
+-}
+-
+-/*
+- * Read/parse the MPC oem tables
+- */
+-
+-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
+-	unsigned short oemsize)
+-{
+-	int count = sizeof (*oemtable); /* the header size */
+-	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
+-	
+-	mpc_record = 0;
+-	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+-	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
+-	{
+-		printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+-			oemtable->oem_signature[0],
+-			oemtable->oem_signature[1],
+-			oemtable->oem_signature[2],
+-			oemtable->oem_signature[3]);
+-		return;
+-	}
+-	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
+-	{
+-		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+-		return;
+-	}
+-	while (count < oemtable->oem_length) {
+-		switch (*oemptr) {
+-			case MP_TRANSLATION:
+-			{
+-				struct mpc_config_translation *m=
+-					(struct mpc_config_translation *)oemptr;
+-				MP_translation_info(m);
+-				oemptr += sizeof(*m);
+-				count += sizeof(*m);
+-				++mpc_record;
+-				break;
+-			}
+-			default:
+-			{
+-				printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
+-				return;
+-			}
+-		}
+-       }
+-}
+-
+-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+-		char *productid)
+-{
+-	if (strncmp(oem, "IBM NUMA", 8))
+-		printk("Warning!  May not be a NUMA-Q system!\n");
+-	if (mpc->mpc_oemptr)
+-		smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
+-				mpc->mpc_oemsize);
+-}
+-#endif	/* CONFIG_X86_NUMAQ */
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+-	char str[16];
+-	char oem[10];
+-	int count=sizeof(*mpc);
+-	unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+-		printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
+-			*(u32 *)mpc->mpc_signature);
+-		return 0;
+-	}
+-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+-		printk(KERN_ERR "SMP mptable: checksum error!\n");
+-		return 0;
+-	}
+-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+-		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
+-			mpc->mpc_spec);
+-		return 0;
+-	}
+-	if (!mpc->mpc_lapic) {
+-		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
+-		return 0;
+-	}
+-	memcpy(oem,mpc->mpc_oem,8);
+-	oem[8]=0;
+-	printk(KERN_INFO "OEM ID: %s ",oem);
+-
+-	memcpy(str,mpc->mpc_productid,12);
+-	str[12]=0;
+-	printk("Product ID: %s ",str);
+-
+-	mps_oem_check(mpc, oem, str);
+-
+-	printk("APIC at: 0x%X\n", mpc->mpc_lapic);
+-
+-	/*
+-	 * Save the local APIC address (it might be non-default) -- but only
+-	 * if we're not using ACPI.
+-	 */
+-	if (!acpi_lapic)
+-		mp_lapic_addr = mpc->mpc_lapic;
+-
+-	/*
+-	 *	Now process the configuration blocks.
+-	 */
+-	mpc_record = 0;
+-	while (count < mpc->mpc_length) {
+-		switch(*mpt) {
+-			case MP_PROCESSOR:
+-			{
+-				struct mpc_config_processor *m=
+-					(struct mpc_config_processor *)mpt;
+-				/* ACPI may have already provided this data */
+-				if (!acpi_lapic)
+-					MP_processor_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_BUS:
+-			{
+-				struct mpc_config_bus *m=
+-					(struct mpc_config_bus *)mpt;
+-				MP_bus_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_IOAPIC:
+-			{
+-				struct mpc_config_ioapic *m=
+-					(struct mpc_config_ioapic *)mpt;
+-				MP_ioapic_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			case MP_INTSRC:
+-			{
+-				struct mpc_config_intsrc *m=
+-					(struct mpc_config_intsrc *)mpt;
+-
+-				MP_intsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			case MP_LINTSRC:
+-			{
+-				struct mpc_config_lintsrc *m=
+-					(struct mpc_config_lintsrc *)mpt;
+-				MP_lintsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
+-				break;
+-			}
+-			default:
+-			{
+-				count = mpc->mpc_length;
+-				break;
+-			}
+-		}
+-		++mpc_record;
+-	}
+-	setup_apic_routing();
+-	if (!num_processors)
+-		printk(KERN_ERR "SMP mptable: no processors registered!\n");
+-	return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+-	unsigned int port;
+-
+-	port = 0x4d0 + (irq >> 3);
+-	return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i;
+-	int ELCR_fallback = 0;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;			/* conforming */
+-	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+-	intsrc.mpc_irqtype = mp_INT;
+-
+-	/*
+-	 *  If true, we have an ISA/PCI system with no IRQ entries
+-	 *  in the MP table. To prevent the PCI interrupts from being set up
+-	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+-	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+-	 *  never be level sensitive, so we simply see if the ELCR agrees.
+-	 *  If it does, we assume it's valid.
+-	 */
+-	if (mpc_default_type == 5) {
+-		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+-		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+-			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
+-		else {
+-			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+-			ELCR_fallback = 1;
+-		}
+-	}
+-
+-	for (i = 0; i < 16; i++) {
+-		switch (mpc_default_type) {
+-		case 2:
+-			if (i == 0 || i == 13)
+-				continue;	/* IRQ0 & IRQ13 not connected */
+-			/* fall through */
+-		default:
+-			if (i == 2)
+-				continue;	/* IRQ2 is never connected */
+-		}
+-
+-		if (ELCR_fallback) {
+-			/*
+-			 *  If the ELCR indicates a level-sensitive interrupt, we
+-			 *  copy that information over to the MP table in the
+-			 *  irqflag field (level sensitive, active high polarity).
+-			 */
+-			if (ELCR_trigger(i))
+-				intsrc.mpc_irqflag = 13;
+-			else
+-				intsrc.mpc_irqflag = 0;
+-		}
+-
+-		intsrc.mpc_srcbusirq = i;
+-		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
+-		MP_intsrc_info(&intsrc);
+-	}
+-
+-	intsrc.mpc_irqtype = mp_ExtINT;
+-	intsrc.mpc_srcbusirq = 0;
+-	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
+-	MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_processor processor;
+-	struct mpc_config_bus bus;
+-	struct mpc_config_ioapic ioapic;
+-	struct mpc_config_lintsrc lintsrc;
+-	int linttypes[2] = { mp_ExtINT, mp_NMI };
+-	int i;
+-
+-	/*
+-	 * local APIC has default address
+-	 */
+-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+-	/*
+-	 * 2 CPUs, numbered 0 & 1.
+-	 */
+-	processor.mpc_type = MP_PROCESSOR;
+-	/* Either an integrated APIC or a discrete 82489DX. */
+-	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+-				   (boot_cpu_data.x86_model << 4) |
+-				   boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
+-		MP_processor_info(&processor);
+-	}
+-
+-	bus.mpc_type = MP_BUS;
+-	bus.mpc_busid = 0;
+-	switch (mpc_default_type) {
+-		default:
+-			printk("???\n");
+-			printk(KERN_ERR "Unknown standard configuration %d\n",
+-				mpc_default_type);
+-			/* fall through */
+-		case 1:
+-		case 5:
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			break;
+-		case 2:
+-		case 6:
+-		case 3:
+-			memcpy(bus.mpc_bustype, "EISA  ", 6);
+-			break;
+-		case 4:
+-		case 7:
+-			memcpy(bus.mpc_bustype, "MCA   ", 6);
+-	}
+-	MP_bus_info(&bus);
+-	if (mpc_default_type > 4) {
+-		bus.mpc_busid = 1;
+-		memcpy(bus.mpc_bustype, "PCI   ", 6);
+-		MP_bus_info(&bus);
+-	}
+-
+-	ioapic.mpc_type = MP_IOAPIC;
+-	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	ioapic.mpc_flags = MPC_APIC_USABLE;
+-	ioapic.mpc_apicaddr = 0xFEC00000;
+-	MP_ioapic_info(&ioapic);
+-
+-	/*
+-	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+-	 */
+-	construct_default_ioirq_mptable(mpc_default_type);
+-
+-	lintsrc.mpc_type = MP_LINTSRC;
+-	lintsrc.mpc_irqflag = 0;		/* conforming */
+-	lintsrc.mpc_srcbusid = 0;
+-	lintsrc.mpc_srcbusirq = 0;
+-	lintsrc.mpc_destapic = MP_APIC_ALL;
+-	for (i = 0; i < 2; i++) {
+-		lintsrc.mpc_irqtype = linttypes[i];
+-		lintsrc.mpc_destapiclint = i;
+-		MP_lintsrc_info(&lintsrc);
+-	}
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+-	struct intel_mp_floating *mpf = mpf_found;
+-
+-	/*
+-	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
+-	 * processors, where MPS only supports physical.
+-	 */
+-	if (acpi_lapic && acpi_ioapic) {
+-		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+-		return;
+-	}
+-	else if (acpi_lapic)
+-		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+-	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-	if (mpf->mpf_feature2 & (1<<7)) {
+-		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+-		pic_mode = 1;
+-	} else {
+-		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
+-		pic_mode = 0;
+-	}
+-
+-	/*
+-	 * Now see if we need to read further.
+-	 */
+-	if (mpf->mpf_feature1 != 0) {
+-
+-		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+-		construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+-	} else if (mpf->mpf_physptr) {
+-
+-		/*
+-		 * Read the physical hardware table.  Anything here will
+-		 * override the defaults.
+-		 */
+-		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) {
+-			smp_found_config = 0;
+-			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+-			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+-			return;
+-		}
+-		/*
+-		 * If there are no explicit MP IRQ entries, then we are
+-		 * broken.  We set up most of the low 16 IO-APIC pins to
+-		 * ISA defaults and hope it will work.
+-		 */
+-		if (!mp_irq_entries) {
+-			struct mpc_config_bus bus;
+-
+-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+-			bus.mpc_type = MP_BUS;
+-			bus.mpc_busid = 0;
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			MP_bus_info(&bus);
+-
+-			construct_default_ioirq_mptable(0);
+-		}
+-
+-	} else
+-		BUG();
+-
+-	printk(KERN_INFO "Processors: %d\n", num_processors);
+-	/*
+-	 * Only use the first configuration found.
+-	 */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+-	unsigned long *bp = isa_bus_to_virt(base);
+-	struct intel_mp_floating *mpf;
+-
+-	printk(KERN_INFO "Scan SMP from %p for %ld bytes.\n", bp,length);
+-	if (sizeof(*mpf) != 16)
+-		printk("Error: MPF size\n");
+-
+-	while (length > 0) {
+-		mpf = (struct intel_mp_floating *)bp;
+-		if ((*bp == SMP_MAGIC_IDENT) &&
+-			(mpf->mpf_length == 1) &&
+-			!mpf_checksum((unsigned char *)bp, 16) &&
+-			((mpf->mpf_specification == 1)
+-				|| (mpf->mpf_specification == 4)) ) {
+-
+-			smp_found_config = 1;
+-#ifndef CONFIG_XEN
+-			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-				mpf, virt_to_phys(mpf));
+-			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
+-					BOOTMEM_DEFAULT);
+-			if (mpf->mpf_physptr) {
+-				/*
+-				 * We cannot access to MPC table to compute
+-				 * table size yet, as only few megabytes from
+-				 * the bottom is mapped now.
+-				 * PC-9800's MPC table places on the very last
+-				 * of physical memory; so that simply reserving
+-				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+-				 * in reserve_bootmem.
+-				 */
+-				unsigned long size = PAGE_SIZE;
+-				unsigned long end = max_low_pfn * PAGE_SIZE;
+-				if (mpf->mpf_physptr + size > end)
+-					size = end - mpf->mpf_physptr;
+-				reserve_bootmem(mpf->mpf_physptr, size,
+-						BOOTMEM_DEFAULT);
+-			}
+-#else
+-			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-				mpf, ((void *)bp - isa_bus_to_virt(base)) + base);
+-#endif
+-
+-			mpf_found = mpf;
+-			return 1;
+-		}
+-		bp += 4;
+-		length -= 16;
+-	}
+-	return 0;
+-}
+-
+-void __init find_smp_config (void)
+-{
+-#ifndef CONFIG_XEN
+-	unsigned int address;
+-#endif
+-
+-	/*
+-	 * FIXME: Linux assumes you have 640K of base ram..
+-	 * this continues the error...
+-	 *
+-	 * 1) Scan the bottom 1K for a signature
+-	 * 2) Scan the top 1K of base RAM
+-	 * 3) Scan the 64K of bios
+-	 */
+-	if (smp_scan_config(0x0,0x400) ||
+-		smp_scan_config(639*0x400,0x400) ||
+-			smp_scan_config(0xF0000,0x10000))
+-		return;
+-	/*
+-	 * If it is an SMP machine we should know now, unless the
+-	 * configuration is in an EISA/MCA bus machine with an
+-	 * extended bios data area.
+-	 *
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E, calculate and scan it here.
+-	 *
+-	 * NOTE! There are Linux loaders that will corrupt the EBDA
+-	 * area, and as such this kind of SMP config may be less
+-	 * trustworthy, simply because the SMP table may have been
+-	 * stomped on during early boot. These loaders are buggy and
+-	 * should be fixed.
+-	 *
+-	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
+-	 */
+-
+-#ifndef CONFIG_XEN
+-	address = get_bios_ebda();
+-	if (address)
+-		smp_scan_config(address, 0x400);
+-#endif
+-}
+-
+-int es7000_plat;
+-
+-/* --------------------------------------------------------------------------
+-                            ACPI-based MP Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+-#ifndef CONFIG_XEN
+-	mp_lapic_addr = (unsigned long) address;
+-
+-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-
+-	if (boot_cpu_physical_apicid == -1U)
+-		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
+-
+-	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
+-#endif
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+-	struct mpc_config_processor processor;
+-	int boot_cpu = 0;
+-	
+-	if (MAX_APICS - id <= 0) {
+-		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+-			id, MAX_APICS);
+-		return;
+-	}
+-
+-	if (id == boot_cpu_physical_apicid)
+-		boot_cpu = 1;
+-
+-#ifndef CONFIG_XEN
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicid = id;
+-	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+-	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+-	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
+-		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-#endif
+-
+-	MP_processor_info(&processor);
+-}
+-
+-#ifdef	CONFIG_X86_IO_APIC
+-
+-#define MP_ISA_BUS		0
+-#define MP_MAX_IOAPIC_PIN	127
+-
+-static struct mp_ioapic_routing {
+-	int			apic_id;
+-	int			gsi_base;
+-	int			gsi_end;
+-	u32			pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic (int gsi)
+-{
+-	int i = 0;
+-
+-	/* Find the IOAPIC that manages this GSI. */
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if ((gsi >= mp_ioapic_routing[i].gsi_base)
+-			&& (gsi <= mp_ioapic_routing[i].gsi_end))
+-			return i;
+-	}
+-
+-	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-
+-	return -1;
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+-	int idx = 0;
+-	int tmpid;
+-
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+-			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+-	}
+-	if (!address) {
+-		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+-			" found in MADT table, skipping!\n");
+-		return;
+-	}
+-
+-	idx = nr_ioapics++;
+-
+-	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+-	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+-	mp_ioapics[idx].mpc_apicaddr = address;
+-
+-#ifndef CONFIG_XEN
+-	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+-#endif
+-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+-		&& !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+-		tmpid = io_apic_get_unique_id(idx, id);
+-	else
+-		tmpid = id;
+-	if (tmpid == -1) {
+-		nr_ioapics--;
+-		return;
+-	}
+-	mp_ioapics[idx].mpc_apicid = tmpid;
+-	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+-	
+-	/* 
+-	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+-	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+-	 */
+-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+-	mp_ioapic_routing[idx].gsi_base = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base +
+-		io_apic_get_redir_entries(idx);
+-
+-	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+-	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+-	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+-	       mp_ioapic_routing[idx].gsi_base,
+-	       mp_ioapic_routing[idx].gsi_end);
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int			ioapic = -1;
+-	int			pin = -1;
+-
+-	/* 
+-	 * Convert 'gsi' to 'ioapic.pin'.
+-	 */
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0)
+-		return;
+-	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+-	/*
+-	 * TBD: This check is for faulty timer entries, where the override
+-	 *      erroneously sets the trigger to level, resulting in a HUGE 
+-	 *      increase of timer interrupts!
+-	 */
+-	if ((bus_irq == 0) && (trigger == 3))
+-		trigger = 1;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqtype = mp_INT;
+-	intsrc.mpc_irqflag = (trigger << 2) | polarity;
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
+-	intsrc.mpc_dstirq = pin;				    /* INTIN# */
+-
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
+-		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+-	mp_irqs[mp_irq_entries] = intsrc;
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs (void)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i = 0;
+-	int ioapic = -1;
+-
+-	/* 
+-	 * Fabricate the legacy ISA bus (bus #31).
+-	 */
+-	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+-	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+-
+-	/*
+-	 * Older generations of ES7000 have no legacy identity mappings
+-	 */
+-	if (es7000_plat == 1)
+-		return;
+-
+-	/* 
+-	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
+-	 */
+-	ioapic = mp_find_ioapic(0);
+-	if (ioapic < 0)
+-		return;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;					/* Conforming */
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+-	/* 
+-	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overridden by (MADT) interrupt source override entries.
+-	 */
+-	for (i = 0; i < 16; i++) {
+-		int idx;
+-
+-		for (idx = 0; idx < mp_irq_entries; idx++) {
+-			struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+-			/* Do we already have a mapping for this ISA IRQ? */
+-			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+-				break;
+-
+-			/* Do we already have a mapping for this IOAPIC pin */
+-			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+-				(irq->mpc_dstirq == i))
+-				break;
+-		}
+-
+-		if (idx != mp_irq_entries) {
+-			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+-			continue;			/* IRQ already used */
+-		}
+-
+-		intsrc.mpc_irqtype = mp_INT;
+-		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
+-		intsrc.mpc_dstirq = i;
+-
+-		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+-			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
+-			intsrc.mpc_dstirq);
+-
+-		mp_irqs[mp_irq_entries] = intsrc;
+-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-			panic("Max # of irq sources exceeded!\n");
+-	}
+-}
+-
+-#define MAX_GSI_NUM	4096
+-#define IRQ_COMPRESSION_START	64
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+-	int ioapic = -1;
+-	int ioapic_pin = 0;
+-	int idx, bit = 0;
+-	static int pci_irq = IRQ_COMPRESSION_START;
+-	/*
+-	 * Mapping between Global System Interrupts, which
+-	 * represent all possible interrupts, and IRQs
+-	 * assigned to actual devices.
+-	 */
+-	static int		gsi_to_irq[MAX_GSI_NUM];
+-
+-	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_gbl_FADT.sci_interrupt == gsi)
+-		return gsi;
+-
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0) {
+-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+-		return gsi;
+-	}
+-
+-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
+-
+-	if (ioapic_renumber_irq)
+-		gsi = ioapic_renumber_irq(ioapic, gsi);
+-
+-	/* 
+-	 * Avoid pin reprogramming.  PRTs typically include entries  
+-	 * with redundant pin->gsi mappings (but unique PCI devices);
+-	 * we only program the IOAPIC on the first.
+-	 */
+-	bit = ioapic_pin % 32;
+-	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+-	if (idx > 3) {
+-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+-			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+-			ioapic_pin);
+-		return gsi;
+-	}
+-	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+-	}
+-
+-	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+-	/*
+-	 * For GSI >= 64, use IRQ compression
+-	 */
+-	if ((gsi >= IRQ_COMPRESSION_START)
+-		&& (triggering == ACPI_LEVEL_SENSITIVE)) {
+-		/*
+-		 * For PCI devices assign IRQs in order, avoiding gaps
+-		 * due to unused I/O APIC pins.
+-		 */
+-		int irq = gsi;
+-		if (gsi < MAX_GSI_NUM) {
+-			/*
+-			 * Retain the VIA chipset work-around (gsi > 15), but
+-			 * avoid a problem where the 8254 timer (IRQ0) is setup
+-			 * via an override (so it's not on pin 0 of the ioapic),
+-			 * and at the same time, the pin 0 interrupt is a PCI
+-			 * type.  The gsi > 15 test could cause these two pins
+-			 * to be shared as IRQ0, and they are not shareable.
+-			 * So test for this condition, and if necessary, avoid
+-			 * the pin collision.
+-			 */
+-			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
+-				gsi = pci_irq++;
+-			/*
+-			 * Don't assign IRQ used by ACPI SCI
+-			 */
+-			if (gsi == acpi_gbl_FADT.sci_interrupt)
+-				gsi = pci_irq++;
+-			gsi_to_irq[irq] = gsi;
+-		} else {
+-			printk(KERN_ERR "GSI %u is too high\n", gsi);
+-			return gsi;
+-		}
+-	}
+-
+-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+-		    triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+-		    polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+-	return gsi;
+-}
+-
+-#endif /* CONFIG_X86_IO_APIC */
+-#endif /* CONFIG_ACPI */
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,879 +0,0 @@
+-/*
+- *	Intel Multiprocessor Specification 1.1 and 1.4
+- *	compliant MP-table parsing routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+- *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *		Erich Boleyn	:	MP v1.4 and additional changes.
+- *		Alan Cox	:	Added EBDA scanning
+- *		Ingo Molnar	:	various cleanups and rewrites
+- *		Maciej W. Rozycki:	Bits for default MP configurations
+- *		Paul Diefenbaugh:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/acpi.h>
+-#include <linux/module.h>
+-
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/pgalloc.h>
+-#include <asm/io_apic.h>
+-#include <asm/proto.h>
+-#include <asm/acpi.h>
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+-
+-static int mp_current_pci_id = 0;
+-/* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+-
+-/* # of MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* MP IRQ source entries */
+-int mp_irq_entries;
+-
+-int nr_ioapics;
+-unsigned long mp_lapic_addr = 0;
+-
+-
+-
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_id = -1U;
+-EXPORT_SYMBOL(boot_cpu_id);
+-
+-/* Internal processor count */
+-unsigned int num_processors;
+-
+-unsigned disabled_cpus __cpuinitdata;
+-
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+-
+-#ifndef CONFIG_XEN
+-u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
+-				= { [0 ... NR_CPUS-1] = BAD_APICID };
+-void *x86_bios_cpu_apicid_early_ptr;
+-#endif
+-DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
+-
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
+-
+-/*
+- * Checksum an MP configuration block.
+- */
+-
+-static int __init mpf_checksum(unsigned char *mp, int len)
+-{
+-	int sum = 0;
+-
+-	while (len--)
+-		sum += *mp++;
+-
+-	return sum & 0xFF;
+-}
+-
+-#ifndef CONFIG_XEN
+-static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+-{
+-	int cpu;
+-	cpumask_t tmp_map;
+-	char *bootup_cpu = "";
+-
+-	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+-		disabled_cpus++;
+-		return;
+-	}
+-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+-		bootup_cpu = " (Bootup-CPU)";
+-		boot_cpu_id = m->mpc_apicid;
+-	}
+-
+-	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+-
+-	if (num_processors >= NR_CPUS) {
+-		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+-			" Processor ignored.\n", NR_CPUS);
+-		return;
+-	}
+-
+-	num_processors++;
+-	cpus_complement(tmp_map, cpu_present_map);
+-	cpu = first_cpu(tmp_map);
+-
+-	physid_set(m->mpc_apicid, phys_cpu_present_map);
+- 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+- 		/*
+-		 * x86_bios_cpu_apicid is required to have processors listed
+- 		 * in same order as logical cpu numbers. Hence the first
+- 		 * entry is BSP, and so on.
+- 		 */
+-		cpu = 0;
+- 	}
+-	/* are we being called early in kernel startup? */
+-	if (x86_cpu_to_apicid_early_ptr) {
+-		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
+-		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
+-
+-		cpu_to_apicid[cpu] = m->mpc_apicid;
+-		bios_cpu_apicid[cpu] = m->mpc_apicid;
+-	} else {
+-		per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
+-		per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
+-	}
+-
+-	cpu_set(cpu, cpu_possible_map);
+-	cpu_set(cpu, cpu_present_map);
+-}
+-#else
+-static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+-{
+-	num_processors++;
+-}
+-#endif /* CONFIG_XEN */
+-
+-static void __init MP_bus_info (struct mpc_config_bus *m)
+-{
+-	char str[7];
+-
+-	memcpy(str, m->mpc_bustype, 6);
+-	str[6] = 0;
+-	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+-
+-	if (strncmp(str, "ISA", 3) == 0) {
+-		set_bit(m->mpc_busid, mp_bus_not_pci);
+-	} else if (strncmp(str, "PCI", 3) == 0) {
+-		clear_bit(m->mpc_busid, mp_bus_not_pci);
+-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+-		mp_current_pci_id++;
+-	} else {
+-		printk(KERN_ERR "Unknown bustype %s\n", str);
+-	}
+-}
+-
+-static int bad_ioapic(unsigned long address)
+-{
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+-			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+-	}
+-	if (!address) {
+-		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+-			" found in table, skipping!\n");
+-		return 1;
+-	}
+-	return 0;
+-}
+-
+-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+-{
+-	if (!(m->mpc_flags & MPC_APIC_USABLE))
+-		return;
+-
+-	printk("I/O APIC #%d at 0x%X.\n",
+-		m->mpc_apicid, m->mpc_apicaddr);
+-
+-	if (bad_ioapic(m->mpc_apicaddr))
+-		return;
+-
+-	mp_ioapics[nr_ioapics] = *m;
+-	nr_ioapics++;
+-}
+-
+-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+-{
+-	mp_irqs [mp_irq_entries] = *m;
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+-			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+-	if (++mp_irq_entries >= MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!!\n");
+-}
+-
+-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+-{
+-	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-			m->mpc_irqtype, m->mpc_irqflag & 3,
+-			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+-			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-}
+-
+-/*
+- * Read/parse the MPC
+- */
+-
+-static int __init smp_read_mpc(struct mp_config_table *mpc)
+-{
+-	char str[16];
+-	int count=sizeof(*mpc);
+-	unsigned char *mpt=((unsigned char *)mpc)+count;
+-
+-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+-		printk("MPTABLE: bad signature [%c%c%c%c]!\n",
+-			mpc->mpc_signature[0],
+-			mpc->mpc_signature[1],
+-			mpc->mpc_signature[2],
+-			mpc->mpc_signature[3]);
+-		return 0;
+-	}
+-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+-		printk("MPTABLE: checksum error!\n");
+-		return 0;
+-	}
+-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+-		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+-			mpc->mpc_spec);
+-		return 0;
+-	}
+-	if (!mpc->mpc_lapic) {
+-		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+-		return 0;
+-	}
+-	memcpy(str,mpc->mpc_oem,8);
+-	str[8] = 0;
+-	printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
+-
+-	memcpy(str,mpc->mpc_productid,12);
+-	str[12] = 0;
+-	printk("MPTABLE: Product ID: %s ",str);
+-
+-	printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
+-
+-	/* save the local APIC address, it might be non-default */
+-	if (!acpi_lapic)
+-		mp_lapic_addr = mpc->mpc_lapic;
+-
+-	/*
+-	 *	Now process the configuration blocks.
+-	 */
+-	while (count < mpc->mpc_length) {
+-		switch(*mpt) {
+-			case MP_PROCESSOR:
+-			{
+-				struct mpc_config_processor *m=
+-					(struct mpc_config_processor *)mpt;
+-				if (!acpi_lapic)
+-					MP_processor_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_BUS:
+-			{
+-				struct mpc_config_bus *m=
+-					(struct mpc_config_bus *)mpt;
+-				MP_bus_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_IOAPIC:
+-			{
+-				struct mpc_config_ioapic *m=
+-					(struct mpc_config_ioapic *)mpt;
+-				MP_ioapic_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_INTSRC:
+-			{
+-				struct mpc_config_intsrc *m=
+-					(struct mpc_config_intsrc *)mpt;
+-
+-				MP_intsrc_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-			case MP_LINTSRC:
+-			{
+-				struct mpc_config_lintsrc *m=
+-					(struct mpc_config_lintsrc *)mpt;
+-				MP_lintsrc_info(m);
+-				mpt += sizeof(*m);
+-				count += sizeof(*m);
+-				break;
+-			}
+-		}
+-	}
+-	setup_apic_routing();
+-	if (!num_processors)
+-		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+-	return num_processors;
+-}
+-
+-static int __init ELCR_trigger(unsigned int irq)
+-{
+-	unsigned int port;
+-
+-	port = 0x4d0 + (irq >> 3);
+-	return (inb(port) >> (irq & 7)) & 1;
+-}
+-
+-static void __init construct_default_ioirq_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i;
+-	int ELCR_fallback = 0;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;			/* conforming */
+-	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
+-
+-	intsrc.mpc_irqtype = mp_INT;
+-
+-	/*
+-	 *  If true, we have an ISA/PCI system with no IRQ entries
+-	 *  in the MP table. To prevent the PCI interrupts from being set up
+-	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+-	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+-	 *  never be level sensitive, so we simply see if the ELCR agrees.
+-	 *  If it does, we assume it's valid.
+-	 */
+-	if (mpc_default_type == 5) {
+-		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+-
+-		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
+-			printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
+-		else {
+-			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
+-			ELCR_fallback = 1;
+-		}
+-	}
+-
+-	for (i = 0; i < 16; i++) {
+-		switch (mpc_default_type) {
+-		case 2:
+-			if (i == 0 || i == 13)
+-				continue;	/* IRQ0 & IRQ13 not connected */
+-			/* fall through */
+-		default:
+-			if (i == 2)
+-				continue;	/* IRQ2 is never connected */
+-		}
+-
+-		if (ELCR_fallback) {
+-			/*
+-			 *  If the ELCR indicates a level-sensitive interrupt, we
+-			 *  copy that information over to the MP table in the
+-			 *  irqflag field (level sensitive, active high polarity).
+-			 */
+-			if (ELCR_trigger(i))
+-				intsrc.mpc_irqflag = 13;
+-			else
+-				intsrc.mpc_irqflag = 0;
+-		}
+-
+-		intsrc.mpc_srcbusirq = i;
+-		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
+-		MP_intsrc_info(&intsrc);
+-	}
+-
+-	intsrc.mpc_irqtype = mp_ExtINT;
+-	intsrc.mpc_srcbusirq = 0;
+-	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
+-	MP_intsrc_info(&intsrc);
+-}
+-
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+-{
+-	struct mpc_config_processor processor;
+-	struct mpc_config_bus bus;
+-	struct mpc_config_ioapic ioapic;
+-	struct mpc_config_lintsrc lintsrc;
+-	int linttypes[2] = { mp_ExtINT, mp_NMI };
+-	int i;
+-
+-	/*
+-	 * local APIC has default address
+-	 */
+-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+-	/*
+-	 * 2 CPUs, numbered 0 & 1.
+-	 */
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicver = 0;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = 0;
+-	processor.mpc_featureflag = 0;
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
+-		MP_processor_info(&processor);
+-	}
+-
+-	bus.mpc_type = MP_BUS;
+-	bus.mpc_busid = 0;
+-	switch (mpc_default_type) {
+-		default:
+-			printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+-				mpc_default_type);
+-			/* fall through */
+-		case 1:
+-		case 5:
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			break;
+-	}
+-	MP_bus_info(&bus);
+-	if (mpc_default_type > 4) {
+-		bus.mpc_busid = 1;
+-		memcpy(bus.mpc_bustype, "PCI   ", 6);
+-		MP_bus_info(&bus);
+-	}
+-
+-	ioapic.mpc_type = MP_IOAPIC;
+-	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = 0;
+-	ioapic.mpc_flags = MPC_APIC_USABLE;
+-	ioapic.mpc_apicaddr = 0xFEC00000;
+-	MP_ioapic_info(&ioapic);
+-
+-	/*
+-	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+-	 */
+-	construct_default_ioirq_mptable(mpc_default_type);
+-
+-	lintsrc.mpc_type = MP_LINTSRC;
+-	lintsrc.mpc_irqflag = 0;		/* conforming */
+-	lintsrc.mpc_srcbusid = 0;
+-	lintsrc.mpc_srcbusirq = 0;
+-	lintsrc.mpc_destapic = MP_APIC_ALL;
+-	for (i = 0; i < 2; i++) {
+-		lintsrc.mpc_irqtype = linttypes[i];
+-		lintsrc.mpc_destapiclint = i;
+-		MP_lintsrc_info(&lintsrc);
+-	}
+-}
+-
+-static struct intel_mp_floating *mpf_found;
+-
+-/*
+- * Scan the memory blocks for an SMP configuration block.
+- */
+-void __init get_smp_config (void)
+-{
+-	struct intel_mp_floating *mpf = mpf_found;
+-
+-	/*
+- 	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
+- 	 * processors, where MPS only supports physical.
+- 	 */
+- 	if (acpi_lapic && acpi_ioapic) {
+- 		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+- 		return;
+-	}
+- 	else if (acpi_lapic)
+- 		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+-
+-	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-
+-	/*
+-	 * Now see if we need to read further.
+-	 */
+-	if (mpf->mpf_feature1 != 0) {
+-
+-		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
+-		construct_default_ISA_mptable(mpf->mpf_feature1);
+-
+-	} else if (mpf->mpf_physptr) {
+-
+-		/*
+-		 * Read the physical hardware table.  Anything here will
+-		 * override the defaults.
+-		 */
+- 		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) {
+-			smp_found_config = 0;
+-			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+-			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+-			return;
+-		}
+-		/*
+-		 * If there are no explicit MP IRQ entries, then we are
+-		 * broken.  We set up most of the low 16 IO-APIC pins to
+-		 * ISA defaults and hope it will work.
+-		 */
+-		if (!mp_irq_entries) {
+-			struct mpc_config_bus bus;
+-
+-			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+-
+-			bus.mpc_type = MP_BUS;
+-			bus.mpc_busid = 0;
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
+-			MP_bus_info(&bus);
+-
+-			construct_default_ioirq_mptable(0);
+-		}
+-
+-	} else
+-		BUG();
+-
+-	printk(KERN_INFO "Processors: %d\n", num_processors);
+-	/*
+-	 * Only use the first configuration found.
+-	 */
+-}
+-
+-static int __init smp_scan_config (unsigned long base, unsigned long length)
+-{
+-	extern void __bad_mpf_size(void); 
+-	unsigned int *bp = isa_bus_to_virt(base);
+-	struct intel_mp_floating *mpf;
+-
+-	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
+-	if (sizeof(*mpf) != 16)
+-		__bad_mpf_size();
+-
+-	while (length > 0) {
+-		mpf = (struct intel_mp_floating *)bp;
+-		if ((*bp == SMP_MAGIC_IDENT) &&
+-			(mpf->mpf_length == 1) &&
+-			!mpf_checksum((unsigned char *)bp, 16) &&
+-			((mpf->mpf_specification == 1)
+-				|| (mpf->mpf_specification == 4)) ) {
+-
+-			smp_found_config = 1;
+-			mpf_found = mpf;
+-			return 1;
+-		}
+-		bp += 4;
+-		length -= 16;
+-	}
+-	return 0;
+-}
+-
+-void __init find_smp_config(void)
+-{
+-	unsigned int address;
+-
+-	/*
+-	 * FIXME: Linux assumes you have 640K of base ram..
+-	 * this continues the error...
+-	 *
+-	 * 1) Scan the bottom 1K for a signature
+-	 * 2) Scan the top 1K of base RAM
+-	 * 3) Scan the 64K of bios
+-	 */
+-	if (smp_scan_config(0x0,0x400) ||
+-		smp_scan_config(639*0x400,0x400) ||
+-			smp_scan_config(0xF0000,0x10000))
+-		return;
+-	/*
+-	 * If it is an SMP machine we should know now.
+-	 *
+-	 * there is a real-mode segmented pointer pointing to the
+-	 * 4K EBDA area at 0x40E, calculate and scan it here.
+-	 *
+-	 * NOTE! There are Linux loaders that will corrupt the EBDA
+-	 * area, and as such this kind of SMP config may be less
+-	 * trustworthy, simply because the SMP table may have been
+-	 * stomped on during early boot. These loaders are buggy and
+-	 * should be fixed.
+-	 */
+-
+-	address = *(unsigned short *)phys_to_virt(0x40E);
+-	address <<= 4;
+-	if (smp_scan_config(address, 0x1000))
+-		return;
+-
+-	/* If we have come this far, we did not find an MP table  */
+-	 printk(KERN_INFO "No mptable found.\n");
+-}
+-
+-/* --------------------------------------------------------------------------
+-                            ACPI-based MP Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-void __init mp_register_lapic_address(u64 address)
+-{
+-#ifndef CONFIG_XEN
+-	mp_lapic_addr = (unsigned long) address;
+-	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-	if (boot_cpu_id == -1U)
+-		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+-#endif
+-}
+-
+-void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+-{
+-	struct mpc_config_processor processor;
+-	int			boot_cpu = 0;
+-	
+-	if (id == boot_cpu_id)
+-		boot_cpu = 1;
+-
+-#ifndef CONFIG_XEN
+-	processor.mpc_type = MP_PROCESSOR;
+-	processor.mpc_apicid = id;
+-	processor.mpc_apicver = 0;
+-	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+-	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+-	processor.mpc_cpufeature = 0;
+-	processor.mpc_featureflag = 0;
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-#endif
+-
+-	MP_processor_info(&processor);
+-}
+-
+-#define MP_ISA_BUS		0
+-#define MP_MAX_IOAPIC_PIN	127
+-
+-static struct mp_ioapic_routing {
+-	int			apic_id;
+-	int			gsi_start;
+-	int			gsi_end;
+-	u32			pin_programmed[4];
+-} mp_ioapic_routing[MAX_IO_APICS];
+-
+-static int mp_find_ioapic(int gsi)
+-{
+-	int i = 0;
+-
+-	/* Find the IOAPIC that manages this GSI. */
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if ((gsi >= mp_ioapic_routing[i].gsi_start)
+-			&& (gsi <= mp_ioapic_routing[i].gsi_end))
+-			return i;
+-	}
+-
+-	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-	return -1;
+-}
+-
+-static u8 uniq_ioapic_id(u8 id)
+-{
+-	int i;
+-	DECLARE_BITMAP(used, 256);
+-	bitmap_zero(used, 256);
+-	for (i = 0; i < nr_ioapics; i++) {
+-		struct mpc_config_ioapic *ia = &mp_ioapics[i];
+-		__set_bit(ia->mpc_apicid, used);
+-	}
+-	if (!test_bit(id, used))
+-		return id;
+-	return find_first_zero_bit(used, 256);
+-}
+-
+-void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+-{
+-	int idx = 0;
+-
+-	if (bad_ioapic(address))
+-		return;
+-
+-	idx = nr_ioapics;
+-
+-	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+-	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+-	mp_ioapics[idx].mpc_apicaddr = address;
+-
+-#ifndef CONFIG_XEN
+-	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+-#endif
+-	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
+-	mp_ioapics[idx].mpc_apicver = 0;
+-	
+-	/* 
+-	 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
+-	 * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
+-	 */
+-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+-	mp_ioapic_routing[idx].gsi_start = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base + 
+-		io_apic_get_redir_entries(idx);
+-
+-	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
+-		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
+-		mp_ioapics[idx].mpc_apicaddr,
+-		mp_ioapic_routing[idx].gsi_start,
+-		mp_ioapic_routing[idx].gsi_end);
+-
+-	nr_ioapics++;
+-}
+-
+-void __init
+-mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32	gsi)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int			ioapic = -1;
+-	int			pin = -1;
+-
+-	/* 
+-	 * Convert 'gsi' to 'ioapic.pin'.
+-	 */
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0)
+-		return;
+-	pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+-	/*
+-	 * TBD: This check is for faulty timer entries, where the override
+-	 *      erroneously sets the trigger to level, resulting in a HUGE 
+-	 *      increase of timer interrupts!
+-	 */
+-	if ((bus_irq == 0) && (trigger == 3))
+-		trigger = 1;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqtype = mp_INT;
+-	intsrc.mpc_irqflag = (trigger << 2) | polarity;
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
+-	intsrc.mpc_dstirq = pin;				    /* INTIN# */
+-
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", 
+-		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
+-
+-	mp_irqs[mp_irq_entries] = intsrc;
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!\n");
+-}
+-
+-void __init mp_config_acpi_legacy_irqs(void)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int i = 0;
+-	int ioapic = -1;
+-
+-	/* 
+-	 * Fabricate the legacy ISA bus (bus #31).
+-	 */
+-	set_bit(MP_ISA_BUS, mp_bus_not_pci);
+-
+-	/* 
+-	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
+-	 */
+-	ioapic = mp_find_ioapic(0);
+-	if (ioapic < 0)
+-		return;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;					/* Conforming */
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-
+-	/* 
+-	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overridden by (MADT) interrupt source override entries.
+-	 */
+-	for (i = 0; i < 16; i++) {
+-		int idx;
+-
+-		for (idx = 0; idx < mp_irq_entries; idx++) {
+-			struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+-			/* Do we already have a mapping for this ISA IRQ? */
+-			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
+-				break;
+-
+-			/* Do we already have a mapping for this IOAPIC pin */
+-			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+-				(irq->mpc_dstirq == i))
+-				break;
+-		}
+-
+-		if (idx != mp_irq_entries) {
+-			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+-			continue;			/* IRQ already used */
+-		}
+-
+-		intsrc.mpc_irqtype = mp_INT;
+-		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
+-		intsrc.mpc_dstirq = i;
+-
+-		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
+-			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
+-			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
+-			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
+-			intsrc.mpc_dstirq);
+-
+-		mp_irqs[mp_irq_entries] = intsrc;
+-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-			panic("Max # of irq sources exceeded!\n");
+-	}
+-}
+-
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
+-{
+-	int ioapic = -1;
+-	int ioapic_pin = 0;
+-	int idx, bit = 0;
+-
+-	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+-		return gsi;
+-
+-	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_gbl_FADT.sci_interrupt == gsi)
+-		return gsi;
+-
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0) {
+-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+-		return gsi;
+-	}
+-
+-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
+-
+-	/* 
+-	 * Avoid pin reprogramming.  PRTs typically include entries  
+-	 * with redundant pin->gsi mappings (but unique PCI devices);
+-	 * we only program the IOAPIC on the first.
+-	 */
+-	bit = ioapic_pin % 32;
+-	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
+-	if (idx > 3) {
+-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+-			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
+-			ioapic_pin);
+-		return gsi;
+-	}
+-	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return gsi;
+-	}
+-
+-	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+-
+-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+-		triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+-		polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+-	return gsi;
+-}
+-#endif /*CONFIG_ACPI*/
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -1,280 +1,251 @@
+-/*
+- * Dynamic DMA mapping support.
+- *
+- * On i386 there is no hardware dynamic DMA address translation,
+- * so consistent alloc/free are merely page allocation/freeing.
+- * The rest of the dynamic DMA mapping interface is implemented
+- * in asm/pci.h.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmar.h>
++#include <linux/bootmem.h>
+ #include <linux/pci.h>
+-#include <linux/module.h>
+-#include <linux/version.h>
+-#include <asm/io.h>
+-#include <xen/balloon.h>
+-#include <xen/gnttab.h>
+-#include <asm/swiotlb.h>
+-#include <asm/tlbflush.h>
+-#include <asm/swiotlb_32.h>
+-#include <asm/gnttab_dma.h>
+-#include <asm/bug.h>
+ 
+-#ifdef __x86_64__
+-#include <asm/iommu.h>
++#include <asm/proto.h>
++#include <asm/dma.h>
++#include <asm/gart.h>
++#include <asm/calgary.h>
++
++int forbid_dac __read_mostly;
++EXPORT_SYMBOL(forbid_dac);
++
++const struct dma_mapping_ops *dma_ops;
++EXPORT_SYMBOL(dma_ops);
++
++static int iommu_sac_force __read_mostly;
++
++#ifdef CONFIG_IOMMU_DEBUG
++int panic_on_overflow __read_mostly = 1;
++int force_iommu __read_mostly = 1;
++#else
++int panic_on_overflow __read_mostly = 0;
++int force_iommu __read_mostly = 0;
++#endif
+ 
+ int iommu_merge __read_mostly = 0;
+-EXPORT_SYMBOL(iommu_merge);
+ 
+-dma_addr_t bad_dma_address __read_mostly;
+-EXPORT_SYMBOL(bad_dma_address);
++int no_iommu __read_mostly;
++/* Set this to 1 if there is a HW IOMMU in the system */
++int iommu_detected __read_mostly = 0;
+ 
+ /* This tells the BIO block layer to assume merging. Default to off
+    because we cannot guarantee merging later. */
+ int iommu_bio_merge __read_mostly = 0;
+ EXPORT_SYMBOL(iommu_bio_merge);
+ 
+-int force_iommu __read_mostly= 0;
++dma_addr_t bad_dma_address __read_mostly = 0;
++EXPORT_SYMBOL(bad_dma_address);
+ 
+-__init int iommu_setup(char *p)
+-{
+-    return 1;
+-}
++/* Dummy device used for NULL arguments (normally ISA). Better would
++   be probably a smaller DMA mask, but this is bug-to-bug compatible
++   to older i386. */
++struct device fallback_dev = {
++	.bus_id = "fallback device",
++	.coherent_dma_mask = DMA_32BIT_MASK,
++	.dma_mask = &fallback_dev.coherent_dma_mask,
++};
+ 
+-void __init pci_iommu_alloc(void)
++int dma_set_mask(struct device *dev, u64 mask)
+ {
+-#ifdef CONFIG_SWIOTLB
+-	pci_swiotlb_init();
+-#endif
+-}
++	if (!dev->dma_mask || !dma_supported(dev, mask))
++		return -EIO;
++
++	*dev->dma_mask = mask;
+ 
+-static int __init pci_iommu_init(void)
+-{
+-	no_iommu_init();
+ 	return 0;
+ }
++EXPORT_SYMBOL(dma_set_mask);
+ 
+-/* Must execute after PCI subsystem */
+-fs_initcall(pci_iommu_init);
+-#endif
+-
+-struct dma_coherent_mem {
+-	void		*virt_base;
+-	u32		device_base;
+-	int		size;
+-	int		flags;
+-	unsigned long	*bitmap;
+-};
+-
+-#define IOMMU_BUG_ON(test)				\
+-do {							\
+-	if (unlikely(test)) {				\
+-		printk(KERN_ALERT "Fatal DMA error! "	\
+-		       "Please use 'swiotlb=force'\n");	\
+-		BUG();					\
+-	}						\
+-} while (0)
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++static __initdata void *dma32_bootmem_ptr;
++static unsigned long dma32_bootmem_size __initdata = (128ULL<<20);
+ 
+-static int check_pages_physically_contiguous(unsigned long pfn, 
+-					     unsigned int offset,
+-					     size_t length)
++static int __init parse_dma32_size_opt(char *p)
+ {
+-	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;
++	if (!p)
++		return -EINVAL;
++	dma32_bootmem_size = memparse(p, &p);
++	return 0;
+ }
++early_param("dma32_size", parse_dma32_size_opt);
+ 
+-int range_straddles_page_boundary(paddr_t p, size_t size)
++void __init dma32_reserve_bootmem(void)
+ {
+-	unsigned long pfn = p >> PAGE_SHIFT;
+-	unsigned int offset = p & ~PAGE_MASK;
++	unsigned long size, align;
++	if (end_pfn <= MAX_DMA32_PFN)
++		return;
+ 
+-	return ((offset + size > PAGE_SIZE) &&
+-		!check_pages_physically_contiguous(pfn, offset, size));
++	align = 64ULL<<20;
++	size = round_up(dma32_bootmem_size, align);
++	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
++				 __pa(MAX_DMA_ADDRESS));
++	if (dma32_bootmem_ptr)
++		dma32_bootmem_size = size;
++	else
++		dma32_bootmem_size = 0;
+ }
+-
+-int
+-dma_map_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+-	   enum dma_data_direction direction)
++static void __init dma32_free_bootmem(void)
+ {
+-	int i, rc;
++	int node;
++
++	if (end_pfn <= MAX_DMA32_PFN)
++		return;
+ 
+-	BUG_ON(!valid_dma_direction(direction));
+-	WARN_ON(nents == 0 || sgl->length == 0);
++	if (!dma32_bootmem_ptr)
++		return;
+ 
+-	if (swiotlb) {
+-		rc = swiotlb_map_sg(hwdev, sgl, nents, direction);
+-	} else {
+-		struct scatterlist *sg;
+-
+-		for_each_sg(sgl, sg, nents, i) {
+-			BUG_ON(!sg_page(sg));
+-			sg->dma_address =
+-				gnttab_dma_map_page(sg_page(sg)) + sg->offset;
+-			sg->dma_length  = sg->length;
+-			IOMMU_BUG_ON(address_needs_mapping(
+-				hwdev, sg->dma_address));
+-			IOMMU_BUG_ON(range_straddles_page_boundary(
+-				page_to_pseudophys(sg_page(sg)) + sg->offset,
+-				sg->length));
+-		}
+-		rc = nents;
+-	}
++	for_each_online_node(node)
++		free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr),
++				  dma32_bootmem_size);
+ 
+-	flush_write_buffers();
+-	return rc;
++	dma32_bootmem_ptr = NULL;
++	dma32_bootmem_size = 0;
+ }
+-EXPORT_SYMBOL(dma_map_sg);
++#else
++#define dma32_free_bootmem() ((void)0)
++#endif
+ 
+-void
+-dma_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+-	     enum dma_data_direction direction)
+-{
+-	int i;
++static const struct dma_mapping_ops swiotlb_dma_ops = {
++	.mapping_error = swiotlb_dma_mapping_error,
++	.map_single = swiotlb_map_single_phys,
++	.unmap_single = swiotlb_unmap_single,
++	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
++	.sync_single_for_device = swiotlb_sync_single_for_device,
++	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
++	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
++	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
++	.sync_sg_for_device = swiotlb_sync_sg_for_device,
++	.map_sg = swiotlb_map_sg,
++	.unmap_sg = swiotlb_unmap_sg,
++	.dma_supported = swiotlb_dma_supported
++};
+ 
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (swiotlb)
+-		swiotlb_unmap_sg(hwdev, sgl, nents, direction);
+-	else {
+-		struct scatterlist *sg;
++void __init pci_iommu_alloc(void)
++{
++	/* free the range so iommu could get some range less than 4G */
++	dma32_free_bootmem();
++	/*
++	 * The order of these functions is important for
++	 * fall-back/fail-over reasons
++	 */
++#ifdef CONFIG_GART_IOMMU
++	gart_iommu_hole_init();
++#endif
+ 
+-		for_each_sg(sgl, sg, nents, i)
+-			gnttab_dma_unmap_page(sg->dma_address);
+-	}
+-}
+-EXPORT_SYMBOL(dma_unmap_sg);
++#ifdef CONFIG_CALGARY_IOMMU
++	detect_calgary();
++#endif
+ 
+-#ifdef CONFIG_HIGHMEM
+-dma_addr_t
+-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+-	     size_t size, enum dma_data_direction direction)
+-{
+-	dma_addr_t dma_addr;
++	detect_intel_iommu();
+ 
+-	BUG_ON(!valid_dma_direction(direction));
++#ifdef CONFIG_SWIOTLB
++	swiotlb_init();
+ 	if (swiotlb) {
+-		dma_addr = swiotlb_map_page(
+-			dev, page, offset, size, direction);
+-	} else {
+-		dma_addr = gnttab_dma_map_page(page) + offset;
+-		IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr));
++		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
++		dma_ops = &swiotlb_dma_ops;
+ 	}
+-
+-	return dma_addr;
++#endif
+ }
+-EXPORT_SYMBOL(dma_map_page);
+ 
+-void
+-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+-	       enum dma_data_direction direction)
++/*
++ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
++ * documentation.
++ */
++static __init int iommu_setup(char *p)
+ {
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (swiotlb)
+-		swiotlb_unmap_page(dev, dma_address, size, direction);
+-	else
+-		gnttab_dma_unmap_page(dma_address);
+-}
+-EXPORT_SYMBOL(dma_unmap_page);
+-#endif /* CONFIG_HIGHMEM */
++	iommu_merge = 1;
+ 
+-int
+-dma_mapping_error(dma_addr_t dma_addr)
+-{
+-	if (swiotlb)
+-		return swiotlb_dma_mapping_error(dma_addr);
+-	return 0;
+-}
+-EXPORT_SYMBOL(dma_mapping_error);
++	if (!p)
++		return -EINVAL;
+ 
+-int
+-dma_supported(struct device *dev, u64 mask)
+-{
+-	if (swiotlb)
+-		return swiotlb_dma_supported(dev, mask);
+-	/*
+-	 * By default we'll BUG when an infeasible DMA is requested, and
+-	 * request swiotlb=force (see IOMMU_BUG_ON).
+-	 */
+-	return 1;
+-}
+-EXPORT_SYMBOL(dma_supported);
++	while (*p) {
++		if (!strncmp(p, "off", 3))
++			no_iommu = 1;
++		/* gart_parse_options has more force support */
++		if (!strncmp(p, "force", 5))
++			force_iommu = 1;
++		if (!strncmp(p, "noforce", 7)) {
++			iommu_merge = 0;
++			force_iommu = 0;
++		}
+ 
+-void *dma_alloc_coherent(struct device *dev, size_t size,
+-			   dma_addr_t *dma_handle, gfp_t gfp)
+-{
+-	void *ret;
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-	unsigned int order = get_order(size);
+-	unsigned long vstart;
+-	u64 mask;
++		if (!strncmp(p, "biomerge", 8)) {
++			iommu_bio_merge = 4096;
++			iommu_merge = 1;
++			force_iommu = 1;
++		}
++		if (!strncmp(p, "panic", 5))
++			panic_on_overflow = 1;
++		if (!strncmp(p, "nopanic", 7))
++			panic_on_overflow = 0;
++		if (!strncmp(p, "merge", 5)) {
++			iommu_merge = 1;
++			force_iommu = 1;
++		}
++		if (!strncmp(p, "nomerge", 7))
++			iommu_merge = 0;
++		if (!strncmp(p, "forcesac", 8))
++			iommu_sac_force = 1;
++		if (!strncmp(p, "allowdac", 8))
++			forbid_dac = 0;
++		if (!strncmp(p, "nodac", 5))
++			forbid_dac = -1;
++		if (!strncmp(p, "usedac", 6)) {
++			forbid_dac = -1;
++			return 1;
++		}
++#ifdef CONFIG_SWIOTLB
++		if (!strncmp(p, "soft", 4))
++			swiotlb = 1;
++#endif
+ 
+-	/* ignore region specifiers */
+-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
++#ifdef CONFIG_GART_IOMMU
++		gart_parse_options(p);
++#endif
+ 
+-	if (mem) {
+-		int page = bitmap_find_free_region(mem->bitmap, mem->size,
+-						     order);
+-		if (page >= 0) {
+-			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
+-			ret = mem->virt_base + (page << PAGE_SHIFT);
+-			memset(ret, 0, size);
+-			return ret;
+-		}
+-		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+-			return NULL;
++#ifdef CONFIG_CALGARY_IOMMU
++		if (!strncmp(p, "calgary", 7))
++			use_calgary = 1;
++#endif /* CONFIG_CALGARY_IOMMU */
++
++		p += strcspn(p, ",");
++		if (*p == ',')
++			++p;
+ 	}
++	return 0;
++}
++early_param("iommu", iommu_setup);
+ 
+-	vstart = __get_free_pages(gfp, order);
+-	ret = (void *)vstart;
++static int check_pages_physically_contiguous(unsigned long pfn,
++					     unsigned int offset,
++					     size_t length)
++{
++	unsigned long next_mfn;
++	int i;
++	int nr_pages;
+ 
+-	if (dev != NULL && dev->coherent_dma_mask)
+-		mask = dev->coherent_dma_mask;
+-	else
+-		mask = 0xffffffff;
++	next_mfn = pfn_to_mfn(pfn);
++	nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT;
+ 
+-	if (ret != NULL) {
+-		if (xen_create_contiguous_region(vstart, order,
+-						 fls64(mask)) != 0) {
+-			free_pages(vstart, order);
+-			return NULL;
+-		}
+-		memset(ret, 0, size);
+-		*dma_handle = virt_to_bus(ret);
++	for (i = 1; i < nr_pages; i++) {
++		if (pfn_to_mfn(++pfn) != ++next_mfn)
++			return 0;
+ 	}
+-	return ret;
++	return 1;
+ }
+-EXPORT_SYMBOL(dma_alloc_coherent);
+ 
+-void dma_free_coherent(struct device *dev, size_t size,
+-			 void *vaddr, dma_addr_t dma_handle)
++int range_straddles_page_boundary(paddr_t p, size_t size)
+ {
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-	int order = get_order(size);
+-
+-	WARN_ON(irqs_disabled());	/* for portability */
+-	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+-		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
++	unsigned long pfn = p >> PAGE_SHIFT;
++	unsigned int offset = p & ~PAGE_MASK;
+ 
+-		bitmap_release_region(mem->bitmap, page, order);
+-	} else {
+-		xen_destroy_contiguous_region((unsigned long)vaddr, order);
+-		free_pages((unsigned long)vaddr, order);
+-	}
++	return ((offset + size > PAGE_SIZE) &&
++		!check_pages_physically_contiguous(pfn, offset, size));
+ }
+-EXPORT_SYMBOL(dma_free_coherent);
+ 
+-#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++#ifdef CONFIG_X86_32
+ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+ 				dma_addr_t device_addr, size_t size, int flags)
+ {
+@@ -324,8 +295,8 @@ EXPORT_SYMBOL(dma_declare_coherent_memor
+ void dma_release_declared_memory(struct device *dev)
+ {
+ 	struct dma_coherent_mem *mem = dev->dma_mem;
+-	
+-	if(!mem)
++
++	if (!mem)
+ 		return;
+ 	dev->dma_mem = NULL;
+ 	iounmap(mem->virt_base);
+@@ -338,8 +309,10 @@ void *dma_mark_declared_memory_occupied(
+ 					dma_addr_t device_addr, size_t size)
+ {
+ 	struct dma_coherent_mem *mem = dev->dma_mem;
+-	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ 	int pos, err;
++	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
++
++	pages >>= PAGE_SHIFT;
+ 
+ 	if (!mem)
+ 		return ERR_PTR(-EINVAL);
+@@ -351,103 +324,270 @@ void *dma_mark_declared_memory_occupied(
+ 	return mem->virt_base + (pos << PAGE_SHIFT);
+ }
+ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+-#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
+-
+-#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
+-/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+-
+-int forbid_dac;
+-EXPORT_SYMBOL(forbid_dac);
+ 
+-static __devinit void via_no_dac(struct pci_dev *dev)
++static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
++				       dma_addr_t *dma_handle, void **ret)
+ {
+-	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+-		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+-		forbid_dac = 1;
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++	int order = get_order(size);
++
++	if (mem) {
++		int page = bitmap_find_free_region(mem->bitmap, mem->size,
++						     order);
++		if (page >= 0) {
++			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
++			*ret = mem->virt_base + (page << PAGE_SHIFT);
++			memset(*ret, 0, size);
++		}
++		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
++			*ret = NULL;
+ 	}
++	return (mem != NULL);
+ }
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+ 
+-static int check_iommu(char *s)
++static int dma_release_coherent(struct device *dev, int order, void *vaddr)
+ {
+-	if (!strcmp(s, "usedac")) {
+-		forbid_dac = -1;
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++
++	if (mem && vaddr >= mem->virt_base && vaddr <
++		   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
++		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
++
++		bitmap_release_region(mem->bitmap, page, order);
+ 		return 1;
+ 	}
+ 	return 0;
+ }
+-__setup("iommu=", check_iommu);
++#else
++#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
++#define dma_release_coherent(dev, order, vaddr) (0)
++#endif /* CONFIG_X86_32 */
++
++int dma_supported(struct device *dev, u64 mask)
++{
++#ifdef CONFIG_PCI
++	if (mask > 0xffffffff && forbid_dac > 0) {
++		printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
++				 dev->bus_id);
++		return 0;
++	}
+ #endif
+ 
+-dma_addr_t
+-dma_map_single(struct device *dev, void *ptr, size_t size,
+-	       enum dma_data_direction direction)
++	if (dma_ops->dma_supported)
++		return dma_ops->dma_supported(dev, mask);
++
++	/* Copied from i386. Doesn't make much sense, because it will
++	   only work for pci_alloc_coherent.
++	   The caller just has to use GFP_DMA in this case. */
++	if (mask < DMA_24BIT_MASK)
++		return 0;
++
++	/* Tell the device to use SAC when IOMMU force is on.  This
++	   allows the driver to use cheaper accesses in some cases.
++
++	   Problem with this is that if we overflow the IOMMU area and
++	   return DAC as fallback address the device may not handle it
++	   correctly.
++
++	   As a special case some controllers have a 39bit address
++	   mode that is as efficient as 32bit (aic79xx). Don't force
++	   SAC for these.  Assume all masks <= 40 bits are of this
++	   type. Normally this doesn't make any difference, but gives
++	   more gentle handling of IOMMU overflow. */
++	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
++		printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
++				 dev->bus_id, mask);
++		return 0;
++	}
++
++	return 1;
++}
++EXPORT_SYMBOL(dma_supported);
++
++/* Allocate DMA memory on node near device */
++static struct page *
++dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+ {
+-	dma_addr_t dma;
++	int node;
+ 
+-	BUG_ON(!valid_dma_direction(direction));
+-	WARN_ON(size == 0);
++	node = dev_to_node(dev);
+ 
+-	if (swiotlb) {
+-		dma = swiotlb_map_single(dev, ptr, size, direction);
+-	} else {
+-		dma = gnttab_dma_map_page(virt_to_page(ptr)) +
+-		      offset_in_page(ptr);
+-		IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size));
+-		IOMMU_BUG_ON(address_needs_mapping(dev, dma));
+-	}
+-
+-	flush_write_buffers();
+-	return dma;
+-}
+-EXPORT_SYMBOL(dma_map_single);
+-
+-void
+-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+-		 enum dma_data_direction direction)
+-{
+-	BUG_ON(!valid_dma_direction(direction));
+-	if (swiotlb)
+-		swiotlb_unmap_single(dev, dma_addr, size, direction);
+-	else
+-		gnttab_dma_unmap_page(dma_addr);
++	return alloc_pages_node(node, gfp, order);
+ }
+-EXPORT_SYMBOL(dma_unmap_single);
+ 
+-void
+-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+-			enum dma_data_direction direction)
++/*
++ * Allocate memory for a coherent mapping.
++ */
++void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++		   gfp_t gfp)
++{
++	void *memory = NULL;
++	struct page *page;
++	unsigned long dma_mask = 0;
++	int noretry = 0;
++	unsigned int order = get_order(size);
++
++	/* ignore region specifiers */
++	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
++
++	if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
++		return memory;
++
++	if (!dev) {
++		dev = &fallback_dev;
++		gfp |= GFP_DMA;
++	}
++	dma_mask = dev->coherent_dma_mask;
++	if (dma_mask == 0)
++		dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK;
++
++	/* Device not DMA able */
++	if (dev->dma_mask == NULL)
++		return NULL;
++
++#ifdef CONFIG_XEN
++	gfp &= ~(__GFP_DMA | __GFP_DMA32);
++#else
++	/* Don't invoke OOM killer or retry in lower 16MB DMA zone */
++	if (gfp & __GFP_DMA)
++		noretry = 1;
++
++#ifdef CONFIG_X86_64
++	/* Why <=? Even when the mask is smaller than 4GB it is often
++	   larger than 16MB and in this case we have a chance of
++	   finding fitting memory in the next higher zone first. If
++	   not retry with true GFP_DMA. -AK */
++	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
++		gfp |= GFP_DMA32;
++#endif
++
++ again:
++#endif
++	page = dma_alloc_pages(dev,
++		noretry ? gfp | __GFP_NORETRY : gfp, order);
++	if (page == NULL)
++		return NULL;
++
++#ifndef CONFIG_XEN
++	{
++		int high, mmu;
++		dma_addr_t bus = page_to_phys(page);
++		memory = page_address(page);
++		high = (bus + size) >= dma_mask;
++		mmu = high;
++		if (force_iommu && !(gfp & GFP_DMA))
++			mmu = 1;
++		else if (high) {
++			free_pages((unsigned long)memory, order);
++
++			/* Don't use the 16MB ZONE_DMA unless absolutely
++			   needed. It's better to use remapping first. */
++			if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
++				gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
++				goto again;
++			}
++
++			/* Let low level make its own zone decisions */
++			gfp &= ~(GFP_DMA32|GFP_DMA);
++
++			if (dma_ops->alloc_coherent)
++				return dma_ops->alloc_coherent(dev, size,
++							   dma_handle, gfp);
++			return NULL;
++		}
++
++		memset(memory, 0, size);
++		if (!mmu) {
++			*dma_handle = bus;
++			return memory;
++		}
++	}
++
++	if (dma_ops->alloc_coherent) {
++		free_pages((unsigned long)memory, order);
++		gfp &= ~(GFP_DMA|GFP_DMA32);
++		return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
++	}
++
++	if (dma_ops->map_simple) {
++		*dma_handle = dma_ops->map_simple(dev, virt_to_bus(memory),
++					      size,
++					      PCI_DMA_BIDIRECTIONAL);
++		if (*dma_handle != bad_dma_address)
++			return memory;
++	}
++#else
++	memory = page_address(page);
++	if (xen_create_contiguous_region((unsigned long)memory, order,
++					 fls64(dma_mask)) == 0) {
++		memset(memory, 0, size);
++		*dma_handle = virt_to_bus(memory);
++		return memory;
++	}
++#endif
++
++	if (panic_on_overflow)
++		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",
++		      (unsigned long)size);
++	free_pages((unsigned long)memory, order);
++	return NULL;
++}
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++/*
++ * Unmap coherent memory.
++ * The caller must ensure that the device has finished accessing the mapping.
++ */
++void dma_free_coherent(struct device *dev, size_t size,
++			 void *vaddr, dma_addr_t bus)
+ {
+-	if (swiotlb)
+-		swiotlb_sync_single_for_cpu(dev, dma_handle, size, direction);
++	int order = get_order(size);
++	WARN_ON(irqs_disabled());	/* for portability */
++	if (dma_release_coherent(dev, order, vaddr))
++		return;
++#ifndef CONFIG_XEN
++	if (dma_ops->unmap_single)
++		dma_ops->unmap_single(dev, bus, size, 0);
++#endif
++	xen_destroy_contiguous_region((unsigned long)vaddr, order);
++	free_pages((unsigned long)vaddr, order);
+ }
+-EXPORT_SYMBOL(dma_sync_single_for_cpu);
++EXPORT_SYMBOL(dma_free_coherent);
+ 
+-void
+-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+-                           enum dma_data_direction direction)
++static int __init pci_iommu_init(void)
+ {
+-	if (swiotlb)
+-		swiotlb_sync_single_for_device(dev, dma_handle, size, direction);
++#ifdef CONFIG_CALGARY_IOMMU
++	calgary_iommu_init();
++#endif
++
++	intel_iommu_init();
++
++#ifdef CONFIG_GART_IOMMU
++	gart_iommu_init();
++#endif
++
++	no_iommu_init();
++	return 0;
+ }
+-EXPORT_SYMBOL(dma_sync_single_for_device);
+ 
+-void
+-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+-		    enum dma_data_direction direction)
++void pci_iommu_shutdown(void)
+ {
+-	if (swiotlb)
+-		swiotlb_sync_sg_for_cpu(dev,sg,nelems,direction);
+-	flush_write_buffers();
++	gart_iommu_shutdown();
+ }
+-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
++/* Must execute after PCI subsystem */
++fs_initcall(pci_iommu_init);
++
++#ifdef CONFIG_PCI
++/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+ 
+-void
+-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+-		    enum dma_data_direction direction)
++static __devinit void via_no_dac(struct pci_dev *dev)
+ {
+-	if (swiotlb)
+-		swiotlb_sync_sg_for_device(dev,sg,nelems,direction);
+-	flush_write_buffers();
++	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
++		printk(KERN_INFO "PCI: VIA PCI bridge detected."
++				 "Disabling DAC.\n");
++		forbid_dac = 1;
++	}
+ }
+-EXPORT_SYMBOL(dma_sync_sg_for_device);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,103 @@
++#include <linux/dma-mapping.h>
++#include <linux/dmar.h>
++#include <linux/bootmem.h>
++#include <linux/pci.h>
++
++#include <xen/gnttab.h>
++
++#include <asm/proto.h>
++#include <asm/dma.h>
++#include <asm/swiotlb.h>
++#include <asm/tlbflush.h>
++#include <asm/gnttab_dma.h>
++#include <asm/bug.h>
++
++#define IOMMU_BUG_ON(test)				\
++do {							\
++	if (unlikely(test)) {				\
++		printk(KERN_ALERT "Fatal DMA error! "	\
++		       "Please use 'swiotlb=force'\n");	\
++		BUG();					\
++	}						\
++} while (0)
++
++static int
++gnttab_map_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
++	      int direction)
++{
++	unsigned int i;
++	struct scatterlist *sg;
++
++	WARN_ON(nents == 0 || sgl->length == 0);
++
++	for_each_sg(sgl, sg, nents, i) {
++		BUG_ON(!sg_page(sg));
++		sg->dma_address =
++			gnttab_dma_map_page(sg_page(sg)) + sg->offset;
++		sg->dma_length  = sg->length;
++		IOMMU_BUG_ON(address_needs_mapping(
++			hwdev, sg->dma_address));
++		IOMMU_BUG_ON(range_straddles_page_boundary(
++			page_to_pseudophys(sg_page(sg)) + sg->offset,
++			sg->length));
++	}
++
++	return nents;
++}
++
++static void
++gnttab_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
++		int direction)
++{
++	unsigned int i;
++	struct scatterlist *sg;
++
++	for_each_sg(sgl, sg, nents, i)
++		gnttab_dma_unmap_page(sg->dma_address);
++}
++
++static dma_addr_t
++gnttab_map_single(struct device *dev, phys_addr_t paddr, size_t size,
++		  int direction)
++{
++	dma_addr_t dma;
++
++	WARN_ON(size == 0);
++
++	dma = gnttab_dma_map_page(pfn_to_page(paddr >> PAGE_SHIFT)) +
++	      offset_in_page(paddr);
++	IOMMU_BUG_ON(range_straddles_page_boundary(paddr, size));
++	IOMMU_BUG_ON(address_needs_mapping(dev, dma));
++
++	return dma;
++}
++
++static void
++gnttab_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++		    int direction)
++{
++	gnttab_dma_unmap_page(dma_addr);
++}
++
++static int nommu_mapping_error(dma_addr_t dma_addr)
++{
++	return (dma_addr == bad_dma_address);
++}
++
++static const struct dma_mapping_ops nommu_dma_ops = {
++	.map_single = gnttab_map_single,
++	.unmap_single = gnttab_unmap_single,
++	.map_sg = gnttab_map_sg,
++	.unmap_sg = gnttab_unmap_sg,
++	.dma_supported = swiotlb_dma_supported,
++	.mapping_error = nommu_mapping_error
++};
++
++void __init no_iommu_init(void)
++{
++	if (dma_ops)
++		return;
++
++	force_iommu = 0; /* no HW IOMMU */
++	dma_ops = &nommu_dma_ops;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/process-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,188 @@
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/pm.h>
++
++struct kmem_cache *task_xstate_cachep;
++
++int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
++{
++	*dst = *src;
++	if (src->thread.xstate) {
++		dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
++						      GFP_KERNEL);
++		if (!dst->thread.xstate)
++			return -ENOMEM;
++		WARN_ON((unsigned long)dst->thread.xstate & 15);
++		memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
++	}
++	return 0;
++}
++
++void free_thread_xstate(struct task_struct *tsk)
++{
++	if (tsk->thread.xstate) {
++		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
++		tsk->thread.xstate = NULL;
++	}
++}
++
++void free_thread_info(struct thread_info *ti)
++{
++	free_thread_xstate(ti->task);
++	free_pages((unsigned long)ti, get_order(THREAD_SIZE));
++}
++
++void arch_task_cache_init(void)
++{
++        task_xstate_cachep =
++        	kmem_cache_create("task_xstate", xstate_size,
++				  __alignof__(union thread_xstate),
++				  SLAB_PANIC, NULL);
++}
++
++static void do_nothing(void *unused)
++{
++}
++
++/*
++ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
++ * pm_idle and update to new pm_idle value. Required while changing pm_idle
++ * handler on SMP systems.
++ *
++ * Caller must have changed pm_idle to the new value before the call. Old
++ * pm_idle value will not be used by any CPU after the return of this function.
++ */
++void cpu_idle_wait(void)
++{
++	smp_mb();
++	/* kick all the CPUs so that they exit out of pm_idle */
++	smp_call_function(do_nothing, NULL, 0, 1);
++}
++EXPORT_SYMBOL_GPL(cpu_idle_wait);
++
++#ifndef CONFIG_XEN
++/*
++ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
++ * which can obviate IPI to trigger checking of need_resched.
++ * We execute MONITOR against need_resched and enter optimized wait state
++ * through MWAIT. Whenever someone changes need_resched, we would be woken
++ * up from MWAIT (without an IPI).
++ *
++ * New with Core Duo processors, MWAIT can take some hints based on CPU
++ * capability.
++ */
++void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
++{
++	if (!need_resched()) {
++		__monitor((void *)&current_thread_info()->flags, 0, 0);
++		smp_mb();
++		if (!need_resched())
++			__mwait(ax, cx);
++	}
++}
++
++/* Default MONITOR/MWAIT with no hints, used for default C1 state */
++static void mwait_idle(void)
++{
++	if (!need_resched()) {
++		__monitor((void *)&current_thread_info()->flags, 0, 0);
++		smp_mb();
++		if (!need_resched())
++			__sti_mwait(0, 0);
++		else
++			local_irq_enable();
++	} else
++		local_irq_enable();
++}
++#endif
++
++/*
++ * On SMP it's slightly faster (but much more power-consuming!)
++ * to poll the ->work.need_resched flag instead of waiting for the
++ * cross-CPU IPI to arrive. Use this option with caution.
++ */
++static void poll_idle(void)
++{
++	local_irq_enable();
++	cpu_relax();
++}
++
++#ifndef CONFIG_XEN
++/*
++ * mwait selection logic:
++ *
++ * It depends on the CPU. For AMD CPUs that support MWAIT this is
++ * wrong. Family 0x10 and 0x11 CPUs will enter C1 on HLT. Powersavings
++ * then depend on a clock divisor and current Pstate of the core. If
++ * all cores of a processor are in halt state (C1) the processor can
++ * enter the C1E (C1 enhanced) state. If mwait is used this will never
++ * happen.
++ *
++ * idle=mwait overrides this decision and forces the usage of mwait.
++ */
++static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
++{
++	if (force_mwait)
++		return 1;
++
++	if (c->x86_vendor == X86_VENDOR_AMD) {
++		switch(c->x86) {
++		case 0x10:
++		case 0x11:
++			return 0;
++		}
++	}
++	return 1;
++}
++#endif
++
++void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
++{
++#ifndef CONFIG_XEN
++	static int selected;
++
++	if (selected)
++		return;
++#ifdef CONFIG_X86_SMP
++	if (pm_idle == poll_idle && smp_num_siblings > 1) {
++		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
++			" performance may degrade.\n");
++	}
++#endif
++	if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
++		/*
++		 * Skip, if setup has overridden idle.
++		 * One CPU supports mwait => All CPUs supports mwait
++		 */
++		if (!pm_idle) {
++			printk(KERN_INFO "using mwait in idle threads.\n");
++			pm_idle = mwait_idle;
++		}
++	}
++	selected = 1;
++#endif
++}
++
++static int __init idle_setup(char *str)
++{
++	if (!strcmp(str, "poll")) {
++		printk("using polling idle threads.\n");
++		pm_idle = poll_idle;
++	}
++#ifndef CONFIG_XEN
++	else if (!strcmp(str, "mwait"))
++		force_mwait = 1;
++#endif
++	else
++		return -1;
++
++	boot_option_idle_override = 1;
++	return 0;
++}
++early_param("idle", idle_setup);
++
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <linux/personality.h>
+ #include <linux/tick.h>
+ #include <linux/percpu.h>
++#include <linux/prctl.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -45,7 +46,6 @@
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/desc.h>
+-#include <asm/vm86.h>
+ #ifdef CONFIG_MATH_EMULATION
+ #include <asm/math_emu.h>
+ #endif
+@@ -102,16 +102,6 @@ void enable_hlt(void)
+ 
+ EXPORT_SYMBOL(enable_hlt);
+ 
+-/*
+- * On SMP it's slightly faster (but much more power-consuming!)
+- * to poll the ->work.need_resched flag instead of waiting for the
+- * cross-CPU IPI to arrive. Use this option with caution.
+- */
+-static void poll_idle(void)
+-{
+-	cpu_relax();
+-}
+-
+ static void xen_idle(void)
+ {
+ 	current_thread_info()->status &= ~TS_POLLING;
+@@ -121,20 +111,10 @@ static void xen_idle(void)
+ 	 */
+ 	smp_mb();
+ 
+-	local_irq_disable();
+-	if (!need_resched()) {
+-		ktime_t t0, t1;
+-		u64 t0n, t1n;
+-
+-		t0 = ktime_get();
+-		t0n = ktime_to_ns(t0);
++	if (!need_resched())
+ 		safe_halt();	/* enables interrupts racelessly */
+-		local_irq_disable();
+-		t1 = ktime_get();
+-		t1n = ktime_to_ns(t1);
+-		sched_clock_idle_wakeup_event(t1n - t0n);
+-	}
+-	local_irq_enable();
++	else
++		local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+ }
+ #ifdef CONFIG_APM_MODULE
+@@ -142,7 +122,6 @@ EXPORT_SYMBOL(default_idle);
+ #endif
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-extern cpumask_t cpu_initialized;
+ static inline void play_dead(void)
+ {
+ 	idle_task_exit();
+@@ -187,6 +166,7 @@ void cpu_idle(void)
+ 			if (cpu_is_offline(cpu))
+ 				play_dead();
+ 
++			local_irq_disable();
+ 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
+ 			idle();
+ 		}
+@@ -197,44 +177,6 @@ void cpu_idle(void)
+ 	}
+ }
+ 
+-static void do_nothing(void *unused)
+-{
+-}
+-
+-/*
+- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+- * pm_idle and update to new pm_idle value. Required while changing pm_idle
+- * handler on SMP systems.
+- *
+- * Caller must have changed pm_idle to the new value before the call. Old
+- * pm_idle value will not be used by any CPU after the return of this function.
+- */
+-void cpu_idle_wait(void)
+-{
+-	smp_mb();
+-	/* kick all the CPUs so that they exit out of pm_idle */
+-	smp_call_function(do_nothing, NULL, 0, 1);
+-}
+-EXPORT_SYMBOL_GPL(cpu_idle_wait);
+-
+-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+-{
+-}
+-
+-static int __init idle_setup(char *str)
+-{
+-	if (!strcmp(str, "poll")) {
+-		printk("using polling idle threads.\n");
+-		pm_idle = poll_idle;
+-	}
+-	else
+-		return -1;
+-
+-	boot_option_idle_override = 1;
+-	return 0;
+-}
+-early_param("idle", idle_setup);
+-
+ void __show_registers(struct pt_regs *regs, int all)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+@@ -260,7 +202,7 @@ void __show_registers(struct pt_regs *re
+ 			init_utsname()->version);
+ 
+ 	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+-			0xffff & regs->cs, regs->ip, regs->flags,
++			(u16)regs->cs, regs->ip, regs->flags,
+ 			smp_processor_id());
+ 	print_symbol("EIP is at %s\n", regs->ip);
+ 
+@@ -269,8 +211,7 @@ void __show_registers(struct pt_regs *re
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+ 		regs->si, regs->di, regs->bp, sp);
+ 	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+-	       regs->ds & 0xffff, regs->es & 0xffff,
+-	       regs->fs & 0xffff, gs, ss);
++	       (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
+ 
+ 	if (!all)
+ 		return;
+@@ -367,6 +308,7 @@ void flush_thread(void)
+ 	/*
+ 	 * Forget coprocessor state..
+ 	 */
++	tsk->fpu_counter = 0;
+ 	clear_fpu(tsk);
+ 	clear_used_math();
+ }
+@@ -437,11 +379,30 @@ int copy_thread(int nr, unsigned long cl
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_SECCOMP
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++	__asm__("movl %0, %%gs" :: "r"(0));
++	regs->fs		= 0;
++	set_fs(USER_DS);
++	regs->ds		= __USER_DS;
++	regs->es		= __USER_DS;
++	regs->ss		= __USER_DS;
++	regs->cs		= __USER_CS;
++	regs->ip		= new_ip;
++	regs->sp		= new_sp;
++	/*
++	 * Free the old FP and other extended state
++	 */
++	free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
+ static void hard_disable_TSC(void)
+ {
+ 	write_cr4(read_cr4() | X86_CR4_TSD);
+ }
++
+ void disable_TSC(void)
+ {
+ 	preempt_disable();
+@@ -453,11 +414,47 @@ void disable_TSC(void)
+ 		hard_disable_TSC();
+ 	preempt_enable();
+ }
++
+ static void hard_enable_TSC(void)
+ {
+ 	write_cr4(read_cr4() & ~X86_CR4_TSD);
+ }
+-#endif /* CONFIG_SECCOMP */
++
++static void enable_TSC(void)
++{
++	preempt_disable();
++	if (test_and_clear_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_enable_TSC();
++	preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++	unsigned int val;
++
++	if (test_thread_flag(TIF_NOTSC))
++		val = PR_TSC_SIGSEGV;
++	else
++		val = PR_TSC_ENABLE;
++
++	return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++	if (val == PR_TSC_SIGSEGV)
++		disable_TSC();
++	else if (val == PR_TSC_ENABLE)
++		enable_TSC();
++	else
++		return -EINVAL;
++
++	return 0;
++}
+ 
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+@@ -473,12 +470,12 @@ __switch_to_xtra(struct task_struct *pre
+ 		/* we clear debugctl to make sure DS
+ 		 * is not in use when we change it */
+ 		debugctl = 0;
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		update_debugctlmsr(0);
+ 		wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
+ 	}
+ 
+ 	if (next->debugctlmsr != debugctl)
+-		wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
++		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ 		set_debugreg(next->debugreg0, 0);
+@@ -490,7 +487,6 @@ __switch_to_xtra(struct task_struct *pre
+ 		set_debugreg(next->debugreg7, 7);
+ 	}
+ 
+-#ifdef CONFIG_SECCOMP
+ 	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+ 	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+ 		/* prev and next are different */
+@@ -499,7 +495,6 @@ __switch_to_xtra(struct task_struct *pre
+ 		else
+ 			hard_enable_TSC();
+ 	}
+-#endif
+ 
+ #ifdef X86_BTS
+ 	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+@@ -637,7 +632,7 @@ struct task_struct * __switch_to(struct 
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+ 	if (next_p->fpu_counter > 5)
+-		prefetch(&next->i387.fxsave);
++		prefetch(next->xstate);
+ 
+ 	/*
+ 	 * Now maybe handle debug registers
+@@ -658,8 +653,11 @@ struct task_struct * __switch_to(struct 
+ 	/* If the task has used fpu the last 5 timeslices, just do a full
+ 	 * restore of the math state immediately to avoid the trap; the
+ 	 * chances of needing FPU soon are obviously high now
++	 *
++	 * tsk_used_math() checks prevent calling math_state_restore(),
++	 * which can sleep in the case of !tsk_used_math()
+ 	 */
+-	if (next_p->fpu_counter > 5)
++	if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
+ 		math_state_restore();
+ 
+ 	/*
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+ #include <linux/tick.h>
++#include <linux/prctl.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -102,17 +103,6 @@ void exit_idle(void)
+ 	__exit_idle();
+ }
+ 
+-/*
+- * On SMP it's slightly faster (but much more power-consuming!)
+- * to poll the ->need_resched flag instead of waiting for the
+- * cross-CPU IPI to arrive. Use this option with caution.
+- */
+-static void poll_idle(void)
+-{
+-	local_irq_enable();
+-	cpu_relax();
+-}
+-
+ static void xen_idle(void)
+ {
+ 	current_thread_info()->status &= ~TS_POLLING;
+@@ -121,20 +111,10 @@ static void xen_idle(void)
+ 	 * test NEED_RESCHED:
+ 	 */
+ 	smp_mb();
+-	local_irq_disable();
+-	if (!need_resched()) {
+-		ktime_t t0, t1;
+-		u64 t0n, t1n;
+-
+-		t0 = ktime_get();
+-		t0n = ktime_to_ns(t0);
++	if (!need_resched())
+ 		safe_halt();	/* enables interrupts racelessly */
+-		local_irq_disable();
+-		t1 = ktime_get();
+-		t1n = ktime_to_ns(t1);
+-		sched_clock_idle_wakeup_event(t1n - t0n);
+-	}
+-	local_irq_enable();
++	else
++		local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+ }
+ 
+@@ -195,45 +175,6 @@ void cpu_idle(void)
+ 	}
+ }
+ 
+-static void do_nothing(void *unused)
+-{
+-}
+-
+-/*
+- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+- * pm_idle and update to new pm_idle value. Required while changing pm_idle
+- * handler on SMP systems.
+- *
+- * Caller must have changed pm_idle to the new value before the call. Old
+- * pm_idle value will not be used by any CPU after the return of this function.
+- */
+-void cpu_idle_wait(void)
+-{
+-	smp_mb();
+-	/* kick all the CPUs so that they exit out of pm_idle */
+-	smp_call_function(do_nothing, NULL, 0, 1);
+-}
+-EXPORT_SYMBOL_GPL(cpu_idle_wait);
+-
+-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+-{
+-}
+-
+-static int __init idle_setup(char *str)
+-{
+-	if (!strcmp(str, "poll")) {
+-		printk("using polling idle threads.\n");
+-		pm_idle = poll_idle;
+-	} else if (!strcmp(str, "mwait"))
+-		force_mwait = 1;
+-	else
+-		return -1;
+-
+-	boot_option_idle_override = 1;
+-	return 0;
+-}
+-early_param("idle", idle_setup);
+-
+ /* Prints also some state that isn't saved in the pt_regs */
+ void __show_regs(struct pt_regs * regs)
+ {
+@@ -360,6 +301,7 @@ void flush_thread(void)
+ 	/*
+ 	 * Forget coprocessor state..
+ 	 */
++	tsk->fpu_counter = 0;
+ 	clear_fpu(tsk);
+ 	clear_used_math();
+ }
+@@ -472,6 +414,83 @@ out:
+ 	return err;
+ }
+ 
++void
++start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
++{
++	asm volatile("movl %0, %%fs; movl %0, %%es; movl %0, %%ds" :: "r"(0));
++	load_gs_index(0);
++	regs->ip		= new_ip;
++	regs->sp		= new_sp;
++	write_pda(oldrsp, new_sp);
++	regs->cs		= __USER_CS;
++	regs->ss		= __USER_DS;
++	regs->flags		= 0x200;
++	set_fs(USER_DS);
++	/*
++	 * Free the old FP and other extended state
++	 */
++	free_thread_xstate(current);
++}
++EXPORT_SYMBOL_GPL(start_thread);
++
++static void hard_disable_TSC(void)
++{
++	write_cr4(read_cr4() | X86_CR4_TSD);
++}
++
++void disable_TSC(void)
++{
++	preempt_disable();
++	if (!test_and_set_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_disable_TSC();
++	preempt_enable();
++}
++
++static void hard_enable_TSC(void)
++{
++	write_cr4(read_cr4() & ~X86_CR4_TSD);
++}
++
++static void enable_TSC(void)
++{
++	preempt_disable();
++	if (test_and_clear_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_enable_TSC();
++	preempt_enable();
++}
++
++int get_tsc_mode(unsigned long adr)
++{
++	unsigned int val;
++
++	if (test_thread_flag(TIF_NOTSC))
++		val = PR_TSC_SIGSEGV;
++	else
++		val = PR_TSC_ENABLE;
++
++	return put_user(val, (unsigned int __user *)adr);
++}
++
++int set_tsc_mode(unsigned int val)
++{
++	if (val == PR_TSC_SIGSEGV)
++		disable_TSC();
++	else if (val == PR_TSC_ENABLE)
++		enable_TSC();
++	else
++		return -EINVAL;
++
++	return 0;
++}
++
+ /*
+  * This special macro can be used to load a debugging register
+  */
+@@ -491,12 +510,12 @@ static inline void __switch_to_xtra(stru
+ 		/* we clear debugctl to make sure DS
+ 		 * is not in use when we change it */
+ 		debugctl = 0;
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		update_debugctlmsr(0);
+ 		wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
+ 	}
+ 
+ 	if (next->debugctlmsr != debugctl)
+-		wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
++		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ 		loaddebug(next, 0);
+@@ -508,6 +527,15 @@ static inline void __switch_to_xtra(stru
+ 		loaddebug(next, 7);
+ 	}
+ 
++	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
++	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
++		/* prev and next are different */
++		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
++			hard_disable_TSC();
++		else
++			hard_enable_TSC();
++	}
++
+ #ifdef X86_BTS
+ 	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+ 		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
+@@ -547,7 +575,7 @@ __switch_to(struct task_struct *prev_p, 
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+ 	if (next_p->fpu_counter>5)
+-		prefetch(&next->i387.fxsave);
++		prefetch(next->xstate);
+ 
+ 	/*
+ 	 * This is basically '__unlazy_fpu', except that we queue a
+@@ -680,8 +708,11 @@ __switch_to(struct task_struct *prev_p, 
+ 	/* If the task has used fpu the last 5 timeslices, just do a full
+ 	 * restore of the math state immediately to avoid the trap; the
+ 	 * chances of needing FPU soon are obviously high now
++	 *
++	 * tsk_used_math() checks prevent calling math_state_restore(),
++	 * which can sleep in the case of !tsk_used_math()
+ 	 */
+-	if (next_p->fpu_counter>5)
++	if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
+ 		math_state_restore();
+ 	return prev_p;
+ }
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,141 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/percpu.h>
++#include <asm/smp.h>
++#include <asm/percpu.h>
++#include <asm/sections.h>
++#include <asm/processor.h>
++#include <asm/setup.h>
++#include <asm/topology.h>
++#include <asm/mpspec.h>
++#include <asm/apicdef.h>
++
++#ifdef CONFIG_X86_LOCAL_APIC
++unsigned int num_processors;
++unsigned disabled_cpus __cpuinitdata;
++/* Processor that is doing the boot up */
++unsigned int boot_cpu_physical_apicid = -1U;
++EXPORT_SYMBOL(boot_cpu_physical_apicid);
++
++DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++
++/* Bitmask of physically existing CPUs */
++physid_mask_t phys_cpu_present_map;
++#endif
++
++#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP)
++/*
++ * Copy data used in early init routines from the initial arrays to the
++ * per cpu data areas.  These arrays then become expendable and the
++ * *_early_ptr's are zeroed indicating that the static arrays are gone.
++ */
++static void __init setup_per_cpu_maps(void)
++{
++#ifndef CONFIG_XEN
++	int cpu;
++
++	for_each_possible_cpu(cpu) {
++		per_cpu(x86_cpu_to_apicid, cpu) = x86_cpu_to_apicid_init[cpu];
++		per_cpu(x86_bios_cpu_apicid, cpu) =
++						x86_bios_cpu_apicid_init[cpu];
++#ifdef CONFIG_NUMA
++		per_cpu(x86_cpu_to_node_map, cpu) =
++						x86_cpu_to_node_map_init[cpu];
++#endif
++	}
++
++	/* indicate the early static arrays will soon be gone */
++	x86_cpu_to_apicid_early_ptr = NULL;
++	x86_bios_cpu_apicid_early_ptr = NULL;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = NULL;
++#endif
++#endif
++}
++
++#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
++cpumask_t *cpumask_of_cpu_map __read_mostly;
++EXPORT_SYMBOL(cpumask_of_cpu_map);
++
++/* requires nr_cpu_ids to be initialized */
++static void __init setup_cpumask_of_cpu(void)
++{
++	int i;
++
++	/* alloc_bootmem zeroes memory */
++	cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
++	for (i = 0; i < nr_cpu_ids; i++)
++		cpu_set(i, cpumask_of_cpu_map[i]);
++}
++#else
++static inline void setup_cpumask_of_cpu(void) { }
++#endif
++
++#ifdef CONFIG_X86_32
++/*
++ * Great future not-so-futuristic plan: make i386 and x86_64 do it
++ * the same way
++ */
++unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
++EXPORT_SYMBOL(__per_cpu_offset);
++#endif
++
++/*
++ * 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, highest_cpu = 0;
++	unsigned long size;
++
++#ifdef CONFIG_HOTPLUG_CPU
++	prefill_possible_map();
++#endif
++
++	/* Copy section for each CPU (we discard the original) */
++	size = PERCPU_ENOUGH_ROOM;
++	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n",
++			  size);
++
++	for_each_possible_cpu(i) {
++		char *ptr;
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++		ptr = alloc_bootmem_pages(size);
++#else
++		int node = early_cpu_to_node(i);
++		if (!node_online(node) || !NODE_DATA(node)) {
++			ptr = alloc_bootmem_pages(size);
++			printk(KERN_INFO
++			       "cpu %d has no node or node-local memory\n", i);
++		}
++		else
++			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
++#endif
++		if (!ptr)
++			panic("Cannot allocate cpu data for CPU %d\n", i);
++#ifdef CONFIG_X86_64
++		cpu_pda(i)->data_offset = ptr - __per_cpu_start;
++#else
++		__per_cpu_offset[i] = ptr - __per_cpu_start;
++#endif
++		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
++
++		highest_cpu = i;
++	}
++
++	nr_cpu_ids = highest_cpu + 1;
++	printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
++
++	/* Setup percpu data maps */
++	setup_per_cpu_maps();
++
++	/* Setup cpumask_of_cpu map */
++	setup_cpumask_of_cpu();
++}
++
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/bitops.h>
+ #include <linux/module.h>
++#include <linux/kgdb.h>
+ #include <asm/pda.h>
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -27,6 +28,7 @@
+ #include <asm/proto.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
++#include <asm/genapic.h>
+ #ifdef CONFIG_XEN
+ #include <asm/hypervisor.h>
+ #endif
+@@ -81,8 +83,8 @@ int force_personality32 = 0; 
+ 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)
++on	PROT_READ does not imply PROT_EXEC for 32bit processes (default)
++off	PROT_READ implies PROT_EXEC
+ */
+ static int __init nonx32_setup(char *str)
+ {
+@@ -94,85 +96,6 @@ static int __init nonx32_setup(char *str
+ }
+ __setup("noexec32=", nonx32_setup);
+ 
+-/*
+- * Copy data used in early init routines from the initial arrays to the
+- * per cpu data areas.  These arrays then become expendable and the
+- * *_early_ptr's are zeroed indicating that the static arrays are gone.
+- */
+-static void __init setup_per_cpu_maps(void)
+-{
+-#ifndef CONFIG_XEN
+-	int cpu;
+-
+-	for_each_possible_cpu(cpu) {
+-#ifdef CONFIG_SMP
+-		if (per_cpu_offset(cpu)) {
+-#endif
+-			per_cpu(x86_cpu_to_apicid, cpu) =
+-						x86_cpu_to_apicid_init[cpu];
+-			per_cpu(x86_bios_cpu_apicid, cpu) =
+-						x86_bios_cpu_apicid_init[cpu];
+-#ifdef CONFIG_NUMA
+-			per_cpu(x86_cpu_to_node_map, cpu) =
+-						x86_cpu_to_node_map_init[cpu];
+-#endif
+-#ifdef CONFIG_SMP
+-		}
+-		else
+-			printk(KERN_NOTICE "per_cpu_offset zero for cpu %d\n",
+-									cpu);
+-#endif
+-	}
+-
+-	/* indicate the early static arrays will soon be gone */
+-	x86_cpu_to_apicid_early_ptr = NULL;
+-	x86_bios_cpu_apicid_early_ptr = NULL;
+-#ifdef CONFIG_NUMA
+-	x86_cpu_to_node_map_early_ptr = NULL;
+-#endif
+-#endif
+-}
+-
+-/*
+- * 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 = PERCPU_ENOUGH_ROOM;
+-
+-	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
+-	for_each_cpu_mask (i, cpu_possible_map) {
+-		char *ptr;
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+-		ptr = alloc_bootmem_pages(size);
+-#else
+-		int node = early_cpu_to_node(i);
+-
+-		if (!node_online(node) || !NODE_DATA(node))
+-			ptr = alloc_bootmem_pages(size);
+-		else
+-			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
+-#endif
+-		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);
+-	}
+-
+-	/* setup percpu data maps early */
+-	setup_per_cpu_maps();
+-} 
+-
+ #ifdef CONFIG_XEN
+ static void __init_refok switch_pt(int cpu)
+ {
+@@ -410,6 +333,17 @@ void __cpuinit cpu_init (void)
+ #endif
+ 	load_LDT(&init_mm.context);
+ 
++#ifdef CONFIG_KGDB
++	/*
++	 * If the kgdb is connected no debug regs should be altered.  This
++	 * is only applicable when KGDB and a KGDB I/O module are built
++	 * into the kernel and you are using early debugging with
++	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
++	 */
++	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
++		arch_kgdb_ops.correct_hw_break();
++	else {
++#endif
+ 	/*
+ 	 * Clear all 6 debug registers:
+ 	 */
+@@ -420,10 +354,17 @@ void __cpuinit cpu_init (void)
+ 	set_debugreg(0UL, 3);
+ 	set_debugreg(0UL, 6);
+ 	set_debugreg(0UL, 7);
++#ifdef CONFIG_KGDB
++	/* If the kgdb is connected no debug regs should be altered. */
++	}
++#endif
+ 
+ 	fpu_init(); 
+ 
+ 	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
+ 	if (raw_irqs_disabled())
+ 		kernel_eflags &= ~X86_EFLAGS_IF;
++
++	if (is_uv_system())
++		uv_cpu_init();
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/efi.h>
+ #include <linux/init.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/nodemask.h>
+ #include <linux/kernel.h>
+ #include <linux/percpu.h>
+@@ -49,6 +50,7 @@
+ #include <linux/pfn.h>
+ #include <linux/pci.h>
+ #include <linux/init_ohci1394_dma.h>
++#include <linux/kvm_para.h>
+ 
+ #include <video/edid.h>
+ 
+@@ -70,8 +72,9 @@
+ #include <xen/firmware.h>
+ #include <xen/xencons.h>
+ #include <setup_arch.h>
+-#include <bios_ebda.h>
++#include <asm/bios_ebda.h>
+ #include <asm/cacheflush.h>
++#include <asm/processor.h>
+ 
+ #ifdef CONFIG_XEN
+ #include <xen/interface/kexec.h>
+@@ -136,7 +139,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",
+@@ -166,6 +174,8 @@ struct cpuinfo_x86 new_cpu_data __cpuini
+ struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ EXPORT_SYMBOL(boot_cpu_data);
+ 
++unsigned int def_to_bigsmp;
++
+ #ifndef CONFIG_X86_PAE
+ unsigned long mmu_cr4_features;
+ #else
+@@ -204,7 +214,7 @@ EXPORT_SYMBOL(ist_info);
+ extern void early_cpu_init(void);
+ extern int root_mountflags;
+ 
+-unsigned long saved_videomode;
++unsigned long saved_video_mode;
+ 
+ #define RAMDISK_IMAGE_START_MASK	0x07FF
+ #define RAMDISK_PROMPT_FLAG		0x8000
+@@ -259,7 +269,7 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
+-int __initdata user_defined_memmap = 0;
++int __initdata user_defined_memmap;
+ 
+ /*
+  * "mem=nopentium" disables the 4MB page tables.
+@@ -420,20 +430,59 @@ unsigned long __init find_max_low_pfn(vo
+ }
+ 
+ #ifndef CONFIG_XEN
++#define BIOS_LOWMEM_KILOBYTES 0x413
++
+ /*
+- * workaround for Dell systems that neglect to reserve EBDA
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
+  */
+ static void __init reserve_ebda_region(void)
+ {
+-	unsigned int addr;
+-	addr = get_bios_ebda();
+-	if (addr)
+-		reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT);
++	unsigned int lowmem, ebda_addr;
++
++	/* To determine the position of the EBDA and the */
++	/* end of conventional memory, we need to look at */
++	/* the BIOS data area. In a paravirtual environment */
++	/* that area is absent. We'll just have to assume */
++	/* that the paravirt case can handle memory setup */
++	/* correctly, without our help. */
++	if (paravirt_enabled())
++		return;
++
++	/* end of low (conventional) memory */
++	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++	lowmem <<= 10;
++
++	/* start of EBDA area */
++	ebda_addr = get_bios_ebda();
++
++	/* Fixup: bios puts an EBDA in the top 64K segment */
++	/* of conventional memory, but does not adjust lowmem. */
++	if ((lowmem - ebda_addr) <= 0x10000)
++		lowmem = ebda_addr;
++
++	/* Fixup: bios does not report an EBDA at all. */
++	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++		lowmem = 0x9f000;
++
++	/* Paranoia: should never happen, but... */
++	if ((lowmem == 0) || (lowmem >= 0x100000))
++		lowmem = 0x9f000;
++
++	/* reserve all memory between lowmem and the 1MB mark */
++	reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
+ }
+ #endif
+ 
+ #ifndef CONFIG_NEED_MULTIPLE_NODES
+-void __init setup_bootmem_allocator(void);
++static void __init setup_bootmem_allocator(void);
+ static unsigned long __init setup_memory(void)
+ {
+ 	/*
+@@ -469,7 +518,7 @@ static unsigned long __init setup_memory
+ 	return max_low_pfn;
+ }
+ 
+-void __init zone_sizes_init(void)
++static void __init zone_sizes_init(void)
+ {
+ 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+ 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+@@ -523,10 +572,16 @@ static void __init reserve_crashkernel(v
+ 					(unsigned long)(crash_size >> 20),
+ 					(unsigned long)(crash_base >> 20),
+ 					(unsigned long)(total_mem >> 20));
++
++			if (reserve_bootmem(crash_base, crash_size,
++					BOOTMEM_EXCLUSIVE) < 0) {
++				printk(KERN_INFO "crashkernel reservation "
++					"failed - memory is in use\n");
++				return;
++			}
++
+ 			crashk_res.start = crash_base;
+ 			crashk_res.end   = crash_base + crash_size - 1;
+-			reserve_bootmem(crash_base, crash_size,
+-					BOOTMEM_DEFAULT);
+ 		} else
+ 			printk(KERN_INFO "crashkernel reservation failed - "
+ 					"you have to specify a base address\n");
+@@ -660,16 +715,9 @@ void __init setup_bootmem_allocator(void
+ 	 */
+ 	reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+ 
+-	/* reserve EBDA region, it's a 4K region */
++	/* reserve EBDA region */
+ 	reserve_ebda_region();
+ 
+-    /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
+-       PCI prefetch into it (errata #56). Usually the page is reserved anyways,
+-       unless you have no PS/2 mouse plugged in. */
+-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+-	    boot_cpu_data.x86 == 6)
+-	     reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
+-
+ #ifdef CONFIG_SMP
+ 	/*
+ 	 * But first pinch a few for the stack/trampoline stuff
+@@ -691,6 +739,8 @@ void __init setup_bootmem_allocator(void
+ #endif
+ 	numa_kva_reserve();
+ 	reserve_crashkernel();
++
++	reserve_ibft_region();
+ }
+ 
+ /*
+@@ -726,6 +776,18 @@ char * __init __attribute__((weak)) memo
+ 	return machine_specific_memory_setup();
+ }
+ 
++#ifdef CONFIG_NUMA
++/*
++ * In the golden day, when everything among i386 and x86_64 will be
++ * integrated, this will not live here
++ */
++void *x86_cpu_to_node_map_early_ptr;
++int x86_cpu_to_node_map_init[NR_CPUS] = {
++	[0 ... NR_CPUS-1] = NUMA_NO_NODE
++};
++DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
++#endif
++
+ /*
+  * Determine if we were loaded by an EFI loader.  If so, then we have also been
+  * passed the efi memmap, systab, etc., so we should use these data structures
+@@ -775,7 +837,7 @@ void __init setup_arch(char **cmdline_p)
+ 	copy_edid();
+ 	apm_info.bios = boot_params.apm_bios_info;
+ 	ist_info = boot_params.ist_info;
+-	saved_videomode = boot_params.hdr.vid_mode;
++	saved_video_mode = boot_params.hdr.vid_mode;
+ 	if( boot_params.sys_desc_table.length != 0 ) {
+ 		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+ 		machine_id = boot_params.sys_desc_table.table[0];
+@@ -842,15 +904,19 @@ void __init setup_arch(char **cmdline_p)
+ 		efi_init();
+ 
+ 	/* update e820 for memory not covered by WB MTRRs */
+-	find_max_pfn();
++	propagate_e820_map();
+ 	mtrr_bp_init();
+ #ifndef CONFIG_XEN
+ 	if (mtrr_trim_uncached_memory(max_pfn))
+-		find_max_pfn();
++		propagate_e820_map();
+ #endif
+ 
+ 	max_low_pfn = setup_memory();
+ 
++#ifdef CONFIG_KVM_CLOCK
++	kvmclock_init();
++#endif
++
+ #ifdef CONFIG_VMI
+ 	/*
+ 	 * Must be after max_low_pfn is determined, and before kernel
+@@ -858,6 +924,7 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ 	vmi_init();
+ #endif
++	kvm_guest_init();
+ 
+ 	/*
+ 	 * NOTE: before this point _nobody_ is allowed to allocate
+@@ -979,6 +1046,18 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	io_delay_init();
+ 
++#if defined(CONFIG_X86_SMP) && !defined(CONFIG_XEN)
++	/*
++	 * setup to use the early static init tables during kernel startup
++	 * X86_SMP will exclude sub-arches that don't deal well with it.
++	 */
++	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
++	x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
++#endif
++#endif
++
+ #ifdef CONFIG_X86_GENERICARCH
+ 	generic_apic_probe();
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -29,18 +29,22 @@
+ #include <linux/crash_dump.h>
+ #include <linux/root_dev.h>
+ #include <linux/pci.h>
++#include <asm/pci-direct.h>
+ #include <linux/efi.h>
+ #include <linux/acpi.h>
+ #include <linux/kallsyms.h>
+ #include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
+ #include <linux/mmzone.h>
+ #include <linux/kexec.h>
+ #include <linux/cpufreq.h>
+ #include <linux/dmi.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/ctype.h>
++#include <linux/sort.h>
+ #include <linux/uaccess.h>
+ #include <linux/init_ohci1394_dma.h>
++#include <linux/kvm_para.h>
+ 
+ #include <asm/mtrr.h>
+ #include <asm/uaccess.h>
+@@ -58,7 +62,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+ #include <asm/setup.h>
+-#include <asm/mach_apic.h>
+ #include <asm/numa.h>
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
+@@ -66,6 +69,9 @@
+ #include <asm/mce.h>
+ #include <asm/ds.h>
+ #include <asm/topology.h>
++#include <asm/pat.h>
++
++#include <mach_apic.h>
+ #ifdef CONFIG_XEN
+ #include <linux/percpu.h>
+ #include <xen/interface/physdev.h>
+@@ -149,7 +155,7 @@ extern int root_mountflags;
+ 
+ char __initdata command_line[COMMAND_LINE_SIZE];
+ 
+-struct resource standard_io_resources[] = {
++static struct resource standard_io_resources[] = {
+ 	{ .name = "dma1", .start = 0x00, .end = 0x1f,
+ 		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+ 	{ .name = "pic1", .start = 0x20, .end = 0x21,
+@@ -158,7 +164,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 },
+@@ -224,10 +232,10 @@ contig_initmem_init(unsigned long start_
+ 	e820_register_active_regions(0, start_pfn, end_pfn);
+ #ifdef CONFIG_XEN
+ 	if (xen_start_info->nr_pages < end_pfn)
+-		free_bootmem_with_active_regions(0, xen_start_info->nr_pages);
+-	else
++		end_pfn = xen_start_info->nr_pages;
+ #endif
+ 	free_bootmem_with_active_regions(0, end_pfn);
++	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
+ 	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+ }
+ #endif
+@@ -291,6 +299,7 @@ static void __init reserve_crashkernel(v
+ 				(unsigned long)(total_mem >> 20));
+ 		crashk_res.start = crash_base;
+ 		crashk_res.end   = crash_base + crash_size - 1;
++		insert_resource(&iomem_resource, &crashk_res);
+ 	}
+ }
+ #else
+@@ -307,6 +316,40 @@ void __attribute__((weak)) __init memory
+        machine_specific_memory_setup();
+ }
+ 
++static void __init parse_setup_data(void)
++{
++	struct setup_data *data;
++	unsigned long pa_data;
++
++	if (boot_params.hdr.version < 0x0209)
++		return;
++	pa_data = boot_params.hdr.setup_data;
++	while (pa_data) {
++		data = early_ioremap(pa_data, PAGE_SIZE);
++		switch (data->type) {
++		default:
++			break;
++		}
++#ifndef CONFIG_DEBUG_BOOT_PARAMS
++		free_early(pa_data, pa_data+sizeof(*data)+data->len);
++#endif
++		pa_data = data->next;
++		early_iounmap(data, PAGE_SIZE);
++	}
++}
++
++#ifdef CONFIG_PCI_MMCONFIG
++extern void __cpuinit fam10h_check_enable_mmcfg(void);
++extern void __init check_enable_amd_mmconf_dmi(void);
++#else
++void __cpuinit fam10h_check_enable_mmcfg(void)
++{
++}
++void __init check_enable_amd_mmconf_dmi(void)
++{
++}
++#endif
++
+ /*
+  * setup_arch - architecture-specific boot-time initializations
+  *
+@@ -390,6 +433,8 @@ void __init setup_arch(char **cmdline_p)
+ 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
++	parse_setup_data();
++
+ 	parse_early_param();
+ 
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+@@ -399,6 +444,13 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	finish_e820_parsing();
+ 
++#ifndef CONFIG_XEN
++	/* after parse_early_param, so could debug it */
++	insert_resource(&iomem_resource, &code_resource);
++	insert_resource(&iomem_resource, &data_resource);
++	insert_resource(&iomem_resource, &bss_resource);
++#endif
++
+ 	early_gart_iommu_check();
+ 
+ 	e820_register_active_regions(0, 0, -1UL);
+@@ -421,15 +473,23 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	check_efer();
+ 
+-	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
++	max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT));
+ 	if (efi_enabled)
+ 		efi_init();
+ 
++#ifndef CONFIG_XEN
++	vsmp_init();
++#endif
++
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
+ 	io_delay_init();
+ 
++#ifdef CONFIG_KVM_CLOCK
++	kvmclock_init();
++#endif
++
+ #if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ 	/* setup to use the early static init tables during kernel startup */
+ 	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
+@@ -460,9 +520,9 @@ void __init setup_arch(char **cmdline_p)
+ 	contig_initmem_init(0, end_pfn);
+ #endif
+ 
+-	early_res_to_bootmem();
+-
+ #ifndef CONFIG_XEN
++	dma32_reserve_bootmem();
++
+ #ifdef CONFIG_ACPI_SLEEP
+ 	/*
+ 	 * Reserve low memory region for sleep support.
+@@ -488,16 +548,17 @@ void __init setup_arch(char **cmdline_p)
+ 		unsigned long end_of_mem    = end_pfn << PAGE_SHIFT;
+ 
+ 		if (ramdisk_end <= end_of_mem) {
+-#ifndef CONFIG_XEN
+-			reserve_bootmem_generic(ramdisk_image, ramdisk_size);
+-#endif
++			/*
++			 * don't need to reserve again, already reserved early
++			 * in x86_64_start_kernel, and early_res_to_bootmem
++			 * convert that to reserved in bootmem
++			 */
+ 			initrd_start = ramdisk_image + PAGE_OFFSET;
+ 			initrd_end = initrd_start+ramdisk_size;
+ #ifdef CONFIG_XEN
+ 			initrd_below_start_ok = 1;
+ #endif
+ 		} else {
+-			/* Assumes everything on node 0 */
+ 			free_bootmem(ramdisk_image, ramdisk_size);
+ 			printk(KERN_ERR "initrd extends beyond end of memory "
+ 			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+@@ -507,6 +568,9 @@ void __init setup_arch(char **cmdline_p)
+ 	}
+ #endif
+ 	reserve_crashkernel();
++
++	reserve_ibft_region();
++
+ 	paging_init();
+ 	map_vsyscall();
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -634,16 +698,16 @@ void __init setup_arch(char **cmdline_p)
+ 	prefill_possible_map();
+ #endif
+ 
++	kvm_guest_init();
++
+ 	/*
+ 	 * We trust e820 completely. No explicit ROM probing in memory.
+ 	 */
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain())
+-		e820_reserve_resources(machine_e820.map, machine_e820.nr_map,
+-				       &code_resource, &data_resource, &bss_resource);
++		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
+ #else
+-	e820_reserve_resources(e820.map, e820.nr_map,
+-			       &code_resource, &data_resource, &bss_resource);
++	e820_reserve_resources(e820.map, e820.nr_map);
+ 	e820_mark_nosave_regions();
+ #endif
+ 
+@@ -691,6 +755,9 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ #endif /* !CONFIG_XEN */
++
++	/* do this before identify_cpu for boot cpu */
++	check_enable_amd_mmconf_dmi();
+ }
+ 
+ #ifdef CONFIG_XEN
+@@ -787,9 +854,9 @@ static void __cpuinit amd_detect_cmp(str
+ 	bits = c->x86_coreid_bits;
+ 
+ 	/* Low order bits define the core id (index of core in socket) */
+-	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
+-	/* Convert the APIC ID into the socket ID */
+-	c->phys_proc_id = phys_pkg_id(bits);
++	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
++	/* Convert the initial APIC ID into the socket ID */
++	c->phys_proc_id = c->initial_apicid >> bits;
+ 
+ #ifdef CONFIG_NUMA
+ 	node = c->phys_proc_id;
+@@ -806,7 +873,7 @@ static void __cpuinit amd_detect_cmp(str
+ 		   If that doesn't result in a usable node fall back to the
+ 		   path for the previous case.  */
+ 
+-		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
++		int ht_nodeid = c->initial_apicid;
+ 
+ 		if (ht_nodeid >= 0 &&
+ 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+@@ -914,7 +981,7 @@ static void __cpuinit init_amd(struct cp
+ 
+ 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, (unsigned long *)&c->x86_capability);
++	clear_cpu_cap(c, 0*32+31);
+ 
+ 	/* On C+ stepping K8 rep microcode works well for copy/memset */
+ 	level = cpuid_eax(1);
+@@ -956,9 +1023,25 @@ static void __cpuinit init_amd(struct cp
+ 	/* MFENCE stops RDTSC speculation */
+ 	set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+ 
++	if (c->x86 == 0x10)
++		fam10h_check_enable_mmcfg();
++
+ #ifndef CONFIG_XEN
+ 	if (amd_apic_timer_broken())
+ 		disable_apic_timer = 1;
++
++	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
++		unsigned long long tseg;
++
++		/*
++		 * Split up direct mapping around the TSEG SMM area.
++		 * Don't do it for gbpages because there seems very little
++		 * benefit in doing so.
++		 */
++		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) &&
++		(tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT)))
++			set_memory_4k((unsigned long)__va(tseg), 1);
++	}
+ #endif
+ }
+ 
+@@ -1052,7 +1135,7 @@ static void __cpuinit early_init_intel(s
+ {
+ 	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ 	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ }
+ 
+ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -1095,9 +1178,6 @@ static void __cpuinit init_intel(struct 
+ 
+ 	if (c->x86 == 15)
+ 		c->x86_cache_alignment = c->x86_clflush_size * 2;
+-	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+-	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ 	if (c->x86 == 6)
+ 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ 	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+@@ -1106,6 +1186,32 @@ static void __cpuinit init_intel(struct 
+ 	srat_detect_node();
+ }
+ 
++static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
++{
++	if (c->x86 == 0x6 && c->x86_model >= 0xf)
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++}
++
++static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
++{
++	/* Cache sizes */
++	unsigned n;
++
++	n = c->extended_cpuid_level;
++	if (n >= 0x80000008) {
++		unsigned eax = cpuid_eax(0x80000008);
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
++	}
++
++	if (c->x86 == 0x6 && c->x86_model >= 0xf) {
++		c->x86_cache_alignment = c->x86_clflush_size * 2;
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
++	}
++	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
++}
++
+ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ 	char *v = c->x86_vendor_id;
+@@ -1114,6 +1220,8 @@ static void __cpuinit get_cpu_vendor(str
+ 		c->x86_vendor = X86_VENDOR_AMD;
+ 	else if (!strcmp(v, "GenuineIntel"))
+ 		c->x86_vendor = X86_VENDOR_INTEL;
++	else if (!strcmp(v, "CentaurHauls"))
++		c->x86_vendor = X86_VENDOR_CENTAUR;
+ 	else
+ 		c->x86_vendor = X86_VENDOR_UNKNOWN;
+ }
+@@ -1161,15 +1269,16 @@ static void __cpuinit early_identify_cpu
+ 			c->x86 += (tfms >> 20) & 0xff;
+ 		if (c->x86 >= 0x6)
+ 			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		if (c->x86_capability[0] & (1<<19))
++		if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+ 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ 	} else {
+ 		/* Have CPUID level 0 only - unheard of */
+ 		c->x86 = 4;
+ 	}
+ 
++	c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
+ #ifdef CONFIG_SMP
+-	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
++	c->phys_proc_id = c->initial_apicid;
+ #endif
+ 	/* AMD-defined flags: level 0x80000001 */
+ 	xlvl = cpuid_eax(0x80000000);
+@@ -1202,8 +1311,12 @@ static void __cpuinit early_identify_cpu
+ 	case X86_VENDOR_INTEL:
+ 		early_init_intel(c);
+ 		break;
++	case X86_VENDOR_CENTAUR:
++		early_init_centaur(c);
++		break;
+ 	}
+ 
++	validate_pat_support(c);
+ }
+ 
+ /*
+@@ -1240,6 +1353,10 @@ void __cpuinit identify_cpu(struct cpuin
+ 		init_intel(c);
+ 		break;
+ 
++	case X86_VENDOR_CENTAUR:
++		init_centaur(c);
++		break;
++
+ 	case X86_VENDOR_UNKNOWN:
+ 	default:
+ 		display_cacheinfo(c);
+@@ -1269,14 +1386,24 @@ void __cpuinit identify_cpu(struct cpuin
+ #endif
+ 	select_idle_routine(c);
+ 
+-	if (c != &boot_cpu_data)
+-		mtrr_ap_init();
+ #ifdef CONFIG_NUMA
+ 	numa_add_cpu(smp_processor_id());
+ #endif
+ 
+ }
+ 
++void __cpuinit identify_boot_cpu(void)
++{
++	identify_cpu(&boot_cpu_data);
++}
++
++void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
++{
++	BUG_ON(c == &boot_cpu_data);
++	identify_cpu(c);
++	mtrr_ap_init();
++}
++
+ static __init int setup_noclflush(char *arg)
+ {
+ 	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+@@ -1305,123 +1432,3 @@ static __init int setup_disablecpuid(cha
+ 	return 1;
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+-
+-/*
+- *	Get CPU information for use by the procfs.
+- */
+-
+-static int show_cpuinfo(struct seq_file *m, void *v)
+-{
+-	struct cpuinfo_x86 *c = v;
+-	int cpu = 0, i;
+-
+-#ifdef CONFIG_SMP
+-	cpu = c->cpu_index;
+-#endif
+-
+-	seq_printf(m, "processor\t: %u\n"
+-		   "vendor_id\t: %s\n"
+-		   "cpu family\t: %d\n"
+-		   "model\t\t: %d\n"
+-		   "model name\t: %s\n",
+-		   (unsigned)cpu,
+-		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+-		   c->x86,
+-		   (int)c->x86_model,
+-		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
+-
+-	if (c->x86_mask || c->cpuid_level >= 0)
+-		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+-	else
+-		seq_printf(m, "stepping\t: unknown\n");
+-
+-	if (cpu_has(c, X86_FEATURE_TSC)) {
+-		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
+-
+-		if (!freq)
+-			freq = cpu_khz;
+-		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+-			   freq / 1000, (freq % 1000));
+-	}
+-
+-	/* Cache size */
+-	if (c->x86_cache_size >= 0)
+-		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-
+-#ifdef CONFIG_SMP
+-	if (smp_num_siblings * c->x86_max_cores > 1) {
+-		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+-		seq_printf(m, "siblings\t: %d\n",
+-			       cpus_weight(per_cpu(cpu_core_map, cpu)));
+-		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+-		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+-	}
+-#endif
+-
+-	seq_printf(m,
+-		   "fpu\t\t: yes\n"
+-		   "fpu_exception\t: yes\n"
+-		   "cpuid level\t: %d\n"
+-		   "wp\t\t: yes\n"
+-		   "flags\t\t:",
+-		   c->cpuid_level);
+-
+-	for (i = 0; i < 32*NCAPINTS; i++)
+-		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+-			seq_printf(m, " %s", x86_cap_flags[i]);
+-
+-	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+-		   c->loops_per_jiffy/(500000/HZ),
+-		   (c->loops_per_jiffy/(5000/HZ)) % 100);
+-
+-	if (c->x86_tlbsize > 0)
+-		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
+-	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
+-	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
+-
+-	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
+-		   c->x86_phys_bits, c->x86_virt_bits);
+-
+-	seq_printf(m, "power management:");
+-	for (i = 0; i < 32; i++) {
+-		if (c->x86_power & (1 << i)) {
+-			if (i < ARRAY_SIZE(x86_power_flags) &&
+-			    x86_power_flags[i])
+-				seq_printf(m, "%s%s",
+-					   x86_power_flags[i][0]?" ":"",
+-					   x86_power_flags[i]);
+-			else
+-				seq_printf(m, " [%d]", i);
+-		}
+-	}
+-
+-	seq_printf(m, "\n\n");
+-
+-	return 0;
+-}
+-
+-static void *c_start(struct seq_file *m, loff_t *pos)
+-{
+-	if (*pos == 0)	/* just in case, cpu 0 is not the first */
+-		*pos = first_cpu(cpu_online_map);
+-	if ((*pos) < NR_CPUS && cpu_online(*pos))
+-		return &cpu_data(*pos);
+-	return NULL;
+-}
+-
+-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+-	*pos = next_cpu(*pos, cpu_online_map);
+-	return c_start(m, pos);
+-}
+-
+-static void c_stop(struct seq_file *m, void *v)
+-{
+-}
+-
+-const struct seq_operations cpuinfo_op = {
+-	.start = c_start,
+-	.next =	c_next,
+-	.stop =	c_stop,
+-	.show =	show_cpuinfo,
+-};
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,329 @@
++/*
++ *	Intel SMP support routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
++ *      (c) 2002,2003 Andi Kleen, SuSE Labs.
++ *
++ *	i386 and x86_64 integration by Glauber Costa <gcosta@redhat.com>
++ *
++ *	This code is released under the GNU General Public License version 2 or
++ *	later.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <mach_ipi.h>
++#include <xen/evtchn.h>
++/*
++ *	Some notes on x86 processor bugs affecting SMP operation:
++ *
++ *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
++ *	The Linux implications for SMP are handled as follows:
++ *
++ *	Pentium III / [Xeon]
++ *		None of the E1AP-E3AP errata are visible to the user.
++ *
++ *	E1AP.	see PII A1AP
++ *	E2AP.	see PII A2AP
++ *	E3AP.	see PII A3AP
++ *
++ *	Pentium II / [Xeon]
++ *		None of the A1AP-A3AP errata are visible to the user.
++ *
++ *	A1AP.	see PPro 1AP
++ *	A2AP.	see PPro 2AP
++ *	A3AP.	see PPro 7AP
++ *
++ *	Pentium Pro
++ *		None of 1AP-9AP errata are visible to the normal user,
++ *	except occasional delivery of 'spurious interrupt' as trap #15.
++ *	This is very rare and a non-problem.
++ *
++ *	1AP.	Linux maps APIC as non-cacheable
++ *	2AP.	worked around in hardware
++ *	3AP.	fixed in C0 and above steppings microcode update.
++ *		Linux does not use excessive STARTUP_IPIs.
++ *	4AP.	worked around in hardware
++ *	5AP.	symmetric IO mode (normal Linux operation) not affected.
++ *		'noapic' mode has vector 0xf filled out properly.
++ *	6AP.	'noapic' mode might be affected - fixed in later steppings
++ *	7AP.	We do not assume writes to the LVT deassering IRQs
++ *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
++ *	9AP.	We do not use mixed mode
++ *
++ *	Pentium
++ *		There is a marginal case where REP MOVS on 100MHz SMP
++ *	machines with B stepping processors can fail. XXX should provide
++ *	an L1cache=Writethrough or L1cache=off option.
++ *
++ *		B stepping CPUs may hang. There are hardware work arounds
++ *	for this. We warn about it in case your board doesn't have the work
++ *	arounds. Basically that's so I can tell anyone with a B stepping
++ *	CPU and SMP problems "tough".
++ *
++ *	Specific items [From Pentium Processor Specification Update]
++ *
++ *	1AP.	Linux doesn't use remote read
++ *	2AP.	Linux doesn't trust APIC errors
++ *	3AP.	We work around this
++ *	4AP.	Linux never generated 3 interrupts of the same priority
++ *		to cause a lost local interrupt.
++ *	5AP.	Remote read is never used
++ *	6AP.	not affected - worked around in hardware
++ *	7AP.	not affected - worked around in hardware
++ *	8AP.	worked around in hardware - we get explicit CS errors if not
++ *	9AP.	only 'noapic' mode affected. Might generate spurious
++ *		interrupts, we log only the first one and count the
++ *		rest silently.
++ *	10AP.	not affected - worked around in hardware
++ *	11AP.	Linux reads the APIC between writes to avoid this, as per
++ *		the documentation. Make sure you preserve this as it affects
++ *		the C stepping chips too.
++ *	12AP.	not affected - worked around in hardware
++ *	13AP.	not affected - worked around in hardware
++ *	14AP.	we always deassert INIT during bootup
++ *	15AP.	not affected - worked around in hardware
++ *	16AP.	not affected - worked around in hardware
++ *	17AP.	not affected - worked around in hardware
++ *	18AP.	not affected - worked around in hardware
++ *	19AP.	not affected - worked around in BIOS
++ *
++ *	If this sounds worrying believe me these bugs are either ___RARE___,
++ *	or are signal timing bugs worked around in hardware and there's
++ *	about nothing of note with C stepping upwards.
++ */
++
++/*
++ * this function sends a 'reschedule' IPI to another CPU.
++ * it goes straight through and wastes no time serializing
++ * anything. Worst case is that we lose a reschedule ...
++ */
++void xen_smp_send_reschedule(int cpu)
++{
++	if (unlikely(cpu_is_offline(cpu))) {
++		WARN_ON(1);
++		return;
++	}
++	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++}
++
++/*
++ * Structure and data for smp_call_function(). This is designed to minimise
++ * static memory requirements. It also looks cleaner.
++ */
++static DEFINE_SPINLOCK(call_lock);
++
++struct call_data_struct {
++	void (*func) (void *info);
++	void *info;
++	atomic_t started;
++	atomic_t finished;
++	int wait;
++};
++
++void lock_ipi_call_lock(void)
++{
++	spin_lock_irq(&call_lock);
++}
++
++void unlock_ipi_call_lock(void)
++{
++	spin_unlock_irq(&call_lock);
++}
++
++static struct call_data_struct *call_data;
++
++static void __smp_call_function(void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = num_online_cpus() - 1;
++
++	if (!cpus)
++		return;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	mb();
++
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++}
++
++
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * @mask: The set of cpus to run on.  Must not include the current cpu.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++  * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int
++xen_smp_call_function_mask(cpumask_t mask,
++			      void (*func)(void *), void *info,
++			      int wait)
++{
++	struct call_data_struct data;
++	cpumask_t allbutself;
++	int cpus;
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
++	/* Holding any lock stops cpus from going down. */
++	spin_lock(&call_lock);
++
++	allbutself = cpu_online_map;
++	cpu_clear(smp_processor_id(), allbutself);
++
++	cpus_and(mask, mask, allbutself);
++	cpus = cpus_weight(mask);
++
++	if (!cpus) {
++		spin_unlock(&call_lock);
++		return 0;
++	}
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	wmb();
++
++	/* Send a message to other CPUs */
++	if (cpus_equal(mask, allbutself) &&
++	    cpus_equal(cpu_online_map, cpu_callout_map))
++		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++	else
++		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++	spin_unlock(&call_lock);
++
++	return 0;
++}
++
++static void stop_this_cpu(void *dummy)
++{
++	local_irq_disable();
++	/*
++	 * Remove this CPU:
++	 */
++	cpu_clear(smp_processor_id(), cpu_online_map);
++	disable_all_local_evtchn();
++	if (hlt_works(smp_processor_id()))
++		for (;;) halt();
++	for (;;);
++}
++
++/*
++ * this function calls the 'stop' function on all other CPUs in the system.
++ */
++
++void xen_smp_send_stop(void)
++{
++	int nolock;
++	unsigned long flags;
++
++	/* Don't deadlock on the call lock in panic */
++	nolock = !spin_trylock(&call_lock);
++	local_irq_save(flags);
++	__smp_call_function(stop_this_cpu, NULL, 0, 0);
++	if (!nolock)
++		spin_unlock(&call_lock);
++	disable_all_local_evtchn();
++	local_irq_restore(flags);
++}
++
++/*
++ * Reschedule call back. Nothing to do,
++ * all the work is done automatically when
++ * we return from the interrupt.
++ */
++irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
++{
++#ifdef CONFIG_X86_32
++	__get_cpu_var(irq_stat).irq_resched_count++;
++#else
++	add_pda(irq_resched_count, 1);
++#endif
++	return IRQ_HANDLED;
++}
++
++irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
++{
++	void (*func) (void *info) = call_data->func;
++	void *info = call_data->info;
++	int wait = call_data->wait;
++
++	/*
++	 * Notify initiating CPU that I've grabbed the data and am
++	 * about to execute the function
++	 */
++	mb();
++	atomic_inc(&call_data->started);
++	/*
++	 * At this point the info structure may be out of scope unless wait==1
++	 */
++	irq_enter();
++	(*func)(info);
++#ifdef CONFIG_X86_32
++	__get_cpu_var(irq_stat).irq_call_count++;
++#else
++	add_pda(irq_call_count, 1);
++#endif
++	irq_exit();
++
++	if (wait) {
++		mb();
++		atomic_inc(&call_data->finished);
++	}
++
++	return IRQ_HANDLED;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,647 +0,0 @@
+-/*
+- *	Intel SMP support routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+- *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+- *
+- *	This code is released under the GNU General Public License version 2 or
+- *	later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/cache.h>
+-#include <linux/interrupt.h>
+-#include <linux/cpu.h>
+-#include <linux/module.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mmu_context.h>
+-#if 0
+-#include <mach_apic.h>
+-#endif
+-#include <xen/evtchn.h>
+-
+-/*
+- *	Some notes on x86 processor bugs affecting SMP operation:
+- *
+- *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
+- *	The Linux implications for SMP are handled as follows:
+- *
+- *	Pentium III / [Xeon]
+- *		None of the E1AP-E3AP errata are visible to the user.
+- *
+- *	E1AP.	see PII A1AP
+- *	E2AP.	see PII A2AP
+- *	E3AP.	see PII A3AP
+- *
+- *	Pentium II / [Xeon]
+- *		None of the A1AP-A3AP errata are visible to the user.
+- *
+- *	A1AP.	see PPro 1AP
+- *	A2AP.	see PPro 2AP
+- *	A3AP.	see PPro 7AP
+- *
+- *	Pentium Pro
+- *		None of 1AP-9AP errata are visible to the normal user,
+- *	except occasional delivery of 'spurious interrupt' as trap #15.
+- *	This is very rare and a non-problem.
+- *
+- *	1AP.	Linux maps APIC as non-cacheable
+- *	2AP.	worked around in hardware
+- *	3AP.	fixed in C0 and above steppings microcode update.
+- *		Linux does not use excessive STARTUP_IPIs.
+- *	4AP.	worked around in hardware
+- *	5AP.	symmetric IO mode (normal Linux operation) not affected.
+- *		'noapic' mode has vector 0xf filled out properly.
+- *	6AP.	'noapic' mode might be affected - fixed in later steppings
+- *	7AP.	We do not assume writes to the LVT deassering IRQs
+- *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
+- *	9AP.	We do not use mixed mode
+- *
+- *	Pentium
+- *		There is a marginal case where REP MOVS on 100MHz SMP
+- *	machines with B stepping processors can fail. XXX should provide
+- *	an L1cache=Writethrough or L1cache=off option.
+- *
+- *		B stepping CPUs may hang. There are hardware work arounds
+- *	for this. We warn about it in case your board doesn't have the work
+- *	arounds. Basically that's so I can tell anyone with a B stepping
+- *	CPU and SMP problems "tough".
+- *
+- *	Specific items [From Pentium Processor Specification Update]
+- *
+- *	1AP.	Linux doesn't use remote read
+- *	2AP.	Linux doesn't trust APIC errors
+- *	3AP.	We work around this
+- *	4AP.	Linux never generated 3 interrupts of the same priority
+- *		to cause a lost local interrupt.
+- *	5AP.	Remote read is never used
+- *	6AP.	not affected - worked around in hardware
+- *	7AP.	not affected - worked around in hardware
+- *	8AP.	worked around in hardware - we get explicit CS errors if not
+- *	9AP.	only 'noapic' mode affected. Might generate spurious
+- *		interrupts, we log only the first one and count the
+- *		rest silently.
+- *	10AP.	not affected - worked around in hardware
+- *	11AP.	Linux reads the APIC between writes to avoid this, as per
+- *		the documentation. Make sure you preserve this as it affects
+- *		the C stepping chips too.
+- *	12AP.	not affected - worked around in hardware
+- *	13AP.	not affected - worked around in hardware
+- *	14AP.	we always deassert INIT during bootup
+- *	15AP.	not affected - worked around in hardware
+- *	16AP.	not affected - worked around in hardware
+- *	17AP.	not affected - worked around in hardware
+- *	18AP.	not affected - worked around in hardware
+- *	19AP.	not affected - worked around in BIOS
+- *
+- *	If this sounds worrying believe me these bugs are either ___RARE___,
+- *	or are signal timing bugs worked around in hardware and there's
+- *	about nothing of note with C stepping upwards.
+- */
+-
+-DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
+-
+-/*
+- * the following functions deal with sending IPIs between CPUs.
+- *
+- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+- */
+-
+-static inline int __prepare_ICR (unsigned int shortcut, int vector)
+-{
+-	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
+-
+-	switch (vector) {
+-	default:
+-		icr |= APIC_DM_FIXED | vector;
+-		break;
+-	case NMI_VECTOR:
+-		icr |= APIC_DM_NMI;
+-		break;
+-	}
+-	return icr;
+-}
+-
+-static inline int __prepare_ICR2 (unsigned int mask)
+-{
+-	return SET_APIC_DEST_FIELD(mask);
+-}
+-
+-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 __send_IPI_shortcut(unsigned int shortcut, int vector)
+-{
+-	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;
+-	default:
+-		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
+-		       vector);
+-		break;
+-	}
+-}
+-
+-void send_IPI_self(int vector)
+-{
+-	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+-}
+-
+-/*
+- * This is only used on smaller machines.
+- */
+-void send_IPI_mask_bitmask(cpumask_t mask, int vector)
+-{
+-	unsigned long flags;
+-	unsigned int cpu;
+-
+-	local_irq_save(flags);
+-	WARN_ON(cpus_addr(mask)[0] & ~cpus_addr(cpu_online_map)[0]);
+-
+-	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+-		if (cpu_isset(cpu, mask)) {
+-			__send_IPI_one(cpu, vector);
+-		}
+-	}
+-
+-	local_irq_restore(flags);
+-}
+-
+-void send_IPI_mask_sequence(cpumask_t mask, int vector)
+-{
+-
+-	send_IPI_mask_bitmask(mask, vector);
+-}
+-
+-#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+-
+-#if 0 /* XEN */
+-/*
+- *	Smarter SMP flushing macros. 
+- *		c/o Linus Torvalds.
+- *
+- *	These mean you can really definitely utterly forget about
+- *	writing to user space from interrupts. (Its not allowed anyway).
+- *
+- *	Optimizations Manfred Spraul <manfred@colorfullife.com>
+- */
+-
+-static cpumask_t flush_cpumask;
+-static struct mm_struct * flush_mm;
+-static unsigned long flush_va;
+-static DEFINE_SPINLOCK(tlbstate_lock);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- *
+- * We need to reload %cr3 since the page tables may be going
+- * away from under us..
+- */
+-void leave_mm(int cpu)
+-{
+-	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+-		BUG();
+-	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
+-	load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- * 	Stop ipi delivery for the old mm. This is not synchronized with
+- * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * 	for the wrong mm, and in the worst case we perform a superfluous
+- * 	tlb flush.
+- * 1a2) set cpu_tlbstate to TLBSTATE_OK
+- * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- *	was in lazy tlb mode.
+- * 1a3) update cpu_tlbstate[].active_mm
+- * 	Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- * 	Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
+- *	flush ipis.
+- * 1b1) set cpu_tlbstate to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- * 	Atomically set the bit [other cpus will start sending flush ipis],
+- * 	and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- *   runs in kernel space, the cpu could load tlb entries for user space
+- *   pages.
+- *
+- * The good news is that cpu_tlbstate is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- */
+-
+-irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id)
+-{
+-	unsigned long cpu;
+-
+-	cpu = get_cpu();
+-
+-	if (!cpu_isset(cpu, flush_cpumask))
+-		goto out;
+-		/* 
+-		 * This was a BUG() but until someone can quote me the
+-		 * line from the intel manual that guarantees an IPI to
+-		 * multiple CPUs is retried _only_ on the erroring CPUs
+-		 * its staying as a return
+-		 *
+-		 * BUG();
+-		 */
+-		 
+-	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+-		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
+-			if (flush_va == TLB_FLUSH_ALL)
+-				local_flush_tlb();
+-			else
+-				__flush_tlb_one(flush_va);
+-		} else
+-			leave_mm(cpu);
+-	}
+-	smp_mb__before_clear_bit();
+-	cpu_clear(cpu, flush_cpumask);
+-	smp_mb__after_clear_bit();
+-out:
+-	put_cpu_no_resched();
+-	__get_cpu_var(irq_stat).irq_tlb_count++;
+-
+-	return IRQ_HANDLED;
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+-			     unsigned long va)
+-{
+-	cpumask_t cpumask = *cpumaskp;
+-
+-	/*
+-	 * A couple of (to be removed) sanity checks:
+-	 *
+-	 * - current CPU must not be in mask
+-	 * - mask must exist :)
+-	 */
+-	BUG_ON(cpus_empty(cpumask));
+-	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+-	BUG_ON(!mm);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* If a CPU which we ran on has gone down, OK. */
+-	cpus_and(cpumask, cpumask, cpu_online_map);
+-	if (unlikely(cpus_empty(cpumask)))
+-		return;
+-#endif
+-
+-	/*
+-	 * i'm not happy about this global shared spinlock in the
+-	 * MM hot path, but we'll see how contended it is.
+-	 * AK: x86-64 has a faster method that could be ported.
+-	 */
+-	spin_lock(&tlbstate_lock);
+-	
+-	flush_mm = mm;
+-	flush_va = va;
+-	cpus_or(flush_cpumask, cpumask, flush_cpumask);
+-	/*
+-	 * We have to send the IPI only to
+-	 * CPUs affected.
+-	 */
+-	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+-
+-	while (!cpus_empty(flush_cpumask))
+-		/* nothing. lockup detection does not belong here */
+-		cpu_relax();
+-
+-	flush_mm = NULL;
+-	flush_va = 0;
+-	spin_unlock(&tlbstate_lock);
+-}
+-	
+-void flush_tlb_current_task(void)
+-{
+-	struct mm_struct *mm = current->mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	local_flush_tlb();
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-	preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if (current->mm)
+-			local_flush_tlb();
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+-	preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+-	struct mm_struct *mm = vma->vm_mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if(current->mm)
+-			__flush_tlb_one(va);
+-		else
+-		 	leave_mm(smp_processor_id());
+-	}
+-
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, va);
+-
+-	preempt_enable();
+-}
+-EXPORT_SYMBOL(flush_tlb_page);
+-
+-static void do_flush_tlb_all(void* info)
+-{
+-	unsigned long cpu = smp_processor_id();
+-
+-	__flush_tlb_all();
+-	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
+-		leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+-	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-
+-#endif /* XEN */
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-void xen_smp_send_reschedule(int cpu)
+-{
+-	WARN_ON(cpu_is_offline(cpu));
+-	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+-	void (*func) (void *info);
+-	void *info;
+-	atomic_t started;
+-	atomic_t finished;
+-	int wait;
+-};
+-
+-void lock_ipi_call_lock(void)
+-{
+-	spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+-	spin_unlock_irq(&call_lock);
+-}
+-
+-static struct call_data_struct *call_data;
+-
+-static void __smp_call_function(void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
+-{
+-	struct call_data_struct data;
+-	int cpus = num_online_cpus() - 1;
+-
+-	if (!cpus)
+-		return;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	mb();
+-
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-}
+-
+-
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on.  Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+-  * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int
+-xen_smp_call_function_mask(cpumask_t mask,
+-			      void (*func)(void *), void *info,
+-			      int wait)
+-{
+-	struct call_data_struct data;
+-	cpumask_t allbutself;
+-	int cpus;
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	/* Holding any lock stops cpus from going down. */
+-	spin_lock(&call_lock);
+-
+-	allbutself = cpu_online_map;
+-	cpu_clear(smp_processor_id(), allbutself);
+-
+-	cpus_and(mask, mask, allbutself);
+-	cpus = cpus_weight(mask);
+-
+-	if (!cpus) {
+-		spin_unlock(&call_lock);
+-		return 0;
+-	}
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	mb();
+-
+-	/* Send a message to other CPUs */
+-	if (cpus_equal(mask, allbutself))
+-		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-	else
+-		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-	spin_unlock(&call_lock);
+-
+-	return 0;
+-}
+-
+-static void stop_this_cpu (void * dummy)
+-{
+-	local_irq_disable();
+-	/*
+-	 * Remove this CPU:
+-	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
+-	disable_all_local_evtchn();
+-	if (cpu_data(smp_processor_id()).hlt_works_ok)
+-		for(;;) halt();
+-	for (;;);
+-}
+-
+-/*
+- * this function calls the 'stop' function on all other CPUs in the system.
+- */
+-
+-void xen_smp_send_stop(void)
+-{
+-	/* Don't deadlock on the call lock in panic */
+-	int nolock = !spin_trylock(&call_lock);
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	__smp_call_function(stop_this_cpu, NULL, 0, 0);
+-	if (!nolock)
+-		spin_unlock(&call_lock);
+-	disable_all_local_evtchn();
+-	local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+-{
+-	__get_cpu_var(irq_stat).irq_resched_count++;
+-
+-	return IRQ_HANDLED;
+-}
+-
+-#include <linux/kallsyms.h>
+-irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
+-{
+-	void (*func) (void *info) = call_data->func;
+-	void *info = call_data->info;
+-	int wait = call_data->wait;
+-
+-	/*
+-	 * Notify initiating CPU that I've grabbed the data and am
+-	 * about to execute the function
+-	 */
+-	mb();
+-	atomic_inc(&call_data->started);
+-	/*
+-	 * At this point the info structure may be out of scope unless wait==1
+-	 */
+-	irq_enter();
+-	(*func)(info);
+-	__get_cpu_var(irq_stat).irq_call_count++;
+-	irq_exit();
+-
+-	if (wait) {
+-		mb();
+-		atomic_inc(&call_data->finished);
+-	}
+-
+-	return IRQ_HANDLED;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,554 +0,0 @@
+-/*
+- *	Intel SMP support routines.
+- *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+- *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+- *      (c) 2002,2003 Andi Kleen, SuSE Labs.
+- *
+- *	This code is released under the GNU General Public License version 2 or
+- *	later.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/smp.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/interrupt.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlbflush.h>
+-#include <asm/mach_apic.h>
+-#include <asm/mmu_context.h>
+-#include <asm/proto.h>
+-#include <asm/apicdef.h>
+-#include <asm/idle.h>
+-#ifdef CONFIG_XEN
+-#include <xen/evtchn.h>
+-#endif
+-
+-#ifndef CONFIG_XEN
+-/*
+- *	Smarter SMP flushing macros.
+- *		c/o Linus Torvalds.
+- *
+- *	These mean you can really definitely utterly forget about
+- *	writing to user space from interrupts. (Its not allowed anyway).
+- *
+- *	Optimizations Manfred Spraul <manfred@colorfullife.com>
+- *
+- *	More scalable flush, from Andi Kleen
+- *
+- *	To avoid global state use 8 different call vectors.
+- *	Each CPU uses a specific vector to trigger flushes on other
+- *	CPUs. Depending on the received vector the target CPUs look into
+- *	the right per cpu variable for the flush data.
+- *
+- *	With more than 8 CPUs they are hashed to the 8 available
+- *	vectors. The limited global vector space forces us to this right now.
+- *	In future when interrupts are split into per CPU domains this could be
+- *	fixed, at the cost of triggering multiple IPIs in some cases.
+- */
+-
+-union smp_flush_state {
+-	struct {
+-		cpumask_t flush_cpumask;
+-		struct mm_struct *flush_mm;
+-		unsigned long flush_va;
+-		spinlock_t tlbstate_lock;
+-	};
+-	char pad[SMP_CACHE_BYTES];
+-} ____cacheline_aligned;
+-
+-/* State is put into the per CPU data section, but padded
+-   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);
+-
+-/*
+- * We cannot call mmdrop() because we are in interrupt context,
+- * instead update mm->cpu_vm_mask.
+- */
+-void leave_mm(int cpu)
+-{
+-	if (read_pda(mmu_state) == TLBSTATE_OK)
+-		BUG();
+-	cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
+-	load_cr3(swapper_pg_dir);
+-}
+-EXPORT_SYMBOL_GPL(leave_mm);
+-
+-/*
+- *
+- * The flush IPI assumes that a thread switch happens in this order:
+- * [cpu0: the cpu that switches]
+- * 1) switch_mm() either 1a) or 1b)
+- * 1a) thread switch to a different mm
+- * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- *	Stop ipi delivery for the old mm. This is not synchronized with
+- *	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- *	for the wrong mm, and in the worst case we perform a superfluous
+- *	tlb flush.
+- * 1a2) set cpu mmu_state to TLBSTATE_OK
+- *	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+- *	was in lazy tlb mode.
+- * 1a3) update cpu active_mm
+- *	Now cpu0 accepts tlb flushes for the new mm.
+- * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- *	Now the other cpus will send tlb flush ipis.
+- * 1a4) change cr3.
+- * 1b) thread switch without mm change
+- *	cpu active_mm is correct, cpu0 already handles
+- *	flush ipis.
+- * 1b1) set cpu mmu_state to TLBSTATE_OK
+- * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- *	Atomically set the bit [other cpus will start sending flush ipis],
+- *	and test the bit.
+- * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+- * 2) switch %%esp, ie current
+- *
+- * The interrupt must handle 2 special cases:
+- * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+- * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+- *   runs in kernel space, the cpu could load tlb entries for user space
+- *   pages.
+- *
+- * The good news is that cpu mmu_state is local to each cpu, no
+- * write/read ordering problems.
+- */
+-
+-/*
+- * TLB flush IPI:
+- *
+- * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+- * 2) Leave the mm if we are in the lazy tlb mode.
+- *
+- * Interrupts are disabled.
+- */
+-
+-asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
+-{
+-	int cpu;
+-	int sender;
+-	union smp_flush_state *f;
+-
+-	cpu = smp_processor_id();
+-	/*
+-	 * orig_rax contains the negated interrupt vector.
+-	 * Use that to determine where the sender put the data.
+-	 */
+-	sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
+-	f = &per_cpu(flush_state, sender);
+-
+-	if (!cpu_isset(cpu, f->flush_cpumask))
+-		goto out;
+-		/*
+-		 * This was a BUG() but until someone can quote me the
+-		 * line from the intel manual that guarantees an IPI to
+-		 * multiple CPUs is retried _only_ on the erroring CPUs
+-		 * its staying as a return
+-		 *
+-		 * BUG();
+-		 */
+-
+-	if (f->flush_mm == read_pda(active_mm)) {
+-		if (read_pda(mmu_state) == TLBSTATE_OK) {
+-			if (f->flush_va == TLB_FLUSH_ALL)
+-				local_flush_tlb();
+-			else
+-				__flush_tlb_one(f->flush_va);
+-		} else
+-			leave_mm(cpu);
+-	}
+-out:
+-	ack_APIC_irq();
+-	cpu_clear(cpu, f->flush_cpumask);
+-	add_pda(irq_tlb_count, 1);
+-}
+-
+-void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
+-			     unsigned long va)
+-{
+-	int sender;
+-	union smp_flush_state *f;
+-	cpumask_t cpumask = *cpumaskp;
+-
+-	/* Caller has disabled preemption */
+-	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+-	f = &per_cpu(flush_state, sender);
+-
+-	/*
+-	 * Could avoid this lock when
+-	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+-	 * probably not worth checking this for a cache-hot lock.
+-	 */
+-	spin_lock(&f->tlbstate_lock);
+-
+-	f->flush_mm = mm;
+-	f->flush_va = va;
+-	cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
+-
+-	/*
+-	 * We have to send the IPI only to
+-	 * CPUs affected.
+-	 */
+-	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+-
+-	while (!cpus_empty(f->flush_cpumask))
+-		cpu_relax();
+-
+-	f->flush_mm = NULL;
+-	f->flush_va = 0;
+-	spin_unlock(&f->tlbstate_lock);
+-}
+-
+-int __cpuinit init_smp_flush(void)
+-{
+-	int i;
+-
+-	for_each_cpu_mask(i, cpu_possible_map) {
+-		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
+-	}
+-	return 0;
+-}
+-core_initcall(init_smp_flush);
+-
+-void flush_tlb_current_task(void)
+-{
+-	struct mm_struct *mm = current->mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	local_flush_tlb();
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-	preempt_enable();
+-}
+-
+-void flush_tlb_mm (struct mm_struct * mm)
+-{
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if (current->mm)
+-			local_flush_tlb();
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+-
+-	preempt_enable();
+-}
+-
+-void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+-{
+-	struct mm_struct *mm = vma->vm_mm;
+-	cpumask_t cpu_mask;
+-
+-	preempt_disable();
+-	cpu_mask = mm->cpu_vm_mask;
+-	cpu_clear(smp_processor_id(), cpu_mask);
+-
+-	if (current->active_mm == mm) {
+-		if(current->mm)
+-			__flush_tlb_one(va);
+-		else
+-			leave_mm(smp_processor_id());
+-	}
+-
+-	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, va);
+-
+-	preempt_enable();
+-}
+-
+-static void do_flush_tlb_all(void* info)
+-{
+-	unsigned long cpu = smp_processor_id();
+-
+-	__flush_tlb_all();
+-	if (read_pda(mmu_state) == TLBSTATE_LAZY)
+-		leave_mm(cpu);
+-}
+-
+-void flush_tlb_all(void)
+-{
+-	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
+-}
+-#endif /* Xen */
+-
+-/*
+- * this function sends a 'reschedule' IPI to another CPU.
+- * it goes straight through and wastes no time serializing
+- * anything. Worst case is that we lose a reschedule ...
+- */
+-
+-void smp_send_reschedule(int cpu)
+-{
+-	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+-}
+-
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+-	void (*func) (void *info);
+-	void *info;
+-	atomic_t started;
+-	atomic_t finished;
+-	int wait;
+-};
+-
+-static struct call_data_struct * call_data;
+-
+-void lock_ipi_call_lock(void)
+-{
+-	spin_lock_irq(&call_lock);
+-}
+-
+-void unlock_ipi_call_lock(void)
+-{
+-	spin_unlock_irq(&call_lock);
+-}
+-
+-/*
+- * this function sends a 'generic call function' IPI to all other CPU
+- * of the system defined in the mask.
+- */
+-static int __smp_call_function_mask(cpumask_t mask,
+-				    void (*func)(void *), void *info,
+-				    int wait)
+-{
+-	struct call_data_struct data;
+-	cpumask_t allbutself;
+-	int cpus;
+-
+-	allbutself = cpu_online_map;
+-	cpu_clear(smp_processor_id(), allbutself);
+-
+-	cpus_and(mask, mask, allbutself);
+-	cpus = cpus_weight(mask);
+-
+-	if (!cpus)
+-		return 0;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	wmb();
+-
+-	/* Send a message to other CPUs */
+-	if (cpus_equal(mask, allbutself))
+-		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-	else
+-		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (!wait)
+-		return 0;
+-
+-	while (atomic_read(&data.finished) != cpus)
+-		cpu_relax();
+-
+-	return 0;
+-}
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on.  Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+- * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int smp_call_function_mask(cpumask_t mask,
+-			   void (*func)(void *), void *info,
+-			   int wait)
+-{
+-	int ret;
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	spin_lock(&call_lock);
+-	ret = __smp_call_function_mask(mask, func, info, wait);
+-	spin_unlock(&call_lock);
+-	return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_mask);
+-
+-/*
+- * smp_call_function_single - Run a function on a specific CPU
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Currently unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Retrurns 0 on success, else a negative status code.
+- *
+- * Does not return until the remote CPU is nearly ready to execute <func>
+- * or is or has executed.
+- */
+-
+-int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+-			      int nonatomic, int wait)
+-{
+-	/* prevent preemption and reschedule on another processor */
+-	int ret, me = get_cpu();
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	if (cpu == me) {
+-		local_irq_disable();
+-		func(info);
+-		local_irq_enable();
+-		put_cpu();
+-		return 0;
+-	}
+-
+-	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
+-
+-	put_cpu();
+-	return ret;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+-
+-/*
+- * smp_call_function - run a function on all other CPUs.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: currently unused.
+- * @wait: If true, wait (atomically) until function has completed on other
+- *        CPUs.
+- *
+- * Returns 0 on success, else a negative status code. Does not return until
+- * remote CPUs are nearly ready to execute func or are or have executed.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- * Actually there are a few legal cases, like panic.
+- */
+-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+-			int wait)
+-{
+-	return smp_call_function_mask(cpu_online_map, func, info, wait);
+-}
+-EXPORT_SYMBOL(smp_call_function);
+-
+-static void stop_this_cpu(void *dummy)
+-{
+-	local_irq_disable();
+-	/*
+-	 * Remove this CPU:
+-	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
+-	disable_all_local_evtchn();
+-	for (;;)
+-		halt();
+-}
+-
+-void smp_send_stop(void)
+-{
+-	int nolock;
+-	unsigned long flags;
+-
+-#ifndef CONFIG_XEN
+-	if (reboot_force)
+-		return;
+-#endif
+-
+-	/* Don't deadlock on the call lock in panic */
+-	nolock = !spin_trylock(&call_lock);
+-	local_irq_save(flags);
+-	__smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0);
+-	if (!nolock)
+-		spin_unlock(&call_lock);
+-	disable_all_local_evtchn();
+-	local_irq_restore(flags);
+-}
+-
+-/*
+- * Reschedule call back. Nothing to do,
+- * all the work is done automatically when
+- * we return from the interrupt.
+- */
+-#ifndef CONFIG_XEN
+-asmlinkage void smp_reschedule_interrupt(void)
+-#else
+-asmlinkage irqreturn_t smp_reschedule_interrupt(int irq, void *ctx)
+-#endif
+-{
+-#ifndef CONFIG_XEN
+-	ack_APIC_irq();
+-#endif
+-	add_pda(irq_resched_count, 1);
+-#ifdef CONFIG_XEN
+-	return IRQ_HANDLED;
+-#endif
+-}
+-
+-#ifndef CONFIG_XEN
+-asmlinkage void smp_call_function_interrupt(void)
+-#else
+-asmlinkage irqreturn_t smp_call_function_interrupt(int irq, void *ctx)
+-#endif
+-{
+-	void (*func) (void *info) = call_data->func;
+-	void *info = call_data->info;
+-	int wait = call_data->wait;
+-
+-#ifndef CONFIG_XEN
+-	ack_APIC_irq();
+-#endif
+-	/*
+-	 * Notify initiating CPU that I've grabbed the data and am
+-	 * about to execute the function
+-	 */
+-	mb();
+-	atomic_inc(&call_data->started);
+-	/*
+-	 * At this point the info structure may be out of scope unless wait==1
+-	 */
+-	exit_idle();
+-	irq_enter();
+-	(*func)(info);
+-	add_pda(irq_call_count, 1);
+-	irq_exit();
+-	if (wait) {
+-		mb();
+-		atomic_inc(&call_data->finished);
+-	}
+-#ifdef CONFIG_XEN
+-	return IRQ_HANDLED;
+-#endif
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:32:56.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:33:19.000000000 +0100
+@@ -691,8 +691,6 @@ int xen_update_persistent_clock(void)
+ 	return 0;
+ }
+ 
+-extern void (*late_time_init)(void);
+-
+ /* Dynamically-mapped IRQ. */
+ DEFINE_PER_CPU(int, timer_irq);
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -9,26 +9,28 @@
+  * 'Traps.c' handles hardware traps and faults after we have saved some
+  * state in 'asm.s'.
+  */
+-#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/highmem.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
+ #include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
+ #include <linux/errno.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
+ #include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/highmem.h>
+-#include <linux/kallsyms.h>
+-#include <linux/ptrace.h>
+-#include <linux/utsname.h>
+-#include <linux/kprobes.h>
+-#include <linux/kexec.h>
+-#include <linux/unwind.h>
+-#include <linux/uaccess.h>
+-#include <linux/nmi.h>
+ #include <linux/bug.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
+ 
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -43,21 +45,18 @@
+ #include <linux/edac.h>
+ #endif
+ 
++#include <asm/arch_hooks.h>
++#include <asm/stacktrace.h>
+ #include <asm/processor.h>
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/atomic.h>
+ #include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/nmi.h>
+-#include <asm/unwind.h>
+ #include <asm/smp.h>
+-#include <asm/arch_hooks.h>
+-#include <linux/kdebug.h>
+-#include <asm/stacktrace.h>
+-
+-#include <linux/module.h>
++#include <asm/io.h>
+ 
+ #include "mach_traps.h"
+ 
+@@ -71,7 +70,7 @@ EXPORT_SYMBOL_GPL(used_vectors);
+ asmlinkage int system_call(void);
+ 
+ /* Do we ignore FPU interrupts ? */
+-char ignore_fpu_irq = 0;
++char ignore_fpu_irq;
+ 
+ #ifndef CONFIG_X86_NO_IDT
+ /*
+@@ -113,12 +112,13 @@ static unsigned int code_bytes = 64;
+ void printk_address(unsigned long address, int reliable)
+ {
+ #ifdef CONFIG_KALLSYMS
+-	unsigned long offset = 0, symsize;
++	char namebuf[KSYM_NAME_LEN];
++	unsigned long offset = 0;
++	unsigned long symsize;
+ 	const char *symname;
+-	char *modname;
+-	char *delim = ":";
+-	char namebuf[128];
+ 	char reliab[4] = "";
++	char *delim = ":";
++	char *modname;
+ 
+ 	symname = kallsyms_lookup(address, &symsize, &offset,
+ 					&modname, namebuf);
+@@ -146,13 +146,14 @@ static inline int valid_stack_ptr(struct
+ 
+ /* The form of the top of the frame on the stack */
+ struct stack_frame {
+-	struct stack_frame *next_frame;
+-	unsigned long return_address;
++	struct stack_frame	*next_frame;
++	unsigned long		return_address;
+ };
+ 
+-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+-				unsigned long *stack, unsigned long bp,
+-				const struct stacktrace_ops *ops, void *data)
++static inline unsigned long
++print_context_stack(struct thread_info *tinfo,
++		    unsigned long *stack, unsigned long bp,
++		    const struct stacktrace_ops *ops, void *data)
+ {
+ 	struct stack_frame *frame = (struct stack_frame *)bp;
+ 
+@@ -174,7 +175,7 @@ static inline unsigned long print_contex
+ 	return bp;
+ }
+ 
+-#define MSG(msg) ops->warning(data, msg)
++#define MSG(msg)		ops->warning(data, msg)
+ 
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 		unsigned long *stack, unsigned long bp,
+@@ -185,6 +186,7 @@ void dump_trace(struct task_struct *task
+ 
+ 	if (!stack) {
+ 		unsigned long dummy;
++
+ 		stack = &dummy;
+ 		if (task != current)
+ 			stack = (unsigned long *)task->thread.sp;
+@@ -194,7 +196,7 @@ void dump_trace(struct task_struct *task
+ 	if (!bp) {
+ 		if (task == current) {
+ 			/* Grab bp right from our regs */
+-			asm ("movl %%ebp, %0" : "=r" (bp) : );
++			asm("movl %%ebp, %0" : "=r" (bp) :);
+ 		} else {
+ 			/* bp is the last reg pushed by switch_to */
+ 			bp = *(unsigned long *) task->thread.sp;
+@@ -204,15 +206,18 @@ void dump_trace(struct task_struct *task
+ 
+ 	while (1) {
+ 		struct thread_info *context;
++
+ 		context = (struct thread_info *)
+ 			((unsigned long)stack & (~(THREAD_SIZE - 1)));
+ 		bp = print_context_stack(context, stack, bp, ops, data);
+-		/* Should be after the line below, but somewhere
+-		   in early boot context comes out corrupted and we
+-		   can't reference it -AK */
++		/*
++		 * Should be after the line below, but somewhere
++		 * in early boot context comes out corrupted and we
++		 * can't reference it:
++		 */
+ 		if (ops->stack(data, "IRQ") < 0)
+ 			break;
+-		stack = (unsigned long*)context->previous_esp;
++		stack = (unsigned long *)context->previous_esp;
+ 		if (!stack)
+ 			break;
+ 		touch_nmi_watchdog();
+@@ -251,15 +256,15 @@ static void print_trace_address(void *da
+ }
+ 
+ static const struct stacktrace_ops print_trace_ops = {
+-	.warning = print_trace_warning,
+-	.warning_symbol = print_trace_warning_symbol,
+-	.stack = print_trace_stack,
+-	.address = print_trace_address,
++	.warning		= print_trace_warning,
++	.warning_symbol		= print_trace_warning_symbol,
++	.stack			= print_trace_stack,
++	.address		= print_trace_address,
+ };
+ 
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp, char *log_lvl)
++		   unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ 	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ 	printk("%s =======================\n", log_lvl);
+@@ -271,21 +276,22 @@ void show_trace(struct task_struct *task
+ 	show_trace_log_lvl(task, regs, stack, bp, "");
+ }
+ 
+-static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		       unsigned long *sp, unsigned long bp, char *log_lvl)
++static void
++show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++		   unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ 	unsigned long *stack;
+ 	int i;
+ 
+ 	if (sp == NULL) {
+ 		if (task)
+-			sp = (unsigned long*)task->thread.sp;
++			sp = (unsigned long *)task->thread.sp;
+ 		else
+ 			sp = (unsigned long *)&sp;
+ 	}
+ 
+ 	stack = sp;
+-	for(i = 0; i < kstack_depth_to_print; i++) {
++	for (i = 0; i < kstack_depth_to_print; i++) {
+ 		if (kstack_end(stack))
+ 			break;
+ 		if (i && ((i % 8) == 0))
+@@ -293,6 +299,7 @@ static void show_stack_log_lvl(struct ta
+ 		printk("%08lx ", *stack++);
+ 	}
+ 	printk("\n%sCall Trace:\n", log_lvl);
++
+ 	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+ 
+@@ -307,8 +314,8 @@ void show_stack(struct task_struct *task
+  */
+ void dump_stack(void)
+ {
+-	unsigned long stack;
+ 	unsigned long bp = 0;
++	unsigned long stack;
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ 	if (!bp)
+@@ -320,6 +327,7 @@ void dump_stack(void)
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
++
+ 	show_trace(current, NULL, &stack, bp);
+ }
+ 
+@@ -331,6 +339,7 @@ void show_registers(struct pt_regs *regs
+ 
+ 	print_modules();
+ 	__show_registers(regs, 0);
++
+ 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ 		TASK_COMM_LEN, current->comm, task_pid_nr(current),
+ 		current_thread_info(), current, task_thread_info(current));
+@@ -339,10 +348,10 @@ void show_registers(struct pt_regs *regs
+ 	 * time of the fault..
+ 	 */
+ 	if (!user_mode_vm(regs)) {
+-		u8 *ip;
+ 		unsigned int code_prologue = code_bytes * 43 / 64;
+ 		unsigned int code_len = code_bytes;
+ 		unsigned char c;
++		u8 *ip;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+ 		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
+@@ -369,7 +378,7 @@ void show_registers(struct pt_regs *regs
+ 		}
+ 	}
+ 	printk("\n");
+-}	
++}
+ 
+ int is_valid_bugaddr(unsigned long ip)
+ {
+@@ -385,10 +394,10 @@ int is_valid_bugaddr(unsigned long ip)
+ 
+ static int die_counter;
+ 
+-int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+-	unsigned long sp;
+ 	unsigned short ss;
++	unsigned long sp;
+ 
+ 	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+@@ -403,8 +412,8 @@ int __kprobes __die(const char * str, st
+ 	printk("\n");
+ 
+ 	if (notify_die(DIE_OOPS, str, regs, err,
+-				current->thread.trap_no, SIGSEGV) !=
+-			NOTIFY_STOP) {
++			current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
++
+ 		show_registers(regs);
+ 		/* Executive summary in case the oops scrolled away */
+ 		sp = (unsigned long) (&regs->sp);
+@@ -416,17 +425,18 @@ int __kprobes __die(const char * str, st
+ 		printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+ 		print_symbol("%s", regs->ip);
+ 		printk(" SS:ESP %04x:%08lx\n", ss, sp);
++
+ 		return 0;
+-	} else {
+-		return 1;
+ 	}
++
++	return 1;
+ }
+ 
+ /*
+- * This is gone through when something in the kernel has done something bad and
+- * is about to be terminated.
++ * This is gone through when something in the kernel has done something bad
++ * and is about to be terminated:
+  */
+-void die(const char * str, struct pt_regs * regs, long err)
++void die(const char *str, struct pt_regs *regs, long err)
+ {
+ 	static struct {
+ 		raw_spinlock_t lock;
+@@ -448,8 +458,9 @@ void die(const char * str, struct pt_reg
+ 		die.lock_owner = smp_processor_id();
+ 		die.lock_owner_depth = 0;
+ 		bust_spinlocks(1);
+-	} else
++	} else {
+ 		raw_local_irq_save(flags);
++	}
+ 
+ 	if (++die.lock_owner_depth < 3) {
+ 		report_bug(regs->ip, regs);
+@@ -482,19 +493,20 @@ void die(const char * str, struct pt_reg
+ 	do_exit(SIGSEGV);
+ }
+ 
+-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
++static inline void
++die_if_kernel(const char *str, struct pt_regs *regs, long err)
+ {
+ 	if (!user_mode_vm(regs))
+ 		die(str, regs, err);
+ }
+ 
+-static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
+-			      struct pt_regs * regs, long error_code,
+-			      siginfo_t *info)
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
++	long error_code, siginfo_t *info)
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	if (regs->flags & VM_MASK) {
++	if (regs->flags & X86_VM_MASK) {
+ 		if (vm86)
+ 			goto vm86_trap;
+ 		goto trap_signal;
+@@ -503,109 +515,112 @@ static void __kprobes do_trap(int trapnr
+ 	if (!user_mode(regs))
+ 		goto kernel_trap;
+ 
+-	trap_signal: {
+-		/*
+-		 * We want error_code and trap_no set for userspace faults and
+-		 * kernelspace faults which result in die(), but not
+-		 * kernelspace faults which are fixed up.  die() gives the
+-		 * process no chance to handle the signal and notice the
+-		 * kernel fault information, so that won't result in polluting
+-		 * the information about previously queued, but not yet
+-		 * delivered, faults.  See also do_general_protection below.
+-		 */
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = trapnr;
++trap_signal:
++	/*
++	 * We want error_code and trap_no set for userspace faults and
++	 * kernelspace faults which result in die(), but not
++	 * kernelspace faults which are fixed up.  die() gives the
++	 * process no chance to handle the signal and notice the
++	 * kernel fault information, so that won't result in polluting
++	 * the information about previously queued, but not yet
++	 * delivered, faults.  See also do_general_protection below.
++	 */
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
+ 
+-		if (info)
+-			force_sig_info(signr, info, tsk);
+-		else
+-			force_sig(signr, tsk);
+-		return;
+-	}
++	if (info)
++		force_sig_info(signr, info, tsk);
++	else
++		force_sig(signr, tsk);
++	return;
+ 
+-	kernel_trap: {
+-		if (!fixup_exception(regs)) {
+-			tsk->thread.error_code = error_code;
+-			tsk->thread.trap_no = trapnr;
+-			die(str, regs, error_code);
+-		}
+-		return;
++kernel_trap:
++	if (!fixup_exception(regs)) {
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++		die(str, regs, error_code);
+ 	}
++	return;
+ 
+-	vm86_trap: {
+-		int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
+-		if (ret) goto trap_signal;
+-		return;
+-	}
++vm86_trap:
++	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
++						error_code, trapnr))
++		goto trap_signal;
++	return;
+ }
+ 
+-#define DO_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+-}
+-
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	siginfo_t info; \
+-	if (irq) \
+-		local_irq_enable(); \
+-	info.si_signo = signr; \
+-	info.si_errno = 0; \
+-	info.si_code = sicode; \
+-	info.si_addr = (void __user *)siaddr; \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
+-}
+-
+-#define DO_VM86_ERROR(trapnr, signr, str, name) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
+-}
+-
+-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+-void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	siginfo_t info; \
+-	info.si_signo = signr; \
+-	info.si_errno = 0; \
+-	info.si_code = sicode; \
+-	info.si_addr = (void __user *)siaddr; \
+-	trace_hardirqs_fixup(); \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-						== NOTIFY_STOP) \
+-		return; \
+-	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
++#define DO_ERROR(trapnr, signr, str, name)				\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	trace_hardirqs_fixup();						\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 0, regs, error_code, NULL);		\
++}
++
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq)	\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	siginfo_t info;							\
++	if (irq)							\
++		local_irq_enable();					\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 0, regs, error_code, &info);	\
++}
++
++#define DO_VM86_ERROR(trapnr, signr, str, name)				\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 1, regs, error_code, NULL);		\
++}
++
++#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)	\
++void do_##name(struct pt_regs *regs, long error_code)			\
++{									\
++	siginfo_t info;							\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	trace_hardirqs_fixup();						\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++						== NOTIFY_STOP)		\
++		return;							\
++	do_trap(trapnr, signr, str, 1, regs, error_code, &info);	\
+ }
+ 
+-DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_VM86_ERROR_INFO(0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
+ #ifndef CONFIG_KPROBES
+-DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
++DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
+ #endif
+-DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+-DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
++DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO(6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
++DO_ERROR(9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
++DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ 
+ void __kprobes do_general_protection(struct pt_regs * regs,
+ 					      long error_code)
+ {
+-	if (regs->flags & VM_MASK)
++	struct thread_struct *thread;
++
++	thread = &current->thread;
++
++	if (regs->flags & X86_VM_MASK)
+ 		goto gp_in_vm86;
+ 
+ 	if (!user_mode(regs))
+@@ -613,6 +628,7 @@ void __kprobes do_general_protection(str
+ 
+ 	current->thread.error_code = error_code;
+ 	current->thread.trap_no = 13;
++
+ 	if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+ 	    printk_ratelimit()) {
+ 		printk(KERN_INFO
+@@ -642,22 +658,25 @@ gp_in_kernel:
+ 	}
+ }
+ 
+-static __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs *regs)
+ {
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+-		"CPU %d.\n", reason, smp_processor_id());
+-	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
++	printk(KERN_EMERG
++		"You have some hardware problem, likely on the PCI bus.\n");
+ 
+ #if defined(CONFIG_EDAC)
+-	if(edac_handler_set()) {
++	if (edac_handler_set()) {
+ 		edac_atomic_assert_error();
+ 		return;
+ 	}
+ #endif
+ 
+ 	if (panic_on_unrecovered_nmi)
+-                panic("NMI: Not continuing");
++		panic("NMI: Not continuing");
+ 
+ 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ 
+@@ -665,8 +684,8 @@ mem_parity_error(unsigned char reason, s
+ 	clear_mem_error(reason);
+ }
+ 
+-static __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++io_check_error(unsigned char reason, struct pt_regs *regs)
+ {
+ 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+ 	show_registers(regs);
+@@ -675,38 +694,43 @@ io_check_error(unsigned char reason, str
+ 	clear_io_check_error(reason);
+ }
+ 
+-static __kprobes void
+-unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++static notrace __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+ {
++	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
+ #ifdef CONFIG_MCA
+-	/* Might actually be able to figure out what the guilty party
+-	* is. */
+-	if( MCA_bus ) {
++	/*
++	 * Might actually be able to figure out what the guilty party
++	 * is:
++	 */
++	if (MCA_bus) {
+ 		mca_handle_nmi();
+ 		return;
+ 	}
+ #endif
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+-		"CPU %d.\n", reason, smp_processor_id());
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
+ 	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+ 	if (panic_on_unrecovered_nmi)
+-                panic("NMI: Not continuing");
++		panic("NMI: Not continuing");
+ 
+ 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ }
+ 
+ static DEFINE_SPINLOCK(nmi_print_lock);
+ 
+-void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
++void notrace __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ {
+-	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
+-	    NOTIFY_STOP)
++	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+ 		return;
+ 
+ 	spin_lock(&nmi_print_lock);
+ 	/*
+ 	* We are in trouble anyway, lets at least try
+-	* to get a message out.
++	* to get a message out:
+ 	*/
+ 	bust_spinlocks(1);
+ 	printk(KERN_EMERG "%s", msg);
+@@ -717,9 +741,10 @@ void __kprobes die_nmi(struct pt_regs *r
+ 	spin_unlock(&nmi_print_lock);
+ 	bust_spinlocks(0);
+ 
+-	/* If we are in kernel we are probably nested up pretty bad
+-	 * and might aswell get out now while we still can.
+-	*/
++	/*
++	 * If we are in kernel we are probably nested up pretty bad
++	 * and might aswell get out now while we still can:
++	 */
+ 	if (!user_mode_vm(regs)) {
+ 		current->thread.trap_no = 2;
+ 		crash_kexec(regs);
+@@ -728,14 +753,14 @@ void __kprobes die_nmi(struct pt_regs *r
+ 	do_exit(SIGSEGV);
+ }
+ 
+-static __kprobes void default_do_nmi(struct pt_regs * regs)
++static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
+ 
+-	/* Only the BSP gets external NMIs from the system.  */
++	/* Only the BSP gets external NMIs from the system: */
+ 	if (!smp_processor_id())
+ 		reason = get_nmi_reason();
+- 
++
+ 	if (!(reason & 0xc0)) {
+ 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+ 							== NOTIFY_STOP)
+@@ -748,8 +773,10 @@ static __kprobes void default_do_nmi(str
+ 		if (nmi_watchdog_tick(regs, reason))
+ 			return;
+ 		if (!do_nmi_callback(regs, smp_processor_id()))
+-#endif
+ 			unknown_nmi_error(reason, regs);
++#else
++		unknown_nmi_error(reason, regs);
++#endif
+ 
+ 		return;
+ 	}
+@@ -761,14 +788,14 @@ static __kprobes void default_do_nmi(str
+ 		io_check_error(reason, regs);
+ 	/*
+ 	 * Reassert NMI in case it became active meanwhile
+-	 * as it's edge-triggered.
++	 * as it's edge-triggered:
+ 	 */
+ 	reassert_nmi();
+ }
+ 
+ static int ignore_nmis;
+ 
+-__kprobes void do_nmi(struct pt_regs * regs, long error_code)
++notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+ {
+ 	int cpu;
+ 
+@@ -804,9 +831,12 @@ void __kprobes do_int3(struct pt_regs *r
+ 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+ 			== NOTIFY_STOP)
+ 		return;
+-	/* This is an interrupt gate, because kprobes wants interrupts
+-	disabled.  Normal trap handlers don't. */
++	/*
++	 * This is an interrupt gate, because kprobes wants interrupts
++	 * disabled. Normal trap handlers don't.
++	 */
+ 	restore_interrupts(regs);
++
+ 	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+ }
+ #endif
+@@ -821,7 +851,7 @@ void __kprobes do_int3(struct pt_regs *r
+  * from user space. Such code must not hold kernel locks (since it
+  * can equally take a page fault), therefore it is safe to call
+  * force_sig_info even though that claims and releases locks.
+- * 
++ *
+  * Code in ./signal.c ensures that the debug control register
+  * is restored before we deliver any signal, and therefore that
+  * user code runs with the correct debug control register even though
+@@ -833,10 +863,10 @@ void __kprobes do_int3(struct pt_regs *r
+  * find every occurrence of the TF bit that could be saved away even
+  * by user code)
+  */
+-void __kprobes do_debug(struct pt_regs * regs, long error_code)
++void __kprobes do_debug(struct pt_regs *regs, long error_code)
+ {
+-	unsigned int condition;
+ 	struct task_struct *tsk = current;
++	unsigned int condition;
+ 
+ 	trace_hardirqs_fixup();
+ 
+@@ -861,7 +891,7 @@ void __kprobes do_debug(struct pt_regs *
+ 			goto clear_dr7;
+ 	}
+ 
+-	if (regs->flags & VM_MASK)
++	if (regs->flags & X86_VM_MASK)
+ 		goto debug_vm86;
+ 
+ 	/* Save debug status register where ptrace can see it */
+@@ -884,7 +914,8 @@ void __kprobes do_debug(struct pt_regs *
+ 	/* Ok, finally something we can handle */
+ 	send_sigtrap(tsk, regs, error_code);
+ 
+-	/* Disable additional traps. They'll be re-enabled when
++	/*
++	 * Disable additional traps. They'll be re-enabled when
+ 	 * the signal is delivered.
+ 	 */
+ clear_dr7:
+@@ -897,7 +928,7 @@ debug_vm86:
+ 
+ clear_TF_reenable:
+ 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->flags &= ~TF_MASK;
++	regs->flags &= ~X86_EFLAGS_TF;
+ 	return;
+ }
+ 
+@@ -908,9 +939,10 @@ clear_TF_reenable:
+  */
+ void math_error(void __user *ip)
+ {
+-	struct task_struct * task;
++	struct task_struct *task;
++	unsigned short cwd;
++	unsigned short swd;
+ 	siginfo_t info;
+-	unsigned short cwd, swd;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -936,36 +968,36 @@ void math_error(void __user *ip)
+ 	cwd = get_fpu_cwd(task);
+ 	swd = get_fpu_swd(task);
+ 	switch (swd & ~cwd & 0x3f) {
+-		case 0x000: /* No unmasked exception */
+-			return;
+-		default:    /* Multiple exceptions */
+-			break;
+-		case 0x001: /* Invalid Op */
+-			/*
+-			 * swd & 0x240 == 0x040: Stack Underflow
+-			 * swd & 0x240 == 0x240: Stack Overflow
+-			 * User must clear the SF bit (0x40) if set
+-			 */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000: /* No unmasked exception */
++		return;
++	default:    /* Multiple exceptions */
++		break;
++	case 0x001: /* Invalid Op */
++		/*
++		 * swd & 0x240 == 0x040: Stack Underflow
++		 * swd & 0x240 == 0x240: Stack Overflow
++		 * User must clear the SF bit (0x40) if set
++		 */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-void do_coprocessor_error(struct pt_regs * regs, long error_code)
++void do_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ 	ignore_fpu_irq = 1;
+ 	math_error((void __user *)regs->ip);
+@@ -973,9 +1005,9 @@ void do_coprocessor_error(struct pt_regs
+ 
+ static void simd_math_error(void __user *ip)
+ {
+-	struct task_struct * task;
+-	siginfo_t info;
++	struct task_struct *task;
+ 	unsigned short mxcsr;
++	siginfo_t info;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -996,84 +1028,82 @@ static void simd_math_error(void __user 
+ 	 */
+ 	mxcsr = get_fpu_mxcsr(task);
+ 	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+-		case 0x000:
+-		default:
+-			break;
+-		case 0x001: /* Invalid Op */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000:
++	default:
++		break;
++	case 0x001: /* Invalid Op */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-void do_simd_coprocessor_error(struct pt_regs * regs,
+-					  long error_code)
++void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+ {
+ 	if (cpu_has_xmm) {
+ 		/* Handle SIMD FPU exceptions on PIII+ processors. */
+ 		ignore_fpu_irq = 1;
+ 		simd_math_error((void __user *)regs->ip);
+-	} else {
+-		/*
+-		 * Handle strange cache flush from user space exception
+-		 * in all other cases.  This is undocumented behaviour.
+-		 */
+-		if (regs->flags & VM_MASK) {
+-			handle_vm86_fault((struct kernel_vm86_regs *)regs,
+-					  error_code);
+-			return;
+-		}
+-		current->thread.trap_no = 19;
+-		current->thread.error_code = error_code;
+-		die_if_kernel("cache flush denied", regs, error_code);
+-		force_sig(SIGSEGV, current);
++		return;
++	}
++	/*
++	 * Handle strange cache flush from user space exception
++	 * in all other cases.  This is undocumented behaviour.
++	 */
++	if (regs->flags & X86_VM_MASK) {
++		handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
++		return;
+ 	}
++	current->thread.trap_no = 19;
++	current->thread.error_code = error_code;
++	die_if_kernel("cache flush denied", regs, error_code);
++	force_sig(SIGSEGV, current);
+ }
+ 
+ #ifndef CONFIG_XEN
+-void do_spurious_interrupt_bug(struct pt_regs * regs,
+-					  long error_code)
++void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+ {
+ #if 0
+ 	/* No need to warn about this any longer. */
+-	printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
++	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+ #endif
+ }
+ 
+-unsigned long patch_espfix_desc(unsigned long uesp,
+-					  unsigned long kesp)
++unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+ {
+ 	struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
+ 	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+ 	unsigned long new_kesp = kesp - base;
+ 	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+ 	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
++
+ 	/* Set up base for espfix segment */
+- 	desc &= 0x00f0ff0000000000ULL;
+- 	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
++	desc &= 0x00f0ff0000000000ULL;
++	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+ 		((((__u64)base) << 32) & 0xff00000000000000ULL) |
+ 		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+ 		(lim_pages & 0xffff);
+ 	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
++
+ 	return new_kesp;
+ }
+ #endif
+ 
+ /*
+- *  'math_state_restore()' saves the current math information in the
++ * 'math_state_restore()' saves the current math information in the
+  * old math state array, and gets the new ones from the current task
+  *
+  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+@@ -1087,9 +1117,22 @@ asmlinkage void math_state_restore(void)
+ 	struct thread_info *thread = current_thread_info();
+ 	struct task_struct *tsk = thread->task;
+ 
++	if (!tsk_used_math(tsk)) {
++		local_irq_enable();
++		/*
++		 * does a slab alloc which can sleep
++		 */
++		if (init_fpu(tsk)) {
++			/*
++			 * ran out of memory!
++			 */
++			do_group_exit(SIGKILL);
++			return;
++		}
++		local_irq_disable();
++	}
++
+ 	/* NB. 'clts' is done for us by Xen during virtual trap. */
+-	if (!tsk_used_math(tsk))
+-		init_fpu(tsk);
+ 	restore_fpu(tsk);
+ 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+ 	tsk->fpu_counter++;
+@@ -1100,15 +1143,15 @@ EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+ asmlinkage void math_emulate(long arg)
+ {
+-	printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
+-	printk(KERN_EMERG "killing %s.\n",current->comm);
+-	force_sig(SIGFPE,current);
++	printk(KERN_EMERG
++		"math-emulation not enabled and no coprocessor found.\n");
++	printk(KERN_EMERG "killing %s.\n", current->comm);
++	force_sig(SIGFPE, current);
+ 	schedule();
+ }
+ 
+ #endif /* CONFIG_MATH_EMULATION */
+ 
+-
+ /*
+  * NB. All these are "trap gates" (i.e. events_mask isn't set) except
+  * for those that specify <dpl>|4 in the second field.
+@@ -1146,25 +1189,21 @@ void __init trap_init(void)
+ 	if (ret)
+ 		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+ 
+-	/*
+-	 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+-	 * Generate a build-time error if the alignment is wrong.
+-	 */
+-	BUILD_BUG_ON(offsetof(struct task_struct, thread.i387.fxsave) & 15);
+ 	if (cpu_has_fxsr) {
+ 		printk(KERN_INFO "Enabling fast FPU save and restore... ");
+ 		set_in_cr4(X86_CR4_OSFXSR);
+ 		printk("done.\n");
+ 	}
+ 	if (cpu_has_xmm) {
+-		printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
+-				"support... ");
++		printk(KERN_INFO
++			"Enabling unmasked SIMD FPU exception support... ");
+ 		set_in_cr4(X86_CR4_OSXMMEXCPT);
+ 		printk("done.\n");
+ 	}
+ 
++	init_thread_xstate();
+ 	/*
+-	 * Should be a barrier for any external CPU state.
++	 * Should be a barrier for any external CPU state:
+ 	 */
+ 	cpu_init();
+ }
+@@ -1183,6 +1222,7 @@ void __cpuinit smp_trap_init(trap_info_t
+ static int __init kstack_setup(char *s)
+ {
+ 	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
++
+ 	return 1;
+ }
+ __setup("kstack=", kstack_setup);
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -33,6 +33,8 @@
+ #include <linux/kdebug.h>
+ #include <linux/utsname.h>
+ 
++#include <mach_traps.h>
++
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+ #endif
+@@ -601,10 +603,16 @@ void die(const char * str, struct pt_reg
+ }
+ 
+ #if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_SYSCTL)
+-void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
++notrace __kprobes void
++die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+-	unsigned long flags = oops_begin();
++	unsigned long flags;
++
++	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
++	    NOTIFY_STOP)
++		return;
+ 
++	flags = oops_begin();
+ 	/*
+ 	 * We are in trouble anyway, lets at least try
+ 	 * to get a message out.
+@@ -769,7 +777,7 @@ asmlinkage void __kprobes do_general_pro
+ 	die("general protection fault", regs, error_code);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+@@ -792,7 +800,7 @@ mem_parity_error(unsigned char reason, s
+ 	clear_mem_error(reason);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+ 	printk("NMI: IOCK error (debug interrupt?)\n");
+@@ -802,9 +810,11 @@ io_check_error(unsigned char reason, str
+ 	clear_io_check_error(reason);
+ }
+ 
+-static __kprobes void
++static notrace __kprobes void
+ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ {
++	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ 		reason);
+ 	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+@@ -817,7 +827,7 @@ unknown_nmi_error(unsigned char reason, 
+ 
+ /* Runs on IST stack. This code must keep interrupts off all the time.
+    Nested NMIs are prevented by the CPU. */
+-asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
++asmlinkage notrace  __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
+ 	int cpu;
+@@ -1117,11 +1127,25 @@ asmlinkage void __attribute__((weak)) mc
+ asmlinkage void math_state_restore(void)
+ {
+ 	struct task_struct *me = current;
++
++	if (!used_math()) {
++		local_irq_enable();
++		/*
++		 * does a slab alloc which can sleep
++		 */
++		if (init_fpu(me)) {
++			/*
++			 * ran out of memory!
++			 */
++			do_group_exit(SIGKILL);
++			return;
++		}
++		local_irq_disable();
++	}
++
+         /* clts(); */ /* 'clts' is done for us by Xen during virtual trap. */
+ 
+-	if (!used_math())
+-		init_fpu(me);
+-	restore_fpu_checking(&me->thread.i387.fxsave);
++	restore_fpu_checking(&me->thread.xstate->fxsave);
+ 	task_thread_info(me)->status |= TS_USEDFPU;
+ 	me->fpu_counter++;
+ }
+@@ -1168,6 +1192,10 @@ void __init trap_init(void)
+ 		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+ 
+ 	/*
++	 * initialize the per thread extended state:
++	 */
++        init_thread_xstate();
++	/*
+ 	 * Should be a barrier for any external CPU state.
+ 	 */
+ 	cpu_init();
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -216,7 +216,7 @@ vgetcpu(unsigned *cpu, unsigned *node, s
+ 	return 0;
+ }
+ 
+-long __vsyscall(3) venosys_1(void)
++static long __vsyscall(3) venosys_1(void)
+ {
+ 	return -ENOSYS;
+ }
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2009-12-03 15:47:58.000000000 +0100
+@@ -56,11 +56,7 @@ char * __init machine_specific_memory_se
+ {
+ 	int rc;
+ 	struct xen_memory_map memmap;
+-	/*
+-	 * This is rather large for a stack variable but this early in
+-	 * the boot process we know we have plenty slack space.
+-	 */
+-	struct e820entry map[E820MAX];
++	static struct e820entry __initdata map[E820MAX];
+ 
+ 	memmap.nr_entries = E820MAX;
+ 	set_xen_guest_handle(memmap.buffer, map);
+--- head-2010-01-18.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -510,6 +510,11 @@ static int vmalloc_fault(unsigned long a
+ 	unsigned long pgd_paddr;
+ 	pmd_t *pmd_k;
+ 	pte_t *pte_k;
++
++	/* Make sure we are in vmalloc area */
++	if (!(address >= VMALLOC_START && address < VMALLOC_END))
++		return -1;
++
+ 	/*
+ 	 * Synchronize this task's top level page-table
+ 	 * with the 'reference' page table.
+@@ -670,7 +675,7 @@ void __kprobes do_page_fault(struct pt_r
+ #ifdef CONFIG_X86_32
+ 	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+ 	   fault has been handled. */
+-	if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
++	if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
+ 		local_irq_enable();
+ 
+ 	/*
+@@ -1017,9 +1022,5 @@ void vmalloc_sync_all(void)
+ 		if (address == start)
+ 			start = address + PGDIR_SIZE;
+ 	}
+-	/* Check that there is no need to do the same for the modules area. */
+-	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+-	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+-				(__START_KERNEL & PGDIR_MASK)));
+ #endif
+ }
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -200,6 +200,8 @@ EXPORT_SYMBOL(kmap);
+ EXPORT_SYMBOL(kunmap);
+ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
++#ifdef CONFIG_HIGHPTE
+ EXPORT_SYMBOL(kmap_atomic_to_page);
++#endif
+ EXPORT_SYMBOL(clear_highpage);
+ EXPORT_SYMBOL(copy_highpage);
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,4 @@
+ /*
+- *  linux/arch/i386/mm/init.c
+  *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+@@ -22,6 +21,7 @@
+ #include <linux/init.h>
+ #include <linux/highmem.h>
+ #include <linux/pagemap.h>
++#include <linux/pci.h>
+ #include <linux/pfn.h>
+ #include <linux/poison.h>
+ #include <linux/bootmem.h>
+@@ -54,6 +54,8 @@
+ 
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+ 
++unsigned long max_pfn_mapped;
++
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+ 
+@@ -73,7 +75,7 @@ static pmd_t * __init one_md_table_init(
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+ 		pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ 
+-		paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
++		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+ 		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ 		pud = pud_offset(pgd, 0);
+@@ -107,7 +109,7 @@ static pte_t * __init one_page_table_ini
+ 				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ 		}
+ 
+-		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
++		paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+ 					  XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+@@ -209,8 +211,13 @@ static void __init kernel_physical_mappi
+ 			/*
+ 			 * Map with big pages if possible, otherwise
+ 			 * create normal page tables:
++			 *
++			 * Don't use a large page for the first 2/4MB of memory
++			 * because there are often fixed size MTRRs in there
++			 * and overlapping MTRRs into large pages can cause
++			 * slowdowns.
+ 			 */
+-			if (cpu_has_pse) {
++			if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) {
+ 				unsigned int addr2;
+ 				pgprot_t prot = PAGE_KERNEL_LARGE;
+ 
+@@ -224,6 +231,7 @@ static void __init kernel_physical_mappi
+ 				set_pmd(pmd, pfn_pmd(pfn, prot));
+ 
+ 				pfn += PTRS_PER_PTE;
++				max_pfn_mapped = pfn;
+ 				continue;
+ 			}
+ 			pte = one_page_table_init(pmd);
+@@ -241,6 +249,7 @@ static void __init kernel_physical_mappi
+ 
+ 				set_pte(pte, pfn_pte(pfn, prot));
+ 			}
++			max_pfn_mapped = pfn;
+ 			pte_ofs = 0;
+ 		}
+ 		pmd_idx = 0;
+@@ -262,6 +271,25 @@ static inline int page_kills_ppro(unsign
+ 
+ #endif
+ 
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++	if (pagenr <= 256)
++		return 1;
++	if (mfn_to_local_pfn(pagenr) >= max_pfn)
++		return 1;
++	return 0;
++}
++
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+@@ -303,47 +331,17 @@ static void __init permanent_kmaps_init(
+ 	pkmap_page_table = pte;
+ }
+ 
+-static void __meminit free_new_highpage(struct page *page, int pfn)
+-{
+-	init_page_count(page);
+-	__free_page(page);
+-	totalhigh_pages++;
+-}
+-
+ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
+ {
+ 	if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
+ 		ClearPageReserved(page);
+-		free_new_highpage(page, pfn);
++		init_page_count(page);
++		__free_page(page);
++		totalhigh_pages++;
+ 	} else
+ 		SetPageReserved(page);
+ }
+ 
+-static int __meminit
+-add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+-{
+-	free_new_highpage(page, pfn);
+-	totalram_pages++;
+-#ifdef CONFIG_FLATMEM
+-	max_mapnr = max(pfn, max_mapnr);
+-#endif
+-	num_physpages++;
+-
+-	return 0;
+-}
+-
+-/*
+- * Not currently handling the NUMA case.
+- * Assuming single node and all memory that
+- * has been added dynamically that would be
+- * onlined here is in HIGHMEM.
+- */
+-void __meminit online_page(struct page *page)
+-{
+-	ClearPageReserved(page);
+-	add_one_highpage_hotplug(page, page_to_pfn(page));
+-}
+-
+ #ifndef CONFIG_NUMA
+ static void __init set_highmem_pages_init(int bad_ppro)
+ {
+@@ -466,15 +464,13 @@ void zap_low_mappings(void)
+ {
+ 	int i;
+ 
+-	save_pg_dir();
+-
+ 	/*
+ 	 * Zap initial low-memory mappings.
+ 	 *
+ 	 * Note that "pgd_clear()" doesn't do it for
+ 	 * us, because pgd_clear() is a no-op on i386.
+ 	 */
+-	for (i = 0; i < USER_PTRS_PER_PGD; i++) {
++	for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
+ #if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
+ 		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
+ #else
+@@ -579,9 +575,9 @@ void __init paging_init(void)
+ 
+ /*
+  * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+- * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
+- * used to involve black magic jumps to work around some nasty CPU bugs,
+- * but fortunately the switch to using exceptions got rid of all that.
++ * and also on some strange 486's. All 586+'s are OK. This used to involve
++ * black magic jumps to work around some nasty CPU bugs, but fortunately the
++ * switch to using exceptions got rid of all that.
+  */
+ static void __init test_wp_bit(void)
+ {
+@@ -612,9 +608,7 @@ void __init mem_init(void)
+ 	int tmp, bad_ppro;
+ 	unsigned long pfn;
+ 
+-#if defined(CONFIG_SWIOTLB)
+-	swiotlb_init();	
+-#endif
++	pci_iommu_alloc();
+ 
+ #ifdef CONFIG_FLATMEM
+ 	BUG_ON(!mem_map);
+@@ -716,16 +710,8 @@ void __init mem_init(void)
+ 		test_wp_bit();
+ 
+ 	cpa_init();
+-
+-	/*
+-	 * Subtle. SMP is doing it's boot stuff late (because it has to
+-	 * fork idle threads) - but it also needs low mappings for the
+-	 * protected-mode entry to work. We zap these entries only after
+-	 * the WP-bit has been tested.
+-	 */
+-#ifndef CONFIG_SMP
++	save_pg_dir();
+ 	zap_low_mappings();
+-#endif
+ 
+ 	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+@@ -775,25 +761,17 @@ void mark_rodata_ro(void)
+ 	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long size = PFN_ALIGN(_etext) - start;
+ 
+-#ifndef CONFIG_KPROBES
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* It must still be possible to apply SMP alternatives. */
+-	if (num_possible_cpus() <= 1)
+-#endif
+-	{
+-		set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+-		printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+-			size >> 10);
++	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++	printk(KERN_INFO "Write protecting the kernel text: %luk\n",
++		size >> 10);
+ 
+ #ifdef CONFIG_CPA_DEBUG
+-		printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
+-			start, start+size);
+-		set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
++	printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
++		start, start+size);
++	set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
+ 
+-		printk(KERN_INFO "Testing CPA: write protecting again\n");
+-		set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+-#endif
+-	}
++	printk(KERN_INFO "Testing CPA: write protecting again\n");
++	set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+ #endif
+ 	start += size;
+ 	size = (unsigned long)__end_rodata - start;
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -52,9 +52,6 @@
+ 
+ #include <xen/features.h>
+ 
+-const struct dma_mapping_ops *dma_ops;
+-EXPORT_SYMBOL(dma_ops);
+-
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ unsigned int __kernel_page_user;
+ EXPORT_SYMBOL(__kernel_page_user);
+@@ -120,6 +117,28 @@ void __meminit early_make_page_readonly(
+ 		BUG();
+ }
+ 
++#ifndef CONFIG_XEN
++int direct_gbpages __meminitdata
++#ifdef CONFIG_DIRECT_GBPAGES
++				= 1
++#endif
++;
++
++static int __init parse_direct_gbpages_off(char *arg)
++{
++	direct_gbpages = 0;
++	return 0;
++}
++early_param("nogbpages", parse_direct_gbpages_off);
++
++static int __init parse_direct_gbpages_on(char *arg)
++{
++	direct_gbpages = 1;
++	return 0;
++}
++early_param("gbpages", parse_direct_gbpages_on);
++#endif
++
+ /*
+  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+  * physical space so we can cache the place of the first one and move
+@@ -135,9 +154,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n",
+-		nr_swap_pages << (PAGE_SHIFT-10));
+-
+ 	for_each_online_pgdat(pgdat) {
+ 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+ 			/*
+@@ -328,7 +344,7 @@ void __init cleanup_highmap(void)
+ 	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
+ 
+ 	for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
+-		if (!pmd_present(*pmd))
++		if (pmd_none(*pmd))
+ 			continue;
+ 		if (vaddr < (unsigned long) _text || vaddr > end)
+ 			set_pmd(pmd, __pmd(0));
+@@ -337,8 +353,7 @@ void __init cleanup_highmap(void)
+ #endif
+ 
+ /* NOTE: this is meant to be run only at boot */
+-void __init
+-__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+ {
+ 	unsigned long address = __fix_to_virt(idx);
+ 
+@@ -463,7 +478,7 @@ __meminit void early_iounmap(void *addr,
+ }
+ #endif
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ {
+ 	int i = pmd_index(address);
+@@ -503,21 +518,26 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ 			set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
+ 		}
+ 	}
++	return address;
+ }
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+ {
+ 	pmd_t *pmd = pmd_offset(pud, 0);
++	unsigned long last_map_addr;
++
+ 	spin_lock(&init_mm.page_table_lock);
+-	phys_pmd_init(pmd, address, end);
++	last_map_addr = phys_pmd_init(pmd, address, end);
+ 	spin_unlock(&init_mm.page_table_lock);
+ 	__flush_tlb_all();
++	return last_map_addr;
+ }
+ 
+-static void __meminit
++static unsigned long __meminit
+ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ {
++	unsigned long last_map_addr = end;
+ 	int i = pud_index(addr);
+ 
+ 	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+@@ -529,7 +549,15 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 			break;
+ 
+ 		if (__pud_val(*pud)) {
+-			phys_pmd_update(pud, addr, end);
++			if (!pud_large(*pud))
++				last_map_addr = phys_pmd_update(pud, addr, end);
++			continue;
++		}
++
++		if (direct_gbpages) {
++			set_pte((pte_t *)pud,
++				pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++			last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+ 			continue;
+ 		}
+ 
+@@ -537,12 +565,14 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 
+ 		spin_lock(&init_mm.page_table_lock);
+ 		*pud = __pud(pmd_phys | _KERNPG_TABLE);
+-		phys_pmd_init(pmd, addr, end);
++		last_map_addr = phys_pmd_init(pmd, addr, end);
+ 		spin_unlock(&init_mm.page_table_lock);
+ 
+ 		early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 	}
+ 	__flush_tlb_all();
++
++	return last_map_addr >> PAGE_SHIFT;
+ }
+ 
+ void __init xen_init_pt(void)
+@@ -785,16 +815,138 @@ static void __init xen_finish_init_mappi
+ 	table_end = start_pfn;
+ }
+ 
++static void __init init_gbpages(void)
++{
++#ifndef CONFIG_XEN
++	if (direct_gbpages && cpu_has_gbpages)
++		printk(KERN_INFO "Using GB pages for direct mapping\n");
++	else
++		direct_gbpages = 0;
++#endif
++}
++
++#ifdef CONFIG_MEMTEST_BOOTPARAM
++
++static void __init memtest(unsigned long start_phys, unsigned long size,
++				 unsigned pattern)
++{
++	unsigned long i;
++	unsigned long *start;
++	unsigned long start_bad;
++	unsigned long last_bad;
++	unsigned long val;
++	unsigned long start_phys_aligned;
++	unsigned long count;
++	unsigned long incr;
++
++	switch (pattern) {
++	case 0:
++		val = 0UL;
++		break;
++	case 1:
++		val = -1UL;
++		break;
++	case 2:
++		val = 0x5555555555555555UL;
++		break;
++	case 3:
++		val = 0xaaaaaaaaaaaaaaaaUL;
++		break;
++	default:
++		return;
++	}
++
++	incr = sizeof(unsigned long);
++	start_phys_aligned = ALIGN(start_phys, incr);
++	count = (size - (start_phys_aligned - start_phys))/incr;
++	start = __va(start_phys_aligned);
++	start_bad = 0;
++	last_bad = 0;
++
++	for (i = 0; i < count; i++)
++		start[i] = val;
++	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
++		if (*start != val) {
++			if (start_phys_aligned == last_bad + incr) {
++				last_bad += incr;
++			} else {
++				if (start_bad) {
++					printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
++						val, start_bad, last_bad + incr);
++					reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++				}
++				start_bad = last_bad = start_phys_aligned;
++			}
++		}
++	}
++	if (start_bad) {
++		printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
++			val, start_bad, last_bad + incr);
++		reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
++	}
++
++}
++
++static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
++
++static int __init parse_memtest(char *arg)
++{
++	if (arg)
++		memtest_pattern = simple_strtoul(arg, NULL, 0);
++	return 0;
++}
++
++early_param("memtest", parse_memtest);
++
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++	u64 t_start, t_size;
++	unsigned pattern;
++
++	if (!memtest_pattern)
++		return;
++
++	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
++	for (pattern = 0; pattern < memtest_pattern; pattern++) {
++		t_start = start;
++		t_size = 0;
++		while (t_start < end) {
++			t_start = find_e820_area_size(t_start, &t_size, 1);
++
++			/* done ? */
++			if (t_start >= end)
++				break;
++			if (t_start + t_size > end)
++				t_size = end - t_start;
++
++			printk(KERN_CONT "\n  %016llx - %016llx pattern %d",
++				(unsigned long long)t_start,
++				(unsigned long long)t_start + t_size, pattern);
++
++			memtest(t_start, t_size, pattern);
++
++			t_start += t_size;
++		}
++	}
++	printk(KERN_CONT "\n");
++}
++#else
++static void __init early_memtest(unsigned long start, unsigned long end)
++{
++}
++#endif
++
+ /*
+  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+  * This runs before bootmem is initialized and gets pages directly from
+  * the physical memory. To access them they are temporarily mapped.
+  */
+-void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
++unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ {
+-	unsigned long next;
++	unsigned long next, last_map_addr = end;
++	unsigned long start_phys = start, end_phys = end;
+ 
+-	pr_debug("init_memory_mapping\n");
++	printk(KERN_INFO "init_memory_mapping\n");
+ 
+ 	/*
+ 	 * Find space for the kernel direct mapping tables.
+@@ -803,8 +955,10 @@ void __init_refok init_memory_mapping(un
+ 	 * memory mapped. Unfortunately this is done currently before the
+ 	 * nodes are discovered.
+ 	 */
+-	if (!after_bootmem)
++	if (!after_bootmem) {
++		init_gbpages();
+ 		find_early_table_space(end);
++	}
+ 
+ 	start = (unsigned long)__va(start);
+ 	end = (unsigned long)__va(end);
+@@ -821,7 +975,7 @@ void __init_refok init_memory_mapping(un
+ 		next = start + PGDIR_SIZE;
+ 		if (next > end)
+ 			next = end;
+-		phys_pud_init(pud, __pa(start), __pa(next));
++		last_map_addr = phys_pud_init(pud, __pa(start), __pa(next));
+ 		if (!after_bootmem) {
+ 			early_make_page_readonly(pud, XENFEAT_writable_page_tables);
+ 			set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
+@@ -838,6 +992,11 @@ void __init_refok init_memory_mapping(un
+ 	if (!after_bootmem)
+ 		reserve_early(table_start << PAGE_SHIFT,
+ 			      table_end << PAGE_SHIFT, "PGTABLE");
++
++	if (!after_bootmem)
++		early_memtest(start_phys, end_phys);
++
++	return last_map_addr;
+ }
+ 
+ #ifndef CONFIG_NUMA
+@@ -861,15 +1020,6 @@ void __init paging_init(void)
+ /*
+  * Memory hotplug specific functions
+  */
+-void online_page(struct page *page)
+-{
+-	ClearPageReserved(page);
+-	init_page_count(page);
+-	__free_page(page);
+-	totalram_pages++;
+-	num_physpages++;
+-}
+-
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ /*
+  * Memory is added always to NORMAL zone. This means you will never get
+@@ -879,11 +1029,13 @@ int arch_add_memory(int nid, u64 start, 
+ {
+ 	struct pglist_data *pgdat = NODE_DATA(nid);
+ 	struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+-	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 	int ret;
+ 
+-	init_memory_mapping(start, start + size-1);
++	last_mapped_pfn = init_memory_mapping(start, start + size-1);
++	if (last_mapped_pfn > max_pfn_mapped)
++		max_pfn_mapped = last_mapped_pfn;
+ 
+ 	ret = __add_pages(zone, start_pfn, nr_pages);
+ 	WARN_ON(1);
+@@ -902,6 +1054,26 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
+ 
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
++/*
++ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
++ * is valid. The argument is a physical page number.
++ *
++ *
++ * On x86, access has to be given to the first megabyte of ram because that area
++ * contains bios code and data regions used by X and dosemu and similar apps.
++ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
++ * mmio resources as well as potential bios/acpi data regions.
++ */
++int devmem_is_allowed(unsigned long pagenr)
++{
++	if (pagenr <= 256)
++		return 1;
++	if (mfn_to_local_pfn(pagenr) >= max_pfn)
++		return 1;
++	return 0;
++}
++
++
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
+ 			 kcore_modules, kcore_vsyscall;
+ 
+@@ -1009,24 +1181,7 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long start = (unsigned long)_stext, end;
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-	/* It must still be possible to apply SMP alternatives. */
+-	if (num_possible_cpus() > 1)
+-		start = (unsigned long)_etext;
+-#endif
+-
+-#ifdef CONFIG_KPROBES
+-	start = (unsigned long)__start_rodata;
+-#endif
+-
+-	end = (unsigned long)__end_rodata;
+-	start = (start + PAGE_SIZE - 1) & PAGE_MASK;
+-	end &= PAGE_MASK;
+-	if (end <= start)
+-		return;
+-
++	unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
+ 
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
+@@ -1049,6 +1204,7 @@ void mark_rodata_ro(void)
+ 	set_memory_ro(start, (end-start) >> PAGE_SHIFT);
+ #endif
+ }
++
+ #endif
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+@@ -1061,7 +1217,7 @@ void free_initrd_mem(unsigned long start
+ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+ {
+ #ifdef CONFIG_NUMA
+-	int nid = phys_to_nid(phys);
++	int nid, next_nid;
+ #endif
+ 	unsigned long pfn = phys >> PAGE_SHIFT;
+ 
+@@ -1070,7 +1226,7 @@ void __init reserve_bootmem_generic(unsi
+ 		 * This can happen with kdump kernels when accessing
+ 		 * firmware tables:
+ 		 */
+-		if (pfn < end_pfn_map)
++		if (pfn < max_pfn_mapped)
+ 			return;
+ 
+ 		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+@@ -1080,10 +1236,16 @@ void __init reserve_bootmem_generic(unsi
+ 
+ 	/* Should check here against the e820 map to avoid double free */
+ #ifdef CONFIG_NUMA
+-	reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++	nid = phys_to_nid(phys);
++	next_nid = phys_to_nid(phys + len - 1);
++	if (nid == next_nid)
++		reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++	else
++		reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #else
+ 	reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #endif
++
+ #ifndef CONFIG_XEN
+ 	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
+ 		dma_reserve += len / PAGE_SIZE;
+@@ -1179,6 +1341,10 @@ const char *arch_vma_name(struct vm_area
+ /*
+  * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
+  */
++static long __meminitdata addr_start, addr_end;
++static void __meminitdata *p_start, *p_end;
++static int __meminitdata node_start;
++
+ int __meminit
+ vmemmap_populate(struct page *start_page, unsigned long size, int node)
+ {
+@@ -1213,12 +1379,32 @@ vmemmap_populate(struct page *start_page
+ 							PAGE_KERNEL_LARGE);
+ 			set_pmd(pmd, __pmd_ma(__pte_val(entry)));
+ 
+-			printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
+-				addr, addr + PMD_SIZE - 1, p, node);
++			/* check to see if we have contiguous blocks */
++			if (p_end != p || node_start != node) {
++				if (p_start)
++					printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
++						addr_start, addr_end-1, p_start, p_end-1, node_start);
++				addr_start = addr;
++				node_start = node;
++				p_start = p;
++			}
++			addr_end = addr + PMD_SIZE;
++			p_end = p + PMD_SIZE;
+ 		} else {
+ 			vmemmap_verify((pte_t *)pmd, node, addr, next);
+ 		}
+ 	}
+ 	return 0;
+ }
++
++void __meminit vmemmap_populate_print_last(void)
++{
++	if (p_start) {
++		printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
++			addr_start, addr_end-1, p_start, p_end-1, node_start);
++		p_start = NULL;
++		p_end = NULL;
++		node_start = 0;
++	}
++}
+ #endif
+--- head-2010-01-18.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -20,14 +20,11 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/pgalloc.h>
++#include <asm/pat.h>
+ 
+-enum ioremap_mode {
+-	IOR_MODE_UNCACHED,
+-	IOR_MODE_CACHED,
+-};
+-
+-#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++#ifdef CONFIG_X86_64
+ 
++#ifndef CONFIG_XEN
+ unsigned long __phys_addr(unsigned long x)
+ {
+ 	if (x >= __START_KERNEL_map)
+@@ -35,6 +32,19 @@ unsigned long __phys_addr(unsigned long 
+ 	return x - PAGE_OFFSET;
+ }
+ EXPORT_SYMBOL(__phys_addr);
++#endif
++
++static inline int phys_addr_valid(unsigned long addr)
++{
++	return addr < (1UL << boot_cpu_data.x86_phys_bits);
++}
++
++#else
++
++static inline int phys_addr_valid(unsigned long addr)
++{
++	return 1;
++}
+ 
+ #endif
+ 
+@@ -92,7 +102,8 @@ static int __direct_remap_pfn_range(stru
+ 		 * Fill in the machine address: PTE ptr is done later by
+ 		 * apply_to_page_range().
+ 		 */
+-		v->val = __pte_val(pfn_pte_ma(mfn, prot)) | _PAGE_IO;
++		pgprot_val(prot) |= _PAGE_IO;
++		v->val = __pte_val(pte_mkspecial(pfn_pte_ma(mfn, prot)));
+ 
+ 		mfn++;
+ 		address += PAGE_SIZE;
+@@ -189,10 +200,9 @@ int touch_pte_range(struct mm_struct *mm
+ 
+ EXPORT_SYMBOL(touch_pte_range);
+ 
+-#ifdef CONFIG_X86_32
+ int page_is_ram(unsigned long pagenr)
+ {
+-	unsigned long addr, end;
++	resource_size_t addr, end;
+ 	int i;
+ 
+ #ifndef CONFIG_XEN
+@@ -228,31 +238,51 @@ int page_is_ram(unsigned long pagenr)
+ 	}
+ 	return 0;
+ }
+-#endif
+ 
+ /*
+  * Fix up the linear direct mapping of the kernel to avoid cache attribute
+  * conflicts.
+  */
+ static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+-			       enum ioremap_mode mode)
++			       unsigned long prot_val)
+ {
+ 	unsigned long nrpages = size >> PAGE_SHIFT;
+ 	int err;
+ 
+-	switch (mode) {
+-	case IOR_MODE_UNCACHED:
++	switch (prot_val) {
++	case _PAGE_CACHE_UC:
+ 	default:
+-		err = set_memory_uc(vaddr, nrpages);
++		err = _set_memory_uc(vaddr, nrpages);
++		break;
++	case _PAGE_CACHE_WC:
++		err = _set_memory_wc(vaddr, nrpages);
+ 		break;
+-	case IOR_MODE_CACHED:
+-		err = set_memory_wb(vaddr, nrpages);
++	case _PAGE_CACHE_WB:
++		err = _set_memory_wb(vaddr, nrpages);
+ 		break;
+ 	}
+ 
+ 	return err;
+ }
+ 
++int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
++			      unsigned long prot_val)
++{
++	unsigned long sz;
++	int rc;
++
++	for (sz = rc = 0; sz < size && !rc; ++mfn, sz += PAGE_SIZE) {
++		unsigned long pfn = mfn_to_local_pfn(mfn);
++
++		if (pfn >= max_pfn_mapped)
++			continue;
++		rc = ioremap_change_attr((unsigned long)__va(pfn << PAGE_SHIFT),
++					 PAGE_SIZE, prot_val);
++	}
++
++	return rc;
++}
++
+ /*
+  * Remap an arbitrary physical address space into the kernel virtual
+  * address space. Needed when the kernel wants to access high addresses
+@@ -262,12 +292,15 @@ static int ioremap_change_attr(unsigned 
+  * have to convert them into an offset in a page-aligned mapping, but the
+  * caller shouldn't need to know that small detail.
+  */
+-static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+-			       enum ioremap_mode mode)
++static void __iomem *__ioremap_caller(resource_size_t phys_addr,
++		unsigned long size, unsigned long prot_val, void *caller)
+ {
+-	unsigned long mfn, offset, last_addr, vaddr;
++	unsigned long mfn, offset, vaddr;
++	resource_size_t last_addr;
+ 	struct vm_struct *area;
++	unsigned long new_prot_val;
+ 	pgprot_t prot;
++	int retval;
+ 	domid_t domid = DOMID_IO;
+ 
+ 	/* Don't allow wraparound or zero size */
+@@ -275,6 +308,13 @@ static void __iomem *__ioremap(resource_
+ 	if (!size || last_addr < phys_addr)
+ 		return NULL;
+ 
++	if (!phys_addr_valid(phys_addr)) {
++		printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
++		       (unsigned long long)phys_addr);
++		WARN_ON_ONCE(1);
++		return NULL;
++	}
++
+ 	/*
+ 	 * Don't remap the low PCI/ISA area, it's always mapped..
+ 	 */
+@@ -287,55 +327,86 @@ static void __iomem *__ioremap(resource_
+ 	for (mfn = PFN_DOWN(phys_addr); mfn < PFN_UP(last_addr); mfn++) {
+ 		unsigned long pfn = mfn_to_local_pfn(mfn);
+ 
+-		if (pfn >= max_pfn)
+-			continue;
++		if (pfn_valid(pfn)) {
++			if (!PageReserved(pfn_to_page(pfn)))
++				return NULL;
++			domid = DOMID_SELF;
++		}
++	}
++	WARN_ON_ONCE(domid == DOMID_SELF);
+ 
+-		domid = DOMID_SELF;
++	/*
++	 * Mappings have to be page-aligned
++	 */
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
++	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+ 
+-		if (pfn >= max_pfn_mapped) /* bogus */
+-			continue;
++	retval = reserve_memtype(phys_addr, phys_addr + size,
++						prot_val, &new_prot_val);
++	if (retval) {
++		pr_debug("Warning: reserve_memtype returned %d\n", retval);
++		return NULL;
++	}
+ 
+-		if (pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
++	if (prot_val != new_prot_val) {
++		/*
++		 * Do not fallback to certain memory types with certain
++		 * requested type:
++		 * - request is uc-, return cannot be write-back
++		 * - request is uc-, return cannot be write-combine
++		 * - request is write-combine, return cannot be write-back
++		 */
++		if ((prot_val == _PAGE_CACHE_UC_MINUS &&
++		     (new_prot_val == _PAGE_CACHE_WB ||
++		      new_prot_val == _PAGE_CACHE_WC)) ||
++		    (prot_val == _PAGE_CACHE_WC &&
++		     new_prot_val == _PAGE_CACHE_WB)) {
++			pr_debug(
++		"ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
++				(unsigned long long)phys_addr,
++				(unsigned long long)(phys_addr + size),
++				prot_val, new_prot_val);
++			free_memtype(phys_addr, phys_addr + size);
+ 			return NULL;
++		}
++		prot_val = new_prot_val;
+ 	}
+ 
+-	switch (mode) {
+-	case IOR_MODE_UNCACHED:
++	switch (prot_val) {
++	case _PAGE_CACHE_UC:
+ 	default:
+-		/*
+-		 * FIXME: we will use UC MINUS for now, as video fb drivers
+-		 * depend on it. Upcoming ioremap_wc() will fix this behavior.
+-		 */
++		prot = PAGE_KERNEL_NOCACHE;
++		break;
++	case _PAGE_CACHE_UC_MINUS:
+ 		prot = PAGE_KERNEL_UC_MINUS;
+ 		break;
+-	case IOR_MODE_CACHED:
++	case _PAGE_CACHE_WC:
++		prot = PAGE_KERNEL_WC;
++		break;
++	case _PAGE_CACHE_WB:
+ 		prot = PAGE_KERNEL;
+ 		break;
+ 	}
+ 
+ 	/*
+-	 * Mappings have to be page-aligned
+-	 */
+-	offset = phys_addr & ~PAGE_MASK;
+-	phys_addr &= PAGE_MASK;
+-	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+-
+-	/*
+ 	 * Ok, go for it..
+ 	 */
+-	area = get_vm_area(size, VM_IOREMAP | (mode << 20));
++	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ 	if (!area)
+ 		return NULL;
+ 	area->phys_addr = phys_addr;
+ 	vaddr = (unsigned long) area->addr;
+ 	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
+ 				     size, prot, domid)) {
++		free_memtype(phys_addr, phys_addr + size);
+ 		free_vm_area(area);
+ 		return NULL;
+ 	}
+ 
+-	if (ioremap_change_attr(vaddr, size, mode) < 0) {
+-		iounmap((void __iomem *) vaddr);
++	if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
++		free_memtype(phys_addr, phys_addr + size);
++		vunmap(area->addr);
+ 		return NULL;
+ 	}
+ 
+@@ -365,16 +436,72 @@ static void __iomem *__ioremap(resource_
+  */
+ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
+ {
+-	return __ioremap(phys_addr, size, IOR_MODE_UNCACHED);
++	/*
++	 * Ideally, this should be:
++	 *	pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
++	 *
++	 * Till we fix all X drivers to use ioremap_wc(), we will use
++	 * UC MINUS.
++	 */
++	unsigned long val = _PAGE_CACHE_UC_MINUS;
++
++	return __ioremap_caller(phys_addr, size, val,
++				__builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(ioremap_nocache);
+ 
++/**
++ * ioremap_wc	-	map memory into CPU space write combined
++ * @offset:	bus address of the memory
++ * @size:	size of the resource to map
++ *
++ * This version of ioremap ensures that the memory is marked write combining.
++ * Write combining allows faster writes to some hardware devices.
++ *
++ * Must be freed with iounmap.
++ */
++void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
++{
++	if (pat_wc_enabled)
++		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
++					__builtin_return_address(0));
++	else
++		return ioremap_nocache(phys_addr, size);
++}
++EXPORT_SYMBOL(ioremap_wc);
++
+ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
+ {
+-	return __ioremap(phys_addr, size, IOR_MODE_CACHED);
++	return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WB,
++				__builtin_return_address(0));
+ }
+ EXPORT_SYMBOL(ioremap_cache);
+ 
++#ifndef CONFIG_XEN
++static void __iomem *ioremap_default(resource_size_t phys_addr,
++					unsigned long size)
++{
++	unsigned long flags;
++	void *ret;
++	int err;
++
++	/*
++	 * - WB for WB-able memory and no other conflicting mappings
++	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
++	 * - Inherit from confliting mappings otherwise
++	 */
++	err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
++	if (err < 0)
++		return NULL;
++
++	ret = (void *) __ioremap_caller(phys_addr, size, flags,
++					__builtin_return_address(0));
++
++	free_memtype(phys_addr, phys_addr + size);
++	return (void __iomem *)ret;
++}
++#endif
++
+ /**
+  * iounmap - Free a IO remapping
+  * @addr: virtual address from ioremap_*
+@@ -417,15 +544,7 @@ void iounmap(volatile void __iomem *addr
+ 		return;
+ 	}
+ 
+-	if ((p->flags >> 20) != IOR_MODE_CACHED) {
+-		unsigned long n = get_vm_area_size(p) >> PAGE_SHIFT;
+-		unsigned long mfn = p->phys_addr;
+-		unsigned long va = (unsigned long)addr;
+-
+-		for (; n > 0; n--, mfn++, va += PAGE_SIZE)
+-			if (mfn_to_local_pfn(mfn) < max_pfn)
+-				set_memory_wb(va, 1);
+-	}
++	free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
+ 
+ 	/* Finally remove it */
+ 	o = remove_vm_area((void *)addr);
+@@ -434,6 +553,37 @@ void iounmap(volatile void __iomem *addr
+ }
+ EXPORT_SYMBOL(iounmap);
+ 
++#ifndef CONFIG_XEN
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++void *xlate_dev_mem_ptr(unsigned long phys)
++{
++	void *addr;
++	unsigned long start = phys & PAGE_MASK;
++
++	/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
++	if (page_is_ram(start >> PAGE_SHIFT))
++		return __va(phys);
++
++	addr = (void *)ioremap_default(start, PAGE_SIZE);
++	if (addr)
++		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
++
++	return addr;
++}
++
++void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
++{
++	if (page_is_ram(phys >> PAGE_SHIFT))
++		return;
++
++	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
++	return;
++}
++#endif
++
+ int __initdata early_ioremap_debug;
+ 
+ static int __init early_ioremap_debug_setup(char *str)
+@@ -445,8 +595,8 @@ static int __init early_ioremap_debug_se
+ early_param("early_ioremap_debug", early_ioremap_debug_setup);
+ 
+ static __initdata int after_paging_init;
+-static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
+-				__attribute__((aligned(PAGE_SIZE)));
++static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
++		__section(.bss.page_aligned);
+ 
+ #ifdef CONFIG_X86_32
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+@@ -461,8 +611,8 @@ static inline pmd_t * __init early_iorem
+ }
+ #else
+ #define early_ioremap_pmd early_get_pmd
++#undef make_lowmem_page_readonly
+ #define make_lowmem_page_readonly early_make_page_readonly
+-#define make_lowmem_page_writable make_page_writable
+ #endif
+ 
+ static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+@@ -512,7 +662,7 @@ void __init early_ioremap_clear(void)
+ 	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+ 	pmd_clear(pmd);
+ 	make_lowmem_page_writable(bm_pte, XENFEAT_writable_page_tables);
+-	/* paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT); */
++	/* paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT); */
+ 	__flush_tlb_all();
+ }
+ 
+@@ -654,10 +804,11 @@ void __init early_iounmap(void *addr, un
+ 	unsigned long offset;
+ 	unsigned int nrpages;
+ 	enum fixed_addresses idx;
+-	unsigned int nesting;
++	int nesting;
+ 
+ 	nesting = --early_ioremap_nested;
+-	WARN_ON(nesting < 0);
++	if (WARN_ON(nesting < 0))
++		return;
+ 
+ 	if (early_ioremap_debug) {
+ 		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
+--- head-2010-01-18.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -9,6 +9,8 @@
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
++#include <linux/seq_file.h>
++#include <linux/debugfs.h>
+ 
+ #include <asm/e820.h>
+ #include <asm/processor.h>
+@@ -17,371 +19,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
+-#include <asm/mmu_context.h>
+-
+-#ifndef CONFIG_X86_64
+-#define TASK_SIZE64 TASK_SIZE
+-#endif
+-
+-static void _pin_lock(struct mm_struct *mm, int lock) {
+-	if (lock)
+-		spin_lock(&mm->page_table_lock);
+-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+-	/* While mm->page_table_lock protects us against insertions and
+-	 * removals of higher level page table pages, it doesn't protect
+-	 * against updates of pte-s. Such updates, however, require the
+-	 * pte pages to be in consistent state (unpinned+writable or
+-	 * pinned+readonly). The pinning and attribute changes, however
+-	 * cannot be done atomically, which is why such updates must be
+-	 * prevented from happening concurrently.
+-	 * Note that no pte lock can ever elsewhere be acquired nesting
+-	 * with an already acquired one in the same mm, or with the mm's
+-	 * page_table_lock already acquired, as that would break in the
+-	 * non-split case (where all these are actually resolving to the
+-	 * one page_table_lock). Thus acquiring all of them here is not
+-	 * going to result in dead locks, and the order of acquires
+-	 * doesn't matter.
+-	 */
+-	{
+-		pgd_t *pgd = mm->pgd;
+-		unsigned g;
+-
+-		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
+-			pud_t *pud;
+-			unsigned u;
+-
+-			if (pgd_none(*pgd))
+-				continue;
+-			pud = pud_offset(pgd, 0);
+-			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-				pmd_t *pmd;
+-				unsigned m;
+-
+-				if (pud_none(*pud))
+-					continue;
+-				pmd = pmd_offset(pud, 0);
+-				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-					spinlock_t *ptl;
+-
+-					if (pmd_none(*pmd))
+-						continue;
+-					ptl = pte_lockptr(0, pmd);
+-					if (lock)
+-						spin_lock(ptl);
+-					else
+-						spin_unlock(ptl);
+-				}
+-			}
+-		}
+-	}
+-#endif
+-	if (!lock)
+-		spin_unlock(&mm->page_table_lock);
+-}
+-#define pin_lock(mm) _pin_lock(mm, 1)
+-#define pin_unlock(mm) _pin_lock(mm, 0)
+-
+-#define PIN_BATCH sizeof(void *)
+-static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+-
+-static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
+-					     unsigned int cpu, unsigned int seq)
+-{
+-	unsigned long pfn = page_to_pfn(page);
+-
+-	if (PageHighMem(page)) {
+-		if (pgprot_val(flags) & _PAGE_RW)
+-			ClearPagePinned(page);
+-		else
+-			SetPagePinned(page);
+-	} else {
+-		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-					(unsigned long)__va(pfn << PAGE_SHIFT),
+-					pfn_pte(pfn, flags), 0);
+-		if (unlikely(++seq == PIN_BATCH)) {
+-			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-								PIN_BATCH, NULL)))
+-				BUG();
+-			seq = 0;
+-		}
+-	}
+-
+-	return seq;
+-}
+-
+-static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
+-{
+-	pgd_t       *pgd = pgd_base;
+-	pud_t       *pud;
+-	pmd_t       *pmd;
+-	int          g,u,m;
+-	unsigned int cpu, seq;
+-	multicall_entry_t *mcl;
+-
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return;
+-
+-	cpu = get_cpu();
+-
+-	/*
+-	 * Cannot iterate up to USER_PTRS_PER_PGD on x86-64 as these pagetables
+-	 * may not be the 'current' task's pagetables (e.g., current may be
+-	 * 32-bit, but the pagetables may be for a 64-bit task).
+-	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
+-	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
+-	 */
+-	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
+-		if (pgd_none(*pgd))
+-			continue;
+-		pud = pud_offset(pgd, 0);
+-		if (PTRS_PER_PUD > 1) /* not folded */
+-			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
+-		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-			if (pud_none(*pud))
+-				continue;
+-			pmd = pmd_offset(pud, 0);
+-			if (PTRS_PER_PMD > 1) /* not folded */
+-				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
+-			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-				if (pmd_none(*pmd))
+-					continue;
+-				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
+-			}
+-		}
+-	}
+-
+-	mcl = per_cpu(pb_mcl, cpu);
+-#ifdef CONFIG_X86_64
+-	if (unlikely(seq > PIN_BATCH - 2)) {
+-		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
+-			BUG();
+-		seq = 0;
+-	}
+-	MULTI_update_va_mapping(mcl + seq,
+-	       (unsigned long)__user_pgd(pgd_base),
+-	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
+-	       0);
+-	MULTI_update_va_mapping(mcl + seq + 1,
+-	       (unsigned long)pgd_base,
+-	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-	       UVMF_TLB_FLUSH);
+-	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
+-		BUG();
+-#else
+-	if (likely(seq != 0)) {
+-		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-			(unsigned long)pgd_base,
+-			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-			UVMF_TLB_FLUSH);
+-		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-		                                        seq + 1, NULL)))
+-			BUG();
+-	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
+-			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-			UVMF_TLB_FLUSH))
+-		BUG();
+-#endif
+-
+-	put_cpu();
+-}
+-
+-static void __pgd_pin(pgd_t *pgd)
+-{
+-	pgd_walk(pgd, PAGE_KERNEL_RO);
+-	kmap_flush_unused();
+-	xen_pgd_pin(__pa(pgd)); /* kernel */
+-#ifdef CONFIG_X86_64
+-	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
+-#endif
+-	SetPagePinned(virt_to_page(pgd));
+-}
+-
+-static void __pgd_unpin(pgd_t *pgd)
+-{
+-	xen_pgd_unpin(__pa(pgd));
+-#ifdef CONFIG_X86_64
+-	xen_pgd_unpin(__pa(__user_pgd(pgd)));
+-#endif
+-	pgd_walk(pgd, PAGE_KERNEL);
+-	ClearPagePinned(virt_to_page(pgd));
+-}
+-
+-void pgd_test_and_unpin(pgd_t *pgd)
+-{
+-	if (PagePinned(virt_to_page(pgd)))
+-		__pgd_unpin(pgd);
+-}
+-
+-void mm_pin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	pin_lock(mm);
+-	__pgd_pin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_unpin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	pin_lock(mm);
+-	__pgd_unpin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_pin_all(void)
+-{
+-	struct page *page;
+-	unsigned long flags;
+-
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	/*
+-	 * Allow uninterrupted access to the pgd_list. Also protects
+-	 * __pgd_pin() by disabling preemption.
+-	 * All other CPUs must be at a safe point (e.g., in stop_machine
+-	 * or offlined entirely).
+-	 */
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_for_each_entry(page, &pgd_list, lru) {
+-		if (!PagePinned(page))
+-			__pgd_pin((pgd_t *)page_address(page));
+-	}
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+-{
+-	if (!PagePinned(virt_to_page(mm->pgd)))
+-		mm_pin(mm);
+-}
+-
+-void arch_exit_mmap(struct mm_struct *mm)
+-{
+-	struct task_struct *tsk = current;
+-
+-	task_lock(tsk);
+-
+-	/*
+-	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+-	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+-	 */
+-	if (tsk->active_mm == mm) {
+-		tsk->active_mm = &init_mm;
+-		atomic_inc(&init_mm.mm_count);
+-
+-		switch_mm(mm, &init_mm, tsk);
+-
+-		atomic_dec(&mm->mm_count);
+-		BUG_ON(atomic_read(&mm->mm_count) == 0);
+-	}
+-
+-	task_unlock(tsk);
+-
+-	if (PagePinned(virt_to_page(mm->pgd))
+-	    && atomic_read(&mm->mm_count) == 1
+-	    && !mm->context.has_foreign_mappings)
+-		mm_unpin(mm);
+-}
+-
+-static void _pte_free(struct page *page, unsigned int order)
+-{
+-	BUG_ON(order);
+-	__pte_free(page);
+-}
+-
+-pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-	struct page *pte;
+-
+-#ifdef CONFIG_HIGHPTE
+-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+-#else
+-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-#endif
+-	if (pte) {
+-		pgtable_page_ctor(pte);
+-		SetPageForeign(pte, _pte_free);
+-		init_page_count(pte);
+-	}
+-	return pte;
+-}
+-
+-void __pte_free(pgtable_t pte)
+-{
+-	if (!PageHighMem(pte)) {
+-		unsigned long va = (unsigned long)page_address(pte);
+-		unsigned int level;
+-		pte_t *ptep = lookup_address(va, &level);
+-
+-		BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
+-		if (!pte_write(*ptep)
+-		    && HYPERVISOR_update_va_mapping(va,
+-						    mk_pte(pte, PAGE_KERNEL),
+-						    0))
+-			BUG();
+-	} else
+-#ifdef CONFIG_HIGHPTE
+-		ClearPagePinned(pte);
+-#else
+-		BUG();
+-#endif
+-
+-	ClearPageForeign(pte);
+-	init_page_count(pte);
+-	pgtable_page_dtor(pte);
+-	__free_page(pte);
+-}
+-
+-#if PAGETABLE_LEVELS >= 3
+-static void _pmd_free(struct page *page, unsigned int order)
+-{
+-	BUG_ON(order);
+-	__pmd_free(page);
+-}
+-
+-pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-	struct page *pmd;
+-
+-	pmd = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-	if (!pmd)
+-		return NULL;
+-	SetPageForeign(pmd, _pmd_free);
+-	init_page_count(pmd);
+-	return page_address(pmd);
+-}
+-
+-void __pmd_free(pgtable_t pmd)
+-{
+-	unsigned long va = (unsigned long)page_address(pmd);
+-	unsigned int level;
+-	pte_t *ptep = lookup_address(va, &level);
+-
+-	BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
+-	if (!pte_write(*ptep)
+-	    && HYPERVISOR_update_va_mapping(va, mk_pte(pmd, PAGE_KERNEL), 0))
+-		BUG();
+-
+-	ClearPageForeign(pmd);
+-	init_page_count(pmd);
+-	__free_page(pmd);
+-}
+-#endif
+-
+-/* blktap and gntdev need this, as otherwise they would implicitly (and
+- * needlessly, as they never use it) reference init_mm. */
+-pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *vma,
+-				  unsigned long addr, pte_t *ptep, int full)
+-{
+-	return ptep_get_and_clear_full(vma ? vma->vm_mm : &init_mm,
+-				       addr, ptep, full);
+-}
+-EXPORT_SYMBOL_GPL(xen_ptep_get_and_clear_full);
++#include <asm/pat.h>
+ 
+ /*
+  * The current flushing context - we pass it instead of 5 arguments:
+@@ -393,6 +31,7 @@ struct cpa_data {
+ 	int		numpages;
+ 	int		flushtlb;
+ 	unsigned long	pfn;
++	unsigned	force_split : 1;
+ };
+ 
+ #ifdef CONFIG_X86_64
+@@ -638,6 +277,9 @@ try_preserve_large_page(pte_t *kpte, uns
+ 	int i, do_split = 1;
+ 	unsigned int level;
+ 
++	if (cpa->force_split)
++		return 1;
++
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 	/*
+ 	 * Check for races, another CPU might have split this page
+@@ -857,9 +499,7 @@ static int split_large_page(pte_t *kpte,
+ 		goto out_unlock;
+ 
+ 	pbase = (pte_t *)page_address(base);
+-#ifdef CONFIG_X86_32
+-	paravirt_alloc_pt(&init_mm, page_to_pfn(base));
+-#endif
++	paravirt_alloc_pte(&init_mm, page_to_pfn(base));
+ 	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
+ 
+ #ifdef CONFIG_X86_64
+@@ -920,7 +560,7 @@ static int __change_page_attr(struct cpa
+ repeat:
+ 	kpte = lookup_address(address, &level);
+ 	if (!kpte)
+-		return primary ? -EINVAL : 0;
++		return 0;
+ 
+ 	old_pte = *kpte;
+ 	if (!__pte_val(old_pte)) {
+@@ -1079,7 +719,8 @@ static inline int cache_attr(pgprot_t at
+ }
+ 
+ static int change_page_attr_set_clr(unsigned long addr, int numpages,
+-				    pgprot_t mask_set, pgprot_t mask_clr)
++				    pgprot_t mask_set, pgprot_t mask_clr,
++				    int force_split)
+ {
+ 	struct cpa_data cpa;
+ 	int ret, cache, checkalias;
+@@ -1090,7 +731,7 @@ static int change_page_attr_set_clr(unsi
+ 	 */
+ 	mask_set = canon_pgprot(mask_set);
+ 	mask_clr = canon_pgprot(mask_clr);
+-	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
++	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr) && !force_split)
+ 		return 0;
+ 
+ 	/* Ensure we are PAGE_SIZE aligned */
+@@ -1107,6 +748,7 @@ static int change_page_attr_set_clr(unsi
+ 	cpa.mask_set = mask_set;
+ 	cpa.mask_clr = mask_clr;
+ 	cpa.flushtlb = 0;
++	cpa.force_split = force_split;
+ 
+ 	/* No alias checking for _NX bit modifications */
+ 	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+@@ -1145,26 +787,67 @@ out:
+ static inline int change_page_attr_set(unsigned long addr, int numpages,
+ 				       pgprot_t mask)
+ {
+-	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
++	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0);
+ }
+ 
+ static inline int change_page_attr_clear(unsigned long addr, int numpages,
+ 					 pgprot_t mask)
+ {
+-	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
+ }
+ 
+-int set_memory_uc(unsigned long addr, int numpages)
++int _set_memory_uc(unsigned long addr, int numpages)
+ {
++	/*
++	 * for now UC MINUS. see comments in ioremap_nocache()
++	 */
+ 	return change_page_attr_set(addr, numpages,
+-				    __pgprot(_PAGE_PCD));
++				    __pgprot(_PAGE_CACHE_UC_MINUS));
++}
++
++int set_memory_uc(unsigned long addr, int numpages)
++{
++	/*
++	 * for now UC MINUS. see comments in ioremap_nocache()
++	 */
++	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++			    _PAGE_CACHE_UC_MINUS, NULL))
++		return -EINVAL;
++
++	return _set_memory_uc(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+ 
+-int set_memory_wb(unsigned long addr, int numpages)
++int _set_memory_wc(unsigned long addr, int numpages)
++{
++	return change_page_attr_set(addr, numpages,
++				    __pgprot(_PAGE_CACHE_WC));
++}
++
++int set_memory_wc(unsigned long addr, int numpages)
++{
++	if (!pat_wc_enabled)
++		return set_memory_uc(addr, numpages);
++
++	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++		_PAGE_CACHE_WC, NULL))
++		return -EINVAL;
++
++	return _set_memory_wc(addr, numpages);
++}
++EXPORT_SYMBOL(set_memory_wc);
++
++int _set_memory_wb(unsigned long addr, int numpages)
+ {
+ 	return change_page_attr_clear(addr, numpages,
+-				      __pgprot(_PAGE_PCD | _PAGE_PWT));
++				      __pgprot(_PAGE_CACHE_MASK));
++}
++
++int set_memory_wb(unsigned long addr, int numpages)
++{
++	free_memtype(addr, addr + numpages * PAGE_SIZE);
++
++	return _set_memory_wb(addr, numpages);
+ }
+ EXPORT_SYMBOL(set_memory_wb);
+ 
+@@ -1195,6 +878,12 @@ int set_memory_np(unsigned long addr, in
+ 	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
+ }
+ 
++int set_memory_4k(unsigned long addr, int numpages)
++{
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0),
++					__pgprot(0), 1);
++}
++
+ int set_pages_uc(struct page *page, int numpages)
+ {
+ 	unsigned long addr = (unsigned long)page_address(page);
+@@ -1304,6 +993,45 @@ void kernel_map_pages(struct page *page,
+ 	cpa_fill_pool(NULL);
+ }
+ 
++#ifdef CONFIG_DEBUG_FS
++static int dpa_show(struct seq_file *m, void *v)
++{
++	seq_puts(m, "DEBUG_PAGEALLOC\n");
++	seq_printf(m, "pool_size     : %lu\n", pool_size);
++	seq_printf(m, "pool_pages    : %lu\n", pool_pages);
++	seq_printf(m, "pool_low      : %lu\n", pool_low);
++	seq_printf(m, "pool_used     : %lu\n", pool_used);
++	seq_printf(m, "pool_failed   : %lu\n", pool_failed);
++
++	return 0;
++}
++
++static int dpa_open(struct inode *inode, struct file *filp)
++{
++	return single_open(filp, dpa_show, NULL);
++}
++
++static const struct file_operations dpa_fops = {
++	.open		= dpa_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int __init debug_pagealloc_proc_init(void)
++{
++	struct dentry *de;
++
++	de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL,
++				 &dpa_fops);
++	if (!de)
++		return -ENOMEM;
++
++	return 0;
++}
++__initcall(debug_pagealloc_proc_init);
++#endif
++
+ #ifdef CONFIG_HIBERNATION
+ 
+ bool kernel_page_present(struct page *page)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/pat-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,602 @@
++/*
++ * Handle caching attributes in page tables (PAT)
++ *
++ * Authors: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
++ *          Suresh B Siddha <suresh.b.siddha@intel.com>
++ *
++ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen.
++ */
++
++#include <linux/mm.h>
++#include <linux/kernel.h>
++#include <linux/gfp.h>
++#include <linux/fs.h>
++#include <linux/bootmem.h>
++
++#include <asm/msr.h>
++#include <asm/tlbflush.h>
++#include <asm/processor.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/pat.h>
++#include <asm/e820.h>
++#include <asm/cacheflush.h>
++#include <asm/fcntl.h>
++#include <asm/mtrr.h>
++#include <asm/io.h>
++
++#ifdef CONFIG_X86_PAT
++int __read_mostly pat_wc_enabled = 1;
++
++void __cpuinit pat_disable(char *reason)
++{
++	pat_wc_enabled = 0;
++	printk(KERN_INFO "%s\n", reason);
++}
++
++static int __init nopat(char *str)
++{
++	pat_disable("PAT support disabled.");
++	return 0;
++}
++early_param("nopat", nopat);
++#endif
++
++static u64 __read_mostly boot_pat_state;
++
++enum {
++	PAT_UC = 0,		/* uncached */
++	PAT_WC = 1,		/* Write combining */
++	PAT_WT = 4,		/* Write Through */
++	PAT_WP = 5,		/* Write Protected */
++	PAT_WB = 6,		/* Write Back (default) */
++	PAT_UC_MINUS = 7,	/* UC, but can be overriden by MTRR */
++};
++
++#define PAT(x,y)	((u64)PAT_ ## y << ((x)*8))
++
++void pat_init(void)
++{
++	u64 pat;
++
++	if (!pat_wc_enabled)
++		return;
++
++	/* Paranoia check. */
++	if (!cpu_has_pat) {
++		printk(KERN_ERR "PAT enabled, but CPU feature cleared\n");
++		/*
++		 * Panic if this happens on the secondary CPU, and we
++		 * switched to PAT on the boot CPU. We have no way to
++		 * undo PAT.
++		*/
++		BUG_ON(boot_pat_state);
++	}
++
++#ifndef CONFIG_XEN
++	/* Set PWT to Write-Combining. All other bits stay the same */
++	/*
++	 * PTE encoding used in Linux:
++	 *      PAT
++	 *      |PCD
++	 *      ||PWT
++	 *      |||
++	 *      000 WB		_PAGE_CACHE_WB
++	 *      001 WC		_PAGE_CACHE_WC
++	 *      010 UC-		_PAGE_CACHE_UC_MINUS
++	 *      011 UC		_PAGE_CACHE_UC
++	 * PAT bit unused
++	 */
++	pat = PAT(0,WB) | PAT(1,WC) | PAT(2,UC_MINUS) | PAT(3,UC) |
++	      PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC);
++
++	/* Boot CPU check */
++	if (!boot_pat_state)
++		rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
++
++	wrmsrl(MSR_IA32_CR_PAT, pat);
++#else
++	/*
++	 * PAT settings are part of the hypervisor interface, and their
++	 * assignment cannot be changed.
++	 */
++	rdmsrl(MSR_IA32_CR_PAT, pat);
++	if (!boot_pat_state)
++		boot_pat_state = pat;
++#endif
++	printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
++	       smp_processor_id(), boot_pat_state, pat);
++}
++
++#undef PAT
++
++static char *cattr_name(unsigned long flags)
++{
++	switch (flags & _PAGE_CACHE_MASK) {
++		case _PAGE_CACHE_UC:		return "uncached";
++		case _PAGE_CACHE_UC_MINUS:	return "uncached-minus";
++		case _PAGE_CACHE_WB:		return "write-back";
++		case _PAGE_CACHE_WC:		return "write-combining";
++		case _PAGE_CACHE_WP:		return "write-protected";
++		case _PAGE_CACHE_WT:		return "write-through";
++		default:			return "broken";
++	}
++}
++
++/*
++ * The global memtype list keeps track of memory type for specific
++ * physical memory areas. Conflicting memory types in different
++ * mappings can cause CPU cache corruption. To avoid this we keep track.
++ *
++ * The list is sorted based on starting address and can contain multiple
++ * entries for each address (this allows reference counting for overlapping
++ * areas). All the aliases have the same cache attributes of course.
++ * Zero attributes are represented as holes.
++ *
++ * Currently the data structure is a list because the number of mappings
++ * are expected to be relatively small. If this should be a problem
++ * it could be changed to a rbtree or similar.
++ *
++ * memtype_lock protects the whole list.
++ */
++
++struct memtype {
++	u64 start;
++	u64 end;
++	unsigned long type;
++	struct list_head nd;
++};
++
++static LIST_HEAD(memtype_list);
++static DEFINE_SPINLOCK(memtype_lock); 	/* protects memtype list */
++
++/*
++ * Does intersection of PAT memory type and MTRR memory type and returns
++ * the resulting memory type as PAT understands it.
++ * (Type in pat and mtrr will not have same value)
++ * The intersection is based on "Effective Memory Type" tables in IA-32
++ * SDM vol 3a
++ */
++static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
++				unsigned long *ret_prot)
++{
++	unsigned long pat_type;
++	u8 mtrr_type;
++
++	pat_type = prot & _PAGE_CACHE_MASK;
++	prot &= (~_PAGE_CACHE_MASK);
++
++	/*
++	 * We return the PAT request directly for types where PAT takes
++	 * precedence with respect to MTRR and for UC_MINUS.
++	 * Consistency checks with other PAT requests is done later
++	 * while going through memtype list.
++	 */
++	if (pat_type == _PAGE_CACHE_WC) {
++		*ret_prot = prot | _PAGE_CACHE_WC;
++		return 0;
++	} else if (pat_type == _PAGE_CACHE_UC_MINUS) {
++		*ret_prot = prot | _PAGE_CACHE_UC_MINUS;
++		return 0;
++	} else if (pat_type == _PAGE_CACHE_UC) {
++		*ret_prot = prot | _PAGE_CACHE_UC;
++		return 0;
++	}
++
++	/*
++	 * Look for MTRR hint to get the effective type in case where PAT
++	 * request is for WB.
++	 */
++	mtrr_type = mtrr_type_lookup(start, end);
++
++	if (mtrr_type == MTRR_TYPE_UNCACHABLE) {
++		*ret_prot = prot | _PAGE_CACHE_UC;
++	} else if (mtrr_type == MTRR_TYPE_WRCOMB) {
++		*ret_prot = prot | _PAGE_CACHE_WC;
++	} else {
++		*ret_prot = prot | _PAGE_CACHE_WB;
++	}
++
++	return 0;
++}
++
++/*
++ * req_type typically has one of the:
++ * - _PAGE_CACHE_WB
++ * - _PAGE_CACHE_WC
++ * - _PAGE_CACHE_UC_MINUS
++ * - _PAGE_CACHE_UC
++ *
++ * req_type will have a special case value '-1', when requester want to inherit
++ * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
++ *
++ * If ret_type is NULL, function will return an error if it cannot reserve the
++ * region with req_type. If ret_type is non-null, function will return
++ * available type in ret_type in case of no error. In case of any error
++ * it will return a negative return value.
++ */
++int reserve_memtype(u64 start, u64 end, unsigned long req_type,
++			unsigned long *ret_type)
++{
++	struct memtype *new_entry = NULL;
++	struct memtype *parse;
++	unsigned long actual_type;
++	int err = 0;
++
++	/* Only track when pat_wc_enabled */
++	if (!pat_wc_enabled) {
++		/* This is identical to page table setting without PAT */
++		if (ret_type) {
++			if (req_type == -1) {
++				*ret_type = _PAGE_CACHE_WB;
++			} else {
++				*ret_type = req_type;
++			}
++		}
++		return 0;
++	}
++
++	/* Low ISA region is always mapped WB in page table. No need to track */
++	if (start >= ISA_START_ADDRESS && (end - 1) <= ISA_END_ADDRESS) {
++		if (ret_type)
++			*ret_type = _PAGE_CACHE_WB;
++
++		return 0;
++	}
++
++	if (req_type == -1) {
++		/*
++		 * Call mtrr_lookup to get the type hint. This is an
++		 * optimization for /dev/mem mmap'ers into WB memory (BIOS
++		 * tools and ACPI tools). Use WB request for WB memory and use
++		 * UC_MINUS otherwise.
++		 */
++		u8 mtrr_type = mtrr_type_lookup(start, end);
++
++		if (mtrr_type == MTRR_TYPE_WRBACK) {
++			req_type = _PAGE_CACHE_WB;
++			actual_type = _PAGE_CACHE_WB;
++		} else {
++			req_type = _PAGE_CACHE_UC_MINUS;
++			actual_type = _PAGE_CACHE_UC_MINUS;
++		}
++	} else {
++		req_type &= _PAGE_CACHE_MASK;
++		err = pat_x_mtrr_type(start, end, req_type, &actual_type);
++	}
++
++	if (err) {
++		if (ret_type)
++			*ret_type = actual_type;
++
++		return -EINVAL;
++	}
++
++	new_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
++	if (!new_entry)
++		return -ENOMEM;
++
++	new_entry->start = start;
++	new_entry->end = end;
++	new_entry->type = actual_type;
++
++	if (ret_type)
++		*ret_type = actual_type;
++
++	spin_lock(&memtype_lock);
++
++	/* Search for existing mapping that overlaps the current range */
++	list_for_each_entry(parse, &memtype_list, nd) {
++		struct memtype *saved_ptr;
++
++		if (parse->start >= end) {
++			pr_debug("New Entry\n");
++			list_add(&new_entry->nd, parse->nd.prev);
++			new_entry = NULL;
++			break;
++		}
++
++		if (start <= parse->start && end >= parse->start) {
++			if (actual_type != parse->type && ret_type) {
++				actual_type = parse->type;
++				*ret_type = actual_type;
++				new_entry->type = actual_type;
++			}
++
++			if (actual_type != parse->type) {
++				printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++					current->comm, current->pid,
++					start, end,
++					cattr_name(actual_type),
++					cattr_name(parse->type));
++				err = -EBUSY;
++				break;
++			}
++
++			saved_ptr = parse;
++			/*
++			 * Check to see whether the request overlaps more
++			 * than one entry in the list
++			 */
++			list_for_each_entry_continue(parse, &memtype_list, nd) {
++				if (end <= parse->start) {
++					break;
++				}
++
++				if (actual_type != parse->type) {
++					printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++						current->comm, current->pid,
++						start, end,
++						cattr_name(actual_type),
++						cattr_name(parse->type));
++					err = -EBUSY;
++					break;
++				}
++			}
++
++			if (err) {
++				break;
++			}
++
++			pr_debug("Overlap at 0x%Lx-0x%Lx\n",
++			       saved_ptr->start, saved_ptr->end);
++			/* No conflict. Go ahead and add this new entry */
++			list_add(&new_entry->nd, saved_ptr->nd.prev);
++			new_entry = NULL;
++			break;
++		}
++
++		if (start < parse->end) {
++			if (actual_type != parse->type && ret_type) {
++				actual_type = parse->type;
++				*ret_type = actual_type;
++				new_entry->type = actual_type;
++			}
++
++			if (actual_type != parse->type) {
++				printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++					current->comm, current->pid,
++					start, end,
++					cattr_name(actual_type),
++					cattr_name(parse->type));
++				err = -EBUSY;
++				break;
++			}
++
++			saved_ptr = parse;
++			/*
++			 * Check to see whether the request overlaps more
++			 * than one entry in the list
++			 */
++			list_for_each_entry_continue(parse, &memtype_list, nd) {
++				if (end <= parse->start) {
++					break;
++				}
++
++				if (actual_type != parse->type) {
++					printk(
++		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
++						current->comm, current->pid,
++						start, end,
++						cattr_name(actual_type),
++						cattr_name(parse->type));
++					err = -EBUSY;
++					break;
++				}
++			}
++
++			if (err) {
++				break;
++			}
++
++			pr_debug(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
++				 saved_ptr->start, saved_ptr->end);
++			/* No conflict. Go ahead and add this new entry */
++			list_add(&new_entry->nd, &saved_ptr->nd);
++			new_entry = NULL;
++			break;
++		}
++	}
++
++	if (err) {
++		printk(KERN_INFO
++	"reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
++			start, end, cattr_name(new_entry->type),
++			cattr_name(req_type));
++		kfree(new_entry);
++		spin_unlock(&memtype_lock);
++		return err;
++	}
++
++	if (new_entry) {
++		/* No conflict. Not yet added to the list. Add to the tail */
++		list_add_tail(&new_entry->nd, &memtype_list);
++		pr_debug("New Entry\n");
++	}
++
++	if (ret_type) {
++		pr_debug(
++	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
++			start, end, cattr_name(actual_type),
++			cattr_name(req_type), cattr_name(*ret_type));
++	} else {
++		pr_debug(
++	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
++			start, end, cattr_name(actual_type),
++			cattr_name(req_type));
++	}
++
++	spin_unlock(&memtype_lock);
++	return err;
++}
++
++int free_memtype(u64 start, u64 end)
++{
++	struct memtype *ml;
++	int err = -EINVAL;
++
++	/* Only track when pat_wc_enabled */
++	if (!pat_wc_enabled) {
++		return 0;
++	}
++
++	/* Low ISA region is always mapped WB. No need to track */
++	if (start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS) {
++		return 0;
++	}
++
++	spin_lock(&memtype_lock);
++	list_for_each_entry(ml, &memtype_list, nd) {
++		if (ml->start == start && ml->end == end) {
++			list_del(&ml->nd);
++			kfree(ml);
++			err = 0;
++			break;
++		}
++	}
++	spin_unlock(&memtype_lock);
++
++	if (err) {
++		printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
++			current->comm, current->pid, start, end);
++	}
++
++	pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
++	return err;
++}
++
++
++/*
++ * /dev/mem mmap interface. The memtype used for mapping varies:
++ * - Use UC for mappings with O_SYNC flag
++ * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
++ *   inherit the memtype from existing mapping.
++ * - Else use UC_MINUS memtype (for backward compatibility with existing
++ *   X drivers.
++ */
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long mfn,
++				unsigned long size, pgprot_t vma_prot)
++{
++	return vma_prot;
++}
++
++#ifdef CONFIG_NONPROMISC_DEVMEM
++/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
++static inline int range_is_allowed(unsigned long mfn, unsigned long size)
++{
++	return 1;
++}
++#else
++static inline int range_is_allowed(unsigned long mfn, unsigned long size)
++{
++	u64 from = ((u64)mfn) << PAGE_SHIFT;
++	u64 to = from + size;
++	u64 cursor = from;
++
++	while (cursor < to) {
++		if (!devmem_is_allowed(mfn)) {
++			printk(KERN_INFO
++		"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
++				current->comm, from, to);
++			return 0;
++		}
++		cursor += PAGE_SIZE;
++		mfn++;
++	}
++	return 1;
++}
++#endif /* CONFIG_NONPROMISC_DEVMEM */
++
++int phys_mem_access_prot_allowed(struct file *file, unsigned long mfn,
++				unsigned long size, pgprot_t *vma_prot)
++{
++	u64 addr = (u64)mfn << PAGE_SHIFT;
++	unsigned long flags = _PAGE_CACHE_UC_MINUS;
++	int retval;
++
++	if (!range_is_allowed(mfn, size))
++		return 0;
++
++	if (file->f_flags & O_SYNC) {
++		flags = _PAGE_CACHE_UC;
++	}
++
++#ifndef CONFIG_X86_32
++#ifndef CONFIG_XEN /* Xen sets correct MTRR type on non-RAM for us. */
++	/*
++	 * On the PPro and successors, the MTRRs are used to set
++	 * memory types for physical addresses outside main memory,
++	 * so blindly setting UC or PWT on those pages is wrong.
++	 * For Pentiums and earlier, the surround logic should disable
++	 * caching for the high addresses through the KEN pin, but
++	 * we maintain the tradition of paranoia in this code.
++	 */
++	if (!pat_wc_enabled &&
++	    ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
++		test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
++	   (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
++		flags = _PAGE_CACHE_UC;
++	}
++#endif
++#endif
++
++	/*
++	 * With O_SYNC, we can only take UC mapping. Fail if we cannot.
++	 * Without O_SYNC, we want to get
++	 * - WB for WB-able memory and no other conflicting mappings
++	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
++	 * - Inherit from confliting mappings otherwise
++	 */
++	if (flags != _PAGE_CACHE_UC_MINUS) {
++		retval = reserve_memtype(addr, addr + size, flags, NULL);
++	} else {
++		retval = reserve_memtype(addr, addr + size, -1, &flags);
++	}
++
++	if (retval < 0)
++		return 0;
++
++	if (ioremap_check_change_attr(mfn, size, flags) < 0) {
++		free_memtype(addr, addr + size);
++		printk(KERN_INFO
++		"%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
++			current->comm, current->pid,
++			cattr_name(flags),
++			addr, addr + size);
++		return 0;
++	}
++
++	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
++			     flags);
++	return 1;
++}
++
++void map_devmem(unsigned long mfn, unsigned long size, pgprot_t vma_prot)
++{
++	u64 addr = (u64)mfn << PAGE_SHIFT;
++	unsigned long flags;
++	unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
++
++	reserve_memtype(addr, addr + size, want_flags, &flags);
++	if (flags != want_flags) {
++		printk(KERN_INFO
++		"%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n",
++			current->comm, current->pid,
++			cattr_name(want_flags),
++			addr, (unsigned long long)(addr + size),
++			cattr_name(flags));
++	}
++}
++
++void unmap_devmem(unsigned long mfn, unsigned long size, pgprot_t vma_prot)
++{
++	u64 addr = (u64)mfn << PAGE_SHIFT;
++
++	free_memtype(addr, addr + size);
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -0,0 +1,710 @@
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <xen/features.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/tlb.h>
++#include <asm/hypervisor.h>
++#include <asm/mmu_context.h>
++
++pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++	if (pte)
++		make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
++	return pte;
++}
++
++static void _pte_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	__pte_free(page);
++}
++
++pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pte;
++
++#ifdef CONFIG_HIGHPTE
++	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++#else
++	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++#endif
++	if (pte) {
++		pgtable_page_ctor(pte);
++		SetPageForeign(pte, _pte_free);
++		init_page_count(pte);
++	}
++	return pte;
++}
++
++void __pte_free(pgtable_t pte)
++{
++	if (!PageHighMem(pte)) {
++		unsigned long va = (unsigned long)page_address(pte);
++		unsigned int level;
++		pte_t *ptep = lookup_address(va, &level);
++
++		BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
++		if (!pte_write(*ptep)
++		    && HYPERVISOR_update_va_mapping(va,
++						    mk_pte(pte, PAGE_KERNEL),
++						    0))
++			BUG();
++	} else
++#ifdef CONFIG_HIGHPTE
++		ClearPagePinned(pte);
++#else
++		BUG();
++#endif
++
++	ClearPageForeign(pte);
++	init_page_count(pte);
++	pgtable_page_dtor(pte);
++	__free_page(pte);
++}
++
++void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
++{
++	pgtable_page_dtor(pte);
++	paravirt_release_pte(page_to_pfn(pte));
++	tlb_remove_page(tlb, pte);
++}
++
++#if PAGETABLE_LEVELS > 2
++static void _pmd_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	__pmd_free(page);
++}
++
++pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pmd;
++
++	pmd = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++	if (!pmd)
++		return NULL;
++	SetPageForeign(pmd, _pmd_free);
++	init_page_count(pmd);
++	return page_address(pmd);
++}
++
++void __pmd_free(pgtable_t pmd)
++{
++	unsigned long va = (unsigned long)page_address(pmd);
++	unsigned int level;
++	pte_t *ptep = lookup_address(va, &level);
++
++	BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
++	if (!pte_write(*ptep)
++	    && HYPERVISOR_update_va_mapping(va, mk_pte(pmd, PAGE_KERNEL), 0))
++		BUG();
++
++	ClearPageForeign(pmd);
++	init_page_count(pmd);
++	__free_page(pmd);
++}
++
++void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
++{
++	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
++	tlb_remove_page(tlb, virt_to_page(pmd));
++}
++
++#if PAGETABLE_LEVELS > 3
++void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
++{
++	paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
++	tlb_remove_page(tlb, virt_to_page(pud));
++}
++#endif	/* PAGETABLE_LEVELS > 3 */
++#endif	/* PAGETABLE_LEVELS > 2 */
++
++#ifndef CONFIG_X86_64
++#define TASK_SIZE64 TASK_SIZE
++#endif
++
++static void _pin_lock(struct mm_struct *mm, int lock) {
++	if (lock)
++		spin_lock(&mm->page_table_lock);
++#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
++	/* While mm->page_table_lock protects us against insertions and
++	 * removals of higher level page table pages, it doesn't protect
++	 * against updates of pte-s. Such updates, however, require the
++	 * pte pages to be in consistent state (unpinned+writable or
++	 * pinned+readonly). The pinning and attribute changes, however
++	 * cannot be done atomically, which is why such updates must be
++	 * prevented from happening concurrently.
++	 * Note that no pte lock can ever elsewhere be acquired nesting
++	 * with an already acquired one in the same mm, or with the mm's
++	 * page_table_lock already acquired, as that would break in the
++	 * non-split case (where all these are actually resolving to the
++	 * one page_table_lock). Thus acquiring all of them here is not
++	 * going to result in dead locks, and the order of acquires
++	 * doesn't matter.
++	 */
++	{
++		pgd_t *pgd = mm->pgd;
++		unsigned g;
++
++		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++			pud_t *pud;
++			unsigned u;
++
++			if (pgd_none(*pgd))
++				continue;
++			pud = pud_offset(pgd, 0);
++			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++				pmd_t *pmd;
++				unsigned m;
++
++				if (pud_none(*pud))
++					continue;
++				pmd = pmd_offset(pud, 0);
++				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++					spinlock_t *ptl;
++
++					if (pmd_none(*pmd))
++						continue;
++					ptl = pte_lockptr(0, pmd);
++					if (lock)
++						spin_lock(ptl);
++					else
++						spin_unlock(ptl);
++				}
++			}
++		}
++	}
++#endif
++	if (!lock)
++		spin_unlock(&mm->page_table_lock);
++}
++#define pin_lock(mm) _pin_lock(mm, 1)
++#define pin_unlock(mm) _pin_lock(mm, 0)
++
++#define PIN_BATCH sizeof(void *)
++static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
++
++static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
++					     unsigned int cpu, unsigned int seq)
++{
++	unsigned long pfn = page_to_pfn(page);
++
++	if (PageHighMem(page)) {
++		if (pgprot_val(flags) & _PAGE_RW)
++			ClearPagePinned(page);
++		else
++			SetPagePinned(page);
++	} else {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++					(unsigned long)__va(pfn << PAGE_SHIFT),
++					pfn_pte(pfn, flags), 0);
++		if (unlikely(++seq == PIN_BATCH)) {
++			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++								PIN_BATCH, NULL)))
++				BUG();
++			seq = 0;
++		}
++	}
++
++	return seq;
++}
++
++static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
++{
++	pgd_t       *pgd = pgd_base;
++	pud_t       *pud;
++	pmd_t       *pmd;
++	int          g,u,m;
++	unsigned int cpu, seq;
++	multicall_entry_t *mcl;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return;
++
++	cpu = get_cpu();
++
++	/*
++	 * Cannot iterate up to USER_PTRS_PER_PGD on x86-64 as these pagetables
++	 * may not be the 'current' task's pagetables (e.g., current may be
++	 * 32-bit, but the pagetables may be for a 64-bit task).
++	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
++	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
++	 */
++	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++		if (pgd_none(*pgd))
++			continue;
++		pud = pud_offset(pgd, 0);
++		if (PTRS_PER_PUD > 1) /* not folded */
++			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
++		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++			if (pud_none(*pud))
++				continue;
++			pmd = pmd_offset(pud, 0);
++			if (PTRS_PER_PMD > 1) /* not folded */
++				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
++			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++				if (pmd_none(*pmd))
++					continue;
++				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
++			}
++		}
++	}
++
++	mcl = per_cpu(pb_mcl, cpu);
++#ifdef CONFIG_X86_64
++	if (unlikely(seq > PIN_BATCH - 2)) {
++		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
++			BUG();
++		seq = 0;
++	}
++	MULTI_update_va_mapping(mcl + seq,
++	       (unsigned long)__user_pgd(pgd_base),
++	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
++	       0);
++	MULTI_update_va_mapping(mcl + seq + 1,
++	       (unsigned long)pgd_base,
++	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++	       UVMF_TLB_FLUSH);
++	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
++		BUG();
++#else
++	if (likely(seq != 0)) {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++			(unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH);
++		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++		                                        seq + 1, NULL)))
++			BUG();
++	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH))
++		BUG();
++#endif
++
++	put_cpu();
++}
++
++static void __pgd_pin(pgd_t *pgd)
++{
++	pgd_walk(pgd, PAGE_KERNEL_RO);
++	kmap_flush_unused();
++	xen_pgd_pin(__pa(pgd)); /* kernel */
++#ifdef CONFIG_X86_64
++	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
++#endif
++	SetPagePinned(virt_to_page(pgd));
++}
++
++static void __pgd_unpin(pgd_t *pgd)
++{
++	xen_pgd_unpin(__pa(pgd));
++#ifdef CONFIG_X86_64
++	xen_pgd_unpin(__pa(__user_pgd(pgd)));
++#endif
++	pgd_walk(pgd, PAGE_KERNEL);
++	ClearPagePinned(virt_to_page(pgd));
++}
++
++static void pgd_test_and_unpin(pgd_t *pgd)
++{
++	if (PagePinned(virt_to_page(pgd)))
++		__pgd_unpin(pgd);
++}
++
++void mm_pin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++	__pgd_pin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_unpin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++	__pgd_unpin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_pin_all(void)
++{
++	struct page *page;
++	unsigned long flags;
++
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	/*
++	 * Allow uninterrupted access to the pgd_list. Also protects
++	 * __pgd_pin() by disabling preemption.
++	 * All other CPUs must be at a safe point (e.g., in stop_machine
++	 * or offlined entirely).
++	 */
++	spin_lock_irqsave(&pgd_lock, flags);
++	list_for_each_entry(page, &pgd_list, lru) {
++		if (!PagePinned(page))
++			__pgd_pin((pgd_t *)page_address(page));
++	}
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
++{
++	if (!PagePinned(virt_to_page(mm->pgd)))
++		mm_pin(mm);
++}
++
++void arch_exit_mmap(struct mm_struct *mm)
++{
++	struct task_struct *tsk = current;
++
++	task_lock(tsk);
++
++	/*
++	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
++	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
++	 */
++	if (tsk->active_mm == mm) {
++		tsk->active_mm = &init_mm;
++		atomic_inc(&init_mm.mm_count);
++
++		switch_mm(mm, &init_mm, tsk);
++
++		atomic_dec(&mm->mm_count);
++		BUG_ON(atomic_read(&mm->mm_count) == 0);
++	}
++
++	task_unlock(tsk);
++
++	if (PagePinned(virt_to_page(mm->pgd))
++	    && atomic_read(&mm->mm_count) == 1
++	    && !mm->context.has_foreign_mappings)
++		mm_unpin(mm);
++}
++
++static inline void pgd_list_add(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++
++	list_add(&page->lru, &pgd_list);
++}
++
++static inline void pgd_list_del(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++
++	list_del(&page->lru);
++}
++
++#define UNSHARED_PTRS_PER_PGD				\
++	(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
++
++static void pgd_ctor(void *p)
++{
++	pgd_t *pgd = p;
++	unsigned long flags;
++
++	pgd_test_and_unpin(pgd);
++
++	/* Clear usermode parts of PGD */
++	memset(pgd, 0, KERNEL_PGD_BOUNDARY*sizeof(pgd_t));
++
++	spin_lock_irqsave(&pgd_lock, flags);
++
++	/* If the pgd points to a shared pagetable level (either the
++	   ptes in non-PAE, or shared PMD in PAE), then just copy the
++	   references from swapper_pg_dir. */
++	if (PAGETABLE_LEVELS == 2 ||
++	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
++	    PAGETABLE_LEVELS == 4) {
++		clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
++				swapper_pg_dir + KERNEL_PGD_BOUNDARY,
++				KERNEL_PGD_PTRS);
++		paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
++					 __pa(swapper_pg_dir) >> PAGE_SHIFT,
++					 KERNEL_PGD_BOUNDARY,
++					 KERNEL_PGD_PTRS);
++	}
++
++#ifdef CONFIG_X86_64
++	/* set level3_user_pgt for vsyscall area */
++	__user_pgd(pgd)[pgd_index(VSYSCALL_START)] =
++		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
++#endif
++
++#ifndef CONFIG_X86_PAE
++	/* list required to sync kernel mapping updates */
++	if (!SHARED_KERNEL_PMD)
++		pgd_list_add(pgd);
++#endif
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++static void pgd_dtor(void *pgd)
++{
++	unsigned long flags; /* can be called from interrupt context */
++
++	if (!SHARED_KERNEL_PMD) {
++		spin_lock_irqsave(&pgd_lock, flags);
++		pgd_list_del(pgd);
++		spin_unlock_irqrestore(&pgd_lock, flags);
++	}
++
++	pgd_test_and_unpin(pgd);
++}
++
++/*
++ * List of all pgd's needed for non-PAE so it can invalidate entries
++ * in both cached and uncached pgd's; not needed for PAE since the
++ * kernel pmd is shared. If PAE were not to share the pmd a similar
++ * tactic would be needed. This is essentially codepath-based locking
++ * against pageattr.c; it is the unique case in which a valid change
++ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
++ * vmalloc faults work because attached pagetables are never freed.
++ * -- wli
++ */
++
++#ifdef CONFIG_X86_PAE
++/*
++ * Mop up any pmd pages which may still be attached to the pgd.
++ * Normally they will be freed by munmap/exit_mmap, but any pmd we
++ * preallocate which never got a corresponding vma will need to be
++ * freed manually.
++ */
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
++	int i;
++
++	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
++		pgd_t pgd = pgdp[i];
++
++		if (__pgd_val(pgd) != 0) {
++			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
++
++			pgdp[i] = xen_make_pgd(0);
++
++			paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
++			pmd_free(mm, pmd);
++		}
++	}
++
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
++		xen_destroy_contiguous_region((unsigned long)pgdp, 0);
++}
++
++/*
++ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
++ * updating the top-level pagetable entries to guarantee the
++ * processor notices the update.  Since this is expensive, and
++ * all 4 top-level entries are used almost immediately in a
++ * new process's life, we just pre-populate them here.
++ *
++ * Also, if we're in a paravirt environment where the kernel pmd is
++ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
++ * and initialize the kernel pmds here.
++ */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++	pud_t *pud;
++	pmd_t *pmds[UNSHARED_PTRS_PER_PGD];
++	unsigned long addr, flags;
++	int i;
++
++	/*
++	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
++	 * allocation). We therefore store virtual addresses of pmds as they
++	 * do not change across save/restore, and poke the machine addresses
++	 * into the pgdir under the pgd_lock.
++	 */
++ 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD; i++, addr += PUD_SIZE) {
++		pmds[i] = pmd_alloc_one(mm, addr);
++		if (!pmds[i])
++			goto out_oom;
++	}
++
++	spin_lock_irqsave(&pgd_lock, flags);
++
++	/* Protect against save/restore: move below 4GB under pgd_lock. */
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
++	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
++		spin_unlock_irqrestore(&pgd_lock, flags);
++out_oom:
++		while (i--)
++			pmd_free(mm, pmds[i]);
++		return 0;
++	}
++
++	/* Copy kernel pmd contents and write-protect the new pmds. */
++	pud = pud_offset(pgd, 0);
++ 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
++	     i++, pud++, addr += PUD_SIZE) {
++		if (i >= KERNEL_PGD_BOUNDARY) {
++			memcpy(pmds[i],
++			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++			       sizeof(pmd_t) * PTRS_PER_PMD);
++			make_lowmem_page_readonly(
++				pmds[i], XENFEAT_writable_page_tables);
++		}
++
++		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
++		pud_populate(mm, pud, pmds[i]);
++	}
++
++	/* List required to sync kernel mapping updates and
++	 * to pin/unpin on save/restore. */
++	pgd_list_add(pgd);
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	return 1;
++}
++
++void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
++{
++	struct page *page = virt_to_page(pmd);
++	unsigned long pfn = page_to_pfn(page);
++
++	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++
++	/* Note: almost everything apart from _PAGE_PRESENT is
++	   reserved at the pmd (PDPT) level. */
++	if (PagePinned(virt_to_page(mm->pgd))) {
++		BUG_ON(PageHighMem(page));
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			  (unsigned long)__va(pfn << PAGE_SHIFT),
++			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
++		set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
++	} else
++		*pudp = __pud(__pa(pmd) | _PAGE_PRESENT);
++
++	/*
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
++	 */
++	if (mm == current->active_mm)
++		xen_tlb_flush();
++}
++#else  /* !CONFIG_X86_PAE */
++/* No need to prepopulate any pagetable entries in non-PAE modes. */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++	return 1;
++}
++
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgd)
++{
++}
++#endif	/* CONFIG_X86_PAE */
++
++#ifdef CONFIG_X86_64
++/* We allocate two contiguous pages for kernel and user. */
++#define PGD_ORDER 1
++#else
++#define PGD_ORDER 0
++#endif
++
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++	pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
++
++	/* so that alloc_pd can use it */
++	mm->pgd = pgd;
++	if (pgd)
++		pgd_ctor(pgd);
++
++	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
++		free_pages((unsigned long)pgd, PGD_ORDER);
++		pgd = NULL;
++	}
++
++	return pgd;
++}
++
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
++{
++	/*
++	 * After this the pgd should not be pinned for the duration of this
++	 * function's execution. We should never sleep and thus never race:
++	 *  1. User pmds will not become write-protected under our feet due
++	 *     to a concurrent mm_pin_all().
++	 *  2. The machine addresses in PGD entries will not become invalid
++	 *     due to a concurrent save/restore.
++	 */
++	pgd_dtor(pgd);
++
++	pgd_mop_up_pmds(mm, pgd);
++	free_pages((unsigned long)pgd, PGD_ORDER);
++}
++
++/* blktap and gntdev need this, as otherwise they would implicitly (and
++ * needlessly, as they never use it) reference init_mm. */
++pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *vma,
++				  unsigned long addr, pte_t *ptep, int full)
++{
++	return ptep_get_and_clear_full(vma ? vma->vm_mm : &init_mm,
++				       addr, ptep, full);
++}
++EXPORT_SYMBOL_GPL(xen_ptep_get_and_clear_full);
++
++int ptep_set_access_flags(struct vm_area_struct *vma,
++			  unsigned long address, pte_t *ptep,
++			  pte_t entry, int dirty)
++{
++	int changed = !pte_same(*ptep, entry);
++
++	if (changed && dirty) {
++		if (likely(vma->vm_mm == current->mm)) {
++			if (HYPERVISOR_update_va_mapping(address,
++				entry,
++				uvm_multi(vma->vm_mm->cpu_vm_mask) |
++					UVMF_INVLPG))
++				BUG();
++		} else {
++			xen_l1_entry_update(ptep, entry);
++			flush_tlb_page(vma, address);
++		}
++	}
++
++	return changed;
++}
++
++int ptep_test_and_clear_young(struct vm_area_struct *vma,
++			      unsigned long addr, pte_t *ptep)
++{
++	int ret = 0;
++
++	if (pte_young(*ptep))
++		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
++					 &ptep->pte);
++
++	if (ret)
++		pte_update(vma->vm_mm, addr, ptep);
++
++	return ret;
++}
++
++int ptep_clear_flush_young(struct vm_area_struct *vma,
++			   unsigned long address, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	int young = pte_young(pte);
++
++	pte = pte_mkold(pte);
++	if (PagePinned(virt_to_page(vma->vm_mm->pgd)))
++		ptep_set_access_flags(vma, address, ptep, pte, young);
++	else if (young)
++		ptep->pte_low = pte.pte_low;
++
++	return young;
++}
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -1,7 +1,3 @@
+-/*
+- *  linux/arch/i386/mm/pgtable.c
+- */
+-
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -41,7 +37,6 @@ void show_mem(void)
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ 	for_each_online_pgdat(pgdat) {
+ 		pgdat_resize_lock(pgdat, &flags);
+ 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+@@ -157,243 +152,6 @@ void __init reserve_top_address(unsigned
+ 	__VMALLOC_RESERVE += reserve;
+ }
+ 
+-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+-	if (pte)
+-		make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
+-	return pte;
+-}
+-
+-/*
+- * List of all pgd's needed for non-PAE so it can invalidate entries
+- * in both cached and uncached pgd's; not needed for PAE since the
+- * kernel pmd is shared. If PAE were not to share the pmd a similar
+- * tactic would be needed. This is essentially codepath-based locking
+- * against pageattr.c; it is the unique case in which a valid change
+- * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+- * vmalloc faults work because attached pagetables are never freed.
+- * -- wli
+- */
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-
+-	list_add(&page->lru, &pgd_list);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-
+-	list_del(&page->lru);
+-}
+-
+-#define UNSHARED_PTRS_PER_PGD				\
+-	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+-
+-static void pgd_ctor(void *p)
+-{
+-	pgd_t *pgd = p;
+-	unsigned long flags;
+-
+-	pgd_test_and_unpin(pgd);
+-
+-	/* Clear usermode parts of PGD */
+-	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-
+-	/* If the pgd points to a shared pagetable level (either the
+-	   ptes in non-PAE, or shared PMD in PAE), then just copy the
+-	   references from swapper_pg_dir. */
+-	if (PAGETABLE_LEVELS == 2 ||
+-	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
+-		clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+-				swapper_pg_dir + USER_PTRS_PER_PGD,
+-				KERNEL_PGD_PTRS);
+-		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+-					__pa(swapper_pg_dir) >> PAGE_SHIFT,
+-					USER_PTRS_PER_PGD,
+-					KERNEL_PGD_PTRS);
+-	}
+-
+-	/* list required to sync kernel mapping updates */
+-	if (PAGETABLE_LEVELS == 2)
+-		pgd_list_add(pgd);
+-
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static void pgd_dtor(void *pgd)
+-{
+-	unsigned long flags; /* can be called from interrupt context */
+-
+-	if (!SHARED_KERNEL_PMD) {
+-		spin_lock_irqsave(&pgd_lock, flags);
+-		pgd_list_del(pgd);
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-	}
+-
+-	pgd_test_and_unpin(pgd);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * Mop up any pmd pages which may still be attached to the pgd.
+- * Normally they will be freed by munmap/exit_mmap, but any pmd we
+- * preallocate which never got a corresponding vma will need to be
+- * freed manually.
+- */
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-	int i;
+-
+-	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
+-		pgd_t pgd = pgdp[i];
+-
+-		if (__pgd_val(pgd) != 0) {
+-			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+-
+-			pgdp[i] = xen_make_pgd(0);
+-
+-			paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
+-			pmd_free(mm, pmd);
+-		}
+-	}
+-}
+-
+-/*
+- * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+- * updating the top-level pagetable entries to guarantee the
+- * processor notices the update.  Since this is expensive, and
+- * all 4 top-level entries are used almost immediately in a
+- * new process's life, we just pre-populate them here.
+- *
+- * Also, if we're in a paravirt environment where the kernel pmd is
+- * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+- * and initialize the kernel pmds here.
+- */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	pud_t *pud;
+-	pmd_t *pmds[UNSHARED_PTRS_PER_PGD];
+-	unsigned long addr, flags;
+-	int i;
+-
+-	/*
+-	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
+-	 * allocation). We therefore store virtual addresses of pmds as they
+-	 * do not change across save/restore, and poke the machine addresses
+-	 * into the pgdir under the pgd_lock.
+-	 */
+- 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD; i++, addr += PUD_SIZE) {
+-		pmds[i] = pmd_alloc_one(mm, addr);
+-		if (!pmds[i])
+-			goto out_oom;
+-	}
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-
+-	/* Protect against save/restore: move below 4GB under pgd_lock. */
+-	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
+-	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-out_oom:
+-		while (i--)
+-			pmd_free(mm, pmds[i]);
+-		return 0;
+-	}
+-
+-	/* Copy kernel pmd contents and write-protect the new pmds. */
+-	pud = pud_offset(pgd, 0);
+- 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
+-	     i++, pud++, addr += PUD_SIZE) {
+-		if (i >= USER_PTRS_PER_PGD) {
+-			memcpy(pmds[i],
+-			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+-			       sizeof(pmd_t) * PTRS_PER_PMD);
+-			make_lowmem_page_readonly(
+-				pmds[i], XENFEAT_writable_page_tables);
+-		}
+-
+-		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
+-		pud_populate(mm, pud, pmds[i]);
+-	}
+-
+-	/* List required to sync kernel mapping updates and
+-	 * to pin/unpin on save/restore. */
+-	pgd_list_add(pgd);
+-
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-
+-	return 1;
+-}
+-#else  /* !CONFIG_X86_PAE */
+-/* No need to prepopulate any pagetable entries in non-PAE modes. */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	return 1;
+-}
+-
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-}
+-#endif	/* CONFIG_X86_PAE */
+-
+-pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+-	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+-
+-	/* so that alloc_pd can use it */
+-	mm->pgd = pgd;
+-	if (pgd)
+-		pgd_ctor(pgd);
+-
+-	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
+-		free_page((unsigned long)pgd);
+-		pgd = NULL;
+-	}
+-
+-	return pgd;
+-}
+-
+-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	/*
+-	 * After this the pgd should not be pinned for the duration of this
+-	 * function's execution. We should never sleep and thus never race:
+-	 *  1. User pmds will not become write-protected under our feet due
+-	 *     to a concurrent mm_pin_all().
+-	 *  2. The machine addresses in PGD entries will not become invalid
+-	 *     due to a concurrent save/restore.
+-	 */
+-	pgd_dtor(pgd);
+-
+-	if (PTRS_PER_PMD > 1 && !xen_feature(XENFEAT_pae_pgdir_above_4gb))
+-		xen_destroy_contiguous_region((unsigned long)pgd, 0);
+-
+-	pgd_mop_up_pmds(mm, pgd);
+-	free_page((unsigned long)pgd);
+-}
+-
+-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+-{
+-	pgtable_page_dtor(pte);
+-	paravirt_release_pt(page_to_pfn(pte));
+-	tlb_remove_page(tlb, pte);
+-}
+-
+-#ifdef CONFIG_X86_PAE
+-
+-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+-{
+-	paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-	tlb_remove_page(tlb, virt_to_page(pmd));
+-}
+-
+-#endif
+-
+ void make_lowmem_page_readonly(void *va, unsigned int feature)
+ {
+ 	pte_t *pte;
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -140,9 +140,11 @@ static void __init pirq_peer_trick(void)
+ 		busmap[e->bus] = 1;
+ 	}
+ 	for(i = 1; i < 256; i++) {
++		int node;
+ 		if (!busmap[i] || pci_find_bus(0, i))
+ 			continue;
+-		if (pci_scan_bus_with_sysdata(i))
++		node = get_mp_bus_to_node(i);
++		if (pci_scan_bus_on_node(i, &pci_root_ops, node))
+ 			printk(KERN_INFO "PCI: Discovered primary peer "
+ 			       "bus %02x [IRQ]\n", i);
+ 	}
+@@ -204,7 +206,7 @@ static int pirq_ali_get(struct pci_dev *
+ {
+ 	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ 
+-	WARN_ON_ONCE(pirq >= 16);
++	WARN_ON_ONCE(pirq > 16);
+ 	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+ }
+ 
+@@ -213,7 +215,7 @@ static int pirq_ali_set(struct pci_dev *
+ 	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ 	unsigned int val = irqmap[irq];
+ 
+-	WARN_ON_ONCE(pirq >= 16);
++	WARN_ON_ONCE(pirq > 16);
+ 	if (val) {
+ 		write_config_nybble(router, 0x48, pirq-1, val);
+ 		return 1;
+@@ -264,7 +266,7 @@ static int pirq_via586_get(struct pci_de
+ {
+ 	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ 
+-	WARN_ON_ONCE(pirq >= 5);
++	WARN_ON_ONCE(pirq > 5);
+ 	return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+ }
+ 
+@@ -272,7 +274,7 @@ static int pirq_via586_set(struct pci_de
+ {
+ 	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+ 
+-	WARN_ON_ONCE(pirq >= 5);
++	WARN_ON_ONCE(pirq > 5);
+ 	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+@@ -286,7 +288,7 @@ static int pirq_ite_get(struct pci_dev *
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+ 
+-	WARN_ON_ONCE(pirq >= 4);
++	WARN_ON_ONCE(pirq > 4);
+ 	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+ }
+ 
+@@ -294,7 +296,7 @@ static int pirq_ite_set(struct pci_dev *
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+ 
+-	WARN_ON_ONCE(pirq >= 4);
++	WARN_ON_ONCE(pirq > 4);
+ 	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+@@ -623,6 +625,13 @@ static __init int via_router_probe(struc
+ 			 */
+ 			device = PCI_DEVICE_ID_VIA_8235;
+ 			break;
++		case PCI_DEVICE_ID_VIA_8237:
++			/**
++			 * Asus a7v600 bios wrongly reports 8237
++			 * as 586-compatible
++			 */
++			device = PCI_DEVICE_ID_VIA_8237;
++			break;
+ 		}
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -164,7 +164,7 @@ static __init void relocate_vdso(Elf32_E
+ 	Elf32_Shdr *shdr;
+ 	int i;
+ 
+-	BUG_ON(memcmp(ehdr->e_ident, ELFMAG, 4) != 0 ||
++	BUG_ON(memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 ||
+ 	       !elf_check_arch_ia32(ehdr) ||
+ 	       ehdr->e_type != ET_DYN);
+ 
+@@ -233,8 +233,12 @@ void syscall32_cpu_init(void)
+ 		BUG();
+ #endif
+ 
+-	if (use_sysenter < 0)
+-		use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
++	if (use_sysenter < 0) {
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++			use_sysenter = 1;
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
++			use_sysenter = 1;
++	}
+ }
+ 
+ #define compat_uses_vma		1
+@@ -337,8 +341,6 @@ int __init sysenter_setup(void)
+ 
+ #ifdef CONFIG_X86_32
+ 	gate_vma_init();
+-
+-	printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
+ #endif
+ 
+ #if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT < 0x030200
+@@ -383,6 +385,9 @@ int arch_setup_additional_pages(struct l
+ 	int ret = 0;
+ 	bool compat;
+ 
++	if (vdso_enabled == VDSO_DISABLED)
++		return 0;
++
+ 	down_write(&mm->mmap_sem);
+ 
+ 	/* Test compat mode once here, in case someone
+--- head-2010-01-18.orig/drivers/acpi/processor_core.c	2009-12-07 10:38:01.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_core.c	2010-01-04 12:38:43.000000000 +0100
+@@ -706,7 +706,7 @@ static int acpi_processor_get_info(struc
+ 	 * of /proc/cpuinfo
+ 	 */
+ 	status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+-	if (ACPI_SUCCESS(status))
++	if (ACPI_SUCCESS(status) && pr->id != -1)
+ 		arch_fix_phys_package_id(pr->id, object.integer.value);
+ 
+ 	return 0;
+--- head-2010-01-18.orig/drivers/firmware/Kconfig	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/firmware/Kconfig	2009-11-06 10:51:32.000000000 +0100
+@@ -114,7 +114,7 @@ config DMIID
+ 
+ config ISCSI_IBFT_FIND
+ 	bool "iSCSI Boot Firmware Table Attributes"
+-	depends on X86
++	depends on X86 && !XEN_UNPRIVILEGED_GUEST
+ 	default n
+ 	help
+ 	  This option enables the kernel to find the region of memory
+--- head-2010-01-18.orig/drivers/firmware/iscsi_ibft_find.c	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/firmware/iscsi_ibft_find.c	2009-11-06 10:51:32.000000000 +0100
+@@ -78,6 +78,8 @@ void __init reserve_ibft_region(void)
+ 			}
+ 		}
+ 	}
++#ifndef CONFIG_XEN
+ 	if (ibft_addr)
+ 		reserve_bootmem(pos, PAGE_ALIGN(len), BOOTMEM_DEFAULT);
++#endif
+ }
+--- head-2010-01-18.orig/drivers/input/xen-kbdfront.c	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/input/xen-kbdfront.c	2009-11-06 10:51:32.000000000 +0100
+@@ -325,7 +325,6 @@ static struct xenbus_device_id xenkbd_id
+ 
+ static struct xenbus_driver xenkbd_driver = {
+ 	.name = "vkbd",
+-	.owner = THIS_MODULE,
+ 	.ids = xenkbd_ids,
+ 	.probe = xenkbd_probe,
+ 	.remove = xenkbd_remove,
+--- head-2010-01-18.orig/drivers/oprofile/cpu_buffer.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/oprofile/cpu_buffer.c	2009-11-06 10:51:32.000000000 +0100
+@@ -503,7 +503,7 @@ fail:
+ #ifdef CONFIG_XEN
+ int oprofile_add_domain_switch(int32_t domain_id)
+ {
+-	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+ 
+ 	/* should have space for switching into and out of domain
+ 	   (2 slots each) plus one sample and one cpu mode switch */
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:03:15.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:05:41.000000000 +0100
+@@ -543,7 +543,7 @@ int pci_enable_msi(struct pci_dev* dev)
+ EXPORT_SYMBOL(pci_enable_msi);
+ 
+ extern void pci_frontend_disable_msi(struct pci_dev* dev);
+-void pci_disable_msi(struct pci_dev* dev)
++void pci_msi_shutdown(struct pci_dev* dev)
+ {
+ 	int pirq;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+@@ -571,6 +571,10 @@ void pci_disable_msi(struct pci_dev* dev
+ 	pci_intx_for_msi(dev, 1);
+ 	dev->msi_enabled = 0;
+ }
++void pci_disable_msi(struct pci_dev* dev)
++{
++	pci_msi_shutdown(dev);
++}
+ EXPORT_SYMBOL(pci_disable_msi);
+ 
+ /**
+@@ -675,7 +679,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ EXPORT_SYMBOL(pci_enable_msix);
+ 
+ extern void pci_frontend_disable_msix(struct pci_dev* dev);
+-void pci_disable_msix(struct pci_dev* dev)
++void pci_msix_shutdown(struct pci_dev* dev)
+ {
+ 	if (!pci_msi_enable || !dev || !dev->msix_enabled)
+ 		return;
+@@ -708,6 +712,10 @@ void pci_disable_msix(struct pci_dev* de
+ 	pci_intx_for_msi(dev, 1);
+ 	dev->msix_enabled = 0;
+ }
++void pci_disable_msix(struct pci_dev* dev)
++{
++	pci_msix_shutdown(dev);
++}
+ EXPORT_SYMBOL(pci_disable_msix);
+ 
+ /**
+--- head-2010-01-18.orig/drivers/video/Kconfig	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/video/Kconfig	2009-11-06 10:51:32.000000000 +0100
+@@ -2057,7 +2057,7 @@ config FB_VIRTUAL
+ 
+ config XEN_FBDEV_FRONTEND
+ 	tristate "Xen virtual frame buffer support"
+-	depends on FB && XEN
++	depends on FB && PARAVIRT_XEN
+ 	select FB_SYS_FILLRECT
+ 	select FB_SYS_COPYAREA
+ 	select FB_SYS_IMAGEBLIT
+--- head-2010-01-18.orig/drivers/video/xen-fbfront.c	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/video/xen-fbfront.c	2009-11-06 10:51:32.000000000 +0100
+@@ -670,7 +670,6 @@ static struct xenbus_device_id xenfb_ids
+ 
+ static struct xenbus_driver xenfb_driver = {
+ 	.name = "vfb",
+-	.owner = THIS_MODULE,
+ 	.ids = xenfb_ids,
+ 	.probe = xenfb_probe,
+ 	.remove = xenfb_remove,
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:16:29.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-11-06 10:51:32.000000000 +0100
+@@ -2,8 +2,6 @@
+ # This Kconfig describe xen options
+ #
+ 
+-mainmenu "Xen Configuration"
+-
+ config XEN
+ 	bool
+ 
+--- head-2010-01-18.orig/drivers/xen/Makefile	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/Makefile	2009-11-06 10:51:32.000000000 +0100
+@@ -1,13 +1,17 @@
+-obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o
++obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o features.o events.o
++xen-xencomm-$(CONFIG_PARAVIRT_XEN) := xencomm.o
++xen-balloon-$(CONFIG_PARAVIRT_XEN) := balloon.o
+ 
++xen-balloon-$(CONFIG_XEN)	:= balloon/
+ obj-$(CONFIG_XEN)		+= core/
+ obj-$(CONFIG_XEN)		+= console/
+ obj-$(CONFIG_XEN)		+= evtchn/
+ obj-y				+= xenbus/
+ obj-$(CONFIG_XEN)		+= char/
+ 
+-obj-$(CONFIG_XEN)		+= util.o
+-obj-$(CONFIG_XEN_BALLOON)		+= balloon/
++obj-$(CONFIG_XEN)		+= features.o util.o
++obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
++obj-$(CONFIG_XEN_BALLOON)	+= $(xen-balloon-y)
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+ obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
+ obj-$(CONFIG_XEN_BLKDEV_TAP2)           += blktap2/
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:19:36.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2009-11-06 10:51:32.000000000 +0100
+@@ -285,7 +285,11 @@ static void backend_changed(struct xenbu
+ 		break;
+ 
+ 	case XenbusStateClosing:
+-		bd = bdget(info->dev);
++		if (!info->gd) {
++			xenbus_frontend_closed(dev);
++			break;
++		}
++		bd = bdget_disk(info->gd, 0);
+ 		if (bd == NULL)
+ 			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/block.h	2010-01-18 16:18:59.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/block.h	2010-01-18 16:30:27.000000000 +0100
+@@ -97,7 +97,6 @@ struct blk_shadow {
+ struct blkfront_info
+ {
+ 	struct xenbus_device *xbdev;
+-	dev_t dev;
+  	struct gendisk *gd;
+ 	int vdevice;
+ 	blkif_vdev_t handle;
+--- head-2010-01-18.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:19:01.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 16:30:28.000000000 +0100
+@@ -327,17 +327,32 @@ xlvbd_init_blk_queue(struct gendisk *gd,
+ 	return 0;
+ }
+ 
+-static int
+-xlvbd_alloc_gendisk(int major, int minor, blkif_sector_t capacity, int vdevice,
+-		    u16 vdisk_info, u16 sector_size,
+-		    struct blkfront_info *info)
++int
++xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info,
++	  u16 sector_size, struct blkfront_info *info)
+ {
++	int major, minor;
+ 	struct gendisk *gd;
+ 	struct xlbd_major_info *mi;
+ 	int nr_minors = 1;
+ 	int err = -ENODEV;
+ 	unsigned int offset;
+ 
++	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;
++	}
++
++	if (!VDEV_IS_EXTENDED(vdevice)) {
++		major = BLKIF_MAJOR(vdevice);
++		minor = BLKIF_MINOR(vdevice);
++	}
++	else {
++		major = 202;
++		minor = BLKIF_MINOR_EXT(vdevice);
++	}
++
+ 	BUG_ON(info->gd != NULL);
+ 	BUG_ON(info->mi != NULL);
+ 	BUG_ON(info->rq != NULL);
+@@ -425,41 +440,6 @@ xlvbd_alloc_gendisk(int major, int minor
+ 	return err;
+ }
+ 
+-int
+-xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info,
+-	  u16 sector_size, struct blkfront_info *info)
+-{
+-	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;
+-	}
+-
+-	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(major, minor, capacity, vdevice, vdisk_info,
+-				  sector_size, info);
+-
+-	bdput(bd);
+-	return err;
+-}
+-
+ void
+ xlvbd_del(struct blkfront_info *info)
+ {
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2010-01-04 12:38:20.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 12:38:54.000000000 +0100
+@@ -111,6 +111,7 @@ typedef struct tap_blkif {
+ 	unsigned long mode;           /*current switching mode               */
+ 	int minor;                    /*Minor number for tapdisk device      */
+ 	pid_t pid;                    /*tapdisk process id                   */
++	struct pid_namespace *pid_ns; /*... and its corresponding namespace  */
+ 	enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace 
+ 						  shutdown                   */
+ 	unsigned long *idx_map;       /*Record the user ring id to kern 
+@@ -301,16 +302,14 @@ static inline int OFFSET_TO_SEG(int offs
+  * BLKTAP VM OPS
+  */
+ 
+-static struct page *blktap_nopage(struct vm_area_struct *vma,
+-				  unsigned long address,
+-				  int *type)
++static int blktap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	/*
+ 	 * if the page has not been mapped in by the driver then return
+-	 * NOPAGE_SIGBUS to the domain.
++	 * VM_FAULT_SIGBUS to the domain.
+ 	 */
+ 
+-	return NOPAGE_SIGBUS;
++	return VM_FAULT_SIGBUS;
+ }
+ 
+ static pte_t blktap_clear_pte(struct vm_area_struct *vma,
+@@ -428,7 +427,7 @@ static void blktap_vma_close(struct vm_a
+ }
+ 
+ static struct vm_operations_struct blktap_vm_ops = {
+-	nopage:   blktap_nopage,
++	fault:    blktap_fault,
+ 	zap_pte:  blktap_clear_pte,
+ 	open:     blktap_vma_open,
+ 	close:    blktap_vma_close,
+@@ -523,9 +522,8 @@ found:
+ 		tapfds[minor] = info;
+ 
+ 		if ((class = get_xen_class()) != NULL)
+-			class_device_create(class, NULL,
+-					    MKDEV(blktap_major, minor), NULL,
+-					    "blktap%d", minor);
++			device_create(class, NULL, MKDEV(blktap_major, minor),
++				      "blktap%d", minor);
+ 	}
+ 
+ out:
+@@ -567,7 +565,7 @@ void signal_tapdisk(int idx) 
+ 		return;
+ 
+ 	if (info->pid > 0) {
+-		ptask = find_task_by_pid(info->pid);
++		ptask = find_task_by_pid_ns(info->pid, info->pid_ns);
+ 		if (ptask)
+ 			info->status = CLEANSHUTDOWN;
+ 	}
+@@ -801,8 +799,9 @@ static int blktap_ioctl(struct inode *in
+ 	{
+ 		if (info) {
+ 			info->pid = (pid_t)arg;
+-			DPRINTK("blktap: pid received %d\n", 
+-			       info->pid);
++			info->pid_ns = current->nsproxy->pid_ns;
++			DPRINTK("blktap: pid received %p:%d\n",
++			        info->pid_ns, info->pid);
+ 		}
+ 		return 0;
+ 	}
+@@ -1740,9 +1739,7 @@ static int __init blkif_init(void)
+ 		 * We only create the device when a request of a new device is
+ 		 * made.
+ 		 */
+-		class_device_create(class, NULL,
+-				    MKDEV(blktap_major, 0), NULL,
+-				    "blktap0");
++		device_create(class, NULL, MKDEV(blktap_major, 0), "blktap0");
+ 	} else {
+ 		/* this is bad, but not fatal */
+ 		WPRINTK("blktap: sysfs xen_class not created\n");
+--- head-2010-01-18.orig/drivers/xen/blktap2/blktap.h	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/blktap.h	2009-12-16 11:51:26.000000000 +0100
+@@ -127,7 +127,7 @@ struct blktap_ring {
+ 	wait_queue_head_t              poll_wait;
+ 
+ 	dev_t                          devno;
+-	struct class_device           *dev;
++	struct device                 *dev;
+ 	atomic_t                       sysfs_refcnt;
+ 	struct mutex                   sysfs_mutex;
+ };
+--- head-2010-01-18.orig/drivers/xen/blktap2/ring.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/ring.c	2009-11-06 10:51:32.000000000 +0100
+@@ -66,16 +66,15 @@ blktap_read_ring(struct blktap *tap)
+ 	return 0;
+ }
+ 
+-static struct page *
+-blktap_ring_nopage(struct vm_area_struct *vma,
+-		   unsigned long address, int *type)
++static int
++blktap_ring_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	/*
+ 	 * if the page has not been mapped in by the driver then return
+-	 * NOPAGE_SIGBUS to the domain.
++	 * VM_FAULT_SIGBUS to the domain.
+ 	 */
+ 
+-	return NOPAGE_SIGBUS;
++	return VM_FAULT_SIGBUS;
+ }
+ 
+ static pte_t
+@@ -205,7 +204,7 @@ blktap_ring_vm_close(struct vm_area_stru
+ static struct vm_operations_struct blktap_ring_vm_operations = {
+ 	.close    = blktap_ring_vm_close,
+ 	.unmap    = blktap_ring_vm_unmap,
+-	.nopage   = blktap_ring_nopage,
++	.fault    = blktap_ring_fault,
+ 	.zap_pte  = blktap_ring_clear_pte,
+ };
+ 
+--- head-2010-01-18.orig/drivers/xen/blktap2/sysfs.c	2009-12-09 15:58:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/sysfs.c	2009-12-09 16:11:54.000000000 +0100
+@@ -36,16 +36,21 @@ blktap_sysfs_exit(struct blktap *tap)
+ 	blktap_sysfs_put(tap);
+ }
+ 
+-static ssize_t blktap_sysfs_pause_device(struct class_device *, const char *, size_t);
+-CLASS_DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
+-static ssize_t blktap_sysfs_resume_device(struct class_device *, const char *, size_t);
+-CLASS_DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
++static ssize_t blktap_sysfs_pause_device(struct device *,
++					 struct device_attribute *,
++					 const char *, size_t);
++DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
++static ssize_t blktap_sysfs_resume_device(struct device *,
++					  struct device_attribute *,
++					  const char *, size_t);
++DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
+ 
+ static ssize_t
+-blktap_sysfs_set_name(struct class_device *dev, const char *buf, size_t size)
++blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr,
++		      const char *buf, size_t size)
+ {
+ 	int err;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	blktap_sysfs_enter(tap);
+ 
+@@ -79,10 +84,11 @@ out:
+ }
+ 
+ static ssize_t
+-blktap_sysfs_get_name(struct class_device *dev, char *buf)
++blktap_sysfs_get_name(struct device *dev, struct device_attribute *attr,
++		      char *buf)
+ {
+ 	ssize_t size;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	blktap_sysfs_enter(tap);
+ 
+@@ -97,15 +103,15 @@ blktap_sysfs_get_name(struct class_devic
+ 
+ 	return size;
+ }
+-CLASS_DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
++DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
+ 		  blktap_sysfs_get_name, blktap_sysfs_set_name);
+ 
+ static ssize_t
+-blktap_sysfs_remove_device(struct class_device *dev,
++blktap_sysfs_remove_device(struct device *dev, struct device_attribute *attr,
+ 			   const char *buf, size_t size)
+ {
+ 	int err;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	if (!tap->ring.dev)
+ 		return size;
+@@ -117,14 +123,14 @@ blktap_sysfs_remove_device(struct class_
+ 
+ 	return (err ? : size);
+ }
+-CLASS_DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
++DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
+ 
+ static ssize_t
+-blktap_sysfs_pause_device(struct class_device *dev,
++blktap_sysfs_pause_device(struct device *dev, struct device_attribute *attr,
+ 			  const char *buf, size_t size)
+ {
+ 	int err;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	blktap_sysfs_enter(tap);
+ 
+@@ -149,8 +155,8 @@ blktap_sysfs_pause_device(struct class_d
+ 
+ 	err = blktap_device_pause(tap);
+ 	if (!err) {
+-		class_device_remove_file(dev, &class_device_attr_pause);
+-		err = class_device_create_file(dev, &class_device_attr_resume);
++		device_remove_file(dev, &dev_attr_pause);
++		err = device_create_file(dev, &dev_attr_resume);
+ 	}
+ 
+ out:
+@@ -160,11 +166,11 @@ out:
+ }
+ 
+ static ssize_t
+-blktap_sysfs_resume_device(struct class_device *dev,
++blktap_sysfs_resume_device(struct device *dev, struct device_attribute *attr,
+ 			   const char *buf, size_t size)
+ {
+ 	int err;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	blktap_sysfs_enter(tap);
+ 
+@@ -181,8 +187,8 @@ blktap_sysfs_resume_device(struct class_
+ 
+ 	err = blktap_device_resume(tap);
+ 	if (!err) {
+-		class_device_remove_file(dev, &class_device_attr_resume);
+-		err = class_device_create_file(dev, &class_device_attr_pause);
++		device_remove_file(dev, &dev_attr_resume);
++		err = device_create_file(dev, &dev_attr_pause);
+ 	}
+ 
+ out:
+@@ -194,12 +200,13 @@ out:
+ 
+ #ifdef ENABLE_PASSTHROUGH
+ static ssize_t
+-blktap_sysfs_enable_passthrough(struct class_device *dev,
++blktap_sysfs_enable_passthrough(struct device *dev,
++				struct device_attribute *attr,
+ 				const char *buf, size_t size)
+ {
+ 	int err;
+ 	unsigned major, minor;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	BTINFO("passthrough request enabled\n");
+ 
+@@ -237,11 +244,12 @@ out:
+ #endif
+ 
+ static ssize_t
+-blktap_sysfs_debug_device(struct class_device *dev, char *buf)
++blktap_sysfs_debug_device(struct device *dev, struct device_attribute *attr,
++			  char *buf)
+ {
+ 	char *tmp;
+ 	int i, ret;
+-	struct blktap *tap = (struct blktap *)dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+ 	tmp = buf;
+ 	blktap_sysfs_get(tap);
+@@ -285,13 +293,13 @@ out:
+ 
+ 	return ret;
+ }
+-CLASS_DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
++DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
+ 
+ int
+ blktap_sysfs_create(struct blktap *tap)
+ {
+ 	struct blktap_ring *ring;
+-	struct class_device *dev;
++	struct device *dev;
+ 	int err, state = 0;
+ 
+ 	if (!class)
+@@ -299,53 +307,53 @@ blktap_sysfs_create(struct blktap *tap)
+ 
+ 	ring = &tap->ring;
+ 
+-	dev = class_device_create(class, NULL, ring->devno,
+-				  NULL, "blktap%d", tap->minor);
++	dev = device_create_drvdata(class, NULL, ring->devno, tap,
++				    "blktap%d", tap->minor);
+ 	if (IS_ERR(dev))
+ 		return PTR_ERR(dev);
+ 
+-	ring->dev       = dev;
+-	dev->class_data = tap;
++	ring->dev = dev;
+ 
+ 	mutex_init(&ring->sysfs_mutex);
+ 	atomic_set(&ring->sysfs_refcnt, 0);
+ 	set_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+ 
+-	err = class_device_create_file(dev, &class_device_attr_name);
++	err = device_create_file(dev, &dev_attr_name);
+ 	if (!err) {
+ 		++state;
+-		err = class_device_create_file(dev, &class_device_attr_remove);
++		err = device_create_file(dev, &dev_attr_remove);
+ 	}
+ 	if (!err) {
+ 		++state;
+-		err = class_device_create_file(dev, &class_device_attr_pause);
++		err = device_create_file(dev, &dev_attr_pause);
+ 	}
+ 	if (!err) {
+ 		++state;
+-		err = class_device_create_file(dev, &class_device_attr_debug);
++		err = device_create_file(dev, &dev_attr_debug);
+ 	}
+ 
+ 	switch (state * !!err) {
+-	case 3: class_device_remove_file(dev, &class_device_attr_pause);
+-	case 2: class_device_remove_file(dev, &class_device_attr_remove);
+-	case 1: class_device_remove_file(dev, &class_device_attr_name);
++	case 3: device_remove_file(dev, &dev_attr_pause);
++	case 2: device_remove_file(dev, &dev_attr_remove);
++	case 1: device_remove_file(dev, &dev_attr_name);
+ 	}
+ 
+ 	return err;
+ }
+ 
+ static void
+-_blktap_sysfs_destroy(struct device *_dev)
++_blktap_sysfs_destroy(struct device *dev)
+ {
+-	struct class_device *dev = _dev->???;
+-	struct blktap *tap = dev->class_data;
++	struct blktap *tap = dev_get_drvdata(dev);
+ 
+-	class_device_remove_file(dev, &class_device_attr_name);
+-	class_device_remove_file(dev, &class_device_attr_remove);
+-	class_device_remove_file(dev, &class_device_attr_pause);
+-	class_device_remove_file(dev, &class_device_attr_resume);
+-	class_device_remove_file(dev, &class_device_attr_debug);
+-	class_device_unregister(dev);
++	device_remove_file(dev, &dev_attr_name);
++	device_remove_file(dev, &dev_attr_remove);
++	device_remove_file(dev, &dev_attr_pause);
++	device_remove_file(dev, &dev_attr_resume);
++	device_remove_file(dev, &dev_attr_debug);
++
++	put_device(dev);
++	device_unregister(dev);
+ 
+ 	clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+ }
+@@ -354,7 +362,7 @@ int
+ blktap_sysfs_destroy(struct blktap *tap)
+ {
+ 	struct blktap_ring *ring;
+-	struct class_device *dev;
++	struct device *dev;
+ 
+ 	ring = &tap->ring;
+ 	dev  = ring->dev;
+@@ -366,7 +374,7 @@ blktap_sysfs_destroy(struct blktap *tap)
+ 				     !atomic_read(&tap->ring.sysfs_refcnt)))
+ 		return -EAGAIN;
+ 
+-	return device_schedule_callback(dev->???, _blktap_sysfs_destroy);
++	return device_schedule_callback(dev, _blktap_sysfs_destroy);
+ }
+ 
+ static ssize_t
+--- head-2010-01-18.orig/drivers/xen/char/mem.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/char/mem.c	2009-11-06 10:51:32.000000000 +0100
+@@ -33,6 +33,27 @@ static inline int uncached_access(struct
+ 	return 0;
+ }
+ 
++static inline int range_is_allowed(unsigned long pfn, unsigned long size)
++{
++#ifdef CONFIG_NONPROMISC_DEVMEM
++	u64 from = ((u64)pfn) << PAGE_SHIFT;
++	u64 to = from + size;
++	u64 cursor = from;
++
++	while (cursor < to) {
++		if (!devmem_is_allowed(pfn)) {
++			printk(KERN_INFO
++		"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
++				current->comm, from, to);
++			return 0;
++		}
++		cursor += PAGE_SIZE;
++		pfn++;
++	}
++#endif
++	return 1;
++}
++
+ /*
+  * This funcion reads the *physical* memory. The f_pos points directly to the 
+  * memory location. 
+@@ -55,6 +76,9 @@ static ssize_t read_mem(struct file * fi
+ 
+ 		sz = min_t(unsigned long, sz, count);
+ 
++		if (!range_is_allowed(p >> PAGE_SHIFT, count))
++			return -EPERM;
++
+ 		v = ioremap(p, sz);
+ 		if (IS_ERR(v) || v == NULL) {
+ 			/*
+@@ -103,6 +127,9 @@ static ssize_t write_mem(struct file * f
+ 
+ 		sz = min_t(unsigned long, sz, count);
+ 
++		if (!range_is_allowed(p >> PAGE_SHIFT, sz))
++			return -EPERM;
++
+ 		v = ioremap(p, sz);
+ 		if (v == NULL)
+ 			break;
+@@ -131,6 +158,23 @@ static ssize_t write_mem(struct file * f
+ }
+ 
+ #ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
++static void mmap_mem_open(struct vm_area_struct *vma)
++{
++	map_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
++			vma->vm_page_prot);
++}
++
++static void mmap_mem_close(struct vm_area_struct *vma)
++{
++	unmap_devmem(vma->vm_pgoff,  vma->vm_end - vma->vm_start,
++			vma->vm_page_prot);
++}
++
++static struct vm_operations_struct mmap_mem_ops = {
++	.open  = mmap_mem_open,
++	.close = mmap_mem_close
++};
++
+ static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma)
+ {
+ 	size_t size = vma->vm_end - vma->vm_start;
+@@ -138,6 +182,15 @@ static int xen_mmap_mem(struct file * fi
+ 	if (uncached_access(file))
+ 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ 
++	if (!range_is_allowed(vma->vm_pgoff, size))
++		return -EPERM;
++
++	if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
++						&vma->vm_page_prot))
++		return -EINVAL;
++
++	vma->vm_ops = &mmap_mem_ops;
++
+ 	/* We want to return the real error code, not EAGAIN. */
+ 	return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ 				      size, vma->vm_page_prot, DOMID_IO);
+--- head-2010-01-18.orig/drivers/xen/console/console.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/console/console.c	2009-11-06 10:51:32.000000000 +0100
+@@ -551,16 +551,18 @@ static int xencons_write(
+ 	return i;
+ }
+ 
+-static void xencons_put_char(struct tty_struct *tty, u_char ch)
++static int xencons_put_char(struct tty_struct *tty, u_char ch)
+ {
+ 	unsigned long flags;
++	int ret;
+ 
+ 	if (DUMMY_TTY(tty))
+-		return;
++		return 0;
+ 
+ 	spin_lock_irqsave(&xencons_lock, flags);
+-	(void)__xencons_put_char(ch);
++	ret = __xencons_put_char(ch);
+ 	spin_unlock_irqrestore(&xencons_lock, flags);
++	return ret;
+ }
+ 
+ static void xencons_flush_chars(struct tty_struct *tty)
+@@ -582,7 +584,7 @@ static void xencons_wait_until_sent(stru
+ 	if (DUMMY_TTY(tty))
+ 		return;
+ 
+-	while (DRV(tty->driver)->chars_in_buffer(tty)) {
++	while (tty_chars_in_buffer(tty)) {
+ 		set_current_state(TASK_INTERRUPTIBLE);
+ 		schedule_timeout(1);
+ 		if (signal_pending(current))
+@@ -631,8 +633,7 @@ static void xencons_close(struct tty_str
+ 
+ 	tty->closing = 1;
+ 	tty_wait_until_sent(tty, 0);
+-	if (DRV(tty->driver)->flush_buffer != NULL)
+-		DRV(tty->driver)->flush_buffer(tty);
++	tty_driver_flush_buffer(tty);
+ 	if (tty->ldisc.flush_buffer != NULL)
+ 		tty->ldisc.flush_buffer(tty);
+ 	tty->closing = 0;
+--- head-2010-01-18.orig/drivers/xen/core/Makefile	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/Makefile	2009-11-06 10:51:32.000000000 +0100
+@@ -2,7 +2,7 @@
+ # Makefile for the linux kernel.
+ #
+ 
+-obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o firmware.o
++obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o firmware.o
+ 
+ obj-$(CONFIG_PCI)		+= pci.o
+ obj-$(CONFIG_PROC_FS)		+= xen_proc.o
+--- head-2010-01-18.orig/drivers/xen/core/features.c	2009-11-06 10:51:07.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,34 +0,0 @@
+-/******************************************************************************
+- * features.c
+- *
+- * Xen feature flags.
+- *
+- * Copyright (c) 2006, Ian Campbell, XenSource Inc.
+- */
+-#include <linux/types.h>
+-#include <linux/cache.h>
+-#include <linux/module.h>
+-#include <asm/hypervisor.h>
+-#include <xen/features.h>
+-
+-#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+-#include <xen/platform-compat.h>
+-#endif
+-
+-u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
+-/* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */
+-EXPORT_SYMBOL(xen_features);
+-
+-void xen_setup_features(void)
+-{
+-	xen_feature_info_t fi;
+-	int i, j;
+-
+-	for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
+-		fi.submap_idx = i;
+-		if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+-			break;
+-		for (j=0; j<32; j++)
+-			xen_features[i*32+j] = !!(fi.submap & 1<<j);
+-	}
+-}
+--- head-2010-01-18.orig/drivers/xen/core/machine_kexec.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/machine_kexec.c	2009-11-06 10:51:32.000000000 +0100
+@@ -5,6 +5,7 @@
+ 
+ #include <linux/kexec.h>
+ #include <xen/interface/kexec.h>
++#include <linux/reboot.h>
+ #include <linux/mm.h>
+ #include <linux/bootmem.h>
+ 
+@@ -90,6 +91,9 @@ void __init xen_machine_kexec_setup_reso
+ 	xen_hypervisor_res.start = range.start;
+ 	xen_hypervisor_res.end = range.start + range.size - 1;
+ 	xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
++#ifdef CONFIG_X86_64
++	insert_resource(&iomem_resource, &xen_hypervisor_res);
++#endif
+ 
+ 	/* fill in crashk_res if range is reserved by hypervisor */
+ 
+@@ -102,6 +106,9 @@ void __init xen_machine_kexec_setup_reso
+ 	if (range.size) {
+ 		crashk_res.start = range.start;
+ 		crashk_res.end = range.start + range.size - 1;
++#ifdef CONFIG_X86_64
++		insert_resource(&iomem_resource, &crashk_res);
++#endif
+ 	}
+ 
+ 	/* get physical address of vmcoreinfo */
+@@ -134,6 +141,14 @@ void __init xen_machine_kexec_setup_reso
+ 					  xen_max_nr_phys_cpus))
+ 		goto err;
+ 
++#ifdef CONFIG_X86_64
++	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
++		res = xen_phys_cpus + k;
++		if (!res->parent) /* outside of xen_hypervisor_res range */
++			insert_resource(&iomem_resource, res);
++	}
++#endif
++
+ #ifdef CONFIG_X86
+ 	if (xen_create_contiguous_region((unsigned long)&vmcoreinfo_note,
+ 					 get_order(sizeof(vmcoreinfo_note)),
+@@ -153,6 +168,7 @@ void __init xen_machine_kexec_setup_reso
+ 	return;
+ }
+ 
++#ifndef CONFIG_X86_64
+ void __init xen_machine_kexec_register_resources(struct resource *res)
+ {
+ 	int k;
+@@ -166,6 +182,7 @@ void __init xen_machine_kexec_register_r
+ 	} 
+ 	machine_kexec_register_resources(res);
+ }
++#endif
+ 
+ static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+ {
+@@ -236,6 +253,11 @@ void machine_shutdown(void)
+ 	/* do nothing */
+ }
+ 
++void machine_crash_shutdown(struct pt_regs *regs)
++{
++	/* The kernel is broken so disable interrupts */
++	local_irq_disable();
++}
+ 
+ /*
+  * Local variables:
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:51:32.000000000 +0100
+@@ -53,16 +53,15 @@ static DEFINE_PER_CPU(int, callfunc_irq)
+ static char resched_name[NR_CPUS][15];
+ static char callfunc_name[NR_CPUS][15];
+ 
+-u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
++#ifdef CONFIG_X86_LOCAL_APIC
++#define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
++#else
++#define set_cpu_to_apicid(cpu, apicid)
++#endif
+ 
+ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
+ DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+ 
+-#if defined(__i386__)
+-DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+-#endif
+-
+ void __init prefill_possible_map(void)
+ {
+ 	int i, rc;
+@@ -153,7 +152,7 @@ static int __cpuinit xen_smp_intr_init(u
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-static void xen_smp_intr_exit(unsigned int cpu)
++static void __cpuexit xen_smp_intr_exit(unsigned int cpu)
+ {
+ 	if (cpu != 0)
+ 		local_teardown_timer(cpu);
+@@ -262,8 +261,7 @@ void __init smp_prepare_cpus(unsigned in
+ 	boot_cpu_data.apicid = apicid;
+ 	cpu_data(0) = boot_cpu_data;
+ 
+-	cpu_2_logical_apicid[0] = apicid;
+-	per_cpu(x86_cpu_to_apicid, 0) = apicid;
++	set_cpu_to_apicid(0, apicid);
+ 
+ 	current_thread_info()->cpu = 0;
+ 
+@@ -318,8 +316,7 @@ void __init smp_prepare_cpus(unsigned in
+ 		cpu_data(cpu).cpu_index = cpu;
+ 		cpu_data(cpu).apicid = apicid;
+ 
+-		cpu_2_logical_apicid[cpu] = apicid;
+-		per_cpu(x86_cpu_to_apicid, cpu) = apicid;
++		set_cpu_to_apicid(cpu, apicid);
+ 
+ #ifdef __x86_64__
+ 		cpu_pda(cpu)->pcurrent = idle;
+@@ -374,7 +371,7 @@ static int __init initialize_cpu_present
+ }
+ core_initcall(initialize_cpu_present_map);
+ 
+-int __cpu_disable(void)
++int __cpuexit __cpu_disable(void)
+ {
+ 	cpumask_t map = cpu_online_map;
+ 	unsigned int cpu = smp_processor_id();
+@@ -391,7 +388,7 @@ int __cpu_disable(void)
+ 	return 0;
+ }
+ 
+-void __cpu_die(unsigned int cpu)
++void __cpuexit __cpu_die(unsigned int cpu)
+ {
+ 	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+ 		current->state = TASK_UNINTERRUPTIBLE;
+--- head-2010-01-18.orig/drivers/xen/core/xen_proc.c	2007-06-12 13:13:44.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/xen_proc.c	2009-11-06 10:51:32.000000000 +0100
+@@ -8,7 +8,7 @@ static struct proc_dir_entry *xen_base;
+ struct proc_dir_entry *create_xen_proc_entry(const char *name, mode_t mode)
+ {
+ 	if ( xen_base == NULL )
+-		if ( (xen_base = proc_mkdir("xen", &proc_root)) == NULL )
++		if ( (xen_base = proc_mkdir("xen", NULL)) == NULL )
+ 			panic("Couldn't create /proc/xen");
+ 	return create_proc_entry(name, mode, xen_base);
+ }
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenfb.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-11-06 10:51:32.000000000 +0100
+@@ -93,7 +93,7 @@ struct xenfb_info
+  *    only mappings.  The former creates unfaulted pages.  Preserves
+  *    invariant.  The latter removes pages.  Preserves invariant.
+  *
+- * 3. Holding both locks: xenfb_vm_nopage().  Extends the dirty
++ * 3. Holding both locks: xenfb_vm_fault().  Extends the dirty
+  *    rectangle and updates mappings consistently.  Preserves
+  *    invariant.
+  *
+@@ -112,13 +112,13 @@ struct xenfb_info
+  *
+  * But FIXME: the invariant is too weak.  It misses that the fault
+  * record in mappings must be consistent with the mapping of pages in
+- * the associated address space!  do_no_page() updates the PTE after
+- * xenfb_vm_nopage() returns, i.e. outside the critical region.  This
++ * the associated address space!  __do_fault() updates the PTE after
++ * xenfb_vm_fault() returns, i.e. outside the critical region.  This
+  * allows the following race:
+  *
+  * X writes to some address in the Xen frame buffer
+- * Fault - call do_no_page()
+- *     call xenfb_vm_nopage()
++ * Fault - call __do_fault()
++ *     call xenfb_vm_fault()
+  *         grab mm_lock
+  *         map->faults++;
+  *         release mm_lock
+@@ -387,18 +387,17 @@ static void xenfb_vm_close(struct vm_are
+ 	mutex_unlock(&info->mm_lock);
+ }
+ 
+-static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
+-				    unsigned long vaddr, int *type)
++static int xenfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+ 	struct xenfb_mapping *map = vma->vm_private_data;
+ 	struct xenfb_info *info = map->info;
+-	int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
++	int pgnr = ((long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT;
+ 	unsigned long flags;
+ 	struct page *page;
+ 	int y1, y2;
+ 
+ 	if (pgnr >= info->nr_pages)
+-		return NOPAGE_SIGBUS;
++		return VM_FAULT_SIGBUS;
+ 
+ 	mutex_lock(&info->mm_lock);
+ 	spin_lock_irqsave(&info->dirty_lock, flags);
+@@ -414,16 +413,15 @@ static struct page *xenfb_vm_nopage(stru
+ 	spin_unlock_irqrestore(&info->dirty_lock, flags);
+ 	mutex_unlock(&info->mm_lock);
+ 
+-	if (type)
+-		*type = VM_FAULT_MINOR;
++	vmf->page = page;
+ 
+-	return page;
++	return VM_FAULT_MINOR;
+ }
+ 
+ static struct vm_operations_struct xenfb_vm_ops = {
+ 	.open	= xenfb_vm_open,
+ 	.close	= xenfb_vm_close,
+-	.nopage	= xenfb_vm_nopage,
++	.fault	= xenfb_vm_fault,
+ };
+ 
+ static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
+--- head-2010-01-18.orig/drivers/xen/features.c	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/drivers/xen/features.c	2010-01-11 15:55:28.000000000 +0100
+@@ -9,14 +9,21 @@
+ #include <linux/cache.h>
+ #include <linux/module.h>
+ 
++#ifdef CONFIG_PARAVIRT_XEN
+ #include <asm/xen/hypercall.h>
++#else
++#include <asm/hypervisor.h>
++#endif
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
+ 
+ #include <xen/interface/xen.h>
+ #include <xen/interface/version.h>
+ #include <xen/features.h>
+ 
+ u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
+-EXPORT_SYMBOL_GPL(xen_features);
++EXPORT_SYMBOL(xen_features);
+ 
+ void xen_setup_features(void)
+ {
+--- head-2010-01-18.orig/drivers/xen/gntdev/gntdev.c	2010-01-04 12:38:10.000000000 +0100
++++ head-2010-01-18/drivers/xen/gntdev/gntdev.c	2009-11-06 10:51:32.000000000 +0100
+@@ -392,7 +392,7 @@ nomem_out:
+ static int __init gntdev_init(void)
+ {
+ 	struct class *class;
+-	struct class_device *device;
++	struct device *device;
+ 
+ 	if (!is_running_on_xen()) {
+ 		printk(KERN_ERR "You must be running Xen to use gntdev\n");
+@@ -417,8 +417,8 @@ static int __init gntdev_init(void)
+ 		return 0;
+ 	}
+ 
+-	device = class_device_create(class, NULL, MKDEV(gntdev_major, 0),
+-				     NULL, GNTDEV_NAME);
++	device = device_create(class, NULL, MKDEV(gntdev_major, 0),
++			       GNTDEV_NAME);
+ 	if (IS_ERR(device)) {
+ 		printk(KERN_ERR "Error creating gntdev device in xen_class\n");
+ 		printk(KERN_ERR "gntdev created with major number = %d\n",
+@@ -435,7 +435,7 @@ static void __exit gntdev_exit(void)
+ {
+ 	struct class *class;
+ 	if ((class = get_xen_class()) != NULL)
+-		class_device_destroy(class, MKDEV(gntdev_major, 0));
++		device_destroy(class, MKDEV(gntdev_major, 0));
+ 	unregister_chrdev(gntdev_major, GNTDEV_NAME);
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:51:32.000000000 +0100
+@@ -1464,8 +1464,7 @@ err:	
+ 		}
+ 	}
+ 
+-	while ((skb = __skb_dequeue(&errq)))
+-		kfree_skb(skb);
++	__skb_queue_purge(&errq);
+ 
+ 	while ((skb = __skb_dequeue(&rxq)) != NULL) {
+ 		struct page *page = NETFRONT_SKB_CB(skb)->page;
+@@ -1630,8 +1629,7 @@ static void netif_release_rx_bufs_flip(s
+ 		}
+ 	}
+ 
+-	while ((skb = __skb_dequeue(&free_list)) != NULL)
+-		dev_kfree_skb(skb);
++	__skb_queue_purge(&free_list);
+ 
+ 	spin_unlock_bh(&np->rx_lock);
+ }
+--- head-2010-01-18.orig/drivers/xen/privcmd/privcmd.c	2010-01-19 10:31:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/privcmd/privcmd.c	2010-01-19 10:32:17.000000000 +0100
+@@ -400,15 +400,13 @@ static long privcmd_ioctl(struct file *f
+ }
+ 
+ #ifndef HAVE_ARCH_PRIVCMD_MMAP
+-static struct page *privcmd_nopage(struct vm_area_struct *vma,
+-				   unsigned long address,
+-				   int *type)
++static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ {
+-	return NOPAGE_SIGBUS;
++	return VM_FAULT_SIGBUS;
+ }
+ 
+ static struct vm_operations_struct privcmd_vm_ops = {
+-	.nopage = privcmd_nopage
++	.fault = privcmd_fault
+ };
+ 
+ static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:32.000000000 +0100
+@@ -440,7 +440,7 @@ int xenbus_map_ring_valloc(struct xenbus
+ 
+ 	*vaddr = NULL;
+ 
+-	area = alloc_vm_area(PAGE_SIZE);
++	area = xen_alloc_vm_area(PAGE_SIZE);
+ 	if (!area)
+ 		return -ENOMEM;
+ 
+@@ -450,7 +450,7 @@ int xenbus_map_ring_valloc(struct xenbus
+ 		BUG();
+ 
+ 	if (op.status != GNTST_okay) {
+-		free_vm_area(area);
++		xen_free_vm_area(area);
+ 		xenbus_dev_fatal(dev, op.status,
+ 				 "mapping in shared page %d from domain %d",
+ 				 gnt_ref, dev->otherend_id);
+@@ -549,7 +549,7 @@ int xenbus_unmap_ring_vfree(struct xenbu
+ 		BUG();
+ 
+ 	if (op.status == GNTST_okay)
+-		free_vm_area(area);
++		xen_free_vm_area(area);
+ 	else
+ 		xenbus_dev_error(dev, op.status,
+ 				 "unmapping page at handle %d error %d",
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2010-01-04 12:39:22.000000000 +0100
+@@ -174,7 +174,7 @@ static int read_backend_details(struct x
+ 	return read_otherend_details(xendev, "backend-id", "backend");
+ }
+ 
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) && (defined(CONFIG_XEN) || defined(MODULE))
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ static int xenbus_uevent_frontend(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct xenbus_device *xdev;
+@@ -186,8 +186,10 @@ static int xenbus_uevent_frontend(struct
+ 		return -ENODEV;
+ 
+ 	/* stuff we want to pass to /sbin/hotplug */
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype);
+ 	add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename);
++#endif
+ 	add_uevent_var(env, "MODALIAS=xen:%s", xdev->devicetype);
+ 
+ 	return 0;
+@@ -208,10 +210,8 @@ static struct xen_bus_type xenbus_fronte
+ 		.probe    = xenbus_dev_probe,
+ 		.remove   = xenbus_dev_remove,
+ 		.shutdown = xenbus_dev_shutdown,
+-#if defined(CONFIG_XEN) || defined(MODULE)
+ 		.uevent   = xenbus_uevent_frontend,
+ #endif
+-#endif
+ 	},
+ #if defined(CONFIG_XEN) || defined(MODULE)
+ 	.dev = {
+@@ -529,6 +529,15 @@ static ssize_t xendev_show_devtype(struc
+ }
+ static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
+ 
++static ssize_t xendev_show_modalias(struct device *dev,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
++				    struct device_attribute *attr,
++#endif
++				    char *buf)
++{
++	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
++}
++DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+ 
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ 		      const char *type,
+@@ -589,10 +598,16 @@ int xenbus_probe_node(struct xen_bus_typ
+ 
+ 	err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ 	if (err)
+-		goto fail_remove_file;
++		goto fail_remove_nodename;
++
++	err = device_create_file(&xendev->dev, &dev_attr_modalias);
++	if (err)
++		goto fail_remove_devtype;
+ 
+ 	return 0;
+-fail_remove_file:
++fail_remove_devtype:
++	device_remove_file(&xendev->dev, &dev_attr_devtype);
++fail_remove_nodename:
+ 	device_remove_file(&xendev->dev, &dev_attr_nodename);
+ fail_unregister:
+ 	device_unregister(&xendev->dev);
+--- head-2010-01-18.orig/fs/aio.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/fs/aio.c	2009-11-06 10:51:32.000000000 +0100
+@@ -1233,6 +1233,7 @@ static void io_destroy(struct kioctx *io
+ #ifdef CONFIG_EPOLL
+ 	/* forget the poll file, but it's up to the user to close it */
+ 	if (ioctx->file) {
++		fput(ioctx->file);
+ 		ioctx->file->private_data = 0;
+ 		ioctx->file = 0;
+ 	}
+@@ -1257,6 +1258,7 @@ static int aio_queue_fd_close(struct ino
+ 		spin_lock_irq(&ioctx->ctx_lock);
+ 		ioctx->file = 0;
+ 		spin_unlock_irq(&ioctx->ctx_lock);
++		fput(file);
+ 	}
+ 	return 0;
+ }
+@@ -1292,16 +1294,17 @@ static const struct file_operations aioq
+ 
+ static int make_aio_fd(struct kioctx *ioctx)
+ {
+-	int error, fd;
+-	struct inode *inode;
++	int fd;
+ 	struct file *file;
+ 
+-	error = anon_inode_getfd(&fd, &inode, &file, "[aioq]",
+-				 &aioq_fops, ioctx);
+-	if (error)
+-		return error;
++	fd = anon_inode_getfd("[aioq]", &aioq_fops, ioctx);
++	if (fd < 0)
++		return fd;
+ 
+ 	/* associate the file with the IO context */
++	file = fget(fd);
++	if (!file)
++		return -EBADF;
+ 	file->private_data = ioctx;
+ 	ioctx->file = file;
+ 	init_waitqueue_head(&ioctx->poll_wait);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:32.000000000 +0100
+@@ -64,8 +64,8 @@ static inline struct desc_struct *get_cp
+ }
+ 
+ static inline void pack_gate(gate_desc *gate, unsigned char type,
+-       unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+-
++			     unsigned long base, unsigned dpl, unsigned flags,
++			     unsigned short seg)
+ {
+ 	gate->a = (seg << 16) | (base & 0xffff);
+ 	gate->b = (base & 0xffff0000) |
+@@ -84,22 +84,23 @@ static inline int desc_empty(const void 
+ #define load_TR_desc() native_load_tr_desc()
+ #define load_gdt(dtr) native_load_gdt(dtr)
+ #define load_idt(dtr) native_load_idt(dtr)
+-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
++#define load_tr(tr) asm volatile("ltr %0"::"m" (tr))
++#define load_ldt(ldt) asm volatile("lldt %0"::"m" (ldt))
+ 
+ #define store_gdt(dtr) native_store_gdt(dtr)
+ #define store_idt(dtr) native_store_idt(dtr)
+ #define store_tr(tr) (tr = native_store_tr())
+-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
++#define store_ldt(ldt) asm("sldt %0":"=m" (ldt))
+ 
+ #define load_TLS(t, cpu) native_load_tls(t, cpu)
+ #define set_ldt native_set_ldt
+ 
+-#define write_ldt_entry(dt, entry, desc) \
+-				native_write_ldt_entry(dt, entry, desc)
+-#define write_gdt_entry(dt, entry, desc, type) \
+-				native_write_gdt_entry(dt, entry, desc, type)
+-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
++#define write_ldt_entry(dt, entry, desc)	\
++	native_write_ldt_entry(dt, entry, desc)
++#define write_gdt_entry(dt, entry, desc, type)		\
++	native_write_gdt_entry(dt, entry, desc, type)
++#define write_idt_entry(dt, entry, g)		\
++	native_write_idt_entry(dt, entry, g)
+ 
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ 					  const gate_desc *gate)
+@@ -138,8 +139,8 @@ static inline void pack_descriptor(struc
+ {
+ 	desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ 	desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+-		  (limit & 0x000f0000) | ((type & 0xff) << 8) |
+-		  ((flags & 0xf) << 20);
++		(limit & 0x000f0000) | ((type & 0xff) << 8) |
++		((flags & 0xf) << 20);
+ 	desc->p = 1;
+ }
+ 
+@@ -160,7 +161,6 @@ static inline void set_tssldt_descriptor
+ 	desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
+ 	desc->base3 = PTR_HIGH(addr);
+ #else
+-
+ 	pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+ #endif
+ }
+@@ -178,7 +178,8 @@ static inline void __set_tss_desc(unsign
+ 	 * last valid byte
+ 	 */
+ 	set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
+-		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
++			      IO_BITMAP_OFFSET + IO_BITMAP_BYTES +
++			      sizeof(unsigned long) - 1);
+ 	write_gdt_entry(d, entry, &tss, DESC_TSS);
+ }
+ 
+@@ -187,16 +188,16 @@ static inline void __set_tss_desc(unsign
+ static inline void native_set_ldt(const void *addr, unsigned int entries)
+ {
+ 	if (likely(entries == 0))
+-		__asm__ __volatile__("lldt %w0"::"q" (0));
++		asm volatile("lldt %w0"::"q" (0));
+ 	else {
+ 		unsigned cpu = smp_processor_id();
+ 		ldt_desc ldt;
+ 
+-		set_tssldt_descriptor(&ldt, (unsigned long)addr,
+-				      DESC_LDT, entries * sizeof(ldt) - 1);
++		set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,
++				      entries * LDT_ENTRY_SIZE - 1);
+ 		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ 				&ldt, DESC_LDT);
+-		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
++		asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ 	}
+ }
+ 
+@@ -261,15 +262,15 @@ static inline void xen_load_tls(struct t
+ }
+ #endif
+ 
+-#define _LDT_empty(info) (\
+-	(info)->base_addr	== 0	&& \
+-	(info)->limit		== 0	&& \
+-	(info)->contents	== 0	&& \
+-	(info)->read_exec_only	== 1	&& \
+-	(info)->seg_32bit	== 0	&& \
+-	(info)->limit_in_pages	== 0	&& \
+-	(info)->seg_not_present	== 1	&& \
+-	(info)->useable		== 0)
++#define _LDT_empty(info)				\
++	((info)->base_addr		== 0	&&	\
++	 (info)->limit			== 0	&&	\
++	 (info)->contents		== 0	&&	\
++	 (info)->read_exec_only		== 1	&&	\
++	 (info)->seg_32bit		== 0	&&	\
++	 (info)->limit_in_pages		== 0	&&	\
++	 (info)->seg_not_present	== 1	&&	\
++	 (info)->useable		== 0)
+ 
+ #ifdef CONFIG_X86_64
+ #define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+@@ -309,7 +310,7 @@ static inline unsigned long get_desc_lim
+ 
+ #ifndef CONFIG_X86_NO_IDT
+ static inline void _set_gate(int gate, unsigned type, void *addr,
+-			      unsigned dpl, unsigned ist, unsigned seg)
++			     unsigned dpl, unsigned ist, unsigned seg)
+ {
+ 	gate_desc s;
+ 	pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+@@ -393,10 +394,10 @@ static inline void set_system_gate_ist(i
+  *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+  */
+ #define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+-	movb idx*8+4(gdt), lo_b; \
+-	movb idx*8+7(gdt), hi_b; \
+-	shll $16, base; \
+-	movw idx*8+2(gdt), lo_w;
++	movb idx * 8 + 4(gdt), lo_b;			\
++	movb idx * 8 + 7(gdt), hi_b;			\
++	shll $16, base;					\
++	movw idx * 8 + 2(gdt), lo_w;
+ 
+ 
+ #endif /* __ASSEMBLY__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,17 @@
+-#ifdef CONFIG_X86_32
+-# include "dma-mapping_32.h"
+-#else
+-# include "dma-mapping_64.h"
+-#endif
++#ifndef _ASM_DMA_MAPPING_H_
++
++#include_next <asm/dma-mapping.h>
++
++static inline int
++address_needs_mapping(struct device *hwdev, dma_addr_t addr)
++{
++	dma_addr_t mask = 0xffffffff;
++	/* If the device has a mask, use it, otherwise default to 32 bits */
++	if (hwdev && hwdev->dma_mask)
++		mask = *hwdev->dma_mask;
++	return (addr & ~mask) != 0;
++}
++
++extern int range_straddles_page_boundary(paddr_t p, size_t size);
++
++#endif /* _ASM_DMA_MAPPING_H_ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,13 @@
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
+ #ifdef CONFIG_X86_32
+ # include "fixmap_32.h"
+ #else
+ # include "fixmap_64.h"
+ #endif
++
++#define clear_fixmap(idx)			\
++	__set_fixmap(idx, 0, __pgprot(0))
++
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:32.000000000 +0100
+@@ -10,8 +10,8 @@
+  * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+  */
+ 
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_32_H
++#define _ASM_FIXMAP_32_H
+ 
+ /* used by vmalloc.c, vsyscall.lds.S.
+  *
+@@ -102,8 +102,7 @@ enum fixed_addresses {
+ 	 */
+ #define NR_FIX_BTMAPS		64
+ #define FIX_BTMAPS_NESTING	4
+-	FIX_BTMAP_END =
+-		__end_of_permanent_fixed_addresses + 512 -
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+ 			(__end_of_permanent_fixed_addresses & 511),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+ 	FIX_WP_TEST,
+@@ -114,19 +113,16 @@ enum fixed_addresses {
+ };
+ 
+ extern void __set_fixmap(enum fixed_addresses idx,
+-					maddr_t phys, pgprot_t flags);
++			 maddr_t phys, pgprot_t flags);
+ extern void reserve_top_address(unsigned long reserve);
+ 
+-#define set_fixmap(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys)				\
++	__set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+  * Some hardware wants to get fixmapped without caching.
+  */
+-#define set_fixmap_nocache(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+-
+-#define clear_fixmap(idx) \
+-		__set_fixmap(idx, 0, __pgprot(0))
++#define set_fixmap_nocache(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+ 
+ #define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+ 
+@@ -159,7 +155,7 @@ static __always_inline unsigned long fix
+ 	if (idx >= __end_of_fixed_addresses)
+ 		__this_fixmap_does_not_exist();
+ 
+-        return __fix_to_virt(idx);
++	return __fix_to_virt(idx);
+ }
+ 
+ static inline unsigned long virt_to_fix(const unsigned long vaddr)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:32.000000000 +0100
+@@ -8,8 +8,8 @@
+  * Copyright (C) 1998 Ingo Molnar
+  */
+ 
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_FIXMAP_64_H
++#define _ASM_FIXMAP_64_H
+ 
+ #include <linux/kernel.h>
+ #include <asm/apicdef.h>
+@@ -35,7 +35,8 @@
+ 
+ enum fixed_addresses {
+ 	VSYSCALL_LAST_PAGE,
+-	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
++	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
++			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ 	VSYSCALL_HPET,
+ 	FIX_DBGP_BASE,
+ 	FIX_EARLYCON_MEM_BASE,
+@@ -45,11 +46,12 @@ enum fixed_addresses {
+ #endif
+ #ifndef CONFIG_XEN
+ 	FIX_IO_APIC_BASE_0,
+-	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
++	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+ #endif
+ #ifdef CONFIG_EFI
+ 	FIX_EFI_IO_MAP_LAST_PAGE,
+-	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE+MAX_EFI_IO_PAGES-1,
++	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
++				  + MAX_EFI_IO_PAGES - 1,
+ #endif
+ #ifdef CONFIG_ACPI
+ 	FIX_ACPI_BEGIN,
+@@ -79,19 +81,16 @@ enum fixed_addresses {
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void __set_fixmap (enum fixed_addresses idx,
+-					unsigned long phys, pgprot_t flags);
++extern void __set_fixmap(enum fixed_addresses idx,
++			 unsigned long phys, pgprot_t flags);
+ 
+-#define set_fixmap(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL)
++#define set_fixmap(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+  * Some hardware wants to get fixmapped without caching.
+  */
+-#define set_fixmap_nocache(idx, phys) \
+-		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+-
+-#define clear_fixmap(idx) \
+-                __set_fixmap(idx, 0, __pgprot(0))
++#define set_fixmap_nocache(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+ 
+ #define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
+ #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:32.000000000 +0100
+@@ -8,7 +8,7 @@
+  *		      Gerhard.Wichert@pdb.siemens.de
+  *
+  *
+- * Redesigned the x86 32-bit VM architecture to deal with 
++ * Redesigned the x86 32-bit VM architecture to deal with
+  * up to 16 Terabyte physical memory. With current x86 CPUs
+  * we now support up to 64 Gigabytes physical RAM.
+  *
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,22 @@
++#ifndef _ASM_X86_IO_H
++#define _ASM_X86_IO_H
++
++#define ARCH_HAS_IOREMAP_WC
++
+ #ifdef CONFIG_X86_32
+ # include "io_32.h"
+ #else
+ # include "io_64.h"
+ #endif
++
++extern void *xlate_dev_mem_ptr(unsigned long phys);
++extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
++
++extern void map_devmem(unsigned long pfn, unsigned long len, pgprot_t);
++extern void unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t);
++
++extern int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
++				     unsigned long prot_val);
++extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
++
++#endif /* _ASM_X86_IO_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:32.000000000 +0100
+@@ -139,11 +139,11 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ #endif /* __ASSEMBLY__ */
+ 
+ #ifndef __ASSEMBLY__
+-#define raw_local_save_flags(flags) \
+-		do { (flags) = __raw_local_save_flags(); } while (0)
++#define raw_local_save_flags(flags)				\
++	do { (flags) = __raw_local_save_flags(); } while (0)
+ 
+-#define raw_local_irq_save(flags) \
+-		do { (flags) = __raw_local_irq_save(); } while (0)
++#define raw_local_irq_save(flags)				\
++	do { (flags) = __raw_local_irq_save(); } while (0)
+ 
+ static inline int raw_irqs_disabled_flags(unsigned long flags)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:32.000000000 +0100
+@@ -94,7 +94,7 @@ static inline void switch_mm(struct mm_s
+ 		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
+ 
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled 
++			/* We were in lazy tlb mode and leave_mm disabled
+ 			 * tlb flush IPI delivery. We must reload %cr3.
+ 			 */
+ 			load_cr3(next->pgd);
+@@ -107,10 +107,10 @@ static inline void switch_mm(struct mm_s
+ #define deactivate_mm(tsk, mm)			\
+ 	asm("movl %0,%%gs": :"r" (0));
+ 
+-#define activate_mm(prev, next)				\
+-	do {						\
+-		xen_activate_mm(prev, next);		\
+-		switch_mm((prev),(next),NULL);		\
+-	} while(0)
++#define activate_mm(prev, next)			\
++do {						\
++	xen_activate_mm(prev, next);		\
++	switch_mm((prev), (next), NULL);	\
++} while (0)
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:32.000000000 +0100
+@@ -21,7 +21,7 @@ void destroy_context(struct mm_struct *m
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+ #if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-	if (read_pda(mmu_state) == TLBSTATE_OK) 
++	if (read_pda(mmu_state) == TLBSTATE_OK)
+ 		write_pda(mmu_state, TLBSTATE_LAZY);
+ #endif
+ }
+@@ -62,7 +62,7 @@ extern void mm_pin(struct mm_struct *mm)
+ extern void mm_unpin(struct mm_struct *mm);
+ void mm_pin_all(void);
+ 
+-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ 			     struct task_struct *tsk)
+ {
+ 	unsigned cpu = smp_processor_id();
+@@ -106,7 +106,7 @@ static inline void switch_mm(struct mm_s
+ 		if (read_pda(active_mm) != next)
+ 			BUG();
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+-			/* We were in lazy tlb mode and leave_mm disabled 
++			/* We were in lazy tlb mode and leave_mm disabled
+ 			 * tlb flush IPI delivery. We must reload CR3
+ 			 * to make sure to use no freed page tables.
+ 			 */
+@@ -118,10 +118,11 @@ static inline void switch_mm(struct mm_s
+ #endif
+ }
+ 
+-#define deactivate_mm(tsk,mm)	do { \
+-	load_gs_index(0); \
+-	asm volatile("movl %0,%%fs"::"r"(0));  \
+-} while(0)
++#define deactivate_mm(tsk, mm)			\
++do {						\
++	load_gs_index(0);			\
++	asm volatile("movl %0,%%fs"::"r"(0));	\
++} while (0)
+ 
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:32.000000000 +0100
+@@ -8,14 +8,13 @@
+ #include <asm/scatterlist.h>
+ #include <asm/io.h>
+ 
+-
+ #ifdef __KERNEL__
+ 
+ struct pci_sysdata {
+ 	int		domain;		/* PCI domain */
+ 	int		node;		/* NUMA node */
+ #ifdef CONFIG_X86_64
+-	void*		iommu;		/* IOMMU private data */
++	void		*iommu;		/* IOMMU private data */
+ #endif
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+ 	struct pcifront_device *pdev;
+@@ -23,6 +22,8 @@ struct pci_sysdata {
+ };
+ 
+ /* scan a bus after allocating a pci_sysdata for it */
++extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
++					    int node);
+ extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
+ 
+ static inline int pci_domain_nr(struct pci_bus *bus)
+@@ -36,6 +37,7 @@ static inline int pci_proc_domain(struct
+ 	return pci_domain_nr(bus);
+ }
+ 
++extern void pci_iommu_alloc(void);
+ 
+ /* Can be used to override the logic in pci_scan_bus for skipping
+    already-configured bus numbers - to be used for buggy BIOSes
+@@ -57,7 +59,7 @@ extern unsigned long pci_mem_start;
+ #define PCIBIOS_MIN_CARDBUS_IO	0x4000
+ 
+ void pcibios_config_init(void);
+-struct pci_bus * pcibios_scan_root(int bus);
++struct pci_bus *pcibios_scan_root(int bus);
+ 
+ void pcibios_set_master(struct pci_dev *dev);
+ void pcibios_penalize_isa_irq(int irq, int active);
+@@ -67,7 +69,8 @@ int pcibios_set_irq_routing(struct pci_d
+ 
+ #define HAVE_PCI_MMAP
+ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+-			       enum pci_mmap_state mmap_state, int write_combine);
++			       enum pci_mmap_state mmap_state,
++			       int write_combine);
+ 
+ 
+ #ifdef CONFIG_PCI
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,149 @@
+-#ifdef CONFIG_X86_32
+-# include "pgalloc_32.h"
+-#else
+-# include "pgalloc_64.h"
++#ifndef _ASM_X86_PGALLOC_H
++#define _ASM_X86_PGALLOC_H
++
++#include <linux/threads.h>
++#include <linux/mm.h>		/* for struct page */
++#include <linux/pagemap.h>
++
++#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
++
++static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
++					    unsigned long start, unsigned long count) {}
++static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn)	{}
++static inline void paravirt_release_pte(unsigned long pfn) {}
++static inline void paravirt_release_pmd(unsigned long pfn) {}
++static inline void paravirt_release_pud(unsigned long pfn) {}
++
++#ifdef CONFIG_X86_64
++void early_make_page_readonly(void *va, unsigned int feature);
++pmd_t *early_get_pmd(unsigned long va);
++#define make_lowmem_page_readonly make_page_readonly
++#define make_lowmem_page_writable make_page_writable
+ #endif
++
++/*
++ * Allocate and free page tables.
++ */
++extern pgd_t *pgd_alloc(struct mm_struct *);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
++
++extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
++extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
++
++/* Should really implement gc for free page table pages. This could be
++   done with a reference count in struct page. */
++
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
++{
++	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
++	make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
++	free_page((unsigned long)pte);
++}
++
++extern void __pte_free(pgtable_t);
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
++{
++	__pte_free(pte);
++}
++
++extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
++
++static inline void pmd_populate_kernel(struct mm_struct *mm,
++				       pmd_t *pmd, pte_t *pte)
++{
++	paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
++	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
++}
++
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
++				struct page *pte)
++{
++	unsigned long pfn = page_to_pfn(pte);
++
++	paravirt_alloc_pte(mm, pfn);
++	if (PagePinned(virt_to_page(mm->pgd))) {
++		if (!PageHighMem(pte))
++			BUG_ON(HYPERVISOR_update_va_mapping(
++			  (unsigned long)__va(pfn << PAGE_SHIFT),
++			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
++#ifndef CONFIG_X86_64
++		else if (!TestSetPagePinned(pte))
++			kmap_flush_unused();
++#endif
++		set_pmd(pmd, __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
++	} else
++		*pmd = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
++}
++
++#define pmd_pgtable(pmd) pmd_page(pmd)
++
++#if PAGETABLE_LEVELS > 2
++extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr);
++extern void __pmd_free(pgtable_t);
++
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
++{
++	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
++	__pmd_free(virt_to_page(pmd));
++}
++
++extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++
++#ifdef CONFIG_X86_PAE
++extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
++#else	/* !CONFIG_X86_PAE */
++static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
++{
++	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)pmd,
++			       pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT,
++				       PAGE_KERNEL_RO), 0));
++		set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
++	} else
++		*pud =  __pud(_PAGE_TABLE | __pa(pmd));
++}
++#endif	/* CONFIG_X86_PAE */
++
++#if PAGETABLE_LEVELS > 3
++#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
++
++/*
++ * We need to use the batch mode here, but pgd_pupulate() won't be
++ * be called frequently.
++ */
++static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
++{
++	paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)pud,
++			       pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT,
++				       PAGE_KERNEL_RO), 0));
++		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
++		set_pgd(__user_pgd(pgd), __pgd(_PAGE_TABLE | __pa(pud)));
++	} else {
++		*(pgd) =  __pgd(_PAGE_TABLE | __pa(pud));
++		*__user_pgd(pgd) = *(pgd);
++	}
++}
++
++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	return (pud_t *)pmd_alloc_one(mm, addr);
++}
++
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
++{
++	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
++	__pmd_free(virt_to_page(pud));
++}
++
++extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
++#endif	/* PAGETABLE_LEVELS > 3 */
++#endif	/* PAGETABLE_LEVELS > 2 */
++
++#endif	/* _ASM_X86_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,111 +0,0 @@
+-#ifndef _I386_PGALLOC_H
+-#define _I386_PGALLOC_H
+-
+-#include <linux/threads.h>
+-#include <linux/mm.h>		/* for struct page */
+-#include <linux/pagemap.h>
+-#include <asm/tlb.h>
+-#include <asm-generic/tlb.h>
+-#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+-
+-#define paravirt_alloc_pt(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+-#define paravirt_release_pt(pfn) do { } while (0)
+-#define paravirt_release_pd(pfn) do { } while (0)
+-
+-static inline void pmd_populate_kernel(struct mm_struct *mm,
+-				       pmd_t *pmd, pte_t *pte)
+-{
+-	paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);
+-	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+-}
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+-	unsigned long pfn = page_to_pfn(pte);
+-
+-	paravirt_alloc_pt(mm, pfn);
+-	if (PagePinned(virt_to_page(mm->pgd))) {
+-		if (!PageHighMem(pte))
+-			BUG_ON(HYPERVISOR_update_va_mapping(
+-			  (unsigned long)__va(pfn << PAGE_SHIFT),
+-			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
+-		else if (!test_and_set_bit(PG_pinned, &pte->flags))
+-			kmap_flush_unused();
+-		set_pmd(pmd, __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
+-	} else
+-		*pmd = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
+-}
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-/*
+- * Allocate and free page tables.
+- */
+-extern void pgd_test_and_unpin(pgd_t *);
+-extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+-
+-extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+-extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+-	make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
+-	free_page((unsigned long)pte);
+-}
+-
+-extern void __pte_free(pgtable_t);
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+-	__pte_free(pte);
+-}
+-
+-
+-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+-
+-#ifdef CONFIG_X86_PAE
+-/*
+- * In the PAE case we free the pmds as part of the pgd.
+- */
+-extern pmd_t *pmd_alloc_one(struct mm_struct *, unsigned long);
+-
+-extern void __pmd_free(pgtable_t);
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+-	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+-	__pmd_free(virt_to_page(pmd));
+-}
+-
+-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+-
+-static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+-{
+-	struct page *page = virt_to_page(pmd);
+-	unsigned long pfn = page_to_pfn(page);
+-
+-	paravirt_alloc_pd(mm, pfn);
+-
+-	/* Note: almost everything apart from _PAGE_PRESENT is
+-	   reserved at the pmd (PDPT) level. */
+-	if (PagePinned(virt_to_page(mm->pgd))) {
+-		BUG_ON(PageHighMem(page));
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			  (unsigned long)__va(pfn << PAGE_SHIFT),
+-			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
+-		set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
+-	} else
+-		*pudp = __pud(__pa(pmd) | _PAGE_PRESENT);
+-
+-	/*
+-	 * According to Intel App note "TLBs, Paging-Structure Caches,
+-	 * and Their Invalidation", April 2007, document 317080-001,
+-	 * section 8.1: in PAE mode we explicitly have to flush the
+-	 * TLB via cr3 if the top-level pgd is changed...
+-	 */
+-	if (mm == current->active_mm)
+-		xen_tlb_flush();
+-}
+-#endif	/* CONFIG_X86_PAE */
+-
+-#endif /* _I386_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,179 +0,0 @@
+-#ifndef _X86_64_PGALLOC_H
+-#define _X86_64_PGALLOC_H
+-
+-#include <asm/pda.h>
+-#include <linux/threads.h>
+-#include <linux/mm.h>
+-#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+-
+-pmd_t *early_get_pmd(unsigned long va);
+-void early_make_page_readonly(void *va, unsigned int feature);
+-
+-#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+-
+-#define pmd_populate_kernel(mm, pmd, pte) \
+-		set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
+-
+-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+-{
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)pmd,
+-			       pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, 
+-				       PAGE_KERNEL_RO), 0));
+-		set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
+-	} else {
+-		*(pud) =  __pud(_PAGE_TABLE | __pa(pmd));
+-	}
+-}
+-
+-/*
+- * We need to use the batch mode here, but pgd_pupulate() won't be
+- * be called frequently.
+- */
+-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+-{
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)pud,
+-			       pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, 
+-				       PAGE_KERNEL_RO), 0));
+-		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
+-		set_pgd(__user_pgd(pgd), __pgd(_PAGE_TABLE | __pa(pud)));
+-	} else {
+-		*(pgd) =  __pgd(_PAGE_TABLE | __pa(pud));
+-		*(__user_pgd(pgd)) = *(pgd);
+-	}
+-}
+-
+-#define pmd_pgtable(pmd) pmd_page(pmd)
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)__va(page_to_pfn(pte) << PAGE_SHIFT),
+-			       pfn_pte(page_to_pfn(pte), PAGE_KERNEL_RO), 0));
+-		set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
+-	} else {
+-		*(pmd) = __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT));
+-	}
+-}
+-
+-extern void __pmd_free(pgtable_t);
+-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+-{
+-	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+-	__pmd_free(virt_to_page(pmd));
+-}
+-
+-extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr);
+-
+-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+-{
+-	return (pud_t *)pmd_alloc_one(mm, addr);
+-}
+-
+-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+-{
+-	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+-	__pmd_free(virt_to_page(pud));
+-}
+-
+-static inline void pgd_list_add(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_add(&page->lru, &pgd_list);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-static inline void pgd_list_del(pgd_t *pgd)
+-{
+-	struct page *page = virt_to_page(pgd);
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_del(&page->lru);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-extern void pgd_test_and_unpin(pgd_t *);
+-
+-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+-{
+-	/*
+-	 * We allocate two contiguous pages for kernel and user.
+-	 */
+-	unsigned boundary;
+-	pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 1);
+-	if (!pgd)
+-		return NULL;
+-	pgd_list_add(pgd);
+-	pgd_test_and_unpin(pgd);
+-	/*
+-	 * Copy kernel pointers in from init.
+-	 * Could keep a freelist or slab cache of those because the kernel
+-	 * part never changes.
+-	 */
+-	boundary = pgd_index(__PAGE_OFFSET);
+-	memset(pgd, 0, boundary * sizeof(pgd_t));
+-	memcpy(pgd + boundary,
+-	       init_level4_pgt + boundary,
+-	       (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
+-
+-	memset(__user_pgd(pgd), 0, PAGE_SIZE); /* clean up user pgd */
+-	/*
+-	 * Set level3_user_pgt for vsyscall area
+-	 */
+-	__user_pgd(pgd)[pgd_index(VSYSCALL_START)] =
+-		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
+-	return pgd;
+-}
+-
+-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	pgd_test_and_unpin(pgd);
+-	pgd_list_del(pgd);
+-	free_pages((unsigned long)pgd, 1);
+-}
+-
+-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+-{
+-	pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+-	if (pte)
+-		make_page_readonly(pte, XENFEAT_writable_page_tables);
+-
+-	return pte;
+-}
+-
+-extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+-
+-/* Should really implement gc for free page table pages. This could be
+-   done with a reference count in struct page. */
+-
+-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+-{
+-	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+-	make_page_writable(pte, XENFEAT_writable_page_tables);
+-	free_page((unsigned long)pte); 
+-}
+-
+-extern void __pte_free(pgtable_t);
+-static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+-{
+-	__pte_free(pte);
+-}
+-
+-#define __pte_free_tlb(tlb,pte)				\
+-do {							\
+-	pgtable_page_dtor((pte));				\
+-	tlb_remove_page((tlb), (pte));			\
+-} while (0)
+-
+-#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+-#define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+-
+-#endif /* _X86_64_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,17 +1,15 @@
+ #ifndef _ASM_X86_PGTABLE_H
+ #define _ASM_X86_PGTABLE_H
+ 
+-#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
+ #define FIRST_USER_ADDRESS	0
+ 
+-#define _PAGE_BIT_PRESENT	0
+-#define _PAGE_BIT_RW		1
+-#define _PAGE_BIT_USER		2
+-#define _PAGE_BIT_PWT		3
+-#define _PAGE_BIT_PCD		4
+-#define _PAGE_BIT_ACCESSED	5
+-#define _PAGE_BIT_DIRTY		6
+-#define _PAGE_BIT_FILE		6
++#define _PAGE_BIT_PRESENT	0	/* is present */
++#define _PAGE_BIT_RW		1	/* writeable */
++#define _PAGE_BIT_USER		2	/* userspace addressable */
++#define _PAGE_BIT_PWT		3	/* page write through */
++#define _PAGE_BIT_PCD		4	/* page cache disabled */
++#define _PAGE_BIT_ACCESSED	5	/* was accessed (raised by CPU) */
++#define _PAGE_BIT_DIRTY		6	/* was written to (raised by CPU) */
+ #define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+ #define _PAGE_BIT_PAT		7	/* on 4KB pages */
+ #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+@@ -22,6 +20,14 @@
+ #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
+ #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+ 
++/* If _PAGE_BIT_PRESENT is clear, we use these: */
++
++/* set: nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
++
++/* if the user mapped it with PROT_NONE; pte_present gives true */
++#define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
++
+ /*
+  * Note: we use _AC(1, L) instead of _AC(1, UL) so that we get a
+  * sign-extended value on 32-bit with all 1's in the upper word,
+@@ -48,10 +54,8 @@
+ #define _PAGE_NX	0
+ #endif
+ 
+-/* If _PAGE_PRESENT is clear, we use these: */
+-#define _PAGE_FILE	_PAGE_DIRTY	/* nonlinear file mapping, saved PTE; unset:swap */
+-#define _PAGE_PROTNONE	_PAGE_PSE	/* if the user mapped it with PROT_NONE;
+-					   pte_present gives true */
++#define _PAGE_FILE	(_AC(1, L)<<_PAGE_BIT_FILE)
++#define _PAGE_PROTNONE	(_AC(1, L)<<_PAGE_BIT_PROTNONE)
+ 
+ #ifndef __ASSEMBLY__
+ #if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
+@@ -61,20 +65,42 @@ extern unsigned int __kernel_page_user;
+ #endif
+ #endif
+ 
+-#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_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)
++
++/* Set of bits not changed in pte_modify */
++#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_CACHE_MASK | _PAGE_IO |	\
++			 _PAGE_ACCESSED | _PAGE_DIRTY)
+ 
+-#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_IO)
++/*
++ * PAT settings are part of the hypervisor interface, which sets the
++ * MSR to 0x050100070406 (i.e. WB, WT, UC-, UC, WC, WP [, UC, UC]).
++ */
++#define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT | _PAGE_PAT)
++#define _PAGE_CACHE_WB		(0)
++#define _PAGE_CACHE_WT		(_PAGE_PWT)
++#define _PAGE_CACHE_WC		(_PAGE_PAT)
++#define _PAGE_CACHE_WP		(_PAGE_PAT | _PAGE_PWT)
++#define _PAGE_CACHE_UC_MINUS	(_PAGE_PCD)
++#define _PAGE_CACHE_UC		(_PAGE_PCD | _PAGE_PWT)
+ 
+ #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
++				 _PAGE_ACCESSED | _PAGE_NX)
+ 
+-#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW |	\
++					 _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
+ #define PAGE_COPY		PAGE_COPY_NOEXEC
+-#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
++					 _PAGE_ACCESSED)
+ 
+ #ifdef CONFIG_X86_32
+ #define _PAGE_KERNEL_EXEC \
+@@ -93,6 +119,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KE
+ #define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+ #define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+ #define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
+ #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
+ #define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+@@ -109,6 +136,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KE
+ #define PAGE_KERNEL_RO			MAKE_GLOBAL(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
+ #define PAGE_KERNEL_RX			MAKE_GLOBAL(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_WC			MAKE_GLOBAL(__PAGE_KERNEL_WC)
+ #define PAGE_KERNEL_NOCACHE		MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+ #define PAGE_KERNEL_UC_MINUS		MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
+ #define PAGE_KERNEL_EXEC_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
+@@ -142,7 +170,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KE
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+  */
+-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ 
+ extern spinlock_t pgd_lock;
+@@ -152,30 +180,111 @@ extern struct list_head pgd_list;
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+  */
+-static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
+-static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
+-static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
+-static inline int pte_file(pte_t pte)		{ return __pte_val(pte) & _PAGE_FILE; }
+-static inline int pte_huge(pte_t pte)		{ return __pte_val(pte) & _PAGE_PSE; }
+-static inline int pte_global(pte_t pte) 	{ return 0; }
+-static inline int pte_exec(pte_t pte)		{ return !(__pte_val(pte) & _PAGE_NX); }
+-
+-static inline int pmd_large(pmd_t pte) {
+-	return (__pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+-		(_PAGE_PSE|_PAGE_PRESENT);
+-}
+-
+-static inline pte_t pte_mkclean(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); }
+-static inline pte_t pte_mkold(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); }
+-static inline pte_t pte_wrprotect(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_RW); }
+-static inline pte_t pte_mkexec(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_NX); }
+-static inline pte_t pte_mkdirty(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_DIRTY); }
+-static inline pte_t pte_mkyoung(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_ACCESSED); }
+-static inline pte_t pte_mkwrite(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_RW); }
+-static inline pte_t pte_mkhuge(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_PSE); }
+-static inline pte_t pte_clrhuge(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_PSE); }
+-static inline pte_t pte_mkglobal(pte_t pte)	{ return pte; }
+-static inline pte_t pte_clrglobal(pte_t pte)	{ return pte; }
++static inline int pte_dirty(pte_t pte)
++{
++	return __pte_val(pte) & _PAGE_DIRTY;
++}
++
++static inline int pte_young(pte_t pte)
++{
++	return __pte_val(pte) & _PAGE_ACCESSED;
++}
++
++static inline int pte_write(pte_t pte)
++{
++	return __pte_val(pte) & _PAGE_RW;
++}
++
++static inline int pte_file(pte_t pte)
++{
++	return __pte_val(pte) & _PAGE_FILE;
++}
++
++static inline int pte_huge(pte_t pte)
++{
++	return __pte_val(pte) & _PAGE_PSE;
++}
++
++static inline int pte_global(pte_t pte)
++{
++	return 0;
++}
++
++static inline int pte_exec(pte_t pte)
++{
++	return !(__pte_val(pte) & _PAGE_NX);
++}
++
++static inline int pte_special(pte_t pte)
++{
++	return 0;
++}
++
++static inline int pmd_large(pmd_t pte)
++{
++	return (__pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++		(_PAGE_PSE | _PAGE_PRESENT);
++}
++
++static inline pte_t pte_mkclean(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkold(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED);
++}
++
++static inline pte_t pte_wrprotect(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_RW);
++}
++
++static inline pte_t pte_mkexec(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_NX);
++}
++
++static inline pte_t pte_mkdirty(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) | _PAGE_DIRTY);
++}
++
++static inline pte_t pte_mkyoung(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) | _PAGE_ACCESSED);
++}
++
++static inline pte_t pte_mkwrite(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) | _PAGE_RW);
++}
++
++static inline pte_t pte_mkhuge(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) | _PAGE_PSE);
++}
++
++static inline pte_t pte_clrhuge(pte_t pte)
++{
++	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_PSE);
++}
++
++static inline pte_t pte_mkglobal(pte_t pte)
++{
++	return pte;
++}
++
++static inline pte_t pte_clrglobal(pte_t pte)
++{
++	return pte;
++}
++
++static inline pte_t pte_mkspecial(pte_t pte)
++{
++	return pte;
++}
+ 
+ extern pteval_t __supported_pte_mask;
+ 
+@@ -202,15 +311,33 @@ static inline pte_t pte_modify(pte_t pte
+ 	pteval_t val = pte_val(pte);
+ 
+ 	val &= _PAGE_CHG_MASK;
+-	val |= pgprot_val(newprot) & __supported_pte_mask;
++	val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask;
+ 
+ 	return __pte(val);
+ }
+ 
+-#define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX))
++/* mprotect needs to preserve PAT bits when updating vm_page_prot */
++#define pgprot_modify pgprot_modify
++static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
++{
++	pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK;
++	pgprotval_t addbits = pgprot_val(newprot);
++	return __pgprot(preservebits | addbits);
++}
++
++#define pte_pgprot(x) __pgprot(__pte_val(x) & ~PTE_MASK)
+ 
+ #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
+ 
++#ifndef __ASSEMBLY__
++#define __HAVE_PHYS_MEM_ACCESS_PROT
++struct file;
++pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t vma_prot);
++int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
++                              unsigned long size, pgprot_t *vma_prot);
++#endif
++
+ #define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
+ #define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
+ 
+@@ -246,6 +373,9 @@ static inline pte_t pte_modify(pte_t pte
+ # include "pgtable_64.h"
+ #endif
+ 
++#define KERNEL_PGD_BOUNDARY	pgd_index(PAGE_OFFSET)
++#define KERNEL_PGD_PTRS		(PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
++
+ #ifndef __ASSEMBLY__
+ 
+ enum {
+@@ -312,46 +442,17 @@ static inline void xen_pte_clear(struct 
+  * bit at the same time.
+  */
+ #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-({									\
+-	int __changed = !pte_same(*(ptep), entry);			\
+-	if (__changed && (dirty)) {					\
+-		if ( likely((vma)->vm_mm == current->mm) ) {		\
+-			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
+-				entry,					\
+-				uvm_multi((vma)->vm_mm->cpu_vm_mask) |	\
+-					UVMF_INVLPG));			\
+-		} else {						\
+-			xen_l1_entry_update(ptep, entry);		\
+-			flush_tlb_page(vma, address);			\
+-		}							\
+-	}								\
+-	__changed;							\
+-})
++extern int ptep_set_access_flags(struct vm_area_struct *vma,
++				 unsigned long address, pte_t *ptep,
++				 pte_t entry, int dirty);
+ 
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define ptep_test_and_clear_young(vma, addr, ptep) ({			\
+-	int __ret = 0;							\
+-	if (pte_young(*(ptep)))						\
+-		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
+-					   &(ptep)->pte);		\
+-	if (__ret)							\
+-		pte_update((vma)->vm_mm, addr, ptep);			\
+-	__ret;								\
+-})
++extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
++				     unsigned long addr, pte_t *ptep);
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+-#define ptep_clear_flush_young(vma, address, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __young = pte_young(__pte);					\
+-	__pte = pte_mkold(__pte);					\
+-	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
+-		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+-	else if (__young)						\
+-		(ptep)->pte_low = __pte.pte_low;			\
+-	__young;							\
+-})
++extern int ptep_clear_flush_young(struct vm_area_struct *vma,
++				  unsigned long address, pte_t *ptep);
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+ #define ptep_clear_flush(vma, addr, ptep)			\
+@@ -370,7 +471,8 @@ static inline void xen_pte_clear(struct 
+ })
+ 
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
++				       pte_t *ptep)
+ {
+ 	pte_t pte = *ptep;
+ 	if (!pte_none(pte)
+@@ -398,13 +500,29 @@ static inline pte_t ptep_get_and_clear(s
+ pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *, unsigned long, pte_t *, int);
+ 
+ #define __HAVE_ARCH_PTEP_SET_WRPROTECT
+-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void ptep_set_wrprotect(struct mm_struct *mm,
++				      unsigned long addr, pte_t *ptep)
+ {
+ 	pte_t pte = *ptep;
+ 	if (pte_write(pte))
+ 		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
+ }
+ 
++/*
++ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
++ *
++ *  dst - pointer to pgd range anwhere on a pgd page
++ *  src - ""
++ *  count - the number of pgds to copy.
++ *
++ * dst and src can be on the same page, but the range must not overlap,
++ * and must not cross a page boundary.
++ */
++static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
++{
++       memcpy(dst, src, count * sizeof(pgd_t));
++}
++
+ #define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
+ 	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:32.000000000 +0100
+@@ -8,25 +8,28 @@
+  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+  */
+ 
+-#define pte_ERROR(e) \
+-	printk("%s:%d: bad pte %p(%016Lx pfn %08lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pte_val(e), pte_pfn(e))
+-#define pmd_ERROR(e) \
+-	printk("%s:%d: bad pmd %p(%016Lx pfn %08Lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pmd_val(e), (pmd_val(e) & PTE_MASK) >> PAGE_SHIFT)
+-#define pgd_ERROR(e) \
+-	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pgd_val(e), (pgd_val(e) & PTE_MASK) >> PAGE_SHIFT)
+-
++#define pte_ERROR(e)							\
++	printk("%s:%d: bad pte %p(%016Lx pfn %08lx).\n",		\
++	        __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
++#define pmd_ERROR(e)							\
++	printk("%s:%d: bad pmd %p(%016Lx pfn %08Lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pmd_val(e),			\
++	       (pmd_val(e) & PTE_MASK) >> PAGE_SHIFT)
++#define pgd_ERROR(e)							\
++	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
++	       (pgd_val(e) & PTE_MASK) >> PAGE_SHIFT)
+ 
+ static inline int pud_none(pud_t pud)
+ {
+ 	return __pud_val(pud) == 0;
++
+ }
+ static inline int pud_bad(pud_t pud)
+ {
+ 	return (__pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+ }
++
+ static inline int pud_present(pud_t pud)
+ {
+ 	return __pud_val(pud) & _PAGE_PRESENT;
+@@ -48,12 +51,14 @@ static inline void xen_set_pte(pte_t *pt
+ 
+ static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
+ {
+-	set_64bit((unsigned long long *)(ptep),__pte_val(pte));
++	set_64bit((unsigned long long *)(ptep), __pte_val(pte));
+ }
++
+ static inline void xen_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
+ 	xen_l2_entry_update(pmdp, pmd);
+ }
++
+ static inline void xen_set_pud(pud_t *pudp, pud_t pud)
+ {
+ 	xen_l3_entry_update(pudp, pud);
+@@ -92,20 +97,19 @@ static inline void pud_clear(pud_t *pudp
+ 	 * current pgd to avoid unnecessary TLB flushes.
+ 	 */
+ 	pgd = read_cr3();
+-	if (__pa(pudp) >= pgd && __pa(pudp) < (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
++	if (__pa(pudp) >= pgd && __pa(pudp) <
++	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
+ 		xen_tlb_flush();
+ }
+ 
+-#define pud_page(pud) \
+-((struct page *) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_MASK))
+ 
+-#define pud_page_vaddr(pud) \
+-((unsigned long) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_MASK))
+ 
+ 
+ /* Find an entry in the second-level page table.. */
+-#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+-			pmd_index(address))
++#define pmd_offset(pud, address) ((pmd_t *)pud_page(*(pud)) +	\
++				  pmd_index(address))
+ 
+ #ifdef CONFIG_SMP
+ static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res)
+@@ -150,7 +154,8 @@ static inline int pte_none(pte_t pte)
+  * put the 32 bits of offset into the high part.
+  */
+ #define pte_to_pgoff(pte) ((pte).pte_high)
+-#define pgoff_to_pte(off) ((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
++#define pgoff_to_pte(off)						\
++	((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
+ #define PTE_FILE_MAX_BITS       32
+ 
+ /* Encode and de-code a swap entry */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:32.000000000 +0100
+@@ -38,16 +38,13 @@ void paging_init(void);
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level-defs.h>
+ # define PMD_SIZE	(1UL << PMD_SHIFT)
+-# define PMD_MASK	(~(PMD_SIZE-1))
++# define PMD_MASK	(~(PMD_SIZE - 1))
+ #else
+ # include <asm/pgtable-2level-defs.h>
+ #endif
+ 
+ #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+-
+-#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
++#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+ /* Just any arbitrary offset to the start of the vmalloc VM area: the
+  * current 8MB value just means that there will be a 8MB "hole" after the
+@@ -56,21 +53,22 @@ void paging_init(void);
+  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+  * area for the same reason. ;)
+  */
+-#define VMALLOC_OFFSET	(8*1024*1024)
+-#define VMALLOC_START	(((unsigned long) high_memory + \
+-			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_OFFSET	(8 * 1024 * 1024)
++#define VMALLOC_START	(((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \
++			 & ~(VMALLOC_OFFSET - 1))
+ #ifdef CONFIG_X86_PAE
+ #define LAST_PKMAP 512
+ #else
+ #define LAST_PKMAP 1024
+ #endif
+ 
+-#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
++#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1))	\
++		    & PMD_MASK)
+ 
+ #ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
++# define VMALLOC_END	(PKMAP_BASE - 2 * PAGE_SIZE)
+ #else
+-# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
++# define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
+ #endif
+ 
+ /*
+@@ -91,10 +89,10 @@ extern unsigned long pg0[];
+ /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+    can temporarily clear it. */
+ #define pmd_present(x)	(__pmd_val(x))
+-#define pmd_bad(x)	((__pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
++#define pmd_bad(x)	((__pmd_val(x) & (~PTE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
+ #else
+ #define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+-#define pmd_bad(x)	((__pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#define pmd_bad(x)	((__pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+ #endif
+ 
+ 
+@@ -107,32 +105,18 @@ extern unsigned long pg0[];
+ #endif
+ 
+ /*
+- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+- *
+- *  dst - pointer to pgd range anwhere on a pgd page
+- *  src - ""
+- *  count - the number of pgds to copy.
+- *
+- * dst and src can be on the same page, but the range must not overlap,
+- * and must not cross a page boundary.
++ * Macro to mark a page protection value as "uncacheable".
++ * On processors which do not support it, this is a no-op.
+  */
+-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+-{
+-       memcpy(dst, src, count * sizeof(pgd_t));
+-}
+-
+-/*
+- * Macro to mark a page protection value as "uncacheable".  On processors which do not support
+- * it, this is a no-op.
+- */
+-#define pgprot_noncached(prot)	((boot_cpu_data.x86 > 3)					  \
+-				 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) : (prot))
++#define pgprot_noncached(prot)					\
++	((boot_cpu_data.x86 > 3)				\
++	 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))	\
++	 : (prot))
+ 
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+  */
+-
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+ 
+ /*
+@@ -141,20 +125,20 @@ static inline void clone_pgd_range(pgd_t
+  * this macro returns the index of the entry in the pgd page which would
+  * control the given virtual address
+  */
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_index_k(addr) pgd_index(addr)
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_index_k(addr) pgd_index((addr))
+ 
+ /*
+  * pgd_offset() returns a (pgd_t *)
+  * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+  */
+-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
+ 
+ /*
+  * a shortcut which implies the use of the kernel's pgd, instead
+  * of a process's
+  */
+-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
++#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
+ 
+ static inline int pud_large(pud_t pud) { return 0; }
+ 
+@@ -164,8 +148,8 @@ static inline int pud_large(pud_t pud) {
+  * this macro returns the index of the entry in the pmd page which would
+  * control the given virtual address
+  */
+-#define pmd_index(address) \
+-		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
++#define pmd_index(address)				\
++	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+ 
+ /*
+  * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+@@ -173,33 +157,36 @@ static inline int pud_large(pud_t pud) {
+  * this macro returns the index of the entry in the pte page which would
+  * control the given virtual address
+  */
+-#define pte_index(address) \
+-		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address) \
+-	((pte_t *) pmd_page_vaddr(*(dir)) +  pte_index(address))
++#define pte_index(address)					\
++	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address)				\
++	((pte_t *)pmd_page_vaddr(*(dir)) +  pte_index((address)))
+ 
+-#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++#define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+ 
+-#define pmd_page_vaddr(pmd) \
+-		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++#define pmd_page_vaddr(pmd)					\
++	((unsigned long)__va(pmd_val((pmd)) & PTE_MASK))
+ 
+ #if defined(CONFIG_HIGHPTE)
+-#define pte_offset_map(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
+-#else
+-#define pte_offset_map(dir, address) \
+-	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
++#define pte_offset_map(dir, address)					\
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) +		\
++	 pte_index((address)))
++#define pte_offset_map_nested(dir, address)				\
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
++	 pte_index((address)))
++#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
++#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
++#else
++#define pte_offset_map(dir, address)					\
++	((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
++#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
+ #define pte_unmap(pte) do { } while (0)
+ #define pte_unmap_nested(pte) do { } while (0)
+ #endif
+ 
+ /* Clear a kernel PTE and flush it from the TLB */
+-#define kpte_clear_flush(ptep, vaddr) do { \
++#define kpte_clear_flush(ptep, vaddr)					\
++do {									\
+ 	if (HYPERVISOR_update_va_mapping(vaddr, __pte(0), UVMF_INVLPG)) \
+ 		BUG(); \
+ } while (0)
+@@ -208,7 +195,7 @@ static inline int pud_large(pud_t pud) {
+  * The i386 doesn't have any external MMU info: the kernel page
+  * tables contain all the necessary information.
+  */
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+ 
+ void make_lowmem_page_readonly(void *va, unsigned int feature);
+ void make_lowmem_page_writable(void *va, unsigned int feature);
+@@ -225,7 +212,7 @@ void make_lowmem_page_writable(void *va,
+ #define kern_addr_valid(kaddr)	(0)
+ #endif
+ 
+-#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+-direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
++#define io_remap_pfn_range(vma, from, pfn, size, prot)			\
++	direct_remap_pfn_range(vma, from, pfn, size, prot, DOMID_IO)
+ 
+ #endif /* _I386_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:32.000000000 +0100
+@@ -31,7 +31,7 @@ extern void paging_init(void);
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+-#define SHARED_KERNEL_PMD	1
++#define SHARED_KERNEL_PMD	0
+ 
+ /*
+  * PGDIR_SHIFT determines what a top-level page table entry can map
+@@ -59,18 +59,20 @@ extern void paging_init(void);
+ 
+ #ifndef __ASSEMBLY__
+ 
+-#define pte_ERROR(e) \
+-	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pte_val(e), pte_pfn(e))
+-#define pmd_ERROR(e) \
+-	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pmd_val(e), pmd_pfn(e))
+-#define pud_ERROR(e) \
+-	printk("%s:%d: bad pud %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pud_val(e), (pud_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+-#define pgd_ERROR(e) \
+-	printk("%s:%d: bad pgd %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
+-	       &(e), __pgd_val(e), (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pte_ERROR(e)							\
++	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
++#define pmd_ERROR(e)							\
++	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pmd_val(e), pmd_pfn(e))
++#define pud_ERROR(e)							\
++	printk("%s:%d: bad pud %p(%016lx pfn %010lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pud_val(e),			\
++	       (pud_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pgd_ERROR(e)							\
++	printk("%s:%d: bad pgd %p(%016lx pfn %010lx).\n",		\
++	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
++	       (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+ #define pgd_none(x)	(!__pgd_val(x))
+ #define pud_none(x)	(!__pud_val(x))
+@@ -125,7 +127,7 @@ static inline void xen_set_pgd(pgd_t *pg
+ 	xen_l4_entry_update(pgdp, pgd);
+ }
+ 
+-static inline void xen_pgd_clear(pgd_t * pgd)
++static inline void xen_pgd_clear(pgd_t *pgd)
+ {
+ 	xen_set_pgd(pgd, xen_make_pgd(0));
+ 	xen_set_pgd(__user_pgd(pgd), xen_make_pgd(0));
+@@ -135,43 +137,43 @@ static inline void xen_pgd_clear(pgd_t *
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+-#define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
+-#define PMD_MASK	(~(PMD_SIZE-1))
+-#define PUD_SIZE	(_AC(1,UL) << PUD_SHIFT)
+-#define PUD_MASK	(~(PUD_SIZE-1))
+-#define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
+-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
++#define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
++#define PMD_MASK	(~(PMD_SIZE - 1))
++#define PUD_SIZE	(_AC(1, UL) << PUD_SHIFT)
++#define PUD_MASK	(~(PUD_SIZE - 1))
++#define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
++#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+ 
+-#define MAXMEM		 _AC(0x6fffffffff, UL)
++#define MAXMEM		 _AC(0x0000006fffffffff, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+ #define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+-#define MODULES_VADDR    _AC(0xffffffff88000000, UL)
++#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+ #define MODULES_END      _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+ 
+ #ifndef __ASSEMBLY__
+ 
+-static inline unsigned long pgd_bad(pgd_t pgd)
++static inline int pgd_bad(pgd_t pgd)
+ {
+-	return __pgd_val(pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++	return (__pgd_val(pgd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+-static inline unsigned long pud_bad(pud_t pud)
++static inline int pud_bad(pud_t pud)
+ {
+-	return __pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++	return (__pud_val(pud) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+-static inline unsigned long pmd_bad(pmd_t pmd)
++static inline int pmd_bad(pmd_t pmd)
+ {
+-	return __pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++	return (__pmd_val(pmd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+ #define pte_none(x)	(!(x).pte)
+ #define pte_present(x)	((x).pte & (_PAGE_PRESENT | _PAGE_PROTNONE))
+ 
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))	/* FIXME: is this right? */
++#define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))   /* FIXME: is this right? */
+ 
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
+ #define pte_mfn(_pte) ((_pte).pte & _PAGE_PRESENT ? \
+@@ -181,13 +183,13 @@ static inline unsigned long pmd_bad(pmd_
+ 		       mfn_to_local_pfn(__pte_mfn(_pte)) :	\
+ 		       __pte_mfn(_pte))
+ 
+-#define pte_page(x)	pfn_to_page(pte_pfn(x))
++#define pte_page(x)	pfn_to_page(pte_pfn((x)))
+ 
+ /*
+  * Macro to mark a page protection value as "uncacheable".
+  */
+-#define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
+-
++#define pgprot_noncached(prot)					\
++	(__pgprot(pgprot_val((prot)) | _PAGE_PCD | _PAGE_PWT))
+ 
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+@@ -197,36 +199,39 @@ static inline unsigned long pmd_bad(pmd_
+ /*
+  * Level 4 access.
+  */
+-#define pgd_page_vaddr(pgd) ((unsigned long) __va(pgd_val(pgd) & PTE_MASK))
+-#define pgd_page(pgd)		(pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT))
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+-#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+-#define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
++#define pgd_page_vaddr(pgd)						\
++	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
++#define pgd_page(pgd)		(pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_offset(mm, address)	((mm)->pgd + pgd_index((address)))
++#define pgd_offset_k(address) (init_level4_pgt + pgd_index((address)))
+ #define pgd_present(pgd) (__pgd_val(pgd) & _PAGE_PRESENT)
+ static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
+ 
+ /* PUD - Level3 access */
+ /* to find an entry in a page-table-directory. */
+-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
+-#define pud_page(pud)		(pfn_to_page(pud_val(pud) >> PAGE_SHIFT))
+-#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+-#define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
++#define pud_page_vaddr(pud)						\
++	((unsigned long)__va(pud_val((pud)) & PHYSICAL_PAGE_MASK))
++#define pud_page(pud)	(pfn_to_page(pud_val((pud)) >> PAGE_SHIFT))
++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
++#define pud_offset(pgd, address)					\
++	((pud_t *)pgd_page_vaddr(*(pgd)) + pud_index((address)))
+ #define pud_present(pud) (__pud_val(pud) & _PAGE_PRESENT)
+ 
+ static inline int pud_large(pud_t pte)
+ {
+-	return (__pud_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
+-		(_PAGE_PSE|_PAGE_PRESENT);
++	return (__pud_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
++		(_PAGE_PSE | _PAGE_PRESENT);
+ }
+ 
+ /* PMD  - Level 2 access */
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+-#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
++#define pmd_page(pmd)		(pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+ 
+-#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+-#define pmd_offset(dir, address) ((pmd_t *) pud_page_vaddr(*(dir)) + \
+-                                  pmd_index(address))
++#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
++#define pmd_offset(dir, address) ((pmd_t *)pud_page_vaddr(*(dir)) + \
++				  pmd_index(address))
+ #define pmd_none(x)	(!__pmd_val(x))
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+@@ -235,43 +240,56 @@ static inline int pud_large(pud_t pte)
+ #else
+ #define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+ #endif
+-#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
+-#define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pfn_pmd(nr, prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val((prot))))
++#define pmd_pfn(x)  ((pmd_val((x)) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+ #define pte_to_pgoff(pte) ((__pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+-#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | _PAGE_FILE })
++#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) |	\
++					    _PAGE_FILE })
+ #define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
+ 
+ /* PTE - Level 1 access. */
+ 
+ /* page, protection -> pte */
+-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+- 
+-#define pte_index(address) \
+-		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn((page)), (pgprot))
++
++#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+-			pte_index(address))
++					 pte_index((address)))
+ 
+ /* x86-64 always has all page tables mapped. */
+-#define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
+-#define pte_offset_map_nested(dir,address) pte_offset_kernel(dir,address)
++#define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
++#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
+ #define pte_unmap(pte) /* NOP */
+-#define pte_unmap_nested(pte) /* NOP */ 
++#define pte_unmap_nested(pte) /* NOP */
++
++#define update_mmu_cache(vma, address, pte) do { } while (0)
+ 
+-#define update_mmu_cache(vma,address,pte) do { } while (0)
++#define direct_gbpages 0
+ 
+ /* Encode and de-code a swap entry */
+-#define __swp_type(x)			(((x).val >> 1) & 0x3f)
+-#define __swp_offset(x)			((x).val >> 8)
+-#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
++#if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
++#define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
++#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1)
++#else
++#define SWP_TYPE_BITS (_PAGE_BIT_PROTNONE - _PAGE_BIT_PRESENT - 1)
++#define SWP_OFFSET_SHIFT (_PAGE_BIT_FILE + 1)
++#endif
++
++#define __swp_type(x)			(((x).val >> (_PAGE_BIT_PRESENT + 1)) \
++					 & ((1U << SWP_TYPE_BITS) - 1))
++#define __swp_offset(x)			((x).val >> SWP_OFFSET_SHIFT)
++#define __swp_entry(type, offset)	((swp_entry_t) { \
++					 ((type) << (_PAGE_BIT_PRESENT + 1)) \
++					 | ((offset) << SWP_OFFSET_SHIFT) })
+ #define __pte_to_swp_entry(pte)		((swp_entry_t) { __pte_val(pte) })
+ #define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
+ 
+-extern int kern_addr_valid(unsigned long addr); 
++extern int kern_addr_valid(unsigned long addr);
+ extern void cleanup_highmap(void);
+ 
+-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+-		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
++	direct_remap_pfn_range(vma, vaddr, pfn, size, prot, DOMID_IO)
+ 
+ #define HAVE_ARCH_UNMAPPED_AREA
+ #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+@@ -284,8 +302,10 @@ extern void cleanup_highmap(void);
+ 
+ /* fs/proc/kcore.c */
+ #define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+-#define	kc_offset_to_vaddr(o) \
+-   (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
++#define	kc_offset_to_vaddr(o)				\
++	(((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1)))	\
++	 ? ((o) | ~__VIRTUAL_MASK)			\
++	 : (o))
+ 
+ #define __HAVE_ARCH_PTE_SAME
+ #endif /* !__ASSEMBLY__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:32.000000000 +0100
+@@ -3,10 +3,6 @@
+ 
+ #include <asm/processor-flags.h>
+ 
+-/* migration helpers, for KVM - will be removed in 2.6.25: */
+-#include <asm/vm86.h>
+-#define Xgt_desc_struct	desc_ptr
+-
+ /* Forward declaration, a strange C thing */
+ struct task_struct;
+ struct mm_struct;
+@@ -24,6 +20,7 @@ struct mm_struct;
+ #include <asm/msr.h>
+ #include <asm/desc_defs.h>
+ #include <asm/nops.h>
++
+ #include <linux/personality.h>
+ #include <linux/cpumask.h>
+ #include <linux/cache.h>
+@@ -38,16 +35,18 @@ struct mm_struct;
+ static inline void *current_text_addr(void)
+ {
+ 	void *pc;
+-	asm volatile("mov $1f,%0\n1:":"=r" (pc));
++
++	asm volatile("mov $1f, %0; 1:":"=r" (pc));
++
+ 	return pc;
+ }
+ 
+ #ifdef CONFIG_X86_VSMP
+-#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
+-#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_TASKALIGN		(1 << INTERNODE_CACHE_SHIFT)
++# define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
+ #else
+-#define ARCH_MIN_TASKALIGN	16
+-#define ARCH_MIN_MMSTRUCT_ALIGN	0
++# define ARCH_MIN_TASKALIGN		16
++# define ARCH_MIN_MMSTRUCT_ALIGN	0
+ #endif
+ 
+ /*
+@@ -57,68 +56,80 @@ static inline void *current_text_addr(vo
+  */
+ 
+ struct cpuinfo_x86 {
+-	__u8	x86;		/* CPU family */
+-	__u8	x86_vendor;	/* CPU vendor */
+-	__u8	x86_model;
+-	__u8	x86_mask;
++	__u8			x86;		/* CPU family */
++	__u8			x86_vendor;	/* CPU vendor */
++	__u8			x86_model;
++	__u8			x86_mask;
+ #ifdef CONFIG_X86_32
+-	char	wp_works_ok;	/* It doesn't on 386's */
+-	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */
+-	char	hard_math;
+-	char	rfu;
+-	char	fdiv_bug;
+-	char	f00f_bug;
+-	char	coma_bug;
+-	char	pad0;
++	char			wp_works_ok;	/* It doesn't on 386's */
++
++	/* Problems on some 486Dx4's and old 386's: */
++	char			hlt_works_ok;
++	char			hard_math;
++	char			rfu;
++	char			fdiv_bug;
++	char			f00f_bug;
++	char			coma_bug;
++	char			pad0;
+ #else
+-	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
+-	int     x86_tlbsize;
+-	__u8    x86_virt_bits, x86_phys_bits;
+-	/* cpuid returned core id bits */
+-	__u8    x86_coreid_bits;
+-	/* Max extended CPUID function supported */
+-	__u32   extended_cpuid_level;
+-#endif
+-	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
+-	__u32	x86_capability[NCAPINTS];
+-	char	x86_vendor_id[16];
+-	char	x86_model_id[64];
+-	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
+-				    call  */
+-	int 	x86_cache_alignment;	/* In bytes */
+-	int	x86_power;
+-	unsigned long loops_per_jiffy;
++	/* Number of 4K pages in DTLB/ITLB combined(in pages): */
++	int			 x86_tlbsize;
++	__u8			x86_virt_bits;
++	__u8			x86_phys_bits;
++	/* CPUID returned core id bits: */
++	__u8			x86_coreid_bits;
++	/* Max extended CPUID function supported: */
++	__u32			extended_cpuid_level;
++#endif
++	/* Maximum supported CPUID level, -1=no CPUID: */
++	int			cpuid_level;
++	__u32			x86_capability[NCAPINTS];
++	char			x86_vendor_id[16];
++	char			x86_model_id[64];
++	/* in KB - valid for CPUS which support this call: */
++	int			x86_cache_size;
++	int			x86_cache_alignment;	/* In bytes */
++	int			x86_power;
++	unsigned long		loops_per_jiffy;
+ #ifdef CONFIG_SMP
+-	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
++	/* cpus sharing the last level cache: */
++	cpumask_t		llc_shared_map;
+ #endif
+-	u16 x86_max_cores;		/* cpuid returned max cores value */
+-	u16 apicid;
+-	u16 x86_clflush_size;
++	/* cpuid returned max cores value: */
++	u16			 x86_max_cores;
++	u16			apicid;
++	u16			initial_apicid;
++	u16			x86_clflush_size;
+ #ifdef CONFIG_SMP
+-	u16 booted_cores;		/* number of cores as seen by OS */
+-	u16 phys_proc_id; 		/* Physical processor id. */
+-	u16 cpu_core_id;  		/* Core id */
+-	u16 cpu_index;			/* index into per_cpu list */
++	/* number of cores as seen by the OS: */
++	u16			booted_cores;
++	/* Physical processor id: */
++	u16			phys_proc_id;
++	/* Core id: */
++	u16			cpu_core_id;
++	/* Index into per_cpu list: */
++	u16			cpu_index;
+ #endif
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+ 
+-#define X86_VENDOR_INTEL 0
+-#define X86_VENDOR_CYRIX 1
+-#define X86_VENDOR_AMD 2
+-#define X86_VENDOR_UMC 3
+-#define X86_VENDOR_NEXGEN 4
+-#define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_TRANSMETA 7
+-#define X86_VENDOR_NSC 8
+-#define X86_VENDOR_NUM 9
+-#define X86_VENDOR_UNKNOWN 0xff
++#define X86_VENDOR_INTEL	0
++#define X86_VENDOR_CYRIX	1
++#define X86_VENDOR_AMD		2
++#define X86_VENDOR_UMC		3
++#define X86_VENDOR_CENTAUR	5
++#define X86_VENDOR_TRANSMETA	7
++#define X86_VENDOR_NSC		8
++#define X86_VENDOR_NUM		9
++
++#define X86_VENDOR_UNKNOWN	0xff
+ 
+ /*
+  * capabilities of CPUs
+  */
+-extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct cpuinfo_x86 new_cpu_data;
+-extern __u32 cleared_cpu_caps[NCAPINTS];
++extern struct cpuinfo_x86	boot_cpu_data;
++extern struct cpuinfo_x86	new_cpu_data;
++
++extern __u32			cleared_cpu_caps[NCAPINTS];
+ 
+ #ifdef CONFIG_SMP
+ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+@@ -129,7 +140,18 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_
+ #define current_cpu_data	boot_cpu_data
+ #endif
+ 
+-void cpu_detect(struct cpuinfo_x86 *c);
++static inline int hlt_works(int cpu)
++{
++#ifdef CONFIG_X86_32
++	return cpu_data(cpu).hlt_works_ok;
++#else
++	return 1;
++#endif
++}
++
++#define cache_line_size()	(boot_cpu_data.x86_cache_alignment)
++
++extern void cpu_detect(struct cpuinfo_x86 *c);
+ 
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void identify_boot_cpu(void);
+@@ -149,12 +171,12 @@ static inline void xen_cpuid(unsigned in
+ 			     unsigned int *ecx, unsigned int *edx)
+ {
+ 	/* ecx is often an input as well as an output. */
+-	__asm__(XEN_CPUID
+-		: "=a" (*eax),
+-		  "=b" (*ebx),
+-		  "=c" (*ecx),
+-		  "=d" (*edx)
+-		: "0" (*eax), "2" (*ecx));
++	asm(XEN_CPUID
++	    : "=a" (*eax),
++	      "=b" (*ebx),
++	      "=c" (*ecx),
++	      "=d" (*edx)
++	    : "0" (*eax), "2" (*ecx));
+ }
+ 
+ static inline void load_cr3(pgd_t *pgdir)
+@@ -166,57 +188,70 @@ static inline void load_cr3(pgd_t *pgdir
+ #ifdef CONFIG_X86_32
+ /* This is the TSS defined by the hardware. */
+ struct x86_hw_tss {
+-	unsigned short	back_link, __blh;
+-	unsigned long	sp0;
+-	unsigned short	ss0, __ss0h;
+-	unsigned long	sp1;
+-	unsigned short	ss1, __ss1h;	/* ss1 caches MSR_IA32_SYSENTER_CS */
+-	unsigned long	sp2;
+-	unsigned short	ss2, __ss2h;
+-	unsigned long	__cr3;
+-	unsigned long	ip;
+-	unsigned long	flags;
+-	unsigned long	ax, cx, dx, bx;
+-	unsigned long	sp, bp, si, di;
+-	unsigned short	es, __esh;
+-	unsigned short	cs, __csh;
+-	unsigned short	ss, __ssh;
+-	unsigned short	ds, __dsh;
+-	unsigned short	fs, __fsh;
+-	unsigned short	gs, __gsh;
+-	unsigned short	ldt, __ldth;
+-	unsigned short	trace, io_bitmap_base;
++	unsigned short		back_link, __blh;
++	unsigned long		sp0;
++	unsigned short		ss0, __ss0h;
++	unsigned long		sp1;
++	/* ss1 caches MSR_IA32_SYSENTER_CS: */
++	unsigned short		ss1, __ss1h;
++	unsigned long		sp2;
++	unsigned short		ss2, __ss2h;
++	unsigned long		__cr3;
++	unsigned long		ip;
++	unsigned long		flags;
++	unsigned long		ax;
++	unsigned long		cx;
++	unsigned long		dx;
++	unsigned long		bx;
++	unsigned long		sp;
++	unsigned long		bp;
++	unsigned long		si;
++	unsigned long		di;
++	unsigned short		es, __esh;
++	unsigned short		cs, __csh;
++	unsigned short		ss, __ssh;
++	unsigned short		ds, __dsh;
++	unsigned short		fs, __fsh;
++	unsigned short		gs, __gsh;
++	unsigned short		ldt, __ldth;
++	unsigned short		trace;
++	unsigned short		io_bitmap_base;
++
+ } __attribute__((packed));
+ extern struct tss_struct doublefault_tss;
+ #else
+ struct x86_hw_tss {
+-	u32 reserved1;
+-	u64 sp0;
+-	u64 sp1;
+-	u64 sp2;
+-	u64 reserved2;
+-	u64 ist[7];
+-	u32 reserved3;
+-	u32 reserved4;
+-	u16 reserved5;
+-	u16 io_bitmap_base;
++	u32			reserved1;
++	u64			sp0;
++	u64			sp1;
++	u64			sp2;
++	u64			reserved2;
++	u64			ist[7];
++	u32			reserved3;
++	u32			reserved4;
++	u16			reserved5;
++	u16			io_bitmap_base;
++
+ } __attribute__((packed)) ____cacheline_aligned;
+ #endif
+ #endif /* CONFIG_X86_NO_TSS */
+ 
+ /*
+- * Size of io_bitmap.
++ * IO-bitmap sizes:
+  */
+-#define IO_BITMAP_BITS  65536
+-#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+-#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+-#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
+-#define INVALID_IO_BITMAP_OFFSET 0x8000
+-#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
++#define IO_BITMAP_BITS			65536
++#define IO_BITMAP_BYTES			(IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS			(IO_BITMAP_BYTES/sizeof(long))
++#define IO_BITMAP_OFFSET		offsetof(struct tss_struct, io_bitmap)
++#define INVALID_IO_BITMAP_OFFSET	0x8000
++#define INVALID_IO_BITMAP_OFFSET_LAZY	0x9000
+ 
+ #ifndef CONFIG_X86_NO_TSS
+ struct tss_struct {
+-	struct x86_hw_tss x86_tss;
++	/*
++	 * The hardware state:
++	 */
++	struct x86_hw_tss	x86_tss;
+ 
+ 	/*
+ 	 * The extra 1 is there because the CPU will access an
+@@ -224,136 +259,162 @@ struct tss_struct {
+ 	 * bitmap. The extra byte must be all 1 bits, and must
+ 	 * be within the limit.
+ 	 */
+-	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
++	unsigned long		io_bitmap[IO_BITMAP_LONGS + 1];
+ 	/*
+ 	 * Cache the current maximum and the last task that used the bitmap:
+ 	 */
+-	unsigned long io_bitmap_max;
+-	struct thread_struct *io_bitmap_owner;
++	unsigned long		io_bitmap_max;
++	struct thread_struct	*io_bitmap_owner;
++
+ 	/*
+-	 * pads the TSS to be cacheline-aligned (size is 0x100)
++	 * Pad the TSS to be cacheline-aligned (size is 0x100):
+ 	 */
+-	unsigned long __cacheline_filler[35];
++	unsigned long		__cacheline_filler[35];
+ 	/*
+-	 * .. and then another 0x100 bytes for emergency kernel stack
++	 * .. and then another 0x100 bytes for the emergency kernel stack:
+ 	 */
+-	unsigned long stack[64];
++	unsigned long		stack[64];
++
+ } __attribute__((packed));
+ 
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
+ 
+-/* Save the original ist values for checking stack pointers during debugging */
++/*
++ * Save the original ist values for checking stack pointers during debugging
++ */
+ struct orig_ist {
+-	unsigned long ist[7];
++	unsigned long		ist[7];
+ };
+ #endif /* CONFIG_X86_NO_TSS */
+ 
+ #define	MXCSR_DEFAULT		0x1f80
+ 
+ struct i387_fsave_struct {
+-	u32	cwd;
+-	u32	swd;
+-	u32	twd;
+-	u32	fip;
+-	u32	fcs;
+-	u32	foo;
+-	u32	fos;
+-	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	u32	status;		/* software status information */
++	u32			cwd;	/* FPU Control Word		*/
++	u32			swd;	/* FPU Status Word		*/
++	u32			twd;	/* FPU Tag Word			*/
++	u32			fip;	/* FPU IP Offset		*/
++	u32			fcs;	/* FPU IP Selector		*/
++	u32			foo;	/* FPU Operand Pointer Offset	*/
++	u32			fos;	/* FPU Operand Pointer Selector	*/
++
++	/* 8*10 bytes for each FP-reg = 80 bytes:			*/
++	u32			st_space[20];
++
++	/* Software status information [not touched by FSAVE ]:		*/
++	u32			status;
+ };
+ 
+ struct i387_fxsave_struct {
+-	u16	cwd;
+-	u16	swd;
+-	u16	twd;
+-	u16	fop;
++	u16			cwd; /* Control Word			*/
++	u16			swd; /* Status Word			*/
++	u16			twd; /* Tag Word			*/
++	u16			fop; /* Last Instruction Opcode		*/
+ 	union {
+ 		struct {
+-			u64	rip;
+-			u64	rdp;
++			u64	rip; /* Instruction Pointer		*/
++			u64	rdp; /* Data Pointer			*/
+ 		};
+ 		struct {
+-			u32	fip;
+-			u32	fcs;
+-			u32	foo;
+-			u32	fos;
++			u32	fip; /* FPU IP Offset			*/
++			u32	fcs; /* FPU IP Selector			*/
++			u32	foo; /* FPU Operand Offset		*/
++			u32	fos; /* FPU Operand Selector		*/
+ 		};
+ 	};
+-	u32	mxcsr;
+-	u32	mxcsr_mask;
+-	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
+-	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
+-	u32	padding[24];
++	u32			mxcsr;		/* MXCSR Register State */
++	u32			mxcsr_mask;	/* MXCSR Mask		*/
++
++	/* 8*16 bytes for each FP-reg = 128 bytes:			*/
++	u32			st_space[32];
++
++	/* 16*16 bytes for each XMM-reg = 256 bytes:			*/
++	u32			xmm_space[64];
++
++	u32			padding[24];
++
+ } __attribute__((aligned(16)));
+ 
+ struct i387_soft_struct {
+-	u32	cwd;
+-	u32	swd;
+-	u32	twd;
+-	u32	fip;
+-	u32	fcs;
+-	u32	foo;
+-	u32	fos;
+-	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	u8	ftop, changed, lookahead, no_update, rm, alimit;
+-	struct info	*info;
+-	u32	entry_eip;
++	u32			cwd;
++	u32			swd;
++	u32			twd;
++	u32			fip;
++	u32			fcs;
++	u32			foo;
++	u32			fos;
++	/* 8*10 bytes for each FP-reg = 80 bytes: */
++	u32			st_space[20];
++	u8			ftop;
++	u8			changed;
++	u8			lookahead;
++	u8			no_update;
++	u8			rm;
++	u8			alimit;
++	struct info		*info;
++	u32			entry_eip;
+ };
+ 
+-union i387_union {
++union thread_xstate {
+ 	struct i387_fsave_struct	fsave;
+ 	struct i387_fxsave_struct	fxsave;
+-	struct i387_soft_struct 	soft;
++	struct i387_soft_struct		soft;
+ };
+ 
+-#ifdef CONFIG_X86_32
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-#elif !defined(CONFIG_X86_NO_TSS)
++#if defined(CONFIG_X86_64) && !defined(CONFIG_X86_NO_TSS)
+ DECLARE_PER_CPU(struct orig_ist, orig_ist);
+ #endif
+ 
+ extern void print_cpu_info(struct cpuinfo_x86 *);
++extern unsigned int xstate_size;
++extern void free_thread_xstate(struct task_struct *);
++extern struct kmem_cache *task_xstate_cachep;
+ extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+ 
+ struct thread_struct {
+-/* cached TLS descriptors. */
+-	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+-	unsigned long	sp0;
+-	unsigned long	sp;
++	/* Cached TLS descriptors: */
++	struct desc_struct	tls_array[GDT_ENTRY_TLS_ENTRIES];
++	unsigned long		sp0;
++	unsigned long		sp;
+ #ifdef CONFIG_X86_32
+-	unsigned long	sysenter_cs;
++	unsigned long		sysenter_cs;
+ #else
+-	unsigned long 	usersp;	/* Copy from PDA */
+-	unsigned short	es, ds, fsindex, gsindex;
+-#endif
+-	unsigned long	ip;
+-	unsigned long	fs;
+-	unsigned long	gs;
+-/* Hardware debugging registers */
+-	unsigned long	debugreg0;
+-	unsigned long	debugreg1;
+-	unsigned long	debugreg2;
+-	unsigned long	debugreg3;
+-	unsigned long	debugreg6;
+-	unsigned long	debugreg7;
+-/* fault info */
+-	unsigned long	cr2, trap_no, error_code;
+-/* floating point info */
+-	union i387_union	i387 __attribute__((aligned(16)));;
++	unsigned long		usersp;	/* Copy from PDA */
++	unsigned short		es;
++	unsigned short		ds;
++	unsigned short		fsindex;
++	unsigned short		gsindex;
++#endif
++	unsigned long		ip;
++	unsigned long		fs;
++	unsigned long		gs;
++	/* Hardware debugging registers: */
++	unsigned long		debugreg0;
++	unsigned long		debugreg1;
++	unsigned long		debugreg2;
++	unsigned long		debugreg3;
++	unsigned long		debugreg6;
++	unsigned long		debugreg7;
++	/* Fault info: */
++	unsigned long		cr2;
++	unsigned long		trap_no;
++	unsigned long		error_code;
++	/* floating point and extended processor state */
++	union thread_xstate	*xstate;
+ #ifdef CONFIG_X86_32
+-/* virtual 86 mode info */
++	/* Virtual 86 mode info */
+ 	struct vm86_struct __user *vm86_info;
+ 	unsigned long		screen_bitmap;
+ 	unsigned long		v86flags, v86mask, saved_sp0;
+ 	unsigned int		saved_fs, saved_gs;
+ #endif
+-/* IO permissions */
+-	unsigned long	*io_bitmap_ptr;
+-	unsigned long	iopl;
+-/* max allowed port in the bitmap, in bytes: */
+-	unsigned io_bitmap_max;
++	/* IO permissions: */
++	unsigned long		*io_bitmap_ptr;
++	unsigned long		iopl;
++	/* Max allowed port in the bitmap, in bytes: */
++	unsigned		io_bitmap_max;
+ /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
+ 	unsigned long	debugctlmsr;
+ /* Debug Store - if not 0 points to a DS Save Area configuration;
+@@ -384,12 +445,12 @@ static inline void xen_set_iopl_mask(uns
+ }
+ 
+ #ifndef CONFIG_X86_NO_TSS
+-static inline void native_load_sp0(struct tss_struct *tss,
+-				   struct thread_struct *thread)
++static inline void
++native_load_sp0(struct tss_struct *tss, struct thread_struct *thread)
+ {
+ 	tss->x86_tss.sp0 = thread->sp0;
+ #ifdef CONFIG_X86_32
+-	/* Only happens when SEP is enabled, no need to test "SEP"arately */
++	/* Only happens when SEP is enabled, no need to test "SEP"arately: */
+ 	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+ 		tss->x86_tss.ss1 = thread->sysenter_cs;
+ 		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+@@ -403,8 +464,8 @@ static inline void native_load_sp0(struc
+ } while (0)
+ #endif
+ 
+-#define __cpuid xen_cpuid
+-#define paravirt_enabled() 0
++#define __cpuid			xen_cpuid
++#define paravirt_enabled()	0
+ 
+ /*
+  * These special macros can be used to get or set a debugging register
+@@ -424,11 +485,12 @@ static inline void native_load_sp0(struc
+  * enable), so that any CPU's that boot up
+  * after us can get the correct flags.
+  */
+-extern unsigned long mmu_cr4_features;
++extern unsigned long		mmu_cr4_features;
+ 
+ static inline void set_in_cr4(unsigned long mask)
+ {
+ 	unsigned cr4;
++
+ 	mmu_cr4_features |= mask;
+ 	cr4 = read_cr4();
+ 	cr4 |= mask;
+@@ -438,6 +500,7 @@ static inline void set_in_cr4(unsigned l
+ static inline void clear_in_cr4(unsigned long mask)
+ {
+ 	unsigned cr4;
++
+ 	mmu_cr4_features &= ~mask;
+ 	cr4 = read_cr4();
+ 	cr4 &= ~mask;
+@@ -445,42 +508,42 @@ static inline void clear_in_cr4(unsigned
+ }
+ 
+ struct microcode_header {
+-	unsigned int hdrver;
+-	unsigned int rev;
+-	unsigned int date;
+-	unsigned int sig;
+-	unsigned int cksum;
+-	unsigned int ldrver;
+-	unsigned int pf;
+-	unsigned int datasize;
+-	unsigned int totalsize;
+-	unsigned int reserved[3];
++	unsigned int		hdrver;
++	unsigned int		rev;
++	unsigned int		date;
++	unsigned int		sig;
++	unsigned int		cksum;
++	unsigned int		ldrver;
++	unsigned int		pf;
++	unsigned int		datasize;
++	unsigned int		totalsize;
++	unsigned int		reserved[3];
+ };
+ 
+ struct microcode {
+-	struct microcode_header hdr;
+-	unsigned int bits[0];
++	struct microcode_header	hdr;
++	unsigned int		bits[0];
+ };
+ 
+-typedef struct microcode microcode_t;
+-typedef struct microcode_header microcode_header_t;
++typedef struct microcode	microcode_t;
++typedef struct microcode_header	microcode_header_t;
+ 
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+-	unsigned int sig;
+-	unsigned int pf;
+-	unsigned int cksum;
++	unsigned int		sig;
++	unsigned int		pf;
++	unsigned int		cksum;
+ };
+ 
+ struct extended_sigtable {
+-	unsigned int count;
+-	unsigned int cksum;
+-	unsigned int reserved[3];
++	unsigned int		count;
++	unsigned int		cksum;
++	unsigned int		reserved[3];
+ 	struct extended_signature sigs[0];
+ };
+ 
+ typedef struct {
+-	unsigned long seg;
++	unsigned long		seg;
+ } mm_segment_t;
+ 
+ 
+@@ -492,7 +555,7 @@ extern int kernel_thread(int (*fn)(void 
+ /* Free all resources held by a thread. */
+ extern void release_thread(struct task_struct *);
+ 
+-/* Prepare to copy thread state - unlazy all lazy status */
++/* Prepare to copy thread state - unlazy all lazy state */
+ extern void prepare_to_copy(struct task_struct *tsk);
+ 
+ unsigned long get_wchan(struct task_struct *p);
+@@ -529,118 +592,138 @@ static inline unsigned int cpuid_eax(uns
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return eax;
+ }
++
+ static inline unsigned int cpuid_ebx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return ebx;
+ }
++
+ static inline unsigned int cpuid_ecx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return ecx;
+ }
++
+ static inline unsigned int cpuid_edx(unsigned int op)
+ {
+ 	unsigned int eax, ebx, ecx, edx;
+ 
+ 	cpuid(op, &eax, &ebx, &ecx, &edx);
++
+ 	return edx;
+ }
+ 
+ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+ static inline void rep_nop(void)
+ {
+-	__asm__ __volatile__("rep;nop": : :"memory");
++	asm volatile("rep; nop" ::: "memory");
+ }
+ 
+-/* Stop speculative execution */
++static inline void cpu_relax(void)
++{
++	rep_nop();
++}
++
++/* Stop speculative execution: */
+ static inline void sync_core(void)
+ {
+ 	int tmp;
++
+ 	asm volatile("cpuid" : "=a" (tmp) : "0" (1)
+-					  : "ebx", "ecx", "edx", "memory");
++		     : "ebx", "ecx", "edx", "memory");
+ }
+ 
+-#define cpu_relax()   rep_nop()
+-
+ static inline void __monitor(const void *eax, unsigned long ecx,
+-		unsigned long edx)
++			     unsigned long edx)
+ {
+-	/* "monitor %eax,%ecx,%edx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc8;"
+-		: :"a" (eax), "c" (ecx), "d"(edx));
++	/* "monitor %eax, %ecx, %edx;" */
++	asm volatile(".byte 0x0f, 0x01, 0xc8;"
++		     :: "a" (eax), "c" (ecx), "d"(edx));
+ }
+ 
+ static inline void __mwait(unsigned long eax, unsigned long ecx)
+ {
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
++	/* "mwait %eax, %ecx;" */
++	asm volatile(".byte 0x0f, 0x01, 0xc9;"
++		     :: "a" (eax), "c" (ecx));
+ }
+ 
+ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+ {
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		"sti; .byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
++	trace_hardirqs_on();
++	/* "mwait %eax, %ecx;" */
++	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
++		     :: "a" (eax), "c" (ecx));
+ }
+ 
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+ 
+-extern int force_mwait;
++extern int			force_mwait;
+ 
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ 
+-extern unsigned long boot_option_idle_override;
++extern unsigned long		boot_option_idle_override;
+ 
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+ 
+ /* Defined in head.S */
+-extern struct desc_ptr early_gdt_descr;
++extern struct desc_ptr		early_gdt_descr;
+ 
+ extern void cpu_set_gdt(int);
+ extern void switch_to_new_gdt(void);
+ extern void cpu_init(void);
+ extern void init_gdt(int cpu);
+ 
+-/* from system description table in BIOS.  Mostly for MCA use, but
+- * others may find it useful. */
+-extern unsigned int machine_id;
+-extern unsigned int machine_submodel_id;
+-extern unsigned int BIOS_revision;
++static inline void update_debugctlmsr(unsigned long debugctlmsr)
++{
++#ifndef CONFIG_X86_DEBUGCTLMSR
++	if (boot_cpu_data.x86 < 6)
++		return;
++#endif
++	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
++}
+ 
+-/* Boot loader type from the setup header */
+-extern int bootloader_type;
++/*
++ * from system description table in BIOS. Mostly for MCA use, but
++ * others may find it useful:
++ */
++extern unsigned int		machine_id;
++extern unsigned int		machine_submodel_id;
++extern unsigned int		BIOS_revision;
++
++/* Boot loader type from the setup header: */
++extern int			bootloader_type;
+ 
+-extern char ignore_fpu_irq;
+-#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++extern char			ignore_fpu_irq;
+ 
+ #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+ #define ARCH_HAS_PREFETCHW
+ #define ARCH_HAS_SPINLOCK_PREFETCH
+ 
+ #ifdef CONFIG_X86_32
+-#define BASE_PREFETCH	ASM_NOP4
+-#define ARCH_HAS_PREFETCH
++# define BASE_PREFETCH		ASM_NOP4
++# define ARCH_HAS_PREFETCH
+ #else
+-#define BASE_PREFETCH	"prefetcht0 (%1)"
++# define BASE_PREFETCH		"prefetcht0 (%1)"
+ #endif
+ 
+-/* Prefetch instructions for Pentium III and AMD Athlon */
+-/* It's not worth to care about 3dnow! prefetches for the K6
+-   because they are microcoded there and very slow.
+-   However we don't do prefetches for pre XP Athlons currently
+-   That should be fixed. */
++/*
++ * Prefetch instructions for Pentium III (+) and AMD Athlon (+)
++ *
++ * It's not worth to care about 3dnow prefetches for the K6
++ * because they are microcoded there and very slow.
++ */
+ static inline void prefetch(const void *x)
+ {
+ 	alternative_input(BASE_PREFETCH,
+@@ -649,8 +732,11 @@ static inline void prefetch(const void *
+ 			  "r" (x));
+ }
+ 
+-/* 3dnow! prefetch to get an exclusive cache line. Useful for
+-   spinlocks to avoid one state transition in the cache coherency protocol. */
++/*
++ * 3dnow prefetch to get an exclusive cache line.
++ * Useful for spinlocks to avoid one state transition in the
++ * cache coherency protocol:
++ */
+ static inline void prefetchw(const void *x)
+ {
+ 	alternative_input(BASE_PREFETCH,
+@@ -659,21 +745,25 @@ static inline void prefetchw(const void 
+ 			  "r" (x));
+ }
+ 
+-#define spin_lock_prefetch(x)	prefetchw(x)
++static inline void spin_lock_prefetch(const void *x)
++{
++	prefetchw(x);
++}
++
+ #ifdef CONFIG_X86_32
+ /*
+  * User space process size: 3GB (default).
+  */
+-#define TASK_SIZE	(PAGE_OFFSET)
+-#define STACK_TOP	TASK_SIZE
+-#define STACK_TOP_MAX	STACK_TOP
+-
+-#define INIT_THREAD  {							\
+-	.sp0 = sizeof(init_stack) + (long)&init_stack,			\
+-	.vm86_info = NULL,						\
+-	.sysenter_cs = __KERNEL_CS,					\
+-	.io_bitmap_ptr = NULL,						\
+-	.fs = __KERNEL_PERCPU,						\
++#define TASK_SIZE		PAGE_OFFSET
++#define STACK_TOP		TASK_SIZE
++#define STACK_TOP_MAX		STACK_TOP
++
++#define INIT_THREAD  {							  \
++	.sp0			= sizeof(init_stack) + (long)&init_stack, \
++	.vm86_info		= NULL,					  \
++	.sysenter_cs		= __KERNEL_CS,				  \
++	.io_bitmap_ptr		= NULL,					  \
++	.fs			= __KERNEL_PERCPU,			  \
+ }
+ 
+ /*
+@@ -682,28 +772,15 @@ static inline void prefetchw(const void 
+  * permission bitmap. The extra byte must be all 1 bits, and must
+  * be within the limit.
+  */
+-#define INIT_TSS  {							\
+-	.x86_tss = {							\
++#define INIT_TSS  {							  \
++	.x86_tss = {							  \
+ 		.sp0		= sizeof(init_stack) + (long)&init_stack, \
+-		.ss0		= __KERNEL_DS,				\
+-		.ss1		= __KERNEL_CS,				\
+-		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
+-	 },								\
+-	.io_bitmap	= { [0 ... IO_BITMAP_LONGS] = ~0 },		\
+-}
+-
+-#define start_thread(regs, new_eip, new_esp) do {		\
+-	__asm__("movl %0,%%gs": :"r" (0));			\
+-	regs->fs = 0;						\
+-	set_fs(USER_DS);					\
+-	regs->ds = __USER_DS;					\
+-	regs->es = __USER_DS;					\
+-	regs->ss = __USER_DS;					\
+-	regs->cs = __USER_CS;					\
+-	regs->ip = new_eip;					\
+-	regs->sp = new_esp;					\
+-} while (0)
+-
++		.ss0		= __KERNEL_DS,				  \
++		.ss1		= __KERNEL_CS,				  \
++		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		  \
++	 },								  \
++	.io_bitmap		= { [0 ... IO_BITMAP_LONGS] = ~0 },	  \
++}
+ 
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ 
+@@ -731,24 +808,24 @@ extern unsigned long thread_saved_pc(str
+        __regs__ - 1;                                                   \
+ })
+ 
+-#define KSTK_ESP(task) (task_pt_regs(task)->sp)
++#define KSTK_ESP(task)		(task_pt_regs(task)->sp)
+ 
+ #else
+ /*
+  * User space process size. 47bits minus one guard page.
+  */
+-#define TASK_SIZE64	(0x800000000000UL - 4096)
++#define TASK_SIZE64	((1UL << 47) - PAGE_SIZE)
+ 
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+  */
+-#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
+-			   0xc0000000 : 0xFFFFe000)
++#define IA32_PAGE_OFFSET	((current->personality & ADDR_LIMIT_3GB) ? \
++					0xc0000000 : 0xFFFFe000)
+ 
+-#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? \
+-				 IA32_PAGE_OFFSET : TASK_SIZE64)
+-#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? \
+-				  IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \
++					IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \
++					IA32_PAGE_OFFSET : TASK_SIZE64)
+ 
+ #define STACK_TOP		TASK_SIZE
+ #define STACK_TOP_MAX		TASK_SIZE64
+@@ -761,33 +838,32 @@ extern unsigned long thread_saved_pc(str
+ 	.x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+ }
+ 
+-#define start_thread(regs, new_rip, new_rsp) do { 			     \
+-	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));  \
+-	load_gs_index(0);						     \
+-	(regs)->ip = (new_rip);						     \
+-	(regs)->sp = (new_rsp);						     \
+-	write_pda(oldrsp, (new_rsp));					     \
+-	(regs)->cs = __USER_CS;						     \
+-	(regs)->ss = __USER_DS;						     \
+-	(regs)->flags = 0x200;						     \
+-	set_fs(USER_DS);						     \
+-} while (0)
+-
+ /*
+  * Return saved PC of a blocked thread.
+  * What is this good for? it will be always the scheduler or ret_from_fork.
+  */
+-#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8))
++#define thread_saved_pc(t)	(*(unsigned long *)((t)->thread.sp - 8))
+ 
+-#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
+-#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
++#define task_pt_regs(tsk)	((struct pt_regs *)(tsk)->thread.sp0 - 1)
++#define KSTK_ESP(tsk)		-1 /* sorry. doesn't work for syscall. */
+ #endif /* CONFIG_X86_64 */
+ 
+-/* This decides where the kernel will search for a free chunk of vm
++extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
++					       unsigned long new_sp);
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+  */
+ #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+ 
+-#define KSTK_EIP(task) (task_pt_regs(task)->ip)
++#define KSTK_EIP(task)		(task_pt_regs(task)->ip)
++
++/* Get/set a process' ability to use the timestamp counter instruction */
++#define GET_TSC_CTL(adr)	get_tsc_mode((adr))
++#define SET_TSC_CTL(val)	set_tsc_mode((val))
++
++extern int get_tsc_mode(unsigned long adr);
++extern int set_tsc_mode(unsigned int val);
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:13:24.000000000 +0100
+@@ -1,5 +1,224 @@
+-#ifdef CONFIG_X86_32
+-# include "smp_32.h"
++#ifndef _ASM_X86_SMP_H_
++#define _ASM_X86_SMP_H_
++#ifndef __ASSEMBLY__
++#include <linux/cpumask.h>
++#include <linux/init.h>
++#include <asm/percpu.h>
++
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <asm/mpspec.h>
++# include <asm/apic.h>
++# ifdef CONFIG_X86_IO_APIC
++#  include <asm/io_apic.h>
++# endif
++#endif
++#include <asm/pda.h>
++#include <asm/thread_info.h>
++
++#define cpu_callout_map cpu_possible_map
++extern cpumask_t cpu_initialized;
++#define cpu_callin_map cpu_possible_map
++
++extern void (*mtrr_hook)(void);
++extern void zap_low_mappings(void);
++
++extern int smp_num_siblings;
++extern unsigned int num_processors;
++extern cpumask_t cpu_initialized;
++
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
++extern u16 x86_cpu_to_apicid_init[];
++extern u16 x86_bios_cpu_apicid_init[];
++extern void *x86_cpu_to_apicid_early_ptr;
++extern void *x86_bios_cpu_apicid_early_ptr;
++#else
++#define x86_cpu_to_apicid_early_ptr NULL
++#define x86_bios_cpu_apicid_early_ptr NULL
++#endif
++
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(u16, cpu_llc_id);
++DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
++DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
++
++#ifdef CONFIG_SMP
++
++#ifndef CONFIG_XEN
++
++/* Static state in head.S used to set up a CPU */
++extern struct {
++	void *sp;
++	unsigned short ss;
++} stack_start;
++
++struct smp_ops {
++	void (*smp_prepare_boot_cpu)(void);
++	void (*smp_prepare_cpus)(unsigned max_cpus);
++	int (*cpu_up)(unsigned cpu);
++	void (*smp_cpus_done)(unsigned max_cpus);
++
++	void (*smp_send_stop)(void);
++	void (*smp_send_reschedule)(int cpu);
++	int (*smp_call_function_mask)(cpumask_t mask,
++				      void (*func)(void *info), void *info,
++				      int wait);
++};
++
++/* Globals due to paravirt */
++extern void set_cpu_sibling_map(int cpu);
++
++extern struct smp_ops smp_ops;
++
++static inline void smp_send_stop(void)
++{
++	smp_ops.smp_send_stop();
++}
++
++static inline void smp_prepare_boot_cpu(void)
++{
++	smp_ops.smp_prepare_boot_cpu();
++}
++
++static inline void smp_prepare_cpus(unsigned int max_cpus)
++{
++	smp_ops.smp_prepare_cpus(max_cpus);
++}
++
++static inline void smp_cpus_done(unsigned int max_cpus)
++{
++	smp_ops.smp_cpus_done(max_cpus);
++}
++
++static inline int __cpu_up(unsigned int cpu)
++{
++	return smp_ops.cpu_up(cpu);
++}
++
++static inline void smp_send_reschedule(int cpu)
++{
++	smp_ops.smp_send_reschedule(cpu);
++}
++
++static inline int smp_call_function_mask(cpumask_t mask,
++					 void (*func) (void *info), void *info,
++					 int wait)
++{
++	return smp_ops.smp_call_function_mask(mask, func, info, wait);
++}
++
++void native_smp_prepare_boot_cpu(void);
++void native_smp_prepare_cpus(unsigned int max_cpus);
++void native_smp_cpus_done(unsigned int max_cpus);
++int native_cpu_up(unsigned int cpunum);
++
++#else /* CONFIG_XEN */
++
++void xen_smp_send_stop(void);
++void xen_smp_send_reschedule(int cpu);
++int xen_smp_call_function_mask(cpumask_t mask,
++			       void (*func) (void *info), void *info,
++			       int wait);
++
++#define smp_send_stop		xen_smp_send_stop
++#define smp_send_reschedule	xen_smp_send_reschedule
++#define smp_call_function_mask	xen_smp_call_function_mask
++
++extern void prefill_possible_map(void);
++
++#endif /* CONFIG_XEN */
++
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
++
++extern void prefill_possible_map(void);
++
++void smp_store_cpu_info(int id);
++#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
++
++/* We don't mark CPUs online until __cpu_up(), so we need another measure */
++static inline int num_booting_cpus(void)
++{
++	return cpus_weight(cpu_callout_map);
++}
++#endif /* CONFIG_SMP */
++
++extern unsigned disabled_cpus __cpuinitdata;
++
++#ifdef CONFIG_X86_32_SMP
++/*
++ * This function is needed by all SMP systems. It must _always_ be valid
++ * from the initial startup. We map APIC_BASE very early in page_setup(),
++ * so this is correct in the x86 case.
++ */
++DECLARE_PER_CPU(int, cpu_number);
++#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
++#define safe_smp_processor_id() smp_processor_id()
++
++#elif defined(CONFIG_X86_64_SMP)
++#define raw_smp_processor_id()	read_pda(cpunumber)
++
++#define stack_smp_processor_id()					\
++({								\
++	struct thread_info *ti;						\
++	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->cpu;							\
++})
++#define safe_smp_processor_id()		smp_processor_id()
++
++#else /* !CONFIG_X86_32_SMP && !CONFIG_X86_64_SMP */
++#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
++#define safe_smp_processor_id()		0
++#define stack_smp_processor_id() 	0
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC
++
++static inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++}
++
++#ifndef CONFIG_X86_64
++static inline unsigned int read_apic_id(void)
++{
++	return *(u32 *)(APIC_BASE + APIC_ID);
++}
+ #else
+-# include "smp_64.h"
++extern unsigned int read_apic_id(void);
++#endif
++
++
++# ifdef APIC_DEFINITION
++extern int hard_smp_processor_id(void);
++# else
++#  include <mach_apicdef.h>
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(read_apic_id());
++}
++# endif /* APIC_DEFINITION */
++
++#else /* CONFIG_X86_LOCAL_APIC */
++
++# ifndef CONFIG_SMP
++#  define hard_smp_processor_id()	0
++# endif
++
++#endif /* CONFIG_X86_LOCAL_APIC */
++
++#ifdef CONFIG_HOTPLUG_CPU
++extern void cpu_exit_clear(void);
++extern void cpu_uninit(void);
++#endif
++
++extern void smp_alloc_memory(void);
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
++#endif /* __ASSEMBLY__ */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-20 11:12:22.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,174 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#ifndef __ASSEMBLY__
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#ifdef CONFIG_X86_LOCAL_APIC
+-# include <asm/mpspec.h>
+-# include <asm/apic.h>
+-# ifdef CONFIG_X86_IO_APIC
+-#  include <asm/io_apic.h>
+-# endif
+-#endif
+-
+-#define cpu_callout_map cpu_possible_map
+-#define cpu_callin_map cpu_possible_map
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern void (*mtrr_hook) (void);
+-extern void zap_low_mappings (void);
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
+-
+-#ifdef CONFIG_HOTPLUG_CPU
+-extern void cpu_exit_clear(void);
+-extern void cpu_uninit(void);
+-#endif
+-
+-#ifdef CONFIG_SMP
+-
+-#ifndef CONFIG_XEN
+-
+-/* Globals due to paravirt */
+-extern void set_cpu_sibling_map(int cpu);
+-
+-struct smp_ops
+-{
+-	void (*smp_prepare_boot_cpu)(void);
+-	void (*smp_prepare_cpus)(unsigned max_cpus);
+-	int (*cpu_up)(unsigned cpu);
+-	void (*smp_cpus_done)(unsigned max_cpus);
+-
+-	void (*smp_send_stop)(void);
+-	void (*smp_send_reschedule)(int cpu);
+-	int (*smp_call_function_mask)(cpumask_t mask,
+-				      void (*func)(void *info), void *info,
+-				      int wait);
+-};
+-
+-extern struct smp_ops smp_ops;
+-
+-static inline void smp_prepare_boot_cpu(void)
+-{
+-	smp_ops.smp_prepare_boot_cpu();
+-}
+-static inline void smp_prepare_cpus(unsigned int max_cpus)
+-{
+-	smp_ops.smp_prepare_cpus(max_cpus);
+-}
+-static inline int __cpu_up(unsigned int cpu)
+-{
+-	return smp_ops.cpu_up(cpu);
+-}
+-static inline void smp_cpus_done(unsigned int max_cpus)
+-{
+-	smp_ops.smp_cpus_done(max_cpus);
+-}
+-
+-static inline void smp_send_stop(void)
+-{
+-	smp_ops.smp_send_stop();
+-}
+-static inline void smp_send_reschedule(int cpu)
+-{
+-	smp_ops.smp_send_reschedule(cpu);
+-}
+-static inline int smp_call_function_mask(cpumask_t mask,
+-					 void (*func) (void *info), void *info,
+-					 int wait)
+-{
+-	return smp_ops.smp_call_function_mask(mask, func, info, wait);
+-}
+-
+-void native_smp_prepare_boot_cpu(void);
+-void native_smp_prepare_cpus(unsigned int max_cpus);
+-int native_cpu_up(unsigned int cpunum);
+-void native_smp_cpus_done(unsigned int max_cpus);
+-
+-#else /* CONFIG_XEN */
+-
+-void xen_smp_send_stop(void);
+-void xen_smp_send_reschedule(int cpu);
+-int xen_smp_call_function_mask(cpumask_t mask,
+-			       void (*func) (void *info), void *info,
+-			       int wait);
+-
+-#define smp_send_stop		xen_smp_send_stop
+-#define smp_send_reschedule	xen_smp_send_reschedule
+-#define smp_call_function_mask	xen_smp_call_function_mask
+-
+-extern void prefill_possible_map(void);
+-
+-#endif /* CONFIG_XEN */
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-
+-/*
+- * This function is needed by all SMP systems. It must _always_ be valid
+- * from the initial startup. We map APIC_BASE very early in page_setup(),
+- * so this is correct in the x86 case.
+- */
+-DECLARE_PER_CPU(int, cpu_number);
+-#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+-
+-#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+-
+-#define safe_smp_processor_id() smp_processor_id()
+-
+-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+-static inline int num_booting_cpus(void)
+-{
+-	return cpus_weight(cpu_callout_map);
+-}
+-
+-#else /* CONFIG_SMP */
+-
+-#define safe_smp_processor_id()		0
+-#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
+-
+-#endif /* !CONFIG_SMP */
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-# ifdef APIC_DEFINITION
+-extern int hard_smp_processor_id(void);
+-# else
+-#  include <mach_apicdef.h>
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-# endif /* APIC_DEFINITION */
+-
+-#else /* CONFIG_X86_LOCAL_APIC */
+-
+-# ifndef CONFIG_SMP
+-#  define hard_smp_processor_id()	0
+-# endif
+-
+-#endif /* CONFIG_X86_LOCAL_APIC */
+-
+-#endif /* !ASSEMBLY */
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,103 +0,0 @@
+-#ifndef __ASM_SMP_H
+-#define __ASM_SMP_H
+-
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#include <asm/apic.h>
+-#ifdef CONFIG_X86_IO_APIC
+-#include <asm/io_apic.h>
+-#endif
+-#include <asm/mpspec.h>
+-#endif
+-#include <asm/pda.h>
+-#include <asm/thread_info.h>
+-
+-extern cpumask_t cpu_initialized;
+-
+-extern int smp_num_siblings;
+-extern unsigned int num_processors;
+-
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+-
+-extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+-				  void *info, int wait);
+-
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u16, cpu_llc_id);
+-DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+-DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static inline int cpu_present_to_apicid(int mps_cpu)
+-{
+-	if (cpu_present(mps_cpu))
+-		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+-	else
+-		return BAD_APICID;
+-}
+-#endif
+-
+-#ifdef CONFIG_SMP
+-
+-#define SMP_TRAMPOLINE_BASE 0x6000
+-
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-extern void prefill_possible_map(void);
+-extern unsigned __cpuinitdata disabled_cpus;
+-
+-#define raw_smp_processor_id()	read_pda(cpunumber)
+-#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+-
+-#define stack_smp_processor_id()					\
+-	({								\
+-	struct thread_info *ti;						\
+-	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+-	ti->cpu;							\
+-})
+-
+-/*
+- * On x86 all CPUs are mapped 1:1 to the APIC space. This simplifies
+- * scheduling and IPI sending and compresses data structures.
+- */
+-static inline int num_booting_cpus(void)
+-{
+-	return cpus_weight(cpu_possible_map);
+-}
+-
+-extern void smp_send_reschedule(int cpu);
+-
+-#else /* CONFIG_SMP */
+-
+-extern unsigned int boot_cpu_id;
+-#define cpu_physical_id(cpu)	boot_cpu_id
+-#define stack_smp_processor_id() 0
+-
+-#endif /* !CONFIG_SMP */
+-
+-#define safe_smp_processor_id()		smp_processor_id()
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+-}
+-
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+-}
+-#endif
+-
+-#endif
+-
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 14:20:36.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 11:33:34.000000000 +0100
+@@ -87,7 +87,7 @@ void xen_spin_kick(raw_spinlock_t *, uns
+ 	    : "memory", "cc")
+ 
+ 
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp, new;
+ 
+@@ -106,7 +106,7 @@ static inline int __raw_spin_trylock(raw
+ 	return tmp;
+ }
+ 
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token;
+ 	unsigned char kick;
+@@ -153,7 +153,7 @@ static inline void __raw_spin_unlock(raw
+ 		    : "memory", "cc"); \
+ 	} while (0)
+ 
+-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp;
+ 	int new;
+@@ -175,7 +175,7 @@ static inline int __raw_spin_trylock(raw
+ 	return tmp;
+ }
+ 
+-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token, tmp;
+ 	bool kick;
+@@ -195,19 +195,19 @@ static inline void __raw_spin_unlock(raw
+ 
+ static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+ {
+-	int tmp = *(volatile signed int *)(&(lock)->slock);
++	int tmp = ACCESS_ONCE(lock->slock);
+ 
+ 	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+ }
+ 
+ static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+ {
+-	int tmp = *(volatile signed int *)(&(lock)->slock);
++	int tmp = ACCESS_ONCE(lock->slock);
+ 
+ 	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+ }
+ 
+-static inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token, count;
+ 	bool free;
+@@ -222,8 +222,8 @@ static inline void __raw_spin_lock(raw_s
+ 	} while (unlikely(!count) && !xen_spin_wait(lock, token));
+ }
+ 
+-static inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
+-					 unsigned long flags)
++static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
++						  unsigned long flags)
+ {
+ 	unsigned int token, count;
+ 	bool free;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/swiotlb.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/swiotlb.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,5 +1,4 @@
+-#ifdef CONFIG_X86_32
+-# include "swiotlb_32.h"
+-#else
+-# include_next <asm/swiotlb.h>
+-#endif
++#include_next <asm/swiotlb.h>
++
++dma_addr_t swiotlb_map_single_phys(struct device *, phys_addr_t, size_t size,
++				   int dir);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:32.000000000 +0100
+@@ -28,22 +28,44 @@ struct task_struct *__switch_to(struct t
+  * Saving eflags is important. It switches not only IOPL between tasks,
+  * it also protects other tasks from NT leaking through sysenter etc.
+  */
+-#define switch_to(prev, next, last) do {				\
+-	unsigned long esi, edi;						\
+-	asm volatile("pushfl\n\t"		/* Save flags */	\
+-		     "pushl %%ebp\n\t"					\
+-		     "movl %%esp,%0\n\t"	/* save ESP */		\
+-		     "movl %5,%%esp\n\t"	/* restore ESP */	\
+-		     "movl $1f,%1\n\t"		/* save EIP */		\
+-		     "pushl %6\n\t"		/* restore EIP */	\
+-		     "jmp __switch_to\n"				\
++#define switch_to(prev, next, last)					\
++do {									\
++	/*								\
++	 * Context-switching clobbers all registers, so we clobber	\
++	 * them explicitly, via unused output variables.		\
++	 * (EAX and EBP is not listed because EBP is saved/restored	\
++	 * explicitly for wchan access and EAX is the return value of	\
++	 * __switch_to())						\
++	 */								\
++	unsigned long ebx, ecx, edx, esi, edi;				\
++									\
++	asm volatile("pushfl\n\t"		/* save    flags */	\
++		     "pushl %%ebp\n\t"		/* save    EBP   */	\
++		     "movl %%esp,%[prev_sp]\n\t"	/* save    ESP   */ \
++		     "movl %[next_sp],%%esp\n\t"	/* restore ESP   */ \
++		     "movl $1f,%[prev_ip]\n\t"	/* save    EIP   */	\
++		     "pushl %[next_ip]\n\t"	/* restore EIP   */	\
++		     "jmp __switch_to\n"	/* regparm call  */	\
+ 		     "1:\t"						\
+-		     "popl %%ebp\n\t"					\
+-		     "popfl"						\
+-		     :"=m" (prev->thread.sp), "=m" (prev->thread.ip),	\
+-		      "=a" (last), "=S" (esi), "=D" (edi)		\
+-		     :"m" (next->thread.sp), "m" (next->thread.ip),	\
+-		      "2" (prev), "d" (next));				\
++		     "popl %%ebp\n\t"		/* restore EBP   */	\
++		     "popfl\n"			/* restore flags */	\
++									\
++		     /* output parameters */				\
++		     : [prev_sp] "=m" (prev->thread.sp),		\
++		       [prev_ip] "=m" (prev->thread.ip),		\
++		       "=a" (last),					\
++									\
++		       /* clobbered output registers: */		\
++		       "=b" (ebx), "=c" (ecx), "=d" (edx),		\
++		       "=S" (esi), "=D" (edi)				\
++		       							\
++		       /* input parameters: */				\
++		     : [next_sp]  "m" (next->thread.sp),		\
++		       [next_ip]  "m" (next->thread.ip),		\
++		       							\
++		       /* regparm parameters for __switch_to(): */	\
++		       [prev]     "a" (prev),				\
++		       [next]     "d" (next));				\
+ } while (0)
+ 
+ /*
+@@ -123,30 +145,29 @@ extern void load_gs_index(unsigned);
+  */
+ #define loadsegment(seg, value)			\
+ 	asm volatile("\n"			\
+-		"1:\t"				\
+-		"movl %k0,%%" #seg "\n"		\
+-		"2:\n"				\
+-		".section .fixup,\"ax\"\n"	\
+-		"3:\t"				\
+-		"movl %k1, %%" #seg "\n\t"	\
+-		"jmp 2b\n"			\
+-		".previous\n"			\
+-		_ASM_EXTABLE(1b,3b)		\
+-		: :"r" (value), "r" (0))
++		     "1:\t"			\
++		     "movl %k0,%%" #seg "\n"	\
++		     "2:\n"			\
++		     ".section .fixup,\"ax\"\n"	\
++		     "3:\t"			\
++		     "movl %k1, %%" #seg "\n\t"	\
++		     "jmp 2b\n"			\
++		     ".previous\n"		\
++		     _ASM_EXTABLE(1b,3b)	\
++		     : :"r" (value), "r" (0))
+ 
+ 
+ /*
+  * Save a segment register away
+  */
+-#define savesegment(seg, value) \
++#define savesegment(seg, value)				\
+ 	asm volatile("mov %%" #seg ",%0":"=rm" (value))
+ 
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ 	unsigned long __limit;
+-	__asm__("lsll %1,%0"
+-		:"=r" (__limit):"r" (segment));
+-	return __limit+1;
++	asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
++	return __limit + 1;
+ }
+ 
+ static inline void xen_clts(void)
+@@ -171,13 +192,13 @@ static unsigned long __force_order;
+ static inline unsigned long xen_read_cr0(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr0,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+ static inline void xen_write_cr0(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr0": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+ }
+ 
+ #define xen_read_cr2() (current_vcpu_info()->arch.cr2)
+@@ -186,7 +207,7 @@ static inline void xen_write_cr0(unsigne
+ static inline unsigned long xen_read_cr3(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr3,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+ #ifdef CONFIG_X86_32
+ 	return mfn_to_pfn(xen_cr3_to_pfn(val)) << PAGE_SHIFT;
+ #else
+@@ -201,13 +222,13 @@ static inline void xen_write_cr3(unsigne
+ #else
+ 	val = phys_to_machine(val);
+ #endif
+-	asm volatile("mov %0,%%cr3": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+ }
+ 
+ static inline unsigned long xen_read_cr4(void)
+ {
+ 	unsigned long val;
+-	asm volatile("mov %%cr4,%0\n\t" :"=r" (val), "=m" (__force_order));
++	asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+ 	return val;
+ }
+ 
+@@ -215,7 +236,7 @@ static inline unsigned long xen_read_cr4
+ 
+ static inline void xen_write_cr4(unsigned long val)
+ {
+-	asm volatile("mov %0,%%cr4": :"r" (val), "m" (__force_order));
++	asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+ }
+ 
+ #ifdef CONFIG_X86_64
+@@ -234,6 +255,7 @@ static inline void xen_wbinvd(void)
+ {
+ 	asm volatile("wbinvd": : :"memory");
+ }
++
+ #define read_cr0()	(xen_read_cr0())
+ #define write_cr0(x)	(xen_write_cr0(x))
+ #define read_cr2()	(xen_read_cr2())
+@@ -260,7 +282,7 @@ static inline void clflush(volatile void
+ 	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+ }
+ 
+-#define nop() __asm__ __volatile__ ("nop")
++#define nop() asm volatile ("nop")
+ 
+ void disable_hlt(void);
+ void enable_hlt(void);
+@@ -280,16 +302,7 @@ void default_idle(void);
+  */
+ #ifdef CONFIG_X86_32
+ /*
+- * For now, "wmb()" doesn't actually do anything, as all
+- * Intel CPU's follow what Intel calls a *Processor Order*,
+- * in which all writes are seen in the program order even
+- * outside the CPU.
+- *
+- * I expect future Intel CPU's to have a weaker ordering,
+- * but I'd also expect them to finally get their act together
+- * and add some real memory barriers if so.
+- *
+- * Some non intel clones support out of order store. wmb() ceases to be a
++ * Some non-Intel clones support out of order store. wmb() ceases to be a
+  * nop for these.
+  */
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+@@ -368,7 +381,7 @@ void default_idle(void);
+ # define smp_wmb()	barrier()
+ #endif
+ #define smp_read_barrier_depends()	read_barrier_depends()
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+ #else
+ #define smp_mb()	barrier()
+ #define smp_rmb()	barrier()
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:32.000000000 +0100
+@@ -86,8 +86,7 @@ static inline void flush_tlb_range(struc
+ #define TLBSTATE_LAZY	2
+ 
+ #ifdef CONFIG_X86_32
+-struct tlb_state
+-{
++struct tlb_state {
+ 	struct mm_struct *active_mm;
+ 	int state;
+ 	char __cacheline_padding[L1_CACHE_BYTES-8];
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/vga.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/vga.h	2009-11-06 10:51:32.000000000 +0100
+@@ -12,9 +12,9 @@
+  *	access the videoram directly without any black magic.
+  */
+ 
+-#define VGA_MAP_MEM(x,s) (unsigned long)isa_bus_to_virt(x)
++#define VGA_MAP_MEM(x, s) (unsigned long)isa_bus_to_virt(x)
+ 
+ #define vga_readb(x) (*(x))
+-#define vga_writeb(x,y) (*(y) = (x))
++#define vga_writeb(x, y) (*(y) = (x))
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/xor_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor_64.h	2009-11-06 10:51:32.000000000 +0100
+@@ -1,20 +1,23 @@
+ /*
+- * x86-64 changes / gcc fixes from Andi Kleen. 
++ * x86-64 changes / gcc fixes from Andi Kleen.
+  * Copyright 2002 Andi Kleen, SuSE Labs.
+  *
+  * This hasn't been optimized for the hammer yet, but there are likely
+  * no advantages to be gotten from x86-64 here anyways.
+  */
+ 
+-typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
++typedef struct {
++	unsigned long a, b;
++} __attribute__((aligned(16))) xmm_store_t;
+ 
+-/* Doesn't use gcc to save the XMM registers, because there is no easy way to 
++/* Doesn't use gcc to save the XMM registers, because there is no easy way to
+    tell it to do a clts before the register saving. */
+-#define XMMS_SAVE do {				\
++#define XMMS_SAVE				\
++do {						\
+ 	preempt_disable();			\
+ 	if (!(current_thread_info()->status & TS_USEDFPU))	\
+ 		clts();				\
+-	__asm__ __volatile__ ( 			\
++	asm volatile(				\
+ 		"movups %%xmm0,(%1)	;\n\t"	\
+ 		"movups %%xmm1,0x10(%1)	;\n\t"	\
+ 		"movups %%xmm2,0x20(%1)	;\n\t"	\
+@@ -22,10 +25,11 @@ typedef struct { unsigned long a,b; } __
+ 		: "=&r" (cr0)			\
+ 		: "r" (xmm_save) 		\
+ 		: "memory");			\
+-} while(0)
++} while (0)
+ 
+-#define XMMS_RESTORE do {			\
+-	asm volatile (				\
++#define XMMS_RESTORE				\
++do {						\
++	asm volatile(				\
+ 		"sfence			;\n\t"	\
+ 		"movups (%1),%%xmm0	;\n\t"	\
+ 		"movups 0x10(%1),%%xmm1	;\n\t"	\
+@@ -37,72 +41,72 @@ typedef struct { unsigned long a,b; } __
+ 	if (!(current_thread_info()->status & TS_USEDFPU))	\
+ 		stts();				\
+ 	preempt_enable();			\
+-} while(0)
++} while (0)
+ 
+ #define OFFS(x)		"16*("#x")"
+ #define PF_OFFS(x)	"256+16*("#x")"
+ #define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%[p1])		;\n"
+-#define LD(x,y)		"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
+-#define ST(x,y)		"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
++#define LD(x, y)	"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
++#define ST(x, y)	"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
+ #define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%[p2])		;\n"
+ #define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%[p3])		;\n"
+ #define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%[p4])		;\n"
+ #define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%[p5])		;\n"
+ #define PF5(x)		"	prefetchnta "PF_OFFS(x)"(%[p6])		;\n"
+-#define XO1(x,y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
+-#define XO2(x,y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
+-#define XO3(x,y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
+-#define XO4(x,y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
+-#define XO5(x,y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
++#define XO1(x, y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
++#define XO2(x, y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
++#define XO3(x, y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
++#define XO4(x, y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
++#define XO5(x, y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
+ 
+ 
+ static void
+ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+ {
+-        unsigned int lines = bytes >> 8;
++	unsigned int lines = bytes >> 8;
+ 	unsigned long cr0;
+ 	xmm_store_t xmm_save[4];
+ 
+ 	XMMS_SAVE;
+ 
+-        asm volatile (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+-		LD(i,0)					\
+-			LD(i+1,1)			\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF1(i + 2)		\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
+ 		"		decl %[cnt] ; jnz 1b"
+ 	: [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
+-	: [inc] "r" (256UL) 
+-        : "memory");
++	: [inc] "r" (256UL)
++	: "memory");
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -117,52 +121,52 @@ xor_sse_3(unsigned long bytes, unsigned 
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)					\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF2(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]          ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]          ;\n"
++	"       addq %[inc], %[p3]           ;\n"
+ 		"		decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+r" (lines),
+ 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+ 	: [inc] "r" (256UL)
+-	: "memory"); 
++	: "memory");
+ 	XMMS_RESTORE;
+ }
+ 
+@@ -171,64 +175,64 @@ xor_sse_4(unsigned long bytes, unsigned 
+ 	  unsigned long *p3, unsigned long *p4)
+ {
+ 	unsigned int lines = bytes >> 8;
+-	xmm_store_t xmm_save[4]; 
++	xmm_store_t xmm_save[4];
+ 	unsigned long cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++				PF2(i + 2)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
+-		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF3(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
++		XO3(i, 0)				\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
+-        "       addq %[inc], %[p4]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p4]           ;\n"
+ 	"	decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+c" (lines),
+ 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+ 	: [inc] "r" (256UL)
+-        : "memory" );
++	: "memory" );
+ 
+ 	XMMS_RESTORE;
+ }
+@@ -237,70 +241,70 @@ static void
+ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+ 	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
+ {
+-        unsigned int lines = bytes >> 8;
++	unsigned int lines = bytes >> 8;
+ 	xmm_store_t xmm_save[4];
+ 	unsigned long cr0;
+ 
+ 	XMMS_SAVE;
+ 
+-        __asm__ __volatile__ (
++	asm volatile(
+ #undef BLOCK
+ #define BLOCK(i) \
+ 		PF1(i)					\
+-				PF1(i+2)		\
+-		LD(i,0)					\
+-			LD(i+1,1)			\
+-				LD(i+2,2)		\
+-					LD(i+3,3)	\
++				PF1(i + 2)		\
++		LD(i, 0)				\
++			LD(i + 1, 1)			\
++				LD(i + 2, 2)		\
++					LD(i + 3, 3)	\
+ 		PF2(i)					\
+-				PF2(i+2)		\
+-		XO1(i,0)				\
+-			XO1(i+1,1)			\
+-				XO1(i+2,2)		\
+-					XO1(i+3,3)	\
++				PF2(i + 2)		\
++		XO1(i, 0)				\
++			XO1(i + 1, 1)			\
++				XO1(i + 2, 2)		\
++					XO1(i + 3, 3)	\
+ 		PF3(i)					\
+-				PF3(i+2)		\
+-		XO2(i,0)				\
+-			XO2(i+1,1)			\
+-				XO2(i+2,2)		\
+-					XO2(i+3,3)	\
++				PF3(i + 2)		\
++		XO2(i, 0)				\
++			XO2(i + 1, 1)			\
++				XO2(i + 2, 2)		\
++					XO2(i + 3, 3)	\
+ 		PF4(i)					\
+-				PF4(i+2)		\
+-		PF0(i+4)				\
+-				PF0(i+6)		\
+-		XO3(i,0)				\
+-			XO3(i+1,1)			\
+-				XO3(i+2,2)		\
+-					XO3(i+3,3)	\
+-		XO4(i,0)				\
+-			XO4(i+1,1)			\
+-				XO4(i+2,2)		\
+-					XO4(i+3,3)	\
+-		ST(i,0)					\
+-			ST(i+1,1)			\
+-				ST(i+2,2)		\
+-					ST(i+3,3)	\
++				PF4(i + 2)		\
++		PF0(i + 4)				\
++				PF0(i + 6)		\
++		XO3(i, 0)				\
++			XO3(i + 1, 1)			\
++				XO3(i + 2, 2)		\
++					XO3(i + 3, 3)	\
++		XO4(i, 0)				\
++			XO4(i + 1, 1)			\
++				XO4(i + 2, 2)		\
++					XO4(i + 3, 3)	\
++		ST(i, 0)				\
++			ST(i + 1, 1)			\
++				ST(i + 2, 2)		\
++					ST(i + 3, 3)	\
+ 
+ 
+ 		PF0(0)
+ 				PF0(2)
+ 
+ 	" .align 32			;\n"
+-        " 1:                            ;\n"
++	" 1:                            ;\n"
+ 
+ 		BLOCK(0)
+ 		BLOCK(4)
+ 		BLOCK(8)
+ 		BLOCK(12)
+ 
+-        "       addq %[inc], %[p1]           ;\n"
+-        "       addq %[inc], %[p2]           ;\n"
+-        "       addq %[inc], %[p3]           ;\n"
+-        "       addq %[inc], %[p4]           ;\n"
+-        "       addq %[inc], %[p5]           ;\n"
++	"       addq %[inc], %[p1]           ;\n"
++	"       addq %[inc], %[p2]           ;\n"
++	"       addq %[inc], %[p3]           ;\n"
++	"       addq %[inc], %[p4]           ;\n"
++	"       addq %[inc], %[p5]           ;\n"
+ 	"	decl %[cnt] ; jnz 1b"
+ 	: [cnt] "+c" (lines),
+-  	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4), 
++	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
+ 	  [p5] "+r" (p5)
+ 	: [inc] "r" (256UL)
+ 	: "memory");
+@@ -309,18 +313,18 @@ xor_sse_5(unsigned long bytes, unsigned 
+ }
+ 
+ static struct xor_block_template xor_block_sse = {
+-        .name = "generic_sse",
+-        .do_2 = xor_sse_2,
+-        .do_3 = xor_sse_3,
+-        .do_4 = xor_sse_4,
+-        .do_5 = xor_sse_5,
++	.name = "generic_sse",
++	.do_2 = xor_sse_2,
++	.do_3 = xor_sse_3,
++	.do_4 = xor_sse_4,
++	.do_5 = xor_sse_5,
+ };
+ 
+ #undef XOR_TRY_TEMPLATES
+-#define XOR_TRY_TEMPLATES				\
+-	do {						\
+-		xor_speed(&xor_block_sse);	\
+-	} while (0)
++#define XOR_TRY_TEMPLATES			\
++do {						\
++	xor_speed(&xor_block_sse);		\
++} while (0)
+ 
+ /* We force the use of the SSE xor block because it can write around L2.
+    We may also be able to load into the L1 only depending on how the cpu
+--- head-2010-01-18.orig/arch/x86/include/asm/scatterlist.h	2010-01-19 10:18:46.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/scatterlist.h	2009-11-06 10:51:32.000000000 +0100
+@@ -3,6 +3,10 @@
+ 
+ #define ISA_DMA_THRESHOLD (0x00ffffff)
+ 
++#ifdef CONFIG_X86_XEN
++# define sg_dma_len(sg)		((sg)->dma_length)
++#endif
++
+ #include <asm-generic/scatterlist.h>
+ 
+ #endif /* _ASM_X86_SCATTERLIST_H */
+--- head-2010-01-18.orig/include/linux/page-flags.h	2009-12-16 11:50:48.000000000 +0100
++++ head-2010-01-18/include/linux/page-flags.h	2009-12-16 11:51:06.000000000 +0100
+@@ -351,29 +351,28 @@ static inline void SetPageUptodate(struc
+ 
+ CLEARPAGEFLAG(Uptodate, uptodate)
+ 
+-#define PageForeign(page)	test_bit(PG_foreign, &(page)->flags)
+-#define SetPageForeign(_page, dtor) do {		\
+-	set_bit(PG_foreign, &(_page)->flags);		\
+-	BUG_ON((dtor) == (void (*)(struct page *, unsigned int))0); \
+-	(_page)->index = (long)(dtor);			\
+-} while (0)
+-#define ClearPageForeign(page) do {			\
+-	clear_bit(PG_foreign, &(page)->flags);		\
+-	(page)->index = 0;				\
+-} while (0)
+-#define PageForeignDestructor(_page, order)		\
+-	((void (*)(struct page *, unsigned int))(_page)->index)(_page, order)
+-
+-#if 0
+-#define PageNetback(page)       test_bit(PG_netback, &(page)->flags)
+-#define SetPageNetback(page)    set_bit(PG_netback, &(page)->flags)
+-#define ClearPageNetback(page)  clear_bit(PG_netback, &(page)->flags)
++#ifdef CONFIG_XEN
++TESTPAGEFLAG(Foreign, foreign)
++static inline void SetPageForeign(struct page *page,
++				  void (*dtor)(struct page *, unsigned int))
++{
++	BUG_ON(!dtor);
++	set_bit(PG_foreign, &page->flags);
++	page->index = (long)dtor;
++}
++static inline void ClearPageForeign(struct page *page)
++{
++	clear_bit(PG_foreign, &page->flags);
++	page->index = 0;
++}
++static inline void PageForeignDestructor(struct page *page, unsigned int order)
++{
++	((void (*)(struct page *, unsigned int))page->index)(page, order);
++}
++/*PAGEFLAG(Netback, netback)*/
++PAGEFLAG(Blkback, blkback)
+ #endif
+ 
+-#define PageBlkback(page)       test_bit(PG_blkback, &(page)->flags)
+-#define SetPageBlkback(page)    set_bit(PG_blkback, &(page)->flags)
+-#define ClearPageBlkback(page)  clear_bit(PG_blkback, &(page)->flags)
+-
+ extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+ 
+ int test_clear_page_writeback(struct page *page);
+--- head-2010-01-18.orig/include/xen/balloon.h	2007-06-12 13:14:19.000000000 +0200
++++ head-2010-01-18/include/xen/balloon.h	2009-11-06 10:51:32.000000000 +0100
+@@ -31,9 +31,12 @@
+  * IN THE SOFTWARE.
+  */
+ 
+-#ifndef __ASM_BALLOON_H__
+-#define __ASM_BALLOON_H__
++#ifndef __XEN_BALLOON_H__
++#define __XEN_BALLOON_H__
+ 
++#include <linux/spinlock.h>
++
++#if !defined(CONFIG_PARAVIRT_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ /*
+  * Inform the balloon driver that it should allow some slop for device-driver
+  * memory activities.
+@@ -53,5 +56,6 @@ void balloon_release_driver_page(struct 
+ extern spinlock_t balloon_lock;
+ #define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
+ #define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
++#endif
+ 
+-#endif /* __ASM_BALLOON_H__ */
++#endif /* __XEN_BALLOON_H__ */
+--- head-2010-01-18.orig/include/xen/interface/grant_table.h	2010-01-04 12:17:40.000000000 +0100
++++ head-2010-01-18/include/xen/interface/grant_table.h	2010-01-04 12:39:36.000000000 +0100
+@@ -288,6 +288,7 @@ struct gnttab_map_grant_ref {
+     grant_handle_t handle;
+     uint64_t dev_bus_addr;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
+ typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
+ 
+@@ -311,6 +312,7 @@ struct gnttab_unmap_grant_ref {
+     /* OUT parameters. */
+     int16_t  status;              /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
+ typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+ 
+@@ -332,6 +334,7 @@ struct gnttab_setup_table {
+     int16_t  status;              /* GNTST_* */
+     XEN_GUEST_HANDLE(ulong) frame_list;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
+ typedef struct gnttab_setup_table gnttab_setup_table_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
+ 
+@@ -346,6 +349,7 @@ struct gnttab_dump_table {
+     /* OUT parameters. */
+     int16_t status;               /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
+ typedef struct gnttab_dump_table gnttab_dump_table_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
+ 
+@@ -366,6 +370,7 @@ struct gnttab_transfer {
+     /* OUT parameters. */
+     int16_t       status;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
+ typedef struct gnttab_transfer gnttab_transfer_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
+ 
+@@ -411,6 +416,7 @@ typedef struct gnttab_copy {
+     /* OUT parameters. */
+     int16_t       status;
+ } gnttab_copy_t;
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
+ DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
+ 
+ /*
+@@ -429,6 +435,7 @@ struct gnttab_query_size {
+     uint32_t max_nr_frames;
+     int16_t  status;              /* GNTST_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
+ typedef struct gnttab_query_size gnttab_query_size_t;
+ DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
+ 
+--- head-2010-01-18.orig/include/xen/interface/io/fbif.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/io/fbif.h	2009-11-06 10:51:32.000000000 +0100
+@@ -150,7 +150,12 @@ struct xenfb_page
+      * framebuffer with a max resolution of 12,800x10,240.  Should
+      * be enough for a while with room leftover for expansion.
+      */
++#ifndef CONFIG_PARAVIRT_XEN
+     unsigned long pd[256];
++#else
++	/* Two directory pages should be enough for a while. */
++	unsigned long pd[2];
++#endif
+ };
+ 
+ /*
+--- head-2010-01-18.orig/include/xen/interface/memory.h	2010-01-04 12:30:24.000000000 +0100
++++ head-2010-01-18/include/xen/interface/memory.h	2010-01-04 12:39:40.000000000 +0100
+@@ -85,7 +85,6 @@ struct xen_memory_reservation {
+      */
+     domid_t        domid;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+ typedef struct xen_memory_reservation xen_memory_reservation_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+ 
+@@ -171,7 +170,11 @@ struct xen_machphys_mfn_list {
+      * any large discontiguities in the machine address space, 2MB gaps in
+      * the machphys table will be represented by an MFN base of zero.
+      */
++#ifndef CONFIG_PARAVIRT_XEN
+     XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
++#else
++    ulong extent_start;
++#endif
+ 
+     /*
+      * Number of extents written to the above array. This will be smaller
+@@ -179,7 +182,6 @@ struct xen_machphys_mfn_list {
+      */
+     unsigned int nr_extents;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+ 
+@@ -221,7 +223,6 @@ struct xen_add_to_physmap {
+     /* GPFN where the source mapping page should appear. */
+     xen_pfn_t     gpfn;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+ typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+ 
+--- head-2010-01-18.orig/include/xen/interface/vcpu.h	2010-01-04 12:17:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/vcpu.h	2009-11-06 10:51:32.000000000 +0100
+@@ -87,6 +87,7 @@ struct vcpu_runstate_info {
+      */
+     uint64_t time[4];
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
+ typedef struct vcpu_runstate_info vcpu_runstate_info_t;
+ DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
+ 
+@@ -142,6 +143,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_register_ru
+ struct vcpu_set_periodic_timer {
+     uint64_t period_ns;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
+ typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+ DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+ 
+@@ -155,6 +157,7 @@ struct vcpu_set_singleshot_timer {
+     uint64_t timeout_abs_ns;   /* Absolute system time value in nanoseconds. */
+     uint32_t flags;            /* VCPU_SSHOTTMR_??? */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
+ typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+ DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+ 
+@@ -178,6 +181,7 @@ struct vcpu_register_vcpu_info {
+     uint32_t offset; /* offset within page */
+     uint32_t rsvd;   /* unused */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
+ typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
+ DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
+ 
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:51:32.000000000 +0100
+@@ -20,6 +20,7 @@
+ #include <linux/ctype.h>
+ #include <linux/init.h>
+ #include <linux/bootmem.h>
++#include <linux/iommu-helper.h>
+ #include <linux/highmem.h>
+ #include <asm/io.h>
+ #include <asm/pci.h>
+@@ -288,15 +289,6 @@ __sync_single(struct phys_addr buffer, c
+ 	}
+ }
+ 
+-static inline unsigned int is_span_boundary(unsigned int index,
+-					    unsigned int nslots,
+-					    unsigned long offset_slots,
+-					    unsigned long max_slots)
+-{
+-	unsigned long offset = (offset_slots + index) & (max_slots - 1);
+-	return offset + nslots > max_slots;
+-}
+-
+ /*
+  * Allocates bounce buffer and returns its kernel virtual address.
+  */
+@@ -335,61 +327,53 @@ map_single(struct device *hwdev, struct 
+ 	 * request and allocate a buffer from that IO TLB pool.
+ 	 */
+ 	spin_lock_irqsave(&io_tlb_lock, flags);
+-	{
+-		index = ALIGN(io_tlb_index, stride);
+-		if (index >= iotlb_nslabs)
+-			index = 0;
+-		wrap = index;
++	index = ALIGN(io_tlb_index, stride);
++	if (index >= iotlb_nslabs)
++		index = 0;
++	wrap = index;
+ 
+-		do {
+-			while (is_span_boundary(index, nslots, offset_slots,
+-						max_slots)) {
+-				index += stride;
+-				if (index >= iotlb_nslabs)
+-					index = 0;
+-				if (index == wrap)
+-					goto not_found;
+-			}
++	do {
++		while (iommu_is_span_boundary(index, nslots, offset_slots,
++					      max_slots)) {
++			index += stride;
++			if (index >= iotlb_nslabs)
++				index = 0;
++			if (index == wrap)
++				goto not_found;
++		}
++
++		/*
++		 * If we find a slot that indicates we have 'nslots' number of
++		 * contiguous buffers, we allocate the buffers from that slot
++		 * and mark the entries as '0' indicating unavailable.
++		 */
++		if (io_tlb_list[index] >= nslots) {
++			int count = 0;
++
++			for (i = index; i < (int) (index + nslots); i++)
++				io_tlb_list[i] = 0;
++			for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
++				io_tlb_list[i] = ++count;
++			dma_addr = iotlb_virt_start + (index << IO_TLB_SHIFT);
+ 
+ 			/*
+-			 * If we find a slot that indicates we have 'nslots'
+-			 * number of contiguous buffers, we allocate the
+-			 * buffers from that slot and mark the entries as '0'
+-			 * indicating unavailable.
++			 * Update the indices to avoid searching in the next
++			 * round.
+ 			 */
+-			if (io_tlb_list[index] >= nslots) {
+-				int count = 0;
+-
+-				for (i = index; i < (int)(index + nslots); i++)
+-					io_tlb_list[i] = 0;
+-				for (i = index - 1;
+-				     (OFFSET(i, IO_TLB_SEGSIZE) !=
+-				      IO_TLB_SEGSIZE -1) && io_tlb_list[i];
+-				     i--)
+-					io_tlb_list[i] = ++count;
+-				dma_addr = iotlb_virt_start +
+-					(index << IO_TLB_SHIFT);
+-
+-				/*
+-				 * Update the indices to avoid searching in
+-				 * the next round.
+-				 */
+-				io_tlb_index = 
+-					((index + nslots) < iotlb_nslabs
+-					 ? (index + nslots) : 0);
++			io_tlb_index = ((index + nslots) < iotlb_nslabs
++					? (index + nslots) : 0);
+ 
+-				goto found;
+-			}
+-			index += stride;
+-			if (index >= iotlb_nslabs)
+-				index = 0;
+-		} while (index != wrap);
++			goto found;
++		}
++		index += stride;
++		if (index >= iotlb_nslabs)
++			index = 0;
++	} while (index != wrap);
+ 
+-  not_found:
+-		spin_unlock_irqrestore(&io_tlb_lock, flags);
+-		return NULL;
+-	}
+-  found:
++not_found:
++	spin_unlock_irqrestore(&io_tlb_lock, flags);
++	return NULL;
++found:
+ 	spin_unlock_irqrestore(&io_tlb_lock, flags);
+ 
+ 	/*
+@@ -502,11 +486,13 @@ swiotlb_full(struct device *dev, size_t 
+  * Once the device is given the dma address, the device owns this memory until
+  * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
+  */
+-dma_addr_t
+-swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+-{
+-	dma_addr_t dev_addr = gnttab_dma_map_page(virt_to_page(ptr)) +
+-			      offset_in_page(ptr);
++static dma_addr_t
++_swiotlb_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
++			 int dir, struct dma_attrs *attrs)
++{
++	struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
++	dma_addr_t dev_addr = gnttab_dma_map_page(page) +
++			      offset_in_page(paddr);
+ 	void *map;
+ 	struct phys_addr buffer;
+ 
+@@ -517,7 +503,7 @@ swiotlb_map_single(struct device *hwdev,
+ 	 * we can safely return the device addr and not worry about bounce
+ 	 * buffering it.
+ 	 */
+-	if (!range_straddles_page_boundary(__pa(ptr), size) &&
++	if (!range_straddles_page_boundary(paddr, size) &&
+ 	    !address_needs_mapping(hwdev, dev_addr))
+ 		return dev_addr;
+ 
+@@ -525,8 +511,8 @@ swiotlb_map_single(struct device *hwdev,
+ 	 * Oh well, have to allocate and map a bounce buffer.
+ 	 */
+ 	gnttab_dma_unmap_page(dev_addr);
+-	buffer.page   = virt_to_page(ptr);
+-	buffer.offset = (unsigned long)ptr & ~PAGE_MASK;
++	buffer.page   = page;
++	buffer.offset = offset_in_page(paddr);
+ 	map = map_single(hwdev, buffer, size, dir);
+ 	if (!map) {
+ 		swiotlb_full(hwdev, size, dir, 1);
+@@ -537,6 +523,26 @@ swiotlb_map_single(struct device *hwdev,
+ 	return dev_addr;
+ }
+ 
++dma_addr_t
++swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
++			 int dir, struct dma_attrs *attrs)
++{
++	return _swiotlb_map_single(hwdev, virt_to_phys(ptr), size, dir, attrs);
++}
++EXPORT_SYMBOL(swiotlb_map_single_attrs);
++
++dma_addr_t
++swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
++{
++	return _swiotlb_map_single(hwdev, virt_to_phys(ptr), size, dir, NULL);
++}
++
++dma_addr_t
++swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
++{
++	return _swiotlb_map_single(hwdev, paddr, size, dir, NULL);
++}
++
+ /*
+  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
+  * match what was provided for in a previous swiotlb_map_single call.  All
+@@ -546,8 +552,8 @@ swiotlb_map_single(struct device *hwdev,
+  * whatever the device wrote there.
+  */
+ void
+-swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
+-		     int dir)
++swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
++			   size_t size, int dir, struct dma_attrs *attrs)
+ {
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (in_swiotlb_aperture(dev_addr))
+@@ -555,7 +561,14 @@ swiotlb_unmap_single(struct device *hwde
+ 	else
+ 		gnttab_dma_unmap_page(dev_addr);
+ }
++EXPORT_SYMBOL(swiotlb_unmap_single_attrs);
+ 
++void
++swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
++		     int dir)
++{
++	return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
++}
+ /*
+  * Make physical memory consistent for a single streaming mode DMA translation
+  * after a transfer.
+@@ -584,6 +597,26 @@ swiotlb_sync_single_for_device(struct de
+ 		sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
+ }
+ 
++void
++swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
++				  unsigned long offset, size_t size, int dir)
++{
++	BUG_ON(dir == DMA_NONE);
++	if (in_swiotlb_aperture(dev_addr))
++		sync_single(hwdev, bus_to_virt(dev_addr + offset), size, dir);
++}
++
++void
++swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
++				     unsigned long offset, size_t size, int dir)
++{
++	BUG_ON(dir == DMA_NONE);
++	if (in_swiotlb_aperture(dev_addr))
++		sync_single(hwdev, bus_to_virt(dev_addr + offset), size, dir);
++}
++
++void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
++			    struct dma_attrs *);
+ /*
+  * Map a set of buffers described by scatterlist in streaming mode for DMA.
+  * This is the scatter-gather version of the above swiotlb_map_single
+@@ -601,8 +634,8 @@ swiotlb_sync_single_for_device(struct de
+  * same here.
+  */
+ int
+-swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+-	       int dir)
++swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
++		     int dir, struct dma_attrs *attrs)
+ {
+ 	struct scatterlist *sg;
+ 	struct phys_addr buffer;
+@@ -626,7 +659,8 @@ swiotlb_map_sg(struct device *hwdev, str
+ 				/* Don't panic here, we expect map_sg users
+ 				   to do proper error handling. */
+ 				swiotlb_full(hwdev, sg->length, dir, 0);
+-				swiotlb_unmap_sg(hwdev, sgl, i, dir);
++				swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
++						       attrs);
+ 				sgl[0].dma_length = 0;
+ 				return 0;
+ 			}
+@@ -637,14 +671,22 @@ swiotlb_map_sg(struct device *hwdev, str
+ 	}
+ 	return nelems;
+ }
++EXPORT_SYMBOL(swiotlb_map_sg_attrs);
++
++int
++swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
++	       int dir)
++{
++	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
++}
+ 
+ /*
+  * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
+  * concerning calls here are the same as for swiotlb_unmap_single() above.
+  */
+ void
+-swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+-		 int dir)
++swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
++		       int nelems, int dir, struct dma_attrs *attrs)
+ {
+ 	struct scatterlist *sg;
+ 	int i;
+@@ -659,6 +701,14 @@ swiotlb_unmap_sg(struct device *hwdev, s
+ 			gnttab_dma_unmap_page(sg->dma_address);
+ 	}
+ }
++EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
++
++void
++swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
++		 int dir)
++{
++	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
++}
+ 
+ /*
+  * Make physical memory consistent for a set of streaming mode DMA translations
+@@ -699,46 +749,6 @@ swiotlb_sync_sg_for_device(struct device
+ 	}
+ }
+ 
+-#ifdef CONFIG_HIGHMEM
+-
+-dma_addr_t
+-swiotlb_map_page(struct device *hwdev, struct page *page,
+-		 unsigned long offset, size_t size,
+-		 enum dma_data_direction direction)
+-{
+-	struct phys_addr buffer;
+-	dma_addr_t dev_addr;
+-	char *map;
+-
+-	dev_addr = gnttab_dma_map_page(page) + offset;
+-	if (address_needs_mapping(hwdev, dev_addr)) {
+-		gnttab_dma_unmap_page(dev_addr);
+-		buffer.page   = page;
+-		buffer.offset = offset;
+-		map = map_single(hwdev, buffer, size, direction);
+-		if (!map) {
+-			swiotlb_full(hwdev, size, direction, 1);
+-			map = io_tlb_overflow_buffer;
+-		}
+-		dev_addr = (dma_addr_t)virt_to_bus(map);
+-	}
+-
+-	return dev_addr;
+-}
+-
+-void
+-swiotlb_unmap_page(struct device *hwdev, dma_addr_t dma_address,
+-		   size_t size, enum dma_data_direction direction)
+-{
+-	BUG_ON(direction == DMA_NONE);
+-	if (in_swiotlb_aperture(dma_address))
+-		unmap_single(hwdev, bus_to_virt(dma_address), size, direction);
+-	else
+-		gnttab_dma_unmap_page(dma_address);
+-}
+-
+-#endif
+-
+ int
+ swiotlb_dma_mapping_error(dma_addr_t dma_addr)
+ {
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-arch-x86_64.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-arch-x86_64.diff
@@ -0,0 +1,222 @@
+Subject: xen3 arch-x86_64
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-04.orig/arch/x86/kernel/asm-offsets_64.c	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/asm-offsets_64.c	2009-12-04 10:44:49.000000000 +0100
+@@ -115,8 +115,10 @@ int main(void)
+ 	ENTRY(cr8);
+ 	BLANK();
+ #undef ENTRY
++#ifndef CONFIG_X86_NO_TSS
+ 	DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
+ 	BLANK();
++#endif
+ 	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+ 	BLANK();
+ 	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+--- head-2010-01-04.orig/arch/x86/kernel/machine_kexec_64.c	2009-04-21 10:35:13.000000000 +0200
++++ head-2010-01-04/arch/x86/kernel/machine_kexec_64.c	2009-12-04 10:44:49.000000000 +0100
+@@ -19,6 +19,119 @@
+ #include <asm/tlbflush.h>
+ #include <asm/mmu_context.h>
+ 
++#ifdef CONFIG_XEN
++
++/* In the case of Xen, override hypervisor functions to be able to create
++ * a regular identity mapping page table...
++ */
++
++#include <xen/interface/kexec.h>
++#include <xen/interface/memory.h>
++
++#define x__pmd(x) ((pmd_t) { (x) } )
++#define x__pud(x) ((pud_t) { (x) } )
++#define x__pgd(x) ((pgd_t) { (x) } )
++
++#define x_pmd_val(x)   ((x).pmd)
++#define x_pud_val(x)   ((x).pud)
++#define x_pgd_val(x)   ((x).pgd)
++
++static inline void x_set_pmd(pmd_t *dst, pmd_t val)
++{
++	x_pmd_val(*dst) = x_pmd_val(val);
++}
++
++static inline void x_set_pud(pud_t *dst, pud_t val)
++{
++	x_pud_val(*dst) = phys_to_machine(x_pud_val(val));
++}
++
++static inline void x_pud_clear (pud_t *pud)
++{
++	x_pud_val(*pud) = 0;
++}
++
++static inline void x_set_pgd(pgd_t *dst, pgd_t val)
++{
++	x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val));
++}
++
++static inline void x_pgd_clear (pgd_t * pgd)
++{
++	x_pgd_val(*pgd) = 0;
++}
++
++#define X__PAGE_KERNEL_LARGE_EXEC \
++         _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE
++#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY
++
++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
++
++#if PAGES_NR > KEXEC_XEN_NO_PAGES
++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
++#endif
++
++#if PA_CONTROL_PAGE != 0
++#error PA_CONTROL_PAGE is non zero - Xen support will break
++#endif
++
++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
++{
++	void *control_page;
++	void *table_page;
++
++	memset(xki->page_list, 0, sizeof(xki->page_list));
++
++	control_page = page_address(image->control_code_page) + PAGE_SIZE;
++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
++
++	table_page = page_address(image->control_code_page);
++
++	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
++	xki->page_list[PA_TABLE_PAGE] = __ma(table_page);
++
++	xki->page_list[PA_PGD] = __ma(kexec_pgd);
++	xki->page_list[PA_PUD_0] = __ma(kexec_pud0);
++	xki->page_list[PA_PUD_1] = __ma(kexec_pud1);
++	xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
++	xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
++	xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
++	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)
++#define x__pud(x) __pud(x)
++#define x__pgd(x) __pgd(x)
++
++#define x_set_pmd(x, y) set_pmd(x, y)
++#define x_set_pud(x, y) set_pud(x, y)
++#define x_set_pgd(x, y) set_pgd(x, y)
++
++#define x_pud_clear(x) pud_clear(x)
++#define x_pgd_clear(x) pgd_clear(x)
++
++#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC
++#define X_KERNPG_TABLE _KERNPG_TABLE
++
++#endif /* CONFIG_XEN */
++
+ static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
+ 				unsigned long addr)
+ {
+@@ -61,7 +174,7 @@ static void init_level2_page(pmd_t *leve
+ 	addr &= PAGE_MASK;
+ 	end_addr = addr + PUD_SIZE;
+ 	while (addr < end_addr) {
+-		set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
++		x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
+ 		addr += PMD_SIZE;
+ 	}
+ }
+@@ -86,12 +199,12 @@ static int init_level3_page(struct kimag
+ 		}
+ 		level2p = (pmd_t *)page_address(page);
+ 		init_level2_page(level2p, addr);
+-		set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE));
++		x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE));
+ 		addr += PUD_SIZE;
+ 	}
+ 	/* clear the unused entries */
+ 	while (addr < end_addr) {
+-		pud_clear(level3p++);
++		x_pud_clear(level3p++);
+ 		addr += PUD_SIZE;
+ 	}
+ out:
+@@ -121,12 +234,12 @@ static int init_level4_page(struct kimag
+ 		result = init_level3_page(image, level3p, addr, last_addr);
+ 		if (result)
+ 			goto out;
+-		set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE));
++		x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE));
+ 		addr += PGDIR_SIZE;
+ 	}
+ 	/* clear the unused entries */
+ 	while (addr < end_addr) {
+-		pgd_clear(level4p++);
++		x_pgd_clear(level4p++);
+ 		addr += PGDIR_SIZE;
+ 	}
+ out:
+@@ -187,8 +300,14 @@ static int init_pgtable(struct kimage *i
+ {
+ 	pgd_t *level4p;
+ 	int result;
++	unsigned long x_max_pfn = max_pfn;
++
++#ifdef CONFIG_XEN
++	x_max_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
++#endif
++
+ 	level4p = (pgd_t *)__va(start_pgtable);
+-	result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
++	result = init_level4_page(image, level4p, 0, x_max_pfn << PAGE_SHIFT);
+ 	if (result)
+ 		return result;
+ 	/*
+@@ -222,6 +341,7 @@ void machine_kexec_cleanup(struct kimage
+ 	free_transition_pgtable(image);
+ }
+ 
++#ifndef CONFIG_XEN
+ /*
+  * Do not allocate memory (or fail in any way) in machine_kexec().
+  * We are past the point of no return, committed to rebooting now.
+@@ -280,6 +400,7 @@ void machine_kexec(struct kimage *image)
+ 
+ 	__ftrace_enabled_restore(save_ftrace_enabled);
+ }
++#endif
+ 
+ void arch_crash_save_vmcoreinfo(void)
+ {
+--- head-2010-01-04.orig/arch/x86/vdso/Makefile	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/vdso/Makefile	2009-12-04 10:44:49.000000000 +0100
+@@ -65,6 +65,8 @@ obj-$(VDSO32-y)			+= vdso32-syms.lds
+ vdso32.so-$(VDSO32-y)		+= int80
+ vdso32.so-$(CONFIG_COMPAT)	+= syscall
+ vdso32.so-$(VDSO32-y)		+= sysenter
++xen-vdso32-$(subst 1,$(CONFIG_COMPAT),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80
++vdso32.so-$(CONFIG_XEN)		+= $(xen-vdso32-y)
+ 
+ vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32
@@ -0,0 +1,6481 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: Linux: 2.6.32
+Patch-mainline: 2.6.32
+
+ This patch contains the differences between 2.6.31 and 2.6.32.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.32" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 14:53:39.000000000 +0100
+@@ -20,18 +20,15 @@
+ #define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
+ #define __AUDIT_ARCH_LE	   0x40000000
+ 
+-#ifndef CONFIG_AUDITSYSCALL
+-#define sysexit_audit int_ret_from_sys_call
+-#define sysretl_audit int_ret_from_sys_call
+-#endif
+-
+ #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+ 
+ 	.macro IA32_ARG_FIXUP noebp=0
+ 	movl	%edi,%r8d
+ 	.if \noebp
++	jmp	ia32_common
+ 	.else
+ 	movl	%ebp,%r9d
++ia32_common:
+ 	.endif
+ 	xchg	%ecx,%esi
+ 	movl	%ebx,%edi
+@@ -39,12 +36,12 @@
+ 	.endm 
+ 
+ 	/* clobbers %eax */	
+-	.macro  CLEAR_RREGS _r9=rax
++	.macro  CLEAR_RREGS offset=0, _r9=rax
+ 	xorl 	%eax,%eax
+-	movq	%rax,R11(%rsp)
+-	movq	%rax,R10(%rsp)
+-	movq	%\_r9,R9(%rsp)
+-	movq	%rax,R8(%rsp)
++	movq	%rax,\offset+R11(%rsp)
++	movq	%rax,\offset+R10(%rsp)
++	movq	%\_r9,\offset+R9(%rsp)
++	movq	%rax,\offset+R8(%rsp)
+ 	.endm
+ 
+ 	/*
+@@ -144,17 +141,7 @@ ENTRY(ia32_sysenter_target)
+ 	jnz  sysenter_tracesys
+ 	cmpl	$(IA32_NR_syscalls-1),%eax
+ 	ja	ia32_badsys
+-sysenter_do_call:
+-	IA32_ARG_FIXUP
+-sysenter_dispatch:
+-	call	*ia32_sys_call_table(,%rax,8)
+-	movq	%rax,RAX-ARGOFFSET(%rsp)
+-	GET_THREAD_INFO(%r10)
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	TRACE_IRQS_OFF
+-	testl	$_TIF_ALLWORK_MASK,TI_flags(%r10)
+-	jnz	sysexit_audit
+-	jmp int_ret_from_sys_call
++	jmp	ia32_do_call
+ 
+ #ifdef CONFIG_AUDITSYSCALL
+ 	.macro auditsys_entry_common
+@@ -175,31 +162,10 @@ sysenter_dispatch:
+ 	movl RDI-ARGOFFSET(%rsp),%r8d	/* reload 5th syscall arg */
+ 	.endm
+ 
+-	.macro auditsys_exit exit,ebpsave=RBP
+-	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+-	jnz int_ret_from_sys_call
+-	TRACE_IRQS_ON
+-	ENABLE_INTERRUPTS(CLBR_NONE)
+-	movl %eax,%esi		/* second arg, syscall return value */
+-	cmpl $0,%eax		/* is it < 0? */
+-	setl %al		/* 1 if so, 0 if not */
+-	movzbl %al,%edi		/* zero-extend that into %edi */
+-	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+-	call audit_syscall_exit
+-	movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
+-	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	TRACE_IRQS_OFF
+-	jmp int_with_check
+-	.endm
+-
+ sysenter_auditsys:
+ 	auditsys_entry_common
+ 	movl %ebp,%r9d			/* reload 6th syscall arg */
+-	jmp sysenter_dispatch
+-
+-sysexit_audit:
+-	auditsys_exit sysexit_from_sys_call
++	jmp ia32_dispatch
+ #endif
+ 
+ sysenter_tracesys:
+@@ -216,7 +182,7 @@ sysenter_tracesys:
+ 	RESTORE_REST
+ 	cmpl	$(IA32_NR_syscalls-1),%eax
+ 	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+-	jmp	sysenter_do_call
++	jmp	ia32_do_call
+ 	CFI_ENDPROC
+ ENDPROC(ia32_sysenter_target)
+ 
+@@ -272,24 +238,13 @@ ENTRY(ia32_cstar_target)
+ 	ja  ia32_badsys
+ cstar_do_call:
+ 	IA32_ARG_FIXUP 1
+-cstar_dispatch:
+-	call *ia32_sys_call_table(,%rax,8)
+-	movq %rax,RAX-ARGOFFSET(%rsp)
+-	GET_THREAD_INFO(%r10)
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
+-	jnz sysretl_audit
+-	jmp int_ret_from_sys_call
+ 	
+ #ifdef CONFIG_AUDITSYSCALL
+ cstar_auditsys:
+ 	movl %r9d,R9-ARGOFFSET(%rsp)	/* register to be clobbered by call */
+ 	auditsys_entry_common
+ 	movl R9-ARGOFFSET(%rsp),%r9d	/* reload 6th syscall arg */
+-	jmp cstar_dispatch
+-
+-sysretl_audit:
+-	auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
++	jmp ia32_dispatch
+ #endif
+ 
+ cstar_tracesys:
+@@ -299,7 +254,7 @@ cstar_tracesys:
+ #endif
+ 	xchgl %r9d,%ebp
+ 	SAVE_REST
+-	CLEAR_RREGS r9
++	CLEAR_RREGS 0, r9
+ 	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+@@ -367,9 +322,11 @@ ENTRY(ia32_syscall)
+ 	ja ia32_badsys
+ ia32_do_call:
+ 	IA32_ARG_FIXUP
++ia32_dispatch:
+ 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ ia32_sysret:
+ 	movq %rax,RAX-ARGOFFSET(%rsp)
++	CLEAR_RREGS -ARGOFFSET
+ 	jmp int_ret_from_sys_call 
+ 
+ ia32_tracesys:			 
+@@ -387,8 +344,8 @@ END(ia32_syscall)
+ 
+ ia32_badsys:
+ 	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
+-	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+-	jmp int_ret_from_sys_call
++	movq $-ENOSYS,%rax
++	jmp ia32_sysret
+ 
+ quiet_ni_syscall:
+ 	movq $-ENOSYS,%rax
+@@ -482,7 +439,7 @@ ia32_sys_call_table:
+ 	.quad sys_mkdir
+ 	.quad sys_rmdir		/* 40 */
+ 	.quad sys_dup
+-	.quad sys32_pipe
++	.quad sys_pipe
+ 	.quad compat_sys_times
+ 	.quad quiet_ni_syscall			/* old prof syscall holder */
+ 	.quad sys_brk		/* 45 */
+@@ -776,5 +733,5 @@ ia32_sys_call_table:
+ 	.quad compat_sys_preadv
+ 	.quad compat_sys_pwritev
+ 	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */
+-	.quad sys_perf_counter_open
++	.quad sys_perf_event_open
+ ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/include/asm/time.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/time.h	2009-11-06 10:52:22.000000000 +0100
+@@ -8,8 +8,9 @@ extern void hpet_time_init(void);
+ extern void time_init(void);
+ 
+ #ifdef CONFIG_XEN
++struct timespec;
+ extern int xen_independent_wallclock(void);
+-extern unsigned long xen_read_persistent_clock(void);
++extern void xen_read_persistent_clock(struct timespec *);
+ extern int xen_update_persistent_clock(void);
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/include/asm/uv/uv_hub.h	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/uv/uv_hub.h	2009-11-06 11:32:17.000000000 +0100
+@@ -11,7 +11,7 @@
+ #ifndef _ASM_X86_UV_UV_HUB_H
+ #define _ASM_X86_UV_UV_HUB_H
+ 
+-#ifdef CONFIG_X86_64
++#ifdef CONFIG_X86_UV
+ #include <linux/numa.h>
+ #include <linux/percpu.h>
+ #include <linux/timer.h>
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:52:22.000000000 +0100
+@@ -28,10 +28,7 @@
+  */
+ #define flush_agp_cache() wbinvd()
+ 
+-/* Convert a physical address to an address suitable for the GART. */
+-#define phys_to_gart(x) phys_to_machine(x)
+-#define gart_to_phys(x) machine_to_phys(x)
+-#define page_to_gart(x) phys_to_gart(page_to_pseudophys(x))
++#define virt_to_gart virt_to_machine
+ 
+ /* GATT allocation. Returns/accepts GATT kernel virtual address. */
+ #define alloc_gatt_pages(order)	({                                          \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-18 14:54:16.000000000 +0100
+@@ -312,7 +312,14 @@ static inline void load_LDT(mm_context_t
+ 
+ static inline unsigned long get_desc_base(const struct desc_struct *desc)
+ {
+-	return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
++	return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
++}
++
++static inline void set_desc_base(struct desc_struct *desc, unsigned long base)
++{
++	desc->base0 = base & 0xffff;
++	desc->base1 = (base >> 16) & 0xff;
++	desc->base2 = (base >> 24) & 0xff;
+ }
+ 
+ static inline unsigned long get_desc_limit(const struct desc_struct *desc)
+@@ -320,6 +327,12 @@ static inline unsigned long get_desc_lim
+ 	return desc->limit0 | (desc->limit << 16);
+ }
+ 
++static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
++{
++	desc->limit0 = limit & 0xffff;
++	desc->limit = (limit >> 16) & 0xf;
++}
++
+ #ifndef CONFIG_X86_NO_IDT
+ static inline void _set_gate(int gate, unsigned type, void *addr,
+ 			     unsigned dpl, unsigned ist, unsigned seg)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:52:22.000000000 +0100
+@@ -1,11 +1,24 @@
+ #ifndef _ASM_X86_DMA_MAPPING_H_
+ 
++#define phys_to_dma _phys_to_dma_
++#define dma_to_phys _dma_to_phys_
++
+ #include_next <asm/dma-mapping.h>
+ 
+-void dma_generic_free_coherent(struct device *, size_t, void *, dma_addr_t);
++#undef phys_to_dma
++#undef dma_to_phys
++
++static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
++{
++	return phys_to_machine(paddr);
++}
+ 
+-#define address_needs_mapping(hwdev, addr, size) \
+-	!is_buffer_dma_capable(dma_get_mask(hwdev), addr, size)
++static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
++{
++	return machine_to_phys(daddr);
++}
++
++void dma_generic_free_coherent(struct device *, size_t, void *, dma_addr_t);
+ 
+ extern int range_straddles_page_boundary(paddr_t p, size_t size);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:22.000000000 +0100
+@@ -139,6 +139,9 @@ enum fixed_addresses {
+ #ifdef CONFIG_X86_32
+ 	FIX_WP_TEST,
+ #endif
++#ifdef CONFIG_INTEL_TXT
++	FIX_TBOOT_BASE,
++#endif
+ 	__end_of_fixed_addresses
+ };
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:43:12.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:44:04.000000000 +0100
+@@ -70,6 +70,7 @@ extern start_info_t *xen_start_info;
+ #endif
+ 
+ #define init_hypervisor(c) ((void)((c)->x86_hyper_vendor = X86_HYPER_VENDOR_XEN))
++#define init_hypervisor_platform() init_hypervisor(&boot_cpu_data)
+ 
+ struct vcpu_runstate_info *setup_runstate_area(unsigned int cpu);
+ 
+@@ -351,6 +352,6 @@ MULTI_grant_table_op(multicall_entry_t *
+ 
+ #endif
+ 
+-#define uvm_multi(cpumask) ((unsigned long)cpus_addr(cpumask) | UVMF_MULTI)
++#define uvm_multi(cpumask) ((unsigned long)cpumask_bits(cpumask) | UVMF_MULTI)
+ 
+ #endif /* __HYPERVISOR_H__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:52:22.000000000 +0100
+@@ -1,7 +1,7 @@
+ #ifndef _X86_IRQFLAGS_H_
+ #define _X86_IRQFLAGS_H_
+ 
+-#include <asm/processor-flags.h>
++#include <asm/smp-processor-id.h>
+ 
+ #ifndef __ASSEMBLY__
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:52:22.000000000 +0100
+@@ -88,12 +88,12 @@ static inline void switch_mm(struct mm_s
+ 		       !PagePinned(virt_to_page(next->pgd)));
+ 
+ 		/* stop flush ipis for the previous mm */
+-		cpu_clear(cpu, prev->cpu_vm_mask);
++		cpumask_clear_cpu(cpu, mm_cpumask(prev));
+ #if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+ 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ 		percpu_write(cpu_tlbstate.active_mm, next);
+ #endif
+-		cpu_set(cpu, next->cpu_vm_mask);
++		cpumask_set_cpu(cpu, mm_cpumask(next));
+ 
+ 		/* Re-load page tables: load_cr3(next->pgd) */
+ 		op->cmd = MMUEXT_NEW_BASEPTR;
+@@ -125,7 +125,7 @@ static inline void switch_mm(struct mm_s
+ 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+ 		BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
+ 
+-		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
++		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) {
+ 			/* We were in lazy tlb mode and leave_mm disabled
+ 			 * tlb flush IPI delivery. We must reload CR3
+ 			 * to make sure to use no freed page tables.
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:52:22.000000000 +0100
+@@ -151,7 +151,11 @@ static inline int __pcibus_to_node(const
+ static inline const struct cpumask *
+ cpumask_of_pcibus(const struct pci_bus *bus)
+ {
+-	return cpumask_of_node(__pcibus_to_node(bus));
++	int node;
++
++	node = __pcibus_to_node(bus);
++	return (node == -1) ? cpu_online_mask :
++			      cpumask_of_node(node);
+ }
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-20 11:17:56.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-20 11:18:13.000000000 +0100
+@@ -53,16 +53,6 @@ extern struct list_head pgd_list;
+ #define pte_update(mm, addr, ptep)              do { } while (0)
+ #define pte_update_defer(mm, addr, ptep)        do { } while (0)
+ 
+-static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
+-{
+-	xen_pagetable_setup_start(base);
+-}
+-
+-static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
+-{
+-	xen_pagetable_setup_done(base);
+-}
+-
+ #define pgd_val(x)	xen_pgd_val(x)
+ #define __pgd(x)	xen_make_pgd(x)
+ 
+@@ -134,6 +124,11 @@ static inline int pte_special(pte_t pte)
+ 
+ #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
+ 
++static inline unsigned long pmd_pfn(pmd_t pmd)
++{
++	return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
++}
++
+ static inline int pmd_large(pmd_t pte)
+ {
+ 	return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+@@ -363,7 +358,7 @@ static inline unsigned long pmd_page_vad
+  * this macro returns the index of the entry in the pmd page which would
+  * control the given virtual address
+  */
+-static inline unsigned pmd_index(unsigned long address)
++static inline unsigned long pmd_index(unsigned long address)
+ {
+ 	return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+ }
+@@ -383,7 +378,7 @@ static inline unsigned pmd_index(unsigne
+  * this function returns the index of the entry in the pte page which would
+  * control the given virtual address
+  */
+-static inline unsigned pte_index(unsigned long address)
++static inline unsigned long pte_index(unsigned long address)
+ {
+ 	return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+ }
+@@ -439,11 +434,6 @@ static inline pmd_t *pmd_offset(pud_t *p
+ 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
+ }
+ 
+-static inline unsigned long pmd_pfn(pmd_t pmd)
+-{
+-	return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
+-}
+-
+ static inline int pud_large(pud_t pud)
+ {
+ 	return (__pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+@@ -479,7 +469,7 @@ static inline unsigned long pgd_page_vad
+ #define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+ 
+ /* to find an entry in a page-table-directory. */
+-static inline unsigned pud_index(unsigned long address)
++static inline unsigned long pud_index(unsigned long address)
+ {
+ 	return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
+ }
+@@ -600,7 +590,7 @@ extern int ptep_clear_flush_young(struct
+ 	if (!pte_none(__res) &&					\
+ 	    ((vma)->vm_mm != current->mm ||			\
+ 	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
+-			uvm_multi((vma)->vm_mm->cpu_vm_mask) |	\
++			uvm_multi(mm_cpumask((vma)->vm_mm)) |	\
+ 				UVMF_INVLPG))) {		\
+ 		__xen_pte_clear(__ptep);			\
+ 		flush_tlb_page(vma, addr);			\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-11-06 10:52:22.000000000 +0100
+@@ -334,6 +334,7 @@ static inline pteval_t pte_flags(pte_t p
+ typedef struct page *pgtable_t;
+ 
+ extern pteval_t __supported_pte_mask;
++extern void set_nx(void);
+ extern int nx_enabled;
+ 
+ #define pgprot_writecombine	pgprot_writecombine
+@@ -354,14 +355,6 @@ int phys_mem_access_prot_allowed(struct 
+ /* Install a pte for a particular vaddr in kernel space. */
+ void set_pte_vaddr(unsigned long vaddr, pte_t pte);
+ 
+-#ifndef CONFIG_XEN
+-extern void native_pagetable_setup_start(pgd_t *base);
+-extern void native_pagetable_setup_done(pgd_t *base);
+-#else
+-static inline void xen_pagetable_setup_start(pgd_t *base) {}
+-static inline void xen_pagetable_setup_done(pgd_t *base) {}
+-#endif
+-
+ struct seq_file;
+ extern void arch_report_meminfo(struct seq_file *m);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-18 14:54:16.000000000 +0100
+@@ -27,6 +27,7 @@ struct mm_struct;
+ #include <linux/cpumask.h>
+ #include <linux/cache.h>
+ #include <linux/threads.h>
++#include <linux/math64.h>
+ #include <linux/init.h>
+ #include <xen/interface/physdev.h>
+ 
+@@ -411,7 +412,17 @@ extern unsigned long kernel_eflags;
+ extern asmlinkage void ignore_sysret(void);
+ #else	/* X86_64 */
+ #ifdef CONFIG_CC_STACKPROTECTOR
+-DECLARE_PER_CPU(unsigned long, stack_canary);
++/*
++ * Make sure stack canary segment base is cached-aligned:
++ *   "For Intel Atom processors, avoid non zero segment base address
++ *    that is not aligned to cache line boundary at all cost."
++ * (Optim Ref Manual Assembly/Compiler Coding Rule 15.)
++ */
++struct stack_canary {
++	char __pad[20];		/* canary at %gs:20 */
++	unsigned long canary;
++};
++DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+ #endif
+ #endif	/* X86_64 */
+ 
+@@ -648,13 +659,23 @@ static inline void cpu_relax(void)
+ 	rep_nop();
+ }
+ 
+-/* Stop speculative execution: */
++/* Stop speculative execution and prefetching of modified code. */
+ static inline void sync_core(void)
+ {
+ 	int tmp;
+ 
+-	asm volatile("cpuid" : "=a" (tmp) : "0" (1)
+-		     : "ebx", "ecx", "edx", "memory");
++#if defined(CONFIG_M386) || defined(CONFIG_M486)
++	if (boot_cpu_data.x86 < 5)
++		/* There is no speculative execution.
++		 * jmp is a barrier to prefetching. */
++		asm volatile("jmp 1f\n1:\n" ::: "memory");
++	else
++#endif
++		/* cpuid is a barrier to speculative execution.
++		 * Prefetched instructions are automatically
++		 * invalidated when modified. */
++		asm volatile("cpuid" : "=a" (tmp) : "0" (1)
++			     : "ebx", "ecx", "edx", "memory");
+ }
+ 
+ static inline void __monitor(const void *eax, unsigned long ecx,
+@@ -926,7 +947,7 @@ extern unsigned long thread_saved_pc(str
+ #define thread_saved_pc(t)	(*(unsigned long *)((t)->thread.sp - 8))
+ 
+ #define task_pt_regs(tsk)	((struct pt_regs *)(tsk)->thread.sp0 - 1)
+-#define KSTK_ESP(tsk)		-1 /* sorry. doesn't work for syscall. */
++extern unsigned long KSTK_ESP(struct task_struct *task);
+ #endif /* CONFIG_X86_64 */
+ 
+ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
+@@ -947,4 +968,35 @@ extern void start_thread(struct pt_regs 
+ extern int get_tsc_mode(unsigned long adr);
+ extern int set_tsc_mode(unsigned int val);
+ 
++extern int amd_get_nb_id(int cpu);
++
++struct aperfmperf {
++	u64 aperf, mperf;
++};
++
++static inline void get_aperfmperf(struct aperfmperf *am)
++{
++	WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF));
++
++	rdmsrl(MSR_IA32_APERF, am->aperf);
++	rdmsrl(MSR_IA32_MPERF, am->mperf);
++}
++
++#define APERFMPERF_SHIFT 10
++
++static inline
++unsigned long calc_aperfmperf_ratio(struct aperfmperf *old,
++				    struct aperfmperf *new)
++{
++	u64 aperf = new->aperf - old->aperf;
++	u64 mperf = new->mperf - old->mperf;
++	unsigned long ratio = aperf;
++
++	mperf >>= APERFMPERF_SHIFT;
++	if (mperf)
++		ratio = div64_u64(aperf, mperf);
++
++	return ratio;
++}
++
+ #endif /* _ASM_X86_PROCESSOR_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/setup.h	2009-11-06 10:52:22.000000000 +0100
+@@ -0,0 +1,8 @@
++#ifndef __ASSEMBLY__
++
++void xen_start_kernel(void);
++void xen_arch_setup(void);
++
++#endif
++
++#include_next <asm/setup.h>
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp-processor-id.h	2009-11-06 10:52:22.000000000 +0100
+@@ -0,0 +1,36 @@
++#ifndef _ASM_X86_SMP_PROCESSOR_ID_H
++#define _ASM_X86_SMP_PROCESSOR_ID_H
++
++#if defined(CONFIG_SMP) && !defined(__ASSEMBLY__)
++
++#include <asm/percpu.h>
++
++DECLARE_PER_CPU(int, cpu_number);
++
++/*
++ * This function is needed by all SMP systems. It must _always_ be valid
++ * from the initial startup. We map APIC_BASE very early in page_setup(),
++ * so this is correct in the x86 case.
++ */
++#define raw_smp_processor_id() percpu_read(cpu_number)
++#define safe_smp_processor_id() smp_processor_id()
++
++#ifdef CONFIG_X86_64_SMP
++#define stack_smp_processor_id()					\
++({									\
++	struct thread_info *ti;						\
++	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->cpu;							\
++})
++#endif
++
++#ifdef CONFIG_DEBUG_PREEMPT
++extern unsigned int debug_smp_processor_id(void);
++# define smp_processor_id() debug_smp_processor_id()
++#else
++# define smp_processor_id() raw_smp_processor_id()
++#endif
++
++#endif /* SMP && !__ASSEMBLY__ */
++
++#endif /* _ASM_X86_SMP_PROCESSOR_ID_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:17:59.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:18:10.000000000 +0100
+@@ -121,7 +121,6 @@ static inline void arch_send_call_functi
+ 	smp_ops.send_call_func_single_ipi(cpu);
+ }
+ 
+-#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
+ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+ {
+ 	smp_ops.send_call_func_ipi(mask);
+@@ -167,27 +166,7 @@ static inline int num_booting_cpus(void)
+ 
+ extern unsigned disabled_cpus __cpuinitdata;
+ 
+-#ifdef CONFIG_X86_32_SMP
+-/*
+- * This function is needed by all SMP systems. It must _always_ be valid
+- * from the initial startup. We map APIC_BASE very early in page_setup(),
+- * so this is correct in the x86 case.
+- */
+-#define raw_smp_processor_id() (percpu_read(cpu_number))
+-#define safe_smp_processor_id() smp_processor_id()
+-
+-#elif defined(CONFIG_X86_64_SMP)
+-#define raw_smp_processor_id() (percpu_read(cpu_number))
+-
+-#define stack_smp_processor_id()					\
+-({								\
+-	struct thread_info *ti;						\
+-	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+-	ti->cpu;							\
+-})
+-#define safe_smp_processor_id()		smp_processor_id()
+-
+-#endif
++#include <asm/smp-processor-id.h>
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:52:22.000000000 +0100
+@@ -30,7 +30,7 @@ void __switch_to_xtra(struct task_struct
+ 	"movl %P[task_canary](%[next]), %%ebx\n\t"			\
+ 	"movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
+ #define __switch_canary_oparam						\
+-	, [stack_canary] "=m" (per_cpu_var(stack_canary))
++	, [stack_canary] "=m" (per_cpu_var(stack_canary.canary))
+ #define __switch_canary_iparam						\
+ 	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+ #else	/* CC_STACKPROTECTOR */
+@@ -149,33 +149,6 @@ do {									\
+ #endif
+ 
+ #ifdef __KERNEL__
+-#define _set_base(addr, base) do { unsigned long __pr; \
+-__asm__ __volatile__ ("movw %%dx,%1\n\t" \
+-	"rorl $16,%%edx\n\t" \
+-	"movb %%dl,%2\n\t" \
+-	"movb %%dh,%3" \
+-	:"=&d" (__pr) \
+-	:"m" (*((addr)+2)), \
+-	 "m" (*((addr)+4)), \
+-	 "m" (*((addr)+7)), \
+-	 "0" (base) \
+-	); } while (0)
+-
+-#define _set_limit(addr, limit) do { unsigned long __lr; \
+-__asm__ __volatile__ ("movw %%dx,%1\n\t" \
+-	"rorl $16,%%edx\n\t" \
+-	"movb %2,%%dh\n\t" \
+-	"andb $0xf0,%%dh\n\t" \
+-	"orb %%dh,%%dl\n\t" \
+-	"movb %%dl,%2" \
+-	:"=&d" (__lr) \
+-	:"m" (*(addr)), \
+-	 "m" (*((addr)+6)), \
+-	 "0" (limit) \
+-	); } while (0)
+-
+-#define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base))
+-#define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1))
+ 
+ extern void xen_load_gs_index(unsigned);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:52:22.000000000 +0100
+@@ -74,9 +74,9 @@ static inline void reset_lazy_tlbstate(v
+ #define local_flush_tlb() __flush_tlb()
+ 
+ #define flush_tlb_all xen_tlb_flush_all
+-#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
+-#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
+-#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
++#define flush_tlb_current_task() xen_tlb_flush_mask(mm_cpumask(current->mm))
++#define flush_tlb_mm(mm) xen_tlb_flush_mask(mm_cpumask(mm))
++#define flush_tlb_page(vma, va) xen_invlpg_mask(mm_cpumask((vma)->vm_mm), va)
+ 
+ #define flush_tlb()	flush_tlb_current_task()
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:52:22.000000000 +0100
+@@ -132,8 +132,6 @@ ifeq ($(CONFIG_X86_64),y)
+ 
+ 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+ 	obj-y				+= vsmp_64.o
+-
+-	time_64-$(CONFIG_XEN)		+= time_32.o
+ endif
+ 
+ disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
+--- head-2010-01-18.orig/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -79,6 +79,8 @@ unsigned long io_apic_irqs;
+ #endif /* CONFIG_XEN */
+ 
+ #define __apicdebuginit(type) static type __init
++#define for_each_irq_pin(entry, head) \
++	for (entry = head; entry; entry = entry->next)
+ 
+ /*
+  *      Is the SiS APIC rmw bug present ?
+@@ -100,12 +102,24 @@ int nr_ioapic_registers[MAX_IO_APICS];
+ struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
+ int nr_ioapics;
+ 
++/* IO APIC gsi routing info */
++struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
++
+ /* MP IRQ source entries */
+ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ 
+ /* # of MP IRQ source entries */
+ int mp_irq_entries;
+ 
++#ifndef CONFIG_XEN
++/* Number of legacy interrupts */
++static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
++/* GSI interrupts */
++static int nr_irqs_gsi = NR_IRQS_LEGACY;
++#else
++#define nr_legacy_irqs NR_IRQS_LEGACY
++#endif
++
+ #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+ int mp_bus_id_to_type[MAX_MP_BUSSES];
+ #endif
+@@ -132,15 +146,6 @@ static int __init parse_noapic(char *str
+ early_param("noapic", parse_noapic);
+ 
+ #ifndef CONFIG_XEN
+-struct irq_pin_list;
+-
+-/*
+- * This is performance-critical, we want to do it O(1)
+- *
+- * the indexing order of this array favors 1:1 mappings
+- * between pins and IRQs.
+- */
+-
+ struct irq_pin_list {
+ 	int apic, pin;
+ 	struct irq_pin_list *next;
+@@ -155,6 +160,11 @@ static struct irq_pin_list *get_one_free
+ 	return pin;
+ }
+ 
++/*
++ * This is performance-critical, we want to do it O(1)
++ *
++ * Most irqs are mapped 1:1 with pins.
++ */
+ struct irq_cfg {
+ 	struct irq_pin_list *irq_2_pin;
+ 	cpumask_var_t domain;
+@@ -188,6 +198,12 @@ static struct irq_cfg irq_cfgx[NR_IRQS] 
+ 	[15] = { .vector = IRQ15_VECTOR, },
+ };
+ 
++void __init io_apic_disable_legacy(void)
++{
++	nr_legacy_irqs = 0;
++	nr_irqs_gsi = 0;
++}
++
+ int __init arch_early_irq_init(void)
+ {
+ 	struct irq_cfg *cfg;
+@@ -205,7 +221,7 @@ int __init arch_early_irq_init(void)
+ 		desc->chip_data = &cfg[i];
+ 		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
+ 		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+-		if (i < NR_IRQS_LEGACY)
++		if (i < nr_legacy_irqs)
+ 			cpumask_setall(cfg[i].domain);
+ 	}
+ 
+@@ -231,17 +247,14 @@ static struct irq_cfg *get_one_free_irq_
+ 
+ 	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
+ 	if (cfg) {
+-		if (!alloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
++		if (!zalloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
+ 			kfree(cfg);
+ 			cfg = NULL;
+-		} else if (!alloc_cpumask_var_node(&cfg->old_domain,
++		} else if (!zalloc_cpumask_var_node(&cfg->old_domain,
+ 							  GFP_ATOMIC, node)) {
+ 			free_cpumask_var(cfg->domain);
+ 			kfree(cfg);
+ 			cfg = NULL;
+-		} else {
+-			cpumask_clear(cfg->domain);
+-			cpumask_clear(cfg->old_domain);
+ 		}
+ 	}
+ 
+@@ -455,13 +468,10 @@ static bool io_apic_level_ack_pending(st
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	entry = cfg->irq_2_pin;
+-	for (;;) {
++	for_each_irq_pin(entry, cfg->irq_2_pin) {
+ 		unsigned int reg;
+ 		int pin;
+ 
+-		if (!entry)
+-			break;
+ 		pin = entry->pin;
+ 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ 		/* Is the remote IRR bit set? */
+@@ -469,9 +479,6 @@ static bool io_apic_level_ack_pending(st
+ 			spin_unlock_irqrestore(&ioapic_lock, flags);
+ 			return true;
+ 		}
+-		if (!entry->next)
+-			break;
+-		entry = entry->next;
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+@@ -543,72 +550,68 @@ static void ioapic_mask_entry(int apic, 
+  * shared ISA-space IRQs, so we have to support them. We are super
+  * fast in the common case, and fast for shared ISA-space IRQs.
+  */
+-static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
++static int
++add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
+ {
+-	struct irq_pin_list *entry;
++	struct irq_pin_list **last, *entry;
+ 
+-	entry = cfg->irq_2_pin;
+-	if (!entry) {
+-		entry = get_one_free_irq_2_pin(node);
+-		if (!entry) {
+-			printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
+-					apic, pin);
+-			return;
+-		}
+-		cfg->irq_2_pin = entry;
+-		entry->apic = apic;
+-		entry->pin = pin;
+-		return;
+-	}
+-
+-	while (entry->next) {
+-		/* not again, please */
++	/* don't allow duplicates */
++	last = &cfg->irq_2_pin;
++	for_each_irq_pin(entry, cfg->irq_2_pin) {
+ 		if (entry->apic == apic && entry->pin == pin)
+-			return;
+-
+-		entry = entry->next;
++			return 0;
++		last = &entry->next;
+ 	}
+ 
+-	entry->next = get_one_free_irq_2_pin(node);
+-	entry = entry->next;
++	entry = get_one_free_irq_2_pin(node);
++	if (!entry) {
++		printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
++				node, apic, pin);
++		return -ENOMEM;
++	}
+ 	entry->apic = apic;
+ 	entry->pin = pin;
++
++	*last = entry;
++	return 0;
++}
++
++static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
++{
++	if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
++		panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
+ }
+ 
+ /*
+  * Reroute an IRQ to a different pin.
+  */
+ static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
+-				      int oldapic, int oldpin,
+-				      int newapic, int newpin)
++					   int oldapic, int oldpin,
++					   int newapic, int newpin)
+ {
+-	struct irq_pin_list *entry = cfg->irq_2_pin;
+-	int replaced = 0;
++	struct irq_pin_list *entry;
+ 
+-	while (entry) {
++	for_each_irq_pin(entry, cfg->irq_2_pin) {
+ 		if (entry->apic == oldapic && entry->pin == oldpin) {
+ 			entry->apic = newapic;
+ 			entry->pin = newpin;
+-			replaced = 1;
+ 			/* every one is different, right? */
+-			break;
++			return;
+ 		}
+-		entry = entry->next;
+ 	}
+ 
+-	/* why? call replace before add? */
+-	if (!replaced)
+-		add_pin_to_irq_node(cfg, node, newapic, newpin);
++	/* old apic/pin didn't exist, so just add new ones */
++	add_pin_to_irq_node(cfg, node, newapic, newpin);
+ }
+ 
+-static inline void io_apic_modify_irq(struct irq_cfg *cfg,
+-				int mask_and, int mask_or,
+-				void (*final)(struct irq_pin_list *entry))
++static void io_apic_modify_irq(struct irq_cfg *cfg,
++			       int mask_and, int mask_or,
++			       void (*final)(struct irq_pin_list *entry))
+ {
+ 	int pin;
+ 	struct irq_pin_list *entry;
+ 
+-	for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
++	for_each_irq_pin(entry, cfg->irq_2_pin) {
+ 		unsigned int reg;
+ 		pin = entry->pin;
+ 		reg = io_apic_read(entry->apic, 0x10 + pin * 2);
+@@ -625,7 +628,6 @@ static void __unmask_IO_APIC_irq(struct 
+ 	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
+ }
+ 
+-#ifdef CONFIG_X86_64
+ static void io_apic_sync(struct irq_pin_list *entry)
+ {
+ 	/*
+@@ -641,11 +643,6 @@ static void __mask_IO_APIC_irq(struct ir
+ {
+ 	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+ }
+-#else /* CONFIG_X86_32 */
+-static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+-{
+-	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL);
+-}
+ 
+ static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+@@ -658,7 +655,6 @@ static void __unmask_and_level_IO_APIC_i
+ 	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED,
+ 			IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
+ }
+-#endif /* CONFIG_X86_32 */
+ 
+ static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
+ {
+@@ -719,6 +715,7 @@ static void clear_IO_APIC (void)
+ }
+ #else
+ #define add_pin_to_irq_node(cfg, node, apic, pin)
++#define add_pin_to_irq_node_nopanic(cfg, node, apic, pin) 0
+ #endif /* CONFIG_XEN */
+ 
+ #ifdef CONFIG_X86_32
+@@ -935,7 +932,7 @@ static int __init find_isa_irq_apic(int 
+  */
+ static int EISA_ELCR(unsigned int irq)
+ {
+-	if (irq < NR_IRQS_LEGACY) {
++	if (irq < nr_legacy_irqs) {
+ 		unsigned int port = 0x4d0 + (irq >> 3);
+ 		return (inb(port) >> (irq & 7)) & 1;
+ 	}
+@@ -1547,7 +1544,7 @@ static void setup_IO_APIC_irq(int apic_i
+ 	}
+ 
+ 	ioapic_register_intr(irq, desc, trigger);
+-	if (irq < NR_IRQS_LEGACY)
++	if (irq < nr_legacy_irqs)
+ 		disable_8259A_irq(irq);
+ 
+ 	ioapic_write_entry(apic_id, pin, entry);
+@@ -1775,12 +1772,8 @@ __apicdebuginit(void) print_IO_APIC(void
+ 		if (!entry)
+ 			continue;
+ 		printk(KERN_DEBUG "IRQ%d ", irq);
+-		for (;;) {
++		for_each_irq_pin(entry, cfg->irq_2_pin)
+ 			printk("-> %d:%d", entry->apic, entry->pin);
+-			if (!entry->next)
+-				break;
+-			entry = entry->next;
+-		}
+ 		printk("\n");
+ 	}
+ 
+@@ -1924,7 +1917,7 @@ __apicdebuginit(void) print_PIC(void)
+ 	unsigned int v;
+ 	unsigned long flags;
+ 
+-	if (apic_verbosity == APIC_QUIET)
++	if (apic_verbosity == APIC_QUIET || !nr_legacy_irqs)
+ 		return;
+ 
+ 	printk(KERN_DEBUG "\nprinting PIC contents\n");
+@@ -1956,7 +1949,7 @@ __apicdebuginit(int) print_all_ICs(void)
+ 	print_PIC();
+ 
+ 	/* don't print out if apic is not there */
+-	if (!cpu_has_apic || disable_apic)
++	if (!cpu_has_apic && !apic_from_smp_config())
+ 		return 0;
+ 
+ 	print_all_local_APICs();
+@@ -1990,6 +1983,10 @@ void __init enable_IO_APIC(void)
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+ 	}
++
++	if (!nr_legacy_irqs)
++		return;
++
+ #ifndef CONFIG_XEN
+ 	for(apic = 0; apic < nr_ioapics; apic++) {
+ 		int pin;
+@@ -2049,6 +2046,9 @@ void disable_IO_APIC(void)
+ 	 */
+ 	clear_IO_APIC();
+ 
++	if (!nr_legacy_irqs)
++		return;
++
+ 	/*
+ 	 * If the i8259 is routed through an IOAPIC
+ 	 * Put that IOAPIC in virtual wire mode
+@@ -2082,7 +2082,7 @@ void disable_IO_APIC(void)
+ 	/*
+ 	 * Use virtual wire A mode when interrupt remapping is enabled.
+ 	 */
+-	if (cpu_has_apic)
++	if (cpu_has_apic || apic_from_smp_config())
+ 		disconnect_bsp_APIC(!intr_remapping_enabled &&
+ 				ioapic_i8259.pin != -1);
+ }
+@@ -2095,7 +2095,7 @@ void disable_IO_APIC(void)
+  * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+  */
+ 
+-static void __init setup_ioapic_ids_from_mpc(void)
++void __init setup_ioapic_ids_from_mpc(void)
+ {
+ 	union IO_APIC_reg_00 reg_00;
+ 	physid_mask_t phys_id_present_map;
+@@ -2104,9 +2104,8 @@ static void __init setup_ioapic_ids_from
+ 	unsigned char old_id;
+ 	unsigned long flags;
+ 
+-	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
++	if (acpi_ioapic)
+ 		return;
+-
+ 	/*
+ 	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+ 	 * no meaning without the serial APIC bus.
+@@ -2280,7 +2279,7 @@ static unsigned int startup_ioapic_irq(u
+ 	struct irq_cfg *cfg;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	if (irq < NR_IRQS_LEGACY) {
++	if (irq < nr_legacy_irqs) {
+ 		disable_8259A_irq(irq);
+ 		if (i8259A_irq_pending(irq))
+ 			was_pending = 1;
+@@ -2292,7 +2291,6 @@ static unsigned int startup_ioapic_irq(u
+ 	return was_pending;
+ }
+ 
+-#ifdef CONFIG_X86_64
+ static int ioapic_retrigger_irq(unsigned int irq)
+ {
+ 
+@@ -2305,14 +2303,6 @@ static int ioapic_retrigger_irq(unsigned
+ 
+ 	return 1;
+ }
+-#else
+-static int ioapic_retrigger_irq(unsigned int irq)
+-{
+-	apic->send_IPI_self(irq_cfg(irq)->vector);
+-
+-	return 1;
+-}
+-#endif
+ 
+ /*
+  * Level and edge triggered IO-APIC interrupts need different handling,
+@@ -2350,13 +2340,9 @@ static void __target_IO_APIC_irq(unsigne
+ 	struct irq_pin_list *entry;
+ 	u8 vector = cfg->vector;
+ 
+-	entry = cfg->irq_2_pin;
+-	for (;;) {
++	for_each_irq_pin(entry, cfg->irq_2_pin) {
+ 		unsigned int reg;
+ 
+-		if (!entry)
+-			break;
+-
+ 		apic = entry->apic;
+ 		pin = entry->pin;
+ 		/*
+@@ -2369,9 +2355,6 @@ static void __target_IO_APIC_irq(unsigne
+ 		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+ 		reg |= vector;
+ 		io_apic_modify(apic, 0x10 + pin*2, reg);
+-		if (!entry->next)
+-			break;
+-		entry = entry->next;
+ 	}
+ }
+ 
+@@ -2596,11 +2579,8 @@ atomic_t irq_mis_count;
+ static void ack_apic_level(unsigned int irq)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+-
+-#ifdef CONFIG_X86_32
+ 	unsigned long v;
+ 	int i;
+-#endif
+ 	struct irq_cfg *cfg;
+ 	int do_unmask_irq = 0;
+ 
+@@ -2613,31 +2593,28 @@ static void ack_apic_level(unsigned int 
+ 	}
+ #endif
+ 
+-#ifdef CONFIG_X86_32
+ 	/*
+-	* It appears there is an erratum which affects at least version 0x11
+-	* of I/O APIC (that's the 82093AA and cores integrated into various
+-	* chipsets).  Under certain conditions a level-triggered interrupt is
+-	* erroneously delivered as edge-triggered one but the respective IRR
+-	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
+-	* message but it will never arrive and further interrupts are blocked
+-	* from the source.  The exact reason is so far unknown, but the
+-	* phenomenon was observed when two consecutive interrupt requests
+-	* from a given source get delivered to the same CPU and the source is
+-	* temporarily disabled in between.
+-	*
+-	* A workaround is to simulate an EOI message manually.  We achieve it
+-	* by setting the trigger mode to edge and then to level when the edge
+-	* trigger mode gets detected in the TMR of a local APIC for a
+-	* level-triggered interrupt.  We mask the source for the time of the
+-	* operation to prevent an edge-triggered interrupt escaping meanwhile.
+-	* The idea is from Manfred Spraul.  --macro
+-	*/
++	 * It appears there is an erratum which affects at least version 0x11
++	 * of I/O APIC (that's the 82093AA and cores integrated into various
++	 * chipsets).  Under certain conditions a level-triggered interrupt is
++	 * erroneously delivered as edge-triggered one but the respective IRR
++	 * bit gets set nevertheless.  As a result the I/O unit expects an EOI
++	 * message but it will never arrive and further interrupts are blocked
++	 * from the source.  The exact reason is so far unknown, but the
++	 * phenomenon was observed when two consecutive interrupt requests
++	 * from a given source get delivered to the same CPU and the source is
++	 * temporarily disabled in between.
++	 *
++	 * A workaround is to simulate an EOI message manually.  We achieve it
++	 * by setting the trigger mode to edge and then to level when the edge
++	 * trigger mode gets detected in the TMR of a local APIC for a
++	 * level-triggered interrupt.  We mask the source for the time of the
++	 * operation to prevent an edge-triggered interrupt escaping meanwhile.
++	 * The idea is from Manfred Spraul.  --macro
++	 */
+ 	cfg = desc->chip_data;
+ 	i = cfg->vector;
+-
+ 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+-#endif
+ 
+ 	/*
+ 	 * We must acknowledge the irq before we move it or the acknowledge will
+@@ -2679,7 +2656,7 @@ static void ack_apic_level(unsigned int 
+ 		unmask_IO_APIC_irq_desc(desc);
+ 	}
+ 
+-#ifdef CONFIG_X86_32
++	/* Tail end of version 0x11 I/O APIC bug workaround */
+ 	if (!(v & (1 << (i & 0x1f)))) {
+ 		atomic_inc(&irq_mis_count);
+ 		spin_lock(&ioapic_lock);
+@@ -2687,26 +2664,15 @@ static void ack_apic_level(unsigned int 
+ 		__unmask_and_level_IO_APIC_irq(cfg);
+ 		spin_unlock(&ioapic_lock);
+ 	}
+-#endif
+ }
+ 
+ #ifdef CONFIG_INTR_REMAP
+ static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+ {
+-	int apic, pin;
+ 	struct irq_pin_list *entry;
+ 
+-	entry = cfg->irq_2_pin;
+-	for (;;) {
+-
+-		if (!entry)
+-			break;
+-
+-		apic = entry->apic;
+-		pin = entry->pin;
+-		io_apic_eoi(apic, pin);
+-		entry = entry->next;
+-	}
++	for_each_irq_pin(entry, cfg->irq_2_pin)
++		io_apic_eoi(entry->apic, entry->pin);
+ }
+ 
+ static void
+@@ -2796,7 +2762,7 @@ static inline void init_IO_APIC_traps(vo
+ 			 * so default to an old-fashioned 8259
+ 			 * interrupt if we can..
+ 			 */
+-			if (irq < NR_IRQS_LEGACY)
++			if (irq < nr_legacy_irqs)
+ 				make_8259A_irq(irq);
+ 			else
+ 				/* Strange. Oh, well.. */
+@@ -3136,7 +3102,7 @@ out:
+  * the I/O APIC in all cases now.  No actual device should request
+  * it anyway.  --macro
+  */
+-#define PIC_IRQS	(1 << PIC_CASCADE_IR)
++#define PIC_IRQS	(1UL << PIC_CASCADE_IR)
+ 
+ void __init setup_IO_APIC(void)
+ {
+@@ -3148,23 +3114,21 @@ void __init setup_IO_APIC(void)
+ 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
+ 	 */
+ #endif
+-
+-	io_apic_irqs = ~PIC_IRQS;
++	io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+ 
+ 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ 	/*
+          * Set up IO-APIC IRQ routing.
+          */
+ #ifndef CONFIG_XEN
+-#ifdef CONFIG_X86_32
+-	if (!acpi_ioapic)
+-		setup_ioapic_ids_from_mpc();
+-#endif
++	x86_init.mpparse.setup_ioapic_ids();
++
+ 	sync_Arb_IDs();
+ #endif
+ 	setup_IO_APIC_irqs();
+ 	init_IO_APIC_traps();
+-	check_timer();
++	if (nr_legacy_irqs)
++		check_timer();
+ }
+ 
+ /*
+@@ -3274,7 +3238,6 @@ static int __init ioapic_init_sysfs(void
+ 
+ device_initcall(ioapic_init_sysfs);
+ 
+-static int nr_irqs_gsi = NR_IRQS_LEGACY;
+ /*
+  * Dynamic irq allocate and deallocation
+  */
+@@ -3346,8 +3309,7 @@ void destroy_irq(unsigned int irq)
+ 	cfg = desc->chip_data;
+ 	dynamic_irq_cleanup(irq);
+ 	/* connect back irq_cfg */
+-	if (desc)
+-		desc->chip_data = cfg;
++	desc->chip_data = cfg;
+ 
+ 	free_irte(irq);
+ 	spin_lock_irqsave(&vector_lock, flags);
+@@ -4025,9 +3987,13 @@ static int __io_apic_set_pci_routing(str
+ 	/*
+ 	 * IRQs < 16 are already in the irq_2_pin[] map
+ 	 */
+-	if (irq >= NR_IRQS_LEGACY) {
++	if (irq >= nr_legacy_irqs) {
+ 		cfg = desc->chip_data;
+-		add_pin_to_irq_node(cfg, node, ioapic, pin);
++		if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
++			printk(KERN_INFO "can not add pin %d for irq %d\n",
++				pin, irq);
++			return 0;
++		}
+ 	}
+ 
+ 	setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+@@ -4056,11 +4022,28 @@ int io_apic_set_pci_routing(struct devic
+ 	return __io_apic_set_pci_routing(dev, irq, irq_attr);
+ }
+ 
+-/* --------------------------------------------------------------------------
+-                          ACPI-based IOAPIC Configuration
+-   -------------------------------------------------------------------------- */
++u8 __init io_apic_unique_id(u8 id)
++{
++#ifdef CONFIG_X86_32
++	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
++	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		return io_apic_get_unique_id(nr_ioapics, id);
++	else
++		return id;
++#else
++	int i;
++	DECLARE_BITMAP(used, 256);
+ 
+-#ifdef CONFIG_ACPI
++	bitmap_zero(used, 256);
++	for (i = 0; i < nr_ioapics; i++) {
++		struct mpc_ioapic *ia = &mp_ioapics[i];
++		__set_bit(ia->apicid, used);
++	}
++	if (!test_bit(id, used))
++		return id;
++	return find_first_zero_bit(used, 256);
++#endif
++}
+ 
+ #ifdef CONFIG_X86_32
+ int __init io_apic_get_unique_id(int ioapic, int apic_id)
+@@ -4171,8 +4154,6 @@ int acpi_get_override_irq(int bus_irq, i
+ 	return 0;
+ }
+ 
+-#endif /* CONFIG_ACPI */
+-
+ #ifndef CONFIG_XEN
+ /*
+  * This function currently is only a helper for the i386 smp boot process where
+@@ -4227,7 +4208,7 @@ void __init setup_ioapic_dest(void)
+ 
+ static struct resource *ioapic_resources;
+ 
+-static struct resource * __init ioapic_setup_resources(void)
++static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+ {
+ 	unsigned long n;
+ 	struct resource *res;
+@@ -4243,15 +4224,13 @@ static struct resource * __init ioapic_s
+ 	mem = alloc_bootmem(n);
+ 	res = (void *)mem;
+ 
+-	if (mem != NULL) {
+-		mem += sizeof(struct resource) * nr_ioapics;
++	mem += sizeof(struct resource) * nr_ioapics;
+ 
+-		for (i = 0; i < nr_ioapics; i++) {
+-			res[i].name = mem;
+-			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-			sprintf(mem,  "IOAPIC %u", i);
+-			mem += IOAPIC_RESOURCE_NAME_SIZE;
+-		}
++	for (i = 0; i < nr_ioapics; i++) {
++		res[i].name = mem;
++		res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++		sprintf(mem,  "IOAPIC %u", i);
++		mem += IOAPIC_RESOURCE_NAME_SIZE;
+ 	}
+ 
+ 	ioapic_resources = res;
+@@ -4265,7 +4244,7 @@ void __init ioapic_init_mappings(void)
+ 	struct resource *ioapic_res;
+ 	int i;
+ 
+-	ioapic_res = ioapic_setup_resources();
++	ioapic_res = ioapic_setup_resources(nr_ioapics);
+ 	for (i = 0; i < nr_ioapics; i++) {
+ 		if (smp_found_config) {
+ 			ioapic_phys = mp_ioapics[i].apicaddr;
+@@ -4294,11 +4273,9 @@ fake_ioapic_page:
+ 			    __fix_to_virt(idx), ioapic_phys);
+ 		idx++;
+ 
+-		if (ioapic_res != NULL) {
+-			ioapic_res->start = ioapic_phys;
+-			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+-			ioapic_res++;
+-		}
++		ioapic_res->start = ioapic_phys;
++		ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
++		ioapic_res++;
+ 	}
+ }
+ 
+@@ -4320,3 +4297,78 @@ void __init ioapic_insert_resources(void
+ 	}
+ }
+ #endif /* !CONFIG_XEN */
++
++int mp_find_ioapic(int gsi)
++{
++	int i = 0;
++
++	/* Find the IOAPIC that manages this GSI. */
++	for (i = 0; i < nr_ioapics; i++) {
++		if ((gsi >= mp_gsi_routing[i].gsi_base)
++		    && (gsi <= mp_gsi_routing[i].gsi_end))
++			return i;
++	}
++
++	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++	return -1;
++}
++
++int mp_find_ioapic_pin(int ioapic, int gsi)
++{
++	if (WARN_ON(ioapic == -1))
++		return -1;
++	if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end))
++		return -1;
++
++	return gsi - mp_gsi_routing[ioapic].gsi_base;
++}
++
++static int bad_ioapic(unsigned long address)
++{
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
++		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
++		return 1;
++	}
++	if (!address) {
++		printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
++		       " found in table, skipping!\n");
++		return 1;
++	}
++	return 0;
++}
++
++void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
++{
++	int idx = 0;
++
++	if (bad_ioapic(address))
++		return;
++
++	idx = nr_ioapics;
++
++	mp_ioapics[idx].type = MP_IOAPIC;
++	mp_ioapics[idx].flags = MPC_APIC_USABLE;
++	mp_ioapics[idx].apicaddr = address;
++
++#ifndef CONFIG_XEN
++	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++#endif
++	mp_ioapics[idx].apicid = io_apic_unique_id(id);
++	mp_ioapics[idx].apicver = io_apic_get_version(idx);
++
++	/*
++	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
++	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
++	 */
++	mp_gsi_routing[idx].gsi_base = gsi_base;
++	mp_gsi_routing[idx].gsi_end = gsi_base +
++	    io_apic_get_redir_entries(idx);
++
++	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++	       "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
++	       mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
++	       mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end);
++
++	nr_ioapics++;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/Makefile	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/Makefile	2009-11-06 10:52:22.000000000 +0100
+@@ -35,7 +35,7 @@ obj-$(CONFIG_CPU_FREQ)			+= cpufreq/
+ 
+ obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
+ 
+-disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o
++disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o
+ 
+ quiet_cmd_mkcapflags = MKCAP   $@
+       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/amd.c	2010-01-18 16:53:52.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/amd.c	2010-01-18 16:55:14.000000000 +0100
+@@ -336,7 +336,7 @@ static void __cpuinit amd_detect_cmp(str
+ int amd_get_nb_id(int cpu)
+ {
+ 	int id = 0;
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ 	id = per_cpu(cpu_llc_id, cpu);
+ #endif
+ 	return id;
+@@ -492,8 +492,10 @@ static void __cpuinit init_amd(struct cp
+ 	if (c->x86 == 0x10 || c->x86 == 0x11)
+ 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ 
++#ifndef CONFIG_XEN
+ 	/* get apicid instead of initial apic id from cpuid */
+ 	c->apicid = hard_smp_processor_id();
++#endif
+ #else
+ 
+ 	/*
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -13,13 +13,13 @@
+ #include <linux/io.h>
+ 
+ #include <asm/stackprotector.h>
+-#include <asm/perf_counter.h>
++#include <asm/perf_event.h>
+ #include <asm/mmu_context.h>
+ #include <asm/hypervisor.h>
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+-#include <asm/topology.h>
+-#include <asm/cpumask.h>
++#include <linux/topology.h>
++#include <linux/cpumask.h>
+ #include <asm/pgtable.h>
+ #include <asm/atomic.h>
+ #include <asm/proto.h>
+@@ -28,13 +28,12 @@
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/mtrr.h>
+-#include <asm/numa.h>
++#include <linux/numa.h>
+ #include <asm/asm.h>
+ #include <asm/cpu.h>
+ #include <asm/mce.h>
+ #include <asm/msr.h>
+ #include <asm/pat.h>
+-#include <asm/smp.h>
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #include <asm/uv/uv.h>
+@@ -102,17 +101,17 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_p
+ 	 * TLS descriptors are currently at a different place compared to i386.
+ 	 * Hopefully nobody expects them at a fixed place (Wine?)
+ 	 */
+-	[GDT_ENTRY_KERNEL32_CS]		= { { { 0x0000ffff, 0x00cf9b00 } } },
+-	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00af9b00 } } },
+-	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9300 } } },
+-	[GDT_ENTRY_DEFAULT_USER32_CS]	= { { { 0x0000ffff, 0x00cffb00 } } },
+-	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff300 } } },
+-	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00affb00 } } },
++	[GDT_ENTRY_KERNEL32_CS]		= GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
++	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
++	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
++	[GDT_ENTRY_DEFAULT_USER32_CS]	= GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),
++	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),
++	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),
+ #else
+-	[GDT_ENTRY_KERNEL_CS]		= { { { 0x0000ffff, 0x00cf9a00 } } },
+-	[GDT_ENTRY_KERNEL_DS]		= { { { 0x0000ffff, 0x00cf9200 } } },
+-	[GDT_ENTRY_DEFAULT_USER_CS]	= { { { 0x0000ffff, 0x00cffa00 } } },
+-	[GDT_ENTRY_DEFAULT_USER_DS]	= { { { 0x0000ffff, 0x00cff200 } } },
++	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),
++	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
++	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff),
++	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),
+ #ifndef CONFIG_XEN
+ 	/*
+ 	 * Segments used for calling PnP BIOS have byte granularity.
+@@ -120,29 +119,29 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_p
+ 	 * the transfer segment sizes are set at run time.
+ 	 */
+ 	/* 32-bit code */
+-	[GDT_ENTRY_PNPBIOS_CS32]	= { { { 0x0000ffff, 0x00409a00 } } },
++	[GDT_ENTRY_PNPBIOS_CS32]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+ 	/* 16-bit code */
+-	[GDT_ENTRY_PNPBIOS_CS16]	= { { { 0x0000ffff, 0x00009a00 } } },
++	[GDT_ENTRY_PNPBIOS_CS16]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_DS]		= { { { 0x0000ffff, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_DS]		= GDT_ENTRY_INIT(0x0092, 0, 0xffff),
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS1]		= { { { 0x00000000, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_TS1]		= GDT_ENTRY_INIT(0x0092, 0, 0),
+ 	/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS2]		= { { { 0x00000000, 0x00009200 } } },
++	[GDT_ENTRY_PNPBIOS_TS2]		= GDT_ENTRY_INIT(0x0092, 0, 0),
+ 	/*
+ 	 * The APM segments have byte granularity and their bases
+ 	 * are set at run time.  All have 64k limits.
+ 	 */
+ 	/* 32-bit code */
+-	[GDT_ENTRY_APMBIOS_BASE]	= { { { 0x0000ffff, 0x00409a00 } } },
++	[GDT_ENTRY_APMBIOS_BASE]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+ 	/* 16-bit code */
+-	[GDT_ENTRY_APMBIOS_BASE+1]	= { { { 0x0000ffff, 0x00009a00 } } },
++	[GDT_ENTRY_APMBIOS_BASE+1]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+ 	/* data */
+-	[GDT_ENTRY_APMBIOS_BASE+2]	= { { { 0x0000ffff, 0x00409200 } } },
++	[GDT_ENTRY_APMBIOS_BASE+2]	= GDT_ENTRY_INIT(0x4092, 0, 0xffff),
+ 
+-	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x0000ffff, 0x00cf9200 } } },
++	[GDT_ENTRY_ESPFIX_SS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+ #endif
+-	[GDT_ENTRY_PERCPU]		= { { { 0x0000ffff, 0x00cf9200 } } },
++	[GDT_ENTRY_PERCPU]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+ 	GDT_STACK_CANARY_INIT
+ #endif
+ } };
+@@ -900,7 +899,7 @@ void __init identify_boot_cpu(void)
+ #else
+ 	vgetcpu_set_mode();
+ #endif
+-	init_hw_perf_counters();
++	init_hw_perf_events();
+ }
+ 
+ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+@@ -1013,7 +1012,7 @@ __setup("clearcpuid=", setup_disablecpui
+ 
+ #ifdef CONFIG_X86_64
+ #ifndef CONFIG_X86_NO_IDT
+-struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
++struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
+ #endif
+ 
+ DEFINE_PER_CPU_FIRST(union irq_stack_union,
+@@ -1027,13 +1026,21 @@ void xen_switch_pt(void)
+ #endif
+ }
+ 
+-DEFINE_PER_CPU(char *, irq_stack_ptr) =
+-	init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
++/*
++ * The following four percpu variables are hot.  Align current_task to
++ * cacheline size such that all four fall in the same cacheline.
++ */
++DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned =
++	&init_task;
++EXPORT_PER_CPU_SYMBOL(current_task);
+ 
+ DEFINE_PER_CPU(unsigned long, kernel_stack) =
+ 	(unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+ EXPORT_PER_CPU_SYMBOL(kernel_stack);
+ 
++DEFINE_PER_CPU(char *, irq_stack_ptr) =
++	init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
++
+ DEFINE_PER_CPU(unsigned int, irq_count) = -1;
+ 
+ #ifndef CONFIG_X86_NO_TSS
+@@ -1049,8 +1056,7 @@ static const unsigned int exception_stac
+ };
+ 
+ static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
+-	[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ])
+-	__aligned(PAGE_SIZE);
++	[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
+ #endif
+ 
+ void __cpuinit syscall_init(void)
+@@ -1097,8 +1103,11 @@ DEFINE_PER_CPU(struct orig_ist, orig_ist
+ 
+ #else	/* CONFIG_X86_64 */
+ 
++DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
++EXPORT_PER_CPU_SYMBOL(current_task);
++
+ #ifdef CONFIG_CC_STACKPROTECTOR
+-DEFINE_PER_CPU(unsigned long, stack_canary);
++DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+ #endif
+ 
+ /* Make sure %fs and %gs are initialized properly in idle threads */
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mcheck/mce-inject.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mcheck/mce-inject.c	2009-11-06 10:52:22.000000000 +0100
+@@ -143,7 +143,7 @@ static void raise_mce(struct mce *m)
+ 	if (context == MCJ_CTX_RANDOM)
+ 		return;
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	if (m->inject_flags & MCJ_NMI_BROADCAST) {
+ 		unsigned long start;
+ 		int cpu;
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -1,10 +1,9 @@
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/ctype.h>
++#define DEBUG
++
++#include <linux/uaccess.h>
+ #include <linux/module.h>
+-#include <linux/seq_file.h>
+-#include <asm/uaccess.h>
+ #include <linux/mutex.h>
++#include <linux/init.h>
+ 
+ #include <asm/mtrr.h>
+ #include "mtrr.h"
+@@ -58,7 +57,7 @@ static void __init init_table(void)
+ 		mtrr_usage_table[i] = 0;
+ }
+ 
+-int mtrr_add_page(unsigned long base, unsigned long size, 
++int mtrr_add_page(unsigned long base, unsigned long size,
+ 		  unsigned int type, bool increment)
+ {
+ 	int error;
+@@ -88,25 +87,23 @@ int mtrr_add_page(unsigned long base, un
+ static int mtrr_check(unsigned long base, unsigned long size)
+ {
+ 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
+-		printk(KERN_WARNING
+-			"mtrr: size and base must be multiples of 4 kiB\n");
+-		printk(KERN_DEBUG
+-			"mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
++		pr_warning("mtrr: size and base must be multiples of 4 kiB\n");
++		pr_debug("mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+ 		dump_stack();
+ 		return -1;
+ 	}
+ 	return 0;
+ }
+ 
+-int
+-mtrr_add(unsigned long base, unsigned long size, unsigned int type,
+-	 bool increment)
++int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
++	     bool increment)
+ {
+ 	if (mtrr_check(base, size))
+ 		return -EINVAL;
+ 	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
+ 			     increment);
+ }
++EXPORT_SYMBOL(mtrr_add);
+ 
+ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+ {
+@@ -128,13 +125,13 @@ int mtrr_del_page(int reg, unsigned long
+ 			}
+ 		}
+ 		if (reg < 0) {
+-			printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
+-			       size);
++			pr_debug("mtrr: no MTRR for %lx000,%lx000 found\n",
++				 base, size);
+ 			goto out;
+ 		}
+ 	}
+ 	if (mtrr_usage_table[reg] < 1) {
+-		printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
++		pr_warning("mtrr: reg: %d has count=0\n", reg);
+ 		goto out;
+ 	}
+ 	if (--mtrr_usage_table[reg] < 1) {
+@@ -153,15 +150,12 @@ int mtrr_del_page(int reg, unsigned long
+ 	return error;
+ }
+ 
+-int
+-mtrr_del(int reg, unsigned long base, unsigned long size)
++int mtrr_del(int reg, unsigned long base, unsigned long size)
+ {
+ 	if (mtrr_check(base, size))
+ 		return -EINVAL;
+ 	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
+ }
+-
+-EXPORT_SYMBOL(mtrr_add);
+ EXPORT_SYMBOL(mtrr_del);
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/e820-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820-xen.c	2009-12-04 11:31:40.000000000 +0100
+@@ -134,7 +134,7 @@ static void __init __e820_add_region(str
+ {
+ 	int x = e820x->nr_map;
+ 
+-	if (x == ARRAY_SIZE(e820x->map)) {
++	if (x >= ARRAY_SIZE(e820x->map)) {
+ 		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+ 		return;
+ 	}
+@@ -1455,7 +1455,7 @@ void __init e820_reserve_resources(void)
+ 	struct resource *res;
+ 	u64 end;
+ 
+-	res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
++	res = alloc_bootmem(sizeof(struct resource) * e820.nr_map);
+ 	e820_res = res;
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		end = e820.map[i].addr + e820.map[i].size - 1;
+@@ -1502,8 +1502,8 @@ static unsigned long ram_alignment(resou
+ 	if (mb < 16)
+ 		return 1024*1024;
+ 
+-	/* To 32MB for anything above that */
+-	return 32*1024*1024;
++	/* To 64MB for anything above that */
++	return 64*1024*1024;
+ }
+ 
+ #define MAX_RESOURCE_SIZE ((resource_size_t)-1)
+@@ -1543,59 +1543,8 @@ void __init e820_reserve_resources_late(
+ 
+ #undef e820
+ 
+-#ifndef CONFIG_XEN
+ char *__init default_machine_specific_memory_setup(void)
+ {
+-	char *who = "BIOS-e820";
+-	u32 new_nr;
+-	/*
+-	 * Try to copy the BIOS-supplied E820-map.
+-	 *
+-	 * Otherwise fake a memory map; one section from 0k->640k,
+-	 * the next section from 1mb->appropriate_mem_k
+-	 */
+-	new_nr = boot_params.e820_entries;
+-	sanitize_e820_map(boot_params.e820_map,
+-			ARRAY_SIZE(boot_params.e820_map),
+-			&new_nr);
+-	boot_params.e820_entries = new_nr;
+-	if (append_e820_map(boot_params.e820_map, boot_params.e820_entries)
+-	  < 0) {
+-		u64 mem_size;
+-
+-		/* compare results from other methods and take the greater */
+-		if (boot_params.alt_mem_k
+-		    < boot_params.screen_info.ext_mem_k) {
+-			mem_size = boot_params.screen_info.ext_mem_k;
+-			who = "BIOS-88";
+-		} else {
+-			mem_size = boot_params.alt_mem_k;
+-			who = "BIOS-e801";
+-		}
+-
+-		e820.nr_map = 0;
+-		e820_add_region(0, LOWMEMSIZE(), E820_RAM);
+-		e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+-	}
+-
+-	/* In case someone cares... */
+-	return who;
+-}
+-
+-char *__init __attribute__((weak)) machine_specific_memory_setup(void)
+-{
+-	if (x86_quirks->arch_memory_setup) {
+-		char *who = x86_quirks->arch_memory_setup();
+-
+-		if (who)
+-			return who;
+-	}
+-	return default_machine_specific_memory_setup();
+-}
+-#endif
+-
+-static char * __init _memory_setup(void)
+-{
+ 	int rc, nr_map;
+ 	struct xen_memory_map memmap;
+ 	static struct e820entry __initdata map[E820MAX];
+@@ -1639,7 +1588,7 @@ void __init setup_memory_map(void)
+ {
+ 	char *who;
+ 
+-	who = _memory_setup();
++	who = x86_init.resources.memory_setup();
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain()) {
+ 		printk(KERN_INFO "Xen-provided machine memory map:\n");
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -178,7 +178,6 @@ static __init void early_serial_init(cha
+  * mappings. Someone should fix this for domain 0. For now, use fake serial.
+  */
+ #define early_vga_console early_serial_console
+-#define xenboot_console early_serial_console
+ 
+ #endif
+ 
+@@ -189,721 +188,6 @@ static struct console early_serial_conso
+ 	.index =	-1,
+ };
+ 
+-#ifdef CONFIG_EARLY_PRINTK_DBGP
+-
+-static struct ehci_caps __iomem *ehci_caps;
+-static struct ehci_regs __iomem *ehci_regs;
+-static struct ehci_dbg_port __iomem *ehci_debug;
+-static unsigned int dbgp_endpoint_out;
+-
+-struct ehci_dev {
+-	u32 bus;
+-	u32 slot;
+-	u32 func;
+-};
+-
+-static struct ehci_dev ehci_dev;
+-
+-#define USB_DEBUG_DEVNUM 127
+-
+-#define DBGP_DATA_TOGGLE	0x8800
+-
+-static inline u32 dbgp_pid_update(u32 x, u32 tok)
+-{
+-	return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff);
+-}
+-
+-static inline u32 dbgp_len_update(u32 x, u32 len)
+-{
+-	return (x & ~0x0f) | (len & 0x0f);
+-}
+-
+-/*
+- * USB Packet IDs (PIDs)
+- */
+-
+-/* token */
+-#define USB_PID_OUT		0xe1
+-#define USB_PID_IN		0x69
+-#define USB_PID_SOF		0xa5
+-#define USB_PID_SETUP		0x2d
+-/* handshake */
+-#define USB_PID_ACK		0xd2
+-#define USB_PID_NAK		0x5a
+-#define USB_PID_STALL		0x1e
+-#define USB_PID_NYET		0x96
+-/* data */
+-#define USB_PID_DATA0		0xc3
+-#define USB_PID_DATA1		0x4b
+-#define USB_PID_DATA2		0x87
+-#define USB_PID_MDATA		0x0f
+-/* Special */
+-#define USB_PID_PREAMBLE	0x3c
+-#define USB_PID_ERR		0x3c
+-#define USB_PID_SPLIT		0x78
+-#define USB_PID_PING		0xb4
+-#define USB_PID_UNDEF_0		0xf0
+-
+-#define USB_PID_DATA_TOGGLE	0x88
+-#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
+-
+-#define PCI_CAP_ID_EHCI_DEBUG	0xa
+-
+-#define HUB_ROOT_RESET_TIME	50	/* times are in msec */
+-#define HUB_SHORT_RESET_TIME	10
+-#define HUB_LONG_RESET_TIME	200
+-#define HUB_RESET_TIMEOUT	500
+-
+-#define DBGP_MAX_PACKET		8
+-
+-static int dbgp_wait_until_complete(void)
+-{
+-	u32 ctrl;
+-	int loop = 0x100000;
+-
+-	do {
+-		ctrl = readl(&ehci_debug->control);
+-		/* Stop when the transaction is finished */
+-		if (ctrl & DBGP_DONE)
+-			break;
+-	} while (--loop > 0);
+-
+-	if (!loop)
+-		return -1;
+-
+-	/*
+-	 * Now that we have observed the completed transaction,
+-	 * clear the done bit.
+-	 */
+-	writel(ctrl | DBGP_DONE, &ehci_debug->control);
+-	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
+-}
+-
+-static void __init dbgp_mdelay(int ms)
+-{
+-	int i;
+-
+-	while (ms--) {
+-		for (i = 0; i < 1000; i++)
+-			outb(0x1, 0x80);
+-	}
+-}
+-
+-static void dbgp_breath(void)
+-{
+-	/* Sleep to give the debug port a chance to breathe */
+-}
+-
+-static int dbgp_wait_until_done(unsigned ctrl)
+-{
+-	u32 pids, lpid;
+-	int ret;
+-	int loop = 3;
+-
+-retry:
+-	writel(ctrl | DBGP_GO, &ehci_debug->control);
+-	ret = dbgp_wait_until_complete();
+-	pids = readl(&ehci_debug->pids);
+-	lpid = DBGP_PID_GET(pids);
+-
+-	if (ret < 0)
+-		return ret;
+-
+-	/*
+-	 * If the port is getting full or it has dropped data
+-	 * start pacing ourselves, not necessary but it's friendly.
+-	 */
+-	if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
+-		dbgp_breath();
+-
+-	/* If I get a NACK reissue the transmission */
+-	if (lpid == USB_PID_NAK) {
+-		if (--loop > 0)
+-			goto retry;
+-	}
+-
+-	return ret;
+-}
+-
+-static void dbgp_set_data(const void *buf, int size)
+-{
+-	const unsigned char *bytes = buf;
+-	u32 lo, hi;
+-	int i;
+-
+-	lo = hi = 0;
+-	for (i = 0; i < 4 && i < size; i++)
+-		lo |= bytes[i] << (8*i);
+-	for (; i < 8 && i < size; i++)
+-		hi |= bytes[i] << (8*(i - 4));
+-	writel(lo, &ehci_debug->data03);
+-	writel(hi, &ehci_debug->data47);
+-}
+-
+-static void __init dbgp_get_data(void *buf, int size)
+-{
+-	unsigned char *bytes = buf;
+-	u32 lo, hi;
+-	int i;
+-
+-	lo = readl(&ehci_debug->data03);
+-	hi = readl(&ehci_debug->data47);
+-	for (i = 0; i < 4 && i < size; i++)
+-		bytes[i] = (lo >> (8*i)) & 0xff;
+-	for (; i < 8 && i < size; i++)
+-		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
+-}
+-
+-static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
+-			 const char *bytes, int size)
+-{
+-	u32 pids, addr, ctrl;
+-	int ret;
+-
+-	if (size > DBGP_MAX_PACKET)
+-		return -1;
+-
+-	addr = DBGP_EPADDR(devnum, endpoint);
+-
+-	pids = readl(&ehci_debug->pids);
+-	pids = dbgp_pid_update(pids, USB_PID_OUT);
+-
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl = dbgp_len_update(ctrl, size);
+-	ctrl |= DBGP_OUT;
+-	ctrl |= DBGP_GO;
+-
+-	dbgp_set_data(bytes, size);
+-	writel(addr, &ehci_debug->address);
+-	writel(pids, &ehci_debug->pids);
+-
+-	ret = dbgp_wait_until_done(ctrl);
+-	if (ret < 0)
+-		return ret;
+-
+-	return ret;
+-}
+-
+-static int __init dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
+-				 int size)
+-{
+-	u32 pids, addr, ctrl;
+-	int ret;
+-
+-	if (size > DBGP_MAX_PACKET)
+-		return -1;
+-
+-	addr = DBGP_EPADDR(devnum, endpoint);
+-
+-	pids = readl(&ehci_debug->pids);
+-	pids = dbgp_pid_update(pids, USB_PID_IN);
+-
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl = dbgp_len_update(ctrl, size);
+-	ctrl &= ~DBGP_OUT;
+-	ctrl |= DBGP_GO;
+-
+-	writel(addr, &ehci_debug->address);
+-	writel(pids, &ehci_debug->pids);
+-	ret = dbgp_wait_until_done(ctrl);
+-	if (ret < 0)
+-		return ret;
+-
+-	if (size > ret)
+-		size = ret;
+-	dbgp_get_data(data, size);
+-	return ret;
+-}
+-
+-static int __init dbgp_control_msg(unsigned devnum, int requesttype,
+-	int request, int value, int index, void *data, int size)
+-{
+-	u32 pids, addr, ctrl;
+-	struct usb_ctrlrequest req;
+-	int read;
+-	int ret;
+-
+-	read = (requesttype & USB_DIR_IN) != 0;
+-	if (size > (read ? DBGP_MAX_PACKET:0))
+-		return -1;
+-
+-	/* Compute the control message */
+-	req.bRequestType = requesttype;
+-	req.bRequest = request;
+-	req.wValue = cpu_to_le16(value);
+-	req.wIndex = cpu_to_le16(index);
+-	req.wLength = cpu_to_le16(size);
+-
+-	pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
+-	addr = DBGP_EPADDR(devnum, 0);
+-
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl = dbgp_len_update(ctrl, sizeof(req));
+-	ctrl |= DBGP_OUT;
+-	ctrl |= DBGP_GO;
+-
+-	/* Send the setup message */
+-	dbgp_set_data(&req, sizeof(req));
+-	writel(addr, &ehci_debug->address);
+-	writel(pids, &ehci_debug->pids);
+-	ret = dbgp_wait_until_done(ctrl);
+-	if (ret < 0)
+-		return ret;
+-
+-	/* Read the result */
+-	return dbgp_bulk_read(devnum, 0, data, size);
+-}
+-
+-
+-/* Find a PCI capability */
+-static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap)
+-{
+-	u8 pos;
+-	int bytes;
+-
+-	if (!(read_pci_config_16(num, slot, func, PCI_STATUS) &
+-		PCI_STATUS_CAP_LIST))
+-		return 0;
+-
+-	pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST);
+-	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
+-		u8 id;
+-
+-		pos &= ~3;
+-		id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID);
+-		if (id == 0xff)
+-			break;
+-		if (id == cap)
+-			return pos;
+-
+-		pos = read_pci_config_byte(num, slot, func,
+-						 pos+PCI_CAP_LIST_NEXT);
+-	}
+-	return 0;
+-}
+-
+-static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func)
+-{
+-	u32 class;
+-
+-	class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
+-	if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI)
+-		return 0;
+-
+-	return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG);
+-}
+-
+-static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc)
+-{
+-	u32 bus, slot, func;
+-
+-	for (bus = 0; bus < 256; bus++) {
+-		for (slot = 0; slot < 32; slot++) {
+-			for (func = 0; func < 8; func++) {
+-				unsigned cap;
+-
+-				cap = __find_dbgp(bus, slot, func);
+-
+-				if (!cap)
+-					continue;
+-				if (ehci_num-- != 0)
+-					continue;
+-				*rbus = bus;
+-				*rslot = slot;
+-				*rfunc = func;
+-				return cap;
+-			}
+-		}
+-	}
+-	return 0;
+-}
+-
+-static int __init ehci_reset_port(int port)
+-{
+-	u32 portsc;
+-	u32 delay_time, delay;
+-	int loop;
+-
+-	/* Reset the usb debug port */
+-	portsc = readl(&ehci_regs->port_status[port - 1]);
+-	portsc &= ~PORT_PE;
+-	portsc |= PORT_RESET;
+-	writel(portsc, &ehci_regs->port_status[port - 1]);
+-
+-	delay = HUB_ROOT_RESET_TIME;
+-	for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
+-	     delay_time += delay) {
+-		dbgp_mdelay(delay);
+-
+-		portsc = readl(&ehci_regs->port_status[port - 1]);
+-		if (portsc & PORT_RESET) {
+-			/* force reset to complete */
+-			loop = 2;
+-			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET),
+-				&ehci_regs->port_status[port - 1]);
+-			do {
+-				portsc = readl(&ehci_regs->port_status[port-1]);
+-			} while ((portsc & PORT_RESET) && (--loop > 0));
+-		}
+-
+-		/* Device went away? */
+-		if (!(portsc & PORT_CONNECT))
+-			return -ENOTCONN;
+-
+-		/* bomb out completely if something weird happend */
+-		if ((portsc & PORT_CSC))
+-			return -EINVAL;
+-
+-		/* If we've finished resetting, then break out of the loop */
+-		if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
+-			return 0;
+-	}
+-	return -EBUSY;
+-}
+-
+-static int __init ehci_wait_for_port(int port)
+-{
+-	u32 status;
+-	int ret, reps;
+-
+-	for (reps = 0; reps < 3; reps++) {
+-		dbgp_mdelay(100);
+-		status = readl(&ehci_regs->status);
+-		if (status & STS_PCD) {
+-			ret = ehci_reset_port(port);
+-			if (ret == 0)
+-				return 0;
+-		}
+-	}
+-	return -ENOTCONN;
+-}
+-
+-#ifdef DBGP_DEBUG
+-# define dbgp_printk early_printk
+-#else
+-static inline void dbgp_printk(const char *fmt, ...) { }
+-#endif
+-
+-typedef void (*set_debug_port_t)(int port);
+-
+-static void __init default_set_debug_port(int port)
+-{
+-}
+-
+-static set_debug_port_t __initdata set_debug_port = default_set_debug_port;
+-
+-static void __init nvidia_set_debug_port(int port)
+-{
+-	u32 dword;
+-	dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
+-				 0x74);
+-	dword &= ~(0x0f<<12);
+-	dword |= ((port & 0x0f)<<12);
+-	write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74,
+-				 dword);
+-	dbgp_printk("set debug port to %d\n", port);
+-}
+-
+-static void __init detect_set_debug_port(void)
+-{
+-	u32 vendorid;
+-
+-	vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
+-		 0x00);
+-
+-	if ((vendorid & 0xffff) == 0x10de) {
+-		dbgp_printk("using nvidia set_debug_port\n");
+-		set_debug_port = nvidia_set_debug_port;
+-	}
+-}
+-
+-static int __init ehci_setup(void)
+-{
+-	struct usb_debug_descriptor dbgp_desc;
+-	u32 cmd, ctrl, status, portsc, hcs_params;
+-	u32 debug_port, new_debug_port = 0, n_ports;
+-	u32  devnum;
+-	int ret, i;
+-	int loop;
+-	int port_map_tried;
+-	int playtimes = 3;
+-
+-try_next_time:
+-	port_map_tried = 0;
+-
+-try_next_port:
+-
+-	hcs_params = readl(&ehci_caps->hcs_params);
+-	debug_port = HCS_DEBUG_PORT(hcs_params);
+-	n_ports    = HCS_N_PORTS(hcs_params);
+-
+-	dbgp_printk("debug_port: %d\n", debug_port);
+-	dbgp_printk("n_ports:    %d\n", n_ports);
+-
+-	for (i = 1; i <= n_ports; i++) {
+-		portsc = readl(&ehci_regs->port_status[i-1]);
+-		dbgp_printk("portstatus%d: %08x\n", i, portsc);
+-	}
+-
+-	if (port_map_tried && (new_debug_port != debug_port)) {
+-		if (--playtimes) {
+-			set_debug_port(new_debug_port);
+-			goto try_next_time;
+-		}
+-		return -1;
+-	}
+-
+-	loop = 10;
+-	/* Reset the EHCI controller */
+-	cmd = readl(&ehci_regs->command);
+-	cmd |= CMD_RESET;
+-	writel(cmd, &ehci_regs->command);
+-	do {
+-		cmd = readl(&ehci_regs->command);
+-	} while ((cmd & CMD_RESET) && (--loop > 0));
+-
+-	if (!loop) {
+-		dbgp_printk("can not reset ehci\n");
+-		return -1;
+-	}
+-	dbgp_printk("ehci reset done\n");
+-
+-	/* Claim ownership, but do not enable yet */
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl |= DBGP_OWNER;
+-	ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
+-	writel(ctrl, &ehci_debug->control);
+-
+-	/* Start the ehci running */
+-	cmd = readl(&ehci_regs->command);
+-	cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
+-	cmd |= CMD_RUN;
+-	writel(cmd, &ehci_regs->command);
+-
+-	/* Ensure everything is routed to the EHCI */
+-	writel(FLAG_CF, &ehci_regs->configured_flag);
+-
+-	/* Wait until the controller is no longer halted */
+-	loop = 10;
+-	do {
+-		status = readl(&ehci_regs->status);
+-	} while ((status & STS_HALT) && (--loop > 0));
+-
+-	if (!loop) {
+-		dbgp_printk("ehci can be started\n");
+-		return -1;
+-	}
+-	dbgp_printk("ehci started\n");
+-
+-	/* Wait for a device to show up in the debug port */
+-	ret = ehci_wait_for_port(debug_port);
+-	if (ret < 0) {
+-		dbgp_printk("No device found in debug port\n");
+-		goto next_debug_port;
+-	}
+-	dbgp_printk("ehci wait for port done\n");
+-
+-	/* Enable the debug port */
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl |= DBGP_CLAIM;
+-	writel(ctrl, &ehci_debug->control);
+-	ctrl = readl(&ehci_debug->control);
+-	if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
+-		dbgp_printk("No device in debug port\n");
+-		writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control);
+-		goto err;
+-	}
+-	dbgp_printk("debug ported enabled\n");
+-
+-	/* Completely transfer the debug device to the debug controller */
+-	portsc = readl(&ehci_regs->port_status[debug_port - 1]);
+-	portsc &= ~PORT_PE;
+-	writel(portsc, &ehci_regs->port_status[debug_port - 1]);
+-
+-	dbgp_mdelay(100);
+-
+-	/* Find the debug device and make it device number 127 */
+-	for (devnum = 0; devnum <= 127; devnum++) {
+-		ret = dbgp_control_msg(devnum,
+-			USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+-			USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
+-			&dbgp_desc, sizeof(dbgp_desc));
+-		if (ret > 0)
+-			break;
+-	}
+-	if (devnum > 127) {
+-		dbgp_printk("Could not find attached debug device\n");
+-		goto err;
+-	}
+-	if (ret < 0) {
+-		dbgp_printk("Attached device is not a debug device\n");
+-		goto err;
+-	}
+-	dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
+-
+-	/* Move the device to 127 if it isn't already there */
+-	if (devnum != USB_DEBUG_DEVNUM) {
+-		ret = dbgp_control_msg(devnum,
+-			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+-			USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
+-		if (ret < 0) {
+-			dbgp_printk("Could not move attached device to %d\n",
+-				USB_DEBUG_DEVNUM);
+-			goto err;
+-		}
+-		devnum = USB_DEBUG_DEVNUM;
+-		dbgp_printk("debug device renamed to 127\n");
+-	}
+-
+-	/* Enable the debug interface */
+-	ret = dbgp_control_msg(USB_DEBUG_DEVNUM,
+-		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+-		USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
+-	if (ret < 0) {
+-		dbgp_printk(" Could not enable the debug device\n");
+-		goto err;
+-	}
+-	dbgp_printk("debug interface enabled\n");
+-
+-	/* Perform a small write to get the even/odd data state in sync
+-	 */
+-	ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1);
+-	if (ret < 0) {
+-		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
+-		goto err;
+-	}
+-	dbgp_printk("small write doned\n");
+-
+-	return 0;
+-err:
+-	/* Things didn't work so remove my claim */
+-	ctrl = readl(&ehci_debug->control);
+-	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
+-	writel(ctrl, &ehci_debug->control);
+-	return -1;
+-
+-next_debug_port:
+-	port_map_tried |= (1<<(debug_port - 1));
+-	new_debug_port = ((debug_port-1+1)%n_ports) + 1;
+-	if (port_map_tried != ((1<<n_ports) - 1)) {
+-		set_debug_port(new_debug_port);
+-		goto try_next_port;
+-	}
+-	if (--playtimes) {
+-		set_debug_port(new_debug_port);
+-		goto try_next_time;
+-	}
+-
+-	return -1;
+-}
+-
+-static int __init early_dbgp_init(char *s)
+-{
+-	u32 debug_port, bar, offset;
+-	u32 bus, slot, func, cap;
+-	void __iomem *ehci_bar;
+-	u32 dbgp_num;
+-	u32 bar_val;
+-	char *e;
+-	int ret;
+-	u8 byte;
+-
+-	if (!early_pci_allowed())
+-		return -1;
+-
+-	dbgp_num = 0;
+-	if (*s)
+-		dbgp_num = simple_strtoul(s, &e, 10);
+-	dbgp_printk("dbgp_num: %d\n", dbgp_num);
+-
+-	cap = find_dbgp(dbgp_num, &bus, &slot, &func);
+-	if (!cap)
+-		return -1;
+-
+-	dbgp_printk("Found EHCI debug port on %02x:%02x.%1x\n", bus, slot,
+-			 func);
+-
+-	debug_port = read_pci_config(bus, slot, func, cap);
+-	bar = (debug_port >> 29) & 0x7;
+-	bar = (bar * 4) + 0xc;
+-	offset = (debug_port >> 16) & 0xfff;
+-	dbgp_printk("bar: %02x offset: %03x\n", bar, offset);
+-	if (bar != PCI_BASE_ADDRESS_0) {
+-		dbgp_printk("only debug ports on bar 1 handled.\n");
+-
+-		return -1;
+-	}
+-
+-	bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+-	dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset);
+-	if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) {
+-		dbgp_printk("only simple 32bit mmio bars supported\n");
+-
+-		return -1;
+-	}
+-
+-	/* double check if the mem space is enabled */
+-	byte = read_pci_config_byte(bus, slot, func, 0x04);
+-	if (!(byte & 0x2)) {
+-		byte  |= 0x02;
+-		write_pci_config_byte(bus, slot, func, 0x04, byte);
+-		dbgp_printk("mmio for ehci enabled\n");
+-	}
+-
+-	/*
+-	 * FIXME I don't have the bar size so just guess PAGE_SIZE is more
+-	 * than enough.  1K is the biggest I have seen.
+-	 */
+-	set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK);
+-	ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE);
+-	ehci_bar += bar_val & ~PAGE_MASK;
+-	dbgp_printk("ehci_bar: %p\n", ehci_bar);
+-
+-	ehci_caps  = ehci_bar;
+-	ehci_regs  = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
+-	ehci_debug = ehci_bar + offset;
+-	ehci_dev.bus = bus;
+-	ehci_dev.slot = slot;
+-	ehci_dev.func = func;
+-
+-	detect_set_debug_port();
+-
+-	ret = ehci_setup();
+-	if (ret < 0) {
+-		dbgp_printk("ehci_setup failed\n");
+-		ehci_debug = NULL;
+-
+-		return -1;
+-	}
+-
+-	return 0;
+-}
+-
+-static void early_dbgp_write(struct console *con, const char *str, u32 n)
+-{
+-	int chunk, ret;
+-
+-	if (!ehci_debug)
+-		return;
+-	while (n > 0) {
+-		chunk = n;
+-		if (chunk > DBGP_MAX_PACKET)
+-			chunk = DBGP_MAX_PACKET;
+-		ret = dbgp_bulk_write(USB_DEBUG_DEVNUM,
+-			dbgp_endpoint_out, str, chunk);
+-		str += chunk;
+-		n -= chunk;
+-	}
+-}
+-
+-static struct console early_dbgp_console = {
+-	.name =		"earlydbg",
+-	.write =	early_dbgp_write,
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
+-};
+-#endif
+-
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+ static int __initdata early_console_initialized;
+@@ -920,10 +204,24 @@ asmlinkage void early_printk(const char 
+ 	va_end(ap);
+ }
+ 
++static inline void early_console_register(struct console *con, int keep_early)
++{
++	if (early_console->index != -1) {
++		printk(KERN_CRIT "ERROR: earlyprintk= %s already used\n",
++		       con->name);
++		return;
++	}
++	early_console = con;
++	if (keep_early)
++		early_console->flags &= ~CON_BOOT;
++	else
++		early_console->flags |= CON_BOOT;
++	register_console(early_console);
++}
+ 
+ static int __init setup_early_printk(char *buf)
+ {
+-	int keep_early;
++	int keep;
+ 
+ 	if (!buf)
+ 		return 0;
+@@ -932,44 +230,41 @@ static int __init setup_early_printk(cha
+ 		return 0;
+ 	early_console_initialized = 1;
+ 
+-	keep_early = (strstr(buf, "keep") != NULL);
++	keep = (strstr(buf, "keep") != NULL);
+ 
+-	if (!strncmp(buf, "serial", 6)) {
+-		early_serial_init(buf + 6);
+-		early_console = &early_serial_console;
+-	} else if (!strncmp(buf, "ttyS", 4)) {
+-		early_serial_init(buf);
+-		early_console = &early_serial_console;
+-	} else if (!strncmp(buf, "vga", 3)) {
++	while (*buf != '\0') {
++		if (!strncmp(buf, "serial", 6)) {
++			buf += 6;
++			early_serial_init(buf);
++			early_console_register(&early_serial_console, keep);
++			if (!strncmp(buf, ",ttyS", 5))
++				buf += 5;
++		}
++		if (!strncmp(buf, "ttyS", 4)) {
++			early_serial_init(buf + 4);
++			early_console_register(&early_serial_console, keep);
++		}
+ #ifndef CONFIG_XEN
+-		&& boot_params.screen_info.orig_video_isVGA == 1) {
+-		max_xpos = boot_params.screen_info.orig_video_cols;
+-		max_ypos = boot_params.screen_info.orig_video_lines;
+-		current_ypos = boot_params.screen_info.orig_y;
++		if (!strncmp(buf, "vga", 3) &&
++		    boot_params.screen_info.orig_video_isVGA == 1) {
++			max_xpos = boot_params.screen_info.orig_video_cols;
++			max_ypos = boot_params.screen_info.orig_video_lines;
++			current_ypos = boot_params.screen_info.orig_y;
++#else
++		if (!strncmp(buf, "vga", 3) || !strncmp(buf, "xen", 3)) {
+ #endif
+-		early_console = &early_vga_console;
++			early_console_register(&early_vga_console, keep);
++		}
+ #ifdef CONFIG_EARLY_PRINTK_DBGP
+-	} else if (!strncmp(buf, "dbgp", 4)) {
+-		if (early_dbgp_init(buf+4) < 0)
+-			return 0;
+-		early_console = &early_dbgp_console;
+-		/*
+-		 * usb subsys will reset ehci controller, so don't keep
+-		 * that early console
+-		 */
+-		keep_early = 0;
++		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
++			early_console_register(&early_dbgp_console, keep);
+ #endif
+-#ifdef CONFIG_XEN
+-	} else if (!strncmp(buf, "xen", 3)) {
+-		early_console = &xenboot_console;
++#ifdef CONFIG_HVC_XEN
++		if (!strncmp(buf, "xen", 3))
++			early_console_register(&xenboot_console, keep);
+ #endif
++		buf++;
+ 	}
+-
+-	if (keep_early)
+-		early_console->flags &= ~CON_BOOT;
+-	else
+-		early_console->flags |= CON_BOOT;
+-	register_console(early_console);
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:52:22.000000000 +0100
+@@ -53,6 +53,7 @@
+ #include <asm/hw_irq.h>
+ #include <asm/page_types.h>
+ #include <asm/irqflags.h>
++#include <asm/processor-flags.h>
+ #include <asm/ftrace.h>
+ #include <asm/percpu.h>
+ #include <xen/interface/xen.h>
+@@ -150,7 +151,7 @@ ENTRY(ftrace_graph_caller)
+ END(ftrace_graph_caller)
+ 
+ GLOBAL(return_to_handler)
+-	subq  $80, %rsp
++	subq  $24, %rsp
+ 
+ 	/* Save the return values */
+ 	movq %rax, (%rsp)
+@@ -159,10 +160,10 @@ GLOBAL(return_to_handler)
+ 
+ 	call ftrace_return_to_handler
+ 
+-	movq %rax, 72(%rsp)
++	movq %rax, 16(%rsp)
+ 	movq 8(%rsp), %rdx
+ 	movq (%rsp), %rax
+-	addq $72, %rsp
++	addq $16, %rsp
+ 	retq
+ #endif
+ 
+@@ -553,20 +554,13 @@ sysret_signal:
+ 	bt $TIF_SYSCALL_AUDIT,%edx
+ 	jc sysret_audit
+ #endif
+-	/* edx:	work flags (arg3) */
+-	leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
+-	xorl %esi,%esi # oldset -> arg2
+-	SAVE_REST
+-	FIXUP_TOP_OF_STACK %r11
+-	call do_notify_resume
+-	RESTORE_TOP_OF_STACK %r11
+-	RESTORE_REST
+-	movl $_TIF_WORK_MASK,%edi
+-	/* Use IRET because user could have changed frame. This
+-	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	TRACE_IRQS_OFF
+-	jmp int_with_check
++	/*
++	 * We have a signal, or exit tracing or single-step.
++	 * These all wind up with the iret return path anyway,
++	 * so just join that path right now.
++	 */
++	FIXUP_TOP_OF_STACK %r11, -ARGOFFSET
++	jmp int_check_syscall_exit_work
+ 
+ badsys:
+ 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+@@ -675,6 +669,7 @@ int_careful:
+ int_very_careful:
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
++int_check_syscall_exit_work:
+ 	SAVE_REST
+ 	/* Check for syscall exit trace */
+ 	testl $_TIF_WORK_SYSCALL_EXIT,%edx
+@@ -921,7 +916,7 @@ apicinterrupt ERROR_APIC_VECTOR \
+ apicinterrupt SPURIOUS_APIC_VECTOR \
+ 	spurious_interrupt smp_spurious_interrupt
+ 
+-#ifdef CONFIG_PERF_COUNTERS
++#ifdef CONFIG_PERF_EVENTS
+ apicinterrupt LOCAL_PENDING_VECTOR \
+ 	perf_pending_interrupt smp_perf_pending_interrupt
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/head-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -59,7 +59,6 @@ void __init reserve_ebda_region(void)
+ #include <asm/fixmap.h>
+ #include <asm/pgtable.h>
+ #include <asm/sections.h>
+-#include <asm/setup_arch.h>
+ #include <xen/interface/callback.h>
+ #include <xen/interface/memory.h>
+ 
+@@ -163,7 +162,7 @@ void __init xen_start_kernel(void)
+ 
+ }
+ 
+-void __init machine_specific_arch_setup(void)
++void __init xen_arch_setup(void)
+ {
+ 	int ret;
+ 	static const struct callback_register __initconst event = {
+--- head-2010-01-18.orig/arch/x86/kernel/head32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head32-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -9,11 +9,26 @@
+ #include <linux/start_kernel.h>
+ 
+ #include <asm/setup.h>
+-#include <asm/setup_arch.h>
+ #include <asm/sections.h>
+ #include <asm/e820.h>
+-#include <asm/bios_ebda.h>
++#include <asm/page.h>
+ #include <asm/trampoline.h>
++#include <asm/apic.h>
++#include <asm/io_apic.h>
++#include <asm/bios_ebda.h>
++
++static void __init i386_default_early_setup(void)
++{
++	/* Initialize 32bit specific setup functions */
++	if (is_initial_xendomain())
++		x86_init.resources.probe_roms = probe_roms;
++	x86_init.resources.reserve_resources = i386_reserve_resources;
++#ifndef CONFIG_XEN
++	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
++
++	reserve_ebda_region();
++#endif
++}
+ 
+ void __init i386_start_kernel(void)
+ {
+@@ -31,7 +46,16 @@ void __init i386_start_kernel(void)
+ 		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+ 	}
+ #endif
+-	reserve_ebda_region();
++
++	/* Call the subarch specific early setup function */
++	switch (boot_params.hdr.hardware_subarch) {
++	case X86_SUBARCH_MRST:
++		x86_mrst_early_setup();
++		break;
++	default:
++		i386_default_early_setup();
++		break;
++	}
+ #else
+ 	{
+ 		int max_cmdline;
+@@ -42,6 +66,7 @@ void __init i386_start_kernel(void)
+ 		boot_command_line[max_cmdline-1] = '\0';
+ 	}
+ 
++	i386_default_early_setup();
+ 	xen_start_kernel();
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -20,15 +20,14 @@
+ #include <asm/proto.h>
+ #include <asm/smp.h>
+ #include <asm/setup.h>
+-#include <asm/setup_arch.h>
+ #include <asm/desc.h>
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/sections.h>
+ #include <asm/kdebug.h>
+ #include <asm/e820.h>
+-#include <asm/bios_ebda.h>
+ #include <asm/trampoline.h>
++#include <asm/bios_ebda.h>
+ 
+ #ifndef CONFIG_XEN
+ static void __init zap_identity_mappings(void)
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:52:22.000000000 +0100
+@@ -30,7 +30,7 @@
+ #define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
+ #define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id
+ 
+-.section .text.head,"ax",@progbits
++__HEAD
+ #define VIRT_ENTRY_OFFSET 0x0
+ .org VIRT_ENTRY_OFFSET
+ ENTRY(startup_32)
+@@ -69,7 +69,6 @@ ENTRY(startup_32)
+ 	 */
+ 	movl $per_cpu__gdt_page,%eax
+ 	movl $per_cpu__stack_canary,%ecx
+-	subl $20, %ecx
+ 	movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
+ 	shrl $16, %ecx
+ 	movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
+@@ -122,7 +121,7 @@ ENTRY(hypercall_page)
+ /*
+  * BSS section
+  */
+-.section ".bss.page_aligned","wa"
++__PAGE_ALIGNED_BSS
+ 	.align PAGE_SIZE_asm
+ ENTRY(swapper_pg_fixmap)
+ 	.fill 1024,4,0
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:22.000000000 +0100
+@@ -23,7 +23,7 @@
+ #include <asm/percpu.h>
+ #include <xen/interface/elfnote.h>
+ 
+-	.section .text.head, "ax", @progbits
++	__HEAD
+ 	.code64
+ 	.globl startup_64
+ startup_64:
+@@ -51,7 +51,7 @@ startup_64:
+ 
+ #define NEXT_PAGE(name) \
+ 	.balign	PAGE_SIZE; \
+-	phys_##name = . - .text.head; \
++	phys_##name = . - .head.text; \
+ ENTRY(name)
+ 
+ NEXT_PAGE(init_level4_pgt)
+@@ -104,7 +104,7 @@ NEXT_PAGE(hypercall_page)
+ 
+ #undef NEXT_PAGE
+ 
+-	.section .bss.page_aligned, "aw", @nobits
++	__PAGE_ALIGNED_BSS
+ 	.align PAGE_SIZE
+ ENTRY(empty_zero_page)
+ 	.skip PAGE_SIZE
+--- head-2010-01-18.orig/arch/x86/kernel/irq-xen.c	2009-12-18 09:58:56.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq-xen.c	2009-12-18 09:59:05.000000000 +0100
+@@ -67,10 +67,10 @@ static int show_other_interrupts(struct 
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+ 	seq_printf(p, "  Spurious interrupts\n");
+-	seq_printf(p, "%*s: ", prec, "CNT");
++	seq_printf(p, "%*s: ", prec, "PMI");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
+-	seq_printf(p, "  Performance counter interrupts\n");
++	seq_printf(p, "  Performance monitoring interrupts\n");
+ 	seq_printf(p, "%*s: ", prec, "PND");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
+@@ -112,7 +112,7 @@ static int show_other_interrupts(struct 
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
+ 	seq_printf(p, "  Threshold APIC interrupts\n");
+ #endif
+-#ifdef CONFIG_X86_NEW_MCE
++#ifdef CONFIG_X86_MCE
+ 	seq_printf(p, "%*s: ", prec, "MCE");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
+@@ -212,7 +212,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ #ifdef CONFIG_X86_MCE_THRESHOLD
+ 	sum += irq_stats(cpu)->irq_threshold_count;
+ #endif
+-#ifdef CONFIG_X86_NEW_MCE
++#ifdef CONFIG_X86_MCE
+ 	sum += per_cpu(mce_exception_count, cpu);
+ 	sum += per_cpu(mce_poll_count, cpu);
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -218,7 +218,6 @@ bool handle_irq(unsigned irq, struct pt_
+ void fixup_irqs(void)
+ {
+ 	unsigned int irq;
+-	static int warned;
+ 	struct irq_desc *desc;
+ 
+ 	for_each_irq_desc(irq, desc) {
+@@ -236,8 +235,8 @@ void fixup_irqs(void)
+ 		}
+ 		if (desc->chip->set_affinity)
+ 			desc->chip->set_affinity(irq, affinity);
+-		else if (desc->action && !(warned++))
+-			printk("Cannot set affinity for irq %i\n", irq);
++		else if (desc->action)
++			printk_once("Cannot set affinity for irq %i\n", irq);
+ 	}
+ 
+ #if 0
+--- head-2010-01-18.orig/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -70,8 +70,8 @@ static int alloc_ldt(mm_context_t *pc, i
+ 				    XENFEAT_writable_descriptor_tables);
+ 		load_LDT(pc);
+ #ifdef CONFIG_SMP
+-		if (!cpus_equal(current->mm->cpu_vm_mask,
+-				cpumask_of_cpu(smp_processor_id())))
++		if (!cpumask_equal(mm_cpumask(current->mm),
++				   cpumask_of(smp_processor_id())))
+ 			smp_call_function(flush_ldt, current->mm, 1);
+ 		preempt_enable();
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -97,8 +97,8 @@ static ssize_t microcode_write(struct fi
+ {
+ 	ssize_t ret = -EINVAL;
+ 
+-	if ((len >> PAGE_SHIFT) > num_physpages) {
+-		pr_err("microcode: too much data (max %ld pages)\n", num_physpages);
++	if ((len >> PAGE_SHIFT) > totalram_pages) {
++		pr_err("microcode: too much data (max %ld pages)\n", totalram_pages);
+ 		return ret;
+  	}
+ 
+@@ -121,7 +121,7 @@ static const struct file_operations micr
+ static struct miscdevice microcode_dev = {
+ 	.minor			= MICROCODE_MINOR,
+ 	.name			= "microcode",
+-	.devnode		= "cpu/microcode",
++	.nodename		= "cpu/microcode",
+ 	.fops			= &microcode_fops,
+ };
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -51,6 +51,13 @@ static int __init mpf_checksum(unsigned 
+ 	return sum & 0xFF;
+ }
+ 
++#ifndef CONFIG_XEN
++int __init default_mpc_apic_id(struct mpc_cpu *m)
++{
++	return m->apicid;
++}
++#endif
++
+ static void __init MP_processor_info(struct mpc_cpu *m)
+ {
+ #ifndef CONFIG_XEN
+@@ -62,10 +69,7 @@ static void __init MP_processor_info(str
+ 		return;
+ 	}
+ 
+-	if (x86_quirks->mpc_apic_id)
+-		apicid = x86_quirks->mpc_apic_id(m);
+-	else
+-		apicid = m->apicid;
++	apicid = x86_init.mpparse.mpc_apic_id(m);
+ 
+ 	if (m->cpuflag & CPU_BOOTPROCESSOR) {
+ 		bootup_cpu = " (Bootup-CPU)";
+@@ -80,16 +84,18 @@ static void __init MP_processor_info(str
+ }
+ 
+ #ifdef CONFIG_X86_IO_APIC
+-static void __init MP_bus_info(struct mpc_bus *m)
++void __init default_mpc_oem_bus_info(struct mpc_bus *m, char *str)
+ {
+-	char str[7];
+ 	memcpy(str, m->bustype, 6);
+ 	str[6] = 0;
++	apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
++}
+ 
+-	if (x86_quirks->mpc_oem_bus_info)
+-		x86_quirks->mpc_oem_bus_info(m, str);
+-	else
+-		apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
++static void __init MP_bus_info(struct mpc_bus *m)
++{
++	char str[7];
++
++	x86_init.mpparse.mpc_oem_bus_info(m, str);
+ 
+ #if MAX_MP_BUSSES < 256
+ 	if (m->busid >= MAX_MP_BUSSES) {
+@@ -106,8 +112,8 @@ static void __init MP_bus_info(struct mp
+ 		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
+ #endif
+ 	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
+-		if (x86_quirks->mpc_oem_pci_bus)
+-			x86_quirks->mpc_oem_pci_bus(m);
++		if (x86_init.mpparse.mpc_oem_pci_bus)
++			x86_init.mpparse.mpc_oem_pci_bus(m);
+ 
+ 		clear_bit(m->busid, mp_bus_not_pci);
+ #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+@@ -301,6 +307,8 @@ static void __init smp_dump_mptable(stru
+ 			1, mpc, mpc->length, 1);
+ }
+ 
++void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }
++
+ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+ {
+ 	char str[16];
+@@ -322,16 +330,13 @@ static int __init smp_read_mpc(struct mp
+ 	if (early)
+ 		return 1;
+ 
+-	if (mpc->oemptr && x86_quirks->smp_read_mpc_oem) {
+-		struct mpc_oemtable *oem_table = (void *)(long)mpc->oemptr;
+-		x86_quirks->smp_read_mpc_oem(oem_table, mpc->oemsize);
+-	}
++	if (mpc->oemptr)
++		x86_init.mpparse.smp_read_mpc_oem(mpc);
+ 
+ 	/*
+ 	 *      Now process the configuration blocks.
+ 	 */
+-	if (x86_quirks->mpc_record)
+-		*x86_quirks->mpc_record = 0;
++	x86_init.mpparse.mpc_record(0);
+ 
+ 	while (count < mpc->length) {
+ 		switch (*mpt) {
+@@ -363,8 +368,7 @@ static int __init smp_read_mpc(struct mp
+ 			count = mpc->length;
+ 			break;
+ 		}
+-		if (x86_quirks->mpc_record)
+-			(*x86_quirks->mpc_record)++;
++		x86_init.mpparse.mpc_record(1);
+ 	}
+ 
+ #ifdef CONFIG_X86_BIGSMP
+@@ -492,11 +496,11 @@ static void __init construct_ioapic_tabl
+ 		MP_bus_info(&bus);
+ 	}
+ 
+-	ioapic.type = MP_IOAPIC;
+-	ioapic.apicid = 2;
+-	ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	ioapic.flags = MPC_APIC_USABLE;
+-	ioapic.apicaddr = 0xFEC00000;
++	ioapic.type	= MP_IOAPIC;
++	ioapic.apicid	= 2;
++	ioapic.apicver	= mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.flags	= MPC_APIC_USABLE;
++	ioapic.apicaddr	= IO_APIC_DEFAULT_PHYS_BASE;
+ 	MP_ioapic_info(&ioapic);
+ 
+ 	/*
+@@ -618,7 +622,7 @@ static int __init check_physptr(struct m
+ /*
+  * Scan the memory blocks for an SMP configuration block.
+  */
+-static void __init __get_smp_config(unsigned int early)
++void __init default_get_smp_config(unsigned int early)
+ {
+ 	struct mpf_intel *mpf = mpf_found;
+ 
+@@ -635,11 +639,6 @@ static void __init __get_smp_config(unsi
+ 	if (acpi_lapic && acpi_ioapic)
+ 		return;
+ 
+-	if (x86_quirks->mach_get_smp_config) {
+-		if (x86_quirks->mach_get_smp_config(early))
+-			return;
+-	}
+-
+ 	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+ 	       mpf->specification);
+ #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+@@ -680,16 +679,6 @@ static void __init __get_smp_config(unsi
+ 	 */
+ }
+ 
+-void __init early_get_smp_config(void)
+-{
+-	__get_smp_config(1);
+-}
+-
+-void __init get_smp_config(void)
+-{
+-	__get_smp_config(0);
+-}
+-
+ #ifndef CONFIG_XEN
+ static void __init smp_reserve_bootmem(struct mpf_intel *mpf)
+ {
+@@ -761,16 +750,12 @@ static int __init smp_scan_config(unsign
+ 	return 0;
+ }
+ 
+-static void __init __find_smp_config(unsigned int reserve)
++void __init default_find_smp_config(unsigned int reserve)
+ {
+ #ifndef CONFIG_XEN
+ 	unsigned int address;
+ #endif
+ 
+-	if (x86_quirks->mach_find_smp_config) {
+-		if (x86_quirks->mach_find_smp_config(reserve))
+-			return;
+-	}
+ 	/*
+ 	 * FIXME: Linux assumes you have 640K of base ram..
+ 	 * this continues the error...
+@@ -807,16 +792,6 @@ static void __init __find_smp_config(uns
+ #endif
+ }
+ 
+-void __init early_find_smp_config(void)
+-{
+-	__find_smp_config(0);
+-}
+-
+-void __init find_smp_config(void)
+-{
+-	__find_smp_config(1);
+-}
+-
+ #ifdef CONFIG_X86_IO_APIC
+ static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-18 14:54:16.000000000 +0100
+@@ -3,6 +3,7 @@
+ #include <linux/dmar.h>
+ #include <linux/bootmem.h>
+ #include <linux/pci.h>
++#include <linux/kmemleak.h>
+ 
+ #include <asm/proto.h>
+ #include <asm/dma.h>
+@@ -32,17 +33,22 @@ int no_iommu __read_mostly;
+ /* Set this to 1 if there is a HW IOMMU in the system */
+ int iommu_detected __read_mostly = 0;
+ 
+-int iommu_pass_through;
++/*
++ * This variable becomes 1 if iommu=pt is passed on the kernel command line.
++ * If this variable is 1, IOMMU implementations do no DMA translation for
++ * devices and allow every device to access to whole physical memory. This is
++ * useful if a user want to use an IOMMU only for KVM device assignment to
++ * guests and not for driver dma translation.
++ */
++int iommu_pass_through __read_mostly;
+ 
+ dma_addr_t bad_dma_address __read_mostly = 0;
+ EXPORT_SYMBOL(bad_dma_address);
+ 
+-/* Dummy device used for NULL arguments (normally ISA). Better would
+-   be probably a smaller DMA mask, but this is bug-to-bug compatible
+-   to older i386. */
++/* Dummy device used for NULL arguments (normally ISA). */
+ struct device x86_dma_fallback_dev = {
+ 	.init_name = "fallback device",
+-	.coherent_dma_mask = DMA_BIT_MASK(32),
++	.coherent_dma_mask = ISA_DMA_BIT_MASK,
+ 	.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
+ };
+ EXPORT_SYMBOL(x86_dma_fallback_dev);
+@@ -88,6 +94,11 @@ void __init dma32_reserve_bootmem(void)
+ 	size = roundup(dma32_bootmem_size, align);
+ 	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
+ 				 512ULL<<20);
++	/*
++	 * Kmemleak should not scan this block as it may not be mapped via the
++	 * kernel direct mapping.
++	 */
++	kmemleak_ignore(dma32_bootmem_ptr);
+ 	if (dma32_bootmem_ptr)
+ 		dma32_bootmem_size = size;
+ 	else
+@@ -178,7 +189,7 @@ again:
+ 
+ #ifndef CONFIG_XEN
+ 	addr = page_to_phys(page);
+-	if (!is_buffer_dma_capable(dma_mask, addr, size)) {
++	if (addr + size > dma_mask) {
+ 		__free_pages(page, order);
+ 
+ 		if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
+@@ -266,10 +277,8 @@ static __init int iommu_setup(char *p)
+ 		if (!strncmp(p, "soft", 4))
+ 			swiotlb = 1;
+ #endif
+-		if (!strncmp(p, "pt", 2)) {
++		if (!strncmp(p, "pt", 2))
+ 			iommu_pass_through = 1;
+-			return 1;
+-		}
+ 
+ 		gart_parse_options(p);
+ 
+@@ -381,7 +390,7 @@ void pci_iommu_shutdown(void)
+ 	amd_iommu_shutdown();
+ }
+ /* Must execute after PCI subsystem */
+-fs_initcall(pci_iommu_init);
++rootfs_initcall(pci_iommu_init);
+ 
+ #ifdef CONFIG_PCI
+ /* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+--- head-2010-01-18.orig/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:52:22.000000000 +0100
+@@ -36,7 +36,7 @@ gnttab_map_sg(struct device *hwdev, stru
+ 		sg->dma_address =
+ 			gnttab_dma_map_page(sg_page(sg)) + sg->offset;
+ 		sg->dma_length  = sg->length;
+-		IOMMU_BUG_ON(address_needs_mapping(
++		IOMMU_BUG_ON(!dma_capable(
+ 			hwdev, sg->dma_address, sg->length));
+ 		IOMMU_BUG_ON(range_straddles_page_boundary(
+ 			page_to_pseudophys(sg_page(sg)) + sg->offset,
+@@ -68,7 +68,7 @@ gnttab_map_page(struct device *dev, stru
+ 
+ 	dma = gnttab_dma_map_page(page) + offset;
+ 	IOMMU_BUG_ON(range_straddles_page_boundary(offset, size));
+-	IOMMU_BUG_ON(address_needs_mapping(dev, dma, size));
++	IOMMU_BUG_ON(!dma_capable(dev, dma, size));
+ 
+ 	return dma;
+ }
+@@ -80,14 +80,31 @@ gnttab_unmap_page(struct device *dev, dm
+ 	gnttab_dma_unmap_page(dma_addr);
+ }
+ 
++static void nommu_sync_single_for_device(struct device *dev,
++			dma_addr_t addr, size_t size,
++			enum dma_data_direction dir)
++{
++	flush_write_buffers();
++}
++
++
++static void nommu_sync_sg_for_device(struct device *dev,
++			struct scatterlist *sg, int nelems,
++			enum dma_data_direction dir)
++{
++	flush_write_buffers();
++}
++
+ struct dma_map_ops nommu_dma_ops = {
+-	.alloc_coherent	= dma_generic_alloc_coherent,
+-	.free_coherent	= dma_generic_free_coherent,
+-	.map_page	= gnttab_map_page,
+-	.unmap_page	= gnttab_unmap_page,
+-	.map_sg		= gnttab_map_sg,
+-	.unmap_sg	= gnttab_unmap_sg,
+-	.dma_supported	= swiotlb_dma_supported,
++	.alloc_coherent		= dma_generic_alloc_coherent,
++	.free_coherent		= dma_generic_free_coherent,
++	.map_page		= gnttab_map_page,
++	.unmap_page		= gnttab_unmap_page,
++	.map_sg			= gnttab_map_sg,
++	.unmap_sg		= gnttab_unmap_sg,
++	.sync_single_for_device = nommu_sync_single_for_device,
++	.sync_sg_for_device	= nommu_sync_sg_for_device,
++	.dma_supported		= swiotlb_dma_supported,
+ };
+ 
+ void __init no_iommu_init(void)
+--- head-2010-01-18.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -9,7 +9,7 @@
+ #include <linux/pm.h>
+ #include <linux/clockchips.h>
+ #include <linux/random.h>
+-#include <trace/power.h>
++#include <trace/events/power.h>
+ #include <asm/system.h>
+ #include <asm/apic.h>
+ #include <asm/syscalls.h>
+@@ -26,9 +26,6 @@ EXPORT_SYMBOL(idle_nomwait);
+ 
+ struct kmem_cache *task_xstate_cachep;
+ 
+-DEFINE_TRACE(power_start);
+-DEFINE_TRACE(power_end);
+-
+ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+ {
+ 	*dst = *src;
+@@ -285,9 +282,7 @@ static inline int hlt_use_halt(void)
+  */
+ void xen_idle(void)
+ {
+-	struct power_trace it;
+-
+-	trace_power_start(&it, POWER_CSTATE, 1);
++	trace_power_start(POWER_CSTATE, 1);
+ 	current_thread_info()->status &= ~TS_POLLING;
+ 	/*
+ 	 * TS_POLLING-cleared state must be visible before we
+@@ -300,7 +295,6 @@ void xen_idle(void)
+ 	else
+ 		local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+-	trace_power_end(&it);
+ }
+ #ifdef CONFIG_APM_MODULE
+ EXPORT_SYMBOL(default_idle);
+@@ -354,9 +348,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+  */
+ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+ {
+-	struct power_trace it;
+-
+-	trace_power_start(&it, POWER_CSTATE, (ax>>4)+1);
++	trace_power_start(POWER_CSTATE, (ax>>4)+1);
+ 	if (!need_resched()) {
+ 		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+ 			clflush((void *)&current_thread_info()->flags);
+@@ -366,15 +358,13 @@ void mwait_idle_with_hints(unsigned long
+ 		if (!need_resched())
+ 			__mwait(ax, cx);
+ 	}
+-	trace_power_end(&it);
+ }
+ 
+ /* Default MONITOR/MWAIT with no hints, used for default C1 state */
+ static void mwait_idle(void)
+ {
+-	struct power_trace it;
+ 	if (!need_resched()) {
+-		trace_power_start(&it, POWER_CSTATE, 1);
++		trace_power_start(POWER_CSTATE, 1);
+ 		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+ 			clflush((void *)&current_thread_info()->flags);
+ 
+@@ -384,7 +374,6 @@ static void mwait_idle(void)
+ 			__sti_mwait(0, 0);
+ 		else
+ 			local_irq_enable();
+-		trace_power_end(&it);
+ 	} else
+ 		local_irq_enable();
+ }
+@@ -397,13 +386,11 @@ static void mwait_idle(void)
+  */
+ static void poll_idle(void)
+ {
+-	struct power_trace it;
+-
+-	trace_power_start(&it, POWER_CSTATE, 0);
++	trace_power_start(POWER_CSTATE, 0);
+ 	local_irq_enable();
+ 	while (!need_resched())
+ 		cpu_relax();
+-	trace_power_end(&it);
++	trace_power_end(0);
+ }
+ 
+ #ifndef CONFIG_XEN
+@@ -556,10 +543,8 @@ void __init init_c1e_mask(void)
+ {
+ #ifndef CONFIG_XEN
+ 	/* If we're using c1e_idle, we need to allocate c1e_mask. */
+-	if (pm_idle == c1e_idle) {
+-		alloc_cpumask_var(&c1e_mask, GFP_KERNEL);
+-		cpumask_clear(c1e_mask);
+-	}
++	if (pm_idle == c1e_idle)
++		zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
+ #endif
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -66,9 +66,6 @@
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+ 
+-DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+-EXPORT_PER_CPU_SYMBOL(current_task);
+-
+ /*
+  * Return saved PC of a blocked thread.
+  */
+@@ -360,6 +357,7 @@ __switch_to(struct task_struct *prev_p, 
+ #ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ #endif
++	bool preload_fpu;
+ #if CONFIG_XEN_COMPAT > 0x030002
+ 	struct physdev_set_iopl iopl_op;
+ 	struct physdev_set_iobitmap iobmp_op;
+@@ -373,15 +371,24 @@ __switch_to(struct task_struct *prev_p, 
+ 	/* XEN NOTE: FS/GS saved in switch_mm(), not here. */
+ 
+ 	/*
++	 * If the task has used fpu the last 5 timeslices, just do a full
++	 * restore of the math state immediately to avoid the trap; the
++	 * chances of needing FPU soon are obviously high now
++	 */
++	preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
++
++	/*
+ 	 * This is basically '__unlazy_fpu', except that we queue a
+ 	 * multicall to indicate FPU task switch, rather than
+ 	 * synchronously trapping to Xen.
+ 	 */
+ 	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+ 		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+-		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+-		mcl->args[0] = 1;
+-		mcl++;
++		if (!preload_fpu) {
++			mcl->op      = __HYPERVISOR_fpu_taskswitch;
++			mcl->args[0] = 1;
++			mcl++;
++		}
+ 	}
+ #if 0 /* lazy fpu sanity check */
+ 	else BUG_ON(!(read_cr0() & 8));
+@@ -427,6 +434,14 @@ __switch_to(struct task_struct *prev_p, 
+ 		mcl++;
+ 	}
+ 
++	/* If we're going to preload the fpu context, make sure clts
++	   is run while we're batching the cpu state updates. */
++	if (preload_fpu) {
++		mcl->op      = __HYPERVISOR_fpu_taskswitch;
++		mcl->args[0] = 0;
++		mcl++;
++	}
++
+ 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
+ 		set_xen_guest_handle(iobmp_op.bitmap,
+ 				     (char *)next->io_bitmap_ptr);
+@@ -451,7 +466,7 @@ __switch_to(struct task_struct *prev_p, 
+ 		BUG();
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+-	if (next_p->fpu_counter > 5)
++	if (preload_fpu)
+ 		prefetch(next->xstate);
+ 
+ 	/*
+@@ -470,15 +485,8 @@ __switch_to(struct task_struct *prev_p, 
+ 	 */
+ 	arch_end_context_switch(next_p);
+ 
+-	/* If the task has used fpu the last 5 timeslices, just do a full
+-	 * restore of the math state immediately to avoid the trap; the
+-	 * chances of needing FPU soon are obviously high now
+-	 *
+-	 * tsk_used_math() checks prevent calling math_state_restore(),
+-	 * which can sleep in the case of !tsk_used_math()
+-	 */
+-	if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
+-		math_state_restore();
++	if (preload_fpu)
++		__math_state_restore();
+ 
+ 	/*
+ 	 * Restore %gs if needed (which is common)
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-18 14:54:16.000000000 +0100
+@@ -64,9 +64,6 @@
+ 
+ asmlinkage extern void ret_from_fork(void);
+ 
+-DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+-EXPORT_PER_CPU_SYMBOL(current_task);
+-
+ DEFINE_PER_CPU(unsigned long, old_rsp);
+ static DEFINE_PER_CPU(unsigned char, is_idle);
+ 
+@@ -402,6 +399,7 @@ __switch_to(struct task_struct *prev_p, 
+ #ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ #endif
++	bool preload_fpu;
+ #if CONFIG_XEN_COMPAT > 0x030002
+ 	struct physdev_set_iopl iopl_op;
+ 	struct physdev_set_iobitmap iobmp_op;
+@@ -412,8 +410,15 @@ __switch_to(struct task_struct *prev_p, 
+ #endif
+ 	multicall_entry_t _mcl[8], *mcl = _mcl;
+ 
++	/*
++	 * If the task has used fpu the last 5 timeslices, just do a full
++	 * restore of the math state immediately to avoid the trap; the
++	 * chances of needing FPU soon are obviously high now
++	 */
++	preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
++
+ 	/* we're going to use this soon, after a few expensive things */
+-	if (next_p->fpu_counter > 5)
++	if (preload_fpu)
+ 		prefetch(next->xstate);
+ 
+ 	/*
+@@ -425,12 +430,21 @@ __switch_to(struct task_struct *prev_p, 
+ 	 */
+ 	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+ 		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+-		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+-		mcl->args[0] = 1;
+-		mcl++;
++		if (!preload_fpu) {
++			mcl->op      = __HYPERVISOR_fpu_taskswitch;
++			mcl->args[0] = 1;
++			mcl++;
++		}
+ 	} else
+ 		prev_p->fpu_counter = 0;
+ 
++	/* Make sure cpu is ready for new context */
++	if (preload_fpu) {
++		mcl->op      = __HYPERVISOR_fpu_taskswitch;
++		mcl->args[0] = 0;
++		mcl++;
++	}
++
+ 	/*
+ 	 * Reload sp0.
+ 	 * This is load_sp0(tss, next) with a multicall.
+@@ -550,15 +564,12 @@ __switch_to(struct task_struct *prev_p, 
+ 		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
+ 		__switch_to_xtra(prev_p, next_p);
+ 
+-	/* If the task has used fpu the last 5 timeslices, just do a full
+-	 * restore of the math state immediately to avoid the trap; the
+-	 * chances of needing FPU soon are obviously high now
+-	 *
+-	 * tsk_used_math() checks prevent calling math_state_restore(),
+-	 * which can sleep in the case of !tsk_used_math()
++	/*
++	 * Preload the FPU context, now that we've determined that the
++	 * task is likely to be using it.
+ 	 */
+-	if (tsk_used_math(next_p) && next_p->fpu_counter > 5)
+-		math_state_restore();
++	if (preload_fpu)
++		__math_state_restore();
+ 	return prev_p;
+ }
+ 
+@@ -730,3 +741,8 @@ long sys_arch_prctl(int code, unsigned l
+ 	return do_arch_prctl(current, code, addr);
+ }
+ 
++unsigned long KSTK_ESP(struct task_struct *task)
++{
++	return (test_tsk_thread_flag(task, TIF_IA32)) ?
++			(task_pt_regs(task)->sp) : ((task)->thread.usersp);
++}
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -509,7 +509,7 @@ static void __init quirk_amd_nb_node(str
+ 
+ 	pci_read_config_dword(nb_ht, 0x60, &val);
+ 	set_dev_node(&dev->dev, val & 7);
+-	pci_dev_put(dev);
++	pci_dev_put(nb_ht);
+ }
+ 
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
+--- head-2010-01-18.orig/arch/x86/kernel/rtc.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/rtc.c	2009-11-06 10:52:23.000000000 +0100
+@@ -189,8 +189,10 @@ void read_persistent_clock(struct timesp
+ 	unsigned long retval, flags;
+ 
+ #ifdef CONFIG_XEN
+-	if (!is_initial_xendomain())
+-		return xen_read_persistent_clock();
++	if (!is_initial_xendomain()) {
++		xen_read_persistent_clock(ts);
++		return;
++	}
+ #endif
+ 	spin_lock_irqsave(&rtc_lock, flags);
+ 	retval = x86_platform.get_wallclock();
+--- head-2010-01-18.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup-xen.c	2009-11-18 14:54:16.000000000 +0100
+@@ -27,6 +27,7 @@
+ #include <linux/screen_info.h>
+ #include <linux/ioport.h>
+ #include <linux/acpi.h>
++#include <linux/sfi.h>
+ #include <linux/apm_bios.h>
+ #include <linux/initrd.h>
+ #include <linux/bootmem.h>
+@@ -66,6 +67,7 @@
+ 
+ #include <linux/percpu.h>
+ #include <linux/crash_dump.h>
++#include <linux/tboot.h>
+ 
+ #include <video/edid.h>
+ 
+@@ -138,10 +140,6 @@ start_info_t *xen_start_info;
+ EXPORT_SYMBOL(xen_start_info);
+ #endif
+ 
+-#ifndef ARCH_SETUP
+-#define ARCH_SETUP
+-#endif
+-
+ /*
+  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+  * The direct mapping extends to max_pfn_mapped, so that we can directly access
+@@ -164,9 +162,9 @@ int default_cpu_present_to_apicid(int mp
+ 	return __default_cpu_present_to_apicid(mps_cpu);
+ }
+ 
+-int default_check_phys_apicid_present(int boot_cpu_physical_apicid)
++int default_check_phys_apicid_present(int phys_apicid)
+ {
+-	return __default_check_phys_apicid_present(boot_cpu_physical_apicid);
++	return __default_check_phys_apicid_present(phys_apicid);
+ }
+ #endif
+ 
+@@ -203,13 +201,6 @@ static struct resource bss_resource = {
+ 
+ 
+ #ifdef CONFIG_X86_32
+-static struct resource video_ram_resource = {
+-	.name	= "Video RAM area",
+-	.start	= 0xa0000,
+-	.end	= 0xbffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+ /* cpu data as detected by the assembly code in head.S */
+ struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};
+ /* common cpu data for all cpus */
+@@ -670,7 +661,7 @@ static struct resource standard_io_resou
+ 		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
+ };
+ 
+-static void __init reserve_standard_io_resources(void)
++void __init reserve_standard_io_resources(void)
+ {
+ 	int i;
+ 
+@@ -706,10 +697,6 @@ static int __init setup_elfcorehdr(char 
+ early_param("elfcorehdr", setup_elfcorehdr);
+ #endif
+ 
+-static struct x86_quirks default_x86_quirks __initdata;
+-
+-struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+-
+ #ifdef CONFIG_X86_RESERVE_LOW_64K
+ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
+ {
+@@ -742,6 +729,13 @@ static struct dmi_system_id __initdata b
+ 		},
+ 	},
+ 	{
++		.callback = dmi_low_memory_corruption,
++		.ident = "Phoenix/MSC BIOS",
++		.matches = {
++			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
++		},
++	},
++	{
+ 	/*
+ 	 * AMI BIOS with low memory corruption was found on Intel DG45ID board.
+ 	 * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+@@ -865,7 +859,7 @@ void __init setup_arch(char **cmdline_p)
+ 	copy_edid();
+ #endif /* CONFIG_XEN */
+ 
+-	ARCH_SETUP
++	x86_init.oem.arch_setup();
+ 
+ 	setup_memory_map();
+ 	parse_setup_data();
+@@ -906,6 +900,16 @@ void __init setup_arch(char **cmdline_p)
+ 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
++#ifdef CONFIG_X86_64
++	/*
++	 * Must call this twice: Once just to detect whether hardware doesn't
++	 * support NX (so that the early EHCI debug console setup can safely
++	 * call set_fixmap(), and then again after parsing early parameters to
++	 * honor the respective command line option.
++	 */
++	check_efer();
++#endif
++
+ 	parse_early_param();
+ 
+ #ifdef CONFIG_X86_64
+@@ -945,12 +949,9 @@ void __init setup_arch(char **cmdline_p)
+ 	 * VMware detection requires dmi to be available, so this
+ 	 * needs to be done after dmi_scan_machine, for the BP.
+ 	 */
+-	init_hypervisor(&boot_cpu_data);
++	init_hypervisor_platform();
+ 
+-#ifdef CONFIG_X86_32
+-	if (is_initial_xendomain())
+-		probe_roms();
+-#endif
++	x86_init.resources.probe_roms();
+ 
+ #ifndef CONFIG_XEN
+ 	/* after parse_early_param, so could debug it */
+@@ -1103,10 +1104,11 @@ void __init setup_arch(char **cmdline_p)
+ 	kvmclock_init();
+ #endif
+ 
+-	xen_pagetable_setup_start(swapper_pg_dir);
++	x86_init.paging.pagetable_setup_start(swapper_pg_dir);
+ 	paging_init();
+-	xen_pagetable_setup_done(swapper_pg_dir);
+-	paravirt_post_allocator_init();
++	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
++
++	tboot_probe();
+ 
+ #ifdef CONFIG_X86_64
+ 	map_vsyscall();
+@@ -1197,13 +1199,13 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ 	acpi_boot_init();
+ 
+-#if defined(CONFIG_X86_MPPARSE) || defined(CONFIG_X86_VISWS)
++	sfi_init();
++
+ 	/*
+ 	 * get boot-time SMP configuration:
+ 	 */
+ 	if (smp_found_config)
+ 		get_smp_config();
+-#endif
+ 
+ 	prefill_possible_map();
+ 
+@@ -1227,11 +1229,7 @@ void __init setup_arch(char **cmdline_p)
+ 		e820_reserve_resources();
+ #endif
+ 
+-#ifdef CONFIG_X86_32
+-	if (is_initial_xendomain())
+-		request_resource(&iomem_resource, &video_ram_resource);
+-#endif
+-	reserve_standard_io_resources();
++	x86_init.resources.reserve_resources();
+ 
+ #ifndef CONFIG_XEN
+ 	e820_setup_gap();
+@@ -1261,80 +1259,25 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ #endif
+ #endif /* CONFIG_XEN */
++	x86_init.oem.banner();
+ }
+ 
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+-
+-/**
+- * x86_quirk_intr_init - post gate setup interrupt initialisation
+- *
+- * Description:
+- *	Fill in any interrupts that may have been left out by the general
+- *	init_IRQ() routine.  interrupts having to do with the machine rather
+- *	than the devices on the I/O bus (like APIC interrupts in intel MP
+- *	systems) are started here.
+- **/
+-void __init x86_quirk_intr_init(void)
+-{
+-	if (x86_quirks->arch_intr_init) {
+-		if (x86_quirks->arch_intr_init())
+-			return;
+-	}
+-}
+-
+-/**
+- * x86_quirk_trap_init - initialise system specific traps
+- *
+- * Description:
+- *	Called as the final act of trap_init().  Used in VISWS to initialise
+- *	the various board specific APIC traps.
+- **/
+-void __init x86_quirk_trap_init(void)
+-{
+-	if (x86_quirks->arch_trap_init) {
+-		if (x86_quirks->arch_trap_init())
+-			return;
+-	}
+-}
++#ifdef CONFIG_X86_32
+ 
+-static struct irqaction irq0  = {
+-	.handler = timer_interrupt,
+-	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
+-	.name = "timer"
++static struct resource video_ram_resource = {
++	.name	= "Video RAM area",
++	.start	= 0xa0000,
++	.end	= 0xbffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+ 
+-/**
+- * x86_quirk_pre_time_init - do any specific initialisations before.
+- *
+- **/
+-void __init x86_quirk_pre_time_init(void)
++void __init i386_reserve_resources(void)
+ {
+-	if (x86_quirks->arch_pre_time_init)
+-		x86_quirks->arch_pre_time_init();
++	if (is_initial_xendomain())
++		request_resource(&iomem_resource, &video_ram_resource);
++	reserve_standard_io_resources();
+ }
+ 
+-/**
+- * x86_quirk_time_init - do any specific initialisations for the system timer.
+- *
+- * Description:
+- *	Must plug the system timer interrupt source at HZ into the IRQ listed
+- *	in irq_vectors.h:TIMER_IRQ
+- **/
+-void __init x86_quirk_time_init(void)
+-{
+-	if (x86_quirks->arch_time_init) {
+-		/*
+-		 * A nonzero return code does not mean failure, it means
+-		 * that the architecture quirk does not want any
+-		 * generic (timer) setup to be performed after this:
+-		 */
+-		if (x86_quirks->arch_time_init())
+-			return;
+-	}
+-
+-	irq0.mask = cpumask_of_cpu(0);
+-	setup_irq(0, &irq0);
+-}
+ #endif /* CONFIG_X86_32 */
+ 
+ #ifdef CONFIG_XEN
+--- head-2010-01-18.orig/arch/x86/kernel/sfi.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/sfi.c	2009-11-06 10:52:23.000000000 +0100
+@@ -31,7 +31,7 @@
+ #include <asm/setup.h>
+ #include <asm/apic.h>
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+ 
+ void __init mp_sfi_register_lapic_address(unsigned long address)
+@@ -99,9 +99,12 @@ static int __init sfi_parse_ioapic(struc
+ 		pentry++;
+ 	}
+ 
++#ifndef CONFIG_XEN
+ 	WARN(pic_mode, KERN_WARNING
+ 		"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n");
+ 	pic_mode = 0;
++#endif
++
+ 	return 0;
+ }
+ #endif /* CONFIG_X86_IO_APIC */
+@@ -111,7 +114,7 @@ static int __init sfi_parse_ioapic(struc
+  */
+ int __init sfi_platform_init(void)
+ {
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	mp_sfi_register_lapic_address(sfi_lapic_addr);
+ 	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:43:22.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:43:52.000000000 +0100
+@@ -1,31 +1,12 @@
+ /*
+- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
++ *  Copyright (c) 1991,1992,1995  Linus Torvalds
++ *  Copyright (c) 1994  Alan Modra
++ *  Copyright (c) 1995  Markus Kuhn
++ *  Copyright (c) 1996  Ingo Molnar
++ *  Copyright (c) 1998  Andrea Arcangeli
++ *  Copyright (c) 2002,2006  Vojtech Pavlik
++ *  Copyright (c) 2003  Andi Kleen
+  *
+- * This file contains the PC-specific time handling details:
+- * reading the RTC at bootup, etc..
+- * 1994-07-02    Alan Modra
+- *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+- * 1995-03-26    Markus Kuhn
+- *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
+- *      precision CMOS clock update
+- * 1996-05-03    Ingo Molnar
+- *      fixed time warps in do_[slow|fast]_gettimeoffset()
+- * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+- * 1998-09-05    (Various)
+- *	More robust do_fast_gettimeoffset() algorithm implemented
+- *	(works with APM, Cyrix 6x86MX and Centaur C6),
+- *	monotonic gettimeofday() with fast_get_timeoffset(),
+- *	drift-proof precision TSC calibration on boot
+- *	(C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D.
+- *	Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>;
+- *	ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>).
+- * 1998-12-16    Andrea Arcangeli
+- *	Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy
+- *	because was not accounting lost_ticks.
+- * 1998-12-24 Copyright (C) 1998  Andrea Arcangeli
+- *	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
+- *	serialize accesses to xtime/lost_ticks).
+  */
+ 
+ #include <linux/init.h>
+@@ -40,6 +21,7 @@
+ #include <linux/clocksource.h>
+ #include <linux/sysdev.h>
+ 
++#include <asm/vsyscall.h>
+ #include <asm/delay.h>
+ #include <asm/time.h>
+ #include <asm/timer.h>
+@@ -53,7 +35,6 @@ DEFINE_SPINLOCK(i8253_lock);
+ EXPORT_SYMBOL(i8253_lock);
+ 
+ #ifdef CONFIG_X86_64
+-#include <asm/vsyscall.h>
+ volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+ #endif
+ 
+@@ -406,36 +387,31 @@ unsigned long profile_pc(struct pt_regs 
+ {
+ 	unsigned long pc = instruction_pointer(regs);
+ 
+-#if defined(CONFIG_SMP) || defined(__x86_64__)
+ 	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+-# ifdef CONFIG_FRAME_POINTER
++#ifdef CONFIG_FRAME_POINTER
+ 		return *(unsigned long *)(regs->bp + sizeof(long));
+-# else
+-#  ifdef __i386__
+-		unsigned long *sp = (unsigned long *)&regs->sp;
+-#  else
+-		unsigned long *sp = (unsigned long *)regs->sp;
+-#  endif
+-
+-		/* Return address is either directly at stack pointer
+-		   or above a saved flags. Eflags has bits 22-31 zero,
+-		   kernel addresses don't. */
++#else
++		unsigned long *sp =
++			(unsigned long *)kernel_stack_pointer(regs);
++
++		/*
++		 * Return address is either directly at stack pointer
++		 * or above a saved flags. Eflags has bits 22-31 zero,
++		 * kernel addresses don't.
++		 */
+ 		if (sp[0] >> 22)
+ 			return sp[0];
+ 		if (sp[1] >> 22)
+ 			return sp[1];
+-# endif
+-	}
+ #endif
++	}
+ 
+ 	return pc;
+ }
+ EXPORT_SYMBOL(profile_pc);
+ 
+ /*
+- * This is the same as the above, except we _also_ save the current
+- * Time Stamp Counter value at the time of the timer interrupt, so that
+- * we later on can estimate the time of day more exactly.
++ * Default timer interrupt handler
+  */
+ irqreturn_t timer_interrupt(int irq, void *dev_id)
+ {
+@@ -557,8 +533,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 
+ 	/* Local timer processing (see update_process_times()). */
+ 	run_local_timers();
+-	if (rcu_pending(cpu))
+-		rcu_check_callbacks(cpu, user_mode_vm(get_irq_regs()));
++	rcu_check_callbacks(cpu, user_mode_vm(get_irq_regs()));
+ 	printk_tick();
+ 	scheduler_tick();
+ 	run_posix_cpu_timers(current);
+@@ -658,7 +633,7 @@ static void init_missing_ticks_accountin
+ 		runstate->time[RUNSTATE_offline];
+ }
+ 
+-unsigned long xen_read_persistent_clock(void)
++void xen_read_persistent_clock(struct timespec *ts)
+ {
+ 	const shared_info_t *s = HYPERVISOR_shared_info;
+ 	u32 version, sec, nsec;
+@@ -675,7 +650,8 @@ unsigned long xen_read_persistent_clock(
+ 	delta = local_clock() + (u64)sec * NSEC_PER_SEC + nsec;
+ 	do_div(delta, NSEC_PER_SEC);
+ 
+-	return delta;
++	ts->tv_sec = delta;
++	ts->tv_nsec = 0;
+ }
+ 
+ int xen_update_persistent_clock(void)
+--- head-2010-01-18.orig/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -14,7 +14,6 @@
+ #include <linux/spinlock.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+-#include <linux/utsname.h>
+ #include <linux/kdebug.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -59,12 +58,12 @@
+ #include <asm/mach_traps.h>
+ 
+ #ifdef CONFIG_X86_64
++#include <asm/x86_init.h>
+ #include <asm/pgalloc.h>
+ #include <asm/proto.h>
+ #else
+ #include <asm/processor-flags.h>
+ #include <asm/setup.h>
+-#include <asm/traps.h>
+ 
+ asmlinkage int system_call(void);
+ 
+@@ -74,11 +73,9 @@ char ignore_fpu_irq;
+ #ifndef CONFIG_X86_NO_IDT
+ /*
+  * The IDT has to be page-aligned to simplify the Pentium
+- * F0 0F bug workaround.. We have a special link segment
+- * for this.
++ * F0 0F bug workaround.
+  */
+-gate_desc idt_table[256]
+-	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
++gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
+ #endif
+ #endif
+ 
+@@ -780,27 +777,6 @@ do_spurious_interrupt_bug(struct pt_regs
+ #endif
+ }
+ 
+-#ifdef CONFIG_X86_32
+-unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+-{
+-	struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
+-	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+-	unsigned long new_kesp = kesp - base;
+-	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+-	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
+-
+-	/* Set up base for espfix segment */
+-	desc &= 0x00f0ff0000000000ULL;
+-	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+-		((((__u64)base) << 32) & 0xff00000000000000ULL) |
+-		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+-		(lim_pages & 0xffff);
+-	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
+-
+-	return new_kesp;
+-}
+-#endif
+-
+ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+ {
+ }
+@@ -811,6 +787,28 @@ asmlinkage void __attribute__((weak)) sm
+ #endif /* CONFIG_XEN */
+ 
+ /*
++ * __math_state_restore assumes that cr0.TS is already clear and the
++ * fpu state is all ready for use.  Used during context switch.
++ */
++void __math_state_restore(void)
++{
++	struct thread_info *thread = current_thread_info();
++	struct task_struct *tsk = thread->task;
++
++	/*
++	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
++	 */
++	if (unlikely(restore_fpu_checking(tsk))) {
++		stts();
++		force_sig(SIGSEGV, tsk);
++		return;
++	}
++
++	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
++	tsk->fpu_counter++;
++}
++
++/*
+  * 'math_state_restore()' saves the current math information in the
+  * old math state array, and gets the new ones from the current task
+  *
+@@ -841,17 +839,7 @@ asmlinkage void math_state_restore(void)
+ 	}
+ 
+ 	/* NB. 'clts' is done for us by Xen during virtual trap. */
+-	/*
+-	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+-	 */
+-	if (unlikely(restore_fpu_checking(tsk))) {
+-		stts();
+-		force_sig(SIGSEGV, tsk);
+-		return;
+-	}
+-
+-	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+-	tsk->fpu_counter++;
++	__math_state_restore();
+ }
+ EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+@@ -967,6 +955,8 @@ void __init trap_init(void)
+ 	 * Should be a barrier for any external CPU state:
+ 	 */
+ 	cpu_init();
++
++	x86_init.irqs.trap_init();
+ }
+ 
+ void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -87,6 +87,7 @@ void update_vsyscall(struct timespec *wa
+ 	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+ 	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+ 	vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;
++	vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
+ 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+ 
+@@ -227,19 +228,11 @@ static long __vsyscall(3) venosys_1(void
+ }
+ 
+ #ifdef CONFIG_SYSCTL
+-
+-static int
+-vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
+-		       void __user *buffer, size_t *lenp, loff_t *ppos)
+-{
+-	return proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-}
+-
+ static ctl_table kernel_table2[] = {
+ 	{ .procname = "vsyscall64",
+ 	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
+ 	  .mode = 0644,
+-	  .proc_handler = vsyscall_sysctl_change },
++	  .proc_handler = proc_dointvec },
+ 	{}
+ };
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/x86_init-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (C) 2009 Thomas Gleixner <tglx@linutronix.de>
++ *
++ *  For licencing details see kernel-base/COPYING
++ */
++#include <linux/bitmap.h>
++#include <linux/init.h>
++#include <linux/threads.h>
++
++#include <asm/mpspec.h>
++#include <asm/setup.h>
++#include <asm/apic.h>
++#include <asm/e820.h>
++#include <asm/time.h>
++#include <asm/irq.h>
++
++void __cpuinit x86_init_noop(void) { }
++void __init x86_init_uint_noop(unsigned int unused) { }
++void __init x86_init_pgd_noop(pgd_t *unused) { }
++
++/*
++ * The platform setup functions are preset with the default functions
++ * for standard PC hardware.
++ */
++struct x86_init_ops x86_init __initdata = {
++
++	.resources = {
++		.probe_roms		= x86_init_noop,
++		.reserve_resources	= reserve_standard_io_resources,
++		.memory_setup		= default_machine_specific_memory_setup,
++	},
++
++	.mpparse = {
++		.mpc_record		= x86_init_uint_noop,
++		.setup_ioapic_ids	= x86_init_noop,
++		.mpc_apic_id		= NULL,
++		.smp_read_mpc_oem	= default_smp_read_mpc_oem,
++		.mpc_oem_bus_info	= default_mpc_oem_bus_info,
++		.find_smp_config	= default_find_smp_config,
++		.get_smp_config		= default_get_smp_config,
++	},
++
++	.irqs = {
++		.pre_vector_init	= NULL,
++		.intr_init		= NULL,
++		.trap_init		= x86_init_noop,
++	},
++
++	.oem = {
++		.arch_setup		= xen_arch_setup,
++		.banner			= x86_init_noop,
++	},
++
++	.paging = {
++		.pagetable_setup_start	= x86_init_pgd_noop,
++		.pagetable_setup_done	= x86_init_pgd_noop,
++	},
++
++	.timers = {
++		.setup_percpu_clockev	= NULL,
++		.tsc_pre_init		= x86_init_noop,
++		.timer_init		= x86_init_noop,
++	},
++};
++
++struct x86_platform_ops x86_platform = {
++	.calibrate_tsc			= NULL,
++	.get_wallclock			= mach_get_cmos_time,
++	.set_wallclock			= mach_set_rtc_mmss,
++};
+--- head-2010-01-18.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -10,7 +10,7 @@
+ #include <linux/bootmem.h>		/* max_low_pfn			*/
+ #include <linux/kprobes.h>		/* __kprobes, ...		*/
+ #include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/
+-#include <linux/perf_counter.h>		/* perf_swcounter_event		*/
++#include <linux/perf_event.h>		/* perf_sw_event		*/
+ 
+ #include <asm/traps.h>			/* dotraplinkage, ...		*/
+ #include <asm/pgalloc.h>		/* pgd_*(), ...			*/
+@@ -167,6 +167,7 @@ force_sig_info_fault(int si_signo, int s
+ 	info.si_errno	= 0;
+ 	info.si_code	= si_code;
+ 	info.si_addr	= (void __user *)address;
++	info.si_addr_lsb = si_code == BUS_MCEERR_AR ? PAGE_SHIFT : 0;
+ 
+ 	force_sig_info(si_signo, &info, tsk);
+ }
+@@ -293,27 +294,25 @@ check_v8086_mode(struct pt_regs *regs, u
+ 		tsk->thread.screen_bitmap |= 1 << bit;
+ }
+ 
+-static void dump_pagetable(unsigned long address)
++static bool low_pfn(unsigned long pfn)
+ {
+-	__typeof__(pte_val(__pte(0))) page;
++	return pfn < max_low_pfn;
++}
+ 
+-	page = read_cr3();
+-	page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
++static void dump_pagetable(unsigned long address)
++{
++	pgd_t *base = __va(read_cr3());
++	pgd_t *pgd = &base[pgd_index(address)];
++	pmd_t *pmd;
++	pte_t *pte;
+ 
+ #ifdef CONFIG_X86_PAE
+-	printk("*pdpt = %016Lx ", page);
+-	if ((page & _PAGE_PRESENT)
+-	    && mfn_to_local_pfn(page >> PAGE_SHIFT) < max_low_pfn) {
+-		page = mfn_to_pfn(page >> PAGE_SHIFT);
+-		page <<= PAGE_SHIFT;
+-		page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
+-							& (PTRS_PER_PMD - 1)];
+-		printk(KERN_CONT "*pde = %016Lx ", page);
+-		page &= ~_PAGE_NX;
+-	}
+-#else
+-	printk("*pde = %08lx ", page);
++	printk("*pdpt = %016Lx ", __pgd_val(*pgd));
++	if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd))
++		goto out;
+ #endif
++	pmd = pmd_offset(pud_offset(pgd, address), address);
++	printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)__pmd_val(*pmd));
+ 
+ 	/*
+ 	 * We must not directly access the pte in the highpte
+@@ -321,17 +320,12 @@ static void dump_pagetable(unsigned long
+ 	 * And let's rather not kmap-atomic the pte, just in case
+ 	 * it's allocated already:
+ 	 */
+-	if ((page & _PAGE_PRESENT)
+-	    && mfn_to_local_pfn(page >> PAGE_SHIFT) < max_low_pfn
+-	    && !(page & _PAGE_PSE)) {
+-
+-		page = mfn_to_pfn(page >> PAGE_SHIFT);
+-		page <<= PAGE_SHIFT;
+-		page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
+-							& (PTRS_PER_PTE - 1)];
+-		printk(KERN_CONT "*pte = %0*Lx ", sizeof(page)*2, (u64)page);
+-	}
++	if (!low_pfn(pmd_pfn(*pmd)) || !pmd_present(*pmd) || pmd_large(*pmd))
++		goto out;
+ 
++	pte = pte_offset_kernel(pmd, address);
++	printk(KERN_CONT "*pte = %0*Lx ", sizeof(*pte) * 2, (u64)__pte_val(*pte));
++out:
+ 	printk(KERN_CONT "\n");
+ }
+ 
+@@ -460,16 +454,12 @@ static int bad_address(void *p)
+ 
+ static void dump_pagetable(unsigned long address)
+ {
+-	pgd_t *pgd;
++	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
++	pgd_t *pgd = base + pgd_index(address);
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+ 
+-	pgd = (pgd_t *)read_cr3();
+-
+-	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
+-
+-	pgd += pgd_index(address);
+ 	if (bad_address(pgd))
+ 		goto bad;
+ 
+@@ -809,10 +799,12 @@ out_of_memory(struct pt_regs *regs, unsi
+ }
+ 
+ static void
+-do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
++do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
++	  unsigned int fault)
+ {
+ 	struct task_struct *tsk = current;
+ 	struct mm_struct *mm = tsk->mm;
++	int code = BUS_ADRERR;
+ 
+ 	up_read(&mm->mmap_sem);
+ 
+@@ -828,7 +820,15 @@ do_sigbus(struct pt_regs *regs, unsigned
+ 	tsk->thread.error_code	= error_code;
+ 	tsk->thread.trap_no	= 14;
+ 
+-	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
++#ifdef CONFIG_MEMORY_FAILURE
++	if (fault & VM_FAULT_HWPOISON) {
++		printk(KERN_ERR
++	"MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
++			tsk->comm, tsk->pid, address);
++		code = BUS_MCEERR_AR;
++	}
++#endif
++	force_sig_info_fault(SIGBUS, code, address, tsk);
+ }
+ 
+ static noinline void
+@@ -838,8 +838,8 @@ mm_fault_error(struct pt_regs *regs, uns
+ 	if (fault & VM_FAULT_OOM) {
+ 		out_of_memory(regs, error_code, address);
+ 	} else {
+-		if (fault & VM_FAULT_SIGBUS)
+-			do_sigbus(regs, error_code, address);
++		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON))
++			do_sigbus(regs, error_code, address, fault);
+ 		else
+ 			BUG();
+ 	}
+@@ -1053,7 +1053,7 @@ do_page_fault(struct pt_regs *regs, unsi
+ 	if (unlikely(error_code & PF_RSVD))
+ 		pgtable_bad(regs, error_code, address);
+ 
+-	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
++	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+ 
+ 	/*
+ 	 * If we're in an interrupt, have no user context or are running
+@@ -1150,11 +1150,11 @@ good_area:
+ 
+ 	if (fault & VM_FAULT_MAJOR) {
+ 		tsk->maj_flt++;
+-		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
++		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+ 				     regs, address);
+ 	} else {
+ 		tsk->min_flt++;
+-		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
++		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+ 				     regs, address);
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -24,7 +24,7 @@ void kunmap(struct page *page)
+  * no global lock is needed and because the kmap code must perform a global TLB
+  * invalidation when the kmap pool wraps.
+  *
+- * However when holding an atomic kmap is is not legal to sleep, so atomic
++ * However when holding an atomic kmap it is not legal to sleep, so atomic
+  * kmaps are appropriate for short, tight code paths only.
+  */
+ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+@@ -149,9 +149,7 @@ EXPORT_SYMBOL(kunmap);
+ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
+ EXPORT_SYMBOL(kmap_atomic_prot);
+-#ifdef CONFIG_HIGHPTE
+ EXPORT_SYMBOL(kmap_atomic_to_page);
+-#endif
+ EXPORT_SYMBOL(clear_highpage);
+ EXPORT_SYMBOL(copy_highpage);
+ 
+--- head-2010-01-18.orig/arch/x86/mm/init-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -36,69 +36,6 @@ extern unsigned long extend_init_mapping
+ extern void xen_finish_init_mapping(void);
+ #endif
+ 
+-int nx_enabled;
+-
+-#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+-static int disable_nx __cpuinitdata;
+-
+-/*
+- * noexec = on|off
+- *
+- * Control non-executable mappings for processes.
+- *
+- * on      Enable
+- * off     Disable
+- */
+-static int __init noexec_setup(char *str)
+-{
+-	if (!str)
+-		return -EINVAL;
+-	if (!strncmp(str, "on", 2)) {
+-		__supported_pte_mask |= _PAGE_NX;
+-		disable_nx = 0;
+-	} else if (!strncmp(str, "off", 3)) {
+-		disable_nx = 1;
+-		__supported_pte_mask &= ~_PAGE_NX;
+-	}
+-	return 0;
+-}
+-early_param("noexec", noexec_setup);
+-#endif
+-
+-#ifdef CONFIG_X86_PAE
+-static void __init set_nx(void)
+-{
+-	unsigned int v[4], l, h;
+-
+-	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+-		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+-
+-		if ((v[3] & (1 << 20)) && !disable_nx) {
+-			rdmsr(MSR_EFER, l, h);
+-			l |= EFER_NX;
+-			wrmsr(MSR_EFER, l, h);
+-			nx_enabled = 1;
+-			__supported_pte_mask |= _PAGE_NX;
+-		}
+-	}
+-}
+-#else
+-static inline void set_nx(void)
+-{
+-}
+-#endif
+-
+-#ifdef CONFIG_X86_64
+-void __cpuinit check_efer(void)
+-{
+-	unsigned long efer;
+-
+-	rdmsrl(MSR_EFER, efer);
+-	if (!(efer & EFER_NX) || disable_nx)
+-		__supported_pte_mask &= ~_PAGE_NX;
+-}
+-#endif
+-
+ static void __init find_early_table_space(unsigned long end, int use_pse,
+ 					  int use_gbpages)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -87,7 +87,7 @@ static pmd_t * __init one_md_table_init(
+ #ifdef CONFIG_X86_PAE
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+ 		if (after_bootmem)
+-			pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
++			pmd_table = (pmd_t *)alloc_bootmem_pages(PAGE_SIZE);
+ 		else
+ 			pmd_table = (pmd_t *)alloc_low_page();
+ 		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+@@ -124,7 +124,7 @@ static pte_t * __init one_page_table_ini
+ #endif
+ 			if (!page_table)
+ 				page_table =
+-				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
++				(pte_t *)alloc_bootmem_pages(PAGE_SIZE);
+ 		} else
+ 			page_table = (pte_t *)alloc_low_page();
+ 
+@@ -914,8 +914,6 @@ static void __init test_wp_bit(void)
+ 	}
+ }
+ 
+-static struct kcore_list kcore_mem, kcore_vmalloc;
+-
+ void __init mem_init(void)
+ {
+ 	int codesize, reservedpages, datasize, initsize;
+@@ -949,13 +947,9 @@ void __init mem_init(void)
+ 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+ 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+ 
+-	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+-	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+-		   VMALLOC_END-VMALLOC_START);
+-
+ 	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+ 			"%dk reserved, %dk data, %dk init, %ldk highmem)\n",
+-		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
++		nr_free_pages() << (PAGE_SHIFT-10),
+ 		num_physpages << (PAGE_SHIFT-10),
+ 		codesize >> 10,
+ 		reservedpages << (PAGE_SHIFT-10),
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -894,8 +894,7 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
+ 
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
+-static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
+-			 kcore_modules, kcore_vsyscall;
++static struct kcore_list kcore_vsyscall;
+ 
+ void __init mem_init(void)
+ {
+@@ -931,17 +930,12 @@ void __init mem_init(void)
+ 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+ 
+ 	/* Register memory areas for /proc/kcore */
+-	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+-	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+-		   VMALLOC_END-VMALLOC_START);
+-	kclist_add(&kcore_kernel, &_stext, _end - _stext);
+-	kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN);
+ 	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START,
+-				 VSYSCALL_END - VSYSCALL_START);
++			 VSYSCALL_END - VSYSCALL_START, KCORE_OTHER);
+ 
+ 	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+ 			 "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n",
+-		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
++		nr_free_pages() << (PAGE_SHIFT-10),
+ 		max_pfn << (PAGE_SHIFT-10),
+ 		codesize >> 10,
+ 		absent_pages << (PAGE_SHIFT-10),
+--- head-2010-01-18.orig/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -22,7 +22,7 @@
+ #include <linux/module.h>
+ #include <linux/highmem.h>
+ 
+-int is_io_mapping_possible(resource_size_t base, unsigned long size)
++static int is_io_mapping_possible(resource_size_t base, unsigned long size)
+ {
+ #if !defined(CONFIG_X86_PAE) && defined(CONFIG_PHYS_ADDR_T_64BIT)
+ 	/* There is no way to map greater than 1 << 32 address without PAE */
+@@ -31,7 +31,30 @@ int is_io_mapping_possible(resource_size
+ #endif
+ 	return 1;
+ }
+-EXPORT_SYMBOL_GPL(is_io_mapping_possible);
++
++int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot)
++{
++	unsigned long flag = _PAGE_CACHE_WC;
++	int ret;
++
++	if (!is_io_mapping_possible(base, size))
++		return -EINVAL;
++
++	ret = io_reserve_memtype(base, base + size, &flag);
++	if (ret)
++		return ret;
++
++	*prot = __pgprot(__PAGE_KERNEL | flag);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(iomap_create_wc);
++
++void
++iomap_free(resource_size_t base, unsigned long size)
++{
++	io_free_memtype(base, base + size);
++}
++EXPORT_SYMBOL_GPL(iomap_free);
+ 
+ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-18 14:56:06.000000000 +0100
+@@ -23,81 +23,7 @@
+ #include <asm/pgalloc.h>
+ #include <asm/pat.h>
+ 
+-static inline int phys_addr_valid(resource_size_t addr)
+-{
+-#ifdef CONFIG_PHYS_ADDR_T_64BIT
+-	return !(addr >> boot_cpu_data.x86_phys_bits);
+-#else
+-	return 1;
+-#endif
+-}
+-
+-#ifdef CONFIG_X86_64
+-
+-#define phys_base 0
+-
+-unsigned long __phys_addr(unsigned long x)
+-{
+-	if (x >= __START_KERNEL_map) {
+-		x -= __START_KERNEL_map;
+-		VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
+-		x += phys_base;
+-	} else {
+-		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
+-		x -= PAGE_OFFSET;
+-		VIRTUAL_BUG_ON(!phys_addr_valid(x));
+-	}
+-	return x;
+-}
+-EXPORT_SYMBOL(__phys_addr);
+-
+-bool __virt_addr_valid(unsigned long x)
+-{
+-	if (x >= __START_KERNEL_map) {
+-		x -= __START_KERNEL_map;
+-		if (x >= KERNEL_IMAGE_SIZE)
+-			return false;
+-		x += phys_base;
+-	} else {
+-		if (x < PAGE_OFFSET)
+-			return false;
+-		x -= PAGE_OFFSET;
+-		if (!phys_addr_valid(x))
+-			return false;
+-	}
+-
+-	return pfn_valid(x >> PAGE_SHIFT);
+-}
+-EXPORT_SYMBOL(__virt_addr_valid);
+-
+-#undef phys_base
+-
+-#else
+-
+-#ifdef CONFIG_DEBUG_VIRTUAL
+-unsigned long __phys_addr(unsigned long x)
+-{
+-	/* VMALLOC_* aren't constants  */
+-	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
+-	VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
+-	return x - PAGE_OFFSET;
+-}
+-EXPORT_SYMBOL(__phys_addr);
+-#endif
+-
+-bool __virt_addr_valid(unsigned long x)
+-{
+-	if (x < PAGE_OFFSET)
+-		return false;
+-	if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
+-		return false;
+-	if (x >= FIXADDR_START)
+-		return false;
+-	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
+-}
+-EXPORT_SYMBOL(__virt_addr_valid);
+-
+-#endif
++#include "physaddr.h"
+ 
+ static int direct_remap_area_pte_fn(pte_t *pte,
+ 				    struct page *pmd_page,
+@@ -407,30 +333,19 @@ static void __iomem *__ioremap_caller(re
+ 	retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
+ 						prot_val, &new_prot_val);
+ 	if (retval) {
+-		pr_debug("Warning: reserve_memtype returned %d\n", retval);
++		printk(KERN_ERR "ioremap reserve_memtype failed %d\n", retval);
+ 		return NULL;
+ 	}
+ 
+ 	if (prot_val != new_prot_val) {
+-		/*
+-		 * Do not fallback to certain memory types with certain
+-		 * requested type:
+-		 * - request is uc-, return cannot be write-back
+-		 * - request is uc-, return cannot be write-combine
+-		 * - request is write-combine, return cannot be write-back
+-		 */
+-		if ((prot_val == _PAGE_CACHE_UC_MINUS &&
+-		     (new_prot_val == _PAGE_CACHE_WB ||
+-		      new_prot_val == _PAGE_CACHE_WC)) ||
+-		    (prot_val == _PAGE_CACHE_WC &&
+-		     new_prot_val == _PAGE_CACHE_WB)) {
+-			pr_debug(
++		if (!is_new_memtype_allowed(phys_addr, size,
++					    prot_val, new_prot_val)) {
++			printk(KERN_ERR
+ 		"ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
+ 				(unsigned long long)phys_addr,
+ 				(unsigned long long)(phys_addr + size),
+ 				prot_val, new_prot_val);
+-			free_memtype(phys_addr, phys_addr + size);
+-			return NULL;
++			goto err_free_memtype;
+ 		}
+ 		prot_val = new_prot_val;
+ 	}
+@@ -456,27 +371,26 @@ static void __iomem *__ioremap_caller(re
+ 	 */
+ 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ 	if (!area)
+-		return NULL;
++		goto err_free_memtype;
+ 	area->phys_addr = phys_addr;
+ 	vaddr = (unsigned long) area->addr;
+ 
+-	if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
+-		free_memtype(phys_addr, phys_addr + size);
+-		free_vm_area(area);
+-		return NULL;
+-	}
++	if (kernel_map_sync_memtype(phys_addr, size, prot_val))
++		goto err_free_area;
+ 
+ 	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
+-				     size, prot, domid)) {
+-		free_memtype(phys_addr, phys_addr + size);
+-		free_vm_area(area);
+-		return NULL;
+-	}
++				     size, prot, domid))
++		goto err_free_area;
+ 
+ 	ret_addr = (void __iomem *) (vaddr + offset);
+ 	mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
+ 
+ 	return ret_addr;
++err_free_area:
++	free_vm_area(area);
++err_free_memtype:
++	free_memtype(phys_addr, phys_addr + size);
++	return NULL;
+ }
+ 
+ /**
+--- head-2010-01-18.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -12,6 +12,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/debugfs.h>
+ #include <linux/pfn.h>
++#include <linux/percpu.h>
+ 
+ #include <asm/e820.h>
+ #include <asm/processor.h>
+@@ -143,6 +144,7 @@ void clflush_cache_range(void *vaddr, un
+ 
+ 	mb();
+ }
++EXPORT_SYMBOL_GPL(clflush_cache_range);
+ 
+ static void __cpa_flush_all(void *arg)
+ {
+@@ -707,7 +709,7 @@ static int cpa_process_alias(struct cpa_
+ {
+ 	struct cpa_data alias_cpa;
+ 	unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
+-	unsigned long vaddr, remapped;
++	unsigned long vaddr;
+ 	int ret;
+ 
+ 	if (cpa->pfn >= max_pfn_mapped)
+@@ -765,24 +767,6 @@ static int cpa_process_alias(struct cpa_
+ 	}
+ #endif
+ 
+-	/*
+-	 * If the PMD page was partially used for per-cpu remapping,
+-	 * the recycled area needs to be split and modified.  Because
+-	 * the area is always proper subset of a PMD page
+-	 * cpa->numpages is guaranteed to be 1 for these areas, so
+-	 * there's no need to loop over and check for further remaps.
+-	 */
+-	remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
+-	if (remapped) {
+-		WARN_ON(cpa->numpages > 1);
+-		alias_cpa = *cpa;
+-		alias_cpa.vaddr = &remapped;
+-		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+-		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+-		if (ret)
+-			return ret;
+-	}
+-
+ 	return 0;
+ }
+ 
+@@ -843,6 +827,7 @@ static int change_page_attr_set_clr(unsi
+ {
+ 	struct cpa_data cpa;
+ 	int ret, cache, checkalias;
++	unsigned long baddr = 0;
+ 
+ 	/*
+ 	 * Check, if we are requested to change a not supported
+@@ -874,6 +859,11 @@ static int change_page_attr_set_clr(unsi
+ 			 */
+ 			WARN_ON_ONCE(1);
+ 		}
++		/*
++		 * Save address for cache flush. *addr is modified in the call
++		 * to __change_page_attr_set_clr() below.
++		 */
++		baddr = *addr;
+ 	}
+ 
+ 	/* Must avoid aliasing mappings in the highmem code */
+@@ -921,7 +911,7 @@ static int change_page_attr_set_clr(unsi
+ 			cpa_flush_array(addr, numpages, cache,
+ 					cpa.flags, pages);
+ 		} else
+-			cpa_flush_range(*addr, numpages, cache);
++			cpa_flush_range(baddr, numpages, cache);
+ 	} else
+ 		cpa_flush_all(cache);
+ 
+--- head-2010-01-18.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pat-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/gfp.h>
+ #include <linux/mm.h>
+ #include <linux/fs.h>
++#include <linux/rbtree.h>
+ 
+ #include <asm/cacheflush.h>
+ #include <asm/processor.h>
+@@ -80,6 +81,7 @@ enum {
+ void pat_init(void)
+ {
+ 	u64 pat;
++	bool boot_cpu = !boot_pat_state;
+ 
+ 	if (!pat_enabled)
+ 		return;
+@@ -131,8 +133,10 @@ void pat_init(void)
+ 	if (!boot_pat_state)
+ 		boot_pat_state = pat;
+ #endif
+-	printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
+-	       smp_processor_id(), boot_pat_state, pat);
++
++	if (boot_cpu)
++		printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
++		       smp_processor_id(), boot_pat_state, pat);
+ }
+ 
+ #undef PAT
+@@ -160,11 +164,10 @@ static char *cattr_name(unsigned long fl
+  * areas). All the aliases have the same cache attributes of course.
+  * Zero attributes are represented as holes.
+  *
+- * Currently the data structure is a list because the number of mappings
+- * are expected to be relatively small. If this should be a problem
+- * it could be changed to a rbtree or similar.
++ * The data structure is a list that is also organized as an rbtree
++ * sorted on the start address of memtype range.
+  *
+- * memtype_lock protects the whole list.
++ * memtype_lock protects both the linear list and rbtree.
+  */
+ 
+ struct memtype {
+@@ -172,11 +175,53 @@ struct memtype {
+ 	u64			end;
+ 	unsigned long		type;
+ 	struct list_head	nd;
++	struct rb_node		rb;
+ };
+ 
++static struct rb_root memtype_rbroot = RB_ROOT;
+ static LIST_HEAD(memtype_list);
+ static DEFINE_SPINLOCK(memtype_lock);	/* protects memtype list */
+ 
++static struct memtype *memtype_rb_search(struct rb_root *root, u64 start)
++{
++	struct rb_node *node = root->rb_node;
++	struct memtype *last_lower = NULL;
++
++	while (node) {
++		struct memtype *data = container_of(node, struct memtype, rb);
++
++		if (data->start < start) {
++			last_lower = data;
++			node = node->rb_right;
++		} else if (data->start > start) {
++			node = node->rb_left;
++		} else
++			return data;
++	}
++
++	/* Will return NULL if there is no entry with its start <= start */
++	return last_lower;
++}
++
++static void memtype_rb_insert(struct rb_root *root, struct memtype *data)
++{
++	struct rb_node **new = &(root->rb_node);
++	struct rb_node *parent = NULL;
++
++	while (*new) {
++		struct memtype *this = container_of(*new, struct memtype, rb);
++
++		parent = *new;
++		if (data->start <= this->start)
++			new = &((*new)->rb_left);
++		else if (data->start > this->start)
++			new = &((*new)->rb_right);
++	}
++
++	rb_link_node(&data->rb, parent, new);
++	rb_insert_color(&data->rb, root);
++}
++
+ /*
+  * Does intersection of PAT memory type and MTRR memory type and returns
+  * the resulting memory type as PAT understands it.
+@@ -230,9 +275,6 @@ chk_conflict(struct memtype *new, struct
+ 	return -EBUSY;
+ }
+ 
+-static struct memtype *cached_entry;
+-static u64 cached_start;
+-
+ static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
+ {
+ 	int ram_page = 0, not_rampage = 0;
+@@ -261,63 +303,61 @@ static int pat_pagerange_is_ram(unsigned
+ }
+ 
+ /*
+- * For RAM pages, mark the pages as non WB memory type using
+- * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or
+- * set_memory_wc() on a RAM page at a time before marking it as WB again.
+- * This is ok, because only one driver will be owning the page and
+- * doing set_memory_*() calls.
+- *
+- * For now, we use PageNonWB to track that the RAM page is being mapped
+- * as non WB. In future, we will have to use one more flag
+- * (or some other mechanism in page_struct) to distinguish between
+- * UC and WC mapping.
++ * For RAM pages, we use page flags to mark the pages with appropriate type.
++ * Here we do two pass:
++ * - Find the memtype of all the pages in the range, look for any conflicts
++ * - In case of no conflicts, set the new memtype for pages in the range
++ *
++ * Caller must hold memtype_lock for atomicity.
+  */
+ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
+ 				  unsigned long *new_type)
+ {
+ 	struct page *page;
+-	u64 pfn, end_pfn;
++	u64 pfn;
++
++	if (req_type == _PAGE_CACHE_UC) {
++		/* We do not support strong UC */
++		WARN_ON_ONCE(1);
++		req_type = _PAGE_CACHE_UC_MINUS;
++	}
+ 
+ 	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
++		unsigned long type;
++
+ 		page = pfn_to_page(pfn);
+-		if (page_mapped(page) || PageNonWB(page))
+-			goto out;
++		type = get_page_memtype(page);
++		if (type != -1) {
++			printk(KERN_INFO "reserve_ram_pages_type failed "
++				"0x%Lx-0x%Lx, track 0x%lx, req 0x%lx\n",
++				start, end, type, req_type);
++			if (new_type)
++				*new_type = type;
+ 
+-		SetPageNonWB(page);
++			return -EBUSY;
++		}
+ 	}
+-	return 0;
+ 
+-out:
+-	end_pfn = pfn;
+-	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
++	if (new_type)
++		*new_type = req_type;
++
++	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+ 		page = pfn_to_page(pfn);
+-		ClearPageNonWB(page);
++		set_page_memtype(page, req_type);
+ 	}
+-
+-	return -EINVAL;
++	return 0;
+ }
+ 
+ static int free_ram_pages_type(u64 start, u64 end)
+ {
+ 	struct page *page;
+-	u64 pfn, end_pfn;
++	u64 pfn;
+ 
+ 	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+ 		page = pfn_to_page(pfn);
+-		if (page_mapped(page) || !PageNonWB(page))
+-			goto out;
+-
+-		ClearPageNonWB(page);
++		set_page_memtype(page, -1);
+ 	}
+ 	return 0;
+-
+-out:
+-	end_pfn = pfn;
+-	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
+-		page = pfn_to_page(pfn);
+-		SetPageNonWB(page);
+-	}
+-	return -EINVAL;
+ }
+ 
+ /*
+@@ -351,6 +391,8 @@ int reserve_memtype(u64 start, u64 end, 
+ 		if (new_type) {
+ 			if (req_type == -1)
+ 				*new_type = _PAGE_CACHE_WB;
++			else if (req_type == _PAGE_CACHE_WC)
++				*new_type = _PAGE_CACHE_UC_MINUS;
+ 			else
+ 				*new_type = req_type & _PAGE_CACHE_MASK;
+ 		}
+@@ -376,11 +418,16 @@ int reserve_memtype(u64 start, u64 end, 
+ 		*new_type = actual_type;
+ 
+ 	is_range_ram = pat_pagerange_is_ram(start, end);
+-	if (is_range_ram == 1)
+-		return reserve_ram_pages_type(start, end, req_type,
+-					      new_type);
+-	else if (is_range_ram < 0)
++	if (is_range_ram == 1) {
++
++		spin_lock(&memtype_lock);
++		err = reserve_ram_pages_type(start, end, req_type, new_type);
++		spin_unlock(&memtype_lock);
++
++		return err;
++	} else if (is_range_ram < 0) {
+ 		return -EINVAL;
++	}
+ 
+ 	new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+ 	if (!new)
+@@ -392,17 +439,11 @@ int reserve_memtype(u64 start, u64 end, 
+ 
+ 	spin_lock(&memtype_lock);
+ 
+-	if (cached_entry && start >= cached_start)
+-		entry = cached_entry;
+-	else
+-		entry = list_entry(&memtype_list, struct memtype, nd);
+-
+ 	/* Search for existing mapping that overlaps the current range */
+ 	where = NULL;
+-	list_for_each_entry_continue(entry, &memtype_list, nd) {
++	list_for_each_entry(entry, &memtype_list, nd) {
+ 		if (end <= entry->start) {
+ 			where = entry->nd.prev;
+-			cached_entry = list_entry(where, struct memtype, nd);
+ 			break;
+ 		} else if (start <= entry->start) { /* end > entry->start */
+ 			err = chk_conflict(new, entry, new_type);
+@@ -410,8 +451,6 @@ int reserve_memtype(u64 start, u64 end, 
+ 				dprintk("Overlap at 0x%Lx-0x%Lx\n",
+ 					entry->start, entry->end);
+ 				where = entry->nd.prev;
+-				cached_entry = list_entry(where,
+-							struct memtype, nd);
+ 			}
+ 			break;
+ 		} else if (start < entry->end) { /* start > entry->start */
+@@ -419,8 +458,6 @@ int reserve_memtype(u64 start, u64 end, 
+ 			if (!err) {
+ 				dprintk("Overlap at 0x%Lx-0x%Lx\n",
+ 					entry->start, entry->end);
+-				cached_entry = list_entry(entry->nd.prev,
+-							struct memtype, nd);
+ 
+ 				/*
+ 				 * Move to right position in the linked
+@@ -448,13 +485,13 @@ int reserve_memtype(u64 start, u64 end, 
+ 		return err;
+ 	}
+ 
+-	cached_start = start;
+-
+ 	if (where)
+ 		list_add(&new->nd, where);
+ 	else
+ 		list_add_tail(&new->nd, &memtype_list);
+ 
++	memtype_rb_insert(&memtype_rbroot, new);
++
+ 	spin_unlock(&memtype_lock);
+ 
+ 	dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
+@@ -466,7 +503,7 @@ int reserve_memtype(u64 start, u64 end, 
+ 
+ int free_memtype(u64 start, u64 end)
+ {
+-	struct memtype *entry;
++	struct memtype *entry, *saved_entry;
+ 	int err = -EINVAL;
+ 	int is_range_ram;
+ 
+@@ -478,23 +515,58 @@ int free_memtype(u64 start, u64 end)
+ 		return 0;
+ 
+ 	is_range_ram = pat_pagerange_is_ram(start, end);
+-	if (is_range_ram == 1)
+-		return free_ram_pages_type(start, end);
+-	else if (is_range_ram < 0)
++	if (is_range_ram == 1) {
++
++		spin_lock(&memtype_lock);
++		err = free_ram_pages_type(start, end);
++		spin_unlock(&memtype_lock);
++
++		return err;
++	} else if (is_range_ram < 0) {
+ 		return -EINVAL;
++	}
+ 
+ 	spin_lock(&memtype_lock);
+-	list_for_each_entry(entry, &memtype_list, nd) {
++
++	entry = memtype_rb_search(&memtype_rbroot, start);
++	if (unlikely(entry == NULL))
++		goto unlock_ret;
++
++	/*
++	 * Saved entry points to an entry with start same or less than what
++	 * we searched for. Now go through the list in both directions to look
++	 * for the entry that matches with both start and end, with list stored
++	 * in sorted start address
++	 */
++	saved_entry = entry;
++	list_for_each_entry_from(entry, &memtype_list, nd) {
+ 		if (entry->start == start && entry->end == end) {
+-			if (cached_entry == entry || cached_start == start)
+-				cached_entry = NULL;
++			rb_erase(&entry->rb, &memtype_rbroot);
++			list_del(&entry->nd);
++			kfree(entry);
++			err = 0;
++			break;
++		} else if (entry->start > start) {
++			break;
++		}
++	}
++
++	if (!err)
++		goto unlock_ret;
+ 
++	entry = saved_entry;
++	list_for_each_entry_reverse(entry, &memtype_list, nd) {
++		if (entry->start == start && entry->end == end) {
++			rb_erase(&entry->rb, &memtype_rbroot);
+ 			list_del(&entry->nd);
+ 			kfree(entry);
+ 			err = 0;
+ 			break;
++		} else if (entry->start < start) {
++			break;
+ 		}
+ 	}
++unlock_ret:
+ 	spin_unlock(&memtype_lock);
+ 
+ 	if (err) {
+@@ -508,6 +580,103 @@ int free_memtype(u64 start, u64 end)
+ }
+ 
+ 
++#ifndef CONFIG_XEN
++/**
++ * lookup_memtype - Looksup the memory type for a physical address
++ * @paddr: physical address of which memory type needs to be looked up
++ *
++ * Only to be called when PAT is enabled
++ *
++ * Returns _PAGE_CACHE_WB, _PAGE_CACHE_WC, _PAGE_CACHE_UC_MINUS or
++ * _PAGE_CACHE_UC
++ */
++static unsigned long lookup_memtype(u64 paddr)
++{
++	int rettype = _PAGE_CACHE_WB;
++	struct memtype *entry;
++
++	if (is_ISA_range(paddr, paddr + PAGE_SIZE - 1))
++		return rettype;
++
++	if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) {
++		struct page *page;
++		spin_lock(&memtype_lock);
++		page = pfn_to_page(paddr >> PAGE_SHIFT);
++		rettype = get_page_memtype(page);
++		spin_unlock(&memtype_lock);
++		/*
++		 * -1 from get_page_memtype() implies RAM page is in its
++		 * default state and not reserved, and hence of type WB
++		 */
++		if (rettype == -1)
++			rettype = _PAGE_CACHE_WB;
++
++		return rettype;
++	}
++
++	spin_lock(&memtype_lock);
++
++	entry = memtype_rb_search(&memtype_rbroot, paddr);
++	if (entry != NULL)
++		rettype = entry->type;
++	else
++		rettype = _PAGE_CACHE_UC_MINUS;
++
++	spin_unlock(&memtype_lock);
++	return rettype;
++}
++#endif
++
++/**
++ * io_reserve_memtype - Request a memory type mapping for a region of memory
++ * @start: start (physical address) of the region
++ * @end: end (physical address) of the region
++ * @type: A pointer to memtype, with requested type. On success, requested
++ * or any other compatible type that was available for the region is returned
++ *
++ * On success, returns 0
++ * On failure, returns non-zero
++ */
++int io_reserve_memtype(resource_size_t start, resource_size_t end,
++			unsigned long *type)
++{
++	resource_size_t size = end - start;
++	unsigned long req_type = *type;
++	unsigned long new_type;
++	int ret;
++
++	WARN_ON_ONCE(iomem_map_sanity_check(start, size));
++
++	ret = reserve_memtype(start, end, req_type, &new_type);
++	if (ret)
++		goto out_err;
++
++	if (!is_new_memtype_allowed(start, size, req_type, new_type))
++		goto out_free;
++
++	if (kernel_map_sync_memtype(start, size, new_type) < 0)
++		goto out_free;
++
++	*type = new_type;
++	return 0;
++
++out_free:
++	free_memtype(start, end);
++	ret = -EBUSY;
++out_err:
++	return ret;
++}
++
++/**
++ * io_free_memtype - Release a memory type mapping for a region of memory
++ * @start: start (physical address) of the region
++ * @end: end (physical address) of the region
++ */
++void io_free_memtype(resource_size_t start, resource_size_t end)
++{
++	free_memtype(start, end);
++}
++
+ pgprot_t phys_mem_access_prot(struct file *file, unsigned long mfn,
+ 				unsigned long size, pgprot_t vma_prot)
+ {
+@@ -589,9 +758,6 @@ int phys_mem_access_prot_allowed(struct 
+  */
+ int kernel_map_sync_memtype(u64 ma, unsigned long size, unsigned long flags)
+ {
+-	if (!pat_enabled)
+-		return 0;
+-
+ 	return ioremap_check_change_attr(ma >> PAGE_SHIFT, size, flags);
+ }
+ 
+@@ -612,11 +778,29 @@ static int reserve_pfn_range(u64 paddr, 
+ 	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
+ 
+ 	/*
+-	 * reserve_pfn_range() doesn't support RAM pages. Maintain the current
+-	 * behavior with RAM pages by returning success.
++	 * reserve_pfn_range() for RAM pages. We do not refcount to keep
++	 * track of number of mappings of RAM pages. We can assert that
++	 * the type requested matches the type of first page in the range.
+ 	 */
+-	if (is_ram != 0)
++	if (is_ram) {
++		if (!pat_enabled)
++			return 0;
++
++		flags = lookup_memtype(paddr);
++		if (want_flags != flags) {
++			printk(KERN_WARNING
++			"%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
++				current->comm, current->pid,
++				cattr_name(want_flags),
++				(unsigned long long)paddr,
++				(unsigned long long)(paddr + size),
++				cattr_name(flags));
++			*vma_prot = __pgprot((pgprot_val(*vma_prot) &
++					      (~_PAGE_CACHE_MASK)) |
++					     flags);
++		}
+ 		return 0;
++	}
+ 
+ 	ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
+ 	if (ret)
+@@ -678,14 +862,6 @@ int track_pfn_vma_copy(struct vm_area_st
+ 	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 	pgprot_t pgprot;
+ 
+-	if (!pat_enabled)
+-		return 0;
+-
+-	/*
+-	 * For now, only handle remap_pfn_range() vmas where
+-	 * is_linear_pfn_mapping() == TRUE. Handling of
+-	 * vm_insert_pfn() is TBD.
+-	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/*
+ 		 * reserve the whole chunk covered by vma. We need the
+@@ -713,23 +889,24 @@ int track_pfn_vma_copy(struct vm_area_st
+ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
+ 			unsigned long pfn, unsigned long size)
+ {
++	unsigned long flags;
+ 	resource_size_t paddr;
+ 	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 
+-	if (!pat_enabled)
+-		return 0;
+-
+-	/*
+-	 * For now, only handle remap_pfn_range() vmas where
+-	 * is_linear_pfn_mapping() == TRUE. Handling of
+-	 * vm_insert_pfn() is TBD.
+-	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/* reserve the whole chunk starting from vm_pgoff */
+ 		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+ 		return reserve_pfn_range(paddr, vma_size, prot, 0);
+ 	}
+ 
++	if (!pat_enabled)
++		return 0;
++
++	/* for vm_insert_pfn and friends, we set prot based on lookup */
++	flags = lookup_memtype(pfn << PAGE_SHIFT);
++	*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
++			 flags);
++
+ 	return 0;
+ }
+ 
+@@ -744,14 +921,6 @@ void untrack_pfn_vma(struct vm_area_stru
+ 	resource_size_t paddr;
+ 	unsigned long vma_size = vma->vm_end - vma->vm_start;
+ 
+-	if (!pat_enabled)
+-		return;
+-
+-	/*
+-	 * For now, only handle remap_pfn_range() vmas where
+-	 * is_linear_pfn_mapping() == TRUE. Handling of
+-	 * vm_insert_pfn() is TBD.
+-	 */
+ 	if (is_linear_pfn_mapping(vma)) {
+ 		/* free the whole chunk starting from vm_pgoff */
+ 		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+@@ -828,7 +997,7 @@ static int memtype_seq_show(struct seq_f
+ 	return 0;
+ }
+ 
+-static struct seq_operations memtype_seq_ops = {
++static const struct seq_operations memtype_seq_ops = {
+ 	.start = memtype_seq_start,
+ 	.next  = memtype_seq_next,
+ 	.stop  = memtype_seq_stop,
+--- head-2010-01-18.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:23.000000000 +0100
+@@ -692,8 +692,7 @@ int ptep_set_access_flags(struct vm_area
+ 		if (likely(vma->vm_mm == current->mm)) {
+ 			if (HYPERVISOR_update_va_mapping(address,
+ 				entry,
+-				uvm_multi(vma->vm_mm->cpu_vm_mask) |
+-					UVMF_INVLPG))
++				uvm_multi(mm_cpumask(vma->vm_mm))|UVMF_INVLPG))
+ 				BUG();
+ 		} else {
+ 			xen_l1_entry_update(ptep, entry);
+--- head-2010-01-18.orig/arch/x86/mm/physaddr.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/physaddr.c	2009-11-06 10:52:23.000000000 +0100
+@@ -8,6 +8,10 @@
+ 
+ #ifdef CONFIG_X86_64
+ 
++#ifdef CONFIG_XEN
++#define phys_base 0
++#endif
++
+ unsigned long __phys_addr(unsigned long x)
+ {
+ 	if (x >= __START_KERNEL_map) {
+--- head-2010-01-18.orig/drivers/acpi/processor_core.c	2010-01-04 12:41:22.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_core.c	2010-01-04 12:42:24.000000000 +0100
+@@ -880,7 +880,7 @@ static int __cpuinit acpi_processor_add(
+ 
+ 	result = processor_extcntl_prepare(pr);
+ 	if (result)
+-		goto end;
++		goto err_power_exit;
+ 
+ 	pr->cdev = thermal_cooling_device_register("Processor", device,
+ 						&processor_cooling_ops);
+--- head-2010-01-18.orig/drivers/char/agp/agp.h	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/agp.h	2009-11-06 10:52:23.000000000 +0100
+@@ -31,6 +31,10 @@
+ 
+ #include <asm/agp.h>	/* for flush_agp_cache() */
+ 
++#ifndef virt_to_gart
++#define virt_to_gart virt_to_phys
++#endif
++
+ #define PFX "agpgart: "
+ 
+ //#define AGP_DEBUG 1
+--- head-2010-01-18.orig/drivers/char/agp/amd-k7-agp.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/amd-k7-agp.c	2009-11-06 10:52:23.000000000 +0100
+@@ -44,7 +44,7 @@ static int amd_create_page_map(struct am
+ #ifndef CONFIG_X86
+ 	SetPageReserved(virt_to_page(page_map->real));
+ 	global_cache_flush();
+-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
++	page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
+ 					    PAGE_SIZE);
+ 	if (page_map->remapped == NULL) {
+ 		ClearPageReserved(virt_to_page(page_map->real));
+@@ -160,7 +160,7 @@ static int amd_create_gatt_table(struct 
+ 
+ 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
+ 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
+-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
++	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ 
+ 	/* Get the address for the gart region.
+ 	 * This is a bus address even on the alpha, b/c its
+@@ -173,7 +173,7 @@ static int amd_create_gatt_table(struct 
+ 
+ 	/* Calculate the agp offset */
+ 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
+-		writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
++		writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
+ 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
+ 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
+ 	}
+--- head-2010-01-18.orig/drivers/char/agp/amd64-agp.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/amd64-agp.c	2009-11-06 10:52:23.000000000 +0100
+@@ -178,7 +178,7 @@ static const struct aper_size_info_32 am
+ 
+ static int amd_8151_configure(void)
+ {
+-	unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
++	unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
+ 	int i;
+ 
+ 	/* Configure AGP regs in each x86-64 host bridge. */
+@@ -558,7 +558,7 @@ static void __devexit agp_amd64_remove(s
+ {
+ 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ 
+-	release_mem_region(virt_to_phys(bridge->gatt_table_real),
++	release_mem_region(virt_to_gart(bridge->gatt_table_real),
+ 			   amd64_aperture_sizes[bridge->aperture_size_idx].size);
+ 	agp_remove_bridge(bridge);
+ 	agp_put_bridge(bridge);
+--- head-2010-01-18.orig/drivers/char/agp/ati-agp.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/ati-agp.c	2009-11-06 10:52:23.000000000 +0100
+@@ -360,7 +360,7 @@ static int ati_create_gatt_table(struct 
+ 
+ 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
+ 	agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
+-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
++	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ 
+ 	/* Write out the size register */
+ 	current_size = A_SIZE_LVL2(agp_bridge->current_size);
+@@ -390,7 +390,7 @@ static int ati_create_gatt_table(struct 
+ 
+ 	/* Calculate the agp offset */
+ 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
+-		writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,
++		writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
+ 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
+ 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
+ 	}
+--- head-2010-01-18.orig/drivers/char/agp/efficeon-agp.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/efficeon-agp.c	2009-11-06 10:52:23.000000000 +0100
+@@ -226,7 +226,7 @@ static int efficeon_create_gatt_table(st
+ 
+ 		efficeon_private.l1_table[index] = page;
+ 
+-		value = virt_to_phys((unsigned long *)page) | pati | present | index;
++		value = virt_to_gart((unsigned long *)page) | pati | present | index;
+ 
+ 		pci_write_config_dword(agp_bridge->dev,
+ 			EFFICEON_ATTPAGE, value);
+--- head-2010-01-18.orig/drivers/char/agp/generic.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/generic.c	2009-11-06 10:52:23.000000000 +0100
+@@ -988,7 +988,7 @@ int agp_generic_create_gatt_table(struct
+ 	set_memory_uc((unsigned long)table, 1 << page_order);
+ 	bridge->gatt_table = (void *)table;
+ #else
+-	bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
++	bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
+ 					(PAGE_SIZE * (1 << page_order)));
+ 	bridge->driver->cache_flush();
+ #endif
+@@ -1001,7 +1001,7 @@ int agp_generic_create_gatt_table(struct
+ 
+ 		return -ENOMEM;
+ 	}
+-	bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
++	bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
+ 
+ 	/* AK: bogus, should encode addresses > 4GB */
+ 	for (i = 0; i < num_entries; i++) {
+--- head-2010-01-18.orig/drivers/char/agp/sworks-agp.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/char/agp/sworks-agp.c	2009-11-06 10:52:23.000000000 +0100
+@@ -155,7 +155,7 @@ static int serverworks_create_gatt_table
+ 	/* Create a fake scratch directory */
+ 	for (i = 0; i < 1024; i++) {
+ 		writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
+-		writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
++		writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+ 	}
+ 
+ 	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
+@@ -167,7 +167,7 @@ static int serverworks_create_gatt_table
+ 
+ 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
+ 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
+-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
++	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ 
+ 	/* Get the address for the gart region.
+ 	 * This is a bus address even on the alpha, b/c its
+@@ -179,7 +179,7 @@ static int serverworks_create_gatt_table
+ 
+ 	/* Calculate the agp offset */
+ 	for (i = 0; i < value->num_entries / 1024; i++)
+-		writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
++		writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/drivers/net/Kconfig	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/net/Kconfig	2009-11-06 11:36:52.000000000 +0100
+@@ -3235,7 +3235,7 @@ config VIRTIO_NET
+ 
+ config VMXNET3
+        tristate "VMware VMXNET3 ethernet driver"
+-       depends on PCI && X86 && INET
++       depends on PCI && X86 && !XEN && INET
+        help
+          This driver supports VMware's vmxnet3 virtual ethernet NIC.
+          To compile this driver as a module, choose M here: the
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:30:30.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:32:09.000000000 +0100
+@@ -16,12 +16,11 @@
+ #include <linux/proc_fs.h>
+ #include <linux/msi.h>
+ #include <linux/smp.h>
++#include <linux/errno.h>
++#include <linux/io.h>
+ 
+ #include <xen/evtchn.h>
+ 
+-#include <asm/errno.h>
+-#include <asm/io.h>
+-
+ #include "pci.h"
+ #include "msi.h"
+ 
+@@ -479,7 +478,7 @@ static int msix_capability_init(struct p
+  * to determine if MSI/-X are supported for the device. If MSI/-X is
+  * supported return 0, else return an error code.
+  **/
+-static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
++static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)
+ {
+ 	struct pci_bus *bus;
+ 	int ret;
+@@ -496,8 +495,9 @@ static int pci_msi_check_device(struct p
+ 	if (nvec < 1)
+ 		return -ERANGE;
+ 
+-	/* Any bridge which does NOT route MSI transactions from it's
+-	 * secondary bus to it's primary bus must set NO_MSI flag on
++	/*
++	 * Any bridge which does NOT route MSI transactions from its
++	 * secondary bus to its primary bus must set NO_MSI flag on
+ 	 * the secondary pci_bus.
+ 	 * We expect only arch-specific PCI host bus controller driver
+ 	 * or quirks for specific PCI bridges to be setting NO_MSI.
+@@ -615,7 +615,7 @@ void pci_msi_shutdown(struct pci_dev *de
+ 	dev->msi_enabled = 0;
+ }
+ 
+-void pci_disable_msi(struct pci_dev* dev)
++void pci_disable_msi(struct pci_dev *dev)
+ {
+ 	pci_msi_shutdown(dev);
+ }
+@@ -655,14 +655,14 @@ int pci_msix_table_size(struct pci_dev *
+  **/
+ 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)
++int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
+ {
+ 	int status, nr_entries;
+ 	int i, j, temp;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+ 	if (!entries)
+- 		return -EINVAL;
++		return -EINVAL;
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+ 	if (!is_initial_xendomain()) {
+@@ -737,7 +737,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ EXPORT_SYMBOL(pci_enable_msix);
+ 
+ extern void pci_frontend_disable_msix(struct pci_dev* dev);
+-void pci_msix_shutdown(struct pci_dev* dev)
++void pci_msix_shutdown(struct pci_dev *dev)
+ {
+ 	if (!pci_msi_enable || !dev || !dev->msix_enabled)
+ 		return;
+@@ -770,7 +770,8 @@ void pci_msix_shutdown(struct pci_dev* d
+ 	pci_intx_for_msi(dev, 1);
+ 	dev->msix_enabled = 0;
+ }
+-void pci_disable_msix(struct pci_dev* dev)
++
++void pci_disable_msix(struct pci_dev *dev)
+ {
+ 	pci_msix_shutdown(dev);
+ }
+@@ -785,14 +786,14 @@ EXPORT_SYMBOL(pci_disable_msix);
+  * 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)
++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;
++		return;
+ 
+ 	msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+--- head-2010-01-18.orig/drivers/pci/probe.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/pci/probe.c	2009-11-06 10:52:23.000000000 +0100
+@@ -1087,7 +1087,11 @@ int pci_scan_slot(struct pci_bus *bus, i
+ 	if (dev && !dev->is_added)	/* new device? */
+ 		nr++;
+ 
++#ifndef pcibios_scan_all_fns
+ 	if (dev && dev->multifunction) {
++#else
++	if (dev ? dev->multifunction : pcibios_scan_all_fns(bus, devfn)) {
++#endif
+ 		for (fn = 1; fn < 8; fn++) {
+ 			dev = pci_scan_single_device(bus, devfn + fn);
+ 			if (dev) {
+--- head-2010-01-18.orig/drivers/sfi/sfi_core.c	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/sfi/sfi_core.c	2009-12-16 11:53:57.000000000 +0100
+@@ -387,6 +387,11 @@ void __init sfi_init(void)
+ 	if (!acpi_disabled)
+ 		disable_sfi();
+ 
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		disable_sfi();
++#endif
++
+ 	if (sfi_disabled)
+ 		return;
+ 
+--- head-2010-01-18.orig/drivers/staging/hv/Kconfig	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/staging/hv/Kconfig	2009-11-06 10:52:23.000000000 +0100
+@@ -1,6 +1,6 @@
+ config HYPERV
+ 	tristate "Microsoft Hyper-V client drivers"
+-	depends on X86 && m
++	depends on X86 && !XEN && m
+ 	default n
+ 	help
+ 	  Select this option to run Linux as a Hyper-V client operating
+--- head-2010-01-18.orig/drivers/xen/Makefile	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/Makefile	2009-11-06 10:52:23.000000000 +0100
+@@ -10,6 +10,11 @@ obj-$(CONFIG_XEN)		+= evtchn/
+ obj-y				+= xenbus/
+ obj-$(CONFIG_XEN)		+= char/
+ 
++nostackp := $(call cc-option, -fno-stack-protector)
++ifeq ($(CONFIG_PARAVIRT_XEN),y)
++CFLAGS_features.o			:= $(nostackp)
++endif
++
+ obj-$(CONFIG_XEN)		+= features.o util.o
+ obj-$(CONFIG_HOTPLUG_CPU)	+= $(xen-hotplug-y)
+ obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2010-01-04 12:42:42.000000000 +0100
+@@ -77,6 +77,11 @@ static DEFINE_MUTEX(balloon_mutex);
+  */
+ DEFINE_SPINLOCK(balloon_lock);
+ 
++#ifndef MODULE
++#include <linux/pagevec.h>
++static struct pagevec free_pagevec;
++#endif
++
+ struct balloon_stats balloon_stats;
+ 
+ /* We increase/decrease in batches which fit in a page */
+@@ -188,14 +193,27 @@ static struct page *balloon_next_page(st
+ static inline void balloon_free_page(struct page *page)
+ {
+ #ifndef MODULE
+-	if (put_page_testzero(page))
+-		free_cold_page(page);
++	if (put_page_testzero(page) && !pagevec_add(&free_pagevec, page)) {
++		__pagevec_free(&free_pagevec);
++		pagevec_reinit(&free_pagevec);
++	}
+ #else
+-	/* free_cold_page() is not being exported. */
++	/* pagevec interface is not being exported. */
+ 	__free_page(page);
+ #endif
+ }
+ 
++static inline void balloon_free_and_unlock(unsigned long flags)
++{
++#ifndef MODULE
++	if (pagevec_count(&free_pagevec)) {
++		__pagevec_free(&free_pagevec);
++		pagevec_reinit(&free_pagevec);
++	}
++#endif
++	balloon_unlock(flags);
++}
++
+ static void balloon_alarm(unsigned long unused)
+ {
+ 	schedule_work(&balloon_worker);
+@@ -308,7 +326,7 @@ static int increase_reservation(unsigned
+ 	totalram_pages = bs.current_pages;
+ 
+  out:
+-	balloon_unlock(flags);
++	balloon_free_and_unlock(flags);
+ 
+ #ifndef MODULE
+ 	setup_per_zone_wmarks();
+@@ -534,6 +552,7 @@ static int __init balloon_init(void)
+ 	IPRINTK("Initialising balloon driver.\n");
+ 
+ #ifdef CONFIG_XEN
++	pagevec_init(&free_pagevec, true);
+ 	bs.current_pages = min(xen_start_info->nr_pages, max_pfn);
+ 	totalram_pages   = bs.current_pages;
+ #else 
+@@ -676,8 +695,8 @@ struct page **alloc_empty_pages_and_page
+ 		}
+ 
+ 		if (ret != 0) {
+-			balloon_unlock(flags);
+ 			balloon_free_page(page);
++			balloon_free_and_unlock(flags);
+ 			goto err;
+ 		}
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:54:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 16:54:56.000000000 +0100
+@@ -105,7 +105,7 @@ static struct xlbd_major_info *major_inf
+ 
+ #define XLBD_MAJOR_VBD_ALT(idx) ((idx) ^ XLBD_MAJOR_VBD_START ^ (XLBD_MAJOR_VBD_START + 1))
+ 
+-static struct block_device_operations xlvbd_block_fops =
++static const struct block_device_operations xlvbd_block_fops =
+ {
+ 	.owner = THIS_MODULE,
+ 	.open = blkif_open,
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2010-01-04 12:41:52.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2009-11-06 10:52:23.000000000 +0100
+@@ -141,7 +141,7 @@ blktap_device_ioctl(struct block_device 
+ 	return 0;
+ }
+ 
+-static struct block_device_operations blktap_device_file_operations = {
++static const struct block_device_operations blktap_device_file_operations = {
+ 	.owner     = THIS_MODULE,
+ 	.open      = blktap_device_open,
+ 	.release   = blktap_device_release,
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 11:04:38.000000000 +0100
+@@ -138,13 +138,13 @@ static inline unsigned int type_from_irq
+ }
+ 
+ /* IRQ <-> VIRQ mapping. */
+-DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
++DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
+ 
+ /* IRQ <-> IPI mapping. */
+ #ifndef NR_IPIS
+ #define NR_IPIS 1
+ #endif
+-DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1};
++DEFINE_PER_CPU(int[NR_IPIS], ipi_to_irq) = {[0 ... NR_IPIS-1] = -1};
+ 
+ #ifdef CONFIG_SMP
+ 
+--- head-2010-01-18.orig/drivers/xen/netback/interface.c	2010-01-04 12:40:53.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/interface.c	2010-01-04 12:42:38.000000000 +0100
+@@ -159,7 +159,7 @@ static void netbk_get_strings(struct net
+ 	}
+ }
+ 
+-static struct ethtool_ops network_ethtool_ops =
++static const struct ethtool_ops network_ethtool_ops =
+ {
+ 	.get_drvinfo = netbk_get_drvinfo,
+ 
+--- head-2010-01-18.orig/drivers/xen/netback/loopback.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/loopback.c	2009-11-06 10:52:23.000000000 +0100
+@@ -134,7 +134,7 @@ static int loopback_start_xmit(struct sk
+ 	if (!skb_remove_foreign_references(skb)) {
+ 		np->stats.tx_dropped++;
+ 		dev_kfree_skb(skb);
+-		return 0;
++		return NETDEV_TX_OK;
+ 	}
+ 
+ 	dst_release(skb_dst(skb));
+@@ -173,7 +173,7 @@ static int loopback_start_xmit(struct sk
+ 
+ 	netif_rx(skb);
+ 
+-	return 0;
++	return NETDEV_TX_OK;
+ }
+ 
+ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
+@@ -182,7 +182,7 @@ static struct net_device_stats *loopback
+ 	return &np->stats;
+ }
+ 
+-static struct ethtool_ops network_ethtool_ops =
++static const struct ethtool_ops network_ethtool_ops =
+ {
+ 	.get_tx_csum = ethtool_op_get_tx_csum,
+ 	.set_tx_csum = ethtool_op_set_tx_csum,
+--- head-2010-01-18.orig/drivers/xen/netback/netback.c	2010-01-04 12:40:57.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/netback.c	2009-11-06 10:52:23.000000000 +0100
+@@ -340,12 +340,12 @@ int netif_be_start_xmit(struct sk_buff *
+ 	skb_queue_tail(&rx_queue, skb);
+ 	tasklet_schedule(&net_rx_tasklet);
+ 
+-	return 0;
++	return NETDEV_TX_OK;
+ 
+  drop:
+ 	netif->stats.tx_dropped++;
+ 	dev_kfree_skb(skb);
+-	return 0;
++	return NETDEV_TX_OK;
+ }
+ 
+ #if 0
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:52:23.000000000 +0100
+@@ -953,7 +953,7 @@ static int network_start_xmit(struct sk_
+  	if (np->accel_vif_state.hooks && 
+  	    np->accel_vif_state.hooks->start_xmit(skb, dev)) { 
+  		/* Fast path has sent this packet */ 
+- 		return 0; 
++ 		return NETDEV_TX_OK;
+  	} 
+ 
+ 	frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
+@@ -1042,12 +1042,12 @@ static int network_start_xmit(struct sk_
+ 
+ 	spin_unlock_irq(&np->tx_lock);
+ 
+-	return 0;
++	return NETDEV_TX_OK;
+ 
+  drop:
+ 	np->stats.tx_dropped++;
+ 	dev_kfree_skb(skb);
+-	return 0;
++	return NETDEV_TX_OK;
+ }
+ 
+ static irqreturn_t netif_int(int irq, void *dev_id)
+@@ -1872,7 +1872,7 @@ static void netif_uninit(struct net_devi
+ 	gnttab_free_grant_references(np->gref_rx_head);
+ }
+ 
+-static struct ethtool_ops network_ethtool_ops =
++static const struct ethtool_ops network_ethtool_ops =
+ {
+ 	.get_tx_csum = ethtool_op_get_tx_csum,
+ 	.set_tx_csum = ethtool_op_set_tx_csum,
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_fwd.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_fwd.c	2009-11-06 10:52:23.000000000 +0100
+@@ -181,11 +181,10 @@ int netback_accel_fwd_add(const __u8 *ma
+ 	unsigned long flags;
+ 	cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
+ 	struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
+-	DECLARE_MAC_BUF(buf);
+ 
+ 	BUG_ON(fwd_priv == NULL);
+ 
+-	DPRINTK("Adding mac %s\n", print_mac(buf, mac));
++	DPRINTK("Adding mac %pM\n", mac);
+        
+ 	spin_lock_irqsave(&fwd_set->fwd_lock, flags);
+ 	
+@@ -200,8 +199,7 @@ int netback_accel_fwd_add(const __u8 *ma
+ 	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 %s already accelerated.\n",
+-			print_mac(buf, mac));
++		EPRINTK("MAC address %pM already accelerated.\n", mac);
+ 		return -EEXIST;
+ 	}
+ 
+@@ -236,9 +234,8 @@ void netback_accel_fwd_remove(const __u8
+ 	unsigned long flags;
+ 	cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
+ 	struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
+-	DECLARE_MAC_BUF(buf);
+ 
+-	DPRINTK("Removing mac %s\n", print_mac(buf, mac));
++	DPRINTK("Removing mac %pM\n", mac);
+ 
+ 	BUG_ON(fwd_priv == NULL);
+ 
+@@ -396,16 +393,14 @@ void netback_accel_tx_packet(struct sk_b
+ 
+ 	if (is_broadcast_ether_addr(skb_mac_header(skb))
+ 	    && packet_is_arp_reply(skb)) {
+-		DECLARE_MAC_BUF(buf);
+-
+ 		/*
+ 		 * update our fast path forwarding to reflect this
+ 		 * gratuitous ARP
+ 		 */ 
+ 		mac = skb_mac_header(skb)+ETH_ALEN;
+ 
+-		DPRINTK("%s: found gratuitous ARP for %s\n",
+-			__FUNCTION__, print_mac(buf, mac));
++		DPRINTK("%s: found gratuitous ARP for %pM\n",
++			__FUNCTION__, mac);
+ 
+ 		spin_lock_irqsave(&fwd_set->fwd_lock, flags);
+ 		/*
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_msg.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_msg.c	2009-11-06 10:52:23.000000000 +0100
+@@ -57,11 +57,10 @@ static void netback_accel_msg_tx_localma
+ {
+ 	unsigned long lock_state;
+ 	struct net_accel_msg *msg;
+-	DECLARE_MAC_BUF(buf);
+ 
+ 	BUG_ON(bend == NULL || mac == NULL);
+ 
+-	VPRINTK("Sending local mac message: %s\n", print_mac(buf, mac));
++	VPRINTK("Sending local mac message: %pM\n", mac);
+ 	
+ 	msg = net_accel_msg_start_send(bend->shared_page, &bend->to_domU,
+ 				       &lock_state);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:52:23.000000000 +0100
+@@ -327,10 +327,8 @@ static int vnic_process_localmac_msg(net
+ 	cuckoo_hash_mac_key key;
+ 
+ 	if (msg->u.localmac.flags & NET_ACCEL_MSG_ADD) {
+-		DECLARE_MAC_BUF(buf);
+-
+-		DPRINTK("MAC has moved, could be local: %s\n",
+-			print_mac(buf, msg->u.localmac.mac));
++		DPRINTK("MAC has moved, could be local: %pM\n",
++			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 */
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:19:18.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:55:03.000000000 +0100
+@@ -643,10 +643,7 @@ netfront_accel_vi_tx_post(netfront_accel
+ 					  (cuckoo_hash_key *)(&key), &value);
+ 
+ 	if (!try_fastpath) {
+-		DECLARE_MAC_BUF(buf);
+-
+-		VPRINTK("try fast path false for mac: %s\n",
+-			print_mac(buf, skb->data));
++		VPRINTK("try fast path false for mac: %pM\n", skb->data);
+ 		
+ 		return NETFRONT_ACCEL_STATUS_CANT;
+ 	}
+@@ -772,10 +769,9 @@ static void  netfront_accel_vi_rx_comple
+ 	if (compare_ether_addr(skb->data, vnic->mac)) {
+ 		struct iphdr *ip = (struct iphdr *)(skb->data + ETH_HLEN);
+ 		u16 port;
+-		DECLARE_MAC_BUF(buf);
+ 
+-		DPRINTK("%s: saw wrong MAC address %s\n",
+-			__FUNCTION__, print_mac(buf, skb->data));
++		DPRINTK("%s: saw wrong MAC address %pM\n",
++			__FUNCTION__, skb->data);
+ 
+ 		if (ip->protocol == IPPROTO_TCP) {
+ 			struct tcphdr *tcp = (struct tcphdr *)
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_dev.c	2009-05-29 10:25:53.000000000 +0200
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_dev.c	2009-11-06 10:52:23.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <linux/errno.h>
+ #include <linux/uio.h>
+ #include <linux/notifier.h>
++#include <linux/sched.h>
+ #include <linux/wait.h>
+ #include <linux/fs.h>
+ #include <linux/poll.h>
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:30:36.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:52:23.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include <linux/ctype.h>
+ #include <linux/fcntl.h>
+ #include <linux/mm.h>
++#include <linux/sched.h>
+ #include <linux/proc_fs.h>
+ #include <linux/notifier.h>
+ #include <linux/mutex.h>
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-12-14 17:30:30.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-12-14 17:36:28.000000000 +0100
+@@ -111,79 +111,11 @@ setup_io_tlb_npages(char *str)
+ __setup("swiotlb=", setup_io_tlb_npages);
+ /* make io_tlb_overflow tunable too? */
+ 
+-void *__init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+-{
+-	void *start = alloc_bootmem_pages(size);
+-	unsigned int i;
+-	int rc;
+-
+-	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
+-	for (i = 0; i < nslabs; i += IO_TLB_SEGSIZE) {
+-		do {
+-			rc = xen_create_contiguous_region(
+-				(unsigned long)start + (i << IO_TLB_SHIFT),
+-				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+-				dma_bits);
+-		} while (rc && dma_bits++ < max_dma_bits);
+-		if (rc) {
+-			if (i == 0)
+-				panic("No suitable physical memory available for SWIOTLB buffer!\n"
+-				      "Use dom0_mem Xen boot parameter to reserve\n"
+-				      "some DMA memory (e.g., dom0_mem=-128M).\n");
+-			io_tlb_nslabs = i;
+-			i <<= IO_TLB_SHIFT;
+-			free_bootmem(__pa(start + i), size - i);
+-			size = i;
+-			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
+-				unsigned int bits = fls64(virt_to_bus(start + i - 1));
+-
+-				if (bits > dma_bits)
+-					dma_bits = bits;
+-			}
+-			break;
+-		}
+-	}
+-
+-	return start;
+-}
+-
+-#ifndef CONFIG_XEN
+-void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs)
+-{
+-	return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
+-}
+-#endif
+-
+-dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
+-{
+-	return phys_to_machine(paddr);
+-}
+-
+-phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
+-{
+-	return machine_to_phys(baddr);
+-}
+-
++/* Note that this doesn't work with highmem page */
+ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
+ 				      volatile void *address)
+ {
+-	return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
+-}
+-
+-void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
+-{
+-	return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
+-}
+-
+-int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
+-					       dma_addr_t addr, size_t size)
+-{
+-	return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+-}
+-
+-int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
+-{
+-	return 0;
++	return phys_to_dma(hwdev, virt_to_phys(address));
+ }
+ 
+ static void swiotlb_print_info(unsigned long bytes)
+@@ -216,10 +148,35 @@ swiotlb_init_with_default_size(size_t de
+ 	/*
+ 	 * Get IO TLB memory from the low pages
+ 	 */
+-	io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
++	io_tlb_start = alloc_bootmem_pages(bytes);
+ 	if (!io_tlb_start)
+ 		panic("Cannot allocate SWIOTLB buffer!\n");
+-	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
++	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
++	for (i = 0; i < io_tlb_nslabs; i += IO_TLB_SEGSIZE) {
++		do {
++			rc = xen_create_contiguous_region(
++				(unsigned long)io_tlb_start + (i << IO_TLB_SHIFT),
++				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
++				dma_bits);
++		} while (rc && dma_bits++ < max_dma_bits);
++		if (rc) {
++			if (i == 0)
++				panic("No suitable physical memory available for SWIOTLB buffer!\n"
++				      "Use dom0_mem Xen boot parameter to reserve\n"
++				      "some DMA memory (e.g., dom0_mem=-128M).\n");
++			io_tlb_nslabs = i;
++			i <<= IO_TLB_SHIFT;
++			free_bootmem(__pa(io_tlb_start + i), bytes - i);
++			bytes = i;
++			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
++				unsigned int bits = fls64(virt_to_bus(io_tlb_start + i - 1));
++
++				if (bits > dma_bits)
++					dma_bits = bits;
++			}
++			break;
++		}
++	}
+ 	io_tlb_end = io_tlb_start + bytes;
+ 
+ 	/*
+@@ -283,13 +240,10 @@ static inline int range_needs_mapping(ph
+ static int is_swiotlb_buffer(dma_addr_t addr)
+ {
+ 	unsigned long pfn = mfn_to_local_pfn(PFN_DOWN(addr));
+-	char *va = pfn_valid(pfn) ? __va(pfn << PAGE_SHIFT) : NULL;
++	phys_addr_t paddr = (phys_addr_t)pfn << PAGE_SHIFT;
+ 
+-#ifdef CONFIG_HIGHMEM
+-	if (pfn >= highstart_pfn)
+-		return 0;
+-#endif
+-	return va >= io_tlb_start && va < io_tlb_end;
++	return paddr >= virt_to_phys(io_tlb_start) &&
++		paddr < virt_to_phys(io_tlb_end);
+ }
+ 
+ /*
+@@ -514,12 +468,15 @@ swiotlb_full(struct device *dev, size_t 
+ 	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %zu bytes at "
+ 	       "device %s\n", size, dev ? dev_name(dev) : "?");
+ 
+-	if (size > io_tlb_overflow && do_panic) {
+-		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+-			panic("PCI-DMA: Memory would be corrupted\n");
+-		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+-			panic("PCI-DMA: Random memory would be DMAed\n");
+-	}
++	if (size <= io_tlb_overflow || !do_panic)
++		return;
++
++	if (dir == DMA_BIDIRECTIONAL)
++		panic("DMA: Random memory could be DMA accessed\n");
++	if (dir == DMA_FROM_DEVICE)
++		panic("DMA: Random memory could be DMA written\n");
++	if (dir == DMA_TO_DEVICE)
++		panic("DMA: Random memory could be DMA read\n");
+ }
+ 
+ /*
+@@ -545,7 +502,7 @@ dma_addr_t swiotlb_map_page(struct devic
+ 	 * we can safely return the device addr and not worry about bounce
+ 	 * buffering it.
+ 	 */
+-	if (!address_needs_mapping(dev, dev_addr, size) &&
++	if (dma_capable(dev, dev_addr, size) &&
+ 	    !range_needs_mapping(phys, size))
+ 		return dev_addr;
+ 
+@@ -575,12 +532,12 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
+ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
+ 			 size_t size, int dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
++	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	if (is_swiotlb_buffer(dev_addr)) {
+-		do_unmap_single(hwdev, dma_addr, size, dir);
++		do_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
+ 		return;
+ 	}
+ 
+@@ -609,12 +566,12 @@ void
+ swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 			    size_t size, enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
++	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	if (is_swiotlb_buffer(dev_addr))
+-		sync_single(hwdev, dma_addr, size, dir);
++		sync_single(hwdev, phys_to_virt(paddr), size, dir);
+ }
+ EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
+ 
+@@ -622,12 +579,12 @@ void
+ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 			       size_t size, enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
++	phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	if (is_swiotlb_buffer(dev_addr))
+-		sync_single(hwdev, dma_addr, size, dir);
++		sync_single(hwdev, phys_to_virt(paddr), size, dir);
+ }
+ EXPORT_SYMBOL(swiotlb_sync_single_for_device);
+ 
+@@ -680,8 +637,8 @@ swiotlb_map_sg_attrs(struct device *hwde
+ 		phys_addr_t paddr = page_to_pseudophys(sg_page(sg))
+ 				   + sg->offset;
+ 
+-		if (range_needs_mapping(paddr, sg->length)
+-		    || address_needs_mapping(hwdev, dev_addr, sg->length)) {
++		if (range_needs_mapping(paddr, sg->length) ||
++		    !dma_capable(hwdev, dev_addr, sg->length)) {
+ 			void *map;
+ 
+ 			gnttab_dma_unmap_page(dev_addr);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-machphys-prediction
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-machphys-prediction
@@ -0,0 +1,204 @@
+From: jbeulich@novell.com
+Subject: properly predict phys<->mach translations
+Patch-mainline: obsolete
+
+--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/maddr_32.h	2009-07-28 12:14:16.000000000 +0200
++++ head-2009-07-28/arch/x86/include/mach-xen/asm/maddr_32.h	2009-07-29 10:56:35.000000000 +0200
+@@ -30,17 +30,19 @@ extern unsigned int   machine_to_phys_or
+ 
+ static inline unsigned long pfn_to_mfn(unsigned long pfn)
+ {
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return pfn;
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
+ 	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
+ }
+ 
+ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+ {
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return 1;
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
+ 	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+ }
+ 
+@@ -48,7 +50,7 @@ static inline unsigned long mfn_to_pfn(u
+ {
+ 	unsigned long pfn;
+ 
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return mfn;
+ 
+ 	if (unlikely((mfn >> machine_to_phys_order) != 0))
+@@ -95,17 +97,18 @@ static inline unsigned long mfn_to_pfn(u
+ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+ {
+ 	unsigned long pfn = mfn_to_pfn(mfn);
+-	if ((pfn < max_mapnr)
+-	    && !xen_feature(XENFEAT_auto_translated_physmap)
+-	    && (phys_to_machine_mapping[pfn] != mfn))
++	if (likely(pfn < max_mapnr)
++	    && likely(!xen_feature(XENFEAT_auto_translated_physmap))
++	    && unlikely(phys_to_machine_mapping[pfn] != mfn))
+ 		return max_mapnr; /* force !pfn_valid() */
+ 	return pfn;
+ }
+ 
+ static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+ {
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
+-	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+ 		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ 		return;
+ 	}
+--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/maddr_64.h	2009-07-28 12:14:16.000000000 +0200
++++ head-2009-07-28/arch/x86/include/mach-xen/asm/maddr_64.h	2009-07-29 10:56:35.000000000 +0200
+@@ -25,17 +25,19 @@ extern unsigned int   machine_to_phys_or
+ 
+ static inline unsigned long pfn_to_mfn(unsigned long pfn)
+ {
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return pfn;
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
+ 	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
+ }
+ 
+ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+ {
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return 1;
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
+ 	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+ }
+ 
+@@ -43,7 +45,7 @@ static inline unsigned long mfn_to_pfn(u
+ {
+ 	unsigned long pfn;
+ 
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+ 		return mfn;
+ 
+ 	if (unlikely((mfn >> machine_to_phys_order) != 0))
+@@ -90,17 +92,18 @@ static inline unsigned long mfn_to_pfn(u
+ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+ {
+ 	unsigned long pfn = mfn_to_pfn(mfn);
+-	if ((pfn < max_mapnr)
+-	    && !xen_feature(XENFEAT_auto_translated_physmap)
+-	    && (phys_to_machine_mapping[pfn] != mfn))
++	if (likely(pfn < max_mapnr)
++	    && likely(!xen_feature(XENFEAT_auto_translated_physmap))
++	    && unlikely(phys_to_machine_mapping[pfn] != mfn))
+ 		return max_mapnr; /* force !pfn_valid() */
+ 	return pfn;
+ }
+ 
+ static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+ {
+-	BUG_ON(max_mapnr && pfn >= max_mapnr);
+-	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++	if (likely(max_mapnr))
++		BUG_ON(pfn >= max_mapnr);
++	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+ 		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ 		return;
+ 	}
+--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-07-28 13:14:11.000000000 +0200
++++ head-2009-07-28/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-07-29 10:56:35.000000000 +0200
+@@ -207,7 +207,7 @@ typedef struct { pgdval_t pgd; } pgd_t;
+ #define __pgd_ma(x) ((pgd_t) { (x) } )
+ static inline pgd_t xen_make_pgd(pgdval_t val)
+ {
+-	if (val & _PAGE_PRESENT)
++	if (likely(val & _PAGE_PRESENT))
+ 		val = pte_phys_to_machine(val);
+ 	return (pgd_t) { val };
+ }
+@@ -217,10 +217,10 @@ static inline pgdval_t xen_pgd_val(pgd_t
+ {
+ 	pgdval_t ret = __pgd_val(pgd);
+ #if PAGETABLE_LEVELS == 2 && CONFIG_XEN_COMPAT <= 0x030002
+-	if (ret)
++	if (likely(ret))
+ 		ret = machine_to_phys(ret) | _PAGE_PRESENT;
+ #else
+-	if (ret & _PAGE_PRESENT)
++	if (likely(ret & _PAGE_PRESENT))
+ 		ret = pte_machine_to_phys(ret);
+ #endif
+ 	return ret;
+@@ -237,7 +237,7 @@ typedef struct { pudval_t pud; } pud_t;
+ #define __pud_ma(x) ((pud_t) { (x) } )
+ static inline pud_t xen_make_pud(pudval_t val)
+ {
+-	if (val & _PAGE_PRESENT)
++	if (likely(val & _PAGE_PRESENT))
+ 		val = pte_phys_to_machine(val);
+ 	return (pud_t) { val };
+ }
+@@ -246,7 +246,7 @@ static inline pud_t xen_make_pud(pudval_
+ static inline pudval_t xen_pud_val(pud_t pud)
+ {
+ 	pudval_t ret = __pud_val(pud);
+-	if (ret & _PAGE_PRESENT)
++	if (likely(ret & _PAGE_PRESENT))
+ 		ret = pte_machine_to_phys(ret);
+ 	return ret;
+ }
+@@ -266,7 +266,7 @@ typedef struct { pmdval_t pmd; } pmd_t;
+ #define __pmd_ma(x)	((pmd_t) { (x) } )
+ static inline pmd_t xen_make_pmd(pmdval_t val)
+ {
+-	if (val & _PAGE_PRESENT)
++	if (likely(val & _PAGE_PRESENT))
+ 		val = pte_phys_to_machine(val);
+ 	return (pmd_t) { val };
+ }
+@@ -276,10 +276,10 @@ static inline pmdval_t xen_pmd_val(pmd_t
+ {
+ 	pmdval_t ret = __pmd_val(pmd);
+ #if CONFIG_XEN_COMPAT <= 0x030002
+-	if (ret)
++	if (likely(ret))
+ 		ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
+ #else
+-	if (ret & _PAGE_PRESENT)
++	if (likely(ret & _PAGE_PRESENT))
+ 		ret = pte_machine_to_phys(ret);
+ #endif
+ 	return ret;
+@@ -308,7 +308,7 @@ static inline pmdval_t pmd_flags(pmd_t p
+ #define __pte_ma(x) ((pte_t) { .pte = (x) } )
+ static inline pte_t xen_make_pte(pteval_t val)
+ {
+-	if ((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)
++	if (likely((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT))
+ 		val = pte_phys_to_machine(val);
+ 	return (pte_t) { .pte = val };
+ }
+@@ -317,7 +317,7 @@ static inline pte_t xen_make_pte(pteval_
+ static inline pteval_t xen_pte_val(pte_t pte)
+ {
+ 	pteval_t ret = __pte_val(pte);
+-	if ((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)
++	if (likely((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT))
+ 		ret = pte_machine_to_phys(ret);
+ 	return ret;
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-pmd-handling
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-pmd-handling
@@ -0,0 +1,605 @@
+From: jbeulich@novell.com
+Subject: consolidate pmd/pud/pgd entry handling
+Patch-mainline: obsolete
+
+--- head-2009-12-07.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:45:08.000000000 +0100
++++ head-2009-12-07/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:49:39.000000000 +0100
+@@ -99,10 +99,12 @@ void xen_invlpg(unsigned long ptr);
+ void xen_l1_entry_update(pte_t *ptr, pte_t val);
+ void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
+ void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
+-void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
++void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */
+ void xen_pgd_pin(unsigned long ptr);
+ void xen_pgd_unpin(unsigned long ptr);
+ 
++void xen_init_pgd_pin(void);
++
+ void xen_set_ldt(const void *ptr, unsigned int ents);
+ 
+ #ifdef CONFIG_SMP
+@@ -335,6 +337,18 @@ MULTI_update_va_mapping(
+ }
+ 
+ static inline void
++MULTI_mmu_update(multicall_entry_t *mcl, mmu_update_t *req,
++		 unsigned int count, unsigned int *success_count,
++		 domid_t domid)
++{
++    mcl->op = __HYPERVISOR_mmu_update;
++    mcl->args[0] = (unsigned long)req;
++    mcl->args[1] = count;
++    mcl->args[2] = (unsigned long)success_count;
++    mcl->args[3] = domid;
++}
++
++static inline void
+ MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd,
+ 		     void *uop, unsigned int count)
+ {
+--- head-2009-12-07.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2009-12-07/arch/x86/include/mach-xen/asm/pgalloc.h	2009-10-13 17:22:09.000000000 +0200
+@@ -70,20 +70,16 @@ static inline void pmd_populate(struct m
+ 				struct page *pte)
+ {
+ 	unsigned long pfn = page_to_pfn(pte);
++	pmd_t ent = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
+ 
+ 	paravirt_alloc_pte(mm, pfn);
+-	if (PagePinned(virt_to_page(mm->pgd))) {
+-		if (!PageHighMem(pte))
+-			BUG_ON(HYPERVISOR_update_va_mapping(
+-			  (unsigned long)__va(pfn << PAGE_SHIFT),
+-			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
+-#ifndef CONFIG_X86_64
+-		else if (!TestSetPagePinned(pte))
+-			kmap_flush_unused();
++	if (PagePinned(virt_to_page(pmd))) {
++#ifndef CONFIG_HIGHPTE
++		BUG_ON(PageHighMem(pte));
+ #endif
+-		set_pmd(pmd, __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
++		set_pmd(pmd, ent);
+ 	} else
+-		*pmd = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
++		*pmd = ent;
+ }
+ 
+ #define pmd_pgtable(pmd) pmd_page(pmd)
+@@ -111,39 +107,28 @@ extern void pud_populate(struct mm_struc
+ #else	/* !CONFIG_X86_PAE */
+ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+ {
++	pud_t ent = __pud(_PAGE_TABLE | __pa(pmd));
++
+ 	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)pmd,
+-			       pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT,
+-				       PAGE_KERNEL_RO), 0));
+-		set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
+-	} else
+-		*pud =  __pud(_PAGE_TABLE | __pa(pmd));
++	if (PagePinned(virt_to_page(pud)))
++		set_pud(pud, ent);
++	else
++		*pud = ent;
+ }
+ #endif	/* CONFIG_X86_PAE */
+ 
+ #if PAGETABLE_LEVELS > 3
+ #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+ 
+-/*
+- * We need to use the batch mode here, but pgd_pupulate() won't be
+- * be called frequently.
+- */
+ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+ {
++	pgd_t ent = __pgd(_PAGE_TABLE | __pa(pud));
++
+ 	paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)pud,
+-			       pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT,
+-				       PAGE_KERNEL_RO), 0));
+-		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
+-		set_pgd(__user_pgd(pgd), __pgd(_PAGE_TABLE | __pa(pud)));
+-	} else {
+-		*(pgd) =  __pgd(_PAGE_TABLE | __pa(pud));
+-		*__user_pgd(pgd) = *(pgd);
+-	}
++	if (unlikely(PagePinned(virt_to_page(pgd))))
++		xen_l4_entry_update(pgd, 1, ent);
++	else
++		*__user_pgd(pgd) = *pgd = ent;
+ }
+ 
+ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+--- head-2009-12-07.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:52:02.000000000 +0100
++++ head-2009-12-07/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-10-13 17:22:09.000000000 +0200
+@@ -61,12 +61,15 @@ static inline void __xen_pte_clear(pte_t
+ 	ptep->pte_high = 0;
+ }
+ 
+-static inline void xen_pmd_clear(pmd_t *pmd)
+-{
+-	xen_l2_entry_update(pmd, __pmd(0));
+-}
++#define xen_pmd_clear(pmd)			\
++({						\
++	pmd_t *__pmdp = (pmd);			\
++	PagePinned(virt_to_page(__pmdp))	\
++	? set_pmd(__pmdp, __pmd(0))		\
++	: (void)(*__pmdp = __pmd(0));		\
++})
+ 
+-static inline void pud_clear(pud_t *pudp)
++static inline void __xen_pud_clear(pud_t *pudp)
+ {
+ 	pgdval_t pgd;
+ 
+@@ -87,6 +90,14 @@ static inline void pud_clear(pud_t *pudp
+ 		xen_tlb_flush();
+ }
+ 
++#define xen_pud_clear(pudp)			\
++({						\
++	pud_t *__pudp = (pudp);			\
++	PagePinned(virt_to_page(__pudp))	\
++	? __xen_pud_clear(__pudp)		\
++	: (void)(*__pudp = __pud(0));		\
++})
++
+ #ifdef CONFIG_SMP
+ static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+--- head-2009-12-07.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2009-12-07/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-10-13 17:22:09.000000000 +0200
+@@ -79,33 +79,41 @@ static inline void xen_set_pmd(pmd_t *pm
+ 	xen_l2_entry_update(pmdp, pmd);
+ }
+ 
+-static inline void xen_pmd_clear(pmd_t *pmd)
+-{
+-	xen_set_pmd(pmd, xen_make_pmd(0));
+-}
++#define xen_pmd_clear(pmd)			\
++({						\
++	pmd_t *__pmdp = (pmd);			\
++	PagePinned(virt_to_page(__pmdp))	\
++	? set_pmd(__pmdp, xen_make_pmd(0))	\
++	: (void)(*__pmdp = xen_make_pmd(0));	\
++})
+ 
+ static inline void xen_set_pud(pud_t *pudp, pud_t pud)
+ {
+ 	xen_l3_entry_update(pudp, pud);
+ }
+ 
+-static inline void xen_pud_clear(pud_t *pud)
+-{
+-	xen_set_pud(pud, xen_make_pud(0));
+-}
++#define xen_pud_clear(pud)			\
++({						\
++	pud_t *__pudp = (pud);			\
++	PagePinned(virt_to_page(__pudp))	\
++	? set_pud(__pudp, xen_make_pud(0))	\
++	: (void)(*__pudp = xen_make_pud(0));	\
++})
+ 
+ #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+ 
+ static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ {
+-	xen_l4_entry_update(pgdp, pgd);
++	xen_l4_entry_update(pgdp, 0, pgd);
+ }
+ 
+-static inline void xen_pgd_clear(pgd_t *pgd)
+-{
+-	xen_set_pgd(pgd, xen_make_pgd(0));
+-	xen_set_pgd(__user_pgd(pgd), xen_make_pgd(0));
+-}
++#define xen_pgd_clear(pgd)			\
++({						\
++	pgd_t *__pgdp = (pgd);			\
++	PagePinned(virt_to_page(__pgdp))	\
++	? xen_l4_entry_update(__pgdp, 1, xen_make_pgd(0)) \
++	: (void)(*__user_pgd(__pgdp) = *__pgdp = xen_make_pgd(0)); \
++})
+ 
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
+--- head-2009-12-07.orig/arch/x86/mm/hypervisor.c	2009-06-09 15:52:17.000000000 +0200
++++ head-2009-12-07/arch/x86/mm/hypervisor.c	2009-12-11 15:27:37.000000000 +0100
+@@ -360,31 +360,91 @@ void xen_l1_entry_update(pte_t *ptr, pte
+ }
+ EXPORT_SYMBOL_GPL(xen_l1_entry_update);
+ 
++static void do_lN_entry_update(mmu_update_t *mmu, unsigned int mmu_count,
++                               struct page *page)
++{
++	if (likely(page)) {
++		multicall_entry_t mcl[2];
++		unsigned long pfn = page_to_pfn(page);
++
++		MULTI_update_va_mapping(mcl,
++					(unsigned long)__va(pfn << PAGE_SHIFT),
++					pfn_pte(pfn, PAGE_KERNEL_RO), 0);
++		SetPagePinned(page);
++		MULTI_mmu_update(mcl + 1, mmu, mmu_count, NULL, DOMID_SELF);
++		if (unlikely(HYPERVISOR_multicall_check(mcl, 2, NULL)))
++			BUG();
++	} else if (unlikely(HYPERVISOR_mmu_update(mmu, mmu_count,
++						  NULL, DOMID_SELF) < 0))
++		BUG();
++}
++
+ void xen_l2_entry_update(pmd_t *ptr, pmd_t val)
+ {
+ 	mmu_update_t u;
++	struct page *page = NULL;
++
++	if (likely(pmd_present(val)) && likely(!pmd_large(val))
++	    && likely(mem_map)
++	    && likely(PagePinned(virt_to_page(ptr)))) {
++		page = pmd_page(val);
++		if (unlikely(PagePinned(page)))
++			page = NULL;
++		else if (PageHighMem(page)) {
++#ifndef CONFIG_HIGHPTE
++			BUG();
++#endif
++			kmap_flush_unused();
++			page = NULL;
++		}
++	}
+ 	u.ptr = virt_to_machine(ptr);
+ 	u.val = __pmd_val(val);
+-	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++	do_lN_entry_update(&u, 1, page);
+ }
+ 
+ #if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
+ void xen_l3_entry_update(pud_t *ptr, pud_t val)
+ {
+ 	mmu_update_t u;
++	struct page *page = NULL;
++
++	if (likely(pud_present(val))
++#ifdef CONFIG_X86_64
++	    && likely(!pud_large(val))
++#endif
++	    && likely(mem_map)
++	    && likely(PagePinned(virt_to_page(ptr)))) {
++		page = pud_page(val);
++		if (unlikely(PagePinned(page)))
++			page = NULL;
++	}
+ 	u.ptr = virt_to_machine(ptr);
+ 	u.val = __pud_val(val);
+-	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++	do_lN_entry_update(&u, 1, page);
+ }
+ #endif
+ 
+ #ifdef CONFIG_X86_64
+-void xen_l4_entry_update(pgd_t *ptr, pgd_t val)
++void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val)
+ {
+-	mmu_update_t u;
+-	u.ptr = virt_to_machine(ptr);
+-	u.val = __pgd_val(val);
+-	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++	mmu_update_t u[2];
++	struct page *page = NULL;
++
++	if (likely(pgd_present(val)) && likely(mem_map)
++	    && likely(PagePinned(virt_to_page(ptr)))) {
++		page = pgd_page(val);
++		if (unlikely(PagePinned(page)))
++			page = NULL;
++	}
++	u[0].ptr = virt_to_machine(ptr);
++	u[0].val = __pgd_val(val);
++	if (user) {
++		u[1].ptr = virt_to_machine(__user_pgd(ptr));
++		u[1].val = __pgd_val(val);
++		do_lN_entry_update(u, 2, page);
++	} else
++		do_lN_entry_update(u, 1, page);
+ }
+ #endif /* CONFIG_X86_64 */
+ 
+--- head-2009-12-07.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2009-12-07/arch/x86/mm/init_32-xen.c	2009-10-13 17:22:09.000000000 +0200
+@@ -748,6 +748,8 @@ static void __init zone_sizes_init(void)
+ #endif
+ 
+ 	free_area_init_nodes(max_zone_pfns);
++
++	xen_init_pgd_pin();
+ }
+ 
+ static unsigned long __init setup_node_bootmem(int nodeid,
+@@ -1018,8 +1020,6 @@ void __init mem_init(void)
+ 
+ 	save_pg_dir();
+ 	zap_low_mappings(true);
+-
+-	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+ 
+ #ifdef CONFIG_MEMORY_HOTPLUG
+--- head-2009-12-07.orig/arch/x86/mm/init_64-xen.c	2009-12-04 12:07:13.000000000 +0100
++++ head-2009-12-07/arch/x86/mm/init_64-xen.c	2009-11-12 17:37:05.000000000 +0100
+@@ -192,8 +192,11 @@ static pud_t *fill_pud(pgd_t *pgd, unsig
+ {
+ 	if (pgd_none(*pgd)) {
+ 		pud_t *pud = (pud_t *)spp_getpage();
+-		make_page_readonly(pud, XENFEAT_writable_page_tables);
+-		pgd_populate(&init_mm, pgd, pud);
++		if (!after_bootmem) {
++			make_page_readonly(pud, XENFEAT_writable_page_tables);
++			xen_l4_entry_update(pgd, __pgd(__pa(pud) | _PAGE_TABLE));
++		} else
++			pgd_populate(&init_mm, pgd, pud);
+ 		if (pud != pud_offset(pgd, 0))
+ 			printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n",
+ 			       pud, pud_offset(pgd, 0));
+@@ -205,8 +208,11 @@ static pmd_t *fill_pmd(pud_t *pud, unsig
+ {
+ 	if (pud_none(*pud)) {
+ 		pmd_t *pmd = (pmd_t *) spp_getpage();
+-		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+-		pud_populate(&init_mm, pud, pmd);
++		if (!after_bootmem) {
++			make_page_readonly(pmd, XENFEAT_writable_page_tables);
++			xen_l3_entry_update(pud, __pud(__pa(pmd) | _PAGE_TABLE));
++		} else
++			pud_populate(&init_mm, pud, pmd);
+ 		if (pmd != pmd_offset(pud, 0))
+ 			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
+ 			       pmd, pmd_offset(pud, 0));
+@@ -535,7 +541,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ 						   XENFEAT_writable_page_tables);
+ 			*pmd = __pmd(pte_phys | _PAGE_TABLE);
+ 		} else {
+-			make_page_readonly(pte, XENFEAT_writable_page_tables);
+ 			spin_lock(&init_mm.page_table_lock);
+ 			pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
+ 			spin_unlock(&init_mm.page_table_lock);
+@@ -624,7 +629,6 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 			else
+ 				*pud = __pud(pmd_phys | _PAGE_TABLE);
+ 		} else {
+-			make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 			spin_lock(&init_mm.page_table_lock);
+ 			pud_populate(&init_mm, pud, __va(pmd_phys));
+ 			spin_unlock(&init_mm.page_table_lock);
+@@ -798,7 +802,6 @@ kernel_physical_mapping_init(unsigned lo
+ 						   XENFEAT_writable_page_tables);
+ 			xen_l4_entry_update(pgd, __pgd(pud_phys | _PAGE_TABLE));
+ 		} else {
+-			make_page_readonly(pud, XENFEAT_writable_page_tables);
+ 			spin_lock(&init_mm.page_table_lock);
+ 			pgd_populate(&init_mm, pgd, __va(pud_phys));
+ 			spin_unlock(&init_mm.page_table_lock);
+@@ -854,7 +857,7 @@ void __init paging_init(void)
+ 
+ 	free_area_init_nodes(max_zone_pfns);
+ 
+-	SetPagePinned(virt_to_page(init_mm.pgd));
++	xen_init_pgd_pin();
+ }
+ 
+ /*
+--- head-2009-12-07.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2009-12-07/arch/x86/mm/pgtable-xen.c	2009-10-13 17:22:09.000000000 +0200
+@@ -44,16 +44,16 @@ pgtable_t pte_alloc_one(struct mm_struct
+ void __pte_free(pgtable_t pte)
+ {
+ 	if (!PageHighMem(pte)) {
+-		unsigned long va = (unsigned long)page_address(pte);
+-		unsigned int level;
+-		pte_t *ptep = lookup_address(va, &level);
+-
+-		BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
+-		if (!pte_write(*ptep)
+-		    && HYPERVISOR_update_va_mapping(va,
+-						    mk_pte(pte, PAGE_KERNEL),
+-						    0))
+-			BUG();
++		if (PagePinned(pte)) {
++			unsigned long pfn = page_to_pfn(pte);
++
++			if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT),
++							 pfn_pte(pfn,
++								 PAGE_KERNEL),
++							 0))
++				BUG();
++			ClearPagePinned(pte);
++		}
+ 	} else
+ #ifdef CONFIG_HIGHPTE
+ 		ClearPagePinned(pte);
+@@ -95,14 +95,15 @@ pmd_t *pmd_alloc_one(struct mm_struct *m
+ 
+ void __pmd_free(pgtable_t pmd)
+ {
+-	unsigned long va = (unsigned long)page_address(pmd);
+-	unsigned int level;
+-	pte_t *ptep = lookup_address(va, &level);
+-
+-	BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
+-	if (!pte_write(*ptep)
+-	    && HYPERVISOR_update_va_mapping(va, mk_pte(pmd, PAGE_KERNEL), 0))
+-		BUG();
++	if (PagePinned(pmd)) {
++		unsigned long pfn = page_to_pfn(pmd);
++
++		if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT),
++						 pfn_pte(pfn, PAGE_KERNEL),
++						 0))
++			BUG();
++		ClearPagePinned(pmd);
++	}
+ 
+ 	ClearPageForeign(pmd);
+ 	init_page_count(pmd);
+@@ -190,21 +191,20 @@ static inline unsigned int pgd_walk_set_
+ {
+ 	unsigned long pfn = page_to_pfn(page);
+ 
+-	if (PageHighMem(page)) {
+-		if (pgprot_val(flags) & _PAGE_RW)
+-			ClearPagePinned(page);
+-		else
+-			SetPagePinned(page);
+-	} else {
+-		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-					(unsigned long)__va(pfn << PAGE_SHIFT),
+-					pfn_pte(pfn, flags), 0);
+-		if (unlikely(++seq == PIN_BATCH)) {
+-			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-								PIN_BATCH, NULL)))
+-				BUG();
+-			seq = 0;
+-		}
++	if (pgprot_val(flags) & _PAGE_RW)
++		ClearPagePinned(page);
++	else
++		SetPagePinned(page);
++	if (PageHighMem(page))
++		return seq;
++	MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++				(unsigned long)__va(pfn << PAGE_SHIFT),
++				pfn_pte(pfn, flags), 0);
++	if (unlikely(++seq == PIN_BATCH)) {
++		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++							PIN_BATCH, NULL)))
++			BUG();
++		seq = 0;
+ 	}
+ 
+ 	return seq;
+@@ -251,6 +251,16 @@ static void pgd_walk(pgd_t *pgd_base, pg
+ 		}
+ 	}
+ 
++#ifdef CONFIG_X86_PAE
++	for (; g < PTRS_PER_PGD; g++, pgd++) {
++		BUG_ON(pgd_none(*pgd));
++		pud = pud_offset(pgd, 0);
++		BUG_ON(pud_none(*pud));
++		pmd = pmd_offset(pud, 0);
++		seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
++	}
++#endif
++
+ 	mcl = per_cpu(pb_mcl, cpu);
+ #ifdef CONFIG_X86_64
+ 	if (unlikely(seq > PIN_BATCH - 2)) {
+@@ -286,6 +296,51 @@ static void pgd_walk(pgd_t *pgd_base, pg
+ 	put_cpu();
+ }
+ 
++void __init xen_init_pgd_pin(void)
++{
++	pgd_t       *pgd = init_mm.pgd;
++	pud_t       *pud;
++	pmd_t       *pmd;
++	unsigned int g, u, m;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return;
++
++	SetPagePinned(virt_to_page(pgd));
++	for (g = 0; g < PTRS_PER_PGD; g++, pgd++) {
++#ifndef CONFIG_X86_PAE
++		if (g >= pgd_index(HYPERVISOR_VIRT_START)
++		    && g <= pgd_index(HYPERVISOR_VIRT_END - 1))
++			continue;
++#endif
++		if (!pgd_present(*pgd))
++			continue;
++		pud = pud_offset(pgd, 0);
++		if (PTRS_PER_PUD > 1) /* not folded */
++			SetPagePinned(virt_to_page(pud));
++		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++			if (!pud_present(*pud))
++				continue;
++			pmd = pmd_offset(pud, 0);
++			if (PTRS_PER_PMD > 1) /* not folded */
++				SetPagePinned(virt_to_page(pmd));
++			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++#ifdef CONFIG_X86_PAE
++				if (g == pgd_index(HYPERVISOR_VIRT_START)
++				    && m >= pmd_index(HYPERVISOR_VIRT_START))
++					continue;
++#endif
++				if (!pmd_present(*pmd))
++					continue;
++				SetPagePinned(pmd_page(*pmd));
++			}
++		}
++	}
++#ifdef CONFIG_X86_64
++	SetPagePinned(virt_to_page(level3_user_pgt));
++#endif
++}
++
+ static void __pgd_pin(pgd_t *pgd)
+ {
+ 	pgd_walk(pgd, PAGE_KERNEL_RO);
+@@ -476,21 +531,18 @@ static void pgd_dtor(pgd_t *pgd)
+ 
+ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+ {
+-	struct page *page = virt_to_page(pmd);
+-	unsigned long pfn = page_to_pfn(page);
+-
+-	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
+-
+ 	/* Note: almost everything apart from _PAGE_PRESENT is
+ 	   reserved at the pmd (PDPT) level. */
+-	if (PagePinned(virt_to_page(mm->pgd))) {
+-		BUG_ON(PageHighMem(page));
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			  (unsigned long)__va(pfn << PAGE_SHIFT),
+-			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
+-		set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
+-	} else
+-		*pudp = __pud(__pa(pmd) | _PAGE_PRESENT);
++	pud_t pud = __pud(__pa(pmd) | _PAGE_PRESENT);
++
++	paravirt_alloc_pmd(mm, page_to_pfn(virt_to_page(pmd)));
++
++	if (likely(!PagePinned(virt_to_page(pudp)))) {
++		*pudp = pud;
++		return;
++	}
++
++	set_pud(pudp, pud);
+ 
+ 	/*
+ 	 * According to Intel App note "TLBs, Paging-Structure Caches,
+@@ -585,13 +637,10 @@ static void pgd_prepopulate_pmd(struct m
+ 	     i++, pud++, addr += PUD_SIZE) {
+ 		pmd_t *pmd = pmds[i];
+ 
+-		if (i >= KERNEL_PGD_BOUNDARY) {
++		if (i >= KERNEL_PGD_BOUNDARY)
+ 			memcpy(pmd,
+ 			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+ 			       sizeof(pmd_t) * PTRS_PER_PMD);
+-			make_lowmem_page_readonly(
+-				pmd, XENFEAT_writable_page_tables);
+-		}
+ 
+ 		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
+ 		pud_populate(mm, pud, pmd);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-blkfront-cdrom
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-blkfront-cdrom
@@ -0,0 +1,711 @@
+From: plc@novell.com
+Subject: implement forwarding of CD-ROM specific commands
+Patch-mainline: obsolete
+References: fate#300964
+
+--- head-2010-01-18.orig/drivers/cdrom/Makefile	2010-01-18 15:20:20.000000000 +0100
++++ head-2010-01-18/drivers/cdrom/Makefile	2009-10-15 12:13:13.000000000 +0200
+@@ -9,6 +9,7 @@ obj-$(CONFIG_BLK_DEV_IDECD)	+=          
+ obj-$(CONFIG_BLK_DEV_SR)	+=              cdrom.o
+ obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
+ obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
++obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+=		cdrom.o
+ 
+ obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
+ obj-$(CONFIG_GDROM)		+= gdrom.o      cdrom.o
+--- head-2010-01-18.orig/drivers/xen/blkfront/Makefile	2007-06-12 13:13:44.000000000 +0200
++++ head-2010-01-18/drivers/xen/blkfront/Makefile	2009-10-15 12:13:13.000000000 +0200
+@@ -1,5 +1,5 @@
+ 
+ obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	:= xenblk.o
+ 
+-xenblk-objs := blkfront.o vbd.o
++xenblk-objs := blkfront.o vbd.o vcd.o
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 17:06:03.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 17:08:00.000000000 +0100
+@@ -377,6 +377,8 @@ static void connect(struct blkfront_info
+ 	add_disk(info->gd);
+ 
+ 	info->is_ready = 1;
++
++	register_vcd(info);
+ }
+ 
+ /**
+@@ -407,6 +409,8 @@ static void blkfront_closing(struct xenb
+ 
+ 	xlvbd_sysfs_delif(info);
+ 
++	unregister_vcd(info);
++
+ 	xlvbd_del(info);
+ 
+  out:
+--- head-2010-01-18.orig/drivers/xen/blkfront/block.h	2010-01-18 16:49:13.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/block.h	2010-01-18 17:06:20.000000000 +0100
+@@ -163,4 +163,8 @@ static inline void xlvbd_sysfs_delif(str
+ }
+ #endif
+ 
++/* Virtual cdrom block-device */
++extern void register_vcd(struct blkfront_info *info);
++extern void unregister_vcd(struct blkfront_info *info);
++
+ #endif /* __XEN_DRIVERS_BLOCK_H__ */
+--- head-2010-01-18.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:54:56.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 17:06:22.000000000 +0100
+@@ -370,7 +370,8 @@ xlvbd_add(blkif_sector_t capacity, int v
+ 		goto out;
+ 	info->mi = mi;
+ 
+-	if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
++	if (!(vdisk_info & VDISK_CDROM) &&
++	    (minor & ((1 << mi->type->partn_shift) - 1)) == 0)
+ 		nr_minors = 1 << mi->type->partn_shift;
+ 
+ 	err = xlbd_reserve_minors(mi, minor, nr_minors);
+@@ -384,7 +385,7 @@ xlvbd_add(blkif_sector_t capacity, int v
+ 
+ 	offset =  mi->index * mi->type->disks_per_major +
+ 			(minor >> mi->type->partn_shift);
+-	if (nr_minors > 1) {
++	if (nr_minors > 1 || (vdisk_info & VDISK_CDROM)) {
+ 		if (offset < 26) {
+ 			sprintf(gd->disk_name, "%s%c",
+ 				 mi->type->diskname, 'a' + offset );
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkfront/vcd.c	2010-01-18 17:07:41.000000000 +0100
+@@ -0,0 +1,509 @@
++/*******************************************************************************
++* vcd.c
++*
++* Implements CDROM cmd packet passing between frontend guest and backend driver.
++*
++* Copyright (c) 2008, Pat Campell  plc@novell.com
++*
++* 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 REVISION "$Revision: 1.0 $"
++
++#include <linux/module.h>
++#include <linux/blkdev.h>
++#include <linux/list.h>
++#include <linux/cdrom.h>
++#include <xen/interface/io/cdromif.h>
++#include "block.h"
++
++/* List of cdrom_device_info, can have as many as blkfront supports */
++struct vcd_disk {
++	struct list_head vcd_entry;
++	struct cdrom_device_info vcd_cdrom_info;
++	spinlock_t vcd_cdrom_info_lock;
++};
++static LIST_HEAD(vcd_disks);
++static DEFINE_SPINLOCK(vcd_disks_lock);
++
++static struct vcd_disk *xencdrom_get_list_entry(struct gendisk *disk)
++{
++	struct vcd_disk *ret_vcd = NULL;
++	struct vcd_disk *vcd;
++
++	spin_lock(&vcd_disks_lock);
++	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
++		if (vcd->vcd_cdrom_info.disk == disk) {
++			spin_lock(&vcd->vcd_cdrom_info_lock);
++			ret_vcd = vcd;
++			break;
++		}
++	}
++	spin_unlock(&vcd_disks_lock);
++	return ret_vcd;
++}
++
++static void submit_message(struct blkfront_info *info, void *sp)
++{
++	struct request *req = NULL;
++
++	req = blk_get_request(info->rq, READ, __GFP_WAIT);
++	if (blk_rq_map_kern(info->rq, req, sp, PAGE_SIZE, __GFP_WAIT))
++		goto out;
++
++	req->rq_disk = info->gd;
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
++	req->cmd_type = REQ_TYPE_BLOCK_PC;
++	req->cmd_flags |= REQ_NOMERGE;
++#else
++	req->flags |= REQ_BLOCK_PC;
++#endif
++	req->__sector = 0;
++	req->__data_len = PAGE_SIZE;
++	req->timeout = 60*HZ;
++
++	blk_execute_rq(req->q, info->gd, req, 1);
++
++out:
++	blk_put_request(req);
++}
++
++static int submit_cdrom_cmd(struct blkfront_info *info,
++			    struct packet_command *cgc)
++{
++	int ret = 0;
++	struct page *page;
++	size_t size;
++	union xen_block_packet *sp;
++	struct xen_cdrom_packet *xcp;
++	struct vcd_generic_command *vgc;
++
++	if (cgc->buffer && cgc->buflen > MAX_PACKET_DATA) {
++		printk(KERN_WARNING "%s() Packet buffer length is to large \n", __func__);
++		return -EIO;
++	}
++
++	page = alloc_page(GFP_NOIO);
++	if (!page) {
++		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
++		return -ENOMEM;
++	}
++
++	size = PAGE_SIZE;
++	memset(page_address(page), 0, PAGE_SIZE);
++	sp = page_address(page);
++	xcp = &(sp->xcp);
++	xcp->type = XEN_TYPE_CDROM_PACKET;
++	xcp->payload_offset = PACKET_PAYLOAD_OFFSET;
++
++	vgc = (struct vcd_generic_command *)((char *)sp + xcp->payload_offset);
++	memcpy(vgc->cmd, cgc->cmd, CDROM_PACKET_SIZE);
++	vgc->stat = cgc->stat;
++	vgc->data_direction = cgc->data_direction;
++	vgc->quiet = cgc->quiet;
++	vgc->timeout = cgc->timeout;
++	if (cgc->sense) {
++		vgc->sense_offset = PACKET_SENSE_OFFSET;
++		memcpy((char *)sp + vgc->sense_offset, cgc->sense, sizeof(struct request_sense));
++	}
++	if (cgc->buffer) {
++		vgc->buffer_offset = PACKET_BUFFER_OFFSET;
++		memcpy((char *)sp + vgc->buffer_offset, cgc->buffer, cgc->buflen);
++		vgc->buflen = cgc->buflen;
++	}
++
++	submit_message(info,sp);
++
++	if (xcp->ret)
++		ret = xcp->err;
++
++	if (cgc->sense) {
++		memcpy(cgc->sense, (char *)sp + PACKET_SENSE_OFFSET, sizeof(struct request_sense));
++	}
++	if (cgc->buffer && cgc->buflen) {
++		memcpy(cgc->buffer, (char *)sp + PACKET_BUFFER_OFFSET, cgc->buflen);
++	}
++
++	__free_page(page);
++	return ret;
++}
++
++
++static int xencdrom_open(struct cdrom_device_info *cdi, int purpose)
++{
++	int ret = 0;
++	struct page *page;
++	struct blkfront_info *info;
++	union xen_block_packet *sp;
++	struct xen_cdrom_open *xco;
++
++	info = cdi->disk->private_data;
++
++	if(info->is_ready < 0)
++		return -ENODEV;
++
++	if (strlen(info->xbdev->otherend) > MAX_PACKET_DATA) {
++		return -EIO;
++	}
++
++	page = alloc_page(GFP_NOIO);
++	if (!page) {
++		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
++		return -ENOMEM;
++	}
++
++	memset(page_address(page), 0, PAGE_SIZE);
++	sp = page_address(page);
++	xco = &(sp->xco);
++	xco->type = XEN_TYPE_CDROM_OPEN;
++	xco->payload_offset = sizeof(struct xen_cdrom_open);
++	strcpy((char *)sp + xco->payload_offset, info->xbdev->otherend);
++
++	submit_message(info,sp);
++
++	if (xco->ret) {
++		ret = xco->err;
++		goto out;
++	}
++
++	if (xco->media_present)
++		set_capacity(cdi->disk, xco->sectors);
++
++out:
++	__free_page(page);
++	return ret;
++}
++
++static void xencdrom_release(struct cdrom_device_info *cdi)
++{
++}
++
++static int xencdrom_media_changed(struct cdrom_device_info *cdi, int disc_nr)
++{
++	int ret;
++	struct page *page;
++	struct blkfront_info *info;
++	union xen_block_packet *sp;
++	struct xen_cdrom_media_changed *xcmc;
++
++	info = cdi->disk->private_data;
++
++	page = alloc_page(GFP_NOIO);
++	if (!page) {
++		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
++		return -ENOMEM;
++	}
++
++	memset(page_address(page), 0, PAGE_SIZE);
++	sp = page_address(page);
++	xcmc = &(sp->xcmc);
++	xcmc->type = XEN_TYPE_CDROM_MEDIA_CHANGED;
++	submit_message(info,sp);
++	ret = xcmc->media_changed;
++
++	__free_page(page);
++
++	return ret;
++}
++
++static int xencdrom_tray_move(struct cdrom_device_info *cdi, int position)
++{
++	int ret;
++	struct packet_command cgc;
++	struct blkfront_info *info;
++
++	info = cdi->disk->private_data;
++	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
++	cgc.cmd[0] = GPCMD_START_STOP_UNIT;
++	if (position)
++		cgc.cmd[4] = 2;
++	else
++		cgc.cmd[4] = 3;
++	ret = submit_cdrom_cmd(info, &cgc);
++	return ret;
++}
++
++static int xencdrom_lock_door(struct cdrom_device_info *cdi, int lock)
++{
++	int ret = 0;
++	struct blkfront_info *info;
++	struct packet_command cgc;
++
++	info = cdi->disk->private_data;
++	init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
++	cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
++	cgc.cmd[4] = lock;
++	ret = submit_cdrom_cmd(info, &cgc);
++	return ret;
++}
++
++static int xencdrom_packet(struct cdrom_device_info *cdi,
++		struct packet_command *cgc)
++{
++	int ret = -EIO;
++	struct blkfront_info *info;
++
++	info = cdi->disk->private_data;
++	ret = submit_cdrom_cmd(info, cgc);
++	cgc->stat = ret;
++	return ret;
++}
++
++static int xencdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
++		void *arg)
++{
++	return -EINVAL;
++}
++
++/* Query backend to see if CDROM packets are supported */
++static int xencdrom_supported(struct blkfront_info *info)
++{
++	struct page *page;
++	union xen_block_packet *sp;
++	struct xen_cdrom_support *xcs;
++
++	page = alloc_page(GFP_NOIO);
++	if (!page) {
++		printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
++		return -ENOMEM;
++	}
++
++	memset(page_address(page), 0, PAGE_SIZE);
++	sp = page_address(page);
++	xcs = &(sp->xcs);
++	xcs->type = XEN_TYPE_CDROM_SUPPORT;
++	submit_message(info,sp);
++	return xcs->supported;
++}
++
++static struct cdrom_device_ops xencdrom_dops = {
++    .open           = xencdrom_open,
++    .release        = xencdrom_release,
++    .media_changed  = xencdrom_media_changed,
++    .tray_move      = xencdrom_tray_move,
++    .lock_door      = xencdrom_lock_door,
++    .generic_packet = xencdrom_packet,
++    .audio_ioctl    = xencdrom_audio_ioctl,
++    .capability     = (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | \
++                       CDC_MEDIA_CHANGED | CDC_GENERIC_PACKET |  CDC_DVD | \
++                       CDC_CD_R),
++    .n_minors       = 1,
++};
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++static int xencdrom_block_open(struct inode *inode, struct file *file)
++{
++	struct block_device *bd = inode->i_bdev;
++#else
++static int xencdrom_block_open(struct block_device *bd, fmode_t mode)
++{
++#endif
++	struct blkfront_info *info = bd->bd_disk->private_data;
++	struct vcd_disk *vcd;
++	int ret = 0;
++
++	if(info->is_ready < 0)
++		return -ENODEV;
++
++	if ((vcd = xencdrom_get_list_entry(info->gd))) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++		ret = cdrom_open(&vcd->vcd_cdrom_info, inode, file);
++#else
++		ret = cdrom_open(&vcd->vcd_cdrom_info, bd, mode);
++#endif
++		info->users = vcd->vcd_cdrom_info.use_count;
++		spin_unlock(&vcd->vcd_cdrom_info_lock);
++	}
++	return ret;
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++static int xencdrom_block_release(struct inode *inode, struct file *file)
++{
++	struct gendisk *gd = inode->i_bdev->bd_disk;
++#else
++static int xencdrom_block_release(struct gendisk *gd, fmode_t mode)
++{
++#endif
++	struct blkfront_info *info = gd->private_data;
++	struct vcd_disk *vcd;
++	int ret = 0;
++
++	if ((vcd = xencdrom_get_list_entry(info->gd))) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++		ret = cdrom_release(&vcd->vcd_cdrom_info, file);
++#else
++		cdrom_release(&vcd->vcd_cdrom_info, mode);
++#endif
++		spin_unlock(&vcd->vcd_cdrom_info_lock);
++		if (vcd->vcd_cdrom_info.use_count == 0) {
++			info->users = 1;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++			blkif_release(inode, file);
++#else
++			blkif_release(gd, mode);
++#endif
++		}
++	}
++	return ret;
++}
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
++static int xencdrom_block_ioctl(struct inode *inode, struct file *file,
++				unsigned cmd, unsigned long arg)
++{
++	struct block_device *bd = inode->i_bdev;
++#else
++static int xencdrom_block_ioctl(struct block_device *bd, fmode_t mode,
++				unsigned cmd, unsigned long arg)
++{
++#endif
++	struct blkfront_info *info = bd->bd_disk->private_data;
++	struct vcd_disk *vcd;
++	int ret = 0;
++
++	if (!(vcd = xencdrom_get_list_entry(info->gd)))
++		goto out;
++
++	switch (cmd) {
++	case 2285: /* SG_IO */
++		ret = -ENOSYS;
++		break;
++	case CDROMEJECT:
++		ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 1);
++		break;
++	case CDROMCLOSETRAY:
++		ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 0);
++		break;
++	case CDROM_GET_CAPABILITY:
++		ret = vcd->vcd_cdrom_info.ops->capability & ~vcd->vcd_cdrom_info.mask;
++		break;
++	case CDROM_SET_OPTIONS:
++		ret = vcd->vcd_cdrom_info.options;
++		break;
++	case CDROM_SEND_PACKET:
++		ret = submit_cdrom_cmd(info, (struct packet_command *)arg);
++		break;
++	default:
++		/* Not supported, augment supported above if necessary */
++		printk("%s():%d Unsupported IOCTL:%x \n", __func__, __LINE__, cmd);
++		ret = -ENOTTY;
++		break;
++	}
++	spin_unlock(&vcd->vcd_cdrom_info_lock);
++out:
++	return ret;
++}
++
++/* Called as result of cdrom_open, vcd_cdrom_info_lock already held */
++static int xencdrom_block_media_changed(struct gendisk *disk)
++{
++	struct vcd_disk *vcd;
++	struct vcd_disk *ret_vcd = NULL;
++	int ret = 0;
++
++	spin_lock(&vcd_disks_lock);
++	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
++		if (vcd->vcd_cdrom_info.disk == disk) {
++			ret_vcd = vcd;
++			break;
++		}
++	}
++	spin_unlock(&vcd_disks_lock);
++	if (ret_vcd) {
++		ret = cdrom_media_changed(&ret_vcd->vcd_cdrom_info);
++	}
++	return ret;
++}
++
++static const struct block_device_operations xencdrom_bdops =
++{
++	.owner		= THIS_MODULE,
++	.open		= xencdrom_block_open,
++	.release	= xencdrom_block_release,
++	.ioctl		= xencdrom_block_ioctl,
++	.media_changed	= xencdrom_block_media_changed,
++};
++
++void register_vcd(struct blkfront_info *info)
++{
++	struct gendisk *gd = info->gd;
++	struct vcd_disk *vcd;
++
++	/* Make sure this is for a CD device */
++	if (!(gd->flags & GENHD_FL_CD))
++		goto out;
++
++	/* Make sure we have backend support */
++	if (!xencdrom_supported(info)) {
++		goto out;
++	}
++
++	/* Create new vcd_disk and fill in cdrom_info */
++	vcd = (struct vcd_disk *)kzalloc(sizeof(struct vcd_disk), GFP_KERNEL);
++	if (!vcd) {
++		printk(KERN_INFO "%s():  Unable to allocate vcd struct!\n", __func__);
++		goto out;
++	}
++	spin_lock_init(&vcd->vcd_cdrom_info_lock);
++
++	vcd->vcd_cdrom_info.ops	= &xencdrom_dops;
++	vcd->vcd_cdrom_info.speed = 4;
++	vcd->vcd_cdrom_info.capacity = 1;
++	vcd->vcd_cdrom_info.options	= 0;
++	strcpy(vcd->vcd_cdrom_info.name, gd->disk_name);
++	vcd->vcd_cdrom_info.mask = (CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM |
++			CDC_SELECT_DISC | CDC_SELECT_SPEED |
++			CDC_MRW | CDC_MRW_W | CDC_RAM);
++
++	if (register_cdrom(&(vcd->vcd_cdrom_info)) != 0) {
++		printk(KERN_WARNING "%s() Cannot register blkdev as a cdrom %d!\n", __func__,
++				gd->major);
++		goto err_out;
++	}
++	gd->fops = &xencdrom_bdops;
++	vcd->vcd_cdrom_info.disk = gd;
++
++	spin_lock(&vcd_disks_lock);
++	list_add(&(vcd->vcd_entry), &vcd_disks);
++	spin_unlock(&vcd_disks_lock);
++out:
++	return;
++err_out:
++	kfree(vcd);
++}
++
++void unregister_vcd(struct blkfront_info *info) {
++	struct gendisk *gd = info->gd;
++	struct vcd_disk *vcd;
++
++	spin_lock(&vcd_disks_lock);
++	list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
++		if (vcd->vcd_cdrom_info.disk == gd) {
++			spin_lock(&vcd->vcd_cdrom_info_lock);
++			unregister_cdrom(&vcd->vcd_cdrom_info);
++			list_del(&vcd->vcd_entry);
++			spin_unlock(&vcd->vcd_cdrom_info_lock);
++			kfree(vcd);
++			break;
++		}
++	}
++	spin_unlock(&vcd_disks_lock);
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/cdromif.h	2009-10-15 12:13:13.000000000 +0200
+@@ -0,0 +1,120 @@
++/******************************************************************************
++ * cdromif.h
++ *
++ * Shared definitions between backend driver and Xen guest Virtual CDROM
++ * block device.
++ *
++ * Copyright (c) 2008, Pat Campell  plc@novell.com
++ *
++ * 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_PUBLIC_IO_CDROMIF_H__
++#define __XEN_PUBLIC_IO_CDROMIF_H__
++
++/*
++ * Queries backend for CDROM support
++ */
++#define XEN_TYPE_CDROM_SUPPORT         _IO('c', 1)
++
++struct xen_cdrom_support
++{
++	uint32_t type;
++	int8_t ret;                  /* returned, 0 succeded, -1 error */
++	int8_t err;                  /* returned, backend errno */
++	int8_t supported;            /* returned, 1 supported */
++};
++
++/*
++ * Opens backend device, returns drive geometry or
++ * any encountered errors
++ */
++#define XEN_TYPE_CDROM_OPEN            _IO('c', 2)
++
++struct xen_cdrom_open
++{
++	uint32_t type;
++	int8_t ret;
++	int8_t err;
++	int8_t pad;
++	int8_t media_present;        /* returned */
++	uint32_t sectors;            /* returned */
++	uint32_t sector_size;        /* returned */
++	int32_t payload_offset;      /* offset to backend node name payload */
++};
++
++/*
++ * Queries backend for media changed status
++ */
++#define XEN_TYPE_CDROM_MEDIA_CHANGED   _IO('c', 3)
++
++struct xen_cdrom_media_changed
++{
++	uint32_t type;
++	int8_t ret;
++	int8_t err;
++	int8_t media_changed;        /* returned */
++};
++
++/*
++ * Sends vcd generic CDROM packet to backend, followed
++ * immediately by the vcd_generic_command payload
++ */
++#define XEN_TYPE_CDROM_PACKET          _IO('c', 4)
++
++struct xen_cdrom_packet
++{
++	uint32_t type;
++	int8_t ret;
++	int8_t err;
++	int8_t pad[2];
++	int32_t payload_offset;      /* offset to vcd_generic_command payload */
++};
++
++/* CDROM_PACKET_COMMAND, payload for XEN_TYPE_CDROM_PACKET */
++struct vcd_generic_command
++{
++	uint8_t  cmd[CDROM_PACKET_SIZE];
++	uint8_t  pad[4];
++	uint32_t buffer_offset;
++	uint32_t buflen;
++	int32_t  stat;
++	uint32_t sense_offset;
++	uint8_t  data_direction;
++	uint8_t  pad1[3];
++	int32_t  quiet;
++	int32_t  timeout;
++};
++
++union xen_block_packet
++{
++	uint32_t type;
++	struct xen_cdrom_support xcs;
++	struct xen_cdrom_open xco;
++	struct xen_cdrom_media_changed xcmc;
++	struct xen_cdrom_packet xcp;
++};
++
++#define PACKET_PAYLOAD_OFFSET (sizeof(struct xen_cdrom_packet))
++#define PACKET_SENSE_OFFSET (PACKET_PAYLOAD_OFFSET + sizeof(struct vcd_generic_command))
++#define PACKET_BUFFER_OFFSET (PACKET_SENSE_OFFSET + sizeof(struct request_sense))
++#define MAX_PACKET_DATA (PAGE_SIZE - sizeof(struct xen_cdrom_packet) - \
++            sizeof(struct vcd_generic_command) - sizeof(struct request_sense))
++
++#endif
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.11-12
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.11-12
@@ -0,0 +1,110 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.12
+Patch-mainline: 2.6.32.12
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.11-12" by xen-port-patches.py
+
+--- sle11sp1-2010-05-20.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:18:10.000000000 +0100
++++ sle11sp1-2010-05-20/arch/x86/include/mach-xen/asm/smp.h	2010-04-26 11:32:06.000000000 +0200
+@@ -135,6 +135,8 @@ int native_cpu_disable(void);
+ void native_cpu_die(unsigned int cpu);
+ void native_play_dead(void);
+ void play_dead_common(void);
++void wbinvd_on_cpu(int cpu);
++int wbinvd_on_all_cpus(void);
+ 
+ #else /* CONFIG_XEN */
+ 
+@@ -162,8 +164,19 @@ static inline int num_booting_cpus(void)
+ {
+ 	return cpumask_weight(cpu_callout_mask);
+ }
++#elif /* !CONFIG_SMP && */ !defined(CONFIG_XEN)
++#define wbinvd_on_cpu(cpu)     wbinvd()
++static inline int wbinvd_on_all_cpus(void)
++{
++	wbinvd();
++	return 0;
++}
+ #endif /* CONFIG_SMP */
+ 
++#ifdef CONFIG_XEN
++int wbinvd_on_all_cpus(void);
++#endif
++
+ extern unsigned disabled_cpus __cpuinitdata;
+ 
+ #include <asm/smp-processor-id.h>
+--- sle11sp1-2010-05-20.orig/arch/x86/kernel/cpu/intel_cacheinfo.c	2010-05-07 11:21:58.000000000 +0200
++++ sle11sp1-2010-05-20/arch/x86/kernel/cpu/intel_cacheinfo.c	2010-05-20 11:30:31.000000000 +0200
+@@ -299,7 +299,7 @@ struct _cache_attr {
+ 	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+ };
+ 
+-#ifdef CONFIG_CPU_SUP_AMD
++#if defined(CONFIG_CPU_SUP_AMD) && !defined(CONFIG_XEN)
+ static unsigned int __cpuinit amd_calc_l3_indices(void)
+ {
+ 	/*
+@@ -871,7 +871,7 @@ static struct attribute *default_attrs[]
+ 
+ static struct attribute *default_l3_attrs[] = {
+ 	DEFAULT_SYSFS_CACHE_ATTRS,
+-#ifdef CONFIG_CPU_SUP_AMD
++#if defined(CONFIG_CPU_SUP_AMD) && !defined(CONFIG_XEN)
+ 	&cache_disable_0.attr,
+ 	&cache_disable_1.attr,
+ #endif
+--- sle11sp1-2010-05-20.orig/arch/x86/lib/Makefile	2010-03-29 09:06:18.000000000 +0200
++++ sle11sp1-2010-05-20/arch/x86/lib/Makefile	2010-04-26 11:34:51.000000000 +0200
+@@ -3,6 +3,7 @@
+ #
+ 
+ obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
++obj-$(CONFIG_XEN) += cache-smp.o
+ 
+ lib-y := delay.o
+ lib-y += thunk_$(BITS).o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ sle11sp1-2010-05-20/arch/x86/lib/cache-smp-xen.c	2010-05-07 11:12:27.000000000 +0200
+@@ -0,0 +1,27 @@
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <asm/hypervisor.h>
++
++static void __wbinvd(void *dummy)
++{
++	wbinvd();
++}
++
++#ifndef CONFIG_XEN /* XXX Needs hypervisor support. */
++void wbinvd_on_cpu(int cpu)
++{
++	smp_call_function_single(cpu, __wbinvd, NULL, 1);
++}
++EXPORT_SYMBOL(wbinvd_on_cpu);
++#endif
++
++int wbinvd_on_all_cpus(void)
++{
++	struct mmuext_op op = { .cmd = MMUEXT_FLUSH_CACHE_GLOBAL };
++
++	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) == 0)
++		return 0;
++	/* Best effort as fallback. */
++	return on_each_cpu(__wbinvd, NULL, 1);
++}
++EXPORT_SYMBOL(wbinvd_on_all_cpus);
+--- sle11sp1-2010-05-20.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:52:09.000000000 +0100
++++ sle11sp1-2010-05-20/arch/x86/pci/irq-xen.c	2010-04-26 10:41:20.000000000 +0200
+@@ -596,6 +596,8 @@ static __init int intel_router_probe(str
+ 	case PCI_DEVICE_ID_INTEL_ICH10_1:
+ 	case PCI_DEVICE_ID_INTEL_ICH10_2:
+ 	case PCI_DEVICE_ID_INTEL_ICH10_3:
++	case PCI_DEVICE_ID_INTEL_CPT_LPC1:
++	case PCI_DEVICE_ID_INTEL_CPT_LPC2:
+ 		r->name = "PIIX/ICH";
+ 		r->get = pirq_piix_get;
+ 		r->set = pirq_piix_set;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86_64-note-init-p2m
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86_64-note-init-p2m
@@ -0,0 +1,343 @@
+From: jbeulich@novell.com
+Subject: eliminate scalability issues from initial mapping setup
+Patch-mainline: obsolete
+References: bnc#417417
+
+Direct Xen to place the initial P->M table outside of the initial
+mapping, as otherwise the 1G (implementation) / 2G (theoretical)
+restriction on the size of the initial mapping limits the amount
+of memory a domain can be handed initially.
+
+Note that the flags passed to HYPERVISOR_update_va_mapping() from
+__make_page_writable() and make_lowmem_page_writable() are
+intentionally not including UVMF_ALL. This is intended to be on optimal
+choice between the overhead of a potential spurious page fault (as
+remote CPUs may still have read-only translations in their TLBs) and
+the overhead of cross processor flushes. Flushing on the local CPU
+shouldn't be as expensive (and hence can be viewed as an optimization
+avoiding the spurious page fault on the local CPU), but is required
+when the functions are used before the page fault handler gets set up.
+
+--- head-2010-01-04.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/head64-xen.c	2009-12-04 12:12:10.000000000 +0100
+@@ -123,6 +123,14 @@ void __init x86_64_start_reservations(ch
+ 
+ 	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+ 
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		xen_start_info->mfn_list = ~0UL;
++	else if (xen_start_info->mfn_list < __START_KERNEL_map)
++		reserve_early(xen_start_info->first_p2m_pfn << PAGE_SHIFT,
++			      (xen_start_info->first_p2m_pfn
++			       + xen_start_info->nr_p2m_frames) << PAGE_SHIFT,
++			      "INITP2M");
++
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+ 	 * or BIOS or kernel text should be early reserved or marked not
+--- head-2010-01-04.orig/arch/x86/kernel/head_64-xen.S	2009-12-04 14:37:53.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/head_64-xen.S	2009-12-04 14:38:07.000000000 +0100
+@@ -17,6 +17,7 @@
+ #include <linux/elfnote.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
++#include <asm/pgtable.h>
+ #include <asm/msr.h>
+ #include <asm/cache.h>
+ #include <asm/dwarf2.h>
+@@ -146,6 +147,7 @@ ENTRY(empty_zero_page)
+ 	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad startup_64)
+ 	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad hypercall_page)
+ 	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad _PAGE_PRESENT, _PAGE_PRESENT)
++	ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M,       .quad VMEMMAP_START)
+ 	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)
+--- head-2010-01-04.orig/arch/x86/kernel/setup-xen.c	2010-01-04 13:32:59.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/setup-xen.c	2010-01-04 13:33:09.000000000 +0100
+@@ -1130,7 +1130,7 @@ void __init setup_arch(char **cmdline_p)
+ 		difference = xen_start_info->nr_pages - max_pfn;
+ 
+ 		set_xen_guest_handle(reservation.extent_start,
+-				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
++				     phys_to_machine_mapping + max_pfn);
+ 		reservation.nr_extents = difference;
+ 		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+ 					   &reservation);
+@@ -1147,14 +1147,86 @@ void __init setup_arch(char **cmdline_p)
+ 		phys_to_machine_mapping = alloc_bootmem_pages(
+ 			max_pfn * sizeof(unsigned long));
+ 		memcpy(phys_to_machine_mapping,
+-		       (unsigned long *)xen_start_info->mfn_list,
++		       __va(__pa(xen_start_info->mfn_list)),
+ 		       p2m_pages * sizeof(unsigned long));
+ 		memset(phys_to_machine_mapping + p2m_pages, ~0,
+ 		       (max_pfn - p2m_pages) * sizeof(unsigned long));
+-		free_bootmem(
+-			__pa(xen_start_info->mfn_list),
+-			PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+-					sizeof(unsigned long))));
++
++#ifdef CONFIG_X86_64
++		if (xen_start_info->mfn_list == VMEMMAP_START) {
++			/*
++			 * Since it is well isolated we can (and since it is
++			 * perhaps large we should) also free the page tables
++			 * mapping the initial P->M table.
++			 */
++			unsigned long va = VMEMMAP_START, pa;
++			pgd_t *pgd = pgd_offset_k(va);
++			pud_t *pud_page = pud_offset(pgd, 0);
++
++			BUILD_BUG_ON(VMEMMAP_START & ~PGDIR_MASK);
++			xen_l4_entry_update(pgd, __pgd(0));
++			for(;;) {
++				pud_t *pud = pud_page + pud_index(va);
++
++				if (pud_none(*pud))
++					va += PUD_SIZE;
++				else if (pud_large(*pud)) {
++					pa = pud_val(*pud) & PHYSICAL_PAGE_MASK;
++					make_pages_writable(__va(pa),
++						PUD_SIZE >> PAGE_SHIFT,
++						XENFEAT_writable_page_tables);
++					free_bootmem(pa, PUD_SIZE);
++					va += PUD_SIZE;
++				} else {
++					pmd_t *pmd = pmd_offset(pud, va);
++
++					if (pmd_large(*pmd)) {
++						pa = pmd_val(*pmd) & PHYSICAL_PAGE_MASK;
++						make_pages_writable(__va(pa),
++							PMD_SIZE >> PAGE_SHIFT,
++							XENFEAT_writable_page_tables);
++						free_bootmem(pa, PMD_SIZE);
++					} else if (!pmd_none(*pmd)) {
++						pte_t *pte = pte_offset_kernel(pmd, va);
++
++						for (i = 0; i < PTRS_PER_PTE; ++i) {
++							if (pte_none(pte[i]))
++								break;
++							pa = pte_pfn(pte[i]) << PAGE_SHIFT;
++							make_page_writable(__va(pa),
++								XENFEAT_writable_page_tables);
++							free_bootmem(pa, PAGE_SIZE);
++						}
++						ClearPagePinned(virt_to_page(pte));
++						make_page_writable(pte,
++							XENFEAT_writable_page_tables);
++						free_bootmem(__pa(pte), PAGE_SIZE);
++					}
++					va += PMD_SIZE;
++					if (pmd_index(va))
++						continue;
++					ClearPagePinned(virt_to_page(pmd));
++					make_page_writable(pmd,
++						XENFEAT_writable_page_tables);
++					free_bootmem(__pa((unsigned long)pmd
++							  & PAGE_MASK),
++						PAGE_SIZE);
++				}
++				if (!pud_index(va))
++					break;
++			}
++			ClearPagePinned(virt_to_page(pud_page));
++			make_page_writable(pud_page,
++				XENFEAT_writable_page_tables);
++			free_bootmem(__pa((unsigned long)pud_page & PAGE_MASK),
++				PAGE_SIZE);
++		} else if (!WARN_ON(xen_start_info->mfn_list
++				    < __START_KERNEL_map))
++#endif
++			free_bootmem(__pa(xen_start_info->mfn_list),
++				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
++						sizeof(unsigned long))));
++
+ 
+ 		/*
+ 		 * Initialise the list of the frames that specify the list of
+--- head-2010-01-04.orig/arch/x86/mm/init-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/init-xen.c	2009-12-04 12:12:10.000000000 +0100
+@@ -347,9 +347,22 @@ unsigned long __init_refok init_memory_m
+ 
+ 	__flush_tlb_all();
+ 
+-	if (!after_bootmem && e820_table_top > e820_table_start)
++	if (!after_bootmem && e820_table_top > e820_table_start) {
++#ifdef CONFIG_X86_64
++		if (xen_start_info->mfn_list < __START_KERNEL_map
++		    && e820_table_start <= xen_start_info->first_p2m_pfn
++		    && e820_table_top > xen_start_info->first_p2m_pfn) {
++			reserve_early(e820_table_start << PAGE_SHIFT,
++				      xen_start_info->first_p2m_pfn
++				      << PAGE_SHIFT,
++				      "PGTABLE");
++			e820_table_start = xen_start_info->first_p2m_pfn
++					 + xen_start_info->nr_p2m_frames;
++		}
++#endif
+ 		reserve_early(e820_table_start << PAGE_SHIFT,
+ 			      e820_table_top << PAGE_SHIFT, "PGTABLE");
++	}
+ 
+ 	if (!after_bootmem)
+ 		early_memtest(start, end);
+--- head-2010-01-04.orig/arch/x86/mm/init_64-xen.c	2009-12-04 12:11:43.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/init_64-xen.c	2009-12-04 12:12:10.000000000 +0100
+@@ -181,6 +181,17 @@ static int __init nonx32_setup(char *str
+ }
+ __setup("noexec32=", nonx32_setup);
+ 
++static __init unsigned long get_table_end(void)
++{
++	BUG_ON(!e820_table_end);
++	if (xen_start_info->mfn_list < __START_KERNEL_map
++	    && e820_table_end == xen_start_info->first_p2m_pfn) {
++		e820_table_end += xen_start_info->nr_p2m_frames;
++		e820_table_top += xen_start_info->nr_p2m_frames;
++	}
++	return e820_table_end++;
++}
++
+ /*
+  * NOTE: This function is marked __ref because it calls __init function
+  * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
+@@ -192,8 +203,7 @@ static __ref void *spp_getpage(void)
+ 	if (after_bootmem)
+ 		ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
+ 	else if (e820_table_end < e820_table_top) {
+-		ptr = __va(e820_table_end << PAGE_SHIFT);
+-		e820_table_end++;
++		ptr = __va(get_table_end() << PAGE_SHIFT);
+ 		memset(ptr, 0, PAGE_SIZE);
+ 	} else
+ 		ptr = alloc_bootmem_pages(PAGE_SIZE);
+@@ -388,8 +398,7 @@ static __ref void *alloc_low_page(unsign
+ 		return adr;
+ 	}
+ 
+-	BUG_ON(!e820_table_end);
+-	pfn = e820_table_end++;
++	pfn = get_table_end();
+ 	if (pfn >= e820_table_top)
+ 		panic("alloc_low_page: ran out of memory");
+ 
+@@ -415,14 +424,29 @@ static inline int __meminit make_readonl
+ 	/* Make new page tables read-only on the first pass. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
+ 	    && !max_pfn_mapped
+-	    && (paddr >= (e820_table_start << PAGE_SHIFT))
+-	    && (paddr < (e820_table_top << PAGE_SHIFT)))
+-		readonly = 1;
++	    && (paddr >= (e820_table_start << PAGE_SHIFT))) {
++		unsigned long top = e820_table_top;
++
++		/* Account for the range get_table_end() skips. */
++		if (xen_start_info->mfn_list < __START_KERNEL_map
++		    && e820_table_end <= xen_start_info->first_p2m_pfn
++		    && top > xen_start_info->first_p2m_pfn)
++			top += xen_start_info->nr_p2m_frames;
++		if (paddr < (top << PAGE_SHIFT))
++			readonly = 1;
++	}
+ 	/* Make old page tables read-only. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
+ 	    && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+ 	    && (paddr < (e820_table_end << PAGE_SHIFT)))
+ 		readonly = 1;
++	/* Make P->M table (and its page tables) read-only. */
++	if (!xen_feature(XENFEAT_writable_page_tables)
++	    && xen_start_info->mfn_list < __START_KERNEL_map
++	    && paddr >= (xen_start_info->first_p2m_pfn << PAGE_SHIFT)
++	    && paddr < (xen_start_info->first_p2m_pfn
++			+ xen_start_info->nr_p2m_frames) << PAGE_SHIFT)
++		readonly = 1;
+ 
+ 	/*
+ 	 * No need for writable mapping of kernel image. This also ensures that
+@@ -718,6 +742,12 @@ void __init xen_init_pt(void)
+ 	       (PTRS_PER_PUD - pud_index(__START_KERNEL_map))
+ 	       * sizeof(*level3_kernel_pgt));
+ 
++	/* Copy the initial P->M table mappings if necessary. */
++	addr = pgd_index(xen_start_info->mfn_list);
++	if (addr < pgd_index(__START_KERNEL_map))
++		init_level4_pgt[addr] =
++			((pgd_t *)xen_start_info->pt_base)[addr];
++
+ 	/* Do an early initialization of the fixmap area. */
+ 	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ 	if (pud_present(level3_kernel_pgt[pud_index(addr)])) {
+@@ -749,22 +779,27 @@ void __init xen_init_pt(void)
+ void __init xen_finish_init_mapping(void)
+ {
+ 	unsigned long start, end;
++	struct mmuext_op mmuext;
+ 
+ 	/* Re-vector virtual addresses pointing into the initial
+ 	   mapping to the just-established permanent ones. */
+ 	xen_start_info = __va(__pa(xen_start_info));
+ 	xen_start_info->pt_base = (unsigned long)
+ 		__va(__pa(xen_start_info->pt_base));
+-	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++	if (!xen_feature(XENFEAT_auto_translated_physmap)
++	    && xen_start_info->mfn_list >= __START_KERNEL_map)
+ 		phys_to_machine_mapping =
+ 			__va(__pa(xen_start_info->mfn_list));
+-		xen_start_info->mfn_list = (unsigned long)
+-			phys_to_machine_mapping;
+-	}
+ 	if (xen_start_info->mod_start)
+ 		xen_start_info->mod_start = (unsigned long)
+ 			__va(__pa(xen_start_info->mod_start));
+ 
++	/* Unpin the no longer used Xen provided page tables. */
++	mmuext.cmd = MMUEXT_UNPIN_TABLE;
++	mmuext.arg1.mfn = virt_to_mfn(xen_start_info->pt_base);
++	if (HYPERVISOR_mmuext_op(&mmuext, 1, NULL, DOMID_SELF))
++		BUG();
++
+ 	/* Destroy the Xen-created mappings beyond the kernel image. */
+ 	start = PAGE_ALIGN(_brk_end);
+ 	end   = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT);
+--- head-2010-01-04.orig/arch/x86/mm/pageattr-xen.c	2009-12-16 12:04:35.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/pageattr-xen.c	2009-12-16 12:15:55.000000000 +0100
+@@ -1436,7 +1436,7 @@ static void __make_page_writable(unsigne
+ 
+ 	pte = lookup_address(va, &level);
+ 	BUG_ON(!pte || level != PG_LEVEL_4K);
+-	if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), 0))
++	if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), UVMF_INVLPG))
+ 		BUG();
+ 	if (in_secondary_range(va)) {
+ 		unsigned long pfn = pte_pfn(*pte);
+--- head-2010-01-04.orig/arch/x86/mm/pgtable-xen.c	2009-12-04 12:11:43.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/pgtable-xen.c	2009-12-04 12:12:10.000000000 +0100
+@@ -322,7 +322,7 @@ void __init xen_init_pgd_pin(void)
+ 		if (PTRS_PER_PUD > 1) /* not folded */
+ 			SetPagePinned(virt_to_page(pud));
+ 		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-			if (!pud_present(*pud))
++			if (!pud_present(*pud) || pud_large(*pud))
+ 				continue;
+ 			pmd = pmd_offset(pud, 0);
+ 			if (PTRS_PER_PMD > 1) /* not folded */
+@@ -333,7 +333,7 @@ void __init xen_init_pgd_pin(void)
+ 				    && m >= pmd_index(HYPERVISOR_VIRT_START))
+ 					continue;
+ #endif
+-				if (!pmd_present(*pmd))
++				if (!pmd_present(*pmd) || pmd_large(*pmd))
+ 					continue;
+ 				SetPagePinned(pmd_page(*pmd));
+ 			}
+--- head-2010-01-04.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/pgtable_32-xen.c	2009-12-04 12:12:10.000000000 +0100
+@@ -175,6 +175,6 @@ void make_lowmem_page_writable(void *va,
+ 	pte = lookup_address((unsigned long)va, &level);
+ 	BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte));
+ 	rc = HYPERVISOR_update_va_mapping(
+-		(unsigned long)va, pte_mkwrite(*pte), 0);
++		(unsigned long)va, pte_mkwrite(*pte), UVMF_INVLPG);
+ 	BUG_ON(rc);
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.27-28
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.27-28
@@ -0,0 +1,51 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.28
+Patch-mainline: 2.6.32.28
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Automatically created from "patches.kernel.org/patch-2.6.32.27-28" by xen-port-patches.py
+
+--- sle11sp1-2011-01-14.orig/arch/x86/include/mach-xen/asm/processor.h	2010-03-17 14:37:31.000000000 +0100
++++ sle11sp1-2011-01-14/arch/x86/include/mach-xen/asm/processor.h	2011-01-14 12:47:12.000000000 +0100
+@@ -710,31 +710,6 @@ extern unsigned long		boot_option_idle_o
+ extern unsigned long		idle_halt;
+ extern unsigned long		idle_nomwait;
+ 
+-#ifndef CONFIG_XEN
+-/*
+- * on systems with caches, caches must be flashed as the absolute
+- * last instruction before going into a suspended halt.  Otherwise,
+- * dirty data can linger in the cache and become stale on resume,
+- * leading to strange errors.
+- *
+- * perform a variety of operations to guarantee that the compiler
+- * will not reorder instructions.  wbinvd itself is serializing
+- * so the processor will not reorder.
+- *
+- * Systems without cache can just go into halt.
+- */
+-static inline void wbinvd_halt(void)
+-{
+-	mb();
+-	/* check for clflush to determine if wbinvd is legal */
+-	if (cpu_has_clflush)
+-		asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
+-	else
+-		while (1)
+-			halt();
+-}
+-#endif
+-
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+ 
+--- sle11sp1-2011-01-14.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-11-04 13:20:41.000000000 +0100
++++ sle11sp1-2011-01-14/arch/x86/kernel/apic/io_apic-xen.c	2011-01-14 12:46:27.000000000 +0100
+@@ -3678,6 +3678,7 @@ static int dmar_msi_set_affinity(unsigne
+ 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+ 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
+ 
+ 	dmar_msi_write(irq, &msg);
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-consistent-nmi
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-consistent-nmi
@@ -0,0 +1,247 @@
+From: jbeulich@novell.com
+Subject: make i386 and x86 NMI code consistent, disable all APIC-related stuff
+Patch-mainline: obsolete
+References: 191115
+
+--- head-2009-12-16.orig/arch/x86/include/asm/irq.h	2009-12-16 11:43:33.000000000 +0100
++++ head-2009-12-16/arch/x86/include/asm/irq.h	2009-10-13 17:07:27.000000000 +0200
+@@ -15,7 +15,7 @@ static inline int irq_canonicalize(int i
+ 	return ((irq == 2) ? 9 : irq);
+ }
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ # define ARCH_HAS_NMI_WATCHDOG
+ #endif
+ 
+--- head-2009-12-16.orig/arch/x86/include/asm/nmi.h	2009-12-16 11:43:33.000000000 +0100
++++ head-2009-12-16/arch/x86/include/asm/nmi.h	2009-10-13 17:07:27.000000000 +0200
+@@ -5,8 +5,6 @@
+ #include <asm/irq.h>
+ #include <asm/io.h>
+ 
+-#ifdef ARCH_HAS_NMI_WATCHDOG
+-
+ /**
+  * do_nmi_callback
+  *
+@@ -16,6 +14,11 @@
+ int do_nmi_callback(struct pt_regs *regs, int cpu);
+ 
+ extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
++
++extern int unknown_nmi_panic;
++
++#ifdef ARCH_HAS_NMI_WATCHDOG
++
+ extern int check_nmi_watchdog(void);
+ extern int nmi_watchdog_enabled;
+ extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+@@ -42,7 +45,6 @@ extern unsigned int nmi_watchdog;
+ struct ctl_table;
+ extern int proc_nmi_enabled(struct ctl_table *, int ,
+ 			void __user *, size_t *, loff_t *);
+-extern int unknown_nmi_panic;
+ 
+ void arch_trigger_all_cpu_backtrace(void);
+ #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
+@@ -65,7 +67,6 @@ static inline int nmi_watchdog_active(vo
+ 	 */
+ 	return nmi_watchdog & (NMI_LOCAL_APIC | NMI_IO_APIC);
+ }
+-#endif
+ 
+ void lapic_watchdog_stop(void);
+ int lapic_watchdog_init(unsigned nmi_hz);
+@@ -73,6 +74,9 @@ int lapic_wd_event(unsigned nmi_hz);
+ unsigned lapic_adjust_nmi_hz(unsigned hz);
+ void disable_lapic_nmi_watchdog(void);
+ void enable_lapic_nmi_watchdog(void);
++
++#endif
++
+ void stop_nmi(void);
+ void restart_nmi(void);
+ 
+--- head-2009-12-16.orig/arch/x86/kernel/apic/Makefile	2009-11-06 10:52:02.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/apic/Makefile	2009-10-13 17:07:27.000000000 +0200
+@@ -18,8 +18,6 @@ obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
+ obj-$(CONFIG_X86_ES7000)	+= es7000_32.o
+ obj-$(CONFIG_X86_SUMMIT)	+= summit_32.o
+ 
+-obj-$(CONFIG_XEN)		+= nmi.o
+-
+ probe_64-$(CONFIG_XEN)		:= probe_32.o
+ 
+ disabled-obj-$(CONFIG_XEN)	:= apic_flat_$(BITS).o
+--- head-2009-12-16.orig/arch/x86/kernel/apic/nmi.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/apic/nmi.c	2009-10-13 17:18:34.000000000 +0200
+@@ -27,8 +27,10 @@
+ #include <linux/kdebug.h>
+ #include <linux/smp.h>
+ 
+-#ifndef CONFIG_XEN
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ #include <asm/i8259.h>
++#else
++#include <asm/nmi.h>
+ #endif
+ #include <asm/io_apic.h>
+ #include <asm/proto.h>
+@@ -39,6 +41,9 @@
+ #include <asm/mach_traps.h>
+ 
+ int unknown_nmi_panic;
++
++#ifdef ARCH_HAS_NMI_WATCHDOG
++
+ int nmi_watchdog_enabled;
+ 
+ static cpumask_t backtrace_mask __read_mostly;
+@@ -176,13 +181,11 @@ int __init check_nmi_watchdog(void)
+ 	kfree(prev_nmi_count);
+ 	return 0;
+ error:
+-#ifndef CONFIG_XEN
+ 	if (nmi_watchdog == NMI_IO_APIC) {
+ 		if (!timer_through_8259)
+ 			disable_8259A_irq(0);
+ 		on_each_cpu(__acpi_nmi_disable, NULL, 1);
+ 	}
+-#endif
+ 
+ #ifdef CONFIG_X86_32
+ 	timer_ack = 0;
+@@ -472,8 +475,11 @@ nmi_watchdog_tick(struct pt_regs *regs, 
+ 	return rc;
+ }
+ 
++#endif /* ARCH_HAS_NMI_WATCHDOG */
++
+ #ifdef CONFIG_SYSCTL
+ 
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ static void enable_ioapic_nmi_watchdog_single(void *unused)
+ {
+ 	__get_cpu_var(wd_enabled) = 1;
+@@ -491,6 +497,7 @@ static void disable_ioapic_nmi_watchdog(
+ {
+ 	on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
+ }
++#endif
+ 
+ static int __init setup_unknown_nmi_panic(char *str)
+ {
+@@ -509,6 +516,7 @@ static int unknown_nmi_panic_callback(st
+ 	return 0;
+ }
+ 
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ /*
+  * proc handler for /proc/sys/kernel/nmi
+  */
+@@ -546,6 +554,7 @@ int proc_nmi_enabled(struct ctl_table *t
+ 	}
+ 	return 0;
+ }
++#endif
+ 
+ #endif /* CONFIG_SYSCTL */
+ 
+@@ -558,6 +567,7 @@ int do_nmi_callback(struct pt_regs *regs
+ 	return 0;
+ }
+ 
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ void arch_trigger_all_cpu_backtrace(void)
+ {
+ 	int i;
+@@ -574,3 +584,4 @@ void arch_trigger_all_cpu_backtrace(void
+ 		mdelay(1);
+ 	}
+ }
++#endif
+--- head-2009-12-16.orig/arch/x86/kernel/cpu/Makefile	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/cpu/Makefile	2009-10-13 17:17:07.000000000 +0200
+@@ -35,7 +35,7 @@ obj-$(CONFIG_CPU_FREQ)			+= cpufreq/
+ 
+ obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
+ 
+-disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o
++disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o perfctr-watchdog.o
+ 
+ quiet_cmd_mkcapflags = MKCAP   $@
+       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
+--- head-2009-12-16.orig/arch/x86/kernel/head-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/head-xen.c	2009-10-15 15:32:46.000000000 +0200
+@@ -179,12 +179,10 @@ void __init xen_arch_setup(void)
+ 		.address = CALLBACK_ADDR(system_call)
+ 	};
+ #endif
+-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+ 	static const struct callback_register __initconst nmi_cb = {
+ 		.type = CALLBACKTYPE_nmi,
+ 		.address = CALLBACK_ADDR(nmi)
+ 	};
+-#endif
+ 
+ 	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+ 	if (ret == 0)
+@@ -208,7 +206,6 @@ void __init xen_arch_setup(void)
+ #endif
+ 	BUG_ON(ret);
+ 
+-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+ 	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ 	if (ret == -ENOSYS) {
+@@ -219,6 +216,5 @@ void __init xen_arch_setup(void)
+ 		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+ 	}
+ #endif
+-#endif
+ }
+ #endif /* CONFIG_XEN */
+--- head-2009-12-16.orig/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/traps-xen.c	2009-10-14 17:26:48.000000000 +0200
+@@ -51,6 +51,7 @@
+ #include <asm/atomic.h>
+ #include <asm/system.h>
+ #include <asm/traps.h>
++#include <asm/nmi.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+ #include <asm/mce.h>
+@@ -394,12 +395,14 @@ static notrace __kprobes void default_do
+ 								== NOTIFY_STOP)
+ 			return;
+ #ifdef CONFIG_X86_LOCAL_APIC
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ 		/*
+ 		 * Ok, so this is none of the documented NMI sources,
+ 		 * so it must be the NMI watchdog.
+ 		 */
+ 		if (nmi_watchdog_tick(regs, reason))
+ 			return;
++#endif
+ 		if (!do_nmi_callback(regs, cpu))
+ 			unknown_nmi_error(reason, regs);
+ #else
+--- head-2009-12-16.orig/kernel/sysctl.c	2009-12-16 11:47:57.000000000 +0100
++++ head-2009-12-16/kernel/sysctl.c	2009-12-16 12:15:35.000000000 +0100
+@@ -790,6 +790,7 @@ static struct ctl_table kern_table[] = {
+ 		.mode           = 0644,
+ 		.proc_handler   = &proc_dointvec,
+ 	},
++#ifdef ARCH_HAS_NMI_WATCHDOG
+ 	{
+ 		.procname       = "nmi_watchdog",
+ 		.data           = &nmi_watchdog_enabled,
+@@ -798,6 +799,7 @@ static struct ctl_table kern_table[] = {
+ 		.proc_handler   = &proc_nmi_enabled,
+ 	},
+ #endif
++#endif
+ #if defined(CONFIG_X86)
+ 	{
+ 		.ctl_name	= KERN_PANIC_ON_NMI,
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-blkif-protocol-fallback-hack
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-blkif-protocol-fallback-hack
@@ -0,0 +1,219 @@
+Subject: 32-on-64 blkif protocol negotiation fallback for old guests.
+From: kraxel@suse.de
+References: 244055
+Patch-mainline: never.
+
+See the comment below.  Oh well.
+
+--- head-2010-01-04.orig/drivers/xen/Kconfig	2009-12-18 12:27:52.000000000 +0100
++++ head-2010-01-04/drivers/xen/Kconfig	2009-12-18 12:30:34.000000000 +0100
+@@ -28,6 +28,9 @@ config XEN_PRIVCMD
+ 	def_bool y
+ 	depends on PROC_FS
+ 
++config XEN_DOMCTL
++	tristate
++
+ config XEN_XENBUS_DEV
+ 	def_bool y
+ 	depends on PROC_FS
+@@ -47,6 +50,7 @@ config XEN_BLKDEV_BACKEND
+ 	tristate "Block-device backend driver"
+         depends on XEN_BACKEND
+ 	default XEN_BACKEND
++	select XEN_DOMCTL
+ 	help
+ 	  The block-device backend driver allows the kernel to export its
+ 	  block devices to other guests via a high-performance shared-memory
+@@ -56,6 +60,7 @@ config XEN_BLKDEV_TAP
+ 	tristate "Block-device tap backend driver"
+ 	depends on XEN_BACKEND
+ 	default XEN_BACKEND
++	select XEN_DOMCTL
+ 	help
+ 	  The block tap driver is an alternative to the block back driver
+ 	  and allows VM block requests to be redirected to userspace through
+--- head-2010-01-04.orig/drivers/xen/blkback/xenbus.c	2008-09-15 15:10:36.000000000 +0200
++++ head-2010-01-04/drivers/xen/blkback/xenbus.c	2008-09-15 15:10:39.000000000 +0200
+@@ -21,6 +21,7 @@
+ #include <linux/module.h>
+ #include <linux/kthread.h>
+ #include "common.h"
++#include "../core/domctl.h"
+ 
+ #undef DPRINTK
+ #define DPRINTK(fmt, args...)				\
+@@ -488,8 +489,10 @@ static int connect_ring(struct backend_i
+ 	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ 	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+ 			    "%63s", protocol, NULL);
+-	if (err)
+-		strcpy(protocol, "unspecified, assuming native");
++	if (err) {
++		strcpy(protocol, "unspecified");
++		be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
++	}
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+--- head-2010-01-04.orig/drivers/xen/blktap/xenbus.c	2008-09-15 15:10:36.000000000 +0200
++++ head-2010-01-04/drivers/xen/blktap/xenbus.c	2008-09-15 15:10:39.000000000 +0200
+@@ -39,6 +39,7 @@
+ #include <linux/kthread.h>
+ #include <xen/xenbus.h>
+ #include "common.h"
++#include "../core/domctl.h"
+ 
+ 
+ struct backend_info
+@@ -426,8 +427,10 @@ static int connect_ring(struct backend_i
+ 	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ 	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
+ 			    "%63s", protocol, NULL);
+-	if (err)
+-		strcpy(protocol, "unspecified, assuming native");
++	if (err) {
++		strcpy(protocol, "unspecified");
++		be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
++	}
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
+--- head-2010-01-04.orig/drivers/xen/core/Makefile	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/Makefile	2010-01-04 16:17:00.000000000 +0100
+@@ -12,4 +12,7 @@ obj-$(CONFIG_XEN_SYSFS)		+= xen_sysfs.o
+ obj-$(CONFIG_XEN_SMPBOOT)	+= smpboot.o
+ obj-$(CONFIG_SMP)		+= spinlock.o
+ obj-$(CONFIG_KEXEC)		+= machine_kexec.o
++obj-$(CONFIG_XEN_DOMCTL)	+= domctl.o
++CFLAGS_domctl.o			:= -D__XEN_PUBLIC_XEN_H__ -D__XEN_PUBLIC_GRANT_TABLE_H__
++CFLAGS_domctl.o			+= -D__XEN_TOOLS__ -imacros xen/interface/domctl.h
+ obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-04/drivers/xen/core/domctl.c	2010-01-04 16:15:58.000000000 +0100
+@@ -0,0 +1,120 @@
++/*
++ * !!!  dirty hack alert  !!!
++ *
++ * Problem: old guests kernels don't have a "protocol" node
++ *          in the frontend xenstore directory, so mixing
++ *          32 and 64bit domains doesn't work.
++ *
++ * Upstream plans to solve this in the tools, by letting them
++ * create a protocol node.  Which certainly makes sense.
++ * But it isn't trivial and isn't done yet.  Too bad.
++ *
++ * So for the time being we use the get_address_size domctl
++ * hypercall for a pretty good guess.  Not nice as the domctl
++ * hypercall isn't supposed to be used by the kernel.  Because
++ * we don't want to have dependencies between dom0 kernel and
++ * xen kernel versions.  Now we have one.  Ouch.
++ */
++#undef __XEN_PUBLIC_XEN_H__
++#undef __XEN_PUBLIC_GRANT_TABLE_H__
++#undef __XEN_TOOLS__
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <asm/hypervisor.h>
++#include <xen/blkif.h>
++
++#include "domctl.h"
++
++/* stuff copied from xen/interface/domctl.h, which we can't
++ * include directly for the reasons outlined above .... */
++
++typedef struct xen_domctl_address_size {
++	uint32_t size;
++} xen_domctl_address_size_t;
++
++typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t;
++
++union xen_domctl {
++	/* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */
++	struct {
++		uint32_t cmd;
++		uint32_t interface_version;
++		domid_t  domain;
++		union {
++			/* left out lots of other struct xen_domctl_foobar */
++			struct xen_domctl_address_size       address_size;
++			uint64_t                             dummy_align;
++			uint8_t                              dummy_pad[128];
++		};
++	} v4;
++
++	/* v5: upstream: xen 3.1, v6: upstream: xen 4.0 */
++	struct {
++		uint32_t cmd;
++		uint32_t interface_version;
++		domid_t  domain;
++		union {
++			struct xen_domctl_address_size       address_size;
++			uint64_aligned_t                     dummy_align;
++			uint8_t                              dummy_pad[128];
++		};
++	} v5, v6;
++};
++
++/* The actual code comes here */
++
++static inline int hypervisor_domctl(void *domctl)
++{
++	return _hypercall1(int, domctl, domctl);
++}
++
++int xen_guest_address_size(int domid)
++{
++	union xen_domctl domctl;
++	int low, ret;
++
++#define guest_address_size(ver) do {					\
++	memset(&domctl, 0, sizeof(domctl));				\
++	domctl.v##ver.cmd = XEN_DOMCTL_get_address_size;		\
++	domctl.v##ver.interface_version = low = ver;			\
++	domctl.v##ver.domain = domid;					\
++	ret = hypervisor_domctl(&domctl) ?: domctl.v##ver.address_size.size; \
++	if (ret == 32 || ret == 64) {					\
++		printk("v" #ver " domctl worked ok: dom%d is %d-bit\n",	\
++		       domid, ret);					\
++		return ret;						\
++	}								\
++} while (0)
++
++	BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6);
++	guest_address_size(6);
++#if CONFIG_XEN_COMPAT < 0x040000
++	guest_address_size(5);
++#endif
++#if CONFIG_XEN_COMPAT < 0x030100
++	guest_address_size(4);
++#endif
++
++	ret = BITS_PER_LONG;
++	printk("v%d...6 domctls failed, assuming dom%d is native: %d\n",
++	       low, domid, ret);
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(xen_guest_address_size);
++
++int xen_guest_blkif_protocol(int domid)
++{
++	int address_size = xen_guest_address_size(domid);
++
++	if (address_size == BITS_PER_LONG)
++		return BLKIF_PROTOCOL_NATIVE;
++	if (address_size == 32)
++		return BLKIF_PROTOCOL_X86_32;
++	if (address_size == 64)
++		return BLKIF_PROTOCOL_X86_64;
++	return BLKIF_PROTOCOL_NATIVE;
++}
++EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol);
++
++MODULE_LICENSE("GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-04/drivers/xen/core/domctl.h	2008-09-15 15:10:39.000000000 +0200
+@@ -0,0 +1,2 @@
++int xen_guest_address_size(int domid);
++int xen_guest_blkif_protocol(int domid);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-op-packet
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-op-packet
@@ -0,0 +1,190 @@
+From: plc@novell.com
+Subject: add support for new operation type BLKIF_OP_PACKET
+Patch-mainline: obsolete
+References: fate#300964
+
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2010-01-04 12:41:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 13:29:53.000000000 +0100
+@@ -195,13 +195,15 @@ static void fast_flush_area(pending_req_
+ 
+ static void print_stats(blkif_t *blkif)
+ {
+-	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d  |  br %4d\n",
++	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d  |  br %4d |  pk %4d\n",
+ 	       current->comm, blkif->st_oo_req,
+-	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req);
++	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req,
++	       blkif->st_pk_req);
+ 	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
+ 	blkif->st_rd_req = 0;
+ 	blkif->st_wr_req = 0;
+ 	blkif->st_oo_req = 0;
++	blkif->st_pk_req = 0;
+ }
+ 
+ int blkif_schedule(void *arg)
+@@ -371,6 +373,13 @@ handle_request:
+ 			blkif->st_wr_req++;
+ 			ret = dispatch_rw_block_io(blkif, &req, pending_req);
+ 			break;
++		case BLKIF_OP_PACKET:
++			DPRINTK("error: block operation BLKIF_OP_PACKET not implemented\n");
++			blkif->st_pk_req++;
++			make_response(blkif, req.id, req.operation,
++				      BLKIF_RSP_ERROR);
++			free_req(pending_req);
++			break;
+ 		default:
+ 			/* A good sign something is wrong: sleep for a while to
+ 			 * avoid excessive CPU consumption by a bad guest. */
+--- head-2010-01-18.orig/drivers/xen/blkback/common.h	2010-01-04 13:22:13.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/common.h	2010-01-04 13:22:59.000000000 +0100
+@@ -91,6 +91,7 @@ typedef struct blkif_st {
+ 	int                 st_wr_req;
+ 	int                 st_oo_req;
+ 	int                 st_br_req;
++	int                 st_pk_req;
+ 	int                 st_rd_sect;
+ 	int                 st_wr_sect;
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:54:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 17:06:03.000000000 +0100
+@@ -653,6 +653,8 @@ static int blkif_queue_request(struct re
+ 		BLKIF_OP_WRITE : BLKIF_OP_READ;
+ 	if (blk_barrier_rq(req))
+ 		ring_req->operation = BLKIF_OP_WRITE_BARRIER;
++	if (blk_pc_request(req))
++		ring_req->operation = BLKIF_OP_PACKET;
+ 
+ 	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+ 	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+@@ -710,7 +712,7 @@ void do_blkif_request(struct request_que
+ 
+ 		blk_start_request(req);
+ 
+-		if (!blk_fs_request(req)) {
++		if (!blk_fs_request(req) && !blk_pc_request(req)) {
+ 			__blk_end_request_all(req, -EIO);
+ 			continue;
+ 		}
+@@ -781,6 +783,7 @@ static irqreturn_t blkif_int(int irq, vo
+ 			/* fall through */
+ 		case BLKIF_OP_READ:
+ 		case BLKIF_OP_WRITE:
++		case BLKIF_OP_PACKET:
+ 			if (unlikely(bret->status != BLKIF_RSP_OKAY))
+ 				DPRINTK("Bad return from blkdev data "
+ 					"request: %x\n", bret->status);
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2010-01-04 13:22:24.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 13:22:46.000000000 +0100
+@@ -1134,13 +1134,14 @@ static void fast_flush_area(pending_req_
+ 
+ static void print_stats(blkif_t *blkif)
+ {
+-	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d\n",
++	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d |  pk %4d\n",
+ 	       current->comm, blkif->st_oo_req,
+-	       blkif->st_rd_req, blkif->st_wr_req);
++	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_pk_req);
+ 	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
+ 	blkif->st_rd_req = 0;
+ 	blkif->st_wr_req = 0;
+ 	blkif->st_oo_req = 0;
++	blkif->st_pk_req = 0;
+ }
+ 
+ int tap_blkif_schedule(void *arg)
+@@ -1374,6 +1375,11 @@ static int do_block_io_op(blkif_t *blkif
+ 			dispatch_rw_block_io(blkif, &req, pending_req);
+ 			break;
+ 
++		case BLKIF_OP_PACKET:
++			blkif->st_pk_req++;
++			dispatch_rw_block_io(blkif, &req, pending_req);
++			break;
++
+ 		default:
+ 			/* A good sign something is wrong: sleep for a while to
+ 			 * avoid excessive CPU consumption by a bad guest. */
+@@ -1413,6 +1419,8 @@ static void dispatch_rw_block_io(blkif_t
+ 	struct vm_area_struct *vma = NULL;
+ 
+ 	switch (req->operation) {
++	case BLKIF_OP_PACKET:
++		/* Fall through */
+ 	case BLKIF_OP_READ:
+ 		operation = READ;
+ 		break;
+--- head-2010-01-18.orig/drivers/xen/blktap/common.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/common.h	2009-07-29 10:18:11.000000000 +0200
+@@ -75,6 +75,7 @@ typedef struct blkif_st {
+ 	int                 st_rd_req;
+ 	int                 st_wr_req;
+ 	int                 st_oo_req;
++	int                 st_pk_req;
+ 	int                 st_rd_sect;
+ 	int                 st_wr_sect;
+ 
+--- head-2010-01-18.orig/drivers/xen/blktap2/blktap.h	2009-12-16 11:51:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/blktap.h	2009-12-16 12:14:37.000000000 +0100
+@@ -137,6 +137,7 @@ struct blktap_statistics {
+ 	int                            st_rd_req;
+ 	int                            st_wr_req;
+ 	int                            st_oo_req;
++	int                            st_pk_req;
+ 	int                            st_rd_sect;
+ 	int                            st_wr_sect;
+ 	s64                            st_rd_cnt;
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2010-01-04 13:22:52.000000000 +0100
+@@ -369,7 +369,8 @@ blktap_device_fail_pending_requests(stru
+ 
+ 		BTERR("%u:%u: failing pending %s of %d pages\n",
+ 		      blktap_device_major, tap->minor,
+-		      (request->operation == BLKIF_OP_READ ?
++		      (request->operation == BLKIF_OP_PACKET ?
++		       "packet" : request->operation == BLKIF_OP_READ ?
+ 		       "read" : "write"), request->nr_pages);
+ 
+ 		blktap_unmap(tap, request);
+@@ -410,6 +411,7 @@ blktap_device_finish_request(struct blkt
+ 	switch (request->operation) {
+ 	case BLKIF_OP_READ:
+ 	case BLKIF_OP_WRITE:
++	case BLKIF_OP_PACKET:
+ 		if (unlikely(res->status != BLKIF_RSP_OKAY))
+ 			BTERR("Bad return from device data "
+ 				"request: %x\n", res->status);
+@@ -648,6 +650,8 @@ blktap_device_process_request(struct blk
+ 	blkif_req.handle = 0;
+ 	blkif_req.operation = rq_data_dir(req) ?
+ 		BLKIF_OP_WRITE : BLKIF_OP_READ;
++	if (unlikely(blk_pc_request(req)))
++		blkif_req.operation = BLKIF_OP_PACKET;
+ 
+ 	request->id        = (unsigned long)req;
+ 	request->operation = blkif_req.operation;
+@@ -713,7 +717,9 @@ blktap_device_process_request(struct blk
+ 	wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
+ 	ring->ring.req_prod_pvt++;
+ 
+-	if (rq_data_dir(req)) {
++	if (unlikely(blk_pc_request(req)))
++		tap->stats.st_pk_req++;
++	else if (rq_data_dir(req)) {
+ 		tap->stats.st_wr_sect += nr_sects;
+ 		tap->stats.st_wr_req++;
+ 	} else {
+--- head-2010-01-18.orig/include/xen/interface/io/blkif.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/io/blkif.h	2009-07-29 10:18:11.000000000 +0200
+@@ -76,6 +76,10 @@
+  * "feature-flush-cache" node!
+  */
+ #define BLKIF_OP_FLUSH_DISKCACHE   3
++/*
++ * Device specific command packet contained within the request
++ */
++#define BLKIF_OP_PACKET            4
+ 
+ /*
+  * Maximum scatter/gather segments per request.
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.25-26
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.25-26
@@ -0,0 +1,92 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.26
+Patch-mainline: 2.6.32.26
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Automatically created from "patches.kernel.org/patch-2.6.32.25-26" by xen-port-patches.py
+
+--- sle11sp1-2010-11-30.orig/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-11-30/arch/x86/include/mach-xen/asm/io.h	2010-11-30 11:06:49.000000000 +0100
+@@ -180,6 +180,7 @@ static inline void __iomem *ioremap(reso
+ 
+ extern void iounmap(volatile void __iomem *addr);
+ 
++extern void set_iounmap_nonlazy(void);
+ 
+ #ifdef CONFIG_X86_32
+ # include "../../asm/io_32.h"
+--- sle11sp1-2010-11-30.orig/arch/x86/include/mach-xen/asm/smp.h	2010-04-26 11:32:06.000000000 +0200
++++ sle11sp1-2010-11-30/arch/x86/include/mach-xen/asm/smp.h	2010-11-30 11:06:49.000000000 +0100
+@@ -54,7 +54,7 @@ struct smp_ops {
+ 	void (*smp_prepare_cpus)(unsigned max_cpus);
+ 	void (*smp_cpus_done)(unsigned max_cpus);
+ 
+-	void (*smp_send_stop)(void);
++	void (*stop_other_cpus)(int wait);
+ 	void (*smp_send_reschedule)(int cpu);
+ 
+ 	int (*cpu_up)(unsigned cpu);
+@@ -73,7 +73,12 @@ extern struct smp_ops smp_ops;
+ 
+ static inline void smp_send_stop(void)
+ {
+-	smp_ops.smp_send_stop();
++	smp_ops.stop_other_cpus(0);
++}
++
++static inline void stop_other_cpus(void)
++{
++	smp_ops.stop_other_cpus(1);
+ }
+ 
+ static inline void smp_prepare_boot_cpu(void)
+@@ -142,12 +147,16 @@ int wbinvd_on_all_cpus(void);
+ 
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+-void xen_smp_send_stop(void);
++void xen_stop_other_cpus(int wait);
+ void xen_smp_send_reschedule(int cpu);
+ void xen_send_call_func_ipi(const struct cpumask *mask);
+ void xen_send_call_func_single_ipi(int cpu);
+ 
+-#define smp_send_stop		xen_smp_send_stop
++static inline void smp_send_stop(void)
++{
++	xen_stop_other_cpus(0);
++}
++
+ #define smp_send_reschedule	xen_smp_send_reschedule
+ #define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
+ #define arch_send_call_function_ipi_mask	xen_send_call_func_ipi
+--- sle11sp1-2010-11-30.orig/arch/x86/kernel/smp-xen.c	2010-08-17 12:18:28.000000000 +0200
++++ sle11sp1-2010-11-30/arch/x86/kernel/smp-xen.c	2010-11-30 11:06:49.000000000 +0100
+@@ -142,10 +142,10 @@ irqreturn_t smp_reboot_interrupt(int irq
+ 	return IRQ_HANDLED;
+ }
+ 
+-void xen_smp_send_stop(void)
++void xen_stop_other_cpus(int wait)
+ {
+ 	unsigned long flags;
+-	unsigned long wait;
++	unsigned long timeout;
+ 
+ 	/*
+ 	 * Use an own vector here because smp_call_function
+@@ -159,9 +159,12 @@ void xen_smp_send_stop(void)
+ 	if (num_online_cpus() > 1) {
+ 		xen_send_IPI_allbutself(REBOOT_VECTOR);
+ 
+-		/* Don't wait longer than a second */
+-		wait = USEC_PER_SEC;
+-		while (num_online_cpus() > 1 && wait--)
++		/*
++		 * Don't wait longer than a second if the caller
++		 * didn't ask us to wait.
++		 */
++		timeout = USEC_PER_SEC;
++		while (num_online_cpus() > 1 && (wait || timeout--))
+ 			udelay(1);
+ 	}
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-arch-x86.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-arch-x86.diff
@@ -0,0 +1,436 @@
+Subject: xen3 arch-x86
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+List of files that don't require modification anymore (and hence
+removed from this patch), for reference and in case upstream wants to
+take the forward porting patches:
+2.6.26/arch/x86/kernel/crash.c
+2.6.30/arch/x86/kernel/acpi/boot.c
+
+---
+ arch/x86/Makefile                   |   24 +++++++++++++++++++++++-
+ arch/x86/boot/Makefile              |    9 +++++++++
+ arch/x86/include/asm/acpi.h         |   27 +++++++++++++++++++++++++++
+ arch/x86/include/asm/apic.h         |    2 ++
+ arch/x86/include/asm/kexec.h        |   13 +++++++++++++
+ arch/x86/kernel/Makefile            |    9 +++++++++
+ arch/x86/kernel/acpi/Makefile       |    4 ++++
+ arch/x86/kernel/acpi/processor.c    |   11 +++++++++++
+ arch/x86/kernel/cpu/mcheck/Makefile |    1 +
+ arch/x86/kernel/cpu/mcheck/mce.c    |   21 +++++++++++++++++++++
+ arch/x86/kernel/cpu/mtrr/Makefile   |    1 +
+ arch/x86/lib/Makefile               |    2 ++
+ arch/x86/mm/Makefile                |    2 ++
+ arch/x86/oprofile/Makefile          |    7 +++++++
+ arch/x86/pci/Makefile               |    3 +++
+ arch/x86/power/cpu.c                |    4 ++++
+ 16 files changed, 139 insertions(+), 1 deletion(-)
+
+Index: linux-2.6.32-master/arch/x86/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/Makefile
++++ linux-2.6.32-master/arch/x86/Makefile
+@@ -111,6 +111,10 @@ endif
+ # prevent gcc from generating any FP code by mistake
+ KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+ 
++# Xen subarch support
++mflags-$(CONFIG_X86_XEN)	:= -Iinclude/asm-x86/mach-xen
++mcore-$(CONFIG_X86_XEN)		:= arch/x86/mach-xen/
++
+ KBUILD_CFLAGS += $(mflags-y)
+ KBUILD_AFLAGS += $(mflags-y)
+ 
+@@ -151,9 +155,26 @@ boot := arch/x86/boot
+ 
+ BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage
+ 
+-PHONY += bzImage $(BOOT_TARGETS)
++PHONY += bzImage vmlinuz $(BOOT_TARGETS)
++
++ifdef CONFIG_XEN
++CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
++	-Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
++
++ifdef CONFIG_X86_64
++LDFLAGS_vmlinux := -e startup_64
++endif
+ 
+ # Default kernel to build
++all: vmlinuz
++
++# KBUILD_IMAGE specifies the target image being built
++KBUILD_IMAGE := $(boot)/vmlinuz
++
++vmlinuz: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
++else
++# Default kernel to build
+ all: bzImage
+ 
+ # KBUILD_IMAGE specify target image being built
+@@ -166,6 +187,7 @@ bzImage: vmlinux
+ 
+ $(BOOT_TARGETS): vmlinux
+ 	$(Q)$(MAKE) $(build)=$(boot) $@
++endif
+ 
+ PHONY += install
+ install:
+Index: linux-2.6.32-master/arch/x86/boot/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/boot/Makefile
++++ linux-2.6.32-master/arch/x86/boot/Makefile
+@@ -23,6 +23,7 @@ ROOT_DEV	:= CURRENT
+ SVGA_MODE	:= -DSVGA_MODE=NORMAL_VGA
+ 
+ targets		:= vmlinux.bin setup.bin setup.elf bzImage
++targets		+= vmlinuz vmlinux-stripped
+ targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
+ subdir-		:= compressed
+ 
+@@ -195,6 +196,14 @@ bzlilo: $(obj)/bzImage
+ 	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) $(obj)/bzImage \
+ 		System.map "$(INSTALL_PATH)"
+Index: linux-2.6.32-master/arch/x86/kernel/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/Makefile
++++ linux-2.6.32-master/arch/x86/kernel/Makefile
+@@ -117,9 +117,12 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) 
+ 
+ obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
+ 
++obj-$(CONFIG_X86_XEN)		+= fixup.o
++
+ ###
+ # 64 bit specific files
+ ifeq ($(CONFIG_X86_64),y)
++	obj-$(CONFIG_X86_XEN_GENAPIC)	+= genapic_xen_64.o
+ 	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+ 	obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
+ 	obj-$(CONFIG_AUDIT)		+= audit_64.o
+@@ -130,4 +133,10 @@ ifeq ($(CONFIG_X86_64),y)
+ 
+ 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+ 	obj-y				+= vsmp_64.o
++
++	time_64-$(CONFIG_XEN)		+= time_32.o
++	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
++
++disabled-obj-$(CONFIG_XEN) := i8259_$(BITS).o reboot.o smpboot_$(BITS).o
++%/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+Index: linux-2.6.32-master/arch/x86/kernel/acpi/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/acpi/Makefile
++++ linux-2.6.32-master/arch/x86/kernel/acpi/Makefile
+@@ -5,6 +5,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
+ 
+ $(obj)/wakeup_rm.o:    $(obj)/realmode/wakeup.bin
+@@ -12,3 +15,4 @@ $(obj)/wakeup_rm.o:    $(obj)/realmode/w
+ $(obj)/realmode/wakeup.bin: FORCE
+ 	$(Q)$(MAKE) $(build)=$(obj)/realmode
+ 
++disabled-obj-$(CONFIG_XEN)	:= cstate.o wakeup_$(BITS).o
+Index: linux-2.6.32-master/arch/x86/kernel/acpi/processor.c
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/acpi/processor.c
++++ linux-2.6.32-master/arch/x86/kernel/acpi/processor.c
+@@ -76,7 +76,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.
++	 */
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++#else
+ 	struct cpuinfo_x86 *c = &cpu_data(pr->id);
++#endif
+ 
+ 	pr->pdc = NULL;
+ 	if (c->x86_vendor == X86_VENDOR_INTEL ||
+Index: linux-2.6.32-master/arch/x86/kernel/cpu/mcheck/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/cpu/mcheck/Makefile
++++ linux-2.6.32-master/arch/x86/kernel/cpu/mcheck/Makefile
+@@ -4,6 +4,7 @@ obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip
+ obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
+ obj-$(CONFIG_X86_MCE_XEON75XX)	+= mce-xeon75xx.o
+ obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd.o
++obj-$(CONFIG_X86_XEN_MCE)	+= mce_dom0.o
+ obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
+ obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
+ 
+Index: linux-2.6.32-master/arch/x86/kernel/cpu/mcheck/mce.c
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/cpu/mcheck/mce.c
++++ linux-2.6.32-master/arch/x86/kernel/cpu/mcheck/mce.c
+@@ -1127,8 +1127,15 @@ void mce_log_therm_throt_event(__u64 sta
+  * Periodic polling timer for "silent" machine check errors.  If the
+  * poller finds an MCE, poll 2x faster.  When the poller finds no more
+  * errors, poll 2x slower (up to check_interval seconds).
++ *
++ * We will disable polling in DOM0 since all CMCI/Polling
++ * mechanism will be done in XEN for Intel CPUs
+  */
++#if defined (CONFIG_X86_XEN_MCE)
++static int check_interval = 0; /* disable polling */
++#else
+ static int check_interval = 5 * 60; /* 5 minutes */
++#endif
+ 
+ static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */
+ static DEFINE_PER_CPU(struct timer_list, mce_timer);
+@@ -1293,6 +1300,7 @@ static int __cpuinit mce_cpu_quirks(stru
+ 
+ 	/* This should be disabled by the BIOS, but isn't always */
+ 	if (c->x86_vendor == X86_VENDOR_AMD) {
++#ifndef CONFIG_XEN
+ 		if (c->x86 == 15 && banks > 4) {
+ 			/*
+ 			 * disable GART TBL walk error reporting, which
+@@ -1301,6 +1309,7 @@ static int __cpuinit mce_cpu_quirks(stru
+ 			 */
+ 			clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
+ 		}
++#endif
+ 		if (c->x86 <= 17 && mce_bootlog < 0) {
+ 			/*
+ 			 * Lots of broken BIOS around that don't clear them
+@@ -1368,6 +1377,7 @@ static void __cpuinit mce_ancient_init(s
+ 
+ static void mce_cpu_features(struct cpuinfo_x86 *c)
+ {
++#ifndef CONFIG_X86_64_XEN
+ 	switch (c->x86_vendor) {
+ 	case X86_VENDOR_INTEL:
+ 		mce_intel_feature_init(c);
+@@ -1378,6 +1388,7 @@ static void mce_cpu_features(struct cpui
+ 	default:
+ 		break;
+ 	}
++#endif
+ }
+ 
+ static void mce_init_timer(void)
+@@ -2064,6 +2075,16 @@ static __init int mce_init_device(void)
+ 	register_hotcpu_notifier(&mce_cpu_notifier);
+ 	misc_register(&mce_log_device);
+ 
++#ifdef CONFIG_X86_XEN_MCE
++	if (is_initial_xendomain()) {
++		/* Register vIRQ handler for MCE LOG processing */
++		extern void bind_virq_for_mce(void);
++
++		printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n");
++		bind_virq_for_mce();
++	}
++#endif
++
+ 	return err;
+ }
+ 
+Index: linux-2.6.32-master/arch/x86/kernel/cpu/mtrr/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/kernel/cpu/mtrr/Makefile
++++ linux-2.6.32-master/arch/x86/kernel/cpu/mtrr/Makefile
+@@ -1,3 +1,4 @@
+ obj-y		:= main.o if.o generic.o state.o cleanup.o
+ obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o
+ 
++obj-$(CONFIG_XEN) := main.o if.o
+Index: linux-2.6.32-master/arch/x86/lib/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/lib/Makefile
++++ linux-2.6.32-master/arch/x86/lib/Makefile
+@@ -27,3 +27,5 @@ else
+         lib-y += memmove_64.o memset_64.o
+         lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
+ endif
++
++lib-$(CONFIG_XEN_SCRUB_PAGES) += scrub.o
+Index: linux-2.6.32-master/arch/x86/mm/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/mm/Makefile
++++ linux-2.6.32-master/arch/x86/mm/Makefile
+@@ -25,4 +25,6 @@ obj-$(CONFIG_NUMA)		+= numa.o numa_$(BIT
+ obj-$(CONFIG_K8_NUMA)		+= k8topology_64.o
+ obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
+ 
++obj-$(CONFIG_XEN)		+= hypervisor.o
++
+ obj-$(CONFIG_MEMTEST)		+= memtest.o
+Index: linux-2.6.32-master/arch/x86/oprofile/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/oprofile/Makefile
++++ linux-2.6.32-master/arch/x86/oprofile/Makefile
+@@ -6,7 +6,14 @@ DRIVER_OBJS = $(addprefix ../../../drive
+ 		oprofilefs.o oprofile_stats.o  \
+ 		timer_int.o )
+ 
++ifdef CONFIG_XEN
++XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
++			 xenoprofile.o)
++oprofile-y				:= $(DRIVER_OBJS) \
++					   $(XENOPROF_COMMON_OBJS) xenoprof.o
++else
+ oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
+ oprofile-$(CONFIG_X86_LOCAL_APIC) 	+= nmi_int.o op_model_amd.o \
+ 					   op_model_ppro.o op_model_p4.o
+ oprofile-$(CONFIG_X86_IO_APIC)		+= nmi_timer_int.o
++endif
+Index: linux-2.6.32-master/arch/x86/pci/Makefile
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/pci/Makefile
++++ linux-2.6.32-master/arch/x86/pci/Makefile
+@@ -4,6 +4,9 @@ obj-$(CONFIG_PCI_BIOS)		+= pcbios.o
+ obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig_$(BITS).o direct.o mmconfig-shared.o
+ obj-$(CONFIG_PCI_DIRECT)	+= direct.o
+ obj-$(CONFIG_PCI_OLPC)		+= olpc.o
++# pcifront should be after 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
+ 
+ obj-y				+= fixup.o
+ obj-$(CONFIG_ACPI)		+= acpi.o
+Index: linux-2.6.32-master/arch/x86/power/cpu.c
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/power/cpu.c
++++ linux-2.6.32-master/arch/x86/power/cpu.c
+@@ -125,6 +125,7 @@ static void do_fpu_end(void)
+ 
+ static void fix_processor_context(void)
+ {
++#ifndef CONFIG_X86_NO_TSS
+ 	int cpu = smp_processor_id();
+ 	struct tss_struct *t = &per_cpu(init_tss, cpu);
+ 
+@@ -137,7 +138,10 @@ static void fix_processor_context(void)
+ 
+ #ifdef CONFIG_X86_64
+ 	get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
++#endif
++#endif
+ 
++#ifdef CONFIG_X86_64
+ 	syscall_init();				/* This sets MSR_*STAR and related */
+ #endif
+ 	load_TR_desc();				/* This does ltr */
+Index: linux-2.6.32-master/arch/x86/include/asm/acpi.h
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/include/asm/acpi.h
++++ linux-2.6.32-master/arch/x86/include/asm/acpi.h
+@@ -30,6 +30,10 @@
+ #include <asm/mmu.h>
+ #include <asm/mpspec.h>
+ 
++#ifdef CONFIG_XEN
++#include <xen/interface/platform.h>
++#endif
++
+ #define COMPILER_DEPENDENT_INT64   long long
+ #define COMPILER_DEPENDENT_UINT64  unsigned long long
+ 
+@@ -120,6 +124,27 @@ extern unsigned long acpi_wakeup_address
+ /* early initialization routine */
+ extern void acpi_reserve_bootmem(void);
+ 
++#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 */
++
+ /*
+  * Check if the CPU can handle C2 and deeper
+  */
+@@ -152,7 +177,9 @@ static inline void disable_acpi(void) { 
+ 
+ #endif /* !CONFIG_ACPI */
+ 
++#ifndef CONFIG_XEN
+ #define ARCH_HAS_POWER_INIT	1
++#endif
+ 
+ struct bootnode;
+ 
+Index: linux-2.6.32-master/arch/x86/include/asm/apic.h
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/include/asm/apic.h
++++ linux-2.6.32-master/arch/x86/include/asm/apic.h
+@@ -15,7 +15,9 @@
+ #include <asm/system.h>
+ #include <asm/msr.h>
+ 
++#ifndef CONFIG_XEN
+ #define ARCH_APICTIMER_STOPS_ON_C3	1
++#endif
+ 
+ /*
+  * Debugging macros
+Index: linux-2.6.32-master/arch/x86/include/asm/kexec.h
+===================================================================
+--- linux-2.6.32-master.orig/arch/x86/include/asm/kexec.h
++++ linux-2.6.32-master/arch/x86/include/asm/kexec.h
+@@ -163,6 +163,19 @@ struct kimage_arch {
+ };
+ #endif
+ 
++/* Under Xen we need to work with machine addresses. These macros give the
++ * machine address of a certain page to the generic kexec code instead of
++ * the pseudo physical address which would be given by the default macros.
++ */
++
++#ifdef CONFIG_XEN
++#define KEXEC_ARCH_HAS_PAGE_MACROS
++#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
++#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
++#define kexec_virt_to_phys(addr) virt_to_machine(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
++#endif
++
+ #endif /* __ASSEMBLY__ */
+ 
+ #endif /* _ASM_X86_KEXEC_H */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.27
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.27
@@ -0,0 +1,26130 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: [PATCH] Linux: Update to 2.6.27
+Patch-mainline: 2.6.27
+
+ This patch contains the differences between Linux 2.6.26 and 2.6.27.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.27" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:02:02.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:02:09.000000000 +0100
+@@ -755,7 +755,7 @@ config AMD_IOMMU
+ 	bool "AMD IOMMU support"
+ 	select SWIOTLB
+ 	select PCI_MSI
+-	depends on X86_64 && PCI && ACPI
++	depends on X86_64 && PCI && ACPI && !XEN
+ 	---help---
+ 	  With this option you can enable support for AMD IOMMU hardware in
+ 	  your system. An IOMMU is a hardware component which provides
+@@ -1470,7 +1470,7 @@ config MTRR
+ config MTRR_SANITIZER
+ 	def_bool y
+ 	prompt "MTRR cleanup support"
+-	depends on MTRR
++	depends on MTRR && !XEN
+ 	---help---
+ 	  Convert MTRR layout from continuous to discrete, so X drivers can
+ 	  add writeback entries.
+--- head-2010-01-18.orig/arch/x86/Kconfig.debug	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig.debug	2009-11-06 10:51:42.000000000 +0100
+@@ -25,6 +25,7 @@ config STRICT_DEVMEM
+ config X86_VERBOSE_BOOTUP
+ 	bool "Enable verbose x86 bootup info messages"
+ 	default y
++	depends on !XEN
+ 	---help---
+ 	  Enables the informational output from the decompression stage
+ 	  (e.g. bzImage) of the boot. If you disable this you will still
+@@ -185,6 +186,7 @@ config X86_DS_SELFTEST
+ 
+ config HAVE_MMIOTRACE_SUPPORT
+ 	def_bool y
++	depends on !XEN
+ 
+ #
+ # IO delay types:
+--- head-2010-01-18.orig/arch/x86/Makefile	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/Makefile	2009-11-06 10:51:42.000000000 +0100
+@@ -112,8 +112,8 @@ endif
+ KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+ 
+ # Xen subarch support
+-mflags-$(CONFIG_X86_XEN)	:= -Iinclude/asm-x86/mach-xen
+-mcore-$(CONFIG_X86_XEN)		:= arch/x86/mach-xen/
++mflags-$(CONFIG_XEN)		:= -Iinclude/asm-x86/mach-xen
++mcore-$(CONFIG_XEN)		:= arch/x86/mach-xen/
+ 
+ KBUILD_CFLAGS += $(mflags-y)
+ KBUILD_AFLAGS += $(mflags-y)
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:42.000000000 +0100
+@@ -15,6 +15,16 @@
+ #include <asm/irqflags.h>
+ #include <linux/linkage.h>
+ 
++/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
++#include <linux/elf-em.h>
++#define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
++#define __AUDIT_ARCH_LE	   0x40000000
++
++#ifndef CONFIG_AUDITSYSCALL
++#define sysexit_audit int_ret_from_sys_call
++#define sysretl_audit int_ret_from_sys_call
++#endif
++
+ #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+ 
+ 	.macro IA32_ARG_FIXUP noebp=0
+@@ -37,6 +47,11 @@
+ 	movq	%rax,R8(%rsp)
+ 	.endm
+ 
++	/*
++	 * Reload arg registers from stack in case ptrace changed them.
++	 * We don't reload %eax because syscall_trace_enter() returned
++	 * the value it wants us to use in the table lookup.
++	 */
+ 	.macro LOAD_ARGS32 offset
+ 	movl \offset(%rsp),%r11d
+ 	movl \offset+8(%rsp),%r10d
+@@ -46,7 +61,6 @@
+ 	movl \offset+48(%rsp),%edx
+ 	movl \offset+56(%rsp),%esi
+ 	movl \offset+64(%rsp),%edi
+-	movl \offset+72(%rsp),%eax
+ 	.endm
+ 
+ 	.macro CFI_STARTPROC32 simple
+@@ -61,6 +75,19 @@
+ 	CFI_UNDEFINED	r15
+ 	.endm
+ 
++#ifdef CONFIG_PARAVIRT
++ENTRY(native_usergs_sysret32)
++	swapgs
++	sysretl
++ENDPROC(native_usergs_sysret32)
++
++ENTRY(native_irq_enable_sysexit)
++	swapgs
++	sti
++	sysexit
++ENDPROC(native_irq_enable_sysexit)
++#endif
++
+ /*
+  * 32bit SYSENTER instruction entry.
+  *
+@@ -98,7 +125,7 @@ ENTRY(ia32_sysenter_target)
+ 	CFI_RESTORE	rcx
+  	movl	%ebp,%ebp		/* zero extension */
+ 	movl	%eax,%eax
+-	movl	48-THREAD_SIZE+threadinfo_sysenter_return(%rsp),%r10d
++	movl	48-THREAD_SIZE+TI_sysenter_return(%rsp),%r10d
+ 	movl	$__USER32_DS,40(%rsp)
+ 	movq	%rbp,32(%rsp)
+ 	movl	$__USER32_CS,16(%rsp)
+@@ -113,19 +140,75 @@ ENTRY(ia32_sysenter_target)
+  	.quad 1b,ia32_badarg
+  	.previous	
+ 	GET_THREAD_INFO(%r10)
+-	orl    $TS_COMPAT,threadinfo_status(%r10)
+-	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	orl    $TS_COMPAT,TI_status(%r10)
++	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz  sysenter_tracesys
+-sysenter_do_call:	
+ 	cmpl	$(IA32_NR_syscalls-1),%eax
+ 	ja	ia32_badsys
++sysenter_do_call:
+ 	IA32_ARG_FIXUP 1
++sysenter_dispatch:
+ 	call	*ia32_sys_call_table(,%rax,8)
+ 	movq	%rax,RAX-ARGOFFSET(%rsp)
++	GET_THREAD_INFO(%r10)
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	testl	$_TIF_ALLWORK_MASK,TI_flags(%r10)
++	jnz	sysexit_audit
+ 	jmp int_ret_from_sys_call
+ 
++#ifdef CONFIG_AUDITSYSCALL
++	.macro auditsys_entry_common
++	movl %esi,%r9d			/* 6th arg: 4th syscall arg */
++	movl %edx,%r8d			/* 5th arg: 3rd syscall arg */
++	/* (already in %ecx)		   4th arg: 2nd syscall arg */
++	movl %ebx,%edx			/* 3rd arg: 1st syscall arg */
++	movl %eax,%esi			/* 2nd arg: syscall number */
++	movl $AUDIT_ARCH_I386,%edi	/* 1st arg: audit arch */
++	call audit_syscall_entry
++	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall number */
++	cmpl $(IA32_NR_syscalls-1),%eax
++	ja ia32_badsys
++	movl %ebx,%edi			/* reload 1st syscall arg */
++	movl RCX-ARGOFFSET(%rsp),%esi	/* reload 2nd syscall arg */
++	movl RDX-ARGOFFSET(%rsp),%edx	/* reload 3rd syscall arg */
++	movl RSI-ARGOFFSET(%rsp),%ecx	/* reload 4th syscall arg */
++	movl RDI-ARGOFFSET(%rsp),%r8d	/* reload 5th syscall arg */
++	.endm
++
++	.macro auditsys_exit exit,ebpsave=RBP
++	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
++	jnz int_ret_from_sys_call
++	TRACE_IRQS_ON
++	ENABLE_INTERRUPTS(CLBR_NONE)
++	movl %eax,%esi		/* second arg, syscall return value */
++	cmpl $0,%eax		/* is it < 0? */
++	setl %al		/* 1 if so, 0 if not */
++	movzbl %al,%edi		/* zero-extend that into %edi */
++	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
++	call audit_syscall_exit
++	movl \ebpsave-ARGOFFSET(%rsp),%ebp /* reload user register value */
++	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	jmp int_with_check
++	.endm
++
++sysenter_auditsys:
++	auditsys_entry_common
++	movl %ebp,%r9d			/* reload 6th syscall arg */
++	jmp sysenter_dispatch
++
++sysexit_audit:
++	auditsys_exit sysexit_from_sys_call
++#endif
++
+ sysenter_tracesys:
+ 	xchgl	%r9d,%ebp
++#ifdef CONFIG_AUDITSYSCALL
++	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
++	jz	sysenter_auditsys
++#endif
+ 	SAVE_REST
+ 	CLEAR_RREGS
+ 	movq	%r9,R9(%rsp)
+@@ -186,18 +269,38 @@ ENTRY(ia32_cstar_target)
+ 	.quad 1b,ia32_badarg
+ 	.previous	
+ 	GET_THREAD_INFO(%r10)
+-	orl   $TS_COMPAT,threadinfo_status(%r10)
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	orl   $TS_COMPAT,TI_status(%r10)
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz   cstar_tracesys
+ cstar_do_call:	
+ 	cmpl $IA32_NR_syscalls-1,%eax
+ 	ja  ia32_badsys
+ 	IA32_ARG_FIXUP 1
++cstar_dispatch:
+ 	call *ia32_sys_call_table(,%rax,8)
+ 	movq %rax,RAX-ARGOFFSET(%rsp)
++	GET_THREAD_INFO(%r10)
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
++	jnz sysretl_audit
+ 	jmp int_ret_from_sys_call
+ 	
+-cstar_tracesys:	
++#ifdef CONFIG_AUDITSYSCALL
++cstar_auditsys:
++	movl %r9d,R9-ARGOFFSET(%rsp)	/* register to be clobbered by call */
++	auditsys_entry_common
++	movl R9-ARGOFFSET(%rsp),%r9d	/* reload 6th syscall arg */
++	jmp cstar_dispatch
++
++sysretl_audit:
++	auditsys_exit sysretl_from_sys_call, RCX /* user %ebp in RCX slot */
++#endif
++
++cstar_tracesys:
++#ifdef CONFIG_AUDITSYSCALL
++	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
++	jz cstar_auditsys
++#endif
+ 	xchgl %r9d,%ebp
+ 	SAVE_REST
+ 	CLEAR_RREGS
+@@ -263,8 +366,8 @@ ENTRY(ia32_syscall)
+ 	   this could be a problem. */
+ 	SAVE_ARGS 0,0,1
+ 	GET_THREAD_INFO(%r10)
+-	orl   $TS_COMPAT,threadinfo_status(%r10)
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	orl   $TS_COMPAT,TI_status(%r10)
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz ia32_tracesys
+ ia32_do_syscall:	
+ 	cmpl $(IA32_NR_syscalls-1),%eax
+@@ -309,13 +412,11 @@ quiet_ni_syscall:
+ 	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
+ 	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
+ 	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
+-	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx
+ 	PTREGSCALL stub32_execve, sys32_execve, %rcx
+ 	PTREGSCALL stub32_fork, sys_fork, %rdi
+ 	PTREGSCALL stub32_clone, sys32_clone, %rdx
+ 	PTREGSCALL stub32_vfork, sys_vfork, %rdi
+ 	PTREGSCALL stub32_iopl, sys_iopl, %rsi
+-	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
+ 
+ ENTRY(ia32_ptregs_common)
+ 	popq %r11
+@@ -415,7 +516,7 @@ ia32_sys_call_table:
+ 	.quad sys_ssetmask
+ 	.quad sys_setreuid16	/* 70 */
+ 	.quad sys_setregid16
+-	.quad stub32_sigsuspend
++	.quad sys32_sigsuspend
+ 	.quad compat_sys_sigpending
+ 	.quad sys_sethostname
+ 	.quad compat_sys_setrlimit	/* 75 */
+@@ -522,7 +623,7 @@ ia32_sys_call_table:
+ 	.quad sys32_rt_sigpending
+ 	.quad compat_sys_rt_sigtimedwait
+ 	.quad sys32_rt_sigqueueinfo
+-	.quad stub32_rt_sigsuspend
++	.quad sys_rt_sigsuspend
+ 	.quad sys32_pread		/* 180 */
+ 	.quad sys32_pwrite
+ 	.quad sys_chown16
+@@ -670,4 +771,10 @@ ia32_sys_call_table:
+ 	.quad sys32_fallocate
+ 	.quad compat_sys_timerfd_settime	/* 325 */
+ 	.quad compat_sys_timerfd_gettime
++	.quad compat_sys_signalfd4
++	.quad sys_eventfd2
++	.quad sys_epoll_create1
++	.quad sys_dup3			/* 330 */
++	.quad sys_pipe2
++	.quad sys_inotify_init1
+ ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:51:42.000000000 +0100
+@@ -134,9 +134,11 @@ ifeq ($(CONFIG_X86_64),y)
+ 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+ 	obj-y				+= vsmp_64.o
+ 
+-	obj-$(CONFIG_XEN)		+= nmi_64.o
++	obj-$(CONFIG_XEN)		+= nmi.o
+ 	time_64-$(CONFIG_XEN)		+= time_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := crash.o early-quirks.o hpet.o i8253.o i8259_$(BITS).o \
+-	pci-swiotlb_64.o reboot.o smpboot.o tlb_$(BITS).o tsc_$(BITS).o tsc_sync.o vsmp_64.o
++disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
++	i8259.o irqinit_$(BITS).o pci-swiotlb_64.o reboot.o smpboot.o \
++	tlb_$(BITS).o tsc.o tsc_sync.o vsmp_64.o
++disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1300,6 +1300,7 @@ static int __init force_acpi_ht(const st
+ 	return 0;
+ }
+ 
++#ifndef CONFIG_XEN
+ /*
+  * Force ignoring BIOS IRQ0 pin2 override
+  */
+@@ -1317,6 +1318,7 @@ static int __init dmi_ignore_irq0_timer_
+ 	}
+ 	return 0;
+ }
++#endif
+ 
+ static int __init force_acpi_rsdt(const struct dmi_system_id *d)
+ {
+@@ -1521,6 +1523,7 @@ static struct dmi_system_id __initdata a
+ 	{}
+ };
+ 
++#ifndef CONFIG_XEN
+ /* second table for DMI checks that should run after early-quirks */
+ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
+ 	/*
+@@ -1567,6 +1570,7 @@ static struct dmi_system_id __initdata a
+ 	 },
+ 	{}
+ };
++#endif
+ 
+ /*
+  * acpi_boot_table_init() and acpi_boot_init()
+@@ -1651,8 +1655,10 @@ int __init early_acpi_boot_init(void)
+ 
+ int __init acpi_boot_init(void)
+ {
++#ifndef CONFIG_XEN
+ 	/* those are executed after early-quirks are executed */
+ 	dmi_check_system(acpi_dmi_table_late);
++#endif
+ 
+ 	/*
+ 	 * If acpi_disabled, bail out
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -9,6 +9,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
++#include <asm/segment.h>
+ 
+ #include "realmode/wakeup.h"
+ #include "sleep.h"
+@@ -20,7 +21,7 @@ unsigned long acpi_realmode_flags;
+ /* address in low memory of the wakeup routine. */
+ static unsigned long acpi_realmode;
+ 
+-#ifdef CONFIG_64BIT
++#if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
+ static char temp_stack[10240];
+ #endif
+ #endif
+@@ -54,18 +55,27 @@ int acpi_save_state_mem(void)
+ 	header->video_mode = saved_video_mode;
+ 
+ 	header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
++
++	/*
++	 * Set up the wakeup GDT.  We set these up as Big Real Mode,
++	 * that is, with limits set to 4 GB.  At least the Lenovo
++	 * Thinkpad X61 is known to need this for the video BIOS
++	 * initialization quirk to work; this is likely to also
++	 * be the case for other laptops or integrated video devices.
++	 */
++
+ 	/* GDT[0]: GDT self-pointer */
+ 	header->wakeup_gdt[0] =
+ 		(u64)(sizeof(header->wakeup_gdt) - 1) +
+ 		((u64)(acpi_wakeup_address +
+ 			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
+ 				<< 16);
+-	/* GDT[1]: real-mode-like code segment */
+-	header->wakeup_gdt[1] = (0x009bULL << 40) +
+-		((u64)acpi_wakeup_address << 16) + 0xffff;
+-	/* GDT[2]: real-mode-like data segment */
+-	header->wakeup_gdt[2] = (0x0093ULL << 40) +
+-		((u64)acpi_wakeup_address << 16) + 0xffff;
++	/* GDT[1]: big real mode-like code segment */
++	header->wakeup_gdt[1] =
++		GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
++	/* GDT[2]: big real mode-like data segment */
++	header->wakeup_gdt[2] =
++		GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
+ 
+ #ifndef CONFIG_64BIT
+ 	store_gdt((struct desc_ptr *)&header->pmode_gdt);
+@@ -79,7 +89,7 @@ int acpi_save_state_mem(void)
+ #endif /* !CONFIG_64BIT */
+ 
+ 	header->pmode_cr0 = read_cr0();
+-	header->pmode_cr4 = read_cr4();
++	header->pmode_cr4 = read_cr4_safe();
+ 	header->realmode_flags = acpi_realmode_flags;
+ 	header->real_magic = 0x12345678;
+ 
+@@ -89,7 +99,9 @@ int acpi_save_state_mem(void)
+ 	saved_magic = 0x12345678;
+ #else /* CONFIG_64BIT */
+ 	header->trampoline_segment = setup_trampoline() >> 4;
+-	init_rsp = (unsigned long)temp_stack + 4096;
++#ifdef CONFIG_SMP
++	stack_start.sp = temp_stack + 4096;
++#endif
+ 	initial_code = (unsigned long)wakeup_long64;
+ 	saved_magic = 0x123456789abcdef0;
+ #endif /* CONFIG_64BIT */
+@@ -145,6 +157,12 @@ static int __init acpi_sleep_setup(char 
+ 			acpi_realmode_flags |= 2;
+ 		if (strncmp(str, "s3_beep", 7) == 0)
+ 			acpi_realmode_flags |= 4;
++#ifdef CONFIG_HIBERNATION
++		if (strncmp(str, "s4_nohwsig", 10) == 0)
++			acpi_no_s4_hw_signature();
++#endif
++		if (strncmp(str, "old_ordering", 12) == 0)
++			acpi_old_suspend_ordering();
+ 		str = strchr(str, ',');
+ 		if (str != NULL)
+ 			str += strspn(str, ", \t");
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -59,7 +59,10 @@ static cpumask_t timer_bcast_ipi;
+ /*
+  * Debug level, exported for io_apic.c
+  */
+-int apic_verbosity;
++unsigned int apic_verbosity;
++
++/* Have we found an MP table */
++int smp_found_config;
+ 
+ #ifndef CONFIG_XEN
+ static int modern_apic(void)
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -39,7 +39,10 @@ int disable_apic;
+ /*
+  * Debug level, exported for io_apic.c
+  */
+-int apic_verbosity;
++unsigned int apic_verbosity;
++
++/* Have we found an MP table */
++int smp_found_config;
+ 
+ /*
+  * The guts of the apic timer interrupt
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_64.c	2009-12-04 10:44:49.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_64.c	2009-11-06 10:51:42.000000000 +0100
+@@ -132,7 +132,7 @@ int main(void)
+ 
+ 	BLANK();
+ 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ 	BLANK();
+ 	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+ 	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/amd.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/amd.c	2010-01-18 16:31:12.000000000 +0100
+@@ -569,6 +569,7 @@ static void __cpuinit init_amd(struct cp
+ 		fam10h_check_enable_mmcfg();
+ 	}
+ 
++#ifndef CONFIG_XEN
+ 	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
+ 		unsigned long long tseg;
+ 
+@@ -588,6 +589,7 @@ static void __cpuinit init_amd(struct cp
+ 		}
+ 	}
+ #endif
++#endif
+ }
+ 
+ #ifdef CONFIG_X86_32
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/bugs_64.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/bugs_64.c	2009-11-06 10:51:42.000000000 +0100
+@@ -20,6 +20,7 @@ void __init check_bugs(void)
+ #endif
+ 	alternative_instructions();
+ 
++#ifndef CONFIG_XEN
+ 	/*
+ 	 * Make sure the first 2MB area is not mapped by huge pages
+ 	 * There are typically fixed size MTRRs in there and overlapping
+@@ -30,4 +31,5 @@ void __init check_bugs(void)
+ 	 */
+ 	if (!direct_gbpages)
+ 		set_memory_4k((unsigned long)__va(0), 1);
++#endif
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <asm/mtrr.h>
+ #include <asm/mce.h>
+ #include <asm/pat.h>
++#include <asm/asm.h>
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #include <asm/mpspec.h>
+ #include <asm/apic.h>
+@@ -341,11 +342,24 @@ static void __init early_cpu_detect(void
+ 
+ 	get_cpu_vendor(c, 1);
+ 
++	early_get_cap(c);
++
+ 	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
+ 	    cpu_devs[c->x86_vendor]->c_early_init)
+ 		cpu_devs[c->x86_vendor]->c_early_init(c);
++}
+ 
+-	early_get_cap(c);
++/*
++ * The NOPL instruction is supposed to exist on all CPUs with
++ * family >= 6; unfortunately, that's not true in practice because
++ * of early VIA chips and (more importantly) broken virtualizers that
++ * are not easy to detect.  In the latter case it doesn't even *fail*
++ * reliably, so probing for it doesn't even work.  Disable it completely
++ * unless we can find a reliable way to detect all the broken cases.
++ */
++static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
++{
++	clear_cpu_cap(c, X86_FEATURE_NOPL);
+ }
+ 
+ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+@@ -404,8 +418,8 @@ static void __cpuinit generic_identify(s
+ 		}
+ 
+ 		init_scattered_cpuid_features(c);
++		detect_nopl(c);
+ 	}
+-
+ }
+ 
+ static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+@@ -436,7 +450,7 @@ __setup("serialnumber", x86_serial_nr_se
+ /*
+  * This does the hard work of actually picking apart the CPU stuff...
+  */
+-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ {
+ 	int i;
+ 
+@@ -450,6 +464,8 @@ void __cpuinit identify_cpu(struct cpuin
+ 	c->x86_max_cores = 1;
+ 	c->x86_clflush_size = 32;
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++	if (boot_cpu_has(X86_FEATURE_SYSCALL32))
++		set_cpu_cap(c, X86_FEATURE_SYSCALL32);
+ 
+ 	if (!have_cpuid_p()) {
+ 		/*
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/cpu/common_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -0,0 +1,773 @@
++#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 <linux/kgdb.h>
++#include <linux/topology.h>
++#include <linux/delay.h>
++#include <linux/smp.h>
++#include <linux/percpu.h>
++#include <asm/i387.h>
++#include <asm/msr.h>
++#include <asm/io.h>
++#include <asm/linkage.h>
++#include <asm/mmu_context.h>
++#include <asm/mtrr.h>
++#include <asm/mce.h>
++#include <asm/pat.h>
++#include <asm/asm.h>
++#include <asm/numa.h>
++#ifdef CONFIG_X86_LOCAL_APIC
++#include <asm/mpspec.h>
++#include <asm/apic.h>
++#include <mach_apic.h>
++#elif defined(CONFIG_XEN)
++#include <mach_apic.h>
++#endif
++#include <asm/pda.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/proto.h>
++#include <asm/sections.h>
++#include <asm/setup.h>
++#include <asm/genapic.h>
++
++#include "cpu.h"
++
++/* We need valid kernel segments for data and code in long mode too
++ * IRET will check the segment types  kkeil 2000/10/28
++ * Also sysret mandates a special GDT layout
++ */
++/* The TLS descriptors are currently at a different place compared to i386.
++   Hopefully nobody expects them at a fixed place (Wine?) */
++DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
++	[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
++	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
++	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
++	[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
++	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
++	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
++} };
++EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
++
++__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
++
++/* Current gdt points %fs at the "master" per-cpu area: after this,
++ * it's on the real one. */
++void switch_to_new_gdt(void)
++{
++#ifndef CONFIG_XEN
++	struct desc_ptr gdt_descr;
++
++	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
++	gdt_descr.size = GDT_SIZE - 1;
++	load_gdt(&gdt_descr);
++#else
++	void *va, *gdt_addr = get_cpu_gdt_table(smp_processor_id());
++	unsigned long frames[16];
++	unsigned int f = 0;
++
++	for (va = gdt_addr; va < gdt_addr + GDT_SIZE; va += PAGE_SIZE) {
++		frames[f++] = virt_to_mfn(va);
++		make_page_readonly(va, XENFEAT_writable_descriptor_tables);
++	}
++	if (HYPERVISOR_set_gdt(frames, GDT_SIZE / sizeof(struct desc_struct)))
++		BUG();
++#endif
++}
++
++struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
++
++static void __cpuinit default_init(struct cpuinfo_x86 *c)
++{
++	display_cacheinfo(c);
++}
++
++static struct cpu_dev __cpuinitdata default_cpu = {
++	.c_init	= default_init,
++	.c_vendor = "Unknown",
++};
++static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
++
++int __cpuinit get_model_name(struct cpuinfo_x86 *c)
++{
++	unsigned int *v;
++
++	if (c->extended_cpuid_level < 0x80000004)
++		return 0;
++
++	v = (unsigned int *) c->x86_model_id;
++	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
++	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
++	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
++	c->x86_model_id[48] = 0;
++	return 1;
++}
++
++
++void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
++{
++	unsigned int n, dummy, ebx, ecx, edx;
++
++	n = c->extended_cpuid_level;
++
++	if (n >= 0x80000005) {
++		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
++		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
++		       "D cache %dK (%d bytes/line)\n",
++		       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
++		c->x86_cache_size = (ecx>>24) + (edx>>24);
++		/* On K8 L1 TLB is inclusive, so don't count it */
++		c->x86_tlbsize = 0;
++	}
++
++	if (n >= 0x80000006) {
++		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
++		ecx = cpuid_ecx(0x80000006);
++		c->x86_cache_size = ecx >> 16;
++		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
++
++		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
++		c->x86_cache_size, ecx & 0xFF);
++	}
++}
++
++void __cpuinit detect_ht(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_SMP
++	u32 eax, ebx, ecx, edx;
++	int index_msb, core_bits;
++
++	cpuid(1, &eax, &ebx, &ecx, &edx);
++
++
++	if (!cpu_has(c, X86_FEATURE_HT))
++		return;
++	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
++		goto out;
++
++	smp_num_siblings = (ebx & 0xff0000) >> 16;
++
++	if (smp_num_siblings == 1) {
++		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
++	} else if (smp_num_siblings > 1) {
++
++		if (smp_num_siblings > NR_CPUS) {
++			printk(KERN_WARNING "CPU: Unsupported number of "
++			       "siblings %d", smp_num_siblings);
++			smp_num_siblings = 1;
++			return;
++		}
++
++		index_msb = get_count_order(smp_num_siblings);
++		c->phys_proc_id = phys_pkg_id(index_msb);
++
++		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
++
++		index_msb = get_count_order(smp_num_siblings);
++
++		core_bits = get_count_order(c->x86_max_cores);
++
++		c->cpu_core_id = phys_pkg_id(index_msb) &
++					       ((1 << core_bits) - 1);
++	}
++out:
++	if ((c->x86_max_cores * smp_num_siblings) > 1) {
++		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
++		       c->phys_proc_id);
++		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
++		       c->cpu_core_id);
++	}
++
++#endif
++}
++
++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
++{
++	char *v = c->x86_vendor_id;
++	int i;
++	static int printed;
++
++	for (i = 0; i < X86_VENDOR_NUM; i++) {
++		if (cpu_devs[i]) {
++			if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
++			    (cpu_devs[i]->c_ident[1] &&
++			    !strcmp(v, cpu_devs[i]->c_ident[1]))) {
++				c->x86_vendor = i;
++				this_cpu = cpu_devs[i];
++				return;
++			}
++		}
++	}
++	if (!printed) {
++		printed++;
++		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
++		printk(KERN_ERR "CPU: Your system may be unstable.\n");
++	}
++	c->x86_vendor = X86_VENDOR_UNKNOWN;
++}
++
++static void __init early_cpu_support_print(void)
++{
++	int i,j;
++	struct cpu_dev *cpu_devx;
++
++	printk("KERNEL supported cpus:\n");
++	for (i = 0; i < X86_VENDOR_NUM; i++) {
++		cpu_devx = cpu_devs[i];
++		if (!cpu_devx)
++			continue;
++		for (j = 0; j < 2; j++) {
++			if (!cpu_devx->c_ident[j])
++				continue;
++			printk("  %s %s\n", cpu_devx->c_vendor,
++				cpu_devx->c_ident[j]);
++		}
++	}
++}
++
++/*
++ * The NOPL instruction is supposed to exist on all CPUs with
++ * family >= 6, unfortunately, that's not true in practice because
++ * of early VIA chips and (more importantly) broken virtualizers that
++ * are not easy to detect.  Hence, probe for it based on first
++ * principles.
++ *
++ * Note: no 64-bit chip is known to lack these, but put the code here
++ * for consistency with 32 bits, and to make it utterly trivial to
++ * diagnose the problem should it ever surface.
++ */
++static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
++{
++	const u32 nopl_signature = 0x888c53b1; /* Random number */
++	u32 has_nopl = nopl_signature;
++
++	clear_cpu_cap(c, X86_FEATURE_NOPL);
++	if (c->x86 >= 6) {
++		asm volatile("\n"
++			     "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
++			     "2:\n"
++			     "        .section .fixup,\"ax\"\n"
++			     "3:      xor %0,%0\n"
++			     "        jmp 2b\n"
++			     "        .previous\n"
++			     _ASM_EXTABLE(1b,3b)
++			     : "+a" (has_nopl));
++
++		if (has_nopl == nopl_signature)
++			set_cpu_cap(c, X86_FEATURE_NOPL);
++	}
++}
++
++static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
++
++void __init early_cpu_init(void)
++{
++        struct cpu_vendor_dev *cvdev;
++
++        for (cvdev = __x86cpuvendor_start ;
++             cvdev < __x86cpuvendor_end   ;
++             cvdev++)
++                cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
++	early_cpu_support_print();
++	early_identify_cpu(&boot_cpu_data);
++}
++
++/* Do some early cpuid on the boot CPU to get some parameter that are
++   needed before check_bugs. Everything advanced is in identify_cpu
++   below. */
++static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
++{
++	u32 tfms, xlvl;
++
++	c->loops_per_jiffy = loops_per_jiffy;
++	c->x86_cache_size = -1;
++	c->x86_vendor = X86_VENDOR_UNKNOWN;
++	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
++	c->x86_vendor_id[0] = '\0'; /* Unset */
++	c->x86_model_id[0] = '\0';  /* Unset */
++	c->x86_clflush_size = 64;
++	c->x86_cache_alignment = c->x86_clflush_size;
++	c->x86_max_cores = 1;
++	c->x86_coreid_bits = 0;
++	c->extended_cpuid_level = 0;
++	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++
++	/* Get vendor name */
++	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
++	      (unsigned int *)&c->x86_vendor_id[0],
++	      (unsigned int *)&c->x86_vendor_id[8],
++	      (unsigned int *)&c->x86_vendor_id[4]);
++
++	get_cpu_vendor(c);
++
++	/* Initialize the standard set of capabilities */
++	/* Note that the vendor-specific code below might override */
++
++	/* Intel-defined flags: level 0x00000001 */
++	if (c->cpuid_level >= 0x00000001) {
++		__u32 misc;
++		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
++		      &c->x86_capability[0]);
++		c->x86 = (tfms >> 8) & 0xf;
++		c->x86_model = (tfms >> 4) & 0xf;
++		c->x86_mask = tfms & 0xf;
++		if (c->x86 == 0xf)
++			c->x86 += (tfms >> 20) & 0xff;
++		if (c->x86 >= 0x6)
++			c->x86_model += ((tfms >> 16) & 0xF) << 4;
++		if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
++			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
++	} else {
++		/* Have CPUID level 0 only - unheard of */
++		c->x86 = 4;
++	}
++
++	c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
++#ifdef CONFIG_SMP
++	c->phys_proc_id = c->initial_apicid;
++#endif
++	/* AMD-defined flags: level 0x80000001 */
++	xlvl = cpuid_eax(0x80000000);
++	c->extended_cpuid_level = xlvl;
++	if ((xlvl & 0xffff0000) == 0x80000000) {
++		if (xlvl >= 0x80000001) {
++			c->x86_capability[1] = cpuid_edx(0x80000001);
++			c->x86_capability[6] = cpuid_ecx(0x80000001);
++		}
++		if (xlvl >= 0x80000004)
++			get_model_name(c); /* Default name */
++	}
++
++	/* Transmeta-defined flags: level 0x80860001 */
++	xlvl = cpuid_eax(0x80860000);
++	if ((xlvl & 0xffff0000) == 0x80860000) {
++		/* Don't set x86_cpuid_level here for now to not confuse. */
++		if (xlvl >= 0x80860001)
++			c->x86_capability[2] = cpuid_edx(0x80860001);
++	}
++
++	if (c->extended_cpuid_level >= 0x80000007)
++		c->x86_power = cpuid_edx(0x80000007);
++
++	if (c->extended_cpuid_level >= 0x80000008) {
++		u32 eax = cpuid_eax(0x80000008);
++
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
++	}
++
++	detect_nopl(c);
++
++	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
++	    cpu_devs[c->x86_vendor]->c_early_init)
++		cpu_devs[c->x86_vendor]->c_early_init(c);
++
++	validate_pat_support(c);
++}
++
++/*
++ * This does the hard work of actually picking apart the CPU stuff...
++ */
++static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++{
++	int i;
++
++	early_identify_cpu(c);
++
++	init_scattered_cpuid_features(c);
++
++#ifndef CONFIG_XEN
++	c->apicid = phys_pkg_id(0);
++#endif
++
++	/*
++	 * Vendor-specific initialization.  In this section we
++	 * canonicalize the feature flags, meaning if there are
++	 * features a certain CPU supports which CPUID doesn't
++	 * tell us, CPUID claiming incorrect flags, or other bugs,
++	 * we handle them here.
++	 *
++	 * At the end of this section, c->x86_capability better
++	 * indicate the features this CPU genuinely supports!
++	 */
++	if (this_cpu->c_init)
++		this_cpu->c_init(c);
++
++	detect_ht(c);
++
++	/*
++	 * On SMP, boot_cpu_data holds the common feature set between
++	 * all CPUs; so make sure that we indicate which features are
++	 * common between the CPUs.  The first time this routine gets
++	 * executed, c == &boot_cpu_data.
++	 */
++	if (c != &boot_cpu_data) {
++		/* AND the already accumulated flags with these */
++		for (i = 0; i < NCAPINTS; i++)
++			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
++	}
++
++	/* Clear all flags overriden by options */
++	for (i = 0; i < NCAPINTS; i++)
++		c->x86_capability[i] &= ~cleared_cpu_caps[i];
++
++#ifdef CONFIG_X86_MCE
++	mcheck_init(c);
++#endif
++	select_idle_routine(c);
++
++#ifdef CONFIG_NUMA
++	numa_add_cpu(smp_processor_id());
++#endif
++
++}
++
++void __cpuinit identify_boot_cpu(void)
++{
++	identify_cpu(&boot_cpu_data);
++}
++
++void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
++{
++	BUG_ON(c == &boot_cpu_data);
++	identify_cpu(c);
++	mtrr_ap_init();
++}
++
++static __init int setup_noclflush(char *arg)
++{
++	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
++	return 1;
++}
++__setup("noclflush", setup_noclflush);
++
++void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
++{
++	if (c->x86_model_id[0])
++		printk(KERN_CONT "%s", c->x86_model_id);
++
++	if (c->x86_mask || c->cpuid_level >= 0)
++		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
++	else
++		printk(KERN_CONT "\n");
++}
++
++static __init int setup_disablecpuid(char *arg)
++{
++	int bit;
++	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
++		setup_clear_cpu_cap(bit);
++	else
++		return 0;
++	return 1;
++}
++__setup("clearcpuid=", setup_disablecpuid);
++
++cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
++
++struct x8664_pda **_cpu_pda __read_mostly;
++EXPORT_SYMBOL(_cpu_pda);
++
++#ifndef CONFIG_X86_NO_IDT
++struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
++#endif
++
++char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
++
++unsigned long __supported_pte_mask __read_mostly = ~0UL;
++EXPORT_SYMBOL_GPL(__supported_pte_mask);
++
++static int do_not_nx __cpuinitdata;
++
++/* noexec=on|off
++Control non executable mappings for 64bit processes.
++
++on	Enable(default)
++off	Disable
++*/
++static int __init nonx_setup(char *str)
++{
++	if (!str)
++		return -EINVAL;
++	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 0;
++}
++early_param("noexec", nonx_setup);
++
++int force_personality32;
++
++/* 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 (default)
++off	PROT_READ implies PROT_EXEC
++*/
++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);
++
++static void __init_refok switch_pt(int cpu)
++{
++#ifdef CONFIG_XEN
++	if (cpu == 0)
++		xen_init_pt();
++	xen_pt_switch(__pa_symbol(init_level4_pgt));
++	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
++#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 */
++	loadsegment(fs, 0);
++	loadsegment(gs, 0);
++#ifndef CONFIG_XEN
++	/* Memory clobbers used to order PDA accessed */
++	mb();
++	wrmsrl(MSR_GS_BASE, pda);
++	mb();
++#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) {
++		/* others are initialized in smpboot.c */
++		pda->pcurrent = &init_task;
++		pda->irqstackptr = boot_cpu_stack;
++		pda->irqstackptr += IRQSTACKSIZE - 64;
++	} else {
++		if (!pda->irqstackptr) {
++			pda->irqstackptr = (char *)
++				__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
++			if (!pda->irqstackptr)
++				panic("cannot allocate irqstack for cpu %d",
++				      cpu);
++			pda->irqstackptr += IRQSTACKSIZE - 64;
++		}
++
++		if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
++			pda->nodenumber = cpu_to_node(cpu);
++	}
++
++	switch_pt(cpu);
++}
++
++#ifndef CONFIG_X86_NO_TSS
++char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
++			   DEBUG_STKSZ] __page_aligned_bss;
++#endif
++
++extern asmlinkage void ignore_sysret(void);
++
++void __cpuinit 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);
++	wrmsrl(MSR_CSTAR, ignore_sysret);
++
++	/* Flags to clear on syscall */
++	wrmsrl(MSR_SYSCALL_MASK,
++	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
++#endif
++#ifdef CONFIG_IA32_EMULATION
++	syscall32_cpu_init();
++#else
++	static const struct callback_register __cpuinitconst cstar = {
++		.type = CALLBACKTYPE_syscall32,
++		.address = (unsigned long)ignore_sysret
++	};
++
++	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
++		printk(KERN_WARNING "Unable to register CSTAR callback\n");
++#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;
++
++#ifndef CONFIG_X86_NO_TSS
++/*
++ * Copies of the original ist values from the tss are only accessed during
++ * debugging, no special alignment required.
++ */
++DEFINE_PER_CPU(struct orig_ist, orig_ist);
++#endif
++
++/*
++ * 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;
++	int i;
++#endif
++	struct task_struct *me;
++
++	/* CPU 0 is initialised in head64.c */
++	if (cpu != 0)
++		pda_init(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(KERN_INFO "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:
++	 */
++
++	switch_to_new_gdt();
++#ifndef CONFIG_X86_NO_IDT
++	load_idt((const struct desc_ptr *)&idt_descr);
++#endif
++
++	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
++	 */
++	if (!orig_ist->ist[0]) {
++		static const unsigned int order[N_EXCEPTION_STACKS] = {
++		  [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
++		  [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
++		};
++		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
++			if (cpu) {
++				estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
++				if (!estacks)
++					panic("Cannot allocate exception "
++					      "stack %ld %d\n", v, cpu);
++			}
++			estacks += PAGE_SIZE << order[v];
++			orig_ist->ist[v] = t->x86_tss.ist[v] =
++					(unsigned long)estacks;
++		}
++	}
++
++	t->x86_tss.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);
++
++	load_sp0(t, &current->thread);
++#ifndef CONFIG_X86_NO_TSS
++	set_tss_desc(cpu, t);
++	load_TR_desc();
++#endif
++	load_LDT(&init_mm.context);
++
++#ifdef CONFIG_KGDB
++	/*
++	 * If the kgdb is connected no debug regs should be altered.  This
++	 * is only applicable when KGDB and a KGDB I/O module are built
++	 * into the kernel and you are using early debugging with
++	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
++	 */
++	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
++		arch_kgdb_ops.correct_hw_break();
++	else {
++#endif
++	/*
++	 * 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);
++#ifdef CONFIG_KGDB
++	/* If the kgdb is connected no debug regs should be altered. */
++	}
++#endif
++
++	fpu_init();
++
++	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
++	if (raw_irqs_disabled())
++		kernel_eflags &= ~X86_EFLAGS_IF;
++
++	if (is_uv_system())
++		uv_cpu_init();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -0,0 +1,1553 @@
++/*
++ * Handle the memory map.
++ * The functions here do the job until bootmem takes over.
++ *
++ *  Getting sanitize_e820_map() in sync with i386 version by applying change:
++ *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
++ *     Alex Achenbach <xela@slit.de>, December 2002.
++ *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/string.h>
++#include <linux/kexec.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/pfn.h>
++#include <linux/suspend.h>
++#include <linux/firmware-map.h>
++
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/e820.h>
++#include <asm/proto.h>
++#include <asm/setup.h>
++#include <xen/interface/memory.h>
++
++/*
++ * The e820 map is the map that gets modified e.g. with command line parameters
++ * and that is also registered with modifications in the kernel resource tree
++ * with the iomem_resource as parent.
++ *
++ * The e820_saved is directly saved after the BIOS-provided memory map is
++ * copied. It doesn't get modified afterwards. It's registered for the
++ * /sys/firmware/memmap interface.
++ *
++ * That memory map is not modified and is used as base for kexec. The kexec'd
++ * kernel should get the same memory map as the firmware provides. Then the
++ * user can e.g. boot the original kernel with mem=1G while still booting the
++ * next kernel with full memory.
++ */
++struct e820map e820;
++#ifndef CONFIG_XEN
++struct e820map e820_saved;
++#else
++static struct e820map machine_e820;
++#define e820_saved machine_e820
++#endif
++
++/* For PCI or other memory-mapped resources */
++unsigned long pci_mem_start = 0xaeedbabe;
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL(pci_mem_start);
++#endif
++
++/*
++ * 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;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		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.
++ *
++ * Note: this function only works correct if the e820 table is sorted and
++ * not-overlapping, which is the case
++ */
++int __init e820_all_mapped(u64 start, u64 end, unsigned type)
++{
++	int i;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		if (type && ei->type != type)
++			continue;
++		/* is the region (part) in overlap with the current region ?*/
++		if (ei->addr >= end || ei->addr + ei->size <= start)
++			continue;
++
++		/* if the region is at the beginning of <start,end> we move
++		 * start to the end of the region since it's ok until there
++		 */
++		if (ei->addr <= start)
++			start = ei->addr + ei->size;
++		/*
++		 * if start is now at or beyond end, we're done, full
++		 * coverage
++		 */
++		if (start >= end)
++			return 1;
++	}
++	return 0;
++}
++
++/*
++ * Add a memory region to the kernel e820 map.
++ */
++void __init e820_add_region(u64 start, u64 size, int type)
++{
++	int x = e820.nr_map;
++
++	if (x == ARRAY_SIZE(e820.map)) {
++		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++		return;
++	}
++
++	e820.map[x].addr = start;
++	e820.map[x].size = size;
++	e820.map[x].type = type;
++	e820.nr_map++;
++}
++
++static void __init _e820_print_map(const struct e820map *e820, const char *who)
++{
++	int i;
++
++	for (i = 0; i < e820->nr_map; i++) {
++		printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
++		       (unsigned long long) e820->map[i].addr,
++		       (unsigned long long)
++		       (e820->map[i].addr + e820->map[i].size));
++		switch (e820->map[i].type) {
++		case E820_RAM:
++		case E820_RESERVED_KERN:
++			printk(KERN_CONT "(usable)\n");
++			break;
++		case E820_RESERVED:
++			printk(KERN_CONT "(reserved)\n");
++			break;
++		case E820_ACPI:
++			printk(KERN_CONT "(ACPI data)\n");
++			break;
++		case E820_NVS:
++			printk(KERN_CONT "(ACPI NVS)\n");
++			break;
++		default:
++			printk(KERN_CONT "type %u\n", e820->map[i].type);
++			break;
++		}
++	}
++}
++
++/*
++ * Sanitize the BIOS e820 map.
++ *
++ * Some e820 responses include overlapping entries. The following
++ * replaces the original e820 map with a new one, removing overlaps,
++ * and resolving conflicting memory types in favor of highest
++ * numbered type.
++ *
++ * The input parameter biosmap points to an array of 'struct
++ * e820entry' which on entry has elements in the range [0, *pnr_map)
++ * valid, and which has space for up to max_nr_map entries.
++ * On return, the resulting sanitized e820 map entries will be in
++ * overwritten in the same location, starting at biosmap.
++ *
++ * The integer pointed to by pnr_map must be valid on entry (the
++ * current number of valid entries located at biosmap) and will
++ * be updated on return, with the new number of valid entries
++ * (something no more than max_nr_map.)
++ *
++ * The return value from sanitize_e820_map() is zero if it
++ * successfully 'sanitized' the map entries passed in, and is -1
++ * if it did nothing, which can happen if either of (1) it was
++ * only passed one map entry, or (2) any of the input map entries
++ * were invalid (start + size < start, meaning that the size was
++ * so big the described memory range wrapped around through zero.)
++ *
++ *	Visually we're performing the following
++ *	(1,2,3,4 = memory types)...
++ *
++ *	Sample memory map (w/overlaps):
++ *	   ____22__________________
++ *	   ______________________4_
++ *	   ____1111________________
++ *	   _44_____________________
++ *	   11111111________________
++ *	   ____________________33__
++ *	   ___________44___________
++ *	   __________33333_________
++ *	   ______________22________
++ *	   ___________________2222_
++ *	   _________111111111______
++ *	   _____________________11_
++ *	   _________________4______
++ *
++ *	Sanitized equivalent (no overlap):
++ *	   1_______________________
++ *	   _44_____________________
++ *	   ___1____________________
++ *	   ____22__________________
++ *	   ______11________________
++ *	   _________1______________
++ *	   __________3_____________
++ *	   ___________44___________
++ *	   _____________33_________
++ *	   _______________2________
++ *	   ________________1_______
++ *	   _________________4______
++ *	   ___________________2____
++ *	   ____________________33__
++ *	   ______________________4_
++ */
++
++int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
++				int *pnr_map)
++{
++	struct change_member {
++		struct e820entry *pbios; /* pointer to original bios entry */
++		unsigned long long addr; /* address for this change point */
++	};
++	static struct change_member change_point_list[2*E820_X_MAX] __initdata;
++	static struct change_member *change_point[2*E820_X_MAX] __initdata;
++	static struct e820entry *overlap_list[E820_X_MAX] __initdata;
++	static struct e820entry new_bios[E820_X_MAX] __initdata;
++	struct change_member *change_tmp;
++	unsigned long current_type, last_type;
++	unsigned long long last_addr;
++	int chgidx, still_changing;
++	int overlap_entries;
++	int new_bios_entry;
++	int old_nr, new_nr, chg_nr;
++	int i;
++
++	/* if there's only one memory region, don't bother */
++#ifdef CONFIG_XEN
++	if (*pnr_map == 1)
++		return 0;
++#endif
++	if (*pnr_map < 2)
++		return -1;
++
++	old_nr = *pnr_map;
++	BUG_ON(old_nr > max_nr_map);
++
++	/* bail out if we find any unreasonable addresses in bios map */
++	for (i = 0; i < old_nr; i++)
++		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
++			return -1;
++
++	/* create pointers for initial change-point information (for sorting) */
++	for (i = 0; i < 2 * old_nr; i++)
++		change_point[i] = &change_point_list[i];
++
++	/* record all known change-points (starting and ending addresses),
++	   omitting those that are for empty memory regions */
++	chgidx = 0;
++	for (i = 0; i < old_nr; i++)	{
++		if (biosmap[i].size != 0) {
++			change_point[chgidx]->addr = biosmap[i].addr;
++			change_point[chgidx++]->pbios = &biosmap[i];
++			change_point[chgidx]->addr = biosmap[i].addr +
++				biosmap[i].size;
++			change_point[chgidx++]->pbios = &biosmap[i];
++		}
++	}
++	chg_nr = chgidx;
++
++	/* sort change-point list by memory addresses (low -> high) */
++	still_changing = 1;
++	while (still_changing)	{
++		still_changing = 0;
++		for (i = 1; i < chg_nr; i++)  {
++			unsigned long long curaddr, lastaddr;
++			unsigned long long curpbaddr, lastpbaddr;
++
++			curaddr = change_point[i]->addr;
++			lastaddr = change_point[i - 1]->addr;
++			curpbaddr = change_point[i]->pbios->addr;
++			lastpbaddr = change_point[i - 1]->pbios->addr;
++
++			/*
++			 * swap entries, when:
++			 *
++			 * curaddr > lastaddr or
++			 * curaddr == lastaddr and curaddr == curpbaddr and
++			 * lastaddr != lastpbaddr
++			 */
++			if (curaddr < lastaddr ||
++			    (curaddr == lastaddr && curaddr == curpbaddr &&
++			     lastaddr != lastpbaddr)) {
++				change_tmp = change_point[i];
++				change_point[i] = change_point[i-1];
++				change_point[i-1] = change_tmp;
++				still_changing = 1;
++			}
++		}
++	}
++
++	/* create a new bios memory map, removing overlaps */
++	overlap_entries = 0;	 /* number of entries in the overlap table */
++	new_bios_entry = 0;	 /* index for creating new bios map entries */
++	last_type = 0;		 /* start with undefined memory type */
++	last_addr = 0;		 /* start with 0 as last starting address */
++
++	/* loop through change-points, determining affect on the new bios map */
++	for (chgidx = 0; chgidx < chg_nr; chgidx++) {
++		/* keep track of all overlapping bios entries */
++		if (change_point[chgidx]->addr ==
++		    change_point[chgidx]->pbios->addr) {
++			/*
++			 * add map entry to overlap list (> 1 entry
++			 * implies an overlap)
++			 */
++			overlap_list[overlap_entries++] =
++				change_point[chgidx]->pbios;
++		} else {
++			/*
++			 * remove entry from list (order independent,
++			 * so swap with last)
++			 */
++			for (i = 0; i < overlap_entries; i++) {
++				if (overlap_list[i] ==
++				    change_point[chgidx]->pbios)
++					overlap_list[i] =
++						overlap_list[overlap_entries-1];
++			}
++			overlap_entries--;
++		}
++		/*
++		 * if there are overlapping entries, decide which
++		 * "type" to use (larger value takes precedence --
++		 * 1=usable, 2,3,4,4+=unusable)
++		 */
++		current_type = 0;
++		for (i = 0; i < overlap_entries; i++)
++			if (overlap_list[i]->type > current_type)
++				current_type = overlap_list[i]->type;
++		/*
++		 * continue building up new bios map based on this
++		 * information
++		 */
++		if (current_type != last_type)	{
++			if (last_type != 0)	 {
++				new_bios[new_bios_entry].size =
++					change_point[chgidx]->addr - last_addr;
++				/*
++				 * move forward only if the new size
++				 * was non-zero
++				 */
++				if (new_bios[new_bios_entry].size != 0)
++					/*
++					 * no more space left for new
++					 * bios entries ?
++					 */
++					if (++new_bios_entry >= max_nr_map)
++						break;
++			}
++			if (current_type != 0)	{
++				new_bios[new_bios_entry].addr =
++					change_point[chgidx]->addr;
++				new_bios[new_bios_entry].type = current_type;
++				last_addr = change_point[chgidx]->addr;
++			}
++			last_type = current_type;
++		}
++	}
++	/* retain count for new bios entries */
++	new_nr = new_bios_entry;
++
++	/* copy new bios mapping into original location */
++	memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry));
++	*pnr_map = new_nr;
++
++	return 0;
++}
++
++static int __init __append_e820_map(struct e820entry *biosmap, int nr_map)
++{
++	while (nr_map) {
++		u64 start = biosmap->addr;
++		u64 size = biosmap->size;
++		u64 end = start + size;
++		u32 type = biosmap->type;
++
++		/* Overflow in 64 bits? Ignore the memory map. */
++		if (start > end)
++			return -1;
++
++		e820_add_region(start, size, type);
++
++		biosmap++;
++		nr_map--;
++	}
++	return 0;
++}
++
++/*
++ * Copy the BIOS e820 map into a safe place.
++ *
++ * Sanity-check it while we're at it..
++ *
++ * If we're lucky and live on a modern system, the setup code
++ * will have given us a memory map that we can use to properly
++ * set up memory.  If we aren't, we'll fake a memory map.
++ */
++static int __init append_e820_map(struct e820entry *biosmap, int nr_map)
++{
++#ifndef CONFIG_XEN
++	/* Only one memory region (or negative)? Ignore it */
++	if (nr_map < 2)
++		return -1;
++#else
++	BUG_ON(nr_map < 1);
++#endif
++
++	return __append_e820_map(biosmap, nr_map);
++}
++
++static u64 __init e820_update_range_map(struct e820map *e820x, u64 start,
++					u64 size, unsigned old_type,
++					unsigned new_type)
++{
++	unsigned int i, x;
++	u64 real_updated_size = 0;
++
++	BUG_ON(old_type == new_type);
++
++	if (size > (ULLONG_MAX - start))
++		size = ULLONG_MAX - start;
++
++	for (i = 0; i < e820x->nr_map; i++) {
++		struct e820entry *ei = &e820x->map[i];
++		u64 final_start, final_end;
++		if (ei->type != old_type)
++			continue;
++		/* totally covered? */
++		if (ei->addr >= start &&
++		    (ei->addr + ei->size) <= (start + size)) {
++			ei->type = new_type;
++			real_updated_size += ei->size;
++			continue;
++		}
++		/* partially covered */
++		final_start = max(start, ei->addr);
++		final_end = min(start + size, ei->addr + ei->size);
++		if (final_start >= final_end)
++			continue;
++
++		x = e820x->nr_map;
++		if (x == ARRAY_SIZE(e820x->map)) {
++			printk(KERN_ERR "Too many memory map entries!\n");
++			break;
++		}
++		e820x->map[x].addr = final_start;
++		e820x->map[x].size = final_end - final_start;
++		e820x->map[x].type = new_type;
++		e820x->nr_map++;
++
++		real_updated_size += final_end - final_start;
++
++		if (ei->addr < final_start)
++			continue;
++		ei->addr = final_end;
++		ei->size -= final_end - final_start;
++	}
++	return real_updated_size;
++}
++
++u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
++			     unsigned new_type)
++{
++	return e820_update_range_map(&e820, start, size, old_type, new_type);
++}
++
++static u64 __init e820_update_range_saved(u64 start, u64 size,
++					  unsigned old_type, unsigned new_type)
++{
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain())
++		return e820_update_range_map(&machine_e820,
++					     phys_to_machine(start), size,
++					     old_type, new_type);
++#endif
++	return e820_update_range_map(&e820_saved, start, size, old_type,
++				     new_type);
++}
++
++/* make e820 not cover the range */
++u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
++			     int checktype)
++{
++	int i;
++	u64 real_removed_size = 0;
++
++	if (size > (ULLONG_MAX - start))
++		size = ULLONG_MAX - start;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		u64 final_start, final_end;
++
++		if (checktype && ei->type != old_type)
++			continue;
++		/* totally covered? */
++		if (ei->addr >= start &&
++		    (ei->addr + ei->size) <= (start + size)) {
++			real_removed_size += ei->size;
++			memset(ei, 0, sizeof(struct e820entry));
++			continue;
++		}
++		/* partially covered */
++		final_start = max(start, ei->addr);
++		final_end = min(start + size, ei->addr + ei->size);
++		if (final_start >= final_end)
++			continue;
++		real_removed_size += final_end - final_start;
++
++		ei->size -= final_end - final_start;
++		if (ei->addr < final_start)
++			continue;
++		ei->addr = final_end;
++	}
++	return real_removed_size;
++}
++
++void __init update_e820(void)
++{
++	int nr_map;
++
++	nr_map = e820.nr_map;
++	if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
++		return;
++	e820.nr_map = nr_map;
++	printk(KERN_INFO "modified physical RAM map:\n");
++	_e820_print_map(&e820, "modified");
++}
++static void __init update_e820_saved(void)
++{
++	int nr_map;
++
++	nr_map = e820_saved.nr_map;
++	if (sanitize_e820_map(e820_saved.map, ARRAY_SIZE(e820_saved.map), &nr_map))
++		return;
++	e820_saved.nr_map = nr_map;
++}
++
++#ifdef CONFIG_XEN
++#define e820 machine_e820
++#endif
++
++#define MAX_GAP_END 0x100000000ull
++/*
++ * Search for a gap in the e820 memory space from start_addr to end_addr.
++ */
++__init int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
++		unsigned long start_addr, unsigned long long end_addr)
++{
++	unsigned long long last;
++	int i = e820.nr_map;
++	int found = 0;
++
++	last = (end_addr && end_addr < MAX_GAP_END) ? end_addr : MAX_GAP_END;
++#ifdef CONFIG_X86_64
++	if (start_addr >= MAX_GAP_END)
++		last = end_addr ?: (1UL << boot_cpu_data.x86_phys_bits);
++#endif
++
++	while (--i >= 0) {
++		unsigned long long start = e820.map[i].addr;
++		unsigned long long end = start + e820.map[i].size;
++
++		if (end < start_addr)
++			continue;
++
++		/*
++		 * Since "last" is at most 4GB, we know we'll
++		 * fit in 32 bits if this condition is true
++		 */
++		if (last > end) {
++			unsigned long gap = last - end;
++
++			if (gap >= *gapsize) {
++				*gapsize = gap;
++				*gapstart = end;
++				found = 1;
++			}
++		}
++		if (start < last)
++			last = start;
++	}
++	return found;
++}
++
++/*
++ * Search for the biggest gap in the low 32 bits of the e820
++ * memory space.  We pass this space to PCI to assign MMIO resources
++ * for hotplug or unconfigured devices in.
++ * Hopefully the BIOS let enough space left.
++ */
++__init void e820_setup_gap(void)
++{
++	unsigned long gapstart, gapsize, round;
++	int found;
++
++	gapstart = 0x10000000;
++	gapsize = 0x400000;
++	found  = e820_search_gap(&gapstart, &gapsize, 0, MAX_GAP_END);
++
++#ifdef CONFIG_X86_64
++	if (!found) {
++		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
++		       "address range\n"
++		       KERN_ERR "PCI: Unassigned devices with 32bit resource "
++		       "registers may break!\n");
++		found = e820_search_gap(&gapstart, &gapsize, MAX_GAP_END, 0);
++		WARN_ON(!found);
++	}
++#endif
++
++	/*
++	 * See how much we want to round up: start off with
++	 * rounding to the next 1MB area.
++	 */
++	round = 0x100000;
++	while ((gapsize >> 4) > round)
++		round += round;
++	/* Fun with two's complement */
++	pci_mem_start = (gapstart + round) & -round;
++
++	printk(KERN_INFO
++	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
++	       pci_mem_start, gapstart, gapsize);
++}
++
++#undef e820
++
++#ifndef CONFIG_XEN
++/**
++ * Because of the size limitation of struct boot_params, only first
++ * 128 E820 memory entries are passed to kernel via
++ * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
++ * linked list of struct setup_data, which is parsed here.
++ */
++void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
++{
++	u32 map_len;
++	int entries;
++	struct e820entry *extmap;
++
++	entries = sdata->len / sizeof(struct e820entry);
++	map_len = sdata->len + sizeof(struct setup_data);
++	if (map_len > PAGE_SIZE)
++		sdata = early_ioremap(pa_data, map_len);
++	extmap = (struct e820entry *)(sdata->data);
++	__append_e820_map(extmap, entries);
++	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
++	if (map_len > PAGE_SIZE)
++		early_iounmap(sdata, map_len);
++	printk(KERN_INFO "extended physical RAM map:\n");
++	_e820_print_map(&e820, "extended");
++}
++
++#if defined(CONFIG_X86_64) || \
++	(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
++/**
++ * Find the ranges of physical addresses that do not correspond to
++ * e820 RAM areas and mark the corresponding pages as nosave for
++ * hibernation (32 bit) or software suspend and suspend to RAM (64 bit).
++ *
++ * This function requires the e820 map to be sorted and without any
++ * overlapping entries and assumes the first e820 area to be RAM.
++ */
++void __init e820_mark_nosave_regions(unsigned long limit_pfn)
++{
++	int i;
++	unsigned long pfn;
++
++	pfn = PFN_DOWN(e820.map[0].addr + e820.map[0].size);
++	for (i = 1; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++
++		if (pfn < PFN_UP(ei->addr))
++			register_nosave_region(pfn, PFN_UP(ei->addr));
++
++		pfn = PFN_DOWN(ei->addr + ei->size);
++		if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
++			register_nosave_region(PFN_UP(ei->addr), pfn);
++
++		if (pfn >= limit_pfn)
++			break;
++	}
++}
++#endif
++#endif
++
++/*
++ * Early reserved memory areas.
++ */
++#define MAX_EARLY_RES 20
++
++struct early_res {
++	u64 start, end;
++	char name[16];
++	char overlap_ok;
++};
++static struct early_res early_res[MAX_EARLY_RES] __initdata = {
++#ifndef CONFIG_XEN
++	{ 0, PAGE_SIZE, "BIOS data page" },	/* BIOS data page */
++#if defined(CONFIG_X86_64) && defined(CONFIG_X86_TRAMPOLINE)
++	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
++#endif
++#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
++	/*
++	 * But first pinch a few for the stack/trampoline stuff
++	 * FIXME: Don't need the extra page at 4K, but need to fix
++	 * trampoline before removing it. (see the GDT stuff)
++	 */
++	{ PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE" },
++	/*
++	 * Has to be in very low memory so we can execute
++	 * real-mode AP code.
++	 */
++	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + PAGE_SIZE, "TRAMPOLINE" },
++#endif
++#endif
++	{}
++};
++
++static int __init find_overlapped_early(u64 start, u64 end)
++{
++	int i;
++	struct early_res *r;
++
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		r = &early_res[i];
++		if (end > r->start && start < r->end)
++			break;
++	}
++
++	return i;
++}
++
++/*
++ * Drop the i-th range from the early reservation map,
++ * by copying any higher ranges down one over it, and
++ * clearing what had been the last slot.
++ */
++static void __init drop_range(int i)
++{
++	int j;
++
++	for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
++		;
++
++	memmove(&early_res[i], &early_res[i + 1],
++	       (j - 1 - i) * sizeof(struct early_res));
++
++	early_res[j - 1].end = 0;
++}
++
++/*
++ * Split any existing ranges that:
++ *  1) are marked 'overlap_ok', and
++ *  2) overlap with the stated range [start, end)
++ * into whatever portion (if any) of the existing range is entirely
++ * below or entirely above the stated range.  Drop the portion
++ * of the existing range that overlaps with the stated range,
++ * which will allow the caller of this routine to then add that
++ * stated range without conflicting with any existing range.
++ */
++static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
++{
++	int i;
++	struct early_res *r;
++	u64 lower_start, lower_end;
++	u64 upper_start, upper_end;
++	char name[16];
++
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		r = &early_res[i];
++
++		/* Continue past non-overlapping ranges */
++		if (end <= r->start || start >= r->end)
++			continue;
++
++		/*
++		 * Leave non-ok overlaps as is; let caller
++		 * panic "Overlapping early reservations"
++		 * when it hits this overlap.
++		 */
++		if (!r->overlap_ok)
++			return;
++
++		/*
++		 * We have an ok overlap.  We will drop it from the early
++		 * reservation map, and add back in any non-overlapping
++		 * portions (lower or upper) as separate, overlap_ok,
++		 * non-overlapping ranges.
++		 */
++
++		/* 1. Note any non-overlapping (lower or upper) ranges. */
++		strncpy(name, r->name, sizeof(name) - 1);
++
++		lower_start = lower_end = 0;
++		upper_start = upper_end = 0;
++		if (r->start < start) {
++		 	lower_start = r->start;
++			lower_end = start;
++		}
++		if (r->end > end) {
++			upper_start = end;
++			upper_end = r->end;
++		}
++
++		/* 2. Drop the original ok overlapping range */
++		drop_range(i);
++
++		i--;		/* resume for-loop on copied down entry */
++
++		/* 3. Add back in any non-overlapping ranges. */
++		if (lower_end)
++			reserve_early_overlap_ok(lower_start, lower_end, name);
++		if (upper_end)
++			reserve_early_overlap_ok(upper_start, upper_end, name);
++	}
++}
++
++static void __init __reserve_early(u64 start, u64 end, char *name,
++						int overlap_ok)
++{
++	int i;
++	struct early_res *r;
++
++	i = find_overlapped_early(start, end);
++	if (i >= MAX_EARLY_RES)
++		panic("Too many early reservations");
++	r = &early_res[i];
++	if (r->end)
++		panic("Overlapping early reservations "
++		      "%llx-%llx %s to %llx-%llx %s\n",
++		      start, end - 1, name?name:"", r->start,
++		      r->end - 1, r->name);
++	r->start = start;
++	r->end = end;
++	r->overlap_ok = overlap_ok;
++	if (name)
++		strncpy(r->name, name, sizeof(r->name) - 1);
++}
++
++/*
++ * A few early reservtations come here.
++ *
++ * The 'overlap_ok' in the name of this routine does -not- mean it
++ * is ok for these reservations to overlap an earlier reservation.
++ * Rather it means that it is ok for subsequent reservations to
++ * overlap this one.
++ *
++ * Use this entry point to reserve early ranges when you are doing
++ * so out of "Paranoia", reserving perhaps more memory than you need,
++ * just in case, and don't mind a subsequent overlapping reservation
++ * that is known to be needed.
++ *
++ * The drop_overlaps_that_are_ok() call here isn't really needed.
++ * It would be needed if we had two colliding 'overlap_ok'
++ * reservations, so that the second such would not panic on the
++ * overlap with the first.  We don't have any such as of this
++ * writing, but might as well tolerate such if it happens in
++ * the future.
++ */
++void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
++{
++	drop_overlaps_that_are_ok(start, end);
++	__reserve_early(start, end, name, 1);
++}
++
++/*
++ * Most early reservations come here.
++ *
++ * We first have drop_overlaps_that_are_ok() drop any pre-existing
++ * 'overlap_ok' ranges, so that we can then reserve this memory
++ * range without risk of panic'ing on an overlapping overlap_ok
++ * early reservation.
++ */
++void __init reserve_early(u64 start, u64 end, char *name)
++{
++	drop_overlaps_that_are_ok(start, end);
++	__reserve_early(start, end, name, 0);
++}
++
++void __init free_early(u64 start, u64 end)
++{
++	struct early_res *r;
++	int i;
++
++	i = find_overlapped_early(start, end);
++	r = &early_res[i];
++	if (i >= MAX_EARLY_RES || r->end != end || r->start != start)
++		panic("free_early on not reserved area: %llx-%llx!",
++			 start, end - 1);
++
++	drop_range(i);
++}
++
++void __init early_res_to_bootmem(u64 start, u64 end)
++{
++	int i, count;
++	u64 final_start, final_end;
++
++	count  = 0;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++)
++		count++;
++
++	printk(KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n",
++			 count, start, end);
++	for (i = 0; i < count; i++) {
++		struct early_res *r = &early_res[i];
++		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
++			r->start, r->end, r->name);
++		final_start = max(start, r->start);
++		final_end = min(end, r->end);
++		if (final_start >= final_end) {
++			printk(KERN_CONT "\n");
++			continue;
++		}
++		printk(KERN_CONT " ==> [%010llx - %010llx]\n",
++			final_start, final_end);
++		reserve_bootmem_generic(final_start, final_end - final_start,
++				BOOTMEM_DEFAULT);
++	}
++}
++
++/* Check for already reserved areas */
++static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
++{
++	int i;
++	u64 addr = *addrp;
++	int changed = 0;
++	struct early_res *r;
++again:
++	i = find_overlapped_early(addr, addr + size);
++	r = &early_res[i];
++	if (i < MAX_EARLY_RES && r->end) {
++		*addrp = addr = round_up(r->end, align);
++		changed = 1;
++		goto again;
++	}
++	return changed;
++}
++
++/* Check for already reserved areas */
++static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
++{
++	int i;
++	u64 addr = *addrp, last;
++	u64 size = *sizep;
++	int changed = 0;
++again:
++	last = addr + size;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		struct early_res *r = &early_res[i];
++		if (last > r->start && addr < r->start) {
++			size = r->start - addr;
++			changed = 1;
++			goto again;
++		}
++		if (last > r->end && addr < r->end) {
++			addr = round_up(r->end, align);
++			size = last - addr;
++			changed = 1;
++			goto again;
++		}
++		if (last <= r->end && addr >= r->start) {
++			(*sizep)++;
++			return 0;
++		}
++	}
++	if (changed) {
++		*addrp = addr;
++		*sizep = size;
++	}
++	return changed;
++}
++
++/*
++ * Find a free area with specified alignment in a specific range.
++ */
++u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		u64 addr, last;
++		u64 ei_last;
++
++		if (ei->type != E820_RAM)
++			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
++		if (addr < start)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
++			continue;
++		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
++			;
++		last = addr + size;
++		if (last > ei_last)
++			continue;
++		if (last > end)
++			continue;
++		return addr;
++	}
++	return -1ULL;
++}
++
++/*
++ * Find next free range after *start
++ */
++u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		u64 addr, last;
++		u64 ei_last;
++
++		if (ei->type != E820_RAM)
++			continue;
++		addr = round_up(ei->addr, align);
++		ei_last = ei->addr + ei->size;
++		if (addr < start)
++			addr = round_up(start, align);
++		if (addr >= ei_last)
++			continue;
++		*sizep = ei_last - addr;
++		while (bad_addr_size(&addr, sizep, align) &&
++			addr + *sizep <= ei_last)
++			;
++		last = addr + *sizep;
++		if (last > ei_last)
++			continue;
++		return addr;
++	}
++
++	return -1ULL;
++}
++
++/*
++ * pre allocated 4k and reserved it in e820
++ */
++u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
++{
++	u64 size = 0;
++	u64 addr;
++	u64 start;
++#ifdef CONFIG_XEN
++	unsigned int order = get_order(sizet);
++
++	if (is_initial_xendomain()) {
++		sizet = PAGE_SIZE << order;
++		if (align < PAGE_SIZE)
++			align = PAGE_SIZE;
++	}
++#endif
++	for (start = startt; ; start += size) {
++		start = find_e820_area_size(start, &size, align);
++		if (!(start + 1))
++			return 0;
++		if (size >= sizet)
++			break;
++	}
++
++#ifdef CONFIG_X86_32
++	if (start >= MAXMEM)
++		return 0;
++	if (start + size > MAXMEM)
++		size = MAXMEM - start;
++#endif
++#ifdef CONFIG_XEN
++	if ((start >> PAGE_SHIFT) >= xen_start_info->nr_pages)
++		return 0;
++	if (PFN_UP(start + size) > xen_start_info->nr_pages)
++		size = ((u64)xen_start_info->nr_pages << PAGE_SHIFT) - start;
++#endif
++
++	addr = round_down(start + size - sizet, align);
++	if (addr < start)
++		return 0;
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain()) {
++		int rc;
++		unsigned long max_initmap_pfn;
++
++		max_initmap_pfn = ALIGN(PFN_UP(__pa(xen_start_info->pt_base))
++					       + xen_start_info->nr_pt_frames
++					       + 1 + (1 << (19 - PAGE_SHIFT)),
++					1UL << (22 - PAGE_SHIFT));
++#ifdef CONFIG_X86_32
++		if ((addr >> PAGE_SHIFT)
++		    < max(max_initmap_pfn, max_pfn_mapped))
++			rc = xen_create_contiguous_region((unsigned long)
++							  __va(addr),
++							  order, 32);
++#else
++		if ((addr >> PAGE_SHIFT) < max_pfn_mapped)
++			rc = xen_create_contiguous_region((unsigned long)
++							  __va(addr),
++							  order, 32);
++		else if ((addr >> PAGE_SHIFT) < max_initmap_pfn)
++			rc = xen_create_contiguous_region(__START_KERNEL_map
++							  + addr,
++							  order, 32);
++#endif
++		else
++			rc = early_create_contiguous_region(addr >> PAGE_SHIFT,
++							    order, 32);
++		if (rc)
++			return 0;
++	}
++#endif
++	e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
++	e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
++	printk(KERN_INFO "update e820 for early_reserve_e820\n");
++	update_e820();
++	update_e820_saved();
++
++	return addr;
++}
++
++#ifdef CONFIG_X86_32
++# ifdef CONFIG_X86_PAE
++#  define MAX_ARCH_PFN		(1ULL<<(40-PAGE_SHIFT))
++# else
++#  define MAX_ARCH_PFN		(1ULL<<(32-PAGE_SHIFT))
++# endif
++#else /* CONFIG_X86_32 */
++# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT
++#endif
++
++/*
++ * Find the highest page frame number we have available
++ */
++static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
++{
++	int i;
++	unsigned long last_pfn = 0;
++	unsigned long max_arch_pfn = MAX_ARCH_PFN;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long start_pfn;
++		unsigned long end_pfn;
++
++		if (ei->type != type)
++			continue;
++
++		start_pfn = ei->addr >> PAGE_SHIFT;
++		end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;
++
++		if (start_pfn >= limit_pfn)
++			continue;
++		if (end_pfn > limit_pfn) {
++			last_pfn = limit_pfn;
++			break;
++		}
++		if (end_pfn > last_pfn)
++			last_pfn = end_pfn;
++	}
++
++	if (last_pfn > max_arch_pfn)
++		last_pfn = max_arch_pfn;
++
++	printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
++			 last_pfn, max_arch_pfn);
++	return last_pfn;
++}
++unsigned long __init e820_end_of_ram_pfn(void)
++{
++	return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
++}
++
++unsigned long __init e820_end_of_low_ram_pfn(void)
++{
++	return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
++}
++/*
++ * Finds an active region in the address range from start_pfn to last_pfn and
++ * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
++ */
++int __init e820_find_active_region(const struct e820entry *ei,
++				  unsigned long start_pfn,
++				  unsigned long last_pfn,
++				  unsigned long *ei_startpfn,
++				  unsigned long *ei_endpfn)
++{
++	u64 align = PAGE_SIZE;
++
++#ifdef CONFIG_XEN
++	if (last_pfn > xen_start_info->nr_pages)
++		last_pfn = xen_start_info->nr_pages;
++#endif
++
++	*ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
++	*ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
++
++	/* Skip map entries smaller than a page */
++	if (*ei_startpfn >= *ei_endpfn)
++		return 0;
++
++	/* Skip if map is outside the node */
++	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
++				    *ei_startpfn >= last_pfn)
++		return 0;
++
++	/* Check for overlaps */
++	if (*ei_startpfn < start_pfn)
++		*ei_startpfn = start_pfn;
++	if (*ei_endpfn > last_pfn)
++		*ei_endpfn = last_pfn;
++
++	return 1;
++}
++
++/* Walk the e820 map and register active regions within a node */
++void __init e820_register_active_regions(int nid, unsigned long start_pfn,
++					 unsigned long last_pfn)
++{
++	unsigned long ei_startpfn;
++	unsigned long ei_endpfn;
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++)
++		if (e820_find_active_region(&e820.map[i],
++					    start_pfn, last_pfn,
++					    &ei_startpfn, &ei_endpfn))
++			add_active_range(nid, ei_startpfn, ei_endpfn);
++#ifdef CONFIG_XEN
++	BUG_ON(nid);
++	add_active_range(nid, last_pfn, last_pfn);
++#endif
++}
++
++/*
++ * Find the hole size (in bytes) in the memory range.
++ * @start: starting address of the memory range to scan
++ * @end: ending address of the memory range to scan
++ */
++u64 __init e820_hole_size(u64 start, u64 end)
++{
++	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long last_pfn = end >> PAGE_SHIFT;
++	unsigned long ei_startpfn, ei_endpfn, ram = 0;
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		if (e820_find_active_region(&e820.map[i],
++					    start_pfn, last_pfn,
++					    &ei_startpfn, &ei_endpfn))
++			ram += ei_endpfn - ei_startpfn;
++	}
++	return end - start - ((u64)ram << PAGE_SHIFT);
++}
++
++static void early_panic(char *msg)
++{
++	early_printk(msg);
++	panic(msg);
++}
++
++static int userdef __initdata;
++
++/* "mem=nopentium" disables the 4MB page tables. */
++static int __init parse_memopt(char *p)
++{
++	u64 mem_size, current_end;
++	unsigned int i;
++
++	if (!p)
++		return -EINVAL;
++
++#ifdef CONFIG_X86_32
++	if (!strcmp(p, "nopentium")) {
++		setup_clear_cpu_cap(X86_FEATURE_PSE);
++		return 0;
++	}
++#endif
++
++	userdef = 1;
++	mem_size = memparse(p, &p);
++	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
++
++	i = e820.nr_map - 1;
++	current_end = e820.map[i].addr + e820.map[i].size;
++	if (current_end < mem_size) {
++		/*
++		 * The e820 map ends before our requested size so
++		 * extend the final entry to the requested address.
++		 */
++		if (e820.map[i].type == E820_RAM)
++			e820.map[i].size = mem_size - e820.map[i].addr;
++		else
++			e820_add_region(current_end, mem_size - current_end, E820_RAM);
++	}
++
++	return 0;
++}
++early_param("mem", parse_memopt);
++
++#ifndef CONFIG_XEN
++static int __init parse_memmap_opt(char *p)
++{
++	char *oldp;
++	u64 start_at, mem_size;
++
++	if (!p)
++		return -EINVAL;
++
++	if (!strncmp(p, "exactmap", 8)) {
++#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 = e820_end_of_ram_pfn();
++#endif
++		e820.nr_map = 0;
++		userdef = 1;
++		return 0;
++	}
++
++	oldp = p;
++	mem_size = memparse(p, &p);
++	if (p == oldp)
++		return -EINVAL;
++
++	userdef = 1;
++	if (*p == '@') {
++		start_at = memparse(p+1, &p);
++		e820_add_region(start_at, mem_size, E820_RAM);
++	} else if (*p == '#') {
++		start_at = memparse(p+1, &p);
++		e820_add_region(start_at, mem_size, E820_ACPI);
++	} else if (*p == '$') {
++		start_at = memparse(p+1, &p);
++		e820_add_region(start_at, mem_size, E820_RESERVED);
++	} else
++		e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
++
++	return *p == '\0' ? 0 : -EINVAL;
++}
++early_param("memmap", parse_memmap_opt);
++#endif
++
++void __init finish_e820_parsing(void)
++{
++	if (userdef) {
++		int nr = e820.nr_map;
++
++		if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr) < 0)
++			early_panic("Invalid user supplied memory map");
++		e820.nr_map = nr;
++
++		printk(KERN_INFO "user-defined physical RAM map:\n");
++		_e820_print_map(&e820, "user");
++	}
++}
++
++static inline const char *e820_type_to_string(int e820_type)
++{
++	switch (e820_type) {
++	case E820_RESERVED_KERN:
++	case E820_RAM:	return "System RAM";
++	case E820_ACPI:	return "ACPI Tables";
++	case E820_NVS:	return "ACPI Non-volatile Storage";
++	default:	return "reserved";
++	}
++}
++
++#ifdef CONFIG_XEN
++#define e820 machine_e820
++#endif
++
++/*
++ * Mark e820 reserved areas as busy for the resource manager.
++ */
++void __init e820_reserve_resources(void)
++{
++	int i;
++	struct resource *res;
++	u64 end;
++
++	res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
++	for (i = 0; i < e820.nr_map; i++) {
++		end = e820.map[i].addr + e820.map[i].size - 1;
++#ifndef CONFIG_RESOURCES_64BIT
++		if (end > 0x100000000ULL) {
++			res++;
++			continue;
++		}
++#endif
++		res->name = e820_type_to_string(e820.map[i].type);
++		res->start = e820.map[i].addr;
++		res->end = end;
++
++		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++		insert_resource(&iomem_resource, res);
++		res++;
++	}
++
++	for (i = 0; i < e820_saved.nr_map; i++) {
++		struct e820entry *entry = &e820_saved.map[i];
++		firmware_map_add_early(entry->addr,
++			entry->addr + entry->size - 1,
++			e820_type_to_string(entry->type));
++	}
++}
++
++#undef e820
++
++#ifndef CONFIG_XEN
++char *__init default_machine_specific_memory_setup(void)
++{
++	char *who = "BIOS-e820";
++	int new_nr;
++	/*
++	 * Try to copy the BIOS-supplied E820-map.
++	 *
++	 * Otherwise fake a memory map; one section from 0k->640k,
++	 * the next section from 1mb->appropriate_mem_k
++	 */
++	new_nr = boot_params.e820_entries;
++	sanitize_e820_map(boot_params.e820_map,
++			ARRAY_SIZE(boot_params.e820_map),
++			&new_nr);
++	boot_params.e820_entries = new_nr;
++	if (append_e820_map(boot_params.e820_map, boot_params.e820_entries)
++	  < 0) {
++		u64 mem_size;
++
++		/* compare results from other methods and take the greater */
++		if (boot_params.alt_mem_k
++		    < boot_params.screen_info.ext_mem_k) {
++			mem_size = boot_params.screen_info.ext_mem_k;
++			who = "BIOS-88";
++		} else {
++			mem_size = boot_params.alt_mem_k;
++			who = "BIOS-e801";
++		}
++
++		e820.nr_map = 0;
++		e820_add_region(0, LOWMEMSIZE(), E820_RAM);
++		e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
++	}
++
++	/* In case someone cares... */
++	return who;
++}
++
++char *__init __attribute__((weak)) machine_specific_memory_setup(void)
++{
++	if (x86_quirks->arch_memory_setup) {
++		char *who = x86_quirks->arch_memory_setup();
++
++		if (who)
++			return who;
++	}
++	return default_machine_specific_memory_setup();
++}
++#endif
++
++static char * __init _memory_setup(void)
++{
++	int rc, nr_map;
++	struct xen_memory_map memmap;
++	static struct e820entry __initdata map[E820MAX];
++
++	memmap.nr_entries = E820MAX;
++	set_xen_guest_handle(memmap.buffer, map);
++
++	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
++	if (rc == -ENOSYS) {
++		memmap.nr_entries = 1;
++		map[0].addr = 0ULL;
++		map[0].size = PFN_PHYS((unsigned long long)xen_start_info->nr_pages);
++		/* 8MB slack (to balance backend allocations). */
++		map[0].size += 8ULL << 20;
++		map[0].type = E820_RAM;
++		rc = 0;
++	}
++	BUG_ON(rc);
++
++	nr_map = memmap.nr_entries;
++	sanitize_e820_map(map, ARRAY_SIZE(map), &nr_map);
++
++	if (append_e820_map(map, nr_map) < 0)
++		BUG();
++
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain()) {
++		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;
++	}
++#endif
++
++	return "Xen";
++}
++
++void __init setup_memory_map(void)
++{
++	char *who;
++
++	who = _memory_setup();
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain()) {
++		printk(KERN_INFO "Xen-provided machine memory map:\n");
++		_e820_print_map(&machine_e820, "BIOS");
++	} else
++#endif
++		memcpy(&e820_saved, &e820, sizeof(struct e820map));
++	printk(KERN_INFO "Xen-provided physical RAM map:\n");
++	_e820_print_map(&e820, who);
++}
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,860 +0,0 @@
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-#include <linux/ioport.h>
+-#include <linux/string.h>
+-#include <linux/kexec.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/pfn.h>
+-#include <linux/uaccess.h>
+-#include <linux/suspend.h>
+-
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/e820.h>
+-#include <asm/setup.h>
+-#include <xen/interface/memory.h>
+-
+-struct e820map e820;
+-struct change_member {
+-	struct e820entry *pbios; /* pointer to original bios entry */
+-	unsigned long long addr; /* address for this change point */
+-};
+-static struct change_member change_point_list[2*E820MAX] __initdata;
+-static struct change_member *change_point[2*E820MAX] __initdata;
+-static struct e820entry *overlap_list[E820MAX] __initdata;
+-static struct e820entry new_bios[E820MAX] __initdata;
+-/* For PCI or other memory-mapped resources */
+-unsigned long pci_mem_start = 0x10000000;
+-#ifdef CONFIG_PCI
+-EXPORT_SYMBOL(pci_mem_start);
+-#endif
+-extern int user_defined_memmap;
+-
+-static struct resource system_rom_resource = {
+-	.name	= "System ROM",
+-	.start	= 0xf0000,
+-	.end	= 0xfffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-static struct resource extension_rom_resource = {
+-	.name	= "Extension ROM",
+-	.start	= 0xe0000,
+-	.end	= 0xeffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-static struct resource adapter_rom_resources[] = { {
+-	.name 	= "Adapter ROM",
+-	.start	= 0xc8000,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-} };
+-
+-static struct resource video_rom_resource = {
+-	.name 	= "Video ROM",
+-	.start	= 0xc0000,
+-	.end	= 0xc7fff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-#define ROMSIGNATURE 0xaa55
+-
+-static int __init romsignature(const unsigned char *rom)
+-{
+-	const unsigned short * const ptr = (const unsigned short *)rom;
+-	unsigned short sig;
+-
+-	return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
+-}
+-
+-static int __init romchecksum(const unsigned char *rom, unsigned long length)
+-{
+-	unsigned char sum, c;
+-
+-	for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
+-		sum += c;
+-	return !length && !sum;
+-}
+-
+-static void __init probe_roms(void)
+-{
+-	const unsigned char *rom;
+-	unsigned long start, length, upper;
+-	unsigned char c;
+-	int i;
+-
+-#ifdef CONFIG_XEN
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return;
+-#endif
+-
+-	/* video rom */
+-	upper = adapter_rom_resources[0].start;
+-	for (start = video_rom_resource.start; start < upper; start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		video_rom_resource.start = start;
+-
+-		if (probe_kernel_address(rom + 2, c) != 0)
+-			continue;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = c * 512;
+-
+-		/* if checksum okay, trust length byte */
+-		if (length && romchecksum(rom, length))
+-			video_rom_resource.end = start + length - 1;
+-
+-		request_resource(&iomem_resource, &video_rom_resource);
+-		break;
+-	}
+-
+-	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+-	if (start < upper)
+-		start = upper;
+-
+-	/* system rom */
+-	request_resource(&iomem_resource, &system_rom_resource);
+-	upper = system_rom_resource.start;
+-
+-	/* check for extension rom (ignore length byte!) */
+-	rom = isa_bus_to_virt((unsigned long)extension_rom_resource.start);
+-	if (romsignature(rom)) {
+-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+-		if (romchecksum(rom, length)) {
+-			request_resource(&iomem_resource, &extension_rom_resource);
+-			upper = extension_rom_resource.start;
+-		}
+-	}
+-
+-	/* check for adapter roms on 2k boundaries */
+-	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		if (probe_kernel_address(rom + 2, c) != 0)
+-			continue;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = c * 512;
+-
+-		/* but accept any length that fits if checksum okay */
+-		if (!length || start + length > upper || !romchecksum(rom, length))
+-			continue;
+-
+-		adapter_rom_resources[i].start = start;
+-		adapter_rom_resources[i].end = start + length - 1;
+-		request_resource(&iomem_resource, &adapter_rom_resources[i]);
+-
+-		start = adapter_rom_resources[i++].end & ~2047UL;
+-	}
+-}
+-
+-#ifdef CONFIG_XEN
+-static struct e820map machine_e820;
+-#define e820 machine_e820
+-#endif
+-
+-/*
+- * Request address space for all standard RAM and ROM resources
+- * and also for regions reported as reserved by the e820.
+- */
+-void __init init_iomem_resources(struct resource *code_resource,
+-		struct resource *data_resource,
+-		struct resource *bss_resource)
+-{
+-	int i;
+-
+-	probe_roms();
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct resource *res;
+-#ifndef CONFIG_RESOURCES_64BIT
+-		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
+-			continue;
+-#endif
+-		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+-		switch (e820.map[i].type) {
+-		case E820_RAM:	res->name = "System RAM"; break;
+-		case E820_ACPI:	res->name = "ACPI Tables"; break;
+-		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
+-		default:	res->name = "reserved";
+-		}
+-		res->start = e820.map[i].addr;
+-		res->end = res->start + e820.map[i].size - 1;
+-		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		if (request_resource(&iomem_resource, res)) {
+-			kfree(res);
+-			continue;
+-		}
+-		if (e820.map[i].type == E820_RAM) {
+-			/*
+-			 *  We don't know which RAM region contains kernel data,
+-			 *  so we try it repeatedly and let the resource manager
+-			 *  test it.
+-			 */
+-#ifndef CONFIG_XEN
+-			request_resource(res, code_resource);
+-			request_resource(res, data_resource);
+-			request_resource(res, bss_resource);
+-#endif
+-#ifdef CONFIG_KEXEC
+-			if (crashk_res.start != crashk_res.end)
+-				request_resource(res, &crashk_res);
+-#ifdef CONFIG_XEN
+-			xen_machine_kexec_register_resources(res);
+-#endif
+-#endif
+-		}
+-	}
+-}
+-
+-#undef e820
+-
+-#if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)
+-/**
+- * e820_mark_nosave_regions - Find the ranges of physical addresses that do not
+- * correspond to e820 RAM areas and mark the corresponding pages as nosave for
+- * hibernation.
+- *
+- * This function requires the e820 map to be sorted and without any
+- * overlapping entries and assumes the first e820 area to be RAM.
+- */
+-void __init e820_mark_nosave_regions(void)
+-{
+-	int i;
+-	unsigned long pfn;
+-
+-	pfn = PFN_DOWN(e820.map[0].addr + e820.map[0].size);
+-	for (i = 1; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-
+-		if (pfn < PFN_UP(ei->addr))
+-			register_nosave_region(pfn, PFN_UP(ei->addr));
+-
+-		pfn = PFN_DOWN(ei->addr + ei->size);
+-		if (ei->type != E820_RAM)
+-			register_nosave_region(PFN_UP(ei->addr), pfn);
+-
+-		if (pfn >= max_low_pfn)
+-			break;
+-	}
+-}
+-#endif
+-
+-void __init add_memory_region(unsigned long long start,
+-			      unsigned long long size, int type)
+-{
+-	int x;
+-
+-	x = e820.nr_map;
+-
+-	if (x == E820MAX) {
+-		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+-		return;
+-	}
+-
+-	e820.map[x].addr = start;
+-	e820.map[x].size = size;
+-	e820.map[x].type = type;
+-	e820.nr_map++;
+-} /* add_memory_region */
+-
+-/*
+- * Sanitize the BIOS e820 map.
+- *
+- * Some e820 responses include overlapping entries.  The following
+- * replaces the original e820 map with a new one, removing overlaps.
+- *
+- */
+-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+-{
+-	struct change_member *change_tmp;
+-	unsigned long current_type, last_type;
+-	unsigned long long last_addr;
+-	int chgidx, still_changing;
+-	int overlap_entries;
+-	int new_bios_entry;
+-	int old_nr, new_nr, chg_nr;
+-	int i;
+-
+-	/*
+-		Visually we're performing the following (1,2,3,4 = memory types)...
+-
+-		Sample memory map (w/overlaps):
+-		   ____22__________________
+-		   ______________________4_
+-		   ____1111________________
+-		   _44_____________________
+-		   11111111________________
+-		   ____________________33__
+-		   ___________44___________
+-		   __________33333_________
+-		   ______________22________
+-		   ___________________2222_
+-		   _________111111111______
+-		   _____________________11_
+-		   _________________4______
+-
+-		Sanitized equivalent (no overlap):
+-		   1_______________________
+-		   _44_____________________
+-		   ___1____________________
+-		   ____22__________________
+-		   ______11________________
+-		   _________1______________
+-		   __________3_____________
+-		   ___________44___________
+-		   _____________33_________
+-		   _______________2________
+-		   ________________1_______
+-		   _________________4______
+-		   ___________________2____
+-		   ____________________33__
+-		   ______________________4_
+-	*/
+-	/* if there's only one memory region, don't bother */
+-	if (*pnr_map < 2) {
+-		return -1;
+-	}
+-
+-	old_nr = *pnr_map;
+-
+-	/* bail out if we find any unreasonable addresses in bios map */
+-	for (i=0; i<old_nr; i++)
+-		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
+-			return -1;
+-		}
+-
+-	/* create pointers for initial change-point information (for sorting) */
+-	for (i=0; i < 2*old_nr; i++)
+-		change_point[i] = &change_point_list[i];
+-
+-	/* record all known change-points (starting and ending addresses),
+-	   omitting those that are for empty memory regions */
+-	chgidx = 0;
+-	for (i=0; i < old_nr; i++)	{
+-		if (biosmap[i].size != 0) {
+-			change_point[chgidx]->addr = biosmap[i].addr;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-		}
+-	}
+-	chg_nr = chgidx;    	/* true number of change-points */
+-
+-	/* sort change-point list by memory addresses (low -> high) */
+-	still_changing = 1;
+-	while (still_changing)	{
+-		still_changing = 0;
+-		for (i=1; i < chg_nr; i++)  {
+-			/* if <current_addr> > <last_addr>, swap */
+-			/* or, if current=<start_addr> & last=<end_addr>, swap */
+-			if ((change_point[i]->addr < change_point[i-1]->addr) ||
+-				((change_point[i]->addr == change_point[i-1]->addr) &&
+-				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
+-				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+-			   )
+-			{
+-				change_tmp = change_point[i];
+-				change_point[i] = change_point[i-1];
+-				change_point[i-1] = change_tmp;
+-				still_changing=1;
+-			}
+-		}
+-	}
+-
+-	/* create a new bios memory map, removing overlaps */
+-	overlap_entries=0;	 /* number of entries in the overlap table */
+-	new_bios_entry=0;	 /* index for creating new bios map entries */
+-	last_type = 0;		 /* start with undefined memory type */
+-	last_addr = 0;		 /* start with 0 as last starting address */
+-	/* loop through change-points, determining affect on the new bios map */
+-	for (chgidx=0; chgidx < chg_nr; chgidx++)
+-	{
+-		/* keep track of all overlapping bios entries */
+-		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+-		{
+-			/* add map entry to overlap list (> 1 entry implies an overlap) */
+-			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+-		}
+-		else
+-		{
+-			/* remove entry from list (order independent, so swap with last) */
+-			for (i=0; i<overlap_entries; i++)
+-			{
+-				if (overlap_list[i] == change_point[chgidx]->pbios)
+-					overlap_list[i] = overlap_list[overlap_entries-1];
+-			}
+-			overlap_entries--;
+-		}
+-		/* if there are overlapping entries, decide which "type" to use */
+-		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+-		current_type = 0;
+-		for (i=0; i<overlap_entries; i++)
+-			if (overlap_list[i]->type > current_type)
+-				current_type = overlap_list[i]->type;
+-		/* continue building up new bios map based on this information */
+-		if (current_type != last_type)	{
+-			if (last_type != 0)	 {
+-				new_bios[new_bios_entry].size =
+-					change_point[chgidx]->addr - last_addr;
+-				/* move forward only if the new size was non-zero */
+-				if (new_bios[new_bios_entry].size != 0)
+-					if (++new_bios_entry >= E820MAX)
+-						break; 	/* no more space left for new bios entries */
+-			}
+-			if (current_type != 0)	{
+-				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+-				new_bios[new_bios_entry].type = current_type;
+-				last_addr=change_point[chgidx]->addr;
+-			}
+-			last_type = current_type;
+-		}
+-	}
+-	new_nr = new_bios_entry;   /* retain count for new bios entries */
+-
+-	/* copy new bios mapping into original location */
+-	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+-	*pnr_map = new_nr;
+-
+-	return 0;
+-}
+-
+-/*
+- * Copy the BIOS e820 map into a safe place.
+- *
+- * Sanity-check it while we're at it..
+- *
+- * If we're lucky and live on a modern system, the setup code
+- * will have given us a memory map that we can use to properly
+- * set up memory.  If we aren't, we'll fake a memory map.
+- *
+- * We check to see that the memory map contains at least 2 elements
+- * before we'll use it, because the detection code in setup.S may
+- * not be perfect and most every PC known to man has two memory
+- * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
+- * thinkpad 560x, for example, does not cooperate with the memory
+- * detection code.)
+- */
+-int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+-{
+-#ifndef CONFIG_XEN
+-	/* Only one memory region (or negative)? Ignore it */
+-	if (nr_map < 2)
+-		return -1;
+-#else
+-	BUG_ON(nr_map < 1);
+-#endif
+-
+-	do {
+-		u64 start = biosmap->addr;
+-		u64 size = biosmap->size;
+-		u64 end = start + size;
+-		u32 type = biosmap->type;
+-
+-		/* Overflow in 64 bits? Ignore the memory map. */
+-		if (start > end)
+-			return -1;
+-
+-		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;
+-}
+-
+-/*
+- * Find the highest page frame number we have available
+- */
+-void __init propagate_e820_map(void)
+-{
+-	int i;
+-
+-	max_pfn = 0;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		unsigned long start, end;
+-		/* RAM? */
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-		start = PFN_UP(e820.map[i].addr);
+-		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+-		if (start >= end)
+-			continue;
+-		if (end > max_pfn)
+-			max_pfn = end;
+-		memory_present(0, start, end);
+-	}
+-}
+-
+-/*
+- * Register fully available low RAM pages with the bootmem allocator.
+- */
+-void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		unsigned long curr_pfn, last_pfn, size;
+-		/*
+-		 * Reserve usable low memory
+-		 */
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-		/*
+-		 * We are rounding up the start address of usable memory:
+-		 */
+-		curr_pfn = PFN_UP(e820.map[i].addr);
+-		if (curr_pfn >= max_low_pfn)
+-			continue;
+-		/*
+-		 * ... and at the end of the usable range downwards:
+-		 */
+-		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+-
+-#ifdef CONFIG_XEN
+-		/*
+-		 * Truncate to the number of actual pages currently
+-		 * present.
+-		 */
+-		if (last_pfn > xen_start_info->nr_pages)
+-			last_pfn = xen_start_info->nr_pages;
+-#endif
+-
+-		if (last_pfn > max_low_pfn)
+-			last_pfn = max_low_pfn;
+-
+-		/*
+-		 * .. finally, did all the rounding and playing
+-		 * around just make the area go away?
+-		 */
+-		if (last_pfn <= curr_pfn)
+-			continue;
+-
+-		size = last_pfn - curr_pfn;
+-		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+-	}
+-}
+-
+-void __init e820_register_memory(void)
+-{
+-	unsigned long gapstart, gapsize, round;
+-	unsigned long long last;
+-	int i;
+-
+-#ifdef CONFIG_XEN
+-#define e820 machine_e820
+-#endif
+-	/*
+-	 * Search for the biggest gap in the low 32 bits of the e820
+-	 * memory space.
+-	 */
+-	last = 0x100000000ull;
+-	gapstart = 0x10000000;
+-	gapsize = 0x400000;
+-	i = e820.nr_map;
+-	while (--i >= 0) {
+-		unsigned long long start = e820.map[i].addr;
+-		unsigned long long end = start + e820.map[i].size;
+-
+-		/*
+-		 * Since "last" is at most 4GB, we know we'll
+-		 * fit in 32 bits if this condition is true
+-		 */
+-		if (last > end) {
+-			unsigned long gap = last - end;
+-
+-			if (gap > gapsize) {
+-				gapsize = gap;
+-				gapstart = end;
+-			}
+-		}
+-		if (start < last)
+-			last = start;
+-	}
+-#undef e820
+-
+-	/*
+-	 * See how much we want to round up: start off with
+-	 * rounding to the next 1MB area.
+-	 */
+-	round = 0x100000;
+-	while ((gapsize >> 4) > round)
+-		round += round;
+-	/* Fun with two's complement */
+-	pci_mem_start = (gapstart + round) & -round;
+-
+-	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
+-		pci_mem_start, gapstart, gapsize);
+-}
+-
+-void __init print_memory_map(char *who)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		printk(" %s: %016Lx - %016Lx ", who,
+-			e820.map[i].addr,
+-			e820.map[i].addr + e820.map[i].size);
+-		switch (e820.map[i].type) {
+-		case E820_RAM:	printk("(usable)\n");
+-				break;
+-		case E820_RESERVED:
+-				printk("(reserved)\n");
+-				break;
+-		case E820_ACPI:
+-				printk("(ACPI data)\n");
+-				break;
+-		case E820_NVS:
+-				printk("(ACPI NVS)\n");
+-				break;
+-		default:	printk("type %u\n", e820.map[i].type);
+-				break;
+-		}
+-	}
+-}
+-
+-void __init limit_regions(unsigned long long size)
+-{
+-	unsigned long long current_addr = 0;
+-	int i;
+-
+-	print_memory_map("limit_regions start");
+-	for (i = 0; i < e820.nr_map; i++) {
+-		current_addr = e820.map[i].addr + e820.map[i].size;
+-		if (current_addr < size)
+-			continue;
+-
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-
+-		if (e820.map[i].addr >= size) {
+-			/*
+-			 * This region starts past the end of the
+-			 * requested size, skip it completely.
+-			 */
+-			e820.nr_map = i;
+-		} else {
+-			e820.nr_map = i + 1;
+-			e820.map[i].size -= current_addr - size;
+-		}
+-		print_memory_map("limit_regions endfor");
+-		return;
+-	}
+-#ifdef CONFIG_XEN
+-	if (current_addr < size) {
+-		/*
+-		 * The e820 map finished before our requested size so
+-		 * extend the final entry to the requested address.
+-		 */
+-		--i;
+-		if (e820.map[i].type == E820_RAM)
+-			e820.map[i].size -= current_addr - size;
+-		else
+-			add_memory_region(current_addr, size - current_addr, E820_RAM);
+-	}
+-#endif
+-	print_memory_map("limit_regions endfunc");
+-}
+-
+-/*
+- * 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;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		const struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; ++i) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-
+-		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.
+-  *
+-  * Note: this function only works correct if the e820 table is sorted and
+-  * not-overlapping, which is the case
+-  */
+-int __init
+-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
+-{
+-	u64 start = s;
+-	u64 end = e;
+-	int i;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; ++i) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-
+-		if (type && ei->type != type)
+-			continue;
+-		/* is the region (part) in overlap with the current region ?*/
+-		if (ei->addr >= end || ei->addr + ei->size <= start)
+-			continue;
+-		/* if the region is at the beginning of <start,end> we move
+-		 * start to the end of the region since it's ok until there
+-		 */
+-		if (ei->addr <= start)
+-			start = ei->addr + ei->size;
+-		/* if start is now at or beyond end, we're done, full
+-		 * coverage */
+-		if (start >= end)
+-			return 1; /* we're done */
+-	}
+-	return 0;
+-}
+-
+-static int __init parse_memmap(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	if (strcmp(arg, "exactmap") == 0) {
+-#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.
+-		 */
+-		propagate_e820_map();
+-		saved_max_pfn = max_pfn;
+-#endif
+-		e820.nr_map = 0;
+-		user_defined_memmap = 1;
+-	} else {
+-		/* If the user specifies memory size, we
+-		 * limit the BIOS-provided memory map to
+-		 * that size. exactmap can be used to specify
+-		 * the exact map. mem=number can be used to
+-		 * trim the existing memory map.
+-		 */
+-		unsigned long long start_at, mem_size;
+-
+-		mem_size = memparse(arg, &arg);
+-		if (*arg == '@') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_RAM);
+-		} else if (*arg == '#') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_ACPI);
+-		} else if (*arg == '$') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_RESERVED);
+-		} else {
+-			limit_regions(mem_size);
+-			user_defined_memmap = 1;
+-		}
+-	}
+-	return 0;
+-}
+-early_param("memmap", parse_memmap);
+-
+-#ifndef CONFIG_XEN
+-void __init update_memory_range(u64 start, u64 size, unsigned old_type,
+-				unsigned new_type)
+-{
+-	int i;
+-
+-	BUG_ON(old_type == new_type);
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		u64 final_start, final_end;
+-		if (ei->type != old_type)
+-			continue;
+-		/* totally covered? */
+-		if (ei->addr >= start && ei->size <= size) {
+-			ei->type = new_type;
+-			continue;
+-		}
+-		/* partially covered */
+-		final_start = max(start, ei->addr);
+-		final_end = min(start + size, ei->addr + ei->size);
+-		if (final_start >= final_end)
+-			continue;
+-		add_memory_region(final_start, final_end - final_start,
+-					 new_type);
+-	}
+-}
+-
+-void __init update_e820(void)
+-{
+-	u8 nr_map;
+-
+-	nr_map = e820.nr_map;
+-	if (sanitize_e820_map(e820.map, &nr_map))
+-		return;
+-	e820.nr_map = nr_map;
+-	printk(KERN_INFO "modified physical RAM map:\n");
+-	print_memory_map("modified");
+-}
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:09:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1052 +0,0 @@
+-/*
+- * Handle the memory map.
+- * The functions here do the job until bootmem takes over.
+- *
+- *  Getting sanitize_e820_map() in sync with i386 version by applying change:
+- *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
+- *     Alex Achenbach <xela@slit.de>, December 2002.
+- *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+- *
+- */
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/bootmem.h>
+-#include <linux/ioport.h>
+-#include <linux/string.h>
+-#include <linux/kexec.h>
+-#include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/suspend.h>
+-#include <linux/pfn.h>
+-
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/e820.h>
+-#include <asm/proto.h>
+-#include <asm/setup.h>
+-#include <asm/sections.h>
+-#include <asm/kdebug.h>
+-#include <xen/interface/memory.h>
+-
+-struct e820map e820 __initdata;
+-#ifdef CONFIG_XEN
+-struct e820map machine_e820;
+-#endif
+-
+-/*
+- * PFN of last memory page.
+- */
+-unsigned long end_pfn;
+-
+-#ifndef CONFIG_XEN
+-/*
+- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+- * The direct mapping extends to max_pfn_mapped, so that we can directly access
+- * apertures, ACPI and other tables without having to play with fixmaps.
+- */
+-unsigned long max_pfn_mapped;
+-#endif
+-
+-/*
+- * Last pfn which the user wants to use.
+- */
+-static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
+-
+-/*
+- * Early reserved memory areas.
+- */
+-#define MAX_EARLY_RES 20
+-
+-struct early_res {
+-	unsigned long start, end;
+-	char name[16];
+-};
+-static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+-#ifndef CONFIG_XEN
+-	{ 0, PAGE_SIZE, "BIOS data page" },			/* BIOS data page */
+-#ifdef CONFIG_X86_TRAMPOLINE
+-	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
+-#endif
+-#endif
+-	{}
+-};
+-
+-void __init reserve_early(unsigned long start, unsigned long end, char *name)
+-{
+-	int i;
+-	struct early_res *r;
+-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+-		r = &early_res[i];
+-		if (end > r->start && start < r->end)
+-			panic("Overlapping early reservations %lx-%lx %s to %lx-%lx %s\n",
+-			      start, end - 1, name?name:"", r->start, r->end - 1, r->name);
+-	}
+-	if (i >= MAX_EARLY_RES)
+-		panic("Too many early reservations");
+-	r = &early_res[i];
+-	r->start = start;
+-	r->end = end;
+-	if (name)
+-		strncpy(r->name, name, sizeof(r->name) - 1);
+-}
+-
+-void __init free_early(unsigned long start, unsigned long end)
+-{
+-	struct early_res *r;
+-	int i, j;
+-
+-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+-		r = &early_res[i];
+-		if (start == r->start && end == r->end)
+-			break;
+-	}
+-	if (i >= MAX_EARLY_RES || !early_res[i].end)
+-		panic("free_early on not reserved area: %lx-%lx!", start, end);
+-
+-	for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
+-		;
+-
+-	memmove(&early_res[i], &early_res[i + 1],
+-	       (j - 1 - i) * sizeof(struct early_res));
+-
+-	early_res[j - 1].end = 0;
+-}
+-
+-void __init early_res_to_bootmem(unsigned long start, unsigned long end)
+-{
+-	int i;
+-	unsigned long final_start, final_end;
+-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+-		struct early_res *r = &early_res[i];
+-		final_start = max(start, r->start);
+-		final_end = min(end, r->end);
+-		if (final_start >= final_end)
+-			continue;
+-		printk(KERN_INFO "  early res: %d [%lx-%lx] %s\n", i,
+-			final_start, final_end - 1, r->name);
+-		reserve_bootmem_generic(final_start, final_end - final_start);
+-	}
+-}
+-
+-/* Check for already reserved areas */
+-static inline int __init
+-bad_addr(unsigned long *addrp, unsigned long size, unsigned long align)
+-{
+-	int i;
+-	unsigned long addr = *addrp, last;
+-	int changed = 0;
+-again:
+-	last = addr + size;
+-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+-		struct early_res *r = &early_res[i];
+-		if (last >= r->start && addr < r->end) {
+-			*addrp = addr = round_up(r->end, align);
+-			changed = 1;
+-			goto again;
+-		}
+-	}
+-	return changed;
+-}
+-
+-/* Check for already reserved areas */
+-static inline int __init
+-bad_addr_size(unsigned long *addrp, unsigned long *sizep, unsigned long align)
+-{
+-	int i;
+-	unsigned long addr = *addrp, last;
+-	unsigned long size = *sizep;
+-	int changed = 0;
+-again:
+-	last = addr + size;
+-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+-		struct early_res *r = &early_res[i];
+-		if (last > r->start && addr < r->start) {
+-			size = r->start - addr;
+-			changed = 1;
+-			goto again;
+-		}
+-		if (last > r->end && addr < r->end) {
+-			addr = round_up(r->end, align);
+-			size = last - addr;
+-			changed = 1;
+-			goto again;
+-		}
+-		if (last <= r->end && addr >= r->start) {
+-			(*sizep)++;
+-			return 0;
+-		}
+-	}
+-	if (changed) {
+-		*addrp = addr;
+-		*sizep = size;
+-	}
+-	return changed;
+-}
+-/*
+- * This function checks if any part of the range <start,end> is mapped
+- * with type.
+- */
+-int
+-e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
+-{
+-	int i;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; i++) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-
+-		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.
+- *
+- * Note: this function only works correct if the e820 table is sorted and
+- * not-overlapping, which is the case
+- */
+-int __init e820_all_mapped(unsigned long start, unsigned long end,
+-			   unsigned type)
+-{
+-	int i;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; i++) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-
+-		if (type && ei->type != type)
+-			continue;
+-		/* is the region (part) in overlap with the current region ?*/
+-		if (ei->addr >= end || ei->addr + ei->size <= start)
+-			continue;
+-
+-		/* if the region is at the beginning of <start,end> we move
+-		 * start to the end of the region since it's ok until there
+-		 */
+-		if (ei->addr <= start)
+-			start = ei->addr + ei->size;
+-		/*
+-		 * if start is now at or beyond end, we're done, full
+-		 * coverage
+-		 */
+-		if (start >= end)
+-			return 1;
+-	}
+-	return 0;
+-}
+-
+-/*
+- * Find a free area with specified alignment in a specific range.
+- */
+-unsigned long __init find_e820_area(unsigned long start, unsigned long end,
+-				    unsigned long size, unsigned long align)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		unsigned long addr, last;
+-		unsigned long ei_last;
+-
+-		if (ei->type != E820_RAM)
+-			continue;
+-		addr = round_up(ei->addr, align);
+-		ei_last = ei->addr + ei->size;
+-		if (addr < start)
+-			addr = round_up(start, align);
+-		if (addr >= ei_last)
+-			continue;
+-		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+-			;
+-		last = addr + size;
+-		if (last > ei_last)
+-			continue;
+-		if (last > end)
+-			continue;
+-		return addr;
+-	}
+-	return -1UL;
+-}
+-
+-/*
+- * Find next free range after *start
+- */
+-unsigned long __init find_e820_area_size(unsigned long start,
+-					 unsigned long *sizep,
+-					 unsigned long align)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		unsigned long addr, last;
+-		unsigned long ei_last;
+-
+-		if (ei->type != E820_RAM)
+-			continue;
+-		addr = round_up(ei->addr, align);
+-		ei_last = ei->addr + ei->size;
+-		if (addr < start)
+-			addr = round_up(start, align);
+-		if (addr >= ei_last)
+-			continue;
+-		*sizep = ei_last - addr;
+-		while (bad_addr_size(&addr, sizep, align) &&
+-			addr + *sizep <= ei_last)
+-			;
+-		last = addr + *sizep;
+-		if (last > ei_last)
+-			continue;
+-		return addr;
+-	}
+-	return -1UL;
+-
+-}
+-/*
+- * Find the highest page frame number we have available
+- */
+-unsigned long __init e820_end_of_ram(void)
+-{
+-	unsigned long end_pfn;
+-
+-	end_pfn = find_max_pfn_with_active_regions();
+-
+-	if (end_pfn > max_pfn_mapped)
+-		max_pfn_mapped = end_pfn;
+-	if (max_pfn_mapped > MAXMEM>>PAGE_SHIFT)
+-		max_pfn_mapped = MAXMEM>>PAGE_SHIFT;
+-	if (end_pfn > end_user_pfn)
+-		end_pfn = end_user_pfn;
+-	if (end_pfn > max_pfn_mapped)
+-		end_pfn = max_pfn_mapped;
+-
+-	printk(KERN_INFO "max_pfn_mapped = %lu\n", max_pfn_mapped);
+-	return end_pfn;
+-}
+-
+-/*
+- * Mark e820 reserved areas as busy for the resource manager.
+- */
+-void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
+-{
+-	int i;
+-	struct resource *res;
+-
+-	res = alloc_bootmem_low(sizeof(struct resource) * nr_map);
+-	for (i = 0; i < nr_map; i++) {
+-		switch (e820[i].type) {
+-		case E820_RAM:	res->name = "System RAM"; break;
+-		case E820_ACPI:	res->name = "ACPI Tables"; break;
+-		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
+-		default:	res->name = "reserved";
+-		}
+-		res->start = e820[i].addr;
+-		res->end = res->start + e820[i].size - 1;
+-		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		insert_resource(&iomem_resource, res);
+-		res++;
+-	}
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Find the ranges of physical addresses that do not correspond to
+- * e820 RAM areas and mark the corresponding pages as nosave for software
+- * suspend and suspend to RAM.
+- *
+- * This function requires the e820 map to be sorted and without any
+- * overlapping entries and assumes the first e820 area to be RAM.
+- */
+-void __init e820_mark_nosave_regions(void)
+-{
+-	int i;
+-	unsigned long paddr;
+-
+-	paddr = round_down(e820.map[0].addr + e820.map[0].size, PAGE_SIZE);
+-	for (i = 1; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-
+-		if (paddr < ei->addr)
+-			register_nosave_region(PFN_DOWN(paddr),
+-						PFN_UP(ei->addr));
+-
+-		paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
+-		if (ei->type != E820_RAM)
+-			register_nosave_region(PFN_UP(ei->addr),
+-						PFN_DOWN(paddr));
+-
+-		if (paddr >= (end_pfn << PAGE_SHIFT))
+-			break;
+-	}
+-}
+-#endif
+-
+-/*
+- * Finds an active region in the address range from start_pfn to end_pfn and
+- * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
+- */
+-static int __init e820_find_active_region(const struct e820entry *ei,
+-					  unsigned long start_pfn,
+-					  unsigned long end_pfn,
+-					  unsigned long *ei_startpfn,
+-					  unsigned long *ei_endpfn)
+-{
+-#ifdef CONFIG_XEN
+-	if (end_pfn > xen_start_info->nr_pages)
+-		end_pfn = xen_start_info->nr_pages;
+-#endif
+-
+-	*ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
+-	*ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE) >> PAGE_SHIFT;
+-
+-	/* Skip map entries smaller than a page */
+-	if (*ei_startpfn >= *ei_endpfn)
+-		return 0;
+-
+-	/* Check if max_pfn_mapped should be updated */
+-	if (ei->type != E820_RAM && *ei_endpfn > max_pfn_mapped)
+-		max_pfn_mapped = *ei_endpfn;
+-
+-	/* Skip if map is outside the node */
+-	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
+-				    *ei_startpfn >= end_pfn)
+-		return 0;
+-
+-	/* Check for overlaps */
+-	if (*ei_startpfn < start_pfn)
+-		*ei_startpfn = start_pfn;
+-	if (*ei_endpfn > end_pfn)
+-		*ei_endpfn = end_pfn;
+-
+-	/* Obey end_user_pfn to save on memmap */
+-	if (*ei_startpfn >= end_user_pfn)
+-		return 0;
+-	if (*ei_endpfn > end_user_pfn)
+-		*ei_endpfn = end_user_pfn;
+-
+-	return 1;
+-}
+-
+-/* Walk the e820 map and register active regions within a node */
+-void __init
+-e820_register_active_regions(int nid, unsigned long start_pfn,
+-							unsigned long end_pfn)
+-{
+-	unsigned long ei_startpfn;
+-	unsigned long ei_endpfn;
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++)
+-		if (e820_find_active_region(&e820.map[i],
+-					    start_pfn, end_pfn,
+-					    &ei_startpfn, &ei_endpfn))
+-			add_active_range(nid, ei_startpfn, ei_endpfn);
+-#ifdef CONFIG_XEN
+-	BUG_ON(nid);
+-	add_active_range(nid, end_pfn, end_pfn);
+-#endif
+-}
+-
+-/*
+- * Add a memory region to the kernel e820 map.
+- */
+-void __init add_memory_region(unsigned long start, unsigned long size, int type)
+-{
+-	int x = e820.nr_map;
+-
+-	if (x == E820MAX) {
+-		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+-		return;
+-	}
+-
+-	e820.map[x].addr = start;
+-	e820.map[x].size = size;
+-	e820.map[x].type = type;
+-	e820.nr_map++;
+-}
+-
+-/*
+- * Find the hole size (in bytes) in the memory range.
+- * @start: starting address of the memory range to scan
+- * @end: ending address of the memory range to scan
+- */
+-unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
+-{
+-	unsigned long start_pfn = start >> PAGE_SHIFT;
+-	unsigned long end_pfn = end >> PAGE_SHIFT;
+-	unsigned long ei_startpfn, ei_endpfn, ram = 0;
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		if (e820_find_active_region(&e820.map[i],
+-					    start_pfn, end_pfn,
+-					    &ei_startpfn, &ei_endpfn))
+-			ram += ei_endpfn - ei_startpfn;
+-	}
+-	return end - start - (ram << PAGE_SHIFT);
+-}
+-
+-static void __init e820_print_map(char *who)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
+-		       (unsigned long long) e820.map[i].addr,
+-		       (unsigned long long)
+-		       (e820.map[i].addr + e820.map[i].size));
+-		switch (e820.map[i].type) {
+-		case E820_RAM:
+-			printk(KERN_CONT "(usable)\n");
+-			break;
+-		case E820_RESERVED:
+-			printk(KERN_CONT "(reserved)\n");
+-			break;
+-		case E820_ACPI:
+-			printk(KERN_CONT "(ACPI data)\n");
+-			break;
+-		case E820_NVS:
+-			printk(KERN_CONT "(ACPI NVS)\n");
+-			break;
+-		default:
+-			printk(KERN_CONT "type %u\n", e820.map[i].type);
+-			break;
+-		}
+-	}
+-}
+-
+-/*
+- * Sanitize the BIOS e820 map.
+- *
+- * Some e820 responses include overlapping entries. The following
+- * replaces the original e820 map with a new one, removing overlaps.
+- *
+- */
+-static int __init sanitize_e820_map(struct e820entry *biosmap, char *pnr_map)
+-{
+-	struct change_member {
+-		struct e820entry *pbios; /* pointer to original bios entry */
+-		unsigned long long addr; /* address for this change point */
+-	};
+-	static struct change_member change_point_list[2*E820MAX] __initdata;
+-	static struct change_member *change_point[2*E820MAX] __initdata;
+-	static struct e820entry *overlap_list[E820MAX] __initdata;
+-	static struct e820entry new_bios[E820MAX] __initdata;
+-	struct change_member *change_tmp;
+-	unsigned long current_type, last_type;
+-	unsigned long long last_addr;
+-	int chgidx, still_changing;
+-	int overlap_entries;
+-	int new_bios_entry;
+-	int old_nr, new_nr, chg_nr;
+-	int i;
+-
+-	/*
+-		Visually we're performing the following
+-		(1,2,3,4 = memory types)...
+-
+-		Sample memory map (w/overlaps):
+-		   ____22__________________
+-		   ______________________4_
+-		   ____1111________________
+-		   _44_____________________
+-		   11111111________________
+-		   ____________________33__
+-		   ___________44___________
+-		   __________33333_________
+-		   ______________22________
+-		   ___________________2222_
+-		   _________111111111______
+-		   _____________________11_
+-		   _________________4______
+-
+-		Sanitized equivalent (no overlap):
+-		   1_______________________
+-		   _44_____________________
+-		   ___1____________________
+-		   ____22__________________
+-		   ______11________________
+-		   _________1______________
+-		   __________3_____________
+-		   ___________44___________
+-		   _____________33_________
+-		   _______________2________
+-		   ________________1_______
+-		   _________________4______
+-		   ___________________2____
+-		   ____________________33__
+-		   ______________________4_
+-	*/
+-
+-	/* if there's only one memory region, don't bother */
+-	if (*pnr_map < 2)
+-		return -1;
+-
+-	old_nr = *pnr_map;
+-
+-	/* bail out if we find any unreasonable addresses in bios map */
+-	for (i = 0; i < old_nr; i++)
+-		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+-			return -1;
+-
+-	/* create pointers for initial change-point information (for sorting) */
+-	for (i = 0; i < 2 * old_nr; i++)
+-		change_point[i] = &change_point_list[i];
+-
+-	/* record all known change-points (starting and ending addresses),
+-	   omitting those that are for empty memory regions */
+-	chgidx = 0;
+-	for (i = 0; i < old_nr; i++)	{
+-		if (biosmap[i].size != 0) {
+-			change_point[chgidx]->addr = biosmap[i].addr;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-			change_point[chgidx]->addr = biosmap[i].addr +
+-				biosmap[i].size;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-		}
+-	}
+-	chg_nr = chgidx;
+-
+-	/* sort change-point list by memory addresses (low -> high) */
+-	still_changing = 1;
+-	while (still_changing)	{
+-		still_changing = 0;
+-		for (i = 1; i < chg_nr; i++)  {
+-			unsigned long long curaddr, lastaddr;
+-			unsigned long long curpbaddr, lastpbaddr;
+-
+-			curaddr = change_point[i]->addr;
+-			lastaddr = change_point[i - 1]->addr;
+-			curpbaddr = change_point[i]->pbios->addr;
+-			lastpbaddr = change_point[i - 1]->pbios->addr;
+-
+-			/*
+-			 * swap entries, when:
+-			 *
+-			 * curaddr > lastaddr or
+-			 * curaddr == lastaddr and curaddr == curpbaddr and
+-			 * lastaddr != lastpbaddr
+-			 */
+-			if (curaddr < lastaddr ||
+-			    (curaddr == lastaddr && curaddr == curpbaddr &&
+-			     lastaddr != lastpbaddr)) {
+-				change_tmp = change_point[i];
+-				change_point[i] = change_point[i-1];
+-				change_point[i-1] = change_tmp;
+-				still_changing = 1;
+-			}
+-		}
+-	}
+-
+-	/* create a new bios memory map, removing overlaps */
+-	overlap_entries = 0;	 /* number of entries in the overlap table */
+-	new_bios_entry = 0;	 /* index for creating new bios map entries */
+-	last_type = 0;		 /* start with undefined memory type */
+-	last_addr = 0;		 /* start with 0 as last starting address */
+-
+-	/* loop through change-points, determining affect on the new bios map */
+-	for (chgidx = 0; chgidx < chg_nr; chgidx++) {
+-		/* keep track of all overlapping bios entries */
+-		if (change_point[chgidx]->addr ==
+-		    change_point[chgidx]->pbios->addr) {
+-			/*
+-			 * add map entry to overlap list (> 1 entry
+-			 * implies an overlap)
+-			 */
+-			overlap_list[overlap_entries++] =
+-				change_point[chgidx]->pbios;
+-		} else {
+-			/*
+-			 * remove entry from list (order independent,
+-			 * so swap with last)
+-			 */
+-			for (i = 0; i < overlap_entries; i++) {
+-				if (overlap_list[i] ==
+-				    change_point[chgidx]->pbios)
+-					overlap_list[i] =
+-						overlap_list[overlap_entries-1];
+-			}
+-			overlap_entries--;
+-		}
+-		/*
+-		 * if there are overlapping entries, decide which
+-		 * "type" to use (larger value takes precedence --
+-		 * 1=usable, 2,3,4,4+=unusable)
+-		 */
+-		current_type = 0;
+-		for (i = 0; i < overlap_entries; i++)
+-			if (overlap_list[i]->type > current_type)
+-				current_type = overlap_list[i]->type;
+-		/*
+-		 * continue building up new bios map based on this
+-		 * information
+-		 */
+-		if (current_type != last_type)	{
+-			if (last_type != 0)	 {
+-				new_bios[new_bios_entry].size =
+-					change_point[chgidx]->addr - last_addr;
+-				/*
+-				 * move forward only if the new size
+-				 * was non-zero
+-				 */
+-				if (new_bios[new_bios_entry].size != 0)
+-					/*
+-					 * no more space left for new
+-					 * bios entries ?
+-					 */
+-					if (++new_bios_entry >= E820MAX)
+-						break;
+-			}
+-			if (current_type != 0)	{
+-				new_bios[new_bios_entry].addr =
+-					change_point[chgidx]->addr;
+-				new_bios[new_bios_entry].type = current_type;
+-				last_addr = change_point[chgidx]->addr;
+-			}
+-			last_type = current_type;
+-		}
+-	}
+-	/* retain count for new bios entries */
+-	new_nr = new_bios_entry;
+-
+-	/* copy new bios mapping into original location */
+-	memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry));
+-	*pnr_map = new_nr;
+-
+-	return 0;
+-}
+-
+-/*
+- * Copy the BIOS e820 map into a safe place.
+- *
+- * Sanity-check it while we're at it..
+- *
+- * If we're lucky and live on a modern system, the setup code
+- * will have given us a memory map that we can use to properly
+- * set up memory.  If we aren't, we'll fake a memory map.
+- */
+-static int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+-{
+-#ifndef CONFIG_XEN
+-	/* Only one memory region (or negative)? Ignore it */
+-	if (nr_map < 2)
+-		return -1;
+-#else
+-	BUG_ON(nr_map < 1);
+-#endif
+-
+-	do {
+-		u64 start = biosmap->addr;
+-		u64 size = biosmap->size;
+-		u64 end = start + size;
+-		u32 type = biosmap->type;
+-
+-		/* Overflow in 64 bits? Ignore the memory map. */
+-		if (start > end)
+-			return -1;
+-
+-		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;
+-}
+-
+-static void early_panic(char *msg)
+-{
+-	early_printk(msg);
+-	panic(msg);
+-}
+-
+-/* We're not void only for x86 32-bit compat */
+-char * __init machine_specific_memory_setup(void)
+-{
+-#ifndef CONFIG_XEN
+-	char *who = "BIOS-e820";
+-	/*
+-	 * Try to copy the BIOS-supplied E820-map.
+-	 *
+-	 * Otherwise fake a memory map; one section from 0k->640k,
+-	 * the next section from 1mb->appropriate_mem_k
+-	 */
+-	sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
+-	if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0)
+-		early_panic("Cannot find a valid memory map");
+-#else  /* CONFIG_XEN */
+-	char *who = "Xen";
+-	int rc;
+-	struct xen_memory_map memmap;
+-	static struct e820entry __initdata map[E820MAX];
+-
+-	memmap.nr_entries = E820MAX;
+-	set_xen_guest_handle(memmap.buffer, map);
+-
+-	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+-	if ( rc == -ENOSYS ) {
+-		memmap.nr_entries = 1;
+-		map[0].addr = 0ULL;
+-		map[0].size = xen_start_info->nr_pages << PAGE_SHIFT;
+-		/* 8MB slack (to balance backend allocations). */
+-		map[0].size += 8 << 20;
+-		map[0].type = E820_RAM;
+-		rc = 0;
+-	}
+-	BUG_ON(rc);
+-
+-	sanitize_e820_map(map, (char *)&memmap.nr_entries);
+-
+-	if (copy_e820_map(map, (char)memmap.nr_entries) < 0)
+-		early_panic("Cannot find a valid memory map");
+-#endif
+-	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-	e820_print_map(who);
+-
+-	/* In case someone cares... */
+-	return who;
+-}
+-
+-static int __init parse_memopt(char *p)
+-{
+-	int i;
+-	unsigned long current_end;
+-	unsigned long end;
+-
+-	if (!p)
+-		return -EINVAL;
+-	end_user_pfn = memparse(p, &p);
+-	end_user_pfn >>= PAGE_SHIFT;
+-
+-	end = end_user_pfn<<PAGE_SHIFT;
+-	i = e820.nr_map-1;
+-	current_end = e820.map[i].addr + e820.map[i].size;
+-
+-	if (current_end < end) {
+-		/*
+-                 * The e820 map ends before our requested size so
+-                 * extend the final entry to the requested address.
+-                 */
+-		if (e820.map[i].type == E820_RAM)
+-			e820.map[i].size = end - e820.map[i].addr;
+-		else
+-			add_memory_region(current_end, end - current_end, E820_RAM);
+-	}
+-
+-	return 0;
+-}
+-early_param("mem", parse_memopt);
+-
+-static int userdef __initdata;
+-
+-static int __init parse_memmap_opt(char *p)
+-{
+-	char *oldp;
+-	unsigned long long start_at, mem_size;
+-
+-	if (!strcmp(p, "exactmap")) {
+-#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.
+-		 */
+-		e820_register_active_regions(0, 0, -1UL);
+-		saved_max_pfn = e820_end_of_ram();
+-		remove_all_active_ranges();
+-#endif
+-		max_pfn_mapped = 0;
+-		e820.nr_map = 0;
+-		userdef = 1;
+-		return 0;
+-	}
+-
+-	oldp = p;
+-	mem_size = memparse(p, &p);
+-	if (p == oldp)
+-		return -EINVAL;
+-
+-	userdef = 1;
+-	if (*p == '@') {
+-		start_at = memparse(p+1, &p);
+-		add_memory_region(start_at, mem_size, E820_RAM);
+-	} else if (*p == '#') {
+-		start_at = memparse(p+1, &p);
+-		add_memory_region(start_at, mem_size, E820_ACPI);
+-	} else if (*p == '$') {
+-		start_at = memparse(p+1, &p);
+-		add_memory_region(start_at, mem_size, E820_RESERVED);
+-	} else {
+-		end_user_pfn = (mem_size >> PAGE_SHIFT);
+-	}
+-	return *p == '\0' ? 0 : -EINVAL;
+-}
+-early_param("memmap", parse_memmap_opt);
+-
+-void __init finish_e820_parsing(void)
+-{
+-	if (userdef) {
+-		char nr = e820.nr_map;
+-
+-		if (sanitize_e820_map(e820.map, &nr) < 0)
+-			early_panic("Invalid user supplied memory map");
+-		e820.nr_map = nr;
+-
+-		printk(KERN_INFO "user-defined physical RAM map:\n");
+-		e820_print_map("user");
+-	}
+-}
+-
+-#ifndef CONFIG_XEN
+-void __init update_memory_range(u64 start, u64 size, unsigned old_type,
+-				unsigned new_type)
+-{
+-	int i;
+-
+-	BUG_ON(old_type == new_type);
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		u64 final_start, final_end;
+-		if (ei->type != old_type)
+-			continue;
+-		/* totally covered? */
+-		if (ei->addr >= start && ei->size <= size) {
+-			ei->type = new_type;
+-			continue;
+-		}
+-		/* partially covered */
+-		final_start = max(start, ei->addr);
+-		final_end = min(start + size, ei->addr + ei->size);
+-		if (final_start >= final_end)
+-			continue;
+-		add_memory_region(final_start, final_end - final_start,
+-					 new_type);
+-	}
+-}
+-
+-void __init update_e820(void)
+-{
+-	u8 nr_map;
+-
+-	nr_map = e820.nr_map;
+-	if (sanitize_e820_map(e820.map, &nr_map))
+-		return;
+-	e820.nr_map = nr_map;
+-	printk(KERN_INFO "modified physical RAM map:\n");
+-	e820_print_map("modified");
+-}
+-#endif
+-
+-unsigned long pci_mem_start = 0xaeedbabe;
+-EXPORT_SYMBOL(pci_mem_start);
+-
+-/*
+- * Search for the biggest gap in the low 32 bits of the e820
+- * memory space.  We pass this space to PCI to assign MMIO resources
+- * for hotplug or unconfigured devices in.
+- * Hopefully the BIOS let enough space left.
+- */
+-__init void e820_setup_gap(struct e820entry *e820, int nr_map)
+-{
+-	unsigned long gapstart, gapsize, round;
+-	unsigned long last;
+-	int i;
+-	int found = 0;
+-
+-	last = 0x100000000ull;
+-	gapstart = 0x10000000;
+-	gapsize = 0x400000;
+-	i = nr_map;
+-	while (--i >= 0) {
+-		unsigned long long start = e820[i].addr;
+-		unsigned long long end = start + e820[i].size;
+-
+-		/*
+-		 * Since "last" is at most 4GB, we know we'll
+-		 * fit in 32 bits if this condition is true
+-		 */
+-		if (last > end) {
+-			unsigned long gap = last - end;
+-
+-			if (gap > gapsize) {
+-				gapsize = gap;
+-				gapstart = end;
+-				found = 1;
+-			}
+-		}
+-		if (start < last)
+-			last = start;
+-	}
+-
+-	if (!found) {
+-		gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+-		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
+-		       "address range\n"
+-		       KERN_ERR "PCI: Unassigned devices with 32bit resource "
+-		       "registers may break!\n");
+-	}
+-
+-	/*
+-	 * See how much we want to round up: start off with
+-	 * rounding to the next 1MB area.
+-	 */
+-	round = 0x100000;
+-	while ((gapsize >> 4) > round)
+-		round += round;
+-	/* Fun with two's complement */
+-	pci_mem_start = (gapstart + round) & -round;
+-
+-	printk(KERN_INFO
+-	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+-	       pci_mem_start, gapstart, gapsize);
+-}
+-
+-int __init arch_get_ram_range(int slot, u64 *addr, u64 *size)
+-{
+-	int i;
+-
+-	if (slot < 0 || slot >= e820.nr_map)
+-		return -1;
+-	for (i = slot; i < e820.nr_map; i++) {
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-		break;
+-	}
+-	if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT))
+-		return -1;
+-	*addr = e820.map[i].addr;
+-	*size = min_t(u64, e820.map[i].size + e820.map[i].addr,
+-		max_pfn << PAGE_SHIFT) - *addr;
+-	return i + 1;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -225,7 +225,7 @@ static struct console simnow_console = {
+ static struct console *early_console = &early_vga_console;
+ static int early_console_initialized;
+ 
+-void early_printk(const char *fmt, ...)
++asmlinkage void early_printk(const char *fmt, ...)
+ {
+ 	char buf[512];
+ 	int n;
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:42.000000000 +0100
+@@ -51,15 +51,26 @@
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
+ #include <asm/processor-flags.h>
+-#include "irq_vectors.h"
++#include <asm/ftrace.h>
++#include <asm/irq_vectors.h>
+ #include <xen/interface/xen.h>
+ 
++/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
++#include <linux/elf-em.h>
++#define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
++#define __AUDIT_ARCH_LE	   0x40000000
++
++#ifndef CONFIG_AUDITSYSCALL
++#define sysenter_audit	syscall_trace_entry
++#define sysexit_audit	syscall_exit_work
++#endif
++
+ /*
+  * We use macros for low-level operations which need to be overridden
+  * for paravirtualization.  The following will never clobber any registers:
+  *   INTERRUPT_RETURN (aka. "iret")
+  *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
+- *   ENABLE_INTERRUPTS_SYSCALL_RET (aka "sti; sysexit").
++ *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
+  *
+  * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
+  * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
+@@ -277,11 +288,6 @@ END(resume_kernel)
+ #endif
+ 	CFI_ENDPROC
+ 
+-	.macro test_tif ti_reg		# system call tracing in operation / emulation
+-	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+-	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(\ti_reg)
+-	.endm
+-
+ /* SYSENTER_RETURN points to after the "sysenter" instruction in
+    the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
+ 
+@@ -338,8 +344,9 @@ sysenter_past_esp:
+ .previous
+ 
+ 	GET_THREAD_INFO(%ebp)
+-	test_tif %ebp
+-	jnz syscall_trace_entry
++	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
++	jnz sysenter_audit
++sysenter_do_call:
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+ 	call *sys_call_table(,%eax,4)
+@@ -349,14 +356,54 @@ sysenter_past_esp:
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+ 	testw $_TIF_ALLWORK_MASK, %cx
+-	jne syscall_exit_work
++	jne sysexit_audit
++sysenter_exit:
+ /* if something modifies registers it must also disable sysexit */
+ 	movl PT_EIP(%esp), %edx
+ 	movl PT_OLDESP(%esp), %ecx
+ 	xorl %ebp,%ebp
+ 	TRACE_IRQS_ON
+ 1:	mov  PT_FS(%esp), %fs
+-	ENABLE_INTERRUPTS_SYSCALL_RET
++	ENABLE_INTERRUPTS_SYSEXIT
++
++#ifdef CONFIG_AUDITSYSCALL
++sysenter_audit:
++	testw $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	jnz syscall_trace_entry
++	addl $4,%esp
++	CFI_ADJUST_CFA_OFFSET -4
++	/* %esi already in 8(%esp)	   6th arg: 4th syscall arg */
++	/* %edx already in 4(%esp)	   5th arg: 3rd syscall arg */
++	/* %ecx already in 0(%esp)	   4th arg: 2nd syscall arg */
++	movl %ebx,%ecx			/* 3rd arg: 1st syscall arg */
++	movl %eax,%edx			/* 2nd arg: syscall number */
++	movl $AUDIT_ARCH_I386,%eax	/* 1st arg: audit arch */
++	call audit_syscall_entry
++	pushl %ebx
++	CFI_ADJUST_CFA_OFFSET 4
++	movl PT_EAX(%esp),%eax		/* reload syscall number */
++	jmp sysenter_do_call
++
++sysexit_audit:
++	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
++	jne syscall_exit_work
++	TRACE_IRQS_ON
++	ENABLE_INTERRUPTS(CLBR_ANY)
++	movl %eax,%edx		/* second arg, syscall return value */
++	cmpl $0,%eax		/* is it < 0? */
++	setl %al		/* 1 if so, 0 if not */
++	movzbl %al,%eax		/* zero-extend that */
++	inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
++	call audit_syscall_exit
++	DISABLE_INTERRUPTS(CLBR_ANY)
++	TRACE_IRQS_OFF
++	movl TI_flags(%ebp), %ecx
++	testw $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %cx
++	jne syscall_exit_work
++	movl PT_EAX(%esp),%eax	/* reload syscall return value */
++	jmp sysenter_exit
++#endif
++
+ 	CFI_ENDPROC
+ .pushsection .fixup,"ax"
+ 2:	movl $0,PT_FS(%esp)
+@@ -400,7 +447,7 @@ ENTRY(system_call)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	test_tif %ebp
++	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ 	jnz syscall_trace_entry
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+@@ -413,10 +460,6 @@ syscall_exit:
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+-	testl $X86_EFLAGS_TF,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
+-	jz no_singlestep
+-	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+-no_singlestep:
+ 	movl TI_flags(%ebp), %ecx
+ 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
+ 	jne syscall_exit_work
+@@ -588,12 +631,8 @@ END(work_pending)
+ syscall_trace_entry:
+ 	movl $-ENOSYS,PT_EAX(%esp)
+ 	movl %esp, %eax
+-	xorl %edx,%edx
+-	call do_syscall_trace
+-	cmpl $0, %eax
+-	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
+-					# so must skip actual syscall
+-	movl PT_ORIG_EAX(%esp), %eax
++	call syscall_trace_enter
++	/* What it returned is what we'll actually use.  */
+ 	cmpl $(nr_syscalls), %eax
+ 	jnae syscall_call
+ 	jmp syscall_exit
+@@ -602,14 +641,13 @@ END(syscall_trace_entry)
+ 	# perform syscall exit tracing
+ 	ALIGN
+ syscall_exit_work:
+-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
++	testb $_TIF_WORK_SYSCALL_EXIT, %cl
+ 	jz work_pending
+ 	TRACE_IRQS_ON
+-	ENABLE_INTERRUPTS(CLBR_ANY)	# could let do_syscall_trace() call
++	ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
+ 					# schedule() instead
+ 	movl %esp, %eax
+-	movl $1, %edx
+-	call do_syscall_trace
++	call syscall_trace_leave
+ 	jmp resume_userspace
+ END(syscall_exit_work)
+ 	CFI_ENDPROC
+@@ -1113,10 +1151,10 @@ ENTRY(native_iret)
+ .previous
+ END(native_iret)
+ 
+-ENTRY(native_irq_enable_syscall_ret)
++ENTRY(native_irq_enable_sysexit)
+ 	sti
+ 	sysexit
+-END(native_irq_enable_syscall_ret)
++END(native_irq_enable_sysexit)
+ #endif
+ 
+ KPROBE_ENTRY(int3)
+@@ -1265,6 +1303,77 @@ ENTRY(kernel_thread_helper)
+ 	CFI_ENDPROC
+ ENDPROC(kernel_thread_helper)
+ 
++#ifdef CONFIG_FTRACE
++#ifdef CONFIG_DYNAMIC_FTRACE
++
++ENTRY(mcount)
++	pushl %eax
++	pushl %ecx
++	pushl %edx
++	movl 0xc(%esp), %eax
++	subl $MCOUNT_INSN_SIZE, %eax
++
++.globl mcount_call
++mcount_call:
++	call ftrace_stub
++
++	popl %edx
++	popl %ecx
++	popl %eax
++
++	ret
++END(mcount)
++
++ENTRY(ftrace_caller)
++	pushl %eax
++	pushl %ecx
++	pushl %edx
++	movl 0xc(%esp), %eax
++	movl 0x4(%ebp), %edx
++	subl $MCOUNT_INSN_SIZE, %eax
++
++.globl ftrace_call
++ftrace_call:
++	call ftrace_stub
++
++	popl %edx
++	popl %ecx
++	popl %eax
++
++.globl ftrace_stub
++ftrace_stub:
++	ret
++END(ftrace_caller)
++
++#else /* ! CONFIG_DYNAMIC_FTRACE */
++
++ENTRY(mcount)
++	cmpl $ftrace_stub, ftrace_trace_function
++	jnz trace
++.globl ftrace_stub
++ftrace_stub:
++	ret
++
++	/* taken from glibc */
++trace:
++	pushl %eax
++	pushl %ecx
++	pushl %edx
++	movl 0xc(%esp), %eax
++	movl 0x4(%ebp), %edx
++	subl $MCOUNT_INSN_SIZE, %eax
++
++	call *ftrace_trace_function
++
++	popl %edx
++	popl %ecx
++	popl %eax
++
++	jmp ftrace_stub
++END(mcount)
++#endif /* CONFIG_DYNAMIC_FTRACE */
++#endif /* CONFIG_FTRACE */
++
+ #include <asm/alternative-asm.h>
+ 
+ 	# pv syscall call handler stub
+@@ -1290,7 +1399,7 @@ ENTRY(ia32pv_cstar_target)
+ .previous
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	test_tif %ebp
++	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+ 	jnz cstar_trace_entry
+ 	cmpl $nr_syscalls,%eax
+ 	jae cstar_badsys
+@@ -1324,29 +1433,21 @@ cstar_trace_entry:
+ 	btl %eax,cstar_special
+ 	jc .Lcstar_trace_special
+ 1:	movl %esp,%eax
+-	xorl %edx,%edx
+ 	LOCK_PREFIX
+ 	orl $_TIF_CSTAR,TI_flags(%ebp)
+-	call do_syscall_trace
++	call syscall_trace_enter
+ 	LOCK_PREFIX
+ 	andl $~_TIF_CSTAR,TI_flags(%ebp)
+-	testl %eax,%eax
+-	jne .Lcstar_resume		# ret != 0 -> running under PTRACE_SYSEMU,
+-					# so must skip actual syscall
+-	movl PT_ORIG_EAX(%esp),%eax
++	/* What it returned is what we'll actually use.  */
+ 	cmpl $nr_syscalls,%eax
+ 	jb .Lcstar_call
+ 	jmp .Lcstar_exit
+ .Lcstar_trace_special:
+ 	movl PT_ECX(%esp),%ecx
+ 	movl %esp,%eax
+-	xorl %edx,%edx
+ 	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+-	call do_syscall_trace
+-	testl %eax,%eax
+-	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
+-					# so must skip actual syscall
+-	movl PT_ORIG_EAX(%esp),%eax
++	call syscall_trace_enter
++	/* What it returned is what we'll actually use.  */
+ 	cmpl $nr_syscalls,%eax
+ 	jb syscall_call
+ 	jmp syscall_exit
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64.S	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64.S	2009-11-06 10:51:42.000000000 +0100
+@@ -1312,7 +1312,7 @@ ENTRY(arch_unwind_init_running)
+ END(arch_unwind_init_running)
+ #endif
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
+ 
+ /*
+@@ -1409,7 +1409,7 @@ ENTRY(xen_failsafe_callback)
+ 	CFI_ENDPROC
+ END(xen_failsafe_callback)
+ 
+-#endif /* CONFIG_XEN */
++#endif /* CONFIG_PARAVIRT_XEN */
+ 
+ #ifdef	CONFIG_KDB
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:42.000000000 +0100
+@@ -53,19 +53,130 @@
+ #include <asm/hw_irq.h>
+ #include <asm/page.h>
+ #include <asm/irqflags.h>
++#include <asm/ftrace.h>
+ #include <asm/errno.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/features.h>
+ 
++/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
++#include <linux/elf-em.h>
++#define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
++#define __AUDIT_ARCH_64BIT 0x80000000
++#define __AUDIT_ARCH_LE	   0x40000000
++
+ 	.code64
+ 
++#ifdef CONFIG_FTRACE
++#ifdef CONFIG_DYNAMIC_FTRACE
++ENTRY(mcount)
++
++	subq $0x38, %rsp
++	movq %rax, (%rsp)
++	movq %rcx, 8(%rsp)
++	movq %rdx, 16(%rsp)
++	movq %rsi, 24(%rsp)
++	movq %rdi, 32(%rsp)
++	movq %r8, 40(%rsp)
++	movq %r9, 48(%rsp)
++
++	movq 0x38(%rsp), %rdi
++	subq $MCOUNT_INSN_SIZE, %rdi
++
++.globl mcount_call
++mcount_call:
++	call ftrace_stub
++
++	movq 48(%rsp), %r9
++	movq 40(%rsp), %r8
++	movq 32(%rsp), %rdi
++	movq 24(%rsp), %rsi
++	movq 16(%rsp), %rdx
++	movq 8(%rsp), %rcx
++	movq (%rsp), %rax
++	addq $0x38, %rsp
++
++	retq
++END(mcount)
++
++ENTRY(ftrace_caller)
++
++	/* taken from glibc */
++	subq $0x38, %rsp
++	movq %rax, (%rsp)
++	movq %rcx, 8(%rsp)
++	movq %rdx, 16(%rsp)
++	movq %rsi, 24(%rsp)
++	movq %rdi, 32(%rsp)
++	movq %r8, 40(%rsp)
++	movq %r9, 48(%rsp)
++
++	movq 0x38(%rsp), %rdi
++	movq 8(%rbp), %rsi
++	subq $MCOUNT_INSN_SIZE, %rdi
++
++.globl ftrace_call
++ftrace_call:
++	call ftrace_stub
++
++	movq 48(%rsp), %r9
++	movq 40(%rsp), %r8
++	movq 32(%rsp), %rdi
++	movq 24(%rsp), %rsi
++	movq 16(%rsp), %rdx
++	movq 8(%rsp), %rcx
++	movq (%rsp), %rax
++	addq $0x38, %rsp
++
++.globl ftrace_stub
++ftrace_stub:
++	retq
++END(ftrace_caller)
++
++#else /* ! CONFIG_DYNAMIC_FTRACE */
++ENTRY(mcount)
++	cmpq $ftrace_stub, ftrace_trace_function
++	jnz trace
++.globl ftrace_stub
++ftrace_stub:
++	retq
++
++trace:
++	/* taken from glibc */
++	subq $0x38, %rsp
++	movq %rax, (%rsp)
++	movq %rcx, 8(%rsp)
++	movq %rdx, 16(%rsp)
++	movq %rsi, 24(%rsp)
++	movq %rdi, 32(%rsp)
++	movq %r8, 40(%rsp)
++	movq %r9, 48(%rsp)
++
++	movq 0x38(%rsp), %rdi
++	movq 8(%rbp), %rsi
++	subq $MCOUNT_INSN_SIZE, %rdi
++
++	call   *ftrace_trace_function
++
++	movq 48(%rsp), %r9
++	movq 40(%rsp), %r8
++	movq 32(%rsp), %rdi
++	movq 24(%rsp), %rsi
++	movq 16(%rsp), %rdx
++	movq 8(%rsp), %rcx
++	movq (%rsp), %rax
++	addq $0x38, %rsp
++
++	jmp ftrace_stub
++END(mcount)
++#endif /* CONFIG_DYNAMIC_FTRACE */
++#endif /* CONFIG_FTRACE */
++
+ #ifndef CONFIG_PREEMPT
+ #define retint_kernel retint_restore_args
+ #endif	
+ 
+ #ifdef CONFIG_PARAVIRT
+-ENTRY(native_irq_enable_syscall_ret)
+-	movq	%gs:pda_oldrsp,%rsp
++ENTRY(native_usergs_sysret64)
+ 	swapgs
+ 	sysretq
+ #endif /* CONFIG_PARAVIRT */
+@@ -102,7 +213,7 @@ NMI_MASK = 0x80000000
+ 	.macro FAKE_STACK_FRAME child_rip
+ 	/* push in order ss, rsp, eflags, cs, rip */
+ 	xorl %eax, %eax
+-	pushq %rax /* ss */
++	pushq $__KERNEL_DS /* ss */
+ 	CFI_ADJUST_CFA_OFFSET	8
+ 	/*CFI_REL_OFFSET	ss,0*/
+ 	pushq %rax /* rsp */
+@@ -197,13 +308,13 @@ ENTRY(ret_from_fork)
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	call schedule_tail
+ 	GET_THREAD_INFO(%rcx)
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+ 	jnz rff_trace
+ rff_action:	
+ 	RESTORE_REST
+ 	testl $3,CS-ARGOFFSET(%rsp)	# from kernel_thread?
+ 	je   int_ret_from_sys_call
+-	testl $_TIF_IA32,threadinfo_flags(%rcx)
++	testl $_TIF_IA32,TI_flags(%rcx)
+ 	jnz  int_ret_from_sys_call
+ 	RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
+ 	jmp ret_from_sys_call
+@@ -265,8 +376,9 @@ ENTRY(system_call)
+ 	SAVE_ARGS -8,0
+ 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
+ 	GET_THREAD_INFO(%rcx)
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
++	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+ 	jnz tracesys
++system_call_fastpath:
+ 	cmpq $__NR_syscall_max,%rax
+ 	ja badsys
+ 	movq %r10,%rcx
+@@ -284,7 +396,7 @@ sysret_check:		
+ 	GET_THREAD_INFO(%rcx)
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+-	movl threadinfo_flags(%rcx),%edx
++	movl TI_flags(%rcx),%edx
+ 	andl %edi,%edx
+ 	jnz  sysret_careful 
+ 	CFI_REMEMBER_STATE
+@@ -315,16 +427,16 @@ sysret_careful:
+ sysret_signal:
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
+-	testl $_TIF_DO_NOTIFY_MASK,%edx
+-	jz    1f
+-
+-	/* Really a signal */
++#ifdef CONFIG_AUDITSYSCALL
++	bt $TIF_SYSCALL_AUDIT,%edx
++	jc sysret_audit
++#endif
+ 	/* edx:	work flags (arg3) */
+ 	leaq do_notify_resume(%rip),%rax
+ 	leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
+ 	xorl %esi,%esi # oldset -> arg2
+ 	call ptregscall_common
+-1:	movl $_TIF_NEED_RESCHED,%edi
++	movl $_TIF_WORK_MASK,%edi
+ 	/* Use IRET because user could have changed frame. This
+ 	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+@@ -335,14 +447,56 @@ badsys:
+ 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+ 	jmp ret_from_sys_call
+ 
++#ifdef CONFIG_AUDITSYSCALL
++	/*
++	 * Fast path for syscall audit without full syscall trace.
++	 * We just call audit_syscall_entry() directly, and then
++	 * jump back to the normal fast path.
++	 */
++auditsys:
++	movq %r10,%r9			/* 6th arg: 4th syscall arg */
++	movq %rdx,%r8			/* 5th arg: 3rd syscall arg */
++	movq %rsi,%rcx			/* 4th arg: 2nd syscall arg */
++	movq %rdi,%rdx			/* 3rd arg: 1st syscall arg */
++	movq %rax,%rsi			/* 2nd arg: syscall number */
++	movl $AUDIT_ARCH_X86_64,%edi	/* 1st arg: audit arch */
++	call audit_syscall_entry
++	LOAD_ARGS 0		/* reload call-clobbered registers */
++	jmp system_call_fastpath
++
++	/*
++	 * Return fast path for syscall audit.  Call audit_syscall_exit()
++	 * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
++	 * masked off.
++	 */
++sysret_audit:
++	movq %rax,%rsi		/* second arg, syscall return value */
++	cmpq $0,%rax		/* is it < 0? */
++	setl %al		/* 1 if so, 0 if not */
++	movzbl %al,%edi		/* zero-extend that into %edi */
++	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
++	call audit_syscall_exit
++	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
++	jmp sysret_check
++#endif	/* CONFIG_AUDITSYSCALL */
++
+ 	/* Do syscall tracing */
+ tracesys:			 
++#ifdef CONFIG_AUDITSYSCALL
++	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
++	jz auditsys
++#endif
+ 	SAVE_REST
+ 	movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+ 	FIXUP_TOP_OF_STACK %rdi
+ 	movq %rsp,%rdi
+ 	call syscall_trace_enter
+-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	/*
++	 * Reload arg registers from stack in case ptrace changed them.
++	 * We don't reload %rax because syscall_trace_enter() returned
++	 * the value it wants us to use in the table lookup.
++	 */
++	LOAD_ARGS ARGOFFSET, 1
+ 	RESTORE_REST
+ 	cmpq $__NR_syscall_max,%rax
+ 	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
+@@ -356,6 +510,7 @@ tracesys:			 
+  * Has correct top of stack, but partial stack frame.
+  */
+ 	.globl int_ret_from_sys_call
++	.globl int_with_check
+ int_ret_from_sys_call:
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+@@ -370,10 +525,10 @@ int_ret_from_sys_call:
+ int_with_check:
+ 	LOCKDEP_SYS_EXIT_IRQ
+ 	GET_THREAD_INFO(%rcx)
+-	movl threadinfo_flags(%rcx),%edx
++	movl TI_flags(%rcx),%edx
+ 	andl %edi,%edx
+ 	jnz   int_careful
+-	andl    $~TS_COMPAT,threadinfo_status(%rcx)
++	andl    $~TS_COMPAT,TI_status(%rcx)
+ 	jmp   retint_restore_args
+ 
+ 	/* Either reschedule or signal or syscall exit tracking needed. */
+@@ -399,7 +554,7 @@ int_very_careful:
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	SAVE_REST
+ 	/* Check for syscall exit trace */	
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
++	testl $_TIF_WORK_SYSCALL_EXIT,%edx
+ 	jz int_signal
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET 8
+@@ -407,7 +562,7 @@ int_very_careful:
+ 	call syscall_trace_leave
+ 	popq %rdi
+ 	CFI_ADJUST_CFA_OFFSET -8
+-	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
++	andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
+ 	jmp int_restore_rest
+ 	
+ int_signal:
+@@ -416,7 +571,7 @@ int_signal:
+ 	movq %rsp,%rdi		# &ptregs -> arg1
+ 	xorl %esi,%esi		# oldset -> arg2
+ 	call do_notify_resume
+-1:	movl $_TIF_NEED_RESCHED,%edi	
++1:	movl $_TIF_WORK_MASK,%edi
+ int_restore_rest:
+ 	RESTORE_REST
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+@@ -443,7 +598,6 @@ END(\label)
+ 	PTREGSCALL stub_clone, sys_clone, %r8
+ 	PTREGSCALL stub_fork, sys_fork, %rdi
+ 	PTREGSCALL stub_vfork, sys_vfork, %rdi
+-	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
+ 	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
+ 	PTREGSCALL stub_iopl, sys_iopl, %rsi
+ 
+@@ -517,10 +671,12 @@ END(stub_rt_sigreturn)
+  *
+  */ 
+ 
+-retint_check:
++retint_with_reschedule:
+ 	CFI_DEFAULT_STACK adj=1
++	movl $_TIF_WORK_MASK,%edi
++retint_check:
+ 	LOCKDEP_SYS_EXIT_IRQ
+-	movl threadinfo_flags(%rcx),%edx
++	movl TI_flags(%rcx),%edx
+ 	andl %edi,%edx
+ 	CFI_REMEMBER_STATE
+ 	jnz  retint_careful
+@@ -565,17 +721,16 @@ retint_signal:
+ 	RESTORE_REST
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+-	movl $_TIF_NEED_RESCHED,%edi
+ 	GET_THREAD_INFO(%rcx)
+-	jmp retint_check
++	jmp retint_with_reschedule
+ 
+ #ifdef CONFIG_PREEMPT
+ 	/* Returning to kernel space. Check if we need preemption */
+ 	/* rcx:	 threadinfo. interrupts off. */
+ ENTRY(retint_kernel)
+-	cmpl $0,threadinfo_preempt_count(%rcx)
++	cmpl $0,TI_preempt_count(%rcx)
+ 	jnz  retint_restore_args
+-	bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
++	bt  $TIF_NEED_RESCHED,TI_flags(%rcx)
+ 	jnc  retint_restore_args
+ 	bt   $9,EFLAGS-ARGOFFSET(%rsp)	/* interrupts off? */
+ 	jnc  retint_restore_args
+@@ -630,6 +785,9 @@ END(invalidate_interrupt\num)
+ ENTRY(call_function_interrupt)
+ 	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
+ END(call_function_interrupt)
++ENTRY(call_function_single_interrupt)
++	apicinterrupt CALL_FUNCTION_SINGLE_VECTOR,smp_call_function_single_interrupt
++END(call_function_single_interrupt)
+ ENTRY(irq_move_cleanup_interrupt)
+ 	apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
+ END(irq_move_cleanup_interrupt)
+@@ -639,6 +797,10 @@ ENTRY(apic_timer_interrupt)
+ 	apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
+ END(apic_timer_interrupt)
+ 
++ENTRY(uv_bau_message_intr1)
++	apicinterrupt 220,uv_bau_message_interrupt
++END(uv_bau_message_intr1)
++
+ ENTRY(error_interrupt)
+ 	apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
+ END(error_interrupt)
+@@ -752,7 +914,7 @@ paranoid_restore\trace:
+ 	jmp irq_return
+ paranoid_userspace\trace:
+ 	GET_THREAD_INFO(%rcx)
+-	movl threadinfo_flags(%rcx),%ebx
++	movl TI_flags(%rcx),%ebx
+ 	andl $_TIF_WORK_MASK,%ebx
+ 	jz paranoid_swapgs\trace
+ 	movq %rsp,%rdi			/* &pt_regs */
+@@ -849,7 +1011,7 @@ error_exit:
+ 	testb $3,CS-ARGOFFSET(%rsp)
+ 	jz retint_kernel
+ 	LOCKDEP_SYS_EXIT_IRQ
+-	movl  threadinfo_flags(%rcx),%edx
++	movl  TI_flags(%rcx),%edx
+ 	movl  $_TIF_WORK_MASK,%edi	
+ 	andl  %edi,%edx
+ 	jnz   retint_careful
+@@ -871,11 +1033,11 @@ error_kernelspace:
+ 	   iret run with kernel gs again, so don't set the user space flag.
+ 	   B stepping K8s sometimes report an truncated RIP for IRET 
+ 	   exceptions returning to compat mode. Check for these here too. */
+-	leaq irq_return(%rip),%rbp
+-	cmpq %rbp,RIP(%rsp) 
++	leaq irq_return(%rip),%rcx
++	cmpq %rcx,RIP(%rsp)
+ 	je   error_swapgs
+-	movl %ebp,%ebp	/* zero extend */
+-	cmpq %rbp,RIP(%rsp) 
++	movl %ecx,%ecx	/* zero extend */
++	cmpq %rcx,RIP(%rsp)
+ 	je   error_swapgs
+ 	cmpq $gs_change,RIP(%rsp)
+         je   error_swapgs
+@@ -1121,6 +1283,7 @@ END(device_not_available)
+ 	/* runs on exception stack */
+ KPROBE_ENTRY(debug)
+ /* 	INTR_FRAME
++	PARAVIRT_ADJUST_EXCEPTION_FRAME
+ 	pushq $0
+ 	CFI_ADJUST_CFA_OFFSET 8	*/
+ 	zeroentry do_debug
+@@ -1148,6 +1311,7 @@ END(do_nmi_callback)
+ 
+ KPROBE_ENTRY(int3)
+ /* 	INTR_FRAME
++	PARAVIRT_ADJUST_EXCEPTION_FRAME
+  	pushq $0
+  	CFI_ADJUST_CFA_OFFSET 8 */
+  	zeroentry do_int3
+@@ -1171,14 +1335,11 @@ ENTRY(coprocessor_segment_overrun)
+ 	zeroentry do_coprocessor_segment_overrun
+ END(coprocessor_segment_overrun)
+ 
+-ENTRY(reserved)
+-	zeroentry do_reserved
+-END(reserved)
+-
+ #if 0
+ 	/* runs on exception stack */
+ ENTRY(double_fault)
+ 	XCPT_FRAME
++	PARAVIRT_ADJUST_EXCEPTION_FRAME
+ 	paranoidentry do_double_fault
+ 	jmp paranoid_exit1
+ 	CFI_ENDPROC
+@@ -1196,6 +1357,7 @@ END(segment_not_present)
+ 	/* runs on exception stack */
+ ENTRY(stack_segment)
+ /*	XCPT_FRAME
++	PARAVIRT_ADJUST_EXCEPTION_FRAME
+ 	paranoidentry do_stack_segment */
+ 	errorentry do_stack_segment
+ /*	jmp paranoid_exit1
+--- head-2010-01-18.orig/arch/x86/kernel/fixup.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/fixup.c	2009-11-06 10:51:42.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+ #include <linux/version.h>
++#include <asm/traps.h>
+ 
+ #define DP(_f, _args...) printk(KERN_ALERT "  " _f "\n" , ## _args )
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/head-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -0,0 +1,57 @@
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/setup.h>
++#include <asm/bios_ebda.h>
++
++#define BIOS_LOWMEM_KILOBYTES 0x413
++
++/*
++ * The BIOS places the EBDA/XBDA at the top of conventional
++ * memory, and usually decreases the reported amount of
++ * conventional memory (int 0x12) too. This also contains a
++ * workaround for Dell systems that neglect to reserve EBDA.
++ * The same workaround also avoids a problem with the AMD768MPX
++ * chipset: reserve a page before VGA to prevent PCI prefetch
++ * into it (errata #56). Usually the page is reserved anyways,
++ * unless you have no PS/2 mouse plugged in.
++ */
++void __init reserve_ebda_region(void)
++{
++#ifndef CONFIG_XEN
++	unsigned int lowmem, ebda_addr;
++
++	/* To determine the position of the EBDA and the */
++	/* end of conventional memory, we need to look at */
++	/* the BIOS data area. In a paravirtual environment */
++	/* that area is absent. We'll just have to assume */
++	/* that the paravirt case can handle memory setup */
++	/* correctly, without our help. */
++	if (paravirt_enabled())
++		return;
++
++	/* end of low (conventional) memory */
++	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
++	lowmem <<= 10;
++
++	/* start of EBDA area */
++	ebda_addr = get_bios_ebda();
++
++	/* Fixup: bios puts an EBDA in the top 64K segment */
++	/* of conventional memory, but does not adjust lowmem. */
++	if ((lowmem - ebda_addr) <= 0x10000)
++		lowmem = ebda_addr;
++
++	/* Fixup: bios does not report an EBDA at all. */
++	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
++	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
++		lowmem = 0x9f000;
++
++	/* Paranoia: should never happen, but... */
++	if ((lowmem == 0) || (lowmem >= 0x100000))
++		lowmem = 0x9f000;
++
++	/* reserve all memory between lowmem and the 1MB mark */
++	reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
++#endif
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/head32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -0,0 +1,57 @@
++/*
++ *  linux/arch/i386/kernel/head32.c -- prepare to run common code
++ *
++ *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
++ *  Copyright (C) 2007 Eric Biederman <ebiederm@xmission.com>
++ */
++
++#include <linux/init.h>
++#include <linux/start_kernel.h>
++
++#include <asm/setup.h>
++#include <asm/sections.h>
++#include <asm/e820.h>
++#include <asm/bios_ebda.h>
++
++void __init i386_start_kernel(void)
++{
++	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
++
++#ifndef CONFIG_XEN
++#ifdef CONFIG_BLK_DEV_INITRD
++	/* Reserve INITRD */
++	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
++		u64 ramdisk_image = boot_params.hdr.ramdisk_image;
++		u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
++		u64 ramdisk_end   = ramdisk_image + ramdisk_size;
++		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
++	}
++#endif
++	reserve_early(init_pg_tables_start, init_pg_tables_end,
++			"INIT_PG_TABLE");
++#else
++	reserve_early(ALIGN(__pa_symbol(&_end), PAGE_SIZE),
++		      __pa(xen_start_info->pt_base)
++		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
++		      "Xen provided");
++
++	{
++		int max_cmdline;
++
++		if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
++			max_cmdline = COMMAND_LINE_SIZE;
++		memcpy(boot_command_line, xen_start_info->cmd_line, max_cmdline);
++		boot_command_line[max_cmdline-1] = '\0';
++	}
++#endif
++
++	reserve_ebda_region();
++
++	/*
++	 * At this point everything still needed from the boot loader
++	 * or BIOS or kernel text should be early reserved or marked not
++	 * RAM in e820. All other memory is free game.
++	 */
++
++	start_kernel();
++}
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -32,7 +32,26 @@
+ #include <asm/e820.h>
+ #include <asm/bios_ebda.h>
+ 
+-unsigned long start_pfn;
++/* boot cpu pda */
++static struct x8664_pda _boot_cpu_pda __read_mostly;
++
++#ifdef CONFIG_SMP
++/*
++ * We install an empty cpu_pda pointer table to indicate to early users
++ * (numa_set_node) that the cpu_pda pointer table for cpus other than
++ * the boot cpu is not yet setup.
++ */
++static struct x8664_pda *__cpu_pda[NR_CPUS] __initdata;
++#else
++static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
++#endif
++
++void __init x86_64_init_pda(void)
++{
++	_cpu_pda = __cpu_pda;
++	cpu_pda(0) = &_boot_cpu_pda;
++	pda_init(0);
++}
+ 
+ #ifndef CONFIG_XEN
+ static void __init zap_identity_mappings(void)
+@@ -77,83 +96,10 @@ EXPORT_SYMBOL(machine_to_phys_mapping);
+ unsigned int machine_to_phys_order;
+ EXPORT_SYMBOL(machine_to_phys_order);
+ 
+-#define BIOS_LOWMEM_KILOBYTES 0x413
+-
+-/*
+- * The BIOS places the EBDA/XBDA at the top of conventional
+- * memory, and usually decreases the reported amount of
+- * conventional memory (int 0x12) too. This also contains a
+- * workaround for Dell systems that neglect to reserve EBDA.
+- * The same workaround also avoids a problem with the AMD768MPX
+- * chipset: reserve a page before VGA to prevent PCI prefetch
+- * into it (errata #56). Usually the page is reserved anyways,
+- * unless you have no PS/2 mouse plugged in.
+- */
+-static void __init reserve_ebda_region(void)
+-{
+-#ifndef CONFIG_XEN
+-	unsigned int lowmem, ebda_addr;
+-
+-	/* To determine the position of the EBDA and the */
+-	/* end of conventional memory, we need to look at */
+-	/* the BIOS data area. In a paravirtual environment */
+-	/* that area is absent. We'll just have to assume */
+-	/* that the paravirt case can handle memory setup */
+-	/* correctly, without our help. */
+-	if (paravirt_enabled())
+-		return;
+-
+-	/* end of low (conventional) memory */
+-	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
+-	lowmem <<= 10;
+-
+-	/* start of EBDA area */
+-	ebda_addr = get_bios_ebda();
+-
+-	/* Fixup: bios puts an EBDA in the top 64K segment */
+-	/* of conventional memory, but does not adjust lowmem. */
+-	if ((lowmem - ebda_addr) <= 0x10000)
+-		lowmem = ebda_addr;
+-
+-	/* Fixup: bios does not report an EBDA at all. */
+-	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
+-	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
+-		lowmem = 0x9f000;
+-
+-	/* Paranoia: should never happen, but... */
+-	if ((lowmem == 0) || (lowmem >= 0x100000))
+-		lowmem = 0x9f000;
+-
+-	/* reserve all memory between lowmem and the 1MB mark */
+-	reserve_early(lowmem, 0x100000, "BIOS reserved");
+-#endif
+-}
+-
+-static void __init reserve_setup_data(void)
+-{
+-#ifndef CONFIG_XEN
+-	struct setup_data *data;
+-	unsigned long pa_data;
+-	char buf[32];
+-
+-	if (boot_params.hdr.version < 0x0209)
+-		return;
+-	pa_data = boot_params.hdr.setup_data;
+-	while (pa_data) {
+-		data = early_ioremap(pa_data, sizeof(*data));
+-		sprintf(buf, "setup data %x", data->type);
+-		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+-		pa_data = data->next;
+-		early_iounmap(data, sizeof(*data));
+-	}
+-#endif
+-}
+-
+ void __init x86_64_start_kernel(char * real_mode_data)
+ {
+ 	struct xen_machphys_mapping mapping;
+ 	unsigned long machine_to_phys_nr_ents;
+-	int i;
+ 
+ 	/*
+ 	 * Build-time sanity checks on the kernel image and module
+@@ -167,6 +113,7 @@ void __init x86_64_start_kernel(char * r
+ 	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+ 	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+ 				(__START_KERNEL & PGDIR_MASK)));
++	BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END);
+ 
+ 	xen_setup_features();
+ 
+@@ -174,8 +121,6 @@ void __init x86_64_start_kernel(char * r
+ 	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;
+@@ -208,19 +153,23 @@ void __init x86_64_start_kernel(char * r
+ 
+ 	early_printk("Kernel alive\n");
+ 
+- 	for (i = 0; i < NR_CPUS; i++)
+- 		cpu_pda(i) = &boot_cpu_pda[i];
++	x86_64_init_pda();
+ 
+-	pda_init(0);
++	early_printk("Kernel really alive\n");
++
++	x86_64_start_reservations(real_mode_data);
++}
++
++void __init x86_64_start_reservations(char *real_mode_data)
++{
+ 	copy_bootdata(__va(real_mode_data));
+ 
+ 	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+ 
+ 	reserve_early(round_up(__pa_symbol(&_end), PAGE_SIZE),
+-		      start_pfn << PAGE_SHIFT, "Xen provided");
+-
+-	reserve_ebda_region();
+-	reserve_setup_data();
++		      __pa(xen_start_info->pt_base)
++		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
++		      "Xen provided");
+ 
+ 	/*
+ 	 * At this point everything still needed from the boot loader
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:51:42.000000000 +0100
+@@ -92,53 +92,6 @@ NEXT_PAGE(hypercall_page)
+ 
+ #undef NEXT_PAGE
+ 
+-	.data
+-
+-	.align 16
+-	.globl cpu_gdt_descr
+-cpu_gdt_descr:
+-	.word	gdt_end-cpu_gdt_table-1
+-gdt:
+-	.quad	cpu_gdt_table
+-#ifdef CONFIG_SMP
+-	.rept	NR_CPUS-1
+-	.word	0
+-	.quad	0
+-	.endr
+-#endif
+-
+-/* We need valid kernel segments for data and code in long mode too
+- * IRET will check the segment types  kkeil 2000/10/28
+- * Also sysret mandates a special GDT layout 
+- */
+-		 		
+-	.section .data.page_aligned, "aw"
+-	.align PAGE_SIZE
+-
+-/* The TLS descriptors are currently at a different place compared to i386.
+-   Hopefully nobody expects them at a fixed place (Wine?) */
+-
+-ENTRY(cpu_gdt_table)
+-	.quad	0x0000000000000000	/* NULL descriptor */
+-	.quad	0x00cf9b000000ffff	/* __KERNEL32_CS */
+-	.quad	0x00af9b000000ffff	/* __KERNEL_CS */
+-	.quad	0x00cf93000000ffff	/* __KERNEL_DS */
+-	.quad	0x00cffb000000ffff	/* __USER32_CS */
+-	.quad	0x00cff3000000ffff	/* __USER_DS, __USER32_DS  */
+-	.quad	0x00affb000000ffff	/* __USER_CS */
+-	.quad	0x0			/* unused */
+-	.quad	0,0			/* TSS */
+-	.quad	0,0			/* LDT */
+-	.quad   0,0,0			/* three TLS descriptors */
+-	.quad	0x0000f40000000000	/* node/CPU stored in limit */
+-gdt_end:
+-	/* asm/segment.h:GDT_ENTRIES must match this */
+-	/* This should be a multiple of the cache line size */
+-	/* GDTs of other CPUs are now dynamically allocated */
+-
+-	/* zero the remaining page */
+-	.fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
+-
+ 	.section .bss.page_aligned, "aw", @nobits
+ 	.align PAGE_SIZE
+ ENTRY(empty_zero_page)
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/sched.h>
++#include <linux/bootmem.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/compiler.h>
+ #include <linux/acpi.h>
+@@ -75,7 +76,7 @@ static struct { int pin, apic; } ioapic_
+ static DEFINE_SPINLOCK(ioapic_lock);
+ static DEFINE_SPINLOCK(vector_lock);
+ 
+-int timer_over_8254 __initdata = 1;
++int timer_through_8259 __initdata;
+ 
+ /*
+  *	Is the SiS APIC rmw bug present ?
+@@ -89,15 +90,21 @@ int sis_apic_bug = -1;
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
+ /* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
+ int nr_ioapics;
+ 
+ /* MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ 
+ /* # of MP IRQ source entries */
+ int mp_irq_entries;
+ 
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++
+ static int disable_timer_pin_1 __initdata;
+ 
+ /*
+@@ -128,7 +135,7 @@ struct io_apic {
+ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+ {
+ 	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+-		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
++		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+ }
+ #endif
+ 
+@@ -142,7 +149,7 @@ static inline unsigned int io_apic_read(
+ 	struct physdev_apic apic_op;
+ 	int ret;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+ 	apic_op.reg = reg;
+ 	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+ 	if (ret)
+@@ -160,7 +167,7 @@ static inline void io_apic_write(unsigne
+ #else
+ 	struct physdev_apic apic_op;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+ 	apic_op.reg = reg;
+ 	apic_op.value = value;
+ 	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+@@ -288,7 +295,7 @@ static void __init replace_pin_at_irq(un
+ 	}
+ }
+ 
+-static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
++static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
+ {
+ 	struct irq_pin_list *entry = irq_2_pin + irq;
+ 	unsigned int pin, reg;
+@@ -308,30 +315,32 @@ static void __modify_IO_APIC_irq (unsign
+ }
+ 
+ /* mask = 1 */
+-static void __mask_IO_APIC_irq (unsigned int irq)
++static void __mask_IO_APIC_irq(unsigned int irq)
+ {
+-	__modify_IO_APIC_irq(irq, 0x00010000, 0);
++	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
+ }
+ 
+ /* mask = 0 */
+-static void __unmask_IO_APIC_irq (unsigned int irq)
++static void __unmask_IO_APIC_irq(unsigned int irq)
+ {
+-	__modify_IO_APIC_irq(irq, 0, 0x00010000);
++	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
+ }
+ 
+ /* mask = 1, trigger = 0 */
+-static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
++static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
+ {
+-	__modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
++	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
++				IO_APIC_REDIR_LEVEL_TRIGGER);
+ }
+ 
+ /* mask = 0, trigger = 1 */
+-static void __unmask_and_level_IO_APIC_irq (unsigned int irq)
++static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
+ {
+-	__modify_IO_APIC_irq(irq, 0x00008000, 0x00010000);
++	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
++				IO_APIC_REDIR_MASKED);
+ }
+ 
+-static void mask_IO_APIC_irq (unsigned int irq)
++static void mask_IO_APIC_irq(unsigned int irq)
+ {
+ 	unsigned long flags;
+ 
+@@ -340,7 +349,7 @@ static void mask_IO_APIC_irq (unsigned i
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+-static void unmask_IO_APIC_irq (unsigned int irq)
++static void unmask_IO_APIC_irq(unsigned int irq)
+ {
+ 	unsigned long flags;
+ 
+@@ -352,7 +361,7 @@ static void unmask_IO_APIC_irq (unsigned
+ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	
++
+ 	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+ 	entry = ioapic_read_entry(apic, pin);
+ 	if (entry.delivery_mode == dest_SMI)
+@@ -364,7 +373,7 @@ static void clear_IO_APIC_pin(unsigned i
+ 	ioapic_mask_entry(apic, pin);
+ }
+ 
+-static void clear_IO_APIC (void)
++static void clear_IO_APIC(void)
+ {
+ 	int apic, pin;
+ 
+@@ -381,7 +390,7 @@ static void set_ioapic_affinity_irq(unsi
+ 	struct irq_pin_list *entry = irq_2_pin + irq;
+ 	unsigned int apicid_value;
+ 	cpumask_t tmp;
+-	
++
+ 	cpus_and(tmp, cpumask, cpu_online_map);
+ 	if (cpus_empty(tmp))
+ 		tmp = TARGET_CPUS;
+@@ -410,7 +419,7 @@ static void set_ioapic_affinity_irq(unsi
+ # include <linux/kernel_stat.h>	/* kstat */
+ # include <linux/slab.h>		/* kmalloc() */
+ # include <linux/timer.h>
+- 
++
+ #define IRQBALANCE_CHECK_ARCH -999
+ #define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+ #define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
+@@ -422,14 +431,14 @@ static int physical_balance __read_mostl
+ static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
+ 
+ static struct irq_cpu_info {
+-	unsigned long * last_irq;
+-	unsigned long * irq_delta;
++	unsigned long *last_irq;
++	unsigned long *irq_delta;
+ 	unsigned long irq;
+ } irq_cpu_data[NR_CPUS];
+ 
+ #define CPU_IRQ(cpu)		(irq_cpu_data[cpu].irq)
+-#define LAST_CPU_IRQ(cpu,irq)   (irq_cpu_data[cpu].last_irq[irq])
+-#define IRQ_DELTA(cpu,irq) 	(irq_cpu_data[cpu].irq_delta[irq])
++#define LAST_CPU_IRQ(cpu, irq)   (irq_cpu_data[cpu].last_irq[irq])
++#define IRQ_DELTA(cpu, irq) 	(irq_cpu_data[cpu].irq_delta[irq])
+ 
+ #define IDLE_ENOUGH(cpu,now) \
+ 	(idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1))
+@@ -468,8 +477,8 @@ inside:
+ 			if (cpu == -1)
+ 				cpu = NR_CPUS-1;
+ 		}
+-	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
+-			(search_idle && !IDLE_ENOUGH(cpu,now)));
++	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu, allowed_mask) ||
++			(search_idle && !IDLE_ENOUGH(cpu, now)));
+ 
+ 	return cpu;
+ }
+@@ -479,15 +488,14 @@ static inline void balance_irq(int cpu, 
+ 	unsigned long now = jiffies;
+ 	cpumask_t allowed_mask;
+ 	unsigned int new_cpu;
+-		
++
+ 	if (irqbalance_disabled)
+-		return; 
++		return;
+ 
+ 	cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
+ 	new_cpu = move(cpu, allowed_mask, now, 1);
+-	if (cpu != new_cpu) {
++	if (cpu != new_cpu)
+ 		set_pending_irq(irq, cpumask_of_cpu(new_cpu));
+-	}
+ }
+ 
+ static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
+@@ -499,14 +507,14 @@ static inline void rotate_irqs_among_cpu
+ 			if (!irq_desc[j].action)
+ 				continue;
+ 			/* Is it a significant load ?  */
+-			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
++			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i), j) <
+ 						useful_load_threshold)
+ 				continue;
+ 			balance_irq(i, j);
+ 		}
+ 	}
+ 	balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+-		balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);	
++		balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ 	return;
+ }
+ 
+@@ -535,22 +543,22 @@ static void do_irq_balance(void)
+ 			/* Is this an active IRQ or balancing disabled ? */
+ 			if (!irq_desc[j].action || irq_balancing_disabled(j))
+ 				continue;
+-			if ( package_index == i )
+-				IRQ_DELTA(package_index,j) = 0;
++			if (package_index == i)
++				IRQ_DELTA(package_index, j) = 0;
+ 			/* Determine the total count per processor per IRQ */
+ 			value_now = (unsigned long) kstat_cpu(i).irqs[j];
+ 
+ 			/* Determine the activity per processor per IRQ */
+-			delta = value_now - LAST_CPU_IRQ(i,j);
++			delta = value_now - LAST_CPU_IRQ(i, j);
+ 
+ 			/* Update last_cpu_irq[][] for the next time */
+-			LAST_CPU_IRQ(i,j) = value_now;
++			LAST_CPU_IRQ(i, j) = value_now;
+ 
+ 			/* Ignore IRQs whose rate is less than the clock */
+ 			if (delta < useful_load_threshold)
+ 				continue;
+ 			/* update the load for the processor or package total */
+-			IRQ_DELTA(package_index,j) += delta;
++			IRQ_DELTA(package_index, j) += delta;
+ 
+ 			/* Keep track of the higher numbered sibling as well */
+ 			if (i != package_index)
+@@ -576,7 +584,8 @@ static void do_irq_balance(void)
+ 	max_cpu_irq = ULONG_MAX;
+ 
+ tryanothercpu:
+-	/* Look for heaviest loaded processor.
++	/*
++	 * Look for heaviest loaded processor.
+ 	 * We may come back to get the next heaviest loaded processor.
+ 	 * Skip processors with trivial loads.
+ 	 */
+@@ -585,7 +594,7 @@ tryanothercpu:
+ 	for_each_online_cpu(i) {
+ 		if (i != CPU_TO_PACKAGEINDEX(i))
+ 			continue;
+-		if (max_cpu_irq <= CPU_IRQ(i)) 
++		if (max_cpu_irq <= CPU_IRQ(i))
+ 			continue;
+ 		if (tmp_cpu_irq < CPU_IRQ(i)) {
+ 			tmp_cpu_irq = CPU_IRQ(i);
+@@ -594,8 +603,9 @@ tryanothercpu:
+ 	}
+ 
+ 	if (tmp_loaded == -1) {
+- 	 /* In the case of small number of heavy interrupt sources, 
+-	  * loading some of the cpus too much. We use Ingo's original 
++	 /*
++	  * In the case of small number of heavy interrupt sources,
++	  * loading some of the cpus too much. We use Ingo's original
+ 	  * approach to rotate them around.
+ 	  */
+ 		if (!first_attempt && imbalance >= useful_load_threshold) {
+@@ -604,13 +614,14 @@ tryanothercpu:
+ 		}
+ 		goto not_worth_the_effort;
+ 	}
+-	
++
+ 	first_attempt = 0;		/* heaviest search */
+ 	max_cpu_irq = tmp_cpu_irq;	/* load */
+ 	max_loaded = tmp_loaded;	/* processor */
+ 	imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+-	
+-	/* if imbalance is less than approx 10% of max load, then
++
++	/*
++	 * if imbalance is less than approx 10% of max load, then
+ 	 * observe diminishing returns action. - quit
+ 	 */
+ 	if (imbalance < (max_cpu_irq >> 3))
+@@ -626,26 +637,25 @@ tryanotherirq:
+ 		/* Is this an active IRQ? */
+ 		if (!irq_desc[j].action)
+ 			continue;
+-		if (imbalance <= IRQ_DELTA(max_loaded,j))
++		if (imbalance <= IRQ_DELTA(max_loaded, j))
+ 			continue;
+ 		/* Try to find the IRQ that is closest to the imbalance
+ 		 * without going over.
+ 		 */
+-		if (move_this_load < IRQ_DELTA(max_loaded,j)) {
+-			move_this_load = IRQ_DELTA(max_loaded,j);
++		if (move_this_load < IRQ_DELTA(max_loaded, j)) {
++			move_this_load = IRQ_DELTA(max_loaded, j);
+ 			selected_irq = j;
+ 		}
+ 	}
+-	if (selected_irq == -1) {
++	if (selected_irq == -1)
+ 		goto tryanothercpu;
+-	}
+ 
+ 	imbalance = move_this_load;
+-	
++
+ 	/* For physical_balance case, we accumulated both load
+ 	 * values in the one of the siblings cpu_irq[],
+ 	 * to use the same code for physical and logical processors
+-	 * as much as possible. 
++	 * as much as possible.
+ 	 *
+ 	 * NOTE: the cpu_irq[] array holds the sum of the load for
+ 	 * sibling A and sibling B in the slot for the lowest numbered
+@@ -674,11 +684,11 @@ tryanotherirq:
+ 		/* mark for change destination */
+ 		set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+ 
+-		/* Since we made a change, come back sooner to 
++		/* Since we made a change, come back sooner to
+ 		 * check for more variation.
+ 		 */
+ 		balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+-			balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);	
++			balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+ 		return;
+ 	}
+ 	goto tryanotherirq;
+@@ -689,7 +699,7 @@ not_worth_the_effort:
+ 	 * upward
+ 	 */
+ 	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
+-		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);	
++		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+ 	return;
+ }
+ 
+@@ -728,13 +738,13 @@ static int __init balanced_irq_init(void
+ 	cpumask_t tmp;
+ 
+ 	cpus_shift_right(tmp, cpu_online_map, 2);
+-        c = &boot_cpu_data;
++	c = &boot_cpu_data;
+ 	/* When not overwritten by the command line ask subarchitecture. */
+ 	if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
+ 		irqbalance_disabled = NO_BALANCE_IRQ;
+ 	if (irqbalance_disabled)
+ 		return 0;
+-	
++
+ 	 /* disable irqbalance completely if there is only one processor online */
+ 	if (num_online_cpus() < 2) {
+ 		irqbalance_disabled = 1;
+@@ -748,16 +758,14 @@ static int __init balanced_irq_init(void
+ 		physical_balance = 1;
+ 
+ 	for_each_online_cpu(i) {
+-		irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+-		irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
++		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
++		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+ 		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
+ 			printk(KERN_ERR "balanced_irq_init: out of memory");
+ 			goto failed;
+ 		}
+-		memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);
+-		memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);
+ 	}
+-	
++
+ 	printk(KERN_INFO "Starting balanced_irq\n");
+ 	if (!IS_ERR(kthread_run(balanced_irq, NULL, "kirqd")))
+ 		return 0;
+@@ -799,7 +807,7 @@ void send_IPI_self(int vector)
+ 	/*
+ 	 * Send the IPI. The write to APIC_ICR fires this off.
+ 	 */
+-	apic_write_around(APIC_ICR, cfg);
++	apic_write(APIC_ICR, cfg);
+ #endif
+ }
+ #endif /* !CONFIG_SMP */
+@@ -853,10 +861,10 @@ static int find_irq_entry(int apic, int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mpc_irqtype == type &&
+-		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
+-		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
+-		    mp_irqs[i].mpc_dstirq == pin)
++		if (mp_irqs[i].mp_irqtype == type &&
++		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
++		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].mp_dstirq == pin)
+ 			return i;
+ 
+ 	return -1;
+@@ -871,13 +879,13 @@ static int __init find_isa_irq_pin(int i
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mpc_irqtype == type) &&
+-		    (mp_irqs[i].mpc_srcbusirq == irq))
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
+ 
+-			return mp_irqs[i].mpc_dstirq;
++			return mp_irqs[i].mp_dstirq;
+ 	}
+ 	return -1;
+ }
+@@ -887,17 +895,17 @@ static int __init find_isa_irq_apic(int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mpc_irqtype == type) &&
+-		    (mp_irqs[i].mpc_srcbusirq == irq))
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
+ 			break;
+ 	}
+ 	if (i < mp_irq_entries) {
+ 		int apic;
+-		for(apic = 0; apic < nr_ioapics; apic++) {
+-			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
++		for (apic = 0; apic < nr_ioapics; apic++) {
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
+ 				return apic;
+ 		}
+ 	}
+@@ -918,28 +926,28 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 
+ 	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
+ 		"slot:%d, pin:%d.\n", bus, slot, pin);
+-	if (mp_bus_id_to_pci_bus[bus] == -1) {
++	if (test_bit(bus, mp_bus_not_pci)) {
+ 		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+ 		return -1;
+ 	}
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
+-			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
++			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
+ 				break;
+ 
+ 		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].mpc_irqtype &&
++		    !mp_irqs[i].mp_irqtype &&
+ 		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
++		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i, apic, mp_irqs[i].mp_dstirq);
+ 
+ 			if (!(apic || IO_APIC_IRQ(irq)))
+ 				continue;
+ 
+-			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
++			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
+ 				return irq;
+ 			/*
+ 			 * Use the first all-but-pin matching entry as a
+@@ -954,7 +962,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+ 
+ /*
+- * This function currently is only a helper for the i386 smp boot process where 
++ * This function currently is only a helper for the i386 smp boot process where
+  * we need to reprogram the ioredtbls to cater for the cpus which have come online
+  * so mask in all cases should simply be TARGET_CPUS
+  */
+@@ -1008,7 +1016,7 @@ static int EISA_ELCR(unsigned int irq)
+  * EISA conforming in the MP table, that means its trigger type must
+  * be read in from the ELCR */
+ 
+-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
++#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+ #define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+ 
+ /* PCI interrupts are always polarity one level triggered,
+@@ -1025,118 +1033,115 @@ static int EISA_ELCR(unsigned int irq)
+ 
+ static int MPBIOS_polarity(int idx)
+ {
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 	int polarity;
+ 
+ 	/*
+ 	 * Determine IRQ line polarity (high active or low active):
+ 	 */
+-	switch (mp_irqs[idx].mpc_irqflag & 3)
++	switch (mp_irqs[idx].mp_irqflag & 3) {
++	case 0: /* conforms, ie. bus-type dependent polarity */
+ 	{
+-		case 0: /* conforms, ie. bus-type dependent polarity */
+-		{
+-			polarity = test_bit(bus, mp_bus_not_pci)?
+-				default_ISA_polarity(idx):
+-				default_PCI_polarity(idx);
+-			break;
+-		}
+-		case 1: /* high active */
+-		{
+-			polarity = 0;
+-			break;
+-		}
+-		case 2: /* reserved */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			polarity = 1;
+-			break;
+-		}
+-		case 3: /* low active */
+-		{
+-			polarity = 1;
+-			break;
+-		}
+-		default: /* invalid */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			polarity = 1;
+-			break;
+-		}
++		polarity = test_bit(bus, mp_bus_not_pci)?
++			default_ISA_polarity(idx):
++			default_PCI_polarity(idx);
++		break;
++	}
++	case 1: /* high active */
++	{
++		polarity = 0;
++		break;
++	}
++	case 2: /* reserved */
++	{
++		printk(KERN_WARNING "broken BIOS!!\n");
++		polarity = 1;
++		break;
++	}
++	case 3: /* low active */
++	{
++		polarity = 1;
++		break;
++	}
++	default: /* invalid */
++	{
++		printk(KERN_WARNING "broken BIOS!!\n");
++		polarity = 1;
++		break;
++	}
+ 	}
+ 	return polarity;
+ }
+ 
+ static int MPBIOS_trigger(int idx)
+ {
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 	int trigger;
+ 
+ 	/*
+ 	 * Determine IRQ trigger mode (edge or level sensitive):
+ 	 */
+-	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
++	switch ((mp_irqs[idx].mp_irqflag>>2) & 3) {
++	case 0: /* conforms, ie. bus-type dependent */
+ 	{
+-		case 0: /* conforms, ie. bus-type dependent */
+-		{
+-			trigger = test_bit(bus, mp_bus_not_pci)?
+-					default_ISA_trigger(idx):
+-					default_PCI_trigger(idx);
++		trigger = test_bit(bus, mp_bus_not_pci)?
++				default_ISA_trigger(idx):
++				default_PCI_trigger(idx);
+ #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+-			switch (mp_bus_id_to_type[bus])
+-			{
+-				case MP_BUS_ISA: /* ISA pin */
+-				{
+-					/* set before the switch */
+-					break;
+-				}
+-				case MP_BUS_EISA: /* EISA pin */
+-				{
+-					trigger = default_EISA_trigger(idx);
+-					break;
+-				}
+-				case MP_BUS_PCI: /* PCI pin */
+-				{
+-					/* set before the switch */
+-					break;
+-				}
+-				case MP_BUS_MCA: /* MCA pin */
+-				{
+-					trigger = default_MCA_trigger(idx);
+-					break;
+-				}
+-				default:
+-				{
+-					printk(KERN_WARNING "broken BIOS!!\n");
+-					trigger = 1;
+-					break;
+-				}
+-			}
+-#endif
++		switch (mp_bus_id_to_type[bus]) {
++		case MP_BUS_ISA: /* ISA pin */
++		{
++			/* set before the switch */
+ 			break;
+ 		}
+-		case 1: /* edge */
++		case MP_BUS_EISA: /* EISA pin */
+ 		{
+-			trigger = 0;
++			trigger = default_EISA_trigger(idx);
+ 			break;
+ 		}
+-		case 2: /* reserved */
++		case MP_BUS_PCI: /* PCI pin */
+ 		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			trigger = 1;
++			/* set before the switch */
+ 			break;
+ 		}
+-		case 3: /* level */
++		case MP_BUS_MCA: /* MCA pin */
+ 		{
+-			trigger = 1;
++			trigger = default_MCA_trigger(idx);
+ 			break;
+ 		}
+-		default: /* invalid */
++		default:
+ 		{
+ 			printk(KERN_WARNING "broken BIOS!!\n");
+-			trigger = 0;
++			trigger = 1;
+ 			break;
+ 		}
+ 	}
++#endif
++		break;
++	}
++	case 1: /* edge */
++	{
++		trigger = 0;
++		break;
++	}
++	case 2: /* reserved */
++	{
++		printk(KERN_WARNING "broken BIOS!!\n");
++		trigger = 1;
++		break;
++	}
++	case 3: /* level */
++	{
++		trigger = 1;
++		break;
++	}
++	default: /* invalid */
++	{
++		printk(KERN_WARNING "broken BIOS!!\n");
++		trigger = 0;
++		break;
++	}
++	}
+ 	return trigger;
+ }
+ 
+@@ -1153,16 +1158,16 @@ static inline int irq_trigger(int idx)
+ static int pin_2_irq(int idx, int apic, int pin)
+ {
+ 	int irq, i;
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 
+ 	/*
+ 	 * Debugging check, we are in big trouble if this message pops up!
+ 	 */
+-	if (mp_irqs[idx].mpc_dstirq != pin)
++	if (mp_irqs[idx].mp_dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+ 	if (test_bit(bus, mp_bus_not_pci))
+-		irq = mp_irqs[idx].mpc_srcbusirq;
++		irq = mp_irqs[idx].mp_srcbusirq;
+ 	else {
+ 		/*
+ 		 * PCI IRQs are mapped in order
+@@ -1204,8 +1209,8 @@ static inline int IO_APIC_irq_trigger(in
+ 
+ 	for (apic = 0; apic < nr_ioapics; apic++) {
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-			idx = find_irq_entry(apic,pin,mp_INT);
+-			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
++			idx = find_irq_entry(apic, pin, mp_INT);
++			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ 				return irq_trigger(idx);
+ 		}
+ 	}
+@@ -1291,25 +1296,25 @@ static void __init setup_IO_APIC_irqs(vo
+ 		/*
+ 		 * add it to the IO-APIC irq-routing table:
+ 		 */
+-		memset(&entry,0,sizeof(entry));
++		memset(&entry, 0, sizeof(entry));
+ 
+ 		entry.delivery_mode = INT_DELIVERY_MODE;
+ 		entry.dest_mode = INT_DEST_MODE;
+ 		entry.mask = 0;				/* enable IRQ */
+-		entry.dest.logical.logical_dest = 
++		entry.dest.logical.logical_dest =
+ 					cpu_mask_to_apicid(TARGET_CPUS);
+ 
+-		idx = find_irq_entry(apic,pin,mp_INT);
++		idx = find_irq_entry(apic, pin, mp_INT);
+ 		if (idx == -1) {
+ 			if (first_notcon) {
+ 				apic_printk(APIC_VERBOSE, KERN_DEBUG
+ 						" IO-APIC (apicid-pin) %d-%d",
+-						mp_ioapics[apic].mpc_apicid,
++						mp_ioapics[apic].mp_apicid,
+ 						pin);
+ 				first_notcon = 0;
+ 			} else
+ 				apic_printk(APIC_VERBOSE, ", %d-%d",
+-					mp_ioapics[apic].mpc_apicid, pin);
++					mp_ioapics[apic].mp_apicid, pin);
+ 			continue;
+ 		}
+ 
+@@ -1343,7 +1348,7 @@ static void __init setup_IO_APIC_irqs(vo
+ 			vector = assign_irq_vector(irq);
+ 			entry.vector = vector;
+ 			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+-		
++
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
+@@ -1355,27 +1360,23 @@ static void __init setup_IO_APIC_irqs(vo
+ 		apic_printk(APIC_VERBOSE, " not connected.\n");
+ }
+ 
++#ifndef CONFIG_XEN
+ /*
+- * Set up the 8259A-master output pin:
++ * Set up the timer pin, possibly with the 8259A-master behind.
+  */
+-#ifndef CONFIG_XEN
+-static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
++static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
++					int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+ 
+-	memset(&entry,0,sizeof(entry));
+-
+-	disable_8259A_irq(0);
+-
+-	/* mask LVT0 */
+-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++	memset(&entry, 0, sizeof(entry));
+ 
+ 	/*
+ 	 * We use logical delivery to get the timer IRQ
+ 	 * to the first CPU.
+ 	 */
+ 	entry.dest_mode = INT_DEST_MODE;
+-	entry.mask = 0;					/* unmask IRQ now */
++	entry.mask = 1;					/* mask IRQ now */
+ 	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.polarity = 0;
+@@ -1384,17 +1385,14 @@ static void __init setup_ExtINT_IRQ0_pin
+ 
+ 	/*
+ 	 * The timer IRQ doesn't have to know that behind the
+-	 * scene we have a 8259A-master in AEOI mode ...
++	 * scene we may have a 8259A-master in AEOI mode ...
+ 	 */
+-	irq_desc[0].chip = &ioapic_chip;
+-	set_irq_handler(0, handle_edge_irq);
++	ioapic_register_intr(0, vector, IOAPIC_EDGE);
+ 
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+ 	ioapic_write_entry(apic, pin, entry);
+-
+-	enable_8259A_irq(0);
+ }
+ 
+ void __init print_IO_APIC(void)
+@@ -1409,10 +1407,10 @@ void __init print_IO_APIC(void)
+ 	if (apic_verbosity == APIC_QUIET)
+ 		return;
+ 
+- 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
++	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+ 	for (i = 0; i < nr_ioapics; i++)
+ 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+-		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
++		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
+ 
+ 	/*
+ 	 * We are a bit conservative about what we expect.  We have to
+@@ -1431,7 +1429,7 @@ void __init print_IO_APIC(void)
+ 		reg_03.raw = io_apic_read(apic, 3);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
+ 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+ 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+@@ -1512,7 +1510,7 @@ void __init print_IO_APIC(void)
+ 	return;
+ }
+ 
+-static void print_APIC_bitfield (int base)
++static void print_APIC_bitfield(int base)
+ {
+ 	unsigned int v;
+ 	int i, j;
+@@ -1533,7 +1531,7 @@ static void print_APIC_bitfield (int bas
+ 	}
+ }
+ 
+-void /*__init*/ print_local_APIC(void * dummy)
++void /*__init*/ print_local_APIC(void *dummy)
+ {
+ 	unsigned int v, ver, maxlvt;
+ 
+@@ -1542,6 +1540,7 @@ void /*__init*/ print_local_APIC(void * 
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
++	v = apic_read(APIC_ID);
+ 	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
+ 			GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+@@ -1616,9 +1615,9 @@ void /*__init*/ print_local_APIC(void * 
+ 	printk("\n");
+ }
+ 
+-void print_all_local_APICs (void)
++void print_all_local_APICs(void)
+ {
+-	on_each_cpu(print_local_APIC, NULL, 1, 1);
++	on_each_cpu(print_local_APIC, NULL, 1);
+ }
+ 
+ void /*__init*/ print_PIC(void)
+@@ -1639,11 +1638,11 @@ void /*__init*/ print_PIC(void)
+ 	v = inb(0xa0) << 8 | inb(0x20);
+ 	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
+ 
+-	outb(0x0b,0xa0);
+-	outb(0x0b,0x20);
++	outb(0x0b, 0xa0);
++	outb(0x0b, 0x20);
+ 	v = inb(0xa0) << 8 | inb(0x20);
+-	outb(0x0a,0xa0);
+-	outb(0x0a,0x20);
++	outb(0x0a, 0xa0);
++	outb(0x0a, 0x20);
+ 
+ 	spin_unlock_irqrestore(&i8259A_lock, flags);
+ 
+@@ -1652,6 +1651,8 @@ void /*__init*/ print_PIC(void)
+ 	v = inb(0x4d1) << 8 | inb(0x4d0);
+ 	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+ }
++#else
++void __init print_IO_APIC(void) {}
+ #endif /* !CONFIG_XEN */
+ 
+ static void __init enable_IO_APIC(void)
+@@ -1681,7 +1682,7 @@ static void __init enable_IO_APIC(void)
+ 		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+ 	}
+ #ifndef CONFIG_XEN
+-	for(apic = 0; apic < nr_ioapics; apic++) {
++	for (apic = 0; apic < nr_ioapics; apic++) {
+ 		int pin;
+ 		/* See if any of the pins is in ExtINT mode */
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+@@ -1774,7 +1775,7 @@ void disable_IO_APIC(void)
+  * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+  */
+ 
+-#if !defined(CONFIG_XEN) && !defined(CONFIG_X86_NUMAQ)
++#ifndef CONFIG_XEN
+ static void __init setup_ioapic_ids_from_mpc(void)
+ {
+ 	union IO_APIC_reg_00 reg_00;
+@@ -1784,6 +1785,11 @@ static void __init setup_ioapic_ids_from
+ 	unsigned char old_id;
+ 	unsigned long flags;
+ 
++#ifdef CONFIG_X86_NUMAQ
++	if (found_numaq)
++		return;
++#endif
++
+ 	/*
+ 	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+ 	 * no meaning without the serial APIC bus.
+@@ -1806,15 +1812,15 @@ static void __init setup_ioapic_ids_from
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+ 		reg_00.raw = io_apic_read(apic, 0);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		
+-		old_id = mp_ioapics[apic].mpc_apicid;
+ 
+-		if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) {
++		old_id = mp_ioapics[apic].mp_apicid;
++
++		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
+ 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+-				apic, mp_ioapics[apic].mpc_apicid);
++				apic, mp_ioapics[apic].mp_apicid);
+ 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ 				reg_00.bits.ID);
+-			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
++			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
+ 		}
+ 
+ 		/*
+@@ -1823,9 +1829,9 @@ static void __init setup_ioapic_ids_from
+ 		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+ 		 */
+ 		if (check_apicid_used(phys_id_present_map,
+-					mp_ioapics[apic].mpc_apicid)) {
++					mp_ioapics[apic].mp_apicid)) {
+ 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+-				apic, mp_ioapics[apic].mpc_apicid);
++				apic, mp_ioapics[apic].mp_apicid);
+ 			for (i = 0; i < get_physical_broadcast(); i++)
+ 				if (!physid_isset(i, phys_id_present_map))
+ 					break;
+@@ -1834,13 +1840,13 @@ static void __init setup_ioapic_ids_from
+ 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+ 				i);
+ 			physid_set(i, phys_id_present_map);
+-			mp_ioapics[apic].mpc_apicid = i;
++			mp_ioapics[apic].mp_apicid = i;
+ 		} else {
+ 			physid_mask_t tmp;
+-			tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid);
++			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
+ 			apic_printk(APIC_VERBOSE, "Setting %d in the "
+ 					"phys_id_present_map\n",
+-					mp_ioapics[apic].mpc_apicid);
++					mp_ioapics[apic].mp_apicid);
+ 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+ 		}
+ 
+@@ -1849,21 +1855,21 @@ static void __init setup_ioapic_ids_from
+ 		 * We need to adjust the IRQ routing table
+ 		 * if the ID changed.
+ 		 */
+-		if (old_id != mp_ioapics[apic].mpc_apicid)
++		if (old_id != mp_ioapics[apic].mp_apicid)
+ 			for (i = 0; i < mp_irq_entries; i++)
+-				if (mp_irqs[i].mpc_dstapic == old_id)
+-					mp_irqs[i].mpc_dstapic
+-						= mp_ioapics[apic].mpc_apicid;
++				if (mp_irqs[i].mp_dstapic == old_id)
++					mp_irqs[i].mp_dstapic
++						= mp_ioapics[apic].mp_apicid;
+ 
+ 		/*
+ 		 * Read the right value from the MPC table and
+ 		 * write it into the ID register.
+-	 	 */
++		 */
+ 		apic_printk(APIC_VERBOSE, KERN_INFO
+ 			"...changing IO-APIC physical APIC ID to %d ...",
+-			mp_ioapics[apic].mpc_apicid);
++			mp_ioapics[apic].mp_apicid);
+ 
+-		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
++		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+ 		io_apic_write(apic, 0, reg_00.raw);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+@@ -1874,17 +1880,13 @@ static void __init setup_ioapic_ids_from
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+ 		reg_00.raw = io_apic_read(apic, 0);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
++		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
+ 			printk("could not set ID!\n");
+ 		else
+ 			apic_printk(APIC_VERBOSE, " ok.\n");
+ 	}
+ }
+-#else
+-static void __init setup_ioapic_ids_from_mpc(void) { }
+-#endif
+ 
+-#ifndef CONFIG_XEN
+ int no_timer_check __initdata;
+ 
+ static int __init notimercheck(char *s)
+@@ -2077,45 +2079,53 @@ static inline void init_IO_APIC_traps(vo
+  * The local APIC irq-chip implementation:
+  */
+ 
+-static void ack_apic(unsigned int irq)
++static void ack_lapic_irq(unsigned int irq)
+ {
+ 	ack_APIC_irq();
+ }
+ 
+-static void mask_lapic_irq (unsigned int irq)
++static void mask_lapic_irq(unsigned int irq)
+ {
+ 	unsigned long v;
+ 
+ 	v = apic_read(APIC_LVT0);
+-	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
++	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+ }
+ 
+-static void unmask_lapic_irq (unsigned int irq)
++static void unmask_lapic_irq(unsigned int irq)
+ {
+ 	unsigned long v;
+ 
+ 	v = apic_read(APIC_LVT0);
+-	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
++	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+ }
+ 
+ static struct irq_chip lapic_chip __read_mostly = {
+-	.name		= "local-APIC-edge",
++	.name		= "local-APIC",
+ 	.mask		= mask_lapic_irq,
+ 	.unmask		= unmask_lapic_irq,
+-	.eoi		= ack_apic,
++	.ack		= ack_lapic_irq,
+ };
+ 
++static void lapic_register_intr(int irq, int vector)
++{
++	irq_desc[irq].status &= ~IRQ_LEVEL;
++	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
++				      "edge");
++	set_intr_gate(vector, interrupt[irq]);
++}
++
+ static void __init setup_nmi(void)
+ {
+ 	/*
+- 	 * Dirty trick to enable the NMI watchdog ...
++	 * Dirty trick to enable the NMI watchdog ...
+ 	 * We put the 8259A master into AEOI mode and
+ 	 * unmask on all local APICs LVT0 as NMI.
+ 	 *
+ 	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+ 	 * is from Maciej W. Rozycki - so we do not have to EOI from
+ 	 * the NMI handler or the timer interrupt.
+-	 */ 
++	 */
+ 	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+ 
+ 	enable_NMI_through_LVT0();
+@@ -2191,11 +2201,16 @@ static inline void __init unlock_ExtINT_
+ static inline void __init check_timer(void)
+ {
+ 	int apic1, pin1, apic2, pin2;
++	int no_pin1 = 0;
+ 	int vector;
++	unsigned int ver;
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+ 
++	ver = apic_read(APIC_LVR);
++	ver = GET_APIC_VERSION(ver);
++
+ 	/*
+ 	 * get/set the timer IRQ vector:
+ 	 */
+@@ -2204,34 +2219,54 @@ static inline void __init check_timer(vo
+ 	set_intr_gate(vector, interrupt[0]);
+ 
+ 	/*
+-	 * Subtle, code in do_timer_interrupt() expects an AEOI
+-	 * mode for the 8259A whenever interrupts are routed
+-	 * through I/O APICs.  Also IRQ0 has to be enabled in
+-	 * the 8259A which implies the virtual wire has to be
+-	 * disabled in the local APIC.
++	 * As IRQ0 is to be enabled in the 8259A, the virtual
++	 * wire has to be disabled in the local APIC.  Also
++	 * timer interrupts need to be acknowledged manually in
++	 * the 8259A for the i82489DX when using the NMI
++	 * watchdog as that APIC treats NMIs as level-triggered.
++	 * The AEOI mode will finish them in the 8259A
++	 * automatically.
+ 	 */
+-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ 	init_8259A(1);
+-	timer_ack = 1;
+-	if (timer_over_8254 > 0)
+-		enable_8259A_irq(0);
++	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+ 
+ 	pin1  = find_isa_irq_pin(0, mp_INT);
+ 	apic1 = find_isa_irq_apic(0, mp_INT);
+ 	pin2  = ioapic_i8259.pin;
+ 	apic2 = ioapic_i8259.apic;
+ 
+-	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+-		vector, apic1, pin1, apic2, pin2);
++	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
++		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
++		    vector, apic1, pin1, apic2, pin2);
++
++	/*
++	 * Some BIOS writers are clueless and report the ExtINTA
++	 * I/O APIC input from the cascaded 8259A as the timer
++	 * interrupt input.  So just in case, if only one pin
++	 * was found above, try it both directly and through the
++	 * 8259A.
++	 */
++	if (pin1 == -1) {
++		pin1 = pin2;
++		apic1 = apic2;
++		no_pin1 = 1;
++	} else if (pin2 == -1) {
++		pin2 = pin1;
++		apic2 = apic1;
++	}
+ 
+ 	if (pin1 != -1) {
+ 		/*
+ 		 * Ok, does IRQ0 through the IOAPIC work?
+ 		 */
++		if (no_pin1) {
++			add_pin_to_irq(0, apic1, pin1);
++			setup_timer_IRQ0_pin(apic1, pin1, vector);
++		}
+ 		unmask_IO_APIC_irq(0);
+ 		if (timer_irq_works()) {
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+-				disable_8259A_irq(0);
+ 				setup_nmi();
+ 				enable_8259A_irq(0);
+ 			}
+@@ -2240,71 +2275,77 @@ static inline void __init check_timer(vo
+ 			goto out;
+ 		}
+ 		clear_IO_APIC_pin(apic1, pin1);
+-		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
+-				"IO-APIC\n");
+-	}
+-
+-	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
+-	if (pin2 != -1) {
+-		printk("\n..... (found pin %d) ...", pin2);
++		if (!no_pin1)
++			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
++				    "8254 timer not connected to IO-APIC\n");
++
++		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
++			    "(IRQ0) through the 8259A ...\n");
++		apic_printk(APIC_QUIET, KERN_INFO
++			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+ 		/*
+ 		 * legacy devices should be connected to IO APIC #0
+ 		 */
+-		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
++		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
++		setup_timer_IRQ0_pin(apic2, pin2, vector);
++		unmask_IO_APIC_irq(0);
++		enable_8259A_irq(0);
+ 		if (timer_irq_works()) {
+-			printk("works.\n");
+-			if (pin1 != -1)
+-				replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+-			else
+-				add_pin_to_irq(0, apic2, pin2);
++			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
++			timer_through_8259 = 1;
+ 			if (nmi_watchdog == NMI_IO_APIC) {
++				disable_8259A_irq(0);
+ 				setup_nmi();
++				enable_8259A_irq(0);
+ 			}
+ 			goto out;
+ 		}
+ 		/*
+ 		 * Cleanup, just in case ...
+ 		 */
++		disable_8259A_irq(0);
+ 		clear_IO_APIC_pin(apic2, pin2);
++		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+ 	}
+-	printk(" failed.\n");
+ 
+ 	if (nmi_watchdog == NMI_IO_APIC) {
+-		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
+-		nmi_watchdog = 0;
++		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
++			    "through the IO-APIC - disabling NMI Watchdog!\n");
++		nmi_watchdog = NMI_NONE;
+ 	}
++	timer_ack = 0;
+ 
+-	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as Virtual Wire IRQ...\n");
+ 
+-	disable_8259A_irq(0);
+-	set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
+-				      "fasteoi");
+-	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
++	lapic_register_intr(0, vector);
++	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+ 	if (timer_irq_works()) {
+-		printk(" works.\n");
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
+-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+-	printk(" failed.\n");
++	disable_8259A_irq(0);
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+ 
+-	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as ExtINT IRQ...\n");
+ 
+-	timer_ack = 0;
+ 	init_8259A(0);
+ 	make_8259A_irq(0);
+-	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
++	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+ 
+ 	unlock_ExtINT_logic();
+ 
+ 	if (timer_irq_works()) {
+-		printk(" works.\n");
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
+-	printk(" failed :(.\n");
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+ 	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+-		"report.  Then try booting with the 'noapic' option");
++		"report.  Then try booting with the 'noapic' option.\n");
+ out:
+ 	local_irq_restore(flags);
+ }
+@@ -2314,11 +2355,21 @@ int timer_uses_ioapic_pin_0 = 0;
+ #endif
+ 
+ /*
+- *
+- * IRQ's that are handled by the PIC in the MPS IOAPIC case.
+- * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
+- *   Linux doesn't really care, as it's not actually used
+- *   for any interrupt handling anyway.
++ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
++ * to devices.  However there may be an I/O APIC pin available for
++ * this interrupt regardless.  The pin may be left unconnected, but
++ * typically it will be reused as an ExtINT cascade interrupt for
++ * the master 8259A.  In the MPS case such a pin will normally be
++ * reported as an ExtINT interrupt in the MP table.  With ACPI
++ * there is no provision for ExtINT interrupts, and in the absence
++ * of an override it would be treated as an ordinary ISA I/O APIC
++ * interrupt, that is edge-triggered and unmasked by default.  We
++ * used to do this, but it caused problems on some systems because
++ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
++ * the same ExtINT cascade interrupt to drive the local APIC of the
++ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
++ * the I/O APIC in all cases now.  No actual device should request
++ * it anyway.  --macro
+  */
+ #define PIC_IRQS	(1 << PIC_CASCADE_IR)
+ 
+@@ -2328,25 +2379,22 @@ void __init setup_IO_APIC(void)
+ 	int i;
+ 
+ 	/* Reserve all the system vectors. */
+-	for (i = FIRST_SYSTEM_VECTOR; i < NR_VECTORS; i++)
++	for (i = first_system_vector; i < NR_VECTORS; i++)
+ 		set_bit(i, used_vectors);
+ #endif
+ 
+ 	enable_IO_APIC();
+ 
+-	if (acpi_ioapic)
+-		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
+-	else
+-		io_apic_irqs = ~PIC_IRQS;
++	io_apic_irqs = ~PIC_IRQS;
+ 
+ 	printk("ENABLING IO-APIC IRQs\n");
+ 
++#ifndef CONFIG_XEN
+ 	/*
+ 	 * Set up IO-APIC IRQ routing.
+ 	 */
+ 	if (!acpi_ioapic)
+ 		setup_ioapic_ids_from_mpc();
+-#ifndef CONFIG_XEN
+ 	sync_Arb_IDs();
+ #endif
+ 	setup_IO_APIC_irqs();
+@@ -2356,28 +2404,14 @@ void __init setup_IO_APIC(void)
+ 		print_IO_APIC();
+ }
+ 
+-static int __init setup_disable_8254_timer(char *s)
+-{
+-	timer_over_8254 = -1;
+-	return 1;
+-}
+-static int __init setup_enable_8254_timer(char *s)
+-{
+-	timer_over_8254 = 2;
+-	return 1;
+-}
+-
+-__setup("disable_8254_timer", setup_disable_8254_timer);
+-__setup("enable_8254_timer", setup_enable_8254_timer);
+-
+ /*
+  *	Called after all the initialization is done. If we didnt find any
+  *	APIC bugs then we can allow the modify fast path
+  */
+- 
++
+ static int __init io_apic_bug_finalize(void)
+ {
+-	if(sis_apic_bug == -1)
++	if (sis_apic_bug == -1)
+ 		sis_apic_bug = 0;
+ 	if (is_initial_xendomain()) {
+ 		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
+@@ -2396,17 +2430,17 @@ struct sysfs_ioapic_data {
+ 	struct sys_device dev;
+ 	struct IO_APIC_route_entry entry[0];
+ };
+-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
++static struct sysfs_ioapic_data *mp_ioapic_data[MAX_IO_APICS];
+ 
+ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+ {
+ 	struct IO_APIC_route_entry *entry;
+ 	struct sysfs_ioapic_data *data;
+ 	int i;
+-	
++
+ 	data = container_of(dev, struct sysfs_ioapic_data, dev);
+ 	entry = data->entry;
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+ 		entry[i] = ioapic_read_entry(dev->id, i);
+ 
+ 	return 0;
+@@ -2419,18 +2453,18 @@ static int ioapic_resume(struct sys_devi
+ 	unsigned long flags;
+ 	union IO_APIC_reg_00 reg_00;
+ 	int i;
+-	
++
+ 	data = container_of(dev, struct sysfs_ioapic_data, dev);
+ 	entry = data->entry;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	reg_00.raw = io_apic_read(dev->id, 0);
+-	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+-		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
++	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
+ 		io_apic_write(dev->id, 0, reg_00.raw);
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+ 		ioapic_write_entry(dev->id, i, entry[i]);
+ 
+ 	return 0;
+@@ -2444,24 +2478,23 @@ static struct sysdev_class ioapic_sysdev
+ 
+ static int __init ioapic_init_sysfs(void)
+ {
+-	struct sys_device * dev;
++	struct sys_device *dev;
+ 	int i, size, error = 0;
+ 
+ 	error = sysdev_class_register(&ioapic_sysdev_class);
+ 	if (error)
+ 		return error;
+ 
+-	for (i = 0; i < nr_ioapics; i++ ) {
+-		size = sizeof(struct sys_device) + nr_ioapic_registers[i] 
++	for (i = 0; i < nr_ioapics; i++) {
++		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+ 			* sizeof(struct IO_APIC_route_entry);
+-		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
++		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+ 		if (!mp_ioapic_data[i]) {
+ 			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+ 			continue;
+ 		}
+-		memset(mp_ioapic_data[i], 0, size);
+ 		dev = &mp_ioapic_data[i]->dev;
+-		dev->id = i; 
++		dev->id = i;
+ 		dev->cls = &ioapic_sysdev_class;
+ 		error = sysdev_register(dev);
+ 		if (error) {
+@@ -2538,7 +2571,7 @@ static int msi_compose_msg(struct pci_de
+ 		msg->address_lo =
+ 			MSI_ADDR_BASE_LO |
+ 			((INT_DEST_MODE == 0) ?
+-				MSI_ADDR_DEST_MODE_PHYSICAL:
++MSI_ADDR_DEST_MODE_PHYSICAL:
+ 				MSI_ADDR_DEST_MODE_LOGICAL) |
+ 			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+ 				MSI_ADDR_REDIRECTION_CPU:
+@@ -2549,7 +2582,7 @@ static int msi_compose_msg(struct pci_de
+ 			MSI_DATA_TRIGGER_EDGE |
+ 			MSI_DATA_LEVEL_ASSERT |
+ 			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				MSI_DATA_DELIVERY_FIXED:
++MSI_DATA_DELIVERY_FIXED:
+ 				MSI_DATA_DELIVERY_LOWPRI) |
+ 			MSI_DATA_VECTOR(vector);
+ 	}
+@@ -2720,12 +2753,12 @@ int arch_setup_ht_irq(unsigned int irq, 
+ #endif /* CONFIG_HT_IRQ */
+ 
+ /* --------------------------------------------------------------------------
+-                          ACPI-based IOAPIC Configuration
++			ACPI-based IOAPIC Configuration
+    -------------------------------------------------------------------------- */
+ 
+ #ifdef CONFIG_ACPI
+ 
+-int __init io_apic_get_unique_id (int ioapic, int apic_id)
++int __init io_apic_get_unique_id(int ioapic, int apic_id)
+ {
+ #ifndef CONFIG_XEN
+ 	union IO_APIC_reg_00 reg_00;
+@@ -2735,10 +2768,10 @@ int __init io_apic_get_unique_id (int io
+ 	int i = 0;
+ 
+ 	/*
+-	 * The P4 platform supports up to 256 APIC IDs on two separate APIC 
+-	 * buses (one for LAPICs, one for IOAPICs), where predecessors only 
++	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
++	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
+ 	 * supports up to 16 on one shared APIC bus.
+-	 * 
++	 *
+ 	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+ 	 *      advantage of new APIC bus architecture.
+ 	 */
+@@ -2757,7 +2790,7 @@ int __init io_apic_get_unique_id (int io
+ 	}
+ 
+ 	/*
+-	 * Every APIC in a system must have a unique ID or we get lots of nice 
++	 * Every APIC in a system must have a unique ID or we get lots of nice
+ 	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+ 	 */
+ 	if (check_apicid_used(apic_id_map, apic_id)) {
+@@ -2774,7 +2807,7 @@ int __init io_apic_get_unique_id (int io
+ 			"trying %d\n", ioapic, apic_id, i);
+ 
+ 		apic_id = i;
+-	} 
++	}
+ 
+ 	tmp = apicid_to_cpu_present(apic_id);
+ 	physids_or(apic_id_map, apic_id_map, tmp);
+@@ -2802,7 +2835,7 @@ int __init io_apic_get_unique_id (int io
+ }
+ 
+ 
+-int __init io_apic_get_version (int ioapic)
++int __init io_apic_get_version(int ioapic)
+ {
+ 	union IO_APIC_reg_01	reg_01;
+ 	unsigned long flags;
+@@ -2815,7 +2848,7 @@ int __init io_apic_get_version (int ioap
+ }
+ 
+ 
+-int __init io_apic_get_redir_entries (int ioapic)
++int __init io_apic_get_redir_entries(int ioapic)
+ {
+ 	union IO_APIC_reg_01	reg_01;
+ 	unsigned long flags;
+@@ -2828,7 +2861,7 @@ int __init io_apic_get_redir_entries (in
+ }
+ 
+ 
+-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
++int io_apic_set_pci_routing(int ioapic, int pin, int irq, int edge_level, int active_high_low)
+ {
+ 	struct IO_APIC_route_entry entry;
+ 
+@@ -2844,7 +2877,7 @@ int io_apic_set_pci_routing (int ioapic,
+ 	 * corresponding device driver registers for this IRQ.
+ 	 */
+ 
+-	memset(&entry,0,sizeof(entry));
++	memset(&entry, 0, sizeof(entry));
+ 
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.dest_mode = INT_DEST_MODE;
+@@ -2863,7 +2896,7 @@ int io_apic_set_pci_routing (int ioapic,
+ 
+ 	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
+ 		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
+-		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
++		mp_ioapics[ioapic].mp_apicid, pin, entry.vector, irq,
+ 		edge_level, active_high_low);
+ 
+ 	ioapic_register_intr(irq, entry.vector, edge_level);
+@@ -2884,8 +2917,8 @@ int acpi_get_override_irq(int bus_irq, i
+ 		return -1;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mpc_irqtype == mp_INT &&
+-		    mp_irqs[i].mpc_srcbusirq == bus_irq)
++		if (mp_irqs[i].mp_irqtype == mp_INT &&
++		    mp_irqs[i].mp_srcbusirq == bus_irq)
+ 			break;
+ 	if (i >= mp_irq_entries)
+ 		return -1;
+@@ -2918,3 +2951,35 @@ static int __init parse_noapic(char *arg
+ 	return 0;
+ }
+ early_param("noapic", parse_noapic);
++
++#ifndef CONFIG_XEN
++void __init ioapic_init_mappings(void)
++{
++	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
++	int i;
++
++	for (i = 0; i < nr_ioapics; i++) {
++		if (smp_found_config) {
++			ioapic_phys = mp_ioapics[i].mp_apicaddr;
++			if (!ioapic_phys) {
++				printk(KERN_ERR
++				       "WARNING: bogus zero IO-APIC "
++				       "address found in MPTABLE, "
++				       "disabling IO/APIC support!\n");
++				smp_found_config = 0;
++				skip_ioapic_setup = 1;
++				goto fake_ioapic_page;
++			}
++		} else {
++fake_ioapic_page:
++			ioapic_phys = (unsigned long)
++				      alloc_bootmem_pages(PAGE_SIZE);
++			ioapic_phys = __pa(ioapic_phys);
++		}
++		set_fixmap_nocache(idx, ioapic_phys);
++		printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
++		       __fix_to_virt(idx), ioapic_phys);
++		idx++;
++	}
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -45,6 +45,7 @@
+ #include <asm/proto.h>
+ #include <asm/acpi.h>
+ #include <asm/dma.h>
++#include <asm/i8259.h>
+ #include <asm/nmi.h>
+ #include <asm/msidef.h>
+ #include <asm/hypertransport.h>
+@@ -63,10 +64,16 @@ struct irq_cfg {
+ };
+ 
+ /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+-struct irq_cfg irq_cfg[NR_IRQS] __read_mostly;
++static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly;
+ 
+ static int assign_irq_vector(int irq, cpumask_t mask);
+ 
++#ifndef CONFIG_XEN
++int first_system_vector = 0xfe;
++
++char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
++#endif
++
+ #define __apicdebuginit  __init
+ 
+ int sis_apic_bug; /* not actually supported, dummy for compile */
+@@ -89,14 +96,14 @@ unsigned long io_apic_irqs;
+ 
+ #define clear_IO_APIC() ((void)0)
+ #else
+-int timer_over_8254 __initdata = 1;
++int timer_through_8259 __initdata;
+ 
+ /* Where if anywhere is the i8259 connect in external int mode */
+ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+ #endif
+ 
+ static DEFINE_SPINLOCK(ioapic_lock);
+-DEFINE_SPINLOCK(vector_lock);
++static DEFINE_SPINLOCK(vector_lock);
+ 
+ /*
+  * # of IRQ routing registers
+@@ -104,15 +111,17 @@ DEFINE_SPINLOCK(vector_lock);
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
+ /* I/O APIC entries */
+-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
+ int nr_ioapics;
+ 
+ /* MP IRQ source entries */
+-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+ 
+ /* # of MP IRQ source entries */
+ int mp_irq_entries;
+ 
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++
+ /*
+  * Rough estimation of how many shared IRQs there are, can
+  * be changed anytime.
+@@ -141,7 +150,7 @@ struct io_apic {
+ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+ {
+ 	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+-		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
++		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+ }
+ #endif
+ 
+@@ -155,7 +164,7 @@ static inline unsigned int io_apic_read(
+ 	struct physdev_apic apic_op;
+ 	int ret;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+ 	apic_op.reg = reg;
+ 	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+ 	if (ret)
+@@ -173,7 +182,7 @@ static inline void io_apic_write(unsigne
+ #else
+ 	struct physdev_apic apic_op;
+ 
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+ 	apic_op.reg = reg;
+ 	apic_op.value = value;
+ 	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+@@ -209,7 +218,7 @@ static bool io_apic_level_ack_pending(un
+ 			break;
+ 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+ 		/* Is the remote IRR bit set? */
+-		if ((reg >> 14) & 1) {
++		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+ 			spin_unlock_irqrestore(&ioapic_lock, flags);
+ 			return true;
+ 		}
+@@ -308,7 +317,7 @@ static void __target_IO_APIC_irq(unsigne
+ 			break;
+ 		io_apic_write(apic, 0x11 + pin*2, dest);
+ 		reg = io_apic_read(apic, 0x10 + pin*2);
+-		reg &= ~0x000000ff;
++		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+ 		reg |= vector;
+ 		io_apic_modify(apic, reg);
+ 		if (!entry->next)
+@@ -372,6 +381,26 @@ static void add_pin_to_irq(unsigned int 
+ }
+ 
+ #ifndef CONFIG_XEN
++/*
++ * Reroute an IRQ to a different pin.
++ */
++static void __init replace_pin_at_irq(unsigned int irq,
++				      int oldapic, int oldpin,
++				      int newapic, int newpin)
++{
++	struct irq_pin_list *entry = irq_2_pin + irq;
++
++	while (1) {
++		if (entry->apic == oldapic && entry->pin == oldpin) {
++			entry->apic = newapic;
++			entry->pin = newpin;
++		}
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++}
++
+ #define __DO_ACTION(R, ACTION, FINAL)					\
+ 									\
+ {									\
+@@ -399,10 +428,11 @@ static void add_pin_to_irq(unsigned int 
+ 	static void name##_IO_APIC_irq (unsigned int irq)		\
+ 	__DO_ACTION(R, ACTION, FINAL)
+ 
+-DO_ACTION( __mask,             0, |= 0x00010000, io_apic_sync(entry->apic) )
+-						/* mask = 1 */
+-DO_ACTION( __unmask,           0, &= 0xfffeffff, )
+-						/* mask = 0 */
++/* mask = 1 */
++DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
++
++/* mask = 0 */
++DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
+ 
+ static void mask_IO_APIC_irq (unsigned int irq)
+ {
+@@ -465,22 +495,6 @@ static int __init disable_timer_pin_setu
+ }
+ __setup("disable_timer_pin_1", disable_timer_pin_setup);
+ 
+-#ifndef CONFIG_XEN
+-static int __init setup_disable_8254_timer(char *s)
+-{
+-	timer_over_8254 = -1;
+-	return 1;
+-}
+-static int __init setup_enable_8254_timer(char *s)
+-{
+-	timer_over_8254 = 2;
+-	return 1;
+-}
+-
+-__setup("disable_8254_timer", setup_disable_8254_timer);
+-__setup("enable_8254_timer", setup_enable_8254_timer);
+-#endif /* !CONFIG_XEN */
+-
+ 
+ /*
+  * Find the IRQ entry number of a certain pin.
+@@ -490,10 +504,10 @@ static int find_irq_entry(int apic, int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mpc_irqtype == type &&
+-		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
+-		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
+-		    mp_irqs[i].mpc_dstirq == pin)
++		if (mp_irqs[i].mp_irqtype == type &&
++		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
++		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].mp_dstirq == pin)
+ 			return i;
+ 
+ 	return -1;
+@@ -508,13 +522,13 @@ static int __init find_isa_irq_pin(int i
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mpc_irqtype == type) &&
+-		    (mp_irqs[i].mpc_srcbusirq == irq))
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
+ 
+-			return mp_irqs[i].mpc_dstirq;
++			return mp_irqs[i].mp_dstirq;
+ 	}
+ 	return -1;
+ }
+@@ -524,17 +538,17 @@ static int __init find_isa_irq_apic(int 
+ 	int i;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mpc_irqtype == type) &&
+-		    (mp_irqs[i].mpc_srcbusirq == irq))
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
+ 			break;
+ 	}
+ 	if (i < mp_irq_entries) {
+ 		int apic;
+ 		for(apic = 0; apic < nr_ioapics; apic++) {
+-			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
+ 				return apic;
+ 		}
+ 	}
+@@ -555,28 +569,28 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 
+ 	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+ 		bus, slot, pin);
+-	if (mp_bus_id_to_pci_bus[bus] == -1) {
++	if (test_bit(bus, mp_bus_not_pci)) {
+ 		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+ 		return -1;
+ 	}
+ 	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mpc_srcbus;
++		int lbus = mp_irqs[i].mp_srcbus;
+ 
+ 		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
+-			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
++			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
+ 				break;
+ 
+ 		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].mpc_irqtype &&
++		    !mp_irqs[i].mp_irqtype &&
+ 		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
++		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
+ 
+ 			if (!(apic || IO_APIC_IRQ(irq)))
+ 				continue;
+ 
+-			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
++			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
+ 				return irq;
+ 			/*
+ 			 * Use the first all-but-pin matching entry as a
+@@ -604,13 +618,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 
+ static int MPBIOS_polarity(int idx)
+ {
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 	int polarity;
+ 
+ 	/*
+ 	 * Determine IRQ line polarity (high active or low active):
+ 	 */
+-	switch (mp_irqs[idx].mpc_irqflag & 3)
++	switch (mp_irqs[idx].mp_irqflag & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent polarity */
+ 			if (test_bit(bus, mp_bus_not_pci))
+@@ -646,13 +660,13 @@ static int MPBIOS_polarity(int idx)
+ 
+ static int MPBIOS_trigger(int idx)
+ {
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 	int trigger;
+ 
+ 	/*
+ 	 * Determine IRQ trigger mode (edge or level sensitive):
+ 	 */
+-	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
++	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent */
+ 			if (test_bit(bus, mp_bus_not_pci))
+@@ -699,16 +713,16 @@ static inline int irq_trigger(int idx)
+ static int pin_2_irq(int idx, int apic, int pin)
+ {
+ 	int irq, i;
+-	int bus = mp_irqs[idx].mpc_srcbus;
++	int bus = mp_irqs[idx].mp_srcbus;
+ 
+ 	/*
+ 	 * Debugging check, we are in big trouble if this message pops up!
+ 	 */
+-	if (mp_irqs[idx].mpc_dstirq != pin)
++	if (mp_irqs[idx].mp_dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+ 	if (test_bit(bus, mp_bus_not_pci)) {
+-		irq = mp_irqs[idx].mpc_srcbusirq;
++		irq = mp_irqs[idx].mp_srcbusirq;
+ 	} else {
+ 		/*
+ 		 * PCI IRQs are mapped in order
+@@ -722,6 +736,19 @@ static int pin_2_irq(int idx, int apic, 
+ 	return irq;
+ }
+ 
++void lock_vector_lock(void)
++{
++	/* Used to the online set of cpus does not change
++	 * during assign_irq_vector.
++	 */
++	spin_lock(&vector_lock);
++}
++
++void unlock_vector_lock(void)
++{
++	spin_unlock(&vector_lock);
++}
++
+ static int __assign_irq_vector(int irq, cpumask_t mask)
+ {
+ 	struct physdev_irq irq_op;
+@@ -773,7 +800,7 @@ static void __clear_irq_vector(int irq)
+ 
+ 	vector = cfg->vector;
+ 	cpus_and(mask, cfg->domain, cpu_online_map);
+-	for_each_cpu_mask(cpu, mask)
++	for_each_cpu_mask_nr(cpu, mask)
+ 		per_cpu(vector_irq, cpu)[vector] = -1;
+ 
+ 	cfg->vector = 0;
+@@ -842,7 +869,7 @@ static void setup_IO_APIC_irq(int apic, 
+ 	apic_printk(APIC_VERBOSE,KERN_DEBUG
+ 		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+ 		    "IRQ %d Mode:%i Active:%i)\n",
+-		    apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,
++		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
+ 		    irq, trigger, polarity);
+ 
+ 	/*
+@@ -883,10 +910,10 @@ static void __init setup_IO_APIC_irqs(vo
+ 		idx = find_irq_entry(apic,pin,mp_INT);
+ 		if (idx == -1) {
+ 			if (first_notcon) {
+-				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
++				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
+ 				first_notcon = 0;
+ 			} else
+-				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
++				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
+ 			continue;
+ 		}
+ 		if (!first_notcon) {
+@@ -908,26 +935,21 @@ static void __init setup_IO_APIC_irqs(vo
+ 
+ #ifndef CONFIG_XEN
+ /*
+- * Set up the 8259A-master output pin as broadcast to all
+- * CPUs.
++ * Set up the timer pin, possibly with the 8259A-master behind.
+  */
+-static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
++static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
++					int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+ 
+ 	memset(&entry, 0, sizeof(entry));
+ 
+-	disable_8259A_irq(0);
+-
+-	/* mask LVT0 */
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+-
+ 	/*
+ 	 * We use logical delivery to get the timer IRQ
+ 	 * to the first CPU.
+ 	 */
+ 	entry.dest_mode = INT_DEST_MODE;
+-	entry.mask = 0;					/* unmask IRQ now */
++	entry.mask = 1;					/* mask IRQ now */
+ 	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.polarity = 0;
+@@ -936,7 +958,7 @@ static void __init setup_ExtINT_IRQ0_pin
+ 
+ 	/*
+ 	 * The timer IRQ doesn't have to know that behind the
+-	 * scene we have a 8259A-master in AEOI mode ...
++	 * scene we may have a 8259A-master in AEOI mode ...
+ 	 */
+ 	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+ 
+@@ -944,8 +966,6 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+ 	ioapic_write_entry(apic, pin, entry);
+-
+-	enable_8259A_irq(0);
+ }
+ 
+ void __apicdebuginit print_IO_APIC(void)
+@@ -962,7 +982,7 @@ void __apicdebuginit print_IO_APIC(void)
+ 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+ 	for (i = 0; i < nr_ioapics; i++)
+ 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+-		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
++		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
+ 
+ 	/*
+ 	 * We are a bit conservative about what we expect.  We have to
+@@ -980,7 +1000,7 @@ void __apicdebuginit print_IO_APIC(void)
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	printk("\n");
+-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
+ 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+ 
+@@ -1072,6 +1092,7 @@ void __apicdebuginit print_local_APIC(vo
+ 
+ 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
++	v = apic_read(APIC_ID);
+ 	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+@@ -1141,7 +1162,7 @@ void __apicdebuginit print_local_APIC(vo
+ 
+ void print_all_local_APICs (void)
+ {
+-	on_each_cpu(print_local_APIC, NULL, 1, 1);
++	on_each_cpu(print_local_APIC, NULL, 1);
+ }
+ 
+ void __apicdebuginit print_PIC(void)
+@@ -1175,6 +1196,8 @@ void __apicdebuginit print_PIC(void)
+ 	v = inb(0x4d1) << 8 | inb(0x4d0);
+ 	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+ }
++#else
++void __apicdebuginit print_IO_APIC(void) {}
+ #endif /* !CONFIG_XEN */
+ 
+ void __init enable_IO_APIC(void)
+@@ -1359,12 +1382,10 @@ static unsigned int startup_ioapic_irq(u
+ static int ioapic_retrigger_irq(unsigned int irq)
+ {
+ 	struct irq_cfg *cfg = &irq_cfg[irq];
+-	cpumask_t mask;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	mask = cpumask_of_cpu(first_cpu(cfg->domain));
+-	send_IPI_mask(mask, cfg->vector);
++	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return 1;
+@@ -1545,7 +1566,7 @@ static inline void init_IO_APIC_traps(vo
+ }
+ 
+ #ifndef CONFIG_XEN
+-static void enable_lapic_irq (unsigned int irq)
++static void unmask_lapic_irq(unsigned int irq)
+ {
+ 	unsigned long v;
+ 
+@@ -1553,7 +1574,7 @@ static void enable_lapic_irq (unsigned i
+ 	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+ }
+ 
+-static void disable_lapic_irq (unsigned int irq)
++static void mask_lapic_irq(unsigned int irq)
+ {
+ 	unsigned long v;
+ 
+@@ -1566,19 +1587,20 @@ static void ack_lapic_irq (unsigned int 
+ 	ack_APIC_irq();
+ }
+ 
+-static void end_lapic_irq (unsigned int i) { /* nothing */ }
+-
+-static struct hw_interrupt_type lapic_irq_type __read_mostly = {
+-	.name = "local-APIC",
+-	.typename = "local-APIC-edge",
+-	.startup = NULL, /* startup_irq() not used for IRQ0 */
+-	.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
+-	.enable = enable_lapic_irq,
+-	.disable = disable_lapic_irq,
+-	.ack = ack_lapic_irq,
+-	.end = end_lapic_irq,
++static struct irq_chip lapic_chip __read_mostly = {
++	.name		= "local-APIC",
++	.mask		= mask_lapic_irq,
++	.unmask		= unmask_lapic_irq,
++	.ack		= ack_lapic_irq,
+ };
+ 
++static void lapic_register_intr(int irq)
++{
++	irq_desc[irq].status &= ~IRQ_LEVEL;
++	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
++				      "edge");
++}
++
+ static void __init setup_nmi(void)
+ {
+ 	/*
+@@ -1664,6 +1686,7 @@ static inline void __init check_timer(vo
+ 	struct irq_cfg *cfg = irq_cfg + 0;
+ 	int apic1, pin1, apic2, pin2;
+ 	unsigned long flags;
++	int no_pin1 = 0;
+ 
+ 	local_irq_save(flags);
+ 
+@@ -1674,34 +1697,48 @@ static inline void __init check_timer(vo
+ 	assign_irq_vector(0, TARGET_CPUS);
+ 
+ 	/*
+-	 * Subtle, code in do_timer_interrupt() expects an AEOI
+-	 * mode for the 8259A whenever interrupts are routed
+-	 * through I/O APICs.  Also IRQ0 has to be enabled in
+-	 * the 8259A which implies the virtual wire has to be
+-	 * disabled in the local APIC.
++	 * As IRQ0 is to be enabled in the 8259A, the virtual
++	 * wire has to be disabled in the local APIC.
+ 	 */
+ 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ 	init_8259A(1);
+-	if (timer_over_8254 > 0)
+-		enable_8259A_irq(0);
+ 
+ 	pin1  = find_isa_irq_pin(0, mp_INT);
+ 	apic1 = find_isa_irq_apic(0, mp_INT);
+ 	pin2  = ioapic_i8259.pin;
+ 	apic2 = ioapic_i8259.apic;
+ 
+-	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+-		cfg->vector, apic1, pin1, apic2, pin2);
++	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
++		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
++		    cfg->vector, apic1, pin1, apic2, pin2);
++
++	/*
++	 * Some BIOS writers are clueless and report the ExtINTA
++	 * I/O APIC input from the cascaded 8259A as the timer
++	 * interrupt input.  So just in case, if only one pin
++	 * was found above, try it both directly and through the
++	 * 8259A.
++	 */
++	if (pin1 == -1) {
++		pin1 = pin2;
++		apic1 = apic2;
++		no_pin1 = 1;
++	} else if (pin2 == -1) {
++		pin2 = pin1;
++		apic2 = apic1;
++	}
+ 
+ 	if (pin1 != -1) {
+ 		/*
+ 		 * Ok, does IRQ0 through the IOAPIC work?
+ 		 */
++		if (no_pin1) {
++			add_pin_to_irq(0, apic1, pin1);
++			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
++		}
+ 		unmask_IO_APIC_irq(0);
+ 		if (!no_timer_check && timer_irq_works()) {
+-			nmi_watchdog_default();
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+-				disable_8259A_irq(0);
+ 				setup_nmi();
+ 				enable_8259A_irq(0);
+ 			}
+@@ -1710,54 +1747,62 @@ static inline void __init check_timer(vo
+ 			goto out;
+ 		}
+ 		clear_IO_APIC_pin(apic1, pin1);
+-		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
+-				"connected to IO-APIC\n");
+-	}
+-
+-	apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
+-				"through the 8259A ... ");
+-	if (pin2 != -1) {
+-		apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
+-			apic2, pin2);
++		if (!no_pin1)
++			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
++				    "8254 timer not connected to IO-APIC\n");
++
++		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
++			    "(IRQ0) through the 8259A ...\n");
++		apic_printk(APIC_QUIET, KERN_INFO
++			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+ 		/*
+ 		 * legacy devices should be connected to IO APIC #0
+ 		 */
+-		setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
++		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
++		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
++		unmask_IO_APIC_irq(0);
++		enable_8259A_irq(0);
+ 		if (timer_irq_works()) {
+-			apic_printk(APIC_VERBOSE," works.\n");
+-			nmi_watchdog_default();
++			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
++			timer_through_8259 = 1;
+ 			if (nmi_watchdog == NMI_IO_APIC) {
++				disable_8259A_irq(0);
+ 				setup_nmi();
++				enable_8259A_irq(0);
+ 			}
+ 			goto out;
+ 		}
+ 		/*
+ 		 * Cleanup, just in case ...
+ 		 */
++		disable_8259A_irq(0);
+ 		clear_IO_APIC_pin(apic2, pin2);
++		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+ 	}
+-	apic_printk(APIC_VERBOSE," failed.\n");
+ 
+ 	if (nmi_watchdog == NMI_IO_APIC) {
+-		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
+-		nmi_watchdog = 0;
++		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
++			    "through the IO-APIC - disabling NMI Watchdog!\n");
++		nmi_watchdog = NMI_NONE;
+ 	}
+ 
+-	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as Virtual Wire IRQ...\n");
+ 
+-	disable_8259A_irq(0);
+-	irq_desc[0].chip = &lapic_irq_type;
++	lapic_register_intr(0);
+ 	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+ 	if (timer_irq_works()) {
+-		apic_printk(APIC_VERBOSE," works.\n");
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
++	disable_8259A_irq(0);
+ 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+-	apic_printk(APIC_VERBOSE," failed.\n");
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+ 
+-	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as ExtINT IRQ...\n");
+ 
+ 	init_8259A(0);
+ 	make_8259A_irq(0);
+@@ -1766,11 +1811,12 @@ static inline void __init check_timer(vo
+ 	unlock_ExtINT_logic();
+ 
+ 	if (timer_irq_works()) {
+-		apic_printk(APIC_VERBOSE," works.\n");
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+ 		goto out;
+ 	}
+-	apic_printk(APIC_VERBOSE," failed :(.\n");
+-	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
++	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
++		"report.  Then try booting with the 'noapic' option.\n");
+ out:
+ 	local_irq_restore(flags);
+ }
+@@ -1788,10 +1834,21 @@ __setup("no_timer_check", notimercheck);
+ 
+ /*
+  *
+- * IRQs that are handled by the PIC in the MPS IOAPIC case.
+- * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
+- *   Linux doesn't really care, as it's not actually used
+- *   for any interrupt handling anyway.
++ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
++ * to devices.  However there may be an I/O APIC pin available for
++ * this interrupt regardless.  The pin may be left unconnected, but
++ * typically it will be reused as an ExtINT cascade interrupt for
++ * the master 8259A.  In the MPS case such a pin will normally be
++ * reported as an ExtINT interrupt in the MP table.  With ACPI
++ * there is no provision for ExtINT interrupts, and in the absence
++ * of an override it would be treated as an ordinary ISA I/O APIC
++ * interrupt, that is edge-triggered and unmasked by default.  We
++ * used to do this, but it caused problems on some systems because
++ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
++ * the same ExtINT cascade interrupt to drive the local APIC of the
++ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
++ * the I/O APIC in all cases now.  No actual device should request
++ * it anyway.  --macro
+  */
+ #define PIC_IRQS	(1<<2)
+ 
+@@ -1799,10 +1856,7 @@ void __init setup_IO_APIC(void)
+ {
+ 	enable_IO_APIC();
+ 
+-	if (acpi_ioapic)
+-		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
+-	else
+-		io_apic_irqs = ~PIC_IRQS;
++	io_apic_irqs = ~PIC_IRQS;
+ 
+ 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ 
+@@ -1851,8 +1905,8 @@ static int ioapic_resume(struct sys_devi
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	reg_00.raw = io_apic_read(dev->id, 0);
+-	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+-		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
++	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
+ 		io_apic_write(dev->id, 0, reg_00.raw);
+ 	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+@@ -2254,8 +2308,8 @@ int acpi_get_override_irq(int bus_irq, i
+ 		return -1;
+ 
+ 	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mpc_irqtype == mp_INT &&
+-		    mp_irqs[i].mpc_srcbusirq == bus_irq)
++		if (mp_irqs[i].mp_irqtype == mp_INT &&
++		    mp_irqs[i].mp_srcbusirq == bus_irq)
+ 			break;
+ 	if (i >= mp_irq_entries)
+ 		return -1;
+@@ -2349,7 +2403,7 @@ void __init ioapic_init_mappings(void)
+ 	ioapic_res = ioapic_setup_resources();
+ 	for (i = 0; i < nr_ioapics; i++) {
+ 		if (smp_found_config) {
+-			ioapic_phys = mp_ioapics[i].mpc_apicaddr;
++			ioapic_phys = mp_ioapics[i].mp_apicaddr;
+ 		} else {
+ 			ioapic_phys = (unsigned long)
+ 				alloc_bootmem_pages(PAGE_SIZE);
+--- head-2010-01-18.orig/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -8,7 +8,6 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/cache.h>
+-#include <linux/interrupt.h>
+ #include <linux/cpu.h>
+ #include <linux/module.h>
+ 
+@@ -85,7 +84,7 @@ void __send_IPI_shortcut(unsigned int sh
+ 	/*
+ 	 * Send the IPI. The write to APIC_ICR fires this off.
+ 	 */
+-	apic_write_around(APIC_ICR, cfg);
++	apic_write(APIC_ICR, cfg);
+ #else
+ 	int cpu;
+ 
+@@ -132,7 +131,7 @@ static inline void __send_IPI_dest_field
+ 	 * prepare target chip field
+ 	 */
+ 	cfg = __prepare_ICR2(mask);
+-	apic_write_around(APIC_ICR2, cfg);
++	apic_write(APIC_ICR2, cfg);
+ 
+ 	/*
+ 	 * program the ICR
+@@ -142,7 +141,7 @@ static inline void __send_IPI_dest_field
+ 	/*
+ 	 * Send the IPI. The write to APIC_ICR fires this off.
+ 	 */
+-	apic_write_around(APIC_ICR, cfg);
++	apic_write(APIC_ICR, cfg);
+ }
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -48,6 +48,29 @@ void ack_bad_irq(unsigned int irq)
+ #endif
+ }
+ 
++#ifdef CONFIG_DEBUG_STACKOVERFLOW
++/* Debugging check for stack overflow: is there less than 1KB free? */
++static int check_stack_overflow(void)
++{
++	long sp;
++
++	__asm__ __volatile__("andl %%esp,%0" :
++			     "=r" (sp) : "0" (THREAD_SIZE - 1));
++
++	return sp < (sizeof(struct thread_info) + STACK_WARN);
++}
++
++static void print_stack_overflow(void)
++{
++	printk(KERN_WARNING "low stack detected by irq handler\n");
++	dump_stack();
++}
++
++#else
++static inline int check_stack_overflow(void) { return 0; }
++static inline void print_stack_overflow(void) { }
++#endif
++
+ #ifdef CONFIG_4KSTACKS
+ /*
+  * per-CPU IRQ handling contexts (thread information and stack)
+@@ -59,48 +82,26 @@ union irq_ctx {
+ 
+ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+ static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
+-#endif
+-
+-/*
+- * do_IRQ handles all normal device IRQ's (the special
+- * SMP cross-CPU interrupts have their own specific
+- * handlers).
+- */
+-unsigned int do_IRQ(struct pt_regs *regs)
+-{	
+-	struct pt_regs *old_regs;
+-	/* high bit used in ret_from_ code */
+-	int irq = ~regs->orig_ax;
+-	struct irq_desc *desc = irq_desc + irq;
+-#ifdef CONFIG_4KSTACKS
+-	union irq_ctx *curctx, *irqctx;
+-	u32 *isp;
+-#endif
+ 
+-	if (unlikely((unsigned)irq >= NR_IRQS)) {
+-		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+-					__func__, irq);
+-		BUG();
+-	}
++static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
++static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
+ 
+-	old_regs = set_irq_regs(regs);
+-	/*irq_enter();*/
+-#ifdef CONFIG_DEBUG_STACKOVERFLOW
+-	/* Debugging check for stack overflow: is there less than 1KB free? */
+-	{
+-		long sp;
+-
+-		__asm__ __volatile__("andl %%esp,%0" :
+-					"=r" (sp) : "0" (THREAD_SIZE - 1));
+-		if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+-			printk("do_IRQ: stack overflow: %ld\n",
+-				sp - sizeof(struct thread_info));
+-			dump_stack();
+-		}
+-	}
+-#endif
++static void call_on_stack(void *func, void *stack)
++{
++	asm volatile("xchgl	%%ebx,%%esp	\n"
++		     "call	*%%edi		\n"
++		     "movl	%%ebx,%%esp	\n"
++		     : "=b" (stack)
++		     : "0" (stack),
++		       "D"(func)
++		     : "memory", "cc", "edx", "ecx", "eax");
++}
+ 
+-#ifdef CONFIG_4KSTACKS
++static inline int
++execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
++{
++	union irq_ctx *curctx, *irqctx;
++	u32 *isp, arg1, arg2;
+ 
+ 	curctx = (union irq_ctx *) current_thread_info();
+ 	irqctx = hardirq_ctx[smp_processor_id()];
+@@ -111,52 +112,39 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 	 * handler) we can't do that and just have to keep using the
+ 	 * current stack (which is the irq stack already after all)
+ 	 */
+-	if (curctx != irqctx) {
+-		int arg1, arg2, bx;
+-
+-		/* build the stack frame on the IRQ stack */
+-		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
+-		irqctx->tinfo.task = curctx->tinfo.task;
+-		irqctx->tinfo.previous_esp = current_stack_pointer;
++	if (unlikely(curctx == irqctx))
++		return 0;
+ 
+-		/*
+-		 * Copy the softirq bits in preempt_count so that the
+-		 * softirq checks work in the hardirq context.
+-		 */
+-		irqctx->tinfo.preempt_count =
+-			(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+-			(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+-
+-		asm volatile(
+-			"       xchgl  %%ebx,%%esp    \n"
+-			"       call   *%%edi         \n"
+-			"       movl   %%ebx,%%esp    \n"
+-			: "=a" (arg1), "=d" (arg2), "=b" (bx)
+-			:  "0" (irq),   "1" (desc),  "2" (isp),
+-			   "D" (desc->handle_irq)
+-			: "memory", "cc", "ecx"
+-		);
+-	} else
+-#endif
+-		desc->handle_irq(irq, desc);
++	/* build the stack frame on the IRQ stack */
++	isp = (u32 *) ((char*)irqctx + sizeof(*irqctx));
++	irqctx->tinfo.task = curctx->tinfo.task;
++	irqctx->tinfo.previous_esp = current_stack_pointer;
+ 
+-	/*irq_exit();*/
+-	set_irq_regs(old_regs);
++	/*
++	 * Copy the softirq bits in preempt_count so that the
++	 * softirq checks work in the hardirq context.
++	 */
++	irqctx->tinfo.preempt_count =
++		(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
++		(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
++
++	if (unlikely(overflow))
++		call_on_stack(print_stack_overflow, isp);
++
++	asm volatile("xchgl	%%ebx,%%esp	\n"
++		     "call	*%%edi		\n"
++		     "movl	%%ebx,%%esp	\n"
++		     : "=a" (arg1), "=d" (arg2), "=b" (isp)
++		     :  "0" (irq),   "1" (desc),  "2" (isp),
++			"D" (desc->handle_irq)
++		     : "memory", "cc", "ecx");
+ 	return 1;
+ }
+ 
+-#ifdef CONFIG_4KSTACKS
+-
+-static char softirq_stack[NR_CPUS * THREAD_SIZE]
+-		__attribute__((__section__(".bss.page_aligned")));
+-
+-static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+-		__attribute__((__section__(".bss.page_aligned")));
+-
+ /*
+  * allocate per-cpu stacks for hardirq and for softirq processing
+  */
+-void irq_ctx_init(int cpu)
++void __cpuinit irq_ctx_init(int cpu)
+ {
+ 	union irq_ctx *irqctx;
+ 
+@@ -164,25 +152,25 @@ void irq_ctx_init(int cpu)
+ 		return;
+ 
+ 	irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
+-	irqctx->tinfo.task              = NULL;
+-	irqctx->tinfo.exec_domain       = NULL;
+-	irqctx->tinfo.cpu               = cpu;
+-	irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
+-	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
++	irqctx->tinfo.task		= NULL;
++	irqctx->tinfo.exec_domain	= NULL;
++	irqctx->tinfo.cpu		= cpu;
++	irqctx->tinfo.preempt_count	= HARDIRQ_OFFSET;
++	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+ 
+ 	hardirq_ctx[cpu] = irqctx;
+ 
+ 	irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
+-	irqctx->tinfo.task              = NULL;
+-	irqctx->tinfo.exec_domain       = NULL;
+-	irqctx->tinfo.cpu               = cpu;
+-	irqctx->tinfo.preempt_count     = 0;
+-	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
++	irqctx->tinfo.task		= NULL;
++	irqctx->tinfo.exec_domain	= NULL;
++	irqctx->tinfo.cpu		= cpu;
++	irqctx->tinfo.preempt_count	= 0;
++	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+ 
+ 	softirq_ctx[cpu] = irqctx;
+ 
+-	printk("CPU %u irqstacks, hard=%p soft=%p\n",
+-		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
++	printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
++	       cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
+ }
+ 
+ void irq_ctx_exit(int cpu)
+@@ -211,25 +199,56 @@ asmlinkage void do_softirq(void)
+ 		/* build the stack frame on the softirq stack */
+ 		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
+ 
+-		asm volatile(
+-			"       xchgl   %%ebx,%%esp     \n"
+-			"       call    __do_softirq    \n"
+-			"       movl    %%ebx,%%esp     \n"
+-			: "=b"(isp)
+-			: "0"(isp)
+-			: "memory", "cc", "edx", "ecx", "eax"
+-		);
++		call_on_stack(__do_softirq, isp);
+ 		/*
+ 		 * Shouldnt happen, we returned above if in_interrupt():
+-	 	 */
++		 */
+ 		WARN_ON_ONCE(softirq_count());
+ 	}
+ 
+ 	local_irq_restore(flags);
+ }
++
++#else
++static inline int
++execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
+ #endif
+ 
+ /*
++ * do_IRQ handles all normal device IRQ's (the special
++ * SMP cross-CPU interrupts have their own specific
++ * handlers).
++ */
++unsigned int do_IRQ(struct pt_regs *regs)
++{
++	struct pt_regs *old_regs;
++	/* high bit used in ret_from_ code */
++	int overflow, irq = ~regs->orig_ax;
++	struct irq_desc *desc = irq_desc + irq;
++
++	if (unlikely((unsigned)irq >= NR_IRQS)) {
++		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
++					__func__, irq);
++		BUG();
++	}
++
++	old_regs = set_irq_regs(regs);
++	/*irq_enter();*/
++
++	overflow = check_stack_overflow();
++
++	if (!execute_on_irq_stack(overflow, desc, irq)) {
++		if (unlikely(overflow))
++			print_stack_overflow();
++		desc->handle_irq(irq, desc);
++	}
++
++	/*irq_exit();*/
++	set_irq_regs(old_regs);
++	return 1;
++}
++
++/*
+  * Interrupt statistics:
+  */
+ 
+@@ -337,6 +356,42 @@ skip:
+ 	return 0;
+ }
+ 
++/*
++ * /proc/stat helpers
++ */
++u64 arch_irq_stat_cpu(unsigned int cpu)
++{
++	u64 sum = nmi_count(cpu);
++
++#ifdef CONFIG_X86_LOCAL_APIC
++	sum += per_cpu(irq_stat, cpu).apic_timer_irqs;
++#endif
++#ifdef CONFIG_SMP
++	sum += per_cpu(irq_stat, cpu).irq_resched_count;
++	sum += per_cpu(irq_stat, cpu).irq_call_count;
++#ifndef CONFIG_XEN
++	sum += per_cpu(irq_stat, cpu).irq_tlb_count;
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++	sum += per_cpu(irq_stat, cpu).irq_thermal_count;
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++	sum += per_cpu(irq_stat, cpu).irq_spurious_count;
++#endif
++	return sum;
++}
++
++u64 arch_irq_stat(void)
++{
++	u64 sum = atomic_read(&irq_err_count);
++
++#ifdef CONFIG_X86_IO_APIC
++	sum += atomic_read(&irq_mis_count);
++#endif
++	return sum;
++}
++
+ #ifdef CONFIG_HOTPLUG_CPU
+ 
+ void fixup_irqs(cpumask_t map)
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -163,6 +163,34 @@ skip:
+ }
+ 
+ /*
++ * /proc/stat helpers
++ */
++u64 arch_irq_stat_cpu(unsigned int cpu)
++{
++	u64 sum = cpu_pda(cpu)->__nmi_count;
++
++	sum += cpu_pda(cpu)->apic_timer_irqs;
++#ifdef CONFIG_SMP
++	sum += cpu_pda(cpu)->irq_resched_count;
++	sum += cpu_pda(cpu)->irq_call_count;
++#ifndef CONFIG_XEN
++	sum += cpu_pda(cpu)->irq_tlb_count;
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++	sum += cpu_pda(cpu)->irq_thermal_count;
++	sum += cpu_pda(cpu)->irq_threshold_count;
++#endif
++	sum += cpu_pda(cpu)->irq_spurious_count;
++	return sum;
++}
++
++u64 arch_irq_stat(void)
++{
++	return atomic_read(&irq_err_count);
++}
++
++/*
+  * do_IRQ handles all normal device IRQ's (the special
+  * SMP cross-CPU interrupts have their own specific
+  * handlers).
+--- head-2010-01-18.orig/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -20,9 +20,9 @@
+ #include <asm/mmu_context.h>
+ 
+ #ifdef CONFIG_SMP
+-static void flush_ldt(void *null)
++static void flush_ldt(void *current_mm)
+ {
+-	if (current->active_mm)
++	if (current->active_mm == current_mm)
+ 		load_LDT(&current->active_mm->context);
+ }
+ #endif
+@@ -62,8 +62,6 @@ static int alloc_ldt(mm_context_t *pc, i
+ 
+ 	if (reload) {
+ #ifdef CONFIG_SMP
+-		cpumask_t mask;
+-
+ 		preempt_disable();
+ #endif
+ 		make_pages_readonly(newldt,
+@@ -71,9 +69,9 @@ static int alloc_ldt(mm_context_t *pc, i
+ 				    XENFEAT_writable_descriptor_tables);
+ 		load_LDT(pc);
+ #ifdef CONFIG_SMP
+-		mask = cpumask_of_cpu(smp_processor_id());
+-		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
+-			smp_call_function(flush_ldt, NULL, 1, 1);
++		if (!cpus_equal(current->mm->cpu_vm_mask,
++				cpumask_of_cpu(smp_processor_id())))
++			smp_call_function(flush_ldt, current->mm, 1);
+ 		preempt_enable();
+ #endif
+ 	}
+--- head-2010-01-18.orig/arch/x86/kernel/machine_kexec_32.c	2009-12-04 10:44:46.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/machine_kexec_32.c	2009-11-06 10:51:42.000000000 +0100
+@@ -130,6 +130,8 @@ void machine_kexec_setup_load_arg(xen_ke
+ 	xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
+ 	xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
+ 
++	if (image->type == KEXEC_TYPE_DEFAULT)
++		xki->page_list[PA_SWAP_PAGE] = page_to_phys(image->swap_page);
+ }
+ 
+ int __init machine_kexec_setup_resources(struct resource *hypervisor,
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -5,13 +5,14 @@
+  *		      2006	Shaohua Li <shaohua.li@intel.com>
+  *
+  *	This driver allows to upgrade microcode on Intel processors
+- *	belonging to IA-32 family - PentiumPro, Pentium II, 
++ *	belonging to IA-32 family - PentiumPro, Pentium II,
+  *	Pentium III, Xeon, Pentium 4, etc.
+  *
+- *	Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
+- *	Order Number 245472 or free download from:
+- *		
+- *	http://developer.intel.com/design/pentium4/manuals/245472.htm
++ *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
++ *	Software Developer's Manual
++ *	Order Number 253668 or free download from:
++ *
++ *	http://developer.intel.com/design/pentium4/manuals/253668.htm
+  *
+  *	For more information, go to http://www.urbanmyth.org/microcode
+  *
+@@ -26,6 +27,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
++#include <linux/smp_lock.h>
+ #include <linux/cpumask.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+@@ -86,6 +88,7 @@ static int do_microcode_update (const vo
+ 
+ static int microcode_open (struct inode *unused1, struct file *unused2)
+ {
++	cycle_kernel_lock();
+ 	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+ }
+ 
+@@ -162,7 +165,7 @@ static int request_microcode(void)
+ 		c->x86, c->x86_model, c->x86_mask);
+ 	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+ 	if (error) {
+-		pr_debug("microcode: ucode data file %s load failed\n", name);
++		pr_debug("microcode: data file %s load failed\n", name);
+ 		return error;
+ 	}
+ 
+@@ -183,6 +186,9 @@ static int __init microcode_init (void)
+ {
+ 	int error;
+ 
++	printk(KERN_INFO
++		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
++
+ 	error = microcode_dev_init();
+ 	if (error)
+ 		return error;
+@@ -195,8 +201,6 @@ static int __init microcode_init (void)
+ 
+ 	request_microcode();
+ 
+-	printk(KERN_INFO 
+-		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -25,6 +25,9 @@
+ #include <asm/proto.h>
+ #include <asm/acpi.h>
+ #include <asm/bios_ebda.h>
++#include <asm/e820.h>
++#include <asm/trampoline.h>
++#include <asm/setup.h>
+ 
+ #include <mach_apic.h>
+ #ifdef CONFIG_X86_32
+@@ -32,27 +35,10 @@
+ #include <mach_mpparse.h>
+ #endif
+ 
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-/*
+- * Various Linux-internal data structures created from the
+- * MP-table.
+- */
+-#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+-int mp_bus_id_to_type[MAX_MP_BUSSES];
+-#endif
+-
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-int mp_bus_id_to_pci_bus[MAX_MP_BUSSES] = {[0 ... MAX_MP_BUSSES - 1] = -1 };
+-
+-static int mp_current_pci_id;
+-
+-int pic_mode;
+-
+-/*
+- * Intel MP BIOS table parsing routines:
+- */
++static void *_bus_to_virt(unsigned long ma)
++{
++	return is_ISA_range(ma, ma) ? isa_bus_to_virt(ma) : bus_to_virt(ma);
++}
+ 
+ /*
+  * Checksum an MP configuration block.
+@@ -68,19 +54,7 @@ static int __init mpf_checksum(unsigned 
+ 	return sum & 0xFF;
+ }
+ 
+-#ifdef CONFIG_X86_NUMAQ
+-/*
+- * Have to match translation table entries to main table entries by counter
+- * hence the mpc_record variable .... can't see a less disgusting way of
+- * doing this ....
+- */
+-
+-static int mpc_record;
+-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
+-    __cpuinitdata;
+-#endif
+-
+-static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
++static void __init MP_processor_info(struct mpc_config_processor *m)
+ {
+ #ifndef CONFIG_XEN
+ 	int apicid;
+@@ -90,11 +64,12 @@ static void __cpuinit MP_processor_info(
+ 		disabled_cpus++;
+ 		return;
+ 	}
+-#ifdef CONFIG_X86_NUMAQ
+-	apicid = mpc_apic_id(m, translation_table[mpc_record]);
+-#else
+-	apicid = m->mpc_apicid;
+-#endif
++
++	if (x86_quirks->mpc_apic_id)
++		apicid = x86_quirks->mpc_apic_id(m);
++	else
++		apicid = m->mpc_apicid;
++
+ 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+ 		bootup_cpu = " (Bootup-CPU)";
+ 		boot_cpu_physical_apicid = m->mpc_apicid;
+@@ -107,18 +82,17 @@ static void __cpuinit MP_processor_info(
+ #endif
+ }
+ 
++#ifdef CONFIG_X86_IO_APIC
+ static void __init MP_bus_info(struct mpc_config_bus *m)
+ {
+ 	char str[7];
+-
+ 	memcpy(str, m->mpc_bustype, 6);
+ 	str[6] = 0;
+ 
+-#ifdef CONFIG_X86_NUMAQ
+-	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+-#else
+-	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+-#endif
++	if (x86_quirks->mpc_oem_bus_info)
++		x86_quirks->mpc_oem_bus_info(m, str);
++	else
++		apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->mpc_busid, str);
+ 
+ #if MAX_MP_BUSSES < 256
+ 	if (m->mpc_busid >= MAX_MP_BUSSES) {
+@@ -135,12 +109,10 @@ static void __init MP_bus_info(struct mp
+ 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+ #endif
+ 	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
+-#ifdef CONFIG_X86_NUMAQ
+-		mpc_oem_pci_bus(m, translation_table[mpc_record]);
+-#endif
++		if (x86_quirks->mpc_oem_pci_bus)
++			x86_quirks->mpc_oem_pci_bus(m);
++
+ 		clear_bit(m->mpc_busid, mp_bus_not_pci);
+-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+-		mp_current_pci_id++;
+ #if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+ 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+ 	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
+@@ -151,6 +123,7 @@ static void __init MP_bus_info(struct mp
+ 	} else
+ 		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ }
++#endif
+ 
+ #ifdef CONFIG_X86_IO_APIC
+ 
+@@ -180,117 +153,111 @@ static void __init MP_ioapic_info(struct
+ 	if (bad_ioapic(m->mpc_apicaddr))
+ 		return;
+ 
+-	mp_ioapics[nr_ioapics] = *m;
++	mp_ioapics[nr_ioapics].mp_apicaddr = m->mpc_apicaddr;
++	mp_ioapics[nr_ioapics].mp_apicid = m->mpc_apicid;
++	mp_ioapics[nr_ioapics].mp_type = m->mpc_type;
++	mp_ioapics[nr_ioapics].mp_apicver = m->mpc_apicver;
++	mp_ioapics[nr_ioapics].mp_flags = m->mpc_flags;
+ 	nr_ioapics++;
+ }
+ 
+-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
++static void print_MP_intsrc_info(struct mpc_config_intsrc *m)
+ {
+-	mp_irqs[mp_irq_entries] = *m;
+-	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+ 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ 		m->mpc_irqtype, m->mpc_irqflag & 3,
+ 		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+ 		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+-		panic("Max # of irq sources exceeded!!\n");
+ }
+ 
+-#endif
+-
+-static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
++static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+ {
+-	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
+-		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-		m->mpc_irqtype, m->mpc_irqflag & 3,
+-		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
+-		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
++		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
++		mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
++		(mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
++		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+ }
+ 
+-#ifdef CONFIG_X86_NUMAQ
+-static void __init MP_translation_info(struct mpc_config_translation *m)
++static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
++				    struct mp_config_intsrc *mp_irq)
+ {
+-	printk(KERN_INFO
+-	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
+-	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
+-	       m->trans_local);
++	mp_irq->mp_dstapic = m->mpc_dstapic;
++	mp_irq->mp_type = m->mpc_type;
++	mp_irq->mp_irqtype = m->mpc_irqtype;
++	mp_irq->mp_irqflag = m->mpc_irqflag;
++	mp_irq->mp_srcbus = m->mpc_srcbus;
++	mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
++	mp_irq->mp_dstirq = m->mpc_dstirq;
++}
+ 
+-	if (mpc_record >= MAX_MPC_ENTRY)
+-		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+-	else
+-		translation_table[mpc_record] = m;	/* stash this for later */
+-	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+-		node_set_online(m->trans_quad);
++static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
++					struct mpc_config_intsrc *m)
++{
++	m->mpc_dstapic = mp_irq->mp_dstapic;
++	m->mpc_type = mp_irq->mp_type;
++	m->mpc_irqtype = mp_irq->mp_irqtype;
++	m->mpc_irqflag = mp_irq->mp_irqflag;
++	m->mpc_srcbus = mp_irq->mp_srcbus;
++	m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
++	m->mpc_dstirq = mp_irq->mp_dstirq;
+ }
+ 
+-/*
+- * Read/parse the MPC oem tables
+- */
++static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
++					struct mpc_config_intsrc *m)
++{
++	if (mp_irq->mp_dstapic != m->mpc_dstapic)
++		return 1;
++	if (mp_irq->mp_type != m->mpc_type)
++		return 2;
++	if (mp_irq->mp_irqtype != m->mpc_irqtype)
++		return 3;
++	if (mp_irq->mp_irqflag != m->mpc_irqflag)
++		return 4;
++	if (mp_irq->mp_srcbus != m->mpc_srcbus)
++		return 5;
++	if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
++		return 6;
++	if (mp_irq->mp_dstirq != m->mpc_dstirq)
++		return 7;
+ 
+-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
+-				    unsigned short oemsize)
++	return 0;
++}
++
++static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+ {
+-	int count = sizeof(*oemtable);	/* the header size */
+-	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
++	int i;
+ 
+-	mpc_record = 0;
+-	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
+-	       oemtable);
+-	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
+-		printk(KERN_WARNING
+-		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+-		       oemtable->oem_signature[0], oemtable->oem_signature[1],
+-		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
+-		return;
+-	}
+-	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
+-		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+-		return;
+-	}
+-	while (count < oemtable->oem_length) {
+-		switch (*oemptr) {
+-		case MP_TRANSLATION:
+-			{
+-				struct mpc_config_translation *m =
+-				    (struct mpc_config_translation *)oemptr;
+-				MP_translation_info(m);
+-				oemptr += sizeof(*m);
+-				count += sizeof(*m);
+-				++mpc_record;
+-				break;
+-			}
+-		default:
+-			{
+-				printk(KERN_WARNING
+-				       "Unrecognised OEM table entry type! - %d\n",
+-				       (int)*oemptr);
+-				return;
+-			}
+-		}
++	print_MP_intsrc_info(m);
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
++			return;
+ 	}
++
++	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!!\n");
+ }
+ 
+-static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
+-				 char *productid)
++#endif
++
++static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
+ {
+-	if (strncmp(oem, "IBM NUMA", 8))
+-		printk("Warning!  May not be a NUMA-Q system!\n");
+-	if (mpc->mpc_oemptr)
+-		smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
+-				 mpc->mpc_oemsize);
++	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
++		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++		m->mpc_irqtype, m->mpc_irqflag & 3,
++		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
++		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+ }
+-#endif /* CONFIG_X86_NUMAQ */
+ 
+ /*
+  * Read/parse the MPC
+  */
+ 
+-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
++				char *str)
+ {
+-	char str[16];
+-	char oem[10];
+-	int count = sizeof(*mpc);
+-	unsigned char *mpt = ((unsigned char *)mpc) + count;
+ 
+ 	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
+ 		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+@@ -313,19 +280,41 @@ static int __init smp_read_mpc(struct mp
+ 	}
+ 	memcpy(oem, mpc->mpc_oem, 8);
+ 	oem[8] = 0;
+-	printk(KERN_INFO "MPTABLE: OEM ID: %s ", oem);
++	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+ 
+ 	memcpy(str, mpc->mpc_productid, 12);
+ 	str[12] = 0;
+-	printk("Product ID: %s ", str);
+ 
+-#ifdef CONFIG_X86_32
+-	mps_oem_check(mpc, oem, str);
+-#endif
+-	printk(KERN_INFO "MPTABLE: Product ID: %s ", str);
++	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ 
+ 	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ 
++	return 1;
++}
++
++static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++{
++	char str[16];
++	char oem[10];
++
++	int count = sizeof(*mpc);
++	unsigned char *mpt = ((unsigned char *)mpc) + count;
++
++	if (!smp_check_mpc(mpc, oem, str))
++		return 0;
++
++#ifdef CONFIG_X86_32
++	/*
++	 * need to make sure summit and es7000's mps_oem_check is safe to be
++	 * called early via genericarch 's mps_oem_check
++	 */
++	if (early) {
++#ifdef CONFIG_X86_NUMAQ
++		numaq_mps_oem_check(mpc, oem, str);
++#endif
++	} else
++		mps_oem_check(mpc, oem, str);
++#endif
+ 	/* save the local APIC address, it might be non-default */
+ 	if (!acpi_lapic)
+ 		mp_lapic_addr = mpc->mpc_lapic;
+@@ -333,12 +322,17 @@ static int __init smp_read_mpc(struct mp
+ 	if (early)
+ 		return 1;
+ 
++	if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) {
++		struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
++		x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
++	}
++
+ 	/*
+ 	 *      Now process the configuration blocks.
+ 	 */
+-#ifdef CONFIG_X86_NUMAQ
+-	mpc_record = 0;
+-#endif
++	if (x86_quirks->mpc_record)
++		*x86_quirks->mpc_record = 0;
++
+ 	while (count < mpc->mpc_length) {
+ 		switch (*mpt) {
+ 		case MP_PROCESSOR:
+@@ -356,7 +350,9 @@ static int __init smp_read_mpc(struct mp
+ 			{
+ 				struct mpc_config_bus *m =
+ 				    (struct mpc_config_bus *)mpt;
++#ifdef CONFIG_X86_IO_APIC
+ 				MP_bus_info(m);
++#endif
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+ 				break;
+@@ -402,10 +398,14 @@ static int __init smp_read_mpc(struct mp
+ 			count = mpc->mpc_length;
+ 			break;
+ 		}
+-#ifdef CONFIG_X86_NUMAQ
+-		++mpc_record;
+-#endif
++		if (x86_quirks->mpc_record)
++			(*x86_quirks->mpc_record)++;
+ 	}
++
++#ifdef CONFIG_X86_GENERICARCH
++       generic_bigsmp_probe();
++#endif
++
+ 	setup_apic_routing();
+ 	if (!num_processors)
+ 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+@@ -431,7 +431,7 @@ static void __init construct_default_ioi
+ 	intsrc.mpc_type = MP_INTSRC;
+ 	intsrc.mpc_irqflag = 0;	/* conforming */
+ 	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++	intsrc.mpc_dstapic = mp_ioapics[0].mp_apicid;
+ 
+ 	intsrc.mpc_irqtype = mp_INT;
+ 
+@@ -492,40 +492,11 @@ static void __init construct_default_ioi
+ 	MP_intsrc_info(&intsrc);
+ }
+ 
+-#endif
+ 
+-static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++static void __init construct_ioapic_table(int mpc_default_type)
+ {
+-	struct mpc_config_processor processor;
+-	struct mpc_config_bus bus;
+-#ifdef CONFIG_X86_IO_APIC
+ 	struct mpc_config_ioapic ioapic;
+-#endif
+-	struct mpc_config_lintsrc lintsrc;
+-	int linttypes[2] = { mp_ExtINT, mp_NMI };
+-	int i;
+-
+-	/*
+-	 * local APIC has default address
+-	 */
+-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+-
+-	/*
+-	 * 2 CPUs, numbered 0 & 1.
+-	 */
+-	processor.mpc_type = MP_PROCESSOR;
+-	/* Either an integrated APIC or a discrete 82489DX. */
+-	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+-	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
+-	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
+-		MP_processor_info(&processor);
+-	}
++	struct mpc_config_bus bus;
+ 
+ 	bus.mpc_type = MP_BUS;
+ 	bus.mpc_busid = 0;
+@@ -554,7 +525,6 @@ static inline void __init construct_defa
+ 		MP_bus_info(&bus);
+ 	}
+ 
+-#ifdef CONFIG_X86_IO_APIC
+ 	ioapic.mpc_type = MP_IOAPIC;
+ 	ioapic.mpc_apicid = 2;
+ 	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+@@ -566,7 +536,42 @@ static inline void __init construct_defa
+ 	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+ 	 */
+ 	construct_default_ioirq_mptable(mpc_default_type);
++}
++#else
++static inline void __init construct_ioapic_table(int mpc_default_type) { }
+ #endif
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++	struct mpc_config_processor processor;
++	struct mpc_config_lintsrc lintsrc;
++	int linttypes[2] = { mp_ExtINT, mp_NMI };
++	int i;
++
++	/*
++	 * local APIC has default address
++	 */
++	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++	/*
++	 * 2 CPUs, numbered 0 & 1.
++	 */
++	processor.mpc_type = MP_PROCESSOR;
++	/* Either an integrated APIC or a discrete 82489DX. */
++	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_cpuflag = CPU_ENABLED;
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++	for (i = 0; i < 2; i++) {
++		processor.mpc_apicid = i;
++		MP_processor_info(&processor);
++	}
++
++	construct_ioapic_table(mpc_default_type);
++
+ 	lintsrc.mpc_type = MP_LINTSRC;
+ 	lintsrc.mpc_irqflag = 0;	/* conforming */
+ 	lintsrc.mpc_srcbusid = 0;
+@@ -584,10 +589,14 @@ static struct intel_mp_floating *mpf_fou
+ /*
+  * Scan the memory blocks for an SMP configuration block.
+  */
+-static void __init __get_smp_config(unsigned early)
++static void __init __get_smp_config(unsigned int early)
+ {
+ 	struct intel_mp_floating *mpf = mpf_found;
+ 
++	if (x86_quirks->mach_get_smp_config) {
++		if (x86_quirks->mach_get_smp_config(early))
++			return;
++	}
+ 	if (acpi_lapic && early)
+ 		return;
+ 	/*
+@@ -604,7 +613,7 @@ static void __init __get_smp_config(unsi
+ 
+ 	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+ 	       mpf->mpf_specification);
+-#ifdef CONFIG_X86_32
++#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	if (mpf->mpf_feature2 & (1 << 7)) {
+ 		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+ 		pic_mode = 1;
+@@ -635,8 +644,10 @@ static void __init __get_smp_config(unsi
+ 		 * Read the physical hardware table.  Anything here will
+ 		 * override the defaults.
+ 		 */
+-		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr), early)) {
++		if (!smp_read_mpc(_bus_to_virt(mpf->mpf_physptr), early)) {
++#ifdef CONFIG_X86_LOCAL_APIC
+ 			smp_found_config = 0;
++#endif
+ 			printk(KERN_ERR
+ 			       "BIOS bug, MP table errors detected!...\n");
+ 			printk(KERN_ERR "... disabling SMP support. "
+@@ -690,10 +701,11 @@ void __init get_smp_config(void)
+ static int __init smp_scan_config(unsigned long base, unsigned long length,
+ 				  unsigned reserve)
+ {
+-	unsigned int *bp = isa_bus_to_virt(base);
++	unsigned int *bp = _bus_to_virt(base);
+ 	struct intel_mp_floating *mpf;
+ 
+-	Dprintk("Scan SMP from %p for %ld bytes.\n", bp, length);
++	apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
++			bp, length);
+ 	BUILD_BUG_ON(sizeof(*mpf) != 16);
+ 
+ 	while (length > 0) {
+@@ -703,16 +715,22 @@ static int __init smp_scan_config(unsign
+ 		    !mpf_checksum((unsigned char *)bp, 16) &&
+ 		    ((mpf->mpf_specification == 1)
+ 		     || (mpf->mpf_specification == 4))) {
+-
++#ifdef CONFIG_X86_LOCAL_APIC
+ 			smp_found_config = 1;
++#endif
+ 			mpf_found = mpf;
+-#ifdef CONFIG_X86_32
++
+ #ifndef CONFIG_XEN
+ 			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+ 			       mpf, virt_to_phys(mpf));
+-			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
++
++			if (!reserve)
++				return 1;
++			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE,
+ 					BOOTMEM_DEFAULT);
+ 			if (mpf->mpf_physptr) {
++				unsigned long size = PAGE_SIZE;
++#ifdef CONFIG_X86_32
+ 				/*
+ 				 * We cannot access to MPC table to compute
+ 				 * table size yet, as only few megabytes from
+@@ -722,27 +740,18 @@ static int __init smp_scan_config(unsign
+ 				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
+ 				 * in reserve_bootmem.
+ 				 */
+-				unsigned long size = PAGE_SIZE;
+ 				unsigned long end = max_low_pfn * PAGE_SIZE;
+ 				if (mpf->mpf_physptr + size > end)
+ 					size = end - mpf->mpf_physptr;
+-				reserve_bootmem(mpf->mpf_physptr, size,
++#endif
++				reserve_bootmem_generic(mpf->mpf_physptr, size,
+ 						BOOTMEM_DEFAULT);
+ 			}
+ #else
+ 			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+-				mpf, ((void *)bp - isa_bus_to_virt(base)) + base);
+-#endif
+-#elif !defined(CONFIG_XEN)
+-			if (!reserve)
+-				return 1;
+-
+-			reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE);
+-			if (mpf->mpf_physptr)
+-				reserve_bootmem_generic(mpf->mpf_physptr,
+-							PAGE_SIZE);
++				mpf, ((void *)bp - _bus_to_virt(base)) + base);
+ #endif
+-		return 1;
++			return 1;
+ 		}
+ 		bp += 4;
+ 		length -= 16;
+@@ -750,12 +759,16 @@ static int __init smp_scan_config(unsign
+ 	return 0;
+ }
+ 
+-static void __init __find_smp_config(unsigned reserve)
++static void __init __find_smp_config(unsigned int reserve)
+ {
+ #ifndef CONFIG_XEN
+ 	unsigned int address;
+ #endif
+ 
++	if (x86_quirks->mach_find_smp_config) {
++		if (x86_quirks->mach_find_smp_config(reserve))
++			return;
++	}
+ 	/*
+ 	 * FIXME: Linux assumes you have 640K of base ram..
+ 	 * this continues the error...
+@@ -802,300 +815,297 @@ void __init find_smp_config(void)
+ 	__find_smp_config(1);
+ }
+ 
+-/* --------------------------------------------------------------------------
+-                            ACPI-based MP Configuration
+-   -------------------------------------------------------------------------- */
+-
+-/*
+- * Keep this outside and initialized to 0, for !CONFIG_ACPI builds:
+- */
+-int es7000_plat;
+-
+-#ifdef CONFIG_ACPI
++#ifdef CONFIG_X86_IO_APIC
++static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+ 
+-#ifdef	CONFIG_X86_IO_APIC
++static int  __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
++{
++	int i;
+ 
+-#define MP_ISA_BUS		0
++	if (m->mpc_irqtype != mp_INT)
++		return 0;
+ 
+-extern struct mp_ioapic_routing mp_ioapic_routing[MAX_IO_APICS];
++	if (m->mpc_irqflag != 0x0f)
++		return 0;
+ 
+-static int mp_find_ioapic(int gsi)
+-{
+-	int i = 0;
++	/* not legacy */
+ 
+-	/* Find the IOAPIC that manages this GSI. */
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if ((gsi >= mp_ioapic_routing[i].gsi_base)
+-		    && (gsi <= mp_ioapic_routing[i].gsi_end))
+-			return i;
++	for (i = 0; i < mp_irq_entries; i++) {
++		if (mp_irqs[i].mp_irqtype != mp_INT)
++			continue;
++
++		if (mp_irqs[i].mp_irqflag != 0x0f)
++			continue;
++
++		if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
++			continue;
++		if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
++			continue;
++		if (irq_used[i]) {
++			/* already claimed */
++			return -2;
++		}
++		irq_used[i] = 1;
++		return i;
+ 	}
+ 
+-	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++	/* not found */
+ 	return -1;
+ }
+ 
+-static u8 __init uniq_ioapic_id(u8 id)
+-{
+-#ifdef CONFIG_X86_32
+-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+-	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+-		return io_apic_get_unique_id(nr_ioapics, id);
+-	else
+-		return id;
+-#else
+-	int i;
+-	DECLARE_BITMAP(used, 256);
+-	bitmap_zero(used, 256);
+-	for (i = 0; i < nr_ioapics; i++) {
+-		struct mpc_config_ioapic *ia = &mp_ioapics[i];
+-		__set_bit(ia->mpc_apicid, used);
+-	}
+-	if (!test_bit(id, used))
+-		return id;
+-	return find_first_zero_bit(used, 256);
++#define SPARE_SLOT_NUM 20
++
++static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+ #endif
+-}
+ 
+-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
++static int  __init replace_intsrc_all(struct mp_config_table *mpc,
++					unsigned long mpc_new_phys,
++					unsigned long mpc_new_length)
+ {
+-	int idx = 0;
+-
+-	if (bad_ioapic(address))
+-		return;
++#ifdef CONFIG_X86_IO_APIC
++	int i;
++	int nr_m_spare = 0;
++#endif
+ 
+-	idx = nr_ioapics;
++	int count = sizeof(*mpc);
++	unsigned char *mpt = ((unsigned char *)mpc) + count;
+ 
+-	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+-	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+-	mp_ioapics[idx].mpc_apicaddr = address;
++	printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
++	while (count < mpc->mpc_length) {
++		switch (*mpt) {
++		case MP_PROCESSOR:
++			{
++				struct mpc_config_processor *m =
++				    (struct mpc_config_processor *)mpt;
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_BUS:
++			{
++				struct mpc_config_bus *m =
++				    (struct mpc_config_bus *)mpt;
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		case MP_IOAPIC:
++			{
++				mpt += sizeof(struct mpc_config_ioapic);
++				count += sizeof(struct mpc_config_ioapic);
++				break;
++			}
++		case MP_INTSRC:
++			{
++#ifdef CONFIG_X86_IO_APIC
++				struct mpc_config_intsrc *m =
++				    (struct mpc_config_intsrc *)mpt;
+ 
+-#ifndef CONFIG_XEN
+-	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++				apic_printk(APIC_VERBOSE, "OLD ");
++				print_MP_intsrc_info(m);
++				i = get_MP_intsrc_index(m);
++				if (i > 0) {
++					assign_to_mpc_intsrc(&mp_irqs[i], m);
++					apic_printk(APIC_VERBOSE, "NEW ");
++					print_mp_irq_info(&mp_irqs[i]);
++				} else if (!i) {
++					/* legacy, do nothing */
++				} else if (nr_m_spare < SPARE_SLOT_NUM) {
++					/*
++					 * not found (-1), or duplicated (-2)
++					 * are invalid entries,
++					 * we need to use the slot  later
++					 */
++					m_spare[nr_m_spare] = m;
++					nr_m_spare++;
++				}
+ #endif
+-	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
+-#ifdef CONFIG_X86_32
+-	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+-#else
+-	mp_ioapics[idx].mpc_apicver = 0;
++				mpt += sizeof(struct mpc_config_intsrc);
++				count += sizeof(struct mpc_config_intsrc);
++				break;
++			}
++		case MP_LINTSRC:
++			{
++				struct mpc_config_lintsrc *m =
++				    (struct mpc_config_lintsrc *)mpt;
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++		default:
++			/* wrong mptable */
++			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
++			printk(KERN_ERR "type %x\n", *mpt);
++			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
++					1, mpc, mpc->mpc_length, 1);
++			goto out;
++		}
++	}
++
++#ifdef CONFIG_X86_IO_APIC
++	for (i = 0; i < mp_irq_entries; i++) {
++		if (irq_used[i])
++			continue;
++
++		if (mp_irqs[i].mp_irqtype != mp_INT)
++			continue;
++
++		if (mp_irqs[i].mp_irqflag != 0x0f)
++			continue;
++
++		if (nr_m_spare > 0) {
++			apic_printk(APIC_VERBOSE, "*NEW* found\n");
++			nr_m_spare--;
++			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
++			m_spare[nr_m_spare] = NULL;
++		} else {
++			struct mpc_config_intsrc *m =
++			    (struct mpc_config_intsrc *)mpt;
++			count += sizeof(struct mpc_config_intsrc);
++			if (!mpc_new_phys) {
++				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
++			} else {
++				if (count <= mpc_new_length)
++					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
++				else {
++					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
++					goto out;
++				}
++			}
++			assign_to_mpc_intsrc(&mp_irqs[i], m);
++			mpc->mpc_length = count;
++			mpt += sizeof(struct mpc_config_intsrc);
++		}
++		print_mp_irq_info(&mp_irqs[i]);
++	}
+ #endif
+-	/*
+-	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+-	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+-	 */
+-	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+-	mp_ioapic_routing[idx].gsi_base = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base +
+-	    io_apic_get_redir_entries(idx);
+-
+-	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+-	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
+-	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+-	       mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);
++out:
++	/* update checksum */
++	mpc->mpc_checksum = 0;
++	mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
++					   mpc->mpc_length);
+ 
+-	nr_ioapics++;
++	return 0;
+ }
+ 
+-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+-{
+-	struct mpc_config_intsrc intsrc;
+-	int ioapic = -1;
+-	int pin = -1;
+-
+-	/*
+-	 * Convert 'gsi' to 'ioapic.pin'.
+-	 */
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0)
+-		return;
+-	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++static int __initdata enable_update_mptable;
+ 
+-	/*
+-	 * TBD: This check is for faulty timer entries, where the override
+-	 *      erroneously sets the trigger to level, resulting in a HUGE
+-	 *      increase of timer interrupts!
+-	 */
+-	if ((bus_irq == 0) && (trigger == 3))
+-		trigger = 1;
++static int __init update_mptable_setup(char *str)
++{
++	enable_update_mptable = 1;
++	return 0;
++}
++early_param("update_mptable", update_mptable_setup);
+ 
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqtype = mp_INT;
+-	intsrc.mpc_irqflag = (trigger << 2) | polarity;
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-	intsrc.mpc_srcbusirq = bus_irq;	/* IRQ */
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	/* APIC ID */
+-	intsrc.mpc_dstirq = pin;	/* INTIN# */
++static unsigned long __initdata mpc_new_phys;
++static unsigned long mpc_new_length __initdata = 4096;
+ 
+-	MP_intsrc_info(&intsrc);
++/* alloc_mptable or alloc_mptable=4k */
++static int __initdata alloc_mptable;
++static int __init parse_alloc_mptable_opt(char *p)
++{
++	enable_update_mptable = 1;
++	alloc_mptable = 1;
++	if (!p)
++		return 0;
++	mpc_new_length = memparse(p, &p);
++	return 0;
+ }
++early_param("alloc_mptable", parse_alloc_mptable_opt);
+ 
+-void __init mp_config_acpi_legacy_irqs(void)
++void __init early_reserve_e820_mpc_new(void)
+ {
+-	struct mpc_config_intsrc intsrc;
+-	int i = 0;
+-	int ioapic = -1;
+-
+-#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+-	/*
+-	 * Fabricate the legacy ISA bus (bus #31).
+-	 */
+-	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++	if (enable_update_mptable && alloc_mptable) {
++		u64 startt = 0;
++#ifdef CONFIG_X86_TRAMPOLINE
++		startt = TRAMPOLINE_BASE;
+ #endif
+-	set_bit(MP_ISA_BUS, mp_bus_not_pci);
+-	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+-
+-	/*
+-	 * Older generations of ES7000 have no legacy identity mappings
+-	 */
+-	if (es7000_plat == 1)
+-		return;
+-
+-	/*
+-	 * Locate the IOAPIC that manages the ISA IRQs (0-15).
+-	 */
+-	ioapic = mp_find_ioapic(0);
+-	if (ioapic < 0)
+-		return;
+-
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;	/* Conforming */
+-	intsrc.mpc_srcbus = MP_ISA_BUS;
+-#ifdef CONFIG_X86_IO_APIC
+-	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
+-#endif
+-	/*
+-	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overridden by (MADT) interrupt source override entries.
+-	 */
+-	for (i = 0; i < 16; i++) {
+-		int idx;
+-
+-		for (idx = 0; idx < mp_irq_entries; idx++) {
+-			struct mpc_config_intsrc *irq = mp_irqs + idx;
+-
+-			/* Do we already have a mapping for this ISA IRQ? */
+-			if (irq->mpc_srcbus == MP_ISA_BUS
+-			    && irq->mpc_srcbusirq == i)
+-				break;
+-
+-			/* Do we already have a mapping for this IOAPIC pin */
+-			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
+-			    (irq->mpc_dstirq == i))
+-				break;
+-		}
+-
+-		if (idx != mp_irq_entries) {
+-			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+-			continue;	/* IRQ already used */
+-		}
+-
+-		intsrc.mpc_irqtype = mp_INT;
+-		intsrc.mpc_srcbusirq = i;	/* Identity mapped */
+-		intsrc.mpc_dstirq = i;
+-
+-		MP_intsrc_info(&intsrc);
++		mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+ 	}
+ }
+ 
+-int mp_register_gsi(u32 gsi, int triggering, int polarity)
++static int __init update_mp_table(void)
+ {
+-	int ioapic;
+-	int ioapic_pin;
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+-#define MAX_GSI_NUM	4096
+-#define IRQ_COMPRESSION_START	64
++	char str[16];
++	char oem[10];
++	struct intel_mp_floating *mpf;
++	struct mp_config_table *mpc;
++	struct mp_config_table *mpc_new;
++
++	if (!enable_update_mptable)
++		return 0;
++
++	mpf = mpf_found;
++	if (!mpf)
++		return 0;
+ 
+-	static int pci_irq = IRQ_COMPRESSION_START;
+ 	/*
+-	 * Mapping between Global System Interrupts, which
+-	 * represent all possible interrupts, and IRQs
+-	 * assigned to actual devices.
++	 * Now see if we need to go further.
+ 	 */
+-	static int gsi_to_irq[MAX_GSI_NUM];
+-#else
++	if (mpf->mpf_feature1 != 0)
++		return 0;
+ 
+-	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+-		return gsi;
+-#endif
++	if (!mpf->mpf_physptr)
++		return 0;
+ 
+-	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_gbl_FADT.sci_interrupt == gsi)
+-		return gsi;
++	mpc = _bus_to_virt(mpf->mpf_physptr);
+ 
+-	ioapic = mp_find_ioapic(gsi);
+-	if (ioapic < 0) {
+-		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+-		return gsi;
+-	}
++	if (!smp_check_mpc(mpc, oem, str))
++		return 0;
+ 
+-	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++	printk(KERN_INFO "mpf: %lx\n", (long)arbitrary_virt_to_machine(mpf));
++	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+ 
+-#ifndef CONFIG_X86_32
+-	if (ioapic_renumber_irq)
+-		gsi = ioapic_renumber_irq(ioapic, gsi);
+-#endif
++	if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
++		mpc_new_phys = 0;
++		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
++			 mpc_new_length);
++	}
++
++	if (!mpc_new_phys) {
++		unsigned char old, new;
++		/* check if we can change the postion */
++		mpc->mpc_checksum = 0;
++		old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
++		mpc->mpc_checksum = 0xff;
++		new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
++		if (old == new) {
++			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
++			return 0;
++		}
++		printk(KERN_INFO "use in-positon replacing\n");
++	} else {
++		maddr_t mpc_new_bus;
+ 
+-	/*
+-	 * Avoid pin reprogramming.  PRTs typically include entries
+-	 * with redundant pin->gsi mappings (but unique PCI devices);
+-	 * we only program the IOAPIC on the first.
+-	 */
+-	if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
+-		printk(KERN_ERR "Invalid reference to IOAPIC pin "
+-		       "%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
+-		       ioapic_pin);
+-		return gsi;
+-	}
+-	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
+-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+-		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+-#else
+-		return gsi;
+-#endif
++		mpc_new_bus = phys_to_machine(mpc_new_phys);
++		mpf->mpf_physptr = mpc_new_bus;
++		mpc_new = phys_to_virt(mpc_new_phys);
++		memcpy(mpc_new, mpc, mpc->mpc_length);
++		mpc = mpc_new;
++		/* check if we can modify that */
++		if (mpc_new_bus - mpf->mpf_physptr) {
++			struct intel_mp_floating *mpf_new;
++			/* steal 16 bytes from [0, 1k) */
++			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
++			mpf_new = isa_bus_to_virt(0x400 - 16);
++			memcpy(mpf_new, mpf, 16);
++			mpf = mpf_new;
++			mpf->mpf_physptr = mpc_new_bus;
++		}
++		mpf->mpf_checksum = 0;
++		mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
++		printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+ 	}
+ 
+-	set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	/*
+-	 * For GSI >= 64, use IRQ compression
++	 * only replace the one with mp_INT and
++	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
++	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
++	 * may need pci=routeirq for all coverage
+ 	 */
+-	if ((gsi >= IRQ_COMPRESSION_START)
+-	    && (triggering == ACPI_LEVEL_SENSITIVE)) {
+-		/*
+-		 * For PCI devices assign IRQs in order, avoiding gaps
+-		 * due to unused I/O APIC pins.
+-		 */
+-		int irq = gsi;
+-		if (gsi < MAX_GSI_NUM) {
+-			/*
+-			 * Retain the VIA chipset work-around (gsi > 15), but
+-			 * avoid a problem where the 8254 timer (IRQ0) is setup
+-			 * via an override (so it's not on pin 0 of the ioapic),
+-			 * and at the same time, the pin 0 interrupt is a PCI
+-			 * type.  The gsi > 15 test could cause these two pins
+-			 * to be shared as IRQ0, and they are not shareable.
+-			 * So test for this condition, and if necessary, avoid
+-			 * the pin collision.
+-			 */
+-			gsi = pci_irq++;
+-			/*
+-			 * Don't assign IRQ used by ACPI SCI
+-			 */
+-			if (gsi == acpi_gbl_FADT.sci_interrupt)
+-				gsi = pci_irq++;
+-			gsi_to_irq[irq] = gsi;
+-		} else {
+-			printk(KERN_ERR "GSI %u is too high\n", gsi);
+-			return gsi;
+-		}
+-	}
+-#endif
+-	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+-				triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+-				polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+-	return gsi;
++	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
++
++	return 0;
+ }
+ 
+-#endif /* CONFIG_X86_IO_APIC */
+-#endif /* CONFIG_ACPI */
++late_initcall(update_mp_table);
+--- head-2010-01-18.orig/arch/x86/kernel/apic/nmi.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/nmi.c	2009-11-06 10:51:42.000000000 +0100
+@@ -27,7 +27,9 @@
+ #include <linux/kdebug.h>
+ #include <linux/smp.h>
+ 
++#ifndef CONFIG_XEN
+ #include <asm/i8259.h>
++#endif
+ #include <asm/io_apic.h>
+ #include <asm/proto.h>
+ #include <asm/timer.h>
+@@ -174,11 +176,13 @@ int __init check_nmi_watchdog(void)
+ 	kfree(prev_nmi_count);
+ 	return 0;
+ error:
++#ifndef CONFIG_XEN
+ 	if (nmi_watchdog == NMI_IO_APIC) {
+ 		if (!timer_through_8259)
+ 			disable_8259A_irq(0);
+ 		on_each_cpu(__acpi_nmi_disable, NULL, 1);
+ 	}
++#endif
+ 
+ #ifdef CONFIG_X86_32
+ 	timer_ack = 0;
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -5,13 +5,13 @@
+ 
+ #include <asm/proto.h>
+ #include <asm/dma.h>
+-#include <asm/gart.h>
++#include <asm/iommu.h>
+ #include <asm/calgary.h>
++#include <asm/amd_iommu.h>
+ 
+-int forbid_dac __read_mostly;
+-EXPORT_SYMBOL(forbid_dac);
++static int forbid_dac __read_mostly;
+ 
+-const struct dma_mapping_ops *dma_ops;
++struct dma_mapping_ops *dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+ 
+ static int iommu_sac_force __read_mostly;
+@@ -74,13 +74,17 @@ early_param("dma32_size", parse_dma32_si
+ void __init dma32_reserve_bootmem(void)
+ {
+ 	unsigned long size, align;
+-	if (end_pfn <= MAX_DMA32_PFN)
++	if (max_pfn <= MAX_DMA32_PFN)
+ 		return;
+ 
++	/*
++	 * check aperture_64.c allocate_aperture() for reason about
++	 * using 512M as goal
++	 */
+ 	align = 64ULL<<20;
+ 	size = round_up(dma32_bootmem_size, align);
+ 	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
+-				 __pa(MAX_DMA_ADDRESS));
++				 512ULL<<20);
+ 	if (dma32_bootmem_ptr)
+ 		dma32_bootmem_size = size;
+ 	else
+@@ -88,17 +92,14 @@ void __init dma32_reserve_bootmem(void)
+ }
+ static void __init dma32_free_bootmem(void)
+ {
+-	int node;
+ 
+-	if (end_pfn <= MAX_DMA32_PFN)
++	if (max_pfn <= MAX_DMA32_PFN)
+ 		return;
+ 
+ 	if (!dma32_bootmem_ptr)
+ 		return;
+ 
+-	for_each_online_node(node)
+-		free_bootmem_node(NODE_DATA(node), __pa(dma32_bootmem_ptr),
+-				  dma32_bootmem_size);
++	free_bootmem(__pa(dma32_bootmem_ptr), dma32_bootmem_size);
+ 
+ 	dma32_bootmem_ptr = NULL;
+ 	dma32_bootmem_size = 0;
+@@ -107,7 +108,7 @@ static void __init dma32_free_bootmem(vo
+ #define dma32_free_bootmem() ((void)0)
+ #endif
+ 
+-static const struct dma_mapping_ops swiotlb_dma_ops = {
++static struct dma_mapping_ops swiotlb_dma_ops = {
+ 	.mapping_error = swiotlb_dma_mapping_error,
+ 	.map_single = swiotlb_map_single_phys,
+ 	.unmap_single = swiotlb_unmap_single,
+@@ -130,25 +131,31 @@ void __init pci_iommu_alloc(void)
+ 	 * The order of these functions is important for
+ 	 * fall-back/fail-over reasons
+ 	 */
+-#ifdef CONFIG_GART_IOMMU
+ 	gart_iommu_hole_init();
+-#endif
+ 
+-#ifdef CONFIG_CALGARY_IOMMU
+ 	detect_calgary();
+-#endif
+ 
+ 	detect_intel_iommu();
+ 
+-#ifdef CONFIG_SWIOTLB
++	amd_iommu_detect();
++
+ 	swiotlb_init();
+ 	if (swiotlb) {
+ 		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
+ 		dma_ops = &swiotlb_dma_ops;
+ 	}
+-#endif
+ }
+ 
++#ifndef CONFIG_XEN
++unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
++{
++	unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
++
++	return size >> PAGE_SHIFT;
++}
++EXPORT_SYMBOL(iommu_num_pages);
++#endif
++
+ /*
+  * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+  * documentation.
+@@ -201,9 +208,7 @@ static __init int iommu_setup(char *p)
+ 			swiotlb = 1;
+ #endif
+ 
+-#ifdef CONFIG_GART_IOMMU
+ 		gart_parse_options(p);
+-#endif
+ 
+ #ifdef CONFIG_CALGARY_IOMMU
+ 		if (!strncmp(p, "calgary", 7))
+@@ -245,136 +250,19 @@ int range_straddles_page_boundary(paddr_
+ 		!check_pages_physically_contiguous(pfn, offset, size));
+ }
+ 
+-#ifdef CONFIG_X86_32
+-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+-				dma_addr_t device_addr, size_t size, int flags)
+-{
+-	void __iomem *mem_base = NULL;
+-	int pages = size >> PAGE_SHIFT;
+-	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+-
+-	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+-		goto out;
+-	if (!size)
+-		goto out;
+-	if (dev->dma_mem)
+-		goto out;
+-
+-	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+-
+-	mem_base = ioremap(bus_addr, size);
+-	if (!mem_base)
+-		goto out;
+-
+-	dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+-	if (!dev->dma_mem)
+-		goto out;
+-	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+-	if (!dev->dma_mem->bitmap)
+-		goto free1_out;
+-
+-	dev->dma_mem->virt_base = mem_base;
+-	dev->dma_mem->device_base = device_addr;
+-	dev->dma_mem->size = pages;
+-	dev->dma_mem->flags = flags;
+-
+-	if (flags & DMA_MEMORY_MAP)
+-		return DMA_MEMORY_MAP;
+-
+-	return DMA_MEMORY_IO;
+-
+- free1_out:
+-	kfree(dev->dma_mem);
+- out:
+-	if (mem_base)
+-		iounmap(mem_base);
+-	return 0;
+-}
+-EXPORT_SYMBOL(dma_declare_coherent_memory);
+-
+-void dma_release_declared_memory(struct device *dev)
+-{
+-	struct dma_coherent_mem *mem = dev->dma_mem;
+-
+-	if (!mem)
+-		return;
+-	dev->dma_mem = NULL;
+-	iounmap(mem->virt_base);
+-	kfree(mem->bitmap);
+-	kfree(mem);
+-}
+-EXPORT_SYMBOL(dma_release_declared_memory);
+-
+-void *dma_mark_declared_memory_occupied(struct device *dev,
+-					dma_addr_t device_addr, size_t size)
+-{
+-	struct dma_coherent_mem *mem = dev->dma_mem;
+-	int pos, err;
+-	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
+-
+-	pages >>= PAGE_SHIFT;
+-
+-	if (!mem)
+-		return ERR_PTR(-EINVAL);
+-
+-	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+-	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+-	if (err != 0)
+-		return ERR_PTR(err);
+-	return mem->virt_base + (pos << PAGE_SHIFT);
+-}
+-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+-
+-static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
+-				       dma_addr_t *dma_handle, void **ret)
+-{
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-	int order = get_order(size);
+-
+-	if (mem) {
+-		int page = bitmap_find_free_region(mem->bitmap, mem->size,
+-						     order);
+-		if (page >= 0) {
+-			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
+-			*ret = mem->virt_base + (page << PAGE_SHIFT);
+-			memset(*ret, 0, size);
+-		}
+-		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+-			*ret = NULL;
+-	}
+-	return (mem != NULL);
+-}
+-
+-static int dma_release_coherent(struct device *dev, int order, void *vaddr)
+-{
+-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+-
+-	if (mem && vaddr >= mem->virt_base && vaddr <
+-		   (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+-		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+-
+-		bitmap_release_region(mem->bitmap, page, order);
+-		return 1;
+-	}
+-	return 0;
+-}
+-#else
+-#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
+-#define dma_release_coherent(dev, order, vaddr) (0)
+-#endif /* CONFIG_X86_32 */
+-
+ int dma_supported(struct device *dev, u64 mask)
+ {
++	struct dma_mapping_ops *ops = get_dma_ops(dev);
++
+ #ifdef CONFIG_PCI
+ 	if (mask > 0xffffffff && forbid_dac > 0) {
+-		printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
+-				 dev->bus_id);
++		dev_info(dev, "PCI: Disallowing DAC for device\n");
+ 		return 0;
+ 	}
+ #endif
+ 
+-	if (dma_ops->dma_supported)
+-		return dma_ops->dma_supported(dev, mask);
++	if (ops->dma_supported)
++		return ops->dma_supported(dev, mask);
+ 
+ 	/* Copied from i386. Doesn't make much sense, because it will
+ 	   only work for pci_alloc_coherent.
+@@ -395,8 +283,7 @@ int dma_supported(struct device *dev, u6
+ 	   type. Normally this doesn't make any difference, but gives
+ 	   more gentle handling of IOMMU overflow. */
+ 	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
+-		printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
+-				 dev->bus_id, mask);
++		dev_info(dev, "Force SAC with mask %Lx\n", mask);
+ 		return 0;
+ 	}
+ 
+@@ -422,6 +309,9 @@ void *
+ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ 		   gfp_t gfp)
+ {
++#ifndef CONFIG_XEN
++	struct dma_mapping_ops *ops = get_dma_ops(dev);
++#endif
+ 	void *memory = NULL;
+ 	struct page *page;
+ 	unsigned long dma_mask = 0;
+@@ -431,7 +321,7 @@ dma_alloc_coherent(struct device *dev, s
+ 	/* ignore region specifiers */
+ 	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+ 
+-	if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory))
++	if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
+ 		return memory;
+ 
+ 	if (!dev) {
+@@ -491,8 +381,8 @@ dma_alloc_coherent(struct device *dev, s
+ 			/* Let low level make its own zone decisions */
+ 			gfp &= ~(GFP_DMA32|GFP_DMA);
+ 
+-			if (dma_ops->alloc_coherent)
+-				return dma_ops->alloc_coherent(dev, size,
++			if (ops->alloc_coherent)
++				return ops->alloc_coherent(dev, size,
+ 							   dma_handle, gfp);
+ 			return NULL;
+ 		}
+@@ -504,14 +394,14 @@ dma_alloc_coherent(struct device *dev, s
+ 		}
+ 	}
+ 
+-	if (dma_ops->alloc_coherent) {
++	if (ops->alloc_coherent) {
+ 		free_pages((unsigned long)memory, order);
+ 		gfp &= ~(GFP_DMA|GFP_DMA32);
+-		return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
++		return ops->alloc_coherent(dev, size, dma_handle, gfp);
+ 	}
+ 
+-	if (dma_ops->map_simple) {
+-		*dma_handle = dma_ops->map_simple(dev, virt_to_bus(memory),
++	if (ops->map_simple) {
++		*dma_handle = ops->map_simple(dev, virt_to_bus(memory),
+ 					      size,
+ 					      PCI_DMA_BIDIRECTIONAL);
+ 		if (*dma_handle != bad_dma_address)
+@@ -542,13 +432,17 @@ EXPORT_SYMBOL(dma_alloc_coherent);
+ void dma_free_coherent(struct device *dev, size_t size,
+ 			 void *vaddr, dma_addr_t bus)
+ {
++#ifndef CONFIG_XEN
++	struct dma_mapping_ops *ops = get_dma_ops(dev);
++#endif
++
+ 	int order = get_order(size);
+ 	WARN_ON(irqs_disabled());	/* for portability */
+-	if (dma_release_coherent(dev, order, vaddr))
++	if (dma_release_from_coherent(dev, order, vaddr))
+ 		return;
+ #ifndef CONFIG_XEN
+-	if (dma_ops->unmap_single)
+-		dma_ops->unmap_single(dev, bus, size, 0);
++	if (ops->unmap_single)
++		ops->unmap_single(dev, bus, size, 0);
+ #endif
+ 	xen_destroy_contiguous_region((unsigned long)vaddr, order);
+ 	free_pages((unsigned long)vaddr, order);
+@@ -557,15 +451,13 @@ EXPORT_SYMBOL(dma_free_coherent);
+ 
+ static int __init pci_iommu_init(void)
+ {
+-#ifdef CONFIG_CALGARY_IOMMU
+ 	calgary_iommu_init();
+-#endif
+ 
+ 	intel_iommu_init();
+ 
+-#ifdef CONFIG_GART_IOMMU
++	amd_iommu_init();
++
+ 	gart_iommu_init();
+-#endif
+ 
+ 	no_iommu_init();
+ 	return 0;
+--- head-2010-01-18.orig/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -79,18 +79,12 @@ gnttab_unmap_single(struct device *dev, 
+ 	gnttab_dma_unmap_page(dma_addr);
+ }
+ 
+-static int nommu_mapping_error(dma_addr_t dma_addr)
+-{
+-	return (dma_addr == bad_dma_address);
+-}
+-
+-static const struct dma_mapping_ops nommu_dma_ops = {
++static struct dma_mapping_ops nommu_dma_ops = {
+ 	.map_single = gnttab_map_single,
+ 	.unmap_single = gnttab_unmap_single,
+ 	.map_sg = gnttab_map_sg,
+ 	.unmap_sg = gnttab_unmap_sg,
+ 	.dma_supported = swiotlb_dma_supported,
+-	.mapping_error = nommu_mapping_error
+ };
+ 
+ void __init no_iommu_init(void)
+--- head-2010-01-18.orig/arch/x86/kernel/probe_roms_32.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/probe_roms_32.c	2009-11-06 10:51:42.000000000 +0100
+@@ -131,7 +131,7 @@ void __init probe_roms(void)
+ 	upper = system_rom_resource.start;
+ 
+ 	/* check for extension rom (ignore length byte!) */
+-	rom = isa_bus_to_virt(extension_rom_resource.start);
++	rom = isa_bus_to_virt((unsigned long)extension_rom_resource.start);
+ 	if (romsignature(rom)) {
+ 		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+ 		if (romchecksum(rom, length)) {
+--- head-2010-01-18.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -6,6 +6,13 @@
+ #include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
++#include <linux/clockchips.h>
++#include <asm/system.h>
++
++unsigned long idle_halt;
++EXPORT_SYMBOL(idle_halt);
++unsigned long idle_nomwait;
++EXPORT_SYMBOL(idle_nomwait);
+ 
+ struct kmem_cache *task_xstate_cachep;
+ 
+@@ -45,6 +52,70 @@ void arch_task_cache_init(void)
+ 				  SLAB_PANIC, NULL);
+ }
+ 
++/*
++ * Idle related variables and functions
++ */
++unsigned long boot_option_idle_override = 0;
++EXPORT_SYMBOL(boot_option_idle_override);
++
++/*
++ * Powermanagement idle function, if any..
++ */
++void (*pm_idle)(void);
++EXPORT_SYMBOL(pm_idle);
++
++#ifdef CONFIG_X86_32
++/*
++ * This halt magic was a workaround for ancient floppy DMA
++ * wreckage. It should be safe to remove.
++ */
++static int hlt_counter;
++void disable_hlt(void)
++{
++	hlt_counter++;
++}
++EXPORT_SYMBOL(disable_hlt);
++
++void enable_hlt(void)
++{
++	hlt_counter--;
++}
++EXPORT_SYMBOL(enable_hlt);
++
++static inline int hlt_use_halt(void)
++{
++	return (!hlt_counter && boot_cpu_data.hlt_works_ok);
++}
++#else
++static inline int hlt_use_halt(void)
++{
++	return 1;
++}
++#endif
++
++/*
++ * We use this if we don't have any better
++ * idle routine..
++ */
++void xen_idle(void)
++{
++	current_thread_info()->status &= ~TS_POLLING;
++	/*
++	 * TS_POLLING-cleared state must be visible before we
++	 * test NEED_RESCHED:
++	 */
++	smp_mb();
++
++	if (!need_resched())
++		safe_halt();	/* enables interrupts racelessly */
++	else
++		local_irq_enable();
++	current_thread_info()->status |= TS_POLLING;
++}
++#ifdef CONFIG_APM_MODULE
++EXPORT_SYMBOL(default_idle);
++#endif
++
+ static void do_nothing(void *unused)
+ {
+ }
+@@ -61,7 +132,7 @@ void cpu_idle_wait(void)
+ {
+ 	smp_mb();
+ 	/* kick all the CPUs so that they exit out of pm_idle */
+-	smp_call_function(do_nothing, NULL, 0, 1);
++	smp_call_function(do_nothing, NULL, 1);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+@@ -125,60 +196,175 @@ static void poll_idle(void)
+  *
+  * idle=mwait overrides this decision and forces the usage of mwait.
+  */
++static int __cpuinitdata force_mwait;
++
++#define MWAIT_INFO			0x05
++#define MWAIT_ECX_EXTENDED_INFO		0x01
++#define MWAIT_EDX_C1			0xf0
++
+ static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+ {
++	u32 eax, ebx, ecx, edx;
++
+ 	if (force_mwait)
+ 		return 1;
+ 
+-	if (c->x86_vendor == X86_VENDOR_AMD) {
+-		switch(c->x86) {
+-		case 0x10:
+-		case 0x11:
+-			return 0;
++	if (c->cpuid_level < MWAIT_INFO)
++		return 0;
++
++	cpuid(MWAIT_INFO, &eax, &ebx, &ecx, &edx);
++	/* Check, whether EDX has extended info about MWAIT */
++	if (!(ecx & MWAIT_ECX_EXTENDED_INFO))
++		return 1;
++
++	/*
++	 * edx enumeratios MONITOR/MWAIT extensions. Check, whether
++	 * C1  supports MWAIT
++	 */
++	return (edx & MWAIT_EDX_C1);
++}
++
++/*
++ * Check for AMD CPUs, which have potentially C1E support
++ */
++static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
++{
++	if (c->x86_vendor != X86_VENDOR_AMD)
++		return 0;
++
++	if (c->x86 < 0x0F)
++		return 0;
++
++	/* Family 0x0f models < rev F do not have C1E */
++	if (c->x86 == 0x0f && c->x86_model < 0x40)
++		return 0;
++
++	return 1;
++}
++
++static cpumask_t c1e_mask = CPU_MASK_NONE;
++static int c1e_detected;
++
++void c1e_remove_cpu(int cpu)
++{
++	cpu_clear(cpu, c1e_mask);
++}
++
++/*
++ * C1E aware idle routine. We check for C1E active in the interrupt
++ * pending message MSR. If we detect C1E, then we handle it the same
++ * way as C3 power states (local apic timer and TSC stop)
++ */
++static void c1e_idle(void)
++{
++	if (need_resched())
++		return;
++
++	if (!c1e_detected) {
++		u32 lo, hi;
++
++		rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
++		if (lo & K8_INTP_C1E_ACTIVE_MASK) {
++			c1e_detected = 1;
++			if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
++				mark_tsc_unstable("TSC halt in AMD C1E");
++			printk(KERN_INFO "System has AMD C1E enabled\n");
++			set_cpu_cap(&boot_cpu_data, X86_FEATURE_AMDC1E);
+ 		}
+ 	}
+-	return 1;
++
++	if (c1e_detected) {
++		int cpu = smp_processor_id();
++
++		if (!cpu_isset(cpu, c1e_mask)) {
++			cpu_set(cpu, c1e_mask);
++			/*
++			 * Force broadcast so ACPI can not interfere. Needs
++			 * to run with interrupts enabled as it uses
++			 * smp_function_call.
++			 */
++			local_irq_enable();
++			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
++					   &cpu);
++			printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
++			       cpu);
++			local_irq_disable();
++		}
++		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
++
++		default_idle();
++
++		/*
++		 * The switch back from broadcast mode needs to be
++		 * called with interrupts disabled.
++		 */
++		 local_irq_disable();
++		 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
++		 local_irq_enable();
++	} else
++		default_idle();
+ }
+ #endif
+ 
+ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+ {
+ #ifndef CONFIG_XEN
+-	static int selected;
+-
+-	if (selected)
+-		return;
+ #ifdef CONFIG_X86_SMP
+ 	if (pm_idle == poll_idle && smp_num_siblings > 1) {
+ 		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+ 			" performance may degrade.\n");
+ 	}
+ #endif
++	if (pm_idle)
++		return;
++
+ 	if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
+ 		/*
+-		 * Skip, if setup has overridden idle.
+ 		 * One CPU supports mwait => All CPUs supports mwait
+ 		 */
+-		if (!pm_idle) {
+-			printk(KERN_INFO "using mwait in idle threads.\n");
+-			pm_idle = mwait_idle;
+-		}
+-	}
+-	selected = 1;
++		printk(KERN_INFO "using mwait in idle threads.\n");
++		pm_idle = mwait_idle;
++	} else if (check_c1e_idle(c)) {
++		printk(KERN_INFO "using C1E aware idle routine\n");
++		pm_idle = c1e_idle;
++	} else
++		pm_idle = default_idle;
+ #endif
+ }
+ 
+ static int __init idle_setup(char *str)
+ {
++	if (!str)
++		return -EINVAL;
++
+ 	if (!strcmp(str, "poll")) {
+ 		printk("using polling idle threads.\n");
+ 		pm_idle = poll_idle;
+-	}
+ #ifndef CONFIG_XEN
+-	else if (!strcmp(str, "mwait"))
++	} else if (!strcmp(str, "mwait"))
+ 		force_mwait = 1;
++	else if (!strcmp(str, "halt")) {
++		/*
++		 * When the boot option of idle=halt is added, halt is
++		 * forced to be used for CPU idle. In such case CPU C2/C3
++		 * won't be used again.
++		 * To continue to load the CPU idle driver, don't touch
++		 * the boot_option_idle_override.
++		 */
++		pm_idle = default_idle;
++		idle_halt = 1;
++		return 0;
++	} else if (!strcmp(str, "nomwait")) {
++		/*
++		 * If the boot option of "idle=nomwait" is added,
++		 * it means that mwait will be disabled for CPU C2/C3
++		 * states. In such case it won't touch the variable
++		 * of boot_option_idle_override.
++		 */
++		idle_nomwait = 1;
++		return 0;
+ #endif
+-	else
++	} else
+ 		return -1;
+ 
+ 	boot_option_idle_override = 1;
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -59,15 +59,11 @@
+ #include <asm/tlbflush.h>
+ #include <asm/cpu.h>
+ #include <asm/kdebug.h>
++#include <asm/idle.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+ 
+-static int hlt_counter;
+-
+-unsigned long boot_option_idle_override = 0;
+-EXPORT_SYMBOL(boot_option_idle_override);
+-
+ DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+ EXPORT_PER_CPU_SYMBOL(current_task);
+ 
+@@ -82,46 +78,27 @@ unsigned long thread_saved_pc(struct tas
+ 	return ((unsigned long *)tsk->thread.sp)[3];
+ }
+ 
+-/*
+- * Powermanagement idle function, if any..
+- */
+-void (*pm_idle)(void);
+-EXPORT_SYMBOL(pm_idle);
++#ifdef CONFIG_HOTPLUG_CPU
++#ifndef CONFIG_XEN
++#include <asm/nmi.h>
+ 
+-void disable_hlt(void)
++static void cpu_exit_clear(void)
+ {
+-	hlt_counter++;
+-}
++	int cpu = raw_smp_processor_id();
+ 
+-EXPORT_SYMBOL(disable_hlt);
+-
+-void enable_hlt(void)
+-{
+-	hlt_counter--;
+-}
++	idle_task_exit();
+ 
+-EXPORT_SYMBOL(enable_hlt);
++	cpu_uninit();
++	irq_ctx_exit(cpu);
+ 
+-static void xen_idle(void)
+-{
+-	current_thread_info()->status &= ~TS_POLLING;
+-	/*
+-	 * TS_POLLING-cleared state must be visible before we
+-	 * test NEED_RESCHED:
+-	 */
+-	smp_mb();
++	cpu_clear(cpu, cpu_callout_map);
++	cpu_clear(cpu, cpu_callin_map);
+ 
+-	if (!need_resched())
+-		safe_halt();	/* enables interrupts racelessly */
+-	else
+-		local_irq_enable();
+-	current_thread_info()->status |= TS_POLLING;
++	numa_remove_cpu(cpu);
++	c1e_remove_cpu(cpu);
+ }
+-#ifdef CONFIG_APM_MODULE
+-EXPORT_SYMBOL(default_idle);
+ #endif
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+ static inline void play_dead(void)
+ {
+ 	idle_task_exit();
+@@ -152,13 +129,11 @@ void cpu_idle(void)
+ 
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
+-		tick_nohz_stop_sched_tick();
++		tick_nohz_stop_sched_tick(1);
+ 		while (!need_resched()) {
+-			void (*idle)(void);
+ 
+ 			check_pgt_cache();
+ 			rmb();
+-			idle = xen_idle; /* no alternatives */
+ 
+ 			if (rcu_pending(cpu))
+ 				rcu_check_callbacks(cpu, 0);
+@@ -168,7 +143,10 @@ void cpu_idle(void)
+ 
+ 			local_irq_disable();
+ 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
+-			idle();
++			/* Don't trace irqs off for idle */
++			stop_critical_timings();
++			xen_idle();
++			start_critical_timings();
+ 		}
+ 		tick_nohz_restart_sched_tick();
+ 		preempt_enable_no_resched();
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -65,15 +65,6 @@ asmlinkage extern void ret_from_fork(voi
+ 
+ unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
+ 
+-unsigned long boot_option_idle_override = 0;
+-EXPORT_SYMBOL(boot_option_idle_override);
+-
+-/*
+- * Powermanagement idle function, if any..
+- */
+-void (*pm_idle)(void);
+-EXPORT_SYMBOL(pm_idle);
+-
+ static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+ 
+ void idle_notifier_register(struct notifier_block *n)
+@@ -103,25 +94,13 @@ void exit_idle(void)
+ 	__exit_idle();
+ }
+ 
+-static void xen_idle(void)
+-{
+-	current_thread_info()->status &= ~TS_POLLING;
+-	/*
+-	 * TS_POLLING-cleared state must be visible before we
+-	 * test NEED_RESCHED:
+-	 */
+-	smp_mb();
+-	if (!need_resched())
+-		safe_halt();	/* enables interrupts racelessly */
+-	else
+-		local_irq_enable();
+-	current_thread_info()->status |= TS_POLLING;
+-}
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ static inline void play_dead(void)
+ {
+ 	idle_task_exit();
++#ifndef CONFIG_XEN
++	c1e_remove_cpu(raw_smp_processor_id());
++#endif
+ 	local_irq_disable();
+ 	cpu_clear(smp_processor_id(), cpu_initialized);
+ 	preempt_enable_no_resched();
+@@ -146,12 +125,11 @@ void cpu_idle(void)
+ 	current_thread_info()->status |= TS_POLLING;
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
+-		tick_nohz_stop_sched_tick();
++		tick_nohz_stop_sched_tick(1);
+ 		while (!need_resched()) {
+-			void (*idle)(void);
+ 
+ 			rmb();
+-			idle = xen_idle; /* no alternatives */
++
+ 			if (cpu_is_offline(smp_processor_id()))
+ 				play_dead();
+ 			/*
+@@ -161,7 +139,10 @@ void cpu_idle(void)
+ 			 */
+ 			local_irq_disable();
+ 			enter_idle();
+-			idle();
++			/* Don't trace irqs off for idle */
++			stop_critical_timings();
++			xen_idle();
++			start_critical_timings();
+ 			/* In many cases the interrupt that ended idle
+ 			   has already called exit_idle. But some idle
+ 			   loops can be woken up without interrupt. */
+@@ -271,7 +252,7 @@ void exit_thread(void)
+ 	}
+ }
+ 
+-void load_gs_index(unsigned gs)
++void xen_load_gs_index(unsigned gs)
+ {
+ 	WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gs));
+ }
+@@ -373,10 +354,10 @@ int copy_thread(int nr, unsigned long cl
+ 	p->thread.fs = me->thread.fs;
+ 	p->thread.gs = me->thread.gs;
+ 
+-	asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
+-	asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
+-	asm("mov %%es,%0" : "=m" (p->thread.es));
+-	asm("mov %%ds,%0" : "=m" (p->thread.ds));
++	savesegment(gs, p->thread.gsindex);
++	savesegment(fs, p->thread.fsindex);
++	savesegment(es, p->thread.es);
++	savesegment(ds, p->thread.ds);
+ 
+ 	if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
+ 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+@@ -417,7 +398,9 @@ out:
+ void
+ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+ {
+-	asm volatile("movl %0, %%fs; movl %0, %%es; movl %0, %%ds" :: "r"(0));
++	loadsegment(fs, 0);
++	loadsegment(es, 0);
++	loadsegment(ds, 0);
+ 	load_gs_index(0);
+ 	regs->ip		= new_ip;
+ 	regs->sp		= new_sp;
+@@ -557,8 +540,8 @@ static inline void __switch_to_xtra(stru
+ struct task_struct *
+ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+-	struct thread_struct *prev = &prev_p->thread,
+-				 *next = &next_p->thread;
++	struct thread_struct *prev = &prev_p->thread;
++	struct thread_struct *next = &next_p->thread;
+ 	int cpu = smp_processor_id();
+ #ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+@@ -661,12 +644,25 @@ __switch_to(struct task_struct *prev_p, 
+ 	 */
+ 	if (unlikely(next->es))
+ 		loadsegment(es, next->es); 
+-	
++
+ 	if (unlikely(next->ds))
+ 		loadsegment(ds, next->ds);
+ 
++	/*
++	 * Leave lazy mode, flushing any hypercalls made here.
++	 * This must be done before restoring TLS segments so
++	 * the GDT and LDT are properly updated, and must be
++	 * done before math_state_restore, so the TS bit is up
++	 * to date.
++	 */
++	arch_leave_lazy_cpu_mode();
++
+ 	/* 
+ 	 * Switch FS and GS.
++	 *
++	 * Segment register != 0 always requires a reload.  Also
++	 * reload when it has changed.  When prev process used 64bit
++	 * base always reload to avoid an information leak.
+ 	 */
+ 	if (unlikely(next->fsindex))
+ 		loadsegment(fs, next->fsindex);
+@@ -687,7 +683,8 @@ __switch_to(struct task_struct *prev_p, 
+ 	write_pda(oldrsp, next->usersp);
+ 	write_pda(pcurrent, next_p); 
+ 	write_pda(kernelstack,
+-	(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
++		  (unsigned long)task_stack_page(next_p) +
++		  THREAD_SIZE - PDA_STACKOFFSET);
+ #ifdef CONFIG_CC_STACKPROTECTOR
+ 	write_pda(stack_canary, next_p->stack_canary);
+ 
+@@ -848,7 +845,7 @@ long do_arch_prctl(struct task_struct *t
+ 			set_32bit_tls(task, FS_TLS, addr);
+ 			if (doit) {
+ 				load_TLS(&task->thread, cpu);
+-				asm volatile("movl %0,%%fs" :: "r"(FS_TLS_SEL));
++				loadsegment(fs, FS_TLS_SEL);
+ 			}
+ 			task->thread.fsindex = FS_TLS_SEL;
+ 			task->thread.fs = 0;
+@@ -858,7 +855,7 @@ long do_arch_prctl(struct task_struct *t
+ 			if (doit) {
+ 				/* set the selector to 0 to not confuse
+ 				   __switch_to */
+-				asm volatile("movl %0,%%fs" :: "r" (0));
++				loadsegment(fs, 0);
+                                 ret = HYPERVISOR_set_segment_base(SEGBASE_FS,
+ 								  addr);
+ 			}
+@@ -882,7 +879,7 @@ long do_arch_prctl(struct task_struct *t
+ 		if (task->thread.gsindex == GS_TLS_SEL)
+ 			base = read_32bit_tls(task, GS_TLS);
+ 		else if (doit) {
+-			asm("movl %%gs,%0" : "=r" (gsindex));
++			savesegment(gs, gsindex);
+ 			if (gsindex)
+ 				rdmsrl(MSR_KERNEL_GS_BASE, base);
+ 			else
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -63,6 +63,7 @@ static enum {
+ 	ICH_FORCE_HPET_RESUME,
+ 	VT8237_FORCE_HPET_RESUME,
+ 	NVIDIA_FORCE_HPET_RESUME,
++	ATI_FORCE_HPET_RESUME,
+ } force_hpet_resume_type;
+ 
+ static void __iomem *rcba_base;
+@@ -156,6 +157,8 @@ static void ich_force_enable_hpet(struct
+ 
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
+ 			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,
++			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
+ 			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,
+@@ -172,6 +175,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
+ 
+ static struct pci_dev *cached_dev;
+ 
++static void hpet_print_force_info(void)
++{
++	printk(KERN_INFO "HPET not enabled in BIOS. "
++	       "You might try hpet=force boot option\n");
++}
++
+ static void old_ich_force_hpet_resume(void)
+ {
+ 	u32 val;
+@@ -251,8 +260,12 @@ static void old_ich_force_enable_hpet_us
+ {
+ 	if (hpet_force_user)
+ 		old_ich_force_enable_hpet(dev);
++	else
++		hpet_print_force_info();
+ }
+ 
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
++			 old_ich_force_enable_hpet_user);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+ 			 old_ich_force_enable_hpet_user);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
+@@ -288,9 +301,14 @@ static void vt8237_force_enable_hpet(str
+ {
+ 	u32 uninitialized_var(val);
+ 
+-	if (!hpet_force_user || hpet_address || force_hpet_address)
++	if (hpet_address || force_hpet_address)
+ 		return;
+ 
++	if (!hpet_force_user) {
++		hpet_print_force_info();
++		return;
++	}
++
+ 	pci_read_config_dword(dev, 0x68, &val);
+ 	/*
+ 	 * Bit 7 is HPET enable bit.
+@@ -328,6 +346,36 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_V
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
+ 			 vt8237_force_enable_hpet);
+ 
++static void ati_force_hpet_resume(void)
++{
++	pci_write_config_dword(cached_dev, 0x14, 0xfed00000);
++	printk(KERN_DEBUG "Force enabled HPET at resume\n");
++}
++
++static void ati_force_enable_hpet(struct pci_dev *dev)
++{
++	u32 uninitialized_var(val);
++
++	if (hpet_address || force_hpet_address)
++		return;
++
++	if (!hpet_force_user) {
++		hpet_print_force_info();
++		return;
++	}
++
++	pci_write_config_dword(dev, 0x14, 0xfed00000);
++	pci_read_config_dword(dev, 0x14, &val);
++	force_hpet_address = val;
++	force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
++	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
++		   force_hpet_address);
++	cached_dev = dev;
++	return;
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
++			 ati_force_enable_hpet);
++
+ /*
+  * Undocumented chipset feature taken from LinuxBIOS.
+  */
+@@ -341,8 +389,13 @@ static void nvidia_force_enable_hpet(str
+ {
+ 	u32 uninitialized_var(val);
+ 
+-	if (!hpet_force_user || hpet_address || force_hpet_address)
++	if (hpet_address || force_hpet_address)
++		return;
++
++	if (!hpet_force_user) {
++		hpet_print_force_info();
+ 		return;
++	}
+ 
+ 	pci_write_config_dword(dev, 0x44, 0xfed00001);
+ 	pci_read_config_dword(dev, 0x44, &val);
+@@ -395,6 +448,9 @@ void force_hpet_resume(void)
+ 	case NVIDIA_FORCE_HPET_RESUME:
+ 		nvidia_force_hpet_resume();
+ 		return;
++	case ATI_FORCE_HPET_RESUME:
++		ati_force_hpet_resume();
++		return;
+ 	default:
+ 		break;
+ 	}
+--- head-2010-01-18.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1,141 +1,1133 @@
+-#include <linux/kernel.h>
++/*
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ *
++ *  Memory region support
++ *	David Parsons <orc@pell.chi.il.us>, July-August 1999
++ *
++ *  Added E820 sanitization routine (removes overlapping memory regions);
++ *  Brian Moyle <bmoyle@mvista.com>, February 2001
++ *
++ * Moved CPU detection code to cpu/${cpu}.c
++ *    Patrick Mochel <mochel@osdl.org>, March 2002
++ *
++ *  Provisions for empty E820 memory regions (reported by certain BIOSes).
++ *  Alex Achenbach <xela@slit.de>, December 2002.
++ *
++ */
++
++/*
++ * This file handles the architecture-dependent parts of initialization
++ */
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <linux/screen_info.h>
++#include <linux/ioport.h>
++#include <linux/acpi.h>
++#include <linux/apm_bios.h>
++#include <linux/initrd.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/console.h>
++#include <linux/mca.h>
++#include <linux/root_dev.h>
++#include <linux/highmem.h>
+ #include <linux/module.h>
++#include <linux/efi.h>
+ #include <linux/init.h>
+-#include <linux/bootmem.h>
++#include <linux/edd.h>
++#include <linux/iscsi_ibft.h>
++#include <linux/nodemask.h>
++#include <linux/kexec.h>
++#include <linux/dmi.h>
++#include <linux/pfn.h>
++#include <linux/pci.h>
++#include <asm/pci-direct.h>
++#include <linux/init_ohci1394_dma.h>
++#include <linux/kvm_para.h>
++
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/delay.h>
++
++#include <linux/kallsyms.h>
++#include <linux/cpufreq.h>
++#include <linux/dma-mapping.h>
++#include <linux/ctype.h>
++#include <linux/uaccess.h>
++
+ #include <linux/percpu.h>
+-#include <asm/smp.h>
+-#include <asm/percpu.h>
++#include <linux/crash_dump.h>
++
++#include <video/edid.h>
++
++#include <asm/mtrr.h>
++#include <asm/apic.h>
++#include <asm/e820.h>
++#include <asm/mpspec.h>
++#include <asm/setup.h>
++#include <asm/arch_hooks.h>
++#include <asm/efi.h>
+ #include <asm/sections.h>
++#include <asm/dmi.h>
++#include <asm/io_apic.h>
++#include <asm/ist.h>
++#include <asm/vmi.h>
++#include <setup_arch.h>
++#include <asm/bios_ebda.h>
++#include <asm/cacheflush.h>
+ #include <asm/processor.h>
+-#include <asm/setup.h>
++#include <asm/bugs.h>
++
++#include <asm/system.h>
++#include <asm/vsyscall.h>
++#include <asm/smp.h>
++#include <asm/desc.h>
++#include <asm/dma.h>
++#include <asm/iommu.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++
++#include <mach_apic.h>
++#include <asm/paravirt.h>
++
++#include <asm/percpu.h>
+ #include <asm/topology.h>
+-#include <asm/mpspec.h>
+ #include <asm/apicdef.h>
++#ifdef CONFIG_X86_64
++#include <asm/numa_64.h>
++#endif
++
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++#include <xen/interface/kexec.h>
++#include <xen/interface/memory.h>
++#include <xen/interface/nmi.h>
++#include <xen/interface/physdev.h>
++#include <xen/features.h>
++#include <xen/firmware.h>
++#include <xen/xencons.h>
++
++shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++EXPORT_SYMBOL(HYPERVISOR_shared_info);
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-unsigned int num_processors;
+-unsigned disabled_cpus __cpuinitdata;
+-/* Processor that is doing the boot up */
+-unsigned int boot_cpu_physical_apicid = -1U;
+-EXPORT_SYMBOL(boot_cpu_physical_apicid);
++static int xen_panic_event(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xen_panic_block = {
++	xen_panic_event, NULL, 0 /* try to go last */
++};
+ 
+-DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
+-EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
++unsigned long *phys_to_machine_mapping;
++EXPORT_SYMBOL(phys_to_machine_mapping);
+ 
+-/* Bitmask of physically existing CPUs */
+-physid_mask_t phys_cpu_present_map;
++unsigned long *pfn_to_mfn_frame_list_list,
++#ifdef CONFIG_X86_64
++	*pfn_to_mfn_frame_list[512];
++#else
++	*pfn_to_mfn_frame_list[128];
++#endif
++
++/* Raw start-of-day parameters from the hypervisor. */
++start_info_t *xen_start_info;
++EXPORT_SYMBOL(xen_start_info);
++#endif
++
++#ifndef ARCH_SETUP
++#define ARCH_SETUP
++#endif
++
++#ifndef CONFIG_XEN
++#ifndef CONFIG_DEBUG_BOOT_PARAMS
++struct boot_params __initdata boot_params;
++#else
++struct boot_params boot_params;
++#endif
+ #endif
+ 
+-#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP)
+ /*
+- * Copy data used in early init routines from the initial arrays to the
+- * per cpu data areas.  These arrays then become expendable and the
+- * *_early_ptr's are zeroed indicating that the static arrays are gone.
++ * Machine setup..
+  */
+-static void __init setup_per_cpu_maps(void)
++static struct resource data_resource = {
++	.name	= "Kernel data",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource code_resource = {
++	.name	= "Kernel code",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource bss_resource = {
++	.name	= "Kernel bss",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++
++#ifdef CONFIG_X86_32
++#ifndef CONFIG_XEN
++/* This value is set up by the early boot code to point to the value
++   immediately after the boot time page tables.  It contains a *physical*
++   address, and must not be in the .bss segment! */
++unsigned long init_pg_tables_start __initdata = ~0UL;
++unsigned long init_pg_tables_end __initdata = ~0UL;
++#endif
++
++static struct resource video_ram_resource = {
++	.name	= "Video RAM area",
++	.start	= 0xa0000,
++	.end	= 0xbffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++/* cpu data as detected by the assembly code in head.S */
++struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};
++/* common cpu data for all cpus */
++struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1};
++EXPORT_SYMBOL(boot_cpu_data);
++#ifndef CONFIG_XEN
++static void set_mca_bus(int x)
++{
++#ifdef CONFIG_MCA
++	MCA_bus = x;
++#endif
++}
++
++unsigned int def_to_bigsmp;
++
++/* for MCA, but anyone else can use it if they want */
++unsigned int machine_id;
++unsigned int machine_submodel_id;
++unsigned int BIOS_revision;
++
++struct apm_info apm_info;
++EXPORT_SYMBOL(apm_info);
++#endif
++
++#if defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
++struct ist_info ist_info;
++EXPORT_SYMBOL(ist_info);
++#elif defined(CONFIG_X86_SPEEDSTEP_SMI)
++struct ist_info ist_info;
++#endif
++
++#else
++struct cpuinfo_x86 boot_cpu_data __read_mostly;
++EXPORT_SYMBOL(boot_cpu_data);
++#endif
++
++
++#if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
++unsigned long mmu_cr4_features;
++#else
++unsigned long mmu_cr4_features = X86_CR4_PAE;
++#endif
++
++/* Boot loader ID as an integer, for the benefit of proc_dointvec */
++int bootloader_type;
++
++/*
++ * Early DMI memory
++ */
++int dmi_alloc_index;
++char dmi_alloc_data[DMI_MAX_DATA];
++
++/*
++ * Setup options
++ */
++struct screen_info screen_info;
++EXPORT_SYMBOL(screen_info);
++struct edid_info edid_info;
++EXPORT_SYMBOL_GPL(edid_info);
++
++extern int root_mountflags;
++
++unsigned long saved_video_mode;
++
++#define RAMDISK_IMAGE_START_MASK	0x07FF
++#define RAMDISK_PROMPT_FLAG		0x8000
++#define RAMDISK_LOAD_FLAG		0x4000
++
++static char __initdata command_line[COMMAND_LINE_SIZE];
++
++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
++struct edd edd;
++#ifdef CONFIG_EDD_MODULE
++EXPORT_SYMBOL(edd);
++#endif
++#ifndef CONFIG_XEN
++/**
++ * copy_edd() - Copy the BIOS EDD information
++ *              from boot_params into a safe place.
++ *
++ */
++static inline void copy_edd(void)
++{
++     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
++	    sizeof(edd.mbr_signature));
++     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
++     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
++     edd.edd_info_nr = boot_params.eddbuf_entries;
++}
++#endif
++#else
++static inline void copy_edd(void)
++{
++}
++#endif
++
++#ifdef CONFIG_BLK_DEV_INITRD
++
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++
++#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
++static void __init relocate_initrd(void)
++{
++
++	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
++	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
++	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	u64 ramdisk_here;
++	unsigned long slop, clen, mapaddr;
++	char *p, *q;
++
++	/* We need to move the initrd down into lowmem */
++	ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size,
++					 PAGE_SIZE);
++
++	if (ramdisk_here == -1ULL)
++		panic("Cannot find place for new RAMDISK of size %lld\n",
++			 ramdisk_size);
++
++	/* Note: this includes all the lowmem currently occupied by
++	   the initrd, we rely on that fact to keep the data intact. */
++	reserve_early(ramdisk_here, ramdisk_here + ramdisk_size,
++			 "NEW RAMDISK");
++	initrd_start = ramdisk_here + PAGE_OFFSET;
++	initrd_end   = initrd_start + ramdisk_size;
++	printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
++			 ramdisk_here, ramdisk_here + ramdisk_size);
++
++	q = (char *)initrd_start;
++
++	/* Copy any lowmem portion of the initrd */
++	if (ramdisk_image < end_of_lowmem) {
++		clen = end_of_lowmem - ramdisk_image;
++		p = (char *)__va(ramdisk_image);
++		memcpy(q, p, clen);
++		q += clen;
++		ramdisk_image += clen;
++		ramdisk_size  -= clen;
++	}
++
++	/* Copy the highmem portion of the initrd */
++	while (ramdisk_size) {
++		slop = ramdisk_image & ~PAGE_MASK;
++		clen = ramdisk_size;
++		if (clen > MAX_MAP_CHUNK-slop)
++			clen = MAX_MAP_CHUNK-slop;
++		mapaddr = ramdisk_image & PAGE_MASK;
++		p = early_ioremap(mapaddr, clen+slop);
++		memcpy(q, p+slop, clen);
++		early_iounmap(p, clen+slop);
++		q += clen;
++		ramdisk_image += clen;
++		ramdisk_size  -= clen;
++	}
++	/* high pages is not converted by early_res_to_bootmem */
++	ramdisk_image = boot_params.hdr.ramdisk_image;
++	ramdisk_size  = boot_params.hdr.ramdisk_size;
++	printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to"
++		" %08llx - %08llx\n",
++		ramdisk_image, ramdisk_image + ramdisk_size - 1,
++		ramdisk_here, ramdisk_here + ramdisk_size - 1);
++}
++#endif
++
++static void __init reserve_initrd(void)
+ {
+ #ifndef CONFIG_XEN
+-	int cpu;
++	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
++	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
++	u64 ramdisk_end   = ramdisk_image + ramdisk_size;
++	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++
++	if (!boot_params.hdr.type_of_loader ||
++	    !ramdisk_image || !ramdisk_size)
++		return;		/* No initrd provided by bootloader */
++#else
++	unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
++	unsigned long ramdisk_size  = xen_start_info->mod_len;
++	unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
++	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+ 
+-	for_each_possible_cpu(cpu) {
+-		per_cpu(x86_cpu_to_apicid, cpu) = x86_cpu_to_apicid_init[cpu];
+-		per_cpu(x86_bios_cpu_apicid, cpu) =
+-						x86_bios_cpu_apicid_init[cpu];
+-#ifdef CONFIG_NUMA
+-		per_cpu(x86_cpu_to_node_map, cpu) =
+-						x86_cpu_to_node_map_init[cpu];
++	if (!xen_start_info->mod_start || !ramdisk_size)
++		return;		/* No initrd provided by bootloader */
+ #endif
++
++	initrd_start = 0;
++
++	if (ramdisk_size >= (end_of_lowmem>>1)) {
++		free_early(ramdisk_image, ramdisk_end);
++		printk(KERN_ERR "initrd too large to handle, "
++		       "disabling initrd\n");
++		return;
+ 	}
+ 
+-	/* indicate the early static arrays will soon be gone */
+-	x86_cpu_to_apicid_early_ptr = NULL;
+-	x86_bios_cpu_apicid_early_ptr = NULL;
+-#ifdef CONFIG_NUMA
+-	x86_cpu_to_node_map_early_ptr = NULL;
++	printk(KERN_INFO "RAMDISK: %08lx - %08lx\n", ramdisk_image,
++			ramdisk_end);
++
++
++	if (ramdisk_end <= end_of_lowmem) {
++		/* All in lowmem, easy case */
++		/*
++		 * don't need to reserve again, already reserved early
++		 * in i386_start_kernel
++		 */
++		initrd_start = ramdisk_image + PAGE_OFFSET;
++		initrd_end = initrd_start + ramdisk_size;
++#ifdef CONFIG_X86_64_XEN
++		initrd_below_start_ok = 1;
+ #endif
++		return;
++	}
++
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++	relocate_initrd();
++#else
++	printk(KERN_ERR "initrd extends beyond end of memory "
++	       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++	       ramdisk_end, end_of_lowmem);
++	initrd_start = 0;
+ #endif
++	free_early(ramdisk_image, ramdisk_end);
+ }
++#else
++static void __init reserve_initrd(void)
++{
++}
++#endif /* CONFIG_BLK_DEV_INITRD */
++
++static void __init parse_setup_data(void)
++{
++#ifndef CONFIG_XEN
++	struct setup_data *data;
++	u64 pa_data;
+ 
+-#ifdef CONFIG_HAVE_CPUMASK_OF_CPU_MAP
+-cpumask_t *cpumask_of_cpu_map __read_mostly;
+-EXPORT_SYMBOL(cpumask_of_cpu_map);
++	if (boot_params.hdr.version < 0x0209)
++		return;
++	pa_data = boot_params.hdr.setup_data;
++	while (pa_data) {
++		data = early_ioremap(pa_data, PAGE_SIZE);
++		switch (data->type) {
++		case SETUP_E820_EXT:
++			parse_e820_ext(data, pa_data);
++			break;
++		default:
++			break;
++		}
++		pa_data = data->next;
++		early_iounmap(data, PAGE_SIZE);
++	}
++#endif
++}
+ 
+-/* requires nr_cpu_ids to be initialized */
+-static void __init setup_cpumask_of_cpu(void)
++static void __init e820_reserve_setup_data(void)
+ {
+-	int i;
++#ifndef CONFIG_XEN
++	struct setup_data *data;
++	u64 pa_data;
++	int found = 0;
++
++	if (boot_params.hdr.version < 0x0209)
++		return;
++	pa_data = boot_params.hdr.setup_data;
++	while (pa_data) {
++		data = early_ioremap(pa_data, sizeof(*data));
++		e820_update_range(pa_data, sizeof(*data)+data->len,
++			 E820_RAM, E820_RESERVED_KERN);
++		found = 1;
++		pa_data = data->next;
++		early_iounmap(data, sizeof(*data));
++	}
++	if (!found)
++		return;
+ 
+-	/* alloc_bootmem zeroes memory */
+-	cpumask_of_cpu_map = alloc_bootmem_low(sizeof(cpumask_t) * nr_cpu_ids);
+-	for (i = 0; i < nr_cpu_ids; i++)
+-		cpu_set(i, cpumask_of_cpu_map[i]);
++	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
++	memcpy(&e820_saved, &e820, sizeof(struct e820map));
++	printk(KERN_INFO "extended physical RAM map:\n");
++	e820_print_map("reserve setup_data");
++#endif
+ }
+-#else
+-static inline void setup_cpumask_of_cpu(void) { }
++
++static void __init reserve_early_setup_data(void)
++{
++#ifndef CONFIG_XEN
++	struct setup_data *data;
++	u64 pa_data;
++	char buf[32];
++
++	if (boot_params.hdr.version < 0x0209)
++		return;
++	pa_data = boot_params.hdr.setup_data;
++	while (pa_data) {
++		data = early_ioremap(pa_data, sizeof(*data));
++		sprintf(buf, "setup data %x", data->type);
++		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
++		pa_data = data->next;
++		early_iounmap(data, sizeof(*data));
++	}
+ #endif
++}
+ 
+-#ifdef CONFIG_X86_32
+ /*
+- * Great future not-so-futuristic plan: make i386 and x86_64 do it
+- * the same way
++ * --------- Crashkernel reservation ------------------------------
++ */
++
++#ifdef CONFIG_KEXEC
++
++#ifndef CONFIG_XEN
++/**
++ * Reserve @size bytes of crashkernel memory at any suitable offset.
++ *
++ * @size: Size of the crashkernel memory to reserve.
++ * Returns the base address on success, and -1ULL on failure.
++ */
++unsigned long long __init find_and_reserve_crashkernel(unsigned long long size)
++{
++	const unsigned long long alignment = 16<<20; 	/* 16M */
++	unsigned long long start = 0LL;
++
++	while (1) {
++		int ret;
++
++		start = find_e820_area(start, ULONG_MAX, size, alignment);
++		if (start == -1ULL)
++			return start;
++
++		/* try to reserve it */
++		ret = reserve_bootmem_generic(start, size, BOOTMEM_EXCLUSIVE);
++		if (ret >= 0)
++			return start;
++
++		start += alignment;
++	}
++}
++
++static inline unsigned long long get_total_mem(void)
++{
++	unsigned long long total;
++
++	total = max_low_pfn - min_low_pfn;
++#ifdef CONFIG_HIGHMEM
++	total += highend_pfn - highstart_pfn;
++#endif
++
++	return total << PAGE_SHIFT;
++}
++
++static void __init reserve_crashkernel(void)
++{
++	unsigned long long total_mem;
++	unsigned long long crash_size, crash_base;
++	int ret;
++
++	total_mem = get_total_mem();
++
++	ret = parse_crashkernel(boot_command_line, total_mem,
++			&crash_size, &crash_base);
++	if (ret != 0 || crash_size <= 0)
++		return;
++
++	/* 0 means: find the address automatically */
++	if (crash_base <= 0) {
++		crash_base = find_and_reserve_crashkernel(crash_size);
++		if (crash_base == -1ULL) {
++			pr_info("crashkernel reservation failed. "
++				"No suitable area found.\n");
++			return;
++		}
++	} else {
++		ret = reserve_bootmem_generic(crash_base, crash_size,
++					BOOTMEM_EXCLUSIVE);
++		if (ret < 0) {
++			pr_info("crashkernel reservation failed - "
++				"memory is in use\n");
++			return;
++		}
++	}
++
++	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
++			"for crashkernel (System RAM: %ldMB)\n",
++			(unsigned long)(crash_size >> 20),
++			(unsigned long)(crash_base >> 20),
++			(unsigned long)(total_mem >> 20));
++
++	crashk_res.start = crash_base;
++	crashk_res.end   = crash_base + crash_size - 1;
++	insert_resource(&iomem_resource, &crashk_res);
++}
++#else
++#define reserve_crashkernel xen_machine_kexec_setup_resources
++#endif
++#else
++static void __init reserve_crashkernel(void)
++{
++}
++#endif
++
++static struct resource standard_io_resources[] = {
++	{ .name = "dma1", .start = 0x00, .end = 0x1f,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "pic1", .start = 0x20, .end = 0x21,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "timer0", .start = 0x40, .end = 0x43,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "timer1", .start = 0x50, .end = 0x53,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .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 },
++	{ .name = "pic2", .start = 0xa0, .end = 0xa1,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "dma2", .start = 0xc0, .end = 0xdf,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "fpu", .start = 0xf0, .end = 0xff,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
++};
++
++static void __init reserve_standard_io_resources(void)
++{
++	int i;
++
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return;
++
++	/* request I/O space for devices used on all i[345]86 PCs */
++	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
++		request_resource(&ioport_resource, &standard_io_resources[i]);
++
++}
++
++#ifdef CONFIG_PROC_VMCORE
++/* elfcorehdr= specifies the location of elf core header
++ * stored by the crashed kernel. This option will be passed
++ * by kexec loader to the capture kernel.
+  */
+-unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
+-EXPORT_SYMBOL(__per_cpu_offset);
++static int __init setup_elfcorehdr(char *arg)
++{
++	char *end;
++	if (!arg)
++		return -EINVAL;
++	elfcorehdr_addr = memparse(arg, &end);
++	return end > arg ? 0 : -EINVAL;
++}
++early_param("elfcorehdr", setup_elfcorehdr);
+ #endif
+ 
++static struct x86_quirks default_x86_quirks __initdata;
++
++struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
++
++/*
++ * Determine if we were loaded by an EFI loader.  If so, then we have also been
++ * passed the efi memmap, systab, etc., so we should use these data structures
++ * for initialization.  Note, the efi init code path is determined by the
++ * global efi_enabled. This allows the same kernel image to be used on existing
++ * systems (with a traditional BIOS) as well as on EFI systems.
++ */
+ /*
+- * Great future plan:
+- * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
+- * Always point %gs to its beginning
++ * setup_arch - architecture-specific boot-time initializations
++ *
++ * Note: On x86_64, fixmaps are ready for use even before this is called.
+  */
+-void __init setup_per_cpu_areas(void)
++
++void __init setup_arch(char **cmdline_p)
+ {
+-	int i, highest_cpu = 0;
+-	unsigned long size;
++#ifdef CONFIG_XEN
++	unsigned int i;
++	unsigned long p2m_pages;
++	struct physdev_set_iopl set_iopl;
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+-	prefill_possible_map();
++#ifdef CONFIG_X86_32
++	/* Force a quick death if the kernel panics (not domain 0). */
++	extern int panic_timeout;
++	if (!panic_timeout && !is_initial_xendomain())
++		panic_timeout = 1;
+ #endif
+ 
+-	/* Copy section for each CPU (we discard the original) */
+-	size = PERCPU_ENOUGH_ROOM;
+-	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n",
+-			  size);
+-
+-	for_each_possible_cpu(i) {
+-		char *ptr;
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+-		ptr = alloc_bootmem_pages(size);
+-#else
+-		int node = early_cpu_to_node(i);
+-		if (!node_online(node) || !NODE_DATA(node)) {
+-			ptr = alloc_bootmem_pages(size);
+-			printk(KERN_INFO
+-			       "cpu %d has no node or node-local memory\n", i);
+-		}
+-		else
+-			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
++	/* Register a call for panic conditions. */
++	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_writable_pagetables));
++#ifdef CONFIG_X86_32
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_4gb_segments));
++#endif
++#endif /* CONFIG_XEN */
++
++#ifdef CONFIG_X86_32
++	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
++	visws_early_detect();
++	pre_setup_arch_hook();
++#else
++	printk(KERN_INFO "Command line: %s\n", boot_command_line);
++#endif
++
++	early_cpu_init();
++	early_ioremap_init();
++
++#ifndef CONFIG_XEN
++	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
++	screen_info = boot_params.screen_info;
++	edid_info = boot_params.edid_info;
++#ifdef CONFIG_X86_32
++	apm_info.bios = boot_params.apm_bios_info;
++	ist_info = boot_params.ist_info;
++	if (boot_params.sys_desc_table.length != 0) {
++		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
++		machine_id = boot_params.sys_desc_table.table[0];
++		machine_submodel_id = boot_params.sys_desc_table.table[1];
++		BIOS_revision = boot_params.sys_desc_table.table[2];
++	}
++#endif
++	saved_video_mode = boot_params.hdr.vid_mode;
++	bootloader_type = boot_params.hdr.type_of_loader;
++
++#ifdef CONFIG_BLK_DEV_RAM
++	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
++	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
++	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
++#endif
++#ifdef CONFIG_EFI
++	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
++#ifdef CONFIG_X86_32
++		     "EL32",
++#else
++		     "EL64",
+ #endif
+-		if (!ptr)
+-			panic("Cannot allocate cpu data for CPU %d\n", i);
++	 4)) {
++		efi_enabled = 1;
++		efi_reserve_early();
++	}
++#endif
++#else /* CONFIG_XEN */
++#ifdef CONFIG_X86_32
++	/* This must be initialized to UNNAMED_MAJOR for ipconfig to work
++	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
++	*/
++	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
++#else
++ 	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
++#endif
++	if (is_initial_xendomain()) {
++		const struct dom0_vga_console_info *info =
++			(void *)((char *)xen_start_info +
++			         xen_start_info->console.dom0.info_off);
++
++		dom0_init_screen_info(info,
++		                      xen_start_info->console.dom0.info_size);
++		xen_start_info->console.domU.mfn = 0;
++		xen_start_info->console.domU.evtchn = 0;
++	} else
++		screen_info.orig_video_isVGA = 0;
++	copy_edid();
++#endif /* CONFIG_XEN */
++
++	ARCH_SETUP
++
++	setup_memory_map();
++	parse_setup_data();
++	/* update the e820_saved too */
++	e820_reserve_setup_data();
++
++	copy_edd();
++
++#ifndef CONFIG_XEN
++	if (!boot_params.hdr.root_flags)
++		root_mountflags &= ~MS_RDONLY;
++#endif
++	init_mm.start_code = (unsigned long) _text;
++	init_mm.end_code = (unsigned long) _etext;
++	init_mm.end_data = (unsigned long) _edata;
++#ifdef CONFIG_X86_32
++#ifndef CONFIG_XEN
++	init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
++#else
++	init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
++		       xen_start_info->nr_pt_frames) << PAGE_SHIFT;
++#endif
++#else
++	init_mm.brk = (unsigned long) &_end;
++#endif
++
++	code_resource.start = virt_to_phys(_text);
++	code_resource.end = virt_to_phys(_etext)-1;
++	data_resource.start = virt_to_phys(_etext);
++	data_resource.end = virt_to_phys(_edata)-1;
++	bss_resource.start = virt_to_phys(&__bss_start);
++	bss_resource.end = virt_to_phys(&__bss_stop)-1;
++
++	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
++	*cmdline_p = command_line;
++
++	parse_early_param();
++
+ #ifdef CONFIG_X86_64
+-		cpu_pda(i)->data_offset = ptr - __per_cpu_start;
++	check_efer();
++#endif
++
++#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
++	/*
++	 * Must be before kernel pagetables are setup
++	 * or fixmap area is touched.
++	 */
++	vmi_init();
++#endif
++
++	/* after early param, so could get panic from serial */
++	reserve_early_setup_data();
++
++	if (acpi_mps_check()) {
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
++		disable_apic = 1;
++#endif
++		setup_clear_cpu_cap(X86_FEATURE_APIC);
++	}
++
++#ifdef CONFIG_PCI
++	if (pci_early_dump_regs)
++		early_dump_pci_devices();
++#endif
++
++	finish_e820_parsing();
++
++#ifdef CONFIG_X86_32
++	if (is_initial_xendomain())
++		probe_roms();
++#endif
++
++#ifndef CONFIG_XEN
++	/* after parse_early_param, so could debug it */
++	insert_resource(&iomem_resource, &code_resource);
++	insert_resource(&iomem_resource, &data_resource);
++	insert_resource(&iomem_resource, &bss_resource);
++
++	if (efi_enabled)
++		efi_init();
++
++#ifdef CONFIG_X86_32
++	if (ppro_with_ram_bug()) {
++		e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
++				  E820_RESERVED);
++		sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
++		printk(KERN_INFO "fixed physical RAM map:\n");
++		e820_print_map("bad_ppro");
++	}
+ #else
+-		__per_cpu_offset[i] = ptr - __per_cpu_start;
++	early_gart_iommu_check();
+ #endif
+-		memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
++#endif /* CONFIG_XEN */
+ 
+-		highest_cpu = i;
++	/*
++	 * partially used pages are not usable - thus
++	 * we are rounding upwards:
++	 */
++	max_pfn = e820_end_of_ram_pfn();
++
++	/* preallocate 4k for mptable mpc */
++	early_reserve_e820_mpc_new();
++	/* update e820 for memory not covered by WB MTRRs */
++	mtrr_bp_init();
++#ifndef CONFIG_XEN
++	if (mtrr_trim_uncached_memory(max_pfn))
++		max_pfn = e820_end_of_ram_pfn();
++#endif
++
++#ifdef CONFIG_X86_32
++	/* max_low_pfn get updated here */
++	find_low_pfn_range();
++#else
++	num_physpages = max_pfn;
++	max_mapnr = max_pfn;
++
++
++	/* How many end-of-memory variables you have, grandma! */
++	/* need this before calling reserve_initrd */
++	if (max_pfn > (1UL<<(32 - PAGE_SHIFT)))
++		max_low_pfn = e820_end_of_low_ram_pfn();
++	else
++		max_low_pfn = max_pfn;
++
++	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
++#endif
++
++	/* max_pfn_mapped is updated here */
++	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
++	max_pfn_mapped = max_low_pfn_mapped;
++
++#ifdef CONFIG_X86_64
++	if (max_pfn > max_low_pfn) {
++		max_pfn_mapped = init_memory_mapping(1UL<<32,
++						     max_pfn<<PAGE_SHIFT);
++		/* can we preseve max_low_pfn ?*/
++		max_low_pfn = max_pfn;
+ 	}
++#endif
+ 
+-	nr_cpu_ids = highest_cpu + 1;
+-	printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d\n", NR_CPUS, nr_cpu_ids);
++	/*
++	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
++	 */
+ 
+-	/* Setup percpu data maps */
+-	setup_per_cpu_maps();
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	if (init_ohci1394_dma_early)
++		init_ohci1394_dma_on_all_controllers();
++#endif
+ 
+-	/* Setup cpumask_of_cpu map */
+-	setup_cpumask_of_cpu();
+-}
++	reserve_initrd();
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++	vsmp_init();
++#endif
++
++	if (is_initial_xendomain())
++		dmi_scan_machine();
++
++	io_delay_init();
++
++#ifdef CONFIG_ACPI
++	if (!is_initial_xendomain()) {
++		printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
++		disable_acpi();
++	}
++#endif
++
++	/*
++	 * Parse the ACPI tables for possible boot-time SMP configuration.
++	 */
++	acpi_boot_table_init();
++
++#ifdef CONFIG_ACPI_NUMA
++	/*
++	 * Parse SRAT to discover nodes.
++	 */
++	acpi_numa_init();
++#endif
++
++	initmem_init(0, max_pfn);
+ 
++#ifdef CONFIG_ACPI_SLEEP
++	/*
++	 * Reserve low memory region for sleep support.
++	 */
++	acpi_reserve_bootmem();
+ #endif
++#ifdef CONFIG_X86_FIND_SMP_CONFIG
++	/*
++	 * Find and reserve possible boot-time SMP configuration:
++	 */
++	find_smp_config();
++#endif
++	reserve_crashkernel();
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++	/*
++	 * dma32_reserve_bootmem() allocates bootmem which may conflict
++	 * with the crashkernel command line, so do that after
++	 * reserve_crashkernel()
++	 */
++	dma32_reserve_bootmem();
++#endif
++
++	reserve_ibft_region();
++
++#ifdef CONFIG_KVM_CLOCK
++	kvmclock_init();
++#endif
++
++	xen_pagetable_setup_start(swapper_pg_dir);
++	paging_init();
++	xen_pagetable_setup_done(swapper_pg_dir);
++	paravirt_post_allocator_init();
++
++#ifdef CONFIG_X86_64
++	map_vsyscall();
++#endif
++
++#ifdef CONFIG_XEN
++	p2m_pages = max_pfn;
++	if (xen_start_info->nr_pages > max_pfn) {
++		/*
++		 * the max_pfn was shrunk (probably by mem= or highmem=
++		 * kernel parameter); shrink reservation with the HV
++		 */
++		struct xen_memory_reservation reservation = {
++			.address_bits = 0,
++			.extent_order = 0,
++			.domid = DOMID_SELF
++		};
++		unsigned int difference;
++		int ret;
++
++		difference = xen_start_info->nr_pages - max_pfn;
++
++		set_xen_guest_handle(reservation.extent_start,
++				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
++		reservation.nr_extents = difference;
++		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					   &reservation);
++		BUG_ON(ret != difference);
++	}
++	else if (max_pfn > xen_start_info->nr_pages)
++		p2m_pages = xen_start_info->nr_pages;
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		unsigned long i, j;
++		unsigned int k, fpp;
++
++		/* Make sure we have a large enough P->M table. */
++		phys_to_machine_mapping = alloc_bootmem_pages(
++			max_pfn * sizeof(unsigned long));
++		memset(phys_to_machine_mapping, ~0,
++		       max_pfn * sizeof(unsigned long));
++		memcpy(phys_to_machine_mapping,
++		       (unsigned long *)xen_start_info->mfn_list,
++		       p2m_pages * sizeof(unsigned long));
++		free_bootmem(
++			__pa(xen_start_info->mfn_list),
++			PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
++					sizeof(unsigned long))));
++
++		/*
++		 * Initialise the list of the frames that specify the list of
++		 * frames that make up the p2m table. Used by save/restore.
++		 */
++		pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE);
++
++		fpp = PAGE_SIZE/sizeof(unsigned long);
++		for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) {
++			if (j == fpp)
++				j = 0;
++			if (j == 0) {
++				k++;
++				BUG_ON(k>=ARRAY_SIZE(pfn_to_mfn_frame_list));
++				pfn_to_mfn_frame_list[k] =
++					alloc_bootmem_pages(PAGE_SIZE);
++				pfn_to_mfn_frame_list_list[k] =
++					virt_to_mfn(pfn_to_mfn_frame_list[k]);
++			}
++			pfn_to_mfn_frame_list[k][j] =
++				virt_to_mfn(&phys_to_machine_mapping[i]);
++		}
++		HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
++		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
++			virt_to_mfn(pfn_to_mfn_frame_list_list);
++	}
++
++	/* Mark all ISA DMA channels in-use - using them wouldn't work. */
++	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
++		if (i != 4 && request_dma(i, "xen") != 0)
++			BUG();
++#endif /* CONFIG_XEN */
++
++#ifdef CONFIG_X86_GENERICARCH
++	generic_apic_probe();
++#endif
++
++#ifndef CONFIG_XEN
++	early_quirks();
++#endif
++
++	/*
++	 * Read APIC and some other early information from ACPI tables.
++	 */
++	acpi_boot_init();
++
++#if defined(CONFIG_X86_MPPARSE) || defined(CONFIG_X86_VISWS)
++	/*
++	 * get boot-time SMP configuration:
++	 */
++	if (smp_found_config)
++		get_smp_config();
++#endif
++
++	prefill_possible_map();
++#ifdef CONFIG_X86_64
++	init_cpu_to_node();
++#endif
++
++#ifndef CONFIG_XEN
++	init_apic_mappings();
++	ioapic_init_mappings();
++
++	kvm_guest_init();
++
++	e820_reserve_resources();
++	e820_mark_nosave_regions(max_low_pfn);
++#else
++	if (is_initial_xendomain())
++		e820_reserve_resources();
++#endif
++
++#ifdef CONFIG_X86_32
++	if (is_initial_xendomain())
++		request_resource(&iomem_resource, &video_ram_resource);
++#endif
++	reserve_standard_io_resources();
++
++#ifndef CONFIG_XEN
++	e820_setup_gap();
++
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
++		conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++	conswitchp = &dummy_con;
++#endif
++#endif
++#else /* CONFIG_XEN */
++	if (is_initial_xendomain())
++		e820_setup_gap();
++
++	set_iopl.iopl = 1;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++
++#ifdef CONFIG_VT
++#ifdef CONFIG_DUMMY_CONSOLE
++	conswitchp = &dummy_con;
++#endif
++#ifdef CONFIG_VGA_CONSOLE
++	if (is_initial_xendomain())
++		conswitchp = &vga_con;
++#endif
++#endif
++#endif /* CONFIG_XEN */
++}
++
++#ifdef CONFIG_XEN
++static int
++xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++	HYPERVISOR_shutdown(SHUTDOWN_crash);
++	/* we're never actually going to get here... */
++	return NOTIFY_DONE;
++}
++#endif /* !CONFIG_XEN */
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,370 +0,0 @@
+-/* 
+- * 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 <linux/kgdb.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>
+-#include <asm/setup.h>
+-#include <asm/genapic.h>
+-#ifdef CONFIG_XEN
+-#include <asm/hypervisor.h>
+-#endif
+-
+-#ifndef CONFIG_DEBUG_BOOT_PARAMS
+-struct boot_params __initdata boot_params;
+-#else
+-struct boot_params boot_params;
+-#endif
+-
+-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
+-*/ 
+-static int __init nonx_setup(char *str)
+-{
+-	if (!str)
+-		return -EINVAL;
+-	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 0;
+-} 
+-early_param("noexec", nonx_setup);
+-
+-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 (default)
+-off	PROT_READ implies PROT_EXEC
+-*/
+-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);
+-
+-#ifdef CONFIG_XEN
+-static void __init_refok switch_pt(int cpu)
+-{
+-	if (cpu == 0)
+-		xen_init_pt();
+-	xen_pt_switch(__pa_symbol(init_level4_pgt));
+-	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
+-}
+-#define switch_pt() switch_pt(cpu)
+-
+-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)
+-{
+-	load_gdt(gdt_descr);
+-	load_idt(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
+-	/* Memory clobbers used to order PDA accessed */
+-	mb();
+-	wrmsrl(MSR_GS_BASE, pda);
+-	mb();
+-#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) {
+-		/* 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
+-
+-extern asmlinkage void ignore_sysret(void);
+-
+-/* 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); 
+-	wrmsrl(MSR_CSTAR, ignore_sysret);
+-
+-	/* Flags to clear on syscall */
+-	wrmsrl(MSR_SYSCALL_MASK,
+-	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
+-#endif
+-#ifdef CONFIG_IA32_EMULATION   		
+-	syscall32_cpu_init ();
+-#else
+-	{
+-		static const struct callback_register cstar = {
+-			.type = CALLBACKTYPE_syscall32,
+-			.address = (unsigned long)ignore_sysret
+-		};
+-		if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
+-			printk(KERN_WARNING "Unable to register CSTAR callback\n");
+-	}
+-#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;
+-
+-#ifndef CONFIG_X86_NO_TSS
+-/*
+- * Copies of the original ist values from the tss are only accessed during
+- * debugging, no special alignment required.
+- */
+-DEFINE_PER_CPU(struct orig_ist, orig_ist);
+-#endif
+-
+-/*
+- * 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);
+-	}
+-#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(get_cpu_gdt_table(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++) {
+-		static const unsigned int order[N_EXCEPTION_STACKS] = {
+-			[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+-			[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+-		};
+-		if (cpu) {
+-			estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+-			if (!estacks)
+-				panic("Cannot allocate exception stack %ld %d\n",
+-				      v, cpu); 
+-		}
+-		estacks += PAGE_SIZE << order[v];
+-		orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
+-	}
+-
+-	t->x86_tss.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);
+-
+-#ifdef CONFIG_KGDB
+-	/*
+-	 * If the kgdb is connected no debug regs should be altered.  This
+-	 * is only applicable when KGDB and a KGDB I/O module are built
+-	 * into the kernel and you are using early debugging with
+-	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
+-	 */
+-	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
+-		arch_kgdb_ops.correct_hw_break();
+-	else {
+-#endif
+-	/*
+-	 * 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);
+-#ifdef CONFIG_KGDB
+-	/* If the kgdb is connected no debug regs should be altered. */
+-	}
+-#endif
+-
+-	fpu_init(); 
+-
+-	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
+-	if (raw_irqs_disabled())
+-		kernel_eflags &= ~X86_EFLAGS_IF;
+-
+-	if (is_uv_system())
+-		uv_cpu_init();
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1153 +0,0 @@
+-/*
+- *  Copyright (C) 1995  Linus Torvalds
+- *
+- *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+- *
+- *  Memory region support
+- *	David Parsons <orc@pell.chi.il.us>, July-August 1999
+- *
+- *  Added E820 sanitization routine (removes overlapping memory regions);
+- *  Brian Moyle <bmoyle@mvista.com>, February 2001
+- *
+- * Moved CPU detection code to cpu/${cpu}.c
+- *    Patrick Mochel <mochel@osdl.org>, March 2002
+- *
+- *  Provisions for empty E820 memory regions (reported by certain BIOSes).
+- *  Alex Achenbach <xela@slit.de>, December 2002.
+- *
+- */
+-
+-/*
+- * This file handles the architecture-dependent parts of initialization
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/mm.h>
+-#include <linux/mmzone.h>
+-#include <linux/screen_info.h>
+-#include <linux/ioport.h>
+-#include <linux/acpi.h>
+-#include <linux/apm_bios.h>
+-#include <linux/initrd.h>
+-#include <linux/bootmem.h>
+-#include <linux/seq_file.h>
+-#include <linux/console.h>
+-#include <linux/mca.h>
+-#include <linux/root_dev.h>
+-#include <linux/highmem.h>
+-#include <linux/module.h>
+-#include <linux/efi.h>
+-#include <linux/init.h>
+-#include <linux/edd.h>
+-#include <linux/iscsi_ibft.h>
+-#include <linux/nodemask.h>
+-#include <linux/kernel.h>
+-#include <linux/percpu.h>
+-#include <linux/notifier.h>
+-#include <linux/kexec.h>
+-#include <linux/crash_dump.h>
+-#include <linux/dmi.h>
+-#include <linux/pfn.h>
+-#include <linux/pci.h>
+-#include <linux/init_ohci1394_dma.h>
+-#include <linux/kvm_para.h>
+-
+-#include <video/edid.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/apic.h>
+-#include <asm/e820.h>
+-#include <asm/mpspec.h>
+-#include <asm/mmzone.h>
+-#include <asm/setup.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/sections.h>
+-#include <asm/io_apic.h>
+-#include <asm/ist.h>
+-#include <asm/io.h>
+-#include <asm/hypervisor.h>
+-#include <xen/interface/physdev.h>
+-#include <xen/interface/memory.h>
+-#include <xen/features.h>
+-#include <xen/firmware.h>
+-#include <xen/xencons.h>
+-#include <setup_arch.h>
+-#include <asm/bios_ebda.h>
+-#include <asm/cacheflush.h>
+-#include <asm/processor.h>
+-
+-#ifdef CONFIG_XEN
+-#include <xen/interface/kexec.h>
+-#endif
+-
+-static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xen_panic_block = {
+-	xen_panic_event, NULL, 0 /* try to go last */
+-};
+-
+-/*
+- * Machine setup..
+- */
+-static struct resource data_resource = {
+-	.name	= "Kernel data",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource code_resource = {
+-	.name	= "Kernel code",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource bss_resource = {
+-	.name	= "Kernel bss",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource video_ram_resource = {
+-	.name	= "Video RAM area",
+-	.start	= 0xa0000,
+-	.end	= 0xbffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource standard_io_resources[] = { {
+-	.name	= "dma1",
+-	.start	= 0x0000,
+-	.end	= 0x001f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic1",
+-	.start	= 0x0020,
+-	.end	= 0x0021,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer0",
+-	.start	= 0x0040,
+-	.end    = 0x0043,
+-	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer1",
+-	.start  = 0x0050,
+-	.end    = 0x0053,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "keyboard",
+-	.start	= 0x0060,
+-	.end	= 0x0060,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "keyboard",
+-	.start	= 0x0064,
+-	.end	= 0x0064,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma page reg",
+-	.start	= 0x0080,
+-	.end	= 0x008f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic2",
+-	.start	= 0x00a0,
+-	.end	= 0x00a1,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma2",
+-	.start	= 0x00c0,
+-	.end	= 0x00df,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "fpu",
+-	.start	= 0x00f0,
+-	.end	= 0x00ff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-} };
+-
+-/* cpu data as detected by the assembly code in head.S */
+-struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+-/* common cpu data for all cpus */
+-struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+-EXPORT_SYMBOL(boot_cpu_data);
+-
+-unsigned int def_to_bigsmp;
+-
+-#ifndef CONFIG_X86_PAE
+-unsigned long mmu_cr4_features;
+-#else
+-unsigned long mmu_cr4_features = X86_CR4_PAE;
+-#endif
+-
+-/* for MCA, but anyone else can use it if they want */
+-unsigned int machine_id;
+-unsigned int machine_submodel_id;
+-unsigned int BIOS_revision;
+-
+-/* Boot loader ID as an integer, for the benefit of proc_dointvec */
+-int bootloader_type;
+-
+-/* user-defined highmem size */
+-static unsigned int highmem_pages = -1;
+-
+-/*
+- * Setup options
+- */
+-struct screen_info screen_info;
+-EXPORT_SYMBOL(screen_info);
+-struct apm_info apm_info;
+-EXPORT_SYMBOL(apm_info);
+-struct edid_info edid_info;
+-EXPORT_SYMBOL_GPL(edid_info);
+-#ifndef CONFIG_XEN
+-#define copy_edid() (edid_info = boot_params.edid_info)
+-#endif
+-struct ist_info ist_info;
+-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
+-	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+-EXPORT_SYMBOL(ist_info);
+-#endif
+-
+-extern void early_cpu_init(void);
+-extern int root_mountflags;
+-
+-unsigned long saved_video_mode;
+-
+-#define RAMDISK_IMAGE_START_MASK	0x07FF
+-#define RAMDISK_PROMPT_FLAG		0x8000
+-#define RAMDISK_LOAD_FLAG		0x4000
+-
+-static char __initdata command_line[COMMAND_LINE_SIZE];
+-
+-#ifndef CONFIG_DEBUG_BOOT_PARAMS
+-struct boot_params __initdata boot_params;
+-#else
+-struct boot_params boot_params;
+-#endif
+-
+-/*
+- * Point at the empty zero page to start with. We map the real shared_info
+- * page as soon as fixmap is up and running.
+- */
+-shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+-EXPORT_SYMBOL(HYPERVISOR_shared_info);
+-
+-unsigned long *phys_to_machine_mapping;
+-unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[16];
+-EXPORT_SYMBOL(phys_to_machine_mapping);
+-
+-/* Raw start-of-day parameters from the hypervisor. */
+-start_info_t *xen_start_info;
+-EXPORT_SYMBOL(xen_start_info);
+-
+-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+-struct edd edd;
+-#ifdef CONFIG_EDD_MODULE
+-EXPORT_SYMBOL(edd);
+-#endif
+-#ifndef CONFIG_XEN
+-/**
+- * copy_edd() - Copy the BIOS EDD information
+- *              from boot_params into a safe place.
+- *
+- */
+-static inline void copy_edd(void)
+-{
+-     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
+-	    sizeof(edd.mbr_signature));
+-     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
+-     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
+-     edd.edd_info_nr = boot_params.eddbuf_entries;
+-}
+-#endif
+-#else
+-static inline void copy_edd(void)
+-{
+-}
+-#endif
+-
+-int __initdata user_defined_memmap;
+-
+-/*
+- * "mem=nopentium" disables the 4MB page tables.
+- * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+- * to <mem>, overriding the bios size.
+- * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+- * <start> to <start>+<mem>, overriding the bios size.
+- *
+- * HPA tells me bootloaders need to parse mem=, so no new
+- * option should be mem=  [also see Documentation/i386/boot.txt]
+- */
+-static int __init parse_mem(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	if (strcmp(arg, "nopentium") == 0) {
+-		setup_clear_cpu_cap(X86_FEATURE_PSE);
+-	} else {
+-		/* If the user specifies memory size, we
+-		 * limit the BIOS-provided memory map to
+-		 * that size. exactmap can be used to specify
+-		 * the exact map. mem=number can be used to
+-		 * trim the existing memory map.
+-		 */
+-		unsigned long long mem_size;
+-
+-		mem_size = memparse(arg, &arg);
+-		limit_regions(mem_size);
+-		user_defined_memmap = 1;
+-	}
+-	return 0;
+-}
+-early_param("mem", parse_mem);
+-
+-#ifdef CONFIG_PROC_VMCORE
+-/* elfcorehdr= specifies the location of elf core header
+- * stored by the crashed kernel.
+- */
+-static int __init parse_elfcorehdr(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	elfcorehdr_addr = memparse(arg, &arg);
+-	return 0;
+-}
+-early_param("elfcorehdr", parse_elfcorehdr);
+-#endif /* CONFIG_PROC_VMCORE */
+-
+-/*
+- * highmem=size forces highmem to be exactly 'size' bytes.
+- * This works even on boxes that have no highmem otherwise.
+- * This also works to reduce highmem size on bigger boxes.
+- */
+-static int __init parse_highmem(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
+-	return 0;
+-}
+-early_param("highmem", parse_highmem);
+-
+-/*
+- * vmalloc=size forces the vmalloc area to be exactly 'size'
+- * bytes. This can be used to increase (or decrease) the
+- * vmalloc area - the default is 128m.
+- */
+-static int __init parse_vmalloc(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	__VMALLOC_RESERVE = memparse(arg, &arg);
+-	return 0;
+-}
+-early_param("vmalloc", parse_vmalloc);
+-
+-#ifndef CONFIG_XEN
+-/*
+- * reservetop=size reserves a hole at the top of the kernel address space which
+- * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
+- * so relocating the fixmap can be done before paging initialization.
+- */
+-static int __init parse_reservetop(char *arg)
+-{
+-	unsigned long address;
+-
+-	if (!arg)
+-		return -EINVAL;
+-
+-	address = memparse(arg, &arg);
+-	reserve_top_address(address);
+-	return 0;
+-}
+-early_param("reservetop", parse_reservetop);
+-#endif
+-
+-/*
+- * Determine low and high memory ranges:
+- */
+-unsigned long __init find_max_low_pfn(void)
+-{
+-	unsigned long max_low_pfn;
+-
+-	max_low_pfn = max_pfn;
+-	if (max_low_pfn > MAXMEM_PFN) {
+-		if (highmem_pages == -1)
+-			highmem_pages = max_pfn - MAXMEM_PFN;
+-		if (highmem_pages + MAXMEM_PFN < max_pfn)
+-			max_pfn = MAXMEM_PFN + highmem_pages;
+-		if (highmem_pages + MAXMEM_PFN > max_pfn) {
+-			printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
+-			highmem_pages = 0;
+-		}
+-		max_low_pfn = MAXMEM_PFN;
+-#ifndef CONFIG_HIGHMEM
+-		/* Maximum memory usable is what is directly addressable */
+-		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+-					MAXMEM>>20);
+-		if (max_pfn > MAX_NONPAE_PFN)
+-			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
+-		else
+-			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+-		max_pfn = MAXMEM_PFN;
+-#else /* !CONFIG_HIGHMEM */
+-#ifndef CONFIG_HIGHMEM64G
+-		if (max_pfn > MAX_NONPAE_PFN) {
+-			max_pfn = MAX_NONPAE_PFN;
+-			printk(KERN_WARNING "Warning only 4GB will be used.\n");
+-			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
+-		}
+-#endif /* !CONFIG_HIGHMEM64G */
+-#endif /* !CONFIG_HIGHMEM */
+-	} else {
+-		if (highmem_pages == -1)
+-			highmem_pages = 0;
+-#ifdef CONFIG_HIGHMEM
+-		if (highmem_pages >= max_pfn) {
+-			printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
+-			highmem_pages = 0;
+-		}
+-		if (highmem_pages) {
+-			if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
+-				printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
+-				highmem_pages = 0;
+-			}
+-			max_low_pfn -= highmem_pages;
+-		}
+-#else
+-		if (highmem_pages)
+-			printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
+-#endif
+-	}
+-	return max_low_pfn;
+-}
+-
+-#ifndef CONFIG_XEN
+-#define BIOS_LOWMEM_KILOBYTES 0x413
+-
+-/*
+- * The BIOS places the EBDA/XBDA at the top of conventional
+- * memory, and usually decreases the reported amount of
+- * conventional memory (int 0x12) too. This also contains a
+- * workaround for Dell systems that neglect to reserve EBDA.
+- * The same workaround also avoids a problem with the AMD768MPX
+- * chipset: reserve a page before VGA to prevent PCI prefetch
+- * into it (errata #56). Usually the page is reserved anyways,
+- * unless you have no PS/2 mouse plugged in.
+- */
+-static void __init reserve_ebda_region(void)
+-{
+-	unsigned int lowmem, ebda_addr;
+-
+-	/* To determine the position of the EBDA and the */
+-	/* end of conventional memory, we need to look at */
+-	/* the BIOS data area. In a paravirtual environment */
+-	/* that area is absent. We'll just have to assume */
+-	/* that the paravirt case can handle memory setup */
+-	/* correctly, without our help. */
+-	if (paravirt_enabled())
+-		return;
+-
+-	/* end of low (conventional) memory */
+-	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
+-	lowmem <<= 10;
+-
+-	/* start of EBDA area */
+-	ebda_addr = get_bios_ebda();
+-
+-	/* Fixup: bios puts an EBDA in the top 64K segment */
+-	/* of conventional memory, but does not adjust lowmem. */
+-	if ((lowmem - ebda_addr) <= 0x10000)
+-		lowmem = ebda_addr;
+-
+-	/* Fixup: bios does not report an EBDA at all. */
+-	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
+-	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
+-		lowmem = 0x9f000;
+-
+-	/* Paranoia: should never happen, but... */
+-	if ((lowmem == 0) || (lowmem >= 0x100000))
+-		lowmem = 0x9f000;
+-
+-	/* reserve all memory between lowmem and the 1MB mark */
+-	reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
+-}
+-#endif
+-
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+-static void __init setup_bootmem_allocator(void);
+-static unsigned long __init setup_memory(void)
+-{
+-	/*
+-	 * partially used pages are not usable - thus
+-	 * we are rounding upwards:
+-	 */
+- 	min_low_pfn = PFN_UP(__pa(xen_start_info->pt_base)) +
+-		xen_start_info->nr_pt_frames;
+-
+-	max_low_pfn = find_max_low_pfn();
+-
+-#ifdef CONFIG_HIGHMEM
+-	highstart_pfn = highend_pfn = max_pfn;
+-	if (max_pfn > max_low_pfn) {
+-		highstart_pfn = max_low_pfn;
+-	}
+-	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+-		pages_to_mb(highend_pfn - highstart_pfn));
+-	num_physpages = highend_pfn;
+-	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+-#else
+-	num_physpages = max_low_pfn;
+-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+-#endif
+-#ifdef CONFIG_FLATMEM
+-	max_mapnr = num_physpages;
+-#endif
+-	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+-			pages_to_mb(max_low_pfn));
+-
+-	setup_bootmem_allocator();
+-
+-	return max_low_pfn;
+-}
+-
+-static void __init zone_sizes_init(void)
+-{
+-	unsigned long max_zone_pfns[MAX_NR_ZONES];
+-	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+-	max_zone_pfns[ZONE_DMA] =
+-		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+-	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+-#ifdef CONFIG_HIGHMEM
+-	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
+-	add_active_range(0, 0, min(xen_start_info->nr_pages, highend_pfn));
+-	add_active_range(0, highend_pfn, highend_pfn);
+-#else
+-	add_active_range(0, 0, min(xen_start_info->nr_pages, max_low_pfn));
+-	add_active_range(0, max_low_pfn, max_low_pfn);
+-#endif
+-
+-	free_area_init_nodes(max_zone_pfns);
+-}
+-#else
+-extern unsigned long __init setup_memory(void);
+-extern void zone_sizes_init(void);
+-#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+-
+-static inline unsigned long long get_total_mem(void)
+-{
+-	unsigned long long total;
+-
+-	total = max_low_pfn - min_low_pfn;
+-#ifdef CONFIG_HIGHMEM
+-	total += highend_pfn - highstart_pfn;
+-#endif
+-
+-	return total << PAGE_SHIFT;
+-}
+-
+-#ifdef CONFIG_KEXEC
+-#ifndef CONFIG_XEN
+-static void __init reserve_crashkernel(void)
+-{
+-	unsigned long long total_mem;
+-	unsigned long long crash_size, crash_base;
+-	int ret;
+-
+-	total_mem = get_total_mem();
+-
+-	ret = parse_crashkernel(boot_command_line, total_mem,
+-			&crash_size, &crash_base);
+-	if (ret == 0 && crash_size > 0) {
+-		if (crash_base > 0) {
+-			printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+-					"for crashkernel (System RAM: %ldMB)\n",
+-					(unsigned long)(crash_size >> 20),
+-					(unsigned long)(crash_base >> 20),
+-					(unsigned long)(total_mem >> 20));
+-
+-			if (reserve_bootmem(crash_base, crash_size,
+-					BOOTMEM_EXCLUSIVE) < 0) {
+-				printk(KERN_INFO "crashkernel reservation "
+-					"failed - memory is in use\n");
+-				return;
+-			}
+-
+-			crashk_res.start = crash_base;
+-			crashk_res.end   = crash_base + crash_size - 1;
+-		} else
+-			printk(KERN_INFO "crashkernel reservation failed - "
+-					"you have to specify a base address\n");
+-	}
+-}
+-#else
+-#define reserve_crashkernel xen_machine_kexec_setup_resources
+-#endif
+-#else
+-static inline void __init reserve_crashkernel(void)
+-{}
+-#endif
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-
+-static bool do_relocate_initrd = false;
+-
+-static void __init reserve_initrd(void)
+-{
+-	unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
+-	unsigned long ramdisk_size  = xen_start_info->mod_len;
+-	unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+-	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+-	unsigned long ramdisk_here;
+-
+-	initrd_start = 0;
+-
+-	if (!xen_start_info->mod_start || !ramdisk_size)
+-		return;		/* No initrd provided by bootloader */
+-
+-	if (ramdisk_end < ramdisk_image) {
+-		printk(KERN_ERR "initrd wraps around end of memory, "
+-		       "disabling initrd\n");
+-		return;
+-	}
+-	if (ramdisk_size >= end_of_lowmem/2) {
+-		printk(KERN_ERR "initrd too large to handle, "
+-		       "disabling initrd\n");
+-		return;
+-	}
+-	if (ramdisk_end <= end_of_lowmem) {
+-		/* All in lowmem, easy case */
+-		reserve_bootmem(ramdisk_image, ramdisk_size, BOOTMEM_DEFAULT);
+-		initrd_start = ramdisk_image + PAGE_OFFSET;
+-		initrd_end = initrd_start+ramdisk_size;
+-		return;
+-	}
+-
+-	/* We need to move the initrd down into lowmem */
+-	ramdisk_here = (end_of_lowmem - ramdisk_size) & PAGE_MASK;
+-
+-	/* Note: this includes all the lowmem currently occupied by
+-	   the initrd, we rely on that fact to keep the data intact. */
+-	reserve_bootmem(ramdisk_here, ramdisk_size, BOOTMEM_DEFAULT);
+-	initrd_start = ramdisk_here + PAGE_OFFSET;
+-	initrd_end   = initrd_start + ramdisk_size;
+-
+-	do_relocate_initrd = true;
+-}
+-
+-#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
+-
+-static void __init relocate_initrd(void)
+-{
+-	unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+-	unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
+-	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+-	unsigned long ramdisk_here;
+-	unsigned long slop, clen, mapaddr;
+-	char *p, *q;
+-
+-	if (!do_relocate_initrd)
+-		return;
+-
+-	ramdisk_here = initrd_start - PAGE_OFFSET;
+-
+-	q = (char *)initrd_start;
+-
+-	/* Copy any lowmem portion of the initrd */
+-	if (ramdisk_image < end_of_lowmem) {
+-		clen = end_of_lowmem - ramdisk_image;
+-		p = (char *)__va(ramdisk_image);
+-		memcpy(q, p, clen);
+-		q += clen;
+-		ramdisk_image += clen;
+-		ramdisk_size  -= clen;
+-	}
+-
+-	/* Copy the highmem portion of the initrd */
+-	while (ramdisk_size) {
+-		slop = ramdisk_image & ~PAGE_MASK;
+-		clen = ramdisk_size;
+-		if (clen > MAX_MAP_CHUNK-slop)
+-			clen = MAX_MAP_CHUNK-slop;
+-		mapaddr = ramdisk_image & PAGE_MASK;
+-		p = early_ioremap(mapaddr, clen+slop);
+-		memcpy(q, p+slop, clen);
+-		early_iounmap(p, clen+slop);
+-		q += clen;
+-		ramdisk_image += clen;
+-		ramdisk_size  -= clen;
+-	}
+-}
+-
+-#endif /* CONFIG_BLK_DEV_INITRD */
+-
+-void __init setup_bootmem_allocator(void)
+-{
+-	unsigned long bootmap_size;
+-	/*
+-	 * Initialize the boot-time allocator (with low memory only):
+-	 */
+-	bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);
+-
+-	register_bootmem_low_pages(max_low_pfn);
+-
+-	/*
+-	 * Reserve the bootmem bitmap itself as well. We do this in two
+-	 * steps (first step was init_bootmem()) because this catches
+-	 * the (very unlikely) case of us accidentally initializing the
+-	 * bootmem allocator with an invalid RAM area.
+-	 */
+-	reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
+-			 bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text),
+-			 BOOTMEM_DEFAULT);
+-
+-#ifndef CONFIG_XEN
+-	/*
+-	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+-	 * enabling clean reboots, SMP operation, laptop functions.
+-	 */
+-	reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+-
+-	/* reserve EBDA region */
+-	reserve_ebda_region();
+-
+-#ifdef CONFIG_SMP
+-	/*
+-	 * But first pinch a few for the stack/trampoline stuff
+-	 * FIXME: Don't need the extra page at 4K, but need to fix
+-	 * trampoline before removing it. (see the GDT stuff)
+-	 */
+-	reserve_bootmem(PAGE_SIZE, PAGE_SIZE, BOOTMEM_DEFAULT);
+-#endif
+-#ifdef CONFIG_ACPI_SLEEP
+-	/*
+-	 * Reserve low memory region for sleep support.
+-	 */
+-	acpi_reserve_bootmem();
+-#endif
+-#endif /* !CONFIG_XEN */
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	reserve_initrd();
+-#endif
+-	numa_kva_reserve();
+-	reserve_crashkernel();
+-
+-	reserve_ibft_region();
+-}
+-
+-/*
+- * The node 0 pgdat is initialized before all of these because
+- * it's needed for bootmem.  node>0 pgdats have their virtual
+- * space allocated before the pagetables are in place to access
+- * them, so they can't be cleared then.
+- *
+- * This should all compile down to nothing when NUMA is off.
+- */
+-static void __init remapped_pgdat_init(void)
+-{
+-	int nid;
+-
+-	for_each_online_node(nid) {
+-		if (nid != 0)
+-			memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+-	}
+-}
+-
+-#ifdef CONFIG_MCA
+-static void set_mca_bus(int x)
+-{
+-	MCA_bus = x;
+-}
+-#else
+-static void set_mca_bus(int x) { }
+-#endif
+-
+-/* Overridden in paravirt.c if CONFIG_PARAVIRT */
+-char * __init __attribute__((weak)) memory_setup(void)
+-{
+-	return machine_specific_memory_setup();
+-}
+-
+-#ifdef CONFIG_NUMA
+-/*
+- * In the golden day, when everything among i386 and x86_64 will be
+- * integrated, this will not live here
+- */
+-void *x86_cpu_to_node_map_early_ptr;
+-int x86_cpu_to_node_map_init[NR_CPUS] = {
+-	[0 ... NR_CPUS-1] = NUMA_NO_NODE
+-};
+-DEFINE_PER_CPU(int, x86_cpu_to_node_map) = NUMA_NO_NODE;
+-#endif
+-
+-/*
+- * Determine if we were loaded by an EFI loader.  If so, then we have also been
+- * passed the efi memmap, systab, etc., so we should use these data structures
+- * for initialization.  Note, the efi init code path is determined by the
+- * global efi_enabled. This allows the same kernel image to be used on existing
+- * systems (with a traditional BIOS) as well as on EFI systems.
+- */
+-void __init setup_arch(char **cmdline_p)
+-{
+-	int i, j, k, fpp;
+-	struct physdev_set_iopl set_iopl;
+-	unsigned long max_low_pfn;
+-	unsigned long p2m_pages;
+-
+-	/* Force a quick death if the kernel panics (not domain 0). */
+-	extern int panic_timeout;
+-	if (!panic_timeout && !is_initial_xendomain())
+-		panic_timeout = 1;
+-
+-	/* Register a call for panic conditions. */
+-	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+-
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_4gb_segments));
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_writable_pagetables));
+-
+-	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+-	pre_setup_arch_hook();
+-	early_cpu_init();
+-	early_ioremap_init();
+-#ifdef CONFIG_SMP
+-	prefill_possible_map();
+-#endif
+-
+-#ifdef CONFIG_EFI
+-	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
+-		     "EL32", 4))
+-		efi_enabled = 1;
+-#endif
+-
+-	/* This must be initialized to UNNAMED_MAJOR for ipconfig to work
+-	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
+-	*/
+-	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
+-	screen_info = boot_params.screen_info;
+-	copy_edid();
+-	apm_info.bios = boot_params.apm_bios_info;
+-	ist_info = boot_params.ist_info;
+-	saved_video_mode = boot_params.hdr.vid_mode;
+-	if( boot_params.sys_desc_table.length != 0 ) {
+-		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+-		machine_id = boot_params.sys_desc_table.table[0];
+-		machine_submodel_id = boot_params.sys_desc_table.table[1];
+-		BIOS_revision = boot_params.sys_desc_table.table[2];
+-	}
+-	bootloader_type = boot_params.hdr.type_of_loader;
+-
+-	if (is_initial_xendomain()) {
+-		const struct dom0_vga_console_info *info =
+-			(void *)((char *)xen_start_info +
+-			         xen_start_info->console.dom0.info_off);
+-
+-		dom0_init_screen_info(info,
+-		                      xen_start_info->console.dom0.info_size);
+-		xen_start_info->console.domU.mfn = 0;
+-		xen_start_info->console.domU.evtchn = 0;
+-	} else
+-		screen_info.orig_video_isVGA = 0;
+-
+-#ifdef CONFIG_BLK_DEV_RAM
+-	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+-	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+-	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+-#endif
+-
+-	ARCH_SETUP
+-
+-	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-	print_memory_map(memory_setup());
+-
+-	copy_edd();
+-
+-	if (!boot_params.hdr.root_flags)
+-		root_mountflags &= ~MS_RDONLY;
+-	init_mm.start_code = (unsigned long) _text;
+-	init_mm.end_code = (unsigned long) _etext;
+-	init_mm.end_data = (unsigned long) _edata;
+-	init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
+-		       xen_start_info->nr_pt_frames) << PAGE_SHIFT;
+-
+-	code_resource.start = virt_to_phys(_text);
+-	code_resource.end = virt_to_phys(_etext)-1;
+-	data_resource.start = virt_to_phys(_etext);
+-	data_resource.end = virt_to_phys(_edata)-1;
+-	bss_resource.start = virt_to_phys(&__bss_start);
+-	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+-
+-	if ((i = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
+-		i = COMMAND_LINE_SIZE;
+-	memcpy(boot_command_line, xen_start_info->cmd_line, i);
+-	boot_command_line[i - 1] = '\0';
+-	parse_early_param();
+-
+-	if (user_defined_memmap) {
+-		printk(KERN_INFO "user-defined physical RAM map:\n");
+-		print_memory_map("user");
+-	}
+-
+-	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+-	*cmdline_p = command_line;
+-
+-	if (efi_enabled)
+-		efi_init();
+-
+-	/* update e820 for memory not covered by WB MTRRs */
+-	propagate_e820_map();
+-	mtrr_bp_init();
+-#ifndef CONFIG_XEN
+-	if (mtrr_trim_uncached_memory(max_pfn))
+-		propagate_e820_map();
+-#endif
+-
+-	max_low_pfn = setup_memory();
+-
+-#ifdef CONFIG_KVM_CLOCK
+-	kvmclock_init();
+-#endif
+-
+-#ifdef CONFIG_VMI
+-	/*
+-	 * Must be after max_low_pfn is determined, and before kernel
+-	 * pagetables are setup.
+-	 */
+-	vmi_init();
+-#endif
+-	kvm_guest_init();
+-
+-	/*
+-	 * NOTE: before this point _nobody_ is allowed to allocate
+-	 * any memory using the bootmem allocator.  Although the
+-	 * allocator is now initialised only the first 8Mb of the kernel
+-	 * virtual address space has been mapped.  All allocations before
+-	 * paging_init() has completed must use the alloc_bootmem_low_pages()
+-	 * variant (which allocates DMA'able memory) and care must be taken
+-	 * not to exceed the 8Mb limit.
+-	 */
+-
+-#ifdef CONFIG_SMP
+-	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+-#endif
+-	paging_init();
+-
+-	/*
+-	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
+-	 */
+-
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	if (init_ohci1394_dma_early)
+-		init_ohci1394_dma_on_all_controllers();
+-#endif
+-
+-	remapped_pgdat_init();
+-	sparse_init();
+-	zone_sizes_init();
+-
+-#ifdef CONFIG_X86_FIND_SMP_CONFIG
+-	/*
+-	 * Find and reserve possible boot-time SMP configuration:
+-	 */
+-	find_smp_config();
+-#endif
+-
+-	p2m_pages = max_pfn;
+-	if (xen_start_info->nr_pages > max_pfn) {
+-		/*
+-		 * the max_pfn was shrunk (probably by mem= or highmem=
+-		 * kernel parameter); shrink reservation with the HV
+-		 */
+-		struct xen_memory_reservation reservation = {
+-			.address_bits = 0,
+-			.extent_order = 0,
+-			.domid = DOMID_SELF
+-		};
+-		unsigned int difference;
+-		int ret;
+-
+-		difference = xen_start_info->nr_pages - max_pfn;
+-
+-		set_xen_guest_handle(reservation.extent_start,
+-				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
+-		reservation.nr_extents = difference;
+-		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+-					   &reservation);
+-		BUG_ON (ret != difference);
+-	}
+-	else if (max_pfn > xen_start_info->nr_pages)
+-		p2m_pages = xen_start_info->nr_pages;
+-
+-	/* Make sure we have a correctly sized P->M table. */
+-	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-		phys_to_machine_mapping = alloc_bootmem_low_pages(
+-		     max_pfn * sizeof(unsigned long));
+-		memset(phys_to_machine_mapping, ~0,
+-		       max_pfn * sizeof(unsigned long));
+-		memcpy(phys_to_machine_mapping,
+-		       (unsigned long *)xen_start_info->mfn_list,
+-		       p2m_pages * sizeof(unsigned long));
+-		free_bootmem(
+-		     __pa(xen_start_info->mfn_list),
+-		     PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+-				     sizeof(unsigned long))));
+-
+-		/*
+-		 * Initialise the list of the frames that specify the list of
+-		 * frames that make up the p2m table. Used by save/restore
+-		 */
+-		pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
+-
+-		fpp = PAGE_SIZE/sizeof(unsigned long);
+-		for (i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++) {
+-			if ((j % fpp) == 0) {
+-				k++;
+-				BUG_ON(k>=16);
+-				pfn_to_mfn_frame_list[k] =
+-					alloc_bootmem_low_pages(PAGE_SIZE);
+-				pfn_to_mfn_frame_list_list[k] =
+-					virt_to_mfn(pfn_to_mfn_frame_list[k]);
+-				j=0;
+-			}
+-			pfn_to_mfn_frame_list[k][j] =
+-				virt_to_mfn(&phys_to_machine_mapping[i]);
+-		}
+-		HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+-		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+-		     virt_to_mfn(pfn_to_mfn_frame_list_list);
+-	}
+-
+-	/* Mark all ISA DMA channels in-use - using them wouldn't work. */
+-	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
+-		if (i != 4 && request_dma(i, "xen") != 0)
+-			BUG();
+-
+-	/*
+-	 * NOTE: at this point the bootmem allocator is fully available.
+-	 */
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	relocate_initrd();
+-#endif
+-
+-	paravirt_post_allocator_init();
+-
+-	if (is_initial_xendomain())
+-		dmi_scan_machine();
+-
+-	io_delay_init();
+-
+-#if defined(CONFIG_X86_SMP) && !defined(CONFIG_XEN)
+-	/*
+-	 * setup to use the early static init tables during kernel startup
+-	 * X86_SMP will exclude sub-arches that don't deal well with it.
+-	 */
+-	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
+-	x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
+-#ifdef CONFIG_NUMA
+-	x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
+-#endif
+-#endif
+-
+-#ifdef CONFIG_X86_GENERICARCH
+-	generic_apic_probe();
+-#endif
+-
+-	set_iopl.iopl = 1;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+-
+-#ifdef CONFIG_ACPI
+-	if (!is_initial_xendomain()) {
+-		printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
+-		acpi_disabled = 1;
+-		acpi_ht = 0;
+-	}
+-
+-	/*
+-	 * Parse the ACPI tables for possible boot-time SMP configuration.
+-	 */
+-	acpi_boot_table_init();
+-#endif
+-
+-#ifndef CONFIG_XEN
+-	early_quirks();
+-#endif
+-
+-#ifdef CONFIG_ACPI
+-	acpi_boot_init();
+-
+-#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
+-	if (def_to_bigsmp)
+-		printk(KERN_WARNING "More than 8 CPUs detected and "
+-			"CONFIG_X86_PC cannot handle it.\nUse "
+-			"CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
+-#endif
+-#endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	if (smp_found_config)
+-		get_smp_config();
+-#endif
+-
+-	e820_register_memory();
+-	e820_mark_nosave_regions();
+-
+-	if (is_initial_xendomain()) {
+-#ifdef CONFIG_VT
+-#if defined(CONFIG_VGA_CONSOLE)
+-		if (!efi_enabled ||
+-		    (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+-			conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-		conswitchp = &dummy_con;
+-#endif
+-#endif
+-	} else {
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-		conswitchp = &dummy_con;
+-#endif
+-	}
+-}
+-
+-static int
+-xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+-	HYPERVISOR_shutdown(SHUTDOWN_crash);
+-	/* we're never actually going to get here... */
+-	return NOTIFY_DONE;
+-}
+-
+-/*
+- * Request address space for all standard resources
+- *
+- * This is called just before pcibios_init(), which is also a
+- * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
+- */
+-static int __init request_standard_resources(void)
+-{
+-	int i;
+-
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return 0;
+-
+-	printk(KERN_INFO "Setting up standard PCI resources\n");
+-	init_iomem_resources(&code_resource, &data_resource, &bss_resource);
+-
+-	request_resource(&iomem_resource, &video_ram_resource);
+-
+-	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+-		request_resource(&ioport_resource, &standard_io_resources[i]);
+-	return 0;
+-}
+-
+-subsys_initcall(request_standard_resources);
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1434 +0,0 @@
+-/*
+- *  Copyright (C) 1995  Linus Torvalds
+- */
+-
+-/*
+- * This file handles the architecture-dependent parts of initialization
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/stddef.h>
+-#include <linux/unistd.h>
+-#include <linux/ptrace.h>
+-#include <linux/slab.h>
+-#include <linux/user.h>
+-#include <linux/screen_info.h>
+-#include <linux/ioport.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/initrd.h>
+-#include <linux/highmem.h>
+-#include <linux/bootmem.h>
+-#include <linux/module.h>
+-#include <asm/processor.h>
+-#include <linux/console.h>
+-#include <linux/seq_file.h>
+-#include <linux/crash_dump.h>
+-#include <linux/root_dev.h>
+-#include <linux/pci.h>
+-#include <asm/pci-direct.h>
+-#include <linux/efi.h>
+-#include <linux/acpi.h>
+-#include <linux/kallsyms.h>
+-#include <linux/edd.h>
+-#include <linux/iscsi_ibft.h>
+-#include <linux/mmzone.h>
+-#include <linux/kexec.h>
+-#include <linux/cpufreq.h>
+-#include <linux/dmi.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/ctype.h>
+-#include <linux/sort.h>
+-#include <linux/uaccess.h>
+-#include <linux/init_ohci1394_dma.h>
+-#include <linux/kvm_para.h>
+-
+-#include <asm/mtrr.h>
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/vsyscall.h>
+-#include <asm/io.h>
+-#include <asm/smp.h>
+-#include <asm/msr.h>
+-#include <asm/desc.h>
+-#include <video/edid.h>
+-#include <asm/e820.h>
+-#include <asm/dma.h>
+-#include <asm/gart.h>
+-#include <asm/mpspec.h>
+-#include <asm/mmu_context.h>
+-#include <asm/proto.h>
+-#include <asm/setup.h>
+-#include <asm/numa.h>
+-#include <asm/sections.h>
+-#include <asm/dmi.h>
+-#include <asm/cacheflush.h>
+-#include <asm/mce.h>
+-#include <asm/ds.h>
+-#include <asm/topology.h>
+-#include <asm/pat.h>
+-
+-#include <mach_apic.h>
+-#ifdef CONFIG_XEN
+-#include <linux/percpu.h>
+-#include <xen/interface/physdev.h>
+-#include "setup_arch_pre.h"
+-#include <asm/hypervisor.h>
+-#include <xen/interface/nmi.h>
+-#include <xen/features.h>
+-#include <xen/firmware.h>
+-#include <xen/xencons.h>
+-#define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+-#define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
+-#include <asm/mach-xen/setup_arch_post.h>
+-#include <xen/interface/memory.h>
+-
+-#ifdef CONFIG_XEN
+-#include <xen/interface/kexec.h>
+-#endif
+-
+-extern unsigned long start_pfn;
+-extern struct edid_info edid_info;
+-
+-shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+-EXPORT_SYMBOL(HYPERVISOR_shared_info);
+-
+-static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+-static struct notifier_block xen_panic_block = {
+-	xen_panic_event, NULL, 0 /* try to go last */
+-};
+-
+-unsigned long *phys_to_machine_mapping;
+-unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512];
+-
+-EXPORT_SYMBOL(phys_to_machine_mapping);
+-
+-DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]);
+-DEFINE_PER_CPU(int, nr_multicall_ents);
+-
+-/* Raw start-of-day parameters from the hypervisor. */
+-start_info_t *xen_start_info;
+-EXPORT_SYMBOL(xen_start_info);
+-#endif
+-
+-/*
+- * Machine setup..
+- */
+-
+-struct cpuinfo_x86 boot_cpu_data __read_mostly;
+-EXPORT_SYMBOL(boot_cpu_data);
+-
+-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+-
+-unsigned long mmu_cr4_features;
+-
+-/* Boot loader ID as an integer, for the benefit of proc_dointvec */
+-int bootloader_type;
+-
+-unsigned long saved_video_mode;
+-
+-int force_mwait __cpuinitdata;
+-
+-/*
+- * Early DMI memory
+- */
+-int dmi_alloc_index;
+-char dmi_alloc_data[DMI_MAX_DATA];
+-
+-/*
+- * Setup options
+- */
+-struct screen_info screen_info;
+-EXPORT_SYMBOL(screen_info);
+-struct sys_desc_table_struct {
+-	unsigned short length;
+-	unsigned char table[0];
+-};
+-
+-struct edid_info edid_info;
+-EXPORT_SYMBOL_GPL(edid_info);
+-
+-extern int root_mountflags;
+-
+-char __initdata command_line[COMMAND_LINE_SIZE];
+-
+-static struct resource standard_io_resources[] = {
+-	{ .name = "dma1", .start = 0x00, .end = 0x1f,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .name = "pic1", .start = 0x20, .end = 0x21,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .name = "timer0", .start = 0x40, .end = 0x43,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .name = "timer1", .start = 0x50, .end = 0x53,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .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 },
+-	{ .name = "pic2", .start = 0xa0, .end = 0xa1,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .name = "dma2", .start = 0xc0, .end = 0xdf,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+-	{ .name = "fpu", .start = 0xf0, .end = 0xff,
+-		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
+-};
+-
+-#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
+-
+-static struct resource data_resource = {
+-	.name = "Kernel data",
+-	.start = 0,
+-	.end = 0,
+-	.flags = IORESOURCE_RAM,
+-};
+-static struct resource code_resource = {
+-	.name = "Kernel code",
+-	.start = 0,
+-	.end = 0,
+-	.flags = IORESOURCE_RAM,
+-};
+-static struct resource bss_resource = {
+-	.name = "Kernel bss",
+-	.start = 0,
+-	.end = 0,
+-	.flags = IORESOURCE_RAM,
+-};
+-
+-static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
+-
+-#ifdef CONFIG_PROC_VMCORE
+-/* elfcorehdr= specifies the location of elf core header
+- * stored by the crashed kernel. This option will be passed
+- * by kexec loader to the capture kernel.
+- */
+-static int __init setup_elfcorehdr(char *arg)
+-{
+-	char *end;
+-	if (!arg)
+-		return -EINVAL;
+-	elfcorehdr_addr = memparse(arg, &end);
+-	return end > arg ? 0 : -EINVAL;
+-}
+-early_param("elfcorehdr", setup_elfcorehdr);
+-#endif
+-
+-#ifndef CONFIG_NUMA
+-static void __init
+-contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+-{
+-	unsigned long bootmap_size, bootmap;
+-
+-	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+-	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
+-				 PAGE_SIZE);
+-	if (bootmap == -1L)
+-		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+-	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+-	e820_register_active_regions(0, start_pfn, end_pfn);
+-#ifdef CONFIG_XEN
+-	if (xen_start_info->nr_pages < end_pfn)
+-		end_pfn = xen_start_info->nr_pages;
+-#endif
+-	free_bootmem_with_active_regions(0, end_pfn);
+-	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
+-	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+-}
+-#endif
+-
+-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+-struct edd edd;
+-#ifdef CONFIG_EDD_MODULE
+-EXPORT_SYMBOL(edd);
+-#endif
+-#ifndef CONFIG_XEN
+-/**
+- * copy_edd() - Copy the BIOS EDD information
+- *              from boot_params into a safe place.
+- *
+- */
+-static inline void copy_edd(void)
+-{
+-     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
+-	    sizeof(edd.mbr_signature));
+-     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
+-     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
+-     edd.edd_info_nr = boot_params.eddbuf_entries;
+-}
+-#endif
+-#else
+-static inline void copy_edd(void)
+-{
+-}
+-#endif
+-
+-#ifdef CONFIG_KEXEC
+-#ifndef CONFIG_XEN
+-static void __init reserve_crashkernel(void)
+-{
+-	unsigned long long total_mem;
+-	unsigned long long crash_size, crash_base;
+-	int ret;
+-
+-	total_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+-
+-	ret = parse_crashkernel(boot_command_line, total_mem,
+-			&crash_size, &crash_base);
+-	if (ret == 0 && crash_size) {
+-		if (crash_base <= 0) {
+-			printk(KERN_INFO "crashkernel reservation failed - "
+-					"you have to specify a base address\n");
+-			return;
+-		}
+-
+-		if (reserve_bootmem(crash_base, crash_size,
+-					BOOTMEM_EXCLUSIVE) < 0) {
+-			printk(KERN_INFO "crashkernel reservation failed - "
+-					"memory is in use\n");
+-			return;
+-		}
+-
+-		printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+-				"for crashkernel (System RAM: %ldMB)\n",
+-				(unsigned long)(crash_size >> 20),
+-				(unsigned long)(crash_base >> 20),
+-				(unsigned long)(total_mem >> 20));
+-		crashk_res.start = crash_base;
+-		crashk_res.end   = crash_base + crash_size - 1;
+-		insert_resource(&iomem_resource, &crashk_res);
+-	}
+-}
+-#else
+-#define reserve_crashkernel xen_machine_kexec_setup_resources
+-#endif
+-#else
+-static inline void __init reserve_crashkernel(void)
+-{}
+-#endif
+-
+-/* Overridden in paravirt.c if CONFIG_PARAVIRT */
+-void __attribute__((weak)) __init memory_setup(void)
+-{
+-       machine_specific_memory_setup();
+-}
+-
+-static void __init parse_setup_data(void)
+-{
+-	struct setup_data *data;
+-	unsigned long pa_data;
+-
+-	if (boot_params.hdr.version < 0x0209)
+-		return;
+-	pa_data = boot_params.hdr.setup_data;
+-	while (pa_data) {
+-		data = early_ioremap(pa_data, PAGE_SIZE);
+-		switch (data->type) {
+-		default:
+-			break;
+-		}
+-#ifndef CONFIG_DEBUG_BOOT_PARAMS
+-		free_early(pa_data, pa_data+sizeof(*data)+data->len);
+-#endif
+-		pa_data = data->next;
+-		early_iounmap(data, PAGE_SIZE);
+-	}
+-}
+-
+-#ifdef CONFIG_PCI_MMCONFIG
+-extern void __cpuinit fam10h_check_enable_mmcfg(void);
+-extern void __init check_enable_amd_mmconf_dmi(void);
+-#else
+-void __cpuinit fam10h_check_enable_mmcfg(void)
+-{
+-}
+-void __init check_enable_amd_mmconf_dmi(void)
+-{
+-}
+-#endif
+-
+-/*
+- * setup_arch - architecture-specific boot-time initializations
+- *
+- * Note: On x86_64, fixmaps are ready for use even before this is called.
+- */
+-void __init setup_arch(char **cmdline_p)
+-{
+-	unsigned i;
+-
+-#ifdef CONFIG_XEN
+-	extern struct e820map machine_e820;
+-
+-	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+-
+-	/* Register a call for panic conditions. */
+-	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+-
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_writable_pagetables));
+-
+-	early_ioremap_init();
+-
+- 	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); 
+-	screen_info = boot_params.screen_info;
+-
+-	if (is_initial_xendomain()) {
+-		const struct dom0_vga_console_info *info =
+-			(void *)((char *)xen_start_info +
+-			         xen_start_info->console.dom0.info_off);
+-
+-		dom0_init_screen_info(info,
+-		                      xen_start_info->console.dom0.info_size);
+-		xen_start_info->console.domU.mfn = 0;
+-		xen_start_info->console.domU.evtchn = 0;
+-	} else
+-		screen_info.orig_video_isVGA = 0;
+-
+-	copy_edid();
+-#else
+-	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+-
+-	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
+-	screen_info = boot_params.screen_info;
+-	edid_info = boot_params.edid_info;
+-#endif	/* !CONFIG_XEN */
+-	saved_video_mode = boot_params.hdr.vid_mode;
+-	bootloader_type = boot_params.hdr.type_of_loader;
+-
+-#ifdef CONFIG_BLK_DEV_RAM
+-	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+-	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+-	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+-#endif
+-#ifdef CONFIG_EFI
+-	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
+-		     "EL64", 4))
+-		efi_enabled = 1;
+-#endif
+-
+-	ARCH_SETUP
+-
+-	memory_setup();
+-	copy_edd();
+-
+-	if (!boot_params.hdr.root_flags)
+-		root_mountflags &= ~MS_RDONLY;
+-	init_mm.start_code = (unsigned long) &_text;
+-	init_mm.end_code = (unsigned long) &_etext;
+-	init_mm.end_data = (unsigned long) &_edata;
+-	init_mm.brk = (unsigned long) &_end;
+-
+-	code_resource.start = virt_to_phys(&_text);
+-	code_resource.end = virt_to_phys(&_etext)-1;
+-	data_resource.start = virt_to_phys(&_etext);
+-	data_resource.end = virt_to_phys(&_edata)-1;
+-	bss_resource.start = virt_to_phys(&__bss_start);
+-	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+-
+-	early_identify_cpu(&boot_cpu_data);
+-
+-	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+-	*cmdline_p = command_line;
+-
+-	parse_setup_data();
+-
+-	parse_early_param();
+-
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	if (init_ohci1394_dma_early)
+-		init_ohci1394_dma_on_all_controllers();
+-#endif
+-
+-	finish_e820_parsing();
+-
+-#ifndef CONFIG_XEN
+-	/* after parse_early_param, so could debug it */
+-	insert_resource(&iomem_resource, &code_resource);
+-	insert_resource(&iomem_resource, &data_resource);
+-	insert_resource(&iomem_resource, &bss_resource);
+-#endif
+-
+-	early_gart_iommu_check();
+-
+-	e820_register_active_regions(0, 0, -1UL);
+-	/*
+-	 * partially used pages are not usable - thus
+-	 * we are rounding upwards:
+-	 */
+-	end_pfn = e820_end_of_ram();
+-	/* update e820 for memory not covered by WB MTRRs */
+-	mtrr_bp_init();
+-#ifndef CONFIG_XEN
+-	if (mtrr_trim_uncached_memory(end_pfn)) {
+-		e820_register_active_regions(0, 0, -1UL);
+-		end_pfn = e820_end_of_ram();
+-	}
+-#endif
+-
+-	num_physpages = end_pfn;
+-	max_mapnr = end_pfn;
+-
+-	check_efer();
+-
+-	max_pfn_mapped = init_memory_mapping(0, (max_pfn_mapped << PAGE_SHIFT));
+-	if (efi_enabled)
+-		efi_init();
+-
+-#ifndef CONFIG_XEN
+-	vsmp_init();
+-#endif
+-
+-	if (is_initial_xendomain())
+-		dmi_scan_machine();
+-
+-	io_delay_init();
+-
+-#ifdef CONFIG_KVM_CLOCK
+-	kvmclock_init();
+-#endif
+-
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-	/* setup to use the early static init tables during kernel startup */
+-	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
+-	x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
+-#ifdef CONFIG_NUMA
+-	x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
+-#endif
+-#endif
+-
+-	/* How many end-of-memory variables you have, grandma! */
+-	max_low_pfn = end_pfn;
+-	max_pfn = end_pfn;
+-	high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
+-
+-	/* Remove active ranges so rediscovery with NUMA-awareness happens */
+-	remove_all_active_ranges();
+-
+-#ifdef CONFIG_ACPI_NUMA
+-	/*
+-	 * Parse SRAT to discover nodes.
+-	 */
+-	acpi_numa_init();
+-#endif
+-
+-#ifdef CONFIG_NUMA
+-	numa_initmem_init(0, end_pfn);
+-#else
+-	contig_initmem_init(0, end_pfn);
+-#endif
+-
+-#ifndef CONFIG_XEN
+-	dma32_reserve_bootmem();
+-
+-#ifdef CONFIG_ACPI_SLEEP
+-	/*
+-	 * Reserve low memory region for sleep support.
+-	 */
+-       acpi_reserve_bootmem();
+-#endif
+-
+-	if (efi_enabled)
+-		efi_reserve_bootmem();
+-#endif
+-
+-#ifdef CONFIG_BLK_DEV_INITRD
+-#ifdef CONFIG_XEN
+-	if (xen_start_info->mod_start) {
+-		unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
+-		unsigned long ramdisk_size  = xen_start_info->mod_len;
+-#else
+-	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+-		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+-		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
+-#endif
+-		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+-		unsigned long end_of_mem    = end_pfn << PAGE_SHIFT;
+-
+-		if (ramdisk_end <= end_of_mem) {
+-			/*
+-			 * don't need to reserve again, already reserved early
+-			 * in x86_64_start_kernel, and early_res_to_bootmem
+-			 * convert that to reserved in bootmem
+-			 */
+-			initrd_start = ramdisk_image + PAGE_OFFSET;
+-			initrd_end = initrd_start+ramdisk_size;
+-#ifdef CONFIG_XEN
+-			initrd_below_start_ok = 1;
+-#endif
+-		} else {
+-			free_bootmem(ramdisk_image, ramdisk_size);
+-			printk(KERN_ERR "initrd extends beyond end of memory "
+-			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-			       ramdisk_end, end_of_mem);
+-			initrd_start = 0;
+-		}
+-	}
+-#endif
+-	reserve_crashkernel();
+-
+-	reserve_ibft_region();
+-
+-	paging_init();
+-	map_vsyscall();
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	/*
+-	* Find and reserve possible boot-time SMP configuration:
+-	*/
+-	find_smp_config();
+-#endif
+-#ifdef CONFIG_XEN
+-	{
+-		int i, j, k, fpp;
+-		unsigned long p2m_pages;
+-
+-		p2m_pages = end_pfn;
+-		if (xen_start_info->nr_pages > end_pfn) {
+-			/*
+-			 * the end_pfn was shrunk (probably by mem= or highmem=
+-			 * kernel parameter); shrink reservation with the HV
+-			 */
+-			struct xen_memory_reservation reservation = {
+-				.address_bits = 0,
+-				.extent_order = 0,
+-				.domid = DOMID_SELF
+-			};
+-			unsigned int difference;
+-			int ret;
+-			
+-			difference = xen_start_info->nr_pages - end_pfn;
+-			
+-			set_xen_guest_handle(reservation.extent_start,
+-					     ((unsigned long *)xen_start_info->mfn_list) + end_pfn);
+-			reservation.nr_extents = difference;
+-			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+-						   &reservation);
+-			BUG_ON (ret != difference);
+-		}
+-		else if (end_pfn > xen_start_info->nr_pages)
+-			p2m_pages = xen_start_info->nr_pages;
+-
+-		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-			/* Make sure we have a large enough P->M table. */
+-			phys_to_machine_mapping = alloc_bootmem_pages(
+-				end_pfn * sizeof(unsigned long));
+-			memset(phys_to_machine_mapping, ~0,
+-			       end_pfn * sizeof(unsigned long));
+-			memcpy(phys_to_machine_mapping,
+-			       (unsigned long *)xen_start_info->mfn_list,
+-			       p2m_pages * sizeof(unsigned long));
+-			free_bootmem(
+-				__pa(xen_start_info->mfn_list),
+-				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+-						sizeof(unsigned long))));
+-
+-			/*
+-			 * Initialise the list of the frames that specify the
+-			 * list of frames that make up the p2m table. Used by
+-                         * save/restore.
+-			 */
+-			pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE);
+-
+-			fpp = PAGE_SIZE/sizeof(unsigned long);
+-			for (i=0, j=0, k=-1; i< end_pfn; i+=fpp, j++) {
+-				if ((j % fpp) == 0) {
+-					k++;
+-					BUG_ON(k>=fpp);
+-					pfn_to_mfn_frame_list[k] =
+-						alloc_bootmem_pages(PAGE_SIZE);
+-					pfn_to_mfn_frame_list_list[k] =
+-						virt_to_mfn(pfn_to_mfn_frame_list[k]);
+-					j=0;
+-				}
+-				pfn_to_mfn_frame_list[k][j] =
+-					virt_to_mfn(&phys_to_machine_mapping[i]);
+-			}
+-			HYPERVISOR_shared_info->arch.max_pfn = end_pfn;
+-			HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+-				virt_to_mfn(pfn_to_mfn_frame_list_list);
+-		}
+-
+-		/* Mark all ISA DMA channels in-use - using them wouldn't work. */
+-		for (i = 0; i < MAX_DMA_CHANNELS; ++i)
+-			if (i != 4 && request_dma(i, "xen") != 0)
+-				BUG();
+-	}
+-
+-#ifdef CONFIG_ACPI
+-	if (!is_initial_xendomain()) {
+-		acpi_disabled = 1;
+-		acpi_ht = 0;
+-	}
+-#endif
+-#endif
+-
+-#ifndef CONFIG_XEN
+-	early_quirks();
+-#endif
+-
+-#ifdef CONFIG_ACPI
+-	/*
+-	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
+-	 * Call this early for SRAT node setup.
+-	 */
+-	acpi_boot_table_init();
+-
+-	/*
+-	 * Read APIC and some other early information from ACPI tables.
+-	 */
+-	acpi_boot_init();
+-#endif
+-
+-	init_cpu_to_node();
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	/*
+-	 * get boot-time SMP configuration:
+-	 */
+-	if (smp_found_config)
+-		get_smp_config();
+-#ifndef CONFIG_XEN
+-	init_apic_mappings();
+-	ioapic_init_mappings();
+-#endif
+-#endif
+-#if defined(CONFIG_XEN) && defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
+-	prefill_possible_map();
+-#endif
+-
+-	kvm_guest_init();
+-
+-	/*
+-	 * We trust e820 completely. No explicit ROM probing in memory.
+-	 */
+-#ifdef CONFIG_XEN
+-	if (is_initial_xendomain())
+-		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
+-#else
+-	e820_reserve_resources(e820.map, e820.nr_map);
+-	e820_mark_nosave_regions();
+-#endif
+-
+-	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+-		request_resource(&ioport_resource, &standard_io_resources[i]);
+-
+-#ifdef CONFIG_XEN
+-	if (is_initial_xendomain())
+-		e820_setup_gap(machine_e820.map, machine_e820.nr_map);
+-#else
+-	e820_setup_gap(e820.map, e820.nr_map);
+-#endif
+-
+-#ifdef CONFIG_XEN
+-	{
+-		struct physdev_set_iopl set_iopl;
+-
+-		set_iopl.iopl = 1;
+-		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+-
+-		if (is_initial_xendomain()) {
+-#ifdef CONFIG_VT
+-#if defined(CONFIG_VGA_CONSOLE)
+-			conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-			conswitchp = &dummy_con;
+-#endif
+-#endif
+-		} else {
+-#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+-			conswitchp = &dummy_con;
+-#endif
+-                }
+-	}
+-#else	/* CONFIG_XEN */
+-
+-#ifdef CONFIG_VT
+-#if defined(CONFIG_VGA_CONSOLE)
+-	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+-		conswitchp = &vga_con;
+-#elif defined(CONFIG_DUMMY_CONSOLE)
+-	conswitchp = &dummy_con;
+-#endif
+-#endif
+-
+-#endif /* !CONFIG_XEN */
+-
+-	/* do this before identify_cpu for boot cpu */
+-	check_enable_amd_mmconf_dmi();
+-}
+-
+-#ifdef CONFIG_XEN
+-static int
+-xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+-	HYPERVISOR_shutdown(SHUTDOWN_crash);
+-	/* we're never actually going to get here... */
+-	return NOTIFY_DONE;
+-}
+-#endif /* !CONFIG_XEN */
+-
+-
+-static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+-{
+-	unsigned int *v;
+-
+-	if (c->extended_cpuid_level < 0x80000004)
+-		return 0;
+-
+-	v = (unsigned int *) c->x86_model_id;
+-	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+-	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+-	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+-	c->x86_model_id[48] = 0;
+-	return 1;
+-}
+-
+-
+-static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+-{
+-	unsigned int n, dummy, eax, ebx, ecx, edx;
+-
+-	n = c->extended_cpuid_level;
+-
+-	if (n >= 0x80000005) {
+-		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
+-		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
+-		       "D cache %dK (%d bytes/line)\n",
+-		       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size = (ecx>>24) + (edx>>24);
+-		/* On K8 L1 TLB is inclusive, so don't count it */
+-		c->x86_tlbsize = 0;
+-	}
+-
+-	if (n >= 0x80000006) {
+-		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
+-		ecx = cpuid_ecx(0x80000006);
+-		c->x86_cache_size = ecx >> 16;
+-		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
+-
+-		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+-		c->x86_cache_size, ecx & 0xFF);
+-	}
+-	if (n >= 0x80000008) {
+-		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy);
+-		c->x86_virt_bits = (eax >> 8) & 0xff;
+-		c->x86_phys_bits = eax & 0xff;
+-	}
+-}
+-
+-#ifdef CONFIG_NUMA
+-static int __cpuinit nearby_node(int apicid)
+-{
+-	int i, node;
+-
+-	for (i = apicid - 1; i >= 0; i--) {
+-		node = apicid_to_node[i];
+-		if (node != NUMA_NO_NODE && node_online(node))
+-			return node;
+-	}
+-	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+-		node = apicid_to_node[i];
+-		if (node != NUMA_NO_NODE && node_online(node))
+-			return node;
+-	}
+-	return first_node(node_online_map); /* Shouldn't happen */
+-}
+-#endif
+-
+-/*
+- * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
+- * Assumes number of cores is a power of two.
+- */
+-static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+-{
+-#ifdef CONFIG_SMP
+-	unsigned bits;
+-#ifdef CONFIG_NUMA
+-	int cpu = smp_processor_id();
+-	int node = 0;
+-	unsigned apicid = hard_smp_processor_id();
+-#endif
+-	bits = c->x86_coreid_bits;
+-
+-	/* Low order bits define the core id (index of core in socket) */
+-	c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
+-	/* Convert the initial APIC ID into the socket ID */
+-	c->phys_proc_id = c->initial_apicid >> bits;
+-
+-#ifdef CONFIG_NUMA
+-	node = c->phys_proc_id;
+-	if (apicid_to_node[apicid] != NUMA_NO_NODE)
+-		node = apicid_to_node[apicid];
+-	if (!node_online(node)) {
+-		/* Two possibilities here:
+-		   - The CPU is missing memory and no node was created.
+-		   In that case try picking one from a nearby CPU
+-		   - The APIC IDs differ from the HyperTransport node IDs
+-		   which the K8 northbridge parsing fills in.
+-		   Assume they are all increased by a constant offset,
+-		   but in the same order as the HT nodeids.
+-		   If that doesn't result in a usable node fall back to the
+-		   path for the previous case.  */
+-
+-		int ht_nodeid = c->initial_apicid;
+-
+-		if (ht_nodeid >= 0 &&
+-		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+-			node = apicid_to_node[ht_nodeid];
+-		/* Pick a nearby node */
+-		if (!node_online(node))
+-			node = nearby_node(apicid);
+-	}
+-	numa_set_node(cpu, node);
+-
+-	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+-#endif
+-#endif
+-}
+-
+-static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
+-{
+-#ifdef CONFIG_SMP
+-	unsigned bits, ecx;
+-
+-	/* Multi core CPU? */
+-	if (c->extended_cpuid_level < 0x80000008)
+-		return;
+-
+-	ecx = cpuid_ecx(0x80000008);
+-
+-	c->x86_max_cores = (ecx & 0xff) + 1;
+-
+-	/* CPU telling us the core id bits shift? */
+-	bits = (ecx >> 12) & 0xF;
+-
+-	/* Otherwise recompute */
+-	if (bits == 0) {
+-		while ((1 << bits) < c->x86_max_cores)
+-			bits++;
+-	}
+-
+-	c->x86_coreid_bits = bits;
+-
+-#endif
+-}
+-
+-#define ENABLE_C1E_MASK		0x18000000
+-#define CPUID_PROCESSOR_SIGNATURE	1
+-#define CPUID_XFAM		0x0ff00000
+-#define CPUID_XFAM_K8		0x00000000
+-#define CPUID_XFAM_10H		0x00100000
+-#define CPUID_XFAM_11H		0x00200000
+-#define CPUID_XMOD		0x000f0000
+-#define CPUID_XMOD_REV_F	0x00040000
+-
+-#ifndef CONFIG_XEN
+-/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
+-static __cpuinit int amd_apic_timer_broken(void)
+-{
+-	u32 lo, hi, eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
+-
+-	switch (eax & CPUID_XFAM) {
+-	case CPUID_XFAM_K8:
+-		if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
+-			break;
+-	case CPUID_XFAM_10H:
+-	case CPUID_XFAM_11H:
+-		rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
+-		if (lo & ENABLE_C1E_MASK)
+-			return 1;
+-		break;
+-	default:
+-		/* err on the side of caution */
+-		return 1;
+-	}
+-	return 0;
+-}
+-#endif
+-
+-static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
+-{
+-	early_init_amd_mc(c);
+-
+- 	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
+-	if (c->x86_power & (1<<8))
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+-}
+-
+-static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+-{
+-	unsigned level;
+-
+-#ifdef CONFIG_SMP
+-	unsigned long value;
+-
+-	/*
+-	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
+-	 * bit 6 of msr C001_0015
+-	 *
+-	 * Errata 63 for SH-B3 steppings
+-	 * Errata 122 for all steppings (F+ have it disabled by default)
+-	 */
+-	if (c->x86 == 15) {
+-		rdmsrl(MSR_K8_HWCR, value);
+-		value |= 1 << 6;
+-		wrmsrl(MSR_K8_HWCR, value);
+-	}
+-#endif
+-
+-	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+-	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_cpu_cap(c, 0*32+31);
+-
+-	/* On C+ stepping K8 rep microcode works well for copy/memset */
+-	level = cpuid_eax(1);
+-	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
+-			     level >= 0x0f58))
+-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+-	if (c->x86 == 0x10 || c->x86 == 0x11)
+-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+-
+-	/* Enable workaround for FXSAVE leak */
+-	if (c->x86 >= 6)
+-		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
+-
+-	level = get_model_name(c);
+-	if (!level) {
+-		switch (c->x86) {
+-		case 15:
+-			/* Should distinguish Models here, but this is only
+-			   a fallback anyways. */
+-			strcpy(c->x86_model_id, "Hammer");
+-			break;
+-		}
+-	}
+-	display_cacheinfo(c);
+-
+-	/* Multi core CPU? */
+-	if (c->extended_cpuid_level >= 0x80000008)
+-		amd_detect_cmp(c);
+-
+-	if (c->extended_cpuid_level >= 0x80000006 &&
+-		(cpuid_edx(0x80000006) & 0xf000))
+-		num_cache_leaves = 4;
+-	else
+-		num_cache_leaves = 3;
+-
+-	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
+-		set_cpu_cap(c, X86_FEATURE_K8);
+-
+-	/* MFENCE stops RDTSC speculation */
+-	set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+-
+-	if (c->x86 == 0x10)
+-		fam10h_check_enable_mmcfg();
+-
+-#ifndef CONFIG_XEN
+-	if (amd_apic_timer_broken())
+-		disable_apic_timer = 1;
+-
+-	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
+-		unsigned long long tseg;
+-
+-		/*
+-		 * Split up direct mapping around the TSEG SMM area.
+-		 * Don't do it for gbpages because there seems very little
+-		 * benefit in doing so.
+-		 */
+-		if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg) &&
+-		(tseg >> PMD_SHIFT) < (max_pfn_mapped >> (PMD_SHIFT-PAGE_SHIFT)))
+-			set_memory_4k((unsigned long)__va(tseg), 1);
+-	}
+-#endif
+-}
+-
+-void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+-{
+-#ifdef CONFIG_SMP
+-	u32 eax, ebx, ecx, edx;
+-	int index_msb, core_bits;
+-
+-	cpuid(1, &eax, &ebx, &ecx, &edx);
+-
+-
+-	if (!cpu_has(c, X86_FEATURE_HT))
+-		return;
+-	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+-		goto out;
+-
+-	smp_num_siblings = (ebx & 0xff0000) >> 16;
+-
+-	if (smp_num_siblings == 1) {
+-		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1) {
+-
+-		if (smp_num_siblings > NR_CPUS) {
+-			printk(KERN_WARNING "CPU: Unsupported number of "
+-			       "siblings %d", smp_num_siblings);
+-			smp_num_siblings = 1;
+-			return;
+-		}
+-
+-		index_msb = get_count_order(smp_num_siblings);
+-		c->phys_proc_id = phys_pkg_id(index_msb);
+-
+-		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+-
+-		index_msb = get_count_order(smp_num_siblings);
+-
+-		core_bits = get_count_order(c->x86_max_cores);
+-
+-		c->cpu_core_id = phys_pkg_id(index_msb) &
+-					       ((1 << core_bits) - 1);
+-	}
+-out:
+-	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+-		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+-		       c->phys_proc_id);
+-		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+-		       c->cpu_core_id);
+-	}
+-
+-#endif
+-}
+-
+-/*
+- * find out the number of processor cores on the die
+- */
+-static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
+-{
+-	unsigned int eax, t;
+-
+-	if (c->cpuid_level < 4)
+-		return 1;
+-
+-	cpuid_count(4, 0, &eax, &t, &t, &t);
+-
+-	if (eax & 0x1f)
+-		return ((eax >> 26) + 1);
+-	else
+-		return 1;
+-}
+-
+-static void __cpuinit srat_detect_node(void)
+-{
+-#ifdef CONFIG_NUMA
+-	unsigned node;
+-	int cpu = smp_processor_id();
+-	int apicid = hard_smp_processor_id();
+-
+-	/* Don't do the funky fallback heuristics the AMD version employs
+-	   for now. */
+-	node = apicid_to_node[apicid];
+-	if (node == NUMA_NO_NODE || !node_online(node))
+-		node = first_node(node_online_map);
+-	numa_set_node(cpu, node);
+-
+-	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+-#endif
+-}
+-
+-static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
+-{
+-	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+-	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+-}
+-
+-static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+-{
+-	/* Cache sizes */
+-	unsigned n;
+-
+-	init_intel_cacheinfo(c);
+-	if (c->cpuid_level > 9) {
+-		unsigned eax = cpuid_eax(10);
+-		/* Check for version and the number of counters */
+-		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+-			set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
+-	}
+-
+-	if (cpu_has_ds) {
+-		unsigned int l1, l2;
+-		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+-		if (!(l1 & (1<<11)))
+-			set_cpu_cap(c, X86_FEATURE_BTS);
+-		if (!(l1 & (1<<12)))
+-			set_cpu_cap(c, X86_FEATURE_PEBS);
+-	}
+-
+-
+-	if (cpu_has_bts)
+-		ds_init_intel(c);
+-
+-	n = c->extended_cpuid_level;
+-	if (n >= 0x80000008) {
+-		unsigned eax = cpuid_eax(0x80000008);
+-		c->x86_virt_bits = (eax >> 8) & 0xff;
+-		c->x86_phys_bits = eax & 0xff;
+-		/* CPUID workaround for Intel 0F34 CPU */
+-		if (c->x86_vendor == X86_VENDOR_INTEL &&
+-		    c->x86 == 0xF && c->x86_model == 0x3 &&
+-		    c->x86_mask == 0x4)
+-			c->x86_phys_bits = 36;
+-	}
+-
+-	if (c->x86 == 15)
+-		c->x86_cache_alignment = c->x86_clflush_size * 2;
+-	if (c->x86 == 6)
+-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+-	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+-	c->x86_max_cores = intel_num_cpu_cores(c);
+-
+-	srat_detect_node();
+-}
+-
+-static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c)
+-{
+-	if (c->x86 == 0x6 && c->x86_model >= 0xf)
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+-}
+-
+-static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
+-{
+-	/* Cache sizes */
+-	unsigned n;
+-
+-	n = c->extended_cpuid_level;
+-	if (n >= 0x80000008) {
+-		unsigned eax = cpuid_eax(0x80000008);
+-		c->x86_virt_bits = (eax >> 8) & 0xff;
+-		c->x86_phys_bits = eax & 0xff;
+-	}
+-
+-	if (c->x86 == 0x6 && c->x86_model >= 0xf) {
+-		c->x86_cache_alignment = c->x86_clflush_size * 2;
+-		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+-	}
+-	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
+-}
+-
+-static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+-{
+-	char *v = c->x86_vendor_id;
+-
+-	if (!strcmp(v, "AuthenticAMD"))
+-		c->x86_vendor = X86_VENDOR_AMD;
+-	else if (!strcmp(v, "GenuineIntel"))
+-		c->x86_vendor = X86_VENDOR_INTEL;
+-	else if (!strcmp(v, "CentaurHauls"))
+-		c->x86_vendor = X86_VENDOR_CENTAUR;
+-	else
+-		c->x86_vendor = X86_VENDOR_UNKNOWN;
+-}
+-
+-/* Do some early cpuid on the boot CPU to get some parameter that are
+-   needed before check_bugs. Everything advanced is in identify_cpu
+-   below. */
+-static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+-{
+-	u32 tfms, xlvl;
+-
+-	c->loops_per_jiffy = loops_per_jiffy;
+-	c->x86_cache_size = -1;
+-	c->x86_vendor = X86_VENDOR_UNKNOWN;
+-	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+-	c->x86_vendor_id[0] = '\0'; /* Unset */
+-	c->x86_model_id[0] = '\0';  /* Unset */
+-	c->x86_clflush_size = 64;
+-	c->x86_cache_alignment = c->x86_clflush_size;
+-	c->x86_max_cores = 1;
+-	c->x86_coreid_bits = 0;
+-	c->extended_cpuid_level = 0;
+-	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+-
+-	/* Get vendor name */
+-	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+-	      (unsigned int *)&c->x86_vendor_id[0],
+-	      (unsigned int *)&c->x86_vendor_id[8],
+-	      (unsigned int *)&c->x86_vendor_id[4]);
+-
+-	get_cpu_vendor(c);
+-
+-	/* Initialize the standard set of capabilities */
+-	/* Note that the vendor-specific code below might override */
+-
+-	/* Intel-defined flags: level 0x00000001 */
+-	if (c->cpuid_level >= 0x00000001) {
+-		__u32 misc;
+-		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
+-		      &c->x86_capability[0]);
+-		c->x86 = (tfms >> 8) & 0xf;
+-		c->x86_model = (tfms >> 4) & 0xf;
+-		c->x86_mask = tfms & 0xf;
+-		if (c->x86 == 0xf)
+-			c->x86 += (tfms >> 20) & 0xff;
+-		if (c->x86 >= 0x6)
+-			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+-			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+-	} else {
+-		/* Have CPUID level 0 only - unheard of */
+-		c->x86 = 4;
+-	}
+-
+-	c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
+-#ifdef CONFIG_SMP
+-	c->phys_proc_id = c->initial_apicid;
+-#endif
+-	/* AMD-defined flags: level 0x80000001 */
+-	xlvl = cpuid_eax(0x80000000);
+-	c->extended_cpuid_level = xlvl;
+-	if ((xlvl & 0xffff0000) == 0x80000000) {
+-		if (xlvl >= 0x80000001) {
+-			c->x86_capability[1] = cpuid_edx(0x80000001);
+-			c->x86_capability[6] = cpuid_ecx(0x80000001);
+-		}
+-		if (xlvl >= 0x80000004)
+-			get_model_name(c); /* Default name */
+-	}
+-
+-	/* Transmeta-defined flags: level 0x80860001 */
+-	xlvl = cpuid_eax(0x80860000);
+-	if ((xlvl & 0xffff0000) == 0x80860000) {
+-		/* Don't set x86_cpuid_level here for now to not confuse. */
+-		if (xlvl >= 0x80860001)
+-			c->x86_capability[2] = cpuid_edx(0x80860001);
+-	}
+-
+-	c->extended_cpuid_level = cpuid_eax(0x80000000);
+-	if (c->extended_cpuid_level >= 0x80000007)
+-		c->x86_power = cpuid_edx(0x80000007);
+-
+-	switch (c->x86_vendor) {
+-	case X86_VENDOR_AMD:
+-		early_init_amd(c);
+-		break;
+-	case X86_VENDOR_INTEL:
+-		early_init_intel(c);
+-		break;
+-	case X86_VENDOR_CENTAUR:
+-		early_init_centaur(c);
+-		break;
+-	}
+-
+-	validate_pat_support(c);
+-}
+-
+-/*
+- * This does the hard work of actually picking apart the CPU stuff...
+- */
+-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+-{
+-	int i;
+-
+-	early_identify_cpu(c);
+-
+-	init_scattered_cpuid_features(c);
+-
+-#ifndef CONFIG_XEN
+-	c->apicid = phys_pkg_id(0);
+-#endif
+-
+-	/*
+-	 * Vendor-specific initialization.  In this section we
+-	 * canonicalize the feature flags, meaning if there are
+-	 * features a certain CPU supports which CPUID doesn't
+-	 * tell us, CPUID claiming incorrect flags, or other bugs,
+-	 * we handle them here.
+-	 *
+-	 * At the end of this section, c->x86_capability better
+-	 * indicate the features this CPU genuinely supports!
+-	 */
+-	switch (c->x86_vendor) {
+-	case X86_VENDOR_AMD:
+-		init_amd(c);
+-		break;
+-
+-	case X86_VENDOR_INTEL:
+-		init_intel(c);
+-		break;
+-
+-	case X86_VENDOR_CENTAUR:
+-		init_centaur(c);
+-		break;
+-
+-	case X86_VENDOR_UNKNOWN:
+-	default:
+-		display_cacheinfo(c);
+-		break;
+-	}
+-
+-	detect_ht(c);
+-
+-	/*
+-	 * On SMP, boot_cpu_data holds the common feature set between
+-	 * all CPUs; so make sure that we indicate which features are
+-	 * common between the CPUs.  The first time this routine gets
+-	 * executed, c == &boot_cpu_data.
+-	 */
+-	if (c != &boot_cpu_data) {
+-		/* AND the already accumulated flags with these */
+-		for (i = 0; i < NCAPINTS; i++)
+-			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+-	}
+-
+-	/* Clear all flags overriden by options */
+-	for (i = 0; i < NCAPINTS; i++)
+-		c->x86_capability[i] &= ~cleared_cpu_caps[i];
+-
+-#ifdef CONFIG_X86_MCE
+-	mcheck_init(c);
+-#endif
+-	select_idle_routine(c);
+-
+-#ifdef CONFIG_NUMA
+-	numa_add_cpu(smp_processor_id());
+-#endif
+-
+-}
+-
+-void __cpuinit identify_boot_cpu(void)
+-{
+-	identify_cpu(&boot_cpu_data);
+-}
+-
+-void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+-{
+-	BUG_ON(c == &boot_cpu_data);
+-	identify_cpu(c);
+-	mtrr_ap_init();
+-}
+-
+-static __init int setup_noclflush(char *arg)
+-{
+-	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+-	return 1;
+-}
+-__setup("noclflush", setup_noclflush);
+-
+-void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+-{
+-	if (c->x86_model_id[0])
+-		printk(KERN_CONT "%s", c->x86_model_id);
+-
+-	if (c->x86_mask || c->cpuid_level >= 0)
+-		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
+-	else
+-		printk(KERN_CONT "\n");
+-}
+-
+-static __init int setup_disablecpuid(char *arg)
+-{
+-	int bit;
+-	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+-		setup_clear_cpu_cap(bit);
+-	else
+-		return 0;
+-	return 1;
+-}
+-__setup("clearcpuid=", setup_disablecpuid);
+--- head-2010-01-18.orig/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -121,132 +121,14 @@ void xen_smp_send_reschedule(int cpu)
+ 	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+ }
+ 
+-/*
+- * Structure and data for smp_call_function(). This is designed to minimise
+- * static memory requirements. It also looks cleaner.
+- */
+-static DEFINE_SPINLOCK(call_lock);
+-
+-struct call_data_struct {
+-	void (*func) (void *info);
+-	void *info;
+-	atomic_t started;
+-	atomic_t finished;
+-	int wait;
+-};
+-
+-void lock_ipi_call_lock(void)
++void xen_send_call_func_single_ipi(int cpu)
+ {
+-	spin_lock_irq(&call_lock);
++	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNC_SINGLE_VECTOR);
+ }
+ 
+-void unlock_ipi_call_lock(void)
++void xen_send_call_func_ipi(cpumask_t mask)
+ {
+-	spin_unlock_irq(&call_lock);
+-}
+-
+-static struct call_data_struct *call_data;
+-
+-static void __smp_call_function(void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
+-{
+-	struct call_data_struct data;
+-	int cpus = num_online_cpus() - 1;
+-
+-	if (!cpus)
+-		return;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	mb();
+-
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-}
+-
+-
+-/**
+- * smp_call_function_mask(): Run a function on a set of other CPUs.
+- * @mask: The set of cpus to run on.  Must not include the current cpu.
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @wait: If true, wait (atomically) until function has completed on other CPUs.
+- *
+-  * Returns 0 on success, else a negative status code.
+- *
+- * If @wait is true, then returns once @func has returned; otherwise
+- * it returns just before the target cpu calls @func.
+- *
+- * You must not call this function with disabled interrupts or from a
+- * hardware interrupt handler or from a bottom half handler.
+- */
+-int
+-xen_smp_call_function_mask(cpumask_t mask,
+-			      void (*func)(void *), void *info,
+-			      int wait)
+-{
+-	struct call_data_struct data;
+-	cpumask_t allbutself;
+-	int cpus;
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	/* Holding any lock stops cpus from going down. */
+-	spin_lock(&call_lock);
+-
+-	allbutself = cpu_online_map;
+-	cpu_clear(smp_processor_id(), allbutself);
+-
+-	cpus_and(mask, mask, allbutself);
+-	cpus = cpus_weight(mask);
+-
+-	if (!cpus) {
+-		spin_unlock(&call_lock);
+-		return 0;
+-	}
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	wmb();
+-
+-	/* Send a message to other CPUs */
+-	if (cpus_equal(mask, allbutself) &&
+-	    cpus_equal(cpu_online_map, cpu_callout_map))
+-		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-	else
+-		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (wait)
+-		while (atomic_read(&data.finished) != cpus)
+-			cpu_relax();
+-	spin_unlock(&call_lock);
+-
+-	return 0;
++	send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+ }
+ 
+ static void stop_this_cpu(void *dummy)
+@@ -268,15 +150,10 @@ static void stop_this_cpu(void *dummy)
+ 
+ void xen_smp_send_stop(void)
+ {
+-	int nolock;
+ 	unsigned long flags;
+ 
+-	/* Don't deadlock on the call lock in panic */
+-	nolock = !spin_trylock(&call_lock);
++	smp_call_function(stop_this_cpu, NULL, 0);
+ 	local_irq_save(flags);
+-	__smp_call_function(stop_this_cpu, NULL, 0, 0);
+-	if (!nolock)
+-		spin_unlock(&call_lock);
+ 	disable_all_local_evtchn();
+ 	local_irq_restore(flags);
+ }
+@@ -298,21 +175,8 @@ irqreturn_t smp_reschedule_interrupt(int
+ 
+ irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
+ {
+-	void (*func) (void *info) = call_data->func;
+-	void *info = call_data->info;
+-	int wait = call_data->wait;
+-
+-	/*
+-	 * Notify initiating CPU that I've grabbed the data and am
+-	 * about to execute the function
+-	 */
+-	mb();
+-	atomic_inc(&call_data->started);
+-	/*
+-	 * At this point the info structure may be out of scope unless wait==1
+-	 */
+ 	irq_enter();
+-	(*func)(info);
++	generic_smp_call_function_interrupt();
+ #ifdef CONFIG_X86_32
+ 	__get_cpu_var(irq_stat).irq_call_count++;
+ #else
+@@ -320,10 +184,19 @@ irqreturn_t smp_call_function_interrupt(
+ #endif
+ 	irq_exit();
+ 
+-	if (wait) {
+-		mb();
+-		atomic_inc(&call_data->finished);
+-	}
++	return IRQ_HANDLED;
++}
++
++irqreturn_t smp_call_function_single_interrupt(int irq, void *dev_id)
++{
++	irq_enter();
++	generic_smp_call_function_single_interrupt();
++#ifdef CONFIG_X86_32
++	__get_cpu_var(irq_stat).irq_call_count++;
++#else
++	add_pda(irq_call_count, 1);
++#endif
++	irq_exit();
+ 
+ 	return IRQ_HANDLED;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:33:19.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:33:38.000000000 +0100
+@@ -450,7 +450,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 
+ 	/* Keep nmi watchdog up to date */
+ #ifdef __i386__
+-	per_cpu(irq_stat, smp_processor_id()).irq0_irqs++;
++	x86_add_percpu(irq_stat.irq0_irqs, 1);
+ #else
+ 	add_pda(irq0_irqs, 1);
+ #endif
+@@ -738,9 +738,7 @@ void __init time_init(void)
+ 
+ 	update_wallclock();
+ 
+-#ifndef CONFIG_X86_64
+ 	use_tsc_delay();
+-#endif
+ 
+ 	/* Cannot request_irq() until kmem is initialised. */
+ 	late_time_init = setup_cpu0_timer_irq;
+@@ -797,7 +795,8 @@ static void stop_hz_timer(void)
+ 
+ 	/* Leave ourselves in tick mode if rcu or softirq or timer pending. */
+ 	if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
+-	    (j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
++	    (j = get_next_timer_interrupt(jiffies),
++	     time_before_eq(j, jiffies))) {
+ 		cpu_clear(cpu, nohz_cpu_mask);
+ 		j = jiffies + 1;
+ 	}
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1,5 +1,6 @@
+ /*
+  *  Copyright (C) 1991, 1992  Linus Torvalds
++ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+  *
+  *  Pentium III FXSR, SSE support
+  *	Gareth Hughes <gareth@valinux.com>, May 2000
+@@ -57,11 +58,10 @@
+ #include <asm/nmi.h>
+ #include <asm/smp.h>
+ #include <asm/io.h>
++#include <asm/traps.h>
+ 
+ #include "mach_traps.h"
+ 
+-int panic_on_unrecovered_nmi;
+-
+ #ifndef CONFIG_XEN
+ DECLARE_BITMAP(used_vectors, NR_VECTORS);
+ EXPORT_SYMBOL_GPL(used_vectors);
+@@ -82,43 +82,22 @@ gate_desc idt_table[256]
+ 	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
+ #endif
+ 
+-asmlinkage void divide_error(void);
+-asmlinkage void debug(void);
+-asmlinkage void nmi(void);
+-asmlinkage void int3(void);
+-asmlinkage void overflow(void);
+-asmlinkage void bounds(void);
+-asmlinkage void invalid_op(void);
+-asmlinkage void device_not_available(void);
+-asmlinkage void coprocessor_segment_overrun(void);
+-asmlinkage void invalid_TSS(void);
+-asmlinkage void segment_not_present(void);
+-asmlinkage void stack_segment(void);
+-asmlinkage void general_protection(void);
+-asmlinkage void page_fault(void);
+-asmlinkage void coprocessor_error(void);
+-asmlinkage void simd_coprocessor_error(void);
+-asmlinkage void alignment_check(void);
+-#ifndef CONFIG_XEN
+-asmlinkage void spurious_interrupt_bug(void);
+-#else
+-asmlinkage void fixup_4gb_segment(void);
+-#endif
+-asmlinkage void machine_check(void);
+-
++int panic_on_unrecovered_nmi;
+ int kstack_depth_to_print = 24;
+ static unsigned int code_bytes = 64;
++static int ignore_nmis;
++static int die_counter;
+ 
+ void printk_address(unsigned long address, int reliable)
+ {
+ #ifdef CONFIG_KALLSYMS
+-	char namebuf[KSYM_NAME_LEN];
+ 	unsigned long offset = 0;
+ 	unsigned long symsize;
+ 	const char *symname;
+-	char reliab[4] = "";
+-	char *delim = ":";
+ 	char *modname;
++	char *delim = ":";
++	char namebuf[KSYM_NAME_LEN];
++	char reliab[4] = "";
+ 
+ 	symname = kallsyms_lookup(address, &symsize, &offset,
+ 					&modname, namebuf);
+@@ -138,22 +117,23 @@ void printk_address(unsigned long addres
+ #endif
+ }
+ 
+-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size)
++static inline int valid_stack_ptr(struct thread_info *tinfo,
++			void *p, unsigned int size)
+ {
+-	return	p > (void *)tinfo &&
+-		p <= (void *)tinfo + THREAD_SIZE - size;
++	void *t = tinfo;
++	return	p > t && p <= t + THREAD_SIZE - size;
+ }
+ 
+ /* The form of the top of the frame on the stack */
+ struct stack_frame {
+-	struct stack_frame	*next_frame;
+-	unsigned long		return_address;
++	struct stack_frame *next_frame;
++	unsigned long return_address;
+ };
+ 
+ static inline unsigned long
+ print_context_stack(struct thread_info *tinfo,
+-		    unsigned long *stack, unsigned long bp,
+-		    const struct stacktrace_ops *ops, void *data)
++		unsigned long *stack, unsigned long bp,
++		const struct stacktrace_ops *ops, void *data)
+ {
+ 	struct stack_frame *frame = (struct stack_frame *)bp;
+ 
+@@ -175,8 +155,6 @@ print_context_stack(struct thread_info *
+ 	return bp;
+ }
+ 
+-#define MSG(msg)		ops->warning(data, msg)
+-
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 		unsigned long *stack, unsigned long bp,
+ 		const struct stacktrace_ops *ops, void *data)
+@@ -186,7 +164,6 @@ void dump_trace(struct task_struct *task
+ 
+ 	if (!stack) {
+ 		unsigned long dummy;
+-
+ 		stack = &dummy;
+ 		if (task != current)
+ 			stack = (unsigned long *)task->thread.sp;
+@@ -204,7 +181,7 @@ void dump_trace(struct task_struct *task
+ 	}
+ #endif
+ 
+-	while (1) {
++	for (;;) {
+ 		struct thread_info *context;
+ 
+ 		context = (struct thread_info *)
+@@ -256,15 +233,15 @@ static void print_trace_address(void *da
+ }
+ 
+ static const struct stacktrace_ops print_trace_ops = {
+-	.warning		= print_trace_warning,
+-	.warning_symbol		= print_trace_warning_symbol,
+-	.stack			= print_trace_stack,
+-	.address		= print_trace_address,
++	.warning = print_trace_warning,
++	.warning_symbol = print_trace_warning_symbol,
++	.stack = print_trace_stack,
++	.address = print_trace_address,
+ };
+ 
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		   unsigned long *stack, unsigned long bp, char *log_lvl)
++		unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ 	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ 	printk("%s =======================\n", log_lvl);
+@@ -359,15 +336,14 @@ void show_registers(struct pt_regs *regs
+ 		printk(KERN_EMERG "Code: ");
+ 
+ 		ip = (u8 *)regs->ip - code_prologue;
+-		if (ip < (u8 *)PAGE_OFFSET ||
+-			probe_kernel_address(ip, c)) {
++		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+ 			/* try starting at EIP */
+ 			ip = (u8 *)regs->ip;
+ 			code_len = code_len - code_prologue + 1;
+ 		}
+ 		for (i = 0; i < code_len; i++, ip++) {
+ 			if (ip < (u8 *)PAGE_OFFSET ||
+-				probe_kernel_address(ip, c)) {
++					probe_kernel_address(ip, c)) {
+ 				printk(" Bad EIP value.");
+ 				break;
+ 			}
+@@ -392,7 +368,53 @@ int is_valid_bugaddr(unsigned long ip)
+ 	return ud2 == 0x0b0f;
+ }
+ 
+-static int die_counter;
++static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
++static int die_owner = -1;
++static unsigned int die_nest_count;
++
++unsigned __kprobes long oops_begin(void)
++{
++	unsigned long flags;
++
++	oops_enter();
++
++	if (die_owner != raw_smp_processor_id()) {
++		console_verbose();
++		raw_local_irq_save(flags);
++		__raw_spin_lock(&die_lock);
++		die_owner = smp_processor_id();
++		die_nest_count = 0;
++		bust_spinlocks(1);
++	} else {
++		raw_local_irq_save(flags);
++	}
++	die_nest_count++;
++	return flags;
++}
++
++void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
++{
++	bust_spinlocks(0);
++	die_owner = -1;
++	add_taint(TAINT_DIE);
++	__raw_spin_unlock(&die_lock);
++	raw_local_irq_restore(flags);
++
++	if (!regs)
++		return;
++
++	if (kexec_should_crash(current))
++		crash_kexec(regs);
++
++	if (in_interrupt())
++		panic("Fatal exception in interrupt");
++
++	if (panic_on_oops)
++		panic("Fatal exception");
++
++	oops_exit();
++	do_exit(signr);
++}
+ 
+ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+@@ -410,26 +432,22 @@ int __kprobes __die(const char *str, str
+ 	printk("DEBUG_PAGEALLOC");
+ #endif
+ 	printk("\n");
+-
+ 	if (notify_die(DIE_OOPS, str, regs, err,
+-			current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) {
++			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
++		return 1;
+ 
+-		show_registers(regs);
+-		/* Executive summary in case the oops scrolled away */
+-		sp = (unsigned long) (&regs->sp);
+-		savesegment(ss, ss);
+-		if (user_mode(regs)) {
+-			sp = regs->sp;
+-			ss = regs->ss & 0xffff;
+-		}
+-		printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+-		print_symbol("%s", regs->ip);
+-		printk(" SS:ESP %04x:%08lx\n", ss, sp);
+-
+-		return 0;
+-	}
+-
+-	return 1;
++	show_registers(regs);
++	/* Executive summary in case the oops scrolled away */
++	sp = (unsigned long) (&regs->sp);
++	savesegment(ss, ss);
++	if (user_mode(regs)) {
++		sp = regs->sp;
++		ss = regs->ss & 0xffff;
++	}
++	printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
++	print_symbol("%s", regs->ip);
++	printk(" SS:ESP %04x:%08lx\n", ss, sp);
++	return 0;
+ }
+ 
+ /*
+@@ -438,31 +456,9 @@ int __kprobes __die(const char *str, str
+  */
+ void die(const char *str, struct pt_regs *regs, long err)
+ {
+-	static struct {
+-		raw_spinlock_t lock;
+-		u32 lock_owner;
+-		int lock_owner_depth;
+-	} die = {
+-		.lock =			__RAW_SPIN_LOCK_UNLOCKED,
+-		.lock_owner =		-1,
+-		.lock_owner_depth =	0
+-	};
+-	unsigned long flags;
+-
+-	oops_enter();
++	unsigned long flags = oops_begin();
+ 
+-	if (die.lock_owner != raw_smp_processor_id()) {
+-		console_verbose();
+-		raw_local_irq_save(flags);
+-		__raw_spin_lock(&die.lock);
+-		die.lock_owner = smp_processor_id();
+-		die.lock_owner_depth = 0;
+-		bust_spinlocks(1);
+-	} else {
+-		raw_local_irq_save(flags);
+-	}
+-
+-	if (++die.lock_owner_depth < 3) {
++	if (die_nest_count < 3) {
+ 		report_bug(regs->ip, regs);
+ 
+ 		if (__die(str, regs, err))
+@@ -471,26 +467,7 @@ void die(const char *str, struct pt_regs
+ 		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
+ 	}
+ 
+-	bust_spinlocks(0);
+-	die.lock_owner = -1;
+-	add_taint(TAINT_DIE);
+-	__raw_spin_unlock(&die.lock);
+-	raw_local_irq_restore(flags);
+-
+-	if (!regs)
+-		return;
+-
+-	if (kexec_should_crash(current))
+-		crash_kexec(regs);
+-
+-	if (in_interrupt())
+-		panic("Fatal exception in interrupt");
+-
+-	if (panic_on_oops)
+-		panic("Fatal exception");
+-
+-	oops_exit();
+-	do_exit(SIGSEGV);
++	oops_end(flags, regs, SIGSEGV);
+ }
+ 
+ static inline void
+@@ -554,7 +531,7 @@ void do_##name(struct pt_regs *regs, lon
+ {									\
+ 	trace_hardirqs_fixup();						\
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-						== NOTIFY_STOP)		\
++							== NOTIFY_STOP)	\
+ 		return;							\
+ 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL);		\
+ }
+@@ -570,7 +547,7 @@ void do_##name(struct pt_regs *regs, lon
+ 	info.si_code = sicode;						\
+ 	info.si_addr = (void __user *)siaddr;				\
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-						== NOTIFY_STOP)		\
++							== NOTIFY_STOP)	\
+ 		return;							\
+ 	do_trap(trapnr, signr, str, 0, regs, error_code, &info);	\
+ }
+@@ -579,7 +556,7 @@ void do_##name(struct pt_regs *regs, lon
+ void do_##name(struct pt_regs *regs, long error_code)			\
+ {									\
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-						== NOTIFY_STOP)		\
++							== NOTIFY_STOP)	\
+ 		return;							\
+ 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL);		\
+ }
+@@ -594,28 +571,29 @@ void do_##name(struct pt_regs *regs, lon
+ 	info.si_addr = (void __user *)siaddr;				\
+ 	trace_hardirqs_fixup();						\
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-						== NOTIFY_STOP)		\
++							== NOTIFY_STOP)	\
+ 		return;							\
+ 	do_trap(trapnr, signr, str, 1, regs, error_code, &info);	\
+ }
+ 
+-DO_VM86_ERROR_INFO(0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+ #ifndef CONFIG_KPROBES
+ DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
+ #endif
+ DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
+ DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO(6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+-DO_ERROR(9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
++DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+-DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+-DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
++DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
++DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+ DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ 
+-void __kprobes do_general_protection(struct pt_regs * regs,
+-					      long error_code)
++void __kprobes
++do_general_protection(struct pt_regs *regs, long error_code)
+ {
++	struct task_struct *tsk;
+ 	struct thread_struct *thread;
+ 
+ 	thread = &current->thread;
+@@ -623,23 +601,24 @@ void __kprobes do_general_protection(str
+ 	if (regs->flags & X86_VM_MASK)
+ 		goto gp_in_vm86;
+ 
++	tsk = current;
+ 	if (!user_mode(regs))
+ 		goto gp_in_kernel;
+ 
+-	current->thread.error_code = error_code;
+-	current->thread.trap_no = 13;
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
+ 
+-	if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+-	    printk_ratelimit()) {
++	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++			printk_ratelimit()) {
+ 		printk(KERN_INFO
+-		    "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+-		    current->comm, task_pid_nr(current),
+-		    regs->ip, regs->sp, error_code);
++			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
++			tsk->comm, task_pid_nr(tsk),
++			regs->ip, regs->sp, error_code);
+ 		print_vma_addr(" in ", regs->ip);
+ 		printk("\n");
+ 	}
+ 
+-	force_sig(SIGSEGV, current);
++	force_sig(SIGSEGV, tsk);
+ 	return;
+ 
+ gp_in_vm86:
+@@ -648,14 +627,15 @@ gp_in_vm86:
+ 	return;
+ 
+ gp_in_kernel:
+-	if (!fixup_exception(regs)) {
+-		current->thread.error_code = error_code;
+-		current->thread.trap_no = 13;
+-		if (notify_die(DIE_GPF, "general protection fault", regs,
++	if (fixup_exception(regs))
++		return;
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
++	if (notify_die(DIE_GPF, "general protection fault", regs,
+ 				error_code, 13, SIGSEGV) == NOTIFY_STOP)
+-			return;
+-		die("general protection fault", regs, error_code);
+-	}
++		return;
++	die("general protection fault", regs, error_code);
+ }
+ 
+ static notrace __kprobes void
+@@ -722,9 +702,9 @@ unknown_nmi_error(unsigned char reason, 
+ 
+ static DEFINE_SPINLOCK(nmi_print_lock);
+ 
+-void notrace __kprobes die_nmi(struct pt_regs *regs, const char *msg)
++void notrace __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+-	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == NOTIFY_STOP)
++	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+ 		return;
+ 
+ 	spin_lock(&nmi_print_lock);
+@@ -733,10 +713,12 @@ void notrace __kprobes die_nmi(struct pt
+ 	* to get a message out:
+ 	*/
+ 	bust_spinlocks(1);
+-	printk(KERN_EMERG "%s", msg);
++	printk(KERN_EMERG "%s", str);
+ 	printk(" on CPU%d, ip %08lx, registers:\n",
+ 		smp_processor_id(), regs->ip);
+ 	show_registers(regs);
++	if (do_panic)
++		panic("Non maskable interrupt");
+ 	console_silent();
+ 	spin_unlock(&nmi_print_lock);
+ 	bust_spinlocks(0);
+@@ -756,14 +738,17 @@ void notrace __kprobes die_nmi(struct pt
+ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
++	int cpu;
+ 
+-	/* Only the BSP gets external NMIs from the system: */
+-	if (!smp_processor_id())
++	cpu = smp_processor_id();
++
++	/* Only the BSP gets external NMIs from the system. */
++	if (!cpu)
+ 		reason = get_nmi_reason();
+ 
+ 	if (!(reason & 0xc0)) {
+ 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+-							== NOTIFY_STOP)
++								== NOTIFY_STOP)
+ 			return;
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 		/*
+@@ -772,7 +757,7 @@ static notrace __kprobes void default_do
+ 		 */
+ 		if (nmi_watchdog_tick(regs, reason))
+ 			return;
+-		if (!do_nmi_callback(regs, smp_processor_id()))
++		if (!do_nmi_callback(regs, cpu))
+ 			unknown_nmi_error(reason, regs);
+ #else
+ 		unknown_nmi_error(reason, regs);
+@@ -782,6 +767,8 @@ static notrace __kprobes void default_do
+ 	}
+ 	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+ 		return;
++
++	/* AK: following checks seem to be broken on modern chipsets. FIXME */
+ 	if (reason & 0x80)
+ 		mem_parity_error(reason, regs);
+ 	if (reason & 0x40)
+@@ -793,8 +780,6 @@ static notrace __kprobes void default_do
+ 	reassert_nmi();
+ }
+ 
+-static int ignore_nmis;
+-
+ notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+ {
+ 	int cpu;
+@@ -879,7 +864,7 @@ void __kprobes do_debug(struct pt_regs *
+ 	tsk->thread.debugctlmsr = 0;
+ 
+ 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+-					SIGTRAP) == NOTIFY_STOP)
++						SIGTRAP) == NOTIFY_STOP)
+ 		return;
+ 	/* It's safe to allow irq's after DR6 has been saved */
+ 	if (regs->flags & X86_EFLAGS_IF)
+@@ -940,9 +925,8 @@ clear_TF_reenable:
+ void math_error(void __user *ip)
+ {
+ 	struct task_struct *task;
+-	unsigned short cwd;
+-	unsigned short swd;
+ 	siginfo_t info;
++	unsigned short cwd, swd;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -961,7 +945,7 @@ void math_error(void __user *ip)
+ 	 * C1 reg you need in case of a stack fault, 0x040 is the stack
+ 	 * fault bit.  We should only be taking one exception at a time,
+ 	 * so if this combination doesn't produce any single exception,
+-	 * then we have a bad program that isn't syncronizing its FPU usage
++	 * then we have a bad program that isn't synchronizing its FPU usage
+ 	 * and it will suffer the consequences since we won't be able to
+ 	 * fully reproduce the context of the exception
+ 	 */
+@@ -970,7 +954,7 @@ void math_error(void __user *ip)
+ 	switch (swd & ~cwd & 0x3f) {
+ 	case 0x000: /* No unmasked exception */
+ 		return;
+-	default:    /* Multiple exceptions */
++	default: /* Multiple exceptions */
+ 		break;
+ 	case 0x001: /* Invalid Op */
+ 		/*
+@@ -1006,8 +990,8 @@ void do_coprocessor_error(struct pt_regs
+ static void simd_math_error(void __user *ip)
+ {
+ 	struct task_struct *task;
+-	unsigned short mxcsr;
+ 	siginfo_t info;
++	unsigned short mxcsr;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -1084,7 +1068,7 @@ void do_spurious_interrupt_bug(struct pt
+ 
+ unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+ {
+-	struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
++	struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
+ 	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+ 	unsigned long new_kesp = kesp - base;
+ 	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -10,73 +10,56 @@
+  * 'Traps.c' handles hardware traps and faults after we have saved some
+  * state in 'entry.S'.
+  */
+-#include <linux/sched.h>
++#include <linux/moduleparam.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
+ #include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
+ #include <linux/errno.h>
+-#include <linux/ptrace.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
+ #include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/spinlock.h>
+-#include <linux/interrupt.h>
+-#include <linux/kallsyms.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/nmi.h>
+-#include <linux/kprobes.h>
+-#include <linux/kexec.h>
+-#include <linux/unwind.h>
+-#include <linux/uaccess.h>
+ #include <linux/bug.h>
+-#include <linux/kdebug.h>
+-#include <linux/utsname.h>
+-
+-#include <mach_traps.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
+ 
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+ #endif
+ 
+-#include <asm/system.h>
+-#include <asm/io.h>
+-#include <asm/atomic.h>
++#include <asm/stacktrace.h>
++#include <asm/processor.h>
+ #include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+-#include <asm/processor.h>
+-#include <asm/unwind.h>
++#include <asm/nmi.h>
+ #include <asm/smp.h>
++#include <asm/io.h>
+ #include <asm/pgalloc.h>
+-#include <asm/pda.h>
+ #include <asm/proto.h>
+-#include <asm/nmi.h>
+-#include <asm/stacktrace.h>
++#include <asm/pda.h>
++#include <asm/traps.h>
+ 
+-asmlinkage void divide_error(void);
+-asmlinkage void debug(void);
+-asmlinkage void nmi(void);
+-asmlinkage void int3(void);
+-asmlinkage void overflow(void);
+-asmlinkage void bounds(void);
+-asmlinkage void invalid_op(void);
+-asmlinkage void device_not_available(void);
+-asmlinkage void double_fault(void);
+-asmlinkage void coprocessor_segment_overrun(void);
+-asmlinkage void invalid_TSS(void);
+-asmlinkage void segment_not_present(void);
+-asmlinkage void stack_segment(void);
+-asmlinkage void general_protection(void);
+-asmlinkage void page_fault(void);
+-asmlinkage void coprocessor_error(void);
+-asmlinkage void simd_coprocessor_error(void);
+-asmlinkage void reserved(void);
+-asmlinkage void alignment_check(void);
+-asmlinkage void machine_check(void);
+-asmlinkage void spurious_interrupt_bug(void);
++#include <mach_traps.h>
+ 
++int panic_on_unrecovered_nmi;
++int kstack_depth_to_print = 12;
+ static unsigned int code_bytes = 64;
++static int ignore_nmis;
++static int die_counter;
+ 
+ static inline void conditional_sti(struct pt_regs *regs)
+ {
+@@ -100,34 +83,9 @@ static inline void preempt_conditional_c
+ 	dec_preempt_count();
+ }
+ 
+-int kstack_depth_to_print = 12;
+-
+ void printk_address(unsigned long address, int reliable)
+ {
+-#ifdef CONFIG_KALLSYMS
+-	unsigned long offset = 0, symsize;
+-	const char *symname;
+-	char *modname;
+-	char *delim = ":";
+-	char namebuf[KSYM_NAME_LEN];
+-	char reliab[4] = "";
+-
+-	symname = kallsyms_lookup(address, &symsize, &offset,
+-					&modname, namebuf);
+-	if (!symname) {
+-		printk(" [<%016lx>]\n", address);
+-		return;
+-	}
+-	if (!reliable)
+-		strcpy(reliab, "? ");
+-
+-	if (!modname)
+-		modname = delim = "";
+-	printk(" [<%016lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
+-		address, reliab, delim, modname, delim, symname, offset, symsize);
+-#else
+-	printk(" [<%016lx>]\n", address);
+-#endif
++	printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address);
+ }
+ 
+ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+@@ -206,8 +164,6 @@ static unsigned long *in_exception_stack
+ 	return NULL;
+ }
+ 
+-#define MSG(txt) ops->warning(data, txt)
+-
+ /*
+  * x86-64 can have up to three kernel stacks:
+  * process stack
+@@ -234,11 +190,11 @@ struct stack_frame {
+ 	unsigned long return_address;
+ };
+ 
+-
+-static inline unsigned long print_context_stack(struct thread_info *tinfo,
+-				unsigned long *stack, unsigned long bp,
+-				const struct stacktrace_ops *ops, void *data,
+-				unsigned long *end)
++static inline unsigned long
++print_context_stack(struct thread_info *tinfo,
++		unsigned long *stack, unsigned long bp,
++		const struct stacktrace_ops *ops, void *data,
++		unsigned long *end)
+ {
+ 	struct stack_frame *frame = (struct stack_frame *)bp;
+ 
+@@ -260,7 +216,7 @@ static inline unsigned long print_contex
+ 	return bp;
+ }
+ 
+-void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
++void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 		unsigned long *stack, unsigned long bp,
+ 		const struct stacktrace_ops *ops, void *data)
+ {
+@@ -269,36 +225,34 @@ void dump_trace(struct task_struct *tsk,
+ 	unsigned used = 0;
+ 	struct thread_info *tinfo;
+ 
+-	if (!tsk)
+-		tsk = current;
+-	tinfo = task_thread_info(tsk);
++	if (!task)
++		task = current;
+ 
+ 	if (!stack) {
+ 		unsigned long dummy;
+ 		stack = &dummy;
+-		if (tsk && tsk != current)
+-			stack = (unsigned long *)tsk->thread.sp;
++		if (task && task != current)
++			stack = (unsigned long *)task->thread.sp;
+ 	}
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ 	if (!bp) {
+-		if (tsk == current) {
++		if (task == current) {
+ 			/* Grab bp right from our regs */
+-			asm("movq %%rbp, %0" : "=r" (bp):);
++			asm("movq %%rbp, %0" : "=r" (bp) :);
+ 		} else {
+ 			/* bp is the last reg pushed by switch_to */
+-			bp = *(unsigned long *) tsk->thread.sp;
++			bp = *(unsigned long *) task->thread.sp;
+ 		}
+ 	}
+ #endif
+ 
+-
+-
+ 	/*
+ 	 * Print function call entries in all stacks, starting at the
+ 	 * current stack address. If the stacks consist of nested
+ 	 * exceptions
+ 	 */
++	tinfo = task_thread_info(task);
+ 	for (;;) {
+ 		char *id;
+ 		unsigned long *estack_end;
+@@ -383,18 +337,24 @@ static const struct stacktrace_ops print
+ 	.address = print_trace_address,
+ };
+ 
+-void
+-show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
+-		unsigned long bp)
++static void
++show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
++		unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+ 	printk("\nCall Trace:\n");
+-	dump_trace(tsk, regs, stack, bp, &print_trace_ops, NULL);
++	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ 	printk("\n");
+ }
+ 
++void show_trace(struct task_struct *task, struct pt_regs *regs,
++		unsigned long *stack, unsigned long bp)
++{
++	show_trace_log_lvl(task, regs, stack, bp, "");
++}
++
+ static void
+-_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp,
+-							unsigned long bp)
++show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++		unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ 	unsigned long *stack;
+ 	int i;
+@@ -406,14 +366,14 @@ _show_stack(struct task_struct *tsk, str
+ 	// back trace for this cpu.
+ 
+ 	if (sp == NULL) {
+-		if (tsk)
+-			sp = (unsigned long *)tsk->thread.sp;
++		if (task)
++			sp = (unsigned long *)task->thread.sp;
+ 		else
+ 			sp = (unsigned long *)&sp;
+ 	}
+ 
+ 	stack = sp;
+-	for(i=0; i < kstack_depth_to_print; i++) {
++	for (i = 0; i < kstack_depth_to_print; i++) {
+ 		if (stack >= irqstack && stack <= irqstack_end) {
+ 			if (stack == irqstack_end) {
+ 				stack = (unsigned long *) (irqstack_end[-1]);
+@@ -428,12 +388,12 @@ _show_stack(struct task_struct *tsk, str
+ 		printk(" %016lx", *stack++);
+ 		touch_nmi_watchdog();
+ 	}
+-	show_trace(tsk, regs, sp, bp);
++	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+ 
+-void show_stack(struct task_struct *tsk, unsigned long * sp)
++void show_stack(struct task_struct *task, unsigned long *sp)
+ {
+-	_show_stack(tsk, NULL, sp, 0);
++	show_stack_log_lvl(task, NULL, sp, 0, "");
+ }
+ 
+ /*
+@@ -441,8 +401,8 @@ void show_stack(struct task_struct *tsk,
+  */
+ void dump_stack(void)
+ {
+-	unsigned long dummy;
+ 	unsigned long bp = 0;
++	unsigned long stack;
+ 
+ #ifdef CONFIG_FRAME_POINTER
+ 	if (!bp)
+@@ -454,7 +414,7 @@ void dump_stack(void)
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
+-	show_trace(NULL, NULL, &dummy, bp);
++	show_trace(NULL, NULL, &stack, bp);
+ }
+ 
+ EXPORT_SYMBOL(dump_stack);
+@@ -465,12 +425,8 @@ void show_registers(struct pt_regs *regs
+ 	unsigned long sp;
+ 	const int cpu = smp_processor_id();
+ 	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
+-	u8 *ip;
+-	unsigned int code_prologue = code_bytes * 43 / 64;
+-	unsigned int code_len = code_bytes;
+ 
+ 	sp = regs->sp;
+-	ip = (u8 *) regs->ip - code_prologue;
+ 	printk("CPU %d ", cpu);
+ 	__show_regs(regs);
+ 	printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
+@@ -481,15 +437,22 @@ void show_registers(struct pt_regs *regs
+ 	 * time of the fault..
+ 	 */
+ 	if (!user_mode(regs)) {
++		unsigned int code_prologue = code_bytes * 43 / 64;
++		unsigned int code_len = code_bytes;
+ 		unsigned char c;
++		u8 *ip;
++
+ 		printk("Stack: ");
+-		_show_stack(NULL, regs, (unsigned long *)sp, regs->bp);
++		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
++				regs->bp, "");
+ 		printk("\n");
+ 
+ 		printk(KERN_EMERG "Code: ");
++
++		ip = (u8 *)regs->ip - code_prologue;
+ 		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+ 			/* try starting at RIP */
+-			ip = (u8 *) regs->ip;
++			ip = (u8 *)regs->ip;
+ 			code_len = code_len - code_prologue + 1;
+ 		}
+ 		for (i = 0; i < code_len; i++, ip++) {
+@@ -505,7 +468,7 @@ void show_registers(struct pt_regs *regs
+ 		}
+ 	}
+ 	printk("\n");
+-}	
++}
+ 
+ int is_valid_bugaddr(unsigned long ip)
+ {
+@@ -545,7 +508,7 @@ unsigned __kprobes long oops_begin(void)
+ }
+ 
+ void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+-{ 
++{
+ 	die_owner = -1;
+ 	bust_spinlocks(0);
+ 	die_nest_count--;
+@@ -563,10 +526,9 @@ void __kprobes oops_end(unsigned long fl
+ 	do_exit(signr);
+ }
+ 
+-int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+ {
+-	static int die_counter;
+-	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
++	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+ 	printk("PREEMPT ");
+ #endif
+@@ -577,8 +539,10 @@ int __kprobes __die(const char * str, st
+ 	printk("DEBUG_PAGEALLOC");
+ #endif
+ 	printk("\n");
+-	if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
++	if (notify_die(DIE_OOPS, str, regs, err,
++			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+ 		return 1;
++
+ 	show_registers(regs);
+ 	add_taint(TAINT_DIE);
+ 	/* Executive summary in case the oops scrolled away */
+@@ -590,7 +554,7 @@ int __kprobes __die(const char * str, st
+ 	return 0;
+ }
+ 
+-void die(const char * str, struct pt_regs * regs, long err)
++void die(const char *str, struct pt_regs *regs, long err)
+ {
+ 	unsigned long flags = oops_begin();
+ 
+@@ -608,8 +572,7 @@ die_nmi(char *str, struct pt_regs *regs,
+ {
+ 	unsigned long flags;
+ 
+-	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) ==
+-	    NOTIFY_STOP)
++	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+ 		return;
+ 
+ 	flags = oops_begin();
+@@ -617,7 +580,9 @@ die_nmi(char *str, struct pt_regs *regs,
+ 	 * We are in trouble anyway, lets at least try
+ 	 * to get a message out.
+ 	 */
+-	printk(str, smp_processor_id());
++	printk(KERN_EMERG "%s", str);
++	printk(" on CPU%d, ip %08lx, registers:\n",
++		smp_processor_id(), regs->ip);
+ 	show_registers(regs);
+ 	if (kexec_should_crash(current))
+ 		crash_kexec(regs);
+@@ -630,44 +595,44 @@ die_nmi(char *str, struct pt_regs *regs,
+ }
+ #endif
+ 
+-static void __kprobes do_trap(int trapnr, int signr, char *str,
+-			      struct pt_regs * regs, long error_code,
+-			      siginfo_t *info)
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
++	long error_code, siginfo_t *info)
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	if (user_mode(regs)) {
+-		/*
+-		 * We want error_code and trap_no set for userspace
+-		 * faults and kernelspace faults which result in
+-		 * die(), but not kernelspace faults which are fixed
+-		 * up.  die() gives the process no chance to handle
+-		 * the signal and notice the kernel fault information,
+-		 * so that won't result in polluting the information
+-		 * about previously queued, but not yet delivered,
+-		 * faults.  See also do_general_protection below.
+-		 */
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = trapnr;
++	if (!user_mode(regs))
++		goto kernel_trap;
+ 
+-		if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+-		    printk_ratelimit()) {
+-			printk(KERN_INFO
+-			       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+-			       tsk->comm, tsk->pid, str,
+-			       regs->ip, regs->sp, error_code);
+-			print_vma_addr(" in ", regs->ip);
+-			printk("\n");
+-		}
++	/*
++	 * We want error_code and trap_no set for userspace faults and
++	 * kernelspace faults which result in die(), but not
++	 * kernelspace faults which are fixed up.  die() gives the
++	 * process no chance to handle the signal and notice the
++	 * kernel fault information, so that won't result in polluting
++	 * the information about previously queued, but not yet
++	 * delivered, faults.  See also do_general_protection below.
++	 */
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
+ 
+-		if (info)
+-			force_sig_info(signr, info, tsk);
+-		else
+-			force_sig(signr, tsk);
+-		return;
++	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
++	    printk_ratelimit()) {
++		printk(KERN_INFO
++		       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
++		       tsk->comm, tsk->pid, str,
++		       regs->ip, regs->sp, error_code);
++		print_vma_addr(" in ", regs->ip);
++		printk("\n");
+ 	}
+ 
++	if (info)
++		force_sig_info(signr, info, tsk);
++	else
++		force_sig(signr, tsk);
++	return;
+ 
++kernel_trap:
+ 	if (!fixup_exception(regs)) {
+ 		tsk->thread.error_code = error_code;
+ 		tsk->thread.trap_no = trapnr;
+@@ -677,41 +642,39 @@ static void __kprobes do_trap(int trapnr
+ }
+ 
+ #define DO_ERROR(trapnr, signr, str, name) \
+-asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-							== NOTIFY_STOP) \
+-		return; \
++asmlinkage void do_##name(struct pt_regs * regs, long error_code)	\
++{									\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++							== NOTIFY_STOP)	\
++		return;							\
+ 	conditional_sti(regs);						\
+-	do_trap(trapnr, signr, str, regs, error_code, NULL); \
++	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
+ }
+ 
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+-asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+-{ \
+-	siginfo_t info; \
+-	info.si_signo = signr; \
+-	info.si_errno = 0; \
+-	info.si_code = sicode; \
+-	info.si_addr = (void __user *)siaddr; \
+-	trace_hardirqs_fixup(); \
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+-							== NOTIFY_STOP) \
+-		return; \
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
++asmlinkage void do_##name(struct pt_regs * regs, long error_code)	\
++{									\
++	siginfo_t info;							\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	trace_hardirqs_fixup();						\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++							== NOTIFY_STOP)	\
++		return;							\
+ 	conditional_sti(regs);						\
+-	do_trap(trapnr, signr, str, regs, error_code, &info); \
++	do_trap(trapnr, signr, str, regs, error_code, &info);		\
+ }
+ 
+-DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
+-DO_ERROR( 4, SIGSEGV, "overflow", overflow)
+-DO_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
+-DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
+-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_ERROR(4, SIGSEGV, "overflow", overflow)
++DO_ERROR(5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
++DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+-DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
++DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+-DO_ERROR(18, SIGSEGV, "reserved", reserved)
+ 
+ /* Runs on IST stack */
+ asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+@@ -741,31 +704,34 @@ asmlinkage void do_double_fault(struct p
+ 		die(str, regs, error_code);
+ }
+ 
+-asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
+-						long error_code)
++asmlinkage void __kprobes
++do_general_protection(struct pt_regs *regs, long error_code)
+ {
+-	struct task_struct *tsk = current;
++	struct task_struct *tsk;
+ 
+ 	conditional_sti(regs);
+ 
+-	if (user_mode(regs)) {
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = 13;
++	tsk = current;
++	if (!user_mode(regs))
++		goto gp_in_kernel;
+ 
+-		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-		    printk_ratelimit()) {
+-			printk(KERN_INFO
+-		       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+-			       tsk->comm, tsk->pid,
+-			       regs->ip, regs->sp, error_code);
+-			print_vma_addr(" in ", regs->ip);
+-			printk("\n");
+-		}
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
+ 
+-		force_sig(SIGSEGV, tsk);
+-		return;
+-	} 
++	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++			printk_ratelimit()) {
++		printk(KERN_INFO
++			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
++			tsk->comm, tsk->pid,
++			regs->ip, regs->sp, error_code);
++		print_vma_addr(" in ", regs->ip);
++		printk("\n");
++	}
+ 
++	force_sig(SIGSEGV, tsk);
++	return;
++
++gp_in_kernel:
+ 	if (fixup_exception(regs))
+ 		return;
+ 
+@@ -778,14 +744,14 @@ asmlinkage void __kprobes do_general_pro
+ }
+ 
+ static notrace __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs * regs)
++mem_parity_error(unsigned char reason, struct pt_regs *regs)
+ {
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ 		reason);
+ 	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
+ 
+ #if defined(CONFIG_EDAC)
+-	if(edac_handler_set()) {
++	if (edac_handler_set()) {
+ 		edac_atomic_assert_error();
+ 		return;
+ 	}
+@@ -801,7 +767,7 @@ mem_parity_error(unsigned char reason, s
+ }
+ 
+ static notrace __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs * regs)
++io_check_error(unsigned char reason, struct pt_regs *regs)
+ {
+ 	printk("NMI: IOCK error (debug interrupt?)\n");
+ 	show_registers(regs);
+@@ -827,14 +793,14 @@ unknown_nmi_error(unsigned char reason, 
+ 
+ /* Runs on IST stack. This code must keep interrupts off all the time.
+    Nested NMIs are prevented by the CPU. */
+-asmlinkage notrace  __kprobes void default_do_nmi(struct pt_regs *regs)
++asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+ {
+ 	unsigned char reason = 0;
+ 	int cpu;
+ 
+ 	cpu = smp_processor_id();
+ 
+-	/* Only the BSP gets external NMIs from the system.  */
++	/* Only the BSP gets external NMIs from the system. */
+ 	if (!cpu)
+ 		reason = get_nmi_reason();
+ 
+@@ -847,33 +813,58 @@ asmlinkage notrace  __kprobes void defau
+ 		 * Ok, so this is none of the documented NMI sources,
+ 		 * so it must be the NMI watchdog.
+ 		 */
+-		if (nmi_watchdog_tick(regs,reason))
++		if (nmi_watchdog_tick(regs, reason))
+ 			return;
+ #endif
+-		if (!do_nmi_callback(regs,cpu))
++		if (!do_nmi_callback(regs, cpu))
+ 			unknown_nmi_error(reason, regs);
+ 
+ 		return;
+ 	}
+ 	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+-		return; 
++		return;
+ 
+ 	/* AK: following checks seem to be broken on modern chipsets. FIXME */
+-
+ 	if (reason & 0x80)
+ 		mem_parity_error(reason, regs);
+ 	if (reason & 0x40)
+ 		io_check_error(reason, regs);
+ }
+ 
++asmlinkage notrace __kprobes void
++do_nmi(struct pt_regs *regs, long error_code)
++{
++	nmi_enter();
++
++	add_pda(__nmi_count, 1);
++
++	if (!ignore_nmis)
++		default_do_nmi(regs);
++
++	nmi_exit();
++}
++
++void stop_nmi(void)
++{
++	acpi_nmi_disable();
++	ignore_nmis++;
++}
++
++void restart_nmi(void)
++{
++	ignore_nmis--;
++	acpi_nmi_enable();
++}
++
+ /* runs on IST stack. */
+ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
+ {
+ 	trace_hardirqs_fixup();
+ 
+-	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
++	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
++			== NOTIFY_STOP)
+ 		return;
+-	}
++
+ 	preempt_conditional_sti(regs);
+ 	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+ 	preempt_conditional_cli(regs);
+@@ -904,8 +895,8 @@ asmlinkage __kprobes struct pt_regs *syn
+ asmlinkage void __kprobes do_debug(struct pt_regs * regs,
+ 				   unsigned long error_code)
+ {
+-	unsigned long condition;
+ 	struct task_struct *tsk = current;
++	unsigned long condition;
+ 	siginfo_t info;
+ 
+ 	trace_hardirqs_fixup();
+@@ -926,21 +917,19 @@ asmlinkage void __kprobes do_debug(struc
+ 
+ 	/* Mask out spurious debug traps due to lazy DR7 setting */
+ 	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+-		if (!tsk->thread.debugreg7) { 
++		if (!tsk->thread.debugreg7)
+ 			goto clear_dr7;
+-		}
+ 	}
+ 
+ 	tsk->thread.debugreg6 = condition;
+ 
+-
+ 	/*
+ 	 * Single-stepping through TF: make sure we ignore any events in
+ 	 * kernel space (but re-enable TF when returning to user mode).
+ 	 */
+ 	if (condition & DR_STEP) {
+-                if (!user_mode(regs))
+-                       goto clear_TF_reenable;
++		if (!user_mode(regs))
++			goto clear_TF_reenable;
+ 	}
+ 
+ 	/* Ok, finally something we can handle */
+@@ -953,7 +942,7 @@ asmlinkage void __kprobes do_debug(struc
+ 	force_sig_info(SIGTRAP, &info, tsk);
+ 
+ clear_dr7:
+-	set_debugreg(0UL, 7);
++	set_debugreg(0, 7);
+ 	preempt_conditional_cli(regs);
+ 	return;
+ 
+@@ -961,6 +950,7 @@ clear_TF_reenable:
+ 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+ 	regs->flags &= ~X86_EFLAGS_TF;
+ 	preempt_conditional_cli(regs);
++	return;
+ }
+ 
+ static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
+@@ -983,7 +973,7 @@ static int kernel_math_error(struct pt_r
+ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
+ {
+ 	void __user *ip = (void __user *)(regs->ip);
+-	struct task_struct * task;
++	struct task_struct *task;
+ 	siginfo_t info;
+ 	unsigned short cwd, swd;
+ 
+@@ -1016,30 +1006,30 @@ asmlinkage void do_coprocessor_error(str
+ 	cwd = get_fpu_cwd(task);
+ 	swd = get_fpu_swd(task);
+ 	switch (swd & ~cwd & 0x3f) {
+-		case 0x000:
+-		default:
+-			break;
+-		case 0x001: /* Invalid Op */
+-			/*
+-			 * swd & 0x240 == 0x040: Stack Underflow
+-			 * swd & 0x240 == 0x240: Stack Overflow
+-			 * User must clear the SF bit (0x40) if set
+-			 */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000: /* No unmasked exception */
++	default: /* Multiple exceptions */
++		break;
++	case 0x001: /* Invalid Op */
++		/*
++		 * swd & 0x240 == 0x040: Stack Underflow
++		 * swd & 0x240 == 0x240: Stack Overflow
++		 * User must clear the SF bit (0x40) if set
++		 */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+@@ -1052,7 +1042,7 @@ asmlinkage void bad_intr(void)
+ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
+ {
+ 	void __user *ip = (void __user *)(regs->ip);
+-	struct task_struct * task;
++	struct task_struct *task;
+ 	siginfo_t info;
+ 	unsigned short mxcsr;
+ 
+@@ -1080,25 +1070,25 @@ asmlinkage void do_simd_coprocessor_erro
+ 	 */
+ 	mxcsr = get_fpu_mxcsr(task);
+ 	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+-		case 0x000:
+-		default:
+-			break;
+-		case 0x001: /* Invalid Op */
+-			info.si_code = FPE_FLTINV;
+-			break;
+-		case 0x002: /* Denormalize */
+-		case 0x010: /* Underflow */
+-			info.si_code = FPE_FLTUND;
+-			break;
+-		case 0x004: /* Zero Divide */
+-			info.si_code = FPE_FLTDIV;
+-			break;
+-		case 0x008: /* Overflow */
+-			info.si_code = FPE_FLTOVF;
+-			break;
+-		case 0x020: /* Precision */
+-			info.si_code = FPE_FLTRES;
+-			break;
++	case 0x000:
++	default:
++		break;
++	case 0x001: /* Invalid Op */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+@@ -1118,7 +1108,7 @@ asmlinkage void __attribute__((weak)) mc
+ }
+ 
+ /*
+- *  'math_state_restore()' saves the current math information in the
++ * 'math_state_restore()' saves the current math information in the
+  * old math state array, and gets the new ones from the current task
+  *
+  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+@@ -1145,7 +1135,14 @@ asmlinkage void math_state_restore(void)
+ 
+         /* clts(); */ /* 'clts' is done for us by Xen during virtual trap. */
+ 
+-	restore_fpu_checking(&me->thread.xstate->fxsave);
++	/*
++	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
++	 */
++	if (unlikely(restore_fpu_checking(&me->thread.xstate->fxsave))) {
++		stts();
++		force_sig(SIGSEGV, me);
++		return;
++	}
+ 	task_thread_info(me)->status |= TS_USEDFPU;
+ 	me->fpu_counter++;
+ }
+@@ -1190,13 +1187,12 @@ void __init trap_init(void)
+         ret = HYPERVISOR_set_trap_table(trap_table);
+         if (ret) 
+ 		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+-
+ 	/*
+ 	 * initialize the per thread extended state:
+ 	 */
+-        init_thread_xstate();
++	init_thread_xstate();
+ 	/*
+-	 * Should be a barrier for any external CPU state.
++	 * Should be a barrier for any external CPU state:
+ 	 */
+ 	cpu_init();
+ }
+@@ -1212,27 +1208,25 @@ void __cpuinit smp_trap_init(trap_info_t
+ 	}
+ }
+ 
+-
+ static int __init oops_setup(char *s)
+-{ 
++{
+ 	if (!s)
+ 		return -EINVAL;
+ 	if (!strcmp(s, "panic"))
+ 		panic_on_oops = 1;
+ 	return 0;
+-} 
++}
+ early_param("oops", oops_setup);
+ 
+ static int __init kstack_setup(char *s)
+ {
+ 	if (!s)
+ 		return -EINVAL;
+-	kstack_depth_to_print = simple_strtoul(s,NULL,0);
++	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+ 	return 0;
+ }
+ early_param("kstack", kstack_setup);
+ 
+-
+ static int __init code_bytes_setup(char *s)
+ {
+ 	code_bytes = simple_strtoul(s, NULL, 0);
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -42,7 +42,8 @@
+ #include <asm/topology.h>
+ #include <asm/vgtod.h>
+ 
+-#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
++#define __vsyscall(nr) \
++		__attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace
+ #define __syscall_clobber "r11","cx","memory"
+ 
+ /*
+@@ -264,10 +265,7 @@ static void __cpuinit vsyscall_set_cpu(i
+ 	d |= cpu;
+ 	d |= (node & 0xf) << 12;
+ 	d |= (node >> 4) << 48;
+-	if (HYPERVISOR_update_descriptor(virt_to_machine(get_cpu_gdt_table(cpu)
+-							 + GDT_ENTRY_PER_CPU),
+-					 d))
+-		BUG();
++	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S);
+ }
+ 
+ static void __cpuinit cpu_vsyscall_init(void *arg)
+@@ -281,7 +279,7 @@ cpu_vsyscall_notifier(struct notifier_bl
+ {
+ 	long cpu = (long)arg;
+ 	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
+-		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
++		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 1);
+ 	return NOTIFY_DONE;
+ }
+ 
+@@ -311,7 +309,7 @@ static int __init vsyscall_init(void)
+ #ifdef CONFIG_SYSCTL
+ 	register_sysctl_table(kernel_root_table2);
+ #endif
+-	on_each_cpu(cpu_vsyscall_init, NULL, 0, 1);
++	on_each_cpu(cpu_vsyscall_init, NULL, 1);
+ 	hotcpu_notifier(cpu_vsyscall_notifier, 0);
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2009-12-03 15:47:58.000000000 +0100
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2009-12-04 11:23:33.000000000 +0100
+@@ -17,6 +17,8 @@
+ #include <xen/interface/callback.h>
+ #include <xen/interface/memory.h>
+ 
++#ifdef CONFIG_X86_32
++
+ #ifdef CONFIG_HOTPLUG_CPU
+ #define DEFAULT_SEND_IPI	(1)
+ #else
+@@ -44,47 +46,6 @@ static int __init print_ipi_mode(void)
+ 
+ late_initcall(print_ipi_mode);
+ 
+-/**
+- * machine_specific_memory_setup - Hook for machine specific memory setup.
+- *
+- * Description:
+- *	This is included late in kernel/setup.c so that it can make
+- *	use of all of the static functions.
+- **/
+-
+-char * __init machine_specific_memory_setup(void)
+-{
+-	int rc;
+-	struct xen_memory_map memmap;
+-	static struct e820entry __initdata map[E820MAX];
+-
+-	memmap.nr_entries = E820MAX;
+-	set_xen_guest_handle(memmap.buffer, map);
+-
+-	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+-	if ( rc == -ENOSYS ) {
+-		memmap.nr_entries = 1;
+-		map[0].addr = 0ULL;
+-		map[0].size = PFN_PHYS((unsigned long long)xen_start_info->nr_pages);
+-		/* 8MB slack (to balance backend allocations). */
+-		map[0].size += 8ULL << 20;
+-		map[0].type = E820_RAM;
+-		rc = 0;
+-	}
+-	BUG_ON(rc);
+-
+-	sanitize_e820_map(map, (char *)&memmap.nr_entries);
+-
+-	BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0);
+-
+-	return "Xen";
+-}
+-
+-
+-extern void hypervisor_callback(void);
+-extern void failsafe_callback(void);
+-extern void nmi(void);
+-
+ unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
+ EXPORT_SYMBOL(machine_to_phys_mapping);
+ unsigned int machine_to_phys_order;
+@@ -117,33 +78,66 @@ void __init pre_setup_arch_hook(void)
+ 			(unsigned long *)xen_start_info->mfn_list;
+ }
+ 
++#endif /* CONFIG_X86_32 */
++
++extern void hypervisor_callback(void);
++extern void failsafe_callback(void);
++extern void nmi(void);
++
++#ifdef CONFIG_X86_64
++#include <asm/proto.h>
++#define CALLBACK_ADDR(fn) ((unsigned long)(fn))
++#else
++#define CALLBACK_ADDR(fn) { __KERNEL_CS, (unsigned long)(fn) }
++#endif
++
+ 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 },
++		.address = CALLBACK_ADDR(hypervisor_callback)
+ 	};
+ 	static struct callback_register __initdata failsafe = {
+ 		.type = CALLBACKTYPE_failsafe,
+-		.address = { __KERNEL_CS, (unsigned long)failsafe_callback },
++		.address = CALLBACK_ADDR(failsafe_callback)
++	};
++#ifdef CONFIG_X86_64
++	static struct callback_register __initdata syscall = {
++		.type = CALLBACKTYPE_syscall,
++		.address = CALLBACK_ADDR(system_call)
+ 	};
++#endif
++#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+ 	static struct callback_register __initdata nmi_cb = {
+ 		.type = CALLBACKTYPE_nmi,
+-		.address = { __KERNEL_CS, (unsigned long)nmi },
++		.address = CALLBACK_ADDR(nmi)
+ 	};
++#endif
+ 
+ 	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+ 	if (ret == 0)
+ 		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
++#ifdef CONFIG_X86_64
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
++#endif
+ #if CONFIG_XEN_COMPAT <= 0x030002
++#ifdef CONFIG_X86_32
+ 	if (ret == -ENOSYS)
+ 		ret = HYPERVISOR_set_callbacks(
+ 			event.address.cs, event.address.eip,
+ 			failsafe.address.cs, failsafe.address.eip);
++#else
++		ret = HYPERVISOR_set_callbacks(
++			event.address,
++			failsafe.address,
++			syscall.address);
++#endif
+ #endif
+ 	BUG_ON(ret);
+ 
++#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32)
+ 	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ 	if (ret == -ENOSYS) {
+@@ -154,15 +148,43 @@ void __init machine_specific_arch_setup(
+ 		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+ 	}
+ #endif
++#endif
+ 
++#ifdef CONFIG_X86_32
+ 	/* Do an early initialization of the fixmap area */
+ 	{
+ 		extern pte_t swapper_pg_fixmap[PTRS_PER_PTE];
+ 		unsigned long addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ 		pud_t *pud = pud_offset(swapper_pg_dir + pgd_index(addr), addr);
+ 		pmd_t *pmd = pmd_offset(pud, addr);
++		unsigned int i;
+ 
+ 		make_lowmem_page_readonly(swapper_pg_fixmap, XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa_symbol(swapper_pg_fixmap) | _PAGE_TABLE));
++
++#define __FIXADDR_TOP (-PAGE_SIZE)
++#define FIX_BUG_ON(fix) BUILD_BUG_ON(pmd_index(__fix_to_virt(FIX_##fix)) \
++			!= pmd_index(__fix_to_virt(FIX_EARLYCON_MEM_BASE)))
++		FIX_BUG_ON(SHARED_INFO);
++		FIX_BUG_ON(ISAMAP_BEGIN);
++		FIX_BUG_ON(ISAMAP_END);
++#undef __FIXADDR_TOP
++		BUG_ON(pte_index(hypervisor_virt_start));
++
++		/* Switch to the real shared_info page, and clear the
++		 * dummy page. */
++		set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++		HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++		memset(empty_zero_page, 0, sizeof(empty_zero_page));
++
++		/* Setup mapping of lower 1st MB */
++		for (i = 0; i < NR_FIX_ISAMAPS; i++)
++			if (is_initial_xendomain())
++				set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
++			else
++				__set_fixmap(FIX_ISAMAP_BEGIN - i,
++					     virt_to_machine(empty_zero_page),
++					     PAGE_KERNEL_RO);
+ 	}
++#endif
+ }
+--- head-2010-01-18.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -10,6 +10,7 @@
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/ptrace.h>
++#include <linux/mmiotrace.h>
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+@@ -49,17 +50,23 @@
+ #define PF_RSVD		(1<<3)
+ #define PF_INSTR	(1<<4)
+ 
++static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
++{
++#ifdef CONFIG_MMIOTRACE_HOOKS
++	if (unlikely(is_kmmio_active()))
++		if (kmmio_handler(regs, addr) == 1)
++			return -1;
++#endif
++	return 0;
++}
++
+ static inline int notify_page_fault(struct pt_regs *regs)
+ {
+ #ifdef CONFIG_KPROBES
+ 	int ret = 0;
+ 
+ 	/* kprobe_running() needs smp_processor_id() */
+-#ifdef CONFIG_X86_32
+ 	if (!user_mode_vm(regs)) {
+-#else
+-	if (!user_mode(regs)) {
+-#endif
+ 		preempt_disable();
+ 		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+ 			ret = 1;
+@@ -409,11 +416,7 @@ static void show_fault_oops(struct pt_re
+ 		printk(KERN_CONT "NULL pointer dereference");
+ 	else
+ 		printk(KERN_CONT "paging request");
+-#ifdef CONFIG_X86_32
+-	printk(KERN_CONT " at %08lx\n", address);
+-#else
+-	printk(KERN_CONT " at %016lx\n", address);
+-#endif
++	printk(KERN_CONT " at %p\n", (void *) address);
+ 	printk(KERN_ALERT "IP:");
+ 	printk_address(regs->ip, 1);
+ 	dump_pagetable(address);
+@@ -628,6 +631,8 @@ void __kprobes do_page_fault(struct pt_r
+ 
+ 	if (notify_page_fault(regs))
+ 		return;
++	if (unlikely(kmmio_fault(regs, address)))
++		return;
+ 
+ 	/*
+ 	 * We fault-in kernel-space virtual memory on-demand. The
+@@ -831,14 +836,10 @@ bad_area_nosemaphore:
+ 		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+ 		    printk_ratelimit()) {
+ 			printk(
+-#ifdef CONFIG_X86_32
+-			"%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
+-#else
+-			"%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
+-#endif
++			"%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+ 			task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+-			tsk->comm, task_pid_nr(tsk), address, regs->ip,
+-			regs->sp, error_code);
++			tsk->comm, task_pid_nr(tsk), address,
++			(void *) regs->ip, (void *) regs->sp, error_code);
+ 			print_vma_addr(" in ", regs->ip);
+ 			printk("\n");
+ 		}
+@@ -946,81 +947,45 @@ LIST_HEAD(pgd_list);
+ void vmalloc_sync_all(void)
+ {
+ #ifdef CONFIG_X86_32
+-	/*
+-	 * Note that races in the updates of insync and start aren't
+-	 * problematic: insync can only get set bits added, and updates to
+-	 * start are only improving performance (without affecting correctness
+-	 * if undone).
+-	 * XEN: To work on PAE, we need to iterate over PMDs rather than PGDs.
+-	 *      This change works just fine with 2-level paging too.
+-	 */
+-#define sync_index(a) ((a) >> PMD_SHIFT)
+-	static DECLARE_BITMAP(insync, PTRS_PER_PGD*PTRS_PER_PMD);
+-	static unsigned long start = TASK_SIZE;
+-	unsigned long address;
++	unsigned long address = VMALLOC_START & PGDIR_MASK;
+ 
+ 	if (SHARED_KERNEL_PMD)
+ 		return;
+ 
+ 	BUILD_BUG_ON(TASK_SIZE & ~PMD_MASK);
+-	for (address = start;
+-	     address < hypervisor_virt_start;
+-	     address += PMD_SIZE) {
+-		if (!test_bit(sync_index(address), insync)) {
+-			unsigned long flags;
+-			struct page *page;
+-
+-			spin_lock_irqsave(&pgd_lock, flags);
+-			/* XEN: failure path assumes non-empty pgd_list. */
+-			if (unlikely(list_empty(&pgd_list))) {
+-				spin_unlock_irqrestore(&pgd_lock, flags);
+-				return;
+-			}
+-			list_for_each_entry(page, &pgd_list, lru) {
+-				if (!vmalloc_sync_one(page_address(page),
+-						      address))
+-					break;
+-			}
+-			spin_unlock_irqrestore(&pgd_lock, flags);
+-			if (!page)
+-				set_bit(sync_index(address), insync);
++	for (; address < hypervisor_virt_start; address += PMD_SIZE) {
++		unsigned long flags;
++		struct page *page;
++
++		spin_lock_irqsave(&pgd_lock, flags);
++		list_for_each_entry(page, &pgd_list, lru) {
++			if (!vmalloc_sync_one(page_address(page),
++					      address))
++				break;
+ 		}
+-		if (address == start && test_bit(sync_index(address), insync))
+-			start = address + PMD_SIZE;
++		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+ #else /* CONFIG_X86_64 */
+-	/*
+-	 * Note that races in the updates of insync and start aren't
+-	 * problematic: insync can only get set bits added, and updates to
+-	 * start are only improving performance (without affecting correctness
+-	 * if undone).
+-	 */
+-	static DECLARE_BITMAP(insync, PTRS_PER_PGD);
+-	static unsigned long start = VMALLOC_START & PGDIR_MASK;
++	unsigned long start = VMALLOC_START & PGDIR_MASK;
+ 	unsigned long address;
+ 
+ 	for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
+-		if (!test_bit(pgd_index(address), insync)) {
+-			const pgd_t *pgd_ref = pgd_offset_k(address);
+-			unsigned long flags;
+-			struct page *page;
+-
+-			if (pgd_none(*pgd_ref))
+-				continue;
+-			spin_lock_irqsave(&pgd_lock, flags);
+-			list_for_each_entry(page, &pgd_list, lru) {
+-				pgd_t *pgd;
+-				pgd = (pgd_t *)page_address(page) + pgd_index(address);
+-				if (pgd_none(*pgd))
+-					set_pgd(pgd, *pgd_ref);
+-				else
+-					BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+-			}
+-			spin_unlock_irqrestore(&pgd_lock, flags);
+-			set_bit(pgd_index(address), insync);
++		const pgd_t *pgd_ref = pgd_offset_k(address);
++		unsigned long flags;
++		struct page *page;
++
++		if (pgd_none(*pgd_ref))
++			continue;
++		spin_lock_irqsave(&pgd_lock, flags);
++		list_for_each_entry(page, &pgd_list, lru) {
++			pgd_t *pgd;
++			pgd = (pgd_t *)page_address(page) + pgd_index(address);
++			if (pgd_none(*pgd))
++				set_pgd(pgd, *pgd_ref);
++			else
++				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ 		}
+-		if (address == start)
+-			start = address + PGDIR_SIZE;
++		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+ #endif
+ }
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:51:42.000000000 +0100
+@@ -713,6 +713,72 @@ void xen_destroy_contiguous_region(unsig
+ }
+ EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
+ 
++int __init early_create_contiguous_region(unsigned long pfn,
++					  unsigned int order,
++					  unsigned int address_bits)
++{
++	unsigned long *in_frames = discontig_frames, out_frame = pfn;
++	unsigned int i;
++	int rc, success;
++	struct xen_memory_exchange exchange = {
++		.in = {
++			.nr_extents   = 1UL << order,
++			.extent_order = 0,
++			.domid        = DOMID_SELF
++		},
++		.out = {
++			.nr_extents   = 1,
++			.extent_order = order,
++			.address_bits = address_bits,
++			.domid        = DOMID_SELF
++		}
++	};
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 0;
++
++	if (unlikely(order > MAX_CONTIG_ORDER))
++		return -ENOMEM;
++
++	for (i = 0; i < (1U << order); ++i) {
++		in_frames[i] = pfn_to_mfn(pfn + i);
++		set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY);
++	}
++
++	set_xen_guest_handle(exchange.in.extent_start, in_frames);
++	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
++
++	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
++	success = (exchange.nr_exchanged == (1UL << order));
++	BUG_ON(!success && (exchange.nr_exchanged || !rc));
++	BUG_ON(success && rc);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		/* Compatibility when XENMEM_exchange is unavailable. */
++		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					 &exchange.in) != (1UL << order))
++			BUG();
++		success = (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++						&exchange.out) == 1);
++		if (!success) {
++			for (i = 0; i < (1U << order); ++i)
++				in_frames[i] = pfn + i;
++			if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++						 &exchange.in) != (1UL << order))
++				BUG();
++		}
++	}
++#endif
++
++	for (i = 0; i < (1U << order); ++i, ++out_frame) {
++		if (!success)
++			out_frame = in_frames[i];
++		set_phys_to_machine(pfn + i, out_frame);
++	}
++
++	return success ? 0 : -ENOMEM;
++}
++
+ static void undo_limit_pages(struct page *pages, unsigned int order)
+ {
+ 	BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+@@ -879,42 +945,9 @@ int write_ldt_entry(struct desc_struct *
+ 	return HYPERVISOR_update_descriptor(mach_lp, *(const u64*)desc);
+ }
+ 
+-#define MAX_BATCHED_FULL_PTES 32
+-
+-int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-			 unsigned long addr, unsigned long end, pgprot_t newprot,
+-			 int dirty_accountable)
++int write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc,
++		    int type)
+ {
+-	int rc = 0, i = 0;
+-	mmu_update_t u[MAX_BATCHED_FULL_PTES];
+-	pte_t *pte;
+-	spinlock_t *ptl;
+-
+-	if (!xen_feature(XENFEAT_mmu_pt_update_preserve_ad))
+-		return 0;
+-
+-	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+-	do {
+-		if (pte_present(*pte)) {
+-			pte_t ptent = pte_modify(*pte, newprot);
+-
+-			if (dirty_accountable && pte_dirty(ptent))
+-				ptent = pte_mkwrite(ptent);
+-			u[i].ptr = (__pmd_val(*pmd) & PHYSICAL_PAGE_MASK)
+-				   | ((unsigned long)pte & ~PAGE_MASK)
+-				   | MMU_PT_UPDATE_PRESERVE_AD;
+-			u[i].val = __pte_val(ptent);
+-			if (++i == MAX_BATCHED_FULL_PTES) {
+-				if ((rc = HYPERVISOR_mmu_update(
+-					&u[0], i, NULL, DOMID_SELF)) != 0)
+-					break;
+-				i = 0;
+-			}
+-		}
+-	} while (pte++, addr += PAGE_SIZE, addr != end);
+-	if (i)
+-		rc = HYPERVISOR_mmu_update( &u[0], i, NULL, DOMID_SELF);
+-	pte_unmap_unlock(pte - 1, ptl);
+-	BUG_ON(rc && rc != -ENOSYS);
+-	return !rc;
++	maddr_t mach_gp = virt_to_machine(gdt + entry);
++	return HYPERVISOR_update_descriptor(mach_gp, *(const u64*)desc);
+ }
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -54,6 +54,7 @@
+ 
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+ 
++unsigned long max_low_pfn_mapped;
+ unsigned long max_pfn_mapped;
+ 
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+@@ -61,6 +62,27 @@ unsigned long highstart_pfn, highend_pfn
+ 
+ static noinline int do_test_wp_bit(void);
+ 
++
++static unsigned long __initdata table_start;
++static unsigned long __initdata table_end;
++static unsigned long __initdata table_top;
++
++static int __initdata after_init_bootmem;
++
++static __init void *alloc_low_page(unsigned long *phys)
++{
++	unsigned long pfn = table_end++;
++	void *adr;
++
++	if (pfn >= table_top)
++		panic("alloc_low_page: ran out of memory");
++
++	adr = __va(pfn * PAGE_SIZE);
++	memset(adr, 0, PAGE_SIZE);
++	*phys  = pfn * PAGE_SIZE;
++	return adr;
++}
++
+ /*
+  * Creates a middle page table and puts a pointer to it in the
+  * given global directory entry. This only returns the gd entry
+@@ -72,9 +94,12 @@ static pmd_t * __init one_md_table_init(
+ 	pmd_t *pmd_table;
+ 
+ #ifdef CONFIG_X86_PAE
++	unsigned long phys;
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+-		pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+-
++		if (after_init_bootmem)
++			pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
++		else
++			pmd_table = (pmd_t *)alloc_low_page(&phys);
+ 		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+ 		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+@@ -101,12 +126,16 @@ static pte_t * __init one_page_table_ini
+ #endif
+ 		pte_t *page_table = NULL;
+ 
++		if (after_init_bootmem) {
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+-		page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
++			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+ #endif
+-		if (!page_table) {
+-			page_table =
++			if (!page_table)
++				page_table =
+ 				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
++		} else {
++			unsigned long phys;
++			page_table = (pte_t *)alloc_low_page(&phys);
+ 		}
+ 
+ 		paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+@@ -167,24 +196,24 @@ static inline int is_kernel_text(unsigne
+  * of max_low_pfn pages, by creating page tables starting from address
+  * PAGE_OFFSET:
+  */
+-static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
++static void __init kernel_physical_mapping_init(pgd_t *pgd_base,
++						unsigned long start_pfn,
++						unsigned long end_pfn,
++						int use_pse)
+ {
+ 	int pgd_idx, pmd_idx, pte_ofs;
+ 	unsigned long pfn;
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
++	unsigned pages_2m = 0, pages_4k = 0;
+ 
+-	unsigned long max_ram_pfn = xen_start_info->nr_pages;
+-	if (max_ram_pfn > max_low_pfn)
+-		max_ram_pfn = max_low_pfn;
++	if (!cpu_has_pse)
++		use_pse = 0;
+ 
+-	pgd_idx = pgd_index(PAGE_OFFSET);
++	pfn = start_pfn;
++	pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+ 	pgd = pgd_base + pgd_idx;
+-	pfn = 0;
+-	pmd_idx = pmd_index(PAGE_OFFSET);
+-	pte_ofs = pte_index(PAGE_OFFSET);
+-
+ 	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+ #ifdef CONFIG_XEN
+ 		/*
+@@ -198,10 +227,16 @@ static void __init kernel_physical_mappi
+ #else
+ 		pmd = one_md_table_init(pgd);
+ #endif
+-		if (pfn >= max_low_pfn)
++
++		if (pfn >= end_pfn)
+ 			continue;
++#ifdef CONFIG_X86_PAE
++		pmd_idx = pmd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+ 		pmd += pmd_idx;
+-		for (; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn;
++#else
++		pmd_idx = 0;
++#endif
++		for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn;
+ 		     pmd++, pmd_idx++) {
+ 			unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET;
+ 
+@@ -211,13 +246,8 @@ static void __init kernel_physical_mappi
+ 			/*
+ 			 * Map with big pages if possible, otherwise
+ 			 * create normal page tables:
+-			 *
+-			 * Don't use a large page for the first 2/4MB of memory
+-			 * because there are often fixed size MTRRs in there
+-			 * and overlapping MTRRs into large pages can cause
+-			 * slowdowns.
+ 			 */
+-			if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == 0)) {
++			if (use_pse) {
+ 				unsigned int addr2;
+ 				pgprot_t prot = PAGE_KERNEL_LARGE;
+ 
+@@ -228,49 +258,35 @@ static void __init kernel_physical_mappi
+ 				    is_kernel_text(addr2))
+ 					prot = PAGE_KERNEL_LARGE_EXEC;
+ 
++				pages_2m++;
+ 				set_pmd(pmd, pfn_pmd(pfn, prot));
+ 
+ 				pfn += PTRS_PER_PTE;
+-				max_pfn_mapped = pfn;
+ 				continue;
+ 			}
+ 			pte = one_page_table_init(pmd);
+ 
+-			for (pte += pte_ofs;
+-			     pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
++			pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
++			pte += pte_ofs;
++			for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn;
+ 			     pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) {
+ 				pgprot_t prot = PAGE_KERNEL;
+ 
+ 				/* XEN: Only map initial RAM allocation. */
+-				if ((pfn >= max_ram_pfn) || pte_present(*pte))
++				if (pfn >= xen_start_info->nr_pages || pte_present(*pte))
+ 					continue;
+ 				if (is_kernel_text(addr))
+ 					prot = PAGE_KERNEL_EXEC;
+ 
++				pages_4k++;
+ 				set_pte(pte, pfn_pte(pfn, prot));
+ 			}
+-			max_pfn_mapped = pfn;
+-			pte_ofs = 0;
+ 		}
+-		pmd_idx = 0;
+ 	}
++	update_page_count(PG_LEVEL_2M, pages_2m);
++	update_page_count(PG_LEVEL_4K, pages_4k);
+ }
+ 
+-#ifndef CONFIG_XEN
+-
+-static inline int page_kills_ppro(unsigned long pagenr)
+-{
+-	if (pagenr >= 0x70000 && pagenr <= 0x7003F)
+-		return 1;
+-	return 0;
+-}
+-
+-#else
+-
+-#define page_kills_ppro(p)	0
+-
+-#endif
+-
+ /*
+  * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+  * is valid. The argument is a physical page number.
+@@ -331,33 +347,66 @@ static void __init permanent_kmaps_init(
+ 	pkmap_page_table = pte;
+ }
+ 
+-void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
++static void __init add_one_highpage_init(struct page *page, int pfn)
+ {
+-	if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
+-		ClearPageReserved(page);
+-		init_page_count(page);
+-		__free_page(page);
+-		totalhigh_pages++;
+-	} else
+-		SetPageReserved(page);
++	ClearPageReserved(page);
++	init_page_count(page);
++	__free_page(page);
++	totalhigh_pages++;
++}
++
++struct add_highpages_data {
++	unsigned long start_pfn;
++	unsigned long end_pfn;
++};
++
++static int __init add_highpages_work_fn(unsigned long start_pfn,
++					 unsigned long end_pfn, void *datax)
++{
++	int node_pfn;
++	struct page *page;
++	unsigned long final_start_pfn, final_end_pfn;
++	struct add_highpages_data *data;
++
++	data = (struct add_highpages_data *)datax;
++
++	final_start_pfn = max(start_pfn, data->start_pfn);
++	final_end_pfn = min(end_pfn, data->end_pfn);
++	if (final_start_pfn >= final_end_pfn)
++		return 0;
++
++	for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
++	     node_pfn++) {
++		if (!pfn_valid(node_pfn))
++			continue;
++		page = pfn_to_page(node_pfn);
++		add_one_highpage_init(page, node_pfn);
++	}
++
++	return 0;
++
++}
++
++void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
++					      unsigned long end_pfn)
++{
++	struct add_highpages_data data;
++
++	data.start_pfn = start_pfn;
++	data.end_pfn = end_pfn;
++
++	work_with_active_regions(nid, add_highpages_work_fn, &data);
+ }
+ 
+ #ifndef CONFIG_NUMA
+-static void __init set_highmem_pages_init(int bad_ppro)
++static void __init set_highmem_pages_init(void)
+ {
+ 	int pfn;
+ 
+-	for (pfn = highstart_pfn; pfn < highend_pfn
+-				  && pfn < xen_start_info->nr_pages; pfn++) {
+-		/*
+-		 * Holes under sparsemem might not have no mem_map[]:
+-		 */
+-		if (pfn_valid(pfn))
+-			add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
+-	}
++	add_highpages_with_active_regions(0, highstart_pfn, highend_pfn);
+ 
+ 	/* XEN: init high-mem pages outside initial allocation. */
+-	for (; pfn < highend_pfn; pfn++) {
++	for (pfn = xen_start_info->nr_pages; pfn < highend_pfn; pfn++) {
+ 		ClearPageReserved(pfn_to_page(pfn));
+ 		init_page_count(pfn_to_page(pfn));
+ 	}
+@@ -369,24 +418,11 @@ static void __init set_highmem_pages_ini
+ #else
+ # define kmap_init()				do { } while (0)
+ # define permanent_kmaps_init(pgd_base)		do { } while (0)
+-# define set_highmem_pages_init(bad_ppro)	do { } while (0)
++# define set_highmem_pages_init()	do { } while (0)
+ #endif /* CONFIG_HIGHMEM */
+ 
+-pteval_t __PAGE_KERNEL = _PAGE_KERNEL;
+-EXPORT_SYMBOL(__PAGE_KERNEL);
+-
+-pteval_t __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
+-
+ pgd_t *swapper_pg_dir;
+ 
+-static void __init xen_pagetable_setup_start(pgd_t *base)
+-{
+-}
+-
+-static void __init xen_pagetable_setup_done(pgd_t *base)
+-{
+-}
+-
+ /*
+  * Build a proper pagetable for the kernel mappings.  Up until this
+  * point, we've been running on some set of pagetables constructed by
+@@ -406,27 +442,10 @@ static void __init xen_pagetable_setup_d
+  * be partially populated, and so it avoids stomping on any existing
+  * mappings.
+  */
+-static void __init pagetable_init(void)
++static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base)
+ {
+-	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
+ 	unsigned long vaddr, end;
+ 
+-	xen_pagetable_setup_start(pgd_base);
+-
+-	/* Enable PSE if available */
+-	if (cpu_has_pse)
+-		set_in_cr4(X86_CR4_PSE);
+-
+-	/* Enable PGE if available */
+-	if (cpu_has_pge) {
+-		set_in_cr4(X86_CR4_PGE);
+-		__PAGE_KERNEL |= _PAGE_GLOBAL;
+-		__PAGE_KERNEL_EXEC |= _PAGE_GLOBAL;
+-	}
+-
+-	kernel_physical_mapping_init(pgd_base);
+-	remap_numa_kva();
+-
+ 	/*
+ 	 * Fixed mappings, only the page table structure has to be
+ 	 * created - mappings will be set by set_fixmap():
+@@ -436,10 +455,13 @@ static void __init pagetable_init(void)
+ 	end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+ 	page_table_range_init(vaddr, end, pgd_base);
+ 	early_ioremap_reset();
++}
+ 
+-	permanent_kmaps_init(pgd_base);
++static void __init pagetable_init(void)
++{
++	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
+ 
+-	xen_pagetable_setup_done(pgd_base);
++	permanent_kmaps_init(pgd_base);
+ }
+ 
+ #if defined(CONFIG_ACPI_SLEEP) && !defined(CONFIG_XEN)
+@@ -482,7 +504,7 @@ void zap_low_mappings(void)
+ 
+ int nx_enabled;
+ 
+-pteval_t __supported_pte_mask __read_mostly = ~_PAGE_NX;
++pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+ #ifdef CONFIG_X86_PAE
+@@ -535,42 +557,364 @@ static void __init set_nx(void)
+ }
+ #endif
+ 
++/* user-defined highmem size */
++static unsigned int highmem_pages = -1;
++
+ /*
+- * paging_init() sets up the page tables - note that the first 8MB are
+- * already mapped by head.S.
+- *
+- * This routines also unmaps the page at virtual kernel address 0, so
+- * that we can trap those pesky NULL-reference errors in the kernel.
++ * highmem=size forces highmem to be exactly 'size' bytes.
++ * This works even on boxes that have no highmem otherwise.
++ * This also works to reduce highmem size on bigger boxes.
+  */
+-void __init paging_init(void)
++static int __init parse_highmem(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++
++	highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
++	return 0;
++}
++early_param("highmem", parse_highmem);
++
++/*
++ * Determine low and high memory ranges:
++ */
++void __init find_low_pfn_range(void)
++{
++	/* it could update max_pfn */
++
++	/* max_low_pfn is 0, we already have early_res support */
++
++	max_low_pfn = max_pfn;
++	if (max_low_pfn > MAXMEM_PFN) {
++		if (highmem_pages == -1)
++			highmem_pages = max_pfn - MAXMEM_PFN;
++		if (highmem_pages + MAXMEM_PFN < max_pfn)
++			max_pfn = MAXMEM_PFN + highmem_pages;
++		if (highmem_pages + MAXMEM_PFN > max_pfn) {
++			printk(KERN_WARNING "only %luMB highmem pages "
++				"available, ignoring highmem size of %uMB.\n",
++				pages_to_mb(max_pfn - MAXMEM_PFN),
++				pages_to_mb(highmem_pages));
++			highmem_pages = 0;
++		}
++		max_low_pfn = MAXMEM_PFN;
++#ifndef CONFIG_HIGHMEM
++		/* Maximum memory usable is what is directly addressable */
++		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
++					MAXMEM>>20);
++		if (max_pfn > MAX_NONPAE_PFN)
++			printk(KERN_WARNING
++				 "Use a HIGHMEM64G enabled kernel.\n");
++		else
++			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
++		max_pfn = MAXMEM_PFN;
++#else /* !CONFIG_HIGHMEM */
++#ifndef CONFIG_HIGHMEM64G
++		if (max_pfn > MAX_NONPAE_PFN) {
++			max_pfn = MAX_NONPAE_PFN;
++			printk(KERN_WARNING "Warning only 4GB will be used."
++				"Use a HIGHMEM64G enabled kernel.\n");
++		}
++#endif /* !CONFIG_HIGHMEM64G */
++#endif /* !CONFIG_HIGHMEM */
++	} else {
++		if (highmem_pages == -1)
++			highmem_pages = 0;
++#ifdef CONFIG_HIGHMEM
++		if (highmem_pages >= max_pfn) {
++			printk(KERN_ERR "highmem size specified (%uMB) is "
++				"bigger than pages available (%luMB)!.\n",
++				pages_to_mb(highmem_pages),
++				pages_to_mb(max_pfn));
++			highmem_pages = 0;
++		}
++		if (highmem_pages) {
++			if (max_low_pfn - highmem_pages <
++			    64*1024*1024/PAGE_SIZE){
++				printk(KERN_ERR "highmem size %uMB results in "
++				"smaller than 64MB lowmem, ignoring it.\n"
++					, pages_to_mb(highmem_pages));
++				highmem_pages = 0;
++			}
++			max_low_pfn -= highmem_pages;
++		}
++#else
++		if (highmem_pages)
++			printk(KERN_ERR "ignoring highmem size on non-highmem"
++					" kernel!\n");
++#endif
++	}
++}
++
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++void __init initmem_init(unsigned long start_pfn,
++				  unsigned long end_pfn)
++{
++#ifdef CONFIG_HIGHMEM
++	highstart_pfn = highend_pfn = max_pfn;
++	if (max_pfn > max_low_pfn)
++		highstart_pfn = max_low_pfn;
++	memory_present(0, 0, highend_pfn);
++	e820_register_active_regions(0, 0, highend_pfn);
++	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
++		pages_to_mb(highend_pfn - highstart_pfn));
++	num_physpages = highend_pfn;
++	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
++#else
++	memory_present(0, 0, max_low_pfn);
++	e820_register_active_regions(0, 0, max_low_pfn);
++	num_physpages = max_low_pfn;
++	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
++#endif
++#ifdef CONFIG_FLATMEM
++	max_mapnr = num_physpages;
++#endif
++	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
++			pages_to_mb(max_low_pfn));
++
++	setup_bootmem_allocator();
++}
++#endif /* !CONFIG_NEED_MULTIPLE_NODES */
++
++static void __init zone_sizes_init(void)
++{
++	unsigned long max_zone_pfns[MAX_NR_ZONES];
++	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
++	max_zone_pfns[ZONE_DMA] =
++		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
++	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
++#ifdef CONFIG_HIGHMEM
++	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
++#endif
++
++	free_area_init_nodes(max_zone_pfns);
++}
++
++void __init setup_bootmem_allocator(void)
+ {
+ 	int i;
++	unsigned long bootmap_size, bootmap;
++	unsigned long end_pfn = min(max_low_pfn, xen_start_info->nr_pages);
++
++	/*
++	 * Initialize the boot-time allocator (with low memory only):
++	 */
++	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
++	bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT,
++				 min(max_pfn_mapped, xen_start_info->nr_pages)<<PAGE_SHIFT,
++				 bootmap_size, PAGE_SIZE);
++	if (bootmap == -1L)
++		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
++	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
++
++	/* don't touch min_low_pfn */
++	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
++					 min_low_pfn, end_pfn);
++	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
++		 max_pfn_mapped<<PAGE_SHIFT);
++	printk(KERN_INFO "  low ram: %08lx - %08lx\n",
++		 min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT);
++	printk(KERN_INFO "  bootmap %08lx - %08lx\n",
++		 bootmap, bootmap + bootmap_size);
++	for_each_online_node(i)
++		free_bootmem_with_active_regions(i, end_pfn);
++	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
++
++	after_init_bootmem = 1;
++}
++
++static unsigned long __init extend_init_mapping(unsigned long tables_space)
++{
++	unsigned long start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT)
++				  + xen_start_info->nr_pt_frames;
++	unsigned long start = start_pfn, va = (unsigned long)&_text;
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	/* Ensure init mappings cover kernel text/data and initial tables. */
++	while (va < PAGE_OFFSET + (start_pfn << PAGE_SHIFT) + tables_space) {
++		pgd = pgd_offset_k(va);
++		pud = pud_offset(pgd, va);
++		pmd = pmd_offset(pud, va);
++		if (pmd_none(*pmd)) {
++			unsigned long pa = start_pfn++ << PAGE_SHIFT;
++
++			memset(__va(pa), 0, PAGE_SIZE);
++			make_lowmem_page_readonly(__va(pa),
++						  XENFEAT_writable_page_tables);
++			xen_l2_entry_update(pmd, __pmd(pa | _KERNPG_TABLE));
++		}
++		pte = pte_offset_kernel(pmd, va);
++		if (pte_none(*pte)) {
++			pte_t new_pte = __pte(__pa(va) | _KERNPG_TABLE);
++
++			if (HYPERVISOR_update_va_mapping(va, new_pte, 0))
++				BUG();
++		}
++		va += PAGE_SIZE;
++	}
++
++	/* Finally, blow away any spurious initial mappings. */
++	while (1) {
++		pgd = pgd_offset_k(va);
++		pud = pud_offset(pgd, va);
++		pmd = pmd_offset(pud, va);
++		if (pmd_none(*pmd))
++			break;
++		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++			BUG();
++		va += PAGE_SIZE;
++	}
++
++	if (start_pfn > start)
++		reserve_early(start << PAGE_SHIFT,
++			      start_pfn << PAGE_SHIFT, "INITMAP");
++
++	return start_pfn;
++}
++
++static void __init find_early_table_space(unsigned long end)
++{
++	unsigned long puds, pmds, ptes, tables;
++
++	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
++	tables = PAGE_ALIGN(puds * sizeof(pud_t));
++
++	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
++	tables += PAGE_ALIGN(pmds * sizeof(pmd_t));
++
++	if (cpu_has_pse) {
++		unsigned long extra;
++
++		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
++		extra += PMD_SIZE;
++		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	} else
++		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++	tables += PAGE_ALIGN(ptes * sizeof(pte_t));
++
++	/* for fixmap */
++	tables += PAGE_SIZE
++	          * ((((FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK)
++	              - (__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK))
++	             >> PMD_SHIFT);
++
++	table_start = extend_init_mapping(tables);
++
++	table_end = table_start;
++	table_top = table_start + (tables>>PAGE_SHIFT);
++
++	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
++		end, table_start << PAGE_SHIFT,
++		(table_start << PAGE_SHIFT) + tables);
++}
++
++unsigned long __init_refok init_memory_mapping(unsigned long start,
++						unsigned long end)
++{
++	pgd_t *pgd_base = swapper_pg_dir;
++	unsigned long start_pfn, end_pfn;
++	unsigned long big_page_start;
++
++	/*
++	 * Find space for the kernel direct mapping tables.
++	 */
++	if (!after_init_bootmem)
++		find_early_table_space(end);
+ 
+ #ifdef CONFIG_X86_PAE
+ 	set_nx();
+ 	if (nx_enabled)
+ 		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+ #endif
++
++	/* Enable PSE if available */
++	if (cpu_has_pse)
++		set_in_cr4(X86_CR4_PSE);
++
++	/* Enable PGE if available */
++	if (cpu_has_pge) {
++		set_in_cr4(X86_CR4_PGE);
++		__supported_pte_mask |= _PAGE_GLOBAL;
++	}
++
++	/*
++	 * Don't use a large page for the first 2/4MB of memory
++	 * because there are often fixed size MTRRs in there
++	 * and overlapping MTRRs into large pages can cause
++	 * slowdowns.
++	 */
++	big_page_start = PMD_SIZE;
++
++	if (start < big_page_start) {
++		start_pfn = start >> PAGE_SHIFT;
++		end_pfn = min(big_page_start>>PAGE_SHIFT, end>>PAGE_SHIFT);
++	} else {
++		/* head is not big page alignment ? */
++		start_pfn = start >> PAGE_SHIFT;
++		end_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
++				 << (PMD_SHIFT - PAGE_SHIFT);
++	}
++	if (start_pfn < end_pfn)
++		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn, 0);
++
++	/* big page range */
++	start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
++			 << (PMD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < (big_page_start >> PAGE_SHIFT))
++		start_pfn =  big_page_start >> PAGE_SHIFT;
++	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < end_pfn)
++		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn,
++						cpu_has_pse);
++
++	/* tail is not big page alignment ? */
++	start_pfn = end_pfn;
++	if (start_pfn > (big_page_start>>PAGE_SHIFT)) {
++		end_pfn = end >> PAGE_SHIFT;
++		if (start_pfn < end_pfn)
++			kernel_physical_mapping_init(pgd_base, start_pfn,
++							 end_pfn, 0);
++	}
++
++	early_ioremap_page_table_range_init(pgd_base);
++
++	__flush_tlb_all();
++
++	if (!after_init_bootmem)
++		reserve_early(table_start << PAGE_SHIFT,
++			      table_end << PAGE_SHIFT, "PGTABLE");
++
++	if (!after_init_bootmem)
++		early_memtest(start, end);
++
++	return end >> PAGE_SHIFT;
++}
++
++
++/*
++ * paging_init() sets up the page tables - note that the first 8MB are
++ * already mapped by head.S.
++ *
++ * This routines also unmaps the page at virtual kernel address 0, so
++ * that we can trap those pesky NULL-reference errors in the kernel.
++ */
++void __init paging_init(void)
++{
+ 	pagetable_init();
+ 
+ 	__flush_tlb_all();
+ 
+ 	kmap_init();
+ 
+-	/* Switch to the real shared_info page, and clear the
+-	 * dummy page. */
+-	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+-	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+-	memset(empty_zero_page, 0, sizeof(empty_zero_page));
+-
+-	/* Setup mapping of lower 1st MB */
+-	for (i = 0; i < NR_FIX_ISAMAPS; i++)
+-		if (is_initial_xendomain())
+-			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
+-		else
+-			__set_fixmap(FIX_ISAMAP_BEGIN - i,
+-				     virt_to_machine(empty_zero_page),
+-				     PAGE_KERNEL_RO);
++	/*
++	 * NOTE: at this point the bootmem allocator is fully available.
++	 */
++	sparse_init();
++	zone_sizes_init();
+ }
+ 
+ /*
+@@ -605,7 +949,7 @@ static struct kcore_list kcore_mem, kcor
+ void __init mem_init(void)
+ {
+ 	int codesize, reservedpages, datasize, initsize;
+-	int tmp, bad_ppro;
++	int tmp;
+ 	unsigned long pfn;
+ 
+ 	pci_iommu_alloc();
+@@ -613,19 +957,6 @@ void __init mem_init(void)
+ #ifdef CONFIG_FLATMEM
+ 	BUG_ON(!mem_map);
+ #endif
+-	bad_ppro = ppro_with_ram_bug();
+-
+-#ifdef CONFIG_HIGHMEM
+-	/* check that fixmap and pkmap do not overlap */
+-	if (PKMAP_BASE + LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+-		printk(KERN_ERR
+-			"fixmap and kmap areas overlap - this will crash\n");
+-		printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+-				PKMAP_BASE, PKMAP_BASE + LAST_PKMAP*PAGE_SIZE,
+-				FIXADDR_START);
+-		BUG();
+-	}
+-#endif
+ 	/* this will put all low memory onto the freelists */
+ 	totalram_pages += free_all_bootmem();
+ 	/* XEN: init low-mem pages outside initial allocation. */
+@@ -642,7 +973,7 @@ void __init mem_init(void)
+ 		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
+ 			reservedpages++;
+ 
+-	set_highmem_pages_init(bad_ppro);
++	set_highmem_pages_init();
+ 
+ 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+ 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+@@ -663,7 +994,6 @@ void __init mem_init(void)
+ 		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
+ 	       );
+ 
+-#if 1 /* double-sanity-check paranoia */
+ 	printk(KERN_INFO "virtual kernel memory layout:\n"
+ 		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+ #ifdef CONFIG_HIGHMEM
+@@ -704,7 +1034,6 @@ void __init mem_init(void)
+ #endif
+ 	BUG_ON(VMALLOC_START				> VMALLOC_END);
+ 	BUG_ON((unsigned long)high_memory		> VMALLOC_START);
+-#endif /* double-sanity-check paranoia */
+ 
+ 	if (boot_cpu_data.wp_works_ok < 0)
+ 		test_wp_bit();
+@@ -761,6 +1090,8 @@ void mark_rodata_ro(void)
+ 	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long size = PFN_ALIGN(_etext) - start;
+ 
++#ifndef CONFIG_DYNAMIC_FTRACE
++	/* Dynamic tracing modifies the kernel text section */
+ 	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+ 	printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+ 		size >> 10);
+@@ -773,6 +1104,8 @@ void mark_rodata_ro(void)
+ 	printk(KERN_INFO "Testing CPA: write protecting again\n");
+ 	set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+ #endif
++#endif /* CONFIG_DYNAMIC_FTRACE */
++
+ 	start += size;
+ 	size = (unsigned long)__end_rodata - start;
+ 	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+@@ -835,3 +1168,9 @@ void free_initrd_mem(unsigned long start
+ 	free_init_pages("initrd memory", start, end);
+ }
+ #endif
++
++int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
++				   int flags)
++{
++	return reserve_bootmem(phys, len, flags);
++}
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -21,6 +21,7 @@
+ #include <linux/swap.h>
+ #include <linux/smp.h>
+ #include <linux/init.h>
++#include <linux/initrd.h>
+ #include <linux/pagemap.h>
+ #include <linux/bootmem.h>
+ #include <linux/proc_fs.h>
+@@ -52,6 +53,14 @@
+ 
+ #include <xen/features.h>
+ 
++/*
++ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
++ * The direct mapping extends to max_pfn_mapped, so that we can directly access
++ * apertures, ACPI and other tables without having to play with fixmaps.
++ */
++unsigned long max_low_pfn_mapped;
++unsigned long max_pfn_mapped;
++
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ unsigned int __kernel_page_user;
+ EXPORT_SYMBOL(__kernel_page_user);
+@@ -60,7 +69,6 @@ EXPORT_SYMBOL(__kernel_page_user);
+ int after_bootmem;
+ 
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+-extern unsigned long start_pfn;
+ 
+ extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
+ extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
+@@ -118,7 +126,7 @@ void __meminit early_make_page_readonly(
+ }
+ 
+ #ifndef CONFIG_XEN
+-int direct_gbpages __meminitdata
++int direct_gbpages
+ #ifdef CONFIG_DIRECT_GBPAGES
+ 				= 1
+ #endif
+@@ -145,55 +153,23 @@ early_param("gbpages", parse_direct_gbpa
+  * around without checking the pgd every time.
+  */
+ 
+-void show_mem(void)
+-{
+-	long i, total = 0, reserved = 0;
+-	long shared = 0, cached = 0;
+-	struct page *page;
+-	pg_data_t *pgdat;
+-
+-	printk(KERN_INFO "Mem-info:\n");
+-	show_free_areas();
+-	for_each_online_pgdat(pgdat) {
+-		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+-			/*
+-			 * This loop can take a while with 256 GB and
+-			 * 4k pages so defer the NMI watchdog:
+-			 */
+-			if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+-				touch_nmi_watchdog();
+-
+-			if (!pfn_valid(pgdat->node_start_pfn + i))
+-				continue;
+-
+-			page = pfn_to_page(pgdat->node_start_pfn + i);
+-			total++;
+-			if (PageReserved(page))
+-				reserved++;
+-			else if (PageSwapCache(page))
+-				cached++;
+-			else if (page_count(page))
+-				shared += page_count(page) - 1;
+-		}
+-	}
+-	printk(KERN_INFO "%lu pages of RAM\n",		total);
+-	printk(KERN_INFO "%lu reserved pages\n",	reserved);
+-	printk(KERN_INFO "%lu pages shared\n",		shared);
+-	printk(KERN_INFO "%lu pages swap cached\n",	cached);
+-}
+-
+ static unsigned long __meminitdata table_start;
+-static unsigned long __meminitdata table_end;
++static unsigned long __meminitdata table_cur;
++static unsigned long __meminitdata table_top;
+ 
+-static __init void *spp_getpage(void)
++/*
++ * NOTE: This function is marked __ref because it calls __init function
++ * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
++ */
++static __ref void *spp_getpage(void)
+ {
+ 	void *ptr;
+ 
+ 	if (after_bootmem)
+ 		ptr = (void *) get_zeroed_page(GFP_ATOMIC);
+-	else if (start_pfn < table_end) {
+-		ptr = __va(start_pfn << PAGE_SHIFT);
+-		start_pfn++;
++	else if (table_cur < table_top) {
++		ptr = __va(table_cur << PAGE_SHIFT);
++		table_cur++;
+ 		memset(ptr, 0, PAGE_SIZE);
+ 	} else
+ 		ptr = alloc_bootmem_pages(PAGE_SIZE);
+@@ -208,30 +184,18 @@ static __init void *spp_getpage(void)
+ 	return ptr;
+ }
+ 
+-#define pgd_offset_u(address) (__user_pgd(init_level4_pgt) + pgd_index(address))
+-#define pud_offset_u(address) (level3_user_pgt + pud_index(address))
+-
+-static __init void
+-set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot, int user_mode)
++void
++set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte)
+ {
+-	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+-	pte_t *pte, new_pte;
+-
+-	pr_debug("set_pte_phys %lx to %lx\n", vaddr, phys);
++	pte_t *pte;
+ 
+-	pgd = (user_mode ? pgd_offset_u(vaddr) : pgd_offset_k(vaddr));
+-	if (pgd_none(*pgd)) {
+-		printk(KERN_ERR
+-			"PGD FIXMAP MISSING, it should be setup in head.S!\n");
+-		return;
+-	}
+-	pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr));
++	pud = pud_page + pud_index(vaddr);
+ 	if (pud_none(*pud)) {
+ 		pmd = (pmd_t *) spp_getpage();
+ 		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+-		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
++		pud_populate(&init_mm, pud, pmd);
+ 		if (pmd != pmd_offset(pud, 0)) {
+ 			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
+ 				pmd, pmd_offset(pud, 0));
+@@ -242,19 +206,20 @@ set_pte_phys(unsigned long vaddr, unsign
+ 	if (pmd_none(*pmd)) {
+ 		pte = (pte_t *) spp_getpage();
+ 		make_page_readonly(pte, XENFEAT_writable_page_tables);
+-		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
++		pmd_populate_kernel(&init_mm, pmd, pte);
+ 		if (pte != pte_offset_kernel(pmd, 0)) {
+ 			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+ 			return;
+ 		}
+ 	}
+-	if (pgprot_val(prot))
+-		new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
+-	else
+-		new_pte = __pte(0);
+ 
+ 	pte = pte_offset_kernel(pmd, vaddr);
+ 	if (!pte_none(*pte) && __pte_val(new_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);
+@@ -266,15 +231,13 @@ set_pte_phys(unsigned long vaddr, unsign
+ 	__flush_tlb_one(vaddr);
+ }
+ 
+-static __init void
+-set_pte_phys_ma(unsigned long vaddr, unsigned long phys, pgprot_t prot)
++void
++set_pte_vaddr(unsigned long vaddr, pte_t pteval)
+ {
+ 	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte, new_pte;
++	pud_t *pud_page;
+ 
+-	pr_debug("set_pte_phys_ma %lx to %lx\n", vaddr, phys);
++	pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, __pte_val(pteval));
+ 
+ 	pgd = pgd_offset_k(vaddr);
+ 	if (pgd_none(*pgd)) {
+@@ -282,47 +245,51 @@ set_pte_phys_ma(unsigned long vaddr, uns
+ 			"PGD FIXMAP MISSING, it should be setup in head.S!\n");
+ 		return;
+ 	}
+-	pud = pud_offset(pgd, vaddr);
+-	if (pud_none(*pud)) {
+-		pmd = (pmd_t *) spp_getpage();
+-		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+-		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+-		if (pmd != pmd_offset(pud, 0)) {
+-			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
+-				pmd, pmd_offset(pud, 0));
++	pud_page = (pud_t*)pgd_page_vaddr(*pgd);
++	set_pte_vaddr_pud(pud_page, vaddr, pteval);
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Create large page table mappings for a range of physical addresses.
++ */
++static void __init __init_extra_mapping(unsigned long phys, unsigned long size,
++						pgprot_t prot)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++
++	BUG_ON((phys & ~PMD_MASK) || (size & ~PMD_MASK));
++	for (; size; phys += PMD_SIZE, size -= PMD_SIZE) {
++		pgd = pgd_offset_k((unsigned long)__va(phys));
++		if (pgd_none(*pgd)) {
++			pud = (pud_t *) spp_getpage();
++			set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE |
++						_PAGE_USER));
+ 		}
+-	}
+-	pmd = pmd_offset(pud, vaddr);
+-	if (pmd_none(*pmd)) {
+-		pte = (pte_t *) spp_getpage();
+-		make_page_readonly(pte, XENFEAT_writable_page_tables);
+-		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+-		if (pte != pte_offset_kernel(pmd, 0)) {
+-			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+-			return;
++		pud = pud_offset(pgd, (unsigned long)__va(phys));
++		if (pud_none(*pud)) {
++			pmd = (pmd_t *) spp_getpage();
++			set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE |
++						_PAGE_USER));
+ 		}
++		pmd = pmd_offset(pud, phys);
++		BUG_ON(!pmd_none(*pmd));
++		set_pmd(pmd, __pmd(phys | pgprot_val(prot)));
+ 	}
+-	new_pte = pfn_pte_ma(phys >> PAGE_SHIFT, prot);
++}
+ 
+-	pte = pte_offset_kernel(pmd, vaddr);
+-	if (!pte_none(*pte) && __pte_val(new_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);
++void __init init_extra_mapping_wb(unsigned long phys, unsigned long size)
++{
++	__init_extra_mapping(phys, size, PAGE_KERNEL_LARGE);
++}
+ 
+-	/*
+-	 * It's enough to flush this one mapping.
+-	 * (PGE mappings get flushed as well)
+-	 */
+-	__flush_tlb_one(vaddr);
++void __init init_extra_mapping_uc(unsigned long phys, unsigned long size)
++{
++	__init_extra_mapping(phys, size, PAGE_KERNEL_LARGE_NOCACHE);
+ }
+ 
+-#ifndef CONFIG_XEN
+ /*
+  * The head.S code sets up the kernel high mapping:
+  *
+@@ -352,63 +319,52 @@ void __init cleanup_highmap(void)
+ }
+ #endif
+ 
+-/* NOTE: this is meant to be run only at boot */
+-void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++static __ref void *alloc_low_page(unsigned long *phys)
+ {
+-	unsigned long address = __fix_to_virt(idx);
+-
+-	if (idx >= __end_of_fixed_addresses) {
+-		printk(KERN_ERR "Invalid __set_fixmap\n");
+-		return;
+-	}
+-	switch (idx) {
+-	case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
+-		set_pte_phys(address, phys, prot, 0);
+-		set_pte_phys(address, phys, prot, 1);
+-		break;
+-	case FIX_EARLYCON_MEM_BASE:
+-		xen_l1_entry_update(level1_fixmap_pgt + pte_index(address),
+-				    pfn_pte_ma(phys >> PAGE_SHIFT, prot));
+-		break;
+-	default:
+-		set_pte_phys_ma(address, phys, prot);
+-		break;
+-	}
+-}
+-
+-static __meminit void *alloc_static_page(unsigned long *phys)
+-{
+-	unsigned long va = (start_pfn << PAGE_SHIFT) + __START_KERNEL_map;
++	unsigned long pfn;
++	void *adr;
+ 
+ 	if (after_bootmem) {
+-		void *adr = (void *)get_zeroed_page(GFP_ATOMIC);
++		adr = (void *)get_zeroed_page(GFP_ATOMIC);
+ 		*phys = __pa(adr);
+ 
+ 		return adr;
+ 	}
+ 
+-	*phys = start_pfn << PAGE_SHIFT;
+-	start_pfn++;
+-	memset((void *)va, 0, PAGE_SIZE);
+-	return (void *)va;
++	BUG_ON(!table_cur);
++	pfn = table_cur++;
++	if (pfn >= table_top)
++		panic("alloc_low_page: ran out of memory");
++
++	adr = early_ioremap(pfn_to_mfn(pfn) * PAGE_SIZE, PAGE_SIZE);
++	memset(adr, 0, PAGE_SIZE);
++	*phys  = pfn * PAGE_SIZE;
++	return adr;
+ }
+ 
+-#define PTE_SIZE PAGE_SIZE
++static __ref void unmap_low_page(void *adr)
++{
++	if (after_bootmem)
++		return;
++
++	early_iounmap(adr, PAGE_SIZE);
++}
+ 
+ static inline int __meminit make_readonly(unsigned long paddr)
+ {
+ 	extern char __vsyscall_0;
+ 	int readonly = 0;
+ 
+-	/* Make new page tables read-only. */
++	/* Make new page tables read-only on the first pass. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
++	    && !max_pfn_mapped
+ 	    && (paddr >= (table_start << PAGE_SHIFT))
+-	    && (paddr < (table_end << PAGE_SHIFT)))
++	    && (paddr < (table_top << PAGE_SHIFT)))
+ 		readonly = 1;
+ 	/* Make old page tables read-only. */
+ 	if (!xen_feature(XENFEAT_writable_page_tables)
+ 	    && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+-	    && (paddr < (start_pfn << PAGE_SHIFT)))
++	    && (paddr < (table_cur << PAGE_SHIFT)))
+ 		readonly = 1;
+ 
+ 	/*
+@@ -425,118 +381,131 @@ static inline int __meminit make_readonl
+ 	return readonly;
+ }
+ 
+-#ifndef CONFIG_XEN
+-/* Must run before zap_low_mappings */
+-__meminit void *early_ioremap(unsigned long addr, unsigned long size)
++static unsigned long __meminit
++phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end)
+ {
+-	pmd_t *pmd, *last_pmd;
+-	unsigned long vaddr;
+-	int i, pmds;
+-
+-	pmds = ((addr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+-	vaddr = __START_KERNEL_map;
+-	pmd = level2_kernel_pgt;
+-	last_pmd = level2_kernel_pgt + PTRS_PER_PMD - 1;
+-
+-	for (; pmd <= last_pmd; pmd++, vaddr += PMD_SIZE) {
+-		for (i = 0; i < pmds; i++) {
+-			if (pmd_present(pmd[i]))
+-				goto continue_outer_loop;
+-		}
+-		vaddr += addr & ~PMD_MASK;
+-		addr &= PMD_MASK;
++	unsigned pages = 0;
++	unsigned long last_map_addr = end;
++	int i;
++
++	pte_t *pte = pte_page + pte_index(addr);
++
++	for(i = pte_index(addr); i < PTRS_PER_PTE; i++, addr += PAGE_SIZE, pte++) {
++		unsigned long pteval = addr | __PAGE_KERNEL;
++
++		if (addr >= end ||
++		    (!after_bootmem &&
++		     (addr >> PAGE_SHIFT) >= xen_start_info->nr_pages))
++			break;
++
++		if (__pte_val(*pte))
++			continue;
+ 
+-		for (i = 0; i < pmds; i++, addr += PMD_SIZE)
+-			set_pmd(pmd+i, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
+-		__flush_tlb_all();
+-
+-		return (void *)vaddr;
+-continue_outer_loop:
+-		;
++		if (make_readonly(addr))
++			pteval &= ~_PAGE_RW;
++		if (0)
++			printk("   pte=%p addr=%lx pte=%016lx\n",
++			       pte, addr, pteval);
++		if (!after_bootmem)
++			*pte = __pte(pteval & __supported_pte_mask);
++		else
++			set_pte(pte, __pte(pteval & __supported_pte_mask));
++		last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE;
++		pages++;
+ 	}
+-	printk("early_ioremap(0x%lx, %lu) failed\n", addr, size);
+-	return NULL;
++	update_page_count(PG_LEVEL_4K, pages);
++
++	return last_map_addr;
+ }
+ 
+-/*
+- * To avoid virtual aliases later:
+- */
+-__meminit void early_iounmap(void *addr, unsigned long size)
++static unsigned long __meminit
++phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end)
+ {
+-	unsigned long vaddr;
+-	pmd_t *pmd;
+-	int i, pmds;
+-
+-	vaddr = (unsigned long)addr;
+-	pmds = ((vaddr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+-	pmd = level2_kernel_pgt + pmd_index(vaddr);
++	pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
+ 
+-	for (i = 0; i < pmds; i++)
+-		pmd_clear(pmd + i);
+-
+-	__flush_tlb_all();
++	BUG_ON(!max_pfn_mapped);
++	return phys_pte_init(pte, address, end);
+ }
+-#endif
+ 
+ static unsigned long __meminit
+-phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
++phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
++			 unsigned long page_size_mask)
+ {
++	unsigned long pages = 0;
++	unsigned long last_map_addr = end;
++	unsigned long start = address;
++
+ 	int i = pmd_index(address);
+ 
+-	for (; i < PTRS_PER_PMD; i++) {
++	for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
+ 		unsigned long pte_phys;
+-		pmd_t *pmd = pmd_page + i;
+-		pte_t *pte, *pte_save;
+-		int k;
++		pmd_t *pmd = pmd_page + pmd_index(address);
++		pte_t *pte;
+ 
+ 		if (address >= end)
+ 			break;
+ 
+ 		if (__pmd_val(*pmd)) {
+-			address += PMD_SIZE;
++			if (!pmd_large(*pmd)) {
++				spin_lock(&init_mm.page_table_lock);
++				last_map_addr = phys_pte_update(pmd, address,
++								end);
++				spin_unlock(&init_mm.page_table_lock);
++			}
++			/* Count entries we're using from level2_ident_pgt */
++			if (start == 0)
++				pages++;
+ 			continue;
+ 		}
+ 
+-		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 ||
+-			    (!after_bootmem &&
+-			     (address >> PAGE_SHIFT) >= xen_start_info->nr_pages))
+-				pteval = 0;
+-			else if (make_readonly(address))
+-				pteval &= ~_PAGE_RW;
+-			set_pte(pte, __pte(pteval & __supported_pte_mask));
++		if (page_size_mask & (1<<PG_LEVEL_2M)) {
++			pages++;
++			spin_lock(&init_mm.page_table_lock);
++			set_pte((pte_t *)pmd,
++				pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++			spin_unlock(&init_mm.page_table_lock);
++			last_map_addr = (address & PMD_MASK) + PMD_SIZE;
++			continue;
+ 		}
++
++		pte = alloc_low_page(&pte_phys);
++		last_map_addr = phys_pte_init(pte, address, end);
++		unmap_low_page(pte);
++
+ 		if (!after_bootmem) {
+-			early_make_page_readonly(pte_save, XENFEAT_writable_page_tables);
+-			*pmd = __pmd(pte_phys | _KERNPG_TABLE);
++			if (max_pfn_mapped)
++				make_page_readonly(__va(pte_phys),
++						   XENFEAT_writable_page_tables);
++			*pmd = __pmd(pte_phys | _PAGE_TABLE);
+ 		} else {
+-			make_page_readonly(pte_save, XENFEAT_writable_page_tables);
+-			set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
++			make_page_readonly(pte, XENFEAT_writable_page_tables);
++			spin_lock(&init_mm.page_table_lock);
++			pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
++			spin_unlock(&init_mm.page_table_lock);
+ 		}
+ 	}
+-	return address;
++	update_page_count(PG_LEVEL_2M, pages);
++	return last_map_addr;
+ }
+ 
+ static unsigned long __meminit
+-phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
++phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
++			 unsigned long page_size_mask)
+ {
+ 	pmd_t *pmd = pmd_offset(pud, 0);
+ 	unsigned long last_map_addr;
+ 
+-	spin_lock(&init_mm.page_table_lock);
+-	last_map_addr = phys_pmd_init(pmd, address, end);
+-	spin_unlock(&init_mm.page_table_lock);
++	BUG_ON(!max_pfn_mapped);
++	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask);
+ 	__flush_tlb_all();
+ 	return last_map_addr;
+ }
+ 
+ static unsigned long __meminit
+-phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
++phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
++			 unsigned long page_size_mask)
+ {
++	unsigned long pages = 0;
+ 	unsigned long last_map_addr = end;
+ 	int i = pud_index(addr);
+ 
+@@ -550,29 +519,55 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 
+ 		if (__pud_val(*pud)) {
+ 			if (!pud_large(*pud))
+-				last_map_addr = phys_pmd_update(pud, addr, end);
++				last_map_addr = phys_pmd_update(pud, addr, end,
++							 page_size_mask);
+ 			continue;
+ 		}
+ 
+-		if (direct_gbpages) {
++		if (page_size_mask & (1<<PG_LEVEL_1G)) {
++			pages++;
++			spin_lock(&init_mm.page_table_lock);
+ 			set_pte((pte_t *)pud,
+ 				pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++			spin_unlock(&init_mm.page_table_lock);
+ 			last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+ 			continue;
+ 		}
+ 
+-		pmd = alloc_static_page(&pmd_phys);
+-
+-		spin_lock(&init_mm.page_table_lock);
+-		*pud = __pud(pmd_phys | _KERNPG_TABLE);
+-		last_map_addr = phys_pmd_init(pmd, addr, end);
+-		spin_unlock(&init_mm.page_table_lock);
++		pmd = alloc_low_page(&pmd_phys);
++		last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask);
++		unmap_low_page(pmd);
+ 
+-		early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
++		if (!after_bootmem) {
++			if (max_pfn_mapped)
++				make_page_readonly(__va(pmd_phys),
++						   XENFEAT_writable_page_tables);
++			if (page_size_mask & (1 << PG_LEVEL_NUM))
++				xen_l3_entry_update(pud, __pud(pmd_phys | _PAGE_TABLE));
++			else
++				*pud = __pud(pmd_phys | _PAGE_TABLE);
++		} else {
++			make_page_readonly(pmd, XENFEAT_writable_page_tables);
++			spin_lock(&init_mm.page_table_lock);
++			pud_populate(&init_mm, pud, __va(pmd_phys));
++			spin_unlock(&init_mm.page_table_lock);
++		}
+ 	}
+ 	__flush_tlb_all();
++	update_page_count(PG_LEVEL_1G, pages);
+ 
+-	return last_map_addr >> PAGE_SHIFT;
++	return last_map_addr;
++}
++
++static unsigned long __meminit
++phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
++		 unsigned long page_size_mask)
++{
++	pud_t *pud;
++
++	pud = (pud_t *)pgd_page_vaddr(*pgd);
++
++	return phys_pud_init(pud, addr, end, page_size_mask | (1 << PG_LEVEL_NUM));
+ }
+ 
+ void __init xen_init_pt(void)
+@@ -656,112 +651,36 @@ void __init xen_init_pt(void)
+ 	}
+ }
+ 
+-static void __init extend_init_mapping(unsigned long tables_space)
+-{
+-	unsigned long va = __START_KERNEL_map;
+-	unsigned long start = start_pfn;
+-	unsigned long phys, addr, *pte_page;
+-	pmd_t *pmd;
+-	pte_t *pte, new_pte;
+-	unsigned long *page = (unsigned long *)init_level4_pgt;
+-
+-	addr = page[pgd_index(va)];
+-	addr_to_page(addr, page);
+-	addr = page[pud_index(va)];
+-	addr_to_page(addr, page);
+-
+-	/* Kill mapping of low 1MB. */
+-	while (va < (unsigned long)&_text) {
+-		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+-			BUG();
+-		va += PAGE_SIZE;
+-	}
+-
+-	/* Ensure init mappings cover kernel text/data and initial tables. */
+-	while (va < (__START_KERNEL_map
+-		     + (start_pfn << PAGE_SHIFT)
+-		     + tables_space)) {
+-		if (!(pmd_index(va) | pte_index(va))) {
+-			pud_t *pud;
+-
+-			page = (unsigned long *)init_level4_pgt;
+-			addr = page[pgd_index(va)];
+-			addr_to_page(addr, page);
+-			pud = (pud_t *)&page[pud_index(va)];
+-			if (pud_none(*pud)) {
+-				page = alloc_static_page(&phys);
+-				early_make_page_readonly(
+-					page, XENFEAT_writable_page_tables);
+-				set_pud(pud, __pud(phys | _KERNPG_TABLE));
+-			} else {
+-				addr = page[pud_index(va)];
+-				addr_to_page(addr, page);
+-			}
+-		}
+-		pmd = (pmd_t *)&page[pmd_index(va)];
+-		if (pmd_none(*pmd)) {
+-			pte_page = alloc_static_page(&phys);
+-			early_make_page_readonly(
+-				pte_page, XENFEAT_writable_page_tables);
+-			set_pmd(pmd, __pmd(phys | _KERNPG_TABLE));
+-		} else {
+-			addr = page[pmd_index(va)];
+-			addr_to_page(addr, pte_page);
+-		}
+-		pte = (pte_t *)&pte_page[pte_index(va)];
+-		if (pte_none(*pte)) {
+-			new_pte = pfn_pte(
+-				(va - __START_KERNEL_map) >> PAGE_SHIFT, 
+-				__pgprot(_KERNPG_TABLE));
+-			xen_l1_entry_update(pte, new_pte);
+-		}
+-		va += PAGE_SIZE;
+-	}
+-
+-	/* Finally, blow away any spurious initial mappings. */
+-	while (1) {
+-		if (!(pmd_index(va) | pte_index(va))) {
+-			page = (unsigned long *)init_level4_pgt;
+-			addr = page[pgd_index(va)];
+-			addr_to_page(addr, page);
+-			if (pud_none(((pud_t *)page)[pud_index(va)]))
+-				break;
+-			addr = page[pud_index(va)];
+-			addr_to_page(addr, page);
+-		}
+-		pmd = (pmd_t *)&page[pmd_index(va)];
+-		if (pmd_none(*pmd))
+-			break;
+-		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+-			BUG();
+-		va += PAGE_SIZE;
+-	}
+-
+-	if (start_pfn > start)
+-		reserve_early(start << PAGE_SHIFT,
+-			      start_pfn << PAGE_SHIFT, "INITMAP");
+-}
+-
+ static void __init find_early_table_space(unsigned long end)
+ {
+ 	unsigned long puds, pmds, ptes, tables;
+ 
+ 	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
++	tables = round_up(puds * sizeof(pud_t), PAGE_SIZE);
+ 	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+-	ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
++	tables += round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
+ 
+-	tables = round_up(puds * 8, PAGE_SIZE) + 
+-		round_up(pmds * 8, PAGE_SIZE) + 
+-		round_up(ptes * 8, PAGE_SIZE); 
++	ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	tables += round_up(ptes * sizeof(pte_t), PAGE_SIZE);
+ 
+-	extend_init_mapping(tables);
++	if (!table_top) {
++		table_start = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
++			xen_start_info->nr_pt_frames;
++		table_cur = table_start;
++	} else {
++		/*
++		 * [table_start, table_top) gets passed to reserve_early(),
++		 * so we must not use table_cur here, despite continuing
++		 * to allocate from there. table_cur possibly being below
++		 * table_start is otoh not a problem.
++		 */
++		table_start = table_top;
++	}
+ 
+-	table_start = start_pfn;
+-	table_end = table_start + (tables>>PAGE_SHIFT);
++	table_top = table_cur + (tables >> PAGE_SHIFT);
+ 
+-	early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
+-		end, table_start << PAGE_SHIFT,
+-		(table_start << PAGE_SHIFT) + tables);
++	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
++		end, table_cur << PAGE_SHIFT, table_top << PAGE_SHIFT);
+ }
+ 
+ static void __init xen_finish_init_mapping(void)
+@@ -783,18 +702,18 @@ static void __init xen_finish_init_mappi
+ 		xen_start_info->mod_start = (unsigned long)
+ 			__va(__pa(xen_start_info->mod_start));
+ 
+-	/* Destroy the Xen-created mappings beyond the kernel image as
+-	 * well as the temporary mappings created above. Prevents
+-	 * overlap with modules area (if init mapping is very big).
+-	 */
++	/* Destroy the Xen-created mappings beyond the kernel image. */
+ 	start = PAGE_ALIGN((unsigned long)_end);
+-	end   = __START_KERNEL_map + (table_end << PAGE_SHIFT);
++	end   = __START_KERNEL_map + (table_start << PAGE_SHIFT);
+ 	for (; start < end; start += PAGE_SIZE)
+ 		if (HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0))
+ 			BUG();
+ 
+-	/* Allocate pte's for initial fixmaps from 'start_pfn' allocator. */
+-	table_end = ~0UL;
++	/* Allocate pte's for initial fixmaps from 'table_cur' allocator. */
++	start = table_top;
++	WARN(table_cur != start, "start=%lx cur=%lx top=%lx\n",
++	     table_start, table_cur, start);
++	table_top = ~0UL;
+ 
+ 	/* Switch to the real shared_info page, and clear the dummy page. */
+ 	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+@@ -811,8 +730,7 @@ static void __init xen_finish_init_mappi
+ 				     << PAGE_SHIFT,
+ 				     PAGE_KERNEL_RO);
+ 
+-	/* Disable the 'start_pfn' allocator. */
+-	table_end = start_pfn;
++	table_top = max(table_cur, start);
+ }
+ 
+ static void __init init_gbpages(void)
+@@ -825,126 +743,91 @@ static void __init init_gbpages(void)
+ #endif
+ }
+ 
+-#ifdef CONFIG_MEMTEST_BOOTPARAM
+-
+-static void __init memtest(unsigned long start_phys, unsigned long size,
+-				 unsigned pattern)
++static unsigned long __init kernel_physical_mapping_init(unsigned long start,
++						unsigned long end,
++						unsigned long page_size_mask)
+ {
+-	unsigned long i;
+-	unsigned long *start;
+-	unsigned long start_bad;
+-	unsigned long last_bad;
+-	unsigned long val;
+-	unsigned long start_phys_aligned;
+-	unsigned long count;
+-	unsigned long incr;
+-
+-	switch (pattern) {
+-	case 0:
+-		val = 0UL;
+-		break;
+-	case 1:
+-		val = -1UL;
+-		break;
+-	case 2:
+-		val = 0x5555555555555555UL;
+-		break;
+-	case 3:
+-		val = 0xaaaaaaaaaaaaaaaaUL;
+-		break;
+-	default:
+-		return;
+-	}
+-
+-	incr = sizeof(unsigned long);
+-	start_phys_aligned = ALIGN(start_phys, incr);
+-	count = (size - (start_phys_aligned - start_phys))/incr;
+-	start = __va(start_phys_aligned);
+-	start_bad = 0;
+-	last_bad = 0;
+-
+-	for (i = 0; i < count; i++)
+-		start[i] = val;
+-	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
+-		if (*start != val) {
+-			if (start_phys_aligned == last_bad + incr) {
+-				last_bad += incr;
+-			} else {
+-				if (start_bad) {
+-					printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
+-						val, start_bad, last_bad + incr);
+-					reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
+-				}
+-				start_bad = last_bad = start_phys_aligned;
+-			}
+-		}
+-	}
+-	if (start_bad) {
+-		printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
+-			val, start_bad, last_bad + incr);
+-		reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
+-	}
+ 
+-}
++	unsigned long next, last_map_addr = end;
+ 
+-static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE;
++	start = (unsigned long)__va(start);
++	end = (unsigned long)__va(end);
+ 
+-static int __init parse_memtest(char *arg)
+-{
+-	if (arg)
+-		memtest_pattern = simple_strtoul(arg, NULL, 0);
+-	return 0;
+-}
++	for (; start < end; start = next) {
++		pgd_t *pgd = pgd_offset_k(start);
++		unsigned long pud_phys;
++		pud_t *pud;
+ 
+-early_param("memtest", parse_memtest);
++		next = (start + PGDIR_SIZE) & PGDIR_MASK;
++		if (next > end)
++			next = end;
+ 
+-static void __init early_memtest(unsigned long start, unsigned long end)
+-{
+-	u64 t_start, t_size;
+-	unsigned pattern;
++		if (__pgd_val(*pgd)) {
++			last_map_addr = phys_pud_update(pgd, __pa(start),
++						 __pa(end), page_size_mask);
++			continue;
++		}
+ 
+-	if (!memtest_pattern)
+-		return;
++		pud = alloc_low_page(&pud_phys);
++		last_map_addr = phys_pud_init(pud, __pa(start), __pa(next),
++						 page_size_mask);
++		unmap_low_page(pud);
++
++		if(!after_bootmem) {
++			if (max_pfn_mapped)
++				make_page_readonly(__va(pud_phys),
++						   XENFEAT_writable_page_tables);
++			xen_l4_entry_update(pgd, __pgd(pud_phys | _PAGE_TABLE));
++		} else {
++			make_page_readonly(pud, XENFEAT_writable_page_tables);
++			spin_lock(&init_mm.page_table_lock);
++			pgd_populate(&init_mm, pgd, __va(pud_phys));
++			spin_unlock(&init_mm.page_table_lock);
++		}
++	}
+ 
+-	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
+-	for (pattern = 0; pattern < memtest_pattern; pattern++) {
+-		t_start = start;
+-		t_size = 0;
+-		while (t_start < end) {
+-			t_start = find_e820_area_size(t_start, &t_size, 1);
++	return last_map_addr;
++}
+ 
+-			/* done ? */
+-			if (t_start >= end)
+-				break;
+-			if (t_start + t_size > end)
+-				t_size = end - t_start;
++struct map_range {
++	unsigned long start;
++	unsigned long end;
++	unsigned page_size_mask;
++};
+ 
+-			printk(KERN_CONT "\n  %016llx - %016llx pattern %d",
+-				(unsigned long long)t_start,
+-				(unsigned long long)t_start + t_size, pattern);
++#define NR_RANGE_MR 5
+ 
+-			memtest(t_start, t_size, pattern);
++static int save_mr(struct map_range *mr, int nr_range,
++		   unsigned long start_pfn, unsigned long end_pfn,
++		   unsigned long page_size_mask)
++{
+ 
+-			t_start += t_size;
+-		}
++	if (start_pfn < end_pfn) {
++		if (nr_range >= NR_RANGE_MR)
++			panic("run out of range for init_memory_mapping\n");
++		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
++		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
++		mr[nr_range].page_size_mask = page_size_mask;
++		nr_range++;
+ 	}
+-	printk(KERN_CONT "\n");
+-}
+-#else
+-static void __init early_memtest(unsigned long start, unsigned long end)
+-{
++
++	return nr_range;
+ }
+-#endif
+ 
+ /*
+  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+  * This runs before bootmem is initialized and gets pages directly from
+  * the physical memory. To access them they are temporarily mapped.
+  */
+-unsigned long __init_refok init_memory_mapping(unsigned long start, unsigned long end)
++unsigned long __init_refok init_memory_mapping(unsigned long start,
++					       unsigned long end)
+ {
+-	unsigned long next, last_map_addr = end;
+-	unsigned long start_phys = start, end_phys = end;
++	unsigned long last_map_addr = 0;
++	unsigned long page_size_mask = 0;
++	unsigned long start_pfn, end_pfn;
++
++	struct map_range mr[NR_RANGE_MR];
++	int nr_range, i;
+ 
+ 	printk(KERN_INFO "init_memory_mapping\n");
+ 
+@@ -955,51 +838,150 @@ unsigned long __init_refok init_memory_m
+ 	 * memory mapped. Unfortunately this is done currently before the
+ 	 * nodes are discovered.
+ 	 */
+-	if (!after_bootmem) {
++	if (!after_bootmem)
+ 		init_gbpages();
+-		find_early_table_space(end);
++
++	if (direct_gbpages)
++		page_size_mask |= 1 << PG_LEVEL_1G;
++	if (cpu_has_pse)
++		page_size_mask |= 1 << PG_LEVEL_2M;
++
++	memset(mr, 0, sizeof(mr));
++	nr_range = 0;
++
++	/* head if not big page alignment ?*/
++	start_pfn = start >> PAGE_SHIFT;
++	end_pfn = ((start + (PMD_SIZE - 1)) >> PMD_SHIFT)
++			<< (PMD_SHIFT - PAGE_SHIFT);
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++
++	/* big page (2M) range*/
++	start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
++			 << (PMD_SHIFT - PAGE_SHIFT);
++	end_pfn = ((start + (PUD_SIZE - 1))>>PUD_SHIFT)
++			 << (PUD_SHIFT - PAGE_SHIFT);
++	if (end_pfn > ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT)))
++		end_pfn = ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT));
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++			page_size_mask & (1<<PG_LEVEL_2M));
++
++	/* big page (1G) range */
++	start_pfn = end_pfn;
++	end_pfn = (end>>PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask &
++				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
++
++	/* tail is not big page (1G) alignment */
++	start_pfn = end_pfn;
++	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++			page_size_mask & (1<<PG_LEVEL_2M));
++
++	/* tail is not big page (2M) alignment */
++	start_pfn = end_pfn;
++	end_pfn = end>>PAGE_SHIFT;
++	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++
++	/* try to merge same page size and continuous */
++	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
++		unsigned long old_start;
++		if (mr[i].end != mr[i+1].start ||
++		    mr[i].page_size_mask != mr[i+1].page_size_mask)
++			continue;
++		/* move it */
++		old_start = mr[i].start;
++		memmove(&mr[i], &mr[i+1],
++			 (nr_range - 1 - i) * sizeof (struct map_range));
++		mr[i--].start = old_start;
++		nr_range--;
+ 	}
+ 
+-	start = (unsigned long)__va(start);
+-	end = (unsigned long)__va(end);
++	for (i = 0; i < nr_range; i++)
++		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
++				mr[i].start, mr[i].end,
++			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
++			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
+ 
+-	for (; start < end; start = next) {
+-		pgd_t *pgd = pgd_offset_k(start);
+-		unsigned long pud_phys;
+-		pud_t *pud;
++	if (!after_bootmem)
++		find_early_table_space(end);
+ 
+-		if (after_bootmem)
+-			pud = pud_offset(pgd, start & PGDIR_MASK);
+-		else
+-			pud = alloc_static_page(&pud_phys);
+-		next = start + PGDIR_SIZE;
+-		if (next > end)
+-			next = end;
+-		last_map_addr = phys_pud_init(pud, __pa(start), __pa(next));
+-		if (!after_bootmem) {
+-			early_make_page_readonly(pud, XENFEAT_writable_page_tables);
+-			set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
++	if (!start) {
++		unsigned long addr, va = __START_KERNEL_map;
++		unsigned long *page = (unsigned long *)init_level4_pgt;
++
++		/* Kill mapping of memory below _text. */
++		while (va < (unsigned long)&_text) {
++			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++				BUG();
++			va += PAGE_SIZE;
++		}
++
++		/* Blow away any spurious initial mappings. */
++		va = __START_KERNEL_map + (table_start << PAGE_SHIFT);
++		addr = page[pgd_index(va)];
++		addr_to_page(addr, page);
++		addr = page[pud_index(va)];
++		addr_to_page(addr, page);
++		while (pmd_index(va) | pte_index(va)) {
++			if (pmd_none(*(pmd_t *)&page[pmd_index(va)]))
++				break;
++			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++				BUG();
++			va += PAGE_SIZE;
+ 		}
+ 	}
+ 
+-	if (!after_bootmem) {
+-		BUG_ON(start_pfn != table_end);
++	for (i = 0; i < nr_range; i++)
++		last_map_addr = kernel_physical_mapping_init(
++					mr[i].start, mr[i].end,
++					mr[i].page_size_mask);
++
++	BUG_ON(table_cur > table_top);
++	if (!start)
+ 		xen_finish_init_mapping();
+-	}
++	else if (table_cur < table_top)
++		/* Disable the 'table_cur' allocator. */
++		table_top = table_cur;
+ 
+ 	__flush_tlb_all();
+ 
+-	if (!after_bootmem)
++	if (!after_bootmem && table_top > table_start)
+ 		reserve_early(table_start << PAGE_SHIFT,
+-			      table_end << PAGE_SHIFT, "PGTABLE");
++			      table_top << PAGE_SHIFT, "PGTABLE");
++
++	printk(KERN_INFO "last_map_addr: %lx end: %lx\n",
++			 last_map_addr, end);
+ 
+ 	if (!after_bootmem)
+-		early_memtest(start_phys, end_phys);
++		early_memtest(start, end);
+ 
+-	return last_map_addr;
++	return last_map_addr >> PAGE_SHIFT;
+ }
+ 
+ #ifndef CONFIG_NUMA
++void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn)
++{
++	unsigned long bootmap_size, bootmap;
++
++	e820_register_active_regions(0, start_pfn, end_pfn);
++#ifdef CONFIG_XEN
++	if (end_pfn > xen_start_info->nr_pages)
++		end_pfn = xen_start_info->nr_pages;
++#endif
++	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
++	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
++				 PAGE_SIZE);
++	if (bootmap == -1L)
++		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
++	/* don't touch min_low_pfn */
++	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
++					 0, end_pfn);
++	free_bootmem_with_active_regions(0, end_pfn);
++	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
++	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
++}
++
+ void __init paging_init(void)
+ {
+ 	unsigned long max_zone_pfns[MAX_NR_ZONES];
+@@ -1007,9 +989,9 @@ void __init paging_init(void)
+ 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ 	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+ 	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+-	max_zone_pfns[ZONE_NORMAL] = end_pfn;
++	max_zone_pfns[ZONE_NORMAL] = max_pfn;
+ 
+-	memory_present(0, 0, end_pfn);
++	memory_present(0, 0, max_pfn);
+ 	sparse_init();
+ 	free_area_init_nodes(max_zone_pfns);
+ 
+@@ -1099,8 +1081,8 @@ void __init mem_init(void)
+ 		ClearPageReserved(pfn_to_page(pfn));
+ 		init_page_count(pfn_to_page(pfn));
+ 	}
+-	reservedpages = end_pfn - totalram_pages -
+-					absent_pages_in_range(0, end_pfn);
++	reservedpages = max_pfn - totalram_pages -
++					absent_pages_in_range(0, max_pfn);
+ 	after_bootmem = 1;
+ 
+ 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+@@ -1119,7 +1101,7 @@ void __init mem_init(void)
+ 	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+ 				"%ldk reserved, %ldk data, %ldk init)\n",
+ 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+-		end_pfn << (PAGE_SHIFT-10),
++		max_pfn << (PAGE_SHIFT-10),
+ 		codesize >> 10,
+ 		reservedpages << (PAGE_SHIFT-10),
+ 		datasize >> 10,
+@@ -1182,6 +1164,13 @@ EXPORT_SYMBOL_GPL(rodata_test_data);
+ void mark_rodata_ro(void)
+ {
+ 	unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
++	unsigned long rodata_start =
++		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
++
++#ifdef CONFIG_DYNAMIC_FTRACE
++	/* Dynamic tracing modifies the kernel text section */
++	start = rodata_start;
++#endif
+ 
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
+@@ -1191,8 +1180,7 @@ void mark_rodata_ro(void)
+ 	 * The rodata section (but not the kernel text!) should also be
+ 	 * not-executable.
+ 	 */
+-	start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+-	set_memory_nx(start, (end - start) >> PAGE_SHIFT);
++	set_memory_nx(rodata_start, (end - rodata_start) >> PAGE_SHIFT);
+ 
+ 	rodata_test();
+ 
+@@ -1214,24 +1202,26 @@ void free_initrd_mem(unsigned long start
+ }
+ #endif
+ 
+-void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
++int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
++				   int flags)
+ {
+ #ifdef CONFIG_NUMA
+ 	int nid, next_nid;
++	int ret;
+ #endif
+ 	unsigned long pfn = phys >> PAGE_SHIFT;
+ 
+-	if (pfn >= end_pfn) {
++	if (pfn >= max_pfn) {
+ 		/*
+ 		 * This can happen with kdump kernels when accessing
+ 		 * firmware tables:
+ 		 */
+ 		if (pfn < max_pfn_mapped)
+-			return;
++			return -EFAULT;
+ 
+-		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
++		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n",
+ 				phys, len);
+-		return;
++		return -EFAULT;
+ 	}
+ 
+ 	/* Should check here against the e820 map to avoid double free */
+@@ -1239,9 +1229,13 @@ void __init reserve_bootmem_generic(unsi
+ 	nid = phys_to_nid(phys);
+ 	next_nid = phys_to_nid(phys + len - 1);
+ 	if (nid == next_nid)
+-		reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++		ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags);
+ 	else
+-		reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
++		ret = reserve_bootmem(phys, len, flags);
++
++	if (ret != 0)
++		return ret;
++
+ #else
+ 	reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #endif
+@@ -1252,6 +1246,8 @@ void __init reserve_bootmem_generic(unsi
+ 		set_dma_reserve(dma_reserve);
+ 	}
+ #endif
++
++	return 0;
+ }
+ 
+ int kern_addr_valid(unsigned long addr)
+@@ -1356,7 +1352,7 @@ vmemmap_populate(struct page *start_page
+ 	pmd_t *pmd;
+ 
+ 	for (; addr < end; addr = next) {
+-		next = pmd_addr_end(addr, end);
++		void *p = NULL;
+ 
+ 		pgd = vmemmap_pgd_populate(addr, node);
+ 		if (!pgd)
+@@ -1366,33 +1362,51 @@ vmemmap_populate(struct page *start_page
+ 		if (!pud)
+ 			return -ENOMEM;
+ 
+-		pmd = pmd_offset(pud, addr);
+-		if (pmd_none(*pmd)) {
+-			pte_t entry;
+-			void *p;
++		if (!cpu_has_pse) {
++			next = (addr + PAGE_SIZE) & PAGE_MASK;
++			pmd = vmemmap_pmd_populate(pud, addr, node);
++
++			if (!pmd)
++				return -ENOMEM;
++
++			p = vmemmap_pte_populate(pmd, addr, node);
+ 
+-			p = vmemmap_alloc_block(PMD_SIZE, node);
+ 			if (!p)
+ 				return -ENOMEM;
+ 
+-			entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
+-							PAGE_KERNEL_LARGE);
+-			set_pmd(pmd, __pmd_ma(__pte_val(entry)));
+-
+-			/* check to see if we have contiguous blocks */
+-			if (p_end != p || node_start != node) {
+-				if (p_start)
+-					printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
+-						addr_start, addr_end-1, p_start, p_end-1, node_start);
+-				addr_start = addr;
+-				node_start = node;
+-				p_start = p;
+-			}
+-			addr_end = addr + PMD_SIZE;
+-			p_end = p + PMD_SIZE;
++			addr_end = addr + PAGE_SIZE;
++			p_end = p + PAGE_SIZE;
+ 		} else {
+-			vmemmap_verify((pte_t *)pmd, node, addr, next);
++			next = pmd_addr_end(addr, end);
++
++			pmd = pmd_offset(pud, addr);
++			if (pmd_none(*pmd)) {
++				pte_t entry;
++
++				p = vmemmap_alloc_block(PMD_SIZE, node);
++				if (!p)
++					return -ENOMEM;
++
++				entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
++						PAGE_KERNEL_LARGE);
++				set_pmd(pmd, __pmd_ma(__pte_val(entry)));
++
++				/* check to see if we have contiguous blocks */
++				if (p_end != p || node_start != node) {
++					if (p_start)
++						printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
++						       addr_start, addr_end-1, p_start, p_end-1, node_start);
++					addr_start = addr;
++					node_start = node;
++					p_start = p;
++				}
++
++				addr_end = addr + PMD_SIZE;
++				p_end = p + PMD_SIZE;
++			} else
++				vmemmap_verify((pte_t *)pmd, node, addr, next);
+ 		}
++
+ 	}
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <linux/pfn.h>
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
++#include <linux/mmiotrace.h>
+ 
+ #include <asm/cacheflush.h>
+ #include <asm/e820.h>
+@@ -274,7 +275,8 @@ int ioremap_check_change_attr(unsigned l
+ 	for (sz = rc = 0; sz < size && !rc; ++mfn, sz += PAGE_SIZE) {
+ 		unsigned long pfn = mfn_to_local_pfn(mfn);
+ 
+-		if (pfn >= max_pfn_mapped)
++		if (pfn >= max_low_pfn_mapped &&
++		    (pfn < (1UL<<(32 - PAGE_SHIFT)) || pfn >= max_pfn_mapped))
+ 			continue;
+ 		rc = ioremap_change_attr((unsigned long)__va(pfn << PAGE_SHIFT),
+ 					 PAGE_SIZE, prot_val);
+@@ -297,11 +299,14 @@ static void __iomem *__ioremap_caller(re
+ {
+ 	unsigned long mfn, offset, vaddr;
+ 	resource_size_t last_addr;
++	const resource_size_t unaligned_phys_addr = phys_addr;
++	const unsigned long unaligned_size = size;
+ 	struct vm_struct *area;
+ 	unsigned long new_prot_val;
+ 	pgprot_t prot;
+ 	int retval;
+ 	domid_t domid = DOMID_IO;
++	void __iomem *ret_addr;
+ 
+ 	/* Don't allow wraparound or zero size */
+ 	last_addr = phys_addr + size - 1;
+@@ -318,7 +323,7 @@ static void __iomem *__ioremap_caller(re
+ 	/*
+ 	 * Don't remap the low PCI/ISA area, it's always mapped..
+ 	 */
+-	if (is_initial_xendomain() && last_addr < ISA_END_ADDRESS)
++	if (is_initial_xendomain() && is_ISA_range(phys_addr, last_addr))
+ 		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
+ 
+ 	/*
+@@ -342,7 +347,7 @@ static void __iomem *__ioremap_caller(re
+ 	phys_addr &= PAGE_MASK;
+ 	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+ 
+-	retval = reserve_memtype(phys_addr, phys_addr + size,
++	retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
+ 						prot_val, &new_prot_val);
+ 	if (retval) {
+ 		pr_debug("Warning: reserve_memtype returned %d\n", retval);
+@@ -410,7 +415,10 @@ static void __iomem *__ioremap_caller(re
+ 		return NULL;
+ 	}
+ 
+-	return (void __iomem *) (vaddr + offset);
++	ret_addr = (void __iomem *) (vaddr + offset);
++	mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
++
++	return ret_addr;
+ }
+ 
+ /**
+@@ -438,7 +446,7 @@ void __iomem *ioremap_nocache(resource_s
+ {
+ 	/*
+ 	 * Ideally, this should be:
+-	 *	pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
++	 *	pat_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
+ 	 *
+ 	 * Till we fix all X drivers to use ioremap_wc(), we will use
+ 	 * UC MINUS.
+@@ -462,7 +470,7 @@ EXPORT_SYMBOL(ioremap_nocache);
+  */
+ void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
+ {
+-	if (pat_wc_enabled)
++	if (pat_enabled)
+ 		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
+ 					__builtin_return_address(0));
+ 	else
+@@ -502,6 +510,14 @@ static void __iomem *ioremap_default(res
+ }
+ #endif
+ 
++void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
++				unsigned long prot_val)
++{
++	return __ioremap_caller(phys_addr, size, (prot_val & _PAGE_CACHE_MASK),
++				__builtin_return_address(0));
++}
++EXPORT_SYMBOL(ioremap_prot);
++
+ /**
+  * iounmap - Free a IO remapping
+  * @addr: virtual address from ioremap_*
+@@ -526,6 +542,8 @@ void iounmap(volatile void __iomem *addr
+ 	addr = (volatile void __iomem *)
+ 		(PAGE_MASK & (unsigned long __force)addr);
+ 
++	mmiotrace_iounmap(addr);
++
+ 	/* Use the vm area unlocked, assuming the caller
+ 	   ensures there isn't another iounmap for the same address
+ 	   in parallel. Reuse of the virtual address is prevented by
+@@ -533,7 +551,7 @@ void iounmap(volatile void __iomem *addr
+ 	   cpa takes care of the direct mappings. */
+ 	read_lock(&vmlist_lock);
+ 	for (p = vmlist; p; p = p->next) {
+-		if (p->addr == addr)
++		if (p->addr == (void __force *)addr)
+ 			break;
+ 	}
+ 	read_unlock(&vmlist_lock);
+@@ -547,7 +565,7 @@ void iounmap(volatile void __iomem *addr
+ 	free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
+ 
+ 	/* Finally remove it */
+-	o = remove_vm_area((void *)addr);
++	o = remove_vm_area((void __force *)addr);
+ 	BUG_ON(p != o || o == NULL);
+ 	kfree(p);
+ }
+@@ -567,7 +585,7 @@ void *xlate_dev_mem_ptr(unsigned long ph
+ 	if (page_is_ram(start >> PAGE_SHIFT))
+ 		return __va(phys);
+ 
+-	addr = (void *)ioremap_default(start, PAGE_SIZE);
++	addr = (void __force *)ioremap_default(start, PAGE_SIZE);
+ 	if (addr)
+ 		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+ 
+@@ -595,8 +613,7 @@ static int __init early_ioremap_debug_se
+ early_param("early_ioremap_debug", early_ioremap_debug_setup);
+ 
+ static __initdata int after_paging_init;
+-static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
+-		__section(.bss.page_aligned);
++static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
+ 
+ #ifdef CONFIG_X86_32
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+@@ -695,10 +712,11 @@ static void __init __early_set_fixmap(en
+ 		return;
+ 	}
+ 	pte = early_ioremap_pte(addr);
++
+ 	if (pgprot_val(flags))
+ 		set_pte(pte, pfn_pte_ma(phys >> PAGE_SHIFT, flags));
+ 	else
+-		pte_clear(NULL, addr, pte);
++		pte_clear(&init_mm, addr, pte);
+ 	__flush_tlb_one(addr);
+ }
+ 
+@@ -726,13 +744,11 @@ static int __init check_early_ioremap_le
+ {
+ 	if (!early_ioremap_nested)
+ 		return 0;
+-
+-	printk(KERN_WARNING
++	WARN(1, KERN_WARNING
+ 	       "Debug warning: early ioremap leak of %d areas detected.\n",
+-	       early_ioremap_nested);
++		early_ioremap_nested);
+ 	printk(KERN_WARNING
+-	       "please boot with early_ioremap_debug and report the dmesg.\n");
+-	WARN_ON(1);
++		"please boot with early_ioremap_debug and report the dmesg.\n");
+ 
+ 	return 1;
+ }
+--- head-2010-01-18.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -34,6 +34,47 @@ struct cpa_data {
+ 	unsigned	force_split : 1;
+ };
+ 
++#ifdef CONFIG_PROC_FS
++static unsigned long direct_pages_count[PG_LEVEL_NUM];
++
++void update_page_count(int level, unsigned long pages)
++{
++	unsigned long flags;
++
++	/* Protect against CPA */
++	spin_lock_irqsave(&pgd_lock, flags);
++	direct_pages_count[level] += pages;
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++static void split_page_count(int level)
++{
++	direct_pages_count[level]--;
++	direct_pages_count[level - 1] += PTRS_PER_PTE;
++}
++
++int arch_report_meminfo(char *page)
++{
++	int n = sprintf(page, "DirectMap4k:  %8lu kB\n",
++			direct_pages_count[PG_LEVEL_4K] << 2);
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++	n += sprintf(page + n, "DirectMap2M:  %8lu kB\n",
++			direct_pages_count[PG_LEVEL_2M] << 11);
++#else
++	n += sprintf(page + n, "DirectMap4M:  %8lu kB\n",
++			direct_pages_count[PG_LEVEL_2M] << 12);
++#endif
++#ifdef CONFIG_X86_64
++	if (direct_gbpages)
++		n += sprintf(page + n, "DirectMap1G:  %8lu kB\n",
++			direct_pages_count[PG_LEVEL_1G] << 20);
++#endif
++	return n;
++}
++#else
++static inline void split_page_count(int level) { }
++#endif
++
+ #ifdef CONFIG_X86_64
+ 
+ static inline unsigned long highmap_start_pfn(void)
+@@ -106,7 +147,7 @@ static void cpa_flush_all(unsigned long 
+ {
+ 	BUG_ON(irqs_disabled());
+ 
+-	on_each_cpu(__cpa_flush_all, (void *) cache, 1, 1);
++	on_each_cpu(__cpa_flush_all, (void *) cache, 1);
+ }
+ 
+ static void __cpa_flush_range(void *arg)
+@@ -127,7 +168,7 @@ static void cpa_flush_range(unsigned lon
+ 	BUG_ON(irqs_disabled());
+ 	WARN_ON(PAGE_ALIGN(start) != start);
+ 
+-	on_each_cpu(__cpa_flush_range, NULL, 1, 1);
++	on_each_cpu(__cpa_flush_range, NULL, 1);
+ 
+ 	if (!cache)
+ 		return;
+@@ -229,6 +270,7 @@ pte_t *lookup_address(unsigned long addr
+ 
+ 	return pte_offset_kernel(pmd, address);
+ }
++EXPORT_SYMBOL_GPL(lookup_address);
+ 
+ /*
+  * Set the new pmd in all the pgds we know about:
+@@ -509,6 +551,16 @@ static int split_large_page(pte_t *kpte,
+ 	}
+ #endif
+ 
++	if (address >= (unsigned long)__va(0) &&
++		address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT))
++		split_page_count(level);
++
++#ifdef CONFIG_X86_64
++	if (address >= (unsigned long)__va(1UL<<32) &&
++		address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
++		split_page_count(level);
++#endif
++
+ 	/*
+ 	 * Get the target mfn from the original entry:
+ 	 */
+@@ -566,10 +618,9 @@ repeat:
+ 	if (!__pte_val(old_pte)) {
+ 		if (!primary)
+ 			return 0;
+-		printk(KERN_WARNING "CPA: called for zero pte. "
++		WARN(1, KERN_WARNING "CPA: called for zero pte. "
+ 		       "vaddr = %lx cpa->vaddr = %lx\n", address,
+ 		       cpa->vaddr);
+-		WARN_ON(1);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -634,15 +685,24 @@ static int cpa_process_alias(struct cpa_
+ 	struct cpa_data alias_cpa;
+ 	int ret = 0;
+ 
+-	if (cpa->pfn > max_pfn_mapped)
++	if (cpa->pfn >= max_pfn_mapped)
+ 		return 0;
+ 
++#ifdef CONFIG_X86_64
++	if (cpa->pfn >= max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT)))
++		return 0;
++#endif
+ 	/*
+ 	 * No need to redo, when the primary call touched the direct
+ 	 * mapping already:
+ 	 */
+-	if (!within(cpa->vaddr, PAGE_OFFSET,
+-		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
++	if (!(within(cpa->vaddr, PAGE_OFFSET,
++		    PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
++#ifdef CONFIG_X86_64
++		|| within(cpa->vaddr, PAGE_OFFSET + (1UL<<32),
++		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
++#endif
++	)) {
+ 
+ 		alias_cpa = *cpa;
+ 		alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
+@@ -796,6 +856,51 @@ static inline int change_page_attr_clear
+ 	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
+ }
+ 
++#ifdef CONFIG_XEN
++static void _free_memtype(u64 pstart, u64 pend)
++{
++	u64 pa = pstart &= __PHYSICAL_MASK;
++	u64 ma = phys_to_machine(pa);
++
++	while ((pa += PAGE_SIZE) < pend) {
++		if (phys_to_machine(pa) != ma + (pa - pstart)) {
++			free_memtype(ma, ma + (pa - pstart));
++			pstart = pa;
++			ma = phys_to_machine(pa);
++		}
++	}
++	free_memtype(ma, ma + (pend - pstart));
++}
++#define free_memtype _free_memtype
++
++static int _reserve_memtype(u64 pstart, u64 pend, unsigned long req_type)
++{
++	u64 pcur = pstart &= __PHYSICAL_MASK, pa = pcur;
++	u64 ma = phys_to_machine(pa);
++	int rc = 0;
++
++	while ((pa += PAGE_SIZE) < pend) {
++		if (phys_to_machine(pa) != ma + (pa - pcur)) {
++			rc = reserve_memtype(ma, ma + (pa - pcur),
++					     req_type, NULL);
++			if (rc)
++				break;
++			pcur = pa;
++			ma = phys_to_machine(pa);
++		}
++	}
++	if (likely(!rc))
++		rc = reserve_memtype(ma, ma + (pend - pcur), req_type, NULL);
++
++	if (unlikely(!rc) && pstart < pcur)
++		_free_memtype(pstart, pcur);
++
++	return rc;
++}
++#define reserve_memtype(s, e, r, n) \
++	_reserve_memtype(s, e, BUILD_BUG_ON_ZERO(n) ?: (r))
++#endif
++
+ int _set_memory_uc(unsigned long addr, int numpages)
+ {
+ 	/*
+@@ -810,7 +915,7 @@ int set_memory_uc(unsigned long addr, in
+ 	/*
+ 	 * for now UC MINUS. see comments in ioremap_nocache()
+ 	 */
+-	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++	if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+ 			    _PAGE_CACHE_UC_MINUS, NULL))
+ 		return -EINVAL;
+ 
+@@ -826,10 +931,10 @@ int _set_memory_wc(unsigned long addr, i
+ 
+ int set_memory_wc(unsigned long addr, int numpages)
+ {
+-	if (!pat_wc_enabled)
++	if (!pat_enabled)
+ 		return set_memory_uc(addr, numpages);
+ 
+-	if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
++	if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+ 		_PAGE_CACHE_WC, NULL))
+ 		return -EINVAL;
+ 
+@@ -845,7 +950,7 @@ int _set_memory_wb(unsigned long addr, i
+ 
+ int set_memory_wb(unsigned long addr, int numpages)
+ {
+-	free_memtype(addr, addr + numpages * PAGE_SIZE);
++	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+ 
+ 	return _set_memory_wb(addr, numpages);
+ }
+--- head-2010-01-18.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pat-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -12,6 +12,8 @@
+ #include <linux/gfp.h>
+ #include <linux/fs.h>
+ #include <linux/bootmem.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
+ 
+ #include <asm/msr.h>
+ #include <asm/tlbflush.h>
+@@ -26,11 +28,11 @@
+ #include <asm/io.h>
+ 
+ #ifdef CONFIG_X86_PAT
+-int __read_mostly pat_wc_enabled = 1;
++int __read_mostly pat_enabled = 1;
+ 
+ void __cpuinit pat_disable(char *reason)
+ {
+-	pat_wc_enabled = 0;
++	pat_enabled = 0;
+ 	printk(KERN_INFO "%s\n", reason);
+ }
+ 
+@@ -42,6 +44,19 @@ static int __init nopat(char *str)
+ early_param("nopat", nopat);
+ #endif
+ 
++
++static int debug_enable;
++static int __init pat_debug_setup(char *str)
++{
++	debug_enable = 1;
++	return 0;
++}
++__setup("debugpat", pat_debug_setup);
++
++#define dprintk(fmt, arg...) \
++	do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
++
++
+ static u64 __read_mostly boot_pat_state;
+ 
+ enum {
+@@ -53,24 +68,25 @@ enum {
+ 	PAT_UC_MINUS = 7,	/* UC, but can be overriden by MTRR */
+ };
+ 
+-#define PAT(x,y)	((u64)PAT_ ## y << ((x)*8))
++#define PAT(x, y)	((u64)PAT_ ## y << ((x)*8))
+ 
+ void pat_init(void)
+ {
+ 	u64 pat;
+ 
+-	if (!pat_wc_enabled)
++	if (!pat_enabled)
+ 		return;
+ 
+ 	/* Paranoia check. */
+-	if (!cpu_has_pat) {
+-		printk(KERN_ERR "PAT enabled, but CPU feature cleared\n");
++	if (!cpu_has_pat && boot_pat_state) {
+ 		/*
+-		 * Panic if this happens on the secondary CPU, and we
++		 * If this happens we are on a secondary CPU, but
+ 		 * switched to PAT on the boot CPU. We have no way to
+ 		 * undo PAT.
+-		*/
+-		BUG_ON(boot_pat_state);
++		 */
++		printk(KERN_ERR "PAT enabled, "
++		       "but not supported by secondary CPU\n");
++		BUG();
+ 	}
+ 
+ #ifndef CONFIG_XEN
+@@ -87,8 +103,8 @@ void pat_init(void)
+ 	 *      011 UC		_PAGE_CACHE_UC
+ 	 * PAT bit unused
+ 	 */
+-	pat = PAT(0,WB) | PAT(1,WC) | PAT(2,UC_MINUS) | PAT(3,UC) |
+-	      PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC);
++	pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
++	      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
+ 
+ 	/* Boot CPU check */
+ 	if (!boot_pat_state)
+@@ -113,13 +129,13 @@ void pat_init(void)
+ static char *cattr_name(unsigned long flags)
+ {
+ 	switch (flags & _PAGE_CACHE_MASK) {
+-		case _PAGE_CACHE_UC:		return "uncached";
+-		case _PAGE_CACHE_UC_MINUS:	return "uncached-minus";
+-		case _PAGE_CACHE_WB:		return "write-back";
+-		case _PAGE_CACHE_WC:		return "write-combining";
+-		case _PAGE_CACHE_WP:		return "write-protected";
+-		case _PAGE_CACHE_WT:		return "write-through";
+-		default:			return "broken";
++	case _PAGE_CACHE_UC:		return "uncached";
++	case _PAGE_CACHE_UC_MINUS:	return "uncached-minus";
++	case _PAGE_CACHE_WB:		return "write-back";
++	case _PAGE_CACHE_WC:		return "write-combining";
++	case _PAGE_CACHE_WP:		return "write-protected";
++	case _PAGE_CACHE_WT:		return "write-through";
++	default:			return "broken";
+ 	}
+ }
+ 
+@@ -157,49 +173,55 @@ static DEFINE_SPINLOCK(memtype_lock); 	/
+  * The intersection is based on "Effective Memory Type" tables in IA-32
+  * SDM vol 3a
+  */
+-static int pat_x_mtrr_type(u64 start, u64 end, unsigned long prot,
+-				unsigned long *ret_prot)
++static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type)
+ {
+-	unsigned long pat_type;
+-	u8 mtrr_type;
+-
+-	pat_type = prot & _PAGE_CACHE_MASK;
+-	prot &= (~_PAGE_CACHE_MASK);
+-
+-	/*
+-	 * We return the PAT request directly for types where PAT takes
+-	 * precedence with respect to MTRR and for UC_MINUS.
+-	 * Consistency checks with other PAT requests is done later
+-	 * while going through memtype list.
+-	 */
+-	if (pat_type == _PAGE_CACHE_WC) {
+-		*ret_prot = prot | _PAGE_CACHE_WC;
+-		return 0;
+-	} else if (pat_type == _PAGE_CACHE_UC_MINUS) {
+-		*ret_prot = prot | _PAGE_CACHE_UC_MINUS;
+-		return 0;
+-	} else if (pat_type == _PAGE_CACHE_UC) {
+-		*ret_prot = prot | _PAGE_CACHE_UC;
+-		return 0;
+-	}
+-
+ 	/*
+ 	 * Look for MTRR hint to get the effective type in case where PAT
+ 	 * request is for WB.
+ 	 */
+-	mtrr_type = mtrr_type_lookup(start, end);
++	if (req_type == _PAGE_CACHE_WB) {
++		u8 mtrr_type;
+ 
+-	if (mtrr_type == MTRR_TYPE_UNCACHABLE) {
+-		*ret_prot = prot | _PAGE_CACHE_UC;
+-	} else if (mtrr_type == MTRR_TYPE_WRCOMB) {
+-		*ret_prot = prot | _PAGE_CACHE_WC;
+-	} else {
+-		*ret_prot = prot | _PAGE_CACHE_WB;
++		mtrr_type = mtrr_type_lookup(start, end);
++		if (mtrr_type == MTRR_TYPE_UNCACHABLE)
++			return _PAGE_CACHE_UC;
++		if (mtrr_type == MTRR_TYPE_WRCOMB)
++			return _PAGE_CACHE_WC;
++	}
++
++	return req_type;
++}
++
++static int chk_conflict(struct memtype *new, struct memtype *entry,
++			unsigned long *type)
++{
++	if (new->type != entry->type) {
++		if (type) {
++			new->type = entry->type;
++			*type = entry->type;
++		} else
++			goto conflict;
+ 	}
+ 
++	 /* check overlaps with more than one entry in the list */
++	list_for_each_entry_continue(entry, &memtype_list, nd) {
++		if (new->end <= entry->start)
++			break;
++		else if (new->type != entry->type)
++			goto conflict;
++	}
+ 	return 0;
++
++ conflict:
++	printk(KERN_INFO "%s:%d conflicting memory types "
++	       "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start,
++	       new->end, cattr_name(new->type), cattr_name(entry->type));
++	return -EBUSY;
+ }
+ 
++static struct memtype *cached_entry;
++static u64 cached_start;
++
+ /*
+  * req_type typically has one of the:
+  * - _PAGE_CACHE_WB
+@@ -210,37 +232,36 @@ static int pat_x_mtrr_type(u64 start, u6
+  * req_type will have a special case value '-1', when requester want to inherit
+  * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
+  *
+- * If ret_type is NULL, function will return an error if it cannot reserve the
+- * region with req_type. If ret_type is non-null, function will return
+- * available type in ret_type in case of no error. In case of any error
++ * If new_type is NULL, function will return an error if it cannot reserve the
++ * region with req_type. If new_type is non-NULL, function will return
++ * available type in new_type in case of no error. In case of any error
+  * it will return a negative return value.
+  */
+ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
+-			unsigned long *ret_type)
++			unsigned long *new_type)
+ {
+-	struct memtype *new_entry = NULL;
+-	struct memtype *parse;
++	struct memtype *new, *entry;
+ 	unsigned long actual_type;
++	struct list_head *where;
+ 	int err = 0;
+ 
+-	/* Only track when pat_wc_enabled */
+-	if (!pat_wc_enabled) {
++ 	BUG_ON(start >= end); /* end is exclusive */
++
++	if (!pat_enabled) {
+ 		/* This is identical to page table setting without PAT */
+-		if (ret_type) {
+-			if (req_type == -1) {
+-				*ret_type = _PAGE_CACHE_WB;
+-			} else {
+-				*ret_type = req_type;
+-			}
++		if (new_type) {
++			if (req_type == -1)
++				*new_type = _PAGE_CACHE_WB;
++			else
++				*new_type = req_type & _PAGE_CACHE_MASK;
+ 		}
+ 		return 0;
+ 	}
+ 
+ 	/* Low ISA region is always mapped WB in page table. No need to track */
+-	if (start >= ISA_START_ADDRESS && (end - 1) <= ISA_END_ADDRESS) {
+-		if (ret_type)
+-			*ret_type = _PAGE_CACHE_WB;
+-
++	if (is_ISA_range(start, end - 1)) {
++		if (new_type)
++			*new_type = _PAGE_CACHE_WB;
+ 		return 0;
+ 	}
+ 
+@@ -253,206 +274,118 @@ int reserve_memtype(u64 start, u64 end, 
+ 		 */
+ 		u8 mtrr_type = mtrr_type_lookup(start, end);
+ 
+-		if (mtrr_type == MTRR_TYPE_WRBACK) {
+-			req_type = _PAGE_CACHE_WB;
++		if (mtrr_type == MTRR_TYPE_WRBACK)
+ 			actual_type = _PAGE_CACHE_WB;
+-		} else {
+-			req_type = _PAGE_CACHE_UC_MINUS;
++		else
+ 			actual_type = _PAGE_CACHE_UC_MINUS;
+-		}
+-	} else {
+-		req_type &= _PAGE_CACHE_MASK;
+-		err = pat_x_mtrr_type(start, end, req_type, &actual_type);
+-	}
+-
+-	if (err) {
+-		if (ret_type)
+-			*ret_type = actual_type;
++	} else
++		actual_type = pat_x_mtrr_type(start, end,
++					      req_type & _PAGE_CACHE_MASK);
+ 
+-		return -EINVAL;
+-	}
+-
+-	new_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+-	if (!new_entry)
++	new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
++	if (!new)
+ 		return -ENOMEM;
+ 
+-	new_entry->start = start;
+-	new_entry->end = end;
+-	new_entry->type = actual_type;
++	new->start = start;
++	new->end = end;
++	new->type = actual_type;
+ 
+-	if (ret_type)
+-		*ret_type = actual_type;
++	if (new_type)
++		*new_type = actual_type;
+ 
+ 	spin_lock(&memtype_lock);
+ 
+-	/* Search for existing mapping that overlaps the current range */
+-	list_for_each_entry(parse, &memtype_list, nd) {
+-		struct memtype *saved_ptr;
++	if (cached_entry && start >= cached_start)
++		entry = cached_entry;
++	else
++		entry = list_entry(&memtype_list, struct memtype, nd);
+ 
+-		if (parse->start >= end) {
+-			pr_debug("New Entry\n");
+-			list_add(&new_entry->nd, parse->nd.prev);
+-			new_entry = NULL;
++	/* Search for existing mapping that overlaps the current range */
++	where = NULL;
++	list_for_each_entry_continue(entry, &memtype_list, nd) {
++		if (end <= entry->start) {
++			where = entry->nd.prev;
++			cached_entry = list_entry(where, struct memtype, nd);
+ 			break;
+-		}
+-
+-		if (start <= parse->start && end >= parse->start) {
+-			if (actual_type != parse->type && ret_type) {
+-				actual_type = parse->type;
+-				*ret_type = actual_type;
+-				new_entry->type = actual_type;
+-			}
+-
+-			if (actual_type != parse->type) {
+-				printk(
+-		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
+-					current->comm, current->pid,
+-					start, end,
+-					cattr_name(actual_type),
+-					cattr_name(parse->type));
+-				err = -EBUSY;
+-				break;
+-			}
+-
+-			saved_ptr = parse;
+-			/*
+-			 * Check to see whether the request overlaps more
+-			 * than one entry in the list
+-			 */
+-			list_for_each_entry_continue(parse, &memtype_list, nd) {
+-				if (end <= parse->start) {
+-					break;
+-				}
+-
+-				if (actual_type != parse->type) {
+-					printk(
+-		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
+-						current->comm, current->pid,
+-						start, end,
+-						cattr_name(actual_type),
+-						cattr_name(parse->type));
+-					err = -EBUSY;
+-					break;
+-				}
+-			}
+-
+-			if (err) {
+-				break;
++		} else if (start <= entry->start) { /* end > entry->start */
++			err = chk_conflict(new, entry, new_type);
++			if (!err) {
++				dprintk("Overlap at 0x%Lx-0x%Lx\n",
++					entry->start, entry->end);
++				where = entry->nd.prev;
++				cached_entry = list_entry(where,
++							struct memtype, nd);
+ 			}
+-
+-			pr_debug("Overlap at 0x%Lx-0x%Lx\n",
+-			       saved_ptr->start, saved_ptr->end);
+-			/* No conflict. Go ahead and add this new entry */
+-			list_add(&new_entry->nd, saved_ptr->nd.prev);
+-			new_entry = NULL;
+ 			break;
+-		}
+-
+-		if (start < parse->end) {
+-			if (actual_type != parse->type && ret_type) {
+-				actual_type = parse->type;
+-				*ret_type = actual_type;
+-				new_entry->type = actual_type;
+-			}
+-
+-			if (actual_type != parse->type) {
+-				printk(
+-		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
+-					current->comm, current->pid,
+-					start, end,
+-					cattr_name(actual_type),
+-					cattr_name(parse->type));
+-				err = -EBUSY;
+-				break;
+-			}
+-
+-			saved_ptr = parse;
+-			/*
+-			 * Check to see whether the request overlaps more
+-			 * than one entry in the list
+-			 */
+-			list_for_each_entry_continue(parse, &memtype_list, nd) {
+-				if (end <= parse->start) {
+-					break;
+-				}
+-
+-				if (actual_type != parse->type) {
+-					printk(
+-		KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
+-						current->comm, current->pid,
+-						start, end,
+-						cattr_name(actual_type),
+-						cattr_name(parse->type));
+-					err = -EBUSY;
+-					break;
++		} else if (start < entry->end) { /* start > entry->start */
++			err = chk_conflict(new, entry, new_type);
++			if (!err) {
++				dprintk("Overlap at 0x%Lx-0x%Lx\n",
++					entry->start, entry->end);
++				cached_entry = list_entry(entry->nd.prev,
++							struct memtype, nd);
++
++				/*
++				 * Move to right position in the linked
++				 * list to add this new entry
++				 */
++				list_for_each_entry_continue(entry,
++							&memtype_list, nd) {
++					if (start <= entry->start) {
++						where = entry->nd.prev;
++						break;
++					}
+ 				}
+ 			}
+-
+-			if (err) {
+-				break;
+-			}
+-
+-			pr_debug(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n",
+-				 saved_ptr->start, saved_ptr->end);
+-			/* No conflict. Go ahead and add this new entry */
+-			list_add(&new_entry->nd, &saved_ptr->nd);
+-			new_entry = NULL;
+ 			break;
+ 		}
+ 	}
+ 
+ 	if (err) {
+-		printk(KERN_INFO
+-	"reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
+-			start, end, cattr_name(new_entry->type),
+-			cattr_name(req_type));
+-		kfree(new_entry);
++		printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
++		       "track %s, req %s\n",
++		       start, end, cattr_name(new->type), cattr_name(req_type));
++		kfree(new);
+ 		spin_unlock(&memtype_lock);
+ 		return err;
+ 	}
+ 
+-	if (new_entry) {
+-		/* No conflict. Not yet added to the list. Add to the tail */
+-		list_add_tail(&new_entry->nd, &memtype_list);
+-		pr_debug("New Entry\n");
+-	}
++	cached_start = start;
+ 
+-	if (ret_type) {
+-		pr_debug(
+-	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
+-			start, end, cattr_name(actual_type),
+-			cattr_name(req_type), cattr_name(*ret_type));
+-	} else {
+-		pr_debug(
+-	"reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
+-			start, end, cattr_name(actual_type),
+-			cattr_name(req_type));
+-	}
++	if (where)
++		list_add(&new->nd, where);
++	else
++		list_add_tail(&new->nd, &memtype_list);
+ 
+ 	spin_unlock(&memtype_lock);
++
++	dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
++		start, end, cattr_name(new->type), cattr_name(req_type),
++		new_type ? cattr_name(*new_type) : "-");
++
+ 	return err;
+ }
+ 
+ int free_memtype(u64 start, u64 end)
+ {
+-	struct memtype *ml;
++	struct memtype *entry;
+ 	int err = -EINVAL;
+ 
+-	/* Only track when pat_wc_enabled */
+-	if (!pat_wc_enabled) {
++	if (!pat_enabled)
+ 		return 0;
+-	}
+ 
+ 	/* Low ISA region is always mapped WB. No need to track */
+-	if (start >= ISA_START_ADDRESS && end <= ISA_END_ADDRESS) {
++	if (is_ISA_range(start, end - 1))
+ 		return 0;
+-	}
+ 
+ 	spin_lock(&memtype_lock);
+-	list_for_each_entry(ml, &memtype_list, nd) {
+-		if (ml->start == start && ml->end == end) {
+-			list_del(&ml->nd);
+-			kfree(ml);
++	list_for_each_entry(entry, &memtype_list, nd) {
++		if (entry->start == start && entry->end == end) {
++			if (cached_entry == entry || cached_start == start)
++				cached_entry = NULL;
++
++			list_del(&entry->nd);
++			kfree(entry);
+ 			err = 0;
+ 			break;
+ 		}
+@@ -464,27 +397,19 @@ int free_memtype(u64 start, u64 end)
+ 			current->comm, current->pid, start, end);
+ 	}
+ 
+-	pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end);
++	dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
+ 	return err;
+ }
+ 
+ 
+-/*
+- * /dev/mem mmap interface. The memtype used for mapping varies:
+- * - Use UC for mappings with O_SYNC flag
+- * - Without O_SYNC flag, if there is any conflict in reserve_memtype,
+- *   inherit the memtype from existing mapping.
+- * - Else use UC_MINUS memtype (for backward compatibility with existing
+- *   X drivers.
+- */
+ pgprot_t phys_mem_access_prot(struct file *file, unsigned long mfn,
+ 				unsigned long size, pgprot_t vma_prot)
+ {
+ 	return vma_prot;
+ }
+ 
+-#ifdef CONFIG_NONPROMISC_DEVMEM
+-/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
++#ifdef CONFIG_STRICT_DEVMEM
++/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/
+ static inline int range_is_allowed(unsigned long mfn, unsigned long size)
+ {
+ 	return 1;
+@@ -508,20 +433,20 @@ static inline int range_is_allowed(unsig
+ 	}
+ 	return 1;
+ }
+-#endif /* CONFIG_NONPROMISC_DEVMEM */
++#endif /* CONFIG_STRICT_DEVMEM */
+ 
+ int phys_mem_access_prot_allowed(struct file *file, unsigned long mfn,
+ 				unsigned long size, pgprot_t *vma_prot)
+ {
+ 	u64 addr = (u64)mfn << PAGE_SHIFT;
+-	unsigned long flags = _PAGE_CACHE_UC_MINUS;
++	unsigned long flags = -1;
+ 	int retval;
+ 
+ 	if (!range_is_allowed(mfn, size))
+ 		return 0;
+ 
+ 	if (file->f_flags & O_SYNC) {
+-		flags = _PAGE_CACHE_UC;
++		flags = _PAGE_CACHE_UC_MINUS;
+ 	}
+ 
+ #ifndef CONFIG_X86_32
+@@ -534,25 +459,26 @@ int phys_mem_access_prot_allowed(struct 
+ 	 * caching for the high addresses through the KEN pin, but
+ 	 * we maintain the tradition of paranoia in this code.
+ 	 */
+-	if (!pat_wc_enabled &&
+-	    ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+-		test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+-		test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+-		test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) &&
+-	   (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
++	if (!pat_enabled &&
++	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
++	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
++	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
++	      boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
++	    (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
+ 		flags = _PAGE_CACHE_UC;
+ 	}
+ #endif
+ #endif
+ 
+ 	/*
+-	 * With O_SYNC, we can only take UC mapping. Fail if we cannot.
++	 * With O_SYNC, we can only take UC_MINUS mapping. Fail if we cannot.
++	 *
+ 	 * Without O_SYNC, we want to get
+ 	 * - WB for WB-able memory and no other conflicting mappings
+ 	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+ 	 * - Inherit from confliting mappings otherwise
+ 	 */
+-	if (flags != _PAGE_CACHE_UC_MINUS) {
++	if (flags != -1) {
+ 		retval = reserve_memtype(addr, addr + size, flags, NULL);
+ 	} else {
+ 		retval = reserve_memtype(addr, addr + size, -1, &flags);
+@@ -600,3 +526,88 @@ void unmap_devmem(unsigned long mfn, uns
+ 	free_memtype(addr, addr + size);
+ }
+ 
++#if defined(CONFIG_DEBUG_FS)
++
++/* get Nth element of the linked list */
++static struct memtype *memtype_get_idx(loff_t pos)
++{
++	struct memtype *list_node, *print_entry;
++	int i = 1;
++
++	print_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
++	if (!print_entry)
++		return NULL;
++
++	spin_lock(&memtype_lock);
++	list_for_each_entry(list_node, &memtype_list, nd) {
++		if (pos == i) {
++			*print_entry = *list_node;
++			spin_unlock(&memtype_lock);
++			return print_entry;
++		}
++		++i;
++	}
++	spin_unlock(&memtype_lock);
++	kfree(print_entry);
++	return NULL;
++}
++
++static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)
++{
++	if (*pos == 0) {
++		++*pos;
++		seq_printf(seq, "PAT memtype list:\n");
++	}
++
++	return memtype_get_idx(*pos);
++}
++
++static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
++{
++	++*pos;
++	return memtype_get_idx(*pos);
++}
++
++static void memtype_seq_stop(struct seq_file *seq, void *v)
++{
++}
++
++static int memtype_seq_show(struct seq_file *seq, void *v)
++{
++	struct memtype *print_entry = (struct memtype *)v;
++
++	seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type),
++			print_entry->start, print_entry->end);
++	kfree(print_entry);
++	return 0;
++}
++
++static struct seq_operations memtype_seq_ops = {
++	.start = memtype_seq_start,
++	.next  = memtype_seq_next,
++	.stop  = memtype_seq_stop,
++	.show  = memtype_seq_show,
++};
++
++static int memtype_seq_open(struct inode *inode, struct file *file)
++{
++	return seq_open(file, &memtype_seq_ops);
++}
++
++static const struct file_operations memtype_fops = {
++	.open    = memtype_seq_open,
++	.read    = seq_read,
++	.llseek  = seq_lseek,
++	.release = seq_release,
++};
++
++static int __init pat_memtype_list_init(void)
++{
++	debugfs_create_file("pat_memtype_list", S_IRUSR, arch_debugfs_dir,
++				NULL, &memtype_fops);
++	return 0;
++}
++
++late_initcall(pat_memtype_list_init);
++
++#endif /* CONFIG_DEBUG_FS */
+--- head-2010-01-18.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -4,6 +4,7 @@
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+ #include <asm/tlb.h>
++#include <asm/fixmap.h>
+ #include <asm/hypervisor.h>
+ #include <asm/mmu_context.h>
+ 
+@@ -410,15 +411,9 @@ static inline void pgd_list_del(pgd_t *p
+ static void pgd_ctor(void *p)
+ {
+ 	pgd_t *pgd = p;
+-	unsigned long flags;
+ 
+ 	pgd_test_and_unpin(pgd);
+ 
+-	/* Clear usermode parts of PGD */
+-	memset(pgd, 0, KERNEL_PGD_BOUNDARY*sizeof(pgd_t));
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-
+ 	/* If the pgd points to a shared pagetable level (either the
+ 	   ptes in non-PAE, or shared PMD in PAE), then just copy the
+ 	   references from swapper_pg_dir. */
+@@ -440,13 +435,9 @@ static void pgd_ctor(void *p)
+ 		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
+ #endif
+ 
+-#ifndef CONFIG_X86_PAE
+ 	/* list required to sync kernel mapping updates */
+ 	if (!SHARED_KERNEL_PMD)
+ 		pgd_list_add(pgd);
+-#endif
+-
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+ 
+ static void pgd_dtor(void *pgd)
+@@ -475,33 +466,6 @@ static void pgd_dtor(void *pgd)
+ 
+ #ifdef CONFIG_X86_PAE
+ /*
+- * Mop up any pmd pages which may still be attached to the pgd.
+- * Normally they will be freed by munmap/exit_mmap, but any pmd we
+- * preallocate which never got a corresponding vma will need to be
+- * freed manually.
+- */
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+-{
+-	int i;
+-
+-	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
+-		pgd_t pgd = pgdp[i];
+-
+-		if (__pgd_val(pgd) != 0) {
+-			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+-
+-			pgdp[i] = xen_make_pgd(0);
+-
+-			paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
+-			pmd_free(mm, pmd);
+-		}
+-	}
+-
+-	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
+-		xen_destroy_contiguous_region((unsigned long)pgdp, 0);
+-}
+-
+-/*
+  * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+  * updating the top-level pagetable entries to guarantee the
+  * processor notices the update.  Since this is expensive, and
+@@ -512,61 +476,7 @@ static void pgd_mop_up_pmds(struct mm_st
+  * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+  * and initialize the kernel pmds here.
+  */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+-{
+-	pud_t *pud;
+-	pmd_t *pmds[UNSHARED_PTRS_PER_PGD];
+-	unsigned long addr, flags;
+-	int i;
+-
+-	/*
+-	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
+-	 * allocation). We therefore store virtual addresses of pmds as they
+-	 * do not change across save/restore, and poke the machine addresses
+-	 * into the pgdir under the pgd_lock.
+-	 */
+- 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD; i++, addr += PUD_SIZE) {
+-		pmds[i] = pmd_alloc_one(mm, addr);
+-		if (!pmds[i])
+-			goto out_oom;
+-	}
+-
+-	spin_lock_irqsave(&pgd_lock, flags);
+-
+-	/* Protect against save/restore: move below 4GB under pgd_lock. */
+-	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
+-	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-out_oom:
+-		while (i--)
+-			pmd_free(mm, pmds[i]);
+-		return 0;
+-	}
+-
+-	/* Copy kernel pmd contents and write-protect the new pmds. */
+-	pud = pud_offset(pgd, 0);
+- 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
+-	     i++, pud++, addr += PUD_SIZE) {
+-		if (i >= KERNEL_PGD_BOUNDARY) {
+-			memcpy(pmds[i],
+-			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+-			       sizeof(pmd_t) * PTRS_PER_PMD);
+-			make_lowmem_page_readonly(
+-				pmds[i], XENFEAT_writable_page_tables);
+-		}
+-
+-		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
+-		pud_populate(mm, pud, pmds[i]);
+-	}
+-
+-	/* List required to sync kernel mapping updates and
+-	 * to pin/unpin on save/restore. */
+-	pgd_list_add(pgd);
+-
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-
+-	return 1;
+-}
++#define PREALLOCATED_PMDS	UNSHARED_PTRS_PER_PGD
+ 
+ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+ {
+@@ -596,16 +506,101 @@ void pud_populate(struct mm_struct *mm, 
+ 		xen_tlb_flush();
+ }
+ #else  /* !CONFIG_X86_PAE */
++
+ /* No need to prepopulate any pagetable entries in non-PAE modes. */
+-static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++#define PREALLOCATED_PMDS	0
++
++#endif	/* CONFIG_X86_PAE */
++
++static void free_pmds(pmd_t *pmds[], struct mm_struct *mm, bool contig)
+ {
+-	return 1;
++	int i;
++
++#ifdef CONFIG_X86_PAE
++	if (contig)
++		xen_destroy_contiguous_region((unsigned long)mm->pgd, 0);
++#endif
++
++	for(i = 0; i < PREALLOCATED_PMDS; i++)
++		if (pmds[i])
++			pmd_free(mm, pmds[i]);
+ }
+ 
+-static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgd)
++static int preallocate_pmds(pmd_t *pmds[], struct mm_struct *mm)
+ {
++	int i;
++	bool failed = false;
++
++	for(i = 0; i < PREALLOCATED_PMDS; i++) {
++		pmd_t *pmd = pmd_alloc_one(mm, i << PUD_SHIFT);
++		if (pmd == NULL)
++			failed = true;
++		pmds[i] = pmd;
++	}
++
++	if (failed) {
++		free_pmds(pmds, mm, false);
++		return -ENOMEM;
++	}
++
++	return 0;
++}
++
++/*
++ * Mop up any pmd pages which may still be attached to the pgd.
++ * Normally they will be freed by munmap/exit_mmap, but any pmd we
++ * preallocate which never got a corresponding vma will need to be
++ * freed manually.
++ */
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
++	int i;
++
++	for(i = 0; i < PREALLOCATED_PMDS; i++) {
++		pgd_t pgd = pgdp[i];
++
++		if (__pgd_val(pgd) != 0) {
++			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
++
++			pgdp[i] = xen_make_pgd(0);
++
++			paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
++			pmd_free(mm, pmd);
++		}
++	}
++
++#ifdef CONFIG_X86_PAE
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
++		xen_destroy_contiguous_region((unsigned long)pgdp, 0);
++#endif
++}
++
++static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
++{
++	pud_t *pud;
++	unsigned long addr;
++	int i;
++
++	if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */
++		return;
++
++	pud = pud_offset(pgd, 0);
++ 	for (addr = i = 0; i < PREALLOCATED_PMDS;
++	     i++, pud++, addr += PUD_SIZE) {
++		pmd_t *pmd = pmds[i];
++
++		if (i >= KERNEL_PGD_BOUNDARY) {
++			memcpy(pmd,
++			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++			       sizeof(pmd_t) * PTRS_PER_PMD);
++			make_lowmem_page_readonly(
++				pmd, XENFEAT_writable_page_tables);
++		}
++
++		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
++		pud_populate(mm, pud, pmd);
++	}
+ }
+-#endif	/* CONFIG_X86_PAE */
+ 
+ #ifdef CONFIG_X86_64
+ /* We allocate two contiguous pages for kernel and user. */
+@@ -616,19 +611,52 @@ static void pgd_mop_up_pmds(struct mm_st
+ 
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+-	pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
++	pgd_t *pgd;
++	pmd_t *pmds[PREALLOCATED_PMDS];
++	unsigned long flags;
++
++	pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
++
++	if (pgd == NULL)
++		goto out;
+ 
+-	/* so that alloc_pd can use it */
+ 	mm->pgd = pgd;
+-	if (pgd)
+-		pgd_ctor(pgd);
+ 
+-	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
+-		free_pages((unsigned long)pgd, PGD_ORDER);
+-		pgd = NULL;
++	if (preallocate_pmds(pmds, mm) != 0)
++		goto out_free_pgd;
++
++	if (paravirt_pgd_alloc(mm) != 0)
++		goto out_free_pmds;
++
++	/*
++	 * Make sure that pre-populating the pmds is atomic with
++	 * respect to anything walking the pgd_list, so that they
++	 * never see a partially populated pgd.
++	 */
++	spin_lock_irqsave(&pgd_lock, flags);
++
++#ifdef CONFIG_X86_PAE
++	/* Protect against save/restore: move below 4GB under pgd_lock. */
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
++	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
++		spin_unlock_irqrestore(&pgd_lock, flags);
++		goto out_free_pmds;
+ 	}
++#endif
++
++	pgd_ctor(pgd);
++	pgd_prepopulate_pmd(mm, pgd, pmds);
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ 
+ 	return pgd;
++
++out_free_pmds:
++	free_pmds(pmds, mm, !xen_feature(XENFEAT_pae_pgdir_above_4gb));
++out_free_pgd:
++	free_pages((unsigned long)pgd, PGD_ORDER);
++out:
++	return NULL;
+ }
+ 
+ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+@@ -644,6 +672,7 @@ void pgd_free(struct mm_struct *mm, pgd_
+ 	pgd_dtor(pgd);
+ 
+ 	pgd_mop_up_pmds(mm, pgd);
++	paravirt_pgd_free(mm, pgd);
+ 	free_pages((unsigned long)pgd, PGD_ORDER);
+ }
+ 
+@@ -686,7 +715,7 @@ int ptep_test_and_clear_young(struct vm_
+ 
+ 	if (pte_young(*ptep))
+ 		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
+-					 &ptep->pte);
++					 (unsigned long *) &ptep->pte);
+ 
+ 	if (ret)
+ 		pte_update(vma->vm_mm, addr, ptep);
+@@ -708,3 +737,42 @@ int ptep_clear_flush_young(struct vm_are
+ 
+ 	return young;
+ }
++
++int fixmaps_set;
++
++void xen_set_fixmap(enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
++{
++	unsigned long address = __fix_to_virt(idx);
++	pte_t pte;
++
++	if (idx >= __end_of_fixed_addresses) {
++		BUG();
++		return;
++	}
++
++	switch (idx) {
++#ifdef CONFIG_X86_64
++	extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
++
++	case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
++		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
++		set_pte_vaddr_pud(level3_user_pgt, address, pte);
++		break;
++	case FIX_EARLYCON_MEM_BASE:
++		xen_l1_entry_update(level1_fixmap_pgt + pte_index(address),
++				    pfn_pte_ma(phys >> PAGE_SHIFT, flags));
++		fixmaps_set++;
++		return;
++#else
++	case FIX_WP_TEST:
++	case FIX_VDSO:
++		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
++		break;
++#endif
++	default:
++		pte = pfn_pte_ma(phys >> PAGE_SHIFT, flags);
++		break;
++	}
++	set_pte_vaddr(address, pte);
++	fixmaps_set++;
++}
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -25,51 +25,49 @@
+ #include <xen/features.h>
+ #include <asm/hypervisor.h>
+ 
+-void show_mem(void)
++/*
++ * Associate a virtual page frame with a given physical page frame
++ * and protection flags for that frame.
++ */
++void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
+ {
+-	int total = 0, reserved = 0;
+-	int shared = 0, cached = 0;
+-	int highmem = 0;
+-	struct page *page;
+-	pg_data_t *pgdat;
+-	unsigned long i;
+-	unsigned long flags;
+-
+-	printk(KERN_INFO "Mem-info:\n");
+-	show_free_areas();
+-	for_each_online_pgdat(pgdat) {
+-		pgdat_resize_lock(pgdat, &flags);
+-		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+-			if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+-				touch_nmi_watchdog();
+-			page = pgdat_page_nr(pgdat, i);
+-			total++;
+-			if (PageHighMem(page))
+-				highmem++;
+-			if (PageReserved(page))
+-				reserved++;
+-			else if (PageSwapCache(page))
+-				cached++;
+-			else if (page_count(page))
+-				shared += page_count(page) - 1;
+-		}
+-		pgdat_resize_unlock(pgdat, &flags);
+-	}
+-	printk(KERN_INFO "%d pages of RAM\n", total);
+-	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+-	printk(KERN_INFO "%d reserved pages\n", reserved);
+-	printk(KERN_INFO "%d pages shared\n", shared);
+-	printk(KERN_INFO "%d pages swap cached\n", cached);
+-
+-	printk(KERN_INFO "%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
+-	printk(KERN_INFO "%lu pages writeback\n",
+-					global_page_state(NR_WRITEBACK));
+-	printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
+-	printk(KERN_INFO "%lu pages slab\n",
+-		global_page_state(NR_SLAB_RECLAIMABLE) +
+-		global_page_state(NR_SLAB_UNRECLAIMABLE));
+-	printk(KERN_INFO "%lu pages pagetables\n",
+-					global_page_state(NR_PAGETABLE));
++#ifndef CONFIG_XEN
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	pgd = swapper_pg_dir + pgd_index(vaddr);
++	if (pgd_none(*pgd)) {
++		BUG();
++		return;
++	}
++	pud = pud_offset(pgd, vaddr);
++	if (pud_none(*pud)) {
++		BUG();
++		return;
++	}
++	pmd = pmd_offset(pud, vaddr);
++	if (pmd_none(*pmd)) {
++		BUG();
++		return;
++	}
++	pte = pte_offset_kernel(pmd, vaddr);
++	if (pte_val(pteval))
++		set_pte_present(&init_mm, vaddr, pte, pteval);
++	else
++		pte_clear(&init_mm, vaddr, pte);
++
++	/*
++	 * It's enough to flush this one mapping.
++	 * (PGE mappings get flushed as well)
++	 */
++	__flush_tlb_one(vaddr);
++#else
++	if (HYPERVISOR_update_va_mapping(vaddr, pteval,
++					 UVMF_INVLPG|UVMF_ALL))
++		BUG();
++#endif
+ }
+ 
+ /*
+@@ -107,35 +105,10 @@ void set_pmd_pfn(unsigned long vaddr, un
+ 	__flush_tlb_one(vaddr);
+ }
+ 
+-static int fixmaps;
+ unsigned long hypervisor_virt_start = HYPERVISOR_VIRT_START;
+ unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - PAGE_SIZE);
+ EXPORT_SYMBOL(__FIXADDR_TOP);
+ 
+-void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
+-{
+-	unsigned long address = __fix_to_virt(idx);
+-	pte_t pte;
+-
+-	if (idx >= __end_of_fixed_addresses) {
+-		BUG();
+-		return;
+-	}
+-	switch (idx) {
+-	case FIX_WP_TEST:
+-	case FIX_VDSO:
+-		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
+-		break;
+-	default:
+-		pte = pfn_pte_ma(phys >> PAGE_SHIFT, flags);
+-		break;
+-	}
+-	if (HYPERVISOR_update_va_mapping(address, pte,
+-					 UVMF_INVLPG|UVMF_ALL))
+-		BUG();
+-	fixmaps++;
+-}
+-
+ /**
+  * reserve_top_address - reserves a hole in the top of kernel address space
+  * @reserve - size of hole to reserve
+@@ -145,13 +118,48 @@ void __set_fixmap (enum fixed_addresses 
+  */
+ void __init reserve_top_address(unsigned long reserve)
+ {
+-	BUG_ON(fixmaps > 0);
++	BUG_ON(fixmaps_set > 0);
+ 	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+ 	       (int)-reserve);
+ 	__FIXADDR_TOP = -reserve - PAGE_SIZE;
+ 	__VMALLOC_RESERVE += reserve;
+ }
+ 
++/*
++ * vmalloc=size forces the vmalloc area to be exactly 'size'
++ * bytes. This can be used to increase (or decrease) the
++ * vmalloc area - the default is 128m.
++ */
++static int __init parse_vmalloc(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++
++	__VMALLOC_RESERVE = memparse(arg, &arg);
++	return 0;
++}
++early_param("vmalloc", parse_vmalloc);
++
++#ifndef CONFIG_XEN
++/*
++ * reservetop=size reserves a hole at the top of the kernel address space which
++ * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
++ * so relocating the fixmap can be done before paging initialization.
++ */
++static int __init parse_reservetop(char *arg)
++{
++	unsigned long address;
++
++	if (!arg)
++		return -EINVAL;
++
++	address = memparse(arg, &arg);
++	reserve_top_address(address);
++	return 0;
++}
++early_param("reservetop", parse_reservetop);
++#endif
++
+ void make_lowmem_page_readonly(void *va, unsigned int feature)
+ {
+ 	pte_t *pte;
+--- head-2010-01-18.orig/arch/x86/pci/amd_bus.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/amd_bus.c	2009-11-06 10:51:42.000000000 +0100
+@@ -553,6 +553,14 @@ static int __init pci_io_ecs_init(void)
+ 	for_each_online_cpu(cpu)
+ 		amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
+ 			       (void *)(long)cpu);
++#ifdef CONFIG_XEN
++	{
++		u64 reg;
++		rdmsrl(MSR_AMD64_NB_CFG, reg);
++		if (!(reg & ENABLE_CF8_EXT_CFG))
++			return 0;
++	}
++#endif
+ 	pci_probe |= PCI_HAS_IO_ECS;
+ 
+ 	return 0;
+@@ -560,6 +568,10 @@ static int __init pci_io_ecs_init(void)
+ 
+ static int __init amd_postcore_init(void)
+ {
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return 0;
++#endif
+ 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ 		return 0;
+ 
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -11,8 +11,8 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ #include <linux/dmi.h>
+-#include <asm/io.h>
+-#include <asm/smp.h>
++#include <linux/io.h>
++#include <linux/smp.h>
+ #include <asm/io_apic.h>
+ #include <linux/irq.h>
+ #include <linux/acpi.h>
+@@ -45,7 +45,8 @@ struct irq_router {
+ 	char *name;
+ 	u16 vendor, device;
+ 	int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
+-	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
++	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq,
++		int new);
+ };
+ 
+ struct irq_router_handler {
+@@ -61,7 +62,7 @@ void (*pcibios_disable_irq)(struct pci_d
+  *  and perform checksum verification.
+  */
+ 
+-static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
++static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
+ {
+ 	struct irq_routing_table *rt;
+ 	int i;
+@@ -74,10 +75,11 @@ static inline struct irq_routing_table *
+ 	    rt->size < sizeof(struct irq_routing_table))
+ 		return NULL;
+ 	sum = 0;
+-	for (i=0; i < rt->size; i++)
++	for (i = 0; i < rt->size; i++)
+ 		sum += addr[i];
+ 	if (!sum) {
+-		DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
++		DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n",
++			rt);
+ 		return rt;
+ 	}
+ 	return NULL;
+@@ -104,7 +106,9 @@ static struct irq_routing_table * __init
+ 			return rt;
+ 		printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
+ 	}
+-	for(addr = (u8 *) isa_bus_to_virt(0xf0000); addr < (u8 *) isa_bus_to_virt(0x100000); addr += 16) {
++	for (addr = (u8 *) isa_bus_to_virt(0xf0000);
++	     addr < (u8 *) isa_bus_to_virt(0x100000);
++	     addr += 16) {
+ 		rt = pirq_check_routing_table(addr);
+ 		if (rt)
+ 			return rt;
+@@ -126,20 +130,20 @@ static void __init pirq_peer_trick(void)
+ 	struct irq_info *e;
+ 
+ 	memset(busmap, 0, sizeof(busmap));
+-	for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
++	for (i = 0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
+ 		e = &rt->slots[i];
+ #ifdef DEBUG
+ 		{
+ 			int j;
+ 			DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
+-			for(j=0; j<4; j++)
++			for (j = 0; j < 4; j++)
+ 				DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
+ 			DBG("\n");
+ 		}
+ #endif
+ 		busmap[e->bus] = 1;
+ 	}
+-	for(i = 1; i < 256; i++) {
++	for (i = 1; i < 256; i++) {
+ 		int node;
+ 		if (!busmap[i] || pci_find_bus(0, i))
+ 			continue;
+@@ -187,7 +191,8 @@ static unsigned int read_config_nybble(s
+ 	return (nr & 1) ? (x >> 4) : (x & 0xf);
+ }
+ 
+-static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
++static void write_config_nybble(struct pci_dev *router, unsigned offset,
++	unsigned nr, unsigned int val)
+ {
+ 	u8 x;
+ 	unsigned reg = offset + (nr >> 1);
+@@ -289,7 +294,7 @@ static int pirq_ite_get(struct pci_dev *
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+ 
+ 	WARN_ON_ONCE(pirq > 4);
+-	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
++	return read_config_nybble(router, 0x43, pirqmap[pirq-1]);
+ }
+ 
+ static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+@@ -318,7 +323,7 @@ static int pirq_opti_set(struct pci_dev 
+ 
+ /*
+  * Cyrix: nibble offset 0x5C
+- * 0x5C bits 7:4 is INTB bits 3:0 is INTA 
++ * 0x5C bits 7:4 is INTB bits 3:0 is INTA
+  * 0x5D bits 7:4 is INTD bits 3:0 is INTC
+  */
+ static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+@@ -354,7 +359,7 @@ static int pirq_cyrix_set(struct pci_dev
+  *	Apparently there are systems implementing PCI routing table using
+  *	link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
+  *	We try our best to handle both link mappings.
+- *	
++ *
+  *	Currently (2003-05-21) it appears most SiS chipsets follow the
+  *	definition of routing registers from the SiS-5595 southbridge.
+  *	According to the SiS 5595 datasheets the revision id's of the
+@@ -374,7 +379,7 @@ static int pirq_cyrix_set(struct pci_dev
+  *
+  *	0x62:	USBIRQ:
+  *		bit 6 OHCI function disabled (0), enabled (1)
+- *	
++ *
+  *	0x6a:	ACPI/SCI IRQ: bits 4-6 reserved
+  *
+  *	0x7e:	Data Acq. Module IRQ - bits 4-6 reserved
+@@ -437,7 +442,7 @@ static int pirq_vlsi_get(struct pci_dev 
+ {
+ 	WARN_ON_ONCE(pirq >= 9);
+ 	if (pirq > 8) {
+-		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
++		dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
+ 		return 0;
+ 	}
+ 	return read_config_nybble(router, 0x74, pirq-1);
+@@ -447,7 +452,7 @@ static int pirq_vlsi_set(struct pci_dev 
+ {
+ 	WARN_ON_ONCE(pirq >= 9);
+ 	if (pirq > 8) {
+-		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
++		dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
+ 		return 0;
+ 	}
+ 	write_config_nybble(router, 0x74, pirq-1, irq);
+@@ -471,7 +476,8 @@ static int pirq_serverworks_get(struct p
+ 	return inb(0xc01) & 0xf;
+ }
+ 
+-static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev,
++	int pirq, int irq)
+ {
+ 	outb(pirq, 0xc00);
+ 	outb(irq, 0xc01);
+@@ -491,22 +497,20 @@ static int pirq_amd756_get(struct pci_de
+ 	u8 irq;
+ 	irq = 0;
+ 	if (pirq <= 4)
+-	{
+ 		irq = read_config_nybble(router, 0x56, pirq - 1);
+-	}
+-	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
+-		dev->vendor, dev->device, pirq, irq);
++	dev_info(&dev->dev,
++		 "AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n",
++		 dev->vendor, dev->device, pirq, irq);
+ 	return irq;
+ }
+ 
+ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+ {
+-	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
+-		dev->vendor, dev->device, pirq, irq);
++	dev_info(&dev->dev,
++		 "AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n",
++		 dev->vendor, dev->device, pirq, irq);
+ 	if (pirq <= 4)
+-	{
+ 		write_config_nybble(router, 0x56, pirq - 1, irq);
+-	}
+ 	return 1;
+ }
+ 
+@@ -553,50 +557,51 @@ static __init int intel_router_probe(str
+ 	if (pci_dev_present(pirq_440gx))
+ 		return 0;
+ 
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_INTEL_82371FB_0:
+-		case PCI_DEVICE_ID_INTEL_82371SB_0:
+-		case PCI_DEVICE_ID_INTEL_82371AB_0:
+-		case PCI_DEVICE_ID_INTEL_82371MX:
+-		case PCI_DEVICE_ID_INTEL_82443MX_0:
+-		case PCI_DEVICE_ID_INTEL_82801AA_0:
+-		case PCI_DEVICE_ID_INTEL_82801AB_0:
+-		case PCI_DEVICE_ID_INTEL_82801BA_0:
+-		case PCI_DEVICE_ID_INTEL_82801BA_10:
+-		case PCI_DEVICE_ID_INTEL_82801CA_0:
+-		case PCI_DEVICE_ID_INTEL_82801CA_12:
+-		case PCI_DEVICE_ID_INTEL_82801DB_0:
+-		case PCI_DEVICE_ID_INTEL_82801E_0:
+-		case PCI_DEVICE_ID_INTEL_82801EB_0:
+-		case PCI_DEVICE_ID_INTEL_ESB_1:
+-		case PCI_DEVICE_ID_INTEL_ICH6_0:
+-		case PCI_DEVICE_ID_INTEL_ICH6_1:
+-		case PCI_DEVICE_ID_INTEL_ICH7_0:
+-		case PCI_DEVICE_ID_INTEL_ICH7_1:
+-		case PCI_DEVICE_ID_INTEL_ICH7_30:
+-		case PCI_DEVICE_ID_INTEL_ICH7_31:
+-		case PCI_DEVICE_ID_INTEL_ESB2_0:
+-		case PCI_DEVICE_ID_INTEL_ICH8_0:
+-		case PCI_DEVICE_ID_INTEL_ICH8_1:
+-		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_TOLAPAI_0:
+-		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;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_INTEL_82371FB_0:
++	case PCI_DEVICE_ID_INTEL_82371SB_0:
++	case PCI_DEVICE_ID_INTEL_82371AB_0:
++	case PCI_DEVICE_ID_INTEL_82371MX:
++	case PCI_DEVICE_ID_INTEL_82443MX_0:
++	case PCI_DEVICE_ID_INTEL_82801AA_0:
++	case PCI_DEVICE_ID_INTEL_82801AB_0:
++	case PCI_DEVICE_ID_INTEL_82801BA_0:
++	case PCI_DEVICE_ID_INTEL_82801BA_10:
++	case PCI_DEVICE_ID_INTEL_82801CA_0:
++	case PCI_DEVICE_ID_INTEL_82801CA_12:
++	case PCI_DEVICE_ID_INTEL_82801DB_0:
++	case PCI_DEVICE_ID_INTEL_82801E_0:
++	case PCI_DEVICE_ID_INTEL_82801EB_0:
++	case PCI_DEVICE_ID_INTEL_ESB_1:
++	case PCI_DEVICE_ID_INTEL_ICH6_0:
++	case PCI_DEVICE_ID_INTEL_ICH6_1:
++	case PCI_DEVICE_ID_INTEL_ICH7_0:
++	case PCI_DEVICE_ID_INTEL_ICH7_1:
++	case PCI_DEVICE_ID_INTEL_ICH7_30:
++	case PCI_DEVICE_ID_INTEL_ICH7_31:
++	case PCI_DEVICE_ID_INTEL_ESB2_0:
++	case PCI_DEVICE_ID_INTEL_ICH8_0:
++	case PCI_DEVICE_ID_INTEL_ICH8_1:
++	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_TOLAPAI_0:
++	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:
++	case PCI_DEVICE_ID_INTEL_PCH_0:
++	case PCI_DEVICE_ID_INTEL_PCH_1:
++		r->name = "PIIX/ICH";
++		r->get = pirq_piix_get;
++		r->set = pirq_piix_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+@@ -610,7 +615,7 @@ static __init int via_router_probe(struc
+ 	 * workarounds for some buggy BIOSes
+ 	 */
+ 	if (device == PCI_DEVICE_ID_VIA_82C586_0) {
+-		switch(router->device) {
++		switch (router->device) {
+ 		case PCI_DEVICE_ID_VIA_82C686:
+ 			/*
+ 			 * Asus k7m bios wrongly reports 82C686A
+@@ -635,7 +640,7 @@ static __init int via_router_probe(struc
+ 		}
+ 	}
+ 
+-	switch(device) {
++	switch (device) {
+ 	case PCI_DEVICE_ID_VIA_82C586_0:
+ 		r->name = "VIA";
+ 		r->get = pirq_via586_get;
+@@ -658,28 +663,27 @@ static __init int via_router_probe(struc
+ 
+ static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_VLSI_82C534:
+-			r->name = "VLSI 82C534";
+-			r->get = pirq_vlsi_get;
+-			r->set = pirq_vlsi_set;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_VLSI_82C534:
++		r->name = "VLSI 82C534";
++		r->get = pirq_vlsi_get;
++		r->set = pirq_vlsi_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ 
+-static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++static __init int serverworks_router_probe(struct irq_router *r,
++		struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+-		case PCI_DEVICE_ID_SERVERWORKS_CSB5:
+-			r->name = "ServerWorks";
+-			r->get = pirq_serverworks_get;
+-			r->set = pirq_serverworks_set;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_SERVERWORKS_OSB4:
++	case PCI_DEVICE_ID_SERVERWORKS_CSB5:
++		r->name = "ServerWorks";
++		r->get = pirq_serverworks_get;
++		r->set = pirq_serverworks_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+@@ -688,7 +692,7 @@ static __init int sis_router_probe(struc
+ {
+ 	if (device != PCI_DEVICE_ID_SI_503)
+ 		return 0;
+-		
++
+ 	r->name = "SIS";
+ 	r->get = pirq_sis_get;
+ 	r->set = pirq_sis_set;
+@@ -697,50 +701,45 @@ static __init int sis_router_probe(struc
+ 
+ static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_CYRIX_5520:
+-			r->name = "NatSemi";
+-			r->get = pirq_cyrix_get;
+-			r->set = pirq_cyrix_set;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_CYRIX_5520:
++		r->name = "NatSemi";
++		r->get = pirq_cyrix_get;
++		r->set = pirq_cyrix_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_OPTI_82C700:
+-			r->name = "OPTI";
+-			r->get = pirq_opti_get;
+-			r->set = pirq_opti_set;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_OPTI_82C700:
++		r->name = "OPTI";
++		r->get = pirq_opti_get;
++		r->set = pirq_opti_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_ITE_IT8330G_0:
+-			r->name = "ITE";
+-			r->get = pirq_ite_get;
+-			r->set = pirq_ite_set;
+-			return 1;
++	switch (device) {
++	case PCI_DEVICE_ID_ITE_IT8330G_0:
++		r->name = "ITE";
++		r->get = pirq_ite_get;
++		r->set = pirq_ite_set;
++		return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
++	switch (device) {
+ 	case PCI_DEVICE_ID_AL_M1533:
+ 	case PCI_DEVICE_ID_AL_M1563:
+-		printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
+ 		r->name = "ALI";
+ 		r->get = pirq_ali_get;
+ 		r->set = pirq_ali_set;
+@@ -751,25 +750,24 @@ static __init int ali_router_probe(struc
+ 
+ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+-	switch(device)
+-	{
+-		case PCI_DEVICE_ID_AMD_VIPER_740B:
+-			r->name = "AMD756";
+-			break;
+-		case PCI_DEVICE_ID_AMD_VIPER_7413:
+-			r->name = "AMD766";
+-			break;
+-		case PCI_DEVICE_ID_AMD_VIPER_7443:
+-			r->name = "AMD768";
+-			break;
+-		default:
+-			return 0;
++	switch (device) {
++	case PCI_DEVICE_ID_AMD_VIPER_740B:
++		r->name = "AMD756";
++		break;
++	case PCI_DEVICE_ID_AMD_VIPER_7413:
++		r->name = "AMD766";
++		break;
++	case PCI_DEVICE_ID_AMD_VIPER_7443:
++		r->name = "AMD768";
++		break;
++	default:
++		return 0;
+ 	}
+ 	r->get = pirq_amd756_get;
+ 	r->set = pirq_amd756_set;
+ 	return 1;
+ }
+-		
++
+ static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+ {
+ 	switch (device) {
+@@ -811,7 +809,7 @@ static struct pci_dev *pirq_router_dev;
+  *	FIXME: should we have an option to say "generic for
+  *	chipset" ?
+  */
+- 
++
+ static void __init pirq_find_router(struct irq_router *r)
+ {
+ 	struct irq_routing_table *rt = pirq_table;
+@@ -830,7 +828,7 @@ static void __init pirq_find_router(stru
+ 	r->name = "default";
+ 	r->get = NULL;
+ 	r->set = NULL;
+-	
++
+ 	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
+ 	    rt->rtr_vendor, rt->rtr_device);
+ 
+@@ -841,19 +839,19 @@ static void __init pirq_find_router(stru
+ 		return;
+ 	}
+ 
+-	for( h = pirq_routers; h->vendor; h++) {
++	for (h = pirq_routers; h->vendor; h++) {
+ 		/* First look for a router match */
+-		if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
++		if (rt->rtr_vendor == h->vendor &&
++			h->probe(r, pirq_router_dev, rt->rtr_device))
+ 			break;
+ 		/* Fall back to a device match */
+-		if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
++		if (pirq_router_dev->vendor == h->vendor &&
++			h->probe(r, pirq_router_dev, pirq_router_dev->device))
+ 			break;
+ 	}
+-	printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
+-		pirq_router.name,
+-		pirq_router_dev->vendor,
+-		pirq_router_dev->device,
+-		pci_name(pirq_router_dev));
++	dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n",
++		 pirq_router.name,
++		 pirq_router_dev->vendor, pirq_router_dev->device);
+ 
+ 	/* The device remains referenced for the kernel lifetime */
+ }
+@@ -861,11 +859,13 @@ static void __init pirq_find_router(stru
+ static struct irq_info *pirq_get_info(struct pci_dev *dev)
+ {
+ 	struct irq_routing_table *rt = pirq_table;
+-	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
++	int entries = (rt->size - sizeof(struct irq_routing_table)) /
++		sizeof(struct irq_info);
+ 	struct irq_info *info;
+ 
+ 	for (info = rt->slots; entries--; info++)
+-		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
++		if (info->bus == dev->bus->number &&
++			PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
+ 			return info;
+ 	return NULL;
+ }
+@@ -884,7 +884,7 @@ static int pcibios_lookup_irq(struct pci
+ 	/* Find IRQ pin */
+ 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ 	if (!pin) {
+-		DBG(KERN_DEBUG " -> no interrupt pin\n");
++		dev_dbg(&dev->dev, "no interrupt pin\n");
+ 		return 0;
+ 	}
+ 	pin = pin - 1;
+@@ -893,20 +893,21 @@ static int pcibios_lookup_irq(struct pci
+ 
+ 	if (!pirq_table)
+ 		return 0;
+-	
+-	DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
++
+ 	info = pirq_get_info(dev);
+ 	if (!info) {
+-		DBG(" -> not found in routing table\n" KERN_DEBUG);
++		dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
++			'A' + pin);
+ 		return 0;
+ 	}
+ 	pirq = info->irq[pin].link;
+ 	mask = info->irq[pin].bitmap;
+ 	if (!pirq) {
+-		DBG(" -> not routed\n" KERN_DEBUG);
++		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
+ 		return 0;
+ 	}
+-	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
++	dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
++		'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
+ 	mask &= pcibios_irq_mask;
+ 
+ 	/* Work around broken HP Pavilion Notebooks which assign USB to
+@@ -919,7 +920,8 @@ static int pcibios_lookup_irq(struct pci
+ 	}
+ 
+ 	/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
+-	if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
++	if (acer_tm360_irqrouting && dev->irq == 11 &&
++		dev->vendor == PCI_VENDOR_ID_O2) {
+ 		pirq = 0x68;
+ 		mask = 0x400;
+ 		dev->irq = r->get(pirq_router_dev, dev, pirq);
+@@ -932,51 +934,50 @@ static int pcibios_lookup_irq(struct pci
+ 	 */
+ 	newirq = dev->irq;
+ 	if (newirq && !((1 << newirq) & mask)) {
+-		if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
+-		else printk("\n" KERN_WARNING
+-			"PCI: IRQ %i for device %s doesn't match PIRQ mask "
+-			"- try pci=usepirqmask\n" KERN_DEBUG, newirq,
+-			pci_name(dev));
++		if (pci_probe & PCI_USE_PIRQ_MASK)
++			newirq = 0;
++		else
++			dev_warn(&dev->dev, "IRQ %d doesn't match PIRQ mask "
++				 "%#x; try pci=usepirqmask\n", newirq, mask);
+ 	}
+ 	if (!newirq && assign) {
+ 		for (i = 0; i < 16; i++) {
+ 			if (!(mask & (1 << i)))
+ 				continue;
+-			if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED))
++			if (pirq_penalty[i] < pirq_penalty[newirq] &&
++				can_request_irq(i, IRQF_SHARED))
+ 				newirq = i;
+ 		}
+ 	}
+-	DBG(" -> newirq=%d", newirq);
++	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
+ 
+ 	/* Check if it is hardcoded */
+ 	if ((pirq & 0xf0) == 0xf0) {
+ 		irq = pirq & 0xf;
+-		DBG(" -> hardcoded IRQ %d\n", irq);
+-		msg = "Hardcoded";
+-	} else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
+-	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
+-		DBG(" -> got IRQ %d\n", irq);
+-		msg = "Found";
++		msg = "hardcoded";
++	} else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
++	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) {
++		msg = "found";
+ 		eisa_set_level_irq(irq);
+-	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+-		DBG(" -> assigning IRQ %d", newirq);
++	} else if (newirq && r->set &&
++		(dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+ 		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
+ 			eisa_set_level_irq(newirq);
+-			DBG(" ... OK\n");
+-			msg = "Assigned";
++			msg = "assigned";
+ 			irq = newirq;
+ 		}
+ 	}
+ 
+ 	if (!irq) {
+-		DBG(" ... failed\n");
+ 		if (newirq && mask == (1 << newirq)) {
+-			msg = "Guessed";
++			msg = "guessed";
+ 			irq = newirq;
+-		} else
++		} else {
++			dev_dbg(&dev->dev, "can't route interrupt\n");
+ 			return 0;
++		}
+ 	}
+-	printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
++	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
+ 
+ 	/* Update IRQ for all devices with the same pirq value */
+ 	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
+@@ -988,20 +989,25 @@ static int pcibios_lookup_irq(struct pci
+ 		if (!info)
+ 			continue;
+ 		if (info->irq[pin].link == pirq) {
+-			/* We refuse to override the dev->irq information. Give a warning! */
+-		    	if ( dev2->irq && dev2->irq != irq && \
++			/*
++			 * We refuse to override the dev->irq
++			 * information. Give a warning!
++			 */
++			if (dev2->irq && dev2->irq != irq && \
+ 			(!(pci_probe & PCI_USE_PIRQ_MASK) || \
+-			((1 << dev2->irq) & mask)) ) {
++			((1 << dev2->irq) & mask))) {
+ #ifndef CONFIG_PCI_MSI
+-		    		printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
+-				       pci_name(dev2), dev2->irq, irq);
++				dev_info(&dev2->dev, "IRQ routing conflict: "
++					 "have IRQ %d, want IRQ %d\n",
++					 dev2->irq, irq);
+ #endif
+-		    		continue;
+-		    	}
++				continue;
++			}
+ 			dev2->irq = irq;
+ 			pirq_penalty[irq]++;
+ 			if (dev != dev2)
+-				printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
++				dev_info(&dev->dev, "sharing IRQ %d with %s\n",
++					 irq, pci_name(dev2));
+ 		}
+ 	}
+ 	return 1;
+@@ -1015,15 +1021,20 @@ static void __init pcibios_fixup_irqs(vo
+ 	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
+ 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ 		/*
+-		 * If the BIOS has set an out of range IRQ number, just ignore it.
+-		 * Also keep track of which IRQ's are already in use.
++		 * If the BIOS has set an out of range IRQ number, just
++		 * ignore it.  Also keep track of which IRQ's are
++		 * already in use.
+ 		 */
+ 		if (dev->irq >= 16) {
+-			DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
++			dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
+ 			dev->irq = 0;
+ 		}
+-		/* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
+-		if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
++		/*
++		 * If the IRQ is already assigned to a PCI device,
++		 * ignore its ISA use penalty
++		 */
++		if (pirq_penalty[dev->irq] >= 100 &&
++				pirq_penalty[dev->irq] < 100000)
+ 			pirq_penalty[dev->irq] = 0;
+ 		pirq_penalty[dev->irq]++;
+ 	}
+@@ -1035,13 +1046,17 @@ static void __init pcibios_fixup_irqs(vo
+ 		/*
+ 		 * Recalculate IRQ numbers if we use the I/O APIC.
+ 		 */
+-		if (io_apic_assign_pci_irqs)
+-		{
++		if (io_apic_assign_pci_irqs) {
+ 			int irq;
+ 
+ 			if (pin) {
+-				pin--;		/* interrupt pins are numbered starting from 1 */
+-				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
++				/*
++				 * interrupt pins are numbered starting
++				 * from 1
++				 */
++				pin--;
++				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
++					PCI_SLOT(dev->devfn), pin);
+ 	/*
+ 	 * Busses behind bridges are typically not listed in the MP-table.
+ 	 * In this case we have to look up the IRQ based on the parent bus,
+@@ -1049,18 +1064,18 @@ static void __init pcibios_fixup_irqs(vo
+ 	 * busses itself so we should get into this branch reliably.
+ 	 */
+ 				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+-					struct pci_dev * bridge = dev->bus->self;
++					struct pci_dev *bridge = dev->bus->self;
+ 
+ 					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+-					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
++					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+ 							PCI_SLOT(bridge->devfn), pin);
+ 					if (irq >= 0)
+-						printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+-							pci_name(bridge), 'A' + pin, irq);
++						dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n",
++							 pci_name(bridge),
++							 'A' + pin, irq);
+ 				}
+ 				if (irq >= 0) {
+-					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+-						pci_name(dev), 'A' + pin, irq);
++					dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq);
+ 					dev->irq = irq;
+ 				}
+ 			}
+@@ -1082,7 +1097,8 @@ static int __init fix_broken_hp_bios_irq
+ {
+ 	if (!broken_hp_bios_irq9) {
+ 		broken_hp_bios_irq9 = 1;
+-		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
++		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
++			d->ident);
+ 	}
+ 	return 0;
+ }
+@@ -1095,7 +1111,8 @@ static int __init fix_acer_tm360_irqrout
+ {
+ 	if (!acer_tm360_irqrouting) {
+ 		acer_tm360_irqrouting = 1;
+-		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
++		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
++			d->ident);
+ 	}
+ 	return 0;
+ }
+@@ -1107,7 +1124,8 @@ static struct dmi_system_id __initdata p
+ 		.matches = {
+ 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ 			DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+-			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
++			DMI_MATCH(DMI_PRODUCT_VERSION,
++				"HP Pavilion Notebook Model GE"),
+ 			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+ 		},
+ 	},
+@@ -1122,7 +1140,7 @@ static struct dmi_system_id __initdata p
+ 	{ }
+ };
+ 
+-static int __init pcibios_irq_init(void)
++int __init pcibios_irq_init(void)
+ {
+ 	DBG(KERN_DEBUG "PCI: IRQ init\n");
+ 
+@@ -1142,11 +1160,14 @@ static int __init pcibios_irq_init(void)
+ 		pirq_find_router(&pirq_router);
+ 		if (pirq_table->exclusive_irqs) {
+ 			int i;
+-			for (i=0; i<16; i++)
++			for (i = 0; i < 16; i++)
+ 				if (!(pirq_table->exclusive_irqs & (1 << i)))
+ 					pirq_penalty[i] += 100;
+ 		}
+-		/* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
++		/*
++		 * If we're using the I/O APIC, avoid using the PCI IRQ
++		 * routing table
++		 */
+ 		if (io_apic_assign_pci_irqs)
+ 			pirq_table = NULL;
+ 	}
+@@ -1157,9 +1178,6 @@ static int __init pcibios_irq_init(void)
+ 	return 0;
+ }
+ 
+-subsys_initcall(pcibios_irq_init);
+-
+-
+ static void pirq_penalize_isa_irq(int irq, int active)
+ {
+ 	/*
+@@ -1193,7 +1211,7 @@ static int pirq_enable_irq(struct pci_de
+ 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+ 		char *msg = "";
+ 
+-		pin--;		/* interrupt pins are numbered starting from 1 */
++		pin--; /* interrupt pins are numbered starting from 1 */
+ 
+ 		if (io_apic_assign_pci_irqs) {
+ 			int irq;
+@@ -1207,35 +1225,41 @@ static int pirq_enable_irq(struct pci_de
+ 			 */
+ 			temp_dev = dev;
+ 			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+-				struct pci_dev * bridge = dev->bus->self;
++				struct pci_dev *bridge = dev->bus->self;
+ 
+ 				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+-				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
++				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+ 						PCI_SLOT(bridge->devfn), pin);
+ 				if (irq >= 0)
+-					printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+-						pci_name(bridge), 'A' + pin, irq);
++					dev_warn(&dev->dev, "using bridge %s "
++						 "INT %c to get IRQ %d\n",
++						 pci_name(bridge), 'A' + pin,
++						 irq);
+ 				dev = bridge;
+ 			}
+ 			dev = temp_dev;
+ 			if (irq >= 0) {
+-				printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+-					pci_name(dev), 'A' + pin, irq);
++				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
++					 "INT %c -> IRQ %d\n", 'A' + pin, irq);
+ 				dev->irq = irq;
+ 				return 0;
+ 			} else
+-				msg = " Probably buggy MP table.";
++				msg = "; probably buggy MP table";
+ 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+ 			msg = "";
+ 		else
+-			msg = " Please try using pci=biosirq.";
++			msg = "; please try using pci=biosirq";
+ 
+-		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
+-		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
++		/*
++		 * With IDE legacy devices the IRQ lookup failure is not
++		 * a problem..
++		 */
++		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
++				!(dev->class & 0x5))
+ 			return 0;
+ 
+-		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+-		       'A' + pin, pci_name(dev), msg);
++		dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
++			 'A' + pin, msg);
+ 	}
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/vdso/Makefile	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/Makefile	2009-11-06 10:51:42.000000000 +0100
+@@ -65,9 +65,7 @@ obj-$(VDSO32-y)			+= vdso32-syms.lds
+ vdso32.so-$(VDSO32-y)		+= int80
+ vdso32.so-$(CONFIG_COMPAT)	+= syscall
+ vdso32.so-$(VDSO32-y)		+= sysenter
+-xen-vdso32-$(subst 1,$(CONFIG_COMPAT),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80
+-xen-vdso32-$(CONFIG_X86_32)	+= syscall
+-vdso32.so-$(CONFIG_XEN)		+= $(xen-vdso32-y)
++vdso32.so-$(CONFIG_X86_XEN)	+= syscall
+ 
+ vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
+ 
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32.S	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32.S	2009-11-06 10:51:42.000000000 +0100
+@@ -9,7 +9,7 @@ vdso32_int80_end:
+ 
+ 	.globl vdso32_syscall_start, vdso32_syscall_end
+ vdso32_syscall_start:
+-#ifdef CONFIG_COMPAT
++#if defined(CONFIG_COMPAT) || defined(CONFIG_X86_XEN)
+ 	.incbin "arch/x86/vdso/vdso32-syscall.so"
+ #endif
+ vdso32_syscall_end:
+@@ -19,16 +19,4 @@ vdso32_sysenter_start:
+ 	.incbin "arch/x86/vdso/vdso32-sysenter.so"
+ vdso32_sysenter_end:
+ 
+-#if defined(CONFIG_X86_64_XEN) && CONFIG_XEN_COMPAT < 0x030200
+-	.globl vdso32_int80_start, vdso32_int80_end
+-vdso32_int80_start:
+-	.incbin "arch/x86/vdso/vdso32-int80.so"
+-vdso32_int80_end:
+-#elif defined(CONFIG_X86_XEN)
+-	.globl vdso32_syscall_start, vdso32_syscall_end
+-vdso32_syscall_start:
+-	.incbin "arch/x86/vdso/vdso32-syscall.so"
+-vdso32_syscall_end:
+-#endif
+-
+ __FINIT
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -195,50 +195,28 @@ static __init void relocate_vdso(Elf32_E
+ 	}
+ }
+ 
+-/*
+- * These symbols are defined by vdso32.S to mark the bounds
+- * of the ELF DSO images included therein.
+- */
+-extern const char vdso32_default_start, vdso32_default_end;
+-extern const char vdso32_sysenter_start, vdso32_sysenter_end;
+ static struct page *vdso32_pages[1];
+ 
+ #ifdef CONFIG_X86_64
+ 
+-#if CONFIG_XEN_COMPAT < 0x030200
+-static int use_int80 = 1;
+-#endif
+-static int use_sysenter __read_mostly = -1;
+-
+-#define	vdso32_sysenter()	(use_sysenter > 0)
++#define	vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SYSENTER32))
++#define	vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
+ 
+-/* May not be __init: called during resume */
+-void syscall32_cpu_init(void)
++void __cpuinit syscall32_cpu_init(void)
+ {
+-	static const struct callback_register cstar = {
++	static const struct callback_register __cpuinitconst cstar = {
+ 		.type = CALLBACKTYPE_syscall32,
+ 		.address = (unsigned long)ia32_cstar_target
+ 	};
+-	static const struct callback_register sysenter = {
++	static const struct callback_register __cpuinitconst sysenter = {
+ 		.type = CALLBACKTYPE_sysenter,
+ 		.address = (unsigned long)ia32_sysenter_target
+ 	};
+ 
+-	if ((HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0) ||
+-	    (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) < 0))
+-#if CONFIG_XEN_COMPAT < 0x030200
+-		return;
+-	use_int80 = 0;
+-#else
+-		BUG();
+-#endif
+-
+-	if (use_sysenter < 0) {
+-		if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+-			use_sysenter = 1;
+-		if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR)
+-			use_sysenter = 1;
+-	}
++	if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
++		setup_clear_cpu_cap(X86_FEATURE_SYSENTER32);
++	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) < 0)
++		setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
+ }
+ 
+ #define compat_uses_vma		1
+@@ -250,6 +228,7 @@ static inline void map_compat_vdso(int m
+ #else  /* CONFIG_X86_32 */
+ 
+ #define vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SEP))
++#define vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
+ 
+ extern asmlinkage void ia32pv_cstar_target(void);
+ static const struct callback_register __cpuinitconst cstar = {
+@@ -265,13 +244,13 @@ void __cpuinit enable_sep_cpu(void)
+ 		.address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target },
+ 	};
+ 
+-	if (boot_cpu_has(X86_FEATURE_SYSCALL)) {
++	if (vdso32_syscall()) {
+ 		if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) != 0)
+ 			BUG();
+ 		return;
+ 	}
+ 
+-	if (!boot_cpu_has(X86_FEATURE_SEP))
++	if (!vdso32_sysenter())
+ 		return;
+ 
+ 	if (xen_feature(XENFEAT_supervisor_mode_kernel))
+@@ -341,34 +320,26 @@ int __init sysenter_setup(void)
+ 
+ #ifdef CONFIG_X86_32
+ 	gate_vma_init();
+-#endif
+ 
+-#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT < 0x030200
+-	if (use_int80) {
+-		extern const char vdso32_int80_start, vdso32_int80_end;
+-
+-		vsyscall = &vdso32_int80_start;
+-		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
+-	} else
+-#elif defined(CONFIG_X86_32)
+-	if (boot_cpu_has(X86_FEATURE_SYSCALL)
+-	    && (boot_cpu_data.x86_vendor != X86_VENDOR_AMD
+-		|| HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) != 0))
+-		setup_clear_cpu_cap(X86_FEATURE_SYSCALL);
+-	barrier(); /* until clear_bit()'s constraints are correct ... */
+ 	if (boot_cpu_has(X86_FEATURE_SYSCALL)) {
+-		extern const char vdso32_syscall_start, vdso32_syscall_end;
+-
++		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD
++		    && HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) == 0)
++			setup_force_cpu_cap(X86_FEATURE_SYSCALL32);
++		else {
++			setup_clear_cpu_cap(X86_FEATURE_SYSCALL);
++			setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
++		}
++	}
++#endif
++	if (vdso32_syscall()) {
+ 		vsyscall = &vdso32_syscall_start;
+ 		vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
+-	} else
+-#endif
+-	if (!vdso32_sysenter()) {
+-		vsyscall = &vdso32_default_start;
+-		vsyscall_len = &vdso32_default_end - &vdso32_default_start;
+-	} else {
++	} else if (vdso32_sysenter()){
+ 		vsyscall = &vdso32_sysenter_start;
+ 		vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
++	} else {
++		vsyscall = &vdso32_int80_start;
++		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
+ 	}
+ 
+ 	memcpy(syscall_page, vsyscall, vsyscall_len);
+--- head-2010-01-18.orig/arch/x86/xen/Kconfig	2009-11-20 11:01:03.000000000 +0100
++++ head-2010-01-18/arch/x86/xen/Kconfig	2009-11-06 10:51:42.000000000 +0100
+@@ -17,7 +17,7 @@ config XEN_MAX_DOMAIN_MEMORY
+        int "Maximum allowed size of a domain in gigabytes"
+        default 8 if X86_32
+        default 32 if X86_64
+-       depends on XEN
++       depends on PARAVIRT_XEN
+        help
+          The pseudo-physical to machine address array is sized
+          according to the maximum possible memory size of a Xen
+@@ -26,7 +26,7 @@ config XEN_MAX_DOMAIN_MEMORY
+ 
+ config XEN_SAVE_RESTORE
+        bool
+-       depends on XEN && PM
++       depends on PARAVIRT_XEN && PM
+        default y
+ 
+ config XEN_DEBUG_FS
+--- head-2010-01-18.orig/drivers/acpi/processor_core.c	2010-01-04 12:38:43.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_core.c	2010-01-04 12:40:08.000000000 +0100
+@@ -841,10 +841,12 @@ static int __cpuinit acpi_processor_add(
+ 	if (result)
+ 		goto err_free_cpumask;
+ 
+-	sysdev = get_cpu_sysdev(pr->id);
+-	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
+-		result = -EFAULT;
+-		goto err_remove_fs;
++	if (pr->id != -1) {
++		sysdev = get_cpu_sysdev(pr->id);
++		if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
++			result = -EFAULT;
++			goto err_remove_fs;
++		}
+ 	}
+ 
+ 	/* _PDC call should be done before doing anything else (if reqd.). */
+@@ -934,7 +936,8 @@ static int acpi_processor_remove(struct 
+ 
+ 	acpi_processor_power_exit(pr, device);
+ 
+-	sysfs_remove_link(&device->dev.kobj, "sysdev");
++	if (pr->id != -1)
++		sysfs_remove_link(&device->dev.kobj, "sysdev");
+ 
+ 	acpi_processor_remove_fs(device);
+ 
+--- head-2010-01-18.orig/drivers/char/tpm/tpm_vtpm.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/char/tpm/tpm_vtpm.c	2009-11-06 10:51:42.000000000 +0100
+@@ -347,7 +347,7 @@ static int _vtpm_send_queued(struct tpm_
+ {
+ 	int rc;
+ 	int error = 0;
+-	long flags;
++	unsigned long flags;
+ 	unsigned char buffer[1];
+ 	struct vtpm_state *vtpms;
+ 	vtpms = (struct vtpm_state *)chip_get_private(chip);
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:05:41.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:23:40.000000000 +0100
+@@ -92,12 +92,10 @@ arch_teardown_msi_irqs(struct pci_dev *d
+ }
+ #endif
+ 
+-static void msi_set_enable(struct pci_dev *dev, int enable)
++static void __msi_set_enable(struct pci_dev *dev, int pos, int enable)
+ {
+-	int pos;
+ 	u16 control;
+ 
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ 	if (pos) {
+ 		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ 		control &= ~PCI_MSI_FLAGS_ENABLE;
+@@ -107,6 +105,11 @@ static void msi_set_enable(struct pci_de
+ 	}
+ }
+ 
++static void msi_set_enable(struct pci_dev *dev, int enable)
++{
++	__msi_set_enable(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), enable);
++}
++
+ static void msix_set_enable(struct pci_dev *dev, int enable)
+ {
+ 	int pos;
+@@ -219,8 +222,7 @@ static int msi_get_dev_owner(struct pci_
+ 
+ 	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);
++		dev_info(&dev->dev, "get owner: %x \n", owner);
+ 		return owner;
+ 	}
+ 
+@@ -240,7 +242,7 @@ static int msi_unmap_pirq(struct pci_dev
+ 		? pirq : evtchn_get_xen_pirq(pirq);
+ 
+ 	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap)))
+-		printk(KERN_WARNING "unmap irq %x failed\n", pirq);
++		dev_warn(&dev->dev, "unmap irq %x failed\n", pirq);
+ 
+ 	if (rc < 0)
+ 		return rc;
+@@ -288,7 +290,7 @@ static int msi_map_vector(struct pci_dev
+ 	map_irq.table_base = table_base;
+ 
+ 	if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
+-		printk(KERN_WARNING "map irq failed\n");
++		dev_warn(&dev->dev, "map irq failed\n");
+ 
+ 	if (rc < 0)
+ 		return rc;
+@@ -399,10 +401,9 @@ static int msix_capability_init(struct p
+ 		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));
++				dev_warn(&dev->dev,
++					 "msix entry %d was not freed\n",
++					 entries[i].entry);
+ 				(entries + i)->vector = pirq_entry->pirq;
+ 				mapped = 1;
+ 				break;
+@@ -528,9 +529,8 @@ int pci_enable_msi(struct pci_dev* dev)
+ 
+ 	/* Check whether driver already requested for MSI-X irqs */
+ 	if (dev->msix_enabled) {
+-		printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
+-		       "Device already has MSI-X enabled\n",
+-		       pci_name(dev));
++		dev_info(&dev->dev, "can't enable MSI "
++			 "(MSI-X already enabled)\n");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -612,7 +612,8 @@ int pci_enable_msix(struct pci_dev* dev,
+ 		temp = dev->irq;
+ 		ret = pci_frontend_enable_msix(dev, entries, nvec);
+ 		if (ret) {
+-			printk("get %x from pci_frontend_enable_msix\n", ret);
++			dev_warn(&dev->dev,
++				 "got %x from frontend_enable_msix\n", ret);
+ 			return ret;
+ 		}
+ 		dev->msix_enabled = 1;
+@@ -663,9 +664,8 @@ int pci_enable_msix(struct pci_dev* dev,
+ 	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 irq assigned\n",
+-		       pci_name(dev));
++		dev_info(&dev->dev, "can't enable MSI-X "
++		       "(MSI IRQ already assigned)\n");
+ 		return -EINVAL;
+ 	}
+ 
+--- head-2010-01-18.orig/drivers/xen/Makefile	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/Makefile	2009-11-06 10:51:42.000000000 +0100
+@@ -1,4 +1,4 @@
+-obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o features.o events.o
++obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o features.o events.o manage.o
+ xen-xencomm-$(CONFIG_PARAVIRT_XEN) := xencomm.o
+ xen-balloon-$(CONFIG_PARAVIRT_XEN) := balloon.o
+ 
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2009-11-06 10:51:42.000000000 +0100
+@@ -82,7 +82,7 @@ struct balloon_stats balloon_stats;
+ /* We increase/decrease in batches which fit in a page */
+ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+ 
+-#if !defined(MODULE) && defined(CONFIG_HIGHMEM)
++#ifdef CONFIG_HIGHMEM
+ #define inc_totalhigh_pages() (totalhigh_pages++)
+ #define dec_totalhigh_pages() (totalhigh_pages--)
+ #else
+--- head-2010-01-18.orig/drivers/xen/balloon/sysfs.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/sysfs.c	2009-11-06 10:51:42.000000000 +0100
+@@ -45,6 +45,7 @@
+ 
+ #define BALLOON_SHOW(name, format, args...)			\
+ 	static ssize_t show_##name(struct sys_device *dev,	\
++				   struct sysdev_attribute *attr, \
+ 				   char *buf)			\
+ 	{							\
+ 		return sprintf(buf, format, ##args);		\
+@@ -56,14 +57,15 @@ BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(b
+ BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high));
+ BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages));
+ 
+-static ssize_t show_target_kb(struct sys_device *dev, char *buf)
++static ssize_t show_target_kb(struct sys_device *dev,
++			      struct sysdev_attribute *attr, char *buf)
+ {
+ 	return sprintf(buf, "%lu\n", PAGES2KB(bs.target_pages));
+ }
+ 
+ static ssize_t store_target_kb(struct sys_device *dev,
+-			       const char *buf,
+-			       size_t count)
++			       struct sysdev_attribute *attr,
++			       const char *buf, size_t count)
+ {
+ 	char memstring[64], *endchar;
+ 	unsigned long long target_bytes;
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2010-01-04 12:38:54.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 12:40:02.000000000 +0100
+@@ -54,6 +54,7 @@
+ #include <linux/gfp.h>
+ #include <linux/poll.h>
+ #include <linux/delay.h>
++#include <linux/nsproxy.h>
+ #include <asm/tlbflush.h>
+ 
+ #define MAX_TAP_DEV 256     /*the maximum number of tapdisk ring devices    */
+@@ -523,7 +524,7 @@ found:
+ 
+ 		if ((class = get_xen_class()) != NULL)
+ 			device_create(class, NULL, MKDEV(blktap_major, minor),
+-				      "blktap%d", minor);
++				      NULL, "blktap%d", minor);
+ 	}
+ 
+ out:
+@@ -1739,7 +1740,8 @@ static int __init blkif_init(void)
+ 		 * We only create the device when a request of a new device is
+ 		 * made.
+ 		 */
+-		device_create(class, NULL, MKDEV(blktap_major, 0), "blktap0");
++		device_create(class, NULL, MKDEV(blktap_major, 0), NULL,
++			      "blktap0");
+ 	} else {
+ 		/* this is bad, but not fatal */
+ 		WPRINTK("blktap: sysfs xen_class not created\n");
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2010-01-04 12:37:57.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2009-11-06 10:51:42.000000000 +0100
+@@ -3,6 +3,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/hdreg.h>
+ #include <linux/module.h>
++#include <linux/version.h>
+ #include <asm/tlbflush.h>
+ 
+ #include <scsi/scsi.h>
+--- head-2010-01-18.orig/drivers/xen/blktap2/sysfs.c	2009-12-09 16:11:54.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/sysfs.c	2009-12-09 16:14:04.000000000 +0100
+@@ -307,8 +307,8 @@ blktap_sysfs_create(struct blktap *tap)
+ 
+ 	ring = &tap->ring;
+ 
+-	dev = device_create_drvdata(class, NULL, ring->devno, tap,
+-				    "blktap%d", tap->minor);
++	dev = device_create(class, NULL, ring->devno, tap,
++			    "blktap%d", tap->minor);
+ 	if (IS_ERR(dev))
+ 		return PTR_ERR(dev);
+ 
+--- head-2010-01-18.orig/drivers/xen/char/mem.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/char/mem.c	2009-11-06 10:51:42.000000000 +0100
+@@ -35,7 +35,7 @@ static inline int uncached_access(struct
+ 
+ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
+ {
+-#ifdef CONFIG_NONPROMISC_DEVMEM
++#ifdef CONFIG_STRICT_DEVMEM
+ 	u64 from = ((u64)pfn) << PAGE_SHIFT;
+ 	u64 to = from + size;
+ 	u64 cursor = from;
+@@ -172,7 +172,10 @@ static void mmap_mem_close(struct vm_are
+ 
+ static struct vm_operations_struct mmap_mem_ops = {
+ 	.open  = mmap_mem_open,
+-	.close = mmap_mem_close
++	.close = mmap_mem_close,
++#ifdef CONFIG_HAVE_IOREMAP_PROT
++	.access = generic_access_phys
++#endif
+ };
+ 
+ static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma)
+--- head-2010-01-18.orig/drivers/xen/console/console.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/console/console.c	2009-11-06 10:51:42.000000000 +0100
+@@ -431,9 +431,7 @@ static void __xencons_tx_flush(void)
+ 
+ 	if (work_done && (xencons_tty != NULL)) {
+ 		wake_up_interruptible(&xencons_tty->write_wait);
+-		if ((xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+-		    (xencons_tty->ldisc.write_wakeup != NULL))
+-			(xencons_tty->ldisc.write_wakeup)(xencons_tty);
++		tty_wakeup(xencons_tty);
+ 	}
+ }
+ 
+@@ -634,8 +632,8 @@ static void xencons_close(struct tty_str
+ 	tty->closing = 1;
+ 	tty_wait_until_sent(tty, 0);
+ 	tty_driver_flush_buffer(tty);
+-	if (tty->ldisc.flush_buffer != NULL)
+-		tty->ldisc.flush_buffer(tty);
++	if (tty->ldisc.ops->flush_buffer != NULL)
++		tty->ldisc.ops->flush_buffer(tty);
+ 	tty->closing = 0;
+ 	spin_lock_irqsave(&xencons_lock, flags);
+ 	xencons_tty = NULL;
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:51:42.000000000 +0100
+@@ -746,8 +746,9 @@ static struct irq_chip dynirq_chip = {
+ };
+ 
+ /* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
+-static int pirq_eoi_does_unmask;
++static bool pirq_eoi_does_unmask;
+ static unsigned long *pirq_needs_eoi;
++static DECLARE_BITMAP(probing_pirq, NR_PIRQS);
+ 
+ static void pirq_unmask_and_notify(unsigned int evtchn, unsigned int irq)
+ {
+@@ -794,25 +795,31 @@ static inline void pirq_query_unmask(int
+ 		set_bit(irq - PIRQ_BASE, pirq_needs_eoi);
+ }
+ 
+-/*
+- * On startup, if there is no action associated with the IRQ then we are
+- * probing. In this case we should not share with others as it will confuse us.
+- */
+-#define probing_irq(_irq) (irq_desc[(_irq)].action == NULL)
++static int set_type_pirq(unsigned int irq, unsigned int type)
++{
++	if (type != IRQ_TYPE_PROBE)
++		return -EINVAL;
++	set_bit(irq - PIRQ_BASE, probing_pirq);
++	return 0;
++}
+ 
+ static unsigned int startup_pirq(unsigned int irq)
+ {
+ 	struct evtchn_bind_pirq bind_pirq;
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+-	if (VALID_EVTCHN(evtchn))
++	if (VALID_EVTCHN(evtchn)) {
++		clear_bit(irq - PIRQ_BASE, probing_pirq);
+ 		goto out;
++	}
+ 
+ 	bind_pirq.pirq = evtchn_get_xen_pirq(irq);
+ 	/* NB. We are happy to share unless we are probing. */
+-	bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
++	bind_pirq.flags = test_and_clear_bit(irq - PIRQ_BASE, probing_pirq)
++			  || (irq_desc[irq].status & IRQ_AUTODETECT)
++			  ? 0 : BIND_PIRQ__WILL_SHARE;
+ 	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+-		if (!probing_irq(irq))
++		if (bind_pirq.flags)
+ 			printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
+ 			       irq);
+ 		return 0;
+@@ -891,6 +898,7 @@ static struct irq_chip pirq_chip = {
+ 	.mask_ack = ack_pirq,
+ 	.ack      = ack_pirq,
+ 	.end      = end_pirq,
++	.set_type = set_type_pirq,
+ #ifdef CONFIG_SMP
+ 	.set_affinity = set_affinity_irq,
+ #endif
+@@ -1003,6 +1011,7 @@ void xen_poll_irq(int irq)
+ 		BUG();
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
+ static void restore_cpu_virqs(unsigned int cpu)
+ {
+ 	struct evtchn_bind_virq bind_virq;
+@@ -1095,6 +1104,7 @@ void irq_resume(void)
+ 	}
+ 
+ }
++#endif
+ 
+ #if defined(CONFIG_X86_IO_APIC)
+ #define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
+@@ -1177,7 +1187,7 @@ void __init xen_init_IRQ(void)
+ 		* BITS_TO_LONGS(ALIGN(NR_PIRQS, PAGE_SIZE * 8)));
+  	eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
+ 	if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
+-		pirq_eoi_does_unmask = 1;
++		pirq_eoi_does_unmask = true;
+ 
+ 	/* No event channels are 'live' right now. */
+ 	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+--- head-2010-01-18.orig/drivers/xen/core/gnttab.c	2009-12-15 09:20:45.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/gnttab.c	2009-12-15 09:24:56.000000000 +0100
+@@ -449,6 +449,7 @@ static int map_pte_fn(pte_t *pte, struct
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
+ static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
+ 			unsigned long addr, void *data)
+ {
+@@ -456,6 +457,7 @@ static int unmap_pte_fn(pte_t *pte, stru
+ 	set_pte_at(&init_mm, addr, pte, __pte(0));
+ 	return 0;
+ }
++#endif
+ 
+ void *arch_gnttab_alloc_shared(unsigned long *frames)
+ {
+@@ -636,6 +638,75 @@ void __gnttab_dma_map_page(struct page *
+ 	} while (unlikely(read_seqretry(&gnttab_dma_lock, seq)));
+ }
+ 
++#ifdef __HAVE_ARCH_PTE_SPECIAL
++
++static unsigned int GNTMAP_pte_special;
++
++bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *map,
++			   unsigned int count)
++{
++	unsigned int i;
++
++	if (unlikely(cmd != GNTTABOP_map_grant_ref))
++		count = 0;
++
++	for (i = 0; i < count; ++i, ++map) {
++		if (!(map->flags & GNTMAP_host_map)
++		    || !(map->flags & GNTMAP_application_map))
++			continue;
++		if (GNTMAP_pte_special)
++			map->flags |= GNTMAP_pte_special;
++		else {
++			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++			return true;
++		}
++	}
++
++	return false;
++}
++EXPORT_SYMBOL(gnttab_pre_map_adjust);
++
++#if CONFIG_XEN_COMPAT < 0x030400
++int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *map, unsigned int count)
++{
++	unsigned int i;
++	int rc = 0;
++
++	for (i = 0; i < count && rc == 0; ++i, ++map) {
++		pte_t pte;
++
++		if (!(map->flags & GNTMAP_host_map)
++		    || !(map->flags & GNTMAP_application_map))
++			continue;
++
++#ifdef CONFIG_X86
++		pte = __pte_ma((map->dev_bus_addr | _PAGE_PRESENT | _PAGE_USER
++				| _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NX
++				| _PAGE_SPECIAL)
++			       & __supported_pte_mask);
++#else
++#error Architecture not yet supported.
++#endif
++		if (!(map->flags & GNTMAP_readonly))
++			pte = pte_mkwrite(pte);
++
++		if (map->flags & GNTMAP_contains_pte) {
++			mmu_update_t u;
++
++			u.ptr = map->host_addr;
++			u.val = __pte_val(pte);
++			rc = HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF);
++		} else
++			rc = HYPERVISOR_update_va_mapping(map->host_addr, pte, 0);
++	}
++
++	return rc;
++}
++EXPORT_SYMBOL(gnttab_post_map_adjust);
++#endif
++
++#endif /* __HAVE_ARCH_PTE_SPECIAL */
++
+ int gnttab_resume(void)
+ {
+ 	if (max_nr_grant_frames() < nr_grant_frames)
+@@ -643,6 +714,7 @@ int gnttab_resume(void)
+ 	return gnttab_map(0, nr_grant_frames - 1);
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
+ int gnttab_suspend(void)
+ {
+ #ifdef CONFIG_X86
+@@ -652,6 +724,7 @@ int gnttab_suspend(void)
+ #endif
+ 	return 0;
+ }
++#endif
+ 
+ #else /* !CONFIG_XEN */
+ 
+@@ -762,6 +835,18 @@ int __devinit gnttab_init(void)
+ 	gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
+ 	gnttab_free_head  = NR_RESERVED_ENTRIES;
+ 
++#if defined(CONFIG_XEN) && defined(__HAVE_ARCH_PTE_SPECIAL)
++	if (!xen_feature(XENFEAT_auto_translated_physmap)
++	    && xen_feature(XENFEAT_gnttab_map_avail_bits)) {
++#ifdef CONFIG_X86
++		GNTMAP_pte_special = (__pte_val(pte_mkspecial(__pte_ma(0)))
++				      >> _PAGE_BIT_UNUSED1) << _GNTMAP_guest_avail0;
++#else
++#error Architecture not yet supported.
++#endif
++	}
++#endif
++
+ 	return 0;
+ 
+  ini_nomem:
+--- head-2010-01-18.orig/drivers/xen/core/machine_kexec.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/machine_kexec.c	2009-11-06 10:51:42.000000000 +0100
+@@ -57,8 +57,7 @@ void __init xen_machine_kexec_setup_reso
+ 
+ 	/* allocate xen_phys_cpus */
+ 
+-	xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
+-	BUG_ON(xen_phys_cpus == NULL);
++	xen_phys_cpus = alloc_bootmem(k * sizeof(struct resource));
+ 
+ 	/* fill in xen_phys_cpus with per-cpu crash note information */
+ 
+@@ -91,7 +90,7 @@ void __init xen_machine_kexec_setup_reso
+ 	xen_hypervisor_res.start = range.start;
+ 	xen_hypervisor_res.end = range.start + range.size - 1;
+ 	xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+-#ifdef CONFIG_X86_64
++#ifdef CONFIG_X86
+ 	insert_resource(&iomem_resource, &xen_hypervisor_res);
+ #endif
+ 
+@@ -106,7 +105,7 @@ void __init xen_machine_kexec_setup_reso
+ 	if (range.size) {
+ 		crashk_res.start = range.start;
+ 		crashk_res.end = range.start + range.size - 1;
+-#ifdef CONFIG_X86_64
++#ifdef CONFIG_X86
+ 		insert_resource(&iomem_resource, &crashk_res);
+ #endif
+ 	}
+@@ -141,15 +140,13 @@ void __init xen_machine_kexec_setup_reso
+ 					  xen_max_nr_phys_cpus))
+ 		goto err;
+ 
+-#ifdef CONFIG_X86_64
++#ifdef CONFIG_X86
+ 	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
+ 		res = xen_phys_cpus + k;
+ 		if (!res->parent) /* outside of xen_hypervisor_res range */
+ 			insert_resource(&iomem_resource, res);
+ 	}
+-#endif
+ 
+-#ifdef CONFIG_X86
+ 	if (xen_create_contiguous_region((unsigned long)&vmcoreinfo_note,
+ 					 get_order(sizeof(vmcoreinfo_note)),
+ 					 BITS_PER_LONG))
+@@ -168,7 +165,7 @@ void __init xen_machine_kexec_setup_reso
+ 	return;
+ }
+ 
+-#ifndef CONFIG_X86_64
++#ifndef CONFIG_X86
+ void __init xen_machine_kexec_register_resources(struct resource *res)
+ {
+ 	int k;
+--- head-2010-01-18.orig/drivers/xen/core/machine_reboot.c	2009-11-23 10:38:09.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/machine_reboot.c	2009-11-23 10:40:43.000000000 +0100
+@@ -57,6 +57,7 @@ EXPORT_SYMBOL(machine_restart);
+ EXPORT_SYMBOL(machine_halt);
+ EXPORT_SYMBOL(machine_power_off);
+ 
++#ifdef CONFIG_PM_SLEEP
+ static void pre_suspend(void)
+ {
+ 	HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+@@ -113,6 +114,7 @@ static void post_suspend(int suspend_can
+ 	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ 		virt_to_mfn(pfn_to_mfn_frame_list_list);
+ }
++#endif
+ 
+ #else /* !(defined(__i386__) || defined(__x86_64__)) */
+ 
+@@ -131,6 +133,7 @@ static void post_suspend(int suspend_can
+ 
+ #endif
+ 
++#ifdef CONFIG_PM_SLEEP
+ struct suspend {
+ 	int fast_suspend;
+ 	void (*resume_notifier)(int);
+@@ -224,7 +227,8 @@ int __xen_suspend(int fast_suspend, void
+ 
+ 	if (fast_suspend) {
+ 		xenbus_suspend();
+-		err = stop_machine_run(take_machine_down, &suspend, 0);
++		err = stop_machine(take_machine_down, &suspend,
++				   &cpumask_of_cpu(0));
+ 		if (err < 0)
+ 			xenbus_suspend_cancel();
+ 	} else {
+@@ -247,3 +251,4 @@ int __xen_suspend(int fast_suspend, void
+ 
+ 	return 0;
+ }
++#endif
+--- head-2010-01-18.orig/drivers/xen/core/reboot.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/reboot.c	2009-11-06 10:51:42.000000000 +0100
+@@ -29,17 +29,12 @@ MODULE_LICENSE("Dual BSD/GPL");
+ /* 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(struct work_struct *unused);
+ static DECLARE_DELAYED_WORK(shutdown_work, __shutdown_handler);
+ 
+-static int setup_suspend_evtchn(void);
+-
+ int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
+ 
+ static int shutdown_process(void *__unused)
+@@ -69,6 +64,13 @@ static int shutdown_process(void *__unus
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
++
++static int setup_suspend_evtchn(void);
++
++/* Was last suspend request cancelled? */
++static int suspend_cancelled;
++
+ static void xen_resume_notifier(int _suspend_cancelled)
+ {
+ 	int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
+@@ -118,6 +120,10 @@ static int xen_suspend(void *__unused)
+ 	return 0;
+ }
+ 
++#else
++# define xen_suspend NULL
++#endif
++
+ static void switch_shutdown_state(int new_state)
+ {
+ 	int prev_state, old_state = SHUTDOWN_INVALID;
+@@ -194,8 +200,10 @@ static void shutdown_handler(struct xenb
+ 		new_state = SHUTDOWN_POWEROFF;
+ 	else if (strcmp(str, "reboot") == 0)
+ 		ctrl_alt_del();
++#ifdef CONFIG_PM_SLEEP
+ 	else if (strcmp(str, "suspend") == 0)
+ 		new_state = SHUTDOWN_SUSPEND;
++#endif
+ 	else if (strcmp(str, "halt") == 0)
+ 		new_state = SHUTDOWN_HALT;
+ 	else
+@@ -247,6 +255,7 @@ static struct xenbus_watch sysrq_watch =
+ 	.callback = sysrq_handler
+ };
+ 
++#ifdef CONFIG_PM_SLEEP
+ static irqreturn_t suspend_int(int irq, void* dev_id)
+ {
+ 	switch_shutdown_state(SHUTDOWN_SUSPEND);
+@@ -274,6 +283,9 @@ static int setup_suspend_evtchn(void)
+ 
+ 	return 0;
+ }
++#else
++#define setup_suspend_evtchn() 0
++#endif
+ 
+ static int setup_shutdown_watcher(void)
+ {
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:51:42.000000000 +0100
+@@ -27,6 +27,7 @@
+ 
+ extern irqreturn_t smp_reschedule_interrupt(int, void *);
+ extern irqreturn_t smp_call_function_interrupt(int, void *);
++extern irqreturn_t smp_call_function_single_interrupt(int, void *);
+ 
+ extern int local_setup_timer(unsigned int cpu);
+ extern void local_teardown_timer(unsigned int cpu);
+@@ -50,8 +51,10 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
+ 
+ static DEFINE_PER_CPU(int, resched_irq);
+ static DEFINE_PER_CPU(int, callfunc_irq);
++static DEFINE_PER_CPU(int, call1func_irq);
+ static char resched_name[NR_CPUS][15];
+ static char callfunc_name[NR_CPUS][15];
++static char call1func_name[NR_CPUS][15];
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
+@@ -72,15 +75,13 @@ void __init prefill_possible_map(void)
+ 
+ 	for (i = 0; i < NR_CPUS; i++) {
+ 		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+-		if (rc >= 0)
++		if (rc >= 0) {
+ 			cpu_set(i, cpu_possible_map);
++			nr_cpu_ids = i + 1;
++		}
+ 	}
+ }
+ 
+-void __init smp_alloc_memory(void)
+-{
+-}
+-
+ static inline void
+ set_cpu_sibling_map(unsigned int cpu)
+ {
+@@ -109,7 +110,8 @@ static int __cpuinit xen_smp_intr_init(u
+ {
+ 	int rc;
+ 
+-	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
++	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) =
++		per_cpu(call1func_irq, cpu) = -1;
+ 
+ 	sprintf(resched_name[cpu], "resched%u", cpu);
+ 	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
+@@ -133,6 +135,17 @@ static int __cpuinit xen_smp_intr_init(u
+ 		goto fail;
+ 	per_cpu(callfunc_irq, cpu) = rc;
+ 
++	sprintf(call1func_name[cpu], "call1func%u", cpu);
++	rc = bind_ipi_to_irqhandler(CALL_FUNC_SINGLE_VECTOR,
++				    cpu,
++				    smp_call_function_single_interrupt,
++				    IRQF_DISABLED|IRQF_NOBALANCING,
++				    call1func_name[cpu],
++				    NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(call1func_irq, cpu) = rc;
++
+ 	rc = xen_spinlock_init(cpu);
+ 	if (rc < 0)
+ 		goto fail;
+@@ -147,6 +160,8 @@ static int __cpuinit xen_smp_intr_init(u
+ 		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	if (per_cpu(callfunc_irq, cpu) >= 0)
+ 		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	if (per_cpu(call1func_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+ 	xen_spinlock_cleanup(cpu);
+ 	return rc;
+ }
+@@ -159,6 +174,7 @@ static void __cpuexit xen_smp_intr_exit(
+ 
+ 	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+ 	xen_spinlock_cleanup(cpu);
+ }
+ #endif
+@@ -166,11 +182,7 @@ static void __cpuexit xen_smp_intr_exit(
+ void __cpuinit cpu_bringup(void)
+ {
+ 	cpu_init();
+-#ifdef __i386__
+ 	identify_secondary_cpu(&current_cpu_data);
+-#else
+-	identify_cpu(&current_cpu_data);
+-#endif
+ 	touch_softlockup_watchdog();
+ 	preempt_disable();
+ 	local_irq_enable();
+@@ -250,9 +262,6 @@ void __init smp_prepare_cpus(unsigned in
+ 	struct task_struct *idle;
+ 	int apicid;
+ 	struct vcpu_get_physid cpu_id;
+-#ifdef __x86_64__
+-	struct desc_ptr *gdt_descr;
+-#endif
+ 	void *gdt_addr;
+ 
+ 	apicid = 0;
+@@ -265,7 +274,7 @@ void __init smp_prepare_cpus(unsigned in
+ 
+ 	current_thread_info()->cpu = 0;
+ 
+-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++	for_each_possible_cpu (cpu) {
+ 		cpus_clear(per_cpu(cpu_sibling_map, cpu));
+ 		cpus_clear(per_cpu(cpu_core_map, cpu));
+ 	}
+@@ -292,21 +301,10 @@ void __init smp_prepare_cpus(unsigned in
+ 		if (IS_ERR(idle))
+ 			panic("failed fork for CPU %d", cpu);
+ 
+-#ifdef __x86_64__
+-		gdt_descr = &cpu_gdt_descr[cpu];
+-		gdt_descr->address = get_zeroed_page(GFP_KERNEL);
+-		if (unlikely(!gdt_descr->address)) {
+-			printk(KERN_CRIT "CPU%d failed to allocate GDT\n",
+-			       cpu);
+-			continue;
+-		}
+-		gdt_descr->size = GDT_SIZE;
+-		memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
+-		gdt_addr = (void *)gdt_descr->address;
+-#else
++#ifdef __i386__
+ 		init_gdt(cpu);
+-		gdt_addr = get_cpu_gdt_table(cpu);
+ #endif
++		gdt_addr = get_cpu_gdt_table(cpu);
+ 		make_page_readonly(gdt_addr, XENFEAT_writable_descriptor_tables);
+ 
+ 		apicid = cpu;
+@@ -352,8 +350,8 @@ void __init smp_prepare_boot_cpu(void)
+ {
+ #ifdef __i386__
+ 	init_gdt(smp_processor_id());
+-	switch_to_new_gdt();
+ #endif
++	switch_to_new_gdt();
+ 	prefill_possible_map();
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/spinlock.c	2010-01-18 16:29:40.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/spinlock.c	2010-01-18 16:45:21.000000000 +0100
+@@ -12,6 +12,8 @@
+ #include <linux/module.h>
+ #include <xen/evtchn.h>
+ 
++#ifdef TICKET_SHIFT
++
+ extern irqreturn_t smp_reschedule_interrupt(int, void *);
+ 
+ static DEFINE_PER_CPU(int, spinlock_irq) = -1;
+@@ -73,9 +75,9 @@ int xen_spin_wait(raw_spinlock_t *lock, 
+ 	/* announce we're spinning */
+ 	spinning.ticket = token;
+ 	spinning.lock = lock;
+-	spinning.prev = __get_cpu_var(spinning);
++	spinning.prev = x86_read_percpu(spinning);
+ 	smp_wmb();
+-	__get_cpu_var(spinning) = &spinning;
++	x86_write_percpu(spinning, &spinning);
+ 
+ 	/* clear pending */
+ 	xen_clear_irq_pending(irq);
+@@ -102,7 +104,7 @@ int xen_spin_wait(raw_spinlock_t *lock, 
+ 	kstat_this_cpu.irqs[irq] += !rc;
+ 
+ 	/* announce we're done */
+-	__get_cpu_var(spinning) = spinning.prev;
++	x86_write_percpu(spinning, spinning.prev);
+ 	rm_lock = &__get_cpu_var(spinning_rm_lock);
+ 	raw_local_irq_save(flags);
+ 	__raw_write_lock(rm_lock);
+@@ -116,7 +118,7 @@ unsigned int xen_spin_adjust(raw_spinloc
+ {
+ 	struct spinning *spinning;
+ 
+-	for (spinning = __get_cpu_var(spinning); spinning; spinning = spinning->prev)
++	for (spinning = x86_read_percpu(spinning); spinning; spinning = spinning->prev)
+ 		if (spinning->lock == lock) {
+ 			unsigned int ticket = spinning->ticket;
+ 
+@@ -143,9 +145,9 @@ int xen_spin_wait_flags(raw_spinlock_t *
+ 	/* announce we're spinning */
+ 	spinning.ticket = *ptok >> TICKET_SHIFT;
+ 	spinning.lock = lock;
+-	spinning.prev = __get_cpu_var(spinning);
++	spinning.prev = x86_read_percpu(spinning);
+ 	smp_wmb();
+-	__get_cpu_var(spinning) = &spinning;
++	x86_write_percpu(spinning, &spinning);
+ 
+ 	for (nested = spinning.prev; nested; nested = nested->prev)
+ 		if (nested->lock == lock)
+@@ -184,7 +186,7 @@ int xen_spin_wait_flags(raw_spinlock_t *
+ 		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ 
+ 	/* announce we're done */
+-	__get_cpu_var(spinning) = spinning.prev;
++	x86_write_percpu(spinning, spinning.prev);
+ 	rm_lock = &__get_cpu_var(spinning_rm_lock);
+ 	__raw_write_lock(rm_lock);
+ 	__raw_write_unlock(rm_lock);
+@@ -226,3 +228,5 @@ void xen_spin_kick(raw_spinlock_t *lock,
+ 	}
+ }
+ EXPORT_SYMBOL(xen_spin_kick);
++
++#endif /* TICKET_SHIFT */
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenfb.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-11-06 10:51:42.000000000 +0100
+@@ -18,6 +18,7 @@
+  * frame buffer.
+  */
+ 
++#include <linux/console.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/fb.h>
+@@ -545,6 +546,28 @@ static unsigned long vmalloc_to_mfn(void
+ 	return pfn_to_mfn(vmalloc_to_pfn(address));
+ }
+ 
++static __devinit void
++xenfb_make_preferred_console(void)
++{
++	struct console *c;
++
++	if (console_set_on_cmdline)
++		return;
++
++	acquire_console_sem();
++	for (c = console_drivers; c; c = c->next) {
++		if (!strcmp(c->name, "tty") && c->index == 0)
++			break;
++	}
++	release_console_sem();
++	if (c) {
++		unregister_console(c);
++		c->flags |= CON_CONSDEV;
++		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
++		register_console(c);
++	}
++}
++
+ static int __devinit xenfb_probe(struct xenbus_device *dev,
+ 				 const struct xenbus_device_id *id)
+ {
+@@ -665,6 +688,7 @@ static int __devinit xenfb_probe(struct 
+ 	if (ret < 0)
+ 		goto error;
+ 
++	xenfb_make_preferred_console();
+ 	return 0;
+ 
+  error_nomem:
+@@ -882,4 +906,5 @@ static void __exit xenfb_cleanup(void)
+ module_init(xenfb_init);
+ module_exit(xenfb_cleanup);
+ 
++MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
+ MODULE_LICENSE("GPL");
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:51:42.000000000 +0100
+@@ -350,4 +350,5 @@ static void __exit xenkbd_cleanup(void)
+ module_init(xenkbd_init);
+ module_exit(xenkbd_cleanup);
+ 
++MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
+ MODULE_LICENSE("GPL");
+--- head-2010-01-18.orig/drivers/xen/gntdev/gntdev.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/gntdev/gntdev.c	2009-11-06 10:51:42.000000000 +0100
+@@ -418,7 +418,7 @@ static int __init gntdev_init(void)
+ 	}
+ 
+ 	device = device_create(class, NULL, MKDEV(gntdev_major, 0),
+-			       GNTDEV_NAME);
++			       NULL, GNTDEV_NAME);
+ 	if (IS_ERR(device)) {
+ 		printk(KERN_ERR "Error creating gntdev device in xen_class\n");
+ 		printk(KERN_ERR "gntdev created with major number = %d\n",
+--- head-2010-01-18.orig/drivers/xen/netfront/accel.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/accel.c	2009-11-06 10:51:42.000000000 +0100
+@@ -28,6 +28,7 @@
+  * IN THE SOFTWARE.
+  */
+ 
++#include <linux/version.h>
+ #include <linux/netdevice.h>
+ #include <linux/skbuff.h>
+ #include <linux/list.h>
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:51:42.000000000 +0100
+@@ -640,7 +640,7 @@ static int network_open(struct net_devic
+ 	}
+ 	spin_unlock_bh(&np->rx_lock);
+ 
+-	network_maybe_wake_tx(dev);
++	netif_start_queue(dev);
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel.h	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel.h	2009-11-06 10:51:42.000000000 +0100
+@@ -25,6 +25,7 @@
+ #ifndef NETBACK_ACCEL_H
+ #define NETBACK_ACCEL_H
+ 
++#include <linux/version.h>
+ #include <linux/slab.h>
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel.h	2009-11-06 10:51:42.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <xen/evtchn.h>
+ 
+ #include <linux/kernel.h>
++#include <linux/version.h>
+ #include <linux/list.h>
+ 
+ enum netfront_accel_post_status {
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:42.000000000 +0100
+@@ -150,7 +150,7 @@ int xenbus_watch_pathfmt(struct xenbus_d
+ 	char *path;
+ 
+ 	va_start(ap, pathfmt);
+-	path = kvasprintf(GFP_KERNEL, pathfmt, ap);
++	path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap);
+ 	va_end(ap);
+ 
+ 	if (!path) {
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:51:42.000000000 +0100
+@@ -249,14 +249,11 @@ int xb_init_comms(void)
+ 		intf->rsp_cons = intf->rsp_prod;
+ 	}
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	if (xenbus_irq)
+ 		unbind_from_irqhandler(xenbus_irq, &xb_waitq);
+ 
+-#if defined(CONFIG_XEN) || defined(MODULE)
+ 	err = bind_caller_port_to_irqhandler(
+-#else
+-	err = bind_evtchn_to_irqhandler(
+-#endif
+ 		xen_store_evtchn, wake_waiting,
+ 		0, "xenbus", &xb_waitq);
+ 	if (err <= 0) {
+@@ -265,6 +262,20 @@ int xb_init_comms(void)
+ 	}
+ 
+ 	xenbus_irq = err;
++#else
++	if (xenbus_irq) {
++		/* Already have an irq; assume we're resuming */
++		rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
++	} else {
++		err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
++						0, "xenbus", &xb_waitq);
++		if (err <= 0) {
++			printk(KERN_ERR "XENBUS request irq failed %i\n", err);
++			return err;
++		}
++		xenbus_irq = err;
++	}
++#endif
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2010-01-04 12:39:22.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:51:42.000000000 +0100
+@@ -36,6 +36,7 @@
+ 		 __FUNCTION__, __LINE__, ##args)
+ 
+ #include <linux/kernel.h>
++#include <linux/version.h>
+ #include <linux/err.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+--- head-2010-01-18.orig/fs/aio.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/fs/aio.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1297,7 +1297,7 @@ static int make_aio_fd(struct kioctx *io
+ 	int fd;
+ 	struct file *file;
+ 
+-	fd = anon_inode_getfd("[aioq]", &aioq_fops, ioctx);
++	fd = anon_inode_getfd("[aioq]", &aioq_fops, ioctx, 0);
+ 	if (fd < 0)
+ 		return fd;
+ 
+--- head-2010-01-18.orig/include/Kbuild	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/include/Kbuild	2009-12-18 10:50:15.000000000 +0100
+@@ -8,5 +8,6 @@ header-y += mtd/
+ header-y += rdma/
+ header-y += video/
+ header-y += drm/
++header-y += xen/public/
+ header-y += xen/
+ header-y += scsi/
+--- head-2010-01-18.orig/include/asm-generic/pgtable.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/include/asm-generic/pgtable.h	2009-11-06 10:51:42.000000000 +0100
+@@ -99,10 +99,6 @@ static inline void ptep_set_wrprotect(st
+ }
+ #endif
+ 
+-#ifndef arch_change_pte_range
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) 0
+-#endif
+-
+ #ifndef __HAVE_ARCH_PTE_SAME
+ #define pte_same(A,B)	(pte_val(A) == pte_val(B))
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/asm/kexec.h	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/kexec.h	2009-11-06 10:51:42.000000000 +0100
+@@ -5,8 +5,21 @@
+ # define PA_CONTROL_PAGE	0
+ # define VA_CONTROL_PAGE	1
+ # define PA_PGD			2
++# ifndef CONFIG_XEN
+ # define PA_SWAP_PAGE		3
+ # define PAGES_NR		4
++# else /* CONFIG_XEN */
++/*
++ * The hypervisor interface implicitly requires that all entries (except
++ * for possibly the final one) are arranged in matching PA_/VA_ pairs.
++ */
++#  define PA_PMD_0		8
++#  define VA_PMD_0		9
++#  define PA_PMD_1		10
++#  define VA_PMD_1		11
++#  define PA_SWAP_PAGE		12
++#  define PAGES_NR		13
++# endif /* CONFIG_XEN */
+ #else
+ # define PA_CONTROL_PAGE	0
+ # define VA_CONTROL_PAGE	1
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:42.000000000 +0100
+@@ -31,11 +31,17 @@ extern struct desc_ptr idt_descr;
+ extern gate_desc idt_table[];
+ #endif
+ 
++struct gdt_page {
++	struct desc_struct gdt[GDT_ENTRIES];
++} __attribute__((aligned(PAGE_SIZE)));
++DECLARE_PER_CPU(struct gdt_page, gdt_page);
++
++static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
++{
++	return per_cpu(gdt_page, cpu).gdt;
++}
++
+ #ifdef CONFIG_X86_64
+-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+-extern struct desc_ptr cpu_gdt_descr[];
+-/* the cpu gdt accessor */
+-#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+ 
+ static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+ 			     unsigned dpl, unsigned ist, unsigned seg)
+@@ -53,16 +59,6 @@ static inline void pack_gate(gate_desc *
+ }
+ 
+ #else
+-struct gdt_page {
+-	struct desc_struct gdt[GDT_ENTRIES];
+-} __attribute__((aligned(PAGE_SIZE)));
+-DECLARE_PER_CPU(struct gdt_page, gdt_page);
+-
+-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+-{
+-	return per_cpu(gdt_page, cpu).gdt;
+-}
+-
+ static inline void pack_gate(gate_desc *gate, unsigned char type,
+ 			     unsigned long base, unsigned dpl, unsigned flags,
+ 			     unsigned short seg)
+@@ -333,6 +329,28 @@ static inline void set_intr_gate(unsigne
+ 	_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+ }
+ 
++#define SYS_VECTOR_FREE		0
++#define SYS_VECTOR_ALLOCED	1
++
++extern int first_system_vector;
++extern char system_vectors[];
++
++static inline void alloc_system_vector(int vector)
++{
++	if (system_vectors[vector] == SYS_VECTOR_FREE) {
++		system_vectors[vector] = SYS_VECTOR_ALLOCED;
++		if (first_system_vector > vector)
++			first_system_vector = vector;
++	} else
++		BUG();
++}
++
++static inline void alloc_intr_gate(unsigned int n, void *addr)
++{
++	alloc_system_vector(n);
++	set_intr_gate(n, addr);
++}
++
+ /*
+  * This routine sets up an interrupt gate at directory privilege level 3.
+  */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:42.000000000 +0100
+@@ -7,7 +7,58 @@
+ # include "fixmap_64.h"
+ #endif
+ 
++extern int fixmaps_set;
++
++void xen_set_fixmap(enum fixed_addresses, maddr_t, pgprot_t);
++
++static inline void __set_fixmap(enum fixed_addresses idx,
++				maddr_t phys, pgprot_t flags)
++{
++	xen_set_fixmap(idx, phys, flags);
++}
++
++#define set_fixmap(idx, phys)				\
++	__set_fixmap(idx, phys, PAGE_KERNEL)
++
++/*
++ * Some hardware wants to get fixmapped without caching.
++ */
++#define set_fixmap_nocache(idx, phys)			\
++	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++
+ #define clear_fixmap(idx)			\
+ 	__set_fixmap(idx, 0, __pgprot(0))
+ 
++#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
++#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
++
++extern void __this_fixmap_does_not_exist(void);
++
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without translation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++static __always_inline unsigned long fix_to_virt(const unsigned int idx)
++{
++	/*
++	 * this branch gets completely eliminated after inlining,
++	 * except when someone tries to use fixaddr indices in an
++	 * illegal way. (such as mixing up address types or using
++	 * out-of-range indices).
++	 *
++	 * If it doesn't get removed, the linker will complain
++	 * loudly with a reasonably clear error message..
++	 */
++	if (idx >= __end_of_fixed_addresses)
++		__this_fixmap_does_not_exist();
++
++	return __fix_to_virt(idx);
++}
++
++static inline unsigned long virt_to_fix(const unsigned long vaddr)
++{
++	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
++	return __virt_to_fix(vaddr);
++}
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:42.000000000 +0100
+@@ -58,10 +58,17 @@ enum fixed_addresses {
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+-#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_IO_APIC
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+ #endif
++#else
++	FIX_SHARED_INFO,
++#define NR_FIX_ISAMAPS	256
++	FIX_ISAMAP_END,
++	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
++#endif
+ #ifdef CONFIG_X86_VISWS_APIC
+ 	FIX_CO_CPU,	/* Cobalt timer */
+ 	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
+@@ -78,51 +85,38 @@ enum fixed_addresses {
+ 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+ 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ #endif
+-#ifdef CONFIG_ACPI
+-	FIX_ACPI_BEGIN,
+-	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+-#endif
+ #ifdef CONFIG_PCI_MMCONFIG
+ 	FIX_PCIE_MCFG,
+ #endif
+ #ifdef CONFIG_PARAVIRT
+ 	FIX_PARAVIRT_BOOTMAP,
+ #endif
+-	FIX_SHARED_INFO,
+-#define NR_FIX_ISAMAPS	256
+-	FIX_ISAMAP_END,
+-	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ 	__end_of_permanent_fixed_addresses,
+ 	/*
+ 	 * 256 temporary boot-time mappings, used by early_ioremap(),
+ 	 * before ioremap() is functional.
+ 	 *
+-	 * We round it up to the next 512 pages boundary so that we
++	 * We round it up to the next 256 pages boundary so that we
+ 	 * can have a single pgd entry and a single pte table:
+ 	 */
+ #define NR_FIX_BTMAPS		64
+ #define FIX_BTMAPS_NESTING	4
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+-			(__end_of_permanent_fixed_addresses & 511),
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
++			(__end_of_permanent_fixed_addresses & 255),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+ 	FIX_WP_TEST,
++#ifdef CONFIG_ACPI
++	FIX_ACPI_BEGIN,
++	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
++#endif
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+ 	FIX_OHCI1394_BASE,
+ #endif
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void __set_fixmap(enum fixed_addresses idx,
+-			 maddr_t phys, pgprot_t flags);
+ extern void reserve_top_address(unsigned long reserve);
+ 
+-#define set_fixmap(idx, phys)				\
+-	__set_fixmap(idx, phys, PAGE_KERNEL)
+-/*
+- * Some hardware wants to get fixmapped without caching.
+- */
+-#define set_fixmap_nocache(idx, phys)			\
+-	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+ 
+ #define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+ 
+@@ -131,38 +125,5 @@ extern void reserve_top_address(unsigned
+ #define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
+ #define FIXADDR_BOOT_START	(FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
+ 
+-#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+-#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+-
+-extern void __this_fixmap_does_not_exist(void);
+-
+-/*
+- * 'index to address' translation. If anyone tries to use the idx
+- * directly without tranlation, we catch the bug with a NULL-deference
+- * kernel oops. Illegal ranges of incoming indices are caught too.
+- */
+-static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+-{
+-	/*
+-	 * this branch gets completely eliminated after inlining,
+-	 * except when someone tries to use fixaddr indices in an
+-	 * illegal way. (such as mixing up address types or using
+-	 * out-of-range indices).
+-	 *
+-	 * If it doesn't get removed, the linker will complain
+-	 * loudly with a reasonably clear error message..
+-	 */
+-	if (idx >= __end_of_fixed_addresses)
+-		__this_fixmap_does_not_exist();
+-
+-	return __fix_to_virt(idx);
+-}
+-
+-static inline unsigned long virt_to_fix(const unsigned long vaddr)
+-{
+-	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+-	return __virt_to_fix(vaddr);
+-}
+-
+ #endif /* !__ASSEMBLY__ */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:42.000000000 +0100
+@@ -12,6 +12,7 @@
+ #define _ASM_FIXMAP_64_H
+ 
+ #include <linux/kernel.h>
++#include <asm/acpi.h>
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+ #include <asm/vsyscall.h>
+@@ -40,7 +41,6 @@ enum fixed_addresses {
+ 	VSYSCALL_HPET,
+ 	FIX_DBGP_BASE,
+ 	FIX_EARLYCON_MEM_BASE,
+-	FIX_HPET_BASE,
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+@@ -53,14 +53,21 @@ enum fixed_addresses {
+ 	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
+ 				  + MAX_EFI_IO_PAGES - 1,
+ #endif
++#ifdef CONFIG_PARAVIRT
++	FIX_PARAVIRT_BOOTMAP,
++#else
++	FIX_SHARED_INFO,
++#endif
+ #ifdef CONFIG_ACPI
+ 	FIX_ACPI_BEGIN,
+ 	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+ #endif
+-	FIX_SHARED_INFO,
+ #define NR_FIX_ISAMAPS	256
+ 	FIX_ISAMAP_END,
+ 	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
+ 	__end_of_permanent_fixed_addresses,
+ 	/*
+ 	 * 256 temporary boot-time mappings, used by early_ioremap(),
+@@ -71,27 +78,12 @@ enum fixed_addresses {
+ 	 */
+ #define NR_FIX_BTMAPS		64
+ #define FIX_BTMAPS_NESTING	4
+-	FIX_BTMAP_END =
+-		__end_of_permanent_fixed_addresses + 512 -
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+ 			(__end_of_permanent_fixed_addresses & 511),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	FIX_OHCI1394_BASE,
+-#endif
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void __set_fixmap(enum fixed_addresses idx,
+-			 unsigned long phys, pgprot_t flags);
+-
+-#define set_fixmap(idx, phys)			\
+-	__set_fixmap(idx, phys, PAGE_KERNEL)
+-/*
+- * Some hardware wants to get fixmapped without caching.
+- */
+-#define set_fixmap_nocache(idx, phys)			\
+-	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+-
+ #define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
+ #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+ #define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+@@ -100,30 +92,4 @@ extern void __set_fixmap(enum fixed_addr
+ #define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
+ #define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+ 
+-#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+-
+-extern void __this_fixmap_does_not_exist(void);
+-
+-/*
+- * 'index to address' translation. If anyone tries to use the idx
+- * directly without translation, we catch the bug with a NULL-deference
+- * kernel oops. Illegal ranges of incoming indices are caught too.
+- */
+-static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+-{
+-	/*
+-	 * this branch gets completely eliminated after inlining,
+-	 * except when someone tries to use fixaddr indices in an
+-	 * illegal way. (such as mixing up address types or using
+-	 * out-of-range indices).
+-	 *
+-	 * If it doesn't get removed, the linker will complain
+-	 * loudly with a reasonably clear error message..
+-	 */
+-	if (idx >= __end_of_fixed_addresses)
+-		__this_fixmap_does_not_exist();
+-
+-	return __fix_to_virt(idx);
+-}
+-
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:42.000000000 +0100
+@@ -74,6 +74,9 @@ struct page *kmap_atomic_to_page(void *p
+ 
+ #define flush_cache_kmaps()	do { } while (0)
+ 
++extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn,
++					unsigned long end_pfn);
++
+ void clear_highpage(struct page *);
+ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypercall.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall.h	2009-11-06 10:51:42.000000000 +0100
+@@ -332,9 +332,19 @@ static inline int __must_check
+ HYPERVISOR_grant_table_op(
+ 	unsigned int cmd, void *uop, unsigned int count)
+ {
++	bool fixup = false;
++	int rc;
++
+ 	if (arch_use_lazy_mmu_mode())
+ 		xen_multicall_flush(false);
+-	return _hypercall3(int, grant_table_op, cmd, uop, count);
++#ifdef GNTTABOP_map_grant_ref
++	if (cmd == GNTTABOP_map_grant_ref)
++#endif
++		fixup = gnttab_pre_map_adjust(cmd, uop, count);
++	rc = _hypercall3(int, grant_table_op, cmd, uop, count);
++	if (rc == 0 && fixup)
++		rc = gnttab_post_map_adjust(uop, count);
++	return rc;
+ }
+ 
+ static inline int __must_check
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:32:34.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:33:49.000000000 +0100
+@@ -35,7 +35,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/platform.h>
+@@ -119,6 +118,8 @@ int xen_create_contiguous_region(
+     unsigned long vstart, unsigned int order, unsigned int address_bits);
+ void xen_destroy_contiguous_region(
+     unsigned long vstart, unsigned int order);
++int early_create_contiguous_region(unsigned long pfn, unsigned int order,
++				   unsigned int address_bits);
+ 
+ struct page;
+ 
+@@ -188,6 +189,29 @@ static inline void xen_multicall_flush(b
+ 
+ #endif /* CONFIG_XEN && !MODULE */
+ 
++#ifdef CONFIG_XEN
++
++struct gnttab_map_grant_ref;
++bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *,
++			   unsigned int count);
++#if CONFIG_XEN_COMPAT < 0x030400
++int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *, unsigned int);
++#else
++static inline int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *m,
++					 unsigned int count)
++{
++	BUG();
++	return -ENOSYS;
++}
++#endif
++
++#else /* !CONFIG_XEN */
++
++#define gnttab_pre_map_adjust(...) false
++#define gnttab_post_map_adjust(...) ({ BUG(); -ENOSYS; })
++
++#endif /* CONFIG_XEN */
++
+ #if defined(CONFIG_X86_64)
+ #define MULTI_UVMFLAGS_INDEX 2
+ #define MULTI_UVMDOMID_INDEX 3
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:42.000000000 +0100
+@@ -3,20 +3,140 @@
+ 
+ #define ARCH_HAS_IOREMAP_WC
+ 
++#include <linux/compiler.h>
++
++/*
++ * early_ioremap() and early_iounmap() are for temporary early boot-time
++ * mappings, before the real ioremap() is functional.
++ * A boot-time mapping is currently limited to at most 16 pages.
++ */
++#ifndef __ASSEMBLY__
++extern void early_ioremap_init(void);
++extern void early_ioremap_clear(void);
++extern void early_ioremap_reset(void);
++extern void *early_ioremap(unsigned long offset, unsigned long size);
++extern void early_iounmap(void *addr, unsigned long size);
++extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
++#endif
++
++#define build_mmio_read(name, size, type, reg, barrier) \
++static inline type name(const volatile void __iomem *addr) \
++{ type ret; asm volatile("mov" size " %1,%0":reg (ret) \
++:"m" (*(volatile type __force *)addr) barrier); return ret; }
++
++#define build_mmio_write(name, size, type, reg, barrier) \
++static inline void name(type val, volatile void __iomem *addr) \
++{ asm volatile("mov" size " %0,%1": :reg (val), \
++"m" (*(volatile type __force *)addr) barrier); }
++
++build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
++build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
++build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
++
++build_mmio_read(__readb, "b", unsigned char, "=q", )
++build_mmio_read(__readw, "w", unsigned short, "=r", )
++build_mmio_read(__readl, "l", unsigned int, "=r", )
++
++build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
++build_mmio_write(writew, "w", unsigned short, "r", :"memory")
++build_mmio_write(writel, "l", unsigned int, "r", :"memory")
++
++build_mmio_write(__writeb, "b", unsigned char, "q", )
++build_mmio_write(__writew, "w", unsigned short, "r", )
++build_mmio_write(__writel, "l", unsigned int, "r", )
++
++#define readb_relaxed(a) __readb(a)
++#define readw_relaxed(a) __readw(a)
++#define readl_relaxed(a) __readl(a)
++#define __raw_readb __readb
++#define __raw_readw __readw
++#define __raw_readl __readl
++
++#define __raw_writeb __writeb
++#define __raw_writew __writew
++#define __raw_writel __writel
++
++#define mmiowb() barrier()
++
++#ifdef CONFIG_X86_64
++build_mmio_read(readq, "q", unsigned long, "=r", :"memory")
++build_mmio_read(__readq, "q", unsigned long, "=r", )
++build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
++build_mmio_write(__writeq, "q", unsigned long, "r", )
++
++#define readq_relaxed(a) __readq(a)
++#define __raw_readq __readq
++#define __raw_writeq writeq
++
++/* Let people know we have them */
++#define readq readq
++#define writeq writeq
++#endif
++
++#define native_io_delay xen_io_delay
++
+ #ifdef CONFIG_X86_32
+-# include "io_32.h"
++# include "../../io_32.h"
+ #else
+-# include "io_64.h"
++# include "../../io_64.h"
++#endif
++
++#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
++
++/* We will be supplying our own /dev/mem implementation */
++#define ARCH_HAS_DEV_MEM
++
++#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
++#undef page_to_phys
++#define page_to_phys(page)	 (phys_to_machine(page_to_pseudophys(page)))
++#define page_to_bus(page)	 (phys_to_machine(page_to_pseudophys(page)))
++
++#define bvec_to_pseudophys(bv)	 (page_to_pseudophys((bv)->bv_page) + \
++				  (unsigned long)(bv)->bv_offset)
++
++#define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
++	(bvec_to_phys(vec1) + (vec1)->bv_len == bvec_to_phys(vec2) \
++	 && bvec_to_pseudophys(vec1) + (vec1)->bv_len \
++	    == bvec_to_pseudophys(vec2))
++
++#undef virt_to_bus
++#undef bus_to_virt
++#define virt_to_bus(_x) phys_to_machine(__pa(_x))
++#define bus_to_virt(_x) __va(machine_to_phys(_x))
++
++#include <asm/fixmap.h>
++
++#undef __ISA_IO_base
++#undef isa_virt_to_bus
++#undef isa_page_to_bus
++#undef isa_bus_to_virt
++#define isa_virt_to_bus(_x) ({ \
++	unsigned long _va_ = (unsigned long)(_x); \
++	_va_ - fix_to_virt(FIX_ISAMAP_BEGIN) < (NR_FIX_ISAMAPS << PAGE_SHIFT) \
++	? _va_ - fix_to_virt(FIX_ISAMAP_BEGIN) \
++	: ({ BUG(); (unsigned long)virt_to_bus(_va_); }); })
++#define isa_bus_to_virt(_x) ((void *)fix_to_virt(FIX_ISAMAP_BEGIN) + (_x))
++
+ #endif
+ 
+ extern void *xlate_dev_mem_ptr(unsigned long phys);
+ extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+ 
+-extern void map_devmem(unsigned long pfn, unsigned long len, pgprot_t);
+-extern void unmap_devmem(unsigned long pfn, unsigned long len, pgprot_t);
+-
+ extern int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
+ 				     unsigned long prot_val);
+ extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
+ 
++/*
++ * early_ioremap() and early_iounmap() are for temporary early boot-time
++ * mappings, before the real ioremap() is functional.
++ * A boot-time mapping is currently limited to at most 16 pages.
++ */
++extern void early_ioremap_init(void);
++extern void early_ioremap_clear(void);
++extern void early_ioremap_reset(void);
++extern void *early_ioremap(unsigned long offset, unsigned long size);
++extern void early_iounmap(void *addr, unsigned long size);
++extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
++
++
+ #endif /* _ASM_X86_IO_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:42.000000000 +0100
+@@ -0,0 +1,52 @@
++#ifndef _ASM_IRQ_VECTORS_H
++#define _ASM_IRQ_VECTORS_H
++
++#ifdef CONFIG_X86_32
++# define SYSCALL_VECTOR		0x80
++#else
++# define IA32_SYSCALL_VECTOR	0x80
++#endif
++
++#define RESCHEDULE_VECTOR	0
++#define CALL_FUNCTION_VECTOR	1
++#define CALL_FUNC_SINGLE_VECTOR 2
++#define SPIN_UNLOCK_VECTOR	3
++#define NR_IPIS			4
++
++/*
++ * The maximum number of vectors supported by i386 processors
++ * is limited to 256. For processors other than i386, NR_VECTORS
++ * should be changed accordingly.
++ */
++#define NR_VECTORS		256
++
++#define	FIRST_VM86_IRQ		3
++#define LAST_VM86_IRQ		15
++#define invalid_vm86_irq(irq)	((irq) < 3 || (irq) > 15)
++
++/*
++ * The flat IRQ space is divided into two regions:
++ *  1. A one-to-one mapping of real physical IRQs. This space is only used
++ *     if we have physical device-access privilege. This region is at the
++ *     start of the IRQ space so that existing device drivers do not need
++ *     to be modified to translate physical IRQ numbers into our IRQ space.
++ *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
++ *     are bound using the provided bind/unbind functions.
++ */
++
++#define PIRQ_BASE		0
++#if defined(NR_CPUS) && defined(MAX_IO_APICS)
++# if NR_CPUS < MAX_IO_APICS
++#  define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
++# else
++#  define NR_PIRQS		(NR_VECTORS + 32 * MAX_IO_APICS)
++# endif
++#endif
++
++#define DYNIRQ_BASE		(PIRQ_BASE + NR_PIRQS)
++#define NR_DYNIRQS		256
++
++#define NR_IRQS			(NR_PIRQS + NR_DYNIRQS)
++#define NR_IRQ_VECTORS		NR_IRQS
++
++#endif /* _ASM_IRQ_VECTORS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:42.000000000 +0100
+@@ -118,7 +118,7 @@ static inline void halt(void)
+ 
+ #ifndef CONFIG_X86_64
+ #define INTERRUPT_RETURN		iret
+-#define ENABLE_INTERRUPTS_SYSCALL_RET __ENABLE_INTERRUPTS		; \
++#define ENABLE_INTERRUPTS_SYSEXIT	__ENABLE_INTERRUPTS		; \
+ sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
+ 	__TEST_PENDING							; \
+ 	jnz  14f	/* process more events if necessary... */	; \
+@@ -177,18 +177,6 @@ static inline void trace_hardirqs_fixup_
+ #else
+ 
+ #ifdef CONFIG_X86_64
+-/*
+- * Currently paravirt can't handle swapgs nicely when we
+- * don't have a stack we can rely on (such as a user space
+- * stack).  So we either find a way around these or just fault
+- * and emulate if a guest tries to call swapgs directly.
+- *
+- * Either way, this is a good way to document that we don't
+- * have a reliable stack. x86_64 only.
+- */
+-#define SWAPGS_UNSAFE_STACK	swapgs
+-#define ARCH_TRACE_IRQS_ON		call trace_hardirqs_on_thunk
+-#define ARCH_TRACE_IRQS_OFF		call trace_hardirqs_off_thunk
+ #define ARCH_LOCKDEP_SYS_EXIT		call lockdep_sys_exit_thunk
+ #define ARCH_LOCKDEP_SYS_EXIT_IRQ	\
+ 	TRACE_IRQS_ON; \
+@@ -200,24 +188,6 @@ static inline void trace_hardirqs_fixup_
+ 	TRACE_IRQS_OFF;
+ 
+ #else
+-#define ARCH_TRACE_IRQS_ON			\
+-	pushl %eax;				\
+-	pushl %ecx;				\
+-	pushl %edx;				\
+-	call trace_hardirqs_on;			\
+-	popl %edx;				\
+-	popl %ecx;				\
+-	popl %eax;
+-
+-#define ARCH_TRACE_IRQS_OFF			\
+-	pushl %eax;				\
+-	pushl %ecx;				\
+-	pushl %edx;				\
+-	call trace_hardirqs_off;		\
+-	popl %edx;				\
+-	popl %ecx;				\
+-	popl %eax;
+-
+ #define ARCH_LOCKDEP_SYS_EXIT			\
+ 	pushl %eax;				\
+ 	pushl %ecx;				\
+@@ -231,8 +201,8 @@ static inline void trace_hardirqs_fixup_
+ #endif
+ 
+ #ifdef CONFIG_TRACE_IRQFLAGS
+-#  define TRACE_IRQS_ON		ARCH_TRACE_IRQS_ON
+-#  define TRACE_IRQS_OFF	ARCH_TRACE_IRQS_OFF
++#  define TRACE_IRQS_ON		call trace_hardirqs_on_thunk;
++#  define TRACE_IRQS_OFF	call trace_hardirqs_off_thunk;
+ #else
+ #  define TRACE_IRQS_ON
+ #  define TRACE_IRQS_OFF
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:42.000000000 +0100
+@@ -1,5 +1,42 @@
++#ifndef __ASM_X86_MMU_CONTEXT_H
++#define __ASM_X86_MMU_CONTEXT_H
++
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++
++void arch_exit_mmap(struct mm_struct *mm);
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
++
++void mm_pin(struct mm_struct *mm);
++void mm_unpin(struct mm_struct *mm);
++void mm_pin_all(void);
++
++static inline void xen_activate_mm(struct mm_struct *prev,
++				   struct mm_struct *next)
++{
++	if (!PagePinned(virt_to_page(next->pgd)))
++		mm_pin(next);
++}
++
++/*
++ * Used for LDT copy/destruction.
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
++void destroy_context(struct mm_struct *mm);
++
+ #ifdef CONFIG_X86_32
+ # include "mmu_context_32.h"
+ #else
+ # include "mmu_context_64.h"
+ #endif
++
++#define activate_mm(prev, next)			\
++do {						\
++	xen_activate_mm(prev, next);		\
++	switch_mm((prev), (next), NULL);	\
++} while (0);
++
++
++#endif /* __ASM_X86_MMU_CONTEXT_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:42.000000000 +0100
+@@ -1,32 +1,6 @@
+ #ifndef __I386_SCHED_H
+ #define __I386_SCHED_H
+ 
+-#include <asm/desc.h>
+-#include <asm/atomic.h>
+-#include <asm/pgalloc.h>
+-#include <asm/tlbflush.h>
+-
+-void arch_exit_mmap(struct mm_struct *mm);
+-void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
+-
+-void mm_pin(struct mm_struct *mm);
+-void mm_unpin(struct mm_struct *mm);
+-void mm_pin_all(void);
+-
+-static inline void xen_activate_mm(struct mm_struct *prev,
+-				   struct mm_struct *next)
+-{
+-	if (!PagePinned(virt_to_page(next->pgd)))
+-		mm_pin(next);
+-}
+-
+-/*
+- * Used for LDT copy/destruction.
+- */
+-int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+-void destroy_context(struct mm_struct *mm);
+-
+-
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+ #if 0 /* XEN: no lazy tlb */
+@@ -107,10 +81,4 @@ static inline void switch_mm(struct mm_s
+ #define deactivate_mm(tsk, mm)			\
+ 	asm("movl %0,%%gs": :"r" (0));
+ 
+-#define activate_mm(prev, next)			\
+-do {						\
+-	xen_activate_mm(prev, next);		\
+-	switch_mm((prev), (next), NULL);	\
+-} while (0)
+-
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:42.000000000 +0100
+@@ -1,23 +1,6 @@
+ #ifndef __X86_64_MMU_CONTEXT_H
+ #define __X86_64_MMU_CONTEXT_H
+ 
+-#include <asm/desc.h>
+-#include <asm/atomic.h>
+-#include <asm/pgalloc.h>
+-#include <asm/page.h>
+-#include <asm/pda.h>
+-#include <asm/pgtable.h>
+-#include <asm/tlbflush.h>
+-
+-void arch_exit_mmap(struct mm_struct *mm);
+-void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
+-
+-/*
+- * possibly do the LDT unload here?
+- */
+-int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+-void destroy_context(struct mm_struct *mm);
+-
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+ #if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+@@ -58,10 +41,6 @@ static inline void __prepare_arch_switch
+ 	}
+ }
+ 
+-extern void mm_pin(struct mm_struct *mm);
+-extern void mm_unpin(struct mm_struct *mm);
+-void mm_pin_all(void);
+-
+ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ 			     struct task_struct *tsk)
+ {
+@@ -124,11 +103,4 @@ do {						\
+ 	asm volatile("movl %0,%%fs"::"r"(0));	\
+ } while (0)
+ 
+-static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+-{
+-	if (!PagePinned(virt_to_page(next->pgd)))
+-		mm_pin(next);
+-	switch_mm(prev, next, NULL);
+-}
+-
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:42.000000000 +0100
+@@ -21,6 +21,8 @@ struct pci_sysdata {
+ #endif
+ };
+ 
++extern int pci_routeirq;
++
+ /* scan a bus after allocating a pci_sysdata for it */
+ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
+ 					    int node);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:42.000000000 +0100
+@@ -7,6 +7,9 @@
+ 
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+ 
++static inline int paravirt_pgd_alloc(struct mm_struct *mm) { return 0; }
++static inline void paravirt_pgd_free(struct mm_struct *mm, pgd_t *pgd) {}
++
+ static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn)	{}
+ static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)	{}
+ static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:42.000000000 +0100
+@@ -13,11 +13,12 @@
+ #define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+ #define _PAGE_BIT_PAT		7	/* on 4KB pages */
+ #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+-#define _PAGE_BIT_IO		9	/* Mapped page is I/O or foreign and
++#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
++#define _PAGE_BIT_UNUSED2	10
++#define _PAGE_BIT_IO		11	/* Mapped page is I/O or foreign and
+ 					 * has no associated page struct. */
+-#define _PAGE_BIT_UNUSED2	10	/* available for programmer */
+-#define _PAGE_BIT_UNUSED3	11
+ #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
++#define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
+ #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+ 
+ /* If _PAGE_BIT_PRESENT is clear, we use these: */
+@@ -28,34 +29,31 @@
+ /* if the user mapped it with PROT_NONE; pte_present gives true */
+ #define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
+ 
+-/*
+- * Note: we use _AC(1, L) instead of _AC(1, UL) so that we get a
+- * sign-extended value on 32-bit with all 1's in the upper word,
+- * which preserves the upper pte values on 64-bit ptes:
+- */
+-#define _PAGE_PRESENT	(_AC(1, L)<<_PAGE_BIT_PRESENT)
+-#define _PAGE_RW	(_AC(1, L)<<_PAGE_BIT_RW)
+-#define _PAGE_USER	(_AC(1, L)<<_PAGE_BIT_USER)
+-#define _PAGE_PWT	(_AC(1, L)<<_PAGE_BIT_PWT)
+-#define _PAGE_PCD	(_AC(1, L)<<_PAGE_BIT_PCD)
+-#define _PAGE_ACCESSED	(_AC(1, L)<<_PAGE_BIT_ACCESSED)
+-#define _PAGE_DIRTY	(_AC(1, L)<<_PAGE_BIT_DIRTY)
+-#define _PAGE_PSE	(_AC(1, L)<<_PAGE_BIT_PSE)	/* 2MB page */
+-#define _PAGE_GLOBAL	(_AC(1, L)<<_PAGE_BIT_GLOBAL)	/* Global TLB entry */
+-#define _PAGE_IO	(_AC(1, L)<<_PAGE_BIT_IO)
+-#define _PAGE_UNUSED2	(_AC(1, L)<<_PAGE_BIT_UNUSED2)
+-#define _PAGE_UNUSED3	(_AC(1, L)<<_PAGE_BIT_UNUSED3)
+-#define _PAGE_PAT	(_AC(1, L)<<_PAGE_BIT_PAT)
+-#define _PAGE_PAT_LARGE (_AC(1, L)<<_PAGE_BIT_PAT_LARGE)
++#define _PAGE_PRESENT	(_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
++#define _PAGE_RW	(_AT(pteval_t, 1) << _PAGE_BIT_RW)
++#define _PAGE_USER	(_AT(pteval_t, 1) << _PAGE_BIT_USER)
++#define _PAGE_PWT	(_AT(pteval_t, 1) << _PAGE_BIT_PWT)
++#define _PAGE_PCD	(_AT(pteval_t, 1) << _PAGE_BIT_PCD)
++#define _PAGE_ACCESSED	(_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED)
++#define _PAGE_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
++#define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
++#define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
++#define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
++#define _PAGE_UNUSED2	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2)
++#define _PAGE_IO	(_AT(pteval_t, 1) << _PAGE_BIT_IO)
++#define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
++#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
++#define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
++#define __HAVE_ARCH_PTE_SPECIAL
+ 
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+-#define _PAGE_NX	(_AC(1, ULL) << _PAGE_BIT_NX)
++#define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
+ #else
+-#define _PAGE_NX	0
++#define _PAGE_NX	(_AT(pteval_t, 0))
+ #endif
+ 
+-#define _PAGE_FILE	(_AC(1, L)<<_PAGE_BIT_FILE)
+-#define _PAGE_PROTNONE	(_AC(1, L)<<_PAGE_BIT_PROTNONE)
++#define _PAGE_FILE	(_AT(pteval_t, 1) << _PAGE_BIT_FILE)
++#define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
+ 
+ #ifndef __ASSEMBLY__
+ #if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
+@@ -71,8 +69,8 @@ extern unsigned int __kernel_page_user;
+ 			 _PAGE_DIRTY | __kernel_page_user)
+ 
+ /* Set of bits not changed in pte_modify */
+-#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_CACHE_MASK | _PAGE_IO |	\
+-			 _PAGE_ACCESSED | _PAGE_DIRTY)
++#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IO |	\
++			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+ 
+ /*
+  * PAT settings are part of the hypervisor interface, which sets the
+@@ -102,19 +100,9 @@ extern unsigned int __kernel_page_user;
+ #define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+ 					 _PAGE_ACCESSED)
+ 
+-#ifdef CONFIG_X86_32
+-#define _PAGE_KERNEL_EXEC \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+-#define _PAGE_KERNEL (_PAGE_KERNEL_EXEC | _PAGE_NX)
+-
+-#ifndef __ASSEMBLY__
+-extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+-#endif	/* __ASSEMBLY__ */
+-#else
+ #define __PAGE_KERNEL_EXEC						\
+ 	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
+ #define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
+-#endif
+ 
+ #define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+ #define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+@@ -125,25 +113,22 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KE
+ #define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+ #define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+ #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+ 
+-/*
+- * We don't support GLOBAL page in xenolinux64
+- */
+-#define MAKE_GLOBAL(x)			__pgprot((x))
+-
+-#define PAGE_KERNEL			MAKE_GLOBAL(__PAGE_KERNEL)
+-#define PAGE_KERNEL_RO			MAKE_GLOBAL(__PAGE_KERNEL_RO)
+-#define PAGE_KERNEL_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
+-#define PAGE_KERNEL_RX			MAKE_GLOBAL(__PAGE_KERNEL_RX)
+-#define PAGE_KERNEL_WC			MAKE_GLOBAL(__PAGE_KERNEL_WC)
+-#define PAGE_KERNEL_NOCACHE		MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+-#define PAGE_KERNEL_UC_MINUS		MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
+-#define PAGE_KERNEL_EXEC_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
+-#define PAGE_KERNEL_LARGE		MAKE_GLOBAL(__PAGE_KERNEL_LARGE)
+-#define PAGE_KERNEL_LARGE_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_LARGE_EXEC)
+-#define PAGE_KERNEL_VSYSCALL		MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL)
+-#define PAGE_KERNEL_VSYSCALL_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL_NOCACHE)
++#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
++#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
++#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_WC			__pgprot(__PAGE_KERNEL_WC)
++#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
++#define PAGE_KERNEL_UC_MINUS		__pgprot(__PAGE_KERNEL_UC_MINUS)
++#define PAGE_KERNEL_EXEC_NOCACHE	__pgprot(__PAGE_KERNEL_EXEC_NOCACHE)
++#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
++#define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
++#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
++#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
++#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+ 
+ /*         xwr */
+ #define __P000	PAGE_NONE
+@@ -182,27 +167,27 @@ extern struct list_head pgd_list;
+  */
+ static inline int pte_dirty(pte_t pte)
+ {
+-	return __pte_val(pte) & _PAGE_DIRTY;
++	return pte_flags(pte) & _PAGE_DIRTY;
+ }
+ 
+ static inline int pte_young(pte_t pte)
+ {
+-	return __pte_val(pte) & _PAGE_ACCESSED;
++	return pte_flags(pte) & _PAGE_ACCESSED;
+ }
+ 
+ static inline int pte_write(pte_t pte)
+ {
+-	return __pte_val(pte) & _PAGE_RW;
++	return pte_flags(pte) & _PAGE_RW;
+ }
+ 
+ static inline int pte_file(pte_t pte)
+ {
+-	return __pte_val(pte) & _PAGE_FILE;
++	return pte_flags(pte) & _PAGE_FILE;
+ }
+ 
+ static inline int pte_huge(pte_t pte)
+ {
+-	return __pte_val(pte) & _PAGE_PSE;
++	return pte_flags(pte) & _PAGE_PSE;
+ }
+ 
+ static inline int pte_global(pte_t pte)
+@@ -212,12 +197,12 @@ static inline int pte_global(pte_t pte)
+ 
+ static inline int pte_exec(pte_t pte)
+ {
+-	return !(__pte_val(pte) & _PAGE_NX);
++	return !(pte_flags(pte) & _PAGE_NX);
+ }
+ 
+ static inline int pte_special(pte_t pte)
+ {
+-	return 0;
++	return pte_flags(pte) & _PAGE_SPECIAL;
+ }
+ 
+ static inline int pmd_large(pmd_t pte)
+@@ -228,22 +213,22 @@ static inline int pmd_large(pmd_t pte)
+ 
+ static inline pte_t pte_mkclean(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_DIRTY);
++	return __pte_ma(__pte_val(pte) & ~_PAGE_DIRTY);
+ }
+ 
+ static inline pte_t pte_mkold(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED);
++	return __pte_ma(__pte_val(pte) & ~_PAGE_ACCESSED);
+ }
+ 
+ static inline pte_t pte_wrprotect(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_RW);
++	return __pte_ma(__pte_val(pte) & ~_PAGE_RW);
+ }
+ 
+ static inline pte_t pte_mkexec(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_NX);
++	return __pte_ma(__pte_val(pte) & ~_PAGE_NX);
+ }
+ 
+ static inline pte_t pte_mkdirty(pte_t pte)
+@@ -268,7 +253,7 @@ static inline pte_t pte_mkhuge(pte_t pte
+ 
+ static inline pte_t pte_clrhuge(pte_t pte)
+ {
+-	return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_PSE);
++	return __pte_ma(__pte_val(pte) & ~_PAGE_PSE);
+ }
+ 
+ static inline pte_t pte_mkglobal(pte_t pte)
+@@ -283,35 +268,46 @@ static inline pte_t pte_clrglobal(pte_t 
+ 
+ static inline pte_t pte_mkspecial(pte_t pte)
+ {
+-	return pte;
++	return __pte_ma(__pte_val(pte) | _PAGE_SPECIAL);
+ }
+ 
+ extern pteval_t __supported_pte_mask;
+ 
+ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+ {
+-	return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) |
+-		      pgprot_val(pgprot)) & __supported_pte_mask);
++	pgprotval_t prot = pgprot_val(pgprot);
++
++	if (prot & _PAGE_PRESENT)
++		prot &= __supported_pte_mask;
++	return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
+ }
+ 
+ static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+ {
+-	return __pte_ma((((phys_addr_t)page_nr << PAGE_SHIFT) |
+-			 pgprot_val(pgprot)) & __supported_pte_mask);
++	pgprotval_t prot = pgprot_val(pgprot);
++
++	if (prot & _PAGE_PRESENT)
++		prot &= __supported_pte_mask;
++	return __pte_ma(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
+ }
+ 
+ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+ {
+-	return __pmd((((phys_addr_t)page_nr << PAGE_SHIFT) |
+-		      pgprot_val(pgprot)) & __supported_pte_mask);
++	pgprotval_t prot = pgprot_val(pgprot);
++
++	if (prot & _PAGE_PRESENT)
++		prot &= __supported_pte_mask;
++	return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
+ }
+ 
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+-	pteval_t val = pte_val(pte);
++	pgprotval_t prot = pgprot_val(newprot);
++	pteval_t val = pte_val(pte) & _PAGE_CHG_MASK;
+ 
+-	val &= _PAGE_CHG_MASK;
+-	val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask;
++	if (prot & _PAGE_PRESENT)
++		prot &= __supported_pte_mask;
++	val |= prot & ~_PAGE_CHG_MASK;
+ 
+ 	return __pte(val);
+ }
+@@ -325,9 +321,11 @@ static inline pgprot_t pgprot_modify(pgp
+ 	return __pgprot(preservebits | addbits);
+ }
+ 
+-#define pte_pgprot(x) __pgprot(__pte_val(x) & ~PTE_MASK)
++#define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
+ 
+-#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
++#define canon_pgprot(p) __pgprot(pgprot_val(p) & _PAGE_PRESENT \
++				 ? pgprot_val(p) & __supported_pte_mask \
++				 : pgprot_val(p))
+ 
+ #ifndef __ASSEMBLY__
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+@@ -338,6 +336,17 @@ int phys_mem_access_prot_allowed(struct 
+                               unsigned long size, pgprot_t *vma_prot);
+ #endif
+ 
++/* Install a pte for a particular vaddr in kernel space. */
++void set_pte_vaddr(unsigned long vaddr, pte_t pte);
++
++#ifndef CONFIG_XEN
++extern void native_pagetable_setup_start(pgd_t *base);
++extern void native_pagetable_setup_done(pgd_t *base);
++#else
++static inline void xen_pagetable_setup_start(pgd_t *base) {}
++static inline void xen_pagetable_setup_done(pgd_t *base) {}
++#endif
++
+ #define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
+ #define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
+ 
+@@ -373,6 +382,26 @@ int phys_mem_access_prot_allowed(struct 
+ # include "pgtable_64.h"
+ #endif
+ 
++/*
++ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
++ *
++ * this macro returns the index of the entry in the pgd page which would
++ * control the given virtual address
++ */
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++
++/*
++ * pgd_offset() returns a (pgd_t *)
++ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
++ */
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
++/*
++ * a shortcut which implies the use of the kernel's pgd, instead
++ * of a process's
++ */
++#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
++
++
+ #define KERNEL_PGD_BOUNDARY	pgd_index(PAGE_OFFSET)
+ #define KERNEL_PGD_PTRS		(PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
+ 
+@@ -383,8 +412,15 @@ enum {
+ 	PG_LEVEL_4K,
+ 	PG_LEVEL_2M,
+ 	PG_LEVEL_1G,
++	PG_LEVEL_NUM
+ };
+ 
++#ifdef CONFIG_PROC_FS
++extern void update_page_count(int level, unsigned long pages);
++#else
++static inline void update_page_count(int level, unsigned long pages) { }
++#endif
++
+ /*
+  * Helper function that returns the kernel pagetable entry controlling
+  * the virtual address 'address'. NULL means no pagetable entry present.
+@@ -441,6 +477,8 @@ static inline void xen_pte_clear(struct 
+  * race with other CPU's that might be updating the dirty
+  * bit at the same time.
+  */
++struct vm_area_struct;
++
+ #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ extern int ptep_set_access_flags(struct vm_area_struct *vma,
+ 				 unsigned long address, pte_t *ptep,
+@@ -523,9 +561,6 @@ static inline void clone_pgd_range(pgd_t
+        memcpy(dst, src, count * sizeof(pgd_t));
+ }
+ 
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
+-	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+-
+ #define arbitrary_virt_to_machine(va)					\
+ ({									\
+ 	unsigned int __lvl;						\
+@@ -548,6 +583,34 @@ struct page *kmap_atomic_to_page(void *)
+ #define ptep_to_machine(ptep)	virt_to_machine(ptep)
+ #endif
+ 
++#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
++static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
++					   pte_t *ptep)
++{
++#if CONFIG_XEN_COMPAT < 0x030300
++	if (unlikely(!xen_feature(XENFEAT_mmu_pt_update_preserve_ad)))
++		return ptep_get_and_clear(mm, addr, ptep);
++#endif
++	return *ptep;
++}
++
++static inline void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
++					   pte_t *ptep, pte_t pte)
++{
++	mmu_update_t u;
++
++#if CONFIG_XEN_COMPAT < 0x030300
++	if (unlikely(!xen_feature(XENFEAT_mmu_pt_update_preserve_ad))) {
++		set_pte_at(mm, addr, ptep, pte);
++		return;
++	}
++#endif
++	u.ptr = ptep_to_machine(ptep) | MMU_PT_UPDATE_PRESERVE_AD;
++	u.val = __pte_val(pte);
++	if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF))
++		BUG();
++}
++
+ #include <asm-generic/pgtable.h>
+ 
+ #include <xen/features.h>
+@@ -576,10 +639,6 @@ int touch_pte_range(struct mm_struct *mm
+                     unsigned long address,
+                     unsigned long size);
+ 
+-int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-		unsigned long addr, unsigned long end, pgprot_t newprot,
+-		int dirty_accountable);
+-
+ #endif	/* __ASSEMBLY__ */
+ 
+ #endif	/* _ASM_X86_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:42.000000000 +0100
+@@ -14,11 +14,11 @@
+ #define pmd_ERROR(e)							\
+ 	printk("%s:%d: bad pmd %p(%016Lx pfn %08Lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pmd_val(e),			\
+-	       (pmd_val(e) & PTE_MASK) >> PAGE_SHIFT)
++	       (pmd_val(e) & PTE_PFN_MASK) >> PAGE_SHIFT)
+ #define pgd_ERROR(e)							\
+ 	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+-	       (pgd_val(e) & PTE_MASK) >> PAGE_SHIFT)
++	       (pgd_val(e) & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
+ static inline int pud_none(pud_t pud)
+ {
+@@ -27,7 +27,7 @@ static inline int pud_none(pud_t pud)
+ }
+ static inline int pud_bad(pud_t pud)
+ {
+-	return (__pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
++	return (__pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+ }
+ 
+ static inline int pud_present(pud_t pud)
+@@ -102,9 +102,9 @@ static inline void pud_clear(pud_t *pudp
+ 		xen_tlb_flush();
+ }
+ 
+-#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_MASK))
++#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_PFN_MASK))
+ 
+-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_MASK))
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK))
+ 
+ 
+ /* Find an entry in the second-level page table.. */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:42.000000000 +0100
+@@ -89,10 +89,10 @@ extern unsigned long pg0[];
+ /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+    can temporarily clear it. */
+ #define pmd_present(x)	(__pmd_val(x))
+-#define pmd_bad(x)	((__pmd_val(x) & (~PTE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
++#define pmd_bad(x)	((__pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
+ #else
+ #define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+-#define pmd_bad(x)	((__pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#define pmd_bad(x)	((__pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+ #endif
+ 
+ 
+@@ -119,26 +119,6 @@ extern unsigned long pg0[];
+  */
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+ 
+-/*
+- * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+- *
+- * this macro returns the index of the entry in the pgd page which would
+- * control the given virtual address
+- */
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+-#define pgd_index_k(addr) pgd_index((addr))
+-
+-/*
+- * pgd_offset() returns a (pgd_t *)
+- * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+- */
+-#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
+-
+-/*
+- * a shortcut which implies the use of the kernel's pgd, instead
+- * of a process's
+- */
+-#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
+ 
+ static inline int pud_large(pud_t pud) { return 0; }
+ 
+@@ -165,7 +145,7 @@ static inline int pud_large(pud_t pud) {
+ #define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+ 
+ #define pmd_page_vaddr(pmd)					\
+-	((unsigned long)__va(pmd_val((pmd)) & PTE_MASK))
++	((unsigned long)__va(pmd_val((pmd)) & PTE_PFN_MASK))
+ 
+ #if defined(CONFIG_HIGHPTE)
+ #define pte_offset_map(dir, address)					\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:42.000000000 +0100
+@@ -23,6 +23,8 @@ extern void xen_init_pt(void);
+ extern pud_t level3_kernel_pgt[512];
+ extern pud_t level3_ident_pgt[512];
+ extern pmd_t level2_kernel_pgt[512];
++extern pmd_t level2_fixmap_pgt[512];
++extern pmd_t level2_ident_pgt[512];
+ extern pgd_t init_level4_pgt[];
+ 
+ #define swapper_pg_dir init_level4_pgt
+@@ -79,6 +81,9 @@ extern void paging_init(void);
+ 
+ struct mm_struct;
+ 
++void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte);
++
++
+ #define __xen_pte_clear(ptep) xen_set_pte(ptep, __pte(0))
+ 
+ static inline void xen_set_pte(pte_t *ptep, pte_t pte)
+@@ -145,7 +150,7 @@ static inline void xen_pgd_clear(pgd_t *
+ #define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+ 
+-#define MAXMEM		 _AC(0x0000006fffffffff, UL)
++#define MAXMEM		 _AC(0x000004ffffffffff, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+ #define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+@@ -157,17 +162,17 @@ static inline void xen_pgd_clear(pgd_t *
+ 
+ static inline int pgd_bad(pgd_t pgd)
+ {
+-	return (__pgd_val(pgd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
++	return (__pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+ static inline int pud_bad(pud_t pud)
+ {
+-	return (__pud_val(pud) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
++	return (__pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+ static inline int pmd_bad(pmd_t pmd)
+ {
+-	return (__pmd_val(pmd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
++	return (__pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+ }
+ 
+ #define pte_none(x)	(!(x).pte)
+@@ -175,7 +180,7 @@ static inline int pmd_bad(pmd_t pmd)
+ 
+ #define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))   /* FIXME: is this right? */
+ 
+-#define __pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
++#define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_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_IO ? max_mapnr :	\
+@@ -200,11 +205,8 @@ static inline int pmd_bad(pmd_t pmd)
+  * Level 4 access.
+  */
+ #define pgd_page_vaddr(pgd)						\
+-	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
++	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK))
+ #define pgd_page(pgd)		(pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
+-#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+-#define pgd_offset(mm, address)	((mm)->pgd + pgd_index((address)))
+-#define pgd_offset_k(address) (init_level4_pgt + pgd_index((address)))
+ #define pgd_present(pgd) (__pgd_val(pgd) & _PAGE_PRESENT)
+ static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
+@@ -226,7 +228,7 @@ static inline int pud_large(pud_t pte)
+ }
+ 
+ /* PMD  - Level 2 access */
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_PFN_MASK))
+ #define pmd_page(pmd)		(pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
+ 
+ #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:42.000000000 +0100
+@@ -134,7 +134,7 @@ extern __u32			cleared_cpu_caps[NCAPINTS
+ #ifdef CONFIG_SMP
+ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+ #define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+-#define current_cpu_data	cpu_data(smp_processor_id())
++#define current_cpu_data	__get_cpu_var(cpu_info)
+ #else
+ #define cpu_data(cpu)		boot_cpu_data
+ #define current_cpu_data	boot_cpu_data
+@@ -153,7 +153,7 @@ static inline int hlt_works(int cpu)
+ 
+ extern void cpu_detect(struct cpuinfo_x86 *c);
+ 
+-extern void identify_cpu(struct cpuinfo_x86 *);
++extern void early_cpu_init(void);
+ extern void identify_boot_cpu(void);
+ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
+@@ -267,15 +267,11 @@ struct tss_struct {
+ 	struct thread_struct	*io_bitmap_owner;
+ 
+ 	/*
+-	 * Pad the TSS to be cacheline-aligned (size is 0x100):
+-	 */
+-	unsigned long		__cacheline_filler[35];
+-	/*
+ 	 * .. and then another 0x100 bytes for the emergency kernel stack:
+ 	 */
+ 	unsigned long		stack[64];
+ 
+-} __attribute__((packed));
++} ____cacheline_aligned;
+ 
+ DECLARE_PER_CPU(struct tss_struct, init_tss);
+ 
+@@ -668,11 +664,36 @@ static inline void __sti_mwait(unsigned 
+ 
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+ 
+-extern int			force_mwait;
+-
+ extern void select_idle_routine(const struct cpuinfo_x86 *c);
+ 
+ extern unsigned long		boot_option_idle_override;
++extern unsigned long		idle_halt;
++extern unsigned long		idle_nomwait;
++
++#ifndef CONFIG_XEN
++/*
++ * on systems with caches, caches must be flashed as the absolute
++ * last instruction before going into a suspended halt.  Otherwise,
++ * dirty data can linger in the cache and become stale on resume,
++ * leading to strange errors.
++ *
++ * perform a variety of operations to guarantee that the compiler
++ * will not reorder instructions.  wbinvd itself is serializing
++ * so the processor will not reorder.
++ *
++ * Systems without cache can just go into halt.
++ */
++static inline void wbinvd_halt(void)
++{
++	mb();
++	/* check for clflush to determine if wbinvd is legal */
++	if (cpu_has_clflush)
++		asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
++	else
++		while (1)
++			halt();
++}
++#endif
+ 
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:13:24.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:24.000000000 +0100
+@@ -25,23 +25,16 @@ extern cpumask_t cpu_initialized;
+ extern void (*mtrr_hook)(void);
+ extern void zap_low_mappings(void);
+ 
++extern int __cpuinit get_local_pda(int cpu);
++
+ extern int smp_num_siblings;
+ extern unsigned int num_processors;
+ extern cpumask_t cpu_initialized;
+ 
+-#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-extern u16 x86_cpu_to_apicid_init[];
+-extern u16 x86_bios_cpu_apicid_init[];
+-extern void *x86_cpu_to_apicid_early_ptr;
+-extern void *x86_bios_cpu_apicid_early_ptr;
+-#else
+-#define x86_cpu_to_apicid_early_ptr NULL
+-#define x86_bios_cpu_apicid_early_ptr NULL
+-#endif
+-
+ DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+ DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+ DECLARE_PER_CPU(u16, cpu_llc_id);
++
+ DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+ DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+ 
+@@ -63,9 +56,9 @@ struct smp_ops {
+ 
+ 	void (*smp_send_stop)(void);
+ 	void (*smp_send_reschedule)(int cpu);
+-	int (*smp_call_function_mask)(cpumask_t mask,
+-				      void (*func)(void *info), void *info,
+-				      int wait);
++
++	void (*send_call_func_ipi)(cpumask_t mask);
++	void (*send_call_func_single_ipi)(int cpu);
+ };
+ 
+ /* Globals due to paravirt */
+@@ -103,11 +96,14 @@ static inline void smp_send_reschedule(i
+ 	smp_ops.smp_send_reschedule(cpu);
+ }
+ 
+-static inline int smp_call_function_mask(cpumask_t mask,
+-					 void (*func) (void *info), void *info,
+-					 int wait)
++static inline void arch_send_call_function_single_ipi(int cpu)
+ {
+-	return smp_ops.smp_call_function_mask(mask, func, info, wait);
++	smp_ops.send_call_func_single_ipi(cpu);
++}
++
++static inline void arch_send_call_function_ipi(cpumask_t mask)
++{
++	smp_ops.send_call_func_ipi(mask);
+ }
+ 
+ void native_smp_prepare_boot_cpu(void);
+@@ -119,23 +115,19 @@ int native_cpu_up(unsigned int cpunum);
+ 
+ void xen_smp_send_stop(void);
+ void xen_smp_send_reschedule(int cpu);
+-int xen_smp_call_function_mask(cpumask_t mask,
+-			       void (*func) (void *info), void *info,
+-			       int wait);
++void xen_send_call_func_ipi(cpumask_t mask);
++void xen_send_call_func_single_ipi(int cpu);
+ 
+ #define smp_send_stop		xen_smp_send_stop
+ #define smp_send_reschedule	xen_smp_send_reschedule
+-#define smp_call_function_mask	xen_smp_call_function_mask
+-
+-extern void prefill_possible_map(void);
++#define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
++#define arch_send_call_function_ipi		xen_send_call_func_ipi
+ 
+ #endif /* CONFIG_XEN */
+ 
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ 
+-extern void prefill_possible_map(void);
+-
+ void smp_store_cpu_info(int id);
+ #define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+ 
+@@ -146,6 +138,14 @@ static inline int num_booting_cpus(void)
+ }
+ #endif /* CONFIG_SMP */
+ 
++#if defined(CONFIG_SMP) && (defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_XEN))
++extern void prefill_possible_map(void);
++#else
++static inline void prefill_possible_map(void)
++{
++}
++#endif
++
+ extern unsigned disabled_cpus __cpuinitdata;
+ 
+ #ifdef CONFIG_X86_32_SMP
+@@ -213,12 +213,8 @@ static inline int hard_smp_processor_id(
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-extern void cpu_exit_clear(void);
+ extern void cpu_uninit(void);
+ #endif
+ 
+-extern void smp_alloc_memory(void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+ #endif /* __ASSEMBLY__ */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 11:33:34.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:21.000000000 +0100
+@@ -38,6 +38,8 @@
+ # define UNLOCK_LOCK_PREFIX
+ #endif
+ 
++#ifdef TICKET_SHIFT
++
+ int xen_spinlock_init(unsigned int cpu);
+ void xen_spinlock_cleanup(unsigned int cpu);
+ int xen_spin_wait(raw_spinlock_t *, unsigned int token);
+@@ -64,14 +66,14 @@ void xen_spin_kick(raw_spinlock_t *, uns
+  * much between them in performance though, especially as locks are out of line.
+  */
+ #if TICKET_SHIFT == 8
+-#define __raw_spin_lock_preamble \
++#define __ticket_spin_lock_preamble \
+ 	asm(LOCK_PREFIX "xaddw %w0, %2\n\t" \
+ 	    "cmpb %h0, %b0\n\t" \
+ 	    "sete %1" \
+ 	    : "=&Q" (token), "=qm" (free), "+m" (lock->slock) \
+ 	    : "0" (0x0100) \
+ 	    : "memory", "cc")
+-#define __raw_spin_lock_body \
++#define __ticket_spin_lock_body \
+ 	asm("1:\t" \
+ 	    "cmpb %h0, %b0\n\t" \
+ 	    "je 2f\n\t" \
+@@ -87,7 +89,7 @@ void xen_spin_kick(raw_spinlock_t *, uns
+ 	    : "memory", "cc")
+ 
+ 
+-static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp, new;
+ 
+@@ -106,7 +108,7 @@ static __always_inline int __raw_spin_tr
+ 	return tmp;
+ }
+ 
+-static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token;
+ 	unsigned char kick;
+@@ -122,7 +124,7 @@ static __always_inline void __raw_spin_u
+ 		xen_spin_kick(lock, token);
+ }
+ #elif TICKET_SHIFT == 16
+-#define __raw_spin_lock_preamble \
++#define __ticket_spin_lock_preamble \
+ 	do { \
+ 		unsigned int tmp; \
+ 		asm(LOCK_PREFIX "xaddl %0, %2\n\t" \
+@@ -134,7 +136,7 @@ static __always_inline void __raw_spin_u
+ 		    : "0" (0x00010000) \
+ 		    : "memory", "cc"); \
+ 	} while (0)
+-#define __raw_spin_lock_body \
++#define __ticket_spin_lock_body \
+ 	do { \
+ 		unsigned int tmp; \
+ 		asm("shldl $16, %0, %2\n" \
+@@ -153,7 +155,7 @@ static __always_inline void __raw_spin_u
+ 		    : "memory", "cc"); \
+ 	} while (0)
+ 
+-static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
++static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
+ {
+ 	int tmp;
+ 	int new;
+@@ -175,7 +177,7 @@ static __always_inline int __raw_spin_tr
+ 	return tmp;
+ }
+ 
+-static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
++static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token, tmp;
+ 	bool kick;
+@@ -193,60 +195,173 @@ static __always_inline void __raw_spin_u
+ }
+ #endif
+ 
+-static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
++static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
+ {
+ 	int tmp = ACCESS_ONCE(lock->slock);
+ 
+ 	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+ }
+ 
+-static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
++static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
+ {
+ 	int tmp = ACCESS_ONCE(lock->slock);
+ 
+ 	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+ }
+ 
+-static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
++static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
+ {
+ 	unsigned int token, count;
+ 	bool free;
+ 
+-	__raw_spin_lock_preamble;
++	__ticket_spin_lock_preamble;
+ 	if (likely(free))
+ 		return;
+ 	token = xen_spin_adjust(lock, token);
+ 	do {
+ 		count = 1 << 10;
+-		__raw_spin_lock_body;
++		__ticket_spin_lock_body;
+ 	} while (unlikely(!count) && !xen_spin_wait(lock, token));
+ }
+ 
+-static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
+-						  unsigned long flags)
++static __always_inline void __ticket_spin_lock_flags(raw_spinlock_t *lock,
++						     unsigned long flags)
+ {
+ 	unsigned int token, count;
+ 	bool free;
+ 
+-	__raw_spin_lock_preamble;
++	__ticket_spin_lock_preamble;
+ 	if (likely(free))
+ 		return;
+ 	token = xen_spin_adjust(lock, token);
+ 	do {
+ 		count = 1 << 10;
+-		__raw_spin_lock_body;
++		__ticket_spin_lock_body;
+ 	} while (unlikely(!count) && !xen_spin_wait_flags(lock, &token, flags));
+ }
+ 
++#undef __ticket_spin_lock_preamble
++#undef __ticket_spin_lock_body
++
++#define __raw_spin(n) __ticket_spin_##n
++
++#else /* TICKET_SHIFT */
++
++static inline int xen_spinlock_init(unsigned int cpu) { return 0; }
++static inline void xen_spinlock_cleanup(unsigned int cpu) {}
++
++/*
++ * Define virtualization-friendly old-style lock byte lock, for use in
++ * pv_lock_ops if desired.
++ *
++ * This differs from the pre-2.6.24 spinlock by always using xchgb
++ * rather than decb to take the lock; this allows it to use a
++ * zero-initialized lock structure.  It also maintains a 1-byte
++ * contention counter, so that we can implement
++ * __byte_spin_is_contended.
++ */
++struct __byte_spinlock {
++	s8 lock;
++#if NR_CPUS < 256
++	s8 spinners;
++#else
++#error NR_CPUS >= 256 support not implemented
++#endif
++};
++
++static inline int __byte_spin_is_locked(raw_spinlock_t *lock)
++{
++	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
++	return bl->lock != 0;
++}
++
++static inline int __byte_spin_is_contended(raw_spinlock_t *lock)
++{
++	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
++	return bl->spinners != 0;
++}
++
++static inline void __byte_spin_lock(raw_spinlock_t *lock)
++{
++	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
++	s8 val = 1;
++
++	asm("1: xchgb %1, %0\n"
++	    "   test %1,%1\n"
++	    "   jz 3f\n"
++	    "   " LOCK_PREFIX "incb %2\n"
++	    "2: rep;nop\n"
++	    "   cmpb $1, %0\n"
++	    "   je 2b\n"
++	    "   " LOCK_PREFIX "decb %2\n"
++	    "   jmp 1b\n"
++	    "3:"
++	    : "+m" (bl->lock), "+q" (val), "+m" (bl->spinners): : "memory");
++}
++
++#define __byte_spin_lock_flags(lock, flags) __byte_spin_lock(lock)
++
++static inline int __byte_spin_trylock(raw_spinlock_t *lock)
++{
++	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
++	u8 old = 1;
++
++	asm("xchgb %1,%0"
++	    : "+m" (bl->lock), "+q" (old) : : "memory");
++
++	return old == 0;
++}
++
++static inline void __byte_spin_unlock(raw_spinlock_t *lock)
++{
++	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
++	smp_wmb();
++	bl->lock = 0;
++}
++
++#define __raw_spin(n) __byte_spin_##n
++
++#endif /* TICKET_SHIFT */
++
++static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
++{
++	return __raw_spin(is_locked)(lock);
++}
++
++static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
++{
++	return __raw_spin(is_contended)(lock);
++}
++
++static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
++{
++	__raw_spin(lock)(lock);
++}
++
++static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
++{
++	return __raw_spin(trylock)(lock);
++}
++
++static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
++{
++	__raw_spin(unlock)(lock);
++}
++
++static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
++						  unsigned long flags)
++{
++	__raw_spin(lock_flags)(lock, flags);
++}
++
++#undef __raw_spin
++
+ static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+ {
+ 	while (__raw_spin_is_locked(lock))
+ 		cpu_relax();
+ }
+ 
+-#undef __raw_spin_lock_preamble
+-#undef __raw_spin_lock_body
+-
+ /*
+  * Read-write spinlocks, allowing multiple readers
+  * but only one writer.
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:22:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:52:08.000000000 +0100
+@@ -9,6 +9,10 @@ typedef union {
+ 	unsigned int slock;
+ 	struct {
+ /*
++ * Xen versions prior to 3.2.x have a race condition with HYPERVISOR_poll().
++ */
++#if CONFIG_XEN_COMPAT >= 0x030200
++/*
+  * On Xen we support a single level of interrupt re-enabling per lock. Hence
+  * we can have twice as many outstanding tickets. Thus the cut-off for using
+  * byte register pairs must be at half the number of CPUs.
+@@ -20,6 +24,7 @@ typedef union {
+ # define TICKET_SHIFT 16
+ 		u16 cur, seq;
+ #endif
++#endif
+ 	};
+ } raw_spinlock_t;
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:42.000000000 +0100
+@@ -137,7 +137,7 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"
+ #define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base))
+ #define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1))
+ 
+-extern void load_gs_index(unsigned);
++extern void xen_load_gs_index(unsigned);
+ 
+ /*
+  * Load a segment. Fall back on loading the zero
+@@ -154,14 +154,14 @@ extern void load_gs_index(unsigned);
+ 		     "jmp 2b\n"			\
+ 		     ".previous\n"		\
+ 		     _ASM_EXTABLE(1b,3b)	\
+-		     : :"r" (value), "r" (0))
++		     : :"r" (value), "r" (0) : "memory")
+ 
+ 
+ /*
+  * Save a segment register away
+  */
+ #define savesegment(seg, value)				\
+-	asm volatile("mov %%" #seg ",%0":"=rm" (value))
++	asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+ 
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+@@ -269,6 +269,7 @@ static inline void xen_wbinvd(void)
+ #ifdef CONFIG_X86_64
+ #define read_cr8()	(xen_read_cr8())
+ #define write_cr8(x)	(xen_write_cr8(x))
++#define load_gs_index   xen_load_gs_index
+ #endif
+ 
+ /* Clear the 'TS' bit */
+@@ -287,13 +288,12 @@ static inline void clflush(volatile void
+ void disable_hlt(void);
+ void enable_hlt(void);
+ 
+-extern int es7000_plat;
+ void cpu_idle_wait(void);
+ 
+ extern unsigned long arch_align_stack(unsigned long sp);
+ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+ 
+-void default_idle(void);
++void xen_idle(void);
+ 
+ /*
+  * Force strict CPU ordering.
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/xor_64.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor_64.h	2009-11-06 10:51:42.000000000 +0100
+@@ -1,3 +1,6 @@
++#ifndef ASM_X86__XOR_64_H
++#define ASM_X86__XOR_64_H
++
+ /*
+  * x86-64 changes / gcc fixes from Andi Kleen.
+  * Copyright 2002 Andi Kleen, SuSE Labs.
+@@ -330,3 +333,5 @@ do {						\
+    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)
++
++#endif /* ASM_X86__XOR_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/irq_vectors.h	2009-11-06 10:51:25.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,126 +0,0 @@
+-/*
+- * This file should contain #defines for all of the interrupt vector
+- * numbers used by this architecture.
+- *
+- * In addition, there are some standard defines:
+- *
+- *	FIRST_EXTERNAL_VECTOR:
+- *		The first free place for external interrupts
+- *
+- *	SYSCALL_VECTOR:
+- *		The IRQ vector a syscall makes the user to kernel transition
+- *		under.
+- *
+- *	TIMER_IRQ:
+- *		The IRQ number the timer interrupt comes in at.
+- *
+- *	NR_IRQS:
+- *		The total number of interrupt vectors (including all the
+- *		architecture specific interrupts) needed.
+- *
+- */			
+-#ifndef _ASM_IRQ_VECTORS_H
+-#define _ASM_IRQ_VECTORS_H
+-
+-/*
+- * IDT vectors usable for external interrupt sources start
+- * at 0x20:
+- */
+-#define FIRST_EXTERNAL_VECTOR	0x20
+-
+-#define SYSCALL_VECTOR		0x80
+-
+-/*
+- * Vectors 0x20-0x2f are used for ISA interrupts.
+- */
+-
+-#if 0
+-/*
+- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
+- *
+- *  some of the following vectors are 'rare', they are merged
+- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+- *  TLB, reschedule and local APIC vectors are performance-critical.
+- *
+- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
+- */
+-#define SPURIOUS_APIC_VECTOR	0xff
+-#define ERROR_APIC_VECTOR	0xfe
+-#define INVALIDATE_TLB_VECTOR	0xfd
+-#define RESCHEDULE_VECTOR	0xfc
+-#define CALL_FUNCTION_VECTOR	0xfb
+-
+-#define THERMAL_APIC_VECTOR	0xf0
+-/*
+- * Local APIC timer IRQ vector is on a different priority level,
+- * to work around the 'lost local interrupt if more than 2 IRQ
+- * sources per level' errata.
+- */
+-#define LOCAL_TIMER_VECTOR	0xef
+-#endif
+-
+-#define SPURIOUS_APIC_VECTOR	0xff
+-#define ERROR_APIC_VECTOR	0xfe
+-
+-/*
+- * First APIC vector available to drivers: (vectors 0x30-0xee)
+- * we start at 0x31 to spread out vectors evenly between priority
+- * levels. (0x80 is the syscall vector)
+- */
+-#define FIRST_DEVICE_VECTOR	0x31
+-#define FIRST_SYSTEM_VECTOR	0xef
+-
+-/*
+- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+- * Right now the APIC is mostly only used for SMP.
+- * 256 vectors is an architectural limit. (we can have
+- * more than 256 devices theoretically, but they will
+- * have to use shared interrupts)
+- * Since vectors 0x00-0x1f are used/reserved for the CPU,
+- * the usable vector space is 0x20-0xff (224 vectors)
+- */
+-
+-#define RESCHEDULE_VECTOR	0
+-#define CALL_FUNCTION_VECTOR	1
+-#define SPIN_UNLOCK_VECTOR	2
+-#define NR_IPIS			3
+-
+-/*
+- * The maximum number of vectors supported by i386 processors
+- * is limited to 256. For processors other than i386, NR_VECTORS
+- * should be changed accordingly.
+- */
+-#define NR_VECTORS 256
+-
+-#define FPU_IRQ			13
+-
+-#define	FIRST_VM86_IRQ		3
+-#define LAST_VM86_IRQ		15
+-#define invalid_vm86_irq(irq)	((irq) < 3 || (irq) > 15)
+-
+-/*
+- * The flat IRQ space is divided into two regions:
+- *  1. A one-to-one mapping of real physical IRQs. This space is only used
+- *     if we have physical device-access privilege. This region is at the 
+- *     start of the IRQ space so that existing device drivers do not need
+- *     to be modified to translate physical IRQ numbers into our IRQ space.
+- *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+- *     are bound using the provided bind/unbind functions.
+- */
+-
+-#define PIRQ_BASE		0
+-#if !defined(MAX_IO_APICS)
+-# define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
+-#elif NR_CPUS < MAX_IO_APICS
+-# define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
+-#else
+-# define NR_PIRQS		(NR_VECTORS + 32 * MAX_IO_APICS)
+-#endif
+-
+-#define DYNIRQ_BASE		(PIRQ_BASE + NR_PIRQS)
+-#define NR_DYNIRQS		256
+-
+-#define NR_IRQS			(NR_PIRQS + NR_DYNIRQS)
+-#define NR_IRQ_VECTORS		NR_IRQS
+-
+-#endif /* _ASM_IRQ_VECTORS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/setup_arch_post.h	2007-06-12 13:14:13.000000000 +0200
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,63 +0,0 @@
+-/**
+- * machine_specific_* - Hooks for machine specific setup.
+- *
+- * Description:
+- *	This is included late in kernel/setup.c so that it can make
+- *	use of all of the static functions.
+- **/
+-
+-#include <xen/interface/callback.h>
+-
+-extern void hypervisor_callback(void);
+-extern void failsafe_callback(void);
+-extern void nmi(void);
+-
+-static void __init machine_specific_arch_setup(void)
+-{
+-	int ret;
+-	static struct callback_register __initdata event = {
+-		.type = CALLBACKTYPE_event,
+-		.address = (unsigned long) hypervisor_callback,
+-	};
+-	static struct callback_register __initdata failsafe = {
+-		.type = CALLBACKTYPE_failsafe,
+-		.address = (unsigned long)failsafe_callback,
+-	};
+-	static struct callback_register __initdata syscall = {
+-		.type = CALLBACKTYPE_syscall,
+-		.address = (unsigned long)system_call,
+-	};
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	static struct callback_register __initdata nmi_cb = {
+-		.type = CALLBACKTYPE_nmi,
+-		.address = (unsigned long)nmi,
+-	};
+-#endif
+-
+-	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+-	if (ret == 0)
+-		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
+-	if (ret == 0)
+-		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (ret == -ENOSYS)
+-		ret = HYPERVISOR_set_callbacks(
+-			event.address,
+-			failsafe.address,
+-			syscall.address);
+-#endif
+-	BUG_ON(ret);
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (ret == -ENOSYS) {
+-		static struct xennmi_callback __initdata cb = {
+-			.handler_address = (unsigned long)nmi
+-		};
+-
+-		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+-	}
+-#endif
+-#endif
+-}
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/setup_arch_pre.h	2007-06-12 13:14:13.000000000 +0200
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,5 +0,0 @@
+-/* Hook to call BIOS initialisation function */
+-
+-#define ARCH_SETUP machine_specific_arch_setup();
+-
+-static void __init machine_specific_arch_setup(void);
+--- head-2010-01-18.orig/arch/x86/include/asm/traps.h	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/traps.h	2009-11-06 10:51:42.000000000 +0100
+@@ -37,6 +37,9 @@ asmlinkage void alignment_check(void);
+ asmlinkage void machine_check(void);
+ #endif /* CONFIG_X86_MCE */
+ asmlinkage void simd_coprocessor_error(void);
++#ifdef CONFIG_X86_XEN
++asmlinkage void fixup_4gb_segment(void);
++#endif
+ 
+ dotraplinkage void do_divide_error(struct pt_regs *, long);
+ dotraplinkage void do_debug(struct pt_regs *, long);
+@@ -65,6 +68,9 @@ dotraplinkage void do_machine_check(stru
+ dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
+ #ifdef CONFIG_X86_32
+ dotraplinkage void do_iret_error(struct pt_regs *, long);
++#ifdef CONFIG_XEN
++void do_fixup_4gb_segment(struct pt_regs *, long);
++#endif
+ #endif
+ 
+ static inline int get_si_code(unsigned long condition)
+--- head-2010-01-18.orig/include/linux/page-flags.h	2009-12-16 11:51:06.000000000 +0100
++++ head-2010-01-18/include/linux/page-flags.h	2009-12-16 11:51:46.000000000 +0100
+@@ -127,12 +127,12 @@ enum pageflags {
+ 	PG_fscache = PG_private_2,	/* page backed by cache */
+ 
+ 	/* XEN */
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN)
+ 	PG_pinned = PG_locked,	/* Cannot alias with PG_owner_priv_1 since
+ 				 * bad_page() checks should include this bit.
+ 				 * Should not use PG_arch_1 as that may have
+ 				 * a different purpose elsewhere. */
+-#else
++#elif defined(CONFIG_PARAVIRT_XEN)
+ 	PG_pinned = PG_owner_priv_1,
+ 	PG_savepinned = PG_dirty,
+ #endif
+@@ -229,8 +229,12 @@ PAGEFLAG(Active, active) __CLEARPAGEFLAG
+ 	TESTCLEARFLAG(Active, active)
+ __PAGEFLAG(Slab, slab)
+ PAGEFLAG(Checked, checked)		/* Used by some filesystems */
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned)	/* Xen */
++#endif
++#ifdef CONFIG_PARAVIRT_XEN
+ PAGEFLAG(SavePinned, savepinned);			/* Xen */
++#endif
+ PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
+ PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
+ 
+--- head-2010-01-18.orig/include/xen/interface/memory.h	2010-01-04 12:39:40.000000000 +0100
++++ head-2010-01-18/include/xen/interface/memory.h	2010-01-04 12:39:53.000000000 +0100
+@@ -85,6 +85,7 @@ struct xen_memory_reservation {
+      */
+     domid_t        domid;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+ typedef struct xen_memory_reservation xen_memory_reservation_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+ 
+@@ -170,11 +171,7 @@ struct xen_machphys_mfn_list {
+      * any large discontiguities in the machine address space, 2MB gaps in
+      * the machphys table will be represented by an MFN base of zero.
+      */
+-#ifndef CONFIG_PARAVIRT_XEN
+     XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+-#else
+-    ulong extent_start;
+-#endif
+ 
+     /*
+      * Number of extents written to the above array. This will be smaller
+@@ -182,6 +179,7 @@ struct xen_machphys_mfn_list {
+      */
+     unsigned int nr_extents;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+ 
+@@ -223,6 +221,7 @@ struct xen_add_to_physmap {
+     /* GPFN where the source mapping page should appear. */
+     xen_pfn_t     gpfn;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+ typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/public/Kbuild	2009-12-18 10:11:37.000000000 +0100
+@@ -0,0 +1,4 @@
++header-y += evtchn.h
++header-y += gntdev.h
++header-y += privcmd.h
++header-y += xenbus.h
+--- head-2010-01-18.orig/include/xen/public/privcmd.h	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/include/xen/public/privcmd.h	2009-12-18 10:38:09.000000000 +0100
+@@ -35,10 +35,6 @@
+ 
+ #include <linux/types.h>
+ 
+-#ifndef __user
+-#define __user
+-#endif
+-
+ typedef struct privcmd_hypercall
+ {
+ 	__u64 op;
+--- head-2010-01-18.orig/include/xen/public/xenbus.h	2009-05-29 10:25:53.000000000 +0200
++++ head-2010-01-18/include/xen/public/xenbus.h	2009-12-18 10:38:02.000000000 +0100
+@@ -35,10 +35,6 @@
+ 
+ #include <linux/types.h>
+ 
+-#ifndef __user
+-#define __user
+-#endif
+-
+ typedef struct xenbus_alloc {
+ 	domid_t dom;
+ 	__u32 port;
+--- head-2010-01-18.orig/kernel/hrtimer.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/kernel/hrtimer.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1083,7 +1083,7 @@ ktime_t hrtimer_get_remaining(const stru
+ }
+ EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
+ 
+-#ifdef CONFIG_NO_HZ
++#if defined(CONFIG_NO_HZ) || defined(CONFIG_NO_IDLE_HZ)
+ /**
+  * hrtimer_get_next_event - get the time until next expiry event
+  *
+--- head-2010-01-18.orig/kernel/kexec.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/kernel/kexec.c	2009-11-06 10:51:42.000000000 +0100
+@@ -55,7 +55,7 @@ int dump_after_notifier;
+ static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+ u32
+ #if defined(CONFIG_XEN) && defined(CONFIG_X86)
+-__attribute__((__section__(".bss.page_aligned"), __aligned__(PAGE_SIZE)))
++__page_aligned_bss
+ #endif
+ vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+ size_t vmcoreinfo_size;
+--- head-2010-01-18.orig/kernel/timer.c	2010-01-18 16:51:20.000000000 +0100
++++ head-2010-01-18/kernel/timer.c	2009-11-06 10:51:42.000000000 +0100
+@@ -1044,7 +1044,7 @@ static inline void __run_timers(struct t
+ 	spin_unlock_irq(&base->lock);
+ }
+ 
+-#ifdef CONFIG_NO_HZ
++#if defined(CONFIG_NO_HZ) || defined(CONFIG_NO_IDLE_HZ)
+ /*
+  * Find out when the next timer event is due to happen. This
+  * is used on S/390 to stop all activity when a CPU is idle.
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:51:42.000000000 +0100
+@@ -750,7 +750,7 @@ swiotlb_sync_sg_for_device(struct device
+ }
+ 
+ int
+-swiotlb_dma_mapping_error(dma_addr_t dma_addr)
++swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
+ {
+ 	return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
+ }
+--- head-2010-01-18.orig/mm/mprotect.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/mm/mprotect.c	2009-11-06 10:51:42.000000000 +0100
+@@ -91,8 +91,6 @@ static inline void change_pmd_range(stru
+ 		next = pmd_addr_end(addr, end);
+ 		if (pmd_none_or_clear_bad(pmd))
+ 			continue;
+-		if (arch_change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable))
+-			continue;
+ 		change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable);
+ 	} while (pmd++, addr = next, addr != end);
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.24-25
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.24-25
@@ -0,0 +1,59 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.25
+Patch-mainline: 2.6.32.25
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Automatically created from "patches.kernel.org/patch-2.6.32.24-25" by xen-port-patches.py
+
+--- sle11sp1-2010-11-04.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-09-22 11:35:36.000000000 +0200
++++ sle11sp1-2010-11-04/arch/x86/kernel/apic/io_apic-xen.c	2010-11-04 13:20:41.000000000 +0100
+@@ -352,14 +352,19 @@ void arch_init_copy_chip_data(struct irq
+ 
+ 	old_cfg = old_desc->chip_data;
+ 
+-	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
++	cfg->vector = old_cfg->vector;
++	cfg->move_in_progress = old_cfg->move_in_progress;
++	cpumask_copy(cfg->domain, old_cfg->domain);
++	cpumask_copy(cfg->old_domain, old_cfg->old_domain);
+ 
+ 	init_copy_irq_2_pin(old_cfg, cfg, node);
+ }
+ 
+-static void free_irq_cfg(struct irq_cfg *old_cfg)
++static void free_irq_cfg(struct irq_cfg *cfg)
+ {
+-	kfree(old_cfg);
++	free_cpumask_var(cfg->domain);
++	free_cpumask_var(cfg->old_domain);
++	kfree(cfg);
+ }
+ 
+ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+--- sle11sp1-2010-11-04.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ sle11sp1-2010-11-04/arch/x86/kernel/cpu/common-xen.c	2010-11-04 13:20:41.000000000 +0100
+@@ -568,7 +568,7 @@ void __cpuinit cpu_detect(struct cpuinfo
+ 	}
+ }
+ 
+-static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
++void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+ {
+ 	u32 tfms, xlvl;
+ 	u32 ebx;
+@@ -607,6 +607,7 @@ static void __cpuinit get_cpu_cap(struct
+ 	if (c->extended_cpuid_level >= 0x80000007)
+ 		c->x86_power = cpuid_edx(0x80000007);
+ 
++	init_scattered_cpuid_features(c);
+ }
+ 
+ static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
+@@ -755,7 +756,6 @@ static void __cpuinit generic_identify(s
+ 
+ 	get_model_name(c); /* Default name */
+ 
+-	init_scattered_cpuid_features(c);
+ 	detect_nopl(c);
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.16-17
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.16-17
@@ -0,0 +1,133 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.17
+Patch-mainline: 2.6.32.17
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.16-17" by xen-port-patches.py
+
+--- sle11sp1-2010-10-26.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:52:22.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/include/mach-xen/asm/system.h	2010-08-06 17:06:53.000000000 +0200
+@@ -431,7 +431,7 @@ void stop_this_cpu(void *dummy);
+  *
+  * (Could use an alternative three way for this if there was one.)
+  */
+-static inline void rdtsc_barrier(void)
++static __always_inline void rdtsc_barrier(void)
+ {
+ 	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+ 	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+--- sle11sp1-2010-10-26.orig/arch/x86/kernel/acpi/processor_extcntl_xen.c	2010-10-08 16:30:46.000000000 +0200
++++ sle11sp1-2010-10-26/arch/x86/kernel/acpi/processor_extcntl_xen.c	2010-08-06 17:12:49.000000000 +0200
+@@ -63,7 +63,7 @@ static int xen_cx_notifier(struct acpi_p
+ 		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.access_size = cx->reg.access_size;
+ 		data->reg.address = cx->reg.address;
+ 
+ 		/* Get dependency relationships */
+--- sle11sp1-2010-10-26.orig/arch/x86/kernel/acpi/sleep-xen.c	2010-05-20 11:32:32.000000000 +0200
++++ sle11sp1-2010-10-26/arch/x86/kernel/acpi/sleep-xen.c	2010-08-06 17:06:53.000000000 +0200
+@@ -169,8 +169,6 @@ static int __init acpi_sleep_setup(char 
+ #endif
+ 		if (strncmp(str, "old_ordering", 12) == 0)
+ 			acpi_old_suspend_ordering();
+-		if (strncmp(str, "sci_force_enable", 16) == 0)
+-			acpi_set_sci_en_on_resume();
+ 		str = strchr(str, ',');
+ 		if (str != NULL)
+ 			str += strspn(str, ", \t");
+--- sle11sp1-2010-10-26.orig/drivers/hwmon/coretemp-xen.c	2010-10-26 09:19:38.000000000 +0200
++++ sle11sp1-2010-10-26/drivers/hwmon/coretemp-xen.c	2010-10-26 09:20:36.000000000 +0200
+@@ -54,6 +54,7 @@ struct pdev_entry {
+ 	struct device *hwmon_dev;
+ 	struct mutex update_lock;
+ 	const char *name;
++	u32 cpu_core_id, phys_proc_id;
+ 	u8 x86_model, x86_mask;
+ 	u32 ucode_rev;
+ 	char valid;		/* zero until following fields are valid */
+@@ -78,7 +79,7 @@ static ssize_t show_name(struct device *
+ 	if (attr->index == SHOW_NAME)
+ 		ret = sprintf(buf, "%s\n", data->name);
+ 	else	/* show label */
+-		ret = sprintf(buf, "Core %d\n", data->pdev->id);
++		ret = sprintf(buf, "Core %d\n", data->cpu_core_id);
+ 	return ret;
+ }
+ 
+@@ -376,11 +377,10 @@ static int coretemp_device_add(unsigned 
+ 	struct platform_device *pdev;
+ 	struct pdev_entry *pdev_entry;
+ 
+-	pdev_entry = kzalloc(sizeof(*pdev_entry), GFP_KERNEL);
++	info.pdev_entry = kzalloc(sizeof(*pdev_entry), GFP_KERNEL);
+ 	if (!info.pdev_entry)
+ 		return -ENOMEM;
+ 
+-	info.pdev_entry = pdev_entry;
+ 	err = xen_set_physical_cpu_affinity(cpu);
+ 	if (!err) {
+ 		get_cpuid_info(&info);
+@@ -417,13 +417,30 @@ static int coretemp_device_add(unsigned 
+ 		goto exit_entry_free;
+ 	}
+ 
++	err = xen_get_topology_info(cpu, &info.pdev_entry->cpu_core_id,
++				    &info.pdev_entry->phys_proc_id, NULL);
++	if (err)
++		goto exit_entry_free;
++
++	mutex_lock(&pdev_list_mutex);
++
++	/* Skip second HT entry of each core */
++	list_for_each_entry(pdev_entry, &pdev_list, list) {
++		if (info.pdev_entry->phys_proc_id == pdev_entry->phys_proc_id &&
++		    info.pdev_entry->cpu_core_id == pdev_entry->cpu_core_id) {
++			err = 0;	/* Not an error */
++			goto exit;
++		}
++	}
++
+ 	pdev = platform_device_alloc(DRVNAME, cpu);
+ 	if (!pdev) {
+ 		err = -ENOMEM;
+ 		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+-		goto exit_entry_free;
++		goto exit;
+ 	}
+ 
++	pdev_entry = info.pdev_entry;
+ 	platform_set_drvdata(pdev, pdev_entry);
+ 	pdev_entry->pdev = pdev;
+ 
+@@ -434,7 +451,6 @@ static int coretemp_device_add(unsigned 
+ 		goto exit_device_put;
+ 	}
+ 
+-	mutex_lock(&pdev_list_mutex);
+ 	list_add_tail(&pdev_entry->list, &pdev_list);
+ 	mutex_unlock(&pdev_list_mutex);
+ 
+@@ -442,6 +458,8 @@ static int coretemp_device_add(unsigned 
+ 
+ exit_device_put:
+ 	platform_device_put(pdev);
++exit:
++	mutex_unlock(&pdev_list_mutex);
+ exit_entry_free:
+ 	kfree(info.pdev_entry);
+ 	return err;
+--- sle11sp1-2010-10-26.orig/include/acpi/processor.h	2010-08-23 10:22:57.000000000 +0200
++++ sle11sp1-2010-10-26/include/acpi/processor.h	2010-08-30 15:06:10.000000000 +0200
+@@ -104,7 +104,7 @@ struct acpi_processor_cx {
+ 	struct acpi_processor_cx_policy promotion;
+ 	struct acpi_processor_cx_policy demotion;
+ 	char desc[ACPI_CX_DESC_LEN];
+-#ifndef __GENKSYMS__
++#if !defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) && !defined(__GENKSYMS__)
+ 	u8 bm_sts_skip;
+ #endif
+ };
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.18
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.18
@@ -0,0 +1,358 @@
+From: www.kernel.org
+Subject: Linux 2.6.18
+Patch-mainline: 2.6.18
+
+Automatically created from "patches.kernel.org/patch-2.6.18" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- sle11sp1-2010-01-20.orig/arch/x86/Kconfig	2009-10-15 11:53:21.000000000 +0200
++++ sle11sp1-2010-01-20/arch/x86/Kconfig	2009-11-20 10:59:38.000000000 +0100
+@@ -63,7 +63,6 @@ config ARCH_DEFCONFIG
+ 
+ config GENERIC_TIME
+ 	def_bool y
+-	depends on !X86_XEN
+ 
+ config GENERIC_CMOS_UPDATE
+ 	def_bool y
+@@ -1615,7 +1614,7 @@ config KEXEC_JUMP
+ 	  code in physical address mode via KEXEC
+ 
+ config PHYSICAL_START
+-	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
++	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP || XEN)
+ 	default "0x1000000"
+ 	---help---
+ 	  This gives the physical address where the kernel is loaded.
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/Makefile	2009-11-06 10:45:44.000000000 +0100
+@@ -138,5 +138,5 @@ ifeq ($(CONFIG_X86_64),y)
+ 	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := i8259_$(BITS).o reboot.o smpboot_$(BITS).o
++disabled-obj-$(CONFIG_XEN) := i8253.o i8259_$(BITS).o reboot.o smpboot_$(BITS).o tsc_$(BITS).o
+ %/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/setup64-xen.c	2008-01-28 12:24:19.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/setup64-xen.c	2009-11-06 10:45:44.000000000 +0100
+@@ -363,5 +363,7 @@ void __cpuinit cpu_init (void)
+ 
+ 	fpu_init(); 
+ 
+-	raw_local_save_flags(kernel_eflags);
++	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
++	if (raw_irqs_disabled())
++		kernel_eflags &= ~X86_EFLAGS_IF;
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/time-xen.c	2009-09-02 11:42:46.000000000 +0200
++++ sle11sp1-2010-01-20/arch/x86/kernel/time-xen.c	2009-11-06 10:45:44.000000000 +0100
+@@ -76,8 +76,13 @@
+ 
+ #if defined (__i386__)
+ #include <asm/i8259.h>
++#include <asm/i8253.h>
++DEFINE_SPINLOCK(i8253_lock);
++EXPORT_SYMBOL(i8253_lock);
+ #endif
+ 
++#define XEN_SHIFT 22
++
+ int pit_latch_buggy;              /* extern */
+ 
+ #if defined(__x86_64__)
+@@ -97,10 +102,6 @@ extern unsigned long wall_jiffies;
+ DEFINE_SPINLOCK(rtc_lock);
+ EXPORT_SYMBOL(rtc_lock);
+ 
+-extern struct init_timer_opts timer_tsc_init;
+-extern struct timer_opts timer_tsc;
+-#define timer_none timer_tsc
+-
+ /* These are peridically updated in shared_info, and then copied here. */
+ struct shadow_time_info {
+ 	u64 tsc_timestamp;     /* TSC at last update of time vals.  */
+@@ -175,24 +176,6 @@ static int __init __permitted_clock_jitt
+ }
+ __setup("permitted_clock_jitter=", __permitted_clock_jitter);
+ 
+-#if 0
+-static void delay_tsc(unsigned long loops)
+-{
+-	unsigned long bclock, now;
+-
+-	rdtscl(bclock);
+-	do {
+-		rep_nop();
+-		rdtscl(now);
+-	} while ((now - bclock) < loops);
+-}
+-
+-struct timer_opts timer_tsc = {
+-	.name = "tsc",
+-	.delay = delay_tsc,
+-};
+-#endif
+-
+ /*
+  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+  * yielding a 64-bit result.
+@@ -229,14 +212,6 @@ static inline u64 scale_delta(u64 delta,
+ 	return product;
+ }
+ 
+-#if 0 /* defined (__i386__) */
+-int read_current_timer(unsigned long *timer_val)
+-{
+-	rdtscl(*timer_val);
+-	return 0;
+-}
+-#endif
+-
+ void init_cpu_khz(void)
+ {
+ 	u64 __cpu_khz = 1000000ULL << 32;
+@@ -256,6 +231,7 @@ static u64 get_nsec_offset(struct shadow
+ 	return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
+ }
+ 
++#ifdef CONFIG_X86_64
+ static unsigned long get_usec_offset(struct shadow_time_info *shadow)
+ {
+ 	u64 now, delta;
+@@ -263,6 +239,7 @@ static unsigned long get_usec_offset(str
+ 	delta = now - shadow->tsc_timestamp;
+ 	return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift);
+ }
++#endif
+ 
+ static void __update_wallclock(time_t sec, long nsec)
+ {
+@@ -377,6 +354,8 @@ void rtc_cmos_write(unsigned char val, u
+ }
+ EXPORT_SYMBOL(rtc_cmos_write);
+ 
++#ifdef CONFIG_X86_64
++
+ /*
+  * This version of gettimeofday has microsecond resolution
+  * and better than microsecond precision on fast x86 machines with TSC.
+@@ -515,6 +494,8 @@ int do_settimeofday(struct timespec *tv)
+ 
+ EXPORT_SYMBOL(do_settimeofday);
+ 
++#endif
++
+ static void sync_xen_wallclock(unsigned long dummy);
+ static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
+ static void sync_xen_wallclock(unsigned long dummy)
+@@ -566,11 +547,15 @@ static int set_rtc_mmss(unsigned long no
+ 	return retval;
+ }
+ 
++#ifdef CONFIG_X86_64
+ /* monotonic_clock(): returns # of nanoseconds passed since time_init()
+  *		Note: This function is required to return accurate
+  *		time even in the absence of multiple timer ticks.
+  */
+ unsigned long long monotonic_clock(void)
++#else
++unsigned long long sched_clock(void)
++#endif
+ {
+ 	unsigned int cpu = get_cpu();
+ 	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+@@ -590,9 +575,9 @@ unsigned long long monotonic_clock(void)
+ 
+ 	return time;
+ }
++#ifdef CONFIG_X86_64
+ EXPORT_SYMBOL(monotonic_clock);
+ 
+-#ifdef __x86_64__
+ unsigned long long sched_clock(void)
+ {
+ 	return monotonic_clock();
+@@ -762,6 +747,89 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	return IRQ_HANDLED;
+ }
+ 
++#ifndef CONFIG_X86_64
++
++void tsc_init(void)
++{
++	init_cpu_khz();
++	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
++	       cpu_khz / 1000, cpu_khz % 1000);
++
++	use_tsc_delay();
++}
++
++#include <linux/clocksource.h>
++
++void mark_tsc_unstable(void)
++{
++#ifndef CONFIG_XEN /* XXX Should tell the hypervisor about this fact. */
++	tsc_unstable = 1;
++#endif
++}
++EXPORT_SYMBOL_GPL(mark_tsc_unstable);
++
++static cycle_t xen_clocksource_read(void)
++{
++#ifdef CONFIG_SMP
++	static cycle_t last_ret;
++#ifndef CONFIG_64BIT
++	cycle_t last = cmpxchg64(&last_ret, 0, 0);
++#else
++	cycle_t last = last_ret;
++#define cmpxchg64 cmpxchg
++#endif
++	cycle_t ret = sched_clock();
++
++	if (unlikely((s64)(ret - last) < 0)) {
++		if (last - ret > permitted_clock_jitter
++		    && printk_ratelimit()) {
++			unsigned int cpu = get_cpu();
++			struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
++
++			printk(KERN_WARNING "clocksource/%u: "
++			       "Time went backwards: "
++			       "ret=%Lx delta=%Ld shadow=%Lx offset=%Lx\n",
++			       cpu, ret, ret - last, shadow->system_timestamp,
++			       get_nsec_offset(shadow));
++			put_cpu();
++		}
++		return last;
++	}
++
++	for (;;) {
++		cycle_t cur = cmpxchg64(&last_ret, last, ret);
++
++		if (cur == last || (s64)(ret - cur) < 0)
++			return ret;
++		last = cur;
++	}
++#else
++	return sched_clock();
++#endif
++}
++
++static struct clocksource clocksource_xen = {
++	.name			= "xen",
++	.rating			= 400,
++	.read			= xen_clocksource_read,
++	.mask			= CLOCKSOURCE_MASK(64),
++	.mult			= 1 << XEN_SHIFT,		/* time directly in nanoseconds */
++	.shift			= XEN_SHIFT,
++	.is_continuous		= 1,
++};
++
++static int __init init_xen_clocksource(void)
++{
++	clocksource_xen.mult = clocksource_khz2mult(cpu_khz,
++						clocksource_xen.shift);
++
++	return clocksource_register(&clocksource_xen);
++}
++
++module_init(init_xen_clocksource);
++
++#endif
++
+ static void init_missing_ticks_accounting(unsigned int cpu)
+ {
+ 	struct vcpu_register_runstate_memory_area area;
+@@ -908,7 +976,7 @@ static void setup_cpu0_timer_irq(void)
+ 			VIRQ_TIMER,
+ 			0,
+ 			timer_interrupt,
+-			SA_INTERRUPT,
++			IRQF_DISABLED|IRQF_TIMER,
+ 			"timer0",
+ 			NULL);
+ 	BUG_ON(per_cpu(timer_irq, 0) < 0);
+@@ -950,11 +1018,11 @@ void __init time_init(void)
+ 
+ 	update_wallclock();
+ 
++#ifdef CONFIG_X86_64
+ 	init_cpu_khz();
+ 	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
+ 	       cpu_khz / 1000, cpu_khz % 1000);
+ 
+-#if defined(__x86_64__)
+ 	vxtime.mode = VXTIME_TSC;
+ 	vxtime.quot = (1000000L << 32) / vxtime_hz;
+ 	vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+@@ -1116,7 +1184,7 @@ int __cpuinit local_setup_timer(unsigned
+ 	irq = bind_virq_to_irqhandler(VIRQ_TIMER,
+ 				      cpu,
+ 				      timer_interrupt,
+-				      SA_INTERRUPT,
++				      IRQF_DISABLED|IRQF_TIMER,
+ 				      timer_name[cpu],
+ 				      NULL);
+ 	if (irq < 0)
+--- sle11sp1-2010-01-20.orig/drivers/char/agp/intel-agp.c	2010-01-20 10:22:01.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/agp/intel-agp.c	2010-01-20 10:22:47.000000000 +0100
+@@ -409,6 +409,10 @@ static struct page *i8xx_alloc_pages(voi
+ 
+ 	if (set_pages_uc(page, 4) < 0) {
+ 		set_pages_wb(page, 4);
++#ifdef CONFIG_XEN
++		xen_destroy_contiguous_region((unsigned long)page_address(page),
++					      2);
++#endif
+ 		__free_pages(page, 2);
+ 		return NULL;
+ 	}
+--- sle11sp1-2010-01-20.orig/drivers/xen/console/console.c	2009-03-18 10:39:31.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/console/console.c	2009-11-06 10:45:44.000000000 +0100
+@@ -94,7 +94,6 @@ static int __init xencons_setup(char *st
+ {
+ 	char *q;
+ 	int n;
+-	extern int console_use_vt;
+ 
+ 	console_use_vt = 1;
+ 	if (!strncmp(str, "ttyS", 4)) {
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-06-23 09:28:21.000000000 +0200
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:45:44.000000000 +0100
+@@ -394,7 +394,6 @@ static inline int pmd_large(pmd_t pte) {
+ 
+ /*
+  * Level 4 access.
+- * Never use these in the common code.
+  */
+ #define pgd_page(pgd) ((unsigned long) __va(pgd_val(pgd) & PTE_MASK))
+ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/processor_32.h	2008-01-28 12:24:19.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:45:44.000000000 +0100
+@@ -23,7 +23,7 @@
+ #include <xen/interface/physdev.h>
+ 
+ /* flag for disabling the tsc */
+-extern int tsc_disable;
++#define tsc_disable 0
+ 
+ struct desc_struct {
+ 	unsigned long a,b;
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/thread_info.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/thread_info.h	2009-11-06 10:45:44.000000000 +0100
+@@ -145,11 +145,15 @@ struct thread_info {
+ 	(_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
+ 
+ /* flags to check in __switch_to() */
++#ifndef CONFIG_XEN
+ #define _TIF_WORK_CTXSW							\
+ 	(_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_NOTSC)
+ 
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
++#else
++#define _TIF_WORK_CTXSW _TIF_DEBUG
++#endif
+ 
+ #define PREEMPT_ACTIVE		0x10000000
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86_64-dump-user-pgt
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86_64-dump-user-pgt
@@ -0,0 +1,51 @@
+From: jbeulich@novell.com
+Subject: dump the correct page tables for user mode faults
+Patch-mainline: obsolete
+
+--- head-2009-10-12.orig/arch/x86/mm/fault-xen.c	2009-10-13 13:40:11.000000000 +0200
++++ head-2009-10-12/arch/x86/mm/fault-xen.c	2009-10-13 17:28:26.000000000 +0200
+@@ -328,6 +328,7 @@ static void dump_pagetable(unsigned long
+ out:
+ 	printk(KERN_CONT "\n");
+ }
++#define dump_pagetable(addr, krnl) dump_pagetable(addr)
+ 
+ #else /* CONFIG_X86_64: */
+ 
+@@ -452,7 +453,7 @@ static int bad_address(void *p)
+ 	return probe_kernel_address((unsigned long *)p, dummy);
+ }
+ 
+-static void dump_pagetable(unsigned long address)
++static void dump_pagetable(unsigned long address, bool kernel)
+ {
+ 	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+ 	pgd_t *pgd = base + pgd_index(address);
+@@ -460,6 +461,9 @@ static void dump_pagetable(unsigned long
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+ 
++	if (!kernel)
++		pgd = __user_pgd(base) + pgd_index(address);
++
+ 	if (bad_address(pgd))
+ 		goto bad;
+ 
+@@ -598,7 +602,7 @@ show_fault_oops(struct pt_regs *regs, un
+ 	printk(KERN_ALERT "IP:");
+ 	printk_address(regs->ip, 1);
+ 
+-	dump_pagetable(address);
++	dump_pagetable(address, !(error_code & PF_USER));
+ }
+ 
+ static noinline void
+@@ -615,7 +619,7 @@ pgtable_bad(struct pt_regs *regs, unsign
+ 
+ 	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+ 	       tsk->comm, address);
+-	dump_pagetable(address);
++	dump_pagetable(address, !(error_code & PF_USER));
+ 
+ 	tsk->thread.cr2		= address;
+ 	tsk->thread.trap_no	= 14;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-netback-nr-irqs
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-netback-nr-irqs
@@ -0,0 +1,61 @@
+From: jbeulich@novell.com
+Subject: netback: reduce overhead of IRQ recording
+Patch-mainline: obsolete
+
+Since both NR_PIRQS and NR_DYNIRQS are no longer hardcoded, the
+(memory) overhead of tracking which ones to send notifications to can
+be pretty unbounded. Also, store the dynirq rather than the raw irq
+to push up the limit where the type of notify_list needs to become
+'int' rather than 'u16'.
+
+--- head-2010-01-04.orig/drivers/xen/netback/interface.c	2010-01-04 12:42:38.000000000 +0100
++++ head-2010-01-04/drivers/xen/netback/interface.c	2010-01-04 13:31:46.000000000 +0100
+@@ -339,6 +339,7 @@ int netif_map(netif_t *netif, unsigned l
+ 		netif->dev->name, netif);
+ 	if (err < 0)
+ 		goto err_hypervisor;
++	BUG_ON(err < DYNIRQ_BASE || err >= DYNIRQ_BASE + NR_DYNIRQS);
+ 	netif->irq = err;
+ 	disable_irq(netif->irq);
+ 
+--- head-2010-01-04.orig/drivers/xen/netback/netback.c	2010-01-04 13:31:38.000000000 +0100
++++ head-2010-01-04/drivers/xen/netback/netback.c	2010-01-04 13:31:44.000000000 +0100
+@@ -590,8 +590,12 @@ static void net_rx_action(unsigned long 
+ 	static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
+ 	static gnttab_transfer_t grant_trans_op[NET_RX_RING_SIZE];
+ 	static gnttab_copy_t grant_copy_op[NET_RX_RING_SIZE];
+-	static unsigned char rx_notify[NR_IRQS];
++	static DECLARE_BITMAP(rx_notify, NR_DYNIRQS);
++#if NR_DYNIRQS <= 0x10000
+ 	static u16 notify_list[NET_RX_RING_SIZE];
++#else
++	static int notify_list[NET_RX_RING_SIZE];
++#endif
+ 	static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
+ 
+ 	struct netrx_pending_operations npo = {
+@@ -749,11 +753,9 @@ static void net_rx_action(unsigned long 
+ 					 nr_frags);
+ 
+ 		RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
+-		irq = netif->irq;
+-		if (ret && !rx_notify[irq]) {
+-			rx_notify[irq] = 1;
++		irq = netif->irq - DYNIRQ_BASE;
++		if (ret && !__test_and_set_bit(irq, rx_notify))
+ 			notify_list[notify_nr++] = irq;
+-		}
+ 
+ 		if (netif_queue_stopped(netif->dev) &&
+ 		    netif_schedulable(netif) &&
+@@ -778,8 +780,8 @@ static void net_rx_action(unsigned long 
+ 
+ 	while (notify_nr != 0) {
+ 		irq = notify_list[--notify_nr];
+-		rx_notify[irq] = 0;
+-		notify_remote_via_irq(irq);
++		__clear_bit(irq, rx_notify);
++		notify_remote_via_irq(irq + DYNIRQ_BASE);
+ 	}
+ 
+ 	/* More work to do? */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-unpriv-build
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-unpriv-build
@@ -0,0 +1,273 @@
+From: jbeulich@novell.com
+Subject: no need to build certain bits when building non-privileged kernel
+Patch-mainline: n/a
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:04:42.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-12-22 13:45:33.000000000 +0100
+@@ -700,6 +700,7 @@ config HPET_EMULATE_RTC
+ config DMI
+ 	default y
+ 	bool "Enable DMI scanning" if EMBEDDED
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 	---help---
+ 	  Enabled scanning of DMI to identify machine quirks. Say Y
+ 	  here unless you have verified that your setup is not
+@@ -1974,13 +1975,15 @@ config PCI_GOBIOS
+ 
+ config PCI_GOMMCONFIG
+ 	bool "MMConfig"
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ config PCI_GODIRECT
+ 	bool "Direct"
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ config PCI_GOOLPC
+ 	bool "OLPC"
+-	depends on OLPC
++	depends on OLPC && !XEN_UNPRIVILEGED_GUEST
+ 
+ config PCI_GOXEN_FE
+ 	bool "Xen PCI Frontend"
+@@ -1991,6 +1994,7 @@ config PCI_GOXEN_FE
+ 
+ config PCI_GOANY
+ 	bool "Any"
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ endchoice
+ 
+@@ -2021,7 +2025,7 @@ config PCI_MMCONFIG
+ 
+ config XEN_PCIDEV_FRONTEND
+ 	def_bool y
+-	prompt "Xen PCI Frontend" if X86_64
++	prompt "Xen PCI Frontend" if X86_64 && !XEN_UNPRIVILEGED_GUEST
+ 	depends on PCI && XEN && (PCI_GOXEN_FE || PCI_GOANY || X86_64)
+  	select HOTPLUG
+ 	help
+@@ -2226,7 +2230,9 @@ source "net/Kconfig"
+ 
+ source "drivers/Kconfig"
+ 
++if !XEN_UNPRIVILEGED_GUEST
+ source "drivers/firmware/Kconfig"
++endif
+ 
+ source "fs/Kconfig"
+ 
+--- head-2010-01-18.orig/drivers/firmware/Kconfig	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/firmware/Kconfig	2009-11-06 11:10:32.000000000 +0100
+@@ -114,7 +114,7 @@ config DMIID
+ 
+ config ISCSI_IBFT_FIND
+ 	bool "iSCSI Boot Firmware Table Attributes"
+-	depends on X86 && !XEN_UNPRIVILEGED_GUEST
++	depends on X86
+ 	default n
+ 	help
+ 	  This option enables the kernel to find the region of memory
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:31:00.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-18 12:31:08.000000000 +0100
+@@ -273,6 +273,7 @@ config XEN_USB_FRONTEND_HCD_PM
+ 
+ config XEN_GRANT_DEV
+ 	tristate "User-space granted page access driver"
++	depends on XEN_BACKEND != n
+ 	default XEN_PRIVILEGED_GUEST
+ 	help
+ 	  Device for accessing (in user-space) pages that have been granted
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2009-10-14 16:19:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2010-01-04 13:32:27.000000000 +0100
+@@ -619,6 +619,9 @@ void balloon_update_driver_allowance(lon
+ 	bs.driver_pages += delta;
+ 	balloon_unlock(flags);
+ }
++EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
++
++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
+ 
+ #ifdef CONFIG_XEN
+ static int dealloc_pte_fn(
+@@ -727,6 +730,7 @@ struct page **alloc_empty_pages_and_page
+ 	pagevec = NULL;
+ 	goto out;
+ }
++EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+ 
+ void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
+ {
+@@ -747,6 +751,9 @@ void free_empty_pages_and_pagevec(struct
+ 
+ 	schedule_work(&balloon_worker);
+ }
++EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
++
++#endif /* CONFIG_XEN_BACKEND */
+ 
+ void balloon_release_driver_page(struct page *page)
+ {
+@@ -760,10 +767,6 @@ void balloon_release_driver_page(struct 
+ 
+ 	schedule_work(&balloon_worker);
+ }
+-
+-EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
+-EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+-EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+ EXPORT_SYMBOL_GPL(balloon_release_driver_page);
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
+--- head-2010-01-18.orig/drivers/xen/core/Makefile	2010-01-04 16:17:00.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/Makefile	2009-11-06 11:10:32.000000000 +0100
+@@ -2,9 +2,10 @@
+ # Makefile for the linux kernel.
+ #
+ 
+-obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o firmware.o
++obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o
+ 
+-obj-$(CONFIG_PCI)		+= pci.o
++priv-$(CONFIG_PCI)		+= pci.o
++obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += firmware.o $(priv-y)
+ obj-$(CONFIG_PROC_FS)		+= xen_proc.o
+ obj-$(CONFIG_SYS_HYPERVISOR)	+= hypervisor_sysfs.o
+ obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
+--- head-2010-01-18.orig/drivers/xen/core/gnttab.c	2009-12-15 09:28:00.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/gnttab.c	2009-12-15 09:29:45.000000000 +0100
+@@ -437,8 +437,6 @@ static inline unsigned int max_nr_grant_
+ 
+ #ifdef CONFIG_XEN
+ 
+-static DEFINE_SEQLOCK(gnttab_dma_lock);
+-
+ #ifdef CONFIG_X86
+ static int map_pte_fn(pte_t *pte, struct page *pmd_page,
+ 		      unsigned long addr, void *data)
+@@ -508,6 +506,10 @@ static int gnttab_map(unsigned int start
+ 	return 0;
+ }
+ 
++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
++
++static DEFINE_SEQLOCK(gnttab_dma_lock);
++
+ static void gnttab_page_free(struct page *page, unsigned int order)
+ {
+ 	BUG_ON(order);
+@@ -639,6 +641,8 @@ void __gnttab_dma_map_page(struct page *
+ 	} while (unlikely(read_seqretry(&gnttab_dma_lock, seq)));
+ }
+ 
++#endif /* CONFIG_XEN_BACKEND */
++
+ #ifdef __HAVE_ARCH_PTE_SPECIAL
+ 
+ static unsigned int GNTMAP_pte_special;
+--- head-2010-01-18.orig/drivers/xen/privcmd/Makefile	2007-07-10 09:42:30.000000000 +0200
++++ head-2010-01-18/drivers/xen/privcmd/Makefile	2009-12-18 08:20:46.000000000 +0100
+@@ -1,3 +1,3 @@
+-
+-obj-y	+= privcmd.o
+-obj-$(CONFIG_COMPAT)	+= compat_privcmd.o
++priv-$(CONFIG_COMPAT) := compat_privcmd.o
++obj-y := privcmd.o
++obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += $(priv-y)
+--- head-2010-01-18.orig/drivers/xen/privcmd/privcmd.c	2010-01-19 10:32:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/privcmd/privcmd.c	2010-01-19 10:33:58.000000000 +0100
+@@ -33,6 +33,9 @@
+ static struct proc_dir_entry *privcmd_intf;
+ static struct proc_dir_entry *capabilities_intf;
+ 
++#ifndef CONFIG_XEN_PRIVILEGED_GUEST
++#define HAVE_ARCH_PRIVCMD_MMAP
++#endif
+ #ifndef HAVE_ARCH_PRIVCMD_MMAP
+ static int enforce_singleshot_mapping_fn(pte_t *pte, struct page *pmd_page,
+ 					 unsigned long addr, void *data)
+@@ -57,12 +60,14 @@ static long privcmd_ioctl(struct file *f
+ {
+ 	long ret;
+ 	void __user *udata = (void __user *) data;
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ 	unsigned long i, addr, nr, nr_pages;
+ 	int paged_out;
+ 	struct mm_struct *mm = current->mm;
+ 	struct vm_area_struct *vma;
+ 	LIST_HEAD(pagelist);
+ 	struct list_head *l, *l2;
++#endif
+ 
+ 	switch (cmd) {
+ 	case IOCTL_PRIVCMD_HYPERCALL: {
+@@ -87,6 +92,8 @@ static long privcmd_ioctl(struct file *f
+ 	}
+ 	break;
+ 
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++
+ 	case IOCTL_PRIVCMD_MMAP: {
+ #define MMAP_NR_PER_PAGE \
+ 	(unsigned long)((PAGE_SIZE - sizeof(*l)) / sizeof(*msg))
+@@ -391,6 +398,8 @@ static long privcmd_ioctl(struct file *f
+ 	}
+ 	break;
+ 
++#endif /* CONFIG_XEN_PRIVILEGED_GUEST */
++
+ 	default:
+ 		ret = -EINVAL;
+ 		break;
+@@ -426,7 +435,9 @@ static int privcmd_mmap(struct file * fi
+ 
+ static const struct file_operations privcmd_file_ops = {
+ 	.unlocked_ioctl = privcmd_ioctl,
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ 	.mmap = privcmd_mmap,
++#endif
+ };
+ 
+ static int capabilities_read(char *page, char **start, off_t off,
+--- head-2010-01-18.orig/fs/compat_ioctl.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/fs/compat_ioctl.c	2010-01-18 17:13:42.000000000 +0100
+@@ -2734,10 +2734,12 @@ IGNORE_IOCTL(FBIOSCURSOR32)
+ IGNORE_IOCTL(FBIOGCURSOR32)
+ #endif
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32)
+ HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32)
+ HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_V2_32, privcmd_ioctl_32)
++#endif
++#ifdef CONFIG_XEN
+ COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL)
+ COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ)
+ COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN)
+--- head-2010-01-18.orig/include/xen/firmware.h	2007-07-02 08:16:19.000000000 +0200
++++ head-2010-01-18/include/xen/firmware.h	2009-11-06 11:10:32.000000000 +0100
+@@ -5,6 +5,10 @@
+ void copy_edd(void);
+ #endif
+ 
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ void copy_edid(void);
++#else
++static inline void copy_edid(void) {}
++#endif
+ 
+ #endif /* __XEN_FIRMWARE_H__ */
+--- head-2010-01-18.orig/include/xen/gnttab.h	2009-11-06 11:10:15.000000000 +0100
++++ head-2010-01-18/include/xen/gnttab.h	2009-12-15 09:54:17.000000000 +0100
+@@ -103,7 +103,11 @@ void gnttab_grant_foreign_transfer_ref(g
+ 				       unsigned long pfn);
+ 
+ int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep);
++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
+ void __gnttab_dma_map_page(struct page *page);
++#else
++#define __gnttab_dma_map_page __gnttab_dma_unmap_page
++#endif
+ static inline void __gnttab_dma_unmap_page(struct page *page)
+ {
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-include-xen-interface.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-include-xen-interface.diff
@@ -0,0 +1,6149 @@
+Subject: xen3 include-xen-interface
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/COPYING	2007-06-12 13:14:19.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.
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/cpuid.h	2008-01-21 11:15:27.000000000 +0100
+@@ -0,0 +1,68 @@
++/******************************************************************************
++ * arch-x86/cpuid.h
++ * 
++ * CPUID interface to 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) 2007 Citrix Systems, Inc.
++ * 
++ * Authors:
++ *    Keir Fraser <keir.fraser@citrix.com>
++ */
++
++#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
++#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
++
++/* Xen identification leaves start at 0x40000000. */
++#define XEN_CPUID_FIRST_LEAF 0x40000000
++#define XEN_CPUID_LEAF(i)    (XEN_CPUID_FIRST_LEAF + (i))
++
++/*
++ * Leaf 1 (0x40000000)
++ * EAX: Largest Xen-information leaf. All leaves up to an including @EAX
++ *      are supported by the Xen host.
++ * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
++ *      of a Xen host.
++ */
++#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */
++#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */
++#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
++
++/*
++ * Leaf 2 (0x40000001)
++ * EAX[31:16]: Xen major version.
++ * EAX[15: 0]: Xen minor version.
++ * EBX-EDX: Reserved (currently all zeroes).
++ */
++
++/*
++ * Leaf 3 (0x40000002)
++ * EAX: Number of hypercall transfer pages. This register is always guaranteed
++ *      to specify one hypercall page.
++ * EBX: Base address of Xen-specific MSRs.
++ * ECX: Features 1. Unused bits are set to zero.
++ * EDX: Features 2. Unused bits are set to zero.
++ */
++
++/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */
++#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
++#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD  (1u<<0)
++
++#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/hvm/save.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,439 @@
++/* 
++ * Structure definitions for HVM state that is held by Xen and must
++ * be saved along with the domain's memory and device-model state.
++ * 
++ * Copyright (c) 2007 XenSource Ltd.
++ *
++ * 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_PUBLIC_HVM_SAVE_X86_H__
++#define __XEN_PUBLIC_HVM_SAVE_X86_H__
++
++/* 
++ * Save/restore header: general info about the save file. 
++ */
++
++#define HVM_FILE_MAGIC   0x54381286
++#define HVM_FILE_VERSION 0x00000001
++
++struct hvm_save_header {
++    uint32_t magic;             /* Must be HVM_FILE_MAGIC */
++    uint32_t version;           /* File format version */
++    uint64_t changeset;         /* Version of Xen that saved this file */
++    uint32_t cpuid;             /* CPUID[0x01][%eax] on the saving machine */
++    uint32_t gtsc_khz;        /* Guest's TSC frequency in kHz */
++};
++
++DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
++
++
++/*
++ * Processor
++ */
++
++struct hvm_hw_cpu {
++    uint8_t  fpu_regs[512];
++
++    uint64_t rax;
++    uint64_t rbx;
++    uint64_t rcx;
++    uint64_t rdx;
++    uint64_t rbp;
++    uint64_t rsi;
++    uint64_t rdi;
++    uint64_t rsp;
++    uint64_t r8;
++    uint64_t r9;
++    uint64_t r10;
++    uint64_t r11;
++    uint64_t r12;
++    uint64_t r13;
++    uint64_t r14;
++    uint64_t r15;
++
++    uint64_t rip;
++    uint64_t rflags;
++
++    uint64_t cr0;
++    uint64_t cr2;
++    uint64_t cr3;
++    uint64_t cr4;
++
++    uint64_t dr0;
++    uint64_t dr1;
++    uint64_t dr2;
++    uint64_t dr3;
++    uint64_t dr6;
++    uint64_t dr7;    
++
++    uint32_t cs_sel;
++    uint32_t ds_sel;
++    uint32_t es_sel;
++    uint32_t fs_sel;
++    uint32_t gs_sel;
++    uint32_t ss_sel;
++    uint32_t tr_sel;
++    uint32_t ldtr_sel;
++
++    uint32_t cs_limit;
++    uint32_t ds_limit;
++    uint32_t es_limit;
++    uint32_t fs_limit;
++    uint32_t gs_limit;
++    uint32_t ss_limit;
++    uint32_t tr_limit;
++    uint32_t ldtr_limit;
++    uint32_t idtr_limit;
++    uint32_t gdtr_limit;
++
++    uint64_t cs_base;
++    uint64_t ds_base;
++    uint64_t es_base;
++    uint64_t fs_base;
++    uint64_t gs_base;
++    uint64_t ss_base;
++    uint64_t tr_base;
++    uint64_t ldtr_base;
++    uint64_t idtr_base;
++    uint64_t gdtr_base;
++
++    uint32_t cs_arbytes;
++    uint32_t ds_arbytes;
++    uint32_t es_arbytes;
++    uint32_t fs_arbytes;
++    uint32_t gs_arbytes;
++    uint32_t ss_arbytes;
++    uint32_t tr_arbytes;
++    uint32_t ldtr_arbytes;
++
++    uint64_t sysenter_cs;
++    uint64_t sysenter_esp;
++    uint64_t sysenter_eip;
++
++    /* msr for em64t */
++    uint64_t shadow_gs;
++
++    /* msr content saved/restored. */
++    uint64_t msr_flags;
++    uint64_t msr_lstar;
++    uint64_t msr_star;
++    uint64_t msr_cstar;
++    uint64_t msr_syscall_mask;
++    uint64_t msr_efer;
++    uint64_t msr_tsc_aux;
++
++    /* guest's idea of what rdtsc() would return */
++    uint64_t tsc;
++
++    /* pending event, if any */
++    union {
++        uint32_t pending_event;
++        struct {
++            uint8_t  pending_vector:8;
++            uint8_t  pending_type:3;
++            uint8_t  pending_error_valid:1;
++            uint32_t pending_reserved:19;
++            uint8_t  pending_valid:1;
++        };
++    };
++    /* error code for pending event */
++    uint32_t error_code;
++};
++
++DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu);
++
++
++/*
++ * PIC
++ */
++
++struct hvm_hw_vpic {
++    /* IR line bitmasks. */
++    uint8_t irr;
++    uint8_t imr;
++    uint8_t isr;
++
++    /* Line IRx maps to IRQ irq_base+x */
++    uint8_t irq_base;
++
++    /*
++     * Where are we in ICW2-4 initialisation (0 means no init in progress)?
++     * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
++     * Bit 2: ICW1.IC4  (1 == ICW4 included in init sequence)
++     * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
++     */
++    uint8_t init_state:4;
++
++    /* IR line with highest priority. */
++    uint8_t priority_add:4;
++
++    /* Reads from A=0 obtain ISR or IRR? */
++    uint8_t readsel_isr:1;
++
++    /* Reads perform a polling read? */
++    uint8_t poll:1;
++
++    /* Automatically clear IRQs from the ISR during INTA? */
++    uint8_t auto_eoi:1;
++
++    /* Automatically rotate IRQ priorities during AEOI? */
++    uint8_t rotate_on_auto_eoi:1;
++
++    /* Exclude slave inputs when considering in-service IRQs? */
++    uint8_t special_fully_nested_mode:1;
++
++    /* Special mask mode excludes masked IRs from AEOI and priority checks. */
++    uint8_t special_mask_mode:1;
++
++    /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
++    uint8_t is_master:1;
++
++    /* Edge/trigger selection. */
++    uint8_t elcr;
++
++    /* Virtual INT output. */
++    uint8_t int_output;
++};
++
++DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
++
++
++/*
++ * IO-APIC
++ */
++
++#ifdef __ia64__
++#define VIOAPIC_IS_IOSAPIC 1
++#define VIOAPIC_NUM_PINS  24
++#else
++#define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
++#endif
++
++struct hvm_hw_vioapic {
++    uint64_t base_address;
++    uint32_t ioregsel;
++    uint32_t id;
++    union vioapic_redir_entry
++    {
++        uint64_t bits;
++        struct {
++            uint8_t vector;
++            uint8_t delivery_mode:3;
++            uint8_t dest_mode:1;
++            uint8_t delivery_status:1;
++            uint8_t polarity:1;
++            uint8_t remote_irr:1;
++            uint8_t trig_mode:1;
++            uint8_t mask:1;
++            uint8_t reserve:7;
++#if !VIOAPIC_IS_IOSAPIC
++            uint8_t reserved[4];
++            uint8_t dest_id;
++#else
++            uint8_t reserved[3];
++            uint16_t dest_id;
++#endif
++        } fields;
++    } redirtbl[VIOAPIC_NUM_PINS];
++};
++
++DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
++
++
++/*
++ * LAPIC
++ */
++
++struct hvm_hw_lapic {
++    uint64_t             apic_base_msr;
++    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
++    uint32_t             timer_divisor;
++};
++
++DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
++
++struct hvm_hw_lapic_regs {
++    uint8_t data[1024];
++};
++
++DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
++
++
++/*
++ * IRQs
++ */
++
++struct hvm_hw_pci_irqs {
++    /*
++     * Virtual interrupt wires for a single PCI bus.
++     * Indexed by: device*4 + INTx#.
++     */
++    union {
++        unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
++        uint64_t pad[2];
++    };
++};
++
++DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
++
++struct hvm_hw_isa_irqs {
++    /*
++     * Virtual interrupt wires for ISA devices.
++     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
++     */
++    union {
++        unsigned long i[1];  /* DECLARE_BITMAP(i, 16); */
++        uint64_t pad[1];
++    };
++};
++
++DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
++
++struct hvm_hw_pci_link {
++    /*
++     * PCI-ISA interrupt router.
++     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
++     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
++     * The router provides a programmable mapping from each link to a GSI.
++     */
++    uint8_t route[4];
++    uint8_t pad0[4];
++};
++
++DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
++
++/* 
++ *  PIT
++ */
++
++struct hvm_hw_pit {
++    struct hvm_hw_pit_channel {
++        uint32_t count; /* can be 65536 */
++        uint16_t latched_count;
++        uint8_t count_latched;
++        uint8_t status_latched;
++        uint8_t status;
++        uint8_t read_state;
++        uint8_t write_state;
++        uint8_t write_latch;
++        uint8_t rw_mode;
++        uint8_t mode;
++        uint8_t bcd; /* not supported */
++        uint8_t gate; /* timer start */
++    } channels[3];  /* 3 x 16 bytes */
++    uint32_t speaker_data_on;
++    uint32_t pad0;
++};
++
++DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
++
++
++/* 
++ * RTC
++ */ 
++
++#define RTC_CMOS_SIZE 14
++struct hvm_hw_rtc {
++    /* CMOS bytes */
++    uint8_t cmos_data[RTC_CMOS_SIZE];
++    /* Index register for 2-part operations */
++    uint8_t cmos_index;
++    uint8_t pad0;
++};
++
++DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
++
++
++/*
++ * HPET
++ */
++
++#define HPET_TIMER_NUM     3    /* 3 timers supported now */
++struct hvm_hw_hpet {
++    /* Memory-mapped, software visible registers */
++    uint64_t capability;        /* capabilities */
++    uint64_t res0;              /* reserved */
++    uint64_t config;            /* configuration */
++    uint64_t res1;              /* reserved */
++    uint64_t isr;               /* interrupt status reg */
++    uint64_t res2[25];          /* reserved */
++    uint64_t mc64;              /* main counter */
++    uint64_t res3;              /* reserved */
++    struct {                    /* timers */
++        uint64_t config;        /* configuration/cap */
++        uint64_t cmp;           /* comparator */
++        uint64_t fsb;           /* FSB route, not supported now */
++        uint64_t res4;          /* reserved */
++    } timers[HPET_TIMER_NUM];
++    uint64_t res5[4*(24-HPET_TIMER_NUM)];  /* reserved, up to 0x3ff */
++
++    /* Hidden register state */
++    uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
++};
++
++DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
++
++
++/*
++ * PM timer
++ */
++
++struct hvm_hw_pmtimer {
++    uint32_t tmr_val;   /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
++    uint16_t pm1a_sts;  /* PM1a_EVT_BLK.PM1a_STS: status register */
++    uint16_t pm1a_en;   /* PM1a_EVT_BLK.PM1a_EN: enable register */
++};
++
++DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
++
++/*
++ * MTRR MSRs
++ */
++
++struct hvm_hw_mtrr {
++#define MTRR_VCNT 8
++#define NUM_FIXED_MSR 11
++    uint64_t msr_pat_cr;
++    /* mtrr physbase & physmask msr pair*/
++    uint64_t msr_mtrr_var[MTRR_VCNT*2];
++    uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
++    uint64_t msr_mtrr_cap;
++    uint64_t msr_mtrr_def_type;
++};
++
++DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
++
++/*
++ * Viridian hypervisor context.
++ */
++
++struct hvm_viridian_context {
++    uint64_t hypercall_gpa;
++    uint64_t guest_os_id;
++};
++
++DECLARE_HVM_SAVE_TYPE(VIRIDIAN, 15, struct hvm_viridian_context);
++
++/* 
++ * Largest type-code in use
++ */
++#define HVM_SAVE_CODE_MAX 15
++
++#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/xen-mca.h	2009-05-19 09:16:41.000000000 +0200
+@@ -0,0 +1,422 @@
++/******************************************************************************
++ * 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
++
++/*
++ * The xen-unstable repo has interface version 0x03000001; out interface
++ * is incompatible with that and any future minor revisions, so we
++ * choose a different version number range that is numerically less
++ * than that used in xen-unstable.
++ */
++#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
++
++/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */
++#define XEN_MC_NONURGENT  0x0001
++/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */
++#define XEN_MC_URGENT     0x0002
++/* IN: Dom0 acknowledges previosly-fetched telemetry */
++#define XEN_MC_ACK        0x0004
++
++/* 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
++#define MC_TYPE_RECOVERY        3
++
++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)
++#define MC_FLAG_RECOVERABLE	(1 << 2)
++#define MC_FLAG_POLLED		(1 << 3)
++#define MC_FLAG_RESET		(1 << 4)
++#define MC_FLAG_CMCI		(1 << 5)
++#define MC_FLAG_MCE		(1 << 6)
++/* 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;
++    uint16_t mc_vcpuid; /* virtual cpu scheduled for 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 */
++    uint32_t mc_apicid;
++    uint32_t mc_flags;
++    uint64_t mc_gstatus; /* global status */
++};
++
++/* 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;
++    uint64_t mc_ctrl2;
++    uint64_t mc_tsc;
++};
++
++
++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. */
++    /*
++     * Currently Intel extended MSR (32/64) include all gp registers
++     * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be
++     * useful at present. So expand this array to 16/32 to leave room.
++     */
++    struct mcinfo_msr mc_msr[sizeof(void *) * 4];
++};
++
++/* Recovery Action flags. Giving recovery result information to DOM0 */
++
++/* Xen takes successful recovery action, the error is recovered */
++#define REC_ACTION_RECOVERED (0x1 << 0)
++/* No action is performed by XEN */
++#define REC_ACTION_NONE (0x1 << 1)
++/* It's possible DOM0 might take action ownership in some case */
++#define REC_ACTION_NEED_RESET (0x1 << 2)
++
++/* Different Recovery Action types, if the action is performed successfully,
++ * REC_ACTION_RECOVERED flag will be returned.
++ */
++
++/* Page Offline Action */
++#define MC_ACTION_PAGE_OFFLINE (0x1 << 0)
++/* CPU offline Action */
++#define MC_ACTION_CPU_OFFLINE (0x1 << 1)
++/* L3 cache disable Action */
++#define MC_ACTION_CACHE_SHRINK (0x1 << 2)
++
++/* Below interface used between XEN/DOM0 for passing XEN's recovery action 
++ * information to DOM0. 
++ * usage Senario: After offlining broken page, XEN might pass its page offline
++ * recovery action result to DOM0. DOM0 will save the information in 
++ * non-volatile memory for further proactive actions, such as offlining the
++ * easy broken page earlier when doing next reboot.
++*/
++struct page_offline_action
++{
++    /* Params for passing the offlined page number to DOM0 */
++    uint64_t mfn;
++    uint64_t status;
++};
++
++struct cpu_offline_action
++{
++    /* Params for passing the identity of the offlined CPU to DOM0 */
++    uint32_t mc_socketid;
++    uint16_t mc_coreid;
++    uint16_t mc_core_threadid;
++};
++
++#define MAX_UNION_SIZE 16
++struct mcinfo_recovery
++{
++    struct mcinfo_common common;
++    uint16_t mc_bank; /* bank nr */
++    uint8_t action_flags;
++    uint8_t action_types;
++    union {
++        struct page_offline_action page_retire;
++        struct cpu_offline_action cpu_offline;
++        uint8_t pad[MAX_UNION_SIZE];
++    } action_info;
++};
++
++
++#define MCINFO_HYPERCALLSIZE	1024
++#define MCINFO_MAXSIZE		768
++
++struct mc_info {
++    /* Number of mcinfo_* entries in mi_data */
++    uint32_t mi_nentries;
++    uint32_t _pad0;
++    uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
++};
++typedef struct mc_info mc_info_t;
++DEFINE_XEN_GUEST_HANDLE(mc_info_t);
++
++#define __MC_MSR_ARRAYSIZE 8
++#define __MC_NMSRS 1
++#define MC_NCAPS	7	/* 7 CPU feature flag words */
++#define MC_CAPS_STD_EDX	0	/* cpuid level 0x00000001 (%edx) */
++#define MC_CAPS_AMD_EDX	1	/* cpuid level 0x80000001 (%edx) */
++#define MC_CAPS_TM	2	/* cpuid level 0x80860001 (TransMeta) */
++#define MC_CAPS_LINUX	3	/* Linux-defined */
++#define MC_CAPS_STD_ECX	4	/* cpuid level 0x00000001 (%ecx) */
++#define MC_CAPS_VIA	5	/* cpuid level 0xc0000001 */
++#define MC_CAPS_AMD_ECX	6	/* cpuid level 0x80000001 (%ecx) */
++
++struct mcinfo_logical_cpu {
++    uint32_t mc_cpunr;          
++    uint32_t mc_chipid; 
++    uint16_t mc_coreid;
++    uint16_t mc_threadid;
++    uint32_t mc_apicid;
++    uint32_t mc_clusterid;
++    uint32_t mc_ncores;
++    uint32_t mc_ncores_active;
++    uint32_t mc_nthreads;
++    int32_t mc_cpuid_level;
++    uint32_t mc_family;
++    uint32_t mc_vendor;
++    uint32_t mc_model;
++    uint32_t mc_step;
++    char mc_vendorid[16];
++    char mc_brandid[64];
++    uint32_t mc_cpu_caps[MC_NCAPS];
++    uint32_t mc_cache_size;
++    uint32_t mc_cache_alignment;
++    int32_t mc_nmsrvals;
++    struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
++};
++typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t;
++DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_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_NONURGENT, XEN_MC_URGENT,
++                           XEN_MC_ACK if ack'ing an earlier fetch */
++			/* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED,
++			   XEN_MC_NODATA, XEN_MC_NOMATCH */
++    uint32_t _pad0;
++    uint64_t fetch_id;	/* OUT: id for ack, IN: id we are ack'ing */
++
++    /* OUT variables. */
++    XEN_GUEST_HANDLE(mc_info_t) data;
++};
++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. */
++
++    /* 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);
++
++#define XEN_MC_physcpuinfo 3
++struct xen_mc_physcpuinfo {
++	/* IN/OUT */
++	uint32_t ncpus;
++	uint32_t _pad0;
++	/* OUT */
++	XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
++};
++
++#define XEN_MC_msrinject    4
++#define MC_MSRINJ_MAXMSRS       8
++struct xen_mc_msrinject {
++       /* IN */
++	uint32_t mcinj_cpunr;           /* target processor id */
++	uint32_t mcinj_flags;           /* see MC_MSRINJ_F_* below */
++	uint32_t mcinj_count;           /* 0 .. count-1 in array are valid */
++	uint32_t _pad0;
++	struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
++};
++
++/* Flags for mcinj_flags above; bits 16-31 are reserved */
++#define MC_MSRINJ_F_INTERPOSE   0x1
++
++#define XEN_MC_mceinject    5
++struct xen_mc_mceinject {
++	unsigned int mceinj_cpunr;      /* target processor id */
++};
++
++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;
++        struct xen_mc_physcpuinfo  mc_physcpuinfo;
++        struct xen_mc_msrinject    mc_msrinject;
++        struct xen_mc_mceinject    mc_mceinject;
++    } u;
++};
++typedef struct xen_mc xen_mc_t;
++DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/xen-x86_32.h	2008-07-21 11:00:33.000000000 +0200
+@@ -0,0 +1,180 @@
++/******************************************************************************
++ * xen-x86_32.h
++ * 
++ * Guest OS interface to x86 32-bit 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-2007, K A Fraser
++ */
++
++#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
++#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
++
++/*
++ * Hypercall interface:
++ *  Input:  %ebx, %ecx, %edx, %esi, %edi (arguments 1-5)
++ *  Output: %eax
++ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
++ *  call hypercall_page + hypercall-number * 32
++ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
++ */
++
++#if __XEN_INTERFACE_VERSION__ < 0x00030203
++/*
++ * Legacy hypercall interface:
++ * As above, except the entry sequence to the hypervisor is:
++ *  mov $hypercall-number*32,%eax ; int $0x82
++ */
++#define TRAP_INSTR "int $0x82"
++#endif
++
++/*
++ * These flat segments are in the Xen-private section of every GDT. Since these
++ * are also present in the initial GDT, many OSes will be able to avoid
++ * installing their own GDT.
++ */
++#define FLAT_RING1_CS 0xe019    /* GDT index 259 */
++#define FLAT_RING1_DS 0xe021    /* GDT index 260 */
++#define FLAT_RING1_SS 0xe021    /* GDT index 260 */
++#define FLAT_RING3_CS 0xe02b    /* GDT index 261 */
++#define FLAT_RING3_DS 0xe033    /* GDT index 262 */
++#define FLAT_RING3_SS 0xe033    /* GDT index 262 */
++
++#define FLAT_KERNEL_CS FLAT_RING1_CS
++#define FLAT_KERNEL_DS FLAT_RING1_DS
++#define FLAT_KERNEL_SS FLAT_RING1_SS
++#define FLAT_USER_CS    FLAT_RING3_CS
++#define FLAT_USER_DS    FLAT_RING3_DS
++#define FLAT_USER_SS    FLAT_RING3_SS
++
++#define __HYPERVISOR_VIRT_START_PAE    0xF5800000
++#define __MACH2PHYS_VIRT_START_PAE     0xF5800000
++#define __MACH2PHYS_VIRT_END_PAE       0xF6800000
++#define HYPERVISOR_VIRT_START_PAE      \
++    mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
++#define MACH2PHYS_VIRT_START_PAE       \
++    mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
++#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
++#define HYPERVISOR_VIRT_START_NONPAE   \
++    mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
++#define MACH2PHYS_VIRT_START_NONPAE    \
++    mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
++#define MACH2PHYS_VIRT_END_NONPAE      \
++    mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
++
++#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
++#define __MACH2PHYS_VIRT_START  __MACH2PHYS_VIRT_START_PAE
++#define __MACH2PHYS_VIRT_END    __MACH2PHYS_VIRT_END_PAE
++
++#ifndef HYPERVISOR_VIRT_START
++#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
++#endif
++
++#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
++#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
++#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
++#ifndef machine_to_phys_mapping
++#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
++#endif
++
++/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
++#if defined(__XEN__) || defined(__XEN_TOOLS__)
++#undef ___DEFINE_XEN_GUEST_HANDLE
++#define ___DEFINE_XEN_GUEST_HANDLE(name, type)                  \
++    typedef struct { type *p; }                                 \
++        __guest_handle_ ## name;                                \
++    typedef struct { union { type *p; uint64_aligned_t q; }; }  \
++        __guest_handle_64_ ## name
++#undef set_xen_guest_handle
++#define set_xen_guest_handle(hnd, val)                      \
++    do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0;   \
++         (hnd).p = val;                                     \
++    } while ( 0 )
++#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
++#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
++#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
++#endif
++
++#ifndef __ASSEMBLY__
++
++struct cpu_user_regs {
++    uint32_t ebx;
++    uint32_t ecx;
++    uint32_t edx;
++    uint32_t esi;
++    uint32_t edi;
++    uint32_t ebp;
++    uint32_t eax;
++    uint16_t error_code;    /* private */
++    uint16_t entry_vector;  /* private */
++    uint32_t eip;
++    uint16_t cs;
++    uint8_t  saved_upcall_mask;
++    uint8_t  _pad0;
++    uint32_t eflags;        /* eflags.IF == !saved_upcall_mask */
++    uint32_t esp;
++    uint16_t ss, _pad1;
++    uint16_t es, _pad2;
++    uint16_t ds, _pad3;
++    uint16_t fs, _pad4;
++    uint16_t gs, _pad5;
++};
++typedef struct cpu_user_regs cpu_user_regs_t;
++DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
++
++/*
++ * Page-directory addresses above 4GB do not fit into architectural %cr3.
++ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
++ * must use the following accessor macros to pack/unpack valid MFNs.
++ */
++#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
++#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
++
++struct arch_vcpu_info {
++    unsigned long cr2;
++    unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
++};
++typedef struct arch_vcpu_info arch_vcpu_info_t;
++
++struct xen_callback {
++    unsigned long cs;
++    unsigned long eip;
++};
++typedef struct xen_callback xen_callback_t;
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/xen-x86_64.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,212 @@
++/******************************************************************************
++ * xen-x86_64.h
++ * 
++ * Guest OS interface to x86 64-bit 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_X86_64_H__
++#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
++
++/*
++ * Hypercall interface:
++ *  Input:  %rdi, %rsi, %rdx, %r10, %r8 (arguments 1-5)
++ *  Output: %rax
++ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
++ *  call hypercall_page + hypercall-number * 32
++ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
++ */
++
++#if __XEN_INTERFACE_VERSION__ < 0x00030203
++/*
++ * Legacy hypercall interface:
++ * As above, except the entry sequence to the hypervisor is:
++ *  mov $hypercall-number*32,%eax ; syscall
++ * Clobbered: %rcx, %r11, argument registers (as above)
++ */
++#define TRAP_INSTR "syscall"
++#endif
++
++/*
++ * 64-bit segment selectors
++ * These flat segments are in the Xen-private section of every GDT. Since these
++ * are also present in the initial GDT, many OSes will be able to avoid
++ * installing their own GDT.
++ */
++
++#define FLAT_RING3_CS32 0xe023  /* GDT index 260 */
++#define FLAT_RING3_CS64 0xe033  /* GDT index 261 */
++#define FLAT_RING3_DS32 0xe02b  /* GDT index 262 */
++#define FLAT_RING3_DS64 0x0000  /* NULL selector */
++#define FLAT_RING3_SS32 0xe02b  /* GDT index 262 */
++#define FLAT_RING3_SS64 0xe02b  /* GDT index 262 */
++
++#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
++#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
++#define FLAT_KERNEL_DS   FLAT_KERNEL_DS64
++#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
++#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
++#define FLAT_KERNEL_CS   FLAT_KERNEL_CS64
++#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
++#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
++#define FLAT_KERNEL_SS   FLAT_KERNEL_SS64
++
++#define FLAT_USER_DS64 FLAT_RING3_DS64
++#define FLAT_USER_DS32 FLAT_RING3_DS32
++#define FLAT_USER_DS   FLAT_USER_DS64
++#define FLAT_USER_CS64 FLAT_RING3_CS64
++#define FLAT_USER_CS32 FLAT_RING3_CS32
++#define FLAT_USER_CS   FLAT_USER_CS64
++#define FLAT_USER_SS64 FLAT_RING3_SS64
++#define FLAT_USER_SS32 FLAT_RING3_SS32
++#define FLAT_USER_SS   FLAT_USER_SS64
++
++#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
++#define __HYPERVISOR_VIRT_END   0xFFFF880000000000
++#define __MACH2PHYS_VIRT_START  0xFFFF800000000000
++#define __MACH2PHYS_VIRT_END    0xFFFF804000000000
++
++#ifndef HYPERVISOR_VIRT_START
++#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
++#define HYPERVISOR_VIRT_END   mk_unsigned_long(__HYPERVISOR_VIRT_END)
++#endif
++
++#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
++#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
++#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
++#ifndef machine_to_phys_mapping
++#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
++#endif
++
++/*
++ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
++ *  @which == SEGBASE_*  ;  @base == 64-bit base address
++ * Returns 0 on success.
++ */
++#define SEGBASE_FS          0
++#define SEGBASE_GS_USER     1
++#define SEGBASE_GS_KERNEL   2
++#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
++
++/*
++ * int HYPERVISOR_iret(void)
++ * All arguments are on the kernel stack, in the following format.
++ * Never returns if successful. Current kernel context is lost.
++ * The saved CS is mapped as follows:
++ *   RING0 -> RING3 kernel mode.
++ *   RING1 -> RING3 kernel mode.
++ *   RING2 -> RING3 kernel mode.
++ *   RING3 -> RING3 user mode.
++ * However RING0 indicates that the guest kernel should return to iteself
++ * directly with
++ *      orb   $3,1*8(%rsp)
++ *      iretq
++ * If flags contains VGCF_in_syscall:
++ *   Restore RAX, RIP, RFLAGS, RSP.
++ *   Discard R11, RCX, CS, SS.
++ * Otherwise:
++ *   Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
++ * All other registers are saved on hypercall entry and restored to user.
++ */
++/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
++#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. */
++};
++
++#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; \
++    uint32_t _e ## name; \
++}
++#else
++/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
++#define __DECL_REG(name) uint64_t r ## name
++#endif
++
++struct cpu_user_regs {
++    uint64_t r15;
++    uint64_t r14;
++    uint64_t r13;
++    uint64_t r12;
++    __DECL_REG(bp);
++    __DECL_REG(bx);
++    uint64_t r11;
++    uint64_t r10;
++    uint64_t r9;
++    uint64_t r8;
++    __DECL_REG(ax);
++    __DECL_REG(cx);
++    __DECL_REG(dx);
++    __DECL_REG(si);
++    __DECL_REG(di);
++    uint32_t error_code;    /* private */
++    uint32_t entry_vector;  /* private */
++    __DECL_REG(ip);
++    uint16_t cs, _pad0[1];
++    uint8_t  saved_upcall_mask;
++    uint8_t  _pad1[3];
++    __DECL_REG(flags);      /* rflags.IF == !saved_upcall_mask */
++    __DECL_REG(sp);
++    uint16_t ss, _pad2[3];
++    uint16_t es, _pad3[3];
++    uint16_t ds, _pad4[3];
++    uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base.     */
++    uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
++};
++typedef struct cpu_user_regs cpu_user_regs_t;
++DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
++
++#undef __DECL_REG
++
++#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
++#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
++
++struct arch_vcpu_info {
++    unsigned long cr2;
++    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
++};
++typedef struct arch_vcpu_info arch_vcpu_info_t;
++
++typedef unsigned long xen_callback_t;
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86/xen.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,200 @@
++/******************************************************************************
++ * 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 legacy multi-processor guests. */
++#define XEN_LEGACY_MAX_VCPUS 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:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86_32.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,27 @@
++/******************************************************************************
++ * arch-x86_32.h
++ * 
++ * Guest OS interface to x86 32-bit 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 "arch-x86/xen.h"
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/arch-x86_64.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,27 @@
++/******************************************************************************
++ * arch-x86_64.h
++ * 
++ * Guest OS interface to x86 64-bit 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 "arch-x86/xen.h"
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/dom0_ops.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,120 @@
++/******************************************************************************
++ * dom0_ops.h
++ * 
++ * Process command requests from domain-0 guest OS.
++ * 
++ * 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) 2002-2003, B Dragovic
++ * Copyright (c) 2002-2006, K Fraser
++ */
++
++#ifndef __XEN_PUBLIC_DOM0_OPS_H__
++#define __XEN_PUBLIC_DOM0_OPS_H__
++
++#include "xen.h"
++#include "platform.h"
++
++#if __XEN_INTERFACE_VERSION__ >= 0x00030204
++#error "dom0_ops.h is a compatibility interface only"
++#endif
++
++#define DOM0_INTERFACE_VERSION XENPF_INTERFACE_VERSION
++
++#define DOM0_SETTIME          XENPF_settime
++#define dom0_settime          xenpf_settime
++#define dom0_settime_t        xenpf_settime_t
++
++#define DOM0_ADD_MEMTYPE      XENPF_add_memtype
++#define dom0_add_memtype      xenpf_add_memtype
++#define dom0_add_memtype_t    xenpf_add_memtype_t
++
++#define DOM0_DEL_MEMTYPE      XENPF_del_memtype
++#define dom0_del_memtype      xenpf_del_memtype
++#define dom0_del_memtype_t    xenpf_del_memtype_t
++
++#define DOM0_READ_MEMTYPE     XENPF_read_memtype
++#define dom0_read_memtype     xenpf_read_memtype
++#define dom0_read_memtype_t   xenpf_read_memtype_t
++
++#define DOM0_MICROCODE        XENPF_microcode_update
++#define dom0_microcode        xenpf_microcode_update
++#define dom0_microcode_t      xenpf_microcode_update_t
++
++#define DOM0_PLATFORM_QUIRK   XENPF_platform_quirk
++#define dom0_platform_quirk   xenpf_platform_quirk
++#define dom0_platform_quirk_t xenpf_platform_quirk_t
++
++typedef uint64_t cpumap_t;
++
++/* Unsupported legacy operation -- defined for API compatibility. */
++#define DOM0_MSR                 15
++struct dom0_msr {
++    /* IN variables. */
++    uint32_t write;
++    cpumap_t cpu_mask;
++    uint32_t msr;
++    uint32_t in1;
++    uint32_t in2;
++    /* OUT variables. */
++    uint32_t out1;
++    uint32_t out2;
++};
++typedef struct dom0_msr dom0_msr_t;
++DEFINE_XEN_GUEST_HANDLE(dom0_msr_t);
++
++/* Unsupported legacy operation -- defined for API compatibility. */
++#define DOM0_PHYSICAL_MEMORY_MAP 40
++struct dom0_memory_map_entry {
++    uint64_t start, end;
++    uint32_t flags; /* reserved */
++    uint8_t  is_ram;
++};
++typedef struct dom0_memory_map_entry dom0_memory_map_entry_t;
++DEFINE_XEN_GUEST_HANDLE(dom0_memory_map_entry_t);
++
++struct dom0_op {
++    uint32_t cmd;
++    uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
++    union {
++        struct dom0_msr               msr;
++        struct dom0_settime           settime;
++        struct dom0_add_memtype       add_memtype;
++        struct dom0_del_memtype       del_memtype;
++        struct dom0_read_memtype      read_memtype;
++        struct dom0_microcode         microcode;
++        struct dom0_platform_quirk    platform_quirk;
++        struct dom0_memory_map_entry  physical_memory_map;
++        uint8_t                       pad[128];
++    } u;
++};
++typedef struct dom0_op dom0_op_t;
++DEFINE_XEN_GUEST_HANDLE(dom0_op_t);
++
++#endif /* __XEN_PUBLIC_DOM0_OPS_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/domctl.h	2010-01-07 09:38:29.000000000 +0100
+@@ -0,0 +1,904 @@
++/******************************************************************************
++ * domctl.h
++ * 
++ * Domain management operations. For use by node control stack.
++ * 
++ * 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) 2002-2003, B Dragovic
++ * Copyright (c) 2002-2006, K Fraser
++ */
++
++#ifndef __XEN_PUBLIC_DOMCTL_H__
++#define __XEN_PUBLIC_DOMCTL_H__
++
++#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
++#error "domctl operations are intended for use by node control tools only"
++#endif
++
++#include "xen.h"
++#include "grant_table.h"
++
++#define XEN_DOMCTL_INTERFACE_VERSION 0x00000006
++
++struct xenctl_cpumap {
++    XEN_GUEST_HANDLE_64(uint8) bitmap;
++    uint32_t nr_cpus;
++};
++
++/*
++ * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
++ * If it is specified as zero, an id is auto-allocated and returned.
++ */
++/* XEN_DOMCTL_createdomain */
++struct xen_domctl_createdomain {
++    /* IN parameters */
++    uint32_t ssidref;
++    xen_domain_handle_t handle;
++ /* 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)
++ /* Should domain memory integrity be verifed by tboot during Sx? */
++#define _XEN_DOMCTL_CDF_s3_integrity  2
++#define XEN_DOMCTL_CDF_s3_integrity   (1U<<_XEN_DOMCTL_CDF_s3_integrity)
++    uint32_t flags;
++ /* Disable out-of-sync shadow page tables? */
++#define _XEN_DOMCTL_CDF_oos_off       3
++#define XEN_DOMCTL_CDF_oos_off        (1U<<_XEN_DOMCTL_CDF_oos_off)
++};
++typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
++
++/* XEN_DOMCTL_getdomaininfo */
++struct xen_domctl_getdomaininfo {
++    /* OUT variables. */
++    domid_t  domain;              /* Also echoed in domctl.domain */
++ /* Domain is scheduled to die. */
++#define _XEN_DOMINF_dying     0
++#define XEN_DOMINF_dying      (1U<<_XEN_DOMINF_dying)
++ /* Domain is an HVM guest (as opposed to a PV guest). */
++#define _XEN_DOMINF_hvm_guest 1
++#define XEN_DOMINF_hvm_guest  (1U<<_XEN_DOMINF_hvm_guest)
++ /* The guest OS has shut down. */
++#define _XEN_DOMINF_shutdown  2
++#define XEN_DOMINF_shutdown   (1U<<_XEN_DOMINF_shutdown)
++ /* Currently paused by control software. */
++#define _XEN_DOMINF_paused    3
++#define XEN_DOMINF_paused     (1U<<_XEN_DOMINF_paused)
++ /* Currently blocked pending an event.     */
++#define _XEN_DOMINF_blocked   4
++#define XEN_DOMINF_blocked    (1U<<_XEN_DOMINF_blocked)
++ /* Domain is currently running.            */
++#define _XEN_DOMINF_running   5
++#define XEN_DOMINF_running    (1U<<_XEN_DOMINF_running)
++ /* Being debugged.  */
++#define _XEN_DOMINF_debugged  6
++#define XEN_DOMINF_debugged   (1U<<_XEN_DOMINF_debugged)
++ /* XEN_DOMINF_shutdown guest-supplied code.  */
++#define XEN_DOMINF_shutdownmask 255
++#define XEN_DOMINF_shutdownshift 16
++    uint32_t flags;              /* XEN_DOMINF_* */
++    uint64_aligned_t tot_pages;
++    uint64_aligned_t max_pages;
++    uint64_aligned_t shr_pages;
++    uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
++    uint64_aligned_t cpu_time;
++    uint32_t nr_online_vcpus;    /* Number of VCPUs currently online. */
++    uint32_t max_vcpu_id;        /* Maximum VCPUID in use by this domain. */
++    uint32_t ssidref;
++    xen_domain_handle_t handle;
++};
++typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t);
++
++
++/* XEN_DOMCTL_getmemlist */
++struct xen_domctl_getmemlist {
++    /* IN variables. */
++    /* Max entries to write to output buffer. */
++    uint64_aligned_t max_pfns;
++    /* Start index in guest's page list. */
++    uint64_aligned_t start_pfn;
++    XEN_GUEST_HANDLE_64(uint64) buffer;
++    /* OUT variables. */
++    uint64_aligned_t num_pfns;
++};
++typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
++
++
++/* XEN_DOMCTL_getpageframeinfo */
++
++#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28
++#define XEN_DOMCTL_PFINFO_NOTAB   (0x0U<<28)
++#define XEN_DOMCTL_PFINFO_L1TAB   (0x1U<<28)
++#define XEN_DOMCTL_PFINFO_L2TAB   (0x2U<<28)
++#define XEN_DOMCTL_PFINFO_L3TAB   (0x3U<<28)
++#define XEN_DOMCTL_PFINFO_L4TAB   (0x4U<<28)
++#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
++#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
++#define XEN_DOMCTL_PFINFO_XTAB    (0xfU<<28) /* invalid page */
++#define XEN_DOMCTL_PFINFO_PAGEDTAB (0x8U<<28)
++#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)
++
++struct xen_domctl_getpageframeinfo {
++    /* IN variables. */
++    uint64_aligned_t gmfn; /* GMFN to query */
++    /* OUT variables. */
++    /* Is the page PINNED to a type? */
++    uint32_t type;         /* see above type defs */
++};
++typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t);
++
++
++/* XEN_DOMCTL_getpageframeinfo2 */
++struct xen_domctl_getpageframeinfo2 {
++    /* IN variables. */
++    uint64_aligned_t num;
++    /* IN/OUT variables. */
++    XEN_GUEST_HANDLE_64(uint32) array;
++};
++typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t);
++
++
++/*
++ * Control shadow pagetables operation
++ */
++/* XEN_DOMCTL_shadow_op */
++
++/* Disable shadow mode. */
++#define XEN_DOMCTL_SHADOW_OP_OFF         0
++
++/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */
++#define XEN_DOMCTL_SHADOW_OP_ENABLE      32
++
++/* Log-dirty bitmap operations. */
++ /* Return the bitmap and clean internal copy for next round. */
++#define XEN_DOMCTL_SHADOW_OP_CLEAN       11
++ /* Return the bitmap but do not modify internal copy. */
++#define XEN_DOMCTL_SHADOW_OP_PEEK        12
++
++/* Memory allocation accessors. */
++#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION   30
++#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION   31
++
++/* Legacy enable operations. */
++ /* Equiv. to ENABLE with no mode flags. */
++#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST       1
++ /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */
++#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY   2
++ /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */
++#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE  3
++
++/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */
++ /*
++  * Shadow pagetables are refcounted: guest does not use explicit mmu
++  * operations nor write-protect its pagetables.
++  */
++#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT  (1 << 1)
++ /*
++  * Log pages in a bitmap as they are dirtied.
++  * Used for live relocation to determine which pages must be re-sent.
++  */
++#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
++ /*
++  * Automatically translate GPFNs into MFNs.
++  */
++#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
++ /*
++  * Xen does not steal virtual address space from the guest.
++  * Requires HVM support.
++  */
++#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL  (1 << 4)
++
++struct xen_domctl_shadow_op_stats {
++    uint32_t fault_count;
++    uint32_t dirty_count;
++};
++typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t);
++
++struct xen_domctl_shadow_op {
++    /* IN variables. */
++    uint32_t       op;       /* XEN_DOMCTL_SHADOW_OP_* */
++
++    /* OP_ENABLE */
++    uint32_t       mode;     /* XEN_DOMCTL_SHADOW_ENABLE_* */
++
++    /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */
++    uint32_t       mb;       /* Shadow memory allocation in MB */
++
++    /* OP_PEEK / OP_CLEAN */
++    XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
++    uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */
++    struct xen_domctl_shadow_op_stats stats;
++};
++typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t);
++
++
++/* XEN_DOMCTL_max_mem */
++struct xen_domctl_max_mem {
++    /* IN variables. */
++    uint64_aligned_t max_memkb;
++};
++typedef struct xen_domctl_max_mem xen_domctl_max_mem_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t);
++
++
++/* XEN_DOMCTL_setvcpucontext */
++/* XEN_DOMCTL_getvcpucontext */
++struct xen_domctl_vcpucontext {
++    uint32_t              vcpu;                  /* IN */
++    XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */
++};
++typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t);
++
++
++/* XEN_DOMCTL_getvcpuinfo */
++struct xen_domctl_getvcpuinfo {
++    /* IN variables. */
++    uint32_t vcpu;
++    /* OUT variables. */
++    uint8_t  online;                  /* currently online (not hotplugged)? */
++    uint8_t  blocked;                 /* blocked waiting for an event? */
++    uint8_t  running;                 /* currently scheduled on its CPU? */
++    uint64_aligned_t cpu_time;        /* total cpu time consumed (ns) */
++    uint32_t cpu;                     /* current mapping   */
++};
++typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t);
++
++
++/* Get/set which physical cpus a vcpu can execute on. */
++/* XEN_DOMCTL_setvcpuaffinity */
++/* XEN_DOMCTL_getvcpuaffinity */
++struct xen_domctl_vcpuaffinity {
++    uint32_t  vcpu;              /* IN */
++    struct xenctl_cpumap cpumap; /* IN/OUT */
++};
++typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
++
++
++/* XEN_DOMCTL_max_vcpus */
++struct xen_domctl_max_vcpus {
++    uint32_t max;           /* maximum number of vcpus */
++};
++typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
++
++
++/* XEN_DOMCTL_scheduler_op */
++/* Scheduler types. */
++#define XEN_SCHEDULER_SEDF     4
++#define XEN_SCHEDULER_CREDIT   5
++/* Set or get info? */
++#define XEN_DOMCTL_SCHEDOP_putinfo 0
++#define XEN_DOMCTL_SCHEDOP_getinfo 1
++struct xen_domctl_scheduler_op {
++    uint32_t sched_id;  /* XEN_SCHEDULER_* */
++    uint32_t cmd;       /* XEN_DOMCTL_SCHEDOP_* */
++    union {
++        struct xen_domctl_sched_sedf {
++            uint64_aligned_t period;
++            uint64_aligned_t slice;
++            uint64_aligned_t latency;
++            uint32_t extratime;
++            uint32_t weight;
++        } sedf;
++        struct xen_domctl_sched_credit {
++            uint16_t weight;
++            uint16_t cap;
++        } credit;
++    } u;
++};
++typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t);
++
++
++/* XEN_DOMCTL_setdomainhandle */
++struct xen_domctl_setdomainhandle {
++    xen_domain_handle_t handle;
++};
++typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t);
++
++
++/* XEN_DOMCTL_setdebugging */
++struct xen_domctl_setdebugging {
++    uint8_t enable;
++};
++typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t);
++
++
++/* XEN_DOMCTL_irq_permission */
++struct xen_domctl_irq_permission {
++    uint8_t pirq;
++    uint8_t allow_access;    /* flag to specify enable/disable of IRQ access */
++};
++typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t);
++
++
++/* XEN_DOMCTL_iomem_permission */
++struct xen_domctl_iomem_permission {
++    uint64_aligned_t first_mfn;/* first page (physical page number) in range */
++    uint64_aligned_t nr_mfns;  /* number of pages in range (>0) */
++    uint8_t  allow_access;     /* allow (!0) or deny (0) access to range? */
++};
++typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t);
++
++
++/* XEN_DOMCTL_ioport_permission */
++struct xen_domctl_ioport_permission {
++    uint32_t first_port;              /* first port int range */
++    uint32_t nr_ports;                /* size of port range */
++    uint8_t  allow_access;            /* allow or deny access to range? */
++};
++typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
++
++
++/* XEN_DOMCTL_hypercall_init */
++struct xen_domctl_hypercall_init {
++    uint64_aligned_t  gmfn;           /* GMFN to be initialised */
++};
++typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
++
++
++/* XEN_DOMCTL_arch_setup */
++#define _XEN_DOMAINSETUP_hvm_guest 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__
++    uint64_aligned_t bp;     /* mpaddr of boot param area */
++    uint64_aligned_t maxmem; /* Highest memory address for MDT.  */
++    uint64_aligned_t xsi_va; /* Xen shared_info area virtual address.  */
++    uint32_t hypercall_imm;  /* Break imm for Xen hypercalls.  */
++    int8_t vhpt_size_log2;   /* Log2 of VHPT size. */
++#endif
++} xen_domctl_arch_setup_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t);
++
++
++/* XEN_DOMCTL_settimeoffset */
++struct xen_domctl_settimeoffset {
++    int32_t  time_offset_seconds; /* applied to domain wallclock time */
++};
++typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
++
++/* XEN_DOMCTL_gethvmcontext */
++/* XEN_DOMCTL_sethvmcontext */
++typedef struct xen_domctl_hvmcontext {
++    uint32_t size; /* IN/OUT: size of buffer / bytes filled */
++    XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call
++                                        * gethvmcontext with NULL
++                                        * buffer to get size req'd */
++} xen_domctl_hvmcontext_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
++
++
++/* XEN_DOMCTL_set_address_size */
++/* XEN_DOMCTL_get_address_size */
++typedef struct xen_domctl_address_size {
++    uint32_t size;
++} xen_domctl_address_size_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
++
++
++/* XEN_DOMCTL_real_mode_area */
++struct xen_domctl_real_mode_area {
++    uint32_t log; /* log2 of Real Mode Area size */
++};
++typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
++
++
++/* XEN_DOMCTL_sendtrigger */
++#define XEN_DOMCTL_SENDTRIGGER_NMI    0
++#define XEN_DOMCTL_SENDTRIGGER_RESET  1
++#define XEN_DOMCTL_SENDTRIGGER_INIT   2
++#define XEN_DOMCTL_SENDTRIGGER_POWER  3
++struct xen_domctl_sendtrigger {
++    uint32_t  trigger;  /* IN */
++    uint32_t  vcpu;     /* IN */
++};
++typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
++
++
++/* Assign PCI device to HVM guest. Sets up IOMMU structures. */
++/* XEN_DOMCTL_assign_device */
++/* XEN_DOMCTL_test_assign_device */
++/* XEN_DOMCTL_deassign_device */
++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 */
++/* XEN_DOMCTL_get_device_group */
++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. */
++/* XEN_DOMCTL_bind_pt_irq */
++/* XEN_DOMCTL_unbind_pt_irq */
++typedef enum pt_irq_type_e {
++    PT_IRQ_TYPE_PCI,
++    PT_IRQ_TYPE_ISA,
++    PT_IRQ_TYPE_MSI,
++    PT_IRQ_TYPE_MSI_TRANSLATE,
++} pt_irq_type_t;
++struct xen_domctl_bind_pt_irq {
++    uint32_t machine_irq;
++    pt_irq_type_t irq_type;
++    uint32_t hvm_domid;
++
++    union {
++        struct {
++            uint8_t isa_irq;
++        } isa;
++        struct {
++            uint8_t bus;
++            uint8_t device;
++            uint8_t intx;
++        } pci;
++        struct {
++            uint8_t gvec;
++            uint32_t gflags;
++            uint64_aligned_t gtable;
++        } msi;
++    } u;
++};
++typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t);
++
++
++/* Bind machine I/O address range -> HVM address range. */
++/* XEN_DOMCTL_memory_mapping */
++#define DPCI_ADD_MAPPING         1
++#define DPCI_REMOVE_MAPPING      0
++struct xen_domctl_memory_mapping {
++    uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */
++    uint64_aligned_t first_mfn; /* first page (machine page) in range */
++    uint64_aligned_t nr_mfns;   /* number of pages in range (>0) */
++    uint32_t add_mapping;       /* add or remove mapping */
++    uint32_t padding;           /* padding for 64-bit aligned structure */
++};
++typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t);
++
++
++/* Bind machine I/O port range -> HVM I/O port range. */
++/* XEN_DOMCTL_ioport_mapping */
++struct xen_domctl_ioport_mapping {
++    uint32_t first_gport;     /* first guest IO port*/
++    uint32_t first_mport;     /* first machine IO port */
++    uint32_t nr_ports;        /* size of port range */
++    uint32_t add_mapping;     /* add or remove mapping */
++};
++typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
++
++
++/*
++ * Pin caching type of RAM space for x86 HVM domU.
++ */
++/* XEN_DOMCTL_pin_mem_cacheattr */
++/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
++#define XEN_DOMCTL_MEM_CACHEATTR_UC  0
++#define XEN_DOMCTL_MEM_CACHEATTR_WC  1
++#define XEN_DOMCTL_MEM_CACHEATTR_WT  4
++#define XEN_DOMCTL_MEM_CACHEATTR_WP  5
++#define XEN_DOMCTL_MEM_CACHEATTR_WB  6
++#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
++struct xen_domctl_pin_mem_cacheattr {
++    uint64_aligned_t start, end;
++    uint32_t type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
++};
++typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
++
++
++/* XEN_DOMCTL_set_ext_vcpucontext */
++/* XEN_DOMCTL_get_ext_vcpucontext */
++struct xen_domctl_ext_vcpucontext {
++    /* IN: VCPU that this call applies to. */
++    uint32_t         vcpu;
++    /*
++     * SET: Size of struct (IN)
++     * GET: Size of struct (OUT)
++     */
++    uint32_t         size;
++#if defined(__i386__) || defined(__x86_64__)
++    /* SYSCALL from 32-bit mode and SYSENTER callback information. */
++    /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */
++    uint64_aligned_t syscall32_callback_eip;
++    uint64_aligned_t sysenter_callback_eip;
++    uint16_t         syscall32_callback_cs;
++    uint16_t         sysenter_callback_cs;
++    uint8_t          syscall32_disables_events;
++    uint8_t          sysenter_disables_events;
++#endif
++};
++typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t);
++
++/*
++ * Set optimizaton features for a domain
++ */
++/* XEN_DOMCTL_set_opt_feature */
++struct xen_domctl_set_opt_feature {
++#if defined(__ia64__)
++    struct xen_ia64_opt_feature optf;
++#else
++    /* Make struct non-empty: do not depend on this field name! */
++    uint64_t dummy;
++#endif
++};
++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
++ */
++/* XEN_DOMCTL_set_target */
++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
++/* XEN_DOMCTL_set_cpuid */
++struct xen_domctl_cpuid {
++  uint32_t input[2];
++  uint32_t eax;
++  uint32_t ebx;
++  uint32_t ecx;
++  uint32_t edx;
++};
++typedef struct xen_domctl_cpuid xen_domctl_cpuid_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t);
++#endif
++
++/* XEN_DOMCTL_subscribe */
++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.
++ */
++/* XEN_DOMCTL_set_machine_address_size */
++/* XEN_DOMCTL_get_machine_address_size */
++
++/*
++ * Do not inject spurious page faults into this domain.
++ */
++/* XEN_DOMCTL_suppress_spurious_page_faults */
++
++/* XEN_DOMCTL_debug_op */
++#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF         0
++#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON          1
++struct xen_domctl_debug_op {
++    uint32_t op;   /* IN */
++    uint32_t vcpu; /* IN */
++};
++typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
++
++/*
++ * Request a particular record from the HVM context
++ */
++/* XEN_DOMCTL_gethvmcontext_partial */
++typedef struct xen_domctl_hvmcontext_partial {
++    uint32_t type;                      /* IN: Type of record required */
++    uint32_t instance;                  /* IN: Instance of that type */
++    XEN_GUEST_HANDLE_64(uint8) buffer;  /* OUT: buffer to write record into */
++} xen_domctl_hvmcontext_partial_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
++
++/* XEN_DOMCTL_disable_migrate */
++typedef struct xen_domctl_disable_migrate {
++    uint32_t disable; /* IN: 1: disable migration and restore */
++} xen_domctl_disable_migrate_t;
++
++
++/* XEN_DOMCTL_gettscinfo */
++/* XEN_DOMCTL_settscinfo */
++struct xen_guest_tsc_info {
++    uint32_t tsc_mode;
++    uint32_t gtsc_khz;
++    uint32_t incarnation;
++    uint32_t pad;
++    uint64_aligned_t elapsed_nsec;
++};
++typedef struct xen_guest_tsc_info xen_guest_tsc_info_t;
++DEFINE_XEN_GUEST_HANDLE(xen_guest_tsc_info_t);
++typedef struct xen_domctl_tsc_info {
++    XEN_GUEST_HANDLE_64(xen_guest_tsc_info_t) out_info; /* OUT */
++    xen_guest_tsc_info_t info; /* IN */
++} xen_domctl_tsc_info_t;
++
++/* XEN_DOMCTL_gdbsx_guestmemio      guest mem io */
++struct xen_domctl_gdbsx_memio {
++    /* IN */
++    uint64_aligned_t pgd3val;/* optional: init_mm.pgd[3] value */
++    uint64_aligned_t gva;    /* guest virtual address */
++    uint64_aligned_t uva;    /* user buffer virtual address */
++    uint32_t         len;    /* number of bytes to read/write */
++    uint8_t          gwr;    /* 0 = read from guest. 1 = write to guest */
++    /* OUT */
++    uint32_t         remain; /* bytes remaining to be copied */
++};
++
++/* XEN_DOMCTL_gdbsx_pausevcpu */
++/* XEN_DOMCTL_gdbsx_unpausevcpu */
++struct xen_domctl_gdbsx_pauseunp_vcpu { /* pause/unpause a vcpu */
++    uint32_t         vcpu;         /* which vcpu */
++};
++
++/* XEN_DOMCTL_gdbsx_domstatus */
++struct xen_domctl_gdbsx_domstatus {
++    /* OUT */
++    uint8_t          paused;     /* is the domain paused */
++    uint32_t         vcpu_id;    /* any vcpu in an event? */
++    uint32_t         vcpu_ev;    /* if yes, what event? */
++};
++
++/*
++ * Memory event operations
++ */
++
++/* XEN_DOMCTL_mem_event_op */
++
++/* Add and remove memory handlers */
++#define XEN_DOMCTL_MEM_EVENT_OP_ENABLE     0
++#define XEN_DOMCTL_MEM_EVENT_OP_DISABLE    1
++
++/*
++ * Page memory in and out. 
++ */
++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING (1 << 0)
++
++/* Domain memory paging */
++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE   0
++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT      1
++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP       2
++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME     3
++
++struct xen_domctl_mem_event_op {
++    uint32_t       op;           /* XEN_DOMCTL_MEM_EVENT_OP_* */
++    uint32_t       mode;         /* XEN_DOMCTL_MEM_EVENT_ENABLE_* */
++
++    /* OP_ENABLE */
++    uint64_aligned_t shared_addr;  /* IN:  Virtual address of shared page */
++    uint64_aligned_t ring_addr;    /* IN:  Virtual address of ring page */
++
++    /* Other OPs */
++    uint64_aligned_t gfn;          /* IN:  gfn of page being operated on */
++};
++typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t);
++
++/*
++ * Memory sharing operations
++ */
++/* XEN_DOMCTL_mem_sharing_op */
++
++#define XEN_DOMCTL_MEM_SHARING_OP_CONTROL        0
++#define XEN_DOMCTL_MEM_SHARING_OP_NOMINATE_GFN   1
++#define XEN_DOMCTL_MEM_SHARING_OP_NOMINATE_GREF  2
++#define XEN_DOMCTL_MEM_SHARING_OP_SHARE          3
++#define XEN_DOMCTL_MEM_SHARING_OP_RESUME         4
++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_GFN      5
++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_MFN      6
++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_GREF     7
++
++#define XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID  (-10)
++#define XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID  (-9)
++
++struct xen_domctl_mem_sharing_op {
++    uint8_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */
++
++    union {
++        uint8_t enable;                   /* OP_CONTROL                */
++
++        struct mem_sharing_op_nominate {  /* OP_NOMINATE_xxx           */
++            union {
++                uint64_aligned_t gfn;     /* IN: gfn to nominate       */
++                uint32_t      grant_ref;  /* IN: grant ref to nominate */
++            } u;
++            uint64_aligned_t  handle;     /* OUT: the handle           */
++        } nominate;
++        struct mem_sharing_op_share {     /* OP_SHARE */
++            uint64_aligned_t source_handle; /* IN: handle to the source page */
++            uint64_aligned_t client_handle; /* IN: handle to the client page */
++        } share; 
++        struct mem_sharing_op_debug {     /* OP_DEBUG_xxx */
++            union {
++                uint64_aligned_t gfn;      /* IN: gfn to debug          */
++                uint64_aligned_t mfn;      /* IN: mfn to debug          */
++                grant_ref_t    gref;       /* IN: gref to debug         */
++            } u;
++        } debug;
++    } u;
++};
++typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_sharing_op_t);
++
++
++struct xen_domctl {
++    uint32_t cmd;
++#define XEN_DOMCTL_createdomain                   1
++#define XEN_DOMCTL_destroydomain                  2
++#define XEN_DOMCTL_pausedomain                    3
++#define XEN_DOMCTL_unpausedomain                  4
++#define XEN_DOMCTL_getdomaininfo                  5
++#define XEN_DOMCTL_getmemlist                     6
++#define XEN_DOMCTL_getpageframeinfo               7
++#define XEN_DOMCTL_getpageframeinfo2              8
++#define XEN_DOMCTL_setvcpuaffinity                9
++#define XEN_DOMCTL_shadow_op                     10
++#define XEN_DOMCTL_max_mem                       11
++#define XEN_DOMCTL_setvcpucontext                12
++#define XEN_DOMCTL_getvcpucontext                13
++#define XEN_DOMCTL_getvcpuinfo                   14
++#define XEN_DOMCTL_max_vcpus                     15
++#define XEN_DOMCTL_scheduler_op                  16
++#define XEN_DOMCTL_setdomainhandle               17
++#define XEN_DOMCTL_setdebugging                  18
++#define XEN_DOMCTL_irq_permission                19
++#define XEN_DOMCTL_iomem_permission              20
++#define XEN_DOMCTL_ioport_permission             21
++#define XEN_DOMCTL_hypercall_init                22
++#define XEN_DOMCTL_arch_setup                    23
++#define XEN_DOMCTL_settimeoffset                 24
++#define XEN_DOMCTL_getvcpuaffinity               25
++#define XEN_DOMCTL_real_mode_area                26
++#define XEN_DOMCTL_resumedomain                  27
++#define XEN_DOMCTL_sendtrigger                   28
++#define XEN_DOMCTL_subscribe                     29
++#define XEN_DOMCTL_gethvmcontext                 33
++#define XEN_DOMCTL_sethvmcontext                 34
++#define XEN_DOMCTL_set_address_size              35
++#define XEN_DOMCTL_get_address_size              36
++#define XEN_DOMCTL_assign_device                 37
++#define XEN_DOMCTL_bind_pt_irq                   38
++#define XEN_DOMCTL_memory_mapping                39
++#define XEN_DOMCTL_ioport_mapping                40
++#define XEN_DOMCTL_pin_mem_cacheattr             41
++#define XEN_DOMCTL_set_ext_vcpucontext           42
++#define XEN_DOMCTL_get_ext_vcpucontext           43
++#define XEN_DOMCTL_set_opt_feature               44
++#define XEN_DOMCTL_test_assign_device            45
++#define XEN_DOMCTL_set_target                    46
++#define XEN_DOMCTL_deassign_device               47
++#define XEN_DOMCTL_unbind_pt_irq                 48
++#define XEN_DOMCTL_set_cpuid                     49
++#define XEN_DOMCTL_get_device_group              50
++#define XEN_DOMCTL_set_machine_address_size      51
++#define XEN_DOMCTL_get_machine_address_size      52
++#define XEN_DOMCTL_suppress_spurious_page_faults 53
++#define XEN_DOMCTL_debug_op                      54
++#define XEN_DOMCTL_gethvmcontext_partial         55
++#define XEN_DOMCTL_mem_event_op                  56
++#define XEN_DOMCTL_mem_sharing_op                57
++#define XEN_DOMCTL_disable_migrate               58
++#define XEN_DOMCTL_gettscinfo                    59
++#define XEN_DOMCTL_settscinfo                    60
++#define XEN_DOMCTL_gdbsx_guestmemio            1000
++#define XEN_DOMCTL_gdbsx_pausevcpu             1001
++#define XEN_DOMCTL_gdbsx_unpausevcpu           1002
++#define XEN_DOMCTL_gdbsx_domstatus             1003
++    uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
++    domid_t  domain;
++    union {
++        struct xen_domctl_createdomain      createdomain;
++        struct xen_domctl_getdomaininfo     getdomaininfo;
++        struct xen_domctl_getmemlist        getmemlist;
++        struct xen_domctl_getpageframeinfo  getpageframeinfo;
++        struct xen_domctl_getpageframeinfo2 getpageframeinfo2;
++        struct xen_domctl_vcpuaffinity      vcpuaffinity;
++        struct xen_domctl_shadow_op         shadow_op;
++        struct xen_domctl_max_mem           max_mem;
++        struct xen_domctl_vcpucontext       vcpucontext;
++        struct xen_domctl_getvcpuinfo       getvcpuinfo;
++        struct xen_domctl_max_vcpus         max_vcpus;
++        struct xen_domctl_scheduler_op      scheduler_op;
++        struct xen_domctl_setdomainhandle   setdomainhandle;
++        struct xen_domctl_setdebugging      setdebugging;
++        struct xen_domctl_irq_permission    irq_permission;
++        struct xen_domctl_iomem_permission  iomem_permission;
++        struct xen_domctl_ioport_permission ioport_permission;
++        struct xen_domctl_hypercall_init    hypercall_init;
++        struct xen_domctl_arch_setup        arch_setup;
++        struct xen_domctl_settimeoffset     settimeoffset;
++        struct xen_domctl_disable_migrate   disable_migrate;
++        struct xen_domctl_tsc_info          tsc_info;
++        struct xen_domctl_real_mode_area    real_mode_area;
++        struct xen_domctl_hvmcontext        hvmcontext;
++        struct xen_domctl_hvmcontext_partial hvmcontext_partial;
++        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;
++        struct xen_domctl_ioport_mapping    ioport_mapping;
++        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;
++        struct xen_domctl_debug_op          debug_op;
++        struct xen_domctl_mem_event_op      mem_event_op;
++        struct xen_domctl_mem_sharing_op    mem_sharing_op;
++#if defined(__i386__) || defined(__x86_64__)
++        struct xen_domctl_cpuid             cpuid;
++#endif
++        struct xen_domctl_gdbsx_memio       gdbsx_guest_memio;
++        struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
++        struct xen_domctl_gdbsx_domstatus   gdbsx_domstatus;
++        uint8_t                             pad[128];
++    } u;
++};
++typedef struct xen_domctl xen_domctl_t;
++DEFINE_XEN_GUEST_HANDLE(xen_domctl_t);
++
++#endif /* __XEN_PUBLIC_DOMCTL_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/e820.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,34 @@
++
++/*
++ * 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_PUBLIC_HVM_E820_H__
++#define __XEN_PUBLIC_HVM_E820_H__
++
++/* E820 location in HVM virtual address space. */
++#define HVM_E820_PAGE        0x00090000
++#define HVM_E820_NR_OFFSET   0x000001E8
++#define HVM_E820_OFFSET      0x000002D0
++
++#define HVM_BELOW_4G_RAM_END        0xF0000000
++#define HVM_BELOW_4G_MMIO_START     HVM_BELOW_4G_RAM_END
++#define HVM_BELOW_4G_MMIO_LENGTH    ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
++
++#endif /* __XEN_PUBLIC_HVM_E820_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/hvm_info_table.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,75 @@
++/******************************************************************************
++ * hvm/hvm_info_table.h
++ * 
++ * HVM parameter and information table, written into guest memory map.
++ *
++ * 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_PUBLIC_HVM_HVM_INFO_TABLE_H__
++#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
++
++#define HVM_INFO_PFN         0x09F
++#define HVM_INFO_OFFSET      0x800
++#define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
++
++/* Maximum we can support with current vLAPIC ID mapping. */
++#define HVM_MAX_VCPUS        128
++
++struct hvm_info_table {
++    char        signature[8]; /* "HVM INFO" */
++    uint32_t    length;
++    uint8_t     checksum;
++
++    /* Should firmware build ACPI tables? */
++    uint8_t     acpi_enabled;
++
++    /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */
++    uint8_t     apic_mode;
++
++    /* How many CPUs does this domain have? */
++    uint32_t    nr_vcpus;
++
++    /*
++     * MEMORY MAP provided by HVM domain builder.
++     * Notes:
++     *  1. page_to_phys(x) = x << 12
++     *  2. If a field is zero, the corresponding range does not exist.
++     */
++    /*
++     *  0x0 to page_to_phys(low_mem_pgend)-1:
++     *    RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF)
++     */
++    uint32_t    low_mem_pgend;
++    /*
++     *  page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF:
++     *    Reserved for special memory mappings
++     */
++    uint32_t    reserved_mem_pgstart;
++    /*
++     *  0x100000000 to page_to_phys(high_mem_pgend)-1:
++     *    RAM above 4GB
++     */
++    uint32_t    high_mem_pgend;
++
++    /* Bitmap of which CPUs are online at boot time. */
++    uint8_t     vcpu_online[HVM_MAX_VCPUS/8];
++};
++
++#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/hvm_op.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,133 @@
++/*
++ * 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_PUBLIC_HVM_HVM_OP_H__
++#define __XEN_PUBLIC_HVM_HVM_OP_H__
++
++#include "../xen.h"
++
++/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
++#define HVMOP_set_param           0
++#define HVMOP_get_param           1
++struct xen_hvm_param {
++    domid_t  domid;    /* IN */
++    uint32_t index;    /* IN */
++    uint64_t value;    /* IN/OUT */
++};
++typedef struct xen_hvm_param xen_hvm_param_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
++
++/* Set the logical level of one of a domain's PCI INTx wires. */
++#define HVMOP_set_pci_intx_level  2
++struct xen_hvm_set_pci_intx_level {
++    /* Domain to be updated. */
++    domid_t  domid;
++    /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
++    uint8_t  domain, bus, device, intx;
++    /* Assertion level (0 = unasserted, 1 = asserted). */
++    uint8_t  level;
++};
++typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
++
++/* Set the logical level of one of a domain's ISA IRQ wires. */
++#define HVMOP_set_isa_irq_level   3
++struct xen_hvm_set_isa_irq_level {
++    /* Domain to be updated. */
++    domid_t  domid;
++    /* ISA device identification, by ISA IRQ (0-15). */
++    uint8_t  isa_irq;
++    /* Assertion level (0 = unasserted, 1 = asserted). */
++    uint8_t  level;
++};
++typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
++
++#define HVMOP_set_pci_link_route  4
++struct xen_hvm_set_pci_link_route {
++    /* Domain to be updated. */
++    domid_t  domid;
++    /* PCI link identifier (0-3). */
++    uint8_t  link;
++    /* ISA IRQ (1-15), or 0 (disable link). */
++    uint8_t  isa_irq;
++};
++typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
++
++/* 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/ioreq.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,119 @@
++/*
++ * ioreq.h: I/O request definitions for device models
++ * Copyright (c) 2004, Intel Corporation.
++ * 
++ * 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 _IOREQ_H_
++#define _IOREQ_H_
++
++#define IOREQ_READ      1
++#define IOREQ_WRITE     0
++
++#define STATE_IOREQ_NONE        0
++#define STATE_IOREQ_READY       1
++#define STATE_IOREQ_INPROCESS   2
++#define STATE_IORESP_READY      3
++
++#define IOREQ_TYPE_PIO          0 /* pio */
++#define IOREQ_TYPE_COPY         1 /* mmio ops */
++#define IOREQ_TYPE_TIMEOFFSET   7
++#define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
++
++/*
++ * VMExit dispatcher should cooperate with instruction decoder to
++ * prepare this structure and notify service OS and DM by sending
++ * virq
++ */
++struct ioreq {
++    uint64_t addr;          /* physical address */
++    uint64_t data;          /* data (or paddr of data) */
++    uint32_t count;         /* for rep prefixes */
++    uint32_t size;          /* size in bytes */
++    uint32_t vp_eport;      /* evtchn for notifications to/from device model */
++    uint16_t _pad0;
++    uint8_t state:4;
++    uint8_t data_is_ptr:1;  /* if 1, data above is the guest paddr 
++                             * of the real data to use. */
++    uint8_t dir:1;          /* 1=read, 0=write */
++    uint8_t df:1;
++    uint8_t _pad1:1;
++    uint8_t type;           /* I/O type */
++};
++typedef struct ioreq ioreq_t;
++
++struct shared_iopage {
++    struct ioreq vcpu_ioreq[1];
++};
++typedef struct shared_iopage shared_iopage_t;
++
++struct buf_ioreq {
++    uint8_t  type;   /* I/O type                    */
++    uint8_t  pad:1;
++    uint8_t  dir:1;  /* 1=read, 0=write             */
++    uint8_t  size:2; /* 0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */
++    uint32_t addr:20;/* physical address            */
++    uint32_t data;   /* data                        */
++};
++typedef struct buf_ioreq buf_ioreq_t;
++
++#define IOREQ_BUFFER_SLOT_NUM     511 /* 8 bytes each, plus 2 4-byte indexes */
++struct buffered_iopage {
++    unsigned int read_pointer;
++    unsigned int write_pointer;
++    buf_ioreq_t buf_ioreq[IOREQ_BUFFER_SLOT_NUM];
++}; /* NB. Size of this structure must be no greater than one page. */
++typedef struct buffered_iopage buffered_iopage_t;
++
++#if defined(__ia64__)
++struct pio_buffer {
++    uint32_t page_offset;
++    uint32_t pointer;
++    uint32_t data_end;
++    uint32_t buf_size;
++    void *opaque;
++};
++
++#define PIO_BUFFER_IDE_PRIMARY   0 /* I/O port = 0x1F0 */
++#define PIO_BUFFER_IDE_SECONDARY 1 /* I/O port = 0x170 */
++#define PIO_BUFFER_ENTRY_NUM     2
++struct buffered_piopage {
++    struct pio_buffer pio[PIO_BUFFER_ENTRY_NUM];
++    uint8_t buffer[1];
++};
++#endif /* defined(__ia64__) */
++
++#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)
++#define ACPI_GPE0_BLK_ADDRESS               (ACPI_PM_TMR_BLK_ADDRESS + 0x20)
++#define ACPI_GPE0_BLK_LEN                   0x08
++
++#endif /* _IOREQ_H_ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/params.h	2009-04-07 13:58:49.000000000 +0200
+@@ -0,0 +1,111 @@
++/*
++ * 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_PUBLIC_HVM_PARAMS_H__
++#define __XEN_PUBLIC_HVM_PARAMS_H__
++
++#include "hvm_op.h"
++
++/*
++ * Parameter space for HVMOP_{set,get}_param.
++ */
++
++/*
++ * How should CPU0 event-channel notifications be delivered?
++ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
++ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
++ *                  Domain = val[47:32], Bus  = val[31:16],
++ *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
++ * If val == 0 then CPU0 event-channel notifications are not delivered.
++ */
++#define HVM_PARAM_CALLBACK_IRQ 0
++
++/*
++ * These are not used by Xen. They are here for convenience of HVM-guest
++ * xenbus implementations.
++ */
++#define HVM_PARAM_STORE_PFN    1
++#define HVM_PARAM_STORE_EVTCHN 2
++
++#define HVM_PARAM_PAE_ENABLED  4
++
++#define HVM_PARAM_IOREQ_PFN    5
++
++#define HVM_PARAM_BUFIOREQ_PFN 6
++
++#ifdef __ia64__
++
++#define HVM_PARAM_NVRAM_FD     7
++#define HVM_PARAM_VHPT_SIZE    8
++#define HVM_PARAM_BUFPIOREQ_PFN	9
++
++#elif defined(__i386__) || defined(__x86_64__)
++
++/* Expose Viridian interfaces to this HVM guest? */
++#define HVM_PARAM_VIRIDIAN     9
++
++#endif
++
++/*
++ * Set mode for virtual timers (currently x86 only):
++ *  delay_for_missed_ticks (default):
++ *   Do not advance a vcpu's time beyond the correct delivery time for
++ *   interrupts that have been missed due to preemption. Deliver missed
++ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
++ *   time stepwise for each one.
++ *  no_delay_for_missed_ticks:
++ *   As above, missed interrupts are delivered, but guest time always tracks
++ *   wallclock (i.e., real) time while doing so.
++ *  no_missed_ticks_pending:
++ *   No missed interrupts are held pending. Instead, to ensure ticks are
++ *   delivered at some non-zero rate, if we detect missed ticks then the
++ *   internal tick alarm is not disabled if the VCPU is preempted during the
++ *   next tick period.
++ *  one_missed_tick_pending:
++ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
++ *   Guest time always tracks wallclock (i.e., real) time.
++ */
++#define HVM_PARAM_TIMER_MODE   10
++#define HVMPTM_delay_for_missed_ticks    0
++#define HVMPTM_no_delay_for_missed_ticks 1
++#define HVMPTM_no_missed_ticks_pending   2
++#define HVMPTM_one_missed_tick_pending   3
++
++/* 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
++
++/* TSS used on Intel when CR0.PE=0. */
++#define HVM_PARAM_VM86_TSS     15
++
++/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
++#define HVM_PARAM_VPT_ALIGN    16
++
++#define HVM_NR_PARAMS          17
++
++#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/hvm/save.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,88 @@
++/* 
++ * hvm/save.h
++ *
++ * Structure definitions for HVM state that is held by Xen and must
++ * be saved along with the domain's memory and device-model state.
++ * 
++ * Copyright (c) 2007 XenSource Ltd.
++ *
++ * 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_PUBLIC_HVM_SAVE_H__
++#define __XEN_PUBLIC_HVM_SAVE_H__
++
++/*
++ * Structures in this header *must* have the same layout in 32bit 
++ * and 64bit environments: this means that all fields must be explicitly 
++ * sized types and aligned to their sizes, and the structs must be 
++ * a multiple of eight bytes long.
++ *
++ * Only the state necessary for saving and restoring (i.e. fields 
++ * that are analogous to actual hardware state) should go in this file. 
++ * 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
++ */
++struct hvm_save_descriptor {
++    uint16_t typecode;          /* Used to demux the various types below */
++    uint16_t instance;          /* Further demux within a type */
++    uint32_t length;            /* In bytes, *not* including this descriptor */
++};
++
++
++/* 
++ * Each entry has a datatype associated with it: for example, the CPU state 
++ * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU), 
++ * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU).
++ * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system
++ * ugliness.
++ */
++
++#define DECLARE_HVM_SAVE_TYPE(_x, _code, _type)                   \
++  struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; }
++
++#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t)
++#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x)))
++#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c))
++
++
++/* 
++ * The series of save records is teminated by a zero-type, zero-length 
++ * descriptor.
++ */
++
++struct hvm_save_end {};
++DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
++
++#if defined(__i386__) || defined(__x86_64__)
++#include "../arch-x86/hvm/save.h"
++#elif defined(__ia64__)
++#include "../arch-ia64/hvm/save.h"
++#else
++#error "unsupported architecture"
++#endif
++
++#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/fsif.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,192 @@
++/******************************************************************************
++ * fsif.h
++ * 
++ * Interface to FS level split device drivers.
++ * 
++ * 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) 2007, Grzegorz Milos, <gm281@cam.ac.uk>.
++ */
++
++#ifndef __XEN_PUBLIC_IO_FSIF_H__
++#define __XEN_PUBLIC_IO_FSIF_H__
++
++#include "ring.h"
++#include "../grant_table.h"
++
++#define REQ_FILE_OPEN        1
++#define REQ_FILE_CLOSE       2
++#define REQ_FILE_READ        3
++#define REQ_FILE_WRITE       4
++#define REQ_STAT             5
++#define REQ_FILE_TRUNCATE    6
++#define REQ_REMOVE           7
++#define REQ_RENAME           8
++#define REQ_CREATE           9
++#define REQ_DIR_LIST        10
++#define REQ_CHMOD           11
++#define REQ_FS_SPACE        12
++#define REQ_FILE_SYNC       13
++
++struct fsif_open_request {
++    grant_ref_t gref;
++};
++
++struct fsif_close_request {
++    uint32_t fd;
++};
++
++struct fsif_read_request {
++    uint32_t fd;
++    int32_t pad;
++    uint64_t len;
++    uint64_t offset;
++    grant_ref_t grefs[1];  /* Variable length */
++};
++
++struct fsif_write_request {
++    uint32_t fd;
++    int32_t pad;
++    uint64_t len;
++    uint64_t offset;
++    grant_ref_t grefs[1];  /* Variable length */
++};
++
++struct fsif_stat_request {
++    uint32_t fd;
++};
++
++/* 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  stat_ret;
++    int64_t  stat_size;
++    int64_t  stat_atime;
++    int64_t  stat_mtime;
++    int64_t  stat_ctime;
++};
++
++struct fsif_truncate_request {
++    uint32_t fd;
++    int32_t pad;
++    int64_t length;
++};
++
++struct fsif_remove_request {
++    grant_ref_t gref;
++};
++
++struct fsif_rename_request {
++    uint16_t old_name_offset;
++    uint16_t new_name_offset;
++    grant_ref_t gref;
++};
++
++struct fsif_create_request {
++    int8_t directory;
++    int8_t pad;
++    int16_t pad2;
++    int32_t mode;
++    grant_ref_t gref;
++};
++
++struct fsif_list_request {
++    uint32_t offset;
++    grant_ref_t gref;
++};
++
++#define NR_FILES_SHIFT  0
++#define NR_FILES_SIZE   16   /* 16 bits for the number of files mask */
++#define NR_FILES_MASK   (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
++#define ERROR_SIZE      32   /* 32 bits for the error mask */
++#define ERROR_SHIFT     (NR_FILES_SIZE + NR_FILES_SHIFT)
++#define ERROR_MASK      (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
++#define HAS_MORE_SHIFT  (ERROR_SHIFT + ERROR_SIZE)    
++#define HAS_MORE_FLAG   (1ULL << HAS_MORE_SHIFT)
++
++struct fsif_chmod_request {
++    uint32_t fd;
++    int32_t mode;
++};
++
++struct fsif_space_request {
++    grant_ref_t gref;
++};
++
++struct fsif_sync_request {
++    uint32_t fd;
++};
++
++
++/* FS operation request */
++struct fsif_request {
++    uint8_t type;                 /* Type of the request                  */
++    uint8_t pad;
++    uint16_t id;                  /* Request ID, copied to the response   */
++    uint32_t pad2;
++    union {
++        struct fsif_open_request     fopen;
++        struct fsif_close_request    fclose;
++        struct fsif_read_request     fread;
++        struct fsif_write_request    fwrite;
++        struct fsif_stat_request     fstat;
++        struct fsif_truncate_request ftruncate;
++        struct fsif_remove_request   fremove;
++        struct fsif_rename_request   frename;
++        struct fsif_create_request   fcreate;
++        struct fsif_list_request     flist;
++        struct fsif_chmod_request    fchmod;
++        struct fsif_space_request    fspace;
++        struct fsif_sync_request     fsync;
++    } u;
++};
++typedef struct fsif_request fsif_request_t;
++
++/* FS operation response */
++struct fsif_response {
++    uint16_t id;
++    uint16_t pad1;
++    uint32_t pad2;
++    union {
++        uint64_t ret_val;
++        struct fsif_stat_response fstat;
++    } u;
++};
++
++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);
++
++#define STATE_INITIALISED     "init"
++#define STATE_READY           "ready"
++#define STATE_CLOSING         "closing"
++#define STATE_CLOSED          "closed"
++
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/pciif.h	2009-04-07 13:58:49.000000000 +0200
+@@ -0,0 +1,124 @@
++/*
++ * PCI Backend/Frontend Common Data Structures & Macros
++ *
++ * 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.
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#ifndef __XEN_PCI_COMMON_H__
++#define __XEN_PCI_COMMON_H__
++
++/* Be sure to bump this number if you change this file */
++#define XEN_PCI_MAGIC "7"
++
++/* xen_pci_sharedinfo flags */
++#define _XEN_PCIF_active     (0)
++#define XEN_PCIF_active      (1<<_XEN_PCIF_active)
++#define _XEN_PCIB_AERHANDLER (1)
++#define XEN_PCIB_AERHANDLER  (1<<_XEN_PCIB_AERHANDLER)
++#define _XEN_PCIB_active     (2)
++#define XEN_PCIB_active      (1<<_XEN_PCIB_active)
++
++/* 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)
++#define XEN_PCI_OP_aer_detected 	(6)
++#define XEN_PCI_OP_aer_resume		(7)
++#define XEN_PCI_OP_aer_mmio		(8)
++#define XEN_PCI_OP_aer_slotreset	(9)
++
++/* xen_pci_op error numbers */
++#define XEN_PCI_ERR_success          (0)
++#define XEN_PCI_ERR_dev_not_found   (-1)
++#define XEN_PCI_ERR_invalid_offset  (-2)
++#define XEN_PCI_ERR_access_denied   (-3)
++#define XEN_PCI_ERR_not_implemented (-4)
++/* 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;
++
++    /* OUT: will contain an error number (if any) from errno.h */
++    int32_t err;
++
++    /* IN: which device to touch */
++    uint32_t domain; /* PCI Domain/Segment */
++    uint32_t bus;
++    uint32_t devfn;
++
++    /* IN: which configuration registers to touch */
++    int32_t offset;
++    int32_t size;
++
++    /* 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];
++};
++
++/*used for pcie aer handling*/
++struct xen_pcie_aer_op
++{
++
++    /* IN: what action to perform: XEN_PCI_OP_* */
++    uint32_t cmd;
++    /*IN/OUT: return aer_op result or carry error_detected state as input*/
++    int32_t err;
++
++    /* IN: which device to touch */
++    uint32_t domain; /* PCI Domain/Segment*/
++    uint32_t bus;
++    uint32_t devfn;
++};
++struct xen_pci_sharedinfo {
++    /* flags - XEN_PCIF_* */
++    uint32_t flags;
++    struct xen_pci_op op;
++    struct xen_pcie_aer_op aer_op;
++};
++
++#endif /* __XEN_PCI_COMMON_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/tpmif.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,77 @@
++/******************************************************************************
++ * tpmif.h
++ *
++ * TPM I/O interface for Xen guest OSes.
++ *
++ * 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) 2005, IBM Corporation
++ *
++ * Author: Stefan Berger, stefanb@us.ibm.com
++ * Grant table support: Mahadevan Gomathisankaran
++ *
++ * This code has been derived from tools/libxc/xen/io/netif.h
++ *
++ * Copyright (c) 2003-2004, Keir Fraser
++ */
++
++#ifndef __XEN_PUBLIC_IO_TPMIF_H__
++#define __XEN_PUBLIC_IO_TPMIF_H__
++
++#include "../grant_table.h"
++
++struct tpmif_tx_request {
++    unsigned long addr;   /* Machine address of packet.   */
++    grant_ref_t ref;      /* grant table access reference */
++    uint16_t unused;
++    uint16_t size;        /* Packet size in bytes.        */
++};
++typedef struct tpmif_tx_request tpmif_tx_request_t;
++
++/*
++ * The TPMIF_TX_RING_SIZE defines the number of pages the
++ * front-end and backend can exchange (= size of array).
++ */
++typedef uint32_t TPMIF_RING_IDX;
++
++#define TPMIF_TX_RING_SIZE 1
++
++/* This structure must fit in a memory page. */
++
++struct tpmif_ring {
++    struct tpmif_tx_request req;
++};
++typedef struct tpmif_ring tpmif_ring_t;
++
++struct tpmif_tx_interface {
++    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
++};
++typedef struct tpmif_tx_interface tpmif_tx_interface_t;
++
++#endif
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/usbif.h	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,151 @@
++/*
++ * usbif.h
++ *
++ * USB I/O interface for Xen guest OSes.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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_PUBLIC_IO_USBIF_H__
++#define __XEN_PUBLIC_IO_USBIF_H__
++
++#include "ring.h"
++#include "../grant_table.h"
++
++enum usb_spec_version {
++	USB_VER_UNKNOWN = 0,
++	USB_VER_USB11,
++	USB_VER_USB20,
++	USB_VER_USB30,	/* not supported yet */
++};
++
++/*
++ *  USB pipe in usbif_request
++ *
++ *  bits 0-5 are specific bits for virtual USB driver.
++ *  bits 7-31 are standard urb pipe.
++ *
++ *  - port number(NEW):	bits 0-4
++ *  				(USB_MAXCHILDREN is 31)
++ *
++ *  - operation flag(NEW):	bit 5
++ *  				(0 = submit urb,
++ *  				 1 = unlink urb)
++ *
++ *  - direction:		bit 7
++ *  				(0 = Host-to-Device [Out]
++ *                           1 = Device-to-Host [In])
++ *
++ *  - device address:	bits 8-14
++ *
++ *  - endpoint:		bits 15-18
++ *
++ *  - pipe type:		bits 30-31
++ *  				(00 = isochronous, 01 = interrupt,
++ *                           10 = control, 11 = bulk)
++ */
++#define usbif_pipeportnum(pipe) ((pipe) & 0x1f)
++#define usbif_setportnum_pipe(pipe, portnum) \
++	((pipe)|(portnum))
++
++#define usbif_pipeunlink(pipe) ((pipe) & 0x20)
++#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
++#define usbif_setunlink_pipe(pipe) ((pipe)|(0x20))
++
++#define USBIF_BACK_MAX_PENDING_REQS (128)
++#define USBIF_MAX_SEGMENTS_PER_REQUEST (16)
++
++/*
++ * RING for transferring urbs.
++ */
++struct usbif_request_segment {
++	grant_ref_t gref;
++	uint16_t offset;
++	uint16_t length;
++};
++
++struct usbif_urb_request {
++	uint16_t id; /* request id */
++	uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
++
++	/* basic urb parameter */
++	uint32_t pipe;
++	uint16_t transfer_flags;
++	uint16_t buffer_length;
++	union {
++		uint8_t ctrl[8]; /* setup_packet (Ctrl) */
++
++		struct {
++			uint16_t interval; /* maximum (1024*8) in usb core */
++			uint16_t start_frame; /* start frame */
++			uint16_t number_of_packets; /* number of ISO packet */
++			uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
++		} isoc;
++
++		struct {
++			uint16_t interval; /* maximum (1024*8) in usb core */
++			uint16_t pad[3];
++		} intr;
++
++		struct {
++			uint16_t unlink_id; /* unlink request id */
++			uint16_t pad[3];
++		} unlink;
++
++	} u;
++
++	/* urb data segments */
++	struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
++};
++typedef struct usbif_urb_request usbif_urb_request_t;
++
++struct usbif_urb_response {
++	uint16_t id; /* request id */
++	uint16_t start_frame;  /* start frame (ISO) */
++	int32_t status; /* status (non-ISO) */
++	int32_t actual_length; /* actual transfer length */
++	int32_t error_count; /* number of ISO errors */
++};
++typedef struct usbif_urb_response usbif_urb_response_t;
++
++DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response);
++#define USB_URB_RING_SIZE __RING_SIZE((struct usbif_urb_sring *)0, PAGE_SIZE)
++
++/*
++ * RING for notifying connect/disconnect events to frontend
++ */
++struct usbif_conn_request {
++	uint16_t id;
++};
++typedef struct usbif_conn_request usbif_conn_request_t;
++
++struct usbif_conn_response {
++	uint16_t id; /* request id */
++	uint8_t portnum; /* port number */
++	uint8_t speed; /* usb_device_speed */
++};
++typedef struct usbif_conn_response usbif_conn_response_t;
++
++DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response);
++#define USB_CONN_RING_SIZE __RING_SIZE((struct usbif_conn_sring *)0, PAGE_SIZE)
++
++#endif /* __XEN_PUBLIC_IO_USBIF_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/io/vscsiif.h	2008-07-21 11:00:33.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:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/kexec.h	2008-11-25 12:22:34.000000000 +0100
+@@ -0,0 +1,168 @@
++/******************************************************************************
++ * 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>
++ */
++
++#ifndef _XEN_PUBLIC_KEXEC_H
++#define _XEN_PUBLIC_KEXEC_H
++
++
++/* This file describes the Kexec / Kdump hypercall interface for Xen.
++ *
++ * Kexec under vanilla Linux allows a user to reboot the physical machine 
++ * into a new user-specified kernel. The Xen port extends this idea
++ * to allow rebooting of the machine from dom0. When kexec for dom0
++ * is used to reboot,  both the hypervisor and the domains get replaced
++ * with some other kernel. It is possible to kexec between vanilla
++ * Linux and Xen and back again. Xen to Xen works well too.
++ *
++ * The hypercall interface for kexec can be divided into three main
++ * types of hypercall operations:
++ *
++ * 1) Range information:
++ *    This is used by the dom0 kernel to ask the hypervisor about various 
++ *    address information. This information is needed to allow kexec-tools 
++ *    to fill in the ELF headers for /proc/vmcore properly.
++ *
++ * 2) Load and unload of images:
++ *    There are no big surprises here, the kexec binary from kexec-tools
++ *    runs in userspace in dom0. The tool loads/unloads data into the
++ *    dom0 kernel such as new kernel, initramfs and hypervisor. When
++ *    loaded the dom0 kernel performs a load hypercall operation, and
++ *    before releasing all page references the dom0 kernel calls unload.
++ *
++ * 3) Kexec operation:
++ *    This is used to start a previously loaded kernel.
++ */
++
++#include "xen.h"
++
++#if defined(__i386__) || defined(__x86_64__)
++#define KEXEC_XEN_NO_PAGES 17
++#endif
++
++/*
++ * Prototype for this hypercall is:
++ *  int kexec_op(int cmd, void *args)
++ * @cmd  == KEXEC_CMD_... 
++ *          KEXEC operation to perform
++ * @args == Operation-specific extra arguments (NULL if none).
++ */
++
++/*
++ * Kexec supports two types of operation:
++ * - kexec into a regular kernel, very similar to a standard reboot
++ *   - KEXEC_TYPE_DEFAULT is used to specify this type
++ * - kexec into a special "crash kernel", aka kexec-on-panic
++ *   - KEXEC_TYPE_CRASH is used to specify this type
++ *   - parts of our system may be broken at kexec-on-panic time
++ *     - the code should be kept as simple and self-contained as possible
++ */
++
++#define KEXEC_TYPE_DEFAULT 0
++#define KEXEC_TYPE_CRASH   1
++
++
++/* The kexec implementation for Xen allows the user to load two
++ * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
++ * All data needed for a kexec reboot is kept in one xen_kexec_image_t
++ * per "instance". The data mainly consists of machine address lists to pages
++ * together with destination addresses. The data in xen_kexec_image_t
++ * is passed to the "code page" which is one page of code that performs
++ * the final relocations before jumping to the new kernel.
++ */
++ 
++typedef struct xen_kexec_image {
++#if defined(__i386__) || defined(__x86_64__)
++    unsigned long page_list[KEXEC_XEN_NO_PAGES];
++#endif
++#if defined(__ia64__)
++    unsigned long reboot_code_buffer;
++#endif
++    unsigned long indirection_page;
++    unsigned long start_address;
++} xen_kexec_image_t;
++
++/*
++ * Perform kexec having previously loaded a kexec or kdump kernel
++ * as appropriate.
++ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
++ */
++#define KEXEC_CMD_kexec                 0
++typedef struct xen_kexec_exec {
++    int type;
++} xen_kexec_exec_t;
++
++/*
++ * Load/Unload kernel image for kexec or kdump.
++ * type  == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
++ * image == relocation information for kexec (ignored for unload) [in]
++ */
++#define KEXEC_CMD_kexec_load            1
++#define KEXEC_CMD_kexec_unload          2
++typedef struct xen_kexec_load {
++    int type;
++    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_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
++ * range == KEXEC_RANGE_... [in]
++ * nr    == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
++ * size  == number of bytes reserved in window [out]
++ * start == address of the first byte in the window [out]
++ */
++#define KEXEC_CMD_kexec_get_range       3
++typedef struct xen_kexec_range {
++    int range;
++    int nr;
++    unsigned long size;
++    unsigned long start;
++} xen_kexec_range_t;
++
++#endif /* _XEN_PUBLIC_KEXEC_H */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/mem_event.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,69 @@
++/******************************************************************************
++ * mem_event.h
++ *
++ * Memory event common structures.
++ *
++ * Copyright (c) 2009 by Citrix Systems, Inc. (Patrick Colp)
++ *
++ * 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_MEM_EVENT_H
++#define _XEN_PUBLIC_MEM_EVENT_H
++
++
++#include "xen.h"
++#include "io/ring.h"
++
++
++/* Memory event notification modes */
++#define MEM_EVENT_MODE_ASYNC    0
++#define MEM_EVENT_MODE_SYNC     (1 << 0)
++#define MEM_EVENT_MODE_SYNC_ALL (1 << 1)
++
++/* Memory event flags */
++#define MEM_EVENT_FLAG_VCPU_PAUSED  (1 << 0)
++#define MEM_EVENT_FLAG_DOM_PAUSED   (1 << 1)
++#define MEM_EVENT_FLAG_OUT_OF_MEM   (1 << 2)
++
++
++typedef struct mem_event_shared_page {
++    int port;
++} mem_event_shared_page_t;
++
++typedef struct mem_event_st {
++    unsigned long gfn;
++    unsigned long offset;
++    unsigned long p2mt;
++    int vcpu_id;
++    uint64_t flags;
++} mem_event_request_t, mem_event_response_t;
++
++
++DEFINE_RING_TYPES(mem_event, mem_event_request_t, mem_event_response_t);
++
++
++#endif
++
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/nmi.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,80 @@
++/******************************************************************************
++ * nmi.h
++ * 
++ * NMI callback registration and reason codes.
++ * 
++ * 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) 2005, Keir Fraser <keir@xensource.com>
++ */
++
++#ifndef __XEN_PUBLIC_NMI_H__
++#define __XEN_PUBLIC_NMI_H__
++
++#include "xen.h"
++
++/*
++ * NMI reason codes:
++ * Currently these are x86-specific, stored in arch_shared_info.nmi_reason.
++ */
++ /* I/O-check error reported via ISA port 0x61, bit 6. */
++#define _XEN_NMIREASON_io_error     0
++#define XEN_NMIREASON_io_error      (1UL << _XEN_NMIREASON_io_error)
++ /* Parity error reported via ISA port 0x61, bit 7. */
++#define _XEN_NMIREASON_parity_error 1
++#define XEN_NMIREASON_parity_error  (1UL << _XEN_NMIREASON_parity_error)
++ /* Unknown hardware-generated NMI. */
++#define _XEN_NMIREASON_unknown      2
++#define XEN_NMIREASON_unknown       (1UL << _XEN_NMIREASON_unknown)
++
++/*
++ * long nmi_op(unsigned int cmd, void *arg)
++ * NB. All ops return zero on success, else a negative error code.
++ */
++
++/*
++ * Register NMI callback for this (calling) VCPU. Currently this only makes
++ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
++ * arg == pointer to xennmi_callback structure.
++ */
++#define XENNMI_register_callback   0
++struct xennmi_callback {
++    unsigned long handler_address;
++    unsigned long pad;
++};
++typedef struct xennmi_callback xennmi_callback_t;
++DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t);
++
++/*
++ * Deregister NMI callback for this (calling) VCPU.
++ * arg == NULL.
++ */
++#define XENNMI_unregister_callback 1
++
++#endif /* __XEN_PUBLIC_NMI_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/platform.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,393 @@
++/******************************************************************************
++ * platform.h
++ * 
++ * Hardware platform operations. Intended for use by domain-0 kernel.
++ * 
++ * 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) 2002-2006, K Fraser
++ */
++
++#ifndef __XEN_PUBLIC_PLATFORM_H__
++#define __XEN_PUBLIC_PLATFORM_H__
++
++#include "xen.h"
++
++#define XENPF_INTERFACE_VERSION 0x03000001
++
++/*
++ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
++ * 1 January, 1970 if the current system time was <system_time>.
++ */
++#define XENPF_settime             17
++struct xenpf_settime {
++    /* IN variables. */
++    uint32_t secs;
++    uint32_t nsecs;
++    uint64_t system_time;
++};
++typedef struct xenpf_settime xenpf_settime_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
++
++/*
++ * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type.
++ * On x86, @type is an architecture-defined MTRR memory type.
++ * On success, returns the MTRR that was used (@reg) and a handle that can
++ * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting.
++ * (x86-specific).
++ */
++#define XENPF_add_memtype         31
++struct xenpf_add_memtype {
++    /* IN variables. */
++    xen_pfn_t mfn;
++    uint64_t nr_mfns;
++    uint32_t type;
++    /* OUT variables. */
++    uint32_t handle;
++    uint32_t reg;
++};
++typedef struct xenpf_add_memtype xenpf_add_memtype_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t);
++
++/*
++ * Tear down an existing memory-range type. If @handle is remembered then it
++ * should be passed in to accurately tear down the correct setting (in case
++ * of overlapping memory regions with differing types). If it is not known
++ * then @handle should be set to zero. In all cases @reg must be set.
++ * (x86-specific).
++ */
++#define XENPF_del_memtype         32
++struct xenpf_del_memtype {
++    /* IN variables. */
++    uint32_t handle;
++    uint32_t reg;
++};
++typedef struct xenpf_del_memtype xenpf_del_memtype_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t);
++
++/* Read current type of an MTRR (x86-specific). */
++#define XENPF_read_memtype        33
++struct xenpf_read_memtype {
++    /* IN variables. */
++    uint32_t reg;
++    /* OUT variables. */
++    xen_pfn_t mfn;
++    uint64_t nr_mfns;
++    uint32_t type;
++};
++typedef struct xenpf_read_memtype xenpf_read_memtype_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t);
++
++#define XENPF_microcode_update    35
++struct xenpf_microcode_update {
++    /* IN variables. */
++    XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
++    uint32_t length;                  /* Length of microcode data. */
++};
++typedef struct xenpf_microcode_update xenpf_microcode_update_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t);
++
++#define XENPF_platform_quirk      39
++#define QUIRK_NOIRQBALANCING      1 /* Do not restrict IO-APIC RTE targets */
++#define QUIRK_IOAPIC_BAD_REGSEL   2 /* IO-APIC REGSEL forgets its value    */
++#define QUIRK_IOAPIC_GOOD_REGSEL  3 /* IO-APIC REGSEL behaves properly     */
++struct xenpf_platform_quirk {
++    /* IN variables. */
++    uint32_t quirk_id;
++};
++typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
++
++#define XENPF_firmware_info       50
++#define XEN_FW_DISK_INFO          1 /* from int 13 AH=08/41/48 */
++#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
++#define XEN_FW_VBEDDC_INFO        3 /* from int 10 AX=4f15 */
++struct xenpf_firmware_info {
++    /* IN variables. */
++    uint32_t type;
++    uint32_t index;
++    /* OUT variables. */
++    union {
++        struct {
++            /* Int13, Fn48: Check Extensions Present. */
++            uint8_t device;                   /* %dl: bios device number */
++            uint8_t version;                  /* %ah: major version      */
++            uint16_t interface_support;       /* %cx: support bitmap     */
++            /* Int13, Fn08: Legacy Get Device Parameters. */
++            uint16_t legacy_max_cylinder;     /* %cl[7:6]:%ch: max cyl # */
++            uint8_t legacy_max_head;          /* %dh: max head #         */
++            uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector #  */
++            /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
++            /* NB. First uint16_t of buffer must be set to buffer size.      */
++            XEN_GUEST_HANDLE(void) edd_params;
++        } disk_info; /* XEN_FW_DISK_INFO */
++        struct {
++            uint8_t device;                   /* bios device number  */
++            uint32_t mbr_signature;           /* offset 0x1b8 in mbr */
++        } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */
++        struct {
++            /* Int10, AX=4F15: Get EDID info. */
++            uint8_t capabilities;
++            uint8_t edid_transfer_time;
++            /* must refer to 128-byte buffer */
++            XEN_GUEST_HANDLE(uint8) edid;
++        } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
++    } u;
++};
++typedef struct xenpf_firmware_info xenpf_firmware_info_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
++
++#define XENPF_enter_acpi_sleep    51
++struct xenpf_enter_acpi_sleep {
++    /* IN variables */
++    uint16_t pm1a_cnt_val;      /* PM1a control value. */
++    uint16_t pm1b_cnt_val;      /* PM1b control value. */
++    uint32_t sleep_state;       /* Which state to enter (Sn). */
++    uint32_t flags;             /* Must be zero. */
++};
++typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
++
++#define XENPF_change_freq         52
++struct xenpf_change_freq {
++    /* IN variables */
++    uint32_t flags; /* Must be zero. */
++    uint32_t cpu;   /* Physical cpu. */
++    uint64_t freq;  /* New frequency (Hz). */
++};
++typedef struct xenpf_change_freq xenpf_change_freq_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
++
++/*
++ * Get idle times (nanoseconds since boot) for physical CPUs specified in the
++ * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is
++ * indexed by CPU number; only entries with the corresponding @cpumap_bitmap
++ * bit set are written to. On return, @cpumap_bitmap is modified so that any
++ * non-existent CPUs are cleared. Such CPUs have their @idletime array entry
++ * cleared.
++ */
++#define XENPF_getidletime         53
++struct xenpf_getidletime {
++    /* IN/OUT variables */
++    /* IN: CPUs to interrogate; OUT: subset of IN which are present */
++    XEN_GUEST_HANDLE(uint8) cpumap_bitmap;
++    /* IN variables */
++    /* Size of cpumap bitmap. */
++    uint32_t cpumap_nr_cpus;
++    /* Must be indexable for every cpu in cpumap_bitmap. */
++    XEN_GUEST_HANDLE(uint64) idletime;
++    /* OUT variables */
++    /* System time when the idletime snapshots were taken. */
++    uint64_t now;
++};
++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 platform_limit;  /* 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 */
++    } u;
++};
++typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
++
++#define XENPF_get_cpuinfo 55
++struct xenpf_pcpuinfo {
++    /* IN */
++    uint32_t xen_cpuid;
++    /* OUT */
++    /* The maxium cpu_id that is present */
++    uint32_t max_present;
++#define XEN_PCPU_FLAGS_ONLINE   1
++    /* Correponding xen_cpuid is not present*/
++#define XEN_PCPU_FLAGS_INVALID  2
++    uint32_t flags;
++    uint32_t apic_id;
++    uint32_t acpi_id;
++};
++typedef struct xenpf_pcpuinfo xenpf_pcpuinfo_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_pcpuinfo_t);
++
++#define XENPF_cpu_online    56
++#define XENPF_cpu_offline   57
++struct xenpf_cpu_ol
++{
++    uint32_t cpuid;
++};
++typedef struct xenpf_cpu_ol xenpf_cpu_ol_t;
++DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_ol_t);
++
++#define XENPF_cpu_hotadd    58
++struct xenpf_cpu_hotadd
++{
++	uint32_t apic_id;
++	uint32_t acpi_id;
++	uint32_t pxm;
++};
++
++#define XENPF_mem_hotadd    59
++struct xenpf_mem_hotadd
++{
++    uint64_t spfn;
++    uint64_t epfn;
++    uint32_t pxm;
++    uint32_t flags;
++};
++
++struct xen_platform_op {
++    uint32_t cmd;
++    uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
++    union {
++        struct xenpf_settime           settime;
++        struct xenpf_add_memtype       add_memtype;
++        struct xenpf_del_memtype       del_memtype;
++        struct xenpf_read_memtype      read_memtype;
++        struct xenpf_microcode_update  microcode;
++        struct xenpf_platform_quirk    platform_quirk;
++        struct xenpf_firmware_info     firmware_info;
++        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;
++        struct xenpf_pcpuinfo          pcpu_info;
++        struct xenpf_cpu_ol            cpu_ol;
++        struct xenpf_cpu_hotadd        cpu_add;
++        struct xenpf_mem_hotadd        mem_add;
++        uint8_t                        pad[128];
++    } u;
++};
++typedef struct xen_platform_op xen_platform_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t);
++
++#endif /* __XEN_PUBLIC_PLATFORM_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/sysctl.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,523 @@
++/******************************************************************************
++ * sysctl.h
++ * 
++ * System management operations. For use by node control stack.
++ * 
++ * 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) 2002-2006, K Fraser
++ */
++
++#ifndef __XEN_PUBLIC_SYSCTL_H__
++#define __XEN_PUBLIC_SYSCTL_H__
++
++#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
++#error "sysctl operations are intended for use by node control tools only"
++#endif
++
++#include "xen.h"
++#include "domctl.h"
++
++#define XEN_SYSCTL_INTERFACE_VERSION 0x00000007
++
++/*
++ * Read console content from Xen buffer ring.
++ */
++#define XEN_SYSCTL_readconsole       1
++struct xen_sysctl_readconsole {
++    /* IN: Non-zero -> clear after reading. */
++    uint8_t clear;
++    /* IN: Non-zero -> start index specified by @index field. */
++    uint8_t incremental;
++    uint8_t pad0, pad1;
++    /*
++     * IN:  Start index for consuming from ring buffer (if @incremental);
++     * OUT: End index after consuming from ring buffer.
++     */
++    uint32_t index; 
++    /* IN: Virtual address to write console data. */
++    XEN_GUEST_HANDLE_64(char) buffer;
++    /* IN: Size of buffer; OUT: Bytes written to buffer. */
++    uint32_t count;
++};
++typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
++
++/* Get trace buffers machine base address */
++#define XEN_SYSCTL_tbuf_op           2
++struct xen_sysctl_tbuf_op {
++    /* IN variables */
++#define XEN_SYSCTL_TBUFOP_get_info     0
++#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1
++#define XEN_SYSCTL_TBUFOP_set_evt_mask 2
++#define XEN_SYSCTL_TBUFOP_set_size     3
++#define XEN_SYSCTL_TBUFOP_enable       4
++#define XEN_SYSCTL_TBUFOP_disable      5
++    uint32_t cmd;
++    /* IN/OUT variables */
++    struct xenctl_cpumap cpu_mask;
++    uint32_t             evt_mask;
++    /* OUT variables */
++    uint64_aligned_t buffer_mfn;
++    uint32_t size;
++};
++typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
++
++/*
++ * 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 {
++    uint32_t threads_per_core;
++    uint32_t cores_per_socket;
++    uint32_t nr_cpus;
++    uint32_t max_node_id;
++    uint32_t cpu_khz;
++    uint64_aligned_t total_pages;
++    uint64_aligned_t free_pages;
++    uint64_aligned_t scrub_pages;
++    uint32_t hw_cap[8];
++
++    /*
++     * IN: maximum addressable entry in the caller-provided cpu_to_node array.
++     * OUT: largest cpu identifier in the system.
++     * If OUT is greater than IN then the cpu_to_node array is truncated!
++     */
++    uint32_t max_cpu_id;
++    /*
++     * If not NULL, this array is filled with node identifier for each cpu.
++     * If a cpu has no node information (e.g., cpu not present) then the
++     * sentinel value ~0u is written.
++     * The size of this array is specified by the caller in @max_cpu_id.
++     * If the actual @max_cpu_id is smaller than the array then the trailing
++     * 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);
++
++/*
++ * Get the ID of the current scheduler.
++ */
++#define XEN_SYSCTL_sched_id          4
++struct xen_sysctl_sched_id {
++    /* OUT variable */
++    uint32_t sched_id;
++};
++typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t);
++
++/* Interface for controlling Xen software performance counters. */
++#define XEN_SYSCTL_perfc_op          5
++/* Sub-operations: */
++#define XEN_SYSCTL_PERFCOP_reset 1   /* Reset all counters to zero. */
++#define XEN_SYSCTL_PERFCOP_query 2   /* Get perfctr information. */
++struct xen_sysctl_perfc_desc {
++    char         name[80];             /* name of perf counter */
++    uint32_t     nr_vals;              /* number of values for this counter */
++};
++typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t);
++typedef uint32_t xen_sysctl_perfc_val_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t);
++
++struct xen_sysctl_perfc_op {
++    /* IN variables. */
++    uint32_t       cmd;                /*  XEN_SYSCTL_PERFCOP_??? */
++    /* OUT variables. */
++    uint32_t       nr_counters;       /*  number of counters description  */
++    uint32_t       nr_vals;           /*  number of values  */
++    /* counter information (or NULL) */
++    XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc;
++    /* counter values (or NULL) */
++    XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val;
++};
++typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t);
++
++#define XEN_SYSCTL_getdomaininfolist 6
++struct xen_sysctl_getdomaininfolist {
++    /* IN variables. */
++    domid_t               first_domain;
++    uint32_t              max_domains;
++    XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
++    /* OUT variables. */
++    uint32_t              num_domains;
++};
++typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
++
++/* Inject debug keys into Xen. */
++#define XEN_SYSCTL_debug_keys        7
++struct xen_sysctl_debug_keys {
++    /* IN variables. */
++    XEN_GUEST_HANDLE_64(char) keys;
++    uint32_t nr_keys;
++};
++typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
++
++/* Get physical CPU information. */
++#define XEN_SYSCTL_getcpuinfo        8
++struct xen_sysctl_cpuinfo {
++    uint64_aligned_t idletime;
++};
++typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t); 
++struct xen_sysctl_getcpuinfo {
++    /* IN variables. */
++    uint32_t max_cpus;
++    XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info;
++    /* OUT variables. */
++    uint32_t nr_cpus;
++}; 
++typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); 
++
++#define XEN_SYSCTL_availheap         9
++struct xen_sysctl_availheap {
++    /* IN variables. */
++    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
++    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
++    int32_t  node;          /* NUMA node of interest (-1 for all nodes). */
++    /* OUT variables. */
++    uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */
++};
++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);
++
++/*
++ * Status codes. Must be greater than 0 to avoid confusing
++ * sysctl callers that see 0 as a plain successful return.
++ */
++#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1
++#define XEN_CPU_HOTPLUG_STATUS_ONLINE  2
++#define XEN_CPU_HOTPLUG_STATUS_NEW     3
++
++#define XEN_SYSCTL_cpu_hotplug       11
++struct xen_sysctl_cpu_hotplug {
++    /* IN variables */
++    uint32_t cpu;   /* Physical cpu. */
++#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE  0
++#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
++#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2
++    uint32_t op;    /* hotplug opcode */
++};
++typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
++
++/*
++ * Get/set xen power management, include 
++ * 1. cpufreq governors and related parameters
++ */
++#define XEN_SYSCTL_pm_op        12
++struct xen_userspace {
++    uint32_t scaling_setspeed;
++};
++typedef struct xen_userspace xen_userspace_t;
++
++struct xen_ondemand {
++    uint32_t sampling_rate_max;
++    uint32_t sampling_rate_min;
++
++    uint32_t sampling_rate;
++    uint32_t up_threshold;
++};
++typedef struct xen_ondemand xen_ondemand_t;
++
++/* 
++ * cpufreq para name of this structure named 
++ * same as sysfs file name of native linux
++ */
++#define CPUFREQ_NAME_LEN 16
++struct xen_get_cpufreq_para {
++    /* IN/OUT variable */
++    uint32_t cpu_num;
++    uint32_t freq_num;
++    uint32_t gov_num;
++
++    /* for all governors */
++    /* OUT variable */
++    XEN_GUEST_HANDLE_64(uint32) affected_cpus;
++    XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
++    XEN_GUEST_HANDLE_64(char)   scaling_available_governors;
++    char scaling_driver[CPUFREQ_NAME_LEN];
++
++    uint32_t cpuinfo_cur_freq;
++    uint32_t cpuinfo_max_freq;
++    uint32_t cpuinfo_min_freq;
++    uint32_t scaling_cur_freq;
++
++    char scaling_governor[CPUFREQ_NAME_LEN];
++    uint32_t scaling_max_freq;
++    uint32_t scaling_min_freq;
++
++    /* for specific governor */
++    union {
++        struct  xen_userspace userspace;
++        struct  xen_ondemand ondemand;
++    } u;
++};
++
++struct xen_set_cpufreq_gov {
++    char scaling_governor[CPUFREQ_NAME_LEN];
++};
++
++struct xen_set_cpufreq_para {
++    #define SCALING_MAX_FREQ           1
++    #define SCALING_MIN_FREQ           2
++    #define SCALING_SETSPEED           3
++    #define SAMPLING_RATE              4
++    #define UP_THRESHOLD               5
++
++    uint32_t ctrl_type;
++    uint32_t ctrl_value;
++};
++
++/* Get physical CPU topology information. */
++#define INVALID_TOPOLOGY_ID  (~0U)
++struct xen_get_cputopo {
++     /* IN: maximum addressable entry in
++      * the caller-provided cpu_to_core/socket.
++      */
++    uint32_t max_cpus;
++    XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
++    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
++
++    /* OUT: number of cpus returned
++     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
++     */
++    uint32_t nr_cpus;
++};
++
++struct xen_sysctl_pm_op {
++    #define PM_PARA_CATEGORY_MASK      0xf0
++    #define CPUFREQ_PARA               0x10
++
++    /* cpufreq command type */
++    #define GET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x01)
++    #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
++    #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
++    #define GET_CPUFREQ_AVGFREQ        (CPUFREQ_PARA | 0x04)
++
++    /* get CPU topology */
++    #define XEN_SYSCTL_pm_op_get_cputopo  0x20
++
++    /* set/reset scheduler power saving option */
++    #define XEN_SYSCTL_pm_op_set_sched_opt_smt    0x21
++
++    /* cpuidle max_cstate access command */
++    #define XEN_SYSCTL_pm_op_get_max_cstate       0x22
++    #define XEN_SYSCTL_pm_op_set_max_cstate       0x23
++
++    /* set scheduler migration cost value */
++    #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay   0x24
++    #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay   0x25
++
++    uint32_t cmd;
++    uint32_t cpuid;
++    union {
++        struct xen_get_cpufreq_para get_para;
++        struct xen_set_cpufreq_gov  set_gov;
++        struct xen_set_cpufreq_para set_para;
++        uint64_aligned_t get_avgfreq;
++        struct xen_get_cputopo      get_topo;
++        uint32_t                    set_sched_opt_smt;
++        uint32_t                    get_max_cstate;
++        uint32_t                    set_max_cstate;
++        uint32_t                    get_vcpu_migration_delay;
++        uint32_t                    set_vcpu_migration_delay;
++    } u;
++};
++
++#define XEN_SYSCTL_page_offline_op        14
++struct xen_sysctl_page_offline_op {
++    /* IN: range of page to be offlined */
++#define sysctl_page_offline     1
++#define sysctl_page_online      2
++#define sysctl_query_page_offline  3
++    uint32_t cmd;
++    uint32_t start;
++    uint32_t end;
++    /* OUT: result of page offline request */
++    /*
++     * bit 0~15: result flags
++     * bit 16~31: owner
++     */
++    XEN_GUEST_HANDLE(uint32) status;
++};
++
++#define PG_OFFLINE_STATUS_MASK    (0xFFUL)
++
++/* The result is invalid, i.e. HV does not handle it */
++#define PG_OFFLINE_INVALID   (0x1UL << 0)
++
++#define PG_OFFLINE_OFFLINED  (0x1UL << 1)
++#define PG_OFFLINE_PENDING   (0x1UL << 2)
++#define PG_OFFLINE_FAILED    (0x1UL << 3)
++
++#define PG_ONLINE_FAILED     PG_OFFLINE_FAILED
++#define PG_ONLINE_ONLINED    PG_OFFLINE_OFFLINED
++
++#define PG_OFFLINE_STATUS_OFFLINED              (0x1UL << 1)
++#define PG_OFFLINE_STATUS_ONLINE                (0x1UL << 2)
++#define PG_OFFLINE_STATUS_OFFLINE_PENDING       (0x1UL << 3)
++#define PG_OFFLINE_STATUS_BROKEN                (0x1UL << 4)
++
++#define PG_OFFLINE_MISC_MASK    (0xFFUL << 4)
++
++/* only valid when PG_OFFLINE_FAILED */
++#define PG_OFFLINE_XENPAGE   (0x1UL << 8)
++#define PG_OFFLINE_DOM0PAGE  (0x1UL << 9)
++#define PG_OFFLINE_ANONYMOUS (0x1UL << 10)
++#define PG_OFFLINE_NOT_CONV_RAM   (0x1UL << 11)
++#define PG_OFFLINE_OWNED     (0x1UL << 12)
++
++#define PG_OFFLINE_BROKEN    (0x1UL << 13)
++#define PG_ONLINE_BROKEN     PG_OFFLINE_BROKEN
++
++#define PG_OFFLINE_OWNER_SHIFT 16
++
++#define XEN_SYSCTL_lockprof_op       15
++/* Sub-operations: */
++#define XEN_SYSCTL_LOCKPROF_reset 1   /* Reset all profile data to zero. */
++#define XEN_SYSCTL_LOCKPROF_query 2   /* Get lock profile information. */
++/* Record-type: */
++#define LOCKPROF_TYPE_GLOBAL      0   /* global lock, idx meaningless */
++#define LOCKPROF_TYPE_PERDOM      1   /* per-domain lock, idx is domid */
++#define LOCKPROF_TYPE_N           2   /* number of types */
++struct xen_sysctl_lockprof_data {
++    char     name[40];     /* lock name (may include up to 2 %d specifiers) */
++    int32_t  type;         /* LOCKPROF_TYPE_??? */
++    int32_t  idx;          /* index (e.g. domain id) */
++    uint64_aligned_t lock_cnt;     /* # of locking succeeded */
++    uint64_aligned_t block_cnt;    /* # of wait for lock */
++    uint64_aligned_t lock_time;    /* nsecs lock held */
++    uint64_aligned_t block_time;   /* nsecs waited for lock */
++};
++typedef struct xen_sysctl_lockprof_data xen_sysctl_lockprof_data_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_data_t);
++struct xen_sysctl_lockprof_op {
++    /* IN variables. */
++    uint32_t       cmd;               /* XEN_SYSCTL_LOCKPROF_??? */
++    uint32_t       max_elem;          /* size of output buffer */
++    /* OUT variables (query only). */
++    uint32_t       nr_elem;           /* number of elements available */
++    uint64_aligned_t time;            /* nsecs of profile measurement */
++    /* profile information (or NULL) */
++    XEN_GUEST_HANDLE_64(xen_sysctl_lockprof_data_t) data;
++};
++typedef struct xen_sysctl_lockprof_op xen_sysctl_lockprof_op_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_op_t);
++
++struct xen_sysctl {
++    uint32_t cmd;
++    uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
++    union {
++        struct xen_sysctl_readconsole       readconsole;
++        struct xen_sysctl_tbuf_op           tbuf_op;
++        struct xen_sysctl_physinfo          physinfo;
++        struct xen_sysctl_sched_id          sched_id;
++        struct xen_sysctl_perfc_op          perfc_op;
++        struct xen_sysctl_getdomaininfolist getdomaininfolist;
++        struct xen_sysctl_debug_keys        debug_keys;
++        struct xen_sysctl_getcpuinfo        getcpuinfo;
++        struct xen_sysctl_availheap         availheap;
++        struct xen_sysctl_get_pmstat        get_pmstat;
++        struct xen_sysctl_cpu_hotplug       cpu_hotplug;
++        struct xen_sysctl_pm_op             pm_op;
++        struct xen_sysctl_page_offline_op   page_offline;
++        struct xen_sysctl_lockprof_op       lockprof_op;
++        uint8_t                             pad[128];
++    } u;
++};
++typedef struct xen_sysctl xen_sysctl_t;
++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);
++
++#endif /* __XEN_PUBLIC_SYSCTL_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/tmem.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,144 @@
++/******************************************************************************
++ * tmem.h
++ * 
++ * Guest OS interface to Xen Transcendent Memory.
++ * 
++ * 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, K A Fraser
++ */
++
++#ifndef __XEN_PUBLIC_TMEM_H__
++#define __XEN_PUBLIC_TMEM_H__
++
++#include "xen.h"
++
++/* Commands to HYPERVISOR_tmem_op() */
++#define TMEM_CONTROL               0
++#define TMEM_NEW_POOL              1
++#define TMEM_DESTROY_POOL          2
++#define TMEM_NEW_PAGE              3
++#define TMEM_PUT_PAGE              4
++#define TMEM_GET_PAGE              5
++#define TMEM_FLUSH_PAGE            6
++#define TMEM_FLUSH_OBJECT          7
++#define TMEM_READ                  8
++#define TMEM_WRITE                 9
++#define TMEM_XCHG                 10
++
++/* Privileged commands to HYPERVISOR_tmem_op() */
++#define TMEM_AUTH                 101 
++#define TMEM_RESTORE_NEW          102
++
++/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
++#define TMEMC_THAW                   0
++#define TMEMC_FREEZE                 1
++#define TMEMC_FLUSH                  2
++#define TMEMC_DESTROY                3
++#define TMEMC_LIST                   4
++#define TMEMC_SET_WEIGHT             5
++#define TMEMC_SET_CAP                6
++#define TMEMC_SET_COMPRESS           7
++#define TMEMC_QUERY_FREEABLE_MB      8
++#define TMEMC_SAVE_BEGIN             10
++#define TMEMC_SAVE_GET_VERSION       11
++#define TMEMC_SAVE_GET_MAXPOOLS      12
++#define TMEMC_SAVE_GET_CLIENT_WEIGHT 13
++#define TMEMC_SAVE_GET_CLIENT_CAP    14
++#define TMEMC_SAVE_GET_CLIENT_FLAGS  15
++#define TMEMC_SAVE_GET_POOL_FLAGS    16
++#define TMEMC_SAVE_GET_POOL_NPAGES   17
++#define TMEMC_SAVE_GET_POOL_UUID     18
++#define TMEMC_SAVE_GET_NEXT_PAGE     19
++#define TMEMC_SAVE_GET_NEXT_INV      20
++#define TMEMC_SAVE_END               21
++#define TMEMC_RESTORE_BEGIN          30
++#define TMEMC_RESTORE_PUT_PAGE       32
++#define TMEMC_RESTORE_FLUSH_PAGE     33
++
++/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
++#define TMEM_POOL_PERSIST          1
++#define TMEM_POOL_SHARED           2
++#define TMEM_POOL_PAGESIZE_SHIFT   4
++#define TMEM_POOL_PAGESIZE_MASK  0xf
++#define TMEM_POOL_VERSION_SHIFT   24
++#define TMEM_POOL_VERSION_MASK  0xff
++
++/* Bits for client flags (save/restore) */
++#define TMEM_CLIENT_COMPRESS       1
++#define TMEM_CLIENT_FROZEN         2
++
++/* Special errno values */
++#define EFROZEN                 1000
++#define EEMPTY                  1001
++
++
++#ifndef __ASSEMBLY__
++typedef xen_pfn_t tmem_cli_mfn_t;
++typedef XEN_GUEST_HANDLE(char) tmem_cli_va_t;
++struct tmem_op {
++    uint32_t cmd;
++    int32_t pool_id;
++    union {
++        struct {
++            uint64_t uuid[2];
++            uint32_t flags;
++            uint32_t arg1;
++        } new; /* for cmd == TMEM_NEW_POOL, TMEM_AUTH, TMEM_RESTORE_NEW */
++        struct { 
++            uint32_t subop;
++            uint32_t cli_id;
++            uint32_t arg1;
++            uint32_t arg2;
++            uint64_t arg3;
++            tmem_cli_va_t buf;
++        } ctrl; /* for cmd == TMEM_CONTROL */
++        struct {
++            
++            uint64_t object;
++            uint32_t index;
++            uint32_t tmem_offset;
++            uint32_t pfn_offset;
++            uint32_t len;
++            tmem_cli_mfn_t cmfn; /* client machine page frame */
++        } gen; /* for all other cmd ("generic") */
++    } u;
++};
++typedef struct tmem_op tmem_op_t;
++DEFINE_XEN_GUEST_HANDLE(tmem_op_t);
++
++struct tmem_handle {
++    uint32_t pool_id;
++    uint32_t index;
++    uint64_t oid;
++};
++
++#endif
++
++#endif /* __XEN_PUBLIC_TMEM_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/trace.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,208 @@
++/******************************************************************************
++ * include/public/trace.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.
++ *
++ * Mark Williamson, (C) 2004 Intel Research Cambridge
++ * Copyright (C) 2005 Bin Ren
++ */
++
++#ifndef __XEN_PUBLIC_TRACE_H__
++#define __XEN_PUBLIC_TRACE_H__
++
++#define TRACE_EXTRA_MAX    7
++#define TRACE_EXTRA_SHIFT 28
++
++/* Trace classes */
++#define TRC_CLS_SHIFT 16
++#define TRC_GEN      0x0001f000    /* General trace            */
++#define TRC_SCHED    0x0002f000    /* Xen Scheduler trace      */
++#define TRC_DOM0OP   0x0004f000    /* Xen DOM0 operation trace */
++#define TRC_HVM      0x0008f000    /* Xen HVM trace            */
++#define TRC_MEM      0x0010f000    /* Xen memory trace         */
++#define TRC_PV       0x0020f000    /* Xen PV traces            */
++#define TRC_SHADOW   0x0040f000    /* Xen shadow tracing       */
++#define TRC_PM       0x0080f000    /* Xen power management trace */
++#define TRC_ALL      0x0ffff000
++#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
++#define TRC_HD_CYCLE_FLAG (1UL<<31)
++#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
++#define TRC_HD_EXTRA(x)    (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
++
++/* Trace subclasses */
++#define TRC_SUBCLS_SHIFT 12
++
++/* trace subclasses for SVM */
++#define TRC_HVM_ENTRYEXIT 0x00081000   /* VMENTRY and #VMEXIT       */
++#define TRC_HVM_HANDLER   0x00082000   /* various HVM handlers      */
++
++#define TRC_SCHED_MIN       0x00021000   /* Just runstate changes */
++#define TRC_SCHED_VERBOSE   0x00028000   /* More inclusive scheduling */
++
++/* Trace events per class */
++#define TRC_LOST_RECORDS        (TRC_GEN + 1)
++#define TRC_TRACE_WRAP_BUFFER  (TRC_GEN + 2)
++#define TRC_TRACE_CPU_CHANGE    (TRC_GEN + 3)
++#define TRC_TRACE_IRQ           (TRC_GEN + 4)
++
++#define TRC_SCHED_RUNSTATE_CHANGE   (TRC_SCHED_MIN + 1)
++#define TRC_SCHED_CONTINUE_RUNNING  (TRC_SCHED_MIN + 2)
++#define TRC_SCHED_DOM_ADD        (TRC_SCHED_VERBOSE +  1)
++#define TRC_SCHED_DOM_REM        (TRC_SCHED_VERBOSE +  2)
++#define TRC_SCHED_SLEEP          (TRC_SCHED_VERBOSE +  3)
++#define TRC_SCHED_WAKE           (TRC_SCHED_VERBOSE +  4)
++#define TRC_SCHED_YIELD          (TRC_SCHED_VERBOSE +  5)
++#define TRC_SCHED_BLOCK          (TRC_SCHED_VERBOSE +  6)
++#define TRC_SCHED_SHUTDOWN       (TRC_SCHED_VERBOSE +  7)
++#define TRC_SCHED_CTL            (TRC_SCHED_VERBOSE +  8)
++#define TRC_SCHED_ADJDOM         (TRC_SCHED_VERBOSE +  9)
++#define TRC_SCHED_SWITCH         (TRC_SCHED_VERBOSE + 10)
++#define TRC_SCHED_S_TIMER_FN     (TRC_SCHED_VERBOSE + 11)
++#define TRC_SCHED_T_TIMER_FN     (TRC_SCHED_VERBOSE + 12)
++#define TRC_SCHED_DOM_TIMER_FN   (TRC_SCHED_VERBOSE + 13)
++#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
++#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
++
++#define TRC_MEM_PAGE_GRANT_MAP      (TRC_MEM + 1)
++#define TRC_MEM_PAGE_GRANT_UNMAP    (TRC_MEM + 2)
++#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3)
++
++#define TRC_PV_HYPERCALL             (TRC_PV +  1)
++#define TRC_PV_TRAP                  (TRC_PV +  3)
++#define TRC_PV_PAGE_FAULT            (TRC_PV +  4)
++#define TRC_PV_FORCED_INVALID_OP     (TRC_PV +  5)
++#define TRC_PV_EMULATE_PRIVOP        (TRC_PV +  6)
++#define TRC_PV_EMULATE_4GB           (TRC_PV +  7)
++#define TRC_PV_MATH_STATE_RESTORE    (TRC_PV +  8)
++#define TRC_PV_PAGING_FIXUP          (TRC_PV +  9)
++#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV + 10)
++#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_64_FLAG               (0x100) 
++
++#define TRC_SHADOW_NOT_SHADOW                 (TRC_SHADOW +  1)
++#define TRC_SHADOW_FAST_PROPAGATE             (TRC_SHADOW +  2)
++#define TRC_SHADOW_FAST_MMIO                  (TRC_SHADOW +  3)
++#define TRC_SHADOW_FALSE_FAST_PATH            (TRC_SHADOW +  4)
++#define TRC_SHADOW_MMIO                       (TRC_SHADOW +  5)
++#define TRC_SHADOW_FIXUP                      (TRC_SHADOW +  6)
++#define TRC_SHADOW_DOMF_DYING                 (TRC_SHADOW +  7)
++#define TRC_SHADOW_EMULATE                    (TRC_SHADOW +  8)
++#define TRC_SHADOW_EMULATE_UNSHADOW_USER      (TRC_SHADOW +  9)
++#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ    (TRC_SHADOW + 10)
++#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
++#define TRC_SHADOW_WRMAP_BF                   (TRC_SHADOW + 12)
++#define TRC_SHADOW_PREALLOC_UNPIN             (TRC_SHADOW + 13)
++#define TRC_SHADOW_RESYNC_FULL                (TRC_SHADOW + 14)
++#define TRC_SHADOW_RESYNC_ONLY                (TRC_SHADOW + 15)
++
++/* 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 + 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)
++#define TRC_HVM_MSR_WRITE       (TRC_HVM_HANDLER + 0x0D)
++#define TRC_HVM_CPUID           (TRC_HVM_HANDLER + 0x0E)
++#define TRC_HVM_INTR            (TRC_HVM_HANDLER + 0x0F)
++#define TRC_HVM_NMI             (TRC_HVM_HANDLER + 0x10)
++#define TRC_HVM_SMI             (TRC_HVM_HANDLER + 0x11)
++#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_IOPORT_READ     (TRC_HVM_HANDLER + 0x16)
++#define TRC_HVM_IOMEM_READ      (TRC_HVM_HANDLER + 0x17)
++#define TRC_HVM_CLTS            (TRC_HVM_HANDLER + 0x18)
++#define TRC_HVM_LMSW            (TRC_HVM_HANDLER + 0x19)
++#define TRC_HVM_LMSW64          (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
++#define TRC_HVM_INTR_WINDOW     (TRC_HVM_HANDLER + 0x20)
++#define TRC_HVM_IOPORT_WRITE    (TRC_HVM_HANDLER + 0x216)
++#define TRC_HVM_IOMEM_WRITE     (TRC_HVM_HANDLER + 0x217)
++
++/* trace subclasses for power management */
++#define TRC_PM_FREQ     0x00801000      /* xen cpu freq events */
++#define TRC_PM_IDLE     0x00802000      /* xen cpu idle events */
++
++/* trace events for per class */
++#define TRC_PM_FREQ_CHANGE      (TRC_PM_FREQ + 0x01)
++#define TRC_PM_IDLE_ENTRY       (TRC_PM_IDLE + 0x01)
++#define TRC_PM_IDLE_EXIT        (TRC_PM_IDLE + 0x02)
++
++/* This structure represents a single trace buffer record. */
++struct t_rec {
++    uint32_t event:28;
++    uint32_t extra_u32:3;         /* # entries in trailing extra_u32[] array */
++    uint32_t cycles_included:1;   /* u.cycles or u.no_cycles? */
++    union {
++        struct {
++            uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
++            uint32_t extra_u32[7];         /* event data items */
++        } cycles;
++        struct {
++            uint32_t extra_u32[7];         /* event data items */
++        } nocycles;
++    } u;
++};
++
++/*
++ * This structure contains the metadata for a single trace buffer.  The head
++ * 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.    */
++};
++
++#endif /* __XEN_PUBLIC_TRACE_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/xen-compat.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,44 @@
++/******************************************************************************
++ * xen-compat.h
++ * 
++ * Guest OS interface to Xen.  Compatibility layer.
++ * 
++ * 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) 2006, Christian Limpach
++ */
++
++#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
++#define __XEN_PUBLIC_XEN_COMPAT_H__
++
++#define __XEN_LATEST_INTERFACE_VERSION__ 0x0003020a
++
++#if defined(__XEN__) || defined(__XEN_TOOLS__)
++/* Xen is built with matching headers and implements the latest interface. */
++#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
++#elif !defined(__XEN_INTERFACE_VERSION__)
++/* Guests which do not specify a version get the legacy interface. */
++#define __XEN_INTERFACE_VERSION__ 0x00000000
++#endif
++
++#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
++#error "These header files do not support the requested interface version."
++#endif
++
++#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/xenoprof.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,138 @@
++/******************************************************************************
++ * xenoprof.h
++ * 
++ * Interface for enabling system wide profiling based on hardware performance
++ * counters
++ * 
++ * 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) 2005 Hewlett-Packard Co.
++ * Written by Aravind Menon & Jose Renato Santos
++ */
++
++#ifndef __XEN_PUBLIC_XENOPROF_H__
++#define __XEN_PUBLIC_XENOPROF_H__
++
++#include "xen.h"
++
++/*
++ * Commands to HYPERVISOR_xenoprof_op().
++ */
++#define XENOPROF_init                0
++#define XENOPROF_reset_active_list   1
++#define XENOPROF_reset_passive_list  2
++#define XENOPROF_set_active          3
++#define XENOPROF_set_passive         4
++#define XENOPROF_reserve_counters    5
++#define XENOPROF_counter             6
++#define XENOPROF_setup_events        7
++#define XENOPROF_enable_virq         8
++#define XENOPROF_start               9
++#define XENOPROF_stop               10
++#define XENOPROF_disable_virq       11
++#define XENOPROF_release_counters   12
++#define XENOPROF_shutdown           13
++#define XENOPROF_get_buffer         14
++#define XENOPROF_set_backtrace      15
++#define XENOPROF_last_op            15
++
++#define MAX_OPROF_EVENTS    32
++#define MAX_OPROF_DOMAINS   25
++#define XENOPROF_CPU_TYPE_SIZE 64
++
++/* Xenoprof performance events (not Xen events) */
++struct event_log {
++    uint64_t eip;
++    uint8_t mode;
++    uint8_t event;
++};
++
++/* PC value that indicates a special code */
++#define XENOPROF_ESCAPE_CODE ~0UL
++/* Transient events for the xenoprof->oprofile cpu buf */
++#define XENOPROF_TRACE_BEGIN 1
++
++/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
++struct xenoprof_buf {
++    uint32_t event_head;
++    uint32_t event_tail;
++    uint32_t event_size;
++    uint32_t vcpu_id;
++    uint64_t xen_samples;
++    uint64_t kernel_samples;
++    uint64_t user_samples;
++    uint64_t lost_samples;
++    struct event_log event_log[1];
++};
++#ifndef __XEN__
++typedef struct xenoprof_buf xenoprof_buf_t;
++DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
++#endif
++
++struct xenoprof_init {
++    int32_t  num_events;
++    int32_t  is_primary;
++    char cpu_type[XENOPROF_CPU_TYPE_SIZE];
++};
++typedef struct xenoprof_init xenoprof_init_t;
++DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
++
++struct xenoprof_get_buffer {
++    int32_t  max_samples;
++    int32_t  nbuf;
++    int32_t  bufsize;
++    uint64_t buf_gmaddr;
++};
++typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
++DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
++
++struct xenoprof_counter {
++    uint32_t ind;
++    uint64_t count;
++    uint32_t enabled;
++    uint32_t event;
++    uint32_t hypervisor;
++    uint32_t kernel;
++    uint32_t user;
++    uint64_t unit_mask;
++};
++typedef struct xenoprof_counter xenoprof_counter_t;
++DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
++
++typedef struct xenoprof_passive {
++    uint16_t domain_id;
++    int32_t  max_samples;
++    int32_t  nbuf;
++    int32_t  bufsize;
++    uint64_t buf_gmaddr;
++} xenoprof_passive_t;
++DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
++
++
++#endif /* __XEN_PUBLIC_XENOPROF_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/xsm/acm.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,223 @@
++/*
++ * acm.h: Xen access control module interface defintions
++ *
++ * 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.
++ *
++ * Reiner Sailer <sailer@watson.ibm.com>
++ * Copyright (c) 2005, International Business Machines Corporation.
++ */
++
++#ifndef _XEN_PUBLIC_ACM_H
++#define _XEN_PUBLIC_ACM_H
++
++#include "../xen.h"
++
++/* default ssid reference value if not supplied */
++#define ACM_DEFAULT_SSID  0x0
++#define ACM_DEFAULT_LOCAL_SSID  0x0
++
++/* Internal ACM ERROR types */
++#define ACM_OK     0
++#define ACM_UNDEF   -1
++#define ACM_INIT_SSID_ERROR  -2
++#define ACM_INIT_SOID_ERROR  -3
++#define ACM_ERROR          -4
++
++/* External ACCESS DECISIONS */
++#define ACM_ACCESS_PERMITTED        0
++#define ACM_ACCESS_DENIED           -111
++#define ACM_NULL_POINTER_ERROR      -200
++
++/*
++   Error codes reported in when trying to test for a new policy
++   These error codes are reported in an array of tuples where
++   each error code is followed by a parameter describing the error
++   more closely, such as a domain id.
++*/
++#define ACM_EVTCHN_SHARING_VIOLATION       0x100
++#define ACM_GNTTAB_SHARING_VIOLATION       0x101
++#define ACM_DOMAIN_LOOKUP                  0x102
++#define ACM_CHWALL_CONFLICT                0x103
++#define ACM_SSIDREF_IN_USE                 0x104
++
++
++/* primary policy in lower 4 bits */
++#define ACM_NULL_POLICY 0
++#define ACM_CHINESE_WALL_POLICY 1
++#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
++#define ACM_POLICY_UNDEFINED 15
++
++/* combinations have secondary policy component in higher 4bit */
++#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
++    ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
++
++/* policy: */
++#define ACM_POLICY_NAME(X) \
++ ((X) == (ACM_NULL_POLICY)) ? "NULL" :                        \
++    ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL" :        \
++    ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT" : \
++    ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT" : \
++     "UNDEFINED"
++
++/* the following policy versions must be increased
++ * whenever the interpretation of the related
++ * policy's data structure changes
++ */
++#define ACM_POLICY_VERSION 4
++#define ACM_CHWALL_VERSION 1
++#define ACM_STE_VERSION  1
++
++/* defines a ssid reference used by xen */
++typedef uint32_t ssidref_t;
++
++/* hooks that are known to domains */
++#define ACMHOOK_none          0
++#define ACMHOOK_sharing       1
++#define ACMHOOK_authorization 2
++#define ACMHOOK_conflictset   3
++
++/* -------security policy relevant type definitions-------- */
++
++/* type identifier; compares to "equal" or "not equal" */
++typedef uint16_t domaintype_t;
++
++/* CHINESE WALL POLICY DATA STRUCTURES
++ *
++ * current accumulated conflict type set:
++ * When a domain is started and has a type that is in
++ * a conflict set, the conflicting types are incremented in
++ * the aggregate set. When a domain is destroyed, the 
++ * conflicting types to its type are decremented.
++ * If a domain has multiple types, this procedure works over
++ * all those types.
++ *
++ * conflict_aggregate_set[i] holds the number of
++ *   running domains that have a conflict with type i.
++ *
++ * running_types[i] holds the number of running domains
++ *        that include type i in their ssidref-referenced type set
++ *
++ * conflict_sets[i][j] is "0" if type j has no conflict
++ *    with type i and is "1" otherwise.
++ */
++/* 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 */
++
++/* V3 of the policy buffer aded a version structure */
++struct acm_policy_version
++{
++    uint32_t major;
++    uint32_t minor;
++};
++
++
++/* each buffer consists of all policy information for
++ * the respective policy given in the policy code
++ *
++ * acm_policy_buffer, acm_chwall_policy_buffer,
++ * and acm_ste_policy_buffer need to stay 32-bit aligned
++ * because we create binary policies also with external
++ * tools that assume packed representations (e.g. the java tool)
++ */
++struct acm_policy_buffer {
++    uint32_t magic;
++    uint32_t policy_version; /* ACM_POLICY_VERSION */
++    uint32_t len;
++    uint32_t policy_reference_offset;
++    uint32_t primary_policy_code;
++    uint32_t primary_buffer_offset;
++    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 */
++};
++
++
++struct acm_policy_reference_buffer {
++    uint32_t len;
++};
++
++struct acm_chwall_policy_buffer {
++    uint32_t policy_version; /* ACM_CHWALL_VERSION */
++    uint32_t policy_code;
++    uint32_t chwall_max_types;
++    uint32_t chwall_max_ssidrefs;
++    uint32_t chwall_max_conflictsets;
++    uint32_t chwall_ssid_offset;
++    uint32_t chwall_conflict_sets_offset;
++    uint32_t chwall_running_types_offset;
++    uint32_t chwall_conflict_aggregate_offset;
++};
++
++struct acm_ste_policy_buffer {
++    uint32_t policy_version; /* ACM_STE_VERSION */
++    uint32_t policy_code;
++    uint32_t ste_max_types;
++    uint32_t ste_max_ssidrefs;
++    uint32_t ste_ssid_offset;
++};
++
++struct acm_stats_buffer {
++    uint32_t magic;
++    uint32_t len;
++    uint32_t primary_policy_code;
++    uint32_t primary_stats_offset;
++    uint32_t secondary_policy_code;
++    uint32_t secondary_stats_offset;
++};
++
++struct acm_ste_stats_buffer {
++    uint32_t ec_eval_count;
++    uint32_t gt_eval_count;
++    uint32_t ec_denied_count;
++    uint32_t gt_denied_count;
++    uint32_t ec_cachehit_count;
++    uint32_t gt_cachehit_count;
++};
++
++struct acm_ssid_buffer {
++    uint32_t len;
++    ssidref_t ssidref;
++    uint32_t policy_reference_offset;
++    uint32_t primary_policy_code;
++    uint32_t primary_max_types;
++    uint32_t primary_types_offset;
++    uint32_t secondary_policy_code;
++    uint32_t secondary_max_types;
++    uint32_t secondary_types_offset;
++};
++
++#endif
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/xsm/acm_ops.h	2007-10-22 13:39:15.000000000 +0200
+@@ -0,0 +1,159 @@
++/*
++ * acm_ops.h: Xen access control module hypervisor commands
++ *
++ * 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.
++ *
++ * Reiner Sailer <sailer@watson.ibm.com>
++ * Copyright (c) 2005,2006 International Business Machines Corporation.
++ */
++
++#ifndef __XEN_PUBLIC_ACM_OPS_H__
++#define __XEN_PUBLIC_ACM_OPS_H__
++
++#include "../xen.h"
++#include "acm.h"
++
++/*
++ * Make sure you increment the interface version whenever you modify this file!
++ * This makes sure that old versions of acm tools will stop working in a
++ * well-defined way (rather than crashing the machine, for instance).
++ */
++#define ACM_INTERFACE_VERSION   0xAAAA000A
++
++/************************************************************************/
++
++/*
++ * Prototype for this hypercall is:
++ *  int acm_op(int cmd, void *args)
++ * @cmd  == ACMOP_??? (access control module operation).
++ * @args == Operation-specific extra arguments (NULL if none).
++ */
++
++
++#define ACMOP_setpolicy         1
++struct acm_setpolicy {
++    /* IN */
++    XEN_GUEST_HANDLE_64(void) pushcache;
++    uint32_t pushcache_size;
++};
++
++
++#define ACMOP_getpolicy         2
++struct acm_getpolicy {
++    /* IN */
++    XEN_GUEST_HANDLE_64(void) pullcache;
++    uint32_t pullcache_size;
++};
++
++
++#define ACMOP_dumpstats         3
++struct acm_dumpstats {
++    /* IN */
++    XEN_GUEST_HANDLE_64(void) pullcache;
++    uint32_t pullcache_size;
++};
++
++
++#define ACMOP_getssid           4
++#define ACM_GETBY_ssidref  1
++#define ACM_GETBY_domainid 2
++struct acm_getssid {
++    /* IN */
++    uint32_t get_ssid_by; /* ACM_GETBY_* */
++    union {
++        domaintype_t domainid;
++        ssidref_t    ssidref;
++    } id;
++    XEN_GUEST_HANDLE_64(void) ssidbuf;
++    uint32_t ssidbuf_size;
++};
++
++#define ACMOP_getdecision      5
++struct acm_getdecision {
++    /* IN */
++    uint32_t get_decision_by1; /* ACM_GETBY_* */
++    uint32_t get_decision_by2; /* ACM_GETBY_* */
++    union {
++        domaintype_t domainid;
++        ssidref_t    ssidref;
++    } id1;
++    union {
++        domaintype_t domainid;
++        ssidref_t    ssidref;
++    } id2;
++    uint32_t hook;
++    /* OUT */
++    uint32_t acm_decision;
++};
++
++
++#define ACMOP_chgpolicy        6
++struct acm_change_policy {
++    /* IN */
++    XEN_GUEST_HANDLE_64(void) policy_pushcache;
++    uint32_t policy_pushcache_size;
++    XEN_GUEST_HANDLE_64(void) del_array;
++    uint32_t delarray_size;
++    XEN_GUEST_HANDLE_64(void) chg_array;
++    uint32_t chgarray_size;
++    /* OUT */
++    /* array with error code */
++    XEN_GUEST_HANDLE_64(void) err_array;
++    uint32_t errarray_size;
++};
++
++#define ACMOP_relabeldoms       7
++struct acm_relabel_doms {
++    /* IN */
++    XEN_GUEST_HANDLE_64(void) relabel_map;
++    uint32_t relabel_map_size;
++    /* OUT */
++    XEN_GUEST_HANDLE_64(void) err_array;
++    uint32_t errarray_size;
++};
++
++/* future interface to Xen */
++struct xen_acmctl {
++    uint32_t cmd;
++    uint32_t interface_version;
++    union {
++        struct acm_setpolicy     setpolicy;
++        struct acm_getpolicy     getpolicy;
++        struct acm_dumpstats     dumpstats;
++        struct acm_getssid       getssid;
++        struct acm_getdecision   getdecision;
++        struct acm_change_policy change_policy;
++        struct acm_relabel_doms  relabel_doms;
++    } u;
++};
++
++typedef struct xen_acmctl xen_acmctl_t;
++DEFINE_XEN_GUEST_HANDLE(xen_acmctl_t);
++
++#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
++
++/*
++ * Local variables:
++ * mode: C
++ * c-set-style: "BSD"
++ * c-basic-offset: 4
++ * tab-width: 4
++ * indent-tabs-mode: nil
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/interface/xsm/flask_op.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,47 @@
++/*
++ *  This file contains the flask_op hypercall commands and definitions.
++ *
++ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
++ *
++ *  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.
++ */
++
++#ifndef __FLASK_OP_H__
++#define __FLASK_OP_H__
++
++#define FLASK_LOAD              1
++#define FLASK_GETENFORCE        2
++#define FLASK_SETENFORCE        3
++#define FLASK_CONTEXT_TO_SID    4
++#define FLASK_SID_TO_CONTEXT    5
++#define FLASK_ACCESS            6
++#define FLASK_CREATE            7
++#define FLASK_RELABEL           8
++#define FLASK_USER              9
++#define FLASK_POLICYVERS        10
++#define FLASK_GETBOOL           11
++#define FLASK_SETBOOL           12
++#define FLASK_COMMITBOOLS       13
++#define FLASK_MLS               14
++#define FLASK_DISABLE           15
++#define FLASK_GETAVC_THRESHOLD  16
++#define FLASK_SETAVC_THRESHOLD  17
++#define FLASK_AVC_HASHSTATS     18
++#define FLASK_AVC_CACHESTATS    19
++#define FLASK_MEMBER            20
++#define FLASK_ADD_OCONTEXT      21
++#define FLASK_DEL_OCONTEXT      22
++
++#define FLASK_LAST              FLASK_DEL_OCONTEXT
++
++typedef struct flask_op {
++    uint32_t  cmd;
++    uint32_t  size;
++    char      *buf;
++} flask_op_t;
++
++DEFINE_XEN_GUEST_HANDLE(flask_op_t);
++
++#endif
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-staging-build
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-staging-build
@@ -0,0 +1,40 @@
+From: jbeulich@novell.com
+Subject: fix issue with Windows-style types used in drivers/staging/
+Patch-mainline: obsolete
+
+--- head-2009-11-20.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:44:04.000000000 +0100
++++ head-2009-11-20/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:45:08.000000000 +0100
+@@ -354,4 +354,9 @@ MULTI_grant_table_op(multicall_entry_t *
+ 
+ #define uvm_multi(cpumask) ((unsigned long)cpumask_bits(cpumask) | UVMF_MULTI)
+ 
++#ifdef LINUX
++/* drivers/staging/ use Windows-style types, including VOID */
++#undef VOID
++#endif
++
+ #endif /* __HYPERVISOR_H__ */
+--- head-2009-11-20.orig/drivers/staging/vt6655/ttype.h	2009-11-23 10:15:03.000000000 +0100
++++ head-2009-11-20/drivers/staging/vt6655/ttype.h	2009-10-13 17:02:12.000000000 +0200
+@@ -30,6 +30,9 @@
+ #ifndef __TTYPE_H__
+ #define __TTYPE_H__
+ 
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++#endif
+ 
+ /******* Common definitions and typedefs ***********************************/
+ 
+--- head-2009-11-20.orig/drivers/staging/vt6656/ttype.h	2009-11-23 10:15:03.000000000 +0100
++++ head-2009-11-20/drivers/staging/vt6656/ttype.h	2009-10-13 17:02:12.000000000 +0200
+@@ -30,6 +30,9 @@
+ #ifndef __TTYPE_H__
+ #define __TTYPE_H__
+ 
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++#endif
+ 
+ /******* Common definitions and typedefs ***********************************/
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-vmalloc_32
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-vmalloc_32
@@ -0,0 +1,66 @@
+From: jbeulich@novell.com
+Subject: guarantee 32-bit (bus-)addressability of vmalloc_32() output
+Patch-mainline: non-Xen part in 2.6.33
+References: bnc#548010, bnc#552492
+
+--- head-2009-12-16.orig/mm/vmalloc.c	2009-12-16 11:52:01.000000000 +0100
++++ head-2009-12-16/mm/vmalloc.c	2009-12-16 12:15:18.000000000 +0100
+@@ -1416,6 +1416,14 @@ static void *__vmalloc_area_node(struct 
+ {
+ 	struct page **pages;
+ 	unsigned int nr_pages, array_size, i;
++	gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
++#ifdef CONFIG_XEN
++	gfp_t dma_mask = gfp_mask & (__GFP_DMA | __GFP_DMA32);
++
++	BUILD_BUG_ON((__GFP_DMA | __GFP_DMA32) != (__GFP_DMA + __GFP_DMA32));
++	if (dma_mask == (__GFP_DMA | __GFP_DMA32))
++		gfp_mask &= ~(__GFP_DMA | __GFP_DMA32);
++#endif
+ 
+ 	nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT;
+ 	array_size = (nr_pages * sizeof(struct page *));
+@@ -1423,13 +1431,12 @@ static void *__vmalloc_area_node(struct 
+ 	area->nr_pages = nr_pages;
+ 	/* Please note that the recursion is strictly bounded. */
+ 	if (array_size > PAGE_SIZE) {
+-		pages = __vmalloc_node(array_size, 1, gfp_mask | __GFP_ZERO,
+-				PAGE_KERNEL, node, caller);
++		pages = __vmalloc_node(array_size, 1,
++				       nested_gfp | __GFP_HIGHMEM,
++				       PAGE_KERNEL, node, caller);
+ 		area->flags |= VM_VPAGES;
+ 	} else {
+-		pages = kmalloc_node(array_size,
+-				(gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO,
+-				node);
++		pages = kmalloc_node(array_size, nested_gfp, node);
+ 	}
+ 	area->pages = pages;
+ 	area->caller = caller;
+@@ -1453,6 +1460,16 @@ static void *__vmalloc_area_node(struct 
+ 			goto fail;
+ 		}
+ 		area->pages[i] = page;
++#ifdef CONFIG_XEN
++		if (dma_mask) {
++			if (xen_limit_pages_to_max_mfn(page, 0, 32)) {
++				area->nr_pages = i + 1;
++				goto fail;
++			}
++			if (gfp_mask & __GFP_ZERO)
++				clear_highpage(page);
++		}
++#endif
+ 	}
+ 
+ 	if (map_vm_area(area, prot, &pages))
+@@ -1612,6 +1629,8 @@ void *vmalloc_exec(unsigned long size)
+ #define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL
+ #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)
+ #define GFP_VMALLOC32 GFP_DMA | GFP_KERNEL
++#elif defined(CONFIG_XEN)
++#define GFP_VMALLOC32 __GFP_DMA | __GFP_DMA32 | GFP_KERNEL
+ #else
+ #define GFP_VMALLOC32 GFP_KERNEL
+ #endif
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.22
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.22
@@ -0,0 +1,7412 @@
+From: www.kernel.org
+Subject: Update to 2.6.22
+Patch-mainline: 2.6.22
+
+Automatically created from "patches.kernel.org/patch-2.6.22" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:00:19.000000000 +0100
+@@ -1659,7 +1659,7 @@ config PHYSICAL_START
+ 
+ config RELOCATABLE
+ 	bool "Build a relocatable kernel"
+-	depends on !X86_XEN
++	depends on !XEN
+ 	default y
+ 	---help---
+ 	  This builds a kernel image that retains relocation information
+@@ -1719,7 +1719,6 @@ config COMPAT_VDSO
+ 	def_bool y
+ 	prompt "Compat VDSO support"
+ 	depends on X86_32 || IA32_EMULATION
+-	depends on !X86_XEN
+ 	---help---
+ 	  Map the 32-bit VDSO to the predictable old-style address too.
+ 	---help---
+@@ -1942,6 +1941,7 @@ config PCI
+ 	bool "PCI support"
+ 	default y
+ 	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
++	select ARCH_SUPPORTS_MSI if (XEN_UNPRIVILEGED_GUEST && XEN_PCIDEV_FRONTEND)
+ 	---help---
+ 	  Find out whether you have a PCI motherboard. PCI is the name of a
+ 	  bus system, i.e. the way the CPU talks to the other stuff inside
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:49:47.000000000 +0100
+@@ -141,4 +141,4 @@ endif
+ disabled-obj-$(CONFIG_XEN) := early-quirks.o hpet.o i8253.o i8259_$(BITS).o reboot.o \
+ 	smpboot_$(BITS).o tsc_$(BITS).o tsc_sync.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += mpparse_64.o
+-%/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
++%/head_64.o %/head_64.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -19,7 +19,6 @@
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+ #include <linux/bootmem.h>
+-#include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/kernel_stat.h>
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:49:47.000000000 +0100
+@@ -111,11 +111,6 @@ void foo(void)
+ 
+ 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+ 
+-#ifdef CONFIG_XEN
+-	BLANK();
+-	OFFSET(XEN_START_mfn_list, start_info, mfn_list);
+-#endif
+-
+ #ifdef CONFIG_PARAVIRT
+ 	BLANK();
+ 	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -22,16 +22,40 @@
+ #define phys_pkg_id(a,b) a
+ #endif
+ #endif
+-#include <asm/pda.h>
+ #include <asm/hypervisor.h>
+ 
+ #include "cpu.h"
+ 
+-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
+-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
++DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
++	[GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },
++	[GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },
++	[GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },
++	[GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },
++#ifndef CONFIG_XEN
++	/*
++	 * Segments used for calling PnP BIOS have byte granularity.
++	 * They code segments and data segments have fixed 64k limits,
++	 * the transfer segment sizes are set at run time.
++	 */
++	[GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
++	[GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */
++	[GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */
++	[GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */
++	[GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */
++	/*
++	 * The APM segments have byte granularity and their bases
++	 * are set at run time.  All have 64k limits.
++	 */
++	[GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
++	/* 16-bit code */
++	[GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
++	[GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+ 
+-struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly;
+-EXPORT_SYMBOL(_cpu_pda);
++	[GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
++#endif
++	[GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
++} };
++EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+ 
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_fxsr __cpuinitdata;
+@@ -375,7 +399,7 @@ __setup("serialnumber", x86_serial_nr_se
+ /*
+  * This does the hard work of actually picking apart the CPU stuff...
+  */
+-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ {
+ 	int i;
+ 
+@@ -486,15 +510,22 @@ void __cpuinit identify_cpu(struct cpuin
+ 
+ 	/* Init Machine Check Exception if available. */
+ 	mcheck_init(c);
++}
+ 
+-	if (c == &boot_cpu_data)
+-		sysenter_setup();
++void __init identify_boot_cpu(void)
++{
++	identify_cpu(&boot_cpu_data);
++	sysenter_setup();
+ 	enable_sep_cpu();
++	mtrr_bp_init();
++}
+ 
+-	if (c == &boot_cpu_data)
+-		mtrr_bp_init();
+-	else
+-		mtrr_ap_init();
++void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
++{
++	BUG_ON(c == &boot_cpu_data);
++	identify_cpu(c);
++	enable_sep_cpu();
++	mtrr_ap_init();
+ }
+ 
+ #ifdef CONFIG_X86_HT
+@@ -608,136 +639,47 @@ void __init early_cpu_init(void)
+ #endif
+ }
+ 
+-/* Make sure %gs is initialized properly in idle threads */
++/* Make sure %fs is initialized properly in idle threads */
+ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+ {
+ 	memset(regs, 0, sizeof(struct pt_regs));
+-	regs->xfs = __KERNEL_PDA;
++	regs->xfs = __KERNEL_PERCPU;
+ 	return regs;
+ }
+ 
+-static __cpuinit int alloc_gdt(int cpu)
+-{
+-	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+-	struct desc_struct *gdt;
+-	struct i386_pda *pda;
+-
+-	gdt = (struct desc_struct *)cpu_gdt_descr->address;
+-	pda = cpu_pda(cpu);
+-
+-	/*
+-	 * This is a horrible hack to allocate the GDT.  The problem
+-	 * is that cpu_init() is called really early for the boot CPU
+-	 * (and hence needs bootmem) but much later for the secondary
+-	 * CPUs, when bootmem will have gone away
+-	 */
+-	if (NODE_DATA(0)->bdata->node_bootmem_map) {
+-		BUG_ON(gdt != NULL || pda != NULL);
+-
+-		gdt = alloc_bootmem_pages(PAGE_SIZE);
+-		pda = alloc_bootmem(sizeof(*pda));
+-		/* alloc_bootmem(_pages) panics on failure, so no check */
+-
+-		memset(gdt, 0, PAGE_SIZE);
+-		memset(pda, 0, sizeof(*pda));
+-	} else {
+-		/* GDT and PDA might already have been allocated if
+-		   this is a CPU hotplug re-insertion. */
+-		if (gdt == NULL)
+-			gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
+-
+-		if (pda == NULL)
+-			pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu));
+-
+-		if (unlikely(!gdt || !pda)) {
+-			free_pages((unsigned long)gdt, 0);
+-			kfree(pda);
+-			return 0;
+-		}
+-	}
+-
+- 	cpu_gdt_descr->address = (unsigned long)gdt;
+-	cpu_pda(cpu) = pda;
+-
+-	return 1;
+-}
+-
+-/* Initial PDA used by boot CPU */
+-struct i386_pda boot_pda = {
+-	._pda = &boot_pda,
+-	.cpu_number = 0,
+-	.pcurrent = &init_task,
+-};
+-
+-static inline void set_kernel_fs(void)
+-{
+-	/* Set %fs for this CPU's PDA.  Memory clobber is to create a
+-	   barrier with respect to any PDA operations, so the compiler
+-	   doesn't move any before here. */
+-	asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
+-}
+-
+-/* Initialize the CPU's GDT and PDA.  The boot CPU does this for
+-   itself, but secondaries find this done for them. */
+-__cpuinit int init_gdt(int cpu, struct task_struct *idle)
+-{
+-	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+-	struct desc_struct *gdt;
+-	struct i386_pda *pda;
+-
+-	/* For non-boot CPUs, the GDT and PDA should already have been
+-	   allocated. */
+-	if (!alloc_gdt(cpu)) {
+-		printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu);
+-		return 0;
+-	}
+-
+-	gdt = (struct desc_struct *)cpu_gdt_descr->address;
+-	pda = cpu_pda(cpu);
+-
+-	BUG_ON(gdt == NULL || pda == NULL);
+-
+-	/*
+-	 * Initialize the per-CPU GDT with the boot GDT,
+-	 * and set up the GDT descriptor:
+-	 */
+- 	memcpy(gdt, cpu_gdt_table, GDT_SIZE);
+-	cpu_gdt_descr->size = GDT_SIZE - 1;
+-
+-	pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
+-			(u32 *)&gdt[GDT_ENTRY_PDA].b,
+-			(unsigned long)pda, sizeof(*pda) - 1,
+-			0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
+-
+-	memset(pda, 0, sizeof(*pda));
+-	pda->_pda = pda;
+-	pda->cpu_number = cpu;
+-	pda->pcurrent = idle;
+-
+-	return 1;
+-}
+-
+-void __cpuinit cpu_set_gdt(int cpu)
++/* Current gdt points %fs at the "master" per-cpu area: after this,
++ * it's on the real one. */
++void switch_to_new_gdt(void)
+ {
+-	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++	struct Xgt_desc_struct gdt_descr;
+ 	unsigned long va, frames[16];
+ 	int f;
+ 
+-	for (va = cpu_gdt_descr->address, f = 0;
+-	     va < cpu_gdt_descr->address + cpu_gdt_descr->size;
++	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
++	gdt_descr.size = GDT_SIZE - 1;
++
++	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_lowmem_page_readonly(
+ 			(void *)va, XENFEAT_writable_descriptor_tables);
+ 	}
+-	BUG_ON(HYPERVISOR_set_gdt(frames, (cpu_gdt_descr->size + 1) / 8));
+-
+-	set_kernel_fs();
++	if (HYPERVISOR_set_gdt(frames, (gdt_descr.size + 1) / 8))
++		BUG();
++	asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
+ }
+ 
+-/* Common CPU init for both boot and secondary CPUs */
+-static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
++/*
++ * 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.
++ */
++void __cpuinit cpu_init(void)
+ {
++	int cpu = smp_processor_id();
++	struct task_struct *curr = current;
+ #ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct * t = &per_cpu(init_tss, cpu);
+ #endif
+@@ -759,6 +701,8 @@ static void __cpuinit _cpu_init(int cpu,
+ 		set_in_cr4(X86_CR4_TSD);
+ 	}
+ 
++	switch_to_new_gdt();
++
+ 	/*
+ 	 * Set up and load the per-CPU TSS and LDT
+ 	 */
+@@ -796,38 +740,6 @@ static void __cpuinit _cpu_init(int cpu,
+ 	mxcsr_feature_mask_init();
+ }
+ 
+-/* Entrypoint to initialize secondary CPU */
+-void __cpuinit secondary_cpu_init(void)
+-{
+-	int cpu = smp_processor_id();
+-	struct task_struct *curr = current;
+-
+-	_cpu_init(cpu, curr);
+-}
+-
+-/*
+- * 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.
+- */
+-void __cpuinit cpu_init(void)
+-{
+-	int cpu = smp_processor_id();
+-	struct task_struct *curr = current;
+-
+-	/* Set up the real GDT and PDA, so we can transition from the
+-	   boot versions. */
+-	if (!init_gdt(cpu, curr)) {
+-		/* failed to allocate something; not much we can do... */
+-		for (;;)
+-			local_irq_enable();
+-	}
+-
+-	cpu_set_gdt(cpu);
+-	_cpu_init(cpu, curr);
+-}
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ void __cpuinit cpu_uninit(void)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -167,7 +167,7 @@ mtrr_del(int reg, unsigned long base, un
+ EXPORT_SYMBOL(mtrr_add);
+ EXPORT_SYMBOL(mtrr_del);
+ 
+-void __init mtrr_bp_init(void)
++__init void mtrr_bp_init(void)
+ {
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -162,26 +162,27 @@ static struct resource standard_io_resou
+ 
+ static int __init romsignature(const unsigned char *rom)
+ {
++	const unsigned short * const ptr = (const unsigned short *)rom;
+ 	unsigned short sig;
+ 
+-	return probe_kernel_address((const unsigned short *)rom, sig) == 0 &&
+-	       sig == ROMSIGNATURE;
++	return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
+ }
+ 
+-static int __init romchecksum(unsigned char *rom, unsigned long length)
++static int __init romchecksum(const unsigned char *rom, unsigned long length)
+ {
+-	unsigned char sum;
++	unsigned char sum, c;
+ 
+-	for (sum = 0; length; length--)
+-		sum += *rom++;
+-	return sum == 0;
++	for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
++		sum += c;
++	return !length && !sum;
+ }
+ 
+ static void __init probe_roms(void)
+ {
++	const unsigned char *rom;
+ 	unsigned long start, length, upper;
+-	unsigned char *rom;
+-	int	      i;
++	unsigned char c;
++	int i;
+ 
+ #ifdef CONFIG_XEN
+ 	/* Nothing to do if not running in dom0. */
+@@ -198,8 +199,11 @@ static void __init probe_roms(void)
+ 
+ 		video_rom_resource.start = start;
+ 
++		if (probe_kernel_address(rom + 2, c) != 0)
++			continue;
++
+ 		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
++		length = c * 512;
+ 
+ 		/* if checksum okay, trust length byte */
+ 		if (length && romchecksum(rom, length))
+@@ -233,8 +237,11 @@ static void __init probe_roms(void)
+ 		if (!romsignature(rom))
+ 			continue;
+ 
++		if (probe_kernel_address(rom + 2, c) != 0)
++			continue;
++
+ 		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
++		length = c * 512;
+ 
+ 		/* but accept any length that fits if checksum okay */
+ 		if (!length || start + length > upper || !romchecksum(rom, length))
+@@ -249,7 +256,7 @@ static void __init probe_roms(void)
+ }
+ 
+ #ifdef CONFIG_XEN
+-static struct e820map machine_e820 __initdata;
++static struct e820map machine_e820;
+ #define e820 machine_e820
+ #endif
+ 
+@@ -409,10 +416,8 @@ int __init sanitize_e820_map(struct e820
+ 		   ____________________33__
+ 		   ______________________4_
+ 	*/
+-	printk("sanitize start\n");
+ 	/* if there's only one memory region, don't bother */
+ 	if (*pnr_map < 2) {
+-		printk("sanitize bail 0\n");
+ 		return -1;
+ 	}
+ 
+@@ -421,7 +426,6 @@ int __init sanitize_e820_map(struct e820
+ 	/* bail out if we find any unreasonable addresses in bios map */
+ 	for (i=0; i<old_nr; i++)
+ 		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
+-			printk("sanitize bail 1\n");
+ 			return -1;
+ 		}
+ 
+@@ -517,7 +521,6 @@ int __init sanitize_e820_map(struct e820
+ 	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+ 	*pnr_map = new_nr;
+ 
+-	printk("sanitize end\n");
+ 	return 0;
+ }
+ 
+@@ -552,7 +555,6 @@ int __init copy_e820_map(struct e820entr
+ 		unsigned long long size = biosmap->size;
+ 		unsigned long long end = start + size;
+ 		unsigned long type = biosmap->type;
+-		printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type);
+ 
+ 		/* Overflow in 64 bits? Ignore the memory map. */
+ 		if (start > end)
+@@ -564,17 +566,11 @@ int __init copy_e820_map(struct e820entr
+ 		 * Not right. Fix it up.
+ 		 */
+ 		if (type == E820_RAM) {
+-			printk("copy_e820_map() type is E820_RAM\n");
+ 			if (start < 0x100000ULL && end > 0xA0000ULL) {
+-				printk("copy_e820_map() lies in range...\n");
+-				if (start < 0xA0000ULL) {
+-					printk("copy_e820_map() start < 0xA0000ULL\n");
++				if (start < 0xA0000ULL)
+ 					add_memory_region(start, 0xA0000ULL-start, type);
+-				}
+-				if (end <= 0x100000ULL) {
+-					printk("copy_e820_map() end <= 0x100000ULL\n");
++				if (end <= 0x100000ULL)
+ 					continue;
+-				}
+ 				start = 0x100000ULL;
+ 				size = end - start;
+ 			}
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:49:47.000000000 +0100
+@@ -15,7 +15,7 @@
+  * I changed all the .align's to 4 (16 byte alignment), as that's faster
+  * on a 486.
+  *
+- * Stack layout in 'ret_from_system_call':
++ * Stack layout in 'syscall_exit':
+  * 	ptrace needs to have all regs on the stack.
+  *	if the order here is changed, it needs to be
+  *	updated in fork.c:copy_process, signal.c:do_signal,
+@@ -135,7 +135,7 @@ NMI_MASK	= 0x80000000
+ 	movl $(__USER_DS), %edx; \
+ 	movl %edx, %ds; \
+ 	movl %edx, %es; \
+-	movl $(__KERNEL_PDA), %edx; \
++	movl $(__KERNEL_PERCPU), %edx; \
+ 	movl %edx, %fs
+ 
+ #define RESTORE_INT_REGS \
+@@ -308,16 +308,12 @@ sysenter_past_esp:
+ 	pushl $(__USER_CS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET cs, 0*/
+-#ifndef CONFIG_COMPAT_VDSO
+ 	/*
+ 	 * Push current_thread_info()->sysenter_return to the stack.
+ 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+ 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+ 	 */
+ 	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+-#else
+-	pushl $SYSENTER_RETURN
+-#endif
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eip, 0
+ 
+@@ -345,7 +341,7 @@ sysenter_past_esp:
+ 	jae syscall_badsys
+ 	call *sys_call_table(,%eax,4)
+ 	movl %eax,PT_EAX(%esp)
+-	DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX)
++	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+ 	testw $_TIF_ALLWORK_MASK, %cx
+@@ -400,10 +396,6 @@ ENTRY(system_call)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	testl $TF_MASK,PT_EFLAGS(%esp)
+-	jz no_singlestep
+-	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+-no_singlestep:
+ 					# system call tracing in operation / emulation
+ 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+ 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+@@ -418,6 +410,10 @@ syscall_exit:
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
++	testl $TF_MASK,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
++	jz no_singlestep
++	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
++no_singlestep:
+ 	movl TI_flags(%ebp), %ecx
+ 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
+ 	jne syscall_exit_work
+@@ -635,9 +631,7 @@ END(syscall_badsys)
+ #ifndef CONFIG_XEN
+ #define FIXUP_ESPFIX_STACK \
+ 	/* since we are on a wrong stack, we cant make it a C code :( */ \
+-	movl %fs:PDA_cpu, %ebx; \
+-	PER_CPU(cpu_gdt_descr, %ebx); \
+-	movl GDS_address(%ebx), %ebx; \
++	PER_CPU(gdt_page, %ebx); \
+ 	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
+ 	addl %esp, %eax; \
+ 	pushl $__KERNEL_DS; \
+@@ -710,7 +704,7 @@ ENTRY(name)				\
+ 	SAVE_ALL;			\
+ 	TRACE_IRQS_OFF			\
+ 	movl %esp,%eax;			\
+-	call smp_/**/name;		\
++	call smp_##name;		\
+ 	jmp ret_from_intr;		\
+ 	CFI_ENDPROC;			\
+ ENDPROC(name)
+@@ -718,10 +712,6 @@ ENDPROC(name)
+ /* The include is where all of the SMP etc. interrupts come from */
+ #include "entry_arch.h"
+ 
+-/* This alternate entry is needed because we hijack the apic LVTT */
+-#if defined(CONFIG_VMI) && defined(CONFIG_X86_LOCAL_APIC)
+-BUILD_INTERRUPT(apic_vmi_timer_interrupt,LOCAL_TIMER_VECTOR)
+-#endif
+ #else
+ #define UNWIND_ESPFIX_STACK
+ #endif
+@@ -764,7 +754,7 @@ error_code:
+ 	pushl %fs
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET fs, 0*/
+-	movl $(__KERNEL_PDA), %ecx
++	movl $(__KERNEL_PERCPU), %ecx
+ 	movl %ecx, %fs
+ 	UNWIND_ESPFIX_STACK
+ 	popl %ecx
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:49:47.000000000 +0100
+@@ -37,7 +37,8 @@ ENTRY(startup_32)
+ 	/* Set up the stack pointer */
+ 	movl $(init_thread_union+THREAD_SIZE),%esp
+ 
+-	call setup_pda
++	movl %ss,%eax
++	movl %eax,%fs			# gets reset once there's real percpu
+ 
+ 	/* get vendor info */
+ 	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
+@@ -64,55 +65,11 @@ ENTRY(startup_32)
+ 	xorl %eax,%eax		# Clear GS
+ 	movl %eax,%gs
+ 
+-	movl $(__KERNEL_PDA),%eax
+-	mov  %eax,%fs
+-
+ 	cld			# gcc2 wants the direction flag cleared at all times
+ 
+ 	pushl $0		# fake return address for unwinder
+ 	jmp start_kernel
+ 
+-/*
+- * Point the GDT at this CPU's PDA.  This will be
+- * cpu_gdt_table and boot_pda.
+- */
+-ENTRY(setup_pda)
+-	/* get the PDA pointer */
+-	movl $boot_pda, %eax
+-
+-	/* slot the PDA address into the GDT */
+-	mov $cpu_gdt_table, %ecx
+-	mov %ax, (__KERNEL_PDA+0+2)(%ecx)		/* base & 0x0000ffff */
+-	shr $16, %eax
+-	mov %al, (__KERNEL_PDA+4+0)(%ecx)		/* base & 0x00ff0000 */
+-	mov %ah, (__KERNEL_PDA+4+3)(%ecx)		/* base & 0xff000000 */
+-
+-	# %esi still points to start_info, and no registers
+-	# need to be preserved.
+-
+-	movl XEN_START_mfn_list(%esi), %ebx
+-	movl $(cpu_gdt_table - __PAGE_OFFSET), %eax
+-	shrl $PAGE_SHIFT, %eax
+-	movl (%ebx,%eax,4), %ecx
+-	pushl %ecx			# frame number for set_gdt below
+-
+-	xorl %esi, %esi
+-	xorl %edx, %edx
+-	shldl $PAGE_SHIFT, %ecx, %edx
+-	shll $PAGE_SHIFT, %ecx
+-	orl $0x61, %ecx
+-	movl $cpu_gdt_table, %ebx
+-	movl $__HYPERVISOR_update_va_mapping, %eax
+-	int $0x82
+-
+-	movl $(PAGE_SIZE_asm / 8), %ecx
+-	movl %esp, %ebx
+-	movl $__HYPERVISOR_set_gdt, %eax
+-	int $0x82
+-
+-	popl %ecx
+-	ret
+-
+ #define HYPERCALL_PAGE_OFFSET 0x1000
+ .org HYPERCALL_PAGE_OFFSET
+ ENTRY(hypercall_page)
+@@ -138,60 +95,6 @@ ENTRY(empty_zero_page)
+  */
+ .data
+ 
+-/*
+- * The Global Descriptor Table contains 28 quadwords, per-CPU.
+- */
+-	.section .data.page_aligned, "aw"
+-	.align PAGE_SIZE_asm
+-ENTRY(cpu_gdt_table)
+-	.quad 0x0000000000000000	/* NULL descriptor */
+-	.quad 0x0000000000000000	/* 0x0b reserved */
+-	.quad 0x0000000000000000	/* 0x13 reserved */
+-	.quad 0x0000000000000000	/* 0x1b reserved */
+-	.quad 0x0000000000000000	/* 0x20 unused */
+-	.quad 0x0000000000000000	/* 0x28 unused */
+-	.quad 0x0000000000000000	/* 0x33 TLS entry 1 */
+-	.quad 0x0000000000000000	/* 0x3b TLS entry 2 */
+-	.quad 0x0000000000000000	/* 0x43 TLS entry 3 */
+-	.quad 0x0000000000000000	/* 0x4b reserved */
+-	.quad 0x0000000000000000	/* 0x53 reserved */
+-	.quad 0x0000000000000000	/* 0x5b reserved */
+-
+-	.quad 0x00cf9a000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
+-	.quad 0x00cf92000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
+-	.quad 0x00cffa000000ffff	/* 0x73 user 4GB code at 0x00000000 */
+-	.quad 0x00cff2000000ffff	/* 0x7b user 4GB data at 0x00000000 */
+-
+-	.quad 0x0000000000000000	/* 0x80 TSS descriptor */
+-	.quad 0x0000000000000000	/* 0x88 LDT descriptor */
+-
+-	/*
+-	 * Segments used for calling PnP BIOS have byte granularity.
+-	 * They code segments and data segments have fixed 64k limits,
+-	 * the transfer segment sizes are set at run time.
+-	 */
+-	.quad 0x0000000000000000	/* 0x90 32-bit code */
+-	.quad 0x0000000000000000	/* 0x98 16-bit code */
+-	.quad 0x0000000000000000	/* 0xa0 16-bit data */
+-	.quad 0x0000000000000000	/* 0xa8 16-bit data */
+-	.quad 0x0000000000000000	/* 0xb0 16-bit data */
+-
+-	/*
+-	 * The APM segments have byte granularity and their bases
+-	 * are set at run time.  All have 64k limits.
+-	 */
+-	.quad 0x0000000000000000	/* 0xb8 APM CS    code */
+-	.quad 0x0000000000000000	/* 0xc0 APM CS 16 code (16 bit) */
+-	.quad 0x0000000000000000	/* 0xc8 APM DS    data */
+-
+-	.quad 0x0000000000000000	/* 0xd0 - ESPFIX SS */
+-	.quad 0x00cf92000000ffff	/* 0xd8 - PDA */
+-	.quad 0x0000000000000000	/* 0xe0 - unused */
+-	.quad 0x0000000000000000	/* 0xe8 - unused */
+-	.quad 0x0000000000000000	/* 0xf0 - unused */
+-	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
+-	.align PAGE_SIZE_asm
+-
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ /*
+  * __xen_guest information
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -25,7 +25,6 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/sched.h>
+-#include <linux/smp_lock.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/compiler.h>
+ #include <linux/acpi.h>
+@@ -35,6 +34,7 @@
+ #include <linux/msi.h>
+ #include <linux/htirq.h>
+ #include <linux/freezer.h>
++#include <linux/kthread.h>
+ 
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -710,8 +710,6 @@ static int balanced_irq(void *unused)
+ 	unsigned long prev_balance_time = jiffies;
+ 	long time_remaining = balanced_irq_interval;
+ 
+-	daemonize("kirqd");
+-	
+ 	/* push everything to CPU 0 to give us a starting point.  */
+ 	for (i = 0 ; i < NR_IRQS ; i++) {
+ 		irq_desc[i].pending_mask = cpumask_of_cpu(0);
+@@ -771,10 +769,9 @@ static int __init balanced_irq_init(void
+ 	}
+ 	
+ 	printk(KERN_INFO "Starting balanced_irq\n");
+-	if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) 
++	if (!IS_ERR(kthread_run(balanced_irq, NULL, "kirqd")))
+ 		return 0;
+-	else 
+-		printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
++	printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
+ failed:
+ 	for_each_possible_cpu(i) {
+ 		kfree(irq_cpu_data[i].irq_delta);
+@@ -1455,10 +1452,6 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	enable_8259A_irq(0);
+ }
+ 
+-static inline void UNEXPECTED_IO_APIC(void)
+-{
+-}
+-
+ void __init print_IO_APIC(void)
+ {
+ 	int apic, i;
+@@ -1498,34 +1491,12 @@ void __init print_IO_APIC(void)
+ 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+ 	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+ 	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
+-	if (reg_00.bits.ID >= get_physical_broadcast())
+-		UNEXPECTED_IO_APIC();
+-	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+ 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+-	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
+-		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
+-		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
+-		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
+-		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
+-		(reg_01.bits.entries != 0x2E) &&
+-		(reg_01.bits.entries != 0x3F)
+-	)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+ 	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+-	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
+-		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
+-		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
+-		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
+-		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
+-	)
+-		UNEXPECTED_IO_APIC();
+-	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	/*
+ 	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+@@ -1535,8 +1506,6 @@ void __init print_IO_APIC(void)
+ 	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+ 		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+ 		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+-		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
+-			UNEXPECTED_IO_APIC();
+ 	}
+ 
+ 	/*
+@@ -1548,8 +1517,6 @@ void __init print_IO_APIC(void)
+ 	    reg_03.raw != reg_01.raw) {
+ 		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+ 		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+-		if (reg_03.bits.__reserved_1)
+-			UNEXPECTED_IO_APIC();
+ 	}
+ 
+ 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+@@ -2686,19 +2653,19 @@ int arch_setup_msi_irq(struct pci_dev *d
+ 	if (irq < 0)
+ 		return irq;
+ 
+-	set_irq_msi(irq, desc);
+ 	ret = msi_compose_msg(dev, irq, &msg);
+ 	if (ret < 0) {
+ 		destroy_irq(irq);
+ 		return ret;
+ 	}
+ 
++	set_irq_msi(irq, desc);
+ 	write_msi_msg(irq, &msg);
+ 
+ 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
+ 				      "edge");
+ 
+-	return irq;
++	return 0;
+ }
+ 
+ void arch_teardown_msi_irq(unsigned int irq)
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_32-xen.c	2008-01-28 12:24:19.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -12,10 +12,10 @@
+ #include <linux/types.h>
+ #include <linux/ioport.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/stddef.h>
+ #include <linux/slab.h>
+ #include <linux/thread_info.h>
++#include <linux/syscalls.h>
+ #include <xen/interface/physdev.h>
+ 
+ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -24,6 +24,9 @@
+ DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
+ EXPORT_PER_CPU_SYMBOL(irq_stat);
+ 
++DEFINE_PER_CPU(struct pt_regs *, irq_regs);
++EXPORT_PER_CPU_SYMBOL(irq_regs);
++
+ /*
+  * 'what should we do if we get a hw irq event on an illegal vector'.
+  * each architecture has to answer this themselves.
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -10,7 +10,6 @@
+ #include <linux/string.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -135,7 +135,7 @@ static int __init microcode_dev_init (vo
+ 	return 0;
+ }
+ 
+-static void __exit microcode_dev_exit (void)
++static void microcode_dev_exit (void)
+ {
+ 	misc_deregister(&microcode_dev);
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -18,7 +18,6 @@
+ #include <linux/acpi.h>
+ #include <linux/delay.h>
+ #include <linux/bootmem.h>
+-#include <linux/smp_lock.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/bitops.h>
+@@ -484,7 +483,7 @@ static int __init smp_read_mpc(struct mp
+ 		}
+ 		++mpc_record;
+ 	}
+-	clustered_apic_check();
++	setup_apic_routing();
+ 	if (!num_processors)
+ 		printk(KERN_ERR "SMP mptable: no processors registered!\n");
+ 	return num_processors;
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <linux/pci.h>
+ #include <linux/module.h>
+ #include <linux/version.h>
++#include <linux/pci.h>
+ #include <asm/io.h>
+ #include <xen/balloon.h>
+ #include <xen/gnttab.h>
+@@ -275,7 +276,7 @@ int dma_declare_coherent_memory(struct d
+ {
+ 	void __iomem *mem_base = NULL;
+ 	int pages = size >> PAGE_SHIFT;
+-	int bitmap_size = (pages + 31)/32;
++	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+ 
+ 	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+ 		goto out;
+@@ -348,6 +349,32 @@ void *dma_mark_declared_memory_occupied(
+ EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+ #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
+ 
++#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
++/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
++
++int forbid_dac;
++EXPORT_SYMBOL(forbid_dac);
++
++static __devinit void via_no_dac(struct pci_dev *dev)
++{
++	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
++		printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
++		forbid_dac = 1;
++	}
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
++
++static int check_iommu(char *s)
++{
++	if (!strcmp(s, "usedac")) {
++		forbid_dac = -1;
++		return 1;
++	}
++	return 0;
++}
++__setup("iommu=", check_iommu);
++#endif
++
+ dma_addr_t
+ dma_map_single(struct device *dev, void *ptr, size_t size,
+ 	       enum dma_data_direction direction)
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -21,7 +21,6 @@
+ #include <linux/mm.h>
+ #include <linux/elfcore.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/stddef.h>
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+@@ -39,6 +38,7 @@
+ #include <linux/random.h>
+ #include <linux/personality.h>
+ #include <linux/tick.h>
++#include <linux/percpu.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -61,7 +61,6 @@
+ 
+ #include <asm/tlbflush.h>
+ #include <asm/cpu.h>
+-#include <asm/pda.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ 
+@@ -70,6 +69,12 @@ static int hlt_counter;
+ unsigned long boot_option_idle_override = 0;
+ EXPORT_SYMBOL(boot_option_idle_override);
+ 
++DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
++EXPORT_PER_CPU_SYMBOL(current_task);
++
++DEFINE_PER_CPU(int, cpu_number);
++EXPORT_PER_CPU_SYMBOL(cpu_number);
++
+ /*
+  * Return saved PC of a blocked thread.
+  */
+@@ -168,6 +173,7 @@ void cpu_idle(void)
+ 			if (__get_cpu_var(cpu_idle_state))
+ 				__get_cpu_var(cpu_idle_state) = 0;
+ 
++			check_pgt_cache();
+ 			rmb();
+ 			idle = xen_idle; /* no alternatives */
+ 
+@@ -218,18 +224,19 @@ void __devinit select_idle_routine(const
+ {
+ }
+ 
+-static int __init idle_setup (char *str)
++static int __init idle_setup(char *str)
+ {
+-	if (!strncmp(str, "poll", 4)) {
++	if (!strcmp(str, "poll")) {
+ 		printk("using polling idle threads.\n");
+ 		pm_idle = poll_idle;
+ 	}
++	else
++		return -1;
+ 
+ 	boot_option_idle_override = 1;
+-	return 1;
++	return 0;
+ }
+-
+-__setup("idle=", idle_setup);
++early_param("idle", idle_setup);
+ 
+ void show_regs(struct pt_regs * regs)
+ {
+@@ -282,7 +289,7 @@ int kernel_thread(int (*fn)(void *), voi
+ 
+ 	regs.xds = __USER_DS;
+ 	regs.xes = __USER_DS;
+-	regs.xfs = __KERNEL_PDA;
++	regs.xfs = __KERNEL_PERCPU;
+ 	regs.orig_eax = -1;
+ 	regs.eip = (unsigned long) kernel_thread_helper;
+ 	regs.xcs = __KERNEL_CS | get_kernel_rpl();
+@@ -562,7 +569,7 @@ struct task_struct fastcall * __switch_t
+ 	 * multicall to indicate FPU task switch, rather than
+ 	 * synchronously trapping to Xen.
+ 	 */
+-	if (prev_p->thread_info->status & TS_USEDFPU) {
++	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+ 		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+ 		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+ 		mcl->args[0] = 1;
+@@ -669,7 +676,7 @@ struct task_struct fastcall * __switch_t
+ 	if (prev->gs | next->gs)
+ 		loadsegment(gs, next->gs);
+ 
+-	write_pda(pcurrent, next_p);
++	x86_write_percpu(current_task, next_p);
+ 
+ 	return prev_p;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -3,12 +3,10 @@
+  */
+ #include <linux/pci.h>
+ #include <linux/irq.h>
+-#include <asm/pci-direct.h>
+-#include <asm/genapic.h>
+-#include <asm/cpu.h>
+ 
+ #if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI)
+-static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
++
++static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+ {
+ 	u8 config, rev;
+ 	u32 word;
+@@ -16,7 +14,7 @@ static void __devinit verify_quirk_intel
+ 	/* BIOS may enable hardware IRQ balancing for
+ 	 * E7520/E7320/E7525(revision ID 0x9 and below)
+ 	 * based platforms.
+-	 * For those platforms, make sure that the genapic is set to 'flat'
++	 * Disable SW irqbalance/affinity on those platforms.
+ 	 */
+ 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ 	if (rev > 0x9)
+@@ -30,59 +28,20 @@ static void __devinit verify_quirk_intel
+ 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+ 
+ 	if (!(word & (1 << 13))) {
+-#ifndef CONFIG_XEN
+-#ifdef CONFIG_X86_64
+-		if (genapic !=  &apic_flat)
+-			panic("APIC mode must be flat on this system\n");
+-#elif defined(CONFIG_X86_GENERICARCH)
+-		if (genapic != &apic_default)
+-			panic("APIC mode must be default(flat) on this system. Use apic=default\n");
+-#endif
+-#endif
+-	}
+-
+-	/* put back the original value for config space*/
+-	if (!(config & 0x2))
+-		pci_write_config_byte(dev, 0xf4, config);
+-}
+-
+-void __init quirk_intel_irqbalance(void)
+-{
+-	u8 config, rev;
+-	u32 word;
+-
+-	/* BIOS may enable hardware IRQ balancing for
+-	 * E7520/E7320/E7525(revision ID 0x9 and below)
+-	 * based platforms.
+-	 * Disable SW irqbalance/affinity on those platforms.
+-	 */
+-	rev = read_pci_config_byte(0, 0, 0, PCI_CLASS_REVISION);
+-	if (rev > 0x9)
+-		return;
+-
+-	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+-
+-	/* enable access to config space */
+-	config = read_pci_config_byte(0, 0, 0, 0xf4);
+-	write_pci_config_byte(0, 0, 0, 0xf4, config|0x2);
+-
+-	/* read xTPR register */
+-	word = read_pci_config_16(0, 0, 0x40, 0x4c);
+-
+-	if (!(word & (1 << 13))) {
+ 		struct xen_platform_op op;
+-		printk(KERN_INFO "Disabling irq balancing and affinity\n");
++
++		printk(KERN_INFO "Intel E7520/7320/7525 detected. "
++			"Disabling irq balancing and affinity\n");
+ 		op.cmd = XENPF_platform_quirk;
+ 		op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
+ 		WARN_ON(HYPERVISOR_platform_op(&op));
+ 	}
+ 
+-	/* put back the original value for config space */
++	/* put back the original value for config space*/
+ 	if (!(config & 0x2))
+-		write_pci_config_byte(0, 0, 0, 0xf4, config);
++		pci_write_config_byte(dev, 0xf4, config);
+ }
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  verify_quirk_intel_irqbalance);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  verify_quirk_intel_irqbalance);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  verify_quirk_intel_irqbalance);
+-
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
++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
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,7 +13,6 @@
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/cache.h>
+@@ -216,7 +215,6 @@ static cpumask_t flush_cpumask;
+ static struct mm_struct * flush_mm;
+ static unsigned long flush_va;
+ static DEFINE_SPINLOCK(tlbstate_lock);
+-#define FLUSH_ALL	0xffffffff
+ 
+ /*
+  * We cannot call mmdrop() because we are in interrupt context, 
+@@ -298,7 +296,7 @@ irqreturn_t smp_invalidate_interrupt(int
+ 		 
+ 	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+ 		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
+-			if (flush_va == FLUSH_ALL)
++			if (flush_va == TLB_FLUSH_ALL)
+ 				local_flush_tlb();
+ 			else
+ 				__flush_tlb_one(flush_va);
+@@ -314,9 +312,11 @@ out:
+ 	return IRQ_HANDLED;
+ }
+ 
+-static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+-						unsigned long va)
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++			     unsigned long va)
+ {
++	cpumask_t cpumask = *cpumaskp;
++
+ 	/*
+ 	 * A couple of (to be removed) sanity checks:
+ 	 *
+@@ -327,10 +327,12 @@ static void flush_tlb_others(cpumask_t c
+ 	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
+ 	BUG_ON(!mm);
+ 
++#ifdef CONFIG_HOTPLUG_CPU
+ 	/* If a CPU which we ran on has gone down, OK. */
+ 	cpus_and(cpumask, cpumask, cpu_online_map);
+-	if (cpus_empty(cpumask))
++	if (unlikely(cpus_empty(cpumask)))
+ 		return;
++#endif
+ 
+ 	/*
+ 	 * i'm not happy about this global shared spinlock in the
+@@ -341,17 +343,7 @@ static void flush_tlb_others(cpumask_t c
+ 	
+ 	flush_mm = mm;
+ 	flush_va = va;
+-#if NR_CPUS <= BITS_PER_LONG
+-	atomic_set_mask(cpumask, &flush_cpumask);
+-#else
+-	{
+-		int k;
+-		unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
+-		unsigned long *cpu_mask = (unsigned long *)&cpumask;
+-		for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
+-			atomic_set_mask(cpu_mask[k], &flush_mask[k]);
+-	}
+-#endif
++	cpus_or(flush_cpumask, cpumask, flush_cpumask);
+ 	/*
+ 	 * We have to send the IPI only to
+ 	 * CPUs affected.
+@@ -378,7 +370,7 @@ void flush_tlb_current_task(void)
+ 
+ 	local_flush_tlb();
+ 	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+ 	preempt_enable();
+ }
+ 
+@@ -397,7 +389,7 @@ void flush_tlb_mm (struct mm_struct * mm
+ 			leave_mm(smp_processor_id());
+ 	}
+ 	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+ 
+ 	preempt_enable();
+ }
+@@ -446,7 +438,7 @@ void flush_tlb_all(void)
+  * it goes straight through and wastes no time serializing
+  * anything. Worst case is that we lose a reschedule ...
+  */
+-void smp_send_reschedule(int cpu)
++void xen_smp_send_reschedule(int cpu)
+ {
+ 	WARN_ON(cpu_is_offline(cpu));
+ 	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+@@ -478,36 +470,79 @@ void unlock_ipi_call_lock(void)
+ 
+ static struct call_data_struct *call_data;
+ 
++static void __smp_call_function(void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = num_online_cpus() - 1;
++
++	if (!cpus)
++		return;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	mb();
++
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++}
++
++
+ /**
+- * smp_call_function(): Run a function on all other CPUs.
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * @mask: The set of cpus to run on.  Must not include the current cpu.
+  * @func: The function to run. This must be fast and non-blocking.
+  * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: currently unused.
+  * @wait: If true, wait (atomically) until function has completed on other CPUs.
+  *
+- * Returns 0 on success, else a negative status code. Does not return until
+- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
++  * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
+  *
+  * You must not call this function with disabled interrupts or from a
+  * hardware interrupt handler or from a bottom half handler.
+  */
+-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+-			int wait)
++int
++xen_smp_call_function_mask(cpumask_t mask,
++			      void (*func)(void *), void *info,
++			      int wait)
+ {
+ 	struct call_data_struct data;
++	cpumask_t allbutself;
+ 	int cpus;
+ 
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
+ 	/* Holding any lock stops cpus from going down. */
+ 	spin_lock(&call_lock);
+-	cpus = num_online_cpus() - 1;
++
++	allbutself = cpu_online_map;
++	cpu_clear(smp_processor_id(), allbutself);
++
++	cpus_and(mask, mask, allbutself);
++	cpus = cpus_weight(mask);
++
+ 	if (!cpus) {
+ 		spin_unlock(&call_lock);
+ 		return 0;
+ 	}
+ 
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+ 	data.func = func;
+ 	data.info = info;
+ 	atomic_set(&data.started, 0);
+@@ -517,9 +552,12 @@ int smp_call_function (void (*func) (voi
+ 
+ 	call_data = &data;
+ 	mb();
+-	
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Send a message to other CPUs */
++	if (cpus_equal(mask, allbutself))
++		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++	else
++		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+ 
+ 	/* Wait for response */
+ 	while (atomic_read(&data.started) != cpus)
+@@ -532,15 +570,14 @@ int smp_call_function (void (*func) (voi
+ 
+ 	return 0;
+ }
+-EXPORT_SYMBOL(smp_call_function);
+ 
+ static void stop_this_cpu (void * dummy)
+ {
++	local_irq_disable();
+ 	/*
+ 	 * Remove this CPU:
+ 	 */
+ 	cpu_clear(smp_processor_id(), cpu_online_map);
+-	local_irq_disable();
+ 	disable_all_local_evtchn();
+ 	if (cpu_data[smp_processor_id()].hlt_works_ok)
+ 		for(;;) halt();
+@@ -551,13 +588,18 @@ static void stop_this_cpu (void * dummy)
+  * this function calls the 'stop' function on all other CPUs in the system.
+  */
+ 
+-void smp_send_stop(void)
++void xen_smp_send_stop(void)
+ {
+-	smp_call_function(stop_this_cpu, NULL, 1, 0);
++	/* Don't deadlock on the call lock in panic */
++	int nolock = !spin_trylock(&call_lock);
++	unsigned long flags;
+ 
+-	local_irq_disable();
++	local_irq_save(flags);
++	__smp_call_function(stop_this_cpu, NULL, 0, 0);
++	if (!nolock)
++		spin_unlock(&call_lock);
+ 	disable_all_local_evtchn();
+-	local_irq_enable();
++	local_irq_restore(flags);
+ }
+ 
+ /*
+@@ -598,74 +640,3 @@ irqreturn_t smp_call_function_interrupt(
+ 
+ 	return IRQ_HANDLED;
+ }
+-
+-/*
+- * this function sends a 'generic call function' IPI to one other CPU
+- * in the system.
+- *
+- * cpu is a standard Linux logical CPU number.
+- */
+-static void
+-__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
+-{
+-	struct call_data_struct data;
+-	int cpus = 1;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	wmb();
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (!wait)
+-		return;
+-
+-	while (atomic_read(&data.finished) != cpus)
+-		cpu_relax();
+-}
+-
+-/*
+- * smp_call_function_single - Run a function on another CPU
+- * @func: The function to run. This must be fast and non-blocking.
+- * @info: An arbitrary pointer to pass to the function.
+- * @nonatomic: Currently unused.
+- * @wait: If true, wait until function has completed on other CPUs.
+- *
+- * Retrurns 0 on success, else a negative status code.
+- *
+- * Does not return until the remote CPU is nearly ready to execute <func>
+- * or is or has executed.
+- */
+-
+-int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+-			int nonatomic, int wait)
+-{
+-	/* prevent preemption and reschedule on another processor */
+-	int me = get_cpu();
+-	if (cpu == me) {
+-		WARN_ON(1);
+-		put_cpu();
+-		return -EBUSY;
+-	}
+-
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	spin_lock_bh(&call_lock);
+-	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+-	spin_unlock_bh(&call_lock);
+-	put_cpu();
+-	return 0;
+-}
+-EXPORT_SYMBOL(smp_call_function_single);
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:27:26.000000000 +0100
+@@ -80,7 +80,6 @@
+ #include <asm/i8253.h>
+ DEFINE_SPINLOCK(i8253_lock);
+ EXPORT_SYMBOL(i8253_lock);
+-int pit_latch_buggy;              /* extern */
+ #else
+ volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+ #endif
+@@ -200,6 +199,26 @@ static inline u64 scale_delta(u64 delta,
+ 	return product;
+ }
+ 
++static inline u64 get64(volatile u64 *ptr)
++{
++#ifndef CONFIG_64BIT
++	return cmpxchg64(ptr, 0, 0);
++#else
++	return *ptr;
++#define cmpxchg64 cmpxchg
++#endif
++}
++
++static inline u64 get64_local(volatile u64 *ptr)
++{
++#ifndef CONFIG_64BIT
++	return cmpxchg64_local(ptr, 0, 0);
++#else
++	return *ptr;
++#define cmpxchg64_local cmpxchg_local
++#endif
++}
++
+ static void init_cpu_khz(void)
+ {
+ 	u64 __cpu_khz = 1000000ULL << 32;
+@@ -379,7 +398,7 @@ static int set_rtc_mmss(unsigned long no
+ 	return retval;
+ }
+ 
+-unsigned long long sched_clock(void)
++static unsigned long long local_clock(void)
+ {
+ 	unsigned int cpu = get_cpu();
+ 	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+@@ -400,6 +419,61 @@ unsigned long long sched_clock(void)
+ 	return time;
+ }
+ 
++/*
++ * Runstate accounting
++ */
++static void get_runstate_snapshot(struct vcpu_runstate_info *res)
++{
++	u64 state_time;
++	struct vcpu_runstate_info *state;
++
++	BUG_ON(preemptible());
++
++	state = &__get_cpu_var(runstate);
++
++	do {
++		state_time = get64_local(&state->state_entry_time);
++		*res = *state;
++	} while (get64_local(&state->state_entry_time) != state_time);
++
++	WARN_ON_ONCE(res->state != RUNSTATE_running);
++}
++
++/*
++ * Xen sched_clock implementation.  Returns the number of unstolen
++ * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED
++ * states.
++ */
++unsigned long long sched_clock(void)
++{
++	struct vcpu_runstate_info runstate;
++	cycle_t now;
++	u64 ret;
++	s64 offset;
++
++	/*
++	 * Ideally sched_clock should be called on a per-cpu basis
++	 * anyway, so preempt should already be disabled, but that's
++	 * not current practice at the moment.
++	 */
++	preempt_disable();
++
++	now = local_clock();
++
++	get_runstate_snapshot(&runstate);
++
++	offset = now - runstate.state_entry_time;
++	if (offset < 0)
++		offset = 0;
++
++	ret = offset + runstate.time[RUNSTATE_running]
++	      + runstate.time[RUNSTATE_blocked];
++
++	preempt_enable();
++
++	return ret;
++}
++
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+ 	unsigned long pc = instruction_pointer(regs);
+@@ -447,10 +521,9 @@ EXPORT_SYMBOL(profile_pc);
+ irqreturn_t timer_interrupt(int irq, void *dev_id)
+ {
+ 	s64 delta, delta_cpu, stolen, blocked;
+-	u64 sched_time;
+ 	unsigned int i, cpu = smp_processor_id();
+ 	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+-	struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
++	struct vcpu_runstate_info runstate;
+ 
+ 	/*
+ 	 * Here we are in the timer irq handler. We just have irqs locally
+@@ -470,20 +543,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 		delta     -= processed_system_time;
+ 		delta_cpu -= per_cpu(processed_system_time, cpu);
+ 
+-		/*
+-		 * Obtain a consistent snapshot of stolen/blocked cycles. We
+-		 * can use state_entry_time to detect if we get preempted here.
+-		 */
+-		do {
+-			sched_time = runstate->state_entry_time;
+-			barrier();
+-			stolen = runstate->time[RUNSTATE_runnable] +
+-				runstate->time[RUNSTATE_offline] -
+-				per_cpu(processed_stolen_time, cpu);
+-			blocked = runstate->time[RUNSTATE_blocked] -
+-				per_cpu(processed_blocked_time, cpu);
+-			barrier();
+-		} while (sched_time != runstate->state_entry_time);
++		get_runstate_snapshot(&runstate);
+ 	} while (!time_values_up_to_date(cpu));
+ 
+ 	if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
+@@ -526,6 +586,9 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	 * HACK: Passing NULL to account_steal_time()
+ 	 * ensures that the ticks are accounted as stolen.
+ 	 */
++	stolen = runstate.time[RUNSTATE_runnable]
++		 + runstate.time[RUNSTATE_offline]
++		 - per_cpu(processed_stolen_time, cpu);
+ 	if ((stolen > 0) && (delta_cpu > 0)) {
+ 		delta_cpu -= stolen;
+ 		if (unlikely(delta_cpu < 0))
+@@ -541,6 +604,8 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	 * HACK: Passing idle_task to account_steal_time()
+ 	 * ensures that the ticks are accounted as idle/wait.
+ 	 */
++	blocked = runstate.time[RUNSTATE_blocked]
++		  - per_cpu(processed_blocked_time, cpu);
+ 	if ((blocked > 0) && (delta_cpu > 0)) {
+ 		delta_cpu -= blocked;
+ 		if (unlikely(delta_cpu < 0))
+@@ -577,7 +642,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	return IRQ_HANDLED;
+ }
+ 
+-void mark_tsc_unstable(void)
++void mark_tsc_unstable(char *reason)
+ {
+ #ifndef CONFIG_XEN /* XXX Should tell the hypervisor about this fact. */
+ 	tsc_unstable = 1;
+@@ -585,17 +650,13 @@ void mark_tsc_unstable(void)
+ }
+ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+ 
++static cycle_t cs_last;
++
+ static cycle_t xen_clocksource_read(void)
+ {
+ #ifdef CONFIG_SMP
+-	static cycle_t last_ret;
+-#ifndef CONFIG_64BIT
+-	cycle_t last = cmpxchg64(&last_ret, 0, 0);
+-#else
+-	cycle_t last = last_ret;
+-#define cmpxchg64 cmpxchg
+-#endif
+-	cycle_t ret = sched_clock();
++	cycle_t last = get64(&cs_last);
++	cycle_t ret = local_clock();
+ 
+ 	if (unlikely((s64)(ret - last) < 0)) {
+ 		if (last - ret > permitted_clock_jitter
+@@ -614,17 +675,25 @@ static cycle_t xen_clocksource_read(void
+ 	}
+ 
+ 	for (;;) {
+-		cycle_t cur = cmpxchg64(&last_ret, last, ret);
++		cycle_t cur = cmpxchg64(&cs_last, last, ret);
+ 
+ 		if (cur == last || (s64)(ret - cur) < 0)
+ 			return ret;
+ 		last = cur;
+ 	}
+ #else
+-	return sched_clock();
++	return local_clock();
+ #endif
+ }
+ 
++static void xen_clocksource_resume(void)
++{
++	extern void time_resume(void);
++
++	time_resume();
++	cs_last = local_clock();
++}
++
+ static struct clocksource clocksource_xen = {
+ 	.name			= "xen",
+ 	.rating			= 400,
+@@ -633,19 +702,29 @@ static struct clocksource clocksource_xe
+ 	.mult			= 1 << XEN_SHIFT,		/* time directly in nanoseconds */
+ 	.shift			= XEN_SHIFT,
+ 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
++	.resume			= xen_clocksource_resume,
+ };
+ 
+-static void init_missing_ticks_accounting(unsigned int cpu)
++struct vcpu_runstate_info *setup_runstate_area(unsigned int cpu)
+ {
+ 	struct vcpu_register_runstate_memory_area area;
+ 	struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
+ 	int rc;
+ 
+-	memset(runstate, 0, sizeof(*runstate));
+-
+-	area.addr.v = runstate;
++	set_xen_guest_handle(area.addr.h, runstate);
+ 	rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area);
+-	WARN_ON(rc && rc != -ENOSYS);
++	if (rc) {
++		BUILD_BUG_ON(RUNSTATE_running);
++		memset(runstate, 0, sizeof(*runstate));
++		WARN_ON(rc != -ENOSYS);
++	}
++
++	return runstate;
++}
++
++static void init_missing_ticks_accounting(unsigned int cpu)
++{
++	struct vcpu_runstate_info *runstate = setup_runstate_area(cpu);
+ 
+ 	per_cpu(processed_blocked_time, cpu) =
+ 		runstate->time[RUNSTATE_blocked];
+@@ -721,35 +800,6 @@ void notify_arch_cmos_timer(void)
+ 	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
+ }
+ 
+-static int timer_resume(struct sys_device *dev)
+-{
+-	extern void time_resume(void);
+-	time_resume();
+-	return 0;
+-}
+-
+-static struct sysdev_class timer_sysclass = {
+-	.resume = timer_resume,
+-	set_kset_name("timer"),
+-};
+-
+-
+-/* XXX this driverfs stuff should probably go elsewhere later -john */
+-static struct sys_device device_timer = {
+-	.id	= 0,
+-	.cls	= &timer_sysclass,
+-};
+-
+-static int time_init_device(void)
+-{
+-	int error = sysdev_class_register(&timer_sysclass);
+-	if (!error)
+-		error = sysdev_register(&device_timer);
+-	return error;
+-}
+-
+-device_initcall(time_init_device);
+-
+ extern void (*late_time_init)(void);
+ 
+ /* Dynamically-mapped IRQ. */
+@@ -880,21 +930,21 @@ static void start_hz_timer(void)
+ 	cpu_clear(smp_processor_id(), nohz_cpu_mask);
+ }
+ 
+-void raw_safe_halt(void)
++void xen_safe_halt(void)
+ {
+ 	stop_hz_timer();
+ 	/* Blocking includes an implicit local_irq_enable(). */
+ 	HYPERVISOR_block();
+ 	start_hz_timer();
+ }
+-EXPORT_SYMBOL(raw_safe_halt);
++EXPORT_SYMBOL(xen_safe_halt);
+ 
+-void halt(void)
++void xen_halt(void)
+ {
+ 	if (irqs_disabled())
+ 		VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+ }
+-EXPORT_SYMBOL(halt);
++EXPORT_SYMBOL(xen_halt);
+ 
+ /* No locking required. Interrupts are disabled on all CPUs. */
+ void time_resume(void)
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -52,7 +52,7 @@
+ #include <asm/unwind.h>
+ #include <asm/smp.h>
+ #include <asm/arch_hooks.h>
+-#include <asm/kdebug.h>
++#include <linux/kdebug.h>
+ #include <asm/stacktrace.h>
+ 
+ #include <linux/module.h>
+@@ -101,20 +101,6 @@ asmlinkage void machine_check(void);
+ 
+ int kstack_depth_to_print = 24;
+ static unsigned int code_bytes = 64;
+-ATOMIC_NOTIFIER_HEAD(i386die_chain);
+-
+-int register_die_notifier(struct notifier_block *nb)
+-{
+-	vmalloc_sync_all();
+-	return atomic_notifier_chain_register(&i386die_chain, nb);
+-}
+-EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
+-
+-int unregister_die_notifier(struct notifier_block *nb)
+-{
+-	return atomic_notifier_chain_unregister(&i386die_chain, nb);
+-}
+-EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
+ 
+ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+ {
+@@ -325,7 +311,7 @@ void show_registers(struct pt_regs *regs
+ 	       regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
+ 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ 		TASK_COMM_LEN, current->comm, current->pid,
+-		current_thread_info(), current, current->thread_info);
++		current_thread_info(), current, task_thread_info(current));
+ 	/*
+ 	 * When in-kernel, we also print out the stack and code at the
+ 	 * time of the fault..
+@@ -482,8 +468,6 @@ static void __kprobes do_trap(int trapnr
+ 			      siginfo_t *info)
+ {
+ 	struct task_struct *tsk = current;
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = trapnr;
+ 
+ 	if (regs->eflags & VM_MASK) {
+ 		if (vm86)
+@@ -495,6 +479,18 @@ static void __kprobes do_trap(int trapnr
+ 		goto kernel_trap;
+ 
+ 	trap_signal: {
++		/*
++		 * We want error_code and trap_no set for userspace faults and
++		 * kernelspace faults which result in die(), but not
++		 * kernelspace faults which are fixed up.  die() gives the
++		 * process no chance to handle the signal and notice the
++		 * kernel fault information, so that won't result in polluting
++		 * the information about previously queued, but not yet
++		 * delivered, faults.  See also do_general_protection below.
++		 */
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++
+ 		if (info)
+ 			force_sig_info(signr, info, tsk);
+ 		else
+@@ -503,8 +499,11 @@ static void __kprobes do_trap(int trapnr
+ 	}
+ 
+ 	kernel_trap: {
+-		if (!fixup_exception(regs))
++		if (!fixup_exception(regs)) {
++			tsk->thread.error_code = error_code;
++			tsk->thread.trap_no = trapnr;
+ 			die(str, regs, error_code);
++		}
+ 		return;
+ 	}
+ 
+@@ -578,9 +577,6 @@ DO_ERROR_INFO(32, SIGSEGV, "iret excepti
+ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
+ 					      long error_code)
+ {
+-	current->thread.error_code = error_code;
+-	current->thread.trap_no = 13;
+-
+ 	if (regs->eflags & VM_MASK)
+ 		goto gp_in_vm86;
+ 
+@@ -599,6 +595,8 @@ gp_in_vm86:
+ 
+ gp_in_kernel:
+ 	if (!fixup_exception(regs)) {
++		current->thread.error_code = error_code;
++		current->thread.trap_no = 13;
+ 		if (notify_die(DIE_GPF, "general protection fault", regs,
+ 				error_code, 13, SIGSEGV) == NOTIFY_STOP)
+ 			return;
+@@ -987,9 +985,7 @@ fastcall void do_spurious_interrupt_bug(
+ fastcall unsigned long patch_espfix_desc(unsigned long uesp,
+ 					  unsigned long kesp)
+ {
+-	int cpu = smp_processor_id();
+-	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+-	struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
++	struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
+ 	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+ 	unsigned long new_kesp = kesp - base;
+ 	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -14,19 +14,20 @@
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>		/* For unblank_screen() */
+ #include <linux/highmem.h>
++#include <linux/bootmem.h>		/* for max_low_pfn */
++#include <linux/vmalloc.h>
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
++#include <linux/kdebug.h>
+ 
+ #include <asm/system.h>
+ #include <asm/desc.h>
+-#include <asm/kdebug.h>
+ #include <asm/segment.h>
+ 
+ extern void die(const char *,struct pt_regs *,long);
+@@ -259,25 +260,20 @@ static void dump_fault_path(unsigned lon
+ 	unsigned long page;
+ 
+ 	page = read_cr3();
+-	page = ((unsigned long *) __va(page))[address >> 22];
+-	if (oops_may_print())
+-		printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
+-		       machine_to_phys(page));
++	page = ((unsigned long *) __va(page))[address >> PGDIR_SHIFT];
++	printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
++	       machine_to_phys(page));
+ 	/*
+ 	 * We must not directly access the pte in the highpte
+ 	 * case if the page table is located in highmem.
+ 	 * And lets rather not kmap-atomic the pte, just in case
+ 	 * it's allocated already.
+ 	 */
+-#ifdef CONFIG_HIGHPTE
+-	if ((page >> PAGE_SHIFT) >= highstart_pfn)
+-		return;
+-#endif
+-	if ((page & 1) && oops_may_print()) {
+-		page &= PAGE_MASK;
+-		address &= 0x003ff000;
+-		page = machine_to_phys(page);
+-		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
++	if ((machine_to_phys(page) >> PAGE_SHIFT) < max_low_pfn
++	    && (page & _PAGE_PRESENT)) {
++		page = machine_to_phys(page & PAGE_MASK);
++		page = ((unsigned long *) __va(page))[(address >> PAGE_SHIFT)
++		                                      & (PTRS_PER_PTE - 1)];
+ 		printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
+ 		       machine_to_phys(page));
+ 	}
+@@ -581,6 +577,11 @@ bad_area:
+ bad_area_nosemaphore:
+ 	/* User mode accesses just cause a SIGSEGV */
+ 	if (error_code & 4) {
++		/*
++		 * It's possible to have interrupts off here.
++		 */
++		local_irq_enable();
++
+ 		/* 
+ 		 * Valid to do another page fault here because this one came 
+ 		 * from user space.
+@@ -633,7 +634,7 @@ no_context:
+ 	bust_spinlocks(1);
+ 
+ 	if (oops_may_print()) {
+-	#ifdef CONFIG_X86_PAE
++#ifdef CONFIG_X86_PAE
+ 		if (error_code & 16) {
+ 			pte_t *pte = lookup_address(address);
+ 
+@@ -642,7 +643,7 @@ no_context:
+ 					"NX-protected page - exploit attempt? "
+ 					"(uid: %d)\n", current->uid);
+ 		}
+-	#endif
++#endif
+ 		if (address < PAGE_SIZE)
+ 			printk(KERN_ALERT "BUG: unable to handle kernel NULL "
+ 					"pointer dereference");
+@@ -652,8 +653,8 @@ no_context:
+ 		printk(" at virtual address %08lx\n",address);
+ 		printk(KERN_ALERT " printing eip:\n");
+ 		printk("%08lx\n", regs->eip);
++		dump_fault_path(address);
+ 	}
+-	dump_fault_path(address);
+ 	tsk->thread.cr2 = address;
+ 	tsk->thread.trap_no = 14;
+ 	tsk->thread.error_code = error_code;
+@@ -694,7 +695,6 @@ do_sigbus:
+ 	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
+ }
+ 
+-#if !HAVE_SHARED_KERNEL_PMD
+ void vmalloc_sync_all(void)
+ {
+ 	/*
+@@ -710,6 +710,9 @@ void vmalloc_sync_all(void)
+ 	static unsigned long start = TASK_SIZE;
+ 	unsigned long address;
+ 
++	if (SHARED_KERNEL_PMD)
++		return;
++
+ 	BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK);
+ 	for (address = start;
+ 	     address >= TASK_SIZE && address < hypervisor_virt_start;
+@@ -739,4 +742,3 @@ void vmalloc_sync_all(void)
+ 			start = address + (1UL << PMD_SHIFT);
+ 	}
+ }
+-#endif
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -26,7 +26,7 @@ void kunmap(struct page *page)
+  * However when holding an atomic kmap is is not legal to sleep, so atomic
+  * kmaps are appropriate for short, tight code paths only.
+  */
+-static void *__kmap_atomic(struct page *page, enum km_type type, pgprot_t prot)
++void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+ {
+ 	enum fixed_addresses idx;
+ 	unsigned long vaddr;
+@@ -49,15 +49,7 @@ static void *__kmap_atomic(struct page *
+ 
+ void *kmap_atomic(struct page *page, enum km_type type)
+ {
+-	return __kmap_atomic(page, type, kmap_prot);
+-}
+-
+-/* Same as kmap_atomic but with PAGE_KERNEL_RO page protection. */
+-void *kmap_atomic_pte(struct page *page, enum km_type type)
+-{
+-	return __kmap_atomic(page, type,
+-	                     test_bit(PG_pinned, &page->flags)
+-	                     ? PAGE_KERNEL_RO : kmap_prot);
++	return kmap_atomic_prot(page, type, kmap_prot);
+ }
+ 
+ void kunmap_atomic(void *kvaddr, enum km_type type)
+@@ -80,6 +72,7 @@ void kunmap_atomic(void *kvaddr, enum km
+ #endif
+ 	}
+ 
++	/*arch_flush_lazy_mmu_mode();*/
+ 	pagefault_enable();
+ }
+ 
+@@ -162,7 +155,6 @@ void copy_highpage(struct page *to, stru
+ EXPORT_SYMBOL(kmap);
+ EXPORT_SYMBOL(kunmap);
+ EXPORT_SYMBOL(kmap_atomic);
+-EXPORT_SYMBOL(kmap_atomic_pte);
+ EXPORT_SYMBOL(kunmap_atomic);
+ EXPORT_SYMBOL(kmap_atomic_to_page);
+ EXPORT_SYMBOL(clear_highpage);
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:49:47.000000000 +0100
+@@ -421,13 +421,13 @@ void xen_tlb_flush_all(void)
+ }
+ EXPORT_SYMBOL_GPL(xen_tlb_flush_all);
+ 
+-void xen_tlb_flush_mask(cpumask_t *mask)
++void xen_tlb_flush_mask(const cpumask_t *mask)
+ {
+ 	struct mmuext_op op;
+ 	if ( cpus_empty(*mask) )
+ 		return;
+ 	op.cmd = MMUEXT_TLB_FLUSH_MULTI;
+-	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
++	set_xen_guest_handle(op.arg2.vcpumask, cpus_addr(*mask));
+ 	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
+ EXPORT_SYMBOL_GPL(xen_tlb_flush_mask);
+@@ -441,14 +441,14 @@ void xen_invlpg_all(unsigned long ptr)
+ }
+ EXPORT_SYMBOL_GPL(xen_invlpg_all);
+ 
+-void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr)
++void xen_invlpg_mask(const cpumask_t *mask, unsigned long ptr)
+ {
+ 	struct mmuext_op op;
+ 	if ( cpus_empty(*mask) )
+ 		return;
+ 	op.cmd = MMUEXT_INVLPG_MULTI;
+ 	op.arg1.linear_addr = ptr & PAGE_MASK;
+-	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
++	set_xen_guest_handle(op.arg2.vcpumask, cpus_addr(*mask));
+ 	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
+ EXPORT_SYMBOL_GPL(xen_invlpg_mask);
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -22,6 +22,7 @@
+ #include <linux/init.h>
+ #include <linux/highmem.h>
+ #include <linux/pagemap.h>
++#include <linux/pfn.h>
+ #include <linux/poison.h>
+ #include <linux/bootmem.h>
+ #include <linux/slab.h>
+@@ -65,17 +66,19 @@ static pmd_t * __init one_md_table_init(
+ 	pmd_t *pmd_table;
+ 		
+ #ifdef CONFIG_X86_PAE
+-	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+-	paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
+-	make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+-	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+-	pud = pud_offset(pgd, 0);
+-	if (pmd_table != pmd_offset(pud, 0)) 
+-		BUG();
+-#else
++	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
++		pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++
++		paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
++		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
++		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
++		pud = pud_offset(pgd, 0);
++		if (pmd_table != pmd_offset(pud, 0))
++			BUG();
++	}
++#endif
+ 	pud = pud_offset(pgd, 0);
+ 	pmd_table = pmd_offset(pud, 0);
+-#endif
+ 
+ 	return pmd_table;
+ }
+@@ -86,16 +89,18 @@ static pmd_t * __init one_md_table_init(
+  */
+ static pte_t * __init one_page_table_init(pmd_t *pmd)
+ {
++#if CONFIG_XEN_COMPAT <= 0x030002
+ 	if (pmd_none(*pmd)) {
++#else
++	if (!(__pmd_val(*pmd) & _PAGE_PRESENT)) {
++#endif
+ 		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++
+ 		paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+ 					  XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+-		if (page_table != pte_offset_kernel(pmd, 0))
+-			BUG();	
+-
+-		return page_table;
++		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+ 	}
+ 	
+ 	return pte_offset_kernel(pmd, 0);
+@@ -115,7 +120,6 @@ static pte_t * __init one_page_table_ini
+ static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
+ {
+ 	pgd_t *pgd;
+-	pud_t *pud;
+ 	pmd_t *pmd;
+ 	int pgd_idx, pmd_idx;
+ 	unsigned long vaddr;
+@@ -126,12 +130,10 @@ static void __init page_table_range_init
+ 	pgd = pgd_base + pgd_idx;
+ 
+ 	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+-		if (pgd_none(*pgd)) 
+-			one_md_table_init(pgd);
+-		pud = pud_offset(pgd, vaddr);
+-		pmd = pmd_offset(pud, vaddr);
++		pmd = one_md_table_init(pgd);
++		pmd = pmd + pmd_index(vaddr);
+ 		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
+-			if (vaddr < hypervisor_virt_start && pmd_none(*pmd))
++			if (vaddr < hypervisor_virt_start)
+ 				one_page_table_init(pmd);
+ 
+ 			vaddr += PMD_SIZE;
+@@ -194,24 +196,25 @@ static void __init kernel_physical_mappi
+ 			/* Map with big pages if possible, otherwise create normal page tables. */
+ 			if (cpu_has_pse) {
+ 				unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
+-
+ 				if (is_kernel_text(address) || is_kernel_text(address2))
+ 					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
+ 				else
+ 					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
++
+ 				pfn += PTRS_PER_PTE;
+ 			} else {
+ 				pte = one_page_table_init(pmd);
+ 
+-				pte += pte_ofs;
+-				for (; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
+-						/* XEN: Only map initial RAM allocation. */
+-						if ((pfn >= max_ram_pfn) || pte_present(*pte))
+-							continue;
+-						if (is_kernel_text(address))
+-							set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+-						else
+-							set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
++				for (pte += pte_ofs;
++				     pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
++				     pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
++					/* XEN: Only map initial RAM allocation. */
++					if ((pfn >= max_ram_pfn) || pte_present(*pte))
++						continue;
++					if (is_kernel_text(address))
++						set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
++					else
++						set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
+ 				}
+ 				pte_ofs = 0;
+ 			}
+@@ -388,15 +391,44 @@ extern void __init remap_numa_kva(void);
+ 
+ pgd_t *swapper_pg_dir;
+ 
++static void __init xen_pagetable_setup_start(pgd_t *base)
++{
++}
++
++static void __init xen_pagetable_setup_done(pgd_t *base)
++{
++}
++
++/*
++ * Build a proper pagetable for the kernel mappings.  Up until this
++ * point, we've been running on some set of pagetables constructed by
++ * the boot process.
++ *
++ * If we're booting on native hardware, this will be a pagetable
++ * constructed in arch/i386/kernel/head.S, and not running in PAE mode
++ * (even if we'll end up running in PAE).  The root of the pagetable
++ * will be swapper_pg_dir.
++ *
++ * If we're booting paravirtualized under a hypervisor, then there are
++ * more options: we may already be running PAE, and the pagetable may
++ * or may not be based in swapper_pg_dir.  In any case,
++ * paravirt_pagetable_setup_start() will set up swapper_pg_dir
++ * appropriately for the rest of the initialization to work.
++ *
++ * In general, pagetable_init() assumes that the pagetable may already
++ * be partially populated, and so it avoids stomping on any existing
++ * mappings.
++ */
+ static void __init pagetable_init (void)
+ {
+-	unsigned long vaddr;
++	unsigned long vaddr, end;
+ 	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
+ 
++	xen_pagetable_setup_start(pgd_base);
++
+ 	/* Enable PSE if available */
+-	if (cpu_has_pse) {
++	if (cpu_has_pse)
+ 		set_in_cr4(X86_CR4_PSE);
+-	}
+ 
+ 	/* Enable PGE if available */
+ 	if (cpu_has_pge) {
+@@ -413,9 +445,12 @@ static void __init pagetable_init (void)
+ 	 * created - mappings will be set by set_fixmap():
+ 	 */
+ 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+-	page_table_range_init(vaddr, hypervisor_virt_start, pgd_base);
++	end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
++	page_table_range_init(vaddr, end, pgd_base);
+ 
+ 	permanent_kmaps_init(pgd_base);
++
++	xen_pagetable_setup_done(pgd_base);
+ }
+ 
+ #if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
+@@ -756,34 +791,29 @@ int remove_memory(u64 start, u64 size)
+ EXPORT_SYMBOL_GPL(remove_memory);
+ #endif
+ 
+-struct kmem_cache *pgd_cache;
+ struct kmem_cache *pmd_cache;
+ 
+ void __init pgtable_cache_init(void)
+ {
++	size_t pgd_size = PTRS_PER_PGD*sizeof(pgd_t);
++
+ 	if (PTRS_PER_PMD > 1) {
+ 		pmd_cache = kmem_cache_create("pmd",
+ 					PTRS_PER_PMD*sizeof(pmd_t),
+ 					PTRS_PER_PMD*sizeof(pmd_t),
+-					0,
++					SLAB_PANIC,
+ 					pmd_ctor,
+ 					NULL);
+-		if (!pmd_cache)
+-			panic("pgtable_cache_init(): cannot create pmd cache");
++		if (!SHARED_KERNEL_PMD) {
++			/* If we're in PAE mode and have a non-shared
++			   kernel pmd, then the pgd size must be a
++			   page size.  This is because the pgd_list
++			   links through the page structure, so there
++			   can only be one pgd per page for this to
++			   work. */
++			pgd_size = PAGE_SIZE;
++		}
+ 	}
+-	pgd_cache = kmem_cache_create("pgd",
+-#ifndef CONFIG_XEN
+-				PTRS_PER_PGD*sizeof(pgd_t),
+-				PTRS_PER_PGD*sizeof(pgd_t),
+-#else
+-				PAGE_SIZE,
+-				PAGE_SIZE,
+-#endif
+-				0,
+-				pgd_ctor,
+-				PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
+-	if (!pgd_cache)
+-		panic("pgtable_cache_init(): Cannot create pgd cache");
+ }
+ 
+ /*
+@@ -817,13 +847,26 @@ static int noinline do_test_wp_bit(void)
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long addr = (unsigned long)__start_rodata;
+-
+-	for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
+-		change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
++	unsigned long start = PFN_ALIGN(_text);
++	unsigned long size = PFN_ALIGN(_etext) - start;
+ 
+-	printk("Write protecting the kernel read-only data: %uk\n",
+-			(__end_rodata - __start_rodata) >> 10);
++#ifndef CONFIG_KPROBES
++#ifdef CONFIG_HOTPLUG_CPU
++	/* It must still be possible to apply SMP alternatives. */
++	if (num_possible_cpus() <= 1)
++#endif
++	{
++		change_page_attr(virt_to_page(start),
++		                 size >> PAGE_SHIFT, PAGE_KERNEL_RX);
++		printk("Write protecting the kernel text: %luk\n", size >> 10);
++	}
++#endif
++	start += size;
++	size = (unsigned long)__end_rodata - start;
++	change_page_attr(virt_to_page(start),
++	                 size >> PAGE_SHIFT, PAGE_KERNEL_RO);
++	printk("Write protecting the kernel read-only data: %luk\n",
++	       size >> 10);
+ 
+ 	/*
+ 	 * change_page_attr() requires a global_flush_tlb() call after it.
+@@ -846,7 +889,7 @@ void free_init_pages(char *what, unsigne
+ 		free_page(addr);
+ 		totalram_pages++;
+ 	}
+-	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
++	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
+ }
+ 
+ void free_initmem(void)
+--- head-2010-01-18.orig/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <linux/slab.h>
+ #include <linux/module.h>
+ #include <linux/io.h>
++#include <linux/sched.h>
+ #include <asm/fixmap.h>
+ #include <asm/cacheflush.h>
+ #include <asm/tlbflush.h>
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <linux/pagemap.h>
+ #include <linux/spinlock.h>
+ #include <linux/module.h>
++#include <linux/quicklist.h>
+ 
+ #include <asm/system.h>
+ #include <asm/pgtable.h>
+@@ -218,8 +219,6 @@ void pmd_ctor(void *pmd, struct kmem_cac
+  * against pageattr.c; it is the unique case in which a valid change
+  * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+  * vmalloc faults work because attached pagetables are never freed.
+- * The locking scheme was chosen on the basis of manfred's
+- * recommendations and having no core impact whatsoever.
+  * -- wli
+  */
+ DEFINE_SPINLOCK(pgd_lock);
+@@ -245,37 +244,54 @@ static inline void pgd_list_del(pgd_t *p
+ 		set_page_private(next, (unsigned long)pprev);
+ }
+ 
+-void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
++
++
++#if (PTRS_PER_PMD == 1)
++/* Non-PAE pgd constructor */
++void pgd_ctor(void *pgd)
+ {
+ 	unsigned long flags;
+ 
+-	if (PTRS_PER_PMD > 1) {
+-		if (HAVE_SHARED_KERNEL_PMD)
+-			clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+-					swapper_pg_dir + USER_PTRS_PER_PGD,
+-					KERNEL_PGD_PTRS);
+-	} else {
+-		spin_lock_irqsave(&pgd_lock, flags);
++	/* !PAE, no pagetable sharing */
++	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++
++	spin_lock_irqsave(&pgd_lock, flags);
++
++	/* must happen under lock */
++	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
++			swapper_pg_dir + USER_PTRS_PER_PGD,
++			KERNEL_PGD_PTRS);
++
++	paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
++				__pa(swapper_pg_dir) >> PAGE_SHIFT,
++				USER_PTRS_PER_PGD,
++				KERNEL_PGD_PTRS);
++	pgd_list_add(pgd);
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++#else  /* PTRS_PER_PMD > 1 */
++/* PAE pgd constructor */
++void pgd_ctor(void *pgd)
++{
++	/* PAE, kernel PMD may be shared */
++
++	if (SHARED_KERNEL_PMD) {
+ 		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+ 				swapper_pg_dir + USER_PTRS_PER_PGD,
+ 				KERNEL_PGD_PTRS);
++	} else {
+ 		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-
+-		/* must happen under lock */
+-		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+-			__pa(swapper_pg_dir) >> PAGE_SHIFT,
+-			USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
+-
+-		pgd_list_add(pgd);
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+ }
++#endif	/* PTRS_PER_PMD */
+ 
+-/* never called when PTRS_PER_PMD > 1 */
+-void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
++void pgd_dtor(void *pgd)
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
++	if (SHARED_KERNEL_PMD)
++		return;
++
+ 	paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 	pgd_list_del(pgd);
+@@ -284,11 +300,46 @@ void pgd_dtor(void *pgd, struct kmem_cac
+ 	pgd_test_and_unpin(pgd);
+ }
+ 
++#define UNSHARED_PTRS_PER_PGD				\
++	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
++
++/* If we allocate a pmd for part of the kernel address space, then
++   make sure its initialized with the appropriate kernel mappings.
++   Otherwise use a cached zeroed pmd.  */
++static pmd_t *pmd_cache_alloc(int idx)
++{
++	pmd_t *pmd;
++
++	if (idx >= USER_PTRS_PER_PGD) {
++		pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
++
++#ifndef CONFIG_XEN
++		if (pmd)
++			memcpy(pmd,
++			       (void *)pgd_page_vaddr(swapper_pg_dir[idx]),
++			       sizeof(pmd_t) * PTRS_PER_PMD);
++#endif
++	} else
++		pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++
++	return pmd;
++}
++
++static void pmd_cache_free(pmd_t *pmd, int idx)
++{
++	if (idx >= USER_PTRS_PER_PGD) {
++		make_lowmem_page_writable(pmd, XENFEAT_writable_page_tables);
++		memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
++		free_page((unsigned long)pmd);
++	} else
++		kmem_cache_free(pmd_cache, pmd);
++}
++
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ 	int i;
+-	pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
+-	pmd_t **pmd;
++	pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
++	pmd_t **pmds = NULL;
+ 	unsigned long flags;
+ 
+ 	pgd_test_and_unpin(pgd);
+@@ -296,37 +347,40 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	if (PTRS_PER_PMD == 1 || !pgd)
+ 		return pgd;
+ 
+-	if (HAVE_SHARED_KERNEL_PMD) {
+-		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+-			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+-			if (!pmd)
+-				goto out_oom;
+-			paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
+-			set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
++#ifdef CONFIG_XEN
++	if (!SHARED_KERNEL_PMD) {
++		/*
++		 * We can race save/restore (if we sleep during a GFP_KERNEL memory
++		 * allocation). We therefore store virtual addresses of pmds as they
++		 * do not change across save/restore, and poke the machine addresses
++		 * into the pgdir under the pgd_lock.
++		 */
++		pmds = kmalloc(PTRS_PER_PGD * sizeof(pmd_t *), GFP_KERNEL);
++		if (!pmds) {
++			quicklist_free(0, pgd_dtor, pgd);
++			return NULL;
+ 		}
+-		return pgd;
+-	}
+-
+-	/*
+-	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
+-	 * allocation). We therefore store virtual addresses of pmds as they
+-	 * do not change across save/restore, and poke the machine addresses
+-	 * into the pgdir under the pgd_lock.
+-	 */
+-	pmd = kmalloc(PTRS_PER_PGD * sizeof(pmd_t *), GFP_KERNEL);
+-	if (!pmd) {
+-		kmem_cache_free(pgd_cache, pgd);
+-		return NULL;
+ 	}
++#endif
+ 
+ 	/* Allocate pmds, remember virtual addresses. */
+-	for (i = 0; i < PTRS_PER_PGD; ++i) {
+-		pmd[i] = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+-		if (!pmd[i])
++	for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
++		pmd_t *pmd = pmd_cache_alloc(i);
++
++		if (!pmd)
+ 			goto out_oom;
++
+ 		paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
++		if (pmds)
++			pmds[i] = pmd;
++		else
++			set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+ 	}
+ 
++#ifdef CONFIG_XEN
++	if (SHARED_KERNEL_PMD)
++		return pgd;
++
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 
+ 	/* Protect against save/restore: move below 4GB under pgd_lock. */
+@@ -341,44 +395,43 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 
+ 	/* Copy kernel pmd contents and write-protect the new pmds. */
+ 	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);
+-		memcpy(pmd[i], kpmd, PAGE_SIZE);
++		memcpy(pmds[i],
++		       (void *)pgd_page_vaddr(swapper_pg_dir[i]),
++		       sizeof(pmd_t) * PTRS_PER_PMD);
+ 		make_lowmem_page_readonly(
+-			pmd[i], XENFEAT_writable_page_tables);
++			pmds[i], XENFEAT_writable_page_tables);
+ 	}
+ 
+ 	/* It is safe to poke machine addresses of pmds under the pmd_lock. */
+ 	for (i = 0; i < PTRS_PER_PGD; i++)
+-		set_pgd(&pgd[i], __pgd(1 + __pa(pmd[i])));
++		set_pgd(&pgd[i], __pgd(1 + __pa(pmds[i])));
+ 
+ 	/* Ensure this pgd gets picked up and pinned on save/restore. */
+ 	pgd_list_add(pgd);
+ 
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+ 
+-	kfree(pmd);
++	kfree(pmds);
++#endif
+ 
+ 	return pgd;
+ 
+ out_oom:
+-	if (HAVE_SHARED_KERNEL_PMD) {
++	if (!pmds) {
+ 		for (i--; i >= 0; i--) {
+ 			pgd_t pgdent = pgd[i];
+ 			void* pmd = (void *)__va(pgd_val(pgdent)-1);
+ 			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-			kmem_cache_free(pmd_cache, pmd);
++			pmd_cache_free(pmd, i);
+ 		}
+ 	} else {
+ 		for (i--; i >= 0; i--) {
+-			paravirt_release_pd(__pa(pmd[i]) >> PAGE_SHIFT);
+-			kmem_cache_free(pmd_cache, pmd[i]);
++			paravirt_release_pd(__pa(pmds[i]) >> PAGE_SHIFT);
++			pmd_cache_free(pmds[i], i);
+ 		}
+-		kfree(pmd);
++		kfree(pmds);
+ 	}
+-	kmem_cache_free(pgd_cache, pgd);
++	quicklist_free(0, pgd_dtor, pgd);
+ 	return NULL;
+ }
+ 
+@@ -398,35 +451,24 @@ void pgd_free(pgd_t *pgd)
+ 
+ 	/* 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) {
++		for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
+ 			pgd_t pgdent = pgd[i];
+ 			void* pmd = (void *)__va(pgd_val(pgdent)-1);
+ 			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-			kmem_cache_free(pmd_cache, pmd);
++			pmd_cache_free(pmd, i);
+ 		}
+ 
+-		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);
+-				make_lowmem_page_writable(
+-					pmd, XENFEAT_writable_page_tables);
+-				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+-				kmem_cache_free(pmd_cache, pmd);
+-			}
+-
+-			if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
+-				xen_destroy_contiguous_region(
+-					(unsigned long)pgd, 0);
+-		}
++		if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
++			xen_destroy_contiguous_region((unsigned long)pgd, 0);
+ 	}
+ 
+ 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
+-	kmem_cache_free(pgd_cache, pgd);
++	quicklist_free(0, pgd_dtor, pgd);
++}
++
++void check_pgt_cache(void)
++{
++	quicklist_trim(0, pgd_dtor, 25, 16);
+ }
+ 
+ void make_lowmem_page_readonly(void *va, unsigned int feature)
+@@ -723,13 +765,13 @@ void mm_pin_all(void)
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+ 
+-void _arch_dup_mmap(struct mm_struct *mm)
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+ {
+ 	if (!test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags))
+ 		mm_pin(mm);
+ }
+ 
+-void _arch_exit_mmap(struct mm_struct *mm)
++void arch_exit_mmap(struct mm_struct *mm)
+ {
+ 	struct task_struct *tsk = current;
+ 
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:49:47.000000000 +0100
+@@ -431,11 +431,7 @@ ia32_sys_call_table:
+ 	.quad sys_symlink
+ 	.quad sys_lstat
+ 	.quad sys_readlink		/* 85 */
+-#ifdef CONFIG_IA32_AOUT
+ 	.quad sys_uselib
+-#else
+-	.quad quiet_ni_syscall
+-#endif
+ 	.quad sys_swapon
+ 	.quad sys_reboot
+ 	.quad compat_sys_old_readdir
+@@ -574,7 +570,7 @@ ia32_sys_call_table:
+ 	.quad quiet_ni_syscall		/* tux */
+ 	.quad quiet_ni_syscall    	/* security */
+ 	.quad sys_gettid	
+-	.quad sys_readahead	/* 225 */
++	.quad sys32_readahead	/* 225 */
+ 	.quad sys_setxattr
+ 	.quad sys_lsetxattr
+ 	.quad sys_fsetxattr
+@@ -599,7 +595,7 @@ ia32_sys_call_table:
+ 	.quad compat_sys_io_getevents
+ 	.quad compat_sys_io_submit
+ 	.quad sys_io_cancel
+-	.quad sys_fadvise64		/* 250 */
++	.quad sys32_fadvise64		/* 250 */
+ 	.quad quiet_ni_syscall 	/* free_huge_pages */
+ 	.quad sys_exit_group
+ 	.quad sys32_lookup_dcookie
+@@ -663,10 +659,14 @@ ia32_sys_call_table:
+ 	.quad compat_sys_set_robust_list
+ 	.quad compat_sys_get_robust_list
+ 	.quad sys_splice
+-	.quad sys_sync_file_range
+-	.quad sys_tee
++	.quad sys32_sync_file_range
++	.quad sys_tee			/* 315 */
+ 	.quad compat_sys_vmsplice
+ 	.quad compat_sys_move_pages
+ 	.quad sys_getcpu
+ 	.quad sys_epoll_pwait
+-ia32_syscall_end:		
++	.quad compat_sys_utimensat	/* 320 */
++	.quad compat_sys_signalfd
++	.quad compat_sys_timerfd
++	.quad sys_eventfd
++ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -60,19 +60,6 @@ unsigned long acpi_video_flags;
+ extern char wakeup_start, wakeup_end;
+ 
+ extern unsigned long acpi_copy_wakeup_routine(unsigned long);
+-
+-static pgd_t low_ptr;
+-
+-static void init_low_mapping(void)
+-{
+-	pgd_t *slot0 = pgd_offset(current->mm, 0UL);
+-	low_ptr = *slot0;
+-	/* FIXME: We're playing with the current task's page tables here, which
+-	 * is potentially dangerous on SMP systems.
+-	 */
+-	set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
+-	local_flush_tlb();
+-}
+ #endif
+ 
+ /**
+@@ -84,8 +71,6 @@ static void init_low_mapping(void)
+ int acpi_save_state_mem(void)
+ {
+ #ifndef CONFIG_ACPI_PV_SLEEP
+-	init_low_mapping();
+-
+ 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
+ 	       &wakeup_end - &wakeup_start);
+ 	acpi_copy_wakeup_routine(acpi_wakeup_address);
+@@ -98,10 +83,6 @@ int acpi_save_state_mem(void)
+  */
+ void acpi_restore_state_mem(void)
+ {
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
+-	local_flush_tlb();
+-#endif
+ }
+ 
+ /**
+@@ -115,10 +96,11 @@ void acpi_restore_state_mem(void)
+ void __init acpi_reserve_bootmem(void)
+ {
+ #ifndef CONFIG_ACPI_PV_SLEEP
+-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
+-	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE)
++	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
++	if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE*2))
+ 		printk(KERN_CRIT
+-		       "ACPI: Wakeup code way too big, will crash on attempt to suspend\n");
++		       "ACPI: Wakeup code way too big, will crash on attempt"
++		       " to suspend\n");
+ #endif
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -19,7 +19,6 @@
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+ #include <linux/bootmem.h>
+-#include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/kernel_stat.h>
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:52:06.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:57:54.000000000 +0100
+@@ -17,6 +17,8 @@
+ #include <linux/kexec.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
++#include <linux/suspend.h>
++#include <linux/pfn.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
+@@ -28,7 +30,7 @@
+ 
+ struct e820map e820 __initdata;
+ #ifdef CONFIG_XEN
+-struct e820map machine_e820 __initdata;
++struct e820map machine_e820;
+ #endif
+ 
+ /* 
+@@ -293,22 +295,6 @@ void __init e820_reserve_resources(struc
+ }
+ 
+ #ifndef CONFIG_XEN
+-/* Mark pages corresponding to given address range as nosave */
+-static void __init
+-e820_mark_nosave_range(unsigned long start, unsigned long end)
+-{
+-	unsigned long pfn, max_pfn;
+-
+-	if (start >= end)
+-		return;
+-
+-	printk("Nosave address range: %016lx - %016lx\n", start, end);
+-	max_pfn = end >> PAGE_SHIFT;
+-	for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
+-		if (pfn_valid(pfn))
+-			SetPageNosave(pfn_to_page(pfn));
+-}
+-
+ /*
+  * Find the ranges of physical addresses that do not correspond to
+  * e820 RAM areas and mark the corresponding pages as nosave for software
+@@ -327,13 +313,13 @@ void __init e820_mark_nosave_regions(voi
+ 		struct e820entry *ei = &e820.map[i];
+ 
+ 		if (paddr < ei->addr)
+-			e820_mark_nosave_range(paddr,
+-					round_up(ei->addr, PAGE_SIZE));
++			register_nosave_region(PFN_DOWN(paddr),
++						PFN_UP(ei->addr));
+ 
+ 		paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
+ 		if (ei->type != E820_RAM)
+-			e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE),
+-					paddr);
++			register_nosave_region(PFN_UP(ei->addr),
++						PFN_DOWN(paddr));
+ 
+ 		if (paddr >= (end_pfn << PAGE_SHIFT))
+ 			break;
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -11,13 +11,12 @@
+ 
+ #ifdef __i386__
+ #include <asm/setup.h>
+-#define VGABASE		(__ISA_IO_base + 0xb8000)
+ #else
+ #include <asm/bootsetup.h>
+-#define VGABASE		((void __iomem *)0xffffffff800b8000UL)
+ #endif
+-
+ #ifndef CONFIG_XEN
++#define VGABASE		(__ISA_IO_base + 0xb8000)
++
+ static int max_ypos = 25, max_xpos = 80;
+ static int current_ypos = 25, current_xpos = 0; 
+ 
+@@ -93,9 +92,9 @@ static int early_serial_putc(unsigned ch
+ static void early_serial_write(struct console *con, const char *s, unsigned n)
+ {
+ 	while (*s && n-- > 0) {
+-		early_serial_putc(*s);
+ 		if (*s == '\n')
+ 			early_serial_putc('\r');
++		early_serial_putc(*s);
+ 		s++;
+ 	}
+ }
+@@ -205,7 +204,7 @@ static noinline long simnow(long cmd, lo
+ 	return ret;
+ }
+ 
+-void __init simnow_init(char *str)
++static void __init simnow_init(char *str)
+ {
+ 	char *fn = "klog";
+ 	if (*str == '=')
+@@ -277,22 +276,12 @@ static int __init setup_early_printk(cha
+  		early_console = &simnow_console;
+  		keep_early = 1;
+ 	}
++
++	if (keep_early)
++		early_console->flags &= ~CON_BOOT;
++	else
++		early_console->flags |= CON_BOOT;
+ 	register_console(early_console);
+ 	return 0;
+ }
+-
+ early_param("earlyprintk", setup_early_printk);
+-
+-void __init disable_early_printk(void)
+-{
+-	if (!early_console_initialized || !early_console)
+-		return;
+-	if (!keep_early) {
+-		printk("disabling early console\n");
+-		unregister_console(early_console);
+-		early_console_initialized = 0;
+-	} else {
+-		printk("keeping early console\n");
+-	}
+-}
+-
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:49:47.000000000 +0100
+@@ -1249,3 +1249,23 @@ ENTRY(call_softirq)
+ 	ret
+ 	CFI_ENDPROC
+ ENDPROC(call_softirq)
++
++#ifndef CONFIG_IA32_EMULATION
++KPROBE_ENTRY(ignore_sysret)
++	CFI_STARTPROC	simple
++	CFI_SIGNAL_FRAME
++	CFI_DEF_CFA	rsp,SS+8-RIP+16
++/*	CFI_REL_OFFSET	ss,SS-RIP+16 */
++	CFI_REL_OFFSET	rsp,RSP-RIP+16
++/*	CFI_REL_OFFSET	rflags,EFLAGS-RIP+16 */
++/*	CFI_REL_OFFSET	cs,CS-RIP+16 */
++	CFI_REL_OFFSET	rip,RIP-RIP+16
++	popq %rcx
++	CFI_ADJUST_CFA_OFFSET -8
++	popq %r11
++	CFI_ADJUST_CFA_OFFSET -8
++	mov $-ENOSYS,%eax
++	HYPERVISOR_IRET 0
++	CFI_ENDPROC
++ENDPROC(ignore_sysret)
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:49:47.000000000 +0100
+@@ -5,6 +5,7 @@
+  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
+  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
+  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
++ *  Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
+  *  Jun Nakajima <jun.nakajima@intel.com>
+  *    Modified for Xen                                
+  */
+@@ -34,27 +35,15 @@ startup_64:
+ 	pushq $0		# fake return address
+ 	jmp x86_64_start_kernel
+ 
+-#ifdef CONFIG_ACPI_SLEEP
+-.org 0xf00
+-	.globl pGDT32
+-pGDT32:
+-	.word	gdt_end-cpu_gdt_table-1
+-	.long	cpu_gdt_table-__START_KERNEL_map
+-#endif
+-ENTRY(stext)
+-ENTRY(_stext)
++.balign PAGE_SIZE
+ 
+-	$page = 0
+ #define NEXT_PAGE(name) \
+-	$page = $page + 1; \
+-	.org $page * 0x1000; \
+-	phys_##name = $page * 0x1000 + __PHYSICAL_START; \
++	.balign	PAGE_SIZE; \
++	phys_##name = . - .bootstrap.text; \
+ ENTRY(name)
+ 
+ NEXT_PAGE(init_level4_pgt)
+-	/* This gets initialized in x86_64_start_kernel */
+ 	.fill	512,8,0
+-NEXT_PAGE(init_level4_user_pgt)
+         /*
+          * We update two pgd entries to make kernel and user pgd consistent
+          * at pgd_populate(). It can be used for kernel modules. So we place 
+@@ -98,14 +87,6 @@ NEXT_PAGE(hypercall_page)
+ #undef NEXT_PAGE
+ 
+ 	.data
+-/* Just dummy symbol to allow compilation. Not used in sleep path */
+-#ifdef CONFIG_ACPI_SLEEP
+-	.align PAGE_SIZE
+-ENTRY(wakeup_level4_pgt)
+-	.fill	512,8,0
+-#endif
+-
+-	.data
+ 
+ 	.align 16
+ 	.globl cpu_gdt_descr
+@@ -133,13 +114,13 @@ gdt:
+ 
+ ENTRY(cpu_gdt_table)
+ 	.quad	0x0000000000000000	/* NULL descriptor */
++	.quad	0x00cf9b000000ffff	/* __KERNEL32_CS */
++	.quad	0x00af9b000000ffff	/* __KERNEL_CS */
++	.quad	0x00cf93000000ffff	/* __KERNEL_DS */
++	.quad	0x00cffb000000ffff	/* __USER32_CS */
++	.quad	0x00cff3000000ffff	/* __USER_DS, __USER32_DS  */
++	.quad	0x00affb000000ffff	/* __USER_CS */
+ 	.quad	0x0			/* unused */
+-	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
+-	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
+-	.quad	0x00cffa000000ffff	/* __USER32_CS */
+-	.quad	0x00cff2000000ffff	/* __USER_DS, __USER32_DS  */
+-	.quad	0x00affa000000ffff	/* __USER_CS */
+-	.quad	0x00cf9a000000ffff	/* __KERNEL32_CS */
+ 	.quad	0,0			/* TSS */
+ 	.quad	0,0			/* LDT */
+ 	.quad   0,0,0			/* three TLS descriptors */
+@@ -162,14 +143,11 @@ ENTRY(empty_zero_page)
+  * __xen_guest information
+  */
+ .macro utoh value
+- .if (\value) < 0 || (\value) >= 0x10
+-	utoh (((\value)>>4)&0x0fffffffffffffff)
+- .endif
+- .if ((\value) & 0xf) < 10
+-  .byte '0' + ((\value) & 0xf)
+- .else
+-  .byte 'A' + ((\value) & 0xf) - 10
+- .endif
++ i = 64
++ .rept 16
++  i = i - 4
++  .byte '0' + ((((\value) >> i) & 0xf) > 9) * ('0' - 'A' + 10) + (((\value) >> i) & 0xf)
++ .endr
+ .endm
+ 
+ .section __xen_guest
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -25,13 +25,21 @@
+ #include <asm/setup.h>
+ #include <asm/desc.h>
+ #include <asm/pgtable.h>
++#include <asm/tlbflush.h>
+ #include <asm/sections.h>
+ 
+ unsigned long start_pfn;
+ 
++#ifndef CONFIG_XEN
++static void __init zap_identity_mappings(void)
++{
++	pgd_t *pgd = pgd_offset_k(0UL);
++	pgd_clear(pgd);
++	__flush_tlb();
++}
++
+ /* 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,
+@@ -40,26 +48,25 @@ static void __init clear_bss(void)
+ #endif
+ 
+ #define NEW_CL_POINTER		0x228	/* Relative to real mode data */
+-#define OLD_CL_MAGIC_ADDR	0x90020
++#define OLD_CL_MAGIC_ADDR	0x20
+ #define OLD_CL_MAGIC            0xA33F
+-#define OLD_CL_BASE_ADDR        0x90000
+-#define OLD_CL_OFFSET           0x90022
++#define OLD_CL_OFFSET           0x22
+ 
+ static void __init copy_bootdata(char *real_mode_data)
+ {
+ #ifndef CONFIG_XEN
+-	int new_data;
++	unsigned long new_data;
+ 	char * command_line;
+ 
+ 	memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
+-	new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
++	new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER);
+ 	if (!new_data) {
+-		if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
++		if (OLD_CL_MAGIC != *(u16 *)(real_mode_data + OLD_CL_MAGIC_ADDR)) {
+ 			return;
+ 		}
+-		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
++		new_data = __pa(real_mode_data) + *(u16 *)(real_mode_data + OLD_CL_OFFSET);
+ 	}
+-	command_line = (char *) ((u64)(new_data));
++	command_line = __va(new_data);
+ 	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ #else
+ 	int max_cmdline;
+@@ -101,10 +108,13 @@ void __init x86_64_start_kernel(char * r
+ 	while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
+ 		machine_to_phys_order++;
+ 
+-#if 0
++#ifndef CONFIG_XEN
+ 	/* clear bss before set_intr_gate with early_idt_handler */
+ 	clear_bss();
+ 
++	/* Make NULL pointers segfault */
++	zap_identity_mappings();
++
+ 	for (i = 0; i < IDT_ENTRIES; i++)
+ 		set_intr_gate(i, early_idt_handler);
+ 	asm volatile("lidt %0" :: "m" (idt_descr));
+@@ -116,7 +126,7 @@ void __init x86_64_start_kernel(char * r
+  		cpu_pda(i) = &boot_cpu_pda[i];
+ 
+ 	pda_init(0);
+-	copy_bootdata(real_mode_data);
++	copy_bootdata(__va(real_mode_data));
+ #ifdef CONFIG_SMP
+ 	cpu_set(0, cpu_online_map);
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -25,7 +25,6 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/sched.h>
+-#include <linux/smp_lock.h>
+ #include <linux/pci.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/acpi.h>
+@@ -904,10 +903,6 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	enable_8259A_irq(0);
+ }
+ 
+-void __init UNEXPECTED_IO_APIC(void)
+-{
+-}
+-
+ void __apicdebuginit print_IO_APIC(void)
+ {
+ 	int apic, i;
+@@ -943,40 +938,16 @@ void __apicdebuginit print_IO_APIC(void)
+ 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
+ 	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ 	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+-	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
+ 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+-	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
+-		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
+-		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
+-		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
+-		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
+-		(reg_01.bits.entries != 0x2E) &&
+-		(reg_01.bits.entries != 0x3F) &&
+-		(reg_01.bits.entries != 0x03) 
+-	)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+ 	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+-	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
+-		(reg_01.bits.version != 0x02) && /* 82801BA IO-APICs (ICH2) */
+-		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
+-		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
+-		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
+-		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
+-	)
+-		UNEXPECTED_IO_APIC();
+-	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
+-		UNEXPECTED_IO_APIC();
+ 
+ 	if (reg_01.bits.version >= 0x10) {
+ 		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+ 		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+-		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
+-			UNEXPECTED_IO_APIC();
+ 	}
+ 
+ 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+@@ -1408,8 +1379,7 @@ static void irq_complete_move(unsigned i
+ 
+ 	vector = ~get_irq_regs()->orig_rax;
+ 	me = smp_processor_id();
+-	if ((vector == cfg->vector) &&
+-	    cpu_isset(smp_processor_id(), cfg->domain)) {
++	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
+ 		cpumask_t cleanup_mask;
+ 
+ 		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+@@ -1444,7 +1414,7 @@ static void ack_apic_level(unsigned int 
+ 
+ 	/*
+ 	 * We must acknowledge the irq before we move it or the acknowledge will
+-	 * not propogate properly.
++	 * not propagate properly.
+ 	 */
+ 	ack_APIC_irq();
+ 
+@@ -1527,6 +1497,7 @@ static void ack_lapic_irq (unsigned int 
+ static void end_lapic_irq (unsigned int i) { /* nothing */ }
+ 
+ static struct hw_interrupt_type lapic_irq_type __read_mostly = {
++	.name = "local-APIC",
+ 	.typename = "local-APIC-edge",
+ 	.startup = NULL, /* startup_irq() not used for IRQ0 */
+ 	.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
+@@ -1998,18 +1969,18 @@ int arch_setup_msi_irq(struct pci_dev *d
+ 	if (irq < 0)
+ 		return irq;
+ 
+-	set_irq_msi(irq, desc);
+ 	ret = msi_compose_msg(dev, irq, &msg);
+ 	if (ret < 0) {
+ 		destroy_irq(irq);
+ 		return ret;
+ 	}
+ 
++	set_irq_msi(irq, desc);
+ 	write_msi_msg(irq, &msg);
+ 
+ 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+ 
+-	return irq;
++	return 0;
+ }
+ 
+ void arch_teardown_msi_irq(unsigned int irq)
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,10 +13,10 @@
+ #include <linux/ioport.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/stddef.h>
+ #include <linux/slab.h>
+ #include <linux/thread_info.h>
++#include <linux/syscalls.h>
+ #include <xen/interface/physdev.h>
+ 
+ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -32,7 +32,7 @@ atomic_t irq_err_count;
+  */
+ static inline void stack_overflow_check(struct pt_regs *regs)
+ {
+-	u64 curbase = (u64) current->thread_info;
++	u64 curbase = (u64)task_stack_page(current);
+ 	static unsigned long warned = -60*HZ;
+ 
+ 	if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
+@@ -145,17 +145,43 @@ void fixup_irqs(cpumask_t map)
+ 
+ 	for (irq = 0; irq < NR_IRQS; irq++) {
+ 		cpumask_t mask;
++		int break_affinity = 0;
++		int set_affinity = 1;
++
+ 		if (irq == 2)
+ 			continue;
+ 
++		/* interrupt's are disabled at this point */
++		spin_lock(&irq_desc[irq].lock);
++
++		if (!irq_has_action(irq) ||
++		    cpus_equal(irq_desc[irq].affinity, map)) {
++			spin_unlock(&irq_desc[irq].lock);
++			continue;
++		}
++
+ 		cpus_and(mask, irq_desc[irq].affinity, map);
+-		if (any_online_cpu(mask) == NR_CPUS) {
+-			/*printk("Breaking affinity for irq %i\n", irq);*/
++		if (cpus_empty(mask)) {
++			break_affinity = 1;
+ 			mask = map;
+ 		}
++
++		if (irq_desc[irq].chip->mask)
++			irq_desc[irq].chip->mask(irq);
++
+ 		if (irq_desc[irq].chip->set_affinity)
+ 			irq_desc[irq].chip->set_affinity(irq, mask);
+-		else if (irq_desc[irq].action && !(warned++))
++		else if (!(warned++))
++			set_affinity = 0;
++
++		if (irq_desc[irq].chip->unmask)
++			irq_desc[irq].chip->unmask(irq);
++
++		spin_unlock(&irq_desc[irq].lock);
++
++		if (break_affinity && set_affinity)
++			/*printk("Broke affinity for irq %i\n", irq)*/;
++		else if (!set_affinity)
+ 			printk("Cannot set affinity for irq %i\n", irq);
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_64-xen.c	2007-06-12 13:13:01.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -13,7 +13,6 @@
+ #include <linux/string.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -17,7 +17,6 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/bootmem.h>
+-#include <linux/smp_lock.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/acpi.h>
+@@ -307,7 +306,7 @@ static int __init smp_read_mpc(struct mp
+ 			}
+ 		}
+ 	}
+-	clustered_apic_check();
++	setup_apic_routing();
+ 	if (!num_processors)
+ 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ 	return num_processors;
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/random.h>
+ #include <linux/notifier.h>
+ #include <linux/kprobes.h>
++#include <linux/kdebug.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -49,7 +50,6 @@
+ #include <asm/mmu_context.h>
+ #include <asm/pda.h>
+ #include <asm/prctl.h>
+-#include <asm/kdebug.h>
+ #include <xen/interface/platform.h>
+ #include <xen/interface/physdev.h>
+ #include <xen/interface/vcpu.h>
+@@ -232,16 +232,18 @@ void __cpuinit select_idle_routine(const
+ 
+ static int __init idle_setup (char *str)
+ {
+-	if (!strncmp(str, "poll", 4)) {
++	if (!strcmp(str, "poll")) {
+ 		printk("using polling idle threads.\n");
+ 		pm_idle = poll_idle;
+-	}
++	} else if (!strcmp(str, "mwait"))
++		force_mwait = 1;
++	else
++		return -1;
+ 
+ 	boot_option_idle_override = 1;
+-	return 1;
++	return 0;
+ }
+-
+-__setup("idle=", idle_setup);
++early_param("idle", idle_setup);
+ 
+ /* Prints also some state that isn't saved in the pt_regs */ 
+ void __show_regs(struct pt_regs * regs)
+@@ -546,7 +548,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	 * The AMD workaround requires it to be after DS reload, or
+ 	 * after DS has been cleared, which we do in __prepare_arch_switch.
+ 	 */
+-	if (prev_p->thread_info->status & TS_USEDFPU) {
++	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+ 		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+ 		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+ 		mcl->args[0] = 1;
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -120,6 +120,8 @@ int bootloader_type;
+ 
+ unsigned long saved_video_mode;
+ 
++int force_mwait __cpuinitdata;
++
+ /* 
+  * Early DMI memory
+  */
+@@ -254,10 +256,10 @@ static void discover_ebda(void)
+ 	 * there is a real-mode segmented pointer pointing to the 
+ 	 * 4K EBDA area at 0x40E
+ 	 */
+-	ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
++	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
+ 	ebda_addr <<= 4;
+ 
+-	ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
++	ebda_size = *(unsigned short *)__va(ebda_addr);
+ 
+ 	/* Round EBDA up to pages */
+ 	if (ebda_size == 0)
+@@ -411,15 +413,8 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ #ifdef CONFIG_SMP
+-	/*
+-	 * But first pinch a few for the stack/trampoline stuff
+-	 * FIXME: Don't need the extra page at 4K, but need to fix
+-	 * trampoline before removing it. (see the GDT stuff)
+-	 */
+-	reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);
+-
+ 	/* Reserve SMP trampoline */
+-	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
++	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
+ #endif
+ #endif
+ 
+@@ -571,8 +566,6 @@ void __init setup_arch(char **cmdline_p)
+ 	early_quirks();
+ #endif
+ 
+-	zap_low_mappings(0);
+-
+ 	/*
+ 	 * set this early, so we dont allocate cpu0
+ 	 * if MADT list doesnt list BSP first
+@@ -865,6 +858,10 @@ static void __cpuinit init_amd(struct cp
+ 
+ 	/* RDTSC can be speculated around */
+ 	clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++
++	/* Family 10 doesn't support C states in MWAIT so don't use it */
++	if (c->x86 == 0x10 && !force_mwait)
++		clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
+ }
+ 
+ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -1149,9 +1146,7 @@ void __cpuinit identify_cpu(struct cpuin
+ #ifdef CONFIG_X86_MCE
+ 	mcheck_init(c);
+ #endif
+-	if (c == &boot_cpu_data)
+-		mtrr_bp_init();
+-	else
++	if (c != &boot_cpu_data)
+ 		mtrr_ap_init();
+ #ifdef CONFIG_NUMA
+ 	numa_add_cpu(smp_processor_id());
+@@ -1242,9 +1237,8 @@ static int show_cpuinfo(struct seq_file 
+ 		"stc",
+ 		"100mhzsteps",
+ 		"hwpstate",
+-		NULL,	/* tsc invariant mapped to constant_tsc */
+-		NULL,
+-		/* nothing */	/* constant_tsc - moved to flags */
++		"",	/* tsc invariant mapped to constant_tsc */
++		/* nothing */
+ 	};
+ 
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -113,9 +113,9 @@ void __init setup_per_cpu_areas(void)
+ 		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);
++			ptr = alloc_bootmem_pages(size);
+ 		} else { 
+-			ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
++			ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
+ 		}
+ 		if (!ptr)
+ 			panic("Cannot allocate cpu data for CPU %d\n", i);
+@@ -208,6 +208,8 @@ char boot_exception_stacks[(N_EXCEPTION_
+ __attribute__((section(".bss.page_aligned")));
+ #endif
+ 
++extern asmlinkage void ignore_sysret(void);
++
+ /* May not be marked __init: used by software suspend */
+ void syscall_init(void)
+ {
+@@ -219,12 +221,22 @@ void syscall_init(void)
+ 	 */ 
+ 	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); 
+ 	wrmsrl(MSR_LSTAR, system_call); 
++	wrmsrl(MSR_CSTAR, ignore_sysret);
+ 
+ 	/* Flags to clear on syscall */
+ 	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
+ #endif
+ #ifdef CONFIG_IA32_EMULATION   		
+ 	syscall32_cpu_init ();
++#else
++	{
++		static const struct callback_register cstar = {
++			.type = CALLBACKTYPE_syscall32,
++			.address = (unsigned long)ignore_sysret
++		};
++		if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
++			printk(KERN_WARNING "Unable to register CSTAR callback\n");
++	}
+ #endif
+ }
+ 
+@@ -262,7 +274,6 @@ void __cpuinit cpu_init (void)
+ 	/* CPU 0 is initialised in head64.c */
+ 	if (cpu != 0) {
+ 		pda_init(cpu);
+-		zap_low_mappings(cpu);
+ 	}
+ #ifndef CONFIG_X86_NO_TSS
+ 	else
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -14,7 +14,6 @@
+ #include <linux/mm.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+-#include <linux/smp_lock.h>
+ #include <linux/smp.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/mc146818rtc.h>
+@@ -457,44 +456,36 @@ int smp_call_function (void (*func) (voi
+ }
+ EXPORT_SYMBOL(smp_call_function);
+ 
+-void smp_stop_cpu(void)
++static void stop_this_cpu(void *dummy)
+ {
+-	unsigned long flags;
++	local_irq_disable();
+ 	/*
+ 	 * Remove this CPU:
+ 	 */
+ 	cpu_clear(smp_processor_id(), cpu_online_map);
+-	local_irq_save(flags);
+ 	disable_all_local_evtchn();
+-	local_irq_restore(flags); 
+-}
+-
+-static void smp_really_stop_cpu(void *dummy)
+-{
+-	smp_stop_cpu(); 
+ 	for (;;) 
+ 		halt();
+ } 
+ 
+ void smp_send_stop(void)
+ {
+-	int nolock = 0;
++	int nolock;
++	unsigned long flags;
++
+ #ifndef CONFIG_XEN
+ 	if (reboot_force)
+ 		return;
+ #endif
++
+ 	/* Don't deadlock on the call lock in panic */
+-	if (!spin_trylock(&call_lock)) {
+-		/* ignore locking because we have panicked anyways */
+-		nolock = 1;
+-	}
+-	__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
++	nolock = !spin_trylock(&call_lock);
++	local_irq_save(flags);
++	__smp_call_function(stop_this_cpu, NULL, 0, 0);
+ 	if (!nolock)
+ 		spin_unlock(&call_lock);
+-
+-	local_irq_disable();
+ 	disable_all_local_evtchn();
+-	local_irq_enable();
++	local_irq_restore(flags);
+ }
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -32,6 +32,7 @@
+ #include <linux/unwind.h>
+ #include <linux/uaccess.h>
+ #include <linux/bug.h>
++#include <linux/kdebug.h>
+ 
+ #include <asm/system.h>
+ #include <asm/io.h>
+@@ -39,7 +40,6 @@
+ #include <asm/debugreg.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+-#include <asm/kdebug.h>
+ #include <asm/processor.h>
+ #include <asm/unwind.h>
+ #include <asm/smp.h>
+@@ -71,22 +71,6 @@ asmlinkage void alignment_check(void);
+ asmlinkage void machine_check(void);
+ asmlinkage void spurious_interrupt_bug(void);
+ 
+-ATOMIC_NOTIFIER_HEAD(die_chain);
+-EXPORT_SYMBOL(die_chain);
+-
+-int register_die_notifier(struct notifier_block *nb)
+-{
+-	vmalloc_sync_all();
+-	return atomic_notifier_chain_register(&die_chain, nb);
+-}
+-EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
+-
+-int unregister_die_notifier(struct notifier_block *nb)
+-{
+-	return atomic_notifier_chain_unregister(&die_chain, nb);
+-}
+-EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
+-
+ static inline void conditional_sti(struct pt_regs *regs)
+ {
+ 	if (regs->eflags & X86_EFLAGS_IF)
+@@ -428,8 +412,7 @@ void show_registers(struct pt_regs *regs
+ 	const int cpu = smp_processor_id();
+ 	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
+ 
+-		rsp = regs->rsp;
+-
++	rsp = regs->rsp;
+ 	printk("CPU %d ", cpu);
+ 	__show_regs(regs);
+ 	printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
+@@ -440,7 +423,6 @@ void show_registers(struct pt_regs *regs
+ 	 * time of the fault..
+ 	 */
+ 	if (in_kernel) {
+-
+ 		printk("Stack: ");
+ 		_show_stack(NULL, regs, (unsigned long*)rsp);
+ 
+@@ -485,13 +467,14 @@ static unsigned int die_nest_count;
+ 
+ unsigned __kprobes long oops_begin(void)
+ {
+-	int cpu = smp_processor_id();
++	int cpu;
+ 	unsigned long flags;
+ 
+ 	oops_enter();
+ 
+ 	/* racy, but better than risking deadlock. */
+ 	local_irq_save(flags);
++	cpu = smp_processor_id();
+ 	if (!spin_trylock(&die_lock)) { 
+ 		if (cpu == die_owner) 
+ 			/* nested oops. should stop eventually */;
+@@ -585,10 +568,20 @@ static void __kprobes do_trap(int trapnr
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = trapnr;
+-
+ 	if (user_mode(regs)) {
++		/*
++		 * We want error_code and trap_no set for userspace
++		 * faults and kernelspace faults which result in
++		 * die(), but not kernelspace faults which are fixed
++		 * up.  die() gives the process no chance to handle
++		 * the signal and notice the kernel fault information,
++		 * so that won't result in polluting the information
++		 * about previously queued, but not yet delivered,
++		 * faults.  See also do_general_protection below.
++		 */
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++
+ 		if (exception_trace && unhandled_signal(tsk, signr))
+ 			printk(KERN_INFO
+ 			       "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
+@@ -609,8 +602,11 @@ static void __kprobes do_trap(int trapnr
+ 		fixup = search_exception_tables(regs->rip);
+ 		if (fixup)
+ 			regs->rip = fixup->fixup;
+-		else	
++		else {
++			tsk->thread.error_code = error_code;
++			tsk->thread.trap_no = trapnr;
+ 			die(str, regs, error_code);
++		}
+ 		return;
+ 	}
+ }
+@@ -686,10 +682,10 @@ asmlinkage void __kprobes do_general_pro
+ 
+ 	conditional_sti(regs);
+ 
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 13;
+-
+ 	if (user_mode(regs)) {
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = 13;
++
+ 		if (exception_trace && unhandled_signal(tsk, SIGSEGV))
+ 			printk(KERN_INFO
+ 		       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
+@@ -708,6 +704,9 @@ asmlinkage void __kprobes do_general_pro
+ 			regs->rip = fixup->fixup;
+ 			return;
+ 		}
++
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = 13;
+ 		if (notify_die(DIE_GPF, "general protection fault", regs,
+ 					error_code, 13, SIGSEGV) == NOTIFY_STOP)
+ 			return;
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -45,14 +45,34 @@
+ 
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+ #define __syscall_clobber "r11","rcx","memory"
++#define __pa_vsymbol(x)			\
++	({unsigned long v;  		\
++	extern char __vsyscall_0; 	\
++	  asm("" : "=r" (v) : "0" (x)); \
++	  ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); })
+ 
++/*
++ * vsyscall_gtod_data contains data that is :
++ * - readonly from vsyscalls
++ * - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
++ * Try to keep this structure as small as possible to avoid cache line ping pongs
++ */
+ struct vsyscall_gtod_data_t {
+-	seqlock_t lock;
+-	int sysctl_enabled;
+-	struct timeval wall_time_tv;
++	seqlock_t	lock;
++
++	/* open coded 'struct timespec' */
++	time_t		wall_time_sec;
++	u32		wall_time_nsec;
++
++	int		sysctl_enabled;
+ 	struct timezone sys_tz;
+-	cycle_t offset_base;
+-	struct clocksource clock;
++	struct { /* extract of a clocksource struct */
++		cycle_t (*vread)(void);
++		cycle_t	cycle_last;
++		cycle_t	mask;
++		u32	mult;
++		u32	shift;
++	} clock;
+ };
+ int __vgetcpu_mode __section_vgetcpu_mode;
+ 
+@@ -68,9 +88,13 @@ void update_vsyscall(struct timespec *wa
+ 
+ 	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+ 	/* copy vsyscall data */
+-	vsyscall_gtod_data.clock = *clock;
+-	vsyscall_gtod_data.wall_time_tv.tv_sec = wall_time->tv_sec;
+-	vsyscall_gtod_data.wall_time_tv.tv_usec = wall_time->tv_nsec/1000;
++	vsyscall_gtod_data.clock.vread = clock->vread;
++	vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
++	vsyscall_gtod_data.clock.mask = clock->mask;
++	vsyscall_gtod_data.clock.mult = clock->mult;
++	vsyscall_gtod_data.clock.shift = clock->shift;
++	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
++	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+ 	vsyscall_gtod_data.sys_tz = sys_tz;
+ 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+@@ -105,7 +129,8 @@ static __always_inline long time_syscall
+ static __always_inline void do_vgettimeofday(struct timeval * tv)
+ {
+ 	cycle_t now, base, mask, cycle_delta;
+-	unsigned long seq, mult, shift, nsec_delta;
++	unsigned seq;
++	unsigned long mult, shift, nsec;
+ 	cycle_t (*vread)(void);
+ 	do {
+ 		seq = read_seqbegin(&__vsyscall_gtod_data.lock);
+@@ -121,21 +146,20 @@ static __always_inline void do_vgettimeo
+ 		mult = __vsyscall_gtod_data.clock.mult;
+ 		shift = __vsyscall_gtod_data.clock.shift;
+ 
+-		*tv = __vsyscall_gtod_data.wall_time_tv;
+-
++		tv->tv_sec = __vsyscall_gtod_data.wall_time_sec;
++		nsec = __vsyscall_gtod_data.wall_time_nsec;
+ 	} while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
+ 
+ 	/* calculate interval: */
+ 	cycle_delta = (now - base) & mask;
+ 	/* convert to nsecs: */
+-	nsec_delta = (cycle_delta * mult) >> shift;
++	nsec += (cycle_delta * mult) >> shift;
+ 
+-	/* convert to usecs and add to timespec: */
+-	tv->tv_usec += nsec_delta / NSEC_PER_USEC;
+-	while (tv->tv_usec > USEC_PER_SEC) {
++	while (nsec >= NSEC_PER_SEC) {
+ 		tv->tv_sec += 1;
+-		tv->tv_usec -= USEC_PER_SEC;
++		nsec -= NSEC_PER_SEC;
+ 	}
++	tv->tv_usec = nsec / NSEC_PER_USEC;
+ }
+ 
+ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+@@ -151,11 +175,16 @@ int __vsyscall(0) vgettimeofday(struct t
+  * unlikely */
+ time_t __vsyscall(1) vtime(time_t *t)
+ {
++	struct timeval tv;
++	time_t result;
+ 	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
+ 		return time_syscall(t);
+-	else if (t)
+-		*t = __vsyscall_gtod_data.wall_time_tv.tv_sec;
+-	return __vsyscall_gtod_data.wall_time_tv.tv_sec;
++
++	vgettimeofday(&tv, 0);
++	result = tv.tv_sec;
++	if (t)
++		*t = result;
++	return result;
+ }
+ 
+ /* Fast way to get current CPU and node.
+@@ -224,10 +253,10 @@ static int vsyscall_sysctl_change(ctl_ta
+ 		return ret;
+ 	/* gcc has some trouble with __va(__pa()), so just do it this
+ 	   way. */
+-	map1 = ioremap(__pa_symbol(&vsysc1), 2);
++	map1 = ioremap(__pa_vsymbol(&vsysc1), 2);
+ 	if (!map1)
+ 		return -ENOMEM;
+-	map2 = ioremap(__pa_symbol(&vsysc2), 2);
++	map2 = ioremap(__pa_vsymbol(&vsysc2), 2);
+ 	if (!map2) {
+ 		ret = -ENOMEM;
+ 		goto out;
+@@ -304,7 +333,7 @@ static int __cpuinit
+ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
+ {
+ 	long cpu = (long)arg;
+-	if (action == CPU_ONLINE)
++	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
+ 		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
+ 	return NOTIFY_DONE;
+ }
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -15,22 +15,22 @@
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+-#include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h>		/* For unblank_screen() */
+ #include <linux/compiler.h>
++#include <linux/vmalloc.h>
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
++#include <linux/kdebug.h>
+ 
+ #include <asm/system.h>
+ #include <asm/pgalloc.h>
+ #include <asm/smp.h>
+ #include <asm/tlbflush.h>
+ #include <asm/proto.h>
+-#include <asm/kdebug.h>
+ #include <asm-generic/sections.h>
+ 
+ /* Page fault error code bits */
+@@ -537,6 +537,12 @@ bad_area:
+ bad_area_nosemaphore:
+ 	/* User mode accesses just cause a SIGSEGV */
+ 	if (error_code & PF_USER) {
++
++		/*
++		 * It's possible to have interrupts off here.
++		 */
++		local_irq_enable();
++
+ 		if (is_prefetch(regs, address, error_code))
+ 			return;
+ 
+@@ -646,7 +652,7 @@ do_sigbus:
+ }
+ 
+ DEFINE_SPINLOCK(pgd_lock);
+-struct page *pgd_list;
++LIST_HEAD(pgd_list);
+ 
+ void vmalloc_sync_all(void)
+ {
+@@ -666,8 +672,7 @@ void vmalloc_sync_all(void)
+ 			if (pgd_none(*pgd_ref))
+ 				continue;
+ 			spin_lock(&pgd_lock);
+-			for (page = pgd_list; page;
+-			     page = (struct page *)page->index) {
++			list_for_each_entry(page, &pgd_list, lru) {
+ 				pgd_t *pgd;
+ 				pgd = (pgd_t *)page_address(page) + pgd_index(address);
+ 				if (pgd_none(*pgd))
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -25,10 +25,12 @@
+ #include <linux/bootmem.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
++#include <linux/pfn.h>
+ #include <linux/poison.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/module.h>
+ #include <linux/memory_hotplug.h>
++#include <linux/nmi.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/system.h>
+@@ -51,7 +53,7 @@
+ #define Dprintk(x...)
+ #endif
+ 
+-struct dma_mapping_ops* dma_ops;
++const struct dma_mapping_ops* dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+ 
+ #if CONFIG_XEN_COMPAT <= 0x030002
+@@ -191,6 +193,13 @@ void show_mem(void)
+ 
+ 	for_each_online_pgdat(pgdat) {
+                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
++			/* this loop can take a while with 256 GB and 4k pages
++			   so update the NMI watchdog */
++			if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
++				touch_nmi_watchdog();
++			}
++			if (!pfn_valid(pgdat->node_start_pfn + i))
++				continue;
+ 			page = pfn_to_page(pgdat->node_start_pfn + i);
+ 			total++;
+ 			if (PageReserved(page))
+@@ -359,7 +368,7 @@ __set_fixmap (enum fixed_addresses idx, 
+ 	}
+ }
+ 
+-unsigned long __initdata table_start, table_end; 
++unsigned long __meminitdata table_start, table_end;
+ 
+ static __meminit void *alloc_static_page(unsigned long *phys)
+ {
+@@ -376,7 +385,7 @@ static __meminit void *alloc_static_page
+ 	start_pfn++;
+ 	memset((void *)va, 0, PAGE_SIZE);
+ 	return (void *)va;
+-} 
++}
+ 
+ #define PTE_SIZE PAGE_SIZE
+ 
+@@ -412,28 +421,46 @@ static inline int make_readonly(unsigned
+ 
+ #ifndef CONFIG_XEN
+ /* Must run before zap_low_mappings */
+-__init void *early_ioremap(unsigned long addr, unsigned long size)
++__meminit void *early_ioremap(unsigned long addr, unsigned long size)
+ {
+-	unsigned long map = round_down(addr, LARGE_PAGE_SIZE);
+-
+-	/* actually usually some more */
+-	if (size >= LARGE_PAGE_SIZE) {
+-		return NULL;
++	unsigned long vaddr;
++	pmd_t *pmd, *last_pmd;
++	int i, pmds;
++
++	pmds = ((addr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
++	vaddr = __START_KERNEL_map;
++	pmd = level2_kernel_pgt;
++	last_pmd = level2_kernel_pgt + PTRS_PER_PMD - 1;
++	for (; pmd <= last_pmd; pmd++, vaddr += PMD_SIZE) {
++		for (i = 0; i < pmds; i++) {
++			if (pmd_present(pmd[i]))
++				goto next;
++		}
++		vaddr += addr & ~PMD_MASK;
++		addr &= PMD_MASK;
++		for (i = 0; i < pmds; i++, addr += PMD_SIZE)
++			set_pmd(pmd + i,__pmd(addr | _KERNPG_TABLE | _PAGE_PSE));
++		__flush_tlb();
++		return (void *)vaddr;
++	next:
++		;
+ 	}
+-	set_pmd(temp_mappings[0].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
+-	map += LARGE_PAGE_SIZE;
+-	set_pmd(temp_mappings[1].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
+-	__flush_tlb();
+-	return temp_mappings[0].address + (addr & (LARGE_PAGE_SIZE-1));
++	printk("early_ioremap(0x%lx, %lu) failed\n", addr, size);
++	return NULL;
+ }
+ 
+ /* To avoid virtual aliases later */
+-__init void early_iounmap(void *addr, unsigned long size)
++__meminit void early_iounmap(void *addr, unsigned long size)
+ {
+-	if ((void *)round_down((unsigned long)addr, LARGE_PAGE_SIZE) != temp_mappings[0].address)
+-		printk("early_iounmap: bad address %p\n", addr);
+-	set_pmd(temp_mappings[0].pmd, __pmd(0));
+-	set_pmd(temp_mappings[1].pmd, __pmd(0));
++	unsigned long vaddr;
++	pmd_t *pmd;
++	int i, pmds;
++
++	vaddr = (unsigned long)addr;
++	pmds = ((vaddr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
++	pmd = level2_kernel_pgt + pmd_index(vaddr);
++	for (i = 0; i < pmds; i++)
++		pmd_clear(pmd + i);
+ 	__flush_tlb();
+ }
+ #endif
+@@ -792,14 +819,6 @@ void __meminit init_memory_mapping(unsig
+ 	__flush_tlb_all();
+ }
+ 
+-void __cpuinit zap_low_mappings(int cpu)
+-{
+-	/* this is not required for Xen */
+-#if 0
+-	swap_low_mappings();
+-#endif
+-}
+-
+ #ifndef CONFIG_NUMA
+ void __init paging_init(void)
+ {
+@@ -984,17 +1003,6 @@ void __init mem_init(void)
+ 		reservedpages << (PAGE_SHIFT-10),
+ 		datasize >> 10,
+ 		initsize >> 10);
+-
+-#ifndef CONFIG_XEN
+-#ifdef CONFIG_SMP
+-	/*
+-	 * Sync boot_level4_pgt mappings with the init_level4_pgt
+-	 * except for the low identity mappings which are already zapped
+-	 * in init_level4_pgt. This sync-up is essential for AP's bringup
+-	 */
+-	memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t));
+-#endif
+-#endif
+ }
+ 
+ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+@@ -1004,7 +1012,7 @@ void free_init_pages(char *what, unsigne
+ 	if (begin >= end)
+ 		return;
+ 
+-	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
++	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
+ 	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ 		ClearPageReserved(virt_to_page(addr));
+ 		init_page_count(virt_to_page(addr));
+@@ -1013,24 +1021,17 @@ void free_init_pages(char *what, unsigne
+ 		if (addr >= __START_KERNEL_map) {
+ 			/* make_readonly() reports all kernel addresses. */
+ 			__make_page_writable(__va(__pa(addr)));
+-			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+-				pgd_t *pgd = pgd_offset_k(addr);
+-				pud_t *pud = pud_offset(pgd, addr);
+-				pmd_t *pmd = pmd_offset(pud, addr);
+-				pte_t *pte = pte_offset_kernel(pmd, addr);
+-
+-				xen_l1_entry_update(pte, __pte(0)); /* fallback */
+-			}
++			change_page_attr_addr(addr, 1, __pgprot(0));
+ 		}
+ 		free_page(addr);
+ 		totalram_pages++;
+ 	}
++	if (addr > __START_KERNEL_map)
++		global_flush_tlb();
+ }
+ 
+ void free_initmem(void)
+ {
+-	memset(__initdata_begin, POISON_FREE_INITDATA,
+-		__initdata_end - __initdata_begin);
+ 	free_init_pages("unused kernel memory",
+ 			(unsigned long)(&__init_begin),
+ 			(unsigned long)(&__init_end));
+@@ -1040,13 +1041,28 @@ void free_initmem(void)
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long addr = (unsigned long)__start_rodata;
++	unsigned long start = (unsigned long)_stext, end;
++
++#ifdef CONFIG_HOTPLUG_CPU
++	/* It must still be possible to apply SMP alternatives. */
++	if (num_possible_cpus() > 1)
++		start = (unsigned long)_etext;
++#endif
++
++#ifdef CONFIG_KPROBES
++	start = (unsigned long)__start_rodata;
++#endif
++
++	end = (unsigned long)__end_rodata;
++	start = (start + PAGE_SIZE - 1) & PAGE_MASK;
++	end &= PAGE_MASK;
++	if (end <= start)
++		return;
+ 
+-	for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
+-		change_page_attr_addr(addr, 1, PAGE_KERNEL_RO);
++	change_page_attr_addr(start, (end - start) >> PAGE_SHIFT, PAGE_KERNEL_RO);
+ 
+-	printk ("Write protecting the kernel read-only data: %luk\n",
+-			(__end_rodata - __start_rodata) >> 10);
++	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
++	       (end - start) >> 10);
+ 
+ 	/*
+ 	 * change_page_attr_addr() requires a global_flush_tlb() call after it.
+@@ -1197,3 +1213,11 @@ int in_gate_area_no_task(unsigned long a
+ {
+ 	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
+ }
++
++#ifndef CONFIG_XEN
++void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
++{
++	return __alloc_bootmem_core(pgdat->bdata, size,
++			SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -215,13 +215,13 @@ void mm_pin_all(void)
+ 	preempt_enable();
+ }
+ 
+-void _arch_dup_mmap(struct mm_struct *mm)
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+ {
+ 	if (!mm->context.pinned)
+ 		mm_pin(mm);
+ }
+ 
+-void _arch_exit_mmap(struct mm_struct *mm)
++void arch_exit_mmap(struct mm_struct *mm)
+ {
+ 	struct task_struct *tsk = current;
+ 
+@@ -343,10 +343,11 @@ static void flush_kernel_map(void *arg)
+ 	struct page *pg;
+ 
+ 	/* When clflush is available always use it because it is
+-	   much cheaper than WBINVD */
+-	if (!cpu_has_clflush)
++	   much cheaper than WBINVD. Disable clflush for now because
++	   the high level code is not ready yet */
++	if (1 || !cpu_has_clflush)
+ 		asm volatile("wbinvd" ::: "memory");
+-	list_for_each_entry(pg, l, lru) {
++	else list_for_each_entry(pg, l, lru) {
+ 		void *adr = page_address(pg);
+ 		if (cpu_has_clflush)
+ 			cache_flush_page(adr);
+@@ -460,16 +461,24 @@ __change_page_attr(unsigned long address
+  */
+ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
+ {
+-	int err = 0; 
++	int err = 0, kernel_map = 0;
+ 	int i; 
+ 
++	if (address >= __START_KERNEL_map
++	    && address < __START_KERNEL_map + KERNEL_TEXT_SIZE) {
++		address = (unsigned long)__va(__pa(address));
++		kernel_map = 1;
++	}
++
+ 	down_write(&init_mm.mmap_sem);
+ 	for (i = 0; i < numpages; i++, address += PAGE_SIZE) {
+ 		unsigned long pfn = __pa(address) >> PAGE_SHIFT;
+ 
+-		err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
+-		if (err) 
+-			break; 
++		if (!kernel_map || pte_present(pfn_pte(0, prot))) {
++			err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
++			if (err)
++				break;
++		}
+ 		/* Handle kernel mapping too which aliases part of the
+ 		 * lowmem */
+ 		if (__pa(address) < KERNEL_TEXT_SIZE) {
+--- head-2010-01-18.orig/drivers/char/tpm/tpm_xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/char/tpm/tpm_xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -463,7 +463,7 @@ static int tpmif_connect(struct xenbus_d
+ 	tp->backend_id = domid;
+ 
+ 	err = bind_listening_port_to_irqhandler(
+-		domid, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
++		domid, tpmif_int, IRQF_SAMPLE_RANDOM, "tpmif", tp);
+ 	if (err <= 0) {
+ 		WPRINTK("bind_listening_port_to_irqhandler failed "
+ 			"(err=%d)\n", err);
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 10:54:10.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 10:56:57.000000000 +0100
+@@ -12,16 +12,15 @@
+ #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 <linux/msi.h>
++#include <linux/smp.h>
+ 
+ #include <xen/evtchn.h>
+ 
+ #include <asm/errno.h>
+ #include <asm/io.h>
+-#include <asm/smp.h>
+ 
+ #include "pci.h"
+ #include "msi.h"
+@@ -156,6 +155,7 @@ int register_msi_get_owner(int (*func)(s
+ 	get_owner = func;
+ 	return 0;
+ }
++EXPORT_SYMBOL(register_msi_get_owner);
+ 
+ int unregister_msi_get_owner(int (*func)(struct pci_dev *dev))
+ {
+@@ -164,6 +164,7 @@ int unregister_msi_get_owner(int (*func)
+ 	get_owner = NULL;
+ 	return 0;
+ }
++EXPORT_SYMBOL(unregister_msi_get_owner);
+ 
+ static int msi_get_dev_owner(struct pci_dev *dev)
+ {
+@@ -259,11 +260,6 @@ static int msi_map_vector(struct pci_dev
+ 		map_irq.pirq : evtchn_map_pirq(-1, map_irq.pirq));
+ }
+ 
+-static int msi_init(void)
+-{
+-	return 0;
+-}
+-
+ #ifdef CONFIG_PM
+ void pci_restore_msi_state(struct pci_dev *dev)
+ {
+@@ -392,21 +388,32 @@ static int msix_capability_init(struct p
+ }
+ 
+ /**
+- * pci_msi_supported - check whether MSI may be enabled on device
++ * pci_msi_check_device - check whether MSI may be enabled on a device
+  * @dev: pointer to the pci_dev data structure of MSI device function
++ * @nvec: how many MSIs have been requested ?
++ * @type: are we checking for MSI or MSI-X ?
+  *
+  * Look at global flags, the device itself, and its parent busses
+- * to return 0 if MSI are supported for the device.
++ * to determine if MSI/-X are supported for the device. If MSI/-X is
++ * supported return 0, else return an error code.
+  **/
+-static
+-int pci_msi_supported(struct pci_dev * dev)
++static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type)
+ {
+ 	struct pci_bus *bus;
++	int ret;
+ 
+ 	/* MSI must be globally enabled and supported by the device */
+ 	if (!pci_msi_enable || !dev || dev->no_msi)
+ 		return -EINVAL;
+ 
++	/*
++	 * You can't ask to have 0 or less MSIs configured.
++	 *  a) it's stupid ..
++	 *  b) the list manipulation code assumes nvec >= 1.
++	 */
++	if (nvec < 1)
++		return -ERANGE;
++
+ 	/* Any bridge which does NOT route MSI transactions from it's
+ 	 * secondary bus to it's primary bus must set NO_MSI flag on
+ 	 * the secondary pci_bus.
+@@ -417,6 +424,13 @@ int pci_msi_supported(struct pci_dev * d
+ 		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+ 			return -EINVAL;
+ 
++	ret = arch_msi_check_device(dev, nvec, type);
++	if (ret)
++		return ret;
++
++	if (!pci_find_capability(dev, type))
++		return -EINVAL;
++
+ 	return 0;
+ }
+ 
+@@ -433,15 +447,12 @@ int pci_msi_supported(struct pci_dev * d
+ extern int pci_frontend_enable_msi(struct pci_dev *dev);
+ int pci_enable_msi(struct pci_dev* dev)
+ {
+-	int pos, temp, status;
++	int temp, status;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	if (pci_msi_supported(dev) < 0)
+- 		return -EINVAL;
+-
+-	status = msi_init();
+-	if (status < 0)
+-		return status;
++	status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
++	if (status)
++ 		return status;
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+ 	if (!is_initial_xendomain())
+@@ -463,10 +474,6 @@ int pci_enable_msi(struct pci_dev* dev)
+ 
+ 	temp = dev->irq;
+ 
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+-	if (!pos)
+-		return -EINVAL;
+-
+ 	/* Check whether driver already requested for MSI-X irqs */
+ 	if (dev->msix_enabled) {
+ 		printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
+@@ -481,6 +488,7 @@ int pci_enable_msi(struct pci_dev* dev)
+ 
+ 	return status;
+ }
++EXPORT_SYMBOL(pci_enable_msi);
+ 
+ extern void pci_frontend_disable_msi(struct pci_dev* dev);
+ void pci_disable_msi(struct pci_dev* dev)
+@@ -488,12 +496,7 @@ void pci_disable_msi(struct pci_dev* dev
+ 	int pirq;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	if (!pci_msi_enable)
+-		return;
+-	if (!dev)
+-		return;
+-
+-	if (!dev->msi_enabled)
++	if (!pci_msi_enable || !dev || !dev->msi_enabled)
+ 		return;
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+@@ -516,6 +519,7 @@ void pci_disable_msi(struct pci_dev* dev
+ 	pci_intx(dev, 1);		/* enable intx */
+ 	dev->msi_enabled = 0;
+ }
++EXPORT_SYMBOL(pci_disable_msi);
+ 
+ /**
+  * pci_enable_msix - configure device's MSI-X capability structure
+@@ -541,7 +545,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ 	u16 control;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	if (!entries || pci_msi_supported(dev) < 0)
++	if (!entries)
+  		return -EINVAL;
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+@@ -580,14 +584,11 @@ int pci_enable_msix(struct pci_dev* dev,
+ 	}
+ #endif
+ 
+-	status = msi_init();
+-	if (status < 0)
++	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
++	if (status)
+ 		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)
+@@ -619,16 +620,12 @@ int pci_enable_msix(struct pci_dev* dev,
+ 
+ 	return status;
+ }
++EXPORT_SYMBOL(pci_enable_msix);
+ 
+ extern void pci_frontend_disable_msix(struct pci_dev* dev);
+ void pci_disable_msix(struct pci_dev* dev)
+ {
+-	if (!pci_msi_enable)
+-		return;
+-	if (!dev)
+-		return;
+-
+-	if (!dev->msix_enabled)
++	if (!pci_msi_enable || !dev || !dev->msix_enabled)
+ 		return;
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+@@ -659,6 +656,7 @@ void pci_disable_msix(struct pci_dev* de
+ 	pci_intx(dev, 1);		/* enable intx */
+ 	dev->msix_enabled = 0;
+ }
++EXPORT_SYMBOL(pci_disable_msix);
+ 
+ /**
+  * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state
+@@ -697,12 +695,57 @@ 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);
++void pci_msi_init_pci_dev(struct pci_dev *dev)
++{
++#ifndef CONFIG_XEN
++	INIT_LIST_HEAD(&dev->msi_list);
+ #endif
++}
++
++
++/* Arch hooks */
++
++int __attribute__ ((weak))
++arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
++{
++	return 0;
++}
++
++#ifndef CONFIG_XEN
++int __attribute__ ((weak))
++arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
++{
++	return 0;
++}
++
++int __attribute__ ((weak))
++arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
++{
++	struct msi_desc *entry;
++	int ret;
++
++	list_for_each_entry(entry, &dev->msi_list, list) {
++		ret = arch_setup_msi_irq(dev, entry);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
+ 
++void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
++{
++	return;
++}
++
++void __attribute__ ((weak))
++arch_teardown_msi_irqs(struct pci_dev *dev)
++{
++	struct msi_desc *entry;
++
++	list_for_each_entry(entry, &dev->msi_list, list) {
++		if (entry->irq != 0)
++			arch_teardown_msi_irq(entry->irq);
++	}
++}
++#endif
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:18:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2009-11-06 10:49:47.000000000 +0100
+@@ -244,7 +244,7 @@ static int setup_blkring(struct xenbus_d
+ 	info->ring_ref = err;
+ 
+ 	err = bind_listening_port_to_irqhandler(
+-		dev->otherend_id, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
++		dev->otherend_id, blkif_int, IRQF_SAMPLE_RANDOM, "blkif", info);
+ 	if (err <= 0) {
+ 		xenbus_dev_fatal(dev, err,
+ 				 "bind_listening_port_to_irqhandler");
+--- head-2010-01-18.orig/drivers/xen/char/mem.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/char/mem.c	2009-11-06 10:49:47.000000000 +0100
+@@ -18,7 +18,6 @@
+ #include <linux/raw.h>
+ #include <linux/tty.h>
+ #include <linux/capability.h>
+-#include <linux/smp_lock.h>
+ #include <linux/ptrace.h>
+ #include <linux/device.h>
+ #include <asm/pgalloc.h>
+--- head-2010-01-18.orig/drivers/xen/core/hypervisor_sysfs.c	2007-07-10 09:42:30.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/hypervisor_sysfs.c	2009-11-06 10:49:47.000000000 +0100
+@@ -50,7 +50,7 @@ static int __init hypervisor_subsys_init
+ 	if (!is_running_on_xen())
+ 		return -ENODEV;
+ 
+-	hypervisor_subsys.kset.kobj.ktype = &hyp_sysfs_kobj_type;
++	hypervisor_subsys.kobj.ktype = &hyp_sysfs_kobj_type;
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/machine_reboot.c	2008-09-01 12:07:31.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/machine_reboot.c	2009-11-23 10:38:09.000000000 +0100
+@@ -85,6 +85,8 @@ static void post_suspend(int suspend_can
+ #ifdef CONFIG_SMP
+ 		cpu_initialized_map = cpu_online_map;
+ #endif
++		for_each_possible_cpu(i)
++			setup_runstate_area(i);
+ 	}
+ 
+ 	shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT;
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:49:47.000000000 +0100
+@@ -160,13 +160,12 @@ static void xen_smp_intr_exit(unsigned i
+ 
+ void __cpuinit cpu_bringup(void)
+ {
++	cpu_init();
+ #ifdef __i386__
+-	cpu_set_gdt(current_thread_info()->cpu);
+-	secondary_cpu_init();
++	identify_secondary_cpu(cpu_data + smp_processor_id());
+ #else
+-	cpu_init();
+-#endif
+ 	identify_cpu(cpu_data + smp_processor_id());
++#endif
+ 	touch_softlockup_watchdog();
+ 	preempt_disable();
+ 	local_irq_enable();
+@@ -186,11 +185,6 @@ static void __cpuinit cpu_initialize_con
+ 	static DEFINE_SPINLOCK(ctxt_lock);
+ 
+ 	struct task_struct *idle = idle_task(cpu);
+-#ifdef __x86_64__
+-	struct desc_ptr *gdt_descr = &cpu_gdt_descr[cpu];
+-#else
+-	struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+-#endif
+ 
+ 	if (cpu_test_and_set(cpu, cpu_initialized_map))
+ 		return;
+@@ -213,11 +207,11 @@ static void __cpuinit cpu_initialize_con
+ 	smp_trap_init(ctxt.trap_ctxt);
+ 
+ 	ctxt.ldt_ents = 0;
+-
+-	ctxt.gdt_frames[0] = virt_to_mfn(gdt_descr->address);
+-	ctxt.gdt_ents      = gdt_descr->size / 8;
++	ctxt.gdt_ents = GDT_SIZE / 8;
+ 
+ #ifdef __i386__
++	ctxt.gdt_frames[0] = virt_to_mfn(get_cpu_gdt_table(cpu));
++
+ 	ctxt.user_regs.cs = __KERNEL_CS;
+ 	ctxt.user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs);
+ 
+@@ -230,7 +224,11 @@ static void __cpuinit cpu_initialize_con
+ 	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
+ 
+ 	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
++
++	ctxt.user_regs.fs = __KERNEL_PERCPU;
+ #else /* __x86_64__ */
++	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[cpu].address);
++
+ 	ctxt.user_regs.cs = __KERNEL_CS;
+ 	ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs);
+ 
+@@ -260,9 +258,8 @@ void __init smp_prepare_cpus(unsigned in
+ 	struct vcpu_get_physid cpu_id;
+ #ifdef __x86_64__
+ 	struct desc_ptr *gdt_descr;
+-#else
+-	struct Xgt_desc_struct *gdt_descr;
+ #endif
++	void *gdt_addr;
+ 
+ 	apicid = 0;
+ 	if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0)
+@@ -312,14 +309,12 @@ void __init smp_prepare_cpus(unsigned in
+ 		}
+ 		gdt_descr->size = GDT_SIZE;
+ 		memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
++		gdt_addr = (void *)gdt_descr->address;
+ #else
+-		if (unlikely(!init_gdt(cpu, idle)))
+-			continue;
+-		gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++		init_gdt(cpu);
++		gdt_addr = get_cpu_gdt_table(cpu);
+ #endif
+-		make_page_readonly(
+-			(void *)gdt_descr->address,
+-			XENFEAT_writable_descriptor_tables);
++		make_page_readonly(gdt_addr, XENFEAT_writable_descriptor_tables);
+ 
+ 		apicid = cpu;
+ 		if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0)
+@@ -334,6 +329,8 @@ void __init smp_prepare_cpus(unsigned in
+ 		cpu_pda(cpu)->pcurrent = idle;
+ 		cpu_pda(cpu)->cpunumber = cpu;
+ 		clear_tsk_thread_flag(idle, TIF_FORK);
++#else
++	 	per_cpu(current_task, cpu) = idle;
+ #endif
+ 
+ 		irq_ctx_init(cpu);
+@@ -358,8 +355,12 @@ void __init smp_prepare_cpus(unsigned in
+ #endif
+ }
+ 
+-void __devinit smp_prepare_boot_cpu(void)
++void __init smp_prepare_boot_cpu(void)
+ {
++#ifdef __i386__
++	init_gdt(smp_processor_id());
++	switch_to_new_gdt();
++#endif
+ 	prefill_possible_map();
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/xen_sysfs.c	2009-05-29 10:25:53.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/xen_sysfs.c	2009-11-06 10:49:47.000000000 +0100
+@@ -30,12 +30,12 @@ HYPERVISOR_ATTR_RO(type);
+ 
+ static int __init xen_sysfs_type_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++	return sysfs_create_file(&hypervisor_subsys.kobj, &type_attr.attr);
+ }
+ 
+ static void xen_sysfs_type_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++	sysfs_remove_file(&hypervisor_subsys.kobj, &type_attr.attr);
+ }
+ 
+ /* xen version attributes */
+@@ -91,13 +91,13 @@ static struct attribute_group version_gr
+ 
+ static int __init xen_sysfs_version_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++	return sysfs_create_group(&hypervisor_subsys.kobj,
+ 				  &version_group);
+ }
+ 
+ static void xen_sysfs_version_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group);
++	sysfs_remove_group(&hypervisor_subsys.kobj, &version_group);
+ }
+ 
+ /* UUID */
+@@ -126,12 +126,12 @@ HYPERVISOR_ATTR_RO(uuid);
+ 
+ static int __init xen_sysfs_uuid_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
++	return sysfs_create_file(&hypervisor_subsys.kobj, &uuid_attr.attr);
+ }
+ 
+ static void xen_sysfs_uuid_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
++	sysfs_remove_file(&hypervisor_subsys.kobj, &uuid_attr.attr);
+ }
+ 
+ /* xen compilation attributes */
+@@ -204,13 +204,13 @@ static struct attribute_group xen_compil
+ 
+ int __init static xen_compilation_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++	return sysfs_create_group(&hypervisor_subsys.kobj,
+ 				  &xen_compilation_group);
+ }
+ 
+ static void xen_compilation_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kset.kobj,
++	sysfs_remove_group(&hypervisor_subsys.kobj,
+ 			   &xen_compilation_group);
+ }
+ 
+@@ -325,13 +325,13 @@ static struct attribute_group xen_proper
+ 
+ static int __init xen_properties_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++	return sysfs_create_group(&hypervisor_subsys.kobj,
+ 				  &xen_properties_group);
+ }
+ 
+ static void xen_properties_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kset.kobj,
++	sysfs_remove_group(&hypervisor_subsys.kobj,
+ 			   &xen_properties_group);
+ }
+ 
+@@ -350,13 +350,13 @@ HYPERVISOR_ATTR_RO(vmcoreinfo);
+ 
+ static int __init xen_sysfs_vmcoreinfo_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kset.kobj,
++	return sysfs_create_file(&hypervisor_subsys.kobj,
+ 				 &vmcoreinfo_attr.attr);
+ }
+ 
+ static void xen_sysfs_vmcoreinfo_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kset.kobj, &vmcoreinfo_attr.attr);
++	sysfs_remove_file(&hypervisor_subsys.kobj, &vmcoreinfo_attr.attr);
+ }
+ 
+ #endif
+--- head-2010-01-18.orig/drivers/xen/netback/netback.c	2010-01-04 12:22:49.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/netback.c	2010-01-04 12:26:56.000000000 +0100
+@@ -198,7 +198,7 @@ static struct sk_buff *netbk_copy_skb(st
+ 		goto err;
+ 
+ 	skb_reserve(nskb, 16 + NET_IP_ALIGN);
+-	headlen = nskb->end - nskb->data;
++	headlen = skb_end_pointer(nskb) - nskb->data;
+ 	if (headlen > skb_headlen(skb))
+ 		headlen = skb_headlen(skb);
+ 	ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen);
+@@ -244,11 +244,15 @@ static struct sk_buff *netbk_copy_skb(st
+ 		len -= copy;
+ 	}
+ 
++#ifdef NET_SKBUFF_DATA_USES_OFFSET
++	offset = 0;
++#else
+ 	offset = nskb->data - skb->data;
++#endif
+ 
+-	nskb->h.raw = skb->h.raw + offset;
+-	nskb->nh.raw = skb->nh.raw + offset;
+-	nskb->mac.raw = skb->mac.raw + offset;
++	nskb->transport_header = skb->transport_header + offset;
++	nskb->network_header   = skb->network_header   + offset;
++	nskb->mac_header       = skb->mac_header       + offset;
+ 
+ 	return nskb;
+ 
+@@ -1678,7 +1682,7 @@ static int __init netback_init(void)
+ 	(void)bind_virq_to_irqhandler(VIRQ_DEBUG,
+ 				      0,
+ 				      netif_be_dbg,
+-				      SA_SHIRQ, 
++				      IRQF_SHARED,
+ 				      "net-be-dbg",
+ 				      &netif_be_dbg);
+ #endif
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:49:47.000000000 +0100
+@@ -513,7 +513,7 @@ static int setup_device(struct xenbus_de
+ 	memcpy(netdev->dev_addr, info->mac, ETH_ALEN);
+ 
+ 	err = bind_listening_port_to_irqhandler(
+-		dev->otherend_id, netif_int, SA_SAMPLE_RANDOM, netdev->name,
++		dev->otherend_id, netif_int, IRQF_SAMPLE_RANDOM, netdev->name,
+ 		netdev);
+ 	if (err < 0)
+ 		goto fail;
+--- head-2010-01-18.orig/drivers/xen/pciback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/xenbus.c	2009-11-06 10:49:47.000000000 +0100
+@@ -100,7 +100,7 @@ static int pciback_do_attach(struct pcib
+ 
+ 	err = bind_interdomain_evtchn_to_irqhandler(
+ 		pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
+-		SA_SAMPLE_RANDOM, "pciback", pdev);
++		IRQF_SAMPLE_RANDOM, "pciback", pdev);
+ 	if (err < 0) {
+ 		xenbus_dev_fatal(pdev->xdev, err,
+ 				 "Error binding event channel to IRQ");
+--- head-2010-01-18.orig/drivers/xen/pcifront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
+@@ -11,10 +11,6 @@
+ #include <xen/gnttab.h>
+ #include "pcifront.h"
+ 
+-#ifndef __init_refok
+-#define __init_refok
+-#endif
+-
+ #define INVALID_GRANT_REF (0)
+ #define INVALID_EVTCHN    (-1)
+ 
+@@ -95,7 +91,7 @@ static int pcifront_publish_info(struct 
+ 		goto out;
+ 
+ 	bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, 
+-		SA_SAMPLE_RANDOM, "pcifront", pdev); 
++		IRQF_SAMPLE_RANDOM, "pcifront", pdev);
+ 
+       do_publish:
+ 	err = xenbus_transaction_start(&trans);
+--- head-2010-01-18.orig/drivers/xen/scsifront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
+@@ -96,7 +96,7 @@ static int scsifront_alloc_ring(struct v
+ 
+ 	err = bind_listening_port_to_irqhandler(
+ 			dev->otherend_id, scsifront_intr,
+-			SA_SAMPLE_RANDOM, "scsifront", info);
++			IRQF_SAMPLE_RANDOM, "scsifront", info);
+ 
+ 	if (err <= 0) {
+ 		xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler");
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_fwd.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_fwd.c	2009-11-06 10:49:47.000000000 +0100
+@@ -308,7 +308,7 @@ static struct netback_accel *for_a_vnic(
+ 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);
++		&& arp_hdr(skb)->ar_op == ntohs(ARPOP_REPLY);
+ }
+ 
+ 
+@@ -392,12 +392,13 @@ void netback_accel_tx_packet(struct sk_b
+ 
+ 	BUG_ON(fwd_priv == NULL);
+ 
+-	if (is_broadcast_ether_addr(skb->mac.raw) && packet_is_arp_reply(skb)) {
++	if (is_broadcast_ether_addr(skb_mac_header(skb))
++	    && packet_is_arp_reply(skb)) {
+ 		/*
+ 		 * update our fast path forwarding to reflect this
+ 		 * gratuitous ARP
+ 		 */ 
+-		mac = skb->mac.raw+ETH_ALEN;
++		mac = skb_mac_header(skb)+ETH_ALEN;
+ 
+ 		DPRINTK("%s: found gratuitous ARP for " MAC_FMT "\n",
+ 			__FUNCTION__, MAC_ARG(mac));
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_solarflare.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_solarflare.c	2009-11-06 10:49:47.000000000 +0100
+@@ -113,7 +113,7 @@ bend_dl_tx_packet(struct efx_dl_device *
+ 	BUG_ON(port == NULL);
+ 
+ 	NETBACK_ACCEL_STATS_OP(global_stats.dl_tx_packets++);
+-	if (skb->mac.raw != NULL)
++	if (skb_mac_header_was_set(skb))
+ 		netback_accel_tx_packet(skb, port->fwd_priv);
+ 	else {
+ 		DPRINTK("Ignoring packet with missing mac address\n");
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_tso.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_tso.c	2009-11-06 10:49:47.000000000 +0100
+@@ -33,10 +33,9 @@
+ 
+ #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)
++#define ETH_HDR_LEN(skb)  skb_network_offset(skb)
++#define SKB_TCP_OFF(skb)  skb_transport_offset(skb)
++#define SKB_IP_OFF(skb)   skb_network_offset(skb)
+ 
+ /*
+  * Set a maximum number of buffers in each output packet to make life
+@@ -114,9 +113,8 @@ struct netfront_accel_tso_state {
+ 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));
++	EPRINTK_ON(ip_hdr(skb)->protocol != IPPROTO_TCP);
++	EPRINTK_ON((SKB_TCP_OFF(skb) + tcp_hdrlen(skb)) > skb_headlen(skb));
+ }
+ 
+ 
+@@ -129,17 +127,17 @@ static inline void tso_start(struct netf
+ 	 * 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.header_length = tcp_hdrlen(skb) + 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);
++	st->p.ip_id = htons(ip_hdr(skb)->id);
++	st->seqnum = ntohl(tcp_hdr(skb)->seq);
+ 
+-	EPRINTK_ON(skb->h.th->urg);
+-	EPRINTK_ON(skb->h.th->syn);
+-	EPRINTK_ON(skb->h.th->rst);
++	EPRINTK_ON(tcp_hdr(skb)->urg);
++	EPRINTK_ON(tcp_hdr(skb)->syn);
++	EPRINTK_ON(tcp_hdr(skb)->rst);
+ 
+ 	st->remaining_len = skb->len - st->p.header_length;
+ 
+@@ -258,8 +256,8 @@ int tso_start_new_packet(netfront_accel_
+ 		/* 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_th->fin = tcp_hdr(skb)->fin;
++		tsoh_th->psh = tcp_hdr(skb)->psh;
+ 	}
+ 
+ 	tsoh_iph->tot_len = htons(ip_length);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:17:54.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:18:26.000000000 +0100
+@@ -465,7 +465,7 @@ netfront_accel_enqueue_skb_multi(netfron
+ 
+ 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+-		*(u16*)(skb->h.raw + skb->csum_offset) = 0;
++		*(u16*)(skb->head + skb->csum_start + skb->csum_offset) = 0;
+ 	}
+ 
+ 	if (multi_post_start_new_buffer(vnic, &state)) {
+@@ -584,7 +584,7 @@ netfront_accel_enqueue_skb_single(netfro
+ 
+ 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+-		*(u16*)(skb->h.raw + skb->csum_offset) = 0;
++		*(u16*)(skb->head + skb->csum_start + skb->csum_offset) = 0;
+ 	}
+ 	NETFRONT_ACCEL_PKTBUFF_FOR_EACH_FRAGMENT
+ 		(skb, idx, frag_data, frag_len, {
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_xenbus.c	2008-02-20 09:32:49.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_xenbus.c	2009-11-06 10:49:47.000000000 +0100
+@@ -356,7 +356,7 @@ static int vnic_setup_domU_shared_state(
+ 	/* 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);
++		 IRQF_SAMPLE_RANDOM, "vnicctrl", vnic);
+ 	if (err < 0) {
+ 		EPRINTK("Couldn't bind msg event channel\n");
+ 		goto fail_msg_irq;
+@@ -367,7 +367,7 @@ static int vnic_setup_domU_shared_state(
+ 	/* 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);
++		 IRQF_SAMPLE_RANDOM, "vnicfront", vnic);
+ 	if (err < 0) {
+ 		EPRINTK("Couldn't bind net event channel\n");
+ 		goto fail_net_irq;
+--- head-2010-01-18.orig/drivers/xen/usbfront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
+@@ -111,7 +111,7 @@ static int setup_rings(struct xenbus_dev
+ 	info->conn_ring_ref = err;
+ 
+ 	err = bind_listening_port_to_irqhandler(
+-		dev->otherend_id, xenhcd_int, SA_SAMPLE_RANDOM, "usbif", info);
++		dev->otherend_id, xenhcd_int, IRQF_SAMPLE_RANDOM, "usbif", info);
+ 	if (err <= 0) {
+ 		xenbus_dev_fatal(dev, err,
+ 				 "bind_listening_port_to_irqhandler");
+--- head-2010-01-18.orig/fs/aio.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/fs/aio.c	2009-11-06 10:49:47.000000000 +0100
+@@ -38,7 +38,7 @@
+ 
+ #ifdef CONFIG_EPOLL
+ #include <linux/poll.h>
+-#include <linux/eventpoll.h>
++#include <linux/anon_inodes.h>
+ #endif
+ 
+ #if DEBUG > 1
+@@ -1287,7 +1287,7 @@ static const struct file_operations aioq
+ 
+ /* make_aio_fd:
+  *  Create a file descriptor that can be used to poll the event queue.
+- *  Based and piggybacked on the excellent epoll code.
++ *  Based on the excellent epoll code.
+  */
+ 
+ static int make_aio_fd(struct kioctx *ioctx)
+@@ -1296,7 +1296,8 @@ static int make_aio_fd(struct kioctx *io
+ 	struct inode *inode;
+ 	struct file *file;
+ 
+-	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
++	error = anon_inode_getfd(&fd, &inode, &file, "[aioq]",
++				 &aioq_fops, ioctx);
+ 	if (error)
+ 		return error;
+ 
+--- head-2010-01-18.orig/arch/x86/include/asm/boot.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/boot.h	2009-11-06 10:49:47.000000000 +0100
+@@ -16,7 +16,7 @@
+ 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
+ 
+ /* Minimum kernel alignment, as a power of two */
+-#ifdef CONFIG_X86_64
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+ #define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
+ #else
+ #define MIN_KERNEL_ALIGN_LG2	(PAGE_SHIFT + THREAD_ORDER)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -11,23 +11,24 @@
+ 
+ #include <asm/mmu.h>
+ 
+-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+-
+ struct Xgt_desc_struct {
+ 	unsigned short size;
+ 	unsigned long address __attribute__((packed));
+ 	unsigned short pad;
+ } __attribute__ ((packed));
+ 
+-extern struct Xgt_desc_struct idt_descr;
+-DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
+-extern struct Xgt_desc_struct early_gdt_descr;
++struct gdt_page
++{
++	struct desc_struct gdt[GDT_ENTRIES];
++} __attribute__((aligned(PAGE_SIZE)));
++DECLARE_PER_CPU(struct gdt_page, gdt_page);
+ 
+ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ {
+-	return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
++	return per_cpu(gdt_page, cpu).gdt;
+ }
+ 
++extern struct Xgt_desc_struct idt_descr;
+ extern struct desc_struct idt_table[];
+ extern void set_intr_gate(unsigned int irq, void * addr);
+ 
+@@ -55,53 +56,32 @@ static inline void pack_gate(__u32 *a, _
+ #define DESCTYPE_S	0x10	/* !system */
+ 
+ #ifndef CONFIG_XEN
+-#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
+-
+-#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+-#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
++#define load_TR_desc() native_load_tr_desc()
++#define load_gdt(dtr) native_load_gdt(dtr)
++#define load_idt(dtr) native_load_idt(dtr)
+ #define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+ #define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+ 
+-#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
+-#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
+-#define store_tr(tr) __asm__ ("str %0":"=m" (tr))
++#define store_gdt(dtr) native_store_gdt(dtr)
++#define store_idt(dtr) native_store_idt(dtr)
++#define store_tr(tr) (tr = native_store_tr())
+ #define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+-#endif
+ 
+-#if TLS_SIZE != 24
+-# error update this code.
+-#endif
+-
+-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
+-{
+-#define C(i) if (HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), \
+-					      *(u64 *)&t->tls_array[i]) \
+-		BUG()
+-	C(0); C(1); C(2);
+-#undef C
+-}
++#define load_TLS(t, cpu) native_load_tls(t, cpu)
++#define set_ldt native_set_ldt
+ 
+-#ifndef CONFIG_XEN
+ #define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+ #define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+ #define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+ 
+-static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
++static inline void write_dt_entry(struct desc_struct *dt,
++				  int entry, u32 entry_low, u32 entry_high)
+ {
+-	__u32 *lp = (__u32 *)((char *)dt + entry*8);
+-	*lp = entry_a;
+-	*(lp+1) = entry_b;
++	dt[entry].a = entry_low;
++	dt[entry].b = entry_high;
+ }
+-#define set_ldt native_set_ldt
+-#else
+-extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
+-extern int write_gdt_entry(void *gdt, int entry, __u32 entry_a, __u32 entry_b);
+-#define set_ldt xen_set_ldt
+-#endif
+ 
+-#ifndef CONFIG_XEN
+-static inline fastcall void native_set_ldt(const void *addr,
+-					   unsigned int entries)
++static inline void native_set_ldt(const void *addr, unsigned int entries)
+ {
+ 	if (likely(entries == 0))
+ 		__asm__ __volatile__("lldt %w0"::"q" (0));
+@@ -116,6 +96,65 @@ static inline fastcall void native_set_l
+ 		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ 	}
+ }
++
++
++static inline void native_load_tr_desc(void)
++{
++	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
++}
++
++static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
++{
++	asm volatile("lgdt %0"::"m" (*dtr));
++}
++
++static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
++{
++	asm volatile("lidt %0"::"m" (*dtr));
++}
++
++static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
++{
++	asm ("sgdt %0":"=m" (*dtr));
++}
++
++static inline void native_store_idt(struct Xgt_desc_struct *dtr)
++{
++	asm ("sidt %0":"=m" (*dtr));
++}
++
++static inline unsigned long native_store_tr(void)
++{
++	unsigned long tr;
++	asm ("str %0":"=r" (tr));
++	return tr;
++}
++
++static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
++{
++	unsigned int i;
++	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
++
++	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
++		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
++}
++#else
++#define load_TLS(t, cpu) xen_load_tls(t, cpu)
++#define set_ldt xen_set_ldt
++
++extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
++extern int write_gdt_entry(void *gdt, int entry, __u32 entry_a, __u32 entry_b);
++
++static inline void xen_load_tls(struct thread_struct *t, unsigned int cpu)
++{
++	unsigned int i;
++	struct desc_struct *gdt = get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN;
++
++	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
++		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
++						 *(u64 *)&t->tls_array[i]))
++			BUG();
++}
+ #endif
+ 
+ #ifndef CONFIG_X86_NO_IDT
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -19,10 +19,8 @@
+  * the start of the fixmap.
+  */
+ extern unsigned long __FIXADDR_TOP;
+-#ifdef CONFIG_COMPAT_VDSO
+-#define FIXADDR_USER_START	__fix_to_virt(FIX_VDSO)
+-#define FIXADDR_USER_END	__fix_to_virt(FIX_VDSO - 1)
+-#endif
++#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
++#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
+ 
+ #ifndef __ASSEMBLY__
+ #include <linux/kernel.h>
+@@ -85,6 +83,9 @@ enum fixed_addresses {
+ #ifdef CONFIG_PCI_MMCONFIG
+ 	FIX_PCIE_MCFG,
+ #endif
++#ifdef CONFIG_PARAVIRT
++	FIX_PARAVIRT_BOOTMAP,
++#endif
+ 	FIX_SHARED_INFO,
+ #define NR_FIX_ISAMAPS	256
+ 	FIX_ISAMAP_END,
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:49:47.000000000 +0100
+@@ -67,12 +67,18 @@ extern void FASTCALL(kunmap_high(struct 
+ 
+ void *kmap(struct page *page);
+ void kunmap(struct page *page);
++void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
+ void *kmap_atomic(struct page *page, enum km_type type);
+ void *kmap_atomic_pte(struct page *page, enum km_type type);
+ void kunmap_atomic(void *kvaddr, enum km_type type);
+ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+ struct page *kmap_atomic_to_page(void *ptr);
+ 
++#define kmap_atomic_pte(page, type) \
++	kmap_atomic_prot(page, type, \
++	                 test_bit(PG_pinned, &(page)->flags) \
++	                 ? PAGE_KERNEL_RO : kmap_prot)
++
+ #define flush_cache_kmaps()	do { } while (0)
+ 
+ void clear_highpage(struct page *);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:23:50.000000000 +0100
+@@ -69,6 +69,8 @@ extern start_info_t *xen_start_info;
+ #define is_initial_xendomain() 0
+ #endif
+ 
++struct vcpu_runstate_info *setup_runstate_area(unsigned int cpu);
++
+ /* arch/xen/kernel/evtchn.c */
+ /* Force a proper event-channel callback from Xen. */
+ void force_evtchn_callback(void);
+@@ -104,8 +106,8 @@ void xen_set_ldt(const void *ptr, unsign
+ #include <linux/cpumask.h>
+ void xen_tlb_flush_all(void);
+ void xen_invlpg_all(unsigned long ptr);
+-void xen_tlb_flush_mask(cpumask_t *mask);
+-void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr);
++void xen_tlb_flush_mask(const cpumask_t *mask);
++void xen_invlpg_mask(const cpumask_t *mask, unsigned long ptr);
+ #else
+ #define xen_tlb_flush_all xen_tlb_flush
+ #define xen_invlpg_all xen_invlpg
+@@ -156,7 +158,9 @@ static inline void arch_leave_lazy_mmu_m
+ 	xen_multicall_flush(false);
+ }
+ 
+-#ifndef arch_use_lazy_mmu_mode
++#if defined(CONFIG_X86_32)
++#define arch_use_lazy_mmu_mode() unlikely(x86_read_percpu(xen_lazy_mmu))
++#elif !defined(arch_use_lazy_mmu_mode)
+ #define arch_use_lazy_mmu_mode() unlikely(__get_cpu_var(xen_lazy_mmu))
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -11,6 +11,40 @@
+ #define _ASM_IRQFLAGS_H
+ 
+ #ifndef __ASSEMBLY__
++#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask)
++
++#define xen_restore_fl(f)					\
++do {								\
++	vcpu_info_t *_vcpu;					\
++	barrier();						\
++	_vcpu = current_vcpu_info();				\
++	if ((_vcpu->evtchn_upcall_mask = (f)) == 0) {		\
++		barrier(); /* unmask then check (avoid races) */\
++		if (unlikely(_vcpu->evtchn_upcall_pending))	\
++			force_evtchn_callback();		\
++	}							\
++} while (0)
++
++#define xen_irq_disable()					\
++do {								\
++	current_vcpu_info()->evtchn_upcall_mask = 1;		\
++	barrier();						\
++} while (0)
++
++#define xen_irq_enable()					\
++do {								\
++	vcpu_info_t *_vcpu;					\
++	barrier();						\
++	_vcpu = current_vcpu_info();				\
++	_vcpu->evtchn_upcall_mask = 0;				\
++	barrier(); /* unmask then check (avoid races) */	\
++	if (unlikely(_vcpu->evtchn_upcall_pending))		\
++		force_evtchn_callback();			\
++} while (0)
++
++void xen_safe_halt(void);
++
++void xen_halt(void);
+ 
+ /* 
+  * The use of 'barrier' in the following reflects their use as local-lock
+@@ -20,48 +54,31 @@
+  * includes these barriers, for example.
+  */
+ 
+-#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask)
++#define __raw_local_save_flags() xen_save_fl()
+ 
+-#define raw_local_irq_restore(x)					\
+-do {									\
+-	vcpu_info_t *_vcpu;						\
+-	barrier();							\
+-	_vcpu = current_vcpu_info();					\
+-	if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {			\
+-		barrier(); /* unmask then check (avoid races) */	\
+-		if (unlikely(_vcpu->evtchn_upcall_pending))		\
+-			force_evtchn_callback();			\
+-	}								\
+-} while (0)
++#define raw_local_irq_restore(flags) xen_restore_fl(flags)
+ 
+-#define raw_local_irq_disable()						\
+-do {									\
+-	current_vcpu_info()->evtchn_upcall_mask = 1;			\
+-	barrier();							\
+-} while (0)
++#define raw_local_irq_disable()	xen_irq_disable()
+ 
+-#define raw_local_irq_enable()						\
+-do {									\
+-	vcpu_info_t *_vcpu;						\
+-	barrier();							\
+-	_vcpu = current_vcpu_info();					\
+-	_vcpu->evtchn_upcall_mask = 0;					\
+-	barrier(); /* unmask then check (avoid races) */		\
+-	if (unlikely(_vcpu->evtchn_upcall_pending))			\
+-		force_evtchn_callback();				\
+-} while (0)
++#define raw_local_irq_enable() xen_irq_enable()
+ 
+ /*
+  * Used in the idle loop; sti takes one instruction cycle
+  * to complete:
+  */
+-void raw_safe_halt(void);
++static inline void raw_safe_halt(void)
++{
++	xen_safe_halt();
++}
+ 
+ /*
+  * Used when interrupts are already enabled or to
+  * shutdown the processor:
+  */
+-void halt(void);
++static inline void halt(void)
++{
++	xen_halt();
++}
+ 
+ /*
+  * For spinlocks, etc:
+@@ -106,7 +123,7 @@ sysexit_scrit:	/**** START OF SYSEXIT CR
+ 14:	__DISABLE_INTERRUPTS						; \
+ 	TRACE_IRQS_OFF							; \
+ sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+-	mov  $__KERNEL_PDA, %ecx					; \
++	mov  $__KERNEL_PERCPU, %ecx					; \
+ 	push %esp							; \
+ 	mov  %ecx, %fs							; \
+ 	call evtchn_do_upcall						; \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -6,6 +6,20 @@
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+ 
++void arch_exit_mmap(struct mm_struct *mm);
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
++
++void mm_pin(struct mm_struct *mm);
++void mm_unpin(struct mm_struct *mm);
++void mm_pin_all(void);
++
++static inline void xen_activate_mm(struct mm_struct *prev,
++				   struct mm_struct *next)
++{
++	if (!test_bit(PG_pinned, &virt_to_page(next->pgd)->flags))
++		mm_pin(next);
++}
++
+ /*
+  * Used for LDT copy/destruction.
+  */
+@@ -37,10 +51,6 @@ static inline void __prepare_arch_switch
+ 		: : "r" (0) );
+ }
+ 
+-extern void mm_pin(struct mm_struct *mm);
+-extern void mm_unpin(struct mm_struct *mm);
+-void mm_pin_all(void);
+-
+ static inline void switch_mm(struct mm_struct *prev,
+ 			     struct mm_struct *next,
+ 			     struct task_struct *tsk)
+@@ -97,11 +107,10 @@ static inline void switch_mm(struct mm_s
+ #define deactivate_mm(tsk, mm)			\
+ 	asm("movl %0,%%gs": :"r" (0));
+ 
+-static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+-{
+-	if (!test_bit(PG_pinned, &virt_to_page(next->pgd)->flags))
+-		mm_pin(next);
+-	switch_mm(prev, next, NULL);
+-}
++#define activate_mm(prev, next)				\
++	do {						\
++		xen_activate_mm(prev, next);		\
++		switch_mm((prev),(next),NULL);		\
++	} while(0)
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -1,7 +1,6 @@
+ #ifndef _I386_PGALLOC_H
+ #define _I386_PGALLOC_H
+ 
+-#include <asm/fixmap.h>
+ #include <linux/threads.h>
+ #include <linux/mm.h>		/* for struct page */
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+@@ -69,6 +68,4 @@ do {									\
+ #define pud_populate(mm, pmd, pte)	BUG()
+ #endif
+ 
+-#define check_pgt_cache()	do { } while (0)
+-
+ #endif /* _I386_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:49:47.000000000 +0100
+@@ -52,32 +52,40 @@ static inline int pte_exec_kernel(pte_t 
+  * value and then use set_pte to update it.  -ben
+  */
+ 
+-static inline void set_pte(pte_t *ptep, pte_t pte)
++static inline void xen_set_pte(pte_t *ptep, pte_t pte)
+ {
+ 	ptep->pte_high = pte.pte_high;
+ 	smp_wmb();
+ 	ptep->pte_low = pte.pte_low;
+ }
+-#define set_pte_atomic(pteptr,pteval) \
+-		set_64bit((unsigned long long *)(pteptr),__pte_val(pteval))
+ 
+-#define set_pte_at(_mm,addr,ptep,pteval) do {				\
+-	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
+-	    HYPERVISOR_update_va_mapping((addr), (pteval), 0))		\
+-		set_pte((ptep), (pteval));				\
+-} while (0)
+-
+-#define set_pmd(pmdptr,pmdval)				\
+-		xen_l2_entry_update((pmdptr), (pmdval))
+-#define set_pud(pudptr,pudval) \
+-		xen_l3_entry_update((pudptr), (pudval))
++static inline void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
++				  pte_t *ptep , pte_t pte)
++{
++	if ((mm != current->mm && mm != &init_mm) ||
++	    HYPERVISOR_update_va_mapping(addr, pte, 0))
++		xen_set_pte(ptep, pte);
++}
++
++static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
++{
++	set_64bit((unsigned long long *)(ptep),__pte_val(pte));
++}
++static inline void xen_set_pmd(pmd_t *pmdp, pmd_t pmd)
++{
++	xen_l2_entry_update(pmdp, pmd);
++}
++static inline void xen_set_pud(pud_t *pudp, pud_t pud)
++{
++	xen_l3_entry_update(pudp, pud);
++}
+ 
+ /*
+  * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+  * entry, so clear the bottom half first and enforce ordering with a compiler
+  * barrier.
+  */
+-static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ 	if ((mm != current->mm && mm != &init_mm)
+ 	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+@@ -87,7 +95,18 @@ static inline void pte_clear(struct mm_s
+ 	}
+ }
+ 
+-#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
++static inline void xen_pmd_clear(pmd_t *pmd)
++{
++	xen_l2_entry_update(pmd, __pmd(0));
++}
++
++#define set_pte(ptep, pte)			xen_set_pte(ptep, pte)
++#define set_pte_at(mm, addr, ptep, pte)		xen_set_pte_at(mm, addr, ptep, pte)
++#define set_pte_atomic(ptep, pte)		xen_set_pte_atomic(ptep, pte)
++#define set_pmd(pmdp, pmd)			xen_set_pmd(pmdp, pmd)
++#define set_pud(pudp, pud)			xen_set_pud(pudp, pud)
++#define pte_clear(mm, addr, ptep)		xen_pte_clear(mm, addr, ptep)
++#define pmd_clear(pmd)				xen_pmd_clear(pmd)
+ 
+ /*
+  * Pentium-II erratum A13: in PAE mode we explicitly have to flush
+@@ -108,7 +127,8 @@ static inline void pud_clear (pud_t * pu
+ #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+ 			pmd_index(address))
+ 
+-static inline pte_t raw_ptep_get_and_clear(pte_t *ptep, pte_t res)
++#ifdef CONFIG_SMP
++static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+ 	uint64_t val = __pte_val(res);
+ 	if (__cmpxchg64(ptep, val, 0) != val) {
+@@ -119,6 +139,9 @@ static inline pte_t raw_ptep_get_and_cle
+ 	}
+ 	return res;
+ }
++#else
++#define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
++#endif
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+ #define ptep_clear_flush(vma, addr, ptep)			\
+@@ -165,13 +188,13 @@ extern unsigned long long __supported_pt
+ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+ {
+ 	return __pte((((unsigned long long)page_nr << PAGE_SHIFT) |
+-			pgprot_val(pgprot)) & __supported_pte_mask);
++		      pgprot_val(pgprot)) & __supported_pte_mask);
+ }
+ 
+ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+ {
+ 	return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) |
+-			pgprot_val(pgprot)) & __supported_pte_mask);
++		      pgprot_val(pgprot)) & __supported_pte_mask);
+ }
+ 
+ /*
+@@ -191,6 +214,4 @@ static inline pmd_t pfn_pmd(unsigned lon
+ 
+ #define __pmd_free_tlb(tlb, x)		do { } while (0)
+ 
+-void vmalloc_sync_all(void);
+-
+ #endif /* _I386_PGTABLE_3LEVEL_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2009-11-06 10:49:47.000000000 +0100
+@@ -1,7 +1,7 @@
+ #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
+ #define _I386_PGTABLE_3LEVEL_DEFS_H
+ 
+-#define HAVE_SHARED_KERNEL_PMD 0
++#define SHARED_KERNEL_PMD	0
+ 
+ /*
+  * PGDIR_SHIFT determines what a top-level page table entry can map
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -24,11 +24,11 @@
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
++#include <linux/sched.h>
+ 
+ /* Is this pagetable pinned? */
+ #define PG_pinned	PG_arch_1
+ 
+-struct mm_struct;
+ struct vm_area_struct;
+ 
+ /*
+@@ -38,17 +38,16 @@ struct vm_area_struct;
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ extern unsigned long empty_zero_page[1024];
+ extern pgd_t *swapper_pg_dir;
+-extern struct kmem_cache *pgd_cache;
+ extern struct kmem_cache *pmd_cache;
+ extern spinlock_t pgd_lock;
+ extern struct page *pgd_list;
++void check_pgt_cache(void);
+ 
+ void pmd_ctor(void *, struct kmem_cache *, unsigned long);
+-void pgd_ctor(void *, struct kmem_cache *, unsigned long);
+-void pgd_dtor(void *, struct kmem_cache *, unsigned long);
+ void pgtable_cache_init(void);
+ void paging_init(void);
+ 
++
+ /*
+  * The Linux x86 paging architecture is 'compile-time dual-mode', it
+  * implements both the traditional 2-level x86 page tables and the
+@@ -165,6 +164,7 @@ void paging_init(void);
+ 
+ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
++#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+ #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD)
+ #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+@@ -172,6 +172,7 @@ extern unsigned long long __PAGE_KERNEL,
+ #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
+ #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX)
+ #define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
+ #define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
+ #define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+@@ -275,7 +276,13 @@ static inline pte_t pte_mkhuge(pte_t pte
+  */
+ #define pte_update(mm, addr, ptep)		do { } while (0)
+ #define pte_update_defer(mm, addr, ptep)	do { } while (0)
+-#define paravirt_map_pt_hook(slot, va, pfn)	do { } while (0)
++
++/* local pte updates need not use xchg for locking */
++static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
++{
++	xen_set_pte(ptep, __pte(0));
++	return res;
++}
+ 
+ /*
+  * We only update the dirty/accessed state if we set
+@@ -286,17 +293,34 @@ static inline pte_t pte_mkhuge(pte_t pte
+  */
+ #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ #define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-do {									\
+-	if (dirty)							\
++({									\
++	int __changed = !pte_same(*(ptep), entry);			\
++	if (__changed && (dirty))					\
+ 		ptep_establish(vma, address, ptep, entry);		\
+-} while (0)
++	__changed;							\
++})
+ 
+-/*
+- * We don't actually have these, but we want to advertise them so that
+- * we can encompass the flush here.
+- */
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++#define ptep_test_and_clear_dirty(vma, addr, ptep) ({			\
++	int __ret = 0;							\
++	if (pte_dirty(*(ptep)))						\
++		__ret = test_and_clear_bit(_PAGE_BIT_DIRTY,		\
++						&(ptep)->pte_low);	\
++	if (__ret)							\
++		pte_update((vma)->vm_mm, addr, ptep);			\
++	__ret;								\
++})
++
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++#define ptep_test_and_clear_young(vma, addr, ptep) ({			\
++	int __ret = 0;							\
++	if (pte_young(*(ptep)))						\
++		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
++						&(ptep)->pte_low);	\
++	if (__ret)							\
++		pte_update((vma)->vm_mm, addr, ptep);			\
++	__ret;								\
++})
+ 
+ /*
+  * Rules for using ptep_establish: the pte MUST be a user pte, and
+@@ -323,7 +347,7 @@ do {									\
+ 	int __dirty = pte_dirty(__pte);					\
+ 	__pte = pte_mkclean(__pte);					\
+ 	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
+-		ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
++		(void)ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
+ 	else if (__dirty)						\
+ 		(ptep)->pte_low = __pte.pte_low;			\
+ 	__dirty;							\
+@@ -336,7 +360,7 @@ do {									\
+ 	int __young = pte_young(__pte);					\
+ 	__pte = pte_mkold(__pte);					\
+ 	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
+-		ptep_set_access_flags(vma, address, ptep, __pte, __young); \
++		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+ 	else if (__young)						\
+ 		(ptep)->pte_low = __pte.pte_low;			\
+ 	__young;							\
+@@ -349,7 +373,7 @@ static inline pte_t ptep_get_and_clear(s
+ 	if (!pte_none(pte)
+ 	    && (mm != &init_mm
+ 	        || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))) {
+-		pte = raw_ptep_get_and_clear(ptep, pte);
++		pte = xen_ptep_get_and_clear(ptep, pte);
+ 		pte_update(mm, addr, ptep);
+ 	}
+ 	return pte;
+@@ -491,24 +515,10 @@ extern pte_t *lookup_address(unsigned lo
+ #endif
+ 
+ #if defined(CONFIG_HIGHPTE)
+-#define pte_offset_map(dir, address)				\
+-({								\
+-	pte_t *__ptep;						\
+-	unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;		\
+-	__ptep = (pte_t *)kmap_atomic_pte(pfn_to_page(pfn),KM_PTE0); \
+-	paravirt_map_pt_hook(KM_PTE0,__ptep, pfn);		\
+-	__ptep = __ptep + pte_index(address);			\
+-	__ptep;							\
+-})
+-#define pte_offset_map_nested(dir, address)			\
+-({								\
+-	pte_t *__ptep;						\
+-	unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;		\
+-	__ptep = (pte_t *)kmap_atomic_pte(pfn_to_page(pfn),KM_PTE1); \
+-	paravirt_map_pt_hook(KM_PTE1,__ptep, pfn);		\
+-	__ptep = __ptep + pte_index(address);			\
+-	__ptep;							\
+-})
++#define pte_offset_map(dir, address) \
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
++#define pte_offset_map_nested(dir, address) \
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
+ #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+ #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
+ #else
+@@ -597,10 +607,6 @@ int xen_change_pte_range(struct mm_struc
+ #define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
+ 
+-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
+-#define GET_IOSPACE(pfn)		0
+-#define GET_PFN(pfn)			(pfn)
+-
+ #include <asm-generic/pgtable.h>
+ 
+ #endif /* _I386_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -21,6 +21,7 @@
+ #include <asm/percpu.h>
+ #include <linux/cpumask.h>
+ #include <linux/init.h>
++#include <asm/processor-flags.h>
+ #include <xen/interface/physdev.h>
+ 
+ /* flag for disabling the tsc */
+@@ -118,7 +119,8 @@ extern char ignore_fpu_irq;
+ 
+ void __init cpu_detect(struct cpuinfo_x86 *c);
+ 
+-extern void identify_cpu(struct cpuinfo_x86 *);
++extern void identify_boot_cpu(void);
++extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+@@ -129,29 +131,8 @@ extern void detect_ht(struct cpuinfo_x86
+ static inline void detect_ht(struct cpuinfo_x86 *c) {}
+ #endif
+ 
+-/*
+- * EFLAGS bits
+- */
+-#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
+-#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
+-#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
+-#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
+-#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
+-#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
+-#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
+-#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
+-#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
+-#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
+-#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
+-#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
+-#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
+-#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
+-#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
+-#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
+-#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
+-
+-static inline fastcall void xen_cpuid(unsigned int *eax, unsigned int *ebx,
+-				      unsigned int *ecx, unsigned int *edx)
++static inline void xen_cpuid(unsigned int *eax, unsigned int *ebx,
++			     unsigned int *ecx, unsigned int *edx)
+ {
+ 	/* ecx is often an input as well as an output. */
+ 	__asm__(XEN_CPUID
+@@ -165,21 +146,6 @@ static inline fastcall void xen_cpuid(un
+ #define load_cr3(pgdir) write_cr3(__pa(pgdir))
+ 
+ /*
+- * Intel CPU features in CR4
+- */
+-#define X86_CR4_VME		0x0001	/* enable vm86 extensions */
+-#define X86_CR4_PVI		0x0002	/* virtual interrupts flag enable */
+-#define X86_CR4_TSD		0x0004	/* disable time stamp at ipl 3 */
+-#define X86_CR4_DE		0x0008	/* enable debugging extensions */
+-#define X86_CR4_PSE		0x0010	/* enable page size extensions */
+-#define X86_CR4_PAE		0x0020	/* enable physical address extensions */
+-#define X86_CR4_MCE		0x0040	/* Machine check enable */
+-#define X86_CR4_PGE		0x0080	/* enable global pages */
+-#define X86_CR4_PCE		0x0100	/* enable performance counters at ipl 3 */
+-#define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
+-#define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
+-
+-/*
+  * Save the cr4 feature set we're using (ie
+  * Pentium 4MB enable and PPro Global page
+  * enable), so that any CPU's that boot up
+@@ -206,26 +172,6 @@ static inline void clear_in_cr4 (unsigne
+ }
+ 
+ /*
+- *      NSC/Cyrix CPU configuration register indexes
+- */
+-
+-#define CX86_PCR0 0x20
+-#define CX86_GCR  0xb8
+-#define CX86_CCR0 0xc0
+-#define CX86_CCR1 0xc1
+-#define CX86_CCR2 0xc2
+-#define CX86_CCR3 0xc3
+-#define CX86_CCR4 0xe8
+-#define CX86_CCR5 0xe9
+-#define CX86_CCR6 0xea
+-#define CX86_CCR7 0xeb
+-#define CX86_PCR1 0xf0
+-#define CX86_DIR0 0xfe
+-#define CX86_DIR1 0xff
+-#define CX86_ARR_BASE 0xc4
+-#define CX86_RCR_BASE 0xdc
+-
+-/*
+  *      NSC/Cyrix CPU indexed register access macros
+  */
+ 
+@@ -351,7 +297,8 @@ typedef struct {
+ struct thread_struct;
+ 
+ #ifndef CONFIG_X86_NO_TSS
+-struct tss_struct {
++/* This is the TSS defined by the hardware. */
++struct i386_hw_tss {
+ 	unsigned short	back_link,__blh;
+ 	unsigned long	esp0;
+ 	unsigned short	ss0,__ss0h;
+@@ -375,6 +322,11 @@ struct tss_struct {
+ 	unsigned short	gs, __gsh;
+ 	unsigned short	ldt, __ldth;
+ 	unsigned short	trace, io_bitmap_base;
++} __attribute__((packed));
++
++struct tss_struct {
++	struct i386_hw_tss x86_tss;
++
+ 	/*
+ 	 * The extra 1 is there because the CPU will access an
+ 	 * additional byte beyond the end of the IO permission
+@@ -428,10 +380,11 @@ struct thread_struct {
+ };
+ 
+ #define INIT_THREAD  {							\
++	.esp0 = sizeof(init_stack) + (long)&init_stack,			\
+ 	.vm86_info = NULL,						\
+ 	.sysenter_cs = __KERNEL_CS,					\
+ 	.io_bitmap_ptr = NULL,						\
+-	.fs = __KERNEL_PDA,						\
++	.fs = __KERNEL_PERCPU,						\
+ }
+ 
+ /*
+@@ -441,10 +394,12 @@ struct thread_struct {
+  * be within the limit.
+  */
+ #define INIT_TSS  {							\
+-	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
+-	.ss0		= __KERNEL_DS,					\
+-	.ss1		= __KERNEL_CS,					\
+-	.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,			\
++	.x86_tss = {							\
++		.esp0		= sizeof(init_stack) + (long)&init_stack, \
++		.ss0		= __KERNEL_DS,				\
++		.ss1		= __KERNEL_CS,				\
++		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
++	 },								\
+ 	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
+ }
+ 
+@@ -551,38 +506,33 @@ static inline void rep_nop(void)
+ 
+ #define cpu_relax()	rep_nop()
+ 
+-#define paravirt_enabled() 0
+-#define __cpuid xen_cpuid
+-
+ #ifndef CONFIG_X86_NO_TSS
+-static inline void __load_esp0(struct tss_struct *tss, struct thread_struct *thread)
++static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+ {
+-	tss->esp0 = thread->esp0;
++	tss->x86_tss.esp0 = thread->esp0;
+ 	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+-	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+-		tss->ss1 = thread->sysenter_cs;
++	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
++		tss->x86_tss.ss1 = thread->sysenter_cs;
+ 		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+ 	}
+ }
+-#define load_esp0(tss, thread) \
+-	__load_esp0(tss, thread)
+ #else
+-#define load_esp0(tss, thread) do { \
++#define xen_load_esp0(tss, thread) do { \
+ 	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)) \
+ 		BUG(); \
+ } while (0)
+ #endif
+ 
+ 
+-/*
+- * These special macros can be used to get or set a debugging register
+- */
+-#define get_debugreg(var, register)				\
+-		(var) = HYPERVISOR_get_debugreg(register)
+-#define set_debugreg(value, register)				\
+-		WARN_ON(HYPERVISOR_set_debugreg(register, value))
++static inline unsigned long xen_get_debugreg(int regno)
++{
++	return HYPERVISOR_get_debugreg(regno);
++}
+ 
+-#define set_iopl_mask xen_set_iopl_mask
++static inline void xen_set_debugreg(int regno, unsigned long value)
++{
++	WARN_ON(HYPERVISOR_set_debugreg(regno, value));
++}
+ 
+ /*
+  * Set IOPL bits in EFLAGS from given mask
+@@ -597,6 +547,21 @@ static inline void xen_set_iopl_mask(uns
+ }
+ 
+ 
++#define paravirt_enabled() 0
++#define __cpuid xen_cpuid
++
++#define load_esp0 xen_load_esp0
++
++/*
++ * These special macros can be used to get or set a debugging register
++ */
++#define get_debugreg(var, register)				\
++	(var) = xen_get_debugreg(register)
++#define set_debugreg(value, register)				\
++	xen_set_debugreg(register, value)
++
++#define set_iopl_mask xen_set_iopl_mask
++
+ /*
+  * Generic CPUID function
+  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+@@ -749,8 +714,14 @@ extern unsigned long boot_option_idle_ov
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+ 
+-extern int init_gdt(int cpu, struct task_struct *idle);
++/* Defined in head.S */
++extern struct Xgt_desc_struct early_gdt_descr;
++
+ extern void cpu_set_gdt(int);
+-extern void secondary_cpu_init(void);
++extern void switch_to_new_gdt(void);
++extern void cpu_init(void);
++extern void init_gdt(int cpu);
++
++extern int force_mwait;
+ 
+ #endif /* __ASM_I386_PROCESSOR_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -8,19 +8,15 @@
+ #include <linux/kernel.h>
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
+-#include <asm/pda.h>
+ #endif
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-#ifndef __ASSEMBLY__
+-#include <asm/fixmap.h>
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(__ASSEMBLY__)
+ #include <asm/bitops.h>
+ #include <asm/mpspec.h>
++#include <asm/apic.h>
+ #ifdef CONFIG_X86_IO_APIC
+ #include <asm/io_apic.h>
+ #endif
+-#include <asm/apic.h>
+-#endif
+ #endif
+ 
+ #define BAD_APICID 0xFFu
+@@ -52,9 +48,76 @@ extern void cpu_exit_clear(void);
+ extern void cpu_uninit(void);
+ #endif
+ 
+-#ifndef CONFIG_PARAVIRT
++#ifndef CONFIG_XEN
++struct smp_ops
++{
++	void (*smp_prepare_boot_cpu)(void);
++	void (*smp_prepare_cpus)(unsigned max_cpus);
++	int (*cpu_up)(unsigned cpu);
++	void (*smp_cpus_done)(unsigned max_cpus);
++
++	void (*smp_send_stop)(void);
++	void (*smp_send_reschedule)(int cpu);
++	int (*smp_call_function_mask)(cpumask_t mask,
++				      void (*func)(void *info), void *info,
++				      int wait);
++};
++
++extern struct smp_ops smp_ops;
++
++static inline void smp_prepare_boot_cpu(void)
++{
++	smp_ops.smp_prepare_boot_cpu();
++}
++static inline void smp_prepare_cpus(unsigned int max_cpus)
++{
++	smp_ops.smp_prepare_cpus(max_cpus);
++}
++static inline int __cpu_up(unsigned int cpu)
++{
++	return smp_ops.cpu_up(cpu);
++}
++static inline void smp_cpus_done(unsigned int max_cpus)
++{
++	smp_ops.smp_cpus_done(max_cpus);
++}
++
++static inline void smp_send_stop(void)
++{
++	smp_ops.smp_send_stop();
++}
++static inline void smp_send_reschedule(int cpu)
++{
++	smp_ops.smp_send_reschedule(cpu);
++}
++static inline int smp_call_function_mask(cpumask_t mask,
++					 void (*func) (void *info), void *info,
++					 int wait)
++{
++	return smp_ops.smp_call_function_mask(mask, func, info, wait);
++}
++
++void native_smp_prepare_boot_cpu(void);
++void native_smp_prepare_cpus(unsigned int max_cpus);
++int native_cpu_up(unsigned int cpunum);
++void native_smp_cpus_done(unsigned int max_cpus);
++
+ #define startup_ipi_hook(phys_apicid, start_eip, start_esp) 		\
+ do { } while (0)
++
++#else
++
++
++void xen_smp_send_stop(void);
++void xen_smp_send_reschedule(int cpu);
++int xen_smp_call_function_mask(cpumask_t mask,
++			       void (*func) (void *info), void *info,
++			       int wait);
++
++#define smp_send_stop		xen_smp_send_stop
++#define smp_send_reschedule	xen_smp_send_reschedule
++#define smp_call_function_mask	xen_smp_call_function_mask
++
+ #endif
+ 
+ /*
+@@ -62,7 +125,8 @@ do { } while (0)
+  * from the initial startup. We map APIC_BASE very early in page_setup(),
+  * so this is correct in the x86 case.
+  */
+-#define raw_smp_processor_id() (read_pda(cpu_number))
++DECLARE_PER_CPU(int, cpu_number);
++#define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+ 
+ extern cpumask_t cpu_possible_map;
+ #define cpu_callin_map cpu_possible_map
+@@ -73,20 +137,6 @@ static inline int num_booting_cpus(void)
+ 	return cpus_weight(cpu_possible_map);
+ }
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-
+-#ifdef APIC_DEFINITION
+-extern int hard_smp_processor_id(void);
+-#else
+-#include <mach_apicdef.h>
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
+-}
+-#endif
+-#endif
+-
+ #define safe_smp_processor_id() smp_processor_id()
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+@@ -102,10 +152,31 @@ extern unsigned int num_processors;
+ 
+ #define NO_PROC_ID		0xFF		/* No processor magic marker */
+ 
+-#endif
++#endif /* CONFIG_SMP */
+ 
+ #ifndef __ASSEMBLY__
+ 
++#ifdef CONFIG_X86_LOCAL_APIC
++
++#ifdef APIC_DEFINITION
++extern int hard_smp_processor_id(void);
++#else
++#include <mach_apicdef.h>
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
++}
++#endif /* APIC_DEFINITION */
++
++#else /* CONFIG_X86_LOCAL_APIC */
++
++#ifndef CONFIG_SMP
++#define hard_smp_processor_id()		0
++#endif
++
++#endif /* CONFIG_X86_LOCAL_APIC */
++
+ extern u8 apicid_2_node[];
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -4,7 +4,7 @@
+ #include <linux/kernel.h>
+ #include <asm/segment.h>
+ #include <asm/cpufeature.h>
+-#include <linux/bitops.h> /* for LOCK_PREFIX */
++#include <asm/cmpxchg.h>
+ #include <asm/synch_bitops.h>
+ #include <asm/hypervisor.h>
+ 
+@@ -90,308 +90,102 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"
+ #define savesegment(seg, value) \
+ 	asm volatile("mov %%" #seg ",%0":"=rm" (value))
+ 
+-#define read_cr0() ({ \
+-	unsigned int __dummy; \
+-	__asm__ __volatile__( \
+-		"movl %%cr0,%0\n\t" \
+-		:"=r" (__dummy)); \
+-	__dummy; \
+-})
+-#define write_cr0(x) \
+-	__asm__ __volatile__("movl %0,%%cr0": :"r" (x))
+-
+-#define read_cr2() (current_vcpu_info()->arch.cr2)
+-#define write_cr2(x) \
+-	__asm__ __volatile__("movl %0,%%cr2": :"r" (x))
+-
+-#define read_cr3() ({ \
+-	unsigned int __dummy; \
+-	__asm__ ( \
+-		"movl %%cr3,%0\n\t" \
+-		:"=r" (__dummy)); \
+-	__dummy = xen_cr3_to_pfn(__dummy); \
+-	mfn_to_pfn(__dummy) << PAGE_SHIFT; \
+-})
+-#define write_cr3(x) ({						\
+-	unsigned int __dummy = pfn_to_mfn((x) >> PAGE_SHIFT);	\
+-	__dummy = xen_pfn_to_cr3(__dummy);			\
+-	__asm__ __volatile__("movl %0,%%cr3": :"r" (__dummy));	\
+-})
+-#define read_cr4() ({ \
+-	unsigned int __dummy; \
+-	__asm__( \
+-		"movl %%cr4,%0\n\t" \
+-		:"=r" (__dummy)); \
+-	__dummy; \
+-})
+-#define read_cr4_safe() ({			      \
+-	unsigned int __dummy;			      \
+-	/* This could fault if %cr4 does not exist */ \
+-	__asm__("1: movl %%cr4, %0		\n"   \
+-		"2:				\n"   \
+-		".section __ex_table,\"a\"	\n"   \
+-		".long 1b,2b			\n"   \
+-		".previous			\n"   \
+-		: "=r" (__dummy): "0" (0));	      \
+-	__dummy;				      \
+-})
+-
+-#define write_cr4(x) \
+-	__asm__ __volatile__("movl %0,%%cr4": :"r" (x))
+-
+-#define wbinvd() \
+-	__asm__ __volatile__ ("wbinvd": : :"memory")
+-
+-/* Clear the 'TS' bit */
+-#define clts() (HYPERVISOR_fpu_taskswitch(0))
+-
+-/* Set the 'TS' bit */
+-#define stts() (HYPERVISOR_fpu_taskswitch(1))
+-
+-#endif	/* __KERNEL__ */
+-
+-static inline unsigned long get_limit(unsigned long segment)
++static inline void xen_clts(void)
+ {
+-	unsigned long __limit;
+-	__asm__("lsll %1,%0"
+-		:"=r" (__limit):"r" (segment));
+-	return __limit+1;
++	HYPERVISOR_fpu_taskswitch(0);
+ }
+ 
+-#define nop() __asm__ __volatile__ ("nop")
+-
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+-
+-#define tas(ptr) (xchg((ptr),1))
+-
+-struct __xchg_dummy { unsigned long a[100]; };
+-#define __xg(x) ((struct __xchg_dummy *)(x))
++static inline unsigned long xen_read_cr0(void)
++{
++	unsigned long val;
++	asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
++	return val;
++}
+ 
++static inline void xen_write_cr0(unsigned long val)
++{
++	asm volatile("movl %0,%%cr0": :"r" (val));
++}
+ 
+-#ifdef CONFIG_X86_CMPXCHG64
++#define xen_read_cr2() (current_vcpu_info()->arch.cr2)
+ 
+-/*
+- * The semantics of XCHGCMP8B are a bit strange, this is why
+- * there is a loop and the loading of %%eax and %%edx has to
+- * be inside. This inlines well in most cases, the cached
+- * cost is around ~38 cycles. (in the future we might want
+- * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
+- * might have an implicit FPU-save as a cost, so it's not
+- * clear which path to go.)
+- *
+- * cmpxchg8b must be used with the lock prefix here to allow
+- * the instruction to be executed atomically, see page 3-102
+- * of the instruction set reference 24319102.pdf. We need
+- * the reader side to see the coherent 64bit value.
+- */
+-static inline void __set_64bit (unsigned long long * ptr,
+-		unsigned int low, unsigned int high)
++static inline void xen_write_cr2(unsigned long val)
+ {
+-	__asm__ __volatile__ (
+-		"\n1:\t"
+-		"movl (%0), %%eax\n\t"
+-		"movl 4(%0), %%edx\n\t"
+-		"lock cmpxchg8b (%0)\n\t"
+-		"jnz 1b"
+-		: /* no outputs */
+-		:	"D"(ptr),
+-			"b"(low),
+-			"c"(high)
+-		:	"ax","dx","memory");
++	asm volatile("movl %0,%%cr2": :"r" (val));
+ }
+ 
+-static inline void __set_64bit_constant (unsigned long long *ptr,
+-						 unsigned long long value)
++static inline unsigned long xen_read_cr3(void)
+ {
+-	__set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
++	unsigned long val;
++	asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
++	return mfn_to_pfn(xen_cr3_to_pfn(val)) << PAGE_SHIFT;
+ }
+-#define ll_low(x)	*(((unsigned int*)&(x))+0)
+-#define ll_high(x)	*(((unsigned int*)&(x))+1)
+ 
+-static inline void __set_64bit_var (unsigned long long *ptr,
+-			 unsigned long long value)
++static inline void xen_write_cr3(unsigned long val)
+ {
+-	__set_64bit(ptr,ll_low(value), ll_high(value));
++	val = xen_pfn_to_cr3(pfn_to_mfn(val >> PAGE_SHIFT));
++	asm volatile("movl %0,%%cr3": :"r" (val));
+ }
+ 
+-#define set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit_constant(ptr, value) : \
+- __set_64bit_var(ptr, value) )
+-
+-#define _set_64bit(ptr,value) \
+-(__builtin_constant_p(value) ? \
+- __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+- __set_64bit(ptr, ll_low(value), ll_high(value)) )
+-
+-#endif
+-
+-/*
+- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+- * Note 2: xchg has side effect, so that attribute volatile is necessary,
+- *	  but generally the primitive is invalid, *ptr is output argument. --ANK
+- */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++static inline unsigned long xen_read_cr4(void)
+ {
+-	switch (size) {
+-		case 1:
+-			__asm__ __volatile__("xchgb %b0,%1"
+-				:"=q" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 2:
+-			__asm__ __volatile__("xchgw %w0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 4:
+-			__asm__ __volatile__("xchgl %0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-	}
+-	return x;
++	unsigned long val;
++	asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
++	return val;
+ }
+ 
+-/*
+- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+- * store NEW in MEM.  Return the initial value in MEM.  Success is
+- * indicated by comparing RETURN with OLD.
+- */
+-
+-#ifdef CONFIG_X86_CMPXCHG
+-#define __HAVE_ARCH_CMPXCHG 1
+-#define cmpxchg(ptr,o,n)\
+-	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+-					(unsigned long)(n),sizeof(*(ptr))))
+-#define sync_cmpxchg(ptr,o,n)\
+-	((__typeof__(*(ptr)))__sync_cmpxchg((ptr),(unsigned long)(o),\
+-					(unsigned long)(n),sizeof(*(ptr))))
+-#endif
++static inline unsigned long xen_read_cr4_safe(void)
++{
++	unsigned long val;
++	/* This could fault if %cr4 does not exist */
++	asm("1: movl %%cr4, %0		\n"
++		"2:				\n"
++		".section __ex_table,\"a\"	\n"
++		".long 1b,2b			\n"
++		".previous			\n"
++		: "=r" (val): "0" (0));
++	return val;
++}
+ 
+-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+-				      unsigned long new, int size)
++static inline void xen_write_cr4(unsigned long val)
+ {
+-	unsigned long prev;
+-	switch (size) {
+-	case 1:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 2:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 4:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	}
+-	return old;
++	asm volatile("movl %0,%%cr4": :"r" (val));
+ }
+ 
+-/*
+- * Always use locked operations when touching memory shared with a
+- * hypervisor, since the system may be SMP even if the guest kernel
+- * isn't.
+- */
+-static inline unsigned long __sync_cmpxchg(volatile void *ptr,
+-					    unsigned long old,
+-					    unsigned long new, int size)
+-{
+-	unsigned long prev;
+-	switch (size) {
+-	case 1:
+-		__asm__ __volatile__("lock; cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 2:
+-		__asm__ __volatile__("lock; cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 4:
+-		__asm__ __volatile__("lock; cmpxchgl %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	}
+-	return old;
++static inline void xen_wbinvd(void)
++{
++	asm volatile("wbinvd": : :"memory");
+ }
+ 
+-#ifndef CONFIG_X86_CMPXCHG
+-/*
+- * Building a kernel capable running on 80386. It may be necessary to
+- * simulate the cmpxchg on the 80386 CPU. For that purpose we define
+- * a function for each of the sizes we support.
+- */
++#define read_cr0()	(xen_read_cr0())
++#define write_cr0(x)	(xen_write_cr0(x))
++#define read_cr2()	(xen_read_cr2())
++#define write_cr2(x)	(xen_write_cr2(x))
++#define read_cr3()	(xen_read_cr3())
++#define write_cr3(x)	(xen_write_cr3(x))
++#define read_cr4()	(xen_read_cr4())
++#define read_cr4_safe()	(xen_read_cr4_safe())
++#define write_cr4(x)	(xen_write_cr4(x))
++#define wbinvd()	(xen_wbinvd())
+ 
+-extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8);
+-extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
+-extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
+-
+-static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
+-				      unsigned long new, int size)
+-{
+-	switch (size) {
+-	case 1:
+-		return cmpxchg_386_u8(ptr, old, new);
+-	case 2:
+-		return cmpxchg_386_u16(ptr, old, new);
+-	case 4:
+-		return cmpxchg_386_u32(ptr, old, new);
+-	}
+-	return old;
+-}
+-
+-#define cmpxchg(ptr,o,n)						\
+-({									\
+-	__typeof__(*(ptr)) __ret;					\
+-	if (likely(boot_cpu_data.x86 > 3))				\
+-		__ret = __cmpxchg((ptr), (unsigned long)(o),		\
+-					(unsigned long)(n), sizeof(*(ptr))); \
+-	else								\
+-		__ret = cmpxchg_386((ptr), (unsigned long)(o),		\
+-					(unsigned long)(n), sizeof(*(ptr))); \
+-	__ret;								\
+-})
+-#endif
++/* Clear the 'TS' bit */
++#define clts()		(xen_clts())
+ 
+-#ifdef CONFIG_X86_CMPXCHG64
++/* Set the 'TS' bit */
++#define stts() (HYPERVISOR_fpu_taskswitch(1))
+ 
+-static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
+-				      unsigned long long new)
++#endif	/* __KERNEL__ */
++
++static inline unsigned long get_limit(unsigned long segment)
+ {
+-	unsigned long long prev;
+-	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
+-			     : "=A"(prev)
+-			     : "b"((unsigned long)new),
+-			       "c"((unsigned long)(new >> 32)),
+-			       "m"(*__xg(ptr)),
+-			       "0"(old)
+-			     : "memory");
+-	return prev;
+-}
+-
+-#define cmpxchg64(ptr,o,n)\
+-	((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
+-					(unsigned long long)(n)))
++	unsigned long __limit;
++	__asm__("lsll %1,%0"
++		:"=r" (__limit):"r" (segment));
++	return __limit+1;
++}
++
++#define nop() __asm__ __volatile__ ("nop")
+ 
+-#endif
+-    
+ /*
+  * Force strict CPU ordering.
+  * And yes, this is required on UP too when we're talking
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:49:47.000000000 +0100
+@@ -29,8 +29,13 @@
+  * and page-granular flushes are available only on i486 and up.
+  */
+ 
++#define TLB_FLUSH_ALL	0xffffffff
++
++
+ #ifndef CONFIG_SMP
+ 
++#include <linux/sched.h>
++
+ #define flush_tlb() __flush_tlb()
+ #define flush_tlb_all() __flush_tlb_all()
+ #define local_flush_tlb() __flush_tlb()
+@@ -55,7 +60,7 @@ static inline void flush_tlb_range(struc
+ 		__flush_tlb();
+ }
+ 
+-#else
++#else  /* SMP */
+ 
+ #include <asm/smp.h>
+ 
+@@ -84,9 +89,7 @@ struct tlb_state
+ 	char __cacheline_padding[L1_CACHE_BYTES-8];
+ };
+ DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
+-
+-
+-#endif
++#endif	/* SMP */
+ 
+ #define flush_tlb_kernel_range(start, end) flush_tlb_all()
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -127,16 +127,6 @@ static inline void set_ldt_desc(unsigned
+ 			      DESC_LDT, size * 8 - 1);
+ }
+ 
+-static inline void set_seg_base(unsigned cpu, int entry, void *base)
+-{ 
+-	struct desc_struct *d = &cpu_gdt(cpu)[entry];
+-	u32 addr = (u32)(u64)base;
+-	BUG_ON((u64)base >> 32); 
+-	d->base0 = addr & 0xffff;
+-	d->base1 = (addr >> 16) & 0xff;
+-	d->base2 = (addr >> 24) & 0xff;
+-} 
+-
+ #define LDT_entry_a(info) \
+ 	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+ /* Don't allow setting of the lm bit. It is useless anyways because 
+@@ -165,25 +155,15 @@ static inline void set_seg_base(unsigned
+ 	(info)->useable		== 0	&& \
+ 	(info)->lm		== 0)
+ 
+-#if TLS_SIZE != 24
+-# error update this code.
+-#endif
+-
+ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
+ {
+-#if 0
++	unsigned int i;
+ 	u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
+-	gdt[0] = t->tls_array[0];
+-	gdt[1] = t->tls_array[1];
+-	gdt[2] = t->tls_array[2];
+-#endif
+-#define C(i) \
+-	if (HYPERVISOR_update_descriptor(virt_to_machine(&cpu_gdt(cpu)[GDT_ENTRY_TLS_MIN + i]), \
+-						 t->tls_array[i])) \
+-		BUG();
+ 
+-	C(0); C(1); C(2);
+-#undef C
++	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
++		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
++						 t->tls_array[i]))
++			BUG();
+ } 
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -15,7 +15,6 @@
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+ #include <asm/vsyscall.h>
+-#include <asm/vsyscall32.h>
+ #include <asm/acpi.h>
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -9,6 +9,7 @@
+  */
+ #ifndef _ASM_IRQFLAGS_H
+ #define _ASM_IRQFLAGS_H
++#include <asm/processor-flags.h>
+ 
+ #ifndef __ASSEMBLY__
+ /*
+@@ -50,19 +51,19 @@ static inline void raw_local_irq_disable
+ {
+ 	unsigned long flags = __raw_local_save_flags();
+ 
+-	raw_local_irq_restore((flags & ~(1 << 9)) | (1 << 18));
++	raw_local_irq_restore((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+ }
+ 
+ static inline void raw_local_irq_enable(void)
+ {
+ 	unsigned long flags = __raw_local_save_flags();
+ 
+-	raw_local_irq_restore((flags | (1 << 9)) & ~(1 << 18));
++	raw_local_irq_restore((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
+ }
+ 
+ static inline int raw_irqs_disabled_flags(unsigned long flags)
+ {
+-	return !(flags & (1<<9)) || (flags & (1 << 18));
++	return !(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC);
+ }
+ 
+ #else /* CONFIG_X86_VSMP */
+@@ -118,13 +119,21 @@ static inline int raw_irqs_disabled_flag
+  * Used in the idle loop; sti takes one instruction cycle
+  * to complete:
+  */
+-void raw_safe_halt(void);
++void xen_safe_halt(void);
++static inline void raw_safe_halt(void)
++{
++	xen_safe_halt();
++}
+ 
+ /*
+  * Used when interrupts are already enabled or to
+  * shutdown the processor:
+  */
+-void halt(void);
++void xen_halt(void);
++static inline void halt(void)
++{
++	xen_halt();
++}
+ 
+ #else /* __ASSEMBLY__: */
+ # ifdef CONFIG_TRACE_IRQFLAGS
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -9,6 +9,9 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ 
++void arch_exit_mmap(struct mm_struct *mm);
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
++
+ /*
+  * possibly do the LDT unload here?
+  */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_64.h	2007-06-18 08:38:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -1,7 +1,6 @@
+ #ifndef _X86_64_PGALLOC_H
+ #define _X86_64_PGALLOC_H
+ 
+-#include <asm/fixmap.h>
+ #include <asm/pda.h>
+ #include <linux/threads.h>
+ #include <linux/mm.h>
+@@ -100,24 +99,16 @@ static inline void pgd_list_add(pgd_t *p
+ 	struct page *page = virt_to_page(pgd);
+ 
+ 	spin_lock(&pgd_lock);
+-	page->index = (pgoff_t)pgd_list;
+-	if (pgd_list)
+-		pgd_list->private = (unsigned long)&page->index;
+-	pgd_list = page;
+-	page->private = (unsigned long)&pgd_list;
++	list_add(&page->lru, &pgd_list);
+ 	spin_unlock(&pgd_lock);
+ }
+ 
+ static inline void pgd_list_del(pgd_t *pgd)
+ {
+-	struct page *next, **pprev, *page = virt_to_page(pgd);
++	struct page *page = virt_to_page(pgd);
+ 
+ 	spin_lock(&pgd_lock);
+-	next = (struct page *)page->index;
+-	pprev = (struct page **)page->private;
+-	*pprev = next;
+-	if (next)
+-		next->private = (unsigned long)pprev;
++	list_del(&page->lru);
+ 	spin_unlock(&pgd_lock);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -1,12 +1,14 @@
+ #ifndef _X86_64_PGTABLE_H
+ #define _X86_64_PGTABLE_H
+ 
++#include <linux/const.h>
++#ifndef __ASSEMBLY__
++
+ /*
+  * This file contains the functions and defines necessary to modify and use
+  * the x86-64 page table tree.
+  */
+ #include <asm/processor.h>
+-#include <asm/fixmap.h>
+ #include <asm/bitops.h>
+ #include <linux/threads.h>
+ #include <linux/sched.h>
+@@ -35,11 +37,9 @@ extern pte_t *lookup_address(unsigned lo
+ #endif
+ 
+ extern pud_t level3_kernel_pgt[512];
+-extern pud_t level3_physmem_pgt[512];
+ extern pud_t level3_ident_pgt[512];
+ extern pmd_t level2_kernel_pgt[512];
+ extern pgd_t init_level4_pgt[];
+-extern pgd_t boot_level4_pgt[];
+ extern unsigned long __supported_pte_mask;
+ 
+ #define swapper_pg_dir init_level4_pgt
+@@ -54,6 +54,8 @@ extern void clear_kernel_mapping(unsigne
+ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ 
++#endif /* !__ASSEMBLY__ */
++
+ /*
+  * PGDIR_SHIFT determines what a top-level page table entry can map
+  */
+@@ -78,6 +80,8 @@ extern unsigned long empty_zero_page[PAG
+  */
+ #define PTRS_PER_PTE	512
+ 
++#ifndef __ASSEMBLY__
++
+ #define pte_ERROR(e) \
+ 	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
+ 	       &(e), __pte_val(e), pte_pfn(e))
+@@ -120,22 +124,23 @@ static inline void pgd_clear (pgd_t * pg
+ 
+ #define pte_pgprot(a)	(__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
+ 
+-#define PMD_SIZE	(1UL << PMD_SHIFT)
++#endif /* !__ASSEMBLY__ */
++
++#define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
+ #define PMD_MASK	(~(PMD_SIZE-1))
+-#define PUD_SIZE	(1UL << PUD_SHIFT)
++#define PUD_SIZE	(_AC(1,UL) << PUD_SHIFT)
+ #define PUD_MASK	(~(PUD_SIZE-1))
+-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
++#define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE-1))
+ 
+ #define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
+ #define FIRST_USER_ADDRESS	0
+ 
+-#ifndef __ASSEMBLY__
+-#define MAXMEM		 0x6fffffffffUL
+-#define VMALLOC_START    0xffffc20000000000UL
+-#define VMALLOC_END      0xffffe1ffffffffffUL
+-#define MODULES_VADDR    0xffffffff88000000UL
+-#define MODULES_END      0xffffffffff000000UL
++#define MAXMEM		 _AC(0x6fffffffff, UL)
++#define VMALLOC_START    _AC(0xffffc20000000000, UL)
++#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
++#define MODULES_VADDR    _AC(0xffffffff88000000, UL)
++#define MODULES_END      _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+ 
+ #define _PAGE_BIT_PRESENT	0
+@@ -161,16 +166,18 @@ static inline void pgd_clear (pgd_t * pg
+ #define _PAGE_GLOBAL	0x100	/* Global TLB entry */
+ 
+ #define _PAGE_PROTNONE	0x080	/* If not present */
+-#define _PAGE_NX        (1UL<<_PAGE_BIT_NX)
++#define _PAGE_NX        (_AC(1,UL)<<_PAGE_BIT_NX)
+ 
+ /* Mapped page is I/O or foreign and has no associated page struct. */
+ #define _PAGE_IO	0x200
+ 
++#ifndef __ASSEMBLY__
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ extern unsigned int __kernel_page_user;
+ #else
+ #define __kernel_page_user 0
+ #endif
++#endif
+ 
+ #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)
+@@ -235,6 +242,8 @@ extern unsigned int __kernel_page_user;
+ #define __S110	PAGE_SHARED_EXEC
+ #define __S111	PAGE_SHARED_EXEC
+ 
++#ifndef __ASSEMBLY__
++
+ static inline unsigned long pgd_bad(pgd_t pgd)
+ {
+ 	return __pgd_val(pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
+@@ -346,6 +355,20 @@ static inline pte_t pte_mkwrite(pte_t pt
+ static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
+ static inline pte_t pte_clrhuge(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_PSE; return pte; }
+ 
++static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
++{
++	if (!pte_dirty(*ptep))
++		return 0;
++	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
++}
++
++static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
++{
++	if (!pte_young(*ptep))
++		return 0;
++	return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte);
++}
++
+ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ 	pte_t pte = *ptep;
+@@ -470,18 +493,12 @@ static inline pte_t pte_modify(pte_t pte
+  * bit at the same time. */
+ #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ #define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-	do {								\
+-		if (dirty)						\
+-			ptep_establish(vma, address, ptep, entry);	\
+-	} while (0)
+-
+-
+-/*
+- * i386 says: We don't actually have these, but we want to advertise
+- * them so that we can encompass the flush here.
+- */
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++({									\
++	int __changed = !pte_same(*(ptep), entry);			\
++	if (__changed && (dirty))					\
++		ptep_establish(vma, address, ptep, entry);		\
++	__changed;							\
++})
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+ #define ptep_clear_flush_dirty(vma, address, ptep)			\
+@@ -490,7 +507,7 @@ static inline pte_t pte_modify(pte_t pte
+ 	int __dirty = pte_dirty(__pte);					\
+ 	__pte = pte_mkclean(__pte);					\
+ 	if ((vma)->vm_mm->context.pinned)				\
+-		ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
++		(void)ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
+ 	else if (__dirty)						\
+ 		set_pte(ptep, __pte);					\
+ 	__dirty;							\
+@@ -503,7 +520,7 @@ static inline pte_t pte_modify(pte_t pte
+ 	int __young = pte_young(__pte);					\
+ 	__pte = pte_mkold(__pte);					\
+ 	if ((vma)->vm_mm->context.pinned)				\
+-		ptep_set_access_flags(vma, address, ptep, __pte, __young); \
++		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+ 	else if (__young)						\
+ 		set_pte(ptep, __pte);					\
+ 	__young;							\
+@@ -517,10 +534,7 @@ static inline pte_t pte_modify(pte_t pte
+ #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+ 
+ extern spinlock_t pgd_lock;
+-extern struct page *pgd_list;
+-void vmalloc_sync_all(void);
+-
+-#endif /* !__ASSEMBLY__ */
++extern struct list_head pgd_list;
+ 
+ extern int kern_addr_valid(unsigned long addr); 
+ 
+@@ -559,10 +573,6 @@ int xen_change_pte_range(struct mm_struc
+ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+ 		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
+ 
+-#define MK_IOSPACE_PFN(space, pfn)	(pfn)
+-#define GET_IOSPACE(pfn)		0
+-#define GET_PFN(pfn)			(pfn)
+-
+ #define HAVE_ARCH_UNMAPPED_AREA
+ 
+ #define pgtable_cache_init()   do { } while (0)
+@@ -576,11 +586,14 @@ int xen_change_pte_range(struct mm_struc
+ #define	kc_offset_to_vaddr(o) \
+    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
+ 
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+ #define __HAVE_ARCH_PTEP_SET_WRPROTECT
+ #define __HAVE_ARCH_PTE_SAME
+ #include <asm-generic/pgtable.h>
++#endif /* !__ASSEMBLY__ */
+ 
+ #endif /* _X86_64_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -20,6 +20,7 @@
+ #include <asm/percpu.h>
+ #include <linux/personality.h>
+ #include <linux/cpumask.h>
++#include <asm/processor-flags.h>
+ 
+ #define TF_MASK		0x00000100
+ #define IF_MASK		0x00000200
+@@ -103,42 +104,6 @@ extern unsigned int init_intel_cacheinfo
+ extern unsigned short num_cache_leaves;
+ 
+ /*
+- * EFLAGS bits
+- */
+-#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
+-#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
+-#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
+-#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
+-#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
+-#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
+-#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
+-#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
+-#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
+-#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
+-#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
+-#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
+-#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
+-#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
+-#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
+-#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
+-#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
+-
+-/*
+- * Intel CPU features in CR4
+- */
+-#define X86_CR4_VME		0x0001	/* enable vm86 extensions */
+-#define X86_CR4_PVI		0x0002	/* virtual interrupts flag enable */
+-#define X86_CR4_TSD		0x0004	/* disable time stamp at ipl 3 */
+-#define X86_CR4_DE		0x0008	/* enable debugging extensions */
+-#define X86_CR4_PSE		0x0010	/* enable page size extensions */
+-#define X86_CR4_PAE		0x0020	/* enable physical address extensions */
+-#define X86_CR4_MCE		0x0040	/* Machine check enable */
+-#define X86_CR4_PGE		0x0080	/* enable global pages */
+-#define X86_CR4_PCE		0x0100	/* enable performance counters at ipl 3 */
+-#define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
+-#define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
+-
+-/*
+  * Save the cr4 feature set we're using (ie
+  * Pentium 4MB enable and PPro Global page
+  * enable), so that any CPU's that boot up
+@@ -203,7 +168,7 @@ struct i387_fxsave_struct {
+ 	u32	mxcsr;
+ 	u32	mxcsr_mask;
+ 	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
+-	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 128 bytes */
++	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
+ 	u32	padding[24];
+ } __attribute__ ((aligned (16)));
+ 
+@@ -436,22 +401,6 @@ static inline void prefetchw(void *x) 
+ #define cpu_relax()   rep_nop()
+ 
+ /*
+- *      NSC/Cyrix CPU configuration register indexes
+- */
+-#define CX86_CCR0 0xc0
+-#define CX86_CCR1 0xc1
+-#define CX86_CCR2 0xc2
+-#define CX86_CCR3 0xc3
+-#define CX86_CCR4 0xe8
+-#define CX86_CCR5 0xe9
+-#define CX86_CCR6 0xea
+-#define CX86_CCR7 0xeb
+-#define CX86_DIR0 0xfe
+-#define CX86_DIR1 0xff
+-#define CX86_ARR_BASE 0xc4
+-#define CX86_RCR_BASE 0xdc
+-
+-/*
+  *      NSC/Cyrix CPU indexed register access macros
+  */
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -11,12 +11,11 @@
+ extern int disable_apic;
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+-#include <asm/fixmap.h>
+ #include <asm/mpspec.h>
++#include <asm/apic.h>
+ #ifdef CONFIG_X86_IO_APIC
+ #include <asm/io_apic.h>
+ #endif
+-#include <asm/apic.h>
+ #include <asm/thread_info.h>
+ #endif
+ 
+@@ -41,7 +40,6 @@ extern void lock_ipi_call_lock(void);
+ extern void unlock_ipi_call_lock(void);
+ extern int smp_num_siblings;
+ extern void smp_send_reschedule(int cpu);
+-void smp_stop_cpu(void);
+ 
+ extern cpumask_t cpu_sibling_map[NR_CPUS];
+ extern cpumask_t cpu_core_map[NR_CPUS];
+@@ -62,14 +60,6 @@ static inline int num_booting_cpus(void)
+ 
+ #define raw_smp_processor_id() read_pda(cpunumber)
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
+-}
+-#endif
+-
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void prefill_possible_map(void);
+@@ -78,6 +68,14 @@ extern unsigned __cpuinitdata disabled_c
+ 
+ #define NO_PROC_ID		0xFF		/* No processor magic marker */
+ 
++#endif /* CONFIG_SMP */
++
++#ifdef CONFIG_X86_LOCAL_APIC
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
++}
+ #endif
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -3,7 +3,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <asm/segment.h>
+-#include <asm/alternative.h>
++#include <asm/cmpxchg.h>
+ 
+ #include <asm/synch_bitops.h>
+ #include <asm/hypervisor.h>
+@@ -43,7 +43,7 @@
+ 		       [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
+ 		       [ti_flags] "i" (offsetof(struct thread_info, flags)),\
+ 		       [tif_fork] "i" (TIF_FORK),			  \
+-		       [thread_info] "i" (offsetof(struct task_struct, thread_info)), \
++		       [thread_info] "i" (offsetof(struct task_struct, stack)), \
+ 		       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))   \
+ 		     : "memory", "cc" __EXTRA_CLOBBER)
+     
+@@ -92,6 +92,12 @@ static inline void write_cr0(unsigned lo
+ 	machine_to_phys(__dummy); \
+ })
+ 
++static inline void write_cr3(unsigned long val)
++{
++	val = phys_to_machine(val);
++	asm volatile("movq %0,%%cr3" :: "r" (val) : "memory");
++}
++
+ static inline unsigned long read_cr4(void)
+ { 
+ 	unsigned long cr4;
+@@ -101,7 +107,7 @@ static inline unsigned long read_cr4(voi
+ 
+ static inline void write_cr4(unsigned long val)
+ { 
+-	asm volatile("movq %0,%%cr4" :: "r" (val));
++	asm volatile("movq %0,%%cr4" :: "r" (val) : "memory");
+ } 
+ 
+ #define stts() (HYPERVISOR_fpu_taskswitch(1))
+@@ -122,100 +128,6 @@ static inline void sched_cacheflush(void
+ 
+ #define nop() __asm__ __volatile__ ("nop")
+ 
+-#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+-
+-#define tas(ptr) (xchg((ptr),1))
+-
+-#define __xg(x) ((volatile long *)(x))
+-
+-static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+-{
+-	*ptr = val;
+-}
+-
+-#define _set_64bit set_64bit
+-
+-/*
+- * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+- * Note 2: xchg has side effect, so that attribute volatile is necessary,
+- *	  but generally the primitive is invalid, *ptr is output argument. --ANK
+- */
+-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+-{
+-	switch (size) {
+-		case 1:
+-			__asm__ __volatile__("xchgb %b0,%1"
+-				:"=q" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 2:
+-			__asm__ __volatile__("xchgw %w0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 4:
+-			__asm__ __volatile__("xchgl %k0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-		case 8:
+-			__asm__ __volatile__("xchgq %0,%1"
+-				:"=r" (x)
+-				:"m" (*__xg(ptr)), "0" (x)
+-				:"memory");
+-			break;
+-	}
+-	return x;
+-}
+-
+-/*
+- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+- * store NEW in MEM.  Return the initial value in MEM.  Success is
+- * indicated by comparing RETURN with OLD.
+- */
+-
+-#define __HAVE_ARCH_CMPXCHG 1
+-
+-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+-				      unsigned long new, int size)
+-{
+-	unsigned long prev;
+-	switch (size) {
+-	case 1:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+-				     : "=a"(prev)
+-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 2:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 4:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	case 8:
+-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
+-				     : "=a"(prev)
+-				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+-				     : "memory");
+-		return prev;
+-	}
+-	return old;
+-}
+-
+-#define cmpxchg(ptr,o,n)\
+-	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+-					(unsigned long)(n),sizeof(*(ptr))))
+-
+ #ifdef CONFIG_SMP
+ #define smp_mb()	mb()
+ #define smp_rmb()	rmb()
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:49:47.000000000 +0100
+@@ -2,7 +2,9 @@
+ #define _X8664_TLBFLUSH_H
+ 
+ #include <linux/mm.h>
++#include <linux/sched.h>
+ #include <asm/processor.h>
++#include <asm/system.h>
+ 
+ #define __flush_tlb()	xen_tlb_flush()
+ 
+--- head-2010-01-18.orig/include/linux/pci.h	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/include/linux/pci.h	2009-11-06 10:49:47.000000000 +0100
+@@ -289,7 +289,7 @@ struct pci_dev {
+ 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
+ 	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
+ 	struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
+-#ifdef CONFIG_PCI_MSI
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ 	struct list_head msi_list;
+ #endif
+ 	struct pci_vpd *vpd;
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:49:47.000000000 +0100
+@@ -723,7 +723,6 @@ swiotlb_dma_supported (struct device *hw
+ 	return (mask >= ((1UL << dma_bits) - 1));
+ }
+ 
+-EXPORT_SYMBOL(swiotlb_init);
+ EXPORT_SYMBOL(swiotlb_map_single);
+ EXPORT_SYMBOL(swiotlb_unmap_single);
+ EXPORT_SYMBOL(swiotlb_map_sg);
+--- head-2010-01-18.orig/net/core/dev.c	2009-12-04 10:51:26.000000000 +0100
++++ head-2010-01-18/net/core/dev.c	2009-12-04 10:55:51.000000000 +0100
+@@ -1827,12 +1827,17 @@ static struct netdev_queue *dev_pick_tx(
+ inline int skb_checksum_setup(struct sk_buff *skb)
+ {
+ 	if (skb->proto_csum_blank) {
++		struct iphdr *iph;
++		unsigned char *th;
++
+ 		if (skb->protocol != htons(ETH_P_IP))
+ 			goto out;
+-		skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
+-		if (skb->h.raw >= skb->tail)
++		iph = ip_hdr(skb);
++		th = skb_network_header(skb) + 4 * iph->ihl;
++		if (th >= skb_tail_pointer(skb))
+ 			goto out;
+-		switch (skb->nh.iph->protocol) {
++		skb->csum_start = th - skb->head;
++		switch (iph->protocol) {
+ 		case IPPROTO_TCP:
+ 			skb->csum_offset = offsetof(struct tcphdr, check);
+ 			break;
+@@ -1843,10 +1848,10 @@ inline int skb_checksum_setup(struct sk_
+ 			if (net_ratelimit())
+ 				printk(KERN_ERR "Attempting to checksum a non-"
+ 				       "TCP/UDP packet, dropping a protocol"
+-				       " %d packet", skb->nh.iph->protocol);
++				       " %d packet", iph->protocol);
+ 			goto out;
+ 		}
+-		if ((skb->h.raw + skb->csum_offset + 2) > skb->tail)
++		if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+ 			goto out;
+ 		skb->ip_summed = CHECKSUM_PARTIAL;
+ 		skb->proto_csum_blank = 0;
+--- head-2010-01-18.orig/scripts/Makefile.xen.awk	2007-08-06 15:10:49.000000000 +0200
++++ head-2010-01-18/scripts/Makefile.xen.awk	2009-11-06 10:49:47.000000000 +0100
+@@ -13,7 +13,7 @@ BEGIN {
+ 	next
+ }
+ 
+-/:[[:space:]]*%\.[cS][[:space:]]/ {
++/:[[:space:]]*\$\(src\)\/%\.[cS][[:space:]]/ {
+ 	line = gensub(/%.([cS])/, "%-xen.\\1", "g", $0)
+ 	line = gensub(/(single-used-m)/, "xen-\\1", "g", line)
+ 	print line
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-resource-driver
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-resource-driver
@@ -0,0 +1,15052 @@
+From: David Riddoch <driddoch@solarflare.com>
+# replaces http://xenbits.xensource.com/linux-2.6.18-xen.hg c/s 421:
+# HG changeset patch
+# User Keir Fraser <keir.fraser@citrix.com>
+# Date 1203330569 0
+# Node ID e4dd072db2595c420bb21d9e835416f4fd543526
+# Parent  fc90e9b2c12b316b5460ece28f013e6de881af1a
+Subject: Solarflare: Resource driver.
+References: FATE#303479
+Acked-by: jbeulich@novell.com
+
+--- head-2009-04-21.orig/drivers/net/sfc/Kconfig	2009-04-21 11:01:52.000000000 +0200
++++ head-2009-04-21/drivers/net/sfc/Kconfig	2009-04-21 11:02:22.000000000 +0200
+@@ -11,6 +11,13 @@ config SFC
+ 
+ 	  To compile this driver as a module, choose M here.  The module
+ 	  will be called sfc.
++
++config SFC_RESOURCE
++	depends on SFC && X86
++	tristate "Solarflare Solarstorm SFC4000 resource driver"
++	help
++	  This module provides the SFC resource manager driver.
++
+ config SFC_MTD
+ 	bool "Solarflare Solarstorm SFC4000 flash MTD support"
+ 	depends on SFC && MTD && !(SFC=y && MTD=m)
+--- head-2009-04-21.orig/drivers/net/sfc/Makefile	2009-04-21 11:01:52.000000000 +0200
++++ head-2009-04-21/drivers/net/sfc/Makefile	2009-02-06 12:42:18.000000000 +0100
+@@ -5,3 +5,5 @@ sfc-y			+= efx.o falcon.o tx.o rx.o falc
+ sfc-$(CONFIG_SFC_MTD)	+= mtd.o
+ 
+ obj-$(CONFIG_SFC)	+= sfc.o
++
++obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/Makefile	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,14 @@
++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_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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/assert_valid.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,92 @@
++/****************************************************************************
++ * 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_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 || rs->rs_ref_count > 0)
++		    || !(!ref_count_is_zero || rs->rs_ref_count == 0))
++			EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT,
++				  __func__,
++				  ref_count_is_zero == 0 ? "non-" : "",
++				  rs->rs_ref_count,
++				  EFRM_RESOURCE_PRI_ARG(rs->rs_handle));
++
++		_EFRM_ASSERT(!(ref_count_is_zero == 0) ||
++			     rs->rs_ref_count != 0, file, line);
++		_EFRM_ASSERT(!(ref_count_is_zero > 0) ||
++			     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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/buddy.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,220 @@
++
++/****************************************************************************
++ * 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",
++		    __func__, 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", __func__, 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) 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)", __func__, 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)", __func__, 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)", __func__, 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, buddy_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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/buffer_table.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,209 @@
++/****************************************************************************
++ * 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, i;
++
++	EFRM_ASSERT(high > 0);
++	EFRM_ASSERT(low < high);
++
++	EFRM_TRACE("%s: low=%u high=%u", __func__, low, high);
++	EFRM_NOTICE("%s: low=%u high=%u", __func__, 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;
++	}
++	for (i = 0; i < (1 << log2_n_entries); ++i) {
++		rc = efrm_buddy_alloc(&efrm_buffers.buddy, 0);
++		EFRM_ASSERT(rc >= 0);
++		EFRM_ASSERT(rc < (1 << log2_n_entries));
++	}
++	for (i = low; i < (int) high; ++i)
++		efrm_buddy_free(&efrm_buffers.buddy, i, 0);
++
++	spin_lock_init(&efrm_buffers.lock);
++
++	EFRM_TRACE("%s: done", __func__);
++
++	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("%s: done", __func__);
++}
++
++/**********************************************************************/
++
++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,
++		      struct efhw_nic *nic,
++		      unsigned i, dma_addr_t dma_addr, int owner)
++{
++	EFRM_ASSERT(a);
++	EFRM_ASSERT(i < (unsigned)1 << a->order);
++
++	efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE,
++				  0, owner, a->base + i);
++}
++
++
++int efrm_buffer_table_size(void)
++{
++	return efrm_buddy_size(&efrm_buffers.buddy);
++}
++
++/**********************************************************************/
++
++int
++efrm_page_register(struct efhw_nic *nic, 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, nic, 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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h	2008-07-17 16:18: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 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, non_irq_evq) \
++	((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr), \
++					 (non_irq_evq)))
++
++/*-------------- 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) \
++	((nic)->efhw_func->interrupt_enable(nic))
++
++#define efhw_nic_interrupt_disable(nic) \
++	((nic)->efhw_func->interrupt_disable(nic))
++
++#define efhw_nic_set_interrupt_moderation(nic, evq, val)                 \
++	((nic)->efhw_func->set_interrupt_moderation(nic, evq, val))
++
++/*-------------- Event support  ------------ */
++
++#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base,   \
++				    interrupting)                       \
++	((nic)->efhw_func->event_queue_enable((nic), (evq), (size), (q_base), \
++					      (buf_base), (interrupting)))
++
++#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_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))
++
++/*-------------- New filter API ------------ */
++#define efhw_nic_filter_set(nic, spec, index_out) \
++	((nic)->efhw_func->filter_set(nic, spec, index_out))
++
++#define efhw_nic_filter_clear(nic, type, index_out) \
++	((nic)->efhw_func->filter_clear(nic, type, index_out))
++
++
++/* --- 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
++
++#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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h	2008-07-17 16:18: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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,422 @@
++/****************************************************************************
++ * 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_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
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Note: the following constants have moved to values in struct efhw_nic:
++ *   FALCON_EVQ_TBL_NUM  ->  nic->num_evqs
++ *   FALCON_DMAQ_NUM     ->  nic->num_dmaqs
++ *   FALCON_TIMERS_NUM   ->  nic->num_times
++ * These replacement constants are used as sanity checks in assertions in
++ * certain functions that don't have access to struct efhw_nic.
++ */
++#define FALCON_DMAQ_NUM_SANITY          (EFHW_4K)
++#define FALCON_EVQ_TBL_NUM_SANITY       (EFHW_4K)
++#define FALCON_TIMERS_NUM_SANITY        (EFHW_4K)
++
++/* This value is an upper limit on the total number of filter table
++ * entries.  The actual size of filter table is determined at runtime, as
++ * it can vary.
++ */
++#define FALCON_FILTER_TBL_NUM		(EFHW_8K)
++
++/* 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(volatile char __iomem *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(volatile char __iomem *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(volatile char __iomem *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(volatile char __iomem *kva, uint64_t q0, uint64_t q1)
++{
++	writeq(q0, kva + 0);
++	falcon_write_q(kva + 8, q1);
++}
++
++static inline void
++falcon_read_qq(volatile char __iomem *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_SANITY);
++
++	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_SANITY);
++
++	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_SANITY);
++
++	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      */
++
++/* 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(volatile char __iomem *efhw_kva, unsigned what)
++{
++	writel(what, efhw_kva + 0x300);
++	mmiowb();
++}
++#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */
++/*! \cidoxg_end */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,1147 @@
++/****************************************************************************
++ * 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 NIC_STAT_REG_KER_OFST 0x200 /* ASIC strap status register */
++#define NIC_STAT_REG_OFST 0x200 /* ASIC strap status register */
++  #define ONCHIP_SRAM_LBN 16
++  #define ONCHIP_SRAM_WIDTH 0
++  #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_NOTAF_LBN 19
++  #define TX_PACE_SB_NOTAF_WIDTH 10
++  #define TX_PACE_SB_AF_LBN 9
++  #define TX_PACE_SB_AF_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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h	2008-07-17 16:18: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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h	2008-07-17 16:18: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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h	2008-07-17 16:18: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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h	2008-07-17 16:18: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 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_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 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 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 */
++
++#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,273 @@
++/****************************************************************************
++ * 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 ifindex Index of the network interface desired
++ * \return Zero on success (and vih_out set), non-zero on failure.
++ */
++extern int
++efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex);
++
++/*!
++ * 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_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 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h	2008-07-17 16:18: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 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__
++
++#include <ci/efrm/efrm_nic.h>
++#include <linux/interrupt.h>
++
++
++/************************************************************************
++ * Per-nic structure in the resource driver                             *
++ ************************************************************************/
++
++struct linux_efhw_nic {
++	struct efrm_nic efrm_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, efrm_nic.efhw_nic)
++
++#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/checks.h	2008-07-17 16:18: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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/common.h	2008-07-17 16:18: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 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>
++
++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;
++} 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,61 @@
++/****************************************************************************
++ * 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>
++
++/* 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
++
++#endif /* __CI_EFHW_COMMON_LINUX_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/debug.h	2008-07-17 16:18: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 __func__ 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h	2008-07-17 16:18: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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,382 @@
++/****************************************************************************
++ * 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>
++
++/*--------------------------------------------------------------------
++ *
++ * 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 */
++	struct efhw_iopages 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 {
++	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;
++};
++
++/*--------------------------------------------------------------------
++ *
++ * filters
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_filter_spec {
++	uint dmaq_id;
++	uint32_t saddr_le32;
++	uint32_t daddr_le32;
++	uint16_t sport_le16;
++	uint16_t dport_le16;
++	unsigned tcp     : 1;
++	unsigned full    : 1;
++	unsigned rss     : 1;  /* not supported on A1 */
++	unsigned scatter : 1;  /* not supported on A1 */
++};
++
++struct efhw_filter_depth {
++	unsigned needed;
++	unsigned max;
++};
++
++struct efhw_filter_search_limits {
++	unsigned tcp_full;
++	unsigned tcp_wild;
++	unsigned udp_full;
++	unsigned udp_wild;
++};
++
++
++/**********************************************************************
++ * 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, int non_irq_evq);
++
++  /*-------------- 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 the interrupt */
++	void (*interrupt_enable) (struct efhw_nic *nic);
++
++	/*! Disable the interrupt */
++	void (*interrupt_disable) (struct efhw_nic *nic);
++
++	/*! Set interrupt moderation strategy for the given IRQ unit
++	 ** val is in usec
++	 */
++	void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq,
++					 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,
++				    int interrupting);
++
++	/*! 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);
++
++  /*-------------- IP Filter API  ------------ */
++
++	/*! 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);
++
++	/*! 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);
++
++  /*-------------- New filter API ------------ */
++
++	/*! Set a given filter */
++	int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec,
++			   int *filter_idx_out);
++
++	/*! Clear a given filter */
++	void (*filter_clear) (struct efhw_nic *nic, int filter_idx);
++};
++
++
++/*----------------------------------------------------------------------------
++ *
++ * 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_tablep->nic array */
++	int index;
++	int ifindex;		/*!< OS level nic index */
++	struct net *nd_net;
++
++	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
++
++	unsigned mtu;		/*!< MAC MTU (includes MAC hdr) */
++
++	/* hardware resources */
++
++	/*! I/O address of the start of the bar */
++	volatile char __iomem *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;
++
++	/*! 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 interrupting_evq;
++
++/* 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 for the interrupting event queue  */
++	unsigned int irq_unit;
++
++	struct efhw_keventq non_interrupting_evq;
++
++	struct efhw_iopage 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. */
++	unsigned ip_filter_tbl_size;
++
++	/* Number of filters currently used */
++	unsigned ip_filter_tbl_used;
++
++	/* Dynamically allocated filter state. */
++	uint8_t *filter_in_use;
++	struct efhw_filter_spec *filter_spec_cache;
++
++	/* Currently required and maximum filter table search depths. */
++	struct efhw_filter_depth tcp_full_srch;
++	struct efhw_filter_depth tcp_wild_srch;
++	struct efhw_filter_depth udp_full_srch;
++	struct efhw_filter_depth udp_wild_srch;
++
++	/* Number of event queues, DMA queues and timers. */
++	unsigned num_evqs;
++	unsigned num_dmaqs;
++	unsigned num_timers;
++};
++
++
++#define EFHW_KVA(nic)       ((nic)->bar_ioaddr)
++
++
++#endif /* __CI_EFHW_EFHW_TYPES_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h	2008-07-17 16:18: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 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, unsigned);
++	void (*timeout_fn)(struct efhw_nic *nic, unsigned);
++	void (*dmaq_flushed_fn) (struct efhw_nic *, unsigned, 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,77 @@
++/****************************************************************************
++ * 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 */
++/* 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
++
++#define EFHW_EVENT_OVERFLOW(evq, s)			\
++	(EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1)))
++
++#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h	2008-07-17 16:18: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 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);
++
++/*! configure the pace engine */
++extern void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base,
++				int bin_thresh);
++
++/*! 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);
++
++/*! 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 int falcon_nic_filter_ctor(struct efhw_nic *nic);
++
++extern void falcon_nic_filter_dtor(struct efhw_nic *nic);
++
++#endif /* __CI_EFHW_FALCON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h	2008-07-17 16:18: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__
++
++extern unsigned int
++falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
++		       unsigned int dest_ip, unsigned int dest_port,
++		       int tcp, int full);
++
++extern unsigned int
++falcon_hash_function1(unsigned int key, unsigned int nfilters);
++
++extern unsigned int
++falcon_hash_function2(unsigned int key, unsigned int nfilters);
++
++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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h	2008-07-17 16:18: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 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 <linux/io.h>
++
++#ifdef __LITTLE_ENDIAN
++#define EFHW_IS_LITTLE_ENDIAN
++#elif __BIG_ENDIAN
++#define EFHW_IS_BIG_ENDIAN
++#else
++#error Unknown endianness
++#endif
++
++#ifndef readq
++static inline uint64_t __readq(volatile void __iomem *addr)
++{
++	return *(volatile uint64_t *)addr;
++}
++#define readq(x) __readq(x)
++#endif
++
++#ifndef writeq
++static inline void __writeq(uint64_t v, volatile void __iomem *addr)
++{
++	*(volatile uint64_t *)addr = v;
++}
++#define writeq(val, addr) __writeq((val), (addr))
++#endif
++
++#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h	2008-07-17 16:18: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 *, struct efhw_iopage *p);
++extern void efhw_iopage_free(struct efhw_nic *, struct efhw_iopage *p);
++
++extern int efhw_iopages_alloc(struct efhw_nic *, struct efhw_iopages *p,
++			      unsigned order);
++extern void efhw_iopages_free(struct efhw_nic *, struct efhw_iopages *p);
++
++#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h	2008-07-17 16:18: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 provides struct efhw_page and struct efhw_iopage 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 <linux/errno.h>
++#include <ci/efhw/debug.h>
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_page: A single page of memory.  Directly mapped in the
++ * driver, and can be mapped to userlevel.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_page {
++	unsigned long kva;
++};
++
++static inline int efhw_page_alloc(struct efhw_page *p)
++{
++	p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++	return p->kva ? 0 : -ENOMEM;
++}
++
++static inline int efhw_page_alloc_zeroed(struct efhw_page *p)
++{
++	p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
++	return p->kva ? 0 : -ENOMEM;
++}
++
++static inline void efhw_page_free(struct efhw_page *p)
++{
++	free_page(p->kva);
++	EFHW_DO_DEBUG(memset(p, 0, sizeof(*p)));
++}
++
++static inline char *efhw_page_ptr(struct efhw_page *p)
++{
++	return (char *)p->kva;
++}
++
++static inline unsigned efhw_page_pfn(struct efhw_page *p)
++{
++	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline void efhw_page_mark_invalid(struct efhw_page *p)
++{
++	p->kva = 0;
++}
++
++static inline int efhw_page_is_valid(struct efhw_page *p)
++{
++	return p->kva != 0;
++}
++
++static inline void efhw_page_init_from_va(struct efhw_page *p, void *va)
++{
++	p->kva = (unsigned long)va;
++}
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_iopage: A single page of memory.  Directly mapped in the driver,
++ * and can be mapped to userlevel.  Can also be accessed by the NIC.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_iopage {
++	struct efhw_page p;
++	dma_addr_t dma_addr;
++};
++
++static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *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)
++
++/*--------------------------------------------------------------------
++ *
++ * struct efhw_iopages: 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.
++ *
++ *--------------------------------------------------------------------*/
++
++struct efhw_iopages {
++	caddr_t kva;
++	unsigned order;
++	dma_addr_t dma_addr;
++};
++
++static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p)
++{
++	return p->kva;
++}
++
++static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p)
++{
++	return (unsigned)(__pa(p->kva) >> PAGE_SHIFT);
++}
++
++static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p)
++{
++	return p->dma_addr;
++}
++
++static inline unsigned efhw_iopages_size(struct efhw_iopages *p)
++{
++	return 1u << (p->order + PAGE_SHIFT);
++}
++
++/* struct efhw_iopage <-> struct efhw_iopages 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 struct efhw_iopage 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(struct efhw_iopage *iopage,
++			      struct efhw_iopages *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(struct efhw_iopages *iopages,
++			      struct efhw_iopage *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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/nic.h	2008-07-17 16:18: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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/public.h	2008-07-17 16:18: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 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);
++
++/*! Get RX filter search limits from RX_FILTER_CTL_REG.
++ *  use_raw_values = 0 to get actual depth of search, or 1 to get raw values
++ *  from register.
++ */
++extern void
++falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
++				       struct efhw_filter_search_limits *lim,
++				       int use_raw_values);
++
++/*! Set RX filter search limits in RX_FILTER_CTL_REG.
++ *  use_raw_values = 0 if specifying actual depth of search, or 1 if specifying
++ *  raw values to write to the register.
++ */
++extern void
++falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
++				       struct efhw_filter_search_limits *lim,
++				       int use_raw_values);
++
++
++/*! Legacy RX IP filter search depth control interface */
++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);
++
++/*! Legacy RX IP filter search depth control interface */
++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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,55 @@
++/****************************************************************************
++ * 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/module.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++#include <linux/vmalloc.h>
++#include <linux/if_ether.h>
++
++#include <linux/netdevice.h> /* necessary for etherdevice.h on some kernels */
++#include <linux/etherdevice.h>
++
++typedef unsigned long irq_flags_t;
++
++#define spin_lock_destroy(l_)  do {} while (0)
++
++#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h	2008-07-17 16:18: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 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);
++
++
++#endif /* __CI_EFRM_BUDDY_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h	2008-07-17 16:18: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 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);
++
++
++/*--------------------------------------------------------------------
++ *
++ * 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 */
++extern void efrm_buffer_table_commit(void);
++
++extern void efrm_buffer_table_set(struct efhw_buffer_table_allocation *,
++				  struct efhw_nic *,
++				  unsigned i, dma_addr_t dma_addr, int owner);
++
++
++#endif /* __CI_EFRM_BUFFER_TABLE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/debug.h	2008-07-17 16:18: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 __func__ 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 !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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,89 @@
++/****************************************************************************
++ * 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
++ *
++ *--------------------------------------------------------------------*/
++
++struct efrm_nic;
++
++extern void efrm_driver_ctor(void);
++extern void efrm_driver_dtor(void);
++extern int efrm_driver_register_nic(struct efrm_nic *, int nic_index,
++				    int ifindex);
++extern int efrm_driver_unregister_nic(struct efrm_nic *);
++
++/*--------------------------------------------------------------------
++ *
++ * create/destroy resource managers
++ *
++ *--------------------------------------------------------------------*/
++
++struct vi_resource_dimensions {
++	unsigned evq_int_min, evq_int_lim;
++	unsigned evq_timer_min, evq_timer_lim;
++	unsigned rxq_min, rxq_lim;
++	unsigned txq_min, txq_lim;
++};
++
++/*! Initialise resources */
++extern int
++efrm_resources_init(const struct vi_resource_dimensions *,
++		    int buffer_table_min, int buffer_table_lim);
++
++/*! Tear down resources */
++extern void efrm_resources_fini(void);
++
++#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,32 @@
++#ifndef __EFRM_CLIENT_H__
++#define __EFRM_CLIENT_H__
++
++
++struct efrm_client;
++
++
++struct efrm_client_callbacks {
++	/* Called before device is reset.  Callee may block. */
++	void (*pre_reset)(struct efrm_client *, void *user_data);
++	void (*stop)(struct efrm_client *, void *user_data);
++	void (*restart)(struct efrm_client *, void *user_data);
++};
++
++
++#define EFRM_IFINDEX_DEFAULT  -1
++
++
++/* NB. Callbacks may be invoked even before this returns. */
++extern int  efrm_client_get(int ifindex, struct efrm_client_callbacks *,
++			    void *user_data, struct efrm_client **client_out);
++extern void efrm_client_put(struct efrm_client *);
++
++extern struct efhw_nic *efrm_client_get_nic(struct efrm_client *);
++
++#if 0
++/* For each resource type... */
++extern void efrm_x_resource_resume(struct x_resource *);
++#endif
++
++
++#endif  /* __EFRM_CLIENT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,26 @@
++#ifndef __EFRM_NIC_H__
++#define __EFRM_NIC_H__
++
++#include <ci/efhw/efhw_types.h>
++
++
++struct efrm_nic_per_vi {
++	unsigned long state;
++	struct vi_resource *vi;
++};
++
++
++struct efrm_nic {
++	struct efhw_nic efhw_nic;
++	struct list_head link;
++	struct list_head clients;
++	struct efrm_nic_per_vi *vis;
++};
++
++
++#define efrm_nic(_efhw_nic)				\
++  container_of(_efhw_nic, struct efrm_nic, efhw_nic)
++
++
++
++#endif  /* __EFRM_NIC_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/filter.h	2008-07-17 16:18: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 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/efhw/common.h>
++
++
++struct filter_resource;
++struct vi_resource;
++struct efrm_client;
++
++
++/*!
++ * 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);
++
++extern void
++efrm_filter_resource_release(struct filter_resource *);
++
++
++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);
++}
++
++
++extern int
++efrm_filter_resource_instance(struct filter_resource *);
++
++extern struct efrm_resource *
++efrm_filter_resource_to_resource(struct filter_resource *);
++
++extern struct filter_resource *
++efrm_filter_resource_from_resource(struct efrm_resource *);
++
++extern void
++efrm_filter_resource_free(struct filter_resource *);
++
++
++#endif /* __CI_EFRM_FILTER_H__ */
++/*! \cidoxg_end */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,110 @@
++/****************************************************************************
++ * 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 iobufset_resource *linked;
++	struct efhw_buffer_table_allocation buf_tbl_alloc;
++	unsigned int n_bufs;
++	unsigned int pages_per_contiguous_chunk;
++	unsigned chunk_order;
++	struct efhw_iopage 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        VI that "owns" these buffers. Grabs a reference
++ *                  on success.
++ * \param linked    Uses memory from an existing iobufset.  Grabs a
++ *                  reference 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,
++			     struct iobufset_resource *linked,
++			     bool phys_addr_mode,
++			     struct iobufset_resource **iobrs_out);
++
++extern void efrm_iobufset_resource_free(struct iobufset_resource *);
++extern void efrm_iobufset_resource_release(struct iobufset_resource *);
++
++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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h	2008-07-17 16:18: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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h	2008-07-17 16:18: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_tablep;
++
++static inline void efrm_nic_table_hold(void)
++{
++	atomic_inc(&efrm_nic_tablep->ref_count);
++}
++
++static inline void efrm_nic_table_rele(void)
++{
++	atomic_dec(&efrm_nic_tablep->ref_count);
++}
++
++static inline int efrm_nic_table_held(void)
++{
++	return atomic_read(&efrm_nic_tablep->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_tablep->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_tablep->nic[_i]) &&		\
++		    efrm_nic_set_read((_set), (_i)))
++
++#endif /* __CI_EFRM_NIC_TABLE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/private.h	2008-07-17 16:18: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 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 *);
++
++
++/*--------------------------------------------------------------------
++ *
++ * 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);
++
++extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm);
++
++
++#endif /* __CI_EFRM_PRIVATE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/resource.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,119 @@
++/****************************************************************************
++ * 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 {
++	int rs_ref_count;
++	efrm_resource_handle_t rs_handle;
++	struct efrm_client *rs_client;
++	struct list_head rs_client_link;
++	struct list_head rs_manager_link;
++};
++
++/*--------------------------------------------------------------------
++ *
++ * 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;
++	struct list_head rm_resources_list;
++	/**
++	 * 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
++
++
++extern void efrm_resource_ref(struct efrm_resource *rs);
++extern int  __efrm_resource_release(struct efrm_resource *);
++
++
++#endif /* __CI_EFRM_RESOURCE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h	2008-07-17 16:18: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 {
++	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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,46 @@
++/****************************************************************************
++ * 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>
++
++#include <ci/efrm/sysdep_linux.h>
++
++#endif /* __CI_EFRM_SYSDEP_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h	2008-07-17 16:18: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 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/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>
++#include <linux/log2.h>
++#include <linux/kfifo.h>
++
++
++/********************************************************************
++ *
++ * List API
++ *
++ ********************************************************************/
++
++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;
++}
++
++/********************************************************************
++ *
++ * Kfifo API
++ *
++ ********************************************************************/
++
++static inline void kfifo_vfree(struct kfifo *fifo)
++{
++	vfree(fifo->buffer);
++	kfree(fifo);
++}
++
++#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,157 @@
++/****************************************************************************
++ * 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 efrm_client *client,
++		       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);
++
++extern void efrm_vi_resource_free(struct vi_resource *);
++extern void efrm_vi_resource_release(struct vi_resource *);
++
++
++/*--------------------------------------------------------------------
++ *
++ * eventq handling
++ *
++ *--------------------------------------------------------------------*/
++
++/*! Reset an event queue and clear any associated timers */
++extern void efrm_eventq_reset(struct vi_resource *virs);
++
++/*! 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);
++
++/*! 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 */);
++
++
++/* Fill [out_vi_data] with information required to allow a VI to be init'd.
++ * [out_vi_data] must ref at least VI_MAPPINGS_SIZE bytes.
++ */
++extern void efrm_vi_resource_mappings(struct vi_resource *, void *out_vi_data);
++
++
++#endif /* __CI_EFRM_VI_RESOURCE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h	2008-07-17 16:18: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 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>
++
++
++#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))
++
++
++/*! 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;
++
++	/* 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;
++	struct workqueue_struct *workqueue;
++};
++
++struct vi_resource_nic_info {
++	struct eventq_resource_hardware evq_pages;
++	struct efhw_iopages dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT];
++};
++
++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. */
++
++	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;
++	int rx_flushing;
++	int rx_flush_outstanding;
++	int tx_flushing;
++	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 */
++
++	 struct efhw_buffer_table_allocation
++	    dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT];
++
++	struct vi_resource_nic_info nic_info;
++};
++
++#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)
++{
++	struct eventq_resource_hardware *hw;
++	hw = &virs->nic_info.evq_pages;
++	return efhw_iopages_dma_addr(&hw->iobuff) + hw->iobuff_off;
++}
++
++#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,65 @@
++/****************************************************************************
++ * 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);
++
++/*! Wakeup handler */
++extern void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned id);
++
++/*! Timeout handler */
++extern void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned id);
++
++/*! DMA flush handler */
++extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, unsigned id,
++				   int rx_flush);
++
++/*! SRAM update handler */
++extern void efrm_handle_sram_event(struct efhw_nic *nic);
++
++#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/driver_object.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,328 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/efrm_client.h>
++#include <ci/efrm/efrm_nic.h>
++#include "efrm_internal.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_tablep->lock, irqlock_state)
++
++#define efrm_driver_unlock(irqlock_state)		\
++	spin_unlock_irqrestore(&efrm_nic_tablep->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 */
++static struct efrm_nic_table efrm_nic_table;
++struct efrm_nic_table *efrm_nic_tablep;
++EXPORT_SYMBOL(efrm_nic_tablep);
++
++
++/* 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);
++
++
++/* List of registered nics. */
++static LIST_HEAD(efrm_nics);
++
++
++void efrm_driver_ctor(void)
++{
++	efrm_nic_tablep = &efrm_nic_table;
++	spin_lock_init(&efrm_nic_tablep->lock);
++	EFRM_TRACE("%s: driver created", __func__);
++}
++
++void efrm_driver_dtor(void)
++{
++	EFRM_ASSERT(!efrm_nic_table_held());
++
++	spin_lock_destroy(&efrm_nic_tablep->lock);
++	memset(&efrm_nic_table, 0, sizeof(efrm_nic_table));
++	memset(&efrm_rm_table, 0, sizeof(efrm_rm_table));
++	EFRM_TRACE("%s: driver deleted", __func__);
++}
++
++int efrm_driver_register_nic(struct efrm_nic *rnic, int nic_index,
++			     int ifindex)
++{
++	struct efhw_nic *nic = &rnic->efhw_nic;
++	struct efrm_nic_per_vi *vis;
++	int max_vis, rc = 0;
++	irq_flags_t lock_flags;
++
++	EFRM_ASSERT(nic_index >= 0);
++	EFRM_ASSERT(ifindex >= 0);
++
++	max_vis = 4096; /* TODO: Get runtime value. */
++	vis = vmalloc(max_vis * sizeof(rnic->vis[0]));
++	if (vis == NULL) {
++		EFRM_ERR("%s: Out of memory", __func__);
++		return -ENOMEM;
++	}
++
++	efrm_driver_lock(lock_flags);
++
++	if (efrm_nic_table_held()) {
++		EFRM_ERR("%s: driver object is in use", __func__);
++		rc = -EBUSY;
++		goto done;
++	}
++
++	if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
++		EFRM_ERR("%s: filled up NIC table size %d", __func__,
++			 EFHW_MAX_NR_DEVS);
++		rc = -E2BIG;
++		goto done;
++	}
++
++	rnic->vis = vis;
++
++	EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == NULL);
++	efrm_nic_tablep->nic[nic_index] = nic;
++	nic->index = nic_index;
++	nic->ifindex = ifindex;
++
++	if (efrm_nic_tablep->a_nic == NULL)
++		efrm_nic_tablep->a_nic = nic;
++
++	efrm_nic_tablep->nic_count++;
++
++	INIT_LIST_HEAD(&rnic->clients);
++	list_add(&rnic->link, &efrm_nics);
++
++	efrm_driver_unlock(lock_flags);
++	return 0;
++
++done:
++	efrm_driver_unlock(lock_flags);
++	vfree(vis);
++	return rc;
++}
++
++int efrm_driver_unregister_nic(struct efrm_nic *rnic)
++{
++	struct efhw_nic *nic = &rnic->efhw_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_ERR("%s: driver object is in use", __func__);
++		rc = -EBUSY;
++		goto done;
++	}
++	if (!list_empty(&rnic->clients)) {
++		EFRM_ERR("%s: nic has active clients", __func__);
++		rc = -EBUSY;
++		goto done;
++	}
++
++	EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == nic);
++	EFRM_ASSERT(list_empty(&rnic->clients));
++
++	list_del(&rnic->link);
++
++	nic->index = -1;
++	efrm_nic_tablep->nic[nic_index] = NULL;
++
++	--efrm_nic_tablep->nic_count;
++
++	if (efrm_nic_tablep->a_nic == nic) {
++		if (efrm_nic_tablep->nic_count == 0) {
++			efrm_nic_tablep->a_nic = NULL;
++		} else {
++			for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS;
++			     nic_index++) {
++				if (efrm_nic_tablep->nic[nic_index] != NULL)
++					efrm_nic_tablep->a_nic =
++					    efrm_nic_tablep->nic[nic_index];
++			}
++			EFRM_ASSERT(efrm_nic_tablep->a_nic);
++		}
++	}
++
++done:
++	efrm_driver_unlock(lock_flags);
++	return rc;
++}
++
++
++int efrm_nic_pre_reset(struct efhw_nic *nic)
++{
++	struct efrm_nic *rnic = efrm_nic(nic);
++	struct efrm_client *client;
++	struct efrm_resource *rs;
++	struct list_head *client_link;
++	struct list_head *rs_link;
++	irq_flags_t lock_flags;
++
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	list_for_each(client_link, &rnic->clients) {
++		client = container_of(client_link, struct efrm_client, link);
++		EFRM_ERR("%s: client %p", __func__, client);
++		if (client->callbacks->pre_reset)
++			client->callbacks->pre_reset(client, client->user_data);
++		list_for_each(rs_link, &client->resources) {
++			rs = container_of(rs_link, struct efrm_resource,
++					  rs_client_link);
++			EFRM_ERR("%s: resource %p", __func__, rs);
++			/* TODO: mark rs defunct */
++		}
++	}
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++
++	return 0;
++}
++
++
++int efrm_nic_stop(struct efhw_nic *nic)
++{
++	/* TODO */
++	return 0;
++}
++
++
++int efrm_nic_resume(struct efhw_nic *nic)
++{
++	/* TODO */
++	return 0;
++}
++
++
++static void efrm_client_nullcb(struct efrm_client *client, void *user_data)
++{
++}
++
++static struct efrm_client_callbacks efrm_null_callbacks = {
++	efrm_client_nullcb,
++	efrm_client_nullcb,
++	efrm_client_nullcb
++};
++
++
++int efrm_client_get(int ifindex, struct efrm_client_callbacks *callbacks,
++		    void *user_data, struct efrm_client **client_out)
++{
++	struct efrm_nic *n, *rnic = NULL;
++	irq_flags_t lock_flags;
++	struct list_head *link;
++	struct efrm_client *client;
++
++	if (callbacks == NULL)
++		callbacks = &efrm_null_callbacks;
++
++	client = kmalloc(sizeof(*client), GFP_KERNEL);
++	if (client == NULL)
++		return -ENOMEM;
++
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	list_for_each(link, &efrm_nics) {
++		n = container_of(link, struct efrm_nic, link);
++		if (n->efhw_nic.ifindex == ifindex || ifindex < 0) {
++			rnic = n;
++			break;
++		}
++	}
++	if (rnic) {
++		client->user_data = user_data;
++		client->callbacks = callbacks;
++		client->nic = &rnic->efhw_nic;
++		client->ref_count = 1;
++		INIT_LIST_HEAD(&client->resources);
++		list_add(&client->link, &rnic->clients);
++	}
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++
++	if (rnic == NULL)
++		return -ENODEV;
++
++	*client_out = client;
++	return 0;
++}
++EXPORT_SYMBOL(efrm_client_get);
++
++
++void efrm_client_put(struct efrm_client *client)
++{
++	irq_flags_t lock_flags;
++
++	EFRM_ASSERT(client->ref_count > 0);
++
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	if (--client->ref_count > 0)
++		client = NULL;
++	else
++		list_del(&client->link);
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++	kfree(client);
++}
++EXPORT_SYMBOL(efrm_client_put);
++
++
++struct efhw_nic *efrm_client_get_nic(struct efrm_client *client)
++{
++	return client->nic;
++}
++EXPORT_SYMBOL(efrm_client_get_nic);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/driverlink_new.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,260 @@
++/****************************************************************************
++ * 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>
++#include <net/net_namespace.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_lim = res->evq_timer_lim;
++	rd->evq_int_min = res->evq_int_min;
++	rd->evq_int_lim = res->evq_int_lim;
++	rd->rxq_min = res->rxq_min;
++	rd->rxq_lim = res->rxq_lim;
++	rd->txq_min = res->txq_min;
++	rd->txq_lim = res->txq_lim;
++	EFRM_TRACE
++	    ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)",
++	     res->evq_int_min, res->evq_int_lim, res->evq_timer_min,
++	     res->evq_timer_lim, res->rxq_min, res->rxq_lim, res->txq_min,
++	     res->txq_lim);
++}
++
++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 non_irq_evq;
++	int rc;
++
++	efrm_dev->priv = NULL;
++
++	efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES,
++				  struct efx_dl_falcon_resources,
++				  hdr, res);
++
++	if (res == NULL) {
++		EFRM_ERR("%s: Unable to find falcon driverlink resources",
++			 __func__);
++		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;
++
++		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.", __func__);
++			return -ENODEV;
++		}
++		pci_dev_put(dev);
++	}
++
++	init_vi_resource_dimensions(&res_dim, res);
++
++	EFRM_ASSERT(res_dim.evq_timer_lim > res_dim.evq_timer_min);
++	res_dim.evq_timer_lim--;
++	non_irq_evq = res_dim.evq_timer_lim;
++
++	rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic,
++			  res->biu_lock,
++			  res->buffer_table_min, res->buffer_table_lim,
++			  non_irq_evq, &res_dim);
++	if (rc != 0)
++		return rc;
++
++	nic = &lnic->efrm_nic.efhw_nic;
++	nic->mtu = net_dev->mtu + ETH_HLEN;
++	nic->net_driver_dev = efrm_dev;
++	nic->ifindex = net_dev->ifindex;
++#ifdef CONFIG_NET_NS
++	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)", __func__);
++		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)",
++			 __func__, 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", __func__);
++	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", __func__);
++}
++
++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev)
++{
++	EFRM_NOTICE("%s:", __func__);
++}
++
++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok)
++{
++	EFRM_NOTICE("%s: ok=%d", __func__, ok);
++}
++
++int efrm_driverlink_register(void)
++{
++	EFRM_TRACE("%s:", __func__);
++	return efx_dl_register_driver(&efrm_dl_driver);
++}
++
++void efrm_driverlink_unregister(void)
++{
++	EFRM_TRACE("%s:", __func__);
++	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", __func__, 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", __func__,
++			  (unsigned)FALCON_EVENT_CODE(ev));
++		break;
++	}
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/efrm_internal.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,41 @@
++#ifndef __EFRM_INTERNAL_H__
++#define __EFRM_INTERNAL_H__
++
++
++struct filter_resource {
++	struct efrm_resource rs;
++	struct vi_resource *pt;
++	int filter_idx;
++};
++
++#define filter_resource(rs1)  container_of((rs1), struct filter_resource, rs)
++
++
++struct efrm_client {
++	void *user_data;
++	struct list_head link;
++	struct efrm_client_callbacks *callbacks;
++	struct efhw_nic *nic;
++	int ref_count;
++	struct list_head resources;
++};
++
++
++extern void efrm_client_add_resource(struct efrm_client *,
++				     struct efrm_resource *);
++
++extern int efrm_buffer_table_size(void);
++
++
++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);
++	rs->rs_ref_count = 1;
++	rs->rs_handle.handle = (type << 28u) |
++		(((unsigned)jiffies & 0xfff) << 16) | instance;
++}
++
++
++#endif  /* __EFRM_INTERNAL_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/efx_vi_shm.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,707 @@
++/****************************************************************************
++ * 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/vi_resource_manager.h>
++#include <ci/driver/resource/efx_vi.h>
++#include <ci/efrm/filter.h>
++#include <ci/efrm/buffer_table.h>
++#include <ci/efrm/efrm_client.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 ifindex;
++	struct efrm_client *efrm_client;
++	struct efhw_nic *nic;
++
++	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(state->efrm_client, 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",
++			 __func__, 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",
++			     __func__, 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 ifindex)
++{
++	struct efx_vi_state *efx_state;
++	int rc;
++
++	efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL);
++
++	if (!efx_state) {
++		EFRM_ERR("%s: failed to allocate memory for efx_vi_state",
++			 __func__);
++		rc = -ENOMEM;
++		goto fail;
++	}
++
++	efx_state->ifindex = ifindex;
++	rc = efrm_client_get(ifindex, NULL, NULL, &efx_state->efrm_client);
++	if (rc < 0) {
++		EFRM_ERR("%s: efrm_client_get(%d) failed: %d", __func__,
++			 ifindex, rc);
++		rc = -ENODEV;
++		goto fail_no_ifindex;
++	}
++	efx_state->nic = efrm_client_get_nic(efx_state->efrm_client);
++
++	init_completion(&efx_state->flush_completion);
++
++	/* basically allocate_pt_endpoint() */
++	rc = alloc_ep(efx_state);
++	if (rc) {
++		EFRM_ERR("%s: alloc_ep failed: %d", __func__, 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:
++	efrm_client_put(efx_state->efrm_client);
++fail_no_ifindex:
++	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);
++
++	efrm_client_put(efx_state->efrm_client);
++
++	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);
++	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)", __func__, 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(efx_state->nic)->
++					  pci_dev, pages[i], 0, PAGE_SIZE,
++					PCI_DMA_TODEVICE);
++
++		efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic,
++				      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)", __func__, 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",
++		  __func__, 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, efx_state->nic,
++				      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(efx_state->nic)->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", __func__);
++#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 *uninitialized_var(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!", __func__);
++
++	return 0;
++}
++EXPORT_SYMBOL(efx_vi_hw_resource_get_virt);
++
++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;
++	struct linux_efhw_nic *lnic = linux_efhw_nic(efx_state->nic);
++	unsigned long phys = lnic->ctr_ap_pci_addr;
++	struct efrm_resource *ep_res = &efx_state->vi_res->rs;
++	unsigned ep_mmap_bytes;
++	int i;
++
++	if (*length < EFX_VI_HW_RESOURCE_MAXSIZE)
++		return -EINVAL;
++
++	mdata->nic_arch = efx_state->nic->devtype.arch;
++	mdata->nic_variant = efx_state->nic->devtype.variant;
++	mdata->nic_revision = efx_state->nic->devtype.revision;
++
++	mdata->evq_order =
++	    efx_state->vi_res->nic_info.evq_pages.iobuff.order;
++	mdata->evq_offs = efx_state->vi_res->nic_info.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.
++			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.
++			dmaq_pages[EFRM_VI_RM_DMA_QUEUE_RX].kva;
++
++	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 (efx_state->nic->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.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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/eventq.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,321 @@
++/****************************************************************************
++ * 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",
++			  __func__, 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", __func__, 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,
++				    1 /* interrupting */);
++
++	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", __func__, 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]", __func__, 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", __func__, instance);
++
++	if (!h->dmaq_flushed_fn) {
++		EFHW_WARN("%s: no handler registered", __func__);
++		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)
++{
++	unsigned instance = (unsigned)FALCON_EVENT_RX_FLUSH_Q_ID(evp);
++	EFHW_TRACE("%s: instance=%d", __func__, instance);
++
++	if (!h->dmaq_flushed_fn) {
++		EFHW_WARN("%s: no handler registered", __func__);
++		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)
++{
++	unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
++
++	if (!h->wakeup_fn) {
++		EFHW_WARN("%s: no handler registered", __func__);
++		return;
++	}
++
++	h->wakeup_fn(nic, instance);
++}
++
++void
++efhw_handle_timeout_event(struct efhw_nic *nic, struct efhw_ev_handler *h,
++			  efhw_event_t *evp)
++{
++	unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp);
++
++	if (!h->timeout_fn) {
++		EFHW_WARN("%s: no handler registered", __func__);
++		return;
++	}
++
++	h->timeout_fn(nic, instance);
++}
++
++/**********************************************************************
++ * 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!", __func__, 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)) {
++
++			case FALCON_EVENT_CODE_CHAR:
++				falcon_handle_char_event(nic, q->ev_handlers,
++							 ev);
++				break;
++
++			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:
++	/* 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);
++	return count;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/falcon.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,2525 @@
++/****************************************************************************
++ * 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
++ *
++ *---------------------------------------------------------------------------*/
++
++/* Keep a software copy of the filter table and check for duplicates. */
++#define FALCON_FULL_FILTER_CACHE 1
++
++/* Read filters back from the hardware to detect corruption. */
++#define FALCON_VERIFY_FILTERS    0
++
++/* 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 FALCON_MAC_SET_TYPE_BY_SPEED           0
++
++/* FIXME: We should detect mode at runtime. */
++#define FALCON_BUFFER_TABLE_FULL_MODE          1
++
++/* "Fudge factors" - difference between programmed value and actual depth */
++#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 TX_FILTER_CTL_SRCH_FUDGE_WILD 3	/* increase the search limit */
++#define TX_FILTER_CTL_SRCH_FUDGE_FULL 1	/* increase the search limit */
++
++/*----------------------------------------------------------------------------
++ *
++ * Debug Macros
++ *
++ *---------------------------------------------------------------------------*/
++
++#define _DEBUG_SYM_ static
++
++ /*----------------------------------------------------------------------------
++  *
++  * 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
++
++
++/*----------------------------------------------------------------------------
++ *
++ * 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
++
++*/
++
++
++/*----------------------------------------------------------------------------
++ *
++ * 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 < nic->num_dmaqs);
++	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;
++	volatile char __iomem *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",
++				 __func__, 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,
++		   __func__,
++		   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 < nic->num_dmaqs);
++	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;
++	volatile char __iomem *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,
++		   __func__,
++		   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;
++	volatile char __iomem *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,
++		   __func__, 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;
++	volatile char __iomem *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;
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++	volatile char __iomem *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]: %lx:%x:%" PRIx64 "->%x = %"
++		   PRIx64, __func__, buffer_id, (unsigned long) 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", __func__);
++				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)
++{
++	volatile char __iomem *offset;
++	uint64_t entry;
++	volatile char __iomem *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]: %lx:bufsz=%x:region=%x:ownid=%x",
++		   __func__, buffer_id, (unsigned long) dma_addr, bufsz,
++		   region, own_id);
++
++	EFHW_TRACE("%s: BUF[%x]:NIC[%x]->%" PRIx64,
++		   __func__, 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")",
++					  __func__, 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 */
++	volatile char __iomem *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;
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++
++	volatile char __iomem *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;
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++
++	EFHW_BUILD_ASSERT(SRM_UPD_EVQ_REG_OFST == SRM_UPD_EVQ_REG_KER_OFST);
++
++	__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 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;
++	volatile char __iomem *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 < nic->num_evqs);
++
++	offset = EVQ_PTR_TBL_CHAR_OFST;
++	offset += evq * FALCON_REGISTER128;
++
++	EFHW_TRACE("%s: evq %u en=%x:buf=%x:size=%x->%x at %lx",
++		   __func__, 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;
++	volatile char __iomem *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 < nic->num_evqs);
++
++	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", __func__, evq, rptr, wakeup, val);
++
++	writel(val, efhw_kva + offset);
++	mmiowb();
++}
++
++/*---------------------------------------------------------------------------*/
++
++static inline void
++falcon_drv_ev(struct efhw_nic *nic, uint64_t data, uint qid)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *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_ab_timer_tbl_set(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;
++	volatile char __iomem *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 < nic->num_evqs);
++
++	EFHW_TRACE("%s: evq %u mode %x (%s) time %x -> %08x",
++		   __func__, 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;
++	volatile char __iomem *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",
++		   __func__, dmaq, offset, pace);
++}
++
++/*--------------------------------------------------------------------
++ *
++ * Interrupt - Low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++static void falcon_nic_handle_fatal_int(struct efhw_nic *nic)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *offset;
++	volatile char __iomem *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;
++	volatile char __iomem *offset;
++	volatile char __iomem *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", __func__, (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;
++	volatile char __iomem *offset;
++	volatile char __iomem *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", __func__, (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);
++}
++
++static void falcon_nic_irq_addr_set(struct efhw_nic *nic, dma_addr_t dma_addr)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *offset;
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++
++	offset = (efhw_kva + INT_ADR_REG_CHAR_OFST);
++
++	EFHW_NOTICE("%s: %x -> " DMA_ADDR_T_FMT, __func__,
++		    (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);
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * RXDP - low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++void
++falcon_nic_set_rx_usr_buf_size(struct efhw_nic *nic, int usr_buf_bytes)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *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);
++
++
++/*--------------------------------------------------------------------
++ *
++ * TXDP - low level interface
++ *
++ *--------------------------------------------------------------------*/
++
++_DEBUG_SYM_ void falcon_nic_tx_cfg(struct efhw_nic *nic, int unlocked)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *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)
++ *
++ *--------------------------------------------------------------------*/
++
++void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base, int bin_thresh)
++{
++	FALCON_LOCK_DECL;
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++	unsigned offset = 0;
++	uint64_t val;
++
++	__DWCHCK(TX_PACE_FB_BASE_LBN, TX_PACE_FB_BASE_WIDTH);
++	__DWCHCK(TX_PACE_BIN_TH_LBN, TX_PACE_BIN_TH_WIDTH);
++
++	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;
++	}
++
++	val = (0x15 << TX_PACE_SB_NOTAF_LBN);
++	val |= (0xb << TX_PACE_SB_AF_LBN);
++
++	val |= ((fb_base & __FALCON_MASK64(TX_PACE_FB_BASE_WIDTH)) <<
++		 TX_PACE_FB_BASE_LBN);
++	val |= ((bin_thresh & __FALCON_MASK64(TX_PACE_BIN_TH_WIDTH)) <<
++		 TX_PACE_BIN_TH_LBN);
++
++	/* Falcon requires 128 bit atomic access for this register */
++	FALCON_LOCK_LOCK(nic);
++	falcon_write_qq(efhw_kva + offset, val, 0);
++	mmiowb();
++	FALCON_LOCK_UNLOCK(nic);
++}
++
++
++/**********************************************************************
++ * Implementation of the HAL. ********************************************
++ **********************************************************************/
++
++/*----------------------------------------------------------------------------
++ *
++ * Initialisation and configuration discovery
++ *
++ *---------------------------------------------------------------------------*/
++
++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: %lx %sable", __func__,
++		   (unsigned long) efhw_iopage_dma_addr(&nic->irq_iobuff),
++		   enable ? "en" : "dis");
++
++	return 0;
++}
++
++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);
++	falcon_nic_filter_dtor(nic);
++
++	EFHW_NOTICE("%s:", __func__);
++}
++
++static int
++falcon_nic_init_hardware(struct efhw_nic *nic,
++			 struct efhw_ev_handler *ev_handlers,
++			 const uint8_t *mac_addr, int non_irq_evq)
++{
++	int rc;
++
++	/* header sanity checks */
++	FALCON_ASSERT_VALID();
++
++	/* Initialise supporting modules */
++	rc = falcon_nic_filter_ctor(nic);
++	if (rc < 0)
++		return rc;
++
++#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:", __func__);
++
++	/* 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 = 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, non_irq_evq);
++
++	/* 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, 4, 2);
++
++	/* ?? 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->interrupting_evq, ev_handlers);
++		if (rc < 0) {
++			EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
++				 __func__, rc, FALCON_EVQ_CHAR);
++			return rc;
++		}
++	}
++	rc = efhw_keventq_ctor(nic, non_irq_evq,
++			       &nic->non_interrupting_evq, NULL);
++	if (rc < 0) {
++		EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d",
++			 __func__, rc, non_irq_evq);
++		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)
++{
++	struct efhw_keventq *q;
++	unsigned rdptr;
++
++	if (nic->flags & NIC_FLAG_NO_INTERRUPT)
++		return;
++
++	/* Enable driver interrupts */
++	EFHW_NOTICE("%s: enable master interrupt", __func__);
++	falcon_nic_interrupt_hw_enable(nic);
++
++	/* An interrupting eventq must start of day ack its read pointer */
++	q = &nic->interrupting_evq;
++	rdptr = EFHW_EVENT_OFFSET(q, q, 1) / sizeof(efhw_event_t);
++	falcon_nic_evq_ack(nic, FALCON_EVQ_CHAR, rdptr, false);
++	EFHW_NOTICE("%s: ACK evq[%d]:%x", __func__,
++		    FALCON_EVQ_CHAR, rdptr);
++}
++
++static void falcon_nic_interrupt_disable(struct efhw_nic *nic)
++{
++	/* NB. No need to check for NIC_FLAG_NO_INTERRUPT, as
++	 ** falcon_nic_interrupt_hw_disable() will do it. */
++	falcon_nic_interrupt_hw_disable(nic);
++}
++
++static void
++falcon_nic_set_interrupt_moderation(struct efhw_nic *nic, int evq,
++				    uint32_t val)
++{
++	if (evq < 0)
++		evq = FALCON_EVQ_CHAR;
++
++	falcon_ab_timer_tbl_set(nic, evq, 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)
++{
++	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", __func__,
++			  *(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", __func__, 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, int interrupting)
++{
++	EFHW_ASSERT(nic);
++
++	/* Whether or not queue has an interrupt depends on
++	 * instance number and h/w variant, so [interrupting] is
++	 * ignored.
++	 */
++	falcon_ab_timer_tbl_set(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", __func__, evq, evq_size);
++}
++
++static void
++falcon_nic_event_queue_disable(struct efhw_nic *nic, uint evq, int timer_only)
++{
++	EFHW_ASSERT(nic);
++
++	falcon_ab_timer_tbl_set(nic, evq, 0 /* disable */ , 0);
++
++	if (!timer_only)
++		falcon_nic_evq_ptr_tbl(nic, evq, 0, 0, 0);
++	EFHW_TRACE("%s: disenable evq %u", __func__, 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", __func__, 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", __func__, evq, data);
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * 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)
++{
++	/* 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;
++
++	/* 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", __func__, 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->non_interrupting_evq.ev_handlers = &handler;
++		rc = efhw_keventq_poll(nic, &nic->non_interrupting_evq);
++		nic->non_interrupting_evq.ev_handlers = NULL;
++
++		if (rc < 0) {
++			EFHW_ERR("%s: poll ERROR (%d:%d) ***** ",
++				 __func__, rc,
++				 nic->buf_commit_outstanding);
++			goto out;
++		}
++
++		FALCON_LOCK_UNLOCK(nic);
++
++		if (count++)
++			udelay(1);
++
++		if (count > 1000) {
++			EFHW_WARN("%s: poll Timeout ***** (%d)", __func__,
++				  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;
++
++	/* 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;
++	volatile char __iomem *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;
++	volatile char __iomem *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;
++	volatile char __iomem *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;
++	volatile char __iomem *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, __func__,
++		   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", __func__, 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;
++	volatile char __iomem *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;
++	volatile char __iomem *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", __func__, 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));
++		efhw_handle_txdmaq_flushed(nic, h, ev);
++		break;
++
++	case RX_DESCQ_FLS_DONE_EV_DECODE:
++		EFHW_TRACE("RX[%d] flushed",
++			   (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev));
++		efhw_handle_rxdmaq_flushed(nic, h, ev);
++		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("%sEVQ INIT", "");
++		break;
++
++	case WAKE_UP_EV_DECODE:
++		EFHW_TRACE("%sWAKE UP", "");
++		efhw_handle_wakeup_event(nic, h, ev);
++		break;
++
++	case TIMER_EV_DECODE:
++		EFHW_TRACE("%sTIMER", "");
++		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", __func__);
++		return -EINVAL;
++
++	default:
++		EFHW_TRACE("UNKOWN DRIVER EVENT: " FALCON_EVENT_FMT,
++			   FALCON_EVENT_PRI_ARG(*ev));
++		break;
++	}
++	return 0;
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * Filter search depth control
++ *
++ *--------------------------------------------------------------------*/
++
++
++#define Q0_READ(q0, name) \
++	((unsigned)(((q0) >> name##_LBN) & (__FALCON_MASK64(name##_WIDTH))))
++#define Q0_MASK(name) \
++	((__FALCON_MASK64(name##_WIDTH)) << name##_LBN)
++#define Q0_VALUE(name, value) \
++	(((uint64_t)(value)) << name##_LBN)
++
++#define Q1_READ(q1, name) \
++	((unsigned)(((q1) >> (name##_LBN - 64)) & \
++		    (__FALCON_MASK64(name##_WIDTH))))
++#define Q1_MASK(name) \
++	((__FALCON_MASK64(name##_WIDTH)) << (name##_LBN - 64))
++#define Q1_VALUE(name, value) \
++	(((uint64_t)(value)) << (name##_LBN - 64))
++
++
++void
++falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic,
++				       struct efhw_filter_search_limits *lim,
++				       int use_raw_values)
++{
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++	FALCON_LOCK_DECL;
++	uint64_t q0, q1;
++	unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
++	unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
++
++	FALCON_LOCK_LOCK(nic);
++	falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
++	FALCON_LOCK_UNLOCK(nic);
++
++	lim->tcp_full = Q0_READ(q0, TCP_FULL_SRCH_LIMIT) - ff;
++	lim->tcp_wild = Q0_READ(q0, TCP_WILD_SRCH_LIMIT) - wf;
++	lim->udp_full = Q0_READ(q0, UDP_FULL_SRCH_LIMIT) - ff;
++	lim->udp_wild = Q0_READ(q0, UDP_WILD_SRCH_LIMIT) - wf;
++}
++EXPORT_SYMBOL(falcon_nic_get_rx_filter_search_limits);
++
++
++void
++falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic,
++				       struct efhw_filter_search_limits *lim,
++				       int use_raw_values)
++{
++	volatile char __iomem *efhw_kva = EFHW_KVA(nic);
++	FALCON_LOCK_DECL;
++	uint64_t q0, q1;
++	unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL);
++	unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD);
++
++	FALCON_LOCK_LOCK(nic);
++	falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1);
++
++	q0 &= ~Q0_MASK(TCP_FULL_SRCH_LIMIT);
++	q0 &= ~Q0_MASK(TCP_WILD_SRCH_LIMIT);
++	q0 &= ~Q0_MASK(UDP_FULL_SRCH_LIMIT);
++	q0 &= ~Q0_MASK(UDP_WILD_SRCH_LIMIT);
++	q0 |= Q0_VALUE(TCP_FULL_SRCH_LIMIT, lim->tcp_full + ff);
++	q0 |= Q0_VALUE(TCP_WILD_SRCH_LIMIT, lim->tcp_wild + wf);
++	q0 |= Q0_VALUE(UDP_FULL_SRCH_LIMIT, lim->udp_full + ff);
++	q0 |= Q0_VALUE(UDP_WILD_SRCH_LIMIT, lim->udp_wild + wf);
++	nic->tcp_full_srch.max = lim->tcp_full + ff
++					- RX_FILTER_CTL_SRCH_FUDGE_FULL;
++	nic->tcp_wild_srch.max = lim->tcp_wild + wf
++					- RX_FILTER_CTL_SRCH_FUDGE_WILD;
++	nic->udp_full_srch.max = lim->udp_full + ff
++					- RX_FILTER_CTL_SRCH_FUDGE_FULL;
++	nic->udp_wild_srch.max = lim->udp_wild + wf
++					- RX_FILTER_CTL_SRCH_FUDGE_WILD;
++
++	falcon_write_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, q0, q1);
++	mmiowb();
++	FALCON_LOCK_UNLOCK(nic);
++}
++EXPORT_SYMBOL(falcon_nic_set_rx_filter_search_limits);
++
++
++#undef READ_Q0
++#undef Q0_MASK
++#undef Q0_VALUE
++#undef READ_Q1
++#undef Q1_MASK
++#undef Q1_VALUE
++
++
++/*--------------------------------------------------------------------
++ *
++ * New unified filter API
++ *
++ *--------------------------------------------------------------------*/
++
++
++#if FALCON_FULL_FILTER_CACHE
++static inline struct efhw_filter_spec *
++filter_spec_cache_entry(struct efhw_nic *nic, int filter_idx)
++{
++	EFHW_ASSERT(nic->filter_spec_cache);
++	return &nic->filter_spec_cache[filter_idx];
++}
++#endif
++
++
++static int filter_is_active(struct efhw_nic *nic, int filter_idx)
++{
++	return nic->filter_in_use[filter_idx];
++}
++
++
++static void set_filter_cache_entry(struct efhw_nic *nic,
++				   struct efhw_filter_spec *spec,
++				   int filter_idx)
++{
++	nic->filter_in_use[filter_idx] = 1;
++#if FALCON_FULL_FILTER_CACHE
++	memcpy(filter_spec_cache_entry(nic, filter_idx), spec,
++	       sizeof(struct efhw_filter_spec));
++#endif
++}
++
++
++static void clear_filter_cache_entry(struct efhw_nic *nic,
++				     int filter_idx)
++{
++	nic->filter_in_use[filter_idx] = 0;
++#if FALCON_FULL_FILTER_CACHE
++	memset(filter_spec_cache_entry(nic, filter_idx), 0,
++	       sizeof(struct efhw_filter_spec));
++#endif
++}
++
++
++#if FALCON_FULL_FILTER_CACHE
++static int filter_is_duplicate(struct efhw_nic *nic,
++			       struct efhw_filter_spec *spec, int filter_idx)
++{
++	struct efhw_filter_spec *cmp;
++
++	cmp = filter_spec_cache_entry(nic, filter_idx);
++
++	EFHW_ASSERT(filter_is_active(nic, filter_idx));
++
++	return (spec->saddr_le32 == cmp->saddr_le32) &&
++	       (spec->daddr_le32 == cmp->daddr_le32) &&
++	       (spec->sport_le16 == cmp->sport_le16) &&
++	       (spec->dport_le16 == cmp->dport_le16) &&
++	       (spec->tcp == cmp->tcp) &&
++	       (spec->full == cmp->full);
++}
++#endif
++
++
++static void common_build_ip_filter(struct efhw_nic *nic, int tcp, int full,
++				   int rss, int scatter, 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;
++	unsigned tmp_port_le16;
++
++	if (!full) {
++		saddr_le32 = 0;
++		sport_le16 = 0;
++		if (!tcp) {
++			tmp_port_le16 = sport_le16;
++			sport_le16 = dport_le16;
++			dport_le16 = tmp_port_le16;
++		}
++	}
++
++	v4 = (((!tcp) << __DW4(TCP_UDP_0_LBN)) |
++	      (dmaq_id << __DW4(RXQ_ID_0_LBN)));
++
++	switch (nic->devtype.variant) {
++	case 'A':
++		EFHW_ASSERT(!rss);
++		break;
++	case 'B':
++		v4 |= scatter << __DW4(SCATTER_EN_0_B0_LBN);
++		v4 |= rss << __DW4(RSS_EN_0_B0_LBN);
++		break;
++	default:
++		EFHW_ASSERT(0);
++		break;
++	}
++
++	v3 = daddr_le32;
++	v2 = ((dport_le16 << __DW2(DEST_PORT_TCP_0_LBN)) |
++	      (__HIGH(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)));
++	v1 = ((__LOW(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)) |
++	      (sport_le16 << SRC_TCP_DEST_UDP_0_LBN));
++
++	*q0 = (v2 << 32) | v1;
++	*q1 = (v4 << 32) | v3;
++}
++
++
++static void build_filter(struct efhw_nic *nic, struct efhw_filter_spec *spec,
++			 unsigned *key, unsigned *tbl_size,
++			 struct efhw_filter_depth **depth,
++			 uint64_t *q0, uint64_t *q1)
++{
++	*key = falcon_hash_get_ip_key(spec->saddr_le32,
++				      spec->sport_le16,
++				      spec->daddr_le32,
++				      spec->dport_le16,
++				      spec->tcp,
++				      spec->full);
++	*tbl_size = nic->ip_filter_tbl_size;
++	if (spec->tcp && spec->full)
++		*depth = &nic->tcp_full_srch;
++	else if (spec->tcp && !spec->full)
++		*depth = &nic->tcp_wild_srch;
++	else if (!spec->tcp && spec->full)
++		*depth = &nic->udp_full_srch;
++	else
++		*depth = &nic->udp_wild_srch;
++	common_build_ip_filter(nic, spec->tcp, spec->full,
++			       spec->rss, spec->scatter,
++			       spec->dmaq_id,
++			       spec->saddr_le32,
++			       spec->sport_le16,
++			       spec->daddr_le32,
++			       spec->dport_le16,
++			       q0, q1);
++}
++
++
++#if FALCON_VERIFY_FILTERS
++static void verify_filters(struct efhw_nic *nic)
++{
++	unsigned table_offset, table_stride;
++	unsigned i, dummy_key, dummy_tbl_size;
++	struct efhw_filter_depth *dummy_depth;
++	unsigned filter_tbl_size;
++	struct efhw_filter_spec *spec;
++	uint64_t q0_expect, q1_expect, q0_got, q1_got;
++
++	filter_tbl_size = nic->ip_filter_tbl_size;
++	table_offset = RX_FILTER_TBL0_OFST;
++	table_stride = 2 * FALCON_REGISTER128;
++
++	for (i = 0; i < filter_tbl_size; i++) {
++		if (!filter_is_active(nic, type, i))
++			continue;
++
++		spec = filter_spec_cache_entry(nic, type, i);
++
++		build_filter(nic, spec, &dummy_key, &dummy_tbl_size,
++			     &dummy_depth, &q0_expect, &q1_expect);
++
++		falcon_read_qq(EFHW_KVA(nic) + table_offset + i * table_stride,
++			       &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
++
++
++static void write_filter_table_entry(struct efhw_nic *nic,
++				     unsigned filter_idx,
++				     uint64_t q0, uint64_t q1)
++{
++	unsigned table_offset, table_stride, offset;
++
++	EFHW_ASSERT(filter_idx < nic->ip_filter_tbl_size);
++	table_offset = RX_FILTER_TBL0_OFST;
++	table_stride = 2 * FALCON_REGISTER128;
++
++	offset = table_offset + filter_idx * table_stride;
++	falcon_write_qq(EFHW_KVA(nic) + offset, q0, q1);
++	mmiowb();
++
++#if FALCON_VERIFY_FILTERS
++	{
++		uint64_t q0read, q1read;
++
++		/* Read a different entry first - ensure 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);
++
++		verify_filters(nic, type);
++	}
++#endif
++}
++
++
++static int falcon_nic_filter_set(struct efhw_nic *nic,
++				 struct efhw_filter_spec *spec,
++				 int *filter_idx_out)
++{
++	FALCON_LOCK_DECL;
++	unsigned key = 0, tbl_size = 0, hash1, hash2, k;
++	struct efhw_filter_depth *depth = NULL;
++	int filter_idx = -1;
++	int rc = 0;
++	uint64_t q0, q1;
++
++	build_filter(nic, spec, &key, &tbl_size, &depth, &q0, &q1);
++
++	if (tbl_size == 0)
++		return -EINVAL;
++
++	EFHW_TRACE("%s: depth->max=%d", __func__, depth->max);
++
++	hash1 = falcon_hash_function1(key, tbl_size);
++	hash2 = falcon_hash_function2(key, tbl_size);
++
++	FALCON_LOCK_LOCK(nic);
++
++	for (k = 0; k < depth->max; k++) {
++		filter_idx = falcon_hash_iterator(hash1, hash2, k, tbl_size);
++		if (!filter_is_active(nic, filter_idx))
++			break;
++#if FALCON_FULL_FILTER_CACHE
++		if (filter_is_duplicate(nic, spec, filter_idx)) {
++			EFHW_WARN("%s: ERROR: duplicate filter (disabling "
++				  "interrupts)", __func__);
++			falcon_nic_interrupt_hw_disable(nic);
++			rc = -EINVAL;
++			goto fail1;
++		}
++#endif
++	}
++	if (k == depth->max) {
++		rc = -EADDRINUSE;
++		filter_idx = -1;
++		goto fail1;
++	} else if (depth->needed < (k + 1)) {
++		depth->needed = k + 1;
++	}
++
++	EFHW_ASSERT(filter_idx < (int)tbl_size);
++
++	set_filter_cache_entry(nic, spec, filter_idx);
++	write_filter_table_entry(nic, filter_idx, q0, q1);
++
++	++nic->ip_filter_tbl_used;
++
++	*filter_idx_out = filter_idx;
++
++	EFHW_TRACE("%s: filter index %d rxq %u set in %u",
++		   __func__, filter_idx, spec->dmaq_id, k);
++
++fail1:
++	FALCON_LOCK_UNLOCK(nic);
++	return rc;
++}
++
++
++static void falcon_nic_filter_clear(struct efhw_nic *nic,
++				    int filter_idx)
++{
++	FALCON_LOCK_DECL;
++
++	if (filter_idx < 0)
++		return;
++
++	FALCON_LOCK_LOCK(nic);
++	if (filter_is_active(nic, filter_idx)) {
++		if (--nic->ip_filter_tbl_used == 0) {
++			nic->tcp_full_srch.needed = 0;
++			nic->tcp_wild_srch.needed = 0;
++			nic->udp_full_srch.needed = 0;
++			nic->udp_wild_srch.needed = 0;
++		}
++	}
++	clear_filter_cache_entry(nic, filter_idx);
++	write_filter_table_entry(nic, filter_idx, 0, 0);
++	FALCON_LOCK_UNLOCK(nic);
++}
++
++
++int
++falcon_nic_filter_ctor(struct efhw_nic *nic)
++{
++	nic->ip_filter_tbl_size = 8 * 1024;
++	nic->ip_filter_tbl_used = 0;
++
++	nic->tcp_full_srch.needed = 0;
++	nic->tcp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL
++				   - RX_FILTER_CTL_SRCH_FUDGE_FULL;
++	nic->tcp_wild_srch.needed = 0;
++	nic->tcp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD
++				   - RX_FILTER_CTL_SRCH_FUDGE_WILD;
++	nic->udp_full_srch.needed = 0;
++	nic->udp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL
++				   - RX_FILTER_CTL_SRCH_FUDGE_FULL;
++	nic->udp_wild_srch.needed = 0;
++	nic->udp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD
++				   - RX_FILTER_CTL_SRCH_FUDGE_WILD;
++
++	nic->filter_in_use = vmalloc(FALCON_FILTER_TBL_NUM);
++	if (nic->filter_in_use == NULL)
++		return -ENOMEM;
++	memset(nic->filter_in_use, 0, FALCON_FILTER_TBL_NUM);
++#if FALCON_FULL_FILTER_CACHE
++	nic->filter_spec_cache = vmalloc(FALCON_FILTER_TBL_NUM
++					 * sizeof(struct efhw_filter_spec));
++	if (nic->filter_spec_cache == NULL)
++		return -ENOMEM;
++	memset(nic->filter_spec_cache, 0, FALCON_FILTER_TBL_NUM
++					  * sizeof(struct efhw_filter_spec));
++#endif
++
++	return 0;
++}
++
++
++void
++falcon_nic_filter_dtor(struct efhw_nic *nic)
++{
++#if FALCON_FULL_FILTER_CACHE
++	if (nic->filter_spec_cache)
++		vfree(nic->filter_spec_cache);
++#endif
++	if (nic->filter_in_use)
++		vfree(nic->filter_in_use);
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * Compatibility with old filter API
++ *
++ *--------------------------------------------------------------------*/
++
++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)
++{
++	struct efhw_filter_search_limits lim;
++
++	falcon_nic_get_rx_filter_search_limits(nic, &lim, 0);
++	*tcp_full = (uint32_t)lim.tcp_full;
++	*tcp_wild = (uint32_t)lim.tcp_wild;
++	*udp_full = (uint32_t)lim.udp_full;
++	*udp_wild = (uint32_t)lim.udp_wild;
++}
++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)
++{
++	struct efhw_filter_search_limits lim;
++
++	lim.tcp_full = (unsigned)tcp_full;
++	lim.tcp_wild = (unsigned)tcp_wild;
++	lim.udp_full = (unsigned)udp_full;
++	lim.udp_wild = (unsigned)udp_wild;
++	falcon_nic_set_rx_filter_search_limits(nic, &lim, 0);
++}
++EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_set);
++
++
++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)
++{
++	struct efhw_filter_spec spec;
++
++	spec.dmaq_id = dmaq;
++	spec.saddr_le32 = ntohl(saddr_be32);
++	spec.daddr_le32 = ntohl(daddr_be32);
++	spec.sport_le16 = ntohs((unsigned short) sport_be16);
++	spec.dport_le16 = ntohs((unsigned short) dport_be16);
++	spec.tcp = ((type & EFHW_IP_FILTER_TYPE_TCP_MASK) != 0);
++	spec.full = ((type & EFHW_IP_FILTER_TYPE_FULL_MASK) != 0);
++	spec.rss = ((type & EFHW_IP_FILTER_TYPE_RSS_B0_MASK) != 0);
++	spec.scatter = ((type & EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK) == 0);
++	return falcon_nic_filter_set(nic, &spec, _filter_idx);
++}
++
++static void falcon_nic_ipfilter_clear(struct efhw_nic *nic, int filter_idx)
++{
++	falcon_nic_filter_clear(nic, filter_idx);
++}
++
++
++/*--------------------------------------------------------------------
++ *
++ * 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_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,
++	falcon_nic_filter_set,
++	falcon_nic_filter_clear,
++};
++
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/falcon_hash.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,159 @@
++/****************************************************************************
++ * 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>
++
++
++static unsigned int
++common_get_ip_key(unsigned int src_ip, unsigned int src_port,
++		  unsigned int dest_ip, unsigned int dest_port,
++		  int tcp, int full, int tx, unsigned int masked_q_id)
++{
++
++	unsigned int tmp_port, result;
++
++	EFHW_ASSERT(tcp == 0 || tcp == 1);
++	EFHW_ASSERT(full == 0 || full == 1);
++	EFHW_ASSERT(masked_q_id < (1 << 10));
++
++	/* m=masked_q_id(TX)/0(RX)  u=UDP  S,D=src/dest addr  s,d=src/dest port
++	 *
++	 * Wildcard filters have src(TX)/dest(RX) addr and port = 0;
++	 * and UDP wildcard filters have the src and dest port fields swapped.
++	 *
++	 * Addr/port fields are little-endian.
++	 *
++	 * 3322222222221111111111
++	 * 10987654321098765432109876543210
++	 *
++	 * 000000000000000000000mmmmmmmmmmu ^
++	 * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ^
++	 * ddddddddddddddddSSSSSSSSSSSSSSSS ^
++	 * SSSSSSSSSSSSSSSSssssssssssssssss
++	 */
++
++	if (!tx)
++		masked_q_id = 0;
++
++	if (!full) {
++		if (tx) {
++			dest_ip = 0;
++			dest_port = 0;
++		} else {
++			src_ip = 0;
++			src_port = 0;
++		}
++		if (!tcp) {
++			tmp_port = src_port;
++			src_port = dest_port;
++			dest_port = tmp_port;
++		}
++	}
++
++	result = ((masked_q_id << 1) | (!tcp))                              ^
++		 (dest_ip)                                                  ^
++		 (((dest_port & 0xffff) << 16) | ((src_ip >> 16) & 0xffff)) ^
++		 (((src_ip & 0xffff) << 16) | (src_port & 0xffff));
++
++	EFHW_TRACE("%s: IP %s %s %x", __func__, tcp ? "TCP" : "UDP",
++		   full ? "Full" : "Wildcard", result);
++
++	return result;
++}
++
++
++unsigned int
++falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port,
++		       unsigned int dest_ip, unsigned int dest_port,
++		       int tcp, int full)
++{
++	return common_get_ip_key(src_ip, src_port, dest_ip, dest_port, tcp,
++				 full, 0, 0);
++}
++
++
++/* 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 & (nfilters - 1);
++
++	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) &
++			      (nfilters - 1));
++}
++
++/* 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)) & (nfilters - 1);
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/filter_resource.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,250 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/efrm_client.h>
++#include "efrm_internal.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 = frs->rs.rs_client->nic;
++	int id;
++
++	EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 1);
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
++		   EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle));
++
++	efhw_nic_ipfilter_clear(nic, frs->filter_idx);
++	frs->filter_idx = -1;
++	efrm_vi_resource_release(frs->pt);
++
++	/* 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_client_put(frs->rs.rs_client);
++	EFRM_DO_DEBUG(memset(frs, 0, sizeof(*frs)));
++	kfree(frs);
++}
++EXPORT_SYMBOL(efrm_filter_resource_free);
++
++
++void efrm_filter_resource_release(struct filter_resource *frs)
++{
++	if (__efrm_resource_release(&frs->rs))
++		efrm_filter_resource_free(frs);
++}
++EXPORT_SYMBOL(efrm_filter_resource_release);
++
++
++static void filter_rm_dtor(struct efrm_resource_manager *rm)
++{
++	EFRM_TRACE("%s:", __func__);
++
++	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("%s: done", __func__);
++}
++
++/**********************************************************************/
++/**********************************************************************/
++/**********************************************************************/
++
++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);
++	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",
++		   __func__, 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;
++
++}
++
++
++int efrm_filter_resource_clear(struct filter_resource *frs)
++{
++	struct efhw_nic *nic = frs->rs.rs_client->nic;
++
++	efhw_nic_ipfilter_clear(nic, frs->filter_idx);
++	frs->filter_idx = -1;
++	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 = frs->rs.rs_client->nic;
++	int vi_instance;
++
++	EFRM_ASSERT(frs);
++
++	if (efrm_nic_tablep->a_nic->devtype.variant >= 'B' &&
++	    (frs->pt->flags & EFHW_VI_JUMBO_EN) == 0)
++		type |= EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK;
++	vi_instance = EFRM_RESOURCE_INSTANCE(frs->pt->rs.rs_handle);
++
++	return efhw_nic_ipfilter_set(nic, type, &frs->filter_idx,
++				     vi_instance, saddr, sport, daddr, dport);
++}
++EXPORT_SYMBOL(__efrm_filter_resource_set);;
++
++
++int
++efrm_filter_resource_alloc(struct vi_resource *vi_parent,
++			   struct filter_resource **frs_out)
++{
++	struct filter_resource *frs;
++	int rc, instance;
++
++	EFRM_ASSERT(frs_out);
++	EFRM_ASSERT(efrm_filter_manager);
++	EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm);
++	EFRM_ASSERT(vi_parent != NULL);
++	EFRM_ASSERT(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;
++
++	/* 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", __func__);
++		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;
++	efrm_resource_ref(&frs->pt->rs);
++	frs->filter_idx = -1;
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " VI %d", __func__,
++		   EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle),
++		   EFRM_RESOURCE_INSTANCE(vi_parent->rs.rs_handle));
++
++	efrm_client_add_resource(vi_parent->rs.rs_client, &frs->rs);
++	*frs_out = frs;
++	return 0;
++
++fail1:
++	memset(frs, 0, sizeof(*frs));
++	kfree(frs);
++	return rc;
++}
++EXPORT_SYMBOL(efrm_filter_resource_alloc);
++
++
++int efrm_filter_resource_instance(struct filter_resource *frs)
++{
++	return EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle);
++}
++EXPORT_SYMBOL(efrm_filter_resource_instance);
++
++
++struct efrm_resource *
++efrm_filter_resource_to_resource(struct filter_resource *frs)
++{
++	return &frs->rs;
++}
++EXPORT_SYMBOL(efrm_filter_resource_to_resource);
++
++
++struct filter_resource *
++efrm_filter_resource_from_resource(struct efrm_resource *rs)
++{
++	return filter_resource(rs);
++}
++EXPORT_SYMBOL(efrm_filter_resource_from_resource);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/iobufset_resource.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,404 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/efrm_client.h>
++#include "efrm_internal.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 n_pages)
++{
++	return offsetof(struct iobufset_resource, bufs) +
++	    n_pages * sizeof(struct efhw_iopage);
++}
++
++void efrm_iobufset_resource_free(struct iobufset_resource *rs)
++{
++	unsigned int i;
++	int id;
++
++	EFRM_RESOURCE_ASSERT_VALID(&rs->rs, 1);
++
++	if (!rs->linked && 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_tablep->a_nic here */
++	EFRM_ASSERT(efrm_nic_tablep->a_nic);
++	if (rs->linked) {
++		/* Nothing to do. */
++	} else if (rs->chunk_order == 0) {
++		for (i = 0; i < rs->n_bufs; ++i)
++			efhw_iopage_free(efrm_nic_tablep->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) {
++			struct efhw_iopages iopages;
++			efhw_iopages_init_from_iopage(&iopages, &rs->bufs[i],
++						    rs->chunk_order);
++			efhw_iopages_free(efrm_nic_tablep->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);
++	if (rs->linked)
++		efrm_iobufset_resource_release(rs->linked);
++
++	efrm_client_put(rs->rs.rs_client);
++	if (iobsrs_size(rs->n_bufs) < PAGE_SIZE) {
++		EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
++		kfree(rs);
++	} else {
++		EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs)));
++		vfree(rs);
++	}
++}
++EXPORT_SYMBOL(efrm_iobufset_resource_free);
++
++
++void efrm_iobufset_resource_release(struct iobufset_resource *iobrs)
++{
++	if (__efrm_resource_release(&iobrs->rs))
++		efrm_iobufset_resource_free(iobrs);
++}
++EXPORT_SYMBOL(efrm_iobufset_resource_release);
++
++
++
++int
++efrm_iobufset_resource_alloc(int32_t n_pages,
++			     int32_t pages_per_contiguous_chunk,
++			     struct vi_resource *vi_evq,
++			     struct iobufset_resource *linked,
++			     bool phys_addr_mode,
++			     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_tablep->a_nic);
++
++	if (linked) {
++		/* This resource will share properties and memory with
++		 * another.  Only difference is that we'll program it into
++		 * the buffer table of another nic.
++		 */
++		n_pages = linked->n_bufs;
++		pages_per_contiguous_chunk = linked->pages_per_contiguous_chunk;
++		phys_addr_mode = linked->buf_tbl_alloc.base == (unsigned) -1;
++	}
++
++	/* 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",
++				 __func__, n_pages);
++			EFRM_ASSERT(!in_interrupt());
++			EFRM_ASSERT(!in_atomic());
++		}
++#endif
++		iobrs = (struct iobufset_resource *) vmalloc(object_size);
++	}
++	if (iobrs == NULL) {
++		EFRM_WARN("%s: failed to allocate container", __func__);
++		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_WARN("%s: out of instances", __func__);
++		EFRM_ASSERT(rc == 0);
++		rc = -EBUSY;
++		goto fail3;
++	}
++
++	efrm_resource_init(&iobrs->rs, EFRM_RESOURCE_IOBUFSET, instance);
++
++	iobrs->evq = vi_evq;
++	iobrs->linked = linked;
++	iobrs->n_bufs = n_pages;
++	iobrs->pages_per_contiguous_chunk = pages_per_contiguous_chunk;
++	iobrs->chunk_order = fls(iobrs->pages_per_contiguous_chunk - 1);
++	iobrs->buf_tbl_alloc.base = (unsigned) -1;
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %u pages", __func__,
++		   EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), iobrs->n_bufs);
++
++	/* Allocate the iobuffers. */
++	if (linked) {
++		memcpy(iobrs->bufs, linked->bufs,
++		       iobrs->n_bufs * sizeof(iobrs->bufs[0]));
++	} else if (iobrs->chunk_order == 0) {
++		memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
++		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_tablep->a_nic),
++			 * it is suitable for all NICs.
++			 * XXX I bet that breaks in Solaris.
++			 */
++			rc = efhw_iopage_alloc(efrm_nic_tablep->a_nic,
++					     &iobrs->bufs[i]);
++			if (rc < 0) {
++				EFRM_WARN("%s: failed (rc %d) to allocate "
++					  "page (i=%u)", __func__, rc, i);
++				goto fail4;
++			}
++		}
++	} else {
++		struct efhw_iopages iopages;
++		unsigned j;
++
++		memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0]));
++		for (i = 0; i < iobrs->n_bufs;
++		     i += iobrs->pages_per_contiguous_chunk) {
++			rc = efhw_iopages_alloc(efrm_nic_tablep->a_nic,
++						&iopages, iobrs->chunk_order);
++			if (rc < 0) {
++				EFRM_WARN("%s: failed (rc %d) to allocate "
++					  "pages (i=%u order %d)",
++					  __func__, rc, i,
++					  iobrs->chunk_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);
++			}
++		}
++	}
++
++	if (!phys_addr_mode) {
++		unsigned owner_id = EFAB_VI_RESOURCE_INSTANCE(iobrs->evq);
++
++		if (!linked) {
++			/* 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_WARN("%s: failed (%d) to alloc %d buffer "
++					  "table entries", __func__, rc,
++					  iobrs->n_bufs);
++				goto fail5;
++			}
++			EFRM_ASSERT(((unsigned)1 << iobrs->buf_tbl_alloc.order)
++				    >= (unsigned) iobrs->n_bufs);
++		} else {
++			iobrs->buf_tbl_alloc = linked->buf_tbl_alloc;
++		}
++
++		/* Initialise the buffer table entries. */
++		for (i = 0; i < iobrs->n_bufs; ++i) {
++			/*\ ?? \TODO burst them! */
++			efrm_buffer_table_set(&iobrs->buf_tbl_alloc,
++					      vi_evq->rs.rs_client->nic,
++					      i,
++					      efhw_iopage_dma_addr(&iobrs->
++								   bufs[i]),
++					      owner_id);
++		}
++		efrm_buffer_table_commit();
++	}
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %d pages @ "
++		   EFHW_BUFFER_ADDR_FMT, __func__,
++		   EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle),
++		   iobrs->n_bufs, EFHW_BUFFER_ADDR(iobrs->buf_tbl_alloc.base,
++						   0));
++	efrm_resource_ref(&iobrs->evq->rs);
++	if (linked != NULL)
++		efrm_resource_ref(&linked->rs);
++	efrm_client_add_resource(vi_evq->rs.rs_client, &iobrs->rs);
++	*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_tablep->a_nic here */
++	if (linked) {
++		/* Nothing to do. */
++	} else if (iobrs->chunk_order == 0) {
++		while (i--) {
++			struct efhw_iopage *page = &iobrs->bufs[i];
++			efhw_iopage_free(efrm_nic_tablep->a_nic, page);
++		}
++	} else {
++		unsigned int j;
++		for (j = 0; j < i; j += iobrs->pages_per_contiguous_chunk) {
++			struct efhw_iopages 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->chunk_order);
++			efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages);
++		}
++	}
++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);
++
++	/* HACK: There currently exists an option to allocate buffers that
++	 * are not programmed into the buffer table, so the max number is
++	 * not limited by the buffer table size.  I'm hoping this usage
++	 * will go away eventually.
++	 */
++	max = 32768;
++
++	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);
++	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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/iopage.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,103 @@
++/****************************************************************************
++ * 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, struct efhw_iopage *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, struct efhw_iopage *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, struct efhw_iopages *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, struct efhw_iopages *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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kernel_compat.c	2008-07-17 16:18: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 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
++
++
++/****************************************************************************
++ *
++ * allocate a buffer suitable for DMA to/from the NIC
++ *
++ ****************************************************************************/
++
++#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)
++{
++	void *ptr;
++	unsigned order;
++
++	order = __ffs(size/PAGE_SIZE);
++	EFRM_ASSERT(size == (PAGE_SIZE<<order));
++
++	/* 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;
++
++#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)
++{
++	unsigned order;
++
++	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
++
++	dma_free_coherent(dev, size, ptr, dma_addr);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kernel_compat.h	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,70 @@
++/****************************************************************************
++ * 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/moduleparam.h>
++#include <linux/sched.h>
++#include <linux/io.h>
++#include <linux/pci.h>
++
++/********* pci_map_*() ********************/
++
++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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kernel_proc.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,109 @@
++/****************************************************************************
++ * 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/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("driver/sfc_resource", NULL);
++	if (!efrm_proc_root)
++		return -ENOMEM;
++
++	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", __func__);
++	}
++	return 0;
++}
++
++void efrm_uninstall_proc_entries(void)
++{
++	EFRM_ASSERT(efrm_proc_root);
++	remove_proc_entry("resources", efrm_proc_root);
++	remove_proc_entry(efrm_proc_root->name, efrm_proc_root->parent);
++	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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kfifo.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,208 @@
++/*
++ * 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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/linux_resource_internal.h	2008-07-17 16:18: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 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, int non_irq_evq,
++	     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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/nic.c	2008-07-17 16:18: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 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->variant = 'A';
++		switch (class_revision) {
++		case 0:
++			dt->revision = 0;
++			break;
++		case 1:
++			dt->revision = 1;
++			break;
++		default:
++			return 0;
++		}
++		break;
++	case 0x0710:
++		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)
++{
++	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;
++
++	nic->irq_unit = EFHW_IRQ_UNIT_UNUSED;
++
++	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;
++		nic->num_evqs   = 4096;
++		nic->num_dmaqs  = 4096;
++		nic->num_timers = 4096;
++		break;
++	case 'B':
++		nic->flags |= NIC_FLAG_NO_INTERRUPT;
++		nic->ctr_ap_bar = FALCON_P_CTR_AP_BAR;
++		nic->num_evqs   = 4096;
++		nic->num_dmaqs  = 4096;
++		nic->num_timers = 4096;
++		break;
++	default:
++		EFHW_ASSERT(0);
++		break;
++	}
++}
++
++
++void efhw_nic_close_interrupts(struct efhw_nic *nic)
++{
++	EFHW_ASSERT(nic);
++	if (!efhw_nic_have_hw(nic))
++		return;
++
++	EFHW_ASSERT(efhw_nic_have_hw(nic));
++
++	if (nic->irq_unit != EFHW_IRQ_UNIT_UNUSED)
++		efhw_nic_interrupt_disable(nic);
++}
++
++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 */
++
++	/* 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 ... ", __func__);
++
++	if (efhw_nic_have_functional_units(nic)) {
++		efhw_nic_close_interrupts(nic);
++		efhw_nic_close_hardware(nic);
++	}
++	EFHW_TRACE("%s: functional units ... done", __func__);
++
++	/* destroy event queues */
++	EFHW_TRACE("%s: event queues ... ", __func__);
++
++	if (nic->interrupting_evq.evq_mask)
++		efhw_keventq_dtor(nic, &nic->interrupting_evq);
++	if (nic->non_interrupting_evq.evq_mask)
++		efhw_keventq_dtor(nic, &nic->non_interrupting_evq);
++
++	EFHW_TRACE("%s: event queues ... done", __func__);
++
++	spin_lock_destroy(&nic->the_reg_lock);
++
++	EFHW_TRACE("%s: DONE", __func__);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resource_driver.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,600 @@
++/****************************************************************************
++ * 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>
++
++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,
++};
++
++const int max_hardware_init_repeats = 10;
++
++/*--------------------------------------------------------------------
++ *
++ * Module load time variables
++ *
++ *--------------------------------------------------------------------*/
++/* See docs/notes/pci_alloc_consistent */
++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(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
++ *
++ *--------------------------------------------------------------------*/
++
++static inline irqreturn_t
++linux_efrm_interrupt(int irr, void *dev_id)
++{
++	return efhw_nic_interrupt((struct efhw_nic *)dev_id);
++}
++
++int linux_efrm_irq_ctor(struct linux_efhw_nic *lnic)
++{
++	struct efhw_nic *nic = &lnic->efrm_nic.efhw_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)",
++				  __func__, rc);
++			EFRM_WARN("%s: Continuing with legacy interrupt mode",
++				  __func__);
++		} else {
++			EFRM_NOTICE("%s: MSI enabled", __func__);
++			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("%s: start", __func__);
++
++	if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_OS_IRQ_EN) {
++		free_irq(lnic->pci_dev->irq, &lnic->efrm_nic.efhw_nic);
++		lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_OS_IRQ_EN;
++	}
++
++	if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_MSI) {
++		pci_disable_msi(lnic->pci_dev);
++		lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_MSI;
++	}
++
++	EFRM_TRACE("%s: done", __func__);
++}
++
++/* 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 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)",
++			     __func__, nic->evq_sizes);
++			return -E2BIG;
++		} else if (capacity & nic->evq_sizes)
++			break;
++	}
++
++	nic->interrupting_evq.hw.capacity = capacity;
++	nic->interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1;
++
++	nic->non_interrupting_evq.hw.capacity = capacity;
++	nic->non_interrupting_evq.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->interrupting_evq
++					     .hw.buf_tbl_alloc);
++		if (rc < 0) {
++			EFRM_WARN
++			    ("%s: failed (%d) to alloc %d buffer table entries",
++			     __func__, rc, page_order);
++			return rc;
++		}
++	}
++	rc = efrm_buffer_table_alloc(page_order,
++				     &nic->non_interrupting_evq.hw.
++				     buf_tbl_alloc);
++	if (rc < 0) {
++		EFRM_WARN
++		    ("%s: failed (%d) to alloc %d buffer table entries",
++		     __func__, 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)
++{
++	if (nic->interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
++		efrm_buffer_table_free(&nic->interrupting_evq.hw
++				       .buf_tbl_alloc);
++	if (nic->non_interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1)
++		efrm_buffer_table_free(&nic->non_interrupting_evq
++				       .hw.buf_tbl_alloc);
++}
++
++static int iomap_bar(struct linux_efhw_nic *lnic, size_t len)
++{
++	volatile char __iomem *ioaddr;
++
++	ioaddr = ioremap_nocache(lnic->ctr_ap_pci_addr, len);
++	if (ioaddr == 0)
++		return -ENOMEM;
++
++	lnic->efrm_nic.efhw_nic.bar_ioaddr = ioaddr;
++	return 0;
++}
++
++static int linux_efhw_nic_map_ctr_ap(struct linux_efhw_nic *lnic)
++{
++	struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic;
++	int rc;
++
++	rc = iomap_bar(lnic, nic->ctr_ap_bytes);
++
++	/* 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);
++	}
++
++	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->efrm_nic.efhw_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)",
++			 __func__, 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)",
++			 __func__, (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)",
++			 __func__, 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", __func__,
++			 (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", __func__,
++			 (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",
++			 __func__, (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->efrm_nic.efhw_nic;
++	volatile char __iomem *bar_ioaddr = nic->bar_ioaddr;
++
++	efhw_nic_dtor(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->interrupting_evq);
++	EFRM_TRACE("%s: complete", __func__);
++}
++
++/****************************************************************************
++ *
++ * 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", __func__);
++	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_lim, int non_irq_evq,
++	     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)", __func__,
++		   pci_name(dev) ? pci_name(dev) : "?", dev->irq);
++
++	/* Ensure that we have room for the new adapter-structure. */
++	if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) {
++		EFRM_WARN("%s: WARNING: too many devices", __func__);
++		rc = -ENOMEM;
++		goto failed;
++	}
++
++	if (n_nics_probed == 0) {
++		rc = efrm_resources_init(res_dim, bt_min, bt_lim);
++		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", __func__);
++		rc = -ENOMEM;
++		goto failed;
++	}
++	memset(lnic, 0, sizeof(*lnic));
++	nic = &lnic->efrm_nic.efhw_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", __func__);
++		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(&lnic->efrm_nic, nic_index,
++				      /* TODO: ifindex */ nic_index);
++	if (rc < 0) {
++		EFRM_ERR("%s: cannot register nic %d with nic error code %d",
++			 __func__, efrm_nic_tablep->nic_count, rc);
++		goto failed;
++	}
++	++nic_index;
++	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,
++					    non_irq_evq);
++		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, -1, irq_moderation);
++		efhw_nic_interrupt_enable(nic);
++	}
++	EFRM_TRACE("interrupts are %sregistered", do_irq ? "" : "not ");
++
++	*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(&lnic->efrm_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->efrm_nic.efhw_nic;
++
++	EFRM_TRACE("%s:", __func__);
++	EFRM_ASSERT(nic);
++
++	efrm_nic_buffer_table_free(nic);
++
++	efrm_driver_unregister_nic(&lnic->efrm_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("%s: done", __func__);
++}
++
++/****************************************************************************
++ *
++ * init_module: register as a PCI driver.
++ *
++ ****************************************************************************/
++static int init_sfc_resource(void)
++{
++	int rc = 0;
++
++	EFRM_TRACE("%s: RESOURCE driver starting", __func__);
++
++	efrm_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", __func__);
++	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",
++			  __func__);
++	}
++
++	return 0;
++
++failed_driverlink:
++	efrm_driver_dtor();
++	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("%s: unloaded", __func__);
++}
++
++module_init(init_sfc_resource);
++module_exit(cleanup_sfc_resource);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resource_manager.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,145 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/private.h>
++#include "efrm_internal.h"
++
++/**********************************************************************
++ * 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",
++			       __func__, rm->rm_name, rm->rm_resources));
++	EFRM_ASSERT(rm->rm_resources == 0);
++	EFRM_ASSERT(list_empty(&rm->rm_resources_list));
++
++	rm->rm_dtor(rm);
++
++	/* clear out things built by efrm_resource_manager_ctor */
++	spin_lock_destroy(&rm->rm_lock);
++
++	/* 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)
++{
++	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;
++	INIT_LIST_HEAD(&rm->rm_resources_list);
++	EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm);
++	return 0;
++}
++
++
++void efrm_client_add_resource(struct efrm_client *client,
++			      struct efrm_resource *rs)
++{
++	struct efrm_resource_manager *rm;
++	irq_flags_t lock_flags;
++
++	EFRM_ASSERT(client != NULL);
++	EFRM_ASSERT(rs != NULL);
++
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
++	++rm->rm_resources;
++	list_add(&rs->rs_manager_link, &rm->rm_resources_list);
++	if (rm->rm_resources > rm->rm_resources_hiwat)
++		rm->rm_resources_hiwat = rm->rm_resources;
++	rs->rs_client = client;
++	++client->ref_count;
++	list_add(&rs->rs_client_link, &client->resources);
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++}
++
++
++void efrm_resource_ref(struct efrm_resource *rs)
++{
++	irq_flags_t lock_flags;
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	++rs->rs_ref_count;
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++}
++EXPORT_SYMBOL(efrm_resource_ref);
++
++
++int __efrm_resource_release(struct efrm_resource *rs)
++{
++	struct efrm_resource_manager *rm;
++	irq_flags_t lock_flags;
++	int free_rs;
++
++	spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags);
++	free_rs = --rs->rs_ref_count == 0;
++	if (free_rs) {
++		rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)];
++		EFRM_ASSERT(rm->rm_resources > 0);
++		--rm->rm_resources;
++		list_del(&rs->rs_manager_link);
++		list_del(&rs->rs_client_link);
++	}
++	spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags);
++	return free_rs;
++}
++EXPORT_SYMBOL(__efrm_resource_release);
++
++/*
++ * vi: sw=8:ai:aw
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resources.c	2008-07-17 16:18: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_lim)
++{
++	int i, rc;
++
++	rc = efrm_buffer_table_ctor(buffer_table_min, buffer_table_lim);
++	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)",
++				 __func__, 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();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_alloc.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,820 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/efrm_client.h>
++#include "efrm_internal.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(struct efrm_client *client,
++			       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(virs->rs.rs_client, 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_tablep->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_tablep->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",
++			     __func__);
++			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",
++				  __func__);
++			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_tablep->a_nic == NULL)	/* ?? FIXME: surely not right */
++		return;
++
++	if (efrm_nic_tablep->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 ((size & sizes) && size >= size_rq)
++			return size;
++		else if ((sizes & ~((size - 1) | size)) == 0)
++			return -1;
++}
++
++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 ", __func__,
++				   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, __func__,
++				   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)",
++			   __func__,
++			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle));
++	}
++}
++
++/*** Buffer Table allocations ********************************************/
++
++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",
++			     __func__, 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",
++			     __func__, 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;
++}
++
++/*** Per-NIC allocations *************************************************/
++
++static inline int
++efrm_vi_rm_init_evq(struct vi_resource *virs, struct efhw_nic *nic)
++{
++	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	struct eventq_resource_hardware *evq_hw =
++	    &virs->nic_info.evq_pages;
++	uint32_t buf_bytes = efrm_vi_rm_evq_bytes(virs);
++	int rc;
++
++	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",
++			  __func__, 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", __func__, 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,
++				    instance < 64);
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " capacity=%u", __func__,
++		   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_ROUNDUP(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, struct efhw_nic *nic)
++{
++	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	struct vi_resource_nic_info *nic_info = &virs->nic_info;
++
++	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;
++	int evq_instance;
++	efhw_buffer_addr_t buf_addr;
++
++	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	evq_instance = EFRM_RESOURCE_INSTANCE(virs->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,
++			     struct efhw_nic *nic)
++{
++	int rc;
++	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	uint32_t buf_bytes;
++	struct vi_resource_nic_info *nic_info = &virs->nic_info;
++	int page_order;
++	uint32_t num_pages;
++	struct efhw_iopages *iobuff;
++
++	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));
++
++	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.", __func__,
++			 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 += roundup(buf_bytes, PAGE_SIZE);
++
++	/* Make sure there is an event queue. */
++	if (virs->evq_virs->evq_capacity <= 0) {
++		EFRM_ERR("%s: Cannot use empty event queue for %s DMA",
++			 __func__, 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;
++
++	/* Ensure TX pacing turned off -- queue flush doesn't reset this. */
++	if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX)
++		falcon_nic_pace(nic, instance, 0);
++
++	/* No need to disable the queue here.  Nobody is using it anyway. */
++
++fail_evq:
++	efhw_iopages_free(nic, &nic_info->dmaq_pages[queue_type]);
++fail_iopages:
++
++	return rc;
++}
++
++static int
++efrm_vi_rm_init_or_fini_nic(struct vi_resource *virs, int init,
++			    struct efhw_nic *nic)
++{
++	int rc;
++#ifndef NDEBUG
++	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++#endif
++
++	if (!init)
++		goto destroy;
++
++	rc = efrm_vi_rm_init_evq(virs, nic);
++	if (rc != 0)
++		goto fail_evq;
++
++	rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
++					  init, nic);
++	if (rc != 0)
++		goto fail_txq;
++
++	rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
++					  init, nic);
++	if (rc != 0)
++		goto fail_rxq;
++
++	/* 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;
++
++	return 0;
++
++destroy:
++	rc = 0;
++
++	efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX,
++				     false, nic);
++fail_rxq:
++
++	efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX,
++				     false, nic);
++fail_txq:
++
++	efrm_vi_rm_fini_evq(virs, nic);
++fail_evq:
++
++	EFRM_ASSERT(rc != 0 || !init);
++	return rc;
++}
++
++static int
++efrm_vi_resource_alloc_or_free(struct efrm_client *client,
++			       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 efhw_nic *nic = client->nic;
++	struct vi_resource *virs;
++	int rc;
++	int instance;
++
++	EFRM_ASSERT(virs_in_out);
++	EFRM_ASSERT(efrm_vi_manager);
++	EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm);
++
++	if (!alloc)
++		goto destroy;
++
++	rx_q_tag &= (1 << TX_DESCQ_LABEL_WIDTH) - 1;
++	tx_q_tag &= (1 << RX_DESCQ_LABEL_WIDTH) - 1;
++
++	virs = kmalloc(sizeof(*virs), GFP_KERNEL);
++	if (virs == NULL) {
++		EFRM_ERR("%s: Error allocating VI resource object",
++			 __func__);
++		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.", __func__);
++	}
++
++	if (instance < 0) {
++		/* Could flush resources and try again here. */
++		EFRM_ERR("%s: Out of appropriate VI resources", __func__);
++		rc = -EBUSY;
++		goto fail_alloc_id;
++	}
++
++	EFRM_TRACE("%s: new VI ID %d", __func__, 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);
++
++	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);
++	virs->tx_flushing = 0;
++	virs->rx_flushing = 0;
++
++	/* Adjust the queue sizes. */
++	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", __func__,
++			   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, __func__,
++				 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,
++			   __func__,
++			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++			   EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle));
++	}
++	virs->evq_virs = evq_virs;
++
++	rc = efrm_vi_rm_alloc_or_free_buffer_table(virs, true);
++	if (rc != 0)
++		goto fail_buffer_table;
++
++	rc = efrm_vi_rm_init_or_fini_nic(virs, true, nic);
++	if (rc != 0)
++		goto fail_init_nic;
++
++	efrm_client_add_resource(client, &virs->rs);
++	*virs_in_out = virs;
++	EFRM_TRACE("%s: Allocated " EFRM_RESOURCE_FMT, __func__,
++		   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", __func__,
++		   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_vi_rm_init_or_fini_nic(virs, false, nic);
++
++	efrm_vi_rm_alloc_or_free_buffer_table(virs, false);
++fail_buffer_table:
++
++	efrm_vi_rm_detach_evq(virs);
++
++fail_adjust_request:
++
++	EFRM_ASSERT(virs->evq_callback_fn == NULL);
++	EFRM_TRACE("%s: delete VI ID %d", __func__, instance);
++	efrm_vi_rm_free_id(instance);
++fail_alloc_id:
++	if (!alloc)
++		efrm_client_put(virs->rs.rs_client);
++	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 efrm_client *client,
++		       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;
++	EFRM_ASSERT(client != NULL);
++	rc = efrm_vi_resource_alloc_or_free(client, 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(virs->rs.rs_ref_count == 0);
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
++		   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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_event.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,250 @@
++/****************************************************************************
++ * 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>
++#include <ci/efrm/efrm_nic.h>
++#include "efrm_internal.h"
++
++
++static inline int
++efrm_eventq_bytes(struct vi_resource *virs)
++{
++	return efrm_vi_rm_evq_bytes(virs);
++}
++
++
++static inline efhw_event_t *
++efrm_eventq_base(struct vi_resource *virs)
++{
++	struct eventq_resource_hardware *hw;
++	hw = &(virs->nic_info.evq_pages);
++	return (efhw_event_t *) (efhw_iopages_ptr(&(hw->iobuff)) +
++				 hw->iobuff_off);
++}
++
++
++void
++efrm_eventq_request_wakeup(struct vi_resource *virs, unsigned current_ptr)
++{
++	struct efhw_nic *nic = virs->rs.rs_client->nic;
++	int next_i;
++	next_i = ((current_ptr / sizeof(efhw_event_t)) &
++		  (virs->evq_capacity - 1));
++
++	efhw_nic_wakeup_request(nic, efrm_eventq_dma_addr(virs), next_i,
++				EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle));
++}
++EXPORT_SYMBOL(efrm_eventq_request_wakeup);
++
++void efrm_eventq_reset(struct vi_resource *virs)
++{
++	struct efhw_nic *nic = virs->rs.rs_client->nic;
++	int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++	EFRM_ASSERT(virs->evq_capacity != 0);
++
++	/* FIXME: Protect against concurrent resets. */
++
++	efhw_nic_event_queue_disable(nic, instance, 0);
++
++	memset(efrm_eventq_base(virs), EFHW_CLEAR_EVENT_VALUE,
++	       efrm_eventq_bytes(virs));
++	efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity,
++				    efrm_eventq_dma_addr(virs),
++				    virs->nic_info.evq_pages.
++				      buf_tbl_alloc.base,
++				    instance < 64);
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__,
++		   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)
++{
++	struct efrm_nic_per_vi *cb_info;
++	int instance;
++	int bit;
++
++	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++	EFRM_ASSERT(virs->evq_capacity != 0);
++	EFRM_ASSERT(handler != NULL);
++
++	/* ?? TODO: Get rid of this test when client is compulsory. */
++	if (virs->rs.rs_client == NULL) {
++		EFRM_ERR("%s: no client", __func__);
++		return -EINVAL;
++	}
++
++	virs->evq_callback_arg = arg;
++	virs->evq_callback_fn = handler;
++	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
++
++	/* The handler can be set only once. */
++	bit = test_and_set_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++			       &cb_info->state);
++	if (bit)
++		return -EBUSY;
++	cb_info->vi = virs;
++
++	return 0;
++}
++EXPORT_SYMBOL(efrm_eventq_register_callback);
++
++void efrm_eventq_kill_callback(struct vi_resource *virs)
++{
++	struct efrm_nic_per_vi *cb_info;
++	int32_t evq_state;
++	int instance;
++	int bit;
++
++	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++	EFRM_ASSERT(virs->evq_capacity != 0);
++	EFRM_ASSERT(virs->rs.rs_client != NULL);
++
++	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance];
++	cb_info->vi = NULL;
++
++	/* Disable the timer. */
++	efhw_nic_event_queue_disable(virs->rs.rs_client->nic,
++				     instance, /*timer_only */ 1);
++
++	/* Disable the callback. */
++	bit = test_and_clear_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED,
++				 &cb_info->state);
++	EFRM_ASSERT(bit);	/* do not call me twice! */
++
++	/* Spin until the callback is complete. */
++	do {
++		rmb();
++
++		udelay(1);
++		evq_state = cb_info->state;
++	} while ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)));
++
++	virs->evq_callback_fn = NULL;
++}
++EXPORT_SYMBOL(efrm_eventq_kill_callback);
++
++static void
++efrm_eventq_do_callback(struct efhw_nic *nic, unsigned instance,
++			bool is_timeout)
++{
++	struct efrm_nic *rnic = efrm_nic(nic);
++	void (*handler) (void *, int is_timeout, struct efhw_nic *nic);
++	void *arg;
++	struct efrm_nic_per_vi *cb_info;
++	int32_t evq_state;
++	int32_t new_evq_state;
++	struct vi_resource *virs;
++	int bit;
++
++	EFRM_ASSERT(efrm_vi_manager);
++
++	cb_info = &rnic->vis[instance];
++
++	/* Set the BUSY bit and clear WAKEUP_PENDING.  Do this
++	 * before waking up the sleeper to avoid races. */
++	while (1) {
++		evq_state = cb_info->state;
++		new_evq_state = evq_state;
++
++		if ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)) != 0) {
++			EFRM_ERR("%s:%d: evq_state[%d] corrupted!",
++				 __func__, __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);
++			virs = cb_info->vi;
++			if (cmpxchg(&cb_info->state, evq_state,
++				    new_evq_state) == evq_state)
++				break;
++		} else {
++			/* Just update the state if necessary. */
++			if (new_evq_state == evq_state ||
++			    cmpxchg(&cb_info->state, evq_state,
++				    new_evq_state) == evq_state)
++				return;
++		}
++	}
++
++	if (virs) {
++		handler = virs->evq_callback_fn;
++		arg = virs->evq_callback_arg;
++		EFRM_ASSERT(handler != NULL);
++		handler(arg, is_timeout, nic);
++	}
++
++	/* Clear the BUSY bit. */
++	bit =
++	    test_and_clear_bit(VI_RESOURCE_EVQ_STATE_BUSY,
++			       &cb_info->state);
++	if (!bit) {
++		EFRM_ERR("%s:%d: evq_state corrupted!",
++			 __func__, __LINE__);
++	}
++}
++
++void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned instance)
++{
++	efrm_eventq_do_callback(nic, instance, false);
++}
++
++void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned instance)
++{
++	efrm_eventq_do_callback(nic, instance, true);
++}
++
++void efrm_handle_sram_event(struct efhw_nic *nic)
++{
++  if (nic->buf_commit_outstanding > 0)
++    nic->buf_commit_outstanding--;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_flush.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,483 @@
++/****************************************************************************
++ * 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>
++#include "efrm_internal.h"
++
++
++/* can fail as workitem can already be scheuled -- ignore failure */
++#define EFRM_VI_RM_DELAYED_FREE(manager) \
++	queue_work(manager->workqueue, &manager->work_item)
++
++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, bool *completed)
++{
++	/* We should only get a flush event if there is a flush
++	 * outstanding. */
++	EFRM_ASSERT(virs->rx_flush_outstanding);
++
++	virs->rx_flush_outstanding = 0;
++	virs->rx_flushing = 0;
++
++	list_del(&virs->rx_flush_link);
++	efrm_vi_manager->rx_flush_outstanding_count--;
++
++	if (virs->tx_flushing == 0) {
++		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, bool *completed)
++{
++	/* We should only get a flush event if there is a flush
++	 * outstanding. */
++	EFRM_ASSERT(virs->tx_flushing);
++
++	virs->tx_flushing = 0;
++
++	list_del(&virs->tx_flush_link);
++
++	if (virs->rx_flushing == 0) {
++		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 = virs->rs.rs_client->nic;
++	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 = virs->rx_flushing;
++	efrm_vi_manager->rx_flush_outstanding_count++;
++
++	EFRM_TRACE("%s: rx queue %d flush requested for nic %d",
++		   __func__, instance, nic->index);
++	rc = efhw_nic_flush_rx_dma_channel(nic, instance);
++	if (rc == -EAGAIN)
++		efrm_vi_resource_rx_flush_done(virs, completed);
++}
++
++static void
++efrm_vi_resource_issue_tx_flush(struct vi_resource *virs, bool *completed)
++{
++	struct efhw_nic *nic = virs->rs.rs_client->nic;
++	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_TRACE("%s: tx queue %d flush requested for nic %d",
++		   __func__, instance, nic->index);
++	rc = efhw_nic_flush_tx_dma_channel(nic, instance);
++	if (rc == -EAGAIN)
++		efrm_vi_resource_tx_flush_done(virs, 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 instance;
++
++	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++
++	virs->flush_count++;
++	virs->flush_time = time_now;
++	nic = virs->rs.rs_client->nic;
++
++#if BUG7916_WORKAROUND
++	if (virs->rx_flush_outstanding) {
++		EFRM_TRACE("%s: Retrying RX flush on instance %d",
++			   __func__, 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 (virs->tx_flushing) {
++		if (virs->flush_count > 5) {
++			EFRM_TRACE("%s: VI resource stuck flush pending "
++				   "(instance=%d, count=%d)",
++				   __func__, instance, virs->flush_count);
++			falcon_clobber_tx_dma_ptrs(nic, instance);
++		} else {
++			EFRM_TRACE("%s: Retrying TX flush on instance %d",
++				   __func__, 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 (virs->rx_flushing == 0 && virs->tx_flushing == 0)
++		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(virs->rx_flushing == 0);
++	EFRM_ASSERT(virs->rx_flush_outstanding == 0);
++	EFRM_ASSERT(virs->tx_flushing == 0);
++
++	EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " EVQ=%d TXQ=%d RXQ=%d",
++		   __func__, 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_flushing = 1;
++
++	if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0)
++		virs->tx_flushing = 1;
++
++	/* Clean up immediately if there are no flushes. */
++	if (virs->rx_flushing == 0 && virs->tx_flushing == 0) {
++		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 (virs->rx_flushing) {
++#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 (virs->tx_flushing)
++		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, completed);
++			efrm_vi_resource_process_waiting_flushes(completed);
++			return;
++		}
++	}
++	EFRM_TRACE("%s: Unhandled rx flush event, nic %d, instance %d",
++		   __func__, 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, completed);
++			return;
++		}
++	}
++	EFRM_TRACE("%s: Unhandled tx flush event, nic %d, instance %d",
++		   __func__, flush_nic->index, instance);
++}
++
++void
++efrm_handle_dmaq_flushed(struct efhw_nic *flush_nic, unsigned instance,
++			 int rx_flush)
++{
++	irq_flags_t lock_flags;
++	bool completed = false;
++
++	EFRM_TRACE("%s: nic_i=%d  instance=%d  rx_flush=%d", __func__,
++		   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 = virs->rs.rs_client->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", __func__, 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", __func__,
++			   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);
++
++
++void efrm_vi_resource_release(struct vi_resource *virs)
++{
++	if (__efrm_resource_release(&virs->rs))
++		efrm_vi_resource_free(virs);
++}
++EXPORT_SYMBOL(efrm_vi_resource_release);
++
++/*
++ * vi: sw=8:ai:aw
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_manager.c	2008-07-17 16:18:07.000000000 +0200
+@@ -0,0 +1,231 @@
++/****************************************************************************
++ * 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>
++#include "efrm_internal.h"
++
++
++int efrm_pt_pace(struct vi_resource *virs, unsigned int val)
++{
++	struct efhw_nic *nic = virs->rs.rs_client->nic;
++	int instance;
++
++	EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0);
++	instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle);
++	falcon_nic_pace(nic, instance, val);
++	EFRM_TRACE("%s[%d]=%d DONE", __func__, instance, val);
++	return 0;
++}
++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;
++	unsigned dmaq_min, dmaq_lim;
++
++	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_lim,
++		    dims->evq_timer_min, dims->evq_timer_lim);
++	EFRM_NOTICE("vi_resource_manager: rxq=%u-%u txq=%u-%u",
++		    dims->rxq_min, dims->rxq_lim,
++		    dims->txq_min, dims->txq_lim);
++
++	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_lim = min(dims->rxq_lim, dims->txq_lim);
++
++	efrm_vi_manager->with_timer_base =
++	    max(dmaq_min, dims->evq_timer_min);
++	efrm_vi_manager->with_timer_limit =
++	    min(dmaq_lim, dims->evq_timer_lim);
++	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_lim, dims->evq_int_lim);
++	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;
++
++	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);
++	efrm_vi_manager->workqueue = create_workqueue("sfc_vi");
++	if (efrm_vi_manager->workqueue == NULL)
++		goto fail_create_workqueue;
++	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);
++	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_flushing
++	 * 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 (virs->tx_flushing == 0)
++			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 (virs->tx_flushing == 0)
++			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]",
++			   __func__,
++			   EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle),
++			   virs->tx_flushing,
++			   virs->rx_flushing,
++			   virs->rx_flush_outstanding);
++		efrm_vi_rm_free_flushed_resource(virs);
++	}
++
++fail_rm_ctor:
++
++	/* Complete outstanding closes. */
++	destroy_workqueue(efrm_vi_manager->workqueue);
++fail_create_workqueue:
++	EFRM_ASSERT(list_empty(&efrm_vi_manager->close_pending));
++	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", __func__, 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);
++}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.31
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.31
@@ -0,0 +1,7178 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: Linux: 2.6.31
+Patch-mainline: 2.6.31
+
+ This patch contains the differences between 2.6.30 and 2.6.31.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.31-rc4" by xen-port-patches.py
+
+--- sle11sp1-2010-01-20.orig/arch/x86/Kconfig	2009-11-20 11:03:01.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/Kconfig	2009-11-20 11:04:42.000000000 +0100
+@@ -24,7 +24,7 @@ config X86
+ 	select HAVE_UNSTABLE_SCHED_CLOCK
+ 	select HAVE_IDE
+ 	select HAVE_OPROFILE
+-	select HAVE_PERF_EVENTS if (!M386 && !M486)
++	select HAVE_PERF_EVENTS if (!M386 && !M486 && !XEN)
+ 	select HAVE_IOREMAP_PROT
+ 	select HAVE_KPROBES
+ 	select ARCH_WANT_OPTIONAL_GPIOLIB
+@@ -904,7 +904,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 
+ config X86_MCE
+ 	bool "Machine Check / overheating reporting"
+-	depends on !X86_XEN && !XEN_UNPRIVILEGED_GUEST
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 	---help---
+ 	  Machine Check support allows the processor to notify the
+ 	  kernel if it detects a problem (e.g. overheating, data corruption).
+@@ -929,7 +929,7 @@ config X86_MCE_AMD
+ 
+ config X86_ANCIENT_MCE
+ 	def_bool n
+-	depends on X86_32 && X86_MCE
++	depends on X86_32 && X86_MCE && !XEN
+ 	prompt "Support for old Pentium 5 / WinChip machine checks"
+ 	---help---
+ 	  Include support for machine check handling on old Pentium 5 or WinChip
+@@ -1617,6 +1617,7 @@ config KEXEC_JUMP
+ 
+ config PHYSICAL_START
+ 	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP || XEN)
++	default 0x100000 if XEN
+ 	default "0x1000000"
+ 	---help---
+ 	  This gives the physical address where the kernel is loaded.
+--- sle11sp1-2010-01-20.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:52:09.000000000 +0100
+@@ -770,9 +770,11 @@ ia32_sys_call_table:
+ 	.quad compat_sys_signalfd4
+ 	.quad sys_eventfd2
+ 	.quad sys_epoll_create1
+-	.quad sys_dup3			/* 330 */
++	.quad sys_dup3				/* 330 */
+ 	.quad sys_pipe2
+ 	.quad sys_inotify_init1
+ 	.quad compat_sys_preadv
+ 	.quad compat_sys_pwritev
++	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */
++	.quad sys_perf_counter_open
+ ia32_syscall_end:
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/hw_irq.h	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/hw_irq.h	2009-11-06 10:52:09.000000000 +0100
+@@ -121,6 +121,7 @@ extern asmlinkage void smp_invalidate_in
+ extern irqreturn_t smp_reschedule_interrupt(int, void *);
+ extern irqreturn_t smp_call_function_interrupt(int, void *);
+ extern irqreturn_t smp_call_function_single_interrupt(int, void *);
++extern irqreturn_t smp_reboot_interrupt(int, void *);
+ #endif
+ #endif
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/required-features.h	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/required-features.h	2009-11-20 11:04:37.000000000 +0100
+@@ -48,7 +48,7 @@
+ #endif
+ 
+ #ifdef CONFIG_X86_64
+-#ifdef CONFIG_PARAVIRT_MMU
++#if defined(CONFIG_PARAVIRT_MMU) || defined(CONFIG_XEN)
+ /* Paravirtualized systems may not have PSE or PGE available */
+ #define NEED_PSE	0
+ #define NEED_PGE	0
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:52:09.000000000 +0100
+@@ -31,6 +31,7 @@
+ /* Convert a physical address to an address suitable for the GART. */
+ #define phys_to_gart(x) phys_to_machine(x)
+ #define gart_to_phys(x) machine_to_phys(x)
++#define page_to_gart(x) phys_to_gart(page_to_pseudophys(x))
+ 
+ /* GATT allocation. Returns/accepts GATT kernel virtual address. */
+ #define alloc_gatt_pages(order)	({                                          \
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:52:09.000000000 +0100
+@@ -1,7 +1,6 @@
+ #ifndef _ASM_X86_DESC_H
+ #define _ASM_X86_DESC_H
+ 
+-#ifndef __ASSEMBLY__
+ #include <asm/desc_defs.h>
+ #include <asm/ldt.h>
+ #include <asm/mmu.h>
+@@ -406,29 +405,4 @@ static inline void set_system_intr_gate_
+ }
+ #endif
+ 
+-#else
+-/*
+- * GET_DESC_BASE reads the descriptor base of the specified segment.
+- *
+- * Args:
+- *    idx - descriptor index
+- *    gdt - GDT pointer
+- *    base - 32bit register to which the base will be written
+- *    lo_w - lo word of the "base" register
+- *    lo_b - lo byte of the "base" register
+- *    hi_b - hi byte of the low word of the "base" register
+- *
+- * Example:
+- *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+- *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+- */
+-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+-	movb idx * 8 + 4(gdt), lo_b;			\
+-	movb idx * 8 + 7(gdt), hi_b;			\
+-	shll $16, base;					\
+-	movw idx * 8 + 2(gdt), lo_w;
+-
+-
+-#endif /* __ASSEMBLY__ */
+-
+ #endif /* _ASM_X86_DESC_H */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:09.000000000 +0100
+@@ -118,12 +118,9 @@ enum fixed_addresses {
+ #ifdef CONFIG_PARAVIRT
+ 	FIX_PARAVIRT_BOOTMAP,
+ #endif
+-	FIX_TEXT_POKE0,	/* reserve 2 pages for text_poke() */
+-	FIX_TEXT_POKE1,
++	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
++	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
+ 	__end_of_permanent_fixed_addresses,
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	FIX_OHCI1394_BASE,
+-#endif
+ 	/*
+ 	 * 256 temporary boot-time mappings, used by early_ioremap(),
+ 	 * before ioremap() is functional.
+@@ -136,6 +133,9 @@ enum fixed_addresses {
+ 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+ 			(__end_of_permanent_fixed_addresses & 255),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
+ #ifdef CONFIG_X86_32
+ 	FIX_WP_TEST,
+ #endif
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-12-22 13:20:34.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:52:09.000000000 +0100
+@@ -1,8 +1,11 @@
+ #ifndef _ASM_X86_IRQ_VECTORS_H
+ #define _ASM_X86_IRQ_VECTORS_H
+ 
++#define MCE_VECTOR			0x12
++
+ #ifdef CONFIG_X86_32
+ # define SYSCALL_VECTOR			0x80
++# define IA32_SYSCALL_VECTOR		0x80
+ #else
+ # define IA32_SYSCALL_VECTOR		0x80
+ #endif
+@@ -11,7 +14,8 @@
+ #define CALL_FUNCTION_VECTOR		1
+ #define CALL_FUNC_SINGLE_VECTOR		2
+ #define SPIN_UNLOCK_VECTOR		3
+-#define NR_IPIS				4
++#define REBOOT_VECTOR			4
++#define NR_IPIS				5
+ 
+ /*
+  * The maximum number of vectors supported by i386 processors
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:52:09.000000000 +0100
+@@ -97,7 +97,8 @@ extern void pci_iommu_alloc(void);
+ 
+ #define PCI_DMA_BUS_IS_PHYS 0
+ 
+-#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG) || defined(CONFIG_SWIOTLB)
++#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG) \
++	|| defined(CONFIG_SWIOTLB)
+ 
+ #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
+ 	        dma_addr_t ADDR_NAME;
+@@ -136,6 +137,7 @@ extern void pci_iommu_alloc(void);
+ 
+ /* generic pci stuff */
+ #include <asm-generic/pci.h>
++#define PCIBIOS_MAX_MEM_32 0xffffffff
+ 
+ #ifdef CONFIG_NUMA
+ /* Returns the node based on pci bus */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:52:09.000000000 +0100
+@@ -51,7 +51,13 @@ static inline void pte_free(struct mm_st
+ 	__pte_free(pte);
+ }
+ 
+-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
++extern void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
++
++static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
++				  unsigned long address)
++{
++	___pte_free_tlb(tlb, pte);
++}
+ 
+ static inline void pmd_populate_kernel(struct mm_struct *mm,
+ 				       pmd_t *pmd, pte_t *pte)
+@@ -92,7 +98,13 @@ static inline void pmd_free(struct mm_st
+ 	__pmd_free(virt_to_page(pmd));
+ }
+ 
+-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++
++static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
++				  unsigned long adddress)
++{
++	___pmd_free_tlb(tlb, pmd);
++}
+ 
+ #ifdef CONFIG_X86_PAE
+ extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
+@@ -145,7 +157,14 @@ static inline void pud_free(struct mm_st
+ 	__pmd_free(virt_to_page(pud));
+ }
+ 
+-extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
++extern void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
++
++static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
++				  unsigned long address)
++{
++	___pud_free_tlb(tlb, pud);
++}
++
+ #endif	/* PAGETABLE_LEVELS > 3 */
+ #endif	/* PAGETABLE_LEVELS > 2 */
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-20 11:15:54.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-20 11:17:56.000000000 +0100
+@@ -2,6 +2,7 @@
+ #define _ASM_X86_PGTABLE_H
+ 
+ #include <asm/page.h>
++#include <asm/e820.h>
+ 
+ #include <asm/pgtable_types.h>
+ 
+@@ -78,6 +79,8 @@ static inline void __init paravirt_paget
+ #define pte_val(x)	xen_pte_val(x)
+ #define __pte(x)	xen_make_pte(x)
+ 
++#define arch_end_context_switch(prev)	do {} while(0)
++
+ /*
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+@@ -265,10 +268,17 @@ static inline pgprot_t pgprot_modify(pgp
+ 
+ #define canon_pgprot(p) __pgprot(massage_pgprot(p))
+ 
+-static inline int is_new_memtype_allowed(unsigned long flags,
+-						unsigned long new_flags)
++static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
++					 unsigned long flags,
++					 unsigned long new_flags)
+ {
+ 	/*
++	 * PAT type is always WB for ISA. So no need to check.
++	 */
++	if (is_ISA_range(paddr, paddr + size - 1))
++		return 1;
++
++	/*
+ 	 * Certain new memtypes are not allowed with certain
+ 	 * requested memtype:
+ 	 * - request is uncached, return cannot be write-back
+@@ -313,6 +323,11 @@ static inline int pte_present(pte_t a)
+ 	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
+ }
+ 
++static inline int pte_hidden(pte_t pte)
++{
++	return pte_flags(pte) & _PAGE_HIDDEN;
++}
++
+ static inline int pmd_present(pmd_t pmd)
+ {
+ #if CONFIG_XEN_COMPAT <= 0x030002
+@@ -512,6 +527,8 @@ static inline int pgd_none(pgd_t pgd)
+ 
+ #ifndef __ASSEMBLY__
+ 
++#define direct_gbpages 0
++
+ /* local pte updates need not use xchg for locking */
+ static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:52:09.000000000 +0100
+@@ -48,13 +48,17 @@ extern void set_pmd_pfn(unsigned long, u
+ #endif
+ 
+ #if defined(CONFIG_HIGHPTE)
++#define __KM_PTE			\
++	(in_nmi() ? KM_NMI_PTE : 	\
++	 in_irq() ? KM_IRQ_PTE :	\
++	 KM_PTE0)
+ #define pte_offset_map(dir, address)					\
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) +		\
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) +		\
+ 	 pte_index((address)))
+ #define pte_offset_map_nested(dir, address)				\
+ 	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
+ 	 pte_index((address)))
+-#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
++#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
+ #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+ #else
+ #define pte_offset_map(dir, address)					\
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:52:09.000000000 +0100
+@@ -33,10 +33,6 @@ extern pgd_t init_level4_pgt[];
+ 
+ extern void paging_init(void);
+ 
+-#endif /* !__ASSEMBLY__ */
+-
+-#ifndef __ASSEMBLY__
+-
+ #define pte_ERROR(e)							\
+ 	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
+@@ -142,8 +138,6 @@ static inline int pgd_large(pgd_t pgd) {
+ 
+ #define update_mmu_cache(vma, address, pte) do { } while (0)
+ 
+-#define direct_gbpages 0
+-
+ /* Encode and de-code a swap entry */
+ #if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
+ #define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
+@@ -178,10 +172,7 @@ extern void cleanup_highmap(void);
+ 
+ /* fs/proc/kcore.c */
+ #define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+-#define	kc_offset_to_vaddr(o)				\
+-	(((o) & (1UL << (__VIRTUAL_MASK_SHIFT - 1)))	\
+-	 ? ((o) | ~__VIRTUAL_MASK)			\
+-	 : (o))
++#define	kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
+ 
+ #define __HAVE_ARCH_PTE_SAME
+ #endif /* !__ASSEMBLY__ */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_64_types.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_64_types.h	2009-11-06 10:52:09.000000000 +0100
+@@ -51,11 +51,12 @@ typedef union { pteval_t pte; unsigned i
+ #define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
++/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
+ #define MAX_PHYSMEM_BITS 43
+ #define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
+-#define VMALLOC_START    _AC(0xffffc20000000000, UL)
+-#define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+-#define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
++#define VMALLOC_START    _AC(0xffffc90000000000, UL)
++#define VMALLOC_END      _AC(0xffffe8ffffffffff, UL)
++#define VMEMMAP_START	 _AC(0xffffea0000000000, UL)
+ #define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+ #define MODULES_END      _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_types.h	2009-11-06 10:52:09.000000000 +0100
+@@ -18,7 +18,7 @@
+ #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+ #define _PAGE_BIT_UNUSED1	9	/* available for programmer */
+ #define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
+-#define _PAGE_BIT_UNUSED3	11
++#define _PAGE_BIT_HIDDEN	11	/* hidden by kmemcheck */
+ #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
+ #define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
+ #define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
+@@ -41,13 +41,18 @@
+ #define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
+ #define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
+ #define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
+-#define _PAGE_UNUSED3	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
+ #define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
+ #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+ #define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
+ #define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
+ #define __HAVE_ARCH_PTE_SPECIAL
+ 
++#ifdef CONFIG_KMEMCHECK
++#define _PAGE_HIDDEN	(_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
++#else
++#define _PAGE_HIDDEN	(_AT(pteval_t, 0))
++#endif
++
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+ #define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
+ #else
+@@ -330,7 +335,6 @@ typedef struct page *pgtable_t;
+ 
+ extern pteval_t __supported_pte_mask;
+ extern int nx_enabled;
+-extern void set_nx(void);
+ 
+ #define pgprot_writecombine	pgprot_writecombine
+ extern pgprot_t pgprot_writecombine(pgprot_t prot);
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:52:09.000000000 +0100
+@@ -136,7 +136,8 @@ struct cpuinfo_x86 {
+ extern struct cpuinfo_x86	boot_cpu_data;
+ extern struct cpuinfo_x86	new_cpu_data;
+ 
+-extern __u32			cleared_cpu_caps[NCAPINTS];
++extern __u32			cpu_caps_cleared[NCAPINTS];
++extern __u32			cpu_caps_set[NCAPINTS];
+ 
+ #ifdef CONFIG_SMP
+ DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+@@ -417,9 +418,6 @@ DECLARE_PER_CPU(unsigned long, stack_can
+ extern unsigned int xstate_size;
+ extern void free_thread_xstate(struct task_struct *);
+ extern struct kmem_cache *task_xstate_cachep;
+-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+-extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+-extern unsigned short num_cache_leaves;
+ 
+ struct thread_struct {
+ 	/* Cached TLS descriptors: */
+@@ -435,8 +433,12 @@ struct thread_struct {
+ 	unsigned short		fsindex;
+ 	unsigned short		gsindex;
+ #endif
++#ifdef CONFIG_X86_32
+ 	unsigned long		ip;
++#endif
++#ifdef CONFIG_X86_64
+ 	unsigned long		fs;
++#endif
+ 	unsigned long		gs;
+ 	/* Hardware debugging registers: */
+ 	unsigned long		debugreg0;
+@@ -465,14 +467,8 @@ struct thread_struct {
+ 	unsigned		io_bitmap_max;
+ /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
+ 	unsigned long	debugctlmsr;
+-#ifdef CONFIG_X86_DS
+-/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
++	/* Debug Store context; see asm/ds.h */
+ 	struct ds_context	*ds_ctx;
+-#endif /* CONFIG_X86_DS */
+-#ifdef CONFIG_X86_PTRACE_BTS
+-/* the signal to send on a bts buffer overflow */
+-	unsigned int	bts_ovfl_signal;
+-#endif /* CONFIG_X86_PTRACE_BTS */
+ };
+ 
+ static inline unsigned long xen_get_debugreg(int regno)
+@@ -742,6 +738,21 @@ static inline unsigned long get_debugctl
+     return debugctlmsr;
+ }
+ 
++static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
++{
++	u64 debugctlmsr = 0;
++	u32 val1, val2;
++
++#ifndef CONFIG_X86_DEBUGCTLMSR
++	if (boot_cpu_data.x86 < 6)
++		return 0;
++#endif
++	rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
++	debugctlmsr = val1 | ((u64)val2 << 32);
++
++	return debugctlmsr;
++}
++
+ static inline void update_debugctlmsr(unsigned long debugctlmsr)
+ {
+ #ifndef CONFIG_X86_DEBUGCTLMSR
+@@ -751,6 +762,18 @@ static inline void update_debugctlmsr(un
+ 	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
+ }
+ 
++static inline void update_debugctlmsr_on_cpu(int cpu,
++					     unsigned long debugctlmsr)
++{
++#ifndef CONFIG_X86_DEBUGCTLMSR
++	if (boot_cpu_data.x86 < 6)
++		return;
++#endif
++	wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
++		     (u32)((u64)debugctlmsr),
++		     (u32)((u64)debugctlmsr >> 32));
++}
++
+ /*
+  * from system description table in BIOS. Mostly for MCA use, but
+  * others may find it useful:
+@@ -761,6 +784,7 @@ extern unsigned int		BIOS_revision;
+ 
+ /* Boot loader type from the setup header: */
+ extern int			bootloader_type;
++extern int			bootloader_version;
+ 
+ extern char			ignore_fpu_irq;
+ 
+@@ -821,7 +845,6 @@ static inline void spin_lock_prefetch(co
+ 	.vm86_info		= NULL,					  \
+ 	.sysenter_cs		= __KERNEL_CS,				  \
+ 	.io_bitmap_ptr		= NULL,					  \
+-	.fs			= __KERNEL_PERCPU,			  \
+ }
+ 
+ /*
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:15:20.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:17:59.000000000 +0100
+@@ -195,7 +195,7 @@ extern unsigned disabled_cpus __cpuinitd
+ static inline int logical_smp_processor_id(void)
+ {
+ 	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++	return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
+ }
+ 
+ #endif
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:53.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:31:08.000000000 +0100
+@@ -427,4 +427,8 @@ static inline void __raw_write_unlock(ra
+ #define _raw_read_relax(lock)	cpu_relax()
+ #define _raw_write_relax(lock)	cpu_relax()
+ 
++/* The {read|write|spin}_lock() on x86 are full memory barriers. */
++static inline void smp_mb__after_lock(void) { }
++#define ARCH_HAS_SMP_MB_AFTER_LOCK
++
+ #endif /* _ASM_X86_SPINLOCK_H */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:52:09.000000000 +0100
+@@ -111,6 +111,6 @@ static inline void flush_tlb_kernel_rang
+ 	flush_tlb_all();
+ }
+ 
+-extern void zap_low_mappings(void);
++extern void zap_low_mappings(bool early);
+ 
+ #endif /* _ASM_X86_TLBFLUSH_H */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/xor.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/xor.h	2009-11-06 10:52:09.000000000 +0100
+@@ -1,4 +1,7 @@
+-#ifdef CONFIG_X86_32
++#ifdef CONFIG_KMEMCHECK
++/* kmemcheck doesn't handle MMX/SSE/SSE2 instructions */
++# include <asm-generic/xor.h>
++#elif defined(CONFIG_X86_32)
+ # include "../../asm/xor_32.h"
+ #else
+ # include "xor_64.h"
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/Makefile	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/Makefile	2009-11-06 10:52:09.000000000 +0100
+@@ -137,6 +137,6 @@ ifeq ($(CONFIG_X86_64),y)
+ endif
+ 
+ disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
+-	i8259.o irqinit_$(BITS).o pci-swiotlb.o reboot.o smpboot.o tsc.o \
+-	tsc_sync.o uv_%.o vsmp_64.o
++	i8259.o irqinit.o pci-swiotlb.o reboot.o smpboot.o tsc.o tsc_sync.o \
++	uv_%.o vsmp_64.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -107,7 +107,7 @@ int acpi_save_state_mem(void)
+ 	initial_gs = per_cpu_offset(smp_processor_id());
+ #endif
+ 	initial_code = (unsigned long)wakeup_long64;
+-	saved_magic = 0x123456789abcdef0;
++       saved_magic = 0x123456789abcdef0L;
+ #endif /* CONFIG_64BIT */
+ #endif
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -59,6 +59,7 @@
+ #include <asm/setup.h>
+ #include <asm/irq_remapping.h>
+ #include <asm/hpet.h>
++#include <asm/hw_irq.h>
+ #include <asm/uv/uv_hub.h>
+ #include <asm/uv/uv_irq.h>
+ 
+@@ -145,12 +146,9 @@ struct irq_pin_list {
+ 	struct irq_pin_list *next;
+ };
+ 
+-static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
++static struct irq_pin_list *get_one_free_irq_2_pin(int node)
+ {
+ 	struct irq_pin_list *pin;
+-	int node;
+-
+-	node = cpu_to_node(cpu);
+ 
+ 	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
+ 
+@@ -164,9 +162,6 @@ struct irq_cfg {
+ 	unsigned move_cleanup_count;
+ 	u8 vector;
+ 	u8 move_in_progress : 1;
+-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
+-	u8 move_desc_pending : 1;
+-#endif
+ };
+ 
+ /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+@@ -198,16 +193,18 @@ int __init arch_early_irq_init(void)
+ 	struct irq_cfg *cfg;
+ 	struct irq_desc *desc;
+ 	int count;
++	int node;
+ 	int i;
+ 
+ 	cfg = irq_cfgx;
+ 	count = ARRAY_SIZE(irq_cfgx);
++	node= cpu_to_node(boot_cpu_id);
+ 
+ 	for (i = 0; i < count; i++) {
+ 		desc = irq_to_desc(i);
+ 		desc->chip_data = &cfg[i];
+-		alloc_bootmem_cpumask_var(&cfg[i].domain);
+-		alloc_bootmem_cpumask_var(&cfg[i].old_domain);
++		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
++		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+ 		if (i < NR_IRQS_LEGACY)
+ 			cpumask_setall(cfg[i].domain);
+ 	}
+@@ -228,12 +225,9 @@ static struct irq_cfg *irq_cfg(unsigned 
+ 	return cfg;
+ }
+ 
+-static struct irq_cfg *get_one_free_irq_cfg(int cpu)
++static struct irq_cfg *get_one_free_irq_cfg(int node)
+ {
+ 	struct irq_cfg *cfg;
+-	int node;
+-
+-	node = cpu_to_node(cpu);
+ 
+ 	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
+ 	if (cfg) {
+@@ -254,13 +248,13 @@ static struct irq_cfg *get_one_free_irq_
+ 	return cfg;
+ }
+ 
+-int arch_init_chip_data(struct irq_desc *desc, int cpu)
++int arch_init_chip_data(struct irq_desc *desc, int node)
+ {
+ 	struct irq_cfg *cfg;
+ 
+ 	cfg = desc->chip_data;
+ 	if (!cfg) {
+-		desc->chip_data = get_one_free_irq_cfg(cpu);
++		desc->chip_data = get_one_free_irq_cfg(node);
+ 		if (!desc->chip_data) {
+ 			printk(KERN_ERR "can not alloc irq_cfg\n");
+ 			BUG_ON(1);
+@@ -270,10 +264,9 @@ int arch_init_chip_data(struct irq_desc 
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
+-
++/* for move_irq_desc */
+ static void
+-init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
++init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
+ {
+ 	struct irq_pin_list *old_entry, *head, *tail, *entry;
+ 
+@@ -282,7 +275,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_
+ 	if (!old_entry)
+ 		return;
+ 
+-	entry = get_one_free_irq_2_pin(cpu);
++	entry = get_one_free_irq_2_pin(node);
+ 	if (!entry)
+ 		return;
+ 
+@@ -292,7 +285,7 @@ init_copy_irq_2_pin(struct irq_cfg *old_
+ 	tail		= entry;
+ 	old_entry	= old_entry->next;
+ 	while (old_entry) {
+-		entry = get_one_free_irq_2_pin(cpu);
++		entry = get_one_free_irq_2_pin(node);
+ 		if (!entry) {
+ 			entry = head;
+ 			while (entry) {
+@@ -332,12 +325,12 @@ static void free_irq_2_pin(struct irq_cf
+ }
+ 
+ void arch_init_copy_chip_data(struct irq_desc *old_desc,
+-				 struct irq_desc *desc, int cpu)
++				 struct irq_desc *desc, int node)
+ {
+ 	struct irq_cfg *cfg;
+ 	struct irq_cfg *old_cfg;
+ 
+-	cfg = get_one_free_irq_cfg(cpu);
++	cfg = get_one_free_irq_cfg(node);
+ 
+ 	if (!cfg)
+ 		return;
+@@ -348,7 +341,7 @@ void arch_init_copy_chip_data(struct irq
+ 
+ 	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
+ 
+-	init_copy_irq_2_pin(old_cfg, cfg, cpu);
++	init_copy_irq_2_pin(old_cfg, cfg, node);
+ }
+ 
+ static void free_irq_cfg(struct irq_cfg *old_cfg)
+@@ -372,19 +365,7 @@ void arch_free_chip_data(struct irq_desc
+ 		old_desc->chip_data = NULL;
+ 	}
+ }
+-
+-static void
+-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
+-{
+-	struct irq_cfg *cfg = desc->chip_data;
+-
+-	if (!cfg->move_in_progress) {
+-		/* it means that domain is not changed */
+-		if (!cpumask_intersects(desc->affinity, mask))
+-			cfg->move_desc_pending = 1;
+-	}
+-}
+-#endif
++/* end for move_irq_desc */
+ 
+ #else
+ static struct irq_cfg *irq_cfg(unsigned int irq)
+@@ -394,13 +375,6 @@ static struct irq_cfg *irq_cfg(unsigned 
+ 
+ #endif
+ 
+-#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
+-static inline void
+-set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
+-{
+-}
+-#endif
+-
+ struct io_apic {
+ 	unsigned int index;
+ 	unsigned int unused[3];
+@@ -532,7 +506,8 @@ static struct IO_APIC_route_entry ioapic
+ static void
+ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+ {
+-	union entry_union eu;
++	union entry_union eu = {{0, 0}};
++
+ 	eu.entry = e;
+ 	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+ 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+@@ -563,132 +538,18 @@ static void ioapic_mask_entry(int apic, 
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+-#ifdef CONFIG_SMP
+-static void send_cleanup_vector(struct irq_cfg *cfg)
+-{
+-	cpumask_var_t cleanup_mask;
+-
+-	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+-		unsigned int i;
+-		cfg->move_cleanup_count = 0;
+-		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+-			cfg->move_cleanup_count++;
+-		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+-			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+-	} else {
+-		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+-		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+-		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+-		free_cpumask_var(cleanup_mask);
+-	}
+-	cfg->move_in_progress = 0;
+-}
+-
+-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+-{
+-	int apic, pin;
+-	struct irq_pin_list *entry;
+-	u8 vector = cfg->vector;
+-
+-	entry = cfg->irq_2_pin;
+-	for (;;) {
+-		unsigned int reg;
+-
+-		if (!entry)
+-			break;
+-
+-		apic = entry->apic;
+-		pin = entry->pin;
+-		/*
+-		 * With interrupt-remapping, destination information comes
+-		 * from interrupt-remapping table entry.
+-		 */
+-		if (!irq_remapped(irq))
+-			io_apic_write(apic, 0x11 + pin*2, dest);
+-		reg = io_apic_read(apic, 0x10 + pin*2);
+-		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+-		reg |= vector;
+-		io_apic_modify(apic, 0x10 + pin*2, reg);
+-		if (!entry->next)
+-			break;
+-		entry = entry->next;
+-	}
+-}
+-
+-static int
+-assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+-
+-/*
+- * Either sets desc->affinity to a valid value, and returns
+- * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+- * leaves desc->affinity untouched.
+- */
+-static unsigned int
+-set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+-{
+-	struct irq_cfg *cfg;
+-	unsigned int irq;
+-
+-	if (!cpumask_intersects(mask, cpu_online_mask))
+-		return BAD_APICID;
+-
+-	irq = desc->irq;
+-	cfg = desc->chip_data;
+-	if (assign_irq_vector(irq, cfg, mask))
+-		return BAD_APICID;
+-
+-	/* check that before desc->addinity get updated */
+-	set_extra_move_desc(desc, mask);
+-
+-	cpumask_copy(desc->affinity, mask);
+-
+-	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+-}
+-
+-static void
+-set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+-{
+-	struct irq_cfg *cfg;
+-	unsigned long flags;
+-	unsigned int dest;
+-	unsigned int irq;
+-
+-	irq = desc->irq;
+-	cfg = desc->chip_data;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	dest = set_desc_affinity(desc, mask);
+-	if (dest != BAD_APICID) {
+-		/* Only the high 8 bits are valid. */
+-		dest = SET_APIC_LOGICAL_ID(dest);
+-		__target_IO_APIC_irq(irq, dest, cfg);
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-static void
+-set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+-{
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+-
+-	set_ioapic_affinity_irq_desc(desc, mask);
+-}
+-#endif /* CONFIG_SMP */
+-
+ /*
+  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+  * shared ISA-space IRQs, so we have to support them. We are super
+  * fast in the common case, and fast for shared ISA-space IRQs.
+  */
+-static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
++static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
+ {
+ 	struct irq_pin_list *entry;
+ 
+ 	entry = cfg->irq_2_pin;
+ 	if (!entry) {
+-		entry = get_one_free_irq_2_pin(cpu);
++		entry = get_one_free_irq_2_pin(node);
+ 		if (!entry) {
+ 			printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
+ 					apic, pin);
+@@ -708,7 +569,7 @@ static void add_pin_to_irq_cpu(struct ir
+ 		entry = entry->next;
+ 	}
+ 
+-	entry->next = get_one_free_irq_2_pin(cpu);
++	entry->next = get_one_free_irq_2_pin(node);
+ 	entry = entry->next;
+ 	entry->apic = apic;
+ 	entry->pin = pin;
+@@ -717,7 +578,7 @@ static void add_pin_to_irq_cpu(struct ir
+ /*
+  * Reroute an IRQ to a different pin.
+  */
+-static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
++static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
+ 				      int oldapic, int oldpin,
+ 				      int newapic, int newpin)
+ {
+@@ -737,7 +598,7 @@ static void __init replace_pin_at_irq_cp
+ 
+ 	/* why? call replace before add? */
+ 	if (!replaced)
+-		add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
++		add_pin_to_irq_node(cfg, node, newapic, newpin);
+ }
+ 
+ static inline void io_apic_modify_irq(struct irq_cfg *cfg,
+@@ -857,7 +718,7 @@ static void clear_IO_APIC (void)
+ 			clear_IO_APIC_pin(apic, pin);
+ }
+ #else
+-#define add_pin_to_irq_cpu(cfg, cpu, apic, pin)
++#define add_pin_to_irq_node(cfg, node, apic, pin)
+ #endif /* CONFIG_XEN */
+ 
+ #ifdef CONFIG_X86_32
+@@ -898,7 +759,7 @@ static int __init ioapic_pirq_setup(char
+ __setup("pirq=", ioapic_pirq_setup);
+ #endif /* CONFIG_X86_32 */
+ 
+-#ifdef CONFIG_INTR_REMAP
++#ifndef CONFIG_XEN
+ struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+ {
+ 	int apic;
+@@ -996,20 +857,6 @@ int restore_IO_APIC_setup(struct IO_APIC
+ 	return 0;
+ }
+ 
+-void reinit_intr_remapped_IO_APIC(int intr_remapping,
+-	struct IO_APIC_route_entry **ioapic_entries)
+-
+-{
+-	/*
+-	 * for now plain restore of previous settings.
+-	 * TBD: In the case of OS enabling interrupt-remapping,
+-	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
+-	 * table entries. for now, do a plain restore, and wait for
+-	 * the setup_IO_APIC_irqs() to do proper initialization.
+-	 */
+-	restore_IO_APIC_setup(ioapic_entries);
+-}
+-
+ void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
+ {
+ 	int apic;
+@@ -1019,7 +866,7 @@ void free_ioapic_entries(struct IO_APIC_
+ 
+ 	kfree(ioapic_entries);
+ }
+-#endif
++#endif /* CONFIG_XEN */
+ 
+ /*
+  * Find the IRQ entry number of a certain pin.
+@@ -1082,54 +929,6 @@ static int __init find_isa_irq_apic(int 
+ }
+ #endif
+ 
+-/*
+- * Find a specific PCI IRQ entry.
+- * Not an __init, possibly needed by modules
+- */
+-static int pin_2_irq(int idx, int apic, int pin);
+-
+-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+-{
+-	int apic, i, best_guess = -1;
+-
+-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+-		bus, slot, pin);
+-	if (test_bit(bus, mp_bus_not_pci)) {
+-		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+-		return -1;
+-	}
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].srcbus;
+-
+-		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
+-			    mp_irqs[i].dstapic == MP_APIC_ALL)
+-				break;
+-
+-		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].irqtype &&
+-		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+-
+-			if (!(apic || IO_APIC_IRQ(irq)))
+-				continue;
+-
+-			if (pin == (mp_irqs[i].srcbusirq & 3))
+-				return irq;
+-			/*
+-			 * Use the first all-but-pin matching entry as a
+-			 * best-guess fuzzy result for broken mptables.
+-			 */
+-			if (best_guess < 0)
+-				best_guess = irq;
+-		}
+-	}
+-	return best_guess;
+-}
+-
+-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+-
+ #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ /*
+  * EISA Edge/Level control register, ELCR
+@@ -1348,6 +1147,64 @@ static int pin_2_irq(int idx, int apic, 
+ 	return irq;
+ }
+ 
++/*
++ * Find a specific PCI IRQ entry.
++ * Not an __init, possibly needed by modules
++ */
++int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
++				struct io_apic_irq_attr *irq_attr)
++{
++	int apic, i, best_guess = -1;
++
++	apic_printk(APIC_DEBUG,
++		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
++		    bus, slot, pin);
++	if (test_bit(bus, mp_bus_not_pci)) {
++		apic_printk(APIC_VERBOSE,
++			    "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
++		return -1;
++	}
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].srcbus;
++
++		for (apic = 0; apic < nr_ioapics; apic++)
++			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
++			    mp_irqs[i].dstapic == MP_APIC_ALL)
++				break;
++
++		if (!test_bit(lbus, mp_bus_not_pci) &&
++		    !mp_irqs[i].irqtype &&
++		    (bus == lbus) &&
++		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
++
++			if (!(apic || IO_APIC_IRQ(irq)))
++				continue;
++
++			if (pin == (mp_irqs[i].srcbusirq & 3)) {
++				set_io_apic_irq_attr(irq_attr, apic,
++						     mp_irqs[i].dstirq,
++						     irq_trigger(i),
++						     irq_polarity(i));
++				return irq;
++			}
++			/*
++			 * Use the first all-but-pin matching entry as a
++			 * best-guess fuzzy result for broken mptables.
++			 */
++			if (best_guess < 0) {
++				set_io_apic_irq_attr(irq_attr, apic,
++						     mp_irqs[i].dstirq,
++						     irq_trigger(i),
++						     irq_polarity(i));
++				best_guess = irq;
++			}
++		}
++	}
++	return best_guess;
++}
++EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
++
+ #ifndef CONFIG_XEN
+ void lock_vector_lock(void)
+ {
+@@ -1619,6 +1476,9 @@ int setup_ioapic_entry(int apic_id, int 
+ 		irte.vector = vector;
+ 		irte.dest_id = IRTE_DEST(destination);
+ 
++		/* Set source-id of interrupt request */
++		set_ioapic_sid(&irte, apic_id);
++
+ 		modify_irte(irq, &irte);
+ 
+ 		ir_entry->index2 = (index >> 15) & 0x1;
+@@ -1693,63 +1553,75 @@ static void setup_IO_APIC_irq(int apic_i
+ 	ioapic_write_entry(apic_id, pin, entry);
+ }
+ 
++static struct {
++	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
++} mp_ioapic_routing[MAX_IO_APICS];
++
+ static void __init setup_IO_APIC_irqs(void)
+ {
+-	int apic_id, pin, idx, irq;
++	int apic_id = 0, pin, idx, irq;
+ 	int notcon = 0;
+ 	struct irq_desc *desc;
+ 	struct irq_cfg *cfg;
+-	int cpu = boot_cpu_id;
++	int node = cpu_to_node(boot_cpu_id);
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
+-		for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
++#ifdef CONFIG_ACPI
++	if (!acpi_disabled && acpi_ioapic) {
++		apic_id = mp_find_ioapic(0);
++		if (apic_id < 0)
++			apic_id = 0;
++	}
++#endif
+ 
+-			idx = find_irq_entry(apic_id, pin, mp_INT);
+-			if (idx == -1) {
+-				if (!notcon) {
+-					notcon = 1;
+-					apic_printk(APIC_VERBOSE,
+-						KERN_DEBUG " %d-%d",
+-						mp_ioapics[apic_id].apicid, pin);
+-				} else
+-					apic_printk(APIC_VERBOSE, " %d-%d",
+-						mp_ioapics[apic_id].apicid, pin);
+-				continue;
+-			}
+-			if (notcon) {
++	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
++		idx = find_irq_entry(apic_id, pin, mp_INT);
++		if (idx == -1) {
++			if (!notcon) {
++				notcon = 1;
+ 				apic_printk(APIC_VERBOSE,
+-					" (apicid-pin) not connected\n");
+-				notcon = 0;
+-			}
++					KERN_DEBUG " %d-%d",
++					mp_ioapics[apic_id].apicid, pin);
++			} else
++				apic_printk(APIC_VERBOSE, " %d-%d",
++					mp_ioapics[apic_id].apicid, pin);
++			continue;
++		}
++		if (notcon) {
++			apic_printk(APIC_VERBOSE,
++				" (apicid-pin) not connected\n");
++			notcon = 0;
++		}
+ 
+-			irq = pin_2_irq(idx, apic_id, pin);
++		irq = pin_2_irq(idx, apic_id, pin);
+ 
+ #if defined(CONFIG_XEN)
+-			if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+-				continue;
++		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
++			continue;
+ #else
+-			/*
+-			 * Skip the timer IRQ if there's a quirk handler
+-			 * installed and if it returns 1:
+-			 */
+-			if (apic->multi_timer_check &&
+-					apic->multi_timer_check(apic_id, irq))
+-				continue;
++		/*
++		 * Skip the timer IRQ if there's a quirk handler
++		 * installed and if it returns 1:
++		 */
++		if (apic->multi_timer_check &&
++				apic->multi_timer_check(apic_id, irq))
++			continue;
+ #endif
+ 
+-			desc = irq_to_desc_alloc_cpu(irq, cpu);
+-			if (!desc) {
+-				printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+-				continue;
+-			}
+-			cfg = desc->chip_data;
+-			add_pin_to_irq_cpu(cfg, cpu, apic_id, pin);
+-
+-			setup_IO_APIC_irq(apic_id, pin, irq, desc,
+-					irq_trigger(idx), irq_polarity(idx));
++		desc = irq_to_desc_alloc_node(irq, node);
++		if (!desc) {
++			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
++			continue;
+ 		}
++		cfg = desc->chip_data;
++		add_pin_to_irq_node(cfg, node, apic_id, pin);
++		/*
++		 * don't mark it in pin_programmed, so later acpi could
++		 * set it correctly when irq < 16
++		 */
++		setup_IO_APIC_irq(apic_id, pin, irq, desc,
++				irq_trigger(idx), irq_polarity(idx));
+ 	}
+ 
+ 	if (notcon)
+@@ -1917,36 +1789,30 @@ __apicdebuginit(void) print_IO_APIC(void
+ 	return;
+ }
+ 
+-__apicdebuginit(void) print_APIC_bitfield(int base)
++__apicdebuginit(void) print_APIC_field(int base)
+ {
+-	unsigned int v;
+-	int i, j;
++	int i;
+ 
+ 	if (apic_verbosity == APIC_QUIET)
+ 		return;
+ 
+-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
+-	for (i = 0; i < 8; i++) {
+-		v = apic_read(base + i*0x10);
+-		for (j = 0; j < 32; j++) {
+-			if (v & (1<<j))
+-				printk("1");
+-			else
+-				printk("0");
+-		}
+-		printk("\n");
+-	}
++	printk(KERN_DEBUG);
++
++	for (i = 0; i < 8; i++)
++		printk(KERN_CONT "%08x", apic_read(base + i*0x10));
++
++	printk(KERN_CONT "\n");
+ }
+ 
+ __apicdebuginit(void) print_local_APIC(void *dummy)
+ {
+-	unsigned int v, ver, maxlvt;
++	unsigned int i, v, ver, maxlvt;
+ 	u64 icr;
+ 
+ 	if (apic_verbosity == APIC_QUIET)
+ 		return;
+ 
+-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
++	printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+ 		smp_processor_id(), hard_smp_processor_id());
+ 	v = apic_read(APIC_ID);
+ 	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
+@@ -1987,11 +1853,11 @@ __apicdebuginit(void) print_local_APIC(v
+ 	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
+ 
+ 	printk(KERN_DEBUG "... APIC ISR field:\n");
+-	print_APIC_bitfield(APIC_ISR);
++	print_APIC_field(APIC_ISR);
+ 	printk(KERN_DEBUG "... APIC TMR field:\n");
+-	print_APIC_bitfield(APIC_TMR);
++	print_APIC_field(APIC_TMR);
+ 	printk(KERN_DEBUG "... APIC IRR field:\n");
+-	print_APIC_bitfield(APIC_IRR);
++	print_APIC_field(APIC_IRR);
+ 
+ 	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
+ 		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
+@@ -2028,6 +1894,18 @@ __apicdebuginit(void) print_local_APIC(v
+ 	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
+ 	v = apic_read(APIC_TDCR);
+ 	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
++
++	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
++		v = apic_read(APIC_EFEAT);
++		maxlvt = (v >> 16) & 0xff;
++		printk(KERN_DEBUG "... APIC EFEAT: %08x\n", v);
++		v = apic_read(APIC_ECTRL);
++		printk(KERN_DEBUG "... APIC ECTRL: %08x\n", v);
++		for (i = 0; i < maxlvt; i++) {
++			v = apic_read(APIC_EILVTn(i));
++			printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
++		}
++	}
+ 	printk("\n");
+ }
+ 
+@@ -2076,6 +1954,11 @@ __apicdebuginit(void) print_PIC(void)
+ __apicdebuginit(int) print_all_ICs(void)
+ {
+ 	print_PIC();
++
++	/* don't print out if apic is not there */
++	if (!cpu_has_apic || disable_apic)
++		return 0;
++
+ 	print_all_local_APICs();
+ 	print_IO_APIC();
+ 
+@@ -2199,7 +2082,9 @@ void disable_IO_APIC(void)
+ 	/*
+ 	 * Use virtual wire A mode when interrupt remapping is enabled.
+ 	 */
+-	disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
++	if (cpu_has_apic)
++		disconnect_bsp_APIC(!intr_remapping_enabled &&
++				ioapic_i8259.pin != -1);
+ }
+ 
+ #ifdef CONFIG_X86_32
+@@ -2438,7 +2323,119 @@ static int ioapic_retrigger_irq(unsigned
+  * races.
+  */
+ 
+-#ifdef CONFIG_SMP
++#ifdef CONFIG_SMP
++static void send_cleanup_vector(struct irq_cfg *cfg)
++{
++	cpumask_var_t cleanup_mask;
++
++	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
++		unsigned int i;
++		cfg->move_cleanup_count = 0;
++		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
++			cfg->move_cleanup_count++;
++		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
++			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
++	} else {
++		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
++		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
++		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		free_cpumask_var(cleanup_mask);
++	}
++	cfg->move_in_progress = 0;
++}
++
++static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
++{
++	int apic, pin;
++	struct irq_pin_list *entry;
++	u8 vector = cfg->vector;
++
++	entry = cfg->irq_2_pin;
++	for (;;) {
++		unsigned int reg;
++
++		if (!entry)
++			break;
++
++		apic = entry->apic;
++		pin = entry->pin;
++		/*
++		 * With interrupt-remapping, destination information comes
++		 * from interrupt-remapping table entry.
++		 */
++		if (!irq_remapped(irq))
++			io_apic_write(apic, 0x11 + pin*2, dest);
++		reg = io_apic_read(apic, 0x10 + pin*2);
++		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
++		reg |= vector;
++		io_apic_modify(apic, 0x10 + pin*2, reg);
++		if (!entry->next)
++			break;
++		entry = entry->next;
++	}
++}
++
++static int
++assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
++
++/*
++ * Either sets desc->affinity to a valid value, and returns
++ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
++ * leaves desc->affinity untouched.
++ */
++static unsigned int
++set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
++{
++	struct irq_cfg *cfg;
++	unsigned int irq;
++
++	if (!cpumask_intersects(mask, cpu_online_mask))
++		return BAD_APICID;
++
++	irq = desc->irq;
++	cfg = desc->chip_data;
++	if (assign_irq_vector(irq, cfg, mask))
++		return BAD_APICID;
++
++	cpumask_copy(desc->affinity, mask);
++
++	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
++}
++
++static int
++set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
++{
++	struct irq_cfg *cfg;
++	unsigned long flags;
++	unsigned int dest;
++	unsigned int irq;
++	int ret = -1;
++
++	irq = desc->irq;
++	cfg = desc->chip_data;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	dest = set_desc_affinity(desc, mask);
++	if (dest != BAD_APICID) {
++		/* Only the high 8 bits are valid. */
++		dest = SET_APIC_LOGICAL_ID(dest);
++		__target_IO_APIC_irq(irq, dest, cfg);
++		ret = 0;
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return ret;
++}
++
++static int
++set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
++{
++	struct irq_desc *desc;
++
++	desc = irq_to_desc(irq);
++
++	return set_ioapic_affinity_irq_desc(desc, mask);
++}
+ 
+ #ifdef CONFIG_INTR_REMAP
+ 
+@@ -2453,26 +2450,25 @@ static int ioapic_retrigger_irq(unsigned
+  * Real vector that is used for interrupting cpu will be coming from
+  * the interrupt-remapping table entry.
+  */
+-static void
++static int
+ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ {
+ 	struct irq_cfg *cfg;
+ 	struct irte irte;
+ 	unsigned int dest;
+ 	unsigned int irq;
++	int ret = -1;
+ 
+ 	if (!cpumask_intersects(mask, cpu_online_mask))
+-		return;
++		return ret;
+ 
+ 	irq = desc->irq;
+ 	if (get_irte(irq, &irte))
+-		return;
++		return ret;
+ 
+ 	cfg = desc->chip_data;
+ 	if (assign_irq_vector(irq, cfg, mask))
+-		return;
+-
+-	set_extra_move_desc(desc, mask);
++		return ret;
+ 
+ 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+ 
+@@ -2488,27 +2484,30 @@ migrate_ioapic_irq_desc(struct irq_desc 
+ 		send_cleanup_vector(cfg);
+ 
+ 	cpumask_copy(desc->affinity, mask);
++
++	return 0;
+ }
+ 
+ /*
+  * Migrates the IRQ destination in the process context.
+  */
+-static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
++static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+ 					    const struct cpumask *mask)
+ {
+-	migrate_ioapic_irq_desc(desc, mask);
++	return migrate_ioapic_irq_desc(desc, mask);
+ }
+-static void set_ir_ioapic_affinity_irq(unsigned int irq,
++static int set_ir_ioapic_affinity_irq(unsigned int irq,
+ 				       const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+ 
+-	set_ir_ioapic_affinity_irq_desc(desc, mask);
++	return set_ir_ioapic_affinity_irq_desc(desc, mask);
+ }
+ #else
+-static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
++static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+ 						   const struct cpumask *mask)
+ {
++	return 0;
+ }
+ #endif
+ 
+@@ -2570,86 +2569,19 @@ static void irq_complete_move(struct irq
+ 	struct irq_cfg *cfg = desc->chip_data;
+ 	unsigned vector, me;
+ 
+-	if (likely(!cfg->move_in_progress)) {
+-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
+-		if (likely(!cfg->move_desc_pending))
+-			return;
+-
+-		/* domain has not changed, but affinity did */
+-		me = smp_processor_id();
+-		if (cpumask_test_cpu(me, desc->affinity)) {
+-			*descp = desc = move_irq_desc(desc, me);
+-			/* get the new one */
+-			cfg = desc->chip_data;
+-			cfg->move_desc_pending = 0;
+-		}
+-#endif
++	if (likely(!cfg->move_in_progress))
+ 		return;
+-	}
+ 
+ 	vector = ~get_irq_regs()->orig_ax;
+ 	me = smp_processor_id();
+ 
+-	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
+-#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
+-		*descp = desc = move_irq_desc(desc, me);
+-		/* get the new one */
+-		cfg = desc->chip_data;
+-#endif
++	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
+ 		send_cleanup_vector(cfg);
+-	}
+ }
+ #else
+ static inline void irq_complete_move(struct irq_desc **descp) {}
+ #endif
+ 
+-static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+-{
+-	int apic, pin;
+-	struct irq_pin_list *entry;
+-
+-	entry = cfg->irq_2_pin;
+-	for (;;) {
+-
+-		if (!entry)
+-			break;
+-
+-		apic = entry->apic;
+-		pin = entry->pin;
+-		io_apic_eoi(apic, pin);
+-		entry = entry->next;
+-	}
+-}
+-
+-static void
+-eoi_ioapic_irq(struct irq_desc *desc)
+-{
+-	struct irq_cfg *cfg;
+-	unsigned long flags;
+-	unsigned int irq;
+-
+-	irq = desc->irq;
+-	cfg = desc->chip_data;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__eoi_ioapic_irq(irq, cfg);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-#ifdef CONFIG_X86_X2APIC
+-static void ack_x2apic_level(unsigned int irq)
+-{
+-	struct irq_desc *desc = irq_to_desc(irq);
+-	ack_x2APIC_irq();
+-	eoi_ioapic_irq(desc);
+-}
+-
+-static void ack_x2apic_edge(unsigned int irq)
+-{
+-	ack_x2APIC_irq();
+-}
+-#endif
+-
+ static void ack_apic_edge(unsigned int irq)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+@@ -2713,9 +2645,6 @@ static void ack_apic_level(unsigned int 
+ 	 */
+ 	ack_APIC_irq();
+ 
+-	if (irq_remapped(irq))
+-		eoi_ioapic_irq(desc);
+-
+ 	/* Now we can move and renable the irq */
+ 	if (unlikely(do_unmask_irq)) {
+ 		/* Only migrate the irq if the ack has been received.
+@@ -2762,22 +2691,50 @@ static void ack_apic_level(unsigned int 
+ }
+ 
+ #ifdef CONFIG_INTR_REMAP
++static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
++{
++	int apic, pin;
++	struct irq_pin_list *entry;
++
++	entry = cfg->irq_2_pin;
++	for (;;) {
++
++		if (!entry)
++			break;
++
++		apic = entry->apic;
++		pin = entry->pin;
++		io_apic_eoi(apic, pin);
++		entry = entry->next;
++	}
++}
++
++static void
++eoi_ioapic_irq(struct irq_desc *desc)
++{
++	struct irq_cfg *cfg;
++	unsigned long flags;
++	unsigned int irq;
++
++	irq = desc->irq;
++	cfg = desc->chip_data;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__eoi_ioapic_irq(irq, cfg);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
+ static void ir_ack_apic_edge(unsigned int irq)
+ {
+-#ifdef CONFIG_X86_X2APIC
+-       if (x2apic_enabled())
+-               return ack_x2apic_edge(irq);
+-#endif
+-       return ack_apic_edge(irq);
++	ack_APIC_irq();
+ }
+ 
+ static void ir_ack_apic_level(unsigned int irq)
+ {
+-#ifdef CONFIG_X86_X2APIC
+-       if (x2apic_enabled())
+-               return ack_x2apic_level(irq);
+-#endif
+-       return ack_apic_level(irq);
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	ack_APIC_irq();
++	eoi_ioapic_irq(desc);
+ }
+ #endif /* CONFIG_INTR_REMAP */
+ 
+@@ -2988,7 +2945,7 @@ static inline void __init check_timer(vo
+ {
+ 	struct irq_desc *desc = irq_to_desc(0);
+ 	struct irq_cfg *cfg = desc->chip_data;
+-	int cpu = boot_cpu_id;
++	int node = cpu_to_node(boot_cpu_id);
+ 	int apic1, pin1, apic2, pin2;
+ 	unsigned long flags;
+ 	int no_pin1 = 0;
+@@ -3054,7 +3011,7 @@ static inline void __init check_timer(vo
+ 		 * Ok, does IRQ0 through the IOAPIC work?
+ 		 */
+ 		if (no_pin1) {
+-			add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
++			add_pin_to_irq_node(cfg, node, apic1, pin1);
+ 			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+ 		} else {
+ 			/* for edge trigger, setup_IO_APIC_irq already
+@@ -3091,7 +3048,7 @@ static inline void __init check_timer(vo
+ 		/*
+ 		 * legacy devices should be connected to IO APIC #0
+ 		 */
+-		replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
++		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
+ 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+ 		enable_8259A_irq(0);
+ 		if (timer_irq_works()) {
+@@ -3321,14 +3278,13 @@ static int nr_irqs_gsi = NR_IRQS_LEGACY;
+ /*
+  * Dynamic irq allocate and deallocation
+  */
+-unsigned int create_irq_nr(unsigned int irq_want)
++unsigned int create_irq_nr(unsigned int irq_want, int node)
+ {
+ 	/* Allocate an unused irq */
+ 	unsigned int irq;
+ 	unsigned int new;
+ 	unsigned long flags;
+ 	struct irq_cfg *cfg_new = NULL;
+-	int cpu = boot_cpu_id;
+ 	struct irq_desc *desc_new = NULL;
+ 
+ 	irq = 0;
+@@ -3337,7 +3293,7 @@ unsigned int create_irq_nr(unsigned int 
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+ 	for (new = irq_want; new < nr_irqs; new++) {
+-		desc_new = irq_to_desc_alloc_cpu(new, cpu);
++		desc_new = irq_to_desc_alloc_node(new, node);
+ 		if (!desc_new) {
+ 			printk(KERN_INFO "can not get irq_desc for %d\n", new);
+ 			continue;
+@@ -3346,6 +3302,9 @@ unsigned int create_irq_nr(unsigned int 
+ 
+ 		if (cfg_new->vector != 0)
+ 			continue;
++
++		desc_new = move_irq_desc(desc_new, node);
++
+ 		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
+ 			irq = new;
+ 		break;
+@@ -3363,11 +3322,12 @@ unsigned int create_irq_nr(unsigned int 
+ 
+ int create_irq(void)
+ {
++	int node = cpu_to_node(boot_cpu_id);
+ 	unsigned int irq_want;
+ 	int irq;
+ 
+ 	irq_want = nr_irqs_gsi;
+-	irq = create_irq_nr(irq_want);
++	irq = create_irq_nr(irq_want, node);
+ 
+ 	if (irq == 0)
+ 		irq = -1;
+@@ -3433,6 +3393,9 @@ static int msi_compose_msg(struct pci_de
+ 		irte.vector = cfg->vector;
+ 		irte.dest_id = IRTE_DEST(dest);
+ 
++		/* Set source-id of interrupt request */
++		set_msi_sid(&irte, pdev);
++
+ 		modify_irte(irq, &irte);
+ 
+ 		msg->address_hi = MSI_ADDR_BASE_HI;
+@@ -3470,7 +3433,7 @@ static int msi_compose_msg(struct pci_de
+ }
+ 
+ #ifdef CONFIG_SMP
+-static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
++static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+@@ -3479,7 +3442,7 @@ static void set_msi_irq_affinity(unsigne
+ 
+ 	dest = set_desc_affinity(desc, mask);
+ 	if (dest == BAD_APICID)
+-		return;
++		return -1;
+ 
+ 	cfg = desc->chip_data;
+ 
+@@ -3491,13 +3454,15 @@ static void set_msi_irq_affinity(unsigne
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	write_msi_msg_desc(desc, &msg);
++
++	return 0;
+ }
+ #ifdef CONFIG_INTR_REMAP
+ /*
+  * Migrate the MSI irq to another cpumask. This migration is
+  * done in the process context using interrupt-remapping hardware.
+  */
+-static void
++static int
+ ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+@@ -3506,11 +3471,11 @@ ir_set_msi_irq_affinity(unsigned int irq
+ 	struct irte irte;
+ 
+ 	if (get_irte(irq, &irte))
+-		return;
++		return -1;
+ 
+ 	dest = set_desc_affinity(desc, mask);
+ 	if (dest == BAD_APICID)
+-		return;
++		return -1;
+ 
+ 	irte.vector = cfg->vector;
+ 	irte.dest_id = IRTE_DEST(dest);
+@@ -3527,6 +3492,8 @@ ir_set_msi_irq_affinity(unsigned int irq
+ 	 */
+ 	if (cfg->move_in_progress)
+ 		send_cleanup_vector(cfg);
++
++	return 0;
+ }
+ 
+ #endif
+@@ -3622,15 +3589,17 @@ int arch_setup_msi_irqs(struct pci_dev *
+ 	unsigned int irq_want;
+ 	struct intel_iommu *iommu = NULL;
+ 	int index = 0;
++	int node;
+ 
+ 	/* x86 doesn't support multiple MSI yet */
+ 	if (type == PCI_CAP_ID_MSI && nvec > 1)
+ 		return 1;
+ 
++	node = dev_to_node(&dev->dev);
+ 	irq_want = nr_irqs_gsi;
+ 	sub_handle = 0;
+ 	list_for_each_entry(msidesc, &dev->msi_list, list) {
+-		irq = create_irq_nr(irq_want);
++		irq = create_irq_nr(irq_want, node);
+ 		if (irq == 0)
+ 			return -1;
+ 		irq_want = irq + 1;
+@@ -3680,7 +3649,7 @@ void arch_teardown_msi_irq(unsigned int 
+ 
+ #if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+ #ifdef CONFIG_SMP
+-static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
++static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+@@ -3689,7 +3658,7 @@ static void dmar_msi_set_affinity(unsign
+ 
+ 	dest = set_desc_affinity(desc, mask);
+ 	if (dest == BAD_APICID)
+-		return;
++		return -1;
+ 
+ 	cfg = desc->chip_data;
+ 
+@@ -3701,11 +3670,13 @@ static void dmar_msi_set_affinity(unsign
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	dmar_msi_write(irq, &msg);
++
++	return 0;
+ }
+ 
+ #endif /* CONFIG_SMP */
+ 
+-struct irq_chip dmar_msi_type = {
++static struct irq_chip dmar_msi_type = {
+ 	.name = "DMAR_MSI",
+ 	.unmask = dmar_msi_unmask,
+ 	.mask = dmar_msi_mask,
+@@ -3734,7 +3705,7 @@ int arch_setup_dmar_msi(unsigned int irq
+ #ifdef CONFIG_HPET_TIMER
+ 
+ #ifdef CONFIG_SMP
+-static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
++static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+@@ -3743,7 +3714,7 @@ static void hpet_msi_set_affinity(unsign
+ 
+ 	dest = set_desc_affinity(desc, mask);
+ 	if (dest == BAD_APICID)
+-		return;
++		return -1;
+ 
+ 	cfg = desc->chip_data;
+ 
+@@ -3755,6 +3726,8 @@ static void hpet_msi_set_affinity(unsign
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	hpet_msi_write(irq, &msg);
++
++	return 0;
+ }
+ 
+ #endif /* CONFIG_SMP */
+@@ -3811,7 +3784,7 @@ static void target_ht_irq(unsigned int i
+ 	write_ht_irq_msg(irq, &msg);
+ }
+ 
+-static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
++static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+ 	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+@@ -3819,11 +3792,13 @@ static void set_ht_irq_affinity(unsigned
+ 
+ 	dest = set_desc_affinity(desc, mask);
+ 	if (dest == BAD_APICID)
+-		return;
++		return -1;
+ 
+ 	cfg = desc->chip_data;
+ 
+ 	target_ht_irq(irq, dest, cfg->vector);
++
++	return 0;
+ }
+ 
+ #endif
+@@ -3898,6 +3873,8 @@ int arch_enable_uv_irq(char *irq_name, u
+ 	unsigned long flags;
+ 	int err;
+ 
++	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
++
+ 	cfg = irq_cfg(irq);
+ 
+ 	err = assign_irq_vector(irq, cfg, eligible_cpu);
+@@ -3911,19 +3888,20 @@ int arch_enable_uv_irq(char *irq_name, u
+ 
+ 	mmr_value = 0;
+ 	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+-	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+-
+-	entry->vector = cfg->vector;
+-	entry->delivery_mode = apic->irq_delivery_mode;
+-	entry->dest_mode = apic->irq_dest_mode;
+-	entry->polarity = 0;
+-	entry->trigger = 0;
+-	entry->mask = 0;
+-	entry->dest = apic->cpu_mask_to_apicid(eligible_cpu);
++	entry->vector		= cfg->vector;
++	entry->delivery_mode	= apic->irq_delivery_mode;
++	entry->dest_mode	= apic->irq_dest_mode;
++	entry->polarity		= 0;
++	entry->trigger		= 0;
++	entry->mask		= 0;
++	entry->dest		= apic->cpu_mask_to_apicid(eligible_cpu);
+ 
+ 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+ 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+ 
++	if (cfg->move_in_progress)
++		send_cleanup_vector(cfg);
++
+ 	return irq;
+ }
+ 
+@@ -3937,10 +3915,10 @@ void arch_disable_uv_irq(int mmr_blade, 
+ 	struct uv_IO_APIC_route_entry *entry;
+ 	int mmr_pnode;
+ 
++	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
++
+ 	mmr_value = 0;
+ 	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+-	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+-
+ 	entry->mask = 1;
+ 
+ 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+@@ -4006,6 +3984,78 @@ int __init arch_probe_nr_irqs(void)
+ #endif
+ #endif /* CONFIG_XEN */
+ 
++static int __io_apic_set_pci_routing(struct device *dev, int irq,
++				struct io_apic_irq_attr *irq_attr)
++{
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++	int node;
++	int ioapic, pin;
++	int trigger, polarity;
++
++	ioapic = irq_attr->ioapic;
++#ifdef CONFIG_XEN
++	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
++		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
++			    ioapic, irq);
++		return -EINVAL;
++	}
++#endif
++	if (!IO_APIC_IRQ(irq)) {
++		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
++			ioapic);
++		return -EINVAL;
++	}
++
++	if (dev)
++		node = dev_to_node(dev);
++	else
++		node = cpu_to_node(boot_cpu_id);
++
++	desc = irq_to_desc_alloc_node(irq, node);
++	if (!desc) {
++		printk(KERN_INFO "can not get irq_desc %d\n", irq);
++		return 0;
++	}
++
++	pin = irq_attr->ioapic_pin;
++	trigger = irq_attr->trigger;
++	polarity = irq_attr->polarity;
++
++	/*
++	 * IRQs < 16 are already in the irq_2_pin[] map
++	 */
++	if (irq >= NR_IRQS_LEGACY) {
++		cfg = desc->chip_data;
++		add_pin_to_irq_node(cfg, node, ioapic, pin);
++	}
++
++	setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
++
++	return 0;
++}
++
++int io_apic_set_pci_routing(struct device *dev, int irq,
++				struct io_apic_irq_attr *irq_attr)
++{
++	int ioapic, pin;
++	/*
++	 * Avoid pin reprogramming.  PRTs typically include entries
++	 * with redundant pin->gsi mappings (but unique PCI devices);
++	 * we only program the IOAPIC on the first.
++	 */
++	ioapic = irq_attr->ioapic;
++	pin = irq_attr->ioapic_pin;
++	if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
++		pr_debug("Pin %d-%d already programmed\n",
++			 mp_ioapics[ioapic].apicid, pin);
++		return 0;
++	}
++	set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
++
++	return __io_apic_set_pci_routing(dev, irq, irq_attr);
++}
++
+ /* --------------------------------------------------------------------------
+                           ACPI-based IOAPIC Configuration
+    -------------------------------------------------------------------------- */
+@@ -4088,6 +4138,7 @@ int __init io_apic_get_unique_id(int ioa
+ 
+ 	return apic_id;
+ }
++#endif
+ 
+ int __init io_apic_get_version(int ioapic)
+ {
+@@ -4100,47 +4151,6 @@ int __init io_apic_get_version(int ioapi
+ 
+ 	return reg_01.bits.version;
+ }
+-#endif
+-
+-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+-{
+-	struct irq_desc *desc;
+-	struct irq_cfg *cfg;
+-	int cpu = boot_cpu_id;
+-
+-#ifdef CONFIG_XEN
+-	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
+-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
+-			    ioapic, irq);
+-		return -EINVAL;
+-	}
+-#endif
+-
+-	if (!IO_APIC_IRQ(irq)) {
+-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+-			ioapic);
+-		return -EINVAL;
+-	}
+-
+-	desc = irq_to_desc_alloc_cpu(irq, cpu);
+-	if (!desc) {
+-		printk(KERN_INFO "can not get irq_desc %d\n", irq);
+-		return 0;
+-	}
+-
+-	/*
+-	 * IRQs < 16 are already in the irq_2_pin[] map
+-	 */
+-	if (irq >= NR_IRQS_LEGACY) {
+-		cfg = desc->chip_data;
+-		add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
+-	}
+-
+-	setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
+-
+-	return 0;
+-}
+-
+ 
+ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+ {
+@@ -4172,51 +4182,44 @@ int acpi_get_override_irq(int bus_irq, i
+ #ifdef CONFIG_SMP
+ void __init setup_ioapic_dest(void)
+ {
+-	int pin, ioapic, irq, irq_entry;
++	int pin, ioapic = 0, irq, irq_entry;
+ 	struct irq_desc *desc;
+-	struct irq_cfg *cfg;
+ 	const struct cpumask *mask;
+ 
+ 	if (skip_ioapic_setup == 1)
+ 		return;
+ 
+-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+-			if (irq_entry == -1)
+-				continue;
+-			irq = pin_2_irq(irq_entry, ioapic, pin);
+-
+-			/* setup_IO_APIC_irqs could fail to get vector for some device
+-			 * when you have too many devices, because at that time only boot
+-			 * cpu is online.
+-			 */
+-			desc = irq_to_desc(irq);
+-			cfg = desc->chip_data;
+-			if (!cfg->vector) {
+-				setup_IO_APIC_irq(ioapic, pin, irq, desc,
+-						  irq_trigger(irq_entry),
+-						  irq_polarity(irq_entry));
+-				continue;
++#ifdef CONFIG_ACPI
++	if (!acpi_disabled && acpi_ioapic) {
++		ioapic = mp_find_ioapic(0);
++		if (ioapic < 0)
++			ioapic = 0;
++	}
++#endif
+ 
+-			}
++	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
++		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
++		if (irq_entry == -1)
++			continue;
++		irq = pin_2_irq(irq_entry, ioapic, pin);
+ 
+-			/*
+-			 * Honour affinities which have been set in early boot
+-			 */
+-			if (desc->status &
+-			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+-				mask = desc->affinity;
+-			else
+-				mask = apic->target_cpus();
++		desc = irq_to_desc(irq);
+ 
+-			if (intr_remapping_enabled)
+-				set_ir_ioapic_affinity_irq_desc(desc, mask);
+-			else
+-				set_ioapic_affinity_irq_desc(desc, mask);
+-		}
++		/*
++		 * Honour affinities which have been set in early boot
++		 */
++		if (desc->status &
++		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
++			mask = desc->affinity;
++		else
++			mask = apic->target_cpus();
+ 
++		if (intr_remapping_enabled)
++			set_ir_ioapic_affinity_irq_desc(desc, mask);
++		else
++			set_ioapic_affinity_irq_desc(desc, mask);
+ 	}
++
+ }
+ #endif
+ 
+@@ -4299,29 +4302,21 @@ fake_ioapic_page:
+ 	}
+ }
+ 
+-static int __init ioapic_insert_resources(void)
++void __init ioapic_insert_resources(void)
+ {
+ 	int i;
+ 	struct resource *r = ioapic_resources;
+ 
+ 	if (!r) {
+-		if (nr_ioapics > 0) {
++		if (nr_ioapics > 0)
+ 			printk(KERN_ERR
+ 				"IO APIC resources couldn't be allocated.\n");
+-			return -1;
+-		}
+-		return 0;
++		return;
+ 	}
+ 
+ 	for (i = 0; i < nr_ioapics; i++) {
+ 		insert_resource(&iomem_resource, r);
+ 		r++;
+ 	}
+-
+-	return 0;
+ }
+-
+-/* Insert the IO APIC resources after PCI initialization has occured to handle
+- * IO APICS that are mapped in on a BAR in PCI space. */
+-late_initcall(ioapic_insert_resources);
+ #endif /* !CONFIG_XEN */
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/apic/probe_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/apic/probe_32-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -20,23 +20,12 @@
+ #include <asm/apic.h>
+ #include <asm/setup.h>
+ 
+-#include <linux/threads.h>
+-#include <linux/cpumask.h>
+-#include <asm/mpspec.h>
+-#include <asm/fixmap.h>
+-#include <asm/apicdef.h>
+-#include <linux/kernel.h>
+-#include <linux/string.h>
+ #include <linux/smp.h>
+-#include <linux/init.h>
+ #include <asm/ipi.h>
+ 
+-#include <linux/smp.h>
+-#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <asm/acpi.h>
+ #include <asm/e820.h>
+-#include <asm/setup.h>
+ 
+ static int xen_phys_pkg_id(int cpuid_apic, int index_msb)
+ {
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/amd.c	2010-01-18 16:31:12.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/amd.c	2010-01-18 16:53:52.000000000 +0100
+@@ -426,7 +426,7 @@ static void __cpuinit early_init_amd(str
+ 		    (c->x86_model == 8 && c->x86_mask >= 8))
+ 			set_cpu_cap(c, X86_FEATURE_K6_MTRR);
+ #endif
+-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
++#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) && !defined(CONFIG_XEN)
+ 	/* check CPU config space for extended APIC ID */
+ 	if (cpu_has_apic && c->x86 >= 0xf) {
+ 		unsigned int val;
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -13,6 +13,7 @@
+ #include <linux/io.h>
+ 
+ #include <asm/stackprotector.h>
++#include <asm/perf_counter.h>
+ #include <asm/mmu_context.h>
+ #include <asm/hypervisor.h>
+ #include <asm/processor.h>
+@@ -66,7 +67,30 @@ void __init setup_cpu_local_masks(void)
+ 	alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
+ }
+ 
+-static const struct cpu_dev *this_cpu __cpuinitdata;
++static void __cpuinit default_init(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_X86_64
++	display_cacheinfo(c);
++#else
++	/* Not much we can do here... */
++	/* Check if at least it has cpuid */
++	if (c->cpuid_level == -1) {
++		/* No cpuid. It must be an ancient CPU */
++		if (c->x86 == 4)
++			strcpy(c->x86_model_id, "486");
++		else if (c->x86 == 3)
++			strcpy(c->x86_model_id, "386");
++	}
++#endif
++}
++
++static const struct cpu_dev __cpuinitconst default_cpu = {
++	.c_init		= default_init,
++	.c_vendor	= "Unknown",
++	.c_x86_vendor	= X86_VENDOR_UNKNOWN,
++};
++
++static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+ 
+ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+ #ifdef CONFIG_X86_64
+@@ -116,7 +140,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_p
+ 	/* data */
+ 	[GDT_ENTRY_APMBIOS_BASE+2]	= { { { 0x0000ffff, 0x00409200 } } },
+ 
+-	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x00000000, 0x00c09200 } } },
++	[GDT_ENTRY_ESPFIX_SS]		= { { { 0x0000ffff, 0x00cf9200 } } },
+ #endif
+ 	[GDT_ENTRY_PERCPU]		= { { { 0x0000ffff, 0x00cf9200 } } },
+ 	GDT_STACK_CANARY_INIT
+@@ -309,7 +333,8 @@ static const char *__cpuinit table_looku
+ 	return NULL;		/* Not found */
+ }
+ 
+-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
++__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
++__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
+ 
+ void load_percpu_segment(int cpu)
+ {
+@@ -358,29 +383,6 @@ void switch_to_new_gdt(int cpu)
+ 
+ static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
+ 
+-static void __cpuinit default_init(struct cpuinfo_x86 *c)
+-{
+-#ifdef CONFIG_X86_64
+-	display_cacheinfo(c);
+-#else
+-	/* Not much we can do here... */
+-	/* Check if at least it has cpuid */
+-	if (c->cpuid_level == -1) {
+-		/* No cpuid. It must be an ancient CPU */
+-		if (c->x86 == 4)
+-			strcpy(c->x86_model_id, "486");
+-		else if (c->x86 == 3)
+-			strcpy(c->x86_model_id, "386");
+-	}
+-#endif
+-}
+-
+-static const struct cpu_dev __cpuinitconst default_cpu = {
+-	.c_init	= default_init,
+-	.c_vendor = "Unknown",
+-	.c_x86_vendor = X86_VENDOR_UNKNOWN,
+-};
+-
+ static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
+ {
+ 	unsigned int *v;
+@@ -513,7 +515,6 @@ out:
+ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ 	char *v = c->x86_vendor_id;
+-	static int printed;
+ 	int i;
+ 
+ 	for (i = 0; i < X86_VENDOR_NUM; i++) {
+@@ -530,13 +531,9 @@ static void __cpuinit get_cpu_vendor(str
+ 		}
+ 	}
+ 
+-	if (!printed) {
+-		printed++;
+-		printk(KERN_ERR
+-		    "CPU: vendor_id '%s' unknown, using generic init.\n", v);
+-
+-		printk(KERN_ERR "CPU: Your system may be unstable.\n");
+-	}
++	printk_once(KERN_ERR
++			"CPU: vendor_id '%s' unknown, using generic init.\n" \
++			"CPU: Your system may be unstable.\n", v);
+ 
+ 	c->x86_vendor = X86_VENDOR_UNKNOWN;
+ 	this_cpu = &default_cpu;
+@@ -798,6 +795,12 @@ static void __cpuinit identify_cpu(struc
+ 	if (this_cpu->c_identify)
+ 		this_cpu->c_identify(c);
+ 
++	/* Clear/Set all flags overriden by options, after probe */
++	for (i = 0; i < NCAPINTS; i++) {
++		c->x86_capability[i] &= ~cpu_caps_cleared[i];
++		c->x86_capability[i] |= cpu_caps_set[i];
++	}
++
+ #if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+ 	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+ #endif
+@@ -843,6 +846,16 @@ static void __cpuinit identify_cpu(struc
+ #endif
+ 
+ 	init_hypervisor(c);
++
++	/*
++	 * Clear/Set all flags overriden by options, need do it
++	 * before following smp all cpus cap AND.
++	 */
++	for (i = 0; i < NCAPINTS; i++) {
++		c->x86_capability[i] &= ~cpu_caps_cleared[i];
++		c->x86_capability[i] |= cpu_caps_set[i];
++	}
++
+ 	/*
+ 	 * On SMP, boot_cpu_data holds the common feature set between
+ 	 * all CPUs; so make sure that we indicate which features are
+@@ -855,10 +868,6 @@ static void __cpuinit identify_cpu(struc
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
+-	/* Clear all flags overriden by options */
+-	for (i = 0; i < NCAPINTS; i++)
+-		c->x86_capability[i] &= ~cleared_cpu_caps[i];
+-
+ #ifdef CONFIG_X86_MCE
+ 	/* Init Machine Check Exception if available. */
+ 	mcheck_init(c);
+@@ -891,6 +900,7 @@ void __init identify_boot_cpu(void)
+ #else
+ 	vgetcpu_set_mode();
+ #endif
++	init_hw_perf_counters();
+ }
+ 
+ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/mcheck/Makefile	2009-11-06 10:45:48.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/mcheck/Makefile	2009-11-06 10:52:09.000000000 +0100
+@@ -8,5 +8,3 @@ obj-$(CONFIG_X86_MCE_THRESHOLD) += thres
+ obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
+ 
+ obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
+-
+-disabled-obj-$(CONFIG_XEN)	:= therm_throt.o
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/mcheck/mce.c	2009-12-04 10:44:45.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/mcheck/mce.c	2010-01-04 12:41:32.000000000 +0100
+@@ -447,7 +447,9 @@ static inline void mce_get_rip(struct mc
+  */
+ asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
+ {
++#ifndef CONFIG_XEN
+ 	ack_APIC_irq();
++#endif
+ 	exit_idle();
+ 	irq_enter();
+ 	mce_notify_irq();
+@@ -470,7 +472,7 @@ static void mce_report_event(struct pt_r
+ 		return;
+ 	}
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	/*
+ 	 * Without APIC do not notify. The event will be picked
+ 	 * up eventually.
+@@ -2067,7 +2069,7 @@ static __init int mce_init_device(void)
+ #ifdef CONFIG_X86_XEN_MCE
+ 	if (is_initial_xendomain()) {
+ 		/* Register vIRQ handler for MCE LOG processing */
+-		extern void bind_virq_for_mce(void);
++		extern int bind_virq_for_mce(void);
+ 
+ 		printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n");
+ 		bind_virq_for_mce();
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/mcheck/mce_dom0.c	2009-11-06 10:45:48.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/mcheck/mce_dom0.c	2009-11-06 10:52:09.000000000 +0100
+@@ -7,12 +7,17 @@
+ #include <asm/hypercall.h>
+ #include <asm/mce.h>
+ 
++static xen_mc_logical_cpu_t *g_physinfo;
++static unsigned int ncpus;
++
+ static int convert_log(struct mc_info *mi)
+ {
+ 	struct mcinfo_common *mic = NULL;
+ 	struct mcinfo_global *mc_global;
+ 	struct mcinfo_bank *mc_bank;
+ 	struct mce m;
++	unsigned int i;
++	bool found = false;
+ 
+ 	x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL);
+ 	if (mic == NULL)
+@@ -21,9 +26,21 @@ static int convert_log(struct mc_info *m
+ 		return -1;
+ 	}
+ 
++	mce_setup(&m);
+ 	mc_global = (struct mcinfo_global*)mic;
+ 	m.mcgstatus = mc_global->mc_gstatus;
+-	m.cpu = mc_global->mc_coreid;/*for test*/
++	m.apicid = mc_global->mc_apicid;
++
++	for (i = 0; i < ncpus; i++)
++		if (g_physinfo[i].mc_apicid == m.apicid) {
++			found = true;
++			break;
++		}
++	WARN_ON_ONCE(!found);
++	m.socketid = g_physinfo[i].mc_chipid;
++	m.cpu = m.extcpu = g_physinfo[i].mc_cpunr;
++	m.cpuvendor = (__u8)g_physinfo[i].mc_vendor;
++
+ 	x86_mcinfo_lookup(mic, mi, MC_TYPE_BANK);
+ 	do
+ 	{
+@@ -36,7 +53,6 @@ static int convert_log(struct mc_info *m
+ 			m.status = mc_bank->mc_status;
+ 			m.addr = mc_bank->mc_addr;
+ 			m.tsc = mc_bank->mc_tsc;
+-			m.res1 = mc_bank->mc_ctrl2;
+ 			m.bank = mc_bank->mc_bank;
+ 			printk(KERN_DEBUG "[CPU%d, BANK%d, addr %llx, state %llx]\n", 
+ 						m.bank, m.cpu, m.addr, m.status);
+@@ -116,18 +132,55 @@ end:
+ 	return IRQ_HANDLED;
+ }
+ 
+-void bind_virq_for_mce(void)
++int __init bind_virq_for_mce(void)
+ {
+ 	int ret;
++	xen_mc_t mc_op;
++
++	g_mi = kmalloc(sizeof(*g_mi), GFP_KERNEL);
++	if (!g_mi)
++		return -ENOMEM;
++
++	/* fetch physical CPU count */
++	mc_op.cmd = XEN_MC_physcpuinfo;
++	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
++	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, NULL);
++	ret = HYPERVISOR_mca(&mc_op);
++	if (ret) {
++		printk(KERN_ERR "MCE: Failed to get physical CPU count\n");
++		kfree(g_mi);
++		return ret;
++	}
++
++	/* fetch CPU physical info for later reference */
++	ncpus = mc_op.u.mc_physcpuinfo.ncpus;
++	g_physinfo = kmalloc(sizeof(*g_physinfo) * ncpus, GFP_KERNEL);
++	if (!g_physinfo) {
++		kfree(g_mi);
++		return -ENOMEM;
++	}
++	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
++	ret = HYPERVISOR_mca(&mc_op);
++	if (ret) {
++		printk(KERN_ERR "MCE: Failed to get physical CPUs' info\n");
++		kfree(g_mi);
++		kfree(g_physinfo);
++		return ret;
++	}
+ 
+ 	ret  = bind_virq_to_irqhandler(VIRQ_MCA, 0, 
+ 		mce_dom0_interrupt, 0, "mce", NULL);
+ 
+-	g_mi = kmalloc(sizeof(struct mc_info), GFP_KERNEL);
+-	if (ret < 0)
+-		printk(KERN_ERR "MCE_DOM0_LOG: bind_virq for DOM0 failed\n");
++	if (ret < 0) {
++		printk(KERN_ERR "MCE: Failed to bind vIRQ for Dom0\n");
++		kfree(g_mi);
++		kfree(g_physinfo);
++		return ret;
++	}
+ 
+ 	/* Log the machine checks left over from the previous reset. */
+ 	mce_dom0_interrupt(VIRQ_MCA, NULL);
++
++	return 0;
+ }
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/dumpstack_64.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/dumpstack_64.c	2009-11-06 10:52:09.000000000 +0100
+@@ -36,7 +36,11 @@ static char x86_stack_ids[][8] = {
+ 
+ int x86_is_stack_id(int id, char *name)
+ {
++#ifndef CONFIG_X86_NO_TSS
+ 	return x86_stack_ids[id - 1] == name;
++#else
++	return 0;
++#endif
+ }
+ 
+ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/e820-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/e820-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -659,7 +659,7 @@ __init int e820_search_gap(unsigned long
+  */
+ __init void e820_setup_gap(void)
+ {
+-	unsigned long gapstart, gapsize, round;
++	unsigned long gapstart, gapsize;
+ 	int found;
+ 
+ 	gapstart = 0x10000000;
+@@ -668,24 +668,18 @@ __init void e820_setup_gap(void)
+ 
+ #ifdef CONFIG_X86_64
+ 	if (!found) {
+-		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
+-		       "address range\n"
+-		       KERN_ERR "PCI: Unassigned devices with 32bit resource "
+-		       "registers may break!\n");
++		printk(KERN_ERR
++	"PCI: Warning: Cannot find a gap in the 32bit address range\n"
++	"PCI: Unassigned devices with 32bit resource registers may break!\n");
+ 		found = e820_search_gap(&gapstart, &gapsize, MAX_GAP_END, 0);
+ 		WARN_ON(!found);
+ 	}
+ #endif
+ 
+ 	/*
+-	 * See how much we want to round up: start off with
+-	 * rounding to the next 1MB area.
++	 * e820_reserve_resources_late protect stolen RAM already
+ 	 */
+-	round = 0x100000;
+-	while ((gapsize >> 4) > round)
+-		round += round;
+-	/* Fun with two's complement */
+-	pci_mem_start = (gapstart + round) & -round;
++	pci_mem_start = gapstart;
+ 
+ 	printk(KERN_INFO
+ 	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+@@ -1495,6 +1489,25 @@ void __init e820_reserve_resources(void)
+ 	}
+ }
+ 
++/* How much should we pad RAM ending depending on where it is? */
++static unsigned long ram_alignment(resource_size_t pos)
++{
++	unsigned long mb = pos >> 20;
++
++	/* To 64kB in the first megabyte */
++	if (!mb)
++		return 64*1024;
++
++	/* To 1MB in the first 16MB */
++	if (mb < 16)
++		return 1024*1024;
++
++	/* To 32MB for anything above that */
++	return 32*1024*1024;
++}
++
++#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
++
+ void __init e820_reserve_resources_late(void)
+ {
+ 	int i;
+@@ -1506,6 +1519,26 @@ void __init e820_reserve_resources_late(
+ 			insert_resource_expand_to_fit(&iomem_resource, res);
+ 		res++;
+ 	}
++
++	/*
++	 * Try to bump up RAM regions to reasonable boundaries to
++	 * avoid stolen RAM:
++	 */
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *entry = &e820.map[i];
++		u64 start, end;
++
++		if (entry->type != E820_RAM)
++			continue;
++		start = entry->addr + entry->size;
++		end = round_up(start, ram_alignment(start)) - 1;
++		if (end > MAX_RESOURCE_SIZE)
++			end = MAX_RESOURCE_SIZE;
++		if (start >= end)
++			continue;
++		reserve_region_with_split(&iomem_resource, start, end,
++					  "RAM buffer");
++	}
+ }
+ 
+ #undef e820
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:52:09.000000000 +0100
+@@ -48,7 +48,6 @@
+ #include <asm/segment.h>
+ #include <asm/smp.h>
+ #include <asm/page_types.h>
+-#include <asm/desc.h>
+ #include <asm/percpu.h>
+ #include <asm/dwarf2.h>
+ #include <asm/processor-flags.h>
+@@ -88,7 +87,7 @@ NMI_MASK	= 0x80000000
+ #define preempt_stop(clobbers)	DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
+ #else
+ #define preempt_stop(clobbers)
+-#define resume_kernel		restore_nocheck
++#define resume_kernel		restore_all
+ #endif
+ 
+ .macro TRACE_IRQS_IRET
+@@ -376,7 +375,7 @@ END(ret_from_exception)
+ ENTRY(resume_kernel)
+ 	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+-	jnz restore_nocheck
++	jnz restore_all
+ need_resched:
+ 	movl TI_flags(%ebp), %ecx	# need_resched set ?
+ 	testb $_TIF_NEED_RESCHED, %cl
+@@ -569,6 +568,8 @@ syscall_exit:
+ 	jne syscall_exit_work
+ 
+ restore_all:
++	TRACE_IRQS_IRET
++restore_all_notrace:
+ #ifndef CONFIG_XEN
+ 	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
+ 	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
+@@ -594,8 +595,6 @@ restore_nocheck:
+ 	CFI_REMEMBER_STATE
+ 	jnz restore_all_enable_events	#        != 0 => enable event delivery
+ #endif
+-	TRACE_IRQS_IRET
+-restore_nocheck_notrace:
+ 	RESTORE_REGS 4			# skip orig_eax/error_code
+ 	CFI_ADJUST_CFA_OFFSET -4
+ irq_return:
+@@ -632,22 +631,34 @@ ldt_ss:
+ 	jne restore_nocheck
+ #endif
+ 
+-	/* If returning to userspace with 16bit stack,
+-	 * try to fix the higher word of ESP, as the CPU
+-	 * won't restore it.
+-	 * This is an "official" bug of all the x86-compatible
+-	 * CPUs, which we can try to work around to make
+-	 * dosemu and wine happy. */
+-	movl PT_OLDESP(%esp), %eax
+-	movl %esp, %edx
+-	call patch_espfix_desc
++/*
++ * Setup and switch to ESPFIX stack
++ *
++ * We're returning to userspace with a 16 bit stack. The CPU will not
++ * restore the high word of ESP for us on executing iret... This is an
++ * "official" bug of all the x86-compatible CPUs, which we can work
++ * around to make dosemu and wine happy. We do this by preloading the
++ * high word of ESP with the high word of the userspace ESP while
++ * compensating for the offset by changing to the ESPFIX segment with
++ * a base address that matches for the difference.
++ */
++	mov %esp, %edx			/* load kernel esp */
++	mov PT_OLDESP(%esp), %eax	/* load userspace esp */
++	mov %dx, %ax			/* eax: new kernel esp */
++	sub %eax, %edx			/* offset (low word is 0) */
++	PER_CPU(gdt_page, %ebx)
++	shr $16, %edx
++	mov %dl, GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx) /* bits 16..23 */
++	mov %dh, GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx) /* bits 24..31 */
+ 	pushl $__ESPFIX_SS
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	pushl %eax
++	push %eax			/* new kernel esp */
+ 	CFI_ADJUST_CFA_OFFSET 4
++	/* Disable interrupts, but do not irqtrace this section: we
++	 * will soon execute iret and the tracer was already set to
++	 * the irqstate after the iret */
+ 	DISABLE_INTERRUPTS(CLBR_EAX)
+-	TRACE_IRQS_OFF
+-	lss (%esp), %esp
++	lss (%esp), %esp		/* switch to espfix segment */
+ 	CFI_ADJUST_CFA_OFFSET -8
+ 	jmp restore_nocheck
+ #else
+@@ -786,15 +797,24 @@ PTREGSCALL(vm86old)
+ 
+ #ifndef CONFIG_XEN
+ .macro FIXUP_ESPFIX_STACK
+-	/* since we are on a wrong stack, we cant make it a C code :( */
++/*
++ * Switch back for ESPFIX stack to the normal zerobased stack
++ *
++ * We can't call C functions using the ESPFIX stack. This code reads
++ * the high word of the segment base from the GDT and swiches to the
++ * normal stack and adjusts ESP with the matching offset.
++ */
++	/* fixup the stack */
+ 	PER_CPU(gdt_page, %ebx)
+-	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+-	addl %esp, %eax
++	mov GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx), %al /* bits 16..23 */
++	mov GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx), %ah /* bits 24..31 */
++	shl $16, %eax
++	addl %esp, %eax			/* the adjusted stack pointer */
+ 	pushl $__KERNEL_DS
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	lss (%esp), %esp
++	lss (%esp), %esp		/* switch to the normal stack segment */
+ 	CFI_ADJUST_CFA_OFFSET -8
+ .endm
+ .macro UNWIND_ESPFIX_STACK
+@@ -1284,6 +1304,7 @@ ENTRY(ftrace_graph_caller)
+ 	pushl %edx
+ 	movl 0xc(%esp), %edx
+ 	lea 0x4(%ebp), %eax
++	movl (%ebp), %ecx
+ 	subl $MCOUNT_INSN_SIZE, %edx
+ 	call prepare_ftrace_return
+ 	popl %edx
+@@ -1298,6 +1319,7 @@ return_to_handler:
+ 	pushl %eax
+ 	pushl %ecx
+ 	pushl %edx
++	movl %ebp, %eax
+ 	call ftrace_return_to_handler
+ 	movl %eax, 0xc(%esp)
+ 	popl %edx
+@@ -1593,7 +1615,7 @@ nmi_stack_correct:
+ 	xorl %edx,%edx		# zero error code
+ 	movl %esp,%eax		# pt_regs pointer
+ 	call do_nmi
+-	jmp restore_nocheck_notrace
++	jmp restore_all_notrace
+ 	CFI_ENDPROC
+ 
+ nmi_stack_fixup:
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/entry_64.S	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/entry_64.S	2009-11-06 10:52:09.000000000 +0100
+@@ -1446,7 +1446,7 @@ END(kdb_call)
+ paranoidzeroentry_ist debug do_debug DEBUG_STACK
+ paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
+ paranoiderrorentry stack_segment do_stack_segment
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ zeroentry xen_debug do_debug
+ zeroentry xen_int3 do_int3
+ errorentry xen_stack_segment do_stack_segment
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:52:09.000000000 +0100
+@@ -139,6 +139,7 @@ ENTRY(ftrace_graph_caller)
+ 
+ 	leaq 8(%rbp), %rdi
+ 	movq 0x38(%rsp), %rsi
++	movq (%rbp), %rdx
+ 	subq $MCOUNT_INSN_SIZE, %rsi
+ 
+ 	call	prepare_ftrace_return
+@@ -151,27 +152,15 @@ END(ftrace_graph_caller)
+ GLOBAL(return_to_handler)
+ 	subq  $80, %rsp
+ 
++	/* Save the return values */
+ 	movq %rax, (%rsp)
+-	movq %rcx, 8(%rsp)
+-	movq %rdx, 16(%rsp)
+-	movq %rsi, 24(%rsp)
+-	movq %rdi, 32(%rsp)
+-	movq %r8, 40(%rsp)
+-	movq %r9, 48(%rsp)
+-	movq %r10, 56(%rsp)
+-	movq %r11, 64(%rsp)
++	movq %rdx, 8(%rsp)
++	movq %rbp, %rdi
+ 
+ 	call ftrace_return_to_handler
+ 
+ 	movq %rax, 72(%rsp)
+-	movq 64(%rsp), %r11
+-	movq 56(%rsp), %r10
+-	movq 48(%rsp), %r9
+-	movq 40(%rsp), %r8
+-	movq 32(%rsp), %rdi
+-	movq 24(%rsp), %rsi
+-	movq 16(%rsp), %rdx
+-	movq 8(%rsp), %rcx
++	movq 8(%rsp), %rdx
+ 	movq (%rsp), %rax
+ 	addq $72, %rsp
+ 	retq
+@@ -876,6 +865,8 @@ END(\sym)
+ #ifdef CONFIG_SMP
+ apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
+ 	irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
++apicinterrupt REBOOT_VECTOR \
++	reboot_interrupt smp_reboot_interrupt
+ #endif
+ 
+ #ifdef CONFIG_X86_UV
+@@ -907,10 +898,15 @@ apicinterrupt INVALIDATE_TLB_VECTOR_STAR
+ #endif
+ 
+ apicinterrupt THRESHOLD_APIC_VECTOR \
+-	threshold_interrupt mce_threshold_interrupt
++	threshold_interrupt smp_threshold_interrupt
+ apicinterrupt THERMAL_APIC_VECTOR \
+ 	thermal_interrupt smp_thermal_interrupt
+ 
++#ifdef CONFIG_X86_MCE
++apicinterrupt MCE_SELF_VECTOR \
++	mce_self_interrupt smp_mce_self_interrupt
++#endif
++
+ #ifdef CONFIG_SMP
+ apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
+ 	call_function_single_interrupt smp_call_function_single_interrupt
+@@ -924,6 +920,11 @@ apicinterrupt ERROR_APIC_VECTOR \
+ 	error_interrupt smp_error_interrupt
+ apicinterrupt SPURIOUS_APIC_VECTOR \
+ 	spurious_interrupt smp_spurious_interrupt
++
++#ifdef CONFIG_PERF_COUNTERS
++apicinterrupt LOCAL_PENDING_VECTOR \
++	perf_pending_interrupt smp_perf_pending_interrupt
++#endif
+ #endif /* !CONFIG_XEN */
+ 
+ /*
+@@ -1226,7 +1227,7 @@ paranoiderrorentry stack_segment do_stac
+ errorentry general_protection do_general_protection
+ errorentry page_fault do_page_fault
+ #ifdef CONFIG_X86_MCE
+-paranoidzeroentry machine_check do_machine_check
++paranoidzeroentry machine_check *machine_check_vector(%rip)
+ #endif
+ 
+ #ifndef CONFIG_XEN
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/head_32-xen.S	2009-11-06 10:52:09.000000000 +0100
+@@ -120,12 +120,6 @@ ENTRY(hypercall_page)
+ 	CFI_ENDPROC
+ 
+ /*
+- * Real beginning of normal "text" segment
+- */
+-ENTRY(stext)
+-ENTRY(_stext)
+-
+-/*
+  * BSS section
+  */
+ .section ".bss.page_aligned","wa"
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:09.000000000 +0100
+@@ -15,7 +15,6 @@
+ #include <linux/threads.h>
+ #include <linux/init.h>
+ #include <linux/elfnote.h>
+-#include <asm/desc.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
+ #include <asm/msr.h>
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/init_task.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/init_task.c	2009-11-06 10:52:09.000000000 +0100
+@@ -31,6 +31,7 @@ union thread_union init_thread_union __i
+ struct task_struct init_task = INIT_TASK(init_task);
+ EXPORT_SYMBOL(init_task);
+ 
++#ifndef CONFIG_X86_NO_TSS
+ /*
+  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
+  * no more per-task TSS's. The TSS size is kept cacheline-aligned
+@@ -39,4 +40,4 @@ EXPORT_SYMBOL(init_task);
+  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+  */
+ DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
+-
++#endif
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/irq-xen.c	2009-12-18 09:57:23.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/irq-xen.c	2009-12-18 09:58:56.000000000 +0100
+@@ -12,6 +12,8 @@
+ #include <asm/io_apic.h>
+ #include <asm/irq.h>
+ #include <asm/idle.h>
++#include <asm/mce.h>
++#include <asm/hw_irq.h>
+ 
+ atomic_t irq_err_count;
+ 
+@@ -26,9 +28,10 @@ void (*generic_interrupt_extension)(void
+  */
+ void ack_bad_irq(unsigned int irq)
+ {
+-	printk(KERN_ERR "unexpected IRQ trap at irq %02x\n", irq);
++	if (printk_ratelimit())
++		pr_err("unexpected IRQ trap at vector %02x\n", irq);
+ 
+-#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
+ 	/*
+ 	 * Currently unexpected vectors happen only on SMP and APIC.
+ 	 * We _must_ ack these because every local APIC has only N
+@@ -38,8 +41,7 @@ void ack_bad_irq(unsigned int irq)
+ 	 * completely.
+ 	 * But only ack when the APIC is enabled -AK
+ 	 */
+-	if (cpu_has_apic)
+-		ack_APIC_irq();
++	ack_APIC_irq();
+ #endif
+ }
+ 
+@@ -65,6 +67,14 @@ static int show_other_interrupts(struct 
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+ 	seq_printf(p, "  Spurious interrupts\n");
++	seq_printf(p, "%*s: ", prec, "CNT");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
++	seq_printf(p, "  Performance counter interrupts\n");
++	seq_printf(p, "%*s: ", prec, "PND");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
++	seq_printf(p, "  Performance pending work\n");
+ #endif
+ #ifndef CONFIG_XEN
+ 	if (generic_interrupt_extension) {
+@@ -90,17 +100,27 @@ static int show_other_interrupts(struct 
+ 	seq_printf(p, "  TLB shootdowns\n");
+ #endif
+ #endif
+-#ifdef CONFIG_X86_MCE
++#ifdef CONFIG_X86_THERMAL_VECTOR
+ 	seq_printf(p, "%*s: ", prec, "TRM");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
+ 	seq_printf(p, "  Thermal event interrupts\n");
+-# ifdef CONFIG_X86_64
++#endif
++#ifdef CONFIG_X86_MCE_THRESHOLD
+ 	seq_printf(p, "%*s: ", prec, "THR");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
+ 	seq_printf(p, "  Threshold APIC interrupts\n");
+-# endif
++#endif
++#ifdef CONFIG_X86_NEW_MCE
++	seq_printf(p, "%*s: ", prec, "MCE");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
++	seq_printf(p, "  Machine check exceptions\n");
++	seq_printf(p, "%*s: ", prec, "MCP");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
++	seq_printf(p, "  Machine check polls\n");
+ #endif
+ 	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+@@ -172,6 +192,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	sum += irq_stats(cpu)->apic_timer_irqs;
+ 	sum += irq_stats(cpu)->irq_spurious_count;
++	sum += irq_stats(cpu)->apic_perf_irqs;
++	sum += irq_stats(cpu)->apic_pending_irqs;
+ #endif
+ #ifndef CONFIG_XEN
+ 	if (generic_interrupt_extension)
+@@ -184,11 +206,15 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ 	sum += irq_stats(cpu)->irq_tlb_count;
+ #endif
+ #endif
+-#ifdef CONFIG_X86_MCE
++#ifdef CONFIG_X86_THERMAL_VECTOR
+ 	sum += irq_stats(cpu)->irq_thermal_count;
+-# ifdef CONFIG_X86_64
++#endif
++#ifdef CONFIG_X86_MCE_THRESHOLD
+ 	sum += irq_stats(cpu)->irq_threshold_count;
+ #endif
++#ifdef CONFIG_X86_NEW_MCE
++	sum += per_cpu(mce_exception_count, cpu);
++	sum += per_cpu(mce_poll_count, cpu);
+ #endif
+ 	return sum;
+ }
+@@ -224,14 +250,11 @@ unsigned int __irq_entry do_IRQ(struct p
+ 	irq = __get_cpu_var(vector_irq)[vector];
+ 
+ 	if (!handle_irq(irq, regs)) {
+-#ifdef CONFIG_X86_64
+-		if (!disable_apic)
+-			ack_APIC_irq();
+-#endif
++		ack_APIC_irq();
+ 
+ 		if (printk_ratelimit())
+-			printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
+-			       __func__, smp_processor_id(), vector, irq);
++			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
++				__func__, smp_processor_id(), vector, irq);
+ 	}
+ 
+ 	irq_exit();
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -22,27 +22,21 @@
+  *	2 of the License, or (at your option) any later version.
+  */
+ #include <linux/platform_device.h>
+-#include <linux/capability.h>
+ #include <linux/miscdevice.h>
+-#include <linux/firmware.h>
++#include <linux/capability.h>
+ #include <linux/smp_lock.h>
+-#include <linux/spinlock.h>
+-#include <linux/cpumask.h>
+-#include <linux/uaccess.h>
+-#include <linux/vmalloc.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+ #include <linux/cpu.h>
+ #include <linux/fs.h>
+ #include <linux/mm.h>
++#include <linux/firmware.h>
++#include <linux/uaccess.h>
++#include <linux/vmalloc.h>
+ 
+ #include <asm/microcode.h>
+ #include <asm/processor.h>
+-#include <asm/msr.h>
+ 
+ MODULE_DESCRIPTION("Microcode Update Driver");
+ MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+@@ -53,7 +47,18 @@ module_param(verbose, int, 0644);
+ 
+ #define MICROCODE_VERSION	"2.00-xen"
+ 
+-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
++/*
++ * Synchronization.
++ *
++ * All non cpu-hotplug-callback call sites use:
++ *
++ * - microcode_mutex to synchronize with each other;
++ * - get/put_online_cpus() to synchronize with
++ *   the cpu-hotplug-callback call sites.
++ *
++ * We guarantee that only a single cpu is being
++ * updated at any particular moment of time.
++ */
+ static DEFINE_MUTEX(microcode_mutex);
+ 
+ #ifdef CONFIG_MICROCODE_OLD_INTERFACE
+@@ -90,18 +95,16 @@ static int microcode_open(struct inode *
+ static ssize_t microcode_write(struct file *file, const char __user *buf,
+ 			       size_t len, loff_t *ppos)
+ {
+-	ssize_t ret;
++	ssize_t ret = -EINVAL;
+ 
+ 	if ((len >> PAGE_SHIFT) > num_physpages) {
+-		printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
+-		       num_physpages);
+- 		return -EINVAL;
++		pr_err("microcode: too much data (max %ld pages)\n", num_physpages);
++		return ret;
+  	}
+ 
+ 	mutex_lock(&microcode_mutex);
+ 
+-	ret = do_microcode_update(buf, len);
+-	if (!ret)
++	if (do_microcode_update(buf, len) == 0)
+ 		ret = (ssize_t)len;
+ 
+ 	mutex_unlock(&microcode_mutex);
+@@ -110,15 +113,16 @@ static ssize_t microcode_write(struct fi
+ }
+ 
+ static const struct file_operations microcode_fops = {
+-	.owner		= THIS_MODULE,
+-	.write		= microcode_write,
+-	.open		= microcode_open,
++	.owner			= THIS_MODULE,
++	.write			= microcode_write,
++	.open			= microcode_open,
+ };
+ 
+ static struct miscdevice microcode_dev = {
+-	.minor		= MICROCODE_MINOR,
+-	.name		= "microcode",
+-	.fops		= &microcode_fops,
++	.minor			= MICROCODE_MINOR,
++	.name			= "microcode",
++	.devnode		= "cpu/microcode",
++	.fops			= &microcode_fops,
+ };
+ 
+ static int __init microcode_dev_init(void)
+@@ -127,9 +131,7 @@ static int __init microcode_dev_init(voi
+ 
+ 	error = misc_register(&microcode_dev);
+ 	if (error) {
+-		printk(KERN_ERR
+-			"microcode: can't misc_register on minor=%d\n",
+-			MICROCODE_MINOR);
++		pr_err("microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR);
+ 		return error;
+ 	}
+ 
+@@ -188,38 +190,35 @@ static int __init microcode_init(void)
+ 	else if (c->x86_vendor == X86_VENDOR_AMD)
+ 		fw_name = "amd-ucode/microcode_amd.bin";
+ 	else {
+-		printk(KERN_ERR "microcode: no support for this CPU vendor\n");
++		pr_err("microcode: no support for this CPU vendor\n");
+ 		return -ENODEV;
+ 	}
+ 
+-	error = microcode_dev_init();
+-	if (error)
+-		return error;
+ 	microcode_pdev = platform_device_register_simple("microcode", -1,
+ 							 NULL, 0);
+ 	if (IS_ERR(microcode_pdev)) {
+-		microcode_dev_exit();
+ 		return PTR_ERR(microcode_pdev);
+ 	}
+ 
++	error = microcode_dev_init();
++	if (error)
++		return error;
++
+ 	request_microcode(fw_name);
+ 
+-	printk(KERN_INFO
+-	       "Microcode Update Driver: v" MICROCODE_VERSION
++	pr_info("Microcode Update Driver: v" MICROCODE_VERSION
+ 	       " <tigran@aivazian.fsnet.co.uk>,"
+ 	       " Peter Oruba\n");
+ 
+ 	return 0;
+ }
++module_init(microcode_init);
+ 
+ static void __exit microcode_exit(void)
+ {
+ 	microcode_dev_exit();
+ 	platform_device_unregister(microcode_pdev);
+ 
+-	printk(KERN_INFO
+-	       "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
++	pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
+ }
+-
+-module_init(microcode_init);
+ module_exit(microcode_exit);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -17,6 +17,7 @@
+ #include <linux/acpi.h>
+ #include <linux/module.h>
+ #include <linux/smp.h>
++#include <linux/pci.h>
+ 
+ #include <asm/mtrr.h>
+ #include <asm/mpspec.h>
+@@ -890,24 +891,17 @@ static
+ inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
+ #endif /* CONFIG_X86_IO_APIC */
+ 
+-static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
+-		      int count)
++static int
++check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
+ {
+-	if (!mpc_new_phys) {
+-		pr_info("No spare slots, try to append...take your risk, "
+-			"new mpc_length %x\n", count);
+-	} else {
+-		if (count <= mpc_new_length)
+-			pr_info("No spare slots, try to append..., "
+-				"new mpc_length %x\n", count);
+-		else {
+-			pr_err("mpc_new_length %lx is too small\n",
+-				mpc_new_length);
+-			return -1;
+-		}
++	int ret = 0;
++
++	if (!mpc_new_phys || count <= mpc_new_length) {
++		WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
++		return -1;
+ 	}
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static int  __init replace_intsrc_all(struct mpc_table *mpc,
+@@ -966,7 +960,7 @@ static int  __init replace_intsrc_all(st
+ 		} else {
+ 			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+ 			count += sizeof(struct mpc_intsrc);
+-			if (!check_slot(mpc_new_phys, mpc_new_length, count))
++			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
+ 				goto out;
+ 			assign_to_mpc_intsrc(&mp_irqs[i], m);
+ 			mpc->length = count;
+@@ -983,11 +977,14 @@ out:
+ 	return 0;
+ }
+ 
+-static int __initdata enable_update_mptable;
++int enable_update_mptable;
+ 
+ static int __init update_mptable_setup(char *str)
+ {
+ 	enable_update_mptable = 1;
++#ifdef CONFIG_PCI
++	pci_routeirq = 1;
++#endif
+ 	return 0;
+ }
+ early_param("update_mptable", update_mptable_setup);
+@@ -1000,6 +997,9 @@ static int __initdata alloc_mptable;
+ static int __init parse_alloc_mptable_opt(char *p)
+ {
+ 	enable_update_mptable = 1;
++#ifdef CONFIG_PCI
++	pci_routeirq = 1;
++#endif
+ 	alloc_mptable = 1;
+ 	if (!p)
+ 		return 0;
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -32,6 +32,8 @@ int no_iommu __read_mostly;
+ /* Set this to 1 if there is a HW IOMMU in the system */
+ int iommu_detected __read_mostly = 0;
+ 
++int iommu_pass_through;
++
+ dma_addr_t bad_dma_address __read_mostly = 0;
+ EXPORT_SYMBOL(bad_dma_address);
+ 
+@@ -264,6 +266,10 @@ static __init int iommu_setup(char *p)
+ 		if (!strncmp(p, "soft", 4))
+ 			swiotlb = 1;
+ #endif
++		if (!strncmp(p, "pt", 2)) {
++			iommu_pass_through = 1;
++			return 1;
++		}
+ 
+ 		gart_parse_options(p);
+ 
+@@ -371,6 +377,8 @@ static int __init pci_iommu_init(void)
+ void pci_iommu_shutdown(void)
+ {
+ 	gart_iommu_shutdown();
++
++	amd_iommu_shutdown();
+ }
+ /* Must execute after PCI subsystem */
+ fs_initcall(pci_iommu_init);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -8,12 +8,15 @@
+ #include <linux/module.h>
+ #include <linux/pm.h>
+ #include <linux/clockchips.h>
++#include <linux/random.h>
+ #include <trace/power.h>
+ #include <asm/system.h>
+ #include <asm/apic.h>
++#include <asm/syscalls.h>
+ #include <asm/idle.h>
+ #include <asm/uaccess.h>
+ #include <asm/i387.h>
++#include <asm/ds.h>
+ #include <xen/evtchn.h>
+ 
+ unsigned long idle_halt;
+@@ -46,6 +49,8 @@ void free_thread_xstate(struct task_stru
+ 		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
+ 		tsk->thread.xstate = NULL;
+ 	}
++
++	WARN(tsk->thread.ds_ctx, "leaking DS context\n");
+ }
+ 
+ void free_thread_info(struct thread_info *ti)
+@@ -59,7 +64,7 @@ void arch_task_cache_init(void)
+         task_xstate_cachep =
+         	kmem_cache_create("task_xstate", xstate_size,
+ 				  __alignof__(union thread_xstate),
+-				  SLAB_PANIC, NULL);
++				  SLAB_PANIC | SLAB_NOTRACK, NULL);
+ }
+ 
+ /*
+@@ -85,8 +90,6 @@ void exit_thread(void)
+ 		t->io_bitmap_max = 0;
+ 		kfree(bp);
+ 	}
+-
+-	ds_exit_thread(current);
+ }
+ 
+ void flush_thread(void)
+@@ -500,16 +503,12 @@ static void c1e_idle(void)
+ 		if (!cpumask_test_cpu(cpu, c1e_mask)) {
+ 			cpumask_set_cpu(cpu, c1e_mask);
+ 			/*
+-			 * Force broadcast so ACPI can not interfere. Needs
+-			 * to run with interrupts enabled as it uses
+-			 * smp_function_call.
++			 * Force broadcast so ACPI can not interfere.
+ 			 */
+-			local_irq_enable();
+ 			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
+ 					   &cpu);
+ 			printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
+ 			       cpu);
+-			local_irq_disable();
+ 		}
+ 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+ 
+@@ -604,3 +603,16 @@ static int __init idle_setup(char *str)
+ }
+ early_param("idle", idle_setup);
+ 
++unsigned long arch_align_stack(unsigned long sp)
++{
++	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
++		sp -= get_random_int() % 8192;
++	return sp & ~0xf;
++}
++
++unsigned long arch_randomize_brk(struct mm_struct *mm)
++{
++	unsigned long range_end = mm->brk + 0x02000000;
++	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
++}
++
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process_32-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -9,8 +9,6 @@
+  * This file handles the architecture-dependent parts of process handling..
+  */
+ 
+-#include <stdarg.h>
+-
+ #include <linux/stackprotector.h>
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+@@ -33,7 +31,6 @@
+ #include <linux/module.h>
+ #include <linux/kallsyms.h>
+ #include <linux/ptrace.h>
+-#include <linux/random.h>
+ #include <linux/personality.h>
+ #include <linux/tick.h>
+ #include <linux/percpu.h>
+@@ -299,7 +296,8 @@ int copy_thread(unsigned long clone_flag
+ 		p->thread.io_bitmap_max = 0;
+ 	}
+ 
+-	ds_copy_thread(p, current);
++	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
++	p->thread.ds_ctx = NULL;
+ 
+ 	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
+ 	p->thread.debugctlmsr = 0;
+@@ -470,7 +468,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	 * done before math_state_restore, so the TS bit is up
+ 	 * to date.
+ 	 */
+-	arch_leave_lazy_cpu_mode();
++	arch_end_context_switch(next_p);
+ 
+ 	/* If the task has used fpu the last 5 timeslices, just do a full
+ 	 * restore of the math state immediately to avoid the trap; the
+@@ -560,15 +558,3 @@ unsigned long get_wchan(struct task_stru
+ 	return 0;
+ }
+ 
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+-	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+-		sp -= get_random_int() % 8192;
+-	return sp & ~0xf;
+-}
+-
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+-	unsigned long range_end = mm->brk + 0x02000000;
+-	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+-}
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process_64-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -17,8 +17,6 @@
+  * This file handles the architecture-dependent parts of process handling..
+  */
+ 
+-#include <stdarg.h>
+-
+ #include <linux/stackprotector.h>
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+@@ -35,7 +33,6 @@
+ #include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/ptrace.h>
+-#include <linux/random.h>
+ #include <linux/notifier.h>
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
+@@ -350,7 +347,8 @@ int copy_thread(unsigned long clone_flag
+ 	}
+         p->thread.iopl = current->thread.iopl;
+ 
+-	ds_copy_thread(p, me);
++	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
++	p->thread.ds_ctx = NULL;
+ 
+ 	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
+ 	p->thread.debugctlmsr = 0;
+@@ -513,7 +511,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	 * done before math_state_restore, so the TS bit is up
+ 	 * to date.
+ 	 */
+-	arch_leave_lazy_cpu_mode();
++	arch_end_context_switch(next_p);
+ 
+ 	/*
+ 	 * Switch FS and GS.
+@@ -732,15 +730,3 @@ long sys_arch_prctl(int code, unsigned l
+ 	return do_arch_prctl(current, code, addr);
+ }
+ 
+-unsigned long arch_align_stack(unsigned long sp)
+-{
+-	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+-		sp -= get_random_int() % 8192;
+-	return sp & ~0xf;
+-}
+-
+-unsigned long arch_randomize_brk(struct mm_struct *mm)
+-{
+-	unsigned long range_end = mm->brk + 0x02000000;
+-	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+-}
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -492,5 +492,42 @@ void force_hpet_resume(void)
+ 		break;
+ 	}
+ }
++#endif
++
++#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
++/* Set correct numa_node information for AMD NB functions */
++static void __init quirk_amd_nb_node(struct pci_dev *dev)
++{
++	struct pci_dev *nb_ht;
++	unsigned int devfn;
++	u32 val;
++
++	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
++	nb_ht = pci_get_slot(dev->bus, devfn);
++	if (!nb_ht)
++		return;
++
++	pci_read_config_dword(nb_ht, 0x60, &val);
++	set_dev_node(&dev->dev, val & 7);
++	pci_dev_put(dev);
++}
+ 
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_HT,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MAP,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,
++			quirk_amd_nb_node);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
++			quirk_amd_nb_node);
+ #endif
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/setup-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -142,6 +142,14 @@ EXPORT_SYMBOL(xen_start_info);
+ #define ARCH_SETUP
+ #endif
+ 
++/*
++ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
++ * The direct mapping extends to max_pfn_mapped, so that we can directly access
++ * apertures, ACPI and other tables without having to play with fixmaps.
++ */
++unsigned long max_low_pfn_mapped;
++unsigned long max_pfn_mapped;
++
+ RESERVE_BRK(dmi_alloc, 65536);
+ 
+ unsigned int boot_cpu_id __read_mostly;
+@@ -247,8 +255,8 @@ unsigned long mmu_cr4_features;
+ unsigned long mmu_cr4_features = X86_CR4_PAE;
+ #endif
+ 
+-/* Boot loader ID as an integer, for the benefit of proc_dointvec */
+-int bootloader_type;
++/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
++int bootloader_type, bootloader_version;
+ 
+ /*
+  * Setup options
+@@ -316,6 +324,20 @@ void * __init extend_brk(size_t size, si
+ 	return ret;
+ }
+ 
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++static void __init init_gbpages(void)
++{
++	if (direct_gbpages && cpu_has_gbpages)
++		printk(KERN_INFO "Using GB pages for direct mapping\n");
++	else
++		direct_gbpages = 0;
++}
++#else
++static inline void init_gbpages(void)
++{
++}
++#endif
++
+ static void __init reserve_brk(void)
+ {
+ 	if (_brk_end > _brk_start)
+@@ -328,15 +350,13 @@ static void __init reserve_brk(void)
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+-
+ #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
+ static void __init relocate_initrd(void)
+ {
+-
++#ifndef CONFIG_XEN
+ 	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
+ 	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+-	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+ 	u64 ramdisk_here;
+ 	unsigned long slop, clen, mapaddr;
+ 	char *p, *q;
+@@ -391,8 +411,14 @@ static void __init relocate_initrd(void)
+ 		" %08llx - %08llx\n",
+ 		ramdisk_image, ramdisk_image + ramdisk_size - 1,
+ 		ramdisk_here, ramdisk_here + ramdisk_size - 1);
+-}
++#else
++	printk(KERN_ERR "initrd extends beyond end of memory "
++	       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++	       __pa(xen_start_info->mod_start) + xen_start_info->mod_len,
++	       max_low_pfn_mapped << PAGE_SHIFT);
++	initrd_start = 0;
+ #endif
++}
+ 
+ static void __init reserve_initrd(void)
+ {
+@@ -400,7 +426,7 @@ static void __init reserve_initrd(void)
+ 	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
+ 	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+ 	u64 ramdisk_end   = ramdisk_image + ramdisk_size;
+-	u64 end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+ 
+ 	if (!boot_params.hdr.type_of_loader ||
+ 	    !ramdisk_image || !ramdisk_size)
+@@ -409,7 +435,7 @@ static void __init reserve_initrd(void)
+ 	unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
+ 	unsigned long ramdisk_size  = xen_start_info->mod_len;
+ 	unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+-	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	unsigned long end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+ 
+ 	if (!xen_start_info->mod_start || !ramdisk_size)
+ 		return;		/* No initrd provided by bootloader */
+@@ -442,14 +468,8 @@ static void __init reserve_initrd(void)
+ 		return;
+ 	}
+ 
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	relocate_initrd();
+-#else
+-	printk(KERN_ERR "initrd extends beyond end of memory "
+-	       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-	       ramdisk_end, end_of_lowmem);
+-	initrd_start = 0;
+-#endif
++
+ 	free_early(ramdisk_image, ramdisk_end);
+ }
+ #else
+@@ -721,6 +741,19 @@ static struct dmi_system_id __initdata b
+ 			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
+ 		},
+ 	},
++	{
++	/*
++	 * AMI BIOS with low memory corruption was found on Intel DG45ID board.
++	 * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
++	 * match only DMI_BOARD_NAME and see if there is more bad products
++	 * with this vendor.
++	 */
++		.callback = dmi_low_memory_corruption,
++		.ident = "AMI BIOS",
++		.matches = {
++			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
++		},
++	},
+ #endif
+ 	{}
+ };
+@@ -785,6 +818,12 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 	saved_video_mode = boot_params.hdr.vid_mode;
+ 	bootloader_type = boot_params.hdr.type_of_loader;
++	if ((bootloader_type >> 4) == 0xe) {
++		bootloader_type &= 0xf;
++		bootloader_type |= (boot_params.hdr.ext_loader_type+0x10) << 4;
++	}
++	bootloader_version  = bootloader_type & 0xf;
++	bootloader_version |= boot_params.hdr.ext_loader_ver << 4;
+ 
+ #ifdef CONFIG_BLK_DEV_RAM
+ 	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+@@ -967,14 +1006,22 @@ void __init setup_arch(char **cmdline_p)
+ 		max_low_pfn = max_pfn;
+ 
+ 	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
++#ifndef CONFIG_XEN
++	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
++#endif
+ #endif
+ 
+ #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+ 	setup_bios_corruption_check();
+ #endif
+ 
++	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
++			max_pfn_mapped<<PAGE_SHIFT);
++
+ 	reserve_brk();
+ 
++	init_gbpages();
++
+ 	/* max_pfn_mapped is updated here */
+ 	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
+ 	max_pfn_mapped = max_low_pfn_mapped;
+@@ -1219,24 +1266,6 @@ void __init setup_arch(char **cmdline_p)
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 
+ /**
+- * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+- *
+- * Description:
+- *	Perform any necessary interrupt initialisation prior to setting up
+- *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA
+- *	interrupts should be initialised here if the machine emulates a PC
+- *	in any way.
+- **/
+-void __init x86_quirk_pre_intr_init(void)
+-{
+-	if (x86_quirks->arch_pre_intr_init) {
+-		if (x86_quirks->arch_pre_intr_init())
+-			return;
+-	}
+-	init_ISA_irqs();
+-}
+-
+-/**
+  * x86_quirk_intr_init - post gate setup interrupt initialisation
+  *
+  * Description:
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/smp-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/smp-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -135,11 +135,38 @@ void xen_send_call_func_ipi(const struct
+  * this function calls the 'stop' function on all other CPUs in the system.
+  */
+ 
++irqreturn_t smp_reboot_interrupt(int irq, void *dev_id)
++{
++	irq_enter();
++	stop_this_cpu(NULL);
++	irq_exit();
++
++	return IRQ_HANDLED;
++}
++
+ void xen_smp_send_stop(void)
+ {
+ 	unsigned long flags;
++	unsigned long wait;
++
++	/*
++	 * Use an own vector here because smp_call_function
++	 * does lots of things not suitable in a panic situation.
++	 * On most systems we could also use an NMI here,
++	 * but there are a few systems around where NMI
++	 * is problematic so stay with an non NMI for now
++	 * (this implies we cannot stop CPUs spinning with irq off
++	 * currently)
++	 */
++	if (num_online_cpus() > 1) {
++		xen_send_IPI_allbutself(REBOOT_VECTOR);
++
++		/* Don't wait longer than a second */
++		wait = USEC_PER_SEC;
++		while (num_online_cpus() > 1 && wait--)
++			udelay(1);
++	}
+ 
+-	smp_call_function(stop_this_cpu, NULL, 0);
+ 	local_irq_save(flags);
+ 	disable_all_local_evtchn();
+ 	local_irq_restore(flags);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/traps-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -45,6 +45,7 @@
+ #include <linux/edac.h>
+ #endif
+ 
++#include <asm/kmemcheck.h>
+ #include <asm/stacktrace.h>
+ #include <asm/processor.h>
+ #include <asm/debugreg.h>
+@@ -53,6 +54,7 @@
+ #include <asm/traps.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
++#include <asm/mce.h>
+ 
+ #include <asm/mach_traps.h>
+ 
+@@ -64,8 +66,6 @@
+ #include <asm/setup.h>
+ #include <asm/traps.h>
+ 
+-#include "cpu/mcheck/mce.h"
+-
+ asmlinkage int system_call(void);
+ 
+ /* Do we ignore FPU interrupts ? */
+@@ -347,6 +347,9 @@ io_check_error(unsigned char reason, str
+ 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+ 	show_registers(regs);
+ 
++	if (panic_on_io_nmi)
++		panic("NMI IOCK error: Not continuing");
++
+ 	/* Re-enable the IOCK line, wait for a few seconds */
+ 	clear_io_check_error(reason);
+ }
+@@ -527,6 +530,10 @@ dotraplinkage void __kprobes do_debug(st
+ 
+ 	get_debugreg(condition, 6);
+ 
++	/* Catch kmemcheck conditions first of all! */
++	if (condition & DR_STEP && kmemcheck_trap(regs))
++		return;
++
+ 	/*
+ 	 * The processor cleared BTF, so don't mark that we need it set.
+ 	 */
+@@ -792,15 +799,15 @@ unsigned long patch_espfix_desc(unsigned
+ 
+ 	return new_kesp;
+ }
+-#else
++#endif
++
+ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+ {
+ }
+ 
+-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
++asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
+ {
+ }
+-#endif
+ #endif /* CONFIG_XEN */
+ 
+ /*
+@@ -834,9 +841,6 @@ asmlinkage void math_state_restore(void)
+ 	}
+ 
+ 	/* NB. 'clts' is done for us by Xen during virtual trap. */
+-#ifdef CONFIG_X86_32
+-	restore_fpu(tsk);
+-#else
+ 	/*
+ 	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+ 	 */
+@@ -845,7 +849,7 @@ asmlinkage void math_state_restore(void)
+ 		force_sig(SIGSEGV, tsk);
+ 		return;
+ 	}
+-#endif
++
+ 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+ 	tsk->fpu_counter++;
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -132,15 +132,7 @@ static __always_inline void do_vgettimeo
+ 			return;
+ 		}
+ 
+-		/*
+-		 * Surround the RDTSC by barriers, to make sure it's not
+-		 * speculated to outside the seqlock critical section and
+-		 * does not cause time warps:
+-		 */
+-		rdtsc_barrier();
+ 		now = vread();
+-		rdtsc_barrier();
+-
+ 		base = __vsyscall_gtod_data.clock.cycle_last;
+ 		mask = __vsyscall_gtod_data.clock.mask;
+ 		mult = __vsyscall_gtod_data.clock.mult;
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/fault-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -3,40 +3,18 @@
+  *  Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
+  *  Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
+  */
+-#include <linux/interrupt.h>
+-#include <linux/mmiotrace.h>
+-#include <linux/bootmem.h>
+-#include <linux/compiler.h>
+-#include <linux/highmem.h>
+-#include <linux/kprobes.h>
+-#include <linux/uaccess.h>
+-#include <linux/vmalloc.h>
+-#include <linux/vt_kern.h>
+-#include <linux/signal.h>
+-#include <linux/kernel.h>
+-#include <linux/ptrace.h>
+-#include <linux/string.h>
+-#include <linux/module.h>
+-#include <linux/kdebug.h>
+-#include <linux/errno.h>
+-#include <linux/magic.h>
+-#include <linux/sched.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/mman.h>
+-#include <linux/tty.h>
+-#include <linux/smp.h>
+-#include <linux/mm.h>
+-
+-#include <asm-generic/sections.h>
+-
+-#include <asm/tlbflush.h>
+-#include <asm/pgalloc.h>
+-#include <asm/segment.h>
+-#include <asm/system.h>
+-#include <asm/proto.h>
+-#include <asm/traps.h>
+-#include <asm/desc.h>
++#include <linux/magic.h>		/* STACK_END_MAGIC		*/
++#include <linux/sched.h>		/* test_thread_flag(), ...	*/
++#include <linux/kdebug.h>		/* oops_begin/end, ...		*/
++#include <linux/module.h>		/* search_exception_table	*/
++#include <linux/bootmem.h>		/* max_low_pfn			*/
++#include <linux/kprobes.h>		/* __kprobes, ...		*/
++#include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/
++#include <linux/perf_counter.h>		/* perf_swcounter_event		*/
++
++#include <asm/traps.h>			/* dotraplinkage, ...		*/
++#include <asm/pgalloc.h>		/* pgd_*(), ...			*/
++#include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
+ 
+ /*
+  * Page fault error code bits:
+@@ -225,10 +203,7 @@ static inline pmd_t *vmalloc_sync_one(pg
+ 	if (!pmd_present(*pmd_k))
+ 		return NULL;
+ 
+-	if (!pmd_present(*pmd)) {
+-		bool lazy = percpu_read(xen_lazy_mmu);
+-
+-		percpu_write(xen_lazy_mmu, false);
++	if (!pmd_present(*pmd))
+ #if CONFIG_XEN_COMPAT > 0x030002
+ 		set_pmd(pmd, *pmd_k);
+ #else
+@@ -238,10 +213,8 @@ static inline pmd_t *vmalloc_sync_one(pg
+ 		 */
+ 		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+ #endif
+-		percpu_write(xen_lazy_mmu, lazy);
+-	} else {
++	else
+ 		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+-	}
+ 
+ 	return pmd_k;
+ }
+@@ -463,10 +436,11 @@ static noinline int vmalloc_fault(unsign
+ }
+ 
+ static const char errata93_warning[] =
+-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
+-KERN_ERR "******* Please consider a BIOS update.\n"
+-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
++KERN_ERR
++"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
++"******* Working around it, but it may cause SEGVs or burn power.\n"
++"******* Please consider a BIOS update.\n"
++"******* Disabling USB legacy in the BIOS may also help.\n";
+ 
+ /*
+  * No vm86 mode in 64-bit mode:
+@@ -551,8 +525,6 @@ bad:
+ static int is_errata93(struct pt_regs *regs, unsigned long address)
+ {
+ #ifdef CONFIG_X86_64
+-	static int once;
+-
+ 	if (address != regs->ip)
+ 		return 0;
+ 
+@@ -562,10 +534,7 @@ static int is_errata93(struct pt_regs *r
+ 	address |= 0xffffffffUL << 32;
+ 	if ((address >= (u64)_stext && address <= (u64)_etext) ||
+ 	    (address >= MODULES_VADDR && address <= MODULES_END)) {
+-		if (!once) {
+-			printk(errata93_warning);
+-			once = 1;
+-		}
++		printk_once(errata93_warning);
+ 		regs->ip = address;
+ 		return 1;
+ 	}
+@@ -738,7 +707,7 @@ show_signal_msg(struct pt_regs *regs, un
+ 	if (!printk_ratelimit())
+ 		return;
+ 
+-	printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
++	printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+ 		task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+ 		tsk->comm, task_pid_nr(tsk), address,
+ 		(void *)regs->ip, (void *)regs->sp, error_code);
+@@ -1000,11 +969,17 @@ do_page_fault(struct pt_regs *regs, unsi
+ 	tsk = current;
+ 	mm = tsk->mm;
+ 
+-	prefetchw(&mm->mmap_sem);
+-
+ 	/* Get the faulting address: */
+ 	address = read_cr2();
+ 
++	/*
++	 * Detect and handle instructions that would cause a page fault for
++	 * both a tracked kernel page and a userspace page.
++	 */
++	if (kmemcheck_active(regs))
++		kmemcheck_hide(regs);
++	prefetchw(&mm->mmap_sem);
++
+ 	if (unlikely(kmmio_fault(regs, address)))
+ 		return;
+ 
+@@ -1033,9 +1008,13 @@ do_page_fault(struct pt_regs *regs, unsi
+ 			return;
+ 		}
+ 
+-		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
+-		    vmalloc_fault(address) >= 0)
+-			return;
++		if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
++			if (vmalloc_fault(address) >= 0)
++				return;
++
++			if (kmemcheck_fault(regs, address, error_code))
++				return;
++		}
+ 
+ 		/* Can handle a stale RO->RW TLB: */
+ 		if (spurious_fault(error_code, address))
+@@ -1074,6 +1053,8 @@ do_page_fault(struct pt_regs *regs, unsi
+ 	if (unlikely(error_code & PF_RSVD))
+ 		pgtable_bad(regs, error_code, address);
+ 
++	perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
++
+ 	/*
+ 	 * If we're in an interrupt, have no user context or are running
+ 	 * in an atomic region then we must not take the fault:
+@@ -1160,17 +1141,22 @@ good_area:
+ 	 * make sure we exit gracefully rather than endlessly redo
+ 	 * the fault:
+ 	 */
+-	fault = handle_mm_fault(mm, vma, address, write);
++	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+ 
+ 	if (unlikely(fault & VM_FAULT_ERROR)) {
+ 		mm_fault_error(regs, error_code, address, fault);
+ 		return;
+ 	}
+ 
+-	if (fault & VM_FAULT_MAJOR)
++	if (fault & VM_FAULT_MAJOR) {
+ 		tsk->maj_flt++;
+-	else
++		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
++				     regs, address);
++	} else {
+ 		tsk->min_flt++;
++		perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
++				     regs, address);
++	}
+ 
+ 	check_v8086_mode(regs, address, tsk);
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -44,7 +44,6 @@ void *kmap_atomic_prot(struct page *page
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	BUG_ON(!pte_none(*(kmap_pte-idx)));
+ 	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+-	/*arch_flush_lazy_mmu_mode();*/
+ 
+ 	return (void *)vaddr;
+ }
+@@ -74,7 +73,6 @@ void kunmap_atomic(void *kvaddr, enum km
+ #endif
+ 	}
+ 
+-	/*arch_flush_lazy_mmu_mode();*/
+ 	pagefault_enable();
+ }
+ 
+@@ -150,6 +148,7 @@ EXPORT_SYMBOL(kmap);
+ EXPORT_SYMBOL(kunmap);
+ EXPORT_SYMBOL(kmap_atomic);
+ EXPORT_SYMBOL(kunmap_atomic);
++EXPORT_SYMBOL(kmap_atomic_prot);
+ #ifdef CONFIG_HIGHPTE
+ EXPORT_SYMBOL(kmap_atomic_to_page);
+ #endif
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/init-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/init-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -1,3 +1,4 @@
++#include <linux/initrd.h>
+ #include <linux/ioport.h>
+ #include <linux/swap.h>
+ #include <linux/bootmem.h>
+@@ -11,6 +12,10 @@
+ #include <asm/setup.h>
+ #include <asm/system.h>
+ #include <asm/tlbflush.h>
++#include <asm/tlb.h>
++#include <asm/proto.h>
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ 
+ unsigned long __meminitdata e820_table_start;
+ unsigned long __meminitdata e820_table_end;
+@@ -31,6 +36,69 @@ extern unsigned long extend_init_mapping
+ extern void xen_finish_init_mapping(void);
+ #endif
+ 
++int nx_enabled;
++
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++static int disable_nx __cpuinitdata;
++
++/*
++ * noexec = on|off
++ *
++ * Control non-executable mappings for processes.
++ *
++ * on      Enable
++ * off     Disable
++ */
++static int __init noexec_setup(char *str)
++{
++	if (!str)
++		return -EINVAL;
++	if (!strncmp(str, "on", 2)) {
++		__supported_pte_mask |= _PAGE_NX;
++		disable_nx = 0;
++	} else if (!strncmp(str, "off", 3)) {
++		disable_nx = 1;
++		__supported_pte_mask &= ~_PAGE_NX;
++	}
++	return 0;
++}
++early_param("noexec", noexec_setup);
++#endif
++
++#ifdef CONFIG_X86_PAE
++static void __init set_nx(void)
++{
++	unsigned int v[4], l, h;
++
++	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
++		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
++
++		if ((v[3] & (1 << 20)) && !disable_nx) {
++			rdmsr(MSR_EFER, l, h);
++			l |= EFER_NX;
++			wrmsr(MSR_EFER, l, h);
++			nx_enabled = 1;
++			__supported_pte_mask |= _PAGE_NX;
++		}
++	}
++}
++#else
++static inline void set_nx(void)
++{
++}
++#endif
++
++#ifdef CONFIG_X86_64
++void __cpuinit check_efer(void)
++{
++	unsigned long efer;
++
++	rdmsrl(MSR_EFER, efer);
++	if (!(efer & EFER_NX) || disable_nx)
++		__supported_pte_mask &= ~_PAGE_NX;
++}
++#endif
++
+ static void __init find_early_table_space(unsigned long end, int use_pse,
+ 					  int use_gbpages)
+ {
+@@ -127,20 +195,6 @@ static int __meminit save_mr(struct map_
+ 	return nr_range;
+ }
+ 
+-#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+-static void __init init_gbpages(void)
+-{
+-	if (direct_gbpages && cpu_has_gbpages)
+-		printk(KERN_INFO "Using GB pages for direct mapping\n");
+-	else
+-		direct_gbpages = 0;
+-}
+-#else
+-static inline void init_gbpages(void)
+-{
+-}
+-#endif
+-
+ /*
+  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+  * This runs before bootmem is initialized and gets pages directly from
+@@ -160,10 +214,7 @@ unsigned long __init_refok init_memory_m
+ 
+ 	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
+ 
+-	if (!after_bootmem)
+-		init_gbpages();
+-
+-#ifdef CONFIG_DEBUG_PAGEALLOC
++#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
+ 	/*
+ 	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+ 	 * This will simplify cpa(), which otherwise needs to support splitting
+@@ -175,12 +226,9 @@ unsigned long __init_refok init_memory_m
+ 	use_gbpages = direct_gbpages;
+ #endif
+ 
+-#ifdef CONFIG_X86_32
+-#ifdef CONFIG_X86_PAE
+ 	set_nx();
+ 	if (nx_enabled)
+ 		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+-#endif
+ 
+ 	/* Enable PSE if available */
+ 	if (cpu_has_pse)
+@@ -191,7 +239,6 @@ unsigned long __init_refok init_memory_m
+ 		set_in_cr4(X86_CR4_PGE);
+ 		__supported_pte_mask |= _PAGE_GLOBAL;
+ 	}
+-#endif
+ 
+ 	if (use_gbpages)
+ 		page_size_mask |= 1 << PG_LEVEL_1G;
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/init_32-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -52,12 +52,9 @@
+ #include <asm/swiotlb.h>
+ #include <asm/setup.h>
+ #include <asm/cacheflush.h>
++#include <asm/page_types.h>
+ #include <asm/init.h>
+ 
+-unsigned long max_low_pfn_mapped;
+-unsigned long max_pfn_mapped;
+-
+-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+ 
+ static noinline int do_test_wp_bit(void);
+@@ -122,7 +119,7 @@ static pte_t * __init one_page_table_ini
+ 		pte_t *page_table = NULL;
+ 
+ 		if (after_bootmem) {
+-#ifdef CONFIG_DEBUG_PAGEALLOC
++#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
+ 			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+ #endif
+ 			if (!page_table)
+@@ -569,7 +566,7 @@ static inline void save_pg_dir(void)
+ }
+ #endif /* !CONFIG_ACPI_SLEEP */
+ 
+-void zap_low_mappings(void)
++void zap_low_mappings(bool early)
+ {
+ 	int i;
+ 
+@@ -586,64 +583,16 @@ void zap_low_mappings(void)
+ 		set_pgd(swapper_pg_dir+i, __pgd(0));
+ #endif
+ 	}
+-	flush_tlb_all();
+-}
+ 
+-int nx_enabled;
++	if (early)
++		__flush_tlb();
++	else
++		flush_tlb_all();
++}
+ 
+ pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+-#ifdef CONFIG_X86_PAE
+-
+-static int disable_nx __initdata;
+-
+-/*
+- * noexec = on|off
+- *
+- * Control non executable mappings.
+- *
+- * on      Enable
+- * off     Disable
+- */
+-static int __init noexec_setup(char *str)
+-{
+-	if (!str || !strcmp(str, "on")) {
+-		if (cpu_has_nx) {
+-			__supported_pte_mask |= _PAGE_NX;
+-			disable_nx = 0;
+-		}
+-	} else {
+-		if (!strcmp(str, "off")) {
+-			disable_nx = 1;
+-			__supported_pte_mask &= ~_PAGE_NX;
+-		} else {
+-			return -EINVAL;
+-		}
+-	}
+-
+-	return 0;
+-}
+-early_param("noexec", noexec_setup);
+-
+-void __init set_nx(void)
+-{
+-	unsigned int v[4], l, h;
+-
+-	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+-		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
+-
+-		if ((v[3] & (1 << 20)) && !disable_nx) {
+-			rdmsr(MSR_EFER, l, h);
+-			l |= EFER_NX;
+-			wrmsr(MSR_EFER, l, h);
+-			nx_enabled = 1;
+-			__supported_pte_mask |= _PAGE_NX;
+-		}
+-	}
+-}
+-#endif
+-
+ /* user-defined highmem size */
+ static unsigned int highmem_pages = -1;
+ 
+@@ -763,15 +712,15 @@ void __init initmem_init(unsigned long s
+ 	highstart_pfn = highend_pfn = max_pfn;
+ 	if (max_pfn > max_low_pfn)
+ 		highstart_pfn = max_low_pfn;
+-	memory_present(0, 0, highend_pfn);
+ 	e820_register_active_regions(0, 0, highend_pfn);
++	sparse_memory_present_with_active_regions(0);
+ 	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ 		pages_to_mb(highend_pfn - highstart_pfn));
+ 	num_physpages = highend_pfn;
+ 	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+ #else
+-	memory_present(0, 0, max_low_pfn);
+ 	e820_register_active_regions(0, 0, max_low_pfn);
++	sparse_memory_present_with_active_regions(0);
+ 	num_physpages = max_low_pfn;
+ 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+ #endif
+@@ -1074,7 +1023,7 @@ void __init mem_init(void)
+ 		test_wp_bit();
+ 
+ 	save_pg_dir();
+-	zap_low_mappings();
++	zap_low_mappings(true);
+ 
+ 	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -56,21 +56,11 @@
+ 
+ #include <xen/features.h>
+ 
+-/*
+- * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+- * The direct mapping extends to max_pfn_mapped, so that we can directly access
+- * apertures, ACPI and other tables without having to play with fixmaps.
+- */
+-unsigned long max_low_pfn_mapped;
+-unsigned long max_pfn_mapped;
+-
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ unsigned int __kernel_page_user;
+ EXPORT_SYMBOL(__kernel_page_user);
+ #endif
+ 
+-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+-
+ extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
+ extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
+ 
+@@ -151,39 +141,6 @@ early_param("gbpages", parse_direct_gbpa
+ pteval_t __supported_pte_mask __read_mostly = ~0UL;
+ EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+-static int disable_nx __cpuinitdata;
+-
+-/*
+- * noexec=on|off
+- * Control non-executable mappings for 64-bit processes.
+- *
+- * on	Enable (default)
+- * off	Disable
+- */
+-static int __init nonx_setup(char *str)
+-{
+-	if (!str)
+-		return -EINVAL;
+-	if (!strncmp(str, "on", 2)) {
+-		__supported_pte_mask |= _PAGE_NX;
+-		disable_nx = 0;
+-	} else if (!strncmp(str, "off", 3)) {
+-		disable_nx = 1;
+-		__supported_pte_mask &= ~_PAGE_NX;
+-	}
+-	return 0;
+-}
+-early_param("noexec", nonx_setup);
+-
+-void __cpuinit check_efer(void)
+-{
+-	unsigned long efer;
+-
+-	rdmsrl(MSR_EFER, efer);
+-	if (!(efer & EFER_NX) || disable_nx)
+-		__supported_pte_mask &= ~_PAGE_NX;
+-}
+-
+ int force_personality32;
+ 
+ /*
+@@ -213,7 +170,7 @@ static __ref void *spp_getpage(void)
+ 	void *ptr;
+ 
+ 	if (after_bootmem)
+-		ptr = (void *) get_zeroed_page(GFP_ATOMIC);
++		ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
+ 	else if (e820_table_end < e820_table_top) {
+ 		ptr = __va(e820_table_end << PAGE_SHIFT);
+ 		e820_table_end++;
+@@ -399,7 +356,7 @@ static __ref void *alloc_low_page(unsign
+ 	void *adr;
+ 
+ 	if (after_bootmem) {
+-		adr = (void *)get_zeroed_page(GFP_ATOMIC);
++		adr = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
+ 		*phys = __pa(adr);
+ 
+ 		return adr;
+@@ -804,7 +761,7 @@ void __init xen_finish_init_mapping(void
+ 		e820_table_top = e820_table_end;
+ }
+ 
+-unsigned long __init
++unsigned long __meminit
+ kernel_physical_mapping_init(unsigned long start,
+ 			     unsigned long end,
+ 			     unsigned long page_size_mask)
+@@ -873,6 +830,7 @@ void __init initmem_init(unsigned long s
+ 	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
+ 	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+ }
++#endif
+ 
+ void __init paging_init(void)
+ {
+@@ -883,13 +841,21 @@ void __init paging_init(void)
+ 	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+ 	max_zone_pfns[ZONE_NORMAL] = max_pfn;
+ 
+-	memory_present(0, 0, max_pfn);
++	sparse_memory_present_with_active_regions(MAX_NUMNODES);
+ 	sparse_init();
++
++	/*
++	 * clear the default setting with node 0
++	 * note: don't use nodes_clear here, that is really clearing when
++	 *	 numa support is not compiled in, and later node_set_state
++	 *	 will not set it back.
++	 */
++	node_clear_state(0, N_NORMAL_MEMORY);
++
+ 	free_area_init_nodes(max_zone_pfns);
+ 
+ 	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+-#endif
+ 
+ /*
+  * Memory hotplug specific functions
+@@ -1084,7 +1050,7 @@ int __init reserve_bootmem_generic(unsig
+ 		return ret;
+ 
+ #else
+-	reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
++	reserve_bootmem(phys, len, flags);
+ #endif
+ 
+ #ifndef CONFIG_XEN
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -84,7 +84,6 @@ iounmap_atomic(void *kvaddr, enum km_typ
+ 	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+ 		kpte_clear_flush(kmap_pte-idx, vaddr);
+ 
+-	/*arch_flush_lazy_mmu_mode();*/
+ 	pagefault_enable();
+ }
+ EXPORT_SYMBOL_GPL(iounmap_atomic);
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -11,6 +11,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/seq_file.h>
+ #include <linux/debugfs.h>
++#include <linux/pfn.h>
+ 
+ #include <asm/e820.h>
+ #include <asm/processor.h>
+@@ -486,7 +487,7 @@ static int split_large_page(pte_t *kpte,
+ 
+ 	if (!debug_pagealloc)
+ 		spin_unlock(&cpa_lock);
+-	base = alloc_pages(GFP_KERNEL, 0);
++	base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
+ 	if (!debug_pagealloc)
+ 		spin_lock(&cpa_lock);
+ 	if (!base)
+@@ -610,9 +611,12 @@ static int __change_page_attr(struct cpa
+ 	unsigned int level;
+ 	pte_t *kpte, old_pte;
+ 
+-	if (cpa->flags & CPA_PAGES_ARRAY)
+-		address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
+-	else if (cpa->flags & CPA_ARRAY)
++	if (cpa->flags & CPA_PAGES_ARRAY) {
++		struct page *page = cpa->pages[cpa->curpage];
++		if (unlikely(PageHighMem(page)))
++			return 0;
++		address = (unsigned long)page_address(page);
++	} else if (cpa->flags & CPA_ARRAY)
+ 		address = cpa->vaddr[cpa->curpage];
+ 	else
+ 		address = *cpa->vaddr;
+@@ -702,8 +706,9 @@ static int __change_page_attr_set_clr(st
+ static int cpa_process_alias(struct cpa_data *cpa)
+ {
+ 	struct cpa_data alias_cpa;
+-	int ret = 0;
+-	unsigned long temp_cpa_vaddr, vaddr;
++	unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
++	unsigned long vaddr, remapped;
++	int ret;
+ 
+ 	if (cpa->pfn >= max_pfn_mapped)
+ 		return 0;
+@@ -716,9 +721,12 @@ static int cpa_process_alias(struct cpa_
+ 	 * No need to redo, when the primary call touched the direct
+ 	 * mapping already:
+ 	 */
+-	if (cpa->flags & CPA_PAGES_ARRAY)
+-		vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
+-	else if (cpa->flags & CPA_ARRAY)
++	if (cpa->flags & CPA_PAGES_ARRAY) {
++		struct page *page = cpa->pages[cpa->curpage];
++		if (unlikely(PageHighMem(page)))
++			return 0;
++		vaddr = (unsigned long)page_address(page);
++	} else if (cpa->flags & CPA_ARRAY)
+ 		vaddr = cpa->vaddr[cpa->curpage];
+ 	else
+ 		vaddr = *cpa->vaddr;
+@@ -727,42 +735,55 @@ static int cpa_process_alias(struct cpa_
+ 		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
+ 
+ 		alias_cpa = *cpa;
+-		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
+-		alias_cpa.vaddr = &temp_cpa_vaddr;
++		alias_cpa.vaddr = &laddr;
+ 		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ 
+-
+ 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
++		if (ret)
++			return ret;
+ 	}
+ 
+ #ifdef CONFIG_X86_64
+-	if (ret)
+-		return ret;
+-	/*
+-	 * No need to redo, when the primary call touched the high
+-	 * mapping already:
+-	 */
+-	if (within(vaddr, (unsigned long) _text, _brk_end))
+-		return 0;
+-
+ 	/*
+-	 * If the physical address is inside the kernel map, we need
++	 * If the primary call didn't touch the high mapping already
++	 * and the physical address is inside the kernel map, we need
+ 	 * to touch the high mapped kernel as well:
+ 	 */
+-	if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
+-		return 0;
++	if (!within(vaddr, (unsigned long)_text, _brk_end) &&
++	    within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
++		unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
++					       __START_KERNEL_map;
++		alias_cpa = *cpa;
++		alias_cpa.vaddr = &temp_cpa_vaddr;
++		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+ 
+-	alias_cpa = *cpa;
+-	temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
+-	alias_cpa.vaddr = &temp_cpa_vaddr;
+-	alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
++		/*
++		 * The high mapping range is imprecise, so ignore the
++		 * return value.
++		 */
++		__change_page_attr_set_clr(&alias_cpa, 0);
++	}
++#endif
+ 
+ 	/*
+-	 * The high mapping range is imprecise, so ignore the return value.
+-	 */
+-	__change_page_attr_set_clr(&alias_cpa, 0);
+-#endif
+-	return ret;
++	 * If the PMD page was partially used for per-cpu remapping,
++	 * the recycled area needs to be split and modified.  Because
++	 * the area is always proper subset of a PMD page
++	 * cpa->numpages is guaranteed to be 1 for these areas, so
++	 * there's no need to loop over and check for further remaps.
++	 */
++	remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
++	if (remapped) {
++		WARN_ON(cpa->numpages > 1);
++		alias_cpa = *cpa;
++		alias_cpa.vaddr = &remapped;
++		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
++		ret = __change_page_attr_set_clr(&alias_cpa, 0);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
+ }
+ 
+ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
+@@ -860,15 +881,6 @@ static int change_page_attr_set_clr(unsi
+ 
+ 	vm_unmap_aliases();
+ 
+-	/*
+-	 * If we're called with lazy mmu updates enabled, the
+-	 * in-memory pte state may be stale.  Flush pending updates to
+-	 * bring them up to date.
+-	 *
+-	arch_flush_lazy_mmu_mode();*/
+-	if (arch_use_lazy_mmu_mode())
+-		xen_multicall_flush(true);
+-
+ 	cpa.vaddr = addr;
+ 	cpa.pages = pages;
+ 	cpa.numpages = numpages;
+@@ -913,14 +925,6 @@ static int change_page_attr_set_clr(unsi
+ 	} else
+ 		cpa_flush_all(cache);
+ 
+-	/*
+-	 * If we've been called with lazy mmu updates enabled, then
+-	 * make sure that everything gets flushed out before we
+-	 * return.
+-	 *
+-	arch_flush_lazy_mmu_mode();*/
+-	WARN_ON_ONCE(arch_use_lazy_mmu_mode() && !irq_count());
+-
+ out:
+ 	return ret;
+ }
+@@ -1065,12 +1069,15 @@ EXPORT_SYMBOL(set_memory_array_uc);
+ int _set_memory_wc(unsigned long addr, int numpages)
+ {
+ 	int ret;
++	unsigned long addr_copy = addr;
++
+ 	ret = change_page_attr_set(&addr, numpages,
+ 				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
+-
+ 	if (!ret) {
+-		ret = change_page_attr_set(&addr, numpages,
+-				    __pgprot(_PAGE_CACHE_WC), 0);
++		ret = change_page_attr_set_clr(&addr_copy, numpages,
++					       __pgprot(_PAGE_CACHE_WC),
++					       __pgprot(_PAGE_CACHE_MASK),
++					       0, 0, NULL);
+ 	}
+ 	return ret;
+ }
+@@ -1187,7 +1194,9 @@ int set_pages_array_uc(struct page **pag
+ 	int free_idx;
+ 
+ 	for (i = 0; i < addrinarray; i++) {
+-		start = (unsigned long)page_address(pages[i]);
++		if (PageHighMem(pages[i]))
++			continue;
++		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+ 		end = start + PAGE_SIZE;
+ 		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
+ 			goto err_out;
+@@ -1200,7 +1209,9 @@ int set_pages_array_uc(struct page **pag
+ err_out:
+ 	free_idx = i;
+ 	for (i = 0; i < free_idx; i++) {
+-		start = (unsigned long)page_address(pages[i]);
++		if (PageHighMem(pages[i]))
++			continue;
++		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+ 		end = start + PAGE_SIZE;
+ 		free_memtype(start, end);
+ 	}
+@@ -1229,7 +1240,9 @@ int set_pages_array_wb(struct page **pag
+ 		return retval;
+ 
+ 	for (i = 0; i < addrinarray; i++) {
+-		start = (unsigned long)page_address(pages[i]);
++		if (PageHighMem(pages[i]))
++			continue;
++		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+ 		end = start + PAGE_SIZE;
+ 		free_memtype(start, end);
+ 	}
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/pat-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -623,7 +623,8 @@ static int reserve_pfn_range(u64 paddr, 
+ 		return ret;
+ 
+ 	if (flags != want_flags) {
+-		if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
++		if (strict_prot ||
++		    !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
+ 			free_memtype(paddr, paddr + size);
+ 			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
+ 				" for %Lx-%Lx, got %s\n",
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/pgtable-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -8,9 +8,11 @@
+ #include <asm/hypervisor.h>
+ #include <asm/mmu_context.h>
+ 
++#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
++
+ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+ {
+-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++	pte_t *pte = (pte_t *)__get_free_page(PGALLOC_GFP);
+ 	if (pte)
+ 		make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
+ 	return pte;
+@@ -27,9 +29,9 @@ pgtable_t pte_alloc_one(struct mm_struct
+ 	struct page *pte;
+ 
+ #ifdef CONFIG_HIGHPTE
+-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++	pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0);
+ #else
+-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++	pte = alloc_pages(PGALLOC_GFP, 0);
+ #endif
+ 	if (pte) {
+ 		pgtable_page_ctor(pte);
+@@ -65,7 +67,7 @@ void __pte_free(pgtable_t pte)
+ 	__free_page(pte);
+ }
+ 
+-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
++void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+ {
+ 	pgtable_page_dtor(pte);
+ 	paravirt_release_pte(page_to_pfn(pte));
+@@ -83,7 +85,7 @@ pmd_t *pmd_alloc_one(struct mm_struct *m
+ {
+ 	struct page *pmd;
+ 
+-	pmd = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++	pmd = alloc_pages(PGALLOC_GFP, 0);
+ 	if (!pmd)
+ 		return NULL;
+ 	SetPageForeign(pmd, _pmd_free);
+@@ -107,14 +109,14 @@ void __pmd_free(pgtable_t pmd)
+ 	__free_page(pmd);
+ }
+ 
+-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
++void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+ {
+ 	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+ 	tlb_remove_page(tlb, virt_to_page(pmd));
+ }
+ 
+ #if PAGETABLE_LEVELS > 3
+-void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
++void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+ {
+ 	paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
+ 	tlb_remove_page(tlb, virt_to_page(pud));
+@@ -609,7 +611,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	pmd_t *pmds[PREALLOCATED_PMDS];
+ 	unsigned long flags;
+ 
+-	pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
++	pgd = (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ORDER);
+ 
+ 	if (pgd == NULL)
+ 		goto out;
+--- sle11sp1-2010-01-20.orig/arch/x86/pci/i386.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/pci/i386.c	2009-11-06 10:52:09.000000000 +0100
+@@ -228,12 +228,14 @@ void __init pcibios_resource_survey(void
+ 	pcibios_allocate_resources(1);
+ 
+ 	e820_reserve_resources_late();
++#ifndef CONFIG_XEN
+ 	/*
+ 	 * Insert the IO APIC resources after PCI initialization has
+ 	 * occured to handle IO APICS that are mapped in on a BAR in
+ 	 * PCI space, but before trying to assign unassigned pci res.
+ 	 */
+ 	ioapic_insert_resources();
++#endif
+ }
+ 
+ /**
+--- sle11sp1-2010-01-20.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/pci/irq-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -895,6 +895,9 @@ static int pcibios_lookup_irq(struct pci
+ 		return 0;
+ 	}
+ 
++	if (io_apic_assign_pci_irqs)
++		return 0;
++
+ 	/* Find IRQ routing entry */
+ 
+ 	if (!pirq_table)
+@@ -1045,56 +1048,15 @@ static void __init pcibios_fixup_irqs(vo
+ 		pirq_penalty[dev->irq]++;
+ 	}
+ 
++	if (io_apic_assign_pci_irqs)
++		return;
++
+ 	dev = NULL;
+ 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ 		if (!pin)
+ 			continue;
+ 
+-#ifdef CONFIG_X86_IO_APIC
+-		/*
+-		 * Recalculate IRQ numbers if we use the I/O APIC.
+-		 */
+-		if (io_apic_assign_pci_irqs) {
+-			int irq;
+-
+-			/*
+-			 * interrupt pins are numbered starting from 1
+-			 */
+-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+-				PCI_SLOT(dev->devfn), pin - 1);
+-			/*
+-			 * Busses behind bridges are typically not listed in the
+-			 * MP-table.  In this case we have to look up the IRQ
+-			 * based on the parent bus, parent slot, and pin number.
+-			 * The SMP code detects such bridged busses itself so we
+-			 * should get into this branch reliably.
+-			 */
+-			if (irq < 0 && dev->bus->parent) {
+-				/* go back to the bridge */
+-				struct pci_dev *bridge = dev->bus->self;
+-				int bus;
+-
+-				pin = pci_swizzle_interrupt_pin(dev, pin);
+-				bus = bridge->bus->number;
+-				irq = IO_APIC_get_PCI_irq_vector(bus,
+-						PCI_SLOT(bridge->devfn), pin - 1);
+-				if (irq >= 0)
+-					dev_warn(&dev->dev,
+-						"using bridge %s INT %c to "
+-							"get IRQ %d\n",
+-						 pci_name(bridge),
+-						 'A' + pin - 1, irq);
+-			}
+-			if (irq >= 0) {
+-				dev_info(&dev->dev,
+-					"PCI->APIC IRQ transform: INT %c "
+-						"-> IRQ %d\n",
+-					'A' + pin - 1, irq);
+-				dev->irq = irq;
+-			}
+-		}
+-#endif
+ 		/*
+ 		 * Still no IRQ? Try to lookup one...
+ 		 */
+@@ -1189,6 +1151,19 @@ int __init pcibios_irq_init(void)
+ 	pcibios_enable_irq = pirq_enable_irq;
+ 
+ 	pcibios_fixup_irqs();
++
++	if (io_apic_assign_pci_irqs && pci_routeirq) {
++		struct pci_dev *dev = NULL;
++		/*
++		 * PCI IRQ routing is set up by pci_enable_device(), but we
++		 * also do it here in case there are still broken drivers that
++		 * don't use pci_enable_device().
++		 */
++		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
++		for_each_pci_dev(dev)
++			pirq_enable_irq(dev);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -1219,16 +1194,23 @@ void pcibios_penalize_isa_irq(int irq, i
+ static int pirq_enable_irq(struct pci_dev *dev)
+ {
+ 	u8 pin;
+-	struct pci_dev *temp_dev;
+ 
+ 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+-	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
++	if (pin && !pcibios_lookup_irq(dev, 1)) {
+ 		char *msg = "";
+ 
++		if (!io_apic_assign_pci_irqs && dev->irq)
++			return 0;
++
+ 		if (io_apic_assign_pci_irqs) {
++#ifdef CONFIG_X86_IO_APIC
++			struct pci_dev *temp_dev;
+ 			int irq;
++			struct io_apic_irq_attr irq_attr;
+ 
+-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
++			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
++						PCI_SLOT(dev->devfn),
++						pin - 1, &irq_attr);
+ 			/*
+ 			 * Busses behind bridges are typically not listed in the MP-table.
+ 			 * In this case we have to look up the IRQ based on the parent bus,
+@@ -1241,7 +1223,8 @@ static int pirq_enable_irq(struct pci_de
+ 
+ 				pin = pci_swizzle_interrupt_pin(dev, pin);
+ 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+-						PCI_SLOT(bridge->devfn), pin - 1);
++						PCI_SLOT(bridge->devfn),
++						pin - 1, &irq_attr);
+ 				if (irq >= 0)
+ 					dev_warn(&dev->dev, "using bridge %s "
+ 						 "INT %c to get IRQ %d\n",
+@@ -1251,12 +1234,15 @@ static int pirq_enable_irq(struct pci_de
+ 			}
+ 			dev = temp_dev;
+ 			if (irq >= 0) {
++				io_apic_set_pci_routing(&dev->dev, irq,
++							 &irq_attr);
++				dev->irq = irq;
+ 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
+ 					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
+-				dev->irq = irq;
+ 				return 0;
+ 			} else
+ 				msg = "; probably buggy MP table";
++#endif
+ 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+ 			msg = "";
+ 		else
+--- sle11sp1-2010-01-20.orig/arch/x86/pci/pcifront.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/pci/pcifront.c	2009-11-06 10:52:09.000000000 +0100
+@@ -6,6 +6,7 @@
+  */
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/irq.h>
+ #include <linux/pci.h>
+ #include <asm/acpi.h>
+ #include <asm/pci_x86.h>
+@@ -15,6 +16,7 @@ static int pcifront_enable_irq(struct pc
+ {
+ 	u8 irq;
+ 	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
++	irq_to_desc_alloc_node(irq, numa_node_id());
+ 	evtchn_register_pirq(irq);
+ 	dev->irq = irq;
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:52:09.000000000 +0100
+@@ -377,6 +377,8 @@ int arch_setup_additional_pages(struct l
+ 		}
+ 	}
+ 
++	current->mm->context.vdso = (void *)addr;
++
+ 	if (compat_uses_vma || !compat) {
+ 		/*
+ 		 * MAYWRITE to allow gdb to COW and set breakpoints
+@@ -397,11 +399,13 @@ int arch_setup_additional_pages(struct l
+ 			goto up_fail;
+ 	}
+ 
+-	current->mm->context.vdso = (void *)addr;
+ 	current_thread_info()->sysenter_return =
+ 		VDSO32_SYMBOL(addr, SYSENTER_RETURN);
+ 
+   up_fail:
++	if (ret)
++		current->mm->context.vdso = NULL;
++
+ 	up_write(&mm->mmap_sem);
+ 
+ 	return ret;
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_core.c	2010-01-04 12:40:08.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_core.c	2010-01-04 12:41:22.000000000 +0100
+@@ -674,7 +674,14 @@ static int acpi_processor_get_info(struc
+ 	 * generated as the following format:
+ 	 * CPU+CPU ID.
+ 	 */
+-	sprintf(acpi_device_bid(device), "CPU%X", pr->id);
++	if (pr->id != -1)
++		sprintf(acpi_device_bid(device), "CPU%X", pr->id);
++	else
++		snprintf(acpi_device_bid(device),
++			 ARRAY_SIZE(acpi_device_bid(device)),
++			 "#%0*X",
++			 (int)ARRAY_SIZE(acpi_device_bid(device)) - 2,
++			 pr->acpi_id);
+ 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
+ 			  pr->acpi_id));
+ 
+--- sle11sp1-2010-01-20.orig/drivers/char/agp/intel-agp.c	2010-01-20 10:22:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/agp/intel-agp.c	2010-01-20 10:24:03.000000000 +0100
+@@ -564,7 +564,11 @@ static struct agp_memory *alloc_agpphysm
+ 	new->page_count = pg_count;
+ 	new->num_scratch_pages = pg_count;
+ 	new->type = AGP_PHYS_MEMORY;
++#ifndef CONFIG_XEN
+ 	new->physical = page_to_phys(new->pages[0]);
++#else
++	new->physical = page_to_pseudophys(new->pages[0]);
++#endif
+ 	return new;
+ }
+ 
+--- sle11sp1-2010-01-20.orig/drivers/edac/Kconfig	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/edac/Kconfig	2009-11-06 10:52:09.000000000 +0100
+@@ -72,6 +72,7 @@ config EDAC_MM_EDAC
+ config EDAC_AMD64
+ 	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
+ 	depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
++	depends on !XEN
+ 	help
+ 	  Support for error detection and correction on the AMD 64
+ 	  Families of Memory Controllers (K8, F10h and F11h)
+--- sle11sp1-2010-01-20.orig/drivers/pci/msi-xen.c	2009-12-04 11:29:54.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/pci/msi-xen.c	2009-12-04 11:30:30.000000000 +0100
+@@ -95,22 +95,17 @@ void arch_teardown_msi_irqs(struct pci_d
+ }
+ #endif
+ 
+-static void __msi_set_enable(struct pci_dev *dev, int pos, int enable)
++static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
+ {
+ 	u16 control;
+ 
+-	if (pos) {
+-		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+-		control &= ~PCI_MSI_FLAGS_ENABLE;
+-		if (enable)
+-			control |= PCI_MSI_FLAGS_ENABLE;
+-		pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+-	}
+-}
++	BUG_ON(!pos);
+ 
+-static void msi_set_enable(struct pci_dev *dev, int enable)
+-{
+-	__msi_set_enable(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), enable);
++	pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
++	control &= ~PCI_MSI_FLAGS_ENABLE;
++	if (enable)
++		control |= PCI_MSI_FLAGS_ENABLE;
++	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ }
+ 
+ static void msix_set_enable(struct pci_dev *dev, int enable)
+@@ -335,8 +330,11 @@ void pci_restore_msi_state(struct pci_de
+ 		return;
+ 
+ 	pci_intx_for_msi(dev, 0);
+-	if (dev->msi_enabled)
+-		msi_set_enable(dev, 0);
++	if (dev->msi_enabled) {
++		int pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++
++		msi_set_enable(dev, pos, 0);
++	}
+ 	if (dev->msix_enabled)
+ 		msix_set_enable(dev, 0);
+ 
+@@ -363,9 +361,9 @@ static int msi_capability_init(struct pc
+ 	int pos, pirq;
+ 	u16 control;
+ 
+-	msi_set_enable(dev, 0);	/* Ensure msi is disabled as I set it up */
+-
+ 	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	msi_set_enable(dev, pos, 0);	/* Disable MSI during set up */
++
+ 	pci_read_config_word(dev, msi_control_reg(pos), &control);
+ 
+ 	WARN_ON(nvec > 1); /* XXX */
+@@ -375,7 +373,7 @@ static int msi_capability_init(struct pc
+ 
+ 	/* Set MSI enabled bits	 */
+ 	pci_intx_for_msi(dev, 0);
+-	msi_set_enable(dev, 1);
++	msi_set_enable(dev, pos, 1);
+ 	dev->msi_enabled = 1;
+ 
+ 	dev->irq = pirq;
+@@ -397,6 +395,7 @@ static int msix_capability_init(struct p
+ {
+ 	u64 table_base;
+ 	int pirq, i, j, mapped, pos;
++	u16 control;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 	struct msi_pirq_entry *pirq_entry;
+ 
+@@ -406,11 +405,24 @@ static int msix_capability_init(struct p
+ 	msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
+ 
+ 	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++	pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
++
++	/* Ensure MSI-X is disabled while it is set up */
++	control &= ~PCI_MSIX_FLAGS_ENABLE;
++	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
++
+ 	table_base = find_table_base(dev, pos);
+ 	if (!table_base)
+ 		return -ENODEV;
+ 
+-	/* MSI-X Table Initialization */
++	/*
++	 * Some devices require MSI-X to be enabled before we can touch the
++	 * MSI-X registers.  We need to mask all the vectors to prevent
++	 * interrupts coming in before they're fully set up.
++	 */
++	control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
++	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
++
+ 	for (i = 0; i < nvec; i++) {
+ 		mapped = 0;
+ 		list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
+@@ -447,10 +459,13 @@ static int msix_capability_init(struct p
+ 		return avail;
+ 	}
+ 
++	/* Set MSI-X enabled bits and unmask the function */
+ 	pci_intx_for_msi(dev, 0);
+-	msix_set_enable(dev, 1);
+ 	dev->msix_enabled = 1;
+ 
++	control &= ~PCI_MSIX_FLAGS_MASKALL;
++	pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
++
+ 	return 0;
+ }
+ 
+@@ -572,7 +587,7 @@ EXPORT_SYMBOL(pci_enable_msi_block);
+ extern void pci_frontend_disable_msi(struct pci_dev* dev);
+ void pci_msi_shutdown(struct pci_dev *dev)
+ {
+-	int pirq;
++	int pirq, pos;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+ 	if (!pci_msi_enable || !dev || !dev->msi_enabled)
+@@ -594,7 +609,8 @@ void pci_msi_shutdown(struct pci_dev *de
+ 	msi_unmap_pirq(dev, pirq);
+ 
+ 	/* Disable MSI mode */
+-	msi_set_enable(dev, 0);
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	msi_set_enable(dev, pos, 0);
+ 	pci_intx_for_msi(dev, 1);
+ 	dev->msi_enabled = 0;
+ }
+@@ -634,8 +650,8 @@ int pci_msix_table_size(struct pci_dev *
+  * indicates the successful configuration of MSI-X capability structure
+  * with new allocated MSI-X irqs. A return of < 0 indicates a failure.
+  * Or a return of > 0 indicates that driver request is exceeding the number
+- * of irqs available. Driver should use the returned value to re-send
+- * its request.
++ * of irqs or MSI-X 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);
+@@ -691,7 +707,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ 
+ 	nr_entries = pci_msix_table_size(dev);
+ 	if (nvec > nr_entries)
+-		return -EINVAL;
++		return nr_entries;
+ 
+ 	/* Check for any invalid entries */
+ 	for (i = 0; i < nvec; i++) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/Kconfig	2009-12-18 12:27:45.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/Kconfig	2009-12-18 12:27:52.000000000 +0100
+@@ -371,7 +371,7 @@ config XEN_SCRUB_PAGES
+ 
+ config XEN_DEV_EVTCHN
+ 	tristate "Xen /dev/xen/evtchn device"
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	default y
+ 	help
+ 	  The evtchn driver allows a userspace process to triger event
+@@ -404,7 +404,7 @@ config XEN_COMPAT_XENFS
+ 
+ config XEN_SYS_HYPERVISOR
+        bool "Create xen entries under /sys/hypervisor"
+-       depends on XEN && SYSFS
++       depends on PARAVIRT_XEN && SYSFS
+        select SYS_HYPERVISOR
+        default y
+        help
+--- sle11sp1-2010-01-20.orig/drivers/xen/Makefile	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/Makefile	2009-11-06 10:52:09.000000000 +0100
+@@ -14,7 +14,9 @@ obj-$(CONFIG_XEN)		+= features.o util.o
+ obj-$(CONFIG_HOTPLUG_CPU)	+= $(xen-hotplug-y)
+ obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
+ obj-$(CONFIG_XEN_BALLOON)	+= $(xen-balloon-y)
++obj-$(CONFIG_XEN_DEV_EVTCHN)	+= evtchn.o
+ obj-$(CONFIG_XENFS)		+= xenfs/
++obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+ obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
+ obj-$(CONFIG_XEN_BLKDEV_TAP2)           += blktap2/
+--- sle11sp1-2010-01-20.orig/drivers/xen/balloon/balloon.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/balloon/balloon.c	2009-11-06 10:52:09.000000000 +0100
+@@ -311,7 +311,7 @@ static int increase_reservation(unsigned
+ 	balloon_unlock(flags);
+ 
+ #ifndef MODULE
+-	setup_per_zone_pages_min();
++	setup_per_zone_wmarks();
+ 	if (rc > 0)
+ 		kswapd_run(0);
+ 	if (need_zonelists_rebuild)
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkback/blkback.c	2010-01-04 12:38:24.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkback/blkback.c	2010-01-04 12:41:42.000000000 +0100
+@@ -523,7 +523,7 @@ static int dispatch_rw_block_io(blkif_t 
+ 
+ 	for (i = 0; i < nseg; i++) {
+ 		if (((int)preq.sector_number|(int)seg[i].nsec) &
+-		    ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
++		    ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) {
+ 			DPRINTK("Misaligned I/O request from domain %d",
+ 				blkif->domid);
+ 			goto fail_put_bio;
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkback/vbd.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkback/vbd.c	2009-11-06 10:52:09.000000000 +0100
+@@ -47,7 +47,7 @@ unsigned int vbd_info(struct vbd *vbd)
+ 
+ unsigned long vbd_secsize(struct vbd *vbd)
+ {
+-	return bdev_hardsect_size(vbd->bdev);
++	return bdev_logical_block_size(vbd->bdev);
+ }
+ 
+ int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -105,7 +105,7 @@ static void update_blkif_status(blkif_t 
+ 				   char *buf)				\
+ 	{								\
+ 		struct xenbus_device *dev = to_xenbus_device(_dev);	\
+-		struct backend_info *be = dev->dev.driver_data;		\
++		struct backend_info *be = dev_get_drvdata(&dev->dev);	\
+ 									\
+ 		return sprintf(buf, format, ##args);			\
+ 	}								\
+@@ -169,7 +169,7 @@ void xenvbd_sysfs_delif(struct xenbus_de
+ 
+ static int blkback_remove(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("");
+ 
+@@ -190,7 +190,7 @@ static int blkback_remove(struct xenbus_
+ 	}
+ 
+ 	kfree(be);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return 0;
+ }
+ 
+@@ -225,7 +225,7 @@ static int blkback_probe(struct xenbus_d
+ 		return -ENOMEM;
+ 	}
+ 	be->dev = dev;
+-	dev->dev.driver_data = be;
++	dev_set_drvdata(&dev->dev, be);
+ 
+ 	be->blkif = blkif_alloc(dev->otherend_id);
+ 	if (IS_ERR(be->blkif)) {
+@@ -348,7 +348,7 @@ static void backend_changed(struct xenbu
+ static void frontend_changed(struct xenbus_device *dev,
+ 			     enum xenbus_state frontend_state)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	DPRINTK("%s", xenbus_strstate(frontend_state));
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:50:18.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkfront/blkfront.c	2010-01-18 16:54:21.000000000 +0100
+@@ -119,12 +119,12 @@ static int blkfront_probe(struct xenbus_
+ 
+ 	/* Front end dir is a number, which is used as the id. */
+ 	info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 
+ 	err = talk_to_backend(dev, info);
+ 	if (err) {
+ 		kfree(info);
+-		dev->dev.driver_data = NULL;
++		dev_set_drvdata(&dev->dev, NULL);
+ 		return err;
+ 	}
+ 
+@@ -140,7 +140,7 @@ static int blkfront_probe(struct xenbus_
+  */
+ static int blkfront_resume(struct xenbus_device *dev)
+ {
+-	struct blkfront_info *info = dev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	DPRINTK("blkfront_resume: %s\n", dev->nodename);
+@@ -265,7 +265,7 @@ fail:
+ static void backend_changed(struct xenbus_device *dev,
+ 			    enum xenbus_state backend_state)
+ {
+-	struct blkfront_info *info = dev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+ 	struct block_device *bd;
+ 
+ 	DPRINTK("blkfront:backend_changed.\n");
+@@ -387,7 +387,7 @@ static void connect(struct blkfront_info
+  */
+ static void blkfront_closing(struct xenbus_device *dev)
+ {
+-	struct blkfront_info *info = dev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+ 	unsigned long flags;
+ 
+ 	DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
+@@ -416,7 +416,7 @@ static void blkfront_closing(struct xenb
+ 
+ static int blkfront_remove(struct xenbus_device *dev)
+ {
+-	struct blkfront_info *info = dev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("blkfront_remove: %s removed\n", dev->nodename);
+ 
+@@ -646,7 +646,7 @@ static int blkif_queue_request(struct re
+ 	info->shadow[id].request = (unsigned long)req;
+ 
+ 	ring_req->id = id;
+-	ring_req->sector_number = (blkif_sector_t)req->sector;
++	ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
+ 	ring_req->handle = info->handle;
+ 
+ 	ring_req->operation = rq_data_dir(req) ?
+@@ -702,25 +702,25 @@ void do_blkif_request(struct request_que
+ 
+ 	queued = 0;
+ 
+-	while ((req = elv_next_request(rq)) != NULL) {
++	while ((req = blk_peek_request(rq)) != NULL) {
+ 		info = req->rq_disk->private_data;
+-		if (!blk_fs_request(req)) {
+-			end_request(req, 0);
+-			continue;
+-		}
+ 
+ 		if (RING_FULL(&info->ring))
+ 			goto wait;
+ 
+-		DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
+-			"(%u/%li) buffer:%p [%s]\n",
+-			req, req->cmd, (long long)req->sector,
+-			req->current_nr_sectors,
+-			req->nr_sectors, req->buffer,
+-			rq_data_dir(req) ? "write" : "read");
++		blk_start_request(req);
+ 
++		if (!blk_fs_request(req)) {
++			__blk_end_request_all(req, -EIO);
++			continue;
++		}
++
++		DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
++			"(%u/%u) buffer:%p [%s]\n",
++			req, req->cmd, (long long)blk_rq_pos(req),
++			blk_rq_cur_sectors(req), blk_rq_sectors(req),
++			req->buffer, rq_data_dir(req) ? "write" : "read");
+ 
+-		blkdev_dequeue_request(req);
+ 		if (blkif_queue_request(req)) {
+ 			blk_requeue_request(rq, req);
+ 		wait:
+@@ -785,8 +785,7 @@ static irqreturn_t blkif_int(int irq, vo
+ 				DPRINTK("Bad return from blkdev data "
+ 					"request: %x\n", bret->status);
+ 
+-			ret = __blk_end_request(req, ret, blk_rq_bytes(req));
+-			BUG_ON(ret);
++			__blk_end_request_all(req, ret);
+ 			break;
+ 		default:
+ 			BUG();
+@@ -912,7 +911,7 @@ static void blkif_recover(struct blkfron
+ 
+ int blkfront_is_ready(struct xenbus_device *dev)
+ {
+-	struct blkfront_info *info = dev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	return info->is_ready > 0;
+ }
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:50:37.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkfront/vbd.c	2010-01-18 16:54:23.000000000 +0100
+@@ -313,7 +313,7 @@ xlvbd_init_blk_queue(struct gendisk *gd,
+ #endif
+ 
+ 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
+-	blk_queue_hardsect_size(rq, sector_size);
++	blk_queue_logical_block_size(rq, sector_size);
+ 	blk_queue_max_sectors(rq, 512);
+ 
+ 	/* Each segment in a request is up to an aligned page in size. */
+@@ -500,7 +500,7 @@ static ssize_t show_media(struct device 
+ 		                  struct device_attribute *attr, char *buf)
+ {
+ 	struct xenbus_device *xendev = to_xenbus_device(dev);
+-	struct blkfront_info *info = xendev->dev.driver_data;
++	struct blkfront_info *info = dev_get_drvdata(&xendev->dev);
+ 
+ 	if (info->gd->flags & GENHD_FL_CD)
+ 		return sprintf(buf, "cdrom\n");
+--- sle11sp1-2010-01-20.orig/drivers/xen/blktap/blktap.c	2010-01-04 12:40:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blktap/blktap.c	2010-01-04 12:41:47.000000000 +0100
+@@ -566,7 +566,8 @@ void signal_tapdisk(int idx) 
+ 		return;
+ 
+ 	if (info->pid > 0) {
+-		ptask = find_task_by_pid_ns(info->pid, info->pid_ns);
++		ptask = pid_task(find_pid_ns(info->pid, info->pid_ns),
++				 PIDTYPE_PID);
+ 		if (ptask)
+ 			info->status = CLEANSHUTDOWN;
+ 	}
+--- sle11sp1-2010-01-20.orig/drivers/xen/blktap/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blktap/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -123,7 +123,7 @@ static int blktap_name(blkif_t *blkif, c
+ 				   char *buf)				\
+ 	{								\
+ 		struct xenbus_device *dev = to_xenbus_device(_dev);	\
+-		struct backend_info *be = dev->dev.driver_data;		\
++		struct backend_info *be = dev_get_drvdata(&dev->dev);	\
+ 									\
+ 		return sprintf(buf, format, ##args);			\
+ 	}								\
+@@ -152,7 +152,7 @@ static struct attribute_group tapstat_gr
+ int xentap_sysfs_addif(struct xenbus_device *dev)
+ {
+ 	int err;
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
+ 	if (!err)
+ 		be->group_added = 1;
+@@ -161,14 +161,14 @@ int xentap_sysfs_addif(struct xenbus_dev
+ 
+ void xentap_sysfs_delif(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
+ 	be->group_added = 0;
+ }
+ 
+ static int blktap_remove(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	if (be->group_added)
+ 		xentap_sysfs_delif(be->dev);
+@@ -186,7 +186,7 @@ static int blktap_remove(struct xenbus_d
+ 		be->blkif = NULL;
+ 	}
+ 	kfree(be);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return 0;
+ }
+ 
+@@ -252,7 +252,7 @@ static int blktap_probe(struct xenbus_de
+ 	}
+ 
+ 	be->dev = dev;
+-	dev->dev.driver_data = be;
++	dev_set_drvdata(&dev->dev, be);
+ 	be->xenbus_id = get_id(dev->nodename);
+ 
+ 	be->blkif = tap_alloc_blkif(dev->otherend_id);
+@@ -332,7 +332,7 @@ static void tap_backend_changed(struct x
+ static void tap_frontend_changed(struct xenbus_device *dev,
+ 			     enum xenbus_state frontend_state)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	DPRINTK("\n");
+--- sle11sp1-2010-01-20.orig/drivers/xen/blktap2/device.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blktap2/device.c	2010-01-04 12:41:52.000000000 +0100
+@@ -208,13 +208,6 @@ flush_tlb_kernel_page(unsigned long kvad
+ #endif
+ }
+ 
+-static void
+-blktap_device_end_dequeued_request(struct request *req, int ret)
+-{
+-	if (blk_end_request(req, ret, blk_rq_bytes(req)))
+-		BUG();
+-}
+-
+ /*
+  * tap->tap_sem held on entry
+  */
+@@ -381,7 +374,7 @@ blktap_device_fail_pending_requests(stru
+ 
+ 		blktap_unmap(tap, request);
+ 		req = (struct request *)(unsigned long)request->id;
+-		blktap_device_end_dequeued_request(req, -ENODEV);
++		blk_end_request_all(req, -ENODEV);
+ 		blktap_request_free(tap, request);
+ 	}
+ 
+@@ -420,7 +413,7 @@ blktap_device_finish_request(struct blkt
+ 		if (unlikely(res->status != BLKIF_RSP_OKAY))
+ 			BTERR("Bad return from device data "
+ 				"request: %x\n", res->status);
+-		blktap_device_end_dequeued_request(req,
++		blk_end_request_all(req,
+ 			res->status == BLKIF_RSP_OKAY ? 0 : -EIO);
+ 		break;
+ 	default:
+@@ -651,7 +644,7 @@ blktap_device_process_request(struct blk
+ 	ring    = &tap->ring;
+ 	usr_idx = request->usr_idx;
+ 	blkif_req.id = usr_idx;
+-	blkif_req.sector_number = (blkif_sector_t)req->sector;
++	blkif_req.sector_number = (blkif_sector_t)blk_rq_pos(req);
+ 	blkif_req.handle = 0;
+ 	blkif_req.operation = rq_data_dir(req) ?
+ 		BLKIF_OP_WRITE : BLKIF_OP_READ;
+@@ -848,47 +841,46 @@ blktap_device_run_queue(struct blktap *t
+ 
+ 	BTDBG("running queue for %d\n", tap->minor);
+ 
+-	while ((req = elv_next_request(rq)) != NULL) {
++	while ((req = blk_peek_request(rq)) != NULL) {
++		if (RING_FULL(&ring->ring)) {
++		wait:
++			/* Avoid pointless unplugs. */
++			blk_stop_queue(rq);
++			blktap_defer(tap);
++			break;
++		}
++
++		blk_start_request(req);
++
+ 		if (!blk_fs_request(req)) {
+-			end_request(req, 0);
++			__blk_end_request_all(req, -EIO);
+ 			continue;
+ 		}
+ 
+ 		if (blk_barrier_rq(req)) {
+-			end_request(req, 0);
++			__blk_end_request_all(req, -EOPNOTSUPP);
+ 			continue;
+ 		}
+ 
+ #ifdef ENABLE_PASSTHROUGH
+ 		if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
+-			blkdev_dequeue_request(req);
+ 			blktap_device_forward_request(tap, req);
+ 			continue;
+ 		}
+ #endif
+ 
+-		if (RING_FULL(&ring->ring)) {
+-		wait:
+-			/* Avoid pointless unplugs. */
+-			blk_stop_queue(rq);
+-			blktap_defer(tap);
+-			break;
+-		}
+-
+ 		request = blktap_request_allocate(tap);
+ 		if (!request) {
+ 			tap->stats.st_oo_req++;
+ 			goto wait;
+ 		}
+ 
+-		BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%lx) "
++		BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%x) "
+ 		      "buffer:%p [%s], pending: %p\n", req, tap->minor,
+-		      req->cmd, (unsigned long long)req->sector,
+-		      req->current_nr_sectors, req->nr_sectors, req->buffer,
++		      req->cmd, (unsigned long long)blk_rq_pos(req),
++		      blk_rq_cur_sectors(req), blk_rq_sectors(req), req->buffer,
+ 		      rq_data_dir(req) ? "write" : "read", request);
+ 
+-		blkdev_dequeue_request(req);
+-
+ 		spin_unlock_irq(&dev->lock);
+ 		down_read(&tap->tap_sem);
+ 
+@@ -896,7 +888,7 @@ blktap_device_run_queue(struct blktap *t
+ 		if (!err)
+ 			queued++;
+ 		else {
+-			blktap_device_end_dequeued_request(req, err);
++			blk_end_request_all(req, err);
+ 			blktap_request_free(tap, request);
+ 		}
+ 
+@@ -936,11 +928,13 @@ blktap_device_do_request(struct request_
+ 	return;
+ 
+ fail:
+-	while ((req = elv_next_request(rq))) {
++	while ((req = blk_peek_request(rq))) {
+ 		BTERR("device closed: failing secs %llu - %llu\n",
+-		      (unsigned long long)req->sector,
+-		      (unsigned long long)req->sector + req->nr_sectors);
+-		end_request(req, 0);
++		      (unsigned long long)blk_rq_pos(req),
++		      (unsigned long long)blk_rq_pos(req)
++		      + blk_rq_cur_sectors(req));
++		blk_start_request(req);
++		__blk_end_request_all(req, -EIO);
+ 	}
+ }
+ 
+@@ -993,7 +987,7 @@ blktap_device_configure(struct blktap *t
+ 	set_capacity(dev->gd, tap->params.capacity);
+ 
+ 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
+-	blk_queue_hardsect_size(rq, tap->params.sector_size);
++	blk_queue_logical_block_size(rq, tap->params.sector_size);
+ 	blk_queue_max_sectors(rq, 512);
+ 
+ 	/* Each segment in a request is up to an aligned page in size. */
+--- sle11sp1-2010-01-20.orig/drivers/xen/console/console.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/console/console.c	2009-11-06 10:52:09.000000000 +0100
+@@ -46,7 +46,6 @@
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/console.h>
+-#include <linux/bootmem.h>
+ #include <linux/sysrq.h>
+ #include <linux/screen_info.h>
+ #include <linux/vt.h>
+@@ -236,7 +235,7 @@ static int __init xen_console_init(void)
+ 		goto out;
+ 	}
+ 
+-	wbuf = alloc_bootmem(wbuf_size);
++	wbuf = kmalloc(wbuf_size, GFP_KERNEL);
+ 
+ 	register_console(&kcons_info);
+ 
+@@ -632,8 +631,8 @@ static void xencons_close(struct tty_str
+ 	tty->closing = 1;
+ 	tty_wait_until_sent(tty, 0);
+ 	tty_driver_flush_buffer(tty);
+-	if (tty->ldisc.ops->flush_buffer != NULL)
+-		tty->ldisc.ops->flush_buffer(tty);
++	if (tty->ldisc->ops->flush_buffer)
++		tty->ldisc->ops->flush_buffer(tty);
+ 	tty->closing = 0;
+ 	spin_lock_irqsave(&xencons_lock, flags);
+ 	xencons_tty = NULL;
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/evtchn.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/evtchn.c	2009-11-06 10:52:09.000000000 +0100
+@@ -35,7 +35,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
+-#include <linux/bootmem.h>
+ #include <linux/ftrace.h>
+ #include <linux/version.h>
+ #include <asm/atomic.h>
+@@ -344,7 +343,7 @@ static int find_unbound_irq(unsigned int
+ 	int irq;
+ 
+ 	for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++) {
+-		struct irq_desc *desc = irq_to_desc_alloc_cpu(irq, cpu);
++		struct irq_desc *desc = irq_to_desc_alloc_node(irq, cpu_to_node(cpu));
+ 		struct irq_cfg *cfg = desc->chip_data;
+ 
+ 		if (!cfg->bindcount) {
+@@ -697,9 +696,11 @@ static void rebind_irq_to_cpu(unsigned i
+ 		rebind_evtchn_to_cpu(evtchn, tcpu);
+ }
+ 
+-static void set_affinity_irq(unsigned int irq, const struct cpumask *dest)
++static int set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+ {
+ 	rebind_irq_to_cpu(irq, cpumask_first(dest));
++
++	return 0;
+ }
+ #endif
+ 
+@@ -1260,7 +1261,7 @@ int evtchn_map_pirq(int irq, int xen_pir
+ 
+ 			if (identity_mapped_irq(irq))
+ 				continue;
+-			desc = irq_to_desc_alloc_cpu(irq, smp_processor_id());
++			desc = irq_to_desc_alloc_node(irq, numa_node_id());
+ 			cfg = desc->chip_data;
+ 			if (!index_from_irq(irq)) {
+ 				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
+@@ -1311,8 +1312,9 @@ void __init xen_init_IRQ(void)
+ 
+ 	init_evtchn_cpu_bindings();
+ 
+-	pirq_needs_eoi = alloc_bootmem_pages(sizeof(unsigned long)
+-		* BITS_TO_LONGS(ALIGN(nr_pirqs, PAGE_SIZE * 8)));
++	i = get_order(sizeof(unsigned long) * BITS_TO_LONGS(nr_pirqs));
++	pirq_needs_eoi = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, i);
++	BUILD_BUG_ON(NR_PIRQS > PAGE_SIZE * 8);
+  	eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
+ 	if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
+ 		pirq_eoi_does_unmask = true;
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/smpboot.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/smpboot.c	2009-11-06 10:52:09.000000000 +0100
+@@ -43,9 +43,11 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
+ static DEFINE_PER_CPU(int, resched_irq);
+ static DEFINE_PER_CPU(int, callfunc_irq);
+ static DEFINE_PER_CPU(int, call1func_irq);
++static DEFINE_PER_CPU(int, reboot_irq);
+ static char resched_name[NR_CPUS][15];
+ static char callfunc_name[NR_CPUS][15];
+ static char call1func_name[NR_CPUS][15];
++static char reboot_name[NR_CPUS][15];
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
+@@ -102,7 +104,7 @@ static int __cpuinit xen_smp_intr_init(u
+ 	int rc;
+ 
+ 	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) =
+-		per_cpu(call1func_irq, cpu) = -1;
++		per_cpu(call1func_irq, cpu) = per_cpu(reboot_irq, cpu) = -1;
+ 
+ 	sprintf(resched_name[cpu], "resched%u", cpu);
+ 	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
+@@ -137,6 +139,17 @@ static int __cpuinit xen_smp_intr_init(u
+ 		goto fail;
+ 	per_cpu(call1func_irq, cpu) = rc;
+ 
++	sprintf(reboot_name[cpu], "reboot%u", cpu);
++	rc = bind_ipi_to_irqhandler(REBOOT_VECTOR,
++				    cpu,
++				    smp_reboot_interrupt,
++				    IRQF_DISABLED|IRQF_NOBALANCING,
++				    reboot_name[cpu],
++				    NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(reboot_irq, cpu) = rc;
++
+ 	rc = xen_spinlock_init(cpu);
+ 	if (rc < 0)
+ 		goto fail;
+@@ -153,6 +166,8 @@ static int __cpuinit xen_smp_intr_init(u
+ 		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+ 	if (per_cpu(call1func_irq, cpu) >= 0)
+ 		unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
++	if (per_cpu(reboot_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
+ 	xen_spinlock_cleanup(cpu);
+ 	return rc;
+ }
+@@ -166,6 +181,7 @@ static void __cpuexit xen_smp_intr_exit(
+ 	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
++	unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
+ 	xen_spinlock_cleanup(cpu);
+ }
+ #endif
+--- sle11sp1-2010-01-20.orig/drivers/xen/fbfront/xenfb.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/fbfront/xenfb.c	2009-11-06 10:52:09.000000000 +0100
+@@ -597,7 +597,7 @@ static int __devinit xenfb_probe(struct 
+ 		fb_size = XENFB_DEFAULT_FB_LEN;
+ 	}
+ 
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 	info->xbdev = dev;
+ 	info->irq = -1;
+ 	info->x1 = info->y1 = INT_MAX;
+@@ -701,7 +701,7 @@ static int __devinit xenfb_probe(struct 
+ 
+ static int xenfb_resume(struct xenbus_device *dev)
+ {
+-	struct xenfb_info *info = dev->dev.driver_data;
++	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	xenfb_disconnect_backend(info);
+ 	xenfb_init_shared_page(info, info->fb_info);
+@@ -710,7 +710,7 @@ static int xenfb_resume(struct xenbus_de
+ 
+ static int xenfb_remove(struct xenbus_device *dev)
+ {
+-	struct xenfb_info *info = dev->dev.driver_data;
++	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	del_timer(&info->refresh);
+ 	if (info->kthread)
+@@ -817,7 +817,7 @@ static void xenfb_disconnect_backend(str
+ static void xenfb_backend_changed(struct xenbus_device *dev,
+ 				  enum xenbus_state backend_state)
+ {
+-	struct xenfb_info *info = dev->dev.driver_data;
++	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+ 	int val;
+ 
+ 	switch (backend_state) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:52:09.000000000 +0100
+@@ -113,7 +113,7 @@ int __devinit xenkbd_probe(struct xenbus
+ 		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+ 		return -ENOMEM;
+ 	}
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 	info->xbdev = dev;
+ 	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+ 
+@@ -186,7 +186,7 @@ int __devinit xenkbd_probe(struct xenbus
+ 
+ static int xenkbd_resume(struct xenbus_device *dev)
+ {
+-	struct xenkbd_info *info = dev->dev.driver_data;
++	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	xenkbd_disconnect_backend(info);
+ 	info->page->in_cons = info->page->in_prod = 0;
+@@ -196,7 +196,7 @@ static int xenkbd_resume(struct xenbus_d
+ 
+ static int xenkbd_remove(struct xenbus_device *dev)
+ {
+-	struct xenkbd_info *info = dev->dev.driver_data;
++	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	xenkbd_disconnect_backend(info);
+ 	input_unregister_device(info->kbd);
+@@ -262,7 +262,7 @@ static void xenkbd_disconnect_backend(st
+ static void xenkbd_backend_changed(struct xenbus_device *dev,
+ 				   enum xenbus_state backend_state)
+ {
+-	struct xenkbd_info *info = dev->dev.driver_data;
++	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+ 	int ret, val;
+ 
+ 	switch (backend_state) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/accel.c	2009-11-06 10:45:48.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/accel.c	2009-11-06 10:52:09.000000000 +0100
+@@ -103,7 +103,7 @@ static int netback_accelerator_probe_bac
+ 	struct xenbus_device *xendev = to_xenbus_device(dev);
+ 
+ 	if (!strcmp("vif", xendev->devicetype)) {
+-		struct backend_info *be = xendev->dev.driver_data;
++		struct backend_info *be = dev_get_drvdata(&xendev->dev);
+ 
+ 		if (match_accelerator(xendev, be, accelerator) &&
+ 		    try_module_get(accelerator->hooks->owner)) {
+@@ -124,7 +124,7 @@ static int netback_accelerator_remove_ba
+ 		(struct netback_accelerator *)arg;
+ 	
+ 	if (!strcmp("vif", xendev->devicetype)) {
+-		struct backend_info *be = xendev->dev.driver_data;
++		struct backend_info *be = dev_get_drvdata(&xendev->dev);
+ 
+ 		if (be->accelerator == accelerator) {
+ 			be->accelerator->hooks->remove(xendev);
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/loopback.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/loopback.c	2009-11-06 10:52:09.000000000 +0100
+@@ -137,8 +137,8 @@ static int loopback_start_xmit(struct sk
+ 		return 0;
+ 	}
+ 
+-	dst_release(skb->dst);
+-	skb->dst = NULL;
++	dst_release(skb_dst(skb));
++	skb_dst_set(skb, NULL);
+ 
+ 	skb_orphan(skb);
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/xenbus.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -35,7 +35,7 @@ static void backend_create_netif(struct 
+ 
+ static int netback_remove(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	netback_remove_accelerators(be, dev);
+ 
+@@ -45,7 +45,7 @@ static int netback_remove(struct xenbus_
+ 		be->netif = NULL;
+ 	}
+ 	kfree(be);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return 0;
+ }
+ 
+@@ -70,7 +70,7 @@ static int netback_probe(struct xenbus_d
+ 	}
+ 
+ 	be->dev = dev;
+-	dev->dev.driver_data = be;
++	dev_set_drvdata(&dev->dev, be);
+ 
+ 	sg = 1;
+ 	if (netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB)
+@@ -151,7 +151,7 @@ fail:
+  */
+ static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *env)
+ {
+-	struct backend_info *be = xdev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&xdev->dev);
+ 	netif_t *netif = be->netif;
+ 	char *val;
+ 
+@@ -207,7 +207,7 @@ static void backend_create_netif(struct 
+ static void frontend_changed(struct xenbus_device *dev,
+ 			     enum xenbus_state frontend_state)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("%s", xenbus_strstate(frontend_state));
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netfront/netfront.c	2009-11-06 10:52:09.000000000 +0100
+@@ -257,7 +257,7 @@ static int __devinit netfront_probe(stru
+ 	}
+ 
+ 	info = netdev_priv(netdev);
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 
+ 	err = register_netdev(info->netdev);
+ 	if (err) {
+@@ -278,13 +278,13 @@ static int __devinit netfront_probe(stru
+ 
+  fail:
+ 	free_netdev(netdev);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return err;
+ }
+ 
+ static int __devexit netfront_remove(struct xenbus_device *dev)
+ {
+-	struct netfront_info *info = dev->dev.driver_data;
++	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("%s\n", dev->nodename);
+ 
+@@ -306,14 +306,14 @@ static int __devexit netfront_remove(str
+ 
+ static int netfront_suspend(struct xenbus_device *dev)
+ {
+-	struct netfront_info *info = dev->dev.driver_data;
++	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+ 	return netfront_accelerator_suspend(info, dev);
+ }
+ 
+ 
+ static int netfront_suspend_cancel(struct xenbus_device *dev)
+ {
+-	struct netfront_info *info = dev->dev.driver_data;
++	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+ 	return netfront_accelerator_suspend_cancel(info, dev);
+ }
+ 
+@@ -326,7 +326,7 @@ static int netfront_suspend_cancel(struc
+  */
+ static int netfront_resume(struct xenbus_device *dev)
+ {
+-	struct netfront_info *info = dev->dev.driver_data;
++	struct netfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("%s\n", dev->nodename);
+ 
+@@ -531,7 +531,7 @@ static int setup_device(struct xenbus_de
+ static void backend_changed(struct xenbus_device *dev,
+ 			    enum xenbus_state backend_state)
+ {
+-	struct netfront_info *np = dev->dev.driver_data;
++	struct netfront_info *np = dev_get_drvdata(&dev->dev);
+ 	struct net_device *netdev = np->netdev;
+ 
+ 	DPRINTK("%s\n", xenbus_strstate(backend_state));
+--- sle11sp1-2010-01-20.orig/drivers/xen/pciback/xenbus.c	2009-11-06 10:49:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/pciback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -24,7 +24,7 @@ static struct pciback_device *alloc_pdev
+ 	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
+ 
+ 	pdev->xdev = xdev;
+-	xdev->dev.driver_data = pdev;
++	dev_set_drvdata(&xdev->dev, pdev);
+ 
+ 	spin_lock_init(&pdev->dev_lock);
+ 
+@@ -74,7 +74,7 @@ static void free_pdev(struct pciback_dev
+ 
+ 	pciback_release_devices(pdev);
+ 
+-	pdev->xdev->dev.driver_data = NULL;
++	dev_set_drvdata(&pdev->xdev->dev, NULL);
+ 	pdev->xdev = NULL;
+ 
+ 	kfree(pdev);
+@@ -475,7 +475,7 @@ static int pciback_reconfigure(struct pc
+ static void pciback_frontend_changed(struct xenbus_device *xdev,
+ 				     enum xenbus_state fe_state)
+ {
+-	struct pciback_device *pdev = xdev->dev.driver_data;
++	struct pciback_device *pdev = dev_get_drvdata(&xdev->dev);
+ 
+ 	dev_dbg(&xdev->dev, "fe state changed %d\n", fe_state);
+ 
+@@ -668,7 +668,7 @@ static int pciback_xenbus_probe(struct x
+ 
+ static int pciback_xenbus_remove(struct xenbus_device *dev)
+ {
+-	struct pciback_device *pdev = dev->dev.driver_data;
++	struct pciback_device *pdev = dev_get_drvdata(&dev->dev);
+ 
+ 	if (pdev != NULL)
+ 		free_pdev(pdev);
+--- sle11sp1-2010-01-20.orig/drivers/xen/pcifront/pci_op.c	2009-11-06 10:46:27.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/pcifront/pci_op.c	2009-11-06 10:52:09.000000000 +0100
+@@ -416,7 +416,7 @@ void pci_frontend_disable_msi(struct pci
+ #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)
++static int pcifront_claim_resource(struct pci_dev *dev, void *data)
+ {
+ 	struct pcifront_device *pdev = data;
+ 	int i;
+@@ -431,6 +431,8 @@ static void pcifront_claim_resource(stru
+ 			pci_claim_resource(dev, i);
+ 		}
+ 	}
++
++	return 0;
+ }
+ 
+ int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+--- sle11sp1-2010-01-20.orig/drivers/xen/pcifront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/pcifront/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -34,7 +34,7 @@ static struct pcifront_device *alloc_pde
+ 	/*Flag for registering PV AER handler*/
+ 	set_bit(_XEN_PCIB_AERHANDLER, (void*)&pdev->sh_info->flags);
+ 
+-	xdev->dev.driver_data = pdev;
++	dev_set_drvdata(&xdev->dev, pdev);
+ 	pdev->xdev = xdev;
+ 
+ 	INIT_LIST_HEAD(&pdev->root_buses);
+@@ -70,7 +70,7 @@ static void free_pdev(struct pcifront_de
+ 		gnttab_end_foreign_access(pdev->gnt_ref,
+ 					  (unsigned long)pdev->sh_info);
+ 
+-	pdev->xdev->dev.driver_data = NULL;
++	dev_set_drvdata(&pdev->xdev->dev, NULL);
+ 
+ 	kfree(pdev);
+ }
+@@ -381,7 +381,7 @@ static int pcifront_detach_devices(struc
+ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
+ 						  enum xenbus_state be_state)
+ {
+-	struct pcifront_device *pdev = xdev->dev.driver_data;
++	struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
+ 
+ 	switch (be_state) {
+ 	case XenbusStateUnknown:
+@@ -431,8 +431,8 @@ static int pcifront_xenbus_probe(struct 
+ 
+ static int pcifront_xenbus_remove(struct xenbus_device *xdev)
+ {
+-	if (xdev->dev.driver_data)
+-		free_pdev(xdev->dev.driver_data);
++	if (dev_get_drvdata(&xdev->dev))
++		free_pdev(dev_get_drvdata(&xdev->dev));
+ 
+ 	return 0;
+ }
+--- sle11sp1-2010-01-20.orig/drivers/xen/scsiback/scsiback.c	2010-01-04 12:35:40.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/scsiback/scsiback.c	2010-01-04 12:41:57.000000000 +0100
+@@ -224,7 +224,7 @@ static void scsiback_cmd_done(struct req
+ 	int errors;
+ 
+ 	sense_buffer = req->sense;
+-	resid        = req->data_len;
++	resid        = blk_rq_bytes(req);
+ 	errors       = req->errors;
+ 
+ 	if (errors != 0) {
+@@ -339,21 +339,6 @@ fail_flush:
+ 	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);
+-
+-	return blk_rq_append_bio(q, rq, bio);
+-}
+-
+-
+ /* quoted scsi_lib.c/scsi_bi_endio */
+ static void scsiback_bi_endio(struct bio *bio, int error)
+ {
+@@ -363,29 +348,28 @@ static void scsiback_bi_endio(struct bio
+ 
+ 
+ /* quoted scsi_lib.c/scsi_req_map_sg . */
+-static int request_map_sg(struct request *rq, pending_req_t *pending_req, unsigned int count)
++static struct bio *request_map_sg(pending_req_t *pending_req)
+ {
+-	struct request_queue *q = rq->q;
+-	int nr_pages;
+-	unsigned int nsegs = count;
+-	unsigned int data_len = 0, len, bytes, off;
++	struct request_queue *q = pending_req->sdev->request_queue;
++	unsigned int nsegs = (unsigned int)pending_req->nr_segments;
++	unsigned int i, len, bytes, off, nr_pages, nr_vecs = 0;
+ 	struct scatterlist *sg;
+ 	struct page *page;
+-	struct bio *bio = NULL;
+-	int i, err, nr_vecs = 0;
++	struct bio *bio = NULL, *bio_first = NULL, *bio_last = NULL;
++	int err;
+ 
+ 	for_each_sg (pending_req->sgl, sg, nsegs, i) {
+ 		page = sg_page(sg);
+ 		off = sg->offset;
+ 		len = sg->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_vecs = min_t(unsigned int, BIO_MAX_PAGES,
++					 	nr_pages);
+ 				nr_pages -= nr_vecs;
+ 				bio = bio_alloc(GFP_KERNEL, nr_vecs);
+ 				if (!bio) {
+@@ -393,6 +377,11 @@ static int request_map_sg(struct request
+ 					goto free_bios;
+ 				}
+ 				bio->bi_end_io = scsiback_bi_endio;
++				if (bio_last)
++					bio_last->bi_next = bio;
++				else
++					bio_first = bio;
++				bio_last = bio;
+ 			}
+ 
+ 			if (bio_add_pc_page(q, bio, page, bytes, off) !=
+@@ -403,11 +392,9 @@ static int request_map_sg(struct request
+ 			}
+ 
+ 			if (bio->bi_vcnt >= nr_vecs) {
+-				err = scsiback_merge_bio(rq, bio);
+-				if (err) {
+-					bio_endio(bio, 0);
+-					goto free_bios;
+-				}
++				bio->bi_flags &= ~(1 << BIO_SEG_VALID);
++				if (pending_req->sc_data_direction == WRITE)
++					bio->bi_rw |= (1 << BIO_RW);
+ 				bio = NULL;
+ 			}
+ 
+@@ -417,21 +404,15 @@ static int request_map_sg(struct request
+ 		}
+ 	}
+ 
+-	rq->buffer   = rq->data = NULL;
+-	rq->data_len = data_len;
+-
+-	return 0;
++	return bio_first;
+ 
+ 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, 0);
++	while ((bio = bio_first) != NULL) {
++		bio_first = bio->bi_next;
++		bio_put(bio);
+ 	}
+ 
+-	return err;
++	return ERR_PTR(err);
+ }
+ 
+ 
+@@ -439,7 +420,6 @@ void scsiback_cmd_exec(pending_req_t *pe
+ {
+ 	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;
+@@ -453,7 +433,30 @@ void scsiback_cmd_exec(pending_req_t *pe
+ 		timeout = VSCSIIF_TIMEOUT;
+ 
+ 	write = (data_dir == DMA_TO_DEVICE);
+-	rq = blk_get_request(pending_req->sdev->request_queue, write, GFP_KERNEL);
++	if (pending_req->nr_segments) {
++		struct bio *bio = request_map_sg(pending_req);
++
++		if (IS_ERR(bio)) {
++			printk(KERN_ERR "scsiback: SG Request Map Error\n");
++			return;
++		}
++
++		rq = blk_make_request(pending_req->sdev->request_queue, bio,
++				      GFP_KERNEL);
++		if (IS_ERR(rq)) {
++			printk(KERN_ERR "scsiback: Make Request Error\n");
++			return;
++		}
++
++		rq->buffer = NULL;
++	} else {
++		rq = blk_get_request(pending_req->sdev->request_queue, write,
++				     GFP_KERNEL);
++		if (unlikely(!rq)) {
++			printk(KERN_ERR "scsiback: Get Request Error\n");
++			return;
++		}
++	}
+ 
+ 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ 	rq->cmd_len = cmd_len;
+@@ -468,14 +471,6 @@ void scsiback_cmd_exec(pending_req_t *pe
+ 	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);
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/scsiback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/scsiback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -224,7 +224,7 @@ static void scsiback_do_lun_hotplug(stru
+ static void scsiback_frontend_changed(struct xenbus_device *dev,
+ 					enum xenbus_state frontend_state)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	switch (frontend_state) {
+@@ -281,7 +281,7 @@ static void scsiback_frontend_changed(st
+ 
+ static int scsiback_remove(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	if (be->info) {
+ 		scsiback_disconnect(be->info);
+@@ -291,7 +291,7 @@ static int scsiback_remove(struct xenbus
+ 	}
+ 
+ 	kfree(be);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 
+ 	return 0;
+ }
+@@ -314,7 +314,7 @@ static int scsiback_probe(struct xenbus_
+ 		return -ENOMEM;
+ 	}
+ 	be->dev = dev;
+-	dev->dev.driver_data = be;
++	dev_set_drvdata(&dev->dev, be);
+ 
+ 	be->info = vscsibk_info_alloc(dev->otherend_id);
+ 	if (IS_ERR(be->info)) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/scsifront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/scsifront/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -185,7 +185,7 @@ static int scsifront_probe(struct xenbus
+ 	info->host = host;
+ 
+ 
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 	info->dev  = dev;
+ 
+ 	for (i = 0; i < VSCSIIF_MAX_REQS; i++) {
+@@ -238,7 +238,7 @@ free_sring:
+ 
+ static int scsifront_remove(struct xenbus_device *dev)
+ {
+-	struct vscsifrnt_info *info = dev->dev.driver_data;
++	struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("%s: %s removed\n",__FUNCTION__ ,dev->nodename);
+ 
+@@ -350,7 +350,7 @@ static void scsifront_do_lun_hotplug(str
+ static void scsifront_backend_changed(struct xenbus_device *dev,
+ 				enum xenbus_state backend_state)
+ {
+-	struct vscsifrnt_info *info = dev->dev.driver_data;
++	struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	DPRINTK("%p %u %u\n", dev, dev->state, backend_state);
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/sfc_netback/accel_xenbus.c	2010-01-04 12:23:14.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/sfc_netback/accel_xenbus.c	2010-01-04 12:42:06.000000000 +0100
+@@ -36,7 +36,7 @@
+ #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
++	((struct backend_info *)dev_get_drvdata(&(_dev)->dev))->netback_accel_priv
+ 
+ /* List of all the bends currently in existence. */
+ struct netback_accel *bend_list = NULL;
+@@ -615,7 +615,7 @@ int netback_accel_probe(struct xenbus_de
+ 	mutex_lock(&bend->bend_mutex);
+ 
+ 	/* ...and store it where we can get at it */
+-	binfo = (struct backend_info *) dev->dev.driver_data;
++	binfo = dev_get_drvdata(&dev->dev);
+ 	binfo->netback_accel_priv = bend;
+ 	/* And vice-versa */
+ 	bend->hdev_data = dev;
+@@ -729,7 +729,7 @@ int netback_accel_remove(struct xenbus_d
+ 	struct netback_accel *bend; 
+ 	int frontend_state;
+ 
+-	binfo = (struct backend_info *) dev->dev.driver_data;
++	binfo = dev_get_drvdata(&dev->dev);
+ 	bend = (struct netback_accel *) binfo->netback_accel_priv;
+ 
+ 	DPRINTK("%s: dev %p bend %p\n", __FUNCTION__, dev, bend);
+--- sle11sp1-2010-01-20.orig/drivers/xen/sfc_netfront/accel_xenbus.c	2009-11-06 10:49:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/sfc_netfront/accel_xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -727,8 +727,7 @@ int netfront_accel_probe(struct net_devi
+ 
+ int netfront_accel_remove(struct xenbus_device *dev)
+ {
+-	struct netfront_info *np =
+-		(struct netfront_info *)dev->dev.driver_data;
++	struct netfront_info *np = dev_get_drvdata(&dev->dev);
+ 	netfront_accel_vnic *vnic = (netfront_accel_vnic *)np->accel_priv;
+ 
+ 	DPRINTK("%s %s\n", __FUNCTION__, dev->nodename);
+--- sle11sp1-2010-01-20.orig/drivers/xen/sys-hypervisor.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/sys-hypervisor.c	2009-11-06 10:52:09.000000000 +0100
+@@ -18,6 +18,8 @@
+ #include <xen/interface/xen.h>
+ #include <xen/interface/version.h>
+ 
++#include "xenbus/xenbus_comms.h"
++
+ #define HYPERVISOR_ATTR_RO(_name) \
+ static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
+ 
+@@ -116,9 +118,8 @@ static ssize_t uuid_show(struct hyp_sysf
+ {
+ 	char *vm, *val;
+ 	int ret;
+-	extern int xenstored_ready;
+ 
+-	if (!xenstored_ready)
++	if (!is_xenstored_ready())
+ 		return -EBUSY;
+ 
+ 	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
+--- sle11sp1-2010-01-20.orig/drivers/xen/tpmback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/tpmback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -54,7 +54,7 @@ long int tpmback_get_instance(struct bac
+ 
+ static int tpmback_remove(struct xenbus_device *dev)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 
+ 	if (!be) return 0;
+ 
+@@ -70,7 +70,7 @@ static int tpmback_remove(struct xenbus_
+ 		be->tpmif = NULL;
+ 	}
+ 	kfree(be);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return 0;
+ }
+ 
+@@ -89,7 +89,7 @@ static int tpmback_probe(struct xenbus_d
+ 
+ 	be->is_instance_set = 0;
+ 	be->dev = dev;
+-	dev->dev.driver_data = be;
++	dev_set_drvdata(&dev->dev, be);
+ 
+ 	err = xenbus_watch_path2(dev, dev->nodename,
+ 				 "instance", &be->backend_watch,
+@@ -139,7 +139,7 @@ static void backend_changed(struct xenbu
+ static void frontend_changed(struct xenbus_device *dev,
+ 			     enum xenbus_state frontend_state)
+ {
+-	struct backend_info *be = dev->dev.driver_data;
++	struct backend_info *be = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	switch (frontend_state) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/usbback/usbback.h	2009-11-06 10:45:48.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/usbback/usbback.h	2009-11-06 10:52:09.000000000 +0100
+@@ -64,6 +64,12 @@
+ 
+ struct usbstub;
+ 
++#ifndef BUS_ID_SIZE
++#define USBBACK_BUS_ID_SIZE 20
++#else
++#define USBBACK_BUS_ID_SIZE BUS_ID_SIZE
++#endif
++
+ #define USB_DEV_ADDR_SIZE 128
+ 
+ typedef struct usbif_st {
+@@ -111,7 +117,7 @@ typedef struct usbif_st {
+ struct vusb_port_id {
+ 	struct list_head id_list;
+ 
+-	char phys_bus[BUS_ID_SIZE];
++	char phys_bus[USBBACK_BUS_ID_SIZE];
+ 	domid_t domid;
+ 	unsigned int handle;
+ 	int portnum;
+--- sle11sp1-2010-01-20.orig/drivers/xen/usbback/usbstub.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/usbback/usbstub.c	2009-11-06 10:52:09.000000000 +0100
+@@ -56,7 +56,7 @@ struct vusb_port_id *find_portid_by_busi
+ 
+ 	spin_lock_irqsave(&port_list_lock, flags);
+ 	list_for_each_entry(portid, &port_list, id_list) {
+-		if (!(strncmp(portid->phys_bus, busid, BUS_ID_SIZE))) {
++		if (!(strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))) {
+ 			found = 1;
+ 			break;
+ 		}
+@@ -110,7 +110,7 @@ int portid_add(const char *busid,
+ 	portid->handle = handle;
+ 	portid->portnum = portnum;
+ 
+-	strncpy(portid->phys_bus, busid, BUS_ID_SIZE);
++	strncpy(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE);
+ 
+ 	spin_lock_irqsave(&port_list_lock, flags);
+ 	list_add(&portid->id_list, &port_list);
+@@ -228,7 +228,7 @@ static int usbstub_probe(struct usb_inte
+ 		usbbk_hotplug_notify(usbif, portid->portnum, udev->speed);
+ 	} else {
+ 		/* maybe already called and connected by other intf */
+-		if (strncmp(stub->portid->phys_bus, busid, BUS_ID_SIZE))
++		if (strncmp(stub->portid->phys_bus, busid, USBBACK_BUS_ID_SIZE))
+ 			goto out; /* invalid call */
+ 	}
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/usbback/xenbus.c	2009-11-06 10:49:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/usbback/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -112,7 +112,7 @@ again:
+ 		 */
+ 		portid = find_portid(usbif->domid, usbif->handle, i);
+ 		if (portid) {
+-			if ((strncmp(portid->phys_bus, busid, BUS_ID_SIZE)))
++			if ((strncmp(portid->phys_bus, busid, USBBACK_BUS_ID_SIZE)))
+ 				xenbus_dev_fatal(dev, err,
+ 					"can't add port/%d, remove first", i);
+ 			else
+@@ -142,7 +142,7 @@ abort:
+ 
+ static int usbback_remove(struct xenbus_device *dev)
+ {
+-	usbif_t *usbif = dev->dev.driver_data;
++	usbif_t *usbif = dev_get_drvdata(&dev->dev);
+ 	int i;
+ 
+ 	if (usbif->backend_watch.node) {
+@@ -158,7 +158,7 @@ static int usbback_remove(struct xenbus_
+ 		usbif_disconnect(usbif);
+ 		usbif_free(usbif);;
+ 	}
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 
+ 	return 0;
+ }
+@@ -182,7 +182,7 @@ static int usbback_probe(struct xenbus_d
+ 		return -ENOMEM;
+ 	}
+ 	usbif->xbdev = dev;
+-	dev->dev.driver_data = usbif;
++	dev_set_drvdata(&dev->dev, usbif);
+ 
+ 	err = xenbus_scanf(XBT_NIL, dev->nodename,
+ 				"num-ports", "%d", &num_ports);
+@@ -259,7 +259,7 @@ static int connect_rings(usbif_t *usbif)
+ static void frontend_changed(struct xenbus_device *dev,
+ 				     enum xenbus_state frontend_state)
+ {
+-	usbif_t *usbif = dev->dev.driver_data;
++	usbif_t *usbif = dev_get_drvdata(&dev->dev);
+ 	int err;
+ 
+ 	switch (frontend_state) {
+--- sle11sp1-2010-01-20.orig/drivers/xen/usbfront/xenbus.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/usbfront/xenbus.c	2009-11-06 10:52:09.000000000 +0100
+@@ -187,7 +187,7 @@ out:
+ 
+ static int connect(struct xenbus_device *dev)
+ {
+-	struct usbfront_info *info = dev->dev.driver_data;
++	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+ 
+ 	usbif_conn_request_t *req;
+ 	int i, idx, err;
+@@ -288,7 +288,7 @@ static int usbfront_probe(struct xenbus_
+ 	}
+ 
+ 	info = hcd_to_info(hcd);
+-	dev->dev.driver_data = info;
++	dev_set_drvdata(&dev->dev, info);
+ 
+ 	err = usb_add_hcd(hcd, 0, 0);
+ 	if (err != 0) {
+@@ -310,13 +310,13 @@ static int usbfront_probe(struct xenbus_
+ 
+ fail:
+ 	usb_put_hcd(hcd);
+-	dev->dev.driver_data = NULL;
++	dev_set_drvdata(&dev->dev, NULL);
+ 	return err;
+ }
+ 
+ static void usbfront_disconnect(struct xenbus_device *dev)
+ {
+-	struct usbfront_info *info = dev->dev.driver_data;
++	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+ 	struct usb_hcd *hcd = info_to_hcd(info);
+ 
+ 	usb_remove_hcd(hcd);
+@@ -360,7 +360,7 @@ static void backend_changed(struct xenbu
+ 
+ static int usbfront_remove(struct xenbus_device *dev)
+ {
+-	struct usbfront_info *info = dev->dev.driver_data;
++	struct usbfront_info *info = dev_get_drvdata(&dev->dev);
+ 	struct usb_hcd *hcd = info_to_hcd(info);
+ 
+ 	destroy_rings(info);
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:30:36.000000000 +0100
+@@ -91,6 +91,11 @@ static int xenbus_probe_frontend(const c
+ 
+ static void xenbus_dev_shutdown(struct device *_dev);
+ 
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++static int xenbus_dev_suspend(struct device *dev, pm_message_t state);
++static int xenbus_dev_resume(struct device *dev);
++#endif
++
+ /* If something in array of ids matches this device, return it. */
+ static const struct xenbus_device_id *
+ match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
+@@ -227,6 +232,10 @@ static struct xen_bus_type xenbus_fronte
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+ 		.dev_attrs = xenbus_dev_attrs,
+ #endif
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++		.suspend   = xenbus_dev_suspend,
++		.resume    = xenbus_dev_resume,
++#endif
+ 	},
+ #if defined(CONFIG_XEN) || defined(MODULE)
+ 	.dev = {
+@@ -763,6 +772,9 @@ void xenbus_dev_changed(const char *node
+ 
+ 	kfree(root);
+ }
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++EXPORT_SYMBOL_GPL(xenbus_dev_changed);
++#endif
+ 
+ static void frontend_changed(struct xenbus_watch *watch,
+ 			     const char **vec, unsigned int len)
+@@ -778,7 +790,11 @@ static struct xenbus_watch fe_watch = {
+ 	.callback = frontend_changed,
+ };
+ 
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
++#else
+ static int suspend_dev(struct device *dev, void *data)
++#endif
+ {
+ 	int err = 0;
+ 	struct xenbus_driver *drv;
+@@ -791,13 +807,18 @@ static int suspend_dev(struct device *de
+ 	drv = to_xenbus_driver(dev->driver);
+ 	xdev = container_of(dev, struct xenbus_device, dev);
+ 	if (drv->suspend)
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++		err = drv->suspend(xdev, state);
++#else
+ 		err = drv->suspend(xdev);
++#endif
+ 	if (err)
+ 		printk(KERN_WARNING
+ 		       "xenbus: suspend %s failed: %i\n", dev_name(dev), err);
+ 	return 0;
+ }
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ static int suspend_cancel_dev(struct device *dev, void *data)
+ {
+ 	int err = 0;
+@@ -818,8 +839,13 @@ static int suspend_cancel_dev(struct dev
+ 		       dev_name(dev), err);
+ 	return 0;
+ }
++#endif
+ 
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++static int xenbus_dev_resume(struct device *dev)
++#else
+ static int resume_dev(struct device *dev, void *data)
++#endif
+ {
+ 	int err;
+ 	struct xenbus_driver *drv;
+@@ -864,6 +890,7 @@ static int resume_dev(struct device *dev
+ 	return 0;
+ }
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ void xenbus_suspend(void)
+ {
+ 	DPRINTK("");
+@@ -893,6 +920,7 @@ void xenbus_suspend_cancel(void)
+ 	xenbus_backend_resume(suspend_cancel_dev);
+ }
+ EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
++#endif
+ 
+ /* A flag to determine if xenstored is 'ready' (i.e. has started) */
+ atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED);
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:52:02.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:52:09.000000000 +0100
+@@ -73,7 +73,7 @@ static int read_frontend_details(struct 
+ }
+ 
+ /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
+-static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
++static int backend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
+ {
+ 	int domid, err;
+ 	const char *devid, *type, *frontend;
+@@ -103,8 +103,8 @@ static int backend_bus_id(char bus_id[BU
+ 	if (err)
+ 		return err;
+ 
+-	if (snprintf(bus_id, BUS_ID_SIZE,
+-		     "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
++	if (snprintf(bus_id, XEN_BUS_ID_SIZE, "%.*s-%i-%s",
++		     typelen, type, domid, devid) >= XEN_BUS_ID_SIZE)
+ 		return -ENOSPC;
+ 	return 0;
+ }
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_xs.c	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_xs.c	2009-11-06 10:52:09.000000000 +0100
+@@ -723,6 +723,10 @@ void xs_resume(void)
+ 	struct xenbus_watch *watch;
+ 	char token[sizeof(watch) * 2 + 1];
+ 
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++	xb_init_comms();
++#endif
++
+ 	mutex_unlock(&xs_state.response_mutex);
+ 	mutex_unlock(&xs_state.request_mutex);
+ 	transaction_resume();
+--- sle11sp1-2010-01-20.orig/include/Kbuild	2009-12-18 10:50:15.000000000 +0100
++++ sle11sp1-2010-01-20/include/Kbuild	2009-12-18 10:51:55.000000000 +0100
+@@ -8,6 +8,5 @@ header-y += mtd/
+ header-y += rdma/
+ header-y += video/
+ header-y += drm/
+-header-y += xen/public/
+ header-y += xen/
+ header-y += scsi/
+--- sle11sp1-2010-01-20.orig/include/xen/Kbuild	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/include/xen/Kbuild	2009-12-18 10:10:56.000000000 +0100
+@@ -1 +1 @@
+-header-y += evtchn.h
++header-y += public/
+--- sle11sp1-2010-01-20.orig/include/xen/xenbus.h	2009-11-06 10:51:55.000000000 +0100
++++ sle11sp1-2010-01-20/include/xen/xenbus.h	2009-11-06 10:52:09.000000000 +0100
+@@ -104,8 +104,12 @@ struct xenbus_driver {
+ 	void (*otherend_changed)(struct xenbus_device *dev,
+ 				 enum xenbus_state backend_state);
+ 	int (*remove)(struct xenbus_device *dev);
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++	int (*suspend)(struct xenbus_device *dev, pm_message_t state);
++#else
+ 	int (*suspend)(struct xenbus_device *dev);
+ 	int (*suspend_cancel)(struct xenbus_device *dev);
++#endif
+ 	int (*resume)(struct xenbus_device *dev);
+ 	int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
+ 	struct device_driver driver;
+--- sle11sp1-2010-01-20.orig/lib/swiotlb-xen.c	2009-12-14 17:28:34.000000000 +0100
++++ sle11sp1-2010-01-20/lib/swiotlb-xen.c	2009-12-14 17:30:30.000000000 +0100
+@@ -39,8 +39,8 @@ int swiotlb;
+ int swiotlb_force;
+ 
+ /*
+- * Used to do a quick range check in swiotlb_unmap_single and
+- * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
++ * Used to do a quick range check in unmap_single and
++ * sync_single_*, to see if the memory was in fact allocated by this
+  * API.
+  */
+ static char *io_tlb_start, *io_tlb_end;
+@@ -159,7 +159,7 @@ dma_addr_t swiotlb_phys_to_bus(struct de
+ 	return phys_to_machine(paddr);
+ }
+ 
+-phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr)
++phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
+ {
+ 	return machine_to_phys(baddr);
+ }
+@@ -170,9 +170,15 @@ static dma_addr_t swiotlb_virt_to_bus(st
+ 	return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
+ }
+ 
+-static void *swiotlb_bus_to_virt(dma_addr_t address)
++void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
+ {
+-	return phys_to_virt(swiotlb_bus_to_phys(address));
++	return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
++}
++
++int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
++					       dma_addr_t addr, size_t size)
++{
++	return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+ }
+ 
+ int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
+@@ -307,7 +313,7 @@ static void swiotlb_bounce(phys_addr_t p
+ 		unsigned long flags;
+ 
+ 		while (size) {
+-			sz = min((size_t)(PAGE_SIZE - offset), size);
++			sz = min_t(size_t, PAGE_SIZE - offset, size);
+ 
+ 			local_irq_save(flags);
+ 			buffer = kmap_atomic(pfn_to_page(pfn),
+@@ -441,7 +447,7 @@ found:
+  * dma_addr is the kernel virtual address of the bounce buffer to unmap.
+  */
+ static void
+-unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
++do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+ {
+ 	unsigned long flags;
+ 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+@@ -521,7 +527,7 @@ swiotlb_full(struct device *dev, size_t 
+  * PCI address to use is returned.
+  *
+  * Once the device is given the dma address, the device owns this memory until
+- * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
++ * either swiotlb_unmap_page or swiotlb_dma_sync_single is performed.
+  */
+ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
+ 			    unsigned long offset, size_t size,
+@@ -535,7 +541,7 @@ dma_addr_t swiotlb_map_page(struct devic
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	/*
+-	 * If the pointer passed in happens to be in the device's DMA window,
++	 * If the address happens to be in the device's DMA window,
+ 	 * we can safely return the device addr and not worry about bounce
+ 	 * buffering it.
+ 	 */
+@@ -560,23 +566,32 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
+ 
+ /*
+  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
+- * match what was provided for in a previous swiotlb_map_single call.  All
++ * match what was provided for in a previous swiotlb_map_page call.  All
+  * other usages are undefined.
+  *
+  * After this call, reads by the cpu to the buffer are guaranteed to see
+  * whatever the device wrote there.
+  */
++static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
++			 size_t size, int dir)
++{
++	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
++
++	BUG_ON(dir == DMA_NONE);
++
++	if (is_swiotlb_buffer(dev_addr)) {
++		do_unmap_single(hwdev, dma_addr, size, dir);
++		return;
++	}
++
++	gnttab_dma_unmap_page(dev_addr);
++}
++
+ void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
+ 			size_t size, enum dma_data_direction dir,
+ 			struct dma_attrs *attrs)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+-
+-	BUG_ON(dir == DMA_NONE);
+-	if (is_swiotlb_buffer(dev_addr))
+-		unmap_single(hwdev, dma_addr, size, dir);
+-	else
+-		gnttab_dma_unmap_page(dev_addr);
++	unmap_single(hwdev, dev_addr, size, dir);
+ }
+ EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
+ 
+@@ -584,7 +599,7 @@ EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
+  * Make physical memory consistent for a single streaming mode DMA translation
+  * after a transfer.
+  *
+- * If you perform a swiotlb_map_single() but wish to interrogate the buffer
++ * If you perform a swiotlb_map_page() but wish to interrogate the buffer
+  * using the cpu, yet do not wish to teardown the PCI dma mapping, you must
+  * call this function before doing so.  At the next point you give the PCI dma
+  * address back to the card, you must first perform a
+@@ -594,9 +609,10 @@ void
+ swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 			    size_t size, enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
++
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr, size, dir);
+ }
+@@ -606,9 +622,10 @@ void
+ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 			       size_t size, enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
++
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr, size, dir);
+ }
+@@ -619,11 +636,7 @@ swiotlb_sync_single_range_for_cpu(struct
+ 				  unsigned long offset, size_t size,
+ 				  enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+-
+-	BUG_ON(dir == DMA_NONE);
+-	if (is_swiotlb_buffer(dev_addr))
+-		sync_single(hwdev, dma_addr + offset, size, dir);
++	swiotlb_sync_single_for_cpu(hwdev, dev_addr + offset, size, dir);
+ }
+ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_cpu);
+ 
+@@ -632,17 +645,13 @@ swiotlb_sync_single_range_for_device(str
+ 				     unsigned long offset, size_t size,
+ 				     enum dma_data_direction dir)
+ {
+-	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+-
+-	BUG_ON(dir == DMA_NONE);
+-	if (is_swiotlb_buffer(dev_addr))
+-		sync_single(hwdev, dma_addr + offset, size, dir);
++	swiotlb_sync_single_for_device(hwdev, dev_addr + offset, size, dir);
+ }
+ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
+ 
+ /*
+  * Map a set of buffers described by scatterlist in streaming mode for DMA.
+- * This is the scatter-gather version of the above swiotlb_map_single
++ * This is the scatter-gather version of the above swiotlb_map_page
+  * interface.  Here the scatter gather list elements are each tagged with the
+  * appropriate dma address and length.  They are obtained via
+  * sg_dma_{address,length}(SG).
+@@ -653,7 +662,7 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_ra
+  *       The routine returns the number of addr/length pairs actually
+  *       used, at most nents.
+  *
+- * Device ownership issues as mentioned above for swiotlb_map_single are the
++ * Device ownership issues as mentioned above for swiotlb_map_page are the
+  * same here.
+  */
+ int
+@@ -706,7 +715,7 @@ EXPORT_SYMBOL(swiotlb_map_sg);
+ 
+ /*
+  * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
+- * concerning calls here are the same as for swiotlb_unmap_single() above.
++ * concerning calls here are the same as for swiotlb_unmap_page() above.
+  */
+ void
+ swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
+@@ -717,13 +726,9 @@ swiotlb_unmap_sg_attrs(struct device *hw
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+-	for_each_sg(sgl, sg, nelems, i) {
+-		if (sg->dma_address != sg_phys(sg))
+-			unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+-				     sg->dma_length, dir);
+-		else
+-			gnttab_dma_unmap_page(sg->dma_address);
+-	}
++	for_each_sg(sgl, sg, nelems, i)
++		unmap_single(hwdev, sg->dma_address, sg->dma_length, dir);
++
+ }
+ EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
+ 
+@@ -749,13 +754,9 @@ swiotlb_sync_sg_for_cpu(struct device *h
+ 	struct scatterlist *sg;
+ 	int i;
+ 
+-	BUG_ON(dir == DMA_NONE);
+-
+-	for_each_sg(sgl, sg, nelems, i) {
+-		if (sg->dma_address != sg_phys(sg))
+-			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+-				    sg->dma_length, dir);
+-	}
++	for_each_sg(sgl, sg, nelems, i)
++		swiotlb_sync_single_for_cpu(hwdev, sg->dma_address,
++					    sg->dma_length, dir);
+ }
+ EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
+ 
+@@ -766,13 +767,9 @@ swiotlb_sync_sg_for_device(struct device
+ 	struct scatterlist *sg;
+ 	int i;
+ 
+-	BUG_ON(dir == DMA_NONE);
+-
+-	for_each_sg(sgl, sg, nelems, i) {
+-		if (sg->dma_address != sg_phys(sg))
+-			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+-				    sg->dma_length, dir);
+-	}
++	for_each_sg(sgl, sg, nelems, i)
++		swiotlb_sync_single_for_device(hwdev, sg->dma_address,
++					       sg->dma_length, dir);
+ }
+ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
+ 
+--- sle11sp1-2010-01-20.orig/mm/init-mm.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/mm/init-mm.c	2009-11-06 10:52:09.000000000 +0100
+@@ -8,6 +8,10 @@
+ #include <asm/atomic.h>
+ #include <asm/pgtable.h>
+ 
++#ifdef CONFIG_X86_XEN
++#define swapper_pg_dir ((pgd_t *)NULL)
++#endif
++
+ struct mm_struct init_mm = {
+ 	.mm_rb		= RB_ROOT,
+ 	.pgd		= swapper_pg_dir,
+--- sle11sp1-2010-01-20.orig/mm/memory.c	2009-12-16 11:50:45.000000000 +0100
++++ sle11sp1-2010-01-20/mm/memory.c	2009-12-04 11:30:17.000000000 +0100
+@@ -1332,7 +1332,7 @@ int __get_user_pages(struct task_struct 
+ 					vmas[i] = vma;
+ 				i++;
+ 				start += PAGE_SIZE;
+-				len--;
++				nr_pages--;
+ 				continue;
+ 			}
+ 		}
+--- sle11sp1-2010-01-20.orig/mm/page_alloc.c	2009-12-04 11:30:00.000000000 +0100
++++ sle11sp1-2010-01-20/mm/page_alloc.c	2009-12-04 11:30:15.000000000 +0100
+@@ -594,6 +594,7 @@ static void __free_pages_ok(struct page 
+ 
+ #ifdef CONFIG_XEN
+ 	if (PageForeign(page)) {
++		WARN_ON(wasMlocked);
+ 		PageForeignDestructor(page, order);
+ 		return;
+ 	}
+@@ -1102,6 +1103,7 @@ static void free_hot_cold_page(struct pa
+ 
+ #ifdef CONFIG_XEN
+ 	if (PageForeign(page)) {
++		WARN_ON(wasMlocked);
+ 		PageForeignDestructor(page, 0);
+ 		return;
+ 	}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86_64-pgd-pin
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86_64-pgd-pin
@@ -0,0 +1,111 @@
+From: jbeulich@novell.com
+Subject: make pinning of pgd pairs transparent to callers
+Patch-mainline: obsolete
+
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:53:45.000000000 +0100
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:55:40.000000000 +0100
+@@ -114,8 +114,8 @@ void xen_l1_entry_update(pte_t *ptr, pte
+ void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
+ void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
+ void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */
+-void xen_pgd_pin(unsigned long ptr);
+-void xen_pgd_unpin(unsigned long ptr);
++void xen_pgd_pin(pgd_t *);
++void xen_pgd_unpin(pgd_t *);
+ 
+ void xen_init_pgd_pin(void);
+ 
+--- head-2010-01-04.orig/arch/x86/mm/hypervisor.c	2010-01-05 16:47:18.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/hypervisor.c	2010-01-05 16:47:51.000000000 +0100
+@@ -624,26 +624,38 @@ EXPORT_SYMBOL_GPL(xen_invlpg_mask);
+ 
+ #endif /* CONFIG_SMP */
+ 
+-void xen_pgd_pin(unsigned long ptr)
+-{
+-	struct mmuext_op op;
+ #ifdef CONFIG_X86_64
+-	op.cmd = MMUEXT_PIN_L4_TABLE;
+-#elif defined(CONFIG_X86_PAE)
+-	op.cmd = MMUEXT_PIN_L3_TABLE;
++#define NR_PGD_PIN_OPS 2
+ #else
+-	op.cmd = MMUEXT_PIN_L2_TABLE;
++#define NR_PGD_PIN_OPS 1
+ #endif
+-	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
+-	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++
++void xen_pgd_pin(pgd_t *pgd)
++{
++	struct mmuext_op op[NR_PGD_PIN_OPS];
++
++	op[0].cmd = MMUEXT_PIN_L3_TABLE;
++	op[0].arg1.mfn = virt_to_mfn(pgd);
++#ifdef CONFIG_X86_64
++	op[1].cmd = op[0].cmd = MMUEXT_PIN_L4_TABLE;
++	op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd));
++#endif
++	if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0)
++		BUG();
+ }
+ 
+-void xen_pgd_unpin(unsigned long ptr)
++void xen_pgd_unpin(pgd_t *pgd)
+ {
+-	struct mmuext_op op;
+-	op.cmd = MMUEXT_UNPIN_TABLE;
+-	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
+-	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++	struct mmuext_op op[NR_PGD_PIN_OPS];
++
++	op[0].cmd = MMUEXT_UNPIN_TABLE;
++	op[0].arg1.mfn = virt_to_mfn(pgd);
++#ifdef CONFIG_X86_64
++	op[1].cmd = MMUEXT_UNPIN_TABLE;
++	op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd));
++#endif
++	if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0)
++		BUG();
+ }
+ 
+ void xen_set_ldt(const void *ptr, unsigned int ents)
+--- head-2010-01-04.orig/arch/x86/mm/init_64-xen.c	2009-11-06 11:12:01.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/init_64-xen.c	2009-10-13 17:25:37.000000000 +0200
+@@ -747,10 +747,8 @@ void __init xen_init_pt(void)
+ 	early_make_page_readonly(level1_fixmap_pgt,
+ 				 XENFEAT_writable_page_tables);
+ 
+-	if (!xen_feature(XENFEAT_writable_page_tables)) {
+-		xen_pgd_pin(__pa_symbol(init_level4_pgt));
+-		xen_pgd_pin(__pa_symbol(__user_pgd(init_level4_pgt)));
+-	}
++	if (!xen_feature(XENFEAT_writable_page_tables))
++		xen_pgd_pin(init_level4_pgt);
+ }
+ 
+ void __init xen_finish_init_mapping(void)
+--- head-2010-01-04.orig/arch/x86/mm/pgtable-xen.c	2009-10-14 14:19:25.000000000 +0200
++++ head-2010-01-04/arch/x86/mm/pgtable-xen.c	2009-10-14 14:20:47.000000000 +0200
+@@ -346,19 +346,13 @@ static void __pgd_pin(pgd_t *pgd)
+ {
+ 	pgd_walk(pgd, PAGE_KERNEL_RO);
+ 	kmap_flush_unused();
+-	xen_pgd_pin(__pa(pgd)); /* kernel */
+-#ifdef CONFIG_X86_64
+-	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
+-#endif
++	xen_pgd_pin(pgd);
+ 	SetPagePinned(virt_to_page(pgd));
+ }
+ 
+ static void __pgd_unpin(pgd_t *pgd)
+ {
+-	xen_pgd_unpin(__pa(pgd));
+-#ifdef CONFIG_X86_64
+-	xen_pgd_unpin(__pa(__user_pgd(pgd)));
+-#endif
++	xen_pgd_unpin(pgd);
+ 	pgd_walk(pgd, PAGE_KERNEL);
+ 	ClearPagePinned(virt_to_page(pgd));
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-xen-kconfig.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-xen-kconfig.diff
@@ -0,0 +1,854 @@
+Subject: xen3 xen-kconfig
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -63,6 +63,7 @@ config ARCH_DEFCONFIG
+ 
+ config GENERIC_TIME
+ 	def_bool y
++	depends on !X86_XEN
+ 
+ config GENERIC_CMOS_UPDATE
+ 	def_bool y
+@@ -213,12 +214,23 @@ config X86_64_SMP
+ 
+ config X86_HT
+ 	bool
+-	depends on SMP
++	depends on SMP && !XEN
+ 	default y
+ 
+ config X86_TRAMPOLINE
+ 	bool
+ 	depends on SMP || (64BIT && ACPI_SLEEP)
++	depends on !XEN
++	default y
++
++config X86_NO_TSS
++	bool
++	depends on X86_XEN || X86_64_XEN
++	default y
++
++config X86_NO_IDT
++	bool
++	depends on X86_XEN || X86_64_XEN
+ 	default y
+ 
+ config X86_32_LAZY_GS
+@@ -298,6 +310,17 @@ config X86_MPPARSE
+ 	  For old smp systems that do not have proper acpi support. Newer systems
+ 	  (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+ 
++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
++	help
++	  Choose this option if you plan to run this kernel on top of the
++	  Xen Hypervisor.
++
+ config X86_BIGSMP
+ 	bool "Support for big SMP systems with more than 8 CPUs"
+ 	depends on X86_32 && SMP
+@@ -327,6 +350,13 @@ config X86_EXTENDED_PLATFORM
+ 	  generic distribution kernel, say Y here - otherwise say N.
+ endif
+ 
++config X86_64_XEN
++	bool "Enable Xen compatible kernel"
++	select XEN
++	select SWIOTLB
++	help
++	  This option will compile a kernel compatible with Xen hypervisor
++
+ if X86_64
+ config X86_EXTENDED_PLATFORM
+ 	bool "Support for extended (non-PC) x86 platforms"
+@@ -639,6 +669,7 @@ source "arch/x86/Kconfig.cpu"
+ config HPET_TIMER
+ 	def_bool X86_64
+ 	prompt "HPET Timer Support" if X86_32
++	depends on !X86_XEN && !X86_64_XEN
+ 	---help---
+ 	  Use the IA-PC HPET (High Precision Event Timer) to manage
+ 	  time in preference to the PIT and RTC, if a HPET is
+@@ -674,7 +705,7 @@ config GART_IOMMU
+ 	bool "GART IOMMU support" if EMBEDDED
+ 	default y
+ 	select SWIOTLB
+-	depends on X86_64 && PCI
++	depends on X86_64 && 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,
+@@ -689,7 +720,7 @@ config GART_IOMMU
+ config CALGARY_IOMMU
+ 	bool "IBM Calgary IOMMU support"
+ 	select SWIOTLB
+-	depends on X86_64 && PCI && EXPERIMENTAL
++	depends on X86_64 && 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
+@@ -773,6 +804,7 @@ config NR_CPUS
+ 	default "1" if !SMP
+ 	default "4096" if MAXSMP
+ 	default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
++	default "16" if X86_64_XEN
+ 	default "8" if SMP
+ 	---help---
+ 	  This allows you to specify the maximum number of CPUs which this
+@@ -804,7 +836,7 @@ source "kernel/Kconfig.preempt"
+ 
+ config X86_UP_APIC
+ 	bool "Local APIC support on uniprocessors"
+-	depends on X86_32 && !SMP && !X86_32_NON_STANDARD
++	depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !XEN_UNPRIVILEGED_GUEST
+ 	---help---
+ 	  A local APIC (Advanced Programmable Interrupt Controller) is an
+ 	  integrated interrupt controller in the CPU. If you have a single-CPU
+@@ -830,15 +862,22 @@ config X86_UP_IOAPIC
+ config X86_LOCAL_APIC
+ 	def_bool y
+ 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ config X86_IO_APIC
+ 	def_bool y
+ 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ config X86_VISWS_APIC
+ 	def_bool y
+ 	depends on X86_32 && X86_VISWS
+ 
++config X86_XEN_GENAPIC
++	bool
++	depends on X86_64_XEN
++	default y
++
+ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 	bool "Reroute for broken boot IRQs"
+ 	default n
+@@ -865,6 +904,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 
+ config X86_MCE
+ 	bool "Machine Check / overheating reporting"
++	depends on !X86_XEN && !XEN_UNPRIVILEGED_GUEST
+ 	---help---
+ 	  Machine Check support allows the processor to notify the
+ 	  kernel if it detects a problem (e.g. overheating, data corruption).
+@@ -874,7 +914,7 @@ config X86_MCE
+ config X86_MCE_INTEL
+ 	def_bool y
+ 	prompt "Intel MCE features"
+-	depends on X86_MCE && X86_LOCAL_APIC
++	depends on X86_MCE && X86_LOCAL_APIC && !XEN
+ 	---help---
+ 	   Additional support for intel specific MCE features such as
+ 	   the thermal monitor.
+@@ -882,7 +922,7 @@ config X86_MCE_INTEL
+ config X86_MCE_AMD
+ 	def_bool y
+ 	prompt "AMD MCE features"
+-	depends on X86_MCE && X86_LOCAL_APIC
++	depends on X86_MCE && X86_LOCAL_APIC && !XEN
+ 	---help---
+ 	   Additional support for AMD specific MCE features such as
+ 	   the DRAM Error Threshold.
+@@ -909,6 +949,10 @@ config X86_MCE_INJECT
+ 	  If you don't know what a machine check is and you don't do kernel
+ 	  QA it is safe to say n.
+ 
++config X86_XEN_MCE
++	def_bool y
++	depends on XEN && X86_MCE
++
+ config X86_THERMAL_VECTOR
+ 	def_bool y
+ 	depends on X86_MCE_INTEL
+@@ -961,7 +1005,7 @@ config I8K
+ 
+ config X86_REBOOTFIXUPS
+ 	bool "Enable X86 board specific fixups for reboot"
+-	depends on X86_32
++	depends on X86_32 && !X86_XEN
+ 	---help---
+ 	  This enables chipset and/or board specific fixups to be done
+ 	  in order to get reboot to work correctly. This is only needed on
+@@ -978,6 +1022,7 @@ config X86_REBOOTFIXUPS
+ 
+ config MICROCODE
+ 	tristate "/dev/cpu/microcode - microcode support"
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 	select FW_LOADER
+ 	---help---
+ 	  If you say Y here, you will be able to update the microcode on
+@@ -1174,7 +1219,7 @@ config DIRECT_GBPAGES
+ # Common NUMA Features
+ config NUMA
+ 	bool "Numa Memory Allocation and Scheduler Support"
+-	depends on SMP
++	depends on SMP && !XEN
+ 	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
+ 	default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
+ 	---help---
+@@ -1283,6 +1328,7 @@ config ARCH_SPARSEMEM_DEFAULT
+ config ARCH_SPARSEMEM_ENABLE
+ 	def_bool y
+ 	depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD
++	depends on !XEN
+ 	select SPARSEMEM_STATIC if X86_32
+ 	select SPARSEMEM_VMEMMAP_ENABLE if X86_64
+ 
+@@ -1358,6 +1404,7 @@ config X86_RESERVE_LOW_64K
+ config MATH_EMULATION
+ 	bool
+ 	prompt "Math emulation" if X86_32
++	depends on !X86_XEN
+ 	---help---
+ 	  Linux can emulate a math coprocessor (used for floating point
+ 	  operations) if you don't have one. 486DX and Pentium processors have
+@@ -1383,6 +1430,7 @@ config MATH_EMULATION
+ 
+ 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
+@@ -1467,7 +1515,7 @@ config ARCH_USES_PG_UNCACHED
+ 
+ config EFI
+ 	bool "EFI runtime service support"
+-	depends on ACPI
++	depends on ACPI && !XEN
+ 	---help---
+ 	  This enables the kernel to use EFI runtime services that are
+ 	  available (such as the EFI variable services).
+@@ -1527,6 +1575,7 @@ source kernel/Kconfig.hz
+ 
+ config KEXEC
+ 	bool "kexec system call"
++	depends on !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
+@@ -1544,6 +1593,7 @@ config KEXEC
+ config CRASH_DUMP
+ 	bool "kernel crash dumps"
+ 	depends on X86_64 || (X86_32 && HIGHMEM)
++	depends on !XEN
+ 	---help---
+ 	  Generate crash dump after being started by kexec.
+ 	  This should be normally only set in special crash dump kernels
+@@ -1664,6 +1714,7 @@ config COMPAT_VDSO
+ 	def_bool y
+ 	prompt "Compat VDSO support"
+ 	depends on X86_32 || IA32_EMULATION
++	depends on !X86_XEN
+ 	---help---
+ 	  Map the 32-bit VDSO to the predictable old-style address too.
+ 	---help---
+@@ -1733,6 +1784,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
+ 	depends on NUMA
+ 
+ menu "Power management and ACPI options"
++	depends on !XEN_UNPRIVILEGED_GUEST
+ 
+ config ARCH_HIBERNATION_HEADER
+ 	def_bool y
+@@ -1751,7 +1803,7 @@ config X86_APM_BOOT
+ 
+ menuconfig APM
+ 	tristate "APM (Advanced Power Management) BIOS support"
+-	depends on X86_32 && PM_SLEEP
++	depends on X86_32 && PM_SLEEP && !XEN
+ 	---help---
+ 	  APM is a BIOS specification for saving power using several different
+ 	  techniques. This is mostly useful for battery powered laptops with
+@@ -1912,6 +1964,7 @@ choice
+ 
+ config PCI_GOBIOS
+ 	bool "BIOS"
++	depends on !X86_XEN
+ 
+ config PCI_GOMMCONFIG
+ 	bool "MMConfig"
+@@ -1923,6 +1976,13 @@ config PCI_GOOLPC
+ 	bool "OLPC"
+ 	depends on OLPC
+ 
++config PCI_GOXEN_FE
++	bool "Xen PCI Frontend"
++	depends on X86_XEN
++	help
++	  The PCI device frontend driver allows the kernel to import arbitrary
++	  PCI devices from a PCI backend to support PCI driver domains.
++
+ config PCI_GOANY
+ 	bool "Any"
+ 
+@@ -1930,7 +1990,7 @@ endchoice
+ 
+ config PCI_BIOS
+ 	def_bool y
+-	depends on X86_32 && PCI && (PCI_GOBIOS || PCI_GOANY)
++	depends on X86_32 && PCI && !XEN && (PCI_GOBIOS || PCI_GOANY)
+ 
+ # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
+ config PCI_DIRECT
+@@ -1953,6 +2013,22 @@ config PCI_MMCONFIG
+ 	bool "Support mmconfig PCI config space access"
+ 	depends on X86_64 && PCI && ACPI
+ 
++config XEN_PCIDEV_FRONTEND
++	bool "Xen PCI Frontend" if X86_64
++	depends on PCI && ((X86_XEN && (PCI_GOXEN_FE || PCI_GOANY)) || 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.
++
+ config DMAR
+ 	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
+ 	depends on PCI_MSI && ACPI && EXPERIMENTAL
+@@ -2015,6 +2091,7 @@ if X86_32
+ 
+ config ISA
+ 	bool "ISA support"
++	depends on !XEN
+ 	---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
+@@ -2042,6 +2119,7 @@ source "drivers/eisa/Kconfig"
+ 
+ config MCA
+ 	bool "MCA support"
++	depends on !XEN
+ 	---help---
+ 	  MicroChannel Architecture is found in some IBM PS/2 machines and
+ 	  laptops.  It is a bus system similar to PCI or ISA. See
+@@ -2155,4 +2233,6 @@ source "crypto/Kconfig"
+ 
+ source "arch/x86/kvm/Kconfig"
+ 
++source "drivers/xen/Kconfig"
++
+ source "lib/Kconfig"
+--- head-2010-01-18.orig/arch/x86/Kconfig.cpu	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig.cpu	2009-12-04 10:44:40.000000000 +0100
+@@ -340,7 +340,7 @@ config X86_PPRO_FENCE
+ 
+ config X86_F00F_BUG
+ 	def_bool y
+-	depends on M586MMX || M586TSC || M586 || M486 || M386
++	depends on (M586MMX || M586TSC || M586 || M486 || M386) && !X86_NO_IDT
+ 
+ config X86_WP_WORKS_OK
+ 	def_bool y
+@@ -397,6 +397,7 @@ config X86_P6_NOP
+ config X86_TSC
+ 	def_bool y
+ 	depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) && !X86_NUMAQ) || X86_64
++	depends on !XEN
+ 
+ config X86_CMPXCHG64
+ 	def_bool y
+--- head-2010-01-18.orig/arch/x86/Kconfig.debug	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig.debug	2009-12-04 10:44:40.000000000 +0100
+@@ -136,7 +136,7 @@ config 4KSTACKS
+ config DOUBLEFAULT
+ 	default y
+ 	bool "Enable doublefault exception handler" if EMBEDDED
+-	depends on X86_32
++	depends on X86_32 && !X86_NO_TSS
+ 	---help---
+ 	  This option allows trapping of rare doublefault exceptions that
+ 	  would otherwise cause a system to silently reboot. Disabling this
+--- head-2010-01-18.orig/drivers/acpi/Kconfig	2010-01-19 10:53:23.000000000 +0100
++++ head-2010-01-18/drivers/acpi/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -307,6 +307,7 @@ config ACPI_PCI_SLOT
+ config X86_PM_TIMER
+ 	bool "Power Management Timer Support" if EMBEDDED
+ 	depends on X86
++	depends on !XEN
+ 	default y
+ 	help
+ 	  The Power Management Timer is available on all ACPI-capable,
+@@ -360,4 +361,13 @@ config ACPI_SBS
+ 	  To compile this driver as a module, choose M here:
+ 	  the modules will be called sbs and sbshc.
+ 
++config ACPI_PV_SLEEP
++	bool
++	depends on X86 && XEN && ACPI_SLEEP
++	default y
++
++config PROCESSOR_EXTERNAL_CONTROL
++	bool
++	depends on (X86 || IA64) && XEN
++	default y
+ endif	# ACPI
+--- head-2010-01-18.orig/drivers/char/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/drivers/char/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -1052,7 +1052,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
+--- head-2010-01-18.orig/drivers/char/tpm/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/drivers/char/tpm/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -58,4 +58,13 @@ config TCG_INFINEON
+ 	  Further information on this driver and the supported hardware
+ 	  can be found at http://www.prosec.rub.de/tpm
+ 
++config TCG_XEN
++	tristate "XEN TPM Interface"
++	depends on XEN
++	---help---
++	  If you want to make TPM support available to a Xen user domain,
++	  say Yes and it will be accessible from within Linux.
++	  To compile this driver as a module, choose M here; the module
++	  will be called tpm_xenu.
++
+ endif # TCG_TPM
+--- head-2010-01-18.orig/drivers/cpufreq/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/drivers/cpufreq/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -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 
+--- head-2010-01-18.orig/drivers/serial/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/drivers/serial/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -9,6 +9,7 @@ menu "Serial drivers"
+ # The new 8250/16550 serial drivers
+ config SERIAL_8250
+ 	tristate "8250/16550 and compatible serial support"
++	depends on !XEN_DISABLE_SERIAL
+ 	select SERIAL_CORE
+ 	---help---
+ 	  This selects whether you want to include the driver for the standard
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -1,6 +1,354 @@
++#
++# 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)"
++	select PCI_REASSIGN if PCI
++	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_BLKDEV_TAP2
++	tristate "Block-device tap backend driver 2"
++	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_BLKBACK_PAGEMAP
++	tristate
++	depends on XEN_BLKDEV_BACKEND != n && XEN_BLKDEV_TAP2 != n
++	default XEN_BLKDEV_BACKEND || XEN_BLKDEV_TAP2
++
++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_USB_BACKEND
++	tristate "USB backend driver"
++	depends on USB && XEN_BACKEND
++	default m
++	help
++	  The USB backend driver allows the kernel to export its USB Devices
++	  to other guests.
++
++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_USB_FRONTEND
++	tristate "USB frontend driver"
++	depends on USB
++	default m
++	help
++	  The USB frontend driver allows the kernel to access USB Devices
++	  within another guest OS.
++
++config XEN_USB_FRONTEND_HCD_STATS
++	bool "Taking the HCD statistics (for debug)"
++	depends on XEN_USB_FRONTEND
++	default y
++	help
++	  Count the transferred urb status and the RING_FULL occurrence.
++
++config XEN_USB_FRONTEND_HCD_PM
++	bool "HCD suspend/resume support (DO NOT USE)"
++	depends on XEN_USB_FRONTEND
++	default n
++	help
++	  Experimental bus suspend/resume feature support.
++
++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_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_XENCOMM
++	bool
++
++config XEN_DEVMEM
++	def_bool y
++
++endif
++
+ config XEN_BALLOON
+-	bool "Xen memory balloon driver"
+-	depends on XEN
++	bool "Xen memory balloon driver" if PARAVIRT_XEN
++	depends on (XEN && !PPC_XEN) || PARAVIRT_XEN
+ 	default y
+ 	help
+ 	  The balloon driver allows the Xen domain to request more memory from
+@@ -8,14 +356,16 @@ config XEN_BALLOON
+ 	  return unneeded memory to the system.
+ 
+ config XEN_SCRUB_PAGES
+-	bool "Scrub pages before returning them to system"
+-	depends on XEN_BALLOON
++	bool "Scrub memory before freeing it to Xen"
++	depends on XEN || XEN_BALLOON
+ 	default y
+ 	help
+-	  Scrub pages before returning them to the system for reuse by
+-	  other domains.  This makes sure that any confidential data
+-	  is not accidentally visible to other domains.  Is it more
+-	  secure, but slightly less efficient.
++	  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.
+ 	  If in doubt, say yes.
+ 
+ config XEN_DEV_EVTCHN
+--- head-2010-01-18.orig/fs/Kconfig	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/fs/Kconfig	2009-12-04 10:44:40.000000000 +0100
+@@ -160,6 +160,7 @@ config HUGETLBFS
+ 	bool "HugeTLB file system support"
+ 	depends on X86 || IA64 || SPARC64 || (S390 && 64BIT) || \
+ 		   SYS_SUPPORTS_HUGETLBFS || 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
+--- head-2010-01-18.orig/kernel/Kconfig.preempt	2010-01-19 10:52:41.000000000 +0100
++++ head-2010-01-18/kernel/Kconfig.preempt	2009-12-04 10:44:40.000000000 +0100
+@@ -36,6 +36,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)
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-modular-blktap
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-modular-blktap
@@ -0,0 +1,27 @@
+From: ccoffing@novell.com
+Subject: Retain backwards-compatible module name with CONFIG_XEN_BLKDEV_TAP=m
+Patch-mainline: obsolete
+
+--- head-2009-05-29.orig/drivers/xen/blktap/Makefile	2007-06-12 13:13:44.000000000 +0200
++++ head-2009-05-29/drivers/xen/blktap/Makefile	2009-05-29 12:39:04.000000000 +0200
+@@ -1,5 +1,5 @@
+ LINUXINCLUDE += -I../xen/include/public/io
+ 
+-obj-$(CONFIG_XEN_BLKDEV_TAP) := xenblktap.o
++obj-$(CONFIG_XEN_BLKDEV_TAP) := blktap.o
+ 
+-xenblktap-y := xenbus.o interface.o blktap.o 
++blktap-y := xenbus.o interface.o blocktap.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-05-29/drivers/xen/blktap/blocktap.c	2009-05-29 12:39:04.000000000 +0200
+@@ -0,0 +1 @@
++#include "blktap.c"
+--- head-2009-05-29.orig/drivers/xen/blktap2/Makefile	2009-05-29 10:25:53.000000000 +0200
++++ head-2009-05-29/drivers/xen/blktap2/Makefile	2009-05-29 12:39:04.000000000 +0200
+@@ -1,3 +1,4 @@
+-obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap.o
++obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap2.o
+ 
+-blktap-objs := control.o ring.o wait_queue.o device.o request.o sysfs.o
++blktap2-y := control.o ring.o wait_queue.o device.o request.o
++blktap2-$(CONFIG_SYSFS) += sysfs.o
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-xen-arch.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-xen-arch.diff
@@ -0,0 +1,45308 @@
+Subject: xen3 xen-arch
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+List of files having Xen derivates (perhaps created during the merging
+of newer kernel versions), for xen-port-patches.py to pick up (i.e. this
+must be retained here until the XenSource tree has these in the right
+places):
++++ linux/arch/x86/kernel/acpi/sleep-xen.c
++++ linux/arch/x86/kernel/apic/apic-xen.c
++++ linux/arch/x86/kernel/apic/io_apic-xen.c
++++ linux/arch/x86/kernel/apic/ipi-xen.c
++++ linux/arch/x86/kernel/apic/probe_32-xen.c
++++ linux/arch/x86/kernel/apic-xen.c
++++ linux/arch/x86/kernel/cpu/common_64-xen.c
++++ linux/arch/x86/kernel/e820-xen.c
++++ linux/arch/x86/kernel/head-xen.c
++++ linux/arch/x86/kernel/head32-xen.c
++++ linux/arch/x86/kernel/ioport-xen.c
++++ linux/arch/x86/kernel/io_apic-xen.c
++++ linux/arch/x86/kernel/ipi-xen.c
++++ linux/arch/x86/kernel/irq-xen.c
++++ linux/arch/x86/kernel/ldt-xen.c
++++ linux/arch/x86/kernel/microcode_core-xen.c
++++ linux/arch/x86/kernel/mpparse-xen.c
++++ linux/arch/x86/kernel/pci-nommu-xen.c
++++ linux/arch/x86/kernel/process-xen.c
++++ linux/arch/x86/kernel/setup-xen.c
++++ linux/arch/x86/kernel/smp-xen.c
++++ linux/arch/x86/kernel/traps-xen.c
++++ linux/arch/x86/kernel/x86_init-xen.c
++++ linux/arch/x86/mm/fault-xen.c
++++ linux/arch/x86/mm/init-xen.c
++++ linux/arch/x86/mm/iomap_32-xen.c
++++ linux/arch/x86/mm/ioremap-xen.c
++++ linux/arch/x86/mm/pageattr-xen.c
++++ linux/arch/x86/mm/pat-xen.c
++++ linux/arch/x86/mm/pgtable-xen.c
++++ linux/arch/x86/vdso/vdso32-setup-xen.c
++++ linux/drivers/char/mem-xen.c
++++ linux/arch/x86/include/mach-xen/asm/desc.h
++++ linux/arch/x86/include/mach-xen/asm/dma-mapping.h
++++ linux/arch/x86/include/mach-xen/asm/fixmap.h
++++ linux/arch/x86/include/mach-xen/asm/io.h
++++ linux/arch/x86/include/mach-xen/asm/ipi.h
++++ linux/arch/x86/include/mach-xen/asm/irq_vectors.h
++++ linux/arch/x86/include/mach-xen/asm/irqflags.h
++++ linux/arch/x86/include/mach-xen/asm/mmu_context.h
++++ linux/arch/x86/include/mach-xen/asm/pci.h
++++ linux/arch/x86/include/mach-xen/asm/pgalloc.h
++++ linux/arch/x86/include/mach-xen/asm/pgtable.h
++++ linux/arch/x86/include/mach-xen/asm/pgtable-3level_types.h
++++ linux/arch/x86/include/mach-xen/asm/pgtable_64_types.h
++++ linux/arch/x86/include/mach-xen/asm/pgtable_types.h
++++ linux/arch/x86/include/mach-xen/asm/processor.h
++++ linux/arch/x86/include/mach-xen/asm/smp.h
++++ linux/arch/x86/include/mach-xen/asm/spinlock.h
++++ linux/arch/x86/include/mach-xen/asm/spinlock_types.h
++++ linux/arch/x86/include/mach-xen/asm/swiotlb.h
++++ linux/arch/x86/include/mach-xen/asm/system.h
++++ linux/arch/x86/include/mach-xen/asm/tlbflush.h
++++ linux/arch/x86/include/mach-xen/asm/xor.h
+
+List of files folded into their native counterparts (and hence removed
+from this patch for xen-port-patches.py to not needlessly pick them up;
+for reference, prefixed with the version the removal occured):
+2.6.18/arch/x86/include/mach-xen/asm/pgtable-2level.h
+2.6.18/arch/x86/include/mach-xen/asm/pgtable-2level-defs.h
+2.6.19/arch/x86/include/mach-xen/asm/ptrace.h
+2.6.23/arch/x86/include/mach-xen/asm/ptrace_64.h
+2.6.23/arch/x86/kernel/vsyscall-note_32-xen.S
+2.6.24/arch/x86/include/mach-xen/asm/arch_hooks_64.h
+2.6.24/arch/x86/include/mach-xen/asm/bootsetup_64.h
+2.6.24/arch/x86/include/mach-xen/asm/mmu_32.h
+2.6.24/arch/x86/include/mach-xen/asm/mmu_64.h
+2.6.24/arch/x86/include/mach-xen/asm/nmi_64.h
+2.6.24/arch/x86/include/mach-xen/asm/setup.h
+2.6.24/arch/x86/include/mach-xen/asm/time_64.h (added in 2.6.20)
+2.6.24/arch/x86/include/mach-xen/mach_timer.h
+2.6.24/arch/x86/kernel/early_printk_32-xen.c
+2.6.25/arch/x86/ia32/syscall32-xen.c
+2.6.25/arch/x86/ia32/syscall32_syscall-xen.S
+2.6.25/arch/x86/ia32/vsyscall-int80.S
+2.6.25/arch/x86/include/mach-xen/asm/msr.h
+2.6.25/arch/x86/include/mach-xen/asm/page_32.h
+2.6.25/arch/x86/include/mach-xen/asm/spinlock_32.h
+2.6.25/arch/x86/include/mach-xen/asm/timer.h (added in 2.6.24)
+2.6.25/arch/x86/include/mach-xen/asm/timer_64.h
+2.6.25/arch/x86/include/mach-xen/mach_time.h
+2.6.25/arch/x86/kernel/acpi/boot-xen.c
+2.6.26/arch/x86/include/mach-xen/asm/dma-mapping_32.h
+2.6.26/arch/x86/include/mach-xen/asm/dma-mapping_64.h
+2.6.26/arch/x86/include/mach-xen/asm/nmi.h (added in 2.6.24)
+2.6.26/arch/x86/include/mach-xen/asm/scatterlist.h (added in 2.6.24)
+2.6.26/arch/x86/include/mach-xen/asm/scatterlist_32.h
+2.6.26/arch/x86/include/mach-xen/asm/swiotlb_32.h
+2.6.26/arch/x86/kernel/pci-dma_32-xen.c
+2.6.26/arch/x86/kernel/pci-swiotlb_64-xen.c
+2.6.26/include/xen/xencomm.h
+2.6.27/arch/x86/include/mach-xen/asm/e820.h (added in 2.6.24)
+2.6.27/arch/x86/include/mach-xen/asm/e820_64.h
+2.6.27/arch/x86/include/mach-xen/asm/hw_irq.h (added in 2.6.24)
+2.6.27/arch/x86/include/mach-xen/asm/hw_irq_32.h
+2.6.27/arch/x86/include/mach-xen/asm/hw_irq_64.h
+2.6.27/arch/x86/include/mach-xen/asm/io_32.h
+2.6.27/arch/x86/include/mach-xen/asm/io_64.h
+2.6.27/arch/x86/include/mach-xen/asm/irq.h (added in 2.6.24)
+2.6.27/arch/x86/include/mach-xen/asm/irq_64.h
+2.6.27/arch/x86/kernel/e820_32-xen.c
+2.6.28/arch/x86/include/mach-xen/asm/pci_64.h
+2.6.28/arch/x86/include/mach-xen/asm/segment.h (added in 2.6.24)
+2.6.28/arch/x86/include/mach-xen/asm/segment_32.h
+2.6.30/arch/x86/include/mach-xen/asm/page.h (added in 2.6.24)
+2.6.30/arch/x86/include/mach-xen/asm/page_64.h
+2.6.30/arch/x86/include/mach-xen/asm/pci_32.h
+2.6.30/arch/x86/kernel/apic/apic_xen_64.c
+2.6.30/arch/x86/kernel/apic/probe_64-xen.c
+2.6.30/arch/x86/kernel/setup_percpu-xen.c (added in 2.6.27)
+2.6.31/arch/x86/kernel/init_task-xen.c
+2.6.32/arch/x86/include/mach-xen/asm/setup_arch.h
+
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/acpi/processor_extcntl_xen.c	2009-07-13 14:25:35.000000000 +0200
+@@ -0,0 +1,206 @@
++/*
++ * 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_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;
++
++	/* 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.u.power.count = count;
++	op.u.set_pminfo.u.power.flags.bm_control = pr->flags.bm_control;
++	op.u.set_pminfo.u.power.flags.bm_check = pr->flags.bm_check;
++	op.u.set_pminfo.u.power.flags.has_cst = pr->flags.has_cst;
++	op.u.set_pminfo.u.power.flags.power_setup_done = pr->flags.power_setup_done;
++
++	set_xen_guest_handle(op.u.set_pminfo.u.power.states, buf);
++	ret = HYPERVISOR_platform_op(&op);
++	kfree(buf);
++	return ret;
++}
++
++static int xen_px_notifier(struct acpi_processor *pr, int action)
++{
++	int ret = -EINVAL;
++	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;
++
++	if (!pr)
++		return -EINVAL;
++
++	perf = &op.u.set_pminfo.u.perf;
++	px = pr->performance;
++
++	switch(action) {
++	case PROCESSOR_PM_CHANGE:
++		/* ppc dynamic handle */
++		perf->flags = XEN_PX_PPC;
++		perf->platform_limit = pr->performance_platform_limit;
++
++		ret = HYPERVISOR_platform_op(&op);
++		break;
++
++	case PROCESSOR_PM_INIT:
++		/* px normal init */
++		perf->flags = XEN_PX_PPC | 
++			      XEN_PX_PCT | 
++			      XEN_PX_PSS | 
++			      XEN_PX_PSD;
++
++		/* ppc */
++		perf->platform_limit = pr->performance_platform_limit;
++
++		/* pct */
++		xen_convert_pct_reg(&perf->control_register, &px->control_register);
++		xen_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;
++		xen_convert_pss_states(states, px->states, px->state_count);
++		set_xen_guest_handle(perf->states, states);
++
++		/* psd */
++		pdomain = &px->domain_info;
++		xen_convert_psd_pack(&perf->domain_info, pdomain);
++		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 {
++			ret = -ENODEV;
++			kfree(states);
++			break;
++		}
++
++		ret = HYPERVISOR_platform_op(&op);
++		kfree(states);
++		break;
++
++	default:
++		break;
++	}
++
++	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)
++{
++	unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
++
++	if (!pmbits)
++		return;
++	if (pmbits & XEN_PROCESSOR_PM_CX)
++		xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
++	if (pmbits & XEN_PROCESSOR_PM_PX)
++		xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
++	if (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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_32-xen.c	2008-04-15 09:29:41.000000000 +0200
+@@ -0,0 +1,113 @@
++/*
++ * sleep.c - x86-specific ACPI sleep support.
++ *
++ *  Copyright (C) 2001-2003 Patrick Mochel
++ *  Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
++ */
++
++#include <linux/acpi.h>
++#include <linux/bootmem.h>
++#include <linux/dmi.h>
++#include <linux/cpumask.h>
++
++#include <asm/smp.h>
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++/* address in low memory of the wakeup routine. */
++unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_video_flags;
++extern char wakeup_start, wakeup_end;
++
++extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
++#endif
++
++/**
++ * acpi_save_state_mem - save kernel state
++ *
++ * Create an identity mapped page table and copy the wakeup routine to
++ * low memory.
++ */
++int acpi_save_state_mem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	if (!acpi_wakeup_address)
++		return 1;
++	memcpy((void *)acpi_wakeup_address, &wakeup_start,
++	       &wakeup_end - &wakeup_start);
++	acpi_copy_wakeup_routine(acpi_wakeup_address);
++#endif
++	return 0;
++}
++
++/*
++ * acpi_restore_state - undo effects of acpi_save_state_mem
++ */
++void acpi_restore_state_mem(void)
++{
++}
++
++/**
++ * acpi_reserve_bootmem - do _very_ early ACPI initialisation
++ *
++ * We allocate a page from the first 1MB of memory for the wakeup
++ * routine for when we come back from a sleep state. The
++ * runtime allocator allows specification of <16MB pages, but not
++ * <1MB pages.
++ */
++void __init acpi_reserve_bootmem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) {
++		printk(KERN_ERR
++		       "ACPI: Wakeup code way too big, S3 disabled.\n");
++		return;
++	}
++
++	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
++	if (!acpi_wakeup_address)
++		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
++#endif
++}
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++static int __init acpi_sleep_setup(char *str)
++{
++	while ((str != NULL) && (*str != '\0')) {
++		if (strncmp(str, "s3_bios", 7) == 0)
++			acpi_video_flags = 1;
++		if (strncmp(str, "s3_mode", 7) == 0)
++			acpi_video_flags |= 2;
++		str = strchr(str, ',');
++		if (str != NULL)
++			str += strspn(str, ", \t");
++	}
++	return 1;
++}
++
++__setup("acpi_sleep=", acpi_sleep_setup);
++
++static __init int reset_videomode_after_s3(struct dmi_system_id *d)
++{
++	acpi_video_flags |= 2;
++	return 0;
++}
++
++static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
++	{			/* Reset video mode after returning from ACPI S3 sleep */
++	 .callback = reset_videomode_after_s3,
++	 .ident = "Toshiba Satellite 4030cdt",
++	 .matches = {
++		     DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
++		     },
++	 },
++	{}
++};
++
++static int __init acpisleep_dmi_init(void)
++{
++	dmi_check_system(acpisleep_dmi_table);
++	return 0;
++}
++
++core_initcall(acpisleep_dmi_init);
++#endif /* CONFIG_ACPI_PV_SLEEP */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,155 @@
++/*
++ *	Local APIC handling, local APIC timers
++ *
++ *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
++ *					thanks to Eric Gilmore
++ *					and Rolf G. Tews
++ *					for testing these extensively.
++ *	Maciej W. Rozycki	:	Various updates and fixes.
++ *	Mikael Pettersson	:	Power Management for UP-APIC.
++ *	Pavel Machek and
++ *	Mikael Pettersson	:	PM converted to driver model.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/mc146818rtc.h>
++#include <linux/kernel_stat.h>
++#include <linux/sysdev.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++#include <asm/atomic.h>
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/desc.h>
++#include <asm/arch_hooks.h>
++#include <asm/hpet.h>
++#include <asm/i8253.h>
++#include <asm/nmi.h>
++
++#include <mach_apic.h>
++#include <mach_apicdef.h>
++#include <mach_ipi.h>
++
++#include "io_ports.h"
++
++#ifndef CONFIG_XEN
++/*
++ * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
++ * IPIs in place of local APIC timers
++ */
++static cpumask_t timer_bcast_ipi;
++#endif
++
++/*
++ * Knob to control our willingness to enable the local APIC.
++ */
++int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
++
++/*
++ * Debug level
++ */
++int apic_verbosity;
++
++#ifndef CONFIG_XEN
++static int modern_apic(void)
++{
++	unsigned int lvr, version;
++	/* AMD systems use old APIC versions, so check the CPU */
++	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
++		boot_cpu_data.x86 >= 0xf)
++		return 1;
++	lvr = apic_read(APIC_LVR);
++	version = GET_APIC_VERSION(lvr);
++	return version >= 0x14;
++}
++#endif /* !CONFIG_XEN */
++
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++	printk("unexpected IRQ trap at vector %02x\n", irq);
++	/*
++	 * Currently unexpected vectors happen only on SMP and APIC.
++	 * We _must_ ack these because every local APIC has only N
++	 * irq slots per priority level, and a 'hanging, unacked' IRQ
++	 * holds up an irq slot - in excessive cases (when multiple
++	 * unexpected vectors occur) that might lock up the APIC
++	 * completely.
++	 * But only ack when the APIC is enabled -AK
++	 */
++	if (cpu_has_apic)
++		ack_APIC_irq();
++}
++
++int get_physical_broadcast(void)
++{
++        return 0xff;
++}
++
++#ifndef CONFIG_XEN
++#ifndef CONFIG_SMP
++static void up_apic_timer_interrupt_call(struct pt_regs *regs)
++{
++	int cpu = smp_processor_id();
++
++	/*
++	 * the NMI deadlock-detector uses this.
++	 */
++	per_cpu(irq_stat, cpu).apic_timer_irqs++;
++
++	smp_local_timer_interrupt(regs);
++}
++#endif
++
++void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
++{
++	cpumask_t mask;
++
++	cpus_and(mask, cpu_online_map, timer_bcast_ipi);
++	if (!cpus_empty(mask)) {
++#ifdef CONFIG_SMP
++		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
++#else
++		/*
++		 * We can directly call the apic timer interrupt handler
++		 * in UP case. Minus all irq related functions
++		 */
++		up_apic_timer_interrupt_call(regs);
++#endif
++	}
++}
++#endif
++
++int setup_profiling_timer(unsigned int multiplier)
++{
++	return -EINVAL;
++}
++
++/*
++ * This initializes the IO-APIC and APIC hardware if this is
++ * a UP kernel.
++ */
++int __init APIC_init_uniprocessor (void)
++{
++#ifdef CONFIG_X86_IO_APIC
++	if (smp_found_config)
++		if (!skip_ioapic_setup && nr_ioapics)
++			setup_IO_APIC();
++#endif
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-05-19 09:16:41.000000000 +0200
+@@ -0,0 +1,745 @@
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/percpu.h>
++#include <linux/bootmem.h>
++#include <asm/semaphore.h>
++#include <asm/processor.h>
++#include <asm/i387.h>
++#include <asm/msr.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++#include <asm/mtrr.h>
++#include <asm/mce.h>
++#ifdef CONFIG_X86_LOCAL_APIC
++#include <asm/mpspec.h>
++#include <asm/apic.h>
++#include <mach_apic.h>
++#else
++#ifdef CONFIG_XEN
++#define phys_pkg_id(a,b) a
++#endif
++#endif
++#include <asm/hypervisor.h>
++
++#include "cpu.h"
++
++DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
++EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
++
++#ifndef CONFIG_XEN
++DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
++EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
++#endif
++
++static int cachesize_override __cpuinitdata = -1;
++static int disable_x86_fxsr __cpuinitdata;
++static int disable_x86_serial_nr __cpuinitdata = 1;
++static int disable_x86_sep __cpuinitdata;
++
++struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
++
++extern int disable_pse;
++
++static void default_init(struct cpuinfo_x86 * c)
++{
++	/* Not much we can do here... */
++	/* Check if at least it has cpuid */
++	if (c->cpuid_level == -1) {
++		/* No cpuid. It must be an ancient CPU */
++		if (c->x86 == 4)
++			strcpy(c->x86_model_id, "486");
++		else if (c->x86 == 3)
++			strcpy(c->x86_model_id, "386");
++	}
++}
++
++static struct cpu_dev default_cpu = {
++	.c_init	= default_init,
++	.c_vendor = "Unknown",
++};
++static struct cpu_dev * this_cpu = &default_cpu;
++
++static int __init cachesize_setup(char *str)
++{
++	get_option (&str, &cachesize_override);
++	return 1;
++}
++__setup("cachesize=", cachesize_setup);
++
++int __cpuinit get_model_name(struct cpuinfo_x86 *c)
++{
++	unsigned int *v;
++	char *p, *q;
++
++	if (cpuid_eax(0x80000000) < 0x80000004)
++		return 0;
++
++	v = (unsigned int *) c->x86_model_id;
++	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
++	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
++	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
++	c->x86_model_id[48] = 0;
++
++	/* Intel chips right-justify this string for some dumb reason;
++	   undo that brain damage */
++	p = q = &c->x86_model_id[0];
++	while ( *p == ' ' )
++	     p++;
++	if ( p != q ) {
++	     while ( *p )
++		  *q++ = *p++;
++	     while ( q <= &c->x86_model_id[48] )
++		  *q++ = '\0';	/* Zero-pad the rest */
++	}
++
++	return 1;
++}
++
++
++void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
++{
++	unsigned int n, dummy, ecx, edx, l2size;
++
++	n = cpuid_eax(0x80000000);
++
++	if (n >= 0x80000005) {
++		cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
++		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
++			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
++		c->x86_cache_size=(ecx>>24)+(edx>>24);	
++	}
++
++	if (n < 0x80000006)	/* Some chips just has a large L1. */
++		return;
++
++	ecx = cpuid_ecx(0x80000006);
++	l2size = ecx >> 16;
++	
++	/* do processor-specific cache resizing */
++	if (this_cpu->c_size_cache)
++		l2size = this_cpu->c_size_cache(c,l2size);
++
++	/* Allow user to override all this if necessary. */
++	if (cachesize_override != -1)
++		l2size = cachesize_override;
++
++	if ( l2size == 0 )
++		return;		/* Again, no L2 cache is possible */
++
++	c->x86_cache_size = l2size;
++
++	printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
++	       l2size, ecx & 0xFF);
++}
++
++/* Naming convention should be: <Name> [(<Codename>)] */
++/* This table only is used unless init_<vendor>() below doesn't set it; */
++/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
++
++/* Look up CPU names by table lookup. */
++static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
++{
++	struct cpu_model_info *info;
++
++	if ( c->x86_model >= 16 )
++		return NULL;	/* Range check */
++
++	if (!this_cpu)
++		return NULL;
++
++	info = this_cpu->c_models;
++
++	while (info && info->family) {
++		if (info->family == c->x86)
++			return info->model_names[c->x86_model];
++		info++;
++	}
++	return NULL;		/* Not found */
++}
++
++
++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
++{
++	char *v = c->x86_vendor_id;
++	int i;
++	static int printed;
++
++	for (i = 0; i < X86_VENDOR_NUM; i++) {
++		if (cpu_devs[i]) {
++			if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
++			    (cpu_devs[i]->c_ident[1] && 
++			     !strcmp(v,cpu_devs[i]->c_ident[1]))) {
++				c->x86_vendor = i;
++				if (!early)
++					this_cpu = cpu_devs[i];
++				return;
++			}
++		}
++	}
++	if (!printed) {
++		printed++;
++		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
++		printk(KERN_ERR "CPU: Your system may be unstable.\n");
++	}
++	c->x86_vendor = X86_VENDOR_UNKNOWN;
++	this_cpu = &default_cpu;
++}
++
++
++static int __init x86_fxsr_setup(char * s)
++{
++	disable_x86_fxsr = 1;
++	return 1;
++}
++__setup("nofxsr", x86_fxsr_setup);
++
++
++static int __init x86_sep_setup(char * s)
++{
++	disable_x86_sep = 1;
++	return 1;
++}
++__setup("nosep", x86_sep_setup);
++
++
++/* Standard macro to see if a specific flag is changeable */
++static inline int flag_is_changeable_p(u32 flag)
++{
++	u32 f1, f2;
++
++	asm("pushfl\n\t"
++	    "pushfl\n\t"
++	    "popl %0\n\t"
++	    "movl %0,%1\n\t"
++	    "xorl %2,%0\n\t"
++	    "pushl %0\n\t"
++	    "popfl\n\t"
++	    "pushfl\n\t"
++	    "popl %0\n\t"
++	    "popfl\n\t"
++	    : "=&r" (f1), "=&r" (f2)
++	    : "ir" (flag));
++
++	return ((f1^f2) & flag) != 0;
++}
++
++
++/* Probe for the CPUID instruction */
++static int __cpuinit have_cpuid_p(void)
++{
++	return flag_is_changeable_p(X86_EFLAGS_ID);
++}
++
++/* Do minimum CPU detection early.
++   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
++   The others are not touched to avoid unwanted side effects.
++
++   WARNING: this function is only called on the BP.  Don't add code here
++   that is supposed to run on all CPUs. */
++static void __init early_cpu_detect(void)
++{
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++
++	c->x86_cache_alignment = 32;
++
++	if (!have_cpuid_p())
++		return;
++
++	/* Get vendor name */
++	cpuid(0x00000000, &c->cpuid_level,
++	      (int *)&c->x86_vendor_id[0],
++	      (int *)&c->x86_vendor_id[8],
++	      (int *)&c->x86_vendor_id[4]);
++
++	get_cpu_vendor(c, 1);
++
++	c->x86 = 4;
++	if (c->cpuid_level >= 0x00000001) {
++		u32 junk, tfms, cap0, misc;
++		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
++		c->x86 = (tfms >> 8) & 15;
++		c->x86_model = (tfms >> 4) & 15;
++		if (c->x86 == 0xf)
++			c->x86 += (tfms >> 20) & 0xff;
++		if (c->x86 >= 0x6)
++			c->x86_model += ((tfms >> 16) & 0xF) << 4;
++		c->x86_mask = tfms & 15;
++		if (cap0 & (1<<19))
++			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
++	}
++}
++
++void __cpuinit generic_identify(struct cpuinfo_x86 * c)
++{
++	u32 tfms, xlvl;
++	int ebx;
++
++	if (have_cpuid_p()) {
++		/* Get vendor name */
++		cpuid(0x00000000, &c->cpuid_level,
++		      (int *)&c->x86_vendor_id[0],
++		      (int *)&c->x86_vendor_id[8],
++		      (int *)&c->x86_vendor_id[4]);
++		
++		get_cpu_vendor(c, 0);
++		/* Initialize the standard set of capabilities */
++		/* Note that the vendor-specific code below might override */
++	
++		/* Intel-defined flags: level 0x00000001 */
++		if ( c->cpuid_level >= 0x00000001 ) {
++			u32 capability, excap;
++			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
++			c->x86_capability[0] = capability;
++			c->x86_capability[4] = excap;
++			c->x86 = (tfms >> 8) & 15;
++			c->x86_model = (tfms >> 4) & 15;
++			if (c->x86 == 0xf)
++				c->x86 += (tfms >> 20) & 0xff;
++			if (c->x86 >= 0x6)
++				c->x86_model += ((tfms >> 16) & 0xF) << 4;
++			c->x86_mask = tfms & 15;
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_HT
++			c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
++#else
++			c->apicid = (ebx >> 24) & 0xFF;
++#endif
++#endif
++		} else {
++			/* Have CPUID level 0 only - unheard of */
++			c->x86 = 4;
++		}
++
++		/* AMD-defined flags: level 0x80000001 */
++		xlvl = cpuid_eax(0x80000000);
++		if ( (xlvl & 0xffff0000) == 0x80000000 ) {
++			if ( xlvl >= 0x80000001 ) {
++				c->x86_capability[1] = cpuid_edx(0x80000001);
++				c->x86_capability[6] = cpuid_ecx(0x80000001);
++			}
++			if ( xlvl >= 0x80000004 )
++				get_model_name(c); /* Default name */
++		}
++	}
++
++	early_intel_workaround(c);
++
++#ifdef CONFIG_X86_HT
++	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
++#endif
++}
++
++static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
++{
++	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
++		/* Disable processor serial number */
++		unsigned long lo,hi;
++		rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		lo |= 0x200000;
++		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
++		printk(KERN_NOTICE "CPU serial number disabled.\n");
++		clear_bit(X86_FEATURE_PN, c->x86_capability);
++
++		/* Disabling the serial number may affect the cpuid level */
++		c->cpuid_level = cpuid_eax(0);
++	}
++}
++
++static int __init x86_serial_nr_setup(char *s)
++{
++	disable_x86_serial_nr = 0;
++	return 1;
++}
++__setup("serialnumber", x86_serial_nr_setup);
++
++
++
++/*
++ * This does the hard work of actually picking apart the CPU stuff...
++ */
++void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++{
++	int i;
++
++	c->loops_per_jiffy = loops_per_jiffy;
++	c->x86_cache_size = -1;
++	c->x86_vendor = X86_VENDOR_UNKNOWN;
++	c->cpuid_level = -1;	/* CPUID not detected */
++	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
++	c->x86_vendor_id[0] = '\0'; /* Unset */
++	c->x86_model_id[0] = '\0';  /* Unset */
++	c->x86_max_cores = 1;
++	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++
++	if (!have_cpuid_p()) {
++		/* First of all, decide if this is a 486 or higher */
++		/* It's a 486 if we can modify the AC flag */
++		if ( flag_is_changeable_p(X86_EFLAGS_AC) )
++			c->x86 = 4;
++		else
++			c->x86 = 3;
++	}
++
++	generic_identify(c);
++
++	printk(KERN_DEBUG "CPU: After generic identify, caps:");
++	for (i = 0; i < NCAPINTS; i++)
++		printk(" %08lx", c->x86_capability[i]);
++	printk("\n");
++
++	if (this_cpu->c_identify) {
++		this_cpu->c_identify(c);
++
++		printk(KERN_DEBUG "CPU: After vendor identify, caps:");
++		for (i = 0; i < NCAPINTS; i++)
++			printk(" %08lx", c->x86_capability[i]);
++		printk("\n");
++	}
++
++	/*
++	 * Vendor-specific initialization.  In this section we
++	 * canonicalize the feature flags, meaning if there are
++	 * features a certain CPU supports which CPUID doesn't
++	 * tell us, CPUID claiming incorrect flags, or other bugs,
++	 * we handle them here.
++	 *
++	 * At the end of this section, c->x86_capability better
++	 * indicate the features this CPU genuinely supports!
++	 */
++	if (this_cpu->c_init)
++		this_cpu->c_init(c);
++
++	/* Disable the PN if appropriate */
++	squash_the_stupid_serial_number(c);
++
++	/*
++	 * The vendor-specific functions might have changed features.  Now
++	 * we do "generic changes."
++	 */
++
++	/* TSC disabled? */
++	if ( tsc_disable )
++		clear_bit(X86_FEATURE_TSC, c->x86_capability);
++
++	/* FXSR disabled? */
++	if (disable_x86_fxsr) {
++		clear_bit(X86_FEATURE_FXSR, c->x86_capability);
++		clear_bit(X86_FEATURE_XMM, c->x86_capability);
++	}
++
++	/* SEP disabled? */
++	if (disable_x86_sep)
++		clear_bit(X86_FEATURE_SEP, c->x86_capability);
++
++	if (disable_pse)
++		clear_bit(X86_FEATURE_PSE, c->x86_capability);
++
++	/* If the model name is still unset, do table lookup. */
++	if ( !c->x86_model_id[0] ) {
++		char *p;
++		p = table_lookup_model(c);
++		if ( p )
++			strcpy(c->x86_model_id, p);
++		else
++			/* Last resort... */
++			sprintf(c->x86_model_id, "%02x/%02x",
++				c->x86, c->x86_model);
++	}
++
++	/* Now the feature flags better reflect actual CPU features! */
++
++	printk(KERN_DEBUG "CPU: After all inits, caps:");
++	for (i = 0; i < NCAPINTS; i++)
++		printk(" %08lx", c->x86_capability[i]);
++	printk("\n");
++
++	/*
++	 * On SMP, boot_cpu_data holds the common feature set between
++	 * all CPUs; so make sure that we indicate which features are
++	 * common between the CPUs.  The first time this routine gets
++	 * executed, c == &boot_cpu_data.
++	 */
++	if ( c != &boot_cpu_data ) {
++		/* AND the already accumulated flags with these */
++		for ( i = 0 ; i < NCAPINTS ; i++ )
++			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
++	}
++
++	/* Init Machine Check Exception if available. */
++	mcheck_init(c);
++
++	if (c == &boot_cpu_data)
++		sysenter_setup();
++	enable_sep_cpu();
++
++	if (c == &boot_cpu_data)
++		mtrr_bp_init();
++	else
++		mtrr_ap_init();
++}
++
++#ifdef CONFIG_X86_HT
++void __cpuinit detect_ht(struct cpuinfo_x86 *c)
++{
++	u32 	eax, ebx, ecx, edx;
++	int 	index_msb, core_bits;
++
++	cpuid(1, &eax, &ebx, &ecx, &edx);
++
++	if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
++		return;
++
++	smp_num_siblings = (ebx & 0xff0000) >> 16;
++
++	if (smp_num_siblings == 1) {
++		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
++	} else if (smp_num_siblings > 1 ) {
++
++		if (smp_num_siblings > NR_CPUS) {
++			printk(KERN_WARNING "CPU: Unsupported number of the "
++					"siblings %d", smp_num_siblings);
++			smp_num_siblings = 1;
++			return;
++		}
++
++		index_msb = get_count_order(smp_num_siblings);
++		c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
++
++		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
++		       c->phys_proc_id);
++
++		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
++
++		index_msb = get_count_order(smp_num_siblings) ;
++
++		core_bits = get_count_order(c->x86_max_cores);
++
++		c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
++					       ((1 << core_bits) - 1);
++
++		if (c->x86_max_cores > 1)
++			printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
++			       c->cpu_core_id);
++	}
++}
++#endif
++
++void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
++{
++	char *vendor = NULL;
++
++	if (c->x86_vendor < X86_VENDOR_NUM)
++		vendor = this_cpu->c_vendor;
++	else if (c->cpuid_level >= 0)
++		vendor = c->x86_vendor_id;
++
++	if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
++		printk("%s ", vendor);
++
++	if (!c->x86_model_id[0])
++		printk("%d86", c->x86);
++	else
++		printk("%s", c->x86_model_id);
++
++	if (c->x86_mask || c->cpuid_level >= 0) 
++		printk(" stepping %02x\n", c->x86_mask);
++	else
++		printk("\n");
++}
++
++cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
++
++/* This is hacky. :)
++ * We're emulating future behavior.
++ * In the future, the cpu-specific init functions will be called implicitly
++ * via the magic of initcalls.
++ * They will insert themselves into the cpu_devs structure.
++ * Then, when cpu_init() is called, we can just iterate over that array.
++ */
++
++extern int intel_cpu_init(void);
++extern int cyrix_init_cpu(void);
++extern int nsc_init_cpu(void);
++extern int amd_init_cpu(void);
++extern int centaur_init_cpu(void);
++extern int transmeta_init_cpu(void);
++extern int rise_init_cpu(void);
++extern int nexgen_init_cpu(void);
++extern int umc_init_cpu(void);
++
++void __init early_cpu_init(void)
++{
++	intel_cpu_init();
++	cyrix_init_cpu();
++	nsc_init_cpu();
++	amd_init_cpu();
++	centaur_init_cpu();
++	transmeta_init_cpu();
++	rise_init_cpu();
++	nexgen_init_cpu();
++	umc_init_cpu();
++	early_cpu_detect();
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/* pse is not compatible with on-the-fly unmapping,
++	 * disable it even if the cpus claim to support it.
++	 */
++	clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
++	disable_pse = 1;
++#endif
++}
++
++static void __cpuinit cpu_gdt_init(const struct Xgt_desc_struct *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_lowmem_page_readonly(
++			(void *)va, XENFEAT_writable_descriptor_tables);
++	}
++	if (HYPERVISOR_set_gdt(frames, (gdt_descr->size + 1) / 8))
++		BUG();
++}
++
++/*
++ * 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.
++ */
++void __cpuinit cpu_init(void)
++{
++	int cpu = smp_processor_id();
++#ifndef CONFIG_X86_NO_TSS
++	struct tss_struct * t = &per_cpu(init_tss, cpu);
++#endif
++	struct thread_struct *thread = &current->thread;
++	struct desc_struct *gdt;
++	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++
++	if (cpu_test_and_set(cpu, cpu_initialized)) {
++		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
++		for (;;) local_irq_enable();
++	}
++	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
++
++	if (cpu_has_vme || cpu_has_de)
++		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
++	if (tsc_disable && cpu_has_tsc) {
++		printk(KERN_NOTICE "Disabling TSC...\n");
++		/**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
++		clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
++		set_in_cr4(X86_CR4_TSD);
++	}
++
++#ifndef CONFIG_XEN
++	/* The CPU hotplug case */
++	if (cpu_gdt_descr->address) {
++		gdt = (struct desc_struct *)cpu_gdt_descr->address;
++		memset(gdt, 0, PAGE_SIZE);
++		goto old_gdt;
++	}
++	/*
++	 * This is a horrible hack to allocate the GDT.  The problem
++	 * is that cpu_init() is called really early for the boot CPU
++	 * (and hence needs bootmem) but much later for the secondary
++	 * CPUs, when bootmem will have gone away
++	 */
++	if (NODE_DATA(0)->bdata->node_bootmem_map) {
++		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
++		/* alloc_bootmem_pages panics on failure, so no check */
++		memset(gdt, 0, PAGE_SIZE);
++	} else {
++		gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
++		if (unlikely(!gdt)) {
++			printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
++			for (;;)
++				local_irq_enable();
++		}
++	}
++old_gdt:
++	/*
++	 * Initialize the per-CPU GDT with the boot GDT,
++	 * and set up the GDT descriptor:
++	 */
++ 	memcpy(gdt, cpu_gdt_table, GDT_SIZE);
++
++	/* Set up GDT entry for 16bit stack */
++ 	*(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
++		((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
++		((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
++		(CPU_16BIT_STACK_SIZE - 1);
++
++	cpu_gdt_descr->size = GDT_SIZE - 1;
++ 	cpu_gdt_descr->address = (unsigned long)gdt;
++#else
++	if (cpu == 0 && cpu_gdt_descr->address == 0) {
++		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
++		/* alloc_bootmem_pages panics on failure, so no check */
++		memset(gdt, 0, PAGE_SIZE);
++
++		memcpy(gdt, cpu_gdt_table, GDT_SIZE);
++		
++		cpu_gdt_descr->size = GDT_SIZE;
++		cpu_gdt_descr->address = (unsigned long)gdt;
++	}
++#endif
++
++	cpu_gdt_init(cpu_gdt_descr);
++
++	/*
++	 * Set up and load the per-CPU TSS and LDT
++	 */
++	atomic_inc(&init_mm.mm_count);
++	current->active_mm = &init_mm;
++	if (current->mm)
++		BUG();
++	enter_lazy_tlb(&init_mm, current);
++
++	load_esp0(t, thread);
++
++	load_LDT(&init_mm.context);
++
++#ifdef CONFIG_DOUBLEFAULT
++	/* Set up doublefault TSS pointer in the GDT */
++	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
++#endif
++
++	/* Clear %fs and %gs. */
++	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
++
++	/* Clear all 6 debug registers: */
++	set_debugreg(0, 0);
++	set_debugreg(0, 1);
++	set_debugreg(0, 2);
++	set_debugreg(0, 3);
++	set_debugreg(0, 6);
++	set_debugreg(0, 7);
++
++	/*
++	 * Force FPU initialization:
++	 */
++	current_thread_info()->status = 0;
++	clear_used_math();
++	mxcsr_feature_mask_init();
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++void __cpuinit cpu_uninit(void)
++{
++	int cpu = raw_smp_processor_id();
++	cpu_clear(cpu, cpu_initialized);
++
++	/* lazy TLB state */
++	per_cpu(cpu_tlbstate, cpu).state = 0;
++	per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
++}
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/cpu/mcheck/mce_dom0.c	2009-10-01 11:00:47.000000000 +0200
+@@ -0,0 +1,134 @@
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <xen/interface/xen.h>
++#include <xen/evtchn.h>
++#include <xen/interface/vcpu.h>
++#include <asm/hypercall.h>
++#include <asm/mce.h>
++
++static int convert_log(struct mc_info *mi)
++{
++	struct mcinfo_common *mic = NULL;
++	struct mcinfo_global *mc_global;
++	struct mcinfo_bank *mc_bank;
++	struct mce m;
++
++	x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL);
++	if (mic == NULL)
++	{
++		printk(KERN_ERR "DOM0_MCE_LOG: global data is NULL\n");
++		return -1;
++	}
++
++	mc_global = (struct mcinfo_global*)mic;
++	m.mcgstatus = mc_global->mc_gstatus;
++	m.cpu = mc_global->mc_coreid;/*for test*/
++	x86_mcinfo_lookup(mic, mi, MC_TYPE_BANK);
++	do
++	{
++		if (mic == NULL || mic->size == 0)
++			break;
++		if (mic->type == MC_TYPE_BANK)
++		{
++			mc_bank = (struct mcinfo_bank*)mic;
++			m.misc = mc_bank->mc_misc;
++			m.status = mc_bank->mc_status;
++			m.addr = mc_bank->mc_addr;
++			m.tsc = mc_bank->mc_tsc;
++			m.res1 = mc_bank->mc_ctrl2;
++			m.bank = mc_bank->mc_bank;
++			printk(KERN_DEBUG "[CPU%d, BANK%d, addr %llx, state %llx]\n", 
++						m.bank, m.cpu, m.addr, m.status);
++			/*log this record*/
++			mce_log(&m);
++		}
++		mic = x86_mcinfo_next(mic);
++	}while (1);
++
++	return 0;
++}
++
++static struct mc_info *g_mi;
++
++/*dom0 mce virq handler, logging physical mce error info*/
++
++static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id,
++									struct pt_regs *regs)
++{
++	xen_mc_t mc_op;
++	int result = 0;
++
++	printk(KERN_DEBUG "MCE_DOM0_LOG: enter dom0 mce vIRQ handler\n");
++	mc_op.cmd = XEN_MC_fetch;
++	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
++	set_xen_guest_handle(mc_op.u.mc_fetch.data, g_mi);
++urgent:
++	mc_op.u.mc_fetch.flags = XEN_MC_URGENT;
++	result = HYPERVISOR_mca(&mc_op);
++	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
++			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
++	{
++		printk(KERN_DEBUG "MCE_DOM0_LOG: No more urgent data\n");
++		goto nonurgent;
++	}
++	else
++	{
++		result = convert_log(g_mi);
++		if (result) {
++			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
++			goto end;
++		}
++		/* After fetching the telem from DOM0, we need to dec the telem's
++		 * refcnt and release the entry. The telem is reserved and inc
++		 * refcnt when filling the telem.
++		 */
++		mc_op.u.mc_fetch.flags = XEN_MC_URGENT | XEN_MC_ACK;
++		result = HYPERVISOR_mca(&mc_op);
++
++		goto urgent;
++	}
++nonurgent:
++	mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT;
++	result = HYPERVISOR_mca(&mc_op);
++	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
++			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
++	{
++		printk(KERN_DEBUG "MCE_DOM0_LOG: No more nonurgent data\n");
++		goto end;
++	}
++	else
++	{
++		result = convert_log(g_mi);
++		if (result) {
++			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
++			goto end;
++		}
++		/* After fetching the telem from DOM0, we need to dec the telem's
++		 * refcnt and release the entry. The telem is reserved and inc
++		 * refcnt when filling the telem.
++		 */
++		mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT | XEN_MC_ACK;
++		result = HYPERVISOR_mca(&mc_op);
++
++		goto nonurgent;
++	}
++end:
++	return IRQ_HANDLED;
++}
++
++void bind_virq_for_mce(void)
++{
++	int ret;
++
++	ret  = bind_virq_to_irqhandler(VIRQ_MCA, 0, 
++		mce_dom0_interrupt, 0, "mce", NULL);
++
++	g_mi = kmalloc(sizeof(struct mc_info), GFP_KERNEL);
++	if (ret < 0)
++		printk(KERN_ERR "MCE_DOM0_LOG: bind_virq for DOM0 failed\n");
++
++	/* Log the machine checks left over from the previous reset. */
++	mce_dom0_interrupt(VIRQ_MCA, NULL, NULL);
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2008-01-28 12:24:18.000000000 +0100
+@@ -0,0 +1,198 @@
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/ctype.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <asm/uaccess.h>
++#include <linux/mutex.h>
++
++#include <asm/mtrr.h>
++#include "mtrr.h"
++
++static DEFINE_MUTEX(mtrr_mutex);
++
++void generic_get_mtrr(unsigned int reg, unsigned long *base,
++		      unsigned int *size, mtrr_type * type)
++{
++	struct xen_platform_op op;
++
++	op.cmd = XENPF_read_memtype;
++	op.u.read_memtype.reg = reg;
++	if (unlikely(HYPERVISOR_platform_op(&op)))
++		memset(&op.u.read_memtype, 0, sizeof(op.u.read_memtype));
++
++	*size = op.u.read_memtype.nr_mfns;
++	*base = op.u.read_memtype.mfn;
++	*type = op.u.read_memtype.type;
++}
++
++struct mtrr_ops generic_mtrr_ops = {
++	.use_intel_if      = 1,
++	.get               = generic_get_mtrr,
++};
++
++struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
++unsigned int num_var_ranges;
++unsigned int *usage_table;
++
++static void __init set_num_var_ranges(void)
++{
++	struct xen_platform_op op;
++
++	for (num_var_ranges = 0; ; num_var_ranges++) {
++		op.cmd = XENPF_read_memtype;
++		op.u.read_memtype.reg = num_var_ranges;
++		if (HYPERVISOR_platform_op(&op) != 0)
++			break;
++	}
++}
++
++static void __init init_table(void)
++{
++	int i, max;
++
++	max = num_var_ranges;
++	if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
++	    == NULL) {
++		printk(KERN_ERR "mtrr: could not allocate\n");
++		return;
++	}
++	for (i = 0; i < max; i++)
++		usage_table[i] = 0;
++}
++
++int mtrr_add_page(unsigned long base, unsigned long size, 
++		  unsigned int type, char increment)
++{
++	int error;
++	struct xen_platform_op op;
++
++	mutex_lock(&mtrr_mutex);
++
++	op.cmd = XENPF_add_memtype;
++	op.u.add_memtype.mfn     = base;
++	op.u.add_memtype.nr_mfns = size;
++	op.u.add_memtype.type    = type;
++	error = HYPERVISOR_platform_op(&op);
++	if (error) {
++		mutex_unlock(&mtrr_mutex);
++		BUG_ON(error > 0);
++		return error;
++	}
++
++	if (increment)
++		++usage_table[op.u.add_memtype.reg];
++
++	mutex_unlock(&mtrr_mutex);
++
++	return op.u.add_memtype.reg;
++}
++
++static int mtrr_check(unsigned long base, unsigned long size)
++{
++	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
++		printk(KERN_WARNING
++			"mtrr: size and base must be multiples of 4 kiB\n");
++		printk(KERN_DEBUG
++			"mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
++		dump_stack();
++		return -1;
++	}
++	return 0;
++}
++
++int
++mtrr_add(unsigned long base, unsigned long size, unsigned int type,
++	 char increment)
++{
++	if (mtrr_check(base, size))
++		return -EINVAL;
++	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
++			     increment);
++}
++
++int mtrr_del_page(int reg, unsigned long base, unsigned long size)
++{
++	unsigned i;
++	mtrr_type ltype;
++	unsigned long lbase;
++	unsigned int lsize;
++	int error = -EINVAL;
++	struct xen_platform_op op;
++
++	mutex_lock(&mtrr_mutex);
++
++	if (reg < 0) {
++		/*  Search for existing MTRR  */
++		for (i = 0; i < num_var_ranges; ++i) {
++			mtrr_if->get(i, &lbase, &lsize, &ltype);
++			if (lbase == base && lsize == size) {
++				reg = i;
++				break;
++			}
++		}
++		if (reg < 0) {
++			printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
++			       size);
++			goto out;
++		}
++	}
++	if (usage_table[reg] < 1) {
++		printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
++		goto out;
++	}
++	if (--usage_table[reg] < 1) {
++		op.cmd = XENPF_del_memtype;
++		op.u.del_memtype.handle = 0;
++		op.u.del_memtype.reg    = reg;
++		error = HYPERVISOR_platform_op(&op);
++		if (error) {
++			BUG_ON(error > 0);
++			goto out;
++		}
++	}
++	error = reg;
++ out:
++	mutex_unlock(&mtrr_mutex);
++	return error;
++}
++
++int
++mtrr_del(int reg, unsigned long base, unsigned long size)
++{
++	if (mtrr_check(base, size))
++		return -EINVAL;
++	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
++}
++
++EXPORT_SYMBOL(mtrr_add);
++EXPORT_SYMBOL(mtrr_del);
++
++void __init mtrr_bp_init(void)
++{
++}
++
++void mtrr_ap_init(void)
++{
++}
++
++static int __init mtrr_init(void)
++{
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++
++	if (!is_initial_xendomain())
++		return -ENODEV;
++
++	if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
++	    (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
++	    (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
++	    (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
++		return -ENODEV;
++
++	set_num_var_ranges();
++	init_table();
++
++	return 0;
++}
++
++subsys_initcall(mtrr_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-05-19 09:16:41.000000000 +0200
+@@ -0,0 +1,1242 @@
++/*
++ *  linux/arch/i386/entry.S
++ *
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ */
++
++/*
++ * entry.S contains the system-call and fault low-level handling routines.
++ * This also contains the timer-interrupt handler, as well as all interrupts
++ * and faults that can result in a task-switch.
++ *
++ * NOTE: This code handles signal-recognition, which happens every time
++ * after a timer-interrupt and after each system call.
++ *
++ * I changed all the .align's to 4 (16 byte alignment), as that's faster
++ * on a 486.
++ *
++ * Stack layout in 'ret_from_system_call':
++ * 	ptrace needs to have all regs on the stack.
++ *	if the order here is changed, it needs to be
++ *	updated in fork.c:copy_process, signal.c:do_signal,
++ *	ptrace.c and ptrace.h
++ *
++ *	 0(%esp) - %ebx
++ *	 4(%esp) - %ecx
++ *	 8(%esp) - %edx
++ *       C(%esp) - %esi
++ *	10(%esp) - %edi
++ *	14(%esp) - %ebp
++ *	18(%esp) - %eax
++ *	1C(%esp) - %ds
++ *	20(%esp) - %es
++ *	24(%esp) - orig_eax
++ *	28(%esp) - %eip
++ *	2C(%esp) - %cs
++ *	30(%esp) - %eflags
++ *	34(%esp) - %oldesp
++ *	38(%esp) - %oldss
++ *
++ * "current" is in register %ebx during any slow entries.
++ */
++
++#include <linux/linkage.h>
++#include <asm/thread_info.h>
++#include <asm/irqflags.h>
++#include <asm/errno.h>
++#include <asm/segment.h>
++#include <asm/smp.h>
++#include <asm/page.h>
++#include <asm/desc.h>
++#include <asm/dwarf2.h>
++#include "irq_vectors.h"
++#include <xen/interface/xen.h>
++
++#define nr_syscalls ((syscall_table_size)/4)
++
++EBX		= 0x00
++ECX		= 0x04
++EDX		= 0x08
++ESI		= 0x0C
++EDI		= 0x10
++EBP		= 0x14
++EAX		= 0x18
++DS		= 0x1C
++ES		= 0x20
++ORIG_EAX	= 0x24
++EIP		= 0x28
++CS		= 0x2C
++EFLAGS		= 0x30
++OLDESP		= 0x34
++OLDSS		= 0x38
++
++CF_MASK		= 0x00000001
++TF_MASK		= 0x00000100
++IF_MASK		= 0x00000200
++DF_MASK		= 0x00000400 
++NT_MASK		= 0x00004000
++VM_MASK		= 0x00020000
++/* Pseudo-eflags. */
++NMI_MASK	= 0x80000000
++
++#ifndef CONFIG_XEN
++#define DISABLE_INTERRUPTS	cli
++#define ENABLE_INTERRUPTS	sti
++#else
++/* Offsets into shared_info_t. */
++#define evtchn_upcall_pending		/* 0 */
++#define evtchn_upcall_mask		1
++
++#define sizeof_vcpu_shift		6
++
++#ifdef CONFIG_SMP
++#define GET_VCPU_INFO		movl TI_cpu(%ebp),%esi			; \
++				shl  $sizeof_vcpu_shift,%esi		; \
++				addl HYPERVISOR_shared_info,%esi
++#else
++#define GET_VCPU_INFO		movl HYPERVISOR_shared_info,%esi
++#endif
++
++#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(%esi)
++#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(%esi)
++#define DISABLE_INTERRUPTS	GET_VCPU_INFO				; \
++				__DISABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS	GET_VCPU_INFO				; \
++				__ENABLE_INTERRUPTS
++#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
++#endif
++
++#ifdef CONFIG_PREEMPT
++#define preempt_stop		cli; TRACE_IRQS_OFF
++#else
++#define preempt_stop
++#define resume_kernel		restore_nocheck
++#endif
++
++.macro TRACE_IRQS_IRET
++#ifdef CONFIG_TRACE_IRQFLAGS
++	testl $IF_MASK,EFLAGS(%esp)     # interrupts off?
++	jz 1f
++	TRACE_IRQS_ON
++1:
++#endif
++.endm
++
++#ifdef CONFIG_VM86
++#define resume_userspace_sig	check_userspace
++#else
++#define resume_userspace_sig	resume_userspace
++#endif
++
++#define SAVE_ALL \
++	cld; \
++	pushl %es; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	/*CFI_REL_OFFSET es, 0;*/\
++	pushl %ds; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	/*CFI_REL_OFFSET ds, 0;*/\
++	pushl %eax; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET eax, 0;\
++	pushl %ebp; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET ebp, 0;\
++	pushl %edi; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET edi, 0;\
++	pushl %esi; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET esi, 0;\
++	pushl %edx; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET edx, 0;\
++	pushl %ecx; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET ecx, 0;\
++	pushl %ebx; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	CFI_REL_OFFSET ebx, 0;\
++	movl $(__USER_DS), %edx; \
++	movl %edx, %ds; \
++	movl %edx, %es;
++
++#define RESTORE_INT_REGS \
++	popl %ebx;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE ebx;\
++	popl %ecx;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE ecx;\
++	popl %edx;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE edx;\
++	popl %esi;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE esi;\
++	popl %edi;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE edi;\
++	popl %ebp;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE ebp;\
++	popl %eax;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	CFI_RESTORE eax
++
++#define RESTORE_REGS	\
++	RESTORE_INT_REGS; \
++1:	popl %ds;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	/*CFI_RESTORE ds;*/\
++2:	popl %es;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	/*CFI_RESTORE es;*/\
++.section .fixup,"ax";	\
++3:	movl $0,(%esp);	\
++	jmp 1b;		\
++4:	movl $0,(%esp);	\
++	jmp 2b;		\
++.previous;		\
++.section __ex_table,"a";\
++	.align 4;	\
++	.long 1b,3b;	\
++	.long 2b,4b;	\
++.previous
++
++#define RING0_INT_FRAME \
++	CFI_STARTPROC simple;\
++	CFI_DEF_CFA esp, 3*4;\
++	/*CFI_OFFSET cs, -2*4;*/\
++	CFI_OFFSET eip, -3*4
++
++#define RING0_EC_FRAME \
++	CFI_STARTPROC simple;\
++	CFI_DEF_CFA esp, 4*4;\
++	/*CFI_OFFSET cs, -2*4;*/\
++	CFI_OFFSET eip, -3*4
++
++#define RING0_PTREGS_FRAME \
++	CFI_STARTPROC simple;\
++	CFI_DEF_CFA esp, OLDESP-EBX;\
++	/*CFI_OFFSET cs, CS-OLDESP;*/\
++	CFI_OFFSET eip, EIP-OLDESP;\
++	/*CFI_OFFSET es, ES-OLDESP;*/\
++	/*CFI_OFFSET ds, DS-OLDESP;*/\
++	CFI_OFFSET eax, EAX-OLDESP;\
++	CFI_OFFSET ebp, EBP-OLDESP;\
++	CFI_OFFSET edi, EDI-OLDESP;\
++	CFI_OFFSET esi, ESI-OLDESP;\
++	CFI_OFFSET edx, EDX-OLDESP;\
++	CFI_OFFSET ecx, ECX-OLDESP;\
++	CFI_OFFSET ebx, EBX-OLDESP
++
++ENTRY(ret_from_fork)
++	CFI_STARTPROC
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	call schedule_tail
++	GET_THREAD_INFO(%ebp)
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
++	pushl $0x0202			# Reset kernel eflags
++	CFI_ADJUST_CFA_OFFSET 4
++	popfl
++	CFI_ADJUST_CFA_OFFSET -4
++	jmp syscall_exit
++	CFI_ENDPROC
++
++/*
++ * Return to user mode is not as complex as all this looks,
++ * but we want the default path for a system call return to
++ * go as quickly as possible which is why some of this is
++ * less clear than it otherwise should be.
++ */
++
++	# userspace resumption stub bypassing syscall exit tracing
++	ALIGN
++	RING0_PTREGS_FRAME
++ret_from_exception:
++	preempt_stop
++ret_from_intr:
++	GET_THREAD_INFO(%ebp)
++check_userspace:
++	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
++	movb CS(%esp), %al
++	testl $(VM_MASK | 2), %eax
++	jz resume_kernel
++ENTRY(resume_userspace)
++	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++					# setting need_resched or sigpending
++					# between sampling and the iret
++	movl TI_flags(%ebp), %ecx
++	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done on
++					# int/exception return?
++	jne work_pending
++	jmp restore_all
++
++#ifdef CONFIG_PREEMPT
++ENTRY(resume_kernel)
++	cli
++	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
++	jnz restore_nocheck
++need_resched:
++	movl TI_flags(%ebp), %ecx	# need_resched set ?
++	testb $_TIF_NEED_RESCHED, %cl
++	jz restore_all
++	testl $IF_MASK,EFLAGS(%esp)     # interrupts off (exception path) ?
++	jz restore_all
++	call preempt_schedule_irq
++	jmp need_resched
++#endif
++	CFI_ENDPROC
++
++/* SYSENTER_RETURN points to after the "sysenter" instruction in
++   the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
++
++	# sysenter call handler stub
++ENTRY(sysenter_entry)
++	CFI_STARTPROC simple
++	CFI_DEF_CFA esp, 0
++	CFI_REGISTER esp, ebp
++	movl SYSENTER_stack_esp0(%esp),%esp
++sysenter_past_esp:
++	/*
++	 * No need to follow this irqs on/off section: the syscall
++	 * disabled irqs and here we enable it straight after entry:
++	 */
++	sti
++	pushl $(__USER_DS)
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET ss, 0*/
++	pushl %ebp
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET esp, 0
++	pushfl
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $(__USER_CS)
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET cs, 0*/
++	/*
++	 * Push current_thread_info()->sysenter_return to the stack.
++	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
++	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
++	 */
++	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET eip, 0
++
++/*
++ * Load the potential sixth argument from user stack.
++ * Careful about security.
++ */
++	cmpl $__PAGE_OFFSET-3,%ebp
++	jae syscall_fault
++1:	movl (%ebp),%ebp
++.section __ex_table,"a"
++	.align 4
++	.long 1b,syscall_fault
++.previous
++
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	GET_THREAD_INFO(%ebp)
++
++	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
++	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	jnz syscall_trace_entry
++	cmpl $(nr_syscalls), %eax
++	jae syscall_badsys
++	call *sys_call_table(,%eax,4)
++	movl %eax,EAX(%esp)
++	DISABLE_INTERRUPTS
++	TRACE_IRQS_OFF
++	movl TI_flags(%ebp), %ecx
++	testw $_TIF_ALLWORK_MASK, %cx
++	jne syscall_exit_work
++/* if something modifies registers it must also disable sysexit */
++	movl EIP(%esp), %edx
++	movl OLDESP(%esp), %ecx
++	xorl %ebp,%ebp
++#ifdef CONFIG_XEN
++	TRACE_IRQS_ON
++	__ENABLE_INTERRUPTS
++sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/
++	__TEST_PENDING
++	jnz  14f			# process more events if necessary...
++	movl ESI(%esp), %esi
++	sysexit
++14:	__DISABLE_INTERRUPTS
++	TRACE_IRQS_OFF
++sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/
++	push %esp
++	call evtchn_do_upcall
++	add  $4,%esp
++	jmp  ret_from_intr
++#else
++	TRACE_IRQS_ON
++	sti
++	sysexit
++#endif /* !CONFIG_XEN */
++	CFI_ENDPROC
++
++	# pv sysenter call handler stub
++ENTRY(sysenter_entry_pv)
++	RING0_INT_FRAME
++	movl $__USER_DS,16(%esp)
++	movl %ebp,12(%esp)
++	movl $__USER_CS,4(%esp)
++	addl $4,%esp
++	CFI_ADJUST_CFA_OFFSET -4
++	/* +5*4 is SS:ESP,EFLAGS,CS:EIP. +8 is esp0 setting. */
++	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
++	CFI_ADJUST_CFA_OFFSET 4
++/*
++ * Load the potential sixth argument from user stack.
++ * Careful about security.
++ */
++	cmpl $__PAGE_OFFSET-3,%ebp
++	jae syscall_fault
++1:	movl (%ebp),%ebp
++.section __ex_table,"a"
++	.align 4
++	.long 1b,syscall_fault
++.previous
++	/* fall through */
++	CFI_ENDPROC
++ENDPROC(sysenter_entry_pv)
++
++	# system call handler stub
++ENTRY(system_call)
++	RING0_INT_FRAME			# can't unwind into user space anyway
++	pushl %eax			# save orig_eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	GET_THREAD_INFO(%ebp)
++	testl $TF_MASK,EFLAGS(%esp)
++	jz no_singlestep
++	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
++no_singlestep:
++					# system call tracing in operation / emulation
++	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
++	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	jnz syscall_trace_entry
++	cmpl $(nr_syscalls), %eax
++	jae syscall_badsys
++syscall_call:
++	call *sys_call_table(,%eax,4)
++	movl %eax,EAX(%esp)		# store the return value
++syscall_exit:
++	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++					# setting need_resched or sigpending
++					# between sampling and the iret
++	TRACE_IRQS_OFF
++	movl TI_flags(%ebp), %ecx
++	testw $_TIF_ALLWORK_MASK, %cx	# current->work
++	jne syscall_exit_work
++
++restore_all:
++#ifndef CONFIG_XEN
++	movl EFLAGS(%esp), %eax		# mix EFLAGS, SS and CS
++	# Warning: OLDSS(%esp) contains the wrong/random values if we
++	# are returning to the kernel.
++	# See comments in process.c:copy_thread() for details.
++	movb OLDSS(%esp), %ah
++	movb CS(%esp), %al
++	andl $(VM_MASK | (4 << 8) | 3), %eax
++	cmpl $((4 << 8) | 3), %eax
++	CFI_REMEMBER_STATE
++	je ldt_ss			# returning to user-space with LDT SS
++restore_nocheck:
++#else
++restore_nocheck:
++	movl EFLAGS(%esp), %eax
++	testl $(VM_MASK|NMI_MASK), %eax
++	CFI_REMEMBER_STATE
++	jnz hypervisor_iret
++	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
++	GET_VCPU_INFO
++	andb evtchn_upcall_mask(%esi),%al
++	andb $1,%al			# EAX[0] == IRET_EFLAGS.IF & event_mask
++	CFI_REMEMBER_STATE
++	jnz restore_all_enable_events	#        != 0 => enable event delivery
++#endif
++	TRACE_IRQS_IRET
++restore_nocheck_notrace:
++	RESTORE_REGS
++	addl $4, %esp
++	CFI_ADJUST_CFA_OFFSET -4
++1:	iret
++.section .fixup,"ax"
++iret_exc:
++#ifndef CONFIG_XEN
++	TRACE_IRQS_ON
++	sti
++#endif
++	pushl $0			# no error code
++	pushl $do_iret_error
++	jmp error_code
++.previous
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
++
++	CFI_RESTORE_STATE
++#ifndef CONFIG_XEN
++ldt_ss:
++	larl OLDSS(%esp), %eax
++	jnz restore_nocheck
++	testl $0x00400000, %eax		# returning to 32bit stack?
++	jnz restore_nocheck		# allright, normal return
++	/* If returning to userspace with 16bit stack,
++	 * try to fix the higher word of ESP, as the CPU
++	 * won't restore it.
++	 * This is an "official" bug of all the x86-compatible
++	 * CPUs, which we can try to work around to make
++	 * dosemu and wine happy. */
++	subl $8, %esp		# reserve space for switch16 pointer
++	CFI_ADJUST_CFA_OFFSET 8
++	cli
++	TRACE_IRQS_OFF
++	movl %esp, %eax
++	/* Set up the 16bit stack frame with switch32 pointer on top,
++	 * and a switch16 pointer on top of the current frame. */
++	call setup_x86_bogus_stack
++	CFI_ADJUST_CFA_OFFSET -8	# frame has moved
++	TRACE_IRQS_IRET
++	RESTORE_REGS
++	lss 20+4(%esp), %esp	# switch to 16bit stack
++1:	iret
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
++#else
++        ALIGN
++restore_all_enable_events:
++	TRACE_IRQS_ON
++	__ENABLE_INTERRUPTS
++scrit:	/**** START OF CRITICAL REGION ****/
++	__TEST_PENDING
++	jnz  14f			# process more events if necessary...
++	RESTORE_REGS
++	addl $4, %esp
++	CFI_ADJUST_CFA_OFFSET -4
++1:	iret
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
++14:	__DISABLE_INTERRUPTS
++	TRACE_IRQS_OFF
++ecrit:  /**** END OF CRITICAL REGION ****/
++	jmp  .Ldo_upcall
++
++	CFI_RESTORE_STATE
++hypervisor_iret:
++	andl $~NMI_MASK, EFLAGS(%esp)
++	RESTORE_REGS
++	addl $4, %esp
++	CFI_ADJUST_CFA_OFFSET -4
++	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
++#endif
++	CFI_ENDPROC
++
++	# perform work that needs to be done immediately before resumption
++	ALIGN
++	RING0_PTREGS_FRAME		# can't unwind into user space anyway
++work_pending:
++	testb $_TIF_NEED_RESCHED, %cl
++	jz work_notifysig
++work_resched:
++	call schedule
++	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++					# setting need_resched or sigpending
++					# between sampling and the iret
++	TRACE_IRQS_OFF
++	movl TI_flags(%ebp), %ecx
++	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done other
++					# than syscall tracing?
++	jz restore_all
++	testb $_TIF_NEED_RESCHED, %cl
++	jnz work_resched
++
++work_notifysig:				# deal with pending signals and
++					# notify-resume requests
++	testl $VM_MASK, EFLAGS(%esp)
++	movl %esp, %eax
++	jne work_notifysig_v86		# returning to kernel-space or
++					# vm86-space
++	xorl %edx, %edx
++	call do_notify_resume
++	jmp resume_userspace_sig
++
++	ALIGN
++work_notifysig_v86:
++#ifdef CONFIG_VM86
++	pushl %ecx			# save ti_flags for do_notify_resume
++	CFI_ADJUST_CFA_OFFSET 4
++	call save_v86_state		# %eax contains pt_regs pointer
++	popl %ecx
++	CFI_ADJUST_CFA_OFFSET -4
++	movl %eax, %esp
++	xorl %edx, %edx
++	call do_notify_resume
++	jmp resume_userspace_sig
++#endif
++
++	# perform syscall exit tracing
++	ALIGN
++syscall_trace_entry:
++	movl $-ENOSYS,EAX(%esp)
++	movl %esp, %eax
++	xorl %edx,%edx
++	call do_syscall_trace
++	cmpl $0, %eax
++	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
++					# so must skip actual syscall
++	movl ORIG_EAX(%esp), %eax
++	cmpl $(nr_syscalls), %eax
++	jnae syscall_call
++	jmp syscall_exit
++
++	# perform syscall exit tracing
++	ALIGN
++syscall_exit_work:
++	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
++	jz work_pending
++	TRACE_IRQS_ON
++	ENABLE_INTERRUPTS		# could let do_syscall_trace() call
++					# schedule() instead
++	movl %esp, %eax
++	movl $1, %edx
++	call do_syscall_trace
++	jmp resume_userspace
++	CFI_ENDPROC
++
++	RING0_INT_FRAME			# can't unwind into user space anyway
++syscall_fault:
++	pushl %eax			# save orig_eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	GET_THREAD_INFO(%ebp)
++	movl $-EFAULT,EAX(%esp)
++	jmp resume_userspace
++
++syscall_badsys:
++	movl $-ENOSYS,EAX(%esp)
++	jmp resume_userspace
++	CFI_ENDPROC
++
++#ifndef CONFIG_XEN
++#define FIXUP_ESPFIX_STACK \
++	movl %esp, %eax; \
++	/* switch to 32bit stack using the pointer on top of 16bit stack */ \
++	lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
++	/* copy data from 16bit stack to 32bit stack */ \
++	call fixup_x86_bogus_stack; \
++	/* put ESP to the proper location */ \
++	movl %eax, %esp;
++#define UNWIND_ESPFIX_STACK \
++	pushl %eax; \
++	CFI_ADJUST_CFA_OFFSET 4; \
++	movl %ss, %eax; \
++	/* see if on 16bit stack */ \
++	cmpw $__ESPFIX_SS, %ax; \
++	je 28f; \
++27:	popl %eax; \
++	CFI_ADJUST_CFA_OFFSET -4; \
++.section .fixup,"ax"; \
++28:	movl $__KERNEL_DS, %eax; \
++	movl %eax, %ds; \
++	movl %eax, %es; \
++	/* switch to 32bit stack */ \
++	FIXUP_ESPFIX_STACK; \
++	jmp 27b; \
++.previous
++
++/*
++ * Build the entry stubs and pointer table with
++ * some assembler magic.
++ */
++.data
++ENTRY(interrupt)
++.text
++
++vector=0
++ENTRY(irq_entries_start)
++	RING0_INT_FRAME
++.rept NR_IRQS
++	ALIGN
++ .if vector
++	CFI_ADJUST_CFA_OFFSET -4
++ .endif
++1:	pushl $~(vector)
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp common_interrupt
++.data
++	.long 1b
++.text
++vector=vector+1
++.endr
++
++/*
++ * the CPU automatically disables interrupts when executing an IRQ vector,
++ * so IRQ-flags tracing has to follow that:
++ */
++	ALIGN
++common_interrupt:
++	SAVE_ALL
++	TRACE_IRQS_OFF
++	movl %esp,%eax
++	call do_IRQ
++	jmp ret_from_intr
++	CFI_ENDPROC
++
++#define BUILD_INTERRUPT(name, nr)	\
++ENTRY(name)				\
++	RING0_INT_FRAME;		\
++	pushl $~(nr);			\
++	CFI_ADJUST_CFA_OFFSET 4;	\
++	SAVE_ALL;			\
++	TRACE_IRQS_OFF			\
++	movl %esp,%eax;			\
++	call smp_/**/name;		\
++	jmp ret_from_intr;		\
++	CFI_ENDPROC
++
++/* The include is where all of the SMP etc. interrupts come from */
++#include "entry_arch.h"
++#else
++#define UNWIND_ESPFIX_STACK
++#endif
++
++ENTRY(divide_error)
++	RING0_INT_FRAME
++	pushl $0			# no error code
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_divide_error
++	CFI_ADJUST_CFA_OFFSET 4
++	ALIGN
++error_code:
++	pushl %ds
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET ds, 0*/
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET eax, 0
++	xorl %eax, %eax
++	pushl %ebp
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebp, 0
++	pushl %edi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edi, 0
++	pushl %esi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET esi, 0
++	pushl %edx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edx, 0
++	decl %eax			# eax = -1
++	pushl %ecx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ecx, 0
++	pushl %ebx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebx, 0
++	cld
++	pushl %es
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET es, 0*/
++	UNWIND_ESPFIX_STACK
++	popl %ecx
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_REGISTER es, ecx*/
++	movl ES(%esp), %edi		# get the function address
++	movl ORIG_EAX(%esp), %edx	# get the error code
++	movl %eax, ORIG_EAX(%esp)
++	movl %ecx, ES(%esp)
++	/*CFI_REL_OFFSET es, ES*/
++	movl $(__USER_DS), %ecx
++	movl %ecx, %ds
++	movl %ecx, %es
++	movl %esp,%eax			# pt_regs pointer
++	call *%edi
++	jmp ret_from_exception
++	CFI_ENDPROC
++
++#ifdef CONFIG_XEN
++# A note on the "critical region" in our callback handler.
++# We want to avoid stacking callback handlers due to events occurring
++# during handling of the last event. To do this, we keep events disabled
++# until we've done all processing. HOWEVER, we must enable events before
++# popping the stack frame (can't be done atomically) and so it would still
++# be possible to get enough handler activations to overflow the stack.
++# Although unlikely, bugs of that kind are hard to track down, so we'd
++# like to avoid the possibility.
++# So, on entry to the handler we detect whether we interrupted an
++# existing activation in its critical region -- if so, we pop the current
++# activation and restart the handler using the previous one.
++#
++# The sysexit critical region is slightly different. sysexit
++# atomically removes the entire stack frame. If we interrupt in the
++# critical region we know that the entire frame is present and correct
++# so we can simply throw away the new one.
++ENTRY(hypervisor_callback)
++	RING0_INT_FRAME
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	testb $2,CS(%esp)
++	movl EIP(%esp),%eax
++	jnz  .Ldo_upcall
++	cmpl $scrit,%eax
++	jb   0f
++	cmpl $ecrit,%eax
++	jb   critical_region_fixup
++0:
++#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL
++	cmpl $sysexit_scrit,%eax
++	jb   .Ldo_upcall
++	cmpl $sysexit_ecrit,%eax
++	ja   .Ldo_upcall
++	addl $OLDESP,%esp		# Remove eflags...ebx from stack frame.
++#endif
++.Ldo_upcall:
++	push %esp
++	CFI_ADJUST_CFA_OFFSET 4
++	call evtchn_do_upcall
++	add  $4,%esp
++	CFI_ADJUST_CFA_OFFSET -4
++	jmp  ret_from_intr
++	CFI_ENDPROC
++
++# [How we do the fixup]. We want to merge the current stack frame with the
++# just-interrupted frame. How we do this depends on where in the critical
++# region the interrupted handler was executing, and so how many saved
++# registers are in each frame. We do this quickly using the lookup table
++# 'critical_fixup_table'. For each byte offset in the critical region, it
++# provides the number of bytes which have already been popped from the
++# interrupted stack frame.
++critical_region_fixup:
++	movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped
++	testl %ecx,%ecx
++	leal (%esp,%ecx,4),%esi		# %esi points at end of src region
++	leal OLDESP(%esp),%edi		# %edi points at end of dst region
++	jle   17f			# skip loop if nothing to copy
++16:	subl $4,%esi			# pre-decrementing copy loop
++	subl $4,%edi
++	movl (%esi),%eax
++	movl %eax,(%edi)
++	loop 16b
++17:	movl %edi,%esp			# final %edi is top of merged stack
++	jmp  .Ldo_upcall
++
++.section .rodata,"a"
++critical_fixup_table:
++	.byte -1,-1,-1			# testb $0xff,(%esi) = __TEST_PENDING
++	.byte -1,-1			# jnz  14f
++	.byte 0				# pop  %ebx
++	.byte 1				# pop  %ecx
++	.byte 2				# pop  %edx
++	.byte 3				# pop  %esi
++	.byte 4				# pop  %edi
++	.byte 5				# pop  %ebp
++	.byte 6				# pop  %eax
++	.byte 7				# pop  %ds
++	.byte 8				# pop  %es
++	.byte 9,9,9			# add  $4,%esp
++	.byte 10			# iret
++	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
++.previous
++
++# Hypervisor uses this for application faults while it executes.
++# We get here for two reasons:
++#  1. Fault while reloading DS, ES, FS or GS
++#  2. Fault while executing IRET
++# Category 1 we fix up by reattempting the load, and zeroing the segment
++# register if the load fails.
++# Category 2 we fix up by jumping to do_iret_error. We cannot use the
++# normal Linux return path in this case because if we use the IRET hypercall
++# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
++# We distinguish between categories by maintaining a status value in EAX.
++ENTRY(failsafe_callback)
++	pushl %eax
++	movl $1,%eax
++1:	mov 4(%esp),%ds
++2:	mov 8(%esp),%es
++3:	mov 12(%esp),%fs
++4:	mov 16(%esp),%gs
++	testl %eax,%eax
++	popl %eax
++	jz 5f
++	addl $16,%esp		# EAX != 0 => Category 2 (Bad IRET)
++	jmp iret_exc
++5:	addl $16,%esp		# EAX == 0 => Category 1 (Bad segment)
++	RING0_INT_FRAME
++	pushl $0
++	SAVE_ALL
++	jmp ret_from_exception
++.section .fixup,"ax";		\
++6:	xorl %eax,%eax;		\
++	movl %eax,4(%esp);	\
++	jmp 1b;			\
++7:	xorl %eax,%eax;		\
++	movl %eax,8(%esp);	\
++	jmp 2b;			\
++8:	xorl %eax,%eax;		\
++	movl %eax,12(%esp);	\
++	jmp 3b;			\
++9:	xorl %eax,%eax;		\
++	movl %eax,16(%esp);	\
++	jmp 4b;			\
++.previous;			\
++.section __ex_table,"a";	\
++	.align 4;		\
++	.long 1b,6b;		\
++	.long 2b,7b;		\
++	.long 3b,8b;		\
++	.long 4b,9b;		\
++.previous
++#endif
++	CFI_ENDPROC
++
++ENTRY(coprocessor_error)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_coprocessor_error
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(simd_coprocessor_error)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_simd_coprocessor_error
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(device_not_available)
++	RING0_INT_FRAME
++	pushl $-1			# mark this as an int
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++#ifndef CONFIG_XEN
++	movl %cr0, %eax
++	testl $0x4, %eax		# EM (math emulation bit)
++	je device_available_emulate
++	pushl $0			# temporary storage for ORIG_EIP
++	CFI_ADJUST_CFA_OFFSET 4
++	call math_emulate
++	addl $4, %esp
++	CFI_ADJUST_CFA_OFFSET -4
++	jmp ret_from_exception
++device_available_emulate:
++#endif
++	preempt_stop
++	call math_state_restore
++	jmp ret_from_exception
++	CFI_ENDPROC
++
++#ifndef CONFIG_XEN
++/*
++ * Debug traps and NMI can happen at the one SYSENTER instruction
++ * that sets up the real kernel stack. Check here, since we can't
++ * allow the wrong stack to be used.
++ *
++ * "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.
++ *
++ * We just load the right stack, and push the three (known) values
++ * by hand onto the new stack - while updating the return eip past
++ * the instruction that would have done it for sysenter.
++ */
++#define FIX_STACK(offset, ok, label)		\
++	cmpw $__KERNEL_CS,4(%esp);		\
++	jne ok;					\
++label:						\
++	movl SYSENTER_stack_esp0+offset(%esp),%esp;	\
++	pushfl;					\
++	pushl $__KERNEL_CS;			\
++	pushl $sysenter_past_esp
++#endif /* CONFIG_XEN */
++
++KPROBE_ENTRY(debug)
++	RING0_INT_FRAME
++#ifndef CONFIG_XEN
++	cmpl $sysenter_entry,(%esp)
++	jne debug_stack_correct
++	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
++debug_stack_correct:
++#endif /* !CONFIG_XEN */
++	pushl $-1			# mark this as an int
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	xorl %edx,%edx			# error code 0
++	movl %esp,%eax			# pt_regs pointer
++	call do_debug
++	jmp ret_from_exception
++	CFI_ENDPROC
++	.previous .text
++#ifndef CONFIG_XEN
++/*
++ * NMI is doubly nasty. It can happen _while_ we're handling
++ * a debug fault, and the debug fault hasn't yet been able to
++ * clear up the stack. So we first check whether we got  an
++ * NMI on the sysenter entry path, but after that we need to
++ * check whether we got an NMI on the debug path where the debug
++ * fault happened on the sysenter path.
++ */
++ENTRY(nmi)
++	RING0_INT_FRAME
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	movl %ss, %eax
++	cmpw $__ESPFIX_SS, %ax
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
++	je nmi_16bit_stack
++	cmpl $sysenter_entry,(%esp)
++	je nmi_stack_fixup
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	movl %esp,%eax
++	/* Do not access memory above the end of our stack page,
++	 * it might not exist.
++	 */
++	andl $(THREAD_SIZE-1),%eax
++	cmpl $(THREAD_SIZE-20),%eax
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
++	jae nmi_stack_correct
++	cmpl $sysenter_entry,12(%esp)
++	je nmi_debug_stack_check
++nmi_stack_correct:
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_nmi
++	jmp restore_nocheck_notrace
++	CFI_ENDPROC
++
++nmi_stack_fixup:
++	FIX_STACK(12,nmi_stack_correct, 1)
++	jmp nmi_stack_correct
++nmi_debug_stack_check:
++	cmpw $__KERNEL_CS,16(%esp)
++	jne nmi_stack_correct
++	cmpl $debug,(%esp)
++	jb nmi_stack_correct
++	cmpl $debug_esp_fix_insn,(%esp)
++	ja nmi_stack_correct
++	FIX_STACK(24,nmi_stack_correct, 1)
++	jmp nmi_stack_correct
++
++nmi_16bit_stack:
++	RING0_INT_FRAME
++	/* create the pointer to lss back */
++	pushl %ss
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl %esp
++	CFI_ADJUST_CFA_OFFSET 4
++	movzwl %sp, %esp
++	addw $4, (%esp)
++	/* copy the iret frame of 12 bytes */
++	.rept 3
++	pushl 16(%esp)
++	CFI_ADJUST_CFA_OFFSET 4
++	.endr
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	FIXUP_ESPFIX_STACK		# %eax == %esp
++	CFI_ADJUST_CFA_OFFSET -20	# the frame has now moved
++	xorl %edx,%edx			# zero error code
++	call do_nmi
++	RESTORE_REGS
++	lss 12+4(%esp), %esp		# back to 16bit stack
++1:	iret
++	CFI_ENDPROC
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
++#else
++ENTRY(nmi)
++	RING0_INT_FRAME
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_nmi
++	orl  $NMI_MASK, EFLAGS(%esp)
++	jmp restore_all
++	CFI_ENDPROC
++#endif
++
++KPROBE_ENTRY(int3)
++	RING0_INT_FRAME
++	pushl $-1			# mark this as an int
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_int3
++	jmp ret_from_exception
++	CFI_ENDPROC
++	.previous .text
++
++ENTRY(overflow)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_overflow
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(bounds)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_bounds
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(invalid_op)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_invalid_op
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(coprocessor_segment_overrun)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_coprocessor_segment_overrun
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(invalid_TSS)
++	RING0_EC_FRAME
++	pushl $do_invalid_TSS
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(segment_not_present)
++	RING0_EC_FRAME
++	pushl $do_segment_not_present
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++ENTRY(stack_segment)
++	RING0_EC_FRAME
++	pushl $do_stack_segment
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++KPROBE_ENTRY(general_protection)
++	RING0_EC_FRAME
++	pushl $do_general_protection
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++	.previous .text
++
++ENTRY(alignment_check)
++	RING0_EC_FRAME
++	pushl $do_alignment_check
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++KPROBE_ENTRY(page_fault)
++	RING0_EC_FRAME
++	pushl $do_page_fault
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++	.previous .text
++
++#ifdef CONFIG_X86_MCE
++ENTRY(machine_check)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl machine_check_vector
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++#endif
++
++#ifndef CONFIG_XEN
++ENTRY(spurious_interrupt_bug)
++	RING0_INT_FRAME
++	pushl $0
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_spurious_interrupt_bug
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++#endif /* !CONFIG_XEN */
++
++#ifdef CONFIG_STACK_UNWIND
++ENTRY(arch_unwind_init_running)
++	CFI_STARTPROC
++	movl	4(%esp), %edx
++	movl	(%esp), %ecx
++	leal	4(%esp), %eax
++	movl	%ebx, EBX(%edx)
++	xorl	%ebx, %ebx
++	movl	%ebx, ECX(%edx)
++	movl	%ebx, EDX(%edx)
++	movl	%esi, ESI(%edx)
++	movl	%edi, EDI(%edx)
++	movl	%ebp, EBP(%edx)
++	movl	%ebx, EAX(%edx)
++	movl	$__USER_DS, DS(%edx)
++	movl	$__USER_DS, ES(%edx)
++	movl	%ebx, ORIG_EAX(%edx)
++	movl	%ecx, EIP(%edx)
++	movl	12(%esp), %ecx
++	movl	$__KERNEL_CS, CS(%edx)
++	movl	%ebx, EFLAGS(%edx)
++	movl	%eax, OLDESP(%edx)
++	movl	8(%esp), %eax
++	movl	%ecx, 8(%esp)
++	movl	EBX(%edx), %ebx
++	movl	$__KERNEL_DS, OLDSS(%edx)
++	jmpl	*%eax
++	CFI_ENDPROC
++ENDPROC(arch_unwind_init_running)
++#endif
++
++ENTRY(fixup_4gb_segment)
++	RING0_EC_FRAME
++	pushl $do_fixup_4gb_segment
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++
++.section .rodata,"a"
++#include "syscall_table.S"
++
++syscall_table_size=(.-sys_call_table)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/fixup.c	2008-01-28 12:24:18.000000000 +0100
+@@ -0,0 +1,88 @@
++/******************************************************************************
++ * fixup.c
++ * 
++ * Binary-rewriting of certain IA32 instructions, on notification by Xen.
++ * Used to avoid repeated slow emulation of common instructions used by the
++ * user-space TLS (Thread-Local Storage) libraries.
++ * 
++ * **** NOTE ****
++ *  Issues with the binary rewriting have caused it to be removed. Instead
++ *  we rely on Xen's emulator to boot the kernel, and then print a banner
++ *  message recommending that the user disables /lib/tls.
++ * 
++ * Copyright (c) 2004, K A Fraser
++ * 
++ * 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/init.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/version.h>
++
++#define DP(_f, _args...) printk(KERN_ALERT "  " _f "\n" , ## _args )
++
++fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
++{
++	static unsigned long printed = 0;
++	char info[100];
++	int i;
++
++	/* Ignore statically-linked init. */
++	if (current->tgid == 1)
++		return;
++            
++	VOID(HYPERVISOR_vm_assist(VMASST_CMD_disable,
++				  VMASST_TYPE_4gb_segments_notify));
++
++	if (test_and_set_bit(0, &printed))
++		return;
++
++	sprintf(info, "%s (pid=%d)", current->comm, current->tgid);
++
++	DP("");
++	DP("***************************************************************");
++	DP("***************************************************************");
++	DP("** WARNING: Currently emulating unsupported memory accesses  **");
++	DP("**          in /lib/tls glibc libraries. The emulation is    **");
++	DP("**          slow. To ensure full performance you should      **");
++	DP("**          install a 'xen-friendly' (nosegneg) version of   **");
++	DP("**          the library, or disable tls support by executing **");
++	DP("**          the following as root:                           **");
++	DP("**          mv /lib/tls /lib/tls.disabled                    **");
++	DP("** Offending process: %-38.38s **", info);
++	DP("***************************************************************");
++	DP("***************************************************************");
++	DP("");
++
++	for (i = 5; i > 0; i--) {
++		touch_softlockup_watchdog();
++		printk("Pausing... %d", i);
++		mdelay(1000);
++		printk("\b\b\b\b\b\b\b\b\b\b\b\b");
++	}
++
++	printk("Continuing...\n\n");
++}
++
++static int __init fixup_init(void)
++{
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_4gb_segments_notify));
++	return 0;
++}
++__initcall(fixup_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,207 @@
++
++
++.text
++#include <linux/elfnote.h>
++#include <linux/threads.h>
++#include <linux/linkage.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/cache.h>
++#include <asm/thread_info.h>
++#include <asm/asm-offsets.h>
++#include <asm/dwarf2.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/elfnote.h>
++
++/*
++ * References to members of the new_cpu_data structure.
++ */
++
++#define X86		new_cpu_data+CPUINFO_x86
++#define X86_VENDOR	new_cpu_data+CPUINFO_x86_vendor
++#define X86_MODEL	new_cpu_data+CPUINFO_x86_model
++#define X86_MASK	new_cpu_data+CPUINFO_x86_mask
++#define X86_HARD_MATH	new_cpu_data+CPUINFO_hard_math
++#define X86_CPUID	new_cpu_data+CPUINFO_cpuid_level
++#define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
++#define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id
++
++#define VIRT_ENTRY_OFFSET 0x0
++.org VIRT_ENTRY_OFFSET
++ENTRY(startup_32)
++	movl %esi,xen_start_info
++	cld
++
++	/* Set up the stack pointer */
++	movl $(init_thread_union+THREAD_SIZE),%esp
++
++	/* get vendor info */
++	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
++	XEN_CPUID
++	movl %eax,X86_CPUID		# save CPUID level
++	movl %ebx,X86_VENDOR_ID		# lo 4 chars
++	movl %edx,X86_VENDOR_ID+4	# next 4 chars
++	movl %ecx,X86_VENDOR_ID+8	# last 4 chars
++
++	movl $1,%eax		# Use the CPUID instruction to get CPU type
++	XEN_CPUID
++	movb %al,%cl		# save reg for future use
++	andb $0x0f,%ah		# mask processor family
++	movb %ah,X86
++	andb $0xf0,%al		# mask model
++	shrb $4,%al
++	movb %al,X86_MODEL
++	andb $0x0f,%cl		# mask mask revision
++	movb %cl,X86_MASK
++	movl %edx,X86_CAPABILITY
++
++	movb $1,X86_HARD_MATH
++
++	xorl %eax,%eax			# Clear FS/GS and LDT
++	movl %eax,%fs
++	movl %eax,%gs
++	cld			# gcc2 wants the direction flag cleared at all times
++
++	pushl %eax		# fake return address
++	jmp start_kernel
++
++#define HYPERCALL_PAGE_OFFSET 0x1000
++.org HYPERCALL_PAGE_OFFSET
++ENTRY(hypercall_page)
++	CFI_STARTPROC
++.skip 0x1000
++	CFI_ENDPROC
++
++/*
++ * Real beginning of normal "text" segment
++ */
++ENTRY(stext)
++ENTRY(_stext)
++
++/*
++ * BSS section
++ */
++.section ".bss.page_aligned","w"
++ENTRY(empty_zero_page)
++	.fill 4096,1,0
++
++/*
++ * This starts the data section.
++ */
++.data
++
++/*
++ * The Global Descriptor Table contains 28 quadwords, per-CPU.
++ */
++	.align L1_CACHE_BYTES
++ENTRY(cpu_gdt_table)
++	.quad 0x0000000000000000	/* NULL descriptor */
++	.quad 0x0000000000000000	/* 0x0b reserved */
++	.quad 0x0000000000000000	/* 0x13 reserved */
++	.quad 0x0000000000000000	/* 0x1b reserved */
++	.quad 0x0000000000000000	/* 0x20 unused */
++	.quad 0x0000000000000000	/* 0x28 unused */
++	.quad 0x0000000000000000	/* 0x33 TLS entry 1 */
++	.quad 0x0000000000000000	/* 0x3b TLS entry 2 */
++	.quad 0x0000000000000000	/* 0x43 TLS entry 3 */
++	.quad 0x0000000000000000	/* 0x4b reserved */
++	.quad 0x0000000000000000	/* 0x53 reserved */
++	.quad 0x0000000000000000	/* 0x5b reserved */
++
++	.quad 0x00cf9a000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
++	.quad 0x00cf92000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
++	.quad 0x00cffa000000ffff	/* 0x73 user 4GB code at 0x00000000 */
++	.quad 0x00cff2000000ffff	/* 0x7b user 4GB data at 0x00000000 */
++
++	.quad 0x0000000000000000	/* 0x80 TSS descriptor */
++	.quad 0x0000000000000000	/* 0x88 LDT descriptor */
++
++	/*
++	 * Segments used for calling PnP BIOS have byte granularity.
++	 * They code segments and data segments have fixed 64k limits,
++	 * the transfer segment sizes are set at run time.
++	 */
++	.quad 0x0000000000000000	/* 0x90 32-bit code */
++	.quad 0x0000000000000000	/* 0x98 16-bit code */
++	.quad 0x0000000000000000	/* 0xa0 16-bit data */
++	.quad 0x0000000000000000	/* 0xa8 16-bit data */
++	.quad 0x0000000000000000	/* 0xb0 16-bit data */
++
++	/*
++	 * The APM segments have byte granularity and their bases
++	 * are set at run time.  All have 64k limits.
++	 */
++	.quad 0x0000000000000000	/* 0xb8 APM CS    code */
++	.quad 0x0000000000000000	/* 0xc0 APM CS 16 code (16 bit) */
++	.quad 0x0000000000000000	/* 0xc8 APM DS    data */
++
++	.quad 0x0000000000000000	/* 0xd0 - ESPFIX 16-bit SS */
++	.quad 0x0000000000000000	/* 0xd8 - unused */
++	.quad 0x0000000000000000	/* 0xe0 - unused */
++	.quad 0x0000000000000000	/* 0xe8 - unused */
++	.quad 0x0000000000000000	/* 0xf0 - unused */
++	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++/*
++ * __xen_guest information
++ */
++.macro utoa value
++ .if (\value) < 0 || (\value) >= 0x10
++	utoa (((\value)>>4)&0x0fffffff)
++ .endif
++ .if ((\value) & 0xf) < 10
++  .byte '0' + ((\value) & 0xf)
++ .else
++  .byte 'A' + ((\value) & 0xf) - 10
++ .endif
++.endm
++
++.section __xen_guest
++	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
++	.ascii	",XEN_VER=xen-3.0"
++	.ascii	",VIRT_BASE=0x"
++		utoa __PAGE_OFFSET
++	.ascii	",ELF_PADDR_OFFSET=0x"
++		utoa __PAGE_OFFSET
++	.ascii	",VIRT_ENTRY=0x"
++		utoa (__PAGE_OFFSET + __PHYSICAL_START + VIRT_ENTRY_OFFSET)
++	.ascii	",HYPERCALL_PAGE=0x"
++		utoa ((__PHYSICAL_START+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
++	.ascii  ",FEATURES=writable_page_tables"
++	.ascii	         "|writable_descriptor_tables"
++	.ascii	         "|auto_translated_physmap"
++	.ascii	         "|pae_pgdir_above_4gb"
++	.ascii	         "|supervisor_mode_kernel"
++#ifdef CONFIG_X86_PAE
++	.ascii	",PAE=yes[extended-cr3]"
++#else
++	.ascii	",PAE=no"
++#endif
++	.ascii	",LOADER=generic"
++	.byte	0
++#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
++
++
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")	
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
++	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
++	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long,  __PAGE_OFFSET)
++#if CONFIG_XEN_COMPAT <= 0x030002
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  __PAGE_OFFSET)
++#else
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  0)
++#endif
++	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long,  startup_32)
++	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long,  hypercall_page)
++	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long,  HYPERVISOR_VIRT_START)
++	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
++#ifdef CONFIG_X86_PAE
++	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "yes")
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  _PAGE_PRESENT,_PAGE_PRESENT)
++#else
++	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "no")
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .long,  _PAGE_PRESENT,_PAGE_PRESENT)
++#endif
++	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz, "generic")
++	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long,  1)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,2786 @@
++/*
++ *	Intel IO-APIC support for multi-Pentium hosts.
++ *
++ *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
++ *
++ *	Many thanks to Stig Venaas for trying out countless experimental
++ *	patches and reporting/debugging problems patiently!
++ *
++ *	(c) 1999, Multiple IO-APIC support, developed by
++ *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
++ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
++ *	further tested and cleaned up by Zach Brown <zab@redhat.com>
++ *	and Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
++ *					thanks to Eric Gilmore
++ *					and Rolf G. Tews
++ *					for testing these extensively
++ *	Paul Diefenbaugh	:	Added full ACPI support
++ */
++
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/mc146818rtc.h>
++#include <linux/compiler.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++#include <linux/sysdev.h>
++
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/desc.h>
++#include <asm/timer.h>
++#include <asm/i8259.h>
++#include <asm/nmi.h>
++
++#include <mach_apic.h>
++
++#include "io_ports.h"
++
++#ifdef CONFIG_XEN
++
++#include <xen/interface/xen.h>
++#include <xen/interface/physdev.h>
++#include <xen/evtchn.h>
++
++/* Fake i8259 */
++#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
++#define disable_8259A_irq(_irq)  ((void)0)
++#define i8259A_irq_pending(_irq) (0)
++
++unsigned long io_apic_irqs;
++
++static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
++{
++	struct physdev_apic apic_op;
++	int ret;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
++	if (ret)
++		return ret;
++	return apic_op.value;
++}
++
++static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
++{
++	struct physdev_apic apic_op;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	apic_op.value = value;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
++}
++
++#define io_apic_read(a,r)    xen_io_apic_read(a,r)
++#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
++
++#endif /* CONFIG_XEN */
++
++int (*ioapic_renumber_irq)(int ioapic, int irq);
++atomic_t irq_mis_count;
++
++#ifndef CONFIG_XEN
++/* Where if anywhere is the i8259 connect in external int mode */
++static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
++#endif
++
++static DEFINE_SPINLOCK(ioapic_lock);
++static DEFINE_SPINLOCK(vector_lock);
++
++int timer_over_8254 __initdata = 1;
++
++/*
++ *	Is the SiS APIC rmw bug present ?
++ *	-1 = don't know, 0 = no, 1 = yes
++ */
++int sis_apic_bug = -1;
++
++/*
++ * # of IRQ routing registers
++ */
++int nr_ioapic_registers[MAX_IO_APICS];
++
++int disable_timer_pin_1 __initdata;
++
++/*
++ * Rough estimation of how many shared IRQs there are, can
++ * be changed anytime.
++ */
++#define MAX_PLUS_SHARED_IRQS NR_IRQS
++#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
++
++/*
++ * This is performance-critical, we want to do it O(1)
++ *
++ * the indexing order of this array favors 1:1 mappings
++ * between pins and IRQs.
++ */
++
++static struct irq_pin_list {
++	int apic, pin, next;
++} irq_2_pin[PIN_MAP_SIZE];
++
++int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
++#ifdef CONFIG_PCI_MSI
++#define vector_to_irq(vector) 	\
++	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
++#else
++#define vector_to_irq(vector)	(vector)
++#endif
++
++/*
++ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
++ * shared ISA-space IRQs, so we have to support them. We are super
++ * fast in the common case, and fast for shared ISA-space IRQs.
++ */
++static void add_pin_to_irq(unsigned int irq, int apic, int pin)
++{
++	static int first_free_entry = NR_IRQS;
++	struct irq_pin_list *entry = irq_2_pin + irq;
++
++	while (entry->next)
++		entry = irq_2_pin + entry->next;
++
++	if (entry->pin != -1) {
++		entry->next = first_free_entry;
++		entry = irq_2_pin + entry->next;
++		if (++first_free_entry >= PIN_MAP_SIZE)
++			panic("io_apic.c: whoops");
++	}
++	entry->apic = apic;
++	entry->pin = pin;
++}
++
++#ifdef CONFIG_XEN
++#define clear_IO_APIC() ((void)0)
++#else
++/*
++ * Reroute an IRQ to a different pin.
++ */
++static void __init replace_pin_at_irq(unsigned int irq,
++				      int oldapic, int oldpin,
++				      int newapic, int newpin)
++{
++	struct irq_pin_list *entry = irq_2_pin + irq;
++
++	while (1) {
++		if (entry->apic == oldapic && entry->pin == oldpin) {
++			entry->apic = newapic;
++			entry->pin = newpin;
++		}
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++}
++
++static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable)
++{
++	struct irq_pin_list *entry = irq_2_pin + irq;
++	unsigned int pin, reg;
++
++	for (;;) {
++		pin = entry->pin;
++		if (pin == -1)
++			break;
++		reg = io_apic_read(entry->apic, 0x10 + pin*2);
++		reg &= ~disable;
++		reg |= enable;
++		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++}
++
++/* mask = 1 */
++static void __mask_IO_APIC_irq (unsigned int irq)
++{
++	__modify_IO_APIC_irq(irq, 0x00010000, 0);
++}
++
++/* mask = 0 */
++static void __unmask_IO_APIC_irq (unsigned int irq)
++{
++	__modify_IO_APIC_irq(irq, 0, 0x00010000);
++}
++
++/* mask = 1, trigger = 0 */
++static void __mask_and_edge_IO_APIC_irq (unsigned int irq)
++{
++	__modify_IO_APIC_irq(irq, 0x00010000, 0x00008000);
++}
++
++/* mask = 0, trigger = 1 */
++static void __unmask_and_level_IO_APIC_irq (unsigned int irq)
++{
++	__modify_IO_APIC_irq(irq, 0x00008000, 0x00010000);
++}
++
++static void mask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__mask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void unmask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++	
++	/* Check delivery_mode to be sure we're not clearing an SMI pin */
++	spin_lock_irqsave(&ioapic_lock, flags);
++	*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++	*(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	if (entry.delivery_mode == dest_SMI)
++		return;
++
++	/*
++	 * Disable it in the IO-APIC irq-routing table:
++	 */
++	memset(&entry, 0, sizeof(entry));
++	entry.mask = 1;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void clear_IO_APIC (void)
++{
++	int apic, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++)
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
++			clear_IO_APIC_pin(apic, pin);
++}
++
++#ifdef CONFIG_SMP
++static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
++{
++	unsigned long flags;
++	int pin;
++	struct irq_pin_list *entry = irq_2_pin + irq;
++	unsigned int apicid_value;
++	cpumask_t tmp;
++	
++	cpus_and(tmp, cpumask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	cpus_and(cpumask, tmp, CPU_MASK_ALL);
++
++	apicid_value = cpu_mask_to_apicid(cpumask);
++	/* Prepare to do the io_apic_write */
++	apicid_value = apicid_value << 24;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	for (;;) {
++		pin = entry->pin;
++		if (pin == -1)
++			break;
++		io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value);
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++	set_irq_info(irq, cpumask);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#if defined(CONFIG_IRQBALANCE)
++# include <asm/processor.h>	/* kernel_thread() */
++# include <linux/kernel_stat.h>	/* kstat */
++# include <linux/slab.h>		/* kmalloc() */
++# include <linux/timer.h>	/* time_after() */
++ 
++#ifdef CONFIG_BALANCED_IRQ_DEBUG
++#  define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
++#  define Dprintk(x...) do { TDprintk(x); } while (0)
++# else
++#  define TDprintk(x...) 
++#  define Dprintk(x...) 
++# endif
++
++#define IRQBALANCE_CHECK_ARCH -999
++#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
++#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
++#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
++#define BALANCED_IRQ_LESS_DELTA		(HZ)
++
++static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
++static int physical_balance __read_mostly;
++static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
++
++static struct irq_cpu_info {
++	unsigned long * last_irq;
++	unsigned long * irq_delta;
++	unsigned long irq;
++} irq_cpu_data[NR_CPUS];
++
++#define CPU_IRQ(cpu)		(irq_cpu_data[cpu].irq)
++#define LAST_CPU_IRQ(cpu,irq)   (irq_cpu_data[cpu].last_irq[irq])
++#define IRQ_DELTA(cpu,irq) 	(irq_cpu_data[cpu].irq_delta[irq])
++
++#define IDLE_ENOUGH(cpu,now) \
++	(idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1))
++
++#define IRQ_ALLOWED(cpu, allowed_mask)	cpu_isset(cpu, allowed_mask)
++
++#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
++
++static cpumask_t balance_irq_affinity[NR_IRQS] = {
++	[0 ... NR_IRQS-1] = CPU_MASK_ALL
++};
++
++void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	balance_irq_affinity[irq] = mask;
++}
++
++static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
++			unsigned long now, int direction)
++{
++	int search_idle = 1;
++	int cpu = curr_cpu;
++
++	goto inside;
++
++	do {
++		if (unlikely(cpu == curr_cpu))
++			search_idle = 0;
++inside:
++		if (direction == 1) {
++			cpu++;
++			if (cpu >= NR_CPUS)
++				cpu = 0;
++		} else {
++			cpu--;
++			if (cpu == -1)
++				cpu = NR_CPUS-1;
++		}
++	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
++			(search_idle && !IDLE_ENOUGH(cpu,now)));
++
++	return cpu;
++}
++
++static inline void balance_irq(int cpu, int irq)
++{
++	unsigned long now = jiffies;
++	cpumask_t allowed_mask;
++	unsigned int new_cpu;
++		
++	if (irqbalance_disabled)
++		return; 
++
++	cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
++	new_cpu = move(cpu, allowed_mask, now, 1);
++	if (cpu != new_cpu) {
++		set_pending_irq(irq, cpumask_of_cpu(new_cpu));
++	}
++}
++
++static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
++{
++	int i, j;
++	Dprintk("Rotating IRQs among CPUs.\n");
++	for_each_online_cpu(i) {
++		for (j = 0; j < NR_IRQS; j++) {
++			if (!irq_desc[j].action)
++				continue;
++			/* Is it a significant load ?  */
++			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
++						useful_load_threshold)
++				continue;
++			balance_irq(i, j);
++		}
++	}
++	balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
++		balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);	
++	return;
++}
++
++static void do_irq_balance(void)
++{
++	int i, j;
++	unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
++	unsigned long move_this_load = 0;
++	int max_loaded = 0, min_loaded = 0;
++	int load;
++	unsigned long useful_load_threshold = balanced_irq_interval + 10;
++	int selected_irq;
++	int tmp_loaded, first_attempt = 1;
++	unsigned long tmp_cpu_irq;
++	unsigned long imbalance = 0;
++	cpumask_t allowed_mask, target_cpu_mask, tmp;
++
++	for_each_possible_cpu(i) {
++		int package_index;
++		CPU_IRQ(i) = 0;
++		if (!cpu_online(i))
++			continue;
++		package_index = CPU_TO_PACKAGEINDEX(i);
++		for (j = 0; j < NR_IRQS; j++) {
++			unsigned long value_now, delta;
++			/* Is this an active IRQ? */
++			if (!irq_desc[j].action)
++				continue;
++			if ( package_index == i )
++				IRQ_DELTA(package_index,j) = 0;
++			/* Determine the total count per processor per IRQ */
++			value_now = (unsigned long) kstat_cpu(i).irqs[j];
++
++			/* Determine the activity per processor per IRQ */
++			delta = value_now - LAST_CPU_IRQ(i,j);
++
++			/* Update last_cpu_irq[][] for the next time */
++			LAST_CPU_IRQ(i,j) = value_now;
++
++			/* Ignore IRQs whose rate is less than the clock */
++			if (delta < useful_load_threshold)
++				continue;
++			/* update the load for the processor or package total */
++			IRQ_DELTA(package_index,j) += delta;
++
++			/* Keep track of the higher numbered sibling as well */
++			if (i != package_index)
++				CPU_IRQ(i) += delta;
++			/*
++			 * We have sibling A and sibling B in the package
++			 *
++			 * cpu_irq[A] = load for cpu A + load for cpu B
++			 * cpu_irq[B] = load for cpu B
++			 */
++			CPU_IRQ(package_index) += delta;
++		}
++	}
++	/* Find the least loaded processor package */
++	for_each_online_cpu(i) {
++		if (i != CPU_TO_PACKAGEINDEX(i))
++			continue;
++		if (min_cpu_irq > CPU_IRQ(i)) {
++			min_cpu_irq = CPU_IRQ(i);
++			min_loaded = i;
++		}
++	}
++	max_cpu_irq = ULONG_MAX;
++
++tryanothercpu:
++	/* Look for heaviest loaded processor.
++	 * We may come back to get the next heaviest loaded processor.
++	 * Skip processors with trivial loads.
++	 */
++	tmp_cpu_irq = 0;
++	tmp_loaded = -1;
++	for_each_online_cpu(i) {
++		if (i != CPU_TO_PACKAGEINDEX(i))
++			continue;
++		if (max_cpu_irq <= CPU_IRQ(i)) 
++			continue;
++		if (tmp_cpu_irq < CPU_IRQ(i)) {
++			tmp_cpu_irq = CPU_IRQ(i);
++			tmp_loaded = i;
++		}
++	}
++
++	if (tmp_loaded == -1) {
++ 	 /* In the case of small number of heavy interrupt sources, 
++	  * loading some of the cpus too much. We use Ingo's original 
++	  * approach to rotate them around.
++	  */
++		if (!first_attempt && imbalance >= useful_load_threshold) {
++			rotate_irqs_among_cpus(useful_load_threshold);
++			return;
++		}
++		goto not_worth_the_effort;
++	}
++	
++	first_attempt = 0;		/* heaviest search */
++	max_cpu_irq = tmp_cpu_irq;	/* load */
++	max_loaded = tmp_loaded;	/* processor */
++	imbalance = (max_cpu_irq - min_cpu_irq) / 2;
++	
++	Dprintk("max_loaded cpu = %d\n", max_loaded);
++	Dprintk("min_loaded cpu = %d\n", min_loaded);
++	Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq);
++	Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq);
++	Dprintk("load imbalance = %lu\n", imbalance);
++
++	/* if imbalance is less than approx 10% of max load, then
++	 * observe diminishing returns action. - quit
++	 */
++	if (imbalance < (max_cpu_irq >> 3)) {
++		Dprintk("Imbalance too trivial\n");
++		goto not_worth_the_effort;
++	}
++
++tryanotherirq:
++	/* if we select an IRQ to move that can't go where we want, then
++	 * see if there is another one to try.
++	 */
++	move_this_load = 0;
++	selected_irq = -1;
++	for (j = 0; j < NR_IRQS; j++) {
++		/* Is this an active IRQ? */
++		if (!irq_desc[j].action)
++			continue;
++		if (imbalance <= IRQ_DELTA(max_loaded,j))
++			continue;
++		/* Try to find the IRQ that is closest to the imbalance
++		 * without going over.
++		 */
++		if (move_this_load < IRQ_DELTA(max_loaded,j)) {
++			move_this_load = IRQ_DELTA(max_loaded,j);
++			selected_irq = j;
++		}
++	}
++	if (selected_irq == -1) {
++		goto tryanothercpu;
++	}
++
++	imbalance = move_this_load;
++	
++	/* For physical_balance case, we accumlated both load
++	 * values in the one of the siblings cpu_irq[],
++	 * to use the same code for physical and logical processors
++	 * as much as possible. 
++	 *
++	 * NOTE: the cpu_irq[] array holds the sum of the load for
++	 * sibling A and sibling B in the slot for the lowest numbered
++	 * sibling (A), _AND_ the load for sibling B in the slot for
++	 * the higher numbered sibling.
++	 *
++	 * We seek the least loaded sibling by making the comparison
++	 * (A+B)/2 vs B
++	 */
++	load = CPU_IRQ(min_loaded) >> 1;
++	for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {
++		if (load > CPU_IRQ(j)) {
++			/* This won't change cpu_sibling_map[min_loaded] */
++			load = CPU_IRQ(j);
++			min_loaded = j;
++		}
++	}
++
++	cpus_and(allowed_mask,
++		cpu_online_map,
++		balance_irq_affinity[selected_irq]);
++	target_cpu_mask = cpumask_of_cpu(min_loaded);
++	cpus_and(tmp, target_cpu_mask, allowed_mask);
++
++	if (!cpus_empty(tmp)) {
++
++		Dprintk("irq = %d moved to cpu = %d\n",
++				selected_irq, min_loaded);
++		/* mark for change destination */
++		set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
++
++		/* Since we made a change, come back sooner to 
++		 * check for more variation.
++		 */
++		balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
++			balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);	
++		return;
++	}
++	goto tryanotherirq;
++
++not_worth_the_effort:
++	/*
++	 * if we did not find an IRQ to move, then adjust the time interval
++	 * upward
++	 */
++	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
++		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);	
++	Dprintk("IRQ worth rotating not found\n");
++	return;
++}
++
++static int balanced_irq(void *unused)
++{
++	int i;
++	unsigned long prev_balance_time = jiffies;
++	long time_remaining = balanced_irq_interval;
++
++	daemonize("kirqd");
++	
++	/* push everything to CPU 0 to give us a starting point.  */
++	for (i = 0 ; i < NR_IRQS ; i++) {
++		irq_desc[i].pending_mask = cpumask_of_cpu(0);
++		set_pending_irq(i, cpumask_of_cpu(0));
++	}
++
++	for ( ; ; ) {
++		time_remaining = schedule_timeout_interruptible(time_remaining);
++		try_to_freeze();
++		if (time_after(jiffies,
++				prev_balance_time+balanced_irq_interval)) {
++			preempt_disable();
++			do_irq_balance();
++			prev_balance_time = jiffies;
++			time_remaining = balanced_irq_interval;
++			preempt_enable();
++		}
++	}
++	return 0;
++}
++
++static int __init balanced_irq_init(void)
++{
++	int i;
++	struct cpuinfo_x86 *c;
++	cpumask_t tmp;
++
++	cpus_shift_right(tmp, cpu_online_map, 2);
++        c = &boot_cpu_data;
++	/* When not overwritten by the command line ask subarchitecture. */
++	if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
++		irqbalance_disabled = NO_BALANCE_IRQ;
++	if (irqbalance_disabled)
++		return 0;
++	
++	 /* disable irqbalance completely if there is only one processor online */
++	if (num_online_cpus() < 2) {
++		irqbalance_disabled = 1;
++		return 0;
++	}
++	/*
++	 * Enable physical balance only if more than 1 physical processor
++	 * is present
++	 */
++	if (smp_num_siblings > 1 && !cpus_empty(tmp))
++		physical_balance = 1;
++
++	for_each_online_cpu(i) {
++		irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
++		irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
++		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
++			printk(KERN_ERR "balanced_irq_init: out of memory");
++			goto failed;
++		}
++		memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS);
++		memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS);
++	}
++	
++	printk(KERN_INFO "Starting balanced_irq\n");
++	if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) 
++		return 0;
++	else 
++		printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
++failed:
++	for_each_possible_cpu(i) {
++		kfree(irq_cpu_data[i].irq_delta);
++		irq_cpu_data[i].irq_delta = NULL;
++		kfree(irq_cpu_data[i].last_irq);
++		irq_cpu_data[i].last_irq = NULL;
++	}
++	return 0;
++}
++
++int __init irqbalance_disable(char *str)
++{
++	irqbalance_disabled = 1;
++	return 1;
++}
++
++__setup("noirqbalance", irqbalance_disable);
++
++late_initcall(balanced_irq_init);
++#endif /* CONFIG_IRQBALANCE */
++#endif /* CONFIG_SMP */
++#endif
++
++#ifndef CONFIG_SMP
++void fastcall send_IPI_self(int vector)
++{
++#ifndef CONFIG_XEN
++	unsigned int cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	apic_wait_icr_idle();
++	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write_around(APIC_ICR, cfg);
++#endif
++}
++#endif /* !CONFIG_SMP */
++
++
++/*
++ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
++ * specific CPU-side IRQs.
++ */
++
++#define MAX_PIRQS 8
++static int pirq_entries [MAX_PIRQS];
++static int pirqs_enabled;
++int skip_ioapic_setup;
++
++static int __init ioapic_setup(char *str)
++{
++	skip_ioapic_setup = 1;
++	return 1;
++}
++
++__setup("noapic", ioapic_setup);
++
++static int __init ioapic_pirq_setup(char *str)
++{
++	int i, max;
++	int ints[MAX_PIRQS+1];
++
++	get_options(str, ARRAY_SIZE(ints), ints);
++
++	for (i = 0; i < MAX_PIRQS; i++)
++		pirq_entries[i] = -1;
++
++	pirqs_enabled = 1;
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"PIRQ redirection, working around broken MP-BIOS.\n");
++	max = MAX_PIRQS;
++	if (ints[0] < MAX_PIRQS)
++		max = ints[0];
++
++	for (i = 0; i < max; i++) {
++		apic_printk(APIC_VERBOSE, KERN_DEBUG
++				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
++		/*
++		 * PIRQs are mapped upside down, usually.
++		 */
++		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
++	}
++	return 1;
++}
++
++__setup("pirq=", ioapic_pirq_setup);
++
++/*
++ * Find the IRQ entry number of a certain pin.
++ */
++static int find_irq_entry(int apic, int pin, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mpc_irqtype == type &&
++		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
++		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].mpc_dstirq == pin)
++			return i;
++
++	return -1;
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Find the pin to which IRQ[irq] (ISA) is connected
++ */
++static int __init find_isa_irq_pin(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
++		    ) &&
++		    (mp_irqs[i].mpc_irqtype == type) &&
++		    (mp_irqs[i].mpc_srcbusirq == irq))
++
++			return mp_irqs[i].mpc_dstirq;
++	}
++	return -1;
++}
++
++static int __init find_isa_irq_apic(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
++		    ) &&
++		    (mp_irqs[i].mpc_irqtype == type) &&
++		    (mp_irqs[i].mpc_srcbusirq == irq))
++			break;
++	}
++	if (i < mp_irq_entries) {
++		int apic;
++		for(apic = 0; apic < nr_ioapics; apic++) {
++			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
++				return apic;
++		}
++	}
++
++	return -1;
++}
++#endif
++
++/*
++ * Find a specific PCI IRQ entry.
++ * Not an __init, possibly needed by modules
++ */
++static int pin_2_irq(int idx, int apic, int pin);
++
++int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
++{
++	int apic, i, best_guess = -1;
++
++	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
++		"slot:%d, pin:%d.\n", bus, slot, pin);
++	if (mp_bus_id_to_pci_bus[bus] == -1) {
++		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
++		return -1;
++	}
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		for (apic = 0; apic < nr_ioapics; apic++)
++			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
++			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
++				break;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++		    !mp_irqs[i].mpc_irqtype &&
++		    (bus == lbus) &&
++		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
++
++			if (!(apic || IO_APIC_IRQ(irq)))
++				continue;
++
++			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
++				return irq;
++			/*
++			 * Use the first all-but-pin matching entry as a
++			 * best-guess fuzzy result for broken mptables.
++			 */
++			if (best_guess < 0)
++				best_guess = irq;
++		}
++	}
++	return best_guess;
++}
++EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
++
++/*
++ * This function currently is only a helper for the i386 smp boot process where 
++ * we need to reprogram the ioredtbls to cater for the cpus which have come online
++ * so mask in all cases should simply be TARGET_CPUS
++ */
++#ifdef CONFIG_SMP
++#ifndef CONFIG_XEN
++void __init setup_ioapic_dest(void)
++{
++	int pin, ioapic, irq, irq_entry;
++
++	if (skip_ioapic_setup == 1)
++		return;
++
++	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
++		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
++			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
++			if (irq_entry == -1)
++				continue;
++			irq = pin_2_irq(irq_entry, ioapic, pin);
++			set_ioapic_affinity_irq(irq, TARGET_CPUS);
++		}
++
++	}
++}
++#endif /* !CONFIG_XEN */
++#endif
++
++/*
++ * EISA Edge/Level control register, ELCR
++ */
++static int EISA_ELCR(unsigned int irq)
++{
++	if (irq < 16) {
++		unsigned int port = 0x4d0 + (irq >> 3);
++		return (inb(port) >> (irq & 7)) & 1;
++	}
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"Broken MPtable reports ISA irq %d\n", irq);
++	return 0;
++}
++
++/* EISA interrupts are always polarity zero and can be edge or level
++ * trigger depending on the ELCR value.  If an interrupt is listed as
++ * EISA conforming in the MP table, that means its trigger type must
++ * be read in from the ELCR */
++
++#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
++#define default_EISA_polarity(idx)	(0)
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx)	(0)
++#define default_ISA_polarity(idx)	(0)
++
++/* PCI interrupts are always polarity one level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_PCI_trigger(idx)	(1)
++#define default_PCI_polarity(idx)	(1)
++
++/* MCA interrupts are always polarity zero level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_MCA_trigger(idx)	(1)
++#define default_MCA_polarity(idx)	(0)
++
++/* NEC98 interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_NEC98_trigger(idx)     (0)
++#define default_NEC98_polarity(idx)    (0)
++
++static int __init MPBIOS_polarity(int idx)
++{
++	int bus = mp_irqs[idx].mpc_srcbus;
++	int polarity;
++
++	/*
++	 * Determine IRQ line polarity (high active or low active):
++	 */
++	switch (mp_irqs[idx].mpc_irqflag & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent polarity */
++		{
++			switch (mp_bus_id_to_type[bus])
++			{
++				case MP_BUS_ISA: /* ISA pin */
++				{
++					polarity = default_ISA_polarity(idx);
++					break;
++				}
++				case MP_BUS_EISA: /* EISA pin */
++				{
++					polarity = default_EISA_polarity(idx);
++					break;
++				}
++				case MP_BUS_PCI: /* PCI pin */
++				{
++					polarity = default_PCI_polarity(idx);
++					break;
++				}
++				case MP_BUS_MCA: /* MCA pin */
++				{
++					polarity = default_MCA_polarity(idx);
++					break;
++				}
++				case MP_BUS_NEC98: /* NEC 98 pin */
++				{
++					polarity = default_NEC98_polarity(idx);
++					break;
++				}
++				default:
++				{
++					printk(KERN_WARNING "broken BIOS!!\n");
++					polarity = 1;
++					break;
++				}
++			}
++			break;
++		}
++		case 1: /* high active */
++		{
++			polarity = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++		case 3: /* low active */
++		{
++			polarity = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++	}
++	return polarity;
++}
++
++static int MPBIOS_trigger(int idx)
++{
++	int bus = mp_irqs[idx].mpc_srcbus;
++	int trigger;
++
++	/*
++	 * Determine IRQ trigger mode (edge or level sensitive):
++	 */
++	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent */
++		{
++			switch (mp_bus_id_to_type[bus])
++			{
++				case MP_BUS_ISA: /* ISA pin */
++				{
++					trigger = default_ISA_trigger(idx);
++					break;
++				}
++				case MP_BUS_EISA: /* EISA pin */
++				{
++					trigger = default_EISA_trigger(idx);
++					break;
++				}
++				case MP_BUS_PCI: /* PCI pin */
++				{
++					trigger = default_PCI_trigger(idx);
++					break;
++				}
++				case MP_BUS_MCA: /* MCA pin */
++				{
++					trigger = default_MCA_trigger(idx);
++					break;
++				}
++				case MP_BUS_NEC98: /* NEC 98 pin */
++				{
++					trigger = default_NEC98_trigger(idx);
++					break;
++				}
++				default:
++				{
++					printk(KERN_WARNING "broken BIOS!!\n");
++					trigger = 1;
++					break;
++				}
++			}
++			break;
++		}
++		case 1: /* edge */
++		{
++			trigger = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 1;
++			break;
++		}
++		case 3: /* level */
++		{
++			trigger = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 0;
++			break;
++		}
++	}
++	return trigger;
++}
++
++static inline int irq_polarity(int idx)
++{
++	return MPBIOS_polarity(idx);
++}
++
++static inline int irq_trigger(int idx)
++{
++	return MPBIOS_trigger(idx);
++}
++
++static int pin_2_irq(int idx, int apic, int pin)
++{
++	int irq, i;
++	int bus = mp_irqs[idx].mpc_srcbus;
++
++	/*
++	 * Debugging check, we are in big trouble if this message pops up!
++	 */
++	if (mp_irqs[idx].mpc_dstirq != pin)
++		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
++
++	switch (mp_bus_id_to_type[bus])
++	{
++		case MP_BUS_ISA: /* ISA pin */
++		case MP_BUS_EISA:
++		case MP_BUS_MCA:
++		case MP_BUS_NEC98:
++		{
++			irq = mp_irqs[idx].mpc_srcbusirq;
++			break;
++		}
++		case MP_BUS_PCI: /* PCI pin */
++		{
++			/*
++			 * PCI IRQs are mapped in order
++			 */
++			i = irq = 0;
++			while (i < apic)
++				irq += nr_ioapic_registers[i++];
++			irq += pin;
++
++			/*
++			 * For MPS mode, so far only needed by ES7000 platform
++			 */
++			if (ioapic_renumber_irq)
++				irq = ioapic_renumber_irq(apic, irq);
++
++			break;
++		}
++		default:
++		{
++			printk(KERN_ERR "unknown bus type %d.\n",bus); 
++			irq = 0;
++			break;
++		}
++	}
++
++	/*
++	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
++	 */
++	if ((pin >= 16) && (pin <= 23)) {
++		if (pirq_entries[pin-16] != -1) {
++			if (!pirq_entries[pin-16]) {
++				apic_printk(APIC_VERBOSE, KERN_DEBUG
++						"disabling PIRQ%d\n", pin-16);
++			} else {
++				irq = pirq_entries[pin-16];
++				apic_printk(APIC_VERBOSE, KERN_DEBUG
++						"using PIRQ%d -> IRQ %d\n",
++						pin-16, irq);
++			}
++		}
++	}
++	return irq;
++}
++
++static inline int IO_APIC_irq_trigger(int irq)
++{
++	int apic, idx, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			idx = find_irq_entry(apic,pin,mp_INT);
++			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
++				return irq_trigger(idx);
++		}
++	}
++	/*
++	 * nonexistent IRQs are edge default
++	 */
++	return 0;
++}
++
++/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
++u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */
++
++int assign_irq_vector(int irq)
++{
++	unsigned long flags;
++	int vector;
++	struct physdev_irq irq_op;
++
++	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
++
++	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
++		return -EINVAL;
++
++	spin_lock_irqsave(&vector_lock, flags);
++
++	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
++		spin_unlock_irqrestore(&vector_lock, flags);
++		return IO_APIC_VECTOR(irq);
++	}
++
++	irq_op.irq = irq;
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
++		spin_unlock_irqrestore(&vector_lock, flags);
++		return -ENOSPC;
++	}
++
++	vector = irq_op.vector;
++	vector_irq[vector] = irq;
++	if (irq != AUTO_ASSIGN)
++		IO_APIC_VECTOR(irq) = vector;
++
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	return vector;
++}
++
++#ifndef CONFIG_XEN
++static struct hw_interrupt_type ioapic_level_type;
++static struct hw_interrupt_type ioapic_edge_type;
++
++#define IOAPIC_AUTO	-1
++#define IOAPIC_EDGE	0
++#define IOAPIC_LEVEL	1
++
++static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
++{
++	unsigned idx;
++
++	idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
++
++	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++			trigger == IOAPIC_LEVEL)
++		irq_desc[idx].chip = &ioapic_level_type;
++	else
++		irq_desc[idx].chip = &ioapic_edge_type;
++	set_intr_gate(vector, interrupt[idx]);
++}
++#else
++#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
++#endif
++
++static void __init setup_IO_APIC_irqs(void)
++{
++	struct IO_APIC_route_entry entry;
++	int apic, pin, idx, irq, first_notcon = 1, vector;
++	unsigned long flags;
++
++	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++
++		/*
++		 * add it to the IO-APIC irq-routing table:
++		 */
++		memset(&entry,0,sizeof(entry));
++
++		entry.delivery_mode = INT_DELIVERY_MODE;
++		entry.dest_mode = INT_DEST_MODE;
++		entry.mask = 0;				/* enable IRQ */
++		entry.dest.logical.logical_dest = 
++					cpu_mask_to_apicid(TARGET_CPUS);
++
++		idx = find_irq_entry(apic,pin,mp_INT);
++		if (idx == -1) {
++			if (first_notcon) {
++				apic_printk(APIC_VERBOSE, KERN_DEBUG
++						" IO-APIC (apicid-pin) %d-%d",
++						mp_ioapics[apic].mpc_apicid,
++						pin);
++				first_notcon = 0;
++			} else
++				apic_printk(APIC_VERBOSE, ", %d-%d",
++					mp_ioapics[apic].mpc_apicid, pin);
++			continue;
++		}
++
++		entry.trigger = irq_trigger(idx);
++		entry.polarity = irq_polarity(idx);
++
++		if (irq_trigger(idx)) {
++			entry.trigger = 1;
++			entry.mask = 1;
++		}
++
++		irq = pin_2_irq(idx, apic, pin);
++		/*
++		 * skip adding the timer int on secondary nodes, which causes
++		 * a small but painful rift in the time-space continuum
++		 */
++		if (multi_timer_check(apic, irq))
++			continue;
++		else
++			add_pin_to_irq(irq, apic, pin);
++
++		if (/*!apic &&*/ !IO_APIC_IRQ(irq))
++			continue;
++
++		if (IO_APIC_IRQ(irq)) {
++			vector = assign_irq_vector(irq);
++			entry.vector = vector;
++			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
++		
++			if (!apic && (irq < 16))
++				disable_8259A_irq(irq);
++		}
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
++		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
++		set_native_irq_info(irq, TARGET_CPUS);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++	}
++	}
++
++	if (!first_notcon)
++		apic_printk(APIC_VERBOSE, " not connected.\n");
++}
++
++/*
++ * Set up the 8259A-master output pin:
++ */
++#ifndef CONFIG_XEN
++static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++
++	memset(&entry,0,sizeof(entry));
++
++	disable_8259A_irq(0);
++
++	/* mask LVT0 */
++	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++
++	/*
++	 * We use logical delivery to get the timer IRQ
++	 * to the first CPU.
++	 */
++	entry.dest_mode = INT_DEST_MODE;
++	entry.mask = 0;					/* unmask IRQ now */
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.polarity = 0;
++	entry.trigger = 0;
++	entry.vector = vector;
++
++	/*
++	 * The timer IRQ doesn't have to know that behind the
++	 * scene we have a 8259A-master in AEOI mode ...
++	 */
++	irq_desc[0].chip = &ioapic_edge_type;
++
++	/*
++	 * Add it to the IO-APIC irq-routing table:
++	 */
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
++	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	enable_8259A_irq(0);
++}
++
++static inline void UNEXPECTED_IO_APIC(void)
++{
++}
++
++void __init print_IO_APIC(void)
++{
++	int apic, i;
++	union IO_APIC_reg_00 reg_00;
++	union IO_APIC_reg_01 reg_01;
++	union IO_APIC_reg_02 reg_02;
++	union IO_APIC_reg_03 reg_03;
++	unsigned long flags;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++ 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
++	for (i = 0; i < nr_ioapics; i++)
++		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
++		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
++
++	/*
++	 * We are a bit conservative about what we expect.  We have to
++	 * know about every hardware change ASAP.
++	 */
++	printk(KERN_INFO "testing the IO APIC.......................\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(apic, 0);
++	reg_01.raw = io_apic_read(apic, 1);
++	if (reg_01.bits.version >= 0x10)
++		reg_02.raw = io_apic_read(apic, 2);
++	if (reg_01.bits.version >= 0x20)
++		reg_03.raw = io_apic_read(apic, 3);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
++	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
++	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
++	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
++	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
++	if (reg_00.bits.ID >= get_physical_broadcast())
++		UNEXPECTED_IO_APIC();
++	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
++		UNEXPECTED_IO_APIC();
++
++	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
++	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
++	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
++		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
++		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
++		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
++		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
++		(reg_01.bits.entries != 0x2E) &&
++		(reg_01.bits.entries != 0x3F)
++	)
++		UNEXPECTED_IO_APIC();
++
++	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
++	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
++	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
++		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
++		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
++		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
++		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
++	)
++		UNEXPECTED_IO_APIC();
++	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
++		UNEXPECTED_IO_APIC();
++
++	/*
++	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
++	 * but the value of reg_02 is read as the previous read register
++	 * value, so ignore it if reg_02 == reg_01.
++	 */
++	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
++		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
++		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
++		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
++			UNEXPECTED_IO_APIC();
++	}
++
++	/*
++	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
++	 * or reg_03, but the value of reg_0[23] is read as the previous read
++	 * register value, so ignore it if reg_03 == reg_0[12].
++	 */
++	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
++	    reg_03.raw != reg_01.raw) {
++		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
++		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
++		if (reg_03.bits.__reserved_1)
++			UNEXPECTED_IO_APIC();
++	}
++
++	printk(KERN_DEBUG ".... IRQ redirection table:\n");
++
++	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
++			  " Stat Dest Deli Vect:   \n");
++
++	for (i = 0; i <= reg_01.bits.entries; i++) {
++		struct IO_APIC_route_entry entry;
++
++		spin_lock_irqsave(&ioapic_lock, flags);
++		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
++		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		printk(KERN_DEBUG " %02x %03X %02X  ",
++			i,
++			entry.dest.logical.logical_dest,
++			entry.dest.physical.physical_dest
++		);
++
++		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
++			entry.mask,
++			entry.trigger,
++			entry.irr,
++			entry.polarity,
++			entry.delivery_status,
++			entry.dest_mode,
++			entry.delivery_mode,
++			entry.vector
++		);
++	}
++	}
++	if (use_pci_vector())
++		printk(KERN_INFO "Using vector-based indexing\n");
++	printk(KERN_DEBUG "IRQ to pin mappings:\n");
++	for (i = 0; i < NR_IRQS; i++) {
++		struct irq_pin_list *entry = irq_2_pin + i;
++		if (entry->pin < 0)
++			continue;
++ 		if (use_pci_vector() && !platform_legacy_irq(i))
++			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
++		else
++			printk(KERN_DEBUG "IRQ%d ", i);
++		for (;;) {
++			printk("-> %d:%d", entry->apic, entry->pin);
++			if (!entry->next)
++				break;
++			entry = irq_2_pin + entry->next;
++		}
++		printk("\n");
++	}
++
++	printk(KERN_INFO ".................................... done.\n");
++
++	return;
++}
++
++static void print_APIC_bitfield (int base)
++{
++	unsigned int v;
++	int i, j;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
++	for (i = 0; i < 8; i++) {
++		v = apic_read(base + i*0x10);
++		for (j = 0; j < 32; j++) {
++			if (v & (1<<j))
++				printk("1");
++			else
++				printk("0");
++		}
++		printk("\n");
++	}
++}
++
++void /*__init*/ print_local_APIC(void * dummy)
++{
++	unsigned int v, ver, maxlvt;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
++		smp_processor_id(), hard_smp_processor_id());
++	v = apic_read(APIC_ID);
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	v = apic_read(APIC_LVR);
++	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
++	ver = GET_APIC_VERSION(v);
++	maxlvt = get_maxlvt();
++
++	v = apic_read(APIC_TASKPRI);
++	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
++
++	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
++		v = apic_read(APIC_ARBPRI);
++		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
++			v & APIC_ARBPRI_MASK);
++		v = apic_read(APIC_PROCPRI);
++		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
++	}
++
++	v = apic_read(APIC_EOI);
++	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
++	v = apic_read(APIC_RRR);
++	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
++	v = apic_read(APIC_LDR);
++	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
++	v = apic_read(APIC_DFR);
++	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
++	v = apic_read(APIC_SPIV);
++	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
++
++	printk(KERN_DEBUG "... APIC ISR field:\n");
++	print_APIC_bitfield(APIC_ISR);
++	printk(KERN_DEBUG "... APIC TMR field:\n");
++	print_APIC_bitfield(APIC_TMR);
++	printk(KERN_DEBUG "... APIC IRR field:\n");
++	print_APIC_bitfield(APIC_IRR);
++
++	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
++		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
++			apic_write(APIC_ESR, 0);
++		v = apic_read(APIC_ESR);
++		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
++	}
++
++	v = apic_read(APIC_ICR);
++	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
++	v = apic_read(APIC_ICR2);
++	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
++
++	v = apic_read(APIC_LVTT);
++	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
++
++	if (maxlvt > 3) {                       /* PC is LVT#4. */
++		v = apic_read(APIC_LVTPC);
++		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
++	}
++	v = apic_read(APIC_LVT0);
++	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
++	v = apic_read(APIC_LVT1);
++	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
++
++	if (maxlvt > 2) {			/* ERR is LVT#3. */
++		v = apic_read(APIC_LVTERR);
++		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
++	}
++
++	v = apic_read(APIC_TMICT);
++	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
++	v = apic_read(APIC_TMCCT);
++	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
++	v = apic_read(APIC_TDCR);
++	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
++	printk("\n");
++}
++
++void print_all_local_APICs (void)
++{
++	on_each_cpu(print_local_APIC, NULL, 1, 1);
++}
++
++void /*__init*/ print_PIC(void)
++{
++	unsigned int v;
++	unsigned long flags;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "\nprinting PIC contents\n");
++
++	spin_lock_irqsave(&i8259A_lock, flags);
++
++	v = inb(0xa1) << 8 | inb(0x21);
++	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
++
++	v = inb(0xa0) << 8 | inb(0x20);
++	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
++
++	outb(0x0b,0xa0);
++	outb(0x0b,0x20);
++	v = inb(0xa0) << 8 | inb(0x20);
++	outb(0x0a,0xa0);
++	outb(0x0a,0x20);
++
++	spin_unlock_irqrestore(&i8259A_lock, flags);
++
++	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
++
++	v = inb(0x4d1) << 8 | inb(0x4d0);
++	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
++}
++#endif /* !CONFIG_XEN */
++
++static void __init enable_IO_APIC(void)
++{
++	union IO_APIC_reg_01 reg_01;
++#ifndef CONFIG_XEN
++	int i8259_apic, i8259_pin;
++#endif
++	int i, apic;
++	unsigned long flags;
++
++	for (i = 0; i < PIN_MAP_SIZE; i++) {
++		irq_2_pin[i].pin = -1;
++		irq_2_pin[i].next = 0;
++	}
++	if (!pirqs_enabled)
++		for (i = 0; i < MAX_PIRQS; i++)
++			pirq_entries[i] = -1;
++
++	/*
++	 * The number of IO-APIC IRQ registers (== #pins):
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_01.raw = io_apic_read(apic, 1);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
++	}
++#ifndef CONFIG_XEN
++	for(apic = 0; apic < nr_ioapics; apic++) {
++		int pin;
++		/* See if any of the pins is in ExtINT mode */
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			struct IO_APIC_route_entry entry;
++			spin_lock_irqsave(&ioapic_lock, flags);
++			*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++			*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++			spin_unlock_irqrestore(&ioapic_lock, flags);
++
++
++			/* If the interrupt line is enabled and in ExtInt mode
++			 * I have found the pin where the i8259 is connected.
++			 */
++			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
++				ioapic_i8259.apic = apic;
++				ioapic_i8259.pin  = pin;
++				goto found_i8259;
++			}
++		}
++	}
++ found_i8259:
++	/* Look to see what if the MP table has reported the ExtINT */
++	/* If we could not find the appropriate pin by looking at the ioapic
++	 * the i8259 probably is not connected the ioapic but give the
++	 * mptable a chance anyway.
++	 */
++	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
++	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
++	/* Trust the MP table if nothing is setup in the hardware */
++	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
++		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
++		ioapic_i8259.pin  = i8259_pin;
++		ioapic_i8259.apic = i8259_apic;
++	}
++	/* Complain if the MP table and the hardware disagree */
++	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
++		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
++	{
++		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
++	}
++#endif
++
++	/*
++	 * Do not trust the IO-APIC being empty at bootup
++	 */
++	clear_IO_APIC();
++}
++
++/*
++ * Not an __init, needed by the reboot code
++ */
++void disable_IO_APIC(void)
++{
++	/*
++	 * Clear the IO-APIC before rebooting:
++	 */
++	clear_IO_APIC();
++
++#ifndef CONFIG_XEN
++	/*
++	 * If the i8259 is routed through an IOAPIC
++	 * Put that IOAPIC in virtual wire mode
++	 * so legacy interrupts can be delivered.
++	 */
++	if (ioapic_i8259.pin != -1) {
++		struct IO_APIC_route_entry entry;
++		unsigned long flags;
++
++		memset(&entry, 0, sizeof(entry));
++		entry.mask            = 0; /* Enabled */
++		entry.trigger         = 0; /* Edge */
++		entry.irr             = 0;
++		entry.polarity        = 0; /* High */
++		entry.delivery_status = 0;
++		entry.dest_mode       = 0; /* Physical */
++		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
++		entry.vector          = 0;
++		entry.dest.physical.physical_dest =
++					GET_APIC_ID(apic_read(APIC_ID));
++
++		/*
++		 * Add it to the IO-APIC irq-routing table:
++		 */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
++			*(((int *)&entry)+1));
++		io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
++			*(((int *)&entry)+0));
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++	}
++	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
++#endif
++}
++
++/*
++ * function to set the IO-APIC physical IDs based on the
++ * values stored in the MPC table.
++ *
++ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
++ */
++
++#if !defined(CONFIG_XEN) && !defined(CONFIG_X86_NUMAQ)
++static void __init setup_ioapic_ids_from_mpc(void)
++{
++	union IO_APIC_reg_00 reg_00;
++	physid_mask_t phys_id_present_map;
++	int apic;
++	int i;
++	unsigned char old_id;
++	unsigned long flags;
++
++	/*
++	 * Don't check I/O APIC IDs for xAPIC systems.  They have
++	 * no meaning without the serial APIC bus.
++	 */
++	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		return;
++	/*
++	 * This is broken; anything with a real cpu count has to
++	 * circumvent this idiocy regardless.
++	 */
++	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
++
++	/*
++	 * Set the IOAPIC ID to the value stored in the MPC table.
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++		/* Read the register 0 value */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		
++		old_id = mp_ioapics[apic].mpc_apicid;
++
++		if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) {
++			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
++				apic, mp_ioapics[apic].mpc_apicid);
++			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
++				reg_00.bits.ID);
++			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
++		}
++
++		/*
++		 * Sanity check, is the ID really free? Every APIC in a
++		 * system must have a unique ID or we get lots of nice
++		 * 'stuck on smp_invalidate_needed IPI wait' messages.
++		 */
++		if (check_apicid_used(phys_id_present_map,
++					mp_ioapics[apic].mpc_apicid)) {
++			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
++				apic, mp_ioapics[apic].mpc_apicid);
++			for (i = 0; i < get_physical_broadcast(); i++)
++				if (!physid_isset(i, phys_id_present_map))
++					break;
++			if (i >= get_physical_broadcast())
++				panic("Max APIC ID exceeded!\n");
++			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
++				i);
++			physid_set(i, phys_id_present_map);
++			mp_ioapics[apic].mpc_apicid = i;
++		} else {
++			physid_mask_t tmp;
++			tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid);
++			apic_printk(APIC_VERBOSE, "Setting %d in the "
++					"phys_id_present_map\n",
++					mp_ioapics[apic].mpc_apicid);
++			physids_or(phys_id_present_map, phys_id_present_map, tmp);
++		}
++
++
++		/*
++		 * We need to adjust the IRQ routing table
++		 * if the ID changed.
++		 */
++		if (old_id != mp_ioapics[apic].mpc_apicid)
++			for (i = 0; i < mp_irq_entries; i++)
++				if (mp_irqs[i].mpc_dstapic == old_id)
++					mp_irqs[i].mpc_dstapic
++						= mp_ioapics[apic].mpc_apicid;
++
++		/*
++		 * Read the right value from the MPC table and
++		 * write it into the ID register.
++	 	 */
++		apic_printk(APIC_VERBOSE, KERN_INFO
++			"...changing IO-APIC physical APIC ID to %d ...",
++			mp_ioapics[apic].mpc_apicid);
++
++		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(apic, 0, reg_00.raw);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		/*
++		 * Sanity check
++		 */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
++			printk("could not set ID!\n");
++		else
++			apic_printk(APIC_VERBOSE, " ok.\n");
++	}
++}
++#else
++static void __init setup_ioapic_ids_from_mpc(void) { }
++#endif
++
++#ifndef CONFIG_XEN
++/*
++ * There is a nasty bug in some older SMP boards, their mptable lies
++ * about the timer IRQ. We do the following to work around the situation:
++ *
++ *	- timer IRQ defaults to IO-APIC IRQ
++ *	- if this function detects that timer IRQs are defunct, then we fall
++ *	  back to ISA timer IRQs
++ */
++static int __init timer_irq_works(void)
++{
++	unsigned long t1 = jiffies;
++
++	local_irq_enable();
++	/* Let ten ticks pass... */
++	mdelay((10 * 1000) / HZ);
++
++	/*
++	 * Expect a few ticks at least, to be sure some possible
++	 * glue logic does not lock up after one or two first
++	 * ticks in a non-ExtINT mode.  Also the local APIC
++	 * might have cached one ExtINT interrupt.  Finally, at
++	 * least one tick may be lost due to delays.
++	 */
++	if (jiffies - t1 > 4)
++		return 1;
++
++	return 0;
++}
++
++/*
++ * In the SMP+IOAPIC case it might happen that there are an unspecified
++ * number of pending IRQ events unhandled. These cases are very rare,
++ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
++ * better to do it this way as thus we do not have to be aware of
++ * 'pending' interrupts in the IRQ path, except at this point.
++ */
++/*
++ * Edge triggered needs to resend any interrupt
++ * that was delayed but this is now handled in the device
++ * independent code.
++ */
++
++/*
++ * Starting up a edge-triggered IO-APIC interrupt is
++ * nasty - we need to make sure that we get the edge.
++ * If it is already asserted for some reason, we need
++ * return 1 to indicate that is was pending.
++ *
++ * This is not complete - we should be able to fake
++ * an edge even if it isn't on the 8259A...
++ */
++static unsigned int startup_edge_ioapic_irq(unsigned int irq)
++{
++	int was_pending = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	if (irq < 16) {
++		disable_8259A_irq(irq);
++		if (i8259A_irq_pending(irq))
++			was_pending = 1;
++	}
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return was_pending;
++}
++
++/*
++ * Once we have recorded IRQ_PENDING already, we can mask the
++ * interrupt for real. This prevents IRQ storms from unhandled
++ * devices.
++ */
++static void ack_edge_ioapic_irq(unsigned int irq)
++{
++	move_irq(irq);
++	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
++					== (IRQ_PENDING | IRQ_DISABLED))
++		mask_IO_APIC_irq(irq);
++	ack_APIC_irq();
++}
++
++/*
++ * Level triggered interrupts can just be masked,
++ * and shutting down and starting up the interrupt
++ * is the same as enabling and disabling them -- except
++ * with a startup need to return a "was pending" value.
++ *
++ * Level triggered interrupts are special because we
++ * do not touch any IO-APIC register while handling
++ * them. We ack the APIC in the end-IRQ handler, not
++ * in the start-IRQ-handler. Protection against reentrance
++ * from the same interrupt is still provided, both by the
++ * generic IRQ layer and by the fact that an unacked local
++ * APIC does not accept IRQs.
++ */
++static unsigned int startup_level_ioapic_irq (unsigned int irq)
++{
++	unmask_IO_APIC_irq(irq);
++
++	return 0; /* don't check for pending */
++}
++
++static void end_level_ioapic_irq (unsigned int irq)
++{
++	unsigned long v;
++	int i;
++
++	move_irq(irq);
++/*
++ * It appears there is an erratum which affects at least version 0x11
++ * of I/O APIC (that's the 82093AA and cores integrated into various
++ * chipsets).  Under certain conditions a level-triggered interrupt is
++ * erroneously delivered as edge-triggered one but the respective IRR
++ * bit gets set nevertheless.  As a result the I/O unit expects an EOI
++ * message but it will never arrive and further interrupts are blocked
++ * from the source.  The exact reason is so far unknown, but the
++ * phenomenon was observed when two consecutive interrupt requests
++ * from a given source get delivered to the same CPU and the source is
++ * temporarily disabled in between.
++ *
++ * A workaround is to simulate an EOI message manually.  We achieve it
++ * by setting the trigger mode to edge and then to level when the edge
++ * trigger mode gets detected in the TMR of a local APIC for a
++ * level-triggered interrupt.  We mask the source for the time of the
++ * operation to prevent an edge-triggered interrupt escaping meanwhile.
++ * The idea is from Manfred Spraul.  --macro
++ */
++	i = IO_APIC_VECTOR(irq);
++
++	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
++
++	ack_APIC_irq();
++
++	if (!(v & (1 << (i & 0x1f)))) {
++		atomic_inc(&irq_mis_count);
++		spin_lock(&ioapic_lock);
++		__mask_and_edge_IO_APIC_irq(irq);
++		__unmask_and_level_IO_APIC_irq(irq);
++		spin_unlock(&ioapic_lock);
++	}
++}
++
++#ifdef CONFIG_PCI_MSI
++static unsigned int startup_edge_ioapic_vector(unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	return startup_edge_ioapic_irq(irq);
++}
++
++static void ack_edge_ioapic_vector(unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	move_native_irq(vector);
++	ack_edge_ioapic_irq(irq);
++}
++
++static unsigned int startup_level_ioapic_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	return startup_level_ioapic_irq (irq);
++}
++
++static void end_level_ioapic_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	move_native_irq(vector);
++	end_level_ioapic_irq(irq);
++}
++
++static void mask_IO_APIC_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	mask_IO_APIC_irq(irq);
++}
++
++static void unmask_IO_APIC_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	unmask_IO_APIC_irq(irq);
++}
++
++#ifdef CONFIG_SMP
++static void set_ioapic_affinity_vector (unsigned int vector,
++					cpumask_t cpu_mask)
++{
++	int irq = vector_to_irq(vector);
++
++	set_native_irq_info(vector, cpu_mask);
++	set_ioapic_affinity_irq(irq, cpu_mask);
++}
++#endif
++#endif
++
++static int ioapic_retrigger(unsigned int irq)
++{
++	send_IPI_self(IO_APIC_VECTOR(irq));
++
++	return 1;
++}
++
++/*
++ * Level and edge triggered IO-APIC interrupts need different handling,
++ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
++ * handled with the level-triggered descriptor, but that one has slightly
++ * more overhead. Level-triggered interrupts cannot be handled with the
++ * edge-triggered handler, without risking IRQ storms and other ugly
++ * races.
++ */
++static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
++	.typename 	= "IO-APIC-edge",
++	.startup 	= startup_edge_ioapic,
++	.shutdown 	= shutdown_edge_ioapic,
++	.enable 	= enable_edge_ioapic,
++	.disable 	= disable_edge_ioapic,
++	.ack 		= ack_edge_ioapic,
++	.end 		= end_edge_ioapic,
++#ifdef CONFIG_SMP
++	.set_affinity 	= set_ioapic_affinity,
++#endif
++	.retrigger	= ioapic_retrigger,
++};
++
++static struct hw_interrupt_type ioapic_level_type __read_mostly = {
++	.typename 	= "IO-APIC-level",
++	.startup 	= startup_level_ioapic,
++	.shutdown 	= shutdown_level_ioapic,
++	.enable 	= enable_level_ioapic,
++	.disable 	= disable_level_ioapic,
++	.ack 		= mask_and_ack_level_ioapic,
++	.end 		= end_level_ioapic,
++#ifdef CONFIG_SMP
++	.set_affinity 	= set_ioapic_affinity,
++#endif
++	.retrigger	= ioapic_retrigger,
++};
++#endif /* !CONFIG_XEN */
++
++static inline void init_IO_APIC_traps(void)
++{
++	int irq;
++
++	/*
++	 * NOTE! The local APIC isn't very good at handling
++	 * multiple interrupts at the same interrupt level.
++	 * As the interrupt level is determined by taking the
++	 * vector number and shifting that right by 4, we
++	 * want to spread these out a bit so that they don't
++	 * all fall in the same interrupt level.
++	 *
++	 * Also, we've got to be careful not to trash gate
++	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
++	 */
++	for (irq = 0; irq < NR_IRQS ; irq++) {
++		int tmp = irq;
++		if (use_pci_vector()) {
++			if (!platform_legacy_irq(tmp))
++				if ((tmp = vector_to_irq(tmp)) == -1)
++					continue;
++		}
++		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
++			/*
++			 * Hmm.. We don't have an entry for this,
++			 * so default to an old-fashioned 8259
++			 * interrupt if we can..
++			 */
++			if (irq < 16)
++				make_8259A_irq(irq);
++#ifndef CONFIG_XEN
++			else
++				/* Strange. Oh, well.. */
++				irq_desc[irq].chip = &no_irq_type;
++#endif
++		}
++	}
++}
++
++#ifndef CONFIG_XEN
++static void enable_lapic_irq (unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
++}
++
++static void disable_lapic_irq (unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
++}
++
++static void ack_lapic_irq (unsigned int irq)
++{
++	ack_APIC_irq();
++}
++
++static void end_lapic_irq (unsigned int i) { /* nothing */ }
++
++static struct hw_interrupt_type lapic_irq_type __read_mostly = {
++	.typename 	= "local-APIC-edge",
++	.startup 	= NULL, /* startup_irq() not used for IRQ0 */
++	.shutdown 	= NULL, /* shutdown_irq() not used for IRQ0 */
++	.enable 	= enable_lapic_irq,
++	.disable 	= disable_lapic_irq,
++	.ack 		= ack_lapic_irq,
++	.end 		= end_lapic_irq
++};
++
++static void setup_nmi (void)
++{
++	/*
++ 	 * Dirty trick to enable the NMI watchdog ...
++	 * We put the 8259A master into AEOI mode and
++	 * unmask on all local APICs LVT0 as NMI.
++	 *
++	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
++	 * is from Maciej W. Rozycki - so we do not have to EOI from
++	 * the NMI handler or the timer interrupt.
++	 */ 
++	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
++
++	on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
++
++	apic_printk(APIC_VERBOSE, " done.\n");
++}
++
++/*
++ * This looks a bit hackish but it's about the only one way of sending
++ * a few INTA cycles to 8259As and any associated glue logic.  ICR does
++ * not support the ExtINT mode, unfortunately.  We need to send these
++ * cycles as some i82489DX-based boards have glue logic that keeps the
++ * 8259A interrupt line asserted until INTA.  --macro
++ */
++static inline void unlock_ExtINT_logic(void)
++{
++	int apic, pin, i;
++	struct IO_APIC_route_entry entry0, entry1;
++	unsigned char save_control, save_freq_select;
++	unsigned long flags;
++
++	pin  = find_isa_irq_pin(8, mp_INT);
++	apic = find_isa_irq_apic(8, mp_INT);
++	if (pin == -1)
++		return;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	clear_IO_APIC_pin(apic, pin);
++
++	memset(&entry1, 0, sizeof(entry1));
++
++	entry1.dest_mode = 0;			/* physical delivery */
++	entry1.mask = 0;			/* unmask IRQ now */
++	entry1.dest.physical.physical_dest = hard_smp_processor_id();
++	entry1.delivery_mode = dest_ExtINT;
++	entry1.polarity = entry0.polarity;
++	entry1.trigger = 0;
++	entry1.vector = 0;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	save_control = CMOS_READ(RTC_CONTROL);
++	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
++	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
++		   RTC_FREQ_SELECT);
++	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
++
++	i = 100;
++	while (i-- > 0) {
++		mdelay(10);
++		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
++			i -= 10;
++	}
++
++	CMOS_WRITE(save_control, RTC_CONTROL);
++	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
++	clear_IO_APIC_pin(apic, pin);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++int timer_uses_ioapic_pin_0;
++
++/*
++ * This code may look a bit paranoid, but it's supposed to cooperate with
++ * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
++ * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
++ * fanatically on his truly buggy board.
++ */
++static inline void check_timer(void)
++{
++	int apic1, pin1, apic2, pin2;
++	int vector;
++
++	/*
++	 * get/set the timer IRQ vector:
++	 */
++	disable_8259A_irq(0);
++	vector = assign_irq_vector(0);
++	set_intr_gate(vector, interrupt[0]);
++
++	/*
++	 * Subtle, code in do_timer_interrupt() expects an AEOI
++	 * mode for the 8259A whenever interrupts are routed
++	 * through I/O APICs.  Also IRQ0 has to be enabled in
++	 * the 8259A which implies the virtual wire has to be
++	 * disabled in the local APIC.
++	 */
++	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++	init_8259A(1);
++	timer_ack = 1;
++	if (timer_over_8254 > 0)
++		enable_8259A_irq(0);
++
++	pin1  = find_isa_irq_pin(0, mp_INT);
++	apic1 = find_isa_irq_apic(0, mp_INT);
++	pin2  = ioapic_i8259.pin;
++	apic2 = ioapic_i8259.apic;
++
++	if (pin1 == 0)
++		timer_uses_ioapic_pin_0 = 1;
++
++	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
++		vector, apic1, pin1, apic2, pin2);
++
++	if (pin1 != -1) {
++		/*
++		 * Ok, does IRQ0 through the IOAPIC work?
++		 */
++		unmask_IO_APIC_irq(0);
++		if (timer_irq_works()) {
++			if (nmi_watchdog == NMI_IO_APIC) {
++				disable_8259A_irq(0);
++				setup_nmi();
++				enable_8259A_irq(0);
++			}
++			if (disable_timer_pin_1 > 0)
++				clear_IO_APIC_pin(0, pin1);
++			return;
++		}
++		clear_IO_APIC_pin(apic1, pin1);
++		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
++				"IO-APIC\n");
++	}
++
++	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
++	if (pin2 != -1) {
++		printk("\n..... (found pin %d) ...", pin2);
++		/*
++		 * legacy devices should be connected to IO APIC #0
++		 */
++		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
++		if (timer_irq_works()) {
++			printk("works.\n");
++			if (pin1 != -1)
++				replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
++			else
++				add_pin_to_irq(0, apic2, pin2);
++			if (nmi_watchdog == NMI_IO_APIC) {
++				setup_nmi();
++			}
++			return;
++		}
++		/*
++		 * Cleanup, just in case ...
++		 */
++		clear_IO_APIC_pin(apic2, pin2);
++	}
++	printk(" failed.\n");
++
++	if (nmi_watchdog == NMI_IO_APIC) {
++		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
++		nmi_watchdog = 0;
++	}
++
++	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
++
++	disable_8259A_irq(0);
++	irq_desc[0].chip = &lapic_irq_type;
++	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
++	enable_8259A_irq(0);
++
++	if (timer_irq_works()) {
++		printk(" works.\n");
++		return;
++	}
++	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
++	printk(" failed.\n");
++
++	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
++
++	timer_ack = 0;
++	init_8259A(0);
++	make_8259A_irq(0);
++	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
++
++	unlock_ExtINT_logic();
++
++	if (timer_irq_works()) {
++		printk(" works.\n");
++		return;
++	}
++	printk(" failed :(.\n");
++	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
++		"report.  Then try booting with the 'noapic' option");
++}
++#else
++int timer_uses_ioapic_pin_0 = 0;
++#define check_timer() ((void)0)
++#endif
++
++/*
++ *
++ * IRQ's that are handled by the PIC in the MPS IOAPIC case.
++ * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
++ *   Linux doesn't really care, as it's not actually used
++ *   for any interrupt handling anyway.
++ */
++#define PIC_IRQS	(1 << PIC_CASCADE_IR)
++
++void __init setup_IO_APIC(void)
++{
++	enable_IO_APIC();
++
++	if (acpi_ioapic)
++		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
++	else
++		io_apic_irqs = ~PIC_IRQS;
++
++	printk("ENABLING IO-APIC IRQs\n");
++
++	/*
++	 * Set up IO-APIC IRQ routing.
++	 */
++	if (!acpi_ioapic)
++		setup_ioapic_ids_from_mpc();
++#ifndef CONFIG_XEN
++	sync_Arb_IDs();
++#endif
++	setup_IO_APIC_irqs();
++	init_IO_APIC_traps();
++	check_timer();
++	if (!acpi_ioapic)
++		print_IO_APIC();
++}
++
++static int __init setup_disable_8254_timer(char *s)
++{
++	timer_over_8254 = -1;
++	return 1;
++}
++static int __init setup_enable_8254_timer(char *s)
++{
++	timer_over_8254 = 2;
++	return 1;
++}
++
++__setup("disable_8254_timer", setup_disable_8254_timer);
++__setup("enable_8254_timer", setup_enable_8254_timer);
++
++/*
++ *	Called after all the initialization is done. If we didnt find any
++ *	APIC bugs then we can allow the modify fast path
++ */
++ 
++static int __init io_apic_bug_finalize(void)
++{
++	if(sis_apic_bug == -1)
++		sis_apic_bug = 0;
++	if (is_initial_xendomain()) {
++		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
++		op.u.platform_quirk.quirk_id = sis_apic_bug ?
++			QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
++		VOID(HYPERVISOR_platform_op(&op));
++	}
++	return 0;
++}
++
++late_initcall(io_apic_bug_finalize);
++
++#ifndef CONFIG_XEN
++
++struct sysfs_ioapic_data {
++	struct sys_device dev;
++	struct IO_APIC_route_entry entry[0];
++};
++static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
++
++static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	unsigned long flags;
++	int i;
++	
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
++		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
++		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++static int ioapic_resume(struct sys_device *dev)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	unsigned long flags;
++	union IO_APIC_reg_00 reg_00;
++	int i;
++	
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(dev->id, 0);
++	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
++		io_apic_write(dev->id, 0, reg_00.raw);
++	}
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
++		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
++		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++static struct sysdev_class ioapic_sysdev_class = {
++	set_kset_name("ioapic"),
++	.suspend = ioapic_suspend,
++	.resume = ioapic_resume,
++};
++
++static int __init ioapic_init_sysfs(void)
++{
++	struct sys_device * dev;
++	int i, size, error = 0;
++
++	error = sysdev_class_register(&ioapic_sysdev_class);
++	if (error)
++		return error;
++
++	for (i = 0; i < nr_ioapics; i++ ) {
++		size = sizeof(struct sys_device) + nr_ioapic_registers[i] 
++			* sizeof(struct IO_APIC_route_entry);
++		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
++		if (!mp_ioapic_data[i]) {
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++		memset(mp_ioapic_data[i], 0, size);
++		dev = &mp_ioapic_data[i]->dev;
++		dev->id = i; 
++		dev->cls = &ioapic_sysdev_class;
++		error = sysdev_register(dev);
++		if (error) {
++			kfree(mp_ioapic_data[i]);
++			mp_ioapic_data[i] = NULL;
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++	}
++
++	return 0;
++}
++
++device_initcall(ioapic_init_sysfs);
++
++#endif /* CONFIG_XEN */
++
++/* --------------------------------------------------------------------------
++                          ACPI-based IOAPIC Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++int __init io_apic_get_unique_id (int ioapic, int apic_id)
++{
++#ifndef CONFIG_XEN
++	union IO_APIC_reg_00 reg_00;
++	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
++	physid_mask_t tmp;
++	unsigned long flags;
++	int i = 0;
++
++	/*
++	 * The P4 platform supports up to 256 APIC IDs on two separate APIC 
++	 * buses (one for LAPICs, one for IOAPICs), where predecessors only 
++	 * supports up to 16 on one shared APIC bus.
++	 * 
++	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
++	 *      advantage of new APIC bus architecture.
++	 */
++
++	if (physids_empty(apic_id_map))
++		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(ioapic, 0);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	if (apic_id >= get_physical_broadcast()) {
++		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
++			"%d\n", ioapic, apic_id, reg_00.bits.ID);
++		apic_id = reg_00.bits.ID;
++	}
++
++	/*
++	 * Every APIC in a system must have a unique ID or we get lots of nice 
++	 * 'stuck on smp_invalidate_needed IPI wait' messages.
++	 */
++	if (check_apicid_used(apic_id_map, apic_id)) {
++
++		for (i = 0; i < get_physical_broadcast(); i++) {
++			if (!check_apicid_used(apic_id_map, i))
++				break;
++		}
++
++		if (i == get_physical_broadcast())
++			panic("Max apic_id exceeded!\n");
++
++		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
++			"trying %d\n", ioapic, apic_id, i);
++
++		apic_id = i;
++	} 
++
++	tmp = apicid_to_cpu_present(apic_id);
++	physids_or(apic_id_map, apic_id_map, tmp);
++
++	if (reg_00.bits.ID != apic_id) {
++		reg_00.bits.ID = apic_id;
++
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(ioapic, 0, reg_00.raw);
++		reg_00.raw = io_apic_read(ioapic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		/* Sanity check */
++		if (reg_00.bits.ID != apic_id) {
++			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
++			return -1;
++		}
++	}
++
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
++#endif /* !CONFIG_XEN */
++
++	return apic_id;
++}
++
++
++int __init io_apic_get_version (int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.version;
++}
++
++
++int __init io_apic_get_redir_entries (int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.entries;
++}
++
++
++int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++
++	if (!IO_APIC_IRQ(irq)) {
++		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
++			ioapic);
++		return -EINVAL;
++	}
++
++	/*
++	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
++	 * Note that we mask (disable) IRQs now -- these get enabled when the
++	 * corresponding device driver registers for this IRQ.
++	 */
++
++	memset(&entry,0,sizeof(entry));
++
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.dest_mode = INT_DEST_MODE;
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.trigger = edge_level;
++	entry.polarity = active_high_low;
++	entry.mask  = 1;
++
++	/*
++	 * IRQs < 16 are already in the irq_2_pin[] map
++	 */
++	if (irq >= 16)
++		add_pin_to_irq(irq, ioapic, pin);
++
++	entry.vector = assign_irq_vector(irq);
++
++	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
++		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
++		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
++		edge_level, active_high_low);
++
++	ioapic_register_intr(irq, entry.vector, edge_level);
++
++	if (!ioapic && (irq < 16))
++		disable_8259A_irq(irq);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
++	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
++	set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++#endif /* CONFIG_ACPI */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ioport_32-xen.c	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,123 @@
++/*
++ *	linux/arch/i386/kernel/ioport.c
++ *
++ * This contains the io-permission bitmap code - written by obz, with changes
++ * by Linus.
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/capability.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/ioport.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/stddef.h>
++#include <linux/slab.h>
++#include <linux/thread_info.h>
++#include <xen/interface/physdev.h>
++
++/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
++static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
++{
++	unsigned long mask;
++	unsigned long *bitmap_base = bitmap + (base / BITS_PER_LONG);
++	unsigned int low_index = base & (BITS_PER_LONG-1);
++	int length = low_index + extent;
++
++	if (low_index != 0) {
++		mask = (~0UL << low_index);
++		if (length < BITS_PER_LONG)
++			mask &= ~(~0UL << length);
++		if (new_value)
++			*bitmap_base++ |= mask;
++		else
++			*bitmap_base++ &= ~mask;
++		length -= BITS_PER_LONG;
++	}
++
++	mask = (new_value ? ~0UL : 0UL);
++	while (length >= BITS_PER_LONG) {
++		*bitmap_base++ = mask;
++		length -= BITS_PER_LONG;
++	}
++
++	if (length > 0) {
++		mask = ~(~0UL << length);
++		if (new_value)
++			*bitmap_base++ |= mask;
++		else
++			*bitmap_base++ &= ~mask;
++	}
++}
++
++
++/*
++ * this changes the io permissions bitmap in the current task.
++ */
++asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
++{
++	struct thread_struct * t = &current->thread;
++	unsigned long *bitmap;
++	struct physdev_set_iobitmap set_iobitmap;
++
++	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
++		return -EINVAL;
++	if (turn_on && !capable(CAP_SYS_RAWIO))
++		return -EPERM;
++
++	/*
++	 * If it's the first ioperm() call in this thread's lifetime, set the
++	 * IO bitmap up. ioperm() is much less timing critical than clone(),
++	 * this is why we delay this operation until now:
++	 */
++	if (!t->io_bitmap_ptr) {
++		bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++		if (!bitmap)
++			return -ENOMEM;
++
++		memset(bitmap, 0xff, IO_BITMAP_BYTES);
++		t->io_bitmap_ptr = bitmap;
++		set_thread_flag(TIF_IO_BITMAP);
++
++		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
++		set_iobitmap.nr_ports = IO_BITMAP_BITS;
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &set_iobitmap));
++	}
++
++	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
++
++	return 0;
++}
++
++/*
++ * sys_iopl has to be used when you want to access the IO ports
++ * beyond the 0x3ff range: to get the full 65536 ports bitmapped
++ * you'd need 8kB of bitmaps/process, which is a bit excessive.
++ *
++ * Here we just change the eflags value on the stack: we allow
++ * only the super-user to do it. This depends on the stack-layout
++ * on system-call entry - see also fork() and the signal handling
++ * code.
++ */
++
++asmlinkage long sys_iopl(unsigned long unused)
++{
++	volatile struct pt_regs * regs = (struct pt_regs *) &unused;
++	unsigned int level = regs->ebx;
++	struct thread_struct *t = &current->thread;
++	unsigned int old = (t->iopl >> 12) & 3;
++
++	if (level > 3)
++		return -EINVAL;
++	/* Trying to gain more privileges? */
++	if (level > old) {
++		if (!capable(CAP_SYS_RAWIO))
++			return -EPERM;
++	}
++	t->iopl = level << 12;
++	set_iopl_mask(t->iopl);
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,324 @@
++/*
++ *	linux/arch/i386/kernel/irq.c
++ *
++ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
++ *
++ * This file contains the lowest level x86-specific interrupt
++ * entry, irq-stacks and irq statistics code. All the remaining
++ * irq logic is done by the generic kernel/irq/ code and
++ * by the x86-specific irq controller code. (e.g. i8259.c and
++ * io_apic.c.)
++ */
++
++#include <asm/uaccess.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/notifier.h>
++#include <linux/cpu.h>
++#include <linux/delay.h>
++
++DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
++EXPORT_PER_CPU_SYMBOL(irq_stat);
++
++#ifndef CONFIG_X86_LOCAL_APIC
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++	printk("unexpected IRQ trap at vector %02x\n", irq);
++}
++#endif
++
++#ifdef CONFIG_4KSTACKS
++/*
++ * per-CPU IRQ handling contexts (thread information and stack)
++ */
++union irq_ctx {
++	struct thread_info      tinfo;
++	u32                     stack[THREAD_SIZE/sizeof(u32)];
++};
++
++static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
++static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
++#endif
++
++/*
++ * do_IRQ handles all normal device IRQ's (the special
++ * SMP cross-CPU interrupts have their own specific
++ * handlers).
++ */
++fastcall unsigned int do_IRQ(struct pt_regs *regs)
++{	
++	/* high bit used in ret_from_ code */
++	int irq = ~regs->orig_eax;
++#ifdef CONFIG_4KSTACKS
++	union irq_ctx *curctx, *irqctx;
++	u32 *isp;
++#endif
++
++	if (unlikely((unsigned)irq >= NR_IRQS)) {
++		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
++					__FUNCTION__, irq);
++		BUG();
++	}
++
++	/*irq_enter();*/
++#ifdef CONFIG_DEBUG_STACKOVERFLOW
++	/* Debugging check for stack overflow: is there less than 1KB free? */
++	{
++		long esp;
++
++		__asm__ __volatile__("andl %%esp,%0" :
++					"=r" (esp) : "0" (THREAD_SIZE - 1));
++		if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
++			printk("do_IRQ: stack overflow: %ld\n",
++				esp - sizeof(struct thread_info));
++			dump_stack();
++		}
++	}
++#endif
++
++#ifdef CONFIG_4KSTACKS
++
++	curctx = (union irq_ctx *) current_thread_info();
++	irqctx = hardirq_ctx[smp_processor_id()];
++
++	/*
++	 * this is where we switch to the IRQ stack. However, if we are
++	 * already using the IRQ stack (because we interrupted a hardirq
++	 * handler) we can't do that and just have to keep using the
++	 * current stack (which is the irq stack already after all)
++	 */
++	if (curctx != irqctx) {
++		int arg1, arg2, ebx;
++
++		/* build the stack frame on the IRQ stack */
++		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
++		irqctx->tinfo.task = curctx->tinfo.task;
++		irqctx->tinfo.previous_esp = current_stack_pointer;
++
++		/*
++		 * Copy the softirq bits in preempt_count so that the
++		 * softirq checks work in the hardirq context.
++		 */
++		irqctx->tinfo.preempt_count =
++			(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
++			(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
++
++		asm volatile(
++			"       xchgl   %%ebx,%%esp      \n"
++			"       call    __do_IRQ         \n"
++			"       movl   %%ebx,%%esp      \n"
++			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
++			:  "0" (irq),   "1" (regs),  "2" (isp)
++			: "memory", "cc", "ecx"
++		);
++	} else
++#endif
++		__do_IRQ(irq, regs);
++
++	/*irq_exit();*/
++
++	return 1;
++}
++
++#ifdef CONFIG_4KSTACKS
++
++/*
++ * These should really be __section__(".bss.page_aligned") as well, but
++ * gcc's 3.0 and earlier don't handle that correctly.
++ */
++static char softirq_stack[NR_CPUS * THREAD_SIZE]
++		__attribute__((__aligned__(THREAD_SIZE)));
++
++static char hardirq_stack[NR_CPUS * THREAD_SIZE]
++		__attribute__((__aligned__(THREAD_SIZE)));
++
++/*
++ * allocate per-cpu stacks for hardirq and for softirq processing
++ */
++void irq_ctx_init(int cpu)
++{
++	union irq_ctx *irqctx;
++
++	if (hardirq_ctx[cpu])
++		return;
++
++	irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
++	irqctx->tinfo.task              = NULL;
++	irqctx->tinfo.exec_domain       = NULL;
++	irqctx->tinfo.cpu               = cpu;
++	irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
++	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
++
++	hardirq_ctx[cpu] = irqctx;
++
++	irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
++	irqctx->tinfo.task              = NULL;
++	irqctx->tinfo.exec_domain       = NULL;
++	irqctx->tinfo.cpu               = cpu;
++	irqctx->tinfo.preempt_count     = 0;
++	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
++
++	softirq_ctx[cpu] = irqctx;
++
++	printk("CPU %u irqstacks, hard=%p soft=%p\n",
++		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
++}
++
++void irq_ctx_exit(int cpu)
++{
++	hardirq_ctx[cpu] = NULL;
++}
++
++extern asmlinkage void __do_softirq(void);
++
++asmlinkage void do_softirq(void)
++{
++	unsigned long flags;
++	struct thread_info *curctx;
++	union irq_ctx *irqctx;
++	u32 *isp;
++
++	if (in_interrupt())
++		return;
++
++	local_irq_save(flags);
++
++	if (local_softirq_pending()) {
++		curctx = current_thread_info();
++		irqctx = softirq_ctx[smp_processor_id()];
++		irqctx->tinfo.task = curctx->task;
++		irqctx->tinfo.previous_esp = current_stack_pointer;
++
++		/* build the stack frame on the softirq stack */
++		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
++
++		asm volatile(
++			"       xchgl   %%ebx,%%esp     \n"
++			"       call    __do_softirq    \n"
++			"       movl    %%ebx,%%esp     \n"
++			: "=b"(isp)
++			: "0"(isp)
++			: "memory", "cc", "edx", "ecx", "eax"
++		);
++		/*
++		 * Shouldnt happen, we returned above if in_interrupt():
++	 	 */
++		WARN_ON_ONCE(softirq_count());
++	}
++
++	local_irq_restore(flags);
++}
++
++EXPORT_SYMBOL(do_softirq);
++#endif
++
++/*
++ * Interrupt statistics:
++ */
++
++atomic_t irq_err_count;
++
++/*
++ * /proc/interrupts printing:
++ */
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++	int i = *(loff_t *) v, j;
++	struct irqaction * action;
++	unsigned long flags;
++
++	if (i == 0) {
++		seq_printf(p, "           ");
++		for_each_online_cpu(j)
++			seq_printf(p, "CPU%-8d",j);
++		seq_putc(p, '\n');
++	}
++
++	if (i < NR_IRQS) {
++		spin_lock_irqsave(&irq_desc[i].lock, flags);
++		action = irq_desc[i].action;
++		if (!action)
++			goto skip;
++		seq_printf(p, "%3d: ",i);
++#ifndef CONFIG_SMP
++		seq_printf(p, "%10u ", kstat_irqs(i));
++#else
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
++#endif
++		seq_printf(p, " %14s", irq_desc[i].chip->typename);
++		seq_printf(p, "  %s", action->name);
++
++		for (action=action->next; action; action = action->next)
++			seq_printf(p, ", %s", action->name);
++
++		seq_putc(p, '\n');
++skip:
++		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
++	} else if (i == NR_IRQS) {
++		seq_printf(p, "NMI: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", nmi_count(j));
++		seq_putc(p, '\n');
++#ifdef CONFIG_X86_LOCAL_APIC
++		seq_printf(p, "LOC: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).apic_timer_irqs);
++		seq_putc(p, '\n');
++#endif
++		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
++#if defined(CONFIG_X86_IO_APIC)
++		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
++#endif
++	}
++	return 0;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++void fixup_irqs(cpumask_t map)
++{
++	unsigned int irq;
++	static int warned;
++
++	for (irq = 0; irq < NR_IRQS; irq++) {
++		cpumask_t mask;
++		if (irq == 2)
++			continue;
++
++		cpus_and(mask, irq_desc[irq].affinity, map);
++		if (any_online_cpu(mask) == NR_CPUS) {
++			/*printk("Breaking affinity for irq %i\n", irq);*/
++			mask = map;
++		}
++		if (irq_desc[irq].chip->set_affinity)
++			irq_desc[irq].chip->set_affinity(irq, mask);
++		else if (irq_desc[irq].action && !(warned++))
++			printk("Cannot set affinity for irq %i\n", irq);
++	}
++
++#if 0
++	barrier();
++	/* Ingo Molnar says: "after the IO-APIC masks have been redirected
++	   [note the nop - the interrupt-enable boundary on x86 is two
++	   instructions from sti] - to flush out pending hardirqs and
++	   IPIs. After this point nothing is supposed to reach this CPU." */
++	__asm__ __volatile__("sti; nop; cli");
++	barrier();
++#else
++	/* That doesn't seem sufficient.  Give it 1ms. */
++	local_irq_enable();
++	mdelay(1);
++	local_irq_disable();
++#endif
++}
++#endif
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ldt_32-xen.c	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,270 @@
++/*
++ * linux/kernel/ldt.c
++ *
++ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
++ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ */
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/ldt.h>
++#include <asm/desc.h>
++#include <asm/mmu_context.h>
++
++#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
++static void flush_ldt(void *null)
++{
++	if (current->active_mm)
++		load_LDT(&current->active_mm->context);
++}
++#endif
++
++static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
++{
++	void *oldldt;
++	void *newldt;
++	int oldsize;
++
++	if (mincount <= pc->size)
++		return 0;
++	oldsize = pc->size;
++	mincount = (mincount+511)&(~511);
++	if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
++		newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
++	else
++		newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
++
++	if (!newldt)
++		return -ENOMEM;
++
++	if (oldsize)
++		memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
++	oldldt = pc->ldt;
++	memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
++	pc->ldt = newldt;
++	wmb();
++	pc->size = mincount;
++	wmb();
++
++	if (reload) {
++#ifdef CONFIG_SMP
++		cpumask_t mask;
++		preempt_disable();
++#endif
++		make_pages_readonly(
++			pc->ldt,
++			(pc->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		load_LDT(pc);
++#ifdef CONFIG_SMP
++		mask = cpumask_of_cpu(smp_processor_id());
++		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
++			smp_call_function(flush_ldt, NULL, 1, 1);
++		preempt_enable();
++#endif
++	}
++	if (oldsize) {
++		make_pages_writable(
++			oldldt,
++			(oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(oldldt);
++		else
++			kfree(oldldt);
++	}
++	return 0;
++}
++
++static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
++{
++	int err = alloc_ldt(new, old->size, 0);
++	if (err < 0)
++		return err;
++	memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
++	make_pages_readonly(
++		new->ldt,
++		(new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++		XENFEAT_writable_descriptor_tables);
++	return 0;
++}
++
++/*
++ * we do not have to muck with descriptors here, that is
++ * done in switch_mm() as needed.
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++	struct mm_struct * old_mm;
++	int retval = 0;
++
++	init_MUTEX(&mm->context.sem);
++	mm->context.size = 0;
++	mm->context.has_foreign_mappings = 0;
++	old_mm = current->mm;
++	if (old_mm && old_mm->context.size > 0) {
++		down(&old_mm->context.sem);
++		retval = copy_ldt(&mm->context, &old_mm->context);
++		up(&old_mm->context.sem);
++	}
++	return retval;
++}
++
++/*
++ * No need to lock the MM as we are the last user
++ */
++void destroy_context(struct mm_struct *mm)
++{
++	if (mm->context.size) {
++		if (mm == current->active_mm)
++			clear_LDT();
++		make_pages_writable(
++			mm->context.ldt,
++			(mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(mm->context.ldt);
++		else
++			kfree(mm->context.ldt);
++		mm->context.size = 0;
++	}
++}
++
++static int read_ldt(void __user * ptr, unsigned long bytecount)
++{
++	int err;
++	unsigned long size;
++	struct mm_struct * mm = current->mm;
++
++	if (!mm->context.size)
++		return 0;
++	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
++		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
++
++	down(&mm->context.sem);
++	size = mm->context.size*LDT_ENTRY_SIZE;
++	if (size > bytecount)
++		size = bytecount;
++
++	err = 0;
++	if (copy_to_user(ptr, mm->context.ldt, size))
++		err = -EFAULT;
++	up(&mm->context.sem);
++	if (err < 0)
++		goto error_return;
++	if (size != bytecount) {
++		/* zero-fill the rest */
++		if (clear_user(ptr+size, bytecount-size) != 0) {
++			err = -EFAULT;
++			goto error_return;
++		}
++	}
++	return bytecount;
++error_return:
++	return err;
++}
++
++static int read_default_ldt(void __user * ptr, unsigned long bytecount)
++{
++	int err;
++	unsigned long size;
++	void *address;
++
++	err = 0;
++	address = &default_ldt[0];
++	size = 5*sizeof(struct desc_struct);
++	if (size > bytecount)
++		size = bytecount;
++
++	err = size;
++	if (copy_to_user(ptr, address, size))
++		err = -EFAULT;
++
++	return err;
++}
++
++static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
++{
++	struct mm_struct * mm = current->mm;
++	__u32 entry_1, entry_2;
++	int error;
++	struct user_desc ldt_info;
++
++	error = -EINVAL;
++	if (bytecount != sizeof(ldt_info))
++		goto out;
++	error = -EFAULT; 	
++	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
++		goto out;
++
++	error = -EINVAL;
++	if (ldt_info.entry_number >= LDT_ENTRIES)
++		goto out;
++	if (ldt_info.contents == 3) {
++		if (oldmode)
++			goto out;
++		if (ldt_info.seg_not_present == 0)
++			goto out;
++	}
++
++	down(&mm->context.sem);
++	if (ldt_info.entry_number >= mm->context.size) {
++		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
++		if (error < 0)
++			goto out_unlock;
++	}
++
++   	/* Allow LDTs to be cleared by the user. */
++   	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
++		if (oldmode || LDT_empty(&ldt_info)) {
++			entry_1 = 0;
++			entry_2 = 0;
++			goto install;
++		}
++	}
++
++	entry_1 = LDT_entry_a(&ldt_info);
++	entry_2 = LDT_entry_b(&ldt_info);
++	if (oldmode)
++		entry_2 &= ~(1 << 20);
++
++	/* Install the new entry ...  */
++install:
++	error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
++				entry_1, entry_2);
++
++out_unlock:
++	up(&mm->context.sem);
++out:
++	return error;
++}
++
++asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
++{
++	int ret = -ENOSYS;
++
++	switch (func) {
++	case 0:
++		ret = read_ldt(ptr, bytecount);
++		break;
++	case 1:
++		ret = write_ldt(ptr, bytecount, 1);
++		break;
++	case 2:
++		ret = read_default_ldt(ptr, bytecount);
++		break;
++	case 0x11:
++		ret = write_ldt(ptr, bytecount, 0);
++		break;
++	}
++	return ret;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,144 @@
++/*
++ *	Intel CPU Microcode Update Driver for Linux
++ *
++ *	Copyright (C) 2000-2004 Tigran Aivazian
++ *
++ *	This driver allows to upgrade microcode on Intel processors
++ *	belonging to IA-32 family - PentiumPro, Pentium II, 
++ *	Pentium III, Xeon, Pentium 4, etc.
++ *
++ *	Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
++ *	Order Number 245472 or free download from:
++ *		
++ *	http://developer.intel.com/design/pentium4/manuals/245472.htm
++ *
++ *	For more information, go to http://www.urbanmyth.org/microcode
++ *
++ *	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.
++ */
++
++//#define DEBUG /* pr_debug */
++#include <linux/capability.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/miscdevice.h>
++#include <linux/spinlock.h>
++#include <linux/mm.h>
++#include <linux/mutex.h>
++#include <linux/syscalls.h>
++
++#include <asm/msr.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++
++MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
++MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
++MODULE_LICENSE("GPL");
++
++static int verbose;
++module_param(verbose, int, 0644);
++
++#define MICROCODE_VERSION 	"1.14a-xen"
++
++#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
++#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
++#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
++
++/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
++static DEFINE_MUTEX(microcode_mutex);
++				
++static int microcode_open (struct inode *unused1, struct file *unused2)
++{
++	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
++}
++
++
++static int do_microcode_update (const void __user *ubuf, size_t len)
++{
++	int err;
++	void *kbuf;
++
++	kbuf = vmalloc(len);
++	if (!kbuf)
++		return -ENOMEM;
++
++	if (copy_from_user(kbuf, ubuf, len) == 0) {
++		struct xen_platform_op op;
++
++		op.cmd = XENPF_microcode_update;
++		set_xen_guest_handle(op.u.microcode.data, kbuf);
++		op.u.microcode.length = len;
++		err = HYPERVISOR_platform_op(&op);
++	} else
++		err = -EFAULT;
++
++	vfree(kbuf);
++
++	return err;
++}
++
++static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
++{
++	ssize_t ret;
++
++	if (len < MC_HEADER_SIZE) {
++		printk(KERN_ERR "microcode: not enough data\n"); 
++		return -EINVAL;
++	}
++
++	mutex_lock(&microcode_mutex);
++
++	ret = do_microcode_update(buf, len);
++	if (!ret)
++		ret = (ssize_t)len;
++
++	mutex_unlock(&microcode_mutex);
++
++	return ret;
++}
++
++static struct file_operations microcode_fops = {
++	.owner		= THIS_MODULE,
++	.write		= microcode_write,
++	.open		= microcode_open,
++};
++
++static struct miscdevice microcode_dev = {
++	.minor		= MICROCODE_MINOR,
++	.name		= "microcode",
++	.fops		= &microcode_fops,
++};
++
++static int __init microcode_init (void)
++{
++	int error;
++
++	error = misc_register(&microcode_dev);
++	if (error) {
++		printk(KERN_ERR
++			"microcode: can't misc_register on minor=%d\n",
++			MICROCODE_MINOR);
++		return error;
++	}
++
++	printk(KERN_INFO 
++		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
++	return 0;
++}
++
++static void __exit microcode_exit (void)
++{
++	misc_deregister(&microcode_dev);
++}
++
++module_init(microcode_init)
++module_exit(microcode_exit)
++MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,1185 @@
++/*
++ *	Intel Multiprocessor Specification 1.1 and 1.4
++ *	compliant MP-table parsing routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *		Erich Boleyn	:	MP v1.4 and additional changes.
++ *		Alan Cox	:	Added EBDA scanning
++ *		Ingo Molnar	:	various cleanups and rewrites
++ *		Maciej W. Rozycki:	Bits for default MP configurations
++ *		Paul Diefenbaugh:	Added full ACPI support
++ */
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/acpi.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/bitops.h>
++
++#include <asm/smp.h>
++#include <asm/acpi.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/io_apic.h>
++
++#include <mach_apic.h>
++#include <mach_mpparse.h>
++#include <bios_ebda.h>
++
++/* Have we found an MP table */
++int smp_found_config;
++unsigned int __initdata maxcpus = NR_CPUS;
++
++/*
++ * Various Linux-internal data structures created from the
++ * MP-table.
++ */
++int apic_version [MAX_APICS];
++int mp_bus_id_to_type [MAX_MP_BUSSES];
++int mp_bus_id_to_node [MAX_MP_BUSSES];
++int mp_bus_id_to_local [MAX_MP_BUSSES];
++int quad_local_to_mp_bus_id [NR_CPUS/4][4];
++int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
++static int mp_current_pci_id;
++
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++
++/* # of MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* MP IRQ source entries */
++int mp_irq_entries;
++
++int nr_ioapics;
++
++int pic_mode;
++unsigned long mp_lapic_addr;
++
++unsigned int def_to_bigsmp = 0;
++
++/* Processor that is doing the boot up */
++unsigned int boot_cpu_physical_apicid = -1U;
++/* Internal processor count */
++static unsigned int __devinitdata num_processors;
++
++/* Bitmask of physically existing CPUs */
++physid_mask_t phys_cpu_present_map;
++
++u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
++
++/*
++ * Intel MP BIOS table parsing routines:
++ */
++
++
++/*
++ * Checksum an MP configuration block.
++ */
++
++static int __init mpf_checksum(unsigned char *mp, int len)
++{
++	int sum = 0;
++
++	while (len--)
++		sum += *mp++;
++
++	return sum & 0xFF;
++}
++
++/*
++ * Have to match translation table entries to main table entries by counter
++ * hence the mpc_record variable .... can't see a less disgusting way of
++ * doing this ....
++ */
++
++static int mpc_record; 
++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
++
++#ifndef CONFIG_XEN
++static void __devinit MP_processor_info (struct mpc_config_processor *m)
++{
++ 	int ver, apicid;
++	physid_mask_t phys_cpu;
++ 	
++	if (!(m->mpc_cpuflag & CPU_ENABLED))
++		return;
++
++	apicid = mpc_apic_id(m, translation_table[mpc_record]);
++
++	if (m->mpc_featureflag&(1<<0))
++		Dprintk("    Floating point unit present.\n");
++	if (m->mpc_featureflag&(1<<7))
++		Dprintk("    Machine Exception supported.\n");
++	if (m->mpc_featureflag&(1<<8))
++		Dprintk("    64 bit compare & exchange supported.\n");
++	if (m->mpc_featureflag&(1<<9))
++		Dprintk("    Internal APIC present.\n");
++	if (m->mpc_featureflag&(1<<11))
++		Dprintk("    SEP present.\n");
++	if (m->mpc_featureflag&(1<<12))
++		Dprintk("    MTRR  present.\n");
++	if (m->mpc_featureflag&(1<<13))
++		Dprintk("    PGE  present.\n");
++	if (m->mpc_featureflag&(1<<14))
++		Dprintk("    MCA  present.\n");
++	if (m->mpc_featureflag&(1<<15))
++		Dprintk("    CMOV  present.\n");
++	if (m->mpc_featureflag&(1<<16))
++		Dprintk("    PAT  present.\n");
++	if (m->mpc_featureflag&(1<<17))
++		Dprintk("    PSE  present.\n");
++	if (m->mpc_featureflag&(1<<18))
++		Dprintk("    PSN  present.\n");
++	if (m->mpc_featureflag&(1<<19))
++		Dprintk("    Cache Line Flush Instruction present.\n");
++	/* 20 Reserved */
++	if (m->mpc_featureflag&(1<<21))
++		Dprintk("    Debug Trace and EMON Store present.\n");
++	if (m->mpc_featureflag&(1<<22))
++		Dprintk("    ACPI Thermal Throttle Registers  present.\n");
++	if (m->mpc_featureflag&(1<<23))
++		Dprintk("    MMX  present.\n");
++	if (m->mpc_featureflag&(1<<24))
++		Dprintk("    FXSR  present.\n");
++	if (m->mpc_featureflag&(1<<25))
++		Dprintk("    XMM  present.\n");
++	if (m->mpc_featureflag&(1<<26))
++		Dprintk("    Willamette New Instructions  present.\n");
++	if (m->mpc_featureflag&(1<<27))
++		Dprintk("    Self Snoop  present.\n");
++	if (m->mpc_featureflag&(1<<28))
++		Dprintk("    HT  present.\n");
++	if (m->mpc_featureflag&(1<<29))
++		Dprintk("    Thermal Monitor present.\n");
++	/* 30, 31 Reserved */
++
++
++	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++		Dprintk("    Bootup CPU\n");
++		boot_cpu_physical_apicid = m->mpc_apicid;
++	}
++
++	ver = m->mpc_apicver;
++
++	/*
++	 * Validate version
++	 */
++	if (ver == 0x0) {
++		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
++				"fixing up to 0x10. (tell your hw vendor)\n",
++				m->mpc_apicid);
++		ver = 0x10;
++	}
++	apic_version[m->mpc_apicid] = ver;
++
++	phys_cpu = apicid_to_cpu_present(apicid);
++	physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
++
++	if (num_processors >= NR_CPUS) {
++		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++			"  Processor ignored.\n", NR_CPUS);
++		return;
++	}
++
++	if (num_processors >= maxcpus) {
++		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
++			" Processor ignored.\n", maxcpus);
++		return;
++	}
++
++	cpu_set(num_processors, cpu_possible_map);
++	num_processors++;
++
++	/*
++	 * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
++	 * but we need to work other dependencies like SMP_SUSPEND etc
++	 * before this can be done without some confusion.
++	 * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
++	 *       - Ashok Raj <ashok.raj@intel.com>
++	 */
++	if (num_processors > 8) {
++		switch (boot_cpu_data.x86_vendor) {
++		case X86_VENDOR_INTEL:
++			if (!APIC_XAPIC(ver)) {
++				def_to_bigsmp = 0;
++				break;
++			}
++			/* If P4 and above fall through */
++		case X86_VENDOR_AMD:
++			def_to_bigsmp = 1;
++		}
++	}
++	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
++}
++#else
++void __init MP_processor_info (struct mpc_config_processor *m)
++{
++	num_processors++;
++}
++#endif /* CONFIG_XEN */
++
++static void __init MP_bus_info (struct mpc_config_bus *m)
++{
++	char str[7];
++
++	memcpy(str, m->mpc_bustype, 6);
++	str[6] = 0;
++
++	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
++
++	if (m->mpc_busid >= MAX_MP_BUSSES) {
++		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
++			" is too large, max. supported is %d\n",
++			m->mpc_busid, str, MAX_MP_BUSSES - 1);
++		return;
++	}
++
++	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
++		mpc_oem_pci_bus(m, translation_table[mpc_record]);
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
++		mp_current_pci_id++;
++	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++	} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
++	} else {
++		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
++	}
++}
++
++static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
++{
++	if (!(m->mpc_flags & MPC_APIC_USABLE))
++		return;
++
++	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
++		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
++			MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
++	}
++	if (!m->mpc_apicaddr) {
++		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
++			" found in MP table, skipping!\n");
++		return;
++	}
++	mp_ioapics[nr_ioapics] = *m;
++	nr_ioapics++;
++}
++
++static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
++{
++	mp_irqs [mp_irq_entries] = *m;
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
++			m->mpc_irqtype, m->mpc_irqflag & 3,
++			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
++			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!!\n");
++}
++
++static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
++{
++	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++			m->mpc_irqtype, m->mpc_irqflag & 3,
++			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
++			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++	/*
++	 * Well it seems all SMP boards in existence
++	 * use ExtINT/LVT1 == LINT0 and
++	 * NMI/LVT2 == LINT1 - the following check
++	 * will show us if this assumptions is false.
++	 * Until then we do not have to add baggage.
++	 */
++	if ((m->mpc_irqtype == mp_ExtINT) &&
++		(m->mpc_destapiclint != 0))
++			BUG();
++	if ((m->mpc_irqtype == mp_NMI) &&
++		(m->mpc_destapiclint != 1))
++			BUG();
++}
++
++#ifdef CONFIG_X86_NUMAQ
++static void __init MP_translation_info (struct mpc_config_translation *m)
++{
++	printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
++
++	if (mpc_record >= MAX_MPC_ENTRY) 
++		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
++	else
++		translation_table[mpc_record] = m; /* stash this for later */
++	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
++		node_set_online(m->trans_quad);
++}
++
++/*
++ * Read/parse the MPC oem tables
++ */
++
++static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
++	unsigned short oemsize)
++{
++	int count = sizeof (*oemtable); /* the header size */
++	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
++	
++	mpc_record = 0;
++	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
++	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
++	{
++		printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
++			oemtable->oem_signature[0],
++			oemtable->oem_signature[1],
++			oemtable->oem_signature[2],
++			oemtable->oem_signature[3]);
++		return;
++	}
++	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
++	{
++		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
++		return;
++	}
++	while (count < oemtable->oem_length) {
++		switch (*oemptr) {
++			case MP_TRANSLATION:
++			{
++				struct mpc_config_translation *m=
++					(struct mpc_config_translation *)oemptr;
++				MP_translation_info(m);
++				oemptr += sizeof(*m);
++				count += sizeof(*m);
++				++mpc_record;
++				break;
++			}
++			default:
++			{
++				printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
++				return;
++			}
++		}
++       }
++}
++
++static inline void mps_oem_check(struct mp_config_table *mpc, char *oem,
++		char *productid)
++{
++	if (strncmp(oem, "IBM NUMA", 8))
++		printk("Warning!  May not be a NUMA-Q system!\n");
++	if (mpc->mpc_oemptr)
++		smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr,
++				mpc->mpc_oemsize);
++}
++#endif	/* CONFIG_X86_NUMAQ */
++
++/*
++ * Read/parse the MPC
++ */
++
++static int __init smp_read_mpc(struct mp_config_table *mpc)
++{
++	char str[16];
++	char oem[10];
++	int count=sizeof(*mpc);
++	unsigned char *mpt=((unsigned char *)mpc)+count;
++
++	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
++		printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",
++			*(u32 *)mpc->mpc_signature);
++		return 0;
++	}
++	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
++		printk(KERN_ERR "SMP mptable: checksum error!\n");
++		return 0;
++	}
++	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
++		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
++			mpc->mpc_spec);
++		return 0;
++	}
++	if (!mpc->mpc_lapic) {
++		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
++		return 0;
++	}
++	memcpy(oem,mpc->mpc_oem,8);
++	oem[8]=0;
++	printk(KERN_INFO "OEM ID: %s ",oem);
++
++	memcpy(str,mpc->mpc_productid,12);
++	str[12]=0;
++	printk("Product ID: %s ",str);
++
++	mps_oem_check(mpc, oem, str);
++
++	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
++
++	/* 
++	 * Save the local APIC address (it might be non-default) -- but only
++	 * if we're not using ACPI.
++	 */
++	if (!acpi_lapic)
++		mp_lapic_addr = mpc->mpc_lapic;
++
++	/*
++	 *	Now process the configuration blocks.
++	 */
++	mpc_record = 0;
++	while (count < mpc->mpc_length) {
++		switch(*mpt) {
++			case MP_PROCESSOR:
++			{
++				struct mpc_config_processor *m=
++					(struct mpc_config_processor *)mpt;
++				/* ACPI may have already provided this data */
++				if (!acpi_lapic)
++					MP_processor_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++			case MP_BUS:
++			{
++				struct mpc_config_bus *m=
++					(struct mpc_config_bus *)mpt;
++				MP_bus_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++			case MP_IOAPIC:
++			{
++				struct mpc_config_ioapic *m=
++					(struct mpc_config_ioapic *)mpt;
++				MP_ioapic_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++			case MP_INTSRC:
++			{
++				struct mpc_config_intsrc *m=
++					(struct mpc_config_intsrc *)mpt;
++
++				MP_intsrc_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++			case MP_LINTSRC:
++			{
++				struct mpc_config_lintsrc *m=
++					(struct mpc_config_lintsrc *)mpt;
++				MP_lintsrc_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++			default:
++			{
++				count = mpc->mpc_length;
++				break;
++			}
++		}
++		++mpc_record;
++	}
++	clustered_apic_check();
++	if (!num_processors)
++		printk(KERN_ERR "SMP mptable: no processors registered!\n");
++	return num_processors;
++}
++
++static int __init ELCR_trigger(unsigned int irq)
++{
++	unsigned int port;
++
++	port = 0x4d0 + (irq >> 3);
++	return (inb(port) >> (irq & 7)) & 1;
++}
++
++static void __init construct_default_ioirq_mptable(int mpc_default_type)
++{
++	struct mpc_config_intsrc intsrc;
++	int i;
++	int ELCR_fallback = 0;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;			/* conforming */
++	intsrc.mpc_srcbus = 0;
++	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++
++	intsrc.mpc_irqtype = mp_INT;
++
++	/*
++	 *  If true, we have an ISA/PCI system with no IRQ entries
++	 *  in the MP table. To prevent the PCI interrupts from being set up
++	 *  incorrectly, we try to use the ELCR. The sanity check to see if
++	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
++	 *  never be level sensitive, so we simply see if the ELCR agrees.
++	 *  If it does, we assume it's valid.
++	 */
++	if (mpc_default_type == 5) {
++		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
++
++		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
++			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
++		else {
++			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
++			ELCR_fallback = 1;
++		}
++	}
++
++	for (i = 0; i < 16; i++) {
++		switch (mpc_default_type) {
++		case 2:
++			if (i == 0 || i == 13)
++				continue;	/* IRQ0 & IRQ13 not connected */
++			/* fall through */
++		default:
++			if (i == 2)
++				continue;	/* IRQ2 is never connected */
++		}
++
++		if (ELCR_fallback) {
++			/*
++			 *  If the ELCR indicates a level-sensitive interrupt, we
++			 *  copy that information over to the MP table in the
++			 *  irqflag field (level sensitive, active high polarity).
++			 */
++			if (ELCR_trigger(i))
++				intsrc.mpc_irqflag = 13;
++			else
++				intsrc.mpc_irqflag = 0;
++		}
++
++		intsrc.mpc_srcbusirq = i;
++		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
++		MP_intsrc_info(&intsrc);
++	}
++
++	intsrc.mpc_irqtype = mp_ExtINT;
++	intsrc.mpc_srcbusirq = 0;
++	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
++	MP_intsrc_info(&intsrc);
++}
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++	struct mpc_config_processor processor;
++	struct mpc_config_bus bus;
++	struct mpc_config_ioapic ioapic;
++	struct mpc_config_lintsrc lintsrc;
++	int linttypes[2] = { mp_ExtINT, mp_NMI };
++	int i;
++
++	/*
++	 * local APIC has default address
++	 */
++	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++	/*
++	 * 2 CPUs, numbered 0 & 1.
++	 */
++	processor.mpc_type = MP_PROCESSOR;
++	/* Either an integrated APIC or a discrete 82489DX. */
++	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_cpuflag = CPU_ENABLED;
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++				   (boot_cpu_data.x86_model << 4) |
++				   boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++	for (i = 0; i < 2; i++) {
++		processor.mpc_apicid = i;
++		MP_processor_info(&processor);
++	}
++
++	bus.mpc_type = MP_BUS;
++	bus.mpc_busid = 0;
++	switch (mpc_default_type) {
++		default:
++			printk("???\n");
++			printk(KERN_ERR "Unknown standard configuration %d\n",
++				mpc_default_type);
++			/* fall through */
++		case 1:
++		case 5:
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			break;
++		case 2:
++		case 6:
++		case 3:
++			memcpy(bus.mpc_bustype, "EISA  ", 6);
++			break;
++		case 4:
++		case 7:
++			memcpy(bus.mpc_bustype, "MCA   ", 6);
++	}
++	MP_bus_info(&bus);
++	if (mpc_default_type > 4) {
++		bus.mpc_busid = 1;
++		memcpy(bus.mpc_bustype, "PCI   ", 6);
++		MP_bus_info(&bus);
++	}
++
++	ioapic.mpc_type = MP_IOAPIC;
++	ioapic.mpc_apicid = 2;
++	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.mpc_flags = MPC_APIC_USABLE;
++	ioapic.mpc_apicaddr = 0xFEC00000;
++	MP_ioapic_info(&ioapic);
++
++	/*
++	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
++	 */
++	construct_default_ioirq_mptable(mpc_default_type);
++
++	lintsrc.mpc_type = MP_LINTSRC;
++	lintsrc.mpc_irqflag = 0;		/* conforming */
++	lintsrc.mpc_srcbusid = 0;
++	lintsrc.mpc_srcbusirq = 0;
++	lintsrc.mpc_destapic = MP_APIC_ALL;
++	for (i = 0; i < 2; i++) {
++		lintsrc.mpc_irqtype = linttypes[i];
++		lintsrc.mpc_destapiclint = i;
++		MP_lintsrc_info(&lintsrc);
++	}
++}
++
++static struct intel_mp_floating *mpf_found;
++
++/*
++ * Scan the memory blocks for an SMP configuration block.
++ */
++void __init get_smp_config (void)
++{
++	struct intel_mp_floating *mpf = mpf_found;
++
++	/*
++	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
++	 * processors, where MPS only supports physical.
++	 */
++	if (acpi_lapic && acpi_ioapic) {
++		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
++		return;
++	}
++	else if (acpi_lapic)
++		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
++
++	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
++	if (mpf->mpf_feature2 & (1<<7)) {
++		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
++		pic_mode = 1;
++	} else {
++		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
++		pic_mode = 0;
++	}
++
++	/*
++	 * Now see if we need to read further.
++	 */
++	if (mpf->mpf_feature1 != 0) {
++
++		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
++		construct_default_ISA_mptable(mpf->mpf_feature1);
++
++	} else if (mpf->mpf_physptr) {
++
++		/*
++		 * Read the physical hardware table.  Anything here will
++		 * override the defaults.
++		 */
++		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) {
++			smp_found_config = 0;
++			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
++			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
++			return;
++		}
++		/*
++		 * If there are no explicit MP IRQ entries, then we are
++		 * broken.  We set up most of the low 16 IO-APIC pins to
++		 * ISA defaults and hope it will work.
++		 */
++		if (!mp_irq_entries) {
++			struct mpc_config_bus bus;
++
++			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
++
++			bus.mpc_type = MP_BUS;
++			bus.mpc_busid = 0;
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			MP_bus_info(&bus);
++
++			construct_default_ioirq_mptable(0);
++		}
++
++	} else
++		BUG();
++
++	printk(KERN_INFO "Processors: %d\n", num_processors);
++	/*
++	 * Only use the first configuration found.
++	 */
++}
++
++static int __init smp_scan_config (unsigned long base, unsigned long length)
++{
++	unsigned long *bp = isa_bus_to_virt(base);
++	struct intel_mp_floating *mpf;
++
++	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
++	if (sizeof(*mpf) != 16)
++		printk("Error: MPF size\n");
++
++	while (length > 0) {
++		mpf = (struct intel_mp_floating *)bp;
++		if ((*bp == SMP_MAGIC_IDENT) &&
++			(mpf->mpf_length == 1) &&
++			!mpf_checksum((unsigned char *)bp, 16) &&
++			((mpf->mpf_specification == 1)
++				|| (mpf->mpf_specification == 4)) ) {
++
++			smp_found_config = 1;
++#ifndef CONFIG_XEN
++			printk(KERN_INFO "found SMP MP-table at %08lx\n",
++						virt_to_phys(mpf));
++			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
++			if (mpf->mpf_physptr) {
++				/*
++				 * We cannot access to MPC table to compute
++				 * table size yet, as only few megabytes from
++				 * the bottom is mapped now.
++				 * PC-9800's MPC table places on the very last
++				 * of physical memory; so that simply reserving
++				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()
++				 * in reserve_bootmem.
++				 */
++				unsigned long size = PAGE_SIZE;
++				unsigned long end = max_low_pfn * PAGE_SIZE;
++				if (mpf->mpf_physptr + size > end)
++					size = end - mpf->mpf_physptr;
++				reserve_bootmem(mpf->mpf_physptr, size);
++			}
++#else
++			printk(KERN_INFO "found SMP MP-table at %08lx\n",
++				((unsigned long)bp - (unsigned long)isa_bus_to_virt(base)) + base);
++#endif
++
++			mpf_found = mpf;
++			return 1;
++		}
++		bp += 4;
++		length -= 16;
++	}
++	return 0;
++}
++
++void __init find_smp_config (void)
++{
++#ifndef CONFIG_XEN
++	unsigned int address;
++#endif
++
++	/*
++	 * FIXME: Linux assumes you have 640K of base ram..
++	 * this continues the error...
++	 *
++	 * 1) Scan the bottom 1K for a signature
++	 * 2) Scan the top 1K of base RAM
++	 * 3) Scan the 64K of bios
++	 */
++	if (smp_scan_config(0x0,0x400) ||
++		smp_scan_config(639*0x400,0x400) ||
++			smp_scan_config(0xF0000,0x10000))
++		return;
++	/*
++	 * If it is an SMP machine we should know now, unless the
++	 * configuration is in an EISA/MCA bus machine with an
++	 * extended bios data area.
++	 *
++	 * there is a real-mode segmented pointer pointing to the
++	 * 4K EBDA area at 0x40E, calculate and scan it here.
++	 *
++	 * NOTE! There are Linux loaders that will corrupt the EBDA
++	 * area, and as such this kind of SMP config may be less
++	 * trustworthy, simply because the SMP table may have been
++	 * stomped on during early boot. These loaders are buggy and
++	 * should be fixed.
++	 *
++	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
++	 */
++
++#ifndef CONFIG_XEN
++	address = get_bios_ebda();
++	if (address)
++		smp_scan_config(address, 0x400);
++#endif
++}
++
++int es7000_plat;
++
++/* --------------------------------------------------------------------------
++                            ACPI-based MP Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++void __init mp_register_lapic_address (
++	u64			address)
++{
++#ifndef CONFIG_XEN
++	mp_lapic_addr = (unsigned long) address;
++
++	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
++
++	if (boot_cpu_physical_apicid == -1U)
++		boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
++
++	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
++#endif
++}
++
++
++void __devinit mp_register_lapic (
++	u8			id, 
++	u8			enabled)
++{
++	struct mpc_config_processor processor;
++	int			boot_cpu = 0;
++	
++	if (MAX_APICS - id <= 0) {
++		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
++			id, MAX_APICS);
++		return;
++	}
++
++	if (id == boot_cpu_physical_apicid)
++		boot_cpu = 1;
++
++#ifndef CONFIG_XEN
++	processor.mpc_type = MP_PROCESSOR;
++	processor.mpc_apicid = id;
++	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
++	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
++	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
++		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++#endif
++
++	MP_processor_info(&processor);
++}
++
++#ifdef	CONFIG_X86_IO_APIC
++
++#define MP_ISA_BUS		0
++#define MP_MAX_IOAPIC_PIN	127
++
++static struct mp_ioapic_routing {
++	int			apic_id;
++	int			gsi_base;
++	int			gsi_end;
++	u32			pin_programmed[4];
++} mp_ioapic_routing[MAX_IO_APICS];
++
++
++static int mp_find_ioapic (
++	int			gsi)
++{
++	int			i = 0;
++
++	/* Find the IOAPIC that manages this GSI. */
++	for (i = 0; i < nr_ioapics; i++) {
++		if ((gsi >= mp_ioapic_routing[i].gsi_base)
++			&& (gsi <= mp_ioapic_routing[i].gsi_end))
++			return i;
++	}
++
++	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++
++	return -1;
++}
++	
++
++void __init mp_register_ioapic (
++	u8			id, 
++	u32			address,
++	u32			gsi_base)
++{
++	int			idx = 0;
++	int			tmpid;
++
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++	}
++	if (!address) {
++		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++			" found in MADT table, skipping!\n");
++		return;
++	}
++
++	idx = nr_ioapics++;
++
++	mp_ioapics[idx].mpc_type = MP_IOAPIC;
++	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
++	mp_ioapics[idx].mpc_apicaddr = address;
++
++#ifndef CONFIG_XEN
++	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++#endif
++	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++		&& !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		tmpid = io_apic_get_unique_id(idx, id);
++	else
++		tmpid = id;
++	if (tmpid == -1) {
++		nr_ioapics--;
++		return;
++	}
++	mp_ioapics[idx].mpc_apicid = tmpid;
++	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++	
++	/* 
++	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
++	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
++	 */
++	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
++	mp_ioapic_routing[idx].gsi_base = gsi_base;
++	mp_ioapic_routing[idx].gsi_end = gsi_base + 
++		io_apic_get_redir_entries(idx);
++
++	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
++		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
++		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++		mp_ioapic_routing[idx].gsi_base,
++		mp_ioapic_routing[idx].gsi_end);
++
++	return;
++}
++
++
++void __init mp_override_legacy_irq (
++	u8			bus_irq,
++	u8			polarity, 
++	u8			trigger, 
++	u32			gsi)
++{
++	struct mpc_config_intsrc intsrc;
++	int			ioapic = -1;
++	int			pin = -1;
++
++	/* 
++	 * Convert 'gsi' to 'ioapic.pin'.
++	 */
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0)
++		return;
++	pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++	/*
++	 * TBD: This check is for faulty timer entries, where the override
++	 *      erroneously sets the trigger to level, resulting in a HUGE 
++	 *      increase of timer interrupts!
++	 */
++	if ((bus_irq == 0) && (trigger == 3))
++		trigger = 1;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqtype = mp_INT;
++	intsrc.mpc_irqflag = (trigger << 2) | polarity;
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
++	intsrc.mpc_dstirq = pin;				    /* INTIN# */
++
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n",
++		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
++		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
++		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
++
++	mp_irqs[mp_irq_entries] = intsrc;
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!\n");
++
++	return;
++}
++
++void __init mp_config_acpi_legacy_irqs (void)
++{
++	struct mpc_config_intsrc intsrc;
++	int			i = 0;
++	int			ioapic = -1;
++
++	/* 
++	 * Fabricate the legacy ISA bus (bus #31).
++	 */
++	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++
++	/*
++	 * Older generations of ES7000 have no legacy identity mappings
++	 */
++	if (es7000_plat == 1)
++		return;
++
++	/* 
++	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
++	 */
++	ioapic = mp_find_ioapic(0);
++	if (ioapic < 0)
++		return;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;					/* Conforming */
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
++
++	/* 
++	 * Use the default configuration for the IRQs 0-15.  Unless
++	 * overriden by (MADT) interrupt source override entries.
++	 */
++	for (i = 0; i < 16; i++) {
++		int idx;
++
++		for (idx = 0; idx < mp_irq_entries; idx++) {
++			struct mpc_config_intsrc *irq = mp_irqs + idx;
++
++			/* Do we already have a mapping for this ISA IRQ? */
++			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
++				break;
++
++			/* Do we already have a mapping for this IOAPIC pin */
++			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
++				(irq->mpc_dstirq == i))
++				break;
++		}
++
++		if (idx != mp_irq_entries) {
++			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
++			continue;			/* IRQ already used */
++		}
++
++		intsrc.mpc_irqtype = mp_INT;
++		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
++		intsrc.mpc_dstirq = i;
++
++		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
++			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
++			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
++			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
++			intsrc.mpc_dstirq);
++
++		mp_irqs[mp_irq_entries] = intsrc;
++		if (++mp_irq_entries == MAX_IRQ_SOURCES)
++			panic("Max # of irq sources exceeded!\n");
++	}
++}
++
++#define MAX_GSI_NUM	4096
++
++int mp_register_gsi (u32 gsi, int triggering, int polarity)
++{
++	int			ioapic = -1;
++	int			ioapic_pin = 0;
++	int			idx, bit = 0;
++	static int		pci_irq = 16;
++	/*
++	 * Mapping between Global System Interrups, which
++	 * represent all possible interrupts, and IRQs
++	 * assigned to actual devices.
++	 */
++	static int		gsi_to_irq[MAX_GSI_NUM];
++
++	/* Don't set up the ACPI SCI because it's already set up */
++	if (acpi_fadt.sci_int == gsi)
++		return gsi;
++
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0) {
++		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
++		return gsi;
++	}
++
++	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
++
++	if (ioapic_renumber_irq)
++		gsi = ioapic_renumber_irq(ioapic, gsi);
++
++	/* 
++	 * Avoid pin reprogramming.  PRTs typically include entries  
++	 * with redundant pin->gsi mappings (but unique PCI devices);
++	 * we only program the IOAPIC on the first.
++	 */
++	bit = ioapic_pin % 32;
++	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
++	if (idx > 3) {
++		printk(KERN_ERR "Invalid reference to IOAPIC pin "
++			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
++			ioapic_pin);
++		return gsi;
++	}
++	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
++		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
++			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
++		return gsi_to_irq[gsi];
++	}
++
++	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
++
++	if (triggering == ACPI_LEVEL_SENSITIVE) {
++		/*
++		 * For PCI devices assign IRQs in order, avoiding gaps
++		 * due to unused I/O APIC pins.
++		 */
++		int irq = gsi;
++		if (gsi < MAX_GSI_NUM) {
++			/*
++			 * Retain the VIA chipset work-around (gsi > 15), but
++			 * avoid a problem where the 8254 timer (IRQ0) is setup
++			 * via an override (so it's not on pin 0 of the ioapic),
++			 * and at the same time, the pin 0 interrupt is a PCI
++			 * type.  The gsi > 15 test could cause these two pins
++			 * to be shared as IRQ0, and they are not shareable.
++			 * So test for this condition, and if necessary, avoid
++			 * the pin collision.
++			 */
++			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
++				gsi = pci_irq++;
++			/*
++			 * Don't assign IRQ used by ACPI SCI
++			 */
++			if (gsi == acpi_fadt.sci_int)
++				gsi = pci_irq++;
++			gsi_to_irq[irq] = gsi;
++		} else {
++			printk(KERN_ERR "GSI %u is too high\n", gsi);
++			return gsi;
++		}
++	}
++
++	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
++		    triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
++		    polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
++	return gsi;
++}
++
++#endif /* CONFIG_X86_IO_APIC */
++#endif /* CONFIG_ACPI */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:23:23.000000000 +0100
+@@ -0,0 +1,406 @@
++/*
++ * Dynamic DMA mapping support.
++ *
++ * On i386 there is no hardware dynamic DMA address translation,
++ * so consistent alloc/free are merely page allocation/freeing.
++ * The rest of the dynamic DMA mapping interface is implemented
++ * in asm/pci.h.
++ */
++
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/string.h>
++#include <linux/pci.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <asm/io.h>
++#include <xen/balloon.h>
++#include <xen/gnttab.h>
++#include <asm/swiotlb.h>
++#include <asm/tlbflush.h>
++#include <asm-i386/mach-xen/asm/swiotlb.h>
++#include <asm-i386/mach-xen/asm/gnttab_dma.h>
++#include <asm/bug.h>
++
++#ifdef __x86_64__
++#include <asm/proto.h>
++
++int iommu_merge __read_mostly = 0;
++EXPORT_SYMBOL(iommu_merge);
++
++dma_addr_t bad_dma_address __read_mostly;
++EXPORT_SYMBOL(bad_dma_address);
++
++/* This tells the BIO block layer to assume merging. Default to off
++   because we cannot guarantee merging later. */
++int iommu_bio_merge __read_mostly = 0;
++EXPORT_SYMBOL(iommu_bio_merge);
++
++int force_iommu __read_mostly= 0;
++
++__init int iommu_setup(char *p)
++{
++    return 1;
++}
++
++void __init pci_iommu_alloc(void)
++{
++#ifdef CONFIG_SWIOTLB
++	pci_swiotlb_init();
++#endif
++}
++
++static int __init pci_iommu_init(void)
++{
++	no_iommu_init();
++	return 0;
++}
++
++/* Must execute after PCI subsystem */
++fs_initcall(pci_iommu_init);
++#endif
++
++struct dma_coherent_mem {
++	void		*virt_base;
++	u32		device_base;
++	int		size;
++	int		flags;
++	unsigned long	*bitmap;
++};
++
++#define IOMMU_BUG_ON(test)				\
++do {							\
++	if (unlikely(test)) {				\
++		printk(KERN_ALERT "Fatal DMA error! "	\
++		       "Please use 'swiotlb=force'\n");	\
++		BUG();					\
++	}						\
++} 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)
++{
++	unsigned long pfn = p >> PAGE_SHIFT;
++	unsigned int offset = p & ~PAGE_MASK;
++
++	return ((offset + size > PAGE_SIZE) &&
++		!check_pages_physically_contiguous(pfn, offset, size));
++}
++
++int
++dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++	   enum dma_data_direction direction)
++{
++	int i, rc;
++
++	if (direction == DMA_NONE)
++		BUG();
++	WARN_ON(nents == 0 || sg[0].length == 0);
++
++	if (swiotlb) {
++		rc = swiotlb_map_sg(hwdev, sg, nents, direction);
++	} else {
++		for (i = 0; i < nents; i++ ) {
++			BUG_ON(!sg[i].page);
++			sg[i].dma_address =
++				gnttab_dma_map_page(sg[i].page) + sg[i].offset;
++			sg[i].dma_length  = sg[i].length;
++			IOMMU_BUG_ON(address_needs_mapping(
++				hwdev, sg[i].dma_address));
++			IOMMU_BUG_ON(range_straddles_page_boundary(
++				page_to_pseudophys(sg[i].page) + sg[i].offset,
++				sg[i].length));
++		}
++		rc = nents;
++	}
++
++	flush_write_buffers();
++	return rc;
++}
++EXPORT_SYMBOL(dma_map_sg);
++
++void
++dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++	     enum dma_data_direction direction)
++{
++	int i;
++
++	BUG_ON(direction == DMA_NONE);
++	if (swiotlb)
++		swiotlb_unmap_sg(hwdev, sg, nents, direction);
++	else {
++		for (i = 0; i < nents; i++ )
++			gnttab_dma_unmap_page(sg[i].dma_address);
++	}
++}
++EXPORT_SYMBOL(dma_unmap_sg);
++
++#ifdef CONFIG_HIGHMEM
++dma_addr_t
++dma_map_page(struct device *dev, struct page *page, unsigned long offset,
++	     size_t size, enum dma_data_direction direction)
++{
++	dma_addr_t dma_addr;
++
++	BUG_ON(direction == DMA_NONE);
++
++	if (swiotlb) {
++		dma_addr = swiotlb_map_page(
++			dev, page, offset, size, direction);
++	} else {
++		dma_addr = gnttab_dma_map_page(page) + offset;
++		IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr));
++	}
++
++	return dma_addr;
++}
++EXPORT_SYMBOL(dma_map_page);
++
++void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++	       enum dma_data_direction direction)
++{
++	BUG_ON(direction == DMA_NONE);
++	if (swiotlb)
++		swiotlb_unmap_page(dev, dma_address, size, direction);
++	else
++		gnttab_dma_unmap_page(dma_address);
++}
++EXPORT_SYMBOL(dma_unmap_page);
++#endif /* CONFIG_HIGHMEM */
++
++int
++dma_mapping_error(dma_addr_t dma_addr)
++{
++	if (swiotlb)
++		return swiotlb_dma_mapping_error(dma_addr);
++	return 0;
++}
++EXPORT_SYMBOL(dma_mapping_error);
++
++int
++dma_supported(struct device *dev, u64 mask)
++{
++	if (swiotlb)
++		return swiotlb_dma_supported(dev, mask);
++	/*
++	 * By default we'll BUG when an infeasible DMA is requested, and
++	 * request swiotlb=force (see IOMMU_BUG_ON).
++	 */
++	return 1;
++}
++EXPORT_SYMBOL(dma_supported);
++
++void *dma_alloc_coherent(struct device *dev, size_t size,
++			   dma_addr_t *dma_handle, gfp_t gfp)
++{
++	void *ret;
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++	unsigned int order = get_order(size);
++	unsigned long vstart;
++	u64 mask;
++
++	/* ignore region specifiers */
++	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
++
++	if (mem) {
++		int page = bitmap_find_free_region(mem->bitmap, mem->size,
++						     order);
++		if (page >= 0) {
++			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
++			ret = mem->virt_base + (page << PAGE_SHIFT);
++			memset(ret, 0, size);
++			return ret;
++		}
++		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
++			return NULL;
++	}
++
++	vstart = __get_free_pages(gfp, order);
++	ret = (void *)vstart;
++
++	if (dev != NULL && dev->coherent_dma_mask)
++		mask = dev->coherent_dma_mask;
++	else
++		mask = 0xffffffff;
++
++	if (ret != NULL) {
++		if (xen_create_contiguous_region(vstart, order,
++						 fls64(mask)) != 0) {
++			free_pages(vstart, order);
++			return NULL;
++		}
++		memset(ret, 0, size);
++		*dma_handle = virt_to_bus(ret);
++	}
++	return ret;
++}
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++void dma_free_coherent(struct device *dev, size_t size,
++			 void *vaddr, dma_addr_t dma_handle)
++{
++	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
++	int order = get_order(size);
++	
++	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
++		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
++
++		bitmap_release_region(mem->bitmap, page, order);
++	} else {
++		xen_destroy_contiguous_region((unsigned long)vaddr, order);
++		free_pages((unsigned long)vaddr, order);
++	}
++}
++EXPORT_SYMBOL(dma_free_coherent);
++
++#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
++				dma_addr_t device_addr, size_t size, int flags)
++{
++	void __iomem *mem_base;
++	int pages = size >> PAGE_SHIFT;
++	int bitmap_size = (pages + 31)/32;
++
++	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
++		goto out;
++	if (!size)
++		goto out;
++	if (dev->dma_mem)
++		goto out;
++
++	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
++
++	mem_base = ioremap(bus_addr, size);
++	if (!mem_base)
++		goto out;
++
++	dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
++	if (!dev->dma_mem)
++		goto out;
++	memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
++	dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL);
++	if (!dev->dma_mem->bitmap)
++		goto free1_out;
++	memset(dev->dma_mem->bitmap, 0, bitmap_size);
++
++	dev->dma_mem->virt_base = mem_base;
++	dev->dma_mem->device_base = device_addr;
++	dev->dma_mem->size = pages;
++	dev->dma_mem->flags = flags;
++
++	if (flags & DMA_MEMORY_MAP)
++		return DMA_MEMORY_MAP;
++
++	return DMA_MEMORY_IO;
++
++ free1_out:
++	kfree(dev->dma_mem->bitmap);
++ out:
++	return 0;
++}
++EXPORT_SYMBOL(dma_declare_coherent_memory);
++
++void dma_release_declared_memory(struct device *dev)
++{
++	struct dma_coherent_mem *mem = dev->dma_mem;
++	
++	if(!mem)
++		return;
++	dev->dma_mem = NULL;
++	iounmap(mem->virt_base);
++	kfree(mem->bitmap);
++	kfree(mem);
++}
++EXPORT_SYMBOL(dma_release_declared_memory);
++
++void *dma_mark_declared_memory_occupied(struct device *dev,
++					dma_addr_t device_addr, size_t size)
++{
++	struct dma_coherent_mem *mem = dev->dma_mem;
++	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	int pos, err;
++
++	if (!mem)
++		return ERR_PTR(-EINVAL);
++
++	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
++	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
++	if (err != 0)
++		return ERR_PTR(err);
++	return mem->virt_base + (pos << PAGE_SHIFT);
++}
++EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
++#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
++
++dma_addr_t
++dma_map_single(struct device *dev, void *ptr, size_t size,
++	       enum dma_data_direction direction)
++{
++	dma_addr_t dma;
++
++	if (direction == DMA_NONE)
++		BUG();
++	WARN_ON(size == 0);
++
++	if (swiotlb) {
++		dma = swiotlb_map_single(dev, ptr, size, direction);
++	} else {
++		dma = gnttab_dma_map_page(virt_to_page(ptr)) +
++		      offset_in_page(ptr);
++		IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size));
++		IOMMU_BUG_ON(address_needs_mapping(dev, dma));
++	}
++
++	flush_write_buffers();
++	return dma;
++}
++EXPORT_SYMBOL(dma_map_single);
++
++void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++		 enum dma_data_direction direction)
++{
++	if (direction == DMA_NONE)
++		BUG();
++	if (swiotlb)
++		swiotlb_unmap_single(dev, dma_addr, size, direction);
++	else
++		gnttab_dma_unmap_page(dma_addr);
++}
++EXPORT_SYMBOL(dma_unmap_single);
++
++void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++			enum dma_data_direction direction)
++{
++	if (swiotlb)
++		swiotlb_sync_single_for_cpu(dev, dma_handle, size, direction);
++}
++EXPORT_SYMBOL(dma_sync_single_for_cpu);
++
++void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++                           enum dma_data_direction direction)
++{
++	if (swiotlb)
++		swiotlb_sync_single_for_device(dev, dma_handle, size, direction);
++}
++EXPORT_SYMBOL(dma_sync_single_for_device);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2008-07-21 11:00:32.000000000 +0200
+@@ -0,0 +1,877 @@
++/*
++ *  linux/arch/i386/kernel/process.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Pentium III FXSR, SSE support
++ *	Gareth Hughes <gareth@valinux.com>, May 2000
++ */
++
++/*
++ * This file handles the architecture-dependent parts of process handling..
++ */
++
++#include <stdarg.h>
++
++#include <linux/cpu.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/elfcore.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/stddef.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/mc146818rtc.h>
++#include <linux/module.h>
++#include <linux/kallsyms.h>
++#include <linux/ptrace.h>
++#include <linux/random.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/ldt.h>
++#include <asm/processor.h>
++#include <asm/i387.h>
++#include <asm/desc.h>
++#include <asm/vm86.h>
++#ifdef CONFIG_MATH_EMULATION
++#include <asm/math_emu.h>
++#endif
++
++#include <xen/interface/physdev.h>
++#include <xen/interface/vcpu.h>
++#include <xen/cpu_hotplug.h>
++
++#include <linux/err.h>
++
++#include <asm/tlbflush.h>
++#include <asm/cpu.h>
++
++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++
++static int hlt_counter;
++
++unsigned long boot_option_idle_override = 0;
++EXPORT_SYMBOL(boot_option_idle_override);
++
++/*
++ * Return saved PC of a blocked thread.
++ */
++unsigned long thread_saved_pc(struct task_struct *tsk)
++{
++	return ((unsigned long *)tsk->thread.esp)[3];
++}
++
++/*
++ * Powermanagement idle function, if any..
++ */
++void (*pm_idle)(void);
++EXPORT_SYMBOL(pm_idle);
++static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
++
++void disable_hlt(void)
++{
++	hlt_counter++;
++}
++
++EXPORT_SYMBOL(disable_hlt);
++
++void enable_hlt(void)
++{
++	hlt_counter--;
++}
++
++EXPORT_SYMBOL(enable_hlt);
++
++/*
++ * On SMP it's slightly faster (but much more power-consuming!)
++ * to poll the ->work.need_resched flag instead of waiting for the
++ * cross-CPU IPI to arrive. Use this option with caution.
++ */
++static void poll_idle (void)
++{
++	local_irq_enable();
++
++	asm volatile(
++		"2:"
++		"testl %0, %1;"
++		"rep; nop;"
++		"je 2b;"
++		: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
++}
++
++static void xen_idle(void)
++{
++	local_irq_disable();
++
++	if (need_resched())
++		local_irq_enable();
++	else {
++		current_thread_info()->status &= ~TS_POLLING;
++		smp_mb__after_clear_bit();
++		safe_halt();
++		current_thread_info()->status |= TS_POLLING;
++	}
++}
++#ifdef CONFIG_APM_MODULE
++EXPORT_SYMBOL(default_idle);
++#endif
++
++#ifdef CONFIG_HOTPLUG_CPU
++extern cpumask_t cpu_initialized;
++static inline void play_dead(void)
++{
++	idle_task_exit();
++	local_irq_disable();
++	cpu_clear(smp_processor_id(), cpu_initialized);
++	preempt_enable_no_resched();
++	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
++	cpu_bringup();
++}
++#else
++static inline void play_dead(void)
++{
++	BUG();
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++/*
++ * The idle thread. There's no useful work to be
++ * done, so just try to conserve power and have a
++ * low exit latency (ie sit in a loop waiting for
++ * somebody to say that they'd like to reschedule)
++ */
++void cpu_idle(void)
++{
++	int cpu = smp_processor_id();
++
++	current_thread_info()->status |= TS_POLLING;
++
++	/* endless idle loop with no priority at all */
++	while (1) {
++		while (!need_resched()) {
++			void (*idle)(void);
++
++			if (__get_cpu_var(cpu_idle_state))
++				__get_cpu_var(cpu_idle_state) = 0;
++
++			rmb();
++			idle = xen_idle; /* no alternatives */
++
++			if (cpu_is_offline(cpu))
++				play_dead();
++
++			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
++			idle();
++		}
++		preempt_enable_no_resched();
++		schedule();
++		preempt_disable();
++	}
++}
++
++void cpu_idle_wait(void)
++{
++	unsigned int cpu, this_cpu = get_cpu();
++	cpumask_t map;
++
++	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
++	put_cpu();
++
++	cpus_clear(map);
++	for_each_online_cpu(cpu) {
++		per_cpu(cpu_idle_state, cpu) = 1;
++		cpu_set(cpu, map);
++	}
++
++	__get_cpu_var(cpu_idle_state) = 0;
++
++	wmb();
++	do {
++		ssleep(1);
++		for_each_online_cpu(cpu) {
++			if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
++				cpu_clear(cpu, map);
++		}
++		cpus_and(map, map, cpu_online_map);
++	} while (!cpus_empty(map));
++}
++EXPORT_SYMBOL_GPL(cpu_idle_wait);
++
++void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
++{
++}
++
++static int __init idle_setup (char *str)
++{
++	if (!strncmp(str, "poll", 4)) {
++		printk("using polling idle threads.\n");
++		pm_idle = poll_idle;
++	}
++
++	boot_option_idle_override = 1;
++	return 1;
++}
++
++__setup("idle=", idle_setup);
++
++void show_regs(struct pt_regs * regs)
++{
++	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
++
++	printk("\n");
++	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
++	printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
++	print_symbol("EIP is at %s\n", regs->eip);
++
++	if (user_mode_vm(regs))
++		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
++	printk(" EFLAGS: %08lx    %s  (%s %.*s)\n",
++	       regs->eflags, print_tainted(), system_utsname.release,
++	       (int)strcspn(system_utsname.version, " "),
++	       system_utsname.version);
++	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
++		regs->eax,regs->ebx,regs->ecx,regs->edx);
++	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
++		regs->esi, regs->edi, regs->ebp);
++	printk(" DS: %04x ES: %04x\n",
++		0xffff & regs->xds,0xffff & regs->xes);
++
++	cr0 = read_cr0();
++	cr2 = read_cr2();
++	cr3 = read_cr3();
++	cr4 = read_cr4_safe();
++	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
++	show_trace(NULL, regs, &regs->esp);
++}
++
++/*
++ * This gets run with %ebx containing the
++ * function to call, and %edx containing
++ * the "args".
++ */
++extern void kernel_thread_helper(void);
++__asm__(".section .text\n"
++	".align 4\n"
++	"kernel_thread_helper:\n\t"
++	"movl %edx,%eax\n\t"
++	"pushl %edx\n\t"
++	"call *%ebx\n\t"
++	"pushl %eax\n\t"
++	"call do_exit\n"
++	".previous");
++
++/*
++ * Create a kernel thread
++ */
++int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
++{
++	struct pt_regs regs;
++
++	memset(&regs, 0, sizeof(regs));
++
++	regs.ebx = (unsigned long) fn;
++	regs.edx = (unsigned long) arg;
++
++	regs.xds = __USER_DS;
++	regs.xes = __USER_DS;
++	regs.orig_eax = -1;
++	regs.eip = (unsigned long) kernel_thread_helper;
++	regs.xcs = GET_KERNEL_CS();
++	regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
++
++	/* Ok, create the new process.. */
++	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
++}
++EXPORT_SYMBOL(kernel_thread);
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++	/* The process may have allocated an io port bitmap... nuke it. */
++	if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
++		struct task_struct *tsk = current;
++		struct thread_struct *t = &tsk->thread;
++		struct physdev_set_iobitmap set_iobitmap;
++		memset(&set_iobitmap, 0, sizeof(set_iobitmap));
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &set_iobitmap));
++		kfree(t->io_bitmap_ptr);
++		t->io_bitmap_ptr = NULL;
++		clear_thread_flag(TIF_IO_BITMAP);
++	}
++}
++
++void flush_thread(void)
++{
++	struct task_struct *tsk = current;
++
++	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
++	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
++	clear_tsk_thread_flag(tsk, TIF_DEBUG);
++	/*
++	 * Forget coprocessor state..
++	 */
++	clear_fpu(tsk);
++	clear_used_math();
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++	BUG_ON(dead_task->mm);
++	release_vm86_irqs(dead_task);
++}
++
++/*
++ * This gets called before we allocate a new thread and copy
++ * the current task into it.
++ */
++void prepare_to_copy(struct task_struct *tsk)
++{
++	unlazy_fpu(tsk);
++}
++
++int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
++	unsigned long unused,
++	struct task_struct * p, struct pt_regs * regs)
++{
++	struct pt_regs * childregs;
++	struct task_struct *tsk;
++	int err;
++
++	childregs = task_pt_regs(p);
++	*childregs = *regs;
++	childregs->eax = 0;
++	childregs->esp = esp;
++
++	p->thread.esp = (unsigned long) childregs;
++	p->thread.esp0 = (unsigned long) (childregs+1);
++
++	p->thread.eip = (unsigned long) ret_from_fork;
++
++	savesegment(fs,p->thread.fs);
++	savesegment(gs,p->thread.gs);
++
++	tsk = current;
++	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
++		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++		if (!p->thread.io_bitmap_ptr) {
++			p->thread.io_bitmap_max = 0;
++			return -ENOMEM;
++		}
++		memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
++			IO_BITMAP_BYTES);
++		set_tsk_thread_flag(p, TIF_IO_BITMAP);
++	}
++
++	/*
++	 * Set a new TLS for the child thread?
++	 */
++	if (clone_flags & CLONE_SETTLS) {
++		struct desc_struct *desc;
++		struct user_desc info;
++		int idx;
++
++		err = -EFAULT;
++		if (copy_from_user(&info, (void __user *)childregs->esi, sizeof(info)))
++			goto out;
++		err = -EINVAL;
++		if (LDT_empty(&info))
++			goto out;
++
++		idx = info.entry_number;
++		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
++			goto out;
++
++		desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
++		desc->a = LDT_entry_a(&info);
++		desc->b = LDT_entry_b(&info);
++	}
++
++	p->thread.iopl = current->thread.iopl;
++
++	err = 0;
++ out:
++	if (err && p->thread.io_bitmap_ptr) {
++		kfree(p->thread.io_bitmap_ptr);
++		p->thread.io_bitmap_max = 0;
++	}
++	return err;
++}
++
++/*
++ * fill in the user structure for a core dump..
++ */
++void dump_thread(struct pt_regs * regs, struct user * dump)
++{
++	int i;
++
++/* changed the size calculations - should hopefully work better. lbt */
++	dump->magic = CMAGIC;
++	dump->start_code = 0;
++	dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
++	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
++	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
++	dump->u_dsize -= dump->u_tsize;
++	dump->u_ssize = 0;
++	for (i = 0; i < 8; i++)
++		dump->u_debugreg[i] = current->thread.debugreg[i];  
++
++	if (dump->start_stack < TASK_SIZE)
++		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
++
++	dump->regs.ebx = regs->ebx;
++	dump->regs.ecx = regs->ecx;
++	dump->regs.edx = regs->edx;
++	dump->regs.esi = regs->esi;
++	dump->regs.edi = regs->edi;
++	dump->regs.ebp = regs->ebp;
++	dump->regs.eax = regs->eax;
++	dump->regs.ds = regs->xds;
++	dump->regs.es = regs->xes;
++	savesegment(fs,dump->regs.fs);
++	savesegment(gs,dump->regs.gs);
++	dump->regs.orig_eax = regs->orig_eax;
++	dump->regs.eip = regs->eip;
++	dump->regs.cs = regs->xcs;
++	dump->regs.eflags = regs->eflags;
++	dump->regs.esp = regs->esp;
++	dump->regs.ss = regs->xss;
++
++	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
++}
++EXPORT_SYMBOL(dump_thread);
++
++/* 
++ * Capture the user space registers if the task is not running (in user space)
++ */
++int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
++{
++	struct pt_regs ptregs = *task_pt_regs(tsk);
++	ptregs.xcs &= 0xffff;
++	ptregs.xds &= 0xffff;
++	ptregs.xes &= 0xffff;
++	ptregs.xss &= 0xffff;
++
++	elf_core_copy_regs(regs, &ptregs);
++
++	return 1;
++}
++
++static noinline void __switch_to_xtra(struct task_struct *next_p)
++{
++	struct thread_struct *next;
++
++	next = &next_p->thread;
++
++	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
++		set_debugreg(next->debugreg[0], 0);
++		set_debugreg(next->debugreg[1], 1);
++		set_debugreg(next->debugreg[2], 2);
++		set_debugreg(next->debugreg[3], 3);
++		/* no 4 and 5 */
++		set_debugreg(next->debugreg[6], 6);
++		set_debugreg(next->debugreg[7], 7);
++	}
++}
++
++/*
++ * This function selects if the context switch from prev to next
++ * has to tweak the TSC disable bit in the cr4.
++ */
++static inline void disable_tsc(struct task_struct *prev_p,
++			       struct task_struct *next_p)
++{
++	struct thread_info *prev, *next;
++
++	/*
++	 * gcc should eliminate the ->thread_info dereference if
++	 * has_secure_computing returns 0 at compile time (SECCOMP=n).
++	 */
++	prev = task_thread_info(prev_p);
++	next = task_thread_info(next_p);
++
++	if (has_secure_computing(prev) || has_secure_computing(next)) {
++		/* slow path here */
++		if (has_secure_computing(prev) &&
++		    !has_secure_computing(next)) {
++			write_cr4(read_cr4() & ~X86_CR4_TSD);
++		} else if (!has_secure_computing(prev) &&
++			   has_secure_computing(next))
++			write_cr4(read_cr4() | X86_CR4_TSD);
++	}
++}
++
++/*
++ *	switch_to(x,yn) should switch tasks from x to y.
++ *
++ * We fsave/fwait so that an exception goes off at the right time
++ * (as a call from the fsave or fwait in effect) rather than to
++ * the wrong process. Lazy FP saving no longer makes any sense
++ * with modern CPU's, and this simplifies a lot of things (SMP
++ * and UP become the same).
++ *
++ * NOTE! We used to use the x86 hardware context switching. The
++ * reason for not using it any more becomes apparent when you
++ * try to recover gracefully from saved state that is no longer
++ * valid (stale segment register values in particular). With the
++ * hardware task-switch, there is no way to fix up bad state in
++ * a reasonable manner.
++ *
++ * The fact that Intel documents the hardware task-switching to
++ * be slow is a fairly red herring - this code is not noticeably
++ * faster. However, there _is_ some room for improvement here,
++ * so the performance issues may eventually be a valid point.
++ * More important, however, is the fact that this allows us much
++ * more flexibility.
++ *
++ * The return value (in %eax) will be the "prev" task after
++ * the task-switch, and shows up in ret_from_fork in entry.S,
++ * for example.
++ */
++struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
++{
++	struct thread_struct *prev = &prev_p->thread,
++				 *next = &next_p->thread;
++	int cpu = smp_processor_id();
++#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. */
++
++	/*
++	 * This is basically '__unlazy_fpu', except that we queue a
++	 * multicall to indicate FPU task switch, rather than
++	 * synchronously trapping to Xen.
++	 */
++	if (prev_p->thread_info->status & TS_USEDFPU) {
++		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
++		mcl->op      = __HYPERVISOR_fpu_taskswitch;
++		mcl->args[0] = 1;
++		mcl++;
++	}
++#if 0 /* lazy fpu sanity check */
++	else BUG_ON(!(read_cr0() & 8));
++#endif
++
++	/*
++	 * Reload esp0.
++	 * This is load_esp0(tss, next) with a multicall.
++	 */
++	mcl->op      = __HYPERVISOR_stack_switch;
++	mcl->args[0] = __KERNEL_DS;
++	mcl->args[1] = next->esp0;
++	mcl++;
++
++	/*
++	 * Load the per-thread Thread-Local Storage descriptor.
++	 * This is load_TLS(next, cpu) with multicalls.
++	 */
++#define C(i) do {							\
++	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
++		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
++		mcl->op = __HYPERVISOR_update_descriptor;		\
++		*(u64 *)&mcl->args[0] =	virt_to_machine(		\
++			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
++		*(u64 *)&mcl->args[2] = *(u64 *)&next->tls_array[i];	\
++		mcl++;							\
++	}								\
++} while (0)
++	C(0); C(1); C(2);
++#undef C
++
++	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++;
++	}
++
++	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
++		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();
++
++	/*
++	 * Restore %fs and %gs if needed.
++	 *
++	 * Glibc normally makes %fs be zero, and %gs is one of
++	 * the TLS segments.
++	 */
++	if (unlikely(next->fs))
++		loadsegment(fs, next->fs);
++
++	if (next->gs)
++		loadsegment(gs, next->gs);
++
++	/*
++	 * Now maybe handle debug registers
++	 */
++	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
++		__switch_to_xtra(next_p);
++
++	disable_tsc(prev_p, next_p);
++
++	return prev_p;
++}
++
++asmlinkage int sys_fork(struct pt_regs regs)
++{
++	return do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
++}
++
++asmlinkage int sys_clone(struct pt_regs regs)
++{
++	unsigned long clone_flags;
++	unsigned long newsp;
++	int __user *parent_tidptr, *child_tidptr;
++
++	clone_flags = regs.ebx;
++	newsp = regs.ecx;
++	parent_tidptr = (int __user *)regs.edx;
++	child_tidptr = (int __user *)regs.edi;
++	if (!newsp)
++		newsp = regs.esp;
++	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
++}
++
++/*
++ * This is trivial, and on the face of it looks like it
++ * could equally well be done in user mode.
++ *
++ * Not so, for quite unobvious reasons - register pressure.
++ * In user mode vfork() cannot have a stack frame, and if
++ * done by calling the "clone()" system call directly, you
++ * do not have enough call-clobbered registers to hold all
++ * the information you need.
++ */
++asmlinkage int sys_vfork(struct pt_regs regs)
++{
++	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
++}
++
++/*
++ * sys_execve() executes a new program.
++ */
++asmlinkage int sys_execve(struct pt_regs regs)
++{
++	int error;
++	char * filename;
++
++	filename = getname((char __user *) regs.ebx);
++	error = PTR_ERR(filename);
++	if (IS_ERR(filename))
++		goto out;
++	error = do_execve(filename,
++			(char __user * __user *) regs.ecx,
++			(char __user * __user *) regs.edx,
++			&regs);
++	if (error == 0) {
++		task_lock(current);
++		current->ptrace &= ~PT_DTRACE;
++		task_unlock(current);
++		/* Make sure we don't return using sysenter.. */
++		set_thread_flag(TIF_IRET);
++	}
++	putname(filename);
++out:
++	return error;
++}
++
++#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
++#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
++
++unsigned long get_wchan(struct task_struct *p)
++{
++	unsigned long ebp, esp, eip;
++	unsigned long stack_page;
++	int count = 0;
++	if (!p || p == current || p->state == TASK_RUNNING)
++		return 0;
++	stack_page = (unsigned long)task_stack_page(p);
++	esp = p->thread.esp;
++	if (!stack_page || esp < stack_page || esp > top_esp+stack_page)
++		return 0;
++	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
++	ebp = *(unsigned long *) esp;
++	do {
++		if (ebp < stack_page || ebp > top_ebp+stack_page)
++			return 0;
++		eip = *(unsigned long *) (ebp+4);
++		if (!in_sched_functions(eip))
++			return eip;
++		ebp = *(unsigned long *) ebp;
++	} while (count++ < 16);
++	return 0;
++}
++
++/*
++ * sys_alloc_thread_area: get a yet unused TLS descriptor index.
++ */
++static int get_free_idx(void)
++{
++	struct thread_struct *t = &current->thread;
++	int idx;
++
++	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
++		if (desc_empty(t->tls_array + idx))
++			return idx + GDT_ENTRY_TLS_MIN;
++	return -ESRCH;
++}
++
++/*
++ * Set a given TLS descriptor:
++ */
++asmlinkage int sys_set_thread_area(struct user_desc __user *u_info)
++{
++	struct thread_struct *t = &current->thread;
++	struct user_desc info;
++	struct desc_struct *desc;
++	int cpu, idx;
++
++	if (copy_from_user(&info, u_info, sizeof(info)))
++		return -EFAULT;
++	idx = info.entry_number;
++
++	/*
++	 * index -1 means the kernel should try to find and
++	 * allocate an empty descriptor:
++	 */
++	if (idx == -1) {
++		idx = get_free_idx();
++		if (idx < 0)
++			return idx;
++		if (put_user(idx, &u_info->entry_number))
++			return -EFAULT;
++	}
++
++	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
++		return -EINVAL;
++
++	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
++
++	/*
++	 * We must not get preempted while modifying the TLS.
++	 */
++	cpu = get_cpu();
++
++	if (LDT_empty(&info)) {
++		desc->a = 0;
++		desc->b = 0;
++	} else {
++		desc->a = LDT_entry_a(&info);
++		desc->b = LDT_entry_b(&info);
++	}
++	load_TLS(t, cpu);
++
++	put_cpu();
++
++	return 0;
++}
++
++/*
++ * Get the current Thread-Local Storage area:
++ */
++
++#define GET_BASE(desc) ( \
++	(((desc)->a >> 16) & 0x0000ffff) | \
++	(((desc)->b << 16) & 0x00ff0000) | \
++	( (desc)->b        & 0xff000000)   )
++
++#define GET_LIMIT(desc) ( \
++	((desc)->a & 0x0ffff) | \
++	 ((desc)->b & 0xf0000) )
++	
++#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)
++#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
++#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
++#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
++#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
++#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
++
++asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
++{
++	struct user_desc info;
++	struct desc_struct *desc;
++	int idx;
++
++	if (get_user(idx, &u_info->entry_number))
++		return -EFAULT;
++	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
++		return -EINVAL;
++
++	memset(&info, 0, sizeof(info));
++
++	desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
++
++	info.entry_number = idx;
++	info.base_addr = GET_BASE(desc);
++	info.limit = GET_LIMIT(desc);
++	info.seg_32bit = GET_32BIT(desc);
++	info.contents = GET_CONTENTS(desc);
++	info.read_exec_only = !GET_WRITABLE(desc);
++	info.limit_in_pages = GET_LIMIT_PAGES(desc);
++	info.seg_not_present = !GET_PRESENT(desc);
++	info.useable = GET_USEABLE(desc);
++
++	if (copy_to_user(u_info, &info, sizeof(info)))
++		return -EFAULT;
++	return 0;
++}
++
++unsigned long arch_align_stack(unsigned long sp)
++{
++	if (randomize_va_space)
++		sp -= get_random_int() % 8192;
++	return sp & ~0xf;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,47 @@
++/*
++ * This file contains work-arounds for x86 and x86_64 platform bugs.
++ */
++#include <linux/pci.h>
++#include <linux/irq.h>
++
++#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI)
++
++static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
++{
++	u8 config, rev;
++	u32 word;
++
++	/* BIOS may enable hardware IRQ balancing for
++	 * E7520/E7320/E7525(revision ID 0x9 and below)
++	 * based platforms.
++	 * Disable SW irqbalance/affinity on those platforms.
++	 */
++	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
++	if (rev > 0x9)
++		return;
++
++	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
++
++	/* enable access to config space*/
++	pci_read_config_byte(dev, 0xf4, &config);
++	pci_write_config_byte(dev, 0xf4, config|0x2);
++
++	/* read xTPR register */
++	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
++
++	if (!(word & (1 << 13))) {
++		struct xen_platform_op op;
++		printk(KERN_INFO "Disabling irq balancing and affinity\n");
++		op.cmd = XENPF_platform_quirk;
++		op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
++		WARN_ON(HYPERVISOR_platform_op(&op));
++	}
++
++	/* put back the original value for config space*/
++	if (!(config & 0x2))
++		pci_write_config_byte(dev, 0xf4, config);
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
++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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2008-04-22 15:41:51.000000000 +0200
+@@ -0,0 +1,1919 @@
++/*
++ *  linux/arch/i386/kernel/setup.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ *
++ *  Memory region support
++ *	David Parsons <orc@pell.chi.il.us>, July-August 1999
++ *
++ *  Added E820 sanitization routine (removes overlapping memory regions);
++ *  Brian Moyle <bmoyle@mvista.com>, February 2001
++ *
++ * Moved CPU detection code to cpu/${cpu}.c
++ *    Patrick Mochel <mochel@osdl.org>, March 2002
++ *
++ *  Provisions for empty E820 memory regions (reported by certain BIOSes).
++ *  Alex Achenbach <xela@slit.de>, December 2002.
++ *
++ */
++
++/*
++ * This file handles the architecture-dependent parts of initialization
++ */
++
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <linux/screen_info.h>
++#include <linux/ioport.h>
++#include <linux/acpi.h>
++#include <linux/apm_bios.h>
++#include <linux/initrd.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/platform_device.h>
++#include <linux/console.h>
++#include <linux/mca.h>
++#include <linux/root_dev.h>
++#include <linux/highmem.h>
++#include <linux/module.h>
++#include <linux/efi.h>
++#include <linux/init.h>
++#include <linux/edd.h>
++#include <linux/nodemask.h>
++#include <linux/kernel.h>
++#include <linux/percpu.h>
++#include <linux/notifier.h>
++#include <linux/kexec.h>
++#include <linux/crash_dump.h>
++#include <linux/dmi.h>
++#include <linux/pfn.h>
++
++#include <video/edid.h>
++
++#include <asm/apic.h>
++#include <asm/e820.h>
++#include <asm/mpspec.h>
++#include <asm/setup.h>
++#include <asm/arch_hooks.h>
++#include <asm/sections.h>
++#include <asm/io_apic.h>
++#include <asm/ist.h>
++#include <asm/io.h>
++#include <asm/hypervisor.h>
++#include <xen/interface/physdev.h>
++#include <xen/interface/memory.h>
++#include <xen/features.h>
++#include <xen/firmware.h>
++#include <xen/xencons.h>
++#include <setup_arch.h>
++#include <bios_ebda.h>
++
++#ifdef CONFIG_XEN
++#include <xen/interface/kexec.h>
++#endif
++
++/* Forward Declaration. */
++void __init find_max_pfn(void);
++
++static int xen_panic_event(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xen_panic_block = {
++	xen_panic_event, NULL, 0 /* try to go last */
++};
++
++extern char hypercall_page[PAGE_SIZE];
++EXPORT_SYMBOL(hypercall_page);
++
++int disable_pse __devinitdata = 0;
++
++/*
++ * Machine setup..
++ */
++
++#ifdef CONFIG_EFI
++int efi_enabled = 0;
++EXPORT_SYMBOL(efi_enabled);
++#endif
++
++/* cpu data as detected by the assembly code in head.S */
++struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
++/* common cpu data for all cpus */
++struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
++EXPORT_SYMBOL(boot_cpu_data);
++
++unsigned long mmu_cr4_features;
++
++#ifdef	CONFIG_ACPI
++	int acpi_disabled = 0;
++#else
++	int acpi_disabled = 1;
++#endif
++EXPORT_SYMBOL(acpi_disabled);
++
++#ifdef	CONFIG_ACPI
++int __initdata acpi_force = 0;
++extern acpi_interrupt_flags	acpi_sci_flags;
++#endif
++
++/* for MCA, but anyone else can use it if they want */
++unsigned int machine_id;
++#ifdef CONFIG_MCA
++EXPORT_SYMBOL(machine_id);
++#endif
++unsigned int machine_submodel_id;
++unsigned int BIOS_revision;
++unsigned int mca_pentium_flag;
++
++/* For PCI or other memory-mapped resources */
++unsigned long pci_mem_start = 0x10000000;
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL(pci_mem_start);
++#endif
++
++/* Boot loader ID as an integer, for the benefit of proc_dointvec */
++int bootloader_type;
++
++/* user-defined highmem size */
++static unsigned int highmem_pages = -1;
++
++/*
++ * Setup options
++ */
++struct drive_info_struct { char dummy[32]; } drive_info;
++#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
++    defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
++EXPORT_SYMBOL(drive_info);
++#endif
++struct screen_info screen_info;
++EXPORT_SYMBOL(screen_info);
++struct apm_info apm_info;
++EXPORT_SYMBOL(apm_info);
++struct sys_desc_table_struct {
++	unsigned short length;
++	unsigned char table[0];
++};
++struct edid_info edid_info;
++EXPORT_SYMBOL_GPL(edid_info);
++#ifndef CONFIG_XEN
++#define copy_edid() (edid_info = EDID_INFO)
++#endif
++struct ist_info ist_info;
++#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
++	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
++EXPORT_SYMBOL(ist_info);
++#endif
++struct e820map e820;
++#ifdef CONFIG_XEN
++struct e820map machine_e820;
++#endif
++
++extern void early_cpu_init(void);
++extern void generic_apic_probe(char *);
++extern int root_mountflags;
++
++unsigned long saved_videomode;
++
++#define RAMDISK_IMAGE_START_MASK  	0x07FF
++#define RAMDISK_PROMPT_FLAG		0x8000
++#define RAMDISK_LOAD_FLAG		0x4000	
++
++static char command_line[COMMAND_LINE_SIZE];
++
++unsigned char __initdata boot_params[PARAM_SIZE];
++
++static struct resource data_resource = {
++	.name	= "Kernel data",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource code_resource = {
++	.name	= "Kernel code",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource system_rom_resource = {
++	.name	= "System ROM",
++	.start	= 0xf0000,
++	.end	= 0xfffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource extension_rom_resource = {
++	.name	= "Extension ROM",
++	.start	= 0xe0000,
++	.end	= 0xeffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource adapter_rom_resources[] = { {
++	.name 	= "Adapter ROM",
++	.start	= 0xc8000,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++} };
++
++#define ADAPTER_ROM_RESOURCES \
++	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
++
++static struct resource video_rom_resource = {
++	.name 	= "Video ROM",
++	.start	= 0xc0000,
++	.end	= 0xc7fff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource video_ram_resource = {
++	.name	= "Video RAM area",
++	.start	= 0xa0000,
++	.end	= 0xbffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource standard_io_resources[] = { {
++	.name	= "dma1",
++	.start	= 0x0000,
++	.end	= 0x001f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic1",
++	.start	= 0x0020,
++	.end	= 0x0021,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer0",
++	.start	= 0x0040,
++	.end    = 0x0043,
++	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer1",
++	.start  = 0x0050,
++	.end    = 0x0053,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "keyboard",
++	.start	= 0x0060,
++	.end	= 0x006f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma page reg",
++	.start	= 0x0080,
++	.end	= 0x008f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic2",
++	.start	= 0x00a0,
++	.end	= 0x00a1,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma2",
++	.start	= 0x00c0,
++	.end	= 0x00df,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "fpu",
++	.start	= 0x00f0,
++	.end	= 0x00ff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++} };
++
++#define STANDARD_IO_RESOURCES \
++	(sizeof standard_io_resources / sizeof standard_io_resources[0])
++
++#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
++
++static int __init romchecksum(unsigned char *rom, unsigned long length)
++{
++	unsigned char *p, sum = 0;
++
++	for (p = rom; p < rom + length; p++)
++		sum += *p;
++	return sum == 0;
++}
++
++static void __init probe_roms(void)
++{
++	unsigned long start, length, upper;
++	unsigned char *rom;
++	int	      i;
++
++#ifdef CONFIG_XEN
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return;
++#endif
++
++	/* video rom */
++	upper = adapter_rom_resources[0].start;
++	for (start = video_rom_resource.start; start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		video_rom_resource.start = start;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* if checksum okay, trust length byte */
++		if (length && romchecksum(rom, length))
++			video_rom_resource.end = start + length - 1;
++
++		request_resource(&iomem_resource, &video_rom_resource);
++		break;
++	}
++
++	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
++	if (start < upper)
++		start = upper;
++
++	/* system rom */
++	request_resource(&iomem_resource, &system_rom_resource);
++	upper = system_rom_resource.start;
++
++	/* check for extension rom (ignore length byte!) */
++	rom = isa_bus_to_virt(extension_rom_resource.start);
++	if (romsignature(rom)) {
++		length = extension_rom_resource.end - extension_rom_resource.start + 1;
++		if (romchecksum(rom, length)) {
++			request_resource(&iomem_resource, &extension_rom_resource);
++			upper = extension_rom_resource.start;
++		}
++	}
++
++	/* check for adapter roms on 2k boundaries */
++	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* but accept any length that fits if checksum okay */
++		if (!length || start + length > upper || !romchecksum(rom, length))
++			continue;
++
++		adapter_rom_resources[i].start = start;
++		adapter_rom_resources[i].end = start + length - 1;
++		request_resource(&iomem_resource, &adapter_rom_resources[i]);
++
++		start = adapter_rom_resources[i++].end & ~2047UL;
++	}
++}
++
++/*
++ * Point at the empty zero page to start with. We map the real shared_info
++ * page as soon as fixmap is up and running.
++ */
++shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++EXPORT_SYMBOL(HYPERVISOR_shared_info);
++
++unsigned long *phys_to_machine_mapping;
++unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[16];
++EXPORT_SYMBOL(phys_to_machine_mapping);
++
++/* Raw start-of-day parameters from the hypervisor. */
++start_info_t *xen_start_info;
++EXPORT_SYMBOL(xen_start_info);
++
++void __init add_memory_region(unsigned long long start,
++			      unsigned long long size, int type)
++{
++	int x;
++
++	if (!efi_enabled) {
++       		x = e820.nr_map;
++
++		if (x == E820MAX) {
++		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++		    return;
++		}
++
++		e820.map[x].addr = start;
++		e820.map[x].size = size;
++		e820.map[x].type = type;
++		e820.nr_map++;
++	}
++} /* add_memory_region */
++
++static void __init limit_regions(unsigned long long size)
++{
++	unsigned long long current_addr = 0;
++	int i;
++
++	if (efi_enabled) {
++		efi_memory_desc_t *md;
++		void *p;
++
++		for (p = memmap.map, i = 0; p < memmap.map_end;
++			p += memmap.desc_size, i++) {
++			md = p;
++			current_addr = md->phys_addr + (md->num_pages << 12);
++			if (md->type == EFI_CONVENTIONAL_MEMORY) {
++				if (current_addr >= size) {
++					md->num_pages -=
++						(((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
++					memmap.nr_map = i + 1;
++					return;
++				}
++			}
++		}
++	}
++	for (i = 0; i < e820.nr_map; i++) {
++		current_addr = e820.map[i].addr + e820.map[i].size;
++		if (current_addr < size)
++			continue;
++
++		if (e820.map[i].type != E820_RAM)
++			continue;
++
++		if (e820.map[i].addr >= size) {
++			/*
++			 * This region starts past the end of the
++			 * requested size, skip it completely.
++			 */
++			e820.nr_map = i;
++		} else {
++			e820.nr_map = i + 1;
++			e820.map[i].size -= current_addr - size;
++		}
++		return;
++	}
++#ifdef CONFIG_XEN
++	if (i==e820.nr_map && current_addr < size) {
++		/*
++                 * The e820 map finished before our requested size so
++                 * extend the final entry to the requested address.
++                 */
++		--i;
++		if (e820.map[i].type == E820_RAM)
++			e820.map[i].size -= current_addr - size;
++		else
++			add_memory_region(current_addr, size - current_addr, E820_RAM);
++	}
++#endif
++}
++
++#define E820_DEBUG	1
++
++static void __init print_memory_map(char *who)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		printk(" %s: %016Lx - %016Lx ", who,
++			e820.map[i].addr,
++			e820.map[i].addr + e820.map[i].size);
++		switch (e820.map[i].type) {
++		case E820_RAM:	printk("(usable)\n");
++				break;
++		case E820_RESERVED:
++				printk("(reserved)\n");
++				break;
++		case E820_ACPI:
++				printk("(ACPI data)\n");
++				break;
++		case E820_NVS:
++				printk("(ACPI NVS)\n");
++				break;
++		default:	printk("type %lu\n", e820.map[i].type);
++				break;
++		}
++	}
++}
++
++/*
++ * Sanitize the BIOS e820 map.
++ *
++ * Some e820 responses include overlapping entries.  The following 
++ * replaces the original e820 map with a new one, removing overlaps.
++ *
++ */
++struct change_member {
++	struct e820entry *pbios; /* pointer to original bios entry */
++	unsigned long long addr; /* address for this change point */
++};
++static struct change_member change_point_list[2*E820MAX] __initdata;
++static struct change_member *change_point[2*E820MAX] __initdata;
++static struct e820entry *overlap_list[E820MAX] __initdata;
++static struct e820entry new_bios[E820MAX] __initdata;
++
++int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
++{
++	struct change_member *change_tmp;
++	unsigned long current_type, last_type;
++	unsigned long long last_addr;
++	int chgidx, still_changing;
++	int overlap_entries;
++	int new_bios_entry;
++	int old_nr, new_nr, chg_nr;
++	int i;
++
++	/*
++		Visually we're performing the following (1,2,3,4 = memory types)...
++
++		Sample memory map (w/overlaps):
++		   ____22__________________
++		   ______________________4_
++		   ____1111________________
++		   _44_____________________
++		   11111111________________
++		   ____________________33__
++		   ___________44___________
++		   __________33333_________
++		   ______________22________
++		   ___________________2222_
++		   _________111111111______
++		   _____________________11_
++		   _________________4______
++
++		Sanitized equivalent (no overlap):
++		   1_______________________
++		   _44_____________________
++		   ___1____________________
++		   ____22__________________
++		   ______11________________
++		   _________1______________
++		   __________3_____________
++		   ___________44___________
++		   _____________33_________
++		   _______________2________
++		   ________________1_______
++		   _________________4______
++		   ___________________2____
++		   ____________________33__
++		   ______________________4_
++	*/
++
++	/* if there's only one memory region, don't bother */
++	if (*pnr_map < 2)
++		return -1;
++
++	old_nr = *pnr_map;
++
++	/* bail out if we find any unreasonable addresses in bios map */
++	for (i=0; i<old_nr; i++)
++		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
++			return -1;
++
++	/* create pointers for initial change-point information (for sorting) */
++	for (i=0; i < 2*old_nr; i++)
++		change_point[i] = &change_point_list[i];
++
++	/* record all known change-points (starting and ending addresses),
++	   omitting those that are for empty memory regions */
++	chgidx = 0;
++	for (i=0; i < old_nr; i++)	{
++		if (biosmap[i].size != 0) {
++			change_point[chgidx]->addr = biosmap[i].addr;
++			change_point[chgidx++]->pbios = &biosmap[i];
++			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
++			change_point[chgidx++]->pbios = &biosmap[i];
++		}
++	}
++	chg_nr = chgidx;    	/* true number of change-points */
++
++	/* sort change-point list by memory addresses (low -> high) */
++	still_changing = 1;
++	while (still_changing)	{
++		still_changing = 0;
++		for (i=1; i < chg_nr; i++)  {
++			/* if <current_addr> > <last_addr>, swap */
++			/* or, if current=<start_addr> & last=<end_addr>, swap */
++			if ((change_point[i]->addr < change_point[i-1]->addr) ||
++				((change_point[i]->addr == change_point[i-1]->addr) &&
++				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
++				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
++			   )
++			{
++				change_tmp = change_point[i];
++				change_point[i] = change_point[i-1];
++				change_point[i-1] = change_tmp;
++				still_changing=1;
++			}
++		}
++	}
++
++	/* create a new bios memory map, removing overlaps */
++	overlap_entries=0;	 /* number of entries in the overlap table */
++	new_bios_entry=0;	 /* index for creating new bios map entries */
++	last_type = 0;		 /* start with undefined memory type */
++	last_addr = 0;		 /* start with 0 as last starting address */
++	/* loop through change-points, determining affect on the new bios map */
++	for (chgidx=0; chgidx < chg_nr; chgidx++)
++	{
++		/* keep track of all overlapping bios entries */
++		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
++		{
++			/* add map entry to overlap list (> 1 entry implies an overlap) */
++			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
++		}
++		else
++		{
++			/* remove entry from list (order independent, so swap with last) */
++			for (i=0; i<overlap_entries; i++)
++			{
++				if (overlap_list[i] == change_point[chgidx]->pbios)
++					overlap_list[i] = overlap_list[overlap_entries-1];
++			}
++			overlap_entries--;
++		}
++		/* if there are overlapping entries, decide which "type" to use */
++		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
++		current_type = 0;
++		for (i=0; i<overlap_entries; i++)
++			if (overlap_list[i]->type > current_type)
++				current_type = overlap_list[i]->type;
++		/* continue building up new bios map based on this information */
++		if (current_type != last_type)	{
++			if (last_type != 0)	 {
++				new_bios[new_bios_entry].size =
++					change_point[chgidx]->addr - last_addr;
++				/* move forward only if the new size was non-zero */
++				if (new_bios[new_bios_entry].size != 0)
++					if (++new_bios_entry >= E820MAX)
++						break; 	/* no more space left for new bios entries */
++			}
++			if (current_type != 0)	{
++				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
++				new_bios[new_bios_entry].type = current_type;
++				last_addr=change_point[chgidx]->addr;
++			}
++			last_type = current_type;
++		}
++	}
++	new_nr = new_bios_entry;   /* retain count for new bios entries */
++
++	/* copy new bios mapping into original location */
++	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
++	*pnr_map = new_nr;
++
++	return 0;
++}
++
++/*
++ * Copy the BIOS e820 map into a safe place.
++ *
++ * Sanity-check it while we're at it..
++ *
++ * If we're lucky and live on a modern system, the setup code
++ * will have given us a memory map that we can use to properly
++ * set up memory.  If we aren't, we'll fake a memory map.
++ *
++ * We check to see that the memory map contains at least 2 elements
++ * before we'll use it, because the detection code in setup.S may
++ * not be perfect and most every PC known to man has two memory
++ * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
++ * thinkpad 560x, for example, does not cooperate with the memory
++ * detection code.)
++ */
++int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++{
++#ifndef CONFIG_XEN
++	/* Only one memory region (or negative)? Ignore it */
++	if (nr_map < 2)
++		return -1;
++#else
++	BUG_ON(nr_map < 1);
++#endif
++
++	do {
++		unsigned long long start = biosmap->addr;
++		unsigned long long size = biosmap->size;
++		unsigned long long end = start + size;
++		unsigned long type = biosmap->type;
++
++		/* Overflow in 64 bits? Ignore the memory map. */
++		if (start > end)
++			return -1;
++
++#ifndef CONFIG_XEN
++		/*
++		 * Some BIOSes claim RAM in the 640k - 1M region.
++		 * Not right. Fix it up.
++		 */
++		if (type == E820_RAM) {
++			if (start < 0x100000ULL && end > 0xA0000ULL) {
++				if (start < 0xA0000ULL)
++					add_memory_region(start, 0xA0000ULL-start, type);
++				if (end <= 0x100000ULL)
++					continue;
++				start = 0x100000ULL;
++				size = end - start;
++			}
++		}
++#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;
++}
++
++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
++struct edd edd;
++#ifdef CONFIG_EDD_MODULE
++EXPORT_SYMBOL(edd);
++#endif
++#ifndef CONFIG_XEN
++/**
++ * copy_edd() - Copy the BIOS EDD information
++ *              from boot_params into a safe place.
++ *
++ */
++static inline void copy_edd(void)
++{
++     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
++     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
++     edd.mbr_signature_nr = EDD_MBR_SIG_NR;
++     edd.edd_info_nr = EDD_NR;
++}
++#endif
++#else
++static inline void copy_edd(void)
++{
++}
++#endif
++
++static void __init parse_cmdline_early (char ** cmdline_p)
++{
++	char c = ' ', *to = command_line, *from = saved_command_line;
++	int len = 0, max_cmdline;
++	int userdef = 0;
++
++	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);
++	/* Save unparsed command line copy for /proc/cmdline */
++	saved_command_line[max_cmdline-1] = '\0';
++
++	for (;;) {
++		if (c != ' ')
++			goto next_char;
++		/*
++		 * "mem=nopentium" disables the 4MB page tables.
++		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
++		 * to <mem>, overriding the bios size.
++		 * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
++		 * <start> to <start>+<mem>, overriding the bios size.
++		 *
++		 * HPA tells me bootloaders need to parse mem=, so no new
++		 * option should be mem=  [also see Documentation/i386/boot.txt]
++		 */
++		if (!memcmp(from, "mem=", 4)) {
++			if (to != command_line)
++				to--;
++			if (!memcmp(from+4, "nopentium", 9)) {
++				from += 9+4;
++				clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
++				disable_pse = 1;
++			} else {
++				/* If the user specifies memory size, we
++				 * limit the BIOS-provided memory map to
++				 * that size. exactmap can be used to specify
++				 * the exact map. mem=number can be used to
++				 * trim the existing memory map.
++				 */
++				unsigned long long mem_size;
++ 
++				mem_size = memparse(from+4, &from);
++				limit_regions(mem_size);
++				userdef=1;
++			}
++		}
++
++		else if (!memcmp(from, "memmap=", 7)) {
++			if (to != command_line)
++				to--;
++			if (!memcmp(from+7, "exactmap", 8)) {
++#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.
++				 */
++				find_max_pfn();
++				saved_max_pfn = max_pfn;
++#endif
++				from += 8+7;
++				e820.nr_map = 0;
++				userdef = 1;
++			} else {
++				/* If the user specifies memory size, we
++				 * limit the BIOS-provided memory map to
++				 * that size. exactmap can be used to specify
++				 * the exact map. mem=number can be used to
++				 * trim the existing memory map.
++				 */
++				unsigned long long start_at, mem_size;
++ 
++				mem_size = memparse(from+7, &from);
++				if (*from == '@') {
++					start_at = memparse(from+1, &from);
++					add_memory_region(start_at, mem_size, E820_RAM);
++				} else if (*from == '#') {
++					start_at = memparse(from+1, &from);
++					add_memory_region(start_at, mem_size, E820_ACPI);
++				} else if (*from == '$') {
++					start_at = memparse(from+1, &from);
++					add_memory_region(start_at, mem_size, E820_RESERVED);
++				} else {
++					limit_regions(mem_size);
++					userdef=1;
++				}
++			}
++		}
++
++		else if (!memcmp(from, "noexec=", 7))
++			noexec_setup(from + 7);
++
++
++#ifdef  CONFIG_X86_MPPARSE
++		/*
++		 * If the BIOS enumerates physical processors before logical,
++		 * maxcpus=N at enumeration-time can be used to disable HT.
++		 */
++		else if (!memcmp(from, "maxcpus=", 8)) {
++			extern unsigned int maxcpus;
++
++			maxcpus = simple_strtoul(from + 8, NULL, 0);
++		}
++#endif
++
++#ifdef CONFIG_ACPI
++		/* "acpi=off" disables both ACPI table parsing and interpreter */
++		else if (!memcmp(from, "acpi=off", 8)) {
++			disable_acpi();
++		}
++
++		/* acpi=force to over-ride black-list */
++		else if (!memcmp(from, "acpi=force", 10)) {
++			acpi_force = 1;
++			acpi_ht = 1;
++			acpi_disabled = 0;
++		}
++
++		/* acpi=strict disables out-of-spec workarounds */
++		else if (!memcmp(from, "acpi=strict", 11)) {
++			acpi_strict = 1;
++		}
++
++		/* Limit ACPI just to boot-time to enable HT */
++		else if (!memcmp(from, "acpi=ht", 7)) {
++			if (!acpi_force)
++				disable_acpi();
++			acpi_ht = 1;
++		}
++		
++		/* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
++		else if (!memcmp(from, "pci=noacpi", 10)) {
++			acpi_disable_pci();
++		}
++		/* "acpi=noirq" disables ACPI interrupt routing */
++		else if (!memcmp(from, "acpi=noirq", 10)) {
++			acpi_noirq_set();
++		}
++
++		else if (!memcmp(from, "acpi_sci=edge", 13))
++			acpi_sci_flags.trigger =  1;
++
++		else if (!memcmp(from, "acpi_sci=level", 14))
++			acpi_sci_flags.trigger = 3;
++
++		else if (!memcmp(from, "acpi_sci=high", 13))
++			acpi_sci_flags.polarity = 1;
++
++		else if (!memcmp(from, "acpi_sci=low", 12))
++			acpi_sci_flags.polarity = 3;
++
++#ifdef CONFIG_X86_IO_APIC
++		else if (!memcmp(from, "acpi_skip_timer_override", 24))
++			acpi_skip_timer_override = 1;
++
++		if (!memcmp(from, "disable_timer_pin_1", 19))
++			disable_timer_pin_1 = 1;
++		if (!memcmp(from, "enable_timer_pin_1", 18))
++			disable_timer_pin_1 = -1;
++
++		/* disable IO-APIC */
++		else if (!memcmp(from, "noapic", 6))
++			disable_ioapic_setup();
++#endif /* CONFIG_X86_IO_APIC */
++#endif /* CONFIG_ACPI */
++
++#ifdef CONFIG_X86_LOCAL_APIC
++		/* enable local APIC */
++		else if (!memcmp(from, "lapic", 5))
++			lapic_enable();
++
++		/* disable local APIC */
++		else if (!memcmp(from, "nolapic", 6))
++			lapic_disable();
++#endif /* CONFIG_X86_LOCAL_APIC */
++
++#ifdef CONFIG_KEXEC
++		/* crashkernel=size@addr specifies the location to reserve for
++		 * a crash kernel.  By reserving this memory we guarantee
++		 * that linux never set's it up as a DMA target.
++		 * Useful for holding code to do something appropriate
++		 * after a kernel panic.
++		 */
++		else if (!memcmp(from, "crashkernel=", 12)) {
++#ifndef CONFIG_XEN
++			unsigned long size, base;
++			size = memparse(from+12, &from);
++			if (*from == '@') {
++				base = memparse(from+1, &from);
++				/* FIXME: Do I want a sanity check
++				 * to validate the memory range?
++				 */
++				crashk_res.start = base;
++				crashk_res.end   = base + size - 1;
++			}
++#else
++			printk("Ignoring crashkernel command line, "
++			       "parameter will be supplied by xen\n");
++#endif
++		}
++#endif
++#ifdef CONFIG_PROC_VMCORE
++		/* elfcorehdr= specifies the location of elf core header
++		 * stored by the crashed kernel.
++		 */
++		else if (!memcmp(from, "elfcorehdr=", 11))
++			elfcorehdr_addr = memparse(from+11, &from);
++#endif
++
++		/*
++		 * highmem=size forces highmem to be exactly 'size' bytes.
++		 * This works even on boxes that have no highmem otherwise.
++		 * This also works to reduce highmem size on bigger boxes.
++		 */
++		else if (!memcmp(from, "highmem=", 8))
++			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
++	
++		/*
++		 * vmalloc=size forces the vmalloc area to be exactly 'size'
++		 * bytes. This can be used to increase (or decrease) the
++		 * vmalloc area - the default is 128m.
++		 */
++		else if (!memcmp(from, "vmalloc=", 8))
++			__VMALLOC_RESERVE = memparse(from+8, &from);
++
++	next_char:
++		c = *(from++);
++		if (!c)
++			break;
++		if (COMMAND_LINE_SIZE <= ++len)
++			break;
++		*(to++) = c;
++	}
++	*to = '\0';
++	*cmdline_p = command_line;
++	if (userdef) {
++		printk(KERN_INFO "user-defined physical RAM map:\n");
++		print_memory_map("user");
++	}
++}
++
++/*
++ * Callback for efi_memory_walk.
++ */
++static int __init
++efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
++{
++	unsigned long *max_pfn = arg, pfn;
++
++	if (start < end) {
++		pfn = PFN_UP(end -1);
++		if (pfn > *max_pfn)
++			*max_pfn = pfn;
++	}
++	return 0;
++}
++
++static int __init
++efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
++{
++	memory_present(0, start, end);
++	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;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		const struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		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.
++  *
++  * Note: this function only works correct if the e820 table is sorted and
++  * not-overlapping, which is the case
++  */
++int __init
++e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
++{
++	u64 start = s;
++	u64 end = e;
++	int i;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++		if (type && ei->type != type)
++			continue;
++		/* is the region (part) in overlap with the current region ?*/
++		if (ei->addr >= end || ei->addr + ei->size <= start)
++			continue;
++		/* if the region is at the beginning of <start,end> we move
++		 * start to the end of the region since it's ok until there
++		 */
++		if (ei->addr <= start)
++			start = ei->addr + ei->size;
++		/* if start is now at or beyond end, we're done, full
++		 * coverage */
++		if (start >= end)
++			return 1; /* we're done */
++	}
++	return 0;
++}
++
++/*
++ * Find the highest page frame number we have available
++ */
++void __init find_max_pfn(void)
++{
++	int i;
++
++	max_pfn = 0;
++	if (efi_enabled) {
++		efi_memmap_walk(efi_find_max_pfn, &max_pfn);
++		efi_memmap_walk(efi_memory_present_wrapper, NULL);
++		return;
++	}
++
++	for (i = 0; i < e820.nr_map; i++) {
++		unsigned long start, end;
++		/* RAM? */
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		start = PFN_UP(e820.map[i].addr);
++		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
++		if (start >= end)
++			continue;
++		if (end > max_pfn)
++			max_pfn = end;
++		memory_present(0, start, end);
++	}
++}
++
++/*
++ * Determine low and high memory ranges:
++ */
++unsigned long __init find_max_low_pfn(void)
++{
++	unsigned long max_low_pfn;
++
++	max_low_pfn = max_pfn;
++	if (max_low_pfn > MAXMEM_PFN) {
++		if (highmem_pages == -1)
++			highmem_pages = max_pfn - MAXMEM_PFN;
++		if (highmem_pages + MAXMEM_PFN < max_pfn)
++			max_pfn = MAXMEM_PFN + highmem_pages;
++		if (highmem_pages + MAXMEM_PFN > max_pfn) {
++			printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
++			highmem_pages = 0;
++		}
++		max_low_pfn = MAXMEM_PFN;
++#ifndef CONFIG_HIGHMEM
++		/* Maximum memory usable is what is directly addressable */
++		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
++					MAXMEM>>20);
++		if (max_pfn > MAX_NONPAE_PFN)
++			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
++		else
++			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
++		max_pfn = MAXMEM_PFN;
++#else /* !CONFIG_HIGHMEM */
++#ifndef CONFIG_X86_PAE
++		if (max_pfn > MAX_NONPAE_PFN) {
++			max_pfn = MAX_NONPAE_PFN;
++			printk(KERN_WARNING "Warning only 4GB will be used.\n");
++			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
++		}
++#endif /* !CONFIG_X86_PAE */
++#endif /* !CONFIG_HIGHMEM */
++	} else {
++		if (highmem_pages == -1)
++			highmem_pages = 0;
++#ifdef CONFIG_HIGHMEM
++		if (highmem_pages >= max_pfn) {
++			printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
++			highmem_pages = 0;
++		}
++		if (highmem_pages) {
++			if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
++				printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
++				highmem_pages = 0;
++			}
++			max_low_pfn -= highmem_pages;
++		}
++#else
++		if (highmem_pages)
++			printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
++#endif
++	}
++	return max_low_pfn;
++}
++
++/*
++ * Free all available memory for boot time allocation.  Used
++ * as a callback function by efi_memory_walk()
++ */
++
++static int __init
++free_available_memory(unsigned long start, unsigned long end, void *arg)
++{
++	/* check max_low_pfn */
++	if (start >= (max_low_pfn << PAGE_SHIFT))
++		return 0;
++	if (end >= (max_low_pfn << PAGE_SHIFT))
++		end = max_low_pfn << PAGE_SHIFT;
++	if (start < end)
++		free_bootmem(start, end - start);
++
++	return 0;
++}
++/*
++ * Register fully available low RAM pages with the bootmem allocator.
++ */
++static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
++{
++	int i;
++
++	if (efi_enabled) {
++		efi_memmap_walk(free_available_memory, NULL);
++		return;
++	}
++	for (i = 0; i < e820.nr_map; i++) {
++		unsigned long curr_pfn, last_pfn, size;
++		/*
++		 * Reserve usable low memory
++		 */
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		/*
++		 * We are rounding up the start address of usable memory:
++		 */
++		curr_pfn = PFN_UP(e820.map[i].addr);
++		if (curr_pfn >= max_low_pfn)
++			continue;
++		/*
++		 * ... and at the end of the usable range downwards:
++		 */
++		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
++
++#ifdef CONFIG_XEN
++		/*
++                 * Truncate to the number of actual pages currently
++                 * present.
++                 */
++		if (last_pfn > xen_start_info->nr_pages)
++			last_pfn = xen_start_info->nr_pages;
++#endif
++
++		if (last_pfn > max_low_pfn)
++			last_pfn = max_low_pfn;
++
++		/*
++		 * .. finally, did all the rounding and playing
++		 * around just make the area go away?
++		 */
++		if (last_pfn <= curr_pfn)
++			continue;
++
++		size = last_pfn - curr_pfn;
++		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
++	}
++}
++
++#ifndef CONFIG_XEN
++/*
++ * workaround for Dell systems that neglect to reserve EBDA
++ */
++static void __init reserve_ebda_region(void)
++{
++	unsigned int addr;
++	addr = get_bios_ebda();
++	if (addr)
++		reserve_bootmem(addr, PAGE_SIZE);	
++}
++#endif
++
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++void __init setup_bootmem_allocator(void);
++static unsigned long __init setup_memory(void)
++{
++	/*
++	 * partially used pages are not usable - thus
++	 * we are rounding upwards:
++	 */
++ 	min_low_pfn = PFN_UP(__pa(xen_start_info->pt_base)) +
++		xen_start_info->nr_pt_frames;
++
++	find_max_pfn();
++
++	max_low_pfn = find_max_low_pfn();
++
++#ifdef CONFIG_HIGHMEM
++	highstart_pfn = highend_pfn = max_pfn;
++	if (max_pfn > max_low_pfn) {
++		highstart_pfn = max_low_pfn;
++	}
++	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
++		pages_to_mb(highend_pfn - highstart_pfn));
++#endif
++	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
++			pages_to_mb(max_low_pfn));
++
++	setup_bootmem_allocator();
++
++	return max_low_pfn;
++}
++
++void __init zone_sizes_init(void)
++{
++	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
++	unsigned int max_dma, low;
++
++	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
++	low = max_low_pfn;
++
++	if (low < max_dma)
++		zones_size[ZONE_DMA] = low;
++	else {
++		zones_size[ZONE_DMA] = max_dma;
++		zones_size[ZONE_NORMAL] = low - max_dma;
++#ifdef CONFIG_HIGHMEM
++		zones_size[ZONE_HIGHMEM] = highend_pfn - low;
++#endif
++	}
++	free_area_init(zones_size);
++}
++#else
++extern unsigned long __init setup_memory(void);
++extern void zone_sizes_init(void);
++#endif /* !CONFIG_NEED_MULTIPLE_NODES */
++
++void __init setup_bootmem_allocator(void)
++{
++	unsigned long bootmap_size;
++	/*
++	 * Initialize the boot-time allocator (with low memory only):
++	 */
++	bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);
++
++	register_bootmem_low_pages(max_low_pfn);
++
++	/*
++	 * Reserve the bootmem bitmap itself as well. We do this in two
++	 * steps (first step was init_bootmem()) because this catches
++	 * the (very unlikely) case of us accidentally initializing the
++	 * bootmem allocator with an invalid RAM area.
++	 */
++	reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
++			 bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
++
++#ifndef CONFIG_XEN
++	/*
++	 * reserve physical page 0 - it's a special BIOS page on many boxes,
++	 * enabling clean reboots, SMP operation, laptop functions.
++	 */
++	reserve_bootmem(0, PAGE_SIZE);
++
++	/* reserve EBDA region, it's a 4K region */
++	reserve_ebda_region();
++
++    /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
++       PCI prefetch into it (errata #56). Usually the page is reserved anyways,
++       unless you have no PS/2 mouse plugged in. */
++	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
++	    boot_cpu_data.x86 == 6)
++	     reserve_bootmem(0xa0000 - 4096, 4096);
++
++#ifdef CONFIG_SMP
++	/*
++	 * But first pinch a few for the stack/trampoline stuff
++	 * FIXME: Don't need the extra page at 4K, but need to fix
++	 * trampoline before removing it. (see the GDT stuff)
++	 */
++	reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
++#endif
++#ifdef CONFIG_ACPI_SLEEP
++	/*
++	 * Reserve low memory region for sleep support.
++	 */
++	acpi_reserve_bootmem();
++#endif
++#endif /* !CONFIG_XEN */
++
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (xen_start_info->mod_start) {
++		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
++			/*reserve_bootmem(INITRD_START, INITRD_SIZE);*/
++			initrd_start = INITRD_START + PAGE_OFFSET;
++			initrd_end = initrd_start+INITRD_SIZE;
++			initrd_below_start_ok = 1;
++		}
++		else {
++			printk(KERN_ERR "initrd extends beyond end of memory "
++			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++			    INITRD_START + INITRD_SIZE,
++			    max_low_pfn << PAGE_SHIFT);
++			initrd_start = 0;
++		}
++	}
++#endif
++#ifdef CONFIG_KEXEC
++#ifdef CONFIG_XEN
++	xen_machine_kexec_setup_resources();
++#else
++	if (crashk_res.start != crashk_res.end)
++		reserve_bootmem(crashk_res.start,
++			crashk_res.end - crashk_res.start + 1);
++#endif
++#endif
++}
++
++/*
++ * The node 0 pgdat is initialized before all of these because
++ * it's needed for bootmem.  node>0 pgdats have their virtual
++ * space allocated before the pagetables are in place to access
++ * them, so they can't be cleared then.
++ *
++ * This should all compile down to nothing when NUMA is off.
++ */
++void __init remapped_pgdat_init(void)
++{
++	int nid;
++
++	for_each_online_node(nid) {
++		if (nid != 0)
++			memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
++	}
++}
++
++/*
++ * Request address space for all standard RAM and ROM resources
++ * and also for regions reported as reserved by the e820.
++ */
++static void __init
++legacy_init_iomem_resources(struct e820entry *e820, int nr_map,
++			    struct resource *code_resource,
++			    struct resource *data_resource)
++{
++	int i;
++
++	probe_roms();
++
++	for (i = 0; i < nr_map; i++) {
++		struct resource *res;
++#ifndef CONFIG_RESOURCES_64BIT
++		if (e820[i].addr + e820[i].size > 0x100000000ULL)
++			continue;
++#endif
++		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
++		switch (e820[i].type) {
++		case E820_RAM:	res->name = "System RAM"; break;
++		case E820_ACPI:	res->name = "ACPI Tables"; break;
++		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
++		default:	res->name = "reserved";
++		}
++		res->start = e820[i].addr;
++		res->end = res->start + e820[i].size - 1;
++		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++		if (request_resource(&iomem_resource, res)) {
++			kfree(res);
++			continue;
++		}
++		if (e820[i].type == E820_RAM) {
++			/*
++			 *  We don't know which RAM region contains kernel data,
++			 *  so we try it repeatedly and let the resource manager
++			 *  test it.
++			 */
++#ifndef CONFIG_XEN
++			request_resource(res, code_resource);
++			request_resource(res, data_resource);
++#endif
++#ifdef CONFIG_KEXEC
++			if (crashk_res.start != crashk_res.end)
++			     request_resource(res, &crashk_res);
++#ifdef CONFIG_XEN
++			xen_machine_kexec_register_resources(res);
++#endif
++#endif
++		}
++	}
++}
++
++/*
++ * Locate a unused range of the physical address space below 4G which
++ * can be used for PCI mappings.
++ */
++static void __init
++e820_setup_gap(struct e820entry *e820, int nr_map)
++{
++	unsigned long gapstart, gapsize, round;
++	unsigned long long last;
++	int i;
++
++	/*
++	 * Search for the bigest gap in the low 32 bits of the e820
++	 * memory space.
++	 */
++	last = 0x100000000ull;
++	gapstart = 0x10000000;
++	gapsize = 0x400000;
++	i = nr_map;
++	while (--i >= 0) {
++		unsigned long long start = e820[i].addr;
++		unsigned long long end = start + e820[i].size;
++
++		/*
++		 * Since "last" is at most 4GB, we know we'll
++		 * fit in 32 bits if this condition is true
++		 */
++		if (last > end) {
++			unsigned long gap = last - end;
++
++			if (gap > gapsize) {
++				gapsize = gap;
++				gapstart = end;
++			}
++		}
++		if (start < last)
++			last = start;
++	}
++
++	/*
++	 * See how much we want to round up: start off with
++	 * rounding to the next 1MB area.
++	 */
++	round = 0x100000;
++	while ((gapsize >> 4) > round)
++		round += round;
++	/* Fun with two's complement */
++	pci_mem_start = (gapstart + round) & -round;
++
++	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
++		pci_mem_start, gapstart, gapsize);
++}
++
++/*
++ * Request address space for all standard resources
++ *
++ * This is called just before pcibios_init(), which is also a
++ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
++ */
++static int __init request_standard_resources(void)
++{
++	int	      i;
++
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return 0;
++
++	printk("Setting up standard PCI resources\n");
++#ifdef CONFIG_XEN
++	legacy_init_iomem_resources(machine_e820.map, machine_e820.nr_map,
++				    &code_resource, &data_resource);
++#else
++	if (efi_enabled)
++		efi_initialize_iomem_resources(&code_resource, &data_resource);
++	else
++		legacy_init_iomem_resources(e820.map, e820.nr_map,
++					    &code_resource, &data_resource);
++#endif
++
++	/* EFI systems may still have VGA */
++	request_resource(&iomem_resource, &video_ram_resource);
++
++	/* request I/O space for devices used on all i[345]86 PCs */
++	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
++		request_resource(&ioport_resource, &standard_io_resources[i]);
++	return 0;
++}
++
++subsys_initcall(request_standard_resources);
++
++static void __init register_memory(void)
++{
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain())
++		e820_setup_gap(machine_e820.map, machine_e820.nr_map);
++	else
++#endif
++		e820_setup_gap(e820.map, e820.nr_map);
++}
++
++#ifdef CONFIG_MCA
++static void set_mca_bus(int x)
++{
++	MCA_bus = x;
++}
++#else
++static void set_mca_bus(int x) { }
++#endif
++
++/*
++ * Determine if we were loaded by an EFI loader.  If so, then we have also been
++ * passed the efi memmap, systab, etc., so we should use these data structures
++ * for initialization.  Note, the efi init code path is determined by the
++ * global efi_enabled. This allows the same kernel image to be used on existing
++ * systems (with a traditional BIOS) as well as on EFI systems.
++ */
++void __init setup_arch(char **cmdline_p)
++{
++	int i, j, k, fpp;
++	struct physdev_set_iopl set_iopl;
++	unsigned long max_low_pfn;
++	unsigned long p2m_pages;
++
++	/* Force a quick death if the kernel panics (not domain 0). */
++	extern int panic_timeout;
++	if (!panic_timeout && !is_initial_xendomain())
++		panic_timeout = 1;
++
++	/* Register a call for panic conditions. */
++	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_4gb_segments));
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     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();
++#endif
++
++	/*
++	 * FIXME: This isn't an official loader_type right
++	 * now but does currently work with elilo.
++	 * If we were configured as an EFI kernel, check to make
++	 * sure that we were loaded correctly from elilo and that
++	 * the system table is valid.  If not, then initialize normally.
++	 */
++#ifdef CONFIG_EFI
++	if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
++		efi_enabled = 1;
++#endif
++
++	/* This must be initialized to UNNAMED_MAJOR for ipconfig to work
++	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
++	*/
++	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
++ 	drive_info = DRIVE_INFO;
++ 	screen_info = SCREEN_INFO;
++	copy_edid();
++	apm_info.bios = APM_BIOS_INFO;
++	ist_info = IST_INFO;
++	saved_videomode = VIDEO_MODE;
++	if( SYS_DESC_TABLE.length != 0 ) {
++		set_mca_bus(SYS_DESC_TABLE.table[3] & 0x2);
++		machine_id = SYS_DESC_TABLE.table[0];
++		machine_submodel_id = SYS_DESC_TABLE.table[1];
++		BIOS_revision = SYS_DESC_TABLE.table[2];
++	}
++	bootloader_type = LOADER_TYPE;
++
++	if (is_initial_xendomain()) {
++		const struct dom0_vga_console_info *info =
++			(void *)((char *)xen_start_info +
++			         xen_start_info->console.dom0.info_off);
++
++		dom0_init_screen_info(info,
++		                      xen_start_info->console.dom0.info_size);
++		xen_start_info->console.domU.mfn = 0;
++		xen_start_info->console.domU.evtchn = 0;
++	} else
++		screen_info.orig_video_isVGA = 0;
++
++#ifdef CONFIG_BLK_DEV_RAM
++	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
++	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
++	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
++#endif
++
++	ARCH_SETUP
++	if (efi_enabled)
++		efi_init();
++	else {
++		printk(KERN_INFO "BIOS-provided physical RAM map:\n");
++		print_memory_map(machine_specific_memory_setup());
++	}
++
++	copy_edd();
++
++	if (!MOUNT_ROOT_RDONLY)
++		root_mountflags &= ~MS_RDONLY;
++	init_mm.start_code = (unsigned long) _text;
++	init_mm.end_code = (unsigned long) _etext;
++	init_mm.end_data = (unsigned long) _edata;
++	init_mm.brk = (PFN_UP(__pa(xen_start_info->pt_base)) +
++		       xen_start_info->nr_pt_frames) << PAGE_SHIFT;
++
++	code_resource.start = virt_to_phys(_text);
++	code_resource.end = virt_to_phys(_etext)-1;
++	data_resource.start = virt_to_phys(_etext);
++	data_resource.end = virt_to_phys(_edata)-1;
++
++	parse_cmdline_early(cmdline_p);
++
++#ifdef CONFIG_EARLY_PRINTK
++	{
++		char *s = strstr(*cmdline_p, "earlyprintk=");
++		if (s) {
++			setup_early_printk(strchr(s, '=') + 1);
++			printk("early console enabled\n");
++		}
++	}
++#endif
++
++	max_low_pfn = setup_memory();
++
++	/*
++	 * NOTE: before this point _nobody_ is allowed to allocate
++	 * any memory using the bootmem allocator.  Although the
++	 * alloctor is now initialised only the first 8Mb of the kernel
++	 * virtual address space has been mapped.  All allocations before
++	 * paging_init() has completed must use the alloc_bootmem_low_pages()
++	 * variant (which allocates DMA'able memory) and care must be taken
++	 * not to exceed the 8Mb limit.
++	 */
++
++#ifdef CONFIG_SMP
++	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
++#endif
++	paging_init();
++	remapped_pgdat_init();
++	sparse_init();
++	zone_sizes_init();
++
++#ifdef CONFIG_X86_FIND_SMP_CONFIG
++	/*
++	 * Find and reserve possible boot-time SMP configuration:
++	 */
++	find_smp_config();
++#endif
++
++	p2m_pages = max_pfn;
++	if (xen_start_info->nr_pages > max_pfn) {
++		/*
++		 * the max_pfn was shrunk (probably by mem= or highmem=
++		 * kernel parameter); shrink reservation with the HV
++		 */
++		struct xen_memory_reservation reservation = {
++			.address_bits = 0,
++			.extent_order = 0,
++			.domid = DOMID_SELF
++		};
++		unsigned int difference;
++		int ret;
++
++		difference = xen_start_info->nr_pages - max_pfn;
++
++		set_xen_guest_handle(reservation.extent_start,
++				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
++		reservation.nr_extents = difference;
++		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					   &reservation);
++		BUG_ON (ret != difference);
++	}
++	else if (max_pfn > xen_start_info->nr_pages)
++		p2m_pages = xen_start_info->nr_pages;
++
++	/* Make sure we have a correctly sized P->M table. */
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		phys_to_machine_mapping = alloc_bootmem_low_pages(
++		     max_pfn * sizeof(unsigned long));
++		memset(phys_to_machine_mapping, ~0,
++		       max_pfn * sizeof(unsigned long));
++		memcpy(phys_to_machine_mapping,
++		       (unsigned long *)xen_start_info->mfn_list,
++		       p2m_pages * sizeof(unsigned long));
++		free_bootmem(
++		     __pa(xen_start_info->mfn_list),
++		     PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
++				     sizeof(unsigned long))));
++
++		/*
++		 * Initialise the list of the frames that specify the list of
++		 * frames that make up the p2m table. Used by save/restore
++		 */
++		pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
++
++		fpp = PAGE_SIZE/sizeof(unsigned long);
++		for (i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++) {
++			if ((j % fpp) == 0) {
++				k++;
++				BUG_ON(k>=16);
++				pfn_to_mfn_frame_list[k] =
++					alloc_bootmem_low_pages(PAGE_SIZE);
++				pfn_to_mfn_frame_list_list[k] =
++					virt_to_mfn(pfn_to_mfn_frame_list[k]);
++				j=0;
++			}
++			pfn_to_mfn_frame_list[k][j] =
++				virt_to_mfn(&phys_to_machine_mapping[i]);
++		}
++		HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
++		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
++		     virt_to_mfn(pfn_to_mfn_frame_list_list);
++	}
++
++	/* Mark all ISA DMA channels in-use - using them wouldn't work. */
++	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
++		if (i != 4 && request_dma(i, "xen") != 0)
++			BUG();
++
++	/*
++	 * NOTE: at this point the bootmem allocator is fully available.
++	 */
++
++	if (is_initial_xendomain())
++		dmi_scan_machine();
++
++#ifdef CONFIG_X86_GENERICARCH
++	generic_apic_probe(*cmdline_p);
++#endif	
++	if (efi_enabled)
++		efi_map_memmap();
++
++	set_iopl.iopl = 1;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++
++#ifdef CONFIG_ACPI
++	if (!is_initial_xendomain()) {
++		printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
++		acpi_disabled = 1;
++		acpi_ht = 0;
++	}
++
++	/*
++	 * Parse the ACPI tables for possible boot-time SMP configuration.
++	 */
++	acpi_boot_table_init();
++#endif
++
++#ifdef CONFIG_X86_IO_APIC
++	check_acpi_pci();	/* Checks more than just ACPI actually */
++#endif
++
++#ifdef CONFIG_ACPI
++	acpi_boot_init();
++
++#if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
++	if (def_to_bigsmp)
++		printk(KERN_WARNING "More than 8 CPUs detected and "
++			"CONFIG_X86_PC cannot handle it.\nUse "
++			"CONFIG_X86_GENERICARCH or CONFIG_X86_BIGSMP.\n");
++#endif
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++	if (smp_found_config)
++		get_smp_config();
++#endif
++
++	register_memory();
++
++	if (is_initial_xendomain()) {
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++		if (!efi_enabled ||
++		    (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
++			conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++		conswitchp = &dummy_con;
++#endif
++#endif
++	} else {
++#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
++		conswitchp = &dummy_con;
++#endif
++	}
++	tsc_init();
++}
++
++static int
++xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++	HYPERVISOR_shutdown(SHUTDOWN_crash);
++	/* we're never actually going to get here... */
++	return NOTIFY_DONE;
++}
++
++static __init int add_pcspkr(void)
++{
++	struct platform_device *pd;
++	int ret;
++
++	if (!is_initial_xendomain())
++		return 0;
++
++	pd = platform_device_alloc("pcspkr", -1);
++	if (!pd)
++		return -ENOMEM;
++
++	ret = platform_device_add(pd);
++	if (ret)
++		platform_device_put(pd);
++
++	return ret;
++}
++device_initcall(add_pcspkr);
++
++/*
++ * Local Variables:
++ * mode:c
++ * c-file-style:"k&r"
++ * c-basic-offset:8
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2007-12-10 08:47:31.000000000 +0100
+@@ -0,0 +1,605 @@
++/*
++ *	Intel SMP support routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
++ *
++ *	This code is released under the GNU General Public License version 2 or
++ *	later.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/cache.h>
++#include <linux/interrupt.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
++
++#include <asm/mtrr.h>
++#include <asm/tlbflush.h>
++#if 0
++#include <mach_apic.h>
++#endif
++#include <xen/evtchn.h>
++
++/*
++ *	Some notes on x86 processor bugs affecting SMP operation:
++ *
++ *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
++ *	The Linux implications for SMP are handled as follows:
++ *
++ *	Pentium III / [Xeon]
++ *		None of the E1AP-E3AP errata are visible to the user.
++ *
++ *	E1AP.	see PII A1AP
++ *	E2AP.	see PII A2AP
++ *	E3AP.	see PII A3AP
++ *
++ *	Pentium II / [Xeon]
++ *		None of the A1AP-A3AP errata are visible to the user.
++ *
++ *	A1AP.	see PPro 1AP
++ *	A2AP.	see PPro 2AP
++ *	A3AP.	see PPro 7AP
++ *
++ *	Pentium Pro
++ *		None of 1AP-9AP errata are visible to the normal user,
++ *	except occasional delivery of 'spurious interrupt' as trap #15.
++ *	This is very rare and a non-problem.
++ *
++ *	1AP.	Linux maps APIC as non-cacheable
++ *	2AP.	worked around in hardware
++ *	3AP.	fixed in C0 and above steppings microcode update.
++ *		Linux does not use excessive STARTUP_IPIs.
++ *	4AP.	worked around in hardware
++ *	5AP.	symmetric IO mode (normal Linux operation) not affected.
++ *		'noapic' mode has vector 0xf filled out properly.
++ *	6AP.	'noapic' mode might be affected - fixed in later steppings
++ *	7AP.	We do not assume writes to the LVT deassering IRQs
++ *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
++ *	9AP.	We do not use mixed mode
++ *
++ *	Pentium
++ *		There is a marginal case where REP MOVS on 100MHz SMP
++ *	machines with B stepping processors can fail. XXX should provide
++ *	an L1cache=Writethrough or L1cache=off option.
++ *
++ *		B stepping CPUs may hang. There are hardware work arounds
++ *	for this. We warn about it in case your board doesn't have the work
++ *	arounds. Basically thats so I can tell anyone with a B stepping
++ *	CPU and SMP problems "tough".
++ *
++ *	Specific items [From Pentium Processor Specification Update]
++ *
++ *	1AP.	Linux doesn't use remote read
++ *	2AP.	Linux doesn't trust APIC errors
++ *	3AP.	We work around this
++ *	4AP.	Linux never generated 3 interrupts of the same priority
++ *		to cause a lost local interrupt.
++ *	5AP.	Remote read is never used
++ *	6AP.	not affected - worked around in hardware
++ *	7AP.	not affected - worked around in hardware
++ *	8AP.	worked around in hardware - we get explicit CS errors if not
++ *	9AP.	only 'noapic' mode affected. Might generate spurious
++ *		interrupts, we log only the first one and count the
++ *		rest silently.
++ *	10AP.	not affected - worked around in hardware
++ *	11AP.	Linux reads the APIC between writes to avoid this, as per
++ *		the documentation. Make sure you preserve this as it affects
++ *		the C stepping chips too.
++ *	12AP.	not affected - worked around in hardware
++ *	13AP.	not affected - worked around in hardware
++ *	14AP.	we always deassert INIT during bootup
++ *	15AP.	not affected - worked around in hardware
++ *	16AP.	not affected - worked around in hardware
++ *	17AP.	not affected - worked around in hardware
++ *	18AP.	not affected - worked around in hardware
++ *	19AP.	not affected - worked around in BIOS
++ *
++ *	If this sounds worrying believe me these bugs are either ___RARE___,
++ *	or are signal timing bugs worked around in hardware and there's
++ *	about nothing of note with C stepping upwards.
++ */
++
++DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
++
++/*
++ * the following functions deal with sending IPIs between CPUs.
++ *
++ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
++ */
++
++static inline int __prepare_ICR (unsigned int shortcut, int vector)
++{
++	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
++
++	switch (vector) {
++	default:
++		icr |= APIC_DM_FIXED | vector;
++		break;
++	case NMI_VECTOR:
++		icr |= APIC_DM_NMI;
++		break;
++	}
++	return icr;
++}
++
++static inline int __prepare_ICR2 (unsigned int mask)
++{
++	return SET_APIC_DEST_FIELD(mask);
++}
++
++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 __send_IPI_shortcut(unsigned int shortcut, int vector)
++{
++	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;
++	default:
++		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
++		       vector);
++		break;
++	}
++}
++
++void fastcall send_IPI_self(int vector)
++{
++	__send_IPI_shortcut(APIC_DEST_SELF, vector);
++}
++
++/*
++ * This is only used on smaller machines.
++ */
++void send_IPI_mask_bitmask(cpumask_t mask, int vector)
++{
++	unsigned long flags;
++	unsigned int cpu;
++
++	local_irq_save(flags);
++	WARN_ON(cpus_addr(mask)[0] & ~cpus_addr(cpu_online_map)[0]);
++
++	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
++		if (cpu_isset(cpu, mask)) {
++			__send_IPI_one(cpu, vector);
++		}
++	}
++
++	local_irq_restore(flags);
++}
++
++void send_IPI_mask_sequence(cpumask_t mask, int vector)
++{
++
++	send_IPI_mask_bitmask(mask, vector);
++}
++
++#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
++
++#if 0 /* XEN */
++/*
++ *	Smarter SMP flushing macros. 
++ *		c/o Linus Torvalds.
++ *
++ *	These mean you can really definitely utterly forget about
++ *	writing to user space from interrupts. (Its not allowed anyway).
++ *
++ *	Optimizations Manfred Spraul <manfred@colorfullife.com>
++ */
++
++static cpumask_t flush_cpumask;
++static struct mm_struct * flush_mm;
++static unsigned long flush_va;
++static DEFINE_SPINLOCK(tlbstate_lock);
++#define FLUSH_ALL	0xffffffff
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context, 
++ * instead update mm->cpu_vm_mask.
++ *
++ * We need to reload %cr3 since the page tables may be going
++ * away from under us..
++ */
++static inline void leave_mm (unsigned long cpu)
++{
++	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
++		BUG();
++	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
++	load_cr3(swapper_pg_dir);
++}
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * 	Stop ipi delivery for the old mm. This is not synchronized with
++ * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * 	for the wrong mm, and in the worst case we perform a superflous
++ * 	tlb flush.
++ * 1a2) set cpu_tlbstate to TLBSTATE_OK
++ * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ *	was in lazy tlb mode.
++ * 1a3) update cpu_tlbstate[].active_mm
++ * 	Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * 	Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
++ *	flush ipis.
++ * 1b1) set cpu_tlbstate to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * 	Atomically set the bit [other cpus will start sending flush ipis],
++ * 	and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ *   runs in kernel space, the cpu could load tlb entries for user space
++ *   pages.
++ *
++ * The good news is that cpu_tlbstate is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ */
++
++irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id,
++				     struct pt_regs *regs)
++{
++	unsigned long cpu;
++
++	cpu = get_cpu();
++
++	if (!cpu_isset(cpu, flush_cpumask))
++		goto out;
++		/* 
++		 * This was a BUG() but until someone can quote me the
++		 * line from the intel manual that guarantees an IPI to
++		 * multiple CPUs is retried _only_ on the erroring CPUs
++		 * its staying as a return
++		 *
++		 * BUG();
++		 */
++		 
++	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
++		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
++			if (flush_va == FLUSH_ALL)
++				local_flush_tlb();
++			else
++				__flush_tlb_one(flush_va);
++		} else
++			leave_mm(cpu);
++	}
++	smp_mb__before_clear_bit();
++	cpu_clear(cpu, flush_cpumask);
++	smp_mb__after_clear_bit();
++out:
++	put_cpu_no_resched();
++
++	return IRQ_HANDLED;
++}
++
++static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
++						unsigned long va)
++{
++	/*
++	 * A couple of (to be removed) sanity checks:
++	 *
++	 * - current CPU must not be in mask
++	 * - mask must exist :)
++	 */
++	BUG_ON(cpus_empty(cpumask));
++	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
++	BUG_ON(!mm);
++
++	/* If a CPU which we ran on has gone down, OK. */
++	cpus_and(cpumask, cpumask, cpu_online_map);
++	if (cpus_empty(cpumask))
++		return;
++
++	/*
++	 * i'm not happy about this global shared spinlock in the
++	 * MM hot path, but we'll see how contended it is.
++	 * Temporarily this turns IRQs off, so that lockups are
++	 * detected by the NMI watchdog.
++	 */
++	spin_lock(&tlbstate_lock);
++	
++	flush_mm = mm;
++	flush_va = va;
++#if NR_CPUS <= BITS_PER_LONG
++	atomic_set_mask(cpumask, &flush_cpumask);
++#else
++	{
++		int k;
++		unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
++		unsigned long *cpu_mask = (unsigned long *)&cpumask;
++		for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
++			atomic_set_mask(cpu_mask[k], &flush_mask[k]);
++	}
++#endif
++	/*
++	 * We have to send the IPI only to
++	 * CPUs affected.
++	 */
++	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
++
++	while (!cpus_empty(flush_cpumask))
++		/* nothing. lockup detection does not belong here */
++		mb();
++
++	flush_mm = NULL;
++	flush_va = 0;
++	spin_unlock(&tlbstate_lock);
++}
++	
++void flush_tlb_current_task(void)
++{
++	struct mm_struct *mm = current->mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	local_flush_tlb();
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++	preempt_enable();
++}
++
++void flush_tlb_mm (struct mm_struct * mm)
++{
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			local_flush_tlb();
++		else
++			leave_mm(smp_processor_id());
++	}
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++
++	preempt_enable();
++}
++
++void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
++{
++	struct mm_struct *mm = vma->vm_mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if(current->mm)
++			__flush_tlb_one(va);
++		else
++		 	leave_mm(smp_processor_id());
++	}
++
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, va);
++
++	preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_page);
++
++static void do_flush_tlb_all(void* info)
++{
++	unsigned long cpu = smp_processor_id();
++
++	__flush_tlb_all();
++	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
++		leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
++
++#endif /* XEN */
++
++/*
++ * this function sends a 'reschedule' IPI to another CPU.
++ * it goes straight through and wastes no time serializing
++ * anything. Worst case is that we lose a reschedule ...
++ */
++void smp_send_reschedule(int cpu)
++{
++	WARN_ON(cpu_is_offline(cpu));
++	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++}
++
++/*
++ * Structure and data for smp_call_function(). This is designed to minimise
++ * static memory requirements. It also looks cleaner.
++ */
++static DEFINE_SPINLOCK(call_lock);
++
++struct call_data_struct {
++	void (*func) (void *info);
++	void *info;
++	atomic_t started;
++	atomic_t finished;
++	int wait;
++};
++
++void lock_ipi_call_lock(void)
++{
++	spin_lock_irq(&call_lock);
++}
++
++void unlock_ipi_call_lock(void)
++{
++	spin_unlock_irq(&call_lock);
++}
++
++static struct call_data_struct *call_data;
++
++/**
++ * smp_call_function(): Run a function on all other CPUs.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: currently unused.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code. Does not return until
++ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
++			int wait)
++{
++	struct call_data_struct data;
++	int cpus;
++
++	/* Holding any lock stops cpus from going down. */
++	spin_lock(&call_lock);
++	cpus = num_online_cpus() - 1;
++	if (!cpus) {
++		spin_unlock(&call_lock);
++		return 0;
++	}
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	mb();
++	
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (wait)
++		while (atomic_read(&data.finished) != cpus)
++			cpu_relax();
++	spin_unlock(&call_lock);
++
++	return 0;
++}
++EXPORT_SYMBOL(smp_call_function);
++
++static void stop_this_cpu (void * dummy)
++{
++	/*
++	 * Remove this CPU:
++	 */
++	cpu_clear(smp_processor_id(), cpu_online_map);
++	local_irq_disable();
++	disable_all_local_evtchn();
++	if (cpu_data[smp_processor_id()].hlt_works_ok)
++		for(;;) halt();
++	for (;;);
++}
++
++/*
++ * this function calls the 'stop' function on all other CPUs in the system.
++ */
++
++void smp_send_stop(void)
++{
++	smp_call_function(stop_this_cpu, NULL, 1, 0);
++
++	local_irq_disable();
++	disable_all_local_evtchn();
++	local_irq_enable();
++}
++
++/*
++ * Reschedule call back. Nothing to do,
++ * all the work is done automatically when
++ * we return from the interrupt.
++ */
++irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id,
++				     struct pt_regs *regs)
++{
++
++	return IRQ_HANDLED;
++}
++
++#include <linux/kallsyms.h>
++irqreturn_t smp_call_function_interrupt(int irq, void *dev_id,
++					struct pt_regs *regs)
++{
++	void (*func) (void *info) = call_data->func;
++	void *info = call_data->info;
++	int wait = call_data->wait;
++
++	/*
++	 * Notify initiating CPU that I've grabbed the data and am
++	 * about to execute the function
++	 */
++	mb();
++	atomic_inc(&call_data->started);
++	/*
++	 * At this point the info structure may be out of scope unless wait==1
++	 */
++	irq_enter();
++	(*func)(info);
++	irq_exit();
++
++	if (wait) {
++		mb();
++		atomic_inc(&call_data->finished);
++	}
++
++	return IRQ_HANDLED;
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-09-02 11:42:46.000000000 +0200
+@@ -0,0 +1,1211 @@
++/*
++ *  linux/arch/i386/kernel/time.c
++ *
++ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
++ *
++ * This file contains the PC-specific time handling details:
++ * reading the RTC at bootup, etc..
++ * 1994-07-02    Alan Modra
++ *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
++ * 1995-03-26    Markus Kuhn
++ *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
++ *      precision CMOS clock update
++ * 1996-05-03    Ingo Molnar
++ *      fixed time warps in do_[slow|fast]_gettimeoffset()
++ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
++ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
++ * 1998-09-05    (Various)
++ *	More robust do_fast_gettimeoffset() algorithm implemented
++ *	(works with APM, Cyrix 6x86MX and Centaur C6),
++ *	monotonic gettimeofday() with fast_get_timeoffset(),
++ *	drift-proof precision TSC calibration on boot
++ *	(C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D.
++ *	Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>;
++ *	ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>).
++ * 1998-12-16    Andrea Arcangeli
++ *	Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy
++ *	because was not accounting lost_ticks.
++ * 1998-12-24 Copyright (C) 1998  Andrea Arcangeli
++ *	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
++ *	serialize accesses to xtime/lost_ticks).
++ */
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/param.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/sysdev.h>
++#include <linux/bcd.h>
++#include <linux/efi.h>
++#include <linux/mca.h>
++#include <linux/sysctl.h>
++#include <linux/percpu.h>
++#include <linux/kernel_stat.h>
++#include <linux/posix-timers.h>
++#include <linux/cpufreq.h>
++
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/irq.h>
++#include <asm/msr.h>
++#include <asm/delay.h>
++#include <asm/mpspec.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++#include <asm/timer.h>
++#include <asm/sections.h>
++
++#include "mach_time.h"
++
++#include <linux/timex.h>
++
++#include <asm/hpet.h>
++
++#include <asm/arch_hooks.h>
++
++#include <xen/evtchn.h>
++#include <xen/interface/vcpu.h>
++
++#if defined (__i386__)
++#include <asm/i8259.h>
++#endif
++
++int pit_latch_buggy;              /* extern */
++
++#if defined(__x86_64__)
++unsigned long vxtime_hz = PIT_TICK_RATE;
++struct vxtime_data __vxtime __section_vxtime;   /* for vsyscalls */
++volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
++unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
++struct timespec __xtime __section_xtime;
++struct timezone __sys_tz __section_sys_tz;
++#endif
++
++unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
++EXPORT_SYMBOL(cpu_khz);
++
++extern unsigned long wall_jiffies;
++
++DEFINE_SPINLOCK(rtc_lock);
++EXPORT_SYMBOL(rtc_lock);
++
++extern struct init_timer_opts timer_tsc_init;
++extern struct timer_opts timer_tsc;
++#define timer_none timer_tsc
++
++/* These are peridically updated in shared_info, and then copied here. */
++struct shadow_time_info {
++	u64 tsc_timestamp;     /* TSC at last update of time vals.  */
++	u64 system_timestamp;  /* Time, in nanosecs, since boot.    */
++	u32 tsc_to_nsec_mul;
++	u32 tsc_to_usec_mul;
++	int tsc_shift;
++	u32 version;
++};
++static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
++static struct timespec shadow_tv;
++static u32 shadow_tv_version;
++
++static struct timeval monotonic_tv;
++static spinlock_t monotonic_lock = SPIN_LOCK_UNLOCKED;
++
++/* Keep track of last time we did processing/updating of jiffies and xtime. */
++static u64 processed_system_time;   /* System time (ns) at last processing. */
++static DEFINE_PER_CPU(u64, processed_system_time);
++
++/* How much CPU time was spent blocked and how much was 'stolen'? */
++static DEFINE_PER_CPU(u64, processed_stolen_time);
++static DEFINE_PER_CPU(u64, processed_blocked_time);
++
++/* Current runstate of each CPU (updated automatically by the hypervisor). */
++static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
++
++/* Must be signed, as it's compared with s64 quantities which can be -ve. */
++#define NS_PER_TICK (1000000000LL/HZ)
++
++static void __clock_was_set(void *unused)
++{
++	clock_was_set();
++}
++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)--;
++	}
++}
++
++/* Does this guest OS track Xen time, or set its wall clock independently? */
++static int independent_wallclock = 0;
++static int __init __independent_wallclock(char *str)
++{
++	independent_wallclock = 1;
++	return 1;
++}
++__setup("independent_wallclock", __independent_wallclock);
++
++/* Permitted clock jitter, in nsecs, beyond which a warning will be printed. */
++static unsigned long permitted_clock_jitter = 10000000UL; /* 10ms */
++static int __init __permitted_clock_jitter(char *str)
++{
++	permitted_clock_jitter = simple_strtoul(str, NULL, 0);
++	return 1;
++}
++__setup("permitted_clock_jitter=", __permitted_clock_jitter);
++
++#if 0
++static void delay_tsc(unsigned long loops)
++{
++	unsigned long bclock, now;
++
++	rdtscl(bclock);
++	do {
++		rep_nop();
++		rdtscl(now);
++	} while ((now - bclock) < loops);
++}
++
++struct timer_opts timer_tsc = {
++	.name = "tsc",
++	.delay = delay_tsc,
++};
++#endif
++
++/*
++ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
++ * yielding a 64-bit result.
++ */
++static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
++{
++	u64 product;
++#ifdef __i386__
++	u32 tmp1, tmp2;
++#endif
++
++	if (shift < 0)
++		delta >>= -shift;
++	else
++		delta <<= shift;
++
++#ifdef __i386__
++	__asm__ (
++		"mul  %5       ; "
++		"mov  %4,%%eax ; "
++		"mov  %%edx,%4 ; "
++		"mul  %5       ; "
++		"xor  %5,%5    ; "
++		"add  %4,%%eax ; "
++		"adc  %5,%%edx ; "
++		: "=A" (product), "=r" (tmp1), "=r" (tmp2)
++		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
++#else
++	__asm__ (
++		"mul %%rdx ; shrd $32,%%rdx,%%rax"
++		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
++#endif
++
++	return product;
++}
++
++#if 0 /* defined (__i386__) */
++int read_current_timer(unsigned long *timer_val)
++{
++	rdtscl(*timer_val);
++	return 0;
++}
++#endif
++
++void init_cpu_khz(void)
++{
++	u64 __cpu_khz = 1000000ULL << 32;
++	struct vcpu_time_info *info = &vcpu_info(0)->time;
++	do_div(__cpu_khz, info->tsc_to_system_mul);
++	if (info->tsc_shift < 0)
++		cpu_khz = __cpu_khz << -info->tsc_shift;
++	else
++		cpu_khz = __cpu_khz >> info->tsc_shift;
++}
++
++static u64 get_nsec_offset(struct shadow_time_info *shadow)
++{
++	u64 now, delta;
++	rdtscll(now);
++	delta = now - shadow->tsc_timestamp;
++	return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
++}
++
++static unsigned long get_usec_offset(struct shadow_time_info *shadow)
++{
++	u64 now, delta;
++	rdtscll(now);
++	delta = now - shadow->tsc_timestamp;
++	return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift);
++}
++
++static void __update_wallclock(time_t sec, long nsec)
++{
++	long wtm_nsec, xtime_nsec;
++	time_t wtm_sec, xtime_sec;
++	u64 tmp, wc_nsec;
++
++	/* Adjust wall-clock time base based on wall_jiffies ticks. */
++	wc_nsec = processed_system_time;
++	wc_nsec += sec * (u64)NSEC_PER_SEC;
++	wc_nsec += nsec;
++	wc_nsec -= (jiffies - wall_jiffies) * (u64)NS_PER_TICK;
++
++	/* Split wallclock base into seconds and nanoseconds. */
++	tmp = wc_nsec;
++	xtime_nsec = do_div(tmp, 1000000000);
++	xtime_sec  = (time_t)tmp;
++
++	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
++	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
++
++	set_normalized_timespec(&xtime, xtime_sec, xtime_nsec);
++	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
++}
++
++static void update_wallclock(void)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++
++	do {
++		shadow_tv_version = s->wc_version;
++		rmb();
++		shadow_tv.tv_sec  = s->wc_sec;
++		shadow_tv.tv_nsec = s->wc_nsec;
++		rmb();
++	} while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
++
++	if (!independent_wallclock)
++		__update_wallclock(shadow_tv.tv_sec, shadow_tv.tv_nsec);
++}
++
++/*
++ * Reads a consistent set of time-base values from Xen, into a shadow data
++ * area.
++ */
++static void get_time_values_from_xen(unsigned int cpu)
++{
++	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 {
++		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();
++		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)
++{
++	struct vcpu_time_info   *src;
++	struct shadow_time_info *dst;
++
++	src = &vcpu_info(cpu)->time;
++	dst = &per_cpu(shadow_time, cpu);
++
++	rmb();
++	return (dst->version == src->version);
++}
++
++/*
++ * This is a special lock that is owned by the CPU and holds the index
++ * register we are working with.  It is required for NMI access to the
++ * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
++ */
++volatile unsigned long cmos_lock = 0;
++EXPORT_SYMBOL(cmos_lock);
++
++/* Routines for accessing the CMOS RAM/RTC. */
++unsigned char rtc_cmos_read(unsigned char addr)
++{
++	unsigned char val;
++	lock_cmos_prefix(addr);
++	outb_p(addr, RTC_PORT(0));
++	val = inb_p(RTC_PORT(1));
++	lock_cmos_suffix(addr);
++	return val;
++}
++EXPORT_SYMBOL(rtc_cmos_read);
++
++void rtc_cmos_write(unsigned char val, unsigned char addr)
++{
++	lock_cmos_prefix(addr);
++	outb_p(addr, RTC_PORT(0));
++	outb_p(val, RTC_PORT(1));
++	lock_cmos_suffix(addr);
++}
++EXPORT_SYMBOL(rtc_cmos_write);
++
++/*
++ * This version of gettimeofday has microsecond resolution
++ * and better than microsecond precision on fast x86 machines with TSC.
++ */
++void do_gettimeofday(struct timeval *tv)
++{
++	unsigned long seq;
++	unsigned long usec, sec;
++	unsigned long flags;
++	s64 nsec;
++	unsigned int cpu;
++	struct shadow_time_info *shadow;
++	u32 local_time_version;
++
++	cpu = get_cpu();
++	shadow = &per_cpu(shadow_time, cpu);
++
++	do {
++		unsigned long lost;
++
++		local_time_version = shadow->version;
++		seq = read_seqbegin(&xtime_lock);
++
++		usec = get_usec_offset(shadow);
++		lost = jiffies - wall_jiffies;
++
++		if (unlikely(lost))
++			usec += lost * (USEC_PER_SEC / HZ);
++
++		sec = xtime.tv_sec;
++		usec += (xtime.tv_nsec / NSEC_PER_USEC);
++
++		nsec = shadow->system_timestamp - processed_system_time;
++		__normalize_time(&sec, &nsec);
++		usec += (long)nsec / NSEC_PER_USEC;
++
++		if (unlikely(!time_values_up_to_date(cpu))) {
++			/*
++			 * We may have blocked for a long time,
++			 * rendering our calculations invalid
++			 * (e.g. the time delta may have
++			 * overflowed). Detect that and recalculate
++			 * with fresh values.
++			 */
++			get_time_values_from_xen(cpu);
++			continue;
++		}
++	} while (read_seqretry(&xtime_lock, seq) ||
++		 (local_time_version != shadow->version));
++
++	put_cpu();
++
++	while (usec >= USEC_PER_SEC) {
++		usec -= USEC_PER_SEC;
++		sec++;
++	}
++
++	spin_lock_irqsave(&monotonic_lock, flags);
++	if ((sec > monotonic_tv.tv_sec) ||
++	    ((sec == monotonic_tv.tv_sec) && (usec > monotonic_tv.tv_usec)))
++	{
++		monotonic_tv.tv_sec = sec;
++		monotonic_tv.tv_usec = usec;
++	} else {
++		sec = monotonic_tv.tv_sec;
++		usec = monotonic_tv.tv_usec;
++	}
++	spin_unlock_irqrestore(&monotonic_lock, flags);
++
++	tv->tv_sec = sec;
++	tv->tv_usec = usec;
++}
++
++EXPORT_SYMBOL(do_gettimeofday);
++
++int do_settimeofday(struct timespec *tv)
++{
++	time_t sec;
++	s64 nsec;
++	unsigned int cpu;
++	struct shadow_time_info *shadow;
++	struct xen_platform_op op;
++
++	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
++		return -EINVAL;
++
++	if (!is_initial_xendomain() && !independent_wallclock)
++		return -EPERM;
++
++	cpu = get_cpu();
++	shadow = &per_cpu(shadow_time, cpu);
++
++	write_seqlock_irq(&xtime_lock);
++
++	/*
++	 * Ensure we don't get blocked for a long time so that our time delta
++	 * overflows. If that were to happen then our shadow time values would
++	 * be stale, so we can retry with fresh ones.
++	 */
++	for (;;) {
++		nsec = tv->tv_nsec - get_nsec_offset(shadow);
++		if (time_values_up_to_date(cpu))
++			break;
++		get_time_values_from_xen(cpu);
++	}
++	sec = tv->tv_sec;
++	__normalize_time(&sec, &nsec);
++
++	if (is_initial_xendomain() && !independent_wallclock) {
++		op.cmd = XENPF_settime;
++		op.u.settime.secs        = sec;
++		op.u.settime.nsecs       = nsec;
++		op.u.settime.system_time = shadow->system_timestamp;
++		WARN_ON(HYPERVISOR_platform_op(&op));
++		update_wallclock();
++	} else if (independent_wallclock) {
++		nsec -= shadow->system_timestamp;
++		__normalize_time(&sec, &nsec);
++		__update_wallclock(sec, nsec);
++	}
++	ntp_clear();
++
++	/* Reset monotonic gettimeofday() timeval. */
++	spin_lock(&monotonic_lock);
++	monotonic_tv.tv_sec = 0;
++	monotonic_tv.tv_usec = 0;
++	spin_unlock(&monotonic_lock);
++
++	write_sequnlock_irq(&xtime_lock);
++
++	put_cpu();
++
++	clock_was_set();
++	return 0;
++}
++
++EXPORT_SYMBOL(do_settimeofday);
++
++static void sync_xen_wallclock(unsigned long dummy);
++static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
++static void sync_xen_wallclock(unsigned long dummy)
++{
++	time_t sec;
++	s64 nsec;
++	struct xen_platform_op op;
++
++	if (!ntp_synced() || independent_wallclock || !is_initial_xendomain())
++		return;
++
++	write_seqlock_irq(&xtime_lock);
++
++	sec  = xtime.tv_sec;
++	nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK);
++	__normalize_time(&sec, &nsec);
++
++	op.cmd = XENPF_settime;
++	op.u.settime.secs        = sec;
++	op.u.settime.nsecs       = nsec;
++	op.u.settime.system_time = processed_system_time;
++	WARN_ON(HYPERVISOR_platform_op(&op));
++
++	update_wallclock();
++
++	write_sequnlock_irq(&xtime_lock);
++
++	/* Once per minute. */
++	mod_timer(&sync_xen_wallclock_timer, jiffies + 60*HZ);
++}
++
++static int set_rtc_mmss(unsigned long nowtime)
++{
++	int retval;
++	unsigned long flags;
++
++	if (independent_wallclock || !is_initial_xendomain())
++		return 0;
++
++	/* gets recalled with irq locally disabled */
++	/* XXX - does irqsave resolve this? -johnstul */
++	spin_lock_irqsave(&rtc_lock, flags);
++	if (efi_enabled)
++		retval = efi_set_rtc_mmss(nowtime);
++	else
++		retval = mach_set_rtc_mmss(nowtime);
++	spin_unlock_irqrestore(&rtc_lock, flags);
++
++	return retval;
++}
++
++/* monotonic_clock(): returns # of nanoseconds passed since time_init()
++ *		Note: This function is required to return accurate
++ *		time even in the absence of multiple timer ticks.
++ */
++unsigned long long monotonic_clock(void)
++{
++	unsigned int cpu = get_cpu();
++	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
++	u64 time;
++	u32 local_time_version;
++
++	do {
++		local_time_version = shadow->version;
++		barrier();
++		time = shadow->system_timestamp + get_nsec_offset(shadow);
++		if (!time_values_up_to_date(cpu))
++			get_time_values_from_xen(cpu);
++		barrier();
++	} while (local_time_version != shadow->version);
++
++	put_cpu();
++
++	return time;
++}
++EXPORT_SYMBOL(monotonic_clock);
++
++#ifdef __x86_64__
++unsigned long long sched_clock(void)
++{
++	return monotonic_clock();
++}
++#endif
++
++#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
++unsigned long profile_pc(struct pt_regs *regs)
++{
++	unsigned long pc = instruction_pointer(regs);
++
++#ifdef __x86_64__
++	/* Assume the lock function has either no stack frame or only a single word.
++	   This checks if the address on the stack looks like a kernel text address.
++	   There is a small window for false hits, but in that case the tick
++	   is just accounted to the spinlock function.
++	   Better would be to write these functions in assembler again
++	   and check exactly. */
++	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
++		char *v = *(char **)regs->rsp;
++		if ((v >= _stext && v <= _etext) ||
++			(v >= _sinittext && v <= _einittext) ||
++			(v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
++			return (unsigned long)v;
++		return ((unsigned long *)regs->rsp)[1];
++	}
++#else
++	if (!user_mode_vm(regs) && in_lock_functions(pc))
++		return *(unsigned long *)(regs->ebp + 4);
++#endif
++
++	return pc;
++}
++EXPORT_SYMBOL(profile_pc);
++#endif
++
++/*
++ * This is the same as the above, except we _also_ save the current
++ * Time Stamp Counter value at the time of the timer interrupt, so that
++ * we later on can estimate the time of day more exactly.
++ */
++irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++	s64 delta, delta_cpu, stolen, blocked;
++	u64 sched_time;
++	unsigned int i, cpu = smp_processor_id();
++	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
++	struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
++
++	/*
++	 * Here we are in the timer irq handler. We just have irqs locally
++	 * disabled but we don't know if the timer_bh is running on the other
++	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
++	 * the irq version of write_lock because as just said we have irq
++	 * locally disabled. -arca
++	 */
++	write_seqlock(&xtime_lock);
++
++	do {
++		get_time_values_from_xen(cpu);
++
++		/* Obtain a consistent snapshot of elapsed wallclock cycles. */
++		delta = delta_cpu =
++			shadow->system_timestamp + get_nsec_offset(shadow);
++		delta     -= processed_system_time;
++		delta_cpu -= per_cpu(processed_system_time, cpu);
++
++		/*
++		 * Obtain a consistent snapshot of stolen/blocked cycles. We
++		 * can use state_entry_time to detect if we get preempted here.
++		 */
++		do {
++			sched_time = runstate->state_entry_time;
++			barrier();
++			stolen = runstate->time[RUNSTATE_runnable] +
++				runstate->time[RUNSTATE_offline] -
++				per_cpu(processed_stolen_time, cpu);
++			blocked = runstate->time[RUNSTATE_blocked] -
++				per_cpu(processed_blocked_time, cpu);
++			barrier();
++		} while (sched_time != runstate->state_entry_time);
++	} while (!time_values_up_to_date(cpu));
++
++	if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
++	     unlikely(delta_cpu < -(s64)permitted_clock_jitter))
++	    && printk_ratelimit()) {
++		printk("Timer ISR/%u: Time went backwards: "
++		       "delta=%lld delta_cpu=%lld shadow=%lld "
++		       "off=%lld processed=%lld cpu_processed=%lld\n",
++		       cpu, delta, delta_cpu, shadow->system_timestamp,
++		       (s64)get_nsec_offset(shadow),
++		       processed_system_time,
++		       per_cpu(processed_system_time, cpu));
++		for (i = 0; i < num_online_cpus(); i++)
++			printk(" %d: %lld\n", i,
++			       per_cpu(processed_system_time, i));
++	}
++
++	/* System-wide jiffy work. */
++	while (delta >= NS_PER_TICK) {
++		delta -= NS_PER_TICK;
++		processed_system_time += NS_PER_TICK;
++		do_timer(regs);
++	}
++
++	if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
++		update_wallclock();
++		if (keventd_up())
++			schedule_work(&clock_was_set_work);
++	}
++
++	write_sequnlock(&xtime_lock);
++
++	/*
++	 * Account stolen ticks.
++	 * HACK: Passing NULL to account_steal_time()
++	 * ensures that the ticks are accounted as stolen.
++	 */
++	if ((stolen > 0) && (delta_cpu > 0)) {
++		delta_cpu -= stolen;
++		if (unlikely(delta_cpu < 0))
++			stolen += delta_cpu; /* clamp local-time progress */
++		do_div(stolen, NS_PER_TICK);
++		per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK;
++		per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK;
++		account_steal_time(NULL, (cputime_t)stolen);
++	}
++
++	/*
++	 * Account blocked ticks.
++	 * HACK: Passing idle_task to account_steal_time()
++	 * ensures that the ticks are accounted as idle/wait.
++	 */
++	if ((blocked > 0) && (delta_cpu > 0)) {
++		delta_cpu -= blocked;
++		if (unlikely(delta_cpu < 0))
++			blocked += delta_cpu; /* clamp local-time progress */
++		do_div(blocked, NS_PER_TICK);
++		per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK;
++		per_cpu(processed_system_time, cpu)  += blocked * NS_PER_TICK;
++		account_steal_time(idle_task(cpu), (cputime_t)blocked);
++	}
++
++	/* Account user/system ticks. */
++	if (delta_cpu > 0) {
++		do_div(delta_cpu, NS_PER_TICK);
++		per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK;
++		if (user_mode_vm(regs))
++			account_user_time(current, (cputime_t)delta_cpu);
++		else
++			account_system_time(current, HARDIRQ_OFFSET,
++					    (cputime_t)delta_cpu);
++	}
++
++	/* Offlined for more than a few seconds? Avoid lockup warnings. */
++	if (stolen > 5*HZ)
++		touch_softlockup_watchdog();
++
++	/* Local timer processing (see update_process_times()). */
++	run_local_timers();
++	if (rcu_pending(cpu))
++		rcu_check_callbacks(cpu, user_mode_vm(regs));
++	scheduler_tick();
++	run_posix_cpu_timers(current);
++	profile_tick(CPU_PROFILING, regs);
++
++	return IRQ_HANDLED;
++}
++
++static void init_missing_ticks_accounting(unsigned int cpu)
++{
++	struct vcpu_register_runstate_memory_area area;
++	struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
++	int rc;
++
++	memset(runstate, 0, sizeof(*runstate));
++
++	area.addr.v = runstate;
++	rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area);
++	WARN_ON(rc && rc != -ENOSYS);
++
++	per_cpu(processed_blocked_time, cpu) =
++		runstate->time[RUNSTATE_blocked];
++	per_cpu(processed_stolen_time, cpu) =
++		runstate->time[RUNSTATE_runnable] +
++		runstate->time[RUNSTATE_offline];
++}
++
++/* not static: needed by APM */
++unsigned long get_cmos_time(void)
++{
++	unsigned long retval;
++	unsigned long flags;
++
++	spin_lock_irqsave(&rtc_lock, flags);
++
++	if (efi_enabled)
++		retval = efi_get_time();
++	else
++		retval = mach_get_cmos_time();
++
++	spin_unlock_irqrestore(&rtc_lock, flags);
++
++	return retval;
++}
++EXPORT_SYMBOL(get_cmos_time);
++
++static void sync_cmos_clock(unsigned long dummy);
++
++static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
++
++static void sync_cmos_clock(unsigned long dummy)
++{
++	struct timeval now, next;
++	int fail = 1;
++
++	/*
++	 * If we have an externally synchronized Linux clock, then update
++	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
++	 * called as close as possible to 500 ms before the new second starts.
++	 * This code is run on a timer.  If the clock is set, that timer
++	 * may not expire at the correct time.  Thus, we adjust...
++	 */
++	if (!ntp_synced())
++		/*
++		 * Not synced, exit, do not restart a timer (if one is
++		 * running, let it run out).
++		 */
++		return;
++
++	do_gettimeofday(&now);
++	if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
++	    now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
++		fail = set_rtc_mmss(now.tv_sec);
++
++	next.tv_usec = USEC_AFTER - now.tv_usec;
++	if (next.tv_usec <= 0)
++		next.tv_usec += USEC_PER_SEC;
++
++	if (!fail)
++		next.tv_sec = 659;
++	else
++		next.tv_sec = 0;
++
++	if (next.tv_usec >= USEC_PER_SEC) {
++		next.tv_sec++;
++		next.tv_usec -= USEC_PER_SEC;
++	}
++	mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
++}
++
++void notify_arch_cmos_timer(void)
++{
++	mod_timer(&sync_cmos_timer, jiffies + 1);
++	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
++}
++
++static int timer_resume(struct sys_device *dev)
++{
++	extern void time_resume(void);
++	time_resume();
++	return 0;
++}
++
++static struct sysdev_class timer_sysclass = {
++	.resume = timer_resume,
++	set_kset_name("timer"),
++};
++
++
++/* XXX this driverfs stuff should probably go elsewhere later -john */
++static struct sys_device device_timer = {
++	.id	= 0,
++	.cls	= &timer_sysclass,
++};
++
++static int time_init_device(void)
++{
++	int error = sysdev_class_register(&timer_sysclass);
++	if (!error)
++		error = sysdev_register(&device_timer);
++	return error;
++}
++
++device_initcall(time_init_device);
++
++#ifdef CONFIG_HPET_TIMER
++extern void (*late_time_init)(void);
++/* Duplicate of time_init() below, with hpet_enable part added */
++static void __init hpet_time_init(void)
++{
++	xtime.tv_sec = get_cmos_time();
++	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
++	set_normalized_timespec(&wall_to_monotonic,
++		-xtime.tv_sec, -xtime.tv_nsec);
++
++	if ((hpet_enable() >= 0) && hpet_use_timer) {
++		printk("Using HPET for base-timer\n");
++	}
++
++	time_init_hook();
++}
++#endif
++
++/* Dynamically-mapped IRQ. */
++DEFINE_PER_CPU(int, timer_irq);
++
++extern void (*late_time_init)(void);
++static void setup_cpu0_timer_irq(void)
++{
++	per_cpu(timer_irq, 0) =
++		bind_virq_to_irqhandler(
++			VIRQ_TIMER,
++			0,
++			timer_interrupt,
++			SA_INTERRUPT,
++			"timer0",
++			NULL);
++	BUG_ON(per_cpu(timer_irq, 0) < 0);
++}
++
++static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
++	.period_ns = NS_PER_TICK
++};
++
++void __init time_init(void)
++{
++#ifdef CONFIG_HPET_TIMER
++	if (is_hpet_capable()) {
++		/*
++		 * HPET initialization needs to do memory-mapped io. So, let
++		 * us do a late initialization after mem_init().
++		 */
++		late_time_init = hpet_time_init;
++		return;
++	}
++#endif
++
++	switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
++				   &xen_set_periodic_tick)) {
++	case 0:
++#if CONFIG_XEN_COMPAT <= 0x030004
++	case -ENOSYS:
++#endif
++		break;
++	default:
++		BUG();
++	}
++
++	get_time_values_from_xen(0);
++
++	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
++	per_cpu(processed_system_time, 0) = processed_system_time;
++	init_missing_ticks_accounting(0);
++
++	update_wallclock();
++
++	init_cpu_khz();
++	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
++	       cpu_khz / 1000, cpu_khz % 1000);
++
++#if defined(__x86_64__)
++	vxtime.mode = VXTIME_TSC;
++	vxtime.quot = (1000000L << 32) / vxtime_hz;
++	vxtime.tsc_quot = (1000L << 32) / cpu_khz;
++	sync_core();
++	rdtscll(vxtime.last_tsc);
++#endif
++
++	/* Cannot request_irq() until kmem is initialised. */
++	late_time_init = setup_cpu0_timer_irq;
++}
++
++/* Convert jiffies to system time. */
++u64 jiffies_to_st(unsigned long j)
++{
++	unsigned long seq;
++	long delta;
++	u64 st;
++
++	do {
++		seq = read_seqbegin(&xtime_lock);
++		delta = j - jiffies;
++		if (delta < 1) {
++			/* Triggers in some wrap-around cases, but that's okay:
++			 * we just end up with a shorter timeout. */
++			st = processed_system_time + NS_PER_TICK;
++		} else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
++			/* Very long timeout means there is no pending timer.
++			 * We indicate this to Xen by passing zero timeout. */
++			st = 0;
++		} else {
++			st = processed_system_time + delta * (u64)NS_PER_TICK;
++		}
++	} while (read_seqretry(&xtime_lock, seq));
++
++	return st;
++}
++EXPORT_SYMBOL(jiffies_to_st);
++
++/*
++ * stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
++ * These functions are based on implementations from arch/s390/kernel/time.c
++ */
++static void stop_hz_timer(void)
++{
++	struct vcpu_set_singleshot_timer singleshot;
++	unsigned int cpu = smp_processor_id();
++	unsigned long j;
++	int rc;
++
++	cpu_set(cpu, nohz_cpu_mask);
++
++	/* See matching smp_mb in rcu_start_batch in rcupdate.c.  These mbs  */
++	/* ensure that if __rcu_pending (nested in rcu_needs_cpu) fetches a  */
++	/* value of rcp->cur that matches rdp->quiescbatch and allows us to  */
++	/* stop the hz timer then the cpumasks created for subsequent values */
++	/* of cur in rcu_start_batch are guaranteed to pick up the updated   */
++	/* nohz_cpu_mask and so will not depend on this cpu.                 */
++
++	smp_mb();
++
++	/* Leave ourselves in tick mode if rcu or softirq or timer pending. */
++	if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
++	    (j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
++		cpu_clear(cpu, nohz_cpu_mask);
++		j = jiffies + 1;
++	}
++
++	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
++	if (rc) {
++		BUG_ON(rc != -ENOSYS);
++		rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
++	}
++#endif
++	BUG_ON(rc);
++}
++
++static void start_hz_timer(void)
++{
++	cpu_clear(smp_processor_id(), nohz_cpu_mask);
++}
++
++void raw_safe_halt(void)
++{
++	stop_hz_timer();
++	/* Blocking includes an implicit local_irq_enable(). */
++	HYPERVISOR_block();
++	start_hz_timer();
++}
++EXPORT_SYMBOL(raw_safe_halt);
++
++void halt(void)
++{
++	if (irqs_disabled())
++		VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
++}
++EXPORT_SYMBOL(halt);
++
++/* No locking required. Interrupts are disabled on all CPUs. */
++void time_resume(void)
++{
++	unsigned int cpu;
++
++	init_cpu_khz();
++
++	for_each_online_cpu(cpu) {
++		switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
++					   &xen_set_periodic_tick)) {
++		case 0:
++#if CONFIG_XEN_COMPAT <= 0x030004
++		case -ENOSYS:
++#endif
++			break;
++		default:
++			BUG();
++		}
++		get_time_values_from_xen(cpu);
++		per_cpu(processed_system_time, cpu) =
++			per_cpu(shadow_time, 0).system_timestamp;
++		init_missing_ticks_accounting(cpu);
++	}
++
++	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
++
++	update_wallclock();
++}
++
++#ifdef CONFIG_SMP
++static char timer_name[NR_CPUS][15];
++
++int __cpuinit local_setup_timer(unsigned int cpu)
++{
++	int seq, irq;
++
++	BUG_ON(cpu == 0);
++
++	switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
++			   &xen_set_periodic_tick)) {
++	case 0:
++#if CONFIG_XEN_COMPAT <= 0x030004
++	case -ENOSYS:
++#endif
++		break;
++	default:
++		BUG();
++	}
++
++	do {
++		seq = read_seqbegin(&xtime_lock);
++		/* Use cpu0 timestamp: cpu's shadow is not initialised yet. */
++		per_cpu(processed_system_time, cpu) =
++			per_cpu(shadow_time, 0).system_timestamp;
++		init_missing_ticks_accounting(cpu);
++	} while (read_seqretry(&xtime_lock, seq));
++
++	sprintf(timer_name[cpu], "timer%u", cpu);
++	irq = bind_virq_to_irqhandler(VIRQ_TIMER,
++				      cpu,
++				      timer_interrupt,
++				      SA_INTERRUPT,
++				      timer_name[cpu],
++				      NULL);
++	if (irq < 0)
++		return irq;
++	per_cpu(timer_irq, cpu) = irq;
++
++	return 0;
++}
++
++void __cpuexit local_teardown_timer(unsigned int cpu)
++{
++	BUG_ON(cpu == 0);
++	unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
++}
++#endif
++
++#ifdef CONFIG_CPU_FREQ
++static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 
++				void *data)
++{
++	struct cpufreq_freqs *freq = data;
++	struct xen_platform_op op;
++
++	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
++		return 0;
++
++	if (val == CPUFREQ_PRECHANGE)
++		return 0;
++
++	op.cmd = XENPF_change_freq;
++	op.u.change_freq.flags = 0;
++	op.u.change_freq.cpu = freq->cpu;
++	op.u.change_freq.freq = (u64)freq->new * 1000;
++	WARN_ON(HYPERVISOR_platform_op(&op));
++
++	return 0;
++}
++
++static struct notifier_block time_cpufreq_notifier_block = {
++	.notifier_call = time_cpufreq_notifier
++};
++
++static int __init cpufreq_time_setup(void)
++{
++	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
++			CPUFREQ_TRANSITION_NOTIFIER)) {
++		printk(KERN_ERR "failed to set up cpufreq notifier\n");
++		return -ENODEV;
++	}
++	return 0;
++}
++
++core_initcall(cpufreq_time_setup);
++#endif
++
++/*
++ * /proc/sys/xen: This really belongs in another file. It can stay here for
++ * now however.
++ */
++static ctl_table xen_subtable[] = {
++	{
++		.ctl_name	= 1,
++		.procname	= "independent_wallclock",
++		.data		= &independent_wallclock,
++		.maxlen		= sizeof(independent_wallclock),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec
++	},
++	{
++		.ctl_name	= 2,
++		.procname	= "permitted_clock_jitter",
++		.data		= &permitted_clock_jitter,
++		.maxlen		= sizeof(permitted_clock_jitter),
++		.mode		= 0644,
++		.proc_handler	= proc_doulongvec_minmax
++	},
++	{ 0 }
++};
++static ctl_table xen_table[] = {
++	{
++		.ctl_name	= 123,
++		.procname	= "xen",
++		.mode		= 0555,
++		.child		= xen_subtable},
++	{ 0 }
++};
++static int __init xen_sysctl_init(void)
++{
++	(void)register_sysctl_table(xen_table, 0);
++	return 0;
++}
++__initcall(xen_sysctl_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,1190 @@
++/*
++ *  linux/arch/i386/traps.c
++ *
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ *
++ *  Pentium III FXSR, SSE support
++ *	Gareth Hughes <gareth@valinux.com>, May 2000
++ */
++
++/*
++ * 'Traps.c' handles hardware traps and faults after we have saved some
++ * state in 'asm.s'.
++ */
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/highmem.h>
++#include <linux/kallsyms.h>
++#include <linux/ptrace.h>
++#include <linux/utsname.h>
++#include <linux/kprobes.h>
++#include <linux/kexec.h>
++#include <linux/unwind.h>
++
++#ifdef CONFIG_EISA
++#include <linux/ioport.h>
++#include <linux/eisa.h>
++#endif
++
++#ifdef CONFIG_MCA
++#include <linux/mca.h>
++#endif
++
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/atomic.h>
++#include <asm/debugreg.h>
++#include <asm/desc.h>
++#include <asm/i387.h>
++#include <asm/nmi.h>
++#include <asm/unwind.h>
++#include <asm/smp.h>
++#include <asm/arch_hooks.h>
++#include <asm/kdebug.h>
++
++#include <linux/module.h>
++
++#include "mach_traps.h"
++
++asmlinkage int system_call(void);
++
++struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
++		{ 0, 0 }, { 0, 0 } };
++
++/* Do we ignore FPU interrupts ? */
++char ignore_fpu_irq = 0;
++
++#ifndef CONFIG_X86_NO_IDT
++/*
++ * The IDT has to be page-aligned to simplify the Pentium
++ * F0 0F bug workaround.. We have a special link segment
++ * for this.
++ */
++struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
++#endif
++
++asmlinkage void divide_error(void);
++asmlinkage void debug(void);
++asmlinkage void nmi(void);
++asmlinkage void int3(void);
++asmlinkage void overflow(void);
++asmlinkage void bounds(void);
++asmlinkage void invalid_op(void);
++asmlinkage void device_not_available(void);
++asmlinkage void coprocessor_segment_overrun(void);
++asmlinkage void invalid_TSS(void);
++asmlinkage void segment_not_present(void);
++asmlinkage void stack_segment(void);
++asmlinkage void general_protection(void);
++asmlinkage void page_fault(void);
++asmlinkage void coprocessor_error(void);
++asmlinkage void simd_coprocessor_error(void);
++asmlinkage void alignment_check(void);
++#ifndef CONFIG_XEN
++asmlinkage void spurious_interrupt_bug(void);
++#else
++asmlinkage void fixup_4gb_segment(void);
++#endif
++asmlinkage void machine_check(void);
++
++static int kstack_depth_to_print = 24;
++#ifdef CONFIG_STACK_UNWIND
++static int call_trace = 1;
++#else
++#define call_trace (-1)
++#endif
++ATOMIC_NOTIFIER_HEAD(i386die_chain);
++
++int register_die_notifier(struct notifier_block *nb)
++{
++	vmalloc_sync_all();
++	return atomic_notifier_chain_register(&i386die_chain, nb);
++}
++EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
++
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&i386die_chain, nb);
++}
++EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
++
++static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
++{
++	return	p > (void *)tinfo &&
++		p < (void *)tinfo + THREAD_SIZE - 3;
++}
++
++/*
++ * Print one address/symbol entries per line.
++ */
++static inline void print_addr_and_symbol(unsigned long addr, char *log_lvl)
++{
++	printk(" [<%08lx>] ", addr);
++
++	print_symbol("%s\n", addr);
++}
++
++static inline unsigned long print_context_stack(struct thread_info *tinfo,
++				unsigned long *stack, unsigned long ebp,
++				char *log_lvl)
++{
++	unsigned long addr;
++
++#ifdef	CONFIG_FRAME_POINTER
++	while (valid_stack_ptr(tinfo, (void *)ebp)) {
++		addr = *(unsigned long *)(ebp + 4);
++		print_addr_and_symbol(addr, log_lvl);
++		/*
++		 * break out of recursive entries (such as
++		 * end_of_stack_stop_unwind_function):
++	 	 */
++		if (ebp == *(unsigned long *)ebp)
++			break;
++		ebp = *(unsigned long *)ebp;
++	}
++#else
++	while (valid_stack_ptr(tinfo, stack)) {
++		addr = *stack++;
++		if (__kernel_text_address(addr))
++			print_addr_and_symbol(addr, log_lvl);
++	}
++#endif
++	return ebp;
++}
++
++static asmlinkage int
++show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
++{
++	int n = 0;
++
++	while (unwind(info) == 0 && UNW_PC(info)) {
++		n++;
++		print_addr_and_symbol(UNW_PC(info), log_lvl);
++		if (arch_unw_user_mode(info))
++			break;
++	}
++	return n;
++}
++
++static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
++			       unsigned long *stack, char *log_lvl)
++{
++	unsigned long ebp;
++
++	if (!task)
++		task = current;
++
++	if (call_trace >= 0) {
++		int unw_ret = 0;
++		struct unwind_frame_info info;
++
++		if (regs) {
++			if (unwind_init_frame_info(&info, task, regs) == 0)
++				unw_ret = show_trace_unwind(&info, log_lvl);
++		} else if (task == current)
++			unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
++		else {
++			if (unwind_init_blocked(&info, task) == 0)
++				unw_ret = show_trace_unwind(&info, log_lvl);
++		}
++		if (unw_ret > 0) {
++			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
++				print_symbol("DWARF2 unwinder stuck at %s\n",
++					     UNW_PC(&info));
++				if (UNW_SP(&info) >= PAGE_OFFSET) {
++					printk("Leftover inexact backtrace:\n");
++					stack = (void *)UNW_SP(&info);
++				} else
++					printk("Full inexact backtrace again:\n");
++			} else if (call_trace >= 1)
++				return;
++			else
++				printk("Full inexact backtrace again:\n");
++		} else
++			printk("Inexact backtrace:\n");
++	}
++
++	if (task == current) {
++		/* Grab ebp right from our regs */
++		asm ("movl %%ebp, %0" : "=r" (ebp) : );
++	} else {
++		/* ebp is the last reg pushed by switch_to */
++		ebp = *(unsigned long *) task->thread.esp;
++	}
++
++	while (1) {
++		struct thread_info *context;
++		context = (struct thread_info *)
++			((unsigned long)stack & (~(THREAD_SIZE - 1)));
++		ebp = print_context_stack(context, stack, ebp, log_lvl);
++		stack = (unsigned long*)context->previous_esp;
++		if (!stack)
++			break;
++		printk("%s =======================\n", log_lvl);
++	}
++}
++
++void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack)
++{
++	show_trace_log_lvl(task, regs, stack, "");
++}
++
++static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
++			       unsigned long *esp, char *log_lvl)
++{
++	unsigned long *stack;
++	int i;
++
++	if (esp == NULL) {
++		if (task)
++			esp = (unsigned long*)task->thread.esp;
++		else
++			esp = (unsigned long *)&esp;
++	}
++
++	stack = esp;
++	for(i = 0; i < kstack_depth_to_print; i++) {
++		if (kstack_end(stack))
++			break;
++		if (i && ((i % 8) == 0))
++			printk("\n%s       ", log_lvl);
++		printk("%08lx ", *stack++);
++	}
++	printk("\n%sCall Trace:\n", log_lvl);
++	show_trace_log_lvl(task, regs, esp, log_lvl);
++}
++
++void show_stack(struct task_struct *task, unsigned long *esp)
++{
++	printk("       ");
++	show_stack_log_lvl(task, NULL, esp, "");
++}
++
++/*
++ * The architecture-independent dump_stack generator
++ */
++void dump_stack(void)
++{
++	unsigned long stack;
++
++	show_trace(current, NULL, &stack);
++}
++
++EXPORT_SYMBOL(dump_stack);
++
++void show_registers(struct pt_regs *regs)
++{
++	int i;
++	int in_kernel = 1;
++	unsigned long esp;
++	unsigned short ss;
++
++	esp = (unsigned long) (&regs->esp);
++	savesegment(ss, ss);
++	if (user_mode_vm(regs)) {
++		in_kernel = 0;
++		esp = regs->esp;
++		ss = regs->xss & 0xffff;
++	}
++	print_modules();
++	printk(KERN_EMERG "CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\n"
++			"EFLAGS: %08lx   (%s %.*s) \n",
++		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
++		print_tainted(), regs->eflags, system_utsname.release,
++		(int)strcspn(system_utsname.version, " "),
++		system_utsname.version);
++	print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
++	printk(KERN_EMERG "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
++		regs->eax, regs->ebx, regs->ecx, regs->edx);
++	printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
++		regs->esi, regs->edi, regs->ebp, esp);
++	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
++		regs->xds & 0xffff, regs->xes & 0xffff, ss);
++	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
++		TASK_COMM_LEN, current->comm, current->pid,
++		current_thread_info(), current, current->thread_info);
++	/*
++	 * When in-kernel, we also print out the stack and code at the
++	 * time of the fault..
++	 */
++	if (in_kernel) {
++		u8 __user *eip;
++
++		printk("\n" KERN_EMERG "Stack: ");
++		show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
++
++		printk(KERN_EMERG "Code: ");
++
++		eip = (u8 __user *)regs->eip - 43;
++		for (i = 0; i < 64; i++, eip++) {
++			unsigned char c;
++
++			if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
++				printk(" Bad EIP value.");
++				break;
++			}
++			if (eip == (u8 __user *)regs->eip)
++				printk("<%02x> ", c);
++			else
++				printk("%02x ", c);
++		}
++	}
++	printk("\n");
++}	
++
++static void handle_BUG(struct pt_regs *regs)
++{
++	unsigned long eip = regs->eip;
++	unsigned short ud2;
++
++	if (eip < PAGE_OFFSET)
++		return;
++	if (__get_user(ud2, (unsigned short __user *)eip))
++		return;
++	if (ud2 != 0x0b0f)
++		return;
++
++	printk(KERN_EMERG "------------[ cut here ]------------\n");
++
++#ifdef CONFIG_DEBUG_BUGVERBOSE
++	do {
++		unsigned short line;
++		char *file;
++		char c;
++
++		if (__get_user(line, (unsigned short __user *)(eip + 2)))
++			break;
++		if (__get_user(file, (char * __user *)(eip + 4)) ||
++		    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
++			file = "<bad filename>";
++
++		printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
++		return;
++	} while (0);
++#endif
++	printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
++}
++
++/* This is gone through when something in the kernel
++ * has done something bad and is about to be terminated.
++*/
++void die(const char * str, struct pt_regs * regs, long err)
++{
++	static struct {
++		spinlock_t lock;
++		u32 lock_owner;
++		int lock_owner_depth;
++	} die = {
++		.lock =			SPIN_LOCK_UNLOCKED,
++		.lock_owner =		-1,
++		.lock_owner_depth =	0
++	};
++	static int die_counter;
++	unsigned long flags;
++
++	oops_enter();
++
++	if (die.lock_owner != raw_smp_processor_id()) {
++		console_verbose();
++		spin_lock_irqsave(&die.lock, flags);
++		die.lock_owner = smp_processor_id();
++		die.lock_owner_depth = 0;
++		bust_spinlocks(1);
++	}
++	else
++		local_save_flags(flags);
++
++	if (++die.lock_owner_depth < 3) {
++		int nl = 0;
++		unsigned long esp;
++		unsigned short ss;
++
++		handle_BUG(regs);
++		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
++#ifdef CONFIG_PREEMPT
++		printk(KERN_EMERG "PREEMPT ");
++		nl = 1;
++#endif
++#ifdef CONFIG_SMP
++		if (!nl)
++			printk(KERN_EMERG);
++		printk("SMP ");
++		nl = 1;
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++		if (!nl)
++			printk(KERN_EMERG);
++		printk("DEBUG_PAGEALLOC");
++		nl = 1;
++#endif
++		if (nl)
++			printk("\n");
++		if (notify_die(DIE_OOPS, str, regs, err,
++					current->thread.trap_no, SIGSEGV) !=
++				NOTIFY_STOP) {
++			show_registers(regs);
++			/* Executive summary in case the oops scrolled away */
++			esp = (unsigned long) (&regs->esp);
++			savesegment(ss, ss);
++			if (user_mode(regs)) {
++				esp = regs->esp;
++				ss = regs->xss & 0xffff;
++			}
++			printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
++			print_symbol("%s", regs->eip);
++			printk(" SS:ESP %04x:%08lx\n", ss, esp);
++		}
++		else
++			regs = NULL;
++  	} else
++		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
++
++	bust_spinlocks(0);
++	die.lock_owner = -1;
++	spin_unlock_irqrestore(&die.lock, flags);
++
++	if (!regs)
++		return;
++
++	if (kexec_should_crash(current))
++		crash_kexec(regs);
++
++	if (in_interrupt())
++		panic("Fatal exception in interrupt");
++
++	if (panic_on_oops)
++		panic("Fatal exception");
++
++	oops_exit();
++	do_exit(SIGSEGV);
++}
++
++static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
++{
++	if (!user_mode_vm(regs))
++		die(str, regs, err);
++}
++
++static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
++			      struct pt_regs * regs, long error_code,
++			      siginfo_t *info)
++{
++	struct task_struct *tsk = current;
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
++
++	if (regs->eflags & VM_MASK) {
++		if (vm86)
++			goto vm86_trap;
++		goto trap_signal;
++	}
++
++	if (!user_mode(regs))
++		goto kernel_trap;
++
++	trap_signal: {
++		if (info)
++			force_sig_info(signr, info, tsk);
++		else
++			force_sig(signr, tsk);
++		return;
++	}
++
++	kernel_trap: {
++		if (!fixup_exception(regs))
++			die(str, regs, error_code);
++		return;
++	}
++
++	vm86_trap: {
++		int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
++		if (ret) goto trap_signal;
++		return;
++	}
++}
++
++#define DO_ERROR(trapnr, signr, str, name) \
++fastcall void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++						== NOTIFY_STOP) \
++		return; \
++	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
++}
++
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++fastcall void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	siginfo_t info; \
++	info.si_signo = signr; \
++	info.si_errno = 0; \
++	info.si_code = sicode; \
++	info.si_addr = (void __user *)siaddr; \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++						== NOTIFY_STOP) \
++		return; \
++	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
++}
++
++#define DO_VM86_ERROR(trapnr, signr, str, name) \
++fastcall void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++						== NOTIFY_STOP) \
++		return; \
++	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
++}
++
++#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++fastcall void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	siginfo_t info; \
++	info.si_signo = signr; \
++	info.si_errno = 0; \
++	info.si_code = sicode; \
++	info.si_addr = (void __user *)siaddr; \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++						== NOTIFY_STOP) \
++		return; \
++	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
++}
++
++DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
++#ifndef CONFIG_KPROBES
++DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
++#endif
++DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
++DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
++DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
++DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
++DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
++DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
++DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
++
++fastcall void __kprobes do_general_protection(struct pt_regs * regs,
++					      long error_code)
++{
++	current->thread.error_code = error_code;
++	current->thread.trap_no = 13;
++
++	if (regs->eflags & VM_MASK)
++		goto gp_in_vm86;
++
++	if (!user_mode(regs))
++		goto gp_in_kernel;
++
++	current->thread.error_code = error_code;
++	current->thread.trap_no = 13;
++	force_sig(SIGSEGV, current);
++	return;
++
++gp_in_vm86:
++	local_irq_enable();
++	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
++	return;
++
++gp_in_kernel:
++	if (!fixup_exception(regs)) {
++		if (notify_die(DIE_GPF, "general protection fault", regs,
++				error_code, 13, SIGSEGV) == NOTIFY_STOP)
++			return;
++		die("general protection fault", regs, error_code);
++	}
++}
++
++static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
++{
++	printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
++			"to continue\n");
++	printk(KERN_EMERG "You probably have a hardware problem with your RAM "
++			"chips\n");
++
++	/* Clear and disable the memory parity error line. */
++	clear_mem_error(reason);
++}
++
++static void io_check_error(unsigned char reason, struct pt_regs * regs)
++{
++	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
++	show_registers(regs);
++
++	/* Re-enable the IOCK line, wait for a few seconds */
++	clear_io_check_error(reason);
++}
++
++static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++{
++#ifdef CONFIG_MCA
++	/* Might actually be able to figure out what the guilty party
++	* is. */
++	if( MCA_bus ) {
++		mca_handle_nmi();
++		return;
++	}
++#endif
++	printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++		reason, smp_processor_id());
++	printk("Dazed and confused, but trying to continue\n");
++	printk("Do you have a strange power saving mode enabled?\n");
++}
++
++static DEFINE_SPINLOCK(nmi_print_lock);
++
++void die_nmi (struct pt_regs *regs, const char *msg)
++{
++	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
++	    NOTIFY_STOP)
++		return;
++
++	spin_lock(&nmi_print_lock);
++	/*
++	* We are in trouble anyway, lets at least try
++	* to get a message out.
++	*/
++	bust_spinlocks(1);
++	printk(KERN_EMERG "%s", msg);
++	printk(" on CPU%d, eip %08lx, registers:\n",
++		smp_processor_id(), regs->eip);
++	show_registers(regs);
++	printk(KERN_EMERG "console shuts up ...\n");
++	console_silent();
++	spin_unlock(&nmi_print_lock);
++	bust_spinlocks(0);
++
++	/* If we are in kernel we are probably nested up pretty bad
++	 * and might aswell get out now while we still can.
++	*/
++	if (!user_mode_vm(regs)) {
++		current->thread.trap_no = 2;
++		crash_kexec(regs);
++	}
++
++	do_exit(SIGSEGV);
++}
++
++static void default_do_nmi(struct pt_regs * regs)
++{
++	unsigned char reason = 0;
++
++	/* Only the BSP gets external NMIs from the system.  */
++	if (!smp_processor_id())
++		reason = get_nmi_reason();
++ 
++	if (!(reason & 0xc0)) {
++		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
++							== NOTIFY_STOP)
++			return;
++#ifdef CONFIG_X86_LOCAL_APIC
++		/*
++		 * Ok, so this is none of the documented NMI sources,
++		 * so it must be the NMI watchdog.
++		 */
++		if (nmi_watchdog) {
++			nmi_watchdog_tick(regs);
++			return;
++		}
++#endif
++		unknown_nmi_error(reason, regs);
++		return;
++	}
++	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
++	if (reason & 0x80)
++		mem_parity_error(reason, regs);
++	if (reason & 0x40)
++		io_check_error(reason, regs);
++	/*
++	 * Reassert NMI in case it became active meanwhile
++	 * as it's edge-triggered.
++	 */
++	reassert_nmi();
++}
++
++static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
++{
++	return 0;
++}
++ 
++static nmi_callback_t nmi_callback = dummy_nmi_callback;
++ 
++fastcall void do_nmi(struct pt_regs * regs, long error_code)
++{
++	int cpu;
++
++	nmi_enter();
++
++	cpu = smp_processor_id();
++
++	++nmi_count(cpu);
++
++	if (!rcu_dereference(nmi_callback)(regs, cpu))
++		default_do_nmi(regs);
++
++	nmi_exit();
++}
++
++void set_nmi_callback(nmi_callback_t callback)
++{
++	vmalloc_sync_all();
++	rcu_assign_pointer(nmi_callback, callback);
++}
++EXPORT_SYMBOL_GPL(set_nmi_callback);
++
++void unset_nmi_callback(void)
++{
++	nmi_callback = dummy_nmi_callback;
++}
++EXPORT_SYMBOL_GPL(unset_nmi_callback);
++
++#ifdef CONFIG_KPROBES
++fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
++{
++	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
++			== NOTIFY_STOP)
++		return;
++	/* This is an interrupt gate, because kprobes wants interrupts
++	disabled.  Normal trap handlers don't. */
++	restore_interrupts(regs);
++	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
++}
++#endif
++
++/*
++ * Our handling of the processor debug registers is non-trivial.
++ * We do not clear them on entry and exit from the kernel. Therefore
++ * it is possible to get a watchpoint trap here from inside the kernel.
++ * However, the code in ./ptrace.c has ensured that the user can
++ * only set watchpoints on userspace addresses. Therefore the in-kernel
++ * watchpoint trap can only occur in code which is reading/writing
++ * from user space. Such code must not hold kernel locks (since it
++ * can equally take a page fault), therefore it is safe to call
++ * force_sig_info even though that claims and releases locks.
++ * 
++ * Code in ./signal.c ensures that the debug control register
++ * is restored before we deliver any signal, and therefore that
++ * user code runs with the correct debug control register even though
++ * we clear it here.
++ *
++ * Being careful here means that we don't have to be as careful in a
++ * lot of more complicated places (task switching can be a bit lazy
++ * about restoring all the debug state, and ptrace doesn't have to
++ * find every occurrence of the TF bit that could be saved away even
++ * by user code)
++ */
++fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
++{
++	unsigned int condition;
++	struct task_struct *tsk = current;
++
++	get_debugreg(condition, 6);
++
++	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
++					SIGTRAP) == NOTIFY_STOP)
++		return;
++	/* It's safe to allow irq's after DR6 has been saved */
++	if (regs->eflags & X86_EFLAGS_IF)
++		local_irq_enable();
++
++	/* Mask out spurious debug traps due to lazy DR7 setting */
++	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
++		if (!tsk->thread.debugreg[7])
++			goto clear_dr7;
++	}
++
++	if (regs->eflags & VM_MASK)
++		goto debug_vm86;
++
++	/* Save debug status register where ptrace can see it */
++	tsk->thread.debugreg[6] = condition;
++
++	/*
++	 * Single-stepping through TF: make sure we ignore any events in
++	 * kernel space (but re-enable TF when returning to user mode).
++	 */
++	if (condition & DR_STEP) {
++		/*
++		 * We already checked v86 mode above, so we can
++		 * check for kernel mode by just checking the CPL
++		 * of CS.
++		 */
++		if (!user_mode(regs))
++			goto clear_TF_reenable;
++	}
++
++	/* Ok, finally something we can handle */
++	send_sigtrap(tsk, regs, error_code);
++
++	/* Disable additional traps. They'll be re-enabled when
++	 * the signal is delivered.
++	 */
++clear_dr7:
++	set_debugreg(0, 7);
++	return;
++
++debug_vm86:
++	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
++	return;
++
++clear_TF_reenable:
++	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
++	regs->eflags &= ~TF_MASK;
++	return;
++}
++
++/*
++ * Note that we play around with the 'TS' bit in an attempt to get
++ * the correct behaviour even in the presence of the asynchronous
++ * IRQ13 behaviour
++ */
++void math_error(void __user *eip)
++{
++	struct task_struct * task;
++	siginfo_t info;
++	unsigned short cwd, swd;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 16;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = eip;
++	/*
++	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
++	 * status.  0x3f is the exception bits in these regs, 0x200 is the
++	 * C1 reg you need in case of a stack fault, 0x040 is the stack
++	 * fault bit.  We should only be taking one exception at a time,
++	 * so if this combination doesn't produce any single exception,
++	 * then we have a bad program that isn't syncronizing its FPU usage
++	 * and it will suffer the consequences since we won't be able to
++	 * fully reproduce the context of the exception
++	 */
++	cwd = get_fpu_cwd(task);
++	swd = get_fpu_swd(task);
++	switch (swd & ~cwd & 0x3f) {
++		case 0x000: /* No unmasked exception */
++			return;
++		default:    /* Multiple exceptions */
++			break;
++		case 0x001: /* Invalid Op */
++			/*
++			 * swd & 0x240 == 0x040: Stack Underflow
++			 * swd & 0x240 == 0x240: Stack Overflow
++			 * User must clear the SF bit (0x40) if set
++			 */
++			info.si_code = FPE_FLTINV;
++			break;
++		case 0x002: /* Denormalize */
++		case 0x010: /* Underflow */
++			info.si_code = FPE_FLTUND;
++			break;
++		case 0x004: /* Zero Divide */
++			info.si_code = FPE_FLTDIV;
++			break;
++		case 0x008: /* Overflow */
++			info.si_code = FPE_FLTOVF;
++			break;
++		case 0x020: /* Precision */
++			info.si_code = FPE_FLTRES;
++			break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code)
++{
++	ignore_fpu_irq = 1;
++	math_error((void __user *)regs->eip);
++}
++
++static void simd_math_error(void __user *eip)
++{
++	struct task_struct * task;
++	siginfo_t info;
++	unsigned short mxcsr;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 19;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = eip;
++	/*
++	 * The SIMD FPU exceptions are handled a little differently, as there
++	 * is only a single status/control register.  Thus, to determine which
++	 * unmasked exception was caught we must mask the exception mask bits
++	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
++	 */
++	mxcsr = get_fpu_mxcsr(task);
++	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
++		case 0x000:
++		default:
++			break;
++		case 0x001: /* Invalid Op */
++			info.si_code = FPE_FLTINV;
++			break;
++		case 0x002: /* Denormalize */
++		case 0x010: /* Underflow */
++			info.si_code = FPE_FLTUND;
++			break;
++		case 0x004: /* Zero Divide */
++			info.si_code = FPE_FLTDIV;
++			break;
++		case 0x008: /* Overflow */
++			info.si_code = FPE_FLTOVF;
++			break;
++		case 0x020: /* Precision */
++			info.si_code = FPE_FLTRES;
++			break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
++					  long error_code)
++{
++	if (cpu_has_xmm) {
++		/* Handle SIMD FPU exceptions on PIII+ processors. */
++		ignore_fpu_irq = 1;
++		simd_math_error((void __user *)regs->eip);
++	} else {
++		/*
++		 * Handle strange cache flush from user space exception
++		 * in all other cases.  This is undocumented behaviour.
++		 */
++		if (regs->eflags & VM_MASK) {
++			handle_vm86_fault((struct kernel_vm86_regs *)regs,
++					  error_code);
++			return;
++		}
++		current->thread.trap_no = 19;
++		current->thread.error_code = error_code;
++		die_if_kernel("cache flush denied", regs, error_code);
++		force_sig(SIGSEGV, current);
++	}
++}
++
++#ifndef CONFIG_XEN
++fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
++					  long error_code)
++{
++#if 0
++	/* No need to warn about this any longer. */
++	printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
++#endif
++}
++
++fastcall void setup_x86_bogus_stack(unsigned char * stk)
++{
++	unsigned long *switch16_ptr, *switch32_ptr;
++	struct pt_regs *regs;
++	unsigned long stack_top, stack_bot;
++	unsigned short iret_frame16_off;
++	int cpu = smp_processor_id();
++	/* reserve the space on 32bit stack for the magic switch16 pointer */
++	memmove(stk, stk + 8, sizeof(struct pt_regs));
++	switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
++	regs = (struct pt_regs *)stk;
++	/* now the switch32 on 16bit stack */
++	stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
++	stack_top = stack_bot +	CPU_16BIT_STACK_SIZE;
++	switch32_ptr = (unsigned long *)(stack_top - 8);
++	iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
++	/* copy iret frame on 16bit stack */
++	memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
++	/* fill in the switch pointers */
++	switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
++	switch16_ptr[1] = __ESPFIX_SS;
++	switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
++		8 - CPU_16BIT_STACK_SIZE;
++	switch32_ptr[1] = __KERNEL_DS;
++}
++
++fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
++{
++	unsigned long *switch32_ptr;
++	unsigned char *stack16, *stack32;
++	unsigned long stack_top, stack_bot;
++	int len;
++	int cpu = smp_processor_id();
++	stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
++	stack_top = stack_bot +	CPU_16BIT_STACK_SIZE;
++	switch32_ptr = (unsigned long *)(stack_top - 8);
++	/* copy the data from 16bit stack to 32bit stack */
++	len = CPU_16BIT_STACK_SIZE - 8 - sp;
++	stack16 = (unsigned char *)(stack_bot + sp);
++	stack32 = (unsigned char *)
++		(switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
++	memcpy(stack32, stack16, len);
++	return stack32;
++}
++#endif
++
++/*
++ *  'math_state_restore()' saves the current math information in the
++ * old math state array, and gets the new ones from the current task
++ *
++ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
++ * Don't touch unless you *really* know how it works.
++ *
++ * Must be called with kernel preemption disabled (in this case,
++ * local interrupts are disabled at the call-site in entry.S).
++ */
++asmlinkage void math_state_restore(struct pt_regs regs)
++{
++	struct thread_info *thread = current_thread_info();
++	struct task_struct *tsk = thread->task;
++
++	/* NB. 'clts' is done for us by Xen during virtual trap. */
++	if (!tsk_used_math(tsk))
++		init_fpu(tsk);
++	restore_fpu(tsk);
++	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
++}
++
++#ifndef CONFIG_MATH_EMULATION
++
++asmlinkage void math_emulate(long arg)
++{
++	printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
++	printk(KERN_EMERG "killing %s.\n",current->comm);
++	force_sig(SIGFPE,current);
++	schedule();
++}
++
++#endif /* CONFIG_MATH_EMULATION */
++
++#ifdef CONFIG_X86_F00F_BUG
++void __init trap_init_f00f_bug(void)
++{
++	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
++
++	/*
++	 * Update the IDT descriptor and reload the IDT so that
++	 * it uses the read-only mapped virtual address.
++	 */
++	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
++	load_idt(&idt_descr);
++}
++#endif
++
++
++/*
++ * 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 __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			},
++	{  4, 3, __KERNEL_CS, (unsigned long)overflow			},
++	{  5, 0, __KERNEL_CS, (unsigned long)bounds			},
++	{  6, 0, __KERNEL_CS, (unsigned long)invalid_op			},
++	{  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available	},
++	{  9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
++	{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS		},
++	{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present	},
++	{ 12, 0, __KERNEL_CS, (unsigned long)stack_segment		},
++	{ 13, 0, __KERNEL_CS, (unsigned long)general_protection		},
++	{ 14, 0|4, __KERNEL_CS, (unsigned long)page_fault		},
++	{ 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment		},
++	{ 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error		},
++	{ 17, 0, __KERNEL_CS, (unsigned long)alignment_check		},
++#ifdef CONFIG_X86_MCE
++	{ 18, 0, __KERNEL_CS, (unsigned long)machine_check		},
++#endif
++	{ 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error	},
++	{ SYSCALL_VECTOR,  3, __KERNEL_CS, (unsigned long)system_call	},
++	{  0, 0,	   0, 0						}
++};
++
++void __init trap_init(void)
++{
++	int ret;
++
++	ret = HYPERVISOR_set_trap_table(trap_table);
++	if (ret)
++		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
++
++	if (cpu_has_fxsr) {
++		/*
++		 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
++		 * Generates a compile-time "error: zero width for bit-field" if
++		 * the alignment is wrong.
++		 */
++		struct fxsrAlignAssert {
++			int _:!(offsetof(struct task_struct,
++					thread.i387.fxsave) & 15);
++		};
++
++		printk(KERN_INFO "Enabling fast FPU save and restore... ");
++		set_in_cr4(X86_CR4_OSFXSR);
++		printk("done.\n");
++	}
++	if (cpu_has_xmm) {
++		printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
++				"support... ");
++		set_in_cr4(X86_CR4_OSXMMEXCPT);
++		printk("done.\n");
++	}
++
++	/*
++	 * Should be a barrier for any external CPU state.
++	 */
++	cpu_init();
++}
++
++void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
++{
++	const trap_info_t *t = trap_table;
++
++	for (t = trap_table; t->address; t++) {
++		trap_ctxt[t->vector].flags = t->flags;
++		trap_ctxt[t->vector].cs = t->cs;
++		trap_ctxt[t->vector].address = t->address;
++	}
++}
++
++static int __init kstack_setup(char *s)
++{
++	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
++	return 1;
++}
++__setup("kstack=", kstack_setup);
++
++#ifdef CONFIG_STACK_UNWIND
++static int __init call_trace_setup(char *s)
++{
++	if (strcmp(s, "old") == 0)
++		call_trace = -1;
++	else if (strcmp(s, "both") == 0)
++		call_trace = 0;
++	else if (strcmp(s, "newfallback") == 0)
++		call_trace = 1;
++	else if (strcmp(s, "new") == 2)
++		call_trace = 2;
++	return 1;
++}
++__setup("call_trace=", call_trace_setup);
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mach-xen/Makefile	2007-06-12 13:12:48.000000000 +0200
+@@ -0,0 +1,5 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y				:= setup.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2008-04-02 12:34:02.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>
++#include <linux/module.h>
++#include <asm/acpi.h>
++#include <asm/arch_hooks.h>
++#include <asm/e820.h>
++#include <asm/setup.h>
++#include <asm/fixmap.h>
++
++#include <xen/interface/callback.h>
++#include <xen/interface/memory.h>
++
++#ifdef CONFIG_HOTPLUG_CPU
++#define DEFAULT_SEND_IPI	(1)
++#else
++#define DEFAULT_SEND_IPI	(0)
++#endif
++
++int no_broadcast=DEFAULT_SEND_IPI;
++
++static __init int no_ipi_broadcast(char *str)
++{
++	get_option(&str, &no_broadcast);
++	printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
++											"IPI Broadcast");
++	return 1;
++}
++
++__setup("no_ipi_broadcast", no_ipi_broadcast);
++
++static int __init print_ipi_mode(void)
++{
++	printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
++											"Shortcut");
++	return 0;
++}
++
++late_initcall(print_ipi_mode);
++
++/**
++ * machine_specific_memory_setup - Hook for machine specific memory setup.
++ *
++ * Description:
++ *	This is included late in kernel/setup.c so that it can make
++ *	use of all of the static functions.
++ **/
++
++char * __init machine_specific_memory_setup(void)
++{
++	int rc;
++	struct xen_memory_map memmap;
++	/*
++	 * This is rather large for a stack variable but this early in
++	 * the boot process we know we have plenty slack space.
++	 */
++	struct e820entry map[E820MAX];
++
++	memmap.nr_entries = E820MAX;
++	set_xen_guest_handle(memmap.buffer, map);
++
++	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
++	if ( rc == -ENOSYS ) {
++		memmap.nr_entries = 1;
++		map[0].addr = 0ULL;
++		map[0].size = PFN_PHYS((unsigned long long)xen_start_info->nr_pages);
++		/* 8MB slack (to balance backend allocations). */
++		map[0].size += 8ULL << 20;
++		map[0].type = E820_RAM;
++		rc = 0;
++	}
++	BUG_ON(rc);
++
++	sanitize_e820_map(map, (char *)&memmap.nr_entries);
++
++	BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0);
++
++	return "Xen";
++}
++
++
++extern void hypervisor_callback(void);
++extern void failsafe_callback(void);
++extern void nmi(void);
++
++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 pre_setup_arch_hook(void)
++{
++	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 },
++	};
++	static struct callback_register __initdata failsafe = {
++		.type = CALLBACKTYPE_failsafe,
++		.address = { __KERNEL_CS, (unsigned long)failsafe_callback },
++	};
++	static struct callback_register __initdata nmi_cb = {
++		.type = CALLBACKTYPE_nmi,
++		.address = { __KERNEL_CS, (unsigned long)nmi },
++	};
++
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret == -ENOSYS)
++		ret = HYPERVISOR_set_callbacks(
++			event.address.cs, event.address.eip,
++			failsafe.address.cs, failsafe.address.eip);
++#endif
++	BUG_ON(ret);
++
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret == -ENOSYS) {
++		static struct xennmi_callback __initdata cb = {
++			.handler_address = (unsigned long)nmi
++		};
++
++		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
++	}
++#endif
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/lib/scrub.c	2008-02-08 12:30:51.000000000 +0100
+@@ -0,0 +1,21 @@
++#include <asm/cpufeature.h>
++#include <asm/page.h>
++#include <asm/processor.h>
++
++void scrub_pages(void *v, unsigned int count)
++{
++	if (likely(cpu_has_xmm2)) {
++		unsigned long n = count * (PAGE_SIZE / sizeof(long) / 4);
++
++		for (; n--; v += sizeof(long) * 4)
++			asm("movnti %1,(%0)\n\t"
++			    "movnti %1,%c2(%0)\n\t"
++			    "movnti %1,2*%c2(%0)\n\t"
++			    "movnti %1,3*%c2(%0)\n\t"
++			    : : "r" (v), "r" (0L), "i" (sizeof(long))
++			    : "memory");
++		asm volatile("sfence" : : : "memory");
++	} else
++		for (; count--; v += PAGE_SIZE)
++			clear_page(v);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2007-12-10 08:47:31.000000000 +0100
+@@ -0,0 +1,779 @@
++/*
++ *  linux/arch/i386/mm/fault.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ */
++
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/vt_kern.h>		/* For unblank_screen() */
++#include <linux/highmem.h>
++#include <linux/module.h>
++#include <linux/kprobes.h>
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/desc.h>
++#include <asm/kdebug.h>
++
++extern void die(const char *,struct pt_regs *,long);
++
++#ifdef CONFIG_KPROBES
++ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
++int register_page_fault_notifier(struct notifier_block *nb)
++{
++	vmalloc_sync_all();
++	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
++}
++
++int unregister_page_fault_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
++}
++
++static inline int notify_page_fault(enum die_val val, const char *str,
++			struct pt_regs *regs, long err, int trap, int sig)
++{
++	struct die_args args = {
++		.regs = regs,
++		.str = str,
++		.err = err,
++		.trapnr = trap,
++		.signr = sig
++	};
++	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
++}
++#else
++static inline int notify_page_fault(enum die_val val, const char *str,
++			struct pt_regs *regs, long err, int trap, int sig)
++{
++	return NOTIFY_DONE;
++}
++#endif
++
++
++/*
++ * Unlock any spinlocks which will prevent us from getting the
++ * message out 
++ */
++void bust_spinlocks(int yes)
++{
++	int loglevel_save = console_loglevel;
++
++	if (yes) {
++		oops_in_progress = 1;
++		return;
++	}
++#ifdef CONFIG_VT
++	unblank_screen();
++#endif
++	oops_in_progress = 0;
++	/*
++	 * OK, the message is on the console.  Now we call printk()
++	 * without oops_in_progress set so that printk will give klogd
++	 * a poke.  Hold onto your hats...
++	 */
++	console_loglevel = 15;		/* NMI oopser may have shut the console up */
++	printk(" ");
++	console_loglevel = loglevel_save;
++}
++
++/*
++ * Return EIP plus the CS segment base.  The segment limit is also
++ * adjusted, clamped to the kernel/user address space (whichever is
++ * appropriate), and returned in *eip_limit.
++ *
++ * The segment is checked, because it might have been changed by another
++ * task between the original faulting instruction and here.
++ *
++ * If CS is no longer a valid code segment, or if EIP is beyond the
++ * limit, or if it is a kernel address when CS is not a kernel segment,
++ * then the returned value will be greater than *eip_limit.
++ * 
++ * This is slow, but is very rarely executed.
++ */
++static inline unsigned long get_segment_eip(struct pt_regs *regs,
++					    unsigned long *eip_limit)
++{
++	unsigned long eip = regs->eip;
++	unsigned seg = regs->xcs & 0xffff;
++	u32 seg_ar, seg_limit, base, *desc;
++
++	/* Unlikely, but must come before segment checks. */
++	if (unlikely(regs->eflags & VM_MASK)) {
++		base = seg << 4;
++		*eip_limit = base + 0xffff;
++		return base + (eip & 0xffff);
++	}
++
++	/* The standard kernel/user address space limit. */
++	*eip_limit = (seg & 2) ? USER_DS.seg : KERNEL_DS.seg;
++	
++	/* By far the most common cases. */
++	if (likely(seg == __USER_CS || seg == GET_KERNEL_CS()))
++		return eip;
++
++	/* Check the segment exists, is within the current LDT/GDT size,
++	   that kernel/user (ring 0..3) has the appropriate privilege,
++	   that it's a code segment, and get the limit. */
++	__asm__ ("larl %3,%0; lsll %3,%1"
++		 : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg));
++	if ((~seg_ar & 0x9800) || eip > seg_limit) {
++		*eip_limit = 0;
++		return 1;	 /* So that returned eip > *eip_limit. */
++	}
++
++	/* Get the GDT/LDT descriptor base. 
++	   When you look for races in this code remember that
++	   LDT and other horrors are only used in user space. */
++	if (seg & (1<<2)) {
++		/* Must lock the LDT while reading it. */
++		down(&current->mm->context.sem);
++		desc = current->mm->context.ldt;
++		desc = (void *)desc + (seg & ~7);
++	} else {
++		/* Must disable preemption while reading the GDT. */
++ 		desc = (u32 *)get_cpu_gdt_table(get_cpu());
++		desc = (void *)desc + (seg & ~7);
++	}
++
++	/* Decode the code segment base from the descriptor */
++	base = get_desc_base((unsigned long *)desc);
++
++	if (seg & (1<<2)) { 
++		up(&current->mm->context.sem);
++	} else
++		put_cpu();
++
++	/* Adjust EIP and segment limit, and clamp at the kernel limit.
++	   It's legitimate for segments to wrap at 0xffffffff. */
++	seg_limit += base;
++	if (seg_limit < *eip_limit && seg_limit >= base)
++		*eip_limit = seg_limit;
++	return eip + base;
++}
++
++/* 
++ * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
++ * Check that here and ignore it.
++ */
++static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
++{ 
++	unsigned long limit;
++	unsigned long instr = get_segment_eip (regs, &limit);
++	int scan_more = 1;
++	int prefetch = 0; 
++	int i;
++
++	for (i = 0; scan_more && i < 15; i++) { 
++		unsigned char opcode;
++		unsigned char instr_hi;
++		unsigned char instr_lo;
++
++		if (instr > limit)
++			break;
++		if (__get_user(opcode, (unsigned char __user *) instr))
++			break; 
++
++		instr_hi = opcode & 0xf0; 
++		instr_lo = opcode & 0x0f; 
++		instr++;
++
++		switch (instr_hi) { 
++		case 0x20:
++		case 0x30:
++			/* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */
++			scan_more = ((instr_lo & 7) == 0x6);
++			break;
++			
++		case 0x60:
++			/* 0x64 thru 0x67 are valid prefixes in all modes. */
++			scan_more = (instr_lo & 0xC) == 0x4;
++			break;		
++		case 0xF0:
++			/* 0xF0, 0xF2, and 0xF3 are valid prefixes */
++			scan_more = !instr_lo || (instr_lo>>1) == 1;
++			break;			
++		case 0x00:
++			/* Prefetch instruction is 0x0F0D or 0x0F18 */
++			scan_more = 0;
++			if (instr > limit)
++				break;
++			if (__get_user(opcode, (unsigned char __user *) instr))
++				break;
++			prefetch = (instr_lo == 0xF) &&
++				(opcode == 0x0D || opcode == 0x18);
++			break;			
++		default:
++			scan_more = 0;
++			break;
++		} 
++	}
++	return prefetch;
++}
++
++static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
++			      unsigned long error_code)
++{
++	if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
++		     boot_cpu_data.x86 >= 6)) {
++		/* Catch an obscure case of prefetch inside an NX page. */
++		if (nx_enabled && (error_code & 16))
++			return 0;
++		return __is_prefetch(regs, addr);
++	}
++	return 0;
++} 
++
++static noinline void force_sig_info_fault(int si_signo, int si_code,
++	unsigned long address, struct task_struct *tsk)
++{
++	siginfo_t info;
++
++	info.si_signo = si_signo;
++	info.si_errno = 0;
++	info.si_code = si_code;
++	info.si_addr = (void __user *)address;
++	force_sig_info(si_signo, &info, tsk);
++}
++
++fastcall void do_invalid_op(struct pt_regs *, unsigned long);
++
++#ifdef CONFIG_X86_PAE
++static void dump_fault_path(unsigned long address)
++{
++	unsigned long *p, page;
++	unsigned long mfn; 
++
++	page = read_cr3();
++	p  = (unsigned long *)__va(page);
++	p += (address >> 30) * 2;
++	printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
++	if (p[0] & _PAGE_PRESENT) {
++		mfn  = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
++		page = mfn_to_pfn(mfn) << PAGE_SHIFT; 
++		p  = (unsigned long *)__va(page);
++		address &= 0x3fffffff;
++		p += (address >> 21) * 2;
++		printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n", 
++		       page, p[1], p[0]);
++		mfn  = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
++#ifdef CONFIG_HIGHPTE
++		if (mfn_to_pfn(mfn) >= highstart_pfn)
++			return;
++#endif
++		if (p[0] & _PAGE_PRESENT) {
++			page = mfn_to_pfn(mfn) << PAGE_SHIFT; 
++			p  = (unsigned long *) __va(page);
++			address &= 0x001fffff;
++			p += (address >> 12) * 2;
++			printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n",
++			       page, p[1], p[0]);
++		}
++	}
++}
++#else
++static void dump_fault_path(unsigned long address)
++{
++	unsigned long page;
++
++	page = read_cr3();
++	page = ((unsigned long *) __va(page))[address >> 22];
++	if (oops_may_print())
++		printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
++		       machine_to_phys(page));
++	/*
++	 * We must not directly access the pte in the highpte
++	 * case if the page table is located in highmem.
++	 * And lets rather not kmap-atomic the pte, just in case
++	 * it's allocated already.
++	 */
++#ifdef CONFIG_HIGHPTE
++	if ((page >> PAGE_SHIFT) >= highstart_pfn)
++		return;
++#endif
++	if ((page & 1) && oops_may_print()) {
++		page &= PAGE_MASK;
++		address &= 0x003ff000;
++		page = machine_to_phys(page);
++		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
++		printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
++		       machine_to_phys(page));
++	}
++}
++#endif
++
++static int spurious_fault(struct pt_regs *regs,
++			  unsigned long address,
++			  unsigned long error_code)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	/* Reserved-bit violation or user access to kernel space? */
++	if (error_code & 0x0c)
++		return 0;
++
++	pgd = init_mm.pgd + pgd_index(address);
++	if (!pgd_present(*pgd))
++		return 0;
++
++	pud = pud_offset(pgd, address);
++	if (!pud_present(*pud))
++		return 0;
++
++	pmd = pmd_offset(pud, address);
++	if (!pmd_present(*pmd))
++		return 0;
++
++	pte = pte_offset_kernel(pmd, address);
++	if (!pte_present(*pte))
++		return 0;
++	if ((error_code & 0x02) && !pte_write(*pte))
++		return 0;
++#ifdef CONFIG_X86_PAE
++	if ((error_code & 0x10) && (__pte_val(*pte) & _PAGE_NX))
++		return 0;
++#endif
++
++	return 1;
++}
++
++static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
++{
++	unsigned index = pgd_index(address);
++	pgd_t *pgd_k;
++	pud_t *pud, *pud_k;
++	pmd_t *pmd, *pmd_k;
++
++	pgd += index;
++	pgd_k = init_mm.pgd + index;
++
++	if (!pgd_present(*pgd_k))
++		return NULL;
++
++	/*
++	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
++	 * and redundant with the set_pmd() on non-PAE. As would
++	 * set_pud.
++	 */
++
++	pud = pud_offset(pgd, address);
++	pud_k = pud_offset(pgd_k, address);
++	if (!pud_present(*pud_k))
++		return NULL;
++
++	pmd = pmd_offset(pud, address);
++	pmd_k = pmd_offset(pud_k, address);
++	if (!pmd_present(*pmd_k))
++		return NULL;
++	if (!pmd_present(*pmd))
++#if CONFIG_XEN_COMPAT > 0x030002
++		set_pmd(pmd, *pmd_k);
++#else
++		/*
++		 * When running on older Xen we must launder *pmd_k through
++		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
++		 */
++		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
++#endif
++	else
++		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
++	return pmd_k;
++}
++
++/*
++ * Handle a fault on the vmalloc or module mapping area
++ *
++ * This assumes no large pages in there.
++ */
++static inline int vmalloc_fault(unsigned long address)
++{
++	unsigned long pgd_paddr;
++	pmd_t *pmd_k;
++	pte_t *pte_k;
++	/*
++	 * Synchronize this task's top level page-table
++	 * with the 'reference' page table.
++	 *
++	 * Do _not_ use "current" here. We might be inside
++	 * an interrupt in the middle of a task switch..
++	 */
++	pgd_paddr = read_cr3();
++	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
++	if (!pmd_k)
++		return -1;
++	pte_k = pte_offset_kernel(pmd_k, address);
++	if (!pte_present(*pte_k))
++		return -1;
++	return 0;
++}
++
++/*
++ * This routine handles page faults.  It determines the address,
++ * and the problem, and then passes it off to one of the appropriate
++ * routines.
++ *
++ * error_code:
++ *	bit 0 == 0 means no page found, 1 means protection fault
++ *	bit 1 == 0 means read, 1 means write
++ *	bit 2 == 0 means kernel, 1 means user-mode
++ *	bit 3 == 1 means use of reserved bit detected
++ *	bit 4 == 1 means fault was an instruction fetch
++ */
++fastcall void __kprobes do_page_fault(struct pt_regs *regs,
++				      unsigned long error_code)
++{
++	struct task_struct *tsk;
++	struct mm_struct *mm;
++	struct vm_area_struct * vma;
++	unsigned long address;
++	int write, si_code;
++
++	/* get the address */
++        address = read_cr2();
++
++	/* Set the "privileged fault" bit to something sane. */
++	error_code &= ~4;
++	error_code |= (regs->xcs & 2) << 1;
++	if (regs->eflags & X86_EFLAGS_VM)
++		error_code |= 4;
++
++	tsk = current;
++
++	si_code = SEGV_MAPERR;
++
++	/*
++	 * We fault-in kernel-space virtual memory on-demand. The
++	 * 'reference' page table is init_mm.pgd.
++	 *
++	 * NOTE! We MUST NOT take any locks for this case. We may
++	 * be in an interrupt or a critical region, and should
++	 * only copy the information from the master page table,
++	 * nothing more.
++	 *
++	 * This verifies that the fault happens in kernel space
++	 * (error_code & 4) == 0, and that the fault was not a
++	 * protection error (error_code & 9) == 0.
++	 */
++	if (unlikely(address >= TASK_SIZE)) {
++#ifdef CONFIG_XEN
++		/* Faults in hypervisor area can never be patched up. */
++		if (address >= hypervisor_virt_start)
++			goto bad_area_nosemaphore;
++#endif
++		if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
++			return;
++		/* Can take a spurious fault if mapping changes R/O -> R/W. */
++		if (spurious_fault(regs, address, error_code))
++			return;
++		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
++						SIGSEGV) == NOTIFY_STOP)
++			return;
++		/* 
++		 * Don't take the mm semaphore here. If we fixup a prefetch
++		 * fault we could otherwise deadlock.
++		 */
++		goto bad_area_nosemaphore;
++	}
++
++	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
++					SIGSEGV) == NOTIFY_STOP)
++		return;
++
++	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
++	   fault has been handled. */
++	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
++		local_irq_enable();
++
++	mm = tsk->mm;
++
++	/*
++	 * If we're in an interrupt, have no user context or are running in an
++	 * atomic region then we must not take the fault..
++	 */
++	if (in_atomic() || !mm)
++		goto bad_area_nosemaphore;
++
++	/* When running in the kernel we expect faults to occur only to
++	 * addresses in user space.  All other faults represent errors in the
++	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
++	 * erroneous fault occurring in a code path which already holds mmap_sem
++	 * we will deadlock attempting to validate the fault against the
++	 * address space.  Luckily the kernel only validly references user
++	 * space from well defined areas of code, which are listed in the
++	 * exceptions table.
++	 *
++	 * As the vast majority of faults will be valid we will only perform
++	 * the source reference check when there is a possibilty of a deadlock.
++	 * Attempt to lock the address space, if we cannot we then validate the
++	 * source.  If this is invalid we can skip the address space check,
++	 * thus avoiding the deadlock.
++	 */
++	if (!down_read_trylock(&mm->mmap_sem)) {
++		if ((error_code & 4) == 0 &&
++		    !search_exception_tables(regs->eip))
++			goto bad_area_nosemaphore;
++		down_read(&mm->mmap_sem);
++	}
++
++	vma = find_vma(mm, address);
++	if (!vma)
++		goto bad_area;
++	if (vma->vm_start <= address)
++		goto good_area;
++	if (!(vma->vm_flags & VM_GROWSDOWN))
++		goto bad_area;
++	if (error_code & 4) {
++		/*
++		 * Accessing the stack below %esp is always a bug.
++		 * The large cushion allows instructions like enter
++		 * and pusha to work.  ("enter $65535,$31" pushes
++		 * 32 pointers and then decrements %esp by 65535.)
++		 */
++		if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp)
++			goto bad_area;
++	}
++	if (expand_stack(vma, address))
++		goto bad_area;
++/*
++ * Ok, we have a good vm_area for this memory access, so
++ * we can handle it..
++ */
++good_area:
++	si_code = SEGV_ACCERR;
++	write = 0;
++	switch (error_code & 3) {
++		default:	/* 3: write, present */
++#ifdef TEST_VERIFY_AREA
++			if (regs->cs == GET_KERNEL_CS())
++				printk("WP fault at %08lx\n", regs->eip);
++#endif
++			/* fall through */
++		case 2:		/* write, not present */
++			if (!(vma->vm_flags & VM_WRITE))
++				goto bad_area;
++			write++;
++			break;
++		case 1:		/* read, present */
++			goto bad_area;
++		case 0:		/* read, not present */
++			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
++				goto bad_area;
++	}
++
++ survive:
++	/*
++	 * If for any reason at all we couldn't handle the fault,
++	 * make sure we exit gracefully rather than endlessly redo
++	 * the fault.
++	 */
++	switch (handle_mm_fault(mm, vma, address, write)) {
++		case VM_FAULT_MINOR:
++			tsk->min_flt++;
++			break;
++		case VM_FAULT_MAJOR:
++			tsk->maj_flt++;
++			break;
++		case VM_FAULT_SIGBUS:
++			goto do_sigbus;
++		case VM_FAULT_OOM:
++			goto out_of_memory;
++		default:
++			BUG();
++	}
++
++	/*
++	 * Did it hit the DOS screen memory VA from vm86 mode?
++	 */
++	if (regs->eflags & VM_MASK) {
++		unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
++		if (bit < 32)
++			tsk->thread.screen_bitmap |= 1 << bit;
++	}
++	up_read(&mm->mmap_sem);
++	return;
++
++/*
++ * Something tried to access memory that isn't in our memory map..
++ * Fix it, but check if it's kernel or user first..
++ */
++bad_area:
++	up_read(&mm->mmap_sem);
++
++bad_area_nosemaphore:
++	/* User mode accesses just cause a SIGSEGV */
++	if (error_code & 4) {
++		/* 
++		 * Valid to do another page fault here because this one came 
++		 * from user space.
++		 */
++		if (is_prefetch(regs, address, error_code))
++			return;
++
++		tsk->thread.cr2 = address;
++		/* Kernel addresses are always protection faults */
++		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
++		tsk->thread.trap_no = 14;
++		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
++		return;
++	}
++
++#ifdef CONFIG_X86_F00F_BUG
++	/*
++	 * Pentium F0 0F C7 C8 bug workaround.
++	 */
++	if (boot_cpu_data.f00f_bug) {
++		unsigned long nr;
++		
++		nr = (address - idt_descr.address) >> 3;
++
++		if (nr == 6) {
++			do_invalid_op(regs, 0);
++			return;
++		}
++	}
++#endif
++
++no_context:
++	/* Are we prepared to handle this kernel fault?  */
++	if (fixup_exception(regs))
++		return;
++
++	/* 
++	 * Valid to do another page fault here, because if this fault
++	 * had been triggered by is_prefetch fixup_exception would have 
++	 * handled it.
++	 */
++ 	if (is_prefetch(regs, address, error_code))
++ 		return;
++
++/*
++ * Oops. The kernel tried to access some bad page. We'll have to
++ * terminate things with extreme prejudice.
++ */
++
++	bust_spinlocks(1);
++
++	if (oops_may_print()) {
++	#ifdef CONFIG_X86_PAE
++		if (error_code & 16) {
++			pte_t *pte = lookup_address(address);
++
++			if (pte && pte_present(*pte) && !pte_exec_kernel(*pte))
++				printk(KERN_CRIT "kernel tried to execute "
++					"NX-protected page - exploit attempt? "
++					"(uid: %d)\n", current->uid);
++		}
++	#endif
++		if (address < PAGE_SIZE)
++			printk(KERN_ALERT "BUG: unable to handle kernel NULL "
++					"pointer dereference");
++		else
++			printk(KERN_ALERT "BUG: unable to handle kernel paging"
++					" request");
++		printk(" at virtual address %08lx\n",address);
++		printk(KERN_ALERT " printing eip:\n");
++		printk("%08lx\n", regs->eip);
++	}
++	dump_fault_path(address);
++	tsk->thread.cr2 = address;
++	tsk->thread.trap_no = 14;
++	tsk->thread.error_code = error_code;
++	die("Oops", regs, error_code);
++	bust_spinlocks(0);
++	do_exit(SIGKILL);
++
++/*
++ * We ran out of memory, or some other thing happened to us that made
++ * us unable to handle the page fault gracefully.
++ */
++out_of_memory:
++	up_read(&mm->mmap_sem);
++	if (tsk->pid == 1) {
++		yield();
++		down_read(&mm->mmap_sem);
++		goto survive;
++	}
++	printk("VM: killing process %s\n", tsk->comm);
++	if (error_code & 4)
++		do_exit(SIGKILL);
++	goto no_context;
++
++do_sigbus:
++	up_read(&mm->mmap_sem);
++
++	/* Kernel mode? Handle exceptions or die */
++	if (!(error_code & 4))
++		goto no_context;
++
++	/* User space => ok to do another page fault */
++	if (is_prefetch(regs, address, error_code))
++		return;
++
++	tsk->thread.cr2 = address;
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 14;
++	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
++}
++
++#if !HAVE_SHARED_KERNEL_PMD
++void vmalloc_sync_all(void)
++{
++	/*
++	 * Note that races in the updates of insync and start aren't
++	 * problematic: insync can only get set bits added, and updates to
++	 * start are only improving performance (without affecting correctness
++	 * if undone).
++	 * XEN: To work on PAE, we need to iterate over PMDs rather than PGDs.
++	 *      This change works just fine with 2-level paging too.
++	 */
++#define sync_index(a) ((a) >> PMD_SHIFT)
++	static DECLARE_BITMAP(insync, PTRS_PER_PGD*PTRS_PER_PMD);
++	static unsigned long start = TASK_SIZE;
++	unsigned long address;
++
++	BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK);
++	for (address = start;
++	     address >= TASK_SIZE && address < hypervisor_virt_start;
++	     address += 1UL << PMD_SHIFT) {
++		if (!test_bit(sync_index(address), insync)) {
++			unsigned long flags;
++			struct page *page;
++
++			spin_lock_irqsave(&pgd_lock, flags);
++			/* XEN: failure path assumes non-empty pgd_list. */
++			if (unlikely(!pgd_list)) {
++				spin_unlock_irqrestore(&pgd_lock, flags);
++				return;
++			}
++			for (page = pgd_list; page; page =
++					(struct page *)page->index)
++				if (!vmalloc_sync_one(page_address(page),
++								address)) {
++					BUG_ON(page != pgd_list);
++					break;
++				}
++			spin_unlock_irqrestore(&pgd_lock, flags);
++			if (!page)
++				set_bit(sync_index(address), insync);
++		}
++		if (address == start && test_bit(sync_index(address), insync))
++			start = address + (1UL << PMD_SHIFT);
++	}
++}
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,183 @@
++#include <linux/highmem.h>
++#include <linux/module.h>
++
++void *kmap(struct page *page)
++{
++	might_sleep();
++	if (!PageHighMem(page))
++		return page_address(page);
++	return kmap_high(page);
++}
++
++void kunmap(struct page *page)
++{
++	if (in_interrupt())
++		BUG();
++	if (!PageHighMem(page))
++		return;
++	kunmap_high(page);
++}
++
++/*
++ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
++ * no global lock is needed and because the kmap code must perform a global TLB
++ * invalidation when the kmap pool wraps.
++ *
++ * However when holding an atomic kmap is is not legal to sleep, so atomic
++ * kmaps are appropriate for short, tight code paths only.
++ */
++static void *__kmap_atomic(struct page *page, enum km_type type, pgprot_t prot)
++{
++	enum fixed_addresses idx;
++	unsigned long vaddr;
++
++	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
++	inc_preempt_count();
++	if (!PageHighMem(page))
++		return page_address(page);
++
++	idx = type + KM_TYPE_NR*smp_processor_id();
++	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++#ifdef CONFIG_DEBUG_HIGHMEM
++	if (!pte_none(*(kmap_pte-idx)))
++		BUG();
++#endif
++	set_pte_at_sync(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
++
++	return (void*) vaddr;
++}
++
++void *kmap_atomic(struct page *page, enum km_type type)
++{
++	return __kmap_atomic(page, type, kmap_prot);
++}
++
++/* Same as kmap_atomic but with PAGE_KERNEL_RO page protection. */
++void *kmap_atomic_pte(struct page *page, enum km_type type)
++{
++	return __kmap_atomic(page, type,
++	                     test_bit(PG_pinned, &page->flags)
++	                     ? PAGE_KERNEL_RO : kmap_prot);
++}
++
++void kunmap_atomic(void *kvaddr, enum km_type type)
++{
++#if defined(CONFIG_DEBUG_HIGHMEM) || defined(CONFIG_XEN)
++	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
++	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
++
++	if (vaddr < FIXADDR_START) { // FIXME
++		dec_preempt_count();
++		preempt_check_resched();
++		return;
++	}
++#endif
++
++#if defined(CONFIG_DEBUG_HIGHMEM)
++	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
++		BUG();
++
++	/*
++	 * force other mappings to Oops if they'll try to access
++	 * this pte without first remap it
++	 */
++	pte_clear(&init_mm, vaddr, kmap_pte-idx);
++	__flush_tlb_one(vaddr);
++#elif defined(CONFIG_XEN)
++	/*
++	 * We must ensure there are no dangling pagetable references when
++	 * returning memory to Xen (decrease_reservation).
++	 * XXX TODO: We could make this faster by only zapping when
++	 * kmap_flush_unused is called but that is trickier and more invasive.
++	 */
++	pte_clear(&init_mm, vaddr, kmap_pte-idx);
++#endif
++
++	dec_preempt_count();
++	preempt_check_resched();
++}
++
++/* This is the same as kmap_atomic() but can map memory that doesn't
++ * have a struct page associated with it.
++ */
++void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
++{
++	enum fixed_addresses idx;
++	unsigned long vaddr;
++
++	inc_preempt_count();
++
++	idx = type + KM_TYPE_NR*smp_processor_id();
++	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
++	__flush_tlb_one(vaddr);
++
++	return (void*) vaddr;
++}
++
++struct page *kmap_atomic_to_page(void *ptr)
++{
++	unsigned long idx, vaddr = (unsigned long)ptr;
++	pte_t *pte;
++
++	if (vaddr < FIXADDR_START)
++		return virt_to_page(ptr);
++
++	idx = virt_to_fix(vaddr);
++	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
++	return pte_page(*pte);
++}
++
++void clear_highpage(struct page *page)
++{
++	void *kaddr;
++
++	if (likely(xen_feature(XENFEAT_highmem_assist))
++	    && PageHighMem(page)) {
++		struct mmuext_op meo;
++
++		meo.cmd = MMUEXT_CLEAR_PAGE;
++		meo.arg1.mfn = pfn_to_mfn(page_to_pfn(page));
++		if (HYPERVISOR_mmuext_op(&meo, 1, NULL, DOMID_SELF) == 0)
++			return;
++	}
++
++	kaddr = kmap_atomic(page, KM_USER0);
++	clear_page(kaddr);
++	kunmap_atomic(kaddr, KM_USER0);
++}
++
++void copy_highpage(struct page *to, struct page *from)
++{
++	void *vfrom, *vto;
++
++	if (likely(xen_feature(XENFEAT_highmem_assist))
++	    && (PageHighMem(from) || PageHighMem(to))) {
++		unsigned long from_pfn = page_to_pfn(from);
++		unsigned long to_pfn = page_to_pfn(to);
++		struct mmuext_op meo;
++
++		meo.cmd = MMUEXT_COPY_PAGE;
++		meo.arg1.mfn = pfn_to_mfn(to_pfn);
++		meo.arg2.src_mfn = pfn_to_mfn(from_pfn);
++		if (mfn_to_pfn(meo.arg2.src_mfn) == from_pfn
++		    && mfn_to_pfn(meo.arg1.mfn) == to_pfn
++		    && HYPERVISOR_mmuext_op(&meo, 1, NULL, DOMID_SELF) == 0)
++			return;
++	}
++
++	vfrom = kmap_atomic(from, KM_USER0);
++	vto = kmap_atomic(to, KM_USER1);
++	copy_page(vto, vfrom);
++	kunmap_atomic(vfrom, KM_USER0);
++	kunmap_atomic(vto, KM_USER1);
++}
++
++EXPORT_SYMBOL(kmap);
++EXPORT_SYMBOL(kunmap);
++EXPORT_SYMBOL(kmap_atomic);
++EXPORT_SYMBOL(kmap_atomic_pte);
++EXPORT_SYMBOL(kunmap_atomic);
++EXPORT_SYMBOL(kmap_atomic_to_page);
++EXPORT_SYMBOL(clear_highpage);
++EXPORT_SYMBOL(copy_highpage);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,579 @@
++/******************************************************************************
++ * mm/hypervisor.c
++ * 
++ * Update page tables via the hypervisor.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser
++ * 
++ * 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/sched.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/hypervisor.h>
++#include <xen/balloon.h>
++#include <xen/features.h>
++#include <xen/interface/memory.h>
++#include <linux/module.h>
++#include <linux/percpu.h>
++#include <asm/tlbflush.h>
++#include <linux/highmem.h>
++
++void xen_l1_entry_update(pte_t *ptr, pte_t val)
++{
++	mmu_update_t u;
++	u.ptr = ptep_to_machine(ptr);
++	u.val = __pte_val(val);
++	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL_GPL(xen_l1_entry_update);
++
++void xen_l2_entry_update(pmd_t *ptr, pmd_t val)
++{
++	mmu_update_t u;
++	u.ptr = virt_to_machine(ptr);
++	u.val = __pmd_val(val);
++	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++}
++
++#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
++void xen_l3_entry_update(pud_t *ptr, pud_t val)
++{
++	mmu_update_t u;
++	u.ptr = virt_to_machine(ptr);
++	u.val = __pud_val(val);
++	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++}
++#endif
++
++#ifdef CONFIG_X86_64
++void xen_l4_entry_update(pgd_t *ptr, pgd_t val)
++{
++	mmu_update_t u;
++	u.ptr = virt_to_machine(ptr);
++	u.val = __pgd_val(val);
++	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
++}
++#endif /* CONFIG_X86_64 */
++
++void xen_pt_switch(unsigned long ptr)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_NEW_BASEPTR;
++	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++
++void xen_new_user_pt(unsigned long ptr)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_NEW_USER_BASEPTR;
++	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++
++void xen_tlb_flush(void)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_TLB_FLUSH_LOCAL;
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL(xen_tlb_flush);
++
++void xen_invlpg(unsigned long ptr)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_INVLPG_LOCAL;
++	op.arg1.linear_addr = ptr & PAGE_MASK;
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL(xen_invlpg);
++
++#ifdef CONFIG_SMP
++
++void xen_tlb_flush_all(void)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_TLB_FLUSH_ALL;
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL_GPL(xen_tlb_flush_all);
++
++void xen_tlb_flush_mask(cpumask_t *mask)
++{
++	struct mmuext_op op;
++	if ( cpus_empty(*mask) )
++		return;
++	op.cmd = MMUEXT_TLB_FLUSH_MULTI;
++	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL_GPL(xen_tlb_flush_mask);
++
++void xen_invlpg_all(unsigned long ptr)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_INVLPG_ALL;
++	op.arg1.linear_addr = ptr & PAGE_MASK;
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL_GPL(xen_invlpg_all);
++
++void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr)
++{
++	struct mmuext_op op;
++	if ( cpus_empty(*mask) )
++		return;
++	op.cmd = MMUEXT_INVLPG_MULTI;
++	op.arg1.linear_addr = ptr & PAGE_MASK;
++	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++EXPORT_SYMBOL_GPL(xen_invlpg_mask);
++
++#endif /* CONFIG_SMP */
++
++void xen_pgd_pin(unsigned long ptr)
++{
++	struct mmuext_op op;
++#ifdef CONFIG_X86_64
++	op.cmd = MMUEXT_PIN_L4_TABLE;
++#elif defined(CONFIG_X86_PAE)
++	op.cmd = MMUEXT_PIN_L3_TABLE;
++#else
++	op.cmd = MMUEXT_PIN_L2_TABLE;
++#endif
++	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++
++void xen_pgd_unpin(unsigned long ptr)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_UNPIN_TABLE;
++	op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT);
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++
++void xen_set_ldt(const void *ptr, unsigned int ents)
++{
++	struct mmuext_op op;
++	op.cmd = MMUEXT_SET_LDT;
++	op.arg1.linear_addr = (unsigned long)ptr;
++	op.arg2.nr_ents     = ents;
++	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
++}
++
++/* Protected by balloon_lock. */
++#define MAX_CONTIG_ORDER 9 /* 2MB */
++static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
++static unsigned long limited_frames[1<<MAX_CONTIG_ORDER];
++static multicall_entry_t cr_mcl[1<<MAX_CONTIG_ORDER];
++
++/* Ensure multi-page extents are contiguous in machine memory. */
++int xen_create_contiguous_region(
++	unsigned long vstart, unsigned int order, unsigned int address_bits)
++{
++	unsigned long *in_frames = discontig_frames, out_frame;
++	unsigned long  frame, flags;
++	unsigned int   i;
++	int            rc, success;
++	struct xen_memory_exchange exchange = {
++		.in = {
++			.nr_extents   = 1UL << order,
++			.extent_order = 0,
++			.domid        = DOMID_SELF
++		},
++		.out = {
++			.nr_extents   = 1,
++			.extent_order = order,
++			.address_bits = address_bits,
++			.domid        = DOMID_SELF
++		}
++	};
++
++	/*
++	 * Currently an auto-translated guest will not perform I/O, nor will
++	 * it require PAE page directories below 4GB. Therefore any calls to
++	 * this function are redundant and can be ignored.
++	 */
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 0;
++
++	if (unlikely(order > MAX_CONTIG_ORDER))
++		return -ENOMEM;
++
++	set_xen_guest_handle(exchange.in.extent_start, in_frames);
++	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
++
++	scrub_pages((void *)vstart, 1 << order);
++
++	balloon_lock(flags);
++
++	/* 1. Zap current PTEs, remembering MFNs. */
++	for (i = 0; i < (1U<<order); i++) {
++		in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
++		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
++					__pte_ma(0), 0);
++		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
++			INVALID_P2M_ENTRY);
++	}
++	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
++		BUG();
++
++	/* 2. Get a new contiguous memory extent. */
++	out_frame = __pa(vstart) >> PAGE_SHIFT;
++	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
++	success = (exchange.nr_exchanged == (1UL << order));
++	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
++	BUG_ON(success && (rc != 0));
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		/* Compatibility when XENMEM_exchange is unsupported. */
++		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					 &exchange.in) != (1UL << order))
++			BUG();
++		success = (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++						&exchange.out) == 1);
++		if (!success) {
++			/* Couldn't get special memory: fall back to normal. */
++			for (i = 0; i < (1U<<order); i++)
++				in_frames[i] = (__pa(vstart)>>PAGE_SHIFT) + i;
++			if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++						 &exchange.in) != (1UL<<order))
++				BUG();
++		}
++	}
++#endif
++
++	/* 3. Map the new extent in place of old pages. */
++	for (i = 0; i < (1U<<order); i++) {
++		frame = success ? (out_frame + i) : in_frames[i];
++		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
++					pfn_pte_ma(frame, PAGE_KERNEL), 0);
++		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
++	}
++
++	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
++						   ? UVMF_TLB_FLUSH|UVMF_ALL
++						   : UVMF_INVLPG|UVMF_ALL;
++	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
++		BUG();
++
++	balloon_unlock(flags);
++
++	return success ? 0 : -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(xen_create_contiguous_region);
++
++void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
++{
++	unsigned long *out_frames = discontig_frames, in_frame;
++	unsigned long  frame, flags;
++	unsigned int   i;
++	int            rc, success;
++	struct xen_memory_exchange exchange = {
++		.in = {
++			.nr_extents   = 1,
++			.extent_order = order,
++			.domid        = DOMID_SELF
++		},
++		.out = {
++			.nr_extents   = 1UL << order,
++			.extent_order = 0,
++			.domid        = DOMID_SELF
++		}
++	};
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return;
++
++	if (unlikely(order > MAX_CONTIG_ORDER))
++		return;
++
++	set_xen_guest_handle(exchange.in.extent_start, &in_frame);
++	set_xen_guest_handle(exchange.out.extent_start, out_frames);
++
++	scrub_pages((void *)vstart, 1 << order);
++
++	balloon_lock(flags);
++
++	/* 1. Find start MFN of contiguous extent. */
++	in_frame = pfn_to_mfn(__pa(vstart) >> PAGE_SHIFT);
++
++	/* 2. Zap current PTEs. */
++	for (i = 0; i < (1U<<order); i++) {
++		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
++					__pte_ma(0), 0);
++		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
++			INVALID_P2M_ENTRY);
++		out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
++	}
++	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
++		BUG();
++
++	/* 3. Do the exchange for non-contiguous MFNs. */
++	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
++	success = (exchange.nr_exchanged == 1);
++	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
++	BUG_ON(success && (rc != 0));
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		/* Compatibility when XENMEM_exchange is unsupported. */
++		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					 &exchange.in) != 1)
++			BUG();
++		if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++					 &exchange.out) != (1UL << order))
++			BUG();
++		success = 1;
++	}
++#endif
++
++	/* 4. Map new pages in place of old pages. */
++	for (i = 0; i < (1U<<order); i++) {
++		frame = success ? out_frames[i] : (in_frame + i);
++		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
++					pfn_pte_ma(frame, PAGE_KERNEL), 0);
++		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
++	}
++
++	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
++						   ? UVMF_TLB_FLUSH|UVMF_ALL
++						   : UVMF_INVLPG|UVMF_ALL;
++	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
++		BUG();
++
++	balloon_unlock(flags);
++}
++EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
++
++static void undo_limit_pages(struct page *pages, unsigned int order)
++{
++	BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++	BUG_ON(order > MAX_CONTIG_ORDER);
++	xen_limit_pages_to_max_mfn(pages, order, 0);
++	ClearPageForeign(pages);
++	__free_pages(pages, order);
++}
++
++int xen_limit_pages_to_max_mfn(
++	struct page *pages, unsigned int order, unsigned int address_bits)
++{
++	unsigned long flags, frame;
++	unsigned long *in_frames = discontig_frames, *out_frames = limited_frames;
++	struct page *page;
++	unsigned int i, n, nr_mcl;
++	int rc, success;
++	DECLARE_BITMAP(limit_map, 1 << MAX_CONTIG_ORDER);
++
++	struct xen_memory_exchange exchange = {
++		.in = {
++			.extent_order = 0,
++			.domid        = DOMID_SELF
++		},
++		.out = {
++			.extent_order = 0,
++			.address_bits = address_bits,
++			.domid        = DOMID_SELF
++		}
++	};
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 0;
++
++	if (unlikely(order > MAX_CONTIG_ORDER))
++		return -ENOMEM;
++
++	if (address_bits) {
++		if (address_bits < PAGE_SHIFT)
++			return -EINVAL;
++		bitmap_zero(limit_map, 1U << order);
++	} else if (order) {
++		BUILD_BUG_ON(sizeof(pages->index) != sizeof(*limit_map));
++		for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
++			limit_map[i] = pages[i + 1].index;
++	} else
++		__set_bit(0, limit_map);
++
++	set_xen_guest_handle(exchange.in.extent_start, in_frames);
++	set_xen_guest_handle(exchange.out.extent_start, out_frames);
++
++	/* 0. Scrub the pages. */
++	for (i = 0, n = 0; i < 1U<<order ; i++) {
++		page = &pages[i];
++		if (address_bits) {
++			if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits - PAGE_SHIFT)))
++				continue;
++			__set_bit(i, limit_map);
++		}
++
++		if (!PageHighMem(page))
++			scrub_pages(page_address(page), 1);
++#ifdef CONFIG_XEN_SCRUB_PAGES
++		else {
++			scrub_pages(kmap(page), 1);
++			kunmap(page);
++			++n;
++		}
++#endif
++	}
++	if (bitmap_empty(limit_map, 1U << order))
++		return 0;
++
++	if (n)
++		kmap_flush_unused();
++
++	balloon_lock(flags);
++
++	/* 1. Zap current PTEs (if any), remembering MFNs. */
++	for (i = 0, n = 0, nr_mcl = 0; i < (1U<<order); i++) {
++		if(!test_bit(i, limit_map))
++			continue;
++		page = &pages[i];
++
++		out_frames[n] = page_to_pfn(page);
++		in_frames[n] = pfn_to_mfn(out_frames[n]);
++
++		if (!PageHighMem(page))
++			MULTI_update_va_mapping(cr_mcl + nr_mcl++,
++						(unsigned long)page_address(page),
++						__pte_ma(0), 0);
++
++		set_phys_to_machine(out_frames[n], INVALID_P2M_ENTRY);
++		++n;
++	}
++	if (nr_mcl && HYPERVISOR_multicall_check(cr_mcl, nr_mcl, NULL))
++		BUG();
++
++	/* 2. Get new memory below the required limit. */
++	exchange.in.nr_extents = n;
++	exchange.out.nr_extents = n;
++	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
++	success = (exchange.nr_exchanged == n);
++	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
++	BUG_ON(success && (rc != 0));
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		/* Compatibility when XENMEM_exchange is unsupported. */
++		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++					 &exchange.in) != n)
++			BUG();
++		if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
++					 &exchange.out) != n)
++			BUG();
++		success = 1;
++	}
++#endif
++
++	/* 3. Map the new pages in place of old pages. */
++	for (i = 0, n = 0, nr_mcl = 0; i < (1U<<order); i++) {
++		if(!test_bit(i, limit_map))
++			continue;
++		page = &pages[i];
++
++		frame = success ? out_frames[n] : in_frames[n];
++
++		if (!PageHighMem(page))
++			MULTI_update_va_mapping(cr_mcl + nr_mcl++,
++						(unsigned long)page_address(page),
++						pfn_pte_ma(frame, PAGE_KERNEL), 0);
++
++		set_phys_to_machine(page_to_pfn(page), frame);
++		++n;
++	}
++	if (nr_mcl) {
++		cr_mcl[nr_mcl - 1].args[MULTI_UVMFLAGS_INDEX] = order
++							        ? UVMF_TLB_FLUSH|UVMF_ALL
++							        : UVMF_INVLPG|UVMF_ALL;
++		if (HYPERVISOR_multicall_check(cr_mcl, nr_mcl, NULL))
++			BUG();
++	}
++
++	balloon_unlock(flags);
++
++	if (!success)
++		return -ENOMEM;
++
++	if (address_bits) {
++		if (order) {
++			BUILD_BUG_ON(sizeof(*limit_map) != sizeof(pages->index));
++			for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
++				pages[i + 1].index = limit_map[i];
++		}
++		SetPageForeign(pages, undo_limit_pages);
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(xen_limit_pages_to_max_mfn);
++
++#ifdef __i386__
++int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
++{
++	__u32 *lp = (__u32 *)((char *)ldt + entry * 8);
++	maddr_t mach_lp = arbitrary_virt_to_machine(lp);
++	return HYPERVISOR_update_descriptor(
++		mach_lp, (u64)entry_a | ((u64)entry_b<<32));
++}
++#endif
++
++#define MAX_BATCHED_FULL_PTES 32
++
++int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
++			 unsigned long addr, unsigned long end, pgprot_t newprot)
++{
++	int rc = 0, i = 0;
++	mmu_update_t u[MAX_BATCHED_FULL_PTES];
++	pte_t *pte;
++	spinlock_t *ptl;
++
++	if (!xen_feature(XENFEAT_mmu_pt_update_preserve_ad))
++		return 0;
++
++	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
++	do {
++		if (pte_present(*pte)) {
++			u[i].ptr = (__pmd_val(*pmd) & PHYSICAL_PAGE_MASK)
++				   | ((unsigned long)pte & ~PAGE_MASK)
++				   | MMU_PT_UPDATE_PRESERVE_AD;
++			u[i].val = __pte_val(pte_modify(*pte, newprot));
++			if (++i == MAX_BATCHED_FULL_PTES) {
++				if ((rc = HYPERVISOR_mmu_update(
++					&u[0], i, NULL, DOMID_SELF)) != 0)
++					break;
++				i = 0;
++			}
++		}
++	} while (pte++, addr += PAGE_SIZE, addr != end);
++	if (i)
++		rc = HYPERVISOR_mmu_update( &u[0], i, NULL, DOMID_SELF);
++	pte_unmap_unlock(pte - 1, ptl);
++	BUG_ON(rc && rc != -ENOSYS);
++	return !rc;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,840 @@
++/*
++ *  linux/arch/i386/mm/init.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ */
++
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/hugetlb.h>
++#include <linux/swap.h>
++#include <linux/smp.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++#include <linux/pagemap.h>
++#include <linux/poison.h>
++#include <linux/bootmem.h>
++#include <linux/slab.h>
++#include <linux/proc_fs.h>
++#include <linux/efi.h>
++#include <linux/memory_hotplug.h>
++#include <linux/initrd.h>
++#include <linux/cpumask.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/dma.h>
++#include <asm/fixmap.h>
++#include <asm/e820.h>
++#include <asm/apic.h>
++#include <asm/tlb.h>
++#include <asm/tlbflush.h>
++#include <asm/sections.h>
++#include <asm/hypervisor.h>
++#include <asm/swiotlb.h>
++
++unsigned int __VMALLOC_RESERVE = 128 << 20;
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++unsigned long highstart_pfn, highend_pfn;
++
++static int noinline do_test_wp_bit(void);
++
++/*
++ * Creates a middle page table and puts a pointer to it in the
++ * given global directory entry. This only returns the gd entry
++ * in non-PAE compilation mode, since the middle layer is folded.
++ */
++static pmd_t * __init one_md_table_init(pgd_t *pgd)
++{
++	pud_t *pud;
++	pmd_t *pmd_table;
++		
++#ifdef CONFIG_X86_PAE
++	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++	make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
++	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
++	pud = pud_offset(pgd, 0);
++	if (pmd_table != pmd_offset(pud, 0)) 
++		BUG();
++#else
++	pud = pud_offset(pgd, 0);
++	pmd_table = pmd_offset(pud, 0);
++#endif
++
++	return pmd_table;
++}
++
++/*
++ * Create a page table and place a pointer to it in a middle page
++ * directory entry.
++ */
++static pte_t * __init one_page_table_init(pmd_t *pmd)
++{
++	if (pmd_none(*pmd)) {
++		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++		make_lowmem_page_readonly(page_table,
++					  XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
++		if (page_table != pte_offset_kernel(pmd, 0))
++			BUG();	
++
++		return page_table;
++	}
++	
++	return pte_offset_kernel(pmd, 0);
++}
++
++/*
++ * This function initializes a certain range of kernel virtual memory 
++ * with new bootmem page tables, everywhere page tables are missing in
++ * the given range.
++ */
++
++/*
++ * NOTE: The pagetables are allocated contiguous on the physical space 
++ * so we can cache the place of the first one and move around without 
++ * checking the pgd every time.
++ */
++static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	int pgd_idx, pmd_idx;
++	unsigned long vaddr;
++
++	vaddr = start;
++	pgd_idx = pgd_index(vaddr);
++	pmd_idx = pmd_index(vaddr);
++	pgd = pgd_base + pgd_idx;
++
++	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
++		if (pgd_none(*pgd)) 
++			one_md_table_init(pgd);
++		pud = pud_offset(pgd, vaddr);
++		pmd = pmd_offset(pud, vaddr);
++		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
++			if (vaddr < hypervisor_virt_start && pmd_none(*pmd))
++				one_page_table_init(pmd);
++
++			vaddr += PMD_SIZE;
++		}
++		pmd_idx = 0;
++	}
++}
++
++static inline int is_kernel_text(unsigned long addr)
++{
++	if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
++		return 1;
++	return 0;
++}
++
++/*
++ * This maps the physical memory to kernel virtual address space, a total 
++ * of max_low_pfn pages, by creating page tables starting from address 
++ * PAGE_OFFSET.
++ */
++static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
++{
++	unsigned long pfn;
++	pgd_t *pgd;
++	pmd_t *pmd;
++	pte_t *pte;
++	int pgd_idx, pmd_idx, pte_ofs;
++
++	unsigned long max_ram_pfn = xen_start_info->nr_pages;
++	if (max_ram_pfn > max_low_pfn)
++		max_ram_pfn = max_low_pfn;
++
++	pgd_idx = pgd_index(PAGE_OFFSET);
++	pgd = pgd_base + pgd_idx;
++	pfn = 0;
++	pmd_idx = pmd_index(PAGE_OFFSET);
++	pte_ofs = pte_index(PAGE_OFFSET);
++
++	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
++#ifdef CONFIG_XEN
++		/*
++		 * Native linux hasn't PAE-paging enabled yet at this
++		 * point.  When running as xen domain we are in PAE
++		 * mode already, thus we can't simply hook a empty
++		 * pmd.  That would kill the mappings we are currently
++		 * using ...
++		 */
++		pmd = pmd_offset(pud_offset(pgd, PAGE_OFFSET), PAGE_OFFSET);
++#else
++		pmd = one_md_table_init(pgd);
++#endif
++		if (pfn >= max_low_pfn)
++			continue;
++		pmd += pmd_idx;
++		for (; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
++			unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
++			if (address >= hypervisor_virt_start)
++				continue;
++
++			/* Map with big pages if possible, otherwise create normal page tables. */
++			if (cpu_has_pse) {
++				unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
++
++				if (is_kernel_text(address) || is_kernel_text(address2))
++					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
++				else
++					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
++				pfn += PTRS_PER_PTE;
++			} else {
++				pte = one_page_table_init(pmd);
++
++				pte += pte_ofs;
++				for (; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
++						/* XEN: Only map initial RAM allocation. */
++						if ((pfn >= max_ram_pfn) || pte_present(*pte))
++							continue;
++						if (is_kernel_text(address))
++							set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
++						else
++							set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
++				}
++				pte_ofs = 0;
++			}
++		}
++		pmd_idx = 0;
++	}
++}
++
++#ifndef CONFIG_XEN
++
++static inline int page_kills_ppro(unsigned long pagenr)
++{
++	if (pagenr >= 0x70000 && pagenr <= 0x7003F)
++		return 1;
++	return 0;
++}
++
++#else
++
++#define page_kills_ppro(p)	0
++
++#endif
++
++extern int is_available_memory(efi_memory_desc_t *);
++
++int page_is_ram(unsigned long pagenr)
++{
++	int i;
++	unsigned long addr, end;
++
++	if (efi_enabled) {
++		efi_memory_desc_t *md;
++		void *p;
++
++		for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
++			md = p;
++			if (!is_available_memory(md))
++				continue;
++			addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
++			end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT;
++
++			if ((pagenr >= addr) && (pagenr < end))
++				return 1;
++		}
++		return 0;
++	}
++
++	for (i = 0; i < e820.nr_map; i++) {
++
++		if (e820.map[i].type != E820_RAM)	/* not usable memory */
++			continue;
++		/*
++		 *	!!!FIXME!!! Some BIOSen report areas as RAM that
++		 *	are not. Notably the 640->1Mb area. We need a sanity
++		 *	check here.
++		 */
++		addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
++		end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
++		if  ((pagenr >= addr) && (pagenr < end))
++			return 1;
++	}
++	return 0;
++}
++
++#ifdef CONFIG_HIGHMEM
++pte_t *kmap_pte;
++pgprot_t kmap_prot;
++
++#define kmap_get_fixmap_pte(vaddr)					\
++	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
++
++static void __init kmap_init(void)
++{
++	unsigned long kmap_vstart;
++
++	/* cache the first kmap pte */
++	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
++	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
++
++	kmap_prot = PAGE_KERNEL;
++}
++
++static void __init permanent_kmaps_init(pgd_t *pgd_base)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++	unsigned long vaddr;
++
++	vaddr = PKMAP_BASE;
++	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
++
++	pgd = swapper_pg_dir + pgd_index(vaddr);
++	pud = pud_offset(pgd, vaddr);
++	pmd = pmd_offset(pud, vaddr);
++	pte = pte_offset_kernel(pmd, vaddr);
++	pkmap_page_table = pte;	
++}
++
++static void __meminit free_new_highpage(struct page *page, int pfn)
++{
++	init_page_count(page);
++	if (pfn < xen_start_info->nr_pages)
++		__free_page(page);
++	totalhigh_pages++;
++}
++
++void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
++{
++	if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
++		ClearPageReserved(page);
++		free_new_highpage(page, pfn);
++	} else
++		SetPageReserved(page);
++}
++
++static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
++{
++	free_new_highpage(page, pfn);
++	totalram_pages++;
++#ifdef CONFIG_FLATMEM
++	max_mapnr = max(pfn, max_mapnr);
++#endif
++	num_physpages++;
++	return 0;
++}
++
++/*
++ * Not currently handling the NUMA case.
++ * Assuming single node and all memory that
++ * has been added dynamically that would be
++ * onlined here is in HIGHMEM
++ */
++void online_page(struct page *page)
++{
++	ClearPageReserved(page);
++	add_one_highpage_hotplug(page, page_to_pfn(page));
++}
++
++
++#ifdef CONFIG_NUMA
++extern void set_highmem_pages_init(int);
++#else
++static void __init set_highmem_pages_init(int bad_ppro)
++{
++	int pfn;
++	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
++		add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
++	totalram_pages += totalhigh_pages;
++}
++#endif /* CONFIG_FLATMEM */
++
++#else
++#define kmap_init() do { } while (0)
++#define permanent_kmaps_init(pgd_base) do { } while (0)
++#define set_highmem_pages_init(bad_ppro) do { } while (0)
++#endif /* CONFIG_HIGHMEM */
++
++unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;
++EXPORT_SYMBOL(__PAGE_KERNEL);
++unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
++
++#ifdef CONFIG_NUMA
++extern void __init remap_numa_kva(void);
++#else
++#define remap_numa_kva() do {} while (0)
++#endif
++
++pgd_t *swapper_pg_dir;
++
++static void __init pagetable_init (void)
++{
++	unsigned long vaddr;
++	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
++
++	/* Enable PSE if available */
++	if (cpu_has_pse) {
++		set_in_cr4(X86_CR4_PSE);
++	}
++
++	/* Enable PGE if available */
++	if (cpu_has_pge) {
++		set_in_cr4(X86_CR4_PGE);
++		__PAGE_KERNEL |= _PAGE_GLOBAL;
++		__PAGE_KERNEL_EXEC |= _PAGE_GLOBAL;
++	}
++
++	kernel_physical_mapping_init(pgd_base);
++	remap_numa_kva();
++
++	/*
++	 * Fixed mappings, only the page table structure has to be
++	 * created - mappings will be set by set_fixmap():
++	 */
++	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
++	page_table_range_init(vaddr, hypervisor_virt_start, pgd_base);
++
++	permanent_kmaps_init(pgd_base);
++}
++
++#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
++/*
++ * Swap suspend & friends need this for resume because things like the intel-agp
++ * driver might have split up a kernel 4MB mapping.
++ */
++char __nosavedata swsusp_pg_dir[PAGE_SIZE]
++	__attribute__ ((aligned (PAGE_SIZE)));
++
++static inline void save_pg_dir(void)
++{
++	memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
++}
++#else
++static inline void save_pg_dir(void)
++{
++}
++#endif
++
++void zap_low_mappings (void)
++{
++	int i;
++
++	save_pg_dir();
++
++	/*
++	 * Zap initial low-memory mappings.
++	 *
++	 * Note that "pgd_clear()" doesn't do it for
++	 * us, because pgd_clear() is a no-op on i386.
++	 */
++	for (i = 0; i < USER_PTRS_PER_PGD; i++)
++#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
++		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
++#else
++		set_pgd(swapper_pg_dir+i, __pgd(0));
++#endif
++	flush_tlb_all();
++}
++
++static int disable_nx __initdata = 0;
++u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
++EXPORT_SYMBOL(__supported_pte_mask);
++
++/*
++ * noexec = on|off
++ *
++ * Control non executable mappings.
++ *
++ * on      Enable
++ * off     Disable
++ */
++void __init noexec_setup(const char *str)
++{
++	if (!strncmp(str, "on",2) && cpu_has_nx) {
++		__supported_pte_mask |= _PAGE_NX;
++		disable_nx = 0;
++	} else if (!strncmp(str,"off",3)) {
++		disable_nx = 1;
++		__supported_pte_mask &= ~_PAGE_NX;
++	}
++}
++
++int nx_enabled = 0;
++#ifdef CONFIG_X86_PAE
++
++static void __init set_nx(void)
++{
++	unsigned int v[4], l, h;
++
++	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
++		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
++		if ((v[3] & (1 << 20)) && !disable_nx) {
++			rdmsr(MSR_EFER, l, h);
++			l |= EFER_NX;
++			wrmsr(MSR_EFER, l, h);
++			nx_enabled = 1;
++			__supported_pte_mask |= _PAGE_NX;
++		}
++	}
++}
++
++/*
++ * Enables/disables executability of a given kernel page and
++ * returns the previous setting.
++ */
++int __init set_kernel_exec(unsigned long vaddr, int enable)
++{
++	pte_t *pte;
++	int ret = 1;
++
++	if (!nx_enabled)
++		goto out;
++
++	pte = lookup_address(vaddr);
++	BUG_ON(!pte);
++
++	if (!pte_exec_kernel(*pte))
++		ret = 0;
++
++	if (enable)
++		pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
++	else
++		pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);
++	__flush_tlb_all();
++out:
++	return ret;
++}
++
++#endif
++
++/*
++ * paging_init() sets up the page tables - note that the first 8MB are
++ * already mapped by head.S.
++ *
++ * This routines also unmaps the page at virtual kernel address 0, so
++ * that we can trap those pesky NULL-reference errors in the kernel.
++ */
++void __init paging_init(void)
++{
++	int i;
++
++#ifdef CONFIG_X86_PAE
++	set_nx();
++	if (nx_enabled)
++		printk("NX (Execute Disable) protection: active\n");
++#endif
++
++	pagetable_init();
++
++#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
++	/*
++	 * We will bail out later - printk doesn't work right now so
++	 * the user would just see a hanging kernel.
++	 * when running as xen domain we are already in PAE mode at
++	 * this point.
++	 */
++	if (cpu_has_pae)
++		set_in_cr4(X86_CR4_PAE);
++#endif
++	__flush_tlb_all();
++
++	kmap_init();
++
++	/* Switch to the real shared_info page, and clear the
++	 * dummy page. */
++	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++	memset(empty_zero_page, 0, sizeof(empty_zero_page));
++
++	/* Setup mapping of lower 1st MB */
++	for (i = 0; i < NR_FIX_ISAMAPS; i++)
++		if (is_initial_xendomain())
++			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
++		else
++			__set_fixmap(FIX_ISAMAP_BEGIN - i,
++				     virt_to_machine(empty_zero_page),
++				     PAGE_KERNEL_RO);
++}
++
++/*
++ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
++ * and also on some strange 486's (NexGen etc.). All 586+'s are OK. This
++ * used to involve black magic jumps to work around some nasty CPU bugs,
++ * but fortunately the switch to using exceptions got rid of all that.
++ */
++
++static void __init test_wp_bit(void)
++{
++	printk("Checking if this processor honours the WP bit even in supervisor mode... ");
++
++	/* Any page-aligned address will do, the test is non-destructive */
++	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
++	boot_cpu_data.wp_works_ok = do_test_wp_bit();
++	clear_fixmap(FIX_WP_TEST);
++
++	if (!boot_cpu_data.wp_works_ok) {
++		printk("No.\n");
++#ifdef CONFIG_X86_WP_WORKS_OK
++		panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
++#endif
++	} else {
++		printk("Ok.\n");
++	}
++}
++
++static void __init set_max_mapnr_init(void)
++{
++#ifdef CONFIG_HIGHMEM
++	num_physpages = highend_pfn;
++#else
++	num_physpages = max_low_pfn;
++#endif
++#ifdef CONFIG_FLATMEM
++	max_mapnr = num_physpages;
++#endif
++}
++
++static struct kcore_list kcore_mem, kcore_vmalloc; 
++
++void __init mem_init(void)
++{
++	extern int ppro_with_ram_bug(void);
++	int codesize, reservedpages, datasize, initsize;
++	int tmp;
++	int bad_ppro;
++	unsigned long pfn;
++
++#if defined(CONFIG_SWIOTLB)
++	swiotlb_init();	
++#endif
++
++#ifdef CONFIG_FLATMEM
++	if (!mem_map)
++		BUG();
++#endif
++	
++	bad_ppro = ppro_with_ram_bug();
++
++#ifdef CONFIG_HIGHMEM
++	/* check that fixmap and pkmap do not overlap */
++	if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
++		printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
++		printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
++				PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
++		BUG();
++	}
++#endif
++ 
++	set_max_mapnr_init();
++
++#ifdef CONFIG_HIGHMEM
++	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
++#else
++	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
++#endif
++	printk("vmalloc area: %lx-%lx, maxmem %lx\n",
++	       VMALLOC_START,VMALLOC_END,MAXMEM);
++	BUG_ON(VMALLOC_START > VMALLOC_END);
++	
++	/* this will put all low memory onto the freelists */
++	totalram_pages += free_all_bootmem();
++	/* XEN: init and count low-mem pages outside initial allocation. */
++	for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) {
++		ClearPageReserved(pfn_to_page(pfn));
++		init_page_count(pfn_to_page(pfn));
++		totalram_pages++;
++	}
++
++	reservedpages = 0;
++	for (tmp = 0; tmp < max_low_pfn; tmp++)
++		/*
++		 * Only count reserved RAM pages
++		 */
++		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
++			reservedpages++;
++
++	set_highmem_pages_init(bad_ppro);
++
++	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
++	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
++	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
++
++	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
++	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, 
++		   VMALLOC_END-VMALLOC_START);
++
++	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
++		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
++		num_physpages << (PAGE_SHIFT-10),
++		codesize >> 10,
++		reservedpages << (PAGE_SHIFT-10),
++		datasize >> 10,
++		initsize >> 10,
++		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
++	       );
++
++#ifdef CONFIG_X86_PAE
++	if (!cpu_has_pae)
++		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
++#endif
++	if (boot_cpu_data.wp_works_ok < 0)
++		test_wp_bit();
++
++	/*
++	 * Subtle. SMP is doing it's boot stuff late (because it has to
++	 * fork idle threads) - but it also needs low mappings for the
++	 * protected-mode entry to work. We zap these entries only after
++	 * the WP-bit has been tested.
++	 */
++#ifndef CONFIG_SMP
++	zap_low_mappings();
++#endif
++
++	set_bit(PG_pinned, &virt_to_page(init_mm.pgd)->flags);
++}
++
++/*
++ * this is for the non-NUMA, single node SMP system case.
++ * Specifically, in the case of x86, we will always add
++ * memory to the highmem for now.
++ */
++#ifdef CONFIG_MEMORY_HOTPLUG
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++int arch_add_memory(int nid, u64 start, u64 size)
++{
++	struct pglist_data *pgdata = &contig_page_data;
++	struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
++	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long nr_pages = size >> PAGE_SHIFT;
++
++	return __add_pages(zone, start_pfn, nr_pages);
++}
++
++int remove_memory(u64 start, u64 size)
++{
++	return -EINVAL;
++}
++#endif
++#endif
++
++kmem_cache_t *pgd_cache;
++kmem_cache_t *pmd_cache;
++
++void __init pgtable_cache_init(void)
++{
++	if (PTRS_PER_PMD > 1) {
++		pmd_cache = kmem_cache_create("pmd",
++					PTRS_PER_PMD*sizeof(pmd_t),
++					PTRS_PER_PMD*sizeof(pmd_t),
++					0,
++					pmd_ctor,
++					NULL);
++		if (!pmd_cache)
++			panic("pgtable_cache_init(): cannot create pmd cache");
++	}
++	pgd_cache = kmem_cache_create("pgd",
++#ifndef CONFIG_XEN
++				PTRS_PER_PGD*sizeof(pgd_t),
++				PTRS_PER_PGD*sizeof(pgd_t),
++#else
++				PAGE_SIZE,
++				PAGE_SIZE,
++#endif
++				0,
++				pgd_ctor,
++				PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
++	if (!pgd_cache)
++		panic("pgtable_cache_init(): Cannot create pgd cache");
++}
++
++/*
++ * This function cannot be __init, since exceptions don't work in that
++ * section.  Put this after the callers, so that it cannot be inlined.
++ */
++static int noinline do_test_wp_bit(void)
++{
++	char tmp_reg;
++	int flag;
++
++	__asm__ __volatile__(
++		"	movb %0,%1	\n"
++		"1:	movb %1,%0	\n"
++		"	xorl %2,%2	\n"
++		"2:			\n"
++		".section __ex_table,\"a\"\n"
++		"	.align 4	\n"
++		"	.long 1b,2b	\n"
++		".previous		\n"
++		:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
++		 "=q" (tmp_reg),
++		 "=r" (flag)
++		:"2" (1)
++		:"memory");
++	
++	return flag;
++}
++
++#ifdef CONFIG_DEBUG_RODATA
++
++void mark_rodata_ro(void)
++{
++	unsigned long addr = (unsigned long)__start_rodata;
++
++	for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
++		change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
++
++	printk("Write protecting the kernel read-only data: %uk\n",
++			(__end_rodata - __start_rodata) >> 10);
++
++	/*
++	 * change_page_attr() requires a global_flush_tlb() call after it.
++	 * We do this after the printk so that if something went wrong in the
++	 * change, the printk gets out at least to give a better debug hint
++	 * of who is the culprit.
++	 */
++	global_flush_tlb();
++}
++#endif
++
++void free_init_pages(char *what, unsigned long begin, unsigned long end)
++{
++	unsigned long addr;
++
++	for (addr = begin; addr < end; addr += PAGE_SIZE) {
++		ClearPageReserved(virt_to_page(addr));
++		init_page_count(virt_to_page(addr));
++		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
++		free_page(addr);
++		totalram_pages++;
++	}
++	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
++}
++
++void free_initmem(void)
++{
++	free_init_pages("unused kernel memory",
++			(unsigned long)(&__init_begin),
++			(unsigned long)(&__init_end));
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++	free_init_pages("initrd memory", start, end);
++}
++#endif
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/ioremap_32-xen.c	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,443 @@
++/*
++ * arch/i386/mm/ioremap.c
++ *
++ * Re-map IO memory to kernel address space so that we can access it.
++ * This is needed for high PCI addresses that aren't mapped in the
++ * 640k-1MB IO memory area on PC's
++ *
++ * (C) Copyright 1995 1996 Linus Torvalds
++ */
++
++#include <linux/vmalloc.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <asm/fixmap.h>
++#include <asm/cacheflush.h>
++#include <asm/tlbflush.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++
++#define ISA_START_ADDRESS	0x0
++#define ISA_END_ADDRESS		0x100000
++
++static int direct_remap_area_pte_fn(pte_t *pte, 
++				    struct page *pmd_page,
++				    unsigned long address, 
++				    void *data)
++{
++	mmu_update_t **v = (mmu_update_t **)data;
++
++	BUG_ON(!pte_none(*pte));
++
++	(*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
++		     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
++	(*v)++;
++
++	return 0;
++}
++
++static int __direct_remap_pfn_range(struct mm_struct *mm,
++				    unsigned long address, 
++				    unsigned long mfn,
++				    unsigned long size, 
++				    pgprot_t prot,
++				    domid_t  domid)
++{
++	int rc;
++	unsigned long i, start_address;
++	mmu_update_t *u, *v, *w;
++
++	u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
++	if (u == NULL)
++		return -ENOMEM;
++
++	start_address = address;
++
++	flush_cache_all();
++
++	for (i = 0; i < size; i += PAGE_SIZE) {
++		if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
++			/* Flush a full batch after filling in the PTE ptrs. */
++			rc = apply_to_page_range(mm, start_address, 
++						 address - start_address,
++						 direct_remap_area_pte_fn, &w);
++			if (rc)
++				goto out;
++			rc = -EFAULT;
++			if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)
++				goto out;
++			v = w = u;
++			start_address = address;
++		}
++
++		/*
++		 * Fill in the machine address: PTE ptr is done later by
++		 * apply_to_page_range(). 
++		 */
++		v->val = __pte_val(pfn_pte_ma(mfn, prot)) | _PAGE_IO;
++
++		mfn++;
++		address += PAGE_SIZE; 
++		v++;
++	}
++
++	if (v != u) {
++		/* Final batch. */
++		rc = apply_to_page_range(mm, start_address,
++					 address - start_address,
++					 direct_remap_area_pte_fn, &w);
++		if (rc)
++			goto out;
++		rc = -EFAULT;
++		if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0))
++			goto out;
++	}
++
++	rc = 0;
++
++ out:
++	flush_tlb_all();
++
++	free_page((unsigned long)u);
++
++	return rc;
++}
++
++int direct_remap_pfn_range(struct vm_area_struct *vma,
++			   unsigned long address, 
++			   unsigned long mfn,
++			   unsigned long size, 
++			   pgprot_t prot,
++			   domid_t  domid)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return remap_pfn_range(vma, address, mfn, size, prot);
++
++	if (domid == DOMID_SELF)
++		return -EINVAL;
++
++	vma->vm_flags |= VM_IO | VM_RESERVED;
++
++	vma->vm_mm->context.has_foreign_mappings = 1;
++
++	return __direct_remap_pfn_range(
++		vma->vm_mm, address, mfn, size, prot, domid);
++}
++EXPORT_SYMBOL(direct_remap_pfn_range);
++
++int direct_kernel_remap_pfn_range(unsigned long address, 
++				  unsigned long mfn,
++				  unsigned long size, 
++				  pgprot_t prot,
++				  domid_t  domid)
++{
++	return __direct_remap_pfn_range(
++		&init_mm, address, mfn, size, prot, domid);
++}
++EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
++
++static int lookup_pte_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	uint64_t *ptep = (uint64_t *)data;
++	if (ptep)
++		*ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
++			 PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
++	return 0;
++}
++
++int create_lookup_pte_addr(struct mm_struct *mm, 
++			   unsigned long address,
++			   uint64_t *ptep)
++{
++	return apply_to_page_range(mm, address, PAGE_SIZE,
++				   lookup_pte_fn, ptep);
++}
++
++EXPORT_SYMBOL(create_lookup_pte_addr);
++
++static int noop_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	return 0;
++}
++
++int touch_pte_range(struct mm_struct *mm,
++		    unsigned long address,
++		    unsigned long size)
++{
++	return apply_to_page_range(mm, address, size, noop_fn, NULL);
++} 
++
++EXPORT_SYMBOL(touch_pte_range);
++
++/*
++ * Does @address reside within a non-highmem page that is local to this virtual
++ * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
++ * See the comment that accompanies mfn_to_local_pfn() in page.h to understand
++ * why this works.
++ */
++static inline int is_local_lowmem(unsigned long address)
++{
++	extern unsigned long max_low_pfn;
++	return (mfn_to_local_pfn(address >> PAGE_SHIFT) < max_low_pfn);
++}
++
++/*
++ * Generic mapping function (not visible outside):
++ */
++
++/*
++ * Remap an arbitrary physical address space into the kernel virtual
++ * address space. Needed when the kernel wants to access high addresses
++ * directly.
++ *
++ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
++ * have to convert them into an offset in a page-aligned mapping, but the
++ * caller shouldn't need to know that small detail.
++ */
++void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
++{
++	void __iomem * addr;
++	struct vm_struct * area;
++	unsigned long offset, last_addr;
++	domid_t domid = DOMID_IO;
++
++	/* Don't allow wraparound or zero size */
++	last_addr = phys_addr + size - 1;
++	if (!size || last_addr < phys_addr)
++		return NULL;
++
++	/*
++	 * Don't remap the low PCI/ISA area, it's always mapped..
++	 */
++	if (is_initial_xendomain() &&
++	    phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
++		return (void __iomem *) isa_bus_to_virt(phys_addr);
++
++	/*
++	 * Don't allow anybody to remap normal RAM that we're using..
++	 */
++	if (is_local_lowmem(phys_addr)) {
++		char *t_addr, *t_end;
++		struct page *page;
++
++		t_addr = bus_to_virt(phys_addr);
++		t_end = t_addr + (size - 1);
++	   
++		for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
++			if(!PageReserved(page))
++				return NULL;
++
++		domid = DOMID_SELF;
++	}
++
++	/*
++	 * Mappings have to be page-aligned
++	 */
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
++	size = PAGE_ALIGN(last_addr+1) - phys_addr;
++
++	/*
++	 * Ok, go for it..
++	 */
++	area = get_vm_area(size, VM_IOREMAP | (flags << 20));
++	if (!area)
++		return NULL;
++	area->phys_addr = phys_addr;
++	addr = (void __iomem *) area->addr;
++	flags |= _KERNPG_TABLE;
++	if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr,
++				     phys_addr>>PAGE_SHIFT,
++				     size, __pgprot(flags), domid)) {
++		vunmap((void __force *) addr);
++		return NULL;
++	}
++	return (void __iomem *) (offset + (char __iomem *)addr);
++}
++EXPORT_SYMBOL(__ioremap);
++
++/**
++ * ioremap_nocache     -   map bus memory into CPU space
++ * @offset:    bus address of the memory
++ * @size:      size of the resource to map
++ *
++ * ioremap_nocache performs a platform specific sequence of operations to
++ * make bus memory CPU accessible via the readb/readw/readl/writeb/
++ * writew/writel functions and the other mmio helpers. The returned
++ * address is not guaranteed to be usable directly as a virtual
++ * address. 
++ *
++ * This version of ioremap ensures that the memory is marked uncachable
++ * on the CPU as well as honouring existing caching rules from things like
++ * the PCI bus. Note that there are other caches and buffers on many 
++ * busses. In particular driver authors should read up on PCI writes
++ *
++ * It's useful if some control registers are in such an area and
++ * write combining or read caching is not desirable:
++ * 
++ * Must be freed with iounmap.
++ */
++
++void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
++{
++	unsigned long last_addr;
++	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
++	if (!p) 
++		return p; 
++
++	/* Guaranteed to be > phys_addr, as per __ioremap() */
++	last_addr = phys_addr + size - 1;
++
++	if (is_local_lowmem(last_addr)) { 
++		struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
++		unsigned long npages;
++
++		phys_addr &= PAGE_MASK;
++
++		/* This might overflow and become zero.. */
++		last_addr = PAGE_ALIGN(last_addr);
++
++		/* .. but that's ok, because modulo-2**n arithmetic will make
++	 	* the page-aligned "last - first" come out right.
++	 	*/
++		npages = (last_addr - phys_addr) >> PAGE_SHIFT;
++
++		if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { 
++			iounmap(p); 
++			p = NULL;
++		}
++		global_flush_tlb();
++	}
++
++	return p;					
++}
++EXPORT_SYMBOL(ioremap_nocache);
++
++/**
++ * iounmap - Free a IO remapping
++ * @addr: virtual address from ioremap_*
++ *
++ * Caller must ensure there is only one unmapping for the same pointer.
++ */
++void iounmap(volatile void __iomem *addr)
++{
++	struct vm_struct *p, *o;
++
++	if ((void __force *)addr <= high_memory)
++		return;
++
++	/*
++	 * __ioremap special-cases the PCI/ISA range by not instantiating a
++	 * vm_area and by simply returning an address into the kernel mapping
++	 * of ISA space.   So handle that here.
++	 */
++	if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
++		return;
++
++	addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
++
++	/* Use the vm area unlocked, assuming the caller
++	   ensures there isn't another iounmap for the same address
++	   in parallel. Reuse of the virtual address is prevented by
++	   leaving it in the global lists until we're done with it.
++	   cpa takes care of the direct mappings. */
++	read_lock(&vmlist_lock);
++	for (p = vmlist; p; p = p->next) {
++		if (p->addr == addr)
++			break;
++	}
++	read_unlock(&vmlist_lock);
++
++	if (!p) {
++		printk("iounmap: bad address %p\n", addr);
++		dump_stack();
++		return;
++	}
++
++	/* Reset the direct mapping. Can block */
++	if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
++		/* p->size includes the guard page, but cpa doesn't like that */
++		change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
++				 (p->size - PAGE_SIZE) >> PAGE_SHIFT,
++				 PAGE_KERNEL);
++		global_flush_tlb();
++	} 
++
++	/* Finally remove it */
++	o = remove_vm_area((void *)addr);
++	BUG_ON(p != o || o == NULL);
++	kfree(p); 
++}
++EXPORT_SYMBOL(iounmap);
++
++void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
++{
++	unsigned long offset, last_addr;
++	unsigned int nrpages;
++	enum fixed_addresses idx;
++
++	/* Don't allow wraparound or zero size */
++	last_addr = phys_addr + size - 1;
++	if (!size || last_addr < phys_addr)
++		return NULL;
++
++	/*
++	 * Don't remap the low PCI/ISA area, it's always mapped..
++	 */
++	if (is_initial_xendomain() &&
++	    phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
++		return isa_bus_to_virt(phys_addr);
++
++	/*
++	 * Mappings have to be page-aligned
++	 */
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
++	size = PAGE_ALIGN(last_addr) - phys_addr;
++
++	/*
++	 * Mappings have to fit in the FIX_BTMAP area.
++	 */
++	nrpages = size >> PAGE_SHIFT;
++	if (nrpages > NR_FIX_BTMAPS)
++		return NULL;
++
++	/*
++	 * Ok, go for it..
++	 */
++	idx = FIX_BTMAP_BEGIN;
++	while (nrpages > 0) {
++		set_fixmap(idx, phys_addr);
++		phys_addr += PAGE_SIZE;
++		--idx;
++		--nrpages;
++	}
++	return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
++}
++
++void __init bt_iounmap(void *addr, unsigned long size)
++{
++	unsigned long virt_addr;
++	unsigned long offset;
++	unsigned int nrpages;
++	enum fixed_addresses idx;
++
++	virt_addr = (unsigned long)addr;
++	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
++		return;
++	if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
++		return;
++	offset = virt_addr & ~PAGE_MASK;
++	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
++
++	idx = FIX_BTMAP_BEGIN;
++	while (nrpages > 0) {
++		clear_fixmap(idx);
++		--idx;
++		--nrpages;
++	}
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,731 @@
++/*
++ *  linux/arch/i386/mm/pgtable.c
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/smp.h>
++#include <linux/highmem.h>
++#include <linux/slab.h>
++#include <linux/pagemap.h>
++#include <linux/spinlock.h>
++#include <linux/module.h>
++
++#include <asm/system.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/fixmap.h>
++#include <asm/e820.h>
++#include <asm/tlb.h>
++#include <asm/tlbflush.h>
++#include <asm/io.h>
++#include <asm/mmu_context.h>
++
++#include <xen/features.h>
++#include <asm/hypervisor.h>
++
++static void pgd_test_and_unpin(pgd_t *pgd);
++
++void show_mem(void)
++{
++	int total = 0, reserved = 0;
++	int shared = 0, cached = 0;
++	int highmem = 0;
++	struct page *page;
++	pg_data_t *pgdat;
++	unsigned long i;
++	unsigned long flags;
++
++	printk(KERN_INFO "Mem-info:\n");
++	show_free_areas();
++	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
++	for_each_online_pgdat(pgdat) {
++		pgdat_resize_lock(pgdat, &flags);
++		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
++			page = pgdat_page_nr(pgdat, i);
++			total++;
++			if (PageHighMem(page))
++				highmem++;
++			if (PageReserved(page))
++				reserved++;
++			else if (PageSwapCache(page))
++				cached++;
++			else if (page_count(page))
++				shared += page_count(page) - 1;
++		}
++		pgdat_resize_unlock(pgdat, &flags);
++	}
++	printk(KERN_INFO "%d pages of RAM\n", total);
++	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
++	printk(KERN_INFO "%d reserved pages\n", reserved);
++	printk(KERN_INFO "%d pages shared\n", shared);
++	printk(KERN_INFO "%d pages swap cached\n", cached);
++
++	printk(KERN_INFO "%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
++	printk(KERN_INFO "%lu pages writeback\n",
++					global_page_state(NR_WRITEBACK));
++	printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
++	printk(KERN_INFO "%lu pages slab\n", global_page_state(NR_SLAB));
++	printk(KERN_INFO "%lu pages pagetables\n",
++					global_page_state(NR_PAGETABLE));
++}
++
++/*
++ * Associate a large virtual page frame with a given physical page frame 
++ * and protection flags for that frame. pfn is for the base of the page,
++ * vaddr is what the page gets mapped to - both must be properly aligned. 
++ * The pmd must already be instantiated. Assumes PAE mode.
++ */ 
++void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++
++	if (vaddr & (PMD_SIZE-1)) {		/* vaddr is misaligned */
++		printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n");
++		return; /* BUG(); */
++	}
++	if (pfn & (PTRS_PER_PTE-1)) {		/* pfn is misaligned */
++		printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n");
++		return; /* BUG(); */
++	}
++	pgd = swapper_pg_dir + pgd_index(vaddr);
++	if (pgd_none(*pgd)) {
++		printk(KERN_WARNING "set_pmd_pfn: pgd_none\n");
++		return; /* BUG(); */
++	}
++	pud = pud_offset(pgd, vaddr);
++	pmd = pmd_offset(pud, vaddr);
++	set_pmd(pmd, pfn_pmd(pfn, flags));
++	/*
++	 * It's enough to flush this one mapping.
++	 * (PGE mappings get flushed as well)
++	 */
++	__flush_tlb_one(vaddr);
++}
++
++static int nr_fixmaps = 0;
++unsigned long hypervisor_virt_start = HYPERVISOR_VIRT_START;
++unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - 2 * PAGE_SIZE);
++EXPORT_SYMBOL(__FIXADDR_TOP);
++
++void __init set_fixaddr_top(unsigned long top)
++{
++	BUG_ON(nr_fixmaps > 0);
++	hypervisor_virt_start = top;
++	__FIXADDR_TOP = hypervisor_virt_start - 2 * PAGE_SIZE;
++}
++
++void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
++{
++	unsigned long address = __fix_to_virt(idx);
++	pte_t pte;
++
++	if (idx >= __end_of_fixed_addresses) {
++		BUG();
++		return;
++	}
++	switch (idx) {
++	case FIX_WP_TEST:
++	case FIX_VDSO:
++		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
++		break;
++	default:
++		pte = pfn_pte_ma(phys >> PAGE_SHIFT, flags);
++		break;
++	}
++	if (HYPERVISOR_update_va_mapping(address, pte,
++					 UVMF_INVLPG|UVMF_ALL))
++		BUG();
++	nr_fixmaps++;
++}
++
++pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++	if (pte)
++		make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
++	return pte;
++}
++
++static void _pte_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	pte_free(page);
++}
++
++struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pte;
++
++#ifdef CONFIG_HIGHPTE
++	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++#else
++	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++#endif
++	if (pte) {
++		SetPageForeign(pte, _pte_free);
++		init_page_count(pte);
++	}
++	return pte;
++}
++
++void pte_free(struct page *pte)
++{
++	unsigned long pfn = page_to_pfn(pte);
++
++	if (!PageHighMem(pte)) {
++		unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
++
++		if (!pte_write(*virt_to_ptep(va)))
++			if (HYPERVISOR_update_va_mapping(
++				va, pfn_pte(pfn, PAGE_KERNEL), 0))
++				BUG();
++	} else
++		clear_bit(PG_pinned, &pte->flags);
++
++	ClearPageForeign(pte);
++	init_page_count(pte);
++
++	__free_page(pte);
++}
++
++void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags)
++{
++	memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
++}
++
++/*
++ * List of all pgd's needed for non-PAE so it can invalidate entries
++ * in both cached and uncached pgd's; not needed for PAE since the
++ * kernel pmd is shared. If PAE were not to share the pmd a similar
++ * tactic would be needed. This is essentially codepath-based locking
++ * against pageattr.c; it is the unique case in which a valid change
++ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
++ * vmalloc faults work because attached pagetables are never freed.
++ * The locking scheme was chosen on the basis of manfred's
++ * recommendations and having no core impact whatsoever.
++ * -- wli
++ */
++DEFINE_SPINLOCK(pgd_lock);
++struct page *pgd_list;
++
++static inline void pgd_list_add(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++	page->index = (unsigned long)pgd_list;
++	if (pgd_list)
++		set_page_private(pgd_list, (unsigned long)&page->index);
++	pgd_list = page;
++	set_page_private(page, (unsigned long)&pgd_list);
++}
++
++static inline void pgd_list_del(pgd_t *pgd)
++{
++	struct page *next, **pprev, *page = virt_to_page(pgd);
++	next = (struct page *)page->index;
++	pprev = (struct page **)page_private(page);
++	*pprev = next;
++	if (next)
++		set_page_private(next, (unsigned long)pprev);
++}
++
++void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
++{
++	unsigned long flags;
++
++	if (PTRS_PER_PMD > 1) {
++		if (HAVE_SHARED_KERNEL_PMD)
++			clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
++					swapper_pg_dir + USER_PTRS_PER_PGD,
++					KERNEL_PGD_PTRS);
++	} else {
++		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);
++		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++		pgd_list_add(pgd);
++		spin_unlock_irqrestore(&pgd_lock, flags);
++	}
++}
++
++/* never called when PTRS_PER_PMD > 1 */
++void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
++{
++	unsigned long flags; /* can be called from interrupt context */
++
++	spin_lock_irqsave(&pgd_lock, flags);
++	pgd_list_del(pgd);
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	pgd_test_and_unpin(pgd);
++}
++
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++	int i;
++	pgd_t *pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL);
++	pmd_t **pmd;
++	unsigned long flags;
++
++	pgd_test_and_unpin(pgd);
++
++	if (PTRS_PER_PMD == 1 || !pgd)
++		return pgd;
++
++	if (HAVE_SHARED_KERNEL_PMD) {
++		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
++			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++			if (!pmd)
++				goto out_oom;
++			set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
++		}
++		return pgd;
++	}
++
++	/*
++	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
++	 * allocation). We therefore store virtual addresses of pmds as they
++	 * do not change across save/restore, and poke the machine addresses
++	 * into the pgdir under the pgd_lock.
++	 */
++	pmd = kmalloc(PTRS_PER_PGD * sizeof(pmd_t *), GFP_KERNEL);
++	if (!pmd) {
++		kmem_cache_free(pgd_cache, pgd);
++		return NULL;
++	}
++
++	/* Allocate pmds, remember virtual addresses. */
++	for (i = 0; i < PTRS_PER_PGD; ++i) {
++		pmd[i] = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++		if (!pmd[i])
++			goto out_oom;
++	}
++
++	spin_lock_irqsave(&pgd_lock, flags);
++
++	/* Protect against save/restore: move below 4GB under pgd_lock. */
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)) {
++		int rc = xen_create_contiguous_region(
++			(unsigned long)pgd, 0, 32);
++		if (rc) {
++			spin_unlock_irqrestore(&pgd_lock, flags);
++			goto out_oom;
++		}
++	}
++
++	/* Copy kernel pmd contents and write-protect the new pmds. */
++	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);
++		memcpy(pmd[i], kpmd, PAGE_SIZE);
++		make_lowmem_page_readonly(
++			pmd[i], XENFEAT_writable_page_tables);
++	}
++
++	/* It is safe to poke machine addresses of pmds under the pmd_lock. */
++	for (i = 0; i < PTRS_PER_PGD; i++)
++		set_pgd(&pgd[i], __pgd(1 + __pa(pmd[i])));
++
++	/* Ensure this pgd gets picked up and pinned on save/restore. */
++	pgd_list_add(pgd);
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	kfree(pmd);
++
++	return pgd;
++
++out_oom:
++	if (HAVE_SHARED_KERNEL_PMD) {
++		for (i--; i >= 0; i--)
++			kmem_cache_free(pmd_cache,
++					(void *)__va(pgd_val(pgd[i])-1));
++	} else {
++		for (i--; i >= 0; i--)
++			kmem_cache_free(pmd_cache, pmd[i]);
++		kfree(pmd);
++	}
++	kmem_cache_free(pgd_cache, pgd);
++	return NULL;
++}
++
++void pgd_free(pgd_t *pgd)
++{
++	int i;
++
++	/*
++	 * After this the pgd should not be pinned for the duration of this
++	 * function's execution. We should never sleep and thus never race:
++	 *  1. User pmds will not become write-protected under our feet due
++	 *     to a concurrent mm_pin_all().
++	 *  2. The machine addresses in PGD entries will not become invalid
++	 *     due to a concurrent save/restore.
++	 */
++	pgd_test_and_unpin(pgd);
++
++	/* 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) {
++			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);
++				make_lowmem_page_writable(
++					pmd, XENFEAT_writable_page_tables);
++				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
++				kmem_cache_free(pmd_cache, pmd);
++			}
++
++			if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
++				xen_destroy_contiguous_region(
++					(unsigned long)pgd, 0);
++		}
++	}
++
++	/* in the non-PAE case, free_pgtables() clears user pgd entries */
++	kmem_cache_free(pgd_cache, pgd);
++}
++
++void make_lowmem_page_readonly(void *va, unsigned int feature)
++{
++	pte_t *pte;
++	int rc;
++
++	if (xen_feature(feature))
++		return;
++
++	pte = virt_to_ptep(va);
++	rc = HYPERVISOR_update_va_mapping(
++		(unsigned long)va, pte_wrprotect(*pte), 0);
++	BUG_ON(rc);
++}
++
++void make_lowmem_page_writable(void *va, unsigned int feature)
++{
++	pte_t *pte;
++	int rc;
++
++	if (xen_feature(feature))
++		return;
++
++	pte = virt_to_ptep(va);
++	rc = HYPERVISOR_update_va_mapping(
++		(unsigned long)va, pte_mkwrite(*pte), 0);
++	BUG_ON(rc);
++}
++
++void make_page_readonly(void *va, unsigned int feature)
++{
++	pte_t *pte;
++	int rc;
++
++	if (xen_feature(feature))
++		return;
++
++	pte = virt_to_ptep(va);
++	rc = HYPERVISOR_update_va_mapping(
++		(unsigned long)va, pte_wrprotect(*pte), 0);
++	if (rc) /* fallback? */
++		xen_l1_entry_update(pte, pte_wrprotect(*pte));
++	if ((unsigned long)va >= (unsigned long)high_memory) {
++		unsigned long pfn = pte_pfn(*pte);
++#ifdef CONFIG_HIGHMEM
++		if (pfn >= highstart_pfn)
++			kmap_flush_unused(); /* flush stale writable kmaps */
++		else
++#endif
++			make_lowmem_page_readonly(
++				phys_to_virt(pfn << PAGE_SHIFT), feature); 
++	}
++}
++
++void make_page_writable(void *va, unsigned int feature)
++{
++	pte_t *pte;
++	int rc;
++
++	if (xen_feature(feature))
++		return;
++
++	pte = virt_to_ptep(va);
++	rc = HYPERVISOR_update_va_mapping(
++		(unsigned long)va, pte_mkwrite(*pte), 0);
++	if (rc) /* fallback? */
++		xen_l1_entry_update(pte, pte_mkwrite(*pte));
++	if ((unsigned long)va >= (unsigned long)high_memory) {
++		unsigned long pfn = pte_pfn(*pte); 
++#ifdef CONFIG_HIGHMEM
++		if (pfn < highstart_pfn)
++#endif
++			make_lowmem_page_writable(
++				phys_to_virt(pfn << PAGE_SHIFT), feature);
++	}
++}
++
++void make_pages_readonly(void *va, unsigned int nr, unsigned int feature)
++{
++	if (xen_feature(feature))
++		return;
++
++	while (nr-- != 0) {
++		make_page_readonly(va, feature);
++		va = (void *)((unsigned long)va + PAGE_SIZE);
++	}
++}
++
++void make_pages_writable(void *va, unsigned int nr, unsigned int feature)
++{
++	if (xen_feature(feature))
++		return;
++
++	while (nr-- != 0) {
++		make_page_writable(va, feature);
++		va = (void *)((unsigned long)va + PAGE_SIZE);
++	}
++}
++
++static void _pin_lock(struct mm_struct *mm, int lock) {
++	if (lock)
++		spin_lock(&mm->page_table_lock);
++#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
++	/* While mm->page_table_lock protects us against insertions and
++	 * removals of higher level page table pages, it doesn't protect
++	 * against updates of pte-s. Such updates, however, require the
++	 * pte pages to be in consistent state (unpinned+writable or
++	 * pinned+readonly). The pinning and attribute changes, however
++	 * cannot be done atomically, which is why such updates must be
++	 * prevented from happening concurrently.
++	 * Note that no pte lock can ever elsewhere be acquired nesting
++	 * with an already acquired one in the same mm, or with the mm's
++	 * page_table_lock already acquired, as that would break in the
++	 * non-split case (where all these are actually resolving to the
++	 * one page_table_lock). Thus acquiring all of them here is not
++	 * going to result in dead locks, and the order of acquires
++	 * doesn't matter.
++	 */
++	{
++		pgd_t *pgd = mm->pgd;
++		unsigned g;
++
++		for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
++			pud_t *pud;
++			unsigned u;
++
++			if (pgd_none(*pgd))
++				continue;
++			pud = pud_offset(pgd, 0);
++			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++				pmd_t *pmd;
++				unsigned m;
++
++				if (pud_none(*pud))
++					continue;
++				pmd = pmd_offset(pud, 0);
++				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++					spinlock_t *ptl;
++
++					if (pmd_none(*pmd))
++						continue;
++					ptl = pte_lockptr(0, pmd);
++					if (lock)
++						spin_lock(ptl);
++					else
++						spin_unlock(ptl);
++				}
++			}
++		}
++	}
++#endif
++	if (!lock)
++		spin_unlock(&mm->page_table_lock);
++}
++#define pin_lock(mm) _pin_lock(mm, 1)
++#define pin_unlock(mm) _pin_lock(mm, 0)
++
++#define PIN_BATCH 4
++static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
++
++static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
++                                             unsigned int cpu, unsigned seq)
++{
++	unsigned long pfn = page_to_pfn(page);
++
++	if (PageHighMem(page)) {
++		if (pgprot_val(flags) & _PAGE_RW)
++			clear_bit(PG_pinned, &page->flags);
++		else
++			set_bit(PG_pinned, &page->flags);
++	} else {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++				(unsigned long)__va(pfn << PAGE_SHIFT),
++				pfn_pte(pfn, flags), 0);
++		if (unlikely(++seq == PIN_BATCH)) {
++			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++		                                                PIN_BATCH, NULL)))
++				BUG();
++			seq = 0;
++		}
++	}
++
++	return seq;
++}
++
++static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
++{
++	pgd_t *pgd = pgd_base;
++	pud_t *pud;
++	pmd_t *pmd;
++	int    g, u, m;
++	unsigned int cpu, seq;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return;
++
++	cpu = get_cpu();
++
++	for (g = 0, seq = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
++		if (pgd_none(*pgd))
++			continue;
++		pud = pud_offset(pgd, 0);
++		if (PTRS_PER_PUD > 1) /* not folded */
++			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
++		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++			if (pud_none(*pud))
++				continue;
++			pmd = pmd_offset(pud, 0);
++			if (PTRS_PER_PMD > 1) /* not folded */
++				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
++			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++				if (pmd_none(*pmd))
++					continue;
++				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
++			}
++		}
++	}
++
++	if (likely(seq != 0)) {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++			(unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH);
++		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++		                                        seq + 1, NULL)))
++			BUG();
++	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH))
++		BUG();
++
++	put_cpu();
++}
++
++static void __pgd_pin(pgd_t *pgd)
++{
++	pgd_walk(pgd, PAGE_KERNEL_RO);
++	kmap_flush_unused();
++	xen_pgd_pin(__pa(pgd));
++	set_bit(PG_pinned, &virt_to_page(pgd)->flags);
++}
++
++static void __pgd_unpin(pgd_t *pgd)
++{
++	xen_pgd_unpin(__pa(pgd));
++	pgd_walk(pgd, PAGE_KERNEL);
++	clear_bit(PG_pinned, &virt_to_page(pgd)->flags);
++}
++
++static void pgd_test_and_unpin(pgd_t *pgd)
++{
++	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
++		__pgd_unpin(pgd);
++}
++
++void mm_pin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++	pin_lock(mm);
++	__pgd_pin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_unpin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++	pin_lock(mm);
++	__pgd_unpin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_pin_all(void)
++{
++	struct page *page;
++	unsigned long flags;
++
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	/*
++	 * Allow uninterrupted access to the pgd_list. Also protects
++	 * __pgd_pin() by disabling preemption.
++	 * All other CPUs must be at a safe point (e.g., in stop_machine
++	 * or offlined entirely).
++	 */
++	spin_lock_irqsave(&pgd_lock, flags);
++	for (page = pgd_list; page; page = (struct page *)page->index) {
++		if (!test_bit(PG_pinned, &page->flags))
++			__pgd_pin((pgd_t *)page_address(page));
++	}
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++void _arch_dup_mmap(struct mm_struct *mm)
++{
++	if (!test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags))
++		mm_pin(mm);
++}
++
++void _arch_exit_mmap(struct mm_struct *mm)
++{
++	struct task_struct *tsk = current;
++
++	task_lock(tsk);
++
++	/*
++	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
++	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
++	 */
++	if (tsk->active_mm == mm) {
++		tsk->active_mm = &init_mm;
++		atomic_inc(&init_mm.mm_count);
++
++		switch_mm(mm, &init_mm, tsk);
++
++		atomic_dec(&mm->mm_count);
++		BUG_ON(atomic_read(&mm->mm_count) == 0);
++	}
++
++	task_unlock(tsk);
++
++	if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
++	    (atomic_read(&mm->mm_count) == 1) &&
++	    !mm->context.has_foreign_mappings)
++		mm_unpin(mm);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/oprofile/xenoprof.c	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,179 @@
++/**
++ * @file xenoprof.c
++ *
++ * @remark Copyright 2002 OProfile authors
++ * @remark Read the file COPYING
++ *
++ * @author John Levon <levon@movementarian.org>
++ *
++ * Modified by Aravind Menon and Jose Renato Santos for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
++ * x86-specific part
++ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan K.K.
++ */
++
++#include <linux/init.h>
++#include <linux/oprofile.h>
++#include <linux/sched.h>
++#include <asm/pgtable.h>
++
++#include <xen/driver_util.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/xenoprof.h>
++#include <xen/xenoprof.h>
++#include "op_counter.h"
++
++static unsigned int num_events = 0;
++
++void __init xenoprof_arch_init_counter(struct xenoprof_init *init)
++{
++	num_events = init->num_events;
++	/* just in case - make sure we do not overflow event list 
++	   (i.e. counter_config list) */
++	if (num_events > OP_MAX_COUNTER) {
++		num_events = OP_MAX_COUNTER;
++		init->num_events = num_events;
++	}
++}
++
++void xenoprof_arch_counter(void)
++{
++	int i;
++	struct xenoprof_counter counter;
++
++	for (i=0; i<num_events; i++) {
++		counter.ind       = i;
++		counter.count     = (uint64_t)counter_config[i].count;
++		counter.enabled   = (uint32_t)counter_config[i].enabled;
++		counter.event     = (uint32_t)counter_config[i].event;
++		counter.kernel    = (uint32_t)counter_config[i].kernel;
++		counter.user      = (uint32_t)counter_config[i].user;
++		counter.unit_mask = (uint64_t)counter_config[i].unit_mask;
++		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_counter,
++					       &counter));
++	}
++}
++
++void xenoprof_arch_start(void) 
++{
++	/* nothing */
++}
++
++void xenoprof_arch_stop(void)
++{
++	/* nothing */
++}
++
++void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf)
++{
++	if (sbuf->buffer) {
++		vunmap(sbuf->buffer);
++		sbuf->buffer = NULL;
++	}
++}
++
++int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer,
++				    struct xenoprof_shared_buffer * sbuf)
++{
++	int npages, ret;
++	struct vm_struct *area;
++
++	sbuf->buffer = NULL;
++	if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) )
++		return ret;
++
++	npages = (get_buffer->bufsize * get_buffer->nbuf - 1) / PAGE_SIZE + 1;
++
++	area = alloc_vm_area(npages * PAGE_SIZE);
++	if (area == NULL)
++		return -ENOMEM;
++
++	if ( (ret = direct_kernel_remap_pfn_range(
++		      (unsigned long)area->addr,
++		      get_buffer->buf_gmaddr >> PAGE_SHIFT,
++		      npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE),
++		      DOMID_SELF)) ) {
++		vunmap(area->addr);
++		return ret;
++	}
++
++	sbuf->buffer = area->addr;
++	return ret;
++}
++
++int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain,
++			      struct xenoprof_shared_buffer * sbuf)
++{
++	int ret;
++	int npages;
++	struct vm_struct *area;
++	pgprot_t prot = __pgprot(_KERNPG_TABLE);
++
++	sbuf->buffer = NULL;
++	ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain);
++	if (ret)
++		goto out;
++
++	npages = (pdomain->bufsize * pdomain->nbuf - 1) / PAGE_SIZE + 1;
++
++	area = alloc_vm_area(npages * PAGE_SIZE);
++	if (area == NULL) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	ret = direct_kernel_remap_pfn_range(
++		(unsigned long)area->addr,
++		pdomain->buf_gmaddr >> PAGE_SHIFT,
++		npages * PAGE_SIZE, prot, DOMID_SELF);
++	if (ret) {
++		vunmap(area->addr);
++		goto out;
++	}
++	sbuf->buffer = area->addr;
++
++out:
++	return ret;
++}
++
++struct op_counter_config counter_config[OP_MAX_COUNTER];
++
++int xenoprof_create_files(struct super_block * sb, struct dentry * root)
++{
++	unsigned int i;
++
++	for (i = 0; i < num_events; ++i) {
++		struct dentry * dir;
++		char buf[2];
++ 
++		snprintf(buf, 2, "%d", i);
++		dir = oprofilefs_mkdir(sb, root, buf);
++		oprofilefs_create_ulong(sb, dir, "enabled",
++					&counter_config[i].enabled);
++		oprofilefs_create_ulong(sb, dir, "event",
++					&counter_config[i].event);
++		oprofilefs_create_ulong(sb, dir, "count",
++					&counter_config[i].count);
++		oprofilefs_create_ulong(sb, dir, "unit_mask",
++					&counter_config[i].unit_mask);
++		oprofilefs_create_ulong(sb, dir, "kernel",
++					&counter_config[i].kernel);
++		oprofilefs_create_ulong(sb, dir, "user",
++					&counter_config[i].user);
++	}
++
++	return 0;
++}
++
++int __init oprofile_arch_init(struct oprofile_operations * ops)
++{
++	return xenoprofile_init(ops);
++}
++
++void oprofile_arch_exit(void)
++{
++	xenoprofile_exit();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2008-03-06 08:54:32.000000000 +0100
+@@ -0,0 +1,1211 @@
++/*
++ *	Low-Level PCI Support for PC -- Routing of Interrupts
++ *
++ *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
++ */
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/dmi.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/io_apic.h>
++#include <linux/irq.h>
++#include <linux/acpi.h>
++
++#include "pci.h"
++
++#define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
++#define PIRQ_VERSION 0x0100
++
++static int broken_hp_bios_irq9;
++static int acer_tm360_irqrouting;
++
++static struct irq_routing_table *pirq_table;
++
++static int pirq_enable_irq(struct pci_dev *dev);
++
++/*
++ * Never use: 0, 1, 2 (timer, keyboard, and cascade)
++ * Avoid using: 13, 14 and 15 (FP error and IDE).
++ * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
++ */
++unsigned int pcibios_irq_mask = 0xfff8;
++
++static int pirq_penalty[16] = {
++	1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
++	0, 0, 0, 0, 1000, 100000, 100000, 100000
++};
++
++struct irq_router {
++	char *name;
++	u16 vendor, device;
++	int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
++	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
++};
++
++struct irq_router_handler {
++	u16 vendor;
++	int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
++};
++
++int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
++void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
++
++/*
++ *  Check passed address for the PCI IRQ Routing Table signature
++ *  and perform checksum verification.
++ */
++
++static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
++{
++	struct irq_routing_table *rt;
++	int i;
++	u8 sum;
++
++	rt = (struct irq_routing_table *) addr;
++	if (rt->signature != PIRQ_SIGNATURE ||
++	    rt->version != PIRQ_VERSION ||
++	    rt->size % 16 ||
++	    rt->size < sizeof(struct irq_routing_table))
++		return NULL;
++	sum = 0;
++	for (i=0; i < rt->size; i++)
++		sum += addr[i];
++	if (!sum) {
++		DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
++		return rt;
++	}
++	return NULL;
++}
++
++
++
++/*
++ *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
++ */
++
++static struct irq_routing_table * __init pirq_find_routing_table(void)
++{
++	u8 *addr;
++	struct irq_routing_table *rt;
++
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return NULL;
++#endif
++	if (pirq_table_addr) {
++		rt = pirq_check_routing_table((u8 *) isa_bus_to_virt(pirq_table_addr));
++		if (rt)
++			return rt;
++		printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
++	}
++	for(addr = (u8 *) isa_bus_to_virt(0xf0000); addr < (u8 *) isa_bus_to_virt(0x100000); addr += 16) {
++		rt = pirq_check_routing_table(addr);
++		if (rt)
++			return rt;
++	}
++	return NULL;
++}
++
++/*
++ *  If we have a IRQ routing table, use it to search for peer host
++ *  bridges.  It's a gross hack, but since there are no other known
++ *  ways how to get a list of buses, we have to go this way.
++ */
++
++static void __init pirq_peer_trick(void)
++{
++	struct irq_routing_table *rt = pirq_table;
++	u8 busmap[256];
++	int i;
++	struct irq_info *e;
++
++	memset(busmap, 0, sizeof(busmap));
++	for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
++		e = &rt->slots[i];
++#ifdef DEBUG
++		{
++			int j;
++			DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
++			for(j=0; j<4; j++)
++				DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
++			DBG("\n");
++		}
++#endif
++		busmap[e->bus] = 1;
++	}
++	for(i = 1; i < 256; i++) {
++		if (!busmap[i] || pci_find_bus(0, i))
++			continue;
++		if (pci_scan_bus(i, &pci_root_ops, NULL))
++			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
++	}
++	pcibios_last_bus = -1;
++}
++
++/*
++ *  Code for querying and setting of IRQ routes on various interrupt routers.
++ */
++
++void eisa_set_level_irq(unsigned int irq)
++{
++	unsigned char mask = 1 << (irq & 7);
++	unsigned int port = 0x4d0 + (irq >> 3);
++	unsigned char val;
++	static u16 eisa_irq_mask;
++
++	if (irq >= 16 || (1 << irq) & eisa_irq_mask)
++		return;
++
++	eisa_irq_mask |= (1 << irq);
++	printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq);
++	val = inb(port);
++	if (!(val & mask)) {
++		DBG(KERN_DEBUG " -> edge");
++		outb(val | mask, port);
++	}
++}
++
++/*
++ * Common IRQ routing practice: nybbles in config space,
++ * offset by some magic constant.
++ */
++static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
++{
++	u8 x;
++	unsigned reg = offset + (nr >> 1);
++
++	pci_read_config_byte(router, reg, &x);
++	return (nr & 1) ? (x >> 4) : (x & 0xf);
++}
++
++static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
++{
++	u8 x;
++	unsigned reg = offset + (nr >> 1);
++
++	pci_read_config_byte(router, reg, &x);
++	x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
++	pci_write_config_byte(router, reg, x);
++}
++
++/*
++ * ALI pirq entries are damn ugly, and completely undocumented.
++ * This has been figured out from pirq tables, and it's not a pretty
++ * picture.
++ */
++static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
++
++	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
++}
++
++static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
++	unsigned int val = irqmap[irq];
++		
++	if (val) {
++		write_config_nybble(router, 0x48, pirq-1, val);
++		return 1;
++	}
++	return 0;
++}
++
++/*
++ * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
++ * just a pointer to the config space.
++ */
++static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	u8 x;
++
++	pci_read_config_byte(router, pirq, &x);
++	return (x < 16) ? x : 0;
++}
++
++static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	pci_write_config_byte(router, pirq, irq);
++	return 1;
++}
++
++/*
++ * The VIA pirq rules are nibble-based, like ALI,
++ * but without the ugly irq number munging.
++ * However, PIRQD is in the upper instead of lower 4 bits.
++ */
++static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
++}
++
++static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
++	return 1;
++}
++
++/*
++ * The VIA pirq rules are nibble-based, like ALI,
++ * but without the ugly irq number munging.
++ * However, for 82C586, nibble map is different .
++ */
++static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	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[5] = { 3, 2, 5, 1, 1 };
++	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
++	return 1;
++}
++
++/*
++ * ITE 8330G pirq rules are nibble-based
++ * FIXME: pirqmap may be { 1, 0, 3, 2 },
++ * 	  2+3 are both mapped to irq 9 on my system
++ */
++static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
++	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
++}
++
++static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
++	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
++	return 1;
++}
++
++/*
++ * OPTI: high four bits are nibble pointer..
++ * I wonder what the low bits do?
++ */
++static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	return read_config_nybble(router, 0xb8, pirq >> 4);
++}
++
++static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	write_config_nybble(router, 0xb8, pirq >> 4, irq);
++	return 1;
++}
++
++/*
++ * Cyrix: nibble offset 0x5C
++ * 0x5C bits 7:4 is INTB bits 3:0 is INTA 
++ * 0x5D bits 7:4 is INTD bits 3:0 is INTC
++ */
++static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	return read_config_nybble(router, 0x5C, (pirq-1)^1);
++}
++
++static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
++	return 1;
++}
++
++/*
++ *	PIRQ routing for SiS 85C503 router used in several SiS chipsets.
++ *	We have to deal with the following issues here:
++ *	- vendors have different ideas about the meaning of link values
++ *	- some onboard devices (integrated in the chipset) have special
++ *	  links and are thus routed differently (i.e. not via PCI INTA-INTD)
++ *	- different revision of the router have a different layout for
++ *	  the routing registers, particularly for the onchip devices
++ *
++ *	For all routing registers the common thing is we have one byte
++ *	per routeable link which is defined as:
++ *		 bit 7      IRQ mapping enabled (0) or disabled (1)
++ *		 bits [6:4] reserved (sometimes used for onchip devices)
++ *		 bits [3:0] IRQ to map to
++ *		     allowed: 3-7, 9-12, 14-15
++ *		     reserved: 0, 1, 2, 8, 13
++ *
++ *	The config-space registers located at 0x41/0x42/0x43/0x44 are
++ *	always used to route the normal PCI INT A/B/C/D respectively.
++ *	Apparently there are systems implementing PCI routing table using
++ *	link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
++ *	We try our best to handle both link mappings.
++ *	
++ *	Currently (2003-05-21) it appears most SiS chipsets follow the
++ *	definition of routing registers from the SiS-5595 southbridge.
++ *	According to the SiS 5595 datasheets the revision id's of the
++ *	router (ISA-bridge) should be 0x01 or 0xb0.
++ *
++ *	Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
++ *	Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
++ *	They seem to work with the current routing code. However there is
++ *	some concern because of the two USB-OHCI HCs (original SiS 5595
++ *	had only one). YMMV.
++ *
++ *	Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
++ *
++ *	0x61:	IDEIRQ:
++ *		bits [6:5] must be written 01
++ *		bit 4 channel-select primary (0), secondary (1)
++ *
++ *	0x62:	USBIRQ:
++ *		bit 6 OHCI function disabled (0), enabled (1)
++ *	
++ *	0x6a:	ACPI/SCI IRQ: bits 4-6 reserved
++ *
++ *	0x7e:	Data Acq. Module IRQ - bits 4-6 reserved
++ *
++ *	We support USBIRQ (in addition to INTA-INTD) and keep the
++ *	IDE, ACPI and DAQ routing untouched as set by the BIOS.
++ *
++ *	Currently the only reported exception is the new SiS 65x chipset
++ *	which includes the SiS 69x southbridge. Here we have the 85C503
++ *	router revision 0x04 and there are changes in the register layout
++ *	mostly related to the different USB HCs with USB 2.0 support.
++ *
++ *	Onchip routing for router rev-id 0x04 (try-and-error observation)
++ *
++ *	0x60/0x61/0x62/0x63:	1xEHCI and 3xOHCI (companion) USB-HCs
++ *				bit 6-4 are probably unused, not like 5595
++ */
++
++#define PIRQ_SIS_IRQ_MASK	0x0f
++#define PIRQ_SIS_IRQ_DISABLE	0x80
++#define PIRQ_SIS_USB_ENABLE	0x40
++
++static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	u8 x;
++	int reg;
++
++	reg = pirq;
++	if (reg >= 0x01 && reg <= 0x04)
++		reg += 0x40;
++	pci_read_config_byte(router, reg, &x);
++	return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
++}
++
++static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	u8 x;
++	int reg;
++
++	reg = pirq;
++	if (reg >= 0x01 && reg <= 0x04)
++		reg += 0x40;
++	pci_read_config_byte(router, reg, &x);
++	x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE);
++	x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE;
++	pci_write_config_byte(router, reg, x);
++	return 1;
++}
++
++
++/*
++ * VLSI: nibble offset 0x74 - educated guess due to routing table and
++ *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
++ *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
++ *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
++ *       for the busbridge to the docking station.
++ */
++
++static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	if (pirq > 8) {
++		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
++		return 0;
++	}
++	return read_config_nybble(router, 0x74, pirq-1);
++}
++
++static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	if (pirq > 8) {
++		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
++		return 0;
++	}
++	write_config_nybble(router, 0x74, pirq-1, irq);
++	return 1;
++}
++
++/*
++ * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
++ * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
++ * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
++ * register is a straight binary coding of desired PIC IRQ (low nibble).
++ *
++ * The 'link' value in the PIRQ table is already in the correct format
++ * for the Index register.  There are some special index values:
++ * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
++ * and 0x03 for SMBus.
++ */
++static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	outb_p(pirq, 0xc00);
++	return inb(0xc01) & 0xf;
++}
++
++static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	outb_p(pirq, 0xc00);
++	outb_p(irq, 0xc01);
++	return 1;
++}
++
++/* Support for AMD756 PCI IRQ Routing
++ * Jhon H. Caicedo <jhcaiced@osso.org.co>
++ * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
++ * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
++ * The AMD756 pirq rules are nibble-based
++ * offset 0x56 0-3 PIRQA  4-7  PIRQB
++ * offset 0x57 0-3 PIRQC  4-7  PIRQD
++ */
++static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	u8 irq;
++	irq = 0;
++	if (pirq <= 4)
++	{
++		irq = read_config_nybble(router, 0x56, pirq - 1);
++	}
++	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
++		dev->vendor, dev->device, pirq, irq);
++	return irq;
++}
++
++static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", 
++		dev->vendor, dev->device, pirq, irq);
++	if (pirq <= 4)
++	{
++		write_config_nybble(router, 0x56, pirq - 1, irq);
++	}
++	return 1;
++}
++
++#ifdef CONFIG_PCI_BIOS
++
++static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
++{
++	struct pci_dev *bridge;
++	int pin = pci_get_interrupt_pin(dev, &bridge);
++	return pcibios_set_irq_routing(bridge, pin, irq);
++}
++
++#endif
++
++static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	static struct pci_device_id __initdata pirq_440gx[] = {
++		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
++		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
++		{ },
++	};
++
++	/* 440GX has a proprietary PIRQ router -- don't use it */
++	if (pci_dev_present(pirq_440gx))
++		return 0;
++
++	switch(device)
++	{
++		case PCI_DEVICE_ID_INTEL_82371FB_0:
++		case PCI_DEVICE_ID_INTEL_82371SB_0:
++		case PCI_DEVICE_ID_INTEL_82371AB_0:
++		case PCI_DEVICE_ID_INTEL_82371MX:
++		case PCI_DEVICE_ID_INTEL_82443MX_0:
++		case PCI_DEVICE_ID_INTEL_82801AA_0:
++		case PCI_DEVICE_ID_INTEL_82801AB_0:
++		case PCI_DEVICE_ID_INTEL_82801BA_0:
++		case PCI_DEVICE_ID_INTEL_82801BA_10:
++		case PCI_DEVICE_ID_INTEL_82801CA_0:
++		case PCI_DEVICE_ID_INTEL_82801CA_12:
++		case PCI_DEVICE_ID_INTEL_82801DB_0:
++		case PCI_DEVICE_ID_INTEL_82801E_0:
++		case PCI_DEVICE_ID_INTEL_82801EB_0:
++		case PCI_DEVICE_ID_INTEL_ESB_1:
++		case PCI_DEVICE_ID_INTEL_ICH6_0:
++		case PCI_DEVICE_ID_INTEL_ICH6_1:
++		case PCI_DEVICE_ID_INTEL_ICH7_0:
++		case PCI_DEVICE_ID_INTEL_ICH7_1:
++		case PCI_DEVICE_ID_INTEL_ICH7_30:
++		case PCI_DEVICE_ID_INTEL_ICH7_31:
++		case PCI_DEVICE_ID_INTEL_ESB2_0:
++		case PCI_DEVICE_ID_INTEL_ICH8_0:
++		case PCI_DEVICE_ID_INTEL_ICH8_1:
++		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;
++			return 1;
++	}
++	return 0;
++}
++
++static __init int via_router_probe(struct irq_router *r,
++				struct pci_dev *router, u16 device)
++{
++	/* FIXME: We should move some of the quirk fixup stuff here */
++
++	/*
++	 * work arounds for some buggy BIOSes
++	 */
++	if (device == PCI_DEVICE_ID_VIA_82C586_0) {
++		switch(router->device) {
++		case PCI_DEVICE_ID_VIA_82C686:
++			/*
++			 * Asus k7m bios wrongly reports 82C686A
++			 * as 586-compatible
++			 */
++			device = PCI_DEVICE_ID_VIA_82C686;
++			break;
++		case PCI_DEVICE_ID_VIA_8235:
++			/**
++			 * Asus a7v-x bios wrongly reports 8235
++			 * as 586-compatible
++			 */
++			device = PCI_DEVICE_ID_VIA_8235;
++			break;
++		}
++	}
++
++	switch(device) {
++	case PCI_DEVICE_ID_VIA_82C586_0:
++		r->name = "VIA";
++		r->get = pirq_via586_get;
++		r->set = pirq_via586_set;
++		return 1;
++	case PCI_DEVICE_ID_VIA_82C596:
++	case PCI_DEVICE_ID_VIA_82C686:
++	case PCI_DEVICE_ID_VIA_8231:
++	case PCI_DEVICE_ID_VIA_8233A:
++	case PCI_DEVICE_ID_VIA_8235:
++	case PCI_DEVICE_ID_VIA_8237:
++		/* FIXME: add new ones for 8233/5 */
++		r->name = "VIA";
++		r->get = pirq_via_get;
++		r->set = pirq_via_set;
++		return 1;
++	}
++	return 0;
++}
++
++static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_VLSI_82C534:
++			r->name = "VLSI 82C534";
++			r->get = pirq_vlsi_get;
++			r->set = pirq_vlsi_set;
++			return 1;
++	}
++	return 0;
++}
++
++
++static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_SERVERWORKS_OSB4:
++		case PCI_DEVICE_ID_SERVERWORKS_CSB5:
++			r->name = "ServerWorks";
++			r->get = pirq_serverworks_get;
++			r->set = pirq_serverworks_set;
++			return 1;
++	}
++	return 0;
++}
++
++static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	if (device != PCI_DEVICE_ID_SI_503)
++		return 0;
++		
++	r->name = "SIS";
++	r->get = pirq_sis_get;
++	r->set = pirq_sis_set;
++	return 1;
++}
++
++static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_CYRIX_5520:
++			r->name = "NatSemi";
++			r->get = pirq_cyrix_get;
++			r->set = pirq_cyrix_set;
++			return 1;
++	}
++	return 0;
++}
++
++static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_OPTI_82C700:
++			r->name = "OPTI";
++			r->get = pirq_opti_get;
++			r->set = pirq_opti_set;
++			return 1;
++	}
++	return 0;
++}
++
++static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_ITE_IT8330G_0:
++			r->name = "ITE";
++			r->get = pirq_ite_get;
++			r->set = pirq_ite_set;
++			return 1;
++	}
++	return 0;
++}
++
++static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++	case PCI_DEVICE_ID_AL_M1533:
++	case PCI_DEVICE_ID_AL_M1563:
++		printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
++		r->name = "ALI";
++		r->get = pirq_ali_get;
++		r->set = pirq_ali_set;
++		return 1;
++	}
++	return 0;
++}
++
++static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch(device)
++	{
++		case PCI_DEVICE_ID_AMD_VIPER_740B:
++			r->name = "AMD756";
++			break;
++		case PCI_DEVICE_ID_AMD_VIPER_7413:
++			r->name = "AMD766";
++			break;
++		case PCI_DEVICE_ID_AMD_VIPER_7443:
++			r->name = "AMD768";
++			break;
++		default:
++			return 0;
++	}
++	r->get = pirq_amd756_get;
++	r->set = pirq_amd756_set;
++	return 1;
++}
++		
++static __initdata struct irq_router_handler pirq_routers[] = {
++	{ PCI_VENDOR_ID_INTEL, intel_router_probe },
++	{ PCI_VENDOR_ID_AL, ali_router_probe },
++	{ PCI_VENDOR_ID_ITE, ite_router_probe },
++	{ PCI_VENDOR_ID_VIA, via_router_probe },
++	{ PCI_VENDOR_ID_OPTI, opti_router_probe },
++	{ PCI_VENDOR_ID_SI, sis_router_probe },
++	{ PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
++	{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
++	{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
++	{ PCI_VENDOR_ID_AMD, amd_router_probe },
++	/* Someone with docs needs to add the ATI Radeon IGP */
++	{ 0, NULL }
++};
++static struct irq_router pirq_router;
++static struct pci_dev *pirq_router_dev;
++
++
++/*
++ *	FIXME: should we have an option to say "generic for
++ *	chipset" ?
++ */
++ 
++static void __init pirq_find_router(struct irq_router *r)
++{
++	struct irq_routing_table *rt = pirq_table;
++	struct irq_router_handler *h;
++
++#ifdef CONFIG_PCI_BIOS
++	if (!rt->signature) {
++		printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
++		r->set = pirq_bios_set;
++		r->name = "BIOS";
++		return;
++	}
++#endif
++
++	/* Default unless a driver reloads it */
++	r->name = "default";
++	r->get = NULL;
++	r->set = NULL;
++	
++	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
++	    rt->rtr_vendor, rt->rtr_device);
++
++	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
++	if (!pirq_router_dev) {
++		DBG(KERN_DEBUG "PCI: Interrupt router not found at "
++			"%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
++		return;
++	}
++
++	for( h = pirq_routers; h->vendor; h++) {
++		/* First look for a router match */
++		if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device))
++			break;
++		/* Fall back to a device match */
++		if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device))
++			break;
++	}
++	printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
++		pirq_router.name,
++		pirq_router_dev->vendor,
++		pirq_router_dev->device,
++		pci_name(pirq_router_dev));
++}
++
++static struct irq_info *pirq_get_info(struct pci_dev *dev)
++{
++	struct irq_routing_table *rt = pirq_table;
++	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
++	struct irq_info *info;
++
++	for (info = rt->slots; entries--; info++)
++		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
++			return info;
++	return NULL;
++}
++
++static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
++{
++	u8 pin;
++	struct irq_info *info;
++	int i, pirq, newirq;
++	int irq = 0;
++	u32 mask;
++	struct irq_router *r = &pirq_router;
++	struct pci_dev *dev2 = NULL;
++	char *msg = NULL;
++
++	/* Find IRQ pin */
++	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
++	if (!pin) {
++		DBG(KERN_DEBUG " -> no interrupt pin\n");
++		return 0;
++	}
++	pin = pin - 1;
++
++	/* Find IRQ routing entry */
++
++	if (!pirq_table)
++		return 0;
++	
++	DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
++	info = pirq_get_info(dev);
++	if (!info) {
++		DBG(" -> not found in routing table\n" KERN_DEBUG);
++		return 0;
++	}
++	pirq = info->irq[pin].link;
++	mask = info->irq[pin].bitmap;
++	if (!pirq) {
++		DBG(" -> not routed\n" KERN_DEBUG);
++		return 0;
++	}
++	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
++	mask &= pcibios_irq_mask;
++
++	/* Work around broken HP Pavilion Notebooks which assign USB to
++	   IRQ 9 even though it is actually wired to IRQ 11 */
++
++	if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
++		dev->irq = 11;
++		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
++		r->set(pirq_router_dev, dev, pirq, 11);
++	}
++
++	/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
++	if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
++		pirq = 0x68;
++		mask = 0x400;
++		dev->irq = r->get(pirq_router_dev, dev, pirq);
++		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
++	}
++
++	/*
++	 * Find the best IRQ to assign: use the one
++	 * reported by the device if possible.
++	 */
++	newirq = dev->irq;
++	if (newirq && !((1 << newirq) & mask)) {
++		if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
++		else printk("\n" KERN_WARNING
++			"PCI: IRQ %i for device %s doesn't match PIRQ mask "
++			"- try pci=usepirqmask\n" KERN_DEBUG, newirq,
++			pci_name(dev));
++	}
++	if (!newirq && assign) {
++		for (i = 0; i < 16; i++) {
++			if (!(mask & (1 << i)))
++				continue;
++			if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED))
++				newirq = i;
++		}
++	}
++	DBG(" -> newirq=%d", newirq);
++
++	/* Check if it is hardcoded */
++	if ((pirq & 0xf0) == 0xf0) {
++		irq = pirq & 0xf;
++		DBG(" -> hardcoded IRQ %d\n", irq);
++		msg = "Hardcoded";
++	} else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
++	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
++		DBG(" -> got IRQ %d\n", irq);
++		msg = "Found";
++		eisa_set_level_irq(irq);
++	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
++		DBG(" -> assigning IRQ %d", newirq);
++		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
++			eisa_set_level_irq(newirq);
++			DBG(" ... OK\n");
++			msg = "Assigned";
++			irq = newirq;
++		}
++	}
++
++	if (!irq) {
++		DBG(" ... failed\n");
++		if (newirq && mask == (1 << newirq)) {
++			msg = "Guessed";
++			irq = newirq;
++		} else
++			return 0;
++	}
++	printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev));
++
++	/* Update IRQ for all devices with the same pirq value */
++	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
++		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
++		if (!pin)
++			continue;
++		pin--;
++		info = pirq_get_info(dev2);
++		if (!info)
++			continue;
++		if (info->irq[pin].link == pirq) {
++			/* We refuse to override the dev->irq information. Give a warning! */
++		    	if ( dev2->irq && dev2->irq != irq && \
++			(!(pci_probe & PCI_USE_PIRQ_MASK) || \
++			((1 << dev2->irq) & mask)) ) {
++#ifndef CONFIG_PCI_MSI
++		    		printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
++				       pci_name(dev2), dev2->irq, irq);
++#endif
++		    		continue;
++		    	}
++			dev2->irq = irq;
++			pirq_penalty[irq]++;
++			if (dev != dev2)
++				printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2));
++		}
++	}
++	return 1;
++}
++
++static void __init pcibios_fixup_irqs(void)
++{
++	struct pci_dev *dev = NULL;
++	u8 pin;
++
++	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
++	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
++		/*
++		 * If the BIOS has set an out of range IRQ number, just ignore it.
++		 * Also keep track of which IRQ's are already in use.
++		 */
++		if (dev->irq >= 16) {
++			DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
++			dev->irq = 0;
++		}
++		/* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
++		if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
++			pirq_penalty[dev->irq] = 0;
++		pirq_penalty[dev->irq]++;
++	}
++
++	dev = NULL;
++	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
++		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
++#ifdef CONFIG_X86_IO_APIC
++		/*
++		 * Recalculate IRQ numbers if we use the I/O APIC.
++		 */
++		if (io_apic_assign_pci_irqs)
++		{
++			int irq;
++
++			if (pin) {
++				pin--;		/* interrupt pins are numbered starting from 1 */
++				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
++	/*
++	 * Busses behind bridges are typically not listed in the MP-table.
++	 * In this case we have to look up the IRQ based on the parent bus,
++	 * parent slot, and pin number. The SMP code detects such bridged
++	 * busses itself so we should get into this branch reliably.
++	 */
++				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
++					struct pci_dev * bridge = dev->bus->self;
++
++					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
++					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
++							PCI_SLOT(bridge->devfn), pin);
++					if (irq >= 0)
++						printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
++							pci_name(bridge), 'A' + pin, irq);
++				}
++				if (irq >= 0) {
++					if (use_pci_vector() &&
++						!platform_legacy_irq(irq))
++						irq = IO_APIC_VECTOR(irq);
++
++					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
++						pci_name(dev), 'A' + pin, irq);
++					dev->irq = irq;
++				}
++			}
++		}
++#endif
++		/*
++		 * Still no IRQ? Try to lookup one...
++		 */
++		if (pin && !dev->irq)
++			pcibios_lookup_irq(dev, 0);
++	}
++}
++
++/*
++ * Work around broken HP Pavilion Notebooks which assign USB to
++ * IRQ 9 even though it is actually wired to IRQ 11
++ */
++static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
++{
++	if (!broken_hp_bios_irq9) {
++		broken_hp_bios_irq9 = 1;
++		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
++	}
++	return 0;
++}
++
++/*
++ * Work around broken Acer TravelMate 360 Notebooks which assign
++ * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
++ */
++static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d)
++{
++	if (!acer_tm360_irqrouting) {
++		acer_tm360_irqrouting = 1;
++		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
++	}
++	return 0;
++}
++
++static struct dmi_system_id __initdata pciirq_dmi_table[] = {
++	{
++		.callback = fix_broken_hp_bios_irq9,
++		.ident = "HP Pavilion N5400 Series Laptop",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
++			DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
++			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
++			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
++		},
++	},
++	{
++		.callback = fix_acer_tm360_irqrouting,
++		.ident = "Acer TravelMate 36x Laptop",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
++		},
++	},
++	{ }
++};
++
++static int __init pcibios_irq_init(void)
++{
++	DBG(KERN_DEBUG "PCI: IRQ init\n");
++
++	if (pcibios_enable_irq || raw_pci_ops == NULL)
++		return 0;
++
++	dmi_check_system(pciirq_dmi_table);
++
++	pirq_table = pirq_find_routing_table();
++
++#ifdef CONFIG_PCI_BIOS
++	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
++		pirq_table = pcibios_get_irq_routing_table();
++#endif
++	if (pirq_table) {
++		pirq_peer_trick();
++		pirq_find_router(&pirq_router);
++		if (pirq_table->exclusive_irqs) {
++			int i;
++			for (i=0; i<16; i++)
++				if (!(pirq_table->exclusive_irqs & (1 << i)))
++					pirq_penalty[i] += 100;
++		}
++		/* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
++		if (io_apic_assign_pci_irqs)
++			pirq_table = NULL;
++	}
++
++	pcibios_enable_irq = pirq_enable_irq;
++
++	pcibios_fixup_irqs();
++	return 0;
++}
++
++subsys_initcall(pcibios_irq_init);
++
++
++static void pirq_penalize_isa_irq(int irq, int active)
++{
++	/*
++	 *  If any ISAPnP device reports an IRQ in its list of possible
++	 *  IRQ's, we try to avoid assigning it to PCI devices.
++	 */
++	if (irq < 16) {
++		if (active)
++			pirq_penalty[irq] += 1000;
++		else
++			pirq_penalty[irq] += 100;
++	}
++}
++
++void pcibios_penalize_isa_irq(int irq, int active)
++{
++#ifdef CONFIG_ACPI
++	if (!acpi_noirq)
++		acpi_penalize_isa_irq(irq, active);
++	else
++#endif
++		pirq_penalize_isa_irq(irq, active);
++}
++
++static int pirq_enable_irq(struct pci_dev *dev)
++{
++	u8 pin;
++	struct pci_dev *temp_dev;
++
++	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
++	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
++		char *msg = "";
++
++		pin--;		/* interrupt pins are numbered starting from 1 */
++
++		if (io_apic_assign_pci_irqs) {
++			int irq;
++
++			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
++			/*
++			 * Busses behind bridges are typically not listed in the MP-table.
++			 * In this case we have to look up the IRQ based on the parent bus,
++			 * parent slot, and pin number. The SMP code detects such bridged
++			 * busses itself so we should get into this branch reliably.
++			 */
++			temp_dev = dev;
++			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
++				struct pci_dev * bridge = dev->bus->self;
++
++				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
++				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
++						PCI_SLOT(bridge->devfn), pin);
++				if (irq >= 0)
++					printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
++						pci_name(bridge), 'A' + pin, irq);
++				dev = bridge;
++			}
++			dev = temp_dev;
++			if (irq >= 0) {
++#ifdef CONFIG_PCI_MSI
++				if (!platform_legacy_irq(irq))
++					irq = IO_APIC_VECTOR(irq);
++#endif
++				printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
++					pci_name(dev), 'A' + pin, irq);
++				dev->irq = irq;
++				return 0;
++			} else
++				msg = " Probably buggy MP table.";
++		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
++			msg = "";
++		else
++			msg = " Please try using pci=biosirq.";
++
++		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
++		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
++			return 0;
++
++		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
++		       'A' + pin, pci_name(dev), msg);
++	}
++	return 0;
++}
++
++int pci_vector_resources(int last, int nr_released)
++{
++	int count = nr_released;
++
++	int next = last;
++	int offset = (last % 8);
++
++	while (next < FIRST_SYSTEM_VECTOR) {
++		next += 8;
++#ifdef CONFIG_X86_64
++		if (next == IA32_SYSCALL_VECTOR)
++			continue;
++#else
++		if (next == SYSCALL_VECTOR)
++			continue;
++#endif
++		count++;
++		if (next >= FIRST_SYSTEM_VECTOR) {
++			if (offset%8) {
++				next = FIRST_DEVICE_VECTOR + offset;
++				offset++;
++				continue;
++			}
++			count--;
++		}
++	}
++
++	return count;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/pci/pcifront.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,57 @@
++/*
++ * PCI Frontend Stub - puts some "dummy" functions in to the Linux x86 PCI core
++ *                     to support the Xen PCI Frontend's operation
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <asm/acpi.h>
++#include <xen/evtchn.h>
++#include "pci.h"
++
++static int pcifront_enable_irq(struct pci_dev *dev)
++{
++	u8 irq;
++	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
++	evtchn_register_pirq(irq);
++	dev->irq = irq;
++
++	return 0;
++}
++
++extern u8 pci_cache_line_size;
++
++static int __init pcifront_x86_stub_init(void)
++{
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++
++	/* Only install our method if we haven't found real hardware already */
++	if (raw_pci_ops)
++		return 0;
++
++	printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
++
++	/* Copied from arch/i386/pci/common.c */
++	pci_cache_line_size = 32 >> 2;
++	if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
++		pci_cache_line_size = 64 >> 2;	/* K7 & K8 */
++	else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
++		pci_cache_line_size = 128 >> 2;	/* P4 */
++
++	/* On x86, we need to disable the normal IRQ routing table and
++	 * just ask the backend
++	 */
++	pcibios_enable_irq = pcifront_enable_irq;
++	pcibios_disable_irq = NULL;
++
++#ifdef CONFIG_ACPI
++	/* Keep ACPI out of the picture */
++	acpi_noirq = 1;
++#endif
++
++	return 0;
++}
++
++arch_initcall(pcifront_x86_stub_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,666 @@
++/*
++ * Compatibility mode system call entry point for x86-64. 
++ * 		
++ * Copyright 2000-2002 Andi Kleen, SuSE Labs.
++ */		 
++
++#include <asm/dwarf2.h>
++#include <asm/calling.h>
++#include <asm/asm-offsets.h>
++#include <asm/current.h>
++#include <asm/errno.h>
++#include <asm/ia32_unistd.h>	
++#include <asm/thread_info.h>	
++#include <asm/segment.h>
++#include <asm/vsyscall32.h>
++#include <asm/irqflags.h>
++#include <linux/linkage.h>
++
++#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
++
++	.macro IA32_ARG_FIXUP noebp=0
++	movl	%edi,%r8d
++	.if \noebp
++	.else
++	movl	%ebp,%r9d
++	.endif
++	xchg	%ecx,%esi
++	movl	%ebx,%edi
++	movl	%edx,%edx	/* zero extension */
++	.endm 
++
++	/* clobbers %eax */	
++	.macro  CLEAR_RREGS
++	xorl 	%eax,%eax
++	movq	%rax,R11(%rsp)
++	movq	%rax,R10(%rsp)
++	movq	%rax,R9(%rsp)
++	movq	%rax,R8(%rsp)
++	.endm
++
++	.macro LOAD_ARGS32 offset
++	movl \offset(%rsp),%r11d
++	movl \offset+8(%rsp),%r10d
++	movl \offset+16(%rsp),%r9d
++	movl \offset+24(%rsp),%r8d
++	movl \offset+40(%rsp),%ecx
++	movl \offset+48(%rsp),%edx
++	movl \offset+56(%rsp),%esi
++	movl \offset+64(%rsp),%edi
++	movl \offset+72(%rsp),%eax
++	.endm
++
++	.macro CFI_STARTPROC32 simple
++	CFI_STARTPROC	\simple
++	CFI_UNDEFINED	r8
++	CFI_UNDEFINED	r9
++	CFI_UNDEFINED	r10
++	CFI_UNDEFINED	r11
++	CFI_UNDEFINED	r12
++	CFI_UNDEFINED	r13
++	CFI_UNDEFINED	r14
++	CFI_UNDEFINED	r15
++	.endm
++
++/*
++ * 32bit SYSENTER instruction entry.
++ *
++ * Arguments:
++ * %eax	System call number.
++ * %ebx Arg1
++ * %ecx Arg2
++ * %edx Arg3
++ * %esi Arg4
++ * %edi Arg5
++ * %ebp user stack
++ * 0(%ebp) Arg6	
++ * 	
++ * Interrupts on.
++ *	
++ * This is purely a fast path. For anything complicated we use the int 0x80
++ * path below.	Set up a complete hardware stack frame to share code
++ * with the int 0x80 path.
++ */ 	
++ENTRY(ia32_sysenter_target)
++	CFI_STARTPROC32	simple
++	CFI_DEF_CFA	rsp,SS+8-RIP+16
++	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
++	CFI_REL_OFFSET	rsp,RSP-RIP+16
++	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
++	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
++	CFI_REL_OFFSET	rip,RIP-RIP+16
++	CFI_REL_OFFSET	r11,8
++	CFI_REL_OFFSET	rcx,0
++	movq	8(%rsp),%r11
++	CFI_RESTORE	r11
++	popq	%rcx
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE	rcx
++ 	movl	%ebp,%ebp		/* zero extension */
++	movl	%eax,%eax
++	movl	$__USER32_DS,40(%rsp)
++	movq	%rbp,32(%rsp)
++	movl	$__USER32_CS,16(%rsp)
++	movl	$VSYSCALL32_SYSEXIT,8(%rsp)
++	movq	%rax,(%rsp)
++	cld
++	SAVE_ARGS 0,0,0
++ 	/* no need to do an access_ok check here because rbp has been
++ 	   32bit zero extended */ 
++1:	movl	(%rbp),%r9d
++ 	.section __ex_table,"a"
++ 	.quad 1b,ia32_badarg
++ 	.previous	
++	GET_THREAD_INFO(%r10)
++	orl    $TS_COMPAT,threadinfo_status(%r10)
++	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	jnz  sysenter_tracesys
++sysenter_do_call:	
++	cmpl	$(IA32_NR_syscalls-1),%eax
++	ja	ia32_badsys
++	IA32_ARG_FIXUP 1
++	call	*ia32_sys_call_table(,%rax,8)
++	movq	%rax,RAX-ARGOFFSET(%rsp)
++	jmp int_ret_from_sys_call
++
++sysenter_tracesys:
++	SAVE_REST
++	CLEAR_RREGS
++	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
++	call	syscall_trace_enter
++	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	RESTORE_REST
++	movl	%ebp, %ebp
++	/* no need to do an access_ok check here because rbp has been
++	   32bit zero extended */ 
++1:	movl	(%rbp),%r9d
++	.section __ex_table,"a"
++	.quad 1b,ia32_badarg
++	.previous
++	jmp	sysenter_do_call
++	CFI_ENDPROC
++ENDPROC(ia32_sysenter_target)
++
++/*
++ * 32bit SYSCALL instruction entry.
++ *
++ * Arguments:
++ * %eax	System call number.
++ * %ebx Arg1
++ * %ecx return EIP 
++ * %edx Arg3
++ * %esi Arg4
++ * %edi Arg5
++ * %ebp Arg2    [note: not saved in the stack frame, should not be touched]
++ * %esp user stack 
++ * 0(%esp) Arg6
++ * 	
++ * Interrupts on.
++ *	
++ * This is purely a fast path. For anything complicated we use the int 0x80
++ * path below.	Set up a complete hardware stack frame to share code
++ * with the int 0x80 path.	
++ */ 	
++ENTRY(ia32_cstar_target)
++	CFI_STARTPROC32	simple
++	CFI_DEF_CFA	rsp,SS+8-RIP+16
++	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
++	CFI_REL_OFFSET	rsp,RSP-RIP+16
++	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
++	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
++	CFI_REL_OFFSET	rip,RIP-RIP+16
++	movl 	%eax,%eax	/* zero extension */
++	movl	RSP-RIP+16(%rsp),%r8d
++	SAVE_ARGS -8,1,1
++	movq	%rax,ORIG_RAX-ARGOFFSET(%rsp)
++	movq	%rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
++	movl	%ebp,%ecx
++	movl	$__USER32_CS,CS-ARGOFFSET(%rsp)
++	movl	$__USER32_DS,SS-ARGOFFSET(%rsp)
++	/* no need to do an access_ok check here because r8 has been
++	   32bit zero extended */ 
++	/* hardware stack frame is complete now */	
++1:	movl	(%r8),%r9d
++	.section __ex_table,"a"
++	.quad 1b,ia32_badarg
++	.previous	
++	GET_THREAD_INFO(%r10)
++	orl   $TS_COMPAT,threadinfo_status(%r10)
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	jnz   cstar_tracesys
++cstar_do_call:	
++	cmpl $IA32_NR_syscalls-1,%eax
++	ja  ia32_badsys
++	IA32_ARG_FIXUP 1
++	call *ia32_sys_call_table(,%rax,8)
++	movq %rax,RAX-ARGOFFSET(%rsp)
++	jmp int_ret_from_sys_call
++	
++cstar_tracesys:	
++	SAVE_REST
++	CLEAR_RREGS
++	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq %rsp,%rdi        /* &pt_regs -> arg1 */
++	call syscall_trace_enter
++	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	RESTORE_REST
++	movl RSP-ARGOFFSET(%rsp), %r8d
++	/* no need to do an access_ok check here because r8 has been
++	   32bit zero extended */ 
++1:	movl	(%r8),%r9d
++	.section __ex_table,"a"
++	.quad 1b,ia32_badarg
++	.previous
++	jmp cstar_do_call
++END(ia32_cstar_target)
++				
++ia32_badarg:
++	movq $-EFAULT,%rax
++	jmp ia32_sysret
++	CFI_ENDPROC
++
++/* 
++ * Emulated IA32 system calls via int 0x80. 
++ *
++ * Arguments:	 
++ * %eax	System call number.
++ * %ebx Arg1
++ * %ecx Arg2
++ * %edx Arg3
++ * %esi Arg4
++ * %edi Arg5
++ * %ebp Arg6    [note: not saved in the stack frame, should not be touched]
++ *
++ * Notes:
++ * Uses the same stack frame as the x86-64 version.	
++ * All registers except %eax must be saved (but ptrace may violate that)
++ * Arguments are zero extended. For system calls that want sign extension and
++ * take long arguments a wrapper is needed. Most calls can just be called
++ * directly.
++ * Assumes it is only called from user space and entered with interrupts on.
++ */ 				
++
++ENTRY(ia32_syscall)
++	CFI_STARTPROC	simple
++	CFI_DEF_CFA	rsp,SS+8-RIP+16
++	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
++	CFI_REL_OFFSET	rsp,RSP-RIP+16
++	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
++	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
++	CFI_REL_OFFSET	rip,RIP-RIP+16
++	CFI_REL_OFFSET	r11,8
++	CFI_REL_OFFSET	rcx,0
++	movq 8(%rsp),%r11
++	CFI_RESTORE	r11
++	popq %rcx
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE	rcx
++	movl %eax,%eax
++	movq %rax,(%rsp)
++	cld
++	/* note the registers are not zero extended to the sf.
++	   this could be a problem. */
++	SAVE_ARGS 0,0,1
++	GET_THREAD_INFO(%r10)
++	orl   $TS_COMPAT,threadinfo_status(%r10)
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
++	jnz ia32_tracesys
++ia32_do_syscall:	
++	cmpl $(IA32_NR_syscalls-1),%eax
++	ja  ia32_badsys
++	IA32_ARG_FIXUP
++	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
++ia32_sysret:
++	movq %rax,RAX-ARGOFFSET(%rsp)
++	jmp int_ret_from_sys_call 
++
++ia32_tracesys:			 
++	SAVE_REST
++	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
++	movq %rsp,%rdi        /* &pt_regs -> arg1 */
++	call syscall_trace_enter
++	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	RESTORE_REST
++	jmp ia32_do_syscall
++END(ia32_syscall)
++
++ia32_badsys:
++	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
++	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
++	jmp int_ret_from_sys_call
++
++quiet_ni_syscall:
++	movq $-ENOSYS,%rax
++	ret
++	CFI_ENDPROC
++	
++	.macro PTREGSCALL label, func, arg
++	.globl \label
++\label:
++	leaq \func(%rip),%rax
++	leaq -ARGOFFSET+8(%rsp),\arg	/* 8 for return address */
++	jmp  ia32_ptregs_common	
++	.endm
++
++	CFI_STARTPROC32
++
++	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
++	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
++	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
++	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx
++	PTREGSCALL stub32_execve, sys32_execve, %rcx
++	PTREGSCALL stub32_fork, sys_fork, %rdi
++	PTREGSCALL stub32_clone, sys32_clone, %rdx
++	PTREGSCALL stub32_vfork, sys_vfork, %rdi
++	PTREGSCALL stub32_iopl, sys_iopl, %rsi
++	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
++
++ENTRY(ia32_ptregs_common)
++	popq %r11
++	CFI_ENDPROC
++	CFI_STARTPROC32	simple
++	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
++	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
++	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
++	CFI_REL_OFFSET	rdx,RDX-ARGOFFSET
++	CFI_REL_OFFSET	rsi,RSI-ARGOFFSET
++	CFI_REL_OFFSET	rdi,RDI-ARGOFFSET
++	CFI_REL_OFFSET	rip,RIP-ARGOFFSET
++/*	CFI_REL_OFFSET	cs,CS-ARGOFFSET*/
++/*	CFI_REL_OFFSET	rflags,EFLAGS-ARGOFFSET*/
++	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
++/*	CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
++	SAVE_REST
++	call *%rax
++	RESTORE_REST
++	jmp  ia32_sysret	/* misbalances the return cache */
++	CFI_ENDPROC
++END(ia32_ptregs_common)
++
++	.section .rodata,"a"
++	.align 8
++ia32_sys_call_table:
++	.quad sys_restart_syscall
++	.quad sys_exit
++	.quad stub32_fork
++	.quad sys_read
++	.quad sys_write
++	.quad compat_sys_open		/* 5 */
++	.quad sys_close
++	.quad sys32_waitpid
++	.quad sys_creat
++	.quad sys_link
++	.quad sys_unlink		/* 10 */
++	.quad stub32_execve
++	.quad sys_chdir
++	.quad compat_sys_time
++	.quad sys_mknod
++	.quad sys_chmod		/* 15 */
++	.quad sys_lchown16
++	.quad quiet_ni_syscall			/* old break syscall holder */
++	.quad sys_stat
++	.quad sys32_lseek
++	.quad sys_getpid		/* 20 */
++	.quad compat_sys_mount	/* mount  */
++	.quad sys_oldumount	/* old_umount  */
++	.quad sys_setuid16
++	.quad sys_getuid16
++	.quad compat_sys_stime	/* stime */		/* 25 */
++	.quad sys32_ptrace	/* ptrace */
++	.quad sys_alarm
++	.quad sys_fstat	/* (old)fstat */
++	.quad sys_pause
++	.quad compat_sys_utime	/* 30 */
++	.quad quiet_ni_syscall	/* old stty syscall holder */
++	.quad quiet_ni_syscall	/* old gtty syscall holder */
++	.quad sys_access
++	.quad sys_nice	
++	.quad quiet_ni_syscall	/* 35 */	/* old ftime syscall holder */
++	.quad sys_sync
++	.quad sys32_kill
++	.quad sys_rename
++	.quad sys_mkdir
++	.quad sys_rmdir		/* 40 */
++	.quad sys_dup
++	.quad sys32_pipe
++	.quad compat_sys_times
++	.quad quiet_ni_syscall			/* old prof syscall holder */
++	.quad sys_brk		/* 45 */
++	.quad sys_setgid16
++	.quad sys_getgid16
++	.quad sys_signal
++	.quad sys_geteuid16
++	.quad sys_getegid16	/* 50 */
++	.quad sys_acct
++	.quad sys_umount			/* new_umount */
++	.quad quiet_ni_syscall			/* old lock syscall holder */
++	.quad compat_sys_ioctl
++	.quad compat_sys_fcntl64		/* 55 */
++	.quad quiet_ni_syscall			/* old mpx syscall holder */
++	.quad sys_setpgid
++	.quad quiet_ni_syscall			/* old ulimit syscall holder */
++	.quad sys32_olduname
++	.quad sys_umask		/* 60 */
++	.quad sys_chroot
++	.quad sys32_ustat
++	.quad sys_dup2
++	.quad sys_getppid
++	.quad sys_getpgrp		/* 65 */
++	.quad sys_setsid
++	.quad sys32_sigaction
++	.quad sys_sgetmask
++	.quad sys_ssetmask
++	.quad sys_setreuid16	/* 70 */
++	.quad sys_setregid16
++	.quad stub32_sigsuspend
++	.quad compat_sys_sigpending
++	.quad sys_sethostname
++	.quad compat_sys_setrlimit	/* 75 */
++	.quad compat_sys_old_getrlimit	/* old_getrlimit */
++	.quad compat_sys_getrusage
++	.quad sys32_gettimeofday
++	.quad sys32_settimeofday
++	.quad sys_getgroups16	/* 80 */
++	.quad sys_setgroups16
++	.quad sys32_old_select
++	.quad sys_symlink
++	.quad sys_lstat
++	.quad sys_readlink		/* 85 */
++#ifdef CONFIG_IA32_AOUT
++	.quad sys_uselib
++#else
++	.quad quiet_ni_syscall
++#endif
++	.quad sys_swapon
++	.quad sys_reboot
++	.quad compat_sys_old_readdir
++	.quad sys32_mmap		/* 90 */
++	.quad sys_munmap
++	.quad sys_truncate
++	.quad sys_ftruncate
++	.quad sys_fchmod
++	.quad sys_fchown16		/* 95 */
++	.quad sys_getpriority
++	.quad sys_setpriority
++	.quad quiet_ni_syscall			/* old profil syscall holder */
++	.quad compat_sys_statfs
++	.quad compat_sys_fstatfs		/* 100 */
++	.quad sys_ioperm
++	.quad compat_sys_socketcall
++	.quad sys_syslog
++	.quad compat_sys_setitimer
++	.quad compat_sys_getitimer	/* 105 */
++	.quad compat_sys_newstat
++	.quad compat_sys_newlstat
++	.quad compat_sys_newfstat
++	.quad sys32_uname
++	.quad stub32_iopl		/* 110 */
++	.quad sys_vhangup
++	.quad quiet_ni_syscall	/* old "idle" system call */
++	.quad sys32_vm86_warning	/* vm86old */ 
++	.quad compat_sys_wait4
++	.quad sys_swapoff		/* 115 */
++	.quad sys32_sysinfo
++	.quad sys32_ipc
++	.quad sys_fsync
++	.quad stub32_sigreturn
++	.quad stub32_clone		/* 120 */
++	.quad sys_setdomainname
++	.quad sys_uname
++	.quad sys_modify_ldt
++	.quad compat_sys_adjtimex
++	.quad sys32_mprotect		/* 125 */
++	.quad compat_sys_sigprocmask
++	.quad quiet_ni_syscall		/* create_module */
++	.quad sys_init_module
++	.quad sys_delete_module
++	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
++	.quad sys_quotactl
++	.quad sys_getpgid
++	.quad sys_fchdir
++	.quad quiet_ni_syscall	/* bdflush */
++	.quad sys_sysfs		/* 135 */
++	.quad sys_personality
++	.quad quiet_ni_syscall	/* for afs_syscall */
++	.quad sys_setfsuid16
++	.quad sys_setfsgid16
++	.quad sys_llseek		/* 140 */
++	.quad compat_sys_getdents
++	.quad compat_sys_select
++	.quad sys_flock
++	.quad sys_msync
++	.quad compat_sys_readv		/* 145 */
++	.quad compat_sys_writev
++	.quad sys_getsid
++	.quad sys_fdatasync
++	.quad sys32_sysctl	/* sysctl */
++	.quad sys_mlock		/* 150 */
++	.quad sys_munlock
++	.quad sys_mlockall
++	.quad sys_munlockall
++	.quad sys_sched_setparam
++	.quad sys_sched_getparam   /* 155 */
++	.quad sys_sched_setscheduler
++	.quad sys_sched_getscheduler
++	.quad sys_sched_yield
++	.quad sys_sched_get_priority_max
++	.quad sys_sched_get_priority_min  /* 160 */
++	.quad sys_sched_rr_get_interval
++	.quad compat_sys_nanosleep
++	.quad sys_mremap
++	.quad sys_setresuid16
++	.quad sys_getresuid16	/* 165 */
++	.quad sys32_vm86_warning	/* vm86 */ 
++	.quad quiet_ni_syscall	/* query_module */
++	.quad sys_poll
++	.quad compat_sys_nfsservctl
++	.quad sys_setresgid16	/* 170 */
++	.quad sys_getresgid16
++	.quad sys_prctl
++	.quad stub32_rt_sigreturn
++	.quad sys32_rt_sigaction
++	.quad sys32_rt_sigprocmask	/* 175 */
++	.quad sys32_rt_sigpending
++	.quad compat_sys_rt_sigtimedwait
++	.quad sys32_rt_sigqueueinfo
++	.quad stub32_rt_sigsuspend
++	.quad sys32_pread		/* 180 */
++	.quad sys32_pwrite
++	.quad sys_chown16
++	.quad sys_getcwd
++	.quad sys_capget
++	.quad sys_capset
++	.quad stub32_sigaltstack
++	.quad sys32_sendfile
++	.quad quiet_ni_syscall		/* streams1 */
++	.quad quiet_ni_syscall		/* streams2 */
++	.quad stub32_vfork            /* 190 */
++	.quad compat_sys_getrlimit
++	.quad sys32_mmap2
++	.quad sys32_truncate64
++	.quad sys32_ftruncate64
++	.quad sys32_stat64		/* 195 */
++	.quad sys32_lstat64
++	.quad sys32_fstat64
++	.quad sys_lchown
++	.quad sys_getuid
++	.quad sys_getgid		/* 200 */
++	.quad sys_geteuid
++	.quad sys_getegid
++	.quad sys_setreuid
++	.quad sys_setregid
++	.quad sys_getgroups	/* 205 */
++	.quad sys_setgroups
++	.quad sys_fchown
++	.quad sys_setresuid
++	.quad sys_getresuid
++	.quad sys_setresgid	/* 210 */
++	.quad sys_getresgid
++	.quad sys_chown
++	.quad sys_setuid
++	.quad sys_setgid
++	.quad sys_setfsuid		/* 215 */
++	.quad sys_setfsgid
++	.quad sys_pivot_root
++	.quad sys_mincore
++	.quad sys_madvise
++	.quad compat_sys_getdents64	/* 220 getdents64 */
++	.quad compat_sys_fcntl64	
++	.quad quiet_ni_syscall		/* tux */
++	.quad quiet_ni_syscall    	/* security */
++	.quad sys_gettid	
++	.quad sys_readahead	/* 225 */
++	.quad sys_setxattr
++	.quad sys_lsetxattr
++	.quad sys_fsetxattr
++	.quad sys_getxattr
++	.quad sys_lgetxattr	/* 230 */
++	.quad sys_fgetxattr
++	.quad sys_listxattr
++	.quad sys_llistxattr
++	.quad sys_flistxattr
++	.quad sys_removexattr	/* 235 */
++	.quad sys_lremovexattr
++	.quad sys_fremovexattr
++	.quad sys_tkill
++	.quad sys_sendfile64 
++	.quad compat_sys_futex		/* 240 */
++	.quad compat_sys_sched_setaffinity
++	.quad compat_sys_sched_getaffinity
++	.quad sys32_set_thread_area
++	.quad sys32_get_thread_area
++	.quad compat_sys_io_setup	/* 245 */
++	.quad sys_io_destroy
++	.quad compat_sys_io_getevents
++	.quad compat_sys_io_submit
++	.quad sys_io_cancel
++	.quad sys_fadvise64		/* 250 */
++	.quad quiet_ni_syscall 	/* free_huge_pages */
++	.quad sys_exit_group
++	.quad sys32_lookup_dcookie
++	.quad sys_epoll_create
++	.quad sys_epoll_ctl		/* 255 */
++	.quad sys_epoll_wait
++	.quad sys_remap_file_pages
++	.quad sys_set_tid_address
++	.quad compat_sys_timer_create
++	.quad compat_sys_timer_settime	/* 260 */
++	.quad compat_sys_timer_gettime
++	.quad sys_timer_getoverrun
++	.quad sys_timer_delete
++	.quad compat_sys_clock_settime
++	.quad compat_sys_clock_gettime	/* 265 */
++	.quad compat_sys_clock_getres
++	.quad compat_sys_clock_nanosleep
++	.quad compat_sys_statfs64
++	.quad compat_sys_fstatfs64
++	.quad sys_tgkill		/* 270 */
++	.quad compat_sys_utimes
++	.quad sys32_fadvise64_64
++	.quad quiet_ni_syscall	/* sys_vserver */
++	.quad sys_mbind
++	.quad compat_sys_get_mempolicy	/* 275 */
++	.quad sys_set_mempolicy
++	.quad compat_sys_mq_open
++	.quad sys_mq_unlink
++	.quad compat_sys_mq_timedsend
++	.quad compat_sys_mq_timedreceive	/* 280 */
++	.quad compat_sys_mq_notify
++	.quad compat_sys_mq_getsetattr
++	.quad compat_sys_kexec_load	/* reserved for kexec */
++	.quad compat_sys_waitid
++	.quad quiet_ni_syscall		/* 285: sys_altroot */
++	.quad sys_add_key
++	.quad sys_request_key
++	.quad sys_keyctl
++	.quad sys_ioprio_set
++	.quad sys_ioprio_get		/* 290 */
++	.quad sys_inotify_init
++	.quad sys_inotify_add_watch
++	.quad sys_inotify_rm_watch
++	.quad sys_migrate_pages
++	.quad compat_sys_openat		/* 295 */
++	.quad sys_mkdirat
++	.quad sys_mknodat
++	.quad sys_fchownat
++	.quad compat_sys_futimesat
++	.quad sys32_fstatat		/* 300 */
++	.quad sys_unlinkat
++	.quad sys_renameat
++	.quad sys_linkat
++	.quad sys_symlinkat
++	.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 sys_unshare		/* 310 */
++	.quad compat_sys_set_robust_list
++	.quad compat_sys_get_robust_list
++	.quad sys_splice
++	.quad sys_sync_file_range
++	.quad sys_tee
++	.quad compat_sys_vmsplice
++	.quad compat_sys_move_pages
++ia32_syscall_end:		
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_64-xen.c	2008-04-15 09:29:41.000000000 +0200
+@@ -0,0 +1,146 @@
++/*
++ *  acpi.c - Architecture-Specific Low-Level ACPI Support
++ *
++ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
++ *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
++ *  Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
++ *  Copyright (C) 2002 Andi Kleen, SuSE Labs (x86-64 port)
++ *  Copyright (C) 2003 Pavel Machek, SuSE Labs
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ *  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/stddef.h>
++#include <linux/slab.h>
++#include <linux/pci.h>
++#include <linux/bootmem.h>
++#include <linux/acpi.h>
++#include <linux/cpumask.h>
++
++#include <asm/mpspec.h>
++#include <asm/io.h>
++#include <asm/apic.h>
++#include <asm/apicdef.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/io_apic.h>
++#include <asm/proto.h>
++#include <asm/tlbflush.h>
++
++/* --------------------------------------------------------------------------
++                              Low-Level Sleep Support
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI_SLEEP
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++/* address in low memory of the wakeup routine. */
++unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_video_flags;
++extern char wakeup_start, wakeup_end;
++
++extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
++
++static pgd_t low_ptr;
++
++static void init_low_mapping(void)
++{
++	pgd_t *slot0 = pgd_offset(current->mm, 0UL);
++	low_ptr = *slot0;
++	set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
++	WARN_ON(num_online_cpus() != 1);
++	local_flush_tlb();
++}
++#endif
++
++/**
++ * acpi_save_state_mem - save kernel state
++ *
++ * Create an identity mapped page table and copy the wakeup routine to
++ * low memory.
++ */
++int acpi_save_state_mem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	init_low_mapping();
++
++	memcpy((void *)acpi_wakeup_address, &wakeup_start,
++	       &wakeup_end - &wakeup_start);
++	acpi_copy_wakeup_routine(acpi_wakeup_address);
++#endif
++	return 0;
++}
++
++/*
++ * acpi_restore_state
++ */
++void acpi_restore_state_mem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
++	local_flush_tlb();
++#endif
++}
++
++/**
++ * acpi_reserve_bootmem - do _very_ early ACPI initialisation
++ *
++ * We allocate a page in low memory for the wakeup
++ * routine for when we come back from a sleep state. The
++ * runtime allocator allows specification of <16M pages, but not
++ * <1M pages.
++ */
++void __init acpi_reserve_bootmem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
++	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE)
++		printk(KERN_CRIT
++		       "ACPI: Wakeup code way too big, will crash on attempt to suspend\n");
++#endif
++}
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++static int __init acpi_sleep_setup(char *str)
++{
++	while ((str != NULL) && (*str != '\0')) {
++		if (strncmp(str, "s3_bios", 7) == 0)
++			acpi_video_flags = 1;
++		if (strncmp(str, "s3_mode", 7) == 0)
++			acpi_video_flags |= 2;
++		str = strchr(str, ',');
++		if (str != NULL)
++			str += strspn(str, ", \t");
++	}
++
++	return 1;
++}
++
++__setup("acpi_sleep=", acpi_sleep_setup);
++#endif				/* CONFIG_ACPI_PV_SLEEP */
++
++#endif				/*CONFIG_ACPI_SLEEP */
++
++void acpi_pci_link_exit(void)
++{
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2007-06-12 13:13:01.000000000 +0200
+@@ -0,0 +1,197 @@
++/*
++ *	Local APIC handling, local APIC timers
++ *
++ *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
++ *					thanks to Eric Gilmore
++ *					and Rolf G. Tews
++ *					for testing these extensively.
++ *	Maciej W. Rozycki	:	Various updates and fixes.
++ *	Mikael Pettersson	:	Power Management for UP-APIC.
++ *	Pavel Machek and
++ *	Mikael Pettersson	:	PM converted to driver model.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/mc146818rtc.h>
++#include <linux/kernel_stat.h>
++#include <linux/sysdev.h>
++#include <linux/module.h>
++
++#include <asm/atomic.h>
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/desc.h>
++#include <asm/arch_hooks.h>
++#include <asm/hpet.h>
++#include <asm/idle.h>
++
++int apic_verbosity;
++
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++	printk("unexpected IRQ trap at vector %02x\n", irq);
++	/*
++	 * Currently unexpected vectors happen only on SMP and APIC.
++	 * We _must_ ack these because every local APIC has only N
++	 * irq slots per priority level, and a 'hanging, unacked' IRQ
++	 * holds up an irq slot - in excessive cases (when multiple
++	 * unexpected vectors occur) that might lock up the APIC
++	 * completely.
++  	 * But don't ack when the APIC is disabled. -AK
++	 */
++	if (!disable_apic)
++		ack_APIC_irq();
++}
++
++int setup_profiling_timer(unsigned int multiplier)
++{
++	return -EINVAL;
++}
++
++void smp_local_timer_interrupt(struct pt_regs *regs)
++{
++	profile_tick(CPU_PROFILING, regs);
++#ifndef CONFIG_XEN
++#ifdef CONFIG_SMP
++		update_process_times(user_mode(regs));
++#endif
++#endif
++	/*
++	 * We take the 'long' return path, and there every subsystem
++	 * grabs the appropriate locks (kernel lock/ irq lock).
++	 *
++	 * we might want to decouple profiling from the 'long path',
++	 * and do the profiling totally in assembly.
++	 *
++	 * Currently this isn't too much of an issue (performance wise),
++	 * we can take more than 100K local irqs per second on a 100 MHz P5.
++	 */
++}
++
++/*
++ * Local APIC timer interrupt. This is the most natural way for doing
++ * local interrupts, but local timer interrupts can be emulated by
++ * broadcast interrupts too. [in case the hw doesn't support APIC timers]
++ *
++ * [ if a single-CPU system runs an SMP kernel then we call the local
++ *   interrupt as well. Thus we cannot inline the local irq ... ]
++ */
++void smp_apic_timer_interrupt(struct pt_regs *regs)
++{
++	/*
++	 * the NMI deadlock-detector uses this.
++	 */
++	add_pda(apic_timer_irqs, 1);
++
++	/*
++	 * NOTE! We'd better ACK the irq immediately,
++	 * because timer handling can be slow.
++	 */
++	ack_APIC_irq();
++	/*
++	 * update_process_times() expects us to have done irq_enter().
++	 * Besides, if we don't timer interrupts ignore the global
++	 * interrupt lock, which is the WrongThing (tm) to do.
++	 */
++	exit_idle();
++	irq_enter();
++	smp_local_timer_interrupt(regs);
++	irq_exit();
++}
++
++/*
++ * This interrupt should _never_ happen with our APIC/SMP architecture
++ */
++asmlinkage void smp_spurious_interrupt(void)
++{
++	unsigned int v;
++	exit_idle();
++	irq_enter();
++	/*
++	 * Check if this really is a spurious interrupt and ACK it
++	 * if it is a vectored one.  Just in case...
++	 * Spurious interrupts should not be ACKed.
++	 */
++	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
++	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
++		ack_APIC_irq();
++
++#if 0
++	static unsigned long last_warning; 
++	static unsigned long skipped; 
++
++	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
++	if (time_before(last_warning+30*HZ,jiffies)) { 
++		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
++		       smp_processor_id(), skipped);
++		last_warning = jiffies; 
++		skipped = 0;
++	} else { 
++		skipped++; 
++	} 
++#endif 
++	irq_exit();
++}
++
++/*
++ * This interrupt should never happen with our APIC/SMP architecture
++ */
++
++asmlinkage void smp_error_interrupt(void)
++{
++	unsigned int v, v1;
++
++	exit_idle();
++	irq_enter();
++	/* First tickle the hardware, only then report what went on. -- REW */
++	v = apic_read(APIC_ESR);
++	apic_write(APIC_ESR, 0);
++	v1 = apic_read(APIC_ESR);
++	ack_APIC_irq();
++	atomic_inc(&irq_err_count);
++
++	/* Here is what the APIC error bits mean:
++	   0: Send CS error
++	   1: Receive CS error
++	   2: Send accept error
++	   3: Receive accept error
++	   4: Reserved
++	   5: Send illegal vector
++	   6: Received illegal vector
++	   7: Illegal register address
++	*/
++	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
++	        smp_processor_id(), v , v1);
++	irq_exit();
++}
++
++int disable_apic;
++
++/*
++ * This initializes the IO-APIC and APIC hardware if this is
++ * a UP kernel.
++ */
++int __init APIC_init_uniprocessor (void)
++{
++#ifdef CONFIG_X86_IO_APIC
++	if (smp_found_config)
++		if (!skip_ioapic_setup && nr_ioapics)
++			setup_IO_APIC();
++#endif
++
++	return 1;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 08:45:56.000000000 +0100
+@@ -0,0 +1,800 @@
++/* 
++ * Handle the memory map.
++ * The functions here do the job until bootmem takes over.
++ *
++ *  Getting sanitize_e820_map() in sync with i386 version by applying change:
++ *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
++ *     Alex Achenbach <xela@slit.de>, December 2002.
++ *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/string.h>
++#include <linux/kexec.h>
++#include <linux/module.h>
++
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/e820.h>
++#include <asm/proto.h>
++#include <asm/bootsetup.h>
++#include <asm/sections.h>
++#include <xen/interface/memory.h>
++
++/* 
++ * PFN of last memory page.
++ */
++unsigned long end_pfn; 
++EXPORT_SYMBOL(end_pfn);
++
++#ifndef CONFIG_XEN
++/* 
++ * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
++ * The direct mapping extends to end_pfn_map, so that we can directly access
++ * apertures, ACPI and other tables without having to play with fixmaps.
++ */ 
++unsigned long end_pfn_map; 
++#endif
++
++/* 
++ * Last pfn which the user wants to use.
++ */
++unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;  
++
++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)
++{ 
++	unsigned long addr = *addrp, last = addr + size; 
++
++#ifndef CONFIG_XEN
++	/* various gunk below that needed for SMP startup */
++	if (addr < 0x8000) { 
++		*addrp = 0x8000;
++		return 1; 
++	}
++
++	/* direct mapping tables of the kernel */
++	if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 
++		*addrp = table_end << PAGE_SHIFT; 
++		return 1;
++	} 
++
++	/* initrd */ 
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 
++	    addr < INITRD_START+INITRD_SIZE) { 
++		*addrp = INITRD_START + INITRD_SIZE; 
++		return 1;
++	} 
++#endif
++	/* kernel code + 640k memory hole (later should not be needed, but 
++	   be paranoid for now) */
++	if (last >= 640*1024 && addr < 1024*1024) {
++		*addrp = 1024*1024;
++		return 1;
++	}
++	if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
++		*addrp = __pa_symbol(&_end);
++		return 1;
++	}
++
++	if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
++		*addrp = ebda_addr + ebda_size;
++		return 1;
++	}
++
++	/* XXX ramdisk image here? */ 
++#else
++	if (last < (table_end<<PAGE_SHIFT)) {
++		*addrp = table_end << PAGE_SHIFT;
++		return 1;
++	}
++#endif
++	return 0;
++} 
++
++/*
++ * This function checks if any part of the range <start,end> is mapped
++ * with type.
++ */
++int e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
++{ 
++	int i;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) { 
++		struct e820entry *ei = &e820.map[i]; 
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; i++) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		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.
++ *
++ * Note: this function only works correct if the e820 table is sorted and
++ * not-overlapping, which is the case
++ */
++int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
++{
++	int i;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; i++) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		if (type && ei->type != type)
++			continue;
++		/* is the region (part) in overlap with the current region ?*/
++		if (ei->addr >= end || ei->addr + ei->size <= start)
++			continue;
++
++		/* if the region is at the beginning of <start,end> we move
++		 * start to the end of the region since it's ok until there
++		 */
++		if (ei->addr <= start)
++			start = ei->addr + ei->size;
++		/* if start is now at or beyond end, we're done, full coverage */
++		if (start >= end)
++			return 1; /* we're done */
++	}
++	return 0;
++}
++
++/* 
++ * Find a free area in a specific range. 
++ */ 
++unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsigned size) 
++{ 
++	int i; 
++	for (i = 0; i < e820.nr_map; i++) { 
++		struct e820entry *ei = &e820.map[i]; 
++		unsigned long addr = ei->addr, last; 
++		if (ei->type != E820_RAM) 
++			continue; 
++		if (addr < start) 
++			addr = start;
++		if (addr > ei->addr + ei->size) 
++			continue; 
++		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
++			;
++		last = addr + size;
++		if (last > ei->addr + ei->size)
++			continue;
++		if (last > end) 
++			continue;
++		return addr; 
++	} 
++	return -1UL;		
++} 
++
++/* 
++ * Free bootmem based on the e820 table for a node.
++ */
++void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
++{
++	int i;
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i]; 
++		unsigned long last, addr;
++
++		if (ei->type != E820_RAM || 
++		    ei->addr+ei->size <= start || 
++		    ei->addr >= end)
++			continue;
++
++		addr = round_up(ei->addr, PAGE_SIZE);
++		if (addr < start) 
++			addr = start;
++
++		last = round_down(ei->addr + ei->size, PAGE_SIZE); 
++		if (last >= end)
++			last = end; 
++
++		if (last > addr && last-addr >= PAGE_SIZE)
++			free_bootmem_node(pgdat, addr, last-addr);
++	}
++}
++
++/*
++ * Find the highest page frame number we have available
++ */
++unsigned long __init e820_end_of_ram(void)
++{
++	int i;
++	unsigned long end_pfn = 0;
++	
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i]; 
++		unsigned long start, end;
++
++		start = round_up(ei->addr, PAGE_SIZE); 
++		end = round_down(ei->addr + ei->size, PAGE_SIZE); 
++		if (start >= end)
++			continue;
++		if (ei->type == E820_RAM) { 
++		if (end > end_pfn<<PAGE_SHIFT)
++			end_pfn = end>>PAGE_SHIFT;
++		} else { 
++			if (end > end_pfn_map<<PAGE_SHIFT) 
++				end_pfn_map = end>>PAGE_SHIFT;
++		} 
++	}
++
++	if (end_pfn > end_pfn_map) 
++		end_pfn_map = end_pfn;
++	if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
++		end_pfn_map = MAXMEM>>PAGE_SHIFT;
++	if (end_pfn > end_user_pfn)
++		end_pfn = end_user_pfn;
++	if (end_pfn > end_pfn_map) 
++		end_pfn = end_pfn_map; 
++
++	return end_pfn;	
++}
++
++/* 
++ * Compute how much memory is missing in a range.
++ * Unlike the other functions in this file the arguments are in page numbers.
++ */
++unsigned long __init
++e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
++{
++	unsigned long ram = 0;
++	unsigned long start = start_pfn << PAGE_SHIFT;
++	unsigned long end = end_pfn << PAGE_SHIFT;
++	int i;
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long last, addr;
++
++		if (ei->type != E820_RAM ||
++		    ei->addr+ei->size <= start ||
++		    ei->addr >= end)
++			continue;
++
++		addr = round_up(ei->addr, PAGE_SIZE);
++		if (addr < start)
++			addr = start;
++
++		last = round_down(ei->addr + ei->size, PAGE_SIZE);
++		if (last >= end)
++			last = end;
++
++		if (last > addr)
++			ram += last - addr;
++	}
++	return ((end - start) - ram) >> PAGE_SHIFT;
++}
++
++/*
++ * Mark e820 reserved areas as busy for the resource manager.
++ */
++void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
++{
++	int i;
++	for (i = 0; i < nr_map; i++) {
++		struct resource *res;
++		res = alloc_bootmem_low(sizeof(struct resource));
++		switch (e820[i].type) {
++		case E820_RAM:	res->name = "System RAM"; break;
++		case E820_ACPI:	res->name = "ACPI Tables"; break;
++		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
++		default:	res->name = "reserved";
++		}
++		res->start = e820[i].addr;
++		res->end = res->start + e820[i].size - 1;
++		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++		request_resource(&iomem_resource, res);
++		if (e820[i].type == E820_RAM) {
++			/*
++			 *  We don't know which RAM region contains kernel data,
++			 *  so we try it repeatedly and let the resource manager
++			 *  test it.
++			 */
++#ifndef CONFIG_XEN
++			request_resource(res, &code_resource);
++			request_resource(res, &data_resource);
++#endif
++#ifdef CONFIG_KEXEC
++			if (crashk_res.start != crashk_res.end)
++				request_resource(res, &crashk_res);
++#ifdef CONFIG_XEN
++			xen_machine_kexec_register_resources(res);
++#endif
++#endif
++		}
++	}
++}
++
++/* 
++ * Add a memory region to the kernel e820 map.
++ */ 
++void __init add_memory_region(unsigned long start, unsigned long size, int type)
++{
++	int x = e820.nr_map;
++
++	if (x == E820MAX) {
++		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++		return;
++	}
++
++	e820.map[x].addr = start;
++	e820.map[x].size = size;
++	e820.map[x].type = type;
++	e820.nr_map++;
++}
++
++void __init e820_print_map(char *who)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		printk(" %s: %016Lx - %016Lx ", who,
++			(unsigned long long) e820.map[i].addr,
++			(unsigned long long) (e820.map[i].addr + e820.map[i].size));
++		switch (e820.map[i].type) {
++		case E820_RAM:	printk("(usable)\n");
++				break;
++		case E820_RESERVED:
++				printk("(reserved)\n");
++				break;
++		case E820_ACPI:
++				printk("(ACPI data)\n");
++				break;
++		case E820_NVS:
++				printk("(ACPI NVS)\n");
++				break;
++		default:	printk("type %u\n", e820.map[i].type);
++				break;
++		}
++	}
++}
++
++/*
++ * Sanitize the BIOS e820 map.
++ *
++ * Some e820 responses include overlapping entries.  The following 
++ * replaces the original e820 map with a new one, removing overlaps.
++ *
++ */
++static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
++{
++	struct change_member {
++		struct e820entry *pbios; /* pointer to original bios entry */
++		unsigned long long addr; /* address for this change point */
++	};
++	static struct change_member change_point_list[2*E820MAX] __initdata;
++	static struct change_member *change_point[2*E820MAX] __initdata;
++	static struct e820entry *overlap_list[E820MAX] __initdata;
++	static struct e820entry new_bios[E820MAX] __initdata;
++	struct change_member *change_tmp;
++	unsigned long current_type, last_type;
++	unsigned long long last_addr;
++	int chgidx, still_changing;
++	int overlap_entries;
++	int new_bios_entry;
++	int old_nr, new_nr, chg_nr;
++	int i;
++
++	/*
++		Visually we're performing the following (1,2,3,4 = memory types)...
++
++		Sample memory map (w/overlaps):
++		   ____22__________________
++		   ______________________4_
++		   ____1111________________
++		   _44_____________________
++		   11111111________________
++		   ____________________33__
++		   ___________44___________
++		   __________33333_________
++		   ______________22________
++		   ___________________2222_
++		   _________111111111______
++		   _____________________11_
++		   _________________4______
++
++		Sanitized equivalent (no overlap):
++		   1_______________________
++		   _44_____________________
++		   ___1____________________
++		   ____22__________________
++		   ______11________________
++		   _________1______________
++		   __________3_____________
++		   ___________44___________
++		   _____________33_________
++		   _______________2________
++		   ________________1_______
++		   _________________4______
++		   ___________________2____
++		   ____________________33__
++		   ______________________4_
++	*/
++
++	/* if there's only one memory region, don't bother */
++	if (*pnr_map < 2)
++		return -1;
++
++	old_nr = *pnr_map;
++
++	/* bail out if we find any unreasonable addresses in bios map */
++	for (i=0; i<old_nr; i++)
++		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
++			return -1;
++
++	/* create pointers for initial change-point information (for sorting) */
++	for (i=0; i < 2*old_nr; i++)
++		change_point[i] = &change_point_list[i];
++
++	/* record all known change-points (starting and ending addresses),
++	   omitting those that are for empty memory regions */
++	chgidx = 0;
++	for (i=0; i < old_nr; i++)	{
++		if (biosmap[i].size != 0) {
++			change_point[chgidx]->addr = biosmap[i].addr;
++			change_point[chgidx++]->pbios = &biosmap[i];
++			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
++			change_point[chgidx++]->pbios = &biosmap[i];
++		}
++	}
++	chg_nr = chgidx;
++
++	/* sort change-point list by memory addresses (low -> high) */
++	still_changing = 1;
++	while (still_changing)	{
++		still_changing = 0;
++		for (i=1; i < chg_nr; i++)  {
++			/* if <current_addr> > <last_addr>, swap */
++			/* or, if current=<start_addr> & last=<end_addr>, swap */
++			if ((change_point[i]->addr < change_point[i-1]->addr) ||
++				((change_point[i]->addr == change_point[i-1]->addr) &&
++				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
++				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
++			   )
++			{
++				change_tmp = change_point[i];
++				change_point[i] = change_point[i-1];
++				change_point[i-1] = change_tmp;
++				still_changing=1;
++			}
++		}
++	}
++
++	/* create a new bios memory map, removing overlaps */
++	overlap_entries=0;	 /* number of entries in the overlap table */
++	new_bios_entry=0;	 /* index for creating new bios map entries */
++	last_type = 0;		 /* start with undefined memory type */
++	last_addr = 0;		 /* start with 0 as last starting address */
++	/* loop through change-points, determining affect on the new bios map */
++	for (chgidx=0; chgidx < chg_nr; chgidx++)
++	{
++		/* keep track of all overlapping bios entries */
++		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
++		{
++			/* add map entry to overlap list (> 1 entry implies an overlap) */
++			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
++		}
++		else
++		{
++			/* remove entry from list (order independent, so swap with last) */
++			for (i=0; i<overlap_entries; i++)
++			{
++				if (overlap_list[i] == change_point[chgidx]->pbios)
++					overlap_list[i] = overlap_list[overlap_entries-1];
++			}
++			overlap_entries--;
++		}
++		/* if there are overlapping entries, decide which "type" to use */
++		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
++		current_type = 0;
++		for (i=0; i<overlap_entries; i++)
++			if (overlap_list[i]->type > current_type)
++				current_type = overlap_list[i]->type;
++		/* continue building up new bios map based on this information */
++		if (current_type != last_type)	{
++			if (last_type != 0)	 {
++				new_bios[new_bios_entry].size =
++					change_point[chgidx]->addr - last_addr;
++				/* move forward only if the new size was non-zero */
++				if (new_bios[new_bios_entry].size != 0)
++					if (++new_bios_entry >= E820MAX)
++						break; 	/* no more space left for new bios entries */
++			}
++			if (current_type != 0)	{
++				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
++				new_bios[new_bios_entry].type = current_type;
++				last_addr=change_point[chgidx]->addr;
++			}
++			last_type = current_type;
++		}
++	}
++	new_nr = new_bios_entry;   /* retain count for new bios entries */
++
++	/* copy new bios mapping into original location */
++	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
++	*pnr_map = new_nr;
++
++	return 0;
++}
++
++/*
++ * Copy the BIOS e820 map into a safe place.
++ *
++ * Sanity-check it while we're at it..
++ *
++ * If we're lucky and live on a modern system, the setup code
++ * will have given us a memory map that we can use to properly
++ * set up memory.  If we aren't, we'll fake a memory map.
++ *
++ * We check to see that the memory map contains at least 2 elements
++ * before we'll use it, because the detection code in setup.S may
++ * not be perfect and most every PC known to man has two memory
++ * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
++ * thinkpad 560x, for example, does not cooperate with the memory
++ * detection code.)
++ */
++static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++{
++#ifndef CONFIG_XEN
++	/* Only one memory region (or negative)? Ignore it */
++	if (nr_map < 2)
++		return -1;
++#else
++	BUG_ON(nr_map < 1);
++#endif
++
++	do {
++		unsigned long start = biosmap->addr;
++		unsigned long size = biosmap->size;
++		unsigned long end = start + size;
++		unsigned long type = biosmap->type;
++
++		/* Overflow in 64 bits? Ignore the memory map. */
++		if (start > end)
++			return -1;
++
++#ifndef CONFIG_XEN
++		/*
++		 * Some BIOSes claim RAM in the 640k - 1M region.
++		 * Not right. Fix it up.
++		 * 
++		 * This should be removed on Hammer which is supposed to not
++		 * have non e820 covered ISA mappings there, but I had some strange
++		 * problems so it stays for now.  -AK
++		 */
++		if (type == E820_RAM) {
++			if (start < 0x100000ULL && end > 0xA0000ULL) {
++				if (start < 0xA0000ULL)
++					add_memory_region(start, 0xA0000ULL-start, type);
++				if (end <= 0x100000ULL)
++					continue;
++				start = 0x100000ULL;
++				size = end - start;
++			}
++		}
++#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;
++}
++
++#ifndef CONFIG_XEN
++void __init setup_memory_region(void)
++{
++	char *who = "BIOS-e820";
++
++	/*
++	 * Try to copy the BIOS-supplied E820-map.
++	 *
++	 * Otherwise fake a memory map; one section from 0k->640k,
++	 * the next section from 1mb->appropriate_mem_k
++	 */
++	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
++	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
++		unsigned long mem_size;
++
++		/* compare results from other methods and take the greater */
++		if (ALT_MEM_K < EXT_MEM_K) {
++			mem_size = EXT_MEM_K;
++			who = "BIOS-88";
++		} else {
++			mem_size = ALT_MEM_K;
++			who = "BIOS-e801";
++		}
++
++		e820.nr_map = 0;
++		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
++		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
++  	}
++	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
++	e820_print_map(who);
++}
++
++#else  /* CONFIG_XEN */
++
++void __init setup_memory_region(void)
++{
++	int rc;
++	struct xen_memory_map memmap;
++	/*
++	 * This is rather large for a stack variable but this early in
++	 * the boot process we know we have plenty slack space.
++	 */
++	struct e820entry map[E820MAX];
++
++	memmap.nr_entries = E820MAX;
++	set_xen_guest_handle(memmap.buffer, map);
++
++	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
++	if ( rc == -ENOSYS ) {
++		memmap.nr_entries = 1;
++		map[0].addr = 0ULL;
++		map[0].size = xen_start_info->nr_pages << PAGE_SHIFT;
++		/* 8MB slack (to balance backend allocations). */
++		map[0].size += 8 << 20;
++		map[0].type = E820_RAM;
++		rc = 0;
++	}
++	BUG_ON(rc);
++
++	sanitize_e820_map(map, (char *)&memmap.nr_entries);
++
++	BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0);
++
++	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
++	e820_print_map("Xen");
++}
++#endif
++
++void __init parse_memopt(char *p, char **from) 
++{ 
++	int i;
++	unsigned long current_end;
++	unsigned long end;
++
++	end_user_pfn = memparse(p, from);
++	end_user_pfn >>= PAGE_SHIFT;	
++
++	end = end_user_pfn<<PAGE_SHIFT;
++	i = e820.nr_map-1;
++	current_end = e820.map[i].addr + e820.map[i].size;
++
++	if (current_end < end) {
++		/*
++                 * The e820 map ends before our requested size so
++                 * extend the final entry to the requested address.
++                 */
++		if (e820.map[i].type == E820_RAM)
++			e820.map[i].size = end - e820.map[i].addr;
++		else
++			add_memory_region(current_end, end - current_end, E820_RAM);
++	}
++} 
++
++void __init parse_memmapopt(char *p, char **from)
++{
++	unsigned long long start_at, mem_size;
++
++	mem_size = memparse(p, from);
++	p = *from;
++	if (*p == '@') {
++		start_at = memparse(p+1, from);
++		add_memory_region(start_at, mem_size, E820_RAM);
++	} else if (*p == '#') {
++		start_at = memparse(p+1, from);
++		add_memory_region(start_at, mem_size, E820_ACPI);
++	} else if (*p == '$') {
++		start_at = memparse(p+1, from);
++		add_memory_region(start_at, mem_size, E820_RESERVED);
++	} else {
++		end_user_pfn = (mem_size >> PAGE_SHIFT);
++	}
++	p = *from;
++}
++
++unsigned long pci_mem_start = 0xaeedbabe;
++EXPORT_SYMBOL(pci_mem_start);
++
++/*
++ * Search for the biggest gap in the low 32 bits of the e820
++ * memory space.  We pass this space to PCI to assign MMIO resources
++ * for hotplug or unconfigured devices in.
++ * Hopefully the BIOS let enough space left.
++ */
++__init void e820_setup_gap(struct e820entry *e820, int nr_map)
++{
++	unsigned long gapstart, gapsize, round;
++	unsigned long last;
++	int i;
++	int found = 0;
++
++	last = 0x100000000ull;
++	gapstart = 0x10000000;
++	gapsize = 0x400000;
++	i = nr_map;
++	while (--i >= 0) {
++		unsigned long long start = e820[i].addr;
++		unsigned long long end = start + e820[i].size;
++
++		/*
++		 * Since "last" is at most 4GB, we know we'll
++		 * fit in 32 bits if this condition is true
++		 */
++		if (last > end) {
++			unsigned long gap = last - end;
++
++			if (gap > gapsize) {
++				gapsize = gap;
++				gapstart = end;
++				found = 1;
++			}
++		}
++		if (start < last)
++			last = start;
++	}
++
++	if (!found) {
++		gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
++		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n"
++		       KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n");
++	}
++
++	/*
++	 * See how much we want to round up: start off with
++	 * rounding to the next 1MB area.
++	 */
++	round = 0x100000;
++	while ((gapsize >> 4) > round)
++		round += round;
++	/* Fun with two's complement */
++	pci_mem_start = (gapstart + round) & -round;
++
++	printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
++		pci_mem_start, gapstart, gapsize);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2007-06-12 13:13:01.000000000 +0200
+@@ -0,0 +1,302 @@
++#include <linux/console.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/screen_info.h>
++#include <asm/io.h>
++#include <asm/processor.h>
++#include <asm/fcntl.h>
++
++/* Simple VGA output */
++
++#ifdef __i386__
++#include <asm/setup.h>
++#define VGABASE		(__ISA_IO_base + 0xb8000)
++#else
++#include <asm/bootsetup.h>
++#define VGABASE		((void __iomem *)0xffffffff800b8000UL)
++#endif
++
++#ifndef CONFIG_XEN
++static int max_ypos = 25, max_xpos = 80;
++static int current_ypos = 25, current_xpos = 0; 
++
++static void early_vga_write(struct console *con, const char *str, unsigned n)
++{
++	char c;
++	int  i, k, j;
++
++	while ((c = *str++) != '\0' && n-- > 0) {
++		if (current_ypos >= max_ypos) {
++			/* scroll 1 line up */
++			for (k = 1, j = 0; k < max_ypos; k++, j++) {
++				for (i = 0; i < max_xpos; i++) {
++					writew(readw(VGABASE+2*(max_xpos*k+i)),
++					       VGABASE + 2*(max_xpos*j + i));
++				}
++			}
++			for (i = 0; i < max_xpos; i++)
++				writew(0x720, VGABASE + 2*(max_xpos*j + i));
++			current_ypos = max_ypos-1;
++		}
++		if (c == '\n') {
++			current_xpos = 0;
++			current_ypos++;
++		} else if (c != '\r')  {
++			writew(((0x7 << 8) | (unsigned short) c),
++			       VGABASE + 2*(max_xpos*current_ypos +
++						current_xpos++));
++			if (current_xpos >= max_xpos) {
++				current_xpos = 0;
++				current_ypos++;
++			}
++		}
++	}
++}
++
++static struct console early_vga_console = {
++	.name =		"earlyvga",
++	.write =	early_vga_write,
++	.flags =	CON_PRINTBUFFER,
++	.index =	-1,
++};
++
++/* Serial functions loosely based on a similar package from Klaus P. Gerlicher */
++
++static int early_serial_base = 0x3f8;  /* ttyS0 */
++
++#define XMTRDY          0x20
++
++#define DLAB		0x80
++
++#define TXR             0       /*  Transmit register (WRITE) */
++#define RXR             0       /*  Receive register  (READ)  */
++#define IER             1       /*  Interrupt Enable          */
++#define IIR             2       /*  Interrupt ID              */
++#define FCR             2       /*  FIFO control              */
++#define LCR             3       /*  Line control              */
++#define MCR             4       /*  Modem control             */
++#define LSR             5       /*  Line Status               */
++#define MSR             6       /*  Modem Status              */
++#define DLL             0       /*  Divisor Latch Low         */
++#define DLH             1       /*  Divisor latch High        */
++
++static int early_serial_putc(unsigned char ch)
++{
++	unsigned timeout = 0xffff;
++	while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
++		cpu_relax();
++	outb(ch, early_serial_base + TXR);
++	return timeout ? 0 : -1;
++}
++
++static void early_serial_write(struct console *con, const char *s, unsigned n)
++{
++	while (*s && n-- > 0) {
++		early_serial_putc(*s);
++		if (*s == '\n')
++			early_serial_putc('\r');
++		s++;
++	}
++}
++
++#define DEFAULT_BAUD 9600
++
++static __init void early_serial_init(char *s)
++{
++	unsigned char c;
++	unsigned divisor;
++	unsigned baud = DEFAULT_BAUD;
++	char *e;
++
++	if (*s == ',')
++		++s;
++
++	if (*s) {
++		unsigned port;
++		if (!strncmp(s,"0x",2)) {
++			early_serial_base = simple_strtoul(s, &e, 16);
++		} else {
++			static int bases[] = { 0x3f8, 0x2f8 };
++
++			if (!strncmp(s,"ttyS",4))
++				s += 4;
++			port = simple_strtoul(s, &e, 10);
++			if (port > 1 || s == e)
++				port = 0;
++			early_serial_base = bases[port];
++		}
++		s += strcspn(s, ",");
++		if (*s == ',')
++			s++;
++	}
++
++	outb(0x3, early_serial_base + LCR);	/* 8n1 */
++	outb(0, early_serial_base + IER);	/* no interrupt */
++	outb(0, early_serial_base + FCR);	/* no fifo */
++	outb(0x3, early_serial_base + MCR);	/* DTR + RTS */
++
++	if (*s) {
++		baud = simple_strtoul(s, &e, 0);
++		if (baud == 0 || s == e)
++			baud = DEFAULT_BAUD;
++	}
++
++	divisor = 115200 / baud;
++	c = inb(early_serial_base + LCR);
++	outb(c | DLAB, early_serial_base + LCR);
++	outb(divisor & 0xff, early_serial_base + DLL);
++	outb((divisor >> 8) & 0xff, early_serial_base + DLH);
++	outb(c & ~DLAB, early_serial_base + LCR);
++}
++
++#else /* CONFIG_XEN */
++
++static void
++early_serial_write(struct console *con, const char *s, unsigned count)
++{
++	int n;
++
++	while (count > 0) {
++		n = HYPERVISOR_console_io(CONSOLEIO_write, count, (char *)s);
++		if (n <= 0)
++			break;
++		count -= n;
++		s += n;
++	}
++} 
++
++static __init void early_serial_init(char *s)
++{
++}
++
++/*
++ * No early VGA console on Xen, as we do not have convenient ISA-space
++ * mappings. Someone should fix this for domain 0. For now, use fake serial.
++ */
++#define early_vga_console early_serial_console
++
++#endif
++
++static struct console early_serial_console = {
++	.name =		"earlyser",
++	.write =	early_serial_write,
++	.flags =	CON_PRINTBUFFER,
++	.index =	-1,
++};
++
++/* Console interface to a host file on AMD's SimNow! */
++
++static int simnow_fd;
++
++enum {
++	MAGIC1 = 0xBACCD00A,
++	MAGIC2 = 0xCA110000,
++	XOPEN = 5,
++	XWRITE = 4,
++};
++
++static noinline long simnow(long cmd, long a, long b, long c)
++{
++	long ret;
++	asm volatile("cpuid" :
++		     "=a" (ret) :
++		     "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
++	return ret;
++}
++
++void __init simnow_init(char *str)
++{
++	char *fn = "klog";
++	if (*str == '=')
++		fn = ++str;
++	/* error ignored */
++	simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
++}
++
++static void simnow_write(struct console *con, const char *s, unsigned n)
++{
++	simnow(XWRITE, simnow_fd, (unsigned long)s, n);
++}
++
++static struct console simnow_console = {
++	.name =		"simnow",
++	.write =	simnow_write,
++	.flags =	CON_PRINTBUFFER,
++	.index =	-1,
++};
++
++/* Direct interface for emergencies */
++struct console *early_console = &early_vga_console;
++static int early_console_initialized = 0;
++
++void early_printk(const char *fmt, ...)
++{
++	char buf[512];
++	int n;
++	va_list ap;
++
++	va_start(ap,fmt);
++	n = vscnprintf(buf,512,fmt,ap);
++	early_console->write(early_console,buf,n);
++	va_end(ap);
++}
++
++static int __initdata keep_early;
++
++int __init setup_early_printk(char *opt)
++{
++	char *space;
++	char buf[256];
++
++	if (early_console_initialized)
++		return 1;
++
++	strlcpy(buf,opt,sizeof(buf));
++	space = strchr(buf, ' ');
++	if (space)
++		*space = 0;
++
++	if (strstr(buf,"keep"))
++		keep_early = 1;
++
++	if (!strncmp(buf, "serial", 6)) {
++		early_serial_init(buf + 6);
++		early_console = &early_serial_console;
++	} else if (!strncmp(buf, "ttyS", 4)) {
++		early_serial_init(buf);
++		early_console = &early_serial_console;
++	} else if (!strncmp(buf, "vga", 3)
++#ifndef CONFIG_XEN
++	           && SCREEN_INFO.orig_video_isVGA == 1) {
++		max_xpos = SCREEN_INFO.orig_video_cols;
++		max_ypos = SCREEN_INFO.orig_video_lines;
++		current_ypos = SCREEN_INFO.orig_y;
++#else
++	           || !strncmp(buf, "xen", 3)) {
++#endif
++		early_console = &early_vga_console;
++ 	} else if (!strncmp(buf, "simnow", 6)) {
++ 		simnow_init(buf + 6);
++ 		early_console = &simnow_console;
++ 		keep_early = 1;
++	}
++	early_console_initialized = 1;
++	register_console(early_console);
++	return 0;
++}
++
++void __init disable_early_printk(void)
++{
++	if (!early_console_initialized || !early_console)
++		return;
++	if (!keep_early) {
++		printk("disabling early console\n");
++		unregister_console(early_console);
++		early_console_initialized = 0;
++	} else {
++		printk("keeping early console\n");
++	}
++}
++
++__setup("earlyprintk=", setup_early_printk);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,1317 @@
++/*
++ *  linux/arch/x86_64/entry.S
++ *
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
++ *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
++ * 
++ *  $Id$
++ *
++ *  Jun Nakajima <jun.nakajima@intel.com>
++ *  Asit Mallick <asit.k.mallick@intel.com>
++ *      Modified for Xen
++ */
++
++/*
++ * entry.S contains the system-call and fault low-level handling routines.
++ *
++ * NOTE: This code handles signal-recognition, which happens every time
++ * after an interrupt and after each system call.
++ * 
++ * Normal syscalls and interrupts don't save a full stack frame, this is 
++ * only done for syscall tracing, signals or fork/exec et.al.
++ * 
++ * A note on terminology:	 
++ * - top of stack: Architecture defined interrupt frame from SS to RIP 
++ * at the top of the kernel process stack.	
++ * - partial stack frame: partially saved registers upto R11.
++ * - full stack frame: Like partial stack frame, but all register saved. 
++ *	
++ * TODO:	 
++ * - schedule it carefully for the final hardware.
++ */
++
++#define ASSEMBLY 1
++#include <linux/linkage.h>
++#include <asm/segment.h>
++#include <asm/smp.h>
++#include <asm/cache.h>
++#include <asm/errno.h>
++#include <asm/dwarf2.h>
++#include <asm/calling.h>
++#include <asm/asm-offsets.h>
++#include <asm/msr.h>
++#include <asm/unistd.h>
++#include <asm/thread_info.h>
++#include <asm/hw_irq.h>
++#include <asm/page.h>
++#include <asm/irqflags.h>
++#include <asm/errno.h>
++#include <xen/interface/arch-x86_64.h>
++#include <xen/interface/features.h>
++
++#include "xen_entry.S"
++	
++	.code64
++
++#ifndef CONFIG_PREEMPT
++#define retint_kernel retint_restore_args
++#endif	
++
++
++.macro TRACE_IRQS_IRETQ offset=ARGOFFSET
++#ifdef CONFIG_TRACE_IRQFLAGS
++	bt   $9,EFLAGS-\offset(%rsp)	/* interrupts off? */
++	jnc  1f
++	TRACE_IRQS_ON
++1:
++#endif
++.endm
++
++NMI_MASK = 0x80000000
++	
++/*
++ * C code is not supposed to know about undefined top of stack. Every time 
++ * a C function with an pt_regs argument is called from the SYSCALL based 
++ * fast path FIXUP_TOP_OF_STACK is needed.
++ * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
++ * manipulation.
++ */        	
++		
++	/* %rsp:at FRAMEEND */ 
++	.macro FIXUP_TOP_OF_STACK tmp
++	movq    $__USER_CS,CS(%rsp)
++	movq 	$-1,RCX(%rsp)
++	.endm
++
++	.macro RESTORE_TOP_OF_STACK tmp,offset=0
++	.endm
++
++	.macro FAKE_STACK_FRAME child_rip
++	/* push in order ss, rsp, eflags, cs, rip */
++	xorl %eax, %eax
++	pushq %rax /* ss */
++	CFI_ADJUST_CFA_OFFSET	8
++	/*CFI_REL_OFFSET	ss,0*/
++	pushq %rax /* rsp */
++	CFI_ADJUST_CFA_OFFSET	8
++	CFI_REL_OFFSET	rsp,0
++	pushq $(1<<9) /* eflags - interrupts on */
++	CFI_ADJUST_CFA_OFFSET	8
++	/*CFI_REL_OFFSET	rflags,0*/
++	pushq $__KERNEL_CS /* cs */
++	CFI_ADJUST_CFA_OFFSET	8
++	/*CFI_REL_OFFSET	cs,0*/
++	pushq \child_rip /* rip */
++	CFI_ADJUST_CFA_OFFSET	8
++	CFI_REL_OFFSET	rip,0
++	pushq	%rax /* orig rax */
++	CFI_ADJUST_CFA_OFFSET	8
++	.endm
++
++	.macro UNFAKE_STACK_FRAME
++	addq $8*6, %rsp
++	CFI_ADJUST_CFA_OFFSET	-(6*8)
++	.endm
++
++	.macro	CFI_DEFAULT_STACK start=1,adj=0
++	.if \start
++	CFI_STARTPROC	simple
++	CFI_DEF_CFA	rsp,SS+8 - \adj*ARGOFFSET
++	.else
++	CFI_DEF_CFA_OFFSET SS+8 - \adj*ARGOFFSET
++	.endif
++	.if \adj == 0
++	CFI_REL_OFFSET	r15,R15
++	CFI_REL_OFFSET	r14,R14
++	CFI_REL_OFFSET	r13,R13
++	CFI_REL_OFFSET	r12,R12
++	CFI_REL_OFFSET	rbp,RBP
++	CFI_REL_OFFSET	rbx,RBX
++	.endif
++	CFI_REL_OFFSET	r11,R11 - \adj*ARGOFFSET
++	CFI_REL_OFFSET	r10,R10 - \adj*ARGOFFSET
++	CFI_REL_OFFSET	r9,R9 - \adj*ARGOFFSET
++	CFI_REL_OFFSET	r8,R8 - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rax,RAX - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rcx,RCX - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rdx,RDX - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rsi,RSI - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rdi,RDI - \adj*ARGOFFSET
++	CFI_REL_OFFSET	rip,RIP - \adj*ARGOFFSET
++	/*CFI_REL_OFFSET	cs,CS - \adj*ARGOFFSET*/
++	/*CFI_REL_OFFSET	rflags,EFLAGS - \adj*ARGOFFSET*/
++	CFI_REL_OFFSET	rsp,RSP - \adj*ARGOFFSET
++	/*CFI_REL_OFFSET	ss,SS - \adj*ARGOFFSET*/
++	.endm
++
++        /*
++         * Must be consistent with the definition in arch-x86/xen-x86_64.h:
++         *     struct iret_context {
++         *        u64 rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
++         *     };
++         * with rax, r11, and rcx being taken care of in the hypercall stub.
++         */
++	.macro HYPERVISOR_IRET flag
++	testb $3,1*8(%rsp)
++	jnz   2f
++	testl $NMI_MASK,2*8(%rsp)
++	jnz   2f
++
++	cmpb  $0,(xen_features+XENFEAT_supervisor_mode_kernel)(%rip)
++	jne   1f
++
++	/* Direct iret to kernel space. Correct CS and SS. */
++	orl   $3,1*8(%rsp)
++	orl   $3,4*8(%rsp)
++1:	iretq
++
++2:	/* Slow iret via hypervisor. */
++	andl  $~NMI_MASK, 2*8(%rsp)
++	pushq $\flag
++	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
++	.endm
++
++/*
++ * A newly forked process directly context switches into this.
++ */ 	
++/* rdi:	prev */	
++ENTRY(ret_from_fork)
++	CFI_DEFAULT_STACK
++	push kernel_eflags(%rip)
++	CFI_ADJUST_CFA_OFFSET 4
++	popf				# reset kernel eflags
++	CFI_ADJUST_CFA_OFFSET -4
++	call schedule_tail
++	GET_THREAD_INFO(%rcx)
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
++	jnz rff_trace
++rff_action:	
++	RESTORE_REST
++	testl $3,CS-ARGOFFSET(%rsp)	# from kernel_thread?
++	je   int_ret_from_sys_call
++	testl $_TIF_IA32,threadinfo_flags(%rcx)
++	jnz  int_ret_from_sys_call
++	RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
++	jmp ret_from_sys_call
++rff_trace:
++	movq %rsp,%rdi
++	call syscall_trace_leave
++	GET_THREAD_INFO(%rcx)	
++	jmp rff_action
++	CFI_ENDPROC
++END(ret_from_fork)
++
++/*
++ * initial frame state for interrupts and exceptions
++ */
++	.macro _frame ref
++	CFI_STARTPROC simple
++	CFI_DEF_CFA rsp,SS+8-\ref
++	/*CFI_REL_OFFSET ss,SS-\ref*/
++	CFI_REL_OFFSET rsp,RSP-\ref
++	/*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
++	/*CFI_REL_OFFSET cs,CS-\ref*/
++	CFI_REL_OFFSET rip,RIP-\ref
++	.endm
++
++/*
++ * System call entry. Upto 6 arguments in registers are supported.
++ *
++ * SYSCALL does not save anything on the stack and does not change the
++ * stack pointer.
++ */
++		
++/*
++ * Register setup:	
++ * rax  system call number
++ * rdi  arg0
++ * rcx  return address for syscall/sysret, C arg3 
++ * rsi  arg1
++ * rdx  arg2	
++ * r10  arg3 	(--> moved to rcx for C)
++ * r8   arg4
++ * r9   arg5
++ * r11  eflags for syscall/sysret, temporary for C
++ * r12-r15,rbp,rbx saved by C code, not touched. 		
++ * 
++ * Interrupts are enabled on entry.
++ * Only called from user space.
++ *
++ * XXX	if we had a free scratch register we could save the RSP into the stack frame
++ *      and report it properly in ps. Unfortunately we haven't.
++ *
++ * When user can change the frames always force IRET. That is because
++ * it deals with uncanonical addresses better. SYSRET has trouble
++ * with them due to bugs in both AMD and Intel CPUs.
++ */ 			 		
++
++ENTRY(system_call)
++	_frame (RIP-0x10)
++	SAVE_ARGS -8,0
++	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
++	GET_THREAD_INFO(%rcx)
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
++	CFI_REMEMBER_STATE
++	jnz tracesys
++	cmpq $__NR_syscall_max,%rax
++	ja badsys
++	movq %r10,%rcx
++	call *sys_call_table(,%rax,8)  # XXX:	 rip relative
++	movq %rax,RAX-ARGOFFSET(%rsp)
++/*
++ * Syscall return path ending with SYSRET (fast path)
++ * Has incomplete stack frame and undefined top of stack. 
++ */		
++	.globl ret_from_sys_call
++ret_from_sys_call:
++	movl $_TIF_ALLWORK_MASK,%edi
++	/* edi:	flagmask */
++sysret_check:		
++	GET_THREAD_INFO(%rcx)
++        XEN_BLOCK_EVENTS(%rsi)        
++	TRACE_IRQS_OFF
++	movl threadinfo_flags(%rcx),%edx
++	andl %edi,%edx
++	CFI_REMEMBER_STATE
++	jnz  sysret_careful 
++	/*
++	 * sysretq will re-enable interrupts:
++	 */
++	TRACE_IRQS_ON
++        XEN_UNBLOCK_EVENTS(%rsi)                
++	RESTORE_ARGS 0,8,0
++        HYPERVISOR_IRET VGCF_IN_SYSCALL
++
++	/* Handle reschedules */
++	/* edx:	work, edi: workmask */	
++sysret_careful:
++	CFI_RESTORE_STATE
++	bt $TIF_NEED_RESCHED,%edx
++	jnc sysret_signal
++	TRACE_IRQS_ON
++	XEN_UNBLOCK_EVENTS(%rsi)
++	pushq %rdi
++	CFI_ADJUST_CFA_OFFSET 8
++	call schedule
++	popq  %rdi
++	CFI_ADJUST_CFA_OFFSET -8
++	jmp sysret_check
++
++	/* Handle a signal */ 
++sysret_signal:
++	TRACE_IRQS_ON
++/*	sti */
++        XEN_UNBLOCK_EVENTS(%rsi)        
++	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
++	jz    1f
++
++	/* Really a signal */
++	/* edx:	work flags (arg3) */
++	leaq do_notify_resume(%rip),%rax
++	leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
++	xorl %esi,%esi # oldset -> arg2
++	call ptregscall_common
++1:	movl $_TIF_NEED_RESCHED,%edi
++	/* Use IRET because user could have changed frame. This
++	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
++	XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	jmp int_with_check
++	
++badsys:
++	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
++	jmp ret_from_sys_call
++
++	/* Do syscall tracing */
++tracesys:			 
++	CFI_RESTORE_STATE
++	SAVE_REST
++	movq $-ENOSYS,RAX(%rsp)
++	FIXUP_TOP_OF_STACK %rdi
++	movq %rsp,%rdi
++	call syscall_trace_enter
++	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	RESTORE_REST
++	cmpq $__NR_syscall_max,%rax
++	ja  1f
++	movq %r10,%rcx	/* fixup for C */
++	call *sys_call_table(,%rax,8)
++1:	movq %rax,RAX-ARGOFFSET(%rsp)
++	/* Use IRET because user could have changed frame */
++	jmp int_ret_from_sys_call
++	CFI_ENDPROC
++END(system_call)
++		
++/* 
++ * Syscall return path ending with IRET.
++ * Has correct top of stack, but partial stack frame.
++ */ 	
++ENTRY(int_ret_from_sys_call)
++	CFI_STARTPROC	simple
++	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
++	/*CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
++	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
++	/*CFI_REL_OFFSET	rflags,EFLAGS-ARGOFFSET*/
++	/*CFI_REL_OFFSET	cs,CS-ARGOFFSET*/
++	CFI_REL_OFFSET	rip,RIP-ARGOFFSET
++	CFI_REL_OFFSET	rdx,RDX-ARGOFFSET
++	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
++	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
++	CFI_REL_OFFSET	rdi,RDI-ARGOFFSET
++	CFI_REL_OFFSET	rsi,RSI-ARGOFFSET
++	CFI_REL_OFFSET	r8,R8-ARGOFFSET
++	CFI_REL_OFFSET	r9,R9-ARGOFFSET
++	CFI_REL_OFFSET	r10,R10-ARGOFFSET
++	CFI_REL_OFFSET	r11,R11-ARGOFFSET
++        XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	testb $3,CS-ARGOFFSET(%rsp)
++        jnz 1f
++        /* Need to set the proper %ss (not NULL) for ring 3 iretq */
++        movl $__KERNEL_DS,SS-ARGOFFSET(%rsp)
++        jmp retint_restore_args   # retrun from ring3 kernel
++1:              
++	movl $_TIF_ALLWORK_MASK,%edi
++	/* edi:	mask to check */
++int_with_check:
++	GET_THREAD_INFO(%rcx)
++	movl threadinfo_flags(%rcx),%edx
++	andl %edi,%edx
++	jnz   int_careful
++	andl    $~TS_COMPAT,threadinfo_status(%rcx)
++	jmp   retint_restore_args
++
++	/* Either reschedule or signal or syscall exit tracking needed. */
++	/* First do a reschedule test. */
++	/* edx:	work, edi: workmask */
++int_careful:
++	bt $TIF_NEED_RESCHED,%edx
++	jnc  int_very_careful
++	TRACE_IRQS_ON
++/*	sti */
++        XEN_UNBLOCK_EVENTS(%rsi)
++	pushq %rdi
++	CFI_ADJUST_CFA_OFFSET 8
++	call schedule
++	popq %rdi
++	CFI_ADJUST_CFA_OFFSET -8
++	XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	jmp int_with_check
++
++	/* handle signals and tracing -- both require a full stack frame */
++int_very_careful:
++	TRACE_IRQS_ON
++/*	sti */
++        XEN_UNBLOCK_EVENTS(%rsi)
++	SAVE_REST
++	/* Check for syscall exit trace */	
++	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
++	jz int_signal
++	pushq %rdi
++	CFI_ADJUST_CFA_OFFSET 8
++	leaq 8(%rsp),%rdi	# &ptregs -> arg1	
++	call syscall_trace_leave
++	popq %rdi
++	CFI_ADJUST_CFA_OFFSET -8
++	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
++	XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	jmp int_restore_rest
++	
++int_signal:
++	testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
++	jz 1f
++	movq %rsp,%rdi		# &ptregs -> arg1
++	xorl %esi,%esi		# oldset -> arg2
++	call do_notify_resume
++1:	movl $_TIF_NEED_RESCHED,%edi	
++int_restore_rest:
++	RESTORE_REST
++	XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	jmp int_with_check
++	CFI_ENDPROC
++END(int_ret_from_sys_call)
++		
++/* 
++ * Certain special system calls that need to save a complete full stack frame.
++ */ 								
++	
++	.macro PTREGSCALL label,func,arg
++	.globl \label
++\label:
++	leaq	\func(%rip),%rax
++	leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
++	jmp	ptregscall_common
++END(\label)
++	.endm
++
++	CFI_STARTPROC
++
++	PTREGSCALL stub_clone, sys_clone, %r8
++	PTREGSCALL stub_fork, sys_fork, %rdi
++	PTREGSCALL stub_vfork, sys_vfork, %rdi
++	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
++	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
++	PTREGSCALL stub_iopl, sys_iopl, %rsi
++
++ENTRY(ptregscall_common)
++	popq %r11
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_REGISTER rip, r11
++	SAVE_REST
++	movq %r11, %r15
++	CFI_REGISTER rip, r15
++	FIXUP_TOP_OF_STACK %r11
++	call *%rax
++	RESTORE_TOP_OF_STACK %r11
++	movq %r15, %r11
++	CFI_REGISTER rip, r11
++	RESTORE_REST
++	pushq %r11
++	CFI_ADJUST_CFA_OFFSET 8
++	CFI_REL_OFFSET rip, 0
++	ret
++	CFI_ENDPROC
++END(ptregscall_common)
++	
++ENTRY(stub_execve)
++	CFI_STARTPROC
++	popq %r11
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_REGISTER rip, r11
++	SAVE_REST
++	FIXUP_TOP_OF_STACK %r11
++	call sys_execve
++	RESTORE_TOP_OF_STACK %r11
++	movq %rax,RAX(%rsp)
++	RESTORE_REST
++	jmp int_ret_from_sys_call
++	CFI_ENDPROC
++END(stub_execve)
++	
++/*
++ * sigreturn is special because it needs to restore all registers on return.
++ * This cannot be done with SYSRET, so use the IRET return path instead.
++ */                
++ENTRY(stub_rt_sigreturn)
++	CFI_STARTPROC
++	addq $8, %rsp
++	CFI_ADJUST_CFA_OFFSET	-8
++	SAVE_REST
++	movq %rsp,%rdi
++	FIXUP_TOP_OF_STACK %r11
++	call sys_rt_sigreturn
++	movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
++	RESTORE_REST
++	jmp int_ret_from_sys_call
++	CFI_ENDPROC
++END(stub_rt_sigreturn)
++
++/* initial frame state for interrupts (and exceptions without error code) */
++#define INTR_FRAME _frame (RIP-0x10); \
++	CFI_REL_OFFSET rcx,0; \
++	CFI_REL_OFFSET r11,8
++
++/* initial frame state for exceptions with error code (and interrupts with
++   vector already pushed) */
++#define XCPT_FRAME _frame (RIP-0x18); \
++	CFI_REL_OFFSET rcx,0; \
++	CFI_REL_OFFSET r11,8
++
++/* 
++ * Interrupt exit.
++ *
++ */ 
++
++retint_check:
++	CFI_DEFAULT_STACK adj=1
++	movl threadinfo_flags(%rcx),%edx
++	andl %edi,%edx
++	CFI_REMEMBER_STATE
++	jnz  retint_careful
++retint_restore_args:
++	movl EFLAGS-REST_SKIP(%rsp), %eax
++	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
++	XEN_GET_VCPU_INFO(%rsi)
++	andb evtchn_upcall_mask(%rsi),%al
++	andb $1,%al			# EAX[0] == IRET_EFLAGS.IF & event_mask
++	jnz restore_all_enable_events	#        != 0 => enable event delivery
++	XEN_PUT_VCPU_INFO(%rsi)
++		
++	RESTORE_ARGS 0,8,0
++	HYPERVISOR_IRET 0
++	
++	/* edi: workmask, edx: work */
++retint_careful:
++	CFI_RESTORE_STATE
++	bt    $TIF_NEED_RESCHED,%edx
++	jnc   retint_signal
++	TRACE_IRQS_ON
++	XEN_UNBLOCK_EVENTS(%rsi)
++/*	sti */        
++	pushq %rdi
++	CFI_ADJUST_CFA_OFFSET	8
++	call  schedule
++	popq %rdi		
++	CFI_ADJUST_CFA_OFFSET	-8
++	GET_THREAD_INFO(%rcx)
++	XEN_BLOCK_EVENTS(%rsi)		
++/*	cli */
++	TRACE_IRQS_OFF
++	jmp retint_check
++	
++retint_signal:
++	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
++	jz    retint_restore_args
++	TRACE_IRQS_ON
++        XEN_UNBLOCK_EVENTS(%rsi)
++	SAVE_REST
++	movq $-1,ORIG_RAX(%rsp) 			
++	xorl %esi,%esi		# oldset
++	movq %rsp,%rdi		# &pt_regs
++	call do_notify_resume
++	RESTORE_REST
++        XEN_BLOCK_EVENTS(%rsi)		
++	TRACE_IRQS_OFF
++	movl $_TIF_NEED_RESCHED,%edi
++	GET_THREAD_INFO(%rcx)
++	jmp retint_check
++
++#ifdef CONFIG_PREEMPT
++	/* Returning to kernel space. Check if we need preemption */
++	/* rcx:	 threadinfo. interrupts off. */
++	.p2align
++retint_kernel:	
++	cmpl $0,threadinfo_preempt_count(%rcx)
++	jnz  retint_restore_args
++	bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
++	jnc  retint_restore_args
++	bt   $9,EFLAGS-ARGOFFSET(%rsp)	/* interrupts off? */
++	jnc  retint_restore_args
++	call preempt_schedule_irq
++	jmp retint_kernel       /* check again */
++#endif	
++
++	CFI_ENDPROC
++END(retint_check)
++	
++#ifndef CONFIG_XEN
++/*
++ * APIC interrupts.
++ */		
++	.macro apicinterrupt num,func
++	INTR_FRAME
++	pushq $~(\num)
++	CFI_ADJUST_CFA_OFFSET 8
++	interrupt \func
++	jmp error_entry
++	CFI_ENDPROC
++	.endm
++
++ENTRY(thermal_interrupt)
++	apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
++END(thermal_interrupt)
++
++ENTRY(threshold_interrupt)
++	apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
++END(threshold_interrupt)
++
++#ifdef CONFIG_SMP	
++ENTRY(reschedule_interrupt)
++	apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
++END(reschedule_interrupt)
++
++	.macro INVALIDATE_ENTRY num
++ENTRY(invalidate_interrupt\num)
++	apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt	
++END(invalidate_interrupt\num)
++	.endm
++
++	INVALIDATE_ENTRY 0
++	INVALIDATE_ENTRY 1
++	INVALIDATE_ENTRY 2
++	INVALIDATE_ENTRY 3
++	INVALIDATE_ENTRY 4
++	INVALIDATE_ENTRY 5
++	INVALIDATE_ENTRY 6
++	INVALIDATE_ENTRY 7
++
++ENTRY(call_function_interrupt)
++	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
++END(call_function_interrupt)
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC	
++ENTRY(apic_timer_interrupt)
++	apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
++END(apic_timer_interrupt)
++
++ENTRY(error_interrupt)
++	apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
++END(error_interrupt)
++
++ENTRY(spurious_interrupt)
++	apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
++END(spurious_interrupt)
++#endif
++#endif /* !CONFIG_XEN */
++				
++/*
++ * Exception entry points.
++ */ 		
++	.macro zeroentry sym
++	INTR_FRAME
++        movq (%rsp),%rcx
++	CFI_RESTORE rcx
++        movq 8(%rsp),%r11
++	CFI_RESTORE r11
++        addq $0x10,%rsp /* skip rcx and r11 */
++	CFI_ADJUST_CFA_OFFSET -0x10
++	pushq $0	/* push error code/oldrax */ 
++	CFI_ADJUST_CFA_OFFSET 8
++	pushq %rax	/* push real oldrax to the rdi slot */ 
++	CFI_ADJUST_CFA_OFFSET 8
++	CFI_REL_OFFSET rax,0
++	leaq  \sym(%rip),%rax
++	jmp error_entry
++	CFI_ENDPROC
++	.endm	
++
++	.macro errorentry sym
++	XCPT_FRAME
++        movq (%rsp),%rcx
++	CFI_RESTORE rcx
++        movq 8(%rsp),%r11
++	CFI_RESTORE r11
++        addq $0x10,%rsp /* rsp points to the error code */
++	CFI_ADJUST_CFA_OFFSET -0x10
++	pushq %rax
++	CFI_ADJUST_CFA_OFFSET 8
++	CFI_REL_OFFSET rax,0
++	leaq  \sym(%rip),%rax
++	jmp error_entry
++	CFI_ENDPROC
++	.endm
++
++#if 0 /* not XEN */
++	/* error code is on the stack already */
++	/* handle NMI like exceptions that can happen everywhere */
++	.macro paranoidentry sym, ist=0, irqtrace=1
++        movq (%rsp),%rcx
++        movq 8(%rsp),%r11
++        addq $0x10,%rsp /* skip rcx and r11 */        
++	SAVE_ALL
++	cld
++#if 0 /* not XEN */
++	movl $1,%ebx
++	movl  $MSR_GS_BASE,%ecx
++	rdmsr
++	testl %edx,%edx
++	js    1f
++	swapgs
++	xorl  %ebx,%ebx
++1:
++#endif
++	.if \ist
++	movq	%gs:pda_data_offset, %rbp
++	.endif
++	movq %rsp,%rdi
++	movq ORIG_RAX(%rsp),%rsi
++	movq $-1,ORIG_RAX(%rsp)
++	.if \ist
++	subq	$EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
++	.endif
++	call \sym
++	.if \ist
++	addq	$EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
++	.endif
++/*	cli */
++	XEN_BLOCK_EVENTS(%rsi)		
++	.if \irqtrace
++	TRACE_IRQS_OFF
++	.endif
++	.endm
++
++	/*
++ 	 * "Paranoid" exit path from exception stack.
++  	 * Paranoid because this is used by NMIs and cannot take
++	 * any kernel state for granted.
++	 * We don't do kernel preemption checks here, because only
++	 * NMI should be common and it does not enable IRQs and
++	 * cannot get reschedule ticks.
++	 *
++	 * "trace" is 0 for the NMI handler only, because irq-tracing
++	 * is fundamentally NMI-unsafe. (we cannot change the soft and
++	 * hard flags at once, atomically)
++	 */
++	.macro paranoidexit trace=1
++	/* ebx:	no swapgs flag */
++paranoid_exit\trace:
++	testl %ebx,%ebx				/* swapgs needed? */
++	jnz paranoid_restore\trace
++	testl $3,CS(%rsp)
++	jnz   paranoid_userspace\trace
++paranoid_swapgs\trace:
++	TRACE_IRQS_IRETQ 0
++	swapgs
++paranoid_restore\trace:
++	RESTORE_ALL 8
++	iretq
++paranoid_userspace\trace:
++	GET_THREAD_INFO(%rcx)
++	movl threadinfo_flags(%rcx),%ebx
++	andl $_TIF_WORK_MASK,%ebx
++	jz paranoid_swapgs\trace
++	movq %rsp,%rdi			/* &pt_regs */
++	call sync_regs
++	movq %rax,%rsp			/* switch stack for scheduling */
++	testl $_TIF_NEED_RESCHED,%ebx
++	jnz paranoid_schedule\trace
++	movl %ebx,%edx			/* arg3: thread flags */
++	.if \trace
++	TRACE_IRQS_ON
++	.endif
++	sti
++	xorl %esi,%esi 			/* arg2: oldset */
++	movq %rsp,%rdi 			/* arg1: &pt_regs */
++	call do_notify_resume
++	cli
++	.if \trace
++	TRACE_IRQS_OFF
++	.endif
++	jmp paranoid_userspace\trace
++paranoid_schedule\trace:
++	.if \trace
++	TRACE_IRQS_ON
++	.endif
++	sti
++	call schedule
++	cli
++	.if \trace
++	TRACE_IRQS_OFF
++	.endif
++	jmp paranoid_userspace\trace
++	CFI_ENDPROC
++	.endm
++#endif
++
++/*
++ * Exception entry point. This expects an error code/orig_rax on the stack
++ * and the exception handler in %rax.	
++ */ 		  				
++ENTRY(error_entry)
++	_frame RDI
++	CFI_REL_OFFSET rax,0
++	/* rdi slot contains rax, oldrax contains error code */
++	cld	
++	subq  $14*8,%rsp
++	CFI_ADJUST_CFA_OFFSET	(14*8)
++	movq %rsi,13*8(%rsp)
++	CFI_REL_OFFSET	rsi,RSI
++	movq 14*8(%rsp),%rsi	/* load rax from rdi slot */
++	CFI_REGISTER	rax,rsi
++	movq %rdx,12*8(%rsp)
++	CFI_REL_OFFSET	rdx,RDX
++	movq %rcx,11*8(%rsp)
++	CFI_REL_OFFSET	rcx,RCX
++	movq %rsi,10*8(%rsp)	/* store rax */ 
++	CFI_REL_OFFSET	rax,RAX
++	movq %r8, 9*8(%rsp)
++	CFI_REL_OFFSET	r8,R8
++	movq %r9, 8*8(%rsp)
++	CFI_REL_OFFSET	r9,R9
++	movq %r10,7*8(%rsp)
++	CFI_REL_OFFSET	r10,R10
++	movq %r11,6*8(%rsp)
++	CFI_REL_OFFSET	r11,R11
++	movq %rbx,5*8(%rsp) 
++	CFI_REL_OFFSET	rbx,RBX
++	movq %rbp,4*8(%rsp) 
++	CFI_REL_OFFSET	rbp,RBP
++	movq %r12,3*8(%rsp) 
++	CFI_REL_OFFSET	r12,R12
++	movq %r13,2*8(%rsp) 
++	CFI_REL_OFFSET	r13,R13
++	movq %r14,1*8(%rsp) 
++	CFI_REL_OFFSET	r14,R14
++	movq %r15,(%rsp) 
++	CFI_REL_OFFSET	r15,R15
++#if 0        
++	cmpl $__KERNEL_CS,CS(%rsp)
++	CFI_REMEMBER_STATE
++	je  error_kernelspace
++#endif        
++error_call_handler:
++	movq %rdi, RDI(%rsp)            
++	CFI_REL_OFFSET	rdi,RDI
++	movq %rsp,%rdi
++	movq ORIG_RAX(%rsp),%rsi	# get error code 
++	movq $-1,ORIG_RAX(%rsp)
++	call *%rax
++error_exit:		
++	RESTORE_REST
++/*	cli */
++	XEN_BLOCK_EVENTS(%rsi)		
++	TRACE_IRQS_OFF
++	GET_THREAD_INFO(%rcx)	
++	testb $3,CS-ARGOFFSET(%rsp)
++	jz retint_kernel
++	movl  threadinfo_flags(%rcx),%edx
++	movl  $_TIF_WORK_MASK,%edi	
++	andl  %edi,%edx
++	jnz   retint_careful
++	/*
++	 * The iret might restore flags:
++	 */
++	TRACE_IRQS_IRETQ
++	jmp   retint_restore_args
++
++#if 0
++         /*
++         * We need to re-write the logic here because we don't do iretq to 
++         * to return to user mode. It's still possible that we get trap/fault
++         * in the kernel (when accessing buffers pointed to by system calls, 
++         * for example).
++         *
++         */           
++	CFI_RESTORE_STATE
++error_kernelspace:
++	incl %ebx
++       /* There are two places in the kernel that can potentially fault with
++          usergs. Handle them here. The exception handlers after
++	   iret run with kernel gs again, so don't set the user space flag.
++	   B stepping K8s sometimes report an truncated RIP for IRET 
++	   exceptions returning to compat mode. Check for these here too. */
++	leaq iret_label(%rip),%rbp
++	cmpq %rbp,RIP(%rsp) 
++	je   error_swapgs
++	movl %ebp,%ebp	/* zero extend */
++	cmpq %rbp,RIP(%rsp) 
++	je   error_swapgs
++	cmpq $gs_change,RIP(%rsp)
++        je   error_swapgs
++	jmp  error_sti
++#endif
++	CFI_ENDPROC
++END(error_entry)
++	
++ENTRY(hypervisor_callback)
++	zeroentry do_hypervisor_callback
++END(hypervisor_callback)
++        
++/*
++ * Copied from arch/xen/i386/kernel/entry.S
++ */               
++# A note on the "critical region" in our callback handler.
++# We want to avoid stacking callback handlers due to events occurring
++# during handling of the last event. To do this, we keep events disabled
++# until we've done all processing. HOWEVER, we must enable events before
++# popping the stack frame (can't be done atomically) and so it would still
++# be possible to get enough handler activations to overflow the stack.
++# Although unlikely, bugs of that kind are hard to track down, so we'd
++# like to avoid the possibility.
++# So, on entry to the handler we detect whether we interrupted an
++# existing activation in its critical region -- if so, we pop the current
++# activation and restart the handler using the previous one.
++ENTRY(do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
++	CFI_STARTPROC
++# Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
++# see the correct pointer to the pt_regs
++	movq %rdi, %rsp            # we don't return, adjust the stack frame
++	CFI_ENDPROC
++	CFI_DEFAULT_STACK
++11:	incl %gs:pda_irqcount
++	movq %rsp,%rbp
++	CFI_DEF_CFA_REGISTER rbp
++	cmovzq %gs:pda_irqstackptr,%rsp
++	pushq %rbp			# backlink for old unwinder
++	call evtchn_do_upcall
++	popq %rsp
++	CFI_DEF_CFA_REGISTER rsp
++	decl %gs:pda_irqcount
++	jmp  error_exit
++	CFI_ENDPROC
++END(do_hypervisor_callback)
++
++#ifdef CONFIG_X86_LOCAL_APIC
++KPROBE_ENTRY(nmi)
++	zeroentry do_nmi_callback
++ENTRY(do_nmi_callback)
++	CFI_STARTPROC
++        addq $8, %rsp
++	CFI_ENDPROC
++	CFI_DEFAULT_STACK
++        call do_nmi
++        orl  $NMI_MASK,EFLAGS(%rsp)
++        RESTORE_REST
++        XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++        GET_THREAD_INFO(%rcx)
++        jmp  retint_restore_args
++	CFI_ENDPROC
++	.previous .text
++END(nmi)
++#endif
++
++        ALIGN
++restore_all_enable_events:  
++	CFI_DEFAULT_STACK adj=1
++	TRACE_IRQS_ON
++	XEN_UNBLOCK_EVENTS(%rsi)        # %rsi is already set up...
++
++scrit:	/**** START OF CRITICAL REGION ****/
++	XEN_TEST_PENDING(%rsi)
++	CFI_REMEMBER_STATE
++	jnz  14f			# process more events if necessary...
++	XEN_PUT_VCPU_INFO(%rsi)
++        RESTORE_ARGS 0,8,0
++        HYPERVISOR_IRET 0
++        
++	CFI_RESTORE_STATE
++14:	XEN_LOCKED_BLOCK_EVENTS(%rsi)
++	XEN_PUT_VCPU_INFO(%rsi)
++	SAVE_REST
++        movq %rsp,%rdi                  # set the argument again
++	jmp  11b
++	CFI_ENDPROC
++ecrit:  /**** END OF CRITICAL REGION ****/
++# At this point, unlike on x86-32, we don't do the fixup to simplify the 
++# code and the stack frame is more complex on x86-64.
++# When the kernel is interrupted in the critical section, the kernel 
++# will do IRET in that case, and everything will be restored at that point, 
++# i.e. it just resumes from the next instruction interrupted with the same context. 
++
++# Hypervisor uses this for application faults while it executes.
++# We get here for two reasons:
++#  1. Fault while reloading DS, ES, FS or GS
++#  2. Fault while executing IRET
++# Category 1 we do not need to fix up as Xen has already reloaded all segment
++# registers that could be reloaded and zeroed the others.
++# Category 2 we fix up by killing the current process. We cannot use the
++# normal Linux return path in this case because if we use the IRET hypercall
++# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
++# We distinguish between categories by comparing each saved segment register
++# with its current contents: any discrepancy means we in category 1.
++ENTRY(failsafe_callback)
++	_frame (RIP-0x30)
++	CFI_REL_OFFSET rcx, 0
++	CFI_REL_OFFSET r11, 8
++	movw %ds,%cx
++	cmpw %cx,0x10(%rsp)
++	CFI_REMEMBER_STATE
++	jne 1f
++	movw %es,%cx
++	cmpw %cx,0x18(%rsp)
++	jne 1f
++	movw %fs,%cx
++	cmpw %cx,0x20(%rsp)
++	jne 1f
++	movw %gs,%cx
++	cmpw %cx,0x28(%rsp)
++	jne 1f
++	/* All segments match their saved values => Category 2 (Bad IRET). */
++	movq (%rsp),%rcx
++	CFI_RESTORE rcx
++	movq 8(%rsp),%r11
++	CFI_RESTORE r11
++	addq $0x30,%rsp
++	CFI_ADJUST_CFA_OFFSET -0x30
++	movq $11,%rdi	/* SIGSEGV */
++	jmp do_exit			
++	CFI_RESTORE_STATE
++1:	/* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
++	movq (%rsp),%rcx
++	CFI_RESTORE rcx
++	movq 8(%rsp),%r11
++	CFI_RESTORE r11
++	addq $0x30,%rsp
++	CFI_ADJUST_CFA_OFFSET -0x30
++	pushq $0
++	CFI_ADJUST_CFA_OFFSET 8
++	SAVE_ALL
++	jmp error_exit
++	CFI_ENDPROC
++#if 0	      
++        .section __ex_table,"a"
++        .align 8
++        .quad gs_change,bad_gs
++        .previous
++        .section .fixup,"ax"
++	/* running with kernelgs */
++bad_gs: 
++/*	swapgs		*/	/* switch back to user gs */
++	xorl %eax,%eax
++        movl %eax,%gs
++        jmp  2b
++        .previous       
++#endif
++	
++/*
++ * Create a kernel thread.
++ *
++ * C extern interface:
++ *	extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
++ *
++ * asm input arguments:
++ *	rdi: fn, rsi: arg, rdx: flags
++ */
++ENTRY(kernel_thread)
++	CFI_STARTPROC
++	FAKE_STACK_FRAME $child_rip
++	SAVE_ALL
++
++	# rdi: flags, rsi: usp, rdx: will be &pt_regs
++	movq %rdx,%rdi
++	orq  kernel_thread_flags(%rip),%rdi
++	movq $-1, %rsi
++	movq %rsp, %rdx
++
++	xorl %r8d,%r8d
++	xorl %r9d,%r9d
++	
++	# clone now
++	call do_fork
++	movq %rax,RAX(%rsp)
++	xorl %edi,%edi
++
++	/*
++	 * It isn't worth to check for reschedule here,
++	 * so internally to the x86_64 port you can rely on kernel_thread()
++	 * not to reschedule the child before returning, this avoids the need
++	 * of hacks for example to fork off the per-CPU idle tasks.
++         * [Hopefully no generic code relies on the reschedule -AK]	
++	 */
++	RESTORE_ALL
++	UNFAKE_STACK_FRAME
++	ret
++	CFI_ENDPROC
++ENDPROC(kernel_thread)
++	
++child_rip:
++	pushq $0		# fake return address
++	CFI_STARTPROC
++	/*
++	 * Here we are in the child and the registers are set as they were
++	 * at kernel_thread() invocation in the parent.
++	 */
++	movq %rdi, %rax
++	movq %rsi, %rdi
++	call *%rax
++	# exit
++	xorl %edi, %edi
++	call do_exit
++	CFI_ENDPROC
++ENDPROC(child_rip)
++
++/*
++ * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
++ *
++ * C extern interface:
++ *	 extern long execve(char *name, char **argv, char **envp)
++ *
++ * asm input arguments:
++ *	rdi: name, rsi: argv, rdx: envp
++ *
++ * We want to fallback into:
++ *	extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
++ *
++ * do_sys_execve asm fallback arguments:
++ *	rdi: name, rsi: argv, rdx: envp, fake frame on the stack
++ */
++ENTRY(execve)
++	CFI_STARTPROC
++	FAKE_STACK_FRAME $0
++	SAVE_ALL	
++	call sys_execve
++	movq %rax, RAX(%rsp)	
++	RESTORE_REST
++	testq %rax,%rax
++	jne 1f
++        jmp int_ret_from_sys_call
++1:      RESTORE_ARGS
++	UNFAKE_STACK_FRAME
++	ret
++	CFI_ENDPROC
++ENDPROC(execve)
++
++KPROBE_ENTRY(page_fault)
++	errorentry do_page_fault
++END(page_fault)
++	.previous .text
++
++ENTRY(coprocessor_error)
++	zeroentry do_coprocessor_error
++END(coprocessor_error)
++
++ENTRY(simd_coprocessor_error)
++	zeroentry do_simd_coprocessor_error	
++END(simd_coprocessor_error)
++
++ENTRY(device_not_available)
++	zeroentry math_state_restore
++END(device_not_available)
++
++	/* runs on exception stack */
++KPROBE_ENTRY(debug)
++/* 	INTR_FRAME
++	pushq $0
++	CFI_ADJUST_CFA_OFFSET 8	*/
++	zeroentry do_debug
++/*	paranoidexit
++	CFI_ENDPROC */
++END(debug)
++	.previous .text
++
++#if 0
++	/* runs on exception stack */	
++KPROBE_ENTRY(nmi)
++	INTR_FRAME
++	pushq $-1
++	CFI_ADJUST_CFA_OFFSET 8
++	paranoidentry do_nmi, 0, 0
++#ifdef CONFIG_TRACE_IRQFLAGS
++	paranoidexit 0
++#else
++	jmp paranoid_exit1
++ 	CFI_ENDPROC
++#endif
++END(nmi)
++	.previous .text
++#endif        
++
++KPROBE_ENTRY(int3)
++/* 	INTR_FRAME
++ 	pushq $0
++ 	CFI_ADJUST_CFA_OFFSET 8 */
++ 	zeroentry do_int3
++/* 	jmp paranoid_exit1
++ 	CFI_ENDPROC */
++END(int3)
++	.previous .text
++
++ENTRY(overflow)
++	zeroentry do_overflow
++END(overflow)
++
++ENTRY(bounds)
++	zeroentry do_bounds
++END(bounds)
++
++ENTRY(invalid_op)
++	zeroentry do_invalid_op	
++END(invalid_op)
++
++ENTRY(coprocessor_segment_overrun)
++	zeroentry do_coprocessor_segment_overrun
++END(coprocessor_segment_overrun)
++
++ENTRY(reserved)
++	zeroentry do_reserved
++END(reserved)
++
++#if 0
++	/* runs on exception stack */
++ENTRY(double_fault)
++	XCPT_FRAME
++	paranoidentry do_double_fault
++	jmp paranoid_exit1
++	CFI_ENDPROC
++END(double_fault)
++#endif
++
++ENTRY(invalid_TSS)
++	errorentry do_invalid_TSS
++END(invalid_TSS)
++
++ENTRY(segment_not_present)
++	errorentry do_segment_not_present
++END(segment_not_present)
++
++	/* runs on exception stack */
++ENTRY(stack_segment)
++/*	XCPT_FRAME
++	paranoidentry do_stack_segment */
++	errorentry do_stack_segment
++/*	jmp paranoid_exit1
++	CFI_ENDPROC */
++END(stack_segment)
++
++KPROBE_ENTRY(general_protection)
++	errorentry do_general_protection
++END(general_protection)
++	.previous .text
++
++ENTRY(alignment_check)
++	errorentry do_alignment_check
++END(alignment_check)
++
++ENTRY(divide_error)
++	zeroentry do_divide_error
++END(divide_error)
++
++ENTRY(spurious_interrupt_bug)
++	zeroentry do_spurious_interrupt_bug
++END(spurious_interrupt_bug)
++
++#ifdef CONFIG_X86_MCE
++	/* runs on exception stack */
++KPROBE_ENTRY(machine_check)
++	zeroentry do_machine_check
++END(machine_check)
++#endif
++
++/* Call softirq on interrupt stack. Interrupts are off. */
++ENTRY(call_softirq)
++	CFI_STARTPROC
++	push %rbp
++	CFI_ADJUST_CFA_OFFSET	8
++	CFI_REL_OFFSET rbp,0
++	mov  %rsp,%rbp
++	CFI_DEF_CFA_REGISTER rbp
++	incl %gs:pda_irqcount
++	cmove %gs:pda_irqstackptr,%rsp
++	push  %rbp			# backlink for old unwinder
++	call __do_softirq
++	leaveq
++	CFI_DEF_CFA_REGISTER	rsp
++	CFI_ADJUST_CFA_OFFSET   -8
++	decl %gs:pda_irqcount
++	ret
++	CFI_ENDPROC
++ENDPROC(call_softirq)
++
++#ifdef CONFIG_STACK_UNWIND
++ENTRY(arch_unwind_init_running)
++	CFI_STARTPROC
++	movq	%r15, R15(%rdi)
++	movq	%r14, R14(%rdi)
++	xchgq	%rsi, %rdx
++	movq	%r13, R13(%rdi)
++	movq	%r12, R12(%rdi)
++	xorl	%eax, %eax
++	movq	%rbp, RBP(%rdi)
++	movq	%rbx, RBX(%rdi)
++	movq	(%rsp), %rcx
++	movq	%rax, R11(%rdi)
++	movq	%rax, R10(%rdi)
++	movq	%rax, R9(%rdi)
++	movq	%rax, R8(%rdi)
++	movq	%rax, RAX(%rdi)
++	movq	%rax, RCX(%rdi)
++	movq	%rax, RDX(%rdi)
++	movq	%rax, RSI(%rdi)
++	movq	%rax, RDI(%rdi)
++	movq	%rax, ORIG_RAX(%rdi)
++	movq	%rcx, RIP(%rdi)
++	leaq	8(%rsp), %rcx
++	movq	$__KERNEL_CS, CS(%rdi)
++	movq	%rax, EFLAGS(%rdi)
++	movq	%rcx, RSP(%rdi)
++	movq	$__KERNEL_DS, SS(%rdi)
++	jmpq	*%rdx
++	CFI_ENDPROC
++ENDPROC(arch_unwind_init_running)
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,211 @@
++/*
++ *  linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
++ *
++ *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
++ *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
++ *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
++ *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
++ *
++ *  $Id: head.S,v 1.49 2002/03/19 17:39:25 ak Exp $
++ *
++ *  Jun Nakajima <jun.nakajima@intel.com>
++ *    Modified for Xen                                
++ */
++
++
++#include <linux/linkage.h>
++#include <linux/threads.h>
++#include <linux/init.h>
++#include <linux/elfnote.h>
++#include <asm/desc.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/msr.h>
++#include <asm/cache.h>
++#include <asm/dwarf2.h>
++#include <xen/interface/elfnote.h>
++
++	.section .bootstrap.text, "ax", @progbits
++	.code64
++	.globl startup_64
++startup_64:
++	movq $(init_thread_union+THREAD_SIZE-8),%rsp
++
++	/* rsi is pointer to startup info structure.
++	   pass it to C */
++	movq %rsi,%rdi
++	pushq $0		# fake return address
++	jmp x86_64_start_kernel
++
++#ifdef CONFIG_ACPI_SLEEP
++.org 0xf00
++	.globl pGDT32
++pGDT32:
++	.word	gdt_end-cpu_gdt_table-1
++	.long	cpu_gdt_table-__START_KERNEL_map
++#endif
++ENTRY(stext)
++ENTRY(_stext)
++
++	$page = 0
++#define NEXT_PAGE(name) \
++	$page = $page + 1; \
++	.org $page * 0x1000; \
++	phys_##name = $page * 0x1000 + __PHYSICAL_START; \
++ENTRY(name)
++
++NEXT_PAGE(init_level4_pgt)
++	/* This gets initialized in x86_64_start_kernel */
++	.fill	512,8,0
++NEXT_PAGE(init_level4_user_pgt)
++        /*
++         * We update two pgd entries to make kernel and user pgd consistent
++         * at pgd_populate(). It can be used for kernel modules. So we place 
++         * this page here for those cases to avoid memory corruption.
++         * We also use this page to establish the initial mapping for the
++         * vsyscall area.
++         */
++	.fill	512,8,0
++
++NEXT_PAGE(level3_kernel_pgt)
++	.fill	512,8,0
++
++        /*
++         * This is used for vsyscall area mapping as we have a different
++         * level4 page table for user.
++         */
++NEXT_PAGE(level3_user_pgt)
++        .fill	512,8,0
++
++NEXT_PAGE(hypercall_page)
++	CFI_STARTPROC
++	.rept 0x1000 / 0x20
++	.skip 1 /* push %rcx */
++	CFI_ADJUST_CFA_OFFSET	8
++	CFI_REL_OFFSET	rcx,0
++	.skip 2 /* push %r11 */
++	CFI_ADJUST_CFA_OFFSET	8
++	CFI_REL_OFFSET	rcx,0
++	.skip 5 /* mov $#,%eax */
++	.skip 2 /* syscall */
++	.skip 2 /* pop %r11 */
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE r11
++	.skip 1 /* pop %rcx */
++	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE rcx
++	.align 0x20,0 /* ret */
++	.endr
++	CFI_ENDPROC
++
++#undef NEXT_PAGE
++
++	.data
++/* Just dummy symbol to allow compilation. Not used in sleep path */
++#ifdef CONFIG_ACPI_SLEEP
++	.align PAGE_SIZE
++ENTRY(wakeup_level4_pgt)
++	.fill	512,8,0
++#endif
++
++	.data
++
++	.align 16
++	.globl cpu_gdt_descr
++cpu_gdt_descr:
++	.word	gdt_end-cpu_gdt_table-1
++gdt:
++	.quad	cpu_gdt_table
++#ifdef CONFIG_SMP
++	.rept	NR_CPUS-1
++	.word	0
++	.quad	0
++	.endr
++#endif
++
++/* We need valid kernel segments for data and code in long mode too
++ * IRET will check the segment types  kkeil 2000/10/28
++ * Also sysret mandates a special GDT layout 
++ */
++		 		
++	.section .data.page_aligned, "aw"
++	.align PAGE_SIZE
++
++/* The TLS descriptors are currently at a different place compared to i386.
++   Hopefully nobody expects them at a fixed place (Wine?) */
++
++ENTRY(cpu_gdt_table)
++	.quad	0x0000000000000000	/* NULL descriptor */
++	.quad	0x0			/* unused */
++	.quad	0x00af9a000000ffff	/* __KERNEL_CS */
++	.quad	0x00cf92000000ffff	/* __KERNEL_DS */
++	.quad	0x00cffa000000ffff	/* __USER32_CS */
++	.quad	0x00cff2000000ffff	/* __USER_DS, __USER32_DS  */
++	.quad	0x00affa000000ffff	/* __USER_CS */
++	.quad	0x00cf9a000000ffff	/* __KERNEL32_CS */
++	.quad	0,0			/* TSS */
++	.quad	0,0			/* LDT */
++	.quad   0,0,0			/* three TLS descriptors */
++	.quad	0			/* unused */
++gdt_end:
++	/* asm/segment.h:GDT_ENTRIES must match this */
++	/* This should be a multiple of the cache line size */
++	/* GDTs of other CPUs are now dynamically allocated */
++
++	/* zero the remaining page */
++	.fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
++
++	.section .bss.page_aligned, "aw", @nobits
++	.align PAGE_SIZE
++ENTRY(empty_zero_page)
++	.skip PAGE_SIZE
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++/*
++ * __xen_guest information
++ */
++.macro utoh value
++ .if (\value) < 0 || (\value) >= 0x10
++	utoh (((\value)>>4)&0x0fffffffffffffff)
++ .endif
++ .if ((\value) & 0xf) < 10
++  .byte '0' + ((\value) & 0xf)
++ .else
++  .byte 'A' + ((\value) & 0xf) - 10
++ .endif
++.endm
++
++.section __xen_guest
++	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
++	.ascii	",XEN_VER=xen-3.0"
++	.ascii	",VIRT_BASE=0x"
++		utoh __START_KERNEL_map
++	.ascii	",ELF_PADDR_OFFSET=0x"
++		utoh __START_KERNEL_map
++	.ascii	",VIRT_ENTRY=0x"
++		utoh (__START_KERNEL_map + __PHYSICAL_START)
++	.ascii	",HYPERCALL_PAGE=0x"
++		utoh (phys_hypercall_page >> PAGE_SHIFT)
++	.ascii  ",FEATURES=writable_page_tables"
++	.ascii		 "|writable_descriptor_tables"
++	.ascii		 "|auto_translated_physmap"
++	.ascii	         "|supervisor_mode_kernel"
++	.ascii	",LOADER=generic"
++	.byte	0
++#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
++	
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
++	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
++	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad,  __START_KERNEL_map)
++#if CONFIG_XEN_COMPAT <= 0x030002
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  __START_KERNEL_map)
++#else
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  0)
++#endif
++	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad,  startup_64)
++	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad,  hypercall_page)
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  _PAGE_PRESENT,_PAGE_PRESENT)
++	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)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2007-06-12 13:13:01.000000000 +0200
+@@ -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();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,2270 @@
++/*
++ *	Intel IO-APIC support for multi-Pentium hosts.
++ *
++ *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
++ *
++ *	Many thanks to Stig Venaas for trying out countless experimental
++ *	patches and reporting/debugging problems patiently!
++ *
++ *	(c) 1999, Multiple IO-APIC support, developed by
++ *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
++ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
++ *	further tested and cleaned up by Zach Brown <zab@redhat.com>
++ *	and Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
++ *					thanks to Eric Gilmore
++ *					and Rolf G. Tews
++ *					for testing these extensively
++ *	Paul Diefenbaugh	:	Added full ACPI support
++ */
++
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/mc146818rtc.h>
++#include <linux/acpi.h>
++#include <linux/sysdev.h>
++#ifdef CONFIG_ACPI
++#include <acpi/acpi_bus.h>
++#endif
++
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/desc.h>
++#include <asm/proto.h>
++#include <asm/mach_apic.h>
++#include <asm/acpi.h>
++#include <asm/dma.h>
++#include <asm/nmi.h>
++
++#define __apicdebuginit  __init
++
++int sis_apic_bug; /* not actually supported, dummy for compile */
++
++static int no_timer_check;
++
++int disable_timer_pin_1 __initdata;
++
++#ifndef CONFIG_XEN
++int timer_over_8254 __initdata = 0;
++
++/* Where if anywhere is the i8259 connect in external int mode */
++static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
++#endif
++
++static DEFINE_SPINLOCK(ioapic_lock);
++static DEFINE_SPINLOCK(vector_lock);
++
++/*
++ * # of IRQ routing registers
++ */
++int nr_ioapic_registers[MAX_IO_APICS];
++
++/*
++ * Rough estimation of how many shared IRQs there are, can
++ * be changed anytime.
++ */
++#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
++#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
++
++/*
++ * This is performance-critical, we want to do it O(1)
++ *
++ * the indexing order of this array favors 1:1 mappings
++ * between pins and IRQs.
++ */
++
++static struct irq_pin_list {
++	short apic, pin, next;
++} irq_2_pin[PIN_MAP_SIZE];
++
++int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
++#ifdef CONFIG_PCI_MSI
++#define vector_to_irq(vector) 	\
++	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
++#else
++#define vector_to_irq(vector)	(vector)
++#endif
++
++#ifdef CONFIG_XEN
++
++#include <xen/interface/xen.h>
++#include <xen/interface/physdev.h>
++#include <xen/evtchn.h>
++
++/* Fake i8259 */
++#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
++#define disable_8259A_irq(_irq)  ((void)0)
++#define i8259A_irq_pending(_irq) (0)
++
++unsigned long io_apic_irqs;
++
++static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
++{
++	struct physdev_apic apic_op;
++	int ret;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
++	if (ret)
++		return ret;
++	return apic_op.value;
++}
++
++static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
++{
++	struct physdev_apic apic_op;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	apic_op.value = value;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
++}
++
++#define io_apic_read(a,r)    xen_io_apic_read(a,r)
++#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
++
++#define clear_IO_APIC() ((void)0)
++
++#else
++
++#ifdef CONFIG_SMP
++static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
++{
++	unsigned long flags;
++	unsigned int dest;
++	cpumask_t tmp;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	cpus_and(mask, tmp, CPU_MASK_ALL);
++
++	dest = cpu_mask_to_apicid(mask);
++
++	/*
++	 * Only the high 8 bits are valid.
++	 */
++	dest = SET_APIC_LOGICAL_ID(dest);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__DO_ACTION(1, = dest, )
++	set_irq_info(irq, mask);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++#endif
++
++#endif /* !CONFIG_XEN */
++
++/*
++ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
++ * shared ISA-space IRQs, so we have to support them. We are super
++ * fast in the common case, and fast for shared ISA-space IRQs.
++ */
++static void add_pin_to_irq(unsigned int irq, int apic, int pin)
++{
++	static int first_free_entry = NR_IRQS;
++	struct irq_pin_list *entry = irq_2_pin + irq;
++
++	BUG_ON(irq >= NR_IRQS);
++	while (entry->next)
++		entry = irq_2_pin + entry->next;
++
++	if (entry->pin != -1) {
++		entry->next = first_free_entry;
++		entry = irq_2_pin + entry->next;
++		if (++first_free_entry >= PIN_MAP_SIZE)
++			panic("io_apic.c: ran out of irq_2_pin entries!");
++	}
++	entry->apic = apic;
++	entry->pin = pin;
++}
++
++#ifndef CONFIG_XEN
++#define __DO_ACTION(R, ACTION, FINAL)					\
++									\
++{									\
++	int pin;							\
++	struct irq_pin_list *entry = irq_2_pin + irq;			\
++									\
++	BUG_ON(irq >= NR_IRQS);						\
++	for (;;) {							\
++		unsigned int reg;					\
++		pin = entry->pin;					\
++		if (pin == -1)						\
++			break;						\
++		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
++		reg ACTION;						\
++		io_apic_modify(entry->apic, reg);			\
++		if (!entry->next)					\
++			break;						\
++		entry = irq_2_pin + entry->next;			\
++	}								\
++	FINAL;								\
++}
++
++#define DO_ACTION(name,R,ACTION, FINAL)					\
++									\
++	static void name##_IO_APIC_irq (unsigned int irq)		\
++	__DO_ACTION(R, ACTION, FINAL)
++
++DO_ACTION( __mask,             0, |= 0x00010000, io_apic_sync(entry->apic) )
++						/* mask = 1 */
++DO_ACTION( __unmask,           0, &= 0xfffeffff, )
++						/* mask = 0 */
++
++static void mask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__mask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void unmask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++
++	/* Check delivery_mode to be sure we're not clearing an SMI pin */
++	spin_lock_irqsave(&ioapic_lock, flags);
++	*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++	*(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	if (entry.delivery_mode == dest_SMI)
++		return;
++	/*
++	 * Disable it in the IO-APIC irq-routing table:
++	 */
++	memset(&entry, 0, sizeof(entry));
++	entry.mask = 1;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void clear_IO_APIC (void)
++{
++	int apic, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++)
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
++			clear_IO_APIC_pin(apic, pin);
++}
++
++#endif /* !CONFIG_XEN */
++
++static u8 gsi_2_irq[NR_IRQ_VECTORS] = { [0 ... NR_IRQ_VECTORS-1] = 0xFF };
++
++/*
++ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
++ * specific CPU-side IRQs.
++ */
++
++#define MAX_PIRQS 8
++static int pirq_entries [MAX_PIRQS];
++static int pirqs_enabled;
++int skip_ioapic_setup;
++int ioapic_force;
++
++/* dummy parsing: see setup.c */
++
++static int __init disable_ioapic_setup(char *str)
++{
++	skip_ioapic_setup = 1;
++	return 1;
++}
++
++static int __init enable_ioapic_setup(char *str)
++{
++	ioapic_force = 1;
++	skip_ioapic_setup = 0;
++	return 1;
++}
++
++__setup("noapic", disable_ioapic_setup);
++__setup("apic", enable_ioapic_setup);
++
++#ifndef CONFIG_XEN
++static int __init setup_disable_8254_timer(char *s)
++{
++	timer_over_8254 = -1;
++	return 1;
++}
++static int __init setup_enable_8254_timer(char *s)
++{
++	timer_over_8254 = 2;
++	return 1;
++}
++
++__setup("disable_8254_timer", setup_disable_8254_timer);
++__setup("enable_8254_timer", setup_enable_8254_timer);
++#endif /* !CONFIG_XEN */
++
++#include <asm/pci-direct.h>
++#include <linux/pci_ids.h>
++#include <linux/pci.h>
++
++
++#ifdef CONFIG_ACPI
++
++static int nvidia_hpet_detected __initdata;
++
++static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
++{
++	nvidia_hpet_detected = 1;
++	return 0;
++}
++#endif
++
++/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
++   off. Check for an Nvidia or VIA PCI bridge and turn it off.
++   Use pci direct infrastructure because this runs before the PCI subsystem. 
++
++   Can be overwritten with "apic"
++
++   And another hack to disable the IOMMU on VIA chipsets.
++
++   ... and others. Really should move this somewhere else.
++
++   Kludge-O-Rama. */
++void __init check_ioapic(void) 
++{ 
++	int num,slot,func; 
++	/* Poor man's PCI discovery */
++	for (num = 0; num < 32; num++) { 
++		for (slot = 0; slot < 32; slot++) { 
++			for (func = 0; func < 8; func++) { 
++				u32 class;
++				u32 vendor;
++				u8 type;
++				class = read_pci_config(num,slot,func,
++							PCI_CLASS_REVISION);
++				if (class == 0xffffffff)
++					break; 
++
++		       		if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
++					continue; 
++
++				vendor = read_pci_config(num, slot, func, 
++							 PCI_VENDOR_ID);
++				vendor &= 0xffff;
++				switch (vendor) { 
++				case PCI_VENDOR_ID_VIA:
++#ifdef CONFIG_IOMMU
++					if ((end_pfn > MAX_DMA32_PFN ||
++					     force_iommu) &&
++					    !iommu_aperture_allowed) {
++						printk(KERN_INFO
++    "Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
++						iommu_aperture_disabled = 1;
++					}
++#endif
++					return;
++				case PCI_VENDOR_ID_NVIDIA:
++#ifdef CONFIG_ACPI
++					/*
++					 * All timer overrides on Nvidia are
++					 * wrong unless HPET is enabled.
++					 */
++					nvidia_hpet_detected = 0;
++					acpi_table_parse(ACPI_HPET,
++							nvidia_hpet_check);
++					if (nvidia_hpet_detected == 0) {
++						acpi_skip_timer_override = 1;
++						printk(KERN_INFO "Nvidia board "
++						    "detected. Ignoring ACPI "
++						    "timer override.\n");
++					}
++#endif
++					/* RED-PEN skip them on mptables too? */
++					return;
++				case PCI_VENDOR_ID_ATI:
++
++				/* This should be actually default, but
++				   for 2.6.16 let's do it for ATI only where
++				   it's really needed. */
++#ifndef CONFIG_XEN
++					if (timer_over_8254 == 1) {	
++						timer_over_8254 = 0;	
++					printk(KERN_INFO
++		"ATI board detected. Disabling timer routing over 8254.\n");
++					}	
++#endif
++					return;
++				} 
++
++
++				/* No multi-function device? */
++				type = read_pci_config_byte(num,slot,func,
++							    PCI_HEADER_TYPE);
++				if (!(type & 0x80))
++					break;
++			} 
++		}
++	}
++} 
++
++static int __init ioapic_pirq_setup(char *str)
++{
++	int i, max;
++	int ints[MAX_PIRQS+1];
++
++	get_options(str, ARRAY_SIZE(ints), ints);
++
++	for (i = 0; i < MAX_PIRQS; i++)
++		pirq_entries[i] = -1;
++
++	pirqs_enabled = 1;
++	apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
++	max = MAX_PIRQS;
++	if (ints[0] < MAX_PIRQS)
++		max = ints[0];
++
++	for (i = 0; i < max; i++) {
++		apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
++		/*
++		 * PIRQs are mapped upside down, usually.
++		 */
++		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
++	}
++	return 1;
++}
++
++__setup("pirq=", ioapic_pirq_setup);
++
++/*
++ * Find the IRQ entry number of a certain pin.
++ */
++static int find_irq_entry(int apic, int pin, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mpc_irqtype == type &&
++		    (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid ||
++		     mp_irqs[i].mpc_dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].mpc_dstirq == pin)
++			return i;
++
++	return -1;
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Find the pin to which IRQ[irq] (ISA) is connected
++ */
++static int __init find_isa_irq_pin(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
++		    (mp_irqs[i].mpc_irqtype == type) &&
++		    (mp_irqs[i].mpc_srcbusirq == irq))
++
++			return mp_irqs[i].mpc_dstirq;
++	}
++	return -1;
++}
++
++static int __init find_isa_irq_apic(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
++		    (mp_irqs[i].mpc_irqtype == type) &&
++		    (mp_irqs[i].mpc_srcbusirq == irq))
++			break;
++	}
++	if (i < mp_irq_entries) {
++		int apic;
++		for(apic = 0; apic < nr_ioapics; apic++) {
++			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
++				return apic;
++		}
++	}
++
++	return -1;
++}
++#endif
++
++/*
++ * Find a specific PCI IRQ entry.
++ * Not an __init, possibly needed by modules
++ */
++static int pin_2_irq(int idx, int apic, int pin);
++
++int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
++{
++	int apic, i, best_guess = -1;
++
++	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
++		bus, slot, pin);
++	if (mp_bus_id_to_pci_bus[bus] == -1) {
++		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
++		return -1;
++	}
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mpc_srcbus;
++
++		for (apic = 0; apic < nr_ioapics; apic++)
++			if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic ||
++			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
++				break;
++
++		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++		    !mp_irqs[i].mpc_irqtype &&
++		    (bus == lbus) &&
++		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
++
++			if (!(apic || IO_APIC_IRQ(irq)))
++				continue;
++
++			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
++				return irq;
++			/*
++			 * Use the first all-but-pin matching entry as a
++			 * best-guess fuzzy result for broken mptables.
++			 */
++			if (best_guess < 0)
++				best_guess = irq;
++		}
++	}
++	BUG_ON(best_guess >= NR_IRQS);
++	return best_guess;
++}
++
++/*
++ * EISA Edge/Level control register, ELCR
++ */
++static int EISA_ELCR(unsigned int irq)
++{
++	if (irq < 16) {
++		unsigned int port = 0x4d0 + (irq >> 3);
++		return (inb(port) >> (irq & 7)) & 1;
++	}
++	apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
++	return 0;
++}
++
++/* EISA interrupts are always polarity zero and can be edge or level
++ * trigger depending on the ELCR value.  If an interrupt is listed as
++ * EISA conforming in the MP table, that means its trigger type must
++ * be read in from the ELCR */
++
++#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
++#define default_EISA_polarity(idx)	(0)
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx)	(0)
++#define default_ISA_polarity(idx)	(0)
++
++/* PCI interrupts are always polarity one level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_PCI_trigger(idx)	(1)
++#define default_PCI_polarity(idx)	(1)
++
++/* MCA interrupts are always polarity zero level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_MCA_trigger(idx)	(1)
++#define default_MCA_polarity(idx)	(0)
++
++static int __init MPBIOS_polarity(int idx)
++{
++	int bus = mp_irqs[idx].mpc_srcbus;
++	int polarity;
++
++	/*
++	 * Determine IRQ line polarity (high active or low active):
++	 */
++	switch (mp_irqs[idx].mpc_irqflag & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent polarity */
++		{
++			switch (mp_bus_id_to_type[bus])
++			{
++				case MP_BUS_ISA: /* ISA pin */
++				{
++					polarity = default_ISA_polarity(idx);
++					break;
++				}
++				case MP_BUS_EISA: /* EISA pin */
++				{
++					polarity = default_EISA_polarity(idx);
++					break;
++				}
++				case MP_BUS_PCI: /* PCI pin */
++				{
++					polarity = default_PCI_polarity(idx);
++					break;
++				}
++				case MP_BUS_MCA: /* MCA pin */
++				{
++					polarity = default_MCA_polarity(idx);
++					break;
++				}
++				default:
++				{
++					printk(KERN_WARNING "broken BIOS!!\n");
++					polarity = 1;
++					break;
++				}
++			}
++			break;
++		}
++		case 1: /* high active */
++		{
++			polarity = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++		case 3: /* low active */
++		{
++			polarity = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++	}
++	return polarity;
++}
++
++static int MPBIOS_trigger(int idx)
++{
++	int bus = mp_irqs[idx].mpc_srcbus;
++	int trigger;
++
++	/*
++	 * Determine IRQ trigger mode (edge or level sensitive):
++	 */
++	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent */
++		{
++			switch (mp_bus_id_to_type[bus])
++			{
++				case MP_BUS_ISA: /* ISA pin */
++				{
++					trigger = default_ISA_trigger(idx);
++					break;
++				}
++				case MP_BUS_EISA: /* EISA pin */
++				{
++					trigger = default_EISA_trigger(idx);
++					break;
++				}
++				case MP_BUS_PCI: /* PCI pin */
++				{
++					trigger = default_PCI_trigger(idx);
++					break;
++				}
++				case MP_BUS_MCA: /* MCA pin */
++				{
++					trigger = default_MCA_trigger(idx);
++					break;
++				}
++				default:
++				{
++					printk(KERN_WARNING "broken BIOS!!\n");
++					trigger = 1;
++					break;
++				}
++			}
++			break;
++		}
++		case 1: /* edge */
++		{
++			trigger = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 1;
++			break;
++		}
++		case 3: /* level */
++		{
++			trigger = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 0;
++			break;
++		}
++	}
++	return trigger;
++}
++
++static inline int irq_polarity(int idx)
++{
++	return MPBIOS_polarity(idx);
++}
++
++static inline int irq_trigger(int idx)
++{
++	return MPBIOS_trigger(idx);
++}
++
++static int next_irq = 16;
++
++/*
++ * gsi_irq_sharing -- Name overload!  "irq" can be either a legacy IRQ
++ * in the range 0-15, a linux IRQ in the range 0-223, or a GSI number
++ * from ACPI, which can reach 800 in large boxen.
++ *
++ * Compact the sparse GSI space into a sequential IRQ series and reuse
++ * vectors if possible.
++ */
++int gsi_irq_sharing(int gsi)
++{
++	int i, tries, vector;
++
++	BUG_ON(gsi >= NR_IRQ_VECTORS);
++
++	if (platform_legacy_irq(gsi))
++		return gsi;
++
++	if (gsi_2_irq[gsi] != 0xFF)
++		return (int)gsi_2_irq[gsi];
++
++	tries = NR_IRQS;
++  try_again:
++	vector = assign_irq_vector(gsi);
++
++	/*
++	 * Sharing vectors means sharing IRQs, so scan irq_vectors for previous
++	 * use of vector and if found, return that IRQ.  However, we never want
++	 * to share legacy IRQs, which usually have a different trigger mode
++	 * than PCI.
++	 */
++	for (i = 0; i < NR_IRQS; i++)
++		if (IO_APIC_VECTOR(i) == vector)
++			break;
++	if (platform_legacy_irq(i)) {
++		if (--tries >= 0) {
++			IO_APIC_VECTOR(i) = 0;
++			goto try_again;
++		}
++		panic("gsi_irq_sharing: didn't find an IRQ using vector 0x%02X for GSI %d", vector, gsi);
++	}
++	if (i < NR_IRQS) {
++		gsi_2_irq[gsi] = i;
++		printk(KERN_INFO "GSI %d sharing vector 0x%02X and IRQ %d\n",
++				gsi, vector, i);
++		return i;
++	}
++
++	i = next_irq++;
++	BUG_ON(i >= NR_IRQS);
++	gsi_2_irq[gsi] = i;
++	IO_APIC_VECTOR(i) = vector;
++	printk(KERN_INFO "GSI %d assigned vector 0x%02X and IRQ %d\n",
++			gsi, vector, i);
++	return i;
++}
++
++static int pin_2_irq(int idx, int apic, int pin)
++{
++	int irq, i;
++	int bus = mp_irqs[idx].mpc_srcbus;
++
++	/*
++	 * Debugging check, we are in big trouble if this message pops up!
++	 */
++	if (mp_irqs[idx].mpc_dstirq != pin)
++		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
++
++	switch (mp_bus_id_to_type[bus])
++	{
++		case MP_BUS_ISA: /* ISA pin */
++		case MP_BUS_EISA:
++		case MP_BUS_MCA:
++		{
++			irq = mp_irqs[idx].mpc_srcbusirq;
++			break;
++		}
++		case MP_BUS_PCI: /* PCI pin */
++		{
++			/*
++			 * PCI IRQs are mapped in order
++			 */
++			i = irq = 0;
++			while (i < apic)
++				irq += nr_ioapic_registers[i++];
++			irq += pin;
++			irq = gsi_irq_sharing(irq);
++			break;
++		}
++		default:
++		{
++			printk(KERN_ERR "unknown bus type %d.\n",bus); 
++			irq = 0;
++			break;
++		}
++	}
++	BUG_ON(irq >= NR_IRQS);
++
++	/*
++	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
++	 */
++	if ((pin >= 16) && (pin <= 23)) {
++		if (pirq_entries[pin-16] != -1) {
++			if (!pirq_entries[pin-16]) {
++				apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
++			} else {
++				irq = pirq_entries[pin-16];
++				apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
++						pin-16, irq);
++			}
++		}
++	}
++	BUG_ON(irq >= NR_IRQS);
++	return irq;
++}
++
++static inline int IO_APIC_irq_trigger(int irq)
++{
++	int apic, idx, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			idx = find_irq_entry(apic,pin,mp_INT);
++			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
++				return irq_trigger(idx);
++		}
++	}
++	/*
++	 * nonexistent IRQs are edge default
++	 */
++	return 0;
++}
++
++/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
++u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
++
++int assign_irq_vector(int irq)
++{
++	unsigned long flags;
++	int vector;
++	struct physdev_irq irq_op;
++  
++  	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
++
++	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
++		return -EINVAL;
++
++	spin_lock_irqsave(&vector_lock, flags);
++
++  	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
++		spin_unlock_irqrestore(&vector_lock, flags);
++  		return IO_APIC_VECTOR(irq);
++	}
++
++	irq_op.irq = irq;
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
++		spin_unlock_irqrestore(&vector_lock, flags);
++		return -ENOSPC;
++	}
++
++	vector = irq_op.vector;
++	vector_irq[vector] = irq;
++	if (irq != AUTO_ASSIGN)
++		IO_APIC_VECTOR(irq) = vector;
++
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	return vector;
++}
++
++extern void (*interrupt[NR_IRQS])(void);
++#ifndef CONFIG_XEN
++static struct hw_interrupt_type ioapic_level_type;
++static struct hw_interrupt_type ioapic_edge_type;
++
++#define IOAPIC_AUTO	-1
++#define IOAPIC_EDGE	0
++#define IOAPIC_LEVEL	1
++
++static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
++{
++	unsigned idx;
++
++	idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
++
++	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++			trigger == IOAPIC_LEVEL)
++		irq_desc[idx].chip = &ioapic_level_type;
++	else
++		irq_desc[idx].chip = &ioapic_edge_type;
++	set_intr_gate(vector, interrupt[idx]);
++}
++#else
++#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
++#endif /* !CONFIG_XEN */
++
++static void __init setup_IO_APIC_irqs(void)
++{
++	struct IO_APIC_route_entry entry;
++	int apic, pin, idx, irq, first_notcon = 1, vector;
++	unsigned long flags;
++
++	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++
++		/*
++		 * add it to the IO-APIC irq-routing table:
++		 */
++		memset(&entry,0,sizeof(entry));
++
++		entry.delivery_mode = INT_DELIVERY_MODE;
++		entry.dest_mode = INT_DEST_MODE;
++		entry.mask = 0;				/* enable IRQ */
++		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++
++		idx = find_irq_entry(apic,pin,mp_INT);
++		if (idx == -1) {
++			if (first_notcon) {
++				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
++				first_notcon = 0;
++			} else
++				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
++			continue;
++		}
++
++		entry.trigger = irq_trigger(idx);
++		entry.polarity = irq_polarity(idx);
++
++		if (irq_trigger(idx)) {
++			entry.trigger = 1;
++			entry.mask = 1;
++			entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++		}
++
++		irq = pin_2_irq(idx, apic, pin);
++		add_pin_to_irq(irq, apic, pin);
++
++		if (/* !apic && */ !IO_APIC_IRQ(irq))
++			continue;
++
++		if (IO_APIC_IRQ(irq)) {
++			vector = assign_irq_vector(irq);
++			entry.vector = vector;
++
++			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
++			if (!apic && (irq < 16))
++				disable_8259A_irq(irq);
++		}
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
++		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
++		set_native_irq_info(irq, TARGET_CPUS);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++	}
++	}
++
++	if (!first_notcon)
++		apic_printk(APIC_VERBOSE," not connected.\n");
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Set up the 8259A-master output pin as broadcast to all
++ * CPUs.
++ */
++static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++
++	memset(&entry,0,sizeof(entry));
++
++	disable_8259A_irq(0);
++
++	/* mask LVT0 */
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++
++	/*
++	 * We use logical delivery to get the timer IRQ
++	 * to the first CPU.
++	 */
++	entry.dest_mode = INT_DEST_MODE;
++	entry.mask = 0;					/* unmask IRQ now */
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.polarity = 0;
++	entry.trigger = 0;
++	entry.vector = vector;
++
++	/*
++	 * The timer IRQ doesn't have to know that behind the
++	 * scene we have a 8259A-master in AEOI mode ...
++	 */
++	irq_desc[0].chip = &ioapic_edge_type;
++
++	/*
++	 * Add it to the IO-APIC irq-routing table:
++	 */
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
++	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	enable_8259A_irq(0);
++}
++
++void __init UNEXPECTED_IO_APIC(void)
++{
++}
++
++void __apicdebuginit print_IO_APIC(void)
++{
++	int apic, i;
++	union IO_APIC_reg_00 reg_00;
++	union IO_APIC_reg_01 reg_01;
++	union IO_APIC_reg_02 reg_02;
++	unsigned long flags;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
++	for (i = 0; i < nr_ioapics; i++)
++		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
++		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
++
++	/*
++	 * We are a bit conservative about what we expect.  We have to
++	 * know about every hardware change ASAP.
++	 */
++	printk(KERN_INFO "testing the IO APIC.......................\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(apic, 0);
++	reg_01.raw = io_apic_read(apic, 1);
++	if (reg_01.bits.version >= 0x10)
++		reg_02.raw = io_apic_read(apic, 2);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	printk("\n");
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
++	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
++	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
++	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
++		UNEXPECTED_IO_APIC();
++
++	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
++	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
++	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
++		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
++		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
++		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
++		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
++		(reg_01.bits.entries != 0x2E) &&
++		(reg_01.bits.entries != 0x3F) &&
++		(reg_01.bits.entries != 0x03) 
++	)
++		UNEXPECTED_IO_APIC();
++
++	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
++	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
++	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
++		(reg_01.bits.version != 0x02) && /* 82801BA IO-APICs (ICH2) */
++		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */
++		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
++		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
++		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */
++	)
++		UNEXPECTED_IO_APIC();
++	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
++		UNEXPECTED_IO_APIC();
++
++	if (reg_01.bits.version >= 0x10) {
++		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
++		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
++		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
++			UNEXPECTED_IO_APIC();
++	}
++
++	printk(KERN_DEBUG ".... IRQ redirection table:\n");
++
++	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
++			  " Stat Dest Deli Vect:   \n");
++
++	for (i = 0; i <= reg_01.bits.entries; i++) {
++		struct IO_APIC_route_entry entry;
++
++		spin_lock_irqsave(&ioapic_lock, flags);
++		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
++		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		printk(KERN_DEBUG " %02x %03X %02X  ",
++			i,
++			entry.dest.logical.logical_dest,
++			entry.dest.physical.physical_dest
++		);
++
++		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
++			entry.mask,
++			entry.trigger,
++			entry.irr,
++			entry.polarity,
++			entry.delivery_status,
++			entry.dest_mode,
++			entry.delivery_mode,
++			entry.vector
++		);
++	}
++	}
++	if (use_pci_vector())
++		printk(KERN_INFO "Using vector-based indexing\n");
++	printk(KERN_DEBUG "IRQ to pin mappings:\n");
++	for (i = 0; i < NR_IRQS; i++) {
++		struct irq_pin_list *entry = irq_2_pin + i;
++		if (entry->pin < 0)
++			continue;
++ 		if (use_pci_vector() && !platform_legacy_irq(i))
++			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
++		else
++			printk(KERN_DEBUG "IRQ%d ", i);
++		for (;;) {
++			printk("-> %d:%d", entry->apic, entry->pin);
++			if (!entry->next)
++				break;
++			entry = irq_2_pin + entry->next;
++		}
++		printk("\n");
++	}
++
++	printk(KERN_INFO ".................................... done.\n");
++
++	return;
++}
++
++static __apicdebuginit void print_APIC_bitfield (int base)
++{
++	unsigned int v;
++	int i, j;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
++	for (i = 0; i < 8; i++) {
++		v = apic_read(base + i*0x10);
++		for (j = 0; j < 32; j++) {
++			if (v & (1<<j))
++				printk("1");
++			else
++				printk("0");
++		}
++		printk("\n");
++	}
++}
++
++void __apicdebuginit print_local_APIC(void * dummy)
++{
++	unsigned int v, ver, maxlvt;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
++		smp_processor_id(), hard_smp_processor_id());
++	v = apic_read(APIC_ID);
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));
++	v = apic_read(APIC_LVR);
++	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
++	ver = GET_APIC_VERSION(v);
++	maxlvt = get_maxlvt();
++
++	v = apic_read(APIC_TASKPRI);
++	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
++
++	v = apic_read(APIC_ARBPRI);
++	printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
++		v & APIC_ARBPRI_MASK);
++	v = apic_read(APIC_PROCPRI);
++	printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
++
++	v = apic_read(APIC_EOI);
++	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
++	v = apic_read(APIC_RRR);
++	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
++	v = apic_read(APIC_LDR);
++	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
++	v = apic_read(APIC_DFR);
++	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
++	v = apic_read(APIC_SPIV);
++	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
++
++	printk(KERN_DEBUG "... APIC ISR field:\n");
++	print_APIC_bitfield(APIC_ISR);
++	printk(KERN_DEBUG "... APIC TMR field:\n");
++	print_APIC_bitfield(APIC_TMR);
++	printk(KERN_DEBUG "... APIC IRR field:\n");
++	print_APIC_bitfield(APIC_IRR);
++
++	v = apic_read(APIC_ESR);
++	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
++
++	v = apic_read(APIC_ICR);
++	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
++	v = apic_read(APIC_ICR2);
++	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
++
++	v = apic_read(APIC_LVTT);
++	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
++
++	if (maxlvt > 3) {                       /* PC is LVT#4. */
++		v = apic_read(APIC_LVTPC);
++		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
++	}
++	v = apic_read(APIC_LVT0);
++	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
++	v = apic_read(APIC_LVT1);
++	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
++
++	if (maxlvt > 2) {			/* ERR is LVT#3. */
++		v = apic_read(APIC_LVTERR);
++		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
++	}
++
++	v = apic_read(APIC_TMICT);
++	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
++	v = apic_read(APIC_TMCCT);
++	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
++	v = apic_read(APIC_TDCR);
++	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
++	printk("\n");
++}
++
++void print_all_local_APICs (void)
++{
++	on_each_cpu(print_local_APIC, NULL, 1, 1);
++}
++
++void __apicdebuginit print_PIC(void)
++{
++	unsigned int v;
++	unsigned long flags;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "\nprinting PIC contents\n");
++
++	spin_lock_irqsave(&i8259A_lock, flags);
++
++	v = inb(0xa1) << 8 | inb(0x21);
++	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
++
++	v = inb(0xa0) << 8 | inb(0x20);
++	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
++
++	outb(0x0b,0xa0);
++	outb(0x0b,0x20);
++	v = inb(0xa0) << 8 | inb(0x20);
++	outb(0x0a,0xa0);
++	outb(0x0a,0x20);
++
++	spin_unlock_irqrestore(&i8259A_lock, flags);
++
++	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
++
++	v = inb(0x4d1) << 8 | inb(0x4d0);
++	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
++}
++#endif /* !CONFIG_XEN */
++
++static void __init enable_IO_APIC(void)
++{
++	union IO_APIC_reg_01 reg_01;
++#ifndef CONFIG_XEN
++	int i8259_apic, i8259_pin;
++#endif
++	int i, apic;
++	unsigned long flags;
++
++	for (i = 0; i < PIN_MAP_SIZE; i++) {
++		irq_2_pin[i].pin = -1;
++		irq_2_pin[i].next = 0;
++	}
++	if (!pirqs_enabled)
++		for (i = 0; i < MAX_PIRQS; i++)
++			pirq_entries[i] = -1;
++
++	/*
++	 * The number of IO-APIC IRQ registers (== #pins):
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_01.raw = io_apic_read(apic, 1);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
++	}
++#ifndef CONFIG_XEN
++	for(apic = 0; apic < nr_ioapics; apic++) {
++		int pin;
++		/* See if any of the pins is in ExtINT mode */
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			struct IO_APIC_route_entry entry;
++			spin_lock_irqsave(&ioapic_lock, flags);
++			*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++			*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++			spin_unlock_irqrestore(&ioapic_lock, flags);
++
++
++			/* If the interrupt line is enabled and in ExtInt mode
++			 * I have found the pin where the i8259 is connected.
++			 */
++			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
++				ioapic_i8259.apic = apic;
++				ioapic_i8259.pin  = pin;
++				goto found_i8259;
++			}
++		}
++	}
++ found_i8259:
++	/* Look to see what if the MP table has reported the ExtINT */
++	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
++	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
++	/* Trust the MP table if nothing is setup in the hardware */
++	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
++		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
++		ioapic_i8259.pin  = i8259_pin;
++		ioapic_i8259.apic = i8259_apic;
++	}
++	/* Complain if the MP table and the hardware disagree */
++	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
++		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
++	{
++		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
++	}
++#endif
++
++	/*
++	 * Do not trust the IO-APIC being empty at bootup
++	 */
++	clear_IO_APIC();
++}
++
++/*
++ * Not an __init, needed by the reboot code
++ */
++void disable_IO_APIC(void)
++{
++	/*
++	 * Clear the IO-APIC before rebooting:
++	 */
++	clear_IO_APIC();
++
++#ifndef CONFIG_XEN
++	/*
++	 * If the i8259 is routed through an IOAPIC
++	 * Put that IOAPIC in virtual wire mode
++	 * so legacy interrupts can be delivered.
++	 */
++	if (ioapic_i8259.pin != -1) {
++		struct IO_APIC_route_entry entry;
++		unsigned long flags;
++
++		memset(&entry, 0, sizeof(entry));
++		entry.mask            = 0; /* Enabled */
++		entry.trigger         = 0; /* Edge */
++		entry.irr             = 0;
++		entry.polarity        = 0; /* High */
++		entry.delivery_status = 0;
++		entry.dest_mode       = 0; /* Physical */
++		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
++		entry.vector          = 0;
++		entry.dest.physical.physical_dest =
++					GET_APIC_ID(apic_read(APIC_ID));
++
++		/*
++		 * Add it to the IO-APIC irq-routing table:
++		 */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
++			*(((int *)&entry)+1));
++		io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
++			*(((int *)&entry)+0));
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++	}
++
++	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
++#endif
++}
++
++/*
++ * function to set the IO-APIC physical IDs based on the
++ * values stored in the MPC table.
++ *
++ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
++ */
++
++#ifndef CONFIG_XEN
++static void __init setup_ioapic_ids_from_mpc (void)
++{
++	union IO_APIC_reg_00 reg_00;
++	int apic;
++	int i;
++	unsigned char old_id;
++	unsigned long flags;
++
++	/*
++	 * Set the IOAPIC ID to the value stored in the MPC table.
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++		/* Read the register 0 value */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		
++		old_id = mp_ioapics[apic].mpc_apicid;
++
++
++		printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
++
++
++		/*
++		 * We need to adjust the IRQ routing table
++		 * if the ID changed.
++		 */
++		if (old_id != mp_ioapics[apic].mpc_apicid)
++			for (i = 0; i < mp_irq_entries; i++)
++				if (mp_irqs[i].mpc_dstapic == old_id)
++					mp_irqs[i].mpc_dstapic
++						= mp_ioapics[apic].mpc_apicid;
++
++		/*
++		 * Read the right value from the MPC table and
++		 * write it into the ID register.
++	 	 */
++		apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
++				mp_ioapics[apic].mpc_apicid);
++
++		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(apic, 0, reg_00.raw);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		/*
++		 * Sanity check
++		 */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
++			printk("could not set ID!\n");
++		else
++			apic_printk(APIC_VERBOSE," ok.\n");
++	}
++}
++#else
++static void __init setup_ioapic_ids_from_mpc(void) { }
++#endif
++
++/*
++ * There is a nasty bug in some older SMP boards, their mptable lies
++ * about the timer IRQ. We do the following to work around the situation:
++ *
++ *	- timer IRQ defaults to IO-APIC IRQ
++ *	- if this function detects that timer IRQs are defunct, then we fall
++ *	  back to ISA timer IRQs
++ */
++#ifndef CONFIG_XEN
++static int __init timer_irq_works(void)
++{
++	unsigned long t1 = jiffies;
++
++	local_irq_enable();
++	/* Let ten ticks pass... */
++	mdelay((10 * 1000) / HZ);
++
++	/*
++	 * Expect a few ticks at least, to be sure some possible
++	 * glue logic does not lock up after one or two first
++	 * ticks in a non-ExtINT mode.  Also the local APIC
++	 * might have cached one ExtINT interrupt.  Finally, at
++	 * least one tick may be lost due to delays.
++	 */
++
++	/* jiffies wrap? */
++	if (jiffies - t1 > 4)
++		return 1;
++	return 0;
++}
++
++/*
++ * In the SMP+IOAPIC case it might happen that there are an unspecified
++ * number of pending IRQ events unhandled. These cases are very rare,
++ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
++ * better to do it this way as thus we do not have to be aware of
++ * 'pending' interrupts in the IRQ path, except at this point.
++ */
++/*
++ * Edge triggered needs to resend any interrupt
++ * that was delayed but this is now handled in the device
++ * independent code.
++ */
++
++/*
++ * Starting up a edge-triggered IO-APIC interrupt is
++ * nasty - we need to make sure that we get the edge.
++ * If it is already asserted for some reason, we need
++ * return 1 to indicate that is was pending.
++ *
++ * This is not complete - we should be able to fake
++ * an edge even if it isn't on the 8259A...
++ */
++
++static unsigned int startup_edge_ioapic_irq(unsigned int irq)
++{
++	int was_pending = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	if (irq < 16) {
++		disable_8259A_irq(irq);
++		if (i8259A_irq_pending(irq))
++			was_pending = 1;
++	}
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return was_pending;
++}
++
++/*
++ * Once we have recorded IRQ_PENDING already, we can mask the
++ * interrupt for real. This prevents IRQ storms from unhandled
++ * devices.
++ */
++static void ack_edge_ioapic_irq(unsigned int irq)
++{
++	move_irq(irq);
++	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
++					== (IRQ_PENDING | IRQ_DISABLED))
++		mask_IO_APIC_irq(irq);
++	ack_APIC_irq();
++}
++
++/*
++ * Level triggered interrupts can just be masked,
++ * and shutting down and starting up the interrupt
++ * is the same as enabling and disabling them -- except
++ * with a startup need to return a "was pending" value.
++ *
++ * Level triggered interrupts are special because we
++ * do not touch any IO-APIC register while handling
++ * them. We ack the APIC in the end-IRQ handler, not
++ * in the start-IRQ-handler. Protection against reentrance
++ * from the same interrupt is still provided, both by the
++ * generic IRQ layer and by the fact that an unacked local
++ * APIC does not accept IRQs.
++ */
++static unsigned int startup_level_ioapic_irq (unsigned int irq)
++{
++	unmask_IO_APIC_irq(irq);
++
++	return 0; /* don't check for pending */
++}
++
++static void end_level_ioapic_irq (unsigned int irq)
++{
++	move_irq(irq);
++	ack_APIC_irq();
++}
++
++#ifdef CONFIG_PCI_MSI
++static unsigned int startup_edge_ioapic_vector(unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	return startup_edge_ioapic_irq(irq);
++}
++
++static void ack_edge_ioapic_vector(unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	move_native_irq(vector);
++	ack_edge_ioapic_irq(irq);
++}
++
++static unsigned int startup_level_ioapic_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	return startup_level_ioapic_irq (irq);
++}
++
++static void end_level_ioapic_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	move_native_irq(vector);
++	end_level_ioapic_irq(irq);
++}
++
++static void mask_IO_APIC_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	mask_IO_APIC_irq(irq);
++}
++
++static void unmask_IO_APIC_vector (unsigned int vector)
++{
++	int irq = vector_to_irq(vector);
++
++	unmask_IO_APIC_irq(irq);
++}
++
++#ifdef CONFIG_SMP
++static void set_ioapic_affinity_vector (unsigned int vector,
++					cpumask_t cpu_mask)
++{
++	int irq = vector_to_irq(vector);
++
++	set_native_irq_info(vector, cpu_mask);
++	set_ioapic_affinity_irq(irq, cpu_mask);
++}
++#endif // CONFIG_SMP
++#endif // CONFIG_PCI_MSI
++
++static int ioapic_retrigger(unsigned int irq)
++{
++	send_IPI_self(IO_APIC_VECTOR(irq));
++
++	return 1;
++}
++
++/*
++ * Level and edge triggered IO-APIC interrupts need different handling,
++ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
++ * handled with the level-triggered descriptor, but that one has slightly
++ * more overhead. Level-triggered interrupts cannot be handled with the
++ * edge-triggered handler, without risking IRQ storms and other ugly
++ * races.
++ */
++
++static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
++	.typename = "IO-APIC-edge",
++	.startup 	= startup_edge_ioapic,
++	.shutdown 	= shutdown_edge_ioapic,
++	.enable 	= enable_edge_ioapic,
++	.disable 	= disable_edge_ioapic,
++	.ack 		= ack_edge_ioapic,
++	.end 		= end_edge_ioapic,
++#ifdef CONFIG_SMP
++	.set_affinity = set_ioapic_affinity,
++#endif
++	.retrigger	= ioapic_retrigger,
++};
++
++static struct hw_interrupt_type ioapic_level_type __read_mostly = {
++	.typename = "IO-APIC-level",
++	.startup 	= startup_level_ioapic,
++	.shutdown 	= shutdown_level_ioapic,
++	.enable 	= enable_level_ioapic,
++	.disable 	= disable_level_ioapic,
++	.ack 		= mask_and_ack_level_ioapic,
++	.end 		= end_level_ioapic,
++#ifdef CONFIG_SMP
++	.set_affinity = set_ioapic_affinity,
++#endif
++	.retrigger	= ioapic_retrigger,
++};
++#endif /* !CONFIG_XEN */
++
++static inline void init_IO_APIC_traps(void)
++{
++	int irq;
++
++	/*
++	 * NOTE! The local APIC isn't very good at handling
++	 * multiple interrupts at the same interrupt level.
++	 * As the interrupt level is determined by taking the
++	 * vector number and shifting that right by 4, we
++	 * want to spread these out a bit so that they don't
++	 * all fall in the same interrupt level.
++	 *
++	 * Also, we've got to be careful not to trash gate
++	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
++	 */
++	for (irq = 0; irq < NR_IRQS ; irq++) {
++		int tmp = irq;
++		if (use_pci_vector()) {
++			if (!platform_legacy_irq(tmp))
++				if ((tmp = vector_to_irq(tmp)) == -1)
++					continue;
++		}
++		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
++			/*
++			 * Hmm.. We don't have an entry for this,
++			 * so default to an old-fashioned 8259
++			 * interrupt if we can..
++			 */
++			if (irq < 16)
++				make_8259A_irq(irq);
++#ifndef CONFIG_XEN
++			else
++				/* Strange. Oh, well.. */
++				irq_desc[irq].chip = &no_irq_type;
++#endif
++		}
++	}
++}
++
++#ifndef CONFIG_XEN
++static void enable_lapic_irq (unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
++}
++
++static void disable_lapic_irq (unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
++}
++
++static void ack_lapic_irq (unsigned int irq)
++{
++	ack_APIC_irq();
++}
++
++static void end_lapic_irq (unsigned int i) { /* nothing */ }
++
++static struct hw_interrupt_type lapic_irq_type __read_mostly = {
++	.typename = "local-APIC-edge",
++	.startup = NULL, /* startup_irq() not used for IRQ0 */
++	.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
++	.enable = enable_lapic_irq,
++	.disable = disable_lapic_irq,
++	.ack = ack_lapic_irq,
++	.end = end_lapic_irq,
++};
++
++static void setup_nmi (void)
++{
++	/*
++ 	 * Dirty trick to enable the NMI watchdog ...
++	 * We put the 8259A master into AEOI mode and
++	 * unmask on all local APICs LVT0 as NMI.
++	 *
++	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
++	 * is from Maciej W. Rozycki - so we do not have to EOI from
++	 * the NMI handler or the timer interrupt.
++	 */ 
++	printk(KERN_INFO "activating NMI Watchdog ...");
++
++	enable_NMI_through_LVT0(NULL);
++
++	printk(" done.\n");
++}
++
++/*
++ * This looks a bit hackish but it's about the only one way of sending
++ * a few INTA cycles to 8259As and any associated glue logic.  ICR does
++ * not support the ExtINT mode, unfortunately.  We need to send these
++ * cycles as some i82489DX-based boards have glue logic that keeps the
++ * 8259A interrupt line asserted until INTA.  --macro
++ */
++static inline void unlock_ExtINT_logic(void)
++{
++	int apic, pin, i;
++	struct IO_APIC_route_entry entry0, entry1;
++	unsigned char save_control, save_freq_select;
++	unsigned long flags;
++
++	pin  = find_isa_irq_pin(8, mp_INT);
++	apic = find_isa_irq_apic(8, mp_INT);
++	if (pin == -1)
++		return;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
++	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	clear_IO_APIC_pin(apic, pin);
++
++	memset(&entry1, 0, sizeof(entry1));
++
++	entry1.dest_mode = 0;			/* physical delivery */
++	entry1.mask = 0;			/* unmask IRQ now */
++	entry1.dest.physical.physical_dest = hard_smp_processor_id();
++	entry1.delivery_mode = dest_ExtINT;
++	entry1.polarity = entry0.polarity;
++	entry1.trigger = 0;
++	entry1.vector = 0;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	save_control = CMOS_READ(RTC_CONTROL);
++	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
++	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
++		   RTC_FREQ_SELECT);
++	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
++
++	i = 100;
++	while (i-- > 0) {
++		mdelay(10);
++		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
++			i -= 10;
++	}
++
++	CMOS_WRITE(save_control, RTC_CONTROL);
++	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
++	clear_IO_APIC_pin(apic, pin);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
++	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++int timer_uses_ioapic_pin_0;
++
++/*
++ * This code may look a bit paranoid, but it's supposed to cooperate with
++ * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
++ * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
++ * fanatically on his truly buggy board.
++ *
++ * FIXME: really need to revamp this for modern platforms only.
++ */
++static inline void check_timer(void)
++{
++	int apic1, pin1, apic2, pin2;
++	int vector;
++
++	/*
++	 * get/set the timer IRQ vector:
++	 */
++	disable_8259A_irq(0);
++	vector = assign_irq_vector(0);
++	set_intr_gate(vector, interrupt[0]);
++
++	/*
++	 * Subtle, code in do_timer_interrupt() expects an AEOI
++	 * mode for the 8259A whenever interrupts are routed
++	 * through I/O APICs.  Also IRQ0 has to be enabled in
++	 * the 8259A which implies the virtual wire has to be
++	 * disabled in the local APIC.
++	 */
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++	init_8259A(1);
++	if (timer_over_8254 > 0)
++		enable_8259A_irq(0);
++
++	pin1  = find_isa_irq_pin(0, mp_INT);
++	apic1 = find_isa_irq_apic(0, mp_INT);
++	pin2  = ioapic_i8259.pin;
++	apic2 = ioapic_i8259.apic;
++
++	if (pin1 == 0)
++		timer_uses_ioapic_pin_0 = 1;
++
++	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
++		vector, apic1, pin1, apic2, pin2);
++
++	if (pin1 != -1) {
++		/*
++		 * Ok, does IRQ0 through the IOAPIC work?
++		 */
++		unmask_IO_APIC_irq(0);
++		if (!no_timer_check && timer_irq_works()) {
++			nmi_watchdog_default();
++			if (nmi_watchdog == NMI_IO_APIC) {
++				disable_8259A_irq(0);
++				setup_nmi();
++				enable_8259A_irq(0);
++			}
++			if (disable_timer_pin_1 > 0)
++				clear_IO_APIC_pin(0, pin1);
++			return;
++		}
++		clear_IO_APIC_pin(apic1, pin1);
++		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
++				"connected to IO-APIC\n");
++	}
++
++	apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
++				"through the 8259A ... ");
++	if (pin2 != -1) {
++		apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
++			apic2, pin2);
++		/*
++		 * legacy devices should be connected to IO APIC #0
++		 */
++		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
++		if (timer_irq_works()) {
++			apic_printk(APIC_VERBOSE," works.\n");
++			nmi_watchdog_default();
++			if (nmi_watchdog == NMI_IO_APIC) {
++				setup_nmi();
++			}
++			return;
++		}
++		/*
++		 * Cleanup, just in case ...
++		 */
++		clear_IO_APIC_pin(apic2, pin2);
++	}
++	apic_printk(APIC_VERBOSE," failed.\n");
++
++	if (nmi_watchdog == NMI_IO_APIC) {
++		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
++		nmi_watchdog = 0;
++	}
++
++	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
++
++	disable_8259A_irq(0);
++	irq_desc[0].chip = &lapic_irq_type;
++	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
++	enable_8259A_irq(0);
++
++	if (timer_irq_works()) {
++		apic_printk(APIC_VERBOSE," works.\n");
++		return;
++	}
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
++	apic_printk(APIC_VERBOSE," failed.\n");
++
++	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
++
++	init_8259A(0);
++	make_8259A_irq(0);
++	apic_write(APIC_LVT0, APIC_DM_EXTINT);
++
++	unlock_ExtINT_logic();
++
++	if (timer_irq_works()) {
++		apic_printk(APIC_VERBOSE," works.\n");
++		return;
++	}
++	apic_printk(APIC_VERBOSE," failed :(.\n");
++	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
++}
++#else
++#define check_timer() ((void)0)
++int timer_uses_ioapic_pin_0 = 0;
++#endif /* !CONFIG_XEN */
++
++static int __init notimercheck(char *s)
++{
++	no_timer_check = 1;
++	return 1;
++}
++__setup("no_timer_check", notimercheck);
++
++/*
++ *
++ * IRQ's that are handled by the PIC in the MPS IOAPIC case.
++ * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
++ *   Linux doesn't really care, as it's not actually used
++ *   for any interrupt handling anyway.
++ */
++#define PIC_IRQS	(1<<2)
++
++void __init setup_IO_APIC(void)
++{
++	enable_IO_APIC();
++
++	if (acpi_ioapic)
++		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
++	else
++		io_apic_irqs = ~PIC_IRQS;
++
++	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
++
++	/*
++	 * Set up the IO-APIC IRQ routing table.
++	 */
++	if (!acpi_ioapic)
++		setup_ioapic_ids_from_mpc();
++#ifndef CONFIG_XEN
++	sync_Arb_IDs();
++#endif /* !CONFIG_XEN */
++	setup_IO_APIC_irqs();
++	init_IO_APIC_traps();
++	check_timer();
++	if (!acpi_ioapic)
++		print_IO_APIC();
++}
++
++#ifndef CONFIG_XEN
++
++struct sysfs_ioapic_data {
++	struct sys_device dev;
++	struct IO_APIC_route_entry entry[0];
++};
++static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
++
++static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	unsigned long flags;
++	int i;
++
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
++		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
++		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++static int ioapic_resume(struct sys_device *dev)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	unsigned long flags;
++	union IO_APIC_reg_00 reg_00;
++	int i;
++
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(dev->id, 0);
++	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
++		io_apic_write(dev->id, 0, reg_00.raw);
++	}
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
++		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
++		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++static struct sysdev_class ioapic_sysdev_class = {
++	set_kset_name("ioapic"),
++	.suspend = ioapic_suspend,
++	.resume = ioapic_resume,
++};
++
++static int __init ioapic_init_sysfs(void)
++{
++	struct sys_device * dev;
++	int i, size, error = 0;
++
++	error = sysdev_class_register(&ioapic_sysdev_class);
++	if (error)
++		return error;
++
++	for (i = 0; i < nr_ioapics; i++ ) {
++		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
++			* sizeof(struct IO_APIC_route_entry);
++		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
++		if (!mp_ioapic_data[i]) {
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++		memset(mp_ioapic_data[i], 0, size);
++		dev = &mp_ioapic_data[i]->dev;
++		dev->id = i;
++		dev->cls = &ioapic_sysdev_class;
++		error = sysdev_register(dev);
++		if (error) {
++			kfree(mp_ioapic_data[i]);
++			mp_ioapic_data[i] = NULL;
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++	}
++
++	return 0;
++}
++
++device_initcall(ioapic_init_sysfs);
++
++#endif /* CONFIG_XEN */
++
++/* --------------------------------------------------------------------------
++                          ACPI-based IOAPIC Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++#define IO_APIC_MAX_ID		0xFE
++
++int __init io_apic_get_version (int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.version;
++}
++
++
++int __init io_apic_get_redir_entries (int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.entries;
++}
++
++
++int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
++{
++	struct IO_APIC_route_entry entry;
++	unsigned long flags;
++
++	if (!IO_APIC_IRQ(irq)) {
++		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
++			ioapic);
++		return -EINVAL;
++	}
++
++	/*
++	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
++	 * Note that we mask (disable) IRQs now -- these get enabled when the
++	 * corresponding device driver registers for this IRQ.
++	 */
++
++	memset(&entry,0,sizeof(entry));
++
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.dest_mode = INT_DEST_MODE;
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.trigger = edge_level;
++	entry.polarity = active_high_low;
++	entry.mask = 1;					 /* Disabled (masked) */
++
++	irq = gsi_irq_sharing(irq);
++	/*
++	 * IRQs < 16 are already in the irq_2_pin[] map
++	 */
++	if (irq >= 16)
++		add_pin_to_irq(irq, ioapic, pin);
++
++	entry.vector = assign_irq_vector(irq);
++
++	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
++		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
++	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
++	       edge_level, active_high_low);
++
++	ioapic_register_intr(irq, entry.vector, edge_level);
++
++	if (!ioapic && (irq < 16))
++		disable_8259A_irq(irq);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
++	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
++	set_native_irq_info(use_pci_vector() ?  entry.vector : irq, TARGET_CPUS);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return 0;
++}
++
++#endif /* CONFIG_ACPI */
++
++
++#ifndef CONFIG_XEN
++/*
++ * This function currently is only a helper for the i386 smp boot process where
++ * we need to reprogram the ioredtbls to cater for the cpus which have come online
++ * so mask in all cases should simply be TARGET_CPUS
++ */
++#ifdef CONFIG_SMP
++void __init setup_ioapic_dest(void)
++{
++	int pin, ioapic, irq, irq_entry;
++
++	if (skip_ioapic_setup == 1)
++		return;
++
++	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
++		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
++			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
++			if (irq_entry == -1)
++				continue;
++			irq = pin_2_irq(irq_entry, ioapic, pin);
++			set_ioapic_affinity_irq(irq, TARGET_CPUS);
++		}
++
++	}
++}
++#endif
++#endif /* !CONFIG_XEN */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ioport_64-xen.c	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,100 @@
++/*
++ *	linux/arch/x86_64/kernel/ioport.c
++ *
++ * This contains the io-permission bitmap code - written by obz, with changes
++ * by Linus.
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/capability.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/stddef.h>
++#include <linux/slab.h>
++#include <linux/thread_info.h>
++#include <xen/interface/physdev.h>
++
++/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
++static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
++{
++	int i;
++
++	if (new_value)
++		for (i = base; i < base + extent; i++)
++			__set_bit(i, bitmap);
++	else
++		for (i = base; i < base + extent; i++)
++			clear_bit(i, bitmap);
++}
++
++/*
++ * this changes the io permissions bitmap in the current task.
++ */
++asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
++{
++	struct thread_struct * t = &current->thread;
++	unsigned long *bitmap;
++	struct physdev_set_iobitmap set_iobitmap;
++
++	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
++		return -EINVAL;
++	if (turn_on && !capable(CAP_SYS_RAWIO))
++		return -EPERM;
++
++	/*
++	 * If it's the first ioperm() call in this thread's lifetime, set the
++	 * IO bitmap up. ioperm() is much less timing critical than clone(),
++	 * this is why we delay this operation until now:
++	 */
++	if (!t->io_bitmap_ptr) {
++		bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++		if (!bitmap)
++			return -ENOMEM;
++
++		memset(bitmap, 0xff, IO_BITMAP_BYTES);
++		t->io_bitmap_ptr = bitmap;
++
++		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
++		set_iobitmap.nr_ports = IO_BITMAP_BITS;
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &set_iobitmap));
++	}
++
++	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
++
++	return 0;
++}
++
++/*
++ * sys_iopl has to be used when you want to access the IO ports
++ * beyond the 0x3ff range: to get the full 65536 ports bitmapped
++ * you'd need 8kB of bitmaps/process, which is a bit excessive.
++ *
++ */
++
++asmlinkage long sys_iopl(unsigned int new_iopl, struct pt_regs *regs)
++{
++	unsigned int old_iopl = current->thread.iopl;
++	struct physdev_set_iopl set_iopl;
++
++	if (new_iopl > 3)
++		return -EINVAL;
++
++	/* Need "raw I/O" privileges for direct port access. */
++	if ((new_iopl > old_iopl) && !capable(CAP_SYS_RAWIO))
++		return -EPERM;
++
++	/* Change our version of the privilege levels. */
++	current->thread.iopl = new_iopl;
++
++	/* Force the change at ring 0. */
++	set_iopl.iopl = (new_iopl == 0) ? 1 : new_iopl;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,197 @@
++/*
++ *	linux/arch/x86_64/kernel/irq.c
++ *
++ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
++ *
++ * This file contains the lowest level x86_64-specific interrupt
++ * entry and irq statistics code. All the remaining irq logic is
++ * done by the generic kernel/irq/ code and in the
++ * x86_64-specific irq controller code. (e.g. i8259.c and
++ * io_apic.c.)
++ */
++
++#include <linux/kernel_stat.h>
++#include <linux/interrupt.h>
++#include <linux/seq_file.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <asm/io_apic.h>
++#include <asm/idle.h>
++
++atomic_t irq_err_count;
++#ifdef CONFIG_X86_IO_APIC
++#ifdef APIC_MISMATCH_DEBUG
++atomic_t irq_mis_count;
++#endif
++#endif
++
++#ifdef CONFIG_DEBUG_STACKOVERFLOW
++/*
++ * Probabilistic stack overflow check:
++ *
++ * Only check the stack in process context, because everything else
++ * runs on the big interrupt stacks. Checking reliably is too expensive,
++ * so we just check from interrupts.
++ */
++static inline void stack_overflow_check(struct pt_regs *regs)
++{
++	u64 curbase = (u64) current->thread_info;
++	static unsigned long warned = -60*HZ;
++
++	if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
++	    regs->rsp <  curbase + sizeof(struct thread_info) + 128 &&
++	    time_after(jiffies, warned + 60*HZ)) {
++		printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n",
++		       current->comm, curbase, regs->rsp);
++		show_stack(NULL,NULL);
++		warned = jiffies;
++	}
++}
++#endif
++
++/*
++ * Generic, controller-independent functions:
++ */
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++	int i = *(loff_t *) v, j;
++	struct irqaction * action;
++	unsigned long flags;
++
++	if (i == 0) {
++		seq_printf(p, "           ");
++		for_each_online_cpu(j)
++			seq_printf(p, "CPU%-8d",j);
++		seq_putc(p, '\n');
++	}
++
++	if (i < NR_IRQS) {
++		spin_lock_irqsave(&irq_desc[i].lock, flags);
++		action = irq_desc[i].action;
++		if (!action) 
++			goto skip;
++		seq_printf(p, "%3d: ",i);
++#ifndef CONFIG_SMP
++		seq_printf(p, "%10u ", kstat_irqs(i));
++#else
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
++#endif
++		seq_printf(p, " %14s", irq_desc[i].chip->typename);
++
++		seq_printf(p, "  %s", action->name);
++		for (action=action->next; action; action = action->next)
++			seq_printf(p, ", %s", action->name);
++		seq_putc(p, '\n');
++skip:
++		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
++	} else if (i == NR_IRQS) {
++		seq_printf(p, "NMI: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
++		seq_putc(p, '\n');
++#ifdef CONFIG_X86_LOCAL_APIC
++		seq_printf(p, "LOC: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
++		seq_putc(p, '\n');
++#endif
++		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
++#ifdef CONFIG_X86_IO_APIC
++#ifdef APIC_MISMATCH_DEBUG
++		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
++#endif
++#endif
++	}
++	return 0;
++}
++
++/*
++ * do_IRQ handles all normal device IRQ's (the special
++ * SMP cross-CPU interrupts have their own specific
++ * handlers).
++ */
++asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
++{	
++	/* high bit used in ret_from_ code  */
++	unsigned irq = ~regs->orig_rax;
++
++	if (unlikely(irq >= NR_IRQS)) {
++		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
++					__FUNCTION__, irq);
++		BUG();
++	}
++
++	/*exit_idle();*/
++	/*irq_enter();*/
++#ifdef CONFIG_DEBUG_STACKOVERFLOW
++	stack_overflow_check(regs);
++#endif
++	__do_IRQ(irq, regs);
++	/*irq_exit();*/
++
++	return 1;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++void fixup_irqs(cpumask_t map)
++{
++	unsigned int irq;
++	static int warned;
++
++	for (irq = 0; irq < NR_IRQS; irq++) {
++		cpumask_t mask;
++		if (irq == 2)
++			continue;
++
++		cpus_and(mask, irq_desc[irq].affinity, map);
++		if (any_online_cpu(mask) == NR_CPUS) {
++			/*printk("Breaking affinity for irq %i\n", irq);*/
++			mask = map;
++		}
++		if (irq_desc[irq].chip->set_affinity)
++			irq_desc[irq].chip->set_affinity(irq, mask);
++		else if (irq_desc[irq].action && !(warned++))
++			printk("Cannot set affinity for irq %i\n", irq);
++	}
++
++	/* That doesn't seem sufficient.  Give it 1ms. */
++	local_irq_enable();
++	mdelay(1);
++	local_irq_disable();
++}
++#endif
++
++extern void call_softirq(void);
++
++asmlinkage void do_softirq(void)
++{
++ 	__u32 pending;
++ 	unsigned long flags;
++
++ 	if (in_interrupt())
++ 		return;
++
++ 	local_irq_save(flags);
++ 	pending = local_softirq_pending();
++ 	/* Switch to interrupt stack */
++ 	if (pending) {
++		call_softirq();
++		WARN_ON_ONCE(softirq_count());
++	}
++ 	local_irq_restore(flags);
++}
++EXPORT_SYMBOL(do_softirq);
++
++#ifndef CONFIG_X86_LOCAL_APIC
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++        printk("unexpected IRQ trap at vector %02x\n", irq);
++}
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ldt_64-xen.c	2007-06-12 13:13:01.000000000 +0200
+@@ -0,0 +1,282 @@
++/*
++ * linux/arch/x86_64/kernel/ldt.c
++ *
++ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
++ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ * Copyright (C) 2002 Andi Kleen
++ * 
++ * This handles calls from both 32bit and 64bit mode.
++ */
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/ldt.h>
++#include <asm/desc.h>
++#include <asm/proto.h>
++#include <asm/pgalloc.h>
++
++#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
++static void flush_ldt(void *null)
++{
++	if (current->active_mm)
++               load_LDT(&current->active_mm->context);
++}
++#endif
++
++static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload)
++{
++	void *oldldt;
++	void *newldt;
++	unsigned oldsize;
++
++	if (mincount <= (unsigned)pc->size)
++		return 0;
++	oldsize = pc->size;
++	mincount = (mincount+511)&(~511);
++	if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
++		newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
++	else
++		newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
++
++	if (!newldt)
++		return -ENOMEM;
++
++	if (oldsize)
++		memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
++	oldldt = pc->ldt;
++	memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
++	wmb();
++	pc->ldt = newldt;
++	wmb();
++	pc->size = mincount;
++	wmb();
++	if (reload) {
++#ifdef CONFIG_SMP
++		cpumask_t mask;
++
++		preempt_disable();
++#endif
++		make_pages_readonly(
++			pc->ldt,
++			(pc->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		load_LDT(pc);
++#ifdef CONFIG_SMP
++		mask = cpumask_of_cpu(smp_processor_id());
++		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
++			smp_call_function(flush_ldt, NULL, 1, 1);
++		preempt_enable();
++#endif
++	}
++	if (oldsize) {
++		make_pages_writable(
++			oldldt,
++			(oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(oldldt);
++		else
++			kfree(oldldt);
++	}
++	return 0;
++}
++
++static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
++{
++	int err = alloc_ldt(new, old->size, 0);
++	if (err < 0)
++		return err;
++	memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
++	make_pages_readonly(
++		new->ldt,
++		(new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++		XENFEAT_writable_descriptor_tables);
++	return 0;
++}
++
++/*
++ * we do not have to muck with descriptors here, that is
++ * done in switch_mm() as needed.
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++	struct mm_struct * old_mm;
++	int retval = 0;
++
++	memset(&mm->context, 0, sizeof(mm->context));
++	init_MUTEX(&mm->context.sem);
++	old_mm = current->mm;
++	if (old_mm && old_mm->context.size > 0) {
++		down(&old_mm->context.sem);
++		retval = copy_ldt(&mm->context, &old_mm->context);
++		up(&old_mm->context.sem);
++	}
++	if (retval == 0) {
++		spin_lock(&mm_unpinned_lock);
++		list_add(&mm->context.unpinned, &mm_unpinned);
++		spin_unlock(&mm_unpinned_lock);
++	}
++	return retval;
++}
++
++/*
++ * 
++ * Don't touch the LDT register - we're already in the next thread.
++ */
++void destroy_context(struct mm_struct *mm)
++{
++	if (mm->context.size) {
++		if (mm == current->active_mm)
++			clear_LDT();
++		make_pages_writable(
++			mm->context.ldt,
++			(mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			XENFEAT_writable_descriptor_tables);
++		if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(mm->context.ldt);
++		else
++			kfree(mm->context.ldt);
++		mm->context.size = 0;
++	}
++	if (!mm->context.pinned) {
++		spin_lock(&mm_unpinned_lock);
++		list_del(&mm->context.unpinned);
++		spin_unlock(&mm_unpinned_lock);
++	}
++}
++
++static int read_ldt(void __user * ptr, unsigned long bytecount)
++{
++	int err;
++	unsigned long size;
++	struct mm_struct * mm = current->mm;
++
++	if (!mm->context.size)
++		return 0;
++	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
++		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
++
++	down(&mm->context.sem);
++	size = mm->context.size*LDT_ENTRY_SIZE;
++	if (size > bytecount)
++		size = bytecount;
++
++	err = 0;
++	if (copy_to_user(ptr, mm->context.ldt, size))
++		err = -EFAULT;
++	up(&mm->context.sem);
++	if (err < 0)
++		goto error_return;
++	if (size != bytecount) {
++		/* zero-fill the rest */
++		if (clear_user(ptr+size, bytecount-size) != 0) {
++			err = -EFAULT;
++			goto error_return;
++		}
++	}
++	return bytecount;
++error_return:
++	return err;
++}
++
++static int read_default_ldt(void __user * ptr, unsigned long bytecount)
++{
++	/* Arbitrary number */ 
++	/* x86-64 default LDT is all zeros */
++	if (bytecount > 128) 
++		bytecount = 128; 	
++	if (clear_user(ptr, bytecount))
++		return -EFAULT;
++	return bytecount; 
++}
++
++static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
++{
++	struct task_struct *me = current;
++	struct mm_struct * mm = me->mm;
++	__u32 entry_1, entry_2, *lp;
++	unsigned long mach_lp;
++	int error;
++	struct user_desc ldt_info;
++
++	error = -EINVAL;
++
++	if (bytecount != sizeof(ldt_info))
++		goto out;
++	error = -EFAULT; 	
++	if (copy_from_user(&ldt_info, ptr, bytecount))
++		goto out;
++
++	error = -EINVAL;
++	if (ldt_info.entry_number >= LDT_ENTRIES)
++		goto out;
++	if (ldt_info.contents == 3) {
++		if (oldmode)
++			goto out;
++		if (ldt_info.seg_not_present == 0)
++			goto out;
++	}
++
++	down(&mm->context.sem);
++	if (ldt_info.entry_number >= (unsigned)mm->context.size) {
++		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
++		if (error < 0)
++			goto out_unlock;
++	}
++
++	lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
++ 	mach_lp = arbitrary_virt_to_machine(lp);
++
++   	/* Allow LDTs to be cleared by the user. */
++   	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
++		if (oldmode || LDT_empty(&ldt_info)) {
++			entry_1 = 0;
++			entry_2 = 0;
++			goto install;
++		}
++	}
++
++	entry_1 = LDT_entry_a(&ldt_info);
++	entry_2 = LDT_entry_b(&ldt_info);
++	if (oldmode)
++		entry_2 &= ~(1 << 20);
++
++	/* Install the new entry ...  */
++install:
++	error = HYPERVISOR_update_descriptor(mach_lp, (unsigned long)((entry_1 | (unsigned long) entry_2 << 32)));
++
++out_unlock:
++	up(&mm->context.sem);
++out:
++	return error;
++}
++
++asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
++{
++	int ret = -ENOSYS;
++
++	switch (func) {
++	case 0:
++		ret = read_ldt(ptr, bytecount);
++		break;
++	case 1:
++		ret = write_ldt(ptr, bytecount, 1);
++		break;
++	case 2:
++		ret = read_default_ldt(ptr, bytecount);
++		break;
++	case 0x11:
++		ret = write_ldt(ptr, bytecount, 0);
++		break;
++	}
++	return ret;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2007-06-12 13:13:01.000000000 +0200
+@@ -0,0 +1,1011 @@
++/*
++ *	Intel Multiprocessor Specification 1.1 and 1.4
++ *	compliant MP-table parsing routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *		Erich Boleyn	:	MP v1.4 and additional changes.
++ *		Alan Cox	:	Added EBDA scanning
++ *		Ingo Molnar	:	various cleanups and rewrites
++ *		Maciej W. Rozycki:	Bits for default MP configurations
++ *		Paul Diefenbaugh:	Added full ACPI support
++ */
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/pgalloc.h>
++#include <asm/io_apic.h>
++#include <asm/proto.h>
++#include <asm/acpi.h>
++
++/* Have we found an MP table */
++int smp_found_config;
++unsigned int __initdata maxcpus = NR_CPUS;
++
++int acpi_found_madt;
++
++/*
++ * Various Linux-internal data structures created from the
++ * MP-table.
++ */
++unsigned char apic_version [MAX_APICS];
++unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
++int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
++
++static int mp_current_pci_id = 0;
++/* I/O APIC entries */
++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
++
++/* # of MP IRQ source entries */
++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* MP IRQ source entries */
++int mp_irq_entries;
++
++int nr_ioapics;
++int pic_mode;
++unsigned long mp_lapic_addr = 0;
++
++
++
++/* Processor that is doing the boot up */
++unsigned int boot_cpu_id = -1U;
++/* Internal processor count */
++unsigned int num_processors __initdata = 0;
++
++unsigned disabled_cpus __initdata;
++
++/* Bitmask of physically existing CPUs */
++physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
++
++/* ACPI MADT entry parsing functions */
++#ifdef CONFIG_ACPI
++extern struct acpi_boot_flags acpi_boot;
++#ifdef CONFIG_X86_LOCAL_APIC
++extern int acpi_parse_lapic (acpi_table_entry_header *header);
++extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
++extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
++#endif /*CONFIG_X86_LOCAL_APIC*/
++#ifdef CONFIG_X86_IO_APIC
++extern int acpi_parse_ioapic (acpi_table_entry_header *header);
++#endif /*CONFIG_X86_IO_APIC*/
++#endif /*CONFIG_ACPI*/
++
++u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
++
++
++/*
++ * Intel MP BIOS table parsing routines:
++ */
++
++/*
++ * Checksum an MP configuration block.
++ */
++
++static int __init mpf_checksum(unsigned char *mp, int len)
++{
++	int sum = 0;
++
++	while (len--)
++		sum += *mp++;
++
++	return sum & 0xFF;
++}
++
++#ifndef CONFIG_XEN
++static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
++{
++	int cpu;
++	unsigned char ver;
++	cpumask_t tmp_map;
++
++	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
++		disabled_cpus++;
++		return;
++	}
++
++	printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
++		m->mpc_apicid,
++	       (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
++	       (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
++		m->mpc_apicver);
++
++	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++		Dprintk("    Bootup CPU\n");
++		boot_cpu_id = m->mpc_apicid;
++	}
++	if (num_processors >= NR_CPUS) {
++		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
++			" Processor ignored.\n", NR_CPUS);
++		return;
++	}
++
++	num_processors++;
++	cpus_complement(tmp_map, cpu_present_map);
++	cpu = first_cpu(tmp_map);
++
++#if MAX_APICS < 255	
++	if ((int)m->mpc_apicid > MAX_APICS) {
++		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
++			m->mpc_apicid, MAX_APICS);
++		return;
++	}
++#endif
++	ver = m->mpc_apicver;
++
++	physid_set(m->mpc_apicid, phys_cpu_present_map);
++	/*
++	 * Validate version
++	 */
++	if (ver == 0x0) {
++		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
++		ver = 0x10;
++	}
++	apic_version[m->mpc_apicid] = ver;
++ 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++ 		/*
++ 		 * bios_cpu_apicid is required to have processors listed
++ 		 * in same order as logical cpu numbers. Hence the first
++ 		 * entry is BSP, and so on.
++ 		 */
++		cpu = 0;
++ 	}
++	bios_cpu_apicid[cpu] = m->mpc_apicid;
++	x86_cpu_to_apicid[cpu] = m->mpc_apicid;
++
++	cpu_set(cpu, cpu_possible_map);
++	cpu_set(cpu, cpu_present_map);
++}
++#else
++static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
++{
++	num_processors++;
++}
++#endif /* CONFIG_XEN */
++
++static void __init MP_bus_info (struct mpc_config_bus *m)
++{
++	char str[7];
++
++	memcpy(str, m->mpc_bustype, 6);
++	str[6] = 0;
++	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
++
++	if (strncmp(str, "ISA", 3) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++	} else if (strncmp(str, "EISA", 4) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++	} else if (strncmp(str, "PCI", 3) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
++		mp_current_pci_id++;
++	} else if (strncmp(str, "MCA", 3) == 0) {
++		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++	} else {
++		printk(KERN_ERR "Unknown bustype %s\n", str);
++	}
++}
++
++static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
++{
++	if (!(m->mpc_flags & MPC_APIC_USABLE))
++		return;
++
++	printk("I/O APIC #%d Version %d at 0x%X.\n",
++		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
++			MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
++	}
++	if (!m->mpc_apicaddr) {
++		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
++			" found in MP table, skipping!\n");
++		return;
++	}
++	mp_ioapics[nr_ioapics] = *m;
++	nr_ioapics++;
++}
++
++static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
++{
++	mp_irqs [mp_irq_entries] = *m;
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
++			m->mpc_irqtype, m->mpc_irqflag & 3,
++			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
++			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++	if (++mp_irq_entries >= MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!!\n");
++}
++
++static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
++{
++	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
++		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
++			m->mpc_irqtype, m->mpc_irqflag & 3,
++			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
++			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++	/*
++	 * Well it seems all SMP boards in existence
++	 * use ExtINT/LVT1 == LINT0 and
++	 * NMI/LVT2 == LINT1 - the following check
++	 * will show us if this assumptions is false.
++	 * Until then we do not have to add baggage.
++	 */
++	if ((m->mpc_irqtype == mp_ExtINT) &&
++		(m->mpc_destapiclint != 0))
++			BUG();
++	if ((m->mpc_irqtype == mp_NMI) &&
++		(m->mpc_destapiclint != 1))
++			BUG();
++}
++
++/*
++ * Read/parse the MPC
++ */
++
++static int __init smp_read_mpc(struct mp_config_table *mpc)
++{
++	char str[16];
++	int count=sizeof(*mpc);
++	unsigned char *mpt=((unsigned char *)mpc)+count;
++
++	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
++		printk("SMP mptable: bad signature [%c%c%c%c]!\n",
++			mpc->mpc_signature[0],
++			mpc->mpc_signature[1],
++			mpc->mpc_signature[2],
++			mpc->mpc_signature[3]);
++		return 0;
++	}
++	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
++		printk("SMP mptable: checksum error!\n");
++		return 0;
++	}
++	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
++		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
++			mpc->mpc_spec);
++		return 0;
++	}
++	if (!mpc->mpc_lapic) {
++		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
++		return 0;
++	}
++	memcpy(str,mpc->mpc_oem,8);
++	str[8]=0;
++	printk(KERN_INFO "OEM ID: %s ",str);
++
++	memcpy(str,mpc->mpc_productid,12);
++	str[12]=0;
++	printk("Product ID: %s ",str);
++
++	printk("APIC at: 0x%X\n",mpc->mpc_lapic);
++
++	/* save the local APIC address, it might be non-default */
++	if (!acpi_lapic)
++	mp_lapic_addr = mpc->mpc_lapic;
++
++	/*
++	 *	Now process the configuration blocks.
++	 */
++	while (count < mpc->mpc_length) {
++		switch(*mpt) {
++			case MP_PROCESSOR:
++			{
++				struct mpc_config_processor *m=
++					(struct mpc_config_processor *)mpt;
++				if (!acpi_lapic)
++				MP_processor_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++			case MP_BUS:
++			{
++				struct mpc_config_bus *m=
++					(struct mpc_config_bus *)mpt;
++				MP_bus_info(m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
++				break;
++			}
++			case MP_IOAPIC:
++			{
++				struct mpc_config_ioapic *m=
++					(struct mpc_config_ioapic *)mpt;
++				MP_ioapic_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++			case MP_INTSRC:
++			{
++				struct mpc_config_intsrc *m=
++					(struct mpc_config_intsrc *)mpt;
++
++				MP_intsrc_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++			case MP_LINTSRC:
++			{
++				struct mpc_config_lintsrc *m=
++					(struct mpc_config_lintsrc *)mpt;
++				MP_lintsrc_info(m);
++				mpt+=sizeof(*m);
++				count+=sizeof(*m);
++				break;
++			}
++		}
++	}
++	clustered_apic_check();
++	if (!num_processors)
++		printk(KERN_ERR "SMP mptable: no processors registered!\n");
++	return num_processors;
++}
++
++static int __init ELCR_trigger(unsigned int irq)
++{
++	unsigned int port;
++
++	port = 0x4d0 + (irq >> 3);
++	return (inb(port) >> (irq & 7)) & 1;
++}
++
++static void __init construct_default_ioirq_mptable(int mpc_default_type)
++{
++	struct mpc_config_intsrc intsrc;
++	int i;
++	int ELCR_fallback = 0;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;			/* conforming */
++	intsrc.mpc_srcbus = 0;
++	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
++
++	intsrc.mpc_irqtype = mp_INT;
++
++	/*
++	 *  If true, we have an ISA/PCI system with no IRQ entries
++	 *  in the MP table. To prevent the PCI interrupts from being set up
++	 *  incorrectly, we try to use the ELCR. The sanity check to see if
++	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
++	 *  never be level sensitive, so we simply see if the ELCR agrees.
++	 *  If it does, we assume it's valid.
++	 */
++	if (mpc_default_type == 5) {
++		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
++
++		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
++			printk(KERN_ERR "ELCR contains invalid data... not using ELCR\n");
++		else {
++			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
++			ELCR_fallback = 1;
++		}
++	}
++
++	for (i = 0; i < 16; i++) {
++		switch (mpc_default_type) {
++		case 2:
++			if (i == 0 || i == 13)
++				continue;	/* IRQ0 & IRQ13 not connected */
++			/* fall through */
++		default:
++			if (i == 2)
++				continue;	/* IRQ2 is never connected */
++		}
++
++		if (ELCR_fallback) {
++			/*
++			 *  If the ELCR indicates a level-sensitive interrupt, we
++			 *  copy that information over to the MP table in the
++			 *  irqflag field (level sensitive, active high polarity).
++			 */
++			if (ELCR_trigger(i))
++				intsrc.mpc_irqflag = 13;
++			else
++				intsrc.mpc_irqflag = 0;
++		}
++
++		intsrc.mpc_srcbusirq = i;
++		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
++		MP_intsrc_info(&intsrc);
++	}
++
++	intsrc.mpc_irqtype = mp_ExtINT;
++	intsrc.mpc_srcbusirq = 0;
++	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
++	MP_intsrc_info(&intsrc);
++}
++
++static inline void __init construct_default_ISA_mptable(int mpc_default_type)
++{
++	struct mpc_config_processor processor;
++	struct mpc_config_bus bus;
++	struct mpc_config_ioapic ioapic;
++	struct mpc_config_lintsrc lintsrc;
++	int linttypes[2] = { mp_ExtINT, mp_NMI };
++	int i;
++
++	/*
++	 * local APIC has default address
++	 */
++	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++
++	/*
++	 * 2 CPUs, numbered 0 & 1.
++	 */
++	processor.mpc_type = MP_PROCESSOR;
++	/* Either an integrated APIC or a discrete 82489DX. */
++	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_cpuflag = CPU_ENABLED;
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++				   (boot_cpu_data.x86_model << 4) |
++				   boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++	for (i = 0; i < 2; i++) {
++		processor.mpc_apicid = i;
++		MP_processor_info(&processor);
++	}
++
++	bus.mpc_type = MP_BUS;
++	bus.mpc_busid = 0;
++	switch (mpc_default_type) {
++		default:
++			printk(KERN_ERR "???\nUnknown standard configuration %d\n",
++				mpc_default_type);
++			/* fall through */
++		case 1:
++		case 5:
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			break;
++		case 2:
++		case 6:
++		case 3:
++			memcpy(bus.mpc_bustype, "EISA  ", 6);
++			break;
++		case 4:
++		case 7:
++			memcpy(bus.mpc_bustype, "MCA   ", 6);
++	}
++	MP_bus_info(&bus);
++	if (mpc_default_type > 4) {
++		bus.mpc_busid = 1;
++		memcpy(bus.mpc_bustype, "PCI   ", 6);
++		MP_bus_info(&bus);
++	}
++
++	ioapic.mpc_type = MP_IOAPIC;
++	ioapic.mpc_apicid = 2;
++	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.mpc_flags = MPC_APIC_USABLE;
++	ioapic.mpc_apicaddr = 0xFEC00000;
++	MP_ioapic_info(&ioapic);
++
++	/*
++	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
++	 */
++	construct_default_ioirq_mptable(mpc_default_type);
++
++	lintsrc.mpc_type = MP_LINTSRC;
++	lintsrc.mpc_irqflag = 0;		/* conforming */
++	lintsrc.mpc_srcbusid = 0;
++	lintsrc.mpc_srcbusirq = 0;
++	lintsrc.mpc_destapic = MP_APIC_ALL;
++	for (i = 0; i < 2; i++) {
++		lintsrc.mpc_irqtype = linttypes[i];
++		lintsrc.mpc_destapiclint = i;
++		MP_lintsrc_info(&lintsrc);
++	}
++}
++
++static struct intel_mp_floating *mpf_found;
++
++/*
++ * Scan the memory blocks for an SMP configuration block.
++ */
++void __init get_smp_config (void)
++{
++	struct intel_mp_floating *mpf = mpf_found;
++
++	/*
++ 	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 
++ 	 * processors, where MPS only supports physical.
++ 	 */
++ 	if (acpi_lapic && acpi_ioapic) {
++ 		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
++ 		return;
++	}
++ 	else if (acpi_lapic)
++ 		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
++
++	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
++	if (mpf->mpf_feature2 & (1<<7)) {
++		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
++		pic_mode = 1;
++	} else {
++		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
++		pic_mode = 0;
++	}
++
++	/*
++	 * Now see if we need to read further.
++	 */
++	if (mpf->mpf_feature1 != 0) {
++
++		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
++		construct_default_ISA_mptable(mpf->mpf_feature1);
++
++	} else if (mpf->mpf_physptr) {
++
++		/*
++		 * Read the physical hardware table.  Anything here will
++		 * override the defaults.
++		 */
++ 		if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) {
++			smp_found_config = 0;
++			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
++			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
++			return;
++		}
++		/*
++		 * If there are no explicit MP IRQ entries, then we are
++		 * broken.  We set up most of the low 16 IO-APIC pins to
++		 * ISA defaults and hope it will work.
++		 */
++		if (!mp_irq_entries) {
++			struct mpc_config_bus bus;
++
++			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
++
++			bus.mpc_type = MP_BUS;
++			bus.mpc_busid = 0;
++			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			MP_bus_info(&bus);
++
++			construct_default_ioirq_mptable(0);
++		}
++
++	} else
++		BUG();
++
++	printk(KERN_INFO "Processors: %d\n", num_processors);
++	/*
++	 * Only use the first configuration found.
++	 */
++}
++
++static int __init smp_scan_config (unsigned long base, unsigned long length)
++{
++	extern void __bad_mpf_size(void); 
++	unsigned int *bp = isa_bus_to_virt(base);
++	struct intel_mp_floating *mpf;
++
++	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
++	if (sizeof(*mpf) != 16)
++		__bad_mpf_size();
++
++	while (length > 0) {
++		mpf = (struct intel_mp_floating *)bp;
++		if ((*bp == SMP_MAGIC_IDENT) &&
++			(mpf->mpf_length == 1) &&
++			!mpf_checksum((unsigned char *)bp, 16) &&
++			((mpf->mpf_specification == 1)
++				|| (mpf->mpf_specification == 4)) ) {
++
++			smp_found_config = 1;
++			mpf_found = mpf;
++			return 1;
++		}
++		bp += 4;
++		length -= 16;
++	}
++	return 0;
++}
++
++void __init find_intel_smp (void)
++{
++	unsigned int address;
++
++	/*
++	 * FIXME: Linux assumes you have 640K of base ram..
++	 * this continues the error...
++	 *
++	 * 1) Scan the bottom 1K for a signature
++	 * 2) Scan the top 1K of base RAM
++	 * 3) Scan the 64K of bios
++	 */
++	if (smp_scan_config(0x0,0x400) ||
++		smp_scan_config(639*0x400,0x400) ||
++			smp_scan_config(0xF0000,0x10000))
++		return;
++	/*
++	 * If it is an SMP machine we should know now, unless the
++	 * configuration is in an EISA/MCA bus machine with an
++	 * extended bios data area.
++	 *
++	 * there is a real-mode segmented pointer pointing to the
++	 * 4K EBDA area at 0x40E, calculate and scan it here.
++	 *
++	 * NOTE! There are Linux loaders that will corrupt the EBDA
++	 * area, and as such this kind of SMP config may be less
++	 * trustworthy, simply because the SMP table may have been
++	 * stomped on during early boot. These loaders are buggy and
++	 * should be fixed.
++	 */
++
++	address = *(unsigned short *)phys_to_virt(0x40E);
++	address <<= 4;
++	if (smp_scan_config(address, 0x1000))
++		return;
++
++	/* If we have come this far, we did not find an MP table  */
++	 printk(KERN_INFO "No mptable found.\n");
++}
++
++/*
++ * - Intel MP Configuration Table
++ */
++void __init find_smp_config (void)
++{
++#ifdef CONFIG_X86_LOCAL_APIC
++	find_intel_smp();
++#endif
++}
++
++
++/* --------------------------------------------------------------------------
++                            ACPI-based MP Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++void __init mp_register_lapic_address (
++	u64			address)
++{
++#ifndef CONFIG_XEN
++	mp_lapic_addr = (unsigned long) address;
++
++	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
++
++	if (boot_cpu_id == -1U)
++		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
++
++	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
++#endif
++}
++
++
++void __cpuinit mp_register_lapic (
++	u8			id, 
++	u8			enabled)
++{
++	struct mpc_config_processor processor;
++	int			boot_cpu = 0;
++	
++	if (id >= MAX_APICS) {
++		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
++			id, MAX_APICS);
++		return;
++	}
++
++	if (id == boot_cpu_physical_apicid)
++		boot_cpu = 1;
++
++#ifndef CONFIG_XEN
++	processor.mpc_type = MP_PROCESSOR;
++	processor.mpc_apicid = id;
++	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
++	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
++	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
++	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
++		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
++	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_reserved[0] = 0;
++	processor.mpc_reserved[1] = 0;
++#endif
++
++	MP_processor_info(&processor);
++}
++
++#ifdef CONFIG_X86_IO_APIC
++
++#define MP_ISA_BUS		0
++#define MP_MAX_IOAPIC_PIN	127
++
++static struct mp_ioapic_routing {
++	int			apic_id;
++	int			gsi_start;
++	int			gsi_end;
++	u32			pin_programmed[4];
++} mp_ioapic_routing[MAX_IO_APICS];
++
++
++static int mp_find_ioapic (
++	int			gsi)
++{
++	int			i = 0;
++
++	/* Find the IOAPIC that manages this GSI. */
++	for (i = 0; i < nr_ioapics; i++) {
++		if ((gsi >= mp_ioapic_routing[i].gsi_start)
++			&& (gsi <= mp_ioapic_routing[i].gsi_end))
++			return i;
++	}
++
++	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
++
++	return -1;
++}
++	
++
++void __init mp_register_ioapic (
++	u8			id, 
++	u32			address,
++	u32			gsi_base)
++{
++	int			idx = 0;
++
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++	}
++	if (!address) {
++		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++			" found in MADT table, skipping!\n");
++		return;
++	}
++
++	idx = nr_ioapics++;
++
++	mp_ioapics[idx].mpc_type = MP_IOAPIC;
++	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
++	mp_ioapics[idx].mpc_apicaddr = address;
++
++#ifndef CONFIG_XEN
++	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
++#endif
++	mp_ioapics[idx].mpc_apicid = id;
++	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++	
++	/* 
++	 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
++	 * and to prevent reprogramming of IOAPIC pins (PCI IRQs).
++	 */
++	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
++	mp_ioapic_routing[idx].gsi_start = gsi_base;
++	mp_ioapic_routing[idx].gsi_end = gsi_base + 
++		io_apic_get_redir_entries(idx);
++
++	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
++		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++		mp_ioapic_routing[idx].gsi_start,
++		mp_ioapic_routing[idx].gsi_end);
++
++	return;
++}
++
++
++void __init mp_override_legacy_irq (
++	u8			bus_irq,
++	u8			polarity, 
++	u8			trigger, 
++	u32			gsi)
++{
++	struct mpc_config_intsrc intsrc;
++	int			ioapic = -1;
++	int			pin = -1;
++
++	/* 
++	 * Convert 'gsi' to 'ioapic.pin'.
++	 */
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0)
++		return;
++	pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
++
++	/*
++	 * TBD: This check is for faulty timer entries, where the override
++	 *      erroneously sets the trigger to level, resulting in a HUGE 
++	 *      increase of timer interrupts!
++	 */
++	if ((bus_irq == 0) && (trigger == 3))
++		trigger = 1;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqtype = mp_INT;
++	intsrc.mpc_irqflag = (trigger << 2) | polarity;
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_srcbusirq = bus_irq;				       /* IRQ */
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;	   /* APIC ID */
++	intsrc.mpc_dstirq = pin;				    /* INTIN# */
++
++	Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", 
++		intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
++		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
++		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
++
++	mp_irqs[mp_irq_entries] = intsrc;
++	if (++mp_irq_entries == MAX_IRQ_SOURCES)
++		panic("Max # of irq sources exceeded!\n");
++
++	return;
++}
++
++
++void __init mp_config_acpi_legacy_irqs (void)
++{
++	struct mpc_config_intsrc intsrc;
++	int			i = 0;
++	int			ioapic = -1;
++
++	/* 
++	 * Fabricate the legacy ISA bus (bus #31).
++	 */
++	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
++	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++
++	/* 
++	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
++	 */
++	ioapic = mp_find_ioapic(0);
++	if (ioapic < 0)
++		return;
++
++	intsrc.mpc_type = MP_INTSRC;
++	intsrc.mpc_irqflag = 0;					/* Conforming */
++	intsrc.mpc_srcbus = MP_ISA_BUS;
++	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
++
++	/* 
++	 * Use the default configuration for the IRQs 0-15.  Unless
++	 * overridden by (MADT) interrupt source override entries.
++	 */
++	for (i = 0; i < 16; i++) {
++		int idx;
++
++		for (idx = 0; idx < mp_irq_entries; idx++) {
++			struct mpc_config_intsrc *irq = mp_irqs + idx;
++
++			/* Do we already have a mapping for this ISA IRQ? */
++			if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i)
++				break;
++
++			/* Do we already have a mapping for this IOAPIC pin */
++			if ((irq->mpc_dstapic == intsrc.mpc_dstapic) &&
++				(irq->mpc_dstirq == i))
++				break;
++		}
++
++		if (idx != mp_irq_entries) {
++			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
++			continue;			/* IRQ already used */
++		}
++
++		intsrc.mpc_irqtype = mp_INT;
++		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
++		intsrc.mpc_dstirq = i;
++
++		Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, "
++			"%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, 
++			(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
++			intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, 
++			intsrc.mpc_dstirq);
++
++		mp_irqs[mp_irq_entries] = intsrc;
++		if (++mp_irq_entries == MAX_IRQ_SOURCES)
++			panic("Max # of irq sources exceeded!\n");
++	}
++
++	return;
++}
++
++#define MAX_GSI_NUM	4096
++
++int mp_register_gsi(u32 gsi, int triggering, int polarity)
++{
++	int			ioapic = -1;
++	int			ioapic_pin = 0;
++	int			idx, bit = 0;
++	static int		pci_irq = 16;
++	/*
++	 * Mapping between Global System Interrupts, which
++	 * represent all possible interrupts, to the IRQs
++	 * assigned to actual devices.
++	 */
++	static int		gsi_to_irq[MAX_GSI_NUM];
++
++	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
++		return gsi;
++
++	/* Don't set up the ACPI SCI because it's already set up */
++	if (acpi_fadt.sci_int == gsi)
++		return gsi;
++
++	ioapic = mp_find_ioapic(gsi);
++	if (ioapic < 0) {
++		printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
++		return gsi;
++	}
++
++	ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start;
++
++	/* 
++	 * Avoid pin reprogramming.  PRTs typically include entries  
++	 * with redundant pin->gsi mappings (but unique PCI devices);
++	 * we only program the IOAPIC on the first.
++	 */
++	bit = ioapic_pin % 32;
++	idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32);
++	if (idx > 3) {
++		printk(KERN_ERR "Invalid reference to IOAPIC pin "
++			"%d-%d\n", mp_ioapic_routing[ioapic].apic_id, 
++			ioapic_pin);
++		return gsi;
++	}
++	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
++		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
++			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
++		return gsi_to_irq[gsi];
++	}
++
++	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
++
++	if (triggering == ACPI_LEVEL_SENSITIVE) {
++		/*
++		 * For PCI devices assign IRQs in order, avoiding gaps
++		 * due to unused I/O APIC pins.
++		 */
++		int irq = gsi;
++		if (gsi < MAX_GSI_NUM) {
++			/*
++			 * Retain the VIA chipset work-around (gsi > 15), but
++			 * avoid a problem where the 8254 timer (IRQ0) is setup
++			 * via an override (so it's not on pin 0 of the ioapic),
++			 * and at the same time, the pin 0 interrupt is a PCI
++			 * type.  The gsi > 15 test could cause these two pins
++			 * to be shared as IRQ0, and they are not shareable.
++			 * So test for this condition, and if necessary, avoid
++			 * the pin collision.
++			 */
++			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
++				gsi = pci_irq++;
++			/*
++			 * Don't assign IRQ used by ACPI SCI
++			 */
++			if (gsi == acpi_fadt.sci_int)
++				gsi = pci_irq++;
++			gsi_to_irq[irq] = gsi;
++		} else {
++			printk(KERN_ERR "GSI %u is too high\n", gsi);
++			return gsi;
++		}
++	}
++
++	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
++		triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
++		polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
++	return gsi;
++}
++
++#endif /*CONFIG_X86_IO_APIC*/
++#endif /*CONFIG_ACPI*/
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2008-08-07 12:44:36.000000000 +0200
+@@ -0,0 +1,848 @@
++/*
++ *  linux/arch/x86-64/kernel/process.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Pentium III FXSR, SSE support
++ *	Gareth Hughes <gareth@valinux.com>, May 2000
++ * 
++ *  X86-64 port
++ *	Andi Kleen.
++ *
++ *	CPU hotplug support - ashok.raj@intel.com
++ * 
++ *  Jun Nakajima <jun.nakajima@intel.com> 
++ *     Modified for Xen
++ */
++
++/*
++ * This file handles the architecture-dependent parts of process handling..
++ */
++
++#include <stdarg.h>
++
++#include <linux/cpu.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/elfcore.h>
++#include <linux/smp.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/module.h>
++#include <linux/a.out.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/ptrace.h>
++#include <linux/utsname.h>
++#include <linux/random.h>
++#include <linux/notifier.h>
++#include <linux/kprobes.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/processor.h>
++#include <asm/i387.h>
++#include <asm/mmu_context.h>
++#include <asm/pda.h>
++#include <asm/prctl.h>
++#include <asm/kdebug.h>
++#include <xen/interface/platform.h>
++#include <xen/interface/physdev.h>
++#include <xen/interface/vcpu.h>
++#include <asm/desc.h>
++#include <asm/proto.h>
++#include <asm/hardirq.h>
++#include <asm/ia32.h>
++#include <asm/idle.h>
++
++#include <xen/cpu_hotplug.h>
++
++asmlinkage extern void ret_from_fork(void);
++
++unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
++
++unsigned long boot_option_idle_override = 0;
++EXPORT_SYMBOL(boot_option_idle_override);
++
++/*
++ * Powermanagement idle function, if any..
++ */
++void (*pm_idle)(void);
++EXPORT_SYMBOL(pm_idle);
++static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
++
++static ATOMIC_NOTIFIER_HEAD(idle_notifier);
++
++void idle_notifier_register(struct notifier_block *n)
++{
++	atomic_notifier_chain_register(&idle_notifier, n);
++}
++EXPORT_SYMBOL_GPL(idle_notifier_register);
++
++void idle_notifier_unregister(struct notifier_block *n)
++{
++	atomic_notifier_chain_unregister(&idle_notifier, n);
++}
++EXPORT_SYMBOL(idle_notifier_unregister);
++
++enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
++static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
++
++void enter_idle(void)
++{
++	__get_cpu_var(idle_state) = CPU_IDLE;
++	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
++}
++
++static void __exit_idle(void)
++{
++	__get_cpu_var(idle_state) = CPU_NOT_IDLE;
++	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
++}
++
++/* Called from interrupts to signify idle end */
++void exit_idle(void)
++{
++	if (current->pid | read_pda(irqcount))
++		return;
++	__exit_idle();
++}
++
++/*
++ * On SMP it's slightly faster (but much more power-consuming!)
++ * to poll the ->need_resched flag instead of waiting for the
++ * cross-CPU IPI to arrive. Use this option with caution.
++ */
++static void poll_idle (void)
++{
++	local_irq_enable();
++
++	asm volatile(
++		"2:"
++		"testl %0,%1;"
++		"rep; nop;"
++		"je 2b;"
++		: :
++		"i" (_TIF_NEED_RESCHED),
++		"m" (current_thread_info()->flags));
++}
++
++static void xen_idle(void)
++{
++	local_irq_disable();
++
++	if (need_resched())
++		local_irq_enable();
++	else {
++		current_thread_info()->status &= ~TS_POLLING;
++		smp_mb__after_clear_bit();
++		safe_halt();
++		current_thread_info()->status |= TS_POLLING;
++	}
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static inline void play_dead(void)
++{
++	idle_task_exit();
++	local_irq_disable();
++	cpu_clear(smp_processor_id(), cpu_initialized);
++	preempt_enable_no_resched();
++	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
++	cpu_bringup();
++}
++#else
++static inline void play_dead(void)
++{
++	BUG();
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++/*
++ * The idle thread. There's no useful work to be
++ * done, so just try to conserve power and have a
++ * low exit latency (ie sit in a loop waiting for
++ * somebody to say that they'd like to reschedule)
++ */
++void cpu_idle (void)
++{
++	current_thread_info()->status |= TS_POLLING;
++	/* endless idle loop with no priority at all */
++	while (1) {
++		while (!need_resched()) {
++			void (*idle)(void);
++
++			if (__get_cpu_var(cpu_idle_state))
++				__get_cpu_var(cpu_idle_state) = 0;
++			rmb();
++			idle = xen_idle; /* no alternatives */
++			if (cpu_is_offline(smp_processor_id()))
++				play_dead();
++			enter_idle();
++			idle();
++			__exit_idle();
++		}
++
++		preempt_enable_no_resched();
++		schedule();
++		preempt_disable();
++	}
++}
++
++void cpu_idle_wait(void)
++{
++	unsigned int cpu, this_cpu = get_cpu();
++	cpumask_t map;
++
++	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
++	put_cpu();
++
++ 	cpus_clear(map);
++	for_each_online_cpu(cpu) {
++		per_cpu(cpu_idle_state, cpu) = 1;
++		cpu_set(cpu, map);
++	}
++
++	__get_cpu_var(cpu_idle_state) = 0;
++
++	wmb();
++	do {
++		ssleep(1);
++		for_each_online_cpu(cpu) {
++			if (cpu_isset(cpu, map) &&
++					!per_cpu(cpu_idle_state, cpu))
++				cpu_clear(cpu, map);
++		}
++		cpus_and(map, map, cpu_online_map);
++	} while (!cpus_empty(map));
++}
++EXPORT_SYMBOL_GPL(cpu_idle_wait);
++
++void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) 
++{
++}
++
++static int __init idle_setup (char *str)
++{
++	if (!strncmp(str, "poll", 4)) {
++		printk("using polling idle threads.\n");
++		pm_idle = poll_idle;
++	}
++
++	boot_option_idle_override = 1;
++	return 1;
++}
++
++__setup("idle=", idle_setup);
++
++/* Prints also some state that isn't saved in the pt_regs */ 
++void __show_regs(struct pt_regs * regs)
++{
++	unsigned long fs, gs, shadowgs;
++	unsigned int fsindex,gsindex;
++	unsigned int ds,cs,es; 
++
++	printk("\n");
++	print_modules();
++	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
++		current->pid, current->comm, print_tainted(),
++		system_utsname.release,
++		(int)strcspn(system_utsname.version, " "),
++		system_utsname.version);
++	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
++	printk_address(regs->rip); 
++	printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp,
++		regs->eflags);
++	printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
++	       regs->rax, regs->rbx, regs->rcx);
++	printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
++	       regs->rdx, regs->rsi, regs->rdi); 
++	printk("RBP: %016lx R08: %016lx R09: %016lx\n",
++	       regs->rbp, regs->r8, regs->r9); 
++	printk("R10: %016lx R11: %016lx R12: %016lx\n",
++	       regs->r10, regs->r11, regs->r12); 
++	printk("R13: %016lx R14: %016lx R15: %016lx\n",
++	       regs->r13, regs->r14, regs->r15); 
++
++	asm("mov %%ds,%0" : "=r" (ds)); 
++	asm("mov %%cs,%0" : "=r" (cs)); 
++	asm("mov %%es,%0" : "=r" (es)); 
++	asm("mov %%fs,%0" : "=r" (fsindex));
++	asm("mov %%gs,%0" : "=r" (gsindex));
++
++	rdmsrl(MSR_FS_BASE, fs);
++	rdmsrl(MSR_GS_BASE, gs); 
++	rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); 
++
++	printk("FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", 
++	       fs,fsindex,gs,gsindex,shadowgs); 
++	printk("CS:  %04x DS: %04x ES: %04x\n", cs, ds, es); 
++
++}
++
++void show_regs(struct pt_regs *regs)
++{
++	printk("CPU %d:", smp_processor_id());
++	__show_regs(regs);
++	show_trace(NULL, regs, (void *)(regs + 1));
++}
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++	struct task_struct *me = current;
++	struct thread_struct *t = &me->thread;
++
++	if (me->thread.io_bitmap_ptr) { 
++#ifndef CONFIG_X86_NO_TSS
++		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
++#endif
++#ifdef CONFIG_XEN
++		struct physdev_set_iobitmap iobmp_op;
++		memset(&iobmp_op, 0, sizeof(iobmp_op));
++#endif
++
++		kfree(t->io_bitmap_ptr);
++		t->io_bitmap_ptr = NULL;
++		/*
++		 * Careful, clear this in the TSS too:
++		 */
++#ifndef CONFIG_X86_NO_TSS
++		memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
++		put_cpu();
++#endif
++#ifdef CONFIG_XEN
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &iobmp_op));
++#endif
++		t->io_bitmap_max = 0;
++	}
++}
++
++void load_gs_index(unsigned gs)
++{
++	WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gs));
++}
++
++void flush_thread(void)
++{
++	struct task_struct *tsk = current;
++	struct thread_info *t = current_thread_info();
++
++	if (t->flags & _TIF_ABI_PENDING) {
++		t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
++		if (t->flags & _TIF_IA32)
++			current_thread_info()->status |= TS_COMPAT;
++	}
++
++	tsk->thread.debugreg0 = 0;
++	tsk->thread.debugreg1 = 0;
++	tsk->thread.debugreg2 = 0;
++	tsk->thread.debugreg3 = 0;
++	tsk->thread.debugreg6 = 0;
++	tsk->thread.debugreg7 = 0;
++	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
++	/*
++	 * Forget coprocessor state..
++	 */
++	clear_fpu(tsk);
++	clear_used_math();
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++	if (dead_task->mm) {
++		if (dead_task->mm->context.size) {
++			printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
++					dead_task->comm,
++					dead_task->mm->context.ldt,
++					dead_task->mm->context.size);
++			BUG();
++		}
++	}
++}
++
++static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
++{
++	struct user_desc ud = { 
++		.base_addr = addr,
++		.limit = 0xfffff,
++		.seg_32bit = 1,
++		.limit_in_pages = 1,
++		.useable = 1,
++	};
++	struct n_desc_struct *desc = (void *)t->thread.tls_array;
++	desc += tls;
++	desc->a = LDT_entry_a(&ud); 
++	desc->b = LDT_entry_b(&ud); 
++}
++
++static inline u32 read_32bit_tls(struct task_struct *t, int tls)
++{
++	struct desc_struct *desc = (void *)t->thread.tls_array;
++	desc += tls;
++	return desc->base0 | 
++		(((u32)desc->base1) << 16) | 
++		(((u32)desc->base2) << 24);
++}
++
++/*
++ * This gets called before we allocate a new thread and copy
++ * the current task into it.
++ */
++void prepare_to_copy(struct task_struct *tsk)
++{
++	unlazy_fpu(tsk);
++}
++
++int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
++		unsigned long unused,
++	struct task_struct * p, struct pt_regs * regs)
++{
++	int err;
++	struct pt_regs * childregs;
++	struct task_struct *me = current;
++
++	childregs = ((struct pt_regs *)
++			(THREAD_SIZE + task_stack_page(p))) - 1;
++	*childregs = *regs;
++
++	childregs->rax = 0;
++	childregs->rsp = rsp;
++	if (rsp == ~0UL)
++		childregs->rsp = (unsigned long)childregs;
++
++	p->thread.rsp = (unsigned long) childregs;
++	p->thread.rsp0 = (unsigned long) (childregs+1);
++	p->thread.userrsp = me->thread.userrsp; 
++
++	set_tsk_thread_flag(p, TIF_FORK);
++
++	p->thread.fs = me->thread.fs;
++	p->thread.gs = me->thread.gs;
++
++	asm("mov %%gs,%0" : "=m" (p->thread.gsindex));
++	asm("mov %%fs,%0" : "=m" (p->thread.fsindex));
++	asm("mov %%es,%0" : "=m" (p->thread.es));
++	asm("mov %%ds,%0" : "=m" (p->thread.ds));
++
++	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
++		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++		if (!p->thread.io_bitmap_ptr) {
++			p->thread.io_bitmap_max = 0;
++			return -ENOMEM;
++		}
++		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
++				IO_BITMAP_BYTES);
++	} 
++
++	/*
++	 * Set a new TLS for the child thread?
++	 */
++	if (clone_flags & CLONE_SETTLS) {
++#ifdef CONFIG_IA32_EMULATION
++		if (test_thread_flag(TIF_IA32))
++			err = ia32_child_tls(p, childregs); 
++		else 			
++#endif	 
++			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 
++		if (err) 
++			goto out;
++	}
++        p->thread.iopl = current->thread.iopl;
++
++	err = 0;
++out:
++	if (err && p->thread.io_bitmap_ptr) {
++		kfree(p->thread.io_bitmap_ptr);
++		p->thread.io_bitmap_max = 0;
++	}
++	return err;
++}
++
++static inline void __save_init_fpu( struct task_struct *tsk )
++{
++	asm volatile( "rex64 ; fxsave %0 ; fnclex"
++		      : "=m" (tsk->thread.i387.fxsave));
++	tsk->thread_info->status &= ~TS_USEDFPU;
++}
++
++/*
++ *	switch_to(x,y) should switch tasks from x to y.
++ *
++ * This could still be optimized: 
++ * - fold all the options into a flag word and test it with a single test.
++ * - could test fs/gs bitsliced
++ *
++ * Kprobes not supported here. Set the probe on schedule instead.
++ */
++__kprobes struct task_struct *
++__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
++{
++	struct thread_struct *prev = &prev_p->thread,
++				 *next = &next_p->thread;
++	int cpu = smp_processor_id();  
++#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;
++
++	/*
++	 * This is basically '__unlazy_fpu', except that we queue a
++	 * multicall to indicate FPU task switch, rather than
++	 * synchronously trapping to Xen.
++	 * The AMD workaround requires it to be after DS reload, or
++	 * after DS has been cleared, which we do in __prepare_arch_switch.
++	 */
++	if (prev_p->thread_info->status & TS_USEDFPU) {
++		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
++		mcl->op      = __HYPERVISOR_fpu_taskswitch;
++		mcl->args[0] = 1;
++		mcl++;
++	}
++
++	/*
++	 * Reload esp0, LDT and the page table pointer:
++	 */
++	mcl->op      = __HYPERVISOR_stack_switch;
++	mcl->args[0] = __KERNEL_DS;
++	mcl->args[1] = next->rsp0;
++	mcl++;
++
++	/*
++	 * Load the per-thread Thread-Local Storage descriptor.
++	 * This is load_TLS(next, cpu) with multicalls.
++	 */
++#define C(i) do {							\
++	if (unlikely(next->tls_array[i] != prev->tls_array[i])) {	\
++		mcl->op      = __HYPERVISOR_update_descriptor;		\
++		mcl->args[0] = virt_to_machine(				\
++			&cpu_gdt(cpu)[GDT_ENTRY_TLS_MIN + i]);		\
++		mcl->args[1] = next->tls_array[i];			\
++		mcl++;							\
++	}								\
++} while (0)
++	C(0); C(1); C(2);
++#undef C
++
++	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++;
++	}
++
++	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
++		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();
++
++	/* 
++	 * Switch DS and ES.
++	 * This won't pick up thread selector changes, but I guess that is ok.
++	 */
++	if (unlikely(next->es))
++		loadsegment(es, next->es); 
++	
++	if (unlikely(next->ds))
++		loadsegment(ds, next->ds);
++
++	/* 
++	 * Switch FS and GS.
++	 */
++	if (unlikely(next->fsindex))
++		loadsegment(fs, next->fsindex);
++
++	if (next->fs)
++		WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_FS, next->fs));
++	
++	if (unlikely(next->gsindex))
++		load_gs_index(next->gsindex);
++
++	if (next->gs)
++		WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER, next->gs));
++
++	/* 
++	 * Switch the PDA context.
++	 */
++	prev->userrsp = read_pda(oldrsp); 
++	write_pda(oldrsp, next->userrsp); 
++	write_pda(pcurrent, next_p); 
++	write_pda(kernelstack,
++		  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
++
++	/*
++	 * Now maybe reload the debug registers
++	 */
++	if (unlikely(next->debugreg7)) {
++		set_debugreg(next->debugreg0, 0);
++		set_debugreg(next->debugreg1, 1);
++		set_debugreg(next->debugreg2, 2);
++		set_debugreg(next->debugreg3, 3);
++		/* no 4 and 5 */
++		set_debugreg(next->debugreg6, 6);
++		set_debugreg(next->debugreg7, 7);
++	}
++
++	return prev_p;
++}
++
++/*
++ * sys_execve() executes a new program.
++ */
++asmlinkage 
++long sys_execve(char __user *name, char __user * __user *argv,
++		char __user * __user *envp, struct pt_regs regs)
++{
++	long error;
++	char * filename;
++
++	filename = getname(name);
++	error = PTR_ERR(filename);
++	if (IS_ERR(filename)) 
++		return error;
++	error = do_execve(filename, argv, envp, &regs); 
++	if (error == 0) {
++		task_lock(current);
++		current->ptrace &= ~PT_DTRACE;
++		task_unlock(current);
++	}
++	putname(filename);
++	return error;
++}
++
++void set_personality_64bit(void)
++{
++	/* inherit personality from parent */
++
++	/* Make sure to be in 64bit mode */
++	clear_thread_flag(TIF_IA32); 
++
++	/* TBD: overwrites user setup. Should have two bits.
++	   But 64bit processes have always behaved this way,
++	   so it's not too bad. The main problem is just that
++   	   32bit childs are affected again. */
++	current->personality &= ~READ_IMPLIES_EXEC;
++}
++
++asmlinkage long sys_fork(struct pt_regs *regs)
++{
++	return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
++}
++
++asmlinkage long
++sys_clone(unsigned long clone_flags, unsigned long newsp,
++	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
++{
++	if (!newsp)
++		newsp = regs->rsp;
++	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
++}
++
++/*
++ * This is trivial, and on the face of it looks like it
++ * could equally well be done in user mode.
++ *
++ * Not so, for quite unobvious reasons - register pressure.
++ * In user mode vfork() cannot have a stack frame, and if
++ * done by calling the "clone()" system call directly, you
++ * do not have enough call-clobbered registers to hold all
++ * the information you need.
++ */
++asmlinkage long sys_vfork(struct pt_regs *regs)
++{
++	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
++		    NULL, NULL);
++}
++
++unsigned long get_wchan(struct task_struct *p)
++{
++	unsigned long stack;
++	u64 fp,rip;
++	int count = 0;
++
++	if (!p || p == current || p->state==TASK_RUNNING)
++		return 0; 
++	stack = (unsigned long)task_stack_page(p);
++	if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE)
++		return 0;
++	fp = *(u64 *)(p->thread.rsp);
++	do { 
++		if (fp < (unsigned long)stack ||
++		    fp > (unsigned long)stack+THREAD_SIZE)
++			return 0; 
++		rip = *(u64 *)(fp+8); 
++		if (!in_sched_functions(rip))
++			return rip; 
++		fp = *(u64 *)fp; 
++	} while (count++ < 16); 
++	return 0;
++}
++
++long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
++{ 
++	int ret = 0; 
++	int doit = task == current;
++	int cpu;
++
++	switch (code) { 
++	case ARCH_SET_GS:
++		if (addr >= TASK_SIZE_OF(task))
++			return -EPERM; 
++		cpu = get_cpu();
++		/* handle small bases via the GDT because that's faster to 
++		   switch. */
++		if (addr <= 0xffffffff) {  
++			set_32bit_tls(task, GS_TLS, addr); 
++			if (doit) { 
++				load_TLS(&task->thread, cpu);
++				load_gs_index(GS_TLS_SEL); 
++			}
++			task->thread.gsindex = GS_TLS_SEL; 
++			task->thread.gs = 0;
++		} else { 
++			task->thread.gsindex = 0;
++			task->thread.gs = addr;
++			if (doit) {
++				load_gs_index(0);
++				ret = HYPERVISOR_set_segment_base(
++					SEGBASE_GS_USER, addr);
++			} 
++		}
++		put_cpu();
++		break;
++	case ARCH_SET_FS:
++		/* Not strictly needed for fs, but do it for symmetry
++		   with gs */
++		if (addr >= TASK_SIZE_OF(task))
++			return -EPERM; 
++		cpu = get_cpu();
++		/* handle small bases via the GDT because that's faster to 
++		   switch. */
++		if (addr <= 0xffffffff) { 
++			set_32bit_tls(task, FS_TLS, addr);
++			if (doit) { 
++				load_TLS(&task->thread, cpu); 
++				asm volatile("movl %0,%%fs" :: "r"(FS_TLS_SEL));
++			}
++			task->thread.fsindex = FS_TLS_SEL;
++			task->thread.fs = 0;
++		} else { 
++			task->thread.fsindex = 0;
++			task->thread.fs = addr;
++			if (doit) {
++				/* set the selector to 0 to not confuse
++				   __switch_to */
++				asm volatile("movl %0,%%fs" :: "r" (0));
++                                ret = HYPERVISOR_set_segment_base(SEGBASE_FS,
++								  addr);
++			}
++		}
++		put_cpu();
++		break;
++	case ARCH_GET_FS: { 
++		unsigned long base; 
++		if (task->thread.fsindex == FS_TLS_SEL)
++			base = read_32bit_tls(task, FS_TLS);
++		else if (doit)
++			rdmsrl(MSR_FS_BASE, base);
++		else
++			base = task->thread.fs;
++		ret = put_user(base, (unsigned long __user *)addr); 
++		break; 
++	}
++	case ARCH_GET_GS: { 
++		unsigned long base;
++		unsigned gsindex;
++		if (task->thread.gsindex == GS_TLS_SEL)
++			base = read_32bit_tls(task, GS_TLS);
++		else if (doit) {
++ 			asm("movl %%gs,%0" : "=r" (gsindex));
++			if (gsindex)
++				rdmsrl(MSR_KERNEL_GS_BASE, base);
++			else
++				base = task->thread.gs;
++		}
++		else
++			base = task->thread.gs;
++		ret = put_user(base, (unsigned long __user *)addr); 
++		break;
++	}
++
++	default:
++		ret = -EINVAL;
++		break;
++	} 
++
++	return ret;	
++} 
++
++long sys_arch_prctl(int code, unsigned long addr)
++{
++	return do_arch_prctl(current, code, addr);
++} 
++
++/* 
++ * Capture the user space registers if the task is not running (in user space)
++ */
++int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
++{
++	struct pt_regs *pp, ptregs;
++
++	pp = task_pt_regs(tsk);
++
++	ptregs = *pp; 
++	ptregs.cs &= 0xffff;
++	ptregs.ss &= 0xffff;
++
++	elf_core_copy_regs(regs, &ptregs);
++ 
++        boot_option_idle_override = 1;
++	return 1;
++}
++
++unsigned long arch_align_stack(unsigned long sp)
++{
++	if (randomize_va_space)
++		sp -= get_random_int() % 8192;
++	return sp & ~0xf;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,1656 @@
++/*
++ *  linux/arch/x86-64/kernel/setup.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *
++ *  Nov 2001 Dave Jones <davej@suse.de>
++ *  Forked from i386 setup code.
++ */
++
++/*
++ * This file handles the architecture-dependent parts of initialization
++ */
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/user.h>
++#include <linux/a.out.h>
++#include <linux/screen_info.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/initrd.h>
++#include <linux/highmem.h>
++#include <linux/bootmem.h>
++#include <linux/module.h>
++#include <asm/processor.h>
++#include <linux/console.h>
++#include <linux/seq_file.h>
++#include <linux/crash_dump.h>
++#include <linux/root_dev.h>
++#include <linux/pci.h>
++#include <linux/acpi.h>
++#include <linux/kallsyms.h>
++#include <linux/edd.h>
++#include <linux/mmzone.h>
++#include <linux/kexec.h>
++#include <linux/cpufreq.h>
++#include <linux/dmi.h>
++#include <linux/dma-mapping.h>
++#include <linux/ctype.h>
++
++#include <asm/mtrr.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/msr.h>
++#include <asm/desc.h>
++#include <video/edid.h>
++#include <asm/e820.h>
++#include <asm/dma.h>
++#include <asm/mpspec.h>
++#include <asm/mmu_context.h>
++#include <asm/bootsetup.h>
++#include <asm/proto.h>
++#include <asm/setup.h>
++#include <asm/mach_apic.h>
++#include <asm/numa.h>
++#include <asm/sections.h>
++#include <asm/dmi.h>
++#ifdef CONFIG_XEN
++#include <linux/percpu.h>
++#include <xen/interface/physdev.h>
++#include "setup_arch_pre.h"
++#include <asm/hypervisor.h>
++#include <xen/interface/nmi.h>
++#include <xen/features.h>
++#include <xen/firmware.h>
++#include <xen/xencons.h>
++#define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
++#define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
++#include <asm/mach-xen/setup_arch_post.h>
++#include <xen/interface/memory.h>
++
++#ifdef CONFIG_XEN
++#include <xen/interface/kexec.h>
++#endif
++
++extern unsigned long start_pfn;
++extern struct edid_info edid_info;
++
++shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++EXPORT_SYMBOL(HYPERVISOR_shared_info);
++
++extern char hypercall_page[PAGE_SIZE];
++EXPORT_SYMBOL(hypercall_page);
++
++static int xen_panic_event(struct notifier_block *, unsigned long, void *);
++static struct notifier_block xen_panic_block = {
++	xen_panic_event, NULL, 0 /* try to go last */
++};
++
++unsigned long *phys_to_machine_mapping;
++unsigned long *pfn_to_mfn_frame_list_list, *pfn_to_mfn_frame_list[512];
++
++EXPORT_SYMBOL(phys_to_machine_mapping);
++
++DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]);
++DEFINE_PER_CPU(int, nr_multicall_ents);
++
++/* Raw start-of-day parameters from the hypervisor. */
++start_info_t *xen_start_info;
++EXPORT_SYMBOL(xen_start_info);
++#endif
++
++/*
++ * Machine setup..
++ */
++
++struct cpuinfo_x86 boot_cpu_data __read_mostly;
++EXPORT_SYMBOL(boot_cpu_data);
++
++unsigned long mmu_cr4_features;
++
++int acpi_disabled;
++EXPORT_SYMBOL(acpi_disabled);
++#ifdef	CONFIG_ACPI
++extern int __initdata acpi_ht;
++extern acpi_interrupt_flags	acpi_sci_flags;
++int __initdata acpi_force = 0;
++#endif
++
++int acpi_numa __initdata;
++
++/* Boot loader ID as an integer, for the benefit of proc_dointvec */
++int bootloader_type;
++
++unsigned long saved_video_mode;
++
++/* 
++ * Early DMI memory
++ */
++int dmi_alloc_index;
++char dmi_alloc_data[DMI_MAX_DATA];
++
++/*
++ * Setup options
++ */
++struct screen_info screen_info;
++EXPORT_SYMBOL(screen_info);
++struct sys_desc_table_struct {
++	unsigned short length;
++	unsigned char table[0];
++};
++
++struct edid_info edid_info;
++EXPORT_SYMBOL_GPL(edid_info);
++struct e820map e820;
++#ifdef CONFIG_XEN
++struct e820map machine_e820;
++#endif
++
++extern int root_mountflags;
++
++char command_line[COMMAND_LINE_SIZE];
++
++struct resource standard_io_resources[] = {
++	{ .name = "dma1", .start = 0x00, .end = 0x1f,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "pic1", .start = 0x20, .end = 0x21,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "timer0", .start = 0x40, .end = 0x43,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "timer1", .start = 0x50, .end = 0x53,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "keyboard", .start = 0x60, .end = 0x6f,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "dma page reg", .start = 0x80, .end = 0x8f,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "pic2", .start = 0xa0, .end = 0xa1,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "dma2", .start = 0xc0, .end = 0xdf,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
++	{ .name = "fpu", .start = 0xf0, .end = 0xff,
++		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
++};
++
++#define STANDARD_IO_RESOURCES \
++	(sizeof standard_io_resources / sizeof standard_io_resources[0])
++
++#define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
++
++struct resource data_resource = {
++	.name = "Kernel data",
++	.start = 0,
++	.end = 0,
++	.flags = IORESOURCE_RAM,
++};
++struct resource code_resource = {
++	.name = "Kernel code",
++	.start = 0,
++	.end = 0,
++	.flags = IORESOURCE_RAM,
++};
++
++#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
++
++static struct resource system_rom_resource = {
++	.name = "System ROM",
++	.start = 0xf0000,
++	.end = 0xfffff,
++	.flags = IORESOURCE_ROM,
++};
++
++static struct resource extension_rom_resource = {
++	.name = "Extension ROM",
++	.start = 0xe0000,
++	.end = 0xeffff,
++	.flags = IORESOURCE_ROM,
++};
++
++static struct resource adapter_rom_resources[] = {
++	{ .name = "Adapter ROM", .start = 0xc8000, .end = 0,
++		.flags = IORESOURCE_ROM },
++	{ .name = "Adapter ROM", .start = 0, .end = 0,
++		.flags = IORESOURCE_ROM },
++	{ .name = "Adapter ROM", .start = 0, .end = 0,
++		.flags = IORESOURCE_ROM },
++	{ .name = "Adapter ROM", .start = 0, .end = 0,
++		.flags = IORESOURCE_ROM },
++	{ .name = "Adapter ROM", .start = 0, .end = 0,
++		.flags = IORESOURCE_ROM },
++	{ .name = "Adapter ROM", .start = 0, .end = 0,
++		.flags = IORESOURCE_ROM }
++};
++
++#define ADAPTER_ROM_RESOURCES \
++	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
++
++static struct resource video_rom_resource = {
++	.name = "Video ROM",
++	.start = 0xc0000,
++	.end = 0xc7fff,
++	.flags = IORESOURCE_ROM,
++};
++
++static struct resource video_ram_resource = {
++	.name = "Video RAM area",
++	.start = 0xa0000,
++	.end = 0xbffff,
++	.flags = IORESOURCE_RAM,
++};
++
++#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
++
++static int __init romchecksum(unsigned char *rom, unsigned long length)
++{
++	unsigned char *p, sum = 0;
++
++	for (p = rom; p < rom + length; p++)
++		sum += *p;
++	return sum == 0;
++}
++
++static void __init probe_roms(void)
++{
++	unsigned long start, length, upper;
++	unsigned char *rom;
++	int	      i;
++
++#ifdef CONFIG_XEN
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return;
++#endif
++
++	/* video rom */
++	upper = adapter_rom_resources[0].start;
++	for (start = video_rom_resource.start; start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		video_rom_resource.start = start;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* if checksum okay, trust length byte */
++		if (length && romchecksum(rom, length))
++			video_rom_resource.end = start + length - 1;
++
++		request_resource(&iomem_resource, &video_rom_resource);
++		break;
++			}
++
++	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
++	if (start < upper)
++		start = upper;
++
++	/* system rom */
++	request_resource(&iomem_resource, &system_rom_resource);
++	upper = system_rom_resource.start;
++
++	/* check for extension rom (ignore length byte!) */
++	rom = isa_bus_to_virt(extension_rom_resource.start);
++	if (romsignature(rom)) {
++		length = extension_rom_resource.end - extension_rom_resource.start + 1;
++		if (romchecksum(rom, length)) {
++			request_resource(&iomem_resource, &extension_rom_resource);
++			upper = extension_rom_resource.start;
++		}
++	}
++
++	/* check for adapter roms on 2k boundaries */
++	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* but accept any length that fits if checksum okay */
++		if (!length || start + length > upper || !romchecksum(rom, length))
++			continue;
++
++		adapter_rom_resources[i].start = start;
++		adapter_rom_resources[i].end = start + length - 1;
++		request_resource(&iomem_resource, &adapter_rom_resources[i]);
++
++		start = adapter_rom_resources[i++].end & ~2047UL;
++	}
++}
++
++/* Check for full argument with no trailing characters */
++static int fullarg(char *p, char *arg)
++{
++	int l = strlen(arg);
++	return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
++}
++
++static __init void parse_cmdline_early (char ** cmdline_p)
++{
++	char c = ' ', *to = command_line, *from = COMMAND_LINE;
++	int len = 0;
++	int userdef = 0;
++
++	for (;;) {
++		if (c != ' ') 
++			goto next_char; 
++
++#ifdef  CONFIG_SMP
++		/*
++		 * If the BIOS enumerates physical processors before logical,
++		 * maxcpus=N at enumeration-time can be used to disable HT.
++		 */
++		else if (!memcmp(from, "maxcpus=", 8)) {
++			extern unsigned int maxcpus;
++
++			maxcpus = simple_strtoul(from + 8, NULL, 0);
++		}
++#endif
++#ifdef CONFIG_ACPI
++		/* "acpi=off" disables both ACPI table parsing and interpreter init */
++		if (fullarg(from,"acpi=off"))
++			disable_acpi();
++
++		if (fullarg(from, "acpi=force")) { 
++			/* add later when we do DMI horrors: */
++			acpi_force = 1;
++			acpi_disabled = 0;
++		}
++
++		/* acpi=ht just means: do ACPI MADT parsing 
++		   at bootup, but don't enable the full ACPI interpreter */
++		if (fullarg(from, "acpi=ht")) { 
++			if (!acpi_force)
++				disable_acpi();
++			acpi_ht = 1; 
++		}
++                else if (fullarg(from, "pci=noacpi")) 
++			acpi_disable_pci();
++		else if (fullarg(from, "acpi=noirq"))
++			acpi_noirq_set();
++
++		else if (fullarg(from, "acpi_sci=edge"))
++			acpi_sci_flags.trigger =  1;
++		else if (fullarg(from, "acpi_sci=level"))
++			acpi_sci_flags.trigger = 3;
++		else if (fullarg(from, "acpi_sci=high"))
++			acpi_sci_flags.polarity = 1;
++		else if (fullarg(from, "acpi_sci=low"))
++			acpi_sci_flags.polarity = 3;
++
++		/* acpi=strict disables out-of-spec workarounds */
++		else if (fullarg(from, "acpi=strict")) {
++			acpi_strict = 1;
++		}
++#ifdef CONFIG_X86_IO_APIC
++		else if (fullarg(from, "acpi_skip_timer_override"))
++			acpi_skip_timer_override = 1;
++#endif
++#endif
++
++#ifndef CONFIG_XEN
++		if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
++			clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
++			disable_apic = 1;
++		}
++
++		if (fullarg(from, "noapic"))
++			skip_ioapic_setup = 1;
++
++		if (fullarg(from,"apic")) {
++			skip_ioapic_setup = 0;
++			ioapic_force = 1;
++		}
++#endif
++			
++		if (!memcmp(from, "mem=", 4))
++			parse_memopt(from+4, &from); 
++
++		if (!memcmp(from, "memmap=", 7)) {
++			/* exactmap option is for used defined memory */
++			if (!memcmp(from+7, "exactmap", 8)) {
++#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 = e820_end_of_ram();
++#endif
++				from += 8+7;
++				end_pfn_map = 0;
++				e820.nr_map = 0;
++				userdef = 1;
++			}
++			else {
++				parse_memmapopt(from+7, &from);
++				userdef = 1;
++			}
++		}
++
++#ifdef CONFIG_NUMA
++		if (!memcmp(from, "numa=", 5))
++			numa_setup(from+5); 
++#endif
++
++		if (!memcmp(from,"iommu=",6)) { 
++			iommu_setup(from+6); 
++		}
++
++		if (fullarg(from,"oops=panic"))
++			panic_on_oops = 1;
++
++		if (!memcmp(from, "noexec=", 7))
++			nonx_setup(from + 7);
++
++#ifdef CONFIG_KEXEC
++		/* crashkernel=size@addr specifies the location to reserve for
++		 * a crash kernel.  By reserving this memory we guarantee
++		 * that linux never set's it up as a DMA target.
++		 * Useful for holding code to do something appropriate
++		 * after a kernel panic.
++		 */
++		else if (!memcmp(from, "crashkernel=", 12)) {
++#ifndef CONFIG_XEN
++			unsigned long size, base;
++			size = memparse(from+12, &from);
++			if (*from == '@') {
++				base = memparse(from+1, &from);
++				/* FIXME: Do I want a sanity check
++				 * to validate the memory range?
++				 */
++				crashk_res.start = base;
++				crashk_res.end   = base + size - 1;
++			}
++#else
++			printk("Ignoring crashkernel command line, "
++			       "parameter will be supplied by xen\n");
++#endif
++		}
++#endif
++
++#ifdef CONFIG_PROC_VMCORE
++		/* elfcorehdr= specifies the location of elf core header
++		 * stored by the crashed kernel. This option will be passed
++		 * by kexec loader to the capture kernel.
++		 */
++		else if(!memcmp(from, "elfcorehdr=", 11))
++			elfcorehdr_addr = memparse(from+11, &from);
++#endif
++
++#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_XEN)
++		else if (!memcmp(from, "additional_cpus=", 16))
++			setup_additional_cpus(from+16);
++#endif
++
++	next_char:
++		c = *(from++);
++		if (!c)
++			break;
++		if (COMMAND_LINE_SIZE <= ++len)
++			break;
++		*(to++) = c;
++	}
++	if (userdef) {
++		printk(KERN_INFO "user-defined physical RAM map:\n");
++		e820_print_map("user");
++	}
++	*to = '\0';
++	*cmdline_p = command_line;
++}
++
++#ifndef CONFIG_NUMA
++static void __init
++contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
++{
++	unsigned long bootmap_size, bootmap;
++
++	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
++	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
++	if (bootmap == -1L)
++		panic("Cannot find bootmem map of size %ld\n",bootmap_size);
++	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
++#ifdef CONFIG_XEN
++	if (xen_start_info->nr_pages < end_pfn)
++		e820_bootmem_free(NODE_DATA(0), 0,
++				  xen_start_info->nr_pages<<PAGE_SHIFT);
++	else
++#endif
++	e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
++	reserve_bootmem(bootmap, bootmap_size);
++} 
++#endif
++
++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
++struct edd edd;
++#ifdef CONFIG_EDD_MODULE
++EXPORT_SYMBOL(edd);
++#endif
++#ifndef CONFIG_XEN
++/**
++ * copy_edd() - Copy the BIOS EDD information
++ *              from boot_params into a safe place.
++ *
++ */
++static inline void copy_edd(void)
++{
++     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
++     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
++     edd.mbr_signature_nr = EDD_MBR_SIG_NR;
++     edd.edd_info_nr = EDD_NR;
++}
++#endif
++#else
++static inline void copy_edd(void)
++{
++}
++#endif
++
++#ifndef CONFIG_XEN
++#define EBDA_ADDR_POINTER 0x40E
++
++unsigned __initdata ebda_addr;
++unsigned __initdata ebda_size;
++
++static void discover_ebda(void)
++{
++	/*
++	 * there is a real-mode segmented pointer pointing to the 
++	 * 4K EBDA area at 0x40E
++	 */
++	ebda_addr = *(unsigned short *)EBDA_ADDR_POINTER;
++	ebda_addr <<= 4;
++
++	ebda_size = *(unsigned short *)(unsigned long)ebda_addr;
++
++	/* Round EBDA up to pages */
++	if (ebda_size == 0)
++		ebda_size = 1;
++	ebda_size <<= 10;
++	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
++	if (ebda_size > 64*1024)
++		ebda_size = 64*1024;
++}
++#else
++#define discover_ebda() ((void)0)
++#endif
++
++void __init setup_arch(char **cmdline_p)
++{
++#ifdef CONFIG_XEN
++	/* Register a call for panic conditions. */
++	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++
++ 	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); 
++ 	screen_info = SCREEN_INFO;
++
++	if (is_initial_xendomain()) {
++		const struct dom0_vga_console_info *info =
++			(void *)((char *)xen_start_info +
++			         xen_start_info->console.dom0.info_off);
++
++		dom0_init_screen_info(info,
++		                      xen_start_info->console.dom0.info_size);
++		xen_start_info->console.domU.mfn = 0;
++		xen_start_info->console.domU.evtchn = 0;
++	} else
++		screen_info.orig_video_isVGA = 0;
++
++	copy_edid();
++
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_writable_pagetables));
++
++	ARCH_SETUP
++#else
++ 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
++ 	screen_info = SCREEN_INFO;
++	edid_info = EDID_INFO;
++#endif	/* !CONFIG_XEN */
++	saved_video_mode = SAVED_VIDEO_MODE;
++	bootloader_type = LOADER_TYPE;
++
++#ifdef CONFIG_BLK_DEV_RAM
++	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
++	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
++	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
++#endif
++	setup_memory_region();
++	copy_edd();
++
++	if (!MOUNT_ROOT_RDONLY)
++		root_mountflags &= ~MS_RDONLY;
++	init_mm.start_code = (unsigned long) &_text;
++	init_mm.end_code = (unsigned long) &_etext;
++	init_mm.end_data = (unsigned long) &_edata;
++	init_mm.brk = (unsigned long) &_end;
++
++	code_resource.start = virt_to_phys(&_text);
++	code_resource.end = virt_to_phys(&_etext)-1;
++	data_resource.start = virt_to_phys(&_etext);
++	data_resource.end = virt_to_phys(&_edata)-1;
++
++	parse_cmdline_early(cmdline_p);
++
++	early_identify_cpu(&boot_cpu_data);
++
++	/*
++	 * partially used pages are not usable - thus
++	 * we are rounding upwards:
++	 */
++	end_pfn = e820_end_of_ram();
++	num_physpages = end_pfn;		/* for pfn_valid */
++
++	check_efer();
++
++	discover_ebda();
++
++	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
++
++	if (is_initial_xendomain())
++		dmi_scan_machine();
++
++#ifdef CONFIG_ACPI_NUMA
++	/*
++	 * Parse SRAT to discover nodes.
++	 */
++	acpi_numa_init();
++#endif
++
++#ifdef CONFIG_NUMA
++	numa_initmem_init(0, end_pfn); 
++#else
++	contig_initmem_init(0, end_pfn);
++#endif
++
++#ifdef CONFIG_XEN
++	/*
++	 * Reserve kernel, physmap, start info, initial page tables, and
++	 * direct mapping.
++	 */
++	reserve_bootmem_generic(__pa_symbol(&_text),
++	                        (table_end << PAGE_SHIFT) - __pa_symbol(&_text));
++#else
++	/* Reserve direct mapping */
++	reserve_bootmem_generic(table_start << PAGE_SHIFT, 
++				(table_end - table_start) << PAGE_SHIFT);
++
++	/* reserve kernel */
++	reserve_bootmem_generic(__pa_symbol(&_text),
++				__pa_symbol(&_end) - __pa_symbol(&_text));
++
++	/*
++	 * reserve physical page 0 - it's a special BIOS page on many boxes,
++	 * enabling clean reboots, SMP operation, laptop functions.
++	 */
++	reserve_bootmem_generic(0, PAGE_SIZE);
++
++	/* reserve ebda region */
++	if (ebda_addr)
++		reserve_bootmem_generic(ebda_addr, ebda_size);
++
++#ifdef CONFIG_SMP
++	/*
++	 * But first pinch a few for the stack/trampoline stuff
++	 * FIXME: Don't need the extra page at 4K, but need to fix
++	 * trampoline before removing it. (see the GDT stuff)
++	 */
++	reserve_bootmem_generic(PAGE_SIZE, PAGE_SIZE);
++
++	/* Reserve SMP trampoline */
++	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, PAGE_SIZE);
++#endif
++#endif
++
++#ifdef CONFIG_ACPI_SLEEP
++       /*
++        * Reserve low memory region for sleep support.
++        */
++       acpi_reserve_bootmem();
++#endif
++#ifdef CONFIG_XEN
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (xen_start_info->mod_start) {
++		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
++			/*reserve_bootmem_generic(INITRD_START, INITRD_SIZE);*/
++			initrd_start = INITRD_START + PAGE_OFFSET;
++			initrd_end = initrd_start+INITRD_SIZE;
++			initrd_below_start_ok = 1;
++		} else {
++			printk(KERN_ERR "initrd extends beyond end of memory "
++				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++				(unsigned long)(INITRD_START + INITRD_SIZE),
++				(unsigned long)(end_pfn << PAGE_SHIFT));
++			initrd_start = 0;
++		}
++	}
++#endif
++#else	/* CONFIG_XEN */
++#ifdef CONFIG_BLK_DEV_INITRD
++	if (LOADER_TYPE && INITRD_START) {
++		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
++			reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
++			initrd_start =
++				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
++			initrd_end = initrd_start+INITRD_SIZE;
++		}
++		else {
++			printk(KERN_ERR "initrd extends beyond end of memory "
++			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++			    (unsigned long)(INITRD_START + INITRD_SIZE),
++			    (unsigned long)(end_pfn << PAGE_SHIFT));
++			initrd_start = 0;
++		}
++	}
++#endif
++#endif	/* !CONFIG_XEN */
++#ifdef CONFIG_KEXEC
++#ifdef CONFIG_XEN
++	xen_machine_kexec_setup_resources();
++#else
++	if (crashk_res.start != crashk_res.end) {
++		reserve_bootmem_generic(crashk_res.start,
++			crashk_res.end - crashk_res.start + 1);
++	}
++#endif
++#endif
++
++	paging_init();
++#ifdef CONFIG_X86_LOCAL_APIC
++	/*
++	 * Find and reserve possible boot-time SMP configuration:
++	 */
++	find_smp_config();
++#endif
++#ifdef CONFIG_XEN
++	{
++		int i, j, k, fpp;
++		unsigned long p2m_pages;
++
++		p2m_pages = end_pfn;
++		if (xen_start_info->nr_pages > end_pfn) {
++			/*
++			 * the end_pfn was shrunk (probably by mem= or highmem=
++			 * kernel parameter); shrink reservation with the HV
++			 */
++			struct xen_memory_reservation reservation = {
++				.address_bits = 0,
++				.extent_order = 0,
++				.domid = DOMID_SELF
++			};
++			unsigned int difference;
++			int ret;
++			
++			difference = xen_start_info->nr_pages - end_pfn;
++			
++			set_xen_guest_handle(reservation.extent_start,
++					     ((unsigned long *)xen_start_info->mfn_list) + end_pfn);
++			reservation.nr_extents = difference;
++			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++						   &reservation);
++			BUG_ON (ret != difference);
++		}
++		else if (end_pfn > xen_start_info->nr_pages)
++			p2m_pages = xen_start_info->nr_pages;
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* Make sure we have a large enough P->M table. */
++			phys_to_machine_mapping = alloc_bootmem_pages(
++				end_pfn * sizeof(unsigned long));
++			memset(phys_to_machine_mapping, ~0,
++			       end_pfn * sizeof(unsigned long));
++			memcpy(phys_to_machine_mapping,
++			       (unsigned long *)xen_start_info->mfn_list,
++			       p2m_pages * sizeof(unsigned long));
++			free_bootmem(
++				__pa(xen_start_info->mfn_list),
++				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
++						sizeof(unsigned long))));
++
++			/*
++			 * Initialise the list of the frames that specify the
++			 * list of frames that make up the p2m table. Used by
++                         * save/restore.
++			 */
++			pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE);
++
++			fpp = PAGE_SIZE/sizeof(unsigned long);
++			for (i=0, j=0, k=-1; i< end_pfn; i+=fpp, j++) {
++				if ((j % fpp) == 0) {
++					k++;
++					BUG_ON(k>=fpp);
++					pfn_to_mfn_frame_list[k] =
++						alloc_bootmem_pages(PAGE_SIZE);
++					pfn_to_mfn_frame_list_list[k] =
++						virt_to_mfn(pfn_to_mfn_frame_list[k]);
++					j=0;
++				}
++				pfn_to_mfn_frame_list[k][j] =
++					virt_to_mfn(&phys_to_machine_mapping[i]);
++			}
++			HYPERVISOR_shared_info->arch.max_pfn = end_pfn;
++			HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
++				virt_to_mfn(pfn_to_mfn_frame_list_list);
++		}
++
++		/* Mark all ISA DMA channels in-use - using them wouldn't work. */
++		for (i = 0; i < MAX_DMA_CHANNELS; ++i)
++			if (i != 4 && request_dma(i, "xen") != 0)
++				BUG();
++	}
++
++	if (!is_initial_xendomain()) {
++		acpi_disabled = 1;
++#ifdef  CONFIG_ACPI
++		acpi_ht = 0;
++#endif
++	}
++#endif
++
++#ifndef CONFIG_XEN
++	check_ioapic();
++#endif
++
++	zap_low_mappings(0);
++
++	/*
++	 * set this early, so we dont allocate cpu0
++	 * if MADT list doesnt list BSP first
++	 * mpparse.c/MP_processor_info() allocates logical cpu numbers.
++	 */
++	cpu_set(0, cpu_present_map);
++#ifdef CONFIG_ACPI
++	/*
++	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
++	 * Call this early for SRAT node setup.
++	 */
++	acpi_boot_table_init();
++
++	/*
++	 * Read APIC and some other early information from ACPI tables.
++	 */
++	acpi_boot_init();
++#endif
++
++	init_cpu_to_node();
++
++#ifdef CONFIG_X86_LOCAL_APIC
++	/*
++	 * get boot-time SMP configuration:
++	 */
++	if (smp_found_config)
++		get_smp_config();
++#ifndef CONFIG_XEN
++	init_apic_mappings();
++#endif
++#endif
++#if defined(CONFIG_XEN) && defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
++	prefill_possible_map();
++#endif
++
++	/*
++	 * Request address space for all standard RAM and ROM resources
++	 * and also for regions reported as reserved by the e820.
++	 */
++	probe_roms();
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain())
++		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
++#else
++	e820_reserve_resources(e820.map, e820.nr_map);
++#endif
++
++	request_resource(&iomem_resource, &video_ram_resource);
++
++	{
++	unsigned i;
++	/* request I/O space for devices used on all i[345]86 PCs */
++	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
++		request_resource(&ioport_resource, &standard_io_resources[i]);
++	}
++
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain())
++		e820_setup_gap(machine_e820.map, machine_e820.nr_map);
++#else
++	e820_setup_gap(e820.map, e820.nr_map);
++#endif
++
++#ifdef CONFIG_XEN
++	{
++		struct physdev_set_iopl set_iopl;
++
++		set_iopl.iopl = 1;
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++
++		if (is_initial_xendomain()) {
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++			conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++			conswitchp = &dummy_con;
++#endif
++#endif
++		} else {
++#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
++			conswitchp = &dummy_con;
++#endif
++                }
++	}
++#else	/* CONFIG_XEN */
++
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++	conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++	conswitchp = &dummy_con;
++#endif
++#endif
++
++#endif /* !CONFIG_XEN */
++}
++
++#ifdef CONFIG_XEN
++static int
++xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
++{
++	HYPERVISOR_shutdown(SHUTDOWN_crash);
++	/* we're never actually going to get here... */
++	return NOTIFY_DONE;
++}
++#endif /* !CONFIG_XEN */
++
++
++static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
++{
++	unsigned int *v;
++
++	if (c->extended_cpuid_level < 0x80000004)
++		return 0;
++
++	v = (unsigned int *) c->x86_model_id;
++	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
++	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
++	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
++	c->x86_model_id[48] = 0;
++	return 1;
++}
++
++
++static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
++{
++	unsigned int n, dummy, eax, ebx, ecx, edx;
++
++	n = c->extended_cpuid_level;
++
++	if (n >= 0x80000005) {
++		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
++		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
++			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
++		c->x86_cache_size=(ecx>>24)+(edx>>24);
++		/* On K8 L1 TLB is inclusive, so don't count it */
++		c->x86_tlbsize = 0;
++	}
++
++	if (n >= 0x80000006) {
++		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
++		ecx = cpuid_ecx(0x80000006);
++		c->x86_cache_size = ecx >> 16;
++		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
++
++		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
++		c->x86_cache_size, ecx & 0xFF);
++	}
++
++	if (n >= 0x80000007)
++		cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power); 
++	if (n >= 0x80000008) {
++		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); 
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
++	}
++}
++
++#ifdef CONFIG_NUMA
++static int nearby_node(int apicid)
++{
++	int i;
++	for (i = apicid - 1; i >= 0; i--) {
++		int node = apicid_to_node[i];
++		if (node != NUMA_NO_NODE && node_online(node))
++			return node;
++	}
++	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
++		int node = apicid_to_node[i];
++		if (node != NUMA_NO_NODE && node_online(node))
++			return node;
++	}
++	return first_node(node_online_map); /* Shouldn't happen */
++}
++#endif
++
++/*
++ * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
++ * Assumes number of cores is a power of two.
++ */
++static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_SMP
++	unsigned bits;
++#ifdef CONFIG_NUMA
++	int cpu = smp_processor_id();
++	int node = 0;
++	unsigned apicid = hard_smp_processor_id();
++#endif
++	unsigned ecx = cpuid_ecx(0x80000008);
++
++	c->x86_max_cores = (ecx & 0xff) + 1;
++
++	/* CPU telling us the core id bits shift? */
++	bits = (ecx >> 12) & 0xF;
++
++	/* Otherwise recompute */
++	if (bits == 0) {
++		while ((1 << bits) < c->x86_max_cores)
++			bits++;
++	}
++
++	/* Low order bits define the core id (index of core in socket) */
++	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
++	/* Convert the APIC ID into the socket ID */
++	c->phys_proc_id = phys_pkg_id(bits);
++
++#ifdef CONFIG_NUMA
++  	node = c->phys_proc_id;
++ 	if (apicid_to_node[apicid] != NUMA_NO_NODE)
++ 		node = apicid_to_node[apicid];
++ 	if (!node_online(node)) {
++ 		/* Two possibilities here:
++ 		   - The CPU is missing memory and no node was created.
++ 		   In that case try picking one from a nearby CPU
++ 		   - The APIC IDs differ from the HyperTransport node IDs
++ 		   which the K8 northbridge parsing fills in.
++ 		   Assume they are all increased by a constant offset,
++ 		   but in the same order as the HT nodeids.
++ 		   If that doesn't result in a usable node fall back to the
++ 		   path for the previous case.  */
++ 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
++ 		if (ht_nodeid >= 0 &&
++ 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
++ 			node = apicid_to_node[ht_nodeid];
++ 		/* Pick a nearby node */
++ 		if (!node_online(node))
++ 			node = nearby_node(apicid);
++ 	}
++	numa_set_node(cpu, node);
++
++	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
++#endif
++#endif
++}
++
++static void __init init_amd(struct cpuinfo_x86 *c)
++{
++	unsigned level;
++
++#ifdef CONFIG_SMP
++	unsigned long value;
++
++	/*
++	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
++	 * bit 6 of msr C001_0015
++ 	 *
++	 * Errata 63 for SH-B3 steppings
++	 * Errata 122 for all steppings (F+ have it disabled by default)
++	 */
++	if (c->x86 == 15) {
++		rdmsrl(MSR_K8_HWCR, value);
++		value |= 1 << 6;
++		wrmsrl(MSR_K8_HWCR, value);
++	}
++#endif
++
++	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
++	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
++	clear_bit(0*32+31, &c->x86_capability);
++	
++	/* On C+ stepping K8 rep microcode works well for copy/memset */
++	level = cpuid_eax(1);
++	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
++		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
++
++	/* Enable workaround for FXSAVE leak */
++	if (c->x86 >= 6)
++		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
++
++	level = get_model_name(c);
++	if (!level) {
++		switch (c->x86) { 
++		case 15:
++			/* Should distinguish Models here, but this is only
++			   a fallback anyways. */
++			strcpy(c->x86_model_id, "Hammer");
++			break; 
++		} 
++	} 
++	display_cacheinfo(c);
++
++	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
++	if (c->x86_power & (1<<8))
++		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++
++	/* Multi core CPU? */
++	if (c->extended_cpuid_level >= 0x80000008)
++		amd_detect_cmp(c);
++
++	/* Fix cpuid4 emulation for more */
++	num_cache_leaves = 3;
++}
++
++static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_SMP
++	u32 	eax, ebx, ecx, edx;
++	int 	index_msb, core_bits;
++
++	cpuid(1, &eax, &ebx, &ecx, &edx);
++
++
++	if (!cpu_has(c, X86_FEATURE_HT))
++		return;
++ 	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
++		goto out;
++
++	smp_num_siblings = (ebx & 0xff0000) >> 16;
++
++	if (smp_num_siblings == 1) {
++		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
++	} else if (smp_num_siblings > 1 ) {
++
++		if (smp_num_siblings > NR_CPUS) {
++			printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
++			smp_num_siblings = 1;
++			return;
++		}
++
++		index_msb = get_count_order(smp_num_siblings);
++		c->phys_proc_id = phys_pkg_id(index_msb);
++
++		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
++
++		index_msb = get_count_order(smp_num_siblings) ;
++
++		core_bits = get_count_order(c->x86_max_cores);
++
++		c->cpu_core_id = phys_pkg_id(index_msb) &
++					       ((1 << core_bits) - 1);
++	}
++out:
++	if ((c->x86_max_cores * smp_num_siblings) > 1) {
++		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n", c->phys_proc_id);
++		printk(KERN_INFO  "CPU: Processor Core ID: %d\n", c->cpu_core_id);
++	}
++
++#endif
++}
++
++/*
++ * find out the number of processor cores on the die
++ */
++static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
++{
++	unsigned int eax, t;
++
++	if (c->cpuid_level < 4)
++		return 1;
++
++	cpuid_count(4, 0, &eax, &t, &t, &t);
++
++	if (eax & 0x1f)
++		return ((eax >> 26) + 1);
++	else
++		return 1;
++}
++
++static void srat_detect_node(void)
++{
++#ifdef CONFIG_NUMA
++	unsigned node;
++	int cpu = smp_processor_id();
++	int apicid = hard_smp_processor_id();
++
++	/* Don't do the funky fallback heuristics the AMD version employs
++	   for now. */
++	node = apicid_to_node[apicid];
++	if (node == NUMA_NO_NODE)
++		node = first_node(node_online_map);
++	numa_set_node(cpu, node);
++
++	if (acpi_numa > 0)
++		printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
++#endif
++}
++
++static void __cpuinit init_intel(struct cpuinfo_x86 *c)
++{
++	/* Cache sizes */
++	unsigned n;
++
++	init_intel_cacheinfo(c);
++	if (c->cpuid_level > 9 ) {
++		unsigned eax = cpuid_eax(10);
++		/* Check for version and the number of counters */
++		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
++			set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
++	}
++
++	n = c->extended_cpuid_level;
++	if (n >= 0x80000008) {
++		unsigned eax = cpuid_eax(0x80000008);
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
++		/* CPUID workaround for Intel 0F34 CPU */
++		if (c->x86_vendor == X86_VENDOR_INTEL &&
++		    c->x86 == 0xF && c->x86_model == 0x3 &&
++		    c->x86_mask == 0x4)
++			c->x86_phys_bits = 36;
++	}
++
++	if (c->x86 == 15)
++		c->x86_cache_alignment = c->x86_clflush_size * 2;
++	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
++	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
++		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++	set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++ 	c->x86_max_cores = intel_num_cpu_cores(c);
++
++	srat_detect_node();
++}
++
++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
++{
++	char *v = c->x86_vendor_id;
++
++	if (!strcmp(v, "AuthenticAMD"))
++		c->x86_vendor = X86_VENDOR_AMD;
++	else if (!strcmp(v, "GenuineIntel"))
++		c->x86_vendor = X86_VENDOR_INTEL;
++	else
++		c->x86_vendor = X86_VENDOR_UNKNOWN;
++}
++
++struct cpu_model_info {
++	int vendor;
++	int family;
++	char *model_names[16];
++};
++
++/* Do some early cpuid on the boot CPU to get some parameter that are
++   needed before check_bugs. Everything advanced is in identify_cpu
++   below. */
++void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
++{
++	u32 tfms;
++
++	c->loops_per_jiffy = loops_per_jiffy;
++	c->x86_cache_size = -1;
++	c->x86_vendor = X86_VENDOR_UNKNOWN;
++	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
++	c->x86_vendor_id[0] = '\0'; /* Unset */
++	c->x86_model_id[0] = '\0';  /* Unset */
++	c->x86_clflush_size = 64;
++	c->x86_cache_alignment = c->x86_clflush_size;
++	c->x86_max_cores = 1;
++	c->extended_cpuid_level = 0;
++	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++
++	/* Get vendor name */
++	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
++	      (unsigned int *)&c->x86_vendor_id[0],
++	      (unsigned int *)&c->x86_vendor_id[8],
++	      (unsigned int *)&c->x86_vendor_id[4]);
++		
++	get_cpu_vendor(c);
++
++	/* Initialize the standard set of capabilities */
++	/* Note that the vendor-specific code below might override */
++
++	/* Intel-defined flags: level 0x00000001 */
++	if (c->cpuid_level >= 0x00000001) {
++		__u32 misc;
++		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
++		      &c->x86_capability[0]);
++		c->x86 = (tfms >> 8) & 0xf;
++		c->x86_model = (tfms >> 4) & 0xf;
++		c->x86_mask = tfms & 0xf;
++		if (c->x86 == 0xf)
++			c->x86 += (tfms >> 20) & 0xff;
++		if (c->x86 >= 0x6)
++			c->x86_model += ((tfms >> 16) & 0xF) << 4;
++		if (c->x86_capability[0] & (1<<19)) 
++			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
++	} else {
++		/* Have CPUID level 0 only - unheard of */
++		c->x86 = 4;
++	}
++
++#ifdef CONFIG_SMP
++	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
++#endif
++}
++
++/*
++ * This does the hard work of actually picking apart the CPU stuff...
++ */
++void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++{
++	int i;
++	u32 xlvl;
++
++	early_identify_cpu(c);
++
++	/* AMD-defined flags: level 0x80000001 */
++	xlvl = cpuid_eax(0x80000000);
++	c->extended_cpuid_level = xlvl;
++	if ((xlvl & 0xffff0000) == 0x80000000) {
++		if (xlvl >= 0x80000001) {
++			c->x86_capability[1] = cpuid_edx(0x80000001);
++			c->x86_capability[6] = cpuid_ecx(0x80000001);
++		}
++		if (xlvl >= 0x80000004)
++			get_model_name(c); /* Default name */
++	}
++
++	/* Transmeta-defined flags: level 0x80860001 */
++	xlvl = cpuid_eax(0x80860000);
++	if ((xlvl & 0xffff0000) == 0x80860000) {
++		/* Don't set x86_cpuid_level here for now to not confuse. */
++		if (xlvl >= 0x80860001)
++			c->x86_capability[2] = cpuid_edx(0x80860001);
++	}
++
++#ifndef CONFIG_XEN
++	c->apicid = phys_pkg_id(0);
++#endif
++
++	/*
++	 * Vendor-specific initialization.  In this section we
++	 * canonicalize the feature flags, meaning if there are
++	 * features a certain CPU supports which CPUID doesn't
++	 * tell us, CPUID claiming incorrect flags, or other bugs,
++	 * we handle them here.
++	 *
++	 * At the end of this section, c->x86_capability better
++	 * indicate the features this CPU genuinely supports!
++	 */
++	switch (c->x86_vendor) {
++	case X86_VENDOR_AMD:
++		init_amd(c);
++		break;
++
++	case X86_VENDOR_INTEL:
++		init_intel(c);
++		break;
++
++	case X86_VENDOR_UNKNOWN:
++	default:
++		display_cacheinfo(c);
++		break;
++	}
++
++	select_idle_routine(c);
++	detect_ht(c); 
++
++	/*
++	 * On SMP, boot_cpu_data holds the common feature set between
++	 * all CPUs; so make sure that we indicate which features are
++	 * common between the CPUs.  The first time this routine gets
++	 * executed, c == &boot_cpu_data.
++	 */
++	if (c != &boot_cpu_data) {
++		/* AND the already accumulated flags with these */
++		for (i = 0 ; i < NCAPINTS ; i++)
++			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
++	}
++
++#ifdef CONFIG_X86_MCE
++	mcheck_init(c);
++#endif
++	if (c == &boot_cpu_data)
++		mtrr_bp_init();
++	else
++		mtrr_ap_init();
++#ifdef CONFIG_NUMA
++	numa_add_cpu(smp_processor_id());
++#endif
++}
++ 
++
++void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
++{
++	if (c->x86_model_id[0])
++		printk("%s", c->x86_model_id);
++
++	if (c->x86_mask || c->cpuid_level >= 0) 
++		printk(" stepping %02x\n", c->x86_mask);
++	else
++		printk("\n");
++}
++
++/*
++ *	Get CPU information for use by the procfs.
++ */
++
++static int show_cpuinfo(struct seq_file *m, void *v)
++{
++	struct cpuinfo_x86 *c = v;
++
++	/* 
++	 * These flag bits must match the definitions in <asm/cpufeature.h>.
++	 * NULL means this bit is undefined or reserved; either way it doesn't
++	 * have meaning as far as Linux is concerned.  Note that it's important
++	 * to realize there is a difference between this table and CPUID -- if
++	 * applications want to get the raw CPUID data, they should access
++	 * /dev/cpu/<cpu_nr>/cpuid instead.
++	 */
++	static char *x86_cap_flags[] = {
++		/* Intel-defined */
++	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
++	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
++	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
++	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
++
++		/* AMD-defined */
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
++		NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
++
++		/* Transmeta-defined */
++		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++		/* Other (Linux-defined) */
++		"cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
++		"constant_tsc", NULL, NULL,
++		"up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++		/* Intel-defined (#2) */
++		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
++		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++		/* VIA/Cyrix/Centaur-defined */
++		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++		/* AMD-defined (#2) */
++		"lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++	};
++	static char *x86_power_flags[] = { 
++		"ts",	/* temperature sensor */
++		"fid",  /* frequency id control */
++		"vid",  /* voltage id control */
++		"ttp",  /* thermal trip */
++		"tm",
++		"stc",
++		NULL,
++		/* nothing */	/* constant_tsc - moved to flags */
++	};
++
++
++#ifdef CONFIG_SMP
++	if (!cpu_online(c-cpu_data))
++		return 0;
++#endif
++
++	seq_printf(m,"processor\t: %u\n"
++		     "vendor_id\t: %s\n"
++		     "cpu family\t: %d\n"
++		     "model\t\t: %d\n"
++		     "model name\t: %s\n",
++		     (unsigned)(c-cpu_data),
++		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
++		     c->x86,
++		     (int)c->x86_model,
++		     c->x86_model_id[0] ? c->x86_model_id : "unknown");
++	
++	if (c->x86_mask || c->cpuid_level >= 0)
++		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
++	else
++		seq_printf(m, "stepping\t: unknown\n");
++	
++	if (cpu_has(c,X86_FEATURE_TSC)) {
++		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
++		if (!freq)
++			freq = cpu_khz;
++		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
++			     freq / 1000, (freq % 1000));
++	}
++
++	/* Cache size */
++	if (c->x86_cache_size >= 0) 
++		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
++	
++#ifdef CONFIG_SMP
++	if (smp_num_siblings * c->x86_max_cores > 1) {
++		int cpu = c - cpu_data;
++		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
++		seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
++		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
++		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
++	}
++#endif	
++
++	seq_printf(m,
++	        "fpu\t\t: yes\n"
++	        "fpu_exception\t: yes\n"
++	        "cpuid level\t: %d\n"
++	        "wp\t\t: yes\n"
++	        "flags\t\t:",
++		   c->cpuid_level);
++
++	{ 
++		int i; 
++		for ( i = 0 ; i < 32*NCAPINTS ; i++ )
++			if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
++				seq_printf(m, " %s", x86_cap_flags[i]);
++	}
++		
++	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
++		   c->loops_per_jiffy/(500000/HZ),
++		   (c->loops_per_jiffy/(5000/HZ)) % 100);
++
++	if (c->x86_tlbsize > 0) 
++		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
++	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
++	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
++
++	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 
++		   c->x86_phys_bits, c->x86_virt_bits);
++
++	seq_printf(m, "power management:");
++	{
++		unsigned i;
++		for (i = 0; i < 32; i++) 
++			if (c->x86_power & (1 << i)) {
++				if (i < ARRAY_SIZE(x86_power_flags) &&
++					x86_power_flags[i])
++					seq_printf(m, "%s%s",
++						x86_power_flags[i][0]?" ":"",
++						x86_power_flags[i]);
++				else
++					seq_printf(m, " [%d]", i);
++			}
++	}
++
++	seq_printf(m, "\n\n");
++
++	return 0;
++}
++
++static void *c_start(struct seq_file *m, loff_t *pos)
++{
++	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
++}
++
++static void *c_next(struct seq_file *m, void *v, loff_t *pos)
++{
++	++*pos;
++	return c_start(m, pos);
++}
++
++static void c_stop(struct seq_file *m, void *v)
++{
++}
++
++struct seq_operations cpuinfo_op = {
++	.start =c_start,
++	.next =	c_next,
++	.stop =	c_stop,
++	.show =	show_cpuinfo,
++};
++
++#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
++#include <linux/platform_device.h>
++static __init int add_pcspkr(void)
++{
++	struct platform_device *pd;
++	int ret;
++
++	if (!is_initial_xendomain())
++		return 0;
++
++	pd = platform_device_alloc("pcspkr", -1);
++	if (!pd)
++		return -ENOMEM;
++
++	ret = platform_device_add(pd);
++	if (ret)
++		platform_device_put(pd);
++
++	return ret;
++}
++device_initcall(add_pcspkr);
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2008-01-28 12:24:19.000000000 +0100
+@@ -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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,575 @@
++/*
++ *	Intel SMP support routines.
++ *
++ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
++ *      (c) 2002,2003 Andi Kleen, SuSE Labs.
++ *
++ *	This code is released under the GNU General Public License version 2 or
++ *	later.
++ */
++
++#include <linux/init.h>
++
++#include <linux/mm.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/smp_lock.h>
++#include <linux/smp.h>
++#include <linux/kernel_stat.h>
++#include <linux/mc146818rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/mtrr.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++#include <asm/mach_apic.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <asm/apicdef.h>
++#include <asm/idle.h>
++#ifdef CONFIG_XEN
++#include <xen/evtchn.h>
++#endif
++
++#ifndef CONFIG_XEN
++/*
++ *	Smarter SMP flushing macros. 
++ *		c/o Linus Torvalds.
++ *
++ *	These mean you can really definitely utterly forget about
++ *	writing to user space from interrupts. (Its not allowed anyway).
++ *
++ *	Optimizations Manfred Spraul <manfred@colorfullife.com>
++ *
++ * 	More scalable flush, from Andi Kleen
++ *
++ * 	To avoid global state use 8 different call vectors.
++ * 	Each CPU uses a specific vector to trigger flushes on other
++ * 	CPUs. Depending on the received vector the target CPUs look into
++ *	the right per cpu variable for the flush data.
++ *
++ * 	With more than 8 CPUs they are hashed to the 8 available
++ * 	vectors. The limited global vector space forces us to this right now.
++ *	In future when interrupts are split into per CPU domains this could be
++ *	fixed, at the cost of triggering multiple IPIs in some cases.
++ */
++
++union smp_flush_state {
++	struct {
++		cpumask_t flush_cpumask;
++		struct mm_struct *flush_mm;
++		unsigned long flush_va;
++#define FLUSH_ALL	-1ULL
++		spinlock_t tlbstate_lock;
++	};
++	char pad[SMP_CACHE_BYTES];
++} ____cacheline_aligned;
++
++/* State is put into the per CPU data section, but padded
++   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);
++
++/*
++ * We cannot call mmdrop() because we are in interrupt context, 
++ * instead update mm->cpu_vm_mask.
++ */
++static inline void leave_mm(unsigned long cpu)
++{
++	if (read_pda(mmu_state) == TLBSTATE_OK)
++		BUG();
++	cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
++	load_cr3(swapper_pg_dir);
++}
++
++/*
++ *
++ * The flush IPI assumes that a thread switch happens in this order:
++ * [cpu0: the cpu that switches]
++ * 1) switch_mm() either 1a) or 1b)
++ * 1a) thread switch to a different mm
++ * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
++ * 	Stop ipi delivery for the old mm. This is not synchronized with
++ * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ * 	for the wrong mm, and in the worst case we perform a superfluous
++ * 	tlb flush.
++ * 1a2) set cpu mmu_state to TLBSTATE_OK
++ * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ *	was in lazy tlb mode.
++ * 1a3) update cpu active_mm
++ * 	Now cpu0 accepts tlb flushes for the new mm.
++ * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
++ * 	Now the other cpus will send tlb flush ipis.
++ * 1a4) change cr3.
++ * 1b) thread switch without mm change
++ *	cpu active_mm is correct, cpu0 already handles
++ *	flush ipis.
++ * 1b1) set cpu mmu_state to TLBSTATE_OK
++ * 1b2) test_and_set the cpu bit in cpu_vm_mask.
++ * 	Atomically set the bit [other cpus will start sending flush ipis],
++ * 	and test the bit.
++ * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
++ * 2) switch %%esp, ie current
++ *
++ * The interrupt must handle 2 special cases:
++ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
++ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
++ *   runs in kernel space, the cpu could load tlb entries for user space
++ *   pages.
++ *
++ * The good news is that cpu mmu_state is local to each cpu, no
++ * write/read ordering problems.
++ */
++
++/*
++ * TLB flush IPI:
++ *
++ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
++ * 2) Leave the mm if we are in the lazy tlb mode.
++ *
++ * Interrupts are disabled.
++ */
++
++asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
++{
++	int cpu;
++	int sender;
++	union smp_flush_state *f;
++
++	cpu = smp_processor_id();
++	/*
++	 * orig_rax contains the negated interrupt vector.
++	 * Use that to determine where the sender put the data.
++	 */
++	sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
++	f = &per_cpu(flush_state, sender);
++
++	if (!cpu_isset(cpu, f->flush_cpumask))
++		goto out;
++		/* 
++		 * This was a BUG() but until someone can quote me the
++		 * line from the intel manual that guarantees an IPI to
++		 * multiple CPUs is retried _only_ on the erroring CPUs
++		 * its staying as a return
++		 *
++		 * BUG();
++		 */
++		 
++	if (f->flush_mm == read_pda(active_mm)) {
++		if (read_pda(mmu_state) == TLBSTATE_OK) {
++			if (f->flush_va == FLUSH_ALL)
++				local_flush_tlb();
++			else
++				__flush_tlb_one(f->flush_va);
++		} else
++			leave_mm(cpu);
++	}
++out:
++	ack_APIC_irq();
++	cpu_clear(cpu, f->flush_cpumask);
++}
++
++static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
++						unsigned long va)
++{
++	int sender;
++	union smp_flush_state *f;
++
++	/* Caller has disabled preemption */
++	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
++	f = &per_cpu(flush_state, sender);
++
++	/* Could avoid this lock when
++	   num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
++	   probably not worth checking this for a cache-hot lock. */
++	spin_lock(&f->tlbstate_lock);
++
++	f->flush_mm = mm;
++	f->flush_va = va;
++	cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
++
++	/*
++	 * We have to send the IPI only to
++	 * CPUs affected.
++	 */
++	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
++
++	while (!cpus_empty(f->flush_cpumask))
++		cpu_relax();
++
++	f->flush_mm = NULL;
++	f->flush_va = 0;
++	spin_unlock(&f->tlbstate_lock);
++}
++
++int __cpuinit init_smp_flush(void)
++{
++	int i;
++	for_each_cpu_mask(i, cpu_possible_map) {
++		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
++	}
++	return 0;
++}
++
++core_initcall(init_smp_flush);
++	
++void flush_tlb_current_task(void)
++{
++	struct mm_struct *mm = current->mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	local_flush_tlb();
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++	preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_current_task);
++
++void flush_tlb_mm (struct mm_struct * mm)
++{
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if (current->mm)
++			local_flush_tlb();
++		else
++			leave_mm(smp_processor_id());
++	}
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++
++	preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_mm);
++
++void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
++{
++	struct mm_struct *mm = vma->vm_mm;
++	cpumask_t cpu_mask;
++
++	preempt_disable();
++	cpu_mask = mm->cpu_vm_mask;
++	cpu_clear(smp_processor_id(), cpu_mask);
++
++	if (current->active_mm == mm) {
++		if(current->mm)
++			__flush_tlb_one(va);
++		 else
++		 	leave_mm(smp_processor_id());
++	}
++
++	if (!cpus_empty(cpu_mask))
++		flush_tlb_others(cpu_mask, mm, va);
++
++	preempt_enable();
++}
++EXPORT_SYMBOL(flush_tlb_page);
++
++static void do_flush_tlb_all(void* info)
++{
++	unsigned long cpu = smp_processor_id();
++
++	__flush_tlb_all();
++	if (read_pda(mmu_state) == TLBSTATE_LAZY)
++		leave_mm(cpu);
++}
++
++void flush_tlb_all(void)
++{
++	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
++}
++#endif /* Xen */
++
++/*
++ * this function sends a 'reschedule' IPI to another CPU.
++ * it goes straight through and wastes no time serializing
++ * anything. Worst case is that we lose a reschedule ...
++ */
++
++void smp_send_reschedule(int cpu)
++{
++	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++}
++
++/*
++ * Structure and data for smp_call_function(). This is designed to minimise
++ * static memory requirements. It also looks cleaner.
++ */
++static DEFINE_SPINLOCK(call_lock);
++
++struct call_data_struct {
++	void (*func) (void *info);
++	void *info;
++	atomic_t started;
++	atomic_t finished;
++	int wait;
++};
++
++static struct call_data_struct * call_data;
++
++void lock_ipi_call_lock(void)
++{
++	spin_lock_irq(&call_lock);
++}
++
++void unlock_ipi_call_lock(void)
++{
++	spin_unlock_irq(&call_lock);
++}
++
++/*
++ * this function sends a 'generic call function' IPI to one other CPU
++ * in the system.
++ *
++ * cpu is a standard Linux logical CPU number.
++ */
++static void
++__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = 1;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	wmb();
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (!wait)
++		return;
++
++	while (atomic_read(&data.finished) != cpus)
++		cpu_relax();
++}
++
++/*
++ * smp_call_function_single - Run a function on another CPU
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Currently unused.
++ * @wait: If true, wait until function has completed on other CPUs.
++ *
++ * Retrurns 0 on success, else a negative status code.
++ *
++ * Does not return until the remote CPU is nearly ready to execute <func>
++ * or is or has executed.
++ */
++
++int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
++	int nonatomic, int wait)
++{
++	/* prevent preemption and reschedule on another processor */
++	int me = get_cpu();
++	if (cpu == me) {
++		WARN_ON(1);
++		put_cpu();
++		return -EBUSY;
++	}
++	spin_lock_bh(&call_lock);
++	__smp_call_function_single(cpu, func, info, nonatomic, wait);
++	spin_unlock_bh(&call_lock);
++	put_cpu();
++	return 0;
++}
++
++/*
++ * this function sends a 'generic call function' IPI to all other CPUs
++ * in the system.
++ */
++static void __smp_call_function (void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = num_online_cpus()-1;
++
++	if (!cpus)
++		return;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	wmb();
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (!wait)
++		return;
++
++	while (atomic_read(&data.finished) != cpus)
++		cpu_relax();
++}
++
++/*
++ * smp_call_function - run a function on all other CPUs.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: currently unused.
++ * @wait: If true, wait (atomically) until function has completed on other
++ *        CPUs.
++ *
++ * Returns 0 on success, else a negative status code. Does not return until
++ * remote CPUs are nearly ready to execute func or are or have executed.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ * Actually there are a few legal cases, like panic.
++ */
++int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
++			int wait)
++{
++	spin_lock(&call_lock);
++	__smp_call_function(func,info,nonatomic,wait);
++	spin_unlock(&call_lock);
++	return 0;
++}
++EXPORT_SYMBOL(smp_call_function);
++
++void smp_stop_cpu(void)
++{
++	unsigned long flags;
++	/*
++	 * Remove this CPU:
++	 */
++	cpu_clear(smp_processor_id(), cpu_online_map);
++	local_irq_save(flags);
++	disable_all_local_evtchn();
++	local_irq_restore(flags); 
++}
++
++static void smp_really_stop_cpu(void *dummy)
++{
++	smp_stop_cpu(); 
++	for (;;) 
++		halt();
++} 
++
++void smp_send_stop(void)
++{
++	int nolock = 0;
++#ifndef CONFIG_XEN
++	if (reboot_force)
++		return;
++#endif
++	/* Don't deadlock on the call lock in panic */
++	if (!spin_trylock(&call_lock)) {
++		/* ignore locking because we have panicked anyways */
++		nolock = 1;
++	}
++	__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
++	if (!nolock)
++		spin_unlock(&call_lock);
++
++	local_irq_disable();
++	disable_all_local_evtchn();
++	local_irq_enable();
++}
++
++/*
++ * Reschedule call back. Nothing to do,
++ * all the work is done automatically when
++ * we return from the interrupt.
++ */
++#ifndef CONFIG_XEN
++asmlinkage void smp_reschedule_interrupt(void)
++#else
++asmlinkage irqreturn_t smp_reschedule_interrupt(void)
++#endif
++{
++#ifndef CONFIG_XEN
++	ack_APIC_irq();
++#else
++	return IRQ_HANDLED;
++#endif
++}
++
++#ifndef CONFIG_XEN
++asmlinkage void smp_call_function_interrupt(void)
++#else
++asmlinkage irqreturn_t smp_call_function_interrupt(void)
++#endif
++{
++	void (*func) (void *info) = call_data->func;
++	void *info = call_data->info;
++	int wait = call_data->wait;
++
++#ifndef CONFIG_XEN
++	ack_APIC_irq();
++#endif
++	/*
++	 * Notify initiating CPU that I've grabbed the data and am
++	 * about to execute the function
++	 */
++	mb();
++	atomic_inc(&call_data->started);
++	/*
++	 * At this point the info structure may be out of scope unless wait==1
++	 */
++	exit_idle();
++	irq_enter();
++	(*func)(info);
++	irq_exit();
++	if (wait) {
++		mb();
++		atomic_inc(&call_data->finished);
++	}
++#ifdef CONFIG_XEN
++	return IRQ_HANDLED;
++#endif
++}
++
++int safe_smp_processor_id(void)
++{
++#ifdef CONFIG_XEN
++	return smp_processor_id();
++#else
++	unsigned apicid, i;
++
++	if (disable_apic)
++		return 0;
++
++	apicid = hard_smp_processor_id();
++	if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid)
++		return apicid;
++
++	for (i = 0; i < NR_CPUS; ++i) {
++		if (x86_cpu_to_apicid[i] == apicid)
++			return i;
++	}
++
++	/* No entries in x86_cpu_to_apicid?  Either no MPS|ACPI,
++	 * or called too early.  Either way, we must be CPU 0. */
++      	if (x86_cpu_to_apicid[0] == BAD_APICID)
++		return 0;
++
++	return 0; /* Should not happen */
++#endif
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,1173 @@
++/*
++ *  linux/arch/x86-64/traps.c
++ *
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
++ *
++ *  Pentium III FXSR, SSE support
++ *	Gareth Hughes <gareth@valinux.com>, May 2000
++ */
++
++/*
++ * 'Traps.c' handles hardware traps and faults after we have saved some
++ * state in 'entry.S'.
++ */
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/ptrace.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/nmi.h>
++#include <linux/kprobes.h>
++#include <linux/kexec.h>
++#include <linux/unwind.h>
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/atomic.h>
++#include <asm/debugreg.h>
++#include <asm/desc.h>
++#include <asm/i387.h>
++#include <asm/kdebug.h>
++#include <asm/processor.h>
++#include <asm/unwind.h>
++#include <asm/smp.h>
++#include <asm/pgalloc.h>
++#include <asm/pda.h>
++#include <asm/proto.h>
++#include <asm/nmi.h>
++
++asmlinkage void divide_error(void);
++asmlinkage void debug(void);
++asmlinkage void nmi(void);
++asmlinkage void int3(void);
++asmlinkage void overflow(void);
++asmlinkage void bounds(void);
++asmlinkage void invalid_op(void);
++asmlinkage void device_not_available(void);
++asmlinkage void double_fault(void);
++asmlinkage void coprocessor_segment_overrun(void);
++asmlinkage void invalid_TSS(void);
++asmlinkage void segment_not_present(void);
++asmlinkage void stack_segment(void);
++asmlinkage void general_protection(void);
++asmlinkage void page_fault(void);
++asmlinkage void coprocessor_error(void);
++asmlinkage void simd_coprocessor_error(void);
++asmlinkage void reserved(void);
++asmlinkage void alignment_check(void);
++asmlinkage void machine_check(void);
++asmlinkage void spurious_interrupt_bug(void);
++
++ATOMIC_NOTIFIER_HEAD(die_chain);
++EXPORT_SYMBOL(die_chain);
++
++int register_die_notifier(struct notifier_block *nb)
++{
++	vmalloc_sync_all();
++	return atomic_notifier_chain_register(&die_chain, nb);
++}
++EXPORT_SYMBOL(register_die_notifier); /* used modular by kdb */
++
++int unregister_die_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&die_chain, nb);
++}
++EXPORT_SYMBOL(unregister_die_notifier); /* used modular by kdb */
++
++static inline void conditional_sti(struct pt_regs *regs)
++{
++	if (regs->eflags & X86_EFLAGS_IF)
++		local_irq_enable();
++}
++
++static inline void preempt_conditional_sti(struct pt_regs *regs)
++{
++	preempt_disable();
++	if (regs->eflags & X86_EFLAGS_IF)
++		local_irq_enable();
++}
++
++static inline void preempt_conditional_cli(struct pt_regs *regs)
++{
++	if (regs->eflags & X86_EFLAGS_IF)
++		local_irq_disable();
++	/* Make sure to not schedule here because we could be running
++	   on an exception stack. */
++	preempt_enable_no_resched();
++}
++
++static int kstack_depth_to_print = 12;
++#ifdef CONFIG_STACK_UNWIND
++static int call_trace = 1;
++#else
++#define call_trace (-1)
++#endif
++
++#ifdef CONFIG_KALLSYMS
++# include <linux/kallsyms.h>
++void printk_address(unsigned long address)
++{
++	unsigned long offset = 0, symsize;
++	const char *symname;
++	char *modname;
++	char *delim = ":";
++	char namebuf[128];
++
++	symname = kallsyms_lookup(address, &symsize, &offset,
++					&modname, namebuf);
++	if (!symname) {
++		printk(" [<%016lx>]\n", address);
++		return;
++	}
++	if (!modname)
++		modname = delim = ""; 		
++	printk(" [<%016lx>] %s%s%s%s+0x%lx/0x%lx\n",
++		address, delim, modname, delim, symname, offset, symsize);
++}
++#else
++void printk_address(unsigned long address)
++{
++	printk(" [<%016lx>]\n", address);
++}
++#endif
++
++static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
++					unsigned *usedp, const char **idp)
++{
++#ifndef CONFIG_X86_NO_TSS
++	static char ids[][8] = {
++		[DEBUG_STACK - 1] = "#DB",
++		[NMI_STACK - 1] = "NMI",
++		[DOUBLEFAULT_STACK - 1] = "#DF",
++		[STACKFAULT_STACK - 1] = "#SS",
++		[MCE_STACK - 1] = "#MC",
++#if DEBUG_STKSZ > EXCEPTION_STKSZ
++		[N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
++#endif
++	};
++	unsigned k;
++
++	/*
++	 * Iterate over all exception stacks, and figure out whether
++	 * 'stack' is in one of them:
++	 */
++	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
++		unsigned long end;
++
++		/*
++		 * set 'end' to the end of the exception stack.
++		 */
++		switch (k + 1) {
++		/*
++		 * TODO: this block is not needed i think, because
++		 * setup64.c:cpu_init() sets up t->ist[DEBUG_STACK]
++		 * properly too.
++		 */
++#if DEBUG_STKSZ > EXCEPTION_STKSZ
++		case DEBUG_STACK:
++			end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
++			break;
++#endif
++		default:
++			end = per_cpu(orig_ist, cpu).ist[k];
++			break;
++		}
++		/*
++		 * Is 'stack' above this exception frame's end?
++		 * If yes then skip to the next frame.
++		 */
++		if (stack >= end)
++			continue;
++		/*
++		 * Is 'stack' above this exception frame's start address?
++		 * If yes then we found the right frame.
++		 */
++		if (stack >= end - EXCEPTION_STKSZ) {
++			/*
++			 * Make sure we only iterate through an exception
++			 * stack once. If it comes up for the second time
++			 * then there's something wrong going on - just
++			 * break out and return NULL:
++			 */
++			if (*usedp & (1U << k))
++				break;
++			*usedp |= 1U << k;
++			*idp = ids[k];
++			return (unsigned long *)end;
++		}
++		/*
++		 * If this is a debug stack, and if it has a larger size than
++		 * the usual exception stacks, then 'stack' might still
++		 * be within the lower portion of the debug stack:
++		 */
++#if DEBUG_STKSZ > EXCEPTION_STKSZ
++		if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
++			unsigned j = N_EXCEPTION_STACKS - 1;
++
++			/*
++			 * Black magic. A large debug stack is composed of
++			 * multiple exception stack entries, which we
++			 * iterate through now. Dont look:
++			 */
++			do {
++				++j;
++				end -= EXCEPTION_STKSZ;
++				ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
++			} while (stack < end - EXCEPTION_STKSZ);
++			if (*usedp & (1U << j))
++				break;
++			*usedp |= 1U << j;
++			*idp = ids[j];
++			return (unsigned long *)end;
++		}
++#endif
++	}
++#endif
++	return NULL;
++}
++
++static int show_trace_unwind(struct unwind_frame_info *info, void *context)
++{
++	int n = 0;
++
++	while (unwind(info) == 0 && UNW_PC(info)) {
++		n++;
++		printk_address(UNW_PC(info));
++		if (arch_unw_user_mode(info))
++			break;
++	}
++	return n;
++}
++
++/*
++ * x86-64 can have upto three kernel stacks: 
++ * process stack
++ * interrupt stack
++ * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
++ */
++
++void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
++{
++	const unsigned cpu = safe_smp_processor_id();
++	unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
++	unsigned used = 0;
++
++	printk("\nCall Trace:\n");
++
++	if (!tsk)
++		tsk = current;
++
++	if (call_trace >= 0) {
++		int unw_ret = 0;
++		struct unwind_frame_info info;
++
++		if (regs) {
++			if (unwind_init_frame_info(&info, tsk, regs) == 0)
++				unw_ret = show_trace_unwind(&info, NULL);
++		} else if (tsk == current)
++			unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
++		else {
++			if (unwind_init_blocked(&info, tsk) == 0)
++				unw_ret = show_trace_unwind(&info, NULL);
++		}
++		if (unw_ret > 0) {
++			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
++				print_symbol("DWARF2 unwinder stuck at %s\n",
++					     UNW_PC(&info));
++				if ((long)UNW_SP(&info) < 0) {
++					printk("Leftover inexact backtrace:\n");
++					stack = (unsigned long *)UNW_SP(&info);
++				} else
++					printk("Full inexact backtrace again:\n");
++			} else if (call_trace >= 1)
++				return;
++			else
++				printk("Full inexact backtrace again:\n");
++		} else
++			printk("Inexact backtrace:\n");
++	}
++
++	/*
++	 * Print function call entries within a stack. 'cond' is the
++	 * "end of stackframe" condition, that the 'stack++'
++	 * iteration will eventually trigger.
++	 */
++#define HANDLE_STACK(cond) \
++	do while (cond) { \
++		unsigned long addr = *stack++; \
++		if (kernel_text_address(addr)) { \
++			/* \
++			 * If the address is either in the text segment of the \
++			 * kernel, or in the region which contains vmalloc'ed \
++			 * memory, it *may* be the address of a calling \
++			 * routine; if so, print it so that someone tracing \
++			 * down the cause of the crash will be able to figure \
++			 * out the call path that was taken. \
++			 */ \
++			printk_address(addr); \
++		} \
++	} while (0)
++
++	/*
++	 * Print function call entries in all stacks, starting at the
++	 * current stack address. If the stacks consist of nested
++	 * exceptions
++	 */
++	for ( ; ; ) {
++		const char *id;
++		unsigned long *estack_end;
++		estack_end = in_exception_stack(cpu, (unsigned long)stack,
++						&used, &id);
++
++		if (estack_end) {
++			printk(" <%s>", id);
++			HANDLE_STACK (stack < estack_end);
++			printk(" <EOE>");
++			/*
++			 * We link to the next stack via the
++			 * second-to-last pointer (index -2 to end) in the
++			 * exception stack:
++			 */
++			stack = (unsigned long *) estack_end[-2];
++			continue;
++		}
++		if (irqstack_end) {
++			unsigned long *irqstack;
++			irqstack = irqstack_end -
++				(IRQSTACKSIZE - 64) / sizeof(*irqstack);
++
++			if (stack >= irqstack && stack < irqstack_end) {
++				printk(" <IRQ>");
++				HANDLE_STACK (stack < irqstack_end);
++				/*
++				 * We link to the next stack (which would be
++				 * the process stack normally) the last
++				 * pointer (index -1 to end) in the IRQ stack:
++				 */
++				stack = (unsigned long *) (irqstack_end[-1]);
++				irqstack_end = NULL;
++				printk(" <EOI>");
++				continue;
++			}
++		}
++		break;
++	}
++
++	/*
++	 * This prints the process stack:
++	 */
++	HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
++#undef HANDLE_STACK
++
++	printk("\n");
++}
++
++static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
++{
++	unsigned long *stack;
++	int i;
++	const int cpu = safe_smp_processor_id();
++	unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
++	unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
++
++	// debugging aid: "show_stack(NULL, NULL);" prints the
++	// back trace for this cpu.
++
++	if (rsp == NULL) {
++		if (tsk)
++			rsp = (unsigned long *)tsk->thread.rsp;
++		else
++			rsp = (unsigned long *)&rsp;
++	}
++
++	stack = rsp;
++	for(i=0; i < kstack_depth_to_print; i++) {
++		if (stack >= irqstack && stack <= irqstack_end) {
++			if (stack == irqstack_end) {
++				stack = (unsigned long *) (irqstack_end[-1]);
++				printk(" <EOI> ");
++			}
++		} else {
++		if (((long) stack & (THREAD_SIZE-1)) == 0)
++			break;
++		}
++		if (i && ((i % 4) == 0))
++			printk("\n");
++		printk(" %016lx", *stack++);
++		touch_nmi_watchdog();
++	}
++	show_trace(tsk, regs, rsp);
++}
++
++void show_stack(struct task_struct *tsk, unsigned long * rsp)
++{
++	_show_stack(tsk, NULL, rsp);
++}
++
++/*
++ * The architecture-independent dump_stack generator
++ */
++void dump_stack(void)
++{
++	unsigned long dummy;
++	show_trace(NULL, NULL, &dummy);
++}
++
++EXPORT_SYMBOL(dump_stack);
++
++void show_registers(struct pt_regs *regs)
++{
++	int i;
++	int in_kernel = !user_mode(regs);
++	unsigned long rsp;
++	const int cpu = safe_smp_processor_id(); 
++	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
++
++		rsp = regs->rsp;
++
++	printk("CPU %d ", cpu);
++	__show_regs(regs);
++	printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
++		cur->comm, cur->pid, task_thread_info(cur), cur);
++
++	/*
++	 * When in-kernel, we also print out the stack and code at the
++	 * time of the fault..
++	 */
++	if (in_kernel) {
++
++		printk("Stack: ");
++		_show_stack(NULL, regs, (unsigned long*)rsp);
++
++		printk("\nCode: ");
++		if (regs->rip < PAGE_OFFSET)
++			goto bad;
++
++		for (i=0; i<20; i++) {
++			unsigned char c;
++			if (__get_user(c, &((unsigned char*)regs->rip)[i])) {
++bad:
++				printk(" Bad RIP value.");
++				break;
++			}
++			printk("%02x ", c);
++		}
++	}
++	printk("\n");
++}	
++
++void handle_BUG(struct pt_regs *regs)
++{ 
++	struct bug_frame f;
++	long len;
++	const char *prefix = "";
++
++	if (user_mode(regs))
++		return; 
++	if (__copy_from_user(&f, (const void __user *) regs->rip,
++			     sizeof(struct bug_frame)))
++		return; 
++	if (f.filename >= 0 ||
++	    f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
++		return;
++	len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
++	if (len < 0 || len >= PATH_MAX)
++		f.filename = (int)(long)"unmapped filename";
++	else if (len > 50) {
++		f.filename += len - 50;
++		prefix = "...";
++	}
++	printk("----------- [cut here ] --------- [please bite here ] ---------\n");
++	printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
++} 
++
++#ifdef CONFIG_BUG
++void out_of_line_bug(void)
++{ 
++	BUG(); 
++} 
++EXPORT_SYMBOL(out_of_line_bug);
++#endif
++
++static DEFINE_SPINLOCK(die_lock);
++static int die_owner = -1;
++static unsigned int die_nest_count;
++
++unsigned __kprobes long oops_begin(void)
++{
++	int cpu = safe_smp_processor_id();
++	unsigned long flags;
++
++	/* racy, but better than risking deadlock. */
++	local_irq_save(flags);
++	if (!spin_trylock(&die_lock)) { 
++		if (cpu == die_owner) 
++			/* nested oops. should stop eventually */;
++		else
++			spin_lock(&die_lock);
++	}
++	die_nest_count++;
++	die_owner = cpu;
++	console_verbose();
++	bust_spinlocks(1);
++	return flags;
++}
++
++void __kprobes oops_end(unsigned long flags)
++{ 
++	die_owner = -1;
++	bust_spinlocks(0);
++	die_nest_count--;
++	if (die_nest_count)
++		/* We still own the lock */
++		local_irq_restore(flags);
++	else
++		/* Nest count reaches zero, release the lock. */
++		spin_unlock_irqrestore(&die_lock, flags);
++	if (panic_on_oops)
++		panic("Fatal exception");
++}
++
++void __kprobes __die(const char * str, struct pt_regs * regs, long err)
++{
++	static int die_counter;
++	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
++#ifdef CONFIG_PREEMPT
++	printk("PREEMPT ");
++#endif
++#ifdef CONFIG_SMP
++	printk("SMP ");
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	printk("DEBUG_PAGEALLOC");
++#endif
++	printk("\n");
++	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
++	show_registers(regs);
++	/* Executive summary in case the oops scrolled away */
++	printk(KERN_ALERT "RIP ");
++	printk_address(regs->rip); 
++	printk(" RSP <%016lx>\n", regs->rsp); 
++	if (kexec_should_crash(current))
++		crash_kexec(regs);
++}
++
++void die(const char * str, struct pt_regs * regs, long err)
++{
++	unsigned long flags = oops_begin();
++
++	handle_BUG(regs);
++	__die(str, regs, err);
++	oops_end(flags);
++	do_exit(SIGSEGV); 
++}
++
++#ifdef CONFIG_X86_LOCAL_APIC
++void __kprobes die_nmi(char *str, struct pt_regs *regs)
++{
++	unsigned long flags = oops_begin();
++
++	/*
++	 * We are in trouble anyway, lets at least try
++	 * to get a message out.
++	 */
++	printk(str, safe_smp_processor_id());
++	show_registers(regs);
++	if (kexec_should_crash(current))
++		crash_kexec(regs);
++	if (panic_on_timeout || panic_on_oops)
++		panic("nmi watchdog");
++	printk("console shuts up ...\n");
++	oops_end(flags);
++	nmi_exit();
++	local_irq_enable();
++	do_exit(SIGSEGV);
++}
++#endif
++
++static void __kprobes do_trap(int trapnr, int signr, char *str,
++			      struct pt_regs * regs, long error_code,
++			      siginfo_t *info)
++{
++	struct task_struct *tsk = current;
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
++
++	if (user_mode(regs)) {
++		if (exception_trace && unhandled_signal(tsk, signr))
++			printk(KERN_INFO
++			       "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
++			       tsk->comm, tsk->pid, str,
++			       regs->rip, regs->rsp, error_code); 
++
++		if (info)
++			force_sig_info(signr, info, tsk);
++		else
++			force_sig(signr, tsk);
++		return;
++	}
++
++
++	/* kernel trap */ 
++	{	     
++		const struct exception_table_entry *fixup;
++		fixup = search_exception_tables(regs->rip);
++		if (fixup)
++			regs->rip = fixup->fixup;
++		else	
++			die(str, regs, error_code);
++		return;
++	}
++}
++
++#define DO_ERROR(trapnr, signr, str, name) \
++asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++							== NOTIFY_STOP) \
++		return; \
++	conditional_sti(regs);						\
++	do_trap(trapnr, signr, str, regs, error_code, NULL); \
++}
++
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
++{ \
++	siginfo_t info; \
++	info.si_signo = signr; \
++	info.si_errno = 0; \
++	info.si_code = sicode; \
++	info.si_addr = (void __user *)siaddr; \
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
++							== NOTIFY_STOP) \
++		return; \
++	conditional_sti(regs);						\
++	do_trap(trapnr, signr, str, regs, error_code, &info); \
++}
++
++DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->rip)
++DO_ERROR( 4, SIGSEGV, "overflow", overflow)
++DO_ERROR( 5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->rip)
++DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
++DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
++DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
++DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
++DO_ERROR(18, SIGSEGV, "reserved", reserved)
++
++/* Runs on IST stack */
++asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
++{
++	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
++			12, SIGBUS) == NOTIFY_STOP)
++		return;
++	preempt_conditional_sti(regs);
++	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
++	preempt_conditional_cli(regs);
++}
++
++asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
++{
++	static const char str[] = "double fault";
++	struct task_struct *tsk = current;
++
++	/* Return not checked because double check cannot be ignored */
++	notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 8;
++
++	/* This is always a kernel trap and never fixable (and thus must
++	   never return). */
++	for (;;)
++		die(str, regs, error_code);
++}
++
++asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
++						long error_code)
++{
++	struct task_struct *tsk = current;
++
++	conditional_sti(regs);
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
++
++	if (user_mode(regs)) {
++		if (exception_trace && unhandled_signal(tsk, SIGSEGV))
++			printk(KERN_INFO
++		       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
++			       tsk->comm, tsk->pid,
++			       regs->rip, regs->rsp, error_code); 
++
++		force_sig(SIGSEGV, tsk);
++		return;
++	} 
++
++	/* kernel gp */
++	{
++		const struct exception_table_entry *fixup;
++		fixup = search_exception_tables(regs->rip);
++		if (fixup) {
++			regs->rip = fixup->fixup;
++			return;
++		}
++		if (notify_die(DIE_GPF, "general protection fault", regs,
++					error_code, 13, SIGSEGV) == NOTIFY_STOP)
++			return;
++		die("general protection fault", regs, error_code);
++	}
++}
++
++static __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs * regs)
++{
++	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
++	printk("You probably have a hardware problem with your RAM chips\n");
++
++#if 0 /* XEN */
++	/* Clear and disable the memory parity error line. */
++	reason = (reason & 0xf) | 4;
++	outb(reason, 0x61);
++#endif /* XEN */
++}
++
++static __kprobes void
++io_check_error(unsigned char reason, struct pt_regs * regs)
++{
++	printk("NMI: IOCK error (debug interrupt?)\n");
++	show_registers(regs);
++
++#if 0 /* XEN */
++	/* Re-enable the IOCK line, wait for a few seconds */
++	reason = (reason & 0xf) | 8;
++	outb(reason, 0x61);
++	mdelay(2000);
++	reason &= ~8;
++	outb(reason, 0x61);
++#endif /* XEN */
++}
++
++static __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++{	printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
++	printk("Dazed and confused, but trying to continue\n");
++	printk("Do you have a strange power saving mode enabled?\n");
++}
++
++/* Runs on IST stack. This code must keep interrupts off all the time.
++   Nested NMIs are prevented by the CPU. */
++asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
++{
++	unsigned char reason = 0;
++	int cpu;
++
++	cpu = smp_processor_id();
++
++	/* Only the BSP gets external NMIs from the system.  */
++	if (!cpu)
++		reason = get_nmi_reason();
++
++	if (!(reason & 0xc0)) {
++		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
++								== NOTIFY_STOP)
++			return;
++#ifdef CONFIG_X86_LOCAL_APIC
++		/*
++		 * Ok, so this is none of the documented NMI sources,
++		 * so it must be the NMI watchdog.
++		 */
++		if (nmi_watchdog > 0) {
++			nmi_watchdog_tick(regs,reason);
++			return;
++		}
++#endif
++		unknown_nmi_error(reason, regs);
++		return;
++	}
++	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return; 
++
++	/* AK: following checks seem to be broken on modern chipsets. FIXME */
++
++	if (reason & 0x80)
++		mem_parity_error(reason, regs);
++	if (reason & 0x40)
++		io_check_error(reason, regs);
++}
++
++/* runs on IST stack. */
++asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
++{
++	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
++		return;
++	}
++	preempt_conditional_sti(regs);
++	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
++	preempt_conditional_cli(regs);
++}
++
++/* Help handler running on IST stack to switch back to user stack
++   for scheduling or signal handling. The actual stack switch is done in
++   entry.S */
++asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
++{
++	struct pt_regs *regs = eregs;
++	/* Did already sync */
++	if (eregs == (struct pt_regs *)eregs->rsp)
++		;
++	/* Exception from user space */
++	else if (user_mode(eregs))
++		regs = task_pt_regs(current);
++	/* Exception from kernel and interrupts are enabled. Move to
++ 	   kernel process stack. */
++	else if (eregs->eflags & X86_EFLAGS_IF)
++		regs = (struct pt_regs *)(eregs->rsp -= sizeof(struct pt_regs));
++	if (eregs != regs)
++		*regs = *eregs;
++	return regs;
++}
++
++/* runs on IST stack. */
++asmlinkage void __kprobes do_debug(struct pt_regs * regs,
++				   unsigned long error_code)
++{
++	unsigned long condition;
++	struct task_struct *tsk = current;
++	siginfo_t info;
++
++	get_debugreg(condition, 6);
++
++	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
++						SIGTRAP) == NOTIFY_STOP)
++		return;
++
++	preempt_conditional_sti(regs);
++
++	/* Mask out spurious debug traps due to lazy DR7 setting */
++	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
++		if (!tsk->thread.debugreg7) { 
++			goto clear_dr7;
++		}
++	}
++
++	tsk->thread.debugreg6 = condition;
++
++	/* Mask out spurious TF errors due to lazy TF clearing */
++	if (condition & DR_STEP) {
++		/*
++		 * The TF error should be masked out only if the current
++		 * process is not traced and if the TRAP flag has been set
++		 * previously by a tracing process (condition detected by
++		 * the PT_DTRACE flag); remember that the i386 TRAP flag
++		 * can be modified by the process itself in user mode,
++		 * allowing programs to debug themselves without the ptrace()
++		 * interface.
++		 */
++                if (!user_mode(regs))
++                       goto clear_TF_reenable;
++		/*
++		 * Was the TF flag set by a debugger? If so, clear it now,
++		 * so that register information is correct.
++		 */
++		if (tsk->ptrace & PT_DTRACE) {
++			regs->eflags &= ~TF_MASK;
++			tsk->ptrace &= ~PT_DTRACE;
++		}
++	}
++
++	/* Ok, finally something we can handle */
++	tsk->thread.trap_no = 1;
++	tsk->thread.error_code = error_code;
++	info.si_signo = SIGTRAP;
++	info.si_errno = 0;
++	info.si_code = TRAP_BRKPT;
++	info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL;
++	force_sig_info(SIGTRAP, &info, tsk);
++
++clear_dr7:
++	set_debugreg(0UL, 7);
++	preempt_conditional_cli(regs);
++	return;
++
++clear_TF_reenable:
++	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
++	regs->eflags &= ~TF_MASK;
++	preempt_conditional_cli(regs);
++}
++
++static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
++{
++	const struct exception_table_entry *fixup;
++	fixup = search_exception_tables(regs->rip);
++	if (fixup) {
++		regs->rip = fixup->fixup;
++		return 1;
++	}
++	notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
++	/* Illegal floating point operation in the kernel */
++	current->thread.trap_no = trapnr;
++	die(str, regs, 0);
++	return 0;
++}
++
++/*
++ * Note that we play around with the 'TS' bit in an attempt to get
++ * the correct behaviour even in the presence of the asynchronous
++ * IRQ13 behaviour
++ */
++asmlinkage void do_coprocessor_error(struct pt_regs *regs)
++{
++	void __user *rip = (void __user *)(regs->rip);
++	struct task_struct * task;
++	siginfo_t info;
++	unsigned short cwd, swd;
++
++	conditional_sti(regs);
++	if (!user_mode(regs) &&
++	    kernel_math_error(regs, "kernel x87 math error", 16))
++		return;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 16;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = rip;
++	/*
++	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
++	 * status.  0x3f is the exception bits in these regs, 0x200 is the
++	 * C1 reg you need in case of a stack fault, 0x040 is the stack
++	 * fault bit.  We should only be taking one exception at a time,
++	 * so if this combination doesn't produce any single exception,
++	 * then we have a bad program that isn't synchronizing its FPU usage
++	 * and it will suffer the consequences since we won't be able to
++	 * fully reproduce the context of the exception
++	 */
++	cwd = get_fpu_cwd(task);
++	swd = get_fpu_swd(task);
++	switch (swd & ~cwd & 0x3f) {
++		case 0x000:
++		default:
++			break;
++		case 0x001: /* Invalid Op */
++			/*
++			 * swd & 0x240 == 0x040: Stack Underflow
++			 * swd & 0x240 == 0x240: Stack Overflow
++			 * User must clear the SF bit (0x40) if set
++			 */
++			info.si_code = FPE_FLTINV;
++			break;
++		case 0x002: /* Denormalize */
++		case 0x010: /* Underflow */
++			info.si_code = FPE_FLTUND;
++			break;
++		case 0x004: /* Zero Divide */
++			info.si_code = FPE_FLTDIV;
++			break;
++		case 0x008: /* Overflow */
++			info.si_code = FPE_FLTOVF;
++			break;
++		case 0x020: /* Precision */
++			info.si_code = FPE_FLTRES;
++			break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++asmlinkage void bad_intr(void)
++{
++	printk("bad interrupt"); 
++}
++
++asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
++{
++	void __user *rip = (void __user *)(regs->rip);
++	struct task_struct * task;
++	siginfo_t info;
++	unsigned short mxcsr;
++
++	conditional_sti(regs);
++	if (!user_mode(regs) &&
++        	kernel_math_error(regs, "kernel simd math error", 19))
++		return;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 19;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = rip;
++	/*
++	 * The SIMD FPU exceptions are handled a little differently, as there
++	 * is only a single status/control register.  Thus, to determine which
++	 * unmasked exception was caught we must mask the exception mask bits
++	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
++	 */
++	mxcsr = get_fpu_mxcsr(task);
++	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
++		case 0x000:
++		default:
++			break;
++		case 0x001: /* Invalid Op */
++			info.si_code = FPE_FLTINV;
++			break;
++		case 0x002: /* Denormalize */
++		case 0x010: /* Underflow */
++			info.si_code = FPE_FLTUND;
++			break;
++		case 0x004: /* Zero Divide */
++			info.si_code = FPE_FLTDIV;
++			break;
++		case 0x008: /* Overflow */
++			info.si_code = FPE_FLTOVF;
++			break;
++		case 0x020: /* Precision */
++			info.si_code = FPE_FLTRES;
++			break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
++{
++}
++
++#if 0
++asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
++{
++}
++#endif
++
++asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
++{
++}
++
++/*
++ *  'math_state_restore()' saves the current math information in the
++ * old math state array, and gets the new ones from the current task
++ *
++ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
++ * Don't touch unless you *really* know how it works.
++ */
++asmlinkage void math_state_restore(void)
++{
++	struct task_struct *me = current;
++        /* clts(); */ /* 'clts' is done for us by Xen during virtual trap. */
++
++	if (!used_math())
++		init_fpu(me);
++	restore_fpu_checking(&me->thread.i387.fxsave);
++	task_thread_info(me)->status |= TS_USEDFPU;
++}
++
++
++/*
++ * 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 __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                       },
++        {  4, 3|4, __KERNEL_CS, (unsigned long)overflow                   },
++        {  5, 0|4, __KERNEL_CS, (unsigned long)bounds                     },
++        {  6, 0|4, __KERNEL_CS, (unsigned long)invalid_op                 },
++        {  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available       },
++        {  9, 0|4, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun},
++        { 10, 0|4, __KERNEL_CS, (unsigned long)invalid_TSS                },
++        { 11, 0|4, __KERNEL_CS, (unsigned long)segment_not_present        },
++        { 12, 0|4, __KERNEL_CS, (unsigned long)stack_segment              },
++        { 13, 0|4, __KERNEL_CS, (unsigned long)general_protection         },
++        { 14, 0|4, __KERNEL_CS, (unsigned long)page_fault                 },
++        { 15, 0|4, __KERNEL_CS, (unsigned long)spurious_interrupt_bug     },
++        { 16, 0|4, __KERNEL_CS, (unsigned long)coprocessor_error          },
++        { 17, 0|4, __KERNEL_CS, (unsigned long)alignment_check            },
++#ifdef CONFIG_X86_MCE
++        { 18, 0|4, __KERNEL_CS, (unsigned long)machine_check              },
++#endif
++        { 19, 0|4, __KERNEL_CS, (unsigned long)simd_coprocessor_error     },
++#ifdef CONFIG_IA32_EMULATION
++	{ IA32_SYSCALL_VECTOR, 3, __KERNEL_CS, (unsigned long)ia32_syscall},
++#endif
++        {  0, 0,           0, 0                                              }
++};
++
++void __init trap_init(void)
++{
++        int ret;
++
++        ret = HYPERVISOR_set_trap_table(trap_table);
++        if (ret) 
++		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
++
++	/*
++	 * Should be a barrier for any external CPU state.
++	 */
++	cpu_init();
++}
++
++void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
++{
++	const trap_info_t *t = trap_table;
++
++	for (t = trap_table; t->address; t++) {
++		trap_ctxt[t->vector].flags = t->flags;
++		trap_ctxt[t->vector].cs = t->cs;
++		trap_ctxt[t->vector].address = t->address;
++	}
++}
++
++
++/* Actual parsing is done early in setup.c. */
++static int __init oops_dummy(char *s)
++{ 
++	panic_on_oops = 1;
++	return 1;
++} 
++__setup("oops=", oops_dummy); 
++
++static int __init kstack_setup(char *s)
++{
++	kstack_depth_to_print = simple_strtoul(s,NULL,0);
++	return 1;
++}
++__setup("kstack=", kstack_setup);
++
++#ifdef CONFIG_STACK_UNWIND
++static int __init call_trace_setup(char *s)
++{
++	if (strcmp(s, "old") == 0)
++		call_trace = -1;
++	else if (strcmp(s, "both") == 0)
++		call_trace = 0;
++	else if (strcmp(s, "newfallback") == 0)
++		call_trace = 1;
++	else if (strcmp(s, "new") == 0)
++		call_trace = 2;
++	return 1;
++}
++__setup("call_trace=", call_trace_setup);
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2007-06-18 08:38:13.000000000 +0200
+@@ -0,0 +1,227 @@
++/*
++ *  linux/arch/x86_64/kernel/vsyscall.c
++ *
++ *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
++ *  Copyright 2003 Andi Kleen, SuSE Labs.
++ *
++ *  Thanks to hpa@transmeta.com for some useful hint.
++ *  Special thanks to Ingo Molnar for his early experience with
++ *  a different vsyscall implementation for Linux/IA32 and for the name.
++ *
++ *  vsyscall 1 is located at -10Mbyte, vsyscall 2 is located
++ *  at virtual address -10Mbyte+1024bytes etc... There are at max 4
++ *  vsyscalls. One vsyscall can reserve more than 1 slot to avoid
++ *  jumping out of line if necessary. We cannot add more with this
++ *  mechanism because older kernels won't return -ENOSYS.
++ *  If we want more than four we need a vDSO.
++ *
++ *  Note: the concept clashes with user mode linux. If you use UML and
++ *  want per guest time just set the kernel.vsyscall64 sysctl to 0.
++ */
++
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/timer.h>
++#include <linux/seqlock.h>
++#include <linux/jiffies.h>
++#include <linux/sysctl.h>
++
++#include <asm/vsyscall.h>
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/fixmap.h>
++#include <asm/errno.h>
++#include <asm/io.h>
++
++#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
++
++int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
++seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
++
++#include <asm/unistd.h>
++
++static __always_inline void timeval_normalize(struct timeval * tv)
++{
++	time_t __sec;
++
++	__sec = tv->tv_usec / 1000000;
++	if (__sec) {
++		tv->tv_usec %= 1000000;
++		tv->tv_sec += __sec;
++	}
++}
++
++static __always_inline void do_vgettimeofday(struct timeval * tv)
++{
++	long sequence, t;
++	unsigned long sec, usec;
++
++	do {
++		sequence = read_seqbegin(&__xtime_lock);
++		
++		sec = __xtime.tv_sec;
++		usec = (__xtime.tv_nsec / 1000) +
++			(__jiffies - __wall_jiffies) * (1000000 / HZ);
++
++		if (__vxtime.mode != VXTIME_HPET) {
++			t = get_cycles_sync();
++			if (t < __vxtime.last_tsc)
++				t = __vxtime.last_tsc;
++			usec += ((t - __vxtime.last_tsc) *
++				 __vxtime.tsc_quot) >> 32;
++			/* See comment in x86_64 do_gettimeofday. */
++		} else {
++			usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) -
++				  __vxtime.last) * __vxtime.quot) >> 32;
++		}
++	} while (read_seqretry(&__xtime_lock, sequence));
++
++	tv->tv_sec = sec + usec / 1000000;
++	tv->tv_usec = usec % 1000000;
++}
++
++/* RED-PEN may want to readd seq locking, but then the variable should be write-once. */
++static __always_inline void do_get_tz(struct timezone * tz)
++{
++	*tz = __sys_tz;
++}
++
++static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
++{
++	int ret;
++	asm volatile("vsysc2: syscall"
++		: "=a" (ret)
++		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber );
++	return ret;
++}
++
++static __always_inline long time_syscall(long *t)
++{
++	long secs;
++	asm volatile("vsysc1: syscall"
++		: "=a" (secs)
++		: "0" (__NR_time),"D" (t) : __syscall_clobber);
++	return secs;
++}
++
++int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
++{
++	if (!__sysctl_vsyscall)
++		return gettimeofday(tv,tz);
++	if (tv)
++		do_vgettimeofday(tv);
++	if (tz)
++		do_get_tz(tz);
++	return 0;
++}
++
++/* This will break when the xtime seconds get inaccurate, but that is
++ * unlikely */
++time_t __vsyscall(1) vtime(time_t *t)
++{
++	if (!__sysctl_vsyscall)
++		return time_syscall(t);
++	else if (t)
++		*t = __xtime.tv_sec;		
++	return __xtime.tv_sec;
++}
++
++long __vsyscall(2) venosys_0(void)
++{
++	return -ENOSYS;
++}
++
++long __vsyscall(3) venosys_1(void)
++{
++	return -ENOSYS;
++}
++
++#ifdef CONFIG_SYSCTL
++
++#define SYSCALL 0x050f
++#define NOP2    0x9090
++
++/*
++ * NOP out syscall in vsyscall page when not needed.
++ */
++static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
++                        void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++	extern u16 vsysc1, vsysc2;
++	u16 *map1, *map2;
++	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
++	if (!write)
++		return ret;
++	/* gcc has some trouble with __va(__pa()), so just do it this
++	   way. */
++	map1 = ioremap(__pa_symbol(&vsysc1), 2);
++	if (!map1)
++		return -ENOMEM;
++	map2 = ioremap(__pa_symbol(&vsysc2), 2);
++	if (!map2) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	if (!sysctl_vsyscall) {
++		*map1 = SYSCALL;
++		*map2 = SYSCALL;
++	} else {
++		*map1 = NOP2;
++		*map2 = NOP2;
++	}
++	iounmap(map2);
++out:
++	iounmap(map1);
++	return ret;
++}
++
++static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
++				void __user *oldval, size_t __user *oldlenp,
++				void __user *newval, size_t newlen,
++				void **context)
++{
++	return -ENOSYS;
++}
++
++static ctl_table kernel_table2[] = {
++	{ .ctl_name = 99, .procname = "vsyscall64",
++	  .data = &sysctl_vsyscall, .maxlen = sizeof(int), .mode = 0644,
++	  .strategy = vsyscall_sysctl_nostrat,
++	  .proc_handler = vsyscall_sysctl_change },
++	{ 0, }
++};
++
++static ctl_table kernel_root_table2[] = {
++	{ .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
++	  .child = kernel_table2 },
++	{ 0 },
++};
++
++#endif
++
++static void __init map_vsyscall(void)
++{
++	extern char __vsyscall_0;
++	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
++
++	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
++}
++
++static int __init vsyscall_init(void)
++{
++	BUG_ON(((unsigned long) &vgettimeofday !=
++			VSYSCALL_ADDR(__NR_vgettimeofday)));
++	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
++	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
++	map_vsyscall();
++#ifdef CONFIG_XEN
++	sysctl_vsyscall = 0; /* disable vgettimeofay() */
++#endif
++#ifdef CONFIG_SYSCTL
++	register_sysctl_table(kernel_root_table2, 0);
++#endif
++	return 0;
++}
++
++__initcall(vsyscall_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/xen_entry_64.S	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,36 @@
++/*
++ * Copied from arch/xen/i386/kernel/entry.S
++ */                        
++/* Offsets into shared_info_t. */                
++#define evtchn_upcall_pending		/* 0 */
++#define evtchn_upcall_mask		1
++
++#define sizeof_vcpu_shift		6
++
++#ifdef CONFIG_SMP
++//#define preempt_disable(reg)	incl threadinfo_preempt_count(reg)
++//#define preempt_enable(reg)	decl threadinfo_preempt_count(reg)
++#define preempt_disable(reg)
++#define preempt_enable(reg)
++#define XEN_GET_VCPU_INFO(reg)	preempt_disable(%rbp)			; \
++				movq %gs:pda_cpunumber,reg		; \
++				shl  $32, reg				; \
++				shr  $32-sizeof_vcpu_shift,reg		; \
++				addq HYPERVISOR_shared_info,reg
++#define XEN_PUT_VCPU_INFO(reg)	preempt_enable(%rbp)			; \
++#define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff
++#else
++#define XEN_GET_VCPU_INFO(reg)	movq HYPERVISOR_shared_info,reg
++#define XEN_PUT_VCPU_INFO(reg)
++#define XEN_PUT_VCPU_INFO_fixup
++#endif
++
++#define XEN_LOCKED_BLOCK_EVENTS(reg)	movb $1,evtchn_upcall_mask(reg)
++#define XEN_LOCKED_UNBLOCK_EVENTS(reg)	movb $0,evtchn_upcall_mask(reg)
++#define XEN_BLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
++				XEN_LOCKED_BLOCK_EVENTS(reg)		; \
++    				XEN_PUT_VCPU_INFO(reg)
++#define XEN_UNBLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
++				XEN_LOCKED_UNBLOCK_EVENTS(reg)		; \
++    				XEN_PUT_VCPU_INFO(reg)
++#define XEN_TEST_PENDING(reg)	testb $0xFF,evtchn_upcall_pending(reg)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2007-11-02 17:34:23.000000000 +0100
+@@ -0,0 +1,724 @@
++/*
++ *  linux/arch/x86-64/mm/fault.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *  Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
++ */
++
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/vt_kern.h>		/* For unblank_screen() */
++#include <linux/compiler.h>
++#include <linux/module.h>
++#include <linux/kprobes.h>
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/pgalloc.h>
++#include <asm/smp.h>
++#include <asm/tlbflush.h>
++#include <asm/proto.h>
++#include <asm/kdebug.h>
++#include <asm-generic/sections.h>
++
++/* Page fault error code bits */
++#define PF_PROT	(1<<0)		/* or no page found */
++#define PF_WRITE	(1<<1)
++#define PF_USER	(1<<2)
++#define PF_RSVD	(1<<3)
++#define PF_INSTR	(1<<4)
++
++#ifdef CONFIG_KPROBES
++ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
++
++/* Hook to register for page fault notifications */
++int register_page_fault_notifier(struct notifier_block *nb)
++{
++	vmalloc_sync_all();
++	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
++}
++
++int unregister_page_fault_notifier(struct notifier_block *nb)
++{
++	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
++}
++
++static inline int notify_page_fault(enum die_val val, const char *str,
++			struct pt_regs *regs, long err, int trap, int sig)
++{
++	struct die_args args = {
++		.regs = regs,
++		.str = str,
++		.err = err,
++		.trapnr = trap,
++		.signr = sig
++	};
++	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
++}
++#else
++static inline int notify_page_fault(enum die_val val, const char *str,
++			struct pt_regs *regs, long err, int trap, int sig)
++{
++	return NOTIFY_DONE;
++}
++#endif
++
++void bust_spinlocks(int yes)
++{
++	int loglevel_save = console_loglevel;
++	if (yes) {
++		oops_in_progress = 1;
++	} else {
++#ifdef CONFIG_VT
++		unblank_screen();
++#endif
++		oops_in_progress = 0;
++		/*
++		 * OK, the message is on the console.  Now we call printk()
++		 * without oops_in_progress set so that printk will give klogd
++		 * a poke.  Hold onto your hats...
++		 */
++		console_loglevel = 15;		/* NMI oopser may have shut the console up */
++		printk(" ");
++		console_loglevel = loglevel_save;
++	}
++}
++
++/* Sometimes the CPU reports invalid exceptions on prefetch.
++   Check that here and ignore.
++   Opcode checker based on code by Richard Brunner */
++static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
++				unsigned long error_code)
++{ 
++	unsigned char *instr;
++	int scan_more = 1;
++	int prefetch = 0; 
++	unsigned char *max_instr;
++
++	/* If it was a exec fault ignore */
++	if (error_code & PF_INSTR)
++		return 0;
++	
++	instr = (unsigned char *)convert_rip_to_linear(current, regs);
++	max_instr = instr + 15;
++
++	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
++		return 0;
++
++	while (scan_more && instr < max_instr) { 
++		unsigned char opcode;
++		unsigned char instr_hi;
++		unsigned char instr_lo;
++
++		if (__get_user(opcode, instr))
++			break; 
++
++		instr_hi = opcode & 0xf0; 
++		instr_lo = opcode & 0x0f; 
++		instr++;
++
++		switch (instr_hi) { 
++		case 0x20:
++		case 0x30:
++			/* Values 0x26,0x2E,0x36,0x3E are valid x86
++			   prefixes.  In long mode, the CPU will signal
++			   invalid opcode if some of these prefixes are
++			   present so we will never get here anyway */
++			scan_more = ((instr_lo & 7) == 0x6);
++			break;
++			
++		case 0x40:
++			/* In AMD64 long mode, 0x40 to 0x4F are valid REX prefixes
++			   Need to figure out under what instruction mode the
++			   instruction was issued ... */
++			/* Could check the LDT for lm, but for now it's good
++			   enough to assume that long mode only uses well known
++			   segments or kernel. */
++			scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
++			break;
++			
++		case 0x60:
++			/* 0x64 thru 0x67 are valid prefixes in all modes. */
++			scan_more = (instr_lo & 0xC) == 0x4;
++			break;		
++		case 0xF0:
++			/* 0xF0, 0xF2, and 0xF3 are valid prefixes in all modes. */
++			scan_more = !instr_lo || (instr_lo>>1) == 1;
++			break;			
++		case 0x00:
++			/* Prefetch instruction is 0x0F0D or 0x0F18 */
++			scan_more = 0;
++			if (__get_user(opcode, instr)) 
++				break;
++			prefetch = (instr_lo == 0xF) &&
++				(opcode == 0x0D || opcode == 0x18);
++			break;			
++		default:
++			scan_more = 0;
++			break;
++		} 
++	}
++	return prefetch;
++}
++
++static int bad_address(void *p) 
++{ 
++	unsigned long dummy;
++	return __get_user(dummy, (unsigned long *)p);
++} 
++
++void dump_pagetable(unsigned long address)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
++	pgd += pgd_index(address);
++	if (bad_address(pgd)) goto bad;
++	printk("PGD %lx ", pgd_val(*pgd));
++	if (!pgd_present(*pgd)) goto ret; 
++
++	pud = pud_offset(pgd, address);
++	if (bad_address(pud)) goto bad;
++	printk("PUD %lx ", pud_val(*pud));
++	if (!pud_present(*pud))	goto ret;
++
++	pmd = pmd_offset(pud, address);
++	if (bad_address(pmd)) goto bad;
++	printk("PMD %lx ", pmd_val(*pmd));
++	if (!pmd_present(*pmd))	goto ret;	 
++
++	pte = pte_offset_kernel(pmd, address);
++	if (bad_address(pte)) goto bad;
++	printk("PTE %lx", pte_val(*pte)); 
++ret:
++	printk("\n");
++	return;
++bad:
++	printk("BAD\n");
++}
++
++static const char errata93_warning[] = 
++KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
++KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
++KERN_ERR "******* Please consider a BIOS update.\n"
++KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
++
++/* Workaround for K8 erratum #93 & buggy BIOS.
++   BIOS SMM functions are required to use a specific workaround
++   to avoid corruption of the 64bit RIP register on C stepping K8. 
++   A lot of BIOS that didn't get tested properly miss this. 
++   The OS sees this as a page fault with the upper 32bits of RIP cleared.
++   Try to work around it here.
++   Note we only handle faults in kernel here. */
++
++static int is_errata93(struct pt_regs *regs, unsigned long address) 
++{
++	static int warned;
++	if (address != regs->rip)
++		return 0;
++	if ((address >> 32) != 0) 
++		return 0;
++	address |= 0xffffffffUL << 32;
++	if ((address >= (u64)_stext && address <= (u64)_etext) || 
++	    (address >= MODULES_VADDR && address <= MODULES_END)) { 
++		if (!warned) {
++			printk(errata93_warning); 		
++			warned = 1;
++		}
++		regs->rip = address;
++		return 1;
++	}
++	return 0;
++} 
++
++int unhandled_signal(struct task_struct *tsk, int sig)
++{
++	if (tsk->pid == 1)
++		return 1;
++	if (tsk->ptrace & PT_PTRACED)
++		return 0;
++	return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
++		(tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
++}
++
++static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
++				 unsigned long error_code)
++{
++	unsigned long flags = oops_begin();
++	struct task_struct *tsk;
++
++	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
++	       current->comm, address);
++	dump_pagetable(address);
++	tsk = current;
++	tsk->thread.cr2 = address;
++	tsk->thread.trap_no = 14;
++	tsk->thread.error_code = error_code;
++	__die("Bad pagetable", regs, error_code);
++	oops_end(flags);
++	do_exit(SIGKILL);
++}
++
++/*
++ * Handle a fault on the vmalloc area
++ *
++ * This assumes no large pages in there.
++ */
++static int vmalloc_fault(unsigned long address)
++{
++	pgd_t *pgd, *pgd_ref;
++	pud_t *pud, *pud_ref;
++	pmd_t *pmd, *pmd_ref;
++	pte_t *pte, *pte_ref;
++
++	/* Copy kernel mappings over when needed. This can also
++	   happen within a race in page table update. In the later
++	   case just flush. */
++
++	/* On Xen the line below does not always work. Needs investigating! */
++	/*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
++	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
++	pgd += pgd_index(address);
++	pgd_ref = pgd_offset_k(address);
++	if (pgd_none(*pgd_ref))
++		return -1;
++	if (pgd_none(*pgd))
++		set_pgd(pgd, *pgd_ref);
++	else
++		BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
++
++	/* Below here mismatches are bugs because these lower tables
++	   are shared */
++
++	pud = pud_offset(pgd, address);
++	pud_ref = pud_offset(pgd_ref, address);
++	if (pud_none(*pud_ref))
++		return -1;
++	if (pud_none(*pud) || pud_page(*pud) != pud_page(*pud_ref))
++		BUG();
++	pmd = pmd_offset(pud, address);
++	pmd_ref = pmd_offset(pud_ref, address);
++	if (pmd_none(*pmd_ref))
++		return -1;
++	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
++		BUG();
++	pte_ref = pte_offset_kernel(pmd_ref, address);
++	if (!pte_present(*pte_ref))
++		return -1;
++	pte = pte_offset_kernel(pmd, address);
++	/* Don't use pte_page here, because the mappings can point
++	   outside mem_map, and the NUMA hash lookup cannot handle
++	   that. */
++	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
++		BUG();
++	return 0;
++}
++
++int page_fault_trace = 0;
++int exception_trace = 1;
++
++
++#define MEM_VERBOSE 1
++
++#ifdef MEM_VERBOSE
++#define MEM_LOG(_f, _a...)			\
++	printk("fault.c:[%d]-> " _f "\n",	\
++	__LINE__ , ## _a )
++#else
++#define MEM_LOG(_f, _a...) ((void)0)
++#endif
++
++static int spurious_fault(struct pt_regs *regs,
++			  unsigned long address,
++			  unsigned long error_code)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++#ifdef CONFIG_XEN
++	/* Faults in hypervisor area are never spurious. */
++	if ((address >= HYPERVISOR_VIRT_START) &&
++	    (address < HYPERVISOR_VIRT_END))
++		return 0;
++#endif
++
++	/* Reserved-bit violation or user access to kernel space? */
++	if (error_code & (PF_RSVD|PF_USER))
++		return 0;
++
++	pgd = init_mm.pgd + pgd_index(address);
++	if (!pgd_present(*pgd))
++		return 0;
++
++	pud = pud_offset(pgd, address);
++	if (!pud_present(*pud))
++		return 0;
++
++	pmd = pmd_offset(pud, address);
++	if (!pmd_present(*pmd))
++		return 0;
++
++	pte = pte_offset_kernel(pmd, address);
++	if (!pte_present(*pte))
++		return 0;
++	if ((error_code & PF_WRITE) && !pte_write(*pte))
++		return 0;
++	if ((error_code & PF_INSTR) && (__pte_val(*pte) & _PAGE_NX))
++		return 0;
++
++	return 1;
++}
++
++/*
++ * This routine handles page faults.  It determines the address,
++ * and the problem, and then passes it off to one of the appropriate
++ * routines.
++ */
++asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
++					unsigned long error_code)
++{
++	struct task_struct *tsk;
++	struct mm_struct *mm;
++	struct vm_area_struct * vma;
++	unsigned long address;
++	const struct exception_table_entry *fixup;
++	int write;
++	unsigned long flags;
++	siginfo_t info;
++
++	if (!user_mode(regs))
++		error_code &= ~PF_USER; /* means kernel */
++
++	tsk = current;
++	mm = tsk->mm;
++	prefetchw(&mm->mmap_sem);
++
++	/* get the address */
++	address = current_vcpu_info()->arch.cr2;
++
++	info.si_code = SEGV_MAPERR;
++
++
++	/*
++	 * We fault-in kernel-space virtual memory on-demand. The
++	 * 'reference' page table is init_mm.pgd.
++	 *
++	 * NOTE! We MUST NOT take any locks for this case. We may
++	 * be in an interrupt or a critical region, and should
++	 * only copy the information from the master page table,
++	 * nothing more.
++	 *
++	 * This verifies that the fault happens in kernel space
++	 * (error_code & 4) == 0, and that the fault was not a
++	 * protection error (error_code & 9) == 0.
++	 */
++	if (unlikely(address >= TASK_SIZE64)) {
++		/*
++		 * Don't check for the module range here: its PML4
++		 * is always initialized because it's shared with the main
++		 * kernel text. Only vmalloc may need PML4 syncups.
++		 */
++		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
++		      ((address >= VMALLOC_START && address < VMALLOC_END))) {
++			if (vmalloc_fault(address) >= 0)
++				return;
++		}
++		/* Can take a spurious fault if mapping changes R/O -> R/W. */
++		if (spurious_fault(regs, address, error_code))
++			return;
++		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
++						SIGSEGV) == NOTIFY_STOP)
++			return;
++		/*
++		 * Don't take the mm semaphore here. If we fixup a prefetch
++		 * fault we could otherwise deadlock.
++		 */
++		goto bad_area_nosemaphore;
++	}
++
++	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
++					SIGSEGV) == NOTIFY_STOP)
++		return;
++
++	if (likely(regs->eflags & X86_EFLAGS_IF))
++		local_irq_enable();
++
++	if (unlikely(page_fault_trace))
++		printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
++		       regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code); 
++
++	if (unlikely(error_code & PF_RSVD))
++		pgtable_bad(address, regs, error_code);
++
++	/*
++	 * If we're in an interrupt or have no user
++	 * context, we must not take the fault..
++	 */
++	if (unlikely(in_atomic() || !mm))
++		goto bad_area_nosemaphore;
++
++ again:
++	/* When running in the kernel we expect faults to occur only to
++	 * addresses in user space.  All other faults represent errors in the
++	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
++	 * erroneous fault occurring in a code path which already holds mmap_sem
++	 * we will deadlock attempting to validate the fault against the
++	 * address space.  Luckily the kernel only validly references user
++	 * space from well defined areas of code, which are listed in the
++	 * exceptions table.
++	 *
++	 * As the vast majority of faults will be valid we will only perform
++	 * the source reference check when there is a possibilty of a deadlock.
++	 * Attempt to lock the address space, if we cannot we then validate the
++	 * source.  If this is invalid we can skip the address space check,
++	 * thus avoiding the deadlock.
++	 */
++	if (!down_read_trylock(&mm->mmap_sem)) {
++		if ((error_code & PF_USER) == 0 &&
++		    !search_exception_tables(regs->rip))
++			goto bad_area_nosemaphore;
++		down_read(&mm->mmap_sem);
++	}
++
++	vma = find_vma(mm, address);
++	if (!vma)
++		goto bad_area;
++	if (likely(vma->vm_start <= address))
++		goto good_area;
++	if (!(vma->vm_flags & VM_GROWSDOWN))
++		goto bad_area;
++	if (error_code & 4) {
++		/* Allow userspace just enough access below the stack pointer
++		 * to let the 'enter' instruction work.
++		 */
++		if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp)
++			goto bad_area;
++	}
++	if (expand_stack(vma, address))
++		goto bad_area;
++/*
++ * Ok, we have a good vm_area for this memory access, so
++ * we can handle it..
++ */
++good_area:
++	info.si_code = SEGV_ACCERR;
++	write = 0;
++	switch (error_code & (PF_PROT|PF_WRITE)) {
++		default:	/* 3: write, present */
++			/* fall through */
++		case PF_WRITE:		/* write, not present */
++			if (!(vma->vm_flags & VM_WRITE))
++				goto bad_area;
++			write++;
++			break;
++		case PF_PROT:		/* read, present */
++			goto bad_area;
++		case 0:			/* read, not present */
++			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
++				goto bad_area;
++	}
++
++	/*
++	 * If for any reason at all we couldn't handle the fault,
++	 * make sure we exit gracefully rather than endlessly redo
++	 * the fault.
++	 */
++	switch (handle_mm_fault(mm, vma, address, write)) {
++	case VM_FAULT_MINOR:
++		tsk->min_flt++;
++		break;
++	case VM_FAULT_MAJOR:
++		tsk->maj_flt++;
++		break;
++	case VM_FAULT_SIGBUS:
++		goto do_sigbus;
++	default:
++		goto out_of_memory;
++	}
++
++	up_read(&mm->mmap_sem);
++	return;
++
++/*
++ * Something tried to access memory that isn't in our memory map..
++ * Fix it, but check if it's kernel or user first..
++ */
++bad_area:
++	up_read(&mm->mmap_sem);
++
++bad_area_nosemaphore:
++	/* User mode accesses just cause a SIGSEGV */
++	if (error_code & PF_USER) {
++		if (is_prefetch(regs, address, error_code))
++			return;
++
++		/* Work around K8 erratum #100 K8 in compat mode
++		   occasionally jumps to illegal addresses >4GB.  We
++		   catch this here in the page fault handler because
++		   these addresses are not reachable. Just detect this
++		   case and return.  Any code segment in LDT is
++		   compatibility mode. */
++		if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
++		    (address >> 32))
++			return;
++
++		if (exception_trace && unhandled_signal(tsk, SIGSEGV)) {
++			printk(
++		       "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
++					tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
++					tsk->comm, tsk->pid, address, regs->rip,
++					regs->rsp, error_code);
++		}
++       
++		tsk->thread.cr2 = address;
++		/* Kernel addresses are always protection faults */
++		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
++		tsk->thread.trap_no = 14;
++		info.si_signo = SIGSEGV;
++		info.si_errno = 0;
++		/* info.si_code has been set above */
++		info.si_addr = (void __user *)address;
++		force_sig_info(SIGSEGV, &info, tsk);
++		return;
++	}
++
++no_context:
++	
++	/* Are we prepared to handle this kernel fault?  */
++	fixup = search_exception_tables(regs->rip);
++	if (fixup) {
++		regs->rip = fixup->fixup;
++		return;
++	}
++
++	/* 
++	 * Hall of shame of CPU/BIOS bugs.
++	 */
++
++ 	if (is_prefetch(regs, address, error_code))
++ 		return;
++
++	if (is_errata93(regs, address))
++		return; 
++
++/*
++ * Oops. The kernel tried to access some bad page. We'll have to
++ * terminate things with extreme prejudice.
++ */
++
++	flags = oops_begin();
++
++	if (address < PAGE_SIZE)
++		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
++	else
++		printk(KERN_ALERT "Unable to handle kernel paging request");
++	printk(" at %016lx RIP: \n" KERN_ALERT,address);
++	printk_address(regs->rip);
++	dump_pagetable(address);
++	tsk->thread.cr2 = address;
++	tsk->thread.trap_no = 14;
++	tsk->thread.error_code = error_code;
++	__die("Oops", regs, error_code);
++	/* Executive summary in case the body of the oops scrolled away */
++	printk(KERN_EMERG "CR2: %016lx\n", address);
++	oops_end(flags);
++	do_exit(SIGKILL);
++
++/*
++ * We ran out of memory, or some other thing happened to us that made
++ * us unable to handle the page fault gracefully.
++ */
++out_of_memory:
++	up_read(&mm->mmap_sem);
++	if (current->pid == 1) { 
++		yield();
++		goto again;
++	}
++	printk("VM: killing process %s\n", tsk->comm);
++	if (error_code & 4)
++		do_exit(SIGKILL);
++	goto no_context;
++
++do_sigbus:
++	up_read(&mm->mmap_sem);
++
++	/* Kernel mode? Handle exceptions or die */
++	if (!(error_code & PF_USER))
++		goto no_context;
++
++	tsk->thread.cr2 = address;
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 14;
++	info.si_signo = SIGBUS;
++	info.si_errno = 0;
++	info.si_code = BUS_ADRERR;
++	info.si_addr = (void __user *)address;
++	force_sig_info(SIGBUS, &info, tsk);
++	return;
++}
++
++DEFINE_SPINLOCK(pgd_lock);
++struct page *pgd_list;
++
++void vmalloc_sync_all(void)
++{
++	/* Note that races in the updates of insync and start aren't 
++	   problematic:
++	   insync can only get set bits added, and updates to start are only
++	   improving performance (without affecting correctness if undone). */
++	static DECLARE_BITMAP(insync, PTRS_PER_PGD);
++	static unsigned long start = VMALLOC_START & PGDIR_MASK;
++	unsigned long address;
++
++	for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
++		if (!test_bit(pgd_index(address), insync)) {
++			const pgd_t *pgd_ref = pgd_offset_k(address);
++			struct page *page;
++
++			if (pgd_none(*pgd_ref))
++				continue;
++			spin_lock(&pgd_lock);
++			for (page = pgd_list; page;
++			     page = (struct page *)page->index) {
++				pgd_t *pgd;
++				pgd = (pgd_t *)page_address(page) + pgd_index(address);
++				if (pgd_none(*pgd))
++					set_pgd(pgd, *pgd_ref);
++				else
++					BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
++			}
++			spin_unlock(&pgd_lock);
++			set_bit(pgd_index(address), insync);
++		}
++		if (address == start)
++			start = address + PGDIR_SIZE;
++	}
++	/* Check that there is no need to do the same for the modules area. */
++	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
++	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == 
++				(__START_KERNEL & PGDIR_MASK)));
++}
++
++static int __init enable_pagefaulttrace(char *str)
++{
++	page_fault_trace = 1;
++	return 1;
++}
++__setup("pagefaulttrace", enable_pagefaulttrace);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,1231 @@
++/*
++ *  linux/arch/x86_64/mm/init.c
++ *
++ *  Copyright (C) 1995  Linus Torvalds
++ *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
++ *  Copyright (C) 2002,2003 Andi Kleen <ak@suse.de>
++ *
++ *  Jun Nakajima <jun.nakajima@intel.com>
++ *	Modified for Xen.
++ */
++
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/smp.h>
++#include <linux/init.h>
++#include <linux/pagemap.h>
++#include <linux/bootmem.h>
++#include <linux/proc_fs.h>
++#include <linux/pci.h>
++#include <linux/poison.h>
++#include <linux/dma-mapping.h>
++#include <linux/module.h>
++#include <linux/memory_hotplug.h>
++
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/dma.h>
++#include <asm/fixmap.h>
++#include <asm/e820.h>
++#include <asm/apic.h>
++#include <asm/tlb.h>
++#include <asm/mmu_context.h>
++#include <asm/proto.h>
++#include <asm/smp.h>
++#include <asm/sections.h>
++
++#include <xen/features.h>
++
++#ifndef Dprintk
++#define Dprintk(x...)
++#endif
++
++struct dma_mapping_ops* dma_ops;
++EXPORT_SYMBOL(dma_ops);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++unsigned int __kernel_page_user;
++EXPORT_SYMBOL(__kernel_page_user);
++#endif
++
++int after_bootmem;
++
++static unsigned long dma_reserve __initdata;
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++extern unsigned long start_pfn;
++
++/*
++ * Use this until direct mapping is established, i.e. before __va() is 
++ * available in init_memory_mapping().
++ */
++
++#define addr_to_page(addr, page)				\
++	(addr) &= PHYSICAL_PAGE_MASK;				\
++	(page) = ((unsigned long *) ((unsigned long)		\
++	(((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) +	\
++	__START_KERNEL_map)))
++
++static void __meminit early_make_page_readonly(void *va, unsigned int feature)
++{
++	unsigned long addr, _va = (unsigned long)va;
++	pte_t pte, *ptep;
++	unsigned long *page = (unsigned long *) init_level4_pgt;
++
++	BUG_ON(after_bootmem);
++
++	if (xen_feature(feature))
++		return;
++
++	addr = (unsigned long) page[pgd_index(_va)];
++	addr_to_page(addr, page);
++
++	addr = page[pud_index(_va)];
++	addr_to_page(addr, page);
++
++	addr = page[pmd_index(_va)];
++	addr_to_page(addr, page);
++
++	ptep = (pte_t *) &page[pte_index(_va)];
++
++	pte.pte = ptep->pte & ~_PAGE_RW;
++	if (HYPERVISOR_update_va_mapping(_va, pte, 0))
++		BUG();
++}
++
++static void __make_page_readonly(void *va)
++{
++	pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
++	unsigned long addr = (unsigned long) va;
++
++	pgd = pgd_offset_k(addr);
++	pud = pud_offset(pgd, addr);
++	pmd = pmd_offset(pud, addr);
++	ptep = pte_offset_kernel(pmd, addr);
++
++	pte.pte = ptep->pte & ~_PAGE_RW;
++	if (HYPERVISOR_update_va_mapping(addr, pte, 0))
++		xen_l1_entry_update(ptep, pte); /* fallback */
++
++	if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
++		__make_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT));
++}
++
++static void __make_page_writable(void *va)
++{
++	pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
++	unsigned long addr = (unsigned long) va;
++
++	pgd = pgd_offset_k(addr);
++	pud = pud_offset(pgd, addr);
++	pmd = pmd_offset(pud, addr);
++	ptep = pte_offset_kernel(pmd, addr);
++
++	pte.pte = ptep->pte | _PAGE_RW;
++	if (HYPERVISOR_update_va_mapping(addr, pte, 0))
++		xen_l1_entry_update(ptep, pte); /* fallback */
++
++	if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
++		__make_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT));
++}
++
++void make_page_readonly(void *va, unsigned int feature)
++{
++	if (!xen_feature(feature))
++		__make_page_readonly(va);
++}
++
++void make_page_writable(void *va, unsigned int feature)
++{
++	if (!xen_feature(feature))
++		__make_page_writable(va);
++}
++
++void make_pages_readonly(void *va, unsigned nr, unsigned int feature)
++{
++	if (xen_feature(feature))
++		return;
++
++	while (nr-- != 0) {
++		__make_page_readonly(va);
++		va = (void*)((unsigned long)va + PAGE_SIZE);
++	}
++}
++
++void make_pages_writable(void *va, unsigned nr, unsigned int feature)
++{
++	if (xen_feature(feature))
++		return;
++
++	while (nr-- != 0) {
++		__make_page_writable(va);
++		va = (void*)((unsigned long)va + PAGE_SIZE);
++	}
++}
++
++/*
++ * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
++ * physical space so we can cache the place of the first one and move
++ * around without checking the pgd every time.
++ */
++
++void show_mem(void)
++{
++	long i, total = 0, reserved = 0;
++	long shared = 0, cached = 0;
++	pg_data_t *pgdat;
++	struct page *page;
++
++	printk(KERN_INFO "Mem-info:\n");
++	show_free_areas();
++	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
++
++	for_each_online_pgdat(pgdat) {
++               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
++			page = pfn_to_page(pgdat->node_start_pfn + i);
++			total++;
++			if (PageReserved(page))
++				reserved++;
++			else if (PageSwapCache(page))
++				cached++;
++			else if (page_count(page))
++				shared += page_count(page) - 1;
++               }
++	}
++	printk(KERN_INFO "%lu pages of RAM\n", total);
++	printk(KERN_INFO "%lu reserved pages\n",reserved);
++	printk(KERN_INFO "%lu pages shared\n",shared);
++	printk(KERN_INFO "%lu pages swap cached\n",cached);
++}
++
++
++static __init void *spp_getpage(void)
++{ 
++	void *ptr;
++	if (after_bootmem)
++		ptr = (void *) get_zeroed_page(GFP_ATOMIC); 
++	else if (start_pfn < table_end) {
++		ptr = __va(start_pfn << PAGE_SHIFT);
++		start_pfn++;
++		memset(ptr, 0, PAGE_SIZE);
++	} else
++		ptr = alloc_bootmem_pages(PAGE_SIZE);
++	if (!ptr || ((unsigned long)ptr & ~PAGE_MASK))
++		panic("set_pte_phys: cannot allocate page data %s\n", after_bootmem?"after bootmem":"");
++
++	Dprintk("spp_getpage %p\n", ptr);
++	return ptr;
++} 
++
++#define pgd_offset_u(address) (__user_pgd(init_level4_pgt) + pgd_index(address))
++#define pud_offset_u(address) (level3_user_pgt + pud_index(address))
++
++static __init void set_pte_phys(unsigned long vaddr,
++			 unsigned long phys, pgprot_t prot, int user_mode)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte, new_pte;
++
++	Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys);
++
++	pgd = (user_mode ? pgd_offset_u(vaddr) : pgd_offset_k(vaddr));
++	if (pgd_none(*pgd)) {
++		printk("PGD FIXMAP MISSING, it should be setup in head.S!\n");
++		return;
++	}
++	pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr));
++	if (pud_none(*pud)) {
++		pmd = (pmd_t *) spp_getpage(); 
++		make_page_readonly(pmd, XENFEAT_writable_page_tables);
++		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
++		if (pmd != pmd_offset(pud, 0)) {
++			printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0));
++			return;
++		}
++	}
++	pmd = pmd_offset(pud, vaddr);
++	if (pmd_none(*pmd)) {
++		pte = (pte_t *) spp_getpage();
++		make_page_readonly(pte, XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
++		if (pte != pte_offset_kernel(pmd, 0)) {
++			printk("PAGETABLE BUG #02!\n");
++			return;
++		}
++	}
++	if (pgprot_val(prot))
++		new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
++	else
++		new_pte = __pte(0);
++
++	pte = pte_offset_kernel(pmd, vaddr);
++	if (!pte_none(*pte) && __pte_val(new_pte) &&
++	    __pte_val(*pte) != (__pte_val(new_pte) & __supported_pte_mask))
++		pte_ERROR(*pte);
++	set_pte(pte, new_pte);
++
++	/*
++	 * It's enough to flush this one mapping.
++	 * (PGE mappings get flushed as well)
++	 */
++	__flush_tlb_one(vaddr);
++}
++
++static __init void set_pte_phys_ma(unsigned long vaddr,
++				   unsigned long phys, pgprot_t prot)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte, new_pte;
++
++	Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys);
++
++	pgd = pgd_offset_k(vaddr);
++	if (pgd_none(*pgd)) {
++		printk("PGD FIXMAP MISSING, it should be setup in head.S!\n");
++		return;
++	}
++	pud = pud_offset(pgd, vaddr);
++	if (pud_none(*pud)) {
++
++		pmd = (pmd_t *) spp_getpage(); 
++		make_page_readonly(pmd, XENFEAT_writable_page_tables);
++		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
++		if (pmd != pmd_offset(pud, 0)) {
++			printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0));
++			return;
++		}
++	}
++	pmd = pmd_offset(pud, vaddr);
++	if (pmd_none(*pmd)) {
++		pte = (pte_t *) spp_getpage();
++		make_page_readonly(pte, XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
++		if (pte != pte_offset_kernel(pmd, 0)) {
++			printk("PAGETABLE BUG #02!\n");
++			return;
++		}
++	}
++	new_pte = pfn_pte_ma(phys >> PAGE_SHIFT, prot);
++
++	pte = pte_offset_kernel(pmd, vaddr);
++	if (!pte_none(*pte) && __pte_val(new_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);
++
++	/*
++	 * It's enough to flush this one mapping.
++	 * (PGE mappings get flushed as well)
++	 */
++	__flush_tlb_one(vaddr);
++}
++
++/* NOTE: this is meant to be run only at boot */
++void __init 
++__set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++{
++	unsigned long address = __fix_to_virt(idx);
++
++	if (idx >= __end_of_fixed_addresses) {
++		printk("Invalid __set_fixmap\n");
++		return;
++	}
++	switch (idx) {
++	case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
++		set_pte_phys(address, phys, prot, 0);
++		set_pte_phys(address, phys, prot, 1);
++		break;
++	default:
++		set_pte_phys_ma(address, phys, prot);
++		break;
++	}
++}
++
++unsigned long __initdata table_start, table_end; 
++
++static __meminit void *alloc_static_page(unsigned long *phys)
++{
++	unsigned long va = (start_pfn << PAGE_SHIFT) + __START_KERNEL_map;
++
++	if (after_bootmem) {
++		void *adr = (void *)get_zeroed_page(GFP_ATOMIC);
++
++		*phys = __pa(adr);
++		return adr;
++	}
++
++	*phys = start_pfn << PAGE_SHIFT;
++	start_pfn++;
++	memset((void *)va, 0, PAGE_SIZE);
++	return (void *)va;
++} 
++
++#define PTE_SIZE PAGE_SIZE
++
++static inline int make_readonly(unsigned long paddr)
++{
++	extern char __vsyscall_0;
++	int readonly = 0;
++
++	/* Make new page tables read-only. */
++	if (!xen_feature(XENFEAT_writable_page_tables)
++	    && (paddr >= (table_start << PAGE_SHIFT))
++	    && (paddr < (table_end << PAGE_SHIFT)))
++		readonly = 1;
++	/* Make old page tables read-only. */
++	if (!xen_feature(XENFEAT_writable_page_tables)
++	    && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
++	    && (paddr < (start_pfn << PAGE_SHIFT)))
++		readonly = 1;
++
++	/*
++	 * No need for writable mapping of kernel image. This also ensures that
++	 * page and descriptor tables embedded inside don't have writable
++	 * mappings. Exclude the vsyscall area here, allowing alternative
++	 * instruction patching to work.
++	 */
++	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end))
++	    && !(paddr >= __pa_symbol(&__vsyscall_0)
++	         && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE))
++		readonly = 1;
++
++	return readonly;
++}
++
++#ifndef CONFIG_XEN
++/* Must run before zap_low_mappings */
++__init void *early_ioremap(unsigned long addr, unsigned long size)
++{
++	unsigned long map = round_down(addr, LARGE_PAGE_SIZE);
++
++	/* actually usually some more */
++	if (size >= LARGE_PAGE_SIZE) {
++		printk("SMBIOS area too long %lu\n", size);
++		return NULL;
++	}
++	set_pmd(temp_mappings[0].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
++	map += LARGE_PAGE_SIZE;
++	set_pmd(temp_mappings[1].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
++	__flush_tlb();
++	return temp_mappings[0].address + (addr & (LARGE_PAGE_SIZE-1));
++}
++
++/* To avoid virtual aliases later */
++__init void early_iounmap(void *addr, unsigned long size)
++{
++	if ((void *)round_down((unsigned long)addr, LARGE_PAGE_SIZE) != temp_mappings[0].address)
++		printk("early_iounmap: bad address %p\n", addr);
++	set_pmd(temp_mappings[0].pmd, __pmd(0));
++	set_pmd(temp_mappings[1].pmd, __pmd(0));
++	__flush_tlb();
++}
++#endif
++
++static void __meminit
++phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
++{
++	int i, k;
++
++	for (i = 0; i < PTRS_PER_PMD; pmd++, i++) {
++		unsigned long pte_phys;
++		pte_t *pte, *pte_save;
++
++		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 ||
++			    (!after_bootmem &&
++			     (address >> PAGE_SHIFT) >= xen_start_info->nr_pages))
++				pteval = 0;
++			else if (make_readonly(address))
++				pteval &= ~_PAGE_RW;
++			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));
++		}
++	}
++}
++
++static void __meminit
++phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
++{
++	pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
++
++	if (pmd_none(*pmd)) {
++		spin_lock(&init_mm.page_table_lock);
++		phys_pmd_init(pmd, address, end);
++		spin_unlock(&init_mm.page_table_lock);
++		__flush_tlb_all();
++	}
++}
++
++static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
++{ 
++	long i = pud_index(address);
++
++	pud = pud + i;
++
++	if (after_bootmem && pud_val(*pud)) {
++		phys_pmd_update(pud, address, end);
++		return;
++	}
++
++	for (; i < PTRS_PER_PUD; pud++, i++) {
++		unsigned long paddr, pmd_phys;
++		pmd_t *pmd;
++
++		paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
++		if (paddr >= end)
++			break;
++
++		pmd = alloc_static_page(&pmd_phys);
++
++		spin_lock(&init_mm.page_table_lock);
++		*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();
++} 
++
++void __init xen_init_pt(void)
++{
++	unsigned long addr, *page;
++
++	/* Find the initial pte page that was built for us. */
++	page = (unsigned long *)xen_start_info->pt_base;
++	addr = page[pgd_index(__START_KERNEL_map)];
++	addr_to_page(addr, page);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	/* On Xen 3.0.2 and older we may need to explicitly specify _PAGE_USER
++	   in kernel PTEs. We check that here. */
++	if (HYPERVISOR_xen_version(XENVER_version, NULL) <= 0x30000) {
++		unsigned long *pg;
++		pte_t pte;
++
++		/* Mess with the initial mapping of page 0. It's not needed. */
++		BUILD_BUG_ON(__START_KERNEL <= __START_KERNEL_map);
++		addr = page[pud_index(__START_KERNEL_map)];
++		addr_to_page(addr, pg);
++		addr = pg[pmd_index(__START_KERNEL_map)];
++		addr_to_page(addr, pg);
++		pte.pte = pg[pte_index(__START_KERNEL_map)];
++		BUG_ON(!(pte.pte & _PAGE_PRESENT));
++
++		/* If _PAGE_USER isn't set, we obviously do not need it. */
++		if (pte.pte & _PAGE_USER) {
++			/* _PAGE_USER is needed, but is it set implicitly? */
++			pte.pte &= ~_PAGE_USER;
++			if ((HYPERVISOR_update_va_mapping(__START_KERNEL_map,
++							  pte, 0) != 0) ||
++			    !(pg[pte_index(__START_KERNEL_map)] & _PAGE_USER))
++				/* We need to explicitly specify _PAGE_USER. */
++				__kernel_page_user = _PAGE_USER;
++		}
++	}
++#endif
++
++	/* Construct mapping of initial pte page in our own directories. */
++	init_level4_pgt[pgd_index(__START_KERNEL_map)] = 
++		__pgd(__pa_symbol(level3_kernel_pgt) | _PAGE_TABLE);
++	memcpy(level3_kernel_pgt + pud_index(__START_KERNEL_map),
++	       page + pud_index(__START_KERNEL_map),
++	       (PTRS_PER_PUD - pud_index(__START_KERNEL_map))
++	       * sizeof(*level3_kernel_pgt));
++
++	__user_pgd(init_level4_pgt)[pgd_index(VSYSCALL_START)] =
++		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
++
++	early_make_page_readonly(init_level4_pgt,
++				 XENFEAT_writable_page_tables);
++	early_make_page_readonly(__user_pgd(init_level4_pgt),
++				 XENFEAT_writable_page_tables);
++	early_make_page_readonly(level3_kernel_pgt,
++				 XENFEAT_writable_page_tables);
++	early_make_page_readonly(level3_user_pgt,
++				 XENFEAT_writable_page_tables);
++
++	if (!xen_feature(XENFEAT_writable_page_tables)) {
++		xen_pgd_pin(__pa_symbol(init_level4_pgt));
++		xen_pgd_pin(__pa_symbol(__user_pgd(init_level4_pgt)));
++	}
++}
++
++static void __init extend_init_mapping(unsigned long tables_space)
++{
++	unsigned long va = __START_KERNEL_map;
++	unsigned long phys, addr, *pte_page;
++	pmd_t *pmd;
++	pte_t *pte, new_pte;
++	unsigned long *page = (unsigned long *)init_level4_pgt;
++
++	addr = page[pgd_index(va)];
++	addr_to_page(addr, page);
++	addr = page[pud_index(va)];
++	addr_to_page(addr, page);
++
++	/* Kill mapping of low 1MB. */
++	while (va < (unsigned long)&_text) {
++		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++			BUG();
++		va += PAGE_SIZE;
++	}
++
++	/* Ensure init mappings cover kernel text/data and initial tables. */
++	while (va < (__START_KERNEL_map
++		     + (start_pfn << PAGE_SHIFT)
++		     + tables_space)) {
++		if (!(pmd_index(va) | pte_index(va))) {
++			pud_t *pud;
++
++			page = (unsigned long *)init_level4_pgt;
++			addr = page[pgd_index(va)];
++			addr_to_page(addr, page);
++			pud = (pud_t *)&page[pud_index(va)];
++			if (pud_none(*pud)) {
++				page = alloc_static_page(&phys);
++				early_make_page_readonly(
++					page, XENFEAT_writable_page_tables);
++				set_pud(pud, __pud(phys | _KERNPG_TABLE));
++			} else {
++				addr = page[pud_index(va)];
++				addr_to_page(addr, page);
++			}
++		}
++		pmd = (pmd_t *)&page[pmd_index(va)];
++		if (pmd_none(*pmd)) {
++			pte_page = alloc_static_page(&phys);
++			early_make_page_readonly(
++				pte_page, XENFEAT_writable_page_tables);
++			set_pmd(pmd, __pmd(phys | _KERNPG_TABLE));
++		} else {
++			addr = page[pmd_index(va)];
++			addr_to_page(addr, pte_page);
++		}
++		pte = (pte_t *)&pte_page[pte_index(va)];
++		if (pte_none(*pte)) {
++			new_pte = pfn_pte(
++				(va - __START_KERNEL_map) >> PAGE_SHIFT, 
++				__pgprot(_KERNPG_TABLE));
++			xen_l1_entry_update(pte, new_pte);
++		}
++		va += PAGE_SIZE;
++	}
++
++	/* Finally, blow away any spurious initial mappings. */
++	while (1) {
++		if (!(pmd_index(va) | pte_index(va))) {
++			page = (unsigned long *)init_level4_pgt;
++			addr = page[pgd_index(va)];
++			addr_to_page(addr, page);
++			if (pud_none(((pud_t *)page)[pud_index(va)]))
++				break;
++			addr = page[pud_index(va)];
++			addr_to_page(addr, page);
++		}
++		pmd = (pmd_t *)&page[pmd_index(va)];
++		if (pmd_none(*pmd))
++			break;
++		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
++			BUG();
++		va += PAGE_SIZE;
++	}
++}
++
++static void __init find_early_table_space(unsigned long end)
++{
++	unsigned long puds, pmds, ptes, tables;
++
++	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
++	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
++	ptes = (end + PTE_SIZE - 1) >> PAGE_SHIFT;
++
++	tables = round_up(puds * 8, PAGE_SIZE) + 
++		round_up(pmds * 8, PAGE_SIZE) + 
++		round_up(ptes * 8, PAGE_SIZE); 
++
++	extend_init_mapping(tables);
++
++	table_start = start_pfn;
++	table_end = table_start + (tables>>PAGE_SHIFT);
++
++	early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
++		end, table_start << PAGE_SHIFT,
++		(table_start << PAGE_SHIFT) + tables);
++}
++
++static void xen_finish_init_mapping(void)
++{
++	unsigned long i, start, end;
++
++	/* Re-vector virtual addresses pointing into the initial
++	   mapping to the just-established permanent ones. */
++	xen_start_info = __va(__pa(xen_start_info));
++	xen_start_info->pt_base = (unsigned long)
++		__va(__pa(xen_start_info->pt_base));
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		phys_to_machine_mapping =
++			__va(__pa(xen_start_info->mfn_list));
++		xen_start_info->mfn_list = (unsigned long)
++			phys_to_machine_mapping;
++	}
++	if (xen_start_info->mod_start)
++		xen_start_info->mod_start = (unsigned long)
++			__va(__pa(xen_start_info->mod_start));
++
++	/* Destroy the Xen-created mappings beyond the kernel image as
++	 * well as the temporary mappings created above. Prevents
++	 * overlap with modules area (if init mapping is very big).
++	 */
++	start = PAGE_ALIGN((unsigned long)_end);
++	end   = __START_KERNEL_map + (table_end << PAGE_SHIFT);
++	for (; start < end; start += PAGE_SIZE)
++		if (HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0))
++			BUG();
++
++	/* Allocate pte's for initial fixmaps from 'start_pfn' allocator. */
++	table_end = ~0UL;
++
++	/*
++	 * Prefetch pte's for the bt_ioremap() area. It gets used before the
++	 * boot-time allocator is online, so allocate-on-demand would fail.
++	 */
++	for (i = FIX_BTMAP_END; i <= FIX_BTMAP_BEGIN; i++)
++		__set_fixmap(i, 0, __pgprot(0));
++
++	/* Switch to the real shared_info page, and clear the dummy page. */
++	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
++	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++	memset(empty_zero_page, 0, sizeof(empty_zero_page));
++
++	/* Set up mapping of lowest 1MB of physical memory. */
++	for (i = 0; i < NR_FIX_ISAMAPS; i++)
++		if (is_initial_xendomain())
++			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
++		else
++			__set_fixmap(FIX_ISAMAP_BEGIN - i,
++				     virt_to_mfn(empty_zero_page)
++				     << PAGE_SHIFT,
++				     PAGE_KERNEL_RO);
++
++	/* Disable the 'start_pfn' allocator. */
++	table_end = start_pfn;
++}
++
++/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
++   This runs before bootmem is initialized and gets pages directly from the 
++   physical memory. To access them they are temporarily mapped. */
++void __meminit init_memory_mapping(unsigned long start, unsigned long end)
++{ 
++	unsigned long next;
++
++	Dprintk("init_memory_mapping\n");
++
++	/* 
++	 * Find space for the kernel direct mapping tables.
++	 * Later we should allocate these tables in the local node of the memory
++	 * mapped.  Unfortunately this is done currently before the nodes are 
++	 * discovered.
++	 */
++	if (!after_bootmem)
++		find_early_table_space(end);
++
++	start = (unsigned long)__va(start);
++	end = (unsigned long)__va(end);
++
++	for (; start < end; start = next) {
++		unsigned long pud_phys; 
++		pgd_t *pgd = pgd_offset_k(start);
++		pud_t *pud;
++
++		if (after_bootmem)
++			pud = pud_offset(pgd, start & PGDIR_MASK);
++		else
++			pud = alloc_static_page(&pud_phys);
++		next = start + PGDIR_SIZE;
++		if (next > end) 
++			next = end; 
++		phys_pud_init(pud, __pa(start), __pa(next));
++		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) {
++		BUG_ON(start_pfn != table_end);
++		xen_finish_init_mapping();
++	}
++
++	__flush_tlb_all();
++}
++
++void __cpuinit zap_low_mappings(int cpu)
++{
++	/* this is not required for Xen */
++#if 0
++	swap_low_mappings();
++#endif
++}
++
++/* Compute zone sizes for the DMA and DMA32 zones in a node. */
++__init void
++size_zones(unsigned long *z, unsigned long *h,
++	   unsigned long start_pfn, unsigned long end_pfn)
++{
++ 	int i;
++ 	unsigned long w;
++
++ 	for (i = 0; i < MAX_NR_ZONES; i++)
++ 		z[i] = 0;
++
++ 	if (start_pfn < MAX_DMA_PFN)
++ 		z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
++ 	if (start_pfn < MAX_DMA32_PFN) {
++ 		unsigned long dma32_pfn = MAX_DMA32_PFN;
++ 		if (dma32_pfn > end_pfn)
++ 			dma32_pfn = end_pfn;
++ 		z[ZONE_DMA32] = dma32_pfn - start_pfn;
++ 	}
++ 	z[ZONE_NORMAL] = end_pfn - start_pfn;
++
++ 	/* Remove lower zones from higher ones. */
++ 	w = 0;
++ 	for (i = 0; i < MAX_NR_ZONES; i++) {
++ 		if (z[i])
++ 			z[i] -= w;
++ 	        w += z[i];
++	}
++
++	/* Compute holes */
++	w = start_pfn;
++	for (i = 0; i < MAX_NR_ZONES; i++) {
++		unsigned long s = w;
++		w += z[i];
++		h[i] = e820_hole_size(s, w);
++	}
++
++	/* Add the space pace needed for mem_map to the holes too. */
++	for (i = 0; i < MAX_NR_ZONES; i++)
++		h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
++
++	/* The 16MB DMA zone has the kernel and other misc mappings.
++ 	   Account them too */
++	if (h[ZONE_DMA]) {
++		h[ZONE_DMA] += dma_reserve;
++		if (h[ZONE_DMA] >= z[ZONE_DMA]) {
++			printk(KERN_WARNING
++				"Kernel too large and filling up ZONE_DMA?\n");
++			h[ZONE_DMA] = z[ZONE_DMA];
++		}
++	}
++}
++
++#ifndef CONFIG_NUMA
++void __init paging_init(void)
++{
++	unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
++
++	memory_present(0, 0, end_pfn);
++	sparse_init();
++	size_zones(zones, holes, 0, end_pfn);
++	free_area_init_node(0, NODE_DATA(0), zones,
++			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
++
++	init_mm.context.pinned = 1;
++}
++#endif
++
++/* Unmap a kernel mapping if it exists. This is useful to avoid prefetches
++   from the CPU leading to inconsistent cache lines. address and size
++   must be aligned to 2MB boundaries. 
++   Does nothing when the mapping doesn't exist. */
++void __init clear_kernel_mapping(unsigned long address, unsigned long size) 
++{
++	unsigned long end = address + size;
++
++	BUG_ON(address & ~LARGE_PAGE_MASK);
++	BUG_ON(size & ~LARGE_PAGE_MASK); 
++	
++	for (; address < end; address += LARGE_PAGE_SIZE) { 
++		pgd_t *pgd = pgd_offset_k(address);
++		pud_t *pud;
++		pmd_t *pmd;
++		if (pgd_none(*pgd))
++			continue;
++		pud = pud_offset(pgd, address);
++		if (pud_none(*pud))
++			continue; 
++		pmd = pmd_offset(pud, address);
++		if (!pmd || pmd_none(*pmd))
++			continue; 
++		if (0 == (__pmd_val(*pmd) & _PAGE_PSE)) {
++			/* Could handle this, but it should not happen currently. */
++			printk(KERN_ERR 
++	       "clear_kernel_mapping: mapping has been split. will leak memory\n"); 
++			pmd_ERROR(*pmd); 
++		}
++		set_pmd(pmd, __pmd(0)); 		
++	}
++	__flush_tlb_all();
++} 
++
++/*
++ * Memory hotplug specific functions
++ */
++void online_page(struct page *page)
++{
++	ClearPageReserved(page);
++	init_page_count(page);
++	__free_page(page);
++	totalram_pages++;
++	num_physpages++;
++}
++
++#ifdef CONFIG_MEMORY_HOTPLUG
++/*
++ * XXX: memory_add_physaddr_to_nid() is to find node id from physical address
++ *	via probe interface of sysfs. If acpi notifies hot-add event, then it
++ *	can tell node id by searching dsdt. But, probe interface doesn't have
++ *	node id. So, return 0 as node id at this time.
++ */
++#ifdef CONFIG_NUMA
++int memory_add_physaddr_to_nid(u64 start)
++{
++	return 0;
++}
++#endif
++
++/*
++ * Memory is added always to NORMAL zone. This means you will never get
++ * additional DMA/DMA32 memory.
++ */
++int arch_add_memory(int nid, u64 start, u64 size)
++{
++	struct pglist_data *pgdat = NODE_DATA(nid);
++	struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
++	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long nr_pages = size >> PAGE_SHIFT;
++	int ret;
++
++	ret = __add_pages(zone, start_pfn, nr_pages);
++	if (ret)
++		goto error;
++
++	init_memory_mapping(start, (start + size -1));
++
++	return ret;
++error:
++	printk("%s: Problem encountered in __add_pages!\n", __func__);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(arch_add_memory);
++
++int remove_memory(u64 start, u64 size)
++{
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(remove_memory);
++
++#else /* CONFIG_MEMORY_HOTPLUG */
++/*
++ * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
++ * just online the pages.
++ */
++int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
++{
++	int err = -EIO;
++	unsigned long pfn;
++	unsigned long total = 0, mem = 0;
++	for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
++		if (pfn_valid(pfn)) {
++			online_page(pfn_to_page(pfn));
++			err = 0;
++			mem++;
++		}
++		total++;
++	}
++	if (!err) {
++		z->spanned_pages += total;
++		z->present_pages += mem;
++		z->zone_pgdat->node_spanned_pages += total;
++		z->zone_pgdat->node_present_pages += mem;
++	}
++	return err;
++}
++#endif /* CONFIG_MEMORY_HOTPLUG */
++
++static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
++			 kcore_vsyscall;
++
++void __init mem_init(void)
++{
++	long codesize, reservedpages, datasize, initsize;
++	unsigned long pfn;
++
++	pci_iommu_alloc();
++
++	/* How many end-of-memory variables you have, grandma! */
++	max_low_pfn = end_pfn;
++	max_pfn = end_pfn;
++	num_physpages = end_pfn;
++	high_memory = (void *) __va(end_pfn * PAGE_SIZE);
++
++	/* clear the zero-page */
++	memset(empty_zero_page, 0, PAGE_SIZE);
++
++	reservedpages = 0;
++
++	/* this will put all low memory onto the freelists */
++#ifdef CONFIG_NUMA
++	totalram_pages = numa_free_all_bootmem();
++#else
++	totalram_pages = free_all_bootmem();
++#endif
++	/* XEN: init and count pages outside initial allocation. */
++	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
++		ClearPageReserved(pfn_to_page(pfn));
++		init_page_count(pfn_to_page(pfn));
++		totalram_pages++;
++	}
++	reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
++
++	after_bootmem = 1;
++
++	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
++	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
++	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
++
++	/* Register memory areas for /proc/kcore */
++	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
++	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, 
++		   VMALLOC_END-VMALLOC_START);
++	kclist_add(&kcore_kernel, &_stext, _end - _stext);
++	kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN);
++	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 
++				 VSYSCALL_END - VSYSCALL_START);
++
++	printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
++		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
++		end_pfn << (PAGE_SHIFT-10),
++		codesize >> 10,
++		reservedpages << (PAGE_SHIFT-10),
++		datasize >> 10,
++		initsize >> 10);
++
++#ifndef CONFIG_XEN
++#ifdef CONFIG_SMP
++	/*
++	 * Sync boot_level4_pgt mappings with the init_level4_pgt
++	 * except for the low identity mappings which are already zapped
++	 * in init_level4_pgt. This sync-up is essential for AP's bringup
++	 */
++	memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t));
++#endif
++#endif
++}
++
++void free_init_pages(char *what, unsigned long begin, unsigned long end)
++{
++	unsigned long addr;
++
++	if (begin >= end)
++		return;
++
++	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
++	for (addr = begin; addr < end; addr += PAGE_SIZE) {
++		ClearPageReserved(virt_to_page(addr));
++		init_page_count(virt_to_page(addr));
++		memset((void *)(addr & ~(PAGE_SIZE-1)),
++		       POISON_FREE_INITMEM, PAGE_SIZE); 
++		if (addr >= __START_KERNEL_map) {
++			/* make_readonly() reports all kernel addresses. */
++			__make_page_writable(__va(__pa(addr)));
++			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
++				pgd_t *pgd = pgd_offset_k(addr);
++				pud_t *pud = pud_offset(pgd, addr);
++				pmd_t *pmd = pmd_offset(pud, addr);
++				pte_t *pte = pte_offset_kernel(pmd, addr);
++
++				xen_l1_entry_update(pte, __pte(0)); /* fallback */
++			}
++		}
++		free_page(addr);
++		totalram_pages++;
++	}
++}
++
++void free_initmem(void)
++{
++	memset(__initdata_begin, POISON_FREE_INITDATA,
++		__initdata_end - __initdata_begin);
++	free_init_pages("unused kernel memory",
++			(unsigned long)(&__init_begin),
++			(unsigned long)(&__init_end));
++}
++
++#ifdef CONFIG_DEBUG_RODATA
++
++void mark_rodata_ro(void)
++{
++	unsigned long addr = (unsigned long)__start_rodata;
++
++	for (; addr < (unsigned long)__end_rodata; addr += PAGE_SIZE)
++		change_page_attr_addr(addr, 1, PAGE_KERNEL_RO);
++
++	printk ("Write protecting the kernel read-only data: %luk\n",
++			(__end_rodata - __start_rodata) >> 10);
++
++	/*
++	 * change_page_attr_addr() requires a global_flush_tlb() call after it.
++	 * We do this after the printk so that if something went wrong in the
++	 * change, the printk gets out at least to give a better debug hint
++	 * of who is the culprit.
++	 */
++	global_flush_tlb();
++}
++#endif
++
++#ifdef CONFIG_BLK_DEV_INITRD
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++	free_init_pages("initrd memory", start, end);
++}
++#endif
++
++void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
++{ 
++	/* Should check here against the e820 map to avoid double free */ 
++#ifdef CONFIG_NUMA
++	int nid = phys_to_nid(phys);
++  	reserve_bootmem_node(NODE_DATA(nid), phys, len);
++#else       		
++	reserve_bootmem(phys, len);    
++#endif
++	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
++		dma_reserve += len / PAGE_SIZE;
++}
++
++int kern_addr_valid(unsigned long addr) 
++{ 
++	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
++       pgd_t *pgd;
++       pud_t *pud;
++       pmd_t *pmd;
++       pte_t *pte;
++
++	if (above != 0 && above != -1UL)
++		return 0; 
++	
++	pgd = pgd_offset_k(addr);
++	if (pgd_none(*pgd))
++		return 0;
++
++	pud = pud_offset(pgd, addr);
++	if (pud_none(*pud))
++		return 0; 
++
++	pmd = pmd_offset(pud, addr);
++	if (pmd_none(*pmd))
++		return 0;
++	if (pmd_large(*pmd))
++		return pfn_valid(pmd_pfn(*pmd));
++
++	pte = pte_offset_kernel(pmd, addr);
++	if (pte_none(*pte))
++		return 0;
++	return pfn_valid(pte_pfn(*pte));
++}
++
++#ifdef CONFIG_SYSCTL
++#include <linux/sysctl.h>
++
++extern int exception_trace, page_fault_trace;
++
++static ctl_table debug_table2[] = {
++	{ 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,
++	  proc_dointvec },
++	{ 0, }
++}; 
++
++static ctl_table debug_root_table2[] = { 
++	{ .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, 
++	   .child = debug_table2 }, 
++	{ 0 }, 
++}; 
++
++static __init int x8664_sysctl_init(void)
++{ 
++	register_sysctl_table(debug_root_table2, 1);
++	return 0;
++}
++__initcall(x8664_sysctl_init);
++#endif
++
++/* A pseudo VMAs to allow ptrace access for the vsyscall page.   This only
++   covers the 64bit vsyscall page now. 32bit has a real VMA now and does
++   not need special handling anymore. */
++
++static struct vm_area_struct gate_vma = {
++	.vm_start = VSYSCALL_START,
++	.vm_end = VSYSCALL_END,
++	.vm_page_prot = PAGE_READONLY
++};
++
++struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
++{
++#ifdef CONFIG_IA32_EMULATION
++	if (test_tsk_thread_flag(tsk, TIF_IA32))
++		return NULL;
++#endif
++	return &gate_vma;
++}
++
++int in_gate_area(struct task_struct *task, unsigned long addr)
++{
++	struct vm_area_struct *vma = get_gate_vma(task);
++	if (!vma)
++		return 0;
++	return (addr >= vma->vm_start) && (addr < vma->vm_end);
++}
++
++/* Use this when you have no reliable task/vma, typically from interrupt
++ * context.  It is less reliable than using the task's vma and may give
++ * false positives.
++ */
++int in_gate_area_no_task(unsigned long addr)
++{
++	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,508 @@
++/* 
++ * Copyright 2002 Andi Kleen, SuSE Labs. 
++ * Thanks to Ben LaHaise for precious feedback.
++ */ 
++
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/highmem.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++#include <asm/tlbflush.h>
++#include <asm/io.h>
++
++#ifdef CONFIG_XEN
++#include <asm/pgalloc.h>
++#include <asm/mmu_context.h>
++
++LIST_HEAD(mm_unpinned);
++DEFINE_SPINLOCK(mm_unpinned_lock);
++
++static void _pin_lock(struct mm_struct *mm, int lock) {
++	if (lock)
++		spin_lock(&mm->page_table_lock);
++#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
++	/* While mm->page_table_lock protects us against insertions and
++	 * removals of higher level page table pages, it doesn't protect
++	 * against updates of pte-s. Such updates, however, require the
++	 * pte pages to be in consistent state (unpinned+writable or
++	 * pinned+readonly). The pinning and attribute changes, however
++	 * cannot be done atomically, which is why such updates must be
++	 * prevented from happening concurrently.
++	 * Note that no pte lock can ever elsewhere be acquired nesting
++	 * with an already acquired one in the same mm, or with the mm's
++	 * page_table_lock already acquired, as that would break in the
++	 * non-split case (where all these are actually resolving to the
++	 * one page_table_lock). Thus acquiring all of them here is not
++	 * going to result in dead locks, and the order of acquires
++	 * doesn't matter.
++	 */
++	{
++		pgd_t *pgd = mm->pgd;
++		unsigned g;
++
++		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++			pud_t *pud;
++			unsigned u;
++
++			if (pgd_none(*pgd))
++				continue;
++			pud = pud_offset(pgd, 0);
++			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++				pmd_t *pmd;
++				unsigned m;
++
++				if (pud_none(*pud))
++					continue;
++				pmd = pmd_offset(pud, 0);
++				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++					spinlock_t *ptl;
++
++					if (pmd_none(*pmd))
++						continue;
++					ptl = pte_lockptr(0, pmd);
++					if (lock)
++						spin_lock(ptl);
++					else
++						spin_unlock(ptl);
++				}
++			}
++		}
++	}
++#endif
++	if (!lock)
++		spin_unlock(&mm->page_table_lock);
++}
++#define pin_lock(mm) _pin_lock(mm, 1)
++#define pin_unlock(mm) _pin_lock(mm, 0)
++
++#define PIN_BATCH 8
++static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
++
++static inline unsigned int mm_walk_set_prot(void *pt, pgprot_t flags,
++                                            unsigned int cpu, unsigned int seq)
++{
++	struct page *page = virt_to_page(pt);
++	unsigned long pfn = page_to_pfn(page);
++
++	MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++		(unsigned long)__va(pfn << PAGE_SHIFT),
++		pfn_pte(pfn, flags), 0);
++	if (unlikely(++seq == PIN_BATCH)) {
++		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++	                                                PIN_BATCH, NULL)))
++			BUG();
++		seq = 0;
++	}
++
++	return seq;
++}
++
++static void mm_walk(struct mm_struct *mm, pgprot_t flags)
++{
++	pgd_t       *pgd;
++	pud_t       *pud;
++	pmd_t       *pmd;
++	pte_t       *pte;
++	int          g,u,m;
++	unsigned int cpu, seq;
++	multicall_entry_t *mcl;
++
++	pgd = mm->pgd;
++	cpu = get_cpu();
++
++	/*
++	 * Cannot iterate up to USER_PTRS_PER_PGD as these pagetables may not
++	 * be the 'current' task's pagetables (e.g., current may be 32-bit,
++	 * but the pagetables may be for a 64-bit task).
++	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
++	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
++	 */
++	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++		if (pgd_none(*pgd))
++			continue;
++		pud = pud_offset(pgd, 0);
++		if (PTRS_PER_PUD > 1) /* not folded */ 
++			seq = mm_walk_set_prot(pud,flags,cpu,seq);
++		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++			if (pud_none(*pud))
++				continue;
++			pmd = pmd_offset(pud, 0);
++			if (PTRS_PER_PMD > 1) /* not folded */ 
++				seq = mm_walk_set_prot(pmd,flags,cpu,seq);
++			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++				if (pmd_none(*pmd))
++					continue;
++				pte = pte_offset_kernel(pmd,0);
++				seq = mm_walk_set_prot(pte,flags,cpu,seq);
++			}
++		}
++	}
++
++	mcl = per_cpu(pb_mcl, cpu);
++	if (unlikely(seq > PIN_BATCH - 2)) {
++		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
++			BUG();
++		seq = 0;
++	}
++	MULTI_update_va_mapping(mcl + seq,
++	       (unsigned long)__user_pgd(mm->pgd),
++	       pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, flags),
++	       0);
++	MULTI_update_va_mapping(mcl + seq + 1,
++	       (unsigned long)mm->pgd,
++	       pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, flags),
++	       UVMF_TLB_FLUSH);
++	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
++		BUG();
++
++	put_cpu();
++}
++
++void mm_pin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++
++	mm_walk(mm, PAGE_KERNEL_RO);
++	xen_pgd_pin(__pa(mm->pgd)); /* kernel */
++	xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
++	mm->context.pinned = 1;
++	spin_lock(&mm_unpinned_lock);
++	list_del(&mm->context.unpinned);
++	spin_unlock(&mm_unpinned_lock);
++
++	pin_unlock(mm);
++}
++
++void mm_unpin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++
++	xen_pgd_unpin(__pa(mm->pgd));
++	xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
++	mm_walk(mm, PAGE_KERNEL);
++	mm->context.pinned = 0;
++	spin_lock(&mm_unpinned_lock);
++	list_add(&mm->context.unpinned, &mm_unpinned);
++	spin_unlock(&mm_unpinned_lock);
++
++	pin_unlock(mm);
++}
++
++void mm_pin_all(void)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	/*
++	 * Allow uninterrupted access to the mm_unpinned list. We don't
++	 * actually take the mm_unpinned_lock as it is taken inside mm_pin().
++	 * All other CPUs must be at a safe point (e.g., in stop_machine
++	 * or offlined entirely).
++	 */
++	preempt_disable();
++	while (!list_empty(&mm_unpinned))	
++		mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
++				  context.unpinned));
++	preempt_enable();
++}
++
++void _arch_dup_mmap(struct mm_struct *mm)
++{
++	if (!mm->context.pinned)
++		mm_pin(mm);
++}
++
++void _arch_exit_mmap(struct mm_struct *mm)
++{
++	struct task_struct *tsk = current;
++
++	task_lock(tsk);
++
++	/*
++	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
++	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
++	 */
++	if (tsk->active_mm == mm) {
++		tsk->active_mm = &init_mm;
++		atomic_inc(&init_mm.mm_count);
++
++		switch_mm(mm, &init_mm, tsk);
++
++		atomic_dec(&mm->mm_count);
++		BUG_ON(atomic_read(&mm->mm_count) == 0);
++	}
++
++	task_unlock(tsk);
++
++	if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
++	     !mm->context.has_foreign_mappings )
++		mm_unpin(mm);
++}
++
++static void _pte_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	pte_free(page);
++}
++
++struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pte;
++
++	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++	if (pte) {
++		SetPageForeign(pte, _pte_free);
++		init_page_count(pte);
++	}
++	return pte;
++}
++
++void pte_free(struct page *pte)
++{
++	unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
++
++	if (!pte_write(*virt_to_ptep(va)))
++		if (HYPERVISOR_update_va_mapping(
++			va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0))
++			BUG();
++
++	ClearPageForeign(pte);
++	init_page_count(pte);
++
++	__free_page(pte);
++}
++#endif	/* CONFIG_XEN */
++
++pte_t *lookup_address(unsigned long address) 
++{ 
++	pgd_t *pgd = pgd_offset_k(address);
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++	if (pgd_none(*pgd))
++		return NULL;
++	pud = pud_offset(pgd, address);
++	if (!pud_present(*pud))
++		return NULL; 
++	pmd = pmd_offset(pud, address);
++	if (!pmd_present(*pmd))
++		return NULL; 
++	if (pmd_large(*pmd))
++		return (pte_t *)pmd;
++	pte = pte_offset_kernel(pmd, address);
++	if (pte && !pte_present(*pte))
++		pte = NULL; 
++	return pte;
++} 
++
++static struct page *split_large_page(unsigned long address, pgprot_t prot,
++				     pgprot_t ref_prot)
++{ 
++	int i; 
++	unsigned long addr;
++	struct page *base = alloc_pages(GFP_KERNEL, 0);
++	pte_t *pbase;
++	if (!base) 
++		return NULL;
++	/*
++	 * page_private is used to track the number of entries in
++	 * the page table page have non standard attributes.
++	 */
++	SetPagePrivate(base);
++	page_private(base) = 0;
++
++	address = __pa(address);
++	addr = address & LARGE_PAGE_MASK; 
++	pbase = (pte_t *)page_address(base);
++	for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
++		pbase[i] = pfn_pte(addr >> PAGE_SHIFT, 
++				   addr == address ? prot : ref_prot);
++	}
++	return base;
++} 
++
++
++static void flush_kernel_map(void *address) 
++{
++	if (0 && address && cpu_has_clflush) {
++		/* is this worth it? */ 
++		int i;
++		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
++			asm volatile("clflush (%0)" :: "r" (address + i)); 
++	} else
++		asm volatile("wbinvd":::"memory"); 
++	if (address)
++		__flush_tlb_one(address);
++	else
++		__flush_tlb_all();
++}
++
++
++static inline void flush_map(unsigned long address)
++{	
++	on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
++}
++
++static struct page *deferred_pages; /* protected by init_mm.mmap_sem */
++
++static inline void save_page(struct page *fpage)
++{
++	fpage->lru.next = (struct list_head *)deferred_pages;
++	deferred_pages = fpage;
++}
++
++/* 
++ * No more special protections in this 2/4MB area - revert to a
++ * large page again. 
++ */
++static void revert_page(unsigned long address, pgprot_t ref_prot)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t large_pte;
++
++	pgd = pgd_offset_k(address);
++	BUG_ON(pgd_none(*pgd));
++	pud = pud_offset(pgd,address);
++	BUG_ON(pud_none(*pud));
++	pmd = pmd_offset(pud, address);
++	BUG_ON(__pmd_val(*pmd) & _PAGE_PSE);
++	pgprot_val(ref_prot) |= _PAGE_PSE;
++	large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
++	set_pte((pte_t *)pmd, large_pte);
++}      
++
++static int
++__change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
++				   pgprot_t ref_prot)
++{ 
++	pte_t *kpte; 
++	struct page *kpte_page;
++	unsigned kpte_flags;
++	pgprot_t ref_prot2;
++	kpte = lookup_address(address);
++	if (!kpte) return 0;
++	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
++	kpte_flags = pte_val(*kpte); 
++	if (pgprot_val(prot) != pgprot_val(ref_prot)) { 
++		if ((kpte_flags & _PAGE_PSE) == 0) { 
++			set_pte(kpte, pfn_pte(pfn, prot));
++		} else {
++ 			/*
++			 * split_large_page will take the reference for this
++			 * change_page_attr on the split page.
++ 			 */
++
++			struct page *split;
++			ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE));
++
++			split = split_large_page(address, prot, ref_prot2);
++			if (!split)
++				return -ENOMEM;
++			set_pte(kpte,mk_pte(split, ref_prot2));
++			kpte_page = split;
++		}	
++		page_private(kpte_page)++;
++	} else if ((kpte_flags & _PAGE_PSE) == 0) { 
++		set_pte(kpte, pfn_pte(pfn, ref_prot));
++		BUG_ON(page_private(kpte_page) == 0);
++		page_private(kpte_page)--;
++	} else
++		BUG();
++
++	/* on x86-64 the direct mapping set at boot is not using 4k pages */
++	/*
++	 * ..., but the XEN guest kernels (currently) do:
++	 * If the pte was reserved, it means it was created at boot
++	 * time (not via split_large_page) and in turn we must not
++	 * replace it with a large page.
++	 */
++#ifndef CONFIG_XEN
++ 	BUG_ON(PageReserved(kpte_page));
++#else
++	if (PageReserved(kpte_page))
++		return 0;
++#endif
++
++	if (page_private(kpte_page) == 0) {
++		save_page(kpte_page);
++		revert_page(address, ref_prot);
++	}
++	return 0;
++} 
++
++/*
++ * Change the page attributes of an page in the linear mapping.
++ *
++ * This should be used when a page is mapped with a different caching policy
++ * than write-back somewhere - some CPUs do not like it when mappings with
++ * different caching policies exist. This changes the page attributes of the
++ * in kernel linear mapping too.
++ * 
++ * The caller needs to ensure that there are no conflicting mappings elsewhere.
++ * This function only deals with the kernel linear map.
++ * 
++ * Caller must call global_flush_tlb() after this.
++ */
++int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
++{
++	int err = 0; 
++	int i; 
++
++	down_write(&init_mm.mmap_sem);
++	for (i = 0; i < numpages; i++, address += PAGE_SIZE) {
++		unsigned long pfn = __pa(address) >> PAGE_SHIFT;
++
++		err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
++		if (err) 
++			break; 
++		/* Handle kernel mapping too which aliases part of the
++		 * lowmem */
++		if (__pa(address) < KERNEL_TEXT_SIZE) {
++			unsigned long addr2;
++			pgprot_t prot2 = prot;
++			addr2 = __START_KERNEL_map + __pa(address);
++ 			pgprot_val(prot2) &= ~_PAGE_NX;
++			err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC);
++		} 
++	} 	
++	up_write(&init_mm.mmap_sem); 
++	return err;
++}
++
++/* Don't call this for MMIO areas that may not have a mem_map entry */
++int change_page_attr(struct page *page, int numpages, pgprot_t prot)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++	return change_page_attr_addr(addr, numpages, prot);
++}
++
++void global_flush_tlb(void)
++{ 
++	struct page *dpage;
++
++	down_read(&init_mm.mmap_sem);
++	dpage = xchg(&deferred_pages, NULL);
++	up_read(&init_mm.mmap_sem);
++
++	flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0);
++	while (dpage) {
++		struct page *tmp = dpage;
++		dpage = (struct page *)dpage->lru.next;
++		ClearPagePrivate(tmp);
++		__free_page(tmp);
++	} 
++} 
++
++EXPORT_SYMBOL(change_page_attr);
++EXPORT_SYMBOL(global_flush_tlb);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 08:45:56.000000000 +0100
+@@ -0,0 +1,910 @@
++/*
++ * 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 <xen/evtchn.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;
++	/* Used for saving/restoring MSI-X tables */
++	void __iomem *mask_base;
++	/* Store default pre-assigned irq */
++	unsigned int default_irq;
++};
++
++struct msi_pirq_entry {
++	struct list_head list;
++	int pirq;
++	int entry_nr;
++#ifdef CONFIG_PM
++	/* PM save area for MSIX address/data */
++	u32	address_hi_save;
++	u32	address_lo_save;
++	u32	data_save;
++#endif
++};
++
++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 = kzalloc(sizeof(struct msi_dev_list), GFP_ATOMIC);
++
++	/* Failed to allocate msi_dev structure */
++	if ( !ret ) {
++		spin_unlock_irqrestore(&msi_dev_lock, flags);
++		return NULL;
++	}
++
++	ret->dev = dev;
++	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);
++	/* See comments in msi_map_pirq_to_vector, input parameter pirq
++	 * mean irq number only if the device belongs to dom0 itself.
++	 */
++	unmap.pirq = (unmap.domid != DOMID_SELF)
++		? pirq : evtchn_get_xen_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;
++
++	if (unmap.domid == DOMID_SELF)
++		evtchn_map_pirq(pirq, 0);
++
++	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 < 0 ? -1 : evtchn_get_xen_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;
++	/* This happens when MSI support is not enabled in Xen. */
++	if (rc == 0 && map_irq.pirq < 0)
++		return -ENOSYS;
++
++	BUG_ON(map_irq.pirq <= 0);
++
++	/* If mapping of this particular MSI is on behalf of another domain,
++	 * we do not need to get an irq in dom0. This also implies:
++	 * dev->irq in dom0 will be 'Xen pirq' if this device belongs to
++	 * to another domain, and will be 'Linux irq' if it belongs to dom0.
++	 */
++	return ((domid != DOMID_SELF) ?
++		map_irq.pirq : evtchn_map_pirq(pirq, 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, i = 0;
++	u16 control;
++	struct pci_cap_saved_state *save_state;
++	u32 *cap;
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	if (pos <= 0 || dev->no_msi)
++		return 0;
++
++	pci_read_config_word(dev, msi_control_reg(pos), &control);
++	if (!(control & PCI_MSI_FLAGS_ENABLE))
++		return 0;
++
++	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
++		GFP_KERNEL);
++	if (!save_state) {
++		printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
++		return -ENOMEM;
++	}
++	cap = &save_state->data[0];
++
++	pci_read_config_dword(dev, pos, &cap[i++]);
++	control = cap[0] >> 16;
++	pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
++	if (control & PCI_MSI_FLAGS_64BIT) {
++		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
++		pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
++	} else
++		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
++	if (control & PCI_MSI_FLAGS_MASKBIT)
++		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
++	save_state->cap_nr = PCI_CAP_ID_MSI;
++	pci_add_saved_cap(dev, save_state);
++	return 0;
++}
++
++void pci_restore_msi_state(struct pci_dev *dev)
++{
++	int i = 0, pos;
++	u16 control;
++	struct pci_cap_saved_state *save_state;
++	u32 *cap;
++
++	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	if (!save_state || pos <= 0)
++		return;
++	cap = &save_state->data[0];
++
++	control = cap[i++] >> 16;
++	pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
++	if (control & PCI_MSI_FLAGS_64BIT) {
++		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
++		pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
++	} else
++		pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
++	if (control & PCI_MSI_FLAGS_MASKBIT)
++		pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
++	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
++	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++	pci_remove_saved_cap(save_state);
++	kfree(save_state);
++}
++
++int pci_save_msix_state(struct pci_dev *dev)
++{
++	int pos;
++	u16 control;
++	struct pci_cap_saved_state *save_state;
++	unsigned long flags;
++	struct msi_dev_list *msi_dev_entry;
++	struct msi_pirq_entry *pirq_entry;
++	void __iomem *base;
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++	if (pos <= 0 || dev->no_msi)
++		return 0;
++
++	/* save the capability */
++	pci_read_config_word(dev, msi_control_reg(pos), &control);
++	if (!(control & PCI_MSIX_FLAGS_ENABLE))
++		return 0;
++
++	msi_dev_entry = get_msi_dev_pirq_list(dev);
++	/* If we failed to map the MSI-X table at pci_enable_msix,
++	 * We could not support saving them here.
++	 */
++	if (!(base = msi_dev_entry->mask_base))
++		return -ENOMEM;
++
++	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
++		GFP_KERNEL);
++	if (!save_state) {
++		printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
++		return -ENOMEM;
++	}
++	*((u16 *)&save_state->data[0]) = control;
++
++	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
++		int j;
++
++		/* save the table */
++		j = pirq_entry->entry_nr;
++		pirq_entry->address_lo_save =
++			readl(base + j * PCI_MSIX_ENTRY_SIZE +
++			      PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++		pirq_entry->address_hi_save =
++			readl(base + j * PCI_MSIX_ENTRY_SIZE +
++			      PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
++		pirq_entry->data_save =
++			readl(base + j * PCI_MSIX_ENTRY_SIZE +
++			      PCI_MSIX_ENTRY_DATA_OFFSET);
++	}
++	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++
++	save_state->cap_nr = PCI_CAP_ID_MSIX;
++	pci_add_saved_cap(dev, save_state);
++	return 0;
++}
++
++void pci_restore_msix_state(struct pci_dev *dev)
++{
++	u16 save;
++	int pos, j;
++	void __iomem *base;
++	struct pci_cap_saved_state *save_state;
++	unsigned long flags;
++	struct msi_dev_list *msi_dev_entry;
++	struct msi_pirq_entry *pirq_entry;
++
++	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
++	if (!save_state)
++		return;
++
++	save = *((u16 *)&save_state->data[0]);
++	pci_remove_saved_cap(save_state);
++	kfree(save_state);
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++	if (pos <= 0)
++		return;
++
++	msi_dev_entry = get_msi_dev_pirq_list(dev);
++	base = msi_dev_entry->mask_base;
++
++	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
++	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
++		/* route the table */
++		j = pirq_entry->entry_nr;
++		writel(pirq_entry->address_lo_save,
++			base + j * PCI_MSIX_ENTRY_SIZE +
++			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++		writel(pirq_entry->address_hi_save,
++			base + j * PCI_MSIX_ENTRY_SIZE +
++			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
++		writel(pirq_entry->data_save,
++			base + j * PCI_MSIX_ENTRY_SIZE +
++			PCI_MSIX_ENTRY_DATA_OFFSET);
++	}
++	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++
++	pci_write_config_word(dev, msi_control_reg(pos), save);
++	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;
++	u16 control;
++	int pirq, i, j, mapped, pos, nr_entries;
++	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;
++
++	pci_read_config_word(dev, msi_control_reg(pos), &control);
++	nr_entries = multi_msix_capable(control);
++	if (!msi_dev_entry->mask_base)
++		msi_dev_entry->mask_base = 
++			ioremap_nocache(table_base, nr_entries * PCI_MSIX_ENTRY_SIZE);
++
++	/* 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;
++	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
++
++	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 = evtchn_map_pirq(-1, dev->irq);
++		dev->msi_enabled = 1;
++		msi_dev_entry->default_irq = 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 )
++		msi_dev_entry->default_irq = 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;
++	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
++
++	if (!pci_msi_enable)
++		return;
++	if (!dev)
++		return;
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++	if (!is_initial_xendomain()) {
++		if (!(dev->msi_enabled)) {
++			printk(KERN_INFO "PCI: %s: Device did not enabled MSI.\n",
++			       pci_name(dev));
++			return;
++		}
++		evtchn_map_pirq(dev->irq, 0);
++		pci_frontend_disable_msi(dev);
++		dev->irq = msi_dev_entry->default_irq;
++		dev->msi_enabled = 0;
++		return;
++	}
++#endif
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	if (!pos)
++		return;
++
++	if (!(dev->msi_enabled)) {
++		printk(KERN_INFO "PCI: %s: Device did not enabled MSI.\n",
++		       pci_name(dev));
++		return;
++	}
++ 
++	pirq = dev->irq;
++	/* Restore dev->irq to its default pin-assertion vector */
++	dev->irq = msi_dev_entry->default_irq;
++	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;
++	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
++
++	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()) {
++		struct msi_pirq_entry *pirq_entry;
++		int ret, irq;
++
++		temp = dev->irq;
++		ret = pci_frontend_enable_msix(dev, entries, nvec);
++		if (ret) {
++			printk("get %x from pci_frontend_enable_msix\n", ret);
++			return ret;
++		}
++		dev->msix_enabled = 1;
++		msi_dev_entry->default_irq = temp;
++
++		for (i = 0; i < nvec; i++) {
++			int mapped = 0;
++
++			list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
++				if (pirq_entry->entry_nr == entries[i].entry) {
++					irq = pirq_entry->pirq;
++					BUG_ON(entries[i].vector != evtchn_get_xen_pirq(irq));
++					entries[i].vector = irq;
++					mapped = 1;
++					break;
++				}
++			}
++			if (mapped)
++				continue;
++			irq = evtchn_map_pirq(-1, entries[i].vector);
++			attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
++			entries[i].vector = irq;
++		}
++        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 )
++		msi_dev_entry->default_irq = 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;
++	if (!dev->msix_enabled) {
++		printk(KERN_INFO "PCI: %s: Device did not enabled MSI-X.\n",
++		       pci_name(dev));
++		return;
++	}
++
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++	if (!is_initial_xendomain()) {
++		struct msi_dev_list *msi_dev_entry;
++		struct msi_pirq_entry *pirq_entry, *tmp;
++
++		pci_frontend_disable_msix(dev);
++
++		msi_dev_entry = get_msi_dev_pirq_list(dev);
++		list_for_each_entry_safe(pirq_entry, tmp,
++		                         &msi_dev_entry->pirq_list_head, list) {
++			evtchn_map_pirq(pirq_entry->pirq, 0);
++			list_del(&pirq_entry->list);
++			kfree(pirq_entry);
++		}
++
++		dev->irq = msi_dev_entry->default_irq;
++		dev->msix_enabled = 0;
++		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))
++		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);
++	iounmap(msi_dev_entry->mask_base);
++	msi_dev_entry->mask_base = NULL;
++	dev->irq = msi_dev_entry->default_irq;
++}
++
++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
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/agp.h	2007-06-22 09:08:06.000000000 +0200
+@@ -0,0 +1,44 @@
++#ifndef AGP_H
++#define AGP_H 1
++
++#include <asm/pgtable.h>
++#include <asm/cacheflush.h>
++#include <asm/system.h>
++
++/* 
++ * Functions to keep the agpgart mappings coherent with the MMU.
++ * The GART gives the CPU a physical alias of pages in memory. The alias region is
++ * mapped uncacheable. Make sure there are no conflicting mappings
++ * with different cachability attributes for the same page. This avoids
++ * data corruption on some CPUs.
++ */
++
++/* Caller's responsibility to call global_flush_tlb() for
++ * performance reasons */
++#define map_page_into_agp(page) ( \
++	xen_create_contiguous_region((unsigned long)page_address(page), 0, 32) \
++	?: change_page_attr(page, 1, PAGE_KERNEL_NOCACHE))
++#define unmap_page_from_agp(page) ( \
++	xen_destroy_contiguous_region((unsigned long)page_address(page), 0), \
++	/* only a fallback: xen_destroy_contiguous_region uses PAGE_KERNEL */ \
++	change_page_attr(page, 1, PAGE_KERNEL))
++#define flush_agp_mappings() global_flush_tlb()
++
++/* Could use CLFLUSH here if the cpu supports it. But then it would
++   need to be called for each cacheline of the whole page so it may not be 
++   worth it. Would need a page for it. */
++#define flush_agp_cache() wbinvd()
++
++/* Convert a physical address to an address suitable for the GART. */
++#define phys_to_gart(x) phys_to_machine(x)
++#define gart_to_phys(x) machine_to_phys(x)
++
++/* GATT allocation. Returns/accepts GATT kernel virtual address. */
++#define alloc_gatt_pages(order)	({                                          \
++	char *_t; dma_addr_t _d;                                            \
++	_t = dma_alloc_coherent(NULL,PAGE_SIZE<<(order),&_d,GFP_KERNEL);    \
++	_t; })
++#define free_gatt_pages(table, order)	\
++	dma_free_coherent(NULL,PAGE_SIZE<<(order),(table),virt_to_bus(table))
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_32.h	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,166 @@
++#ifndef __ARCH_DESC_H
++#define __ARCH_DESC_H
++
++#include <asm/ldt.h>
++#include <asm/segment.h>
++
++#define CPU_16BIT_STACK_SIZE 1024
++
++#ifndef __ASSEMBLY__
++
++#include <linux/preempt.h>
++#include <linux/smp.h>
++
++#include <asm/mmu.h>
++
++extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
++
++DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
++
++struct Xgt_desc_struct {
++	unsigned short size;
++	unsigned long address __attribute__((packed));
++	unsigned short pad;
++} __attribute__ ((packed));
++
++extern struct Xgt_desc_struct idt_descr;
++DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
++
++
++static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
++{
++	return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
++}
++
++#define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
++#define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
++
++#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
++#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
++#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
++#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
++
++#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
++#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
++#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
++#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
++
++/*
++ * This is the ldt that every process will get unless we need
++ * something other than this.
++ */
++extern struct desc_struct default_ldt[];
++extern void set_intr_gate(unsigned int irq, void * addr);
++
++#define _set_tssldt_desc(n,addr,limit,type) \
++__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
++	"movw %w1,2(%2)\n\t" \
++	"rorl $16,%1\n\t" \
++	"movb %b1,4(%2)\n\t" \
++	"movb %4,5(%2)\n\t" \
++	"movb $0,6(%2)\n\t" \
++	"movb %h1,7(%2)\n\t" \
++	"rorl $16,%1" \
++	: "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
++
++#ifndef CONFIG_X86_NO_TSS
++static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
++{
++	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
++		offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
++}
++
++#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
++#endif
++
++static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
++{
++	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
++}
++
++#define LDT_entry_a(info) \
++	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
++
++#define LDT_entry_b(info) \
++	(((info)->base_addr & 0xff000000) | \
++	(((info)->base_addr & 0x00ff0000) >> 16) | \
++	((info)->limit & 0xf0000) | \
++	(((info)->read_exec_only ^ 1) << 9) | \
++	((info)->contents << 10) | \
++	(((info)->seg_not_present ^ 1) << 15) | \
++	((info)->seg_32bit << 22) | \
++	((info)->limit_in_pages << 23) | \
++	((info)->useable << 20) | \
++	0x7000)
++
++#define LDT_empty(info) (\
++	(info)->base_addr	== 0	&& \
++	(info)->limit		== 0	&& \
++	(info)->contents	== 0	&& \
++	(info)->read_exec_only	== 1	&& \
++	(info)->seg_32bit	== 0	&& \
++	(info)->limit_in_pages	== 0	&& \
++	(info)->seg_not_present	== 1	&& \
++	(info)->useable		== 0	)
++
++extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
++
++#if TLS_SIZE != 24
++# error update this code.
++#endif
++
++static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
++{
++#define C(i) if (HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), \
++					       *(u64 *)&t->tls_array[i])) \
++		BUG();
++	C(0); C(1); C(2);
++#undef C
++}
++
++static inline void clear_LDT(void)
++{
++	int cpu = get_cpu();
++
++	/*
++	 * NB. We load the default_ldt for lcall7/27 handling on demand, as
++	 * it slows down context switching. Noone uses it anyway.
++	 */
++	cpu = cpu;		/* XXX avoid compiler warning */
++	xen_set_ldt(NULL, 0);
++	put_cpu();
++}
++
++/*
++ * load one particular LDT into the current CPU
++ */
++static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
++{
++	void *segments = pc->ldt;
++	int count = pc->size;
++
++	if (likely(!count))
++		segments = NULL;
++
++	xen_set_ldt(segments, count);
++}
++
++static inline void load_LDT(mm_context_t *pc)
++{
++	int cpu = get_cpu();
++	load_LDT_nolock(pc, cpu);
++	put_cpu();
++}
++
++static inline unsigned long get_desc_base(unsigned long *desc)
++{
++	unsigned long base;
++	base = ((desc[0] >> 16)  & 0x0000ffff) |
++		((desc[1] << 16) & 0x00ff0000) |
++		(desc[1] & 0xff000000);
++	return base;
++}
++
++#endif /* !__ASSEMBLY__ */
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,155 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1998 Ingo Molnar
++ *
++ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ */
++
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
++
++/* used by vmalloc.c, vsyscall.lds.S.
++ *
++ * Leave one empty page between vmalloc'ed areas and
++ * the start of the fixmap.
++ */
++extern unsigned long __FIXADDR_TOP;
++
++#ifndef __ASSEMBLY__
++#include <linux/kernel.h>
++#include <asm/acpi.h>
++#include <asm/apicdef.h>
++#include <asm/page.h>
++#ifdef CONFIG_HIGHMEM
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#endif
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process. We allocate these special addresses
++ * from the end of virtual memory (0xfffff000) backwards.
++ * Also this lets us do fail-safe vmalloc(), we
++ * can guarantee that these special addresses and
++ * vmalloc()-ed addresses never overlap.
++ *
++ * these 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages. (or larger if used with an increment
++ * highger than 1) use fixmap_set(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++enum fixed_addresses {
++	FIX_HOLE,
++	FIX_VDSO,
++#ifdef CONFIG_X86_LOCAL_APIC
++	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
++#endif
++#ifdef CONFIG_X86_IO_APIC
++	FIX_IO_APIC_BASE_0,
++	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
++#endif
++#ifdef CONFIG_X86_VISWS_APIC
++	FIX_CO_CPU,	/* Cobalt timer */
++	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */ 
++	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
++	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
++#endif
++#ifdef CONFIG_X86_F00F_BUG
++	FIX_F00F_IDT,	/* Virtual mapping for IDT */
++#endif
++#ifdef CONFIG_X86_CYCLONE_TIMER
++	FIX_CYCLONE_TIMER, /*cyclone timer register*/
++#endif 
++#ifdef CONFIG_HIGHMEM
++	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
++	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
++#endif
++#ifdef CONFIG_ACPI
++	FIX_ACPI_BEGIN,
++	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
++#endif
++#ifdef CONFIG_PCI_MMCONFIG
++	FIX_PCIE_MCFG,
++#endif
++	FIX_SHARED_INFO,
++#define NR_FIX_ISAMAPS	256
++	FIX_ISAMAP_END,
++	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
++	__end_of_permanent_fixed_addresses,
++	/* temporary boot-time mappings, used before ioremap() is functional */
++#define NR_FIX_BTMAPS	16
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
++	FIX_WP_TEST,
++	__end_of_fixed_addresses
++};
++
++extern void set_fixaddr_top(unsigned long top);
++
++extern void __set_fixmap(enum fixed_addresses idx,
++					maddr_t phys, pgprot_t flags);
++
++#define set_fixmap(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL)
++/*
++ * Some hardware wants to get fixmapped without caching.
++ */
++#define set_fixmap_nocache(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++
++#define clear_fixmap(idx) \
++		__set_fixmap(idx, 0, __pgprot(0))
++
++#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
++
++#define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
++#define __FIXADDR_BOOT_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_START		(FIXADDR_TOP - __FIXADDR_SIZE)
++#define FIXADDR_BOOT_START	(FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
++
++#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
++#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
++
++extern void __this_fixmap_does_not_exist(void);
++
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without tranlation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++static __always_inline unsigned long fix_to_virt(const unsigned int idx)
++{
++	/*
++	 * this branch gets completely eliminated after inlining,
++	 * except when someone tries to use fixaddr indices in an
++	 * illegal way. (such as mixing up address types or using
++	 * out-of-range indices).
++	 *
++	 * If it doesn't get removed, the linker will complain
++	 * loudly with a reasonably clear error message..
++	 */
++	if (idx >= __end_of_fixed_addresses)
++		__this_fixmap_does_not_exist();
++
++        return __fix_to_virt(idx);
++}
++
++static inline unsigned long virt_to_fix(const unsigned long vaddr)
++{
++	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
++	return __virt_to_fix(vaddr);
++}
++
++#endif /* !__ASSEMBLY__ */
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/gnttab_dma.h	2007-08-06 15:10:49.000000000 +0200
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
++ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan K.K.
++ *
++ * 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 _ASM_I386_GNTTAB_DMA_H
++#define _ASM_I386_GNTTAB_DMA_H
++
++static inline int gnttab_dma_local_pfn(struct page *page)
++{
++	/* Has it become a local MFN? */
++	return pfn_valid(mfn_to_local_pfn(pfn_to_mfn(page_to_pfn(page))));
++}
++
++static inline maddr_t gnttab_dma_map_page(struct page *page)
++{
++	__gnttab_dma_map_page(page);
++	return ((maddr_t)pfn_to_mfn(page_to_pfn(page)) << PAGE_SHIFT);
++}
++
++static inline void gnttab_dma_unmap_page(maddr_t maddr)
++{
++	__gnttab_dma_unmap_page(virt_to_page(bus_to_virt(maddr)));
++}
++
++#endif /* _ASM_I386_GNTTAB_DMA_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,97 @@
++/*
++ * highmem.h: virtual kernel memory mappings for high memory
++ *
++ * Used in CONFIG_HIGHMEM systems for memory pages which
++ * are not addressable by direct kernel virtual addresses.
++ *
++ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
++ *		      Gerhard.Wichert@pdb.siemens.de
++ *
++ *
++ * Redesigned the x86 32-bit VM architecture to deal with 
++ * up to 16 Terabyte physical memory. With current x86 CPUs
++ * we now support up to 64 Gigabytes physical RAM.
++ *
++ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ */
++
++#ifndef _ASM_HIGHMEM_H
++#define _ASM_HIGHMEM_H
++
++#ifdef __KERNEL__
++
++#include <linux/interrupt.h>
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#include <asm/tlbflush.h>
++
++/* declarations for highmem.c */
++extern unsigned long highstart_pfn, highend_pfn;
++
++extern pte_t *kmap_pte;
++extern pgprot_t kmap_prot;
++extern pte_t *pkmap_page_table;
++
++/*
++ * Right now we initialize only a single pte table. It can be extended
++ * easily, subsequent pte tables have to be allocated in one physical
++ * chunk of RAM.
++ */
++#ifdef CONFIG_X86_PAE
++#define LAST_PKMAP 512
++#else
++#define LAST_PKMAP 1024
++#endif
++/*
++ * Ordering is:
++ *
++ * FIXADDR_TOP
++ * 			fixed_addresses
++ * FIXADDR_START
++ * 			temp fixed addresses
++ * FIXADDR_BOOT_START
++ * 			Persistent kmap area
++ * PKMAP_BASE
++ * VMALLOC_END
++ * 			Vmalloc area
++ * VMALLOC_START
++ * high_memory
++ */
++#define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK )
++#define LAST_PKMAP_MASK (LAST_PKMAP-1)
++#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
++#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
++
++extern void * FASTCALL(kmap_high(struct page *page));
++extern void FASTCALL(kunmap_high(struct page *page));
++
++void *kmap(struct page *page);
++void kunmap(struct page *page);
++void *kmap_atomic(struct page *page, enum km_type type);
++void *kmap_atomic_pte(struct page *page, enum km_type type);
++void kunmap_atomic(void *kvaddr, enum km_type type);
++void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
++struct page *kmap_atomic_to_page(void *ptr);
++
++#define flush_cache_kmaps()	do { } while (0)
++
++void clear_highpage(struct page *);
++static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
++{
++	clear_highpage(page);
++}
++#define __HAVE_ARCH_CLEAR_HIGHPAGE
++#define __HAVE_ARCH_CLEAR_USER_HIGHPAGE
++
++void copy_highpage(struct page *to, struct page *from);
++static inline void copy_user_highpage(struct page *to, struct page *from,
++	unsigned long vaddr)
++{
++	copy_highpage(to, from);
++}
++#define __HAVE_ARCH_COPY_HIGHPAGE
++#define __HAVE_ARCH_COPY_USER_HIGHPAGE
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_HIGHMEM_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_32.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,415 @@
++/******************************************************************************
++ * hypercall.h
++ * 
++ * Linux-specific hypervisor handling.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser
++ * 
++ * 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 __HYPERCALL_H__
++#define __HYPERCALL_H__
++
++#include <linux/string.h> /* memcpy() */
++#include <linux/stringify.h>
++
++#ifndef __HYPERVISOR_H__
++# error "please don't include this file directly"
++#endif
++
++#ifdef CONFIG_XEN
++#define HYPERCALL_STR(name)					\
++	"call hypercall_page + ("__stringify(__HYPERVISOR_##name)" * 32)"
++#else
++#define HYPERCALL_STR(name)					\
++	"mov hypercall_stubs,%%eax; "				\
++	"add $("__stringify(__HYPERVISOR_##name)" * 32),%%eax; "\
++	"call *%%eax"
++#endif
++
++#define _hypercall0(type, name)			\
++({						\
++	type __res;				\
++	asm volatile (				\
++		HYPERCALL_STR(name)		\
++		: "=a" (__res)			\
++		:				\
++		: "memory" );			\
++	__res;					\
++})
++
++#define _hypercall1(type, name, a1)				\
++({								\
++	type __res;						\
++	long __ign1;						\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=b" (__ign1)			\
++		: "1" ((long)(a1))				\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall2(type, name, a1, a2)				\
++({								\
++	type __res;						\
++	long __ign1, __ign2;					\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)	\
++		: "1" ((long)(a1)), "2" ((long)(a2))		\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall3(type, name, a1, a2, a3)			\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3;				\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=b" (__ign1), "=c" (__ign2), 	\
++		"=d" (__ign3)					\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		"3" ((long)(a3))				\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall4(type, name, a1, a2, a3, a4)			\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3, __ign4;			\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
++		"=d" (__ign3), "=S" (__ign4)			\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		"3" ((long)(a3)), "4" ((long)(a4))		\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3, __ign4, __ign5;		\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
++		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)	\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		"3" ((long)(a3)), "4" ((long)(a4)),		\
++		"5" ((long)(a5))				\
++		: "memory" );					\
++	__res;							\
++})
++
++static inline int __must_check
++HYPERVISOR_set_trap_table(
++	const trap_info_t *table)
++{
++	return _hypercall1(int, set_trap_table, table);
++}
++
++static inline int __must_check
++HYPERVISOR_mmu_update(
++	mmu_update_t *req, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	return _hypercall4(int, mmu_update, req, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_mmuext_op(
++	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_set_gdt(
++	unsigned long *frame_list, unsigned int entries)
++{
++	return _hypercall2(int, set_gdt, frame_list, entries);
++}
++
++static inline int __must_check
++HYPERVISOR_stack_switch(
++	unsigned long ss, unsigned long esp)
++{
++	return _hypercall2(int, stack_switch, ss, esp);
++}
++
++static inline int __must_check
++HYPERVISOR_set_callbacks(
++	unsigned long event_selector, unsigned long event_address,
++	unsigned long failsafe_selector, unsigned long failsafe_address)
++{
++	return _hypercall4(int, set_callbacks,
++			   event_selector, event_address,
++			   failsafe_selector, failsafe_address);
++}
++
++static inline int
++HYPERVISOR_fpu_taskswitch(
++	int set)
++{
++	return _hypercall1(int, fpu_taskswitch, set);
++}
++
++static inline int __must_check
++HYPERVISOR_sched_op_compat(
++	int cmd, unsigned long arg)
++{
++	return _hypercall2(int, sched_op_compat, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_sched_op(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, sched_op, cmd, arg);
++}
++
++static inline long __must_check
++HYPERVISOR_set_timer_op(
++	u64 timeout)
++{
++	unsigned long timeout_hi = (unsigned long)(timeout>>32);
++	unsigned long timeout_lo = (unsigned long)timeout;
++	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
++}
++
++static inline int __must_check
++HYPERVISOR_platform_op(
++	struct xen_platform_op *platform_op)
++{
++	platform_op->interface_version = XENPF_INTERFACE_VERSION;
++	return _hypercall1(int, platform_op, platform_op);
++}
++
++static inline int __must_check
++HYPERVISOR_set_debugreg(
++	unsigned int reg, unsigned long value)
++{
++	return _hypercall2(int, set_debugreg, reg, value);
++}
++
++static inline unsigned long __must_check
++HYPERVISOR_get_debugreg(
++	unsigned int reg)
++{
++	return _hypercall1(unsigned long, get_debugreg, reg);
++}
++
++static inline int __must_check
++HYPERVISOR_update_descriptor(
++	u64 ma, u64 desc)
++{
++	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
++}
++
++static inline int __must_check
++HYPERVISOR_memory_op(
++	unsigned int cmd, void *arg)
++{
++	return _hypercall2(int, memory_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_multicall(
++	multicall_entry_t *call_list, unsigned int nr_calls)
++{
++	return _hypercall2(int, multicall, call_list, nr_calls);
++}
++
++static inline int __must_check
++HYPERVISOR_update_va_mapping(
++	unsigned long va, pte_t new_val, unsigned long flags)
++{
++	unsigned long pte_hi = 0;
++#ifdef CONFIG_X86_PAE
++	pte_hi = new_val.pte_high;
++#endif
++	return _hypercall4(int, update_va_mapping, va,
++			   new_val.pte_low, pte_hi, flags);
++}
++
++static inline int __must_check
++HYPERVISOR_event_channel_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, event_channel_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct evtchn_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, event_channel_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_xen_version(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, xen_version, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_console_io(
++	int cmd, unsigned int count, char *str)
++{
++	return _hypercall3(int, console_io, cmd, count, str);
++}
++
++static inline int __must_check
++HYPERVISOR_physdev_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, physdev_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct physdev_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, physdev_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_grant_table_op(
++	unsigned int cmd, void *uop, unsigned int count)
++{
++	return _hypercall3(int, grant_table_op, cmd, uop, count);
++}
++
++static inline int __must_check
++HYPERVISOR_update_va_mapping_otherdomain(
++	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
++{
++	unsigned long pte_hi = 0;
++#ifdef CONFIG_X86_PAE
++	pte_hi = new_val.pte_high;
++#endif
++	return _hypercall5(int, update_va_mapping_otherdomain, va,
++			   new_val.pte_low, pte_hi, flags, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_vm_assist(
++	unsigned int cmd, unsigned int type)
++{
++	return _hypercall2(int, vm_assist, cmd, type);
++}
++
++static inline int __must_check
++HYPERVISOR_vcpu_op(
++	int cmd, unsigned int vcpuid, void *extra_args)
++{
++	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
++}
++
++static inline int __must_check
++HYPERVISOR_suspend(
++	unsigned long srec)
++{
++	struct sched_shutdown sched_shutdown = {
++		.reason = SHUTDOWN_suspend
++	};
++
++	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
++			     &sched_shutdown, srec);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
++				 SHUTDOWN_suspend, srec);
++#endif
++
++	return rc;
++}
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++static inline int
++HYPERVISOR_nmi_op(
++	unsigned long op, void *arg)
++{
++	return _hypercall2(int, nmi_op, op, arg);
++}
++#endif
++
++#ifndef CONFIG_XEN
++static inline unsigned long __must_check
++HYPERVISOR_hvm_op(
++    int op, void *arg)
++{
++    return _hypercall2(unsigned long, hvm_op, op, arg);
++}
++#endif
++
++static inline int __must_check
++HYPERVISOR_callback_op(
++	int cmd, const void *arg)
++{
++	return _hypercall2(int, callback_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_xenoprof_op(
++	int op, void *arg)
++{
++	return _hypercall2(int, xenoprof_op, op, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_kexec_op(
++	unsigned long op, void *args)
++{
++	return _hypercall2(int, kexec_op, op, args);
++}
++
++static inline int __must_check
++HYPERVISOR_tmem_op(
++	struct tmem_op *op)
++{
++	return _hypercall1(int, tmem_op, op);
++}
++
++
++#endif /* __HYPERCALL_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-07-13 14:25:35.000000000 +0200
+@@ -0,0 +1,263 @@
++/******************************************************************************
++ * hypervisor.h
++ * 
++ * Linux-specific hypervisor handling.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser
++ * 
++ * 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 __HYPERVISOR_H__
++#define __HYPERVISOR_H__
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/errno.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/platform.h>
++#include <xen/interface/event_channel.h>
++#include <xen/interface/physdev.h>
++#include <xen/interface/sched.h>
++#include <xen/interface/nmi.h>
++#include <xen/interface/tmem.h>
++#include <asm/ptrace.h>
++#include <asm/page.h>
++#if defined(__i386__)
++#  ifdef CONFIG_X86_PAE
++#   include <asm-generic/pgtable-nopud.h>
++#  else
++#   include <asm-generic/pgtable-nopmd.h>
++#  endif
++#elif defined(__x86_64__) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
++#  include <asm-generic/pgtable-nopud.h>
++#endif
++
++extern shared_info_t *HYPERVISOR_shared_info;
++
++#define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu))
++#ifdef CONFIG_SMP
++#define current_vcpu_info() vcpu_info(smp_processor_id())
++#else
++#define current_vcpu_info() vcpu_info(0)
++#endif
++
++#ifdef CONFIG_X86_32
++extern unsigned long hypervisor_virt_start;
++#endif
++
++/* arch/xen/i386/kernel/setup.c */
++extern start_info_t *xen_start_info;
++#ifdef CONFIG_XEN_PRIVILEGED_GUEST
++#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN)
++#else
++#define is_initial_xendomain() 0
++#endif
++
++/* arch/xen/kernel/evtchn.c */
++/* Force a proper event-channel callback from Xen. */
++void force_evtchn_callback(void);
++
++/* arch/xen/kernel/process.c */
++void xen_cpu_idle (void);
++
++/* arch/xen/i386/kernel/hypervisor.c */
++void do_hypervisor_callback(struct pt_regs *regs);
++
++/* arch/xen/i386/mm/hypervisor.c */
++/*
++ * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
++ * be MACHINE addresses.
++ */
++
++void xen_pt_switch(unsigned long ptr);
++void xen_new_user_pt(unsigned long ptr); /* x86_64 only */
++void xen_load_gs(unsigned int selector); /* x86_64 only */
++void xen_tlb_flush(void);
++void xen_invlpg(unsigned long ptr);
++
++void xen_l1_entry_update(pte_t *ptr, pte_t val);
++void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
++void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
++void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
++void xen_pgd_pin(unsigned long ptr);
++void xen_pgd_unpin(unsigned long ptr);
++
++void xen_set_ldt(const void *ptr, unsigned int ents);
++
++#ifdef CONFIG_SMP
++#include <linux/cpumask.h>
++void xen_tlb_flush_all(void);
++void xen_invlpg_all(unsigned long ptr);
++void xen_tlb_flush_mask(cpumask_t *mask);
++void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr);
++#else
++#define xen_tlb_flush_all xen_tlb_flush
++#define xen_invlpg_all xen_invlpg
++#endif
++
++/* Returns zero on success else negative errno. */
++int xen_create_contiguous_region(
++    unsigned long vstart, unsigned int order, unsigned int address_bits);
++void xen_destroy_contiguous_region(
++    unsigned long vstart, unsigned int order);
++
++struct page;
++
++int xen_limit_pages_to_max_mfn(
++	struct page *pages, unsigned int order, unsigned int address_bits);
++
++/* Turn jiffies into Xen system time. */
++u64 jiffies_to_st(unsigned long jiffies);
++
++#ifdef CONFIG_XEN_SCRUB_PAGES
++void scrub_pages(void *, unsigned int);
++#else
++#define scrub_pages(_p,_n) ((void)0)
++#endif
++
++#include <xen/hypercall.h>
++
++#if defined(CONFIG_X86_64)
++#define MULTI_UVMFLAGS_INDEX 2
++#define MULTI_UVMDOMID_INDEX 3
++#else
++#define MULTI_UVMFLAGS_INDEX 3
++#define MULTI_UVMDOMID_INDEX 4
++#endif
++
++#ifdef CONFIG_XEN
++#define is_running_on_xen() 1
++#else
++extern char *hypercall_stubs;
++#define is_running_on_xen() (!!hypercall_stubs)
++#endif
++
++static inline int
++HYPERVISOR_yield(
++	void)
++{
++	int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
++#endif
++
++	return rc;
++}
++
++static inline int
++HYPERVISOR_block(
++	void)
++{
++	int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
++#endif
++
++	return rc;
++}
++
++static inline void /*__noreturn*/
++HYPERVISOR_shutdown(
++	unsigned int reason)
++{
++	struct sched_shutdown sched_shutdown = {
++		.reason = reason
++	};
++
++	VOID(HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown));
++#if CONFIG_XEN_COMPAT <= 0x030002
++	VOID(HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason));
++#endif
++	/* Don't recurse needlessly. */
++	BUG_ON(reason != SHUTDOWN_crash);
++	for(;;);
++}
++
++static inline int __must_check
++HYPERVISOR_poll(
++	evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
++{
++	int rc;
++	struct sched_poll sched_poll = {
++		.nr_ports = nr_ports,
++		.timeout = jiffies_to_st(timeout)
++	};
++	set_xen_guest_handle(sched_poll.ports, ports);
++
++	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
++#endif
++
++	return rc;
++}
++
++#ifdef CONFIG_XEN
++
++static inline void
++MULTI_update_va_mapping(
++    multicall_entry_t *mcl, unsigned long va,
++    pte_t new_val, unsigned long flags)
++{
++    mcl->op = __HYPERVISOR_update_va_mapping;
++    mcl->args[0] = va;
++#if defined(CONFIG_X86_64)
++    mcl->args[1] = new_val.pte;
++#elif defined(CONFIG_X86_PAE)
++    mcl->args[1] = new_val.pte_low;
++    mcl->args[2] = new_val.pte_high;
++#else
++    mcl->args[1] = new_val.pte_low;
++    mcl->args[2] = 0;
++#endif
++    mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
++}
++
++static inline void
++MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd,
++		     void *uop, unsigned int count)
++{
++    mcl->op = __HYPERVISOR_grant_table_op;
++    mcl->args[0] = cmd;
++    mcl->args[1] = (unsigned long)uop;
++    mcl->args[2] = count;
++}
++
++#else /* !defined(CONFIG_XEN) */
++
++/* Multicalls not supported for HVM guests. */
++#define MULTI_update_va_mapping(a,b,c,d) ((void)0)
++#define MULTI_grant_table_op(a,b,c,d) ((void)0)
++
++#endif
++
++#endif /* __HYPERVISOR_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_32.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,127 @@
++/*
++ * include/asm-i386/irqflags.h
++ *
++ * IRQ flags handling
++ *
++ * This file gets included from lowlevel asm headers too, to provide
++ * wrapped versions of the local_irq_*() APIs, based on the
++ * raw_local_irq_*() functions from the lowlevel headers.
++ */
++#ifndef _ASM_IRQFLAGS_H
++#define _ASM_IRQFLAGS_H
++
++#ifndef __ASSEMBLY__
++
++/* 
++ * The use of 'barrier' in the following reflects their use as local-lock
++ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
++ * critical operations are executed. All critical operations must complete
++ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
++ * includes these barriers, for example.
++ */
++
++#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask)
++
++#define raw_local_save_flags(flags) \
++		do { (flags) = __raw_local_save_flags(); } while (0)
++
++#define raw_local_irq_restore(x)					\
++do {									\
++	vcpu_info_t *_vcpu;						\
++	barrier();							\
++	_vcpu = current_vcpu_info();					\
++	if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {			\
++		barrier(); /* unmask then check (avoid races) */	\
++		if (unlikely(_vcpu->evtchn_upcall_pending))		\
++			force_evtchn_callback();			\
++	}								\
++} while (0)
++
++#define raw_local_irq_disable()						\
++do {									\
++	current_vcpu_info()->evtchn_upcall_mask = 1;			\
++	barrier();							\
++} while (0)
++
++#define raw_local_irq_enable()						\
++do {									\
++	vcpu_info_t *_vcpu;						\
++	barrier();							\
++	_vcpu = current_vcpu_info();					\
++	_vcpu->evtchn_upcall_mask = 0;					\
++	barrier(); /* unmask then check (avoid races) */		\
++	if (unlikely(_vcpu->evtchn_upcall_pending))			\
++		force_evtchn_callback();				\
++} while (0)
++
++/*
++ * Used in the idle loop; sti takes one instruction cycle
++ * to complete:
++ */
++void raw_safe_halt(void);
++
++/*
++ * Used when interrupts are already enabled or to
++ * shutdown the processor:
++ */
++void halt(void);
++
++static inline int raw_irqs_disabled_flags(unsigned long flags)
++{
++	return (flags != 0);
++}
++
++#define raw_irqs_disabled()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_irqs_disabled_flags(flags);					\
++})
++
++/*
++ * For spinlocks, etc:
++ */
++#define __raw_local_irq_save()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_local_irq_disable();					\
++									\
++	flags;								\
++})
++
++#define raw_local_irq_save(flags) \
++		do { (flags) = __raw_local_irq_save(); } while (0)
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * Do the CPU's IRQ-state tracing from assembly code. We call a
++ * C function, so save all the C-clobbered registers:
++ */
++#ifdef CONFIG_TRACE_IRQFLAGS
++
++# define TRACE_IRQS_ON				\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call trace_hardirqs_on;			\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++
++# define TRACE_IRQS_OFF				\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call trace_hardirqs_off;		\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++
++#else
++# define TRACE_IRQS_ON
++# define TRACE_IRQS_OFF
++#endif
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr_32.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,193 @@
++#ifndef _I386_MADDR_H
++#define _I386_MADDR_H
++
++#include <xen/features.h>
++#include <xen/interface/xen.h>
++
++/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
++#define INVALID_P2M_ENTRY	(~0UL)
++#define FOREIGN_FRAME_BIT	(1UL<<31)
++#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
++
++/* Definitions for machine and pseudophysical addresses. */
++#ifdef CONFIG_X86_PAE
++typedef unsigned long long paddr_t;
++typedef unsigned long long maddr_t;
++#else
++typedef unsigned long paddr_t;
++typedef unsigned long maddr_t;
++#endif
++
++#ifdef CONFIG_XEN
++
++extern unsigned long *phys_to_machine_mapping;
++extern unsigned long  max_mapnr;
++
++#undef machine_to_phys_mapping
++extern unsigned long *machine_to_phys_mapping;
++extern unsigned int   machine_to_phys_order;
++
++static inline unsigned long pfn_to_mfn(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return pfn;
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
++}
++
++static inline int phys_to_machine_mapping_valid(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 1;
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
++}
++
++static inline unsigned long mfn_to_pfn(unsigned long mfn)
++{
++	unsigned long pfn;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return mfn;
++
++	if (unlikely((mfn >> machine_to_phys_order) != 0))
++		return max_mapnr;
++
++	/* The array access can fail (e.g., device space beyond end of RAM). */
++	asm (
++		"1:	movl %1,%0\n"
++		"2:\n"
++		".section .fixup,\"ax\"\n"
++		"3:	movl %2,%0\n"
++		"	jmp  2b\n"
++		".previous\n"
++		".section __ex_table,\"a\"\n"
++		"	.align 4\n"
++		"	.long 1b,3b\n"
++		".previous"
++		: "=r" (pfn)
++		: "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
++
++	return pfn;
++}
++
++/*
++ * We detect special mappings in one of two ways:
++ *  1. If the MFN is an I/O page then Xen will set the m2p entry
++ *     to be outside our maximum possible pseudophys range.
++ *  2. If the MFN belongs to a different domain then we will certainly
++ *     not have MFN in our p2m table. Conversely, if the page is ours,
++ *     then we'll have p2m(m2p(MFN))==MFN.
++ * If we detect a special mapping then it doesn't have a 'struct page'.
++ * We force !pfn_valid() by returning an out-of-range pointer.
++ *
++ * NB. These checks require that, for any MFN that is not in our reservation,
++ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
++ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
++ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
++ *
++ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
++ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
++ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
++ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
++ */
++static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
++{
++	unsigned long pfn = mfn_to_pfn(mfn);
++	if ((pfn < max_mapnr)
++	    && !xen_feature(XENFEAT_auto_translated_physmap)
++	    && (phys_to_machine_mapping[pfn] != mfn))
++		return max_mapnr; /* force !pfn_valid() */
++	return pfn;
++}
++
++static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
++{
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
++	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
++		return;
++	}
++	phys_to_machine_mapping[pfn] = mfn;
++}
++
++static inline maddr_t phys_to_machine(paddr_t phys)
++{
++	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
++	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
++	return machine;
++}
++
++static inline paddr_t machine_to_phys(maddr_t machine)
++{
++	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
++	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
++	return phys;
++}
++
++#ifdef CONFIG_X86_PAE
++static inline paddr_t pte_phys_to_machine(paddr_t phys)
++{
++	/*
++	 * In PAE mode, the NX bit needs to be dealt with in the value
++	 * passed to pfn_to_mfn(). On x86_64, we need to mask it off,
++	 * but for i386 the conversion to ulong for the argument will
++	 * clip it off.
++	 */
++	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
++	machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
++	return machine;
++}
++
++static inline paddr_t pte_machine_to_phys(maddr_t machine)
++{
++	/*
++	 * In PAE mode, the NX bit needs to be dealt with in the value
++	 * passed to mfn_to_pfn(). On x86_64, we need to mask it off,
++	 * but for i386 the conversion to ulong for the argument will
++	 * clip it off.
++	 */
++	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
++	phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
++	return phys;
++}
++#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;
++
++	pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \
++					(pgprot_val(pgprot) >> 32);
++	pte.pte_high &= (__supported_pte_mask >> 32);
++	pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \
++							__supported_pte_mask;
++	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
++
++#else /* !CONFIG_XEN */
++
++#define pfn_to_mfn(pfn) (pfn)
++#define mfn_to_pfn(mfn) (mfn)
++#define mfn_to_local_pfn(mfn) (mfn)
++#define set_phys_to_machine(pfn, mfn) ((void)0)
++#define phys_to_machine_mapping_valid(pfn) (1)
++#define phys_to_machine(phys) ((maddr_t)(phys))
++#define machine_to_phys(mach) ((paddr_t)(mach))
++#define pfn_pte_ma(pfn, prot) pfn_pte(pfn, prot)
++#define __pte_ma(x) __pte(x)
++
++#endif /* !CONFIG_XEN */
++
++/* VIRT <-> MACHINE conversion */
++#define virt_to_machine(v)	(phys_to_machine(__pa(v)))
++#define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
++#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
++
++#endif /* _I386_MADDR_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,108 @@
++#ifndef __I386_SCHED_H
++#define __I386_SCHED_H
++
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++
++/*
++ * Used for LDT copy/destruction.
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
++void destroy_context(struct mm_struct *mm);
++
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++#if 0 /* XEN: no lazy tlb */
++	unsigned cpu = smp_processor_id();
++	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
++		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_LAZY;
++#endif
++}
++
++#define prepare_arch_switch(next)	__prepare_arch_switch()
++
++static inline void __prepare_arch_switch(void)
++{
++	/*
++	 * Save away %fs and %gs. No need to save %es and %ds, as those
++	 * are always kernel segments while inside the kernel. Must
++	 * happen before reload of cr3/ldt (i.e., not in __switch_to).
++	 */
++	asm volatile ( "mov %%fs,%0 ; mov %%gs,%1"
++		: "=m" (current->thread.fs),
++		  "=m" (current->thread.gs));
++	asm volatile ( "movl %0,%%fs ; movl %0,%%gs"
++		: : "r" (0) );
++}
++
++extern void mm_pin(struct mm_struct *mm);
++extern void mm_unpin(struct mm_struct *mm);
++void mm_pin_all(void);
++
++static inline void switch_mm(struct mm_struct *prev,
++			     struct mm_struct *next,
++			     struct task_struct *tsk)
++{
++	int cpu = smp_processor_id();
++	struct mmuext_op _op[2], *op = _op;
++
++	if (likely(prev != next)) {
++		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
++		       !test_bit(PG_pinned, &virt_to_page(next->pgd)->flags));
++
++		/* stop flush ipis for the previous mm */
++		cpu_clear(cpu, prev->cpu_vm_mask);
++#if 0 /* XEN: no lazy tlb */
++		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
++		per_cpu(cpu_tlbstate, cpu).active_mm = next;
++#endif
++		cpu_set(cpu, next->cpu_vm_mask);
++
++		/* Re-load page tables: load_cr3(next->pgd) */
++		op->cmd = MMUEXT_NEW_BASEPTR;
++		op->arg1.mfn = pfn_to_mfn(__pa(next->pgd) >> PAGE_SHIFT);
++		op++;
++
++		/*
++		 * load the LDT, if the LDT is different:
++		 */
++		if (unlikely(prev->context.ldt != next->context.ldt)) {
++			/* load_LDT_nolock(&next->context, cpu) */
++			op->cmd = MMUEXT_SET_LDT;
++			op->arg1.linear_addr = (unsigned long)next->context.ldt;
++			op->arg2.nr_ents     = next->context.size;
++			op++;
++		}
++
++		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
++	}
++#if 0 /* XEN: no lazy tlb */
++	else {
++		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
++		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
++
++		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
++			/* We were in lazy tlb mode and leave_mm disabled 
++			 * tlb flush IPI delivery. We must reload %cr3.
++			 */
++			load_cr3(next->pgd);
++			load_LDT_nolock(&next->context, cpu);
++		}
++	}
++#endif
++}
++
++#define deactivate_mm(tsk, mm) \
++	asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
++
++static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
++{
++	if (!test_bit(PG_pinned, &virt_to_page(next->pgd)->flags))
++		mm_pin(next);
++	switch_mm(prev, next, NULL);
++}
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_32.h	2008-07-21 11:00:33.000000000 +0200
+@@ -0,0 +1,59 @@
++#ifndef _I386_PGALLOC_H
++#define _I386_PGALLOC_H
++
++#include <asm/fixmap.h>
++#include <linux/threads.h>
++#include <linux/mm.h>		/* for struct page */
++#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
++
++#define pmd_populate_kernel(mm, pmd, pte) \
++		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
++
++#define pmd_populate(mm, pmd, pte) 					\
++do {									\
++	unsigned long pfn = page_to_pfn(pte);				\
++	if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) {	\
++		if (!PageHighMem(pte))					\
++			BUG_ON(HYPERVISOR_update_va_mapping(		\
++			  (unsigned long)__va(pfn << PAGE_SHIFT),	\
++			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));		\
++		else if (!test_and_set_bit(PG_pinned, &pte->flags))	\
++			kmap_flush_unused();				\
++		set_pmd(pmd,						\
++		        __pmd(_PAGE_TABLE + ((paddr_t)pfn << PAGE_SHIFT))); \
++	} else							\
++		*(pmd) = __pmd(_PAGE_TABLE + ((paddr_t)pfn << PAGE_SHIFT)); \
++} while (0)
++
++/*
++ * Allocate and free page tables.
++ */
++extern pgd_t *pgd_alloc(struct mm_struct *);
++extern void pgd_free(pgd_t *pgd);
++
++extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
++extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
++
++static inline void pte_free_kernel(pte_t *pte)
++{
++	make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
++	free_page((unsigned long)pte);
++}
++
++extern void pte_free(struct page *pte);
++
++#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
++
++#ifdef CONFIG_X86_PAE
++/*
++ * In the PAE case we free the pmds as part of the pgd.
++ */
++#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
++#define pmd_free(x)			do { } while (0)
++#define __pmd_free_tlb(tlb,x)		do { } while (0)
++#define pud_populate(mm, pmd, pte)	BUG()
++#endif
++
++#define check_pgt_cache()	do { } while (0)
++
++#endif /* _I386_PGALLOC_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,24 @@
++#ifndef _I386_PGTABLE_3LEVEL_DEFS_H
++#define _I386_PGTABLE_3LEVEL_DEFS_H
++
++#define HAVE_SHARED_KERNEL_PMD 0
++
++/*
++ * PGDIR_SHIFT determines what a top-level page table entry can map
++ */
++#define PGDIR_SHIFT	30
++#define PTRS_PER_PGD	4
++
++/*
++ * PMD_SHIFT determines the size of the area a middle-level
++ * page table can map
++ */
++#define PMD_SHIFT	21
++#define PTRS_PER_PMD	512
++
++/*
++ * entries per page directory level
++ */
++#define PTRS_PER_PTE	512
++
++#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,211 @@
++#ifndef _I386_PGTABLE_3LEVEL_H
++#define _I386_PGTABLE_3LEVEL_H
++
++#include <asm-generic/pgtable-nopud.h>
++
++/*
++ * Intel Physical Address Extension (PAE) Mode - three-level page
++ * tables on PPro+ CPUs.
++ *
++ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ */
++
++#define pte_ERROR(e) \
++	printk("%s:%d: bad pte %p(%016Lx pfn %08lx).\n", __FILE__, __LINE__, \
++	       &(e), __pte_val(e), pte_pfn(e))
++#define pmd_ERROR(e) \
++	printk("%s:%d: bad pmd %p(%016Lx pfn %08Lx).\n", __FILE__, __LINE__, \
++	       &(e), __pmd_val(e), (pmd_val(e) & PTE_MASK) >> PAGE_SHIFT)
++#define pgd_ERROR(e) \
++	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n", __FILE__, __LINE__, \
++	       &(e), __pgd_val(e), (pgd_val(e) & PTE_MASK) >> PAGE_SHIFT)
++
++#define pud_none(pud)				0
++#define pud_bad(pud)				0
++#define pud_present(pud)			1
++
++/*
++ * Is the pte executable?
++ */
++static inline int pte_x(pte_t pte)
++{
++	return !(__pte_val(pte) & _PAGE_NX);
++}
++
++/*
++ * All present user-pages with !NX bit are user-executable:
++ */
++static inline int pte_exec(pte_t pte)
++{
++	return pte_user(pte) && pte_x(pte);
++}
++/*
++ * All present pages with !NX bit are kernel-executable:
++ */
++static inline int pte_exec_kernel(pte_t pte)
++{
++	return pte_x(pte);
++}
++
++/* Rules for using set_pte: the pte being assigned *must* be
++ * either not present or in a state where the hardware will
++ * not attempt to update the pte.  In places where this is
++ * not possible, use pte_get_and_clear to obtain the old pte
++ * value and then use set_pte to update it.  -ben
++ */
++#define __HAVE_ARCH_SET_PTE_ATOMIC
++
++static inline void set_pte(pte_t *ptep, pte_t pte)
++{
++	ptep->pte_high = pte.pte_high;
++	smp_wmb();
++	ptep->pte_low = pte.pte_low;
++}
++#define set_pte_atomic(pteptr,pteval) \
++		set_64bit((unsigned long long *)(pteptr),__pte_val(pteval))
++
++#define set_pte_at(_mm,addr,ptep,pteval) do {				\
++	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
++	    HYPERVISOR_update_va_mapping((addr), (pteval), 0))		\
++		set_pte((ptep), (pteval));				\
++} while (0)
++
++#define set_pte_at_sync(_mm,addr,ptep,pteval) do {			\
++	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
++	    HYPERVISOR_update_va_mapping((addr), (pteval), UVMF_INVLPG)) { \
++		set_pte((ptep), (pteval));				\
++		xen_invlpg((addr));					\
++	}								\
++} while (0)
++
++#define set_pmd(pmdptr,pmdval)				\
++		xen_l2_entry_update((pmdptr), (pmdval))
++#define set_pud(pudptr,pudval) \
++		xen_l3_entry_update((pudptr), (pudval))
++
++/*
++ * Pentium-II erratum A13: in PAE mode we explicitly have to flush
++ * the TLB via cr3 if the top-level pgd is changed...
++ * We do not let the generic code free and clear pgd entries due to
++ * this erratum.
++ */
++static inline void pud_clear (pud_t * pud) { }
++
++#define pud_page(pud) \
++((struct page *) __va(pud_val(pud) & PAGE_MASK))
++
++#define pud_page_kernel(pud) \
++((unsigned long) __va(pud_val(pud) & PAGE_MASK))
++
++
++/* Find an entry in the second-level page table.. */
++#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
++			pmd_index(address))
++
++static inline int pte_none(pte_t pte)
++{
++	return !(pte.pte_low | pte.pte_high);
++}
++
++/*
++ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
++ * entry, so clear the bottom half first and enforce ordering with a compiler
++ * barrier.
++ */
++static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	if ((mm != current->mm && mm != &init_mm)
++	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
++		ptep->pte_low = 0;
++		smp_wmb();
++		ptep->pte_high = 0;
++	}
++}
++
++#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
++
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (!pte_none(pte)) {
++		if ((mm != &init_mm) ||
++		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
++			uint64_t val = __pte_val(pte);
++			if (__cmpxchg64(ptep, val, 0) != val) {
++				/* xchg acts as a barrier before the setting of the high bits */
++				pte.pte_low = xchg(&ptep->pte_low, 0);
++				pte.pte_high = ptep->pte_high;
++				ptep->pte_high = 0;
++			}
++		}
++	}
++	return pte;
++}
++
++#define ptep_clear_flush(vma, addr, ptep)			\
++({								\
++	pte_t *__ptep = (ptep);					\
++	pte_t __res = *__ptep;					\
++	if (!pte_none(__res) &&					\
++	    ((vma)->vm_mm != current->mm ||			\
++	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
++			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
++				UVMF_INVLPG|UVMF_MULTI))) {	\
++		__ptep->pte_low = 0;				\
++		smp_wmb();					\
++		__ptep->pte_high = 0;				\
++		flush_tlb_page(vma, addr);			\
++	}							\
++	__res;							\
++})
++
++static inline int pte_same(pte_t a, pte_t b)
++{
++	return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
++}
++
++#define pte_page(x)	pfn_to_page(pte_pfn(x))
++
++#define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
++			 ((_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_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;
++
++static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pte((((unsigned long long)page_nr << PAGE_SHIFT) |
++			pgprot_val(pgprot)) & __supported_pte_mask);
++}
++
++static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) |
++			pgprot_val(pgprot)) & __supported_pte_mask);
++}
++
++/*
++ * Bits 0, 6 and 7 are taken in the low part of the pte,
++ * put the 32 bits of offset into the high part.
++ */
++#define pte_to_pgoff(pte) ((pte).pte_high)
++#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
++#define PTE_FILE_MAX_BITS       32
++
++/* Encode and de-code a swap entry */
++#define __swp_type(x)			(((x).val) & 0x1f)
++#define __swp_offset(x)			((x).val >> 5)
++#define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
++#define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
++#define __swp_entry_to_pte(x)		((pte_t){ 0, (x).val })
++
++#define __pmd_free_tlb(tlb, x)		do { } while (0)
++
++void vmalloc_sync_all(void);
++
++#endif /* _I386_PGTABLE_3LEVEL_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,550 @@
++#ifndef _I386_PGTABLE_H
++#define _I386_PGTABLE_H
++
++#include <asm/hypervisor.h>
++
++/*
++ * The Linux memory management assumes a three-level page table setup. On
++ * the i386, we use that, but "fold" the mid level into the top-level page
++ * table, so that we physically have the same two-level page table as the
++ * i386 mmu expects.
++ *
++ * This file contains the functions and defines necessary to modify and use
++ * the i386 page table tree.
++ */
++#ifndef __ASSEMBLY__
++#include <asm/processor.h>
++#include <asm/fixmap.h>
++#include <linux/threads.h>
++
++#ifndef _I386_BITOPS_H
++#include <asm/bitops.h>
++#endif
++
++#include <linux/slab.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++
++/* Is this pagetable pinned? */
++#define PG_pinned	PG_arch_1
++
++struct mm_struct;
++struct vm_area_struct;
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
++extern unsigned long empty_zero_page[1024];
++extern pgd_t *swapper_pg_dir;
++extern kmem_cache_t *pgd_cache;
++extern kmem_cache_t *pmd_cache;
++extern spinlock_t pgd_lock;
++extern struct page *pgd_list;
++
++void pmd_ctor(void *, kmem_cache_t *, unsigned long);
++void pgd_ctor(void *, kmem_cache_t *, unsigned long);
++void pgd_dtor(void *, kmem_cache_t *, unsigned long);
++void pgtable_cache_init(void);
++void paging_init(void);
++
++/*
++ * The Linux x86 paging architecture is 'compile-time dual-mode', it
++ * implements both the traditional 2-level x86 page tables and the
++ * newer 3-level PAE-mode page tables.
++ */
++#ifdef CONFIG_X86_PAE
++# include <asm/pgtable-3level-defs.h>
++# define PMD_SIZE	(1UL << PMD_SHIFT)
++# define PMD_MASK	(~(PMD_SIZE-1))
++#else
++# include <asm/pgtable-2level-defs.h>
++#endif
++
++#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
++#define PGDIR_MASK	(~(PGDIR_SIZE-1))
++
++#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
++#define FIRST_USER_ADDRESS	0
++
++#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
++#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
++
++#define TWOLEVEL_PGDIR_SHIFT	22
++#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
++#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
++
++/* Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts.  That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ */
++#define VMALLOC_OFFSET	(8*1024*1024)
++#define VMALLOC_START	(((unsigned long) high_memory + vmalloc_earlyreserve + \
++			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
++#ifdef CONFIG_HIGHMEM
++# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
++#else
++# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
++#endif
++
++/*
++ * _PAGE_PSE set in the page directory entry just means that
++ * the page directory entry points directly to a 4MB-aligned block of
++ * memory. 
++ */
++#define _PAGE_BIT_PRESENT	0
++#define _PAGE_BIT_RW		1
++#define _PAGE_BIT_USER		2
++#define _PAGE_BIT_PWT		3
++#define _PAGE_BIT_PCD		4
++#define _PAGE_BIT_ACCESSED	5
++#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_UNUSED2	10
++#define _PAGE_BIT_UNUSED3	11
++#define _PAGE_BIT_NX		63
++
++#define _PAGE_PRESENT	0x001
++#define _PAGE_RW	0x002
++#define _PAGE_USER	0x004
++#define _PAGE_PWT	0x008
++#define _PAGE_PCD	0x010
++#define _PAGE_ACCESSED	0x020
++#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_UNUSED2	0x400
++#define _PAGE_UNUSED3	0x800
++
++/* If _PAGE_PRESENT is clear, we use these: */
++#define _PAGE_FILE	0x040	/* nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_PROTNONE	0x080	/* if the user mapped it with PROT_NONE;
++				   pte_present gives true */
++#ifdef CONFIG_X86_PAE
++#define _PAGE_NX	(1ULL<<_PAGE_BIT_NX)
++#else
++#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 | _PAGE_IO)
++
++#define PAGE_NONE \
++	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED \
++	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
++
++#define PAGE_SHARED_EXEC \
++	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC \
++	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC \
++	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY \
++	PAGE_COPY_NOEXEC
++#define PAGE_READONLY \
++	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC \
++	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++
++#define _PAGE_KERNEL \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
++#define _PAGE_KERNEL_EXEC \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
++
++extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
++#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
++#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD)
++#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
++
++#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
++#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
++#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
++#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
++#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
++
++/*
++ * The i386 can't do page protection for execute, and considers that
++ * the same are read. Also, write permissions imply read permissions.
++ * This is the closest we can get..
++ */
++#define __P000	PAGE_NONE
++#define __P001	PAGE_READONLY
++#define __P010	PAGE_COPY
++#define __P011	PAGE_COPY
++#define __P100	PAGE_READONLY_EXEC
++#define __P101	PAGE_READONLY_EXEC
++#define __P110	PAGE_COPY_EXEC
++#define __P111	PAGE_COPY_EXEC
++
++#define __S000	PAGE_NONE
++#define __S001	PAGE_READONLY
++#define __S010	PAGE_SHARED
++#define __S011	PAGE_SHARED
++#define __S100	PAGE_READONLY_EXEC
++#define __S101	PAGE_READONLY_EXEC
++#define __S110	PAGE_SHARED_EXEC
++#define __S111	PAGE_SHARED_EXEC
++
++/*
++ * Define this if things work differently on an i386 and an i486:
++ * it will (on an i486) warn about kernel memory accesses that are
++ * done without a 'access_ok(VERIFY_WRITE,..)'
++ */
++#undef TEST_ACCESS_OK
++
++/* The boot page tables (all created as a single array) */
++extern unsigned long pg0[];
++
++#define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
++
++/* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
++#define pmd_none(x)	(!(unsigned long)__pmd_val(x))
++#if CONFIG_XEN_COMPAT <= 0x030002
++/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
++   can temporarily clear it. */
++#define pmd_present(x)	(__pmd_val(x))
++#define pmd_bad(x)	((__pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
++#else
++#define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
++#define pmd_bad(x)	((__pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#endif
++
++
++#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
++
++/*
++ * The following only work if pte_present() is true.
++ * Undefined behaviour if not..
++ */
++static inline int pte_user(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
++static inline int pte_read(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
++static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
++static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
++static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
++static inline int pte_huge(pte_t pte)		{ return (pte).pte_low & _PAGE_PSE; }
++
++/*
++ * The following only works if pte_present() is not true.
++ */
++static inline int pte_file(pte_t pte)		{ return (pte).pte_low & _PAGE_FILE; }
++
++static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
++static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
++static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
++static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
++static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
++static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
++static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
++static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
++static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
++static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
++static inline pte_t pte_mkhuge(pte_t pte)	{ (pte).pte_low |= _PAGE_PSE; return pte; }
++
++#ifdef CONFIG_X86_PAE
++# include <asm/pgtable-3level.h>
++#else
++# include <asm/pgtable-2level.h>
++#endif
++
++#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __ret = pte_dirty(__pte);					\
++	if (__ret) {							\
++		__pte = pte_mkclean(__pte);				\
++		if ((vma)->vm_mm != current->mm ||			\
++		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
++			(ptep)->pte_low = __pte.pte_low;		\
++	}								\
++	__ret;								\
++})
++
++#define ptep_test_and_clear_young(vma, addr, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __ret = pte_young(__pte);					\
++	if (__ret)							\
++		__pte = pte_mkold(__pte);				\
++		if ((vma)->vm_mm != current->mm ||			\
++		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
++			(ptep)->pte_low = __pte.pte_low;		\
++	__ret;								\
++})
++
++#define ptep_get_and_clear_full(mm, addr, ptep, full)			\
++	((full) ? ({							\
++		pte_t __res = *(ptep);					\
++		if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) \
++			xen_l1_entry_update(ptep, __pte(0));		\
++		else							\
++			*(ptep) = __pte(0);				\
++		__res;							\
++	 }) :								\
++	 ptep_get_and_clear(mm, addr, ptep))
++
++static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (pte_write(pte))
++		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
++}
++
++/*
++ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
++ *
++ *  dst - pointer to pgd range anwhere on a pgd page
++ *  src - ""
++ *  count - the number of pgds to copy.
++ *
++ * dst and src can be on the same page, but the range must not overlap,
++ * and must not cross a page boundary.
++ */
++static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
++{
++       memcpy(dst, src, count * sizeof(pgd_t));
++}
++
++/*
++ * Macro to mark a page protection value as "uncacheable".  On processors which do not support
++ * it, this is a no-op.
++ */
++#define pgprot_noncached(prot)	((boot_cpu_data.x86 > 3)					  \
++				 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)) : (prot))
++
++/*
++ * Conversion functions: convert a page and protection to a page entry,
++ * and a page entry and page directory to the page they refer to.
++ */
++
++#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
++
++static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
++{
++	/*
++	 * Since this might change the present bit (which controls whether
++	 * a pte_t object has undergone p2m translation), we must use
++	 * pte_val() on the input pte and __pte() for the return value.
++	 */
++	paddr_t pteval = pte_val(pte);
++
++	pteval &= _PAGE_CHG_MASK;
++	pteval |= pgprot_val(newprot);
++#ifdef CONFIG_X86_PAE
++	pteval &= __supported_pte_mask;
++#endif
++	return __pte(pteval);
++}
++
++#define pmd_large(pmd) \
++((__pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
++
++/*
++ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
++ *
++ * this macro returns the index of the entry in the pgd page which would
++ * control the given virtual address
++ */
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
++#define pgd_index_k(addr) pgd_index(addr)
++
++/*
++ * pgd_offset() returns a (pgd_t *)
++ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
++ */
++#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
++
++/*
++ * a shortcut which implies the use of the kernel's pgd, instead
++ * of a process's
++ */
++#define pgd_offset_k(address) pgd_offset(&init_mm, address)
++
++/*
++ * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
++ *
++ * this macro returns the index of the entry in the pmd page which would
++ * control the given virtual address
++ */
++#define pmd_index(address) \
++		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
++
++/*
++ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
++ *
++ * this macro returns the index of the entry in the pte page which would
++ * control the given virtual address
++ */
++#define pte_index(address) \
++		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address) \
++	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
++
++#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++
++#define pmd_page_kernel(pmd) \
++		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++
++/*
++ * Helper function that returns the kernel pagetable entry controlling
++ * the virtual address 'address'. NULL means no pagetable entry present.
++ * NOTE: the return type is pte_t but if the pmd is PSE then we return it
++ * as a pte too.
++ */
++extern pte_t *lookup_address(unsigned long address);
++
++/*
++ * Make a given kernel text page executable/non-executable.
++ * Returns the previous executability setting of that page (which
++ * is used to restore the previous state). Used by the SMP bootup code.
++ * NOTE: this is an __init function for security reasons.
++ */
++#ifdef CONFIG_X86_PAE
++ extern int set_kernel_exec(unsigned long vaddr, int enable);
++#else
++ static inline int set_kernel_exec(unsigned long vaddr, int enable) { return 0;}
++#endif
++
++extern void noexec_setup(const char *str);
++
++#if defined(CONFIG_HIGHPTE)
++#define pte_offset_map(dir, address) \
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \
++	 pte_index(address))
++#define pte_offset_map_nested(dir, address) \
++	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + \
++	 pte_index(address))
++#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
++#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
++#else
++#define pte_offset_map(dir, address) \
++	((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
++#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
++#define pte_unmap(pte) do { } while (0)
++#define pte_unmap_nested(pte) do { } while (0)
++#endif
++
++#define __HAVE_ARCH_PTEP_ESTABLISH
++#define ptep_establish(vma, address, ptep, pteval)			\
++	do {								\
++		if ( likely((vma)->vm_mm == current->mm) ) {		\
++			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
++				pteval,					\
++				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
++					UVMF_INVLPG|UVMF_MULTI));	\
++		} else {						\
++			xen_l1_entry_update(ptep, pteval);		\
++			flush_tlb_page(vma, address);			\
++		}							\
++	} while (0)
++
++/*
++ * The i386 doesn't have any external MMU info: the kernel page
++ * tables contain all the necessary information.
++ *
++ * Also, we only update the dirty/accessed state if we set
++ * the dirty bit by hand in the kernel, since the hardware
++ * will do the accessed bit for us, and we don't want to
++ * race with other CPU's that might be updating the dirty
++ * bit at the same time.
++ */
++#define update_mmu_cache(vma,address,pte) do { } while (0)
++#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
++	do {								\
++		if (dirty)						\
++			ptep_establish(vma, address, ptep, entry);	\
++	} while (0)
++
++#include <xen/features.h>
++void make_lowmem_page_readonly(void *va, unsigned int feature);
++void make_lowmem_page_writable(void *va, unsigned int feature);
++void make_page_readonly(void *va, unsigned int feature);
++void make_page_writable(void *va, unsigned int feature);
++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)						\
++({									\
++	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)))
++
++#ifdef CONFIG_HIGHPTE
++#include <asm/io.h>
++struct page *kmap_atomic_to_page(void *);
++#define ptep_to_machine(ptep)						\
++({									\
++	pte_t *__ptep = (ptep);						\
++	page_to_phys(kmap_atomic_to_page(__ptep))			\
++		| ((unsigned long)__ptep & (PAGE_SIZE - 1));		\
++})
++#else
++#define ptep_to_machine(ptep)	virt_to_machine(ptep)
++#endif
++
++#endif /* !__ASSEMBLY__ */
++
++#ifdef CONFIG_FLATMEM
++#define kern_addr_valid(addr)	(1)
++#endif /* CONFIG_FLATMEM */
++
++int direct_remap_pfn_range(struct vm_area_struct *vma,
++                           unsigned long address, 
++                           unsigned long mfn,
++                           unsigned long size, 
++                           pgprot_t prot,
++                           domid_t  domid);
++int direct_kernel_remap_pfn_range(unsigned long address, 
++				  unsigned long mfn,
++				  unsigned long size, 
++				  pgprot_t prot,
++				  domid_t  domid);
++int create_lookup_pte_addr(struct mm_struct *mm,
++                           unsigned long address,
++                           uint64_t *ptep);
++int touch_pte_range(struct mm_struct *mm,
++                    unsigned long address,
++                    unsigned long size);
++
++int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
++		unsigned long addr, unsigned long end, pgprot_t newprot);
++
++#define arch_change_pte_range(mm, pmd, addr, end, newprot)	\
++		xen_change_pte_range(mm, pmd, addr, end, newprot)
++
++#define io_remap_pfn_range(vma,from,pfn,size,prot) \
++direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
++
++#define MK_IOSPACE_PFN(space, pfn)	(pfn)
++#define GET_IOSPACE(pfn)		0
++#define GET_PFN(pfn)			(pfn)
++
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
++#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
++#define __HAVE_ARCH_PTEP_SET_WRPROTECT
++#define __HAVE_ARCH_PTE_SAME
++#include <asm-generic/pgtable.h>
++
++#endif /* _I386_PGTABLE_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,743 @@
++/*
++ * include/asm-i386/processor.h
++ *
++ * Copyright (C) 1994 Linus Torvalds
++ */
++
++#ifndef __ASM_I386_PROCESSOR_H
++#define __ASM_I386_PROCESSOR_H
++
++#include <asm/vm86.h>
++#include <asm/math_emu.h>
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/types.h>
++#include <asm/sigcontext.h>
++#include <asm/cpufeature.h>
++#include <asm/msr.h>
++#include <asm/system.h>
++#include <linux/cache.h>
++#include <linux/threads.h>
++#include <asm/percpu.h>
++#include <linux/cpumask.h>
++#include <xen/interface/physdev.h>
++
++/* flag for disabling the tsc */
++extern int tsc_disable;
++
++struct desc_struct {
++	unsigned long a,b;
++};
++
++#define desc_empty(desc) \
++		(!((desc)->a | (desc)->b))
++
++#define desc_equal(desc1, desc2) \
++		(((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
++
++/*
++ *  CPU type and hardware bug flags. Kept separately for each CPU.
++ *  Members of this structure are referenced in head.S, so think twice
++ *  before touching them. [mj]
++ */
++
++struct cpuinfo_x86 {
++	__u8	x86;		/* CPU family */
++	__u8	x86_vendor;	/* CPU vendor */
++	__u8	x86_model;
++	__u8	x86_mask;
++	char	wp_works_ok;	/* It doesn't on 386's */
++	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */
++	char	hard_math;
++	char	rfu;
++       	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
++	unsigned long	x86_capability[NCAPINTS];
++	char	x86_vendor_id[16];
++	char	x86_model_id[64];
++	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
++				    call  */
++	int 	x86_cache_alignment;	/* In bytes */
++	char	fdiv_bug;
++	char	f00f_bug;
++	char	coma_bug;
++	char	pad0;
++	int	x86_power;
++	unsigned long loops_per_jiffy;
++#ifdef CONFIG_SMP
++	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
++#endif
++	unsigned char x86_max_cores;	/* cpuid returned max cores value */
++	unsigned char apicid;
++#ifdef CONFIG_SMP
++	unsigned char booted_cores;	/* number of cores as seen by OS */
++	__u8 phys_proc_id; 		/* Physical processor id. */
++	__u8 cpu_core_id;  		/* Core id */
++#endif
++} __attribute__((__aligned__(SMP_CACHE_BYTES)));
++
++#define X86_VENDOR_INTEL 0
++#define X86_VENDOR_CYRIX 1
++#define X86_VENDOR_AMD 2
++#define X86_VENDOR_UMC 3
++#define X86_VENDOR_NEXGEN 4
++#define X86_VENDOR_CENTAUR 5
++#define X86_VENDOR_RISE 6
++#define X86_VENDOR_TRANSMETA 7
++#define X86_VENDOR_NSC 8
++#define X86_VENDOR_NUM 9
++#define X86_VENDOR_UNKNOWN 0xff
++
++/*
++ * capabilities of CPUs
++ */
++
++extern struct cpuinfo_x86 boot_cpu_data;
++extern struct cpuinfo_x86 new_cpu_data;
++#ifndef CONFIG_X86_NO_TSS
++extern struct tss_struct doublefault_tss;
++DECLARE_PER_CPU(struct tss_struct, init_tss);
++#endif
++
++#ifdef CONFIG_SMP
++extern struct cpuinfo_x86 cpu_data[];
++#define current_cpu_data cpu_data[smp_processor_id()]
++#else
++#define cpu_data (&boot_cpu_data)
++#define current_cpu_data boot_cpu_data
++#endif
++
++extern	int cpu_llc_id[NR_CPUS];
++extern char ignore_fpu_irq;
++
++extern void identify_cpu(struct cpuinfo_x86 *);
++extern void print_cpu_info(struct cpuinfo_x86 *);
++extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
++extern unsigned short num_cache_leaves;
++
++#ifdef CONFIG_X86_HT
++extern void detect_ht(struct cpuinfo_x86 *c);
++#else
++static inline void detect_ht(struct cpuinfo_x86 *c) {}
++#endif
++
++/*
++ * EFLAGS bits
++ */
++#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
++#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
++#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
++#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
++#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
++#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
++#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
++#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
++#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
++#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
++#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
++#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
++#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
++#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
++#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
++#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
++#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
++
++/*
++ * Generic CPUID function
++ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
++ * resulting in stale register contents being returned.
++ */
++static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
++{
++	__asm__(XEN_CPUID
++		: "=a" (*eax),
++		  "=b" (*ebx),
++		  "=c" (*ecx),
++		  "=d" (*edx)
++		: "0" (op), "c"(0));
++}
++
++/* Some CPUID calls want 'count' to be placed in ecx */
++static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
++	       	int *edx)
++{
++	__asm__(XEN_CPUID
++		: "=a" (*eax),
++		  "=b" (*ebx),
++		  "=c" (*ecx),
++		  "=d" (*edx)
++		: "0" (op), "c" (count));
++}
++
++/*
++ * CPUID functions returning a single datum
++ */
++static inline unsigned int cpuid_eax(unsigned int op)
++{
++	unsigned int eax;
++
++	__asm__(XEN_CPUID
++		: "=a" (eax)
++		: "0" (op)
++		: "bx", "cx", "dx");
++	return eax;
++}
++static inline unsigned int cpuid_ebx(unsigned int op)
++{
++	unsigned int eax, ebx;
++
++	__asm__(XEN_CPUID
++		: "=a" (eax), "=b" (ebx)
++		: "0" (op)
++		: "cx", "dx" );
++	return ebx;
++}
++static inline unsigned int cpuid_ecx(unsigned int op)
++{
++	unsigned int eax, ecx;
++
++	__asm__(XEN_CPUID
++		: "=a" (eax), "=c" (ecx)
++		: "0" (op)
++		: "bx", "dx" );
++	return ecx;
++}
++static inline unsigned int cpuid_edx(unsigned int op)
++{
++	unsigned int eax, edx;
++
++	__asm__(XEN_CPUID
++		: "=a" (eax), "=d" (edx)
++		: "0" (op)
++		: "bx", "cx");
++	return edx;
++}
++
++#define load_cr3(pgdir) write_cr3(__pa(pgdir))
++
++/*
++ * Intel CPU features in CR4
++ */
++#define X86_CR4_VME		0x0001	/* enable vm86 extensions */
++#define X86_CR4_PVI		0x0002	/* virtual interrupts flag enable */
++#define X86_CR4_TSD		0x0004	/* disable time stamp at ipl 3 */
++#define X86_CR4_DE		0x0008	/* enable debugging extensions */
++#define X86_CR4_PSE		0x0010	/* enable page size extensions */
++#define X86_CR4_PAE		0x0020	/* enable physical address extensions */
++#define X86_CR4_MCE		0x0040	/* Machine check enable */
++#define X86_CR4_PGE		0x0080	/* enable global pages */
++#define X86_CR4_PCE		0x0100	/* enable performance counters at ipl 3 */
++#define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
++#define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
++
++/*
++ * Save the cr4 feature set we're using (ie
++ * Pentium 4MB enable and PPro Global page
++ * enable), so that any CPU's that boot up
++ * after us can get the correct flags.
++ */
++extern unsigned long mmu_cr4_features;
++
++static inline void set_in_cr4 (unsigned long mask)
++{
++	unsigned cr4;
++	mmu_cr4_features |= mask;
++	cr4 = read_cr4();
++	cr4 |= mask;
++	write_cr4(cr4);
++}
++
++static inline void clear_in_cr4 (unsigned long mask)
++{
++	unsigned cr4;
++	mmu_cr4_features &= ~mask;
++	cr4 = read_cr4();
++	cr4 &= ~mask;
++	write_cr4(cr4);
++}
++
++/*
++ *      NSC/Cyrix CPU configuration register indexes
++ */
++
++#define CX86_PCR0 0x20
++#define CX86_GCR  0xb8
++#define CX86_CCR0 0xc0
++#define CX86_CCR1 0xc1
++#define CX86_CCR2 0xc2
++#define CX86_CCR3 0xc3
++#define CX86_CCR4 0xe8
++#define CX86_CCR5 0xe9
++#define CX86_CCR6 0xea
++#define CX86_CCR7 0xeb
++#define CX86_PCR1 0xf0
++#define CX86_DIR0 0xfe
++#define CX86_DIR1 0xff
++#define CX86_ARR_BASE 0xc4
++#define CX86_RCR_BASE 0xdc
++
++/*
++ *      NSC/Cyrix CPU indexed register access macros
++ */
++
++#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
++
++#define setCx86(reg, data) do { \
++	outb((reg), 0x22); \
++	outb((data), 0x23); \
++} while (0)
++
++/* Stop speculative execution */
++static inline void sync_core(void)
++{
++	int tmp;
++	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
++}
++
++static inline void __monitor(const void *eax, unsigned long ecx,
++		unsigned long edx)
++{
++	/* "monitor %eax,%ecx,%edx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc8;"
++		: :"a" (eax), "c" (ecx), "d"(edx));
++}
++
++static inline void __mwait(unsigned long eax, unsigned long ecx)
++{
++	/* "mwait %eax,%ecx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc9;"
++		: :"a" (eax), "c" (ecx));
++}
++
++/* from system description table in BIOS.  Mostly for MCA use, but
++others may find it useful. */
++extern unsigned int machine_id;
++extern unsigned int machine_submodel_id;
++extern unsigned int BIOS_revision;
++extern unsigned int mca_pentium_flag;
++
++/* Boot loader type from the setup header */
++extern int bootloader_type;
++
++/*
++ * User space process size: 3GB (default).
++ */
++#define TASK_SIZE	(PAGE_OFFSET)
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
++
++#define HAVE_ARCH_PICK_MMAP_LAYOUT
++
++/*
++ * Size of io_bitmap.
++ */
++#define IO_BITMAP_BITS  65536
++#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
++#ifndef CONFIG_X86_NO_TSS
++#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
++#endif
++#define INVALID_IO_BITMAP_OFFSET 0x8000
++#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
++
++struct i387_fsave_struct {
++	long	cwd;
++	long	swd;
++	long	twd;
++	long	fip;
++	long	fcs;
++	long	foo;
++	long	fos;
++	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
++	long	status;		/* software status information */
++};
++
++struct i387_fxsave_struct {
++	unsigned short	cwd;
++	unsigned short	swd;
++	unsigned short	twd;
++	unsigned short	fop;
++	long	fip;
++	long	fcs;
++	long	foo;
++	long	fos;
++	long	mxcsr;
++	long	mxcsr_mask;
++	long	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
++	long	xmm_space[32];	/* 8*16 bytes for each XMM-reg = 128 bytes */
++	long	padding[56];
++} __attribute__ ((aligned (16)));
++
++struct i387_soft_struct {
++	long	cwd;
++	long	swd;
++	long	twd;
++	long	fip;
++	long	fcs;
++	long	foo;
++	long	fos;
++	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
++	unsigned char	ftop, changed, lookahead, no_update, rm, alimit;
++	struct info	*info;
++	unsigned long	entry_eip;
++};
++
++union i387_union {
++	struct i387_fsave_struct	fsave;
++	struct i387_fxsave_struct	fxsave;
++	struct i387_soft_struct soft;
++};
++
++typedef struct {
++	unsigned long seg;
++} mm_segment_t;
++
++struct thread_struct;
++
++#ifndef CONFIG_X86_NO_TSS
++struct tss_struct {
++	unsigned short	back_link,__blh;
++	unsigned long	esp0;
++	unsigned short	ss0,__ss0h;
++	unsigned long	esp1;
++	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
++	unsigned long	esp2;
++	unsigned short	ss2,__ss2h;
++	unsigned long	__cr3;
++	unsigned long	eip;
++	unsigned long	eflags;
++	unsigned long	eax,ecx,edx,ebx;
++	unsigned long	esp;
++	unsigned long	ebp;
++	unsigned long	esi;
++	unsigned long	edi;
++	unsigned short	es, __esh;
++	unsigned short	cs, __csh;
++	unsigned short	ss, __ssh;
++	unsigned short	ds, __dsh;
++	unsigned short	fs, __fsh;
++	unsigned short	gs, __gsh;
++	unsigned short	ldt, __ldth;
++	unsigned short	trace, io_bitmap_base;
++	/*
++	 * The extra 1 is there because the CPU will access an
++	 * additional byte beyond the end of the IO permission
++	 * bitmap. The extra byte must be all 1 bits, and must
++	 * be within the limit.
++	 */
++	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
++	/*
++	 * Cache the current maximum and the last task that used the bitmap:
++	 */
++	unsigned long io_bitmap_max;
++	struct thread_struct *io_bitmap_owner;
++	/*
++	 * pads the TSS to be cacheline-aligned (size is 0x100)
++	 */
++	unsigned long __cacheline_filler[35];
++	/*
++	 * .. and then another 0x100 bytes for emergency kernel stack
++	 */
++	unsigned long stack[64];
++} __attribute__((packed));
++#endif
++
++#define ARCH_MIN_TASKALIGN	16
++
++struct thread_struct {
++/* cached TLS descriptors. */
++	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
++	unsigned long	esp0;
++	unsigned long	sysenter_cs;
++	unsigned long	eip;
++	unsigned long	esp;
++	unsigned long	fs;
++	unsigned long	gs;
++/* Hardware debugging registers */
++	unsigned long	debugreg[8];  /* %%db0-7 debug registers */
++/* fault info */
++	unsigned long	cr2, trap_no, error_code;
++/* floating point info */
++	union i387_union	i387;
++/* virtual 86 mode info */
++	struct vm86_struct __user * vm86_info;
++	unsigned long		screen_bitmap;
++	unsigned long		v86flags, v86mask, saved_esp0;
++	unsigned int		saved_fs, saved_gs;
++/* IO permissions */
++	unsigned long	*io_bitmap_ptr;
++ 	unsigned long	iopl;
++/* max allowed port in the bitmap, in bytes: */
++	unsigned long	io_bitmap_max;
++};
++
++#define INIT_THREAD  {							\
++	.vm86_info = NULL,						\
++	.sysenter_cs = __KERNEL_CS,					\
++	.io_bitmap_ptr = NULL,						\
++}
++
++#ifndef CONFIG_X86_NO_TSS
++/*
++ * Note that the .io_bitmap member must be extra-big. This is because
++ * the CPU will access an additional byte beyond the end of the IO
++ * permission bitmap. The extra byte must be all 1 bits, and must
++ * be within the limit.
++ */
++#define INIT_TSS  {							\
++	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
++	.ss0		= __KERNEL_DS,					\
++	.ss1		= __KERNEL_CS,					\
++	.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,			\
++	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
++}
++
++static inline void __load_esp0(struct tss_struct *tss, struct thread_struct *thread)
++{
++	tss->esp0 = thread->esp0;
++	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
++	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
++		tss->ss1 = thread->sysenter_cs;
++		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
++	}
++}
++#define load_esp0(tss, thread) \
++	__load_esp0(tss, thread)
++#else
++#define load_esp0(tss, thread) do { \
++	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)) \
++		BUG(); \
++} while (0)
++#endif
++
++#define start_thread(regs, new_eip, new_esp) do {		\
++	__asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));	\
++	set_fs(USER_DS);					\
++	regs->xds = __USER_DS;					\
++	regs->xes = __USER_DS;					\
++	regs->xss = __USER_DS;					\
++	regs->xcs = __USER_CS;					\
++	regs->eip = new_eip;					\
++	regs->esp = new_esp;					\
++} while (0)
++
++/*
++ * These special macros can be used to get or set a debugging register
++ */
++#define get_debugreg(var, register)				\
++		(var) = HYPERVISOR_get_debugreg((register))
++#define set_debugreg(value, register)			\
++		WARN_ON(HYPERVISOR_set_debugreg((register), (value)))
++
++/*
++ * Set IOPL bits in EFLAGS from given mask
++ */
++static inline void set_iopl_mask(unsigned mask)
++{
++	struct physdev_set_iopl set_iopl;
++
++	/* Force the change at ring 0. */
++	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++}
++
++/* Forward declaration, a strange C thing */
++struct task_struct;
++struct mm_struct;
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++extern void prepare_to_copy(struct task_struct *tsk);
++
++/*
++ * create a kernel thread without removing it from tasklists
++ */
++extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
++
++extern unsigned long thread_saved_pc(struct task_struct *tsk);
++void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack);
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
++#define KSTK_TOP(info)                                                 \
++({                                                                     \
++       unsigned long *__ptr = (unsigned long *)(info);                 \
++       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
++})
++
++/*
++ * The below -8 is to reserve 8 bytes on top of the ring0 stack.
++ * This is necessary to guarantee that the entire "struct pt_regs"
++ * is accessable even if the CPU haven't stored the SS/ESP registers
++ * on the stack (interrupt gate does not save these registers
++ * when switching to the same priv ring).
++ * Therefore beware: accessing the xss/esp fields of the
++ * "struct pt_regs" is possible, but they may contain the
++ * completely wrong values.
++ */
++#define task_pt_regs(task)                                             \
++({                                                                     \
++       struct pt_regs *__regs__;                                       \
++       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
++       __regs__ - 1;                                                   \
++})
++
++#define KSTK_EIP(task) (task_pt_regs(task)->eip)
++#define KSTK_ESP(task) (task_pt_regs(task)->esp)
++
++
++struct microcode_header {
++	unsigned int hdrver;
++	unsigned int rev;
++	unsigned int date;
++	unsigned int sig;
++	unsigned int cksum;
++	unsigned int ldrver;
++	unsigned int pf;
++	unsigned int datasize;
++	unsigned int totalsize;
++	unsigned int reserved[3];
++};
++
++struct microcode {
++	struct microcode_header hdr;
++	unsigned int bits[0];
++};
++
++typedef struct microcode microcode_t;
++typedef struct microcode_header microcode_header_t;
++
++/* microcode format is extended from prescott processors */
++struct extended_signature {
++	unsigned int sig;
++	unsigned int pf;
++	unsigned int cksum;
++};
++
++struct extended_sigtable {
++	unsigned int count;
++	unsigned int cksum;
++	unsigned int reserved[3];
++	struct extended_signature sigs[0];
++};
++
++/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
++static inline void rep_nop(void)
++{
++	__asm__ __volatile__("rep;nop": : :"memory");
++}
++
++#define cpu_relax()	rep_nop()
++
++/* generic versions from gas */
++#define GENERIC_NOP1	".byte 0x90\n"
++#define GENERIC_NOP2    	".byte 0x89,0xf6\n"
++#define GENERIC_NOP3        ".byte 0x8d,0x76,0x00\n"
++#define GENERIC_NOP4        ".byte 0x8d,0x74,0x26,0x00\n"
++#define GENERIC_NOP5        GENERIC_NOP1 GENERIC_NOP4
++#define GENERIC_NOP6	".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
++#define GENERIC_NOP7	".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
++#define GENERIC_NOP8	GENERIC_NOP1 GENERIC_NOP7
++
++/* Opteron nops */
++#define K8_NOP1 GENERIC_NOP1
++#define K8_NOP2	".byte 0x66,0x90\n" 
++#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
++#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
++#define K8_NOP5	K8_NOP3 K8_NOP2 
++#define K8_NOP6	K8_NOP3 K8_NOP3
++#define K8_NOP7	K8_NOP4 K8_NOP3
++#define K8_NOP8	K8_NOP4 K8_NOP4
++
++/* K7 nops */
++/* uses eax dependencies (arbitary choice) */
++#define K7_NOP1  GENERIC_NOP1
++#define K7_NOP2	".byte 0x8b,0xc0\n" 
++#define K7_NOP3	".byte 0x8d,0x04,0x20\n"
++#define K7_NOP4	".byte 0x8d,0x44,0x20,0x00\n"
++#define K7_NOP5	K7_NOP4 ASM_NOP1
++#define K7_NOP6	".byte 0x8d,0x80,0,0,0,0\n"
++#define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
++#define K7_NOP8        K7_NOP7 ASM_NOP1
++
++#ifdef CONFIG_MK8
++#define ASM_NOP1 K8_NOP1
++#define ASM_NOP2 K8_NOP2
++#define ASM_NOP3 K8_NOP3
++#define ASM_NOP4 K8_NOP4
++#define ASM_NOP5 K8_NOP5
++#define ASM_NOP6 K8_NOP6
++#define ASM_NOP7 K8_NOP7
++#define ASM_NOP8 K8_NOP8
++#elif defined(CONFIG_MK7)
++#define ASM_NOP1 K7_NOP1
++#define ASM_NOP2 K7_NOP2
++#define ASM_NOP3 K7_NOP3
++#define ASM_NOP4 K7_NOP4
++#define ASM_NOP5 K7_NOP5
++#define ASM_NOP6 K7_NOP6
++#define ASM_NOP7 K7_NOP7
++#define ASM_NOP8 K7_NOP8
++#else
++#define ASM_NOP1 GENERIC_NOP1
++#define ASM_NOP2 GENERIC_NOP2
++#define ASM_NOP3 GENERIC_NOP3
++#define ASM_NOP4 GENERIC_NOP4
++#define ASM_NOP5 GENERIC_NOP5
++#define ASM_NOP6 GENERIC_NOP6
++#define ASM_NOP7 GENERIC_NOP7
++#define ASM_NOP8 GENERIC_NOP8
++#endif
++
++#define ASM_NOP_MAX 8
++
++/* Prefetch instructions for Pentium III and AMD Athlon */
++/* It's not worth to care about 3dnow! prefetches for the K6
++   because they are microcoded there and very slow.
++   However we don't do prefetches for pre XP Athlons currently
++   That should be fixed. */
++#define ARCH_HAS_PREFETCH
++static inline void prefetch(const void *x)
++{
++	alternative_input(ASM_NOP4,
++			  "prefetchnta (%1)",
++			  X86_FEATURE_XMM,
++			  "r" (x));
++}
++
++#define ARCH_HAS_PREFETCH
++#define ARCH_HAS_PREFETCHW
++#define ARCH_HAS_SPINLOCK_PREFETCH
++
++/* 3dnow! prefetch to get an exclusive cache line. Useful for 
++   spinlocks to avoid one state transition in the cache coherency protocol. */
++static inline void prefetchw(const void *x)
++{
++	alternative_input(ASM_NOP4,
++			  "prefetchw (%1)",
++			  X86_FEATURE_3DNOW,
++			  "r" (x));
++}
++#define spin_lock_prefetch(x)	prefetchw(x)
++
++extern void select_idle_routine(const struct cpuinfo_x86 *c);
++
++#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++
++extern unsigned long boot_option_idle_override;
++extern void enable_sep_cpu(void);
++extern int sysenter_setup(void);
++
++#endif /* __ASM_I386_PROCESSOR_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,103 @@
++#ifndef __ASM_SMP_H
++#define __ASM_SMP_H
++
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
++#ifndef __ASSEMBLY__
++#include <linux/kernel.h>
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC
++#ifndef __ASSEMBLY__
++#include <asm/fixmap.h>
++#include <asm/bitops.h>
++#include <asm/mpspec.h>
++#ifdef CONFIG_X86_IO_APIC
++#include <asm/io_apic.h>
++#endif
++#include <asm/apic.h>
++#endif
++#endif
++
++#define BAD_APICID 0xFFu
++#ifdef CONFIG_SMP
++#ifndef __ASSEMBLY__
++
++/*
++ * Private routines/data
++ */
++ 
++extern void smp_alloc_memory(void);
++extern int pic_mode;
++extern int smp_num_siblings;
++extern cpumask_t cpu_sibling_map[];
++extern cpumask_t cpu_core_map[];
++
++extern void (*mtrr_hook) (void);
++extern void zap_low_mappings (void);
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
++
++#define MAX_APICID 256
++extern u8 x86_cpu_to_apicid[];
++
++#define cpu_physical_id(cpu)	x86_cpu_to_apicid[cpu]
++
++#ifdef CONFIG_HOTPLUG_CPU
++extern void cpu_exit_clear(void);
++extern void cpu_uninit(void);
++#endif
++
++/*
++ * This function is needed by all SMP systems. It must _always_ be valid
++ * from the initial startup. We map APIC_BASE very early in page_setup(),
++ * so this is correct in the x86 case.
++ */
++#define raw_smp_processor_id() (current_thread_info()->cpu)
++
++extern cpumask_t cpu_possible_map;
++#define cpu_callin_map cpu_possible_map
++
++/* We don't mark CPUs online until __cpu_up(), so we need another measure */
++static inline int num_booting_cpus(void)
++{
++	return cpus_weight(cpu_possible_map);
++}
++
++#ifdef CONFIG_X86_LOCAL_APIC
++
++#ifdef APIC_DEFINITION
++extern int hard_smp_processor_id(void);
++#else
++#include <mach_apicdef.h>
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
++}
++#endif
++
++static __inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
++}
++
++#endif
++
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
++extern void prefill_possible_map(void);
++#endif /* !__ASSEMBLY__ */
++
++#else /* CONFIG_SMP */
++
++#define cpu_physical_id(cpu)		boot_cpu_physical_apicid
++
++#define NO_PROC_ID		0xFF		/* No processor magic marker */
++
++#endif
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/synch_bitops.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,126 @@
++#ifndef __XEN_SYNCH_BITOPS_H__
++#define __XEN_SYNCH_BITOPS_H__
++
++/*
++ * Copyright 1992, Linus Torvalds.
++ * Heavily modified to provide guaranteed strong synchronisation
++ * when communicating with Xen or other guest OSes running on other CPUs.
++ */
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#define ADDR (*(volatile long *) addr)
++
++static __inline__ void synch_set_bit(int nr, volatile void * addr)
++{
++    __asm__ __volatile__ ( 
++        "lock btsl %1,%0"
++        : "+m" (ADDR) : "Ir" (nr) : "memory" );
++}
++
++static __inline__ void synch_clear_bit(int nr, volatile void * addr)
++{
++    __asm__ __volatile__ (
++        "lock btrl %1,%0"
++        : "+m" (ADDR) : "Ir" (nr) : "memory" );
++}
++
++static __inline__ void synch_change_bit(int nr, volatile void * addr)
++{
++    __asm__ __volatile__ (
++        "lock btcl %1,%0"
++        : "+m" (ADDR) : "Ir" (nr) : "memory" );
++}
++
++static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
++{
++    int oldbit;
++    __asm__ __volatile__ (
++        "lock btsl %2,%1\n\tsbbl %0,%0"
++        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
++    return oldbit;
++}
++
++static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
++{
++    int oldbit;
++    __asm__ __volatile__ (
++        "lock btrl %2,%1\n\tsbbl %0,%0"
++        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
++    return oldbit;
++}
++
++static __inline__ int synch_test_and_change_bit(int nr, volatile void * addr)
++{
++    int oldbit;
++
++    __asm__ __volatile__ (
++        "lock btcl %2,%1\n\tsbbl %0,%0"
++        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
++    return oldbit;
++}
++
++struct __synch_xchg_dummy { unsigned long a[100]; };
++#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
++
++#define synch_cmpxchg(ptr, old, new) \
++((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
++                                     (unsigned long)(old), \
++                                     (unsigned long)(new), \
++                                     sizeof(*(ptr))))
++
++static inline unsigned long __synch_cmpxchg(volatile void *ptr,
++					    unsigned long old,
++					    unsigned long new, int size)
++{
++	unsigned long prev;
++	switch (size) {
++	case 1:
++		__asm__ __volatile__("lock; cmpxchgb %b1,%2"
++				     : "=a"(prev)
++				     : "q"(new), "m"(*__synch_xg(ptr)),
++				       "0"(old)
++				     : "memory");
++		return prev;
++	case 2:
++		__asm__ __volatile__("lock; cmpxchgw %w1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__synch_xg(ptr)),
++				       "0"(old)
++				     : "memory");
++		return prev;
++#ifdef CONFIG_X86_64
++	case 4:
++		__asm__ __volatile__("lock; cmpxchgl %k1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__synch_xg(ptr)),
++				       "0"(old)
++				     : "memory");
++		return prev;
++	case 8:
++		__asm__ __volatile__("lock; cmpxchgq %1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__synch_xg(ptr)),
++				       "0"(old)
++				     : "memory");
++		return prev;
++#else
++	case 4:
++		__asm__ __volatile__("lock; cmpxchgl %1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__synch_xg(ptr)),
++				       "0"(old)
++				     : "memory");
++		return prev;
++#endif
++	}
++	return old;
++}
++
++#define synch_test_bit test_bit
++
++#define synch_cmpxchg_subword synch_cmpxchg
++
++#endif /* __XEN_SYNCH_BITOPS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,488 @@
++#ifndef __ASM_SYSTEM_H
++#define __ASM_SYSTEM_H
++
++#include <linux/kernel.h>
++#include <asm/segment.h>
++#include <asm/cpufeature.h>
++#include <linux/bitops.h> /* for LOCK_PREFIX */
++#include <asm/synch_bitops.h>
++#include <asm/hypervisor.h>
++
++#ifdef __KERNEL__
++
++struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
++extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
++
++/*
++ * Saving eflags is important. It switches not only IOPL between tasks,
++ * it also protects other tasks from NT leaking through sysenter etc.
++ */
++#define switch_to(prev,next,last) do {					\
++	unsigned long esi,edi;						\
++	asm volatile("pushfl\n\t"		/* Save flags */	\
++		     "pushl %%ebp\n\t"					\
++		     "movl %%esp,%0\n\t"	/* save ESP */		\
++		     "movl %5,%%esp\n\t"	/* restore ESP */	\
++		     "movl $1f,%1\n\t"		/* save EIP */		\
++		     "pushl %6\n\t"		/* restore EIP */	\
++		     "jmp __switch_to\n"				\
++		     "1:\t"						\
++		     "popl %%ebp\n\t"					\
++		     "popfl"						\
++		     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\
++		      "=a" (last),"=S" (esi),"=D" (edi)			\
++		     :"m" (next->thread.esp),"m" (next->thread.eip),	\
++		      "2" (prev), "d" (next));				\
++} while (0)
++
++#define _set_base(addr,base) do { unsigned long __pr; \
++__asm__ __volatile__ ("movw %%dx,%1\n\t" \
++	"rorl $16,%%edx\n\t" \
++	"movb %%dl,%2\n\t" \
++	"movb %%dh,%3" \
++	:"=&d" (__pr) \
++	:"m" (*((addr)+2)), \
++	 "m" (*((addr)+4)), \
++	 "m" (*((addr)+7)), \
++         "0" (base) \
++        ); } while(0)
++
++#define _set_limit(addr,limit) do { unsigned long __lr; \
++__asm__ __volatile__ ("movw %%dx,%1\n\t" \
++	"rorl $16,%%edx\n\t" \
++	"movb %2,%%dh\n\t" \
++	"andb $0xf0,%%dh\n\t" \
++	"orb %%dh,%%dl\n\t" \
++	"movb %%dl,%2" \
++	:"=&d" (__lr) \
++	:"m" (*(addr)), \
++	 "m" (*((addr)+6)), \
++	 "0" (limit) \
++        ); } while(0)
++
++#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
++#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1) )
++
++/*
++ * Load a segment. Fall back on loading the zero
++ * segment if something goes wrong..
++ */
++#define loadsegment(seg,value)			\
++	asm volatile("\n"			\
++		"1:\t"				\
++		"mov %0,%%" #seg "\n"		\
++		"2:\n"				\
++		".section .fixup,\"ax\"\n"	\
++		"3:\t"				\
++		"pushl $0\n\t"			\
++		"popl %%" #seg "\n\t"		\
++		"jmp 2b\n"			\
++		".previous\n"			\
++		".section __ex_table,\"a\"\n\t"	\
++		".align 4\n\t"			\
++		".long 1b,3b\n"			\
++		".previous"			\
++		: :"rm" (value))
++
++/*
++ * Save a segment register away
++ */
++#define savesegment(seg, value) \
++	asm volatile("mov %%" #seg ",%0":"=rm" (value))
++
++#define read_cr0() ({ \
++	unsigned int __dummy; \
++	__asm__ __volatile__( \
++		"movl %%cr0,%0\n\t" \
++		:"=r" (__dummy)); \
++	__dummy; \
++})
++#define write_cr0(x) \
++	__asm__ __volatile__("movl %0,%%cr0": :"r" (x))
++
++#define read_cr2() (current_vcpu_info()->arch.cr2)
++#define write_cr2(x) \
++	__asm__ __volatile__("movl %0,%%cr2": :"r" (x))
++
++#define read_cr3() ({ \
++	unsigned int __dummy; \
++	__asm__ ( \
++		"movl %%cr3,%0\n\t" \
++		:"=r" (__dummy)); \
++	__dummy = xen_cr3_to_pfn(__dummy); \
++	mfn_to_pfn(__dummy) << PAGE_SHIFT; \
++})
++#define write_cr3(x) ({						\
++	unsigned int __dummy = pfn_to_mfn((x) >> PAGE_SHIFT);	\
++	__dummy = xen_pfn_to_cr3(__dummy);			\
++	__asm__ __volatile__("movl %0,%%cr3": :"r" (__dummy));	\
++})
++#define read_cr4() ({ \
++	unsigned int __dummy; \
++	__asm__( \
++		"movl %%cr4,%0\n\t" \
++		:"=r" (__dummy)); \
++	__dummy; \
++})
++#define read_cr4_safe() ({			      \
++	unsigned int __dummy;			      \
++	/* This could fault if %cr4 does not exist */ \
++	__asm__("1: movl %%cr4, %0		\n"   \
++		"2:				\n"   \
++		".section __ex_table,\"a\"	\n"   \
++		".long 1b,2b			\n"   \
++		".previous			\n"   \
++		: "=r" (__dummy): "0" (0));	      \
++	__dummy;				      \
++})
++
++#define write_cr4(x) \
++	__asm__ __volatile__("movl %0,%%cr4": :"r" (x))
++
++/*
++ * Clear and set 'TS' bit respectively
++ */
++#define clts() (HYPERVISOR_fpu_taskswitch(0))
++#define stts() (HYPERVISOR_fpu_taskswitch(1))
++
++#endif	/* __KERNEL__ */
++
++#define wbinvd() \
++	__asm__ __volatile__ ("wbinvd": : :"memory")
++
++static inline unsigned long get_limit(unsigned long segment)
++{
++	unsigned long __limit;
++	__asm__("lsll %1,%0"
++		:"=r" (__limit):"r" (segment));
++	return __limit+1;
++}
++
++#define nop() __asm__ __volatile__ ("nop")
++
++#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++
++#define tas(ptr) (xchg((ptr),1))
++
++struct __xchg_dummy { unsigned long a[100]; };
++#define __xg(x) ((struct __xchg_dummy *)(x))
++
++
++#ifdef CONFIG_X86_CMPXCHG64
++
++/*
++ * The semantics of XCHGCMP8B are a bit strange, this is why
++ * there is a loop and the loading of %%eax and %%edx has to
++ * be inside. This inlines well in most cases, the cached
++ * cost is around ~38 cycles. (in the future we might want
++ * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
++ * might have an implicit FPU-save as a cost, so it's not
++ * clear which path to go.)
++ *
++ * cmpxchg8b must be used with the lock prefix here to allow
++ * the instruction to be executed atomically, see page 3-102
++ * of the instruction set reference 24319102.pdf. We need
++ * the reader side to see the coherent 64bit value.
++ */
++static inline void __set_64bit (unsigned long long * ptr,
++		unsigned int low, unsigned int high)
++{
++	__asm__ __volatile__ (
++		"\n1:\t"
++		"movl (%0), %%eax\n\t"
++		"movl 4(%0), %%edx\n\t"
++		"lock cmpxchg8b (%0)\n\t"
++		"jnz 1b"
++		: /* no outputs */
++		:	"D"(ptr),
++			"b"(low),
++			"c"(high)
++		:	"ax","dx","memory");
++}
++
++static inline void __set_64bit_constant (unsigned long long *ptr,
++						 unsigned long long value)
++{
++	__set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
++}
++#define ll_low(x)	*(((unsigned int*)&(x))+0)
++#define ll_high(x)	*(((unsigned int*)&(x))+1)
++
++static inline void __set_64bit_var (unsigned long long *ptr,
++			 unsigned long long value)
++{
++	__set_64bit(ptr,ll_low(value), ll_high(value));
++}
++
++#define set_64bit(ptr,value) \
++(__builtin_constant_p(value) ? \
++ __set_64bit_constant(ptr, value) : \
++ __set_64bit_var(ptr, value) )
++
++#define _set_64bit(ptr,value) \
++(__builtin_constant_p(value) ? \
++ __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
++ __set_64bit(ptr, ll_low(value), ll_high(value)) )
++
++#endif
++
++/*
++ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
++ * Note 2: xchg has side effect, so that attribute volatile is necessary,
++ *	  but generally the primitive is invalid, *ptr is output argument. --ANK
++ */
++static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++{
++	switch (size) {
++		case 1:
++			__asm__ __volatile__("xchgb %b0,%1"
++				:"=q" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++		case 2:
++			__asm__ __volatile__("xchgw %w0,%1"
++				:"=r" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++		case 4:
++			__asm__ __volatile__("xchgl %0,%1"
++				:"=r" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++	}
++	return x;
++}
++
++/*
++ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
++ * store NEW in MEM.  Return the initial value in MEM.  Success is
++ * indicated by comparing RETURN with OLD.
++ */
++
++#ifdef CONFIG_X86_CMPXCHG
++#define __HAVE_ARCH_CMPXCHG 1
++#define cmpxchg(ptr,o,n)\
++	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
++					(unsigned long)(n),sizeof(*(ptr))))
++#endif
++
++static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
++				      unsigned long new, int size)
++{
++	unsigned long prev;
++	switch (size) {
++	case 1:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
++				     : "=a"(prev)
++				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 2:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 4:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	}
++	return old;
++}
++
++#ifndef CONFIG_X86_CMPXCHG
++/*
++ * Building a kernel capable running on 80386. It may be necessary to
++ * simulate the cmpxchg on the 80386 CPU. For that purpose we define
++ * a function for each of the sizes we support.
++ */
++
++extern unsigned long cmpxchg_386_u8(volatile void *, u8, u8);
++extern unsigned long cmpxchg_386_u16(volatile void *, u16, u16);
++extern unsigned long cmpxchg_386_u32(volatile void *, u32, u32);
++
++static inline unsigned long cmpxchg_386(volatile void *ptr, unsigned long old,
++				      unsigned long new, int size)
++{
++	switch (size) {
++	case 1:
++		return cmpxchg_386_u8(ptr, old, new);
++	case 2:
++		return cmpxchg_386_u16(ptr, old, new);
++	case 4:
++		return cmpxchg_386_u32(ptr, old, new);
++	}
++	return old;
++}
++
++#define cmpxchg(ptr,o,n)						\
++({									\
++	__typeof__(*(ptr)) __ret;					\
++	if (likely(boot_cpu_data.x86 > 3))				\
++		__ret = __cmpxchg((ptr), (unsigned long)(o),		\
++					(unsigned long)(n), sizeof(*(ptr))); \
++	else								\
++		__ret = cmpxchg_386((ptr), (unsigned long)(o),		\
++					(unsigned long)(n), sizeof(*(ptr))); \
++	__ret;								\
++})
++#endif
++
++#ifdef CONFIG_X86_CMPXCHG64
++
++static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long long old,
++				      unsigned long long new)
++{
++	unsigned long long prev;
++	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
++			     : "=A"(prev)
++			     : "b"((unsigned long)new),
++			       "c"((unsigned long)(new >> 32)),
++			       "m"(*__xg(ptr)),
++			       "0"(old)
++			     : "memory");
++	return prev;
++}
++
++#define cmpxchg64(ptr,o,n)\
++	((__typeof__(*(ptr)))__cmpxchg64((ptr),(unsigned long long)(o),\
++					(unsigned long long)(n)))
++
++#endif
++    
++/*
++ * Force strict CPU ordering.
++ * And yes, this is required on UP too when we're talking
++ * to devices.
++ *
++ * For now, "wmb()" doesn't actually do anything, as all
++ * Intel CPU's follow what Intel calls a *Processor Order*,
++ * in which all writes are seen in the program order even
++ * outside the CPU.
++ *
++ * I expect future Intel CPU's to have a weaker ordering,
++ * but I'd also expect them to finally get their act together
++ * and add some real memory barriers if so.
++ *
++ * Some non intel clones support out of order store. wmb() ceases to be a
++ * nop for these.
++ */
++ 
++
++/* 
++ * Actually only lfence would be needed for mb() because all stores done 
++ * by the kernel should be already ordered. But keep a full barrier for now. 
++ */
++
++#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
++#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
++
++/**
++ * read_barrier_depends - Flush all pending reads that subsequents reads
++ * depend on.
++ *
++ * No data-dependent reads from memory-like regions are ever reordered
++ * over this barrier.  All reads preceding this primitive are guaranteed
++ * to access memory (but not necessarily other CPUs' caches) before any
++ * reads following this primitive that depend on the data return by
++ * any of the preceding reads.  This primitive is much lighter weight than
++ * rmb() on most CPUs, and is never heavier weight than is
++ * rmb().
++ *
++ * These ordering constraints are respected by both the local CPU
++ * and the compiler.
++ *
++ * Ordering is not guaranteed by anything other than these primitives,
++ * not even by data dependencies.  See the documentation for
++ * memory_barrier() for examples and URLs to more information.
++ *
++ * For example, the following code would force ordering (the initial
++ * value of "a" is zero, "b" is one, and "p" is "&a"):
++ *
++ * <programlisting>
++ *	CPU 0				CPU 1
++ *
++ *	b = 2;
++ *	memory_barrier();
++ *	p = &b;				q = p;
++ *					read_barrier_depends();
++ *					d = *q;
++ * </programlisting>
++ *
++ * because the read of "*q" depends on the read of "p" and these
++ * two reads are separated by a read_barrier_depends().  However,
++ * the following code, with the same initial values for "a" and "b":
++ *
++ * <programlisting>
++ *	CPU 0				CPU 1
++ *
++ *	a = 2;
++ *	memory_barrier();
++ *	b = 3;				y = b;
++ *					read_barrier_depends();
++ *					x = a;
++ * </programlisting>
++ *
++ * does not enforce ordering, since there is no data dependency between
++ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
++ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
++ * in cases like this where there are no data dependencies.
++ **/
++
++#define read_barrier_depends()	do { } while(0)
++
++#ifdef CONFIG_X86_OOSTORE
++/* Actually there are no OOO store capable CPUs for now that do SSE, 
++   but make it already an possibility. */
++#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
++#else
++#define wmb()	__asm__ __volatile__ ("": : :"memory")
++#endif
++
++#ifdef CONFIG_SMP
++#define smp_mb()	mb()
++#define smp_rmb()	rmb()
++#define smp_wmb()	wmb()
++#define smp_read_barrier_depends()	read_barrier_depends()
++#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#else
++#define smp_mb()	barrier()
++#define smp_rmb()	barrier()
++#define smp_wmb()	barrier()
++#define smp_read_barrier_depends()	do { } while(0)
++#define set_mb(var, value) do { var = value; barrier(); } while (0)
++#endif
++
++#include <linux/irqflags.h>
++
++/*
++ * disable hlt during certain critical i/o operations
++ */
++#define HAVE_DISABLE_HLT
++void disable_hlt(void);
++void enable_hlt(void);
++
++extern int es7000_plat;
++void cpu_idle_wait(void);
++
++/*
++ * On SMP systems, when the scheduler does migration-cost autodetection,
++ * it needs a way to flush as much of the CPU's caches as possible:
++ */
++static inline void sched_cacheflush(void)
++{
++	wbinvd();
++}
++
++extern unsigned long arch_align_stack(unsigned long sp);
++extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
++
++void default_idle(void);
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_32.h	2007-11-26 16:59:25.000000000 +0100
+@@ -0,0 +1,101 @@
++#ifndef _I386_TLBFLUSH_H
++#define _I386_TLBFLUSH_H
++
++#include <linux/mm.h>
++#include <asm/processor.h>
++
++#define __flush_tlb() xen_tlb_flush()
++#define __flush_tlb_global() xen_tlb_flush()
++#define __flush_tlb_all() xen_tlb_flush()
++
++extern unsigned long pgkern_mask;
++
++#define cpu_has_invlpg	(boot_cpu_data.x86 > 3)
++
++#define __flush_tlb_single(addr) xen_invlpg(addr)
++
++#define __flush_tlb_one(addr) __flush_tlb_single(addr)
++
++/*
++ * TLB flushing:
++ *
++ *  - flush_tlb() flushes the current mm struct TLBs
++ *  - flush_tlb_all() flushes all processes TLBs
++ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
++ *  - flush_tlb_page(vma, vmaddr) flushes one page
++ *  - flush_tlb_range(vma, start, end) flushes a range of pages
++ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
++ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
++ *
++ * ..but the i386 has somewhat limited tlb flushing capabilities,
++ * and page-granular flushes are available only on i486 and up.
++ */
++
++#ifndef CONFIG_SMP
++
++#define flush_tlb() __flush_tlb()
++#define flush_tlb_all() __flush_tlb_all()
++#define local_flush_tlb() __flush_tlb()
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++	if (mm == current->active_mm)
++		__flush_tlb();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma,
++	unsigned long addr)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb_one(addr);
++}
++
++static inline void flush_tlb_range(struct vm_area_struct *vma,
++	unsigned long start, unsigned long end)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb();
++}
++
++#else
++
++#include <asm/smp.h>
++
++#define local_flush_tlb() \
++	__flush_tlb()
++
++#define flush_tlb_all xen_tlb_flush_all
++#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
++#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
++#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
++
++#define flush_tlb()	flush_tlb_current_task()
++
++static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
++{
++	flush_tlb_mm(vma->vm_mm);
++}
++
++#define TLBSTATE_OK	1
++#define TLBSTATE_LAZY	2
++
++struct tlb_state
++{
++	struct mm_struct *active_mm;
++	int state;
++	char __cacheline_padding[L1_CACHE_BYTES-8];
++};
++DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
++
++
++#endif
++
++#define flush_tlb_kernel_range(start, end) flush_tlb_all()
++
++static inline void flush_tlb_pgtables(struct mm_struct *mm,
++				      unsigned long start, unsigned long end)
++{
++	/* i386 does not keep any page table caches in TLB */
++}
++
++#endif /* _I386_TLBFLUSH_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/vga.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,20 @@
++/*
++ *	Access to VGA videoram
++ *
++ *	(c) 1998 Martin Mares <mj@ucw.cz>
++ */
++
++#ifndef _LINUX_ASM_VGA_H_
++#define _LINUX_ASM_VGA_H_
++
++/*
++ *	On the PC, we can just recalculate addresses and then
++ *	access the videoram directly without any black magic.
++ */
++
++#define VGA_MAP_MEM(x,s) (unsigned long)isa_bus_to_virt(x)
++
++#define vga_readb(x) (*(x))
++#define vga_writeb(x,y) (*(y) = (x))
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xenoprof.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,48 @@
++/******************************************************************************
++ * asm-i386/mach-xen/asm/xenoprof.h
++ *
++ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan K.K.
++ *
++ * 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 __ASM_XENOPROF_H__
++#define __ASM_XENOPROF_H__
++#ifdef CONFIG_XEN
++
++struct super_block;
++struct dentry;
++int xenoprof_create_files(struct super_block * sb, struct dentry * root);
++#define HAVE_XENOPROF_CREATE_FILES
++
++struct xenoprof_init;
++void xenoprof_arch_init_counter(struct xenoprof_init *init);
++void xenoprof_arch_counter(void);
++void xenoprof_arch_start(void);
++void xenoprof_arch_stop(void);
++
++struct xenoprof_arch_shared_buffer {
++	/* nothing */
++};
++struct xenoprof_shared_buffer;
++void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf);
++struct xenoprof_get_buffer;
++int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf);
++struct xenoprof_passive;
++int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf);
++
++#endif /* CONFIG_XEN */
++#endif /* __ASM_XENOPROF_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/irq_vectors.h	2008-09-25 13:55:32.000000000 +0200
+@@ -0,0 +1,125 @@
++/*
++ * This file should contain #defines for all of the interrupt vector
++ * numbers used by this architecture.
++ *
++ * In addition, there are some standard defines:
++ *
++ *	FIRST_EXTERNAL_VECTOR:
++ *		The first free place for external interrupts
++ *
++ *	SYSCALL_VECTOR:
++ *		The IRQ vector a syscall makes the user to kernel transition
++ *		under.
++ *
++ *	TIMER_IRQ:
++ *		The IRQ number the timer interrupt comes in at.
++ *
++ *	NR_IRQS:
++ *		The total number of interrupt vectors (including all the
++ *		architecture specific interrupts) needed.
++ *
++ */			
++#ifndef _ASM_IRQ_VECTORS_H
++#define _ASM_IRQ_VECTORS_H
++
++/*
++ * IDT vectors usable for external interrupt sources start
++ * at 0x20:
++ */
++#define FIRST_EXTERNAL_VECTOR	0x20
++
++#define SYSCALL_VECTOR		0x80
++
++/*
++ * Vectors 0x20-0x2f are used for ISA interrupts.
++ */
++
++#if 0
++/*
++ * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
++ *
++ *  some of the following vectors are 'rare', they are merged
++ *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
++ *  TLB, reschedule and local APIC vectors are performance-critical.
++ *
++ *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
++ */
++#define SPURIOUS_APIC_VECTOR	0xff
++#define ERROR_APIC_VECTOR	0xfe
++#define INVALIDATE_TLB_VECTOR	0xfd
++#define RESCHEDULE_VECTOR	0xfc
++#define CALL_FUNCTION_VECTOR	0xfb
++
++#define THERMAL_APIC_VECTOR	0xf0
++/*
++ * Local APIC timer IRQ vector is on a different priority level,
++ * to work around the 'lost local interrupt if more than 2 IRQ
++ * sources per level' errata.
++ */
++#define LOCAL_TIMER_VECTOR	0xef
++#endif
++
++#define SPURIOUS_APIC_VECTOR	0xff
++#define ERROR_APIC_VECTOR	0xfe
++
++/*
++ * First APIC vector available to drivers: (vectors 0x30-0xee)
++ * we start at 0x31 to spread out vectors evenly between priority
++ * levels. (0x80 is the syscall vector)
++ */
++#define FIRST_DEVICE_VECTOR	0x31
++#define FIRST_SYSTEM_VECTOR	0xef
++
++/*
++ * 16 8259A IRQ's, 208 potential APIC interrupt sources.
++ * Right now the APIC is mostly only used for SMP.
++ * 256 vectors is an architectural limit. (we can have
++ * more than 256 devices theoretically, but they will
++ * have to use shared interrupts)
++ * Since vectors 0x00-0x1f are used/reserved for the CPU,
++ * the usable vector space is 0x20-0xff (224 vectors)
++ */
++
++#define RESCHEDULE_VECTOR	0
++#define CALL_FUNCTION_VECTOR	1
++#define NR_IPIS			2
++
++/*
++ * The maximum number of vectors supported by i386 processors
++ * is limited to 256. For processors other than i386, NR_VECTORS
++ * should be changed accordingly.
++ */
++#define NR_VECTORS 256
++
++#define FPU_IRQ			13
++
++#define	FIRST_VM86_IRQ		3
++#define LAST_VM86_IRQ		15
++#define invalid_vm86_irq(irq)	((irq) < 3 || (irq) > 15)
++
++/*
++ * The flat IRQ space is divided into two regions:
++ *  1. A one-to-one mapping of real physical IRQs. This space is only used
++ *     if we have physical device-access privilege. This region is at the 
++ *     start of the IRQ space so that existing device drivers do not need
++ *     to be modified to translate physical IRQ numbers into our IRQ space.
++ *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
++ *     are bound using the provided bind/unbind functions.
++ */
++
++#define PIRQ_BASE		0
++#if !defined(MAX_IO_APICS)
++# define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
++#elif NR_CPUS < MAX_IO_APICS
++# define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
++#else
++# define NR_PIRQS		(NR_VECTORS + 32 * MAX_IO_APICS)
++#endif
++
++#define DYNIRQ_BASE		(PIRQ_BASE + NR_PIRQS)
++#define NR_DYNIRQS		256
++
++#define NR_IRQS			(NR_PIRQS + NR_DYNIRQS)
++#define NR_IRQ_VECTORS		NR_IRQS
++
++#endif /* _ASM_IRQ_VECTORS_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mach_traps.h	2007-06-12 13:14:02.000000000 +0200
+@@ -0,0 +1,33 @@
++/*
++ *  include/asm-xen/asm-i386/mach-xen/mach_traps.h
++ *
++ *  Machine specific NMI handling for Xen
++ */
++#ifndef _MACH_TRAPS_H
++#define _MACH_TRAPS_H
++
++#include <linux/bitops.h>
++#include <xen/interface/nmi.h>
++
++static inline void clear_mem_error(unsigned char reason) {}
++static inline void clear_io_check_error(unsigned char reason) {}
++
++static inline unsigned char get_nmi_reason(void)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	unsigned char reason = 0;
++
++	/* construct a value which looks like it came from
++	 * port 0x61.
++	 */
++	if (test_bit(_XEN_NMIREASON_io_error, &s->arch.nmi_reason))
++		reason |= 0x40;
++	if (test_bit(_XEN_NMIREASON_parity_error, &s->arch.nmi_reason))
++		reason |= 0x80;
++
++        return reason;
++}
++
++static inline void reassert_nmi(void) {}
++
++#endif /* !_MACH_TRAPS_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_64.h	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,265 @@
++/* Written 2000 by Andi Kleen */ 
++#ifndef __ARCH_DESC_H
++#define __ARCH_DESC_H
++
++#include <linux/threads.h>
++#include <asm/ldt.h>
++
++#ifndef __ASSEMBLY__
++
++#include <linux/string.h>
++#include <linux/smp.h>
++
++#include <asm/segment.h>
++#include <asm/mmu.h>
++
++// 8 byte segment descriptor
++struct desc_struct { 
++	u16 limit0;
++	u16 base0;
++	unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
++	unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
++} __attribute__((packed)); 
++
++struct n_desc_struct { 
++	unsigned int a,b;
++}; 	
++
++enum { 
++	GATE_INTERRUPT = 0xE, 
++	GATE_TRAP = 0xF, 	
++	GATE_CALL = 0xC,
++}; 	
++
++// 16byte gate
++struct gate_struct {          
++	u16 offset_low;
++	u16 segment; 
++	unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
++	u16 offset_middle;
++	u32 offset_high;
++	u32 zero1; 
++} __attribute__((packed));
++
++#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF) 
++#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
++#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
++
++enum { 
++	DESC_TSS = 0x9,
++	DESC_LDT = 0x2,
++}; 
++
++// LDT or TSS descriptor in the GDT. 16 bytes.
++struct ldttss_desc { 
++	u16 limit0;
++	u16 base0;
++	unsigned base1 : 8, type : 5, dpl : 2, p : 1;
++	unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
++	u32 base3;
++	u32 zero1; 
++} __attribute__((packed)); 
++
++struct desc_ptr {
++	unsigned short size;
++	unsigned long address;
++} __attribute__((packed)) ;
++
++extern struct desc_ptr idt_descr, cpu_gdt_descr[NR_CPUS];
++
++extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
++
++#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
++#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
++
++static inline void clear_LDT(void)
++{
++	int cpu = get_cpu();
++
++	/*
++	 * NB. We load the default_ldt for lcall7/27 handling on demand, as
++	 * it slows down context switching. Noone uses it anyway.
++	 */
++	cpu = cpu;              /* XXX avoid compiler warning */
++	xen_set_ldt(NULL, 0);
++	put_cpu();
++}
++
++/*
++ * This is the ldt that every process will get unless we need
++ * something other than this.
++ */
++extern struct desc_struct default_ldt[];
++#ifndef CONFIG_X86_NO_IDT
++extern struct gate_struct idt_table[]; 
++#endif
++extern struct desc_ptr cpu_gdt_descr[];
++
++/* the cpu gdt accessor */
++#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
++
++static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)  
++{
++	struct gate_struct s; 	
++	s.offset_low = PTR_LOW(func); 
++	s.segment = __KERNEL_CS;
++	s.ist = ist; 
++	s.p = 1;
++	s.dpl = dpl; 
++	s.zero0 = 0;
++	s.zero1 = 0; 
++	s.type = type; 
++	s.offset_middle = PTR_MIDDLE(func); 
++	s.offset_high = PTR_HIGH(func); 
++	/* does not need to be atomic because it is only done once at setup time */ 
++	memcpy(adr, &s, 16); 
++} 
++
++#ifndef CONFIG_X86_NO_IDT
++static inline void set_intr_gate(int nr, void *func) 
++{ 
++	BUG_ON((unsigned)nr > 0xFF);
++	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); 
++} 
++
++static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) 
++{ 
++	BUG_ON((unsigned)nr > 0xFF);
++	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); 
++} 
++
++static inline void set_system_gate(int nr, void *func) 
++{ 
++	BUG_ON((unsigned)nr > 0xFF);
++	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); 
++} 
++
++static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
++{
++	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
++}
++#endif
++
++static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
++					 unsigned size) 
++{ 
++	struct ldttss_desc d;
++	memset(&d,0,sizeof(d)); 
++	d.limit0 = size & 0xFFFF;
++	d.base0 = PTR_LOW(tss); 
++	d.base1 = PTR_MIDDLE(tss) & 0xFF; 
++	d.type = type;
++	d.p = 1; 
++	d.limit1 = (size >> 16) & 0xF;
++	d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF; 
++	d.base3 = PTR_HIGH(tss); 
++	memcpy(ptr, &d, 16); 
++}
++
++#ifndef CONFIG_X86_NO_TSS
++static inline void set_tss_desc(unsigned cpu, void *addr)
++{ 
++	/*
++	 * sizeof(unsigned long) coming from an extra "long" at the end
++	 * of the iobitmap. See tss_struct definition in processor.h
++	 *
++	 * -1? seg base+limit should be pointing to the address of the
++	 * last valid byte
++	 */
++	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS], 
++		(unsigned long)addr, DESC_TSS,
++		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
++} 
++#endif
++
++static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
++{ 
++	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
++			      DESC_LDT, size * 8 - 1);
++}
++
++static inline void set_seg_base(unsigned cpu, int entry, void *base)
++{ 
++	struct desc_struct *d = &cpu_gdt(cpu)[entry];
++	u32 addr = (u32)(u64)base;
++	BUG_ON((u64)base >> 32); 
++	d->base0 = addr & 0xffff;
++	d->base1 = (addr >> 16) & 0xff;
++	d->base2 = (addr >> 24) & 0xff;
++} 
++
++#define LDT_entry_a(info) \
++	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
++/* Don't allow setting of the lm bit. It is useless anyways because 
++   64bit system calls require __USER_CS. */ 
++#define LDT_entry_b(info) \
++	(((info)->base_addr & 0xff000000) | \
++	(((info)->base_addr & 0x00ff0000) >> 16) | \
++	((info)->limit & 0xf0000) | \
++	(((info)->read_exec_only ^ 1) << 9) | \
++	((info)->contents << 10) | \
++	(((info)->seg_not_present ^ 1) << 15) | \
++	((info)->seg_32bit << 22) | \
++	((info)->limit_in_pages << 23) | \
++	((info)->useable << 20) | \
++	/* ((info)->lm << 21) | */ \
++	0x7000)
++
++#define LDT_empty(info) (\
++	(info)->base_addr	== 0	&& \
++	(info)->limit		== 0	&& \
++	(info)->contents	== 0	&& \
++	(info)->read_exec_only	== 1	&& \
++	(info)->seg_32bit	== 0	&& \
++	(info)->limit_in_pages	== 0	&& \
++	(info)->seg_not_present	== 1	&& \
++	(info)->useable		== 0	&& \
++	(info)->lm		== 0)
++
++#if TLS_SIZE != 24
++# error update this code.
++#endif
++
++static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
++{
++#if 0
++	u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
++	gdt[0] = t->tls_array[0];
++	gdt[1] = t->tls_array[1];
++	gdt[2] = t->tls_array[2];
++#endif
++#define C(i) \
++	if (HYPERVISOR_update_descriptor(virt_to_machine(&cpu_gdt(cpu)[GDT_ENTRY_TLS_MIN + i]), \
++						 t->tls_array[i])) \
++		BUG();
++
++	C(0); C(1); C(2);
++#undef C
++} 
++
++/*
++ * load one particular LDT into the current CPU
++ */
++static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
++{
++	void *segments = pc->ldt;
++	int count = pc->size;
++
++	if (likely(!count))
++		segments = NULL;
++
++	xen_set_ldt(segments, count);
++}
++
++static inline void load_LDT(mm_context_t *pc)
++{
++	int cpu = get_cpu();
++	load_LDT_nolock(pc, cpu);
++	put_cpu();
++}
++
++extern struct desc_ptr idt_descr;
++
++#endif /* !__ASSEMBLY__ */
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,112 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1998 Ingo Molnar
++ */
++
++#ifndef _ASM_FIXMAP_H
++#define _ASM_FIXMAP_H
++
++#include <linux/kernel.h>
++#include <asm/apicdef.h>
++#include <asm/page.h>
++#include <asm/vsyscall.h>
++#include <asm/vsyscall32.h>
++#include <asm/acpi.h>
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process.
++ *
++ * these 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages. (or larger if used with an increment
++ * highger than 1) use fixmap_set(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++
++enum fixed_addresses {
++	VSYSCALL_LAST_PAGE,
++	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
++	VSYSCALL_HPET,
++	FIX_HPET_BASE,
++#ifdef CONFIG_X86_LOCAL_APIC
++	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
++#endif
++#ifdef CONFIG_X86_IO_APIC
++	FIX_IO_APIC_BASE_0,
++	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
++#endif
++#ifdef CONFIG_ACPI
++	FIX_ACPI_BEGIN,
++	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
++#endif
++	FIX_SHARED_INFO,
++#define NR_FIX_ISAMAPS	256
++	FIX_ISAMAP_END,
++	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
++	__end_of_permanent_fixed_addresses,
++	/* temporary boot-time mappings, used before ioremap() is functional */
++#define NR_FIX_BTMAPS	16
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
++	__end_of_fixed_addresses
++};
++
++extern void __set_fixmap (enum fixed_addresses idx,
++					unsigned long phys, pgprot_t flags);
++
++#define set_fixmap(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL)
++/*
++ * Some hardware wants to get fixmapped without caching.
++ */
++#define set_fixmap_nocache(idx, phys) \
++		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
++
++#define clear_fixmap(idx) \
++                __set_fixmap(idx, 0, __pgprot(0))
++
++#define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
++#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
++#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
++
++/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
++#define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
++#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
++
++#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
++
++extern void __this_fixmap_does_not_exist(void);
++
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without translation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++static __always_inline unsigned long fix_to_virt(const unsigned int idx)
++{
++	/*
++	 * this branch gets completely eliminated after inlining,
++	 * except when someone tries to use fixaddr indices in an
++	 * illegal way. (such as mixing up address types or using
++	 * out-of-range indices).
++	 *
++	 * If it doesn't get removed, the linker will complain
++	 * loudly with a reasonably clear error message..
++	 */
++	if (idx >= __end_of_fixed_addresses)
++		__this_fixmap_does_not_exist();
++
++        return __fix_to_virt(idx);
++}
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_64.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,422 @@
++/******************************************************************************
++ * hypercall.h
++ * 
++ * Linux-specific hypervisor handling.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser
++ * 
++ * 64-bit updates:
++ *   Benjamin Liu <benjamin.liu@intel.com>
++ *   Jun Nakajima <jun.nakajima@intel.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; 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 __HYPERCALL_H__
++#define __HYPERCALL_H__
++
++#include <linux/string.h> /* memcpy() */
++#include <linux/stringify.h>
++#include <xen/interface/arch-x86/xen-mca.h>
++
++#ifndef __HYPERVISOR_H__
++# error "please don't include this file directly"
++#endif
++
++#ifdef CONFIG_XEN
++#define HYPERCALL_STR(name)					\
++	"call hypercall_page + ("__stringify(__HYPERVISOR_##name)" * 32)"
++#else
++#define HYPERCALL_STR(name)					\
++	"mov $("__stringify(__HYPERVISOR_##name)" * 32),%%eax; "\
++	"add hypercall_stubs(%%rip),%%rax; "			\
++	"call *%%rax"
++#endif
++
++#define _hypercall0(type, name)			\
++({						\
++	type __res;				\
++	asm volatile (				\
++		HYPERCALL_STR(name)		\
++		: "=a" (__res)			\
++		:				\
++		: "memory" );			\
++	__res;					\
++})
++
++#define _hypercall1(type, name, a1)				\
++({								\
++	type __res;						\
++	long __ign1;						\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=D" (__ign1)			\
++		: "1" ((long)(a1))				\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall2(type, name, a1, a2)				\
++({								\
++	type __res;						\
++	long __ign1, __ign2;					\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
++		: "1" ((long)(a1)), "2" ((long)(a2))		\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall3(type, name, a1, a2, a3)			\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3;				\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
++		"=d" (__ign3)					\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		"3" ((long)(a3))				\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall4(type, name, a1, a2, a3, a4)			\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3;				\
++	register long __arg4 asm("r10") = (long)(a4);		\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
++		  "=d" (__ign3), "+r" (__arg4)			\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		  "3" ((long)(a3))				\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	long __ign1, __ign2, __ign3;				\
++	register long __arg4 asm("r10") = (long)(a4);		\
++	register long __arg5 asm("r8") = (long)(a5);		\
++	asm volatile (						\
++		HYPERCALL_STR(name)				\
++		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
++		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
++		: "1" ((long)(a1)), "2" ((long)(a2)),		\
++		  "3" ((long)(a3))				\
++		: "memory" );					\
++	__res;							\
++})
++
++static inline int __must_check
++HYPERVISOR_set_trap_table(
++	const trap_info_t *table)
++{
++	return _hypercall1(int, set_trap_table, table);
++}
++
++static inline int __must_check
++HYPERVISOR_mmu_update(
++	mmu_update_t *req, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	return _hypercall4(int, mmu_update, req, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_mmuext_op(
++	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_set_gdt(
++	unsigned long *frame_list, unsigned int entries)
++{
++	return _hypercall2(int, set_gdt, frame_list, entries);
++}
++
++static inline int __must_check
++HYPERVISOR_stack_switch(
++	unsigned long ss, unsigned long esp)
++{
++	return _hypercall2(int, stack_switch, ss, esp);
++}
++
++static inline int __must_check
++HYPERVISOR_set_callbacks(
++	unsigned long event_address, unsigned long failsafe_address, 
++	unsigned long syscall_address)
++{
++	return _hypercall3(int, set_callbacks,
++			   event_address, failsafe_address, syscall_address);
++}
++
++static inline int
++HYPERVISOR_fpu_taskswitch(
++	int set)
++{
++	return _hypercall1(int, fpu_taskswitch, set);
++}
++
++static inline int __must_check
++HYPERVISOR_sched_op_compat(
++	int cmd, unsigned long arg)
++{
++	return _hypercall2(int, sched_op_compat, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_sched_op(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, sched_op, cmd, arg);
++}
++
++static inline long __must_check
++HYPERVISOR_set_timer_op(
++	u64 timeout)
++{
++	return _hypercall1(long, set_timer_op, timeout);
++}
++
++static inline int __must_check
++HYPERVISOR_platform_op(
++	struct xen_platform_op *platform_op)
++{
++	platform_op->interface_version = XENPF_INTERFACE_VERSION;
++	return _hypercall1(int, platform_op, platform_op);
++}
++static inline int __must_check
++HYPERVISOR_mca(
++	struct xen_mc *mc_op)
++{
++	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
++	return _hypercall1(int, mca, mc_op);
++}
++static inline int __must_check
++HYPERVISOR_set_debugreg(
++	unsigned int reg, unsigned long value)
++{
++	return _hypercall2(int, set_debugreg, reg, value);
++}
++
++static inline unsigned long __must_check
++HYPERVISOR_get_debugreg(
++	unsigned int reg)
++{
++	return _hypercall1(unsigned long, get_debugreg, reg);
++}
++
++static inline int __must_check
++HYPERVISOR_update_descriptor(
++	unsigned long ma, unsigned long word)
++{
++	return _hypercall2(int, update_descriptor, ma, word);
++}
++
++static inline int __must_check
++HYPERVISOR_memory_op(
++	unsigned int cmd, void *arg)
++{
++	return _hypercall2(int, memory_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_multicall(
++	multicall_entry_t *call_list, unsigned int nr_calls)
++{
++	return _hypercall2(int, multicall, call_list, nr_calls);
++}
++
++static inline int __must_check
++HYPERVISOR_update_va_mapping(
++	unsigned long va, pte_t new_val, unsigned long flags)
++{
++	return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
++}
++
++static inline int __must_check
++HYPERVISOR_event_channel_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, event_channel_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct evtchn_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, event_channel_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_xen_version(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, xen_version, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_console_io(
++	int cmd, unsigned int count, char *str)
++{
++	return _hypercall3(int, console_io, cmd, count, str);
++}
++
++static inline int __must_check
++HYPERVISOR_physdev_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, physdev_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct physdev_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, physdev_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_grant_table_op(
++	unsigned int cmd, void *uop, unsigned int count)
++{
++	return _hypercall3(int, grant_table_op, cmd, uop, count);
++}
++
++static inline int __must_check
++HYPERVISOR_update_va_mapping_otherdomain(
++	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
++{
++	return _hypercall4(int, update_va_mapping_otherdomain, va,
++			   new_val.pte, flags, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_vm_assist(
++	unsigned int cmd, unsigned int type)
++{
++	return _hypercall2(int, vm_assist, cmd, type);
++}
++
++static inline int __must_check
++HYPERVISOR_vcpu_op(
++	int cmd, unsigned int vcpuid, void *extra_args)
++{
++	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
++}
++
++static inline int __must_check
++HYPERVISOR_set_segment_base(
++	int reg, unsigned long value)
++{
++	return _hypercall2(int, set_segment_base, reg, value);
++}
++
++static inline int __must_check
++HYPERVISOR_suspend(
++	unsigned long srec)
++{
++	struct sched_shutdown sched_shutdown = {
++		.reason = SHUTDOWN_suspend
++	};
++
++	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
++			     &sched_shutdown, srec);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
++				 SHUTDOWN_suspend, srec);
++#endif
++
++	return rc;
++}
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++static inline int
++HYPERVISOR_nmi_op(
++	unsigned long op, void *arg)
++{
++	return _hypercall2(int, nmi_op, op, arg);
++}
++#endif
++
++#ifndef CONFIG_XEN
++static inline unsigned long __must_check
++HYPERVISOR_hvm_op(
++    int op, void *arg)
++{
++    return _hypercall2(unsigned long, hvm_op, op, arg);
++}
++#endif
++
++static inline int __must_check
++HYPERVISOR_callback_op(
++	int cmd, const void *arg)
++{
++	return _hypercall2(int, callback_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_xenoprof_op(
++	int op, void *arg)
++{
++	return _hypercall2(int, xenoprof_op, op, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_kexec_op(
++	unsigned long op, void *args)
++{
++	return _hypercall2(int, kexec_op, op, args);
++}
++
++static inline int __must_check
++HYPERVISOR_tmem_op(
++	struct tmem_op *op)
++{
++	return _hypercall1(int, tmem_op, op);
++}
++
++#endif /* __HYPERCALL_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,139 @@
++/*
++ * include/asm-x86_64/irqflags.h
++ *
++ * IRQ flags handling
++ *
++ * This file gets included from lowlevel asm headers too, to provide
++ * wrapped versions of the local_irq_*() APIs, based on the
++ * raw_local_irq_*() functions from the lowlevel headers.
++ */
++#ifndef _ASM_IRQFLAGS_H
++#define _ASM_IRQFLAGS_H
++
++#ifndef __ASSEMBLY__
++/*
++ * Interrupt control:
++ */
++
++/*
++ * The use of 'barrier' in the following reflects their use as local-lock
++ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
++ * critical operations are executed. All critical operations must complete
++ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
++ * includes these barriers, for example.
++ */
++
++#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask)
++
++#define raw_local_save_flags(flags) \
++		do { (flags) = __raw_local_save_flags(); } while (0)
++
++#define raw_local_irq_restore(x)					\
++do {									\
++	vcpu_info_t *_vcpu;						\
++	barrier();							\
++	_vcpu = current_vcpu_info();		\
++	if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {			\
++		barrier(); /* unmask then check (avoid races) */	\
++		if ( unlikely(_vcpu->evtchn_upcall_pending) )		\
++			force_evtchn_callback();			\
++	}								\
++} while (0)
++
++#ifdef CONFIG_X86_VSMP
++
++/*
++ * Interrupt control for the VSMP architecture:
++ */
++
++static inline void raw_local_irq_disable(void)
++{
++	unsigned long flags = __raw_local_save_flags();
++
++	raw_local_irq_restore((flags & ~(1 << 9)) | (1 << 18));
++}
++
++static inline void raw_local_irq_enable(void)
++{
++	unsigned long flags = __raw_local_save_flags();
++
++	raw_local_irq_restore((flags | (1 << 9)) & ~(1 << 18));
++}
++
++static inline int raw_irqs_disabled_flags(unsigned long flags)
++{
++	return !(flags & (1<<9)) || (flags & (1 << 18));
++}
++
++#else /* CONFIG_X86_VSMP */
++
++#define raw_local_irq_disable()						\
++do {									\
++	current_vcpu_info()->evtchn_upcall_mask = 1;					\
++	barrier();							\
++} while (0)
++
++#define raw_local_irq_enable()						\
++do {									\
++	vcpu_info_t *_vcpu;						\
++	barrier();							\
++	_vcpu = current_vcpu_info();		\
++	_vcpu->evtchn_upcall_mask = 0;					\
++	barrier(); /* unmask then check (avoid races) */		\
++	if ( unlikely(_vcpu->evtchn_upcall_pending) )			\
++		force_evtchn_callback();				\
++} while (0)
++
++static inline int raw_irqs_disabled_flags(unsigned long flags)
++{
++	return (flags != 0);
++}
++
++#endif
++
++/*
++ * For spinlocks, etc.:
++ */
++
++#define __raw_local_irq_save()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_local_irq_disable();					\
++									\
++	flags;								\
++})
++
++#define raw_local_irq_save(flags) \
++		do { (flags) = __raw_local_irq_save(); } while (0)
++
++#define raw_irqs_disabled()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_irqs_disabled_flags(flags);					\
++})
++
++/*
++ * Used in the idle loop; sti takes one instruction cycle
++ * to complete:
++ */
++void raw_safe_halt(void);
++
++/*
++ * Used when interrupts are already enabled or to
++ * shutdown the processor:
++ */
++void halt(void);
++
++#else /* __ASSEMBLY__: */
++# ifdef CONFIG_TRACE_IRQFLAGS
++#  define TRACE_IRQS_ON		call trace_hardirqs_on_thunk
++#  define TRACE_IRQS_OFF	call trace_hardirqs_off_thunk
++# else
++#  define TRACE_IRQS_ON
++#  define TRACE_IRQS_OFF
++# endif
++#endif
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,161 @@
++#ifndef _X86_64_MADDR_H
++#define _X86_64_MADDR_H
++
++#include <xen/features.h>
++#include <xen/interface/xen.h>
++
++/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
++#define INVALID_P2M_ENTRY	(~0UL)
++#define FOREIGN_FRAME_BIT	(1UL<<63)
++#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
++
++/* Definitions for machine and pseudophysical addresses. */
++typedef unsigned long paddr_t;
++typedef unsigned long maddr_t;
++
++#ifdef CONFIG_XEN
++
++extern unsigned long *phys_to_machine_mapping;
++
++#undef machine_to_phys_mapping
++extern unsigned long *machine_to_phys_mapping;
++extern unsigned int   machine_to_phys_order;
++
++static inline unsigned long pfn_to_mfn(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return pfn;
++	BUG_ON(end_pfn && pfn >= end_pfn);
++	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
++}
++
++static inline int phys_to_machine_mapping_valid(unsigned long pfn)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 1;
++	BUG_ON(end_pfn && pfn >= end_pfn);
++	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
++}
++
++static inline unsigned long mfn_to_pfn(unsigned long mfn)
++{
++	unsigned long pfn;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return mfn;
++
++	if (unlikely((mfn >> machine_to_phys_order) != 0))
++		return end_pfn;
++
++	/* The array access can fail (e.g., device space beyond end of RAM). */
++	asm (
++		"1:	movq %1,%0\n"
++		"2:\n"
++		".section .fixup,\"ax\"\n"
++		"3:	movq %2,%0\n"
++		"	jmp  2b\n"
++		".previous\n"
++		".section __ex_table,\"a\"\n"
++		"	.align 8\n"
++		"	.quad 1b,3b\n"
++		".previous"
++		: "=r" (pfn)
++		: "m" (machine_to_phys_mapping[mfn]), "m" (end_pfn) );
++
++	return pfn;
++}
++
++/*
++ * We detect special mappings in one of two ways:
++ *  1. If the MFN is an I/O page then Xen will set the m2p entry
++ *     to be outside our maximum possible pseudophys range.
++ *  2. If the MFN belongs to a different domain then we will certainly
++ *     not have MFN in our p2m table. Conversely, if the page is ours,
++ *     then we'll have p2m(m2p(MFN))==MFN.
++ * If we detect a special mapping then it doesn't have a 'struct page'.
++ * We force !pfn_valid() by returning an out-of-range pointer.
++ *
++ * NB. These checks require that, for any MFN that is not in our reservation,
++ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
++ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
++ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
++ *
++ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
++ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
++ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
++ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
++ */
++static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
++{
++	unsigned long pfn = mfn_to_pfn(mfn);
++	if ((pfn < end_pfn)
++	    && !xen_feature(XENFEAT_auto_translated_physmap)
++	    && (phys_to_machine_mapping[pfn] != mfn))
++		return end_pfn; /* force !pfn_valid() */
++	return pfn;
++}
++
++static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
++{
++	BUG_ON(end_pfn && pfn >= end_pfn);
++	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
++		return;
++	}
++	phys_to_machine_mapping[pfn] = mfn;
++}
++
++static inline maddr_t phys_to_machine(paddr_t phys)
++{
++	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
++	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
++	return machine;
++}
++
++static inline paddr_t machine_to_phys(maddr_t machine)
++{
++	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
++	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
++	return phys;
++}
++
++static inline paddr_t pte_phys_to_machine(paddr_t phys)
++{
++	maddr_t machine;
++	machine = pfn_to_mfn((phys & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT);
++	machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
++	return machine;
++}
++
++static inline paddr_t pte_machine_to_phys(maddr_t machine)
++{
++	paddr_t phys;
++	phys = mfn_to_pfn((machine & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT);
++	phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
++	return phys;
++}
++
++#define __pte_ma(x)     ((pte_t) { (x) } )
++#define pfn_pte_ma(pfn, prot)	__pte_ma((((pfn) << PAGE_SHIFT) | pgprot_val(prot)) & __supported_pte_mask)
++
++#else /* !CONFIG_XEN */
++
++#define pfn_to_mfn(pfn) (pfn)
++#define mfn_to_pfn(mfn) (mfn)
++#define mfn_to_local_pfn(mfn) (mfn)
++#define set_phys_to_machine(pfn, mfn) ((void)0)
++#define phys_to_machine_mapping_valid(pfn) (1)
++#define phys_to_machine(phys) ((maddr_t)(phys))
++#define machine_to_phys(mach) ((paddr_t)(mach))
++#define pfn_pte_ma(pfn, prot) pfn_pte(pfn, prot)
++#define __pte_ma(x) __pte(x)
++
++#endif /* !CONFIG_XEN */
++
++/* VIRT <-> MACHINE conversion */
++#define virt_to_machine(v)	(phys_to_machine(__pa(v)))
++#define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
++#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
++
++#endif /* _X86_64_MADDR_H */
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,136 @@
++#ifndef __X86_64_MMU_CONTEXT_H
++#define __X86_64_MMU_CONTEXT_H
++
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/pgalloc.h>
++#include <asm/page.h>
++#include <asm/pda.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++
++/*
++ * possibly do the LDT unload here?
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
++void destroy_context(struct mm_struct *mm);
++
++static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
++	if (read_pda(mmu_state) == TLBSTATE_OK) 
++		write_pda(mmu_state, TLBSTATE_LAZY);
++#endif
++}
++
++#define prepare_arch_switch(next)	__prepare_arch_switch()
++
++static inline void __prepare_arch_switch(void)
++{
++	/*
++	 * Save away %es, %ds, %fs and %gs. Must happen before reload
++	 * of cr3/ldt (i.e., not in __switch_to).
++	 */
++	__asm__ __volatile__ (
++		"mov %%es,%0 ; mov %%ds,%1 ; mov %%fs,%2 ; mov %%gs,%3"
++		: "=m" (current->thread.es),
++		  "=m" (current->thread.ds),
++		  "=m" (current->thread.fsindex),
++		  "=m" (current->thread.gsindex) );
++
++	if (current->thread.ds)
++		__asm__ __volatile__ ( "movl %0,%%ds" : : "r" (0) );
++
++	if (current->thread.es)
++		__asm__ __volatile__ ( "movl %0,%%es" : : "r" (0) );
++
++	if (current->thread.fsindex) {
++		__asm__ __volatile__ ( "movl %0,%%fs" : : "r" (0) );
++		current->thread.fs = 0;
++	}
++
++	if (current->thread.gsindex) {
++		load_gs_index(0);
++		current->thread.gs = 0;
++	}
++}
++
++extern void mm_pin(struct mm_struct *mm);
++extern void mm_unpin(struct mm_struct *mm);
++void mm_pin_all(void);
++
++static inline void load_cr3(pgd_t *pgd)
++{
++	asm volatile("movq %0,%%cr3" :: "r" (phys_to_machine(__pa(pgd))) :
++		     "memory");
++}
++
++static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
++			     struct task_struct *tsk)
++{
++	unsigned cpu = smp_processor_id();
++	struct mmuext_op _op[3], *op = _op;
++
++	if (likely(prev != next)) {
++		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
++		       !next->context.pinned);
++
++		/* stop flush ipis for the previous mm */
++		cpu_clear(cpu, prev->cpu_vm_mask);
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
++		write_pda(mmu_state, TLBSTATE_OK);
++		write_pda(active_mm, next);
++#endif
++		cpu_set(cpu, next->cpu_vm_mask);
++
++		/* load_cr3(next->pgd) */
++		op->cmd = MMUEXT_NEW_BASEPTR;
++		op->arg1.mfn = pfn_to_mfn(__pa(next->pgd) >> PAGE_SHIFT);
++		op++;
++
++		/* xen_new_user_pt(__pa(__user_pgd(next->pgd))) */
++		op->cmd = MMUEXT_NEW_USER_BASEPTR;
++		op->arg1.mfn = pfn_to_mfn(__pa(__user_pgd(next->pgd)) >> PAGE_SHIFT);
++		op++;
++		
++		if (unlikely(next->context.ldt != prev->context.ldt)) {
++			/* load_LDT_nolock(&next->context, cpu) */
++			op->cmd = MMUEXT_SET_LDT;
++			op->arg1.linear_addr = (unsigned long)next->context.ldt;
++			op->arg2.nr_ents     = next->context.size;
++			op++;
++		}
++
++		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
++	}
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
++	else {
++		write_pda(mmu_state, TLBSTATE_OK);
++		if (read_pda(active_mm) != next)
++			out_of_line_bug();
++		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
++			/* We were in lazy tlb mode and leave_mm disabled 
++			 * tlb flush IPI delivery. We must reload CR3
++			 * to make sure to use no freed page tables.
++			 */
++                        load_cr3(next->pgd);
++                        xen_new_user_pt(__pa(__user_pgd(next->pgd)));		
++			load_LDT_nolock(&next->context, cpu);
++		}
++	}
++#endif
++}
++
++#define deactivate_mm(tsk,mm)	do { \
++	load_gs_index(0); \
++	asm volatile("movl %0,%%fs"::"r"(0));  \
++} while(0)
++
++static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
++{
++	if (!next->context.pinned)
++		mm_pin(next);
++	switch_mm(prev, next, NULL);
++}
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_64.h	2007-06-18 08:38:13.000000000 +0200
+@@ -0,0 +1,204 @@
++#ifndef _X86_64_PGALLOC_H
++#define _X86_64_PGALLOC_H
++
++#include <asm/fixmap.h>
++#include <asm/pda.h>
++#include <linux/threads.h>
++#include <linux/mm.h>
++#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
++
++#include <xen/features.h>
++void make_page_readonly(void *va, unsigned int feature);
++void make_page_writable(void *va, unsigned int feature);
++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 __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
++
++static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
++{
++	set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)));
++}
++
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
++{
++	if (unlikely((mm)->context.pinned)) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)__va(page_to_pfn(pte) << PAGE_SHIFT),
++			       pfn_pte(page_to_pfn(pte), PAGE_KERNEL_RO), 0));
++		set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
++	} else {
++		*(pmd) = __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT));
++	}
++}
++
++static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
++{
++	if (unlikely((mm)->context.pinned)) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)pmd,
++			       pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, 
++				       PAGE_KERNEL_RO), 0));
++		set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)));
++	} else {
++		*(pud) =  __pud(_PAGE_TABLE | __pa(pmd));
++	}
++}
++
++/*
++ * We need to use the batch mode here, but pgd_pupulate() won't be
++ * be called frequently.
++ */
++static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
++{
++	if (unlikely((mm)->context.pinned)) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)pud,
++			       pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, 
++				       PAGE_KERNEL_RO), 0));
++		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
++		set_pgd(__user_pgd(pgd), __pgd(_PAGE_TABLE | __pa(pud)));
++	} else {
++		*(pgd) =  __pgd(_PAGE_TABLE | __pa(pud));
++		*(__user_pgd(pgd)) = *(pgd);
++	}
++}
++
++extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
++extern void pte_free(struct page *pte);
++
++static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	struct page *pg;
++
++	pg = pte_alloc_one(mm, addr);
++	return pg ? page_address(pg) : NULL;
++}
++
++static inline void pmd_free(pmd_t *pmd)
++{
++	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
++	pte_free(virt_to_page(pmd));
++}
++
++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++	struct page *pg;
++
++	pg = pte_alloc_one(mm, addr);
++	return pg ? page_address(pg) : NULL;
++}
++
++static inline void pud_free(pud_t *pud)
++{
++	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
++	pte_free(virt_to_page(pud));
++}
++
++static inline void pgd_list_add(pgd_t *pgd)
++{
++	struct page *page = virt_to_page(pgd);
++
++	spin_lock(&pgd_lock);
++	page->index = (pgoff_t)pgd_list;
++	if (pgd_list)
++		pgd_list->private = (unsigned long)&page->index;
++	pgd_list = page;
++	page->private = (unsigned long)&pgd_list;
++	spin_unlock(&pgd_lock);
++}
++
++static inline void pgd_list_del(pgd_t *pgd)
++{
++	struct page *next, **pprev, *page = virt_to_page(pgd);
++
++	spin_lock(&pgd_lock);
++	next = (struct page *)page->index;
++	pprev = (struct page **)page->private;
++	*pprev = next;
++	if (next)
++		next->private = (unsigned long)pprev;
++	spin_unlock(&pgd_lock);
++}
++
++static inline pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++	/*
++	 * We allocate two contiguous pages for kernel and user.
++	 */
++	unsigned boundary;
++	pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 1);
++	if (!pgd)
++		return NULL;
++	pgd_list_add(pgd);
++	/*
++	 * Copy kernel pointers in from init.
++	 * Could keep a freelist or slab cache of those because the kernel
++	 * part never changes.
++	 */
++	boundary = pgd_index(__PAGE_OFFSET);
++	memset(pgd, 0, boundary * sizeof(pgd_t));
++	memcpy(pgd + boundary,
++	       init_level4_pgt + boundary,
++	       (PTRS_PER_PGD - boundary) * sizeof(pgd_t));
++
++	memset(__user_pgd(pgd), 0, PAGE_SIZE); /* clean up user pgd */
++	/*
++	 * Set level3_user_pgt for vsyscall area
++	 */
++	__user_pgd(pgd)[pgd_index(VSYSCALL_START)] =
++		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
++	return pgd;
++}
++
++static inline void pgd_free(pgd_t *pgd)
++{
++	pte_t *ptep = virt_to_ptep(pgd);
++
++	if (!pte_write(*ptep)) {
++		xen_pgd_unpin(__pa(pgd));
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)pgd,
++			       pfn_pte(virt_to_phys(pgd)>>PAGE_SHIFT, PAGE_KERNEL),
++			       0));
++	}
++
++	ptep = virt_to_ptep(__user_pgd(pgd));
++
++	if (!pte_write(*ptep)) {
++		xen_pgd_unpin(__pa(__user_pgd(pgd)));
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)__user_pgd(pgd),
++			       pfn_pte(virt_to_phys(__user_pgd(pgd))>>PAGE_SHIFT, 
++				       PAGE_KERNEL),
++			       0));
++	}
++
++	pgd_list_del(pgd);
++	free_pages((unsigned long)pgd, 1);
++}
++
++static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
++{
++	pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
++	if (pte)
++		make_page_readonly(pte, XENFEAT_writable_page_tables);
++
++	return pte;
++}
++
++/* Should really implement gc for free page table pages. This could be
++   done with a reference count in struct page. */
++
++static inline void pte_free_kernel(pte_t *pte)
++{
++	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
++	make_page_writable(pte, XENFEAT_writable_page_tables);
++	free_page((unsigned long)pte); 
++}
++
++#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
++#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
++#define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
++
++#endif /* _X86_64_PGALLOC_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,585 @@
++#ifndef _X86_64_PGTABLE_H
++#define _X86_64_PGTABLE_H
++
++/*
++ * This file contains the functions and defines necessary to modify and use
++ * the x86-64 page table tree.
++ */
++#include <asm/processor.h>
++#include <asm/fixmap.h>
++#include <asm/bitops.h>
++#include <linux/threads.h>
++#include <linux/sched.h>
++#include <asm/pda.h>
++#ifdef CONFIG_XEN
++#include <asm/hypervisor.h>
++
++extern pud_t level3_user_pgt[512];
++
++extern void xen_init_pt(void);
++
++extern pte_t *lookup_address(unsigned long address);
++
++#define virt_to_ptep(va)						\
++({									\
++	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)))
++
++#define ptep_to_machine(ptep)	virt_to_machine(ptep)
++#endif
++
++extern pud_t level3_kernel_pgt[512];
++extern pud_t level3_physmem_pgt[512];
++extern pud_t level3_ident_pgt[512];
++extern pmd_t level2_kernel_pgt[512];
++extern pgd_t init_level4_pgt[];
++extern pgd_t boot_level4_pgt[];
++extern unsigned long __supported_pte_mask;
++
++#define swapper_pg_dir init_level4_pgt
++
++extern int nonx_setup(char *str);
++extern void paging_init(void);
++extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
++
++extern unsigned long pgkern_mask;
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
++
++/*
++ * PGDIR_SHIFT determines what a top-level page table entry can map
++ */
++#define PGDIR_SHIFT	39
++#define PTRS_PER_PGD	512
++
++/*
++ * 3rd level page
++ */
++#define PUD_SHIFT	30
++#define PTRS_PER_PUD	512
++
++/*
++ * PMD_SHIFT determines the size of the area a middle-level
++ * page table can map
++ */
++#define PMD_SHIFT	21
++#define PTRS_PER_PMD	512
++
++/*
++ * entries per page directory level
++ */
++#define PTRS_PER_PTE	512
++
++#define pte_ERROR(e) \
++	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
++	       &(e), __pte_val(e), pte_pfn(e))
++#define pmd_ERROR(e) \
++	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
++	       &(e), __pmd_val(e), pmd_pfn(e))
++#define pud_ERROR(e) \
++	printk("%s:%d: bad pud %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
++	       &(e), __pud_val(e), (pud_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++#define pgd_ERROR(e) \
++	printk("%s:%d: bad pgd %p(%016lx pfn %010lx).\n", __FILE__, __LINE__, \
++	       &(e), __pgd_val(e), (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++
++#define pgd_none(x)	(!__pgd_val(x))
++#define pud_none(x)	(!__pud_val(x))
++
++static inline void set_pte(pte_t *dst, pte_t val)
++{
++	*dst = val;
++}
++
++#define set_pmd(pmdptr, pmdval) xen_l2_entry_update(pmdptr, (pmdval))
++#define set_pud(pudptr, pudval) xen_l3_entry_update(pudptr, (pudval))
++#define set_pgd(pgdptr, pgdval) xen_l4_entry_update(pgdptr, (pgdval))
++
++static inline void pud_clear (pud_t * pud)
++{
++	set_pud(pud, __pud(0));
++}
++
++#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
++
++static inline void pgd_clear (pgd_t * pgd)
++{
++        set_pgd(pgd, __pgd(0));
++        set_pgd(__user_pgd(pgd), __pgd(0));
++}
++
++#define pud_page(pud) \
++    ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
++
++#define pte_same(a, b)		((a).pte == (b).pte)
++
++#define pte_pgprot(a)	(__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
++
++#define PMD_SIZE	(1UL << PMD_SHIFT)
++#define PMD_MASK	(~(PMD_SIZE-1))
++#define PUD_SIZE	(1UL << PUD_SHIFT)
++#define PUD_MASK	(~(PUD_SIZE-1))
++#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
++#define PGDIR_MASK	(~(PGDIR_SIZE-1))
++
++#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
++#define FIRST_USER_ADDRESS	0
++
++#ifndef __ASSEMBLY__
++#define MAXMEM		 0x6fffffffffUL
++#define VMALLOC_START    0xffffc20000000000UL
++#define VMALLOC_END      0xffffe1ffffffffffUL
++#define MODULES_VADDR    0xffffffff88000000UL
++#define MODULES_END      0xffffffffff000000UL
++#define MODULES_LEN   (MODULES_END - MODULES_VADDR)
++
++#define _PAGE_BIT_PRESENT	0
++#define _PAGE_BIT_RW		1
++#define _PAGE_BIT_USER		2
++#define _PAGE_BIT_PWT		3
++#define _PAGE_BIT_PCD		4
++#define _PAGE_BIT_ACCESSED	5
++#define _PAGE_BIT_DIRTY		6
++#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
++#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
++#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
++
++#define _PAGE_PRESENT	0x001
++#define _PAGE_RW	0x002
++#define _PAGE_USER	0x004
++#define _PAGE_PWT	0x008
++#define _PAGE_PCD	0x010
++#define _PAGE_ACCESSED	0x020
++#define _PAGE_DIRTY	0x040
++#define _PAGE_PSE	0x080	/* 2MB page */
++#define _PAGE_FILE	0x040	/* nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_GLOBAL	0x100	/* Global TLB entry */
++
++#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
++#define __kernel_page_user 0
++#endif
++
++#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 | _PAGE_IO)
++
++#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY PAGE_COPY_NOEXEC
++#define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define __PAGE_KERNEL \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
++#define __PAGE_KERNEL_EXEC \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
++#define __PAGE_KERNEL_NOCACHE \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
++#define __PAGE_KERNEL_RO \
++	(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
++#define __PAGE_KERNEL_VSYSCALL \
++	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define __PAGE_KERNEL_VSYSCALL_NOCACHE \
++	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_PCD)
++#define __PAGE_KERNEL_LARGE \
++	(__PAGE_KERNEL | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_EXEC \
++	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
++
++/*
++ * We don't support GLOBAL page in xenolinux64
++ */
++#define MAKE_GLOBAL(x) __pgprot((x))
++
++#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
++#define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
++#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
++#define PAGE_KERNEL_VSYSCALL32 __pgprot(__PAGE_KERNEL_VSYSCALL)
++#define PAGE_KERNEL_VSYSCALL MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL)
++#define PAGE_KERNEL_LARGE MAKE_GLOBAL(__PAGE_KERNEL_LARGE)
++#define PAGE_KERNEL_VSYSCALL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL_NOCACHE)
++
++/*         xwr */
++#define __P000	PAGE_NONE
++#define __P001	PAGE_READONLY
++#define __P010	PAGE_COPY
++#define __P011	PAGE_COPY
++#define __P100	PAGE_READONLY_EXEC
++#define __P101	PAGE_READONLY_EXEC
++#define __P110	PAGE_COPY_EXEC
++#define __P111	PAGE_COPY_EXEC
++
++#define __S000	PAGE_NONE
++#define __S001	PAGE_READONLY
++#define __S010	PAGE_SHARED
++#define __S011	PAGE_SHARED
++#define __S100	PAGE_READONLY_EXEC
++#define __S101	PAGE_READONLY_EXEC
++#define __S110	PAGE_SHARED_EXEC
++#define __S111	PAGE_SHARED_EXEC
++
++static inline unsigned long pgd_bad(pgd_t pgd)
++{
++       unsigned long val = __pgd_val(pgd);
++       val &= ~PTE_MASK;
++       val &= ~(_PAGE_USER | _PAGE_DIRTY);
++       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);
++}
++
++static inline unsigned long pud_bad(pud_t pud) 
++{ 
++       unsigned long val = __pud_val(pud);
++       val &= ~PTE_MASK; 
++       val &= ~(_PAGE_USER | _PAGE_DIRTY); 
++       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);      
++} 
++
++#define set_pte_at(_mm,addr,ptep,pteval) do {				\
++	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
++	    HYPERVISOR_update_va_mapping((addr), (pteval), 0))		\
++		set_pte((ptep), (pteval));				\
++} while (0)
++
++#define pte_none(x)	(!(x).pte)
++#define pte_present(x)	((x).pte & (_PAGE_PRESENT | _PAGE_PROTNONE))
++#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
++
++#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
++
++#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_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))
++
++static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
++{
++	unsigned long pte = page_nr << PAGE_SHIFT;
++	pte |= pgprot_val(pgprot);
++	pte &= __supported_pte_mask;
++	return __pte(pte);
++}
++
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (!pte_none(pte)) {
++		if ((mm != &init_mm) ||
++		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
++			pte = __pte_ma(xchg(&ptep->pte, 0));
++	}
++	return pte;
++}
++
++static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
++{
++	if (full) {
++		pte_t pte = *ptep;
++		if (mm->context.pinned)
++			xen_l1_entry_update(ptep, __pte(0));
++		else
++			*ptep = __pte(0);
++		return pte;
++	}
++	return ptep_get_and_clear(mm, addr, ptep);
++}
++
++#define ptep_clear_flush(vma, addr, ptep)			\
++({								\
++	pte_t *__ptep = (ptep);					\
++	pte_t __res = *__ptep;					\
++	if (!pte_none(__res) &&					\
++	    ((vma)->vm_mm != current->mm ||			\
++	     HYPERVISOR_update_va_mapping(addr,	__pte(0), 	\
++			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
++				UVMF_INVLPG|UVMF_MULTI))) {	\
++		__ptep->pte = 0;				\
++		flush_tlb_page(vma, addr);			\
++	}							\
++	__res;							\
++})
++
++/*
++ * The following only work if pte_present() is true.
++ * Undefined behaviour if not..
++ */
++#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
++static inline int pte_user(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
++static inline int pte_read(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
++static inline int pte_exec(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
++static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
++static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
++static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
++static inline int pte_file(pte_t pte)		{ return __pte_val(pte) & _PAGE_FILE; }
++static inline int pte_huge(pte_t pte)		{ return __pte_val(pte) & _PAGE_PSE; }
++
++static inline pte_t pte_rdprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_USER; return pte; }
++static inline pte_t pte_exprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_USER; return pte; }
++static inline pte_t pte_mkclean(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
++static inline pte_t pte_mkold(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
++static inline pte_t pte_wrprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_RW; return pte; }
++static inline pte_t pte_mkread(pte_t pte)	{ __pte_val(pte) |= _PAGE_USER; return pte; }
++static inline pte_t pte_mkexec(pte_t pte)	{ __pte_val(pte) |= _PAGE_USER; return pte; }
++static inline pte_t pte_mkdirty(pte_t pte)	{ __pte_val(pte) |= _PAGE_DIRTY; return pte; }
++static inline pte_t pte_mkyoung(pte_t pte)	{ __pte_val(pte) |= _PAGE_ACCESSED; return pte; }
++static inline pte_t pte_mkwrite(pte_t pte)	{ __pte_val(pte) |= _PAGE_RW; return pte; }
++static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
++
++#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __ret = pte_dirty(__pte);					\
++	if (__ret)							\
++		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkclean(__pte)); \
++	__ret;								\
++})
++
++#define ptep_test_and_clear_young(vma, addr, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __ret = pte_young(__pte);					\
++	if (__ret)							\
++		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkold(__pte)); \
++	__ret;								\
++})
++
++static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (pte_write(pte))
++		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
++}
++
++/*
++ * Macro to mark a page protection value as "uncacheable".
++ */
++#define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
++
++static inline int pmd_large(pmd_t pte) { 
++	return (__pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE;
++} 	
++
++
++/*
++ * Conversion functions: convert a page and protection to a page entry,
++ * and a page entry and page directory to the page they refer to.
++ */
++
++/*
++ * Level 4 access.
++ * Never use these in the common code.
++ */
++#define pgd_page(pgd) ((unsigned long) __va(pgd_val(pgd) & PTE_MASK))
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
++#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
++#define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
++#define pgd_present(pgd) (__pgd_val(pgd) & _PAGE_PRESENT)
++#define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
++
++/* PUD - Level3 access */
++/* to find an entry in a page-table-directory. */
++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
++#define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address))
++#define pud_present(pud) (__pud_val(pud) & _PAGE_PRESENT)
++
++/* PMD  - Level 2 access */
++#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
++#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
++
++#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
++#define pmd_offset(dir, address) ((pmd_t *) pud_page(*(dir)) + \
++                                  pmd_index(address))
++#define pmd_none(x)	(!__pmd_val(x))
++#if CONFIG_XEN_COMPAT <= 0x030002
++/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
++   can temporarily clear it. */
++#define pmd_present(x)	(__pmd_val(x))
++#else
++#define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
++#endif
++#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
++#define pmd_bad(x) ((__pmd_val(x) & ~(PTE_MASK | _PAGE_USER | _PAGE_PRESENT)) \
++		    != (_KERNPG_TABLE & ~(_PAGE_USER | _PAGE_PRESENT)))
++#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
++#define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
++
++#define pte_to_pgoff(pte) ((__pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
++#define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE })
++#define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
++
++/* PTE - Level 1 access. */
++
++/* page, protection -> pte */
++#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
++#define mk_pte_huge(entry) (__pte_val(entry) |= _PAGE_PRESENT | _PAGE_PSE)
++ 
++/* physical address -> PTE */
++static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
++{ 
++	unsigned long pteval;
++	pteval = physpage | pgprot_val(pgprot);
++	return __pte(pteval);
++}
++ 
++/* Change flags of a PTE */
++static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
++{ 
++	/*
++	 * Since this might change the present bit (which controls whether
++	 * a pte_t object has undergone p2m translation), we must use
++	 * pte_val() on the input pte and __pte() for the return value.
++	 */
++	unsigned long pteval = pte_val(pte);
++
++	pteval &= _PAGE_CHG_MASK;
++	pteval |= pgprot_val(newprot);
++	pteval &= __supported_pte_mask;
++	return __pte(pteval);
++}
++
++#define pte_index(address) \
++		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
++			pte_index(address))
++
++/* x86-64 always has all page tables mapped. */
++#define pte_offset_map(dir,address) pte_offset_kernel(dir,address)
++#define pte_offset_map_nested(dir,address) pte_offset_kernel(dir,address)
++#define pte_unmap(pte) /* NOP */
++#define pte_unmap_nested(pte) /* NOP */ 
++
++#define update_mmu_cache(vma,address,pte) do { } while (0)
++
++/*
++ * Rules for using ptep_establish: the pte MUST be a user pte, and
++ * must be a present->present transition.
++ */
++#define __HAVE_ARCH_PTEP_ESTABLISH
++#define ptep_establish(vma, address, ptep, pteval)			\
++	do {								\
++		if ( likely((vma)->vm_mm == current->mm) ) {		\
++			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
++				pteval,					\
++				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
++					UVMF_INVLPG|UVMF_MULTI));	\
++		} else {						\
++			xen_l1_entry_update(ptep, pteval);		\
++			flush_tlb_page(vma, address);			\
++		}							\
++	} while (0)
++
++/* We only update the dirty/accessed state if we set
++ * the dirty bit by hand in the kernel, since the hardware
++ * will do the accessed bit for us, and we don't want to
++ * race with other CPU's that might be updating the dirty
++ * bit at the same time. */
++#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
++	do {								\
++		if (dirty)						\
++			ptep_establish(vma, address, ptep, entry);	\
++	} while (0)
++
++/* Encode and de-code a swap entry */
++#define __swp_type(x)			(((x).val >> 1) & 0x3f)
++#define __swp_offset(x)			((x).val >> 8)
++#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
++#define __pte_to_swp_entry(pte)		((swp_entry_t) { __pte_val(pte) })
++#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
++
++extern spinlock_t pgd_lock;
++extern struct page *pgd_list;
++void vmalloc_sync_all(void);
++
++#endif /* !__ASSEMBLY__ */
++
++extern int kern_addr_valid(unsigned long addr); 
++
++#define DOMID_LOCAL (0xFFFFU)
++
++struct vm_area_struct;
++
++int direct_remap_pfn_range(struct vm_area_struct *vma,
++                            unsigned long address,
++                            unsigned long mfn,
++                            unsigned long size,
++                            pgprot_t prot,
++                            domid_t  domid);
++
++int direct_kernel_remap_pfn_range(unsigned long address, 
++				  unsigned long mfn,
++				  unsigned long size, 
++				  pgprot_t prot,
++				  domid_t  domid);
++
++int create_lookup_pte_addr(struct mm_struct *mm,
++                           unsigned long address,
++                           uint64_t *ptep);
++
++int touch_pte_range(struct mm_struct *mm,
++                    unsigned long address,
++                    unsigned long size);
++
++int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
++		unsigned long addr, unsigned long end, pgprot_t newprot);
++
++#define arch_change_pte_range(mm, pmd, addr, end, newprot)	\
++		xen_change_pte_range(mm, pmd, addr, end, newprot)
++
++#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
++		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
++
++#define MK_IOSPACE_PFN(space, pfn)	(pfn)
++#define GET_IOSPACE(pfn)		0
++#define GET_PFN(pfn)			(pfn)
++
++#define HAVE_ARCH_UNMAPPED_AREA
++
++#define pgtable_cache_init()   do { } while (0)
++#define check_pgt_cache()      do { } while (0)
++
++#define PAGE_AGP    PAGE_KERNEL_NOCACHE
++#define HAVE_PAGE_AGP 1
++
++/* fs/proc/kcore.c */
++#define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
++#define	kc_offset_to_vaddr(o) \
++   (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
++
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
++#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
++#define __HAVE_ARCH_PTEP_SET_WRPROTECT
++#define __HAVE_ARCH_PTE_SAME
++#include <asm-generic/pgtable.h>
++
++#endif /* _X86_64_PGTABLE_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2008-03-06 08:54:32.000000000 +0100
+@@ -0,0 +1,502 @@
++/*
++ * include/asm-x86_64/processor.h
++ *
++ * Copyright (C) 1994 Linus Torvalds
++ */
++
++#ifndef __ASM_X86_64_PROCESSOR_H
++#define __ASM_X86_64_PROCESSOR_H
++
++#include <asm/segment.h>
++#include <asm/page.h>
++#include <asm/types.h>
++#include <asm/sigcontext.h>
++#include <asm/cpufeature.h>
++#include <linux/threads.h>
++#include <asm/msr.h>
++#include <asm/current.h>
++#include <asm/system.h>
++#include <asm/mmsegment.h>
++#include <asm/percpu.h>
++#include <linux/personality.h>
++#include <linux/cpumask.h>
++
++#define TF_MASK		0x00000100
++#define IF_MASK		0x00000200
++#define IOPL_MASK	0x00003000
++#define NT_MASK		0x00004000
++#define VM_MASK		0x00020000
++#define AC_MASK		0x00040000
++#define VIF_MASK	0x00080000	/* virtual interrupt flag */
++#define VIP_MASK	0x00100000	/* virtual interrupt pending */
++#define ID_MASK		0x00200000
++
++#define desc_empty(desc) \
++               (!((desc)->a | (desc)->b))
++
++#define desc_equal(desc1, desc2) \
++               (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ void *pc; asm volatile("leaq 1f(%%rip),%0\n1:":"=r"(pc)); pc; })
++
++/*
++ *  CPU type and hardware bug flags. Kept separately for each CPU.
++ */
++
++struct cpuinfo_x86 {
++	__u8	x86;		/* CPU family */
++	__u8	x86_vendor;	/* CPU vendor */
++	__u8	x86_model;
++	__u8	x86_mask;
++	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
++	__u32	x86_capability[NCAPINTS];
++	char	x86_vendor_id[16];
++	char	x86_model_id[64];
++	int 	x86_cache_size;  /* in KB */
++	int	x86_clflush_size;
++	int	x86_cache_alignment;
++	int	x86_tlbsize;	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
++        __u8    x86_virt_bits, x86_phys_bits;
++	__u8	x86_max_cores;	/* cpuid returned max cores value */
++        __u32   x86_power; 	
++	__u32   extended_cpuid_level;	/* Max extended CPUID function supported */
++	unsigned long loops_per_jiffy;
++#ifdef CONFIG_SMP
++	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
++#endif
++	__u8	apicid;
++#ifdef CONFIG_SMP
++	__u8	booted_cores;	/* number of cores as seen by OS */
++	__u8	phys_proc_id;	/* Physical Processor id. */
++	__u8	cpu_core_id;	/* Core id. */
++#endif
++} ____cacheline_aligned;
++
++#define X86_VENDOR_INTEL 0
++#define X86_VENDOR_CYRIX 1
++#define X86_VENDOR_AMD 2
++#define X86_VENDOR_UMC 3
++#define X86_VENDOR_NEXGEN 4
++#define X86_VENDOR_CENTAUR 5
++#define X86_VENDOR_RISE 6
++#define X86_VENDOR_TRANSMETA 7
++#define X86_VENDOR_NUM 8
++#define X86_VENDOR_UNKNOWN 0xff
++
++#ifdef CONFIG_SMP
++extern struct cpuinfo_x86 cpu_data[];
++#define current_cpu_data cpu_data[smp_processor_id()]
++#else
++#define cpu_data (&boot_cpu_data)
++#define current_cpu_data boot_cpu_data
++#endif
++
++extern char ignore_irq13;
++
++extern void identify_cpu(struct cpuinfo_x86 *);
++extern void print_cpu_info(struct cpuinfo_x86 *);
++extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
++extern unsigned short num_cache_leaves;
++
++/*
++ * EFLAGS bits
++ */
++#define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
++#define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
++#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
++#define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
++#define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
++#define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
++#define X86_EFLAGS_IF	0x00000200 /* Interrupt Flag */
++#define X86_EFLAGS_DF	0x00000400 /* Direction Flag */
++#define X86_EFLAGS_OF	0x00000800 /* Overflow Flag */
++#define X86_EFLAGS_IOPL	0x00003000 /* IOPL mask */
++#define X86_EFLAGS_NT	0x00004000 /* Nested Task */
++#define X86_EFLAGS_RF	0x00010000 /* Resume Flag */
++#define X86_EFLAGS_VM	0x00020000 /* Virtual Mode */
++#define X86_EFLAGS_AC	0x00040000 /* Alignment Check */
++#define X86_EFLAGS_VIF	0x00080000 /* Virtual Interrupt Flag */
++#define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
++#define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
++
++/*
++ * Intel CPU features in CR4
++ */
++#define X86_CR4_VME		0x0001	/* enable vm86 extensions */
++#define X86_CR4_PVI		0x0002	/* virtual interrupts flag enable */
++#define X86_CR4_TSD		0x0004	/* disable time stamp at ipl 3 */
++#define X86_CR4_DE		0x0008	/* enable debugging extensions */
++#define X86_CR4_PSE		0x0010	/* enable page size extensions */
++#define X86_CR4_PAE		0x0020	/* enable physical address extensions */
++#define X86_CR4_MCE		0x0040	/* Machine check enable */
++#define X86_CR4_PGE		0x0080	/* enable global pages */
++#define X86_CR4_PCE		0x0100	/* enable performance counters at ipl 3 */
++#define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
++#define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
++
++/*
++ * Save the cr4 feature set we're using (ie
++ * Pentium 4MB enable and PPro Global page
++ * enable), so that any CPU's that boot up
++ * after us can get the correct flags.
++ */
++extern unsigned long mmu_cr4_features;
++
++static inline void set_in_cr4 (unsigned long mask)
++{
++	mmu_cr4_features |= mask;
++	__asm__("movq %%cr4,%%rax\n\t"
++		"orq %0,%%rax\n\t"
++		"movq %%rax,%%cr4\n"
++		: : "irg" (mask)
++		:"ax");
++}
++
++static inline void clear_in_cr4 (unsigned long mask)
++{
++	mmu_cr4_features &= ~mask;
++	__asm__("movq %%cr4,%%rax\n\t"
++		"andq %0,%%rax\n\t"
++		"movq %%rax,%%cr4\n"
++		: : "irg" (~mask)
++		:"ax");
++}
++
++
++/*
++ * User space process size. 47bits minus one guard page.
++ */
++#define TASK_SIZE64	(0x800000000000UL - 4096)
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
++
++#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)
++
++#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE/3)
++
++/*
++ * Size of io_bitmap.
++ */
++#define IO_BITMAP_BITS  65536
++#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
++#ifndef CONFIG_X86_NO_TSS
++#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
++#endif
++#define INVALID_IO_BITMAP_OFFSET 0x8000
++
++struct i387_fxsave_struct {
++	u16	cwd;
++	u16	swd;
++	u16	twd;
++	u16	fop;
++	u64	rip;
++	u64	rdp; 
++	u32	mxcsr;
++	u32	mxcsr_mask;
++	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
++	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 128 bytes */
++	u32	padding[24];
++} __attribute__ ((aligned (16)));
++
++union i387_union {
++	struct i387_fxsave_struct	fxsave;
++};
++
++#ifndef CONFIG_X86_NO_TSS
++struct tss_struct {
++	u32 reserved1;
++	u64 rsp0;	
++	u64 rsp1;
++	u64 rsp2;
++	u64 reserved2;
++	u64 ist[7];
++	u32 reserved3;
++	u32 reserved4;
++	u16 reserved5;
++	u16 io_bitmap_base;
++	/*
++	 * The extra 1 is there because the CPU will access an
++	 * additional byte beyond the end of the IO permission
++	 * bitmap. The extra byte must be all 1 bits, and must
++	 * be within the limit. Thus we have:
++	 *
++	 * 128 bytes, the bitmap itself, for ports 0..0x3ff
++	 * 8 bytes, for an extra "long" of ~0UL
++	 */
++	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
++} __attribute__((packed)) ____cacheline_aligned;
++
++DECLARE_PER_CPU(struct tss_struct,init_tss);
++#endif
++
++
++extern struct cpuinfo_x86 boot_cpu_data;
++#ifndef CONFIG_X86_NO_TSS
++/* Save the original ist values for checking stack pointers during debugging */
++struct orig_ist {
++	unsigned long ist[7];
++};
++DECLARE_PER_CPU(struct orig_ist, orig_ist);
++#endif
++
++#ifdef CONFIG_X86_VSMP
++#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
++#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
++#else
++#define ARCH_MIN_TASKALIGN	16
++#define ARCH_MIN_MMSTRUCT_ALIGN	0
++#endif
++
++struct thread_struct {
++	unsigned long	rsp0;
++	unsigned long	rsp;
++	unsigned long 	userrsp;	/* Copy from PDA */ 
++	unsigned long	fs;
++	unsigned long	gs;
++	unsigned short	es, ds, fsindex, gsindex;	
++/* Hardware debugging registers */
++	unsigned long	debugreg0;  
++	unsigned long	debugreg1;  
++	unsigned long	debugreg2;  
++	unsigned long	debugreg3;  
++	unsigned long	debugreg6;  
++	unsigned long	debugreg7;  
++/* fault info */
++	unsigned long	cr2, trap_no, error_code;
++/* floating point info */
++	union i387_union	i387  __attribute__((aligned(16)));
++/* IO permissions. the bitmap could be moved into the GDT, that would make
++   switch faster for a limited number of ioperm using tasks. -AK */
++	int		ioperm;
++	unsigned long	*io_bitmap_ptr;
++	unsigned io_bitmap_max;
++/* cached TLS descriptors. */
++	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
++	unsigned int	iopl;
++} __attribute__((aligned(16)));
++
++#define INIT_THREAD  { \
++	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++}
++
++#ifndef CONFIG_X86_NO_TSS
++#define INIT_TSS  { \
++	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++}
++#endif
++
++#define INIT_MMAP \
++{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
++
++#define start_thread(regs,new_rip,new_rsp) do { \
++	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));	 \
++	load_gs_index(0);							\
++	(regs)->rip = (new_rip);						 \
++	(regs)->rsp = (new_rsp);						 \
++	write_pda(oldrsp, (new_rsp));						 \
++	(regs)->cs = __USER_CS;							 \
++	(regs)->ss = __USER_DS;							 \
++	(regs)->eflags = 0x200;							 \
++	set_fs(USER_DS);							 \
++} while(0) 
++
++#define get_debugreg(var, register)				\
++	var = HYPERVISOR_get_debugreg(register)
++#define set_debugreg(value, register) do {			\
++	if (HYPERVISOR_set_debugreg(register, value))		\
++		BUG();						\
++} while (0)
++
++struct task_struct;
++struct mm_struct;
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++extern void prepare_to_copy(struct task_struct *tsk);
++
++/*
++ * create a kernel thread without removing it from tasklists
++ */
++extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
++
++/*
++ * Return saved PC of a blocked thread.
++ * What is this good for? it will be always the scheduler or ret_from_fork.
++ */
++#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8))
++
++extern unsigned long get_wchan(struct task_struct *p);
++#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1)
++#define KSTK_EIP(tsk) (task_pt_regs(tsk)->rip)
++#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
++
++
++struct microcode_header {
++	unsigned int hdrver;
++	unsigned int rev;
++	unsigned int date;
++	unsigned int sig;
++	unsigned int cksum;
++	unsigned int ldrver;
++	unsigned int pf;
++	unsigned int datasize;
++	unsigned int totalsize;
++	unsigned int reserved[3];
++};
++
++struct microcode {
++	struct microcode_header hdr;
++	unsigned int bits[0];
++};
++
++typedef struct microcode microcode_t;
++typedef struct microcode_header microcode_header_t;
++
++/* microcode format is extended from prescott processors */
++struct extended_signature {
++	unsigned int sig;
++	unsigned int pf;
++	unsigned int cksum;
++};
++
++struct extended_sigtable {
++	unsigned int count;
++	unsigned int cksum;
++	unsigned int reserved[3];
++	struct extended_signature sigs[0];
++};
++
++
++#define ASM_NOP1 K8_NOP1
++#define ASM_NOP2 K8_NOP2
++#define ASM_NOP3 K8_NOP3
++#define ASM_NOP4 K8_NOP4
++#define ASM_NOP5 K8_NOP5
++#define ASM_NOP6 K8_NOP6
++#define ASM_NOP7 K8_NOP7
++#define ASM_NOP8 K8_NOP8
++
++/* Opteron nops */
++#define K8_NOP1 ".byte 0x90\n"
++#define K8_NOP2	".byte 0x66,0x90\n" 
++#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
++#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
++#define K8_NOP5	K8_NOP3 K8_NOP2 
++#define K8_NOP6	K8_NOP3 K8_NOP3
++#define K8_NOP7	K8_NOP4 K8_NOP3
++#define K8_NOP8	K8_NOP4 K8_NOP4
++
++#define ASM_NOP_MAX 8
++
++/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
++static inline void rep_nop(void)
++{
++	__asm__ __volatile__("rep;nop": : :"memory");
++}
++
++/* Stop speculative execution */
++static inline void sync_core(void)
++{ 
++	int tmp;
++	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
++} 
++
++#define cpu_has_fpu 1
++
++#define ARCH_HAS_PREFETCH
++static inline void prefetch(void *x) 
++{ 
++	asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x));
++} 
++
++#define ARCH_HAS_PREFETCHW 1
++static inline void prefetchw(void *x) 
++{ 
++	alternative_input("prefetcht0 (%1)",
++			  "prefetchw (%1)",
++			  X86_FEATURE_3DNOW,
++			  "r" (x));
++} 
++
++#define ARCH_HAS_SPINLOCK_PREFETCH 1
++
++#define spin_lock_prefetch(x)  prefetchw(x)
++
++#define cpu_relax()   rep_nop()
++
++/*
++ *      NSC/Cyrix CPU configuration register indexes
++ */
++#define CX86_CCR0 0xc0
++#define CX86_CCR1 0xc1
++#define CX86_CCR2 0xc2
++#define CX86_CCR3 0xc3
++#define CX86_CCR4 0xe8
++#define CX86_CCR5 0xe9
++#define CX86_CCR6 0xea
++#define CX86_CCR7 0xeb
++#define CX86_DIR0 0xfe
++#define CX86_DIR1 0xff
++#define CX86_ARR_BASE 0xc4
++#define CX86_RCR_BASE 0xdc
++
++/*
++ *      NSC/Cyrix CPU indexed register access macros
++ */
++
++#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
++
++#define setCx86(reg, data) do { \
++	outb((reg), 0x22); \
++	outb((data), 0x23); \
++} while (0)
++
++static inline void serialize_cpu(void)
++{
++	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
++}
++
++static inline void __monitor(const void *eax, unsigned long ecx,
++		unsigned long edx)
++{
++	/* "monitor %eax,%ecx,%edx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc8;"
++		: :"a" (eax), "c" (ecx), "d"(edx));
++}
++
++static inline void __mwait(unsigned long eax, unsigned long ecx)
++{
++	/* "mwait %eax,%ecx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc9;"
++		: :"a" (eax), "c" (ecx));
++}
++
++#define stack_current() \
++({								\
++	struct thread_info *ti;					\
++	asm("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->task;					\
++})
++
++#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++
++extern unsigned long boot_option_idle_override;
++/* Boot loader type from the setup header */
++extern int bootloader_type;
++
++#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
++
++#endif /* __ASM_X86_64_PROCESSOR_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,150 @@
++#ifndef __ASM_SMP_H
++#define __ASM_SMP_H
++
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
++#ifndef __ASSEMBLY__
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/bitops.h>
++extern int disable_apic;
++#endif
++
++#ifdef CONFIG_X86_LOCAL_APIC
++#ifndef __ASSEMBLY__
++#include <asm/fixmap.h>
++#include <asm/mpspec.h>
++#ifdef CONFIG_X86_IO_APIC
++#include <asm/io_apic.h>
++#endif
++#include <asm/apic.h>
++#include <asm/thread_info.h>
++#endif
++#endif
++
++#ifdef CONFIG_SMP
++#ifndef ASSEMBLY
++
++#include <asm/pda.h>
++
++struct pt_regs;
++
++extern cpumask_t cpu_present_mask;
++extern cpumask_t cpu_possible_map;
++extern cpumask_t cpu_online_map;
++extern cpumask_t cpu_initialized;
++
++/*
++ * Private routines/data
++ */
++ 
++extern void smp_alloc_memory(void);
++extern volatile unsigned long smp_invalidate_needed;
++extern int pic_mode;
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
++extern int smp_num_siblings;
++extern void smp_send_reschedule(int cpu);
++void smp_stop_cpu(void);
++extern int smp_call_function_single(int cpuid, void (*func) (void *info),
++				void *info, int retry, int wait);
++
++extern cpumask_t cpu_sibling_map[NR_CPUS];
++extern cpumask_t cpu_core_map[NR_CPUS];
++extern u8 cpu_llc_id[NR_CPUS];
++
++#define SMP_TRAMPOLINE_BASE 0x6000
++
++/*
++ * On x86 all CPUs are mapped 1:1 to the APIC space.
++ * This simplifies scheduling and IPI sending and
++ * compresses data structures.
++ */
++
++static inline int num_booting_cpus(void)
++{
++	return cpus_weight(cpu_possible_map);
++}
++
++#define raw_smp_processor_id() read_pda(cpunumber)
++
++#ifdef CONFIG_X86_LOCAL_APIC
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
++}
++#endif
++
++extern int safe_smp_processor_id(void);
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
++extern void prefill_possible_map(void);
++extern unsigned num_processors;
++extern unsigned disabled_cpus;
++
++#endif /* !ASSEMBLY */
++
++#define NO_PROC_ID		0xFF		/* No processor magic marker */
++
++#endif
++
++#ifndef ASSEMBLY
++/*
++ * Some lowlevel functions might want to know about
++ * the real APIC ID <-> CPU # mapping.
++ */
++extern u8 x86_cpu_to_apicid[NR_CPUS];	/* physical ID */
++extern u8 x86_cpu_to_log_apicid[NR_CPUS];
++extern u8 bios_cpu_apicid[];
++
++#ifdef CONFIG_X86_LOCAL_APIC
++static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
++{
++	return cpus_addr(cpumask)[0];
++}
++
++static inline int cpu_present_to_apicid(int mps_cpu)
++{
++	if (mps_cpu < NR_CPUS)
++		return (int)bios_cpu_apicid[mps_cpu];
++	else
++		return BAD_APICID;
++}
++#endif
++
++#endif /* !ASSEMBLY */
++
++#ifndef CONFIG_SMP
++#define stack_smp_processor_id() 0
++#define safe_smp_processor_id() 0
++#define cpu_logical_map(x) (x)
++#else
++#include <asm/thread_info.h>
++#define stack_smp_processor_id() \
++({ 								\
++	struct thread_info *ti;					\
++	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->cpu;						\
++})
++#endif
++
++#ifndef __ASSEMBLY__
++#ifdef CONFIG_X86_LOCAL_APIC
++static __inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
++}
++#endif
++#endif
++
++#ifdef CONFIG_SMP
++#define cpu_physical_id(cpu)		x86_cpu_to_apicid[cpu]
++#else
++#define cpu_physical_id(cpu)		boot_cpu_id
++#endif
++
++#endif
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2007-11-26 16:59:25.000000000 +0100
+@@ -0,0 +1,256 @@
++#ifndef __ASM_SYSTEM_H
++#define __ASM_SYSTEM_H
++
++#include <linux/kernel.h>
++#include <asm/segment.h>
++#include <asm/alternative.h>
++
++#include <asm/synch_bitops.h>
++#include <asm/hypervisor.h>
++#include <xen/interface/arch-x86_64.h>
++
++#ifdef __KERNEL__
++
++#define __STR(x) #x
++#define STR(x) __STR(x)
++
++#define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
++#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
++
++/* frame pointer must be last for get_wchan */
++#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
++#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\n\t"
++
++#define __EXTRA_CLOBBER  \
++	,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
++
++#define switch_to(prev,next,last) \
++	asm volatile(SAVE_CONTEXT						    \
++		     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
++		     "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */	  \
++		     "call __switch_to\n\t"					  \
++		     ".globl thread_return\n"					\
++		     "thread_return:\n\t"					    \
++		     "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"			  \
++		     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
++		     LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"	  \
++		     "movq %%rax,%%rdi\n\t" 					  \
++		     "jc   ret_from_fork\n\t"					  \
++		     RESTORE_CONTEXT						    \
++		     : "=a" (last)					  	  \
++		     : [next] "S" (next), [prev] "D" (prev),			  \
++		       [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
++		       [ti_flags] "i" (offsetof(struct thread_info, flags)),\
++		       [tif_fork] "i" (TIF_FORK),			  \
++		       [thread_info] "i" (offsetof(struct task_struct, thread_info)), \
++		       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))   \
++		     : "memory", "cc" __EXTRA_CLOBBER)
++    
++extern void load_gs_index(unsigned); 
++
++/*
++ * Load a segment. Fall back on loading the zero
++ * segment if something goes wrong..
++ */
++#define loadsegment(seg,value)	\
++	asm volatile("\n"			\
++		"1:\t"				\
++		"movl %k0,%%" #seg "\n"		\
++		"2:\n"				\
++		".section .fixup,\"ax\"\n"	\
++		"3:\t"				\
++		"movl %1,%%" #seg "\n\t" 	\
++		"jmp 2b\n"			\
++		".previous\n"			\
++		".section __ex_table,\"a\"\n\t"	\
++		".align 8\n\t"			\
++		".quad 1b,3b\n"			\
++		".previous"			\
++		: :"r" (value), "r" (0))
++
++/*
++ * Clear and set 'TS' bit respectively
++ */
++#define clts() (HYPERVISOR_fpu_taskswitch(0))
++
++static inline unsigned long read_cr0(void)
++{ 
++	unsigned long cr0;
++	asm volatile("movq %%cr0,%0" : "=r" (cr0));
++	return cr0;
++} 
++
++static inline void write_cr0(unsigned long val) 
++{ 
++	asm volatile("movq %0,%%cr0" :: "r" (val));
++} 
++
++#define read_cr3() ({ \
++	unsigned long __dummy; \
++	asm("movq %%cr3,%0" : "=r" (__dummy)); \
++	machine_to_phys(__dummy); \
++})
++
++static inline unsigned long read_cr4(void)
++{ 
++	unsigned long cr4;
++	asm("movq %%cr4,%0" : "=r" (cr4));
++	return cr4;
++} 
++
++static inline void write_cr4(unsigned long val)
++{ 
++	asm volatile("movq %0,%%cr4" :: "r" (val));
++} 
++
++#define stts() (HYPERVISOR_fpu_taskswitch(1))
++
++#define wbinvd() \
++	__asm__ __volatile__ ("wbinvd": : :"memory");
++
++/*
++ * On SMP systems, when the scheduler does migration-cost autodetection,
++ * it needs a way to flush as much of the CPU's caches as possible.
++ */
++static inline void sched_cacheflush(void)
++{
++	wbinvd();
++}
++
++#endif	/* __KERNEL__ */
++
++#define nop() __asm__ __volatile__ ("nop")
++
++#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
++
++#define tas(ptr) (xchg((ptr),1))
++
++#define __xg(x) ((volatile long *)(x))
++
++static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
++{
++	*ptr = val;
++}
++
++#define _set_64bit set_64bit
++
++/*
++ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
++ * Note 2: xchg has side effect, so that attribute volatile is necessary,
++ *	  but generally the primitive is invalid, *ptr is output argument. --ANK
++ */
++static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
++{
++	switch (size) {
++		case 1:
++			__asm__ __volatile__("xchgb %b0,%1"
++				:"=q" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++		case 2:
++			__asm__ __volatile__("xchgw %w0,%1"
++				:"=r" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++		case 4:
++			__asm__ __volatile__("xchgl %k0,%1"
++				:"=r" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++		case 8:
++			__asm__ __volatile__("xchgq %0,%1"
++				:"=r" (x)
++				:"m" (*__xg(ptr)), "0" (x)
++				:"memory");
++			break;
++	}
++	return x;
++}
++
++/*
++ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
++ * store NEW in MEM.  Return the initial value in MEM.  Success is
++ * indicated by comparing RETURN with OLD.
++ */
++
++#define __HAVE_ARCH_CMPXCHG 1
++
++static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
++				      unsigned long new, int size)
++{
++	unsigned long prev;
++	switch (size) {
++	case 1:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
++				     : "=a"(prev)
++				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 2:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 4:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 8:
++		__asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	}
++	return old;
++}
++
++#define cmpxchg(ptr,o,n)\
++	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
++					(unsigned long)(n),sizeof(*(ptr))))
++
++#ifdef CONFIG_SMP
++#define smp_mb()	mb()
++#define smp_rmb()	rmb()
++#define smp_wmb()	wmb()
++#define smp_read_barrier_depends()	do {} while(0)
++#else
++#define smp_mb()	barrier()
++#define smp_rmb()	barrier()
++#define smp_wmb()	barrier()
++#define smp_read_barrier_depends()	do {} while(0)
++#endif
++
++    
++/*
++ * Force strict CPU ordering.
++ * And yes, this is required on UP too when we're talking
++ * to devices.
++ */
++#define mb() 	asm volatile("mfence":::"memory")
++#define rmb()	asm volatile("lfence":::"memory")
++
++#ifdef CONFIG_UNORDERED_IO
++#define wmb()	asm volatile("sfence" ::: "memory")
++#else
++#define wmb()	asm volatile("" ::: "memory")
++#endif
++#define read_barrier_depends()	do {} while(0)
++#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++
++#define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0)
++
++#include <linux/irqflags.h>
++
++void cpu_idle_wait(void);
++
++extern unsigned long arch_align_stack(unsigned long sp);
++extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_64.h	2007-11-26 16:59:25.000000000 +0100
+@@ -0,0 +1,103 @@
++#ifndef _X8664_TLBFLUSH_H
++#define _X8664_TLBFLUSH_H
++
++#include <linux/mm.h>
++#include <asm/processor.h>
++
++#define __flush_tlb()	xen_tlb_flush()
++
++/*
++ * Global pages have to be flushed a bit differently. Not a real
++ * performance problem because this does not happen often.
++ */
++#define __flush_tlb_global()	xen_tlb_flush()
++
++
++extern unsigned long pgkern_mask;
++
++#define __flush_tlb_all() __flush_tlb_global()
++
++#define __flush_tlb_one(addr)	xen_invlpg((unsigned long)addr)
++
++
++/*
++ * TLB flushing:
++ *
++ *  - flush_tlb() flushes the current mm struct TLBs
++ *  - flush_tlb_all() flushes all processes TLBs
++ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
++ *  - flush_tlb_page(vma, vmaddr) flushes one page
++ *  - flush_tlb_range(vma, start, end) flushes a range of pages
++ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
++ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
++ *
++ * x86-64 can only flush individual pages or full VMs. For a range flush
++ * we always do the full VM. Might be worth trying if for a small
++ * range a few INVLPGs in a row are a win.
++ */
++
++#ifndef CONFIG_SMP
++
++#define flush_tlb() __flush_tlb()
++#define flush_tlb_all() __flush_tlb_all()
++#define local_flush_tlb() __flush_tlb()
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++	if (mm == current->active_mm)
++		__flush_tlb();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma,
++	unsigned long addr)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb_one(addr);
++}
++
++static inline void flush_tlb_range(struct vm_area_struct *vma,
++	unsigned long start, unsigned long end)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb();
++}
++
++#else
++
++#include <asm/smp.h>
++
++#define local_flush_tlb() \
++	__flush_tlb()
++
++#define flush_tlb_all xen_tlb_flush_all
++#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
++#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
++#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
++
++#define flush_tlb()	flush_tlb_current_task()
++
++static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
++{
++	flush_tlb_mm(vma->vm_mm);
++}
++
++#define TLBSTATE_OK	1
++#define TLBSTATE_LAZY	2
++
++/* Roughly an IPI every 20MB with 4k pages for freeing page table
++   ranges. Cost is about 42k of memory for each CPU. */
++#define ARCH_FREE_PTE_NR 5350	
++
++#endif
++
++#define flush_tlb_kernel_range(start, end) flush_tlb_all()
++
++static inline void flush_tlb_pgtables(struct mm_struct *mm,
++				      unsigned long start, unsigned long end)
++{
++	/* x86_64 does not keep any page table caches in a software TLB.
++	   The CPUs do in their hardware TLBs, but they are handled
++	   by the normal TLB flushing algorithms. */
++}
++
++#endif /* _X8664_TLBFLUSH_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor_64.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,328 @@
++/*
++ * x86-64 changes / gcc fixes from Andi Kleen. 
++ * Copyright 2002 Andi Kleen, SuSE Labs.
++ *
++ * This hasn't been optimized for the hammer yet, but there are likely
++ * no advantages to be gotten from x86-64 here anyways.
++ */
++
++typedef struct { unsigned long a,b; } __attribute__((aligned(16))) xmm_store_t;
++
++/* Doesn't use gcc to save the XMM registers, because there is no easy way to 
++   tell it to do a clts before the register saving. */
++#define XMMS_SAVE do {				\
++	preempt_disable();			\
++	if (!(current_thread_info()->status & TS_USEDFPU))	\
++		clts();				\
++	__asm__ __volatile__ ( 			\
++		"movups %%xmm0,(%1)	;\n\t"	\
++		"movups %%xmm1,0x10(%1)	;\n\t"	\
++		"movups %%xmm2,0x20(%1)	;\n\t"	\
++		"movups %%xmm3,0x30(%1)	;\n\t"	\
++		: "=&r" (cr0)			\
++		: "r" (xmm_save) 		\
++		: "memory");			\
++} while(0)
++
++#define XMMS_RESTORE do {			\
++	asm volatile (				\
++		"sfence			;\n\t"	\
++		"movups (%1),%%xmm0	;\n\t"	\
++		"movups 0x10(%1),%%xmm1	;\n\t"	\
++		"movups 0x20(%1),%%xmm2	;\n\t"	\
++		"movups 0x30(%1),%%xmm3	;\n\t"	\
++		:				\
++		: "r" (cr0), "r" (xmm_save)	\
++		: "memory");			\
++	if (!(current_thread_info()->status & TS_USEDFPU))	\
++		stts();				\
++	preempt_enable();			\
++} while(0)
++
++#define OFFS(x)		"16*("#x")"
++#define PF_OFFS(x)	"256+16*("#x")"
++#define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%[p1])		;\n"
++#define LD(x,y)		"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
++#define ST(x,y)		"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
++#define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%[p2])		;\n"
++#define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%[p3])		;\n"
++#define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%[p4])		;\n"
++#define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%[p5])		;\n"
++#define PF5(x)		"	prefetchnta "PF_OFFS(x)"(%[p6])		;\n"
++#define XO1(x,y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
++#define XO2(x,y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
++#define XO3(x,y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
++#define XO4(x,y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
++#define XO5(x,y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
++
++
++static void
++xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++        unsigned int lines = bytes >> 8;
++	unsigned long cr0;
++	xmm_store_t xmm_save[4];
++
++	XMMS_SAVE;
++
++        asm volatile (
++#undef BLOCK
++#define BLOCK(i) \
++		LD(i,0)					\
++			LD(i+1,1)			\
++		PF1(i)					\
++				PF1(i+2)		\
++				LD(i+2,2)		\
++					LD(i+3,3)	\
++		PF0(i+4)				\
++				PF0(i+6)		\
++		XO1(i,0)				\
++			XO1(i+1,1)			\
++				XO1(i+2,2)		\
++					XO1(i+3,3)	\
++		ST(i,0)					\
++			ST(i+1,1)			\
++				ST(i+2,2)		\
++					ST(i+3,3)	\
++
++
++		PF0(0)
++				PF0(2)
++
++	" .align 32			;\n"
++        " 1:                            ;\n"
++
++		BLOCK(0)
++		BLOCK(4)
++		BLOCK(8)
++		BLOCK(12)
++
++        "       addq %[inc], %[p1]           ;\n"
++        "       addq %[inc], %[p2]           ;\n"
++		"		decl %[cnt] ; jnz 1b"
++	: [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
++	: [inc] "r" (256UL) 
++        : "memory");
++
++	XMMS_RESTORE;
++}
++
++static void
++xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++	  unsigned long *p3)
++{
++	unsigned int lines = bytes >> 8;
++	xmm_store_t xmm_save[4];
++	unsigned long cr0;
++
++	XMMS_SAVE;
++
++        __asm__ __volatile__ (
++#undef BLOCK
++#define BLOCK(i) \
++		PF1(i)					\
++				PF1(i+2)		\
++		LD(i,0)					\
++			LD(i+1,1)			\
++				LD(i+2,2)		\
++					LD(i+3,3)	\
++		PF2(i)					\
++				PF2(i+2)		\
++		PF0(i+4)				\
++				PF0(i+6)		\
++		XO1(i,0)				\
++			XO1(i+1,1)			\
++				XO1(i+2,2)		\
++					XO1(i+3,3)	\
++		XO2(i,0)				\
++			XO2(i+1,1)			\
++				XO2(i+2,2)		\
++					XO2(i+3,3)	\
++		ST(i,0)					\
++			ST(i+1,1)			\
++				ST(i+2,2)		\
++					ST(i+3,3)	\
++
++
++		PF0(0)
++				PF0(2)
++
++	" .align 32			;\n"
++        " 1:                            ;\n"
++
++		BLOCK(0)
++		BLOCK(4)
++		BLOCK(8)
++		BLOCK(12)
++
++        "       addq %[inc], %[p1]           ;\n"
++        "       addq %[inc], %[p2]          ;\n"
++        "       addq %[inc], %[p3]           ;\n"
++		"		decl %[cnt] ; jnz 1b"
++	: [cnt] "+r" (lines),
++	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
++	: [inc] "r" (256UL)
++	: "memory"); 
++	XMMS_RESTORE;
++}
++
++static void
++xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++	  unsigned long *p3, unsigned long *p4)
++{
++	unsigned int lines = bytes >> 8;
++	xmm_store_t xmm_save[4]; 
++	unsigned long cr0;
++
++	XMMS_SAVE;
++
++        __asm__ __volatile__ (
++#undef BLOCK
++#define BLOCK(i) \
++		PF1(i)					\
++				PF1(i+2)		\
++		LD(i,0)					\
++			LD(i+1,1)			\
++				LD(i+2,2)		\
++					LD(i+3,3)	\
++		PF2(i)					\
++				PF2(i+2)		\
++		XO1(i,0)				\
++			XO1(i+1,1)			\
++				XO1(i+2,2)		\
++					XO1(i+3,3)	\
++		PF3(i)					\
++				PF3(i+2)		\
++		PF0(i+4)				\
++				PF0(i+6)		\
++		XO2(i,0)				\
++			XO2(i+1,1)			\
++				XO2(i+2,2)		\
++					XO2(i+3,3)	\
++		XO3(i,0)				\
++			XO3(i+1,1)			\
++				XO3(i+2,2)		\
++					XO3(i+3,3)	\
++		ST(i,0)					\
++			ST(i+1,1)			\
++				ST(i+2,2)		\
++					ST(i+3,3)	\
++
++
++		PF0(0)
++				PF0(2)
++
++	" .align 32			;\n"
++        " 1:                            ;\n"
++
++		BLOCK(0)
++		BLOCK(4)
++		BLOCK(8)
++		BLOCK(12)
++
++        "       addq %[inc], %[p1]           ;\n"
++        "       addq %[inc], %[p2]           ;\n"
++        "       addq %[inc], %[p3]           ;\n"
++        "       addq %[inc], %[p4]           ;\n"
++	"	decl %[cnt] ; jnz 1b"
++	: [cnt] "+c" (lines),
++	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
++	: [inc] "r" (256UL)
++        : "memory" );
++
++	XMMS_RESTORE;
++}
++
++static void
++xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++        unsigned int lines = bytes >> 8;
++	xmm_store_t xmm_save[4];
++	unsigned long cr0;
++
++	XMMS_SAVE;
++
++        __asm__ __volatile__ (
++#undef BLOCK
++#define BLOCK(i) \
++		PF1(i)					\
++				PF1(i+2)		\
++		LD(i,0)					\
++			LD(i+1,1)			\
++				LD(i+2,2)		\
++					LD(i+3,3)	\
++		PF2(i)					\
++				PF2(i+2)		\
++		XO1(i,0)				\
++			XO1(i+1,1)			\
++				XO1(i+2,2)		\
++					XO1(i+3,3)	\
++		PF3(i)					\
++				PF3(i+2)		\
++		XO2(i,0)				\
++			XO2(i+1,1)			\
++				XO2(i+2,2)		\
++					XO2(i+3,3)	\
++		PF4(i)					\
++				PF4(i+2)		\
++		PF0(i+4)				\
++				PF0(i+6)		\
++		XO3(i,0)				\
++			XO3(i+1,1)			\
++				XO3(i+2,2)		\
++					XO3(i+3,3)	\
++		XO4(i,0)				\
++			XO4(i+1,1)			\
++				XO4(i+2,2)		\
++					XO4(i+3,3)	\
++		ST(i,0)					\
++			ST(i+1,1)			\
++				ST(i+2,2)		\
++					ST(i+3,3)	\
++
++
++		PF0(0)
++				PF0(2)
++
++	" .align 32			;\n"
++        " 1:                            ;\n"
++
++		BLOCK(0)
++		BLOCK(4)
++		BLOCK(8)
++		BLOCK(12)
++
++        "       addq %[inc], %[p1]           ;\n"
++        "       addq %[inc], %[p2]           ;\n"
++        "       addq %[inc], %[p3]           ;\n"
++        "       addq %[inc], %[p4]           ;\n"
++        "       addq %[inc], %[p5]           ;\n"
++	"	decl %[cnt] ; jnz 1b"
++	: [cnt] "+c" (lines),
++  	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4), 
++	  [p5] "+r" (p5)
++	: [inc] "r" (256UL)
++	: "memory");
++
++	XMMS_RESTORE;
++}
++
++static struct xor_block_template xor_block_sse = {
++        .name = "generic_sse",
++        .do_2 = xor_sse_2,
++        .do_3 = xor_sse_3,
++        .do_4 = xor_sse_4,
++        .do_5 = xor_sse_5,
++};
++
++#undef XOR_TRY_TEMPLATES
++#define XOR_TRY_TEMPLATES				\
++	do {						\
++		xor_speed(&xor_block_sse);	\
++	} while (0)
++
++/* We force the use of the SSE xor block because it can write around L2.
++   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)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/setup_arch_post.h	2007-06-12 13:14:13.000000000 +0200
+@@ -0,0 +1,63 @@
++/**
++ * machine_specific_* - Hooks for machine specific setup.
++ *
++ * Description:
++ *	This is included late in kernel/setup.c so that it can make
++ *	use of all of the static functions.
++ **/
++
++#include <xen/interface/callback.h>
++
++extern void hypervisor_callback(void);
++extern void failsafe_callback(void);
++extern void nmi(void);
++
++static void __init machine_specific_arch_setup(void)
++{
++	int ret;
++	static struct callback_register __initdata event = {
++		.type = CALLBACKTYPE_event,
++		.address = (unsigned long) hypervisor_callback,
++	};
++	static struct callback_register __initdata failsafe = {
++		.type = CALLBACKTYPE_failsafe,
++		.address = (unsigned long)failsafe_callback,
++	};
++	static struct callback_register __initdata syscall = {
++		.type = CALLBACKTYPE_syscall,
++		.address = (unsigned long)system_call,
++	};
++#ifdef CONFIG_X86_LOCAL_APIC
++	static struct callback_register __initdata nmi_cb = {
++		.type = CALLBACKTYPE_nmi,
++		.address = (unsigned long)nmi,
++	};
++#endif
++
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
++	if (ret == 0)
++		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret == -ENOSYS)
++		ret = HYPERVISOR_set_callbacks(
++			event.address,
++			failsafe.address,
++			syscall.address);
++#endif
++	BUG_ON(ret);
++
++#ifdef CONFIG_X86_LOCAL_APIC
++	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (ret == -ENOSYS) {
++		static struct xennmi_callback __initdata cb = {
++			.handler_address = (unsigned long)nmi
++		};
++
++		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
++	}
++#endif
++#endif
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/setup_arch_pre.h	2007-06-12 13:14:13.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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/balloon.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,57 @@
++/******************************************************************************
++ * balloon.h
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ * 
++ * 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 __ASM_BALLOON_H__
++#define __ASM_BALLOON_H__
++
++/*
++ * Inform the balloon driver that it should allow some slop for device-driver
++ * memory activities.
++ */
++void balloon_update_driver_allowance(long delta);
++
++/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
++struct page **alloc_empty_pages_and_pagevec(int nr_pages);
++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
++
++void balloon_release_driver_page(struct page *page);
++
++/*
++ * Prevent the balloon driver from changing the memory reservation during
++ * a driver critical region.
++ */
++extern spinlock_t balloon_lock;
++#define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
++#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
++
++#endif /* __ASM_BALLOON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/blkif.h	2008-07-21 11:00:33.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__
++
++#include <xen/interface/io/ring.h>
++#include <xen/interface/io/blkif.h>
++#include <xen/interface/io/protocols.h>
++
++/* Not a real protocol.  Used to generate ring structs which contain
++ * the elements common to all protocols only.  This way we get a
++ * compiler-checkable way to use common struct elements, so we can
++ * avoid using switch(protocol) in a number of places.  */
++struct blkif_common_request {
++	char dummy;
++};
++struct blkif_common_response {
++	char dummy;
++};
++
++/* i386 protocol version */
++#pragma pack(push, 4)
++struct blkif_x86_32_request {
++	uint8_t        operation;    /* BLKIF_OP_???                         */
++	uint8_t        nr_segments;  /* number of segments                   */
++	blkif_vdev_t   handle;       /* only for read/write requests         */
++	uint64_t       id;           /* private guest value, echoed in resp  */
++	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
++	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++};
++struct blkif_x86_32_response {
++	uint64_t        id;              /* copied from request */
++	uint8_t         operation;       /* copied from request */
++	int16_t         status;          /* BLKIF_RSP_???       */
++};
++typedef struct blkif_x86_32_request blkif_x86_32_request_t;
++typedef struct blkif_x86_32_response blkif_x86_32_response_t;
++#pragma pack(pop)
++
++/* x86_64 protocol version */
++struct blkif_x86_64_request {
++	uint8_t        operation;    /* BLKIF_OP_???                         */
++	uint8_t        nr_segments;  /* number of segments                   */
++	blkif_vdev_t   handle;       /* only for read/write requests         */
++	uint64_t       __attribute__((__aligned__(8))) id;
++	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
++	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++};
++struct blkif_x86_64_response {
++	uint64_t       __attribute__((__aligned__(8))) id;
++	uint8_t         operation;       /* copied from request */
++	int16_t         status;          /* BLKIF_RSP_???       */
++};
++typedef struct blkif_x86_64_request blkif_x86_64_request_t;
++typedef struct blkif_x86_64_response blkif_x86_64_response_t;
++
++DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
++DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
++DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
++
++union blkif_back_rings {
++	blkif_back_ring_t        native;
++	blkif_common_back_ring_t common;
++	blkif_x86_32_back_ring_t x86_32;
++	blkif_x86_64_back_ring_t x86_64;
++};
++typedef union blkif_back_rings blkif_back_rings_t;
++
++enum blkif_protocol {
++	BLKIF_PROTOCOL_NATIVE = 1,
++	BLKIF_PROTOCOL_X86_32 = 2,
++	BLKIF_PROTOCOL_X86_64 = 3,
++};
++
++static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
++{
++	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
++	dst->operation = src->operation;
++	dst->nr_segments = src->nr_segments;
++	dst->handle = src->handle;
++	dst->id = src->id;
++	dst->sector_number = src->sector_number;
++	barrier();
++	if (n > dst->nr_segments)
++		n = dst->nr_segments;
++	for (i = 0; i < n; i++)
++		dst->seg[i] = src->seg[i];
++}
++
++static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
++{
++	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
++	dst->operation = src->operation;
++	dst->nr_segments = src->nr_segments;
++	dst->handle = src->handle;
++	dst->id = src->id;
++	dst->sector_number = src->sector_number;
++	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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/compat_ioctl.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,75 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors: Jimi Xenidis <jimix@watson.ibm.com>
++ *          Hollis Blanchard <hollisb@us.ibm.com>
++ */
++
++#ifndef __LINUX_XEN_COMPAT_H__ 
++#define __LINUX_XEN_COMPAT_H__ 
++
++#include <linux/compat.h>
++#include <linux/compiler.h>
++
++#if defined(CONFIG_X86) || defined(CONFIG_IA64)
++#define xen_pfn32_t __u32
++#endif
++
++extern int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg);
++struct privcmd_mmap_32 {
++	int num;
++	domid_t dom;
++	compat_uptr_t entry;
++};
++
++struct privcmd_mmapbatch_32 {
++	int num;     /* number of pages to populate */
++	domid_t dom; /* target domain */
++#if defined(CONFIG_X86) || defined(CONFIG_IA64)
++	union {      /* virtual address */
++		__u64 addr __attribute__((packed));
++		__u32 va; /* ensures union is 4-byte aligned */
++	};
++#else
++	__u64 addr;  /* virtual address */
++#endif
++	compat_uptr_t arr; /* array of mfns - top nibble set on err */
++};
++
++struct privcmd_mmapbatch_v2_32 {
++	unsigned int num; /* number of pages to populate */
++	domid_t dom;      /* target domain */
++#if defined(CONFIG_X86) || defined(CONFIG_IA64)
++	union {      /* virtual address */
++		__u64 addr __attribute__((packed));
++		__u32 va; /* ensures union is 4-byte aligned */
++	};
++#else
++	__u64 addr;  /* virtual address */
++#endif
++	compat_uptr_t arr; /* array of mfns */
++	compat_uptr_t err; /* array of error codes */
++};
++
++#define IOCTL_PRIVCMD_MMAP_32                   \
++	_IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap_32))
++#define IOCTL_PRIVCMD_MMAPBATCH_32              \
++	_IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch_32))
++#define IOCTL_PRIVCMD_MMAPBATCH_V2_32           \
++	_IOC(_IOC_NONE, 'P', 4, sizeof(struct privcmd_mmapbatch_v2_32))
++
++#endif /* __LINUX_XEN_COMPAT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/cpu_hotplug.h	2007-08-16 18:07:01.000000000 +0200
+@@ -0,0 +1,41 @@
++#ifndef __XEN_CPU_HOTPLUG_H__
++#define __XEN_CPU_HOTPLUG_H__
++
++#include <linux/kernel.h>
++#include <linux/cpumask.h>
++
++#if defined(CONFIG_X86) && defined(CONFIG_SMP)
++extern cpumask_t cpu_initialized_map;
++#endif
++
++#if defined(CONFIG_HOTPLUG_CPU)
++
++int cpu_up_check(unsigned int cpu);
++void init_xenbus_allowed_cpumask(void);
++int smp_suspend(void);
++void smp_resume(void);
++
++void cpu_bringup(void);
++
++#else /* !defined(CONFIG_HOTPLUG_CPU) */
++
++#define cpu_up_check(cpu)		(0)
++#define init_xenbus_allowed_cpumask()	((void)0)
++
++static inline int smp_suspend(void)
++{
++	if (num_online_cpus() > 1) {
++		printk(KERN_WARNING "Can't suspend SMP guests "
++		       "without CONFIG_HOTPLUG_CPU\n");
++		return -EOPNOTSUPP;
++	}
++	return 0;
++}
++
++static inline void smp_resume(void)
++{
++}
++
++#endif /* !defined(CONFIG_HOTPLUG_CPU) */
++
++#endif /* __XEN_CPU_HOTPLUG_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/driver_util.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,14 @@
++
++#ifndef __ASM_XEN_DRIVER_UTIL_H__
++#define __ASM_XEN_DRIVER_UTIL_H__
++
++#include <linux/vmalloc.h>
++#include <linux/device.h>
++
++/* Allocate/destroy a 'vmalloc' VM area. */
++extern struct vm_struct *alloc_vm_area(unsigned long size);
++extern void free_vm_area(struct vm_struct *area);
++
++extern struct class *get_xen_class(void);
++
++#endif /* __ASM_XEN_DRIVER_UTIL_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/firmware.h	2007-07-02 08:16:19.000000000 +0200
+@@ -0,0 +1,10 @@
++#ifndef __XEN_FIRMWARE_H__
++#define __XEN_FIRMWARE_H__
++
++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
++void copy_edd(void);
++#endif
++
++void copy_edid(void);
++
++#endif /* __XEN_FIRMWARE_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/gnttab.h	2008-11-04 11:13:10.000000000 +0100
+@@ -0,0 +1,164 @@
++/******************************************************************************
++ * gnttab.h
++ * 
++ * Two sets of functionality:
++ * 1. Granting foreign access to our memory reservation.
++ * 2. Accessing others' memory reservations via grant references.
++ * (i.e., mechanisms for both sender and recipient of grant references)
++ * 
++ * Copyright (c) 2004-2005, K A Fraser
++ * Copyright (c) 2005, Christopher Clark
++ * 
++ * 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 __ASM_GNTTAB_H__
++#define __ASM_GNTTAB_H__
++
++#include <asm/hypervisor.h>
++#include <asm/maddr.h> /* maddr_t */
++#include <linux/mm.h>
++#include <xen/interface/grant_table.h>
++#include <xen/features.h>
++
++struct gnttab_free_callback {
++	struct gnttab_free_callback *next;
++	void (*fn)(void *);
++	void *arg;
++	u16 count;
++	u8 queued;
++};
++
++int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
++				int flags);
++
++/*
++ * End access through the given grant reference, iff the grant entry is no
++ * longer in use.  Return 1 if the grant entry was freed, 0 if it is still in
++ * use.
++ */
++int gnttab_end_foreign_access_ref(grant_ref_t ref);
++
++/*
++ * Eventually end access through the given grant reference, and once that
++ * access has been ended, free the given page too.  Access will be ended
++ * immediately iff the grant entry is not in use, otherwise it will happen
++ * some time later.  page may be 0, in which case no freeing will occur.
++ */
++void gnttab_end_foreign_access(grant_ref_t ref, unsigned long page);
++
++int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
++
++unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
++unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
++
++int gnttab_query_foreign_access(grant_ref_t ref);
++
++/*
++ * operations on reserved batches of grant references
++ */
++int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head);
++
++void gnttab_free_grant_reference(grant_ref_t ref);
++
++void gnttab_free_grant_references(grant_ref_t head);
++
++int gnttab_empty_grant_references(const grant_ref_t *pprivate_head);
++
++int gnttab_claim_grant_reference(grant_ref_t *pprivate_head);
++
++void gnttab_release_grant_reference(grant_ref_t *private_head,
++				    grant_ref_t release);
++
++void gnttab_request_free_callback(struct gnttab_free_callback *callback,
++				  void (*fn)(void *), void *arg, u16 count);
++void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
++
++void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
++				     unsigned long frame, int flags);
++
++void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
++				       unsigned long pfn);
++
++int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep);
++void __gnttab_dma_map_page(struct page *page);
++static inline void __gnttab_dma_unmap_page(struct page *page)
++{
++}
++
++void gnttab_reset_grant_page(struct page *page);
++
++int gnttab_suspend(void);
++int gnttab_resume(void);
++
++void *arch_gnttab_alloc_shared(unsigned long *frames);
++
++static inline void
++gnttab_set_map_op(struct gnttab_map_grant_ref *map, maddr_t addr,
++		  uint32_t flags, grant_ref_t ref, domid_t domid)
++{
++	if (flags & GNTMAP_contains_pte)
++		map->host_addr = addr;
++	else if (xen_feature(XENFEAT_auto_translated_physmap))
++		map->host_addr = __pa(addr);
++	else
++		map->host_addr = addr;
++
++	map->flags = flags;
++	map->ref = ref;
++	map->dom = domid;
++}
++
++static inline void
++gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, maddr_t addr,
++		    uint32_t flags, grant_handle_t handle)
++{
++	if (flags & GNTMAP_contains_pte)
++		unmap->host_addr = addr;
++	else if (xen_feature(XENFEAT_auto_translated_physmap))
++		unmap->host_addr = __pa(addr);
++	else
++		unmap->host_addr = addr;
++
++	unmap->handle = handle;
++	unmap->dev_bus_addr = 0;
++}
++
++static inline void
++gnttab_set_replace_op(struct gnttab_unmap_and_replace *unmap, maddr_t addr,
++		      maddr_t new_addr, grant_handle_t handle)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++		unmap->host_addr = __pa(addr);
++		unmap->new_addr = __pa(new_addr);
++	} else {
++		unmap->host_addr = addr;
++		unmap->new_addr = new_addr;
++	}
++
++	unmap->handle = handle;
++}
++
++#endif /* __ASM_GNTTAB_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/hvm.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,23 @@
++/* Simple wrappers around HVM functions */
++#ifndef XEN_HVM_H__
++#define XEN_HVM_H__
++
++#include <xen/interface/hvm/params.h>
++
++static inline unsigned long hvm_get_parameter(int idx)
++{
++	struct xen_hvm_param xhv;
++	int r;
++
++	xhv.domid = DOMID_SELF;
++	xhv.index = idx;
++	r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
++	if (r < 0) {
++		printk(KERN_ERR "cannot get hvm parameter %d: %d.\n",
++		       idx, r);
++		return 0;
++	}
++	return xhv.value;
++}
++
++#endif /* XEN_HVM_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/hypercall.h	2008-01-28 12:24:19.000000000 +0100
+@@ -0,0 +1,30 @@
++#ifndef __XEN_HYPERCALL_H__
++#define __XEN_HYPERCALL_H__
++
++#include <asm/hypercall.h>
++
++static inline int __must_check
++HYPERVISOR_multicall_check(
++	multicall_entry_t *call_list, unsigned int nr_calls,
++	const unsigned long *rc_list)
++{
++	int rc = HYPERVISOR_multicall(call_list, nr_calls);
++
++	if (unlikely(rc < 0))
++		return rc;
++	BUG_ON(rc);
++	BUG_ON((int)nr_calls < 0);
++
++	for ( ; nr_calls > 0; --nr_calls, ++call_list)
++		if (unlikely(call_list->result != (rc_list ? *rc_list++ : 0)))
++			return nr_calls;
++
++	return 0;
++}
++
++/* A construct to ignore the return value of hypercall wrappers in a few
++ * exceptional cases (simply casting the function result to void doesn't
++ * avoid the compiler warning): */
++#define VOID(expr) ((void)((expr)?:0))
++
++#endif /* __XEN_HYPERCALL_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/hypervisor_sysfs.h	2007-06-22 09:08:06.000000000 +0200
+@@ -0,0 +1,30 @@
++/*
++ *  copyright (c) 2006 IBM Corporation
++ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
++ */
++
++#ifndef _HYP_SYSFS_H_
++#define _HYP_SYSFS_H_
++
++#include <linux/kobject.h>
++#include <linux/sysfs.h>
++
++#define HYPERVISOR_ATTR_RO(_name) \
++static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
++
++#define HYPERVISOR_ATTR_RW(_name) \
++static struct hyp_sysfs_attr _name##_attr = \
++	__ATTR(_name, 0644, _name##_show, _name##_store)
++
++struct hyp_sysfs_attr {
++	struct attribute attr;
++	ssize_t (*show)(struct hyp_sysfs_attr *, char *);
++	ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
++	void *hyp_attr_data;
++};
++
++#endif /* _HYP_SYSFS_H_ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/pcifront.h	2007-06-18 08:38:13.000000000 +0200
+@@ -0,0 +1,83 @@
++/*
++ * PCI Frontend - arch-dependendent declarations
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#ifndef __XEN_ASM_PCIFRONT_H__
++#define __XEN_ASM_PCIFRONT_H__
++
++#include <linux/spinlock.h>
++
++#ifdef __KERNEL__
++
++#ifndef __ia64__
++
++struct pcifront_device;
++struct pci_bus;
++
++struct pcifront_sd {
++	int domain;
++	struct pcifront_device *pdev;
++};
++
++static inline struct pcifront_device *
++pcifront_get_pdev(struct pcifront_sd *sd)
++{
++	return sd->pdev;
++}
++
++static inline void pcifront_init_sd(struct pcifront_sd *sd,
++				    unsigned int domain, unsigned int bus,
++				    struct pcifront_device *pdev)
++{
++	sd->domain = domain;
++	sd->pdev = pdev;
++}
++
++#if defined(CONFIG_PCI_DOMAINS)
++static inline int pci_domain_nr(struct pci_bus *bus)
++{
++	struct pcifront_sd *sd = bus->sysdata;
++	return sd->domain;
++}
++static inline int pci_proc_domain(struct pci_bus *bus)
++{
++	return pci_domain_nr(bus);
++}
++#endif /* CONFIG_PCI_DOMAINS */
++
++static inline void pcifront_setup_root_resources(struct pci_bus *bus,
++						 struct pcifront_sd *sd)
++{
++}
++
++#else /* __ia64__ */
++
++#include <linux/acpi.h>
++#include <asm/pci.h>
++#define pcifront_sd pci_controller
++
++extern void xen_add_resource(struct pci_controller *, unsigned int,
++			     unsigned int, struct acpi_resource *);
++extern void xen_pcibios_setup_root_windows(struct pci_bus *,
++					   struct pci_controller *);
++
++static inline struct pcifront_device *
++pcifront_get_pdev(struct pcifront_sd *sd)
++{
++	return (struct pcifront_device *)sd->platform_data;
++}
++
++static inline void pcifront_setup_root_resources(struct pci_bus *bus,
++						 struct pcifront_sd *sd)
++{
++	xen_pcibios_setup_root_windows(bus, sd);
++}
++
++#endif /* __ia64__ */
++
++extern struct rw_semaphore pci_bus_sem;
++
++#endif /* __KERNEL__ */
++
++#endif /* __XEN_ASM_PCIFRONT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/public/evtchn.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,88 @@
++/******************************************************************************
++ * evtchn.h
++ * 
++ * Interface to /dev/xen/evtchn.
++ * 
++ * Copyright (c) 2003-2005, K A Fraser
++ * 
++ * 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 __LINUX_PUBLIC_EVTCHN_H__
++#define __LINUX_PUBLIC_EVTCHN_H__
++
++/*
++ * Bind a fresh port to VIRQ @virq.
++ * Return allocated port.
++ */
++#define IOCTL_EVTCHN_BIND_VIRQ				\
++	_IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
++struct ioctl_evtchn_bind_virq {
++	unsigned int virq;
++};
++
++/*
++ * Bind a fresh port to remote <@remote_domain, @remote_port>.
++ * Return allocated port.
++ */
++#define IOCTL_EVTCHN_BIND_INTERDOMAIN			\
++	_IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
++struct ioctl_evtchn_bind_interdomain {
++	unsigned int remote_domain, remote_port;
++};
++
++/*
++ * Allocate a fresh port for binding to @remote_domain.
++ * Return allocated port.
++ */
++#define IOCTL_EVTCHN_BIND_UNBOUND_PORT			\
++	_IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
++struct ioctl_evtchn_bind_unbound_port {
++	unsigned int remote_domain;
++};
++
++/*
++ * Unbind previously allocated @port.
++ */
++#define IOCTL_EVTCHN_UNBIND				\
++	_IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
++struct ioctl_evtchn_unbind {
++	unsigned int port;
++};
++
++/*
++ * Unbind previously allocated @port.
++ */
++#define IOCTL_EVTCHN_NOTIFY				\
++	_IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify))
++struct ioctl_evtchn_notify {
++	unsigned int port;
++};
++
++/* Clear and reinitialise the event buffer. Clear error condition. */
++#define IOCTL_EVTCHN_RESET				\
++	_IOC(_IOC_NONE, 'E', 5, 0)
++
++#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/public/gntdev.h	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,119 @@
++/******************************************************************************
++ * gntdev.h
++ * 
++ * Interface to /dev/xen/gntdev.
++ * 
++ * Copyright (c) 2007, D G Murray
++ * 
++ * 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 __LINUX_PUBLIC_GNTDEV_H__
++#define __LINUX_PUBLIC_GNTDEV_H__
++
++struct ioctl_gntdev_grant_ref {
++	/* The domain ID of the grant to be mapped. */
++	uint32_t domid;
++	/* The grant reference of the grant to be mapped. */
++	uint32_t ref;
++};
++
++/*
++ * Inserts the grant references into the mapping table of an instance
++ * of gntdev. N.B. This does not perform the mapping, which is deferred
++ * until mmap() is called with @index as the offset.
++ */
++#define IOCTL_GNTDEV_MAP_GRANT_REF \
++_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
++struct ioctl_gntdev_map_grant_ref {
++	/* IN parameters */
++	/* The number of grants to be mapped. */
++	uint32_t count;
++	uint32_t pad;
++	/* OUT parameters */
++	/* The offset to be used on a subsequent call to mmap(). */
++	uint64_t index;
++	/* Variable IN parameter. */
++	/* Array of grant references, of size @count. */
++	struct ioctl_gntdev_grant_ref refs[1];
++};
++
++/*
++ * Removes the grant references from the mapping table of an instance of
++ * of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
++ * before this ioctl is called, or an error will result.
++ */
++#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
++_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))       
++struct ioctl_gntdev_unmap_grant_ref {
++	/* IN parameters */
++	/* The offset was returned by the corresponding map operation. */
++	uint64_t index;
++	/* The number of pages to be unmapped. */
++	uint32_t count;
++	uint32_t pad;
++};
++
++/*
++ * Returns the offset in the driver's address space that corresponds
++ * to @vaddr. This can be used to perform a munmap(), followed by an
++ * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by
++ * the caller. The number of pages that were allocated at the same time as
++ * @vaddr is returned in @count.
++ *
++ * N.B. Where more than one page has been mapped into a contiguous range, the
++ *      supplied @vaddr must correspond to the start of the range; otherwise
++ *      an error will result. It is only possible to munmap() the entire
++ *      contiguously-allocated range at once, and not any subrange thereof.
++ */
++#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \
++_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr))
++struct ioctl_gntdev_get_offset_for_vaddr {
++	/* IN parameters */
++	/* The virtual address of the first mapped page in a range. */
++	uint64_t vaddr;
++	/* OUT parameters */
++	/* The offset that was used in the initial mmap() operation. */
++	uint64_t offset;
++	/* The number of pages mapped in the VM area that begins at @vaddr. */
++	uint32_t count;
++	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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/public/privcmd.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,89 @@
++/******************************************************************************
++ * privcmd.h
++ * 
++ * Interface to /proc/xen/privcmd.
++ * 
++ * Copyright (c) 2003-2005, K A Fraser
++ * 
++ * 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 __LINUX_PUBLIC_PRIVCMD_H__
++#define __LINUX_PUBLIC_PRIVCMD_H__
++
++#include <linux/types.h>
++
++#ifndef __user
++#define __user
++#endif
++
++typedef struct privcmd_hypercall
++{
++	__u64 op;
++	__u64 arg[5];
++} privcmd_hypercall_t;
++
++typedef struct privcmd_mmap_entry {
++	__u64 va;
++	__u64 mfn;
++	__u64 npages;
++} privcmd_mmap_entry_t; 
++
++typedef struct privcmd_mmap {
++	int num;
++	domid_t dom; /* target domain */
++	privcmd_mmap_entry_t __user *entry;
++} privcmd_mmap_t; 
++
++typedef struct privcmd_mmapbatch {
++	int num;     /* number of pages to populate */
++	domid_t dom; /* target domain */
++	__u64 addr;  /* virtual address */
++	xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */
++} privcmd_mmapbatch_t; 
++
++typedef struct privcmd_mmapbatch_v2 {
++	unsigned int num; /* number of pages to populate */
++	domid_t dom;      /* target domain */
++	__u64 addr;       /* virtual address */
++	const xen_pfn_t __user *arr; /* array of mfns */
++	int __user *err;  /* array of error codes */
++} privcmd_mmapbatch_v2_t;
++
++/*
++ * @cmd: IOCTL_PRIVCMD_HYPERCALL
++ * @arg: &privcmd_hypercall_t
++ * Return: Value returned from execution of the specified hypercall.
++ */
++#define IOCTL_PRIVCMD_HYPERCALL					\
++	_IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
++#define IOCTL_PRIVCMD_MMAP					\
++	_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
++#define IOCTL_PRIVCMD_MMAPBATCH					\
++	_IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
++#define IOCTL_PRIVCMD_MMAPBATCH_V2				\
++	_IOC(_IOC_NONE, 'P', 4, sizeof(privcmd_mmapbatch_v2_t))
++
++#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/public/xenbus.h	2009-05-29 10:25:53.000000000 +0200
+@@ -0,0 +1,56 @@
++/******************************************************************************
++ * xenbus.h
++ * 
++ * Interface to /proc/xen/xenbus.
++ * 
++ * Copyright (c) 2008, Diego Ongaro <diego.ongaro@citrix.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; 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 __LINUX_PUBLIC_XENBUS_H__
++#define __LINUX_PUBLIC_XENBUS_H__
++
++#include <linux/types.h>
++
++#ifndef __user
++#define __user
++#endif
++
++typedef struct xenbus_alloc {
++	domid_t dom;
++	__u32 port;
++	__u32 grant_ref;
++} xenbus_alloc_t;
++
++/*
++ * @cmd: IOCTL_XENBUS_ALLOC
++ * @arg: &xenbus_alloc_t
++ * Return: 0, or -1 for error
++ */
++#define IOCTL_XENBUS_ALLOC					\
++	_IOC(_IOC_NONE, 'X', 0, sizeof(xenbus_alloc_t))
++
++#endif /* __LINUX_PUBLIC_XENBUS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/xen_proc.h	2007-06-12 13:14:19.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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/xencons.h	2007-10-15 09:39:38.000000000 +0200
+@@ -0,0 +1,17 @@
++#ifndef __ASM_XENCONS_H__
++#define __ASM_XENCONS_H__
++
++struct dom0_vga_console_info;
++void dom0_init_screen_info(const struct dom0_vga_console_info *, size_t);
++
++void xencons_force_flush(void);
++void xencons_resume(void);
++
++/* Interrupt work hooks. Receive data, or kick data out. */
++void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
++void xencons_tx(void);
++
++int xencons_ring_init(void);
++int xencons_ring_send(const char *data, unsigned len);
++
++#endif /* __ASM_XENCONS_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/xenoprof.h	2007-06-12 13:14:19.000000000 +0200
+@@ -0,0 +1,42 @@
++/******************************************************************************
++ * xen/xenoprof.h
++ *
++ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan K.K.
++ *
++ * 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_XENOPROF_H__
++#define __XEN_XENOPROF_H__
++#ifdef CONFIG_XEN
++
++#include <asm/xenoprof.h>
++
++struct oprofile_operations;
++int xenoprofile_init(struct oprofile_operations * ops);
++void xenoprofile_exit(void);
++
++struct xenoprof_shared_buffer {
++	char					*buffer;
++	struct xenoprof_arch_shared_buffer	arch;
++};
++#else
++#define xenoprofile_init(ops)	(-ENOSYS)
++#define xenoprofile_exit()	do { } while (0)
++
++#endif /* CONFIG_XEN */
++#endif /* __XEN_XENOPROF_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-04-07 13:58:49.000000000 +0200
+@@ -0,0 +1,739 @@
++/*
++ * Dynamic DMA mapping support.
++ *
++ * This implementation is a fallback for platforms that do not support
++ * I/O TLBs (aka DMA address translation hardware).
++ * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com>
++ * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com>
++ * Copyright (C) 2000, 2003 Hewlett-Packard Co
++ *	David Mosberger-Tang <davidm@hpl.hp.com>
++ * Copyright (C) 2005 Keir Fraser <keir@xensource.com>
++ */
++
++#include <linux/cache.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <asm/io.h>
++#include <asm/pci.h>
++#include <asm/dma.h>
++#include <asm/uaccess.h>
++#include <xen/gnttab.h>
++#include <xen/interface/memory.h>
++#include <asm-i386/mach-xen/asm/gnttab_dma.h>
++
++int swiotlb;
++EXPORT_SYMBOL(swiotlb);
++
++#define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
++
++/*
++ * Maximum allowable number of contiguous slabs to map,
++ * must be a power of 2.  What is the appropriate value ?
++ * The complexity of {map,unmap}_single is linearly dependent on this value.
++ */
++#define IO_TLB_SEGSIZE	128
++
++/*
++ * log of the size of each IO TLB slab.  The number of slabs is command line
++ * controllable.
++ */
++#define IO_TLB_SHIFT 11
++
++int swiotlb_force;
++
++static char *iotlb_virt_start;
++static unsigned long iotlb_nslabs;
++
++/*
++ * Used to do a quick range check in swiotlb_unmap_single and
++ * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
++ * API.
++ */
++static unsigned long iotlb_pfn_start, iotlb_pfn_end;
++
++/* Does the given dma address reside within the swiotlb aperture? */
++static inline int in_swiotlb_aperture(dma_addr_t dev_addr)
++{
++	unsigned long pfn = mfn_to_local_pfn(dev_addr >> PAGE_SHIFT);
++	return (pfn_valid(pfn)
++		&& (pfn >= iotlb_pfn_start)
++		&& (pfn < iotlb_pfn_end));
++}
++
++/*
++ * When the IOMMU overflows we return a fallback buffer. This sets the size.
++ */
++static unsigned long io_tlb_overflow = 32*1024;
++
++void *io_tlb_overflow_buffer;
++
++/*
++ * This is a free list describing the number of free entries available from
++ * each index
++ */
++static unsigned int *io_tlb_list;
++static unsigned int io_tlb_index;
++
++/*
++ * We need to save away the original address corresponding to a mapped entry
++ * for the sync operations.
++ */
++static struct phys_addr {
++	struct page *page;
++	unsigned int offset;
++} *io_tlb_orig_addr;
++
++/*
++ * Protect the above data structures in the map and unmap calls
++ */
++static DEFINE_SPINLOCK(io_tlb_lock);
++
++static unsigned int dma_bits;
++static unsigned int __initdata max_dma_bits = 32;
++static int __init
++setup_dma_bits(char *str)
++{
++	max_dma_bits = simple_strtoul(str, NULL, 0);
++	return 0;
++}
++__setup("dma_bits=", setup_dma_bits);
++
++static int __init
++setup_io_tlb_npages(char *str)
++{
++	/* Unlike ia64, the size is aperture in megabytes, not 'slabs'! */
++	if (isdigit(*str)) {
++		iotlb_nslabs = simple_strtoul(str, &str, 0) <<
++			(20 - IO_TLB_SHIFT);
++		iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE);
++	}
++	if (*str == ',')
++		++str;
++	/*
++         * NB. 'force' enables the swiotlb, but doesn't force its use for
++         * every DMA like it does on native Linux. 'off' forcibly disables
++         * use of the swiotlb.
++         */
++	if (!strcmp(str, "force"))
++		swiotlb_force = 1;
++	else if (!strcmp(str, "off"))
++		swiotlb_force = -1;
++	return 1;
++}
++__setup("swiotlb=", setup_io_tlb_npages);
++/* make io_tlb_overflow tunable too? */
++
++/*
++ * Statically reserve bounce buffer space and initialize bounce buffer data
++ * structures for the software IO TLB used to implement the PCI DMA API.
++ */
++void
++swiotlb_init_with_default_size (size_t default_size)
++{
++	unsigned long i, bytes;
++	int rc;
++
++	if (!iotlb_nslabs) {
++		iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
++		iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE);
++	}
++
++	bytes = iotlb_nslabs * (1UL << IO_TLB_SHIFT);
++
++	/*
++	 * Get IO TLB memory from the low pages
++	 */
++	iotlb_virt_start = alloc_bootmem_pages(bytes);
++	if (!iotlb_virt_start)
++		panic("Cannot allocate SWIOTLB buffer!\n");
++
++	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
++	for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
++		do {
++			rc = xen_create_contiguous_region(
++				(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
++				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
++				dma_bits);
++		} while (rc && dma_bits++ < max_dma_bits);
++		if (rc) {
++			if (i == 0)
++				panic("No suitable physical memory available for SWIOTLB buffer!\n"
++				      "Use dom0_mem Xen boot parameter to reserve\n"
++				      "some DMA memory (e.g., dom0_mem=-128M).\n");
++			iotlb_nslabs = i;
++			i <<= IO_TLB_SHIFT;
++			free_bootmem(__pa(iotlb_virt_start + i), bytes - i);
++			bytes = i;
++			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
++				unsigned int bits = fls64(virt_to_bus(iotlb_virt_start + i - 1));
++
++				if (bits > dma_bits)
++					dma_bits = bits;
++			}
++			break;
++		}
++	}
++
++	/*
++	 * Allocate and initialize the free list array.  This array is used
++	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE.
++	 */
++	io_tlb_list = alloc_bootmem(iotlb_nslabs * sizeof(int));
++	for (i = 0; i < iotlb_nslabs; i++)
++ 		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
++	io_tlb_index = 0;
++	io_tlb_orig_addr = alloc_bootmem(
++		iotlb_nslabs * sizeof(*io_tlb_orig_addr));
++
++	/*
++	 * Get the overflow emergency buffer
++	 */
++	io_tlb_overflow_buffer = alloc_bootmem(io_tlb_overflow);
++	if (!io_tlb_overflow_buffer)
++		panic("Cannot allocate SWIOTLB overflow buffer!\n");
++
++	do {
++		rc = xen_create_contiguous_region(
++			(unsigned long)io_tlb_overflow_buffer,
++			get_order(io_tlb_overflow),
++			dma_bits);
++	} while (rc && dma_bits++ < max_dma_bits);
++	if (rc)
++		panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
++
++	iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT;
++	iotlb_pfn_end   = iotlb_pfn_start + (bytes >> PAGE_SHIFT);
++
++	printk(KERN_INFO "Software IO TLB enabled: \n"
++	       " Aperture:     %lu megabytes\n"
++	       " Kernel range: %p - %p\n"
++	       " Address size: %u bits\n",
++	       bytes >> 20,
++	       iotlb_virt_start, iotlb_virt_start + bytes,
++	       dma_bits);
++}
++
++void
++swiotlb_init(void)
++{
++	long ram_end;
++	size_t defsz = 64 * (1 << 20); /* 64MB default size */
++
++	if (swiotlb_force == 1) {
++		swiotlb = 1;
++	} else if ((swiotlb_force != -1) &&
++		   is_running_on_xen() &&
++		   is_initial_xendomain()) {
++		/* Domain 0 always has a swiotlb. */
++		ram_end = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
++		if (ram_end <= 0x7ffff)
++			defsz = 2 * (1 << 20); /* 2MB on <2GB on systems. */
++		swiotlb = 1;
++	}
++
++	if (swiotlb)
++		swiotlb_init_with_default_size(defsz);
++	else
++		printk(KERN_INFO "Software IO TLB disabled\n");
++}
++
++/*
++ * We use __copy_to_user_inatomic to transfer to the host buffer because the
++ * buffer may be mapped read-only (e.g, in blkback driver) but lower-level
++ * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
++ * unnecessary copy from the aperture to the host buffer, and a page fault.
++ */
++static void
++__sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
++{
++	if (PageHighMem(buffer.page)) {
++		size_t len, bytes;
++		char *dev, *host, *kmp;
++		len = size;
++		while (len != 0) {
++			unsigned long flags;
++
++			if (((bytes = len) + buffer.offset) > PAGE_SIZE)
++				bytes = PAGE_SIZE - buffer.offset;
++			local_irq_save(flags); /* protects KM_BOUNCE_READ */
++			kmp  = kmap_atomic(buffer.page, KM_BOUNCE_READ);
++			dev  = dma_addr + size - len;
++			host = kmp + buffer.offset;
++			if (dir == DMA_FROM_DEVICE) {
++				if (__copy_to_user_inatomic(host, dev, bytes))
++					/* inaccessible */;
++			} else
++				memcpy(dev, host, bytes);
++			kunmap_atomic(kmp, KM_BOUNCE_READ);
++			local_irq_restore(flags);
++			len -= bytes;
++			buffer.page++;
++			buffer.offset = 0;
++		}
++	} else {
++		char *host = (char *)phys_to_virt(
++			page_to_pseudophys(buffer.page)) + buffer.offset;
++		if (dir == DMA_FROM_DEVICE) {
++			if (__copy_to_user_inatomic(host, dma_addr, size))
++				/* inaccessible */;
++		} else if (dir == DMA_TO_DEVICE)
++			memcpy(dma_addr, host, size);
++	}
++}
++
++/*
++ * Allocates bounce buffer and returns its kernel virtual address.
++ */
++static void *
++map_single(struct device *hwdev, struct phys_addr buffer, size_t size, int dir)
++{
++	unsigned long flags;
++	char *dma_addr;
++	unsigned int nslots, stride, index, wrap;
++	struct phys_addr slot_buf;
++	int i;
++
++	/*
++	 * For mappings greater than a page, we limit the stride (and
++	 * hence alignment) to a page size.
++	 */
++	nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
++	if (size > PAGE_SIZE)
++		stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
++	else
++		stride = 1;
++
++	BUG_ON(!nslots);
++
++	/*
++	 * Find suitable number of IO TLB entries size that will fit this
++	 * request and allocate a buffer from that IO TLB pool.
++	 */
++	spin_lock_irqsave(&io_tlb_lock, flags);
++	{
++		wrap = index = ALIGN(io_tlb_index, stride);
++
++		if (index >= iotlb_nslabs)
++			wrap = index = 0;
++
++		do {
++			/*
++			 * If we find a slot that indicates we have 'nslots'
++			 * number of contiguous buffers, we allocate the
++			 * buffers from that slot and mark the entries as '0'
++			 * indicating unavailable.
++			 */
++			if (io_tlb_list[index] >= nslots) {
++				int count = 0;
++
++				for (i = index; i < (int)(index + nslots); i++)
++					io_tlb_list[i] = 0;
++				for (i = index - 1;
++				     (OFFSET(i, IO_TLB_SEGSIZE) !=
++				      IO_TLB_SEGSIZE -1) && io_tlb_list[i];
++				     i--)
++					io_tlb_list[i] = ++count;
++				dma_addr = iotlb_virt_start +
++					(index << IO_TLB_SHIFT);
++
++				/*
++				 * Update the indices to avoid searching in
++				 * the next round.
++				 */
++				io_tlb_index = 
++					((index + nslots) < iotlb_nslabs
++					 ? (index + nslots) : 0);
++
++				goto found;
++			}
++			index += stride;
++			if (index >= iotlb_nslabs)
++				index = 0;
++		} while (index != wrap);
++
++		spin_unlock_irqrestore(&io_tlb_lock, flags);
++		return NULL;
++	}
++  found:
++	spin_unlock_irqrestore(&io_tlb_lock, flags);
++
++	/*
++	 * Save away the mapping from the original address to the DMA address.
++	 * This is needed when we sync the memory.  Then we sync the buffer if
++	 * needed.
++	 */
++	slot_buf = buffer;
++	for (i = 0; i < nslots; i++) {
++		slot_buf.page += slot_buf.offset >> PAGE_SHIFT;
++		slot_buf.offset &= PAGE_SIZE - 1;
++		io_tlb_orig_addr[index+i] = slot_buf;
++		slot_buf.offset += 1 << IO_TLB_SHIFT;
++	}
++	if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL))
++		__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
++
++	return dma_addr;
++}
++
++static struct phys_addr dma_addr_to_phys_addr(char *dma_addr)
++{
++	int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
++	struct phys_addr buffer = io_tlb_orig_addr[index];
++	buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1);
++	buffer.page += buffer.offset >> PAGE_SHIFT;
++	buffer.offset &= PAGE_SIZE - 1;
++	return buffer;
++}
++
++/*
++ * dma_addr is the kernel virtual address of the bounce buffer to unmap.
++ */
++static void
++unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
++{
++	unsigned long flags;
++	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
++	int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
++	struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
++
++	/*
++	 * First, sync the memory before unmapping the entry
++	 */
++	if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
++		__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
++
++	/*
++	 * Return the buffer to the free list by setting the corresponding
++	 * entries to indicate the number of contigous entries available.
++	 * While returning the entries to the free list, we merge the entries
++	 * with slots below and above the pool being returned.
++	 */
++	spin_lock_irqsave(&io_tlb_lock, flags);
++	{
++		count = ((index + nslots) < ALIGN(index + 1, IO_TLB_SEGSIZE) ?
++			 io_tlb_list[index + nslots] : 0);
++		/*
++		 * Step 1: return the slots to the free list, merging the
++		 * slots with superceeding slots
++		 */
++		for (i = index + nslots - 1; i >= index; i--)
++			io_tlb_list[i] = ++count;
++		/*
++		 * Step 2: merge the returned slots with the preceding slots,
++		 * if available (non zero)
++		 */
++		for (i = index - 1;
++		     (OFFSET(i, IO_TLB_SEGSIZE) !=
++		      IO_TLB_SEGSIZE -1) && io_tlb_list[i];
++		     i--)
++			io_tlb_list[i] = ++count;
++	}
++	spin_unlock_irqrestore(&io_tlb_lock, flags);
++}
++
++static void
++sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
++{
++	struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
++	BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
++	__sync_single(buffer, dma_addr, size, dir);
++}
++
++static void
++swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
++{
++	/*
++	 * Ran out of IOMMU space for this operation. This is very bad.
++	 * Unfortunately the drivers cannot handle this operation properly.
++	 * unless they check for pci_dma_mapping_error (most don't)
++	 * When the mapping is small enough return a static buffer to limit
++	 * the damage, or panic when the transfer is too big.
++	 */
++	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %lu bytes at "
++	       "device %s\n", (unsigned long)size, dev ? dev->bus_id : "?");
++
++	if (size > io_tlb_overflow && do_panic) {
++		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
++			panic("PCI-DMA: Memory would be corrupted\n");
++		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL)
++			panic("PCI-DMA: Random memory would be DMAed\n");
++	}
++}
++
++/*
++ * Map a single buffer of the indicated size for DMA in streaming mode.  The
++ * PCI address to use is returned.
++ *
++ * Once the device is given the dma address, the device owns this memory until
++ * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
++ */
++dma_addr_t
++swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
++{
++	dma_addr_t dev_addr = gnttab_dma_map_page(virt_to_page(ptr)) +
++			      offset_in_page(ptr);
++	void *map;
++	struct phys_addr buffer;
++
++	BUG_ON(dir == DMA_NONE);
++
++	/*
++	 * If the pointer passed in happens to be in the device's DMA window,
++	 * we can safely return the device addr and not worry about bounce
++	 * buffering it.
++	 */
++	if (!range_straddles_page_boundary(__pa(ptr), size) &&
++	    !address_needs_mapping(hwdev, dev_addr))
++		return dev_addr;
++
++	/*
++	 * Oh well, have to allocate and map a bounce buffer.
++	 */
++	gnttab_dma_unmap_page(dev_addr);
++	buffer.page   = virt_to_page(ptr);
++	buffer.offset = (unsigned long)ptr & ~PAGE_MASK;
++	map = map_single(hwdev, buffer, size, dir);
++	if (!map) {
++		swiotlb_full(hwdev, size, dir, 1);
++		map = io_tlb_overflow_buffer;
++	}
++
++	dev_addr = virt_to_bus(map);
++	return dev_addr;
++}
++
++/*
++ * Unmap a single streaming mode DMA translation.  The dma_addr and size must
++ * match what was provided for in a previous swiotlb_map_single call.  All
++ * other usages are undefined.
++ *
++ * After this call, reads by the cpu to the buffer are guaranteed to see
++ * whatever the device wrote there.
++ */
++void
++swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
++		     int dir)
++{
++	BUG_ON(dir == DMA_NONE);
++	if (in_swiotlb_aperture(dev_addr))
++		unmap_single(hwdev, bus_to_virt(dev_addr), size, dir);
++	else
++		gnttab_dma_unmap_page(dev_addr);
++}
++
++/*
++ * Make physical memory consistent for a single streaming mode DMA translation
++ * after a transfer.
++ *
++ * If you perform a swiotlb_map_single() but wish to interrogate the buffer
++ * using the cpu, yet do not wish to teardown the PCI dma mapping, you must
++ * call this function before doing so.  At the next point you give the PCI dma
++ * address back to the card, you must first perform a
++ * swiotlb_dma_sync_for_device, and then the device again owns the buffer
++ */
++void
++swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
++			    size_t size, int dir)
++{
++	BUG_ON(dir == DMA_NONE);
++	if (in_swiotlb_aperture(dev_addr))
++		sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
++}
++
++void
++swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
++			       size_t size, int dir)
++{
++	BUG_ON(dir == DMA_NONE);
++	if (in_swiotlb_aperture(dev_addr))
++		sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
++}
++
++/*
++ * Map a set of buffers described by scatterlist in streaming mode for DMA.
++ * This is the scatter-gather version of the above swiotlb_map_single
++ * interface.  Here the scatter gather list elements are each tagged with the
++ * appropriate dma address and length.  They are obtained via
++ * sg_dma_{address,length}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ *       DMA address/length pairs than there are SG table elements.
++ *       (for example via virtual mapping capabilities)
++ *       The routine returns the number of addr/length pairs actually
++ *       used, at most nents.
++ *
++ * Device ownership issues as mentioned above for swiotlb_map_single are the
++ * same here.
++ */
++int
++swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
++	       int dir)
++{
++	struct phys_addr buffer;
++	dma_addr_t dev_addr;
++	char *map;
++	int i;
++
++	BUG_ON(dir == DMA_NONE);
++
++	for (i = 0; i < nelems; i++, sg++) {
++		dev_addr = gnttab_dma_map_page(sg->page) + sg->offset;
++
++		if (range_straddles_page_boundary(page_to_pseudophys(sg->page)
++						  + sg->offset, sg->length)
++		    || address_needs_mapping(hwdev, dev_addr)) {
++			gnttab_dma_unmap_page(dev_addr);
++			buffer.page   = sg->page;
++			buffer.offset = sg->offset;
++			map = map_single(hwdev, buffer, sg->length, dir);
++			if (!map) {
++				/* Don't panic here, we expect map_sg users
++				   to do proper error handling. */
++				swiotlb_full(hwdev, sg->length, dir, 0);
++				swiotlb_unmap_sg(hwdev, sg - i, i, dir);
++				sg[0].dma_length = 0;
++				return 0;
++			}
++			sg->dma_address = (dma_addr_t)virt_to_bus(map);
++		} else
++			sg->dma_address = dev_addr;
++		sg->dma_length = sg->length;
++	}
++	return nelems;
++}
++
++/*
++ * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
++ * concerning calls here are the same as for swiotlb_unmap_single() above.
++ */
++void
++swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
++		 int dir)
++{
++	int i;
++
++	BUG_ON(dir == DMA_NONE);
++
++	for (i = 0; i < nelems; i++, sg++)
++		if (in_swiotlb_aperture(sg->dma_address))
++			unmap_single(hwdev, 
++				     (void *)bus_to_virt(sg->dma_address),
++				     sg->dma_length, dir);
++		else
++			gnttab_dma_unmap_page(sg->dma_address);
++}
++
++/*
++ * Make physical memory consistent for a set of streaming mode DMA translations
++ * after a transfer.
++ *
++ * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules
++ * and usage.
++ */
++void
++swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
++			int nelems, int dir)
++{
++	int i;
++
++	BUG_ON(dir == DMA_NONE);
++
++	for (i = 0; i < nelems; i++, sg++)
++		if (in_swiotlb_aperture(sg->dma_address))
++			sync_single(hwdev,
++				    (void *)bus_to_virt(sg->dma_address),
++				    sg->dma_length, dir);
++}
++
++void
++swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
++			   int nelems, int dir)
++{
++	int i;
++
++	BUG_ON(dir == DMA_NONE);
++
++	for (i = 0; i < nelems; i++, sg++)
++		if (in_swiotlb_aperture(sg->dma_address))
++			sync_single(hwdev,
++				    (void *)bus_to_virt(sg->dma_address),
++				    sg->dma_length, dir);
++}
++
++#ifdef CONFIG_HIGHMEM
++
++dma_addr_t
++swiotlb_map_page(struct device *hwdev, struct page *page,
++		 unsigned long offset, size_t size,
++		 enum dma_data_direction direction)
++{
++	struct phys_addr buffer;
++	dma_addr_t dev_addr;
++	char *map;
++
++	dev_addr = gnttab_dma_map_page(page) + offset;
++	if (address_needs_mapping(hwdev, dev_addr)) {
++		gnttab_dma_unmap_page(dev_addr);
++		buffer.page   = page;
++		buffer.offset = offset;
++		map = map_single(hwdev, buffer, size, direction);
++		if (!map) {
++			swiotlb_full(hwdev, size, direction, 1);
++			map = io_tlb_overflow_buffer;
++		}
++		dev_addr = (dma_addr_t)virt_to_bus(map);
++	}
++
++	return dev_addr;
++}
++
++void
++swiotlb_unmap_page(struct device *hwdev, dma_addr_t dma_address,
++		   size_t size, enum dma_data_direction direction)
++{
++	BUG_ON(direction == DMA_NONE);
++	if (in_swiotlb_aperture(dma_address))
++		unmap_single(hwdev, bus_to_virt(dma_address), size, direction);
++	else
++		gnttab_dma_unmap_page(dma_address);
++}
++
++#endif
++
++int
++swiotlb_dma_mapping_error(dma_addr_t dma_addr)
++{
++	return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
++}
++
++/*
++ * Return whether the given PCI device DMA address mask can be supported
++ * properly.  For example, if your device can only drive the low 24-bits
++ * during PCI bus mastering, then you would pass 0x00ffffff as the mask to
++ * this function.
++ */
++int
++swiotlb_dma_supported (struct device *hwdev, u64 mask)
++{
++	return (mask >= ((1UL << dma_bits) - 1));
++}
++
++EXPORT_SYMBOL(swiotlb_init);
++EXPORT_SYMBOL(swiotlb_map_single);
++EXPORT_SYMBOL(swiotlb_unmap_single);
++EXPORT_SYMBOL(swiotlb_map_sg);
++EXPORT_SYMBOL(swiotlb_unmap_sg);
++EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
++EXPORT_SYMBOL(swiotlb_sync_single_for_device);
++EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
++EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
++EXPORT_SYMBOL(swiotlb_dma_mapping_error);
++EXPORT_SYMBOL(swiotlb_dma_supported);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/mm/tmem-xen.c	2009-06-23 09:28:21.000000000 +0200
+@@ -0,0 +1,41 @@
++/*
++ * Xen implementation for transcendent memory (tmem)
++ *
++ * Dan Magenheimer <dan.magenheimer@oracle.com> 2009
++ */
++
++#include <linux/types.h>
++#include <xen/interface/xen.h>
++#include <asm/hypervisor.h>
++
++int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
++	unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len)
++{
++	struct tmem_op op;
++	int rc = 0;
++
++	op.cmd = tmem_cmd;
++	op.pool_id = tmem_pool;
++	op.u.gen.object = object;
++	op.u.gen.index = index;
++	op.u.gen.tmem_offset = tmem_offset;
++	op.u.gen.pfn_offset = pfn_offset;
++	op.u.gen.len = len;
++	op.u.gen.cmfn = gmfn;
++	rc = HYPERVISOR_tmem_op(&op);
++	return rc;
++}
++
++int xen_tmem_new_pool(uint32_t tmem_cmd, uint64_t uuid_lo,
++	uint64_t uuid_hi, uint32_t flags)
++{
++	struct tmem_op op;
++	int rc = 0;
++
++	op.cmd = tmem_cmd;
++	op.u.new.uuid[0] = uuid_lo;
++	op.u.new.uuid[1] = uuid_hi;
++	op.u.new.flags = flags;
++	rc = HYPERVISOR_tmem_op(&op);
++	return rc;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/scripts/Makefile.xen.awk	2007-08-06 15:10:49.000000000 +0200
+@@ -0,0 +1,34 @@
++BEGIN {
++	is_rule = 0
++}
++
++/^[[:space:]]*#/ {
++	next
++}
++
++/^[[:space:]]*$/ {
++	if (is_rule)
++		print("")
++	is_rule = 0
++	next
++}
++
++/:[[:space:]]*%\.[cS][[:space:]]/ {
++	line = gensub(/%.([cS])/, "%-xen.\\1", "g", $0)
++	line = gensub(/(single-used-m)/, "xen-\\1", "g", line)
++	print line
++	is_rule = 1
++	next
++}
++
++/^[^\t]$/ {
++	if (is_rule)
++		print("")
++	is_rule = 0
++	next
++}
++
++is_rule {
++	print $0
++	next
++}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/series.conf
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/series.conf
@@ -0,0 +1,147 @@
+########################################################
+# XEN architecture, version 3
+########################################################
+
+# xen patches, from xenbits mercurial repository.
+# http://xenbits.xensource.com/ext/linux-2.6-merge.hg
+#
+# everything named "xen3-auto-*" is auto-generated.
+# PLEASE DON'T EDIT THESE PATCHES.  Create fixup patches
+# on top of them instead.  This reduces workload when
+# re-basing to a newer xen tree.
+#
+	### both uml framebuffer and xen need this one.
+	patches.xen/add-console-use-vt
+
+	# split out patches
+	patches.xen/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch
+	patches.xen/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch
+	patches.xen/ipv6-no-autoconf
+	patches.xen/pci-guestdev
+	patches.xen/pci-reserve
+	patches.xen/sfc-driverlink
+	patches.xen/sfc-resource-driver
+	patches.xen/sfc-driverlink-conditional
+	patches.xen/sfc-external-sram
+	patches.xen/tmem
+
+	# bulk stuff, new files for xen
+	patches.xen/xen3-auto-xen-arch.diff
+	patches.xen/xen3-auto-xen-drivers.diff
+	patches.xen/xen3-auto-include-xen-interface.diff
+
+	# kconfig bits for xen
+	patches.xen/xen3-auto-xen-kconfig.diff
+
+	# common code changes
+	patches.xen/xen3-auto-common.diff
+	patches.xen/xen3-auto-arch-x86.diff
+	patches.xen/xen3-auto-arch-i386.diff
+	patches.xen/xen3-auto-arch-x86_64.diff
+
+	# fixups due to upstream Xen parts
+	patches.xen/xen3-fixup-xen
+
+	patches.xen/sfc-set-arch
+	patches.xen/sfc-endianness
+
+	# newer changeset backports
+
+	# changes outside arch/{i386,x86_64}/xen
+	patches.xen/xen3-fixup-kconfig
+	patches.xen/xen3-fixup-common
+	patches.xen/xen3-fixup-arch-x86
+
+	# ports of other patches
+	patches.xen/xen3-patch-2.6.18
+	patches.xen/xen3-patch-2.6.19
+	patches.xen/xen3-patch-2.6.20
+	patches.xen/xen3-patch-2.6.21
+	patches.xen/xen3-patch-2.6.22
+	patches.xen/xen3-patch-2.6.23
+	patches.xen/xen3-patch-2.6.24
+	patches.xen/xen3-patch-2.6.25
+	patches.xen/xen3-patch-2.6.26
+	patches.xen/xen3-patch-2.6.27
+	patches.xen/xen3-patch-2.6.28
+	patches.xen/xen3-patch-2.6.29
+	patches.xen/xen3-patch-2.6.30
+	patches.xen/xen3-patch-2.6.31
+	patches.xen/xen3-patch-2.6.32
+	patches.xen/xen3-patch-2.6.32.1-2
+	patches.xen/xen3-patch-2.6.32.2-3
+	patches.xen/xen3-patch-2.6.32.3-4
+	patches.xen/xen3-seccomp-disable-tsc-option
+	patches.xen/xen3-x86-mcp51-no-dac
+	patches.xen/xen3-x86-64-preserve-large-page-mapping-for-1st-2mb-kernel-txt-with-config_debug_rodata
+	patches.xen/xen3-x86-64-align-rodata-kernel-section-to-2mb-with-config_debug_rodata
+	patches.xen/xen3-x86-mark_rodata_rw.patch
+	patches.xen/xen3-x86-Remove-CPU-cache-size-output-for-non-Intel-too.patch
+	patches.xen/xen3-x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch
+	patches.xen/xen3-x86-Limit-the-number-of-processor-bootup-messages.patch
+	patches.xen/xen3-bug-561933_uv_pat_is_gru_range.patch
+	patches.xen/xen3-x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch
+	patches.xen/xen3-x86-intr-remap-Avoid-irq_chip-mask-unmask-in-fixup_irqs-for-intr-remapping.patch
+	patches.xen/xen3-x86-Remove-local_irq_enable-local_irq_disable-in-fixup_irqs.patch
+	patches.xen/xen3-vmw_pvscsi-scsi-driver-for-vmware-s-virtual-hba.patch
+	patches.xen/xen3-kdb-x86
+	patches.xen/xen3-stack-unwind
+	patches.xen/xen3-x86_64-unwind-annotations
+
+	# bugfixes and enhancements
+	patches.xen/xen-balloon-max-target
+	patches.xen/xen-modular-blktap
+	patches.xen/xen-blkback-bimodal-suse
+	patches.xen/xen-blkif-protocol-fallback-hack
+	patches.xen/xen-blkback-cdrom
+	patches.xen/xen-blktap-write-barriers
+	patches.xen/xen-op-packet
+	patches.xen/xen-blkfront-cdrom
+	patches.xen/xen-sections
+	patches.xen/xen-swiotlb-heuristics
+	patches.xen/xen-kconfig-compat
+	patches.xen/xen-cpufreq-report
+	patches.xen/xen-staging-build
+	patches.xen/xen-sysdev-suspend
+	patches.xen/xen-ipi-per-cpu-irq
+	patches.xen/xen-virq-per-cpu-irq
+	patches.xen/xen-spinlock-poll-early
+	patches.xen/xen-configurable-guest-devices
+	patches.xen/xen-netback-nr-irqs
+	patches.xen/xen-netback-notify-multi
+	patches.xen/xen-pciback-sriov
+	patches.xen/xen-unpriv-build
+	patches.xen/xen-vmalloc_32
+	patches.xen/xen-dcdbas
+	patches.xen/xen-privcmd-mmap-batch-clear
+	patches.xen/xen-x86-panic-no-reboot
+	patches.xen/xen-x86-dcr-fallback
+	patches.xen/xen-x86-consistent-nmi
+	patches.xen/xen-x86-no-lapic
+	patches.xen/xen-x86-pmd-handling
+	patches.xen/xen-x86-bigmem
+	patches.xen/xen-x86-machphys-prediction
+	patches.xen/xen-x86-exit-mmap
+	patches.xen/xen-x86-per-cpu-vcpu-info
+	patches.xen/xen-x86_64-pgd-pin
+	patches.xen/xen-x86_64-pgd-alloc-order
+	patches.xen/xen-x86_64-dump-user-pgt
+	patches.xen/xen-x86_64-note-init-p2m
+
+	# Imported later (individual changes/not 1:1)
+	patches.xen/xen3-patch-2.6.32.7-8
+	patches.xen/xen3-patch-2.6.32.8-9
+	patches.xen/xen3-patch-2.6.32.9-10
+	patches.xen/xen3-patch-2.6.32.10-11
+	patches.xen/xen3-patch-2.6.32.11-12
+	patches.xen/xen3-patch-2.6.32.12-13
+	patches.xen/xen3-patch-2.6.32.13-14
+	patches.xen/xen3-patch-2.6.32.15-16
+	patches.xen/xen3-patch-2.6.32.16-17 # ignored coretemp-xen.c
+	patches.xen/xen3-patch-2.6.32.18-19
+	patches.xen/xen3-patch-2.6.32.20-21
+	patches.xen/xen3-patch-2.6.32.21-22
+	patches.xen/xen3-patch-2.6.32.24-25
+	patches.xen/xen3-patch-2.6.32.25-26
+	patches.xen/xen3-patch-2.6.32.26-27
+	patches.xen/xen3-patch-2.6.32.27-28
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-dcr-fallback
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-dcr-fallback
@@ -0,0 +1,164 @@
+Subject: Add fallback when XENMEM_exchange fails to replace contiguous region
+From: jbeulich@novell.com
+Patch-mainline: obsolete
+References: 181869
+
+This avoids losing precious special memory in places where any memory can be
+used.
+
+--- head-2010-01-04.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/hypervisor.c	2009-06-09 15:52:17.000000000 +0200
+@@ -43,6 +43,7 @@
+ #include <xen/interface/memory.h>
+ #include <linux/module.h>
+ #include <linux/percpu.h>
++#include <linux/highmem.h>
+ #include <asm/tlbflush.h>
+ #include <linux/highmem.h>
+ 
+@@ -719,6 +720,83 @@ void xen_destroy_contiguous_region(unsig
+ 		BUG();
+ 
+ 	balloon_unlock(flags);
++
++	if (unlikely(!success)) {
++		/* Try hard to get the special memory back to Xen. */
++		exchange.in.extent_order = 0;
++		set_xen_guest_handle(exchange.in.extent_start, &in_frame);
++
++		for (i = 0; i < (1U<<order); i++) {
++			struct page *page = alloc_page(__GFP_HIGHMEM|__GFP_COLD);
++			unsigned long pfn;
++			mmu_update_t mmu;
++			unsigned int j = 0;
++
++			if (!page) {
++				printk(KERN_WARNING "Xen and kernel out of memory "
++				       "while trying to release an order %u "
++				       "contiguous region\n", order);
++				break;
++			}
++			pfn = page_to_pfn(page);
++
++			balloon_lock(flags);
++
++			if (!PageHighMem(page)) {
++				void *v = __va(pfn << PAGE_SHIFT);
++
++				scrub_pages(v, 1);
++				MULTI_update_va_mapping(cr_mcl + j, (unsigned long)v,
++							__pte_ma(0), UVMF_INVLPG|UVMF_ALL);
++				++j;
++			}
++#ifdef CONFIG_XEN_SCRUB_PAGES
++			else {
++				scrub_pages(kmap(page), 1);
++				kunmap(page);
++				kmap_flush_unused();
++			}
++#endif
++
++			frame = pfn_to_mfn(pfn);
++			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++
++			MULTI_update_va_mapping(cr_mcl + j, vstart,
++						pfn_pte_ma(frame, PAGE_KERNEL),
++						UVMF_INVLPG|UVMF_ALL);
++			++j;
++
++			pfn = __pa(vstart) >> PAGE_SHIFT;
++			set_phys_to_machine(pfn, frame);
++			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++				mmu.ptr = ((uint64_t)frame << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++				mmu.val = pfn;
++				cr_mcl[j].op = __HYPERVISOR_mmu_update;
++				cr_mcl[j].args[0] = (unsigned long)&mmu;
++				cr_mcl[j].args[1] = 1;
++				cr_mcl[j].args[2] = 0;
++				cr_mcl[j].args[3] = DOMID_SELF;
++				++j;
++			}
++
++			cr_mcl[j].op = __HYPERVISOR_memory_op;
++			cr_mcl[j].args[0] = XENMEM_decrease_reservation;
++			cr_mcl[j].args[1] = (unsigned long)&exchange.in;
++
++			if (HYPERVISOR_multicall(cr_mcl, j + 1))
++				BUG();
++			BUG_ON(cr_mcl[j].result != 1);
++			while (j--)
++				BUG_ON(cr_mcl[j].result != 0);
++
++			balloon_unlock(flags);
++
++			free_empty_pages(&page, 1);
++
++			in_frame++;
++			vstart += PAGE_SIZE;
++		}
++	}
+ }
+ EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
+ 
+--- head-2010-01-04.orig/drivers/xen/balloon/balloon.c	2010-01-04 13:32:27.000000000 +0100
++++ head-2010-01-04/drivers/xen/balloon/balloon.c	2010-01-04 13:32:50.000000000 +0100
+@@ -732,7 +732,10 @@ struct page **alloc_empty_pages_and_page
+ }
+ EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+ 
+-void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++#endif /* CONFIG_XEN_BACKEND */
++
++static void _free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages,
++					  int free_vec)
+ {
+ 	unsigned long flags;
+ 	int i;
+@@ -743,18 +746,31 @@ void free_empty_pages_and_pagevec(struct
+ 	balloon_lock(flags);
+ 	for (i = 0; i < nr_pages; i++) {
+ 		BUG_ON(page_count(pagevec[i]) != 1);
+-		balloon_append(pagevec[i], 0);
++		balloon_append(pagevec[i], !free_vec);
+ 	}
++	if (!free_vec)
++		totalram_pages = bs.current_pages -= nr_pages;
+ 	balloon_unlock(flags);
+ 
+-	kfree(pagevec);
++	if (free_vec)
++		kfree(pagevec);
+ 
+ 	schedule_work(&balloon_worker);
+ }
+-EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+ 
++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++{
++	_free_empty_pages_and_pagevec(pagevec, nr_pages, 1);
++}
++EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+ #endif /* CONFIG_XEN_BACKEND */
+ 
++void free_empty_pages(struct page **pagevec, int nr_pages)
++{
++	_free_empty_pages_and_pagevec(pagevec, nr_pages, 0);
++}
++
+ void balloon_release_driver_page(struct page *page)
+ {
+ 	unsigned long flags;
+--- head-2010-01-04.orig/include/xen/balloon.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-04/include/xen/balloon.h	2009-06-09 15:52:17.000000000 +0200
+@@ -47,6 +47,10 @@ void balloon_update_driver_allowance(lon
+ struct page **alloc_empty_pages_and_pagevec(int nr_pages);
+ void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
+ 
++/* Free an empty page range (not allocated through
++   alloc_empty_pages_and_pagevec), adding to the balloon. */
++void free_empty_pages(struct page **pagevec, int nr_pages);
++
+ void balloon_release_driver_page(struct page *page);
+ 
+ /*
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.19
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.19
@@ -0,0 +1,12680 @@
+From: www.kernel.org
+Subject: Linux 2.6.19
+Patch-mainline: 2.6.19
+
+Automatically created from "patches.kernel.org/patch-2.6.19" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 10:59:38.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-06 10:45:48.000000000 +0100
+@@ -510,6 +510,7 @@ config SCHED_OMIT_FRAME_POINTER
+ 
+ menuconfig PARAVIRT_GUEST
+ 	bool "Paravirtualized guest support"
++	depends on !XEN
+ 	---help---
+ 	  Say Y here to get to see options related to running Linux under
+ 	  various hypervisors.  This option alone does not add any kernel code.
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/boot.c	2010-01-19 10:36:52.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/boot.c	2009-11-06 10:45:48.000000000 +0100
+@@ -68,8 +68,12 @@ int acpi_strict;
+ 
+ u8 acpi_sci_flags __initdata;
+ int acpi_sci_override_gsi __initdata;
++#ifndef CONFIG_XEN
+ int acpi_skip_timer_override __initdata;
+ int acpi_use_timer_override __initdata;
++#else
++#define acpi_skip_timer_override 0
++#endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+@@ -1738,7 +1742,7 @@ int __init acpi_mps_check(void)
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_X86_IO_APIC
++#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_XEN)
+ static int __init parse_acpi_skip_timer_override(char *arg)
+ {
+ 	acpi_skip_timer_override = 1;
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2007-06-12 13:12:48.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -54,7 +54,6 @@ static cpumask_t timer_bcast_ipi;
+ /*
+  * Knob to control our willingness to enable the local APIC.
+  */
+-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+ 
+ /*
+  * Debug level
+@@ -102,7 +101,7 @@ int get_physical_broadcast(void)
+ 
+ #ifndef CONFIG_XEN
+ #ifndef CONFIG_SMP
+-static void up_apic_timer_interrupt_call(struct pt_regs *regs)
++static void up_apic_timer_interrupt_call(void)
+ {
+ 	int cpu = smp_processor_id();
+ 
+@@ -111,11 +110,11 @@ static void up_apic_timer_interrupt_call
+ 	 */
+ 	per_cpu(irq_stat, cpu).apic_timer_irqs++;
+ 
+-	smp_local_timer_interrupt(regs);
++	smp_local_timer_interrupt();
+ }
+ #endif
+ 
+-void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
++void smp_send_timer_broadcast_ipi(void)
+ {
+ 	cpumask_t mask;
+ 
+@@ -128,7 +127,7 @@ void smp_send_timer_broadcast_ipi(struct
+ 		 * We can directly call the apic timer interrupt handler
+ 		 * in UP case. Minus all irq related functions
+ 		 */
+-		up_apic_timer_interrupt_call(regs);
++		up_apic_timer_interrupt_call();
+ #endif
+ 	}
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-05-19 09:16:41.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -43,7 +43,7 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM
+ 
+ extern int disable_pse;
+ 
+-static void default_init(struct cpuinfo_x86 * c)
++static void __cpuinit default_init(struct cpuinfo_x86 * c)
+ {
+ 	/* Not much we can do here... */
+ 	/* Check if at least it has cpuid */
+@@ -56,7 +56,7 @@ static void default_init(struct cpuinfo_
+ 	}
+ }
+ 
+-static struct cpu_dev default_cpu = {
++static struct cpu_dev __cpuinitdata default_cpu = {
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
+ };
+@@ -191,7 +191,16 @@ static void __cpuinit get_cpu_vendor(str
+ 
+ static int __init x86_fxsr_setup(char * s)
+ {
++	/* Tell all the other CPU's to not use it... */
+ 	disable_x86_fxsr = 1;
++
++	/*
++	 * ... and clear the bits early in the boot_cpu_data
++	 * so that the bootup process doesn't try to do this
++	 * either.
++	 */
++	clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability);
++	clear_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability);
+ 	return 1;
+ }
+ __setup("nofxsr", x86_fxsr_setup);
+@@ -272,7 +281,7 @@ static void __init early_cpu_detect(void
+ 	}
+ }
+ 
+-void __cpuinit generic_identify(struct cpuinfo_x86 * c)
++static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ {
+ 	u32 tfms, xlvl;
+ 	int ebx;
+@@ -700,8 +709,7 @@ old_gdt:
+ 	 */
+ 	atomic_inc(&init_mm.mm_count);
+ 	current->active_mm = &init_mm;
+-	if (current->mm)
+-		BUG();
++	BUG_ON(current->mm);
+ 	enter_lazy_tlb(&init_mm, current);
+ 
+ 	load_esp0(t, thread);
+@@ -714,7 +722,7 @@ old_gdt:
+ #endif
+ 
+ 	/* Clear %fs and %gs. */
+-	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
++	asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
+ 
+ 	/* Clear all 6 debug registers: */
+ 	set_debugreg(0, 0);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mcheck/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mcheck/Makefile	2009-11-06 10:45:48.000000000 +0100
+@@ -8,3 +8,5 @@ obj-$(CONFIG_X86_MCE_THRESHOLD) += thres
+ obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
+ 
+ obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
++
++disabled-obj-$(CONFIG_XEN)	:= therm_throt.o
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mcheck/mce_dom0.c	2009-10-01 11:00:47.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/cpu/mcheck/mce_dom0.c	2009-11-06 10:45:48.000000000 +0100
+@@ -53,8 +53,7 @@ static struct mc_info *g_mi;
+ 
+ /*dom0 mce virq handler, logging physical mce error info*/
+ 
+-static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id,
+-									struct pt_regs *regs)
++static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id)
+ {
+ 	xen_mc_t mc_op;
+ 	int result = 0;
+@@ -129,6 +128,6 @@ void bind_virq_for_mce(void)
+ 		printk(KERN_ERR "MCE_DOM0_LOG: bind_virq for DOM0 failed\n");
+ 
+ 	/* Log the machine checks left over from the previous reset. */
+-	mce_dom0_interrupt(VIRQ_MCA, NULL, NULL);
++	mce_dom0_interrupt(VIRQ_MCA, NULL);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-05-19 09:16:41.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:45:48.000000000 +0100
+@@ -80,8 +80,12 @@ VM_MASK		= 0x00020000
+ NMI_MASK	= 0x80000000
+ 
+ #ifndef CONFIG_XEN
+-#define DISABLE_INTERRUPTS	cli
+-#define ENABLE_INTERRUPTS	sti
++/* These are replaces for paravirtualization */
++#define DISABLE_INTERRUPTS		cli
++#define ENABLE_INTERRUPTS		sti
++#define ENABLE_INTERRUPTS_SYSEXIT	sti; sysexit
++#define INTERRUPT_RETURN		iret
++#define GET_CR0_INTO_EAX		movl %cr0, %eax
+ #else
+ /* Offsets into shared_info_t. */
+ #define evtchn_upcall_pending		/* 0 */
+@@ -99,15 +103,29 @@ NMI_MASK	= 0x80000000
+ 
+ #define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(%esi)
+ #define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(%esi)
++#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
+ #define DISABLE_INTERRUPTS	GET_VCPU_INFO				; \
+ 				__DISABLE_INTERRUPTS
+ #define ENABLE_INTERRUPTS	GET_VCPU_INFO				; \
+ 				__ENABLE_INTERRUPTS
+-#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
++#define ENABLE_INTERRUPTS_SYSEXIT __ENABLE_INTERRUPTS			; \
++sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
++	__TEST_PENDING							; \
++	jnz  14f		# process more events if necessary...	; \
++	movl ESI(%esp), %esi						; \
++	sysexit								; \
++14:	__DISABLE_INTERRUPTS						; \
++	TRACE_IRQS_OFF							; \
++sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
++	push %esp							; \
++	call evtchn_do_upcall						; \
++	add  $4,%esp							; \
++	jmp  ret_from_intr
++#define INTERRUPT_RETURN	iret
+ #endif
+ 
+ #ifdef CONFIG_PREEMPT
+-#define preempt_stop		cli; TRACE_IRQS_OFF
++#define preempt_stop		DISABLE_INTERRUPTS; TRACE_IRQS_OFF
+ #else
+ #define preempt_stop
+ #define resume_kernel		restore_nocheck
+@@ -206,18 +224,21 @@ NMI_MASK	= 0x80000000
+ 
+ #define RING0_INT_FRAME \
+ 	CFI_STARTPROC simple;\
++	CFI_SIGNAL_FRAME;\
+ 	CFI_DEF_CFA esp, 3*4;\
+ 	/*CFI_OFFSET cs, -2*4;*/\
+ 	CFI_OFFSET eip, -3*4
+ 
+ #define RING0_EC_FRAME \
+ 	CFI_STARTPROC simple;\
++	CFI_SIGNAL_FRAME;\
+ 	CFI_DEF_CFA esp, 4*4;\
+ 	/*CFI_OFFSET cs, -2*4;*/\
+ 	CFI_OFFSET eip, -3*4
+ 
+ #define RING0_PTREGS_FRAME \
+ 	CFI_STARTPROC simple;\
++	CFI_SIGNAL_FRAME;\
+ 	CFI_DEF_CFA esp, OLDESP-EBX;\
+ 	/*CFI_OFFSET cs, CS-OLDESP;*/\
+ 	CFI_OFFSET eip, EIP-OLDESP;\
+@@ -263,8 +284,9 @@ ret_from_intr:
+ check_userspace:
+ 	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
+ 	movb CS(%esp), %al
+-	testl $(VM_MASK | 2), %eax
+-	jz resume_kernel
++	andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
++	cmpl $USER_RPL, %eax
++	jb resume_kernel		# not returning to v8086 or userspace
+ ENTRY(resume_userspace)
+ 	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+@@ -277,7 +299,7 @@ ENTRY(resume_userspace)
+ 
+ #ifdef CONFIG_PREEMPT
+ ENTRY(resume_kernel)
+-	cli
++	DISABLE_INTERRUPTS
+ 	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+ 	jnz restore_nocheck
+ need_resched:
+@@ -297,6 +319,7 @@ need_resched:
+ 	# sysenter call handler stub
+ ENTRY(sysenter_entry)
+ 	CFI_STARTPROC simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA esp, 0
+ 	CFI_REGISTER esp, ebp
+ 	movl SYSENTER_stack_esp0(%esp),%esp
+@@ -305,7 +328,7 @@ sysenter_past_esp:
+ 	 * No need to follow this irqs on/off section: the syscall
+ 	 * disabled irqs and here we enable it straight after entry:
+ 	 */
+-	sti
++	ENABLE_INTERRUPTS
+ 	pushl $(__USER_DS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET ss, 0*/
+@@ -359,26 +382,8 @@ sysenter_past_esp:
+ 	movl EIP(%esp), %edx
+ 	movl OLDESP(%esp), %ecx
+ 	xorl %ebp,%ebp
+-#ifdef CONFIG_XEN
+ 	TRACE_IRQS_ON
+-	__ENABLE_INTERRUPTS
+-sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/
+-	__TEST_PENDING
+-	jnz  14f			# process more events if necessary...
+-	movl ESI(%esp), %esi
+-	sysexit
+-14:	__DISABLE_INTERRUPTS
+-	TRACE_IRQS_OFF
+-sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/
+-	push %esp
+-	call evtchn_do_upcall
+-	add  $4,%esp
+-	jmp  ret_from_intr
+-#else
+-	TRACE_IRQS_ON
+-	sti
+-	sysexit
+-#endif /* !CONFIG_XEN */
++	ENABLE_INTERRUPTS_SYSEXIT
+ 	CFI_ENDPROC
+ 
+ 	# pv sysenter call handler stub
+@@ -444,8 +449,8 @@ restore_all:
+ 	# See comments in process.c:copy_thread() for details.
+ 	movb OLDSS(%esp), %ah
+ 	movb CS(%esp), %al
+-	andl $(VM_MASK | (4 << 8) | 3), %eax
+-	cmpl $((4 << 8) | 3), %eax
++	andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
++	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+ 	CFI_REMEMBER_STATE
+ 	je ldt_ss			# returning to user-space with LDT SS
+ restore_nocheck:
+@@ -467,12 +472,11 @@ restore_nocheck_notrace:
+ 	RESTORE_REGS
+ 	addl $4, %esp
+ 	CFI_ADJUST_CFA_OFFSET -4
+-1:	iret
++1:	INTERRUPT_RETURN
+ .section .fixup,"ax"
+ iret_exc:
+ #ifndef CONFIG_XEN
+-	TRACE_IRQS_ON
+-	sti
++	ENABLE_INTERRUPTS
+ #endif
+ 	pushl $0			# no error code
+ 	pushl $do_iret_error
+@@ -498,7 +502,7 @@ ldt_ss:
+ 	 * dosemu and wine happy. */
+ 	subl $8, %esp		# reserve space for switch16 pointer
+ 	CFI_ADJUST_CFA_OFFSET 8
+-	cli
++	DISABLE_INTERRUPTS
+ 	TRACE_IRQS_OFF
+ 	movl %esp, %eax
+ 	/* Set up the 16bit stack frame with switch32 pointer on top,
+@@ -508,7 +512,7 @@ ldt_ss:
+ 	TRACE_IRQS_IRET
+ 	RESTORE_REGS
+ 	lss 20+4(%esp), %esp	# switch to 16bit stack
+-1:	iret
++1:	INTERRUPT_RETURN
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,iret_exc
+@@ -524,7 +528,7 @@ scrit:	/**** START OF CRITICAL REGION **
+ 	RESTORE_REGS
+ 	addl $4, %esp
+ 	CFI_ADJUST_CFA_OFFSET -4
+-1:	iret
++1:	INTERRUPT_RETURN
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,iret_exc
+@@ -713,11 +717,9 @@ ENTRY(name)				\
+ #define UNWIND_ESPFIX_STACK
+ #endif
+ 
+-ENTRY(divide_error)
+-	RING0_INT_FRAME
+-	pushl $0			# no error code
+-	CFI_ADJUST_CFA_OFFSET 4
+-	pushl $do_divide_error
++KPROBE_ENTRY(page_fault)
++	RING0_EC_FRAME
++	pushl $do_page_fault
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	ALIGN
+ error_code:
+@@ -767,6 +769,7 @@ error_code:
+ 	call *%edi
+ 	jmp ret_from_exception
+ 	CFI_ENDPROC
++KPROBE_END(page_fault)
+ 
+ #ifdef CONFIG_XEN
+ # A note on the "critical region" in our callback handler.
+@@ -790,9 +793,11 @@ ENTRY(hypervisor_callback)
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+-	testb $2,CS(%esp)
++	movl CS(%esp),%ecx
+ 	movl EIP(%esp),%eax
+-	jnz  .Ldo_upcall
++	andl $SEGMENT_RPL_MASK,%ecx
++	cmpl $USER_RPL,%ecx
++	jae  .Ldo_upcall
+ 	cmpl $scrit,%eax
+ 	jb   0f
+ 	cmpl $ecrit,%eax
+@@ -928,7 +933,7 @@ ENTRY(device_not_available)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ #ifndef CONFIG_XEN
+-	movl %cr0, %eax
++	GET_CR0_INTO_EAX
+ 	testl $0x4, %eax		# EM (math emulation bit)
+ 	je device_available_emulate
+ 	pushl $0			# temporary storage for ORIG_EIP
+@@ -963,9 +968,15 @@ device_available_emulate:
+ 	jne ok;					\
+ label:						\
+ 	movl SYSENTER_stack_esp0+offset(%esp),%esp;	\
++	CFI_DEF_CFA esp, 0;			\
++	CFI_UNDEFINED eip;			\
+ 	pushfl;					\
++	CFI_ADJUST_CFA_OFFSET 4;		\
+ 	pushl $__KERNEL_CS;			\
+-	pushl $sysenter_past_esp
++	CFI_ADJUST_CFA_OFFSET 4;		\
++	pushl $sysenter_past_esp;		\
++	CFI_ADJUST_CFA_OFFSET 4;		\
++	CFI_REL_OFFSET eip, 0
+ #endif /* CONFIG_XEN */
+ 
+ KPROBE_ENTRY(debug)
+@@ -984,7 +995,8 @@ debug_stack_correct:
+ 	call do_debug
+ 	jmp ret_from_exception
+ 	CFI_ENDPROC
+-	.previous .text
++KPROBE_END(debug)
++
+ #ifndef CONFIG_XEN
+ /*
+  * NMI is doubly nasty. It can happen _while_ we're handling
+@@ -994,7 +1006,7 @@ debug_stack_correct:
+  * check whether we got an NMI on the debug path where the debug
+  * fault happened on the sysenter path.
+  */
+-ENTRY(nmi)
++KPROBE_ENTRY(nmi)
+ 	RING0_INT_FRAME
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+@@ -1019,6 +1031,7 @@ ENTRY(nmi)
+ 	cmpl $sysenter_entry,12(%esp)
+ 	je nmi_debug_stack_check
+ nmi_stack_correct:
++	/* We have a RING0_INT_FRAME here */
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+@@ -1029,9 +1042,12 @@ nmi_stack_correct:
+ 	CFI_ENDPROC
+ 
+ nmi_stack_fixup:
++	RING0_INT_FRAME
+ 	FIX_STACK(12,nmi_stack_correct, 1)
+ 	jmp nmi_stack_correct
++
+ nmi_debug_stack_check:
++	/* We have a RING0_INT_FRAME here */
+ 	cmpw $__KERNEL_CS,16(%esp)
+ 	jne nmi_stack_correct
+ 	cmpl $debug,(%esp)
+@@ -1042,8 +1058,10 @@ nmi_debug_stack_check:
+ 	jmp nmi_stack_correct
+ 
+ nmi_16bit_stack:
+-	RING0_INT_FRAME
+-	/* create the pointer to lss back */
++	/* We have a RING0_INT_FRAME here.
++	 *
++	 * create the pointer to lss back
++	 */
+ 	pushl %ss
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl %esp
+@@ -1064,14 +1082,14 @@ nmi_16bit_stack:
+ 	call do_nmi
+ 	RESTORE_REGS
+ 	lss 12+4(%esp), %esp		# back to 16bit stack
+-1:	iret
++1:	INTERRUPT_RETURN
+ 	CFI_ENDPROC
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,iret_exc
+ .previous
+ #else
+-ENTRY(nmi)
++KPROBE_ENTRY(nmi)
+ 	RING0_INT_FRAME
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+@@ -1083,6 +1101,7 @@ ENTRY(nmi)
+ 	jmp restore_all
+ 	CFI_ENDPROC
+ #endif
++KPROBE_END(nmi)
+ 
+ KPROBE_ENTRY(int3)
+ 	RING0_INT_FRAME
+@@ -1094,7 +1113,7 @@ KPROBE_ENTRY(int3)
+ 	call do_int3
+ 	jmp ret_from_exception
+ 	CFI_ENDPROC
+-	.previous .text
++KPROBE_END(int3)
+ 
+ ENTRY(overflow)
+ 	RING0_INT_FRAME
+@@ -1159,7 +1178,7 @@ KPROBE_ENTRY(general_protection)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
+-	.previous .text
++KPROBE_END(general_protection)
+ 
+ ENTRY(alignment_check)
+ 	RING0_EC_FRAME
+@@ -1168,13 +1187,14 @@ ENTRY(alignment_check)
+ 	jmp error_code
+ 	CFI_ENDPROC
+ 
+-KPROBE_ENTRY(page_fault)
+-	RING0_EC_FRAME
+-	pushl $do_page_fault
++ENTRY(divide_error)
++	RING0_INT_FRAME
++	pushl $0			# no error code
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl $do_divide_error
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
+-	.previous .text
+ 
+ #ifdef CONFIG_X86_MCE
+ ENTRY(machine_check)
+@@ -1236,6 +1256,19 @@ ENTRY(fixup_4gb_segment)
+ 	jmp error_code
+ 	CFI_ENDPROC
+ 
++ENTRY(kernel_thread_helper)
++	pushl $0		# fake return address for unwinder
++	CFI_STARTPROC
++	movl %edx,%eax
++	push %edx
++	CFI_ADJUST_CFA_OFFSET 4
++	call *%ebx
++	push %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	call do_exit
++	CFI_ENDPROC
++ENDPROC(kernel_thread_helper)
++
+ .section .rodata,"a"
+ #include "syscall_table.S"
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2007-06-12 13:12:48.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:45:48.000000000 +0100
+@@ -62,7 +62,7 @@ ENTRY(startup_32)
+ 	movl %eax,%gs
+ 	cld			# gcc2 wants the direction flag cleared at all times
+ 
+-	pushl %eax		# fake return address
++	pushl $0		# fake return address for unwinder
+ 	jmp start_kernel
+ 
+ #define HYPERCALL_PAGE_OFFSET 0x1000
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -31,6 +31,9 @@
+ #include <linux/acpi.h>
+ #include <linux/module.h>
+ #include <linux/sysdev.h>
++#include <linux/pci.h>
++#include <linux/msi.h>
++#include <linux/htirq.h>
+ 
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -38,13 +41,15 @@
+ #include <asm/timer.h>
+ #include <asm/i8259.h>
+ #include <asm/nmi.h>
++#include <asm/msidef.h>
++#include <asm/hypertransport.h>
+ 
+ #include <mach_apic.h>
++#include <mach_apicdef.h>
+ 
+ #include "io_ports.h"
+ 
+ #ifdef CONFIG_XEN
+-
+ #include <xen/interface/xen.h>
+ #include <xen/interface/physdev.h>
+ #include <xen/evtchn.h>
+@@ -56,32 +61,7 @@
+ 
+ unsigned long io_apic_irqs;
+ 
+-static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
+-{
+-	struct physdev_apic apic_op;
+-	int ret;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+-	apic_op.reg = reg;
+-	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+-	if (ret)
+-		return ret;
+-	return apic_op.value;
+-}
+-
+-static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+-{
+-	struct physdev_apic apic_op;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+-	apic_op.reg = reg;
+-	apic_op.value = value;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+-}
+-
+-#define io_apic_read(a,r)    xen_io_apic_read(a,r)
+-#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
+-
++#define clear_IO_APIC() ((void)0)
+ #endif /* CONFIG_XEN */
+ 
+ int (*ioapic_renumber_irq)(int ioapic, int irq);
+@@ -108,7 +88,7 @@ int sis_apic_bug = -1;
+  */
+ int nr_ioapic_registers[MAX_IO_APICS];
+ 
+-int disable_timer_pin_1 __initdata;
++static int disable_timer_pin_1 __initdata;
+ 
+ /*
+  * Rough estimation of how many shared IRQs there are, can
+@@ -128,12 +108,124 @@ static struct irq_pin_list {
+ 	int apic, pin, next;
+ } irq_2_pin[PIN_MAP_SIZE];
+ 
+-int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
+-#ifdef CONFIG_PCI_MSI
+-#define vector_to_irq(vector) 	\
+-	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
++#ifndef CONFIG_XEN
++struct io_apic {
++	unsigned int index;
++	unsigned int unused[3];
++	unsigned int data;
++};
++
++static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
++{
++	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
++		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
++}
++#endif
++
++static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
++{
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	return readl(&io_apic->data);
++#else
++	struct physdev_apic apic_op;
++	int ret;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
++	if (ret)
++		return ret;
++	return apic_op.value;
++#endif
++}
++
++static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
++{
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	writel(value, &io_apic->data);
++#else
++	struct physdev_apic apic_op;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
++	apic_op.reg = reg;
++	apic_op.value = value;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
++#endif
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Re-write a value: to be used for read-modify-write
++ * cycles where the read already set up the index register.
++ *
++ * Older SiS APIC requires we rewrite the index register
++ */
++static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
++{
++	volatile struct io_apic *io_apic = io_apic_base(apic);
++	if (sis_apic_bug)
++		writel(reg, &io_apic->index);
++	writel(value, &io_apic->data);
++}
+ #else
+-#define vector_to_irq(vector)	(vector)
++#define io_apic_modify io_apic_write
++#endif
++
++union entry_union {
++	struct { u32 w1, w2; };
++	struct IO_APIC_route_entry entry;
++};
++
++#ifndef CONFIG_XEN
++static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
++{
++	union entry_union eu;
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
++	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	return eu.entry;
++}
++#endif
++
++/*
++ * When we write a new IO APIC routing entry, we need to write the high
++ * word first! If the mask bit in the low word is clear, we will enable
++ * the interrupt, and we need to make sure the entry is fully populated
++ * before that happens.
++ */
++static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	unsigned long flags;
++	union entry_union eu;
++	eu.entry = e;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#ifndef CONFIG_XEN
++/*
++ * When we mask an IO APIC routing entry, we need to write the low
++ * word first, in order to set the mask bit before we change the
++ * high bits!
++ */
++static void ioapic_mask_entry(int apic, int pin)
++{
++	unsigned long flags;
++	union entry_union eu = { .entry.mask = 1 };
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
+ #endif
+ 
+ /*
+@@ -159,9 +251,7 @@ static void add_pin_to_irq(unsigned int 
+ 	entry->pin = pin;
+ }
+ 
+-#ifdef CONFIG_XEN
+-#define clear_IO_APIC() ((void)0)
+-#else
++#ifndef CONFIG_XEN
+ /*
+  * Reroute an IRQ to a different pin.
+  */
+@@ -246,25 +336,16 @@ static void unmask_IO_APIC_irq (unsigned
+ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 	
+ 	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-	*(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	entry = ioapic_read_entry(apic, pin);
+ 	if (entry.delivery_mode == dest_SMI)
+ 		return;
+ 
+ 	/*
+ 	 * Disable it in the IO-APIC irq-routing table:
+ 	 */
+-	memset(&entry, 0, sizeof(entry));
+-	entry.mask = 1;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_mask_entry(apic, pin);
+ }
+ 
+ static void clear_IO_APIC (void)
+@@ -304,7 +385,7 @@ static void set_ioapic_affinity_irq(unsi
+ 			break;
+ 		entry = irq_2_pin + entry->next;
+ 	}
+-	set_irq_info(irq, cpumask);
++	set_native_irq_info(irq, cpumask);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+@@ -1212,43 +1293,43 @@ static inline int IO_APIC_irq_trigger(in
+ /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */
+ 
+-int assign_irq_vector(int irq)
++static int __assign_irq_vector(int irq)
+ {
+-	unsigned long flags;
+ 	int vector;
+ 	struct physdev_irq irq_op;
+ 
+-	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
++	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+ 
+ 	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+ 		return -EINVAL;
+ 
+-	spin_lock_irqsave(&vector_lock, flags);
+-
+-	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+-		spin_unlock_irqrestore(&vector_lock, flags);
+-		return IO_APIC_VECTOR(irq);
+-	}
++	if (irq_vector[irq] > 0)
++		return irq_vector[irq];
+ 
+ 	irq_op.irq = irq;
+-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+-		spin_unlock_irqrestore(&vector_lock, flags);
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+ 		return -ENOSPC;
+-	}
+ 
+ 	vector = irq_op.vector;
+-	vector_irq[vector] = irq;
+-	if (irq != AUTO_ASSIGN)
+-		IO_APIC_VECTOR(irq) = vector;
++	irq_vector[irq] = vector;
++
++	return vector;
++}
++
++static int assign_irq_vector(int irq)
++{
++	unsigned long flags;
++	int vector;
+ 
++	spin_lock_irqsave(&vector_lock, flags);
++	vector = __assign_irq_vector(irq);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return vector;
+ }
+ 
+ #ifndef CONFIG_XEN
+-static struct hw_interrupt_type ioapic_level_type;
+-static struct hw_interrupt_type ioapic_edge_type;
++static struct irq_chip ioapic_chip;
+ 
+ #define IOAPIC_AUTO	-1
+ #define IOAPIC_EDGE	0
+@@ -1256,16 +1337,16 @@ static struct hw_interrupt_type ioapic_e
+ 
+ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+ {
+-	unsigned idx;
+-
+-	idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
+-
+ 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ 			trigger == IOAPIC_LEVEL)
+-		irq_desc[idx].chip = &ioapic_level_type;
+-	else
+-		irq_desc[idx].chip = &ioapic_edge_type;
+-	set_intr_gate(vector, interrupt[idx]);
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					 handle_fasteoi_irq, "fasteoi");
++	else {
++		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					 handle_edge_irq, "edge");
++	}
++	set_intr_gate(vector, interrupt[irq]);
+ }
+ #else
+ #define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
+@@ -1336,9 +1417,8 @@ static void __init setup_IO_APIC_irqs(vo
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
++		ioapic_write_entry(apic, pin, entry);
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+-		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ 		set_native_irq_info(irq, TARGET_CPUS);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+@@ -1355,7 +1435,6 @@ static void __init setup_IO_APIC_irqs(vo
+ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+ 	memset(&entry,0,sizeof(entry));
+ 
+@@ -1380,15 +1459,13 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	 * The timer IRQ doesn't have to know that behind the
+ 	 * scene we have a 8259A-master in AEOI mode ...
+ 	 */
+-	irq_desc[0].chip = &ioapic_edge_type;
++	irq_desc[0].chip = &ioapic_chip;
++	set_irq_handler(0, handle_edge_irq);
+ 
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+ 	 */
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+-	io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry);
+ 
+ 	enable_8259A_irq(0);
+ }
+@@ -1498,10 +1575,7 @@ void __init print_IO_APIC(void)
+ 	for (i = 0; i <= reg_01.bits.entries; i++) {
+ 		struct IO_APIC_route_entry entry;
+ 
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
+-		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		entry = ioapic_read_entry(apic, i);
+ 
+ 		printk(KERN_DEBUG " %02x %03X %02X  ",
+ 			i,
+@@ -1521,17 +1595,12 @@ void __init print_IO_APIC(void)
+ 		);
+ 	}
+ 	}
+-	if (use_pci_vector())
+-		printk(KERN_INFO "Using vector-based indexing\n");
+ 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+ 	for (i = 0; i < NR_IRQS; i++) {
+ 		struct irq_pin_list *entry = irq_2_pin + i;
+ 		if (entry->pin < 0)
+ 			continue;
+- 		if (use_pci_vector() && !platform_legacy_irq(i))
+-			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
+-		else
+-			printk(KERN_DEBUG "IRQ%d ", i);
++		printk(KERN_DEBUG "IRQ%d ", i);
+ 		for (;;) {
+ 			printk("-> %d:%d", entry->apic, entry->pin);
+ 			if (!entry->next)
+@@ -1720,10 +1789,7 @@ static void __init enable_IO_APIC(void)
+ 		/* See if any of the pins is in ExtINT mode */
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ 			struct IO_APIC_route_entry entry;
+-			spin_lock_irqsave(&ioapic_lock, flags);
+-			*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-			*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-			spin_unlock_irqrestore(&ioapic_lock, flags);
++			entry = ioapic_read_entry(apic, pin);
+ 
+ 
+ 			/* If the interrupt line is enabled and in ExtInt mode
+@@ -1782,7 +1848,6 @@ void disable_IO_APIC(void)
+ 	 */
+ 	if (ioapic_i8259.pin != -1) {
+ 		struct IO_APIC_route_entry entry;
+-		unsigned long flags;
+ 
+ 		memset(&entry, 0, sizeof(entry));
+ 		entry.mask            = 0; /* Enabled */
+@@ -1799,12 +1864,7 @@ void disable_IO_APIC(void)
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+ 		 */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
+-			*(((int *)&entry)+1));
+-		io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
+-			*(((int *)&entry)+0));
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+ 	}
+ 	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+ #endif
+@@ -1971,6 +2031,8 @@ static int __init timer_irq_works(void)
+  */
+ 
+ /*
++ * Startup quirk:
++ *
+  * Starting up a edge-triggered IO-APIC interrupt is
+  * nasty - we need to make sure that we get the edge.
+  * If it is already asserted for some reason, we need
+@@ -1978,8 +2040,10 @@ static int __init timer_irq_works(void)
+  *
+  * This is not complete - we should be able to fake
+  * an edge even if it isn't on the 8259A...
++ *
++ * (We do this for level-triggered IRQs too - it cannot hurt.)
+  */
+-static unsigned int startup_edge_ioapic_irq(unsigned int irq)
++static unsigned int startup_ioapic_irq(unsigned int irq)
+ {
+ 	int was_pending = 0;
+ 	unsigned long flags;
+@@ -1996,47 +2060,18 @@ static unsigned int startup_edge_ioapic_
+ 	return was_pending;
+ }
+ 
+-/*
+- * Once we have recorded IRQ_PENDING already, we can mask the
+- * interrupt for real. This prevents IRQ storms from unhandled
+- * devices.
+- */
+-static void ack_edge_ioapic_irq(unsigned int irq)
+-{
+-	move_irq(irq);
+-	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
+-					== (IRQ_PENDING | IRQ_DISABLED))
+-		mask_IO_APIC_irq(irq);
+-	ack_APIC_irq();
+-}
+-
+-/*
+- * Level triggered interrupts can just be masked,
+- * and shutting down and starting up the interrupt
+- * is the same as enabling and disabling them -- except
+- * with a startup need to return a "was pending" value.
+- *
+- * Level triggered interrupts are special because we
+- * do not touch any IO-APIC register while handling
+- * them. We ack the APIC in the end-IRQ handler, not
+- * in the start-IRQ-handler. Protection against reentrance
+- * from the same interrupt is still provided, both by the
+- * generic IRQ layer and by the fact that an unacked local
+- * APIC does not accept IRQs.
+- */
+-static unsigned int startup_level_ioapic_irq (unsigned int irq)
++static void ack_ioapic_irq(unsigned int irq)
+ {
+-	unmask_IO_APIC_irq(irq);
+-
+-	return 0; /* don't check for pending */
++	move_native_irq(irq);
++	ack_APIC_irq();
+ }
+ 
+-static void end_level_ioapic_irq (unsigned int irq)
++static void ack_ioapic_quirk_irq(unsigned int irq)
+ {
+ 	unsigned long v;
+ 	int i;
+ 
+-	move_irq(irq);
++	move_native_irq(irq);
+ /*
+  * It appears there is an erratum which affects at least version 0x11
+  * of I/O APIC (that's the 82093AA and cores integrated into various
+@@ -2056,7 +2091,7 @@ static void end_level_ioapic_irq (unsign
+  * operation to prevent an edge-triggered interrupt escaping meanwhile.
+  * The idea is from Manfred Spraul.  --macro
+  */
+-	i = IO_APIC_VECTOR(irq);
++	i = irq_vector[irq];
+ 
+ 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+ 
+@@ -2071,104 +2106,24 @@ static void end_level_ioapic_irq (unsign
+ 	}
+ }
+ 
+-#ifdef CONFIG_PCI_MSI
+-static unsigned int startup_edge_ioapic_vector(unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	return startup_edge_ioapic_irq(irq);
+-}
+-
+-static void ack_edge_ioapic_vector(unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	move_native_irq(vector);
+-	ack_edge_ioapic_irq(irq);
+-}
+-
+-static unsigned int startup_level_ioapic_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	return startup_level_ioapic_irq (irq);
+-}
+-
+-static void end_level_ioapic_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	move_native_irq(vector);
+-	end_level_ioapic_irq(irq);
+-}
+-
+-static void mask_IO_APIC_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	mask_IO_APIC_irq(irq);
+-}
+-
+-static void unmask_IO_APIC_vector (unsigned int vector)
++static int ioapic_retrigger_irq(unsigned int irq)
+ {
+-	int irq = vector_to_irq(vector);
+-
+-	unmask_IO_APIC_irq(irq);
+-}
+-
+-#ifdef CONFIG_SMP
+-static void set_ioapic_affinity_vector (unsigned int vector,
+-					cpumask_t cpu_mask)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	set_native_irq_info(vector, cpu_mask);
+-	set_ioapic_affinity_irq(irq, cpu_mask);
+-}
+-#endif
+-#endif
+-
+-static int ioapic_retrigger(unsigned int irq)
+-{
+-	send_IPI_self(IO_APIC_VECTOR(irq));
++	send_IPI_self(irq_vector[irq]);
+ 
+ 	return 1;
+ }
+ 
+-/*
+- * Level and edge triggered IO-APIC interrupts need different handling,
+- * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+- * handled with the level-triggered descriptor, but that one has slightly
+- * more overhead. Level-triggered interrupts cannot be handled with the
+- * edge-triggered handler, without risking IRQ storms and other ugly
+- * races.
+- */
+-static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
+-	.typename 	= "IO-APIC-edge",
+-	.startup 	= startup_edge_ioapic,
+-	.shutdown 	= shutdown_edge_ioapic,
+-	.enable 	= enable_edge_ioapic,
+-	.disable 	= disable_edge_ioapic,
+-	.ack 		= ack_edge_ioapic,
+-	.end 		= end_edge_ioapic,
+-#ifdef CONFIG_SMP
+-	.set_affinity 	= set_ioapic_affinity,
+-#endif
+-	.retrigger	= ioapic_retrigger,
+-};
+-
+-static struct hw_interrupt_type ioapic_level_type __read_mostly = {
+-	.typename 	= "IO-APIC-level",
+-	.startup 	= startup_level_ioapic,
+-	.shutdown 	= shutdown_level_ioapic,
+-	.enable 	= enable_level_ioapic,
+-	.disable 	= disable_level_ioapic,
+-	.ack 		= mask_and_ack_level_ioapic,
+-	.end 		= end_level_ioapic,
++static struct irq_chip ioapic_chip __read_mostly = {
++	.name 		= "IO-APIC",
++	.startup 	= startup_ioapic_irq,
++	.mask	 	= mask_IO_APIC_irq,
++	.unmask	 	= unmask_IO_APIC_irq,
++	.ack 		= ack_ioapic_irq,
++	.eoi 		= ack_ioapic_quirk_irq,
+ #ifdef CONFIG_SMP
+-	.set_affinity 	= set_ioapic_affinity,
++	.set_affinity 	= set_ioapic_affinity_irq,
+ #endif
+-	.retrigger	= ioapic_retrigger,
++	.retrigger	= ioapic_retrigger_irq,
+ };
+ #endif /* !CONFIG_XEN */
+ 
+@@ -2189,12 +2144,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+ 		int tmp = irq;
+-		if (use_pci_vector()) {
+-			if (!platform_legacy_irq(tmp))
+-				if ((tmp = vector_to_irq(tmp)) == -1)
+-					continue;
+-		}
+-		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
++		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -2205,22 +2155,23 @@ static inline void init_IO_APIC_traps(vo
+ #ifndef CONFIG_XEN
+ 			else
+ 				/* Strange. Oh, well.. */
+-				irq_desc[irq].chip = &no_irq_type;
++				irq_desc[irq].chip = &no_irq_chip;
+ #endif
+ 		}
+ 	}
+ }
+ 
+ #ifndef CONFIG_XEN
+-static void enable_lapic_irq (unsigned int irq)
+-{
+-	unsigned long v;
++/*
++ * The local APIC irq-chip implementation:
++ */
+ 
+-	v = apic_read(APIC_LVT0);
+-	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
++static void ack_apic(unsigned int irq)
++{
++	ack_APIC_irq();
+ }
+ 
+-static void disable_lapic_irq (unsigned int irq)
++static void mask_lapic_irq (unsigned int irq)
+ {
+ 	unsigned long v;
+ 
+@@ -2228,21 +2179,19 @@ static void disable_lapic_irq (unsigned 
+ 	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+ }
+ 
+-static void ack_lapic_irq (unsigned int irq)
++static void unmask_lapic_irq (unsigned int irq)
+ {
+-	ack_APIC_irq();
+-}
++	unsigned long v;
+ 
+-static void end_lapic_irq (unsigned int i) { /* nothing */ }
++	v = apic_read(APIC_LVT0);
++	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
++}
+ 
+-static struct hw_interrupt_type lapic_irq_type __read_mostly = {
+-	.typename 	= "local-APIC-edge",
+-	.startup 	= NULL, /* startup_irq() not used for IRQ0 */
+-	.shutdown 	= NULL, /* shutdown_irq() not used for IRQ0 */
+-	.enable 	= enable_lapic_irq,
+-	.disable 	= disable_lapic_irq,
+-	.ack 		= ack_lapic_irq,
+-	.end 		= end_lapic_irq
++static struct irq_chip lapic_chip __read_mostly = {
++	.name		= "local-APIC-edge",
++	.mask		= mask_lapic_irq,
++	.unmask		= unmask_lapic_irq,
++	.eoi		= ack_apic,
+ };
+ 
+ static void setup_nmi (void)
+@@ -2275,17 +2224,13 @@ static inline void unlock_ExtINT_logic(v
+ 	int apic, pin, i;
+ 	struct IO_APIC_route_entry entry0, entry1;
+ 	unsigned char save_control, save_freq_select;
+-	unsigned long flags;
+ 
+ 	pin  = find_isa_irq_pin(8, mp_INT);
+ 	apic = find_isa_irq_apic(8, mp_INT);
+ 	if (pin == -1)
+ 		return;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	*(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-	*(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	entry0 = ioapic_read_entry(apic, pin);
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+ 	memset(&entry1, 0, sizeof(entry1));
+@@ -2298,10 +2243,7 @@ static inline void unlock_ExtINT_logic(v
+ 	entry1.trigger = 0;
+ 	entry1.vector = 0;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry1);
+ 
+ 	save_control = CMOS_READ(RTC_CONTROL);
+ 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+@@ -2320,10 +2262,7 @@ static inline void unlock_ExtINT_logic(v
+ 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+ 	clear_IO_APIC_pin(apic, pin);
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_write_entry(apic, pin, entry0);
+ }
+ 
+ int timer_uses_ioapic_pin_0;
+@@ -2423,7 +2362,8 @@ static inline void check_timer(void)
+ 	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
+ 
+ 	disable_8259A_irq(0);
+-	irq_desc[0].chip = &lapic_irq_type;
++	set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
++				      "fasteio");
+ 	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+@@ -2537,17 +2477,12 @@ static int ioapic_suspend(struct sys_dev
+ {
+ 	struct IO_APIC_route_entry *entry;
+ 	struct sysfs_ioapic_data *data;
+-	unsigned long flags;
+ 	int i;
+ 	
+ 	data = container_of(dev, struct sysfs_ioapic_data, dev);
+ 	entry = data->entry;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+-		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+-		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
++		entry[i] = ioapic_read_entry(dev->id, i);
+ 
+ 	return 0;
+ }
+@@ -2569,11 +2504,9 @@ static int ioapic_resume(struct sys_devi
+ 		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+ 		io_apic_write(dev->id, 0, reg_00.raw);
+ 	}
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+-		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+-		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+-	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
++		ioapic_write_entry(dev->id, i, entry[i]);
+ 
+ 	return 0;
+ }
+@@ -2619,8 +2552,240 @@ static int __init ioapic_init_sysfs(void
+ 
+ device_initcall(ioapic_init_sysfs);
+ 
++/*
++ * Dynamic irq allocate and deallocation
++ */
++int create_irq(void)
++{
++	/* Allocate an unused irq */
++	int irq, new, vector;
++	unsigned long flags;
++
++	irq = -ENOSPC;
++	spin_lock_irqsave(&vector_lock, flags);
++	for (new = (NR_IRQS - 1); new >= 0; new--) {
++		if (platform_legacy_irq(new))
++			continue;
++		if (irq_vector[new] != 0)
++			continue;
++		vector = __assign_irq_vector(new);
++		if (likely(vector > 0))
++			irq = new;
++		break;
++	}
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	if (irq >= 0) {
++		set_intr_gate(vector, interrupt[irq]);
++		dynamic_irq_init(irq);
++	}
++	return irq;
++}
++
++void destroy_irq(unsigned int irq)
++{
++	unsigned long flags;
++
++	dynamic_irq_cleanup(irq);
++
++	spin_lock_irqsave(&vector_lock, flags);
++	irq_vector[irq] = 0;
++	spin_unlock_irqrestore(&vector_lock, flags);
++}
++
+ #endif /* CONFIG_XEN */
+ 
++/*
++ * MSI mesage composition
++ */
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
++static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
++{
++	int vector;
++	unsigned dest;
++
++	vector = assign_irq_vector(irq);
++	if (vector >= 0) {
++		dest = cpu_mask_to_apicid(TARGET_CPUS);
++
++		msg->address_hi = MSI_ADDR_BASE_HI;
++		msg->address_lo =
++			MSI_ADDR_BASE_LO |
++			((INT_DEST_MODE == 0) ?
++				MSI_ADDR_DEST_MODE_PHYSICAL:
++				MSI_ADDR_DEST_MODE_LOGICAL) |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_ADDR_REDIRECTION_CPU:
++				MSI_ADDR_REDIRECTION_LOWPRI) |
++			MSI_ADDR_DEST_ID(dest);
++
++		msg->data =
++			MSI_DATA_TRIGGER_EDGE |
++			MSI_DATA_LEVEL_ASSERT |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_DATA_DELIVERY_FIXED:
++				MSI_DATA_DELIVERY_LOWPRI) |
++			MSI_DATA_VECTOR(vector);
++	}
++	return vector;
++}
++
++#ifdef CONFIG_SMP
++static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++	int vector;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	vector = assign_irq_vector(irq);
++	if (vector < 0)
++		return;
++
++	dest = cpu_mask_to_apicid(mask);
++
++	read_msi_msg(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++
++	write_msi_msg(irq, &msg);
++	set_native_irq_info(irq, mask);
++}
++#endif /* CONFIG_SMP */
++
++/*
++ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI or MSI-X Capability Structure.
++ */
++static struct irq_chip msi_chip = {
++	.name		= "PCI-MSI",
++	.unmask		= unmask_msi_irq,
++	.mask		= mask_msi_irq,
++	.ack		= ack_ioapic_irq,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_msi_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
++{
++	struct msi_msg msg;
++	int ret;
++	ret = msi_compose_msg(dev, irq, &msg);
++	if (ret < 0)
++		return ret;
++
++	write_msi_msg(irq, &msg);
++
++	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
++				      "edge");
++
++	return 0;
++}
++
++void arch_teardown_msi_irq(unsigned int irq)
++{
++	return;
++}
++
++#endif /* CONFIG_PCI_MSI */
++
++/*
++ * Hypertransport interrupt support
++ */
++#ifdef CONFIG_HT_IRQ
++
++#ifdef CONFIG_SMP
++
++static void target_ht_irq(unsigned int irq, unsigned int dest)
++{
++	struct ht_irq_msg msg;
++	fetch_ht_irq_msg(irq, &msg);
++
++	msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
++	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
++
++	msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
++	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
++
++	write_ht_irq_msg(irq, &msg);
++}
++
++static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	unsigned int dest;
++	cpumask_t tmp;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	cpus_and(mask, tmp, CPU_MASK_ALL);
++
++	dest = cpu_mask_to_apicid(mask);
++
++	target_ht_irq(irq, dest);
++	set_native_irq_info(irq, mask);
++}
++#endif
++
++static struct irq_chip ht_irq_chip = {
++	.name		= "PCI-HT",
++	.mask		= mask_ht_irq,
++	.unmask		= unmask_ht_irq,
++	.ack		= ack_ioapic_irq,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_ht_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
++{
++	int vector;
++
++	vector = assign_irq_vector(irq);
++	if (vector >= 0) {
++		struct ht_irq_msg msg;
++		unsigned dest;
++		cpumask_t tmp;
++
++		cpus_clear(tmp);
++		cpu_set(vector >> 8, tmp);
++		dest = cpu_mask_to_apicid(tmp);
++
++		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
++
++		msg.address_lo =
++			HT_IRQ_LOW_BASE |
++			HT_IRQ_LOW_DEST_ID(dest) |
++			HT_IRQ_LOW_VECTOR(vector) |
++			((INT_DEST_MODE == 0) ?
++				HT_IRQ_LOW_DM_PHYSICAL :
++				HT_IRQ_LOW_DM_LOGICAL) |
++			HT_IRQ_LOW_RQEOI_EDGE |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				HT_IRQ_LOW_MT_FIXED :
++				HT_IRQ_LOW_MT_ARBITRATED) |
++			HT_IRQ_LOW_IRQ_MASKED;
++
++		write_ht_irq_msg(irq, &msg);
++
++		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
++					      handle_edge_irq, "edge");
++	}
++	return vector;
++}
++#endif /* CONFIG_HT_IRQ */
++
+ /* --------------------------------------------------------------------------
+                           ACPI-based IOAPIC Configuration
+    -------------------------------------------------------------------------- */
+@@ -2774,13 +2939,34 @@ int io_apic_set_pci_routing (int ioapic,
+ 	if (!ioapic && (irq < 16))
+ 		disable_8259A_irq(irq);
+ 
++	ioapic_write_entry(ioapic, pin, entry);
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
+-	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+-	set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
++	set_native_irq_info(irq, TARGET_CPUS);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	return 0;
+ }
+ 
+ #endif /* CONFIG_ACPI */
++
++static int __init parse_disable_timer_pin_1(char *arg)
++{
++	disable_timer_pin_1 = 1;
++	return 0;
++}
++early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
++
++static int __init parse_enable_timer_pin_1(char *arg)
++{
++	disable_timer_pin_1 = -1;
++	return 0;
++}
++early_param("enable_timer_pin_1", parse_enable_timer_pin_1);
++
++static int __init parse_noapic(char *arg)
++{
++	/* disable IO-APIC */
++	disable_ioapic_setup();
++	return 0;
++}
++early_param("noapic", parse_noapic);
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -53,8 +53,10 @@ static union irq_ctx *softirq_ctx[NR_CPU
+  */
+ fastcall unsigned int do_IRQ(struct pt_regs *regs)
+ {	
++	struct pt_regs *old_regs;
+ 	/* high bit used in ret_from_ code */
+ 	int irq = ~regs->orig_eax;
++	struct irq_desc *desc = irq_desc + irq;
+ #ifdef CONFIG_4KSTACKS
+ 	union irq_ctx *curctx, *irqctx;
+ 	u32 *isp;
+@@ -66,6 +68,7 @@ fastcall unsigned int do_IRQ(struct pt_r
+ 		BUG();
+ 	}
+ 
++	old_regs = set_irq_regs(regs);
+ 	/*irq_enter();*/
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ 	/* Debugging check for stack overflow: is there less than 1KB free? */
+@@ -110,19 +113,20 @@ fastcall unsigned int do_IRQ(struct pt_r
+ 			(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+ 
+ 		asm volatile(
+-			"       xchgl   %%ebx,%%esp      \n"
+-			"       call    __do_IRQ         \n"
++			"       xchgl  %%ebx,%%esp      \n"
++			"       call   *%%edi           \n"
+ 			"       movl   %%ebx,%%esp      \n"
+ 			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
+-			:  "0" (irq),   "1" (regs),  "2" (isp)
+-			: "memory", "cc", "ecx"
++			:  "0" (irq),   "1" (desc),  "2" (isp),
++			   "D" (desc->handle_irq)
++			: "memory", "cc"
+ 		);
+ 	} else
+ #endif
+-		__do_IRQ(irq, regs);
++		desc->handle_irq(irq, desc);
+ 
+ 	/*irq_exit();*/
+-
++	set_irq_regs(old_regs);
+ 	return 1;
+ }
+ 
+@@ -253,7 +257,8 @@ int show_interrupts(struct seq_file *p, 
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ #endif
+-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
++		seq_printf(p, " %8s", irq_desc[i].chip->name);
++		seq_printf(p, "-%-8s", irq_desc[i].name);
+ 		seq_printf(p, "  %s", action->name);
+ 
+ 		for (action=action->next; action; action = action->next)
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_32-xen.c	2007-06-12 13:12:48.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * linux/kernel/ldt.c
++ * linux/arch/i386/kernel/ldt.c
+  *
+  * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2007-06-12 13:12:48.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -2,6 +2,7 @@
+  *	Intel CPU Microcode Update Driver for Linux
+  *
+  *	Copyright (C) 2000-2004 Tigran Aivazian
++ *		      2006	Shaohua Li <shaohua.li@intel.com>
+  *
+  *	This driver allows to upgrade microcode on Intel processors
+  *	belonging to IA-32 family - PentiumPro, Pentium II, 
+@@ -33,7 +34,9 @@
+ #include <linux/spinlock.h>
+ #include <linux/mm.h>
+ #include <linux/mutex.h>
+-#include <linux/syscalls.h>
++#include <linux/cpu.h>
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
+ 
+ #include <asm/msr.h>
+ #include <asm/uaccess.h>
+@@ -55,12 +58,7 @@ module_param(verbose, int, 0644);
+ /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+ static DEFINE_MUTEX(microcode_mutex);
+ 				
+-static int microcode_open (struct inode *unused1, struct file *unused2)
+-{
+-	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+-}
+-
+-
++#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+ static int do_microcode_update (const void __user *ubuf, size_t len)
+ {
+ 	int err;
+@@ -85,6 +83,11 @@ static int do_microcode_update (const vo
+ 	return err;
+ }
+ 
++static int microcode_open (struct inode *unused1, struct file *unused2)
++{
++	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
++}
++
+ static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
+ {
+ 	ssize_t ret;
+@@ -117,7 +120,7 @@ static struct miscdevice microcode_dev =
+ 	.fops		= &microcode_fops,
+ };
+ 
+-static int __init microcode_init (void)
++static int __init microcode_dev_init (void)
+ {
+ 	int error;
+ 
+@@ -129,6 +132,68 @@ static int __init microcode_init (void)
+ 		return error;
+ 	}
+ 
++	return 0;
++}
++
++static void __exit microcode_dev_exit (void)
++{
++	misc_deregister(&microcode_dev);
++}
++
++MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
++#else
++#define microcode_dev_init() 0
++#define microcode_dev_exit() do { } while(0)
++#endif
++
++/* fake device for request_firmware */
++static struct platform_device *microcode_pdev;
++
++static int request_microcode(void)
++{
++	char name[30];
++	const struct cpuinfo_x86 *c = &boot_cpu_data;
++	const struct firmware *firmware;
++	int error;
++	struct xen_platform_op op;
++
++	sprintf(name,"intel-ucode/%02x-%02x-%02x",
++		c->x86, c->x86_model, c->x86_mask);
++	error = request_firmware(&firmware, name, &microcode_pdev->dev);
++	if (error) {
++		pr_debug("ucode data file %s load failed\n", name);
++		return error;
++	}
++
++	op.cmd = XENPF_microcode_update;
++	set_xen_guest_handle(op.u.microcode.data, (void *)firmware->data);
++	op.u.microcode.length = firmware->size;
++	error = HYPERVISOR_platform_op(&op);
++
++	release_firmware(firmware);
++
++	if (error)
++		pr_debug("ucode load failed\n");
++
++	return error;
++}
++
++static int __init microcode_init (void)
++{
++	int error;
++
++	error = microcode_dev_init();
++	if (error)
++		return error;
++	microcode_pdev = platform_device_register_simple("microcode", -1,
++							 NULL, 0);
++	if (IS_ERR(microcode_pdev)) {
++		microcode_dev_exit();
++		return PTR_ERR(microcode_pdev);
++	}
++
++	request_microcode();
++
+ 	printk(KERN_INFO 
+ 		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
+ 	return 0;
+@@ -136,9 +201,9 @@ static int __init microcode_init (void)
+ 
+ static void __exit microcode_exit (void)
+ {
+-	misc_deregister(&microcode_dev);
++	microcode_dev_exit();
++	platform_device_unregister(microcode_pdev);
+ }
+ 
+ module_init(microcode_init)
+ module_exit(microcode_exit)
+-MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2007-06-12 13:12:48.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -30,6 +30,7 @@
+ #include <asm/io_apic.h>
+ 
+ #include <mach_apic.h>
++#include <mach_apicdef.h>
+ #include <mach_mpparse.h>
+ #include <bios_ebda.h>
+ 
+@@ -68,7 +69,7 @@ unsigned int def_to_bigsmp = 0;
+ /* Processor that is doing the boot up */
+ unsigned int boot_cpu_physical_apicid = -1U;
+ /* Internal processor count */
+-static unsigned int __devinitdata num_processors;
++unsigned int __cpuinitdata num_processors;
+ 
+ /* Bitmask of physically existing CPUs */
+ physid_mask_t phys_cpu_present_map;
+@@ -235,12 +236,14 @@ static void __init MP_bus_info (struct m
+ 
+ 	mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+ 
++#if MAX_MP_BUSSES < 256
+ 	if (m->mpc_busid >= MAX_MP_BUSSES) {
+ 		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ 			" is too large, max. supported is %d\n",
+ 			m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ 		return;
+ 	}
++#endif
+ 
+ 	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
+ 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+@@ -300,19 +303,6 @@ static void __init MP_lintsrc_info (stru
+ 			m->mpc_irqtype, m->mpc_irqflag & 3,
+ 			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+ 			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-	/*
+-	 * Well it seems all SMP boards in existence
+-	 * use ExtINT/LVT1 == LINT0 and
+-	 * NMI/LVT2 == LINT1 - the following check
+-	 * will show us if this assumptions is false.
+-	 * Until then we do not have to add baggage.
+-	 */
+-	if ((m->mpc_irqtype == mp_ExtINT) &&
+-		(m->mpc_destapiclint != 0))
+-			BUG();
+-	if ((m->mpc_irqtype == mp_NMI) &&
+-		(m->mpc_destapiclint != 1))
+-			BUG();
+ }
+ 
+ #ifdef CONFIG_X86_NUMAQ
+@@ -838,8 +828,7 @@ int es7000_plat;
+ 
+ #ifdef CONFIG_ACPI
+ 
+-void __init mp_register_lapic_address (
+-	u64			address)
++void __init mp_register_lapic_address(u64 address)
+ {
+ #ifndef CONFIG_XEN
+ 	mp_lapic_addr = (unsigned long) address;
+@@ -853,13 +842,10 @@ void __init mp_register_lapic_address (
+ #endif
+ }
+ 
+-
+-void __devinit mp_register_lapic (
+-	u8			id, 
+-	u8			enabled)
++void __devinit mp_register_lapic (u8 id, u8 enabled)
+ {
+ 	struct mpc_config_processor processor;
+-	int			boot_cpu = 0;
++	int boot_cpu = 0;
+ 	
+ 	if (MAX_APICS - id <= 0) {
+ 		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+@@ -898,11 +884,9 @@ static struct mp_ioapic_routing {
+ 	u32			pin_programmed[4];
+ } mp_ioapic_routing[MAX_IO_APICS];
+ 
+-
+-static int mp_find_ioapic (
+-	int			gsi)
++static int mp_find_ioapic (int gsi)
+ {
+-	int			i = 0;
++	int i = 0;
+ 
+ 	/* Find the IOAPIC that manages this GSI. */
+ 	for (i = 0; i < nr_ioapics; i++) {
+@@ -915,15 +899,11 @@ static int mp_find_ioapic (
+ 
+ 	return -1;
+ }
+-	
+ 
+-void __init mp_register_ioapic (
+-	u8			id, 
+-	u32			address,
+-	u32			gsi_base)
++void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+ {
+-	int			idx = 0;
+-	int			tmpid;
++	int idx = 0;
++	int tmpid;
+ 
+ 	if (nr_ioapics >= MAX_IO_APICS) {
+ 		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+@@ -971,16 +951,10 @@ void __init mp_register_ioapic (
+ 		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+ 		mp_ioapic_routing[idx].gsi_base,
+ 		mp_ioapic_routing[idx].gsi_end);
+-
+-	return;
+ }
+ 
+-
+-void __init mp_override_legacy_irq (
+-	u8			bus_irq,
+-	u8			polarity, 
+-	u8			trigger, 
+-	u32			gsi)
++void __init
++mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+ {
+ 	struct mpc_config_intsrc intsrc;
+ 	int			ioapic = -1;
+@@ -1018,15 +992,13 @@ void __init mp_override_legacy_irq (
+ 	mp_irqs[mp_irq_entries] = intsrc;
+ 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ 		panic("Max # of irq sources exceeded!\n");
+-
+-	return;
+ }
+ 
+ void __init mp_config_acpi_legacy_irqs (void)
+ {
+ 	struct mpc_config_intsrc intsrc;
+-	int			i = 0;
+-	int			ioapic = -1;
++	int i = 0;
++	int ioapic = -1;
+ 
+ 	/* 
+ 	 * Fabricate the legacy ISA bus (bus #31).
+@@ -1095,12 +1067,12 @@ void __init mp_config_acpi_legacy_irqs (
+ 
+ #define MAX_GSI_NUM	4096
+ 
+-int mp_register_gsi (u32 gsi, int triggering, int polarity)
++int mp_register_gsi(u32 gsi, int triggering, int polarity)
+ {
+-	int			ioapic = -1;
+-	int			ioapic_pin = 0;
+-	int			idx, bit = 0;
+-	static int		pci_irq = 16;
++	int ioapic = -1;
++	int ioapic_pin = 0;
++	int idx, bit = 0;
++	static int pci_irq = 16;
+ 	/*
+ 	 * Mapping between Global System Interrups, which
+ 	 * represent all possible interrupts, and IRQs
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:23:23.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -110,8 +110,7 @@ dma_map_sg(struct device *hwdev, struct 
+ {
+ 	int i, rc;
+ 
+-	if (direction == DMA_NONE)
+-		BUG();
++	BUG_ON(!valid_dma_direction(direction));
+ 	WARN_ON(nents == 0 || sg[0].length == 0);
+ 
+ 	if (swiotlb) {
+@@ -142,7 +141,7 @@ dma_unmap_sg(struct device *hwdev, struc
+ {
+ 	int i;
+ 
+-	BUG_ON(direction == DMA_NONE);
++	BUG_ON(!valid_dma_direction(direction));
+ 	if (swiotlb)
+ 		swiotlb_unmap_sg(hwdev, sg, nents, direction);
+ 	else {
+@@ -159,8 +158,7 @@ dma_map_page(struct device *dev, struct 
+ {
+ 	dma_addr_t dma_addr;
+ 
+-	BUG_ON(direction == DMA_NONE);
+-
++	BUG_ON(!valid_dma_direction(direction));
+ 	if (swiotlb) {
+ 		dma_addr = swiotlb_map_page(
+ 			dev, page, offset, size, direction);
+@@ -177,7 +175,7 @@ void
+ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ 	       enum dma_data_direction direction)
+ {
+-	BUG_ON(direction == DMA_NONE);
++	BUG_ON(!valid_dma_direction(direction));
+ 	if (swiotlb)
+ 		swiotlb_unmap_page(dev, dma_address, size, direction);
+ 	else
+@@ -356,8 +354,7 @@ dma_map_single(struct device *dev, void 
+ {
+ 	dma_addr_t dma;
+ 
+-	if (direction == DMA_NONE)
+-		BUG();
++	BUG_ON(!valid_dma_direction(direction));
+ 	WARN_ON(size == 0);
+ 
+ 	if (swiotlb) {
+@@ -378,8 +375,7 @@ void
+ dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ 		 enum dma_data_direction direction)
+ {
+-	if (direction == DMA_NONE)
+-		BUG();
++	BUG_ON(!valid_dma_direction(direction));
+ 	if (swiotlb)
+ 		swiotlb_unmap_single(dev, dma_addr, size, direction);
+ 	else
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2008-07-21 11:00:32.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include <linux/kallsyms.h>
+ #include <linux/ptrace.h>
+ #include <linux/random.h>
++#include <linux/personality.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -186,7 +187,7 @@ void cpu_idle(void)
+ void cpu_idle_wait(void)
+ {
+ 	unsigned int cpu, this_cpu = get_cpu();
+-	cpumask_t map;
++	cpumask_t map, tmp = current->cpus_allowed;
+ 
+ 	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ 	put_cpu();
+@@ -208,6 +209,8 @@ void cpu_idle_wait(void)
+ 		}
+ 		cpus_and(map, map, cpu_online_map);
+ 	} while (!cpus_empty(map));
++
++	set_cpus_allowed(current, tmp);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+@@ -240,9 +243,9 @@ void show_regs(struct pt_regs * regs)
+ 	if (user_mode_vm(regs))
+ 		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
+ 	printk(" EFLAGS: %08lx    %s  (%s %.*s)\n",
+-	       regs->eflags, print_tainted(), system_utsname.release,
+-	       (int)strcspn(system_utsname.version, " "),
+-	       system_utsname.version);
++	       regs->eflags, print_tainted(), init_utsname()->release,
++	       (int)strcspn(init_utsname()->version, " "),
++	       init_utsname()->version);
+ 	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+ 		regs->eax,regs->ebx,regs->ecx,regs->edx);
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+@@ -264,15 +267,6 @@ void show_regs(struct pt_regs * regs)
+  * the "args".
+  */
+ extern void kernel_thread_helper(void);
+-__asm__(".section .text\n"
+-	".align 4\n"
+-	"kernel_thread_helper:\n\t"
+-	"movl %edx,%eax\n\t"
+-	"pushl %edx\n\t"
+-	"call *%ebx\n\t"
+-	"pushl %eax\n\t"
+-	"call do_exit\n"
+-	".previous");
+ 
+ /*
+  * Create a kernel thread
+@@ -290,7 +284,7 @@ int kernel_thread(int (*fn)(void *), voi
+ 	regs.xes = __USER_DS;
+ 	regs.orig_eax = -1;
+ 	regs.eip = (unsigned long) kernel_thread_helper;
+-	regs.xcs = GET_KERNEL_CS();
++	regs.xcs = __KERNEL_CS | get_kernel_rpl();
+ 	regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
+ 
+ 	/* Ok, create the new process.. */
+@@ -369,13 +363,12 @@ int copy_thread(int nr, unsigned long cl
+ 
+ 	tsk = current;
+ 	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+-		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
++						IO_BITMAP_BYTES, GFP_KERNEL);
+ 		if (!p->thread.io_bitmap_ptr) {
+ 			p->thread.io_bitmap_max = 0;
+ 			return -ENOMEM;
+ 		}
+-		memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
+-			IO_BITMAP_BYTES);
+ 		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+ 	}
+ 
+@@ -871,7 +864,7 @@ asmlinkage int sys_get_thread_area(struc
+ 
+ unsigned long arch_align_stack(unsigned long sp)
+ {
+-	if (randomize_va_space)
++	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ 		sp -= get_random_int() % 8192;
+ 	return sp & ~0xf;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2008-04-22 15:41:51.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -56,6 +56,7 @@
+ #include <asm/apic.h>
+ #include <asm/e820.h>
+ #include <asm/mpspec.h>
++#include <asm/mmzone.h>
+ #include <asm/setup.h>
+ #include <asm/arch_hooks.h>
+ #include <asm/sections.h>
+@@ -83,9 +84,6 @@ static struct notifier_block xen_panic_b
+ 	xen_panic_event, NULL, 0 /* try to go last */
+ };
+ 
+-extern char hypercall_page[PAGE_SIZE];
+-EXPORT_SYMBOL(hypercall_page);
+-
+ int disable_pse __devinitdata = 0;
+ 
+ /*
+@@ -105,18 +103,6 @@ EXPORT_SYMBOL(boot_cpu_data);
+ 
+ unsigned long mmu_cr4_features;
+ 
+-#ifdef	CONFIG_ACPI
+-	int acpi_disabled = 0;
+-#else
+-	int acpi_disabled = 1;
+-#endif
+-EXPORT_SYMBOL(acpi_disabled);
+-
+-#ifdef	CONFIG_ACPI
+-int __initdata acpi_force = 0;
+-extern acpi_interrupt_flags	acpi_sci_flags;
+-#endif
+-
+ /* for MCA, but anyone else can use it if they want */
+ unsigned int machine_id;
+ #ifdef CONFIG_MCA
+@@ -170,7 +156,6 @@ struct e820map machine_e820;
+ #endif
+ 
+ extern void early_cpu_init(void);
+-extern void generic_apic_probe(char *);
+ extern int root_mountflags;
+ 
+ unsigned long saved_videomode;
+@@ -243,9 +228,6 @@ static struct resource adapter_rom_resou
+ 	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ } };
+ 
+-#define ADAPTER_ROM_RESOURCES \
+-	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
+-
+ static struct resource video_rom_resource = {
+ 	.name 	= "Video ROM",
+ 	.start	= 0xc0000,
+@@ -307,9 +289,6 @@ static struct resource standard_io_resou
+ 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+ } };
+ 
+-#define STANDARD_IO_RESOURCES \
+-	(sizeof standard_io_resources / sizeof standard_io_resources[0])
+-
+ #define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+ 
+ static int __init romchecksum(unsigned char *rom, unsigned long length)
+@@ -372,7 +351,7 @@ static void __init probe_roms(void)
+ 	}
+ 
+ 	/* check for adapter roms on 2k boundaries */
+-	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
++	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
+ 		rom = isa_bus_to_virt(start);
+ 		if (!romsignature(rom))
+ 			continue;
+@@ -779,246 +758,152 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
+-static void __init parse_cmdline_early (char ** cmdline_p)
++static int __initdata user_defined_memmap = 0;
++
++/*
++ * "mem=nopentium" disables the 4MB page tables.
++ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
++ * to <mem>, overriding the bios size.
++ * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
++ * <start> to <start>+<mem>, overriding the bios size.
++ *
++ * HPA tells me bootloaders need to parse mem=, so no new
++ * option should be mem=  [also see Documentation/i386/boot.txt]
++ */
++static int __init parse_mem(char *arg)
+ {
+-	char c = ' ', *to = command_line, *from = saved_command_line;
+-	int len = 0, max_cmdline;
+-	int userdef = 0;
+-
+-	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);
+-	/* Save unparsed command line copy for /proc/cmdline */
+-	saved_command_line[max_cmdline-1] = '\0';
+-
+-	for (;;) {
+-		if (c != ' ')
+-			goto next_char;
+-		/*
+-		 * "mem=nopentium" disables the 4MB page tables.
+-		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+-		 * to <mem>, overriding the bios size.
+-		 * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+-		 * <start> to <start>+<mem>, overriding the bios size.
+-		 *
+-		 * HPA tells me bootloaders need to parse mem=, so no new
+-		 * option should be mem=  [also see Documentation/i386/boot.txt]
+-		 */
+-		if (!memcmp(from, "mem=", 4)) {
+-			if (to != command_line)
+-				to--;
+-			if (!memcmp(from+4, "nopentium", 9)) {
+-				from += 9+4;
+-				clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+-				disable_pse = 1;
+-			} else {
+-				/* If the user specifies memory size, we
+-				 * limit the BIOS-provided memory map to
+-				 * that size. exactmap can be used to specify
+-				 * the exact map. mem=number can be used to
+-				 * trim the existing memory map.
+-				 */
+-				unsigned long long mem_size;
+- 
+-				mem_size = memparse(from+4, &from);
+-				limit_regions(mem_size);
+-				userdef=1;
+-			}
+-		}
++	if (!arg)
++		return -EINVAL;
+ 
+-		else if (!memcmp(from, "memmap=", 7)) {
+-			if (to != command_line)
+-				to--;
+-			if (!memcmp(from+7, "exactmap", 8)) {
+-#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.
+-				 */
+-				find_max_pfn();
+-				saved_max_pfn = max_pfn;
+-#endif
+-				from += 8+7;
+-				e820.nr_map = 0;
+-				userdef = 1;
+-			} else {
+-				/* If the user specifies memory size, we
+-				 * limit the BIOS-provided memory map to
+-				 * that size. exactmap can be used to specify
+-				 * the exact map. mem=number can be used to
+-				 * trim the existing memory map.
+-				 */
+-				unsigned long long start_at, mem_size;
++	if (strcmp(arg, "nopentium") == 0) {
++		clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
++		disable_pse = 1;
++	} else {
++		/* If the user specifies memory size, we
++		 * limit the BIOS-provided memory map to
++		 * that size. exactmap can be used to specify
++		 * the exact map. mem=number can be used to
++		 * trim the existing memory map.
++		 */
++		unsigned long long mem_size;
+  
+-				mem_size = memparse(from+7, &from);
+-				if (*from == '@') {
+-					start_at = memparse(from+1, &from);
+-					add_memory_region(start_at, mem_size, E820_RAM);
+-				} else if (*from == '#') {
+-					start_at = memparse(from+1, &from);
+-					add_memory_region(start_at, mem_size, E820_ACPI);
+-				} else if (*from == '$') {
+-					start_at = memparse(from+1, &from);
+-					add_memory_region(start_at, mem_size, E820_RESERVED);
+-				} else {
+-					limit_regions(mem_size);
+-					userdef=1;
+-				}
+-			}
+-		}
+-
+-		else if (!memcmp(from, "noexec=", 7))
+-			noexec_setup(from + 7);
++		mem_size = memparse(arg, &arg);
++		limit_regions(mem_size);
++		user_defined_memmap = 1;
++	}
++	return 0;
++}
++early_param("mem", parse_mem);
+ 
++static int __init parse_memmap(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
+ 
+-#ifdef  CONFIG_X86_MPPARSE
+-		/*
+-		 * If the BIOS enumerates physical processors before logical,
+-		 * maxcpus=N at enumeration-time can be used to disable HT.
++	if (strcmp(arg, "exactmap") == 0) {
++#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.
+ 		 */
+-		else if (!memcmp(from, "maxcpus=", 8)) {
+-			extern unsigned int maxcpus;
+-
+-			maxcpus = simple_strtoul(from + 8, NULL, 0);
+-		}
++		find_max_pfn();
++		saved_max_pfn = max_pfn;
+ #endif
++		e820.nr_map = 0;
++		user_defined_memmap = 1;
++	} else {
++		/* If the user specifies memory size, we
++		 * limit the BIOS-provided memory map to
++		 * that size. exactmap can be used to specify
++		 * the exact map. mem=number can be used to
++		 * trim the existing memory map.
++		 */
++		unsigned long long start_at, mem_size;
+ 
+-#ifdef CONFIG_ACPI
+-		/* "acpi=off" disables both ACPI table parsing and interpreter */
+-		else if (!memcmp(from, "acpi=off", 8)) {
+-			disable_acpi();
+-		}
+-
+-		/* acpi=force to over-ride black-list */
+-		else if (!memcmp(from, "acpi=force", 10)) {
+-			acpi_force = 1;
+-			acpi_ht = 1;
+-			acpi_disabled = 0;
+-		}
+-
+-		/* acpi=strict disables out-of-spec workarounds */
+-		else if (!memcmp(from, "acpi=strict", 11)) {
+-			acpi_strict = 1;
+-		}
+-
+-		/* Limit ACPI just to boot-time to enable HT */
+-		else if (!memcmp(from, "acpi=ht", 7)) {
+-			if (!acpi_force)
+-				disable_acpi();
+-			acpi_ht = 1;
+-		}
+-		
+-		/* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
+-		else if (!memcmp(from, "pci=noacpi", 10)) {
+-			acpi_disable_pci();
+-		}
+-		/* "acpi=noirq" disables ACPI interrupt routing */
+-		else if (!memcmp(from, "acpi=noirq", 10)) {
+-			acpi_noirq_set();
++		mem_size = memparse(arg, &arg);
++		if (*arg == '@') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_RAM);
++		} else if (*arg == '#') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_ACPI);
++		} else if (*arg == '$') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_RESERVED);
++		} else {
++			limit_regions(mem_size);
++			user_defined_memmap = 1;
+ 		}
++	}
++	return 0;
++}
++early_param("memmap", parse_memmap);
+ 
+-		else if (!memcmp(from, "acpi_sci=edge", 13))
+-			acpi_sci_flags.trigger =  1;
+-
+-		else if (!memcmp(from, "acpi_sci=level", 14))
+-			acpi_sci_flags.trigger = 3;
++#ifdef CONFIG_PROC_VMCORE
++/* elfcorehdr= specifies the location of elf core header
++ * stored by the crashed kernel.
++ */
++static int __init parse_elfcorehdr(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
+ 
+-		else if (!memcmp(from, "acpi_sci=high", 13))
+-			acpi_sci_flags.polarity = 1;
++	elfcorehdr_addr = memparse(arg, &arg);
++	return 0;
++}
++early_param("elfcorehdr", parse_elfcorehdr);
++#endif /* CONFIG_PROC_VMCORE */
+ 
+-		else if (!memcmp(from, "acpi_sci=low", 12))
+-			acpi_sci_flags.polarity = 3;
++/*
++ * highmem=size forces highmem to be exactly 'size' bytes.
++ * This works even on boxes that have no highmem otherwise.
++ * This also works to reduce highmem size on bigger boxes.
++ */
++static int __init parse_highmem(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
+ 
+-#ifdef CONFIG_X86_IO_APIC
+-		else if (!memcmp(from, "acpi_skip_timer_override", 24))
+-			acpi_skip_timer_override = 1;
++	highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
++	return 0;
++}
++early_param("highmem", parse_highmem);
+ 
+-		if (!memcmp(from, "disable_timer_pin_1", 19))
+-			disable_timer_pin_1 = 1;
+-		if (!memcmp(from, "enable_timer_pin_1", 18))
+-			disable_timer_pin_1 = -1;
+-
+-		/* disable IO-APIC */
+-		else if (!memcmp(from, "noapic", 6))
+-			disable_ioapic_setup();
+-#endif /* CONFIG_X86_IO_APIC */
+-#endif /* CONFIG_ACPI */
++/*
++ * vmalloc=size forces the vmalloc area to be exactly 'size'
++ * bytes. This can be used to increase (or decrease) the
++ * vmalloc area - the default is 128m.
++ */
++static int __init parse_vmalloc(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		/* enable local APIC */
+-		else if (!memcmp(from, "lapic", 5))
+-			lapic_enable();
+-
+-		/* disable local APIC */
+-		else if (!memcmp(from, "nolapic", 6))
+-			lapic_disable();
+-#endif /* CONFIG_X86_LOCAL_APIC */
++	__VMALLOC_RESERVE = memparse(arg, &arg);
++	return 0;
++}
++early_param("vmalloc", parse_vmalloc);
+ 
+-#ifdef CONFIG_KEXEC
+-		/* crashkernel=size@addr specifies the location to reserve for
+-		 * a crash kernel.  By reserving this memory we guarantee
+-		 * that linux never set's it up as a DMA target.
+-		 * Useful for holding code to do something appropriate
+-		 * after a kernel panic.
+-		 */
+-		else if (!memcmp(from, "crashkernel=", 12)) {
+ #ifndef CONFIG_XEN
+-			unsigned long size, base;
+-			size = memparse(from+12, &from);
+-			if (*from == '@') {
+-				base = memparse(from+1, &from);
+-				/* FIXME: Do I want a sanity check
+-				 * to validate the memory range?
+-				 */
+-				crashk_res.start = base;
+-				crashk_res.end   = base + size - 1;
+-			}
+-#else
+-			printk("Ignoring crashkernel command line, "
+-			       "parameter will be supplied by xen\n");
+-#endif
+-		}
+-#endif
+-#ifdef CONFIG_PROC_VMCORE
+-		/* elfcorehdr= specifies the location of elf core header
+-		 * stored by the crashed kernel.
+-		 */
+-		else if (!memcmp(from, "elfcorehdr=", 11))
+-			elfcorehdr_addr = memparse(from+11, &from);
+-#endif
++/*
++ * reservetop=size reserves a hole at the top of the kernel address space which
++ * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
++ * so relocating the fixmap can be done before paging initialization.
++ */
++static int __init parse_reservetop(char *arg)
++{
++	unsigned long address;
+ 
+-		/*
+-		 * highmem=size forces highmem to be exactly 'size' bytes.
+-		 * This works even on boxes that have no highmem otherwise.
+-		 * This also works to reduce highmem size on bigger boxes.
+-		 */
+-		else if (!memcmp(from, "highmem=", 8))
+-			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
+-	
+-		/*
+-		 * vmalloc=size forces the vmalloc area to be exactly 'size'
+-		 * bytes. This can be used to increase (or decrease) the
+-		 * vmalloc area - the default is 128m.
+-		 */
+-		else if (!memcmp(from, "vmalloc=", 8))
+-			__VMALLOC_RESERVE = memparse(from+8, &from);
++	if (!arg)
++		return -EINVAL;
+ 
+-	next_char:
+-		c = *(from++);
+-		if (!c)
+-			break;
+-		if (COMMAND_LINE_SIZE <= ++len)
+-			break;
+-		*(to++) = c;
+-	}
+-	*to = '\0';
+-	*cmdline_p = command_line;
+-	if (userdef) {
+-		printk(KERN_INFO "user-defined physical RAM map:\n");
+-		print_memory_map("user");
+-	}
++	address = memparse(arg, &arg);
++	reserve_top_address(address);
++	return 0;
+ }
++early_param("reservetop", parse_reservetop);
++#endif
+ 
+ /*
+  * Callback for efi_memory_walk.
+@@ -1039,7 +924,7 @@ efi_find_max_pfn(unsigned long start, un
+ static int __init
+ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
+ {
+-	memory_present(0, start, end);
++	memory_present(0, PFN_UP(start), PFN_DOWN(end));
+ 	return 0;
+ }
+ 
+@@ -1306,6 +1191,14 @@ static unsigned long __init setup_memory
+ 	}
+ 	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ 		pages_to_mb(highend_pfn - highstart_pfn));
++	num_physpages = highend_pfn;
++	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
++#else
++	num_physpages = max_low_pfn;
++	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
++#endif
++#ifdef CONFIG_FLATMEM
++	max_mapnr = num_physpages;
+ #endif
+ 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+ 			pages_to_mb(max_low_pfn));
+@@ -1317,22 +1210,21 @@ static unsigned long __init setup_memory
+ 
+ void __init zone_sizes_init(void)
+ {
+-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+-	unsigned int max_dma, low;
+-
+-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+-	low = max_low_pfn;
+-
+-	if (low < max_dma)
+-		zones_size[ZONE_DMA] = low;
+-	else {
+-		zones_size[ZONE_DMA] = max_dma;
+-		zones_size[ZONE_NORMAL] = low - max_dma;
++	unsigned long max_zone_pfns[MAX_NR_ZONES];
++	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
++	max_zone_pfns[ZONE_DMA] =
++		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
++	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+ #ifdef CONFIG_HIGHMEM
+-		zones_size[ZONE_HIGHMEM] = highend_pfn - low;
++	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
++	add_active_range(0, 0, min(xen_start_info->nr_pages, highend_pfn));
++	add_active_range(0, highend_pfn, highend_pfn);
++#else
++	add_active_range(0, 0, min(xen_start_info->nr_pages, max_low_pfn));
++	add_active_range(0, max_low_pfn, max_low_pfn);
+ #endif
+-	}
+-	free_area_init(zones_size);
++
++	free_area_init_nodes(max_zone_pfns);
+ }
+ #else
+ extern unsigned long __init setup_memory(void);
+@@ -1389,6 +1281,7 @@ void __init setup_bootmem_allocator(void
+ 	 */
+ 	acpi_reserve_bootmem();
+ #endif
++	numa_kva_reserve();
+ #endif /* !CONFIG_XEN */
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+@@ -1574,7 +1467,7 @@ static int __init request_standard_resou
+ 	request_resource(&iomem_resource, &video_ram_resource);
+ 
+ 	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
++	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+ 		request_resource(&ioport_resource, &standard_io_resources[i]);
+ 	return 0;
+ }
+@@ -1705,17 +1598,19 @@ void __init setup_arch(char **cmdline_p)
+ 	data_resource.start = virt_to_phys(_etext);
+ 	data_resource.end = virt_to_phys(_edata)-1;
+ 
+-	parse_cmdline_early(cmdline_p);
++	if ((i = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
++		i = COMMAND_LINE_SIZE;
++	memcpy(saved_command_line, xen_start_info->cmd_line, i);
++	saved_command_line[i - 1] = '\0';
++	parse_early_param();
+ 
+-#ifdef CONFIG_EARLY_PRINTK
+-	{
+-		char *s = strstr(*cmdline_p, "earlyprintk=");
+-		if (s) {
+-			setup_early_printk(strchr(s, '=') + 1);
+-			printk("early console enabled\n");
+-		}
++	if (user_defined_memmap) {
++		printk(KERN_INFO "user-defined physical RAM map:\n");
++		print_memory_map("user");
+ 	}
+-#endif
++
++	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
++	*cmdline_p = command_line;
+ 
+ 	max_low_pfn = setup_memory();
+ 
+@@ -1822,7 +1717,7 @@ void __init setup_arch(char **cmdline_p)
+ 		dmi_scan_machine();
+ 
+ #ifdef CONFIG_X86_GENERICARCH
+-	generic_apic_probe(*cmdline_p);
++	generic_apic_probe();
+ #endif	
+ 	if (efi_enabled)
+ 		efi_map_memmap();
+@@ -1843,9 +1738,11 @@ void __init setup_arch(char **cmdline_p)
+ 	acpi_boot_table_init();
+ #endif
+ 
++#ifdef CONFIG_PCI
+ #ifdef CONFIG_X86_IO_APIC
+ 	check_acpi_pci();	/* Checks more than just ACPI actually */
+ #endif
++#endif
+ 
+ #ifdef CONFIG_ACPI
+ 	acpi_boot_init();
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2007-12-10 08:47:31.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -279,8 +279,7 @@ static inline void leave_mm (unsigned lo
+  * 2) Leave the mm if we are in the lazy tlb mode.
+  */
+ 
+-irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id,
+-				     struct pt_regs *regs)
++irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id)
+ {
+ 	unsigned long cpu;
+ 
+@@ -567,16 +566,14 @@ void smp_send_stop(void)
+  * all the work is done automatically when
+  * we return from the interrupt.
+  */
+-irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id,
+-				     struct pt_regs *regs)
++irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+ {
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
+ #include <linux/kallsyms.h>
+-irqreturn_t smp_call_function_interrupt(int irq, void *dev_id,
+-					struct pt_regs *regs)
++irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
+ {
+ 	void (*func) (void *info) = call_data->func;
+ 	void *info = call_data->info;
+@@ -603,3 +600,69 @@ irqreturn_t smp_call_function_interrupt(
+ 	return IRQ_HANDLED;
+ }
+ 
++/*
++ * this function sends a 'generic call function' IPI to one other CPU
++ * in the system.
++ *
++ * cpu is a standard Linux logical CPU number.
++ */
++static void
++__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++				int nonatomic, int wait)
++{
++	struct call_data_struct data;
++	int cpus = 1;
++
++	data.func = func;
++	data.info = info;
++	atomic_set(&data.started, 0);
++	data.wait = wait;
++	if (wait)
++		atomic_set(&data.finished, 0);
++
++	call_data = &data;
++	wmb();
++	/* Send a message to all other CPUs and wait for them to respond */
++	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
++
++	/* Wait for response */
++	while (atomic_read(&data.started) != cpus)
++		cpu_relax();
++
++	if (!wait)
++		return;
++
++	while (atomic_read(&data.finished) != cpus)
++		cpu_relax();
++}
++
++/*
++ * smp_call_function_single - Run a function on another CPU
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @nonatomic: Currently unused.
++ * @wait: If true, wait until function has completed on other CPUs.
++ *
++ * Retrurns 0 on success, else a negative status code.
++ *
++ * Does not return until the remote CPU is nearly ready to execute <func>
++ * or is or has executed.
++ */
++
++int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
++			int nonatomic, int wait)
++{
++	/* prevent preemption and reschedule on another processor */
++	int me = get_cpu();
++	if (cpu == me) {
++		WARN_ON(1);
++		put_cpu();
++		return -EBUSY;
++	}
++	spin_lock_bh(&call_lock);
++	__smp_call_function_single(cpu, func, info, nonatomic, wait);
++	spin_unlock_bh(&call_lock);
++	put_cpu();
++	return 0;
++}
++EXPORT_SYMBOL(smp_call_function_single);
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -89,7 +89,6 @@ int pit_latch_buggy;              /* ext
+ unsigned long vxtime_hz = PIT_TICK_RATE;
+ struct vxtime_data __vxtime __section_vxtime;   /* for vsyscalls */
+ volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+-unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
+ struct timespec __xtime __section_xtime;
+ struct timezone __sys_tz __section_sys_tz;
+ #endif
+@@ -97,8 +96,6 @@ struct timezone __sys_tz __section_sys_t
+ unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
+ EXPORT_SYMBOL(cpu_khz);
+ 
+-extern unsigned long wall_jiffies;
+-
+ DEFINE_SPINLOCK(rtc_lock);
+ EXPORT_SYMBOL(rtc_lock);
+ 
+@@ -247,11 +244,10 @@ static void __update_wallclock(time_t se
+ 	time_t wtm_sec, xtime_sec;
+ 	u64 tmp, wc_nsec;
+ 
+-	/* Adjust wall-clock time base based on wall_jiffies ticks. */
++	/* Adjust wall-clock time base. */
+ 	wc_nsec = processed_system_time;
+ 	wc_nsec += sec * (u64)NSEC_PER_SEC;
+ 	wc_nsec += nsec;
+-	wc_nsec -= (jiffies - wall_jiffies) * (u64)NS_PER_TICK;
+ 
+ 	/* Split wallclock base into seconds and nanoseconds. */
+ 	tmp = wc_nsec;
+@@ -374,16 +370,10 @@ void do_gettimeofday(struct timeval *tv)
+ 	shadow = &per_cpu(shadow_time, cpu);
+ 
+ 	do {
+-		unsigned long lost;
+-
+ 		local_time_version = shadow->version;
+ 		seq = read_seqbegin(&xtime_lock);
+ 
+ 		usec = get_usec_offset(shadow);
+-		lost = jiffies - wall_jiffies;
+-
+-		if (unlikely(lost))
+-			usec += lost * (USEC_PER_SEC / HZ);
+ 
+ 		sec = xtime.tv_sec;
+ 		usec += (xtime.tv_nsec / NSEC_PER_USEC);
+@@ -510,7 +500,7 @@ static void sync_xen_wallclock(unsigned 
+ 	write_seqlock_irq(&xtime_lock);
+ 
+ 	sec  = xtime.tv_sec;
+-	nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK);
++	nsec = xtime.tv_nsec;
+ 	__normalize_time(&sec, &nsec);
+ 
+ 	op.cmd = XENPF_settime;
+@@ -584,42 +574,49 @@ unsigned long long sched_clock(void)
+ }
+ #endif
+ 
+-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+ 	unsigned long pc = instruction_pointer(regs);
+ 
+-#ifdef __x86_64__
+-	/* Assume the lock function has either no stack frame or only a single word.
+-	   This checks if the address on the stack looks like a kernel text address.
+-	   There is a small window for false hits, but in that case the tick
+-	   is just accounted to the spinlock function.
+-	   Better would be to write these functions in assembler again
+-	   and check exactly. */
++#if defined(CONFIG_SMP) || defined(__x86_64__)
+ 	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+-		char *v = *(char **)regs->rsp;
+-		if ((v >= _stext && v <= _etext) ||
+-			(v >= _sinittext && v <= _einittext) ||
+-			(v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
+-			return (unsigned long)v;
+-		return ((unsigned long *)regs->rsp)[1];
++# ifdef CONFIG_FRAME_POINTER
++#  ifdef __i386__
++		return ((unsigned long *)regs->ebp)[1];
++#  else
++		return ((unsigned long *)regs->rbp)[1];
++#  endif
++# else
++#  ifdef __i386__
++		unsigned long *sp;
++		if ((regs->xcs & 2) == 0)
++			sp = (unsigned long *)&regs->esp;
++		else
++			sp = (unsigned long *)regs->esp;
++#  else
++		unsigned long *sp = (unsigned long *)regs->rsp;
++#  endif
++		/* Return address is either directly at stack pointer
++		   or above a saved eflags. Eflags has bits 22-31 zero,
++		   kernel addresses don't. */
++ 		if (sp[0] >> 22)
++			return sp[0];
++		if (sp[1] >> 22)
++			return sp[1];
++# endif
+ 	}
+-#else
+-	if (!user_mode_vm(regs) && in_lock_functions(pc))
+-		return *(unsigned long *)(regs->ebp + 4);
+ #endif
+ 
+ 	return pc;
+ }
+ EXPORT_SYMBOL(profile_pc);
+-#endif
+ 
+ /*
+  * This is the same as the above, except we _also_ save the current
+  * Time Stamp Counter value at the time of the timer interrupt, so that
+  * we later on can estimate the time of day more exactly.
+  */
+-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t timer_interrupt(int irq, void *dev_id)
+ {
+ 	s64 delta, delta_cpu, stolen, blocked;
+ 	u64 sched_time;
+@@ -677,10 +674,15 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	}
+ 
+ 	/* System-wide jiffy work. */
+-	while (delta >= NS_PER_TICK) {
+-		delta -= NS_PER_TICK;
+-		processed_system_time += NS_PER_TICK;
+-		do_timer(regs);
++	if (delta >= NS_PER_TICK) {
++		do_div(delta, NS_PER_TICK);
++		processed_system_time += delta * NS_PER_TICK;
++		while (delta > HZ) {
++			clobber_induction_variable(delta);
++			do_timer(HZ);
++			delta -= HZ;
++		}
++		do_timer(delta);
+ 	}
+ 
+ 	if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
+@@ -725,7 +727,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	if (delta_cpu > 0) {
+ 		do_div(delta_cpu, NS_PER_TICK);
+ 		per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK;
+-		if (user_mode_vm(regs))
++		if (user_mode_vm(get_irq_regs()))
+ 			account_user_time(current, (cputime_t)delta_cpu);
+ 		else
+ 			account_system_time(current, HARDIRQ_OFFSET,
+@@ -739,10 +741,10 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	/* Local timer processing (see update_process_times()). */
+ 	run_local_timers();
+ 	if (rcu_pending(cpu))
+-		rcu_check_callbacks(cpu, user_mode_vm(regs));
++		rcu_check_callbacks(cpu, user_mode_vm(get_irq_regs()));
+ 	scheduler_tick();
+ 	run_posix_cpu_timers(current);
+-	profile_tick(CPU_PROFILING, regs);
++	profile_tick(CPU_PROFILING);
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -952,10 +954,11 @@ extern void (*late_time_init)(void);
+ /* Duplicate of time_init() below, with hpet_enable part added */
+ static void __init hpet_time_init(void)
+ {
+-	xtime.tv_sec = get_cmos_time();
+-	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+-	set_normalized_timespec(&wall_to_monotonic,
+-		-xtime.tv_sec, -xtime.tv_nsec);
++	struct timespec ts;
++	ts.tv_sec = get_cmos_time();
++	ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
++
++	do_settimeofday(&ts);
+ 
+ 	if ((hpet_enable() >= 0) && hpet_use_timer) {
+ 		printk("Using HPET for base-timer\n");
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -28,6 +28,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/kexec.h>
+ #include <linux/unwind.h>
++#include <linux/uaccess.h>
+ 
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -40,7 +41,6 @@
+ 
+ #include <asm/processor.h>
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+ #include <asm/debugreg.h>
+@@ -51,11 +51,14 @@
+ #include <asm/smp.h>
+ #include <asm/arch_hooks.h>
+ #include <asm/kdebug.h>
++#include <asm/stacktrace.h>
+ 
+ #include <linux/module.h>
+ 
+ #include "mach_traps.h"
+ 
++int panic_on_unrecovered_nmi;
++
+ asmlinkage int system_call(void);
+ 
+ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+@@ -124,62 +127,63 @@ static inline int valid_stack_ptr(struct
+ 		p < (void *)tinfo + THREAD_SIZE - 3;
+ }
+ 
+-/*
+- * Print one address/symbol entries per line.
+- */
+-static inline void print_addr_and_symbol(unsigned long addr, char *log_lvl)
+-{
+-	printk(" [<%08lx>] ", addr);
+-
+-	print_symbol("%s\n", addr);
+-}
+-
+ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ 				unsigned long *stack, unsigned long ebp,
+-				char *log_lvl)
++				struct stacktrace_ops *ops, void *data)
+ {
+ 	unsigned long addr;
+ 
+ #ifdef	CONFIG_FRAME_POINTER
+ 	while (valid_stack_ptr(tinfo, (void *)ebp)) {
++		unsigned long new_ebp;
+ 		addr = *(unsigned long *)(ebp + 4);
+-		print_addr_and_symbol(addr, log_lvl);
++		ops->address(data, addr);
+ 		/*
+ 		 * break out of recursive entries (such as
+-		 * end_of_stack_stop_unwind_function):
++		 * end_of_stack_stop_unwind_function). Also,
++		 * we can never allow a frame pointer to
++		 * move downwards!
+ 	 	 */
+-		if (ebp == *(unsigned long *)ebp)
++	 	new_ebp = *(unsigned long *)ebp;
++		if (new_ebp <= ebp)
+ 			break;
+-		ebp = *(unsigned long *)ebp;
++		ebp = new_ebp;
+ 	}
+ #else
+ 	while (valid_stack_ptr(tinfo, stack)) {
+ 		addr = *stack++;
+ 		if (__kernel_text_address(addr))
+-			print_addr_and_symbol(addr, log_lvl);
++			ops->address(data, addr);
+ 	}
+ #endif
+ 	return ebp;
+ }
+ 
++struct ops_and_data {
++	struct stacktrace_ops *ops;
++	void *data;
++};
++
+ static asmlinkage int
+-show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
++dump_trace_unwind(struct unwind_frame_info *info, void *data)
+ {
++	struct ops_and_data *oad = (struct ops_and_data *)data;
+ 	int n = 0;
+ 
+ 	while (unwind(info) == 0 && UNW_PC(info)) {
+ 		n++;
+-		print_addr_and_symbol(UNW_PC(info), log_lvl);
++		oad->ops->address(oad->data, UNW_PC(info));
+ 		if (arch_unw_user_mode(info))
+ 			break;
+ 	}
+ 	return n;
+ }
+ 
+-static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-			       unsigned long *stack, char *log_lvl)
++void dump_trace(struct task_struct *task, struct pt_regs *regs,
++	        unsigned long *stack,
++		struct stacktrace_ops *ops, void *data)
+ {
+-	unsigned long ebp;
++	unsigned long ebp = 0;
+ 
+ 	if (!task)
+ 		task = current;
+@@ -187,54 +191,116 @@ static void show_trace_log_lvl(struct ta
+ 	if (call_trace >= 0) {
+ 		int unw_ret = 0;
+ 		struct unwind_frame_info info;
++		struct ops_and_data oad = { .ops = ops, .data = data };
+ 
+ 		if (regs) {
+ 			if (unwind_init_frame_info(&info, task, regs) == 0)
+-				unw_ret = show_trace_unwind(&info, log_lvl);
++				unw_ret = dump_trace_unwind(&info, &oad);
+ 		} else if (task == current)
+-			unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
++			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+ 		else {
+ 			if (unwind_init_blocked(&info, task) == 0)
+-				unw_ret = show_trace_unwind(&info, log_lvl);
++				unw_ret = dump_trace_unwind(&info, &oad);
+ 		}
+ 		if (unw_ret > 0) {
+ 			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-				print_symbol("DWARF2 unwinder stuck at %s\n",
++				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+ 					     UNW_PC(&info));
+ 				if (UNW_SP(&info) >= PAGE_OFFSET) {
+-					printk("Leftover inexact backtrace:\n");
++					ops->warning(data, "Leftover inexact backtrace:\n");
+ 					stack = (void *)UNW_SP(&info);
++					if (!stack)
++						return;
++					ebp = UNW_FP(&info);
+ 				} else
+-					printk("Full inexact backtrace again:\n");
++					ops->warning(data, "Full inexact backtrace again:\n");
+ 			} else if (call_trace >= 1)
+ 				return;
+ 			else
+-				printk("Full inexact backtrace again:\n");
++				ops->warning(data, "Full inexact backtrace again:\n");
+ 		} else
+-			printk("Inexact backtrace:\n");
++			ops->warning(data, "Inexact backtrace:\n");
+ 	}
+-
+-	if (task == current) {
+-		/* Grab ebp right from our regs */
+-		asm ("movl %%ebp, %0" : "=r" (ebp) : );
+-	} else {
+-		/* ebp is the last reg pushed by switch_to */
+-		ebp = *(unsigned long *) task->thread.esp;
++	if (!stack) {
++		unsigned long dummy;
++		stack = &dummy;
++		if (task && task != current)
++			stack = (unsigned long *)task->thread.esp;
++	}
++
++#ifdef CONFIG_FRAME_POINTER
++	if (!ebp) {
++		if (task == current) {
++			/* Grab ebp right from our regs */
++			asm ("movl %%ebp, %0" : "=r" (ebp) : );
++		} else {
++			/* ebp is the last reg pushed by switch_to */
++			ebp = *(unsigned long *) task->thread.esp;
++		}
+ 	}
++#endif
+ 
+ 	while (1) {
+ 		struct thread_info *context;
+ 		context = (struct thread_info *)
+ 			((unsigned long)stack & (~(THREAD_SIZE - 1)));
+-		ebp = print_context_stack(context, stack, ebp, log_lvl);
++		ebp = print_context_stack(context, stack, ebp, ops, data);
++		/* Should be after the line below, but somewhere
++		   in early boot context comes out corrupted and we
++		   can't reference it -AK */
++		if (ops->stack(data, "IRQ") < 0)
++			break;
+ 		stack = (unsigned long*)context->previous_esp;
+ 		if (!stack)
+ 			break;
+-		printk("%s =======================\n", log_lvl);
+ 	}
+ }
++EXPORT_SYMBOL(dump_trace);
++
++static void
++print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
++{
++	printk(data);
++	print_symbol(msg, symbol);
++	printk("\n");
++}
++
++static void print_trace_warning(void *data, char *msg)
++{
++	printk("%s%s\n", (char *)data, msg);
++}
+ 
+-void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack)
++static int print_trace_stack(void *data, char *name)
++{
++	return 0;
++}
++
++/*
++ * Print one address/symbol entries per line.
++ */
++static void print_trace_address(void *data, unsigned long addr)
++{
++	printk("%s [<%08lx>] ", (char *)data, addr);
++	print_symbol("%s\n", addr);
++}
++
++static struct stacktrace_ops print_trace_ops = {
++	.warning = print_trace_warning,
++	.warning_symbol = print_trace_warning_symbol,
++	.stack = print_trace_stack,
++	.address = print_trace_address,
++};
++
++static void
++show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
++		   unsigned long * stack, char *log_lvl)
++{
++	dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
++	printk("%s =======================\n", log_lvl);
++}
++
++void show_trace(struct task_struct *task, struct pt_regs *regs,
++		unsigned long * stack)
+ {
+ 	show_trace_log_lvl(task, regs, stack, "");
+ }
+@@ -297,12 +363,13 @@ void show_registers(struct pt_regs *regs
+ 		ss = regs->xss & 0xffff;
+ 	}
+ 	print_modules();
+-	printk(KERN_EMERG "CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\n"
+-			"EFLAGS: %08lx   (%s %.*s) \n",
++	printk(KERN_EMERG "CPU:    %d\n"
++		KERN_EMERG "EIP:    %04x:[<%08lx>]    %s VLI\n"
++		KERN_EMERG "EFLAGS: %08lx   (%s %.*s)\n",
+ 		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
+-		print_tainted(), regs->eflags, system_utsname.release,
+-		(int)strcspn(system_utsname.version, " "),
+-		system_utsname.version);
++		print_tainted(), regs->eflags, init_utsname()->release,
++		(int)strcspn(init_utsname()->version, " "),
++		init_utsname()->version);
+ 	print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
+ 	printk(KERN_EMERG "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
+ 		regs->eax, regs->ebx, regs->ecx, regs->edx);
+@@ -319,6 +386,8 @@ void show_registers(struct pt_regs *regs
+ 	 */
+ 	if (in_kernel) {
+ 		u8 __user *eip;
++		int code_bytes = 64;
++		unsigned char c;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+ 		show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
+@@ -326,9 +395,12 @@ void show_registers(struct pt_regs *regs
+ 		printk(KERN_EMERG "Code: ");
+ 
+ 		eip = (u8 __user *)regs->eip - 43;
+-		for (i = 0; i < 64; i++, eip++) {
+-			unsigned char c;
+-
++		if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
++			/* try starting at EIP */
++			eip = (u8 __user *)regs->eip;
++			code_bytes = 32;
++		}
++		for (i = 0; i < code_bytes; i++, eip++) {
+ 			if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
+ 				printk(" Bad EIP value.");
+ 				break;
+@@ -349,7 +421,7 @@ static void handle_BUG(struct pt_regs *r
+ 
+ 	if (eip < PAGE_OFFSET)
+ 		return;
+-	if (__get_user(ud2, (unsigned short __user *)eip))
++	if (probe_kernel_address((unsigned short __user *)eip, ud2))
+ 		return;
+ 	if (ud2 != 0x0b0f)
+ 		return;
+@@ -362,7 +434,8 @@ static void handle_BUG(struct pt_regs *r
+ 		char *file;
+ 		char c;
+ 
+-		if (__get_user(line, (unsigned short __user *)(eip + 2)))
++		if (probe_kernel_address((unsigned short __user *)(eip + 2),
++					line))
+ 			break;
+ 		if (__get_user(file, (char * __user *)(eip + 4)) ||
+ 		    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
+@@ -604,18 +677,24 @@ gp_in_kernel:
+ 	}
+ }
+ 
+-static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
++static __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+-	printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
+-			"to continue\n");
++	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
++		"CPU %d.\n", reason, smp_processor_id());
+ 	printk(KERN_EMERG "You probably have a hardware problem with your RAM "
+ 			"chips\n");
++	if (panic_on_unrecovered_nmi)
++                panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ 
+ 	/* Clear and disable the memory parity error line. */
+ 	clear_mem_error(reason);
+ }
+ 
+-static void io_check_error(unsigned char reason, struct pt_regs * regs)
++static __kprobes void
++io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+ 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+ 	show_registers(regs);
+@@ -624,7 +703,8 @@ static void io_check_error(unsigned char
+ 	clear_io_check_error(reason);
+ }
+ 
+-static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
++static __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+ {
+ #ifdef CONFIG_MCA
+ 	/* Might actually be able to figure out what the guilty party
+@@ -634,15 +714,18 @@ static void unknown_nmi_error(unsigned c
+ 		return;
+ 	}
+ #endif
+-	printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+-		reason, smp_processor_id());
+-	printk("Dazed and confused, but trying to continue\n");
+-	printk("Do you have a strange power saving mode enabled?\n");
++	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
++		"CPU %d.\n", reason, smp_processor_id());
++	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
++	if (panic_on_unrecovered_nmi)
++                panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ }
+ 
+ static DEFINE_SPINLOCK(nmi_print_lock);
+ 
+-void die_nmi (struct pt_regs *regs, const char *msg)
++void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
+ {
+ 	if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
+ 	    NOTIFY_STOP)
+@@ -674,7 +757,7 @@ void die_nmi (struct pt_regs *regs, cons
+ 	do_exit(SIGSEGV);
+ }
+ 
+-static void default_do_nmi(struct pt_regs * regs)
++static __kprobes void default_do_nmi(struct pt_regs * regs)
+ {
+ 	unsigned char reason = 0;
+ 
+@@ -691,12 +774,12 @@ static void default_do_nmi(struct pt_reg
+ 		 * Ok, so this is none of the documented NMI sources,
+ 		 * so it must be the NMI watchdog.
+ 		 */
+-		if (nmi_watchdog) {
+-			nmi_watchdog_tick(regs);
++		if (nmi_watchdog_tick(regs, reason))
+ 			return;
+-		}
++		if (!do_nmi_callback(regs, smp_processor_id()))
+ #endif
+-		unknown_nmi_error(reason, regs);
++			unknown_nmi_error(reason, regs);
++
+ 		return;
+ 	}
+ 	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+@@ -712,14 +795,7 @@ static void default_do_nmi(struct pt_reg
+ 	reassert_nmi();
+ }
+ 
+-static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
+-{
+-	return 0;
+-}
+- 
+-static nmi_callback_t nmi_callback = dummy_nmi_callback;
+- 
+-fastcall void do_nmi(struct pt_regs * regs, long error_code)
++fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code)
+ {
+ 	int cpu;
+ 
+@@ -729,25 +805,11 @@ fastcall void do_nmi(struct pt_regs * re
+ 
+ 	++nmi_count(cpu);
+ 
+-	if (!rcu_dereference(nmi_callback)(regs, cpu))
+-		default_do_nmi(regs);
++	default_do_nmi(regs);
+ 
+ 	nmi_exit();
+ }
+ 
+-void set_nmi_callback(nmi_callback_t callback)
+-{
+-	vmalloc_sync_all();
+-	rcu_assign_pointer(nmi_callback, callback);
+-}
+-EXPORT_SYMBOL_GPL(set_nmi_callback);
+-
+-void unset_nmi_callback(void)
+-{
+-	nmi_callback = dummy_nmi_callback;
+-}
+-EXPORT_SYMBOL_GPL(unset_nmi_callback);
+-
+ #ifdef CONFIG_KPROBES
+ fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ {
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2009-11-06 10:45:48.000000000 +0100
+@@ -103,8 +103,10 @@ void __init pre_setup_arch_hook(void)
+ 
+ 	setup_xen_features();
+ 
+-	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0)
+-		set_fixaddr_top(pp.virt_start);
++	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) {
++		hypervisor_virt_start = pp.virt_start;
++		reserve_top_address(0UL - pp.virt_start);
++	}
+ 
+ 	if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
+ 		machine_to_phys_mapping = (unsigned long *)mapping.v_start;
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2007-12-10 08:47:31.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -27,21 +27,24 @@
+ #include <asm/uaccess.h>
+ #include <asm/desc.h>
+ #include <asm/kdebug.h>
++#include <asm/segment.h>
+ 
+ extern void die(const char *,struct pt_regs *,long);
+ 
+-#ifdef CONFIG_KPROBES
+-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
++static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
++
+ int register_page_fault_notifier(struct notifier_block *nb)
+ {
+ 	vmalloc_sync_all();
+ 	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+ }
++EXPORT_SYMBOL_GPL(register_page_fault_notifier);
+ 
+ int unregister_page_fault_notifier(struct notifier_block *nb)
+ {
+ 	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+ }
++EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
+ 
+ static inline int notify_page_fault(enum die_val val, const char *str,
+ 			struct pt_regs *regs, long err, int trap, int sig)
+@@ -55,14 +58,6 @@ static inline int notify_page_fault(enum
+ 	};
+ 	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+ }
+-#else
+-static inline int notify_page_fault(enum die_val val, const char *str,
+-			struct pt_regs *regs, long err, int trap, int sig)
+-{
+-	return NOTIFY_DONE;
+-}
+-#endif
+-
+ 
+ /*
+  * Unlock any spinlocks which will prevent us from getting the
+@@ -119,10 +114,10 @@ static inline unsigned long get_segment_
+ 	}
+ 
+ 	/* The standard kernel/user address space limit. */
+-	*eip_limit = (seg & 2) ? USER_DS.seg : KERNEL_DS.seg;
++	*eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;
+ 	
+ 	/* By far the most common cases. */
+-	if (likely(seg == __USER_CS || seg == GET_KERNEL_CS()))
++	if (likely(SEGMENT_IS_FLAT_CODE(seg)))
+ 		return eip;
+ 
+ 	/* Check the segment exists, is within the current LDT/GDT size,
+@@ -559,11 +554,7 @@ good_area:
+ 	write = 0;
+ 	switch (error_code & 3) {
+ 		default:	/* 3: write, present */
+-#ifdef TEST_VERIFY_AREA
+-			if (regs->cs == GET_KERNEL_CS())
+-				printk("WP fault at %08lx\n", regs->eip);
+-#endif
+-			/* fall through */
++				/* fall through */
+ 		case 2:		/* write, not present */
+ 			if (!(vma->vm_flags & VM_WRITE))
+ 				goto bad_area;
+@@ -572,7 +563,7 @@ good_area:
+ 		case 1:		/* read, present */
+ 			goto bad_area;
+ 		case 0:		/* read, not present */
+-			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
++			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+ 				goto bad_area;
+ 	}
+ 
+@@ -704,7 +695,7 @@ no_context:
+  */
+ out_of_memory:
+ 	up_read(&mm->mmap_sem);
+-	if (tsk->pid == 1) {
++	if (is_init(tsk)) {
+ 		yield();
+ 		down_read(&mm->mmap_sem);
+ 		goto survive;
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -38,11 +38,9 @@ static void *__kmap_atomic(struct page *
+ 
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+-#ifdef CONFIG_DEBUG_HIGHMEM
+ 	if (!pte_none(*(kmap_pte-idx)))
+ 		BUG();
+-#endif
+-	set_pte_at_sync(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
++	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+ 
+ 	return (void*) vaddr;
+ }
+@@ -62,36 +60,26 @@ void *kmap_atomic_pte(struct page *page,
+ 
+ void kunmap_atomic(void *kvaddr, enum km_type type)
+ {
+-#if defined(CONFIG_DEBUG_HIGHMEM) || defined(CONFIG_XEN)
+ 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+ 	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+ 
+-	if (vaddr < FIXADDR_START) { // FIXME
++#ifdef CONFIG_DEBUG_HIGHMEM
++	if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
+ 		dec_preempt_count();
+ 		preempt_check_resched();
+ 		return;
+ 	}
+-#endif
+ 
+-#if defined(CONFIG_DEBUG_HIGHMEM)
+ 	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+ 		BUG();
+-
+-	/*
+-	 * force other mappings to Oops if they'll try to access
+-	 * this pte without first remap it
+-	 */
+-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
+-	__flush_tlb_one(vaddr);
+-#elif defined(CONFIG_XEN)
++#endif
+ 	/*
+-	 * We must ensure there are no dangling pagetable references when
+-	 * returning memory to Xen (decrease_reservation).
+-	 * XXX TODO: We could make this faster by only zapping when
+-	 * kmap_flush_unused is called but that is trickier and more invasive.
++	 * Force other mappings to Oops if they'll try to access this pte
++	 * without first remap it.  Keeping stale mappings around is a bad idea
++	 * also, in case the page changes cacheability attributes or becomes
++	 * a protected page in a hypervisor.
+ 	 */
+-	pte_clear(&init_mm, vaddr, kmap_pte-idx);
+-#endif
++	kpte_clear_flush(kmap_pte-idx, vaddr);
+ 
+ 	dec_preempt_count();
+ 	preempt_check_resched();
+@@ -110,7 +98,6 @@ void *kmap_atomic_pfn(unsigned long pfn,
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+-	__flush_tlb_one(vaddr);
+ 
+ 	return (void*) vaddr;
+ }
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-06-09 15:01:37.000000000 +0200
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:45:48.000000000 +0100
+@@ -31,6 +31,7 @@
+  */
+ 
+ #include <linux/sched.h>
++#include <linux/hardirq.h>
+ #include <linux/mm.h>
+ #include <linux/vmalloc.h>
+ #include <asm/page.h>
+@@ -44,6 +45,302 @@
+ #include <asm/tlbflush.h>
+ #include <linux/highmem.h>
+ 
++EXPORT_SYMBOL(hypercall_page);
++
++#define NR_MC     BITS_PER_LONG
++#define NR_MMU    BITS_PER_LONG
++#define NR_MMUEXT (BITS_PER_LONG / 4)
++
++DEFINE_PER_CPU(bool, xen_lazy_mmu);
++EXPORT_PER_CPU_SYMBOL(xen_lazy_mmu);
++struct lazy_mmu {
++	unsigned int nr_mc, nr_mmu, nr_mmuext;
++	multicall_entry_t mc[NR_MC];
++	mmu_update_t mmu[NR_MMU];
++	struct mmuext_op mmuext[NR_MMUEXT];
++};
++static DEFINE_PER_CPU(struct lazy_mmu, lazy_mmu);
++
++static inline bool use_lazy_mmu_mode(void)
++{
++#ifdef CONFIG_PREEMPT
++	if (!preempt_count())
++		return false;
++#endif
++	return !irq_count();
++}
++
++static void multicall_failed(const multicall_entry_t *mc, int rc)
++{
++	printk(KERN_EMERG "hypercall#%lu(%lx, %lx, %lx, %lx)"
++			  " failed: %d (caller %lx)\n",
++	       mc->op, mc->args[0], mc->args[1], mc->args[2], mc->args[3],
++	       rc, mc->args[5]);
++	BUG();
++}
++
++int xen_multicall_flush(bool ret_last) {
++	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
++	multicall_entry_t *mc = lazy->mc;
++	unsigned int count = lazy->nr_mc;
++
++	if (!count || !use_lazy_mmu_mode())
++		return 0;
++
++	lazy->nr_mc = 0;
++	lazy->nr_mmu = 0;
++	lazy->nr_mmuext = 0;
++
++	if (count == 1) {
++		int rc = _hypercall(int, mc->op, mc->args[0], mc->args[1],
++				    mc->args[2], mc->args[3], mc->args[4]);
++
++		if (unlikely(rc)) {
++			if (ret_last)
++				return rc;
++			multicall_failed(mc, rc);
++		}
++	} else {
++		if (HYPERVISOR_multicall(mc, count))
++			BUG();
++		while (count-- > ret_last)
++			if (unlikely(mc++->result))
++				multicall_failed(mc - 1, mc[-1].result);
++		if (ret_last)
++			return mc->result;
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL(xen_multicall_flush);
++
++int xen_multi_update_va_mapping(unsigned long va, pte_t pte,
++				unsigned long uvmf)
++{
++	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
++	multicall_entry_t *mc;
++
++	if (unlikely(!use_lazy_mmu_mode()))
++#ifdef CONFIG_X86_PAE
++		return _hypercall4(int, update_va_mapping, va,
++				   pte.pte_low, pte.pte_high, uvmf);
++#else
++		return _hypercall3(int, update_va_mapping, va,
++				   pte.pte, uvmf);
++#endif
++
++	if (unlikely(lazy->nr_mc == NR_MC))
++		xen_multicall_flush(false);
++
++	mc = lazy->mc + lazy->nr_mc++;
++	mc->op = __HYPERVISOR_update_va_mapping;
++	mc->args[0] = va;
++#ifndef CONFIG_X86_PAE
++	mc->args[1] = pte.pte;
++#else
++	mc->args[1] = pte.pte_low;
++	mc->args[2] = pte.pte_high;
++#endif
++	mc->args[MULTI_UVMFLAGS_INDEX] = uvmf;
++	mc->args[5] = (long)__builtin_return_address(0);
++
++	return 0;
++}
++
++static inline bool mmu_may_merge(const multicall_entry_t *mc,
++				 unsigned int op, domid_t domid)
++{
++	return mc->op == op && !mc->args[2] && mc->args[3] == domid;
++}
++
++int xen_multi_mmu_update(mmu_update_t *src, unsigned int count,
++			 unsigned int *success_count, domid_t domid)
++{
++	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
++	multicall_entry_t *mc = lazy->mc + lazy->nr_mc;
++	mmu_update_t *dst;
++	bool commit, merge;
++
++	if (unlikely(!use_lazy_mmu_mode()))
++		return _hypercall4(int, mmu_update, src, count,
++				   success_count, domid);
++
++	commit = (lazy->nr_mmu + count) > NR_MMU || success_count;
++	merge = lazy->nr_mc && !commit
++		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmu_update, domid);
++	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
++		xen_multicall_flush(false);
++		mc = lazy->mc;
++		commit = count > NR_MMU || success_count;
++	}
++
++	if (!lazy->nr_mc && unlikely(commit))
++		return _hypercall4(int, mmu_update, src, count,
++				   success_count, domid);
++
++	dst = lazy->mmu + lazy->nr_mmu;
++	lazy->nr_mmu += count;
++	if (merge) {
++		mc[-1].args[1] += count;
++		memcpy(dst, src, count * sizeof(*src));
++	} else {
++		++lazy->nr_mc;
++		mc->op = __HYPERVISOR_mmu_update;
++		if (!commit) {
++			mc->args[0] = (unsigned long)dst;
++			memcpy(dst, src, count * sizeof(*src));
++		} else
++			mc->args[0] = (unsigned long)src;
++		mc->args[1] = count;
++		mc->args[2] = (unsigned long)success_count;
++		mc->args[3] = domid;
++		mc->args[5] = (long)__builtin_return_address(0);
++	}
++
++	while (!commit && count--)
++		switch (src++->ptr & (sizeof(pteval_t) - 1)) {
++		case MMU_NORMAL_PT_UPDATE:
++		case MMU_PT_UPDATE_PRESERVE_AD:
++			break;
++		default:
++			commit = true;
++			break;
++		}
++
++	return commit ? xen_multicall_flush(true) : 0;
++}
++
++int xen_multi_mmuext_op(struct mmuext_op *src, unsigned int count,
++			unsigned int *success_count, domid_t domid)
++{
++	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
++	multicall_entry_t *mc;
++	struct mmuext_op *dst;
++	bool commit, merge;
++
++	if (unlikely(!use_lazy_mmu_mode()))
++		return _hypercall4(int, mmuext_op, src, count,
++				   success_count, domid);
++
++	/*
++	 * While it could be useful in theory, I've never seen the body of
++	 * this conditional to be reached, hence it seems more reasonable
++	 * to disable it for the time being.
++	 */
++	if (0 && likely(count)
++	    && likely(!success_count)
++	    && likely(domid == DOMID_SELF)
++	    && likely(lazy->nr_mc)
++	    && lazy->mc[lazy->nr_mc - 1].op == __HYPERVISOR_update_va_mapping) {
++		unsigned long oldf, newf = UVMF_NONE;
++
++		switch (src->cmd) {
++		case MMUEXT_TLB_FLUSH_ALL:
++			newf = UVMF_TLB_FLUSH | UVMF_ALL;
++			break;
++		case MMUEXT_INVLPG_ALL:
++			newf = UVMF_INVLPG | UVMF_ALL;
++			break;
++		case MMUEXT_TLB_FLUSH_MULTI:
++			newf = UVMF_TLB_FLUSH | UVMF_MULTI
++			       | (unsigned long)src->arg2.vcpumask.p;
++			break;
++		case MMUEXT_INVLPG_MULTI:
++			newf = UVMF_INVLPG | UVMF_MULTI
++			       | (unsigned long)src->arg2.vcpumask.p;
++			break;
++		case MMUEXT_TLB_FLUSH_LOCAL:
++			newf = UVMF_TLB_FLUSH | UVMF_LOCAL;
++			break;
++		case MMUEXT_INVLPG_LOCAL:
++			newf = UVMF_INVLPG | UVMF_LOCAL;
++			break;
++		}
++		mc = lazy->mc + lazy->nr_mc - 1;
++		oldf = mc->args[MULTI_UVMFLAGS_INDEX];
++		if (newf == UVMF_NONE || oldf == UVMF_NONE
++		    || newf == (UVMF_TLB_FLUSH | UVMF_ALL))
++			;
++		else if (oldf == (UVMF_TLB_FLUSH | UVMF_ALL))
++			newf = UVMF_TLB_FLUSH | UVMF_ALL;
++		else if ((newf & UVMF_FLUSHTYPE_MASK) == UVMF_INVLPG
++			 && (oldf & UVMF_FLUSHTYPE_MASK) == UVMF_INVLPG
++			 && ((src->arg1.linear_addr ^ mc->args[0])
++			     >> PAGE_SHIFT))
++			newf = UVMF_NONE;
++		else if (((oldf | newf) & UVMF_ALL)
++			 && !((oldf ^ newf) & UVMF_FLUSHTYPE_MASK))
++			newf |= UVMF_ALL;
++		else if ((oldf ^ newf) & ~UVMF_FLUSHTYPE_MASK)
++			newf = UVMF_NONE;
++		else if ((oldf & UVMF_FLUSHTYPE_MASK) == UVMF_TLB_FLUSH)
++			newf = (newf & ~UVMF_FLUSHTYPE_MASK) | UVMF_TLB_FLUSH;
++		else if ((newf & UVMF_FLUSHTYPE_MASK) != UVMF_TLB_FLUSH
++			 && ((newf ^ oldf) & UVMF_FLUSHTYPE_MASK))
++			newf = UVMF_NONE;
++		if (newf != UVMF_NONE) {
++			mc->args[MULTI_UVMFLAGS_INDEX] = newf;
++			++src;
++			if (!--count)
++				return 0;
++		}
++	}
++
++	mc = lazy->mc + lazy->nr_mc;
++	commit = (lazy->nr_mmuext + count) > NR_MMUEXT || success_count;
++	merge = lazy->nr_mc && !commit
++		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmuext_op, domid);
++	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
++		xen_multicall_flush(false);
++		mc = lazy->mc;
++		commit = count > NR_MMUEXT || success_count;
++	}
++
++	if (!lazy->nr_mc && unlikely(commit))
++		return _hypercall4(int, mmuext_op, src, count,
++				   success_count, domid);
++
++	dst = lazy->mmuext + lazy->nr_mmuext;
++	lazy->nr_mmuext += count;
++	if (merge) {
++		mc[-1].args[1] += count;
++		memcpy(dst, src, count * sizeof(*src));
++	} else {
++		++lazy->nr_mc;
++		mc->op = __HYPERVISOR_mmuext_op;
++		if (!commit) {
++			mc->args[0] = (unsigned long)dst;
++			memcpy(dst, src, count * sizeof(*src));
++		} else
++			mc->args[0] = (unsigned long)src;
++		mc->args[1] = count;
++		mc->args[2] = (unsigned long)success_count;
++		mc->args[3] = domid;
++		mc->args[5] = (long)__builtin_return_address(0);
++	}
++
++	while (!commit && count--)
++		switch (src++->cmd) {
++		case MMUEXT_PIN_L1_TABLE:
++		case MMUEXT_PIN_L2_TABLE:
++		case MMUEXT_PIN_L3_TABLE:
++		case MMUEXT_PIN_L4_TABLE:
++		case MMUEXT_UNPIN_TABLE:
++		case MMUEXT_TLB_FLUSH_LOCAL:
++		case MMUEXT_INVLPG_LOCAL:
++		case MMUEXT_TLB_FLUSH_MULTI:
++		case MMUEXT_INVLPG_MULTI:
++		case MMUEXT_TLB_FLUSH_ALL:
++		case MMUEXT_INVLPG_ALL:
++			break;
++		default:
++			commit = true;
++			break;
++		}
++
++	return commit ? xen_multicall_flush(true) : 0;
++}
++
+ void xen_l1_entry_update(pte_t *ptr, pte_t val)
+ {
+ 	mmu_update_t u;
+@@ -546,7 +843,8 @@ int write_ldt_entry(void *ldt, int entry
+ #define MAX_BATCHED_FULL_PTES 32
+ 
+ int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-			 unsigned long addr, unsigned long end, pgprot_t newprot)
++			 unsigned long addr, unsigned long end, pgprot_t newprot,
++			 int dirty_accountable)
+ {
+ 	int rc = 0, i = 0;
+ 	mmu_update_t u[MAX_BATCHED_FULL_PTES];
+@@ -559,10 +857,14 @@ int xen_change_pte_range(struct mm_struc
+ 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+ 	do {
+ 		if (pte_present(*pte)) {
++			pte_t ptent = pte_modify(*pte, newprot);
++
++			if (dirty_accountable && pte_dirty(ptent))
++				ptent = pte_mkwrite(ptent);
+ 			u[i].ptr = (__pmd_val(*pmd) & PHYSICAL_PAGE_MASK)
+ 				   | ((unsigned long)pte & ~PAGE_MASK)
+ 				   | MMU_PT_UPDATE_PRESERVE_AD;
+-			u[i].val = __pte_val(pte_modify(*pte, newprot));
++			u[i].val = __pte_val(ptent);
+ 			if (++i == MAX_BATCHED_FULL_PTES) {
+ 				if ((rc = HYPERVISOR_mmu_update(
+ 					&u[0], i, NULL, DOMID_SELF)) != 0)
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -313,8 +313,7 @@ static void __init permanent_kmaps_init(
+ static void __meminit free_new_highpage(struct page *page, int pfn)
+ {
+ 	init_page_count(page);
+-	if (pfn < xen_start_info->nr_pages)
+-		__free_page(page);
++	__free_page(page);
+ 	totalhigh_pages++;
+ }
+ 
+@@ -357,8 +356,16 @@ extern void set_highmem_pages_init(int);
+ static void __init set_highmem_pages_init(int bad_ppro)
+ {
+ 	int pfn;
+-	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
++	for (pfn = highstart_pfn; pfn < highend_pfn
++				  && pfn < xen_start_info->nr_pages; pfn++)
+ 		add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
++
++	/* XEN: init high-mem pages outside initial allocation. */
++	for (; pfn < highend_pfn; pfn++) {
++		ClearPageReserved(pfn_to_page(pfn));
++		init_page_count(pfn_to_page(pfn));
++	}
++
+ 	totalram_pages += totalhigh_pages;
+ }
+ #endif /* CONFIG_FLATMEM */
+@@ -462,16 +469,22 @@ EXPORT_SYMBOL(__supported_pte_mask);
+  * on      Enable
+  * off     Disable
+  */
+-void __init noexec_setup(const char *str)
++static int __init noexec_setup(char *str)
+ {
+-	if (!strncmp(str, "on",2) && cpu_has_nx) {
+-		__supported_pte_mask |= _PAGE_NX;
+-		disable_nx = 0;
+-	} else if (!strncmp(str,"off",3)) {
++	if (!str || !strcmp(str, "on")) {
++		if (cpu_has_nx) {
++			__supported_pte_mask |= _PAGE_NX;
++			disable_nx = 0;
++		}
++	} else if (!strcmp(str,"off")) {
+ 		disable_nx = 1;
+ 		__supported_pte_mask &= ~_PAGE_NX;
+-	}
++	} else
++		return -EINVAL;
++
++	return 0;
+ }
++early_param("noexec", noexec_setup);
+ 
+ int nx_enabled = 0;
+ #ifdef CONFIG_X86_PAE
+@@ -514,6 +527,7 @@ int __init set_kernel_exec(unsigned long
+ 		pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
+ 	else
+ 		pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);
++	pte_update_defer(&init_mm, vaddr, pte);
+ 	__flush_tlb_all();
+ out:
+ 	return ret;
+@@ -596,18 +610,6 @@ static void __init test_wp_bit(void)
+ 	}
+ }
+ 
+-static void __init set_max_mapnr_init(void)
+-{
+-#ifdef CONFIG_HIGHMEM
+-	num_physpages = highend_pfn;
+-#else
+-	num_physpages = max_low_pfn;
+-#endif
+-#ifdef CONFIG_FLATMEM
+-	max_mapnr = num_physpages;
+-#endif
+-}
+-
+ static struct kcore_list kcore_mem, kcore_vmalloc; 
+ 
+ void __init mem_init(void)
+@@ -623,8 +625,7 @@ void __init mem_init(void)
+ #endif
+ 
+ #ifdef CONFIG_FLATMEM
+-	if (!mem_map)
+-		BUG();
++	BUG_ON(!mem_map);
+ #endif
+ 	
+ 	bad_ppro = ppro_with_ram_bug();
+@@ -639,24 +640,12 @@ void __init mem_init(void)
+ 	}
+ #endif
+  
+-	set_max_mapnr_init();
+-
+-#ifdef CONFIG_HIGHMEM
+-	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+-#else
+-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+-#endif
+-	printk("vmalloc area: %lx-%lx, maxmem %lx\n",
+-	       VMALLOC_START,VMALLOC_END,MAXMEM);
+-	BUG_ON(VMALLOC_START > VMALLOC_END);
+-	
+ 	/* this will put all low memory onto the freelists */
+ 	totalram_pages += free_all_bootmem();
+-	/* XEN: init and count low-mem pages outside initial allocation. */
++	/* XEN: init low-mem pages outside initial allocation. */
+ 	for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) {
+ 		ClearPageReserved(pfn_to_page(pfn));
+ 		init_page_count(pfn_to_page(pfn));
+-		totalram_pages++;
+ 	}
+ 
+ 	reservedpages = 0;
+@@ -687,6 +676,48 @@ void __init mem_init(void)
+ 		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
+ 	       );
+ 
++#if 1 /* double-sanity-check paranoia */
++	printk("virtual kernel memory layout:\n"
++	       "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++#ifdef CONFIG_HIGHMEM
++	       "    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++#endif
++	       "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++	       "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++	       "      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++	       "      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++	       "      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
++	       FIXADDR_START, FIXADDR_TOP,
++	       (FIXADDR_TOP - FIXADDR_START) >> 10,
++
++#ifdef CONFIG_HIGHMEM
++	       PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
++	       (LAST_PKMAP*PAGE_SIZE) >> 10,
++#endif
++
++	       VMALLOC_START, VMALLOC_END,
++	       (VMALLOC_END - VMALLOC_START) >> 20,
++
++	       (unsigned long)__va(0), (unsigned long)high_memory,
++	       ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
++
++	       (unsigned long)&__init_begin, (unsigned long)&__init_end,
++	       ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10,
++
++	       (unsigned long)&_etext, (unsigned long)&_edata,
++	       ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
++
++	       (unsigned long)&_text, (unsigned long)&_etext,
++	       ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
++
++#ifdef CONFIG_HIGHMEM
++	BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE > FIXADDR_START);
++	BUG_ON(VMALLOC_END                     > PKMAP_BASE);
++#endif
++	BUG_ON(VMALLOC_START                   > VMALLOC_END);
++	BUG_ON((unsigned long)high_memory      > VMALLOC_START);
++#endif /* double-sanity-check paranoia */
++
+ #ifdef CONFIG_X86_PAE
+ 	if (!cpu_has_pae)
+ 		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
+@@ -717,7 +748,7 @@ void __init mem_init(void)
+ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ 	struct pglist_data *pgdata = &contig_page_data;
+-	struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
++	struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
+ 	unsigned long start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 
+--- head-2010-01-18.orig/arch/x86/mm/ioremap_32-xen.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -12,7 +12,7 @@
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
+-#include <asm/io.h>
++#include <linux/io.h>
+ #include <asm/fixmap.h>
+ #include <asm/cacheflush.h>
+ #include <asm/tlbflush.h>
+@@ -118,7 +118,7 @@ int direct_remap_pfn_range(struct vm_are
+ 	if (domid == DOMID_SELF)
+ 		return -EINVAL;
+ 
+-	vma->vm_flags |= VM_IO | VM_RESERVED;
++	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+ 
+ 	vma->vm_mm->context.has_foreign_mappings = 1;
+ 
+@@ -203,6 +203,7 @@ void __iomem * __ioremap(unsigned long p
+ 	void __iomem * addr;
+ 	struct vm_struct * area;
+ 	unsigned long offset, last_addr;
++	pgprot_t prot;
+ 	domid_t domid = DOMID_IO;
+ 
+ 	/* Don't allow wraparound or zero size */
+@@ -234,6 +235,8 @@ void __iomem * __ioremap(unsigned long p
+ 		domid = DOMID_SELF;
+ 	}
+ 
++	prot = __pgprot(_KERNPG_TABLE | flags);
++
+ 	/*
+ 	 * Mappings have to be page-aligned
+ 	 */
+@@ -249,10 +252,9 @@ void __iomem * __ioremap(unsigned long p
+ 		return NULL;
+ 	area->phys_addr = phys_addr;
+ 	addr = (void __iomem *) area->addr;
+-	flags |= _KERNPG_TABLE;
+ 	if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr,
+ 				     phys_addr>>PAGE_SHIFT,
+-				     size, __pgprot(flags), domid)) {
++				     size, prot, domid)) {
+ 		vunmap((void __force *) addr);
+ 		return NULL;
+ 	}
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -68,7 +68,9 @@ void show_mem(void)
+ 	printk(KERN_INFO "%lu pages writeback\n",
+ 					global_page_state(NR_WRITEBACK));
+ 	printk(KERN_INFO "%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
+-	printk(KERN_INFO "%lu pages slab\n", global_page_state(NR_SLAB));
++	printk(KERN_INFO "%lu pages slab\n",
++		global_page_state(NR_SLAB_RECLAIMABLE) +
++		global_page_state(NR_SLAB_UNRECLAIMABLE));
+ 	printk(KERN_INFO "%lu pages pagetables\n",
+ 					global_page_state(NR_PAGETABLE));
+ }
+@@ -108,18 +110,11 @@ void set_pmd_pfn(unsigned long vaddr, un
+ 	__flush_tlb_one(vaddr);
+ }
+ 
+-static int nr_fixmaps = 0;
++static int fixmaps;
+ unsigned long hypervisor_virt_start = HYPERVISOR_VIRT_START;
+-unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - 2 * PAGE_SIZE);
++unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - PAGE_SIZE);
+ EXPORT_SYMBOL(__FIXADDR_TOP);
+ 
+-void __init set_fixaddr_top(unsigned long top)
+-{
+-	BUG_ON(nr_fixmaps > 0);
+-	hypervisor_virt_start = top;
+-	__FIXADDR_TOP = hypervisor_virt_start - 2 * PAGE_SIZE;
+-}
+-
+ void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
+ {
+ 	unsigned long address = __fix_to_virt(idx);
+@@ -141,7 +136,21 @@ void __set_fixmap (enum fixed_addresses 
+ 	if (HYPERVISOR_update_va_mapping(address, pte,
+ 					 UVMF_INVLPG|UVMF_ALL))
+ 		BUG();
+-	nr_fixmaps++;
++	fixmaps++;
++}
++
++/**
++ * reserve_top_address - reserves a hole in the top of kernel address space
++ * @reserve - size of hole to reserve
++ *
++ * Can be used to relocate the fixmap area and poke a hole in the top
++ * of kernel address space to make room for a hypervisor.
++ */
++void __init reserve_top_address(unsigned long reserve)
++{
++	BUG_ON(fixmaps > 0);
++	__FIXADDR_TOP = -reserve - PAGE_SIZE;
++	__VMALLOC_RESERVE += reserve;
+ }
+ 
+ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2008-03-06 08:54:32.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -991,10 +991,6 @@ static void __init pcibios_fixup_irqs(vo
+ 							pci_name(bridge), 'A' + pin, irq);
+ 				}
+ 				if (irq >= 0) {
+-					if (use_pci_vector() &&
+-						!platform_legacy_irq(irq))
+-						irq = IO_APIC_VECTOR(irq);
+-
+ 					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ 						pci_name(dev), 'A' + pin, irq);
+ 					dev->irq = irq;
+@@ -1155,10 +1151,6 @@ static int pirq_enable_irq(struct pci_de
+ 			}
+ 			dev = temp_dev;
+ 			if (irq >= 0) {
+-#ifdef CONFIG_PCI_MSI
+-				if (!platform_legacy_irq(irq))
+-					irq = IO_APIC_VECTOR(irq);
+-#endif
+ 				printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ 					pci_name(dev), 'A' + pin, irq);
+ 				dev->irq = irq;
+@@ -1179,33 +1171,3 @@ static int pirq_enable_irq(struct pci_de
+ 	}
+ 	return 0;
+ }
+-
+-int pci_vector_resources(int last, int nr_released)
+-{
+-	int count = nr_released;
+-
+-	int next = last;
+-	int offset = (last % 8);
+-
+-	while (next < FIRST_SYSTEM_VECTOR) {
+-		next += 8;
+-#ifdef CONFIG_X86_64
+-		if (next == IA32_SYSCALL_VECTOR)
+-			continue;
+-#else
+-		if (next == SYSCALL_VECTOR)
+-			continue;
+-#endif
+-		count++;
+-		if (next >= FIRST_SYSTEM_VECTOR) {
+-			if (offset%8) {
+-				next = FIRST_DEVICE_VECTOR + offset;
+-				offset++;
+-				continue;
+-			}
+-			count--;
+-		}
+-	}
+-
+-	return count;
+-}
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:45:48.000000000 +0100
+@@ -83,6 +83,7 @@
+  */ 	
+ ENTRY(ia32_sysenter_target)
+ 	CFI_STARTPROC32	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-RIP+16
+ 	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+ 	CFI_REL_OFFSET	rsp,RSP-RIP+16
+@@ -164,6 +165,7 @@ ENDPROC(ia32_sysenter_target)
+  */ 	
+ ENTRY(ia32_cstar_target)
+ 	CFI_STARTPROC32	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-RIP+16
+ 	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+ 	CFI_REL_OFFSET	rsp,RSP-RIP+16
+@@ -243,6 +245,7 @@ ia32_badarg:
+ 
+ ENTRY(ia32_syscall)
+ 	CFI_STARTPROC	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-RIP+16
+ 	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+ 	CFI_REL_OFFSET	rsp,RSP-RIP+16
+@@ -320,6 +323,7 @@ ENTRY(ia32_ptregs_common)
+ 	popq %r11
+ 	CFI_ENDPROC
+ 	CFI_STARTPROC32	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
+ 	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
+ 	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
+@@ -653,8 +657,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
+@@ -663,4 +667,5 @@ ia32_sys_call_table:
+ 	.quad sys_tee
+ 	.quad compat_sys_vmsplice
+ 	.quad compat_sys_move_pages
++	.quad sys_getcpu
+ ia32_syscall_end:		
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:45:48.000000000 +0100
+@@ -122,7 +122,7 @@ obj-$(CONFIG_X86_XEN)		+= fixup.o
+ ###
+ # 64 bit specific files
+ ifeq ($(CONFIG_X86_64),y)
+-	obj-$(CONFIG_X86_XEN_GENAPIC)	+= genapic_xen_64.o
++	obj-$(CONFIG_X86_XEN_GENAPIC)	+= genapic_64.o genapic_xen_64.o
+ 	obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+ 	obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
+ 	obj-$(CONFIG_AUDIT)		+= audit_64.o
+@@ -138,5 +138,7 @@ ifeq ($(CONFIG_X86_64),y)
+ 	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := i8253.o i8259_$(BITS).o reboot.o smpboot_$(BITS).o tsc_$(BITS).o
++disabled-obj-$(CONFIG_XEN) := early-quirks.o i8253.o i8259_$(BITS).o reboot.o \
++	smpboot_$(BITS).o tsc_$(BITS).o
++disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += mpparse_64.o
+ %/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2007-06-12 13:13:01.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -43,7 +43,7 @@ int apic_verbosity;
+  */
+ void ack_bad_irq(unsigned int irq)
+ {
+-	printk("unexpected IRQ trap at vector %02x\n", irq);
++	printk("unexpected IRQ trap at irq %02x\n", irq);
+ 	/*
+ 	 * Currently unexpected vectors happen only on SMP and APIC.
+ 	 * We _must_ ack these because every local APIC has only N
+@@ -62,19 +62,19 @@ int setup_profiling_timer(unsigned int m
+ 	return -EINVAL;
+ }
+ 
+-void smp_local_timer_interrupt(struct pt_regs *regs)
++void smp_local_timer_interrupt(void)
+ {
+-	profile_tick(CPU_PROFILING, regs);
++	profile_tick(CPU_PROFILING);
+ #ifndef CONFIG_XEN
+ #ifdef CONFIG_SMP
+-		update_process_times(user_mode(regs));
++	update_process_times(user_mode(get_irq_regs()));
+ #endif
+ #endif
+ 	/*
+ 	 * We take the 'long' return path, and there every subsystem
+ 	 * grabs the appropriate locks (kernel lock/ irq lock).
+ 	 *
+-	 * we might want to decouple profiling from the 'long path',
++	 * We might want to decouple profiling from the 'long path',
+ 	 * and do the profiling totally in assembly.
+ 	 *
+ 	 * Currently this isn't too much of an issue (performance wise),
+@@ -92,6 +92,8 @@ void smp_local_timer_interrupt(struct pt
+  */
+ void smp_apic_timer_interrupt(struct pt_regs *regs)
+ {
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
+ 	/*
+ 	 * the NMI deadlock-detector uses this.
+ 	 */
+@@ -109,8 +111,9 @@ void smp_apic_timer_interrupt(struct pt_
+ 	 */
+ 	exit_idle();
+ 	irq_enter();
+-	smp_local_timer_interrupt(regs);
++	smp_local_timer_interrupt();
+ 	irq_exit();
++	set_irq_regs(old_regs);
+ }
+ 
+ /*
+@@ -188,9 +191,8 @@ int disable_apic;
+ int __init APIC_init_uniprocessor (void)
+ {
+ #ifdef CONFIG_X86_IO_APIC
+-	if (smp_found_config)
+-		if (!skip_ioapic_setup && nr_ioapics)
+-			setup_IO_APIC();
++	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
++		setup_IO_APIC();
+ #endif
+ 
+ 	return 1;
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 08:45:56.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:49:03.000000000 +0100
+@@ -16,6 +16,7 @@
+ #include <linux/string.h>
+ #include <linux/kexec.h>
+ #include <linux/module.h>
++#include <linux/mm.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
+@@ -25,6 +26,11 @@
+ #include <asm/sections.h>
+ #include <xen/interface/memory.h>
+ 
++struct e820map e820 __initdata;
++#ifdef CONFIG_XEN
++struct e820map machine_e820 __initdata;
++#endif
++
+ /* 
+  * PFN of last memory page.
+  */
+@@ -43,14 +49,10 @@ unsigned long end_pfn_map; 
+ /* 
+  * Last pfn which the user wants to use.
+  */
+-unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;  
++static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
+ 
+ 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)
+ { 
+@@ -59,13 +61,13 @@ static inline int bad_addr(unsigned long
+ #ifndef CONFIG_XEN
+ 	/* various gunk below that needed for SMP startup */
+ 	if (addr < 0x8000) { 
+-		*addrp = 0x8000;
++		*addrp = PAGE_ALIGN(0x8000);
+ 		return 1; 
+ 	}
+ 
+ 	/* direct mapping tables of the kernel */
+ 	if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 
+-		*addrp = table_end << PAGE_SHIFT; 
++		*addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
+ 		return 1;
+ 	} 
+ 
+@@ -73,23 +75,18 @@ static inline int bad_addr(unsigned long
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 
+ 	    addr < INITRD_START+INITRD_SIZE) { 
+-		*addrp = INITRD_START + INITRD_SIZE; 
++		*addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
+ 		return 1;
+ 	} 
+ #endif
+-	/* kernel code + 640k memory hole (later should not be needed, but 
+-	   be paranoid for now) */
+-	if (last >= 640*1024 && addr < 1024*1024) {
+-		*addrp = 1024*1024;
+-		return 1;
+-	}
+-	if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
+-		*addrp = __pa_symbol(&_end);
++	/* kernel code */
++	if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
++		*addrp = PAGE_ALIGN(__pa_symbol(&_end));
+ 		return 1;
+ 	}
+ 
+ 	if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
+-		*addrp = ebda_addr + ebda_size;
++		*addrp = PAGE_ALIGN(ebda_addr + ebda_size);
+ 		return 1;
+ 	}
+ 
+@@ -186,7 +183,7 @@ unsigned long __init find_e820_area(unsi
+ 			continue; 
+ 		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
+ 			;
+-		last = addr + size;
++		last = PAGE_ALIGN(addr) + size;
+ 		if (last > ei->addr + ei->size)
+ 			continue;
+ 		if (last > end) 
+@@ -196,59 +193,14 @@ unsigned long __init find_e820_area(unsi
+ 	return -1UL;		
+ } 
+ 
+-/* 
+- * Free bootmem based on the e820 table for a node.
+- */
+-void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
+-{
+-	int i;
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i]; 
+-		unsigned long last, addr;
+-
+-		if (ei->type != E820_RAM || 
+-		    ei->addr+ei->size <= start || 
+-		    ei->addr >= end)
+-			continue;
+-
+-		addr = round_up(ei->addr, PAGE_SIZE);
+-		if (addr < start) 
+-			addr = start;
+-
+-		last = round_down(ei->addr + ei->size, PAGE_SIZE); 
+-		if (last >= end)
+-			last = end; 
+-
+-		if (last > addr && last-addr >= PAGE_SIZE)
+-			free_bootmem_node(pgdat, addr, last-addr);
+-	}
+-}
+-
+ /*
+  * Find the highest page frame number we have available
+  */
+ unsigned long __init e820_end_of_ram(void)
+ {
+-	int i;
+ 	unsigned long end_pfn = 0;
++	end_pfn = find_max_pfn_with_active_regions();
+ 	
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i]; 
+-		unsigned long start, end;
+-
+-		start = round_up(ei->addr, PAGE_SIZE); 
+-		end = round_down(ei->addr + ei->size, PAGE_SIZE); 
+-		if (start >= end)
+-			continue;
+-		if (ei->type == E820_RAM) { 
+-		if (end > end_pfn<<PAGE_SHIFT)
+-			end_pfn = end>>PAGE_SHIFT;
+-		} else { 
+-			if (end > end_pfn_map<<PAGE_SHIFT) 
+-				end_pfn_map = end>>PAGE_SHIFT;
+-		} 
+-	}
+-
+ 	if (end_pfn > end_pfn_map) 
+ 		end_pfn_map = end_pfn;
+ 	if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
+@@ -258,43 +210,10 @@ unsigned long __init e820_end_of_ram(voi
+ 	if (end_pfn > end_pfn_map) 
+ 		end_pfn = end_pfn_map; 
+ 
++	printk("end_pfn_map = %lu\n", end_pfn_map);
+ 	return end_pfn;	
+ }
+ 
+-/* 
+- * Compute how much memory is missing in a range.
+- * Unlike the other functions in this file the arguments are in page numbers.
+- */
+-unsigned long __init
+-e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
+-{
+-	unsigned long ram = 0;
+-	unsigned long start = start_pfn << PAGE_SHIFT;
+-	unsigned long end = end_pfn << PAGE_SHIFT;
+-	int i;
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		unsigned long last, addr;
+-
+-		if (ei->type != E820_RAM ||
+-		    ei->addr+ei->size <= start ||
+-		    ei->addr >= end)
+-			continue;
+-
+-		addr = round_up(ei->addr, PAGE_SIZE);
+-		if (addr < start)
+-			addr = start;
+-
+-		last = round_down(ei->addr + ei->size, PAGE_SIZE);
+-		if (last >= end)
+-			last = end;
+-
+-		if (last > addr)
+-			ram += last - addr;
+-	}
+-	return ((end - start) - ram) >> PAGE_SHIFT;
+-}
+-
+ /*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+@@ -335,6 +254,109 @@ void __init e820_reserve_resources(struc
+ 	}
+ }
+ 
++#ifndef CONFIG_XEN
++/* Mark pages corresponding to given address range as nosave */
++static void __init
++e820_mark_nosave_range(unsigned long start, unsigned long end)
++{
++	unsigned long pfn, max_pfn;
++
++	if (start >= end)
++		return;
++
++	printk("Nosave address range: %016lx - %016lx\n", start, end);
++	max_pfn = end >> PAGE_SHIFT;
++	for (pfn = start >> PAGE_SHIFT; pfn < max_pfn; pfn++)
++		if (pfn_valid(pfn))
++			SetPageNosave(pfn_to_page(pfn));
++}
++
++/*
++ * Find the ranges of physical addresses that do not correspond to
++ * e820 RAM areas and mark the corresponding pages as nosave for software
++ * suspend and suspend to RAM.
++ *
++ * This function requires the e820 map to be sorted and without any
++ * overlapping entries and assumes the first e820 area to be RAM.
++ */
++void __init e820_mark_nosave_regions(void)
++{
++	int i;
++	unsigned long paddr;
++
++	paddr = round_down(e820.map[0].addr + e820.map[0].size, PAGE_SIZE);
++	for (i = 1; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++
++		if (paddr < ei->addr)
++			e820_mark_nosave_range(paddr,
++					round_up(ei->addr, PAGE_SIZE));
++
++		paddr = round_down(ei->addr + ei->size, PAGE_SIZE);
++		if (ei->type != E820_RAM)
++			e820_mark_nosave_range(round_up(ei->addr, PAGE_SIZE),
++					paddr);
++
++		if (paddr >= (end_pfn << PAGE_SHIFT))
++			break;
++	}
++}
++#endif
++
++/* Walk the e820 map and register active regions within a node */
++void __init
++e820_register_active_regions(int nid, unsigned long start_pfn,
++							unsigned long end_pfn)
++{
++	int i;
++	unsigned long ei_startpfn, ei_endpfn;
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
++		ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
++								>> PAGE_SHIFT;
++
++		/* Skip map entries smaller than a page */
++		if (ei_startpfn >= ei_endpfn)
++			continue;
++
++		/* Check if end_pfn_map should be updated */
++		if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
++			end_pfn_map = ei_endpfn;
++
++		/* Skip if map is outside the node */
++		if (ei->type != E820_RAM ||
++				ei_endpfn <= start_pfn ||
++				ei_startpfn >= end_pfn)
++			continue;
++
++		/* Check for overlaps */
++		if (ei_startpfn < start_pfn)
++			ei_startpfn = start_pfn;
++		if (ei_endpfn > end_pfn)
++			ei_endpfn = end_pfn;
++
++		/* Obey end_user_pfn to save on memmap */
++		if (ei_startpfn >= end_user_pfn)
++			continue;
++		if (ei_endpfn > end_user_pfn)
++			ei_endpfn = end_user_pfn;
++
++#ifdef CONFIG_XEN
++		if (ei_startpfn >= xen_start_info->nr_pages)
++			continue;
++		if (ei_endpfn > xen_start_info->nr_pages)
++			ei_endpfn = xen_start_info->nr_pages;
++#endif
++
++		add_active_range(nid, ei_startpfn, ei_endpfn);
++	}
++#ifdef CONFIG_XEN
++	BUG_ON(nid);
++	add_active_range(nid, end_pfn, end_pfn);
++#endif
++}
++
+ /* 
+  * Add a memory region to the kernel e820 map.
+  */ 
+@@ -555,13 +577,6 @@ static int __init sanitize_e820_map(stru
+  * If we're lucky and live on a modern system, the setup code
+  * will have given us a memory map that we can use to properly
+  * set up memory.  If we aren't, we'll fake a memory map.
+- *
+- * We check to see that the memory map contains at least 2 elements
+- * before we'll use it, because the detection code in setup.S may
+- * not be perfect and most every PC known to man has two memory
+- * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
+- * thinkpad 560x, for example, does not cooperate with the memory
+- * detection code.)
+  */
+ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+ {
+@@ -583,27 +598,6 @@ static int __init copy_e820_map(struct e
+ 		if (start > end)
+ 			return -1;
+ 
+-#ifndef CONFIG_XEN
+-		/*
+-		 * Some BIOSes claim RAM in the 640k - 1M region.
+-		 * Not right. Fix it up.
+-		 * 
+-		 * This should be removed on Hammer which is supposed to not
+-		 * have non e820 covered ISA mappings there, but I had some strange
+-		 * problems so it stays for now.  -AK
+-		 */
+-		if (type == E820_RAM) {
+-			if (start < 0x100000ULL && end > 0xA0000ULL) {
+-				if (start < 0xA0000ULL)
+-					add_memory_region(start, 0xA0000ULL-start, type);
+-				if (end <= 0x100000ULL)
+-					continue;
+-				start = 0x100000ULL;
+-				size = end - start;
+-			}
+-		}
+-#endif
+-
+ 		add_memory_region(start, size, type);
+ 	} while (biosmap++,--nr_map);
+ 
+@@ -624,11 +618,15 @@ static int __init copy_e820_map(struct e
+ 	return 0;
+ }
+ 
++void early_panic(char *msg)
++{
++	early_printk(msg);
++	panic(msg);
++}
++
+ #ifndef CONFIG_XEN
+ void __init setup_memory_region(void)
+ {
+-	char *who = "BIOS-e820";
+-
+ 	/*
+ 	 * Try to copy the BIOS-supplied E820-map.
+ 	 *
+@@ -636,24 +634,10 @@ void __init setup_memory_region(void)
+ 	 * the next section from 1mb->appropriate_mem_k
+ 	 */
+ 	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+-		unsigned long mem_size;
+-
+-		/* compare results from other methods and take the greater */
+-		if (ALT_MEM_K < EXT_MEM_K) {
+-			mem_size = EXT_MEM_K;
+-			who = "BIOS-88";
+-		} else {
+-			mem_size = ALT_MEM_K;
+-			who = "BIOS-e801";
+-		}
+-
+-		e820.nr_map = 0;
+-		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+-		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+-  	}
++	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
++		early_panic("Cannot find a valid memory map");
+ 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-	e820_print_map(who);
++	e820_print_map("BIOS-e820");
+ }
+ 
+ #else  /* CONFIG_XEN */
+@@ -685,20 +669,23 @@ void __init setup_memory_region(void)
+ 
+ 	sanitize_e820_map(map, (char *)&memmap.nr_entries);
+ 
+-	BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0);
++	if (copy_e820_map(map, (char)memmap.nr_entries) < 0)
++		early_panic("Cannot find a valid memory map");
+ 
+ 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+ 	e820_print_map("Xen");
+ }
+ #endif
+ 
+-void __init parse_memopt(char *p, char **from) 
+-{ 
++static int __init parse_memopt(char *p)
++{
+ 	int i;
+ 	unsigned long current_end;
+ 	unsigned long end;
+ 
+-	end_user_pfn = memparse(p, from);
++	if (!p)
++		return -EINVAL;
++	end_user_pfn = memparse(p, &p);
+ 	end_user_pfn >>= PAGE_SHIFT;	
+ 
+ 	end = end_user_pfn<<PAGE_SHIFT;
+@@ -715,27 +702,61 @@ void __init parse_memopt(char *p, char *
+ 		else
+ 			add_memory_region(current_end, end - current_end, E820_RAM);
+ 	}
++
++	return 0;
+ } 
++early_param("mem", parse_memopt);
+ 
+-void __init parse_memmapopt(char *p, char **from)
++static int userdef __initdata;
++
++static int __init parse_memmap_opt(char *p)
+ {
++	char *oldp;
+ 	unsigned long long start_at, mem_size;
+ 
+-	mem_size = memparse(p, from);
+-	p = *from;
++	if (!strcmp(p, "exactmap")) {
++#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.
++		 */
++		e820_register_active_regions(0, 0, -1UL);
++		saved_max_pfn = e820_end_of_ram();
++		remove_all_active_ranges();
++#endif
++		end_pfn_map = 0;
++		e820.nr_map = 0;
++		userdef = 1;
++		return 0;
++	}
++
++	oldp = p;
++	mem_size = memparse(p, &p);
++	if (p == oldp)
++		return -EINVAL;
+ 	if (*p == '@') {
+-		start_at = memparse(p+1, from);
++		start_at = memparse(p+1, &p);
+ 		add_memory_region(start_at, mem_size, E820_RAM);
+ 	} else if (*p == '#') {
+-		start_at = memparse(p+1, from);
++		start_at = memparse(p+1, &p);
+ 		add_memory_region(start_at, mem_size, E820_ACPI);
+ 	} else if (*p == '$') {
+-		start_at = memparse(p+1, from);
++		start_at = memparse(p+1, &p);
+ 		add_memory_region(start_at, mem_size, E820_RESERVED);
+ 	} else {
+ 		end_user_pfn = (mem_size >> PAGE_SHIFT);
+ 	}
+-	p = *from;
++	return *p == '\0' ? 0 : -EINVAL;
++}
++early_param("memmap", parse_memmap_opt);
++
++void finish_e820_parsing(void)
++{
++	if (userdef) {
++		printk(KERN_INFO "user-defined physical RAM map:\n");
++		e820_print_map("user");
++	}
+ }
+ 
+ unsigned long pci_mem_start = 0xaeedbabe;
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2007-06-12 13:13:01.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -244,20 +244,16 @@ void early_printk(const char *fmt, ...)
+ 
+ static int __initdata keep_early;
+ 
+-int __init setup_early_printk(char *opt)
++static int __init setup_early_printk(char *buf)
+ {
+-	char *space;
+-	char buf[256];
++	if (!buf)
++		return 0;
+ 
+ 	if (early_console_initialized)
+-		return 1;
+-
+-	strlcpy(buf,opt,sizeof(buf));
+-	space = strchr(buf, ' ');
+-	if (space)
+-		*space = 0;
++		return 0;
++	early_console_initialized = 1;
+ 
+-	if (strstr(buf,"keep"))
++	if (strstr(buf, "keep"))
+ 		keep_early = 1;
+ 
+ 	if (!strncmp(buf, "serial", 6)) {
+@@ -281,11 +277,12 @@ int __init setup_early_printk(char *opt)
+  		early_console = &simnow_console;
+  		keep_early = 1;
+ 	}
+-	early_console_initialized = 1;
+ 	register_console(early_console);
+ 	return 0;
+ }
+ 
++early_param("earlyprintk", setup_early_printk);
++
+ void __init disable_early_printk(void)
+ {
+ 	if (!early_console_initialized || !early_console)
+@@ -299,4 +296,3 @@ void __init disable_early_printk(void)
+ 	}
+ }
+ 
+-__setup("earlyprintk=", setup_early_printk);
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:45:48.000000000 +0100
+@@ -4,9 +4,6 @@
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
+  *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
+- * 
+- *  $Id$
+- *
+  *  Jun Nakajima <jun.nakajima@intel.com>
+  *  Asit Mallick <asit.k.mallick@intel.com>
+  *      Modified for Xen
+@@ -26,15 +23,25 @@
+  * at the top of the kernel process stack.	
+  * - partial stack frame: partially saved registers upto R11.
+  * - full stack frame: Like partial stack frame, but all register saved. 
+- *	
+- * TODO:	 
+- * - schedule it carefully for the final hardware.
++ *
++ * Some macro usage:
++ * - CFI macros are used to generate dwarf2 unwind information for better
++ * backtraces. They don't change any code.
++ * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
++ * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
++ * There are unfortunately lots of special cases where some registers
++ * not touched. The macro is a big mess that should be cleaned up.
++ * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
++ * Gives a full stack frame.
++ * - ENTRY/END Define functions in the symbol table.
++ * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
++ * frame that is otherwise undefined after a SYSCALL
++ * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
++ * - errorentry/paranoidentry/zeroentry - Define exception entry points.
+  */
+ 
+-#define ASSEMBLY 1
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+-#include <asm/smp.h>
+ #include <asm/cache.h>
+ #include <asm/errno.h>
+ #include <asm/dwarf2.h>
+@@ -117,6 +124,7 @@ NMI_MASK = 0x80000000
+ 	.macro	CFI_DEFAULT_STACK start=1,adj=0
+ 	.if \start
+ 	CFI_STARTPROC	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8 - \adj*ARGOFFSET
+ 	.else
+ 	CFI_DEF_CFA_OFFSET SS+8 - \adj*ARGOFFSET
+@@ -207,6 +215,7 @@ END(ret_from_fork)
+  */
+ 	.macro _frame ref
+ 	CFI_STARTPROC simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA rsp,SS+8-\ref
+ 	/*CFI_REL_OFFSET ss,SS-\ref*/
+ 	CFI_REL_OFFSET rsp,RSP-\ref
+@@ -334,6 +343,8 @@ tracesys:			 
+ 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	cmpq $__NR_syscall_max,%rax
++	movq $-ENOSYS,%rcx
++	cmova %rcx,%rax
+ 	ja  1f
+ 	movq %r10,%rcx	/* fixup for C */
+ 	call *sys_call_table(,%rax,8)
+@@ -349,6 +360,7 @@ END(system_call)
+  */ 	
+ ENTRY(int_ret_from_sys_call)
+ 	CFI_STARTPROC	simple
++	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
+ 	/*CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
+ 	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
+@@ -583,8 +595,7 @@ retint_signal:
+ #ifdef CONFIG_PREEMPT
+ 	/* Returning to kernel space. Check if we need preemption */
+ 	/* rcx:	 threadinfo. interrupts off. */
+-	.p2align
+-retint_kernel:	
++ENTRY(retint_kernel)
+ 	cmpl $0,threadinfo_preempt_count(%rcx)
+ 	jnz  retint_restore_args
+ 	bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
+@@ -644,7 +655,6 @@ ENTRY(call_function_interrupt)
+ END(call_function_interrupt)
+ #endif
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC	
+ ENTRY(apic_timer_interrupt)
+ 	apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
+ END(apic_timer_interrupt)
+@@ -656,7 +666,6 @@ END(error_interrupt)
+ ENTRY(spurious_interrupt)
+ 	apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
+ END(spurious_interrupt)
+-#endif
+ #endif /* !CONFIG_XEN */
+ 				
+ /*
+@@ -755,7 +764,9 @@ paranoid_exit\trace:
+ 	testl $3,CS(%rsp)
+ 	jnz   paranoid_userspace\trace
+ paranoid_swapgs\trace:
++	.if \trace
+ 	TRACE_IRQS_IRETQ 0
++	.endif
+ 	swapgs
+ paranoid_restore\trace:
+ 	RESTORE_ALL 8
+@@ -802,7 +813,7 @@ paranoid_schedule\trace:
+  * Exception entry point. This expects an error code/orig_rax on the stack
+  * and the exception handler in %rax.	
+  */ 		  				
+-ENTRY(error_entry)
++KPROBE_ENTRY(error_entry)
+ 	_frame RDI
+ 	CFI_REL_OFFSET rax,0
+ 	/* rdi slot contains rax, oldrax contains error code */
+@@ -896,7 +907,7 @@ error_kernelspace:
+ 	jmp  error_sti
+ #endif
+ 	CFI_ENDPROC
+-END(error_entry)
++KPROBE_END(error_entry)
+ 	
+ ENTRY(hypervisor_callback)
+ 	zeroentry do_hypervisor_callback
+@@ -936,26 +947,6 @@ ENTRY(do_hypervisor_callback)   # do_hyp
+ 	CFI_ENDPROC
+ END(do_hypervisor_callback)
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-KPROBE_ENTRY(nmi)
+-	zeroentry do_nmi_callback
+-ENTRY(do_nmi_callback)
+-	CFI_STARTPROC
+-        addq $8, %rsp
+-	CFI_ENDPROC
+-	CFI_DEFAULT_STACK
+-        call do_nmi
+-        orl  $NMI_MASK,EFLAGS(%rsp)
+-        RESTORE_REST
+-        XEN_BLOCK_EVENTS(%rsi)
+-	TRACE_IRQS_OFF
+-        GET_THREAD_INFO(%rcx)
+-        jmp  retint_restore_args
+-	CFI_ENDPROC
+-	.previous .text
+-END(nmi)
+-#endif
+-
+         ALIGN
+ restore_all_enable_events:  
+ 	CFI_DEFAULT_STACK adj=1
+@@ -1121,7 +1112,7 @@ ENDPROC(child_rip)
+  * do_sys_execve asm fallback arguments:
+  *	rdi: name, rsi: argv, rdx: envp, fake frame on the stack
+  */
+-ENTRY(execve)
++ENTRY(kernel_execve)
+ 	CFI_STARTPROC
+ 	FAKE_STACK_FRAME $0
+ 	SAVE_ALL	
+@@ -1135,12 +1126,11 @@ ENTRY(execve)
+ 	UNFAKE_STACK_FRAME
+ 	ret
+ 	CFI_ENDPROC
+-ENDPROC(execve)
++ENDPROC(kernel_execve)
+ 
+ KPROBE_ENTRY(page_fault)
+ 	errorentry do_page_fault
+-END(page_fault)
+-	.previous .text
++KPROBE_END(page_fault)
+ 
+ ENTRY(coprocessor_error)
+ 	zeroentry do_coprocessor_error
+@@ -1162,25 +1152,25 @@ KPROBE_ENTRY(debug)
+ 	zeroentry do_debug
+ /*	paranoidexit
+ 	CFI_ENDPROC */
+-END(debug)
+-	.previous .text
++KPROBE_END(debug)
+ 
+-#if 0
+-	/* runs on exception stack */	
+ KPROBE_ENTRY(nmi)
+-	INTR_FRAME
+-	pushq $-1
+-	CFI_ADJUST_CFA_OFFSET 8
+-	paranoidentry do_nmi, 0, 0
+-#ifdef CONFIG_TRACE_IRQFLAGS
+-	paranoidexit 0
+-#else
+-	jmp paranoid_exit1
+- 	CFI_ENDPROC
+-#endif
+-END(nmi)
+-	.previous .text
+-#endif        
++	zeroentry do_nmi_callback
++KPROBE_END(nmi)
++do_nmi_callback:
++	CFI_STARTPROC
++	addq $8, %rsp
++	CFI_ENDPROC
++	CFI_DEFAULT_STACK
++	call do_nmi
++	orl  $NMI_MASK,EFLAGS(%rsp)
++	RESTORE_REST
++	XEN_BLOCK_EVENTS(%rsi)
++	TRACE_IRQS_OFF
++	GET_THREAD_INFO(%rcx)
++	jmp  retint_restore_args
++	CFI_ENDPROC
++END(do_nmi_callback)
+ 
+ KPROBE_ENTRY(int3)
+ /* 	INTR_FRAME
+@@ -1189,8 +1179,7 @@ KPROBE_ENTRY(int3)
+  	zeroentry do_int3
+ /* 	jmp paranoid_exit1
+  	CFI_ENDPROC */
+-END(int3)
+-	.previous .text
++KPROBE_END(int3)
+ 
+ ENTRY(overflow)
+ 	zeroentry do_overflow
+@@ -1241,8 +1230,7 @@ END(stack_segment)
+ 
+ KPROBE_ENTRY(general_protection)
+ 	errorentry do_general_protection
+-END(general_protection)
+-	.previous .text
++KPROBE_END(general_protection)
+ 
+ ENTRY(alignment_check)
+ 	errorentry do_alignment_check
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:45:48.000000000 +0100
+@@ -5,9 +5,6 @@
+  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
+  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
+  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
+- *
+- *  $Id: head.S,v 1.49 2002/03/19 17:39:25 ak Exp $
+- *
+  *  Jun Nakajima <jun.nakajima@intel.com>
+  *    Modified for Xen                                
+  */
+@@ -146,7 +143,7 @@ ENTRY(cpu_gdt_table)
+ 	.quad	0,0			/* TSS */
+ 	.quad	0,0			/* LDT */
+ 	.quad   0,0,0			/* three TLS descriptors */
+-	.quad	0			/* unused */
++	.quad	0x0000f40000000000	/* node/CPU stored in limit */
+ gdt_end:
+ 	/* asm/segment.h:GDT_ENTRIES must match this */
+ 	/* This should be a multiple of the cache line size */
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2007-06-12 13:13:01.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -7,6 +7,9 @@
+  *	Modified for Xen.
+  */
+ 
++/* PDA is not ready to be used until the end of x86_64_start_kernel(). */
++#define arch_use_lazy_mmu_mode() false
++
+ #include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <linux/types.h>
+@@ -54,11 +57,9 @@ static void __init copy_bootdata(char *r
+ 	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);
+@@ -70,25 +71,6 @@ static void __init copy_bootdata(char *r
+ 	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>
+@@ -101,7 +83,6 @@ void __init x86_64_start_kernel(char * r
+ {
+ 	struct xen_machphys_mapping mapping;
+ 	unsigned long machine_to_phys_nr_ents;
+-	char *s;
+ 	int i;
+ 
+ 	setup_xen_features();
+@@ -128,10 +109,7 @@ void __init x86_64_start_kernel(char * r
+ 	asm volatile("lidt %0" :: "m" (idt_descr));
+ #endif
+ 
+-	/*
+-	 * This must be called really, really early:
+-	 */
+-	lockdep_init();
++	early_printk("Kernel alive\n");
+ 
+  	for (i = 0; i < NR_CPUS; i++)
+  		cpu_pda(i) = &boot_cpu_pda[i];
+@@ -141,22 +119,5 @@ void __init x86_64_start_kernel(char * r
+ #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();
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -26,9 +26,12 @@
+ #include <linux/delay.h>
+ #include <linux/sched.h>
+ #include <linux/smp_lock.h>
++#include <linux/pci.h>
+ #include <linux/mc146818rtc.h>
+ #include <linux/acpi.h>
+ #include <linux/sysdev.h>
++#include <linux/msi.h>
++#include <linux/htirq.h>
+ #ifdef CONFIG_ACPI
+ #include <acpi/acpi_bus.h>
+ #endif
+@@ -41,6 +44,10 @@
+ #include <asm/acpi.h>
+ #include <asm/dma.h>
+ #include <asm/nmi.h>
++#include <asm/msidef.h>
++#include <asm/hypertransport.h>
++
++static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
+ 
+ #define __apicdebuginit  __init
+ 
+@@ -48,17 +55,30 @@ int sis_apic_bug; /* not actually suppor
+ 
+ static int no_timer_check;
+ 
+-int disable_timer_pin_1 __initdata;
++static int disable_timer_pin_1 __initdata;
+ 
+-#ifndef CONFIG_XEN
+-int timer_over_8254 __initdata = 0;
++#ifdef CONFIG_XEN
++#include <xen/interface/xen.h>
++#include <xen/interface/physdev.h>
++#include <xen/evtchn.h>
++
++/* Fake i8259 */
++#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
++#define disable_8259A_irq(_irq)  ((void)0)
++#define i8259A_irq_pending(_irq) (0)
++
++unsigned long io_apic_irqs;
++
++#define clear_IO_APIC() ((void)0)
++#else
++int timer_over_8254 __initdata = 1;
+ 
+ /* Where if anywhere is the i8259 connect in external int mode */
+ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+ #endif
+ 
+ static DEFINE_SPINLOCK(ioapic_lock);
+-static DEFINE_SPINLOCK(vector_lock);
++DEFINE_SPINLOCK(vector_lock);
+ 
+ /*
+  * # of IRQ routing registers
+@@ -83,29 +103,27 @@ static struct irq_pin_list {
+ 	short apic, pin, next;
+ } irq_2_pin[PIN_MAP_SIZE];
+ 
+-int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
+-#ifdef CONFIG_PCI_MSI
+-#define vector_to_irq(vector) 	\
+-	(platform_legacy_irq(vector) ? vector : vector_irq[vector])
+-#else
+-#define vector_to_irq(vector)	(vector)
+-#endif
+-
+-#ifdef CONFIG_XEN
+-
+-#include <xen/interface/xen.h>
+-#include <xen/interface/physdev.h>
+-#include <xen/evtchn.h>
+-
+-/* Fake i8259 */
+-#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
+-#define disable_8259A_irq(_irq)  ((void)0)
+-#define i8259A_irq_pending(_irq) (0)
++#ifndef CONFIG_XEN
++struct io_apic {
++	unsigned int index;
++	unsigned int unused[3];
++	unsigned int data;
++};
+ 
+-unsigned long io_apic_irqs;
++static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
++{
++	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
++		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
++}
++#endif
+ 
+-static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
++static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+ {
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	return readl(&io_apic->data);
++#else
+ 	struct physdev_apic apic_op;
+ 	int ret;
+ 
+@@ -115,31 +133,133 @@ static inline unsigned int xen_io_apic_r
+ 	if (ret)
+ 		return ret;
+ 	return apic_op.value;
++#endif
+ }
+ 
+-static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
++static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+ {
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	writel(value, &io_apic->data);
++#else
+ 	struct physdev_apic apic_op;
+ 
+ 	apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+ 	apic_op.reg = reg;
+ 	apic_op.value = value;
+ 	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
++#endif
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Re-write a value: to be used for read-modify-write
++ * cycles where the read already set up the index register.
++ */
++static inline void io_apic_modify(unsigned int apic, unsigned int value)
++{
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(value, &io_apic->data);
+ }
++#else
++#define io_apic_modify io_apic_write
++#endif
+ 
+-#define io_apic_read(a,r)    xen_io_apic_read(a,r)
+-#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
++/*
++ * Synchronize the IO-APIC and the CPU by doing
++ * a dummy read from the IO-APIC
++ */
++static inline void io_apic_sync(unsigned int apic)
++{
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	readl(&io_apic->data);
++#endif
++}
+ 
+-#define clear_IO_APIC() ((void)0)
++union entry_union {
++	struct { u32 w1, w2; };
++	struct IO_APIC_route_entry entry;
++};
+ 
+-#else
++#ifndef CONFIG_XEN
++static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
++{
++	union entry_union eu;
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
++	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	return eu.entry;
++}
++#endif
++
++/*
++ * When we write a new IO APIC routing entry, we need to write the high
++ * word first! If the mask bit in the low word is clear, we will enable
++ * the interrupt, and we need to make sure the entry is fully populated
++ * before that happens.
++ */
++static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	unsigned long flags;
++	union entry_union eu;
++	eu.entry = e;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#ifndef CONFIG_XEN
++/*
++ * When we mask an IO APIC routing entry, we need to write the low
++ * word first, in order to set the mask bit before we change the
++ * high bits!
++ */
++static void ioapic_mask_entry(int apic, int pin)
++{
++	unsigned long flags;
++	union entry_union eu = { .entry.mask = 1 };
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
+ 
+ #ifdef CONFIG_SMP
++static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
++{
++	int apic, pin;
++	struct irq_pin_list *entry = irq_2_pin + irq;
++
++	BUG_ON(irq >= NR_IRQS);
++	for (;;) {
++		unsigned int reg;
++		apic = entry->apic;
++		pin = entry->pin;
++		if (pin == -1)
++			break;
++		io_apic_write(apic, 0x11 + pin*2, dest);
++		reg = io_apic_read(apic, 0x10 + pin*2);
++		reg &= ~0x000000ff;
++		reg |= vector;
++		io_apic_modify(apic, reg);
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++}
++
+ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+ {
+ 	unsigned long flags;
+ 	unsigned int dest;
+ 	cpumask_t tmp;
++	int vector;
+ 
+ 	cpus_and(tmp, mask, cpu_online_map);
+ 	if (cpus_empty(tmp))
+@@ -147,7 +267,11 @@ static void set_ioapic_affinity_irq(unsi
+ 
+ 	cpus_and(mask, tmp, CPU_MASK_ALL);
+ 
+-	dest = cpu_mask_to_apicid(mask);
++	vector = assign_irq_vector(irq, mask, &tmp);
++	if (vector < 0)
++		return;
++
++	dest = cpu_mask_to_apicid(tmp);
+ 
+ 	/*
+ 	 * Only the high 8 bits are valid.
+@@ -155,13 +279,12 @@ static void set_ioapic_affinity_irq(unsi
+ 	dest = SET_APIC_LOGICAL_ID(dest);
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	__DO_ACTION(1, = dest, )
+-	set_irq_info(irq, mask);
++	__target_IO_APIC_irq(irq, dest, vector);
++	set_native_irq_info(irq, mask);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ #endif
+-
+-#endif /* !CONFIG_XEN */
++#endif
+ 
+ /*
+  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+@@ -241,24 +364,15 @@ static void unmask_IO_APIC_irq (unsigned
+ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+ 
+ 	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	*(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-	*(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	entry = ioapic_read_entry(apic, pin);
+ 	if (entry.delivery_mode == dest_SMI)
+ 		return;
+ 	/*
+ 	 * Disable it in the IO-APIC irq-routing table:
+ 	 */
+-	memset(&entry, 0, sizeof(entry));
+-	entry.mask = 1;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
+-	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	ioapic_mask_entry(apic, pin);
+ }
+ 
+ static void clear_IO_APIC (void)
+@@ -272,16 +386,6 @@ static void clear_IO_APIC (void)
+ 
+ #endif /* !CONFIG_XEN */
+ 
+-static u8 gsi_2_irq[NR_IRQ_VECTORS] = { [0 ... NR_IRQ_VECTORS-1] = 0xFF };
+-
+-/*
+- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
+- * specific CPU-side IRQs.
+- */
+-
+-#define MAX_PIRQS 8
+-static int pirq_entries [MAX_PIRQS];
+-static int pirqs_enabled;
+ int skip_ioapic_setup;
+ int ioapic_force;
+ 
+@@ -290,18 +394,17 @@ int ioapic_force;
+ static int __init disable_ioapic_setup(char *str)
+ {
+ 	skip_ioapic_setup = 1;
+-	return 1;
++	return 0;
+ }
++early_param("noapic", disable_ioapic_setup);
+ 
+-static int __init enable_ioapic_setup(char *str)
++/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
++static int __init disable_timer_pin_setup(char *arg)
+ {
+-	ioapic_force = 1;
+-	skip_ioapic_setup = 0;
++	disable_timer_pin_1 = 1;
+ 	return 1;
+ }
+-
+-__setup("noapic", disable_ioapic_setup);
+-__setup("apic", enable_ioapic_setup);
++__setup("disable_timer_pin_1", disable_timer_pin_setup);
+ 
+ #ifndef CONFIG_XEN
+ static int __init setup_disable_8254_timer(char *s)
+@@ -319,137 +422,6 @@ __setup("disable_8254_timer", setup_disa
+ __setup("enable_8254_timer", setup_enable_8254_timer);
+ #endif /* !CONFIG_XEN */
+ 
+-#include <asm/pci-direct.h>
+-#include <linux/pci_ids.h>
+-#include <linux/pci.h>
+-
+-
+-#ifdef CONFIG_ACPI
+-
+-static int nvidia_hpet_detected __initdata;
+-
+-static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+-{
+-	nvidia_hpet_detected = 1;
+-	return 0;
+-}
+-#endif
+-
+-/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
+-   off. Check for an Nvidia or VIA PCI bridge and turn it off.
+-   Use pci direct infrastructure because this runs before the PCI subsystem. 
+-
+-   Can be overwritten with "apic"
+-
+-   And another hack to disable the IOMMU on VIA chipsets.
+-
+-   ... and others. Really should move this somewhere else.
+-
+-   Kludge-O-Rama. */
+-void __init check_ioapic(void) 
+-{ 
+-	int num,slot,func; 
+-	/* Poor man's PCI discovery */
+-	for (num = 0; num < 32; num++) { 
+-		for (slot = 0; slot < 32; slot++) { 
+-			for (func = 0; func < 8; func++) { 
+-				u32 class;
+-				u32 vendor;
+-				u8 type;
+-				class = read_pci_config(num,slot,func,
+-							PCI_CLASS_REVISION);
+-				if (class == 0xffffffff)
+-					break; 
+-
+-		       		if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+-					continue; 
+-
+-				vendor = read_pci_config(num, slot, func, 
+-							 PCI_VENDOR_ID);
+-				vendor &= 0xffff;
+-				switch (vendor) { 
+-				case PCI_VENDOR_ID_VIA:
+-#ifdef CONFIG_IOMMU
+-					if ((end_pfn > MAX_DMA32_PFN ||
+-					     force_iommu) &&
+-					    !iommu_aperture_allowed) {
+-						printk(KERN_INFO
+-    "Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
+-						iommu_aperture_disabled = 1;
+-					}
+-#endif
+-					return;
+-				case PCI_VENDOR_ID_NVIDIA:
+-#ifdef CONFIG_ACPI
+-					/*
+-					 * All timer overrides on Nvidia are
+-					 * wrong unless HPET is enabled.
+-					 */
+-					nvidia_hpet_detected = 0;
+-					acpi_table_parse(ACPI_HPET,
+-							nvidia_hpet_check);
+-					if (nvidia_hpet_detected == 0) {
+-						acpi_skip_timer_override = 1;
+-						printk(KERN_INFO "Nvidia board "
+-						    "detected. Ignoring ACPI "
+-						    "timer override.\n");
+-					}
+-#endif
+-					/* RED-PEN skip them on mptables too? */
+-					return;
+-				case PCI_VENDOR_ID_ATI:
+-
+-				/* This should be actually default, but
+-				   for 2.6.16 let's do it for ATI only where
+-				   it's really needed. */
+-#ifndef CONFIG_XEN
+-					if (timer_over_8254 == 1) {	
+-						timer_over_8254 = 0;	
+-					printk(KERN_INFO
+-		"ATI board detected. Disabling timer routing over 8254.\n");
+-					}	
+-#endif
+-					return;
+-				} 
+-
+-
+-				/* No multi-function device? */
+-				type = read_pci_config_byte(num,slot,func,
+-							    PCI_HEADER_TYPE);
+-				if (!(type & 0x80))
+-					break;
+-			} 
+-		}
+-	}
+-} 
+-
+-static int __init ioapic_pirq_setup(char *str)
+-{
+-	int i, max;
+-	int ints[MAX_PIRQS+1];
+-
+-	get_options(str, ARRAY_SIZE(ints), ints);
+-
+-	for (i = 0; i < MAX_PIRQS; i++)
+-		pirq_entries[i] = -1;
+-
+-	pirqs_enabled = 1;
+-	apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
+-	max = MAX_PIRQS;
+-	if (ints[0] < MAX_PIRQS)
+-		max = ints[0];
+-
+-	for (i = 0; i < max; i++) {
+-		apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+-		/*
+-		 * PIRQs are mapped upside down, usually.
+-		 */
+-		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+-	}
+-	return 1;
+-}
+-
+-__setup("pirq=", ioapic_pirq_setup);
+ 
+ /*
+  * Find the IRQ entry number of a certain pin.
+@@ -479,9 +451,7 @@ static int __init find_isa_irq_pin(int i
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 
+@@ -497,9 +467,7 @@ static int __init find_isa_irq_apic(int 
+ 	for (i = 0; i < mp_irq_entries; i++) {
+ 		int lbus = mp_irqs[i].mpc_srcbus;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
++		if (test_bit(lbus, mp_bus_not_pci) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+ 			break;
+@@ -540,7 +508,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 			    mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
+ 				break;
+ 
+-		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
++		if (!test_bit(lbus, mp_bus_not_pci) &&
+ 		    !mp_irqs[i].mpc_irqtype &&
+ 		    (bus == lbus) &&
+ 		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+@@ -563,27 +531,6 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ 	return best_guess;
+ }
+ 
+-/*
+- * EISA Edge/Level control register, ELCR
+- */
+-static int EISA_ELCR(unsigned int irq)
+-{
+-	if (irq < 16) {
+-		unsigned int port = 0x4d0 + (irq >> 3);
+-		return (inb(port) >> (irq & 7)) & 1;
+-	}
+-	apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
+-	return 0;
+-}
+-
+-/* EISA interrupts are always polarity zero and can be edge or level
+- * trigger depending on the ELCR value.  If an interrupt is listed as
+- * EISA conforming in the MP table, that means its trigger type must
+- * be read in from the ELCR */
+-
+-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
+-#define default_EISA_polarity(idx)	(0)
+-
+ /* ISA interrupts are always polarity zero edge triggered,
+  * when listed as conforming in the MP table. */
+ 
+@@ -596,12 +543,6 @@ static int EISA_ELCR(unsigned int irq)
+ #define default_PCI_trigger(idx)	(1)
+ #define default_PCI_polarity(idx)	(1)
+ 
+-/* MCA interrupts are always polarity zero level triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_MCA_trigger(idx)	(1)
+-#define default_MCA_polarity(idx)	(0)
+-
+ static int __init MPBIOS_polarity(int idx)
+ {
+ 	int bus = mp_irqs[idx].mpc_srcbus;
+@@ -613,38 +554,11 @@ static int __init MPBIOS_polarity(int id
+ 	switch (mp_irqs[idx].mpc_irqflag & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent polarity */
+-		{
+-			switch (mp_bus_id_to_type[bus])
+-			{
+-				case MP_BUS_ISA: /* ISA pin */
+-				{
+-					polarity = default_ISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_EISA: /* EISA pin */
+-				{
+-					polarity = default_EISA_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_PCI: /* PCI pin */
+-				{
+-					polarity = default_PCI_polarity(idx);
+-					break;
+-				}
+-				case MP_BUS_MCA: /* MCA pin */
+-				{
+-					polarity = default_MCA_polarity(idx);
+-					break;
+-				}
+-				default:
+-				{
+-					printk(KERN_WARNING "broken BIOS!!\n");
+-					polarity = 1;
+-					break;
+-				}
+-			}
++			if (test_bit(bus, mp_bus_not_pci))
++				polarity = default_ISA_polarity(idx);
++			else
++				polarity = default_PCI_polarity(idx);
+ 			break;
+-		}
+ 		case 1: /* high active */
+ 		{
+ 			polarity = 0;
+@@ -682,38 +596,11 @@ static int MPBIOS_trigger(int idx)
+ 	switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
+ 	{
+ 		case 0: /* conforms, ie. bus-type dependent */
+-		{
+-			switch (mp_bus_id_to_type[bus])
+-			{
+-				case MP_BUS_ISA: /* ISA pin */
+-				{
+-					trigger = default_ISA_trigger(idx);
+-					break;
+-				}
+-				case MP_BUS_EISA: /* EISA pin */
+-				{
+-					trigger = default_EISA_trigger(idx);
+-					break;
+-				}
+-				case MP_BUS_PCI: /* PCI pin */
+-				{
+-					trigger = default_PCI_trigger(idx);
+-					break;
+-				}
+-				case MP_BUS_MCA: /* MCA pin */
+-				{
+-					trigger = default_MCA_trigger(idx);
+-					break;
+-				}
+-				default:
+-				{
+-					printk(KERN_WARNING "broken BIOS!!\n");
+-					trigger = 1;
+-					break;
+-				}
+-			}
++			if (test_bit(bus, mp_bus_not_pci))
++				trigger = default_ISA_trigger(idx);
++			else
++				trigger = default_PCI_trigger(idx);
+ 			break;
+-		}
+ 		case 1: /* edge */
+ 		{
+ 			trigger = 0;
+@@ -750,64 +637,6 @@ static inline int irq_trigger(int idx)
+ 	return MPBIOS_trigger(idx);
+ }
+ 
+-static int next_irq = 16;
+-
+-/*
+- * gsi_irq_sharing -- Name overload!  "irq" can be either a legacy IRQ
+- * in the range 0-15, a linux IRQ in the range 0-223, or a GSI number
+- * from ACPI, which can reach 800 in large boxen.
+- *
+- * Compact the sparse GSI space into a sequential IRQ series and reuse
+- * vectors if possible.
+- */
+-int gsi_irq_sharing(int gsi)
+-{
+-	int i, tries, vector;
+-
+-	BUG_ON(gsi >= NR_IRQ_VECTORS);
+-
+-	if (platform_legacy_irq(gsi))
+-		return gsi;
+-
+-	if (gsi_2_irq[gsi] != 0xFF)
+-		return (int)gsi_2_irq[gsi];
+-
+-	tries = NR_IRQS;
+-  try_again:
+-	vector = assign_irq_vector(gsi);
+-
+-	/*
+-	 * Sharing vectors means sharing IRQs, so scan irq_vectors for previous
+-	 * use of vector and if found, return that IRQ.  However, we never want
+-	 * to share legacy IRQs, which usually have a different trigger mode
+-	 * than PCI.
+-	 */
+-	for (i = 0; i < NR_IRQS; i++)
+-		if (IO_APIC_VECTOR(i) == vector)
+-			break;
+-	if (platform_legacy_irq(i)) {
+-		if (--tries >= 0) {
+-			IO_APIC_VECTOR(i) = 0;
+-			goto try_again;
+-		}
+-		panic("gsi_irq_sharing: didn't find an IRQ using vector 0x%02X for GSI %d", vector, gsi);
+-	}
+-	if (i < NR_IRQS) {
+-		gsi_2_irq[gsi] = i;
+-		printk(KERN_INFO "GSI %d sharing vector 0x%02X and IRQ %d\n",
+-				gsi, vector, i);
+-		return i;
+-	}
+-
+-	i = next_irq++;
+-	BUG_ON(i >= NR_IRQS);
+-	gsi_2_irq[gsi] = i;
+-	IO_APIC_VECTOR(i) = vector;
+-	printk(KERN_INFO "GSI %d assigned vector 0x%02X and IRQ %d\n",
+-			gsi, vector, i);
+-	return i;
+-}
+-
+ static int pin_2_irq(int idx, int apic, int pin)
+ {
+ 	int irq, i;
+@@ -819,49 +648,16 @@ static int pin_2_irq(int idx, int apic, 
+ 	if (mp_irqs[idx].mpc_dstirq != pin)
+ 		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+ 
+-	switch (mp_bus_id_to_type[bus])
+-	{
+-		case MP_BUS_ISA: /* ISA pin */
+-		case MP_BUS_EISA:
+-		case MP_BUS_MCA:
+-		{
+-			irq = mp_irqs[idx].mpc_srcbusirq;
+-			break;
+-		}
+-		case MP_BUS_PCI: /* PCI pin */
+-		{
+-			/*
+-			 * PCI IRQs are mapped in order
+-			 */
+-			i = irq = 0;
+-			while (i < apic)
+-				irq += nr_ioapic_registers[i++];
+-			irq += pin;
+-			irq = gsi_irq_sharing(irq);
+-			break;
+-		}
+-		default:
+-		{
+-			printk(KERN_ERR "unknown bus type %d.\n",bus); 
+-			irq = 0;
+-			break;
+-		}
+-	}
+-	BUG_ON(irq >= NR_IRQS);
+-
+-	/*
+-	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
+-	 */
+-	if ((pin >= 16) && (pin <= 23)) {
+-		if (pirq_entries[pin-16] != -1) {
+-			if (!pirq_entries[pin-16]) {
+-				apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
+-			} else {
+-				irq = pirq_entries[pin-16];
+-				apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
+-						pin-16, irq);
+-			}
+-		}
++	if (test_bit(bus, mp_bus_not_pci)) {
++		irq = mp_irqs[idx].mpc_srcbusirq;
++	} else {
++		/*
++		 * PCI IRQs are mapped in order
++		 */
++		i = irq = 0;
++		while (i < apic)
++			irq += nr_ioapic_registers[i++];
++		irq += pin;
+ 	}
+ 	BUG_ON(irq >= NR_IRQS);
+ 	return irq;
+@@ -885,46 +681,71 @@ static inline int IO_APIC_irq_trigger(in
+ }
+ 
+ /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+-u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
++static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
+ 
+-int assign_irq_vector(int irq)
++static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+ {
+-	unsigned long flags;
+ 	int vector;
+ 	struct physdev_irq irq_op;
+   
+-  	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
++	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+ 
+ 	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+ 		return -EINVAL;
+ 
+-	spin_lock_irqsave(&vector_lock, flags);
++	cpus_and(*result, mask, cpu_online_map);
+ 
+-  	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+-		spin_unlock_irqrestore(&vector_lock, flags);
+-  		return IO_APIC_VECTOR(irq);
+-	}
++	if (irq_vector[irq] > 0)
++		return irq_vector[irq];
+ 
+ 	irq_op.irq = irq;
+-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+-		spin_unlock_irqrestore(&vector_lock, flags);
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+ 		return -ENOSPC;
+-	}
+ 
+ 	vector = irq_op.vector;
+-	vector_irq[vector] = irq;
+-	if (irq != AUTO_ASSIGN)
+-		IO_APIC_VECTOR(irq) = vector;
++	irq_vector[irq] = vector;
+ 
+-	spin_unlock_irqrestore(&vector_lock, flags);
++	return vector;
++}
++
++static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
++{
++	int vector;
++	unsigned long flags;
+ 
++	spin_lock_irqsave(&vector_lock, flags);
++	vector = __assign_irq_vector(irq, mask, result);
++	spin_unlock_irqrestore(&vector_lock, flags);
+ 	return vector;
+ }
+ 
+-extern void (*interrupt[NR_IRQS])(void);
+ #ifndef CONFIG_XEN
+-static struct hw_interrupt_type ioapic_level_type;
+-static struct hw_interrupt_type ioapic_edge_type;
++void __setup_vector_irq(int cpu)
++{
++	/* Initialize vector_irq on a new cpu */
++	/* This function must be called with vector_lock held */
++	int irq, vector;
++
++	/* Mark the inuse vectors */
++	for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
++		if (!cpu_isset(cpu, irq_domain[irq]))
++			continue;
++		vector = irq_vector[irq];
++		per_cpu(vector_irq, cpu)[vector] = irq;
++	}
++	/* Mark the free vectors */
++	for (vector = 0; vector < NR_VECTORS; ++vector) {
++		irq = per_cpu(vector_irq, cpu)[vector];
++		if (irq < 0)
++			continue;
++		if (!cpu_isset(cpu, irq_domain[irq]))
++			per_cpu(vector_irq, cpu)[vector] = -1;
++	}
++}
++
++extern void (*interrupt[NR_IRQS])(void);
++
++static struct irq_chip ioapic_chip;
+ 
+ #define IOAPIC_AUTO	-1
+ #define IOAPIC_EDGE	0
+@@ -932,16 +753,15 @@ static struct hw_interrupt_type ioapic_e
+ 
+ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+ {
+-	unsigned idx;
+-
+-	idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
+-
+ 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ 			trigger == IOAPIC_LEVEL)
+-		irq_desc[idx].chip = &ioapic_level_type;
+-	else
+-		irq_desc[idx].chip = &ioapic_edge_type;
+-	set_intr_gate(vector, interrupt[idx]);
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					      handle_fasteoi_irq, "fasteoi");
++	else {
++		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					      handle_edge_irq, "edge");
++	}
+ }
+ #else
+ #define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
+@@ -994,16 +814,21 @@ static void __init setup_IO_APIC_irqs(vo
+ 			continue;
+ 
+ 		if (IO_APIC_IRQ(irq)) {
+-			vector = assign_irq_vector(irq);
++			cpumask_t mask;
++			vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
++			if (vector < 0)
++				continue;
++
++			entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+ 			entry.vector = vector;
+ 
+ 			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
++		ioapic_write_entry(apic, pin, entry);
++
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+-		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+ 		set_native_irq_info(irq, TARGET_CPUS);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+@@ -1046,7 +871,7 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	 * The timer IRQ doesn't have to know that behind the
+ 	 * scene we have a 8259A-master in AEOI mode ...
+ 	 */
+-	irq_desc[0].chip = &ioapic_edge_type;
++	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+ 
+ 	/*
+ 	 * Add it to the IO-APIC irq-routing table:
+@@ -1142,10 +967,7 @@ void __apicdebuginit print_IO_APIC(void)
+ 	for (i = 0; i <= reg_01.bits.entries; i++) {
+ 		struct IO_APIC_route_entry entry;
+ 
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
+-		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		entry = ioapic_read_entry(apic, i);
+ 
+ 		printk(KERN_DEBUG " %02x %03X %02X  ",
+ 			i,
+@@ -1165,17 +987,12 @@ void __apicdebuginit print_IO_APIC(void)
+ 		);
+ 	}
+ 	}
+-	if (use_pci_vector())
+-		printk(KERN_INFO "Using vector-based indexing\n");
+ 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+ 	for (i = 0; i < NR_IRQS; i++) {
+ 		struct irq_pin_list *entry = irq_2_pin + i;
+ 		if (entry->pin < 0)
+ 			continue;
+- 		if (use_pci_vector() && !platform_legacy_irq(i))
+-			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));
+-		else
+-			printk(KERN_DEBUG "IRQ%d ", i);
++		printk(KERN_DEBUG "IRQ%d ", i);
+ 		for (;;) {
+ 			printk("-> %d:%d", entry->apic, entry->pin);
+ 			if (!entry->next)
+@@ -1339,9 +1156,6 @@ static void __init enable_IO_APIC(void)
+ 		irq_2_pin[i].pin = -1;
+ 		irq_2_pin[i].next = 0;
+ 	}
+-	if (!pirqs_enabled)
+-		for (i = 0; i < MAX_PIRQS; i++)
+-			pirq_entries[i] = -1;
+ 
+ 	/*
+ 	 * The number of IO-APIC IRQ registers (== #pins):
+@@ -1358,11 +1172,7 @@ static void __init enable_IO_APIC(void)
+ 		/* See if any of the pins is in ExtINT mode */
+ 		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ 			struct IO_APIC_route_entry entry;
+-			spin_lock_irqsave(&ioapic_lock, flags);
+-			*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+-			*(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+-			spin_unlock_irqrestore(&ioapic_lock, flags);
+-
++			entry = ioapic_read_entry(apic, pin);
+ 
+ 			/* If the interrupt line is enabled and in ExtInt mode
+ 			 * I have found the pin where the i8259 is connected.
+@@ -1416,7 +1226,6 @@ void disable_IO_APIC(void)
+ 	 */
+ 	if (ioapic_i8259.pin != -1) {
+ 		struct IO_APIC_route_entry entry;
+-		unsigned long flags;
+ 
+ 		memset(&entry, 0, sizeof(entry));
+ 		entry.mask            = 0; /* Enabled */
+@@ -1433,12 +1242,7 @@ void disable_IO_APIC(void)
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+ 		 */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
+-			*(((int *)&entry)+1));
+-		io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
+-			*(((int *)&entry)+0));
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
++		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+ 	}
+ 
+ 	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+@@ -1446,76 +1250,6 @@ void disable_IO_APIC(void)
+ }
+ 
+ /*
+- * function to set the IO-APIC physical IDs based on the
+- * values stored in the MPC table.
+- *
+- * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+- */
+-
+-#ifndef CONFIG_XEN
+-static void __init setup_ioapic_ids_from_mpc (void)
+-{
+-	union IO_APIC_reg_00 reg_00;
+-	int apic;
+-	int i;
+-	unsigned char old_id;
+-	unsigned long flags;
+-
+-	/*
+-	 * Set the IOAPIC ID to the value stored in the MPC table.
+-	 */
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-
+-		/* Read the register 0 value */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		
+-		old_id = mp_ioapics[apic].mpc_apicid;
+-
+-
+-		printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
+-
+-
+-		/*
+-		 * We need to adjust the IRQ routing table
+-		 * if the ID changed.
+-		 */
+-		if (old_id != mp_ioapics[apic].mpc_apicid)
+-			for (i = 0; i < mp_irq_entries; i++)
+-				if (mp_irqs[i].mpc_dstapic == old_id)
+-					mp_irqs[i].mpc_dstapic
+-						= mp_ioapics[apic].mpc_apicid;
+-
+-		/*
+-		 * Read the right value from the MPC table and
+-		 * write it into the ID register.
+-	 	 */
+-		apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
+-				mp_ioapics[apic].mpc_apicid);
+-
+-		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(apic, 0, reg_00.raw);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-		/*
+-		 * Sanity check
+-		 */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
+-			printk("could not set ID!\n");
+-		else
+-			apic_printk(APIC_VERBOSE," ok.\n");
+-	}
+-}
+-#else
+-static void __init setup_ioapic_ids_from_mpc(void) { }
+-#endif
+-
+-/*
+  * There is a nasty bug in some older SMP boards, their mptable lies
+  * about the timer IRQ. We do the following to work around the situation:
+  *
+@@ -1569,7 +1303,7 @@ static int __init timer_irq_works(void)
+  * an edge even if it isn't on the 8259A...
+  */
+ 
+-static unsigned int startup_edge_ioapic_irq(unsigned int irq)
++static unsigned int startup_ioapic_irq(unsigned int irq)
+ {
+ 	int was_pending = 0;
+ 	unsigned long flags;
+@@ -1586,107 +1320,19 @@ static unsigned int startup_edge_ioapic_
+ 	return was_pending;
+ }
+ 
+-/*
+- * Once we have recorded IRQ_PENDING already, we can mask the
+- * interrupt for real. This prevents IRQ storms from unhandled
+- * devices.
+- */
+-static void ack_edge_ioapic_irq(unsigned int irq)
+-{
+-	move_irq(irq);
+-	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
+-					== (IRQ_PENDING | IRQ_DISABLED))
+-		mask_IO_APIC_irq(irq);
+-	ack_APIC_irq();
+-}
+-
+-/*
+- * Level triggered interrupts can just be masked,
+- * and shutting down and starting up the interrupt
+- * is the same as enabling and disabling them -- except
+- * with a startup need to return a "was pending" value.
+- *
+- * Level triggered interrupts are special because we
+- * do not touch any IO-APIC register while handling
+- * them. We ack the APIC in the end-IRQ handler, not
+- * in the start-IRQ-handler. Protection against reentrance
+- * from the same interrupt is still provided, both by the
+- * generic IRQ layer and by the fact that an unacked local
+- * APIC does not accept IRQs.
+- */
+-static unsigned int startup_level_ioapic_irq (unsigned int irq)
+-{
+-	unmask_IO_APIC_irq(irq);
+-
+-	return 0; /* don't check for pending */
+-}
+-
+-static void end_level_ioapic_irq (unsigned int irq)
+-{
+-	move_irq(irq);
+-	ack_APIC_irq();
+-}
+-
+-#ifdef CONFIG_PCI_MSI
+-static unsigned int startup_edge_ioapic_vector(unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	return startup_edge_ioapic_irq(irq);
+-}
+-
+-static void ack_edge_ioapic_vector(unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	move_native_irq(vector);
+-	ack_edge_ioapic_irq(irq);
+-}
+-
+-static unsigned int startup_level_ioapic_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	return startup_level_ioapic_irq (irq);
+-}
+-
+-static void end_level_ioapic_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	move_native_irq(vector);
+-	end_level_ioapic_irq(irq);
+-}
+-
+-static void mask_IO_APIC_vector (unsigned int vector)
+-{
+-	int irq = vector_to_irq(vector);
+-
+-	mask_IO_APIC_irq(irq);
+-}
+-
+-static void unmask_IO_APIC_vector (unsigned int vector)
++static int ioapic_retrigger_irq(unsigned int irq)
+ {
+-	int irq = vector_to_irq(vector);
+-
+-	unmask_IO_APIC_irq(irq);
+-}
+-
+-#ifdef CONFIG_SMP
+-static void set_ioapic_affinity_vector (unsigned int vector,
+-					cpumask_t cpu_mask)
+-{
+-	int irq = vector_to_irq(vector);
++	cpumask_t mask;
++	unsigned vector;
++	unsigned long flags;
+ 
+-	set_native_irq_info(vector, cpu_mask);
+-	set_ioapic_affinity_irq(irq, cpu_mask);
+-}
+-#endif // CONFIG_SMP
+-#endif // CONFIG_PCI_MSI
++	spin_lock_irqsave(&vector_lock, flags);
++	vector = irq_vector[irq];
++	cpus_clear(mask);
++	cpu_set(first_cpu(irq_domain[irq]), mask);
+ 
+-static int ioapic_retrigger(unsigned int irq)
+-{
+-	send_IPI_self(IO_APIC_VECTOR(irq));
++	send_IPI_mask(mask, vector);
++	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return 1;
+ }
+@@ -1700,32 +1346,47 @@ static int ioapic_retrigger(unsigned int
+  * races.
+  */
+ 
+-static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
+-	.typename = "IO-APIC-edge",
+-	.startup 	= startup_edge_ioapic,
+-	.shutdown 	= shutdown_edge_ioapic,
+-	.enable 	= enable_edge_ioapic,
+-	.disable 	= disable_edge_ioapic,
+-	.ack 		= ack_edge_ioapic,
+-	.end 		= end_edge_ioapic,
+-#ifdef CONFIG_SMP
+-	.set_affinity = set_ioapic_affinity,
++static void ack_apic_edge(unsigned int irq)
++{
++	move_native_irq(irq);
++	ack_APIC_irq();
++}
++
++static void ack_apic_level(unsigned int irq)
++{
++	int do_unmask_irq = 0;
++
++#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
++	/* If we are moving the irq we need to mask it */
++	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
++		do_unmask_irq = 1;
++		mask_IO_APIC_irq(irq);
++	}
+ #endif
+-	.retrigger	= ioapic_retrigger,
+-};
+ 
+-static struct hw_interrupt_type ioapic_level_type __read_mostly = {
+-	.typename = "IO-APIC-level",
+-	.startup 	= startup_level_ioapic,
+-	.shutdown 	= shutdown_level_ioapic,
+-	.enable 	= enable_level_ioapic,
+-	.disable 	= disable_level_ioapic,
+-	.ack 		= mask_and_ack_level_ioapic,
+-	.end 		= end_level_ioapic,
++	/*
++	 * We must acknowledge the irq before we move it or the acknowledge will
++	 * not propogate properly.
++	 */
++	ack_APIC_irq();
++
++	/* Now we can move and renable the irq */
++	move_masked_irq(irq);
++	if (unlikely(do_unmask_irq))
++		unmask_IO_APIC_irq(irq);
++}
++
++static struct irq_chip ioapic_chip __read_mostly = {
++	.name 		= "IO-APIC",
++	.startup 	= startup_ioapic_irq,
++	.mask	 	= mask_IO_APIC_irq,
++	.unmask	 	= unmask_IO_APIC_irq,
++	.ack 		= ack_apic_edge,
++	.eoi 		= ack_apic_level,
+ #ifdef CONFIG_SMP
+-	.set_affinity = set_ioapic_affinity,
++	.set_affinity 	= set_ioapic_affinity_irq,
+ #endif
+-	.retrigger	= ioapic_retrigger,
++	.retrigger	= ioapic_retrigger_irq,
+ };
+ #endif /* !CONFIG_XEN */
+ 
+@@ -1746,12 +1407,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+ 		int tmp = irq;
+-		if (use_pci_vector()) {
+-			if (!platform_legacy_irq(tmp))
+-				if ((tmp = vector_to_irq(tmp)) == -1)
+-					continue;
+-		}
+-		if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
++		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -1762,7 +1418,7 @@ static inline void init_IO_APIC_traps(vo
+ #ifndef CONFIG_XEN
+ 			else
+ 				/* Strange. Oh, well.. */
+-				irq_desc[irq].chip = &no_irq_type;
++				irq_desc[irq].chip = &no_irq_chip;
+ #endif
+ 		}
+ 	}
+@@ -1883,8 +1539,6 @@ static inline void unlock_ExtINT_logic(v
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+-int timer_uses_ioapic_pin_0;
+-
+ /*
+  * This code may look a bit paranoid, but it's supposed to cooperate with
+  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+@@ -1897,13 +1551,13 @@ static inline void check_timer(void)
+ {
+ 	int apic1, pin1, apic2, pin2;
+ 	int vector;
++	cpumask_t mask;
+ 
+ 	/*
+ 	 * get/set the timer IRQ vector:
+ 	 */
+ 	disable_8259A_irq(0);
+-	vector = assign_irq_vector(0);
+-	set_intr_gate(vector, interrupt[0]);
++	vector = assign_irq_vector(0, TARGET_CPUS, &mask);
+ 
+ 	/*
+ 	 * Subtle, code in do_timer_interrupt() expects an AEOI
+@@ -1922,9 +1576,6 @@ static inline void check_timer(void)
+ 	pin2  = ioapic_i8259.pin;
+ 	apic2 = ioapic_i8259.apic;
+ 
+-	if (pin1 == 0)
+-		timer_uses_ioapic_pin_0 = 1;
+-
+ 	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ 		vector, apic1, pin1, apic2, pin2);
+ 
+@@ -2039,11 +1690,6 @@ void __init setup_IO_APIC(void)
+ 
+ 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ 
+-	/*
+-	 * Set up the IO-APIC IRQ routing table.
+-	 */
+-	if (!acpi_ioapic)
+-		setup_ioapic_ids_from_mpc();
+ #ifndef CONFIG_XEN
+ 	sync_Arb_IDs();
+ #endif /* !CONFIG_XEN */
+@@ -2066,17 +1712,12 @@ static int ioapic_suspend(struct sys_dev
+ {
+ 	struct IO_APIC_route_entry *entry;
+ 	struct sysfs_ioapic_data *data;
+-	unsigned long flags;
+ 	int i;
+ 
+ 	data = container_of(dev, struct sysfs_ioapic_data, dev);
+ 	entry = data->entry;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+-		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+-		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
++		*entry = ioapic_read_entry(dev->id, i);
+ 
+ 	return 0;
+ }
+@@ -2098,11 +1739,9 @@ static int ioapic_resume(struct sys_devi
+ 		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+ 		io_apic_write(dev->id, 0, reg_00.raw);
+ 	}
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+-		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+-		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+-	}
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
++		ioapic_write_entry(dev->id, i, entry[i]);
+ 
+ 	return 0;
+ }
+@@ -2148,28 +1787,254 @@ static int __init ioapic_init_sysfs(void
+ 
+ device_initcall(ioapic_init_sysfs);
+ 
++/*
++ * Dynamic irq allocate and deallocation
++ */
++int create_irq(void)
++{
++	/* Allocate an unused irq */
++	int irq;
++	int new;
++	int vector = 0;
++	unsigned long flags;
++	cpumask_t mask;
++
++	irq = -ENOSPC;
++	spin_lock_irqsave(&vector_lock, flags);
++	for (new = (NR_IRQS - 1); new >= 0; new--) {
++		if (platform_legacy_irq(new))
++			continue;
++		if (irq_vector[new] != 0)
++			continue;
++		vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
++		if (likely(vector > 0))
++			irq = new;
++		break;
++	}
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	if (irq >= 0) {
++		dynamic_irq_init(irq);
++	}
++	return irq;
++}
++
++void destroy_irq(unsigned int irq)
++{
++	unsigned long flags;
++
++	dynamic_irq_cleanup(irq);
++
++	spin_lock_irqsave(&vector_lock, flags);
++	irq_vector[irq] = 0;
++	spin_unlock_irqrestore(&vector_lock, flags);
++}
++
+ #endif /* CONFIG_XEN */
+ 
+-/* --------------------------------------------------------------------------
+-                          ACPI-based IOAPIC Configuration
+-   -------------------------------------------------------------------------- */
++/*
++ * MSI mesage composition
++ */
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
++static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
++{
++	int vector;
++	unsigned dest;
++	cpumask_t tmp;
+ 
+-#ifdef CONFIG_ACPI
++	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
++	if (vector >= 0) {
++		dest = cpu_mask_to_apicid(tmp);
++
++		msg->address_hi = MSI_ADDR_BASE_HI;
++		msg->address_lo =
++			MSI_ADDR_BASE_LO |
++			((INT_DEST_MODE == 0) ?
++				MSI_ADDR_DEST_MODE_PHYSICAL:
++				MSI_ADDR_DEST_MODE_LOGICAL) |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_ADDR_REDIRECTION_CPU:
++				MSI_ADDR_REDIRECTION_LOWPRI) |
++			MSI_ADDR_DEST_ID(dest);
++
++		msg->data =
++			MSI_DATA_TRIGGER_EDGE |
++			MSI_DATA_LEVEL_ASSERT |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_DATA_DELIVERY_FIXED:
++				MSI_DATA_DELIVERY_LOWPRI) |
++			MSI_DATA_VECTOR(vector);
++	}
++	return vector;
++}
+ 
+-#define IO_APIC_MAX_ID		0xFE
++#ifdef CONFIG_SMP
++static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++	int vector;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	cpus_and(mask, tmp, CPU_MASK_ALL);
++
++	vector = assign_irq_vector(irq, mask, &tmp);
++	if (vector < 0)
++		return;
++
++	dest = cpu_mask_to_apicid(tmp);
++
++	read_msi_msg(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+-int __init io_apic_get_version (int ioapic)
++	write_msi_msg(irq, &msg);
++	set_native_irq_info(irq, mask);
++}
++#endif /* CONFIG_SMP */
++
++/*
++ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI or MSI-X Capability Structure.
++ */
++static struct irq_chip msi_chip = {
++	.name		= "PCI-MSI",
++	.unmask		= unmask_msi_irq,
++	.mask		= mask_msi_irq,
++	.ack		= ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_msi_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+ {
+-	union IO_APIC_reg_01	reg_01;
+-	unsigned long flags;
++	struct msi_msg msg;
++	int ret;
++	ret = msi_compose_msg(dev, irq, &msg);
++	if (ret < 0)
++		return ret;
+ 
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_01.raw = io_apic_read(ioapic, 1);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	write_msi_msg(irq, &msg);
+ 
+-	return reg_01.bits.version;
++	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
++
++	return 0;
++}
++
++void arch_teardown_msi_irq(unsigned int irq)
++{
++	return;
+ }
+ 
++#endif /* CONFIG_PCI_MSI */
++
++/*
++ * Hypertransport interrupt support
++ */
++#ifdef CONFIG_HT_IRQ
++
++#ifdef CONFIG_SMP
++
++static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
++{
++	struct ht_irq_msg msg;
++	fetch_ht_irq_msg(irq, &msg);
++
++	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
++	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
++
++	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
++	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
++
++	write_ht_irq_msg(irq, &msg);
++}
++
++static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	unsigned int dest;
++	cpumask_t tmp;
++	int vector;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		tmp = TARGET_CPUS;
++
++	cpus_and(mask, tmp, CPU_MASK_ALL);
++
++	vector = assign_irq_vector(irq, mask, &tmp);
++	if (vector < 0)
++		return;
++
++	dest = cpu_mask_to_apicid(tmp);
++
++	target_ht_irq(irq, dest, vector);
++	set_native_irq_info(irq, mask);
++}
++#endif
++
++static struct irq_chip ht_irq_chip = {
++	.name		= "PCI-HT",
++	.mask		= mask_ht_irq,
++	.unmask		= unmask_ht_irq,
++	.ack		= ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_ht_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
++{
++	int vector;
++	cpumask_t tmp;
++
++	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
++	if (vector >= 0) {
++		struct ht_irq_msg msg;
++		unsigned dest;
++
++		dest = cpu_mask_to_apicid(tmp);
++
++		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
++
++		msg.address_lo =
++			HT_IRQ_LOW_BASE |
++			HT_IRQ_LOW_DEST_ID(dest) |
++			HT_IRQ_LOW_VECTOR(vector) |
++			((INT_DEST_MODE == 0) ?
++				HT_IRQ_LOW_DM_PHYSICAL :
++				HT_IRQ_LOW_DM_LOGICAL) |
++			HT_IRQ_LOW_RQEOI_EDGE |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				HT_IRQ_LOW_MT_FIXED :
++				HT_IRQ_LOW_MT_ARBITRATED) |
++			HT_IRQ_LOW_IRQ_MASKED;
++
++		write_ht_irq_msg(irq, &msg);
++
++		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
++					      handle_edge_irq, "edge");
++	}
++	return vector;
++}
++#endif /* CONFIG_HT_IRQ */
++
++/* --------------------------------------------------------------------------
++                          ACPI-based IOAPIC Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++#define IO_APIC_MAX_ID		0xFE
+ 
+ int __init io_apic_get_redir_entries (int ioapic)
+ {
+@@ -2188,6 +2053,8 @@ int io_apic_set_pci_routing (int ioapic,
+ {
+ 	struct IO_APIC_route_entry entry;
+ 	unsigned long flags;
++	int vector;
++	cpumask_t mask;
+ 
+ 	if (!IO_APIC_IRQ(irq)) {
+ 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+@@ -2196,6 +2063,17 @@ int io_apic_set_pci_routing (int ioapic,
+ 	}
+ 
+ 	/*
++	 * IRQs < 16 are already in the irq_2_pin[] map
++	 */
++	if (irq >= 16)
++		add_pin_to_irq(irq, ioapic, pin);
++
++
++	vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
++	if (vector < 0)
++		return vector;
++
++	/*
+ 	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
+ 	 * Note that we mask (disable) IRQs now -- these get enabled when the
+ 	 * corresponding device driver registers for this IRQ.
+@@ -2205,19 +2083,11 @@ int io_apic_set_pci_routing (int ioapic,
+ 
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.dest_mode = INT_DEST_MODE;
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+ 	entry.trigger = edge_level;
+ 	entry.polarity = active_high_low;
+ 	entry.mask = 1;					 /* Disabled (masked) */
+-
+-	irq = gsi_irq_sharing(irq);
+-	/*
+-	 * IRQs < 16 are already in the irq_2_pin[] map
+-	 */
+-	if (irq >= 16)
+-		add_pin_to_irq(irq, ioapic, pin);
+-
+-	entry.vector = assign_irq_vector(irq);
++	entry.vector = vector & 0xff;
+ 
+ 	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+ 		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
+@@ -2229,10 +2099,10 @@ int io_apic_set_pci_routing (int ioapic,
+ 	if (!ioapic && (irq < 16))
+ 		disable_8259A_irq(irq);
+ 
++	ioapic_write_entry(ioapic, pin, entry);
++
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
+-	io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
+-	set_native_irq_info(use_pci_vector() ?  entry.vector : irq, TARGET_CPUS);
++	set_native_irq_info(irq, TARGET_CPUS);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	return 0;
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_64-xen.c	2008-01-28 12:24:19.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -58,6 +58,7 @@ asmlinkage long sys_ioperm(unsigned long
+ 
+ 		memset(bitmap, 0xff, IO_BITMAP_BYTES);
+ 		t->io_bitmap_ptr = bitmap;
++		set_thread_flag(TIF_IO_BITMAP);
+ 
+ 		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
+ 		set_iobitmap.nr_ports = IO_BITMAP_BITS;
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -20,11 +20,6 @@
+ #include <asm/idle.h>
+ 
+ atomic_t irq_err_count;
+-#ifdef CONFIG_X86_IO_APIC
+-#ifdef APIC_MISMATCH_DEBUG
+-atomic_t irq_mis_count;
+-#endif
+-#endif
+ 
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /*
+@@ -79,7 +74,8 @@ int show_interrupts(struct seq_file *p, 
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ #endif
+-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
++		seq_printf(p, " %8s", irq_desc[i].chip->name);
++		seq_printf(p, "-%-8s", irq_desc[i].name);
+ 
+ 		seq_printf(p, "  %s", action->name);
+ 		for (action=action->next; action; action = action->next)
+@@ -99,11 +95,6 @@ skip:
+ 		seq_putc(p, '\n');
+ #endif
+ 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+-#ifdef CONFIG_X86_IO_APIC
+-#ifdef APIC_MISMATCH_DEBUG
+-		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+-#endif
+-#endif
+ 	}
+ 	return 0;
+ }
+@@ -114,24 +105,28 @@ skip:
+  * handlers).
+  */
+ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
+-{	
++{
++	struct pt_regs *old_regs = set_irq_regs(regs);
++
+ 	/* high bit used in ret_from_ code  */
+ 	unsigned irq = ~regs->orig_rax;
+ 
+-	if (unlikely(irq >= NR_IRQS)) {
+-		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+-					__FUNCTION__, irq);
+-		BUG();
+-	}
+-
+ 	/*exit_idle();*/
+ 	/*irq_enter();*/
++
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ 	stack_overflow_check(regs);
+ #endif
+-	__do_IRQ(irq, regs);
++
++	if (likely(irq < NR_IRQS))
++		generic_handle_irq(irq);
++	else
++		printk(KERN_EMERG "%s: %d.%d No irq handler for irq\n",
++			__func__, smp_processor_id(), irq);
++
+ 	/*irq_exit();*/
+ 
++	set_irq_regs(old_regs);
+ 	return 1;
+ }
+ 
+@@ -192,6 +187,6 @@ EXPORT_SYMBOL(do_softirq);
+  */
+ void ack_bad_irq(unsigned int irq)
+ {
+-        printk("unexpected IRQ trap at vector %02x\n", irq);
++        printk("unexpected IRQ trap at irq %02x\n", irq);
+ }
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2007-06-12 13:13:01.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -41,8 +41,7 @@ int acpi_found_madt;
+  * Various Linux-internal data structures created from the
+  * MP-table.
+  */
+-unsigned char apic_version [MAX_APICS];
+-unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+ int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+ 
+ static int mp_current_pci_id = 0;
+@@ -56,7 +55,6 @@ struct mpc_config_intsrc mp_irqs[MAX_IRQ
+ int mp_irq_entries;
+ 
+ int nr_ioapics;
+-int pic_mode;
+ unsigned long mp_lapic_addr = 0;
+ 
+ 
+@@ -71,19 +69,6 @@ unsigned disabled_cpus __initdata;
+ /* Bitmask of physically existing CPUs */
+ physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+ 
+-/* ACPI MADT entry parsing functions */
+-#ifdef CONFIG_ACPI
+-extern struct acpi_boot_flags acpi_boot;
+-#ifdef CONFIG_X86_LOCAL_APIC
+-extern int acpi_parse_lapic (acpi_table_entry_header *header);
+-extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
+-extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
+-#endif /*CONFIG_X86_LOCAL_APIC*/
+-#ifdef CONFIG_X86_IO_APIC
+-extern int acpi_parse_ioapic (acpi_table_entry_header *header);
+-#endif /*CONFIG_X86_IO_APIC*/
+-#endif /*CONFIG_ACPI*/
+-
+ u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+ 
+ 
+@@ -109,24 +94,20 @@ static int __init mpf_checksum(unsigned 
+ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+ {
+ 	int cpu;
+-	unsigned char ver;
+ 	cpumask_t tmp_map;
++	char *bootup_cpu = "";
+ 
+ 	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+ 		disabled_cpus++;
+ 		return;
+ 	}
+-
+-	printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
+-		m->mpc_apicid,
+-	       (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
+-	       (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
+-		m->mpc_apicver);
+-
+ 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+-		Dprintk("    Bootup CPU\n");
++		bootup_cpu = " (Bootup-CPU)";
+ 		boot_cpu_id = m->mpc_apicid;
+ 	}
++
++	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
++
+ 	if (num_processors >= NR_CPUS) {
+ 		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
+ 			" Processor ignored.\n", NR_CPUS);
+@@ -137,24 +118,7 @@ static void __cpuinit MP_processor_info 
+ 	cpus_complement(tmp_map, cpu_present_map);
+ 	cpu = first_cpu(tmp_map);
+ 
+-#if MAX_APICS < 255	
+-	if ((int)m->mpc_apicid > MAX_APICS) {
+-		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
+-			m->mpc_apicid, MAX_APICS);
+-		return;
+-	}
+-#endif
+-	ver = m->mpc_apicver;
+-
+ 	physid_set(m->mpc_apicid, phys_cpu_present_map);
+-	/*
+-	 * Validate version
+-	 */
+-	if (ver == 0x0) {
+-		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+-		ver = 0x10;
+-	}
+-	apic_version[m->mpc_apicid] = ver;
+  	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+  		/*
+  		 * bios_cpu_apicid is required to have processors listed
+@@ -185,37 +149,42 @@ static void __init MP_bus_info (struct m
+ 	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+ 
+ 	if (strncmp(str, "ISA", 3) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+-	} else if (strncmp(str, "EISA", 4) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++		set_bit(m->mpc_busid, mp_bus_not_pci);
+ 	} else if (strncmp(str, "PCI", 3) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++		clear_bit(m->mpc_busid, mp_bus_not_pci);
+ 		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+ 		mp_current_pci_id++;
+-	} else if (strncmp(str, "MCA", 3) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+ 	} else {
+ 		printk(KERN_ERR "Unknown bustype %s\n", str);
+ 	}
+ }
+ 
++static int bad_ioapic(unsigned long address)
++{
++	if (nr_ioapics >= MAX_IO_APICS) {
++		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
++			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
++		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
++	}
++	if (!address) {
++		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
++			" found in table, skipping!\n");
++		return 1;
++	}
++	return 0;
++}
++
+ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+ {
+ 	if (!(m->mpc_flags & MPC_APIC_USABLE))
+ 		return;
+ 
+-	printk("I/O APIC #%d Version %d at 0x%X.\n",
+-		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
+-			MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
+-	}
+-	if (!m->mpc_apicaddr) {
+-		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
+-			" found in MP table, skipping!\n");
++	printk("I/O APIC #%d at 0x%X.\n",
++		m->mpc_apicid, m->mpc_apicaddr);
++
++	if (bad_ioapic(m->mpc_apicaddr))
+ 		return;
+-	}
++
+ 	mp_ioapics[nr_ioapics] = *m;
+ 	nr_ioapics++;
+ }
+@@ -239,19 +208,6 @@ static void __init MP_lintsrc_info (stru
+ 			m->mpc_irqtype, m->mpc_irqflag & 3,
+ 			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
+ 			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+-	/*
+-	 * Well it seems all SMP boards in existence
+-	 * use ExtINT/LVT1 == LINT0 and
+-	 * NMI/LVT2 == LINT1 - the following check
+-	 * will show us if this assumptions is false.
+-	 * Until then we do not have to add baggage.
+-	 */
+-	if ((m->mpc_irqtype == mp_ExtINT) &&
+-		(m->mpc_destapiclint != 0))
+-			BUG();
+-	if ((m->mpc_irqtype == mp_NMI) &&
+-		(m->mpc_destapiclint != 1))
+-			BUG();
+ }
+ 
+ /*
+@@ -265,7 +221,7 @@ static int __init smp_read_mpc(struct mp
+ 	unsigned char *mpt=((unsigned char *)mpc)+count;
+ 
+ 	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
+-		printk("SMP mptable: bad signature [%c%c%c%c]!\n",
++		printk("MPTABLE: bad signature [%c%c%c%c]!\n",
+ 			mpc->mpc_signature[0],
+ 			mpc->mpc_signature[1],
+ 			mpc->mpc_signature[2],
+@@ -273,31 +229,31 @@ static int __init smp_read_mpc(struct mp
+ 		return 0;
+ 	}
+ 	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
+-		printk("SMP mptable: checksum error!\n");
++		printk("MPTABLE: checksum error!\n");
+ 		return 0;
+ 	}
+ 	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
+-		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
++		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+ 			mpc->mpc_spec);
+ 		return 0;
+ 	}
+ 	if (!mpc->mpc_lapic) {
+-		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
++		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+ 		return 0;
+ 	}
+ 	memcpy(str,mpc->mpc_oem,8);
+-	str[8]=0;
+-	printk(KERN_INFO "OEM ID: %s ",str);
++	str[8] = 0;
++	printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
+ 
+ 	memcpy(str,mpc->mpc_productid,12);
+-	str[12]=0;
+-	printk("Product ID: %s ",str);
++	str[12] = 0;
++	printk("MPTABLE: Product ID: %s ",str);
+ 
+-	printk("APIC at: 0x%X\n",mpc->mpc_lapic);
++	printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
+ 
+ 	/* save the local APIC address, it might be non-default */
+ 	if (!acpi_lapic)
+-	mp_lapic_addr = mpc->mpc_lapic;
++		mp_lapic_addr = mpc->mpc_lapic;
+ 
+ 	/*
+ 	 *	Now process the configuration blocks.
+@@ -309,7 +265,7 @@ static int __init smp_read_mpc(struct mp
+ 				struct mpc_config_processor *m=
+ 					(struct mpc_config_processor *)mpt;
+ 				if (!acpi_lapic)
+-				MP_processor_info(m);
++					MP_processor_info(m);
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+ 				break;
+@@ -328,8 +284,8 @@ static int __init smp_read_mpc(struct mp
+ 				struct mpc_config_ioapic *m=
+ 					(struct mpc_config_ioapic *)mpt;
+ 				MP_ioapic_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
+ 				break;
+ 			}
+ 			case MP_INTSRC:
+@@ -338,8 +294,8 @@ static int __init smp_read_mpc(struct mp
+ 					(struct mpc_config_intsrc *)mpt;
+ 
+ 				MP_intsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
+ 				break;
+ 			}
+ 			case MP_LINTSRC:
+@@ -347,15 +303,15 @@ static int __init smp_read_mpc(struct mp
+ 				struct mpc_config_lintsrc *m=
+ 					(struct mpc_config_lintsrc *)mpt;
+ 				MP_lintsrc_info(m);
+-				mpt+=sizeof(*m);
+-				count+=sizeof(*m);
++				mpt += sizeof(*m);
++				count += sizeof(*m);
+ 				break;
+ 			}
+ 		}
+ 	}
+ 	clustered_apic_check();
+ 	if (!num_processors)
+-		printk(KERN_ERR "SMP mptable: no processors registered!\n");
++		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ 	return num_processors;
+ }
+ 
+@@ -451,13 +407,10 @@ static inline void __init construct_defa
+ 	 * 2 CPUs, numbered 0 & 1.
+ 	 */
+ 	processor.mpc_type = MP_PROCESSOR;
+-	/* Either an integrated APIC or a discrete 82489DX. */
+-	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.mpc_apicver = 0;
+ 	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+-				   (boot_cpu_data.x86_model << 4) |
+-				   boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_cpufeature = 0;
++	processor.mpc_featureflag = 0;
+ 	processor.mpc_reserved[0] = 0;
+ 	processor.mpc_reserved[1] = 0;
+ 	for (i = 0; i < 2; i++) {
+@@ -476,14 +429,6 @@ static inline void __init construct_defa
+ 		case 5:
+ 			memcpy(bus.mpc_bustype, "ISA   ", 6);
+ 			break;
+-		case 2:
+-		case 6:
+-		case 3:
+-			memcpy(bus.mpc_bustype, "EISA  ", 6);
+-			break;
+-		case 4:
+-		case 7:
+-			memcpy(bus.mpc_bustype, "MCA   ", 6);
+ 	}
+ 	MP_bus_info(&bus);
+ 	if (mpc_default_type > 4) {
+@@ -494,7 +439,7 @@ static inline void __init construct_defa
+ 
+ 	ioapic.mpc_type = MP_IOAPIC;
+ 	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.mpc_apicver = 0;
+ 	ioapic.mpc_flags = MPC_APIC_USABLE;
+ 	ioapic.mpc_apicaddr = 0xFEC00000;
+ 	MP_ioapic_info(&ioapic);
+@@ -537,13 +482,6 @@ void __init get_smp_config (void)
+  		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
+ 
+ 	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+-	if (mpf->mpf_feature2 & (1<<7)) {
+-		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+-		pic_mode = 1;
+-	} else {
+-		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
+-		pic_mode = 0;
+-	}
+ 
+ 	/*
+ 	 * Now see if we need to read further.
+@@ -620,7 +558,7 @@ static int __init smp_scan_config (unsig
+ 	return 0;
+ }
+ 
+-void __init find_intel_smp (void)
++void __init find_smp_config(void)
+ {
+ 	unsigned int address;
+ 
+@@ -637,9 +575,7 @@ void __init find_intel_smp (void)
+ 			smp_scan_config(0xF0000,0x10000))
+ 		return;
+ 	/*
+-	 * If it is an SMP machine we should know now, unless the
+-	 * configuration is in an EISA/MCA bus machine with an
+-	 * extended bios data area.
++	 * If it is an SMP machine we should know now.
+ 	 *
+ 	 * there is a real-mode segmented pointer pointing to the
+ 	 * 4K EBDA area at 0x40E, calculate and scan it here.
+@@ -660,64 +596,38 @@ void __init find_intel_smp (void)
+ 	 printk(KERN_INFO "No mptable found.\n");
+ }
+ 
+-/*
+- * - Intel MP Configuration Table
+- */
+-void __init find_smp_config (void)
+-{
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	find_intel_smp();
+-#endif
+-}
+-
+-
+ /* --------------------------------------------------------------------------
+                             ACPI-based MP Configuration
+    -------------------------------------------------------------------------- */
+ 
+ #ifdef CONFIG_ACPI
+ 
+-void __init mp_register_lapic_address (
+-	u64			address)
++void __init mp_register_lapic_address(u64 address)
+ {
+ #ifndef CONFIG_XEN
+ 	mp_lapic_addr = (unsigned long) address;
+-
+ 	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+-
+ 	if (boot_cpu_id == -1U)
+ 		boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+-
+-	Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
+ #endif
+ }
+ 
+-
+-void __cpuinit mp_register_lapic (
+-	u8			id, 
+-	u8			enabled)
++void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+ {
+ 	struct mpc_config_processor processor;
+ 	int			boot_cpu = 0;
+ 	
+-	if (id >= MAX_APICS) {
+-		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+-			id, MAX_APICS);
+-		return;
+-	}
+-
+-	if (id == boot_cpu_physical_apicid)
++	if (id == boot_cpu_id)
+ 		boot_cpu = 1;
+ 
+ #ifndef CONFIG_XEN
+ 	processor.mpc_type = MP_PROCESSOR;
+ 	processor.mpc_apicid = id;
+-	processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
++	processor.mpc_apicver = 0;
+ 	processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
+ 	processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
+-		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
++	processor.mpc_cpufeature = 0;
++	processor.mpc_featureflag = 0;
+ 	processor.mpc_reserved[0] = 0;
+ 	processor.mpc_reserved[1] = 0;
+ #endif
+@@ -725,8 +635,6 @@ void __cpuinit mp_register_lapic (
+ 	MP_processor_info(&processor);
+ }
+ 
+-#ifdef CONFIG_X86_IO_APIC
+-
+ #define MP_ISA_BUS		0
+ #define MP_MAX_IOAPIC_PIN	127
+ 
+@@ -737,11 +645,9 @@ static struct mp_ioapic_routing {
+ 	u32			pin_programmed[4];
+ } mp_ioapic_routing[MAX_IO_APICS];
+ 
+-
+-static int mp_find_ioapic (
+-	int			gsi)
++static int mp_find_ioapic(int gsi)
+ {
+-	int			i = 0;
++	int i = 0;
+ 
+ 	/* Find the IOAPIC that manages this GSI. */
+ 	for (i = 0; i < nr_ioapics; i++) {
+@@ -751,28 +657,15 @@ static int mp_find_ioapic (
+ 	}
+ 
+ 	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+-
+ 	return -1;
+ }
+-	
+ 
+-void __init mp_register_ioapic (
+-	u8			id, 
+-	u32			address,
+-	u32			gsi_base)
++void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+ {
+-	int			idx = 0;
++	int idx = 0;
+ 
+-	if (nr_ioapics >= MAX_IO_APICS) {
+-		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+-			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
+-		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+-	}
+-	if (!address) {
+-		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+-			" found in MADT table, skipping!\n");
++	if (bad_ioapic(address))
+ 		return;
+-	}
+ 
+ 	idx = nr_ioapics++;
+ 
+@@ -784,7 +677,7 @@ void __init mp_register_ioapic (
+ 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+ #endif
+ 	mp_ioapics[idx].mpc_apicid = id;
+-	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
++	mp_ioapics[idx].mpc_apicver = 0;
+ 	
+ 	/* 
+ 	 * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
+@@ -795,21 +688,15 @@ void __init mp_register_ioapic (
+ 	mp_ioapic_routing[idx].gsi_end = gsi_base + 
+ 		io_apic_get_redir_entries(idx);
+ 
+-	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
+ 		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
+-		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++		mp_ioapics[idx].mpc_apicaddr,
+ 		mp_ioapic_routing[idx].gsi_start,
+ 		mp_ioapic_routing[idx].gsi_end);
+-
+-	return;
+ }
+ 
+-
+-void __init mp_override_legacy_irq (
+-	u8			bus_irq,
+-	u8			polarity, 
+-	u8			trigger, 
+-	u32			gsi)
++void __init
++mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32	gsi)
+ {
+ 	struct mpc_config_intsrc intsrc;
+ 	int			ioapic = -1;
+@@ -847,22 +734,18 @@ void __init mp_override_legacy_irq (
+ 	mp_irqs[mp_irq_entries] = intsrc;
+ 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ 		panic("Max # of irq sources exceeded!\n");
+-
+-	return;
+ }
+ 
+-
+-void __init mp_config_acpi_legacy_irqs (void)
++void __init mp_config_acpi_legacy_irqs(void)
+ {
+ 	struct mpc_config_intsrc intsrc;
+-	int			i = 0;
+-	int			ioapic = -1;
++	int i = 0;
++	int ioapic = -1;
+ 
+ 	/* 
+ 	 * Fabricate the legacy ISA bus (bus #31).
+ 	 */
+-	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+-	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
++	set_bit(MP_ISA_BUS, mp_bus_not_pci);
+ 
+ 	/* 
+ 	 * Locate the IOAPIC that manages the ISA IRQs (0-15). 
+@@ -915,24 +798,13 @@ void __init mp_config_acpi_legacy_irqs (
+ 		if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ 			panic("Max # of irq sources exceeded!\n");
+ 	}
+-
+-	return;
+ }
+ 
+-#define MAX_GSI_NUM	4096
+-
+ int mp_register_gsi(u32 gsi, int triggering, int polarity)
+ {
+-	int			ioapic = -1;
+-	int			ioapic_pin = 0;
+-	int			idx, bit = 0;
+-	static int		pci_irq = 16;
+-	/*
+-	 * Mapping between Global System Interrupts, which
+-	 * represent all possible interrupts, to the IRQs
+-	 * assigned to actual devices.
+-	 */
+-	static int		gsi_to_irq[MAX_GSI_NUM];
++	int ioapic = -1;
++	int ioapic_pin = 0;
++	int idx, bit = 0;
+ 
+ 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+ 		return gsi;
+@@ -965,47 +837,14 @@ int mp_register_gsi(u32 gsi, int trigger
+ 	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+ 		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+ 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return gsi_to_irq[gsi];
++		return gsi;
+ 	}
+ 
+ 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ 
+-	if (triggering == ACPI_LEVEL_SENSITIVE) {
+-		/*
+-		 * For PCI devices assign IRQs in order, avoiding gaps
+-		 * due to unused I/O APIC pins.
+-		 */
+-		int irq = gsi;
+-		if (gsi < MAX_GSI_NUM) {
+-			/*
+-			 * Retain the VIA chipset work-around (gsi > 15), but
+-			 * avoid a problem where the 8254 timer (IRQ0) is setup
+-			 * via an override (so it's not on pin 0 of the ioapic),
+-			 * and at the same time, the pin 0 interrupt is a PCI
+-			 * type.  The gsi > 15 test could cause these two pins
+-			 * to be shared as IRQ0, and they are not shareable.
+-			 * So test for this condition, and if necessary, avoid
+-			 * the pin collision.
+-			 */
+-			if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0))
+-				gsi = pci_irq++;
+-			/*
+-			 * Don't assign IRQ used by ACPI SCI
+-			 */
+-			if (gsi == acpi_fadt.sci_int)
+-				gsi = pci_irq++;
+-			gsi_to_irq[irq] = gsi;
+-		} else {
+-			printk(KERN_ERR "GSI %u is too high\n", gsi);
+-			return gsi;
+-		}
+-	}
+-
+ 	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
+ 		triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ 		polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
+ 	return gsi;
+ }
+-
+-#endif /*CONFIG_X86_IO_APIC*/
+ #endif /*CONFIG_ACPI*/
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2008-08-07 12:44:36.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -89,25 +89,24 @@ void idle_notifier_unregister(struct not
+ }
+ EXPORT_SYMBOL(idle_notifier_unregister);
+ 
+-enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
+-static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
+-
+ void enter_idle(void)
+ {
+-	__get_cpu_var(idle_state) = CPU_IDLE;
++	write_pda(isidle, 1);
+ 	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+ }
+ 
+ static void __exit_idle(void)
+ {
+-	__get_cpu_var(idle_state) = CPU_NOT_IDLE;
++	if (test_and_clear_bit_pda(0, isidle) == 0)
++		return;
+ 	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+ }
+ 
+ /* Called from interrupts to signify idle end */
+ void exit_idle(void)
+ {
+-	if (current->pid | read_pda(irqcount))
++	/* idle loop has pid 0 */
++	if (current->pid)
+ 		return;
+ 	__exit_idle();
+ }
+@@ -184,6 +183,9 @@ void cpu_idle (void)
+ 				play_dead();
+ 			enter_idle();
+ 			idle();
++			/* In many cases the interrupt that ended idle
++			   has already called exit_idle. But some idle
++			   loops can be woken up without interrupt. */
+ 			__exit_idle();
+ 		}
+ 
+@@ -196,7 +198,7 @@ void cpu_idle (void)
+ void cpu_idle_wait(void)
+ {
+ 	unsigned int cpu, this_cpu = get_cpu();
+-	cpumask_t map;
++	cpumask_t map, tmp = current->cpus_allowed;
+ 
+ 	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ 	put_cpu();
+@@ -219,6 +221,8 @@ void cpu_idle_wait(void)
+ 		}
+ 		cpus_and(map, map, cpu_online_map);
+ 	} while (!cpus_empty(map));
++
++	set_cpus_allowed(current, tmp);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+@@ -250,9 +254,9 @@ void __show_regs(struct pt_regs * regs)
+ 	print_modules();
+ 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+ 		current->pid, current->comm, print_tainted(),
+-		system_utsname.release,
+-		(int)strcspn(system_utsname.version, " "),
+-		system_utsname.version);
++		init_utsname()->release,
++		(int)strcspn(init_utsname()->version, " "),
++		init_utsname()->version);
+ 	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
+ 	printk_address(regs->rip); 
+ 	printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp,
+@@ -310,6 +314,7 @@ void exit_thread(void)
+ 
+ 		kfree(t->io_bitmap_ptr);
+ 		t->io_bitmap_ptr = NULL;
++		clear_thread_flag(TIF_IO_BITMAP);
+ 		/*
+ 		 * Careful, clear this in the TSS too:
+ 		 */
+@@ -340,6 +345,7 @@ void flush_thread(void)
+ 		if (t->flags & _TIF_IA32)
+ 			current_thread_info()->status |= TS_COMPAT;
+ 	}
++	t->flags &= ~_TIF_DEBUG;
+ 
+ 	tsk->thread.debugreg0 = 0;
+ 	tsk->thread.debugreg1 = 0;
+@@ -432,7 +438,7 @@ int copy_thread(int nr, unsigned long cl
+ 	asm("mov %%es,%0" : "=m" (p->thread.es));
+ 	asm("mov %%ds,%0" : "=m" (p->thread.ds));
+ 
+-	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
++	if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
+ 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+ 		if (!p->thread.io_bitmap_ptr) {
+ 			p->thread.io_bitmap_max = 0;
+@@ -440,6 +446,7 @@ int copy_thread(int nr, unsigned long cl
+ 		}
+ 		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
+ 				IO_BITMAP_BYTES);
++		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+ 	} 
+ 
+ 	/*
+@@ -474,6 +481,30 @@ static inline void __save_init_fpu( stru
+ }
+ 
+ /*
++ * This special macro can be used to load a debugging register
++ */
++#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
++
++static inline void __switch_to_xtra(struct task_struct *prev_p,
++			     	    struct task_struct *next_p)
++{
++	struct thread_struct *prev, *next;
++
++	prev = &prev_p->thread,
++	next = &next_p->thread;
++
++	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
++		loaddebug(next, 0);
++		loaddebug(next, 1);
++		loaddebug(next, 2);
++		loaddebug(next, 3);
++		/* no 4 and 5 */
++		loaddebug(next, 6);
++		loaddebug(next, 7);
++	}
++}
++
++/*
+  *	switch_to(x,y) should switch tasks from x to y.
+  *
+  * This could still be optimized: 
+@@ -501,6 +532,10 @@ __switch_to(struct task_struct *prev_p, 
+ #endif
+ 	multicall_entry_t _mcl[8], *mcl = _mcl;
+ 
++	/* we're going to use this soon, after a few expensive things */
++	if (next_p->fpu_counter>5)
++		prefetch(&next->i387.fxsave);
++
+ 	/*
+ 	 * This is basically '__unlazy_fpu', except that we queue a
+ 	 * multicall to indicate FPU task switch, rather than
+@@ -513,7 +548,8 @@ __switch_to(struct task_struct *prev_p, 
+ 		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+ 		mcl->args[0] = 1;
+ 		mcl++;
+-	}
++	} else
++		prev_p->fpu_counter = 0;
+ 
+ 	/*
+ 	 * Reload esp0, LDT and the page table pointer:
+@@ -608,21 +644,29 @@ __switch_to(struct task_struct *prev_p, 
+ 	write_pda(oldrsp, next->userrsp); 
+ 	write_pda(pcurrent, next_p); 
+ 	write_pda(kernelstack,
+-		  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
++	(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
++#ifdef CONFIG_CC_STACKPROTECTOR
++	write_pda(stack_canary, next_p->stack_canary);
++
++	/*
++	 * Build time only check to make sure the stack_canary is at
++	 * offset 40 in the pda; this is a gcc ABI requirement
++	 */
++	BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40);
++#endif
+ 
+ 	/*
+ 	 * Now maybe reload the debug registers
+ 	 */
+-	if (unlikely(next->debugreg7)) {
+-		set_debugreg(next->debugreg0, 0);
+-		set_debugreg(next->debugreg1, 1);
+-		set_debugreg(next->debugreg2, 2);
+-		set_debugreg(next->debugreg3, 3);
+-		/* no 4 and 5 */
+-		set_debugreg(next->debugreg6, 6);
+-		set_debugreg(next->debugreg7, 7);
+-	}
++	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
++		__switch_to_xtra(prev_p, next_p);
+ 
++	/* If the task has used fpu the last 5 timeslices, just do a full
++	 * restore of the math state immediately to avoid the trap; the
++	 * chances of needing FPU soon are obviously high now
++	 */
++	if (next_p->fpu_counter>5)
++		math_state_restore();
+ 	return prev_p;
+ }
+ 
+@@ -842,7 +886,7 @@ int dump_task_regs(struct task_struct *t
+ 
+ unsigned long arch_align_stack(unsigned long sp)
+ {
+-	if (randomize_va_space)
++	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ 		sp -= get_random_int() % 8192;
+ 	return sp & ~0xf;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -88,9 +88,6 @@ extern struct edid_info edid_info;
+ shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+ EXPORT_SYMBOL(HYPERVISOR_shared_info);
+ 
+-extern char hypercall_page[PAGE_SIZE];
+-EXPORT_SYMBOL(hypercall_page);
+-
+ static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+ static struct notifier_block xen_panic_block = {
+ 	xen_panic_event, NULL, 0 /* try to go last */
+@@ -118,16 +115,6 @@ EXPORT_SYMBOL(boot_cpu_data);
+ 
+ unsigned long mmu_cr4_features;
+ 
+-int acpi_disabled;
+-EXPORT_SYMBOL(acpi_disabled);
+-#ifdef	CONFIG_ACPI
+-extern int __initdata acpi_ht;
+-extern acpi_interrupt_flags	acpi_sci_flags;
+-int __initdata acpi_force = 0;
+-#endif
+-
+-int acpi_numa __initdata;
+-
+ /* Boot loader ID as an integer, for the benefit of proc_dointvec */
+ int bootloader_type;
+ 
+@@ -151,10 +138,6 @@ struct sys_desc_table_struct {
+ 
+ struct edid_info edid_info;
+ EXPORT_SYMBOL_GPL(edid_info);
+-struct e820map e820;
+-#ifdef CONFIG_XEN
+-struct e820map machine_e820;
+-#endif
+ 
+ extern int root_mountflags;
+ 
+@@ -181,9 +164,6 @@ struct resource standard_io_resources[] 
+ 		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
+ };
+ 
+-#define STANDARD_IO_RESOURCES \
+-	(sizeof standard_io_resources / sizeof standard_io_resources[0])
+-
+ #define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
+ 
+ struct resource data_resource = {
+@@ -230,9 +210,6 @@ static struct resource adapter_rom_resou
+ 		.flags = IORESOURCE_ROM }
+ };
+ 
+-#define ADAPTER_ROM_RESOURCES \
+-	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
+-
+ static struct resource video_rom_resource = {
+ 	.name = "Video ROM",
+ 	.start = 0xc0000,
+@@ -309,7 +286,8 @@ static void __init probe_roms(void)
+ 	}
+ 
+ 	/* check for adapter roms on 2k boundaries */
+-	for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) {
++	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper;
++	     start += 2048) {
+ 		rom = isa_bus_to_virt(start);
+ 		if (!romsignature(rom))
+ 			continue;
+@@ -329,187 +307,22 @@ static void __init probe_roms(void)
+ 	}
+ }
+ 
+-/* Check for full argument with no trailing characters */
+-static int fullarg(char *p, char *arg)
++#ifdef CONFIG_PROC_VMCORE
++/* elfcorehdr= specifies the location of elf core header
++ * stored by the crashed kernel. This option will be passed
++ * by kexec loader to the capture kernel.
++ */
++static int __init setup_elfcorehdr(char *arg)
+ {
+-	int l = strlen(arg);
+-	return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
++	char *end;
++	if (!arg)
++		return -EINVAL;
++	elfcorehdr_addr = memparse(arg, &end);
++	return end > arg ? 0 : -EINVAL;
+ }
+-
+-static __init void parse_cmdline_early (char ** cmdline_p)
+-{
+-	char c = ' ', *to = command_line, *from = COMMAND_LINE;
+-	int len = 0;
+-	int userdef = 0;
+-
+-	for (;;) {
+-		if (c != ' ') 
+-			goto next_char; 
+-
+-#ifdef  CONFIG_SMP
+-		/*
+-		 * If the BIOS enumerates physical processors before logical,
+-		 * maxcpus=N at enumeration-time can be used to disable HT.
+-		 */
+-		else if (!memcmp(from, "maxcpus=", 8)) {
+-			extern unsigned int maxcpus;
+-
+-			maxcpus = simple_strtoul(from + 8, NULL, 0);
+-		}
+-#endif
+-#ifdef CONFIG_ACPI
+-		/* "acpi=off" disables both ACPI table parsing and interpreter init */
+-		if (fullarg(from,"acpi=off"))
+-			disable_acpi();
+-
+-		if (fullarg(from, "acpi=force")) { 
+-			/* add later when we do DMI horrors: */
+-			acpi_force = 1;
+-			acpi_disabled = 0;
+-		}
+-
+-		/* acpi=ht just means: do ACPI MADT parsing 
+-		   at bootup, but don't enable the full ACPI interpreter */
+-		if (fullarg(from, "acpi=ht")) { 
+-			if (!acpi_force)
+-				disable_acpi();
+-			acpi_ht = 1; 
+-		}
+-                else if (fullarg(from, "pci=noacpi")) 
+-			acpi_disable_pci();
+-		else if (fullarg(from, "acpi=noirq"))
+-			acpi_noirq_set();
+-
+-		else if (fullarg(from, "acpi_sci=edge"))
+-			acpi_sci_flags.trigger =  1;
+-		else if (fullarg(from, "acpi_sci=level"))
+-			acpi_sci_flags.trigger = 3;
+-		else if (fullarg(from, "acpi_sci=high"))
+-			acpi_sci_flags.polarity = 1;
+-		else if (fullarg(from, "acpi_sci=low"))
+-			acpi_sci_flags.polarity = 3;
+-
+-		/* acpi=strict disables out-of-spec workarounds */
+-		else if (fullarg(from, "acpi=strict")) {
+-			acpi_strict = 1;
+-		}
+-#ifdef CONFIG_X86_IO_APIC
+-		else if (fullarg(from, "acpi_skip_timer_override"))
+-			acpi_skip_timer_override = 1;
+-#endif
+-#endif
+-
+-#ifndef CONFIG_XEN
+-		if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
+-			clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+-			disable_apic = 1;
+-		}
+-
+-		if (fullarg(from, "noapic"))
+-			skip_ioapic_setup = 1;
+-
+-		if (fullarg(from,"apic")) {
+-			skip_ioapic_setup = 0;
+-			ioapic_force = 1;
+-		}
+-#endif
+-			
+-		if (!memcmp(from, "mem=", 4))
+-			parse_memopt(from+4, &from); 
+-
+-		if (!memcmp(from, "memmap=", 7)) {
+-			/* exactmap option is for used defined memory */
+-			if (!memcmp(from+7, "exactmap", 8)) {
+-#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 = e820_end_of_ram();
+-#endif
+-				from += 8+7;
+-				end_pfn_map = 0;
+-				e820.nr_map = 0;
+-				userdef = 1;
+-			}
+-			else {
+-				parse_memmapopt(from+7, &from);
+-				userdef = 1;
+-			}
+-		}
+-
+-#ifdef CONFIG_NUMA
+-		if (!memcmp(from, "numa=", 5))
+-			numa_setup(from+5); 
++early_param("elfcorehdr", setup_elfcorehdr);
+ #endif
+ 
+-		if (!memcmp(from,"iommu=",6)) { 
+-			iommu_setup(from+6); 
+-		}
+-
+-		if (fullarg(from,"oops=panic"))
+-			panic_on_oops = 1;
+-
+-		if (!memcmp(from, "noexec=", 7))
+-			nonx_setup(from + 7);
+-
+-#ifdef CONFIG_KEXEC
+-		/* crashkernel=size@addr specifies the location to reserve for
+-		 * a crash kernel.  By reserving this memory we guarantee
+-		 * that linux never set's it up as a DMA target.
+-		 * Useful for holding code to do something appropriate
+-		 * after a kernel panic.
+-		 */
+-		else if (!memcmp(from, "crashkernel=", 12)) {
+-#ifndef CONFIG_XEN
+-			unsigned long size, base;
+-			size = memparse(from+12, &from);
+-			if (*from == '@') {
+-				base = memparse(from+1, &from);
+-				/* FIXME: Do I want a sanity check
+-				 * to validate the memory range?
+-				 */
+-				crashk_res.start = base;
+-				crashk_res.end   = base + size - 1;
+-			}
+-#else
+-			printk("Ignoring crashkernel command line, "
+-			       "parameter will be supplied by xen\n");
+-#endif
+-		}
+-#endif
+-
+-#ifdef CONFIG_PROC_VMCORE
+-		/* elfcorehdr= specifies the location of elf core header
+-		 * stored by the crashed kernel. This option will be passed
+-		 * by kexec loader to the capture kernel.
+-		 */
+-		else if(!memcmp(from, "elfcorehdr=", 11))
+-			elfcorehdr_addr = memparse(from+11, &from);
+-#endif
+-
+-#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_XEN)
+-		else if (!memcmp(from, "additional_cpus=", 16))
+-			setup_additional_cpus(from+16);
+-#endif
+-
+-	next_char:
+-		c = *(from++);
+-		if (!c)
+-			break;
+-		if (COMMAND_LINE_SIZE <= ++len)
+-			break;
+-		*(to++) = c;
+-	}
+-	if (userdef) {
+-		printk(KERN_INFO "user-defined physical RAM map:\n");
+-		e820_print_map("user");
+-	}
+-	*to = '\0';
+-	*cmdline_p = command_line;
+-}
+-
+ #ifndef CONFIG_NUMA
+ static void __init
+ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+@@ -521,13 +334,13 @@ contig_initmem_init(unsigned long start_
+ 	if (bootmap == -1L)
+ 		panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+ 	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
++	e820_register_active_regions(0, start_pfn, end_pfn);
+ #ifdef CONFIG_XEN
+ 	if (xen_start_info->nr_pages < end_pfn)
+-		e820_bootmem_free(NODE_DATA(0), 0,
+-				  xen_start_info->nr_pages<<PAGE_SHIFT);
++		free_bootmem_with_active_regions(0, xen_start_info->nr_pages);
+ 	else
+ #endif
+-	e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
++	free_bootmem_with_active_regions(0, end_pfn);
+ 	reserve_bootmem(bootmap, bootmap_size);
+ } 
+ #endif
+@@ -589,6 +402,10 @@ static void discover_ebda(void)
+ void __init setup_arch(char **cmdline_p)
+ {
+ #ifdef CONFIG_XEN
++	extern struct e820map machine_e820;
++
++	printk(KERN_INFO "Command line: %s\n", saved_command_line);
++
+ 	/* Register a call for panic conditions. */
+ 	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+ 
+@@ -614,6 +431,8 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	ARCH_SETUP
+ #else
++	printk(KERN_INFO "Command line: %s\n", saved_command_line);
++
+  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+  	screen_info = SCREEN_INFO;
+ 	edid_info = EDID_INFO;
+@@ -641,16 +460,22 @@ void __init setup_arch(char **cmdline_p)
+ 	data_resource.start = virt_to_phys(&_etext);
+ 	data_resource.end = virt_to_phys(&_edata)-1;
+ 
+-	parse_cmdline_early(cmdline_p);
+-
+ 	early_identify_cpu(&boot_cpu_data);
+ 
++	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
++	*cmdline_p = command_line;
++
++	parse_early_param();
++
++	finish_e820_parsing();
++
++	e820_register_active_regions(0, 0, -1UL);
+ 	/*
+ 	 * partially used pages are not usable - thus
+ 	 * we are rounding upwards:
+ 	 */
+ 	end_pfn = e820_end_of_ram();
+-	num_physpages = end_pfn;		/* for pfn_valid */
++	num_physpages = end_pfn;
+ 
+ 	check_efer();
+ 
+@@ -661,6 +486,14 @@ void __init setup_arch(char **cmdline_p)
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
++	/* How many end-of-memory variables you have, grandma! */
++	max_low_pfn = end_pfn;
++	max_pfn = end_pfn;
++	high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
++
++	/* Remove active ranges so rediscovery with NUMA-awareness happens */
++	remove_all_active_ranges();
++
+ #ifdef CONFIG_ACPI_NUMA
+ 	/*
+ 	 * Parse SRAT to discover nodes.
+@@ -850,16 +683,16 @@ void __init setup_arch(char **cmdline_p)
+ 				BUG();
+ 	}
+ 
++#ifdef CONFIG_ACPI
+ 	if (!is_initial_xendomain()) {
+ 		acpi_disabled = 1;
+-#ifdef  CONFIG_ACPI
+ 		acpi_ht = 0;
+-#endif
+ 	}
+ #endif
++#endif
+ 
+-#ifndef CONFIG_XEN
+-	check_ioapic();
++#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
++	early_quirks();
+ #endif
+ 
+ 	zap_low_mappings(0);
+@@ -909,6 +742,7 @@ void __init setup_arch(char **cmdline_p)
+ 		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
+ #else
+ 	e820_reserve_resources(e820.map, e820.nr_map);
++	e820_mark_nosave_regions();
+ #endif
+ 
+ 	request_resource(&iomem_resource, &video_ram_resource);
+@@ -916,7 +750,7 @@ void __init setup_arch(char **cmdline_p)
+ 	{
+ 	unsigned i;
+ 	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
++	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+ 		request_resource(&ioport_resource, &standard_io_resources[i]);
+ 	}
+ 
+@@ -1100,7 +934,7 @@ static void __init amd_detect_cmp(struct
+ #endif
+ }
+ 
+-static void __init init_amd(struct cpuinfo_x86 *c)
++static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ {
+ 	unsigned level;
+ 
+@@ -1156,6 +990,12 @@ static void __init init_amd(struct cpuin
+ 
+ 	/* Fix cpuid4 emulation for more */
+ 	num_cache_leaves = 3;
++
++	/* When there is only one core no need to synchronize RDTSC */
++	if (num_possible_cpus() == 1)
++	        set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++	else
++	        clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+ }
+ 
+ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -1237,8 +1077,7 @@ static void srat_detect_node(void)
+ 		node = first_node(node_online_map);
+ 	numa_set_node(cpu, node);
+ 
+-	if (acpi_numa > 0)
+-		printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
++	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+ #endif
+ }
+ 
+@@ -1272,6 +1111,8 @@ static void __cpuinit init_intel(struct 
+ 	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ 	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+ 		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++	if (c->x86 == 6)
++		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ 	set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+  	c->x86_max_cores = intel_num_cpu_cores(c);
+ 
+@@ -1492,8 +1333,8 @@ static int show_cpuinfo(struct seq_file 
+ 
+ 		/* Intel-defined (#2) */
+ 		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+-		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
++		NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* VIA/Cyrix/Centaur-defined */
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -31,7 +31,7 @@
+ #include <asm/hypervisor.h>
+ #endif
+ 
+-char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
++char x86_boot_params[BOOT_PARAM_SIZE] __initdata;
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+@@ -55,8 +55,10 @@ Control non executable mappings for 64bi
+ on	Enable(default)
+ off	Disable
+ */ 
+-int __init nonx_setup(char *str)
++static int __init nonx_setup(char *str)
+ {
++	if (!str)
++		return -EINVAL;
+ 	if (!strncmp(str, "on", 2)) {
+                 __supported_pte_mask |= _PAGE_NX; 
+  		do_not_nx = 0; 
+@@ -64,9 +66,9 @@ int __init nonx_setup(char *str)
+ 		do_not_nx = 1;
+ 		__supported_pte_mask &= ~_PAGE_NX;
+         }
+-	return 1;
++	return 0;
+ } 
+-__setup("noexec=", nonx_setup);	/* parsed early actually */
++early_param("noexec", nonx_setup);
+ 
+ int force_personality32 = 0; 
+ 
+@@ -102,12 +104,9 @@ void __init setup_per_cpu_areas(void)
+ #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
++	size = PERCPU_ENOUGH_ROOM;
+ 
++	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
+ 	for_each_cpu_mask (i, cpu_possible_map) {
+ 		char *ptr;
+ 
+@@ -169,7 +168,10 @@ void pda_init(int 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
++	/* Memory clobbers used to order PDA accessed */
++	mb();
+ 	wrmsrl(MSR_GS_BASE, pda);
++	mb();
+ #else
+ 	if (HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL,
+ 					(unsigned long)pda))
+@@ -302,28 +304,17 @@ void __cpuinit cpu_init (void)
+ 	 * set up and load the per-CPU TSS
+ 	 */
+ 	for (v = 0; v < N_EXCEPTION_STACKS; v++) {
++		static const unsigned int order[N_EXCEPTION_STACKS] = {
++			[0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
++			[DEBUG_STACK - 1] = DEBUG_STACK_ORDER
++		};
+ 		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;
+-		}
++		estacks += PAGE_SIZE << order[v];
+ 		orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -381,9 +381,8 @@ int smp_call_function_single (int cpu, v
+ 	/* prevent preemption and reschedule on another processor */
+ 	int me = get_cpu();
+ 	if (cpu == me) {
+-		WARN_ON(1);
+ 		put_cpu();
+-		return -EBUSY;
++		return 0;
+ 	}
+ 	spin_lock_bh(&call_lock);
+ 	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+@@ -501,7 +500,7 @@ void smp_send_stop(void)
+ #ifndef CONFIG_XEN
+ asmlinkage void smp_reschedule_interrupt(void)
+ #else
+-asmlinkage irqreturn_t smp_reschedule_interrupt(void)
++asmlinkage irqreturn_t smp_reschedule_interrupt(int irq, void *ctx)
+ #endif
+ {
+ #ifndef CONFIG_XEN
+@@ -514,7 +513,7 @@ asmlinkage irqreturn_t smp_reschedule_in
+ #ifndef CONFIG_XEN
+ asmlinkage void smp_call_function_interrupt(void)
+ #else
+-asmlinkage irqreturn_t smp_call_function_interrupt(void)
++asmlinkage irqreturn_t smp_call_function_interrupt(int irq, void *ctx)
+ #endif
+ {
+ 	void (*func) (void *info) = call_data->func;
+@@ -545,31 +544,3 @@ asmlinkage irqreturn_t smp_call_function
+ 	return IRQ_HANDLED;
+ #endif
+ }
+-
+-int safe_smp_processor_id(void)
+-{
+-#ifdef CONFIG_XEN
+-	return smp_processor_id();
+-#else
+-	unsigned apicid, i;
+-
+-	if (disable_apic)
+-		return 0;
+-
+-	apicid = hard_smp_processor_id();
+-	if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid)
+-		return apicid;
+-
+-	for (i = 0; i < NR_CPUS; ++i) {
+-		if (x86_cpu_to_apicid[i] == apicid)
+-			return i;
+-	}
+-
+-	/* No entries in x86_cpu_to_apicid?  Either no MPS|ACPI,
+-	 * or called too early.  Either way, we must be CPU 0. */
+-      	if (x86_cpu_to_apicid[0] == BAD_APICID)
+-		return 0;
+-
+-	return 0; /* Should not happen */
+-#endif
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/interrupt.h>
++#include <linux/kallsyms.h>
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/nmi.h>
+@@ -45,6 +46,7 @@
+ #include <asm/pda.h>
+ #include <asm/proto.h>
+ #include <asm/nmi.h>
++#include <asm/stacktrace.h>
+ 
+ asmlinkage void divide_error(void);
+ asmlinkage void debug(void);
+@@ -114,7 +116,6 @@ static int call_trace = 1;
+ #endif
+ 
+ #ifdef CONFIG_KALLSYMS
+-# include <linux/kallsyms.h>
+ void printk_address(unsigned long address)
+ {
+ 	unsigned long offset = 0, symsize;
+@@ -142,7 +143,7 @@ void printk_address(unsigned long addres
+ #endif
+ 
+ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+-					unsigned *usedp, const char **idp)
++					unsigned *usedp, char **idp)
+ {
+ #ifndef CONFIG_X86_NO_TSS
+ 	static char ids[][8] = {
+@@ -162,26 +163,7 @@ static unsigned long *in_exception_stack
+ 	 * 'stack' is in one of them:
+ 	 */
+ 	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
+-		unsigned long end;
+-
+-		/*
+-		 * set 'end' to the end of the exception stack.
+-		 */
+-		switch (k + 1) {
+-		/*
+-		 * TODO: this block is not needed i think, because
+-		 * setup64.c:cpu_init() sets up t->ist[DEBUG_STACK]
+-		 * properly too.
+-		 */
+-#if DEBUG_STKSZ > EXCEPTION_STKSZ
+-		case DEBUG_STACK:
+-			end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
+-			break;
+-#endif
+-		default:
+-			end = per_cpu(orig_ist, cpu).ist[k];
+-			break;
+-		}
++		unsigned long end = per_cpu(orig_ist, cpu).ist[k];
+ 		/*
+ 		 * Is 'stack' above this exception frame's end?
+ 		 * If yes then skip to the next frame.
+@@ -236,13 +218,19 @@ static unsigned long *in_exception_stack
+ 	return NULL;
+ }
+ 
+-static int show_trace_unwind(struct unwind_frame_info *info, void *context)
++struct ops_and_data {
++	struct stacktrace_ops *ops;
++	void *data;
++};
++
++static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
+ {
++	struct ops_and_data *oad = (struct ops_and_data *)context;
+ 	int n = 0;
+ 
+ 	while (unwind(info) == 0 && UNW_PC(info)) {
+ 		n++;
+-		printk_address(UNW_PC(info));
++		oad->ops->address(oad->data, UNW_PC(info));
+ 		if (arch_unw_user_mode(info))
+ 			break;
+ 	}
+@@ -256,13 +244,19 @@ static int show_trace_unwind(struct unwi
+  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+  */
+ 
+-void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
++static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+ {
+-	const unsigned cpu = safe_smp_processor_id();
++	void *t = (void *)tinfo;
++        return p > t && p < t + THREAD_SIZE - 3;
++}
++
++void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack,
++		struct stacktrace_ops *ops, void *data)
++{
++	const unsigned cpu = smp_processor_id();
+ 	unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
+ 	unsigned used = 0;
+-
+-	printk("\nCall Trace:\n");
++	struct thread_info *tinfo;
+ 
+ 	if (!tsk)
+ 		tsk = current;
+@@ -270,32 +264,47 @@ void show_trace(struct task_struct *tsk,
+ 	if (call_trace >= 0) {
+ 		int unw_ret = 0;
+ 		struct unwind_frame_info info;
++		struct ops_and_data oad = { .ops = ops, .data = data };
+ 
+ 		if (regs) {
+ 			if (unwind_init_frame_info(&info, tsk, regs) == 0)
+-				unw_ret = show_trace_unwind(&info, NULL);
++				unw_ret = dump_trace_unwind(&info, &oad);
+ 		} else if (tsk == current)
+-			unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
++			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+ 		else {
+ 			if (unwind_init_blocked(&info, tsk) == 0)
+-				unw_ret = show_trace_unwind(&info, NULL);
++				unw_ret = dump_trace_unwind(&info, &oad);
+ 		}
+ 		if (unw_ret > 0) {
+ 			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-				print_symbol("DWARF2 unwinder stuck at %s\n",
++				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+ 					     UNW_PC(&info));
+ 				if ((long)UNW_SP(&info) < 0) {
+-					printk("Leftover inexact backtrace:\n");
++					ops->warning(data, "Leftover inexact backtrace:\n");
+ 					stack = (unsigned long *)UNW_SP(&info);
++					if (!stack)
++						return;
+ 				} else
+-					printk("Full inexact backtrace again:\n");
++					ops->warning(data, "Full inexact backtrace again:\n");
+ 			} else if (call_trace >= 1)
+ 				return;
+ 			else
+-				printk("Full inexact backtrace again:\n");
++				ops->warning(data, "Full inexact backtrace again:\n");
+ 		} else
+-			printk("Inexact backtrace:\n");
++			ops->warning(data, "Inexact backtrace:\n");
+ 	}
++	if (!stack) {
++		unsigned long dummy;
++		stack = &dummy;
++		if (tsk && tsk != current)
++			stack = (unsigned long *)tsk->thread.rsp;
++	}
++	/*
++	 * Align the stack pointer on word boundary, later loops
++	 * rely on that (and corruption / debug info bugs can cause
++	 * unaligned values here):
++	 */
++	stack = (unsigned long *)((unsigned long)stack & ~(sizeof(long)-1));
+ 
+ 	/*
+ 	 * Print function call entries within a stack. 'cond' is the
+@@ -305,7 +314,9 @@ void show_trace(struct task_struct *tsk,
+ #define HANDLE_STACK(cond) \
+ 	do while (cond) { \
+ 		unsigned long addr = *stack++; \
+-		if (kernel_text_address(addr)) { \
++		if (oops_in_progress ? 		\
++			__kernel_text_address(addr) : \
++			kernel_text_address(addr)) { \
+ 			/* \
+ 			 * If the address is either in the text segment of the \
+ 			 * kernel, or in the region which contains vmalloc'ed \
+@@ -314,7 +325,7 @@ void show_trace(struct task_struct *tsk,
+ 			 * down the cause of the crash will be able to figure \
+ 			 * out the call path that was taken. \
+ 			 */ \
+-			printk_address(addr); \
++			ops->address(data, addr);   \
+ 		} \
+ 	} while (0)
+ 
+@@ -323,16 +334,17 @@ void show_trace(struct task_struct *tsk,
+ 	 * current stack address. If the stacks consist of nested
+ 	 * exceptions
+ 	 */
+-	for ( ; ; ) {
+-		const char *id;
++	for (;;) {
++		char *id;
+ 		unsigned long *estack_end;
+ 		estack_end = in_exception_stack(cpu, (unsigned long)stack,
+ 						&used, &id);
+ 
+ 		if (estack_end) {
+-			printk(" <%s>", id);
++			if (ops->stack(data, id) < 0)
++				break;
+ 			HANDLE_STACK (stack < estack_end);
+-			printk(" <EOE>");
++			ops->stack(data, "<EOE>");
+ 			/*
+ 			 * We link to the next stack via the
+ 			 * second-to-last pointer (index -2 to end) in the
+@@ -347,7 +359,8 @@ void show_trace(struct task_struct *tsk,
+ 				(IRQSTACKSIZE - 64) / sizeof(*irqstack);
+ 
+ 			if (stack >= irqstack && stack < irqstack_end) {
+-				printk(" <IRQ>");
++				if (ops->stack(data, "IRQ") < 0)
++					break;
+ 				HANDLE_STACK (stack < irqstack_end);
+ 				/*
+ 				 * We link to the next stack (which would be
+@@ -356,7 +369,7 @@ void show_trace(struct task_struct *tsk,
+ 				 */
+ 				stack = (unsigned long *) (irqstack_end[-1]);
+ 				irqstack_end = NULL;
+-				printk(" <EOI>");
++				ops->stack(data, "EOI");
+ 				continue;
+ 			}
+ 		}
+@@ -364,19 +377,58 @@ void show_trace(struct task_struct *tsk,
+ 	}
+ 
+ 	/*
+-	 * This prints the process stack:
++	 * This handles the process stack:
+ 	 */
+-	HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
++	tinfo = current_thread_info();
++	HANDLE_STACK (valid_stack_ptr(tinfo, stack));
+ #undef HANDLE_STACK
++}
++EXPORT_SYMBOL(dump_trace);
+ 
++static void
++print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
++{
++	print_symbol(msg, symbol);
+ 	printk("\n");
+ }
+ 
+-static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
++static void print_trace_warning(void *data, char *msg)
++{
++	printk("%s\n", msg);
++}
++
++static int print_trace_stack(void *data, char *name)
++{
++	printk(" <%s> ", name);
++	return 0;
++}
++
++static void print_trace_address(void *data, unsigned long addr)
++{
++	printk_address(addr);
++}
++
++static struct stacktrace_ops print_trace_ops = {
++	.warning = print_trace_warning,
++	.warning_symbol = print_trace_warning_symbol,
++	.stack = print_trace_stack,
++	.address = print_trace_address,
++};
++
++void
++show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack)
++{
++	printk("\nCall Trace:\n");
++	dump_trace(tsk, regs, stack, &print_trace_ops, NULL);
++	printk("\n");
++}
++
++static void
++_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *rsp)
+ {
+ 	unsigned long *stack;
+ 	int i;
+-	const int cpu = safe_smp_processor_id();
++	const int cpu = smp_processor_id();
+ 	unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
+ 	unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
+ 
+@@ -430,7 +482,7 @@ void show_registers(struct pt_regs *regs
+ 	int i;
+ 	int in_kernel = !user_mode(regs);
+ 	unsigned long rsp;
+-	const int cpu = safe_smp_processor_id(); 
++	const int cpu = smp_processor_id();
+ 	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
+ 
+ 		rsp = regs->rsp;
+@@ -505,9 +557,11 @@ static unsigned int die_nest_count;
+ 
+ unsigned __kprobes long oops_begin(void)
+ {
+-	int cpu = safe_smp_processor_id();
++	int cpu = smp_processor_id();
+ 	unsigned long flags;
+ 
++	oops_enter();
++
+ 	/* racy, but better than risking deadlock. */
+ 	local_irq_save(flags);
+ 	if (!spin_trylock(&die_lock)) { 
+@@ -536,6 +590,7 @@ void __kprobes oops_end(unsigned long fl
+ 		spin_unlock_irqrestore(&die_lock, flags);
+ 	if (panic_on_oops)
+ 		panic("Fatal exception");
++	oops_exit();
+ }
+ 
+ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
+@@ -572,8 +627,8 @@ void die(const char * str, struct pt_reg
+ 	do_exit(SIGSEGV); 
+ }
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
+-void __kprobes die_nmi(char *str, struct pt_regs *regs)
++#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_SYSCTL)
++void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
+ {
+ 	unsigned long flags = oops_begin();
+ 
+@@ -581,13 +636,12 @@ void __kprobes die_nmi(char *str, struct
+ 	 * We are in trouble anyway, lets at least try
+ 	 * to get a message out.
+ 	 */
+-	printk(str, safe_smp_processor_id());
++	printk(str, smp_processor_id());
+ 	show_registers(regs);
+ 	if (kexec_should_crash(current))
+ 		crash_kexec(regs);
+-	if (panic_on_timeout || panic_on_oops)
+-		panic("nmi watchdog");
+-	printk("console shuts up ...\n");
++	if (do_panic || panic_on_oops)
++		panic("Non maskable interrupt");
+ 	oops_end(flags);
+ 	nmi_exit();
+ 	local_irq_enable();
+@@ -734,8 +788,15 @@ asmlinkage void __kprobes do_general_pro
+ static __kprobes void
+ mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+-	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+-	printk("You probably have a hardware problem with your RAM chips\n");
++	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
++		reason);
++	printk(KERN_EMERG "You probably have a hardware problem with your "
++		"RAM chips\n");
++
++	if (panic_on_unrecovered_nmi)
++		panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ 
+ #if 0 /* XEN */
+ 	/* Clear and disable the memory parity error line. */
+@@ -762,9 +823,15 @@ io_check_error(unsigned char reason, str
+ 
+ static __kprobes void
+ unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+-{	printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
+-	printk("Dazed and confused, but trying to continue\n");
+-	printk("Do you have a strange power saving mode enabled?\n");
++{
++	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
++		reason);
++	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
++
++	if (panic_on_unrecovered_nmi)
++		panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ }
+ 
+ /* Runs on IST stack. This code must keep interrupts off all the time.
+@@ -789,12 +856,12 @@ asmlinkage __kprobes void default_do_nmi
+ 		 * Ok, so this is none of the documented NMI sources,
+ 		 * so it must be the NMI watchdog.
+ 		 */
+-		if (nmi_watchdog > 0) {
+-			nmi_watchdog_tick(regs,reason);
++		if (nmi_watchdog_tick(regs,reason))
+ 			return;
+-		}
+ #endif
+-		unknown_nmi_error(reason, regs);
++		if (!do_nmi_callback(regs,cpu))
++			unknown_nmi_error(reason, regs);
++
+ 		return;
+ 	}
+ 	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+@@ -1081,6 +1148,7 @@ asmlinkage void math_state_restore(void)
+ 		init_fpu(me);
+ 	restore_fpu_checking(&me->thread.i387.fxsave);
+ 	task_thread_info(me)->status |= TS_USEDFPU;
++	me->fpu_counter++;
+ }
+ 
+ 
+@@ -1141,24 +1209,30 @@ void __cpuinit smp_trap_init(trap_info_t
+ }
+ 
+ 
+-/* Actual parsing is done early in setup.c. */
+-static int __init oops_dummy(char *s)
++static int __init oops_setup(char *s)
+ { 
+-	panic_on_oops = 1;
+-	return 1;
++	if (!s)
++		return -EINVAL;
++	if (!strcmp(s, "panic"))
++		panic_on_oops = 1;
++	return 0;
+ } 
+-__setup("oops=", oops_dummy); 
++early_param("oops", oops_setup);
+ 
+ static int __init kstack_setup(char *s)
+ {
++	if (!s)
++		return -EINVAL;
+ 	kstack_depth_to_print = simple_strtoul(s,NULL,0);
+-	return 1;
++	return 0;
+ }
+-__setup("kstack=", kstack_setup);
++early_param("kstack", kstack_setup);
+ 
+ #ifdef CONFIG_STACK_UNWIND
+ static int __init call_trace_setup(char *s)
+ {
++	if (!s)
++		return -EINVAL;
+ 	if (strcmp(s, "old") == 0)
+ 		call_trace = -1;
+ 	else if (strcmp(s, "both") == 0)
+@@ -1167,7 +1241,7 @@ static int __init call_trace_setup(char 
+ 		call_trace = 1;
+ 	else if (strcmp(s, "new") == 0)
+ 		call_trace = 2;
+-	return 1;
++	return 0;
+ }
+-__setup("call_trace=", call_trace_setup);
++early_param("call_trace", call_trace_setup);
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2007-06-18 08:38:13.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -26,6 +26,10 @@
+ #include <linux/seqlock.h>
+ #include <linux/jiffies.h>
+ #include <linux/sysctl.h>
++#include <linux/getcpu.h>
++#include <linux/cpu.h>
++#include <linux/smp.h>
++#include <linux/notifier.h>
+ 
+ #include <asm/vsyscall.h>
+ #include <asm/pgtable.h>
+@@ -33,11 +37,15 @@
+ #include <asm/fixmap.h>
+ #include <asm/errno.h>
+ #include <asm/io.h>
++#include <asm/segment.h>
++#include <asm/desc.h>
++#include <asm/topology.h>
+ 
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+ 
+ int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
+ seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
++int __vgetcpu_mode __section_vgetcpu_mode;
+ 
+ #include <asm/unistd.h>
+ 
+@@ -61,8 +69,7 @@ static __always_inline void do_vgettimeo
+ 		sequence = read_seqbegin(&__xtime_lock);
+ 		
+ 		sec = __xtime.tv_sec;
+-		usec = (__xtime.tv_nsec / 1000) +
+-			(__jiffies - __wall_jiffies) * (1000000 / HZ);
++		usec = __xtime.tv_nsec / 1000;
+ 
+ 		if (__vxtime.mode != VXTIME_HPET) {
+ 			t = get_cycles_sync();
+@@ -72,7 +79,8 @@ static __always_inline void do_vgettimeo
+ 				 __vxtime.tsc_quot) >> 32;
+ 			/* See comment in x86_64 do_gettimeofday. */
+ 		} else {
+-			usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) -
++			usec += ((readl((void __iomem *)
++				   fix_to_virt(VSYSCALL_HPET) + 0xf0) -
+ 				  __vxtime.last) * __vxtime.quot) >> 32;
+ 		}
+ 	} while (read_seqretry(&__xtime_lock, sequence));
+@@ -127,9 +135,46 @@ time_t __vsyscall(1) vtime(time_t *t)
+ 	return __xtime.tv_sec;
+ }
+ 
+-long __vsyscall(2) venosys_0(void)
+-{
+-	return -ENOSYS;
++/* Fast way to get current CPU and node.
++   This helps to do per node and per CPU caches in user space.
++   The result is not guaranteed without CPU affinity, but usually
++   works out because the scheduler tries to keep a thread on the same
++   CPU.
++
++   tcache must point to a two element sized long array.
++   All arguments can be NULL. */
++long __vsyscall(2)
++vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
++{
++	unsigned int dummy, p;
++	unsigned long j = 0;
++
++	/* Fast cache - only recompute value once per jiffies and avoid
++	   relatively costly rdtscp/cpuid otherwise.
++	   This works because the scheduler usually keeps the process
++	   on the same CPU and this syscall doesn't guarantee its
++	   results anyways.
++	   We do this here because otherwise user space would do it on
++	   its own in a likely inferior way (no access to jiffies).
++	   If you don't like it pass NULL. */
++	if (tcache && tcache->blob[0] == (j = __jiffies)) {
++		p = tcache->blob[1];
++	} else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
++		/* Load per CPU data from RDTSCP */
++		rdtscp(dummy, dummy, p);
++	} else {
++		/* Load per CPU data from GDT */
++		asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
++	}
++	if (tcache) {
++		tcache->blob[0] = j;
++		tcache->blob[1] = p;
++	}
++	if (cpu)
++		*cpu = p & 0xfff;
++	if (node)
++		*node = p >> 12;
++	return 0;
+ }
+ 
+ long __vsyscall(3) venosys_1(void)
+@@ -149,7 +194,8 @@ static int vsyscall_sysctl_change(ctl_ta
+                         void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+ 	extern u16 vsysc1, vsysc2;
+-	u16 *map1, *map2;
++	u16 __iomem *map1;
++	u16 __iomem *map2;
+ 	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+ 	if (!write)
+ 		return ret;
+@@ -164,11 +210,11 @@ static int vsyscall_sysctl_change(ctl_ta
+ 		goto out;
+ 	}
+ 	if (!sysctl_vsyscall) {
+-		*map1 = SYSCALL;
+-		*map2 = SYSCALL;
++		writew(SYSCALL, map1);
++		writew(SYSCALL, map2);
+ 	} else {
+-		*map1 = NOP2;
+-		*map2 = NOP2;
++		writew(NOP2, map1);
++		writew(NOP2, map2);
+ 	}
+ 	iounmap(map2);
+ out:
+@@ -200,6 +246,48 @@ static ctl_table kernel_root_table2[] = 
+ 
+ #endif
+ 
++/* Assume __initcall executes before all user space. Hopefully kmod
++   doesn't violate that. We'll find out if it does. */
++static void __cpuinit vsyscall_set_cpu(int cpu)
++{
++	unsigned long d;
++	unsigned long node = 0;
++#ifdef CONFIG_NUMA
++	node = cpu_to_node[cpu];
++#endif
++	if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP))
++		write_rdtscp_aux((node << 12) | cpu);
++
++	/* Store cpu number in limit so that it can be loaded quickly
++	   in user space in vgetcpu.
++	   12 bits for the CPU and 8 bits for the node. */
++	d = 0x0f40000000000ULL;
++	d |= cpu;
++	d |= (node & 0xf) << 12;
++	d |= (node >> 4) << 48;
++	if (HYPERVISOR_update_descriptor(virt_to_machine(cpu_gdt(cpu)
++							 + GDT_ENTRY_PER_CPU),
++					 d))
++		BUG();
++}
++
++static void __cpuinit cpu_vsyscall_init(void *arg)
++{
++	/* preemption should be already off */
++	vsyscall_set_cpu(raw_smp_processor_id());
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static int __cpuinit
++cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
++{
++	long cpu = (long)arg;
++	if (action == CPU_ONLINE)
++		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
++	return NOTIFY_DONE;
++}
++#endif
++
+ static void __init map_vsyscall(void)
+ {
+ 	extern char __vsyscall_0;
+@@ -214,13 +302,20 @@ static int __init vsyscall_init(void)
+ 			VSYSCALL_ADDR(__NR_vgettimeofday)));
+ 	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
+ 	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
++	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
+ 	map_vsyscall();
+ #ifdef CONFIG_XEN
+ 	sysctl_vsyscall = 0; /* disable vgettimeofay() */
++ 	if (boot_cpu_has(X86_FEATURE_RDTSCP))
++		vgetcpu_mode = VGETCPU_RDTSCP;
++	else
++		vgetcpu_mode = VGETCPU_LSL;
+ #endif
+ #ifdef CONFIG_SYSCTL
+ 	register_sysctl_table(kernel_root_table2, 0);
+ #endif
++	on_each_cpu(cpu_vsyscall_init, NULL, 0, 1);
++	hotcpu_notifier(cpu_vsyscall_notifier, 0);
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2007-11-02 17:34:23.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -40,8 +40,7 @@
+ #define PF_RSVD	(1<<3)
+ #define PF_INSTR	(1<<4)
+ 
+-#ifdef CONFIG_KPROBES
+-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
++static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+ 
+ /* Hook to register for page fault notifications */
+ int register_page_fault_notifier(struct notifier_block *nb)
+@@ -49,11 +48,13 @@ int register_page_fault_notifier(struct 
+ 	vmalloc_sync_all();
+ 	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+ }
++EXPORT_SYMBOL_GPL(register_page_fault_notifier);
+ 
+ int unregister_page_fault_notifier(struct notifier_block *nb)
+ {
+ 	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+ }
++EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
+ 
+ static inline int notify_page_fault(enum die_val val, const char *str,
+ 			struct pt_regs *regs, long err, int trap, int sig)
+@@ -67,13 +68,6 @@ static inline int notify_page_fault(enum
+ 	};
+ 	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+ }
+-#else
+-static inline int notify_page_fault(enum die_val val, const char *str,
+-			struct pt_regs *regs, long err, int trap, int sig)
+-{
+-	return NOTIFY_DONE;
+-}
+-#endif
+ 
+ void bust_spinlocks(int yes)
+ {
+@@ -102,7 +96,7 @@ void bust_spinlocks(int yes)
+ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+ 				unsigned long error_code)
+ { 
+-	unsigned char *instr;
++	unsigned char __user *instr;
+ 	int scan_more = 1;
+ 	int prefetch = 0; 
+ 	unsigned char *max_instr;
+@@ -111,7 +105,7 @@ static noinline int is_prefetch(struct p
+ 	if (error_code & PF_INSTR)
+ 		return 0;
+ 	
+-	instr = (unsigned char *)convert_rip_to_linear(current, regs);
++	instr = (unsigned char __user *)convert_rip_to_linear(current, regs);
+ 	max_instr = instr + 15;
+ 
+ 	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+@@ -122,7 +116,7 @@ static noinline int is_prefetch(struct p
+ 		unsigned char instr_hi;
+ 		unsigned char instr_lo;
+ 
+-		if (__get_user(opcode, instr))
++		if (__get_user(opcode, (char __user *)instr))
+ 			break; 
+ 
+ 		instr_hi = opcode & 0xf0; 
+@@ -160,7 +154,7 @@ static noinline int is_prefetch(struct p
+ 		case 0x00:
+ 			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+ 			scan_more = 0;
+-			if (__get_user(opcode, instr)) 
++			if (__get_user(opcode, (char __user *)instr))
+ 				break;
+ 			prefetch = (instr_lo == 0xF) &&
+ 				(opcode == 0x0D || opcode == 0x18);
+@@ -176,7 +170,7 @@ static noinline int is_prefetch(struct p
+ static int bad_address(void *p) 
+ { 
+ 	unsigned long dummy;
+-	return __get_user(dummy, (unsigned long *)p);
++	return __get_user(dummy, (unsigned long __user *)p);
+ } 
+ 
+ void dump_pagetable(unsigned long address)
+@@ -248,7 +242,7 @@ static int is_errata93(struct pt_regs *r
+ 
+ int unhandled_signal(struct task_struct *tsk, int sig)
+ {
+-	if (tsk->pid == 1)
++	if (is_init(tsk))
+ 		return 1;
+ 	if (tsk->ptrace & PT_PTRACED)
+ 		return 0;
+@@ -300,7 +294,7 @@ static int vmalloc_fault(unsigned long a
+ 	if (pgd_none(*pgd))
+ 		set_pgd(pgd, *pgd_ref);
+ 	else
+-		BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
++		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ 
+ 	/* Below here mismatches are bugs because these lower tables
+ 	   are shared */
+@@ -309,7 +303,7 @@ static int vmalloc_fault(unsigned long a
+ 	pud_ref = pud_offset(pgd_ref, address);
+ 	if (pud_none(*pud_ref))
+ 		return -1;
+-	if (pud_none(*pud) || pud_page(*pud) != pud_page(*pud_ref))
++	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+ 		BUG();
+ 	pmd = pmd_offset(pud, address);
+ 	pmd_ref = pmd_offset(pud_ref, address);
+@@ -531,7 +525,7 @@ good_area:
+ 		case PF_PROT:		/* read, present */
+ 			goto bad_area;
+ 		case 0:			/* read, not present */
+-			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
++			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+ 				goto bad_area;
+ 	}
+ 
+@@ -647,7 +641,7 @@ no_context:
+  */
+ out_of_memory:
+ 	up_read(&mm->mmap_sem);
+-	if (current->pid == 1) { 
++	if (is_init(current)) {
+ 		yield();
+ 		goto again;
+ 	}
+@@ -702,7 +696,7 @@ void vmalloc_sync_all(void)
+ 				if (pgd_none(*pgd))
+ 					set_pgd(pgd, *pgd_ref);
+ 				else
+-					BUG_ON(pgd_page(*pgd) != pgd_page(*pgd_ref));
++					BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ 			}
+ 			spin_unlock(&pgd_lock);
+ 			set_bit(pgd_index(address), insync);
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -61,8 +61,6 @@ EXPORT_SYMBOL(__kernel_page_user);
+ 
+ int after_bootmem;
+ 
+-static unsigned long dma_reserve __initdata;
+-
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ extern unsigned long start_pfn;
+ 
+@@ -420,7 +418,6 @@ __init void *early_ioremap(unsigned long
+ 
+ 	/* actually usually some more */
+ 	if (size >= LARGE_PAGE_SIZE) {
+-		printk("SMBIOS area too long %lu\n", size);
+ 		return NULL;
+ 	}
+ 	set_pmd(temp_mappings[0].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
+@@ -442,16 +439,24 @@ __init void early_iounmap(void *addr, un
+ #endif
+ 
+ static void __meminit
+-phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
++phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ {
+-	int i, k;
++	int i = pmd_index(address);
+ 
+-	for (i = 0; i < PTRS_PER_PMD; pmd++, i++) {
++	for (; i < PTRS_PER_PMD; i++) {
+ 		unsigned long pte_phys;
++		pmd_t *pmd = pmd_page + i;
+ 		pte_t *pte, *pte_save;
++		int k;
+ 
+ 		if (address >= end)
+ 			break;
++
++		if (__pmd_val(*pmd)) {
++			address += PMD_SIZE;
++			continue;
++		}
++
+ 		pte = alloc_static_page(&pte_phys);
+ 		pte_save = pte;
+ 		for (k = 0; k < PTRS_PER_PTE; pte++, k++, address += PTE_SIZE) {
+@@ -478,40 +483,35 @@ phys_pmd_init(pmd_t *pmd, unsigned long 
+ static void __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+ {
+-	pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
+-
+-	if (pmd_none(*pmd)) {
+-		spin_lock(&init_mm.page_table_lock);
+-		phys_pmd_init(pmd, address, end);
+-		spin_unlock(&init_mm.page_table_lock);
+-		__flush_tlb_all();
+-	}
++	pmd_t *pmd = pmd_offset(pud,0);
++	spin_lock(&init_mm.page_table_lock);
++	phys_pmd_init(pmd, address, end);
++	spin_unlock(&init_mm.page_table_lock);
++	__flush_tlb_all();
+ }
+ 
+-static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
++static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+ { 
+-	long i = pud_index(address);
+-
+-	pud = pud + i;
+-
+-	if (after_bootmem && pud_val(*pud)) {
+-		phys_pmd_update(pud, address, end);
+-		return;
+-	}
++	int i = pud_index(addr);
+ 
+-	for (; i < PTRS_PER_PUD; pud++, i++) {
+-		unsigned long paddr, pmd_phys;
++	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE ) {
++		unsigned long pmd_phys;
++		pud_t *pud = pud_page + pud_index(addr);
+ 		pmd_t *pmd;
+ 
+-		paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
+-		if (paddr >= end)
++		if (addr >= end)
+ 			break;
+ 
++		if (__pud_val(*pud)) {
++			phys_pmd_update(pud, addr, end);
++			continue;
++		}
++
+ 		pmd = alloc_static_page(&pmd_phys);
+ 
+ 		spin_lock(&init_mm.page_table_lock);
+ 		*pud = __pud(pmd_phys | _KERNPG_TABLE);
+-		phys_pmd_init(pmd, paddr, end);
++		phys_pmd_init(pmd, addr, end);
+ 		spin_unlock(&init_mm.page_table_lock);
+ 
+ 		early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
+@@ -800,69 +800,18 @@ void __cpuinit zap_low_mappings(int cpu)
+ #endif
+ }
+ 
+-/* Compute zone sizes for the DMA and DMA32 zones in a node. */
+-__init void
+-size_zones(unsigned long *z, unsigned long *h,
+-	   unsigned long start_pfn, unsigned long end_pfn)
+-{
+- 	int i;
+- 	unsigned long w;
+-
+- 	for (i = 0; i < MAX_NR_ZONES; i++)
+- 		z[i] = 0;
+-
+- 	if (start_pfn < MAX_DMA_PFN)
+- 		z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
+- 	if (start_pfn < MAX_DMA32_PFN) {
+- 		unsigned long dma32_pfn = MAX_DMA32_PFN;
+- 		if (dma32_pfn > end_pfn)
+- 			dma32_pfn = end_pfn;
+- 		z[ZONE_DMA32] = dma32_pfn - start_pfn;
+- 	}
+- 	z[ZONE_NORMAL] = end_pfn - start_pfn;
+-
+- 	/* Remove lower zones from higher ones. */
+- 	w = 0;
+- 	for (i = 0; i < MAX_NR_ZONES; i++) {
+- 		if (z[i])
+- 			z[i] -= w;
+- 	        w += z[i];
+-	}
+-
+-	/* Compute holes */
+-	w = start_pfn;
+-	for (i = 0; i < MAX_NR_ZONES; i++) {
+-		unsigned long s = w;
+-		w += z[i];
+-		h[i] = e820_hole_size(s, w);
+-	}
+-
+-	/* Add the space pace needed for mem_map to the holes too. */
+-	for (i = 0; i < MAX_NR_ZONES; i++)
+-		h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
+-
+-	/* The 16MB DMA zone has the kernel and other misc mappings.
+- 	   Account them too */
+-	if (h[ZONE_DMA]) {
+-		h[ZONE_DMA] += dma_reserve;
+-		if (h[ZONE_DMA] >= z[ZONE_DMA]) {
+-			printk(KERN_WARNING
+-				"Kernel too large and filling up ZONE_DMA?\n");
+-			h[ZONE_DMA] = z[ZONE_DMA];
+-		}
+-	}
+-}
+-
+ #ifndef CONFIG_NUMA
+ void __init paging_init(void)
+ {
+-	unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
++	unsigned long max_zone_pfns[MAX_NR_ZONES];
++	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
++	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
++	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
++	max_zone_pfns[ZONE_NORMAL] = end_pfn;
+ 
+ 	memory_present(0, 0, end_pfn);
+ 	sparse_init();
+-	size_zones(zones, holes, 0, end_pfn);
+-	free_area_init_node(0, NODE_DATA(0), zones,
+-			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
++	free_area_init_nodes(max_zone_pfns);
+ 
+ 	init_mm.context.pinned = 1;
+ }
+@@ -916,36 +865,23 @@ void online_page(struct page *page)
+ 
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ /*
+- * XXX: memory_add_physaddr_to_nid() is to find node id from physical address
+- *	via probe interface of sysfs. If acpi notifies hot-add event, then it
+- *	can tell node id by searching dsdt. But, probe interface doesn't have
+- *	node id. So, return 0 as node id at this time.
+- */
+-#ifdef CONFIG_NUMA
+-int memory_add_physaddr_to_nid(u64 start)
+-{
+-	return 0;
+-}
+-#endif
+-
+-/*
+  * Memory is added always to NORMAL zone. This means you will never get
+  * additional DMA/DMA32 memory.
+  */
+ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+ 	struct pglist_data *pgdat = NODE_DATA(nid);
+-	struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
++	struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+ 	unsigned long start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 	int ret;
+ 
++	init_memory_mapping(start, (start + size -1));
++
+ 	ret = __add_pages(zone, start_pfn, nr_pages);
+ 	if (ret)
+ 		goto error;
+ 
+-	init_memory_mapping(start, (start + size -1));
+-
+ 	return ret;
+ error:
+ 	printk("%s: Problem encountered in __add_pages!\n", __func__);
+@@ -959,7 +895,17 @@ int remove_memory(u64 start, u64 size)
+ }
+ EXPORT_SYMBOL_GPL(remove_memory);
+ 
+-#else /* CONFIG_MEMORY_HOTPLUG */
++#if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA)
++int memory_add_physaddr_to_nid(u64 start)
++{
++	return 0;
++}
++EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
++#endif
++
++#endif /* CONFIG_MEMORY_HOTPLUG */
++
++#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+ /*
+  * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
+  * just online the pages.
+@@ -985,7 +931,7 @@ int __add_pages(struct zone *z, unsigned
+ 	}
+ 	return err;
+ }
+-#endif /* CONFIG_MEMORY_HOTPLUG */
++#endif
+ 
+ static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
+ 			 kcore_vsyscall;
+@@ -997,12 +943,6 @@ void __init mem_init(void)
+ 
+ 	pci_iommu_alloc();
+ 
+-	/* How many end-of-memory variables you have, grandma! */
+-	max_low_pfn = end_pfn;
+-	max_pfn = end_pfn;
+-	num_physpages = end_pfn;
+-	high_memory = (void *) __va(end_pfn * PAGE_SIZE);
+-
+ 	/* clear the zero-page */
+ 	memset(empty_zero_page, 0, PAGE_SIZE);
+ 
+@@ -1014,13 +954,13 @@ void __init mem_init(void)
+ #else
+ 	totalram_pages = free_all_bootmem();
+ #endif
+-	/* XEN: init and count pages outside initial allocation. */
++	/* XEN: init pages outside initial allocation. */
+ 	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+ 		ClearPageReserved(pfn_to_page(pfn));
+ 		init_page_count(pfn_to_page(pfn));
+-		totalram_pages++;
+ 	}
+-	reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
++	reservedpages = end_pfn - totalram_pages -
++					absent_pages_in_range(0, end_pfn);
+ 
+ 	after_bootmem = 1;
+ 
+@@ -1127,15 +1067,32 @@ void free_initrd_mem(unsigned long start
+ 
+ void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
+ { 
+-	/* Should check here against the e820 map to avoid double free */ 
+ #ifdef CONFIG_NUMA
+ 	int nid = phys_to_nid(phys);
++#endif
++	unsigned long pfn = phys >> PAGE_SHIFT;
++	if (pfn >= end_pfn) {
++		/* This can happen with kdump kernels when accessing firmware
++		   tables. */
++		if (pfn < end_pfn_map)
++			return;
++		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
++				phys, len);
++		return;
++	}
++
++	/* Should check here against the e820 map to avoid double free */
++#ifdef CONFIG_NUMA
+   	reserve_bootmem_node(NODE_DATA(nid), phys, len);
+ #else       		
+ 	reserve_bootmem(phys, len);    
+ #endif
+-	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
++#ifndef CONFIG_XEN
++	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
+ 		dma_reserve += len / PAGE_SIZE;
++		set_dma_reserve(dma_reserve);
++	}
++#endif
+ }
+ 
+ int kern_addr_valid(unsigned long addr) 
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -377,8 +377,8 @@ static void revert_page(unsigned long ad
+ 	BUG_ON(pud_none(*pud));
+ 	pmd = pmd_offset(pud, address);
+ 	BUG_ON(__pmd_val(*pmd) & _PAGE_PSE);
+-	pgprot_val(ref_prot) |= _PAGE_PSE;
+ 	large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
++	large_pte = pte_mkhuge(large_pte);
+ 	set_pte((pte_t *)pmd, large_pte);
+ }      
+ 
+@@ -388,32 +388,28 @@ __change_page_attr(unsigned long address
+ { 
+ 	pte_t *kpte; 
+ 	struct page *kpte_page;
+-	unsigned kpte_flags;
+ 	pgprot_t ref_prot2;
+ 	kpte = lookup_address(address);
+ 	if (!kpte) return 0;
+ 	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
+-	kpte_flags = pte_val(*kpte); 
+ 	if (pgprot_val(prot) != pgprot_val(ref_prot)) { 
+-		if ((kpte_flags & _PAGE_PSE) == 0) { 
++		if (!pte_huge(*kpte)) {
+ 			set_pte(kpte, pfn_pte(pfn, prot));
+ 		} else {
+  			/*
+ 			 * split_large_page will take the reference for this
+ 			 * change_page_attr on the split page.
+  			 */
+-
+ 			struct page *split;
+-			ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE));
+-
++			ref_prot2 = pte_pgprot(pte_clrhuge(*kpte));
+ 			split = split_large_page(address, prot, ref_prot2);
+ 			if (!split)
+ 				return -ENOMEM;
+-			set_pte(kpte,mk_pte(split, ref_prot2));
++			set_pte(kpte, mk_pte(split, ref_prot2));
+ 			kpte_page = split;
+-		}	
++		}
+ 		page_private(kpte_page)++;
+-	} else if ((kpte_flags & _PAGE_PSE) == 0) { 
++	} else if (!pte_huge(*kpte)) {
+ 		set_pte(kpte, pfn_pte(pfn, ref_prot));
+ 		BUG_ON(page_private(kpte_page) == 0);
+ 		page_private(kpte_page)--;
+@@ -470,10 +466,12 @@ int change_page_attr_addr(unsigned long 
+ 		 * lowmem */
+ 		if (__pa(address) < KERNEL_TEXT_SIZE) {
+ 			unsigned long addr2;
+-			pgprot_t prot2 = prot;
++			pgprot_t prot2;
+ 			addr2 = __START_KERNEL_map + __pa(address);
+- 			pgprot_val(prot2) &= ~_PAGE_NX;
+-			err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC);
++			/* Make sure the kernel mappings stay executable */
++			prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
++			err = __change_page_attr(addr2, pfn, prot2,
++						 PAGE_KERNEL_EXEC);
+ 		} 
+ 	} 	
+ 	up_write(&init_mm.mmap_sem); 
+--- head-2010-01-18.orig/drivers/char/tpm/tpm_xen.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/char/tpm/tpm_xen.c	2009-11-06 10:45:48.000000000 +0100
+@@ -85,8 +85,7 @@ static struct tpm_private *my_priv;
+ 
+ /* local function prototypes */
+ static irqreturn_t tpmif_int(int irq,
+-                             void *tpm_priv,
+-                             struct pt_regs *ptregs);
++                             void *tpm_priv);
+ static void tpmif_rx_action(unsigned long unused);
+ static int tpmif_connect(struct xenbus_device *dev,
+                          struct tpm_private *tp,
+@@ -559,7 +558,7 @@ static void tpmif_rx_action(unsigned lon
+ }
+ 
+ 
+-static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
++static irqreturn_t tpmif_int(int irq, void *tpm_priv)
+ {
+ 	struct tpm_private *tp = tpm_priv;
+ 	unsigned long flags;
+--- head-2010-01-18.orig/drivers/pci/Kconfig	2009-12-04 10:27:49.000000000 +0100
++++ head-2010-01-18/drivers/pci/Kconfig	2009-11-06 10:45:48.000000000 +0100
+@@ -75,7 +75,7 @@ config PCI_STUB
+ config HT_IRQ
+ 	bool "Interrupts on hypertransport devices"
+ 	default y
+-	depends on PCI && X86_LOCAL_APIC && X86_IO_APIC
++	depends on PCI && X86_LOCAL_APIC && X86_IO_APIC && !XEN
+ 	help
+ 	   This allows native hypertransport devices to use interrupts.
+ 
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 08:45:56.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 10:49:14.000000000 +0100
+@@ -6,6 +6,7 @@
+  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
+  */
+ 
++#include <linux/err.h>
+ #include <linux/mm.h>
+ #include <linux/irq.h>
+ #include <linux/interrupt.h>
+@@ -14,6 +15,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/pci.h>
+ #include <linux/proc_fs.h>
++#include <linux/msi.h>
+ 
+ #include <xen/evtchn.h>
+ 
+@@ -26,14 +28,6 @@
+ 
+ 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);
+ 
+@@ -481,9 +475,9 @@ void pci_restore_msix_state(struct pci_d
+  * @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
++ * MSI irq, 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.
++ * of an entry zero with the new MSI irq or non-zero for otherwise.
+  **/
+ static int msi_capability_init(struct pci_dev *dev)
+ {
+@@ -497,11 +491,11 @@ static int msi_capability_init(struct pc
+ 	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;
+ 
++	dev->irq = pirq;
+ 	return 0;
+ }
+ 
+@@ -512,8 +506,8 @@ static int msi_capability_init(struct pc
+  * @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.
++ * single MSI-X irq. A return of zero indicates the successful setup of
++ * requested MSI-X entries with allocated irqs or non-zero for otherwise.
+  **/
+ static int msix_capability_init(struct pci_dev *dev,
+ 				struct msix_entry *entries, int nvec)
+@@ -562,12 +556,18 @@ static int msix_capability_init(struct p
+ 	}
+ 
+ 	if (i != nvec) {
++		int avail = i - 1;
+ 		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;
++		/* If we had some success report the number of irqs
++		 * we succeeded in setting up.
++		 */
++		if (avail <= 0)
++			avail = -EBUSY;
++		return avail;
+ 	}
+ 
+ 	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+@@ -577,11 +577,40 @@ static int msix_capability_init(struct p
+ }
+ 
+ /**
++ * pci_msi_supported - check whether MSI may be enabled on device
++ * @dev: pointer to the pci_dev data structure of MSI device function
++ *
++ * Look at global flags, the device itself, and its parent busses
++ * to return 0 if MSI are supported for the device.
++ **/
++static
++int pci_msi_supported(struct pci_dev * dev)
++{
++	struct pci_bus *bus;
++
++	/* MSI must be globally enabled and supported by the device */
++	if (!pci_msi_enable || !dev || dev->no_msi)
++		return -EINVAL;
++
++	/* Any bridge which does NOT route MSI transactions from it's
++	 * secondary bus to it's primary bus must set NO_MSI flag on
++	 * the secondary pci_bus.
++	 * We expect only arch-specific PCI host bus controller driver
++	 * or quirks for specific PCI bridges to be setting NO_MSI.
++	 */
++	for (bus = dev->bus; bus; bus = bus->parent)
++		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
++			return -EINVAL;
++
++	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
++ * a single MSI irq 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.
+@@ -589,19 +618,11 @@ static int msix_capability_init(struct p
+ 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;
++	int pos, temp, status;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	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;
++	if (pci_msi_supported(dev) < 0)
++ 		return -EINVAL;
+ 
+ 	status = msi_init();
+ 	if (status < 0)
+@@ -631,10 +652,10 @@ int pci_enable_msi(struct pci_dev* dev)
+ 	if (!pos)
+ 		return -EINVAL;
+ 
+-	/* Check whether driver already requested for MSI-X vectors */
++	/* Check whether driver already requested for MSI-X irqs */
+ 	if (dev->msix_enabled) {
+ 		printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
+-			   "Device already has MSI-X vectors assigned\n",
++		       "Device already has MSI-X irq assigned\n",
+ 			   pci_name(dev));
+ 		dev->irq = temp;
+ 		return -EINVAL;
+@@ -699,37 +720,29 @@ void pci_disable_msi(struct pci_dev* dev
+  * 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
++ * @nvec: number of MSI-X irqs 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
++ * of requested irqs 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.
++ * with new allocated MSI-X irqs. 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
++ * of irqs 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;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+-	if (!pci_msi_enable || !dev || !entries)
++	if (!entries || pci_msi_supported(dev) < 0)
+  		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()) {
+ 		struct msi_pirq_entry *pirq_entry;
+@@ -793,7 +806,7 @@ int pci_enable_msix(struct pci_dev* dev,
+ 	/* 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",
++		       "Device already has an MSI irq assigned\n",
+ 		       pci_name(dev));
+ 		dev->irq = temp;
+ 		return -EINVAL;
+@@ -861,11 +874,11 @@ void pci_disable_msix(struct pci_dev* de
+ }
+ 
+ /**
+- * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
++ * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs 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
++ * is hot-removed. All previous assigned MSI/MSI-X irqs, if
+  * allocated for this device function, are reclaimed to unused state,
+  * which may be used later on.
+  **/
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:08:28.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-18 12:13:35.000000000 +0100
+@@ -332,6 +332,10 @@ endmenu
+ config HAVE_IRQ_IGNORE_UNHANDLED
+ 	def_bool y
+ 
++config GENERIC_HARDIRQS_NO__DO_IRQ
++	def_bool y
++	depends on X86
++
+ config NO_IDLE_HZ
+ 	def_bool y
+ 
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2010-01-04 12:19:20.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include <linux/sched.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
++#include <linux/swap.h>
+ #include <linux/mman.h>
+ #include <linux/smp_lock.h>
+ #include <linux/pagemap.h>
+@@ -81,11 +82,7 @@ struct balloon_stats balloon_stats;
+ /* We increase/decrease in batches which fit in a page */
+ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+ 
+-/* VM /proc information for memory */
+-extern unsigned long totalram_pages;
+-
+-#ifndef MODULE
+-extern unsigned long totalhigh_pages;
++#if !defined(MODULE) && defined(CONFIG_HIGHMEM)
+ #define inc_totalhigh_pages() (totalhigh_pages++)
+ #define dec_totalhigh_pages() (totalhigh_pages--)
+ #else
+@@ -121,29 +118,44 @@ static struct timer_list balloon_timer;
+ 	printk(KERN_WARNING "xen_mem: " fmt, ##args)
+ 
+ /* balloon_append: add the given page to the balloon. */
+-static void balloon_append(struct page *page)
++static void balloon_append(struct page *page, int account)
+ {
++	unsigned long pfn;
++
+ 	/* Lowmem is re-populated first, so highmem pages go at list tail. */
+ 	if (PageHighMem(page)) {
+ 		list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
+ 		bs.balloon_high++;
+-		dec_totalhigh_pages();
++		if (account)
++			dec_totalhigh_pages();
+ 	} else {
+ 		list_add(PAGE_TO_LIST(page), &ballooned_pages);
+ 		bs.balloon_low++;
+ 	}
++
++	pfn = page_to_pfn(page);
++	if (account) {
++		SetPageReserved(page);
++		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++		page_zone(page)->present_pages--;
++	} else {
++		BUG_ON(!PageReserved(page));
++		WARN_ON_ONCE(phys_to_machine_mapping_valid(pfn));
++	}
+ }
+ 
+ /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
+-static struct page *balloon_retrieve(void)
++static struct page *balloon_retrieve(int *was_empty)
+ {
+ 	struct page *page;
++	struct zone *zone;
+ 
+ 	if (list_empty(&ballooned_pages))
+ 		return NULL;
+ 
+ 	page = LIST_TO_PAGE(ballooned_pages.next);
+ 	UNLIST_PAGE(page);
++	BUG_ON(!PageReserved(page));
+ 
+ 	if (PageHighMem(page)) {
+ 		bs.balloon_high--;
+@@ -151,6 +163,9 @@ static struct page *balloon_retrieve(voi
+ 	}
+ 	else
+ 		bs.balloon_low--;
++	zone = page_zone(page);
++	*was_empty |= !populated_zone(zone);
++	zone->present_pages++;
+ 
+ 	return page;
+ }
+@@ -236,6 +251,7 @@ static int increase_reservation(unsigned
+ 	unsigned long  pfn, i, flags;
+ 	struct page   *page;
+ 	long           rc;
++	int            need_zonelists_rebuild = 0;
+ 	struct xen_memory_reservation reservation = {
+ 		.address_bits = 0,
+ 		.extent_order = 0,
+@@ -261,7 +277,7 @@ static int increase_reservation(unsigned
+ 		goto out;
+ 
+ 	for (i = 0; i < rc; i++) {
+-		page = balloon_retrieve();
++		page = balloon_retrieve(&need_zonelists_rebuild);
+ 		BUG_ON(page == NULL);
+ 
+ 		pfn = page_to_pfn(page);
+@@ -294,6 +310,18 @@ static int increase_reservation(unsigned
+  out:
+ 	balloon_unlock(flags);
+ 
++#ifndef MODULE
++	setup_per_zone_pages_min();
++# if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
++     || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
++	 /* build_all_zonelists() is __meminit */
++	if (need_zonelists_rebuild)
++		build_all_zonelists();
++	else
++# endif
++		vm_total_pages = nr_free_pagecache_pages();
++#endif
++
+ 	return rc < 0 ? rc : rc != nr_pages;
+ }
+ 
+@@ -352,8 +380,7 @@ static int decrease_reservation(unsigned
+ 	/* No more mappings: invalidate P2M and add to balloon. */
+ 	for (i = 0; i < nr_pages; i++) {
+ 		pfn = mfn_to_pfn(frame_list[i]);
+-		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+-		balloon_append(pfn_to_page(pfn));
++		balloon_append(pfn_to_page(pfn), 1);
+ 	}
+ 
+ 	set_xen_guest_handle(reservation.extent_start, frame_list);
+@@ -538,8 +565,11 @@ static int __init balloon_init(void)
+ 	/* Initialise the balloon with excess memory space. */
+ 	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+ 		page = pfn_to_page(pfn);
+-		if (!PageReserved(page))
+-			balloon_append(page);
++		if (!PageReserved(page)) {
++			SetPageReserved(page);
++			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++			balloon_append(page, 0);
++		}
+ 	}
+ #endif
+ 
+@@ -574,7 +604,7 @@ void balloon_update_driver_allowance(lon
+ static int dealloc_pte_fn(
+ 	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+ {
+-	unsigned long mfn = pte_mfn(*pte);
++	unsigned long pfn, mfn = pte_mfn(*pte);
+ 	int ret;
+ 	struct xen_memory_reservation reservation = {
+ 		.nr_extents   = 1,
+@@ -583,7 +613,9 @@ static int dealloc_pte_fn(
+ 	};
+ 	set_xen_guest_handle(reservation.extent_start, &mfn);
+ 	set_pte_at(&init_mm, addr, pte, __pte_ma(0));
+-	set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
++	pfn = __pa(addr) >> PAGE_SHIFT;
++	set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++	SetPageReserved(pfn_to_page(pfn));
+ 	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
+ 	BUG_ON(ret != 1);
+ 	return 0;
+@@ -652,6 +684,9 @@ struct page **alloc_empty_pages_and_page
+ 		}
+ 
+ 		totalram_pages = --bs.current_pages;
++		if (PageHighMem(page))
++			dec_totalhigh_pages();
++		page_zone(page)->present_pages--;
+ 
+ 		balloon_unlock(flags);
+ 	}
+@@ -666,7 +701,7 @@ struct page **alloc_empty_pages_and_page
+  err:
+ 	balloon_lock(flags);
+ 	while (--i >= 0)
+-		balloon_append(pagevec[i]);
++		balloon_append(pagevec[i], 0);
+ 	balloon_unlock(flags);
+ 	kfree(pagevec);
+ 	pagevec = NULL;
+@@ -684,7 +719,7 @@ void free_empty_pages_and_pagevec(struct
+ 	balloon_lock(flags);
+ 	for (i = 0; i < nr_pages; i++) {
+ 		BUG_ON(page_count(pagevec[i]) != 1);
+-		balloon_append(pagevec[i]);
++		balloon_append(pagevec[i], 0);
+ 	}
+ 	balloon_unlock(flags);
+ 
+@@ -698,7 +733,8 @@ void balloon_release_driver_page(struct 
+ 	unsigned long flags;
+ 
+ 	balloon_lock(flags);
+-	balloon_append(page);
++	balloon_append(page, 1);
++	totalram_pages = --bs.current_pages;
+ 	bs.driver_pages--;
+ 	balloon_unlock(flags);
+ 
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 12:22:06.000000000 +0100
+@@ -291,7 +291,7 @@ static void blkif_notify_work(blkif_t *b
+ 	wake_up(&blkif->wq);
+ }
+ 
+-irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t blkif_be_int(int irq, void *dev_id)
+ {
+ 	blkif_notify_work(dev_id);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/blkback/common.h	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/common.h	2010-01-04 12:22:14.000000000 +0100
+@@ -134,7 +134,7 @@ void blkif_interface_init(void);
+ 
+ void blkif_xenbus_init(void);
+ 
+-irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t blkif_be_int(int irq, void *dev_id);
+ int blkif_schedule(void *arg);
+ 
+ int blkback_barrier(struct xenbus_transaction xbt,
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:17:32.000000000 +0100
+@@ -70,7 +70,7 @@ static int setup_blkring(struct xenbus_d
+ 
+ static void kick_pending_request_queues(struct blkfront_info *);
+ 
+-static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs);
++static irqreturn_t blkif_int(int irq, void *dev_id);
+ static void blkif_restart_queue(void *arg);
+ static void blkif_recover(struct blkfront_info *);
+ static void blkif_completion(struct blk_shadow *);
+@@ -716,7 +716,7 @@ void do_blkif_request(request_queue_t *r
+ }
+ 
+ 
+-static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
++static irqreturn_t blkif_int(int irq, void *dev_id)
+ {
+ 	struct request *req;
+ 	blkif_response_t *bret;
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 12:22:21.000000000 +0100
+@@ -1265,7 +1265,7 @@ static void blkif_notify_work(blkif_t *b
+ 	wake_up(&blkif->wq);
+ }
+ 
+-irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t tap_blkif_be_int(int irq, void *dev_id)
+ {
+ 	blkif_notify_work(dev_id);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/blktap/common.h	2008-09-15 13:40:15.000000000 +0200
++++ head-2010-01-18/drivers/xen/blktap/common.h	2009-11-06 10:45:48.000000000 +0100
+@@ -113,7 +113,7 @@ void tap_blkif_interface_init(void);
+ 
+ void tap_blkif_xenbus_init(void);
+ 
+-irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t tap_blkif_be_int(int irq, void *dev_id);
+ int tap_blkif_schedule(void *arg);
+ 
+ int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif);
+--- head-2010-01-18.orig/drivers/xen/blktap2/sysfs.c	2009-12-16 11:43:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/sysfs.c	2009-12-09 15:32:16.000000000 +0100
+@@ -150,7 +150,7 @@ blktap_sysfs_pause_device(struct class_d
+ 	err = blktap_device_pause(tap);
+ 	if (!err) {
+ 		class_device_remove_file(dev, &class_device_attr_pause);
+-		class_device_create_file(dev, &class_device_attr_resume);
++		err = class_device_create_file(dev, &class_device_attr_resume);
+ 	}
+ 
+ out:
+@@ -182,7 +182,7 @@ blktap_sysfs_resume_device(struct class_
+ 	err = blktap_device_resume(tap);
+ 	if (!err) {
+ 		class_device_remove_file(dev, &class_device_attr_resume);
+-		class_device_create_file(dev, &class_device_attr_pause);
++		err = class_device_create_file(dev, &class_device_attr_pause);
+ 	}
+ 
+ out:
+@@ -292,6 +292,7 @@ blktap_sysfs_create(struct blktap *tap)
+ {
+ 	struct blktap_ring *ring;
+ 	struct class_device *dev;
++	int err, state = 0;
+ 
+ 	if (!class)
+ 		return -ENODEV;
+@@ -310,12 +311,27 @@ blktap_sysfs_create(struct blktap *tap)
+ 	atomic_set(&ring->sysfs_refcnt, 0);
+ 	set_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+ 
+-	class_device_create_file(dev, &class_device_attr_name);
+-	class_device_create_file(dev, &class_device_attr_remove);
+-	class_device_create_file(dev, &class_device_attr_pause);
+-	class_device_create_file(dev, &class_device_attr_debug);
++	err = class_device_create_file(dev, &class_device_attr_name);
++	if (!err) {
++		++state;
++		err = class_device_create_file(dev, &class_device_attr_remove);
++	}
++	if (!err) {
++		++state;
++		err = class_device_create_file(dev, &class_device_attr_pause);
++	}
++	if (!err) {
++		++state;
++		err = class_device_create_file(dev, &class_device_attr_debug);
++	}
+ 
+-	return 0;
++	switch (state * !!err) {
++	case 3: class_device_remove_file(dev, &class_device_attr_pause);
++	case 2: class_device_remove_file(dev, &class_device_attr_remove);
++	case 1: class_device_remove_file(dev, &class_device_attr_name);
++	}
++
++	return err;
+ }
+ 
+ int
+@@ -409,6 +425,7 @@ int __init
+ blktap_sysfs_init(void)
+ {
+ 	struct class *cls;
++	int err;
+ 
+ 	if (class)
+ 		return -EEXIST;
+@@ -417,9 +434,16 @@ blktap_sysfs_init(void)
+ 	if (IS_ERR(cls))
+ 		return PTR_ERR(cls);
+ 
+-	class_create_file(cls, &class_attr_verbosity);
+-	class_create_file(cls, &class_attr_devices);
++	err = class_create_file(cls, &class_attr_verbosity);
++	if (!err) {
++		err = class_create_file(cls, &class_attr_devices);
++		if (err)
++			class_remove_file(cls, &class_attr_verbosity);
++	}
++	if (!err)
++		class = cls;
++	else
++		class_destroy(cls);
+ 
+-	class = cls;
+-	return 0;
++	return err;
+ }
+--- head-2010-01-18.orig/drivers/xen/console/console.c	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/drivers/xen/console/console.c	2009-11-06 10:45:48.000000000 +0100
+@@ -360,7 +360,7 @@ static struct tty_struct *xencons_tty;
+ static int xencons_priv_irq;
+ static char x_char;
+ 
+-void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
++void xencons_rx(char *buf, unsigned len)
+ {
+ 	int           i;
+ 	unsigned long flags;
+@@ -385,8 +385,7 @@ void xencons_rx(char *buf, unsigned len,
+ 				if (time_before(jiffies, sysrq_timeout)) {
+ 					spin_unlock_irqrestore(
+ 						&xencons_lock, flags);
+-					handle_sysrq(
+-						buf[i], regs, xencons_tty);
++					handle_sysrq(buf[i], xencons_tty);
+ 					spin_lock_irqsave(
+ 						&xencons_lock, flags);
+ 					continue;
+@@ -451,14 +450,13 @@ void xencons_tx(void)
+ }
+ 
+ /* Privileged receive callback and transmit kicker. */
+-static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
+-					  struct pt_regs *regs)
++static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id)
+ {
+ 	static char rbuf[16];
+ 	int         l;
+ 
+ 	while ((l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0)
+-		xencons_rx(rbuf, l, regs);
++		xencons_rx(rbuf, l);
+ 
+ 	xencons_tx();
+ 
+@@ -646,7 +644,7 @@ static void xencons_close(struct tty_str
+ 	spin_unlock_irqrestore(&xencons_lock, flags);
+ }
+ 
+-static struct tty_operations xencons_ops = {
++static const struct tty_operations xencons_ops = {
+ 	.open = xencons_open,
+ 	.close = xencons_close,
+ 	.write = xencons_write,
+--- head-2010-01-18.orig/drivers/xen/console/xencons_ring.c	2007-06-12 13:13:44.000000000 +0200
++++ head-2010-01-18/drivers/xen/console/xencons_ring.c	2009-11-06 10:45:48.000000000 +0100
+@@ -83,7 +83,7 @@ int xencons_ring_send(const char *data, 
+ 	return sent;
+ }
+ 
+-static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
++static irqreturn_t handle_input(int irq, void *unused)
+ {
+ 	struct xencons_interface *intf = xencons_interface();
+ 	XENCONS_RING_IDX cons, prod;
+@@ -94,7 +94,7 @@ static irqreturn_t handle_input(int irq,
+ 	BUG_ON((prod - cons) > sizeof(intf->in));
+ 
+ 	while (cons != prod) {
+-		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
++		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1);
+ 		cons++;
+ 	}
+ 
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:45:48.000000000 +0100
+@@ -516,7 +516,7 @@ static void unbind_from_irq(unsigned int
+ 
+ int bind_caller_port_to_irqhandler(
+ 	unsigned int caller_port,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id)
+@@ -539,7 +539,7 @@ EXPORT_SYMBOL_GPL(bind_caller_port_to_ir
+ 
+ int bind_listening_port_to_irqhandler(
+ 	unsigned int remote_domain,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id)
+@@ -563,7 +563,7 @@ EXPORT_SYMBOL_GPL(bind_listening_port_to
+ int bind_interdomain_evtchn_to_irqhandler(
+ 	unsigned int remote_domain,
+ 	unsigned int remote_port,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id)
+@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(bind_interdomain_evtch
+ int bind_virq_to_irqhandler(
+ 	unsigned int virq,
+ 	unsigned int cpu,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id)
+@@ -611,7 +611,7 @@ EXPORT_SYMBOL_GPL(bind_virq_to_irqhandle
+ int bind_ipi_to_irqhandler(
+ 	unsigned int ipi,
+ 	unsigned int cpu,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id)
+@@ -696,15 +696,7 @@ static unsigned int startup_dynirq(unsig
+ 	return 0;
+ }
+ 
+-static void shutdown_dynirq(unsigned int irq)
+-{
+-	int evtchn = evtchn_from_irq(irq);
+-
+-	if (VALID_EVTCHN(evtchn))
+-		mask_evtchn(evtchn);
+-}
+-
+-static void enable_dynirq(unsigned int irq)
++static void unmask_dynirq(unsigned int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+@@ -712,7 +704,7 @@ static void enable_dynirq(unsigned int i
+ 		unmask_evtchn(evtchn);
+ }
+ 
+-static void disable_dynirq(unsigned int irq)
++static void mask_dynirq(unsigned int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+@@ -740,12 +732,13 @@ static void end_dynirq(unsigned int irq)
+ 		unmask_evtchn(evtchn);
+ }
+ 
+-static struct hw_interrupt_type dynirq_type = {
+-	.typename = "Dynamic-irq",
++static struct irq_chip dynirq_chip = {
++	.name     = "Dynamic",
+ 	.startup  = startup_dynirq,
+-	.shutdown = shutdown_dynirq,
+-	.enable   = enable_dynirq,
+-	.disable  = disable_dynirq,
++	.shutdown = mask_dynirq,
++	.mask     = mask_dynirq,
++	.unmask   = unmask_dynirq,
++	.mask_ack = ack_dynirq,
+ 	.ack      = ack_dynirq,
+ 	.end      = end_dynirq,
+ #ifdef CONFIG_SMP
+@@ -859,12 +852,12 @@ static void shutdown_pirq(unsigned int i
+ 	irq_info[irq] = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
+ }
+ 
+-static void enable_pirq(unsigned int irq)
++static void unmask_pirq(unsigned int irq)
+ {
+ 	startup_pirq(irq);
+ }
+ 
+-static void disable_pirq(unsigned int irq)
++static void mask_pirq(unsigned int irq)
+ {
+ }
+ 
+@@ -891,12 +884,13 @@ static void end_pirq(unsigned int irq)
+ 		pirq_unmask_and_notify(evtchn, irq);
+ }
+ 
+-static struct hw_interrupt_type pirq_type = {
+-	.typename = "Phys-irq",
++static struct irq_chip pirq_chip = {
++	.name     = "Phys",
+ 	.startup  = startup_pirq,
+ 	.shutdown = shutdown_pirq,
+-	.enable   = enable_pirq,
+-	.disable  = disable_pirq,
++	.mask     = mask_pirq,
++	.unmask   = unmask_pirq,
++	.mask_ack = ack_pirq,
+ 	.ack      = ack_pirq,
+ 	.end      = end_pirq,
+ #ifdef CONFIG_SMP
+@@ -1081,7 +1075,8 @@ void evtchn_register_pirq(int irq)
+ 	if (identity_mapped_irq(irq) || type_from_irq(irq) != IRQT_UNBOUND)
+ 		return;
+ 	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
+-	irq_desc[irq].chip = &pirq_type;
++	set_irq_chip_and_handler_name(irq, &pirq_chip, handle_level_irq,
++				      "level");
+ }
+ 
+ int evtchn_map_pirq(int irq, int xen_pirq)
+@@ -1104,11 +1099,18 @@ int evtchn_map_pirq(int irq, int xen_pir
+ 		spin_unlock(&irq_alloc_lock);
+ 		if (irq < PIRQ_BASE)
+ 			return -ENOSPC;
+-		irq_desc[irq].chip = &pirq_type;
++		set_irq_chip_and_handler_name(irq, &pirq_chip,
++					      handle_level_irq, "level");
+ 	} else if (!xen_pirq) {
+ 		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
+ 			return -EINVAL;
+-		irq_desc[irq].chip = &no_irq_type;
++		/*
++		 * dynamic_irq_cleanup(irq) would seem to be the correct thing
++		 * here, but cannot be used as we get here also during shutdown
++		 * when a driver didn't free_irq() its MSI(-X) IRQ(s), which
++		 * then causes a warning in dynamic_irq_cleanup().
++		 */
++		set_irq_chip_and_handler(irq, NULL, NULL);
+ 		irq_info[irq] = IRQ_UNBOUND;
+ 		return 0;
+ 	} else if (type_from_irq(irq) != IRQT_PIRQ
+@@ -1154,10 +1156,9 @@ void __init xen_init_IRQ(void)
+ 	for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
+ 		irq_bindcount[i] = 0;
+ 
+-		irq_desc[i].status = IRQ_DISABLED|IRQ_NOPROBE;
+-		irq_desc[i].action = NULL;
+-		irq_desc[i].depth = 1;
+-		irq_desc[i].chip = &dynirq_type;
++		irq_desc[i].status |= IRQ_NOPROBE;
++		set_irq_chip_and_handler_name(i, &dynirq_chip,
++					      handle_level_irq, "level");
+ 	}
+ 
+ 	/* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+@@ -1173,9 +1174,7 @@ void __init xen_init_IRQ(void)
+ 			continue;
+ #endif
+ 
+-		irq_desc[i].status = IRQ_DISABLED;
+-		irq_desc[i].action = NULL;
+-		irq_desc[i].depth = 1;
+-		irq_desc[i].chip = &pirq_type;
++		set_irq_chip_and_handler_name(i, &pirq_chip,
++					      handle_level_irq, "level");
+ 	}
+ }
+--- head-2010-01-18.orig/drivers/xen/core/gnttab.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/gnttab.c	2009-12-15 09:20:45.000000000 +0100
+@@ -510,6 +510,7 @@ static void gnttab_page_free(struct page
+ 	BUG_ON(order);
+ 	ClearPageForeign(page);
+ 	gnttab_reset_grant_page(page);
++	ClearPageReserved(page);
+ 	put_page(page);
+ }
+ 
+@@ -587,6 +588,8 @@ int gnttab_copy_grant_page(grant_ref_t r
+ 	new_page->mapping = page->mapping;
+ 	new_page->index = page->index;
+ 	set_bit(PG_foreign, &new_page->flags);
++	if (PageReserved(page))
++		SetPageReserved(new_page);
+ 	*pagep = new_page;
+ 
+ 	SetPageForeign(page, gnttab_page_free);
+--- head-2010-01-18.orig/drivers/xen/core/reboot.c	2008-08-07 12:44:36.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/reboot.c	2009-11-06 10:45:48.000000000 +0100
+@@ -14,6 +14,7 @@
+ 
+ #ifdef HAVE_XEN_PLATFORM_COMPAT_H
+ #include <xen/platform-compat.h>
++#undef handle_sysrq
+ #endif
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
+@@ -231,7 +232,7 @@ static void sysrq_handler(struct xenbus_
+ 
+ #ifdef CONFIG_MAGIC_SYSRQ
+ 	if (sysrq_key != '\0')
+-		handle_sysrq(sysrq_key, NULL, NULL);
++		handle_sysrq(sysrq_key, NULL);
+ #endif
+ }
+ 
+@@ -245,7 +246,7 @@ static struct xenbus_watch sysrq_watch =
+ 	.callback = sysrq_handler
+ };
+ 
+-static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
++static irqreturn_t suspend_int(int irq, void* dev_id)
+ {
+ 	switch_shutdown_state(SHUTDOWN_SUSPEND);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:45:48.000000000 +0100
+@@ -25,8 +25,8 @@
+ #include <xen/cpu_hotplug.h>
+ #include <xen/xenbus.h>
+ 
+-extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
+-extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
++extern irqreturn_t smp_reschedule_interrupt(int, void *);
++extern irqreturn_t smp_call_function_interrupt(int, void *);
+ 
+ extern int local_setup_timer(unsigned int cpu);
+ extern void local_teardown_timer(unsigned int cpu);
+@@ -61,8 +61,6 @@ cpumask_t cpu_core_map[NR_CPUS] __cachel
+ #if defined(__i386__)
+ u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
+ EXPORT_SYMBOL(x86_cpu_to_apicid);
+-#elif !defined(CONFIG_X86_IO_APIC)
+-unsigned int maxcpus = NR_CPUS;
+ #endif
+ 
+ void __init prefill_possible_map(void)
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenfb.c	2009-12-04 08:45:56.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-11-06 10:45:48.000000000 +0100
+@@ -524,8 +524,7 @@ static struct fb_ops xenfb_fb_ops = {
+ 	.fb_set_par     = xenfb_set_par,
+ };
+ 
+-static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
+-				       struct pt_regs *regs)
++static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
+ {
+ 	/*
+ 	 * No in events recognized, simply ignore them all.
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenkbd.c	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:45:48.000000000 +0100
+@@ -46,7 +46,7 @@ static void xenkbd_disconnect_backend(st
+  * to do that.
+  */
+ 
+-static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t input_handler(int rq, void *dev_id)
+ {
+ 	struct xenkbd_info *info = dev_id;
+ 	struct xenkbd_page *page = info->page;
+--- head-2010-01-18.orig/drivers/xen/gntdev/gntdev.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/gntdev/gntdev.c	2010-01-04 12:22:26.000000000 +0100
+@@ -761,9 +761,6 @@ static pte_t gntdev_clear_pte(struct vm_
+ 		BUG();
+ 	}
+ 
+-	/* Copy the existing value of the PTE for returning. */
+-	copy = *ptep;
+-
+ 	/* Calculate the grant relating to this PTE. */
+ 	slot_index = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
+ 
+@@ -778,6 +775,10 @@ static pte_t gntdev_clear_pte(struct vm_
+ 		    GNTDEV_INVALID_HANDLE && 
+ 		    !xen_feature(XENFEAT_auto_translated_physmap)) {
+ 			/* NOT USING SHADOW PAGE TABLES. */
++
++			/* Copy the existing value of the PTE for returning. */
++			copy = *ptep;
++
+ 			gnttab_set_unmap_op(&op, ptep_to_machine(ptep), 
+ 					    GNTMAP_contains_pte,
+ 					    private_data->grants[slot_index]
+@@ -790,7 +791,7 @@ static pte_t gntdev_clear_pte(struct vm_
+ 				       op.status);
+ 		} else {
+ 			/* USING SHADOW PAGE TABLES. */
+-			pte_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++			copy = ptep_get_and_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
+ 		}
+ 
+ 		/* Finally, we unmap the grant from kernel space. */
+@@ -818,7 +819,7 @@ static pte_t gntdev_clear_pte(struct vm_
+ 			INVALID_P2M_ENTRY);
+ 
+ 	} else {
+-		pte_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++		copy = ptep_get_and_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
+ 	}
+ 
+ 	return copy;
+--- head-2010-01-18.orig/drivers/xen/netback/accel.c	2008-01-07 13:19:18.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/accel.c	2009-11-06 10:45:48.000000000 +0100
+@@ -65,7 +65,7 @@ static int match_accelerator(struct xenb
+ 	
+ 	if (IS_ERR(eth_name)) {
+ 		/* Probably means not present */
+-		DPRINTK("%s: no match due to xenbus_read accel error %d\n", 
++		DPRINTK("%s: no match due to xenbus_read accel error %ld\n",
+ 			__FUNCTION__, PTR_ERR(eth_name));
+ 		return 0;
+ 	} else {
+--- head-2010-01-18.orig/drivers/xen/netback/common.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/common.h	2009-11-06 10:45:48.000000000 +0100
+@@ -203,7 +203,7 @@ void netif_deschedule_work(netif_t *neti
+ 
+ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
+ struct net_device_stats *netif_be_get_stats(struct net_device *dev);
+-irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t netif_be_int(int irq, void *dev_id);
+ 
+ static inline int netbk_can_queue(struct net_device *dev)
+ {
+--- head-2010-01-18.orig/drivers/xen/netback/loopback.c	2007-08-06 15:10:49.000000000 +0200
++++ head-2010-01-18/drivers/xen/netback/loopback.c	2009-11-06 10:45:48.000000000 +0100
+@@ -151,7 +151,7 @@ static int loopback_start_xmit(struct sk
+ 	np->stats.rx_bytes += skb->len;
+ 	np->stats.rx_packets++;
+ 
+-	if (skb->ip_summed == CHECKSUM_HW) {
++	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Defer checksum calculation. */
+ 		skb->proto_csum_blank = 1;
+ 		/* Must be a local packet: assert its integrity. */
+--- head-2010-01-18.orig/drivers/xen/netback/netback.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/netback.c	2010-01-04 12:22:49.000000000 +0100
+@@ -711,7 +711,7 @@ static void net_rx_action(unsigned long 
+ 		id = meta[npo.meta_cons].id;
+ 		flags = nr_frags ? NETRXF_more_data : 0;
+ 
+-		if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
++		if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+ 			flags |= NETRXF_csum_blank | NETRXF_data_validated;
+ 		else if (skb->proto_data_valid) /* remote but checksummed? */
+ 			flags |= NETRXF_data_validated;
+@@ -1518,7 +1518,7 @@ static void netif_page_release(struct pa
+ 	netif_idx_release(idx);
+ }
+ 
+-irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t netif_be_int(int irq, void *dev_id)
+ {
+ 	netif_t *netif = dev_id;
+ 
+@@ -1585,7 +1585,7 @@ static netif_rx_response_t *make_rx_resp
+ }
+ 
+ #ifdef NETBE_DEBUG_INTERRUPT
+-static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t netif_be_dbg(int irq, void *dev_id)
+ {
+ 	struct list_head *ent;
+ 	netif_t *netif;
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-04-07 13:58:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:45:48.000000000 +0100
+@@ -136,7 +136,7 @@ static inline int netif_needs_gso(struct
+ {
+         return skb_is_gso(skb) &&
+                (!skb_gso_ok(skb, dev->features) ||
+-                unlikely(skb->ip_summed != CHECKSUM_HW));
++                unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
+ }
+ #else
+ #define HAVE_GSO			0
+@@ -222,7 +222,7 @@ static void network_tx_buf_gc(struct net
+ static void network_alloc_rx_buffers(struct net_device *);
+ static void send_fake_arp(struct net_device *);
+ 
+-static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs);
++static irqreturn_t netif_int(int irq, void *dev_id);
+ 
+ #ifdef CONFIG_SYSFS
+ static int xennet_sysfs_addif(struct net_device *netdev);
+@@ -992,7 +992,7 @@ static int network_start_xmit(struct sk_
+ 	tx->flags = 0;
+ 	extra = NULL;
+ 
+-	if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
++	if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+ 		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
+ #ifdef CONFIG_XEN
+ 	if (skb->proto_data_valid) /* remote but checksummed? */
+@@ -1049,7 +1049,7 @@ static int network_start_xmit(struct sk_
+ 	return 0;
+ }
+ 
+-static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
++static irqreturn_t netif_int(int irq, void *dev_id)
+ {
+ 	struct net_device *dev = dev_id;
+ 	struct netfront_info *np = netdev_priv(dev);
+--- head-2010-01-18.orig/drivers/xen/pciback/pciback.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/pciback.h	2009-11-06 10:45:48.000000000 +0100
+@@ -99,7 +99,7 @@ int pciback_publish_pci_roots(struct pci
+ 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);
++irqreturn_t pciback_handle_event(int irq, void *dev_id);
+ void pciback_do_op(void *data);
+ 
+ int pciback_xenbus_register(void);
+--- head-2010-01-18.orig/drivers/xen/pciback/pciback_ops.c	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/pciback_ops.c	2009-11-06 10:45:48.000000000 +0100
+@@ -124,7 +124,7 @@ void pciback_do_op(void *data)
+ 	test_and_schedule_op(pdev);
+ }
+ 
+-irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t pciback_handle_event(int irq, void *dev_id)
+ {
+ 	struct pciback_device *pdev = dev_id;
+ 
+--- head-2010-01-18.orig/drivers/xen/pcifront/pcifront.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/pcifront.h	2009-11-06 10:45:48.000000000 +0100
+@@ -50,6 +50,6 @@ void pcifront_free_roots(struct pcifront
+ 
+ void pcifront_do_aer( void *data);
+ 
+-irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs);
++irqreturn_t pcifront_handler_aer(int irq, void *dev);
+ 
+ #endif	/* __XEN_PCIFRONT_H__ */
+--- head-2010-01-18.orig/drivers/xen/pcifront/pci_op.c	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/pci_op.c	2009-11-06 10:45:48.000000000 +0100
+@@ -530,10 +530,16 @@ int __devinit pcifront_rescan_root(struc
+ 
+ 		d = pci_scan_single_device(b, devfn);
+ 		if (d) {
++			int err;
++
+ 			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);
++			err = pci_bus_add_device(d);
++			if (err)
++				dev_err(&pdev->xdev->dev,
++				        "error %d adding device, continuing.\n",
++					err);
+ 		}
+ 	}
+ 
+@@ -658,7 +664,7 @@ void pcifront_do_aer(void *data)
+ 
+ }
+ 
+-irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs)
++irqreturn_t pcifront_handler_aer(int irq, void *dev)
+ {
+ 	struct pcifront_device *pdev = dev;
+ 	schedule_pcifront_aer_op(pdev);
+--- head-2010-01-18.orig/drivers/xen/privcmd/compat_privcmd.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/privcmd/compat_privcmd.c	2009-11-06 10:45:48.000000000 +0100
+@@ -18,7 +18,6 @@
+  * Authors: Jimi Xenidis <jimix@watson.ibm.com>
+  */
+ 
+-#include <linux/config.h>
+ #include <linux/compat.h>
+ #include <linux/ioctl.h>
+ #include <linux/syscalls.h>
+--- head-2010-01-18.orig/drivers/xen/privcmd/privcmd.c	2010-01-19 10:14:18.000000000 +0100
++++ head-2010-01-18/drivers/xen/privcmd/privcmd.c	2010-01-19 10:37:11.000000000 +0100
+@@ -71,43 +71,16 @@ static long privcmd_ioctl(struct file *f
+ 		if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
+ 			return -EFAULT;
+ 
++#ifdef CONFIG_X86
+ 		ret = -ENOSYS;
+-#if defined(__i386__)
+ 		if (hypercall.op >= (PAGE_SIZE >> 5))
+ 			break;
+-		__asm__ __volatile__ (
+-			"pushl %%ebx; pushl %%ecx; pushl %%edx; "
+-			"pushl %%esi; pushl %%edi; "
+-			"movl  8(%%eax),%%ebx ;"
+-			"movl 16(%%eax),%%ecx ;"
+-			"movl 24(%%eax),%%edx ;"
+-			"movl 32(%%eax),%%esi ;"
+-			"movl 40(%%eax),%%edi ;"
+-			"movl   (%%eax),%%eax ;"
+-			"shll $5,%%eax ;"
+-			"addl $hypercall_page,%%eax ;"
+-			"call *%%eax ;"
+-			"popl %%edi; popl %%esi; popl %%edx; "
+-			"popl %%ecx; popl %%ebx"
+-			: "=a" (ret) : "0" (&hypercall) : "memory" );
+-#elif defined (__x86_64__)
+-		if (hypercall.op < (PAGE_SIZE >> 5)) {
+-			long ign1, ign2, ign3;
+-			__asm__ __volatile__ (
+-				"movq %8,%%r10; movq %9,%%r8;"
+-				"shll $5,%%eax ;"
+-				"addq $hypercall_page,%%rax ;"
+-				"call *%%rax"
+-				: "=a" (ret), "=D" (ign1),
+-				  "=S" (ign2), "=d" (ign3)
+-				: "0" ((unsigned int)hypercall.op),
+-				"1" (hypercall.arg[0]),
+-				"2" (hypercall.arg[1]),
+-				"3" (hypercall.arg[2]),
+-				"g" (hypercall.arg[3]),
+-				"g" (hypercall.arg[4])
+-				: "r8", "r10", "memory" );
+-		}
++		ret = _hypercall(long, (unsigned int)hypercall.op,
++				 (unsigned long)hypercall.arg[0],
++				 (unsigned long)hypercall.arg[1],
++				 (unsigned long)hypercall.arg[2],
++				 (unsigned long)hypercall.arg[3],
++				 (unsigned long)hypercall.arg[4]);
+ #else
+ 		ret = privcmd_hypercall(&hypercall);
+ #endif
+@@ -445,7 +418,7 @@ static int privcmd_mmap(struct file * fi
+ 		return -ENOSYS;
+ 
+ 	/* DONTCOPY is essential for Xen as copy_page_range is broken. */
+-	vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
++	vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTCOPY;
+ 	vma->vm_ops = &privcmd_vm_ops;
+ 	vma->vm_private_data = NULL;
+ 
+--- head-2010-01-18.orig/drivers/xen/scsiback/common.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/common.h	2009-11-06 10:45:48.000000000 +0100
+@@ -147,7 +147,7 @@ typedef struct {
+ 
+ #define VSCSI_TYPE_HOST		1
+ 
+-irqreturn_t scsiback_intr(int, void *, struct pt_regs *);
++irqreturn_t scsiback_intr(int, void *);
+ int scsiback_init_sring(struct vscsibk_info *info,
+ 		unsigned long ring_ref, unsigned int evtchn);
+ int scsiback_schedule(void *data);
+--- head-2010-01-18.orig/drivers/xen/scsiback/scsiback.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/scsiback.c	2010-01-04 12:23:07.000000000 +0100
+@@ -467,7 +467,7 @@ void scsiback_cmd_exec(pending_req_t *pe
+ 	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_type = REQ_TYPE_BLOCK_PC;
+ 	rq->cmd_len = cmd_len;
+ 	memcpy(rq->cmd, pending_req->cmnd, cmd_len);
+ 
+@@ -511,7 +511,7 @@ static void scsiback_device_reset_exec(p
+ }
+ 
+ 
+-irqreturn_t scsiback_intr(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t scsiback_intr(int irq, void *dev_id)
+ {
+ 	scsiback_notify_work((struct vscsibk_info *)dev_id);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/scsifront/common.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/common.h	2009-11-06 10:45:48.000000000 +0100
+@@ -129,7 +129,7 @@ struct vscsifrnt_info {
+ 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);
++irqreturn_t scsifront_intr(int irq, void *dev_id);
+ int scsifront_cmd_done(struct vscsifrnt_info *info);
+ 
+ 
+--- head-2010-01-18.orig/drivers/xen/scsifront/scsifront.c	2008-07-21 11:00:33.000000000 +0200
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2009-11-06 10:45:48.000000000 +0100
+@@ -100,7 +100,7 @@ static void scsifront_do_request(struct 
+ 		notify_remote_via_irq(irq);
+ }
+ 
+-irqreturn_t scsifront_intr(int irq, void *dev_id, struct pt_regs *ptregs)
++irqreturn_t scsifront_intr(int irq, void *dev_id)
+ {
+ 	scsifront_notify_work((struct vscsifrnt_info *)dev_id);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_xenbus.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_xenbus.c	2010-01-04 12:23:14.000000000 +0100
+@@ -69,8 +69,7 @@ static void unlink_bend(struct netback_a
+ 
+ 
+ /* Demultiplex a message IRQ from the frontend driver.  */
+-static irqreturn_t msgirq_from_frontend(int irq, void *context, 
+-				     struct pt_regs *unused)
++static irqreturn_t msgirq_from_frontend(int irq, void *context)
+ {
+ 	struct xenbus_device *dev = context;
+ 	struct netback_accel *bend = NETBACK_ACCEL_FROM_XENBUS_DEVICE(dev);
+@@ -85,8 +84,7 @@ static irqreturn_t msgirq_from_frontend(
+  * 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)
++static irqreturn_t netirq_from_frontend(int irq, void *context)
+ {
+ 	VPRINTK("netirq %d from device %s\n", irq,
+ 		((struct xenbus_device *)context)->nodename);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel.h	2009-04-07 13:58:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel.h	2009-11-06 10:45:48.000000000 +0100
+@@ -467,10 +467,8 @@ void netfront_accel_msg_tx_fastpath(netf
+ 				    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);
++irqreturn_t netfront_accel_msg_channel_irq_from_bend(int irq, void *context);
++irqreturn_t netfront_accel_net_channel_irq_from_bend(int irq, void *context);
+ 
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+ extern void netfront_accel_msg_from_bend(struct work_struct *context);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_msg.c	2009-04-07 13:58:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:45:48.000000000 +0100
+@@ -488,8 +488,7 @@ void netfront_accel_msg_from_bend(void *
+ }
+ 
+ 
+-irqreturn_t netfront_accel_msg_channel_irq_from_bend(int irq, void *context, 
+-						 struct pt_regs *unused)
++irqreturn_t netfront_accel_msg_channel_irq_from_bend(int irq, void *context)
+ {
+ 	netfront_accel_vnic *vnic = (netfront_accel_vnic *)context;
+ 	VPRINTK("irq %d from device %s\n", irq, vnic->dev->nodename);
+@@ -500,8 +499,7 @@ irqreturn_t netfront_accel_msg_channel_i
+ }
+ 
+ /* 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)
++irqreturn_t netfront_accel_net_channel_irq_from_bend(int irq, void *context)
+ {
+ 	netfront_accel_vnic *vnic = (netfront_accel_vnic *)context;
+ 	struct net_device *net_dev = vnic->net_dev;
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_tso.c	2008-02-26 10:54:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_tso.c	2009-11-06 10:45:48.000000000 +0100
+@@ -363,7 +363,7 @@ int netfront_accel_enqueue_skb_tso(netfr
+ 
+ 	tso_check_safe(skb);
+ 
+-	if (skb->ip_summed != CHECKSUM_HW)
++	if (skb->ip_summed != CHECKSUM_PARTIAL)
+ 		EPRINTK("Trying to TSO send a packet without HW checksum\n");
+ 
+ 	tso_start(&state, skb);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:17:16.000000000 +0100
+@@ -463,7 +463,7 @@ netfront_accel_enqueue_skb_multi(netfron
+ 
+ 	frag_i = -1;
+ 
+-	if (skb->ip_summed == CHECKSUM_HW) {
++	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+ 		*(u16*)(skb->h.raw + skb->csum) = 0;
+ 	}
+@@ -582,7 +582,7 @@ netfront_accel_enqueue_skb_single(netfro
+ 	
+ 	kva = buf->pkt_kva;
+ 
+-	if (skb->ip_summed == CHECKSUM_HW) {
++	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+ 		*(u16*)(skb->h.raw + skb->csum) = 0;
+ 	}
+--- head-2010-01-18.orig/drivers/xen/tpmback/common.h	2007-06-12 13:13:45.000000000 +0200
++++ head-2010-01-18/drivers/xen/tpmback/common.h	2009-11-06 10:45:48.000000000 +0100
+@@ -61,7 +61,7 @@ void tpmif_deschedule_work(tpmif_t * tpm
+ void tpmif_xenbus_init(void);
+ void tpmif_xenbus_exit(void);
+ int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+-irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t tpmif_be_int(int irq, void *dev_id);
+ 
+ long int tpmback_get_instance(struct backend_info *bi);
+ 
+--- head-2010-01-18.orig/drivers/xen/tpmback/tpmback.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/tpmback.c	2010-01-04 12:23:26.000000000 +0100
+@@ -507,7 +507,7 @@ static ssize_t vtpm_op_read(struct file 
+ 		list_del(&pak->next);
+ 		write_unlock_irqrestore(&dataex.pak_lock, flags);
+ 
+-		DPRINTK("size given by app: %d, available: %d\n", size, left);
++		DPRINTK("size given by app: %zu, available: %u\n", size, left);
+ 
+ 		ret_size = min_t(size_t, size, left);
+ 
+@@ -904,7 +904,7 @@ static void tpm_tx_action(unsigned long 
+ 	}
+ }
+ 
+-irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t tpmif_be_int(int irq, void *dev_id)
+ {
+ 	tpmif_t *tpmif = (tpmif_t *) dev_id;
+ 
+--- head-2010-01-18.orig/drivers/xen/usbback/usbback.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/usbback.c	2009-11-06 10:45:48.000000000 +0100
+@@ -288,7 +288,7 @@ static void usbbk_notify_work(usbif_t *u
+ 	wake_up(&usbif->wq);
+ }
+ 
+-irqreturn_t usbbk_be_int(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t usbbk_be_int(int irq, void *dev_id)
+ {
+ 	usbbk_notify_work(dev_id);
+ 	return IRQ_HANDLED;
+@@ -318,7 +318,7 @@ static void usbbk_do_response(pending_re
+ 		notify_remote_via_irq(usbif->irq);
+ }
+ 
+-static void usbbk_urb_complete(struct urb *urb, struct pt_regs *regs)
++static void usbbk_urb_complete(struct urb *urb)
+ {
+ 	pending_req_t *pending_req = (pending_req_t *)urb->context;
+ 
+--- head-2010-01-18.orig/drivers/xen/usbback/usbback.h	2009-11-06 10:23:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/usbback.h	2009-11-06 10:45:48.000000000 +0100
+@@ -158,7 +158,7 @@ int portid_add(const char *busid,
+ int portid_remove(const domid_t domid,
+ 					const unsigned int handle,
+ 					const int portnum);
+-irqreturn_t usbbk_be_int(int irq, void *dev_id, struct pt_regs *regs);
++irqreturn_t usbbk_be_int(int irq, void *dev_id);
+ int usbbk_schedule(void *arg);
+ struct usbstub *find_attached_device(usbif_t *usbif, int port);
+ void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub);
+--- head-2010-01-18.orig/drivers/xen/usbback/usbstub.c	2009-11-06 10:23:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/usbstub.c	2009-11-06 10:45:48.000000000 +0100
+@@ -284,7 +284,7 @@ static ssize_t usbstub_show_portids(stru
+ DRIVER_ATTR(port_ids, S_IRUSR, usbstub_show_portids, NULL);
+ 
+ /* table of devices that matches any usbdevice */
+-static struct usb_device_id usbstub_table[] = {
++static const struct usb_device_id usbstub_table[] = {
+ 		{ .driver_info = 1 }, /* wildcard, see usb_match_id() */
+ 		{ } /* Terminating entry */
+ };
+@@ -308,7 +308,7 @@ int __init usbstub_init(void)
+ 		goto out;
+ 	}
+ 
+-	err = driver_create_file(&usbback_usb_driver.driver,
++	err = driver_create_file(&usbback_usb_driver.drvwrap.driver,
+ 				&driver_attr_port_ids);
+ 	if (err)
+ 		usb_deregister(&usbback_usb_driver);
+@@ -319,7 +319,7 @@ out:
+ 
+ void usbstub_exit(void)
+ {
+-	driver_remove_file(&usbback_usb_driver.driver,
++	driver_remove_file(&usbback_usb_driver.drvwrap.driver,
+ 				&driver_attr_port_ids);
+ 	usb_deregister(&usbback_usb_driver);
+ }
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront.h	2009-10-15 11:45:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/usbfront/usbfront.h	2009-11-06 10:45:48.000000000 +0100
+@@ -195,7 +195,7 @@ timer_action(struct usbfront_info *info,
+ extern struct kmem_cache *xenhcd_urbp_cachep;
+ extern struct hc_driver xen_usb20_hc_driver;
+ extern struct hc_driver xen_usb11_hc_driver;
+-irqreturn_t xenhcd_int(int irq, void *dev_id, struct pt_regs *ptregs);
++irqreturn_t xenhcd_int(int irq, void *dev_id);
+ void xenhcd_rhport_state_change(struct usbfront_info *info,
+ 				int port, enum usb_device_speed speed);
+ int xenhcd_schedule(void *arg);
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-dbg.c	2009-10-15 11:45:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-dbg.c	2009-11-06 10:45:48.000000000 +0100
+@@ -90,7 +90,9 @@ static CLASS_DEVICE_ATTR(statistics, S_I
+ static inline void create_debug_file(struct usbfront_info *info)
+ {
+ 	struct class_device *cldev = info_to_hcd(info)->self.class_dev;
+-	class_device_create_file(cldev, &class_device_attr_statistics);
++	if (class_device_create_file(cldev, &class_device_attr_statistics))
++		printk(KERN_WARNING "statistics file not created for %s\n",
++		       info_to_hcd(info)->self.bus_name);
+ }
+ 
+ static inline void remove_debug_file(struct usbfront_info *info)
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-q.c	2009-10-15 11:45:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-q.c	2009-11-06 10:45:48.000000000 +0100
+@@ -236,7 +236,7 @@ __acquires(info->lock)
+ 		COUNT(info->stats.complete);
+ 	}
+ 	spin_unlock(&info->lock);
+-	usb_hcd_giveback_urb(info_to_hcd(info), urb, NULL);
++	usb_hcd_giveback_urb(info_to_hcd(info), urb);
+ 	spin_lock(&info->lock);
+ }
+ 
+@@ -534,7 +534,7 @@ static void xenhcd_notify_work(struct us
+ 	wake_up(&info->wq);
+ }
+ 
+-irqreturn_t xenhcd_int(int irq, void *dev_id, struct pt_regs *ptregs)
++irqreturn_t xenhcd_int(int irq, void *dev_id)
+ {
+ 	xenhcd_notify_work((struct usbfront_info *) dev_id);
+ 	return IRQ_HANDLED;
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_comms.c	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:45:48.000000000 +0100
+@@ -54,7 +54,7 @@ static DECLARE_WORK(probe_work, xenbus_p
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+ 
+-static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
++static irqreturn_t wake_waiting(int irq, void *unused)
+ {
+ 	int old, new;
+ 
+--- head-2010-01-18.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:38:29.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:57:42.000000000 +0100
+@@ -194,8 +194,7 @@ done:
+ 		oprofile_add_domain_switch(COORDINATOR_DOMAIN);
+ }
+ 
+-static irqreturn_t 
+-xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
++static irqreturn_t xenoprof_ovf_interrupt(int irq, void *dev_id)
+ {
+ 	struct xenoprof_buf * buf;
+ 	static unsigned long flag;
+--- head-2010-01-18.orig/include/asm-generic/pgtable.h	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/include/asm-generic/pgtable.h	2009-11-06 10:45:48.000000000 +0100
+@@ -100,7 +100,7 @@ static inline void ptep_set_wrprotect(st
+ #endif
+ 
+ #ifndef arch_change_pte_range
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot) 0
++#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) 0
+ #endif
+ 
+ #ifndef __HAVE_ARCH_PTE_SAME
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_32.h	2008-01-28 12:24:19.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -32,52 +32,110 @@ static inline struct desc_struct *get_cp
+ 	return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
+ }
+ 
++/*
++ * This is the ldt that every process will get unless we need
++ * something other than this.
++ */
++extern struct desc_struct default_ldt[];
++extern struct desc_struct idt_table[];
++extern void set_intr_gate(unsigned int irq, void * addr);
++
++static inline void pack_descriptor(__u32 *a, __u32 *b,
++	unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
++{
++	*a = ((base & 0xffff) << 16) | (limit & 0xffff);
++	*b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
++		(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
++}
++
++static inline void pack_gate(__u32 *a, __u32 *b,
++	unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
++{
++	*a = (seg << 16) | (base & 0xffff);
++	*b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
++}
++
++#define DESCTYPE_LDT 	0x82	/* present, system, DPL-0, LDT */
++#define DESCTYPE_TSS 	0x89	/* present, system, DPL-0, 32-bit TSS */
++#define DESCTYPE_TASK	0x85	/* present, system, DPL-0, task gate */
++#define DESCTYPE_INT	0x8e	/* present, system, DPL-0, interrupt gate */
++#define DESCTYPE_TRAP	0x8f	/* present, system, DPL-0, trap gate */
++#define DESCTYPE_DPL3	0x60	/* DPL-3 */
++#define DESCTYPE_S	0x10	/* !system */
++
+ #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
+ #define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
+ 
+ #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+ #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+-#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
+-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
++#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
++#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+ 
+ #define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
+ #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
+-#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
+-#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
++#define store_tr(tr) __asm__ ("str %0":"=m" (tr))
++#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+ 
+-/*
+- * This is the ldt that every process will get unless we need
+- * something other than this.
+- */
+-extern struct desc_struct default_ldt[];
+-extern void set_intr_gate(unsigned int irq, void * addr);
++#if TLS_SIZE != 24
++# error update this code.
++#endif
++
++static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
++{
++#define C(i) if (HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), \
++					      *(u64 *)&t->tls_array[i]) \
++		BUG()
++	C(0); C(1); C(2);
++#undef C
++}
+ 
+-#define _set_tssldt_desc(n,addr,limit,type) \
+-__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
+-	"movw %w1,2(%2)\n\t" \
+-	"rorl $16,%1\n\t" \
+-	"movb %b1,4(%2)\n\t" \
+-	"movb %4,5(%2)\n\t" \
+-	"movb $0,6(%2)\n\t" \
+-	"movb %h1,7(%2)\n\t" \
+-	"rorl $16,%1" \
+-	: "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
++#ifndef CONFIG_XEN
++static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
++{
++	__u32 *lp = (__u32 *)((char *)dt + entry*8);
++	*lp = entry_a;
++	*(lp+1) = entry_b;
++}
+ 
+-#ifndef CONFIG_X86_NO_TSS
+-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
++#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++#else
++extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
++extern int write_gdt_entry(void *gdt, int entry, __u32 entry_a, __u32 entry_b);
++#endif
++#ifndef CONFIG_X86_NO_IDT
++#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++
++static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
+ {
+-	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
+-		offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
++	__u32 a, b;
++	pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
++	write_idt_entry(idt_table, gate, a, b);
+ }
++#endif
+ 
+-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
++#ifndef CONFIG_X86_NO_TSS
++static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
++{
++	__u32 a, b;
++	pack_descriptor(&a, &b, (unsigned long)addr,
++			offsetof(struct tss_struct, __cacheline_filler) - 1,
++			DESCTYPE_TSS, 0);
++	write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
++}
+ #endif
+ 
+-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
++static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entries)
+ {
+-	_set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
++	__u32 a, b;
++	pack_descriptor(&a, &b, (unsigned long)addr,
++			entries * sizeof(struct desc_struct) - 1,
++			DESCTYPE_LDT, 0);
++	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+ }
+ 
++#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
++
+ #define LDT_entry_a(info) \
+ 	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+ 
+@@ -103,21 +161,6 @@ static inline void set_ldt_desc(unsigned
+ 	(info)->seg_not_present	== 1	&& \
+ 	(info)->useable		== 0	)
+ 
+-extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
+-
+-#if TLS_SIZE != 24
+-# error update this code.
+-#endif
+-
+-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
+-{
+-#define C(i) if (HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]), \
+-					       *(u64 *)&t->tls_array[i])) \
+-		BUG();
+-	C(0); C(1); C(2);
+-#undef C
+-}
+-
+ static inline void clear_LDT(void)
+ {
+ 	int cpu = get_cpu();
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -55,7 +55,7 @@ enum fixed_addresses {
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+-#ifdef CONFIG_X86_IO_APIC
++#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_XEN)
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+ #endif
+@@ -95,10 +95,9 @@ enum fixed_addresses {
+ 	__end_of_fixed_addresses
+ };
+ 
+-extern void set_fixaddr_top(unsigned long top);
+-
+ extern void __set_fixmap(enum fixed_addresses idx,
+ 					maddr_t phys, pgprot_t flags);
++extern void reserve_top_address(unsigned long reserve);
+ 
+ #define set_fixmap(idx, phys) \
+ 		__set_fixmap(idx, phys, PAGE_KERNEL)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypercall_32.h	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -128,6 +128,23 @@
+ 	__res;							\
+ })
+ 
++#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	register typeof((a1)+0) __arg1 asm("ebx") = (a1);	\
++	register typeof((a2)+0) __arg2 asm("ecx") = (a2);	\
++	register typeof((a3)+0) __arg3 asm("edx") = (a3);	\
++	register typeof((a4)+0) __arg4 asm("esi") = (a4);	\
++	register typeof((a5)+0) __arg5 asm("edi") = (a5);	\
++	asm volatile (						\
++		"call *%6"					\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
++		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
++		: "0" (hypercall_page + (op) * 32)		\
++		: "memory" );					\
++	__res;							\
++})
++
+ static inline int __must_check
+ HYPERVISOR_set_trap_table(
+ 	const trap_info_t *table)
+@@ -140,6 +157,8 @@ HYPERVISOR_mmu_update(
+ 	mmu_update_t *req, unsigned int count, unsigned int *success_count,
+ 	domid_t domid)
+ {
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmu_update(req, count, success_count, domid);
+ 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+ }
+ 
+@@ -148,6 +167,8 @@ HYPERVISOR_mmuext_op(
+ 	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
+ 	domid_t domid)
+ {
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmuext_op(op, count, success_count, domid);
+ 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+ }
+ 
+@@ -238,6 +259,8 @@ static inline int __must_check
+ HYPERVISOR_memory_op(
+ 	unsigned int cmd, void *arg)
+ {
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
+ 	return _hypercall2(int, memory_op, cmd, arg);
+ }
+ 
+@@ -253,6 +276,9 @@ HYPERVISOR_update_va_mapping(
+ 	unsigned long va, pte_t new_val, unsigned long flags)
+ {
+ 	unsigned long pte_hi = 0;
++
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_update_va_mapping(va, new_val, flags);
+ #ifdef CONFIG_X86_PAE
+ 	pte_hi = new_val.pte_high;
+ #endif
+@@ -316,6 +342,8 @@ static inline int __must_check
+ HYPERVISOR_grant_table_op(
+ 	unsigned int cmd, void *uop, unsigned int count)
+ {
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
+ 	return _hypercall3(int, grant_table_op, cmd, uop, count);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypercall_64.h	2009-06-23 09:28:21.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -135,6 +135,23 @@
+ 	__res;							\
+ })
+ 
++#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	register typeof((a1)+0) __arg1 asm("rdi") = (a1);	\
++	register typeof((a2)+0) __arg2 asm("rsi") = (a2);	\
++	register typeof((a3)+0) __arg3 asm("rdx") = (a3);	\
++	register typeof((a4)+0) __arg4 asm("r10") = (a4);	\
++	register typeof((a5)+0) __arg5 asm("r8") = (a5);	\
++	asm volatile (						\
++		"call *%6"					\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
++		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
++		: "0" (hypercall_page + (op) * 32)		\
++		: "memory" );					\
++	__res;							\
++})
++
+ static inline int __must_check
+ HYPERVISOR_set_trap_table(
+ 	const trap_info_t *table)
+@@ -147,6 +164,8 @@ HYPERVISOR_mmu_update(
+ 	mmu_update_t *req, unsigned int count, unsigned int *success_count,
+ 	domid_t domid)
+ {
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmu_update(req, count, success_count, domid);
+ 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+ }
+ 
+@@ -155,6 +174,8 @@ HYPERVISOR_mmuext_op(
+ 	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
+ 	domid_t domid)
+ {
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmuext_op(op, count, success_count, domid);
+ 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+ }
+ 
+@@ -248,6 +269,8 @@ static inline int __must_check
+ HYPERVISOR_memory_op(
+ 	unsigned int cmd, void *arg)
+ {
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
+ 	return _hypercall2(int, memory_op, cmd, arg);
+ }
+ 
+@@ -262,6 +285,8 @@ static inline int __must_check
+ HYPERVISOR_update_va_mapping(
+ 	unsigned long va, pte_t new_val, unsigned long flags)
+ {
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_update_va_mapping(va, new_val, flags);
+ 	return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
+ }
+ 
+@@ -321,6 +346,8 @@ static inline int __must_check
+ HYPERVISOR_grant_table_op(
+ 	unsigned int cmd, void *uop, unsigned int count)
+ {
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
+ 	return _hypercall3(int, grant_table_op, cmd, uop, count);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-07-13 14:25:35.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:45:48.000000000 +0100
+@@ -44,6 +44,7 @@
+ #include <xen/interface/sched.h>
+ #include <xen/interface/nmi.h>
+ #include <xen/interface/tmem.h>
++#include <asm/percpu.h>
+ #include <asm/ptrace.h>
+ #include <asm/page.h>
+ #if defined(__i386__)
+@@ -139,7 +140,44 @@ void scrub_pages(void *, unsigned int);
+ #define scrub_pages(_p,_n) ((void)0)
+ #endif
+ 
+-#include <xen/hypercall.h>
++#if defined(CONFIG_XEN) && !defined(MODULE)
++
++DECLARE_PER_CPU(bool, xen_lazy_mmu);
++
++int xen_multicall_flush(bool);
++
++int __must_check xen_multi_update_va_mapping(unsigned long va, pte_t,
++					     unsigned long flags);
++int __must_check xen_multi_mmu_update(mmu_update_t *, unsigned int count,
++				      unsigned int *success_count, domid_t);
++int __must_check xen_multi_mmuext_op(struct mmuext_op *, unsigned int count,
++				     unsigned int *success_count, domid_t);
++
++#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
++static inline void arch_enter_lazy_mmu_mode(void)
++{
++	__get_cpu_var(xen_lazy_mmu) = true;
++}
++
++static inline void arch_leave_lazy_mmu_mode(void)
++{
++	__get_cpu_var(xen_lazy_mmu) = false;
++	xen_multicall_flush(false);
++}
++
++#ifndef arch_use_lazy_mmu_mode
++#define arch_use_lazy_mmu_mode() unlikely(__get_cpu_var(xen_lazy_mmu))
++#endif
++
++#else /* !CONFIG_XEN || MODULE */
++
++static inline void xen_multicall_flush(bool ignore) {}
++#define arch_use_lazy_mmu_mode() false
++#define xen_multi_update_va_mapping(...) ({ BUG(); -ENOSYS; })
++#define xen_multi_mmu_update(...) ({ BUG(); -ENOSYS; })
++#define xen_multi_mmuext_op(...) ({ BUG(); -ENOSYS; })
++
++#endif /* CONFIG_XEN && !MODULE */
+ 
+ #if defined(CONFIG_X86_64)
+ #define MULTI_UVMFLAGS_INDEX 2
+@@ -151,11 +189,15 @@ void scrub_pages(void *, unsigned int);
+ 
+ #ifdef CONFIG_XEN
+ #define is_running_on_xen() 1
++extern char hypercall_page[PAGE_SIZE];
+ #else
+ extern char *hypercall_stubs;
++#define hypercall_page hypercall_stubs
+ #define is_running_on_xen() (!!hypercall_stubs)
+ #endif
+ 
++#include <xen/hypercall.h>
++
+ static inline int
+ HYPERVISOR_yield(
+ 	void)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:45:48.000000000 +0100
+@@ -53,7 +53,6 @@ static inline int pte_exec_kernel(pte_t 
+  * not possible, use pte_get_and_clear to obtain the old pte
+  * value and then use set_pte to update it.  -ben
+  */
+-#define __HAVE_ARCH_SET_PTE_ATOMIC
+ 
+ static inline void set_pte(pte_t *ptep, pte_t pte)
+ {
+@@ -70,14 +69,6 @@ static inline void set_pte(pte_t *ptep, 
+ 		set_pte((ptep), (pteval));				\
+ } while (0)
+ 
+-#define set_pte_at_sync(_mm,addr,ptep,pteval) do {			\
+-	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
+-	    HYPERVISOR_update_va_mapping((addr), (pteval), UVMF_INVLPG)) { \
+-		set_pte((ptep), (pteval));				\
+-		xen_invlpg((addr));					\
+-	}								\
+-} while (0)
+-
+ #define set_pmd(pmdptr,pmdval)				\
+ 		xen_l2_entry_update((pmdptr), (pmdval))
+ #define set_pud(pudptr,pudval) \
+@@ -94,7 +85,7 @@ static inline void pud_clear (pud_t * pu
+ #define pud_page(pud) \
+ ((struct page *) __va(pud_val(pud) & PAGE_MASK))
+ 
+-#define pud_page_kernel(pud) \
++#define pud_page_vaddr(pud) \
+ ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
+ 
+ 
+@@ -124,6 +115,7 @@ static inline void pte_clear(struct mm_s
+ 
+ #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+ 
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ 	pte_t pte = *ptep;
+@@ -142,6 +134,7 @@ static inline pte_t ptep_get_and_clear(s
+ 	return pte;
+ }
+ 
++#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+ #define ptep_clear_flush(vma, addr, ptep)			\
+ ({								\
+ 	pte_t *__ptep = (ptep);					\
+@@ -159,6 +152,7 @@ static inline pte_t ptep_get_and_clear(s
+ 	__res;							\
+ })
+ 
++#define __HAVE_ARCH_PTE_SAME
+ static inline int pte_same(pte_t a, pte_t b)
+ {
+ 	return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -260,31 +260,89 @@ static inline pte_t pte_mkhuge(pte_t pte
+ # include <asm/pgtable-2level.h>
+ #endif
+ 
+-#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
++/*
++ * Rules for using pte_update - it must be called after any PTE update which
++ * has not been done using the set_pte / clear_pte interfaces.  It is used by
++ * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
++ * updates should either be sets, clears, or set_pte_atomic for P->P
++ * transitions, which means this hook should only be called for user PTEs.
++ * This hook implies a P->P protection or access change has taken place, which
++ * requires a subsequent TLB flush.  The notification can optionally be delayed
++ * until the TLB flush event by using the pte_update_defer form of the
++ * interface, but care must be taken to assure that the flush happens while
++ * still holding the same page table lock so that the shadow and primary pages
++ * do not become out of sync on SMP.
++ */
++#define pte_update(mm, addr, ptep)		do { } while (0)
++#define pte_update_defer(mm, addr, ptep)	do { } while (0)
++
++
++/*
++ * We only update the dirty/accessed state if we set
++ * the dirty bit by hand in the kernel, since the hardware
++ * will do the accessed bit for us, and we don't want to
++ * race with other CPU's that might be updating the dirty
++ * bit at the same time.
++ */
++#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
++do {									\
++	if (dirty)							\
++		ptep_establish(vma, address, ptep, entry);		\
++} while (0)
++
++/*
++ * We don't actually have these, but we want to advertise them so that
++ * we can encompass the flush here.
++ */
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++
++/*
++ * Rules for using ptep_establish: the pte MUST be a user pte, and
++ * must be a present->present transition.
++ */
++#define __HAVE_ARCH_PTEP_ESTABLISH
++#define ptep_establish(vma, address, ptep, pteval)			\
++do {									\
++	if ( likely((vma)->vm_mm == current->mm) ) {			\
++		BUG_ON(HYPERVISOR_update_va_mapping(address,		\
++			pteval,						\
++			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits|	\
++				UVMF_INVLPG|UVMF_MULTI));		\
++	} else {							\
++		xen_l1_entry_update(ptep, pteval);			\
++		flush_tlb_page(vma, address);				\
++	}								\
++} while (0)
++
++#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
++#define ptep_clear_flush_dirty(vma, address, ptep)			\
+ ({									\
+ 	pte_t __pte = *(ptep);						\
+-	int __ret = pte_dirty(__pte);					\
+-	if (__ret) {							\
+-		__pte = pte_mkclean(__pte);				\
+-		if ((vma)->vm_mm != current->mm ||			\
+-		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
+-			(ptep)->pte_low = __pte.pte_low;		\
+-	}								\
+-	__ret;								\
++	int __dirty = pte_dirty(__pte);					\
++	__pte = pte_mkclean(__pte);					\
++	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
++		ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
++	else if (__dirty)						\
++		(ptep)->pte_low = __pte.pte_low;			\
++	__dirty;							\
+ })
+ 
+-#define ptep_test_and_clear_young(vma, addr, ptep)			\
++#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define ptep_clear_flush_young(vma, address, ptep)			\
+ ({									\
+ 	pte_t __pte = *(ptep);						\
+-	int __ret = pte_young(__pte);					\
+-	if (__ret)							\
+-		__pte = pte_mkold(__pte);				\
+-		if ((vma)->vm_mm != current->mm ||			\
+-		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
+-			(ptep)->pte_low = __pte.pte_low;		\
+-	__ret;								\
++	int __young = pte_young(__pte);					\
++	__pte = pte_mkold(__pte);					\
++	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
++		ptep_set_access_flags(vma, address, ptep, __pte, __young); \
++	else if (__young)						\
++		(ptep)->pte_low = __pte.pte_low;			\
++	__young;							\
+ })
+ 
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+ #define ptep_get_and_clear_full(mm, addr, ptep, full)			\
+ 	((full) ? ({							\
+ 		pte_t __res = *(ptep);					\
+@@ -296,6 +354,7 @@ static inline pte_t pte_mkhuge(pte_t pte
+ 	 }) :								\
+ 	 ptep_get_and_clear(mm, addr, ptep))
+ 
++#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ 	pte_t pte = *ptep;
+@@ -391,11 +450,11 @@ static inline pte_t pte_modify(pte_t pte
+ #define pte_index(address) \
+ 		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) \
+-	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
++	((pte_t *) pmd_page_vaddr(*(dir)) +  pte_index(address))
+ 
+ #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+ 
+-#define pmd_page_kernel(pmd) \
++#define pmd_page_vaddr(pmd) \
+ 		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+ 
+ /*
+@@ -418,8 +477,6 @@ extern pte_t *lookup_address(unsigned lo
+  static inline int set_kernel_exec(unsigned long vaddr, int enable) { return 0;}
+ #endif
+ 
+-extern void noexec_setup(const char *str);
+-
+ #if defined(CONFIG_HIGHPTE)
+ #define pte_offset_map(dir, address) \
+ 	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \
+@@ -437,37 +494,17 @@ extern void noexec_setup(const char *str
+ #define pte_unmap_nested(pte) do { } while (0)
+ #endif
+ 
+-#define __HAVE_ARCH_PTEP_ESTABLISH
+-#define ptep_establish(vma, address, ptep, pteval)			\
+-	do {								\
+-		if ( likely((vma)->vm_mm == current->mm) ) {		\
+-			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
+-				pteval,					\
+-				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+-					UVMF_INVLPG|UVMF_MULTI));	\
+-		} else {						\
+-			xen_l1_entry_update(ptep, pteval);		\
+-			flush_tlb_page(vma, address);			\
+-		}							\
+-	} while (0)
++/* Clear a kernel PTE and flush it from the TLB */
++#define kpte_clear_flush(ptep, vaddr) do { \
++	if (HYPERVISOR_update_va_mapping(vaddr, __pte(0), UVMF_INVLPG)) \
++		BUG(); \
++} while (0)
+ 
+ /*
+  * The i386 doesn't have any external MMU info: the kernel page
+  * tables contain all the necessary information.
+- *
+- * Also, we only update the dirty/accessed state if we set
+- * the dirty bit by hand in the kernel, since the hardware
+- * will do the accessed bit for us, and we don't want to
+- * race with other CPU's that might be updating the dirty
+- * bit at the same time.
+  */
+ #define update_mmu_cache(vma,address,pte) do { } while (0)
+-#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-	do {								\
+-		if (dirty)						\
+-			ptep_establish(vma, address, ptep, entry);	\
+-	} while (0)
+ 
+ #include <xen/features.h>
+ void make_lowmem_page_readonly(void *va, unsigned int feature);
+@@ -526,10 +563,11 @@ int touch_pte_range(struct mm_struct *mm
+                     unsigned long size);
+ 
+ int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-		unsigned long addr, unsigned long end, pgprot_t newprot);
++		unsigned long addr, unsigned long end, pgprot_t newprot,
++		int dirty_accountable);
+ 
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot)	\
+-		xen_change_pte_range(mm, pmd, addr, end, newprot)
++#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
++	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+ 
+ #define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
+@@ -538,13 +576,6 @@ direct_remap_pfn_range(vma,from,pfn,size
+ #define GET_IOSPACE(pfn)		0
+ #define GET_PFN(pfn)			(pfn)
+ 
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+-#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+-#define __HAVE_ARCH_PTE_SAME
+ #include <asm-generic/pgtable.h>
+ 
+ #endif /* _I386_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -146,6 +146,18 @@ static inline void detect_ht(struct cpui
+ #define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
+ #define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
+ 
++static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
++			   unsigned int *ecx, unsigned int *edx)
++{
++	/* ecx is often an input as well as an output. */
++	__asm__(XEN_CPUID
++		: "=a" (*eax),
++		  "=b" (*ebx),
++		  "=c" (*ecx),
++		  "=d" (*edx)
++		: "0" (*eax), "2" (*ecx));
++}
++
+ /*
+  * Generic CPUID function
+  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+@@ -153,24 +165,18 @@ static inline void detect_ht(struct cpui
+  */
+ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
+ {
+-	__asm__(XEN_CPUID
+-		: "=a" (*eax),
+-		  "=b" (*ebx),
+-		  "=c" (*ecx),
+-		  "=d" (*edx)
+-		: "0" (op), "c"(0));
++	*eax = op;
++	*ecx = 0;
++	__cpuid(eax, ebx, ecx, edx);
+ }
+ 
+ /* Some CPUID calls want 'count' to be placed in ecx */
+ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+-	       	int *edx)
++			       int *edx)
+ {
+-	__asm__(XEN_CPUID
+-		: "=a" (*eax),
+-		  "=b" (*ebx),
+-		  "=c" (*ecx),
+-		  "=d" (*edx)
+-		: "0" (op), "c" (count));
++	*eax = op;
++	*ecx = count;
++	__cpuid(eax, ebx, ecx, edx);
+ }
+ 
+ /*
+@@ -178,42 +184,30 @@ static inline void cpuid_count(int op, i
+  */
+ static inline unsigned int cpuid_eax(unsigned int op)
+ {
+-	unsigned int eax;
++	unsigned int eax, ebx, ecx, edx;
+ 
+-	__asm__(XEN_CPUID
+-		: "=a" (eax)
+-		: "0" (op)
+-		: "bx", "cx", "dx");
++	cpuid(op, &eax, &ebx, &ecx, &edx);
+ 	return eax;
+ }
+ static inline unsigned int cpuid_ebx(unsigned int op)
+ {
+-	unsigned int eax, ebx;
++	unsigned int eax, ebx, ecx, edx;
+ 
+-	__asm__(XEN_CPUID
+-		: "=a" (eax), "=b" (ebx)
+-		: "0" (op)
+-		: "cx", "dx" );
++	cpuid(op, &eax, &ebx, &ecx, &edx);
+ 	return ebx;
+ }
+ static inline unsigned int cpuid_ecx(unsigned int op)
+ {
+-	unsigned int eax, ecx;
++	unsigned int eax, ebx, ecx, edx;
+ 
+-	__asm__(XEN_CPUID
+-		: "=a" (eax), "=c" (ecx)
+-		: "0" (op)
+-		: "bx", "dx" );
++	cpuid(op, &eax, &ebx, &ecx, &edx);
+ 	return ecx;
+ }
+ static inline unsigned int cpuid_edx(unsigned int op)
+ {
+-	unsigned int eax, edx;
++	unsigned int eax, ebx, ecx, edx;
+ 
+-	__asm__(XEN_CPUID
+-		: "=a" (eax), "=d" (edx)
+-		: "0" (op)
+-		: "bx", "cx");
++	cpuid(op, &eax, &ebx, &ecx, &edx);
+ 	return edx;
+ }
+ 
+@@ -315,6 +309,8 @@ static inline void __mwait(unsigned long
+ 		: :"a" (eax), "c" (ecx));
+ }
+ 
++extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
++
+ /* from system description table in BIOS.  Mostly for MCA use, but
+ others may find it useful. */
+ extern unsigned int machine_id;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -79,25 +79,36 @@ static inline int hard_smp_processor_id(
+ 	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
+ }
+ #endif
+-
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+-}
+-
+ #endif
+ 
++#define safe_smp_processor_id() smp_processor_id()
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void prefill_possible_map(void);
++extern unsigned int num_processors;
++
+ #endif /* !__ASSEMBLY__ */
+ 
+ #else /* CONFIG_SMP */
+ 
++#define safe_smp_processor_id()		0
+ #define cpu_physical_id(cpu)		boot_cpu_physical_apicid
+ 
+ #define NO_PROC_ID		0xFF		/* No processor magic marker */
+ 
+ #endif
++
++#ifndef __ASSEMBLY__
++
++extern u8 apicid_2_node[];
++
++#ifdef CONFIG_X86_LOCAL_APIC
++static __inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
++}
++#endif
++#endif
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -267,6 +267,9 @@ static inline unsigned long __xchg(unsig
+ #define cmpxchg(ptr,o,n)\
+ 	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+ 					(unsigned long)(n),sizeof(*(ptr))))
++#define sync_cmpxchg(ptr,o,n)\
++	((__typeof__(*(ptr)))__sync_cmpxchg((ptr),(unsigned long)(o),\
++					(unsigned long)(n),sizeof(*(ptr))))
+ #endif
+ 
+ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+@@ -296,6 +299,39 @@ static inline unsigned long __cmpxchg(vo
+ 	return old;
+ }
+ 
++/*
++ * Always use locked operations when touching memory shared with a
++ * hypervisor, since the system may be SMP even if the guest kernel
++ * isn't.
++ */
++static inline unsigned long __sync_cmpxchg(volatile void *ptr,
++					    unsigned long old,
++					    unsigned long new, int size)
++{
++	unsigned long prev;
++	switch (size) {
++	case 1:
++		__asm__ __volatile__("lock; cmpxchgb %b1,%2"
++				     : "=a"(prev)
++				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 2:
++		__asm__ __volatile__("lock; cmpxchgw %w1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	case 4:
++		__asm__ __volatile__("lock; cmpxchgl %1,%2"
++				     : "=a"(prev)
++				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
++				     : "memory");
++		return prev;
++	}
++	return old;
++}
++
+ #ifndef CONFIG_X86_CMPXCHG
+ /*
+  * Building a kernel capable running on 80386. It may be necessary to
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_32.h	2007-11-26 16:59:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:45:48.000000000 +0100
+@@ -8,8 +8,6 @@
+ #define __flush_tlb_global() xen_tlb_flush()
+ #define __flush_tlb_all() xen_tlb_flush()
+ 
+-extern unsigned long pgkern_mask;
+-
+ #define cpu_has_invlpg	(boot_cpu_data.x86 > 3)
+ 
+ #define __flush_tlb_single(addr) xen_invlpg(addr)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -41,7 +41,7 @@ enum fixed_addresses {
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+-#ifdef CONFIG_X86_IO_APIC
++#ifndef CONFIG_XEN
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -44,12 +44,9 @@ extern unsigned long __supported_pte_mas
+ 
+ #define swapper_pg_dir init_level4_pgt
+ 
+-extern int nonx_setup(char *str);
+ extern void paging_init(void);
+ extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
+ 
+-extern unsigned long pgkern_mask;
+-
+ /*
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+@@ -119,9 +116,6 @@ static inline void pgd_clear (pgd_t * pg
+         set_pgd(__user_pgd(pgd), __pgd(0));
+ }
+ 
+-#define pud_page(pud) \
+-    ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
+-
+ #define pte_same(a, b)		((a).pte == (b).pte)
+ 
+ #define pte_pgprot(a)	(__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
+@@ -333,7 +327,7 @@ static inline pte_t ptep_get_and_clear_f
+ #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
+ static inline int pte_user(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
+ static inline int pte_read(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
+-static inline int pte_exec(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
++static inline int pte_exec(pte_t pte)		{ return !(__pte_val(pte) & _PAGE_NX); }
+ static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
+ static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
+@@ -346,29 +340,12 @@ static inline pte_t pte_mkclean(pte_t pt
+ static inline pte_t pte_mkold(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_wrprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_RW; return pte; }
+ static inline pte_t pte_mkread(pte_t pte)	{ __pte_val(pte) |= _PAGE_USER; return pte; }
+-static inline pte_t pte_mkexec(pte_t pte)	{ __pte_val(pte) |= _PAGE_USER; return pte; }
++static inline pte_t pte_mkexec(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_NX; return pte; }
+ static inline pte_t pte_mkdirty(pte_t pte)	{ __pte_val(pte) |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte)	{ __pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte)	{ __pte_val(pte) |= _PAGE_RW; return pte; }
+ static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
+-
+-#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __ret = pte_dirty(__pte);					\
+-	if (__ret)							\
+-		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkclean(__pte)); \
+-	__ret;								\
+-})
+-
+-#define ptep_test_and_clear_young(vma, addr, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __ret = pte_young(__pte);					\
+-	if (__ret)							\
+-		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkold(__pte)); \
+-	__ret;								\
+-})
++static inline pte_t pte_clrhuge(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_PSE; return pte; }
+ 
+ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+@@ -395,7 +372,8 @@ static inline int pmd_large(pmd_t pte) {
+ /*
+  * Level 4 access.
+  */
+-#define pgd_page(pgd) ((unsigned long) __va(pgd_val(pgd) & PTE_MASK))
++#define pgd_page_vaddr(pgd) ((unsigned long) __va(pgd_val(pgd) & PTE_MASK))
++#define pgd_page(pgd)		(pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT))
+ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+ #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+ #define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
+@@ -404,16 +382,18 @@ static inline int pmd_large(pmd_t pte) {
+ 
+ /* PUD - Level3 access */
+ /* to find an entry in a page-table-directory. */
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
++#define pud_page(pud)		(pfn_to_page(pud_val(pud) >> PAGE_SHIFT))
+ #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+-#define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address))
++#define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
+ #define pud_present(pud) (__pud_val(pud) & _PAGE_PRESENT)
+ 
+ /* PMD  - Level 2 access */
+-#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+ #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+ 
+ #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+-#define pmd_offset(dir, address) ((pmd_t *) pud_page(*(dir)) + \
++#define pmd_offset(dir, address) ((pmd_t *) pud_page_vaddr(*(dir)) + \
+                                   pmd_index(address))
+ #define pmd_none(x)	(!__pmd_val(x))
+ #if CONFIG_XEN_COMPAT <= 0x030002
+@@ -444,6 +424,7 @@ static inline pte_t mk_pte_phys(unsigned
+ { 
+ 	unsigned long pteval;
+ 	pteval = physpage | pgprot_val(pgprot);
++	pteval &= __supported_pte_mask;
+ 	return __pte(pteval);
+ }
+  
+@@ -465,7 +446,7 @@ static inline pte_t pte_modify(pte_t pte
+ 
+ #define pte_index(address) \
+ 		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+-#define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
++#define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+ 			pte_index(address))
+ 
+ /* x86-64 always has all page tables mapped. */
+@@ -506,6 +487,40 @@ static inline pte_t pte_modify(pte_t pte
+ 			ptep_establish(vma, address, ptep, entry);	\
+ 	} while (0)
+ 
++
++/*
++ * i386 says: We don't actually have these, but we want to advertise
++ * them so that we can encompass the flush here.
++ */
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++
++#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
++#define ptep_clear_flush_dirty(vma, address, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __dirty = pte_dirty(__pte);					\
++	__pte = pte_mkclean(__pte);					\
++	if ((vma)->vm_mm->context.pinned)				\
++		ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
++	else if (__dirty)						\
++		set_pte(ptep, __pte);					\
++	__dirty;							\
++})
++
++#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define ptep_clear_flush_young(vma, address, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __young = pte_young(__pte);					\
++	__pte = pte_mkold(__pte);					\
++	if ((vma)->vm_mm->context.pinned)				\
++		ptep_set_access_flags(vma, address, ptep, __pte, __young); \
++	else if (__young)						\
++		set_pte(ptep, __pte);					\
++	__young;							\
++})
++
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x)			(((x).val >> 1) & 0x3f)
+ #define __swp_offset(x)			((x).val >> 8)
+@@ -547,10 +562,11 @@ int touch_pte_range(struct mm_struct *mm
+                     unsigned long size);
+ 
+ int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-		unsigned long addr, unsigned long end, pgprot_t newprot);
++		unsigned long addr, unsigned long end, pgprot_t newprot,
++		int dirty_accountable);
+ 
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot)	\
+-		xen_change_pte_range(mm, pmd, addr, end, newprot)
++#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
++	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+ 
+ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+ 		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
+@@ -572,8 +588,6 @@ int xen_change_pte_range(struct mm_struc
+ #define	kc_offset_to_vaddr(o) \
+    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
+ 
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2008-03-06 08:54:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -484,6 +484,8 @@ static inline void __mwait(unsigned long
+ 		: :"a" (eax), "c" (ecx));
+ }
+ 
++extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
++
+ #define stack_current() \
+ ({								\
+ 	struct thread_info *ti;					\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -4,15 +4,12 @@
+ /*
+  * We need the APIC definitions automatically as part of 'smp.h'
+  */
+-#ifndef __ASSEMBLY__
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
+ #include <linux/bitops.h>
+ extern int disable_apic;
+-#endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+-#ifndef __ASSEMBLY__
+ #include <asm/fixmap.h>
+ #include <asm/mpspec.h>
+ #ifdef CONFIG_X86_IO_APIC
+@@ -21,10 +18,8 @@ extern int disable_apic;
+ #include <asm/apic.h>
+ #include <asm/thread_info.h>
+ #endif
+-#endif
+ 
+ #ifdef CONFIG_SMP
+-#ifndef ASSEMBLY
+ 
+ #include <asm/pda.h>
+ 
+@@ -41,14 +36,11 @@ extern cpumask_t cpu_initialized;
+  
+ extern void smp_alloc_memory(void);
+ extern volatile unsigned long smp_invalidate_needed;
+-extern int pic_mode;
+ extern void lock_ipi_call_lock(void);
+ extern void unlock_ipi_call_lock(void);
+ extern int smp_num_siblings;
+ extern void smp_send_reschedule(int cpu);
+ void smp_stop_cpu(void);
+-extern int smp_call_function_single(int cpuid, void (*func) (void *info),
+-				void *info, int retry, int wait);
+ 
+ extern cpumask_t cpu_sibling_map[NR_CPUS];
+ extern cpumask_t cpu_core_map[NR_CPUS];
+@@ -77,20 +69,16 @@ static inline int hard_smp_processor_id(
+ }
+ #endif
+ 
+-extern int safe_smp_processor_id(void);
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void prefill_possible_map(void);
+ extern unsigned num_processors;
+ extern unsigned disabled_cpus;
+ 
+-#endif /* !ASSEMBLY */
+-
+ #define NO_PROC_ID		0xFF		/* No processor magic marker */
+ 
+ #endif
+ 
+-#ifndef ASSEMBLY
+ /*
+  * Some lowlevel functions might want to know about
+  * the real APIC ID <-> CPU # mapping.
+@@ -114,11 +102,8 @@ static inline int cpu_present_to_apicid(
+ }
+ #endif
+ 
+-#endif /* !ASSEMBLY */
+-
+ #ifndef CONFIG_SMP
+ #define stack_smp_processor_id() 0
+-#define safe_smp_processor_id() 0
+ #define cpu_logical_map(x) (x)
+ #else
+ #include <asm/thread_info.h>
+@@ -130,7 +115,6 @@ static inline int cpu_present_to_apicid(
+ })
+ #endif
+ 
+-#ifndef __ASSEMBLY__
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static __inline int logical_smp_processor_id(void)
+ {
+@@ -138,13 +122,18 @@ static __inline int logical_smp_processo
+ 	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+ }
+ #endif
+-#endif
+ 
+ #ifdef CONFIG_SMP
+ #define cpu_physical_id(cpu)		x86_cpu_to_apicid[cpu]
+ #else
+ #define cpu_physical_id(cpu)		boot_cpu_id
+-#endif
+-
++static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
++				void *info, int retry, int wait)
++{
++	/* Disable interrupts here? */
++	func(info);
++	return 0;
++}
++#endif /* !CONFIG_SMP */
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2007-11-26 16:59:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -24,6 +24,7 @@
+ #define __EXTRA_CLOBBER  \
+ 	,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
+ 
++/* Save restore flags to clear handle leaking NT */
+ #define switch_to(prev,next,last) \
+ 	asm volatile(SAVE_CONTEXT						    \
+ 		     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_64.h	2007-11-26 16:59:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:45:48.000000000 +0100
+@@ -12,9 +12,6 @@
+  */
+ #define __flush_tlb_global()	xen_tlb_flush()
+ 
+-
+-extern unsigned long pgkern_mask;
+-
+ #define __flush_tlb_all() __flush_tlb_global()
+ 
+ #define __flush_tlb_one(addr)	xen_invlpg((unsigned long)addr)
+--- head-2010-01-18.orig/include/linux/skbuff.h	2009-12-07 12:13:58.000000000 +0100
++++ head-2010-01-18/include/linux/skbuff.h	2009-12-16 11:49:35.000000000 +0100
+@@ -2121,5 +2121,12 @@ static inline void skb_forward_csum(stru
+ }
+ 
+ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
++
++#ifdef CONFIG_XEN
++int skb_checksum_setup(struct sk_buff *skb);
++#else
++static inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
++#endif
++
+ #endif	/* __KERNEL__ */
+ #endif	/* _LINUX_SKBUFF_H */
+--- head-2010-01-18.orig/include/xen/evtchn.h	2009-12-18 10:08:33.000000000 +0100
++++ head-2010-01-18/include/xen/evtchn.h	2009-12-18 10:09:29.000000000 +0100
+@@ -57,34 +57,34 @@
+  */
+ int bind_caller_port_to_irqhandler(
+ 	unsigned int caller_port,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
+ int bind_listening_port_to_irqhandler(
+ 	unsigned int remote_domain,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
+ int bind_interdomain_evtchn_to_irqhandler(
+ 	unsigned int remote_domain,
+ 	unsigned int remote_port,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
+ int bind_virq_to_irqhandler(
+ 	unsigned int virq,
+ 	unsigned int cpu,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
+ int bind_ipi_to_irqhandler(
+ 	unsigned int ipi,
+ 	unsigned int cpu,
+-	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	irq_handler_t handler,
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
+--- head-2010-01-18.orig/include/xen/xencons.h	2007-10-15 09:39:38.000000000 +0200
++++ head-2010-01-18/include/xen/xencons.h	2009-11-06 10:45:48.000000000 +0100
+@@ -8,7 +8,7 @@ void xencons_force_flush(void);
+ void xencons_resume(void);
+ 
+ /* Interrupt work hooks. Receive data, or kick data out. */
+-void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
++void xencons_rx(char *buf, unsigned len);
+ void xencons_tx(void);
+ 
+ int xencons_ring_init(void);
+--- head-2010-01-18.orig/mm/mprotect.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/mm/mprotect.c	2009-11-06 10:45:48.000000000 +0100
+@@ -91,7 +91,7 @@ static inline void change_pmd_range(stru
+ 		next = pmd_addr_end(addr, end);
+ 		if (pmd_none_or_clear_bad(pmd))
+ 			continue;
+-		if (arch_change_pte_range(mm, pmd, addr, next, newprot))
++		if (arch_change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable))
+ 			continue;
+ 		change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable);
+ 	} while (pmd++, addr = next, addr != end);
+--- head-2010-01-18.orig/mm/page_alloc.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/mm/page_alloc.c	2009-12-04 10:49:40.000000000 +0100
+@@ -4661,6 +4661,23 @@ static void __setup_per_zone_wmarks(void
+ 		spin_unlock_irqrestore(&zone->lock, flags);
+ 	}
+ 
++#ifdef CONFIG_XEN
++	for_each_zone(zone) {
++		unsigned int cpu;
++
++		if (!populated_zone(zone))
++			continue;
++		for_each_online_cpu(cpu) {
++			unsigned long high;
++
++			high = percpu_pagelist_fraction
++			       ? zone->present_pages / percpu_pagelist_fraction
++			       : 5 * zone_batchsize(zone);
++			setup_pagelist_highmark(zone_pcp(zone, cpu), high);
++		}
++	}
++#endif
++
+ 	/* update totalreserve_pages */
+ 	calculate_totalreserve_pages();
+ }
+--- head-2010-01-18.orig/net/core/dev.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/net/core/dev.c	2009-12-04 10:49:48.000000000 +0100
+@@ -1848,17 +1848,15 @@ inline int skb_checksum_setup(struct sk_
+ 		}
+ 		if ((skb->h.raw + skb->csum + 2) > skb->tail)
+ 			goto out;
+-		skb->ip_summed = CHECKSUM_HW;
++		skb->ip_summed = CHECKSUM_PARTIAL;
+ 		skb->proto_csum_blank = 0;
+ 	}
+ 	return 0;
+ out:
+ 	return -EPROTO;
+ }
+-#else
+-inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
+-#endif
+ EXPORT_SYMBOL(skb_checksum_setup);
++#endif
+ 
+ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ 				 struct net_device *dev,
+@@ -2434,7 +2432,7 @@ int netif_receive_skb(struct sk_buff *sk
+ 	case CHECKSUM_UNNECESSARY:
+ 		skb->proto_data_valid = 1;
+ 		break;
+-	case CHECKSUM_HW:
++	case CHECKSUM_PARTIAL:
+ 		/* XXX Implement me. */
+ 	default:
+ 		skb->proto_data_valid = 0;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.29
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.29
@@ -0,0 +1,11693 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: Linux: 2.6.29
+Patch-mainline: 2.6.29
+
+ This patch contains the differences between 2.6.28 and 2.6.29.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.29" by xen-port-patches.py
+
+--- sle11sp1-2010-01-20.orig/arch/x86/Kconfig	2009-11-20 11:02:23.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/Kconfig	2009-11-20 11:02:51.000000000 +0100
+@@ -885,7 +885,7 @@ config X86_XEN_GENAPIC
+ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 	bool "Reroute for broken boot IRQs"
+ 	default n
+-	depends on X86_IO_APIC
++	depends on X86_IO_APIC && !XEN
+ 	---help---
+ 	  This option enables a workaround that fixes a source of
+ 	  spurious interrupts. This is recommended when threaded
+--- sle11sp1-2010-01-20.orig/arch/x86/Makefile	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/Makefile	2009-11-06 10:51:55.000000000 +0100
+@@ -158,8 +158,8 @@ BOOT_TARGETS = bzlilo bzdisk fdimage fdi
+ PHONY += bzImage vmlinuz $(BOOT_TARGETS)
+ 
+ ifdef CONFIG_XEN
+-KBUILD_CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
+-	-I$(srctree)/arch/x86/include/mach-xen $(KBUILD_CPPFLAGS)
++LINUXINCLUDE := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
++	-I$(srctree)/arch/x86/include/mach-xen $(LINUXINCLUDE)
+ 
+ ifdef CONFIG_X86_64
+ LDFLAGS_vmlinux := -e startup_64
+--- sle11sp1-2010-01-20.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:55.000000000 +0100
+@@ -363,9 +363,9 @@ ENTRY(ia32_syscall)
+ 	orl   $TS_COMPAT,TI_status(%r10)
+ 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz ia32_tracesys
+-ia32_do_syscall:	
+ 	cmpl $(IA32_NR_syscalls-1),%eax
+-	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
++	ja ia32_badsys
++ia32_do_call:
+ 	IA32_ARG_FIXUP
+ 	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ ia32_sysret:
+@@ -380,7 +380,9 @@ ia32_tracesys:			 
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+-	jmp ia32_do_syscall
++	cmpl $(IA32_NR_syscalls-1),%eax
++	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
++	jmp ia32_do_call
+ END(ia32_syscall)
+ 
+ ia32_badsys:
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/hw_irq.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/hw_irq.h	2009-11-06 10:51:55.000000000 +0100
+@@ -124,7 +124,9 @@ extern irqreturn_t smp_call_function_sin
+ #endif
+ #endif
+ 
++#ifndef CONFIG_XEN
+ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
++#endif
+ 
+ typedef int vector_irq_t[NR_VECTORS];
+ DECLARE_PER_CPU(vector_irq_t, vector_irq);
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/hypervisor.h	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/hypervisor.h	2009-11-06 10:51:55.000000000 +0100
+@@ -24,3 +24,7 @@ extern void init_hypervisor(struct cpuin
+ extern void init_hypervisor_platform(void);
+ 
+ #endif
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include_next <asm/hypervisor.h>
++#endif
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/kexec.h	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/kexec.h	2009-11-06 10:51:55.000000000 +0100
+@@ -12,13 +12,10 @@
+ /*
+  * The hypervisor interface implicitly requires that all entries (except
+  * for possibly the final one) are arranged in matching PA_/VA_ pairs.
++#  define VA_PGD		3
+  */
+-#  define PA_PMD_0		8
+-#  define VA_PMD_0		9
+-#  define PA_PMD_1		10
+-#  define VA_PMD_1		11
+-#  define PA_SWAP_PAGE		12
+-#  define PAGES_NR		13
++#  define PA_SWAP_PAGE		4
++#  define PAGES_NR		5
+ # endif /* CONFIG_XEN */
+ #else
+ # define PA_CONTROL_PAGE	0
+--- sle11sp1-2010-01-20.orig/arch/x86/include/asm/xen/hypervisor.h	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/asm/xen/hypervisor.h	2009-11-06 10:51:55.000000000 +0100
+@@ -43,7 +43,7 @@ enum xen_domain_type {
+ 	XEN_HVM_DOMAIN,		/* running in a Xen hvm domain */
+ };
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ extern enum xen_domain_type xen_domain_type;
+ #else
+ #define xen_domain_type		XEN_NATIVE
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:55.000000000 +0100
+@@ -342,16 +342,14 @@ static inline void set_intr_gate(unsigne
+ 	_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+ }
+ 
+-#define SYS_VECTOR_FREE		0
+-#define SYS_VECTOR_ALLOCED	1
+-
+ extern int first_system_vector;
+-extern char system_vectors[];
++/* used_vectors is BITMAP for irq is not managed by percpu vector_irq */
++extern unsigned long used_vectors[];
+ 
+ static inline void alloc_system_vector(int vector)
+ {
+-	if (system_vectors[vector] == SYS_VECTOR_FREE) {
+-		system_vectors[vector] = SYS_VECTOR_ALLOCED;
++	if (!test_bit(vector, used_vectors)) {
++		set_bit(vector, used_vectors);
+ 		if (first_system_vector > vector)
+ 			first_system_vector = vector;
+ 	} else
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:55.000000000 +0100
+@@ -16,7 +16,6 @@
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+ #include <asm/vsyscall.h>
+-#include <asm/efi.h>
+ #include <asm/acpi.h>
+ 
+ /*
+@@ -52,11 +51,6 @@ enum fixed_addresses {
+ 	FIX_ISAMAP_END,
+ 	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ #endif
+-#ifdef CONFIG_EFI
+-	FIX_EFI_IO_MAP_LAST_PAGE,
+-	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE
+-				  + MAX_EFI_IO_PAGES - 1,
+-#endif
+ #ifdef CONFIG_PARAVIRT
+ 	FIX_PARAVIRT_BOOTMAP,
+ #else
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:55.000000000 +0100
+@@ -80,6 +80,7 @@ static inline void clear_user_highpage(s
+ 	clear_highpage(page);
+ }
+ #define __HAVE_ARCH_CLEAR_HIGHPAGE
++#define clear_user_highpage clear_user_highpage
+ #define __HAVE_ARCH_CLEAR_USER_HIGHPAGE
+ 
+ void copy_highpage(struct page *to, struct page *from);
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:33:49.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:42:20.000000000 +0100
+@@ -69,6 +69,8 @@ extern start_info_t *xen_start_info;
+ #define is_initial_xendomain() 0
+ #endif
+ 
++#define init_hypervisor(c) ((void)((c)->x86_hyper_vendor = X86_HYPER_VENDOR_XEN))
++
+ struct vcpu_runstate_info *setup_runstate_area(unsigned int cpu);
+ 
+ /* arch/xen/kernel/evtchn.c */
+@@ -139,7 +141,7 @@ void scrub_pages(void *, unsigned int);
+ 
+ DECLARE_PER_CPU(bool, xen_lazy_mmu);
+ 
+-int xen_multicall_flush(bool);
++void xen_multicall_flush(bool);
+ 
+ int __must_check xen_multi_update_va_mapping(unsigned long va, pte_t,
+ 					     unsigned long flags);
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/io.h	2009-12-11 15:20:59.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:55.000000000 +0100
+@@ -4,6 +4,7 @@
+ #define ARCH_HAS_IOREMAP_WC
+ 
+ #include <linux/compiler.h>
++#include <asm-generic/int-ll64.h>
+ 
+ #define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void __iomem *addr) \
+@@ -45,21 +46,39 @@ build_mmio_write(__writel, "l", unsigned
+ #define mmiowb() barrier()
+ 
+ #ifdef CONFIG_X86_64
++
+ build_mmio_read(readq, "q", unsigned long, "=r", :"memory")
+-build_mmio_read(__readq, "q", unsigned long, "=r", )
+ build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
+-build_mmio_write(__writeq, "q", unsigned long, "r", )
+ 
+-#define readq_relaxed(a) __readq(a)
+-#define __raw_readq __readq
+-#define __raw_writeq writeq
+-
+-/* Let people know we have them */
+-#define readq readq
+-#define writeq writeq
++#else
++
++static inline __u64 readq(const volatile void __iomem *addr)
++{
++	const volatile u32 __iomem *p = addr;
++	u32 low, high;
++
++	low = readl(p);
++	high = readl(p + 1);
++
++	return low + ((u64)high << 32);
++}
++
++static inline void writeq(__u64 val, volatile void __iomem *addr)
++{
++	writel(val, addr);
++	writel(val >> 32, addr+4);
++}
++
+ #endif
+ 
+-extern int iommu_bio_merge;
++#define readq_relaxed(a)	readq(a)
++
++#define __raw_readq(a)		readq(a)
++#define __raw_writeq(val, addr)	writeq(val, addr)
++
++/* Let people know that we have them */
++#define readq			readq
++#define writeq			writeq
+ 
+ #define native_io_delay xen_io_delay
+ 
+@@ -120,7 +139,6 @@ extern void __iomem *ioremap_wc(unsigned
+  * A boot-time mapping is currently limited to at most 16 pages.
+  */
+ extern void early_ioremap_init(void);
+-extern void early_ioremap_clear(void);
+ extern void early_ioremap_reset(void);
+ extern void __iomem *early_ioremap(unsigned long offset, unsigned long size);
+ extern void __iomem *early_memremap(unsigned long offset, unsigned long size);
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:55.000000000 +0100
+@@ -24,6 +24,8 @@
+ #define LAST_VM86_IRQ		15
+ #define invalid_vm86_irq(irq)	((irq) < 3 || (irq) > 15)
+ 
++#define NR_IRQS_LEGACY		16
++
+ /*
+  * The flat IRQ space is divided into two regions:
+  *  1. A one-to-one mapping of real physical IRQs. This space is only used
+@@ -36,8 +38,10 @@
+ 
+ #define PIRQ_BASE		0
+ #if defined(NR_CPUS) && defined(MAX_IO_APICS)
+-# if NR_CPUS < MAX_IO_APICS
++# if !defined(CONFIG_SPARSE_IRQ) && NR_CPUS < MAX_IO_APICS
+ #  define NR_PIRQS		(NR_VECTORS + 32 * NR_CPUS)
++# elif defined(CONFIG_SPARSE_IRQ) && 8 * NR_CPUS > 32 * MAX_IO_APICS
++#  define NR_PIRQS		(NR_VECTORS + 8 * NR_CPUS)
+ # else
+ #  define NR_PIRQS		(NR_VECTORS + 32 * MAX_IO_APICS)
+ # endif
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:55.000000000 +0100
+@@ -3,10 +3,9 @@
+ 
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+-#if 0 /* XEN: no lazy tlb */
+-	unsigned cpu = smp_processor_id();
+-	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+-		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_LAZY;
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
++	if (x86_read_percpu(cpu_tlbstate.state) == TLBSTATE_OK)
++		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_LAZY);
+ #endif
+ }
+ 
+@@ -38,9 +37,9 @@ static inline void switch_mm(struct mm_s
+ 
+ 		/* stop flush ipis for the previous mm */
+ 		cpu_clear(cpu, prev->cpu_vm_mask);
+-#if 0 /* XEN: no lazy tlb */
+-		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+-		per_cpu(cpu_tlbstate, cpu).active_mm = next;
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
++		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK);
++		x86_write_percpu(cpu_tlbstate.active_mm, next);
+ #endif
+ 		cpu_set(cpu, next->cpu_vm_mask);
+ 
+@@ -62,10 +61,10 @@ static inline void switch_mm(struct mm_s
+ 
+ 		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
+ 	}
+-#if 0 /* XEN: no lazy tlb */
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+ 	else {
+-		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+-		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
++		x86_write_percpu(cpu_tlbstate.state, TLBSTATE_OK);
++		BUG_ON(x86_read_percpu(cpu_tlbstate.active_mm) != next);
+ 
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+ 			/* We were in lazy tlb mode and leave_mm disabled
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:55.000000000 +0100
+@@ -22,6 +22,8 @@ struct pci_sysdata {
+ };
+ 
+ extern int pci_routeirq;
++extern int noioapicquirk;
++extern int noioapicreroute;
+ 
+ /* scan a bus after allocating a pci_sysdata for it */
+ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
+@@ -88,6 +90,8 @@ static inline void pci_dma_burst_advice(
+ static inline void early_quirks(void) { }
+ #endif
+ 
++extern void pci_iommu_alloc(void);
++
+ #endif  /* __KERNEL__ */
+ 
+ #ifdef CONFIG_X86_32
+@@ -104,9 +108,9 @@ static inline void early_quirks(void) { 
+ 
+ #ifdef CONFIG_NUMA
+ /* Returns the node based on pci bus */
+-static inline int __pcibus_to_node(struct pci_bus *bus)
++static inline int __pcibus_to_node(const struct pci_bus *bus)
+ {
+-	struct pci_sysdata *sd = bus->sysdata;
++	const struct pci_sysdata *sd = bus->sysdata;
+ 
+ 	return sd->node;
+ }
+@@ -115,6 +119,12 @@ static inline cpumask_t __pcibus_to_cpum
+ {
+ 	return node_to_cpumask(__pcibus_to_node(bus));
+ }
++
++static inline const struct cpumask *
++cpumask_of_pcibus(const struct pci_bus *bus)
++{
++	return cpumask_of_node(__pcibus_to_node(bus));
++}
+ #endif
+ 
+ #endif /* _ASM_X86_PCI_H */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:55.000000000 +0100
+@@ -22,12 +22,10 @@
+ #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+ 
+ /* If _PAGE_BIT_PRESENT is clear, we use these: */
+-
+-/* set: nonlinear file mapping, saved PTE; unset:swap */
+-#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
+-
+-/* if the user mapped it with PROT_NONE; pte_present gives true */
++/* - if the user mapped it with PROT_NONE; pte_present gives true */
+ #define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
++/* - set: nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
+ 
+ #define _PAGE_PRESENT	(_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
+ #define _PAGE_RW	(_AT(pteval_t, 1) << _PAGE_BIT_RW)
+@@ -176,8 +174,19 @@ extern unsigned int __kernel_page_user;
+ #define PGD_IDENT_ATTR	 0x001		/* PRESENT (no other attributes) */
+ #endif
+ 
++/*
++ * Macro to mark a page protection value as UC-
++ */
++#define pgprot_noncached(prot)					\
++	((boot_cpu_data.x86 > 3)				\
++	 ? (__pgprot(pgprot_val(prot) | _PAGE_CACHE_UC_MINUS))	\
++	 : (prot))
++
+ #ifndef __ASSEMBLY__
+ 
++#define pgprot_writecombine	pgprot_writecombine
++extern pgprot_t pgprot_writecombine(pgprot_t prot);
++
+ /*
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+@@ -309,41 +318,43 @@ static inline pte_t pte_mkspecial(pte_t 
+ 
+ extern pteval_t __supported_pte_mask;
+ 
+-static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
++/*
++ * Mask out unsupported bits in a present pgprot.  Non-present pgprots
++ * can use those bits for other purposes, so leave them be.
++ */
++static inline pgprotval_t massage_pgprot(pgprot_t pgprot)
+ {
+-	pgprotval_t prot = pgprot_val(pgprot);
++	pgprotval_t protval = pgprot_val(pgprot);
++
++	if (protval & _PAGE_PRESENT)
++		protval &= __supported_pte_mask;
+ 
+-	if (prot & _PAGE_PRESENT)
+-		prot &= __supported_pte_mask;
+-	return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
++	return protval;
+ }
+ 
+-static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
++static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+ {
+-	pgprotval_t prot = pgprot_val(pgprot);
++	return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) |
++		     massage_pgprot(pgprot));
++}
+ 
+-	if (prot & _PAGE_PRESENT)
+-		prot &= __supported_pte_mask;
+-	return __pte_ma(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
++static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pte_ma(((phys_addr_t)page_nr << PAGE_SHIFT) |
++			massage_pgprot(pgprot));
+ }
+ 
+ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+ {
+-	pgprotval_t prot = pgprot_val(pgprot);
+-
+-	if (prot & _PAGE_PRESENT)
+-		prot &= __supported_pte_mask;
+-	return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
++	return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) |
++		     massage_pgprot(pgprot));
+ }
+ 
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+-	pgprotval_t prot = pgprot_val(newprot);
+ 	pteval_t val = pte_val(pte) & _PAGE_CHG_MASK;
+ 
+-	if (prot & _PAGE_PRESENT)
+-		prot &= __supported_pte_mask;
+-	val |= prot & ~_PAGE_CHG_MASK;
++	val |= massage_pgprot(newprot) & ~_PAGE_CHG_MASK;
+ 
+ 	return __pte(val);
+ }
+@@ -359,11 +370,33 @@ static inline pgprot_t pgprot_modify(pgp
+ 
+ #define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
+ 
+-#define canon_pgprot(p) __pgprot(pgprot_val(p) & _PAGE_PRESENT \
+-				 ? pgprot_val(p) & __supported_pte_mask \
+-				 : pgprot_val(p))
++#define canon_pgprot(p) __pgprot(massage_pgprot(p))
++
++static inline int is_new_memtype_allowed(unsigned long flags,
++						unsigned long new_flags)
++{
++	/*
++	 * Certain new memtypes are not allowed with certain
++	 * requested memtype:
++	 * - request is uncached, return cannot be write-back
++	 * - request is write-combine, return cannot be write-back
++	 */
++	if ((flags == _PAGE_CACHE_UC_MINUS &&
++	     new_flags == _PAGE_CACHE_WB) ||
++	    (flags == _PAGE_CACHE_WC &&
++	     new_flags == _PAGE_CACHE_WB)) {
++		return 0;
++	}
++
++	return 1;
++}
+ 
+ #ifndef __ASSEMBLY__
++#ifndef CONFIG_XEN
++/* Indicate that x86 has its own track and untrack pfn vma functions */
++#define __HAVE_PFNMAP_TRACKING
++#endif
++
+ #define __HAVE_PHYS_MEM_ACCESS_PROT
+ struct file;
+ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:55.000000000 +0100
+@@ -151,6 +151,7 @@ static inline int pte_none(pte_t pte)
+ #define PTE_FILE_MAX_BITS       32
+ 
+ /* Encode and de-code a swap entry */
++#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5)
+ #define __swp_type(x)			(((x).val) & 0x1f)
+ #define __swp_offset(x)			((x).val >> 5)
+ #define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:55.000000000 +0100
+@@ -107,15 +107,6 @@ extern unsigned long pg0[];
+ #endif
+ 
+ /*
+- * Macro to mark a page protection value as "uncacheable".
+- * On processors which do not support it, this is a no-op.
+- */
+-#define pgprot_noncached(prot)					\
+-	((boot_cpu_data.x86 > 3)				\
+-	 ? (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))	\
+-	 : (prot))
+-
+-/*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+  */
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:55.000000000 +0100
+@@ -149,8 +149,8 @@ static inline void xen_pgd_clear(pgd_t *
+ #define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+ 
+-
+-#define MAXMEM		 _AC(0x000004ffffffffff, UL)
++#define MAX_PHYSMEM_BITS 43
++#define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
+ #define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+@@ -183,12 +183,6 @@ static inline int pmd_bad(pmd_t pmd)
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
+ /*
+- * Macro to mark a page protection value as "uncacheable".
+- */
+-#define pgprot_noncached(prot)					\
+-	(__pgprot(pgprot_val((prot)) | _PAGE_PCD | _PAGE_PWT))
+-
+-/*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+  */
+@@ -270,6 +264,8 @@ static inline int pud_large(pud_t pte)
+ #define SWP_OFFSET_SHIFT (_PAGE_BIT_FILE + 1)
+ #endif
+ 
++#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
++
+ #define __swp_type(x)			(((x).val >> (_PAGE_BIT_PRESENT + 1)) \
+ 					 & ((1U << SWP_TYPE_BITS) - 1))
+ #define __swp_offset(x)			((x).val >> SWP_OFFSET_SHIFT)
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:55.000000000 +0100
+@@ -111,6 +111,7 @@ struct cpuinfo_x86 {
+ 	/* Index into per_cpu list: */
+ 	u16			cpu_index;
+ #endif
++	unsigned int		x86_hyper_vendor;
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+ 
+ #define X86_VENDOR_INTEL	0
+@@ -124,6 +125,10 @@ struct cpuinfo_x86 {
+ 
+ #define X86_VENDOR_UNKNOWN	0xff
+ 
++#define X86_HYPER_VENDOR_NONE  0
++#define X86_HYPER_VENDOR_VMWARE 1
++#define X86_HYPER_VENDOR_XEN   'X'
++
+ /*
+  * capabilities of CPUs
+  */
+@@ -354,7 +359,7 @@ struct i387_soft_struct {
+ 	u8			no_update;
+ 	u8			rm;
+ 	u8			alimit;
+-	struct info		*info;
++	struct math_emu_info	*info;
+ 	u32			entry_eip;
+ };
+ 
+@@ -696,6 +701,19 @@ extern void switch_to_new_gdt(void);
+ extern void cpu_init(void);
+ extern void init_gdt(int cpu);
+ 
++static inline unsigned long get_debugctlmsr(void)
++{
++    unsigned long debugctlmsr = 0;
++
++#ifndef CONFIG_X86_DEBUGCTLMSR
++	if (boot_cpu_data.x86 < 6)
++		return 0;
++#endif
++	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
++
++    return debugctlmsr;
++}
++
+ static inline void update_debugctlmsr(unsigned long debugctlmsr)
+ {
+ #ifndef CONFIG_X86_DEBUGCTLMSR
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:43.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:58.000000000 +0100
+@@ -18,9 +18,26 @@
+ #include <asm/pda.h>
+ #include <asm/thread_info.h>
+ 
++#ifdef CONFIG_X86_64
++
++#define cpu_callin_mask cpu_possible_mask
++#define cpu_callout_mask cpu_possible_mask
++extern cpumask_var_t cpu_initialized_mask;
++extern cpumask_var_t cpu_sibling_setup_mask;
++
++#else /* CONFIG_X86_32 */
++
++#define cpu_callin_map cpu_possible_map
+ #define cpu_callout_map cpu_possible_map
+ extern cpumask_t cpu_initialized;
+-#define cpu_callin_map cpu_possible_map
++extern cpumask_t cpu_sibling_setup_map;
++
++#define cpu_callin_mask		((struct cpumask *)&cpu_callin_map)
++#define cpu_callout_mask	((struct cpumask *)&cpu_callout_map)
++#define cpu_initialized_mask	((struct cpumask *)&cpu_initialized)
++#define cpu_sibling_setup_mask	((struct cpumask *)&cpu_sibling_setup_map)
++
++#endif /* CONFIG_X86_32 */
+ 
+ extern void (*mtrr_hook)(void);
+ extern void zap_low_mappings(void);
+@@ -29,7 +46,6 @@ extern int __cpuinit get_local_pda(int c
+ 
+ extern int smp_num_siblings;
+ extern unsigned int num_processors;
+-extern cpumask_t cpu_initialized;
+ 
+ DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+ DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+@@ -38,6 +54,16 @@ DECLARE_PER_CPU(u16, cpu_llc_id);
+ DECLARE_PER_CPU(int, cpu_number);
+ #endif
+ 
++static inline struct cpumask *cpu_sibling_mask(int cpu)
++{
++	return &per_cpu(cpu_sibling_map, cpu);
++}
++
++static inline struct cpumask *cpu_core_mask(int cpu)
++{
++	return &per_cpu(cpu_core_map, cpu);
++}
++
+ DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+ DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+ 
+@@ -64,7 +90,7 @@ struct smp_ops {
+ 	void (*cpu_die)(unsigned int cpu);
+ 	void (*play_dead)(void);
+ 
+-	void (*send_call_func_ipi)(cpumask_t mask);
++	void (*send_call_func_ipi)(const struct cpumask *mask);
+ 	void (*send_call_func_single_ipi)(int cpu);
+ };
+ 
+@@ -125,7 +151,7 @@ static inline void arch_send_call_functi
+ 
+ static inline void arch_send_call_function_ipi(cpumask_t mask)
+ {
+-	smp_ops.send_call_func_ipi(mask);
++	smp_ops.send_call_func_ipi(&mask);
+ }
+ 
+ void cpu_disable_common(void);
+@@ -144,13 +170,13 @@ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ void xen_smp_send_stop(void);
+ void xen_smp_send_reschedule(int cpu);
+-void xen_send_call_func_ipi(cpumask_t mask);
++void xen_send_call_func_ipi(const struct cpumask *mask);
+ void xen_send_call_func_single_ipi(int cpu);
+ 
+ #define smp_send_stop		xen_smp_send_stop
+ #define smp_send_reschedule	xen_smp_send_reschedule
+ #define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
+-#define arch_send_call_function_ipi		xen_send_call_func_ipi
++#define arch_send_call_function_ipi(m)		xen_send_call_func_ipi(&(m))
+ 
+ void play_dead(void);
+ 
+@@ -164,7 +190,7 @@ void smp_store_cpu_info(int id);
+ /* We don't mark CPUs online until __cpu_up(), so we need another measure */
+ static inline int num_booting_cpus(void)
+ {
+-	return cpus_weight(cpu_callout_map);
++	return cpumask_weight(cpu_callout_mask);
+ }
+ #else
+ static inline void prefill_possible_map(void)
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:35.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:42.000000000 +0100
+@@ -332,6 +332,7 @@ static inline int __raw_spin_is_contende
+ {
+ 	return __raw_spin(is_contended)(lock);
+ }
++#define __raw_spin_is_contended	__raw_spin_is_contended
+ 
+ static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+ {
+--- sle11sp1-2010-01-20.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:55.000000000 +0100
+@@ -18,12 +18,12 @@
+ # define AT_VECTOR_SIZE_ARCH 1
+ #endif
+ 
+-#ifdef CONFIG_X86_32
+-
+ struct task_struct; /* one of the stranger aspects of C forward declarations */
+ struct task_struct *__switch_to(struct task_struct *prev,
+ 				struct task_struct *next);
+ 
++#ifdef CONFIG_X86_32
++
+ /*
+  * Saving eflags is important. It switches not only IOPL between tasks,
+  * it also protects other tasks from NT leaking through sysenter etc.
+@@ -298,6 +298,8 @@ extern void free_init_pages(char *what, 
+ 
+ void xen_idle(void);
+ 
++void stop_this_cpu(void *dummy);
++
+ /*
+  * Force strict CPU ordering.
+  * And yes, this is required on UP too when we're talking
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -163,6 +163,8 @@ static int __init acpi_sleep_setup(char 
+ #ifdef CONFIG_HIBERNATION
+ 		if (strncmp(str, "s4_nohwsig", 10) == 0)
+ 			acpi_no_s4_hw_signature();
++		if (strncmp(str, "s4_nonvs", 8) == 0)
++			acpi_s4_no_nvs();
+ #endif
+ 		if (strncmp(str, "old_ordering", 12) == 0)
+ 			acpi_old_suspend_ordering();
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/apic/apic-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/apic/apic-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -32,7 +32,7 @@ static int __init apic_set_verbosity(cha
+ 	else if (strcmp("verbose", arg) == 0)
+ 		apic_verbosity = APIC_VERBOSE;
+ 	else {
+-		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
++		pr_warning("APIC Verbosity level %s not recognised"
+ 			" use apic=verbose or apic=debug\n", arg);
+ 		return -EINVAL;
+ 	}
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/Makefile	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/Makefile	2009-11-06 10:51:55.000000000 +0100
+@@ -35,6 +35,8 @@ obj-$(CONFIG_CPU_FREQ)			+= cpufreq/
+ 
+ obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
+ 
++disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o
++
+ quiet_cmd_mkcapflags = MKCAP   $@
+       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -38,17 +38,41 @@
+ #include <asm/proto.h>
+ #include <asm/sections.h>
+ #include <asm/setup.h>
++#include <asm/hypervisor.h>
+ 
+ #ifdef CONFIG_XEN
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_LOCAL_APIC)
+ #define phys_pkg_id(a,b) a
+ #endif
+-#include <asm/hypervisor.h>
+ #include <xen/interface/callback.h>
+ #endif
+ 
+ #include "cpu.h"
+ 
++#ifdef CONFIG_X86_64
++
++/* all of these masks are initialized in setup_cpu_local_masks() */
++#ifndef CONFIG_XEN
++cpumask_var_t cpu_callin_mask;
++cpumask_var_t cpu_callout_mask;
++#endif
++cpumask_var_t cpu_initialized_mask;
++
++/* representing cpus for which sibling maps can be computed */
++cpumask_var_t cpu_sibling_setup_mask;
++
++#else /* CONFIG_X86_32 */
++
++#ifndef CONFIG_XEN
++cpumask_t cpu_callin_map;
++cpumask_t cpu_callout_map;
++#endif
++cpumask_t cpu_initialized;
++cpumask_t cpu_sibling_setup_map;
++
++#endif /* CONFIG_X86_32 */
++
++
+ static struct cpu_dev *this_cpu __cpuinitdata;
+ 
+ #ifdef CONFIG_X86_64
+@@ -377,7 +401,7 @@ void __cpuinit detect_ht(struct cpuinfo_
+ 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+ 	} else if (smp_num_siblings > 1) {
+ 
+-		if (smp_num_siblings > NR_CPUS) {
++		if (smp_num_siblings > nr_cpu_ids) {
+ 			printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
+ 					smp_num_siblings);
+ 			smp_num_siblings = 1;
+@@ -728,6 +752,7 @@ static void __cpuinit identify_cpu(struc
+ 	detect_ht(c);
+ #endif
+ 
++	init_hypervisor(c);
+ 	/*
+ 	 * On SMP, boot_cpu_data holds the common feature set between
+ 	 * all CPUs; so make sure that we indicate which features are
+@@ -879,8 +904,6 @@ static __init int setup_disablecpuid(cha
+ }
+ __setup("clearcpuid=", setup_disablecpuid);
+ 
+-cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+-
+ #ifdef CONFIG_X86_64
+ struct x8664_pda **_cpu_pda __read_mostly;
+ EXPORT_SYMBOL(_cpu_pda);
+@@ -889,7 +912,7 @@ EXPORT_SYMBOL(_cpu_pda);
+ struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
+ #endif
+ 
+-char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
++static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
+ 
+ static void __ref switch_pt(int cpu)
+ {
+@@ -949,8 +972,8 @@ void __cpuinit pda_init(int cpu)
+ }
+ 
+ #ifndef CONFIG_X86_NO_TSS
+-char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
+-			   DEBUG_STKSZ] __page_aligned_bss;
++static char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
++				  DEBUG_STKSZ] __page_aligned_bss;
+ #endif
+ 
+ extern asmlinkage void ignore_sysret(void);
+@@ -1038,7 +1061,7 @@ void __cpuinit cpu_init(void)
+ 
+ 	me = current;
+ 
+-	if (cpu_test_and_set(cpu, cpu_initialized))
++	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask))
+ 		panic("CPU#%d already initialized!\n", cpu);
+ 
+ 	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+@@ -1163,7 +1186,7 @@ void __cpuinit cpu_init(void)
+ #endif
+ 	struct thread_struct *thread = &curr->thread;
+ 
+-	if (cpu_test_and_set(cpu, cpu_initialized)) {
++	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
+ 		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+ 		for (;;) local_irq_enable();
+ 	}
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -33,7 +33,7 @@ struct mtrr_ops generic_mtrr_ops = {
+ 
+ struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
+ unsigned int num_var_ranges;
+-unsigned int mtrr_usage_table[MAX_VAR_RANGES];
++unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
+ 
+ static u64 tom2;
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -719,6 +719,27 @@ void __init e820_mark_nosave_regions(uns
+ 	}
+ }
+ #endif
++
++#ifdef CONFIG_HIBERNATION
++/**
++ * Mark ACPI NVS memory region, so that we can save/restore it during
++ * hibernation and the subsequent resume.
++ */
++static int __init e820_mark_nvs_memory(void)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++
++		if (ei->type == E820_NVS)
++			hibernate_nvs_register(ei->addr, ei->size);
++	}
++
++	return 0;
++}
++core_initcall(e820_mark_nvs_memory);
++#endif
+ #endif
+ 
+ /*
+@@ -734,22 +755,6 @@ struct early_res {
+ static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ #ifndef CONFIG_XEN
+ 	{ 0, PAGE_SIZE, "BIOS data page" },	/* BIOS data page */
+-#if defined(CONFIG_X86_64) && defined(CONFIG_X86_TRAMPOLINE)
+-	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + 2 * PAGE_SIZE, "TRAMPOLINE" },
+-#endif
+-#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
+-	/*
+-	 * But first pinch a few for the stack/trampoline stuff
+-	 * FIXME: Don't need the extra page at 4K, but need to fix
+-	 * trampoline before removing it. (see the GDT stuff)
+-	 */
+-	{ PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE" },
+-	/*
+-	 * Has to be in very low memory so we can execute
+-	 * real-mode AP code.
+-	 */
+-	{ TRAMPOLINE_BASE, TRAMPOLINE_BASE + PAGE_SIZE, "TRAMPOLINE" },
+-#endif
+ #endif
+ 	{}
+ };
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -904,49 +904,6 @@ static struct console early_dbgp_console
+ };
+ #endif
+ 
+-/* Console interface to a host file on AMD's SimNow! */
+-
+-static int simnow_fd;
+-
+-enum {
+-	MAGIC1 = 0xBACCD00A,
+-	MAGIC2 = 0xCA110000,
+-	XOPEN = 5,
+-	XWRITE = 4,
+-};
+-
+-static noinline long simnow(long cmd, long a, long b, long c)
+-{
+-	long ret;
+-
+-	asm volatile("cpuid" :
+-		     "=a" (ret) :
+-		     "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+-	return ret;
+-}
+-
+-static void __init simnow_init(char *str)
+-{
+-	char *fn = "klog";
+-
+-	if (*str == '=')
+-		fn = ++str;
+-	/* error ignored */
+-	simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
+-}
+-
+-static void simnow_write(struct console *con, const char *s, unsigned n)
+-{
+-	simnow(XWRITE, simnow_fd, (unsigned long)s, n);
+-}
+-
+-static struct console simnow_console = {
+-	.name =		"simnow",
+-	.write =	simnow_write,
+-	.flags =	CON_PRINTBUFFER,
+-	.index =	-1,
+-};
+-
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+ static int __initdata early_console_initialized;
+@@ -958,7 +915,7 @@ asmlinkage void early_printk(const char 
+ 	va_list ap;
+ 
+ 	va_start(ap, fmt);
+-	n = vscnprintf(buf, 512, fmt, ap);
++	n = vscnprintf(buf, sizeof(buf), fmt, ap);
+ 	early_console->write(early_console, buf, n);
+ 	va_end(ap);
+ }
+@@ -991,10 +948,6 @@ static int __init setup_early_printk(cha
+ 		current_ypos = boot_params.screen_info.orig_y;
+ #endif
+ 		early_console = &early_vga_console;
+-	} else if (!strncmp(buf, "simnow", 6)) {
+-		simnow_init(buf + 6);
+-		early_console = &simnow_console;
+-		keep_early = 1;
+ #ifdef CONFIG_EARLY_PRINTK_DBGP
+ 	} else if (!strncmp(buf, "dbgp", 4)) {
+ 		if (early_dbgp_init(buf+4) < 0)
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:55.000000000 +0100
+@@ -690,28 +690,37 @@ END(syscall_badsys)
+ 27:;
+ 
+ /*
+- * Build the entry stubs and pointer table with
+- * some assembler magic.
++ * Build the entry stubs and pointer table with some assembler magic.
++ * We pack 7 stubs into a single 32-byte chunk, which will fit in a
++ * single cache line on all modern x86 implementations.
+  */
+-.section .rodata,"a"
++.section .init.rodata,"a"
+ ENTRY(interrupt)
+ .text
+-
++	.p2align 5
++	.p2align CONFIG_X86_L1_CACHE_SHIFT
+ ENTRY(irq_entries_start)
+ 	RING0_INT_FRAME
+-vector=0
+-.rept NR_VECTORS
+-	ALIGN
+- .if vector
++vector=FIRST_EXTERNAL_VECTOR
++.rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7
++	.balign 32
++  .rept	7
++    .if vector < NR_VECTORS
++      .if vector <> FIRST_EXTERNAL_VECTOR
+ 	CFI_ADJUST_CFA_OFFSET -4
+- .endif
+-1:	pushl $~(vector)
++      .endif
++1:	pushl $(~vector+0x80)	/* Note: always in signed byte range */
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	jmp common_interrupt
+- .previous
++      .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
++	jmp 2f
++      .endif
++      .previous
+ 	.long 1b
+- .text
++      .text
+ vector=vector+1
++    .endif
++  .endr
++2:	jmp common_interrupt
+ .endr
+ END(irq_entries_start)
+ 
+@@ -723,8 +732,9 @@ END(interrupt)
+  * the CPU automatically disables interrupts when executing an IRQ vector,
+  * so IRQ-flags tracing has to follow that:
+  */
+-	ALIGN
++	.p2align CONFIG_X86_L1_CACHE_SHIFT
+ common_interrupt:
++	addl $-0x80,(%esp)	/* Adjust vector into the [-256,-1] range */
+ 	SAVE_ALL
+ 	TRACE_IRQS_OFF
+ 	movl %esp,%eax
+@@ -751,68 +761,7 @@ ENDPROC(name)
+ 
+ #else
+ #define UNWIND_ESPFIX_STACK
+-#endif
+-
+-KPROBE_ENTRY(page_fault)
+-	RING0_EC_FRAME
+-	pushl $do_page_fault
+-	CFI_ADJUST_CFA_OFFSET 4
+-	ALIGN
+-error_code:
+-	/* the function address is in %fs's slot on the stack */
+-	pushl %es
+-	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET es, 0*/
+-	pushl %ds
+-	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET ds, 0*/
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET eax, 0
+-	pushl %ebp
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ebp, 0
+-	pushl %edi
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edi, 0
+-	pushl %esi
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET esi, 0
+-	pushl %edx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET edx, 0
+-	pushl %ecx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ecx, 0
+-	pushl %ebx
+-	CFI_ADJUST_CFA_OFFSET 4
+-	CFI_REL_OFFSET ebx, 0
+-	cld
+-	pushl %fs
+-	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET fs, 0*/
+-	movl $(__KERNEL_PERCPU), %ecx
+-	movl %ecx, %fs
+-	UNWIND_ESPFIX_STACK
+-	popl %ecx
+-	CFI_ADJUST_CFA_OFFSET -4
+-	/*CFI_REGISTER es, ecx*/
+-	movl PT_FS(%esp), %edi		# get the function address
+-	movl PT_ORIG_EAX(%esp), %edx	# get the error code
+-	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
+-	mov  %ecx, PT_FS(%esp)
+-	/*CFI_REL_OFFSET fs, ES*/
+-	movl $(__USER_DS), %ecx
+-	movl %ecx, %ds
+-	movl %ecx, %es
+-	TRACE_IRQS_OFF
+-	movl %esp,%eax			# pt_regs pointer
+-	call *%edi
+-	jmp ret_from_exception
+-	CFI_ENDPROC
+-KPROBE_END(page_fault)
+ 
+-#ifdef CONFIG_XEN
+ # A note on the "critical region" in our callback handler.
+ # We want to avoid stacking callback handlers due to events occurring
+ # during handling of the last event. To do this, we keep events disabled
+@@ -981,158 +930,6 @@ ENTRY(device_not_available)
+ 	CFI_ENDPROC
+ END(device_not_available)
+ 
+-#ifndef CONFIG_XEN
+-/*
+- * Debug traps and NMI can happen at the one SYSENTER instruction
+- * that sets up the real kernel stack. Check here, since we can't
+- * allow the wrong stack to be used.
+- *
+- * "SYSENTER_stack_sp0+12" is because the NMI/debug handler will have
+- * already pushed 3 words if it hits on the sysenter instruction:
+- * eflags, cs and eip.
+- *
+- * We just load the right stack, and push the three (known) values
+- * by hand onto the new stack - while updating the return eip past
+- * the instruction that would have done it for sysenter.
+- */
+-#define FIX_STACK(offset, ok, label)		\
+-	cmpw $__KERNEL_CS,4(%esp);		\
+-	jne ok;					\
+-label:						\
+-	movl SYSENTER_stack_sp0+offset(%esp),%esp;	\
+-	CFI_DEF_CFA esp, 0;			\
+-	CFI_UNDEFINED eip;			\
+-	pushfl;					\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
+-	pushl $__KERNEL_CS;			\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
+-	pushl $sysenter_past_esp;		\
+-	CFI_ADJUST_CFA_OFFSET 4;		\
+-	CFI_REL_OFFSET eip, 0
+-#endif /* CONFIG_XEN */
+-
+-KPROBE_ENTRY(debug)
+-	RING0_INT_FRAME
+-#ifndef CONFIG_XEN
+-	cmpl $ia32_sysenter_target,(%esp)
+-	jne debug_stack_correct
+-	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
+-debug_stack_correct:
+-#endif /* !CONFIG_XEN */
+-	pushl $-1			# mark this as an int
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-	TRACE_IRQS_OFF
+-	xorl %edx,%edx			# error code 0
+-	movl %esp,%eax			# pt_regs pointer
+-	call do_debug
+-	jmp ret_from_exception
+-	CFI_ENDPROC
+-KPROBE_END(debug)
+-
+-#ifndef CONFIG_XEN
+-/*
+- * NMI is doubly nasty. It can happen _while_ we're handling
+- * a debug fault, and the debug fault hasn't yet been able to
+- * clear up the stack. So we first check whether we got  an
+- * NMI on the sysenter entry path, but after that we need to
+- * check whether we got an NMI on the debug path where the debug
+- * fault happened on the sysenter path.
+- */
+-KPROBE_ENTRY(nmi)
+-	RING0_INT_FRAME
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	movl %ss, %eax
+-	cmpw $__ESPFIX_SS, %ax
+-	popl %eax
+-	CFI_ADJUST_CFA_OFFSET -4
+-	je nmi_espfix_stack
+-	cmpl $ia32_sysenter_target,(%esp)
+-	je nmi_stack_fixup
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	movl %esp,%eax
+-	/* Do not access memory above the end of our stack page,
+-	 * it might not exist.
+-	 */
+-	andl $(THREAD_SIZE-1),%eax
+-	cmpl $(THREAD_SIZE-20),%eax
+-	popl %eax
+-	CFI_ADJUST_CFA_OFFSET -4
+-	jae nmi_stack_correct
+-	cmpl $ia32_sysenter_target,12(%esp)
+-	je nmi_debug_stack_check
+-nmi_stack_correct:
+-	/* We have a RING0_INT_FRAME here */
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-	TRACE_IRQS_OFF
+-	xorl %edx,%edx		# zero error code
+-	movl %esp,%eax		# pt_regs pointer
+-	call do_nmi
+-	jmp restore_nocheck_notrace
+-	CFI_ENDPROC
+-
+-nmi_stack_fixup:
+-	RING0_INT_FRAME
+-	FIX_STACK(12,nmi_stack_correct, 1)
+-	jmp nmi_stack_correct
+-
+-nmi_debug_stack_check:
+-	/* We have a RING0_INT_FRAME here */
+-	cmpw $__KERNEL_CS,16(%esp)
+-	jne nmi_stack_correct
+-	cmpl $debug,(%esp)
+-	jb nmi_stack_correct
+-	cmpl $debug_esp_fix_insn,(%esp)
+-	ja nmi_stack_correct
+-	FIX_STACK(24,nmi_stack_correct, 1)
+-	jmp nmi_stack_correct
+-
+-nmi_espfix_stack:
+-	/* We have a RING0_INT_FRAME here.
+-	 *
+-	 * create the pointer to lss back
+-	 */
+-	pushl %ss
+-	CFI_ADJUST_CFA_OFFSET 4
+-	pushl %esp
+-	CFI_ADJUST_CFA_OFFSET 4
+-	addw $4, (%esp)
+-	/* copy the iret frame of 12 bytes */
+-	.rept 3
+-	pushl 16(%esp)
+-	CFI_ADJUST_CFA_OFFSET 4
+-	.endr
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-	TRACE_IRQS_OFF
+-	FIXUP_ESPFIX_STACK		# %eax == %esp
+-	xorl %edx,%edx			# zero error code
+-	call do_nmi
+-	RESTORE_REGS
+-	lss 12+4(%esp), %esp		# back to espfix stack
+-	CFI_ADJUST_CFA_OFFSET -24
+-	jmp irq_return
+-	CFI_ENDPROC
+-#else
+-KPROBE_ENTRY(nmi)
+-	RING0_INT_FRAME
+-	pushl %eax
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-	xorl %edx,%edx		# zero error code
+-	movl %esp,%eax		# pt_regs pointer
+-	call do_nmi
+-	orl  $NMI_MASK, PT_EFLAGS(%esp)
+-	jmp restore_all
+-	CFI_ENDPROC
+-#endif
+-KPROBE_END(nmi)
+-
+ #ifdef CONFIG_PARAVIRT
+ ENTRY(native_iret)
+ 	iret
+@@ -1148,19 +945,6 @@ ENTRY(native_irq_enable_sysexit)
+ END(native_irq_enable_sysexit)
+ #endif
+ 
+-KPROBE_ENTRY(int3)
+-	RING0_INT_FRAME
+-	pushl $-1			# mark this as an int
+-	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-	TRACE_IRQS_OFF
+-	xorl %edx,%edx		# zero error code
+-	movl %esp,%eax		# pt_regs pointer
+-	call do_int3
+-	jmp ret_from_exception
+-	CFI_ENDPROC
+-KPROBE_END(int3)
+-
+ ENTRY(overflow)
+ 	RING0_INT_FRAME
+ 	pushl $0
+@@ -1225,14 +1009,6 @@ ENTRY(stack_segment)
+ 	CFI_ENDPROC
+ END(stack_segment)
+ 
+-KPROBE_ENTRY(general_protection)
+-	RING0_EC_FRAME
+-	pushl $do_general_protection
+-	CFI_ADJUST_CFA_OFFSET 4
+-	jmp error_code
+-	CFI_ENDPROC
+-KPROBE_END(general_protection)
+-
+ ENTRY(alignment_check)
+ 	RING0_EC_FRAME
+ 	pushl $do_alignment_check
+@@ -1292,6 +1068,7 @@ ENTRY(kernel_thread_helper)
+ 	push %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	call do_exit
++	ud2			# padding for call trace
+ 	CFI_ENDPROC
+ ENDPROC(kernel_thread_helper)
+ 
+@@ -1303,6 +1080,9 @@ ENTRY(mcount)
+ END(mcount)
+ 
+ ENTRY(ftrace_caller)
++	cmpl $0, function_trace_stop
++	jne  ftrace_stub
++
+ 	pushl %eax
+ 	pushl %ecx
+ 	pushl %edx
+@@ -1317,6 +1097,11 @@ ftrace_call:
+ 	popl %edx
+ 	popl %ecx
+ 	popl %eax
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++.globl ftrace_graph_call
++ftrace_graph_call:
++	jmp ftrace_stub
++#endif
+ 
+ .globl ftrace_stub
+ ftrace_stub:
+@@ -1326,8 +1111,18 @@ END(ftrace_caller)
+ #else /* ! CONFIG_DYNAMIC_FTRACE */
+ 
+ ENTRY(mcount)
++	cmpl $0, function_trace_stop
++	jne  ftrace_stub
++
+ 	cmpl $ftrace_stub, ftrace_trace_function
+ 	jnz trace
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++	cmpl $ftrace_stub, ftrace_graph_return
++	jnz ftrace_graph_caller
++
++	cmpl $ftrace_graph_entry_stub, ftrace_graph_entry
++	jnz ftrace_graph_caller
++#endif
+ .globl ftrace_stub
+ ftrace_stub:
+ 	ret
+@@ -1346,12 +1141,43 @@ trace:
+ 	popl %edx
+ 	popl %ecx
+ 	popl %eax
+-
+ 	jmp ftrace_stub
+ END(mcount)
+ #endif /* CONFIG_DYNAMIC_FTRACE */
+ #endif /* CONFIG_FUNCTION_TRACER */
+ 
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++ENTRY(ftrace_graph_caller)
++	cmpl $0, function_trace_stop
++	jne ftrace_stub
++
++	pushl %eax
++	pushl %ecx
++	pushl %edx
++	movl 0xc(%esp), %edx
++	lea 0x4(%ebp), %eax
++	subl $MCOUNT_INSN_SIZE, %edx
++	call prepare_ftrace_return
++	popl %edx
++	popl %ecx
++	popl %eax
++	ret
++END(ftrace_graph_caller)
++
++.globl return_to_handler
++return_to_handler:
++	pushl $0
++	pushl %eax
++	pushl %ecx
++	pushl %edx
++	call ftrace_return_to_handler
++	movl %eax, 0xc(%esp)
++	popl %edx
++	popl %ecx
++	popl %eax
++	ret
++#endif
++
+ #include <asm/alternative-asm.h>
+ 
+ 	# pv syscall call handler stub
+@@ -1485,3 +1311,238 @@ mask=0
+ #undef	sys_fork
+ #undef	sys_clone
+ #undef	sys_vfork
++
++/*
++ * Some functions should be protected against kprobes
++ */
++	.pushsection .kprobes.text, "ax"
++
++ENTRY(page_fault)
++	RING0_EC_FRAME
++	pushl $do_page_fault
++	CFI_ADJUST_CFA_OFFSET 4
++	ALIGN
++error_code:
++	/* the function address is in %fs's slot on the stack */
++	pushl %es
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET es, 0*/
++	pushl %ds
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET ds, 0*/
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET eax, 0
++	pushl %ebp
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebp, 0
++	pushl %edi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edi, 0
++	pushl %esi
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET esi, 0
++	pushl %edx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET edx, 0
++	pushl %ecx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ecx, 0
++	pushl %ebx
++	CFI_ADJUST_CFA_OFFSET 4
++	CFI_REL_OFFSET ebx, 0
++	cld
++	pushl %fs
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET fs, 0*/
++	movl $(__KERNEL_PERCPU), %ecx
++	movl %ecx, %fs
++	UNWIND_ESPFIX_STACK
++	popl %ecx
++	CFI_ADJUST_CFA_OFFSET -4
++	/*CFI_REGISTER es, ecx*/
++	movl PT_FS(%esp), %edi		# get the function address
++	movl PT_ORIG_EAX(%esp), %edx	# get the error code
++	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
++	mov  %ecx, PT_FS(%esp)
++	/*CFI_REL_OFFSET fs, ES*/
++	movl $(__USER_DS), %ecx
++	movl %ecx, %ds
++	movl %ecx, %es
++	TRACE_IRQS_OFF
++	movl %esp,%eax			# pt_regs pointer
++	call *%edi
++	jmp ret_from_exception
++	CFI_ENDPROC
++END(page_fault)
++
++#ifndef CONFIG_XEN
++/*
++ * Debug traps and NMI can happen at the one SYSENTER instruction
++ * that sets up the real kernel stack. Check here, since we can't
++ * allow the wrong stack to be used.
++ *
++ * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
++ * already pushed 3 words if it hits on the sysenter instruction:
++ * eflags, cs and eip.
++ *
++ * We just load the right stack, and push the three (known) values
++ * by hand onto the new stack - while updating the return eip past
++ * the instruction that would have done it for sysenter.
++ */
++#define FIX_STACK(offset, ok, label)		\
++	cmpw $__KERNEL_CS,4(%esp);		\
++	jne ok;					\
++label:						\
++	movl TSS_sysenter_sp0+offset(%esp),%esp;	\
++	CFI_DEF_CFA esp, 0;			\
++	CFI_UNDEFINED eip;			\
++	pushfl;					\
++	CFI_ADJUST_CFA_OFFSET 4;		\
++	pushl $__KERNEL_CS;			\
++	CFI_ADJUST_CFA_OFFSET 4;		\
++	pushl $sysenter_past_esp;		\
++	CFI_ADJUST_CFA_OFFSET 4;		\
++	CFI_REL_OFFSET eip, 0
++#endif /* CONFIG_XEN */
++
++ENTRY(debug)
++	RING0_INT_FRAME
++#ifndef CONFIG_XEN
++	cmpl $ia32_sysenter_target,(%esp)
++	jne debug_stack_correct
++	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
++debug_stack_correct:
++#endif /* !CONFIG_XEN */
++	pushl $-1			# mark this as an int
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	TRACE_IRQS_OFF
++	xorl %edx,%edx			# error code 0
++	movl %esp,%eax			# pt_regs pointer
++	call do_debug
++	jmp ret_from_exception
++	CFI_ENDPROC
++END(debug)
++
++/*
++ * NMI is doubly nasty. It can happen _while_ we're handling
++ * a debug fault, and the debug fault hasn't yet been able to
++ * clear up the stack. So we first check whether we got  an
++ * NMI on the sysenter entry path, but after that we need to
++ * check whether we got an NMI on the debug path where the debug
++ * fault happened on the sysenter path.
++ */
++ENTRY(nmi)
++	RING0_INT_FRAME
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++#ifndef CONFIG_XEN
++	movl %ss, %eax
++	cmpw $__ESPFIX_SS, %ax
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
++	je nmi_espfix_stack
++	cmpl $ia32_sysenter_target,(%esp)
++	je nmi_stack_fixup
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	movl %esp,%eax
++	/* Do not access memory above the end of our stack page,
++	 * it might not exist.
++	 */
++	andl $(THREAD_SIZE-1),%eax
++	cmpl $(THREAD_SIZE-20),%eax
++	popl %eax
++	CFI_ADJUST_CFA_OFFSET -4
++	jae nmi_stack_correct
++	cmpl $ia32_sysenter_target,12(%esp)
++	je nmi_debug_stack_check
++nmi_stack_correct:
++	/* We have a RING0_INT_FRAME here */
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_nmi
++	jmp restore_nocheck_notrace
++	CFI_ENDPROC
++
++nmi_stack_fixup:
++	RING0_INT_FRAME
++	FIX_STACK(12,nmi_stack_correct, 1)
++	jmp nmi_stack_correct
++
++nmi_debug_stack_check:
++	/* We have a RING0_INT_FRAME here */
++	cmpw $__KERNEL_CS,16(%esp)
++	jne nmi_stack_correct
++	cmpl $debug,(%esp)
++	jb nmi_stack_correct
++	cmpl $debug_esp_fix_insn,(%esp)
++	ja nmi_stack_correct
++	FIX_STACK(24,nmi_stack_correct, 1)
++	jmp nmi_stack_correct
++
++nmi_espfix_stack:
++	/* We have a RING0_INT_FRAME here.
++	 *
++	 * create the pointer to lss back
++	 */
++	pushl %ss
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl %esp
++	CFI_ADJUST_CFA_OFFSET 4
++	addw $4, (%esp)
++	/* copy the iret frame of 12 bytes */
++	.rept 3
++	pushl 16(%esp)
++	CFI_ADJUST_CFA_OFFSET 4
++	.endr
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	FIXUP_ESPFIX_STACK		# %eax == %esp
++	xorl %edx,%edx			# zero error code
++	call do_nmi
++	RESTORE_REGS
++	lss 12+4(%esp), %esp		# back to espfix stack
++	CFI_ADJUST_CFA_OFFSET -24
++	jmp irq_return
++#else
++	SAVE_ALL
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_nmi
++	orl  $NMI_MASK, PT_EFLAGS(%esp)
++	jmp restore_all
++#endif
++	CFI_ENDPROC
++END(nmi)
++
++ENTRY(int3)
++	RING0_INT_FRAME
++	pushl $-1			# mark this as an int
++	CFI_ADJUST_CFA_OFFSET 4
++	SAVE_ALL
++	TRACE_IRQS_OFF
++	xorl %edx,%edx		# zero error code
++	movl %esp,%eax		# pt_regs pointer
++	call do_int3
++	jmp ret_from_exception
++	CFI_ENDPROC
++END(int3)
++
++ENTRY(general_protection)
++	RING0_EC_FRAME
++	pushl $do_general_protection
++	CFI_ADJUST_CFA_OFFSET 4
++	jmp error_code
++	CFI_ENDPROC
++END(general_protection)
++
++/*
++ * End of kprobes section
++ */
++	.popsection
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:55.000000000 +0100
+@@ -14,15 +14,15 @@
+  *
+  * NOTE: This code handles signal-recognition, which happens every time
+  * after an interrupt and after each system call.
+- * 
+- * Normal syscalls and interrupts don't save a full stack frame, this is 
++ *
++ * Normal syscalls and interrupts don't save a full stack frame, this is
+  * only done for syscall tracing, signals or fork/exec et.al.
+- * 
+- * A note on terminology:	 
+- * - top of stack: Architecture defined interrupt frame from SS to RIP 
+- * at the top of the kernel process stack.	
++ *
++ * A note on terminology:
++ * - top of stack: Architecture defined interrupt frame from SS to RIP
++ * at the top of the kernel process stack.
+  * - partial stack frame: partially saved registers upto R11.
+- * - full stack frame: Like partial stack frame, but all register saved. 
++ * - full stack frame: Like partial stack frame, but all register saved.
+  *
+  * Some macro usage:
+  * - CFI macros are used to generate dwarf2 unwind information for better
+@@ -65,7 +65,6 @@
+ #define __AUDIT_ARCH_LE	   0x40000000
+ 
+ 	.code64
+-
+ #ifdef CONFIG_FUNCTION_TRACER
+ #ifdef CONFIG_DYNAMIC_FTRACE
+ ENTRY(mcount)
+@@ -73,16 +72,10 @@ ENTRY(mcount)
+ END(mcount)
+ 
+ ENTRY(ftrace_caller)
++	cmpl $0, function_trace_stop
++	jne  ftrace_stub
+ 
+-	/* taken from glibc */
+-	subq $0x38, %rsp
+-	movq %rax, (%rsp)
+-	movq %rcx, 8(%rsp)
+-	movq %rdx, 16(%rsp)
+-	movq %rsi, 24(%rsp)
+-	movq %rdi, 32(%rsp)
+-	movq %r8, 40(%rsp)
+-	movq %r9, 48(%rsp)
++	MCOUNT_SAVE_FRAME
+ 
+ 	movq 0x38(%rsp), %rdi
+ 	movq 8(%rbp), %rsi
+@@ -92,14 +85,13 @@ ENTRY(ftrace_caller)
+ ftrace_call:
+ 	call ftrace_stub
+ 
+-	movq 48(%rsp), %r9
+-	movq 40(%rsp), %r8
+-	movq 32(%rsp), %rdi
+-	movq 24(%rsp), %rsi
+-	movq 16(%rsp), %rdx
+-	movq 8(%rsp), %rcx
+-	movq (%rsp), %rax
+-	addq $0x38, %rsp
++	MCOUNT_RESTORE_FRAME
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++.globl ftrace_graph_call
++ftrace_graph_call:
++	jmp ftrace_stub
++#endif
+ 
+ .globl ftrace_stub
+ ftrace_stub:
+@@ -108,15 +100,63 @@ END(ftrace_caller)
+ 
+ #else /* ! CONFIG_DYNAMIC_FTRACE */
+ ENTRY(mcount)
++	cmpl $0, function_trace_stop
++	jne  ftrace_stub
++
+ 	cmpq $ftrace_stub, ftrace_trace_function
+ 	jnz trace
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++	cmpq $ftrace_stub, ftrace_graph_return
++	jnz ftrace_graph_caller
++
++	cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
++	jnz ftrace_graph_caller
++#endif
++
+ .globl ftrace_stub
+ ftrace_stub:
+ 	retq
+ 
+ trace:
+-	/* taken from glibc */
+-	subq $0x38, %rsp
++	MCOUNT_SAVE_FRAME
++
++	movq 0x38(%rsp), %rdi
++	movq 8(%rbp), %rsi
++	subq $MCOUNT_INSN_SIZE, %rdi
++
++	call   *ftrace_trace_function
++
++	MCOUNT_RESTORE_FRAME
++
++	jmp ftrace_stub
++END(mcount)
++#endif /* CONFIG_DYNAMIC_FTRACE */
++#endif /* CONFIG_FUNCTION_TRACER */
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++ENTRY(ftrace_graph_caller)
++	cmpl $0, function_trace_stop
++	jne ftrace_stub
++
++	MCOUNT_SAVE_FRAME
++
++	leaq 8(%rbp), %rdi
++	movq 0x38(%rsp), %rsi
++	subq $MCOUNT_INSN_SIZE, %rsi
++
++	call	prepare_ftrace_return
++
++	MCOUNT_RESTORE_FRAME
++
++	retq
++END(ftrace_graph_caller)
++
++
++.globl return_to_handler
++return_to_handler:
++	subq  $80, %rsp
++
+ 	movq %rax, (%rsp)
+ 	movq %rcx, 8(%rsp)
+ 	movq %rdx, 16(%rsp)
+@@ -124,13 +164,14 @@ trace:
+ 	movq %rdi, 32(%rsp)
+ 	movq %r8, 40(%rsp)
+ 	movq %r9, 48(%rsp)
++	movq %r10, 56(%rsp)
++	movq %r11, 64(%rsp)
+ 
+-	movq 0x38(%rsp), %rdi
+-	movq 8(%rbp), %rsi
+-	subq $MCOUNT_INSN_SIZE, %rdi
+-
+-	call   *ftrace_trace_function
++	call ftrace_return_to_handler
+ 
++	movq %rax, 72(%rsp)
++	movq 64(%rsp), %r11
++	movq 56(%rsp), %r10
+ 	movq 48(%rsp), %r9
+ 	movq 40(%rsp), %r8
+ 	movq 32(%rsp), %rdi
+@@ -138,16 +179,14 @@ trace:
+ 	movq 16(%rsp), %rdx
+ 	movq 8(%rsp), %rcx
+ 	movq (%rsp), %rax
+-	addq $0x38, %rsp
++	addq $72, %rsp
++	retq
++#endif
+ 
+-	jmp ftrace_stub
+-END(mcount)
+-#endif /* CONFIG_DYNAMIC_FTRACE */
+-#endif /* CONFIG_FUNCTION_TRACER */
+ 
+ #ifndef CONFIG_PREEMPT
+ #define retint_kernel retint_restore_args
+-#endif	
++#endif
+ 
+ #ifdef CONFIG_PARAVIRT
+ ENTRY(native_usergs_sysret64)
+@@ -168,20 +207,20 @@ ENTRY(native_usergs_sysret64)
+ NMI_MASK = 0x80000000
+ 	
+ /*
+- * C code is not supposed to know about undefined top of stack. Every time 
+- * a C function with an pt_regs argument is called from the SYSCALL based 
++ * C code is not supposed to know about undefined top of stack. Every time
++ * a C function with an pt_regs argument is called from the SYSCALL based
+  * fast path FIXUP_TOP_OF_STACK is needed.
+  * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
+  * manipulation.
+- */        	
+-		
+-	/* %rsp:at FRAMEEND */ 
+-	.macro FIXUP_TOP_OF_STACK tmp
+-	movq    $__USER_CS,CS(%rsp)
+-	movq 	$-1,RCX(%rsp)
++ */
++
++	/* %rsp:at FRAMEEND */
++	.macro FIXUP_TOP_OF_STACK tmp offset=0
++	movq $__USER_CS,CS+\offset(%rsp)
++	movq $-1,RCX+\offset(%rsp)
+ 	.endm
+ 
+-	.macro RESTORE_TOP_OF_STACK tmp,offset=0
++	.macro RESTORE_TOP_OF_STACK tmp offset=0
+ 	.endm
+ 
+ 	.macro FAKE_STACK_FRAME child_rip
+@@ -193,7 +232,7 @@ NMI_MASK = 0x80000000
+ 	pushq %rax /* rsp */
+ 	CFI_ADJUST_CFA_OFFSET	8
+ 	CFI_REL_OFFSET	rsp,0
+-	pushq $(1<<9) /* eflags - interrupts on */
++	pushq $X86_EFLAGS_IF /* eflags - interrupts on */
+ 	CFI_ADJUST_CFA_OFFSET	8
+ 	/*CFI_REL_OFFSET	rflags,0*/
+ 	pushq $__KERNEL_CS /* cs */
+@@ -211,36 +250,80 @@ NMI_MASK = 0x80000000
+ 	CFI_ADJUST_CFA_OFFSET	-(6*8)
+ 	.endm
+ 
+-	.macro	CFI_DEFAULT_STACK start=1,adj=0
++/*
++ * initial frame state for interrupts (and exceptions without error code)
++ */
++	.macro EMPTY_FRAME start=1 offset=0
+ 	.if \start
+-	CFI_STARTPROC	simple
++	CFI_STARTPROC simple
+ 	CFI_SIGNAL_FRAME
+-	CFI_DEF_CFA	rsp,SS+8 - \adj*ARGOFFSET
++	CFI_DEF_CFA rsp,8+\offset
+ 	.else
+-	CFI_DEF_CFA_OFFSET SS+8 - \adj*ARGOFFSET
++	CFI_DEF_CFA_OFFSET 8+\offset
+ 	.endif
+-	.if \adj == 0
+-	CFI_REL_OFFSET	r15,R15
+-	CFI_REL_OFFSET	r14,R14
+-	CFI_REL_OFFSET	r13,R13
+-	CFI_REL_OFFSET	r12,R12
+-	CFI_REL_OFFSET	rbp,RBP
+-	CFI_REL_OFFSET	rbx,RBX
++	.endm
++
++/*
++ * initial frame state for syscall
++ */
++	.macro BASIC_FRAME start=1 offset=0
++	EMPTY_FRAME \start, SS+8+\offset-RIP
++	/*CFI_REL_OFFSET ss, SS+\offset-RIP*/
++	CFI_REL_OFFSET rsp, RSP+\offset-RIP
++	/*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
++	/*CFI_REL_OFFSET cs, CS+\offset-RIP*/
++	CFI_REL_OFFSET rip, RIP+\offset-RIP
++	.endm
++
++/*
++ * initial frame state for interrupts (and exceptions without error code)
++ */
++	.macro INTR_FRAME start=1 offset=0
++	.if \start == 1
++	BASIC_FRAME 1, \offset+2*8
++	CFI_REL_OFFSET rcx, 0+\offset
++	CFI_REL_OFFSET r11, 8+\offset
++	.else
++	BASIC_FRAME \start, \offset
+ 	.endif
+-	CFI_REL_OFFSET	r11,R11 - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	r10,R10 - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	r9,R9 - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	r8,R8 - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rax,RAX - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rcx,RCX - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rdx,RDX - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rsi,RSI - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rdi,RDI - \adj*ARGOFFSET
+-	CFI_REL_OFFSET	rip,RIP - \adj*ARGOFFSET
+-	/*CFI_REL_OFFSET	cs,CS - \adj*ARGOFFSET*/
+-	/*CFI_REL_OFFSET	rflags,EFLAGS - \adj*ARGOFFSET*/
+-	CFI_REL_OFFSET	rsp,RSP - \adj*ARGOFFSET
+-	/*CFI_REL_OFFSET	ss,SS - \adj*ARGOFFSET*/
++	.endm
++
++/*
++ * initial frame state for exceptions with error code (and interrupts
++ * with vector already pushed)
++ */
++	.macro XCPT_FRAME start=1 offset=0
++	INTR_FRAME \start, RIP+\offset-ORIG_RAX
++	/*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
++	.endm
++
++/*
++ * frame that enables calling into C.
++ */
++	.macro PARTIAL_FRAME start=1 offset=0
++	XCPT_FRAME 2*\start, ORIG_RAX+\offset-ARGOFFSET
++	CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
++	CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
++	CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
++	CFI_REL_OFFSET rcx, RCX+\offset-ARGOFFSET
++	CFI_REL_OFFSET rax, RAX+\offset-ARGOFFSET
++	CFI_REL_OFFSET r8, R8+\offset-ARGOFFSET
++	CFI_REL_OFFSET r9, R9+\offset-ARGOFFSET
++	CFI_REL_OFFSET r10, R10+\offset-ARGOFFSET
++	CFI_REL_OFFSET r11, R11+\offset-ARGOFFSET
++	.endm
++
++/*
++ * frame that enables passing a complete pt_regs to a C function.
++ */
++	.macro DEFAULT_FRAME start=1 offset=0
++	PARTIAL_FRAME \start, R11+\offset-R15
++	CFI_REL_OFFSET rbx, RBX+\offset
++	CFI_REL_OFFSET rbp, RBP+\offset
++	CFI_REL_OFFSET r12, R12+\offset
++	CFI_REL_OFFSET r13, R13+\offset
++	CFI_REL_OFFSET r14, R14+\offset
++	CFI_REL_OFFSET r15, R15+\offset
+ 	.endm
+ 
+         /*
+@@ -270,70 +353,149 @@ NMI_MASK = 0x80000000
+ 	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+ 	.endm
+ 
++#ifndef CONFIG_XEN
++/* save partial stack frame */
++ENTRY(save_args)
++	XCPT_FRAME
++	cld
++	movq_cfi rdi, RDI+16-ARGOFFSET
++	movq_cfi rsi, RSI+16-ARGOFFSET
++	movq_cfi rdx, RDX+16-ARGOFFSET
++	movq_cfi rcx, RCX+16-ARGOFFSET
++	movq_cfi rax, RAX+16-ARGOFFSET
++	movq_cfi  r8,  R8+16-ARGOFFSET
++	movq_cfi  r9,  R9+16-ARGOFFSET
++	movq_cfi r10, R10+16-ARGOFFSET
++	movq_cfi r11, R11+16-ARGOFFSET
++
++	leaq -ARGOFFSET+16(%rsp),%rdi	/* arg1 for handler */
++	movq_cfi rbp, 8		/* push %rbp */
++	leaq 8(%rsp), %rbp		/* mov %rsp, %ebp */
++	testl $3, CS(%rdi)
++	je 1f
++	SWAPGS
++	/*
++	 * irqcount is used to check if a CPU is already on an interrupt stack
++	 * or not. While this is essentially redundant with preempt_count it is
++	 * a little cheaper to use a separate counter in the PDA (short of
++	 * moving irq_enter into assembly, which would be too much work)
++	 */
++1:	incl %gs:pda_irqcount
++	jne 2f
++	popq_cfi %rax			/* move return address... */
++	mov %gs:pda_irqstackptr,%rsp
++	EMPTY_FRAME 0
++	pushq_cfi %rbp			/* backlink for unwinder */
++	pushq_cfi %rax			/* ... to the new stack */
++	/*
++	 * We entered an interrupt context - irqs are off:
++	 */
++2:	TRACE_IRQS_OFF
++	ret
++	CFI_ENDPROC
++END(save_args)
++#endif
++
++ENTRY(save_rest)
++	PARTIAL_FRAME 1 REST_SKIP+8
++	movq 5*8+16(%rsp), %r11	/* save return address */
++	movq_cfi rbx, RBX+16
++	movq_cfi rbp, RBP+16
++	movq_cfi r12, R12+16
++	movq_cfi r13, R13+16
++	movq_cfi r14, R14+16
++	movq_cfi r15, R15+16
++	movq %r11, 8(%rsp)	/* return address */
++	FIXUP_TOP_OF_STACK %r11, 16
++	ret
++	CFI_ENDPROC
++END(save_rest)
++
++#ifndef CONFIG_XEN
++/* save complete stack frame */
++ENTRY(save_paranoid)
++	XCPT_FRAME 1 RDI+8
++	cld
++	movq_cfi rdi, RDI+8
++	movq_cfi rsi, RSI+8
++	movq_cfi rdx, RDX+8
++	movq_cfi rcx, RCX+8
++	movq_cfi rax, RAX+8
++	movq_cfi r8, R8+8
++	movq_cfi r9, R9+8
++	movq_cfi r10, R10+8
++	movq_cfi r11, R11+8
++	movq_cfi rbx, RBX+8
++	movq_cfi rbp, RBP+8
++	movq_cfi r12, R12+8
++	movq_cfi r13, R13+8
++	movq_cfi r14, R14+8
++	movq_cfi r15, R15+8
++	movl $1,%ebx
++	movl $MSR_GS_BASE,%ecx
++	rdmsr
++	testl %edx,%edx
++	js 1f	/* negative -> in kernel */
++	SWAPGS
++	xorl %ebx,%ebx
++1:	ret
++	CFI_ENDPROC
++END(save_paranoid)
++#endif
++
+ /*
+- * A newly forked process directly context switches into this.
+- */ 	
+-/* rdi:	prev */	
++ * A newly forked process directly context switches into this address.
++ *
++ * rdi: prev task we switched from
++ */
+ ENTRY(ret_from_fork)
+-	CFI_DEFAULT_STACK
++	DEFAULT_FRAME
++
+ 	push kernel_eflags(%rip)
+ 	CFI_ADJUST_CFA_OFFSET 8
+-	popf				# reset kernel eflags
++	popf					# reset kernel eflags
+ 	CFI_ADJUST_CFA_OFFSET -8
+-	call schedule_tail
++
++	call schedule_tail			# rdi: 'prev' task parameter
++
+ 	GET_THREAD_INFO(%rcx)
+-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+-	jnz rff_trace
+-rff_action:	
++
++	CFI_REMEMBER_STATE
+ 	RESTORE_REST
+-	testl $3,CS-ARGOFFSET(%rsp)	# from kernel_thread?
++
++	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
+ 	je   int_ret_from_sys_call
+-	testl $_TIF_IA32,TI_flags(%rcx)
++
++	testl $_TIF_IA32, TI_flags(%rcx)	# 32-bit compat task needs IRET
+ 	jnz  int_ret_from_sys_call
+-	RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
+-	jmp ret_from_sys_call
+-rff_trace:
+-	movq %rsp,%rdi
+-	call syscall_trace_leave
+-	GET_THREAD_INFO(%rcx)	
+-	jmp rff_action
++
++	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
++	jmp ret_from_sys_call			# go to the SYSRET fastpath
++
++	CFI_RESTORE_STATE
+ 	CFI_ENDPROC
+ END(ret_from_fork)
+ 
+ /*
+- * initial frame state for interrupts and exceptions
+- */
+-	.macro _frame ref
+-	CFI_STARTPROC simple
+-	CFI_SIGNAL_FRAME
+-	CFI_DEF_CFA rsp,SS+8-\ref
+-	/*CFI_REL_OFFSET ss,SS-\ref*/
+-	CFI_REL_OFFSET rsp,RSP-\ref
+-	/*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+-	/*CFI_REL_OFFSET cs,CS-\ref*/
+-	CFI_REL_OFFSET rip,RIP-\ref
+-	.endm
+-
+-/*
+  * System call entry. Upto 6 arguments in registers are supported.
+  *
+  * SYSCALL does not save anything on the stack and does not change the
+  * stack pointer.
+  */
+-		
++
+ /*
+- * Register setup:	
++ * Register setup:
+  * rax  system call number
+  * rdi  arg0
+- * rcx  return address for syscall/sysret, C arg3 
++ * rcx  return address for syscall/sysret, C arg3
+  * rsi  arg1
+- * rdx  arg2	
++ * rdx  arg2
+  * r10  arg3 	(--> moved to rcx for C)
+  * r8   arg4
+  * r9   arg5
+  * r11  eflags for syscall/sysret, temporary for C
+- * r12-r15,rbp,rbx saved by C code, not touched. 		
+- * 
++ * r12-r15,rbp,rbx saved by C code, not touched.
++ *
+  * Interrupts are enabled on entry.
+  * Only called from user space.
+  *
+@@ -343,10 +505,10 @@ END(ret_from_fork)
+  * When user can change the frames always force IRET. That is because
+  * it deals with uncanonical addresses better. SYSRET has trouble
+  * with them due to bugs in both AMD and Intel CPUs.
+- */ 			 		
++ */
+ 
+ ENTRY(system_call)
+-	_frame (RIP-0x10)
++	INTR_FRAME start=2 offset=2*8
+ 	SAVE_ARGS -8,0
+ 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
+ 	GET_THREAD_INFO(%rcx)
+@@ -360,19 +522,19 @@ system_call_fastpath:
+ 	movq %rax,RAX-ARGOFFSET(%rsp)
+ /*
+  * Syscall return path ending with SYSRET (fast path)
+- * Has incomplete stack frame and undefined top of stack. 
+- */		
++ * Has incomplete stack frame and undefined top of stack.
++ */
+ ret_from_sys_call:
+ 	movl $_TIF_ALLWORK_MASK,%edi
+ 	/* edi:	flagmask */
+-sysret_check:		
++sysret_check:
+ 	LOCKDEP_SYS_EXIT
+ 	GET_THREAD_INFO(%rcx)
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%rcx),%edx
+ 	andl %edi,%edx
+-	jnz  sysret_careful 
++	jnz  sysret_careful
+ 	CFI_REMEMBER_STATE
+ 	/*
+ 	 * sysretq will re-enable interrupts:
+@@ -384,7 +546,7 @@ sysret_check:		
+ 
+ 	CFI_RESTORE_STATE
+ 	/* Handle reschedules */
+-	/* edx:	work, edi: workmask */	
++	/* edx:	work, edi: workmask */
+ sysret_careful:
+ 	bt $TIF_NEED_RESCHED,%edx
+ 	jnc sysret_signal
+@@ -397,7 +559,7 @@ sysret_careful:
+ 	CFI_ADJUST_CFA_OFFSET -8
+ 	jmp sysret_check
+ 
+-	/* Handle a signal */ 
++	/* Handle a signal */
+ sysret_signal:
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
+@@ -406,17 +568,20 @@ sysret_signal:
+ 	jc sysret_audit
+ #endif
+ 	/* edx:	work flags (arg3) */
+-	leaq do_notify_resume(%rip),%rax
+ 	leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
+ 	xorl %esi,%esi # oldset -> arg2
+-	call ptregscall_common
++	SAVE_REST
++	FIXUP_TOP_OF_STACK %r11
++	call do_notify_resume
++	RESTORE_TOP_OF_STACK %r11
++	RESTORE_REST
+ 	movl $_TIF_WORK_MASK,%edi
+ 	/* Use IRET because user could have changed frame. This
+ 	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp int_with_check
+-	
++
+ badsys:
+ 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+ 	jmp ret_from_sys_call
+@@ -455,7 +620,7 @@ sysret_audit:
+ #endif	/* CONFIG_AUDITSYSCALL */
+ 
+ 	/* Do syscall tracing */
+-tracesys:			 
++tracesys:
+ #ifdef CONFIG_AUDITSYSCALL
+ 	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+ 	jz auditsys
+@@ -478,8 +643,8 @@ tracesys:			 
+ 	call *sys_call_table(,%rax,8)
+ 	movq %rax,RAX-ARGOFFSET(%rsp)
+ 	/* Use IRET because user could have changed frame */
+-		
+-/* 
++
++/*
+  * Syscall return path ending with IRET.
+  * Has correct top of stack, but partial stack frame.
+  */
+@@ -527,18 +692,18 @@ int_very_careful:
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	SAVE_REST
+-	/* Check for syscall exit trace */	
++	/* Check for syscall exit trace */
+ 	testl $_TIF_WORK_SYSCALL_EXIT,%edx
+ 	jz int_signal
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET 8
+-	leaq 8(%rsp),%rdi	# &ptregs -> arg1	
++	leaq 8(%rsp),%rdi	# &ptregs -> arg1
+ 	call syscall_trace_leave
+ 	popq %rdi
+ 	CFI_ADJUST_CFA_OFFSET -8
+ 	andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
+ 	jmp int_restore_rest
+-	
++
+ int_signal:
+ 	testl $_TIF_DO_NOTIFY_MASK,%edx
+ 	jz 1f
+@@ -553,22 +718,24 @@ int_restore_rest:
+ 	jmp int_with_check
+ 	CFI_ENDPROC
+ END(system_call)
+-		
+-/* 
++
++/*
+  * Certain special system calls that need to save a complete full stack frame.
+- */ 								
+-	
++ */
+ 	.macro PTREGSCALL label,func,arg
+-	.globl \label
+-\label:
+-	leaq	\func(%rip),%rax
+-	leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
+-	jmp	ptregscall_common
++ENTRY(\label)
++	PARTIAL_FRAME 1 8		/* offset 8: return address */
++	subq $REST_SKIP, %rsp
++	CFI_ADJUST_CFA_OFFSET REST_SKIP
++	call save_rest
++	DEFAULT_FRAME 0 8		/* offset 8: return address */
++	leaq 8(%rsp), \arg	/* pt_regs pointer */
++	call \func
++	jmp ptregscall_common
++	CFI_ENDPROC
+ END(\label)
+ 	.endm
+ 
+-	CFI_STARTPROC
+-
+ 	PTREGSCALL stub_clone, sys_clone, %r8
+ 	PTREGSCALL stub_fork, sys_fork, %rdi
+ 	PTREGSCALL stub_vfork, sys_vfork, %rdi
+@@ -576,25 +743,18 @@ END(\label)
+ 	PTREGSCALL stub_iopl, sys_iopl, %rsi
+ 
+ ENTRY(ptregscall_common)
+-	popq %r11
+-	CFI_ADJUST_CFA_OFFSET -8
+-	CFI_REGISTER rip, r11
+-	SAVE_REST
+-	movq %r11, %r15
+-	CFI_REGISTER rip, r15
+-	FIXUP_TOP_OF_STACK %r11
+-	call *%rax
+-	RESTORE_TOP_OF_STACK %r11
+-	movq %r15, %r11
+-	CFI_REGISTER rip, r11
+-	RESTORE_REST
+-	pushq %r11
+-	CFI_ADJUST_CFA_OFFSET 8
+-	CFI_REL_OFFSET rip, 0
+-	ret
++	DEFAULT_FRAME 1 8	/* offset 8: return address */
++	RESTORE_TOP_OF_STACK %r11, 8
++	movq_cfi_restore R15+8, r15
++	movq_cfi_restore R14+8, r14
++	movq_cfi_restore R13+8, r13
++	movq_cfi_restore R12+8, r12
++	movq_cfi_restore RBP+8, rbp
++	movq_cfi_restore RBX+8, rbx
++	ret $REST_SKIP		/* pop extended registers */
+ 	CFI_ENDPROC
+ END(ptregscall_common)
+-	
++
+ ENTRY(stub_execve)
+ 	CFI_STARTPROC
+ 	popq %r11
+@@ -610,11 +770,11 @@ ENTRY(stub_execve)
+ 	jmp int_ret_from_sys_call
+ 	CFI_ENDPROC
+ END(stub_execve)
+-	
++
+ /*
+  * sigreturn is special because it needs to restore all registers on return.
+  * This cannot be done with SYSRET, so use the IRET return path instead.
+- */                
++ */
+ ENTRY(stub_rt_sigreturn)
+ 	CFI_STARTPROC
+ 	addq $8, %rsp
+@@ -629,24 +789,12 @@ ENTRY(stub_rt_sigreturn)
+ 	CFI_ENDPROC
+ END(stub_rt_sigreturn)
+ 
+-/* initial frame state for interrupts (and exceptions without error code) */
+-#define INTR_FRAME _frame (RIP-0x10); \
+-	CFI_REL_OFFSET rcx,0; \
+-	CFI_REL_OFFSET r11,8
+-
+-/* initial frame state for exceptions with error code (and interrupts with
+-   vector already pushed) */
+-#define XCPT_FRAME _frame (RIP-0x18); \
+-	CFI_REL_OFFSET rcx,0; \
+-	CFI_REL_OFFSET r11,8
+-
+-/* 
++/*
+  * Interrupt exit.
+- *
+  */ 
+ 
+ retint_with_reschedule:
+-	CFI_DEFAULT_STACK adj=1
++	PARTIAL_FRAME
+ 	movl $_TIF_WORK_MASK,%edi
+ retint_check:
+ 	LOCKDEP_SYS_EXIT_IRQ
+@@ -675,20 +823,20 @@ retint_careful:
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET	8
+ 	call  schedule
+-	popq %rdi		
++	popq %rdi
+ 	CFI_ADJUST_CFA_OFFSET	-8
+ 	GET_THREAD_INFO(%rcx)
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp retint_check
+-	
++
+ retint_signal:
+ 	testl $_TIF_DO_NOTIFY_MASK,%edx
+ 	jz    retint_restore_args
+ 	TRACE_IRQS_ON
+ 	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	SAVE_REST
+-	movq $-1,ORIG_RAX(%rsp) 			
++	movq $-1,ORIG_RAX(%rsp)
+ 	xorl %esi,%esi		# oldset
+ 	movq %rsp,%rdi		# &pt_regs
+ 	call do_notify_resume
+@@ -710,324 +858,132 @@ ENTRY(retint_kernel)
+ 	jnc  retint_restore_args
+ 	call preempt_schedule_irq
+ 	jmp retint_kernel       /* check again */
+-#endif	
++#endif
+ 
+ 	CFI_ENDPROC
+ END(retint_check)
+-	
++
+ #ifndef CONFIG_XEN
+ /*
+  * APIC interrupts.
+- */		
+-	.macro apicinterrupt num,func
++ */
++.macro apicinterrupt num sym do_sym
++ENTRY(\sym)
+ 	INTR_FRAME
+ 	pushq $~(\num)
+ 	CFI_ADJUST_CFA_OFFSET 8
+-	interrupt \func
++	interrupt \do_sym
+ 	jmp error_entry
+ 	CFI_ENDPROC
+-	.endm
++END(\sym)
++.endm
+ 
+-ENTRY(thermal_interrupt)
+-	apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
+-END(thermal_interrupt)
+-
+-ENTRY(threshold_interrupt)
+-	apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
+-END(threshold_interrupt)
+-
+-#ifdef CONFIG_SMP	
+-ENTRY(reschedule_interrupt)
+-	apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
+-END(reschedule_interrupt)
+-
+-	.macro INVALIDATE_ENTRY num
+-ENTRY(invalidate_interrupt\num)
+-	apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt	
+-END(invalidate_interrupt\num)
+-	.endm
++#ifdef CONFIG_SMP
++apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
++	irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
++#endif
++
++apicinterrupt UV_BAU_MESSAGE \
++	uv_bau_message_intr1 uv_bau_message_interrupt
++apicinterrupt LOCAL_TIMER_VECTOR \
++	apic_timer_interrupt smp_apic_timer_interrupt
++
++#ifdef CONFIG_SMP
++apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
++	invalidate_interrupt0 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+1 \
++	invalidate_interrupt1 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+2 \
++	invalidate_interrupt2 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+3 \
++	invalidate_interrupt3 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+4 \
++	invalidate_interrupt4 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+5 \
++	invalidate_interrupt5 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+6 \
++	invalidate_interrupt6 smp_invalidate_interrupt
++apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
++	invalidate_interrupt7 smp_invalidate_interrupt
++#endif
+ 
+-	INVALIDATE_ENTRY 0
+-	INVALIDATE_ENTRY 1
+-	INVALIDATE_ENTRY 2
+-	INVALIDATE_ENTRY 3
+-	INVALIDATE_ENTRY 4
+-	INVALIDATE_ENTRY 5
+-	INVALIDATE_ENTRY 6
+-	INVALIDATE_ENTRY 7
+-
+-ENTRY(call_function_interrupt)
+-	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
+-END(call_function_interrupt)
+-ENTRY(call_function_single_interrupt)
+-	apicinterrupt CALL_FUNCTION_SINGLE_VECTOR,smp_call_function_single_interrupt
+-END(call_function_single_interrupt)
+-ENTRY(irq_move_cleanup_interrupt)
+-	apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
+-END(irq_move_cleanup_interrupt)
++apicinterrupt THRESHOLD_APIC_VECTOR \
++	threshold_interrupt mce_threshold_interrupt
++apicinterrupt THERMAL_APIC_VECTOR \
++	thermal_interrupt smp_thermal_interrupt
++
++#ifdef CONFIG_SMP
++apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
++	call_function_single_interrupt smp_call_function_single_interrupt
++apicinterrupt CALL_FUNCTION_VECTOR \
++	call_function_interrupt smp_call_function_interrupt
++apicinterrupt RESCHEDULE_VECTOR \
++	reschedule_interrupt smp_reschedule_interrupt
+ #endif
+ 
+-ENTRY(apic_timer_interrupt)
+-	apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
+-END(apic_timer_interrupt)
+-
+-ENTRY(uv_bau_message_intr1)
+-	apicinterrupt 220,uv_bau_message_interrupt
+-END(uv_bau_message_intr1)
+-
+-ENTRY(error_interrupt)
+-	apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
+-END(error_interrupt)
+-
+-ENTRY(spurious_interrupt)
+-	apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
+-END(spurious_interrupt)
++apicinterrupt ERROR_APIC_VECTOR \
++	error_interrupt smp_error_interrupt
++apicinterrupt SPURIOUS_APIC_VECTOR \
++	spurious_interrupt smp_spurious_interrupt
+ #endif /* !CONFIG_XEN */
+-				
++
+ /*
+  * Exception entry points.
+- */ 		
+-	.macro zeroentry sym
++ */
++.macro zeroentry sym do_sym
++ENTRY(\sym)
+ 	INTR_FRAME
+         movq (%rsp),%rcx
+ 	CFI_RESTORE rcx
+         movq 8(%rsp),%r11
+ 	CFI_RESTORE r11
+-        addq $0x10,%rsp /* skip rcx and r11 */
+-	CFI_ADJUST_CFA_OFFSET -0x10
+-	pushq $0	/* push error code/oldrax */ 
+-	CFI_ADJUST_CFA_OFFSET 8
+-	pushq %rax	/* push real oldrax to the rdi slot */ 
+-	CFI_ADJUST_CFA_OFFSET 8
+-	CFI_REL_OFFSET rax,0
+-	leaq  \sym(%rip),%rax
+-	jmp error_entry
++	movq $-1,8(%rsp)	/* ORIG_RAX: no syscall to restart */
++	subq $(15-1)*8,%rsp
++	CFI_ADJUST_CFA_OFFSET (15-1)*8
++	call error_entry
++	DEFAULT_FRAME 0
++	movq %rsp,%rdi		/* pt_regs pointer */
++	xorl %esi,%esi		/* no error code */
++	call \do_sym
++	jmp error_exit		/* %ebx: no swapgs flag */
+ 	CFI_ENDPROC
+-	.endm	
++END(\sym)
++.endm
++
++.macro paranoidzeroentry sym do_sym
++	zeroentry \sym \do_sym
++.endm
++
++.macro paranoidzeroentry_ist sym do_sym ist
++	zeroentry \sym \do_sym
++.endm
+ 
+-	.macro errorentry sym
++.macro errorentry sym do_sym
++ENTRY(\sym)
+ 	XCPT_FRAME
+         movq (%rsp),%rcx
+ 	CFI_RESTORE rcx
+         movq 8(%rsp),%r11
+ 	CFI_RESTORE r11
+-        addq $0x10,%rsp /* rsp points to the error code */
+-	CFI_ADJUST_CFA_OFFSET -0x10
+-	pushq %rax
+-	CFI_ADJUST_CFA_OFFSET 8
+-	CFI_REL_OFFSET rax,0
+-	leaq  \sym(%rip),%rax
+-	jmp error_entry
++	subq $(15-2)*8,%rsp
++	CFI_ADJUST_CFA_OFFSET (15-2)*8
++	call error_entry
++	DEFAULT_FRAME 0
++	movq %rsp,%rdi			/* pt_regs pointer */
++	movq ORIG_RAX(%rsp),%rsi	/* get error code */
++	movq $-1,ORIG_RAX(%rsp)		/* no syscall to restart */
++	call \do_sym
++	jmp error_exit			/* %ebx: no swapgs flag */
+ 	CFI_ENDPROC
+-	.endm
++END(\sym)
++.endm
+ 
+-#if 0 /* not XEN */
+ 	/* error code is on the stack already */
+-	/* handle NMI like exceptions that can happen everywhere */
+-	.macro paranoidentry sym, ist=0, irqtrace=1
+-        movq (%rsp),%rcx
+-        movq 8(%rsp),%r11
+-        addq $0x10,%rsp /* skip rcx and r11 */        
+-	SAVE_ALL
+-	cld
+-#if 0 /* not XEN */
+-	movl $1,%ebx
+-	movl  $MSR_GS_BASE,%ecx
+-	rdmsr
+-	testl %edx,%edx
+-	js    1f
+-	SWAPGS
+-	xorl  %ebx,%ebx
+-1:
+-#endif
+-	.if \ist
+-	movq	%gs:pda_data_offset, %rbp
+-	.endif
+-	.if \irqtrace
+-	TRACE_IRQS_OFF
+-	.endif
+-	movq %rsp,%rdi
+-	movq ORIG_RAX(%rsp),%rsi
+-	movq $-1,ORIG_RAX(%rsp)
+-	.if \ist
+-	subq	$EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+-	.endif
+-	call \sym
+-	.if \ist
+-	addq	$EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+-	.endif
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	.if \irqtrace
+-	TRACE_IRQS_OFF
+-	.endif
+-	.endm
+-
+-	/*
+- 	 * "Paranoid" exit path from exception stack.
+-  	 * Paranoid because this is used by NMIs and cannot take
+-	 * any kernel state for granted.
+-	 * We don't do kernel preemption checks here, because only
+-	 * NMI should be common and it does not enable IRQs and
+-	 * cannot get reschedule ticks.
+-	 *
+-	 * "trace" is 0 for the NMI handler only, because irq-tracing
+-	 * is fundamentally NMI-unsafe. (we cannot change the soft and
+-	 * hard flags at once, atomically)
+-	 */
+-	.macro paranoidexit trace=1
+-	/* ebx:	no swapgs flag */
+-paranoid_exit\trace:
+-	testl %ebx,%ebx				/* swapgs needed? */
+-	jnz paranoid_restore\trace
+-	testl $3,CS(%rsp)
+-	jnz   paranoid_userspace\trace
+-paranoid_swapgs\trace:
+-	.if \trace
+-	TRACE_IRQS_IRETQ 0
+-	.endif
+-	SWAPGS_UNSAFE_STACK
+-paranoid_restore\trace:
+-	RESTORE_ALL 8
+-	jmp irq_return
+-paranoid_userspace\trace:
+-	GET_THREAD_INFO(%rcx)
+-	movl TI_flags(%rcx),%ebx
+-	andl $_TIF_WORK_MASK,%ebx
+-	jz paranoid_swapgs\trace
+-	movq %rsp,%rdi			/* &pt_regs */
+-	call sync_regs
+-	movq %rax,%rsp			/* switch stack for scheduling */
+-	testl $_TIF_NEED_RESCHED,%ebx
+-	jnz paranoid_schedule\trace
+-	movl %ebx,%edx			/* arg3: thread flags */
+-	.if \trace
+-	TRACE_IRQS_ON
+-	.endif
+-	ENABLE_INTERRUPTS(CLBR_NONE)
+-	xorl %esi,%esi 			/* arg2: oldset */
+-	movq %rsp,%rdi 			/* arg1: &pt_regs */
+-	call do_notify_resume
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	.if \trace
+-	TRACE_IRQS_OFF
+-	.endif
+-	jmp paranoid_userspace\trace
+-paranoid_schedule\trace:
+-	.if \trace
+-	TRACE_IRQS_ON
+-	.endif
+-	ENABLE_INTERRUPTS(CLBR_ANY)
+-	call schedule
+-	DISABLE_INTERRUPTS(CLBR_ANY)
+-	.if \trace
+-	TRACE_IRQS_OFF
+-	.endif
+-	jmp paranoid_userspace\trace
+-	CFI_ENDPROC
+-	.endm
+-#endif
++.macro paranoiderrorentry sym do_sym
++	errorentry \sym \do_sym
++.endm
+ 
+ /*
+- * Exception entry point. This expects an error code/orig_rax on the stack
+- * and the exception handler in %rax.	
+- */ 		  				
+-KPROBE_ENTRY(error_entry)
+-	_frame RDI
+-	CFI_REL_OFFSET rax,0
+-	/* rdi slot contains rax, oldrax contains error code */
+-	cld	
+-	subq  $14*8,%rsp
+-	CFI_ADJUST_CFA_OFFSET	(14*8)
+-	movq %rsi,13*8(%rsp)
+-	CFI_REL_OFFSET	rsi,RSI
+-	movq 14*8(%rsp),%rsi	/* load rax from rdi slot */
+-	CFI_REGISTER	rax,rsi
+-	movq %rdx,12*8(%rsp)
+-	CFI_REL_OFFSET	rdx,RDX
+-	movq %rcx,11*8(%rsp)
+-	CFI_REL_OFFSET	rcx,RCX
+-	movq %rsi,10*8(%rsp)	/* store rax */ 
+-	CFI_REL_OFFSET	rax,RAX
+-	movq %r8, 9*8(%rsp)
+-	CFI_REL_OFFSET	r8,R8
+-	movq %r9, 8*8(%rsp)
+-	CFI_REL_OFFSET	r9,R9
+-	movq %r10,7*8(%rsp)
+-	CFI_REL_OFFSET	r10,R10
+-	movq %r11,6*8(%rsp)
+-	CFI_REL_OFFSET	r11,R11
+-	movq %rbx,5*8(%rsp) 
+-	CFI_REL_OFFSET	rbx,RBX
+-	movq %rbp,4*8(%rsp) 
+-	CFI_REL_OFFSET	rbp,RBP
+-	movq %r12,3*8(%rsp) 
+-	CFI_REL_OFFSET	r12,R12
+-	movq %r13,2*8(%rsp) 
+-	CFI_REL_OFFSET	r13,R13
+-	movq %r14,1*8(%rsp) 
+-	CFI_REL_OFFSET	r14,R14
+-	movq %r15,(%rsp) 
+-	CFI_REL_OFFSET	r15,R15
+-#if 0        
+-	cmpl $__KERNEL_CS,CS(%rsp)
+-	CFI_REMEMBER_STATE
+-	je  error_kernelspace
+-#endif        
+-error_call_handler:
+-	movq %rdi, RDI(%rsp)            
+-	CFI_REL_OFFSET	rdi,RDI
+-	movq %rsp,%rdi
+-	movq ORIG_RAX(%rsp),%rsi	# get error code 
+-	movq $-1,ORIG_RAX(%rsp)
+-	call *%rax
+-error_exit:
+-	RESTORE_REST
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	TRACE_IRQS_OFF
+-	GET_THREAD_INFO(%rcx)	
+-	testb $3,CS-ARGOFFSET(%rsp)
+-	jz retint_kernel
+-	LOCKDEP_SYS_EXIT_IRQ
+-	movl  TI_flags(%rcx),%edx
+-	movl  $_TIF_WORK_MASK,%edi	
+-	andl  %edi,%edx
+-	jnz   retint_careful
+-	jmp   retint_restore_args
+-
+-#if 0
+-         /*
+-         * We need to re-write the logic here because we don't do iretq to 
+-         * to return to user mode. It's still possible that we get trap/fault
+-         * in the kernel (when accessing buffers pointed to by system calls, 
+-         * for example).
+-         *
+-         */           
+-	CFI_RESTORE_STATE
+-error_kernelspace:
+-	incl %ebx
+-       /* There are two places in the kernel that can potentially fault with
+-          usergs. Handle them here. The exception handlers after
+-	   iret run with kernel gs again, so don't set the user space flag.
+-	   B stepping K8s sometimes report an truncated RIP for IRET 
+-	   exceptions returning to compat mode. Check for these here too. */
+-	leaq irq_return(%rip),%rcx
+-	cmpq %rcx,RIP(%rsp)
+-	je   error_swapgs
+-	movl %ecx,%ecx	/* zero extend */
+-	cmpq %rcx,RIP(%rsp)
+-	je   error_swapgs
+-	cmpq $gs_change,RIP(%rsp)
+-        je   error_swapgs
+-	jmp  error_sti
+-#endif
+-	CFI_ENDPROC
+-KPROBE_END(error_entry)
+-	
+-ENTRY(hypervisor_callback)
+-	zeroentry do_hypervisor_callback
+-END(hypervisor_callback)
+-        
+-/*
+  * Copied from arch/xen/i386/kernel/entry.S
+  */               
+ # A note on the "critical region" in our callback handler.
+@@ -1047,7 +1003,7 @@ ENTRY(do_hypervisor_callback)   # do_hyp
+ # see the correct pointer to the pt_regs
+ 	movq %rdi, %rsp            # we don't return, adjust the stack frame
+ 	CFI_ENDPROC
+-	CFI_DEFAULT_STACK
++	DEFAULT_FRAME
+ 11:	incl %gs:pda_irqcount
+ 	movq %rsp,%rbp
+ 	CFI_DEF_CFA_REGISTER rbp
+@@ -1063,7 +1019,7 @@ END(do_hypervisor_callback)
+ 
+         ALIGN
+ restore_all_enable_events:  
+-	CFI_DEFAULT_STACK adj=1
++	PARTIAL_FRAME
+ 	TRACE_IRQS_ON
+ 	__ENABLE_INTERRUPTS
+ 
+@@ -1099,9 +1055,7 @@ ecrit:  /**** END OF CRITICAL REGION ***
+ # We distinguish between categories by comparing each saved segment register
+ # with its current contents: any discrepancy means we in category 1.
+ ENTRY(failsafe_callback)
+-	_frame (RIP-0x30)
+-	CFI_REL_OFFSET rcx, 0
+-	CFI_REL_OFFSET r11, 8
++	INTR_FRAME offset=4*8
+ 	movw %ds,%cx
+ 	cmpw %cx,0x10(%rsp)
+ 	CFI_REMEMBER_STATE
+@@ -1137,20 +1091,19 @@ ENTRY(failsafe_callback)
+ 	SAVE_ALL
+ 	jmp error_exit
+ 	CFI_ENDPROC
+-#if 0	      
+-        .section __ex_table,"a"
+-        .align 8
+-        .quad gs_change,bad_gs
+-        .previous
+-        .section .fixup,"ax"
+-	/* running with kernelgs */
+-bad_gs: 
+-/*	swapgs		*/	/* switch back to user gs */
+-	xorl %eax,%eax
+-        movl %eax,%gs
+-        jmp  2b
+-        .previous       
+-#endif
++
++zeroentry divide_error do_divide_error
++zeroentry overflow do_overflow
++zeroentry bounds do_bounds
++zeroentry invalid_op do_invalid_op
++zeroentry device_not_available do_device_not_available
++zeroentry hypervisor_callback do_hypervisor_callback
++zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun
++errorentry invalid_TSS do_invalid_TSS
++errorentry segment_not_present do_segment_not_present
++zeroentry coprocessor_error do_coprocessor_error
++errorentry alignment_check do_alignment_check
++zeroentry simd_coprocessor_error do_simd_coprocessor_error
+ 	
+ /*
+  * Create a kernel thread.
+@@ -1174,7 +1127,7 @@ ENTRY(kernel_thread)
+ 
+ 	xorl %r8d,%r8d
+ 	xorl %r9d,%r9d
+-	
++
+ 	# clone now
+ 	call do_fork
+ 	movq %rax,RAX(%rsp)
+@@ -1185,15 +1138,15 @@ ENTRY(kernel_thread)
+ 	 * so internally to the x86_64 port you can rely on kernel_thread()
+ 	 * not to reschedule the child before returning, this avoids the need
+ 	 * of hacks for example to fork off the per-CPU idle tasks.
+-         * [Hopefully no generic code relies on the reschedule -AK]	
++	 * [Hopefully no generic code relies on the reschedule -AK]
+ 	 */
+ 	RESTORE_ALL
+ 	UNFAKE_STACK_FRAME
+ 	ret
+ 	CFI_ENDPROC
+-ENDPROC(kernel_thread)
+-	
+-child_rip:
++END(kernel_thread)
++
++ENTRY(child_rip)
+ 	pushq $0		# fake return address
+ 	CFI_STARTPROC
+ 	/*
+@@ -1206,8 +1159,9 @@ child_rip:
+ 	# exit
+ 	mov %eax, %edi
+ 	call do_exit
++	ud2			# padding for call trace
+ 	CFI_ENDPROC
+-ENDPROC(child_rip)
++END(child_rip)
+ 
+ /*
+  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
+@@ -1227,10 +1181,10 @@ ENDPROC(child_rip)
+ ENTRY(kernel_execve)
+ 	CFI_STARTPROC
+ 	FAKE_STACK_FRAME $0
+-	SAVE_ALL	
++	SAVE_ALL
+ 	movq %rsp,%rcx
+ 	call sys_execve
+-	movq %rax, RAX(%rsp)	
++	movq %rax, RAX(%rsp)
+ 	RESTORE_REST
+ 	testq %rax,%rax
+ 	jne 1f
+@@ -1239,132 +1193,7 @@ ENTRY(kernel_execve)
+ 	UNFAKE_STACK_FRAME
+ 	ret
+ 	CFI_ENDPROC
+-ENDPROC(kernel_execve)
+-
+-KPROBE_ENTRY(page_fault)
+-	errorentry do_page_fault
+-KPROBE_END(page_fault)
+-
+-ENTRY(coprocessor_error)
+-	zeroentry do_coprocessor_error
+-END(coprocessor_error)
+-
+-ENTRY(simd_coprocessor_error)
+-	zeroentry do_simd_coprocessor_error	
+-END(simd_coprocessor_error)
+-
+-ENTRY(device_not_available)
+-	zeroentry do_device_not_available
+-END(device_not_available)
+-
+-	/* runs on exception stack */
+-KPROBE_ENTRY(debug)
+-/* 	INTR_FRAME
+-	PARAVIRT_ADJUST_EXCEPTION_FRAME
+-	pushq $0
+-	CFI_ADJUST_CFA_OFFSET 8	*/
+-	zeroentry do_debug
+-/*	paranoidexit
+-	CFI_ENDPROC */
+-KPROBE_END(debug)
+-
+-KPROBE_ENTRY(nmi)
+-	zeroentry do_nmi_callback
+-KPROBE_END(nmi)
+-do_nmi_callback:
+-	CFI_STARTPROC
+-	addq $8, %rsp
+-	CFI_ENDPROC
+-	CFI_DEFAULT_STACK
+-	call do_nmi
+-	orl  $NMI_MASK,EFLAGS(%rsp)
+-	RESTORE_REST
+-	DISABLE_INTERRUPTS(CLBR_NONE)
+-	TRACE_IRQS_OFF
+-	GET_THREAD_INFO(%rcx)
+-	jmp  retint_restore_args
+-	CFI_ENDPROC
+-END(do_nmi_callback)
+-
+-KPROBE_ENTRY(int3)
+-/* 	INTR_FRAME
+-	PARAVIRT_ADJUST_EXCEPTION_FRAME
+- 	pushq $0
+- 	CFI_ADJUST_CFA_OFFSET 8 */
+- 	zeroentry do_int3
+-/* 	jmp paranoid_exit1
+- 	CFI_ENDPROC */
+-KPROBE_END(int3)
+-
+-ENTRY(overflow)
+-	zeroentry do_overflow
+-END(overflow)
+-
+-ENTRY(bounds)
+-	zeroentry do_bounds
+-END(bounds)
+-
+-ENTRY(invalid_op)
+-	zeroentry do_invalid_op	
+-END(invalid_op)
+-
+-ENTRY(coprocessor_segment_overrun)
+-	zeroentry do_coprocessor_segment_overrun
+-END(coprocessor_segment_overrun)
+-
+-#if 0
+-	/* runs on exception stack */
+-ENTRY(double_fault)
+-	XCPT_FRAME
+-	PARAVIRT_ADJUST_EXCEPTION_FRAME
+-	paranoidentry do_double_fault
+-	jmp paranoid_exit1
+-	CFI_ENDPROC
+-END(double_fault)
+-#endif
+-
+-ENTRY(invalid_TSS)
+-	errorentry do_invalid_TSS
+-END(invalid_TSS)
+-
+-ENTRY(segment_not_present)
+-	errorentry do_segment_not_present
+-END(segment_not_present)
+-
+-	/* runs on exception stack */
+-ENTRY(stack_segment)
+-/*	XCPT_FRAME
+-	PARAVIRT_ADJUST_EXCEPTION_FRAME
+-	paranoidentry do_stack_segment */
+-	errorentry do_stack_segment
+-/*	jmp paranoid_exit1
+-	CFI_ENDPROC */
+-END(stack_segment)
+-
+-KPROBE_ENTRY(general_protection)
+-	errorentry do_general_protection
+-KPROBE_END(general_protection)
+-
+-ENTRY(alignment_check)
+-	errorentry do_alignment_check
+-END(alignment_check)
+-
+-ENTRY(divide_error)
+-	zeroentry do_divide_error
+-END(divide_error)
+-
+-#ifndef CONFIG_XEN
+-ENTRY(spurious_interrupt_bug)
+-	zeroentry do_spurious_interrupt_bug
+-END(spurious_interrupt_bug)
+-#endif
+-
+-#ifdef CONFIG_X86_MCE
+-	/* runs on exception stack */
+-KPROBE_ENTRY(machine_check)
+-	zeroentry do_machine_check
+-END(machine_check)
+-#endif
++END(kernel_execve)
+ 
+ /* Call softirq on interrupt stack. Interrupts are off. */
+ ENTRY(call_softirq)
+@@ -1384,24 +1213,191 @@ ENTRY(call_softirq)
+ 	decl %gs:pda_irqcount
+ 	ret
+ 	CFI_ENDPROC
+-ENDPROC(call_softirq)
++END(call_softirq)
++
++/*
++ * Some functions should be protected against kprobes
++ */
++	.pushsection .kprobes.text, "ax"
++
++paranoidzeroentry_ist debug do_debug DEBUG_STACK
++zeroentry nmi do_nmi_callback
++paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
++paranoiderrorentry stack_segment do_stack_segment
++errorentry general_protection do_general_protection
++errorentry page_fault do_page_fault
++#ifdef CONFIG_X86_MCE
++paranoidzeroentry machine_check do_machine_check
++#endif
++
++#ifndef CONFIG_XEN
++	/*
++	 * "Paranoid" exit path from exception stack.
++	 * Paranoid because this is used by NMIs and cannot take
++	 * any kernel state for granted.
++	 * We don't do kernel preemption checks here, because only
++	 * NMI should be common and it does not enable IRQs and
++	 * cannot get reschedule ticks.
++	 *
++	 * "trace" is 0 for the NMI handler only, because irq-tracing
++	 * is fundamentally NMI-unsafe. (we cannot change the soft and
++	 * hard flags at once, atomically)
++	 */
++
++	/* ebx:	no swapgs flag */
++ENTRY(paranoid_exit)
++	INTR_FRAME
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	testl %ebx,%ebx				/* swapgs needed? */
++	jnz paranoid_restore
++	testl $3,CS(%rsp)
++	jnz   paranoid_userspace
++paranoid_swapgs:
++	TRACE_IRQS_IRETQ 0
++	SWAPGS_UNSAFE_STACK
++paranoid_restore:
++	RESTORE_ALL 8
++	jmp irq_return
++paranoid_userspace:
++	GET_THREAD_INFO(%rcx)
++	movl TI_flags(%rcx),%ebx
++	andl $_TIF_WORK_MASK,%ebx
++	jz paranoid_swapgs
++	movq %rsp,%rdi			/* &pt_regs */
++	call sync_regs
++	movq %rax,%rsp			/* switch stack for scheduling */
++	testl $_TIF_NEED_RESCHED,%ebx
++	jnz paranoid_schedule
++	movl %ebx,%edx			/* arg3: thread flags */
++	TRACE_IRQS_ON
++	ENABLE_INTERRUPTS(CLBR_NONE)
++	xorl %esi,%esi 			/* arg2: oldset */
++	movq %rsp,%rdi 			/* arg1: &pt_regs */
++	call do_notify_resume
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	jmp paranoid_userspace
++paranoid_schedule:
++	TRACE_IRQS_ON
++	ENABLE_INTERRUPTS(CLBR_ANY)
++	call schedule
++	DISABLE_INTERRUPTS(CLBR_ANY)
++	TRACE_IRQS_OFF
++	jmp paranoid_userspace
++	CFI_ENDPROC
++END(paranoid_exit)
++#endif
++
++/*
++ * Exception entry point. This expects an error code/orig_rax on the stack.
++ * returns in "no swapgs flag" in %ebx.
++ */
++ENTRY(error_entry)
++	XCPT_FRAME 2
++	CFI_ADJUST_CFA_OFFSET 15*8
++	/* oldrax contains error code */
++	cld
++	movq_cfi rdi, RDI+8
++	movq_cfi rsi, RSI+8
++	movq_cfi rdx, RDX+8
++	movq_cfi rcx, RCX+8
++	movq_cfi rax, RAX+8
++	movq_cfi  r8,  R8+8
++	movq_cfi  r9,  R9+8
++	movq_cfi r10, R10+8
++	movq_cfi r11, R11+8
++	movq_cfi rbx, RBX+8
++	movq_cfi rbp, RBP+8
++	movq_cfi r12, R12+8
++	movq_cfi r13, R13+8
++	movq_cfi r14, R14+8
++	movq_cfi r15, R15+8
++#ifndef CONFIG_XEN
++	xorl %ebx,%ebx
++	testl $3,CS+8(%rsp)
++	je error_kernelspace
++error_swapgs:
++	SWAPGS
++error_sti:
++#endif
++	TRACE_IRQS_OFF
++	ret
++	CFI_ENDPROC
++
++#ifndef CONFIG_XEN
++/*
++ * There are two places in the kernel that can potentially fault with
++ * usergs. Handle them here. The exception handlers after iret run with
++ * kernel gs again, so don't set the user space flag. B stepping K8s
++ * sometimes report an truncated RIP for IRET exceptions returning to
++ * compat mode. Check for these here too.
++ */
++error_kernelspace:
++	incl %ebx
++	leaq irq_return(%rip),%rcx
++	cmpq %rcx,RIP+8(%rsp)
++	je error_swapgs
++	movl %ecx,%ecx	/* zero extend */
++	cmpq %rcx,RIP+8(%rsp)
++	je error_swapgs
++	cmpq $gs_change,RIP+8(%rsp)
++	je error_swapgs
++	jmp error_sti
++#endif
++END(error_entry)
++
++
++ENTRY(error_exit)
++	DEFAULT_FRAME
++	RESTORE_REST
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	GET_THREAD_INFO(%rcx)
++	testb $3,CS-ARGOFFSET(%rsp)
++	jz retint_kernel
++	LOCKDEP_SYS_EXIT_IRQ
++	movl TI_flags(%rcx),%edx
++	movl $_TIF_WORK_MASK,%edi
++	andl %edi,%edx
++	jnz retint_careful
++	jmp retint_restore_args
++	CFI_ENDPROC
++END(error_exit)
++
++
++do_nmi_callback:
++	CFI_STARTPROC
++	addq $8, %rsp
++	CFI_ENDPROC
++	DEFAULT_FRAME
++	call do_nmi
++	orl  $NMI_MASK,EFLAGS(%rsp)
++	RESTORE_REST
++	DISABLE_INTERRUPTS(CLBR_NONE)
++	TRACE_IRQS_OFF
++	GET_THREAD_INFO(%rcx)
++	jmp  retint_restore_args
++	CFI_ENDPROC
++END(do_nmi_callback)
++
+ 
+ #ifndef CONFIG_IA32_EMULATION
+-KPROBE_ENTRY(ignore_sysret)
+-	CFI_STARTPROC	simple
+-	CFI_SIGNAL_FRAME
+-	CFI_DEF_CFA	rsp,SS+8-RIP+16
+-/*	CFI_REL_OFFSET	ss,SS-RIP+16 */
+-	CFI_REL_OFFSET	rsp,RSP-RIP+16
+-/*	CFI_REL_OFFSET	rflags,EFLAGS-RIP+16 */
+-/*	CFI_REL_OFFSET	cs,CS-RIP+16 */
+-	CFI_REL_OFFSET	rip,RIP-RIP+16
++ENTRY(ignore_sysret)
++	INTR_FRAME
+ 	popq %rcx
+ 	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE rcx
+ 	popq %r11
+ 	CFI_ADJUST_CFA_OFFSET -8
++	CFI_RESTORE r11
+ 	mov $-ENOSYS,%eax
+ 	HYPERVISOR_IRET 0
+ 	CFI_ENDPROC
+-ENDPROC(ignore_sysret)
++END(ignore_sysret)
+ #endif
++
++/*
++ * End of kprobes section
++ */
++	.popsection
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/head-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/head-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -36,7 +36,6 @@ void __init reserve_ebda_region(void)
+ 
+ 	/* start of EBDA area */
+ 	ebda_addr = get_bios_ebda();
+-	printk(KERN_INFO "BIOS EBDA/lowmem at: %08x/%08x\n", ebda_addr, lowmem);
+ 
+ 	/* Fixup: bios puts an EBDA in the top 64K segment */
+ 	/* of conventional memory, but does not adjust lowmem. */
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/head32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/head32-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -12,9 +12,12 @@
+ #include <asm/sections.h>
+ #include <asm/e820.h>
+ #include <asm/bios_ebda.h>
++#include <asm/trampoline.h>
+ 
+ void __init i386_start_kernel(void)
+ {
++	reserve_trampoline_memory();
++
+ 	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+ 
+ #ifndef CONFIG_XEN
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -31,9 +31,10 @@
+ #include <asm/kdebug.h>
+ #include <asm/e820.h>
+ #include <asm/bios_ebda.h>
++#include <asm/trampoline.h>
+ 
+ /* boot cpu pda */
+-static struct x8664_pda _boot_cpu_pda __read_mostly;
++static struct x8664_pda _boot_cpu_pda;
+ 
+ #ifdef CONFIG_SMP
+ /*
+@@ -163,6 +164,8 @@ void __init x86_64_start_reservations(ch
+ {
+ 	copy_bootdata(__va(real_mode_data));
+ 
++	reserve_trampoline_memory();
++
+ 	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
+ 
+ 	reserve_early(round_up(__pa_symbol(&_end), PAGE_SIZE),
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -122,102 +122,276 @@ static int __init parse_noapic(char *str
+ }
+ early_param("noapic", parse_noapic);
+ 
++#ifndef CONFIG_XEN
+ struct irq_pin_list;
++
++/*
++ * This is performance-critical, we want to do it O(1)
++ *
++ * the indexing order of this array favors 1:1 mappings
++ * between pins and IRQs.
++ */
++
++struct irq_pin_list {
++	int apic, pin;
++	struct irq_pin_list *next;
++};
++
++static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
++{
++	struct irq_pin_list *pin;
++	int node;
++
++	node = cpu_to_node(cpu);
++
++	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
++
++	return pin;
++}
++
+ struct irq_cfg {
+-#ifndef CONFIG_XEN
+-	unsigned int irq;
+ 	struct irq_pin_list *irq_2_pin;
+-	cpumask_t domain;
+-	cpumask_t old_domain;
++	cpumask_var_t domain;
++	cpumask_var_t old_domain;
+ 	unsigned move_cleanup_count;
+-#endif
+ 	u8 vector;
+-#ifndef CONFIG_XEN
+ 	u8 move_in_progress : 1;
++#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
++	u8 move_desc_pending : 1;
+ #endif
+ };
+ 
+ /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
++#ifdef CONFIG_SPARSE_IRQ
++static struct irq_cfg irq_cfgx[] = {
++#else
+ static struct irq_cfg irq_cfgx[NR_IRQS] = {
+-	[0]  = { .irq =  0 },
+-	[1]  = { .irq =  1 },
+-	[2]  = { .irq =  2 },
+-	[3]  = { .irq =  3 },
+-	[4]  = { .irq =  4 },
+-	[5]  = { .irq =  5 },
+-	[6]  = { .irq =  6 },
+-	[7]  = { .irq =  7 },
+-	[8]  = { .irq =  8 },
+-	[9]  = { .irq =  9 },
+-	[10] = { .irq = 10 },
+-	[11] = { .irq = 11 },
+-	[12] = { .irq = 12 },
+-	[13] = { .irq = 13 },
+-	[14] = { .irq = 14 },
+-	[15] = { .irq = 15 },
++#endif
++	[0]  = { .vector = IRQ0_VECTOR,  },
++	[1]  = { .vector = IRQ1_VECTOR,  },
++	[2]  = { .vector = IRQ2_VECTOR,  },
++	[3]  = { .vector = IRQ3_VECTOR,  },
++	[4]  = { .vector = IRQ4_VECTOR,  },
++	[5]  = { .vector = IRQ5_VECTOR,  },
++	[6]  = { .vector = IRQ6_VECTOR,  },
++	[7]  = { .vector = IRQ7_VECTOR,  },
++	[8]  = { .vector = IRQ8_VECTOR,  },
++	[9]  = { .vector = IRQ9_VECTOR,  },
++	[10] = { .vector = IRQ10_VECTOR, },
++	[11] = { .vector = IRQ11_VECTOR, },
++	[12] = { .vector = IRQ12_VECTOR, },
++	[13] = { .vector = IRQ13_VECTOR, },
++	[14] = { .vector = IRQ14_VECTOR, },
++	[15] = { .vector = IRQ15_VECTOR, },
+ };
+ 
+-#define for_each_irq_cfg(irq, cfg)		\
+-	for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)
++int __init arch_early_irq_init(void)
++{
++	struct irq_cfg *cfg;
++	struct irq_desc *desc;
++	int count;
++	int i;
++
++	cfg = irq_cfgx;
++	count = ARRAY_SIZE(irq_cfgx);
+ 
++	for (i = 0; i < count; i++) {
++		desc = irq_to_desc(i);
++		desc->chip_data = &cfg[i];
++		alloc_bootmem_cpumask_var(&cfg[i].domain);
++		alloc_bootmem_cpumask_var(&cfg[i].old_domain);
++		if (i < NR_IRQS_LEGACY)
++			cpumask_setall(cfg[i].domain);
++	}
++
++	return 0;
++}
++
++#ifdef CONFIG_SPARSE_IRQ
+ static struct irq_cfg *irq_cfg(unsigned int irq)
+ {
+-	return irq < nr_irqs ? irq_cfgx + irq : NULL;
++	struct irq_cfg *cfg = NULL;
++	struct irq_desc *desc;
++
++	desc = irq_to_desc(irq);
++	if (desc)
++		cfg = desc->chip_data;
++
++	return cfg;
+ }
+ 
+-static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
++static struct irq_cfg *get_one_free_irq_cfg(int cpu)
+ {
+-	return irq_cfg(irq);
++	struct irq_cfg *cfg;
++	int node;
++
++	node = cpu_to_node(cpu);
++
++	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
++	if (cfg) {
++		if (!alloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
++			kfree(cfg);
++			cfg = NULL;
++		} else if (!alloc_cpumask_var_node(&cfg->old_domain,
++							  GFP_ATOMIC, node)) {
++			free_cpumask_var(cfg->domain);
++			kfree(cfg);
++			cfg = NULL;
++		} else {
++			cpumask_clear(cfg->domain);
++			cpumask_clear(cfg->old_domain);
++		}
++	}
++
++	return cfg;
+ }
+ 
+-#ifdef CONFIG_XEN
+-#define irq_2_pin_init()
+-#define add_pin_to_irq(irq, apic, pin)
+-#else
+-/*
+- * Rough estimation of how many shared IRQs there are, can be changed
+- * anytime.
+- */
+-#define MAX_PLUS_SHARED_IRQS NR_IRQS
+-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
++int arch_init_chip_data(struct irq_desc *desc, int cpu)
++{
++	struct irq_cfg *cfg;
+ 
+-/*
+- * This is performance-critical, we want to do it O(1)
+- *
+- * the indexing order of this array favors 1:1 mappings
+- * between pins and IRQs.
+- */
++	cfg = desc->chip_data;
++	if (!cfg) {
++		desc->chip_data = get_one_free_irq_cfg(cpu);
++		if (!desc->chip_data) {
++			printk(KERN_ERR "can not alloc irq_cfg\n");
++			BUG_ON(1);
++		}
++	}
+ 
+-struct irq_pin_list {
+-	int apic, pin;
+-	struct irq_pin_list *next;
+-};
++	return 0;
++}
+ 
+-static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];
+-static struct irq_pin_list *irq_2_pin_ptr;
++#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
+ 
+-static void __init irq_2_pin_init(void)
++static void
++init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int cpu)
+ {
+-	struct irq_pin_list *pin = irq_2_pin_head;
+-	int i;
++	struct irq_pin_list *old_entry, *head, *tail, *entry;
++
++	cfg->irq_2_pin = NULL;
++	old_entry = old_cfg->irq_2_pin;
++	if (!old_entry)
++		return;
++
++	entry = get_one_free_irq_2_pin(cpu);
++	if (!entry)
++		return;
++
++	entry->apic	= old_entry->apic;
++	entry->pin	= old_entry->pin;
++	head		= entry;
++	tail		= entry;
++	old_entry	= old_entry->next;
++	while (old_entry) {
++		entry = get_one_free_irq_2_pin(cpu);
++		if (!entry) {
++			entry = head;
++			while (entry) {
++				head = entry->next;
++				kfree(entry);
++				entry = head;
++			}
++			/* still use the old one */
++			return;
++		}
++		entry->apic	= old_entry->apic;
++		entry->pin	= old_entry->pin;
++		tail->next	= entry;
++		tail		= entry;
++		old_entry	= old_entry->next;
++	}
+ 
+-	for (i = 1; i < PIN_MAP_SIZE; i++)
+-		pin[i-1].next = &pin[i];
++	tail->next = NULL;
++	cfg->irq_2_pin = head;
++}
++
++static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
++{
++	struct irq_pin_list *entry, *next;
++
++	if (old_cfg->irq_2_pin == cfg->irq_2_pin)
++		return;
++
++	entry = old_cfg->irq_2_pin;
+ 
+-	irq_2_pin_ptr = &pin[0];
++	while (entry) {
++		next = entry->next;
++		kfree(entry);
++		entry = next;
++	}
++	old_cfg->irq_2_pin = NULL;
+ }
+ 
+-static struct irq_pin_list *get_one_free_irq_2_pin(void)
++void arch_init_copy_chip_data(struct irq_desc *old_desc,
++				 struct irq_desc *desc, int cpu)
+ {
+-	struct irq_pin_list *pin = irq_2_pin_ptr;
++	struct irq_cfg *cfg;
++	struct irq_cfg *old_cfg;
+ 
+-	if (!pin)
+-		panic("can not get more irq_2_pin\n");
++	cfg = get_one_free_irq_cfg(cpu);
+ 
+-	irq_2_pin_ptr = pin->next;
+-	pin->next = NULL;
+-	return pin;
++	if (!cfg)
++		return;
++
++	desc->chip_data = cfg;
++
++	old_cfg = old_desc->chip_data;
++
++	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
++
++	init_copy_irq_2_pin(old_cfg, cfg, cpu);
++}
++
++static void free_irq_cfg(struct irq_cfg *old_cfg)
++{
++	kfree(old_cfg);
++}
++
++void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
++{
++	struct irq_cfg *old_cfg, *cfg;
++
++	old_cfg = old_desc->chip_data;
++	cfg = desc->chip_data;
++
++	if (old_cfg == cfg)
++		return;
++
++	if (old_cfg) {
++		free_irq_2_pin(old_cfg, cfg);
++		free_irq_cfg(old_cfg);
++		old_desc->chip_data = NULL;
++	}
++}
++
++static void
++set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
++{
++	struct irq_cfg *cfg = desc->chip_data;
++
++	if (!cfg->move_in_progress) {
++		/* it means that domain is not changed */
++		if (!cpumask_intersects(&desc->affinity, mask))
++			cfg->move_desc_pending = 1;
++	}
++}
++#endif
++
++#else
++static struct irq_cfg *irq_cfg(unsigned int irq)
++{
++	return irq < nr_irqs ? irq_cfgx + irq : NULL;
++}
++
++#endif
++
++#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
++static inline void
++set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
++{
+ }
++#endif
+ 
+ struct io_apic {
+ 	unsigned int index;
+@@ -230,7 +404,7 @@ static __attribute_const__ struct io_api
+ 	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+ 		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+ }
+-#endif
++#endif /* CONFIG_XEN */
+ 
+ static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+ {
+@@ -285,11 +459,10 @@ static inline void io_apic_modify(unsign
+ 	writel(value, &io_apic->data);
+ }
+ 
+-static bool io_apic_level_ack_pending(unsigned int irq)
++static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
+ {
+ 	struct irq_pin_list *entry;
+ 	unsigned long flags;
+-	struct irq_cfg *cfg = irq_cfg(irq);
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	entry = cfg->irq_2_pin;
+@@ -375,13 +548,32 @@ static void ioapic_mask_entry(int apic, 
+ }
+ 
+ #ifdef CONFIG_SMP
+-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
++static void send_cleanup_vector(struct irq_cfg *cfg)
++{
++	cpumask_var_t cleanup_mask;
++
++	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
++		unsigned int i;
++		cfg->move_cleanup_count = 0;
++		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
++			cfg->move_cleanup_count++;
++		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
++			send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
++	} else {
++		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
++		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
++		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		free_cpumask_var(cleanup_mask);
++	}
++	cfg->move_in_progress = 0;
++}
++
++static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+ {
+ 	int apic, pin;
+-	struct irq_cfg *cfg;
+ 	struct irq_pin_list *entry;
++	u8 vector = cfg->vector;
+ 
+-	cfg = irq_cfg(irq);
+ 	entry = cfg->irq_2_pin;
+ 	for (;;) {
+ 		unsigned int reg;
+@@ -411,36 +603,61 @@ static void __target_IO_APIC_irq(unsigne
+ 	}
+ }
+ 
+-static int assign_irq_vector(int irq, cpumask_t mask);
++static int
++assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
++
++/*
++ * Either sets desc->affinity to a valid value, and returns cpu_mask_to_apicid
++ * of that, or returns BAD_APICID and leaves desc->affinity untouched.
++ */
++static unsigned int
++set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
++{
++	struct irq_cfg *cfg;
++	unsigned int irq;
++
++	if (!cpumask_intersects(mask, cpu_online_mask))
++		return BAD_APICID;
++
++	irq = desc->irq;
++	cfg = desc->chip_data;
++	if (assign_irq_vector(irq, cfg, mask))
++		return BAD_APICID;
++
++	cpumask_and(&desc->affinity, cfg->domain, mask);
++	set_extra_move_desc(desc, mask);
++	return cpu_mask_to_apicid_and(&desc->affinity, cpu_online_mask);
++}
+ 
+-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
++static void
++set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ {
+ 	struct irq_cfg *cfg;
+ 	unsigned long flags;
+ 	unsigned int dest;
+-	cpumask_t tmp;
+-	struct irq_desc *desc;
++	unsigned int irq;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
++	irq = desc->irq;
++	cfg = desc->chip_data;
+ 
+-	cfg = irq_cfg(irq);
+-	if (assign_irq_vector(irq, mask))
+-		return;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	dest = set_desc_affinity(desc, mask);
++	if (dest != BAD_APICID) {
++		/* Only the high 8 bits are valid. */
++		dest = SET_APIC_LOGICAL_ID(dest);
++		__target_IO_APIC_irq(irq, dest, cfg);
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
+ 
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-	/*
+-	 * Only the high 8 bits are valid.
+-	 */
+-	dest = SET_APIC_LOGICAL_ID(dest);
++static void
++set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
++{
++	struct irq_desc *desc;
+ 
+ 	desc = irq_to_desc(irq);
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__target_IO_APIC_irq(irq, dest, cfg->vector);
+-	desc->affinity = mask;
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	set_ioapic_affinity_irq_desc(desc, mask);
+ }
+ #endif /* CONFIG_SMP */
+ 
+@@ -449,16 +666,18 @@ static void set_ioapic_affinity_irq(unsi
+  * shared ISA-space IRQs, so we have to support them. We are super
+  * fast in the common case, and fast for shared ISA-space IRQs.
+  */
+-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
++static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
+ {
+-	struct irq_cfg *cfg;
+ 	struct irq_pin_list *entry;
+ 
+-	/* first time to refer irq_cfg, so with new */
+-	cfg = irq_cfg_alloc(irq);
+ 	entry = cfg->irq_2_pin;
+ 	if (!entry) {
+-		entry = get_one_free_irq_2_pin();
++		entry = get_one_free_irq_2_pin(cpu);
++		if (!entry) {
++			printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
++					apic, pin);
++			return;
++		}
+ 		cfg->irq_2_pin = entry;
+ 		entry->apic = apic;
+ 		entry->pin = pin;
+@@ -473,7 +692,7 @@ static void add_pin_to_irq(unsigned int 
+ 		entry = entry->next;
+ 	}
+ 
+-	entry->next = get_one_free_irq_2_pin();
++	entry->next = get_one_free_irq_2_pin(cpu);
+ 	entry = entry->next;
+ 	entry->apic = apic;
+ 	entry->pin = pin;
+@@ -482,11 +701,10 @@ static void add_pin_to_irq(unsigned int 
+ /*
+  * Reroute an IRQ to a different pin.
+  */
+-static void __init replace_pin_at_irq(unsigned int irq,
++static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
+ 				      int oldapic, int oldpin,
+ 				      int newapic, int newpin)
+ {
+-	struct irq_cfg *cfg = irq_cfg(irq);
+ 	struct irq_pin_list *entry = cfg->irq_2_pin;
+ 	int replaced = 0;
+ 
+@@ -503,18 +721,16 @@ static void __init replace_pin_at_irq(un
+ 
+ 	/* why? call replace before add? */
+ 	if (!replaced)
+-		add_pin_to_irq(irq, newapic, newpin);
++		add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
+ }
+ 
+-static inline void io_apic_modify_irq(unsigned int irq,
++static inline void io_apic_modify_irq(struct irq_cfg *cfg,
+ 				int mask_and, int mask_or,
+ 				void (*final)(struct irq_pin_list *entry))
+ {
+ 	int pin;
+-	struct irq_cfg *cfg;
+ 	struct irq_pin_list *entry;
+ 
+-	cfg = irq_cfg(irq);
+ 	for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+ 		unsigned int reg;
+ 		pin = entry->pin;
+@@ -527,13 +743,13 @@ static inline void io_apic_modify_irq(un
+ 	}
+ }
+ 
+-static void __unmask_IO_APIC_irq(unsigned int irq)
++static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+-	io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL);
++	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
+ }
+ 
+ #ifdef CONFIG_X86_64
+-void io_apic_sync(struct irq_pin_list *entry)
++static void io_apic_sync(struct irq_pin_list *entry)
+ {
+ 	/*
+ 	 * Synchronize the IO-APIC and the CPU by doing
+@@ -544,47 +760,64 @@ void io_apic_sync(struct irq_pin_list *e
+ 	readl(&io_apic->data);
+ }
+ 
+-static void __mask_IO_APIC_irq(unsigned int irq)
++static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+-	io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
++	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+ }
+ #else /* CONFIG_X86_32 */
+-static void __mask_IO_APIC_irq(unsigned int irq)
++static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+-	io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL);
++	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL);
+ }
+ 
+-static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
++static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+-	io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER,
++	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER,
+ 			IO_APIC_REDIR_MASKED, NULL);
+ }
+ 
+-static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
++static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg)
+ {
+-	io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED,
++	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED,
+ 			IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
+ }
+ #endif /* CONFIG_X86_32 */
+ 
+-static void mask_IO_APIC_irq (unsigned int irq)
++static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
+ {
++	struct irq_cfg *cfg = desc->chip_data;
+ 	unsigned long flags;
+ 
++	BUG_ON(!cfg);
++
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	__mask_IO_APIC_irq(irq);
++	__mask_IO_APIC_irq(cfg);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+-static void unmask_IO_APIC_irq (unsigned int irq)
++static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
+ {
++	struct irq_cfg *cfg = desc->chip_data;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	__unmask_IO_APIC_irq(irq);
++	__unmask_IO_APIC_irq(cfg);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
++static void mask_IO_APIC_irq(unsigned int irq)
++{
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	mask_IO_APIC_irq_desc(desc);
++}
++static void unmask_IO_APIC_irq(unsigned int irq)
++{
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	unmask_IO_APIC_irq_desc(desc);
++}
++
+ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+ {
+ 	struct IO_APIC_route_entry entry;
+@@ -624,6 +857,8 @@ void send_IPI_self(int vector)
+ 	apic_write(APIC_ICR, cfg);
+ }
+ #endif /* !CONFIG_SMP && CONFIG_X86_32*/
++#else
++#define add_pin_to_irq_cpu(cfg, cpu, apic, pin)
+ #endif /* CONFIG_XEN */
+ 
+ #ifdef CONFIG_X86_32
+@@ -864,7 +1099,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector
+  */
+ static int EISA_ELCR(unsigned int irq)
+ {
+-	if (irq < 16) {
++	if (irq < NR_IRQS_LEGACY) {
+ 		unsigned int port = 0x4d0 + (irq >> 3);
+ 		return (inb(port) >> (irq & 7)) & 1;
+ 	}
+@@ -1089,52 +1324,118 @@ void unlock_vector_lock(void)
+ {
+ 	spin_unlock(&vector_lock);
+ }
+-#endif
+ 
+-static int assign_irq_vector(int irq, cpumask_t mask)
++static int
++__assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
+ {
+-	struct physdev_irq irq_op;
+-	struct irq_cfg *cfg;
+-
+-	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+-		return -EINVAL;
++	/*
++	 * NOTE! The local APIC isn't very good at handling
++	 * multiple interrupts at the same interrupt level.
++	 * As the interrupt level is determined by taking the
++	 * vector number and shifting that right by 4, we
++	 * want to spread these out a bit so that they don't
++	 * all fall in the same interrupt level.
++	 *
++	 * Also, we've got to be careful not to trash gate
++	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
++	 */
++	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
++	unsigned int old_vector;
++	int cpu, err;
++	cpumask_var_t tmp_mask;
++
++	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
++		return -EBUSY;
++
++	if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
++		return -ENOMEM;
++
++	old_vector = cfg->vector;
++	if (old_vector) {
++		cpumask_and(tmp_mask, mask, cpu_online_mask);
++		cpumask_and(tmp_mask, cfg->domain, tmp_mask);
++		if (!cpumask_empty(tmp_mask)) {
++			free_cpumask_var(tmp_mask);
++			return 0;
++		}
++	}
+ 
+-	cfg = irq_cfg(irq);
++	/* Only try and allocate irqs on cpus that are present */
++	err = -ENOSPC;
++	for_each_cpu_and(cpu, mask, cpu_online_mask) {
++		int new_cpu;
++		int vector, offset;
++
++		vector_allocation_domain(cpu, tmp_mask);
++
++		vector = current_vector;
++		offset = current_offset;
++next:
++		vector += 8;
++		if (vector >= first_system_vector) {
++			/* If out of vectors on large boxen, must share them. */
++			offset = (offset + 1) % 8;
++			vector = FIRST_DEVICE_VECTOR + offset;
++		}
++		if (unlikely(current_vector == vector))
++			continue;
+ 
+-	if (cfg->vector)
+-		return 0;
++		if (test_bit(vector, used_vectors))
++			goto next;
+ 
+-	irq_op.irq = irq;
+-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+-		return -ENOSPC;
++#ifdef CONFIG_KDB
++		if (vector == KDBENTER_VECTOR)
++			goto next;
++#endif	/* CONFIG_KDB */
++		for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
++			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
++				goto next;
++		/* Found one! */
++		current_vector = vector;
++		current_offset = offset;
++		if (old_vector) {
++			cfg->move_in_progress = 1;
++			cpumask_copy(cfg->old_domain, cfg->domain);
++		}
++		for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
++			per_cpu(vector_irq, new_cpu)[vector] = irq;
++		cfg->vector = vector;
++		cpumask_copy(cfg->domain, tmp_mask);
++		err = 0;
++		break;
++	}
++	free_cpumask_var(tmp_mask);
++	return err;
++}
+ 
+-	cfg->vector = irq_op.vector;
++static int
++assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
++{
++	int err;
++	unsigned long flags;
+ 
+-	return 0;
++	spin_lock_irqsave(&vector_lock, flags);
++	err = __assign_irq_vector(irq, cfg, mask);
++	spin_unlock_irqrestore(&vector_lock, flags);
++	return err;
+ }
+ 
+-#ifndef CONFIG_XEN
+-static void __clear_irq_vector(int irq)
++static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
+ {
+-	struct irq_cfg *cfg;
+-	cpumask_t mask;
+ 	int cpu, vector;
+ 
+-	cfg = irq_cfg(irq);
+ 	BUG_ON(!cfg->vector);
+ 
+ 	vector = cfg->vector;
+-	cpus_and(mask, cfg->domain, cpu_online_map);
+-	for_each_cpu_mask_nr(cpu, mask)
++	for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
+ 		per_cpu(vector_irq, cpu)[vector] = -1;
+ 
+ 	cfg->vector = 0;
+-	cpus_clear(cfg->domain);
++	cpumask_clear(cfg->domain);
+ 
+ 	if (likely(!cfg->move_in_progress))
+ 		return;
+-	cpus_and(mask, cfg->old_domain, cpu_online_map);
+-	for_each_cpu_mask_nr(cpu, mask) {
++	for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
+ 		for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
+ 								vector++) {
+ 			if (per_cpu(vector_irq, cpu)[vector] != irq)
+@@ -1152,10 +1453,12 @@ void __setup_vector_irq(int cpu)
+ 	/* This function must be called with vector_lock held */
+ 	int irq, vector;
+ 	struct irq_cfg *cfg;
++	struct irq_desc *desc;
+ 
+ 	/* Mark the inuse vectors */
+-	for_each_irq_cfg(irq, cfg) {
+-		if (!cpu_isset(cpu, cfg->domain))
++	for_each_irq_desc(irq, desc) {
++		cfg = desc->chip_data;
++		if (!cpumask_test_cpu(cpu, cfg->domain))
+ 			continue;
+ 		vector = cfg->vector;
+ 		per_cpu(vector_irq, cpu)[vector] = irq;
+@@ -1167,7 +1470,7 @@ void __setup_vector_irq(int cpu)
+ 			continue;
+ 
+ 		cfg = irq_cfg(irq);
+-		if (!cpu_isset(cpu, cfg->domain))
++		if (!cpumask_test_cpu(cpu, cfg->domain))
+ 			per_cpu(vector_irq, cpu)[vector] = -1;
+ 	}
+ }
+@@ -1205,11 +1508,8 @@ static inline int IO_APIC_irq_trigger(in
+ }
+ #endif
+ 
+-static void ioapic_register_intr(int irq, unsigned long trigger)
++static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+ {
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+ 
+ 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+ 	    trigger == IOAPIC_LEVEL)
+@@ -1240,8 +1540,8 @@ static void ioapic_register_intr(int irq
+ 					      handle_edge_irq, "edge");
+ }
+ #else /* !CONFIG_XEN */
+-#define __clear_irq_vector(irq) ((void)(irq))
+-#define ioapic_register_intr(irq, trigger) evtchn_register_pirq(irq)
++#define __clear_irq_vector(irq, cfg) ((void)0)
++#define ioapic_register_intr(irq, desc, trigger) evtchn_register_pirq(irq)
+ #endif
+ 
+ static int setup_ioapic_entry(int apic, int irq,
+@@ -1305,24 +1605,25 @@ static int setup_ioapic_entry(int apic, 
+ 	return 0;
+ }
+ 
+-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
++static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc,
+ 			      int trigger, int polarity)
+ {
+ 	struct irq_cfg *cfg;
+ 	struct IO_APIC_route_entry entry;
+-	cpumask_t mask;
++	unsigned int dest;
+ 
+ 	if (!IO_APIC_IRQ(irq))
+ 		return;
+ 
+-	cfg = irq_cfg(irq);
++	cfg = desc->chip_data;
+ 
+-	mask = TARGET_CPUS;
+-	if (assign_irq_vector(irq, mask))
++	if (assign_irq_vector(irq, cfg, TARGET_CPUS))
+ 		return;
+ 
+ #ifndef CONFIG_XEN
+-	cpus_and(mask, cfg->domain, mask);
++	dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
++#else
++	dest = cpu_mask_to_apicid(TARGET_CPUS);
+ #endif
+ 
+ 	apic_printk(APIC_VERBOSE,KERN_DEBUG
+@@ -1333,16 +1634,15 @@ static void setup_IO_APIC_irq(int apic, 
+ 
+ 
+ 	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
+-			       cpu_mask_to_apicid(mask), trigger, polarity,
+-			       cfg->vector)) {
++			       dest, trigger, polarity, cfg->vector)) {
+ 		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+ 		       mp_ioapics[apic].mp_apicid, pin);
+-		__clear_irq_vector(irq);
++		__clear_irq_vector(irq, cfg);
+ 		return;
+ 	}
+ 
+-	ioapic_register_intr(irq, trigger);
+-	if (irq < 16)
++	ioapic_register_intr(irq, desc, trigger);
++	if (irq < NR_IRQS_LEGACY)
+ 		disable_8259A_irq(irq);
+ 
+ 	ioapic_write_entry(apic, pin, entry);
+@@ -1352,6 +1652,9 @@ static void __init setup_IO_APIC_irqs(vo
+ {
+ 	int apic, pin, idx, irq;
+ 	int notcon = 0;
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++	int cpu = boot_cpu_id;
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+@@ -1386,9 +1689,15 @@ static void __init setup_IO_APIC_irqs(vo
+ 			if (multi_timer_check(apic, irq))
+ 				continue;
+ #endif
+-			add_pin_to_irq(irq, apic, pin);
++			desc = irq_to_desc_alloc_cpu(irq, cpu);
++			if (!desc) {
++				printk(KERN_INFO "can not get irq_desc for %d\n", irq);
++				continue;
++			}
++			cfg = desc->chip_data;
++			add_pin_to_irq_cpu(cfg, cpu, apic, pin);
+ 
+-			setup_IO_APIC_irq(apic, pin, irq,
++			setup_IO_APIC_irq(apic, pin, irq, desc,
+ 					irq_trigger(idx), irq_polarity(idx));
+ 		}
+ 	}
+@@ -1448,6 +1757,7 @@ __apicdebuginit(void) print_IO_APIC(void
+ 	union IO_APIC_reg_03 reg_03;
+ 	unsigned long flags;
+ 	struct irq_cfg *cfg;
++	struct irq_desc *desc;
+ 	unsigned int irq;
+ 
+ 	if (apic_verbosity == APIC_QUIET)
+@@ -1537,8 +1847,11 @@ __apicdebuginit(void) print_IO_APIC(void
+ 	}
+ 	}
+ 	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+-	for_each_irq_cfg(irq, cfg) {
+-		struct irq_pin_list *entry = cfg->irq_2_pin;
++	for_each_irq_desc(irq, desc) {
++		struct irq_pin_list *entry;
++
++		cfg = desc->chip_data;
++		entry = cfg->irq_2_pin;
+ 		if (!entry)
+ 			continue;
+ 		printk(KERN_DEBUG "IRQ%d ", irq);
+@@ -2030,14 +2343,16 @@ static unsigned int startup_ioapic_irq(u
+ {
+ 	int was_pending = 0;
+ 	unsigned long flags;
++	struct irq_cfg *cfg;
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	if (irq < 16) {
++	if (irq < NR_IRQS_LEGACY) {
+ 		disable_8259A_irq(irq);
+ 		if (i8259A_irq_pending(irq))
+ 			was_pending = 1;
+ 	}
+-	__unmask_IO_APIC_irq(irq);
++	cfg = irq_cfg(irq);
++	__unmask_IO_APIC_irq(cfg);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	return was_pending;
+@@ -2051,7 +2366,7 @@ static int ioapic_retrigger_irq(unsigned
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
++	send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return 1;
+@@ -2100,35 +2415,35 @@ static DECLARE_DELAYED_WORK(ir_migration
+  * as simple as edge triggered migration and we can do the irq migration
+  * with a simple atomic update to IO-APIC RTE.
+  */
+-static void migrate_ioapic_irq(int irq, cpumask_t mask)
++static void
++migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ {
+ 	struct irq_cfg *cfg;
+-	struct irq_desc *desc;
+-	cpumask_t tmp, cleanup_mask;
+ 	struct irte irte;
+ 	int modify_ioapic_rte;
+ 	unsigned int dest;
+ 	unsigned long flags;
++	unsigned int irq;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
++	if (!cpumask_intersects(mask, cpu_online_mask))
+ 		return;
+ 
++	irq = desc->irq;
+ 	if (get_irte(irq, &irte))
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
++	cfg = desc->chip_data;
++	if (assign_irq_vector(irq, cfg, mask))
+ 		return;
+ 
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
++	set_extra_move_desc(desc, mask);
++
++	dest = cpu_mask_to_apicid_and(cfg->domain, mask);
+ 
+-	desc = irq_to_desc(irq);
+ 	modify_ioapic_rte = desc->status & IRQ_LEVEL;
+ 	if (modify_ioapic_rte) {
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+-		__target_IO_APIC_irq(irq, dest, cfg->vector);
++		__target_IO_APIC_irq(irq, dest, cfg);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+ 
+@@ -2140,24 +2455,20 @@ static void migrate_ioapic_irq(int irq, 
+ 	 */
+ 	modify_irte(irq, &irte);
+ 
+-	if (cfg->move_in_progress) {
+-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+-		cfg->move_in_progress = 0;
+-	}
++	if (cfg->move_in_progress)
++		send_cleanup_vector(cfg);
+ 
+-	desc->affinity = mask;
++	cpumask_copy(&desc->affinity, mask);
+ }
+ 
+-static int migrate_irq_remapped_level(int irq)
++static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
+ {
+ 	int ret = -1;
+-	struct irq_desc *desc = irq_to_desc(irq);
++	struct irq_cfg *cfg = desc->chip_data;
+ 
+-	mask_IO_APIC_irq(irq);
++	mask_IO_APIC_irq_desc(desc);
+ 
+-	if (io_apic_level_ack_pending(irq)) {
++	if (io_apic_level_ack_pending(cfg)) {
+ 		/*
+ 		 * Interrupt in progress. Migrating irq now will change the
+ 		 * vector information in the IO-APIC RTE and that will confuse
+@@ -2169,14 +2480,15 @@ static int migrate_irq_remapped_level(in
+ 	}
+ 
+ 	/* everthing is clear. we have right of way */
+-	migrate_ioapic_irq(irq, desc->pending_mask);
++	migrate_ioapic_irq_desc(desc, &desc->pending_mask);
+ 
+ 	ret = 0;
+ 	desc->status &= ~IRQ_MOVE_PENDING;
+-	cpus_clear(desc->pending_mask);
++	cpumask_clear(&desc->pending_mask);
+ 
+ unmask:
+-	unmask_IO_APIC_irq(irq);
++	unmask_IO_APIC_irq_desc(desc);
++
+ 	return ret;
+ }
+ 
+@@ -2197,7 +2509,7 @@ static void ir_irq_migration(struct work
+ 				continue;
+ 			}
+ 
+-			desc->chip->set_affinity(irq, desc->pending_mask);
++			desc->chip->set_affinity(irq, &desc->pending_mask);
+ 			spin_unlock_irqrestore(&desc->lock, flags);
+ 		}
+ 	}
+@@ -2206,28 +2518,33 @@ static void ir_irq_migration(struct work
+ /*
+  * Migrates the IRQ destination in the process context.
+  */
+-static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
++static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
++					    const struct cpumask *mask)
+ {
+-	struct irq_desc *desc = irq_to_desc(irq);
+-
+ 	if (desc->status & IRQ_LEVEL) {
+ 		desc->status |= IRQ_MOVE_PENDING;
+-		desc->pending_mask = mask;
+-		migrate_irq_remapped_level(irq);
++		cpumask_copy(&desc->pending_mask, mask);
++		migrate_irq_remapped_level_desc(desc);
+ 		return;
+ 	}
+ 
+-	migrate_ioapic_irq(irq, mask);
++	migrate_ioapic_irq_desc(desc, mask);
++}
++static void set_ir_ioapic_affinity_irq(unsigned int irq,
++				       const struct cpumask *mask)
++{
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	set_ir_ioapic_affinity_irq_desc(desc, mask);
+ }
+ #endif
+ 
+ asmlinkage void smp_irq_move_cleanup_interrupt(void)
+ {
+ 	unsigned vector, me;
++
+ 	ack_APIC_irq();
+-#ifdef CONFIG_X86_64
+ 	exit_idle();
+-#endif
+ 	irq_enter();
+ 
+ 	me = smp_processor_id();
+@@ -2237,6 +2554,9 @@ asmlinkage void smp_irq_move_cleanup_int
+ 		struct irq_cfg *cfg;
+ 		irq = __get_cpu_var(vector_irq)[vector];
+ 
++		if (irq == -1)
++			continue;
++
+ 		desc = irq_to_desc(irq);
+ 		if (!desc)
+ 			continue;
+@@ -2246,7 +2566,7 @@ asmlinkage void smp_irq_move_cleanup_int
+ 		if (!cfg->move_cleanup_count)
+ 			goto unlock;
+ 
+-		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
++		if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
+ 			goto unlock;
+ 
+ 		__get_cpu_var(vector_irq)[vector] = -1;
+@@ -2258,28 +2578,45 @@ unlock:
+ 	irq_exit();
+ }
+ 
+-static void irq_complete_move(unsigned int irq)
++static void irq_complete_move(struct irq_desc **descp)
+ {
+-	struct irq_cfg *cfg = irq_cfg(irq);
++	struct irq_desc *desc = *descp;
++	struct irq_cfg *cfg = desc->chip_data;
+ 	unsigned vector, me;
+ 
+-	if (likely(!cfg->move_in_progress))
++	if (likely(!cfg->move_in_progress)) {
++#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
++		if (likely(!cfg->move_desc_pending))
++			return;
++
++		/* domain has not changed, but affinity did */
++		me = smp_processor_id();
++		if (cpu_isset(me, desc->affinity)) {
++			*descp = desc = move_irq_desc(desc, me);
++			/* get the new one */
++			cfg = desc->chip_data;
++			cfg->move_desc_pending = 0;
++		}
++#endif
+ 		return;
++	}
+ 
+ 	vector = ~get_irq_regs()->orig_ax;
+ 	me = smp_processor_id();
+-	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
+-		cpumask_t cleanup_mask;
+ 
+-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+-		cfg->move_in_progress = 0;
++	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
++#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
++		*descp = desc = move_irq_desc(desc, me);
++		/* get the new one */
++		cfg = desc->chip_data;
++#endif
++		send_cleanup_vector(cfg);
+ 	}
+ }
+ #else
+-static inline void irq_complete_move(unsigned int irq) {}
++static inline void irq_complete_move(struct irq_desc **descp) {}
+ #endif
++
+ #ifdef CONFIG_INTR_REMAP
+ static void ack_x2apic_level(unsigned int irq)
+ {
+@@ -2290,11 +2627,14 @@ static void ack_x2apic_edge(unsigned int
+ {
+ 	ack_x2APIC_irq();
+ }
++
+ #endif
+ 
+ static void ack_apic_edge(unsigned int irq)
+ {
+-	irq_complete_move(irq);
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	irq_complete_move(&desc);
+ 	move_native_irq(irq);
+ 	ack_APIC_irq();
+ }
+@@ -2303,18 +2643,21 @@ atomic_t irq_mis_count;
+ 
+ static void ack_apic_level(unsigned int irq)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
++
+ #ifdef CONFIG_X86_32
+ 	unsigned long v;
+ 	int i;
+ #endif
++	struct irq_cfg *cfg;
+ 	int do_unmask_irq = 0;
+ 
+-	irq_complete_move(irq);
++	irq_complete_move(&desc);
+ #ifdef CONFIG_GENERIC_PENDING_IRQ
+ 	/* If we are moving the irq we need to mask it */
+-	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
++	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+ 		do_unmask_irq = 1;
+-		mask_IO_APIC_irq(irq);
++		mask_IO_APIC_irq_desc(desc);
+ 	}
+ #endif
+ 
+@@ -2338,7 +2681,8 @@ static void ack_apic_level(unsigned int 
+ 	* operation to prevent an edge-triggered interrupt escaping meanwhile.
+ 	* The idea is from Manfred Spraul.  --macro
+ 	*/
+-	i = irq_cfg(irq)->vector;
++	cfg = desc->chip_data;
++	i = cfg->vector;
+ 
+ 	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+ #endif
+@@ -2377,17 +2721,18 @@ static void ack_apic_level(unsigned int 
+ 		 * accurate and is causing problems then it is a hardware bug
+ 		 * and you can go talk to the chipset vendor about it.
+ 		 */
+-		if (!io_apic_level_ack_pending(irq))
++		cfg = desc->chip_data;
++		if (!io_apic_level_ack_pending(cfg))
+ 			move_masked_irq(irq);
+-		unmask_IO_APIC_irq(irq);
++		unmask_IO_APIC_irq_desc(desc);
+ 	}
+ 
+ #ifdef CONFIG_X86_32
+ 	if (!(v & (1 << (i & 0x1f)))) {
+ 		atomic_inc(&irq_mis_count);
+ 		spin_lock(&ioapic_lock);
+-		__mask_and_edge_IO_APIC_irq(irq);
+-		__unmask_and_level_IO_APIC_irq(irq);
++		__mask_and_edge_IO_APIC_irq(cfg);
++		__unmask_and_level_IO_APIC_irq(cfg);
+ 		spin_unlock(&ioapic_lock);
+ 	}
+ #endif
+@@ -2439,24 +2784,23 @@ static inline void init_IO_APIC_traps(vo
+ 	 * Also, we've got to be careful not to trash gate
+ 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ 	 */
+-	for_each_irq_cfg(irq, cfg) {
++	for_each_irq_desc(irq, desc) {
+ #ifdef CONFIG_XEN
+ 		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS)
+ 			continue;
+ #endif
+-		if (IO_APIC_IRQ(irq) && !cfg->vector) {
++		cfg = desc->chip_data;
++		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+ 			 * interrupt if we can..
+ 			 */
+-			if (irq < 16)
++			if (irq < NR_IRQS_LEGACY)
+ 				make_8259A_irq(irq);
+-			else {
+-				desc = irq_to_desc(irq);
++			else
+ 				/* Strange. Oh, well.. */
+ 				desc->chip = &no_irq_chip;
+-			}
+ 		}
+ 	}
+ }
+@@ -2482,7 +2826,7 @@ static void unmask_lapic_irq(unsigned in
+ 	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+ }
+ 
+-static void ack_lapic_irq (unsigned int irq)
++static void ack_lapic_irq(unsigned int irq)
+ {
+ 	ack_APIC_irq();
+ }
+@@ -2494,11 +2838,8 @@ static struct irq_chip lapic_chip __read
+ 	.ack		= ack_lapic_irq,
+ };
+ 
+-static void lapic_register_intr(int irq)
++static void lapic_register_intr(int irq, struct irq_desc *desc)
+ {
+-	struct irq_desc *desc;
+-
+-	desc = irq_to_desc(irq);
+ 	desc->status &= ~IRQ_LEVEL;
+ 	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+ 				      "edge");
+@@ -2602,7 +2943,9 @@ int timer_through_8259 __initdata;
+  */
+ static inline void __init check_timer(void)
+ {
+-	struct irq_cfg *cfg = irq_cfg(0);
++	struct irq_desc *desc = irq_to_desc(0);
++	struct irq_cfg *cfg = desc->chip_data;
++	int cpu = boot_cpu_id;
+ 	int apic1, pin1, apic2, pin2;
+ 	unsigned long flags;
+ 	unsigned int ver;
+@@ -2617,7 +2960,7 @@ static inline void __init check_timer(vo
+ 	 * get/set the timer IRQ vector:
+ 	 */
+ 	disable_8259A_irq(0);
+-	assign_irq_vector(0, TARGET_CPUS);
++	assign_irq_vector(0, cfg, TARGET_CPUS);
+ 
+ 	/*
+ 	 * As IRQ0 is to be enabled in the 8259A, the virtual
+@@ -2668,10 +3011,10 @@ static inline void __init check_timer(vo
+ 		 * Ok, does IRQ0 through the IOAPIC work?
+ 		 */
+ 		if (no_pin1) {
+-			add_pin_to_irq(0, apic1, pin1);
++			add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
+ 			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+ 		}
+-		unmask_IO_APIC_irq(0);
++		unmask_IO_APIC_irq_desc(desc);
+ 		if (timer_irq_works()) {
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+ 				setup_nmi();
+@@ -2697,9 +3040,9 @@ static inline void __init check_timer(vo
+ 		/*
+ 		 * legacy devices should be connected to IO APIC #0
+ 		 */
+-		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
++		replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
+ 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+-		unmask_IO_APIC_irq(0);
++		unmask_IO_APIC_irq_desc(desc);
+ 		enable_8259A_irq(0);
+ 		if (timer_irq_works()) {
+ 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+@@ -2731,7 +3074,7 @@ static inline void __init check_timer(vo
+ 	apic_printk(APIC_QUIET, KERN_INFO
+ 		    "...trying to set up timer as Virtual Wire IRQ...\n");
+ 
+-	lapic_register_intr(0);
++	lapic_register_intr(0, desc);
+ 	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+@@ -2930,22 +3273,26 @@ unsigned int create_irq_nr(unsigned int 
+ 	unsigned int irq;
+ 	unsigned int new;
+ 	unsigned long flags;
+-	struct irq_cfg *cfg_new;
+-
+-	irq_want = nr_irqs - 1;
++	struct irq_cfg *cfg_new = NULL;
++	int cpu = boot_cpu_id;
++	struct irq_desc *desc_new = NULL;
+ 
+ 	irq = 0;
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	for (new = irq_want; new > 0; new--) {
++	for (new = irq_want; new < NR_IRQS; new++) {
+ 		if (platform_legacy_irq(new))
+ 			continue;
+-		cfg_new = irq_cfg(new);
+-		if (cfg_new && cfg_new->vector != 0)
++
++		desc_new = irq_to_desc_alloc_cpu(new, cpu);
++		if (!desc_new) {
++			printk(KERN_INFO "can not get irq_desc for %d\n", new);
++			continue;
++		}
++		cfg_new = desc_new->chip_data;
++
++		if (cfg_new->vector != 0)
+ 			continue;
+-		/* check if need to create one */
+-		if (!cfg_new)
+-			cfg_new = irq_cfg_alloc(new);
+-		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
++		if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0)
+ 			irq = new;
+ 		break;
+ 	}
+@@ -2953,15 +3300,21 @@ unsigned int create_irq_nr(unsigned int 
+ 
+ 	if (irq > 0) {
+ 		dynamic_irq_init(irq);
++		/* restore it, in case dynamic_irq_init clear it */
++		if (desc_new)
++			desc_new->chip_data = cfg_new;
+ 	}
+ 	return irq;
+ }
+ 
++static int nr_irqs_gsi = NR_IRQS_LEGACY;
+ int create_irq(void)
+ {
++	unsigned int irq_want;
+ 	int irq;
+ 
+-	irq = create_irq_nr(nr_irqs - 1);
++	irq_want = nr_irqs_gsi;
++	irq = create_irq_nr(irq_want);
+ 
+ 	if (irq == 0)
+ 		irq = -1;
+@@ -2972,14 +3325,22 @@ int create_irq(void)
+ void destroy_irq(unsigned int irq)
+ {
+ 	unsigned long flags;
++	struct irq_cfg *cfg;
++	struct irq_desc *desc;
+ 
++	/* store it, in case dynamic_irq_cleanup clear it */
++	desc = irq_to_desc(irq);
++	cfg = desc->chip_data;
+ 	dynamic_irq_cleanup(irq);
++	/* connect back irq_cfg */
++	if (desc)
++		desc->chip_data = cfg;
+ 
+ #ifdef CONFIG_INTR_REMAP
+ 	free_irte(irq);
+ #endif
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	__clear_irq_vector(irq);
++	__clear_irq_vector(irq, cfg);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ }
+ #endif /* CONFIG_XEN */
+@@ -2993,16 +3354,13 @@ static int msi_compose_msg(struct pci_de
+ 	struct irq_cfg *cfg;
+ 	int err;
+ 	unsigned dest;
+-	cpumask_t tmp;
+ 
+-	tmp = TARGET_CPUS;
+-	err = assign_irq_vector(irq, tmp);
++	cfg = irq_cfg(irq);
++	err = assign_irq_vector(irq, cfg, TARGET_CPUS);
+ 	if (err)
+ 		return err;
+ 
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, tmp);
+-	dest = cpu_mask_to_apicid(tmp);
++	dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
+ 
+ #ifdef CONFIG_INTR_REMAP
+ 	if (irq_remapped(irq)) {
+@@ -3056,64 +3414,48 @@ static int msi_compose_msg(struct pci_de
+ }
+ 
+ #ifdef CONFIG_SMP
+-static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+ 	struct msi_msg msg;
+ 	unsigned int dest;
+-	cpumask_t tmp;
+-	struct irq_desc *desc;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
++	dest = set_desc_affinity(desc, mask);
++	if (dest == BAD_APICID)
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
++	cfg = desc->chip_data;
+ 
+-	read_msi_msg(irq, &msg);
++	read_msi_msg_desc(desc, &msg);
+ 
+ 	msg.data &= ~MSI_DATA_VECTOR_MASK;
+ 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+ 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+-	write_msi_msg(irq, &msg);
+-	desc = irq_to_desc(irq);
+-	desc->affinity = mask;
++	write_msi_msg_desc(desc, &msg);
+ }
+-
+ #ifdef CONFIG_INTR_REMAP
+ /*
+  * Migrate the MSI irq to another cpumask. This migration is
+  * done in the process context using interrupt-remapping hardware.
+  */
+-static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++static void
++ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
+-	struct irq_cfg *cfg;
++	struct irq_desc *desc = irq_to_desc(irq);
++	struct irq_cfg *cfg = desc->chip_data;
+ 	unsigned int dest;
+-	cpumask_t tmp, cleanup_mask;
+ 	struct irte irte;
+-	struct irq_desc *desc;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
+ 
+ 	if (get_irte(irq, &irte))
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
++	dest = set_desc_affinity(desc, mask);
++	if (dest == BAD_APICID)
+ 		return;
+ 
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-
+ 	irte.vector = cfg->vector;
+ 	irte.dest_id = IRTE_DEST(dest);
+ 
+@@ -3127,16 +3469,10 @@ static void ir_set_msi_irq_affinity(unsi
+ 	 * at the new destination. So, time to cleanup the previous
+ 	 * vector allocation.
+ 	 */
+-	if (cfg->move_in_progress) {
+-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+-		cfg->move_in_progress = 0;
+-	}
+-
+-	desc = irq_to_desc(irq);
+-	desc->affinity = mask;
++	if (cfg->move_in_progress)
++		send_cleanup_vector(cfg);
+ }
++
+ #endif
+ #endif /* CONFIG_SMP */
+ 
+@@ -3195,7 +3531,7 @@ static int msi_alloc_irte(struct pci_dev
+ }
+ #endif
+ 
+-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
++static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
+ {
+ 	int ret;
+ 	struct msi_msg msg;
+@@ -3204,7 +3540,7 @@ static int setup_msi_irq(struct pci_dev 
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	set_irq_msi(irq, desc);
++	set_irq_msi(irq, msidesc);
+ 	write_msi_msg(irq, &msg);
+ 
+ #ifdef CONFIG_INTR_REMAP
+@@ -3224,26 +3560,13 @@ static int setup_msi_irq(struct pci_dev 
+ 	return 0;
+ }
+ 
+-static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
+-{
+-	unsigned int irq;
+-
+-	irq = dev->bus->number;
+-	irq <<= 8;
+-	irq |= dev->devfn;
+-	irq <<= 12;
+-
+-	return irq;
+-}
+-
+-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
++int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc)
+ {
+ 	unsigned int irq;
+ 	int ret;
+ 	unsigned int irq_want;
+ 
+-	irq_want = build_irq_for_pci_dev(dev) + 0x100;
+-
++	irq_want = nr_irqs_gsi;
+ 	irq = create_irq_nr(irq_want);
+ 	if (irq == 0)
+ 		return -1;
+@@ -3257,7 +3580,7 @@ int arch_setup_msi_irq(struct pci_dev *d
+ 		goto error;
+ no_ir:
+ #endif
+-	ret = setup_msi_irq(dev, desc, irq);
++	ret = setup_msi_irq(dev, msidesc, irq);
+ 	if (ret < 0) {
+ 		destroy_irq(irq);
+ 		return ret;
+@@ -3275,7 +3598,7 @@ int arch_setup_msi_irqs(struct pci_dev *
+ {
+ 	unsigned int irq;
+ 	int ret, sub_handle;
+-	struct msi_desc *desc;
++	struct msi_desc *msidesc;
+ 	unsigned int irq_want;
+ 
+ #ifdef CONFIG_INTR_REMAP
+@@ -3283,10 +3606,11 @@ int arch_setup_msi_irqs(struct pci_dev *
+ 	int index = 0;
+ #endif
+ 
+-	irq_want = build_irq_for_pci_dev(dev) + 0x100;
++	irq_want = nr_irqs_gsi;
+ 	sub_handle = 0;
+-	list_for_each_entry(desc, &dev->msi_list, list) {
+-		irq = create_irq_nr(irq_want--);
++	list_for_each_entry(msidesc, &dev->msi_list, list) {
++		irq = create_irq_nr(irq_want);
++		irq_want++;
+ 		if (irq == 0)
+ 			return -1;
+ #ifdef CONFIG_INTR_REMAP
+@@ -3318,7 +3642,7 @@ int arch_setup_msi_irqs(struct pci_dev *
+ 		}
+ no_ir:
+ #endif
+-		ret = setup_msi_irq(dev, desc, irq);
++		ret = setup_msi_irq(dev, msidesc, irq);
+ 		if (ret < 0)
+ 			goto error;
+ 		sub_handle++;
+@@ -3337,24 +3661,18 @@ void arch_teardown_msi_irq(unsigned int 
+ 
+ #ifdef CONFIG_DMAR
+ #ifdef CONFIG_SMP
+-static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
++static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+ 	struct msi_msg msg;
+ 	unsigned int dest;
+-	cpumask_t tmp;
+-	struct irq_desc *desc;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
++	dest = set_desc_affinity(desc, mask);
++	if (dest == BAD_APICID)
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
++	cfg = desc->chip_data;
+ 
+ 	dmar_msi_read(irq, &msg);
+ 
+@@ -3364,9 +3682,8 @@ static void dmar_msi_set_affinity(unsign
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	dmar_msi_write(irq, &msg);
+-	desc = irq_to_desc(irq);
+-	desc->affinity = mask;
+ }
++
+ #endif /* CONFIG_SMP */
+ 
+ struct irq_chip dmar_msi_type = {
+@@ -3398,24 +3715,18 @@ int arch_setup_dmar_msi(unsigned int irq
+ #ifdef CONFIG_HPET_TIMER
+ 
+ #ifdef CONFIG_SMP
+-static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask)
++static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+-	struct irq_desc *desc;
+ 	struct msi_msg msg;
+ 	unsigned int dest;
+-	cpumask_t tmp;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
++	dest = set_desc_affinity(desc, mask);
++	if (dest == BAD_APICID)
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
++	cfg = desc->chip_data;
+ 
+ 	hpet_msi_read(irq, &msg);
+ 
+@@ -3425,9 +3736,8 @@ static void hpet_msi_set_affinity(unsign
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	hpet_msi_write(irq, &msg);
+-	desc = irq_to_desc(irq);
+-	desc->affinity = mask;
+ }
++
+ #endif /* CONFIG_SMP */
+ 
+ struct irq_chip hpet_msi_type = {
+@@ -3480,28 +3790,21 @@ static void target_ht_irq(unsigned int i
+ 	write_ht_irq_msg(irq, &msg);
+ }
+ 
+-static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
++static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+ {
++	struct irq_desc *desc = irq_to_desc(irq);
+ 	struct irq_cfg *cfg;
+ 	unsigned int dest;
+-	cpumask_t tmp;
+-	struct irq_desc *desc;
+ 
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
++	dest = set_desc_affinity(desc, mask);
++	if (dest == BAD_APICID)
+ 		return;
+ 
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cfg = irq_cfg(irq);
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
++	cfg = desc->chip_data;
+ 
+ 	target_ht_irq(irq, dest, cfg->vector);
+-	desc = irq_to_desc(irq);
+-	desc->affinity = mask;
+ }
++
+ #endif
+ 
+ static struct irq_chip ht_irq_chip = {
+@@ -3519,17 +3822,14 @@ int arch_setup_ht_irq(unsigned int irq, 
+ {
+ 	struct irq_cfg *cfg;
+ 	int err;
+-	cpumask_t tmp;
+ 
+-	tmp = TARGET_CPUS;
+-	err = assign_irq_vector(irq, tmp);
++	cfg = irq_cfg(irq);
++	err = assign_irq_vector(irq, cfg, TARGET_CPUS);
+ 	if (!err) {
+ 		struct ht_irq_msg msg;
+ 		unsigned dest;
+ 
+-		cfg = irq_cfg(irq);
+-		cpus_and(tmp, cfg->domain, tmp);
+-		dest = cpu_mask_to_apicid(tmp);
++		dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
+ 
+ 		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+ 
+@@ -3565,7 +3865,7 @@ int arch_setup_ht_irq(unsigned int irq, 
+ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
+ 		       unsigned long mmr_offset)
+ {
+-	const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
++	const struct cpumask *eligible_cpu = cpumask_of(cpu);
+ 	struct irq_cfg *cfg;
+ 	int mmr_pnode;
+ 	unsigned long mmr_value;
+@@ -3573,7 +3873,9 @@ int arch_enable_uv_irq(char *irq_name, u
+ 	unsigned long flags;
+ 	int err;
+ 
+-	err = assign_irq_vector(irq, *eligible_cpu);
++	cfg = irq_cfg(irq);
++
++	err = assign_irq_vector(irq, cfg, eligible_cpu);
+ 	if (err != 0)
+ 		return err;
+ 
+@@ -3582,8 +3884,6 @@ int arch_enable_uv_irq(char *irq_name, u
+ 				      irq_name);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+-	cfg = irq_cfg(irq);
+-
+ 	mmr_value = 0;
+ 	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+ 	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+@@ -3594,7 +3894,7 @@ int arch_enable_uv_irq(char *irq_name, u
+ 	entry->polarity = 0;
+ 	entry->trigger = 0;
+ 	entry->mask = 0;
+-	entry->dest = cpu_mask_to_apicid(*eligible_cpu);
++	entry->dest = cpu_mask_to_apicid(eligible_cpu);
+ 
+ 	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+ 	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+@@ -3635,10 +3935,29 @@ int __init io_apic_get_redir_entries (in
+ 	return reg_01.bits.entries;
+ }
+ 
+-int __init probe_nr_irqs(void)
++#ifndef CONFIG_XEN
++void __init probe_nr_irqs_gsi(void)
+ {
+-	return NR_IRQS;
++	int nr = 0;
++
++	nr = acpi_probe_gsi();
++	if (nr > nr_irqs_gsi) {
++		nr_irqs_gsi = nr;
++	} else {
++		/* for acpi=off or acpi is not compiled in */
++		int idx;
++
++		nr = 0;
++		for (idx = 0; idx < nr_ioapics; idx++)
++			nr += io_apic_get_redir_entries(idx) + 1;
++
++		if (nr > nr_irqs_gsi)
++			nr_irqs_gsi = nr;
++	}
++
++	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
+ }
++#endif
+ 
+ /* --------------------------------------------------------------------------
+                           ACPI-based IOAPIC Configuration
+@@ -3738,6 +4057,10 @@ int __init io_apic_get_version(int ioapi
+ 
+ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+ {
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++	int cpu = boot_cpu_id;
++
+ #ifdef CONFIG_XEN
+ 	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS) {
+ 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
+@@ -3752,13 +4075,21 @@ int io_apic_set_pci_routing (int ioapic,
+ 		return -EINVAL;
+ 	}
+ 
++	desc = irq_to_desc_alloc_cpu(irq, cpu);
++	if (!desc) {
++		printk(KERN_INFO "can not get irq_desc %d\n", irq);
++		return 0;
++	}
++
+ 	/*
+ 	 * IRQs < 16 are already in the irq_2_pin[] map
+ 	 */
+-	if (irq >= 16)
+-		add_pin_to_irq(irq, ioapic, pin);
++	if (irq >= NR_IRQS_LEGACY) {
++		cfg = desc->chip_data;
++		add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
++	}
+ 
+-	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
++	setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
+ 
+ 	return 0;
+ }
+@@ -3797,7 +4128,7 @@ void __init setup_ioapic_dest(void)
+ 	int pin, ioapic, irq, irq_entry;
+ 	struct irq_desc *desc;
+ 	struct irq_cfg *cfg;
+-	cpumask_t mask;
++	const struct cpumask *mask;
+ 
+ 	if (skip_ioapic_setup == 1)
+ 		return;
+@@ -3813,9 +4144,10 @@ void __init setup_ioapic_dest(void)
+ 			 * when you have too many devices, because at that time only boot
+ 			 * cpu is online.
+ 			 */
+-			cfg = irq_cfg(irq);
++			desc = irq_to_desc(irq);
++			cfg = desc->chip_data;
+ 			if (!cfg->vector) {
+-				setup_IO_APIC_irq(ioapic, pin, irq,
++				setup_IO_APIC_irq(ioapic, pin, irq, desc,
+ 						  irq_trigger(irq_entry),
+ 						  irq_polarity(irq_entry));
+ 				continue;
+@@ -3825,19 +4157,18 @@ void __init setup_ioapic_dest(void)
+ 			/*
+ 			 * Honour affinities which have been set in early boot
+ 			 */
+-			desc = irq_to_desc(irq);
+ 			if (desc->status &
+ 			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+-				mask = desc->affinity;
++				mask = &desc->affinity;
+ 			else
+ 				mask = TARGET_CPUS;
+ 
+ #ifdef CONFIG_INTR_REMAP
+ 			if (intr_remapping_enabled)
+-				set_ir_ioapic_affinity_irq(irq, mask);
++				set_ir_ioapic_affinity_irq_desc(desc, mask);
+ 			else
+ #endif
+-				set_ioapic_affinity_irq(irq, mask);
++				set_ioapic_affinity_irq_desc(desc, mask);
+ 		}
+ 
+ 	}
+@@ -3886,7 +4217,6 @@ void __init ioapic_init_mappings(void)
+ 	struct resource *ioapic_res;
+ 	int i;
+ 
+-	irq_2_pin_init();
+ 	ioapic_res = ioapic_setup_resources();
+ 	for (i = 0; i < nr_ioapics; i++) {
+ 		if (smp_found_config) {
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -36,7 +36,7 @@ static void set_bitmap(unsigned long *bi
+  */
+ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+ {
+-	struct thread_struct * t = &current->thread;
++	struct thread_struct *t = &current->thread;
+ 	struct physdev_set_iobitmap set_iobitmap;
+ 
+ 	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -150,31 +150,28 @@ static inline void __send_IPI_dest_field
+ /*
+  * This is only used on smaller machines.
+  */
+-void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
++void send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector)
+ {
+ #ifndef CONFIG_XEN
+-	unsigned long mask = cpus_addr(cpumask)[0];
++	unsigned long mask = cpumask_bits(cpumask)[0];
+ #else
+-	cpumask_t mask;
+ 	unsigned int cpu;
+ #endif
+ 	unsigned long flags;
+ 
+ 	local_irq_save(flags);
+ #ifndef CONFIG_XEN
+-	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
++	WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
+ 	__send_IPI_dest_field(mask, vector);
+ #else
+-	cpus_andnot(mask, cpumask, cpu_online_map);
+-	WARN_ON(!cpus_empty(mask));
+-	for_each_online_cpu(cpu)
+-		if (cpu_isset(cpu, cpumask))
+-			__send_IPI_one(cpu, vector);
++	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
++	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
++		__send_IPI_one(cpu, vector);
+ #endif
+ 	local_irq_restore(flags);
+ }
+ 
+-void send_IPI_mask_sequence(cpumask_t mask, int vector)
++void send_IPI_mask_sequence(const struct cpumask *mask, int vector)
+ {
+ #ifndef CONFIG_XEN
+ 	unsigned long flags;
+@@ -187,18 +184,37 @@ void send_IPI_mask_sequence(cpumask_t ma
+ 	 */
+ 
+ 	local_irq_save(flags);
+-	for_each_possible_cpu(query_cpu) {
+-		if (cpu_isset(query_cpu, mask)) {
+-			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
+-					      vector);
+-		}
+-	}
++	for_each_cpu(query_cpu, mask)
++		__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu), vector);
+ 	local_irq_restore(flags);
+ #else
+ 	send_IPI_mask_bitmask(mask, vector);
+ #endif
+ }
+ 
++void send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
++{
++	unsigned long flags;
++	unsigned int query_cpu;
++	unsigned int this_cpu = smp_processor_id();
++
++	/* See Hack comment above */
++
++	local_irq_save(flags);
++#ifndef CONFIG_XEN
++	for_each_cpu(query_cpu, mask)
++		if (query_cpu != this_cpu)
++			__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
++					      vector);
++#else
++	WARN_ON(!cpumask_subset(mask, cpu_online_mask));
++	for_each_cpu_and(query_cpu, mask, cpu_online_mask)
++		if (query_cpu != this_cpu)
++			__send_IPI_one(query_cpu, vector);
++#endif
++	local_irq_restore(flags);
++}
++
+ #ifndef CONFIG_XEN
+ /* must come after the send_IPI functions above for inlining */
+ static int convert_apicid_to_cpu(int apic_id)
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/irq-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/irq-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -5,10 +5,11 @@
+ #include <linux/interrupt.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/seq_file.h>
++#include <linux/smp.h>
+ 
+ #include <asm/apic.h>
+ #include <asm/io_apic.h>
+-#include <asm/smp.h>
++#include <asm/irq.h>
+ 
+ atomic_t irq_err_count;
+ 
+@@ -43,57 +44,57 @@ void ack_bad_irq(unsigned int irq)
+ /*
+  * /proc/interrupts printing:
+  */
+-static int show_other_interrupts(struct seq_file *p)
++static int show_other_interrupts(struct seq_file *p, int prec)
+ {
+ 	int j;
+ 
+-	seq_printf(p, "NMI: ");
++	seq_printf(p, "%*s: ", prec, "NMI");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
+ 	seq_printf(p, "  Non-maskable interrupts\n");
+ #ifdef CONFIG_X86_LOCAL_APIC
+-	seq_printf(p, "LOC: ");
++	seq_printf(p, "%*s: ", prec, "LOC");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
+ 	seq_printf(p, "  Local timer interrupts\n");
+ #endif
+ #ifdef CONFIG_SMP
+-	seq_printf(p, "RES: ");
++	seq_printf(p, "%*s: ", prec, "RES");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
+ 	seq_printf(p, "  Rescheduling interrupts\n");
+-	seq_printf(p, "CAL: ");
++	seq_printf(p, "%*s: ", prec, "CAL");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
+ 	seq_printf(p, "  Function call interrupts\n");
+ #ifndef CONFIG_XEN
+-	seq_printf(p, "TLB: ");
++	seq_printf(p, "%*s: ", prec, "TLB");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
+ 	seq_printf(p, "  TLB shootdowns\n");
+ #endif
+ #endif
+ #ifdef CONFIG_X86_MCE
+-	seq_printf(p, "TRM: ");
++	seq_printf(p, "%*s: ", prec, "TRM");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
+ 	seq_printf(p, "  Thermal event interrupts\n");
+ # ifdef CONFIG_X86_64
+-	seq_printf(p, "THR: ");
++	seq_printf(p, "%*s: ", prec, "THR");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
+ 	seq_printf(p, "  Threshold APIC interrupts\n");
+ # endif
+ #endif
+ #ifdef CONFIG_X86_LOCAL_APIC
+-	seq_printf(p, "SPU: ");
++	seq_printf(p, "%*s: ", prec, "SPU");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+ 	seq_printf(p, "  Spurious interrupts\n");
+ #endif
+-	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
++	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+-	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
++	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
+ #endif
+ 	return 0;
+ }
+@@ -101,25 +102,31 @@ static int show_other_interrupts(struct 
+ int show_interrupts(struct seq_file *p, void *v)
+ {
+ 	unsigned long flags, any_count = 0;
+-	int i = *(loff_t *) v, j;
++	int i = *(loff_t *) v, j, prec;
+ 	struct irqaction *action;
+ 	struct irq_desc *desc;
+ 
+ 	if (i > nr_irqs)
+ 		return 0;
+ 
++	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
++		j *= 10;
++
+ 	if (i == nr_irqs)
+-		return show_other_interrupts(p);
++		return show_other_interrupts(p, prec);
+ 
+ 	/* print header */
+ 	if (i == 0) {
+-		seq_printf(p, "           ");
++		seq_printf(p, "%*s", prec + 8, "");
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "CPU%-8d", j);
+ 		seq_putc(p, '\n');
+ 	}
+ 
+ 	desc = irq_to_desc(i);
++	if (!desc)
++		return 0;
++
+ 	spin_lock_irqsave(&desc->lock, flags);
+ #ifndef CONFIG_SMP
+ 	any_count = kstat_irqs(i);
+@@ -131,7 +138,7 @@ int show_interrupts(struct seq_file *p, 
+ 	if (!action && !any_count)
+ 		goto out;
+ 
+-	seq_printf(p, "%3d: ", i);
++	seq_printf(p, "%*d: ", prec, i);
+ #ifndef CONFIG_SMP
+ 	seq_printf(p, "%10u ", kstat_irqs(i));
+ #else
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -15,9 +15,9 @@
+ #include <linux/notifier.h>
+ #include <linux/cpu.h>
+ #include <linux/delay.h>
++#include <linux/uaccess.h>
+ 
+ #include <asm/apic.h>
+-#include <asm/uaccess.h>
+ 
+ DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+ EXPORT_PER_CPU_SYMBOL(irq_stat);
+@@ -93,7 +93,7 @@ execute_on_irq_stack(int overflow, struc
+ 		return 0;
+ 
+ 	/* build the stack frame on the IRQ stack */
+-	isp = (u32 *) ((char*)irqctx + sizeof(*irqctx));
++	isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+ 	irqctx->tinfo.task = curctx->tinfo.task;
+ 	irqctx->tinfo.previous_esp = current_stack_pointer;
+ 
+@@ -137,7 +137,7 @@ void __cpuinit irq_ctx_init(int cpu)
+ 
+ 	hardirq_ctx[cpu] = irqctx;
+ 
+-	irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
++	irqctx = (union irq_ctx *) &softirq_stack[cpu*THREAD_SIZE];
+ 	irqctx->tinfo.task		= NULL;
+ 	irqctx->tinfo.exec_domain	= NULL;
+ 	irqctx->tinfo.cpu		= cpu;
+@@ -147,7 +147,7 @@ void __cpuinit irq_ctx_init(int cpu)
+ 	softirq_ctx[cpu] = irqctx;
+ 
+ 	printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
+-	       cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
++	       cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
+ }
+ 
+ void irq_ctx_exit(int cpu)
+@@ -174,7 +174,7 @@ asmlinkage void do_softirq(void)
+ 		irqctx->tinfo.previous_esp = current_stack_pointer;
+ 
+ 		/* build the stack frame on the softirq stack */
+-		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
++		isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+ 
+ 		call_on_stack(__do_softirq, isp);
+ 		/*
+@@ -229,25 +229,28 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ 
+-void fixup_irqs(cpumask_t map)
++/* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
++void fixup_irqs(void)
+ {
+ 	unsigned int irq;
+ 	static int warned;
+ 	struct irq_desc *desc;
+ 
+ 	for_each_irq_desc(irq, desc) {
+-		cpumask_t mask;
++		const struct cpumask *affinity;
+ 
++		if (!desc)
++			continue;
+ 		if (irq == 2)
+ 			continue;
+ 
+-		cpus_and(mask, desc->affinity, map);
+-		if (any_online_cpu(mask) == NR_CPUS) {
++		affinity = &desc->affinity;
++		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ 			/*printk("Breaking affinity for irq %i\n", irq);*/
+-			mask = map;
++			affinity = cpu_all_mask;
+ 		}
+ 		if (desc->chip->set_affinity)
+-			desc->chip->set_affinity(irq, mask);
++			desc->chip->set_affinity(irq, affinity);
+ 		else if (desc->action && !(warned++))
+ 			printk("Cannot set affinity for irq %i\n", irq);
+ 	}
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -13,12 +13,12 @@
+ #include <linux/seq_file.h>
+ #include <linux/module.h>
+ #include <linux/delay.h>
+-#include <asm/uaccess.h>
++#include <linux/ftrace.h>
++#include <linux/uaccess.h>
++#include <linux/smp.h>
+ #include <asm/io_apic.h>
+ #include <asm/idle.h>
+-#include <asm/smp.h>
+ 
+-#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /*
+  * Probabilistic stack overflow check:
+  *
+@@ -28,26 +28,25 @@
+  */
+ static inline void stack_overflow_check(struct pt_regs *regs)
+ {
++#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ 	u64 curbase = (u64)task_stack_page(current);
+-	static unsigned long warned = -60*HZ;
+ 
+-	if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
+-	    regs->sp <  curbase + sizeof(struct thread_info) + 128 &&
+-	    time_after(jiffies, warned + 60*HZ)) {
+-		printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
+-		       current->comm, curbase, regs->sp);
+-		show_stack(NULL,NULL);
+-		warned = jiffies;
+-	}
+-}
++	WARN_ONCE(regs->sp >= curbase &&
++		  regs->sp <= curbase + THREAD_SIZE &&
++		  regs->sp <  curbase + sizeof(struct thread_info) +
++					sizeof(struct pt_regs) + 128,
++
++		  "do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
++			current->comm, curbase, regs->sp);
+ #endif
++}
+ 
+ /*
+  * do_IRQ handles all normal device IRQ's (the special
+  * SMP cross-CPU interrupts have their own specific
+  * handlers).
+  */
+-asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
++asmlinkage unsigned int /*__irq_entry*/ do_IRQ(struct pt_regs *regs)
+ {
+ 	struct pt_regs *old_regs = set_irq_regs(regs);
+ 	struct irq_desc *desc;
+@@ -58,9 +57,7 @@ asmlinkage unsigned int do_IRQ(struct pt
+ 	/*exit_idle();*/
+ 	/*irq_enter();*/
+ 
+-#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ 	stack_overflow_check(regs);
+-#endif
+ 
+ 	desc = irq_to_desc(irq);
+ 	if (likely(desc))
+@@ -82,40 +79,43 @@ asmlinkage unsigned int do_IRQ(struct pt
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-void fixup_irqs(cpumask_t map)
++/* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
++void fixup_irqs(void)
+ {
+ 	unsigned int irq;
+ 	static int warned;
+ 	struct irq_desc *desc;
+ 
+ 	for_each_irq_desc(irq, desc) {
+-		cpumask_t mask;
+ 		int break_affinity = 0;
+ 		int set_affinity = 1;
++		const struct cpumask *affinity;
+ 
++		if (!desc)
++			continue;
+ 		if (irq == 2)
+ 			continue;
+ 
+ 		/* interrupt's are disabled at this point */
+ 		spin_lock(&desc->lock);
+ 
++		affinity = &desc->affinity;
+ 		if (!irq_has_action(irq) ||
+-		    cpus_equal(desc->affinity, map)) {
++		    cpumask_equal(affinity, cpu_online_mask)) {
+ 			spin_unlock(&desc->lock);
+ 			continue;
+ 		}
+ 
+-		cpus_and(mask, desc->affinity, map);
+-		if (cpus_empty(mask)) {
++		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ 			break_affinity = 1;
+-			mask = map;
++			affinity = cpu_all_mask;
+ 		}
+ 
+ 		if (desc->chip->mask)
+ 			desc->chip->mask(irq);
+ 
+ 		if (desc->chip->set_affinity)
+-			desc->chip->set_affinity(irq, mask);
++			desc->chip->set_affinity(irq, affinity);
+ 		else if (!(warned++))
+ 			set_affinity = 0;
+ 
+@@ -141,18 +141,18 @@ extern void call_softirq(void);
+ 
+ asmlinkage void do_softirq(void)
+ {
+- 	__u32 pending;
+- 	unsigned long flags;
++	__u32 pending;
++	unsigned long flags;
+ 
+- 	if (in_interrupt())
+- 		return;
++	if (in_interrupt())
++		return;
+ 
+- 	local_irq_save(flags);
+- 	pending = local_softirq_pending();
+- 	/* Switch to interrupt stack */
+- 	if (pending) {
++	local_irq_save(flags);
++	pending = local_softirq_pending();
++	/* Switch to interrupt stack */
++	if (pending) {
+ 		call_softirq();
+ 		WARN_ON_ONCE(softirq_count());
+ 	}
+- 	local_irq_restore(flags);
++	local_irq_restore(flags);
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -12,8 +12,8 @@
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+ #include <linux/vmalloc.h>
++#include <linux/uaccess.h>
+ 
+-#include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/ldt.h>
+ #include <asm/desc.h>
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/machine_kexec_32.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/machine_kexec_32.c	2009-11-06 10:51:55.000000000 +0100
+@@ -122,13 +122,7 @@ void machine_kexec_setup_load_arg(xen_ke
+ 	memcpy(control_page, relocate_kernel, PAGE_SIZE);
+ 
+ 	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);
++	xki->page_list[PA_PGD] = __ma(image->arch.pgd);
+ 
+ 	if (image->type == KEXEC_TYPE_DEFAULT)
+ 		xki->page_list[PA_SWAP_PAGE] = page_to_phys(image->swap_page);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -2,7 +2,7 @@
+  *	Intel Multiprocessor Specification 1.1 and 1.4
+  *	compliant MP-table parsing routines.
+  *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+  *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+  *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
+  */
+@@ -16,18 +16,18 @@
+ #include <linux/bitops.h>
+ #include <linux/acpi.h>
+ #include <linux/module.h>
++#include <linux/smp.h>
+ 
+-#include <asm/smp.h>
+ #include <asm/mtrr.h>
+ #include <asm/mpspec.h>
+ #include <asm/pgalloc.h>
+ #include <asm/io_apic.h>
+ #include <asm/proto.h>
+-#include <asm/acpi.h>
+ #include <asm/bios_ebda.h>
+ #include <asm/e820.h>
+ #include <asm/trampoline.h>
+ #include <asm/setup.h>
++#include <asm/smp.h>
+ 
+ #include <mach_apic.h>
+ #ifdef CONFIG_X86_32
+@@ -54,13 +54,13 @@ static int __init mpf_checksum(unsigned 
+ 	return sum & 0xFF;
+ }
+ 
+-static void __init MP_processor_info(struct mpc_config_processor *m)
++static void __init MP_processor_info(struct mpc_cpu *m)
+ {
+ #ifndef CONFIG_XEN
+ 	int apicid;
+ 	char *bootup_cpu = "";
+ 
+-	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
++	if (!(m->cpuflag & CPU_ENABLED)) {
+ 		disabled_cpus++;
+ 		return;
+ 	}
+@@ -68,57 +68,57 @@ static void __init MP_processor_info(str
+ 	if (x86_quirks->mpc_apic_id)
+ 		apicid = x86_quirks->mpc_apic_id(m);
+ 	else
+-		apicid = m->mpc_apicid;
++		apicid = m->apicid;
+ 
+-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
++	if (m->cpuflag & CPU_BOOTPROCESSOR) {
+ 		bootup_cpu = " (Bootup-CPU)";
+-		boot_cpu_physical_apicid = m->mpc_apicid;
++		boot_cpu_physical_apicid = m->apicid;
+ 	}
+ 
+-	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+-	generic_processor_info(apicid, m->mpc_apicver);
++	printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
++	generic_processor_info(apicid, m->apicver);
+ #else /* CONFIG_XEN */
+ 	num_processors++;
+ #endif
+ }
+ 
+ #ifdef CONFIG_X86_IO_APIC
+-static void __init MP_bus_info(struct mpc_config_bus *m)
++static void __init MP_bus_info(struct mpc_bus *m)
+ {
+ 	char str[7];
+-	memcpy(str, m->mpc_bustype, 6);
++	memcpy(str, m->bustype, 6);
+ 	str[6] = 0;
+ 
+ 	if (x86_quirks->mpc_oem_bus_info)
+ 		x86_quirks->mpc_oem_bus_info(m, str);
+ 	else
+-		apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->mpc_busid, str);
++		apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
+ 
+ #if MAX_MP_BUSSES < 256
+-	if (m->mpc_busid >= MAX_MP_BUSSES) {
++	if (m->busid >= MAX_MP_BUSSES) {
+ 		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ 		       " is too large, max. supported is %d\n",
+-		       m->mpc_busid, str, MAX_MP_BUSSES - 1);
++		       m->busid, str, MAX_MP_BUSSES - 1);
+ 		return;
+ 	}
+ #endif
+ 
+ 	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
+-		 set_bit(m->mpc_busid, mp_bus_not_pci);
+-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
++		set_bit(m->busid, mp_bus_not_pci);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
++		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
+ #endif
+ 	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
+ 		if (x86_quirks->mpc_oem_pci_bus)
+ 			x86_quirks->mpc_oem_pci_bus(m);
+ 
+-		clear_bit(m->mpc_busid, mp_bus_not_pci);
+-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
++		clear_bit(m->busid, mp_bus_not_pci);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
++		mp_bus_id_to_type[m->busid] = MP_BUS_PCI;
+ 	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
++		mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
+ 	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
++		mp_bus_id_to_type[m->busid] = MP_BUS_MCA;
+ #endif
+ 	} else
+ 		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+@@ -142,32 +142,31 @@ static int bad_ioapic(unsigned long addr
+ 	return 0;
+ }
+ 
+-static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
++static void __init MP_ioapic_info(struct mpc_ioapic *m)
+ {
+-	if (!(m->mpc_flags & MPC_APIC_USABLE))
++	if (!(m->flags & MPC_APIC_USABLE))
+ 		return;
+ 
+ 	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+-	       m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
++	       m->apicid, m->apicver, m->apicaddr);
+ 
+-	if (bad_ioapic(m->mpc_apicaddr))
++	if (bad_ioapic(m->apicaddr))
+ 		return;
+ 
+-	mp_ioapics[nr_ioapics].mp_apicaddr = m->mpc_apicaddr;
+-	mp_ioapics[nr_ioapics].mp_apicid = m->mpc_apicid;
+-	mp_ioapics[nr_ioapics].mp_type = m->mpc_type;
+-	mp_ioapics[nr_ioapics].mp_apicver = m->mpc_apicver;
+-	mp_ioapics[nr_ioapics].mp_flags = m->mpc_flags;
++	mp_ioapics[nr_ioapics].mp_apicaddr = m->apicaddr;
++	mp_ioapics[nr_ioapics].mp_apicid = m->apicid;
++	mp_ioapics[nr_ioapics].mp_type = m->type;
++	mp_ioapics[nr_ioapics].mp_apicver = m->apicver;
++	mp_ioapics[nr_ioapics].mp_flags = m->flags;
+ 	nr_ioapics++;
+ }
+ 
+-static void print_MP_intsrc_info(struct mpc_config_intsrc *m)
++static void print_MP_intsrc_info(struct mpc_intsrc *m)
+ {
+ 	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+ 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+-		m->mpc_irqtype, m->mpc_irqflag & 3,
+-		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
+-		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
++		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
++		m->srcbusirq, m->dstapic, m->dstirq);
+ }
+ 
+ static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+@@ -179,52 +178,52 @@ static void __init print_mp_irq_info(str
+ 		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+ }
+ 
+-static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
++static void __init assign_to_mp_irq(struct mpc_intsrc *m,
+ 				    struct mp_config_intsrc *mp_irq)
+ {
+-	mp_irq->mp_dstapic = m->mpc_dstapic;
+-	mp_irq->mp_type = m->mpc_type;
+-	mp_irq->mp_irqtype = m->mpc_irqtype;
+-	mp_irq->mp_irqflag = m->mpc_irqflag;
+-	mp_irq->mp_srcbus = m->mpc_srcbus;
+-	mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+-	mp_irq->mp_dstirq = m->mpc_dstirq;
++	mp_irq->mp_dstapic = m->dstapic;
++	mp_irq->mp_type = m->type;
++	mp_irq->mp_irqtype = m->irqtype;
++	mp_irq->mp_irqflag = m->irqflag;
++	mp_irq->mp_srcbus = m->srcbus;
++	mp_irq->mp_srcbusirq = m->srcbusirq;
++	mp_irq->mp_dstirq = m->dstirq;
+ }
+ 
+ static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+-					struct mpc_config_intsrc *m)
++					struct mpc_intsrc *m)
+ {
+-	m->mpc_dstapic = mp_irq->mp_dstapic;
+-	m->mpc_type = mp_irq->mp_type;
+-	m->mpc_irqtype = mp_irq->mp_irqtype;
+-	m->mpc_irqflag = mp_irq->mp_irqflag;
+-	m->mpc_srcbus = mp_irq->mp_srcbus;
+-	m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+-	m->mpc_dstirq = mp_irq->mp_dstirq;
++	m->dstapic = mp_irq->mp_dstapic;
++	m->type = mp_irq->mp_type;
++	m->irqtype = mp_irq->mp_irqtype;
++	m->irqflag = mp_irq->mp_irqflag;
++	m->srcbus = mp_irq->mp_srcbus;
++	m->srcbusirq = mp_irq->mp_srcbusirq;
++	m->dstirq = mp_irq->mp_dstirq;
+ }
+ 
+ static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+-					struct mpc_config_intsrc *m)
++					struct mpc_intsrc *m)
+ {
+-	if (mp_irq->mp_dstapic != m->mpc_dstapic)
++	if (mp_irq->mp_dstapic != m->dstapic)
+ 		return 1;
+-	if (mp_irq->mp_type != m->mpc_type)
++	if (mp_irq->mp_type != m->type)
+ 		return 2;
+-	if (mp_irq->mp_irqtype != m->mpc_irqtype)
++	if (mp_irq->mp_irqtype != m->irqtype)
+ 		return 3;
+-	if (mp_irq->mp_irqflag != m->mpc_irqflag)
++	if (mp_irq->mp_irqflag != m->irqflag)
+ 		return 4;
+-	if (mp_irq->mp_srcbus != m->mpc_srcbus)
++	if (mp_irq->mp_srcbus != m->srcbus)
+ 		return 5;
+-	if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
++	if (mp_irq->mp_srcbusirq != m->srcbusirq)
+ 		return 6;
+-	if (mp_irq->mp_dstirq != m->mpc_dstirq)
++	if (mp_irq->mp_dstirq != m->dstirq)
+ 		return 7;
+ 
+ 	return 0;
+ }
+ 
+-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
++static void __init MP_intsrc_info(struct mpc_intsrc *m)
+ {
+ 	int i;
+ 
+@@ -242,57 +241,55 @@ static void __init MP_intsrc_info(struct
+ 
+ #endif
+ 
+-static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
++static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
+ {
+ 	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
+ 		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+-		m->mpc_irqtype, m->mpc_irqflag & 3,
+-		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
+-		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
++		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
++		m->srcbusirq, m->destapic, m->destapiclint);
+ }
+ 
+ /*
+  * Read/parse the MPC
+  */
+ 
+-static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+-				char *str)
++static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
+ {
+ 
+-	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
++	if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
+ 		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+-		       mpc->mpc_signature[0], mpc->mpc_signature[1],
+-		       mpc->mpc_signature[2], mpc->mpc_signature[3]);
++		       mpc->signature[0], mpc->signature[1],
++		       mpc->signature[2], mpc->signature[3]);
+ 		return 0;
+ 	}
+-	if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
++	if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
+ 		printk(KERN_ERR "MPTABLE: checksum error!\n");
+ 		return 0;
+ 	}
+-	if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
++	if (mpc->spec != 0x01 && mpc->spec != 0x04) {
+ 		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+-		       mpc->mpc_spec);
++		       mpc->spec);
+ 		return 0;
+ 	}
+-	if (!mpc->mpc_lapic) {
++	if (!mpc->lapic) {
+ 		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+ 		return 0;
+ 	}
+-	memcpy(oem, mpc->mpc_oem, 8);
++	memcpy(oem, mpc->oem, 8);
+ 	oem[8] = 0;
+ 	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+ 
+-	memcpy(str, mpc->mpc_productid, 12);
++	memcpy(str, mpc->productid, 12);
+ 	str[12] = 0;
+ 
+ 	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ 
+-	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
++	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+ 
+ 	return 1;
+ }
+ 
+-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
++static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+ {
+ 	char str[16];
+ 	char oem[10];
+@@ -317,14 +314,14 @@ static int __init smp_read_mpc(struct mp
+ #endif
+ 	/* save the local APIC address, it might be non-default */
+ 	if (!acpi_lapic)
+-		mp_lapic_addr = mpc->mpc_lapic;
++		mp_lapic_addr = mpc->lapic;
+ 
+ 	if (early)
+ 		return 1;
+ 
+-	if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) {
+-		struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
+-		x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
++	if (mpc->oemptr && x86_quirks->smp_read_mpc_oem) {
++		struct mpc_oemtable *oem_table = (void *)(long)mpc->oemptr;
++		x86_quirks->smp_read_mpc_oem(oem_table, mpc->oemsize);
+ 	}
+ 
+ 	/*
+@@ -333,12 +330,11 @@ static int __init smp_read_mpc(struct mp
+ 	if (x86_quirks->mpc_record)
+ 		*x86_quirks->mpc_record = 0;
+ 
+-	while (count < mpc->mpc_length) {
++	while (count < mpc->length) {
+ 		switch (*mpt) {
+ 		case MP_PROCESSOR:
+ 			{
+-				struct mpc_config_processor *m =
+-				    (struct mpc_config_processor *)mpt;
++				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
+ 				/* ACPI may have already provided this data */
+ 				if (!acpi_lapic)
+ 					MP_processor_info(m);
+@@ -348,8 +344,7 @@ static int __init smp_read_mpc(struct mp
+ 			}
+ 		case MP_BUS:
+ 			{
+-				struct mpc_config_bus *m =
+-				    (struct mpc_config_bus *)mpt;
++				struct mpc_bus *m = (struct mpc_bus *)mpt;
+ #ifdef CONFIG_X86_IO_APIC
+ 				MP_bus_info(m);
+ #endif
+@@ -360,30 +355,28 @@ static int __init smp_read_mpc(struct mp
+ 		case MP_IOAPIC:
+ 			{
+ #ifdef CONFIG_X86_IO_APIC
+-				struct mpc_config_ioapic *m =
+-				    (struct mpc_config_ioapic *)mpt;
++				struct mpc_ioapic *m = (struct mpc_ioapic *)mpt;
+ 				MP_ioapic_info(m);
+ #endif
+-				mpt += sizeof(struct mpc_config_ioapic);
+-				count += sizeof(struct mpc_config_ioapic);
++				mpt += sizeof(struct mpc_ioapic);
++				count += sizeof(struct mpc_ioapic);
+ 				break;
+ 			}
+ 		case MP_INTSRC:
+ 			{
+ #ifdef CONFIG_X86_IO_APIC
+-				struct mpc_config_intsrc *m =
+-				    (struct mpc_config_intsrc *)mpt;
++				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+ 
+ 				MP_intsrc_info(m);
+ #endif
+-				mpt += sizeof(struct mpc_config_intsrc);
+-				count += sizeof(struct mpc_config_intsrc);
++				mpt += sizeof(struct mpc_intsrc);
++				count += sizeof(struct mpc_intsrc);
+ 				break;
+ 			}
+ 		case MP_LINTSRC:
+ 			{
+-				struct mpc_config_lintsrc *m =
+-				    (struct mpc_config_lintsrc *)mpt;
++				struct mpc_lintsrc *m =
++				    (struct mpc_lintsrc *)mpt;
+ 				MP_lintsrc_info(m);
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+@@ -394,8 +387,8 @@ static int __init smp_read_mpc(struct mp
+ 			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+ 			printk(KERN_ERR "type %x\n", *mpt);
+ 			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+-					1, mpc, mpc->mpc_length, 1);
+-			count = mpc->mpc_length;
++					1, mpc, mpc->length, 1);
++			count = mpc->length;
+ 			break;
+ 		}
+ 		if (x86_quirks->mpc_record)
+@@ -426,16 +419,16 @@ static int __init ELCR_trigger(unsigned 
+ 
+ static void __init construct_default_ioirq_mptable(int mpc_default_type)
+ {
+-	struct mpc_config_intsrc intsrc;
++	struct mpc_intsrc intsrc;
+ 	int i;
+ 	int ELCR_fallback = 0;
+ 
+-	intsrc.mpc_type = MP_INTSRC;
+-	intsrc.mpc_irqflag = 0;	/* conforming */
+-	intsrc.mpc_srcbus = 0;
+-	intsrc.mpc_dstapic = mp_ioapics[0].mp_apicid;
++	intsrc.type = MP_INTSRC;
++	intsrc.irqflag = 0;	/* conforming */
++	intsrc.srcbus = 0;
++	intsrc.dstapic = mp_ioapics[0].mp_apicid;
+ 
+-	intsrc.mpc_irqtype = mp_INT;
++	intsrc.irqtype = mp_INT;
+ 
+ 	/*
+ 	 *  If true, we have an ISA/PCI system with no IRQ entries
+@@ -478,30 +471,30 @@ static void __init construct_default_ioi
+ 			 *  irqflag field (level sensitive, active high polarity).
+ 			 */
+ 			if (ELCR_trigger(i))
+-				intsrc.mpc_irqflag = 13;
++				intsrc.irqflag = 13;
+ 			else
+-				intsrc.mpc_irqflag = 0;
++				intsrc.irqflag = 0;
+ 		}
+ 
+-		intsrc.mpc_srcbusirq = i;
+-		intsrc.mpc_dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
++		intsrc.srcbusirq = i;
++		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
+ 		MP_intsrc_info(&intsrc);
+ 	}
+ 
+-	intsrc.mpc_irqtype = mp_ExtINT;
+-	intsrc.mpc_srcbusirq = 0;
+-	intsrc.mpc_dstirq = 0;	/* 8259A to INTIN0 */
++	intsrc.irqtype = mp_ExtINT;
++	intsrc.srcbusirq = 0;
++	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
+ 	MP_intsrc_info(&intsrc);
+ }
+ 
+ 
+ static void __init construct_ioapic_table(int mpc_default_type)
+ {
+-	struct mpc_config_ioapic ioapic;
+-	struct mpc_config_bus bus;
++	struct mpc_ioapic ioapic;
++	struct mpc_bus bus;
+ 
+-	bus.mpc_type = MP_BUS;
+-	bus.mpc_busid = 0;
++	bus.type = MP_BUS;
++	bus.busid = 0;
+ 	switch (mpc_default_type) {
+ 	default:
+ 		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+@@ -509,29 +502,29 @@ static void __init construct_ioapic_tabl
+ 		/* fall through */
+ 	case 1:
+ 	case 5:
+-		memcpy(bus.mpc_bustype, "ISA   ", 6);
++		memcpy(bus.bustype, "ISA   ", 6);
+ 		break;
+ 	case 2:
+ 	case 6:
+ 	case 3:
+-		memcpy(bus.mpc_bustype, "EISA  ", 6);
++		memcpy(bus.bustype, "EISA  ", 6);
+ 		break;
+ 	case 4:
+ 	case 7:
+-		memcpy(bus.mpc_bustype, "MCA   ", 6);
++		memcpy(bus.bustype, "MCA   ", 6);
+ 	}
+ 	MP_bus_info(&bus);
+ 	if (mpc_default_type > 4) {
+-		bus.mpc_busid = 1;
+-		memcpy(bus.mpc_bustype, "PCI   ", 6);
++		bus.busid = 1;
++		memcpy(bus.bustype, "PCI   ", 6);
+ 		MP_bus_info(&bus);
+ 	}
+ 
+-	ioapic.mpc_type = MP_IOAPIC;
+-	ioapic.mpc_apicid = 2;
+-	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	ioapic.mpc_flags = MPC_APIC_USABLE;
+-	ioapic.mpc_apicaddr = 0xFEC00000;
++	ioapic.type = MP_IOAPIC;
++	ioapic.apicid = 2;
++	ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	ioapic.flags = MPC_APIC_USABLE;
++	ioapic.apicaddr = 0xFEC00000;
+ 	MP_ioapic_info(&ioapic);
+ 
+ 	/*
+@@ -545,8 +538,8 @@ static inline void __init construct_ioap
+ 
+ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+ {
+-	struct mpc_config_processor processor;
+-	struct mpc_config_lintsrc lintsrc;
++	struct mpc_cpu processor;
++	struct mpc_lintsrc lintsrc;
+ 	int linttypes[2] = { mp_ExtINT, mp_NMI };
+ 	int i;
+ 
+@@ -558,30 +551,30 @@ static inline void __init construct_defa
+ 	/*
+ 	 * 2 CPUs, numbered 0 & 1.
+ 	 */
+-	processor.mpc_type = MP_PROCESSOR;
++	processor.type = MP_PROCESSOR;
+ 	/* Either an integrated APIC or a discrete 82489DX. */
+-	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+-	processor.mpc_cpuflag = CPU_ENABLED;
+-	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
++	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
++	processor.cpuflag = CPU_ENABLED;
++	processor.cpufeature = (boot_cpu_data.x86 << 8) |
+ 	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+-	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+-	processor.mpc_reserved[0] = 0;
+-	processor.mpc_reserved[1] = 0;
++	processor.featureflag = boot_cpu_data.x86_capability[0];
++	processor.reserved[0] = 0;
++	processor.reserved[1] = 0;
+ 	for (i = 0; i < 2; i++) {
+-		processor.mpc_apicid = i;
++		processor.apicid = i;
+ 		MP_processor_info(&processor);
+ 	}
+ 
+ 	construct_ioapic_table(mpc_default_type);
+ 
+-	lintsrc.mpc_type = MP_LINTSRC;
+-	lintsrc.mpc_irqflag = 0;	/* conforming */
+-	lintsrc.mpc_srcbusid = 0;
+-	lintsrc.mpc_srcbusirq = 0;
+-	lintsrc.mpc_destapic = MP_APIC_ALL;
++	lintsrc.type = MP_LINTSRC;
++	lintsrc.irqflag = 0;		/* conforming */
++	lintsrc.srcbusid = 0;
++	lintsrc.srcbusirq = 0;
++	lintsrc.destapic = MP_APIC_ALL;
+ 	for (i = 0; i < 2; i++) {
+-		lintsrc.mpc_irqtype = linttypes[i];
+-		lintsrc.mpc_destapiclint = i;
++		lintsrc.irqtype = linttypes[i];
++		lintsrc.destapiclint = i;
+ 		MP_lintsrc_info(&lintsrc);
+ 	}
+ }
+@@ -595,26 +588,23 @@ static void __init __get_smp_config(unsi
+ {
+ 	struct intel_mp_floating *mpf = mpf_found;
+ 
+-	if (x86_quirks->mach_get_smp_config) {
+-		if (x86_quirks->mach_get_smp_config(early))
+-			return;
+-	}
++	if (!mpf)
++		return;
++
+ 	if (acpi_lapic && early)
+ 		return;
++
+ 	/*
+-	 * ACPI supports both logical (e.g. Hyper-Threading) and physical
+-	 * processors, where MPS only supports physical.
++	 * MPS doesn't support hyperthreading, aka only have
++	 * thread 0 apic id in MPS table
+ 	 */
+-	if (acpi_lapic && acpi_ioapic) {
+-		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
+-		       "information\n");
++	if (acpi_lapic && acpi_ioapic)
+ 		return;
+-	} else if (acpi_lapic)
+-		printk(KERN_INFO "Using ACPI for processor (LAPIC) "
+-		       "configuration information\n");
+ 
+-	if (!mpf)
+-		return;
++	if (x86_quirks->mach_get_smp_config) {
++		if (x86_quirks->mach_get_smp_config(early))
++			return;
++	}
+ 
+ 	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+ 	       mpf->mpf_specification);
+@@ -669,15 +659,15 @@ static void __init __get_smp_config(unsi
+ 		 * ISA defaults and hope it will work.
+ 		 */
+ 		if (!mp_irq_entries) {
+-			struct mpc_config_bus bus;
++			struct mpc_bus bus;
+ 
+ 			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
+ 			       "using default mptable. "
+ 			       "(tell your hw vendor)\n");
+ 
+-			bus.mpc_type = MP_BUS;
+-			bus.mpc_busid = 0;
+-			memcpy(bus.mpc_bustype, "ISA   ", 6);
++			bus.type = MP_BUS;
++			bus.busid = 0;
++			memcpy(bus.bustype, "ISA   ", 6);
+ 			MP_bus_info(&bus);
+ 
+ 			construct_default_ioirq_mptable(0);
+@@ -823,14 +813,14 @@ void __init find_smp_config(void)
+ #ifdef CONFIG_X86_IO_APIC
+ static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+ 
+-static int  __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
++static int  __init get_MP_intsrc_index(struct mpc_intsrc *m)
+ {
+ 	int i;
+ 
+-	if (m->mpc_irqtype != mp_INT)
++	if (m->irqtype != mp_INT)
+ 		return 0;
+ 
+-	if (m->mpc_irqflag != 0x0f)
++	if (m->irqflag != 0x0f)
+ 		return 0;
+ 
+ 	/* not legacy */
+@@ -842,9 +832,9 @@ static int  __init get_MP_intsrc_index(s
+ 		if (mp_irqs[i].mp_irqflag != 0x0f)
+ 			continue;
+ 
+-		if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
++		if (mp_irqs[i].mp_srcbus != m->srcbus)
+ 			continue;
+-		if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
++		if (mp_irqs[i].mp_srcbusirq != m->srcbusirq)
+ 			continue;
+ 		if (irq_used[i]) {
+ 			/* already claimed */
+@@ -860,10 +850,10 @@ static int  __init get_MP_intsrc_index(s
+ 
+ #define SPARE_SLOT_NUM 20
+ 
+-static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
++static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+ #endif
+ 
+-static int  __init replace_intsrc_all(struct mp_config_table *mpc,
++static int  __init replace_intsrc_all(struct mpc_table *mpc,
+ 					unsigned long mpc_new_phys,
+ 					unsigned long mpc_new_length)
+ {
+@@ -875,36 +865,33 @@ static int  __init replace_intsrc_all(st
+ 	int count = sizeof(*mpc);
+ 	unsigned char *mpt = ((unsigned char *)mpc) + count;
+ 
+-	printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+-	while (count < mpc->mpc_length) {
++	printk(KERN_INFO "mpc_length %x\n", mpc->length);
++	while (count < mpc->length) {
+ 		switch (*mpt) {
+ 		case MP_PROCESSOR:
+ 			{
+-				struct mpc_config_processor *m =
+-				    (struct mpc_config_processor *)mpt;
++				struct mpc_cpu *m = (struct mpc_cpu *)mpt;
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+ 				break;
+ 			}
+ 		case MP_BUS:
+ 			{
+-				struct mpc_config_bus *m =
+-				    (struct mpc_config_bus *)mpt;
++				struct mpc_bus *m = (struct mpc_bus *)mpt;
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+ 				break;
+ 			}
+ 		case MP_IOAPIC:
+ 			{
+-				mpt += sizeof(struct mpc_config_ioapic);
+-				count += sizeof(struct mpc_config_ioapic);
++				mpt += sizeof(struct mpc_ioapic);
++				count += sizeof(struct mpc_ioapic);
+ 				break;
+ 			}
+ 		case MP_INTSRC:
+ 			{
+ #ifdef CONFIG_X86_IO_APIC
+-				struct mpc_config_intsrc *m =
+-				    (struct mpc_config_intsrc *)mpt;
++				struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+ 
+ 				apic_printk(APIC_VERBOSE, "OLD ");
+ 				print_MP_intsrc_info(m);
+@@ -925,14 +912,14 @@ static int  __init replace_intsrc_all(st
+ 					nr_m_spare++;
+ 				}
+ #endif
+-				mpt += sizeof(struct mpc_config_intsrc);
+-				count += sizeof(struct mpc_config_intsrc);
++				mpt += sizeof(struct mpc_intsrc);
++				count += sizeof(struct mpc_intsrc);
+ 				break;
+ 			}
+ 		case MP_LINTSRC:
+ 			{
+-				struct mpc_config_lintsrc *m =
+-				    (struct mpc_config_lintsrc *)mpt;
++				struct mpc_lintsrc *m =
++				    (struct mpc_lintsrc *)mpt;
+ 				mpt += sizeof(*m);
+ 				count += sizeof(*m);
+ 				break;
+@@ -942,7 +929,7 @@ static int  __init replace_intsrc_all(st
+ 			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+ 			printk(KERN_ERR "type %x\n", *mpt);
+ 			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+-					1, mpc, mpc->mpc_length, 1);
++					1, mpc, mpc->length, 1);
+ 			goto out;
+ 		}
+ 	}
+@@ -964,9 +951,8 @@ static int  __init replace_intsrc_all(st
+ 			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+ 			m_spare[nr_m_spare] = NULL;
+ 		} else {
+-			struct mpc_config_intsrc *m =
+-			    (struct mpc_config_intsrc *)mpt;
+-			count += sizeof(struct mpc_config_intsrc);
++			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
++			count += sizeof(struct mpc_intsrc);
+ 			if (!mpc_new_phys) {
+ 				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+ 			} else {
+@@ -978,17 +964,16 @@ static int  __init replace_intsrc_all(st
+ 				}
+ 			}
+ 			assign_to_mpc_intsrc(&mp_irqs[i], m);
+-			mpc->mpc_length = count;
+-			mpt += sizeof(struct mpc_config_intsrc);
++			mpc->length = count;
++			mpt += sizeof(struct mpc_intsrc);
+ 		}
+ 		print_mp_irq_info(&mp_irqs[i]);
+ 	}
+ #endif
+ out:
+ 	/* update checksum */
+-	mpc->mpc_checksum = 0;
+-	mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+-					   mpc->mpc_length);
++	mpc->checksum = 0;
++	mpc->checksum -= mpf_checksum((unsigned char *)mpc, mpc->length);
+ 
+ 	return 0;
+ }
+@@ -1034,8 +1019,7 @@ static int __init update_mp_table(void)
+ 	char str[16];
+ 	char oem[10];
+ 	struct intel_mp_floating *mpf;
+-	struct mp_config_table *mpc;
+-	struct mp_config_table *mpc_new;
++	struct mpc_table *mpc, *mpc_new;
+ 
+ 	if (!enable_update_mptable)
+ 		return 0;
+@@ -1061,7 +1045,7 @@ static int __init update_mp_table(void)
+ 	printk(KERN_INFO "mpf: %lx\n", (long)arbitrary_virt_to_machine(mpf));
+ 	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+ 
+-	if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
++	if (mpc_new_phys && mpc->length > mpc_new_length) {
+ 		mpc_new_phys = 0;
+ 		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ 			 mpc_new_length);
+@@ -1070,10 +1054,10 @@ static int __init update_mp_table(void)
+ 	if (!mpc_new_phys) {
+ 		unsigned char old, new;
+ 		/* check if we can change the postion */
+-		mpc->mpc_checksum = 0;
+-		old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+-		mpc->mpc_checksum = 0xff;
+-		new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
++		mpc->checksum = 0;
++		old = mpf_checksum((unsigned char *)mpc, mpc->length);
++		mpc->checksum = 0xff;
++		new = mpf_checksum((unsigned char *)mpc, mpc->length);
+ 		if (old == new) {
+ 			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ 			return 0;
+@@ -1085,7 +1069,7 @@ static int __init update_mp_table(void)
+ 		mpc_new_bus = phys_to_machine(mpc_new_phys);
+ 		mpf->mpf_physptr = mpc_new_bus;
+ 		mpc_new = phys_to_virt(mpc_new_phys);
+-		memcpy(mpc_new, mpc, mpc->mpc_length);
++		memcpy(mpc_new, mpc, mpc->length);
+ 		mpc = mpc_new;
+ 		/* check if we can modify that */
+ 		if (mpc_new_bus - mpf->mpf_physptr) {
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -6,6 +6,7 @@
+ #include <asm/proto.h>
+ #include <asm/dma.h>
+ #include <asm/iommu.h>
++#include <asm/gart.h>
+ #include <asm/calgary.h>
+ #include <asm/amd_iommu.h>
+ 
+@@ -30,11 +31,6 @@ int no_iommu __read_mostly;
+ /* Set this to 1 if there is a HW IOMMU in the system */
+ int iommu_detected __read_mostly = 0;
+ 
+-/* This tells the BIO block layer to assume merging. Default to off
+-   because we cannot guarantee merging later. */
+-int iommu_bio_merge __read_mostly = 0;
+-EXPORT_SYMBOL(iommu_bio_merge);
+-
+ dma_addr_t bad_dma_address __read_mostly = 0;
+ EXPORT_SYMBOL(bad_dma_address);
+ 
+@@ -42,7 +38,7 @@ EXPORT_SYMBOL(bad_dma_address);
+    be probably a smaller DMA mask, but this is bug-to-bug compatible
+    to older i386. */
+ struct device x86_dma_fallback_dev = {
+-	.bus_id = "fallback device",
++	.init_name = "fallback device",
+ 	.coherent_dma_mask = DMA_32BIT_MASK,
+ 	.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
+ };
+@@ -105,8 +101,6 @@ static void __init dma32_free_bootmem(vo
+ 	dma32_bootmem_ptr = NULL;
+ 	dma32_bootmem_size = 0;
+ }
+-#else
+-#define dma32_free_bootmem() ((void)0)
+ #endif
+ 
+ static struct dma_mapping_ops swiotlb_dma_ops = {
+@@ -128,8 +122,11 @@ static struct dma_mapping_ops swiotlb_dm
+ 
+ void __init pci_iommu_alloc(void)
+ {
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+ 	/* free the range so iommu could get some range less than 4G */
+ 	dma32_free_bootmem();
++#endif
++
+ 	/*
+ 	 * The order of these functions is important for
+ 	 * fall-back/fail-over reasons
+@@ -149,16 +146,6 @@ void __init pci_iommu_alloc(void)
+ 	}
+ }
+ 
+-#ifndef CONFIG_XEN
+-unsigned long iommu_nr_pages(unsigned long addr, unsigned long len)
+-{
+-	unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
+-
+-	return size >> PAGE_SHIFT;
+-}
+-EXPORT_SYMBOL(iommu_nr_pages);
+-#endif
+-
+ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
+ 				 dma_addr_t *dma_addr, gfp_t flag)
+ {
+@@ -246,7 +233,6 @@ static __init int iommu_setup(char *p)
+ 		}
+ 
+ 		if (!strncmp(p, "biomerge", 8)) {
+-			iommu_bio_merge = 4096;
+ 			iommu_merge = 1;
+ 			force_iommu = 1;
+ 		}
+@@ -385,8 +371,8 @@ fs_initcall(pci_iommu_init);
+ static __devinit void via_no_dac(struct pci_dev *dev)
+ {
+ 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+-		printk(KERN_INFO "PCI: VIA PCI bridge detected."
+-				 "Disabling DAC.\n");
++		printk(KERN_INFO
++			"PCI: VIA PCI bridge detected. Disabling DAC.\n");
+ 		forbid_dac = 1;
+ 	}
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -1,13 +1,17 @@
+ #include <linux/errno.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
++#include <asm/idle.h>
+ #include <linux/smp.h>
+ #include <linux/slab.h>
+ #include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/pm.h>
+ #include <linux/clockchips.h>
++#include <linux/ftrace.h>
+ #include <asm/system.h>
++#include <asm/apic.h>
++#include <xen/evtchn.h>
+ 
+ unsigned long idle_halt;
+ EXPORT_SYMBOL(idle_halt);
+@@ -99,6 +103,9 @@ static inline int hlt_use_halt(void)
+  */
+ void xen_idle(void)
+ {
++	struct power_trace it;
++
++	trace_power_start(&it, POWER_CSTATE, 1);
+ 	current_thread_info()->status &= ~TS_POLLING;
+ 	/*
+ 	 * TS_POLLING-cleared state must be visible before we
+@@ -111,11 +118,27 @@ void xen_idle(void)
+ 	else
+ 		local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
++	trace_power_end(&it);
+ }
+ #ifdef CONFIG_APM_MODULE
+ EXPORT_SYMBOL(default_idle);
+ #endif
+ 
++void stop_this_cpu(void *dummy)
++{
++	local_irq_disable();
++	/*
++	 * Remove this CPU:
++	 */
++	cpu_clear(smp_processor_id(), cpu_online_map);
++	disable_all_local_evtchn();
++
++	for (;;) {
++		if (hlt_works(smp_processor_id()))
++			halt();
++	}
++}
++
+ static void do_nothing(void *unused)
+ {
+ }
+@@ -149,24 +172,37 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+  */
+ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+ {
++	struct power_trace it;
++
++	trace_power_start(&it, POWER_CSTATE, (ax>>4)+1);
+ 	if (!need_resched()) {
++		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
++			clflush((void *)&current_thread_info()->flags);
++
+ 		__monitor((void *)&current_thread_info()->flags, 0, 0);
+ 		smp_mb();
+ 		if (!need_resched())
+ 			__mwait(ax, cx);
+ 	}
++	trace_power_end(&it);
+ }
+ 
+ /* Default MONITOR/MWAIT with no hints, used for default C1 state */
+ static void mwait_idle(void)
+ {
++	struct power_trace it;
+ 	if (!need_resched()) {
++		trace_power_start(&it, POWER_CSTATE, 1);
++		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
++			clflush((void *)&current_thread_info()->flags);
++
+ 		__monitor((void *)&current_thread_info()->flags, 0, 0);
+ 		smp_mb();
+ 		if (!need_resched())
+ 			__sti_mwait(0, 0);
+ 		else
+ 			local_irq_enable();
++		trace_power_end(&it);
+ 	} else
+ 		local_irq_enable();
+ }
+@@ -179,9 +215,13 @@ static void mwait_idle(void)
+  */
+ static void poll_idle(void)
+ {
++	struct power_trace it;
++
++	trace_power_start(&it, POWER_CSTATE, 0);
+ 	local_irq_enable();
+ 	while (!need_resched())
+ 		cpu_relax();
++	trace_power_end(&it);
+ }
+ 
+ #ifndef CONFIG_XEN
+@@ -267,7 +307,7 @@ static void c1e_idle(void)
+ 		rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
+ 		if (lo & K8_INTP_C1E_ACTIVE_MASK) {
+ 			c1e_detected = 1;
+-			if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
++			if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ 				mark_tsc_unstable("TSC halt in AMD C1E");
+ 			printk(KERN_INFO "System has AMD C1E enabled\n");
+ 			set_cpu_cap(&boot_cpu_data, X86_FEATURE_AMDC1E);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -38,11 +38,13 @@
+ #include <linux/percpu.h>
+ #include <linux/prctl.h>
+ #include <linux/dmi.h>
++#include <linux/ftrace.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
++#include <linux/kdebug.h>
+ 
+-#include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+-#include <asm/io.h>
+ #include <asm/ldt.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+@@ -59,10 +61,9 @@
+ 
+ #include <asm/tlbflush.h>
+ #include <asm/cpu.h>
+-#include <asm/kdebug.h>
+ #include <asm/idle.h>
+ #include <asm/syscalls.h>
+-#include <asm/smp.h>
++#include <asm/ds.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+@@ -108,9 +109,6 @@ void cpu_idle(void)
+ 			check_pgt_cache();
+ 			rmb();
+ 
+-			if (rcu_pending(cpu))
+-				rcu_check_callbacks(cpu, 0);
+-
+ 			if (cpu_is_offline(cpu))
+ 				play_dead();
+ 
+@@ -208,7 +206,7 @@ extern void kernel_thread_helper(void);
+ /*
+  * Create a kernel thread
+  */
+-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
++int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+ {
+ 	struct pt_regs regs;
+ 
+@@ -247,14 +245,8 @@ void exit_thread(void)
+ 		t->io_bitmap_ptr = NULL;
+ 		clear_thread_flag(TIF_IO_BITMAP);
+ 	}
+-#ifdef CONFIG_X86_DS
+-	/* Free any DS contexts that have not been properly released. */
+-	if (unlikely(current->thread.ds_ctx)) {
+-		/* we clear debugctl to make sure DS is not used. */
+-		update_debugctlmsr(0);
+-		ds_free(current->thread.ds_ctx);
+-	}
+-#endif /* CONFIG_X86_DS */
++
++	ds_exit_thread(current);
+ }
+ 
+ void flush_thread(void)
+@@ -267,7 +259,7 @@ void flush_thread(void)
+ 	tsk->thread.debugreg3 = 0;
+ 	tsk->thread.debugreg6 = 0;
+ 	tsk->thread.debugreg7 = 0;
+-	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
++	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+ 	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+ 	/*
+ 	 * Forget coprocessor state..
+@@ -294,9 +286,9 @@ void prepare_to_copy(struct task_struct 
+ 
+ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 	unsigned long unused,
+-	struct task_struct * p, struct pt_regs * regs)
++	struct task_struct *p, struct pt_regs *regs)
+ {
+-	struct pt_regs * childregs;
++	struct pt_regs *childregs;
+ 	struct task_struct *tsk;
+ 	int err;
+ 
+@@ -340,13 +332,19 @@ int copy_thread(int nr, unsigned long cl
+ 		kfree(p->thread.io_bitmap_ptr);
+ 		p->thread.io_bitmap_max = 0;
+ 	}
++
++	ds_copy_thread(p, current);
++
++	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
++	p->thread.debugctlmsr = 0;
++
+ 	return err;
+ }
+ 
+ void
+ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+ {
+-	__asm__("movl %0, %%gs" :: "r"(0));
++	__asm__("movl %0, %%gs" : : "r"(0));
+ 	regs->fs		= 0;
+ 	set_fs(USER_DS);
+ 	regs->ds		= __USER_DS;
+@@ -420,47 +418,18 @@ int set_tsc_mode(unsigned int val)
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_X86_DS
+-static int update_debugctl(struct thread_struct *prev,
+-			struct thread_struct *next, unsigned long debugctl)
+-{
+-	unsigned long ds_prev = 0;
+-	unsigned long ds_next = 0;
+-
+-	if (prev->ds_ctx)
+-		ds_prev = (unsigned long)prev->ds_ctx->ds;
+-	if (next->ds_ctx)
+-		ds_next = (unsigned long)next->ds_ctx->ds;
+-
+-	if (ds_next != ds_prev) {
+-		/* we clear debugctl to make sure DS
+-		 * is not in use when we change it */
+-		debugctl = 0;
+-		update_debugctlmsr(0);
+-		wrmsr(MSR_IA32_DS_AREA, ds_next, 0);
+-	}
+-	return debugctl;
+-}
+-#else
+-static int update_debugctl(struct thread_struct *prev,
+-			struct thread_struct *next, unsigned long debugctl)
+-{
+-	return debugctl;
+-}
+-#endif /* CONFIG_X86_DS */
+-
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev, *next;
+-	unsigned long debugctl;
+ 
+ 	prev = &prev_p->thread;
+ 	next = &next_p->thread;
+ 
+-	debugctl = update_debugctl(prev, next, prev->debugctlmsr);
+-
+-	if (next->debugctlmsr != debugctl)
++	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
++	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
++		ds_switch_to(prev_p, next_p);
++	else if (next->debugctlmsr != prev->debugctlmsr)
+ 		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+@@ -481,14 +450,6 @@ __switch_to_xtra(struct task_struct *pre
+ 		else
+ 			hard_enable_TSC();
+ 	}
+-
+-#ifdef CONFIG_X86_PTRACE_BTS
+-	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+-		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
+-
+-	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
+-		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
+-#endif /* CONFIG_X86_PTRACE_BTS */
+ }
+ 
+ /*
+@@ -518,7 +479,8 @@ __switch_to_xtra(struct task_struct *pre
+  * the task-switch, and shows up in ret_from_fork in entry.S,
+  * for example.
+  */
+-struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
++__notrace_funcgraph struct task_struct *
++__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev = &prev_p->thread,
+ 				 *next = &next_p->thread;
+@@ -698,7 +660,7 @@ asmlinkage int sys_vfork(struct pt_regs 
+ asmlinkage int sys_execve(struct pt_regs regs)
+ {
+ 	int error;
+-	char * filename;
++	char *filename;
+ 
+ 	filename = getname((char __user *) regs.bx);
+ 	error = PTR_ERR(filename);
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -42,6 +42,8 @@
+ #include <linux/prctl.h>
+ #include <linux/uaccess.h>
+ #include <linux/io.h>
++#include <linux/ftrace.h>
++#include <linux/dmi.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -59,6 +61,7 @@
+ #include <asm/ia32.h>
+ #include <asm/idle.h>
+ #include <asm/syscalls.h>
++#include <asm/ds.h>
+ 
+ #include <xen/cpu_hotplug.h>
+ 
+@@ -158,14 +161,18 @@ void __show_regs(struct pt_regs *regs, i
+ 	unsigned long d0, d1, d2, d3, d6, d7;
+ 	unsigned int fsindex, gsindex;
+ 	unsigned int ds, cs, es;
++	const char *board;
+ 
+ 	printk("\n");
+ 	print_modules();
+-	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n",
++	board = dmi_get_system_info(DMI_PRODUCT_NAME);
++	if (!board)
++		board = "";
++	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n",
+ 		current->pid, current->comm, print_tainted(),
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+-		init_utsname()->version);
++		init_utsname()->version, board);
+ 	printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+ 	printk_address(regs->ip, 1);
+ 	printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
+@@ -256,14 +263,8 @@ void exit_thread(void)
+ #endif
+ 		t->io_bitmap_max = 0;
+ 	}
+-#ifdef CONFIG_X86_DS
+-	/* Free any DS contexts that have not been properly released. */
+-	if (unlikely(t->ds_ctx)) {
+-		/* we clear debugctl to make sure DS is not used. */
+-		update_debugctlmsr(0);
+-		ds_free(t->ds_ctx);
+-	}
+-#endif /* CONFIG_X86_DS */
++
++	ds_exit_thread(current);
+ }
+ 
+ void xen_load_gs_index(unsigned gs)
+@@ -400,6 +401,11 @@ int copy_thread(int nr, unsigned long cl
+ 	}
+         p->thread.iopl = current->thread.iopl;
+ 
++	ds_copy_thread(p, me);
++
++	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
++	p->thread.debugctlmsr = 0;
++
+ 	err = 0;
+ out:
+ 	if (err && p->thread.io_bitmap_ptr) {
+@@ -497,35 +503,14 @@ static inline void __switch_to_xtra(stru
+ 				    struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev, *next;
+-	unsigned long debugctl;
+ 
+ 	prev = &prev_p->thread,
+ 	next = &next_p->thread;
+ 
+-	debugctl = prev->debugctlmsr;
+-
+-#ifdef CONFIG_X86_DS
+-	{
+-		unsigned long ds_prev = 0, ds_next = 0;
+-
+-		if (prev->ds_ctx)
+-			ds_prev = (unsigned long)prev->ds_ctx->ds;
+-		if (next->ds_ctx)
+-			ds_next = (unsigned long)next->ds_ctx->ds;
+-
+-		if (ds_next != ds_prev) {
+-			/*
+-			 * We clear debugctl to make sure DS
+-			 * is not in use when we change it:
+-			 */
+-			debugctl = 0;
+-			update_debugctlmsr(0);
+-			wrmsrl(MSR_IA32_DS_AREA, ds_next);
+-		}
+-	}
+-#endif /* CONFIG_X86_DS */
+-
+-	if (next->debugctlmsr != debugctl)
++	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
++	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
++		ds_switch_to(prev_p, next_p);
++	else if (next->debugctlmsr != prev->debugctlmsr)
+ 		update_debugctlmsr(next->debugctlmsr);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+@@ -546,14 +531,6 @@ static inline void __switch_to_xtra(stru
+ 		else
+ 			hard_enable_TSC();
+ 	}
+-
+-#ifdef CONFIG_X86_PTRACE_BTS
+-	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+-		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
+-
+-	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
+-		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
+-#endif /* CONFIG_X86_PTRACE_BTS */
+ }
+ 
+ /*
+@@ -564,8 +541,9 @@ static inline void __switch_to_xtra(stru
+  * - could test fs/gs bitsliced
+  *
+  * Kprobes not supported here. Set the probe on schedule instead.
++ * Function graph tracer not supported too.
+  */
+-struct task_struct *
++__notrace_funcgraph struct task_struct *
+ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev = &prev_p->thread;
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -169,6 +169,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
+ 			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
+ 			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4,
++			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
+ 			 ich_force_enable_hpet);
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -93,11 +93,13 @@
+ #include <asm/desc.h>
+ #include <asm/dma.h>
+ #include <asm/iommu.h>
++#include <asm/gart.h>
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+ 
+ #include <mach_apic.h>
+ #include <asm/paravirt.h>
++#include <asm/hypervisor.h>
+ 
+ #include <asm/percpu.h>
+ #include <asm/topology.h>
+@@ -508,6 +510,7 @@ static void __init reserve_early_setup_d
+  * @size: Size of the crashkernel memory to reserve.
+  * Returns the base address on success, and -1ULL on failure.
+  */
++static
+ unsigned long long __init find_and_reserve_crashkernel(unsigned long long size)
+ {
+ 	const unsigned long long alignment = 16<<20; 	/* 16M */
+@@ -650,165 +653,32 @@ static int __init setup_elfcorehdr(char 
+ early_param("elfcorehdr", setup_elfcorehdr);
+ #endif
+ 
+-static struct x86_quirks default_x86_quirks __initdata;
+-
+-struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+-
+-/*
+- * Some BIOSes seem to corrupt the low 64k of memory during events
+- * like suspend/resume and unplugging an HDMI cable.  Reserve all
+- * remaining free memory in that area and fill it with a distinct
+- * pattern.
+- */
+-#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+-#define MAX_SCAN_AREAS	8
+-
+-static int __read_mostly memory_corruption_check = -1;
+-
+-static unsigned __read_mostly corruption_check_size = 64*1024;
+-static unsigned __read_mostly corruption_check_period = 60; /* seconds */
+-
+-static struct e820entry scan_areas[MAX_SCAN_AREAS];
+-static int num_scan_areas;
+-
+-
+-static int set_corruption_check(char *arg)
+-{
+-	char *end;
+-
+-	memory_corruption_check = simple_strtol(arg, &end, 10);
+-
+-	return (*end == 0) ? 0 : -EINVAL;
+-}
+-early_param("memory_corruption_check", set_corruption_check);
+-
+-static int set_corruption_check_period(char *arg)
+-{
+-	char *end;
+-
+-	corruption_check_period = simple_strtoul(arg, &end, 10);
+-
+-	return (*end == 0) ? 0 : -EINVAL;
+-}
+-early_param("memory_corruption_check_period", set_corruption_check_period);
+-
+-static int set_corruption_check_size(char *arg)
++#ifndef CONFIG_XEN
++static int __init default_update_genapic(void)
+ {
+-	char *end;
+-	unsigned size;
+-
+-	size = memparse(arg, &end);
+-
+-	if (*end == '\0')
+-		corruption_check_size = size;
++#ifdef CONFIG_X86_SMP
++# if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64)
++	genapic->wakeup_cpu = wakeup_secondary_cpu_via_init;
++# endif
++#endif
+ 
+-	return (size == corruption_check_size) ? 0 : -EINVAL;
++	return 0;
+ }
+-early_param("memory_corruption_check_size", set_corruption_check_size);
+-
+-
+-static void __init setup_bios_corruption_check(void)
+-{
+-	u64 addr = PAGE_SIZE;	/* assume first page is reserved anyway */
+-
+-	if (memory_corruption_check == -1) {
+-		memory_corruption_check =
+-#ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
+-			1
+ #else
+-			0
++#define default_update_genapic NULL
+ #endif
+-			;
+-	}
+-
+-	if (corruption_check_size == 0)
+-		memory_corruption_check = 0;
+-
+-	if (!memory_corruption_check)
+-		return;
+-
+-	corruption_check_size = round_up(corruption_check_size, PAGE_SIZE);
+-
+-	while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
+-		u64 size;
+-		addr = find_e820_area_size(addr, &size, PAGE_SIZE);
+-
+-		if (addr == 0)
+-			break;
+-
+-		if ((addr + size) > corruption_check_size)
+-			size = corruption_check_size - addr;
+ 
+-		if (size == 0)
+-			break;
+-
+-		e820_update_range(addr, size, E820_RAM, E820_RESERVED);
+-		scan_areas[num_scan_areas].addr = addr;
+-		scan_areas[num_scan_areas].size = size;
+-		num_scan_areas++;
+-
+-		/* Assume we've already mapped this early memory */
+-		memset(__va(addr), 0, size);
+-
+-		addr += size;
+-	}
+-
+-	printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
+-	       num_scan_areas);
+-	update_e820();
+-}
+-
+-static struct timer_list periodic_check_timer;
+-
+-void check_for_bios_corruption(void)
+-{
+-	int i;
+-	int corruption = 0;
+-
+-	if (!memory_corruption_check)
+-		return;
+-
+-	for(i = 0; i < num_scan_areas; i++) {
+-		unsigned long *addr = __va(scan_areas[i].addr);
+-		unsigned long size = scan_areas[i].size;
+-
+-		for(; size; addr++, size -= sizeof(unsigned long)) {
+-			if (!*addr)
+-				continue;
+-			printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n",
+-			       addr, __pa(addr), *addr);
+-			corruption = 1;
+-			*addr = 0;
+-		}
+-	}
+-
+-	WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n");
+-}
+-
+-static void periodic_check_for_corruption(unsigned long data)
+-{
+-	check_for_bios_corruption();
+-	mod_timer(&periodic_check_timer, round_jiffies(jiffies + corruption_check_period*HZ));
+-}
+-
+-void start_periodic_check_for_corruption(void)
+-{
+-	if (!memory_corruption_check || corruption_check_period == 0)
+-		return;
+-
+-	printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
+-	       corruption_check_period);
++static struct x86_quirks default_x86_quirks __initdata = {
++	.update_genapic         = default_update_genapic,
++};
+ 
+-	init_timer(&periodic_check_timer);
+-	periodic_check_timer.function = &periodic_check_for_corruption;
+-	periodic_check_for_corruption(0);
+-}
+-#endif
++struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+ 
++#ifdef CONFIG_X86_RESERVE_LOW_64K
+ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
+ {
+ 	printk(KERN_NOTICE
+-		"%s detected: BIOS may corrupt low RAM, working it around.\n",
++		"%s detected: BIOS may corrupt low RAM, working around it.\n",
+ 		d->ident);
+ 
+ 	e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
+@@ -816,6 +686,7 @@ static int __init dmi_low_memory_corrupt
+ 
+ 	return 0;
+ }
++#endif
+ 
+ /* List of systems that have known low memory corruption BIOS problems */
+ static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
+@@ -1023,15 +894,25 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	finish_e820_parsing();
+ 
++	if (efi_enabled)
++		efi_init();
++
+ 	if (is_initial_xendomain()) {
+ 		dmi_scan_machine();
+ 
+ 		dmi_check_system(bad_bios_dmi_table);
++	}
++
++	/*
++	 * VMware detection requires dmi to be available, so this
++	 * needs to be done after dmi_scan_machine, for the BP.
++	 */
++	init_hypervisor(&boot_cpu_data);
+ 
+ #ifdef CONFIG_X86_32
++	if (is_initial_xendomain())
+ 		probe_roms();
+ #endif
+-	}
+ 
+ #ifndef CONFIG_XEN
+ 	/* after parse_early_param, so could debug it */
+@@ -1039,8 +920,6 @@ void __init setup_arch(char **cmdline_p)
+ 	insert_resource(&iomem_resource, &data_resource);
+ 	insert_resource(&iomem_resource, &bss_resource);
+ 
+-	if (efi_enabled)
+-		efi_init();
+ 
+ #ifdef CONFIG_X86_32
+ 	if (ppro_with_ram_bug()) {
+@@ -1295,7 +1174,7 @@ void __init setup_arch(char **cmdline_p)
+ 	ioapic_init_mappings();
+ 
+ 	/* need to wait for io_apic is mapped */
+-	nr_irqs = probe_nr_irqs();
++	probe_nr_irqs_gsi();
+ 
+ 	kvm_guest_init();
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/smp-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -1,7 +1,7 @@
+ /*
+  *	Intel SMP support routines.
+  *
+- *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
++ *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+  *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+  *      (c) 2002,2003 Andi Kleen, SuSE Labs.
+  *
+@@ -118,30 +118,17 @@ void xen_smp_send_reschedule(int cpu)
+ 		WARN_ON(1);
+ 		return;
+ 	}
+-	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
++	send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
+ }
+ 
+ void xen_send_call_func_single_ipi(int cpu)
+ {
+-	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNC_SINGLE_VECTOR);
++	send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_VECTOR);
+ }
+ 
+-void xen_send_call_func_ipi(cpumask_t mask)
++void xen_send_call_func_ipi(const struct cpumask *mask)
+ {
+-	send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+-}
+-
+-static void stop_this_cpu(void *dummy)
+-{
+-	local_irq_disable();
+-	/*
+-	 * Remove this CPU:
+-	 */
+-	cpu_clear(smp_processor_id(), cpu_online_map);
+-	disable_all_local_evtchn();
+-	if (hlt_works(smp_processor_id()))
+-		for (;;) halt();
+-	for (;;);
++	send_IPI_mask_allbutself(mask, CALL_FUNCTION_VECTOR);
+ }
+ 
+ /*
+@@ -165,11 +152,7 @@ void xen_smp_send_stop(void)
+  */
+ irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+ {
+-#ifdef CONFIG_X86_32
+-	__get_cpu_var(irq_stat).irq_resched_count++;
+-#else
+-	add_pda(irq_resched_count, 1);
+-#endif
++	inc_irq_stat(irq_resched_count);
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -177,11 +160,7 @@ irqreturn_t smp_call_function_interrupt(
+ {
+ 	irq_enter();
+ 	generic_smp_call_function_interrupt();
+-#ifdef CONFIG_X86_32
+-	__get_cpu_var(irq_stat).irq_call_count++;
+-#else
+-	add_pda(irq_call_count, 1);
+-#endif
++	inc_irq_stat(irq_call_count);
+ 	irq_exit();
+ 
+ 	return IRQ_HANDLED;
+@@ -191,11 +170,7 @@ irqreturn_t smp_call_function_single_int
+ {
+ 	irq_enter();
+ 	generic_smp_call_function_single_interrupt();
+-#ifdef CONFIG_X86_32
+-	__get_cpu_var(irq_stat).irq_call_count++;
+-#else
+-	add_pda(irq_call_count, 1);
+-#endif
++	inc_irq_stat(irq_call_count);
+ 	irq_exit();
+ 
+ 	return IRQ_HANDLED;
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:41:33.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/time-xen.c	2009-11-23 10:41:53.000000000 +0100
+@@ -445,11 +445,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	struct vcpu_runstate_info runstate;
+ 
+ 	/* Keep nmi watchdog up to date */
+-#ifdef __i386__
+-	x86_add_percpu(irq_stat.irq0_irqs, 1);
+-#else
+-	add_pda(irq0_irqs, 1);
+-#endif
++	inc_irq_stat(irq0_irqs);
+ 
+ 	/*
+ 	 * Here we are in the timer irq handler. We just have irqs locally
+@@ -509,7 +505,6 @@ irqreturn_t timer_interrupt(int irq, voi
+ 
+ 	/*
+ 	 * Account stolen ticks.
+-	 * HACK: Passing NULL to account_steal_time()
+ 	 * ensures that the ticks are accounted as stolen.
+ 	 */
+ 	stolen = runstate.time[RUNSTATE_runnable]
+@@ -522,12 +517,11 @@ irqreturn_t timer_interrupt(int irq, voi
+ 		do_div(stolen, NS_PER_TICK);
+ 		per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK;
+ 		per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK;
+-		account_steal_time(NULL, (cputime_t)stolen);
++		account_steal_time((cputime_t)stolen);
+ 	}
+ 
+ 	/*
+ 	 * Account blocked ticks.
+-	 * HACK: Passing idle_task to account_steal_time()
+ 	 * ensures that the ticks are accounted as idle/wait.
+ 	 */
+ 	blocked = runstate.time[RUNSTATE_blocked]
+@@ -539,7 +533,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 		do_div(blocked, NS_PER_TICK);
+ 		per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK;
+ 		per_cpu(processed_system_time, cpu)  += blocked * NS_PER_TICK;
+-		account_steal_time(idle_task(cpu), (cputime_t)blocked);
++		account_idle_time((cputime_t)blocked);
+ 	}
+ 
+ 	/* Account user/system ticks. */
+@@ -547,10 +541,14 @@ irqreturn_t timer_interrupt(int irq, voi
+ 		do_div(delta_cpu, NS_PER_TICK);
+ 		per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK;
+ 		if (user_mode_vm(get_irq_regs()))
+-			account_user_time(current, (cputime_t)delta_cpu);
+-		else
++			account_user_time(current, (cputime_t)delta_cpu,
++					  (cputime_t)delta_cpu);
++		else if (current != idle_task(cpu))
+ 			account_system_time(current, HARDIRQ_OFFSET,
++					    (cputime_t)delta_cpu,
+ 					    (cputime_t)delta_cpu);
++		else
++			account_idle_time((cputime_t)delta_cpu);
+ 	}
+ 
+ 	/* Offlined for more than a few seconds? Avoid lockup warnings. */
+@@ -779,7 +777,7 @@ static void stop_hz_timer(void)
+ 	unsigned long j;
+ 	int rc;
+ 
+-	cpu_set(cpu, nohz_cpu_mask);
++	cpumask_set_cpu(cpu, nohz_cpu_mask);
+ 
+ 	/* See matching smp_mb in rcu_start_batch in rcupdate.c.  These mbs  */
+ 	/* ensure that if __rcu_pending (nested in rcu_needs_cpu) fetches a  */
+@@ -795,7 +793,7 @@ static void stop_hz_timer(void)
+ 	    local_softirq_pending() ||
+ 	    (j = get_next_timer_interrupt(jiffies),
+ 	     time_before_eq(j, jiffies))) {
+-		cpu_clear(cpu, nohz_cpu_mask);
++		cpumask_clear_cpu(cpu, nohz_cpu_mask);
+ 		j = jiffies + 1;
+ 	}
+ 
+@@ -813,7 +811,7 @@ static void stop_hz_timer(void)
+ 
+ static void start_hz_timer(void)
+ {
+-	cpu_clear(smp_processor_id(), nohz_cpu_mask);
++	cpumask_clear_cpu(smp_processor_id(), nohz_cpu_mask);
+ }
+ 
+ void xen_safe_halt(void)
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/traps-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/traps-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -20,7 +20,6 @@
+ #include <linux/module.h>
+ #include <linux/ptrace.h>
+ #include <linux/string.h>
+-#include <linux/unwind.h>
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/kexec.h>
+@@ -51,7 +50,6 @@
+ #include <asm/debugreg.h>
+ #include <asm/atomic.h>
+ #include <asm/system.h>
+-#include <asm/unwind.h>
+ #include <asm/traps.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+@@ -65,18 +63,10 @@
+ #else
+ #include <asm/processor-flags.h>
+ #include <asm/arch_hooks.h>
+-#include <asm/nmi.h>
+-#include <asm/smp.h>
+-#include <asm/io.h>
+ #include <asm/traps.h>
+ 
+ #include "cpu/mcheck/mce.h"
+ 
+-#ifndef CONFIG_XEN
+-DECLARE_BITMAP(used_vectors, NR_VECTORS);
+-EXPORT_SYMBOL_GPL(used_vectors);
+-#endif
+-
+ asmlinkage int system_call(void);
+ 
+ /* Do we ignore FPU interrupts ? */
+@@ -93,6 +83,11 @@ gate_desc idt_table[256]
+ #endif
+ #endif
+ 
++#ifndef CONFIG_XEN
++DECLARE_BITMAP(used_vectors, NR_VECTORS);
++EXPORT_SYMBOL_GPL(used_vectors);
++#endif
++
+ static int ignore_nmis;
+ 
+ static inline void conditional_sti(struct pt_regs *regs)
+@@ -108,6 +103,12 @@ static inline void preempt_conditional_s
+ 		local_irq_enable();
+ }
+ 
++static inline void conditional_cli(struct pt_regs *regs)
++{
++	if (regs->flags & X86_EFLAGS_IF)
++		local_irq_disable();
++}
++
+ static inline void preempt_conditional_cli(struct pt_regs *regs)
+ {
+ 	if (regs->flags & X86_EFLAGS_IF)
+@@ -298,8 +299,10 @@ dotraplinkage void do_double_fault(struc
+ 	tsk->thread.error_code = error_code;
+ 	tsk->thread.trap_no = 8;
+ 
+-	/* This is always a kernel trap and never fixable (and thus must
+-	   never return). */
++	/*
++	 * This is always a kernel trap and never fixable (and thus must
++	 * never return).
++	 */
+ 	for (;;)
+ 		die(str, regs, error_code);
+ }
+@@ -476,11 +479,7 @@ do_nmi(struct pt_regs *regs, long error_
+ {
+ 	nmi_enter();
+ 
+-#ifdef CONFIG_X86_32
+-	{ int cpu; cpu = smp_processor_id(); ++nmi_count(cpu); }
+-#else
+-	add_pda(__nmi_count, 1);
+-#endif
++	inc_irq_stat(__nmi_count);
+ 
+ 	if (!ignore_nmis)
+ 		default_do_nmi(regs);
+@@ -519,9 +518,11 @@ dotraplinkage void __kprobes do_int3(str
+ }
+ 
+ #if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+-/* Help handler running on IST stack to switch back to user stack
+-   for scheduling or signal handling. The actual stack switch is done in
+-   entry.S */
++/*
++ * Help handler running on IST stack to switch back to user stack
++ * for scheduling or signal handling. The actual stack switch is done in
++ * entry.S
++ */
+ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
+ {
+ 	struct pt_regs *regs = eregs;
+@@ -531,8 +532,10 @@ asmlinkage __kprobes struct pt_regs *syn
+ 	/* Exception from user space */
+ 	else if (user_mode(eregs))
+ 		regs = task_pt_regs(current);
+-	/* Exception from kernel and interrupts are enabled. Move to
+-	   kernel process stack. */
++	/*
++	 * Exception from kernel and interrupts are enabled. Move to
++	 * kernel process stack.
++	 */
+ 	else if (eregs->flags & X86_EFLAGS_IF)
+ 		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
+ 	if (eregs != regs)
+@@ -624,8 +627,10 @@ clear_dr7:
+ 
+ #ifdef CONFIG_X86_32
+ debug_vm86:
++	/* reenable preemption: handle_vm86_trap() might sleep */
++	dec_preempt_count();
+ 	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+-	preempt_conditional_cli(regs);
++	conditional_cli(regs);
+ 	return;
+ #endif
+ 
+@@ -659,7 +664,7 @@ void math_error(void __user *ip)
+ {
+ 	struct task_struct *task;
+ 	siginfo_t info;
+-	unsigned short cwd, swd;
++	unsigned short cwd, swd, err;
+ 
+ 	/*
+ 	 * Save the info for the exception handler and clear the error.
+@@ -670,7 +675,6 @@ void math_error(void __user *ip)
+ 	task->thread.error_code = 0;
+ 	info.si_signo = SIGFPE;
+ 	info.si_errno = 0;
+-	info.si_code = __SI_FAULT;
+ 	info.si_addr = ip;
+ 	/*
+ 	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+@@ -684,34 +688,30 @@ void math_error(void __user *ip)
+ 	 */
+ 	cwd = get_fpu_cwd(task);
+ 	swd = get_fpu_swd(task);
+-	switch (swd & ~cwd & 0x3f) {
+-	case 0x000: /* No unmasked exception */
+-#ifdef CONFIG_X86_32
+-		return;
+-#endif
+-	default: /* Multiple exceptions */
+-		break;
+-	case 0x001: /* Invalid Op */
++
++	err = swd & ~cwd;
++
++	if (err & 0x001) {	/* Invalid op */
+ 		/*
+ 		 * swd & 0x240 == 0x040: Stack Underflow
+ 		 * swd & 0x240 == 0x240: Stack Overflow
+ 		 * User must clear the SF bit (0x40) if set
+ 		 */
+ 		info.si_code = FPE_FLTINV;
+-		break;
+-	case 0x002: /* Denormalize */
+-	case 0x010: /* Underflow */
+-		info.si_code = FPE_FLTUND;
+-		break;
+-	case 0x004: /* Zero Divide */
++	} else if (err & 0x004) { /* Divide by Zero */
+ 		info.si_code = FPE_FLTDIV;
+-		break;
+-	case 0x008: /* Overflow */
++	} else if (err & 0x008) { /* Overflow */
+ 		info.si_code = FPE_FLTOVF;
+-		break;
+-	case 0x020: /* Precision */
++	} else if (err & 0x012) { /* Denormal, Underflow */
++		info.si_code = FPE_FLTUND;
++	} else if (err & 0x020) { /* Precision */
+ 		info.si_code = FPE_FLTRES;
+-		break;
++	} else {
++		/*
++		 * If we're using IRQ 13, or supposedly even some trap 16
++		 * implementations, it's possible we get a spurious trap...
++		 */
++		return;		/* Spurious trap, no error */
+ 	}
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+@@ -901,7 +901,7 @@ asmlinkage void math_state_restore(void)
+ EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+ #ifndef CONFIG_MATH_EMULATION
+-asmlinkage void math_emulate(long arg)
++void math_emulate(struct math_emu_info *info)
+ {
+ 	printk(KERN_EMERG
+ 		"math-emulation not enabled and no coprocessor found.\n");
+@@ -911,16 +911,19 @@ asmlinkage void math_emulate(long arg)
+ }
+ #endif /* CONFIG_MATH_EMULATION */
+ 
+-dotraplinkage void __kprobes
+-do_device_not_available(struct pt_regs *regs, long error)
++dotraplinkage void __kprobes do_device_not_available(struct pt_regs regs)
+ {
+ #if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	if (read_cr0() & X86_CR0_EM) {
+-		conditional_sti(regs);
+-		math_emulate(0);
++		struct math_emu_info info = { };
++
++		conditional_sti(&regs);
++
++		info.regs = &regs;
++		math_emulate(&info);
+ 	} else {
+ 		math_state_restore(); /* interrupts still off */
+-		conditional_sti(regs);
++		conditional_sti(&regs);
+ 	}
+ #else
+ 	math_state_restore();
+--- sle11sp1-2010-01-20.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -17,6 +17,9 @@
+  *  want per guest time just set the kernel.vsyscall64 sysctl to 0.
+  */
+ 
++/* Disable profiling for userspace code: */
++#define DISABLE_BRANCH_PROFILING
++
+ #include <linux/time.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+@@ -128,7 +131,16 @@ static __always_inline void do_vgettimeo
+ 			gettimeofday(tv,NULL);
+ 			return;
+ 		}
++
++		/*
++		 * Surround the RDTSC by barriers, to make sure it's not
++		 * speculated to outside the seqlock critical section and
++		 * does not cause time warps:
++		 */
++		rdtsc_barrier();
+ 		now = vread();
++		rdtsc_barrier();
++
+ 		base = __vsyscall_gtod_data.clock.cycle_last;
+ 		mask = __vsyscall_gtod_data.clock.mask;
+ 		mult = __vsyscall_gtod_data.clock.mult;
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/fault-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -53,7 +53,7 @@
+ 
+ static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
+ {
+-#ifdef CONFIG_MMIOTRACE_HOOKS
++#ifdef CONFIG_MMIOTRACE
+ 	if (unlikely(is_kmmio_active()))
+ 		if (kmmio_handler(regs, addr) == 1)
+ 			return -1;
+@@ -406,7 +406,7 @@ static void show_fault_oops(struct pt_re
+ 		if (pte && pte_present(*pte) && !pte_exec(*pte))
+ 			printk(KERN_CRIT "kernel tried to execute "
+ 				"NX-protected page - exploit attempt? "
+-				"(uid: %d)\n", current->uid);
++				"(uid: %d)\n", current_uid());
+ 	}
+ #endif
+ 
+@@ -426,6 +426,7 @@ static noinline void pgtable_bad(unsigne
+ 				 unsigned long error_code)
+ {
+ 	unsigned long flags = oops_begin();
++	int sig = SIGKILL;
+ 	struct task_struct *tsk;
+ 
+ 	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+@@ -436,8 +437,8 @@ static noinline void pgtable_bad(unsigne
+ 	tsk->thread.trap_no = 14;
+ 	tsk->thread.error_code = error_code;
+ 	if (__die("Bad pagetable", regs, error_code))
+-		regs = NULL;
+-	oops_end(flags, regs, SIGKILL);
++		sig = 0;
++	oops_end(flags, regs, sig);
+ }
+ #endif
+ 
+@@ -546,10 +547,7 @@ static int vmalloc_fault(unsigned long a
+ 	   happen within a race in page table update. In the later
+ 	   case just flush. */
+ 
+-	/* On Xen the line below does not always work. Needs investigating! */
+-	/*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
+-	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+-	pgd += pgd_index(address);
++	pgd = pgd_offset(current->active_mm, address);
+ 	pgd_ref = pgd_offset_k(address);
+ 	if (pgd_none(*pgd_ref))
+ 		return -1;
+@@ -606,6 +604,7 @@ void __kprobes do_page_fault(struct pt_r
+ 	int fault;
+ #ifdef CONFIG_X86_64
+ 	unsigned long flags;
++	int sig;
+ #endif
+ 
+ 	/* Set the "privileged fault" bit to something sane. */
+@@ -623,8 +622,6 @@ void __kprobes do_page_fault(struct pt_r
+ 
+ 	si_code = SEGV_MAPERR;
+ 
+-	if (notify_page_fault(regs))
+-		return;
+ 	if (unlikely(kmmio_fault(regs, address)))
+ 		return;
+ 
+@@ -663,6 +660,9 @@ void __kprobes do_page_fault(struct pt_r
+ 		if (spurious_fault(address, error_code))
+ 			return;
+ 
++		/* kprobes don't want to hook the spurious faults. */
++		if (notify_page_fault(regs))
++			return;
+ 		/*
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+ 		 * fault we could otherwise deadlock.
+@@ -670,6 +670,9 @@ void __kprobes do_page_fault(struct pt_r
+ 		goto bad_area_nosemaphore;
+ 	}
+ 
++	/* kprobes don't want to hook the spurious faults. */
++	if (notify_page_fault(regs))
++		return;
+ 
+ 	/*
+ 	 * It's safe to allow irq's after cr2 has been saved and the
+@@ -696,7 +699,6 @@ void __kprobes do_page_fault(struct pt_r
+ 	if (unlikely(in_atomic() || !mm))
+ 		goto bad_area_nosemaphore;
+ 
+-again:
+ 	/*
+ 	 * When running in the kernel we expect faults to occur only to
+ 	 * addresses in user space.  All other faults represent errors in the
+@@ -880,32 +882,22 @@ no_context:
+ 	bust_spinlocks(0);
+ 	do_exit(SIGKILL);
+ #else
++	sig = SIGKILL;
+ 	if (__die("Oops", regs, error_code))
+-		regs = NULL;
++		sig = 0;
+ 	/* Executive summary in case the body of the oops scrolled away */
+ 	printk(KERN_EMERG "CR2: %016lx\n", address);
+-	oops_end(flags, regs, SIGKILL);
++	oops_end(flags, regs, sig);
+ #endif
+ 
+-/*
+- * We ran out of memory, or some other thing happened to us that made
+- * us unable to handle the page fault gracefully.
+- */
+ out_of_memory:
++	/*
++	 * We ran out of memory, call the OOM killer, and return the userspace
++	 * (which will retry the fault, or kill us if we got oom-killed).
++	 */
+ 	up_read(&mm->mmap_sem);
+-	if (is_global_init(tsk)) {
+-		yield();
+-		/*
+-		 * Re-lookup the vma - in theory the vma tree might
+-		 * have changed:
+-		 */
+-		goto again;
+-	}
+-
+-	printk("VM: killing process %s\n", tsk->comm);
+-	if (error_code & PF_USER)
+-		do_group_exit(SIGKILL);
+-	goto no_context;
++	pagefault_out_of_memory();
++	return;
+ 
+ do_sigbus:
+ 	up_read(&mm->mmap_sem);
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/hypervisor.c	2009-11-06 10:51:55.000000000 +0100
+@@ -79,12 +79,12 @@ static void multicall_failed(const multi
+ 	BUG();
+ }
+ 
+-int xen_multicall_flush(bool ret_last) {
++static int _xen_multicall_flush(bool ret_last) {
+ 	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
+ 	multicall_entry_t *mc = lazy->mc;
+ 	unsigned int count = lazy->nr_mc;
+ 
+-	if (!count || !use_lazy_mmu_mode())
++	if (!count)
+ 		return 0;
+ 
+ 	lazy->nr_mc = 0;
+@@ -112,6 +112,11 @@ int xen_multicall_flush(bool ret_last) {
+ 
+ 	return 0;
+ }
++
++void xen_multicall_flush(bool force) {
++	if (force || use_lazy_mmu_mode())
++		_xen_multicall_flush(false);
++}
+ EXPORT_SYMBOL(xen_multicall_flush);
+ 
+ int xen_multi_update_va_mapping(unsigned long va, pte_t pte,
+@@ -130,7 +135,7 @@ int xen_multi_update_va_mapping(unsigned
+ #endif
+ 
+ 	if (unlikely(lazy->nr_mc == NR_MC))
+-		xen_multicall_flush(false);
++		_xen_multicall_flush(false);
+ 
+ 	mc = lazy->mc + lazy->nr_mc++;
+ 	mc->op = __HYPERVISOR_update_va_mapping;
+@@ -169,7 +174,7 @@ int xen_multi_mmu_update(mmu_update_t *s
+ 	merge = lazy->nr_mc && !commit
+ 		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmu_update, domid);
+ 	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
+-		xen_multicall_flush(false);
++		_xen_multicall_flush(false);
+ 		mc = lazy->mc;
+ 		commit = count > NR_MMU || success_count;
+ 	}
+@@ -207,7 +212,7 @@ int xen_multi_mmu_update(mmu_update_t *s
+ 			break;
+ 		}
+ 
+-	return commit ? xen_multicall_flush(true) : 0;
++	return commit ? _xen_multicall_flush(true) : 0;
+ }
+ 
+ int xen_multi_mmuext_op(struct mmuext_op *src, unsigned int count,
+@@ -291,7 +296,7 @@ int xen_multi_mmuext_op(struct mmuext_op
+ 	merge = lazy->nr_mc && !commit
+ 		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmuext_op, domid);
+ 	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
+-		xen_multicall_flush(false);
++		_xen_multicall_flush(false);
+ 		mc = lazy->mc;
+ 		commit = count > NR_MMUEXT || success_count;
+ 	}
+@@ -338,7 +343,7 @@ int xen_multi_mmuext_op(struct mmuext_op
+ 			break;
+ 		}
+ 
+-	return commit ? xen_multicall_flush(true) : 0;
++	return commit ? _xen_multicall_flush(true) : 0;
+ }
+ 
+ void xen_l1_entry_update(pte_t *ptr, pte_t val)
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -71,7 +71,7 @@ static unsigned long __initdata table_to
+ 
+ static int __initdata after_init_bootmem;
+ 
+-static __init void *alloc_low_page(unsigned long *phys)
++static __init void *alloc_low_page(void)
+ {
+ 	unsigned long pfn = table_end++;
+ 	void *adr;
+@@ -81,7 +81,6 @@ static __init void *alloc_low_page(unsig
+ 
+ 	adr = __va(pfn * PAGE_SIZE);
+ 	memset(adr, 0, PAGE_SIZE);
+-	*phys  = pfn * PAGE_SIZE;
+ 	return adr;
+ }
+ 
+@@ -96,17 +95,18 @@ static pmd_t * __init one_md_table_init(
+ 	pmd_t *pmd_table;
+ 
+ #ifdef CONFIG_X86_PAE
+-	unsigned long phys;
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+ 		if (after_init_bootmem)
+ 			pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ 		else
+-			pmd_table = (pmd_t *)alloc_low_page(&phys);
++			pmd_table = (pmd_t *)alloc_low_page();
+ 		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+ 		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ 		pud = pud_offset(pgd, 0);
+ 		BUG_ON(pmd_table != pmd_offset(pud, 0));
++
++		return pmd_table;
+ 	}
+ #endif
+ 	pud = pud_offset(pgd, 0);
+@@ -135,10 +135,8 @@ static pte_t * __init one_page_table_ini
+ 			if (!page_table)
+ 				page_table =
+ 				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+-		} else {
+-			unsigned long phys;
+-			page_table = (pte_t *)alloc_low_page(&phys);
+-		}
++		} else
++			page_table = (pte_t *)alloc_low_page();
+ 
+ 		paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+@@ -150,6 +148,51 @@ static pte_t * __init one_page_table_ini
+ 	return pte_offset_kernel(pmd, 0);
+ }
+ 
++static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
++					   unsigned long vaddr, pte_t *lastpte)
++{
++#ifdef CONFIG_HIGHMEM
++	/*
++	 * Something (early fixmap) may already have put a pte
++	 * page here, which causes the page table allocation
++	 * to become nonlinear. Attempt to fix it, and if it
++	 * is still nonlinear then we have to bug.
++	 */
++	int pmd_idx_kmap_begin = fix_to_virt(FIX_KMAP_END) >> PMD_SHIFT;
++	int pmd_idx_kmap_end = fix_to_virt(FIX_KMAP_BEGIN) >> PMD_SHIFT;
++
++	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
++	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
++	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
++	    && ((__pa(pte) >> PAGE_SHIFT) < table_start
++		|| (__pa(pte) >> PAGE_SHIFT) >= table_end)) {
++		pte_t *newpte;
++		int i;
++
++		BUG_ON(after_init_bootmem);
++		newpte = alloc_low_page();
++		for (i = 0; i < PTRS_PER_PTE; i++)
++			set_pte(newpte + i, pte[i]);
++
++		paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT);
++		make_lowmem_page_readonly(newpte,
++					  XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE));
++		BUG_ON(newpte != pte_offset_kernel(pmd, 0));
++		__flush_tlb_all();
++
++		paravirt_release_pte(__pa(pte) >> PAGE_SHIFT);
++		make_lowmem_page_writable(pte,
++					  XENFEAT_writable_page_tables);
++		pte = newpte;
++	}
++	BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1)
++	       && vaddr > fix_to_virt(FIX_KMAP_END)
++	       && lastpte && lastpte + PTRS_PER_PTE != pte);
++#endif
++	return pte;
++}
++
+ /*
+  * This function initializes a certain range of kernel virtual memory
+  * with new bootmem page tables, everywhere page tables are missing in
+@@ -166,6 +209,7 @@ page_table_range_init(unsigned long star
+ 	unsigned long vaddr;
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
++	pte_t *pte = NULL;
+ 
+ 	vaddr = start;
+ 	pgd_idx = pgd_index(vaddr);
+@@ -177,8 +221,10 @@ page_table_range_init(unsigned long star
+ 		pmd = pmd + pmd_index(vaddr);
+ 		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
+ 							pmd++, pmd_idx++) {
+-			if (vaddr < hypervisor_virt_start)
+-				one_page_table_init(pmd);
++			if (vaddr >= hypervisor_virt_start)
++				break;
++			pte = page_table_kmap_check(one_page_table_init(pmd),
++			                            pmd, vaddr, pte);
+ 
+ 			vaddr += PMD_SIZE;
+ 		}
+@@ -361,6 +407,8 @@ int devmem_is_allowed(unsigned long page
+ {
+ 	if (pagenr <= 256)
+ 		return 1;
++	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
++		return 0;
+ 	if (mfn_to_local_pfn(pagenr) >= max_pfn)
+ 		return 1;
+ 	return 0;
+@@ -476,8 +524,12 @@ static void __init set_highmem_pages_ini
+ #endif /* !CONFIG_NUMA */
+ 
+ #else
+-# define permanent_kmaps_init(pgd_base)		do { } while (0)
+-# define set_highmem_pages_init()	do { } while (0)
++static inline void permanent_kmaps_init(pgd_t *pgd_base)
++{
++}
++static inline void set_highmem_pages_init(void)
++{
++}
+ #endif /* CONFIG_HIGHMEM */
+ 
+ pgd_t *swapper_pg_dir;
+@@ -509,7 +561,6 @@ static void __init early_ioremap_page_ta
+ 	 * Fixed mappings, only the page table structure has to be
+ 	 * created - mappings will be set by set_fixmap():
+ 	 */
+-	early_ioremap_clear();
+ 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ 	end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+ 	page_table_range_init(vaddr, end, pgd_base);
+@@ -856,10 +907,7 @@ static void __init find_early_table_spac
+ 	tables += PAGE_ALIGN(ptes * sizeof(pte_t));
+ 
+ 	/* for fixmap */
+-	tables += PAGE_SIZE
+-	          * ((((FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK)
+-	              - (__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK))
+-	             >> PMD_SHIFT);
++	tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t));
+ 
+ 	table_start = extend_init_mapping(tables);
+ 
+@@ -1023,8 +1071,6 @@ void __init mem_init(void)
+ 
+ 	pci_iommu_alloc();
+ 
+-	start_periodic_check_for_corruption();
+-
+ #ifdef CONFIG_FLATMEM
+ 	BUG_ON(!mem_map);
+ #endif
+@@ -1099,11 +1145,25 @@ void __init mem_init(void)
+ 		(unsigned long)&_text, (unsigned long)&_etext,
+ 		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+ 
++	/*
++	 * Check boundaries twice: Some fundamental inconsistencies can
++	 * be detected at build time already.
++	 */
++#define __FIXADDR_TOP (-PAGE_SIZE)
++#ifdef CONFIG_HIGHMEM
++	BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
++	BUILD_BUG_ON(VMALLOC_END			> PKMAP_BASE);
++#endif
++#define high_memory (-128UL << 20)
++	BUILD_BUG_ON(VMALLOC_START			>= VMALLOC_END);
++#undef high_memory
++#undef __FIXADDR_TOP
++
+ #ifdef CONFIG_HIGHMEM
+ 	BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
+ 	BUG_ON(VMALLOC_END				> PKMAP_BASE);
+ #endif
+-	BUG_ON(VMALLOC_START				> VMALLOC_END);
++	BUG_ON(VMALLOC_START				>= VMALLOC_END);
+ 	BUG_ON((unsigned long)high_memory		> VMALLOC_START);
+ 
+ 	if (boot_cpu_data.wp_works_ok < 0)
+@@ -1123,7 +1183,7 @@ int arch_add_memory(int nid, u64 start, 
+ 	unsigned long start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 
+-	return __add_pages(zone, start_pfn, nr_pages);
++	return __add_pages(nid, zone, start_pfn, nr_pages);
+ }
+ #endif
+ 
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -841,7 +841,7 @@ static void __init init_gbpages(void)
+ #endif
+ }
+ 
+-static unsigned long __init kernel_physical_mapping_init(unsigned long start,
++static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
+ 						unsigned long end,
+ 						unsigned long page_size_mask)
+ {
+@@ -966,6 +966,8 @@ unsigned long __init_refok init_memory_m
+ 	pos = start_pfn << PAGE_SHIFT;
+ 	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
+ 			<< (PMD_SHIFT - PAGE_SHIFT);
++	if (end_pfn > (end >> PAGE_SHIFT))
++		end_pfn = end >> PAGE_SHIFT;
+ 	if (start_pfn < end_pfn) {
+ 		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+ 		pos = end_pfn << PAGE_SHIFT;
+@@ -1146,7 +1148,7 @@ int arch_add_memory(int nid, u64 start, 
+ 	if (last_mapped_pfn > max_pfn_mapped)
+ 		max_pfn_mapped = last_mapped_pfn;
+ 
+-	ret = __add_pages(zone, start_pfn, nr_pages);
++	ret = __add_pages(nid, zone, start_pfn, nr_pages);
+ 	WARN_ON_ONCE(ret);
+ 
+ 	return ret;
+@@ -1177,6 +1179,8 @@ int devmem_is_allowed(unsigned long page
+ {
+ 	if (pagenr <= 256)
+ 		return 1;
++	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
++		return 0;
+ 	if (mfn_to_local_pfn(pagenr) >= max_pfn)
+ 		return 1;
+ 	return 0;
+@@ -1192,8 +1196,6 @@ void __init mem_init(void)
+ 	unsigned long absent_pages;
+ 	unsigned long pfn;
+ 
+-	start_periodic_check_for_corruption();
+-
+ 	pci_iommu_alloc();
+ 
+ 	/* clear_bss() already clear the empty_zero_page */
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -17,9 +17,21 @@
+  */
+ 
+ #include <asm/iomap.h>
++#include <asm/pat.h>
+ #include <linux/bitops.h>
+ #include <linux/module.h>
+ 
++int is_io_mapping_possible(resource_size_t base, unsigned long size)
++{
++#ifndef CONFIG_X86_PAE
++	/* There is no way to map greater than 1 << 32 address without PAE */
++	if (base + size > 0x100000000ULL)
++		return 0;
++#endif
++	return 1;
++}
++EXPORT_SYMBOL_GPL(is_io_mapping_possible);
++
+ /* Map 'mfn' using fixed map 'type' and protections 'prot'
+  */
+ void *
+@@ -30,6 +42,15 @@ iomap_atomic_prot_pfn(unsigned long mfn,
+ 
+ 	pagefault_disable();
+ 
++	/*
++	 * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
++	 * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
++	 * MTRR is UC or WC.  UC_MINUS gets the real intention, of the
++	 * user, which is "WC if the MTRR is WC, UC if you can't do that."
++	 */
++	if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
++		prot = PAGE_KERNEL_UC_MINUS;
++
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	pgprot_val(prot) |= _PAGE_IOMAP;
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -293,25 +293,6 @@ int page_is_ram(unsigned long pagenr)
+ 	return 0;
+ }
+ 
+-int pagerange_is_ram(unsigned long start, unsigned long end)
+-{
+-	int ram_page = 0, not_rampage = 0;
+-	unsigned long page_nr;
+-
+-	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
+-	     ++page_nr) {
+-		if (page_is_ram(mfn_to_local_pfn(page_nr)))
+-			ram_page = 1;
+-		else
+-			not_rampage = 1;
+-
+-		if (ram_page == not_rampage)
+-			return -1;
+-	}
+-
+-	return ram_page;
+-}
+-
+ /*
+  * Fix up the linear direct mapping of the kernel to avoid cache attribute
+  * conflicts.
+@@ -402,7 +383,8 @@ static void __iomem *__ioremap_caller(re
+ 	 * Check if the request spans more than any BAR in the iomem resource
+ 	 * tree.
+ 	 */
+-	WARN_ON(iomem_map_sanity_check(phys_addr, size));
++	WARN_ONCE(iomem_map_sanity_check(phys_addr, size),
++		  KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
+ 
+ 	/*
+ 	 * Don't allow anybody to remap normal RAM that we're using..
+@@ -746,38 +728,10 @@ void __init early_ioremap_init(void)
+ 	}
+ }
+ 
+-#ifdef CONFIG_X86_32
+-void __init early_ioremap_clear(void)
+-{
+-	pmd_t *pmd;
+-
+-	if (early_ioremap_debug)
+-		printk(KERN_INFO "early_ioremap_clear()\n");
+-
+-	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+-	pmd_clear(pmd);
+-	make_lowmem_page_writable(bm_pte, XENFEAT_writable_page_tables);
+-	/* paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT); */
+-	__flush_tlb_all();
+-}
+-
+ void __init early_ioremap_reset(void)
+ {
+-	enum fixed_addresses idx;
+-	unsigned long addr, phys;
+-	pte_t *pte;
+-
+ 	after_paging_init = 1;
+-	for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
+-		addr = fix_to_virt(idx);
+-		pte = early_ioremap_pte(addr);
+-		if (pte_present(*pte)) {
+-			phys = __pte_val(*pte) & PAGE_MASK;
+-			set_fixmap(idx, phys);
+-		}
+-	}
+ }
+-#endif /* CONFIG_X86_32 */
+ 
+ static void __init __early_set_fixmap(enum fixed_addresses idx,
+ 				   unsigned long phys, pgprot_t flags)
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -524,22 +524,28 @@ static int split_large_page(pte_t *kpte,
+ 		set_pte(&pbase[i], pfn_pte_ma(mfn, ref_prot));
+ 
+ 	/*
+-	 * Install the new, split up pagetable. Important details here:
++	 * Install the new, split up pagetable.
+ 	 *
+-	 * On Intel the NX bit of all levels must be cleared to make a
+-	 * page executable. See section 4.13.2 of Intel 64 and IA-32
+-	 * Architectures Software Developer's Manual).
+-	 *
+-	 * Mark the entry present. The current mapping might be
+-	 * set to not present, which we preserved above.
++	 * We use the standard kernel pagetable protections for the new
++	 * pagetable protections, the actual ptes set above control the
++	 * primary protection behavior:
+ 	 */
+ 	if (!xen_feature(XENFEAT_writable_page_tables) &&
+ 	    HYPERVISOR_update_va_mapping((unsigned long)pbase,
+ 					 mk_pte(base, PAGE_KERNEL_RO), 0))
+ 		BUG();
+-	ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
+-	pgprot_val(ref_prot) |= _PAGE_PRESENT;
+-	__set_pmd_pte(kpte, address, level, mk_pte(base, ref_prot));
++	__set_pmd_pte(kpte, address, level, mk_pte(base, __pgprot(_KERNPG_TABLE)));
++
++	/*
++	 * Intel Atom errata AAH41 workaround.
++	 *
++	 * The real fix should be in hw or in a microcode update, but
++	 * we also probabilistically try to reduce the window of having
++	 * a large TLB mixed with 4K TLBs while instruction fetches are
++	 * going on.
++	 */
++	__flush_tlb_all();
++
+ 	base = NULL;
+ 
+ out_unlock:
+@@ -554,6 +560,36 @@ out_unlock:
+ 	return 0;
+ }
+ 
++static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
++			       int primary)
++{
++	/*
++	 * Ignore all non primary paths.
++	 */
++	if (!primary)
++		return 0;
++
++	/*
++	 * Ignore the NULL PTE for kernel identity mapping, as it is expected
++	 * to have holes.
++	 * Also set numpages to '1' indicating that we processed cpa req for
++	 * one virtual address page and its pfn. TBD: numpages can be set based
++	 * on the initial value and the level returned by lookup_address().
++	 */
++	if (within(vaddr, PAGE_OFFSET,
++		   PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
++		cpa->numpages = 1;
++		cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
++		return 0;
++	} else {
++		WARN(1, KERN_WARNING "CPA: called for zero pte. "
++			"vaddr = %lx cpa->vaddr = %lx\n", vaddr,
++			*cpa->vaddr);
++
++		return -EFAULT;
++	}
++}
++
+ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ {
+ 	unsigned long address;
+@@ -565,21 +601,14 @@ static int __change_page_attr(struct cpa
+ 		address = cpa->vaddr[cpa->curpage];
+ 	else
+ 		address = *cpa->vaddr;
+-
+ repeat:
+ 	kpte = lookup_address(address, &level);
+ 	if (!kpte)
+-		return 0;
++		return __cpa_process_fault(cpa, address, primary);
+ 
+ 	old_pte = *kpte;
+-	if (!__pte_val(old_pte)) {
+-		if (!primary)
+-			return 0;
+-		WARN(1, KERN_WARNING "CPA: called for zero pte. "
+-		       "vaddr = %lx cpa->vaddr = %lx\n", address,
+-		       *cpa->vaddr);
+-		return -EINVAL;
+-	}
++	if (!__pte_val(old_pte))
++		return __cpa_process_fault(cpa, address, primary);
+ 
+ 	if (level == PG_LEVEL_4K) {
+ 		pte_t new_pte;
+@@ -678,12 +707,7 @@ static int cpa_process_alias(struct cpa_
+ 		vaddr = *cpa->vaddr;
+ 
+ 	if (!(within(vaddr, PAGE_OFFSET,
+-		    PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
+-#ifdef CONFIG_X86_64
+-		|| within(vaddr, PAGE_OFFSET + (1UL<<32),
+-		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
+-#endif
+-	)) {
++		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
+ 
+ 		alias_cpa = *cpa;
+ 		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
+@@ -814,6 +838,15 @@ static int change_page_attr_set_clr(unsi
+ 
+ 	vm_unmap_aliases();
+ 
++	/*
++	 * If we're called with lazy mmu updates enabled, the
++	 * in-memory pte state may be stale.  Flush pending updates to
++	 * bring them up to date.
++	 *
++	arch_flush_lazy_mmu_mode();*/
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(true);
++
+ 	cpa.vaddr = addr;
+ 	cpa.numpages = numpages;
+ 	cpa.mask_set = mask_set;
+@@ -856,6 +889,14 @@ static int change_page_attr_set_clr(unsi
+ 	} else
+ 		cpa_flush_all(cache);
+ 
++	/*
++	 * If we've been called with lazy mmu updates enabled, then
++	 * make sure that everything gets flushed out before we
++	 * return.
++	 *
++	arch_flush_lazy_mmu_mode();*/
++	WARN_ON_ONCE(arch_use_lazy_mmu_mode() && !irq_count());
++
+ out:
+ 	return ret;
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/mm/pat-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -11,6 +11,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/debugfs.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/gfp.h>
+ #include <linux/mm.h>
+ #include <linux/fs.h>
+@@ -223,6 +224,33 @@ chk_conflict(struct memtype *new, struct
+ static struct memtype *cached_entry;
+ static u64 cached_start;
+ 
++static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
++{
++	int ram_page = 0, not_rampage = 0;
++	unsigned long page_nr;
++
++	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
++	     ++page_nr) {
++		/*
++		 * For legacy reasons, physical address range in the legacy ISA
++		 * region is tracked as non-RAM. This will allow users of
++		 * /dev/mem to map portions of legacy ISA region, even when
++		 * some of those portions are listed(or not even listed) with
++		 * different e820 types(RAM/reserved/..)
++		 */
++		if (page_nr >= (ISA_END_ADDRESS >> PAGE_SHIFT) &&
++		    page_is_ram(mfn_to_local_pfn(page_nr)))
++			ram_page = 1;
++		else
++			not_rampage = 1;
++
++		if (ram_page == not_rampage)
++			return -1;
++	}
++
++	return ram_page;
++}
++
+ /*
+  * For RAM pages, mark the pages as non WB memory type using
+  * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or
+@@ -345,9 +373,13 @@ int reserve_memtype(u64 start, u64 end, 
+ 					      req_type & _PAGE_CACHE_MASK);
+ 	}
+ 
+-	is_range_ram = pagerange_is_ram(start, end);
++	if (new_type)
++		*new_type = actual_type;
++
++	is_range_ram = pat_pagerange_is_ram(start, end);
+ 	if (is_range_ram == 1)
+-		return reserve_ram_pages_type(start, end, req_type, new_type);
++		return reserve_ram_pages_type(start, end, req_type,
++					      new_type);
+ 	else if (is_range_ram < 0)
+ 		return -EINVAL;
+ 
+@@ -359,9 +391,6 @@ int reserve_memtype(u64 start, u64 end, 
+ 	new->end	= end;
+ 	new->type	= actual_type;
+ 
+-	if (new_type)
+-		*new_type = actual_type;
+-
+ 	spin_lock(&memtype_lock);
+ 
+ 	if (cached_entry && start >= cached_start)
+@@ -449,7 +478,7 @@ int free_memtype(u64 start, u64 end)
+ 	if (is_ISA_range(start, end - 1))
+ 		return 0;
+ 
+-	is_range_ram = pagerange_is_ram(start, end);
++	is_range_ram = pat_pagerange_is_ram(start, end);
+ 	if (is_range_ram == 1)
+ 		return free_ram_pages_type(start, end);
+ 	else if (is_range_ram < 0)
+@@ -608,6 +637,254 @@ void unmap_devmem(unsigned long mfn, uns
+ 	free_memtype(addr, addr + size);
+ }
+ 
++#ifndef CONFIG_XEN
++/*
++ * Internal interface to reserve a range of physical memory with prot.
++ * Reserved non RAM regions only and after successful reserve_memtype,
++ * this func also keeps identity mapping (if any) in sync with this new prot.
++ */
++static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
++				int strict_prot)
++{
++	int is_ram = 0;
++	int id_sz, ret;
++	unsigned long flags;
++	unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
++
++	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
++
++	/*
++	 * reserve_pfn_range() doesn't support RAM pages.
++	 */
++	if (is_ram != 0)
++		return -EINVAL;
++
++	ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
++	if (ret)
++		return ret;
++
++	if (flags != want_flags) {
++		if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
++			free_memtype(paddr, paddr + size);
++			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
++				" for %Lx-%Lx, got %s\n",
++				current->comm, current->pid,
++				cattr_name(want_flags),
++				(unsigned long long)paddr,
++				(unsigned long long)(paddr + size),
++				cattr_name(flags));
++			return -EINVAL;
++		}
++		/*
++		 * We allow returning different type than the one requested in
++		 * non strict case.
++		 */
++		*vma_prot = __pgprot((pgprot_val(*vma_prot) &
++				      (~_PAGE_CACHE_MASK)) |
++				     flags);
++	}
++
++	/* Need to keep identity mapping in sync */
++	if (paddr >= __pa(high_memory))
++		return 0;
++
++	id_sz = (__pa(high_memory) < paddr + size) ?
++				__pa(high_memory) - paddr :
++				size;
++
++	if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
++		free_memtype(paddr, paddr + size);
++		printk(KERN_ERR
++			"%s:%d reserve_pfn_range ioremap_change_attr failed %s "
++			"for %Lx-%Lx\n",
++			current->comm, current->pid,
++			cattr_name(flags),
++			(unsigned long long)paddr,
++			(unsigned long long)(paddr + size));
++		return -EINVAL;
++	}
++	return 0;
++}
++
++/*
++ * Internal interface to free a range of physical memory.
++ * Frees non RAM regions only.
++ */
++static void free_pfn_range(u64 paddr, unsigned long size)
++{
++	int is_ram;
++
++	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
++	if (is_ram == 0)
++		free_memtype(paddr, paddr + size);
++}
++
++/*
++ * track_pfn_vma_copy is called when vma that is covering the pfnmap gets
++ * copied through copy_page_range().
++ *
++ * If the vma has a linear pfn mapping for the entire range, we get the prot
++ * from pte and reserve the entire vma range with single reserve_pfn_range call.
++ * Otherwise, we reserve the entire vma range, my ging through the PTEs page
++ * by page to get physical address and protection.
++ */
++int track_pfn_vma_copy(struct vm_area_struct *vma)
++{
++	int retval = 0;
++	unsigned long i, j;
++	resource_size_t paddr;
++	unsigned long prot;
++	unsigned long vma_start = vma->vm_start;
++	unsigned long vma_end = vma->vm_end;
++	unsigned long vma_size = vma_end - vma_start;
++	pgprot_t pgprot;
++
++	if (!pat_enabled)
++		return 0;
++
++	if (is_linear_pfn_mapping(vma)) {
++		/*
++		 * reserve the whole chunk covered by vma. We need the
++		 * starting address and protection from pte.
++		 */
++		if (follow_phys(vma, vma_start, 0, &prot, &paddr)) {
++			WARN_ON_ONCE(1);
++			return -EINVAL;
++		}
++		pgprot = __pgprot(prot);
++		return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
++	}
++
++	/* reserve entire vma page by page, using pfn and prot from pte */
++	for (i = 0; i < vma_size; i += PAGE_SIZE) {
++		if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
++			continue;
++
++		pgprot = __pgprot(prot);
++		retval = reserve_pfn_range(paddr, PAGE_SIZE, &pgprot, 1);
++		if (retval)
++			goto cleanup_ret;
++	}
++	return 0;
++
++cleanup_ret:
++	/* Reserve error: Cleanup partial reservation and return error */
++	for (j = 0; j < i; j += PAGE_SIZE) {
++		if (follow_phys(vma, vma_start + j, 0, &prot, &paddr))
++			continue;
++
++		free_pfn_range(paddr, PAGE_SIZE);
++	}
++
++	return retval;
++}
++
++/*
++ * track_pfn_vma_new is called when a _new_ pfn mapping is being established
++ * for physical range indicated by pfn and size.
++ *
++ * prot is passed in as a parameter for the new mapping. If the vma has a
++ * linear pfn mapping for the entire range reserve the entire vma range with
++ * single reserve_pfn_range call.
++ * Otherwise, we look t the pfn and size and reserve only the specified range
++ * page by page.
++ *
++ * Note that this function can be called with caller trying to map only a
++ * subrange/page inside the vma.
++ */
++int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
++			unsigned long pfn, unsigned long size)
++{
++	int retval = 0;
++	unsigned long i, j;
++	resource_size_t base_paddr;
++	resource_size_t paddr;
++	unsigned long vma_start = vma->vm_start;
++	unsigned long vma_end = vma->vm_end;
++	unsigned long vma_size = vma_end - vma_start;
++
++	if (!pat_enabled)
++		return 0;
++
++	if (is_linear_pfn_mapping(vma)) {
++		/* reserve the whole chunk starting from vm_pgoff */
++		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
++		return reserve_pfn_range(paddr, vma_size, prot, 0);
++	}
++
++	/* reserve page by page using pfn and size */
++	base_paddr = (resource_size_t)pfn << PAGE_SHIFT;
++	for (i = 0; i < size; i += PAGE_SIZE) {
++		paddr = base_paddr + i;
++		retval = reserve_pfn_range(paddr, PAGE_SIZE, prot, 0);
++		if (retval)
++			goto cleanup_ret;
++	}
++	return 0;
++
++cleanup_ret:
++	/* Reserve error: Cleanup partial reservation and return error */
++	for (j = 0; j < i; j += PAGE_SIZE) {
++		paddr = base_paddr + j;
++		free_pfn_range(paddr, PAGE_SIZE);
++	}
++
++	return retval;
++}
++
++/*
++ * untrack_pfn_vma is called while unmapping a pfnmap for a region.
++ * untrack can be called for a specific region indicated by pfn and size or
++ * can be for the entire vma (in which case size can be zero).
++ */
++void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
++			unsigned long size)
++{
++	unsigned long i;
++	resource_size_t paddr;
++	unsigned long prot;
++	unsigned long vma_start = vma->vm_start;
++	unsigned long vma_end = vma->vm_end;
++	unsigned long vma_size = vma_end - vma_start;
++
++	if (!pat_enabled)
++		return;
++
++	if (is_linear_pfn_mapping(vma)) {
++		/* free the whole chunk starting from vm_pgoff */
++		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
++		free_pfn_range(paddr, vma_size);
++		return;
++	}
++
++	if (size != 0 && size != vma_size) {
++		/* free page by page, using pfn and size */
++		paddr = (resource_size_t)pfn << PAGE_SHIFT;
++		for (i = 0; i < size; i += PAGE_SIZE) {
++			paddr = paddr + i;
++			free_pfn_range(paddr, PAGE_SIZE);
++		}
++	} else {
++		/* free entire vma, page by page, using the pfn from pte */
++		for (i = 0; i < vma_size; i += PAGE_SIZE) {
++			if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
++				continue;
++
++			free_pfn_range(paddr, PAGE_SIZE);
++		}
++	}
++}
++#endif /* CONFIG_XEN */
++
++pgprot_t pgprot_writecombine(pgprot_t prot)
++{
++	if (pat_enabled)
++		return __pgprot(pgprot_val(prot) | _PAGE_CACHE_WC);
++	else
++		return pgprot_noncached(prot);
++}
++EXPORT_SYMBOL_GPL(pgprot_writecombine);
++
+ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
+ 
+ /* get Nth element of the linked list */
+--- sle11sp1-2010-01-20.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/pci/irq-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -16,8 +16,7 @@
+ #include <asm/io_apic.h>
+ #include <linux/irq.h>
+ #include <linux/acpi.h>
+-
+-#include "pci.h"
++#include <asm/pci_x86.h>
+ 
+ #define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
+ #define PIRQ_VERSION 0x0100
+@@ -540,7 +539,7 @@ static int pirq_bios_set(struct pci_dev 
+ {
+ 	struct pci_dev *bridge;
+ 	int pin = pci_get_interrupt_pin(dev, &bridge);
+-	return pcibios_set_irq_routing(bridge, pin, irq);
++	return pcibios_set_irq_routing(bridge, pin - 1, irq);
+ }
+ 
+ #endif
+@@ -579,6 +578,7 @@ static __init int intel_router_probe(str
+ 	case PCI_DEVICE_ID_INTEL_ICH7_1:
+ 	case PCI_DEVICE_ID_INTEL_ICH7_30:
+ 	case PCI_DEVICE_ID_INTEL_ICH7_31:
++	case PCI_DEVICE_ID_INTEL_TGP_LPC:
+ 	case PCI_DEVICE_ID_INTEL_ESB2_0:
+ 	case PCI_DEVICE_ID_INTEL_ICH8_0:
+ 	case PCI_DEVICE_ID_INTEL_ICH8_1:
+@@ -894,7 +894,6 @@ static int pcibios_lookup_irq(struct pci
+ 		dev_dbg(&dev->dev, "no interrupt pin\n");
+ 		return 0;
+ 	}
+-	pin = pin - 1;
+ 
+ 	/* Find IRQ routing entry */
+ 
+@@ -904,17 +903,17 @@ static int pcibios_lookup_irq(struct pci
+ 	info = pirq_get_info(dev);
+ 	if (!info) {
+ 		dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
+-			'A' + pin);
++			'A' + pin - 1);
+ 		return 0;
+ 	}
+-	pirq = info->irq[pin].link;
+-	mask = info->irq[pin].bitmap;
++	pirq = info->irq[pin - 1].link;
++	mask = info->irq[pin - 1].bitmap;
+ 	if (!pirq) {
+-		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
++		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1);
+ 		return 0;
+ 	}
+ 	dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
+-		'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
++		'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs);
+ 	mask &= pcibios_irq_mask;
+ 
+ 	/* Work around broken HP Pavilion Notebooks which assign USB to
+@@ -956,7 +955,7 @@ static int pcibios_lookup_irq(struct pci
+ 				newirq = i;
+ 		}
+ 	}
+-	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
++	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq);
+ 
+ 	/* Check if it is hardcoded */
+ 	if ((pirq & 0xf0) == 0xf0) {
+@@ -984,18 +983,18 @@ static int pcibios_lookup_irq(struct pci
+ 			return 0;
+ 		}
+ 	}
+-	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
++	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
+ 
+ 	/* Update IRQ for all devices with the same pirq value */
+ 	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
+ 		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
+ 		if (!pin)
+ 			continue;
+-		pin--;
++
+ 		info = pirq_get_info(dev2);
+ 		if (!info)
+ 			continue;
+-		if (info->irq[pin].link == pirq) {
++		if (info->irq[pin - 1].link == pirq) {
+ 			/*
+ 			 * We refuse to override the dev->irq
+ 			 * information. Give a warning!
+@@ -1049,6 +1048,9 @@ static void __init pcibios_fixup_irqs(vo
+ 	dev = NULL;
+ 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
++		if (!pin)
++			continue;
++
+ #ifdef CONFIG_X86_IO_APIC
+ 		/*
+ 		 * Recalculate IRQ numbers if we use the I/O APIC.
+@@ -1056,15 +1058,11 @@ static void __init pcibios_fixup_irqs(vo
+ 		if (io_apic_assign_pci_irqs) {
+ 			int irq;
+ 
+-			if (!pin)
+-				continue;
+-
+ 			/*
+ 			 * interrupt pins are numbered starting from 1
+ 			 */
+-			pin--;
+ 			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+-				PCI_SLOT(dev->devfn), pin);
++				PCI_SLOT(dev->devfn), pin - 1);
+ 			/*
+ 			 * Busses behind bridges are typically not listed in the
+ 			 * MP-table.  In this case we have to look up the IRQ
+@@ -1077,22 +1075,22 @@ static void __init pcibios_fixup_irqs(vo
+ 				struct pci_dev *bridge = dev->bus->self;
+ 				int bus;
+ 
+-				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
++				pin = pci_swizzle_interrupt_pin(dev, pin);
+ 				bus = bridge->bus->number;
+ 				irq = IO_APIC_get_PCI_irq_vector(bus,
+-						PCI_SLOT(bridge->devfn), pin);
++						PCI_SLOT(bridge->devfn), pin - 1);
+ 				if (irq >= 0)
+ 					dev_warn(&dev->dev,
+ 						"using bridge %s INT %c to "
+ 							"get IRQ %d\n",
+ 						 pci_name(bridge),
+-						 'A' + pin, irq);
++						 'A' + pin - 1, irq);
+ 			}
+ 			if (irq >= 0) {
+ 				dev_info(&dev->dev,
+ 					"PCI->APIC IRQ transform: INT %c "
+ 						"-> IRQ %d\n",
+-					'A' + pin, irq);
++					'A' + pin - 1, irq);
+ 				dev->irq = irq;
+ 			}
+ 		}
+@@ -1100,7 +1098,7 @@ static void __init pcibios_fixup_irqs(vo
+ 		/*
+ 		 * Still no IRQ? Try to lookup one...
+ 		 */
+-		if (pin && !dev->irq)
++		if (!dev->irq)
+ 			pcibios_lookup_irq(dev, 0);
+ 	}
+ }
+@@ -1227,12 +1225,10 @@ static int pirq_enable_irq(struct pci_de
+ 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+ 		char *msg = "";
+ 
+-		pin--; /* interrupt pins are numbered starting from 1 */
+-
+ 		if (io_apic_assign_pci_irqs) {
+ 			int irq;
+ 
+-			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
++			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
+ 			/*
+ 			 * Busses behind bridges are typically not listed in the MP-table.
+ 			 * In this case we have to look up the IRQ based on the parent bus,
+@@ -1243,20 +1239,20 @@ static int pirq_enable_irq(struct pci_de
+ 			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+ 				struct pci_dev *bridge = dev->bus->self;
+ 
+-				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
++				pin = pci_swizzle_interrupt_pin(dev, pin);
+ 				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+-						PCI_SLOT(bridge->devfn), pin);
++						PCI_SLOT(bridge->devfn), pin - 1);
+ 				if (irq >= 0)
+ 					dev_warn(&dev->dev, "using bridge %s "
+ 						 "INT %c to get IRQ %d\n",
+-						 pci_name(bridge), 'A' + pin,
++						 pci_name(bridge), 'A' + pin - 1,
+ 						 irq);
+ 				dev = bridge;
+ 			}
+ 			dev = temp_dev;
+ 			if (irq >= 0) {
+ 				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
+-					 "INT %c -> IRQ %d\n", 'A' + pin, irq);
++					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
+ 				dev->irq = irq;
+ 				return 0;
+ 			} else
+@@ -1275,7 +1271,7 @@ static int pirq_enable_irq(struct pci_de
+ 			return 0;
+ 
+ 		dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
+-			 'A' + pin, msg);
++			 'A' + pin - 1, msg);
+ 	}
+ 	return 0;
+ }
+--- sle11sp1-2010-01-20.orig/arch/x86/pci/pcifront.c	2009-03-18 10:39:31.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/pci/pcifront.c	2009-11-06 10:51:55.000000000 +0100
+@@ -8,8 +8,8 @@
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <asm/acpi.h>
++#include <asm/pci_x86.h>
+ #include <xen/evtchn.h>
+-#include "pci.h"
+ 
+ static int pcifront_enable_irq(struct pci_dev *dev)
+ {
+--- sle11sp1-2010-01-20.orig/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:55.000000000 +0100
+@@ -349,7 +349,7 @@ int __init sysenter_setup(void)
+ }
+ 
+ /* Setup a VMA at program startup for the vsyscall page */
+-int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
++int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+ {
+ 	struct mm_struct *mm = current->mm;
+ 	unsigned long addr;
+--- sle11sp1-2010-01-20.orig/drivers/acpi/Kconfig	2009-12-04 10:44:40.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/Kconfig	2009-11-06 10:51:55.000000000 +0100
+@@ -9,7 +9,7 @@ menuconfig ACPI
+ 	depends on PCI
+ 	depends on PM
+ 	select PNP
+-	select CPU_IDLE
++	select CPU_IDLE if !PROCESSOR_EXTERNAL_CONTROL
+ 	default y
+ 	help
+ 	  Advanced Configuration and Power Interface (ACPI) support for 
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_extcntl.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_extcntl.c	2009-11-06 10:51:55.000000000 +0100
+@@ -230,3 +230,117 @@ err_out:
+ 	kfree(perf);
+ 	return ret;
+ }
++
++/*
++ * Objects and functions removed in native 2.6.29, and thus moved here.
++ */
++#ifdef CONFIG_SMP
++static void smp_callback(void *v)
++{
++	/* we already woke the CPU up, nothing more to do */
++}
++
++/*
++ * This function gets called when a part of the kernel has a new latency
++ * requirement.  This means we need to get all processors out of their C-state,
++ * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
++ * wakes them all right up.
++ */
++static int acpi_processor_latency_notify(struct notifier_block *b,
++					 unsigned long l, void *v)
++{
++	smp_call_function(smp_callback, NULL, 1);
++	return NOTIFY_OK;
++}
++
++struct notifier_block acpi_processor_latency_notifier = {
++	.notifier_call = acpi_processor_latency_notify,
++};
++#endif
++
++/*
++ * bm_history -- bit-mask with a bit per jiffy of bus-master activity
++ * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
++ * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
++ * 100 HZ: 0x0000000F: 4 jiffies = 40ms
++ * reduce history for more aggressive entry into C3
++ */
++static unsigned int bm_history __read_mostly =
++    (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
++module_param(bm_history, uint, 0644);
++
++int acpi_processor_set_power_policy(struct acpi_processor *pr)
++{
++	unsigned int i;
++	unsigned int state_is_set = 0;
++	struct acpi_processor_cx *lower = NULL;
++	struct acpi_processor_cx *higher = NULL;
++	struct acpi_processor_cx *cx;
++
++
++	if (!pr)
++		return -EINVAL;
++
++	/*
++	 * This function sets the default Cx state policy (OS idle handler).
++	 * Our scheme is to promote quickly to C2 but more conservatively
++	 * to C3.  We're favoring C2  for its characteristics of low latency
++	 * (quick response), good power savings, and ability to allow bus
++	 * mastering activity.  Note that the Cx state policy is completely
++	 * customizable and can be altered dynamically.
++	 */
++
++	/* startup state */
++	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
++		cx = &pr->power.states[i];
++		if (!cx->valid)
++			continue;
++
++		if (!state_is_set)
++			pr->power.state = cx;
++		state_is_set++;
++		break;
++	}
++
++	if (!state_is_set)
++		return -ENODEV;
++
++	/* demotion */
++	for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
++		cx = &pr->power.states[i];
++		if (!cx->valid)
++			continue;
++
++		if (lower) {
++			cx->demotion.state = lower;
++			cx->demotion.threshold.ticks = cx->latency_ticks;
++			cx->demotion.threshold.count = 1;
++			if (cx->type == ACPI_STATE_C3)
++				cx->demotion.threshold.bm = bm_history;
++		}
++
++		lower = cx;
++	}
++
++	/* promotion */
++	for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
++		cx = &pr->power.states[i];
++		if (!cx->valid)
++			continue;
++
++		if (higher) {
++			cx->promotion.state = higher;
++			cx->promotion.threshold.ticks = cx->latency_ticks;
++			if (cx->type >= ACPI_STATE_C2)
++				cx->promotion.threshold.count = 4;
++			else
++				cx->promotion.threshold.count = 10;
++			if (higher->type == ACPI_STATE_C3)
++				cx->promotion.threshold.bm = bm_history;
++		}
++
++		higher = cx;
++	}
++
++	return 0;
++}
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_idle.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_idle.c	2009-11-06 10:51:55.000000000 +0100
+@@ -114,6 +114,7 @@ static struct dmi_system_id __cpuinitdat
+ };
+ 
+ 
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ /*
+  * Callers should disable interrupts before the call and enable
+  * interrupts after return.
+@@ -132,6 +133,7 @@ static void acpi_safe_halt(void)
+ 	}
+ 	current_thread_info()->status |= TS_POLLING;
+ }
++#endif
+ 
+ #ifdef ARCH_APICTIMER_STOPS_ON_C3
+ 
+@@ -196,7 +198,7 @@ static void lapic_timer_state_broadcast(
+ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
+ 				   struct acpi_processor_cx *cstate) { }
+ static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { }
+-static void lapic_timer_state_broadcast(struct acpi_processor *pr,
++static inline void lapic_timer_state_broadcast(struct acpi_processor *pr,
+ 				       struct acpi_processor_cx *cx,
+ 				       int broadcast)
+ {
+@@ -244,7 +246,8 @@ int acpi_processor_resume(struct acpi_de
+ 	return 0;
+ }
+ 
+-#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
++#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) \
++    && !defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
+ static void tsc_check_state(int state)
+ {
+ 	switch (boot_cpu_data.x86_vendor) {
+@@ -517,7 +520,11 @@ static void acpi_processor_power_verify_
+ 	 */
+ 	cx->valid = 1;
+ 
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ 	cx->latency_ticks = cx->latency;
++#else
++	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
++#endif
+ 
+ 	return;
+ }
+@@ -600,7 +607,11 @@ static void acpi_processor_power_verify_
+ 	 */
+ 	cx->valid = 1;
+ 
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ 	cx->latency_ticks = cx->latency;
++#else
++	cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
++#endif
+ 	/*
+ 	 * On older chipsets, BM_RLD needs to be set
+ 	 * in order for Bus Master activity to wake the
+@@ -674,6 +685,20 @@ static int acpi_processor_get_power_info
+ 
+ 	pr->power.count = acpi_processor_power_verify(pr);
+ 
++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++	/*
++	 * Set Default Policy
++	 * ------------------
++	 * Now that we know which states are supported, set the default
++	 * policy.  Note that this policy can be changed dynamically
++	 * (e.g. encourage deeper sleeps to conserve battery life when
++	 * not on AC).
++	 */
++	result = acpi_processor_set_power_policy(pr);
++	if (result)
++		return result;
++#endif
++
+ 	/*
+ 	 * if one state of type C2 or C3 is available, mark this
+ 	 * CPU as being "idle manageable"
+@@ -771,6 +796,7 @@ static const struct file_operations acpi
+ };
+ #endif
+ 
++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
+ /**
+  * acpi_idle_bm_check - checks if bus master activity was detected
+  */
+@@ -1136,6 +1162,13 @@ static int acpi_processor_setup_cpuidle(
+ 	return 0;
+ }
+ 
++#else /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
++static inline int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
++{
++	return 0;
++}
++#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
++
+ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
+ {
+ 	int ret = 0;
+@@ -1202,6 +1235,10 @@ int __cpuinit acpi_processor_power_init(
+ 			       "ACPI: processor limited to max C-state %d\n",
+ 			       max_cstate);
+ 		first_run++;
++#if defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) && defined(CONFIG_SMP)
++		pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
++				    &acpi_processor_latency_notifier);
++#endif
+ 	}
+ 
+ 	if (!pr)
+@@ -1261,5 +1298,12 @@ int acpi_processor_power_exit(struct acp
+ 				  acpi_device_dir(device));
+ #endif
+ 
++#if defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) && defined(CONFIG_SMP)
++	/* Unregister the idle handler when processor #0 is removed. */
++	if (pr->id == 0)
++		pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
++				       &acpi_processor_latency_notifier);
++#endif
++
+ 	return 0;
+ }
+--- sle11sp1-2010-01-20.orig/drivers/gpu/drm/i915/i915_drv.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/gpu/drm/i915/i915_drv.c	2009-11-06 10:51:55.000000000 +0100
+@@ -330,7 +330,7 @@ static struct drm_driver driver = {
+ 		 .open = drm_open,
+ 		 .release = drm_release,
+ 		 .ioctl = drm_ioctl,
+-		 .mmap = drm_gem_mmap,
++		 .mmap = i915_gem_mmap,
+ 		 .poll = drm_poll,
+ 		 .fasync = drm_fasync,
+ #ifdef CONFIG_COMPAT
+--- sle11sp1-2010-01-20.orig/drivers/gpu/drm/i915/i915_drv.h	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/gpu/drm/i915/i915_drv.h	2010-01-20 10:23:43.000000000 +0100
+@@ -825,6 +825,11 @@ uint32_t i915_add_request(struct drm_dev
+ 			  uint32_t flush_domains);
+ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible);
+ int i915_lp_ring_sync(struct drm_device *dev);
++#ifdef CONFIG_XEN
++int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma);
++#else
++#define i915_gem_mmap drm_gem_mmap
++#endif
+ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
+ int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
+ 				      int write);
+--- sle11sp1-2010-01-20.orig/drivers/gpu/drm/i915/i915_gem.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/gpu/drm/i915/i915_gem.c	2010-01-07 10:00:50.000000000 +0100
+@@ -1165,6 +1165,17 @@ i915_gem_mmap_ioctl(struct drm_device *d
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_XEN
++int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++	int ret = drm_gem_mmap(filp, vma);
++
++	pgprot_val(vma->vm_page_prot) |= _PAGE_IOMAP;
++
++	return ret;
++}
++#endif
++
+ /**
+  * i915_gem_fault - fault a page into the GTT
+  * vma: VMA in question
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/buffer_sync.c	2009-11-06 10:45:37.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/buffer_sync.c	2009-11-06 10:51:55.000000000 +0100
+@@ -536,7 +536,6 @@ void sync_buffer(int cpu)
+ 	int cpu_mode = CPU_MODE_KERNEL;
+ 	sync_buffer_state state = sb_buffer_start;
+ 	unsigned int i;
+-	int domain_switch = 0;
+ 	unsigned long available;
+ 	unsigned long flags;
+ 	struct op_entry entry;
+@@ -561,15 +560,6 @@ void sync_buffer(int cpu)
+ 		if (!sample)
+ 			break;
+ 
+-#ifdef CONFIG_XEN
+-		if (domain_switch) {
+-			cpu_current_domain[cpu] = sample->eip;
+-			add_domain_switch(sample->eip);
+-			domain_switch = 0;
+-			continue;
+-		}
+-#endif
+-
+ 		if (is_code(sample->eip)) {
+ 			flags = sample->event;
+ 			if (flags & TRACE_BEGIN) {
+@@ -595,8 +585,11 @@ void sync_buffer(int cpu)
+ 				add_user_ctx_switch(new, cookie);
+ 			}
+ #ifdef CONFIG_XEN
+-			if (flags & DOMAIN_SWITCH)
+-				domain_switch = 1;
++			if ((flags & DOMAIN_SWITCH)
++			    && op_cpu_buffer_get_data(&entry, &val)) {
++				cpu_current_domain[cpu] = val;
++				add_domain_switch(val);
++			}
+ #endif
+ 			if (op_cpu_buffer_get_size(&entry))
+ 				add_data(&entry, mm);
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/cpu_buffer.c	2009-11-06 10:51:32.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/cpu_buffer.c	2009-11-06 10:51:55.000000000 +0100
+@@ -445,34 +445,15 @@ void oprofile_add_pc(unsigned long pc, i
+ 
+ #ifdef CONFIG_XEN
+ /*
+- * This is basically log_sample(b, ESCAPE_CODE, cpu_mode, CPU_TRACE_BEGIN),
++ * This is basically log_sample(b, ESCAPE_CODE, 1, cpu_mode, CPU_TRACE_BEGIN),
+  * as was previously accessible through oprofile_add_pc().
+  */
+ void oprofile_add_mode(int cpu_mode)
+ {
+ 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+-	struct task_struct *task;
+ 
+-	if (nr_available_slots(cpu_buf) < 3) {
++	if (op_add_code(cpu_buf, 1, cpu_mode, current))
+ 		cpu_buf->sample_lost_overflow++;
+-		return;
+-	}
+-
+-	task = current;
+-
+-	/* notice a switch from user->kernel or vice versa */
+-	if (cpu_buf->last_cpu_mode != cpu_mode) {
+-		cpu_buf->last_cpu_mode = cpu_mode;
+-		add_code(cpu_buf, cpu_mode);
+-	}
+-
+-	/* notice a task switch */
+-	if (cpu_buf->last_task != task) {
+-		cpu_buf->last_task = task;
+-		add_code(cpu_buf, (unsigned long)task);
+-	}
+-
+-	add_code(cpu_buf, CPU_TRACE_BEGIN);
+ }
+ #endif
+ 
+@@ -503,17 +484,18 @@ fail:
+ #ifdef CONFIG_XEN
+ int oprofile_add_domain_switch(int32_t domain_id)
+ {
+-	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
++	struct op_entry entry;
++	struct op_sample *sample;
+ 
+-	/* should have space for switching into and out of domain
+-	   (2 slots each) plus one sample and one cpu mode switch */
+-	if (((nr_available_slots(cpu_buf) < 6) &&
+-	     (domain_id != COORDINATOR_DOMAIN)) ||
+-	    (nr_available_slots(cpu_buf) < 2))
++	sample = op_cpu_buffer_write_reserve(&entry, 1);
++	if (!sample)
+ 		return 0;
+ 
+-	add_code(cpu_buf, DOMAIN_SWITCH);
+-	add_sample(cpu_buf, domain_id, 0);
++	sample->eip = ESCAPE_CODE;
++	sample->event = DOMAIN_SWITCH;
++
++	op_cpu_buffer_add_data(&entry, domain_id);
++	op_cpu_buffer_write_commit(&entry);
+ 
+ 	current_domain = domain_id;
+ 
+--- sle11sp1-2010-01-20.orig/drivers/pci/msi-xen.c	2009-12-04 11:28:36.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/pci/msi-xen.c	2009-12-04 11:28:44.000000000 +0100
+@@ -763,30 +763,21 @@ void pci_no_msi(void)
+ 	pci_msi_enable = 0;
+ }
+ 
++/**
++ * pci_msi_enabled - is MSI enabled?
++ *
++ * Returns true if MSI has not been disabled by the command-line option
++ * pci=nomsi.
++ **/
++int pci_msi_enabled(void)
++{
++	return pci_msi_enable;
++}
++EXPORT_SYMBOL(pci_msi_enabled);
++
+ void pci_msi_init_pci_dev(struct pci_dev *dev)
+ {
+ #ifndef CONFIG_XEN
+ 	INIT_LIST_HEAD(&dev->msi_list);
+ #endif
+ }
+-
+-#ifdef CONFIG_ACPI
+-#include <linux/acpi.h>
+-#include <linux/pci-acpi.h>
+-static void __devinit msi_acpi_init(void)
+-{
+-	if (acpi_pci_disabled)
+-		return;
+-	pci_osc_support_set(OSC_MSI_SUPPORT);
+-	pcie_osc_support_set(OSC_MSI_SUPPORT);
+-}
+-#else
+-static inline void msi_acpi_init(void) { }
+-#endif /* CONFIG_ACPI */
+-
+-void __devinit msi_init(void)
+-{
+-	if (!pci_msi_enable)
+-		return;
+-	msi_acpi_init();
+-}
+--- sle11sp1-2010-01-20.orig/drivers/xen/Kconfig	2009-11-06 10:51:32.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/Kconfig	2009-12-18 12:27:38.000000000 +0100
+@@ -386,7 +386,7 @@ config XEN_DEV_EVTCHN
+ 
+ config XENFS
+ 	tristate "Xen filesystem"
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	default y
+ 	help
+ 	  The xen filesystem provides a way for domains to share
+--- sle11sp1-2010-01-20.orig/drivers/xen/Makefile	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/Makefile	2009-11-06 10:51:55.000000000 +0100
+@@ -14,6 +14,7 @@ obj-$(CONFIG_XEN)		+= features.o util.o
+ obj-$(CONFIG_HOTPLUG_CPU)	+= $(xen-hotplug-y)
+ obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
+ obj-$(CONFIG_XEN_BALLOON)	+= $(xen-balloon-y)
++obj-$(CONFIG_XENFS)		+= xenfs/
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+ obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
+ obj-$(CONFIG_XEN_BLKDEV_TAP2)           += blktap2/
+--- sle11sp1-2010-01-20.orig/drivers/xen/balloon/sysfs.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/balloon/sysfs.c	2009-11-06 10:51:55.000000000 +0100
+@@ -67,7 +67,7 @@ static ssize_t store_target_kb(struct sy
+ 			       struct sysdev_attribute *attr,
+ 			       const char *buf, size_t count)
+ {
+-	char memstring[64], *endchar;
++	char *endchar;
+ 	unsigned long long target_bytes;
+ 
+ 	if (!capable(CAP_SYS_ADMIN))
+@@ -75,11 +75,8 @@ static ssize_t store_target_kb(struct sy
+ 	
+ 	if (count <= 1)
+ 		return -EBADMSG; /* runt */
+-	if (count > sizeof(memstring))
+-		return -EFBIG;   /* too long */
+-	strcpy(memstring, buf);
+ 	
+-	target_bytes = memparse(memstring, &endchar);
++	target_bytes = simple_strtoull(buf, &endchar, 0) << 10;
+ 	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+ 	
+ 	return count;
+@@ -88,8 +85,40 @@ static ssize_t store_target_kb(struct sy
+ static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
+ 		   show_target_kb, store_target_kb);
+ 
++static ssize_t show_target(struct sys_device *dev,
++			   struct sysdev_attribute *attr, char *buf)
++{
++	return sprintf(buf, "%llu\n",
++		       (unsigned long long)balloon_stats.target_pages
++		       << PAGE_SHIFT);
++}
++
++static ssize_t store_target(struct sys_device *dev,
++			    struct sysdev_attribute *attr,
++			    const char *buf,
++			    size_t count)
++{
++	char *endchar;
++	unsigned long long target_bytes;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (count <= 1)
++		return -EBADMSG; /* runt */
++
++	target_bytes = memparse(buf, &endchar);
++	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++
++	return count;
++}
++
++static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
++		   show_target, store_target);
++
+ static struct sysdev_attribute *balloon_attrs[] = {
+ 	&attr_target_kb,
++	&attr_target,
+ };
+ 
+ static struct attribute *balloon_info_attrs[] = {
+--- sle11sp1-2010-01-20.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:49:11.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/blkfront/vbd.c	2010-01-18 16:50:37.000000000 +0100
+@@ -308,6 +308,10 @@ xlvbd_init_blk_queue(struct gendisk *gd,
+ 	if (rq == NULL)
+ 		return -1;
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
++#endif
++
+ 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
+ 	blk_queue_hardsect_size(rq, sector_size);
+ 	blk_queue_max_sectors(rq, 512);
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/cpu_hotplug.c	2009-04-07 13:58:48.000000000 +0200
++++ sle11sp1-2010-01-20/drivers/xen/core/cpu_hotplug.c	2009-11-06 10:51:55.000000000 +0100
+@@ -10,10 +10,10 @@
+  * Set of CPUs that remote admin software will allow us to bring online.
+  * Notified to us via xenbus.
+  */
+-static cpumask_t xenbus_allowed_cpumask;
++static cpumask_var_t xenbus_allowed_cpumask;
+ 
+ /* Set of CPUs that local admin will allow us to bring online. */
+-static cpumask_t local_allowed_cpumask = CPU_MASK_ALL;
++static cpumask_var_t local_allowed_cpumask;
+ 
+ static int local_cpu_hotplug_request(void)
+ {
+@@ -40,10 +40,10 @@ static void vcpu_hotplug(unsigned int cp
+ 	}
+ 
+ 	if (strcmp(state, "online") == 0) {
+-		cpu_set(cpu, xenbus_allowed_cpumask);
++		cpumask_set_cpu(cpu, xenbus_allowed_cpumask);
+ 		(void)cpu_up(cpu);
+ 	} else if (strcmp(state, "offline") == 0) {
+-		cpu_clear(cpu, xenbus_allowed_cpumask);
++		cpumask_clear_cpu(cpu, xenbus_allowed_cpumask);
+ 		(void)cpu_down(cpu);
+ 	} else {
+ 		printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
+@@ -75,7 +75,7 @@ static int smpboot_cpu_notify(struct not
+ 	 * as it's always executed from within a stopmachine kthread.
+ 	 */
+ 	if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
+-		cpu_clear(cpu, local_allowed_cpumask);
++		cpumask_clear_cpu(cpu, local_allowed_cpumask);
+ 
+ 	return NOTIFY_OK;
+ }
+@@ -156,21 +156,26 @@ int cpu_up_check(unsigned int cpu)
+ 	int rc = 0;
+ 
+ 	if (local_cpu_hotplug_request()) {
+-		cpu_set(cpu, local_allowed_cpumask);
+-		if (!cpu_isset(cpu, xenbus_allowed_cpumask)) {
++		cpumask_set_cpu(cpu, local_allowed_cpumask);
++		if (!cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
+ 			printk("%s: attempt to bring up CPU %u disallowed by "
+ 			       "remote admin.\n", __FUNCTION__, cpu);
+ 			rc = -EBUSY;
+ 		}
+-	} else if (!cpu_isset(cpu, local_allowed_cpumask) ||
+-		   !cpu_isset(cpu, xenbus_allowed_cpumask)) {
++	} else if (!cpumask_test_cpu(cpu, local_allowed_cpumask) ||
++		   !cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
+ 		rc = -EBUSY;
+ 	}
+ 
+ 	return rc;
+ }
+ 
+-void init_xenbus_allowed_cpumask(void)
++void __init init_xenbus_allowed_cpumask(void)
+ {
+-	xenbus_allowed_cpumask = cpu_present_map;
++	if (!alloc_cpumask_var(&xenbus_allowed_cpumask, GFP_KERNEL))
++		BUG();
++	cpumask_copy(xenbus_allowed_cpumask, cpu_present_mask);
++	if (!alloc_cpumask_var(&local_allowed_cpumask, GFP_KERNEL))
++		BUG();
++	cpumask_setall(local_allowed_cpumask);
+ }
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/evtchn.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/evtchn.c	2009-11-06 10:51:55.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <linux/sched.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/bootmem.h>
++#include <linux/ftrace.h>
+ #include <linux/version.h>
+ #include <asm/atomic.h>
+ #include <asm/system.h>
+@@ -57,9 +58,6 @@ static DEFINE_SPINLOCK(irq_mapping_updat
+ static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+ 	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
+ 
+-/* Packed IRQ information: binding type, sub-type index, and event channel. */
+-static u32 irq_info[NR_IRQS];
+-
+ /* Binding types. */
+ enum {
+ 	IRQT_UNBOUND,
+@@ -75,6 +73,30 @@ enum {
+ #define _EVTCHN_BITS 12
+ #define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
+ 
++/* Convenient shorthand for packed representation of an unbound IRQ. */
++#define IRQ_UNBOUND	(IRQT_UNBOUND << (32 - _IRQT_BITS))
++
++static struct irq_cfg _irq_cfg[] = {
++	[0 ...
++#ifdef CONFIG_SPARSE_IRQ
++	       BUILD_BUG_ON_ZERO(PIRQ_BASE) + NR_IRQS_LEGACY
++#else
++	       NR_IRQS
++#endif
++		       - 1].info = IRQ_UNBOUND
++};
++
++static inline struct irq_cfg *__pure irq_cfg(unsigned int irq)
++{
++#ifdef CONFIG_SPARSE_IRQ
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	return desc ? desc->chip_data : NULL;
++#else
++	return irq < NR_IRQS ? _irq_cfg + irq : NULL;
++#endif
++}
++
+ /* Constructor for packed IRQ information. */
+ static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
+ {
+@@ -90,26 +112,30 @@ static inline u32 mk_irq_info(u32 type, 
+ 	return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
+ }
+ 
+-/* Convenient shorthand for packed representation of an unbound IRQ. */
+-#define IRQ_UNBOUND	mk_irq_info(IRQT_UNBOUND, 0, 0)
+-
+ /*
+  * Accessors for packed IRQ information.
+  */
+ 
+ static inline unsigned int evtchn_from_irq(int irq)
+ {
+-	return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
++	const struct irq_cfg *cfg = irq_cfg(irq);
++
++	return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
+ }
+ 
+ static inline unsigned int index_from_irq(int irq)
+ {
+-	return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
++	const struct irq_cfg *cfg = irq_cfg(irq);
++
++	return cfg ? (cfg->info >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1)
++		   : 0;
+ }
+ 
+ static inline unsigned int type_from_irq(int irq)
+ {
+-	return irq_info[irq] >> (32 - _IRQT_BITS);
++	const struct irq_cfg *cfg = irq_cfg(irq);
++
++	return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
+ }
+ 
+ /* IRQ <-> VIRQ mapping. */
+@@ -121,9 +147,6 @@ DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS
+ #endif
+ DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1};
+ 
+-/* Reference counts for bindings to IRQs. */
+-static int irq_bindcount[NR_IRQS];
+-
+ #ifdef CONFIG_SMP
+ 
+ static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+@@ -157,8 +180,12 @@ static void init_evtchn_cpu_bindings(voi
+ 	int i;
+ 
+ 	/* By default all event channels notify CPU#0. */
+-	for (i = 0; i < NR_IRQS; i++)
+-		irq_to_desc(i)->affinity = cpumask_of_cpu(0);
++	for (i = 0; i < nr_irqs; i++) {
++		struct irq_desc *desc = irq_to_desc(i);
++
++		if (desc)
++			desc->affinity = cpumask_of_cpu(0);
++	}
+ 
+ 	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+ 	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+@@ -232,7 +259,7 @@ static DEFINE_PER_CPU(unsigned int, last
+ static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 };
+ 
+ /* NB. Interrupts are disabled on entry. */
+-asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
++asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs)
+ {
+ 	unsigned long       l1, l2;
+ 	unsigned long       masked_l1, masked_l2;
+@@ -314,14 +341,25 @@ asmlinkage void evtchn_do_upcall(struct 
+ 	irq_exit();
+ }
+ 
+-static int find_unbound_irq(void)
++static struct irq_chip dynirq_chip;
++
++static int find_unbound_irq(unsigned int cpu)
+ {
+ 	static int warned;
+ 	int irq;
+ 
+-	for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++)
+-		if (irq_bindcount[irq] == 0)
++	for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++) {
++		struct irq_desc *desc = irq_to_desc_alloc_cpu(irq, cpu);
++		struct irq_cfg *cfg = desc->chip_data;
++
++		if (!cfg->bindcount) {
++			desc->status |= IRQ_NOPROBE;
++			set_irq_chip_and_handler_name(irq, &dynirq_chip,
++						      handle_level_irq,
++						      "level");
+ 			return irq;
++		}
++	}
+ 
+ 	if (!warned) {
+ 		warned = 1;
+@@ -339,14 +377,15 @@ static int bind_caller_port_to_irq(unsig
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = evtchn_to_irq[caller_port]) == -1) {
+-		if ((irq = find_unbound_irq()) < 0)
++		if ((irq = find_unbound_irq(smp_processor_id())) < 0)
+ 			goto out;
+ 
+ 		evtchn_to_irq[caller_port] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_CALLER_PORT, 0, caller_port);
++		irq_cfg(irq)->info = mk_irq_info(IRQT_CALLER_PORT,
++						  0, caller_port);
+ 	}
+ 
+-	irq_bindcount[irq]++;
++	irq_cfg(irq)->bindcount++;
+ 
+  out:
+ 	spin_unlock(&irq_mapping_update_lock);
+@@ -361,7 +400,7 @@ static int bind_local_port_to_irq(unsign
+ 
+ 	BUG_ON(evtchn_to_irq[local_port] != -1);
+ 
+-	if ((irq = find_unbound_irq()) < 0) {
++	if ((irq = find_unbound_irq(smp_processor_id())) < 0) {
+ 		struct evtchn_close close = { .port = local_port };
+ 		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+ 			BUG();
+@@ -369,8 +408,8 @@ static int bind_local_port_to_irq(unsign
+ 	}
+ 
+ 	evtchn_to_irq[local_port] = irq;
+-	irq_info[irq] = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
+-	irq_bindcount[irq]++;
++	irq_cfg(irq)->info = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
++	irq_cfg(irq)->bindcount++;
+ 
+  out:
+ 	spin_unlock(&irq_mapping_update_lock);
+@@ -414,7 +453,7 @@ static int bind_virq_to_irq(unsigned int
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+-		if ((irq = find_unbound_irq()) < 0)
++		if ((irq = find_unbound_irq(cpu)) < 0)
+ 			goto out;
+ 
+ 		bind_virq.virq = virq;
+@@ -425,14 +464,14 @@ static int bind_virq_to_irq(unsigned int
+ 		evtchn = bind_virq.port;
+ 
+ 		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+ 
+ 		per_cpu(virq_to_irq, cpu)[virq] = irq;
+ 
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 	}
+ 
+-	irq_bindcount[irq]++;
++	irq_cfg(irq)->bindcount++;
+ 
+  out:
+ 	spin_unlock(&irq_mapping_update_lock);
+@@ -447,7 +486,7 @@ static int bind_ipi_to_irq(unsigned int 
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
+-		if ((irq = find_unbound_irq()) < 0)
++		if ((irq = find_unbound_irq(cpu)) < 0)
+ 			goto out;
+ 
+ 		bind_ipi.vcpu = cpu;
+@@ -457,14 +496,14 @@ static int bind_ipi_to_irq(unsigned int 
+ 		evtchn = bind_ipi.port;
+ 
+ 		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
+ 
+ 		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+ 
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 	}
+ 
+-	irq_bindcount[irq]++;
++	irq_cfg(irq)->bindcount++;
+ 
+  out:
+ 	spin_unlock(&irq_mapping_update_lock);
+@@ -479,7 +518,7 @@ static void unbind_from_irq(unsigned int
+ 
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+-	if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
++	if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
+ 		close.port = evtchn;
+ 		if ((type_from_irq(irq) != IRQT_CALLER_PORT) &&
+ 		    HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+@@ -502,11 +541,15 @@ static void unbind_from_irq(unsigned int
+ 		bind_evtchn_to_cpu(evtchn, 0);
+ 
+ 		evtchn_to_irq[evtchn] = -1;
+-		irq_info[irq] = IRQ_UNBOUND;
++		irq_cfg(irq)->info = IRQ_UNBOUND;
+ 
+ 		/* Zap stats across IRQ changes of use. */
+ 		for_each_possible_cpu(cpu)
++#ifdef CONFIG_SPARSE_IRQ
++			irq_to_desc(irq)->kstat_irqs[cpu] = 0;
++#else
+ 			kstat_cpu(cpu).irqs[irq] = 0;
++#endif
+ 	}
+ 
+ 	spin_unlock(&irq_mapping_update_lock);
+@@ -658,10 +701,9 @@ static void rebind_irq_to_cpu(unsigned i
+ 		rebind_evtchn_to_cpu(evtchn, tcpu);
+ }
+ 
+-static void set_affinity_irq(unsigned int irq, cpumask_t dest)
++static void set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+ {
+-	unsigned tcpu = first_cpu(dest);
+-	rebind_irq_to_cpu(irq, tcpu);
++	rebind_irq_to_cpu(irq, cpumask_first(dest));
+ }
+ #endif
+ 
+@@ -830,7 +872,7 @@ static unsigned int startup_pirq(unsigne
+ 
+ 	evtchn_to_irq[evtchn] = irq;
+ 	bind_evtchn_to_cpu(evtchn, 0);
+-	irq_info[irq] = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
++	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
+ 
+  out:
+ 	pirq_unmask_and_notify(evtchn, irq);
+@@ -854,7 +896,7 @@ static void shutdown_pirq(unsigned int i
+ 
+ 	bind_evtchn_to_cpu(evtchn, 0);
+ 	evtchn_to_irq[evtchn] = -1;
+-	irq_info[irq] = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
++	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
+ }
+ 
+ static void unmask_pirq(unsigned int irq)
+@@ -1021,7 +1063,7 @@ static void restore_cpu_virqs(unsigned i
+ 		if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
+ 			continue;
+ 
+-		BUG_ON(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0));
++		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_VIRQ, virq, 0));
+ 
+ 		/* Get a new binding from Xen. */
+ 		bind_virq.virq = virq;
+@@ -1033,7 +1075,7 @@ static void restore_cpu_virqs(unsigned i
+ 
+ 		/* Record the new mapping. */
+ 		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+@@ -1050,7 +1092,7 @@ static void restore_cpu_ipis(unsigned in
+ 		if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
+ 			continue;
+ 
+-		BUG_ON(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0));
++		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_IPI, ipi, 0));
+ 
+ 		/* Get a new binding from Xen. */
+ 		bind_ipi.vcpu = cpu;
+@@ -1061,7 +1103,7 @@ static void restore_cpu_ipis(unsigned in
+ 
+ 		/* Record the new mapping. */
+ 		evtchn_to_irq[evtchn] = irq;
+-		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+@@ -1073,6 +1115,7 @@ static void restore_cpu_ipis(unsigned in
+ void irq_resume(void)
+ {
+ 	unsigned int cpu, irq, evtchn;
++	struct irq_cfg *cfg;
+ 
+ 	init_evtchn_cpu_bindings();
+ 
+@@ -1089,12 +1132,17 @@ void irq_resume(void)
+ 		mask_evtchn(evtchn);
+ 
+ 	/* Check that no PIRQs are still bound. */
+-	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + NR_PIRQS); irq++)
+-		BUG_ON(irq_info[irq] != IRQ_UNBOUND);
++	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + NR_PIRQS); irq++) {
++		cfg = irq_cfg(irq);
++		BUG_ON(cfg && cfg->info != IRQ_UNBOUND);
++	}
+ 
+ 	/* No IRQ <-> event-channel mappings. */
+-	for (irq = 0; irq < NR_IRQS; irq++)
+-		irq_info[irq] &= ~((1U << _EVTCHN_BITS) - 1);
++	for (irq = 0; irq < nr_irqs; irq++) {
++		cfg = irq_cfg(irq);
++		if (cfg)
++			cfg->info &= ~((1U << _EVTCHN_BITS) - 1);
++	}
+ 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
+ 		evtchn_to_irq[evtchn] = -1;
+ 
+@@ -1106,10 +1154,56 @@ void irq_resume(void)
+ }
+ #endif
+ 
++int __init arch_early_irq_init(void)
++{
++	unsigned int i;
++
++	for (i = 0; i < ARRAY_SIZE(_irq_cfg); i++)
++		irq_to_desc(i)->chip_data = _irq_cfg + i;
++
++	return 0;
++}
++
++#ifdef CONFIG_SPARSE_IRQ
++int arch_init_chip_data(struct irq_desc *desc, int cpu)
++{
++	if (!desc->chip_data) {
++		/* By default all event channels notify CPU#0. */
++		desc->affinity = cpumask_of_cpu(0);
++
++		desc->chip_data = kzalloc(sizeof(struct irq_cfg), GFP_ATOMIC);
++	}
++	if (!desc->chip_data) {
++		printk(KERN_ERR "cannot alloc irq_cfg\n");
++		BUG();
++	}
++
++	return 0;
++}
++#endif
++
+ #if defined(CONFIG_X86_IO_APIC)
++int assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
++{
++	struct physdev_irq irq_op;
++
++	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
++		return -EINVAL;
++
++	if (cfg->vector)
++		return 0;
++
++	irq_op.irq = irq;
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
++		return -ENOSPC;
++
++	cfg->vector = irq_op.vector;
++
++	return 0;
++}
+ #define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
+ #elif defined(CONFIG_X86)
+-#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
++#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < NR_IRQS_LEGACY)
+ #else
+ #define identity_mapped_irq(irq) (1)
+ #endif
+@@ -1119,7 +1213,7 @@ void evtchn_register_pirq(int irq)
+ 	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS);
+ 	if (identity_mapped_irq(irq) || type_from_irq(irq) != IRQT_UNBOUND)
+ 		return;
+-	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
++	irq_cfg(irq)->info = mk_irq_info(IRQT_PIRQ, irq, 0);
+ 	set_irq_chip_and_handler_name(irq, &pirq_chip, handle_level_irq,
+ 				      "level");
+ }
+@@ -1132,12 +1226,17 @@ int evtchn_map_pirq(int irq, int xen_pir
+ 		irq = PIRQ_BASE + NR_PIRQS - 1;
+ 		spin_lock(&irq_alloc_lock);
+ 		do {
++			struct irq_desc *desc;
++			struct irq_cfg *cfg;
++
+ 			if (identity_mapped_irq(irq))
+ 				continue;
++			desc = irq_to_desc_alloc_cpu(irq, smp_processor_id());
++			cfg = desc->chip_data;
+ 			if (!index_from_irq(irq)) {
+ 				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
+-				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
+-							    xen_pirq, 0);
++				cfg->info = mk_irq_info(IRQT_PIRQ,
++							xen_pirq, 0);
+ 				break;
+ 			}
+ 		} while (--irq >= PIRQ_BASE);
+@@ -1156,7 +1255,7 @@ int evtchn_map_pirq(int irq, int xen_pir
+ 		 * then causes a warning in dynamic_irq_cleanup().
+ 		 */
+ 		set_irq_chip_and_handler(irq, NULL, NULL);
+-		irq_info[irq] = IRQ_UNBOUND;
++		irq_cfg(irq)->info = IRQ_UNBOUND;
+ 		return 0;
+ 	} else if (type_from_irq(irq) != IRQT_PIRQ
+ 		   || index_from_irq(irq) != xen_pirq) {
+@@ -1193,23 +1292,17 @@ void __init xen_init_IRQ(void)
+ 	for (i = 0; i < NR_EVENT_CHANNELS; i++)
+ 		mask_evtchn(i);
+ 
+-	/* No IRQ -> event-channel mappings. */
+-	for (i = 0; i < NR_IRQS; i++)
+-		irq_info[i] = IRQ_UNBOUND;
+-
+-	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
++#ifndef CONFIG_SPARSE_IRQ
+ 	for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
+-		irq_bindcount[i] = 0;
+-
+ 		irq_to_desc(i)->status |= IRQ_NOPROBE;
+ 		set_irq_chip_and_handler_name(i, &dynirq_chip,
+ 					      handle_level_irq, "level");
+ 	}
+ 
+-	/* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+ 	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
+-		irq_bindcount[i] = 1;
+-
++#else
++	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_IRQS_LEGACY); i++) {
++#endif
+ 		if (!identity_mapped_irq(i))
+ 			continue;
+ 
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/machine_reboot.c	2009-11-23 10:40:43.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/machine_reboot.c	2009-12-18 13:34:27.000000000 +0100
+@@ -19,6 +19,9 @@
+ #include <xen/interface/vcpu.h>
+ 
+ #if defined(__i386__) || defined(__x86_64__)
++#include <asm/pci_x86.h>
++/* TBD: Dom0 should propagate the determined value to Xen. */
++bool port_cf9_safe = false;
+ 
+ /*
+  * Power off function, if any
+@@ -84,7 +87,7 @@ static void post_suspend(int suspend_can
+ 			pfn_to_mfn(xen_start_info->console.domU.mfn);
+ 	} else {
+ #ifdef CONFIG_SMP
+-		cpu_initialized_map = cpu_online_map;
++		cpumask_copy(vcpu_initialized_mask, cpu_online_mask);
+ #endif
+ 		for_each_possible_cpu(i)
+ 			setup_runstate_area(i);
+@@ -222,6 +225,12 @@ int __xen_suspend(int fast_suspend, void
+ 	if (num_possible_cpus() == 1)
+ 		fast_suspend = 0;
+ 
++	if (fast_suspend) {
++		err = stop_machine_create();
++		if (err)
++			return err;
++	}
++
+ 	suspend.fast_suspend = fast_suspend;
+ 	suspend.resume_notifier = resume_notifier;
+ 
+@@ -248,6 +257,8 @@ int __xen_suspend(int fast_suspend, void
+ 
+ 	if (!fast_suspend)
+ 		smp_resume();
++	else
++		stop_machine_destroy();
+ 
+ 	return 0;
+ }
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/smpboot.c	2009-11-06 10:51:55.000000000 +0100
+@@ -36,11 +36,7 @@ extern void smp_trap_init(trap_info_t *)
+ /* Number of siblings per CPU package */
+ int smp_num_siblings = 1;
+ 
+-cpumask_t cpu_online_map;
+-EXPORT_SYMBOL(cpu_online_map);
+-cpumask_t cpu_possible_map;
+-EXPORT_SYMBOL(cpu_possible_map);
+-cpumask_t cpu_initialized_map;
++cpumask_var_t vcpu_initialized_mask;
+ 
+ DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info);
+ EXPORT_PER_CPU_SYMBOL(cpu_info);
+@@ -72,7 +68,7 @@ void __init prefill_possible_map(void)
+ 	for (i = 0; i < NR_CPUS; i++) {
+ 		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+ 		if (rc >= 0) {
+-			cpu_set(i, cpu_possible_map);
++			set_cpu_possible(i, true);
+ 			nr_cpu_ids = i + 1;
+ 		}
+ 	}
+@@ -199,7 +195,7 @@ static void __cpuinit cpu_initialize_con
+ 
+ 	struct task_struct *idle = idle_task(cpu);
+ 
+-	if (cpu_test_and_set(cpu, cpu_initialized_map))
++	if (cpumask_test_and_set_cpu(cpu, vcpu_initialized_mask))
+ 		return;
+ 
+ 	spin_lock(&ctxt_lock);
+@@ -280,13 +276,15 @@ void __init smp_prepare_cpus(unsigned in
+ 	if (xen_smp_intr_init(0))
+ 		BUG();
+ 
+-	cpu_initialized_map = cpumask_of_cpu(0);
++	if (!alloc_cpumask_var(&vcpu_initialized_mask, GFP_KERNEL))
++		BUG();
++	cpumask_copy(vcpu_initialized_mask, cpumask_of(0));
+ 
+ 	/* Restrict the possible_map according to max_cpus. */
+ 	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
+-		for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
++		for (cpu = nr_cpu_ids-1; !cpumask_test_cpu(cpu, cpu_possible_mask); cpu--)
+ 			continue;
+-		cpu_clear(cpu, cpu_possible_map);
++		set_cpu_possible(cpu, false);
+ 	}
+ 
+ 	for_each_possible_cpu (cpu) {
+@@ -324,10 +322,8 @@ void __init smp_prepare_cpus(unsigned in
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ 		if (is_initial_xendomain())
+-			cpu_set(cpu, cpu_present_map);
+-#else
+-		cpu_set(cpu, cpu_present_map);
+ #endif
++			set_cpu_present(cpu, true);
+ 	}
+ 
+ 	init_xenbus_allowed_cpumask();
+@@ -360,14 +356,17 @@ void __init smp_prepare_boot_cpu(void)
+  */
+ static int __init initialize_cpu_present_map(void)
+ {
+-	cpu_present_map = cpu_possible_map;
++	unsigned int cpu;
++
++	for_each_possible_cpu(cpu)
++		set_cpu_present(cpu, true);
++
+ 	return 0;
+ }
+ core_initcall(initialize_cpu_present_map);
+ 
+ int __cpuexit __cpu_disable(void)
+ {
+-	cpumask_t map = cpu_online_map;
+ 	unsigned int cpu = smp_processor_id();
+ 
+ 	if (cpu == 0)
+@@ -375,9 +374,8 @@ int __cpuexit __cpu_disable(void)
+ 
+ 	remove_siblinginfo(cpu);
+ 
+-	cpu_clear(cpu, map);
+-	fixup_irqs(map);
+-	cpu_clear(cpu, cpu_online_map);
++	set_cpu_online(cpu, false);
++	fixup_irqs();
+ 
+ 	return 0;
+ }
+@@ -420,7 +418,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
+ 		return rc;
+ 	}
+ 
+-	cpu_set(cpu, cpu_online_map);
++	set_cpu_online(cpu, true);
+ 
+ 	rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
+ 	BUG_ON(rc);
+@@ -432,7 +430,7 @@ void __ref play_dead(void)
+ {
+ 	idle_task_exit();
+ 	local_irq_disable();
+-	cpu_clear(smp_processor_id(), cpu_initialized);
++	cpumask_clear_cpu(smp_processor_id(), cpu_initialized_mask);
+ 	preempt_enable_no_resched();
+ 	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+ #ifdef CONFIG_HOTPLUG_CPU
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/spinlock.c	2009-11-17 15:19:07.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/core/spinlock.c	2009-11-17 14:57:38.000000000 +0100
+@@ -99,7 +99,8 @@ int xen_spin_wait(raw_spinlock_t *lock, 
+ 
+ 	/* Leave the irq pending so that any interrupted blocker will
+ 	 * re-check. */
+-	kstat_this_cpu.irqs[irq] += !rc;
++	if (!rc)
++		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ 
+ 	/* announce we're done */
+ 	x86_write_percpu(spinning, spinning.prev);
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/interface.c	2010-01-04 12:26:37.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/interface.c	2010-01-04 12:40:36.000000000 +0100
+@@ -176,6 +176,14 @@ static struct ethtool_ops network_ethtoo
+ 	.get_strings = netbk_get_strings,
+ };
+ 
++static const struct net_device_ops netif_be_netdev_ops = {
++	.ndo_open               = net_open,
++	.ndo_stop               = net_close,
++	.ndo_start_xmit         = netif_be_start_xmit,
++	.ndo_change_mtu	        = netbk_change_mtu,
++	.ndo_get_stats          = netif_be_get_stats,
++};
++
+ netif_t *netif_alloc(struct device *parent, domid_t domid, unsigned int handle)
+ {
+ 	int err = 0;
+@@ -210,11 +218,7 @@ netif_t *netif_alloc(struct device *pare
+ 
+ 	init_timer(&netif->tx_queue_timeout);
+ 
+-	dev->hard_start_xmit = netif_be_start_xmit;
+-	dev->get_stats       = netif_be_get_stats;
+-	dev->open            = net_open;
+-	dev->stop            = net_close;
+-	dev->change_mtu	     = netbk_change_mtu;
++	dev->netdev_ops	     = &netif_be_netdev_ops;
+ 	dev->features        = NETIF_F_IP_CSUM;
+ 
+ 	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/loopback.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/loopback.c	2009-11-06 10:51:55.000000000 +0100
+@@ -201,19 +201,21 @@ static void loopback_set_multicast_list(
+ {
+ }
+ 
++static const struct net_device_ops loopback_netdev_ops = {
++	.ndo_open               = loopback_open,
++	.ndo_stop               = loopback_close,
++	.ndo_start_xmit         = loopback_start_xmit,
++	.ndo_set_multicast_list = loopback_set_multicast_list,
++	.ndo_change_mtu	        = NULL, /* allow arbitrary mtu */
++	.ndo_get_stats          = loopback_get_stats,
++};
++
+ static void loopback_construct(struct net_device *dev, struct net_device *lo)
+ {
+ 	struct net_private *np = netdev_priv(dev);
+ 
+ 	np->loopback_dev     = lo;
+-
+-	dev->open            = loopback_open;
+-	dev->stop            = loopback_close;
+-	dev->hard_start_xmit = loopback_start_xmit;
+-	dev->get_stats       = loopback_get_stats;
+-	dev->set_multicast_list = loopback_set_multicast_list;
+-	dev->change_mtu	     = NULL; /* allow arbitrary mtu */
+-
++	dev->netdev_ops      = &loopback_netdev_ops;
+ 	dev->tx_queue_len    = 0;
+ 
+ 	dev->features        = (NETIF_F_HIGHDMA |
+--- sle11sp1-2010-01-20.orig/drivers/xen/netback/netback.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netback/netback.c	2009-11-06 10:51:55.000000000 +0100
+@@ -354,7 +354,7 @@ static void xen_network_done_notify(void
+ 	static struct net_device *eth0_dev = NULL;
+ 	if (unlikely(eth0_dev == NULL))
+ 		eth0_dev = __dev_get_by_name(&init_net, "eth0");
+-	netif_rx_schedule(eth0_dev, ???);
++	netif_rx_schedule(???);
+ }
+ /* 
+  * Add following to poll() function in NAPI driver (Tigon3 is example):
+--- sle11sp1-2010-01-20.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/netfront/netfront.c	2009-11-06 10:51:55.000000000 +0100
+@@ -635,7 +635,7 @@ static int network_open(struct net_devic
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(dev, &np->napi);
++			netif_rx_schedule(&np->napi);
+ 		}
+ 	}
+ 	spin_unlock_bh(&np->rx_lock);
+@@ -707,7 +707,7 @@ static void rx_refill_timeout(unsigned l
+ 
+ 	netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-	netif_rx_schedule(dev, &np->napi);
++	netif_rx_schedule(&np->napi);
+ }
+ 
+ static void network_alloc_rx_buffers(struct net_device *dev)
+@@ -1064,8 +1064,7 @@ static irqreturn_t netif_int(int irq, vo
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(dev, &np->napi);
+-			dev->last_rx = jiffies;
++			netif_rx_schedule(&np->napi);
+ 		}
+ 	}
+ 
+@@ -1481,7 +1480,6 @@ err:	
+ 
+ 		/* Pass it up. */
+ 		netif_receive_skb(skb);
+-		dev->last_rx = jiffies;
+ 	}
+ 
+ 	/* If we get a callback with very few responses, reduce fill target. */
+@@ -1523,7 +1521,7 @@ err:	
+ 		}
+ 
+ 		if (!more_to_do && !accel_more_to_do)
+-			__netif_rx_complete(dev, napi);
++			__netif_rx_complete(napi);
+ 
+ 		local_irq_restore(flags);
+ 	}
+@@ -2024,6 +2022,18 @@ static void network_set_multicast_list(s
+ {
+ }
+ 
++static const struct net_device_ops xennet_netdev_ops = {
++	.ndo_uninit             = netif_uninit,
++	.ndo_open               = network_open,
++	.ndo_stop               = network_close,
++	.ndo_start_xmit         = network_start_xmit,
++	.ndo_set_multicast_list = network_set_multicast_list,
++	.ndo_set_mac_address    = xennet_set_mac_address,
++	.ndo_validate_addr      = eth_validate_addr,
++	.ndo_change_mtu	        = xennet_change_mtu,
++	.ndo_get_stats          = network_get_stats,
++};
++
+ static struct net_device * __devinit create_netdev(struct xenbus_device *dev)
+ {
+ 	int i, err = 0;
+@@ -2080,15 +2090,8 @@ static struct net_device * __devinit cre
+ 		goto exit_free_tx;
+ 	}
+ 
+-	netdev->open            = network_open;
+-	netdev->hard_start_xmit = network_start_xmit;
+-	netdev->stop            = network_close;
+-	netdev->get_stats       = network_get_stats;
++	netdev->netdev_ops	= &xennet_netdev_ops;
+ 	netif_napi_add(netdev, &np->napi, netif_poll, 64);
+-	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->features        = NETIF_F_IP_CSUM;
+ 
+ 	SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+@@ -2119,7 +2122,7 @@ inetdev_notify(struct notifier_block *th
+ 	struct net_device *dev = ifa->ifa_dev->dev;
+ 
+ 	/* UP event and is it one of our devices? */
+-	if (event == NETDEV_UP && dev->open == network_open)
++	if (event == NETDEV_UP && dev->netdev_ops->ndo_open == network_open)
+ 		send_fake_arp(dev);
+ 
+ 	return NOTIFY_DONE;
+--- sle11sp1-2010-01-20.orig/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:51:55.000000000 +0100
+@@ -47,7 +47,7 @@ static void vnic_start_interrupts(netfro
+ 		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, &np->napi);
++		netif_rx_schedule(&np->napi);
+ 	} else {
+ 		/*
+ 		 * Nothing yet, make sure we get interrupts through
+@@ -532,7 +532,7 @@ irqreturn_t netfront_accel_net_channel_i
+ 				vnic->stats.event_count_since_irq;
+ 		vnic->stats.event_count_since_irq = 0;
+ #endif
+-		netif_rx_schedule(net_dev, &np->napi);
++		netif_rx_schedule(&np->napi);
+ 	}
+ 	else {
+ 		spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:55.000000000 +0100
+@@ -170,7 +170,6 @@ EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
+ /**
+  * xenbus_switch_state
+  * @dev: xenbus device
+- * @xbt: transaction handle
+  * @state: new state
+  *
+  * Advertise in the store a change of the given driver to the given new_state.
+@@ -304,7 +303,7 @@ EXPORT_SYMBOL_GPL(xenbus_dev_error);
+  * @fmt: error message format
+  *
+  * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
+- * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
++ * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly
+  * closedown of this driver and its peer.
+  */
+ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:51:42.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:28:50.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include <linux/ctype.h>
+ #include <linux/fcntl.h>
+ #include <linux/mm.h>
++#include <linux/proc_fs.h>
+ #include <linux/notifier.h>
+ #include <linux/mutex.h>
+ #include <linux/io.h>
+@@ -73,6 +74,10 @@
+ #endif
+ 
+ int xen_store_evtchn;
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++EXPORT_SYMBOL(xen_store_evtchn);
++#endif
++
+ struct xenstore_domain_interface *xen_store_interface;
+ static unsigned long xen_store_mfn;
+ 
+@@ -197,6 +202,12 @@ static int xenbus_uevent_frontend(struct
+ }
+ #endif
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++static struct device_attribute xenbus_dev_attrs[] = {
++	__ATTR_NULL
++};
++#endif
++
+ /* Bus type for frontend drivers. */
+ static struct xen_bus_type xenbus_frontend = {
+ 	.root = "device",
+@@ -205,13 +216,16 @@ static struct xen_bus_type xenbus_fronte
+ 	.probe = xenbus_probe_frontend,
+ 	.error = -ENODEV,
+ 	.bus = {
+-		.name     = "xen",
+-		.match    = xenbus_match,
++		.name      = "xen",
++		.match     = xenbus_match,
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+-		.probe    = xenbus_dev_probe,
+-		.remove   = xenbus_dev_remove,
+-		.shutdown = xenbus_dev_shutdown,
+-		.uevent   = xenbus_uevent_frontend,
++		.probe     = xenbus_dev_probe,
++		.remove    = xenbus_dev_remove,
++		.shutdown  = xenbus_dev_shutdown,
++		.uevent    = xenbus_uevent_frontend,
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++		.dev_attrs = xenbus_dev_attrs,
+ #endif
+ 	},
+ #if defined(CONFIG_XEN) || defined(MODULE)
+@@ -584,7 +598,17 @@ int xenbus_probe_node(struct xen_bus_typ
+ 	xendev->dev.bus = &bus->bus;
+ 	xendev->dev.release = xenbus_dev_release;
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
++	{
++		char devname[XEN_BUS_ID_SIZE];
++
++		err = bus->get_bus_id(devname, xendev->nodename);
++		if (!err)
++			dev_set_name(&xendev->dev, devname);
++	}
++#else
+ 	err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
++#endif
+ 	if (err)
+ 		goto fail;
+ 
+@@ -770,7 +794,7 @@ static int suspend_dev(struct device *de
+ 		err = drv->suspend(xdev);
+ 	if (err)
+ 		printk(KERN_WARNING
+-		       "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
++		       "xenbus: suspend %s failed: %i\n", dev_name(dev), err);
+ 	return 0;
+ }
+ 
+@@ -791,7 +815,7 @@ static int suspend_cancel_dev(struct dev
+ 	if (err)
+ 		printk(KERN_WARNING
+ 		       "xenbus: suspend_cancel %s failed: %i\n",
+-		       dev->bus_id, err);
++		       dev_name(dev), err);
+ 	return 0;
+ }
+ 
+@@ -813,7 +837,7 @@ static int resume_dev(struct device *dev
+ 	if (err) {
+ 		printk(KERN_WARNING
+ 		       "xenbus: resume (talk_to_otherend) %s failed: %i\n",
+-		       dev->bus_id, err);
++		       dev_name(dev), err);
+ 		return err;
+ 	}
+ 
+@@ -824,7 +848,7 @@ static int resume_dev(struct device *dev
+ 		if (err) {
+ 			printk(KERN_WARNING
+ 			       "xenbus: resume %s failed: %i\n",
+-			       dev->bus_id, err);
++			       dev_name(dev), err);
+ 			return err;
+ 		}
+ 	}
+@@ -833,7 +857,7 @@ static int resume_dev(struct device *dev
+ 	if (err) {
+ 		printk(KERN_WARNING
+ 		       "xenbus_probe: resume (watch_otherend) %s failed: "
+-		       "%d.\n", dev->bus_id, err);
++		       "%d.\n", dev_name(dev), err);
+ 		return err;
+ 	}
+ 
+@@ -1145,6 +1169,14 @@ static int __devinit xenbus_probe_init(v
+ 	if (!is_initial_xendomain())
+ 		xenbus_probe(NULL);
+ 
++#if defined(CONFIG_XEN_COMPAT_XENFS) && !defined(MODULE)
++	/*
++	 * Create xenfs mountpoint in /proc for compatibility with
++	 * utilities that expect to find "xenbus" under "/proc/xen".
++	 */
++	proc_mkdir("xen", NULL);
++#endif
++
+ 	return 0;
+ 
+  err:
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:51:55.000000000 +0100
+@@ -45,6 +45,10 @@
+ #define is_initial_xendomain() xen_initial_domain()
+ #endif
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
++#define dev_name(dev) ((dev)->bus_id)
++#endif
++
+ #if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
+ extern void xenbus_backend_suspend(int (*fn)(struct device *, void *));
+ extern void xenbus_backend_resume(int (*fn)(struct device *, void *));
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:55.000000000 +0100
+@@ -36,6 +36,7 @@
+ 		 __FUNCTION__, __LINE__, ##args)
+ 
+ #include <linux/kernel.h>
++#include <linux/version.h>
+ #include <linux/err.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+@@ -108,6 +109,10 @@ static int backend_bus_id(char bus_id[BU
+ 	return 0;
+ }
+ 
++static struct device_attribute xenbus_backend_attrs[] = {
++	__ATTR_NULL
++};
++
+ static struct xen_bus_type xenbus_backend = {
+ 	.root = "backend",
+ 	.levels = 3, 		/* backend/type/<frontend>/<id> */
+@@ -115,12 +120,13 @@ static struct xen_bus_type xenbus_backen
+ 	.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,
++		.name      = "xen-backend",
++		.match     = xenbus_match,
++		.probe     = xenbus_dev_probe,
++		.remove    = xenbus_dev_remove,
++//		.shutdown  = xenbus_dev_shutdown,
++		.uevent    = xenbus_uevent_backend,
++		.dev_attrs = xenbus_backend_attrs,
+ 	},
+ 	.dev = {
+ 		.bus_id = "xen-backend",
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenbus/xenbus_xs.c	2009-11-06 10:51:07.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenbus/xenbus_xs.c	2009-11-06 10:51:55.000000000 +0100
+@@ -227,6 +227,9 @@ void *xenbus_dev_request_and_reply(struc
+ 
+ 	return ret;
+ }
++#if !defined(CONFIG_XEN) && !defined(MODULE)
++EXPORT_SYMBOL(xenbus_dev_request_and_reply);
++#endif
+ 
+ /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
+ static void *xs_talkv(struct xenbus_transaction t,
+--- sle11sp1-2010-01-20.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:35.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:59:32.000000000 +0100
+@@ -50,7 +50,7 @@ static int xenoprof_enabled = 0;
+ static int xenoprof_is_primary = 0;
+ static int active_defined;
+ 
+-extern unsigned long backtrace_depth;
++extern unsigned long oprofile_backtrace_depth;
+ 
+ /* Number of buffers in shared area (one per VCPU) */
+ static int nbuf;
+@@ -339,11 +339,11 @@ static int xenoprof_setup(void)
+ 			active_defined = 1;
+ 		}
+ 
+-		if (backtrace_depth > 0) {
++		if (oprofile_backtrace_depth > 0) {
+ 			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_backtrace, 
+-						     &backtrace_depth);
++						     &oprofile_backtrace_depth);
+ 			if (ret)
+-				backtrace_depth = 0;
++				oprofile_backtrace_depth = 0;
+ 		}
+ 
+ 		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
+--- sle11sp1-2010-01-20.orig/fs/xfs/linux-2.6/xfs_buf.c	2010-01-20 10:20:50.000000000 +0100
++++ sle11sp1-2010-01-20/fs/xfs/linux-2.6/xfs_buf.c	2009-11-06 10:51:55.000000000 +0100
+@@ -194,7 +194,7 @@ free_address(
+ {
+ 	a_list_t	*aentry;
+ 
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ 	/*
+ 	 * Xen needs to be able to make sure it can get an exclusive
+ 	 * RO mapping of pages it wants to turn into a pagetable.  If
+--- sle11sp1-2010-01-20.orig/include/acpi/processor.h	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/include/acpi/processor.h	2009-11-06 10:51:55.000000000 +0100
+@@ -438,6 +438,13 @@ extern int processor_extcntl_prepare(str
+ 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 **);
++
++/*
++ * Declarations for objects and functions removed in native 2.6.29, and
++ * thus moved to drivers/acpi/processor_extcntl.c.
++ */
++extern struct notifier_block acpi_processor_latency_notifier;
++int acpi_processor_set_power_policy(struct acpi_processor *);
+ #else
+ static inline int processor_cntl_external(void) {return 0;}
+ static inline int processor_pm_external(void) {return 0;}
+--- sle11sp1-2010-01-20.orig/include/xen/cpu_hotplug.h	2009-11-06 10:51:47.000000000 +0100
++++ sle11sp1-2010-01-20/include/xen/cpu_hotplug.h	2009-11-06 10:51:55.000000000 +0100
+@@ -5,7 +5,7 @@
+ #include <linux/cpumask.h>
+ 
+ #if defined(CONFIG_X86) && defined(CONFIG_SMP)
+-extern cpumask_t cpu_initialized_map;
++extern cpumask_var_t vcpu_initialized_mask;
+ #endif
+ 
+ #if defined(CONFIG_HOTPLUG_CPU)
+--- sle11sp1-2010-01-20.orig/include/xen/evtchn.h	2009-12-18 10:09:52.000000000 +0100
++++ sle11sp1-2010-01-20/include/xen/evtchn.h	2009-12-18 10:10:04.000000000 +0100
+@@ -47,6 +47,17 @@
+ /*
+  * LOW-LEVEL DEFINITIONS
+  */
++struct irq_cfg {
++	u32 info;
++	union {
++		int bindcount; /* for dynamic IRQs */
++#ifdef CONFIG_X86_IO_APIC
++		u8 vector; /* for physical IRQs */
++#endif
++	};
++};
++
++int assign_irq_vector(int irq, struct irq_cfg *, const struct cpumask *);
+ 
+ /*
+  * Dynamically bind an event source to an IRQ-like callback handler.
+--- sle11sp1-2010-01-20.orig/include/xen/xenbus.h	2009-11-06 10:51:17.000000000 +0100
++++ sle11sp1-2010-01-20/include/xen/xenbus.h	2009-11-06 10:51:55.000000000 +0100
+@@ -322,7 +322,9 @@ void xenbus_dev_error(struct xenbus_devi
+ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+ 		      ...);
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ int xenbus_dev_init(void);
++#endif
+ 
+ const char *xenbus_strstate(enum xenbus_state state);
+ int xenbus_dev_is_online(struct xenbus_device *dev);
+--- sle11sp1-2010-01-20.orig/lib/swiotlb-xen.c	2009-12-14 17:24:14.000000000 +0100
++++ sle11sp1-2010-01-20/lib/swiotlb-xen.c	2009-12-14 17:27:59.000000000 +0100
+@@ -8,6 +8,7 @@
+  * Copyright (C) 2000, 2003 Hewlett-Packard Co
+  *	David Mosberger-Tang <davidm@hpl.hp.com>
+  * Copyright (C) 2005 Keir Fraser <keir@xensource.com>
++ * 08/12/11 beckyb	Add highmem support
+  */
+ 
+ #include <linux/cache.h>
+@@ -16,6 +17,8 @@
+ #include <linux/pci.h>
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
++#include <linux/swiotlb.h>
++#include <linux/pfn.h>
+ #include <linux/types.h>
+ #include <linux/ctype.h>
+ #include <linux/init.h>
+@@ -30,27 +33,11 @@
+ #include <xen/interface/memory.h>
+ #include <asm/gnttab_dma.h>
+ 
+-int swiotlb;
+-
+ #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
+ 
+-/*
+- * Maximum allowable number of contiguous slabs to map,
+- * must be a power of 2.  What is the appropriate value ?
+- * The complexity of {map,unmap}_single is linearly dependent on this value.
+- */
+-#define IO_TLB_SEGSIZE	128
+-
+-/*
+- * log of the size of each IO TLB slab.  The number of slabs is command line
+- * controllable.
+- */
+-#define IO_TLB_SHIFT 11
+-
++int swiotlb;
+ int swiotlb_force;
+ 
+-static unsigned long iotlb_nslabs;
+-
+ /*
+  * Used to do a quick range check in swiotlb_unmap_single and
+  * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
+@@ -59,6 +46,12 @@ static unsigned long iotlb_nslabs;
+ static char *io_tlb_start, *io_tlb_end;
+ 
+ /*
++ * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and
++ * io_tlb_end.  This is command line adjustable via setup_io_tlb_npages.
++ */
++static unsigned long io_tlb_nslabs;
++
++/*
+  * When the IOMMU overflows we return a fallback buffer. This sets the size.
+  */
+ static unsigned long io_tlb_overflow = 32*1024;
+@@ -76,10 +69,7 @@ static unsigned int io_tlb_index;
+  * We need to save away the original address corresponding to a mapped entry
+  * for the sync operations.
+  */
+-static struct phys_addr {
+-	struct page *page;
+-	unsigned int offset;
+-} *io_tlb_orig_addr;
++static phys_addr_t *io_tlb_orig_addr;
+ 
+ /*
+  * Protect the above data structures in the map and unmap calls
+@@ -101,9 +91,9 @@ setup_io_tlb_npages(char *str)
+ {
+ 	/* Unlike ia64, the size is aperture in megabytes, not 'slabs'! */
+ 	if (isdigit(*str)) {
+-		iotlb_nslabs = simple_strtoul(str, &str, 0) <<
++		io_tlb_nslabs = simple_strtoul(str, &str, 0) <<
+ 			(20 - IO_TLB_SHIFT);
+-		iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE);
++		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+ 	}
+ 	if (*str == ',')
+ 		++str;
+@@ -121,35 +111,17 @@ setup_io_tlb_npages(char *str)
+ __setup("swiotlb=", setup_io_tlb_npages);
+ /* make io_tlb_overflow tunable too? */
+ 
+-/*
+- * Statically reserve bounce buffer space and initialize bounce buffer data
+- * structures for the software IO TLB used to implement the PCI DMA API.
+- */
+-void __init
+-swiotlb_init_with_default_size(size_t default_size)
++void *__init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+ {
+-	unsigned long i, bytes;
++	void *start = alloc_bootmem_pages(size);
++	unsigned int i;
+ 	int rc;
+ 
+-	if (!iotlb_nslabs) {
+-		iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
+-		iotlb_nslabs = ALIGN(iotlb_nslabs, IO_TLB_SEGSIZE);
+-	}
+-
+-	bytes = iotlb_nslabs * (1UL << IO_TLB_SHIFT);
+-
+-	/*
+-	 * Get IO TLB memory from the low pages
+-	 */
+-	io_tlb_start = alloc_bootmem_pages(bytes);
+-	if (!io_tlb_start)
+-		panic("Cannot allocate SWIOTLB buffer!\n");
+-
+ 	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
+-	for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
++	for (i = 0; i < nslabs; i += IO_TLB_SEGSIZE) {
+ 		do {
+ 			rc = xen_create_contiguous_region(
+-				(unsigned long)io_tlb_start + (i << IO_TLB_SHIFT),
++				(unsigned long)start + (i << IO_TLB_SHIFT),
+ 				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+ 				dma_bits);
+ 		} while (rc && dma_bits++ < max_dma_bits);
+@@ -158,12 +130,12 @@ swiotlb_init_with_default_size(size_t de
+ 				panic("No suitable physical memory available for SWIOTLB buffer!\n"
+ 				      "Use dom0_mem Xen boot parameter to reserve\n"
+ 				      "some DMA memory (e.g., dom0_mem=-128M).\n");
+-			iotlb_nslabs = i;
++			io_tlb_nslabs = i;
+ 			i <<= IO_TLB_SHIFT;
+-			free_bootmem(__pa(io_tlb_start + i), bytes - i);
+-			bytes = i;
++			free_bootmem(__pa(start + i), size - i);
++			size = i;
+ 			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
+-				unsigned int bits = fls64(virt_to_bus(io_tlb_start + i - 1));
++				unsigned int bits = fls64(virt_to_bus(start + i - 1));
+ 
+ 				if (bits > dma_bits)
+ 					dma_bits = bits;
+@@ -171,18 +143,88 @@ swiotlb_init_with_default_size(size_t de
+ 			break;
+ 		}
+ 	}
++
++	return start;
++}
++
++#ifndef CONFIG_XEN
++void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs)
++{
++	return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
++}
++#endif
++
++dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
++{
++	return phys_to_machine(paddr);
++}
++
++phys_addr_t swiotlb_bus_to_phys(dma_addr_t baddr)
++{
++	return machine_to_phys(baddr);
++}
++
++static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
++				      volatile void *address)
++{
++	return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
++}
++
++static void *swiotlb_bus_to_virt(dma_addr_t address)
++{
++	return phys_to_virt(swiotlb_bus_to_phys(address));
++}
++
++int __weak swiotlb_arch_range_needs_mapping(void *ptr, size_t size)
++{
++	return 0;
++}
++
++static void swiotlb_print_info(unsigned long bytes)
++{
++	printk(KERN_INFO "Software IO TLB enabled: \n"
++	       " Aperture:     %lu megabytes\n"
++	       " Address size: %u bits\n"
++	       " Kernel range: %p - %p\n",
++	       bytes >> 20, dma_bits,
++	       io_tlb_start, io_tlb_end);
++}
++
++/*
++ * Statically reserve bounce buffer space and initialize bounce buffer data
++ * structures for the software IO TLB used to implement the PCI DMA API.
++ */
++void __init
++swiotlb_init_with_default_size(size_t default_size)
++{
++	unsigned long i, bytes;
++	int rc;
++
++	if (!io_tlb_nslabs) {
++		io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
++		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
++	}
++
++	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
++
++	/*
++	 * Get IO TLB memory from the low pages
++	 */
++	io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
++	if (!io_tlb_start)
++		panic("Cannot allocate SWIOTLB buffer!\n");
++	bytes = io_tlb_nslabs << IO_TLB_SHIFT;
+ 	io_tlb_end = io_tlb_start + bytes;
+ 
+ 	/*
+ 	 * Allocate and initialize the free list array.  This array is used
+ 	 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE.
+ 	 */
+-	io_tlb_list = alloc_bootmem(iotlb_nslabs * sizeof(int));
+-	for (i = 0; i < iotlb_nslabs; i++)
++	io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
++	for (i = 0; i < io_tlb_nslabs; i++)
+  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+ 	io_tlb_index = 0;
+-	io_tlb_orig_addr = alloc_bootmem(
+-		iotlb_nslabs * sizeof(*io_tlb_orig_addr));
++	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t));
+ 
+ 	/*
+ 	 * Get the overflow emergency buffer
+@@ -200,13 +242,7 @@ swiotlb_init_with_default_size(size_t de
+ 	if (rc)
+ 		panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
+ 
+-	printk(KERN_INFO "Software IO TLB enabled: \n"
+-	       " Aperture:     %lu megabytes\n"
+-	       " Kernel range: %p - %p\n"
+-	       " Address size: %u bits\n",
+-	       bytes >> 20,
+-	       io_tlb_start, io_tlb_end,
+-	       dma_bits);
++	swiotlb_print_info(bytes);
+ }
+ 
+ void __init
+@@ -233,6 +269,11 @@ swiotlb_init(void)
+ 		printk(KERN_INFO "Software IO TLB disabled\n");
+ }
+ 
++static inline int range_needs_mapping(phys_addr_t pa, size_t size)
++{
++	return range_straddles_page_boundary(pa, size);
++}
++
+ static int is_swiotlb_buffer(dma_addr_t addr)
+ {
+ 	unsigned long pfn = mfn_to_local_pfn(PFN_DOWN(addr));
+@@ -246,46 +287,50 @@ static int is_swiotlb_buffer(dma_addr_t 
+ }
+ 
+ /*
++ * Bounce: copy the swiotlb buffer back to the original dma location
++ *
+  * We use __copy_to_user_inatomic to transfer to the host buffer because the
+  * buffer may be mapped read-only (e.g, in blkback driver) but lower-level
+  * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
+  * unnecessary copy from the aperture to the host buffer, and a page fault.
+  */
+-static void
+-__sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
++static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
++			   enum dma_data_direction dir)
+ {
+-	if (PageHighMem(buffer.page)) {
+-		size_t len, bytes;
+-		char *dev, *host, *kmp;
+-		len = size;
+-		while (len != 0) {
+-			unsigned long flags;
+-
+-			if (((bytes = len) + buffer.offset) > PAGE_SIZE)
+-				bytes = PAGE_SIZE - buffer.offset;
+-			local_irq_save(flags); /* protects KM_BOUNCE_READ */
+-			kmp  = kmap_atomic(buffer.page, KM_BOUNCE_READ);
+-			dev  = dma_addr + size - len;
+-			host = kmp + buffer.offset;
+-			if (dir == DMA_FROM_DEVICE) {
+-				if (__copy_to_user_inatomic(host, dev, bytes))
+-					/* inaccessible */;
+-			} else
+-				memcpy(dev, host, bytes);
+-			kunmap_atomic(kmp, KM_BOUNCE_READ);
++	unsigned long pfn = PFN_DOWN(phys);
++
++	if (PageHighMem(pfn_to_page(pfn))) {
++		/* The buffer does not have a mapping.  Map it in and copy */
++		unsigned int offset = phys & ~PAGE_MASK;
++		char *buffer;
++		unsigned int sz = 0;
++		unsigned long flags;
++
++		while (size) {
++			sz = min((size_t)(PAGE_SIZE - offset), size);
++
++			local_irq_save(flags);
++			buffer = kmap_atomic(pfn_to_page(pfn),
++					     KM_BOUNCE_READ);
++			if (dir == DMA_TO_DEVICE)
++				memcpy(dma_addr, buffer + offset, sz);
++			else if (__copy_to_user_inatomic(buffer + offset,
++							 dma_addr, sz))
++				/* inaccessible */;
++			kunmap_atomic(buffer, KM_BOUNCE_READ);
+ 			local_irq_restore(flags);
+-			len -= bytes;
+-			buffer.page++;
+-			buffer.offset = 0;
++
++			size -= sz;
++			pfn++;
++			dma_addr += sz;
++			offset = 0;
+ 		}
+ 	} else {
+-		char *host = (char *)phys_to_virt(
+-			page_to_pseudophys(buffer.page)) + buffer.offset;
+-		if (dir == DMA_FROM_DEVICE) {
+-			if (__copy_to_user_inatomic(host, dma_addr, size))
+-				/* inaccessible */;
+-		} else if (dir == DMA_TO_DEVICE)
+-			memcpy(dma_addr, host, size);
++		if (dir == DMA_TO_DEVICE)
++			memcpy(dma_addr, phys_to_virt(phys), size);
++		else if (__copy_to_user_inatomic(phys_to_virt(phys),
++						 dma_addr, size))
++			/* inaccessible */;
+ 	}
+ }
+ 
+@@ -293,12 +338,11 @@ __sync_single(struct phys_addr buffer, c
+  * Allocates bounce buffer and returns its kernel virtual address.
+  */
+ static void *
+-map_single(struct device *hwdev, struct phys_addr buffer, size_t size, int dir)
++map_single(struct device *hwdev, phys_addr_t phys, size_t size, int dir)
+ {
+ 	unsigned long flags;
+ 	char *dma_addr;
+ 	unsigned int nslots, stride, index, wrap;
+-	struct phys_addr slot_buf;
+ 	int i;
+ 	unsigned long mask;
+ 	unsigned long offset_slots;
+@@ -306,6 +350,10 @@ map_single(struct device *hwdev, struct 
+ 
+ 	mask = dma_get_seg_boundary(hwdev);
+ 	offset_slots = -IO_TLB_SEGSIZE;
++
++	/*
++ 	 * Carefully handle integer overflow which can occur when mask == ~0UL.
++ 	 */
+ 	max_slots = mask + 1
+ 		    ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
+ 		    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+@@ -328,7 +376,7 @@ map_single(struct device *hwdev, struct 
+ 	 */
+ 	spin_lock_irqsave(&io_tlb_lock, flags);
+ 	index = ALIGN(io_tlb_index, stride);
+-	if (index >= iotlb_nslabs)
++	if (index >= io_tlb_nslabs)
+ 		index = 0;
+ 	wrap = index;
+ 
+@@ -336,7 +384,7 @@ map_single(struct device *hwdev, struct 
+ 		while (iommu_is_span_boundary(index, nslots, offset_slots,
+ 					      max_slots)) {
+ 			index += stride;
+-			if (index >= iotlb_nslabs)
++			if (index >= io_tlb_nslabs)
+ 				index = 0;
+ 			if (index == wrap)
+ 				goto not_found;
+@@ -360,13 +408,13 @@ map_single(struct device *hwdev, struct 
+ 			 * Update the indices to avoid searching in the next
+ 			 * round.
+ 			 */
+-			io_tlb_index = ((index + nslots) < iotlb_nslabs
++			io_tlb_index = ((index + nslots) < io_tlb_nslabs
+ 					? (index + nslots) : 0);
+ 
+ 			goto found;
+ 		}
+ 		index += stride;
+-		if (index >= iotlb_nslabs)
++		if (index >= io_tlb_nslabs)
+ 			index = 0;
+ 	} while (index != wrap);
+ 
+@@ -381,29 +429,14 @@ found:
+ 	 * This is needed when we sync the memory.  Then we sync the buffer if
+ 	 * needed.
+ 	 */
+-	slot_buf = buffer;
+-	for (i = 0; i < nslots; i++) {
+-		slot_buf.page += slot_buf.offset >> PAGE_SHIFT;
+-		slot_buf.offset &= PAGE_SIZE - 1;
+-		io_tlb_orig_addr[index+i] = slot_buf;
+-		slot_buf.offset += 1 << IO_TLB_SHIFT;
+-	}
+-	if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+-		__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
++	for (i = 0; i < nslots; i++)
++		io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
++	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
++		swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
+ 
+ 	return dma_addr;
+ }
+ 
+-static struct phys_addr dma_addr_to_phys_addr(char *dma_addr)
+-{
+-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+-	struct phys_addr buffer = io_tlb_orig_addr[index];
+-	buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1);
+-	buffer.page += buffer.offset >> PAGE_SHIFT;
+-	buffer.offset &= PAGE_SIZE - 1;
+-	return buffer;
+-}
+-
+ /*
+  * dma_addr is the kernel virtual address of the bounce buffer to unmap.
+  */
+@@ -413,13 +446,13 @@ unmap_single(struct device *hwdev, char 
+ 	unsigned long flags;
+ 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+ 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+-	struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
++	phys_addr_t phys = io_tlb_orig_addr[index];
+ 
+ 	/*
+ 	 * First, sync the memory before unmapping the entry
+ 	 */
+-	if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+-		__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
++	if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
++		swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
+ 
+ 	/*
+ 	 * Return the buffer to the free list by setting the corresponding
+@@ -453,9 +486,13 @@ unmap_single(struct device *hwdev, char 
+ static void
+ sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+ {
+-	struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
++	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
++	phys_addr_t phys = io_tlb_orig_addr[index];
++
++	phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
++
+ 	BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
+-	__sync_single(buffer, dma_addr, size, dir);
++	swiotlb_bounce(phys, dma_addr, size, dir);
+ }
+ 
+ static void
+@@ -469,7 +506,7 @@ swiotlb_full(struct device *dev, size_t 
+ 	 * the damage, or panic when the transfer is too big.
+ 	 */
+ 	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %zu bytes at "
+-	       "device %s\n", size, dev ? dev->bus_id : "?");
++	       "device %s\n", size, dev ? dev_name(dev) : "?");
+ 
+ 	if (size > io_tlb_overflow && do_panic) {
+ 		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+@@ -494,7 +531,6 @@ _swiotlb_map_single(struct device *hwdev
+ 	dma_addr_t dev_addr = gnttab_dma_map_page(page) +
+ 			      offset_in_page(paddr);
+ 	void *map;
+-	struct phys_addr buffer;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+@@ -503,23 +539,21 @@ _swiotlb_map_single(struct device *hwdev
+ 	 * we can safely return the device addr and not worry about bounce
+ 	 * buffering it.
+ 	 */
+-	if (!range_straddles_page_boundary(paddr, size) &&
+-	    !address_needs_mapping(hwdev, dev_addr, size))
++	if (!address_needs_mapping(hwdev, dev_addr, size) &&
++	    !range_needs_mapping(paddr, size))
+ 		return dev_addr;
+ 
+ 	/*
+ 	 * Oh well, have to allocate and map a bounce buffer.
+ 	 */
+ 	gnttab_dma_unmap_page(dev_addr);
+-	buffer.page   = page;
+-	buffer.offset = offset_in_page(paddr);
+-	map = map_single(hwdev, buffer, size, dir);
++	map = map_single(hwdev, paddr, size, dir);
+ 	if (!map) {
+ 		swiotlb_full(hwdev, size, dir, 1);
+ 		map = io_tlb_overflow_buffer;
+ 	}
+ 
+-	dev_addr = virt_to_bus(map);
++	dev_addr = swiotlb_virt_to_bus(hwdev, map);
+ 	return dev_addr;
+ }
+ 
+@@ -536,6 +570,7 @@ swiotlb_map_single(struct device *hwdev,
+ {
+ 	return _swiotlb_map_single(hwdev, virt_to_phys(ptr), size, dir, NULL);
+ }
++EXPORT_SYMBOL(swiotlb_map_single);
+ 
+ dma_addr_t
+ swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size, int dir)
+@@ -555,7 +590,7 @@ void
+ swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
+ 			   size_t size, int dir, struct dma_attrs *attrs)
+ {
+- 	char *dma_addr = bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (is_swiotlb_buffer(dev_addr))
+@@ -571,6 +606,8 @@ swiotlb_unmap_single(struct device *hwde
+ {
+ 	return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
+ }
++EXPORT_SYMBOL(swiotlb_unmap_single);
++
+ /*
+  * Make physical memory consistent for a single streaming mode DMA translation
+  * after a transfer.
+@@ -585,48 +622,50 @@ void
+ swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 			    size_t size, int dir)
+ {
+- 	char *dma_addr = bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr, size, dir);
+ }
++EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
+ 
+ void
+ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 			       size_t size, int dir)
+ {
+- 	char *dma_addr = bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr, size, dir);
+ }
++EXPORT_SYMBOL(swiotlb_sync_single_for_device);
+ 
+ void
+ swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 				  unsigned long offset, size_t size, int dir)
+ {
+- 	char *dma_addr = bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr + offset, size, dir);
+ }
++EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_cpu);
+ 
+ void
+ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 				     unsigned long offset, size_t size, int dir)
+ {
+- 	char *dma_addr = bus_to_virt(dev_addr);
++	char *dma_addr = swiotlb_bus_to_virt(dev_addr);
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 	if (is_swiotlb_buffer(dev_addr))
+ 		sync_single(hwdev, dma_addr + offset, size, dir);
+ }
++EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
+ 
+-void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
+-			    struct dma_attrs *);
+ /*
+  * Map a set of buffers described by scatterlist in streaming mode for DMA.
+  * This is the scatter-gather version of the above swiotlb_map_single
+@@ -648,23 +687,23 @@ swiotlb_map_sg_attrs(struct device *hwde
+ 		     int dir, struct dma_attrs *attrs)
+ {
+ 	struct scatterlist *sg;
+-	struct phys_addr buffer;
+-	dma_addr_t dev_addr;
+-	char *map;
+ 	int i;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+-		dev_addr = gnttab_dma_map_page(sg_page(sg)) + sg->offset;
++		dma_addr_t dev_addr = gnttab_dma_map_page(sg_page(sg))
++				      + sg->offset;
++		phys_addr_t paddr = page_to_pseudophys(sg_page(sg))
++				   + sg->offset;
+ 
+-		if (range_straddles_page_boundary(page_to_pseudophys(sg_page(sg))
+-						  + sg->offset, sg->length)
++		if (range_needs_mapping(paddr, sg->length)
+ 		    || address_needs_mapping(hwdev, dev_addr, sg->length)) {
++			void *map;
++
+ 			gnttab_dma_unmap_page(dev_addr);
+-			buffer.page   = sg_page(sg);
+-			buffer.offset = sg->offset;
+-			map = map_single(hwdev, buffer, sg->length, dir);
++			map = map_single(hwdev, paddr,
++					 sg->length, dir);
+ 			if (!map) {
+ 				/* Don't panic here, we expect map_sg users
+ 				   to do proper error handling. */
+@@ -674,7 +713,7 @@ swiotlb_map_sg_attrs(struct device *hwde
+ 				sgl[0].dma_length = 0;
+ 				return 0;
+ 			}
+-			sg->dma_address = virt_to_bus(map);
++			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
+ 		} else
+ 			sg->dma_address = dev_addr;
+ 		sg->dma_length = sg->length;
+@@ -689,6 +728,7 @@ swiotlb_map_sg(struct device *hwdev, str
+ {
+ 	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+ }
++EXPORT_SYMBOL(swiotlb_map_sg);
+ 
+ /*
+  * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
+@@ -705,7 +745,7 @@ swiotlb_unmap_sg_attrs(struct device *hw
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+ 		if (sg->dma_address != sg_phys(sg))
+-			unmap_single(hwdev, bus_to_virt(sg->dma_address),
++			unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+ 				     sg->dma_length, dir);
+ 		else
+ 			gnttab_dma_unmap_page(sg->dma_address);
+@@ -719,6 +759,7 @@ swiotlb_unmap_sg(struct device *hwdev, s
+ {
+ 	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+ }
++EXPORT_SYMBOL(swiotlb_unmap_sg);
+ 
+ /*
+  * Make physical memory consistent for a set of streaming mode DMA translations
+@@ -738,10 +779,11 @@ swiotlb_sync_sg_for_cpu(struct device *h
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+ 		if (sg->dma_address != sg_phys(sg))
+-			sync_single(hwdev, bus_to_virt(sg->dma_address),
++			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ 	}
+ }
++EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
+ 
+ void
+ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sgl,
+@@ -754,16 +796,18 @@ swiotlb_sync_sg_for_device(struct device
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+ 		if (sg->dma_address != sg_phys(sg))
+-			sync_single(hwdev, bus_to_virt(sg->dma_address),
++			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ 	}
+ }
++EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
+ 
+ int
+ swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
+ {
+-	return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
++	return (dma_addr == swiotlb_virt_to_bus(hwdev, io_tlb_overflow_buffer));
+ }
++EXPORT_SYMBOL(swiotlb_dma_mapping_error);
+ 
+ /*
+  * Return whether the given PCI device DMA address mask can be supported
+@@ -776,14 +820,4 @@ swiotlb_dma_supported (struct device *hw
+ {
+ 	return (mask >= ((1UL << dma_bits) - 1));
+ }
+-
+-EXPORT_SYMBOL(swiotlb_map_single);
+-EXPORT_SYMBOL(swiotlb_unmap_single);
+-EXPORT_SYMBOL(swiotlb_map_sg);
+-EXPORT_SYMBOL(swiotlb_unmap_sg);
+-EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
+-EXPORT_SYMBOL(swiotlb_sync_single_for_device);
+-EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
+-EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
+-EXPORT_SYMBOL(swiotlb_dma_mapping_error);
+ EXPORT_SYMBOL(swiotlb_dma_supported);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-blkback-bimodal-suse
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-blkback-bimodal-suse
@@ -0,0 +1,43 @@
+Subject: backward compatibility
+From: Gerd Hoffmann <kraxel@suse.de>
+Patch-mainline: obsolete
+
+---
+ linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c |    6 ++++++
+ linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  |    6 ++++++
+ 2 files changed, 12 insertions(+)
+
+Index: head-2008-09-15/drivers/xen/blkback/xenbus.c
+===================================================================
+--- head-2008-09-15.orig/drivers/xen/blkback/xenbus.c	2008-09-15 14:32:56.000000000 +0200
++++ head-2008-09-15/drivers/xen/blkback/xenbus.c	2008-09-15 15:10:36.000000000 +0200
+@@ -496,6 +496,12 @@ static int connect_ring(struct backend_i
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */
++	else if (0 == strcmp(protocol, "1"))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
++	else if (0 == strcmp(protocol, "2"))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++#endif
+ 	else {
+ 		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+ 		return -1;
+Index: head-2008-09-15/drivers/xen/blktap/xenbus.c
+===================================================================
+--- head-2008-09-15.orig/drivers/xen/blktap/xenbus.c	2008-09-15 14:32:56.000000000 +0200
++++ head-2008-09-15/drivers/xen/blktap/xenbus.c	2008-09-15 15:10:36.000000000 +0200
+@@ -434,6 +434,12 @@ static int connect_ring(struct backend_i
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
+ 	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
+ 		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */
++	else if (0 == strcmp(protocol, "1"))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
++	else if (0 == strcmp(protocol, "2"))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++#endif
+ 	else {
+ 		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
+ 		return -1;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-panic-no-reboot
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-panic-no-reboot
@@ -0,0 +1,32 @@
+From: jbeulich@novell.com
+Subject: Don't automatically reboot Dom0 on panic (match native)
+Patch-mainline: obsolete
+
+$subject says it all.
+
+--- head-2010-01-04.orig/arch/x86/kernel/setup-xen.c	2010-01-04 12:50:03.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/setup-xen.c	2010-01-04 13:32:45.000000000 +0100
+@@ -773,15 +773,17 @@ void __init setup_arch(char **cmdline_p)
+ 	unsigned long p2m_pages;
+ 	struct physdev_set_iopl set_iopl;
+ 
++	if (!is_initial_xendomain()) {
+ #ifdef CONFIG_X86_32
+-	/* Force a quick death if the kernel panics (not domain 0). */
+-	extern int panic_timeout;
+-	if (!panic_timeout && !is_initial_xendomain())
+-		panic_timeout = 1;
++		/* Force a quick death if the kernel panics (not domain 0). */
++		extern int panic_timeout;
++		if (!panic_timeout)
++			panic_timeout = 1;
+ #endif
+ 
+-	/* Register a call for panic conditions. */
+-	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++		/* Register a call for panic conditions. */
++		atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
++	}
+ #endif /* CONFIG_XEN */
+ 
+ #ifdef CONFIG_X86_32
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-netback-notify-multi
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-netback-notify-multi
@@ -0,0 +1,85 @@
+From: jbeulich@novell.com
+Subject: netback: use multicall for send multiple notifications
+Patch-mainline: obsolete
+
+This also does a small fairness improvement since now notifications
+get sent in the order requests came in rather than in the inverse one.
+
+--- head-2010-01-04.orig/drivers/xen/core/evtchn.c	2009-11-06 11:10:22.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/evtchn.c	2009-11-06 11:10:30.000000000 +0100
+@@ -1329,6 +1329,21 @@ void notify_remote_via_irq(int irq)
+ }
+ EXPORT_SYMBOL_GPL(notify_remote_via_irq);
+ 
++int multi_notify_remote_via_irq(multicall_entry_t *mcl, int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	BUG_ON(type_from_irq(irq) == IRQT_VIRQ);
++	BUG_IF_IPI(irq);
++
++	if (!VALID_EVTCHN(evtchn))
++		return -EINVAL;
++
++	multi_notify_remote_via_evtchn(mcl, evtchn);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(multi_notify_remote_via_irq);
++
+ int irq_to_evtchn_port(int irq)
+ {
+ 	BUG_IF_VIRQ_PER_CPU(irq);
+--- head-2010-01-04.orig/drivers/xen/netback/netback.c	2010-01-04 13:31:44.000000000 +0100
++++ head-2010-01-04/drivers/xen/netback/netback.c	2010-01-04 13:31:57.000000000 +0100
+@@ -778,10 +778,20 @@ static void net_rx_action(unsigned long 
+ 		npo.meta_cons += nr_frags + 1;
+ 	}
+ 
+-	while (notify_nr != 0) {
+-		irq = notify_list[--notify_nr];
++	if (notify_nr == 1) {
++		irq = *notify_list;
+ 		__clear_bit(irq, rx_notify);
+ 		notify_remote_via_irq(irq + DYNIRQ_BASE);
++	} else {
++		for (count = ret = 0; ret < notify_nr; ++ret) {
++			irq = notify_list[ret];
++			__clear_bit(irq, rx_notify);
++			if (!multi_notify_remote_via_irq(rx_mcl + count,
++							 irq + DYNIRQ_BASE))
++				++count;
++		}
++		if (HYPERVISOR_multicall(rx_mcl, count))
++			BUG();
+ 	}
+ 
+ 	/* More work to do? */
+--- head-2010-01-04.orig/include/xen/evtchn.h	2009-12-18 10:13:32.000000000 +0100
++++ head-2010-01-04/include/xen/evtchn.h	2009-12-18 10:13:40.000000000 +0100
+@@ -193,6 +193,18 @@ static inline void notify_remote_via_evt
+ 	VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send));
+ }
+ 
++static inline void
++multi_notify_remote_via_evtchn(multicall_entry_t *mcl, int port)
++{
++	struct evtchn_send *send = (void *)(mcl->args + 2);
++
++	BUILD_BUG_ON(sizeof(*send) > sizeof(mcl->args) - 2 * sizeof(*mcl->args));
++	send->port = port;
++	mcl->op = __HYPERVISOR_event_channel_op;
++	mcl->args[0] = EVTCHNOP_send;
++	mcl->args[1] = (unsigned long)send;
++}
++
+ /* Clear an irq's pending state, in preparation for polling on it. */
+ void xen_clear_irq_pending(int irq);
+ 
+@@ -211,6 +223,7 @@ void xen_poll_irq(int irq);
+  * by bind_*_to_irqhandler().
+  */
+ void notify_remote_via_irq(int irq);
++int multi_notify_remote_via_irq(multicall_entry_t *, int irq);
+ int irq_to_evtchn_port(int irq);
+ 
+ #if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.15-16
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.15-16
@@ -0,0 +1,28 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.16
+Patch-mainline: 2.6.32.16
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.15-16" by xen-port-patches.py
+
+--- sle11sp1-2010-08-06.orig/arch/x86/kernel/setup-xen.c	2010-02-09 17:12:56.000000000 +0100
++++ sle11sp1-2010-08-06/arch/x86/kernel/setup-xen.c	2010-08-06 17:06:51.000000000 +0200
+@@ -757,6 +757,17 @@ static struct dmi_system_id __initdata b
+ 			DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
+ 		},
+ 	},
++	/*
++	 * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
++	 * match on the product name.
++	 */
++	{
++		.callback = dmi_low_memory_corruption,
++		.ident = "Phoenix BIOS",
++		.matches = {
++			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
++		},
++	},
+ #endif
+ 	{}
+ };
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.1-2
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.1-2
@@ -0,0 +1,93 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.2
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.1-2" by xen-port-patches.py
+
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-18 14:54:16.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/kernel/pci-dma-xen.c	2010-01-04 12:50:03.000000000 +0100
+@@ -268,7 +268,7 @@ static __init int iommu_setup(char *p)
+ 		if (!strncmp(p, "allowdac", 8))
+ 			forbid_dac = 0;
+ 		if (!strncmp(p, "nodac", 5))
+-			forbid_dac = -1;
++			forbid_dac = 1;
+ 		if (!strncmp(p, "usedac", 6)) {
+ 			forbid_dac = -1;
+ 			return 1;
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/setup-xen.c	2009-11-18 14:54:16.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/kernel/setup-xen.c	2010-01-04 12:50:03.000000000 +0100
+@@ -109,6 +109,7 @@
+ #ifdef CONFIG_X86_64
+ #include <asm/numa_64.h>
+ #endif
++#include <asm/mce.h>
+ 
+ #ifdef CONFIG_XEN
+ #include <asm/hypervisor.h>
+@@ -1260,6 +1261,8 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ #endif /* CONFIG_XEN */
+ 	x86_init.oem.banner();
++
++	mcheck_intel_therm_init();
+ }
+ 
+ #ifdef CONFIG_X86_32
+--- sle11sp1-2010-09-22.orig/drivers/xen/blktap2/sysfs.c	2010-09-23 11:01:08.000000000 +0200
++++ sle11sp1-2010-09-22/drivers/xen/blktap2/sysfs.c	2010-09-23 11:01:20.000000000 +0200
+@@ -39,11 +39,11 @@ blktap_sysfs_exit(struct blktap *tap)
+ static ssize_t blktap_sysfs_pause_device(struct device *,
+ 					 struct device_attribute *,
+ 					 const char *, size_t);
+-DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
++static DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
+ static ssize_t blktap_sysfs_resume_device(struct device *,
+ 					  struct device_attribute *,
+ 					  const char *, size_t);
+-DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
++static DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
+ 
+ static ssize_t
+ blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr,
+@@ -103,8 +103,8 @@ blktap_sysfs_get_name(struct device *dev
+ 
+ 	return size;
+ }
+-DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
+-		  blktap_sysfs_get_name, blktap_sysfs_set_name);
++static DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
++		   blktap_sysfs_get_name, blktap_sysfs_set_name);
+ 
+ static ssize_t
+ blktap_sysfs_remove_device(struct device *dev, struct device_attribute *attr,
+@@ -123,7 +123,7 @@ blktap_sysfs_remove_device(struct device
+ 
+ 	return (err ? : size);
+ }
+-DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
++static DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
+ 
+ static ssize_t
+ blktap_sysfs_pause_device(struct device *dev, struct device_attribute *attr,
+@@ -293,7 +293,7 @@ out:
+ 
+ 	return ret;
+ }
+-DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
++static DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
+ 
+ int
+ blktap_sysfs_create(struct blktap *tap)
+--- sle11sp1-2010-09-22.orig/drivers/xen/xenbus/xenbus_probe.c	2010-08-17 13:30:17.000000000 +0200
++++ sle11sp1-2010-09-22/drivers/xen/xenbus/xenbus_probe.c	2010-08-17 13:32:20.000000000 +0200
+@@ -562,7 +562,7 @@ static ssize_t xendev_show_modalias(stru
+ {
+ 	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
+ }
+-DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
++static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+ 
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ 		      const char *type,
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-x86-64-align-rodata-kernel-section-to-2mb-with-config_debug_rodata
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-x86-64-align-rodata-kernel-section-to-2mb-with-config_debug_rodata
@@ -0,0 +1,98 @@
+From: Suresh Siddha <suresh.b.siddha@intel.com>
+Date: Wed, 14 Oct 2009 21:46:56 +0000 (-0700)
+Subject: x86-64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA
+Patch-mainline: 2.6.33-rc1
+Git-commit: 74e081797bd9d2a7d8005fe519e719df343a2ba8
+References: bnc#558249
+
+x86-64: align RODATA kernel section to 2MB with CONFIG_DEBUG_RODATA
+
+CONFIG_DEBUG_RODATA chops the large pages spanning boundaries of kernel
+text/rodata/data to small 4KB pages as they are mapped with different
+attributes (text as RO, RODATA as RO and NX etc).
+
+On x86_64, preserve the large page mappings for kernel text/rodata/data
+boundaries when CONFIG_DEBUG_RODATA is enabled. This is done by allowing the
+RODATA section to be hugepage aligned and having same RWX attributes
+for the 2MB page boundaries
+
+Extra Memory pages padding the sections will be freed during the end of the boot
+and the kernel identity mappings will have different RWX permissions compared to
+the kernel text mappings.
+
+Kernel identity mappings to these physical pages will be mapped with smaller
+pages but large page mappings are still retained for kernel text,rodata,data
+mappings.
+
+Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
+LKML-Reference: <20091014220254.190119924@sbs-t61.sc.intel.com>
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.arch/x86-64-align-rodata-kernel-section-to-2mb-with-config_debug_rodata" by xen-port-patches.py
+
+--- head-2009-12-04.orig/arch/x86/kernel/vmlinux.lds.S	2009-11-06 10:52:02.000000000 +0100
++++ head-2009-12-04/arch/x86/kernel/vmlinux.lds.S	2009-12-04 12:08:47.000000000 +0100
+@@ -43,7 +43,7 @@ ENTRY(phys_startup_64)
+ jiffies_64 = jiffies;
+ #endif
+ 
+-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
++#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) && !defined(CONFIG_XEN)
+ /*
+  * On 64-bit, align RODATA to 2MB so that even with CONFIG_DEBUG_RODATA
+  * we retain large page mappings for boundaries spanning kernel text, rodata
+--- head-2009-12-04.orig/arch/x86/mm/init_64-xen.c	2009-12-04 12:04:25.000000000 +0100
++++ head-2009-12-04/arch/x86/mm/init_64-xen.c	2009-12-04 12:07:13.000000000 +0100
+@@ -980,9 +980,13 @@ void set_kernel_text_ro(void)
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata);
++	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long rodata_start =
+ 		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
++	unsigned long end = (unsigned long) &__end_rodata;
++	unsigned long text_end = PAGE_ALIGN((unsigned long) &__stop___ex_table);
++	unsigned long rodata_end = PAGE_ALIGN((unsigned long) &__end_rodata);
++	unsigned long data_start = (unsigned long) &_sdata;
+ 
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
+@@ -1005,6 +1009,14 @@ void mark_rodata_ro(void)
+ 	printk(KERN_INFO "Testing CPA: again\n");
+ 	set_memory_ro(start, (end-start) >> PAGE_SHIFT);
+ #endif
++
++	free_init_pages("unused kernel memory",
++			(unsigned long) page_address(virt_to_page(text_end)),
++			(unsigned long)
++				 page_address(virt_to_page(rodata_start)));
++	free_init_pages("unused kernel memory",
++			(unsigned long) page_address(virt_to_page(rodata_end)),
++			(unsigned long) page_address(virt_to_page(data_start)));
+ }
+ 
+ #endif
+--- head-2009-12-04.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2009-12-04/arch/x86/mm/pageattr-xen.c	2009-12-04 12:07:13.000000000 +0100
+@@ -281,6 +281,20 @@ static inline pgprot_t static_protection
+ 		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
+ 		pgprot_val(forbidden) |= _PAGE_RW;
+ 
++#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) && !defined(CONFIG_XEN)
++	/*
++	 * Kernel text mappings for the large page aligned .rodata section
++	 * will be read-only. For the kernel identity mappings covering
++	 * the holes caused by this alignment can be anything.
++	 *
++	 * This will preserve the large page mappings for kernel text/data
++	 * at no extra cost.
++	 */
++	if (within(address, (unsigned long)_text,
++		   (unsigned long)__end_rodata_hpage_align))
++		pgprot_val(forbidden) |= _PAGE_RW;
++#endif
++
+ 	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+ 
+ 	return prot;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.20-21
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.20-21
@@ -0,0 +1,30 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.21
+Patch-mainline: 2.6.32.21
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.20-21" by xen-port-patches.py
+
+--- sle11sp1-2010-09-29.orig/arch/x86/Kconfig	2010-09-29 11:07:58.000000000 +0200
++++ sle11sp1-2010-09-29/arch/x86/Kconfig	2010-09-29 11:32:02.000000000 +0200
+@@ -243,7 +243,7 @@ config KTIME_SCALAR
+ 
+ config ARCH_CPU_PROBE_RELEASE
+ 	def_bool y
+-	depends on HOTPLUG_CPU
++	depends on HOTPLUG_CPU && !XEN
+ 
+ source "init/Kconfig"
+ source "kernel/Kconfig.freezer"
+--- sle11sp1-2010-09-29.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-08-23 12:10:22.000000000 +0200
++++ sle11sp1-2010-09-29/arch/x86/kernel/apic/io_apic-xen.c	2010-09-22 11:35:28.000000000 +0200
+@@ -1818,6 +1818,8 @@ __apicdebuginit(void) print_IO_APIC(void
+ 		struct irq_pin_list *entry;
+ 
+ 		cfg = desc->chip_data;
++		if (!cfg)
++			continue;
+ 		entry = cfg->irq_2_pin;
+ 		if (!entry)
+ 			continue;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-driverlink
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-driverlink
@@ -0,0 +1,1133 @@
+From: David Riddoch <driddoch@solarflare.com>
+commit d96c061bfd1839e34e136de0555564520acc97af
+Author: Steve Hodgson <shodgson@solarflare.com>
+Date:   Mon Jul 14 15:38:47 2008 +0100
+
+Subject: sfc: Driverlink API for exporting hardware features to client drivers
+
+References: FATE#303479
+Acked-by: jbeulich@novell.com
+
+--- head-2009-11-06.orig/drivers/net/sfc/Makefile	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/Makefile	2009-07-28 10:04:25.000000000 +0200
+@@ -1,6 +1,7 @@
+ sfc-y			+= efx.o falcon.o tx.o rx.o falcon_gmac.o \
+ 			   falcon_xmac.o selftest.o ethtool.o xfp_phy.o \
+-			   mdio_10g.o tenxpress.o boards.o sfe4001.o
++			   mdio_10g.o tenxpress.o boards.o sfe4001.o \
++			   driverlink.o
+ sfc-$(CONFIG_SFC_MTD)	+= mtd.o
+ 
+ obj-$(CONFIG_SFC)	+= sfc.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-11-06/drivers/net/sfc/driverlink.c	2009-07-28 10:04:25.000000000 +0200
+@@ -0,0 +1,367 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005      Fen Systems Ltd.
++ * Copyright 2005-2008 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, incorporated herein by reference.
++ */
++
++#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_api.h"
++#include "driverlink.h"
++
++/* Protects @efx_driverlink_lock and @efx_driver_list */
++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
++ * @efx_dev: driverlink device handle exported to consumers
++ * @efx: efx_nic backing the driverlink device
++ * @port_node: per-device list head
++ * @driver_node: per-driver list head
++ */
++struct efx_dl_handle {
++	struct efx_dl_device efx_dev;
++	struct efx_nic *efx;
++	struct list_head port_node;
++	struct list_head driver_node;
++};
++
++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, and call the driver's remove() callback if
++ * present. The caller must hold @efx_driverlink_lock. */
++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);
++
++	if (efx_dev->driver->remove)
++		efx_dev->driver->remove(efx_dev);
++
++	list_del(&efx_handle->driver_node);
++	list_del(&efx_handle->port_node);
++
++	kfree(efx_handle);
++}
++
++/* Attempt to probe the given device with the driver, creating a
++ * new &struct efx_dl_device. If the probe routine returns an error,
++ * then the &struct 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;
++
++	efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL);
++	if (!efx_handle)
++		goto fail;
++	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);
++
++	rc = driver->probe(efx_dev, efx->net_dev,
++			   efx->dl_info, efx->silicon_rev);
++	if (rc)
++		goto fail;
++
++	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_handle);
++}
++
++/* Unregister a driver from the driverlink layer, calling the
++ * driver's remove() callback for every attached device */
++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);
++
++	mutex_lock(&efx_driverlink_lock);
++
++	list_for_each_entry_safe(efx_handle, efx_handle_n,
++				 &driver->device_list, driver_node)
++		efx_dl_del_device(&efx_handle->efx_dev);
++
++	list_del(&driver->node);
++
++	mutex_unlock(&efx_driverlink_lock);
++}
++EXPORT_SYMBOL(efx_dl_unregister_driver);
++
++/* Register a new driver with the driverlink layer. The driver's
++ * probe routine will be called for every attached nic. */
++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);
++
++	INIT_LIST_HEAD(&driver->node);
++	INIT_LIST_HEAD(&driver->device_list);
++
++	rc = mutex_lock_interruptible(&efx_driverlink_lock);
++	if (rc)
++		return rc;
++
++	list_add_tail(&driver->node, &efx_driver_list);
++	list_for_each_entry(efx, &efx_port_list, dl_node)
++		efx_dl_try_add_device(efx, driver);
++
++	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;
++
++	mutex_lock(&efx_driverlink_lock);
++
++	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);
++
++	list_del(&efx->dl_node);
++
++	mutex_unlock(&efx_driverlink_lock);
++}
++
++int efx_dl_register_nic(struct efx_nic *efx)
++{
++	struct efx_dl_driver *driver;
++	int rc;
++
++	rc = mutex_lock_interruptible(&efx_driverlink_lock);
++	if (rc)
++		return rc;
++
++	list_add_tail(&efx->dl_node, &efx_port_list);
++	list_for_each_entry(driver, &efx_driver_list, node)
++		efx_dl_try_add_device(efx, driver);
++
++	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.
++ */
++static enum efx_veto efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev,
++						  struct sk_buff *skb)
++{
++	return EFX_ALLOW_PACKET;
++}
++
++static enum efx_veto efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev,
++						  const char *pkt_buf, int len)
++{
++	return EFX_ALLOW_PACKET;
++}
++
++static int efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev,
++					  int new_mtu)
++{
++	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,
++	.request_mtu	= efx_dummy_request_mtu_callback,
++	.mtu_changed	= efx_dummy_mtu_changed_callback,
++	.event		= efx_dummy_event_callback,
++};
++
++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;
++
++	efx_suspend(efx);
++
++	EFX_INFO(efx, "removing callback hooks into %s driver\n",
++		 efx_dev->driver->name);
++
++	if (callbacks->tx_packet) {
++		BUG_ON(efx->dl_cb_dev.tx_packet != efx_dev);
++		efx->dl_cb.tx_packet = efx_default_callbacks.tx_packet;
++		efx->dl_cb_dev.tx_packet = NULL;
++	}
++	if (callbacks->rx_packet) {
++		BUG_ON(efx->dl_cb_dev.rx_packet != efx_dev);
++		efx->dl_cb.rx_packet = efx_default_callbacks.rx_packet;
++		efx->dl_cb_dev.rx_packet = NULL;
++	}
++	if (callbacks->request_mtu) {
++		BUG_ON(efx->dl_cb_dev.request_mtu != efx_dev);
++		efx->dl_cb.request_mtu = efx_default_callbacks.request_mtu;
++		efx->dl_cb_dev.request_mtu = NULL;
++	}
++	if (callbacks->mtu_changed) {
++		BUG_ON(efx->dl_cb_dev.mtu_changed != efx_dev);
++		efx->dl_cb.mtu_changed = efx_default_callbacks.mtu_changed;
++		efx->dl_cb_dev.mtu_changed = NULL;
++	}
++	if (callbacks->event) {
++		BUG_ON(efx->dl_cb_dev.event != efx_dev);
++		efx->dl_cb.event = efx_default_callbacks.event;
++		efx->dl_cb_dev.event = NULL;
++	}
++
++	efx_resume(efx);
++}
++EXPORT_SYMBOL(efx_dl_unregister_callbacks);
++
++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;
++
++	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->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 the requested callbacks, leaving any NULL members
++	 * referencing the members of @efx_default_callbacks */
++	if (callbacks->tx_packet) {
++		efx->dl_cb.tx_packet = callbacks->tx_packet;
++		efx->dl_cb_dev.tx_packet = efx_dev;
++	}
++	if (callbacks->rx_packet) {
++		efx->dl_cb.rx_packet = callbacks->rx_packet;
++		efx->dl_cb_dev.rx_packet = efx_dev;
++	}
++	if (callbacks->request_mtu) {
++		efx->dl_cb.request_mtu = callbacks->request_mtu;
++		efx->dl_cb_dev.request_mtu = efx_dev;
++	}
++	if (callbacks->mtu_changed) {
++		efx->dl_cb.mtu_changed = callbacks->mtu_changed;
++		efx->dl_cb_dev.mtu_changed = efx_dev;
++	}
++	if (callbacks->event) {
++		efx->dl_cb.event = callbacks->event;
++		efx->dl_cb_dev.event = efx_dev;
++	}
++
++ out:
++	efx_resume(efx);
++
++	return rc;
++}
++EXPORT_SYMBOL(efx_dl_register_callbacks);
++
++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);
++
++void efx_dl_reset_unlock(void)
++{
++	mutex_unlock(&efx_driverlink_lock);
++}
++
++/* Suspend ready for reset, serialising against all the driverlink interfacse
++ * and calling the suspend() callback of every registered driver */
++void efx_dl_reset_suspend(struct efx_nic *efx)
++{
++	struct efx_dl_handle *efx_handle;
++	struct efx_dl_device *efx_dev;
++
++	mutex_lock(&efx_driverlink_lock);
++
++	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, calling the resume() callback of every registered
++ * driver, and releasing @Efx_driverlink_lock acquired in
++ * efx_dl_reset_resume() */
++void efx_dl_reset_resume(struct efx_nic *efx, int ok)
++{
++	struct efx_dl_handle *efx_handle;
++	struct efx_dl_device *efx_dev;
++
++	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);
++	}
++
++	mutex_unlock(&efx_driverlink_lock);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-11-06/drivers/net/sfc/driverlink.h	2009-07-28 10:04:25.000000000 +0200
+@@ -0,0 +1,43 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005      Fen Systems Ltd.
++ * Copyright 2006-2008 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_DRIVERLINK_H
++#define EFX_DRIVERLINK_H
++
++/* Forward declarations */
++struct efx_dl_device;
++struct efx_nic;
++
++/* Efx callback devices
++ *
++ * A list of the devices that own each callback. The partner to
++ * struct efx_dl_callbacks.
++ */
++struct efx_dl_cb_devices {
++	struct efx_dl_device *tx_packet;
++	struct efx_dl_device *rx_packet;
++	struct efx_dl_device *request_mtu;
++	struct efx_dl_device *mtu_changed;
++	struct efx_dl_device *event;
++};
++
++extern struct efx_dl_callbacks efx_default_callbacks;
++
++#define EFX_DL_CALLBACK(_port, _name, ...)				\
++	(_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__)
++
++extern int efx_dl_register_nic(struct efx_nic *efx);
++extern void efx_dl_unregister_nic(struct efx_nic *efx);
++
++/* Suspend and resume client drivers over a hardware reset */
++extern void efx_dl_reset_suspend(struct efx_nic *efx);
++extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
++
++#endif /* EFX_DRIVERLINK_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2009-11-06/drivers/net/sfc/driverlink_api.h	2009-07-28 10:04:25.000000000 +0200
+@@ -0,0 +1,303 @@
++/****************************************************************************
++ * Driver for Solarflare Solarstorm network controllers and boards
++ * Copyright 2005-2006 Fen Systems Ltd.
++ * Copyright 2005-2008 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, incorporated herein by reference.
++ */
++
++#ifndef EFX_DRIVERLINK_API_H
++#define EFX_DRIVERLINK_API_H
++
++#include <linux/list.h>
++
++/* Forward declarations */
++struct pci_dev;
++struct net_device;
++struct sk_buff;
++struct efx_dl_device;
++struct efx_dl_device_info;
++
++/* An extra safeguard in addition to symbol versioning */
++#define EFX_DRIVERLINK_API_VERSION 2
++
++/**
++ * struct efx_dl_driver - An Efx driverlink device driver
++ *
++ * A driverlink client defines and initializes as many instances of
++ * efx_dl_driver as required, registering each one with
++ * efx_dl_register_driver().
++ *
++ * @name: Name of the driver
++ * @probe: Called when device added
++ *	The client should use the @def_info linked list and @silicon_rev
++ *	to determine if they wish to attach to this device.
++ *	Context: process, driverlink semaphore held
++ * @remove: Called when device removed
++ *	The client must ensure the finish all operations with this
++ *	device before returning from this method.
++ *	Context: process, driverlink semaphore held
++ * @reset_suspend: Called before device is reset
++ *	Called immediately before a hardware reset. The client must stop all
++ *	hardware processing before returning from this method. Callbacks will
++ *	be inactive when this method is called.
++ *	Context: process, driverlink semaphore held. rtnl_lock may be held
++ * @reset_resume: Called after device is reset
++ *	Called after a hardware reset. If @ok is true, the client should
++ *	state and resume normal operations. If @ok is false, the client should
++ *	abandon use of the hardware resources. remove() will still be called.
++ *	Context: process, driverlink semaphore held. rtnl_lock may be held
++ */
++struct efx_dl_driver {
++	const char *name;
++
++	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);
++	void (*remove) (struct efx_dl_device *efx_dev);
++	void (*reset_suspend) (struct efx_dl_device *efx_dev);
++	void (*reset_resume) (struct efx_dl_device *efx_dev, int ok);
++
++/* private: */
++	struct list_head node;
++	struct list_head device_list;
++};
++
++/**
++ * enum efx_dl_device_info_type - Device information identifier.
++ *
++ * Used to identify each item in the &struct efx_dl_device_info linked list
++ * provided to each driverlink client in the probe() @dev_info member.
++ *
++ * @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
++ */
++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 current Falcon device.
++ *
++ * @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
++ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts.
++ *	Falcon supports traditional legacy interrupts and MSI/MSI-X
++ *	interrupts. The choice is made at run time by the sfc driver, and
++ *	notified to the clients by this enumeration
++ */
++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_lim: Last available buffer table entry + 1
++ * @evq_timer_min: First available event queue with timer
++ * @evq_timer_lim: Last available event queue with timer + 1
++ * @evq_int_min: First available event queue with interrupt
++ * @evq_int_lim: Last available event queue with interrupt + 1
++ * @rxq_min: First available RX queue
++ * @rxq_lim: Last available RX queue + 1
++ * @txq_min: First available TX queue
++ * @txq_lim: 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;
++	unsigned buffer_table_lim;
++	unsigned evq_timer_min;
++	unsigned evq_timer_lim;
++	unsigned evq_int_min;
++	unsigned evq_int_lim;
++	unsigned rxq_min;
++	unsigned rxq_lim;
++	unsigned txq_min;
++	unsigned txq_lim;
++	enum efx_dl_falcon_resource_flags flags;
++};
++
++/**
++ * struct efx_dl_device - An Efx driverlink device.
++ *
++ * @pci_dev: PCI device used by the sfc driver.
++ * @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
++ *
++ * This is a tighly controlled set of simple callbacks, that are attached
++ * to the sfc driver via efx_dl_register_callbacks().  They export just enough
++ * state to allow clients to make use of the available hardware resources.
++ *
++ * For efficiency, only one client can hook each callback. Since these
++ * callbacks are called on packet transmit and reception paths, and the
++ * sfc driver may have multiple tx and rx queues per port, clients should
++ * avoid acquiring locks or allocating memory.
++ *
++ * @tx_packet: Called when packet is about to be transmitted
++ *	Called for every packet about to be transmitted, providing means
++ *	for the client to snoop traffic, and veto transmission by returning
++ *	%EFX_VETO_PACKET (the sfc driver will subsequently free the skb).
++ *	Context: tasklet, netif_tx_lock held
++ * @rx_packet: Called when packet is received
++ *	Called for every received packet (after LRO), allowing the client
++ *	to snoop every received packet (on every rx queue), and veto
++ *	reception by returning %EFX_VETO_PACKET.
++ *	Context: tasklet
++ * @request_mtu: Called to request MTU change.
++ *	Called whenever the user requests the net_dev mtu to be changed.
++ *	If the client returns an error, the mtu change is aborted. The sfc
++ *	driver guarantees that no other callbacks are running.
++ *	Context: process, rtnl_lock held.
++ * @mtu_changed: Called when MTU has been changed.
++ *	Called after the mtu has been successfully changed, always after
++ *	a previous call to request_mtu(). The sfc driver guarantees that no
++ *	other callbacks are running.
++ *	Context: process, rtnl_lock held.
++ * @event: Called when a hardware NIC event is not understood by the sfc driver.
++ *	Context: tasklet.
++ */
++struct efx_dl_callbacks {
++	enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev,
++				    struct sk_buff *skb);
++	enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev,
++				    const char *pkt_hdr, int pkt_len);
++	int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu);
++	void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu);
++	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)
++
++/* Exported driverlink api used to register and unregister the client driver
++ * and any callbacks [only one per port allowed], and to allow a client driver
++ * to request reset to recover from an error condition.
++ *
++ * All of these functions acquire the driverlink semaphore, so must not be
++ * called from an efx_dl_driver or efx_dl_callbacks member, and must be called
++ * from process context.
++ */
++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);
++
++/* Schedule a reset without grabbing any locks */
++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:
++ *	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:
++ *	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)
++ *		....
++ */
++#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 */
+--- head-2009-11-06.orig/drivers/net/sfc/efx.c	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/efx.c	2009-10-12 13:40:25.000000000 +0200
+@@ -1487,12 +1487,21 @@ static int efx_change_mtu(struct net_dev
+ 
+ 	efx_stop_all(efx);
+ 
++	/* Ask driverlink client if we can change MTU */
++	rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu);
++	if (rc)
++		goto out;
++
+ 	EFX_LOG(efx, "changing MTU to %d\n", new_mtu);
+ 
+ 	efx_fini_channels(efx);
+ 	net_dev->mtu = new_mtu;
+ 	efx_init_channels(efx);
+ 
++	/* Notify driverlink client of new MTU */
++	EFX_DL_CALLBACK(efx, mtu_changed, new_mtu);
++
++ out:
+ 	efx_start_all(efx);
+ 	return rc;
+ }
+@@ -1680,6 +1689,23 @@ static void efx_unregister_netdev(struct
+  * Device reset and suspend
+  *
+  **************************************************************************/
++/* Serialise access to the driverlink callbacks, by quiescing event processing
++ * (without flushing the descriptor queues), and acquiring the rtnl_lock */
++void efx_suspend(struct efx_nic *efx)
++{
++	EFX_LOG(efx, "suspending operations\n");
++
++	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();
++}
+ 
+ /* Tears down the entire software state and most of the hardware state
+  * before reset.  */
+@@ -1760,8 +1786,8 @@ static int efx_reset(struct efx_nic *efx
+ 	enum reset_type method = efx->reset_pending;
+ 	int rc = 0;
+ 
+-	/* Serialise with kernel interfaces */
+ 	rtnl_lock();
++	efx_dl_reset_suspend(efx);
+ 
+ 	/* If we're not RUNNING then don't reset. Leave the reset_pending
+ 	 * flag set so that efx_pci_probe_main will be retried */
+@@ -1807,6 +1833,7 @@ out_disable:
+ 	}
+ 
+ out_unlock:
++	efx_dl_reset_resume(efx, 1);
+ 	rtnl_unlock();
+ 	return rc;
+ }
+@@ -1951,6 +1978,9 @@ static int efx_init_struct(struct efx_ni
+ 	efx->mac_op = &efx_dummy_mac_operations;
+ 	efx->phy_op = &efx_dummy_phy_operations;
+ 	efx->mdio.dev = net_dev;
++	INIT_LIST_HEAD(&efx->dl_node);
++	INIT_LIST_HEAD(&efx->dl_device_list);
++	efx->dl_cb = efx_default_callbacks;
+ 	INIT_WORK(&efx->phy_work, efx_phy_work);
+ 	INIT_WORK(&efx->mac_work, efx_mac_work);
+ 	atomic_set(&efx->netif_stop_count, 1);
+@@ -2054,6 +2084,7 @@ static void efx_pci_remove(struct pci_de
+ 	efx = pci_get_drvdata(pci_dev);
+ 	if (!efx)
+ 		return;
++	efx_dl_unregister_nic(efx);
+ 
+ 	/* Mark the NIC as fini, then stop the interface */
+ 	rtnl_lock();
+@@ -2230,9 +2261,16 @@ static int __devinit efx_pci_probe(struc
+ 	if (rc)
+ 		goto fail5;
+ 
++	/* Register with driverlink layer */
++	rc = efx_dl_register_nic(efx);
++	if (rc)
++		goto fail6;
++
+ 	EFX_LOG(efx, "initialisation successful\n");
+ 	return 0;
+ 
++ fail6:
++	efx_unregister_netdev(efx);
+  fail5:
+ 	efx_pci_remove_main(efx);
+  fail4:
+--- head-2009-11-06.orig/drivers/net/sfc/falcon.c	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/falcon.c	2009-07-28 10:04:25.000000000 +0200
+@@ -36,14 +36,14 @@
+ 
+ /**
+  * struct falcon_nic_data - Falcon NIC state
+- * @next_buffer_table: First available buffer table id
++ * @resources: Resource information for driverlink client
+  * @pci_dev2: The secondary PCI device if present
+  * @i2c_data: Operations and state for I2C bit-bashing algorithm
+  * @int_error_count: Number of internal errors seen recently
+  * @int_error_expire: Time at which error count will be expired
+  */
+ struct falcon_nic_data {
+-	unsigned next_buffer_table;
++	struct efx_dl_falcon_resources resources;
+ 	struct pci_dev *pci_dev2;
+ 	struct i2c_algo_bit_data i2c_data;
+ 
+@@ -336,8 +336,8 @@ static int falcon_alloc_special_buffer(s
+ 	memset(buffer->addr, 0xff, len);
+ 
+ 	/* Select new buffer ID */
+-	buffer->index = nic_data->next_buffer_table;
+-	nic_data->next_buffer_table += buffer->entries;
++	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 %llx)\n", buffer->index,
+@@ -960,10 +960,12 @@ static void falcon_handle_driver_event(s
+ 	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",
+@@ -972,14 +974,17 @@ static void falcon_handle_driver_event(s
+ 	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. "
+@@ -1004,6 +1009,7 @@ static void falcon_handle_driver_event(s
+ 		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;
+ 	}
+ }
+@@ -2744,6 +2750,59 @@ static int falcon_probe_nvconfig(struct 
+ 	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 internal_dcs_entries;
++	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;
++
++	/* 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 = 16;
++		res->txq_min = 16;
++		res->evq_int_min = 4;
++		res->evq_int_lim = 5;
++		res->evq_timer_min = 5;
++		res->evq_timer_lim = 4096;
++		internal_dcs_entries = 8192;
++		break;
++	case FALCON_REV_B0:
++	default:
++		res->rxq_min = 0;
++		res->txq_min = 0;
++		res->evq_int_min = 0;
++		res->evq_int_lim = 64;
++		res->evq_timer_min = 64;
++		res->evq_timer_lim = 4096;
++		internal_dcs_entries = 4096;
++		break;
++	}
++
++	/* Internal SRAM only for now */
++	res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES;
++	res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES;
++	res->buffer_table_lim = 8192;
++
++	if (FALCON_IS_DUAL_FUNC(efx))
++		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.
+  */
+@@ -2771,9 +2830,11 @@ static int falcon_probe_nic_variant(stru
+ 			EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
+ 			return -ENODEV;
+ 		}
++		efx->silicon_rev = "falcon/a1";
+ 		break;
+ 
+ 	case FALCON_REV_B0:
++		efx->silicon_rev = "falcon/b0";
+ 		break;
+ 
+ 	default:
+@@ -2883,6 +2944,10 @@ int falcon_probe_nic(struct efx_nic *efx
+ 	if (rc)
+ 		goto fail5;
+ 
++	rc = falcon_dimension_resources(efx);
++	if (rc)
++		goto fail6;
++
+ 	/* Initialise I2C adapter */
+ 	efx->i2c_adap.owner = THIS_MODULE;
+ 	nic_data->i2c_data = falcon_i2c_bit_operations;
+@@ -2892,10 +2957,12 @@ int falcon_probe_nic(struct efx_nic *efx
+ 	strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
+ 	rc = i2c_bit_add_bus(&efx->i2c_adap);
+ 	if (rc)
+-		goto fail5;
++		goto fail6;
+ 
+ 	return 0;
+ 
++ fail6:
++	efx->dl_info = NULL;
+  fail5:
+ 	falcon_remove_spi_devices(efx);
+ 	falcon_free_buffer(efx, &efx->irq_status);
+@@ -3083,6 +3150,7 @@ void falcon_remove_nic(struct efx_nic *e
+ 	/* Tear down the private nic state */
+ 	kfree(efx->nic_data);
+ 	efx->nic_data = NULL;
++	efx->dl_info = NULL;
+ }
+ 
+ void falcon_update_nic_stats(struct efx_nic *efx)
+--- head-2009-11-06.orig/drivers/net/sfc/net_driver.h	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/net_driver.h	2009-07-28 10:04:25.000000000 +0200
+@@ -29,6 +29,8 @@
+ 
+ #include "enum.h"
+ #include "bitfield.h"
++#include "driverlink_api.h"
++#include "driverlink.h"
+ 
+ /**************************************************************************
+  *
+@@ -754,6 +756,12 @@ union efx_multicast_hash {
+  * @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
+  *
+  * The @priv field of the corresponding &struct net_device points to
+  * this.
+@@ -844,6 +852,13 @@ struct efx_nic {
+ 	unsigned int loopback_modes;
+ 
+ 	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;
+ };
+ 
+ static inline int efx_dev_registered(struct efx_nic *efx)
+--- head-2009-11-06.orig/drivers/net/sfc/rx.c	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/rx.c	2009-11-06 10:32:03.000000000 +0100
+@@ -447,7 +447,21 @@ static void efx_rx_packet_lro(struct efx
+ 			      struct efx_rx_buffer *rx_buf,
+ 			      bool checksummed)
+ {
++	struct efx_nic *efx = channel->efx;
+ 	struct napi_struct *napi = &channel->napi_str;
++	enum efx_veto veto;
++
++	/* It would be faster if we had access to packets at the
++	 * other side of generic LRO. Unfortunately, there isn't
++	 * an obvious interface to this, so veto packets before LRO */
++	veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
++	if (unlikely(veto)) {
++		EFX_TRACE(efx, "LRO 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);
++		return;
++	}
+ 
+ 	/* Pass the skb/page into the LRO engine */
+ 	if (rx_buf->page) {
+@@ -550,6 +564,7 @@ void __efx_rx_packet(struct efx_channel 
+ 		     struct efx_rx_buffer *rx_buf, bool 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
+@@ -561,6 +576,16 @@ void __efx_rx_packet(struct efx_channel 
+ 		goto done;
+ 	}
+ 
++	/* 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;
++	}
++
+ 	if (rx_buf->skb) {
+ 		prefetch(skb_shinfo(rx_buf->skb));
+ 
+--- head-2009-11-06.orig/drivers/net/sfc/tx.c	2009-11-06 10:29:51.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/tx.c	2009-10-12 13:40:32.000000000 +0200
+@@ -374,6 +374,7 @@ netdev_tx_t efx_hard_start_xmit(struct s
+ {
+ 	struct efx_nic *efx = netdev_priv(net_dev);
+ 	struct efx_tx_queue *tx_queue;
++	enum efx_veto veto;
+ 
+ 	if (unlikely(efx->port_inhibited))
+ 		return NETDEV_TX_BUSY;
+@@ -383,6 +384,17 @@ netdev_tx_t efx_hard_start_xmit(struct s
+ 	else
+ 		tx_queue = &efx->tx_queue[EFX_TX_QUEUE_NO_CSUM];
+ 
++	/* See if driverlink wants to veto the packet. */
++	veto = EFX_DL_CALLBACK(efx, tx_packet, skb);
++	if (unlikely(veto)) {
++		EFX_TRACE(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(skb);
++		return NETDEV_TX_OK;
++	}
++
+ 	return efx_xmit(efx, tx_queue, skb);
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-per-cpu-vcpu-info
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-per-cpu-vcpu-info
@@ -0,0 +1,611 @@
+From: jbeulich@novell.com
+Subject: x86: use per-cpu storage for shared vcpu_info structure
+Patch-mainline: obsolete
+
+... reducing access code size and latency, as well as being the
+prerequisite for removing the limitation on 32 vCPU-s per guest.
+
+--- head-2010-01-04.orig/arch/x86/include/asm/percpu.h	2010-01-05 16:46:11.000000000 +0100
++++ head-2010-01-04/arch/x86/include/asm/percpu.h	2009-11-06 11:12:01.000000000 +0100
+@@ -133,6 +133,38 @@ do {							\
+ 	ret__;						\
+ })
+ 
++#define percpu_xchg_op(op, var, val)			\
++({							\
++	typedef typeof(var) T__;			\
++	T__ ret__;					\
++	if (0)						\
++		ret__ = (val);				\
++	switch (sizeof(var)) {				\
++	case 1:						\
++		asm(op "b %0,"__percpu_arg(1)		\
++		    : "=q" (ret__), "+m" (var)		\
++		    : "0" ((T__)(val)));		\
++		break;					\
++	case 2:						\
++		asm(op "w %0,"__percpu_arg(1)		\
++		    : "=r" (ret__), "+m" (var)		\
++		    : "0" ((T__)(val)));		\
++		break;					\
++	case 4:						\
++		asm(op "l %0,"__percpu_arg(1)		\
++		    : "=r" (ret__), "+m" (var)		\
++		    : "0" ((T__)(val)));		\
++		break;					\
++	case 8:						\
++		asm(op "q %0,"__percpu_arg(1)		\
++		    : "=r" (ret__), "+m" (var)		\
++		    : "0" ((T__)(val)));		\
++		break;					\
++	default: __bad_percpu_size();			\
++	}						\
++	ret__;						\
++})
++
+ /*
+  * percpu_read() makes gcc load the percpu variable every time it is
+  * accessed while percpu_read_stable() allows the value to be cached.
+@@ -152,6 +184,10 @@ do {							\
+ #define percpu_and(var, val)	percpu_to_op("and", per_cpu__##var, val)
+ #define percpu_or(var, val)	percpu_to_op("or", per_cpu__##var, val)
+ #define percpu_xor(var, val)	percpu_to_op("xor", per_cpu__##var, val)
++#define percpu_xchg(var, val)   percpu_xchg_op("xchg", per_cpu__##var, val)
++#if defined(CONFIG_X86_XADD) || defined(CONFIG_X86_64)
++#define percpu_xadd(var, val)   percpu_xchg_op("xadd", per_cpu__##var, val)
++#endif
+ 
+ /* This is not atomic against other CPUs -- CPU preemption needs to be off */
+ #define x86_test_and_clear_bit_percpu(bit, var)				\
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:49:39.000000000 +0100
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:53:45.000000000 +0100
+@@ -50,12 +50,26 @@
+ 
+ extern shared_info_t *HYPERVISOR_shared_info;
+ 
++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
++DECLARE_PER_CPU(struct vcpu_info, vcpu_info);
++#define vcpu_info(cpu) (&per_cpu(vcpu_info, cpu))
++#define current_vcpu_info() (&__get_cpu_var(vcpu_info))
++#define vcpu_info_read(fld) percpu_read(vcpu_info.fld)
++#define vcpu_info_write(fld, val) percpu_write(vcpu_info.fld, val)
++#define vcpu_info_xchg(fld, val) percpu_xchg(vcpu_info.fld, val)
++void setup_vcpu_info(unsigned int cpu);
++void adjust_boot_vcpu_info(void);
++#else
+ #define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu))
+ #ifdef CONFIG_SMP
+ #define current_vcpu_info() vcpu_info(smp_processor_id())
+ #else
+ #define current_vcpu_info() vcpu_info(0)
+ #endif
++#define vcpu_info_read(fld) (current_vcpu_info()->fld)
++#define vcpu_info_write(fld, val) (current_vcpu_info()->fld = (val))
++static inline void setup_vcpu_info(unsigned int cpu) {}
++#endif
+ 
+ #ifdef CONFIG_X86_32
+ extern unsigned long hypervisor_virt_start;
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:52:22.000000000 +0100
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 11:12:01.000000000 +0100
+@@ -12,7 +12,7 @@
+  * includes these barriers, for example.
+  */
+ 
+-#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask)
++#define xen_save_fl(void) vcpu_info_read(evtchn_upcall_mask)
+ 
+ #define xen_restore_fl(f)					\
+ do {								\
+@@ -28,7 +28,7 @@ do {								\
+ 
+ #define xen_irq_disable()					\
+ do {								\
+-	current_vcpu_info()->evtchn_upcall_mask = 1;		\
++	vcpu_info_write(evtchn_upcall_mask, 1);			\
+ 	barrier();						\
+ } while (0)
+ 
+@@ -90,8 +90,6 @@ static inline void halt(void)
+ #define evtchn_upcall_pending		/* 0 */
+ #define evtchn_upcall_mask		1
+ 
+-#define sizeof_vcpu_shift		6
+-
+ #ifdef CONFIG_X86_64
+ # define __REG_si %rsi
+ # define __CPU_num PER_CPU_VAR(cpu_number)
+@@ -100,6 +98,22 @@ static inline void halt(void)
+ # define __CPU_num TI_cpu(%ebp)
+ #endif
+ 
++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
++
++#define GET_VCPU_INFO		PER_CPU(vcpu_info, __REG_si)
++#define __DISABLE_INTERRUPTS	movb $1,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
++#define __ENABLE_INTERRUPTS	movb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
++#define __TEST_PENDING		cmpb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_pending+0)
++#define DISABLE_INTERRUPTS(clb)	__DISABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS(clb)	__ENABLE_INTERRUPTS
++
++#define __SIZEOF_DISABLE_INTERRUPTS 8
++#define __SIZEOF_TEST_PENDING	8
++
++#else /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
++
++#define sizeof_vcpu_shift	6
++
+ #ifdef CONFIG_SMP
+ #define GET_VCPU_INFO		movl __CPU_num,%esi			; \
+ 				shl $sizeof_vcpu_shift,%esi		; \
+@@ -116,15 +130,21 @@ static inline void halt(void)
+ #define ENABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
+ 				__ENABLE_INTERRUPTS
+ 
++#define __SIZEOF_DISABLE_INTERRUPTS 4
++#define __SIZEOF_TEST_PENDING	3
++
++#endif /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
++
+ #ifndef CONFIG_X86_64
+ #define INTERRUPT_RETURN		iret
+-#define ENABLE_INTERRUPTS_SYSEXIT	__ENABLE_INTERRUPTS		; \
++#define ENABLE_INTERRUPTS_SYSEXIT					  \
++	movb $0,evtchn_upcall_mask(%esi) /* __ENABLE_INTERRUPTS */	; \
+ sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
+-	__TEST_PENDING							; \
++	cmpb $0,evtchn_upcall_pending(%esi) /* __TEST_PENDING */	; \
+ 	jnz  14f	/* process more events if necessary... */	; \
+ 	movl PT_ESI(%esp), %esi						; \
+ 	sysexit								; \
+-14:	__DISABLE_INTERRUPTS						; \
++14:	movb $1,evtchn_upcall_mask(%esi) /* __DISABLE_INTERRUPTS */	; \
+ 	TRACE_IRQS_OFF							; \
+ sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+ 	mov  $__KERNEL_PERCPU, %ecx					; \
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-10-13 17:22:09.000000000 +0200
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 11:12:01.000000000 +0100
+@@ -117,6 +117,8 @@ static inline void xen_set_pgd(pgd_t *pg
+ 
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
+ 
++extern unsigned long early_arbitrary_virt_to_mfn(void *va);
++
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+  * and a page entry and page directory to the page they refer to.
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:52:22.000000000 +0100
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/system.h	2009-11-06 11:12:01.000000000 +0100
+@@ -233,8 +233,8 @@ static inline void xen_write_cr0(unsigne
+ 	asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+ }
+ 
+-#define xen_read_cr2() (current_vcpu_info()->arch.cr2)
+-#define xen_write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val)))
++#define xen_read_cr2() vcpu_info_read(arch.cr2)
++#define xen_write_cr2(val) vcpu_info_write(arch.cr2, val)
+ 
+ static inline unsigned long xen_read_cr3(void)
+ {
+--- head-2010-01-04.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/cpu/common-xen.c	2009-11-06 11:12:01.000000000 +0100
+@@ -335,8 +335,16 @@ static const char *__cpuinit table_looku
+ __u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
+ __u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
+ 
+-void load_percpu_segment(int cpu)
++void __ref load_percpu_segment(int cpu)
+ {
++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
++	static bool done;
++
++	if (!done) {
++		done = true;
++		adjust_boot_vcpu_info();
++	}
++#endif
+ #ifdef CONFIG_X86_32
+ 	loadsegment(fs, __KERNEL_PERCPU);
+ #else
+--- head-2010-01-04.orig/arch/x86/kernel/entry_32-xen.S	2009-10-13 17:01:47.000000000 +0200
++++ head-2010-01-04/arch/x86/kernel/entry_32-xen.S	2009-11-06 11:12:01.000000000 +0100
+@@ -463,6 +463,9 @@ sysenter_exit:
+ 	movl PT_EIP(%esp), %edx
+ 	movl PT_OLDESP(%esp), %ecx
+ 	xorl %ebp,%ebp
++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
++	GET_VCPU_INFO
++#endif
+ 	TRACE_IRQS_ON
+ 1:	mov  PT_FS(%esp), %fs
+ 	PTGS_TO_GS
+@@ -975,7 +978,9 @@ critical_region_fixup:
+ 
+ .section .rodata,"a"
+ critical_fixup_table:
+-	.byte -1,-1,-1			# testb $0xff,(%esi) = __TEST_PENDING
++	.rept __SIZEOF_TEST_PENDING
++	.byte -1
++	.endr
+ 	.byte -1,-1			# jnz  14f
+ 	.byte 0				# pop  %ebx
+ 	.byte 1				# pop  %ecx
+@@ -994,7 +999,9 @@ critical_fixup_table:
+ 	.byte 10,10,10			# add  $8,%esp
+ #endif
+ 	.byte 12			# iret
+-	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
++	.rept __SIZEOF_DISABLE_INTERRUPTS
++	.byte -1
++	.endr
+ .previous
+ 
+ # Hypervisor uses this for application faults while it executes.
+--- head-2010-01-04.orig/arch/x86/kernel/head-xen.c	2009-10-15 15:32:46.000000000 +0200
++++ head-2010-01-04/arch/x86/kernel/head-xen.c	2009-11-06 11:12:01.000000000 +0100
+@@ -151,6 +151,8 @@ void __init xen_start_kernel(void)
+ 	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+ 	memset(empty_zero_page, 0, sizeof(empty_zero_page));
+ 
++	setup_vcpu_info(0);
++
+ 	/* Set up mapping of lowest 1MB of physical memory. */
+ 	for (i = 0; i < NR_FIX_ISAMAPS; i++)
+ 		if (is_initial_xendomain())
+--- head-2010-01-04.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:49:09.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/time-xen.c	2009-11-23 10:53:51.000000000 +0100
+@@ -267,16 +267,10 @@ static void get_time_values_from_xen(uns
+ 	local_irq_restore(flags);
+ }
+ 
+-static inline int time_values_up_to_date(unsigned int cpu)
++static inline int time_values_up_to_date(void)
+ {
+-	struct vcpu_time_info   *src;
+-	struct shadow_time_info *dst;
+-
+-	src = &vcpu_info(cpu)->time;
+-	dst = &per_cpu(shadow_time, cpu);
+-
+ 	rmb();
+-	return (dst->version == src->version);
++	return percpu_read(shadow_time.version) == vcpu_info_read(time.version);
+ }
+ 
+ static void sync_xen_wallclock(unsigned long dummy);
+@@ -322,7 +316,7 @@ static unsigned long long local_clock(vo
+ 		local_time_version = shadow->version;
+ 		rdtsc_barrier();
+ 		time = shadow->system_timestamp + get_nsec_offset(shadow);
+-		if (!time_values_up_to_date(cpu))
++		if (!time_values_up_to_date())
+ 			get_time_values_from_xen(cpu);
+ 		barrier();
+ 	} while (local_time_version != shadow->version);
+@@ -446,7 +440,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 		delta_cpu -= per_cpu(processed_system_time, cpu);
+ 
+ 		get_runstate_snapshot(&runstate);
+-	} while (!time_values_up_to_date(cpu));
++	} while (!time_values_up_to_date());
+ 
+ 	if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
+ 	     unlikely(delta_cpu < -(s64)permitted_clock_jitter))
+--- head-2010-01-04.orig/arch/x86/mm/hypervisor.c	2009-12-11 15:27:37.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/hypervisor.c	2010-01-05 16:47:18.000000000 +0100
+@@ -41,6 +41,7 @@
+ #include <xen/balloon.h>
+ #include <xen/features.h>
+ #include <xen/interface/memory.h>
++#include <xen/interface/vcpu.h>
+ #include <linux/module.h>
+ #include <linux/percpu.h>
+ #include <linux/highmem.h>
+@@ -50,7 +51,105 @@
+ EXPORT_SYMBOL(hypercall_page);
+ 
+ shared_info_t *__read_mostly HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++#ifndef CONFIG_XEN_VCPU_INFO_PLACEMENT
+ EXPORT_SYMBOL(HYPERVISOR_shared_info);
++#else
++DEFINE_PER_CPU(struct vcpu_info, vcpu_info) __aligned(sizeof(struct vcpu_info));
++EXPORT_PER_CPU_SYMBOL(vcpu_info);
++
++void __ref setup_vcpu_info(unsigned int cpu)
++{
++	struct vcpu_info *v = &per_cpu(vcpu_info, cpu);
++	struct vcpu_register_vcpu_info info;
++#ifdef CONFIG_X86_64
++	static bool first = true;
++
++	if (first) {
++		first = false;
++		info.mfn = early_arbitrary_virt_to_mfn(v);
++	} else
++#endif
++		info.mfn = arbitrary_virt_to_mfn(v);
++	info.offset = offset_in_page(v);
++
++	if (HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info,
++			       cpu, &info))
++		BUG();
++}
++
++void __init adjust_boot_vcpu_info(void)
++{
++	unsigned long lpfn, rpfn, lmfn, rmfn;
++	pte_t *lpte, *rpte;
++	unsigned int level;
++	mmu_update_t mmu[2];
++
++	/*
++	 * setup_vcpu_info() cannot be used more than once for a given (v)CPU,
++	 * hence we must swap the underlying MFNs of the two pages holding old
++	 * and new vcpu_info of the boot CPU.
++	 *
++	 * Do *not* use __get_cpu_var() or percpu_{write,...}() here, as the per-
++	 * CPU segment didn't get reloaded yet. Using percpu_read(), as in
++	 * arch_use_lazy_mmu_mode(), though undesirable, is safe except for the
++	 * accesses to variables that were updated in setup_percpu_areas().
++	 */
++	lpte = lookup_address((unsigned long)&per_cpu_var(vcpu_info)
++			      + (__per_cpu_load - __per_cpu_start),
++			      &level);
++	rpte = lookup_address((unsigned long)&per_cpu(vcpu_info, 0), &level);
++	BUG_ON(!lpte || !(pte_flags(*lpte) & _PAGE_PRESENT));
++	BUG_ON(!rpte || !(pte_flags(*rpte) & _PAGE_PRESENT));
++	lmfn = __pte_mfn(*lpte);
++	rmfn = __pte_mfn(*rpte);
++
++	if (lmfn == rmfn)
++		return;
++
++	lpfn = mfn_to_local_pfn(lmfn);
++	rpfn = mfn_to_local_pfn(rmfn);
++
++	printk(KERN_INFO
++	       "Swapping MFNs for PFN %lx and %lx (MFN %lx and %lx)\n",
++	       lpfn, rpfn, lmfn, rmfn);
++
++	xen_l1_entry_update(lpte, pfn_pte_ma(rmfn, pte_pgprot(*lpte)));
++	xen_l1_entry_update(rpte, pfn_pte_ma(lmfn, pte_pgprot(*rpte)));
++#ifdef CONFIG_X86_64
++	if (HYPERVISOR_update_va_mapping((unsigned long)__va(lpfn<<PAGE_SHIFT),
++					 pfn_pte_ma(rmfn, PAGE_KERNEL_RO), 0))
++		BUG();
++#endif
++	if (HYPERVISOR_update_va_mapping((unsigned long)__va(rpfn<<PAGE_SHIFT),
++					 pfn_pte_ma(lmfn, PAGE_KERNEL),
++					 UVMF_TLB_FLUSH))
++		BUG();
++
++	set_phys_to_machine(lpfn, rmfn);
++	set_phys_to_machine(rpfn, lmfn);
++
++	mmu[0].ptr = ((uint64_t)lmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++	mmu[0].val = rpfn;
++	mmu[1].ptr = ((uint64_t)rmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++	mmu[1].val = lpfn;
++	if (HYPERVISOR_mmu_update(mmu, 2, NULL, DOMID_SELF))
++		BUG();
++
++	/*
++	 * Copy over all contents of the page just replaced, except for the
++	 * vcpu_info itself, as it may have got updated after having been
++	 * copied from __per_cpu_load[].
++	 */
++	memcpy(__va(rpfn << PAGE_SHIFT),
++	       __va(lpfn << PAGE_SHIFT),
++	       (unsigned long)&per_cpu_var(vcpu_info) & (PAGE_SIZE - 1));
++	level = (unsigned long)(&per_cpu_var(vcpu_info) + 1) & (PAGE_SIZE - 1);
++	if (level)
++		memcpy(__va(rpfn << PAGE_SHIFT) + level,
++		       __va(lpfn << PAGE_SHIFT) + level,
++		       PAGE_SIZE - level);
++}
++#endif
+ 
+ #define NR_MC     BITS_PER_LONG
+ #define NR_MMU    BITS_PER_LONG
+--- head-2010-01-04.orig/arch/x86/mm/init_64-xen.c	2009-11-12 17:37:05.000000000 +0100
++++ head-2010-01-04/arch/x86/mm/init_64-xen.c	2009-11-06 11:12:01.000000000 +0100
+@@ -116,6 +116,26 @@ void __meminit early_make_page_readonly(
+ 		BUG();
+ }
+ 
++unsigned long __init early_arbitrary_virt_to_mfn(void *v)
++{
++	unsigned long va = (unsigned long)v, addr, *page;
++
++	BUG_ON(va < __START_KERNEL_map);
++
++	page = (void *)(xen_read_cr3() + __START_KERNEL_map);
++
++	addr = page[pgd_index(va)];
++	addr_to_page(addr, page);
++
++	addr = page[pud_index(va)];
++	addr_to_page(addr, page);
++
++	addr = page[pmd_index(va)];
++	addr_to_page(addr, page);
++
++	return (page[pte_index(va)] & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT;
++}
++
+ #ifndef CONFIG_XEN
+ static int __init parse_direct_gbpages_off(char *arg)
+ {
+--- head-2010-01-04.orig/drivers/xen/Kconfig	2009-12-18 12:31:08.000000000 +0100
++++ head-2010-01-04/drivers/xen/Kconfig	2009-12-18 12:31:21.000000000 +0100
+@@ -365,6 +365,18 @@ config XEN_COMPAT
+ 	default 0x030002 if XEN_COMPAT_030002_AND_LATER
+ 	default 0
+ 
++config XEN_VCPU_INFO_PLACEMENT
++	bool "Place shared vCPU info in per-CPU storage"
++#	depends on X86 && (XEN_COMPAT >= 0x00030101)
++	depends on X86
++	depends on !XEN_COMPAT_030002_AND_LATER
++	depends on !XEN_COMPAT_030004_AND_LATER
++	depends on !XEN_COMPAT_030100_AND_LATER
++	default SMP
++	---help---
++	  This allows faster access to the per-vCPU shared info
++	  structure.
++
+ endmenu
+ 
+ config HAVE_IRQ_IGNORE_UNHANDLED
+--- head-2010-01-04.orig/drivers/xen/core/evtchn.c	2009-11-06 11:10:30.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/evtchn.c	2009-11-06 11:12:01.000000000 +0100
+@@ -316,6 +316,24 @@ static DEFINE_PER_CPU(unsigned int, upca
+ static DEFINE_PER_CPU(unsigned int, last_processed_l1i) = { BITS_PER_LONG - 1 };
+ static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 };
+ 
++#ifndef vcpu_info_xchg
++#define vcpu_info_xchg(fld, val) xchg(&current_vcpu_info()->fld, val)
++#endif
++
++#ifndef percpu_xadd
++#define percpu_xadd(var, val)					\
++({								\
++	typeof(per_cpu_var(var)) __tmp_var__;			\
++	unsigned long flags;					\
++	local_irq_save(flags);					\
++	__tmp_var__ = get_cpu_var(var);				\
++	__get_cpu_var(var) += (val);				\
++	put_cpu_var(var);					\
++	local_irq_restore(flags);				\
++	__tmp_var__;						\
++})
++#endif
++
+ /* NB. Interrupts are disabled on entry. */
+ asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs)
+ {
+@@ -324,25 +342,25 @@ asmlinkage void __irq_entry evtchn_do_up
+ 	unsigned long       masked_l1, masked_l2;
+ 	unsigned int        l1i, l2i, port, count;
+ 	int                 irq;
+-	vcpu_info_t        *vcpu_info = current_vcpu_info();
+ 
+ 	exit_idle();
+ 	irq_enter();
+ 
+ 	do {
+ 		/* Avoid a callback storm when we reenable delivery. */
+-		vcpu_info->evtchn_upcall_pending = 0;
++		vcpu_info_write(evtchn_upcall_pending, 0);
+ 
+ 		/* Nested invocations bail immediately. */
+-		percpu_add(upcall_count, 1);
+-		if (unlikely(percpu_read(upcall_count) != 1))
++		if (unlikely(percpu_xadd(upcall_count, 1)))
+ 			break;
+ 
+ #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
+ 		/* Clear master flag /before/ clearing selector flag. */
+ 		wmb();
++#else
++		barrier();
+ #endif
+-		l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
++		l1 = vcpu_info_xchg(evtchn_pending_sel, 0);
+ 
+ 		l1i = percpu_read(last_processed_l1i);
+ 		l2i = percpu_read(last_processed_l2i);
+@@ -1363,7 +1381,6 @@ void unmask_evtchn(int port)
+ {
+ 	shared_info_t *s = HYPERVISOR_shared_info;
+ 	unsigned int cpu = smp_processor_id();
+-	vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
+ 
+ 	BUG_ON(!irqs_disabled());
+ 
+@@ -1377,10 +1394,13 @@ void unmask_evtchn(int port)
+ 	synch_clear_bit(port, s->evtchn_mask);
+ 
+ 	/* Did we miss an interrupt 'edge'? Re-fire if so. */
+-	if (synch_test_bit(port, s->evtchn_pending) &&
+-	    !synch_test_and_set_bit(port / BITS_PER_LONG,
+-				    &vcpu_info->evtchn_pending_sel))
+-		vcpu_info->evtchn_upcall_pending = 1;
++	if (synch_test_bit(port, s->evtchn_pending)) {
++		vcpu_info_t *vcpu_info = current_vcpu_info();
++
++		if (!synch_test_and_set_bit(port / BITS_PER_LONG,
++					    &vcpu_info->evtchn_pending_sel))
++			vcpu_info->evtchn_upcall_pending = 1;
++	}
+ }
+ EXPORT_SYMBOL_GPL(unmask_evtchn);
+ 
+--- head-2010-01-04.orig/drivers/xen/core/machine_reboot.c	2009-12-18 14:15:04.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/machine_reboot.c	2009-12-18 14:15:17.000000000 +0100
+@@ -73,7 +73,7 @@ static void pre_suspend(void)
+ 		mfn_to_pfn(xen_start_info->console.domU.mfn);
+ }
+ 
+-static void post_suspend(int suspend_cancelled)
++static void post_suspend(int suspend_cancelled, int fast_suspend)
+ {
+ 	int i, j, k, fpp;
+ 	unsigned long shinfo_mfn;
+@@ -90,8 +90,21 @@ static void post_suspend(int suspend_can
+ #ifdef CONFIG_SMP
+ 		cpumask_copy(vcpu_initialized_mask, cpu_online_mask);
+ #endif
+-		for_each_possible_cpu(i)
++		for_each_possible_cpu(i) {
+ 			setup_runstate_area(i);
++
++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
++			if (fast_suspend && i != smp_processor_id()
++			    && HYPERVISOR_vcpu_op(VCPUOP_down, i, NULL))
++				BUG();
++
++			setup_vcpu_info(i);
++
++			if (fast_suspend && i != smp_processor_id()
++			    && HYPERVISOR_vcpu_op(VCPUOP_up, i, NULL))
++				BUG();
++#endif
++		}
+ 	}
+ 
+ 	shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT;
+@@ -133,7 +146,7 @@ static void post_suspend(int suspend_can
+ #define switch_idle_mm()	((void)0)
+ #define mm_pin_all()		((void)0)
+ #define pre_suspend()		xen_pre_suspend()
+-#define post_suspend(x)		xen_post_suspend(x)
++#define post_suspend(x, f)	xen_post_suspend(x)
+ 
+ #endif
+ 
+@@ -164,7 +177,7 @@ static int take_machine_down(void *_susp
+ 		BUG_ON(suspend_cancelled > 0);
+ 	suspend->resume_notifier(suspend_cancelled);
+ 	if (suspend_cancelled >= 0) {
+-		post_suspend(suspend_cancelled);
++		post_suspend(suspend_cancelled, suspend->fast_suspend);
+ 		sysdev_resume();
+ 	}
+ 	if (!suspend_cancelled) {
+--- head-2010-01-04.orig/drivers/xen/core/smpboot.c	2009-10-15 11:12:11.000000000 +0200
++++ head-2010-01-04/drivers/xen/core/smpboot.c	2009-11-06 11:12:01.000000000 +0100
+@@ -361,8 +361,13 @@ void __init smp_prepare_cpus(unsigned in
+ 
+ void __init smp_prepare_boot_cpu(void)
+ {
++	unsigned int cpu;
++
+ 	switch_to_new_gdt(smp_processor_id());
+ 	prefill_possible_map();
++	for_each_possible_cpu(cpu)
++		if (cpu != smp_processor_id())
++			setup_vcpu_info(cpu);
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-exit-mmap
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-exit-mmap
@@ -0,0 +1,72 @@
+Subject: be more aggressive about de-activating mm-s under destruction
+From: jbeulich@novell.com
+Patch-mainline: obsolete
+
+... by not only handling the current task on the CPU arch_exit_mmap()
+gets executed on, but also forcing remote CPUs to do so.
+
+--- head-2009-10-12.orig/arch/x86/mm/pgtable-xen.c	2009-10-13 17:22:09.000000000 +0200
++++ head-2009-10-12/arch/x86/mm/pgtable-xen.c	2009-10-14 14:19:25.000000000 +0200
+@@ -1,5 +1,6 @@
+ #include <linux/mm.h>
+ #include <linux/module.h>
++#include <linux/smp.h>
+ #include <xen/features.h>
+ #include <asm/pgalloc.h>
+ #include <asm/pgtable.h>
+@@ -416,27 +417,44 @@ void arch_dup_mmap(struct mm_struct *old
+ 		mm_pin(mm);
+ }
+ 
+-void arch_exit_mmap(struct mm_struct *mm)
++/*
++ * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() *much*
++ * faster this way, as no hypercalls are needed for the page table updates.
++ */
++static void leave_active_mm(struct task_struct *tsk, struct mm_struct *mm)
++	__releases(tsk->alloc_lock)
+ {
+-	struct task_struct *tsk = current;
+-
+-	task_lock(tsk);
+-
+-	/*
+-	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+-	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+-	 */
+ 	if (tsk->active_mm == mm) {
+ 		tsk->active_mm = &init_mm;
+ 		atomic_inc(&init_mm.mm_count);
+ 
+ 		switch_mm(mm, &init_mm, tsk);
+ 
+-		atomic_dec(&mm->mm_count);
+-		BUG_ON(atomic_read(&mm->mm_count) == 0);
++		if (atomic_dec_and_test(&mm->mm_count))
++			BUG();
+ 	}
+ 
+ 	task_unlock(tsk);
++}
++
++static void _leave_active_mm(void *mm)
++{
++	struct task_struct *tsk = current;
++
++	if (spin_trylock(&tsk->alloc_lock))
++		leave_active_mm(tsk, mm);
++}
++
++void arch_exit_mmap(struct mm_struct *mm)
++{
++	struct task_struct *tsk = current;
++
++	task_lock(tsk);
++	leave_active_mm(tsk, mm);
++
++	preempt_disable();
++	smp_call_function_many(mm_cpumask(mm), _leave_active_mm, mm, 1);
++	preempt_enable();
+ 
+ 	if (PagePinned(virt_to_page(mm->pgd))
+ 	    && atomic_read(&mm->mm_count) == 1
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-xen-drivers.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-xen-drivers.diff
@@ -0,0 +1,59929 @@
+Subject: xen3 xen-drivers
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 984:0bec29c94ce9)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/balloon/Makefile	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y := balloon.o sysfs.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,713 @@
++/******************************************************************************
++ * balloon.c
++ *
++ * Xen balloon driver - enables returning/claiming memory to/from Xen.
++ *
++ * Copyright (c) 2003, B Dragovic
++ * Copyright (c) 2003-2004, M Williamson, K Fraser
++ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
++ * 
++ * 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/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/smp_lock.h>
++#include <linux/pagemap.h>
++#include <linux/bootmem.h>
++#include <linux/highmem.h>
++#include <linux/vmalloc.h>
++#include <linux/mutex.h>
++#include <xen/xen_proc.h>
++#include <asm/hypervisor.h>
++#include <xen/balloon.h>
++#include <xen/interface/memory.h>
++#include <asm/maddr.h>
++#include <asm/page.h>
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/tlb.h>
++#include <linux/highmem.h>
++#include <linux/list.h>
++#include <xen/xenbus.h>
++#include "common.h"
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#ifdef CONFIG_PROC_FS
++static struct proc_dir_entry *balloon_pde;
++#endif
++
++static DEFINE_MUTEX(balloon_mutex);
++
++/*
++ * Protects atomic reservation decrease/increase against concurrent increases.
++ * Also protects non-atomic updates of current_pages and driver_pages, and
++ * balloon lists.
++ */
++DEFINE_SPINLOCK(balloon_lock);
++
++struct balloon_stats balloon_stats;
++
++/* We increase/decrease in batches which fit in a page */
++static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
++
++/* VM /proc information for memory */
++extern unsigned long totalram_pages;
++
++#ifndef MODULE
++extern unsigned long totalhigh_pages;
++#define inc_totalhigh_pages() (totalhigh_pages++)
++#define dec_totalhigh_pages() (totalhigh_pages--)
++#else
++#define inc_totalhigh_pages() ((void)0)
++#define dec_totalhigh_pages() ((void)0)
++#endif
++
++/* List of ballooned pages, threaded through the mem_map array. */
++static LIST_HEAD(ballooned_pages);
++
++/* Main work function, always executed in process context. */
++static void balloon_process(void *unused);
++static DECLARE_WORK(balloon_worker, balloon_process, NULL);
++static struct timer_list balloon_timer;
++
++/* When ballooning out (allocating memory to return to Xen) we don't really 
++   want the kernel to try too hard since that can trigger the oom killer. */
++#define GFP_BALLOON \
++	(GFP_HIGHUSER|__GFP_NOWARN|__GFP_NORETRY|__GFP_NOMEMALLOC|__GFP_COLD)
++
++#define PAGE_TO_LIST(p) (&(p)->lru)
++#define LIST_TO_PAGE(l) list_entry((l), struct page, lru)
++#define UNLIST_PAGE(p)				\
++	do {					\
++		list_del(PAGE_TO_LIST(p));	\
++		PAGE_TO_LIST(p)->next = NULL;	\
++		PAGE_TO_LIST(p)->prev = NULL;	\
++	} while(0)
++
++#define IPRINTK(fmt, args...) \
++	printk(KERN_INFO "xen_mem: " fmt, ##args)
++#define WPRINTK(fmt, args...) \
++	printk(KERN_WARNING "xen_mem: " fmt, ##args)
++
++/* balloon_append: add the given page to the balloon. */
++static void balloon_append(struct page *page)
++{
++	/* Lowmem is re-populated first, so highmem pages go at list tail. */
++	if (PageHighMem(page)) {
++		list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
++		bs.balloon_high++;
++		dec_totalhigh_pages();
++	} else {
++		list_add(PAGE_TO_LIST(page), &ballooned_pages);
++		bs.balloon_low++;
++	}
++}
++
++/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
++static struct page *balloon_retrieve(void)
++{
++	struct page *page;
++
++	if (list_empty(&ballooned_pages))
++		return NULL;
++
++	page = LIST_TO_PAGE(ballooned_pages.next);
++	UNLIST_PAGE(page);
++
++	if (PageHighMem(page)) {
++		bs.balloon_high--;
++		inc_totalhigh_pages();
++	}
++	else
++		bs.balloon_low--;
++
++	return page;
++}
++
++static struct page *balloon_first_page(void)
++{
++	if (list_empty(&ballooned_pages))
++		return NULL;
++	return LIST_TO_PAGE(ballooned_pages.next);
++}
++
++static struct page *balloon_next_page(struct page *page)
++{
++	struct list_head *next = PAGE_TO_LIST(page)->next;
++	if (next == &ballooned_pages)
++		return NULL;
++	return LIST_TO_PAGE(next);
++}
++
++static inline void balloon_free_page(struct page *page)
++{
++#ifndef MODULE
++	if (put_page_testzero(page))
++		free_cold_page(page);
++#else
++	/* free_cold_page() is not being exported. */
++	__free_page(page);
++#endif
++}
++
++static void balloon_alarm(unsigned long unused)
++{
++	schedule_work(&balloon_worker);
++}
++
++static unsigned long current_target(void)
++{
++	unsigned long target = bs.target_pages;
++	if (target > (bs.current_pages + bs.balloon_low + bs.balloon_high))
++		target = bs.current_pages + bs.balloon_low + bs.balloon_high;
++	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;
++	struct page   *page;
++	long           rc;
++	struct xen_memory_reservation reservation = {
++		.address_bits = 0,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++
++	if (nr_pages > ARRAY_SIZE(frame_list))
++		nr_pages = ARRAY_SIZE(frame_list);
++
++	balloon_lock(flags);
++
++	page = balloon_first_page();
++	for (i = 0; i < nr_pages; i++) {
++		BUG_ON(page == NULL);
++		frame_list[i] = page_to_pfn(page);;
++		page = balloon_next_page(page);
++	}
++
++	set_xen_guest_handle(reservation.extent_start, frame_list);
++	reservation.nr_extents = nr_pages;
++	rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
++	if (rc < 0)
++		goto out;
++
++	for (i = 0; i < rc; i++) {
++		page = balloon_retrieve();
++		BUG_ON(page == NULL);
++
++		pfn = page_to_pfn(page);
++		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
++		       phys_to_machine_mapping_valid(pfn));
++
++		set_phys_to_machine(pfn, frame_list[i]);
++
++#ifdef CONFIG_XEN
++		/* Link back into the page tables if not highmem. */
++		if (pfn < max_low_pfn) {
++			int ret;
++			ret = HYPERVISOR_update_va_mapping(
++				(unsigned long)__va(pfn << PAGE_SHIFT),
++				pfn_pte_ma(frame_list[i], PAGE_KERNEL),
++				0);
++			BUG_ON(ret);
++		}
++#endif
++
++		/* Relinquish the page back to the allocator. */
++		ClearPageReserved(page);
++		init_page_count(page);
++		balloon_free_page(page);
++	}
++
++	bs.current_pages += rc;
++	totalram_pages = bs.current_pages;
++
++ out:
++	balloon_unlock(flags);
++
++	return rc < 0 ? rc : rc != nr_pages;
++}
++
++static int decrease_reservation(unsigned long nr_pages)
++{
++	unsigned long  pfn, i, flags;
++	struct page   *page;
++	void          *v;
++	int            need_sleep = 0;
++	int ret;
++	struct xen_memory_reservation reservation = {
++		.address_bits = 0,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++
++	if (nr_pages > ARRAY_SIZE(frame_list))
++		nr_pages = ARRAY_SIZE(frame_list);
++
++	for (i = 0; i < nr_pages; i++) {
++		if ((page = alloc_page(GFP_BALLOON)) == NULL) {
++			nr_pages = i;
++			need_sleep = 1;
++			break;
++		}
++
++		pfn = page_to_pfn(page);
++		frame_list[i] = pfn_to_mfn(pfn);
++
++		if (!PageHighMem(page)) {
++			v = phys_to_virt(pfn << PAGE_SHIFT);
++			scrub_pages(v, 1);
++#ifdef CONFIG_XEN
++			ret = HYPERVISOR_update_va_mapping(
++				(unsigned long)v, __pte_ma(0), 0);
++			BUG_ON(ret);
++#endif
++		}
++#ifdef CONFIG_XEN_SCRUB_PAGES
++		else {
++			v = kmap(page);
++			scrub_pages(v, 1);
++			kunmap(page);
++		}
++#endif
++	}
++
++#ifdef CONFIG_XEN
++	/* Ensure that ballooned highmem pages don't have kmaps. */
++	kmap_flush_unused();
++	flush_tlb_all();
++#endif
++
++	balloon_lock(flags);
++
++	/* No more mappings: invalidate P2M and add to balloon. */
++	for (i = 0; i < nr_pages; i++) {
++		pfn = mfn_to_pfn(frame_list[i]);
++		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++		balloon_append(pfn_to_page(pfn));
++	}
++
++	set_xen_guest_handle(reservation.extent_start, frame_list);
++	reservation.nr_extents   = nr_pages;
++	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++	BUG_ON(ret != nr_pages);
++
++	bs.current_pages -= nr_pages;
++	totalram_pages = bs.current_pages;
++
++	balloon_unlock(flags);
++
++	return need_sleep;
++}
++
++/*
++ * We avoid multiple worker processes conflicting via the balloon mutex.
++ * We may of course race updates of the target counts (which are protected
++ * by the balloon lock), or with changes to the Xen hard limit, but we will
++ * recover from these in time.
++ */
++static void balloon_process(void *unused)
++{
++	int need_sleep = 0;
++	long credit;
++
++	mutex_lock(&balloon_mutex);
++
++	do {
++		credit = current_target() - bs.current_pages;
++		if (credit > 0)
++			need_sleep = (increase_reservation(credit) != 0);
++		if (credit < 0)
++			need_sleep = (decrease_reservation(-credit) != 0);
++
++#ifndef CONFIG_PREEMPT
++		if (need_resched())
++			schedule();
++#endif
++	} while ((credit != 0) && !need_sleep);
++
++	/* Schedule more work if there is some still to be done. */
++	if (current_target() != bs.current_pages)
++		mod_timer(&balloon_timer, jiffies + HZ);
++
++	mutex_unlock(&balloon_mutex);
++}
++
++/* Resets the Xen limit, sets new target, and kicks off processing. */
++void balloon_set_new_target(unsigned long target)
++{
++	/* No need for lock. Not read-modify-write updates. */
++	bs.target_pages = max(target, minimum_target());
++	schedule_work(&balloon_worker);
++}
++
++static struct xenbus_watch target_watch =
++{
++	.node = "memory/target"
++};
++
++/* React to a change in the target key */
++static void watch_target(struct xenbus_watch *watch,
++			 const char **vec, unsigned int len)
++{
++	unsigned long long new_target;
++	int err;
++
++	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
++	if (err != 1) {
++		/* This is ok (for domain0 at least) - so just return */
++		return;
++	}
++
++	/* The given memory/target value is in KiB, so it needs converting to
++	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
++	 */
++	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
++}
++
++static int balloon_init_watcher(struct notifier_block *notifier,
++				unsigned long event,
++				void *data)
++{
++	int err;
++
++	err = register_xenbus_watch(&target_watch);
++	if (err)
++		printk(KERN_ERR "Failed to set balloon watcher\n");
++
++	return NOTIFY_DONE;
++}
++
++#ifdef CONFIG_PROC_FS
++static int balloon_write(struct file *file, const char __user *buffer,
++			 unsigned long count, void *data)
++{
++	char memstring[64], *endchar;
++	unsigned long long target_bytes;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++
++	if (count <= 1)
++		return -EBADMSG; /* runt */
++	if (count > sizeof(memstring))
++		return -EFBIG;   /* too long */
++
++	if (copy_from_user(memstring, buffer, count))
++		return -EFAULT;
++	memstring[sizeof(memstring)-1] = '\0';
++
++	target_bytes = memparse(memstring, &endchar);
++	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++
++	return count;
++}
++
++static int balloon_read(char *page, char **start, off_t off,
++			int count, int *eof, void *data)
++{
++	int len;
++
++	len = sprintf(
++		page,
++		"Current allocation: %8lu kB\n"
++		"Requested target:   %8lu kB\n"
++		"Low-mem balloon:    %8lu kB\n"
++		"High-mem balloon:   %8lu kB\n"
++		"Driver pages:       %8lu kB\n",
++		PAGES2KB(bs.current_pages), PAGES2KB(bs.target_pages), 
++		PAGES2KB(bs.balloon_low), PAGES2KB(bs.balloon_high),
++		PAGES2KB(bs.driver_pages));
++
++
++	*eof = 1;
++	return len;
++}
++#endif
++
++static struct notifier_block xenstore_notifier;
++
++static int __init balloon_init(void)
++{
++#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
++	unsigned long pfn;
++	struct page *page;
++#endif
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	IPRINTK("Initialising balloon driver.\n");
++
++#ifdef CONFIG_XEN
++	bs.current_pages = min(xen_start_info->nr_pages, max_pfn);
++	totalram_pages   = bs.current_pages;
++#else 
++	bs.current_pages = totalram_pages; 
++#endif
++	bs.target_pages  = bs.current_pages;
++	bs.balloon_low   = 0;
++	bs.balloon_high  = 0;
++	bs.driver_pages  = 0UL;
++
++	init_timer(&balloon_timer);
++	balloon_timer.data = 0;
++	balloon_timer.function = balloon_alarm;
++    
++#ifdef CONFIG_PROC_FS
++	if ((balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL) {
++		WPRINTK("Unable to create /proc/xen/balloon.\n");
++		return -1;
++	}
++
++	balloon_pde->read_proc  = balloon_read;
++	balloon_pde->write_proc = balloon_write;
++#endif
++	balloon_sysfs_init();
++
++#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
++	/* Initialise the balloon with excess memory space. */
++	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
++		page = pfn_to_page(pfn);
++		if (!PageReserved(page))
++			balloon_append(page);
++	}
++#endif
++
++	target_watch.callback = watch_target;
++	xenstore_notifier.notifier_call = balloon_init_watcher;
++
++	register_xenstore_notifier(&xenstore_notifier);
++    
++	return 0;
++}
++
++subsys_initcall(balloon_init);
++
++static void __exit balloon_exit(void)
++{
++	balloon_sysfs_exit();
++	/* XXX - release balloon here */
++}
++
++module_exit(balloon_exit); 
++
++void balloon_update_driver_allowance(long delta)
++{
++	unsigned long flags;
++
++	balloon_lock(flags);
++	bs.driver_pages += delta;
++	balloon_unlock(flags);
++}
++
++#ifdef CONFIG_XEN
++static int dealloc_pte_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	unsigned long mfn = pte_mfn(*pte);
++	int ret;
++	struct xen_memory_reservation reservation = {
++		.nr_extents   = 1,
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++	set_xen_guest_handle(reservation.extent_start, &mfn);
++	set_pte_at(&init_mm, addr, pte, __pte_ma(0));
++	set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
++	ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
++	BUG_ON(ret != 1);
++	return 0;
++}
++#endif
++
++struct page **alloc_empty_pages_and_pagevec(int nr_pages)
++{
++	unsigned long flags;
++	void *v;
++	struct page *page, **pagevec;
++	int i, ret;
++
++	pagevec = kmalloc(sizeof(page) * nr_pages, GFP_KERNEL);
++	if (pagevec == NULL)
++		return NULL;
++
++	for (i = 0; i < nr_pages; i++) {
++		balloon_lock(flags);
++		page = balloon_first_page();
++		if (page && !PageHighMem(page)) {
++			UNLIST_PAGE(page);
++			bs.balloon_low--;
++			balloon_unlock(flags);
++			pagevec[i] = page;
++			continue;
++		}
++		balloon_unlock(flags);
++
++		page = pagevec[i] = alloc_page(GFP_KERNEL|__GFP_COLD);
++		if (page == NULL)
++			goto err;
++
++		v = page_address(page);
++		scrub_pages(v, 1);
++
++		balloon_lock(flags);
++
++		if (xen_feature(XENFEAT_auto_translated_physmap)) {
++			unsigned long gmfn = page_to_pfn(page);
++			struct xen_memory_reservation reservation = {
++				.nr_extents   = 1,
++				.extent_order = 0,
++				.domid        = DOMID_SELF
++			};
++			set_xen_guest_handle(reservation.extent_start, &gmfn);
++			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++						   &reservation);
++			if (ret == 1)
++				ret = 0; /* success */
++		} else {
++#ifdef CONFIG_XEN
++			ret = apply_to_page_range(&init_mm, (unsigned long)v,
++						  PAGE_SIZE, dealloc_pte_fn,
++						  NULL);
++#else
++			/* Cannot handle non-auto translate mode. */
++			ret = 1;
++#endif
++		}
++
++		if (ret != 0) {
++			balloon_unlock(flags);
++			balloon_free_page(page);
++			goto err;
++		}
++
++		totalram_pages = --bs.current_pages;
++
++		balloon_unlock(flags);
++	}
++
++ out:
++	schedule_work(&balloon_worker);
++#ifdef CONFIG_XEN
++	flush_tlb_all();
++#endif
++	return pagevec;
++
++ err:
++	balloon_lock(flags);
++	while (--i >= 0)
++		balloon_append(pagevec[i]);
++	balloon_unlock(flags);
++	kfree(pagevec);
++	pagevec = NULL;
++	goto out;
++}
++
++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
++{
++	unsigned long flags;
++	int i;
++
++	if (pagevec == NULL)
++		return;
++
++	balloon_lock(flags);
++	for (i = 0; i < nr_pages; i++) {
++		BUG_ON(page_count(pagevec[i]) != 1);
++		balloon_append(pagevec[i]);
++	}
++	balloon_unlock(flags);
++
++	kfree(pagevec);
++
++	schedule_work(&balloon_worker);
++}
++
++void balloon_release_driver_page(struct page *page)
++{
++	unsigned long flags;
++
++	balloon_lock(flags);
++	balloon_append(page);
++	bs.driver_pages--;
++	balloon_unlock(flags);
++
++	schedule_work(&balloon_worker);
++}
++
++EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
++EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
++EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
++EXPORT_SYMBOL_GPL(balloon_release_driver_page);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/balloon/common.h	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,56 @@
++/******************************************************************************
++ * balloon/common.h
++ *
++ * 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_BALLOON_COMMON_H__
++#define __XEN_BALLOON_COMMON_H__
++
++#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
++
++struct balloon_stats {
++	/* We aim for 'current allocation' == 'target allocation'. */
++	unsigned long current_pages;
++	unsigned long target_pages;
++	/*
++	 * Drivers may alter the memory reservation independently, but they
++	 * must inform the balloon driver so we avoid hitting the hard limit.
++	 */
++	unsigned long driver_pages;
++	/* Number of pages in high- and low-memory balloons. */
++	unsigned long balloon_low;
++	unsigned long balloon_high;
++};
++
++extern struct balloon_stats balloon_stats;
++#define bs balloon_stats
++
++int balloon_sysfs_init(void);
++void balloon_sysfs_exit(void);
++
++void balloon_set_new_target(unsigned long target);
++
++#endif /* __XEN_BALLOON_COMMON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/balloon/sysfs.c	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,167 @@
++/******************************************************************************
++ * balloon/sysfs.c
++ *
++ * Xen balloon driver - sysfs interfaces.
++ * 
++ * 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/capability.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/stat.h>
++#include <linux/string.h>
++#include <linux/sysdev.h>
++#include "common.h"
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#define BALLOON_CLASS_NAME "xen_memory"
++
++#define BALLOON_SHOW(name, format, args...)			\
++	static ssize_t show_##name(struct sys_device *dev,	\
++				   char *buf)			\
++	{							\
++		return sprintf(buf, format, ##args);		\
++	}							\
++	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
++
++BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages));
++BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low));
++BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high));
++BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages));
++
++static ssize_t show_target_kb(struct sys_device *dev, char *buf)
++{
++	return sprintf(buf, "%lu\n", PAGES2KB(bs.target_pages));
++}
++
++static ssize_t store_target_kb(struct sys_device *dev,
++			       const char *buf,
++			       size_t count)
++{
++	char memstring[64], *endchar;
++	unsigned long long target_bytes;
++
++	if (!capable(CAP_SYS_ADMIN))
++		return -EPERM;
++	
++	if (count <= 1)
++		return -EBADMSG; /* runt */
++	if (count > sizeof(memstring))
++		return -EFBIG;   /* too long */
++	strcpy(memstring, buf);
++	
++	target_bytes = memparse(memstring, &endchar);
++	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
++	
++	return count;
++}
++
++static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
++		   show_target_kb, store_target_kb);
++
++static struct sysdev_attribute *balloon_attrs[] = {
++	&attr_target_kb,
++};
++
++static struct attribute *balloon_info_attrs[] = {
++	&attr_current_kb.attr,
++	&attr_low_kb.attr,
++	&attr_high_kb.attr,
++	&attr_driver_kb.attr,
++	NULL
++};
++
++static struct attribute_group balloon_info_group = {
++	.name = "info",
++	.attrs = balloon_info_attrs,
++};
++
++static struct sysdev_class balloon_sysdev_class = {
++	set_kset_name(BALLOON_CLASS_NAME),
++};
++
++static struct sys_device balloon_sysdev;
++
++static int __init register_balloon(struct sys_device *sysdev)
++{
++	int i, error;
++
++	error = sysdev_class_register(&balloon_sysdev_class);
++	if (error)
++		return error;
++
++	sysdev->id = 0;
++	sysdev->cls = &balloon_sysdev_class;
++
++	error = sysdev_register(sysdev);
++	if (error) {
++		sysdev_class_unregister(&balloon_sysdev_class);
++		return error;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
++		error = sysdev_create_file(sysdev, balloon_attrs[i]);
++		if (error)
++			goto fail;
++	}
++
++	error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
++	if (error)
++		goto fail;
++	
++	return 0;
++
++ fail:
++	while (--i >= 0)
++		sysdev_remove_file(sysdev, balloon_attrs[i]);
++	sysdev_unregister(sysdev);
++	sysdev_class_unregister(&balloon_sysdev_class);
++	return error;
++}
++
++static __exit void unregister_balloon(struct sys_device *sysdev)
++{
++	int i;
++
++	sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
++	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
++		sysdev_remove_file(sysdev, balloon_attrs[i]);
++	sysdev_unregister(sysdev);
++	sysdev_class_unregister(&balloon_sysdev_class);
++}
++
++int __init balloon_sysfs_init(void)
++{
++	return register_balloon(&balloon_sysdev);
++}
++
++void __exit balloon_sysfs_exit(void)
++{
++	unregister_balloon(&balloon_sysdev);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/Makefile	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,4 @@
++obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
++obj-$(CONFIG_XEN_BLKBACK_PAGEMAP) += blkback-pagemap.o
++
++blkbk-y	:= blkback.o xenbus.o interface.o vbd.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,700 @@
++/******************************************************************************
++ * arch/xen/drivers/blkif/backend/main.c
++ * 
++ * Back-end of the driver for virtual block devices. This portion of the
++ * driver exports a 'unified' block-device interface that can be accessed
++ * by any operating system that implements a compatible front end. A 
++ * reference front-end implementation can be found in:
++ *  arch/xen/drivers/blkif/frontend
++ * 
++ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
++ * Copyright (c) 2005, Christopher Clark
++ * 
++ * 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 "common.h"
++
++/*
++ * These are rather arbitrary. They are fairly large because adjacent requests
++ * pulled from a communication ring are quite likely to end up being part of
++ * the same scatter/gather request at the disc.
++ * 
++ * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW **
++ * 
++ * This will increase the chances of being able to write whole tracks.
++ * 64 should be enough to keep us competitive with Linux.
++ */
++static int blkif_reqs = 64;
++module_param_named(reqs, blkif_reqs, int, 0);
++MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate");
++
++/* Run-time switchable: /sys/module/blkback/parameters/ */
++static unsigned int log_stats = 0;
++static unsigned int debug_lvl = 0;
++module_param(log_stats, int, 0644);
++module_param(debug_lvl, int, 0644);
++
++/*
++ * Each outstanding request that we've passed to the lower device layers has a 
++ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
++ * the pendcnt towards zero. When it hits zero, the specified domain has a 
++ * response queued for it, with the saved 'id' passed back.
++ */
++typedef struct {
++	blkif_t       *blkif;
++	u64            id;
++	int            nr_pages;
++	atomic_t       pendcnt;
++	unsigned short operation;
++	int            status;
++	struct list_head free_list;
++} pending_req_t;
++
++static pending_req_t *pending_reqs;
++static struct list_head pending_free;
++static DEFINE_SPINLOCK(pending_free_lock);
++static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
++
++#define BLKBACK_INVALID_HANDLE (~0)
++
++static struct page **pending_pages;
++static grant_handle_t *pending_grant_handles;
++
++static inline int vaddr_pagenr(pending_req_t *req, int seg)
++{
++	return (req - pending_reqs) * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
++}
++
++#define pending_page(req, seg) pending_pages[vaddr_pagenr(req, seg)]
++
++static inline unsigned long vaddr(pending_req_t *req, int seg)
++{
++	unsigned long pfn = page_to_pfn(pending_page(req, seg));
++	return (unsigned long)pfn_to_kaddr(pfn);
++}
++
++#define pending_handle(_req, _seg) \
++	(pending_grant_handles[vaddr_pagenr(_req, _seg)])
++
++
++static int do_block_io_op(blkif_t *blkif);
++static int dispatch_rw_block_io(blkif_t *blkif,
++				 blkif_request_t *req,
++				 pending_req_t *pending_req);
++static void make_response(blkif_t *blkif, u64 id,
++			  unsigned short op, int st);
++
++/******************************************************************
++ * misc small helpers
++ */
++static pending_req_t* alloc_req(void)
++{
++	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 unplug_queue(blkif_t *blkif)
++{
++	if (blkif->plug == NULL)
++		return;
++	if (blkif->plug->unplug_fn)
++		blkif->plug->unplug_fn(blkif->plug);
++	blk_put_queue(blkif->plug);
++	blkif->plug = NULL;
++}
++
++static void plug_queue(blkif_t *blkif, struct block_device *bdev)
++{
++	request_queue_t *q = bdev_get_queue(bdev);
++
++	if (q == blkif->plug)
++		return;
++	unplug_queue(blkif);
++	blk_get_queue(q);
++	blkif->plug = q;
++}
++
++static void fast_flush_area(pending_req_t *req)
++{
++	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	unsigned int i, invcount = 0;
++	grant_handle_t handle;
++	int ret;
++
++	for (i = 0; i < req->nr_pages; i++) {
++		handle = pending_handle(req, i);
++		if (handle == BLKBACK_INVALID_HANDLE)
++			continue;
++		blkback_pagemap_clear(pending_page(req, i));
++		gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
++				    GNTMAP_host_map, handle);
++		pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
++		invcount++;
++	}
++
++	ret = HYPERVISOR_grant_table_op(
++		GNTTABOP_unmap_grant_ref, unmap, invcount);
++	BUG_ON(ret);
++}
++
++/******************************************************************
++ * SCHEDULER FUNCTIONS
++ */
++
++static void print_stats(blkif_t *blkif)
++{
++	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d  |  br %4d\n",
++	       current->comm, blkif->st_oo_req,
++	       blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req);
++	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
++	blkif->st_rd_req = 0;
++	blkif->st_wr_req = 0;
++	blkif->st_oo_req = 0;
++}
++
++int blkif_schedule(void *arg)
++{
++	blkif_t *blkif = arg;
++
++	blkif_get(blkif);
++
++	if (debug_lvl)
++		printk(KERN_DEBUG "%s: started\n", current->comm);
++
++	while (!kthread_should_stop()) {
++		if (try_to_freeze())
++			continue;
++
++		wait_event_interruptible(
++			blkif->wq,
++			blkif->waiting_reqs || kthread_should_stop());
++		wait_event_interruptible(
++			pending_free_wq,
++			!list_empty(&pending_free) || kthread_should_stop());
++
++		blkif->waiting_reqs = 0;
++		smp_mb(); /* clear flag *before* checking for work */
++
++		if (do_block_io_op(blkif))
++			blkif->waiting_reqs = 1;
++		unplug_queue(blkif);
++
++		if (log_stats && time_after(jiffies, blkif->st_print))
++			print_stats(blkif);
++	}
++
++	if (log_stats)
++		print_stats(blkif);
++	if (debug_lvl)
++		printk(KERN_DEBUG "%s: exiting\n", current->comm);
++
++	blkif->xenblkd = NULL;
++	blkif_put(blkif);
++
++	return 0;
++}
++
++/******************************************************************
++ * COMPLETION CALLBACK -- Called as bh->b_end_io()
++ */
++
++static void __end_block_io_op(pending_req_t *pending_req, int error)
++{
++	/* An error fails the entire request. */
++	if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) &&
++	    (error == -EOPNOTSUPP)) {
++		DPRINTK("blkback: write barrier op failed, not supported\n");
++		blkback_barrier(XBT_NIL, pending_req->blkif->be, 0);
++		pending_req->status = BLKIF_RSP_EOPNOTSUPP;
++	} else if (error) {
++		DPRINTK("Buffer not up-to-date at end of operation, "
++			"error=%d\n", error);
++		pending_req->status = BLKIF_RSP_ERROR;
++	}
++
++	if (atomic_dec_and_test(&pending_req->pendcnt)) {
++		fast_flush_area(pending_req);
++		make_response(pending_req->blkif, pending_req->id,
++			      pending_req->operation, pending_req->status);
++		blkif_put(pending_req->blkif);
++		free_req(pending_req);
++	}
++}
++
++static int end_block_io_op(struct bio *bio, unsigned int done, int error)
++{
++	if (bio->bi_size != 0)
++		return 1;
++	__end_block_io_op(bio->bi_private, error);
++	bio_put(bio);
++	return error;
++}
++
++
++/******************************************************************************
++ * NOTIFICATION FROM GUEST OS.
++ */
++
++static void blkif_notify_work(blkif_t *blkif)
++{
++	blkif->waiting_reqs = 1;
++	wake_up(&blkif->wq);
++}
++
++irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	blkif_notify_work(dev_id);
++	return IRQ_HANDLED;
++}
++
++
++
++/******************************************************************
++ * DOWNWARD CALLS -- These interface with the block-device layer proper.
++ */
++
++static int do_block_io_op(blkif_t *blkif)
++{
++	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
++	blkif_request_t req;
++	pending_req_t *pending_req;
++	RING_IDX rc, rp;
++	int more_to_do = 0, ret;
++
++	rc = blk_rings->common.req_cons;
++	rp = blk_rings->common.sring->req_prod;
++	rmb(); /* Ensure we see queued requests up to 'rp'. */
++
++	while ((rc != rp) || (blkif->is_suspended_req)) {
++
++		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
++			break;
++
++		if (kthread_should_stop()) {
++			more_to_do = 1;
++			break;
++		}
++
++		pending_req = alloc_req();
++		if (NULL == pending_req) {
++			blkif->st_oo_req++;
++			more_to_do = 1;
++			break;
++		}
++
++        /* Handle the suspended request first, if one exists */
++        if(blkif->is_suspended_req)
++        {
++            memcpy(&req, &blkif->suspended_req, sizeof(req));
++            blkif->is_suspended_req = 0;
++            goto handle_request;
++        }
++
++		switch (blkif->blk_protocol) {
++		case BLKIF_PROTOCOL_NATIVE:
++			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req));
++			break;
++		case BLKIF_PROTOCOL_X86_32:
++			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
++			break;
++		case BLKIF_PROTOCOL_X86_64:
++			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
++			break;
++		default:
++			BUG();
++		}
++		blk_rings->common.req_cons = ++rc; /* before make_response() */
++
++		/* Apply all sanity checks to /private copy/ of request. */
++		barrier();
++
++handle_request:
++        ret = 0;
++		switch (req.operation) {
++		case BLKIF_OP_READ:
++			blkif->st_rd_req++;
++			ret = dispatch_rw_block_io(blkif, &req, pending_req); 
++			break;
++		case BLKIF_OP_WRITE_BARRIER:
++			blkif->st_br_req++;
++			/* fall through */
++		case BLKIF_OP_WRITE:
++			blkif->st_wr_req++;
++			ret = dispatch_rw_block_io(blkif, &req, pending_req);
++			break;
++		default:
++			/* A good sign something is wrong: sleep for a while to
++			 * avoid excessive CPU consumption by a bad guest. */
++			msleep(1);
++			DPRINTK("error: unknown block io operation [%d]\n",
++				req.operation);
++			make_response(blkif, req.id, req.operation,
++				      BLKIF_RSP_ERROR);
++			free_req(pending_req);
++			break;
++		}
++        BUG_ON(ret != 0 && ret != -EAGAIN);
++        /* If we can't handle the request at the moment, save it, and break the
++         * loop */ 
++        if(ret == -EAGAIN)
++        {
++            memcpy(&blkif->suspended_req, &req, sizeof(req));
++            blkif->is_suspended_req = 1;
++            /* Return "no more work pending", restart will be handled 'out of
++             * band' */
++            return 0;
++        }
++
++		/* Yield point for this unbounded loop. */
++		cond_resched();
++	}
++
++	return more_to_do;
++}
++
++static int dispatch_rw_block_io(blkif_t *blkif,
++				 blkif_request_t *req,
++				 pending_req_t *pending_req)
++{
++	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
++	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	struct phys_req preq;
++	struct { 
++		unsigned long buf; unsigned int nsec;
++	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	unsigned int nseg;
++	struct bio *bio = NULL;
++	int ret, i;
++	int operation;
++
++	switch (req->operation) {
++	case BLKIF_OP_READ:
++		operation = READ;
++		break;
++	case BLKIF_OP_WRITE:
++		operation = WRITE;
++		break;
++	case BLKIF_OP_WRITE_BARRIER:
++		operation = WRITE_BARRIER;
++		break;
++	default:
++		operation = 0; /* make gcc happy */
++		BUG();
++	}
++
++	/* Check that number of segments is sane. */
++	nseg = req->nr_segments;
++	if (unlikely(nseg == 0 && operation != WRITE_BARRIER) || 
++	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
++		DPRINTK("Bad number of segments in request (%d)\n", nseg);
++		goto fail_response;
++	}
++
++	preq.dev           = req->handle;
++	preq.sector_number = req->sector_number;
++	preq.nr_sects      = 0;
++
++	pending_req->blkif     = blkif;
++	pending_req->id        = req->id;
++	pending_req->operation = req->operation;
++	pending_req->status    = BLKIF_RSP_OKAY;
++	pending_req->nr_pages  = nseg;
++
++	for (i = 0; i < nseg; i++) {
++		uint32_t flags;
++
++		seg[i].nsec = req->seg[i].last_sect -
++			req->seg[i].first_sect + 1;
++
++		if ((req->seg[i].last_sect >= (PAGE_SIZE >> 9)) ||
++		    (req->seg[i].last_sect < req->seg[i].first_sect))
++			goto fail_response;
++		preq.nr_sects += seg[i].nsec;
++
++		flags = GNTMAP_host_map;
++		if (operation != READ)
++			flags |= GNTMAP_readonly;
++		gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
++				  req->seg[i].gref, blkif->domid);
++	}
++
++	ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
++	BUG_ON(ret);
++
++#define GENERAL_ERR   (1<<0)
++#define EAGAIN_ERR    (1<<1)
++	for (i = 0; i < nseg; i++) {
++		if (unlikely(map[i].status != 0)) {
++			DPRINTK("invalid buffer -- could not remap it\n");
++			map[i].handle = BLKBACK_INVALID_HANDLE;
++			ret |= GENERAL_ERR;
++            if(map[i].status == GNTST_eagain)
++			    ret |= EAGAIN_ERR;
++		} else {
++			blkback_pagemap_set(vaddr_pagenr(pending_req, i),
++					    pending_page(pending_req, i),
++					    blkif->domid, req->handle,
++					    req->seg[i].gref);
++		}
++
++		pending_handle(pending_req, i) = map[i].handle;
++
++		if (ret)
++			continue;
++
++		set_phys_to_machine(
++			page_to_pfn(pending_page(pending_req, i)),
++			FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
++		seg[i].buf  = map[i].dev_bus_addr | 
++			(req->seg[i].first_sect << 9);
++	}
++
++    /* If any of grant maps failed with GNTST_eagain, suspend and retry later */
++    if(ret & EAGAIN_ERR)
++    {
++        fast_flush_area(pending_req);
++        free_req(pending_req);
++        return -EAGAIN;
++    }
++
++	if (ret)
++		goto fail_flush;
++
++	if (vbd_translate(&preq, blkif, operation) != 0) {
++		DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", 
++			operation == READ ? "read" : "write",
++			preq.sector_number,
++			preq.sector_number + preq.nr_sects, preq.dev);
++		goto fail_flush;
++	}
++
++	plug_queue(blkif, preq.bdev);
++	atomic_set(&pending_req->pendcnt, 1);
++	blkif_get(blkif);
++
++	for (i = 0; i < nseg; i++) {
++		if (((int)preq.sector_number|(int)seg[i].nsec) &
++		    ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
++			DPRINTK("Misaligned I/O request from domain %d",
++				blkif->domid);
++			goto fail_put_bio;
++		}
++
++		while ((bio == NULL) ||
++		       (bio_add_page(bio,
++				     pending_page(pending_req, i),
++				     seg[i].nsec << 9,
++				     seg[i].buf & ~PAGE_MASK) == 0)) {
++			if (bio) {
++				atomic_inc(&pending_req->pendcnt);
++				submit_bio(operation, bio);
++			}
++
++			bio = bio_alloc(GFP_KERNEL, nseg-i);
++			if (unlikely(bio == NULL))
++				goto fail_put_bio;
++
++			bio->bi_bdev    = preq.bdev;
++			bio->bi_private = pending_req;
++			bio->bi_end_io  = end_block_io_op;
++			bio->bi_sector  = preq.sector_number;
++		}
++
++		preq.sector_number += seg[i].nsec;
++	}
++
++	if (!bio) {
++		BUG_ON(operation != WRITE_BARRIER);
++		bio = bio_alloc(GFP_KERNEL, 0);
++		if (unlikely(bio == NULL))
++			goto fail_put_bio;
++
++		bio->bi_bdev    = preq.bdev;
++		bio->bi_private = pending_req;
++		bio->bi_end_io  = end_block_io_op;
++		bio->bi_sector  = -1;
++	}
++
++	submit_bio(operation, bio);
++
++	if (operation == READ)
++		blkif->st_rd_sect += preq.nr_sects;
++	else if (operation == WRITE || operation == WRITE_BARRIER)
++		blkif->st_wr_sect += preq.nr_sects;
++
++	return 0;
++
++ fail_flush:
++	fast_flush_area(pending_req);
++ fail_response:
++	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
++	free_req(pending_req);
++	msleep(1); /* back off a bit */
++	return 0;
++
++ fail_put_bio:
++	__end_block_io_op(pending_req, -EINVAL);
++	if (bio)
++		bio_put(bio);
++	unplug_queue(blkif);
++	msleep(1); /* back off a bit */
++	return 0;
++}
++
++
++
++/******************************************************************
++ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
++ */
++
++
++static void make_response(blkif_t *blkif, u64 id,
++			  unsigned short op, int st)
++{
++	blkif_response_t  resp;
++	unsigned long     flags;
++	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
++	int more_to_do = 0;
++	int notify;
++
++	resp.id        = id;
++	resp.operation = op;
++	resp.status    = st;
++
++	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
++	/* Place on the response ring for the relevant domain. */
++	switch (blkif->blk_protocol) {
++	case BLKIF_PROTOCOL_NATIVE:
++		memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	case BLKIF_PROTOCOL_X86_32:
++		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	case BLKIF_PROTOCOL_X86_64:
++		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	default:
++		BUG();
++	}
++	blk_rings->common.rsp_prod_pvt++;
++	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
++	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
++		/*
++		 * Tail check for pending requests. Allows frontend to avoid
++		 * notifications if requests are already in flight (lower
++		 * overheads and promotes batching).
++		 */
++		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
++
++	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
++		more_to_do = 1;
++	}
++
++	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
++
++	if (more_to_do)
++		blkif_notify_work(blkif);
++	if (notify)
++		notify_remote_via_irq(blkif->irq);
++}
++
++static int __init blkif_init(void)
++{
++	int i, mmap_pages;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST;
++
++	pending_reqs          = kmalloc(sizeof(pending_reqs[0]) *
++					blkif_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 (blkback_pagemap_init(mmap_pages))
++		goto out_of_memory;
++
++	if (!pending_reqs || !pending_grant_handles || !pending_pages)
++		goto out_of_memory;
++
++	for (i = 0; i < mmap_pages; i++)
++		pending_grant_handles[i] = BLKBACK_INVALID_HANDLE;
++
++	blkif_interface_init();
++
++	memset(pending_reqs, 0, sizeof(pending_reqs));
++	INIT_LIST_HEAD(&pending_free);
++
++	for (i = 0; i < blkif_reqs; i++)
++		list_add_tail(&pending_reqs[i].free_list, &pending_free);
++
++	blkif_xenbus_init();
++
++	return 0;
++
++ out_of_memory:
++	kfree(pending_reqs);
++	kfree(pending_grant_handles);
++	free_empty_pages_and_pagevec(pending_pages, mmap_pages);
++	printk("%s: out of memory\n", __FUNCTION__);
++	return -ENOMEM;
++}
++
++module_init(blkif_init);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/blkback-pagemap.c	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,96 @@
++#include <linux/module.h>
++#include "blkback-pagemap.h"
++
++static int blkback_pagemap_size;
++static struct blkback_pagemap *blkback_pagemap;
++
++static inline int
++blkback_pagemap_entry_clear(struct blkback_pagemap *map)
++{
++	static struct blkback_pagemap zero;
++	return !memcmp(map, &zero, sizeof(zero));
++}
++
++int
++blkback_pagemap_init(int pages)
++{
++	blkback_pagemap = kzalloc(pages * sizeof(struct blkback_pagemap),
++				  GFP_KERNEL);
++	if (!blkback_pagemap)
++		return -ENOMEM;
++
++	blkback_pagemap_size = pages;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(blkback_pagemap_init);
++
++void
++blkback_pagemap_set(int idx, struct page *page,
++		    domid_t domid, busid_t busid, grant_ref_t gref)
++{
++	struct blkback_pagemap *entry;
++
++	BUG_ON(!blkback_pagemap);
++	BUG_ON(idx >= blkback_pagemap_size);
++
++	SetPageBlkback(page);
++	set_page_private(page, idx);
++
++	entry = blkback_pagemap + idx;
++	if (!blkback_pagemap_entry_clear(entry)) {
++		printk("overwriting pagemap %d: d %u b %u g %u\n",
++		       idx, entry->domid, entry->busid, entry->gref);
++		BUG();
++	}
++
++	entry->domid = domid;
++	entry->busid = busid;
++	entry->gref  = gref;
++}
++EXPORT_SYMBOL_GPL(blkback_pagemap_set);
++
++void
++blkback_pagemap_clear(struct page *page)
++{
++	int idx;
++	struct blkback_pagemap *entry;
++
++	idx = (int)page_private(page);
++
++	BUG_ON(!blkback_pagemap);
++	BUG_ON(!PageBlkback(page));
++	BUG_ON(idx >= blkback_pagemap_size);
++
++	entry = blkback_pagemap + idx;
++	if (blkback_pagemap_entry_clear(entry)) {
++		printk("clearing empty pagemap %d\n", idx);
++		BUG();
++	}
++
++	memset(entry, 0, sizeof(*entry));
++}
++EXPORT_SYMBOL_GPL(blkback_pagemap_clear);
++
++struct blkback_pagemap
++blkback_pagemap_read(struct page *page)
++{
++	int idx;
++	struct blkback_pagemap *entry;
++
++	idx = (int)page_private(page);
++
++	BUG_ON(!blkback_pagemap);
++	BUG_ON(!PageBlkback(page));
++	BUG_ON(idx >= blkback_pagemap_size);
++
++	entry = blkback_pagemap + idx;
++	if (blkback_pagemap_entry_clear(entry)) {
++		printk("reading empty pagemap %d\n", idx);
++		BUG();
++	}
++
++	return *entry;
++}
++EXPORT_SYMBOL(blkback_pagemap_read);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/blkback-pagemap.h	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,37 @@
++#ifndef _BLKBACK_PAGEMAP_H_
++#define _BLKBACK_PAGEMAP_H_
++
++#include <linux/mm.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/grant_table.h>
++
++typedef unsigned int busid_t;
++
++struct blkback_pagemap {
++	domid_t          domid;
++	busid_t          busid;
++	grant_ref_t      gref;
++};
++
++#if defined(CONFIG_XEN_BLKBACK_PAGEMAP) || defined(CONFIG_XEN_BLKBACK_PAGEMAP_MODULE)
++
++int blkback_pagemap_init(int);
++void blkback_pagemap_set(int, struct page *, domid_t, busid_t, grant_ref_t);
++void blkback_pagemap_clear(struct page *);
++struct blkback_pagemap blkback_pagemap_read(struct page *);
++
++#else /* CONFIG_XEN_BLKBACK_PAGEMAP */
++
++static inline int blkback_pagemap_init(int pages) { return 0; }
++static inline void blkback_pagemap_set(int idx, struct page *page, domid_t dom,
++				       busid_t bus, grant_ref_t gnt) {}
++static inline void blkback_pagemap_clear(struct page *page) {}
++static inline struct blkback_pagemap blkback_pagemap_read(struct page *page)
++{
++	BUG();
++	return (struct blkback_pagemap){-1, -1, -1};
++}
++
++#endif /* CONFIG_XEN_BLKBACK_PAGEMAP */
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/common.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,143 @@
++/* 
++ * 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 __BLKIF__BACKEND__COMMON_H__
++#define __BLKIF__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <linux/wait.h>
++#include <asm/io.h>
++#include <asm/setup.h>
++#include <asm/pgalloc.h>
++#include <xen/evtchn.h>
++#include <asm/hypervisor.h>
++#include <xen/blkif.h>
++#include <xen/gnttab.h>
++#include <xen/driver_util.h>
++#include <xen/xenbus.h>
++#include "blkback-pagemap.h"
++
++
++#define DPRINTK(_f, _a...)			\
++	pr_debug("(file=%s, line=%d) " _f,	\
++		 __FILE__ , __LINE__ , ## _a )
++
++struct vbd {
++	blkif_vdev_t   handle;      /* what the domain refers to this vbd as */
++	unsigned char  readonly;    /* Non-zero -> read-only */
++	unsigned char  type;        /* VDISK_xxx */
++	u32            pdevice;     /* phys device that this vbd maps to */
++	struct block_device *bdev;
++};
++
++struct backend_info;
++
++typedef struct blkif_st {
++	/* Unique identifier for this interface. */
++	domid_t           domid;
++	unsigned int      handle;
++	/* Physical parameters of the comms window. */
++	unsigned int      irq;
++	/* Comms information. */
++	enum blkif_protocol blk_protocol;
++	blkif_back_rings_t blk_rings;
++	struct vm_struct *blk_ring_area;
++	/* The VBD attached to this interface. */
++	struct vbd        vbd;
++	/* Back pointer to the backend_info. */
++	struct backend_info *be;
++	/* Private fields. */
++	spinlock_t       blk_ring_lock;
++	atomic_t         refcnt;
++
++	wait_queue_head_t   wq;
++	struct task_struct  *xenblkd;
++	unsigned int        waiting_reqs;
++	request_queue_t     *plug;
++    int                 is_suspended_req;
++    blkif_request_t     suspended_req;
++
++	/* statistics */
++	unsigned long       st_print;
++	int                 st_rd_req;
++	int                 st_wr_req;
++	int                 st_oo_req;
++	int                 st_br_req;
++	int                 st_rd_sect;
++	int                 st_wr_sect;
++
++	wait_queue_head_t waiting_to_free;
++
++	grant_handle_t shmem_handle;
++	grant_ref_t    shmem_ref;
++} blkif_t;
++
++blkif_t *blkif_alloc(domid_t domid);
++void blkif_disconnect(blkif_t *blkif);
++void blkif_free(blkif_t *blkif);
++int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
++
++#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
++#define blkif_put(_b)					\
++	do {						\
++		if (atomic_dec_and_test(&(_b)->refcnt))	\
++			wake_up(&(_b)->waiting_to_free);\
++	} while (0)
++
++/* Create a vbd. */
++int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, unsigned major,
++	       unsigned minor, int readonly, int cdrom);
++void vbd_free(struct vbd *vbd);
++
++unsigned long long vbd_size(struct vbd *vbd);
++unsigned int vbd_info(struct vbd *vbd);
++unsigned long vbd_secsize(struct vbd *vbd);
++
++struct phys_req {
++	unsigned short       dev;
++	unsigned short       nr_sects;
++	struct block_device *bdev;
++	blkif_sector_t       sector_number;
++};
++
++int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
++
++void blkif_interface_init(void);
++
++void blkif_xenbus_init(void);
++
++irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++int blkif_schedule(void *arg);
++
++int blkback_barrier(struct xenbus_transaction xbt,
++		    struct backend_info *be, int state);
++
++#endif /* __BLKIF__BACKEND__COMMON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,185 @@
++/******************************************************************************
++ * arch/xen/drivers/blkif/backend/interface.c
++ * 
++ * Block-device interface management.
++ * 
++ * Copyright (c) 2004, Keir Fraser
++ * 
++ * 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 "common.h"
++#include <xen/evtchn.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++
++static kmem_cache_t *blkif_cachep;
++
++blkif_t *blkif_alloc(domid_t domid)
++{
++	blkif_t *blkif;
++
++	blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
++	if (!blkif)
++		return ERR_PTR(-ENOMEM);
++
++	memset(blkif, 0, sizeof(*blkif));
++	blkif->domid = domid;
++	spin_lock_init(&blkif->blk_ring_lock);
++	atomic_set(&blkif->refcnt, 1);
++	init_waitqueue_head(&blkif->wq);
++	blkif->st_print = jiffies;
++	init_waitqueue_head(&blkif->waiting_to_free);
++
++	return blkif;
++}
++
++static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
++{
++	struct gnttab_map_grant_ref op;
++
++	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
++			  GNTMAP_host_map, shared_page, blkif->domid);
++
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(100);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status) {
++		DPRINTK(" Grant table operation failure !\n");
++		return op.status;
++	}
++
++	blkif->shmem_ref = shared_page;
++	blkif->shmem_handle = op.handle;
++
++	return 0;
++}
++
++static void unmap_frontend_page(blkif_t *blkif)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
++			    GNTMAP_host_map, blkif->shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++}
++
++int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
++{
++	int err;
++
++	/* Already connected through? */
++	if (blkif->irq)
++		return 0;
++
++	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
++		return -ENOMEM;
++
++	err = map_frontend_page(blkif, shared_page);
++	if (err) {
++		free_vm_area(blkif->blk_ring_area);
++		return err;
++	}
++
++	switch (blkif->blk_protocol) {
++	case BLKIF_PROTOCOL_NATIVE:
++	{
++		blkif_sring_t *sring;
++		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
++		break;
++	}
++	case BLKIF_PROTOCOL_X86_32:
++	{
++		blkif_x86_32_sring_t *sring_x86_32;
++		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
++		break;
++	}
++	case BLKIF_PROTOCOL_X86_64:
++	{
++		blkif_x86_64_sring_t *sring_x86_64;
++		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
++		break;
++	}
++	default:
++		BUG();
++	}
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++		blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif);
++	if (err < 0)
++	{
++		unmap_frontend_page(blkif);
++		free_vm_area(blkif->blk_ring_area);
++		blkif->blk_rings.common.sring = NULL;
++		return err;
++	}
++	blkif->irq = err;
++
++	return 0;
++}
++
++void blkif_disconnect(blkif_t *blkif)
++{
++	if (blkif->xenblkd) {
++		kthread_stop(blkif->xenblkd);
++		blkif->xenblkd = NULL;
++	}
++
++	atomic_dec(&blkif->refcnt);
++	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
++	atomic_inc(&blkif->refcnt);
++
++	if (blkif->irq) {
++		unbind_from_irqhandler(blkif->irq, blkif);
++		blkif->irq = 0;
++	}
++
++	if (blkif->blk_rings.common.sring) {
++		unmap_frontend_page(blkif);
++		free_vm_area(blkif->blk_ring_area);
++		blkif->blk_rings.common.sring = NULL;
++	}
++}
++
++void blkif_free(blkif_t *blkif)
++{
++	if (!atomic_dec_and_test(&blkif->refcnt))
++		BUG();
++	kmem_cache_free(blkif_cachep, blkif);
++}
++
++void __init blkif_interface_init(void)
++{
++	blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
++					 0, 0, NULL, NULL);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/vbd.c	2009-05-19 09:16:41.000000000 +0200
+@@ -0,0 +1,118 @@
++/******************************************************************************
++ * blkback/vbd.c
++ * 
++ * Routines for managing virtual block devices (VBDs).
++ * 
++ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
++ * 
++ * 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 "common.h"
++
++#define vbd_sz(_v)   ((_v)->bdev->bd_part ?				\
++	(_v)->bdev->bd_part->nr_sects : get_capacity((_v)->bdev->bd_disk))
++
++unsigned long long vbd_size(struct vbd *vbd)
++{
++	return vbd_sz(vbd);
++}
++
++unsigned int vbd_info(struct vbd *vbd)
++{
++	return vbd->type | (vbd->readonly?VDISK_READONLY:0);
++}
++
++unsigned long vbd_secsize(struct vbd *vbd)
++{
++	return bdev_hardsect_size(vbd->bdev);
++}
++
++int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
++	       unsigned minor, int readonly, int cdrom)
++{
++	struct vbd *vbd;
++	struct block_device *bdev;
++
++	vbd = &blkif->vbd;
++	vbd->handle   = handle; 
++	vbd->readonly = readonly;
++	vbd->type     = 0;
++
++	vbd->pdevice  = MKDEV(major, minor);
++
++	bdev = open_by_devnum(vbd->pdevice,
++			      vbd->readonly ? FMODE_READ : FMODE_WRITE);
++
++	if (IS_ERR(bdev)) {
++		DPRINTK("vbd_creat: device %08x could not be opened.\n",
++			vbd->pdevice);
++		return -ENOENT;
++	}
++
++	vbd->bdev = bdev;
++
++	if (vbd->bdev->bd_disk == NULL) {
++		DPRINTK("vbd_creat: device %08x doesn't exist.\n",
++			vbd->pdevice);
++		vbd_free(vbd);
++		return -ENOENT;
++	}
++
++	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;
++
++	DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
++		handle, blkif->domid);
++	return 0;
++}
++
++void vbd_free(struct vbd *vbd)
++{
++	if (vbd->bdev)
++		blkdev_put(vbd->bdev);
++	vbd->bdev = NULL;
++}
++
++int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
++{
++	struct vbd *vbd = &blkif->vbd;
++	int rc = -EACCES;
++
++	if ((operation != READ) && vbd->readonly)
++		goto out;
++
++	if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
++		goto out;
++
++	req->dev  = vbd->pdevice;
++	req->bdev = vbd->bdev;
++	rc = 0;
++
++ out:
++	return rc;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkback/xenbus.c	2008-05-08 14:02:04.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
++
++    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 <stdarg.h>
++#include <linux/module.h>
++#include <linux/kthread.h>
++#include "common.h"
++
++#undef DPRINTK
++#define DPRINTK(fmt, args...)				\
++	pr_debug("blkback/xenbus (%s:%d) " fmt ".\n",	\
++		 __FUNCTION__, __LINE__, ##args)
++
++struct backend_info
++{
++	struct xenbus_device *dev;
++	blkif_t *blkif;
++	struct xenbus_watch backend_watch;
++	unsigned major;
++	unsigned minor;
++	char *mode;
++};
++
++static void connect(struct backend_info *);
++static int connect_ring(struct backend_info *);
++static void backend_changed(struct xenbus_watch *, const char **,
++			    unsigned int);
++
++static int blkback_name(blkif_t *blkif, char *buf)
++{
++	char *devpath, *devname;
++	struct xenbus_device *dev = blkif->be->dev;
++
++	devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
++	if (IS_ERR(devpath)) 
++		return PTR_ERR(devpath);
++	
++	if ((devname = strstr(devpath, "/dev/")) != NULL)
++		devname += strlen("/dev/");
++	else
++		devname  = devpath;
++
++	snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname);
++	kfree(devpath);
++	
++	return 0;
++}
++
++static void update_blkif_status(blkif_t *blkif)
++{ 
++	int err;
++	char name[TASK_COMM_LEN];
++
++	/* Not ready to connect? */
++	if (!blkif->irq || !blkif->vbd.bdev)
++		return;
++
++	/* Already connected? */
++	if (blkif->be->dev->state == XenbusStateConnected)
++		return;
++
++	/* Attempt to connect: exit if we fail to. */
++	connect(blkif->be);
++	if (blkif->be->dev->state != XenbusStateConnected)
++		return;
++
++	err = blkback_name(blkif, name);
++	if (err) {
++		xenbus_dev_error(blkif->be->dev, err, "get blkback dev name");
++		return;
++	}
++
++	blkif->xenblkd = kthread_run(blkif_schedule, blkif, name);
++	if (IS_ERR(blkif->xenblkd)) {
++		err = PTR_ERR(blkif->xenblkd);
++		blkif->xenblkd = NULL;
++		xenbus_dev_error(blkif->be->dev, err, "start xenblkd");
++	}
++}
++
++
++/****************************************************************
++ *  sysfs interface for VBD I/O requests
++ */
++
++#define VBD_SHOW(name, format, args...)					\
++	static ssize_t show_##name(struct device *_dev,			\
++				   struct device_attribute *attr,	\
++				   char *buf)				\
++	{								\
++		struct xenbus_device *dev = to_xenbus_device(_dev);	\
++		struct backend_info *be = dev->dev.driver_data;		\
++									\
++		return sprintf(buf, format, ##args);			\
++	}								\
++	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
++
++VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
++VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
++VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
++VBD_SHOW(br_req,  "%d\n", be->blkif->st_br_req);
++VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
++VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
++
++static struct attribute *vbdstat_attrs[] = {
++	&dev_attr_oo_req.attr,
++	&dev_attr_rd_req.attr,
++	&dev_attr_wr_req.attr,
++	&dev_attr_br_req.attr,
++	&dev_attr_rd_sect.attr,
++	&dev_attr_wr_sect.attr,
++	NULL
++};
++
++static struct attribute_group vbdstat_group = {
++	.name = "statistics",
++	.attrs = vbdstat_attrs,
++};
++
++VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
++VBD_SHOW(mode, "%s\n", be->mode);
++
++int xenvbd_sysfs_addif(struct xenbus_device *dev)
++{
++	int error;
++	
++	error = device_create_file(&dev->dev, &dev_attr_physical_device);
++ 	if (error)
++		goto fail1;
++
++	error = device_create_file(&dev->dev, &dev_attr_mode);
++	if (error)
++		goto fail2;
++
++	error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group);
++	if (error)
++		goto fail3;
++
++	return 0;
++
++fail3:	sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
++fail2:	device_remove_file(&dev->dev, &dev_attr_mode);
++fail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);
++	return error;
++}
++
++void xenvbd_sysfs_delif(struct xenbus_device *dev)
++{
++	sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
++	device_remove_file(&dev->dev, &dev_attr_mode);
++	device_remove_file(&dev->dev, &dev_attr_physical_device);
++}
++
++static int blkback_remove(struct xenbus_device *dev)
++{
++	struct backend_info *be = dev->dev.driver_data;
++
++	DPRINTK("");
++
++	if (be->major || be->minor)
++		xenvbd_sysfs_delif(dev);
++
++	if (be->backend_watch.node) {
++		unregister_xenbus_watch(&be->backend_watch);
++		kfree(be->backend_watch.node);
++		be->backend_watch.node = NULL;
++	}
++
++	if (be->blkif) {
++		blkif_disconnect(be->blkif);
++		vbd_free(&be->blkif->vbd);
++		blkif_free(be->blkif);
++		be->blkif = NULL;
++	}
++
++	kfree(be);
++	dev->dev.driver_data = NULL;
++	return 0;
++}
++
++int blkback_barrier(struct xenbus_transaction xbt,
++		    struct backend_info *be, int state)
++{
++	struct xenbus_device *dev = be->dev;
++	int err;
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
++			    "%d", state);
++	if (err)
++		xenbus_dev_fatal(dev, err, "writing feature-barrier");
++
++	return err;
++}
++
++/**
++ * Entry point to this code when a new device is created.  Allocate the basic
++ * structures, and watch the store waiting for the hotplug scripts to tell us
++ * the device's physical major and minor numbers.  Switch to InitWait.
++ */
++static int blkback_probe(struct xenbus_device *dev,
++			 const struct xenbus_device_id *id)
++{
++	int err;
++	struct backend_info *be = kzalloc(sizeof(struct backend_info),
++					  GFP_KERNEL);
++	if (!be) {
++		xenbus_dev_fatal(dev, -ENOMEM,
++				 "allocating backend structure");
++		return -ENOMEM;
++	}
++	be->dev = dev;
++	dev->dev.driver_data = be;
++
++	be->blkif = blkif_alloc(dev->otherend_id);
++	if (IS_ERR(be->blkif)) {
++		err = PTR_ERR(be->blkif);
++		be->blkif = NULL;
++		xenbus_dev_fatal(dev, err, "creating block interface");
++		goto fail;
++	}
++
++	/* setup back pointer */
++	be->blkif->be = be;
++
++	err = xenbus_watch_path2(dev, dev->nodename, "physical-device",
++				 &be->backend_watch, backend_changed);
++	if (err)
++		goto fail;
++
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err)
++		goto fail;
++
++	return 0;
++
++fail:
++	DPRINTK("failed");
++	blkback_remove(dev);
++	return err;
++}
++
++
++/**
++ * Callback received when the hotplug scripts have placed the physical-device
++ * node.  Read it and the mode node, and create a vbd.  If the frontend is
++ * ready, connect.
++ */
++static void backend_changed(struct xenbus_watch *watch,
++			    const char **vec, unsigned int len)
++{
++	int err;
++	unsigned major;
++	unsigned minor;
++	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("");
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x",
++			   &major, &minor);
++	if (XENBUS_EXIST_ERR(err)) {
++		/* Since this watch will fire once immediately after it is
++		   registered, we expect this.  Ignore it, and wait for the
++		   hotplug scripts. */
++		return;
++	}
++	if (err != 2) {
++		xenbus_dev_fatal(dev, err, "reading physical-device");
++		return;
++	}
++
++	if ((be->major || be->minor) &&
++	    ((be->major != major) || (be->minor != minor))) {
++		printk(KERN_WARNING
++		       "blkback: changing physical device (from %x:%x to "
++		       "%x:%x) not supported.\n", be->major, be->minor,
++		       major, minor);
++		return;
++	}
++
++	be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
++	if (IS_ERR(be->mode)) {
++		err = PTR_ERR(be->mode);
++		be->mode = NULL;
++		xenbus_dev_fatal(dev, err, "reading mode");
++		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. */
++
++		char *p = strrchr(dev->otherend, '/') + 1;
++		long handle = simple_strtoul(p, NULL, 0);
++
++		be->major = major;
++		be->minor = minor;
++
++		err = vbd_create(be->blkif, handle, major, minor,
++				 (NULL == strchr(be->mode, 'w')), cdrom);
++		if (err) {
++			be->major = be->minor = 0;
++			xenbus_dev_fatal(dev, err, "creating vbd structure");
++			return;
++		}
++
++		err = xenvbd_sysfs_addif(dev);
++		if (err) {
++			vbd_free(&be->blkif->vbd);
++			be->major = be->minor = 0;
++			xenbus_dev_fatal(dev, err, "creating sysfs entries");
++			return;
++		}
++
++		/* We're potentially connected now */
++		update_blkif_status(be->blkif);
++	}
++}
++
++
++/**
++ * Callback received when the frontend's state changes.
++ */
++static void frontend_changed(struct xenbus_device *dev,
++			     enum xenbus_state frontend_state)
++{
++	struct backend_info *be = dev->dev.driver_data;
++	int err;
++
++	DPRINTK("%s", xenbus_strstate(frontend_state));
++
++	switch (frontend_state) {
++	case XenbusStateInitialising:
++		if (dev->state == XenbusStateClosed) {
++			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
++			       __FUNCTION__, dev->nodename);
++			xenbus_switch_state(dev, XenbusStateInitWait);
++		}
++		break;
++
++	case XenbusStateInitialised:
++	case XenbusStateConnected:
++		/* Ensure we connect even when two watches fire in 
++		   close successsion and we miss the intermediate value 
++		   of frontend_state. */
++		if (dev->state == XenbusStateConnected)
++			break;
++
++		err = connect_ring(be);
++		if (err)
++			break;
++		update_blkif_status(be->blkif);
++		break;
++
++	case XenbusStateClosing:
++		blkif_disconnect(be->blkif);
++		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;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++				 frontend_state);
++		break;
++	}
++}
++
++
++/* ** Connection ** */
++
++
++/**
++ * Write the physical details regarding the block device to the store, and
++ * switch to Connected state.
++ */
++static void connect(struct backend_info *be)
++{
++	struct xenbus_transaction xbt;
++	int err;
++	struct xenbus_device *dev = be->dev;
++
++	DPRINTK("%s", dev->otherend);
++
++	/* Supply the information about the device the frontend needs */
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		return;
++	}
++
++	err = blkback_barrier(xbt, be, 1);
++	if (err)
++		goto abort;
++
++	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
++			    vbd_size(&be->blkif->vbd));
++	if (err) {
++		xenbus_dev_fatal(dev, err, "writing %s/sectors",
++				 dev->nodename);
++		goto abort;
++	}
++
++	/* FIXME: use a typename instead */
++	err = xenbus_printf(xbt, dev->nodename, "info", "%u",
++			    vbd_info(&be->blkif->vbd));
++	if (err) {
++		xenbus_dev_fatal(dev, err, "writing %s/info",
++				 dev->nodename);
++		goto abort;
++	}
++	err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu",
++			    vbd_secsize(&be->blkif->vbd));
++	if (err) {
++		xenbus_dev_fatal(dev, err, "writing %s/sector-size",
++				 dev->nodename);
++		goto abort;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++	if (err)
++		xenbus_dev_fatal(dev, err, "ending transaction");
++
++	err = xenbus_switch_state(dev, XenbusStateConnected);
++	if (err)
++		xenbus_dev_fatal(dev, err, "switching to Connected state",
++				 dev->nodename);
++
++	return;
++ abort:
++	xenbus_transaction_end(xbt, 1);
++}
++
++
++static int connect_ring(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	unsigned long ring_ref;
++	unsigned int evtchn;
++	char protocol[64] = "";
++	int err;
++
++	DPRINTK("%s", dev->otherend);
++
++	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-ref and event-channel",
++				 dev->otherend);
++		return err;
++	}
++
++	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
++	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
++			    "%63s", protocol, NULL);
++	if (err)
++		strcpy(protocol, "unspecified, assuming native");
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++	else {
++		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
++		return -1;
++	}
++	printk(KERN_INFO
++	       "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
++	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
++
++	/* Map the shared frame, irq etc. */
++	err = blkif_map(be->blkif, ring_ref, evtchn);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
++				 ring_ref, evtchn);
++		return err;
++	}
++
++	return 0;
++}
++
++
++/* ** Driver Registration ** */
++
++
++static const struct xenbus_device_id blkback_ids[] = {
++	{ "vbd" },
++	{ "" }
++};
++
++
++static struct xenbus_driver blkback = {
++	.name = "vbd",
++	.owner = THIS_MODULE,
++	.ids = blkback_ids,
++	.probe = blkback_probe,
++	.remove = blkback_remove,
++	.otherend_changed = frontend_changed
++};
++
++
++void blkif_xenbus_init(void)
++{
++	xenbus_register_backend(&blkback);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkfront/Makefile	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,5 @@
++
++obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	:= xenblk.o
++
++xenblk-objs := blkfront.o vbd.o
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,940 @@
++/******************************************************************************
++ * blkfront.c
++ * 
++ * XenLinux virtual block-device driver.
++ * 
++ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
++ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
++ * Copyright (c) 2004, Christian Limpach
++ * Copyright (c) 2004, Andrew Warfield
++ * Copyright (c) 2005, Christopher Clark
++ * Copyright (c) 2005, XenSource Ltd
++ * 
++ * 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 "block.h"
++#include <linux/cdrom.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/scatterlist.h>
++#include <scsi/scsi.h>
++#include <xen/evtchn.h>
++#include <xen/xenbus.h>
++#include <xen/interface/grant_table.h>
++#include <xen/interface/io/protocols.h>
++#include <xen/gnttab.h>
++#include <asm/hypervisor.h>
++#include <asm/maddr.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#define BLKIF_STATE_DISCONNECTED 0
++#define BLKIF_STATE_CONNECTED    1
++#define BLKIF_STATE_SUSPENDED    2
++
++#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
++    (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLK_RING_SIZE)
++#define GRANT_INVALID_REF	0
++
++static void connect(struct blkfront_info *);
++static void blkfront_closing(struct xenbus_device *);
++static int blkfront_remove(struct xenbus_device *);
++static int talk_to_backend(struct xenbus_device *, struct blkfront_info *);
++static int setup_blkring(struct xenbus_device *, struct blkfront_info *);
++
++static void kick_pending_request_queues(struct blkfront_info *);
++
++static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs);
++static void blkif_restart_queue(void *arg);
++static void blkif_recover(struct blkfront_info *);
++static void blkif_completion(struct blk_shadow *);
++static void blkif_free(struct blkfront_info *, int);
++
++
++/**
++ * Entry point to this code when a new device is created.  Allocate the basic
++ * structures and the ring buffer for communication with the backend, and
++ * inform the backend of the appropriate details for those.  Switch to
++ * Initialised state.
++ */
++static int blkfront_probe(struct xenbus_device *dev,
++			  const struct xenbus_device_id *id)
++{
++	int err, vdevice, i;
++	struct blkfront_info *info;
++
++	/* FIXME: Use dynamic device id if this is not set. */
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++			   "virtual-device", "%i", &vdevice);
++	if (err != 1) {
++		/* 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);
++	if (!info) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++		return -ENOMEM;
++	}
++
++	info->xbdev = dev;
++	info->vdevice = vdevice;
++	info->connected = BLKIF_STATE_DISCONNECTED;
++	INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
++
++	for (i = 0; i < BLK_RING_SIZE; i++)
++		info->shadow[i].req.id = i+1;
++	info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
++
++	/* Front end dir is a number, which is used as the id. */
++	info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
++	dev->dev.driver_data = info;
++
++	err = talk_to_backend(dev, info);
++	if (err) {
++		kfree(info);
++		dev->dev.driver_data = NULL;
++		return err;
++	}
++
++	return 0;
++}
++
++
++/**
++ * We are reconnecting to the backend, due to a suspend/resume, or a backend
++ * driver restart.  We tear down our blkif structure and recreate it, but
++ * leave the device-layer structures intact so that this is transparent to the
++ * rest of the kernel.
++ */
++static int blkfront_resume(struct xenbus_device *dev)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++	int err;
++
++	DPRINTK("blkfront_resume: %s\n", dev->nodename);
++
++	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
++
++	err = talk_to_backend(dev, info);
++	if (info->connected == BLKIF_STATE_SUSPENDED && !err)
++		blkif_recover(info);
++
++	return err;
++}
++
++
++/* Common code used when first setting up, and when resuming. */
++static int talk_to_backend(struct xenbus_device *dev,
++			   struct blkfront_info *info)
++{
++	const char *message = NULL;
++	struct xenbus_transaction xbt;
++	int err;
++
++	/* Create shared ring, alloc event channel. */
++	err = setup_blkring(dev, info);
++	if (err)
++		goto out;
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		goto destroy_blkring;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename,
++			    "ring-ref","%u", info->ring_ref);
++	if (err) {
++		message = "writing ring-ref";
++		goto abort_transaction;
++	}
++	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    irq_to_evtchn_port(info->irq));
++	if (err) {
++		message = "writing event-channel";
++		goto abort_transaction;
++	}
++	err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++			    XEN_IO_PROTO_ABI_NATIVE);
++	if (err) {
++		message = "writing protocol";
++		goto abort_transaction;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err) {
++		if (err == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, err, "completing transaction");
++		goto destroy_blkring;
++	}
++
++	xenbus_switch_state(dev, XenbusStateInitialised);
++
++	return 0;
++
++ abort_transaction:
++	xenbus_transaction_end(xbt, 1);
++	if (message)
++		xenbus_dev_fatal(dev, err, "%s", message);
++ destroy_blkring:
++	blkif_free(info, 0);
++ out:
++	return err;
++}
++
++
++static int setup_blkring(struct xenbus_device *dev,
++			 struct blkfront_info *info)
++{
++	blkif_sring_t *sring;
++	int err;
++
++	info->ring_ref = GRANT_INVALID_REF;
++
++	sring = (blkif_sring_t *)__get_free_page(GFP_NOIO | __GFP_HIGH);
++	if (!sring) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
++		return -ENOMEM;
++	}
++	SHARED_RING_INIT(sring);
++	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
++
++	memset(info->sg, 0, sizeof(info->sg));
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
++	if (err < 0) {
++		free_page((unsigned long)sring);
++		info->ring.sring = NULL;
++		goto fail;
++	}
++	info->ring_ref = err;
++
++	err = bind_listening_port_to_irqhandler(
++		dev->otherend_id, blkif_int, SA_SAMPLE_RANDOM, "blkif", info);
++	if (err <= 0) {
++		xenbus_dev_fatal(dev, err,
++				 "bind_listening_port_to_irqhandler");
++		goto fail;
++	}
++	info->irq = err;
++
++	return 0;
++fail:
++	blkif_free(info, 0);
++	return err;
++}
++
++
++/**
++ * Callback received when the backend's state changes.
++ */
++static void backend_changed(struct xenbus_device *dev,
++			    enum xenbus_state backend_state)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++	struct block_device *bd;
++
++	DPRINTK("blkfront:backend_changed.\n");
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitWait:
++	case XenbusStateInitialised:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateConnected:
++		connect(info);
++		break;
++
++	case XenbusStateClosing:
++		bd = bdget(info->dev);
++		if (bd == NULL)
++			xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
++		down(&bd->bd_sem);
++#else
++		mutex_lock(&bd->bd_mutex);
++#endif
++		if (info->users > 0)
++			xenbus_dev_error(dev, -EBUSY,
++					 "Device in use; refusing to close");
++		else
++			blkfront_closing(dev);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
++		up(&bd->bd_sem);
++#else
++		mutex_unlock(&bd->bd_mutex);
++#endif
++		bdput(bd);
++		break;
++	}
++}
++
++
++/* ** Connection ** */
++
++
++/*
++ * Invoked when the backend is finally 'ready' (and has told produced
++ * the details about the physical device - #sectors, size, etc).
++ */
++static void connect(struct blkfront_info *info)
++{
++	unsigned long long sectors;
++	unsigned long sector_size;
++	unsigned int binfo;
++	int err;
++
++	if ((info->connected == BLKIF_STATE_CONNECTED) ||
++	    (info->connected == BLKIF_STATE_SUSPENDED) )
++		return;
++
++	DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend);
++
++	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
++			    "sectors", "%Lu", &sectors,
++			    "info", "%u", &binfo,
++			    "sector-size", "%lu", &sector_size,
++			    NULL);
++	if (err) {
++		xenbus_dev_fatal(info->xbdev, err,
++				 "reading backend fields at %s",
++				 info->xbdev->otherend);
++		return;
++	}
++
++	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
++			    "feature-barrier", "%lu", &info->feature_barrier,
++			    NULL);
++	if (err)
++		info->feature_barrier = 0;
++
++	err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
++	if (err) {
++		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
++				 info->xbdev->otherend);
++		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. */
++	spin_lock_irq(&blkif_io_lock);
++	info->connected = BLKIF_STATE_CONNECTED;
++	kick_pending_request_queues(info);
++	spin_unlock_irq(&blkif_io_lock);
++
++	add_disk(info->gd);
++
++	info->is_ready = 1;
++}
++
++/**
++ * Handle the change of state of the backend to Closing.  We must delete our
++ * device-layer structures now, to ensure that writes are flushed through to
++ * the backend.  Once is this done, we can switch to Closed in
++ * acknowledgement.
++ */
++static void blkfront_closing(struct xenbus_device *dev)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++	unsigned long flags;
++
++	DPRINTK("blkfront_closing: %s removed\n", dev->nodename);
++
++	if (info->rq == NULL)
++		goto out;
++
++	spin_lock_irqsave(&blkif_io_lock, flags);
++	/* No more blkif_request(). */
++	blk_stop_queue(info->rq);
++	/* No more gnttab callback work. */
++	gnttab_cancel_free_callback(&info->callback);
++	spin_unlock_irqrestore(&blkif_io_lock, flags);
++
++	/* Flush gnttab callback work. Must be done with no locks held. */
++	flush_scheduled_work();
++
++	xlvbd_sysfs_delif(info);
++
++	xlvbd_del(info);
++
++ out:
++	xenbus_frontend_closed(dev);
++}
++
++
++static int blkfront_remove(struct xenbus_device *dev)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++
++	DPRINTK("blkfront_remove: %s removed\n", dev->nodename);
++
++	blkif_free(info, 0);
++
++	if(info->users == 0)
++		kfree(info);
++	else
++		info->is_ready = -1;
++
++	return 0;
++}
++
++
++static inline int GET_ID_FROM_FREELIST(
++	struct blkfront_info *info)
++{
++	unsigned long free = info->shadow_free;
++	BUG_ON(free >= BLK_RING_SIZE);
++	info->shadow_free = info->shadow[free].req.id;
++	info->shadow[free].req.id = 0x0fffffee; /* debug */
++	return free;
++}
++
++static inline void ADD_ID_TO_FREELIST(
++	struct blkfront_info *info, unsigned long id)
++{
++	info->shadow[id].req.id  = info->shadow_free;
++	info->shadow[id].request = 0;
++	info->shadow_free = id;
++}
++
++static inline void flush_requests(struct blkfront_info *info)
++{
++	int notify;
++
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);
++
++	if (notify)
++		notify_remote_via_irq(info->irq);
++}
++
++static void kick_pending_request_queues(struct blkfront_info *info)
++{
++	if (!RING_FULL(&info->ring)) {
++		/* Re-enable calldowns. */
++		blk_start_queue(info->rq);
++		/* Kick things off immediately. */
++		do_blkif_request(info->rq);
++	}
++}
++
++static void blkif_restart_queue(void *arg)
++{
++	struct blkfront_info *info = (struct blkfront_info *)arg;
++	spin_lock_irq(&blkif_io_lock);
++	if (info->connected == BLKIF_STATE_CONNECTED)
++		kick_pending_request_queues(info);
++	spin_unlock_irq(&blkif_io_lock);
++}
++
++static void blkif_restart_queue_callback(void *arg)
++{
++	struct blkfront_info *info = (struct blkfront_info *)arg;
++	schedule_work(&info->work);
++}
++
++int blkif_open(struct inode *inode, struct file *filep)
++{
++	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
++
++	if(info->is_ready < 0)
++		return -ENODEV;
++	info->users++;
++	return 0;
++}
++
++
++int blkif_release(struct inode *inode, struct file *filep)
++{
++	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
++	info->users--;
++	if (info->users == 0) {
++		/* Check whether we have been instructed to close.  We will
++		   have ignored this request initially, as the device was
++		   still mounted. */
++		struct xenbus_device * dev = info->xbdev;
++		enum xenbus_state state = xenbus_read_driver_state(dev->otherend);
++
++		if(info->is_ready < 0) {
++			blkfront_closing(dev);
++			kfree(info);
++		} else if (state == XenbusStateClosing && info->is_ready)
++			blkfront_closing(dev);
++	}
++	return 0;
++}
++
++
++int blkif_ioctl(struct inode *inode, struct file *filep,
++		unsigned command, unsigned long argument)
++{
++	int i;
++
++	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
++		      command, (long)argument, inode->i_rdev);
++
++	switch (command) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++	case HDIO_GETGEO: {
++		struct block_device *bd = inode->i_bdev;
++		struct hd_geometry geo;
++		int ret;
++
++                if (!argument)
++                        return -EINVAL;
++
++		geo.start = get_start_sect(bd);
++		ret = blkif_getgeo(bd, &geo);
++		if (ret)
++			return ret;
++
++		if (copy_to_user((struct hd_geometry __user *)argument, &geo,
++				 sizeof(geo)))
++                        return -EFAULT;
++
++                return 0;
++	}
++#endif
++	case CDROMMULTISESSION:
++		DPRINTK("FIXME: support multisession CDs later\n");
++		for (i = 0; i < sizeof(struct cdrom_multisession); i++)
++			if (put_user(0, (char __user *)(argument + i)))
++				return -EFAULT;
++		return 0;
++
++	case CDROM_GET_CAPABILITY: {
++		struct blkfront_info *info =
++			inode->i_bdev->bd_disk->private_data;
++		struct gendisk *gd = info->gd;
++		if (gd->flags & GENHD_FL_CD)
++			return 0;
++		return -EINVAL;
++	}
++	default:
++		/*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
++		  command);*/
++		return -EINVAL; /* same return as native Linux */
++	}
++
++	return 0;
++}
++
++
++int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
++{
++	/* We don't have real geometry info, but let's at least return
++	   values consistent with the size of the device */
++	sector_t nsect = get_capacity(bd->bd_disk);
++	sector_t cylinders = nsect;
++
++	hg->heads = 0xff;
++	hg->sectors = 0x3f;
++	sector_div(cylinders, hg->heads * hg->sectors);
++	hg->cylinders = cylinders;
++	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
++		hg->cylinders = 0xffff;
++	return 0;
++}
++
++
++/*
++ * blkif_queue_request
++ *
++ * request block io
++ *
++ * id: for guest use only.
++ * operation: BLKIF_OP_{READ,WRITE,PROBE}
++ * buffer: buffer to read/write into. this should be a
++ *   virtual address in the guest os.
++ */
++static int blkif_queue_request(struct request *req)
++{
++	struct blkfront_info *info = req->rq_disk->private_data;
++	unsigned long buffer_mfn;
++	blkif_request_t *ring_req;
++	unsigned long id;
++	unsigned int fsect, lsect;
++	int i, ref;
++	grant_ref_t gref_head;
++	struct scatterlist *sg;
++
++	if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
++		return 1;
++
++	if (gnttab_alloc_grant_references(
++		BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) {
++		gnttab_request_free_callback(
++			&info->callback,
++			blkif_restart_queue_callback,
++			info,
++			BLKIF_MAX_SEGMENTS_PER_REQUEST);
++		return 1;
++	}
++
++	/* Fill out a communications ring structure. */
++	ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
++	id = GET_ID_FROM_FREELIST(info);
++	info->shadow[id].request = (unsigned long)req;
++
++	ring_req->id = id;
++	ring_req->sector_number = (blkif_sector_t)req->sector;
++	ring_req->handle = info->handle;
++
++	ring_req->operation = rq_data_dir(req) ?
++		BLKIF_OP_WRITE : BLKIF_OP_READ;
++	if (blk_barrier_rq(req))
++		ring_req->operation = BLKIF_OP_WRITE_BARRIER;
++
++	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
++	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
++	for (i = 0; i < ring_req->nr_segments; ++i) {
++			sg = info->sg + i;
++			buffer_mfn = page_to_phys(sg->page) >> PAGE_SHIFT;
++			fsect = sg->offset >> 9;
++			lsect = fsect + (sg->length >> 9) - 1;
++			/* install a grant reference. */
++			ref = gnttab_claim_grant_reference(&gref_head);
++			BUG_ON(ref == -ENOSPC);
++
++			gnttab_grant_foreign_access_ref(
++				ref,
++				info->xbdev->otherend_id,
++				buffer_mfn,
++				rq_data_dir(req) ? GTF_readonly : 0 );
++
++			info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
++			ring_req->seg[i] =
++				(struct blkif_request_segment) {
++					.gref       = ref,
++					.first_sect = fsect,
++					.last_sect  = lsect };
++	}
++
++	info->ring.req_prod_pvt++;
++
++	/* Keep a private copy so we can reissue requests when recovering. */
++	info->shadow[id].req = *ring_req;
++
++	gnttab_free_grant_references(gref_head);
++
++	return 0;
++}
++
++/*
++ * do_blkif_request
++ *  read a block; request is in a request queue
++ */
++void do_blkif_request(request_queue_t *rq)
++{
++	struct blkfront_info *info = NULL;
++	struct request *req;
++	int queued;
++
++	DPRINTK("Entered do_blkif_request\n");
++
++	queued = 0;
++
++	while ((req = elv_next_request(rq)) != NULL) {
++		info = req->rq_disk->private_data;
++		if (!blk_fs_request(req)) {
++			end_request(req, 0);
++			continue;
++		}
++
++		if (RING_FULL(&info->ring))
++			goto wait;
++
++		DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
++			"(%u/%li) buffer:%p [%s]\n",
++			req, req->cmd, (long long)req->sector,
++			req->current_nr_sectors,
++			req->nr_sectors, req->buffer,
++			rq_data_dir(req) ? "write" : "read");
++
++
++		blkdev_dequeue_request(req);
++		if (blkif_queue_request(req)) {
++			blk_requeue_request(rq, req);
++		wait:
++			/* Avoid pointless unplugs. */
++			blk_stop_queue(rq);
++			break;
++		}
++
++		queued++;
++	}
++
++	if (queued != 0)
++		flush_requests(info);
++}
++
++
++static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
++{
++	struct request *req;
++	blkif_response_t *bret;
++	RING_IDX i, rp;
++	unsigned long flags;
++	struct blkfront_info *info = (struct blkfront_info *)dev_id;
++	int uptodate;
++
++	spin_lock_irqsave(&blkif_io_lock, flags);
++
++	if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
++		spin_unlock_irqrestore(&blkif_io_lock, flags);
++		return IRQ_HANDLED;
++	}
++
++ again:
++	rp = info->ring.sring->rsp_prod;
++	rmb(); /* Ensure we see queued responses up to 'rp'. */
++
++	for (i = info->ring.rsp_cons; i != rp; i++) {
++		unsigned long id;
++		int ret;
++
++		bret = RING_GET_RESPONSE(&info->ring, i);
++		id   = bret->id;
++		req  = (struct request *)info->shadow[id].request;
++
++		blkif_completion(&info->shadow[id]);
++
++		ADD_ID_TO_FREELIST(info, id);
++
++		uptodate = (bret->status == BLKIF_RSP_OKAY);
++		switch (bret->operation) {
++		case BLKIF_OP_WRITE_BARRIER:
++			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
++				printk("blkfront: %s: write barrier op failed\n",
++				       info->gd->disk_name);
++				uptodate = -EOPNOTSUPP;
++				info->feature_barrier = 0;
++			        xlvbd_barrier(info);
++			}
++			/* fall through */
++		case BLKIF_OP_READ:
++		case BLKIF_OP_WRITE:
++			if (unlikely(bret->status != BLKIF_RSP_OKAY))
++				DPRINTK("Bad return from blkdev data "
++					"request: %x\n", bret->status);
++
++			ret = end_that_request_first(req, uptodate,
++				req->hard_nr_sectors);
++			BUG_ON(ret);
++			end_that_request_last(req, uptodate);
++			break;
++		default:
++			BUG();
++		}
++	}
++
++	info->ring.rsp_cons = i;
++
++	if (i != info->ring.req_prod_pvt) {
++		int more_to_do;
++		RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
++		if (more_to_do)
++			goto again;
++	} else
++		info->ring.sring->rsp_event = i + 1;
++
++	kick_pending_request_queues(info);
++
++	spin_unlock_irqrestore(&blkif_io_lock, flags);
++
++	return IRQ_HANDLED;
++}
++
++static void blkif_free(struct blkfront_info *info, int suspend)
++{
++	/* Prevent new requests being issued until we fix things up. */
++	spin_lock_irq(&blkif_io_lock);
++	info->connected = suspend ?
++		BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
++	/* No more blkif_request(). */
++	if (info->rq)
++		blk_stop_queue(info->rq);
++	/* No more gnttab callback work. */
++	gnttab_cancel_free_callback(&info->callback);
++	spin_unlock_irq(&blkif_io_lock);
++
++	/* Flush gnttab callback work. Must be done with no locks held. */
++	flush_scheduled_work();
++
++	/* Free resources associated with old device channel. */
++	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;
++}
++
++static void blkif_completion(struct blk_shadow *s)
++{
++	int i;
++	for (i = 0; i < s->req.nr_segments; i++)
++		gnttab_end_foreign_access(s->req.seg[i].gref, 0UL);
++}
++
++static void blkif_recover(struct blkfront_info *info)
++{
++	int i;
++	blkif_request_t *req;
++	struct blk_shadow *copy;
++	int j;
++
++	/* Stage 1: Make a safe copy of the shadow state. */
++	copy = kmalloc(sizeof(info->shadow), GFP_NOIO | __GFP_NOFAIL | __GFP_HIGH);
++	memcpy(copy, info->shadow, sizeof(info->shadow));
++
++	/* Stage 2: Set up free list. */
++	memset(&info->shadow, 0, sizeof(info->shadow));
++	for (i = 0; i < BLK_RING_SIZE; i++)
++		info->shadow[i].req.id = i+1;
++	info->shadow_free = info->ring.req_prod_pvt;
++	info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
++
++	/* Stage 3: Find pending requests and requeue them. */
++	for (i = 0; i < BLK_RING_SIZE; i++) {
++		/* Not in use? */
++		if (copy[i].request == 0)
++			continue;
++
++		/* Grab a request slot and copy shadow state into it. */
++		req = RING_GET_REQUEST(
++			&info->ring, info->ring.req_prod_pvt);
++		*req = copy[i].req;
++
++		/* We get a new request id, and must reset the shadow state. */
++		req->id = GET_ID_FROM_FREELIST(info);
++		memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
++
++		/* Rewrite any grant references invalidated by susp/resume. */
++		for (j = 0; j < req->nr_segments; j++)
++			gnttab_grant_foreign_access_ref(
++				req->seg[j].gref,
++				info->xbdev->otherend_id,
++				pfn_to_mfn(info->shadow[req->id].frame[j]),
++				rq_data_dir((struct request *)
++					    info->shadow[req->id].request) ?
++				GTF_readonly : 0);
++		info->shadow[req->id].req = *req;
++
++		info->ring.req_prod_pvt++;
++	}
++
++	kfree(copy);
++
++	(void)xenbus_switch_state(info->xbdev, XenbusStateConnected);
++
++	spin_lock_irq(&blkif_io_lock);
++
++	/* Now safe for us to use the shared ring */
++	info->connected = BLKIF_STATE_CONNECTED;
++
++	/* Send off requeued requests */
++	flush_requests(info);
++
++	/* Kick any other new requests queued since we resumed */
++	kick_pending_request_queues(info);
++
++	spin_unlock_irq(&blkif_io_lock);
++}
++
++int blkfront_is_ready(struct xenbus_device *dev)
++{
++	struct blkfront_info *info = dev->dev.driver_data;
++
++	return info->is_ready > 0;
++}
++
++
++/* ** Driver Registration ** */
++
++
++static const struct xenbus_device_id blkfront_ids[] = {
++	{ "vbd" },
++	{ "" }
++};
++MODULE_ALIAS("xen:vbd");
++
++static struct xenbus_driver blkfront = {
++	.name = "vbd",
++	.owner = THIS_MODULE,
++	.ids = blkfront_ids,
++	.probe = blkfront_probe,
++	.remove = blkfront_remove,
++	.resume = blkfront_resume,
++	.otherend_changed = backend_changed,
++	.is_ready = blkfront_is_ready,
++};
++
++
++static int __init xlblk_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&blkfront);
++}
++module_init(xlblk_init);
++
++
++static void __exit xlblk_exit(void)
++{
++	return xenbus_unregister_driver(&blkfront);
++}
++module_exit(xlblk_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkfront/block.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,160 @@
++/******************************************************************************
++ * block.h
++ * 
++ * Shared definitions between all levels of XenLinux Virtual block devices.
++ * 
++ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
++ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
++ * Copyright (c) 2004-2005, Christian Limpach
++ * 
++ * 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_BLOCK_H__
++#define __XEN_DRIVERS_BLOCK_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/hdreg.h>
++#include <linux/blkdev.h>
++#include <linux/major.h>
++#include <asm/hypervisor.h>
++#include <xen/xenbus.h>
++#include <xen/gnttab.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/io/blkif.h>
++#include <xen/interface/io/ring.h>
++#include <asm/io.h>
++#include <asm/atomic.h>
++#include <asm/uaccess.h>
++
++#define DPRINTK(_f, _a...) pr_debug(_f, ## _a)
++
++#if 0
++#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a)
++#else
++#define DPRINTK_IOCTL(_f, _a...) ((void)0)
++#endif
++
++struct xlbd_type_info
++{
++	int partn_shift;
++	int disks_per_major;
++	char *devname;
++	char *diskname;
++};
++
++struct xlbd_major_info
++{
++	int major;
++	int index;
++	int usage;
++	struct xlbd_type_info *type;
++	struct xlbd_minor_state *minors;
++};
++
++struct blk_shadow {
++	blkif_request_t req;
++	unsigned long request;
++	unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++};
++
++#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
++
++/*
++ * We have one of these per vbd, whether ide, scsi or 'other'.  They
++ * hang in private_data off the gendisk structure. We may end up
++ * putting all kinds of interesting stuff here :-)
++ */
++struct blkfront_info
++{
++	struct xenbus_device *xbdev;
++	dev_t dev;
++ 	struct gendisk *gd;
++	int vdevice;
++	blkif_vdev_t handle;
++	int connected;
++	int ring_ref;
++	blkif_front_ring_t ring;
++	struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	unsigned int irq;
++	struct xlbd_major_info *mi;
++	request_queue_t *rq;
++	struct work_struct work;
++	struct gnttab_free_callback callback;
++	struct blk_shadow shadow[BLK_RING_SIZE];
++	unsigned long shadow_free;
++	int feature_barrier;
++	int is_ready;
++
++	/**
++	 * The number of people holding this device open.  We won't allow a
++	 * hot-unplug unless this is 0.
++	 */
++	int users;
++};
++
++extern spinlock_t blkif_io_lock;
++
++extern int blkif_open(struct inode *inode, struct file *filep);
++extern int blkif_release(struct inode *inode, struct file *filep);
++extern int blkif_ioctl(struct inode *inode, struct file *filep,
++		       unsigned command, unsigned long argument);
++extern int blkif_getgeo(struct block_device *, struct hd_geometry *);
++extern int blkif_check(dev_t dev);
++extern int blkif_revalidate(dev_t dev);
++extern void do_blkif_request (request_queue_t *rq);
++
++/* Virtual block-device subsystem. */
++/* Note that xlvbd_add doesn't call add_disk for you: you're expected
++   to call add_disk on info->gd once the disk is properly connected
++   up. */
++int xlvbd_add(blkif_sector_t capacity, int device,
++	      u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
++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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,553 @@
++/******************************************************************************
++ * vbd.c
++ * 
++ * XenLinux virtual block-device driver (xvd).
++ * 
++ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
++ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
++ * Copyright (c) 2004-2005, Christian Limpach
++ * 
++ * 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 "block.h"
++#include <linux/blkdev.h>
++#include <linux/list.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#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))
++
++struct xlbd_minor_state {
++	unsigned int nr;
++	unsigned long *bitmap;
++	spinlock_t lock;
++};
++
++/*
++ * 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
++ * places.
++ */
++
++#define NUM_IDE_MAJORS 10
++#define NUM_SCSI_MAJORS 17
++#define NUM_VBD_MAJORS 2
++
++static struct xlbd_type_info xlbd_ide_type = {
++	.partn_shift = 6,
++	.disks_per_major = 2,
++	.devname = "ide",
++	.diskname = "hd",
++};
++
++static struct xlbd_type_info xlbd_scsi_type = {
++	.partn_shift = 4,
++	.disks_per_major = 16,
++	.devname = "sd",
++	.diskname = "sd",
++};
++
++static struct xlbd_type_info xlbd_vbd_type = {
++	.partn_shift = 4,
++	.disks_per_major = 16,
++	.devname = "xvd",
++	.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];
++
++#define XLBD_MAJOR_IDE_START	0
++#define XLBD_MAJOR_SCSI_START	(NUM_IDE_MAJORS)
++#define XLBD_MAJOR_VBD_START	(NUM_IDE_MAJORS + NUM_SCSI_MAJORS)
++
++#define XLBD_MAJOR_IDE_RANGE	XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1
++#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
++
++#define XLBD_MAJOR_VBD_ALT(idx) ((idx) ^ XLBD_MAJOR_VBD_START ^ (XLBD_MAJOR_VBD_START + 1))
++
++static struct block_device_operations xlvbd_block_fops =
++{
++	.owner = THIS_MODULE,
++	.open = blkif_open,
++	.release = blkif_release,
++	.ioctl  = blkif_ioctl,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++	.getgeo = blkif_getgeo
++#endif
++};
++
++DEFINE_SPINLOCK(blkif_io_lock);
++
++static struct xlbd_major_info *
++xlbd_alloc_major_info(int major, int minor, int index)
++{
++	struct xlbd_major_info *ptr;
++	struct xlbd_minor_state *minors;
++	int do_register;
++
++	ptr = kzalloc(sizeof(struct xlbd_major_info), GFP_KERNEL);
++	if (ptr == NULL)
++		return NULL;
++
++	ptr->major = major;
++	minors = kmalloc(sizeof(*minors), GFP_KERNEL);
++	if (minors == NULL) {
++		kfree(ptr);
++		return NULL;
++	}
++
++	minors->bitmap = kzalloc(BITS_TO_LONGS(256) * sizeof(*minors->bitmap),
++				 GFP_KERNEL);
++	if (minors->bitmap == NULL) {
++		kfree(minors);
++		kfree(ptr);
++		return NULL;
++	}
++
++	spin_lock_init(&minors->lock);
++	minors->nr = 256;
++	do_register = 1;
++
++	switch (index) {
++	case XLBD_MAJOR_IDE_RANGE:
++		ptr->type = &xlbd_ide_type;
++		ptr->index = index - XLBD_MAJOR_IDE_START;
++		break;
++	case XLBD_MAJOR_SCSI_RANGE:
++		ptr->type = &xlbd_scsi_type;
++		ptr->index = index - XLBD_MAJOR_SCSI_START;
++		break;
++	case XLBD_MAJOR_VBD_RANGE:
++		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_ALT(index)] != NULL) {
++			kfree(minors->bitmap);
++			kfree(minors);
++			minors = major_info[XLBD_MAJOR_VBD_ALT(index)]->minors;
++			do_register = 0;
++		}
++		break;
++	}
++
++	if (do_register) {
++		if (register_blkdev(ptr->major, ptr->type->devname)) {
++			kfree(minors->bitmap);
++			kfree(minors);
++			kfree(ptr);
++			return NULL;
++		}
++
++		printk("xen-vbd: registered block device major %i\n", ptr->major);
++	}
++
++	ptr->minors = minors;
++	major_info[index] = ptr;
++	return ptr;
++}
++
++static struct xlbd_major_info *
++xlbd_get_major_info(int major, int minor, int vdevice)
++{
++	struct xlbd_major_info *mi;
++	int index;
++
++	switch (major) {
++	case IDE0_MAJOR: index = 0; break;
++	case IDE1_MAJOR: index = 1; break;
++	case IDE2_MAJOR: index = 2; break;
++	case IDE3_MAJOR: index = 3; break;
++	case IDE4_MAJOR: index = 4; break;
++	case IDE5_MAJOR: index = 5; break;
++	case IDE6_MAJOR: index = 6; break;
++	case IDE7_MAJOR: index = 7; break;
++	case IDE8_MAJOR: index = 8; break;
++	case IDE9_MAJOR: index = 9; break;
++	case SCSI_DISK0_MAJOR: index = 10; break;
++	case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR:
++		index = 11 + major - SCSI_DISK1_MAJOR;
++		break;
++        case SCSI_DISK8_MAJOR ... SCSI_DISK15_MAJOR:
++                index = 18 + major - SCSI_DISK8_MAJOR;
++                break;
++        case SCSI_CDROM_MAJOR: index = 26; break;
++        default:
++		if (!VDEV_IS_EXTENDED(vdevice))
++			index = 27;
++		else
++			index = 28;
++		break;
++	}
++
++	mi = ((major_info[index] != NULL) ? major_info[index] :
++	      xlbd_alloc_major_info(major, minor, index));
++	if (mi)
++		mi->usage++;
++	return mi;
++}
++
++static void
++xlbd_put_major_info(struct xlbd_major_info *mi)
++{
++	mi->usage--;
++	/* XXX: release major if 0 */
++}
++
++static int
++xlbd_reserve_minors(struct xlbd_major_info *mi, unsigned int minor,
++		    unsigned int nr_minors)
++{
++	struct xlbd_minor_state *ms = mi->minors;
++	unsigned int end = minor + nr_minors;
++	int rc;
++
++	if (end > ms->nr) {
++		unsigned long *bitmap, *old;
++
++		bitmap = kzalloc(BITS_TO_LONGS(end) * sizeof(*bitmap),
++				 GFP_KERNEL);
++		if (bitmap == NULL)
++			return -ENOMEM;
++
++		spin_lock(&ms->lock);
++		if (end > ms->nr) {
++			old = ms->bitmap;
++			memcpy(bitmap, ms->bitmap,
++			       BITS_TO_LONGS(ms->nr) * sizeof(*bitmap));
++			ms->bitmap = bitmap;
++			ms->nr = BITS_TO_LONGS(end) * BITS_PER_LONG;
++		} else
++			old = bitmap;
++		spin_unlock(&ms->lock);
++		kfree(old);
++	}
++
++	spin_lock(&ms->lock);
++	if (find_next_bit(ms->bitmap, end, minor) >= end) {
++		for (; minor < end; ++minor)
++			__set_bit(minor, ms->bitmap);
++		rc = 0;
++	} else
++		rc = -EBUSY;
++	spin_unlock(&ms->lock);
++
++	return rc;
++}
++
++static void
++xlbd_release_minors(struct xlbd_major_info *mi, unsigned int minor,
++		    unsigned int nr_minors)
++{
++	struct xlbd_minor_state *ms = mi->minors;
++	unsigned int end = minor + nr_minors;
++
++	BUG_ON(end > ms->nr);
++	spin_lock(&ms->lock);
++	for (; minor < end; ++minor)
++		__clear_bit(minor, ms->bitmap);
++	spin_unlock(&ms->lock);
++}
++
++static int
++xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
++{
++	request_queue_t *rq;
++
++	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
++	if (rq == NULL)
++		return -1;
++
++	/* Hard sector size and max sectors impersonate the equiv. hardware. */
++	blk_queue_hardsect_size(rq, sector_size);
++	blk_queue_max_sectors(rq, 512);
++
++	/* Each segment in a request is up to an aligned page in size. */
++	blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
++	blk_queue_max_segment_size(rq, PAGE_SIZE);
++
++	/* Ensure a merged request will fit in a single I/O ring slot. */
++	blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
++	blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
++
++	/* Make sure buffer addresses are sector-aligned. */
++	blk_queue_dma_alignment(rq, 511);
++
++	/* Make sure we don't use bounce buffers. */
++	blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
++
++	gd->queue = rq;
++
++	return 0;
++}
++
++static int
++xlvbd_alloc_gendisk(int major, int minor, blkif_sector_t capacity, int vdevice,
++		    u16 vdisk_info, u16 sector_size,
++		    struct blkfront_info *info)
++{
++	struct gendisk *gd;
++	struct xlbd_major_info *mi;
++	int nr_minors = 1;
++	int err = -ENODEV;
++	unsigned int offset;
++
++	BUG_ON(info->gd != NULL);
++	BUG_ON(info->mi != NULL);
++	BUG_ON(info->rq != NULL);
++
++	mi = xlbd_get_major_info(major, minor, vdevice);
++	if (mi == NULL)
++		goto out;
++	info->mi = mi;
++
++	if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
++		nr_minors = 1 << mi->type->partn_shift;
++
++	err = xlbd_reserve_minors(mi, minor, nr_minors);
++	if (err)
++		goto out;
++	err = -ENODEV;
++
++	gd = alloc_disk(nr_minors);
++	if (gd == NULL)
++		goto release;
++
++	offset =  mi->index * mi->type->disks_per_major +
++			(minor >> mi->type->partn_shift);
++	if (nr_minors > 1) {
++		if (offset < 26) {
++			sprintf(gd->disk_name, "%s%c",
++				 mi->type->diskname, 'a' + offset );
++		}
++		else {
++			sprintf(gd->disk_name, "%s%c%c",
++				mi->type->diskname,
++				'a' + ((offset/26)-1), 'a' + (offset%26) );
++		}
++	}
++	else {
++		if (offset < 26) {
++			sprintf(gd->disk_name, "%s%c%d",
++				mi->type->diskname,
++				'a' + offset,
++				minor & ((1 << mi->type->partn_shift) - 1));
++		}
++		else {
++			sprintf(gd->disk_name, "%s%c%c%d",
++				mi->type->diskname,
++				'a' + ((offset/26)-1), 'a' + (offset%26),
++				minor & ((1 << mi->type->partn_shift) - 1));
++		}
++	}
++
++	gd->major = mi->major;
++	gd->first_minor = minor;
++	gd->fops = &xlvbd_block_fops;
++	gd->private_data = info;
++	gd->driverfs_dev = &(info->xbdev->dev);
++	set_capacity(gd, capacity);
++
++	if (xlvbd_init_blk_queue(gd, sector_size)) {
++		del_gendisk(gd);
++		goto release;
++	}
++
++	info->rq = gd->queue;
++	info->gd = gd;
++
++	if (info->feature_barrier)
++		xlvbd_barrier(info);
++
++	if (vdisk_info & VDISK_READONLY)
++		set_disk_ro(gd, 1);
++
++	if (vdisk_info & VDISK_REMOVABLE)
++		gd->flags |= GENHD_FL_REMOVABLE;
++
++	if (vdisk_info & VDISK_CDROM)
++		gd->flags |= GENHD_FL_CD;
++
++	return 0;
++
++ release:
++	xlbd_release_minors(mi, minor, nr_minors);
++ out:
++	if (mi)
++		xlbd_put_major_info(mi);
++	info->mi = NULL;
++	return err;
++}
++
++int
++xlvbd_add(blkif_sector_t capacity, int vdevice, u16 vdisk_info,
++	  u16 sector_size, struct blkfront_info *info)
++{
++	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;
++	}
++
++	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(major, minor, capacity, vdevice, vdisk_info,
++				  sector_size, info);
++
++	bdput(bd);
++	return err;
++}
++
++void
++xlvbd_del(struct blkfront_info *info)
++{
++	unsigned int minor, nr_minors;
++
++	if (info->mi == NULL)
++		return;
++
++	BUG_ON(info->gd == NULL);
++	minor = info->gd->first_minor;
++	nr_minors = info->gd->minors;
++	del_gendisk(info->gd);
++	put_disk(info->gd);
++	info->gd = NULL;
++
++	xlbd_release_minors(info->mi, minor, nr_minors);
++	xlbd_put_major_info(info->mi);
++	info->mi = NULL;
++
++	BUG_ON(info->rq == NULL);
++	blk_cleanup_queue(info->rq);
++	info->rq = NULL;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++int
++xlvbd_barrier(struct blkfront_info *info)
++{
++	int err;
++
++	err = blk_queue_ordered(info->rq,
++		info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, NULL);
++	if (err)
++		return err;
++	printk(KERN_INFO "blkfront: %s: barriers %s\n",
++	       info->gd->disk_name, info->feature_barrier ? "enabled" : "disabled");
++	return 0;
++}
++#else
++int
++xlvbd_barrier(struct blkfront_info *info)
++{
++	printk(KERN_INFO "blkfront: %s: barriers disabled\n", info->gd->disk_name);
++	return -ENOSYS;
++}
++#endif
++
++#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;
++
++	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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap/Makefile	2007-06-12 13:13:44.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 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,1757 @@
++/******************************************************************************
++ * drivers/xen/blktap/blktap.c
++ * 
++ * Back-end driver for user level virtual block devices. This portion of the
++ * driver exports a 'unified' block-device interface that can be accessed
++ * by any operating system that implements a compatible front end. Requests
++ * are remapped to a user-space memory region.
++ *
++ * Based on the blkback driver code.
++ * 
++ * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
++ *
++ * Clean ups and fix ups:
++ *    Copyright (c) 2006, Steven Rostedt - Red Hat, 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.
++ */
++
++#include <linux/spinlock.h>
++#include <linux/kthread.h>
++#include <linux/list.h>
++#include <asm/hypervisor.h>
++#include "common.h"
++#include <xen/balloon.h>
++#include <xen/driver_util.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/errno.h>
++#include <linux/major.h>
++#include <linux/gfp.h>
++#include <linux/poll.h>
++#include <linux/delay.h>
++#include <asm/tlbflush.h>
++
++#define MAX_TAP_DEV 256     /*the maximum number of tapdisk ring devices    */
++#define MAX_DEV_NAME 100    /*the max tapdisk ring device name e.g. blktap0 */
++
++/*
++ * The maximum number of requests that can be outstanding at any time
++ * is determined by 
++ *
++ *   [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] 
++ *
++ * where mmap_alloc < MAX_DYNAMIC_MEM.
++ *
++ * TODO:
++ * mmap_alloc is initialised to 2 and should be adjustable on the fly via
++ * sysfs.
++ */
++#define BLK_RING_SIZE		__RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
++#define MAX_DYNAMIC_MEM		BLK_RING_SIZE
++#define MAX_PENDING_REQS	BLK_RING_SIZE
++#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
++#define MMAP_VADDR(_start, _req,_seg)                                   \
++        (_start +                                                       \
++         ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +        \
++         ((_seg) * PAGE_SIZE))
++static int blkif_reqs = MAX_PENDING_REQS;
++static int mmap_pages = MMAP_PAGES;
++
++#define RING_PAGES 1 /* BLKTAP - immediately before the mmap area, we
++		      * have a bunch of pages reserved for shared
++		      * memory rings.
++		      */
++
++/*Data struct handed back to userspace for tapdisk device to VBD mapping*/
++typedef struct domid_translate {
++	unsigned short domid;
++	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 mm_struct *mm;         /*User address space                   */
++	unsigned long rings_vstart;   /*Kernel memory mapping                */
++	unsigned long user_vstart;    /*User memory mapping                  */
++	unsigned long dev_inuse;      /*One process opens device at a time.  */
++	unsigned long dev_pending;    /*In process of being opened           */
++	unsigned long ring_ok;        /*make this ring->state                */
++	blkif_front_ring_t ufe_ring;  /*Rings up to user space.              */
++	wait_queue_head_t wait;       /*for poll                             */
++	unsigned long mode;           /*current switching mode               */
++	int minor;                    /*Minor number for tapdisk device      */
++	pid_t pid;                    /*tapdisk process id                   */
++	enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace 
++						  shutdown                   */
++	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_ext trans; /*Translation from domid to bus.   */
++	struct vm_foreign_map foreign_map;    /*Mapping page */
++} tap_blkif_t;
++
++static struct tap_blkif *tapfds[MAX_TAP_DEV];
++static int blktap_next_minor;
++
++module_param(blkif_reqs, int, 0);
++/* Run-time switchable: /sys/module/blktap/parameters/ */
++static unsigned int log_stats = 0;
++static unsigned int debug_lvl = 0;
++module_param(log_stats, int, 0644);
++module_param(debug_lvl, int, 0644);
++
++/*
++ * Each outstanding request that we've passed to the lower device layers has a 
++ * 'pending_req' allocated to it. Each buffer_head that completes decrements 
++ * the pendcnt towards zero. When it hits zero, the specified domain has a 
++ * response queued for it, with the saved 'id' passed back.
++ */
++typedef struct {
++	blkif_t       *blkif;
++	u64            id;
++	unsigned short mem_idx;
++	int            nr_pages;
++	atomic_t       pendcnt;
++	unsigned short operation;
++	int            status;
++	struct list_head free_list;
++	int            inuse;
++} pending_req_t;
++
++static pending_req_t *pending_reqs[MAX_PENDING_REQS];
++static struct list_head pending_free;
++static DEFINE_SPINLOCK(pending_free_lock);
++static DECLARE_WAIT_QUEUE_HEAD (pending_free_wq);
++static int alloc_pending_reqs;
++
++typedef unsigned int PEND_RING_IDX;
++
++static inline int MASK_PEND_IDX(int i) { 
++	return (i & (MAX_PENDING_REQS-1));
++}
++
++static inline unsigned int RTN_PEND_IDX(pending_req_t *req, int idx) {
++	return (req - pending_reqs[idx]);
++}
++
++#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
++
++#define BLKBACK_INVALID_HANDLE (~0)
++
++static struct page **foreign_pages[MAX_DYNAMIC_MEM];
++static inline struct page *idx_to_page(
++	unsigned int mmap_idx, unsigned int req_idx, unsigned int sg_idx)
++{
++	unsigned int arr_idx = req_idx*BLKIF_MAX_SEGMENTS_PER_REQUEST + sg_idx;
++	return foreign_pages[mmap_idx][arr_idx];
++}
++static inline unsigned long idx_to_kaddr(
++	unsigned int mmap_idx, unsigned int req_idx, unsigned int sg_idx)
++{
++	unsigned long pfn = page_to_pfn(idx_to_page(mmap_idx,req_idx,sg_idx));
++	return (unsigned long)pfn_to_kaddr(pfn);
++}
++
++static unsigned short mmap_alloc = 0;
++static unsigned short mmap_lock = 0;
++static unsigned short mmap_inuse = 0;
++
++/******************************************************************
++ * GRANT HANDLES
++ */
++
++/* When using grant tables to map a frame for device access then the
++ * handle returned must be used to unmap the frame. This is needed to
++ * drop the ref count on the frame.
++ */
++struct grant_handle_pair
++{
++        grant_handle_t kernel;
++        grant_handle_t user;
++};
++#define INVALID_GRANT_HANDLE	0xFFFF
++
++static struct grant_handle_pair 
++    pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES];
++#define pending_handle(_id, _idx, _i) \
++    (pending_grant_handles[_id][((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) \
++    + (_i)])
++
++
++static int blktap_read_ufe_ring(tap_blkif_t *info); /*local prototypes*/
++
++#define BLKTAP_MINOR 0  /*/dev/xen/blktap has a dynamic major */
++#define BLKTAP_DEV_DIR  "/dev/xen"
++
++static int blktap_major;
++
++/* blktap IOCTLs: */
++#define BLKTAP_IOCTL_KICK_FE         1
++#define BLKTAP_IOCTL_KICK_BE         2 /* currently unused */
++#define BLKTAP_IOCTL_SETMODE         3
++#define BLKTAP_IOCTL_SENDPID	     4
++#define BLKTAP_IOCTL_NEWINTF	     5
++#define BLKTAP_IOCTL_MINOR	     6
++#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)             */
++#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
++#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
++#define BLKTAP_MODE_INTERCEPT_BE     0x00000002  /* unimp.             */
++
++#define BLKTAP_MODE_INTERPOSE \
++           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
++
++
++static inline int BLKTAP_MODE_VALID(unsigned long arg)
++{
++	return ((arg == BLKTAP_MODE_PASSTHROUGH ) ||
++		(arg == BLKTAP_MODE_INTERCEPT_FE) ||
++                (arg == BLKTAP_MODE_INTERPOSE   ));
++}
++
++/* Requests passing through the tap to userspace are re-assigned an ID.
++ * We must record a mapping between the BE [IDX,ID] tuple and the userspace
++ * ring ID. 
++ */
++
++static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
++{
++        return ((fe_dom << 16) | MASK_PEND_IDX(idx));
++}
++
++extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
++{
++        return (PEND_RING_IDX)(id & 0x0000ffff);
++}
++
++extern inline int ID_TO_MIDX(unsigned long id)
++{
++        return (int)(id >> 16);
++}
++
++#define INVALID_REQ 0xdead0000
++
++/*TODO: Convert to a free list*/
++static inline int GET_NEXT_REQ(unsigned long *idx_map)
++{
++	int i;
++	for (i = 0; i < MAX_PENDING_REQS; i++)
++		if (idx_map[i] == INVALID_REQ)
++			return i;
++
++	return INVALID_REQ;
++}
++
++static inline int OFFSET_TO_USR_IDX(int offset)
++{
++	return offset / BLKIF_MAX_SEGMENTS_PER_REQUEST;
++}
++
++static inline int OFFSET_TO_SEG(int offset)
++{
++	return offset % BLKIF_MAX_SEGMENTS_PER_REQUEST;
++}
++
++
++#define BLKTAP_INVALID_HANDLE(_g) \
++    (((_g->kernel) == INVALID_GRANT_HANDLE) &&  \
++     ((_g->user) == INVALID_GRANT_HANDLE))
++
++#define BLKTAP_INVALIDATE_HANDLE(_g) do {       \
++    (_g)->kernel = INVALID_GRANT_HANDLE; (_g)->user = INVALID_GRANT_HANDLE; \
++    } while(0)
++
++
++/******************************************************************
++ * BLKTAP VM OPS
++ */
++
++static struct page *blktap_nopage(struct vm_area_struct *vma,
++				  unsigned long address,
++				  int *type)
++{
++	/*
++	 * if the page has not been mapped in by the driver then return
++	 * NOPAGE_SIGBUS to the domain.
++	 */
++
++	return NOPAGE_SIGBUS;
++}
++
++static pte_t blktap_clear_pte(struct vm_area_struct *vma,
++			      unsigned long uvaddr,
++			      pte_t *ptep, int is_fullmm)
++{
++	pte_t copy;
++	tap_blkif_t *info = NULL;
++	int offset, seg, usr_idx, pending_idx, mmap_idx;
++	unsigned long uvstart = 0;
++	unsigned long kvaddr;
++	struct page *pg;
++	struct grant_handle_pair *khandle;
++	struct gnttab_unmap_grant_ref unmap[2];
++	int count = 0;
++
++	/*
++	 * If the address is before the start of the grant mapped region or
++	 * if vm_file is NULL (meaning mmap failed and we have nothing to do)
++	 */
++	if (vma->vm_file != NULL) {
++		info = vma->vm_file->private_data;
++		uvstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
++	}
++	if (vma->vm_file == NULL || uvaddr < uvstart)
++		return ptep_get_and_clear_full(vma->vm_mm, uvaddr, 
++					       ptep, is_fullmm);
++
++	/* TODO Should these be changed to if statements? */
++	BUG_ON(!info);
++	BUG_ON(!info->idx_map);
++
++	offset = (int) ((uvaddr - uvstart) >> PAGE_SHIFT);
++	usr_idx = OFFSET_TO_USR_IDX(offset);
++	seg = OFFSET_TO_SEG(offset);
++
++	pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
++	mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
++
++	kvaddr = idx_to_kaddr(mmap_idx, pending_idx, seg);
++	pg = idx_to_page(mmap_idx, pending_idx, seg);
++	ClearPageReserved(pg);
++	info->foreign_map.map[offset + RING_PAGES] = NULL;
++
++	khandle = &pending_handle(mmap_idx, pending_idx, seg);
++
++	if (khandle->kernel != INVALID_GRANT_HANDLE) {
++		gnttab_set_unmap_op(&unmap[count], kvaddr, 
++				    GNTMAP_host_map, khandle->kernel);
++		count++;
++
++		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, 
++				    INVALID_P2M_ENTRY);
++	}
++
++	if (khandle->user != INVALID_GRANT_HANDLE) {
++		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++
++		copy = *ptep;
++		gnttab_set_unmap_op(&unmap[count], ptep_to_machine(ptep),
++				    GNTMAP_host_map 
++				    | GNTMAP_application_map 
++				    | GNTMAP_contains_pte,
++				    khandle->user);
++		count++;
++	} else {
++		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap));
++
++		/* USING SHADOW PAGE TABLES. */
++		copy = ptep_get_and_clear_full(vma->vm_mm, uvaddr, ptep,
++					       is_fullmm);
++	}
++
++	if (count) {
++		BLKTAP_INVALIDATE_HANDLE(khandle);
++		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
++					      unmap, count))
++			BUG();
++	}
++
++	return copy;
++}
++
++static void blktap_vma_open(struct vm_area_struct *vma)
++{
++	tap_blkif_t *info;
++	if (vma->vm_file == NULL)
++		return;
++
++	info = vma->vm_file->private_data;
++	vma->vm_private_data =
++		&info->foreign_map.map[(vma->vm_start - info->rings_vstart) >> PAGE_SHIFT];
++}
++
++/* tricky part
++ * When partial munmapping, ->open() is called only splitted vma which
++ * will be released soon. * See split_vma() and do_munmap() in mm/mmap.c
++ * So there is no chance to fix up vm_private_data of the end vma.
++ */
++static void blktap_vma_close(struct vm_area_struct *vma)
++{
++	tap_blkif_t *info;
++	struct vm_area_struct *next = vma->vm_next;
++
++	if (next == NULL ||
++	    vma->vm_ops != next->vm_ops ||
++	    vma->vm_end != next->vm_start ||
++	    vma->vm_file == NULL ||
++	    vma->vm_file != next->vm_file)
++		return;
++
++	info = vma->vm_file->private_data;
++	next->vm_private_data =
++		&info->foreign_map.map[(next->vm_start - info->rings_vstart) >> PAGE_SHIFT];
++}
++
++static struct vm_operations_struct blktap_vm_ops = {
++	nopage:   blktap_nopage,
++	zap_pte:  blktap_clear_pte,
++	open:     blktap_vma_open,
++	close:    blktap_vma_close,
++};
++
++/******************************************************************
++ * BLKTAP FILE OPS
++ */
++ 
++/*Function Declarations*/
++static tap_blkif_t *get_next_free_dev(void);
++static int blktap_open(struct inode *inode, struct file *filp);
++static int blktap_release(struct inode *inode, struct file *filp);
++static int blktap_mmap(struct file *filp, struct vm_area_struct *vma);
++static int blktap_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg);
++static unsigned int blktap_poll(struct file *file, poll_table *wait);
++
++static const struct file_operations blktap_fops = {
++	.owner   = THIS_MODULE,
++	.poll    = blktap_poll,
++	.ioctl   = blktap_ioctl,
++	.open    = blktap_open,
++	.release = blktap_release,
++	.mmap    = blktap_mmap,
++};
++
++
++static tap_blkif_t *get_next_free_dev(void)
++{
++	struct class *class;
++	tap_blkif_t *info;
++	int minor;
++
++	/*
++	 * This is called only from the ioctl, which
++	 * means we should always have interrupts enabled.
++	 */
++	BUG_ON(irqs_disabled());
++
++	spin_lock_irq(&pending_free_lock);
++
++	/* tapfds[0] is always NULL */
++
++	for (minor = 1; minor < blktap_next_minor; minor++) {
++		info = tapfds[minor];
++		/* we could have failed a previous attempt. */
++		if (!info ||
++		    ((!test_bit(0, &info->dev_inuse)) &&
++		     (info->dev_pending == 0)) ) {
++			info->dev_pending = 1;
++			goto found;
++		}
++	}
++	info = NULL;
++	minor = -1;
++
++	/*
++	 * We didn't find free device. If we can still allocate
++	 * more, then we grab the next device minor that is
++	 * available.  This is done while we are still under
++	 * the protection of the pending_free_lock.
++	 */
++	if (blktap_next_minor < MAX_TAP_DEV)
++		minor = blktap_next_minor++;
++found:
++	spin_unlock_irq(&pending_free_lock);
++
++	if (!info && minor > 0) {
++		info = kzalloc(sizeof(*info), GFP_KERNEL);
++		if (unlikely(!info)) {
++			/*
++			 * If we failed here, try to put back
++			 * the next minor number. But if one
++			 * was just taken, then we just lose this
++			 * minor.  We can try to allocate this
++			 * minor again later.
++			 */
++			spin_lock_irq(&pending_free_lock);
++			if (blktap_next_minor == minor+1)
++				blktap_next_minor--;
++			spin_unlock_irq(&pending_free_lock);
++			goto out;
++		}
++
++		info->minor = minor;
++		/*
++		 * Make sure that we have a minor before others can
++		 * see us.
++		 */
++		wmb();
++		tapfds[minor] = info;
++
++		if ((class = get_xen_class()) != NULL)
++			class_device_create(class, NULL,
++					    MKDEV(blktap_major, minor), NULL,
++					    "blktap%d", minor);
++	}
++
++out:
++	return info;
++}
++
++int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif) 
++{
++	tap_blkif_t *info;
++	int i;
++
++	for (i = 1; i < blktap_next_minor; i++) {
++		info = tapfds[i];
++		if ( info &&
++		     (info->trans.domid == domid) &&
++		     (info->trans.busid == xenbus_id) ) {
++			info->blkif = blkif;
++			info->status = RUNNING;
++			return i;
++		}
++	}
++	return -1;
++}
++
++void signal_tapdisk(int idx) 
++{
++	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;
++
++	if (info->pid > 0) {
++		ptask = find_task_by_pid(info->pid);
++		if (ptask)
++			info->status = CLEANSHUTDOWN;
++	}
++	info->blkif = NULL;
++
++	return;
++}
++
++static int blktap_open(struct inode *inode, struct file *filp)
++{
++	blkif_sring_t *sring;
++	int idx = iminor(inode) - BLKTAP_MINOR;
++	tap_blkif_t *info;
++	int i;
++	
++	/* ctrl device, treat differently */
++	if (!idx)
++		return 0;
++
++	info = tapfds[idx];
++
++	if ((idx < 0) || (idx > MAX_TAP_DEV) || !info) {
++		WPRINTK("Unable to open device /dev/xen/blktap%d\n",
++			idx);
++		return -ENODEV;
++	}
++
++	DPRINTK("Opening device /dev/xen/blktap%d\n",idx);
++	
++	/*Only one process can access device at a time*/
++	if (test_and_set_bit(0, &info->dev_inuse))
++		return -EBUSY;
++
++	info->dev_pending = 0;
++	    
++	/* Allocate the fe ring. */
++	sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
++	if (sring == NULL)
++		goto fail_nomem;
++
++	SetPageReserved(virt_to_page(sring));
++    
++	SHARED_RING_INIT(sring);
++	FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE);
++	
++	filp->private_data = info;
++	info->mm = NULL;
++
++	info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, 
++				GFP_KERNEL);
++	
++	if (info->idx_map == NULL)
++		goto fail_nomem;
++
++	if (idx > 0) {
++		init_waitqueue_head(&info->wait);
++		for (i = 0; i < MAX_PENDING_REQS; i++) 
++			info->idx_map[i] = INVALID_REQ;
++	}
++
++	DPRINTK("Tap open: device /dev/xen/blktap%d\n",idx);
++	return 0;
++
++ fail_nomem:
++	return -ENOMEM;
++}
++
++static int blktap_release(struct inode *inode, struct file *filp)
++{
++	tap_blkif_t *info = filp->private_data;
++	
++	/* check for control device */
++	if (!info)
++		return 0;
++
++	info->ring_ok = 0;
++	smp_wmb();
++
++	mmput(info->mm);
++	info->mm = NULL;
++	kfree(info->foreign_map.map);
++	info->foreign_map.map = NULL;
++
++	/* Free the ring page. */
++	ClearPageReserved(virt_to_page(info->ufe_ring.sring));
++	free_page((unsigned long) info->ufe_ring.sring);
++
++	if (info->idx_map) {
++		kfree(info->idx_map);
++		info->idx_map = NULL;
++	}
++
++	if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) {
++		if (info->blkif->xenblkd != NULL) {
++			kthread_stop(info->blkif->xenblkd);
++			info->blkif->xenblkd = NULL;
++		}
++		info->status = CLEANSHUTDOWN;
++	}
++
++	clear_bit(0, &info->dev_inuse);
++	DPRINTK("Freeing device [/dev/xen/blktap%d]\n",info->minor);
++
++	return 0;
++}
++
++
++/* Note on mmap:
++ * We need to map pages to user space in a way that will allow the block
++ * subsystem set up direct IO to them.  This couldn't be done before, because
++ * there isn't really a sane way to translate a user virtual address down to a 
++ * physical address when the page belongs to another domain.
++ *
++ * My first approach was to map the page in to kernel memory, add an entry
++ * for it in the physical frame list (using alloc_lomem_region as in blkback)
++ * and then attempt to map that page up to user space.  This is disallowed
++ * by xen though, which realizes that we don't really own the machine frame
++ * underlying the physical page.
++ *
++ * The new approach is to provide explicit support for this in xen linux.
++ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
++ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
++ * from pages to actual page structs.  There is a new clause in get_user_pages
++ * that does the right thing for this sort of mapping.
++ */
++static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++	int size;
++	tap_blkif_t *info = filp->private_data;
++	int ret;
++
++	if (info == NULL) {
++		WPRINTK("blktap: mmap, retrieving idx failed\n");
++		return -ENOMEM;
++	}
++	
++	vma->vm_flags |= VM_RESERVED;
++	vma->vm_ops = &blktap_vm_ops;
++
++	size = vma->vm_end - vma->vm_start;
++	if (size != ((mmap_pages + RING_PAGES) << PAGE_SHIFT)) {
++		WPRINTK("you _must_ map exactly %d pages!\n",
++		       mmap_pages + RING_PAGES);
++		return -EAGAIN;
++	}
++
++	size >>= PAGE_SHIFT;
++	info->rings_vstart = vma->vm_start;
++	info->user_vstart  = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
++    
++	/* Map the ring pages to the start of the region and reserve it. */
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		ret = vm_insert_page(vma, vma->vm_start,
++				     virt_to_page(info->ufe_ring.sring));
++	else
++		ret = remap_pfn_range(vma, vma->vm_start,
++				      __pa(info->ufe_ring.sring) >> PAGE_SHIFT,
++				      PAGE_SIZE, vma->vm_page_prot);
++	if (ret) {
++		WPRINTK("Mapping user ring failed!\n");
++		goto fail;
++	}
++
++	/* Mark this VM as containing foreign pages, and set up mappings. */
++	info->foreign_map.map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) *
++			    sizeof(*info->foreign_map.map), GFP_KERNEL);
++	if (info->foreign_map.map == NULL) {
++		WPRINTK("Couldn't alloc VM_FOREIGN map.\n");
++		goto fail;
++	}
++
++	vma->vm_private_data = &info->foreign_map;
++	vma->vm_flags |= VM_FOREIGN;
++	vma->vm_flags |= VM_DONTCOPY;
++
++#ifdef CONFIG_X86
++	vma->vm_mm->context.has_foreign_mappings = 1;
++#endif
++
++	info->mm = get_task_mm(current);
++	smp_wmb();
++	info->ring_ok = 1;
++	return 0;
++ fail:
++	/* Clear any active mappings. */
++	zap_page_range(vma, vma->vm_start, 
++		       vma->vm_end - vma->vm_start, NULL);
++
++	return -ENOMEM;
++}
++
++
++static int blktap_ioctl(struct inode *inode, struct file *filp,
++                        unsigned int cmd, unsigned long arg)
++{
++	tap_blkif_t *info = filp->private_data;
++
++	switch(cmd) {
++	case BLKTAP_IOCTL_KICK_FE: 
++	{
++		/* There are fe messages to process. */
++		return blktap_read_ufe_ring(info);
++	}
++	case BLKTAP_IOCTL_SETMODE:
++	{
++		if (info) {
++			if (BLKTAP_MODE_VALID(arg)) {
++				info->mode = arg;
++				/* XXX: may need to flush rings here. */
++				DPRINTK("blktap: set mode to %lx\n", 
++				       arg);
++				return 0;
++			}
++		}
++		return 0;
++	}
++	case BLKTAP_IOCTL_PRINT_IDXS:
++        {
++		if (info) {
++			printk("User Rings: \n-----------\n");
++			printk("UF: rsp_cons: %2d, req_prod_prv: %2d "
++				"| req_prod: %2d, rsp_prod: %2d\n",
++				info->ufe_ring.rsp_cons,
++				info->ufe_ring.req_prod_pvt,
++				info->ufe_ring.sring->req_prod,
++				info->ufe_ring.sring->rsp_prod);
++		}
++            	return 0;
++        }
++	case BLKTAP_IOCTL_SENDPID:
++	{
++		if (info) {
++			info->pid = (pid_t)arg;
++			DPRINTK("blktap: pid received %d\n", 
++			       info->pid);
++		}
++		return 0;
++	}
++	case BLKTAP_IOCTL_NEWINTF:
++	{		
++		uint64_t val = (uint64_t)arg;
++		domid_translate_t *tr = (domid_translate_t *)&val;
++
++		DPRINTK("NEWINTF 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_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;
++		unsigned long flags;
++
++		info = tapfds[dev];
++
++		if ((dev > MAX_TAP_DEV) || !info)
++			return 0; /* should this be an error? */
++
++		spin_lock_irqsave(&pending_free_lock, flags);
++		if (info->dev_pending)
++			info->dev_pending = 0;
++		spin_unlock_irqrestore(&pending_free_lock, flags);
++
++		return 0;
++	}
++	case BLKTAP_IOCTL_MINOR:
++	{
++		unsigned long dev = arg;
++
++		info = tapfds[dev];
++
++		if ((dev > MAX_TAP_DEV) || !info)
++			return -EINVAL;
++
++		return info->minor;
++	}
++	case BLKTAP_IOCTL_MAJOR:
++		return blktap_major;
++
++	case BLKTAP_QUERY_ALLOC_REQS:
++	{
++		WPRINTK("BLKTAP_QUERY_ALLOC_REQS ioctl: %d/%d\n",
++		       alloc_pending_reqs, blkif_reqs);
++		return (alloc_pending_reqs/blkif_reqs) * 100;
++	}
++	}
++	return -ENOIOCTLCMD;
++}
++
++static unsigned int blktap_poll(struct file *filp, poll_table *wait)
++{
++	tap_blkif_t *info = filp->private_data;
++	
++	/* do not work on the control device */
++	if (!info)
++		return 0;
++
++	poll_wait(filp, &info->wait, wait);
++	if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) {
++		RING_PUSH_REQUESTS(&info->ufe_ring);
++		return POLLIN | POLLRDNORM;
++	}
++	return 0;
++}
++
++static void blktap_kick_user(int idx)
++{
++	tap_blkif_t *info;
++
++	info = tapfds[idx];
++
++	if ((idx < 0) || (idx > MAX_TAP_DEV) || !info)
++		return;
++
++	wake_up_interruptible(&info->wait);
++
++	return;
++}
++
++static int do_block_io_op(blkif_t *blkif);
++static void dispatch_rw_block_io(blkif_t *blkif,
++				 blkif_request_t *req,
++				 pending_req_t *pending_req);
++static void make_response(blkif_t *blkif, u64 id,
++                          unsigned short op, int st);
++
++/******************************************************************
++ * misc small helpers
++ */
++static int req_increase(void)
++{
++	int i, j;
++
++	if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) 
++		return -EINVAL;
++
++	pending_reqs[mmap_alloc]  = kzalloc(sizeof(pending_req_t)
++					    * blkif_reqs, GFP_KERNEL);
++	foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages);
++
++	if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc])
++		goto out_of_memory;
++
++	DPRINTK("%s: reqs=%d, pages=%d\n",
++		__FUNCTION__, blkif_reqs, mmap_pages);
++
++	for (i = 0; i < MAX_PENDING_REQS; i++) {
++		list_add_tail(&pending_reqs[mmap_alloc][i].free_list, 
++			      &pending_free);
++		pending_reqs[mmap_alloc][i].mem_idx = mmap_alloc;
++		for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
++			BLKTAP_INVALIDATE_HANDLE(&pending_handle(mmap_alloc, 
++								 i, j));
++	}
++
++	mmap_alloc++;
++	DPRINTK("# MMAPs increased to %d\n",mmap_alloc);
++	return 0;
++
++ out_of_memory:
++	free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
++	kfree(pending_reqs[mmap_alloc]);
++	WPRINTK("%s: out of memory\n", __FUNCTION__);
++	return -ENOMEM;
++}
++
++static void mmap_req_del(int mmap)
++{
++	assert_spin_locked(&pending_free_lock);
++
++	kfree(pending_reqs[mmap]);
++	pending_reqs[mmap] = NULL;
++
++	free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages);
++	foreign_pages[mmap] = NULL;
++
++	mmap_lock = 0;
++	DPRINTK("# MMAPs decreased to %d\n",mmap_alloc);
++	mmap_alloc--;
++}
++
++static pending_req_t* alloc_req(void)
++{
++	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);
++	}
++
++	if (req) {
++		req->inuse = 1;
++		alloc_pending_reqs++;
++	}
++	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);
++
++	alloc_pending_reqs--;
++	req->inuse = 0;
++	if (mmap_lock && (req->mem_idx == mmap_alloc-1)) {
++		mmap_inuse--;
++		if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1);
++		spin_unlock_irqrestore(&pending_free_lock, flags);
++		return;
++	}
++	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 blktap_zap_page_range(struct mm_struct *mm,
++				  unsigned long uvaddr, int nr_pages)
++{
++	unsigned long end = uvaddr + (nr_pages << PAGE_SHIFT);
++	struct vm_area_struct *vma;
++
++	vma = find_vma(mm, uvaddr);
++	while (vma && uvaddr < end) {
++		unsigned long s = max(uvaddr, vma->vm_start);
++		unsigned long e = min(end, vma->vm_end);
++
++		zap_page_range(vma, s, e - s, NULL);
++
++		uvaddr = e;
++		vma = vma->vm_next;
++	}
++}
++
++static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx,
++			    int tapidx)
++{
++	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
++	unsigned int i, invcount = 0, locked = 0;
++	struct grant_handle_pair *khandle;
++	uint64_t ptep;
++	int ret, mmap_idx;
++	unsigned long uvaddr;
++	tap_blkif_t *info;
++	struct mm_struct *mm;
++	
++
++	info = tapfds[tapidx];
++
++	if ((tapidx < 0) || (tapidx > MAX_TAP_DEV) || !info) {
++		WPRINTK("fast_flush: Couldn't get info!\n");
++		return;
++	}
++
++	mm = info->mm;
++
++	if (mm != NULL && xen_feature(XENFEAT_auto_translated_physmap)) {
++		down_write(&mm->mmap_sem);
++		blktap_zap_page_range(mm,
++				      MMAP_VADDR(info->user_vstart, u_idx, 0),
++				      req->nr_pages);
++		up_write(&mm->mmap_sem);
++		return;
++	}
++
++	mmap_idx = req->mem_idx;
++
++	for (i = 0; i < req->nr_pages; i++) {
++		uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i);
++
++		khandle = &pending_handle(mmap_idx, k_idx, i);
++
++		if (khandle->kernel != INVALID_GRANT_HANDLE) {
++			gnttab_set_unmap_op(&unmap[invcount],
++					    idx_to_kaddr(mmap_idx, k_idx, i),
++					    GNTMAP_host_map, khandle->kernel);
++			invcount++;
++
++			set_phys_to_machine(
++				page_to_pfn(idx_to_page(mmap_idx, k_idx, i)),
++				INVALID_P2M_ENTRY);
++		}
++
++		if (khandle->user != INVALID_GRANT_HANDLE) {
++			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++			if (!locked++)
++				down_write(&mm->mmap_sem);
++			if (create_lookup_pte_addr(
++				mm,
++				MMAP_VADDR(info->user_vstart, u_idx, i),
++				&ptep) !=0) {
++				up_write(&mm->mmap_sem);
++				WPRINTK("Couldn't get a pte addr!\n");
++				return;
++			}
++
++			gnttab_set_unmap_op(&unmap[invcount], ptep,
++					    GNTMAP_host_map
++					    | GNTMAP_application_map
++					    | GNTMAP_contains_pte,
++					    khandle->user);
++			invcount++;
++		}
++
++		BLKTAP_INVALIDATE_HANDLE(khandle);
++	}
++	ret = HYPERVISOR_grant_table_op(
++		GNTTABOP_unmap_grant_ref, unmap, invcount);
++	BUG_ON(ret);
++	
++	if (mm != NULL && !xen_feature(XENFEAT_auto_translated_physmap)) {
++		if (!locked++)
++			down_write(&mm->mmap_sem);
++		blktap_zap_page_range(mm, 
++				      MMAP_VADDR(info->user_vstart, u_idx, 0), 
++				      req->nr_pages);
++	}
++
++	if (locked)
++		up_write(&mm->mmap_sem);
++}
++
++/******************************************************************
++ * SCHEDULER FUNCTIONS
++ */
++
++static void print_stats(blkif_t *blkif)
++{
++	printk(KERN_DEBUG "%s: oo %3d  |  rd %4d  |  wr %4d\n",
++	       current->comm, blkif->st_oo_req,
++	       blkif->st_rd_req, blkif->st_wr_req);
++	blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
++	blkif->st_rd_req = 0;
++	blkif->st_wr_req = 0;
++	blkif->st_oo_req = 0;
++}
++
++int tap_blkif_schedule(void *arg)
++{
++	blkif_t *blkif = arg;
++
++	blkif_get(blkif);
++
++	if (debug_lvl)
++		printk(KERN_DEBUG "%s: started\n", current->comm);
++
++	while (!kthread_should_stop()) {
++		if (try_to_freeze())
++			continue;
++
++		wait_event_interruptible(
++			blkif->wq,
++			blkif->waiting_reqs || kthread_should_stop());
++		wait_event_interruptible(
++			pending_free_wq,
++			!list_empty(&pending_free) || kthread_should_stop());
++
++		blkif->waiting_reqs = 0;
++		smp_mb(); /* clear flag *before* checking for work */
++
++		if (do_block_io_op(blkif))
++			blkif->waiting_reqs = 1;
++
++		if (log_stats && time_after(jiffies, blkif->st_print))
++			print_stats(blkif);
++	}
++
++	if (log_stats)
++		print_stats(blkif);
++	if (debug_lvl)
++		printk(KERN_DEBUG "%s: exiting\n", current->comm);
++
++	blkif->xenblkd = NULL;
++	blkif_put(blkif);
++
++	return 0;
++}
++
++/******************************************************************
++ * COMPLETION CALLBACK -- Called by user level ioctl()
++ */
++
++static int blktap_read_ufe_ring(tap_blkif_t *info)
++{
++	/* This is called to read responses from the UFE ring. */
++	RING_IDX i, j, rp;
++	blkif_response_t *resp;
++	blkif_t *blkif=NULL;
++	int pending_idx, usr_idx, mmap_idx;
++	pending_req_t *pending_req;
++	
++	if (!info)
++		return 0;
++
++	/* We currently only forward packets in INTERCEPT_FE mode. */
++	if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE))
++		return 0;
++
++	/* for each outstanding message on the UFEring  */
++	rp = info->ufe_ring.sring->rsp_prod;
++	rmb();
++        
++	for (i = info->ufe_ring.rsp_cons; i != rp; i++) {
++		blkif_response_t res;
++		resp = RING_GET_RESPONSE(&info->ufe_ring, i);
++		memcpy(&res, resp, sizeof(res));
++		mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */
++		++info->ufe_ring.rsp_cons;
++
++		/*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/
++		usr_idx = (int)res.id;
++		pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
++		mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
++
++		if ( (mmap_idx >= mmap_alloc) || 
++		   (ID_TO_IDX(info->idx_map[usr_idx]) >= MAX_PENDING_REQS) )
++			WPRINTK("Incorrect req map"
++			       "[%d], internal map [%d,%d (%d)]\n", 
++			       usr_idx, mmap_idx, 
++			       ID_TO_IDX(info->idx_map[usr_idx]),
++			       MASK_PEND_IDX(
++				       ID_TO_IDX(info->idx_map[usr_idx])));
++
++		pending_req = &pending_reqs[mmap_idx][pending_idx];
++		blkif = pending_req->blkif;
++
++		for (j = 0; j < pending_req->nr_pages; j++) {
++
++			unsigned long uvaddr;
++			struct page *pg;
++			int offset;
++
++			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, j);
++
++			pg = idx_to_page(mmap_idx, pending_idx, j);
++			ClearPageReserved(pg);
++			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
++			info->foreign_map.map[offset] = NULL;
++		}
++		fast_flush_area(pending_req, pending_idx, usr_idx, info->minor);
++		info->idx_map[usr_idx] = INVALID_REQ;
++		make_response(blkif, pending_req->id, res.operation,
++			      res.status);
++		blkif_put(pending_req->blkif);
++		free_req(pending_req);
++	}
++		
++	return 0;
++}
++
++
++/******************************************************************************
++ * NOTIFICATION FROM GUEST OS.
++ */
++
++static void blkif_notify_work(blkif_t *blkif)
++{
++	blkif->waiting_reqs = 1;
++	wake_up(&blkif->wq);
++}
++
++irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	blkif_notify_work(dev_id);
++	return IRQ_HANDLED;
++}
++
++
++
++/******************************************************************
++ * DOWNWARD CALLS -- These interface with the block-device layer proper.
++ */
++static int print_dbug = 1;
++static int do_block_io_op(blkif_t *blkif)
++{
++	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
++	blkif_request_t req;
++	pending_req_t *pending_req;
++	RING_IDX rc, rp;
++	int more_to_do = 0;
++	tap_blkif_t *info;
++
++	rc = blk_rings->common.req_cons;
++	rp = blk_rings->common.sring->req_prod;
++	rmb(); /* Ensure we see queued requests up to 'rp'. */
++
++	/*Check blkif has corresponding UE ring*/
++	if (blkif->dev_num < 0) {
++		/*oops*/
++		if (print_dbug) {
++			WPRINTK("Corresponding UE " 
++			       "ring does not exist!\n");
++			print_dbug = 0; /*We only print this message once*/
++		}
++		return 0;
++	}
++
++	info = tapfds[blkif->dev_num];
++
++	if (blkif->dev_num > MAX_TAP_DEV || !info ||
++	    !test_bit(0, &info->dev_inuse)) {
++		if (print_dbug) {
++			WPRINTK("Can't get UE info!\n");
++			print_dbug = 0;
++		}
++		return 0;
++	}
++
++	while (rc != rp) {
++		
++		if (RING_FULL(&info->ufe_ring)) {
++			WPRINTK("RING_FULL! More to do\n");
++			more_to_do = 1;
++			break;
++		}
++
++		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) {
++			WPRINTK("RING_REQUEST_CONS_OVERFLOW!"
++			       " More to do\n");
++			more_to_do = 1;
++			break;		
++		}
++
++		if (kthread_should_stop()) {
++			more_to_do = 1;
++			break;
++		}
++
++		pending_req = alloc_req();
++		if (NULL == pending_req) {
++			blkif->st_oo_req++;
++			more_to_do = 1;
++			break;
++		}
++
++		switch (blkif->blk_protocol) {
++		case BLKIF_PROTOCOL_NATIVE:
++			memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc),
++			       sizeof(req));
++			break;
++		case BLKIF_PROTOCOL_X86_32:
++			blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc));
++			break;
++		case BLKIF_PROTOCOL_X86_64:
++			blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc));
++			break;
++		default:
++			BUG();
++		}
++		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++;
++			dispatch_rw_block_io(blkif, &req, pending_req);
++			break;
++
++		case BLKIF_OP_WRITE:
++			blkif->st_wr_req++;
++			dispatch_rw_block_io(blkif, &req, pending_req);
++			break;
++
++		default:
++			/* A good sign something is wrong: sleep for a while to
++			 * avoid excessive CPU consumption by a bad guest. */
++			msleep(1);
++			WPRINTK("unknown operation [%d]\n",
++				req.operation);
++			make_response(blkif, req.id, req.operation,
++				      BLKIF_RSP_ERROR);
++			free_req(pending_req);
++			break;
++		}
++
++		/* Yield point for this unbounded loop. */
++		cond_resched();
++	}
++		
++	blktap_kick_user(blkif->dev_num);
++
++	return more_to_do;
++}
++
++static void dispatch_rw_block_io(blkif_t *blkif,
++				 blkif_request_t *req,
++				 pending_req_t *pending_req)
++{
++	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
++	int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
++	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
++	unsigned int nseg;
++	int ret, i, nr_sects = 0;
++	tap_blkif_t *info;
++	blkif_request_t *target;
++	int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
++	int usr_idx;
++	uint16_t mmap_idx = pending_req->mem_idx;
++	struct mm_struct *mm;
++	struct vm_area_struct *vma = NULL;
++
++	if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
++		goto fail_response;
++
++	info = tapfds[blkif->dev_num];
++	if (info == NULL)
++		goto fail_response;
++
++	/* Check we have space on user ring - should never fail. */
++	usr_idx = GET_NEXT_REQ(info->idx_map);
++	if (usr_idx == INVALID_REQ) {
++		BUG();
++		goto fail_response;
++	}
++
++	/* Check that number of segments is sane. */
++	nseg = req->nr_segments;
++	if ( unlikely(nseg == 0) || 
++	    unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) {
++		WPRINTK("Bad number of segments in request (%d)\n", nseg);
++		goto fail_response;
++	}
++	
++	/* Make sure userspace is ready. */
++	if (!info->ring_ok) {
++		WPRINTK("blktap: ring not ready for requests!\n");
++		goto fail_response;
++	}
++	smp_rmb();
++
++	if (RING_FULL(&info->ufe_ring)) {
++		WPRINTK("blktap: fe_ring is full, can't add "
++			"IO Request will be dropped. %d %d\n",
++			RING_SIZE(&info->ufe_ring),
++			RING_SIZE(&blkif->blk_rings.common));
++		goto fail_response;
++	}
++
++	pending_req->blkif     = blkif;
++	pending_req->id        = req->id;
++	pending_req->operation = operation;
++	pending_req->status    = BLKIF_RSP_OKAY;
++	pending_req->nr_pages  = nseg;
++	op = 0;
++	mm = info->mm;
++	if (!xen_feature(XENFEAT_auto_translated_physmap))
++		down_write(&mm->mmap_sem);
++	for (i = 0; i < nseg; i++) {
++		unsigned long uvaddr;
++		unsigned long kvaddr;
++		uint64_t ptep;
++		uint32_t flags;
++
++		uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
++		kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
++
++		flags = GNTMAP_host_map;
++		if (operation == WRITE)
++			flags |= GNTMAP_readonly;
++		gnttab_set_map_op(&map[op], kvaddr, flags,
++				  req->seg[i].gref, blkif->domid);
++		op++;
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* Now map it to user. */
++			ret = create_lookup_pte_addr(mm, uvaddr, &ptep);
++			if (ret) {
++				up_write(&mm->mmap_sem);
++				WPRINTK("Couldn't get a pte addr!\n");
++				goto fail_flush;
++			}
++
++			flags = GNTMAP_host_map | GNTMAP_application_map
++				| GNTMAP_contains_pte;
++			if (operation == WRITE)
++				flags |= GNTMAP_readonly;
++			gnttab_set_map_op(&map[op], ptep, flags,
++					  req->seg[i].gref, blkif->domid);
++			op++;
++		}
++
++		nr_sects += (req->seg[i].last_sect - 
++			     req->seg[i].first_sect + 1);
++	}
++
++	ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op);
++	BUG_ON(ret);
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		up_write(&mm->mmap_sem);
++
++		for (i = 0; i < (nseg*2); i+=2) {
++			unsigned long uvaddr;
++			unsigned long offset;
++			struct page *pg;
++
++			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2);
++
++			if (unlikely(map[i].status != 0)) {
++				WPRINTK("invalid kernel buffer -- "
++					"could not remap it\n");
++                if(map[i].status == GNTST_eagain)
++                    WPRINTK("grant GNTST_eagain: please use blktap2\n");
++				ret |= 1;
++				map[i].handle = INVALID_GRANT_HANDLE;
++			}
++
++			if (unlikely(map[i+1].status != 0)) {
++				WPRINTK("invalid user buffer -- "
++					"could not remap it\n");
++				ret |= 1;
++				map[i+1].handle = INVALID_GRANT_HANDLE;
++			}
++
++			pending_handle(mmap_idx, pending_idx, i/2).kernel 
++				= map[i].handle;
++			pending_handle(mmap_idx, pending_idx, i/2).user   
++				= map[i+1].handle;
++
++			if (ret)
++				continue;
++
++			pg = idx_to_page(mmap_idx, pending_idx, i/2);
++			set_phys_to_machine(page_to_pfn(pg),
++					    FOREIGN_FRAME(map[i].dev_bus_addr
++							  >> PAGE_SHIFT));
++			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
++			info->foreign_map.map[offset] = pg;
++		}
++	} else {
++		for (i = 0; i < nseg; i++) {
++			unsigned long uvaddr;
++			unsigned long offset;
++			struct page *pg;
++
++			uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i);
++
++			if (unlikely(map[i].status != 0)) {
++				WPRINTK("invalid kernel buffer -- "
++					"could not remap it\n");
++                if(map[i].status == GNTST_eagain)
++                    WPRINTK("grant GNTST_eagain: please use blktap2\n");
++				ret |= 1;
++				map[i].handle = INVALID_GRANT_HANDLE;
++			}
++
++			pending_handle(mmap_idx, pending_idx, i).kernel 
++				= map[i].handle;
++
++			if (ret)
++				continue;
++
++			offset = (uvaddr - info->rings_vstart) >> PAGE_SHIFT;
++			pg = idx_to_page(mmap_idx, pending_idx, i);
++			info->foreign_map.map[offset] = pg;
++		}
++	}
++
++	if (ret)
++		goto fail_flush;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		down_write(&mm->mmap_sem);
++	/* Mark mapped pages as reserved: */
++	for (i = 0; i < req->nr_segments; i++) {
++		struct page *pg;
++
++		pg = idx_to_page(mmap_idx, pending_idx, i);
++		SetPageReserved(pg);
++		if (xen_feature(XENFEAT_auto_translated_physmap)) {
++			unsigned long uvaddr = MMAP_VADDR(info->user_vstart,
++							  usr_idx, i);
++			if (vma && uvaddr >= vma->vm_end) {
++				vma = vma->vm_next;
++				if (vma &&
++				    (uvaddr < vma->vm_start ||
++				     uvaddr >= vma->vm_end))
++					vma = NULL;
++			}
++			if (vma == NULL) {
++				vma = find_vma(mm, uvaddr);
++				/* this virtual area was already munmapped.
++				   so skip to next page */
++				if (!vma)
++					continue;
++			}
++			ret = vm_insert_page(vma, uvaddr, pg);
++			if (ret) {
++				up_write(&mm->mmap_sem);
++				goto fail_flush;
++			}
++		}
++	}
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		up_write(&mm->mmap_sem);
++	
++	/*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
++	info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
++
++	blkif_get(blkif);
++	/* Finally, write the request message to the user ring. */
++	target = RING_GET_REQUEST(&info->ufe_ring,
++				  info->ufe_ring.req_prod_pvt);
++	memcpy(target, req, sizeof(*req));
++	target->id = usr_idx;
++	wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
++	info->ufe_ring.req_prod_pvt++;
++
++	if (operation == READ)
++		blkif->st_rd_sect += nr_sects;
++	else if (operation == WRITE)
++		blkif->st_wr_sect += nr_sects;
++
++	return;
++
++ fail_flush:
++	WPRINTK("Reached Fail_flush\n");
++	fast_flush_area(pending_req, pending_idx, usr_idx, blkif->dev_num);
++ fail_response:
++	make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
++	free_req(pending_req);
++	msleep(1); /* back off a bit */
++}
++
++
++
++/******************************************************************
++ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
++ */
++
++
++static void make_response(blkif_t *blkif, u64 id,
++                          unsigned short op, int st)
++{
++	blkif_response_t  resp;
++	unsigned long     flags;
++	blkif_back_rings_t *blk_rings = &blkif->blk_rings;
++	int more_to_do = 0;
++	int notify;
++
++	resp.id        = id;
++	resp.operation = op;
++	resp.status    = st;
++
++	spin_lock_irqsave(&blkif->blk_ring_lock, flags);
++	/* Place on the response ring for the relevant domain. */
++	switch (blkif->blk_protocol) {
++	case BLKIF_PROTOCOL_NATIVE:
++		memcpy(RING_GET_RESPONSE(&blk_rings->native,
++					 blk_rings->native.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	case BLKIF_PROTOCOL_X86_32:
++		memcpy(RING_GET_RESPONSE(&blk_rings->x86_32,
++					 blk_rings->x86_32.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	case BLKIF_PROTOCOL_X86_64:
++		memcpy(RING_GET_RESPONSE(&blk_rings->x86_64,
++					 blk_rings->x86_64.rsp_prod_pvt),
++		       &resp, sizeof(resp));
++		break;
++	default:
++		BUG();
++	}
++	blk_rings->common.rsp_prod_pvt++;
++	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
++
++	if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) {
++		/*
++		 * Tail check for pending requests. Allows frontend to avoid
++		 * notifications if requests are already in flight (lower
++		 * overheads and promotes batching).
++		 */
++		RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do);
++	} else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) {
++		more_to_do = 1;
++	}
++
++	spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
++	if (more_to_do)
++		blkif_notify_work(blkif);
++	if (notify)
++		notify_remote_via_irq(blkif->irq);
++}
++
++static int __init blkif_init(void)
++{
++	int i, ret;
++	struct class *class;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	INIT_LIST_HEAD(&pending_free);
++        for(i = 0; i < 2; i++) {
++		ret = req_increase();
++		if (ret)
++			break;
++	}
++	if (i == 0)
++		return ret;
++
++	tap_blkif_interface_init();
++
++	alloc_pending_reqs = 0;
++
++	tap_blkif_xenbus_init();
++
++	/* Dynamically allocate a major for this device */
++	ret = register_chrdev(0, "blktap", &blktap_fops);
++
++	if (ret < 0) {
++		WPRINTK("Couldn't register /dev/xen/blktap\n");
++		return -ENOMEM;
++	}	
++	
++	blktap_major = ret;
++
++	/* tapfds[0] is always NULL */
++	blktap_next_minor++;
++
++	DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i);
++
++	/* Make sure the xen class exists */
++	if ((class = get_xen_class()) != NULL) {
++		/*
++		 * This will allow udev to create the blktap ctrl device.
++		 * We only want to create blktap0 first.  We don't want
++		 * to flood the sysfs system with needless blktap devices.
++		 * We only create the device when a request of a new device is
++		 * made.
++		 */
++		class_device_create(class, NULL,
++				    MKDEV(blktap_major, 0), NULL,
++				    "blktap0");
++	} else {
++		/* this is bad, but not fatal */
++		WPRINTK("blktap: sysfs xen_class not created\n");
++	}
++
++	DPRINTK("Blktap device successfully created\n");
++
++	return 0;
++}
++
++module_init(blkif_init);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap/common.h	2008-09-15 13:40:15.000000000 +0200
+@@ -0,0 +1,122 @@
++/* 
++ * 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 __BLKIF__BACKEND__COMMON_H__
++#define __BLKIF__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/blkdev.h>
++#include <linux/vmalloc.h>
++#include <asm/io.h>
++#include <asm/setup.h>
++#include <asm/pgalloc.h>
++#include <xen/evtchn.h>
++#include <asm/hypervisor.h>
++#include <xen/blkif.h>
++#include <xen/gnttab.h>
++#include <xen/driver_util.h>
++
++#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \
++                                    __FILE__ , __LINE__ , ## _a )
++
++#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
++
++struct backend_info;
++
++typedef struct blkif_st {
++	/* Unique identifier for this interface. */
++	domid_t           domid;
++	unsigned int      handle;
++	/* Physical parameters of the comms window. */
++	unsigned int      irq;
++	/* Comms information. */
++	enum blkif_protocol blk_protocol;
++	blkif_back_rings_t blk_rings;
++	struct vm_struct *blk_ring_area;
++	/* Back pointer to the backend_info. */
++	struct backend_info *be;
++	/* Private fields. */
++	spinlock_t       blk_ring_lock;
++	atomic_t         refcnt;
++
++	wait_queue_head_t   wq;
++	struct task_struct  *xenblkd;
++	unsigned int        waiting_reqs;
++	request_queue_t     *plug;
++
++	/* statistics */
++	unsigned long       st_print;
++	int                 st_rd_req;
++	int                 st_wr_req;
++	int                 st_oo_req;
++	int                 st_rd_sect;
++	int                 st_wr_sect;
++
++	wait_queue_head_t waiting_to_free;
++
++	grant_handle_t shmem_handle;
++	grant_ref_t    shmem_ref;
++	
++	int		dev_num;
++	uint64_t        sectors;
++} blkif_t;
++
++blkif_t *tap_alloc_blkif(domid_t domid);
++void tap_blkif_free(blkif_t *blkif);
++void tap_blkif_kmem_cache_free(blkif_t *blkif);
++int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
++		  unsigned int evtchn);
++void tap_blkif_unmap(blkif_t *blkif);
++
++#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
++#define blkif_put(_b)					\
++	do {						\
++		if (atomic_dec_and_test(&(_b)->refcnt))	\
++			wake_up(&(_b)->waiting_to_free);\
++	} while (0)
++
++
++struct phys_req {
++	unsigned short       dev;
++	unsigned short       nr_sects;
++	struct block_device *bdev;
++	blkif_sector_t       sector_number;
++};
++
++void tap_blkif_interface_init(void);
++
++void tap_blkif_xenbus_init(void);
++
++irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++int tap_blkif_schedule(void *arg);
++
++int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif);
++void signal_tapdisk(int idx);
++
++#endif /* __BLKIF__BACKEND__COMMON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,185 @@
++/******************************************************************************
++ * drivers/xen/blktap/interface.c
++ * 
++ * Block-device interface management.
++ * 
++ * Copyright (c) 2004, Keir Fraser
++ *
++ * 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 "common.h"
++#include <xen/evtchn.h>
++#include <linux/delay.h>
++
++static kmem_cache_t *blkif_cachep;
++
++blkif_t *tap_alloc_blkif(domid_t domid)
++{
++	blkif_t *blkif;
++
++	blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
++	if (!blkif)
++		return ERR_PTR(-ENOMEM);
++
++	memset(blkif, 0, sizeof(*blkif));
++	blkif->domid = domid;
++	spin_lock_init(&blkif->blk_ring_lock);
++	atomic_set(&blkif->refcnt, 1);
++	init_waitqueue_head(&blkif->wq);
++	blkif->st_print = jiffies;
++	init_waitqueue_head(&blkif->waiting_to_free);
++
++	return blkif;
++}
++
++static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
++{
++	struct gnttab_map_grant_ref op;
++
++	gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
++			  GNTMAP_host_map, shared_page, blkif->domid);
++
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status) {
++		DPRINTK(" Grant table operation failure !\n");
++		return op.status;
++	}
++
++	blkif->shmem_ref = shared_page;
++	blkif->shmem_handle = op.handle;
++
++	return 0;
++}
++
++static void unmap_frontend_page(blkif_t *blkif)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
++			    GNTMAP_host_map, blkif->shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++}
++
++int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, 
++		  unsigned int evtchn)
++{
++	int err;
++
++	/* Already connected through? */
++	if (blkif->irq)
++		return 0;
++
++	if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
++		return -ENOMEM;
++
++	err = map_frontend_page(blkif, shared_page);
++	if (err) {
++		free_vm_area(blkif->blk_ring_area);
++		return err;
++	}
++
++	switch (blkif->blk_protocol) {
++	case BLKIF_PROTOCOL_NATIVE:
++	{
++		blkif_sring_t *sring;
++		sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE);
++		break;
++	}
++	case BLKIF_PROTOCOL_X86_32:
++	{
++		blkif_x86_32_sring_t *sring_x86_32;
++		sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE);
++		break;
++	}
++	case BLKIF_PROTOCOL_X86_64:
++	{
++		blkif_x86_64_sring_t *sring_x86_64;
++		sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr;
++		BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE);
++		break;
++	}
++	default:
++		BUG();
++	}
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++		blkif->domid, evtchn, tap_blkif_be_int,
++		0, "blkif-backend", blkif);
++	if (err < 0) {
++		unmap_frontend_page(blkif);
++		free_vm_area(blkif->blk_ring_area);
++		blkif->blk_rings.common.sring = NULL;
++		return err;
++	}
++	blkif->irq = err;
++
++	return 0;
++}
++
++void tap_blkif_unmap(blkif_t *blkif)
++{
++	if (blkif->irq) {
++		unbind_from_irqhandler(blkif->irq, blkif);
++		blkif->irq = 0;
++	}
++	if (blkif->blk_rings.common.sring) {
++		unmap_frontend_page(blkif);
++		free_vm_area(blkif->blk_ring_area);
++		blkif->blk_rings.common.sring = NULL;
++	}
++}
++
++void tap_blkif_free(blkif_t *blkif)
++{
++	atomic_dec(&blkif->refcnt);
++	wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0);
++	atomic_inc(&blkif->refcnt);
++
++	tap_blkif_unmap(blkif);
++}
++
++void tap_blkif_kmem_cache_free(blkif_t *blkif)
++{
++	if (!atomic_dec_and_test(&blkif->refcnt))
++		BUG();
++	kmem_cache_free(blkif_cachep, blkif);
++}
++
++void __init tap_blkif_interface_init(void)
++{
++	blkif_cachep = kmem_cache_create("blktapif_cache", sizeof(blkif_t), 
++					 0, 0, NULL, NULL);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap/xenbus.c	2008-09-15 13:40:15.000000000 +0200
+@@ -0,0 +1,479 @@
++/* drivers/xen/blktap/xenbus.c
++ *
++ * Xenbus code for blktap
++ *
++ * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield
++ *
++ * Based on the blkback xenbus code:
++ *
++ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
++ * Copyright (C) 2005 XenSource Ltd
++ *
++ * 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 <xen/xenbus.h>
++#include "common.h"
++
++
++struct backend_info
++{
++	struct xenbus_device *dev;
++	blkif_t *blkif;
++	struct xenbus_watch backend_watch;
++	int xenbus_id;
++	int group_added;
++};
++
++
++static void connect(struct backend_info *);
++static int connect_ring(struct backend_info *);
++static int blktap_remove(struct xenbus_device *dev);
++static int blktap_probe(struct xenbus_device *dev,
++			 const struct xenbus_device_id *id);
++static void tap_backend_changed(struct xenbus_watch *, const char **,
++			    unsigned int);
++static void tap_frontend_changed(struct xenbus_device *dev,
++			     enum xenbus_state frontend_state);
++
++static int strsep_len(const char *str, char c, unsigned int len)
++{
++        unsigned int i;
++
++        for (i = 0; str[i]; i++)
++                if (str[i] == c) {
++                        if (len == 0)
++                                return i;
++                        len--;
++                }
++        return (len == 0) ? i : -ERANGE;
++}
++
++static long get_id(const char *str)
++{
++        int len,end;
++        const char *ptr;
++        char *tptr, num[10];
++	
++        len = strsep_len(str, '/', 2);
++        end = strlen(str);
++        if ( (len < 0) || (end < 0) ) return -1;
++	
++        ptr = str + len + 1;
++        strncpy(num,ptr,end - len);
++        tptr = num + (end - (len + 1));
++        *tptr = '\0';
++	DPRINTK("Get_id called for %s (%s)\n",str,num);
++	
++        return simple_strtol(num, NULL, 10);
++}				
++
++static int blktap_name(blkif_t *blkif, char *buf)
++{
++	char *devpath, *devname;
++	struct xenbus_device *dev = blkif->be->dev;
++
++	devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
++	if (IS_ERR(devpath)) 
++		return PTR_ERR(devpath);
++	
++	if ((devname = strstr(devpath, "/dev/")) != NULL)
++		devname += strlen("/dev/");
++	else
++		devname  = devpath;
++
++	snprintf(buf, TASK_COMM_LEN, "blktap.%d.%s", blkif->domid, devname);
++	kfree(devpath);
++	
++	return 0;
++}
++
++/****************************************************************
++ *  sysfs interface for I/O requests of blktap device
++ */
++
++#define VBD_SHOW(name, format, args...)					\
++	static ssize_t show_##name(struct device *_dev,			\
++				   struct device_attribute *attr,	\
++				   char *buf)				\
++	{								\
++		struct xenbus_device *dev = to_xenbus_device(_dev);	\
++		struct backend_info *be = dev->dev.driver_data;		\
++									\
++		return sprintf(buf, format, ##args);			\
++	}								\
++	static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
++
++VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
++VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
++VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
++VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
++VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
++
++static struct attribute *tapstat_attrs[] = {
++	&dev_attr_oo_req.attr,
++	&dev_attr_rd_req.attr,
++	&dev_attr_wr_req.attr,
++	&dev_attr_rd_sect.attr,
++	&dev_attr_wr_sect.attr,
++	NULL
++};
++
++static struct attribute_group tapstat_group = {
++	.name = "statistics",
++	.attrs = tapstat_attrs,
++};
++
++int xentap_sysfs_addif(struct xenbus_device *dev)
++{
++	int err;
++	struct backend_info *be = dev->dev.driver_data;
++	err = sysfs_create_group(&dev->dev.kobj, &tapstat_group);
++	if (!err)
++		be->group_added = 1;
++	return err;
++}
++
++void xentap_sysfs_delif(struct xenbus_device *dev)
++{
++	struct backend_info *be = dev->dev.driver_data;
++	sysfs_remove_group(&dev->dev.kobj, &tapstat_group);
++	be->group_added = 0;
++}
++
++static int blktap_remove(struct xenbus_device *dev)
++{
++	struct backend_info *be = dev->dev.driver_data;
++
++	if (be->group_added)
++		xentap_sysfs_delif(be->dev);
++	if (be->backend_watch.node) {
++		unregister_xenbus_watch(&be->backend_watch);
++		kfree(be->backend_watch.node);
++		be->backend_watch.node = NULL;
++	}
++	if (be->blkif) {
++		if (be->blkif->xenblkd)
++			kthread_stop(be->blkif->xenblkd);
++		signal_tapdisk(be->blkif->dev_num);
++		tap_blkif_free(be->blkif);
++		tap_blkif_kmem_cache_free(be->blkif);
++		be->blkif = NULL;
++	}
++	kfree(be);
++	dev->dev.driver_data = NULL;
++	return 0;
++}
++
++static void tap_update_blkif_status(blkif_t *blkif)
++{ 
++	int err;
++	char name[TASK_COMM_LEN];
++
++	/* Not ready to connect? */
++	if(!blkif->irq || !blkif->sectors) {
++		return;
++	} 
++
++	/* Already connected? */
++	if (blkif->be->dev->state == XenbusStateConnected)
++		return;
++
++	/* Attempt to connect: exit if we fail to. */
++	connect(blkif->be);
++	if (blkif->be->dev->state != XenbusStateConnected)
++		return;
++
++	err = blktap_name(blkif, name);
++	if (err) {
++		xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
++		return;
++	}
++
++	if (!blkif->be->group_added) {
++		err = xentap_sysfs_addif(blkif->be->dev);
++		if (err) {
++			xenbus_dev_fatal(blkif->be->dev, err, 
++					 "creating sysfs entries");
++			return;
++		}
++	}
++
++	blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name);
++	if (IS_ERR(blkif->xenblkd)) {
++		err = PTR_ERR(blkif->xenblkd);
++		blkif->xenblkd = NULL;
++		xenbus_dev_fatal(blkif->be->dev, err, "start xenblkd");
++		WPRINTK("Error starting thread\n");
++	}
++}
++
++/**
++ * Entry point to this code when a new device is created.  Allocate
++ * the basic structures, and watch the store waiting for the
++ * user-space program to tell us the physical device info.  Switch to
++ * InitWait.
++ */
++static int blktap_probe(struct xenbus_device *dev,
++			 const struct xenbus_device_id *id)
++{
++	int err;
++	struct backend_info *be = kzalloc(sizeof(struct backend_info),
++					  GFP_KERNEL);
++	if (!be) {
++		xenbus_dev_fatal(dev, -ENOMEM,
++				 "allocating backend structure");
++		return -ENOMEM;
++	}
++
++	be->dev = dev;
++	dev->dev.driver_data = be;
++	be->xenbus_id = get_id(dev->nodename);
++
++	be->blkif = tap_alloc_blkif(dev->otherend_id);
++	if (IS_ERR(be->blkif)) {
++		err = PTR_ERR(be->blkif);
++		be->blkif = NULL;
++		xenbus_dev_fatal(dev, err, "creating block interface");
++		goto fail;
++	}
++
++	/* setup back pointer */
++	be->blkif->be = be;
++	be->blkif->sectors = 0;
++
++	/* set a watch on disk info, waiting for userspace to update details*/
++	err = xenbus_watch_path2(dev, dev->nodename, "info",
++				 &be->backend_watch, tap_backend_changed);
++	if (err)
++		goto fail;
++	
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err)
++		goto fail;
++	return 0;
++
++fail:
++	DPRINTK("blktap probe failed\n");
++	blktap_remove(dev);
++	return err;
++}
++
++
++/**
++ * Callback received when the user space code has placed the device
++ * information in xenstore. 
++ */
++static void tap_backend_changed(struct xenbus_watch *watch,
++			    const char **vec, unsigned int len)
++{
++	int err;
++	unsigned long info;
++	struct backend_info *be
++		= container_of(watch, struct backend_info, backend_watch);
++	struct xenbus_device *dev = be->dev;
++	
++	/** 
++	 * Check to see whether userspace code has opened the image 
++	 * and written sector
++	 * and disk info to xenstore
++	 */
++	err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info, 
++			    NULL);
++	if (XENBUS_EXIST_ERR(err))
++		return;
++	if (err) {
++		xenbus_dev_error(dev, err, "getting info");
++		return;
++	}
++
++	DPRINTK("Userspace update on disk info, %lu\n",info);
++
++	err = xenbus_gather(XBT_NIL, dev->nodename, "sectors", "%llu", 
++			    &be->blkif->sectors, NULL);
++
++	/* Associate tap dev with domid*/
++	be->blkif->dev_num = dom_to_devid(be->blkif->domid, be->xenbus_id, 
++					  be->blkif);
++	DPRINTK("Thread started for domid [%d], connecting disk\n", 
++		be->blkif->dev_num);
++
++	tap_update_blkif_status(be->blkif);
++}
++
++/**
++ * Callback received when the frontend's state changes.
++ */
++static void tap_frontend_changed(struct xenbus_device *dev,
++			     enum xenbus_state frontend_state)
++{
++	struct backend_info *be = dev->dev.driver_data;
++	int err;
++
++	DPRINTK("\n");
++
++	switch (frontend_state) {
++	case XenbusStateInitialising:
++		if (dev->state == XenbusStateClosed) {
++			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
++			       __FUNCTION__, dev->nodename);
++			xenbus_switch_state(dev, XenbusStateInitWait);
++		}
++		break;
++
++	case XenbusStateInitialised:
++	case XenbusStateConnected:
++		/* Ensure we connect even when two watches fire in 
++		   close successsion and we miss the intermediate value 
++		   of frontend_state. */
++		if (dev->state == XenbusStateConnected)
++			break;
++
++		err = connect_ring(be);
++		if (err)
++			break;
++		tap_update_blkif_status(be->blkif);
++		break;
++
++	case XenbusStateClosing:
++		if (be->blkif->xenblkd) {
++			kthread_stop(be->blkif->xenblkd);
++			be->blkif->xenblkd = NULL;
++		}
++		tap_blkif_free(be->blkif);
++		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;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++				 frontend_state);
++		break;
++	}
++}
++
++
++/**
++ * Switch to Connected state.
++ */
++static void connect(struct backend_info *be)
++{
++	int err;
++
++	struct xenbus_device *dev = be->dev;
++
++	err = xenbus_switch_state(dev, XenbusStateConnected);
++	if (err)
++		xenbus_dev_fatal(dev, err, "switching to Connected state",
++				 dev->nodename);
++
++	return;
++}
++
++
++static int connect_ring(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	unsigned long ring_ref;
++	unsigned int evtchn;
++	char protocol[64];
++	int err;
++
++	DPRINTK("%s\n", dev->otherend);
++
++	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-ref and event-channel",
++				 dev->otherend);
++		return err;
++	}
++
++	be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
++	err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
++			    "%63s", protocol, NULL);
++	if (err)
++		strcpy(protocol, "unspecified, assuming native");
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
++	else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
++		be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
++	else {
++		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
++		return -1;
++	}
++	printk(KERN_INFO
++	       "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n",
++	       ring_ref, evtchn, be->blkif->blk_protocol, protocol);
++
++	/* Map the shared frame, irq etc. */
++	err = tap_blkif_map(be->blkif, ring_ref, evtchn);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u",
++				 ring_ref, evtchn);
++		return err;
++	} 
++
++	return 0;
++}
++
++
++/* ** Driver Registration ** */
++
++
++static const struct xenbus_device_id blktap_ids[] = {
++	{ "tap" },
++	{ "" }
++};
++
++
++static struct xenbus_driver blktap = {
++	.name = "tap",
++	.owner = THIS_MODULE,
++	.ids = blktap_ids,
++	.probe = blktap_probe,
++	.remove = blktap_remove,
++	.otherend_changed = tap_frontend_changed
++};
++
++
++void tap_blkif_xenbus_init(void)
++{
++	xenbus_register_backend(&blktap);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/Makefile	2009-05-29 10:25:53.000000000 +0200
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap.o
++
++blktap-objs := control.o ring.o wait_queue.o device.o request.o sysfs.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/blktap.h	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,254 @@
++#ifndef _BLKTAP_H_
++#define _BLKTAP_H_
++
++#include <linux/fs.h>
++#include <linux/poll.h>
++#include <linux/cdev.h>
++#include <linux/init.h>
++#include <linux/scatterlist.h>
++#include <xen/blkif.h>
++#include <xen/gnttab.h>
++
++//#define ENABLE_PASSTHROUGH
++
++extern int blktap_debug_level;
++
++#define BTPRINTK(level, tag, force, _f, _a...)				\
++	do {								\
++		if (blktap_debug_level > level &&			\
++		    (force || printk_ratelimit()))			\
++			printk(tag "%s: " _f, __func__, ##_a);		\
++	} while (0)
++
++#define BTDBG(_f, _a...)             BTPRINTK(8, KERN_DEBUG, 1, _f, ##_a)
++#define BTINFO(_f, _a...)            BTPRINTK(0, KERN_INFO, 0, _f, ##_a)
++#define BTWARN(_f, _a...)            BTPRINTK(0, KERN_WARNING, 0, _f, ##_a)
++#define BTERR(_f, _a...)             BTPRINTK(0, KERN_ERR, 0, _f, ##_a)
++
++#define MAX_BLKTAP_DEVICE            256
++
++#define BLKTAP_CONTROL               1
++#define BLKTAP_RING_FD               2
++#define BLKTAP_RING_VMA              3
++#define BLKTAP_DEVICE                4
++#define BLKTAP_SYSFS                 5
++#define BLKTAP_PAUSE_REQUESTED       6
++#define BLKTAP_PAUSED                7
++#define BLKTAP_SHUTDOWN_REQUESTED    8
++#define BLKTAP_PASSTHROUGH           9
++#define BLKTAP_DEFERRED              10
++
++/* blktap IOCTLs: */
++#define BLKTAP2_IOCTL_KICK_FE        1
++#define BLKTAP2_IOCTL_ALLOC_TAP	     200
++#define BLKTAP2_IOCTL_FREE_TAP       201
++#define BLKTAP2_IOCTL_CREATE_DEVICE  202
++#define BLKTAP2_IOCTL_SET_PARAMS     203
++#define BLKTAP2_IOCTL_PAUSE          204
++#define BLKTAP2_IOCTL_REOPEN         205
++#define BLKTAP2_IOCTL_RESUME         206
++
++#define BLKTAP2_MAX_MESSAGE_LEN      256
++
++#define BLKTAP2_RING_MESSAGE_PAUSE   1
++#define BLKTAP2_RING_MESSAGE_RESUME  2
++#define BLKTAP2_RING_MESSAGE_CLOSE   3
++
++#define BLKTAP_REQUEST_FREE          0
++#define BLKTAP_REQUEST_PENDING       1
++
++/*
++ * The maximum number of requests that can be outstanding at any time
++ * is determined by
++ *
++ *   [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] 
++ *
++ * where mmap_alloc < MAX_DYNAMIC_MEM.
++ *
++ * TODO:
++ * mmap_alloc is initialised to 2 and should be adjustable on the fly via
++ * sysfs.
++ */
++#define BLK_RING_SIZE		__RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
++#define MAX_DYNAMIC_MEM		BLK_RING_SIZE
++#define MAX_PENDING_REQS	BLK_RING_SIZE
++#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
++#define MMAP_VADDR(_start, _req, _seg)					\
++        (_start +                                                       \
++         ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) +        \
++         ((_seg) * PAGE_SIZE))
++
++#define blktap_get(_b) (atomic_inc(&(_b)->refcnt))
++#define blktap_put(_b)					\
++	do {						\
++		if (atomic_dec_and_test(&(_b)->refcnt))	\
++			wake_up(&(_b)->wq);		\
++	} while (0)
++
++struct blktap;
++
++struct grant_handle_pair {
++	grant_handle_t                 kernel;
++	grant_handle_t                 user;
++};
++#define INVALID_GRANT_HANDLE           0xFFFF
++
++struct blktap_handle {
++	unsigned int                   ring;
++	unsigned int                   device;
++	unsigned int                   minor;
++};
++
++struct blktap_params {
++	char                           name[BLKTAP2_MAX_MESSAGE_LEN];
++	unsigned long long             capacity;
++	unsigned long                  sector_size;
++};
++
++struct blktap_device {
++	int                            users;
++	spinlock_t                     lock;
++	struct gendisk                *gd;
++
++#ifdef ENABLE_PASSTHROUGH
++	struct block_device           *bdev;
++#endif
++};
++
++struct blktap_ring {
++	struct vm_area_struct         *vma;
++	blkif_front_ring_t             ring;
++	struct vm_foreign_map          foreign_map;
++	unsigned long                  ring_vstart;
++	unsigned long                  user_vstart;
++
++	int                            response;
++
++	wait_queue_head_t              poll_wait;
++
++	dev_t                          devno;
++	struct class_device           *dev;
++	atomic_t                       sysfs_refcnt;
++	struct mutex                   sysfs_mutex;
++};
++
++struct blktap_statistics {
++	unsigned long                  st_print;
++	int                            st_rd_req;
++	int                            st_wr_req;
++	int                            st_oo_req;
++	int                            st_rd_sect;
++	int                            st_wr_sect;
++	s64                            st_rd_cnt;
++	s64                            st_rd_sum_usecs;
++	s64                            st_rd_max_usecs;
++	s64                            st_wr_cnt;
++	s64                            st_wr_sum_usecs;
++	s64                            st_wr_max_usecs;	
++};
++
++struct blktap_request {
++	uint64_t                       id;
++	uint16_t                       usr_idx;
++
++	uint8_t                        status;
++	atomic_t                       pendcnt;
++	uint8_t                        nr_pages;
++	unsigned short                 operation;
++
++	struct timeval                 time;
++	struct grant_handle_pair       handles[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	struct list_head               free_list;
++};
++
++struct blktap {
++	int                            minor;
++	pid_t                          pid;
++	atomic_t                       refcnt;
++	unsigned long                  dev_inuse;
++
++	struct blktap_params           params;
++
++	struct rw_semaphore            tap_sem;
++
++	struct blktap_ring             ring;
++	struct blktap_device           device;
++
++	int                            pending_cnt;
++	struct blktap_request         *pending_requests[MAX_PENDING_REQS];
++	struct scatterlist             sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++
++	wait_queue_head_t              wq;
++	struct list_head               deferred_queue;
++
++	struct blktap_statistics       stats;
++};
++
++extern struct blktap *blktaps[MAX_BLKTAP_DEVICE];
++
++static inline int
++blktap_active(struct blktap *tap)
++{
++	return test_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
++}
++
++static inline int
++blktap_validate_params(struct blktap *tap, struct blktap_params *params)
++{
++	/* TODO: sanity check */
++	params->name[sizeof(params->name) - 1] = '\0';
++	BTINFO("%s: capacity: %llu, sector-size: %lu\n",
++	       params->name, params->capacity, params->sector_size);
++	return 0;
++}
++
++int blktap_control_destroy_device(struct blktap *);
++
++int blktap_ring_init(int *);
++int blktap_ring_free(void);
++int blktap_ring_create(struct blktap *);
++int blktap_ring_destroy(struct blktap *);
++int blktap_ring_pause(struct blktap *);
++int blktap_ring_resume(struct blktap *);
++void blktap_ring_kick_user(struct blktap *);
++
++int blktap_sysfs_init(void);
++void blktap_sysfs_free(void);
++int blktap_sysfs_create(struct blktap *);
++int blktap_sysfs_destroy(struct blktap *);
++
++int blktap_device_init(int *);
++void blktap_device_free(void);
++int blktap_device_create(struct blktap *);
++int blktap_device_destroy(struct blktap *);
++int blktap_device_pause(struct blktap *);
++int blktap_device_resume(struct blktap *);
++void blktap_device_restart(struct blktap *);
++void blktap_device_finish_request(struct blktap *,
++				  blkif_response_t *,
++				  struct blktap_request *);
++void blktap_device_fail_pending_requests(struct blktap *);
++#ifdef ENABLE_PASSTHROUGH
++int blktap_device_enable_passthrough(struct blktap *,
++				     unsigned, unsigned);
++#endif
++
++void blktap_defer(struct blktap *);
++void blktap_run_deferred(void);
++
++int blktap_request_pool_init(void);
++void blktap_request_pool_free(void);
++int blktap_request_pool_grow(void);
++int blktap_request_pool_shrink(void);
++struct blktap_request *blktap_request_allocate(struct blktap *);
++void blktap_request_free(struct blktap *, struct blktap_request *);
++struct page *request_to_page(struct blktap_request *, int);
++
++static inline unsigned long
++request_to_kaddr(struct blktap_request *req, int seg)
++{
++	unsigned long pfn = page_to_pfn(request_to_page(req, seg));
++	return (unsigned long)pfn_to_kaddr(pfn);
++}
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/control.c	2009-12-16 11:43:21.000000000 +0100
+@@ -0,0 +1,277 @@
++#include <linux/module.h>
++#include <linux/miscdevice.h>
++
++#include "blktap.h"
++
++static DEFINE_SPINLOCK(blktap_control_lock);
++struct blktap *blktaps[MAX_BLKTAP_DEVICE];
++
++static int ring_major;
++static int device_major;
++static int blktap_control_registered;
++
++static void
++blktap_control_initialize_tap(struct blktap *tap)
++{
++	int minor = tap->minor;
++
++	memset(tap, 0, sizeof(*tap));
++	set_bit(BLKTAP_CONTROL, &tap->dev_inuse);
++	init_rwsem(&tap->tap_sem);
++	init_waitqueue_head(&tap->wq);
++	atomic_set(&tap->refcnt, 0);
++
++	tap->minor = minor;
++}
++
++static struct blktap *
++blktap_control_create_tap(void)
++{
++	int minor;
++	struct blktap *tap;
++
++	tap = kmalloc(sizeof(*tap), GFP_KERNEL);
++	if (unlikely(!tap))
++		return NULL;
++
++	blktap_control_initialize_tap(tap);
++
++	spin_lock_irq(&blktap_control_lock);
++	for (minor = 0; minor < MAX_BLKTAP_DEVICE; minor++)
++		if (!blktaps[minor])
++			break;
++
++	if (minor == MAX_BLKTAP_DEVICE) {
++		kfree(tap);
++		tap = NULL;
++		goto out;
++	}
++
++	tap->minor = minor;
++	blktaps[minor] = tap;
++
++out:
++	spin_unlock_irq(&blktap_control_lock);
++	return tap;
++}
++
++static struct blktap *
++blktap_control_allocate_tap(void)
++{
++	int err, minor;
++	struct blktap *tap;
++
++	/*
++	 * This is called only from the ioctl, which
++	 * means we should always have interrupts enabled.
++	 */
++	BUG_ON(irqs_disabled());
++
++	spin_lock_irq(&blktap_control_lock);
++
++	for (minor = 0; minor < MAX_BLKTAP_DEVICE; minor++) {
++		tap = blktaps[minor];
++		if (!tap)
++			goto found;
++
++		if (!tap->dev_inuse) {
++			blktap_control_initialize_tap(tap);
++			goto found;
++		}
++	}
++
++	tap = NULL;
++
++found:
++	spin_unlock_irq(&blktap_control_lock);
++
++	if (!tap) {
++		tap = blktap_control_create_tap();
++		if (!tap)
++			return NULL;
++	}
++
++	err = blktap_ring_create(tap);
++	if (err) {
++		BTERR("ring creation failed: %d\n", err);
++		clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
++		return NULL;
++	}
++
++	BTINFO("allocated tap %p\n", tap);
++	return tap;
++}
++
++static int
++blktap_control_ioctl(struct inode *inode, struct file *filp,
++		     unsigned int cmd, unsigned long arg)
++{
++	unsigned long dev;
++	struct blktap *tap;
++
++	switch (cmd) {
++	case BLKTAP2_IOCTL_ALLOC_TAP: {
++		struct blktap_handle h;
++
++		tap = blktap_control_allocate_tap();
++		if (!tap) {
++			BTERR("error allocating device\n");
++			return -ENOMEM;
++		}
++
++		h.ring   = ring_major;
++		h.device = device_major;
++		h.minor  = tap->minor;
++
++		if (copy_to_user((struct blktap_handle __user *)arg,
++				 &h, sizeof(h))) {
++			blktap_control_destroy_device(tap);
++			return -EFAULT;
++		}
++
++		return 0;
++	}
++
++	case BLKTAP2_IOCTL_FREE_TAP:
++		dev = arg;
++
++		if (dev > MAX_BLKTAP_DEVICE || !blktaps[dev])
++			return -EINVAL;
++
++		blktap_control_destroy_device(blktaps[dev]);
++		return 0;
++	}
++
++	return -ENOIOCTLCMD;
++}
++
++static struct file_operations blktap_control_file_operations = {
++	.owner    = THIS_MODULE,
++	.ioctl    = blktap_control_ioctl,
++};
++
++static struct miscdevice blktap_misc = {
++	.minor    = MISC_DYNAMIC_MINOR,
++	.name     = "blktap-control",
++	.fops     = &blktap_control_file_operations,
++};
++
++int
++blktap_control_destroy_device(struct blktap *tap)
++{
++	int err;
++	unsigned long inuse;
++
++	if (!tap)
++		return 0;
++
++	set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
++
++	for (;;) {
++		inuse = tap->dev_inuse;
++		err   = blktap_device_destroy(tap);
++		if (err)
++			goto wait;
++
++		inuse = tap->dev_inuse;
++		err   = blktap_ring_destroy(tap);
++		if (err)
++			goto wait;
++
++		inuse = tap->dev_inuse;
++		err   = blktap_sysfs_destroy(tap);
++		if (err)
++			goto wait;
++
++		break;
++
++	wait:
++		BTDBG("inuse: 0x%lx, dev_inuse: 0x%lx\n",
++		      inuse, tap->dev_inuse);
++		if (wait_event_interruptible(tap->wq, tap->dev_inuse != inuse))
++			break;
++	}
++
++	clear_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse);
++
++	if (tap->dev_inuse == (1UL << BLKTAP_CONTROL)) {
++		err = 0;
++		clear_bit(BLKTAP_CONTROL, &tap->dev_inuse);
++	}
++
++	return err;
++}
++
++static int __init
++blktap_control_init(void)
++{
++	int err;
++
++	err = misc_register(&blktap_misc);
++	if (err) {
++		BTERR("misc_register failed for control device");
++		return err;
++	}
++
++	blktap_control_registered = 1;
++	return 0;
++}
++
++static void
++blktap_control_free(void)
++{
++	int i;
++
++	for (i = 0; i < MAX_BLKTAP_DEVICE; i++)
++		blktap_control_destroy_device(blktaps[i]);
++
++	if (blktap_control_registered)
++		if (misc_deregister(&blktap_misc) < 0)
++			BTERR("misc_deregister failed for control device");
++}
++
++static void
++blktap_exit(void)
++{
++	blktap_control_free();
++	blktap_ring_free();
++	blktap_sysfs_free();
++	blktap_device_free();
++	blktap_request_pool_free();
++}
++
++static int __init
++blktap_init(void)
++{
++	int err;
++
++	err = blktap_request_pool_init();
++	if (err)
++		return err;
++
++	err = blktap_device_init(&device_major);
++	if (err)
++		goto fail;
++
++	err = blktap_ring_init(&ring_major);
++	if (err)
++		goto fail;
++
++	err = blktap_sysfs_init();
++	if (err)
++		goto fail;
++
++	err = blktap_control_init();
++	if (err)
++		goto fail;
++
++	return 0;
++
++fail:
++	blktap_exit();
++	return err;
++}
++
++module_init(blktap_init);
++module_exit(blktap_exit);
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,1192 @@
++#include <linux/fs.h>
++#include <linux/blkdev.h>
++#include <linux/cdrom.h>
++#include <linux/hdreg.h>
++#include <linux/module.h>
++#include <asm/tlbflush.h>
++
++#include <scsi/scsi.h>
++#include <scsi/scsi_ioctl.h>
++
++#include <xen/xenbus.h>
++#include <xen/interface/io/blkif.h>
++
++#include "blktap.h"
++
++#include "../blkback/blkback-pagemap.h"
++
++#if 0
++#define DPRINTK_IOCTL(_f, _a...) printk(KERN_ALERT _f, ## _a)
++#else
++#define DPRINTK_IOCTL(_f, _a...) ((void)0)
++#endif
++
++struct blktap_grant_table {
++	int cnt;
++	struct gnttab_map_grant_ref grants[BLKIF_MAX_SEGMENTS_PER_REQUEST * 2];
++};
++
++static int blktap_device_major;
++
++static inline struct blktap *
++dev_to_blktap(struct blktap_device *dev)
++{
++	return container_of(dev, struct blktap, device);
++}
++
++static int
++blktap_device_open(struct inode *inode, struct file *filep)
++{
++	struct blktap *tap;
++	struct blktap_device *dev = inode->i_bdev->bd_disk->private_data;
++
++	if (!dev)
++		return -ENOENT;
++
++	tap = dev_to_blktap(dev);
++	if (!blktap_active(tap) ||
++	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
++		return -ENOENT;
++
++	dev->users++;
++
++	return 0;
++}
++
++static int
++blktap_device_release(struct inode *inode, struct file *filep)
++{
++	struct blktap_device *dev = inode->i_bdev->bd_disk->private_data;
++	struct blktap *tap = dev_to_blktap(dev);
++
++	dev->users--;
++	if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
++		blktap_device_destroy(tap);
++
++	return 0;
++}
++
++static int
++blktap_device_getgeo(struct block_device *bd, struct hd_geometry *hg)
++{
++	/* We don't have real geometry info, but let's at least return
++	   values consistent with the size of the device */
++	sector_t nsect = get_capacity(bd->bd_disk);
++	sector_t cylinders = nsect;
++
++	hg->heads = 0xff;
++	hg->sectors = 0x3f;
++	sector_div(cylinders, hg->heads * hg->sectors);
++	hg->cylinders = cylinders;
++	if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect)
++		hg->cylinders = 0xffff;
++	return 0;
++}
++
++static int
++blktap_device_ioctl(struct inode *inode, struct file *filep,
++		    unsigned command, unsigned long argument)
++{
++	int i;
++
++	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
++		      command, (long)argument, inode->i_rdev);
++
++	switch (command) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++	case HDIO_GETGEO: {
++		struct block_device *bd = inode->i_bdev;
++		struct hd_geometry geo;
++		int ret;
++
++                if (!argument)
++                        return -EINVAL;
++
++		geo.start = get_start_sect(bd);
++		ret = blktap_device_getgeo(bd, &geo);
++		if (ret)
++			return ret;
++
++		if (copy_to_user((struct hd_geometry __user *)argument, &geo,
++				 sizeof(geo)))
++                        return -EFAULT;
++
++                return 0;
++	}
++#endif
++	case CDROMMULTISESSION:
++		BTDBG("FIXME: support multisession CDs later\n");
++		for (i = 0; i < sizeof(struct cdrom_multisession); i++)
++			if (put_user(0, (char __user *)(argument + i)))
++				return -EFAULT;
++		return 0;
++
++	case SCSI_IOCTL_GET_IDLUN:
++		if (!access_ok(VERIFY_WRITE, argument, 
++			sizeof(struct scsi_idlun)))
++			return -EFAULT;
++
++		/* return 0 for now. */
++		__put_user(0, &((struct scsi_idlun __user *)argument)->dev_id);
++		__put_user(0, 
++			&((struct scsi_idlun __user *)argument)->host_unique_id);
++		return 0;
++
++	default:
++		/*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
++		  command);*/
++		return -EINVAL; /* same return as native Linux */
++	}
++
++	return 0;
++}
++
++static struct block_device_operations blktap_device_file_operations = {
++	.owner     = THIS_MODULE,
++	.open      = blktap_device_open,
++	.release   = blktap_device_release,
++	.ioctl     = blktap_device_ioctl,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++	.getgeo    = blktap_device_getgeo
++#endif
++};
++
++static int
++blktap_map_uaddr_fn(pte_t *ptep, struct page *pmd_page,
++		    unsigned long addr, void *data)
++{
++	pte_t *pte = (pte_t *)data;
++
++	BTDBG("ptep %p -> %012llx\n", ptep, (unsigned long long)pte_val(*pte));
++	set_pte(ptep, *pte);
++	return 0;
++}
++
++static int
++blktap_map_uaddr(struct mm_struct *mm, unsigned long address, pte_t pte)
++{
++	return apply_to_page_range(mm, address,
++				   PAGE_SIZE, blktap_map_uaddr_fn, &pte);
++}
++
++static int
++blktap_umap_uaddr_fn(pte_t *ptep, struct page *pmd_page,
++		     unsigned long addr, void *data)
++{
++	struct mm_struct *mm = (struct mm_struct *)data;
++
++	BTDBG("ptep %p\n", ptep);
++	pte_clear(mm, addr, ptep);
++	return 0;
++}
++
++static int
++blktap_umap_uaddr(struct mm_struct *mm, unsigned long address)
++{
++	return apply_to_page_range(mm, address,
++				   PAGE_SIZE, blktap_umap_uaddr_fn, mm);
++}
++
++static inline void
++flush_tlb_kernel_page(unsigned long kvaddr)
++{
++#ifdef CONFIG_X86
++	xen_invlpg_all(kvaddr);
++#else
++	flush_tlb_kernel_range(kvaddr, kvaddr + PAGE_SIZE);
++#endif
++}
++
++static void
++blktap_device_end_dequeued_request(struct blktap_device *dev,
++				   struct request *req, int uptodate)
++{
++	int ret;
++
++	ret = end_that_request_first(req, uptodate, req->hard_nr_sectors);
++	BUG_ON(ret);
++
++	spin_lock_irq(&dev->lock);
++	end_that_request_last(req, uptodate);
++	spin_unlock_irq(&dev->lock);
++}
++
++/*
++ * tap->tap_sem held on entry
++ */
++static void
++blktap_device_fast_flush(struct blktap *tap, struct blktap_request *request)
++{
++	uint64_t ptep;
++	int ret, usr_idx;
++	unsigned int i, cnt;
++	struct page **map, *page;
++	struct blktap_ring *ring;
++	struct grant_handle_pair *khandle;
++	unsigned long kvaddr, uvaddr, offset;
++	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST * 2];
++	grant_handle_t self_gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++	int self_gref_nr = 0;
++
++	cnt     = 0;
++	ring    = &tap->ring;
++	usr_idx = request->usr_idx;
++	map     = ring->foreign_map.map;
++
++	if (!ring->vma)
++		return;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		zap_page_range(ring->vma, 
++			       MMAP_VADDR(ring->user_vstart, usr_idx, 0),
++			       request->nr_pages << PAGE_SHIFT, NULL);
++
++	for (i = 0; i < request->nr_pages; i++) {
++		kvaddr = request_to_kaddr(request, i);
++		uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
++
++		khandle = request->handles + i;
++
++		if (khandle->kernel != INVALID_GRANT_HANDLE) {
++			gnttab_set_unmap_op(&unmap[cnt], kvaddr,
++					    GNTMAP_host_map, khandle->kernel);
++			cnt++;
++			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
++					    INVALID_P2M_ENTRY);
++		}
++
++		if (khandle->user != INVALID_GRANT_HANDLE) {
++			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++			if (create_lookup_pte_addr(ring->vma->vm_mm,
++						   uvaddr, &ptep) != 0) {
++				BTERR("Couldn't get a pte addr!\n");
++				return;
++			}
++
++			gnttab_set_unmap_op(&unmap[cnt], ptep,
++					    GNTMAP_host_map
++					    | GNTMAP_application_map
++					    | GNTMAP_contains_pte,
++					    khandle->user);
++			cnt++;
++		}
++
++		offset = (uvaddr - ring->vma->vm_start) >> PAGE_SHIFT;
++
++		BTDBG("offset: 0x%08lx, page: %p, request: %p, usr_idx: %d, "
++		      "seg: %d, kvaddr: 0x%08lx, khandle: %u, uvaddr: "
++		      "0x%08lx, handle: %u\n", offset, map[offset], request,
++		      usr_idx, i, kvaddr, khandle->kernel, uvaddr,
++		      khandle->user);
++
++		page = map[offset];
++		if (page) {
++			ClearPageReserved(map[offset]);
++			if (PageBlkback(page)) {
++				ClearPageBlkback(page);
++				set_page_private(page, 0);
++			} else if (
++				xen_feature(XENFEAT_auto_translated_physmap)) {
++				self_gref[self_gref_nr] = khandle->kernel;
++				self_gref_nr++;
++			}
++		}
++		map[offset] = NULL;
++
++		khandle->kernel = INVALID_GRANT_HANDLE;
++		khandle->user   = INVALID_GRANT_HANDLE;
++	}
++
++	if (cnt) {
++		ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
++						unmap, cnt);
++		BUG_ON(ret);
++	}
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap))
++		zap_page_range(ring->vma, 
++			       MMAP_VADDR(ring->user_vstart, usr_idx, 0), 
++			       request->nr_pages << PAGE_SHIFT, NULL);
++	else {
++		for (i = 0; i < self_gref_nr; i++) {
++			gnttab_end_foreign_access_ref(self_gref[i]);
++		}
++	}
++}
++
++/*
++ * tap->tap_sem held on entry
++ */
++static void
++blktap_unmap(struct blktap *tap, struct blktap_request *request)
++{
++	int i, usr_idx;
++	unsigned long kvaddr;
++
++	usr_idx = request->usr_idx;
++	down_write(&tap->ring.vma->vm_mm->mmap_sem);
++
++	for (i = 0; i < request->nr_pages; i++) {
++		kvaddr = request_to_kaddr(request, i);
++		BTDBG("request: %p, seg: %d, kvaddr: 0x%08lx, khandle: %u, "
++		      "uvaddr: 0x%08lx, uhandle: %u\n", request, i,
++		      kvaddr, request->handles[i].kernel,
++		      MMAP_VADDR(tap->ring.user_vstart, usr_idx, i),
++		      request->handles[i].user);
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap) &&
++		    request->handles[i].kernel == INVALID_GRANT_HANDLE) {
++			blktap_umap_uaddr(&init_mm, kvaddr);
++			flush_tlb_kernel_page(kvaddr);
++			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
++					    INVALID_P2M_ENTRY);
++		}
++	}
++
++	blktap_device_fast_flush(tap, request);
++	up_write(&tap->ring.vma->vm_mm->mmap_sem);
++}
++
++/*
++ * called if the tapdisk process dies unexpectedly.
++ * fail and release any pending requests and disable queue.
++ */
++void
++blktap_device_fail_pending_requests(struct blktap *tap)
++{
++	int usr_idx;
++	struct request *req;
++	struct blktap_device *dev;
++	struct blktap_request *request;
++
++	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
++		return;
++
++	down_write(&tap->tap_sem);
++
++	dev = &tap->device;
++	for (usr_idx = 0; usr_idx < MAX_PENDING_REQS; usr_idx++) {
++		request = tap->pending_requests[usr_idx];
++		if (!request || request->status != BLKTAP_REQUEST_PENDING)
++			continue;
++
++		BTERR("%u:%u: failing pending %s of %d pages\n",
++		      blktap_device_major, tap->minor,
++		      (request->operation == BLKIF_OP_READ ?
++		       "read" : "write"), request->nr_pages);
++
++		blktap_unmap(tap, request);
++		req = (struct request *)(unsigned long)request->id;
++		blktap_device_end_dequeued_request(dev, req, 0);
++		blktap_request_free(tap, request);
++	}
++
++	up_write(&tap->tap_sem);
++
++	spin_lock_irq(&dev->lock);
++
++	/* fail any future requests */
++	dev->gd->queue->queuedata = NULL;
++	blk_start_queue(dev->gd->queue);
++
++	spin_unlock_irq(&dev->lock);
++}
++
++/*
++ * tap->tap_sem held on entry
++ */
++void
++blktap_device_finish_request(struct blktap *tap,
++			     blkif_response_t *res,
++			     struct blktap_request *request)
++{
++	int uptodate;
++	struct request *req;
++	struct blktap_device *dev;
++
++	dev = &tap->device;
++
++	blktap_unmap(tap, request);
++
++	req = (struct request *)(unsigned long)request->id;
++	uptodate = (res->status == BLKIF_RSP_OKAY);
++
++	BTDBG("req %p res status %d operation %d/%d id %lld\n", req,
++	      res->status, res->operation, request->operation,
++	      (unsigned long long)res->id);
++
++	switch (request->operation) {
++	case BLKIF_OP_READ:
++	case BLKIF_OP_WRITE:
++		if (unlikely(res->status != BLKIF_RSP_OKAY))
++			BTERR("Bad return from device data "
++				"request: %x\n", res->status);
++		blktap_device_end_dequeued_request(dev, req, uptodate);
++		break;
++	default:
++		BUG();
++	}
++
++	blktap_request_free(tap, request);
++}
++
++static int
++blktap_prep_foreign(struct blktap *tap,
++		    struct blktap_request *request,
++		    blkif_request_t *blkif_req,
++		    unsigned int seg, struct page *page,
++		    struct blktap_grant_table *table)
++{
++	uint64_t ptep;
++	uint32_t flags;
++	struct page *tap_page;
++	struct blktap_ring *ring;
++	struct blkback_pagemap map;
++	unsigned long uvaddr, kvaddr;
++
++	ring = &tap->ring;
++	map  = blkback_pagemap_read(page);
++	blkif_req->seg[seg].gref = map.gref;
++
++	uvaddr = MMAP_VADDR(ring->user_vstart, request->usr_idx, seg);
++	kvaddr = request_to_kaddr(request, seg);
++	flags  = GNTMAP_host_map |
++		(request->operation == BLKIF_OP_WRITE ? GNTMAP_readonly : 0);
++
++	gnttab_set_map_op(&table->grants[table->cnt],
++			  kvaddr, flags, map.gref, map.domid);
++	table->cnt++;
++
++	/* enable chained tap devices */
++	tap_page = request_to_page(request, seg);
++	set_page_private(tap_page, page_private(page));
++	SetPageBlkback(tap_page);
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return 0;
++
++	if (create_lookup_pte_addr(ring->vma->vm_mm, uvaddr, &ptep)) {
++		BTERR("couldn't get a pte addr!\n");
++		return -1;
++	}
++
++	flags |= GNTMAP_application_map | GNTMAP_contains_pte;
++	gnttab_set_map_op(&table->grants[table->cnt],
++			  ptep, flags, map.gref, map.domid);
++	table->cnt++;
++
++	return 0;
++}
++
++static int
++blktap_map_foreign(struct blktap *tap,
++		   struct blktap_request *request,
++		   blkif_request_t *blkif_req,
++		   struct blktap_grant_table *table)
++{
++	struct page *page;
++	int i, grant, err, usr_idx;
++	struct blktap_ring *ring;
++	unsigned long uvaddr, foreign_mfn;
++
++	if (!table->cnt)
++		return 0;
++
++	err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++					table->grants, table->cnt);
++	BUG_ON(err);
++
++	grant   = 0;
++	usr_idx = request->usr_idx;
++	ring    = &tap->ring;
++
++	for (i = 0; i < request->nr_pages; i++) {
++		if (!blkif_req->seg[i].gref)
++			continue;
++
++		uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
++
++		if (unlikely(table->grants[grant].status)) {
++			BTERR("invalid kernel buffer: could not remap it\n");
++            /* This should never happen: blkback should handle eagain first */
++            BUG_ON(table->grants[grant].status == GNTST_eagain);
++			err |= 1;
++			table->grants[grant].handle = INVALID_GRANT_HANDLE;
++		}
++
++		request->handles[i].kernel = table->grants[grant].handle;
++		foreign_mfn = table->grants[grant].dev_bus_addr >> PAGE_SHIFT;
++		grant++;
++
++		if (xen_feature(XENFEAT_auto_translated_physmap))
++			goto done;
++
++		if (unlikely(table->grants[grant].status)) {
++			BTERR("invalid user buffer: could not remap it\n");
++			err |= 1;
++			table->grants[grant].handle = INVALID_GRANT_HANDLE;
++		}
++
++		request->handles[i].user = table->grants[grant].handle;
++		grant++;
++
++	done:
++		if (err)
++			continue;
++
++		page = request_to_page(request, i);
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap))
++			set_phys_to_machine(page_to_pfn(page),
++					    FOREIGN_FRAME(foreign_mfn));
++		else if (vm_insert_page(ring->vma, uvaddr, page))
++			err |= 1;
++
++		BTDBG("pending_req: %p, seg: %d, page: %p, "
++		      "kvaddr: 0x%p, khandle: %u, uvaddr: 0x%08lx, "
++		      "uhandle: %u\n", request, i, page,
++		      pfn_to_kaddr(page_to_pfn(page)),
++		      request->handles[i].kernel,
++		      uvaddr, request->handles[i].user);
++	}
++
++	return err;
++}
++
++static int
++blktap_map(struct blktap *tap,
++	   struct blktap_request *request,
++	   unsigned int seg, struct page *page)
++{
++	pte_t pte;
++	int usr_idx;
++	struct blktap_ring *ring;
++	unsigned long uvaddr, kvaddr;
++	int err = 0;
++
++	ring    = &tap->ring;
++	usr_idx = request->usr_idx;
++	uvaddr  = MMAP_VADDR(ring->user_vstart, usr_idx, seg);
++	kvaddr  = request_to_kaddr(request, seg);
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		pte = mk_pte(page, ring->vma->vm_page_prot);
++		blktap_map_uaddr(ring->vma->vm_mm, uvaddr, pte_mkwrite(pte));
++		flush_tlb_page(ring->vma, uvaddr);
++		blktap_map_uaddr(&init_mm, kvaddr, mk_pte(page, PAGE_KERNEL));
++		flush_tlb_kernel_page(kvaddr);
++
++		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, pte_mfn(pte));
++		request->handles[seg].kernel = INVALID_GRANT_HANDLE;
++	} else {
++		/* grant this page access to self domain and map it. */
++		domid_t domid = 0; /* XXX my domian id: grant table hypercall
++				      doesn't understand DOMID_SELF */
++		int gref;
++		uint32_t flags;
++		struct gnttab_map_grant_ref map;
++		struct page *tap_page;
++
++		gref = gnttab_grant_foreign_access(
++			domid, page_to_pfn(page),
++			(request->operation == BLKIF_OP_WRITE)?
++			GTF_readonly: 0);
++
++		flags  = GNTMAP_host_map |
++			(request->operation == BLKIF_OP_WRITE ?
++			 GNTMAP_readonly : 0);
++
++		gnttab_set_map_op(&map, kvaddr, flags, gref, domid);
++
++		/* enable chained tap devices */
++		tap_page = request_to_page(request, seg);
++		set_page_private(tap_page, page_private(page));
++		SetPageBlkback(tap_page);
++
++		err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++						&map, 1);
++		BUG_ON(err);
++        /* We are not expecting the grant op to fail */
++        BUG_ON(map.status != GNTST_okay);
++
++		err = vm_insert_page(ring->vma, uvaddr, tap_page);
++		if (err) {
++			struct gnttab_unmap_grant_ref unmap;
++			gnttab_set_unmap_op(&unmap, kvaddr,
++					    GNTMAP_host_map, gref);
++			VOID(HYPERVISOR_grant_table_op(
++				GNTTABOP_unmap_grant_ref, &unmap, 1));
++		} else
++			request->handles[seg].kernel = gref;
++	}
++	request->handles[seg].user = INVALID_GRANT_HANDLE;
++
++	BTDBG("pending_req: %p, seg: %d, page: %p, kvaddr: 0x%08lx, "
++	      "uvaddr: 0x%08lx\n", request, seg, page, kvaddr,
++	      uvaddr);
++
++	return err;
++}
++
++static int
++blktap_device_process_request(struct blktap *tap,
++			      struct blktap_request *request,
++			      struct request *req)
++{
++	struct page *page;
++	int i, usr_idx, err;
++	struct blktap_ring *ring;
++	struct scatterlist *sg;
++	struct blktap_grant_table table;
++	unsigned int fsect, lsect, nr_sects;
++	unsigned long offset, uvaddr;
++	struct blkif_request blkif_req, *target;
++
++	err = -1;
++	memset(&table, 0, sizeof(table));
++
++	if (!blktap_active(tap))
++		goto out;
++
++	ring    = &tap->ring;
++	usr_idx = request->usr_idx;
++	blkif_req.id = usr_idx;
++	blkif_req.sector_number = (blkif_sector_t)req->sector;
++	blkif_req.handle = 0;
++	blkif_req.operation = rq_data_dir(req) ?
++		BLKIF_OP_WRITE : BLKIF_OP_READ;
++
++	request->id        = (unsigned long)req;
++	request->operation = blkif_req.operation;
++	request->status    = BLKTAP_REQUEST_PENDING;
++	do_gettimeofday(&request->time);
++
++	nr_sects = 0;
++	request->nr_pages = 0;
++	blkif_req.nr_segments = blk_rq_map_sg(req->q, req, tap->sg);
++	BUG_ON(blkif_req.nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
++	for (i = 0; i < blkif_req.nr_segments; ++i) {
++			sg = tap->sg + i;
++			fsect = sg->offset >> 9;
++			lsect = fsect + (sg->length >> 9) - 1;
++			nr_sects += sg->length >> 9;
++
++			blkif_req.seg[i] =
++				(struct blkif_request_segment) {
++				.gref       = 0,
++				.first_sect = fsect,
++				.last_sect  = lsect };
++
++			if (PageBlkback(sg->page)) {
++				/* foreign page -- use xen */
++				if (blktap_prep_foreign(tap,
++							request,
++							&blkif_req,
++							i,
++							sg->page,
++							&table))
++					goto out;
++			} else {
++				/* do it the old fashioned way */
++				if (blktap_map(tap,
++					       request,
++					       i,
++					       sg->page))
++					goto out;
++			}
++
++			uvaddr = MMAP_VADDR(ring->user_vstart, usr_idx, i);
++			offset = (uvaddr - ring->vma->vm_start) >> PAGE_SHIFT;
++			page   = request_to_page(request, i);
++			ring->foreign_map.map[offset] = page;
++			SetPageReserved(page);
++
++			BTDBG("mapped uaddr %08lx to page %p pfn 0x%lx\n",
++			      uvaddr, page, page_to_pfn(page));
++			BTDBG("offset: 0x%08lx, pending_req: %p, seg: %d, "
++			      "page: %p, kvaddr: %p, uvaddr: 0x%08lx\n",
++			      offset, request, i,
++			      page, pfn_to_kaddr(page_to_pfn(page)), uvaddr);
++
++			request->nr_pages++;
++	}
++
++	if (blktap_map_foreign(tap, request, &blkif_req, &table))
++		goto out;
++
++	/* Finally, write the request message to the user ring. */
++	target = RING_GET_REQUEST(&ring->ring, ring->ring.req_prod_pvt);
++	memcpy(target, &blkif_req, sizeof(blkif_req));
++	target->id = request->usr_idx;
++	wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
++	ring->ring.req_prod_pvt++;
++
++	if (rq_data_dir(req)) {
++		tap->stats.st_wr_sect += nr_sects;
++		tap->stats.st_wr_req++;
++	} else {
++		tap->stats.st_rd_sect += nr_sects;
++		tap->stats.st_rd_req++;
++	}
++
++	err = 0;
++
++out:
++	if (err)
++		blktap_device_fast_flush(tap, request);
++	return err;
++}
++
++#ifdef ENABLE_PASSTHROUGH
++#define rq_for_each_bio_safe(_bio, _tmp, _req)				\
++	if ((_req)->bio)						\
++		for (_bio = (_req)->bio;				\
++		     _bio && ((_tmp = _bio->bi_next) || 1);		\
++		     _bio = _tmp)
++
++static void
++blktap_device_forward_request(struct blktap *tap, struct request *req)
++{
++	struct bio *bio, *tmp;
++	struct blktap_device *dev;
++
++	dev = &tap->device;
++
++	rq_for_each_bio_safe(bio, tmp, req) {
++		bio->bi_bdev = dev->bdev;
++		submit_bio(bio->bi_rw, bio);
++	}
++}
++
++static void
++blktap_device_close_bdev(struct blktap *tap)
++{
++	struct blktap_device *dev;
++
++	dev = &tap->device;
++
++	if (dev->bdev)
++		blkdev_put(dev->bdev);
++
++	dev->bdev = NULL;
++	clear_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse);
++}
++
++static int
++blktap_device_open_bdev(struct blktap *tap, u32 pdev)
++{
++	struct block_device *bdev;
++	struct blktap_device *dev;
++
++	dev = &tap->device;
++
++	bdev = open_by_devnum(pdev, FMODE_WRITE);
++	if (IS_ERR(bdev)) {
++		BTERR("opening device %x:%x failed: %ld\n",
++		      MAJOR(pdev), MINOR(pdev), PTR_ERR(bdev));
++		return PTR_ERR(bdev);
++	}
++
++	if (!bdev->bd_disk) {
++		BTERR("device %x:%x doesn't exist\n",
++		      MAJOR(pdev), MINOR(pdev));
++		blkdev_put(dev->bdev);
++		return -ENOENT;
++	}
++
++	dev->bdev = bdev;
++	set_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse);
++
++	/* TODO: readjust queue parameters */
++
++	BTINFO("set device %d to passthrough on %x:%x\n",
++	       tap->minor, MAJOR(pdev), MINOR(pdev));
++
++	return 0;
++}
++
++int
++blktap_device_enable_passthrough(struct blktap *tap,
++				 unsigned major, unsigned minor)
++{
++	u32 pdev;
++	struct blktap_device *dev;
++
++	dev  = &tap->device;
++	pdev = MKDEV(major, minor);
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return -EINVAL;
++
++	if (dev->bdev) {
++		if (pdev)
++			return -EINVAL;
++		blktap_device_close_bdev(tap);
++		return 0;
++	}
++
++	return blktap_device_open_bdev(tap, pdev);
++}
++#endif
++
++/*
++ * dev->lock held on entry
++ */
++static void
++blktap_device_run_queue(struct blktap *tap)
++{
++	int queued, err;
++	request_queue_t *rq;
++	struct request *req;
++	struct blktap_ring *ring;
++	struct blktap_device *dev;
++	struct blktap_request *request;
++
++	queued = 0;
++	ring   = &tap->ring;
++	dev    = &tap->device;
++	rq     = dev->gd->queue;
++
++	BTDBG("running queue for %d\n", tap->minor);
++
++	while ((req = elv_next_request(rq)) != NULL) {
++		if (!blk_fs_request(req)) {
++			end_request(req, 0);
++			continue;
++		}
++
++		if (blk_barrier_rq(req)) {
++			end_request(req, 0);
++			continue;
++		}
++
++#ifdef ENABLE_PASSTHROUGH
++		if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
++			blkdev_dequeue_request(req);
++			blktap_device_forward_request(tap, req);
++			continue;
++		}
++#endif
++
++		if (RING_FULL(&ring->ring)) {
++		wait:
++			/* Avoid pointless unplugs. */
++			blk_stop_queue(rq);
++			blktap_defer(tap);
++			break;
++		}
++
++		request = blktap_request_allocate(tap);
++		if (!request) {
++			tap->stats.st_oo_req++;
++			goto wait;
++		}
++
++		BTDBG("req %p: dev %d cmd %p, sec 0x%llx, (0x%x/0x%lx) "
++		      "buffer:%p [%s], pending: %p\n", req, tap->minor,
++		      req->cmd, (unsigned long long)req->sector,
++		      req->current_nr_sectors, req->nr_sectors, req->buffer,
++		      rq_data_dir(req) ? "write" : "read", request);
++
++		blkdev_dequeue_request(req);
++
++		spin_unlock_irq(&dev->lock);
++		down_read(&tap->tap_sem);
++
++		err = blktap_device_process_request(tap, request, req);
++		if (!err)
++			queued++;
++		else {
++			blktap_device_end_dequeued_request(dev, req, 0);
++			blktap_request_free(tap, request);
++		}
++
++		up_read(&tap->tap_sem);
++		spin_lock_irq(&dev->lock);
++	}
++
++	if (queued)
++		blktap_ring_kick_user(tap);
++}
++
++/*
++ * dev->lock held on entry
++ */
++static void
++blktap_device_do_request(request_queue_t *rq)
++{
++	struct request *req;
++	struct blktap *tap;
++	struct blktap_device *dev;
++
++	dev = rq->queuedata;
++	if (!dev)
++		goto fail;
++
++	tap = dev_to_blktap(dev);
++	if (!blktap_active(tap))
++		goto fail;
++
++	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse) ||
++	    test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
++		blktap_defer(tap);
++		return;
++	}
++
++	blktap_device_run_queue(tap);
++	return;
++
++fail:
++	while ((req = elv_next_request(rq))) {
++		BTERR("device closed: failing secs %llu - %llu\n",
++		      (unsigned long long)req->sector,
++		      (unsigned long long)req->sector + req->nr_sectors);
++		end_request(req, 0);
++	}
++}
++
++void
++blktap_device_restart(struct blktap *tap)
++{
++	struct blktap_device *dev;
++
++	dev = &tap->device;
++	if (!dev->gd || !dev->gd->queue)
++		return;
++
++	if (blktap_active(tap) && RING_FULL(&tap->ring.ring)) {
++		blktap_defer(tap);
++		return;
++	}
++
++	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse) ||
++	    test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
++		blktap_defer(tap);
++		return;
++	}
++
++	spin_lock_irq(&dev->lock);
++
++	/* Re-enable calldowns. */
++	if (blk_queue_stopped(dev->gd->queue))
++		blk_start_queue(dev->gd->queue);
++
++	/* Kick things off immediately. */
++	blktap_device_do_request(dev->gd->queue);
++
++	spin_unlock_irq(&dev->lock);
++}
++
++static void
++blktap_device_configure(struct blktap *tap)
++{
++	struct request_queue *rq;
++	struct blktap_device *dev = &tap->device;
++
++	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !dev->gd)
++		return;
++
++	dev = &tap->device;
++	rq  = dev->gd->queue;
++
++	spin_lock_irq(&dev->lock);
++
++	set_capacity(dev->gd, tap->params.capacity);
++
++	/* Hard sector size and max sectors impersonate the equiv. hardware. */
++	blk_queue_hardsect_size(rq, tap->params.sector_size);
++	blk_queue_max_sectors(rq, 512);
++
++	/* Each segment in a request is up to an aligned page in size. */
++	blk_queue_segment_boundary(rq, PAGE_SIZE - 1);
++	blk_queue_max_segment_size(rq, PAGE_SIZE);
++
++	/* Ensure a merged request will fit in a single I/O ring slot. */
++	blk_queue_max_phys_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
++	blk_queue_max_hw_segments(rq, BLKIF_MAX_SEGMENTS_PER_REQUEST);
++
++	/* Make sure buffer addresses are sector-aligned. */
++	blk_queue_dma_alignment(rq, 511);
++
++	spin_unlock_irq(&dev->lock);
++}
++
++int
++blktap_device_resume(struct blktap *tap)
++{
++	int err;
++
++	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !blktap_active(tap))
++		return -ENODEV;
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return 0;
++
++	err = blktap_ring_resume(tap);
++	if (err)
++		return err;
++
++	/* device size may have changed */
++	blktap_device_configure(tap);
++
++	BTDBG("restarting device\n");
++	blktap_device_restart(tap);
++
++	return 0;
++}
++
++int
++blktap_device_pause(struct blktap *tap)
++{
++	unsigned long flags;
++	struct blktap_device *dev = &tap->device;
++
++	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse) || !blktap_active(tap))
++		return -ENODEV;
++
++	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return 0;
++
++	spin_lock_irqsave(&dev->lock, flags);
++
++	blk_stop_queue(dev->gd->queue);
++	set_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
++
++	spin_unlock_irqrestore(&dev->lock, flags);
++
++	return blktap_ring_pause(tap);
++}
++
++int
++blktap_device_destroy(struct blktap *tap)
++{
++	struct blktap_device *dev = &tap->device;
++
++	if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
++		return 0;
++
++	BTINFO("destroy device %d users %d\n", tap->minor, dev->users);
++
++	if (dev->users)
++		return -EBUSY;
++
++	spin_lock_irq(&dev->lock);
++	/* No more blktap_device_do_request(). */
++	blk_stop_queue(dev->gd->queue);
++	clear_bit(BLKTAP_DEVICE, &tap->dev_inuse);
++	spin_unlock_irq(&dev->lock);
++
++#ifdef ENABLE_PASSTHROUGH
++	if (dev->bdev)
++		blktap_device_close_bdev(tap);
++#endif
++
++	del_gendisk(dev->gd);
++	put_disk(dev->gd);
++	blk_cleanup_queue(dev->gd->queue);
++
++	dev->gd = NULL;
++
++	wake_up(&tap->wq);
++
++	return 0;
++}
++
++int
++blktap_device_create(struct blktap *tap)
++{
++	int minor, err;
++	struct gendisk *gd;
++	struct request_queue *rq;
++	struct blktap_device *dev;
++
++	gd    = NULL;
++	rq    = NULL;
++	dev   = &tap->device;
++	minor = tap->minor;
++
++	if (test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
++		return -EEXIST;
++
++	if (blktap_validate_params(tap, &tap->params))
++		return -EINVAL;
++
++	BTINFO("minor %d sectors %Lu sector-size %lu\n",
++	       minor, tap->params.capacity, tap->params.sector_size);
++
++	err = -ENODEV;
++
++	gd = alloc_disk(1);
++	if (!gd)
++		goto error;
++
++	if (minor < 26)
++		sprintf(gd->disk_name, "tapdev%c", 'a' + minor);
++	else
++		sprintf(gd->disk_name, "tapdev%c%c",
++			'a' + ((minor / 26) - 1), 'a' + (minor % 26));
++
++	gd->major = blktap_device_major;
++	gd->first_minor = minor;
++	gd->fops = &blktap_device_file_operations;
++	gd->private_data = dev;
++
++	spin_lock_init(&dev->lock);
++	rq = blk_init_queue(blktap_device_do_request, &dev->lock);
++	if (!rq)
++		goto error;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
++	elevator_init(rq, "noop");
++#else
++	elevator_init(rq, &elevator_noop);
++#endif
++
++	gd->queue     = rq;
++	rq->queuedata = dev;
++	dev->gd       = gd;
++
++	set_bit(BLKTAP_DEVICE, &tap->dev_inuse);
++	blktap_device_configure(tap);
++
++	add_disk(gd);
++
++	err = 0;
++	goto out;
++
++ error:
++	if (gd)
++		del_gendisk(gd);
++	if (rq)
++		blk_cleanup_queue(rq);
++
++ out:
++	BTINFO("creation of %u:%u: %d\n", blktap_device_major, tap->minor, err);
++	return err;
++}
++
++int __init
++blktap_device_init(int *maj)
++{
++	int major;
++
++	/* Dynamically allocate a major for this device */
++	major = register_blkdev(0, "tapdev");
++	if (major < 0) {
++		BTERR("Couldn't register blktap device\n");
++		return -ENOMEM;
++	}	
++
++	blktap_device_major = *maj = major;
++	BTINFO("blktap device major %d\n", major);
++
++	return 0;
++}
++
++void
++blktap_device_free(void)
++{
++	if (blktap_device_major)
++		if (unregister_blkdev(blktap_device_major, "tapdev"))
++			BTERR("blktap device unregister failed\n");
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/request.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,296 @@
++#include <linux/spinlock.h>
++#include <xen/balloon.h>
++
++#include "blktap.h"
++
++#define MAX_BUCKETS                      8
++#define BUCKET_SIZE                      MAX_PENDING_REQS
++
++#define BLKTAP_POOL_CLOSING              1
++
++struct blktap_request_bucket;
++
++struct blktap_request_handle {
++	int                              slot;
++	uint8_t                          inuse;
++	struct blktap_request            request;
++	struct blktap_request_bucket    *bucket;
++};
++
++struct blktap_request_bucket {
++	atomic_t                         reqs_in_use;
++	struct blktap_request_handle     handles[BUCKET_SIZE];
++	struct page                    **foreign_pages;
++};
++
++struct blktap_request_pool {
++	spinlock_t                       lock;
++	uint8_t                          status;
++	struct list_head                 free_list;
++	atomic_t                         reqs_in_use;
++	wait_queue_head_t                wait_queue;
++	struct blktap_request_bucket    *buckets[MAX_BUCKETS];
++};
++
++static struct blktap_request_pool pool;
++
++static inline struct blktap_request_handle *
++blktap_request_to_handle(struct blktap_request *req)
++{
++	return container_of(req, struct blktap_request_handle, request);
++}
++
++static void
++blktap_request_pool_init_request(struct blktap_request *request)
++{
++	int i;
++
++	request->usr_idx  = -1;
++	request->nr_pages = 0;
++	request->status   = BLKTAP_REQUEST_FREE;
++	INIT_LIST_HEAD(&request->free_list);
++	for (i = 0; i < ARRAY_SIZE(request->handles); i++) {
++		request->handles[i].user   = INVALID_GRANT_HANDLE;
++		request->handles[i].kernel = INVALID_GRANT_HANDLE;
++	}
++}
++
++static int
++blktap_request_pool_allocate_bucket(void)
++{
++	int i, idx;
++	unsigned long flags;
++	struct blktap_request *request;
++	struct blktap_request_handle *handle;
++	struct blktap_request_bucket *bucket;
++
++	bucket = kzalloc(sizeof(struct blktap_request_bucket), GFP_KERNEL);
++	if (!bucket)
++		goto fail;
++
++	bucket->foreign_pages = alloc_empty_pages_and_pagevec(MMAP_PAGES);
++	if (!bucket->foreign_pages)
++		goto fail;
++
++	spin_lock_irqsave(&pool.lock, flags);
++
++	idx = -1;
++	for (i = 0; i < MAX_BUCKETS; i++) {
++		if (!pool.buckets[i]) {
++			idx = i;
++			pool.buckets[idx] = bucket;
++			break;
++		}
++	}
++
++	if (idx == -1) {
++		spin_unlock_irqrestore(&pool.lock, flags);
++		goto fail;
++	}
++
++	for (i = 0; i < BUCKET_SIZE; i++) {
++		handle  = bucket->handles + i;
++		request = &handle->request;
++
++		handle->slot   = i;
++		handle->inuse  = 0;
++		handle->bucket = bucket;
++
++		blktap_request_pool_init_request(request);
++		list_add_tail(&request->free_list, &pool.free_list);
++	}
++
++	spin_unlock_irqrestore(&pool.lock, flags);
++
++	return 0;
++
++fail:
++	if (bucket && bucket->foreign_pages)
++		free_empty_pages_and_pagevec(bucket->foreign_pages, MMAP_PAGES);
++	kfree(bucket);
++	return -ENOMEM;
++}
++
++static void
++blktap_request_pool_free_bucket(struct blktap_request_bucket *bucket)
++{
++	if (!bucket)
++		return;
++
++	BTDBG("freeing bucket %p\n", bucket);
++
++	free_empty_pages_and_pagevec(bucket->foreign_pages, MMAP_PAGES);
++	kfree(bucket);
++}
++
++struct page *
++request_to_page(struct blktap_request *req, int seg)
++{
++	struct blktap_request_handle *handle = blktap_request_to_handle(req);
++	int idx = handle->slot * BLKIF_MAX_SEGMENTS_PER_REQUEST + seg;
++	return handle->bucket->foreign_pages[idx];
++}
++
++int
++blktap_request_pool_shrink(void)
++{
++	int i, err;
++	unsigned long flags;
++	struct blktap_request_bucket *bucket;
++
++	err = -EAGAIN;
++
++	spin_lock_irqsave(&pool.lock, flags);
++
++	/* always keep at least one bucket */
++	for (i = 1; i < MAX_BUCKETS; i++) {
++		bucket = pool.buckets[i];
++		if (!bucket)
++			continue;
++
++		if (atomic_read(&bucket->reqs_in_use))
++			continue;
++
++		blktap_request_pool_free_bucket(bucket);
++		pool.buckets[i] = NULL;
++		err = 0;
++		break;
++	}
++
++	spin_unlock_irqrestore(&pool.lock, flags);
++
++	return err;
++}
++
++int
++blktap_request_pool_grow(void)
++{
++	return blktap_request_pool_allocate_bucket();
++}
++
++struct blktap_request *
++blktap_request_allocate(struct blktap *tap)
++{
++	int i;
++	uint16_t usr_idx;
++	unsigned long flags;
++	struct blktap_request *request;
++
++	usr_idx = -1;
++	request = NULL;
++
++	spin_lock_irqsave(&pool.lock, flags);
++
++	if (pool.status == BLKTAP_POOL_CLOSING)
++		goto out;
++
++	for (i = 0; i < ARRAY_SIZE(tap->pending_requests); i++)
++		if (!tap->pending_requests[i]) {
++			usr_idx = i;
++			break;
++		}
++
++	if (usr_idx == (uint16_t)-1)
++		goto out;
++
++	if (!list_empty(&pool.free_list)) {
++		request = list_entry(pool.free_list.next,
++				     struct blktap_request, free_list);
++		list_del(&request->free_list);
++	}
++
++	if (request) {
++		struct blktap_request_handle *handle;
++
++		atomic_inc(&pool.reqs_in_use);
++
++		handle = blktap_request_to_handle(request);
++		atomic_inc(&handle->bucket->reqs_in_use);
++		handle->inuse = 1;
++
++		request->usr_idx = usr_idx;
++
++		tap->pending_requests[usr_idx] = request;
++		tap->pending_cnt++;
++	}
++
++out:
++	spin_unlock_irqrestore(&pool.lock, flags);
++	return request;
++}
++
++void
++blktap_request_free(struct blktap *tap, struct blktap_request *request)
++{
++	int free;
++	unsigned long flags;
++	struct blktap_request_handle *handle;
++
++	BUG_ON(request->usr_idx >= ARRAY_SIZE(tap->pending_requests));
++	handle = blktap_request_to_handle(request);
++
++	spin_lock_irqsave(&pool.lock, flags);
++
++	handle->inuse = 0;
++	tap->pending_requests[request->usr_idx] = NULL;
++	blktap_request_pool_init_request(request);
++	list_add(&request->free_list, &pool.free_list);
++	atomic_dec(&handle->bucket->reqs_in_use);
++	free = atomic_dec_and_test(&pool.reqs_in_use);
++
++	spin_unlock_irqrestore(&pool.lock, flags);
++
++	if (--tap->pending_cnt == 0)
++		wake_up_interruptible(&tap->wq);
++
++	if (free)
++		wake_up(&pool.wait_queue);
++}
++
++void
++blktap_request_pool_free(void)
++{
++	int i;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pool.lock, flags);
++
++	pool.status = BLKTAP_POOL_CLOSING;
++	while (atomic_read(&pool.reqs_in_use)) {
++		spin_unlock_irqrestore(&pool.lock, flags);
++		wait_event(pool.wait_queue, !atomic_read(&pool.reqs_in_use));
++		spin_lock_irqsave(&pool.lock, flags);
++	}
++
++	for (i = 0; i < MAX_BUCKETS; i++) {
++		blktap_request_pool_free_bucket(pool.buckets[i]);
++		pool.buckets[i] = NULL;
++	}
++
++	spin_unlock_irqrestore(&pool.lock, flags);
++}
++
++int __init
++blktap_request_pool_init(void)
++{
++	int i, err;
++
++	memset(&pool, 0, sizeof(pool));
++
++	spin_lock_init(&pool.lock);
++	INIT_LIST_HEAD(&pool.free_list);
++	atomic_set(&pool.reqs_in_use, 0);
++	init_waitqueue_head(&pool.wait_queue);
++
++	for (i = 0; i < 2; i++) {
++		err = blktap_request_pool_allocate_bucket();
++		if (err)
++			goto fail;
++	}
++
++	return 0;
++
++fail:
++	blktap_request_pool_free();
++	return err;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/ring.c	2009-12-16 11:43:21.000000000 +0100
+@@ -0,0 +1,613 @@
++#include <linux/module.h>
++#include <linux/signal.h>
++
++#include "blktap.h"
++
++static int blktap_ring_major;
++
++static inline struct blktap *
++vma_to_blktap(struct vm_area_struct *vma)
++{
++	struct vm_foreign_map *m = vma->vm_private_data;
++	struct blktap_ring *r = container_of(m, struct blktap_ring, foreign_map);
++	return container_of(r, struct blktap, ring);
++}
++
++ /* 
++  * BLKTAP - immediately before the mmap area,
++  * we have a bunch of pages reserved for shared memory rings.
++  */
++#define RING_PAGES 1
++
++static int
++blktap_read_ring(struct blktap *tap)
++{
++	/* This is called to read responses from the ring. */
++	int usr_idx;
++	RING_IDX rc, rp;
++	blkif_response_t res;
++	struct blktap_ring *ring;
++	struct blktap_request *request;
++
++	down_read(&tap->tap_sem);
++
++	ring = &tap->ring;
++	if (!ring->vma) {
++		up_read(&tap->tap_sem);
++		return 0;
++	}
++
++	/* for each outstanding message on the ring  */
++	rp = ring->ring.sring->rsp_prod;
++	rmb();
++
++	for (rc = ring->ring.rsp_cons; rc != rp; rc++) {
++		memcpy(&res, RING_GET_RESPONSE(&ring->ring, rc), sizeof(res));
++		mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */
++		++ring->ring.rsp_cons;
++
++		usr_idx = (int)res.id;
++		if (usr_idx >= MAX_PENDING_REQS ||
++		    !tap->pending_requests[usr_idx]) {
++			BTWARN("Request %d/%d invalid [%x], tapdisk %d%p\n",
++			       rc, rp, usr_idx, tap->pid, ring->vma);
++			continue;
++		}
++
++		request = tap->pending_requests[usr_idx];
++		BTDBG("request %p response #%d id %x\n", request, rc, usr_idx);
++		blktap_device_finish_request(tap, &res, request);
++	}
++
++	up_read(&tap->tap_sem);
++
++	blktap_run_deferred();
++
++	return 0;
++}
++
++static struct page *
++blktap_ring_nopage(struct vm_area_struct *vma,
++		   unsigned long address, int *type)
++{
++	/*
++	 * if the page has not been mapped in by the driver then return
++	 * NOPAGE_SIGBUS to the domain.
++	 */
++
++	return NOPAGE_SIGBUS;
++}
++
++static pte_t
++blktap_ring_clear_pte(struct vm_area_struct *vma,
++		      unsigned long uvaddr,
++		      pte_t *ptep, int is_fullmm)
++{
++	pte_t copy;
++	struct blktap *tap;
++	unsigned long kvaddr;
++	struct page **map, *page;
++	struct blktap_ring *ring;
++	struct blktap_request *request;
++	struct grant_handle_pair *khandle;
++	struct gnttab_unmap_grant_ref unmap[2];
++	int offset, seg, usr_idx, count = 0;
++
++	tap  = vma_to_blktap(vma);
++	ring = &tap->ring;
++	map  = ring->foreign_map.map;
++	BUG_ON(!map);	/* TODO Should this be changed to if statement? */
++
++	/*
++	 * Zap entry if the address is before the start of the grant
++	 * mapped region.
++	 */
++	if (uvaddr < ring->user_vstart)
++		return ptep_get_and_clear_full(vma->vm_mm, uvaddr,
++					       ptep, is_fullmm);
++
++	offset  = (int)((uvaddr - ring->user_vstart) >> PAGE_SHIFT);
++	usr_idx = offset / BLKIF_MAX_SEGMENTS_PER_REQUEST;
++	seg     = offset % BLKIF_MAX_SEGMENTS_PER_REQUEST;
++
++	offset  = (int)((uvaddr - vma->vm_start) >> PAGE_SHIFT);
++	page    = map[offset];
++	if (page) {
++		ClearPageReserved(page);
++		if (PageBlkback(page)) {
++			ClearPageBlkback(page);
++			set_page_private(page, 0);
++		}
++	}
++	map[offset] = NULL;
++
++	request = tap->pending_requests[usr_idx];
++	kvaddr  = request_to_kaddr(request, seg);
++	khandle = request->handles + seg;
++
++	if (khandle->kernel != INVALID_GRANT_HANDLE) {
++		gnttab_set_unmap_op(&unmap[count], kvaddr, 
++				    GNTMAP_host_map, khandle->kernel);
++		count++;
++
++		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, 
++				    INVALID_P2M_ENTRY);
++	}
++
++
++	if (khandle->user != INVALID_GRANT_HANDLE) {
++		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++
++		copy = *ptep;
++		gnttab_set_unmap_op(&unmap[count], virt_to_machine(ptep), 
++				    GNTMAP_host_map 
++				    | GNTMAP_application_map 
++				    | GNTMAP_contains_pte,
++				    khandle->user);
++		count++;
++	} else
++		copy = ptep_get_and_clear_full(vma->vm_mm, uvaddr, ptep,
++					       is_fullmm);
++
++	if (count)
++		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
++					      unmap, count))
++			BUG();
++
++	khandle->kernel = INVALID_GRANT_HANDLE;
++	khandle->user   = INVALID_GRANT_HANDLE;
++
++	return copy;
++}
++
++static void
++blktap_ring_vm_unmap(struct vm_area_struct *vma)
++{
++	struct blktap *tap = vma_to_blktap(vma);
++
++	down_write(&tap->tap_sem);
++	clear_bit(BLKTAP_RING_VMA, &tap->dev_inuse);
++	clear_bit(BLKTAP_PAUSED, &tap->dev_inuse);
++	clear_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
++	up_write(&tap->tap_sem);
++}
++
++static void
++blktap_ring_vm_close(struct vm_area_struct *vma)
++{
++	struct blktap *tap = vma_to_blktap(vma);
++	struct blktap_ring *ring = &tap->ring;
++
++	blktap_ring_vm_unmap(vma);                 /* fail future requests */
++	blktap_device_fail_pending_requests(tap);  /* fail pending requests */
++	blktap_device_restart(tap);                /* fail deferred requests */
++
++	down_write(&tap->tap_sem);
++
++	zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
++
++	kfree(ring->foreign_map.map);
++	ring->foreign_map.map = NULL;
++
++	/* Free the ring page. */
++	ClearPageReserved(virt_to_page(ring->ring.sring));
++	free_page((unsigned long)ring->ring.sring);
++
++	BTINFO("unmapping ring %d\n", tap->minor);
++	ring->ring.sring = NULL;
++	ring->vma = NULL;
++
++	up_write(&tap->tap_sem);
++
++	wake_up(&tap->wq);
++}
++
++static struct vm_operations_struct blktap_ring_vm_operations = {
++	.close    = blktap_ring_vm_close,
++	.unmap    = blktap_ring_vm_unmap,
++	.nopage   = blktap_ring_nopage,
++	.zap_pte  = blktap_ring_clear_pte,
++};
++
++static int
++blktap_ring_open(struct inode *inode, struct file *filp)
++{
++	int idx;
++	struct blktap *tap;
++
++	idx = iminor(inode);
++	if (idx < 0 || idx > MAX_BLKTAP_DEVICE || blktaps[idx] == NULL) {
++		BTERR("unable to open device blktap%d\n", idx);
++		return -ENODEV;
++	}
++
++	tap = blktaps[idx];
++
++	BTINFO("opening device blktap%d\n", idx);
++
++	if (!test_bit(BLKTAP_CONTROL, &tap->dev_inuse))
++		return -ENODEV;
++
++	/* Only one process can access ring at a time */
++	if (test_and_set_bit(BLKTAP_RING_FD, &tap->dev_inuse))
++		return -EBUSY;
++
++	filp->private_data = tap;
++	BTINFO("opened device %d\n", tap->minor);
++
++	return 0;
++}
++
++static int
++blktap_ring_release(struct inode *inode, struct file *filp)
++{
++	struct blktap *tap = filp->private_data;
++
++	BTINFO("freeing device %d\n", tap->minor);
++	clear_bit(BLKTAP_RING_FD, &tap->dev_inuse);
++	filp->private_data = NULL;
++	wake_up(&tap->wq);	
++	return 0;
++}
++
++/* Note on mmap:
++ * We need to map pages to user space in a way that will allow the block
++ * subsystem set up direct IO to them.  This couldn't be done before, because
++ * there isn't really a sane way to translate a user virtual address down to a 
++ * physical address when the page belongs to another domain.
++ *
++ * My first approach was to map the page in to kernel memory, add an entry
++ * for it in the physical frame list (using alloc_lomem_region as in blkback)
++ * and then attempt to map that page up to user space.  This is disallowed
++ * by xen though, which realizes that we don't really own the machine frame
++ * underlying the physical page.
++ *
++ * The new approach is to provide explicit support for this in xen linux.
++ * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages
++ * mapped from other vms.  vma->vm_private_data is set up as a mapping 
++ * from pages to actual page structs.  There is a new clause in get_user_pages
++ * that does the right thing for this sort of mapping.
++ */
++static int
++blktap_ring_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++	int size, err;
++	struct page **map;
++	struct blktap *tap;
++	blkif_sring_t *sring;
++	struct blktap_ring *ring;
++
++	tap   = filp->private_data;
++	ring  = &tap->ring;
++	map   = NULL;
++	sring = NULL;
++
++	if (!tap || test_and_set_bit(BLKTAP_RING_VMA, &tap->dev_inuse))
++		return -ENOMEM;
++
++	size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++	if (size != (MMAP_PAGES + RING_PAGES)) {
++		BTERR("you _must_ map exactly %lu pages!\n",
++		      MMAP_PAGES + RING_PAGES);
++		return -EAGAIN;
++	}
++
++	/* Allocate the fe ring. */
++	sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
++	if (!sring) {
++		BTERR("Couldn't alloc sring.\n");
++		goto fail_mem;
++	}
++
++	map = kzalloc(size * sizeof(struct page *), GFP_KERNEL);
++	if (!map) {
++		BTERR("Couldn't alloc VM_FOREIGN map.\n");
++		goto fail_mem;
++	}
++
++	SetPageReserved(virt_to_page(sring));
++    
++	SHARED_RING_INIT(sring);
++	FRONT_RING_INIT(&ring->ring, sring, PAGE_SIZE);
++
++	ring->ring_vstart = vma->vm_start;
++	ring->user_vstart = ring->ring_vstart + (RING_PAGES << PAGE_SHIFT);
++
++	/* Map the ring pages to the start of the region and reserve it. */
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		err = vm_insert_page(vma, vma->vm_start,
++				     virt_to_page(ring->ring.sring));
++	else
++		err = remap_pfn_range(vma, vma->vm_start,
++				      __pa(ring->ring.sring) >> PAGE_SHIFT,
++				      PAGE_SIZE, vma->vm_page_prot);
++	if (err) {
++		BTERR("Mapping user ring failed: %d\n", err);
++		goto fail;
++	}
++
++	/* Mark this VM as containing foreign pages, and set up mappings. */
++	ring->foreign_map.map = map;
++	vma->vm_private_data = &ring->foreign_map;
++	vma->vm_flags |= VM_FOREIGN;
++	vma->vm_flags |= VM_DONTCOPY;
++	vma->vm_flags |= VM_RESERVED;
++	vma->vm_ops = &blktap_ring_vm_operations;
++
++#ifdef CONFIG_X86
++	vma->vm_mm->context.has_foreign_mappings = 1;
++#endif
++
++	tap->pid = current->pid;
++	BTINFO("blktap: mapping pid is %d\n", tap->pid);
++
++	ring->vma = vma;
++	return 0;
++
++ fail:
++	/* Clear any active mappings. */
++	zap_page_range(vma, vma->vm_start, 
++		       vma->vm_end - vma->vm_start, NULL);
++	ClearPageReserved(virt_to_page(sring));
++ fail_mem:
++	free_page((unsigned long)sring);
++	kfree(map);
++
++	return -ENOMEM;
++}
++
++static inline void
++blktap_ring_set_message(struct blktap *tap, int msg)
++{
++	struct blktap_ring *ring = &tap->ring;
++
++	down_read(&tap->tap_sem);
++	if (ring->ring.sring)
++		ring->ring.sring->pad[0] = msg;
++	up_read(&tap->tap_sem);
++}
++
++static int
++blktap_ring_ioctl(struct inode *inode, struct file *filp,
++		  unsigned int cmd, unsigned long arg)
++{
++	struct blktap_params params;
++	struct blktap *tap = filp->private_data;
++
++	BTDBG("%d: cmd: %u, arg: %lu\n", tap->minor, cmd, arg);
++
++	switch(cmd) {
++	case BLKTAP2_IOCTL_KICK_FE:
++		/* There are fe messages to process. */
++		return blktap_read_ring(tap);
++
++	case BLKTAP2_IOCTL_CREATE_DEVICE:
++		if (!arg)
++			return -EINVAL;
++
++		if (copy_from_user(&params, (struct blktap_params __user *)arg,
++				   sizeof(params))) {
++			BTERR("failed to get params\n");
++			return -EFAULT;
++		}
++
++		if (blktap_validate_params(tap, &params)) {
++			BTERR("invalid params\n");
++			return -EINVAL;
++		}
++
++		tap->params = params;
++		return blktap_device_create(tap);
++
++	case BLKTAP2_IOCTL_SET_PARAMS:
++		if (!arg)
++			return -EINVAL;
++
++		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++			return -EINVAL;
++
++		if (copy_from_user(&params, (struct blktap_params __user *)arg,
++				   sizeof(params))) {
++			BTERR("failed to get params\n");
++			return -EFAULT;
++		}
++
++		if (blktap_validate_params(tap, &params)) {
++			BTERR("invalid params\n");
++			return -EINVAL;
++		}
++
++		tap->params = params;
++		return 0;
++
++	case BLKTAP2_IOCTL_PAUSE:
++		if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse))
++			return -EINVAL;
++
++		set_bit(BLKTAP_PAUSED, &tap->dev_inuse);
++		clear_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse);
++
++		blktap_ring_set_message(tap, 0);
++		wake_up_interruptible(&tap->wq);
++
++		return 0;
++
++
++	case BLKTAP2_IOCTL_REOPEN:
++		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++			return -EINVAL;
++
++		if (!arg)
++			return -EINVAL;
++
++		if (copy_to_user((char __user *)arg,
++				 tap->params.name,
++				 strlen(tap->params.name) + 1))
++			return -EFAULT;
++
++		blktap_ring_set_message(tap, 0);
++		wake_up_interruptible(&tap->wq);
++
++		return 0;
++
++	case BLKTAP2_IOCTL_RESUME:
++		if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++			return -EINVAL;
++
++		tap->ring.response = (int)arg;
++		if (!tap->ring.response)
++			clear_bit(BLKTAP_PAUSED, &tap->dev_inuse);
++
++		blktap_ring_set_message(tap, 0);
++		wake_up_interruptible(&tap->wq);
++
++		return 0;
++	}
++
++	return -ENOIOCTLCMD;
++}
++
++static unsigned int blktap_ring_poll(struct file *filp, poll_table *wait)
++{
++	struct blktap *tap = filp->private_data;
++	struct blktap_ring *ring = &tap->ring;
++
++	poll_wait(filp, &ring->poll_wait, wait);
++	if (ring->ring.sring->pad[0] != 0 ||
++	    ring->ring.req_prod_pvt != ring->ring.sring->req_prod) {
++		RING_PUSH_REQUESTS(&ring->ring);
++		return POLLIN | POLLRDNORM;
++	}
++
++	return 0;
++}
++
++static struct file_operations blktap_ring_file_operations = {
++	.owner    = THIS_MODULE,
++	.open     = blktap_ring_open,
++	.release  = blktap_ring_release,
++	.ioctl    = blktap_ring_ioctl,
++	.mmap     = blktap_ring_mmap,
++	.poll     = blktap_ring_poll,
++};
++
++void
++blktap_ring_kick_user(struct blktap *tap)
++{
++	wake_up_interruptible(&tap->ring.poll_wait);
++}
++
++int
++blktap_ring_resume(struct blktap *tap)
++{
++	int err;
++	struct blktap_ring *ring = &tap->ring;
++
++	if (!blktap_active(tap))
++		return -ENODEV;
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return -EINVAL;
++
++	/* set shared flag for resume */
++	ring->response = 0;
++
++	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_RESUME);
++	blktap_ring_kick_user(tap);
++
++	wait_event_interruptible(tap->wq, ring->response ||
++				 !test_bit(BLKTAP_PAUSED, &tap->dev_inuse));
++
++	err = ring->response;
++	ring->response = 0;
++
++	BTDBG("err: %d\n", err);
++
++	if (err)
++		return err;
++
++	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return -EAGAIN;
++
++	return 0;
++}
++
++int
++blktap_ring_pause(struct blktap *tap)
++{
++	if (!blktap_active(tap))
++		return -ENODEV;
++
++	if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse))
++		return -EINVAL;
++
++	BTDBG("draining queue\n");
++	wait_event_interruptible(tap->wq, !tap->pending_cnt);
++	if (tap->pending_cnt)
++		return -EAGAIN;
++
++	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_PAUSE);
++	blktap_ring_kick_user(tap);
++
++	BTDBG("waiting for tapdisk response\n");
++	wait_event_interruptible(tap->wq, test_bit(BLKTAP_PAUSED, &tap->dev_inuse));
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse))
++		return -EAGAIN;
++
++	return 0;
++}
++
++int
++blktap_ring_destroy(struct blktap *tap)
++{
++	if (!test_bit(BLKTAP_RING_FD, &tap->dev_inuse) &&
++	    !test_bit(BLKTAP_RING_VMA, &tap->dev_inuse))
++		return 0;
++
++	BTDBG("sending tapdisk close message\n");
++	blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_CLOSE);
++	blktap_ring_kick_user(tap);
++
++	return -EAGAIN;
++}
++
++static void
++blktap_ring_initialize(struct blktap_ring *ring, int minor)
++{
++	memset(ring, 0, sizeof(*ring));
++	init_waitqueue_head(&ring->poll_wait);
++	ring->devno = MKDEV(blktap_ring_major, minor);
++}
++
++int
++blktap_ring_create(struct blktap *tap)
++{
++	struct blktap_ring *ring = &tap->ring;
++	blktap_ring_initialize(ring, tap->minor);
++	return blktap_sysfs_create(tap);
++}
++
++int __init
++blktap_ring_init(int *major)
++{
++	int err;
++
++	err = register_chrdev(0, "blktap2", &blktap_ring_file_operations);
++	if (err < 0) {
++		BTERR("error registering blktap ring device: %d\n", err);
++		return err;
++	}
++
++	blktap_ring_major = *major = err;
++	BTINFO("blktap ring major: %d\n", blktap_ring_major);
++	return 0;
++}
++
++int
++blktap_ring_free(void)
++{
++	if (blktap_ring_major)
++		unregister_chrdev(blktap_ring_major, "blktap2");
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/sysfs.c	2009-12-16 11:43:21.000000000 +0100
+@@ -0,0 +1,425 @@
++#include <linux/types.h>
++#include <linux/device.h>
++#include <linux/module.h>
++
++#include "blktap.h"
++
++int blktap_debug_level = 1;
++
++static struct class *class;
++static DECLARE_WAIT_QUEUE_HEAD(sysfs_wq);
++
++static inline void
++blktap_sysfs_get(struct blktap *tap)
++{
++	atomic_inc(&tap->ring.sysfs_refcnt);
++}
++
++static inline void
++blktap_sysfs_put(struct blktap *tap)
++{
++	if (atomic_dec_and_test(&tap->ring.sysfs_refcnt))
++		wake_up(&sysfs_wq);
++}
++
++static inline void
++blktap_sysfs_enter(struct blktap *tap)
++{
++	blktap_sysfs_get(tap);               /* pin sysfs device */
++	mutex_lock(&tap->ring.sysfs_mutex);  /* serialize sysfs operations */
++}
++
++static inline void
++blktap_sysfs_exit(struct blktap *tap)
++{
++	mutex_unlock(&tap->ring.sysfs_mutex);
++	blktap_sysfs_put(tap);
++}
++
++static ssize_t blktap_sysfs_pause_device(struct class_device *, const char *, size_t);
++CLASS_DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device);
++static ssize_t blktap_sysfs_resume_device(struct class_device *, const char *, size_t);
++CLASS_DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device);
++
++static ssize_t
++blktap_sysfs_set_name(struct class_device *dev, const char *buf, size_t size)
++{
++	int err;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	blktap_sysfs_enter(tap);
++
++	if (!tap->ring.dev ||
++	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
++		err = -ENODEV;
++		goto out;
++	}
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
++		err = -EPERM;
++		goto out;
++	}
++
++	if (size > BLKTAP2_MAX_MESSAGE_LEN) {
++		err = -ENAMETOOLONG;
++		goto out;
++	}
++
++	if (strnlen(buf, BLKTAP2_MAX_MESSAGE_LEN) >= BLKTAP2_MAX_MESSAGE_LEN) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	snprintf(tap->params.name, sizeof(tap->params.name) - 1, "%s", buf);
++	err = size;
++
++out:
++	blktap_sysfs_exit(tap);	
++	return err;
++}
++
++static ssize_t
++blktap_sysfs_get_name(struct class_device *dev, char *buf)
++{
++	ssize_t size;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	blktap_sysfs_enter(tap);
++
++	if (!tap->ring.dev)
++		size = -ENODEV;
++	else if (tap->params.name[0])
++		size = sprintf(buf, "%s\n", tap->params.name);
++	else
++		size = sprintf(buf, "%d\n", tap->minor);
++
++	blktap_sysfs_exit(tap);
++
++	return size;
++}
++CLASS_DEVICE_ATTR(name, S_IRUSR | S_IWUSR,
++		  blktap_sysfs_get_name, blktap_sysfs_set_name);
++
++static ssize_t
++blktap_sysfs_remove_device(struct class_device *dev,
++			   const char *buf, size_t size)
++{
++	int err;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	if (!tap->ring.dev)
++		return size;
++
++	if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse))
++		return -EBUSY;
++
++	err = blktap_control_destroy_device(tap);
++
++	return (err ? : size);
++}
++CLASS_DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device);
++
++static ssize_t
++blktap_sysfs_pause_device(struct class_device *dev,
++			  const char *buf, size_t size)
++{
++	int err;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	blktap_sysfs_enter(tap);
++
++	BTDBG("pausing %u:%u: dev_inuse: %lu\n",
++	      MAJOR(tap->ring.devno), MINOR(tap->ring.devno), tap->dev_inuse);
++
++	if (!tap->ring.dev ||
++	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
++		err = -ENODEV;
++		goto out;
++	}
++
++	if (test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) {
++		err = -EBUSY;
++		goto out;
++	}
++
++	if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
++		err = 0;
++		goto out;
++	}
++
++	err = blktap_device_pause(tap);
++	if (!err) {
++		class_device_remove_file(dev, &class_device_attr_pause);
++		class_device_create_file(dev, &class_device_attr_resume);
++	}
++
++out:
++	blktap_sysfs_exit(tap);
++
++	return (err ? err : size);
++}
++
++static ssize_t
++blktap_sysfs_resume_device(struct class_device *dev,
++			   const char *buf, size_t size)
++{
++	int err;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	blktap_sysfs_enter(tap);
++
++	if (!tap->ring.dev ||
++	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
++		err = -ENODEV;
++		goto out;
++	}
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	err = blktap_device_resume(tap);
++	if (!err) {
++		class_device_remove_file(dev, &class_device_attr_resume);
++		class_device_create_file(dev, &class_device_attr_pause);
++	}
++
++out:
++	blktap_sysfs_exit(tap);
++
++	BTDBG("returning %zd\n", (err ? err : size));
++	return (err ? err : size);
++}
++
++#ifdef ENABLE_PASSTHROUGH
++static ssize_t
++blktap_sysfs_enable_passthrough(struct class_device *dev,
++				const char *buf, size_t size)
++{
++	int err;
++	unsigned major, minor;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	BTINFO("passthrough request enabled\n");
++
++	blktap_sysfs_enter(tap);
++
++	if (!tap->ring.dev ||
++	    test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) {
++		err = -ENODEV;
++		goto out;
++	}
++
++	if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	if (test_bit(BLKTAP_PASSTHROUGH, &tap->dev_inuse)) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	err = sscanf(buf, "%x:%x", &major, &minor);
++	if (err != 2) {
++		err = -EINVAL;
++		goto out;
++	}
++
++	err = blktap_device_enable_passthrough(tap, major, minor);
++
++out:
++	blktap_sysfs_exit(tap);
++	BTDBG("returning %d\n", (err ? err : size));
++	return (err ? err : size);
++}
++#endif
++
++static ssize_t
++blktap_sysfs_debug_device(struct class_device *dev, char *buf)
++{
++	char *tmp;
++	int i, ret;
++	struct blktap *tap = (struct blktap *)dev->class_data;
++
++	tmp = buf;
++	blktap_sysfs_get(tap);
++
++	if (!tap->ring.dev) {
++		ret = sprintf(tmp, "no device\n");
++		goto out;
++	}
++
++	tmp += sprintf(tmp, "%s (%u:%u), refcnt: %d, dev_inuse: 0x%08lx\n",
++		       tap->params.name, MAJOR(tap->ring.devno),
++		       MINOR(tap->ring.devno), atomic_read(&tap->refcnt),
++		       tap->dev_inuse);
++	tmp += sprintf(tmp, "capacity: 0x%llx, sector size: 0x%lx, "
++		       "device users: %d\n", tap->params.capacity,
++		       tap->params.sector_size, tap->device.users);
++
++	down_read(&tap->tap_sem);
++
++	tmp += sprintf(tmp, "pending requests: %d\n", tap->pending_cnt);
++	for (i = 0; i < MAX_PENDING_REQS; i++) {
++		struct blktap_request *req = tap->pending_requests[i];
++		if (!req)
++			continue;
++
++		tmp += sprintf(tmp, "req %d: id: %llu, usr_idx: %d, "
++			       "status: 0x%02x, pendcnt: %d, "
++			       "nr_pages: %u, op: %d, time: %lu:%lu\n",
++			       i, (unsigned long long)req->id, req->usr_idx,
++			       req->status, atomic_read(&req->pendcnt),
++			       req->nr_pages, req->operation, req->time.tv_sec,
++			       req->time.tv_usec);
++	}
++
++	up_read(&tap->tap_sem);
++	ret = (tmp - buf) + 1;
++
++out:
++	blktap_sysfs_put(tap);
++	BTDBG("%s\n", buf);
++
++	return ret;
++}
++CLASS_DEVICE_ATTR(debug, S_IRUSR, blktap_sysfs_debug_device, NULL);
++
++int
++blktap_sysfs_create(struct blktap *tap)
++{
++	struct blktap_ring *ring;
++	struct class_device *dev;
++
++	if (!class)
++		return -ENODEV;
++
++	ring = &tap->ring;
++
++	dev = class_device_create(class, NULL, ring->devno,
++				  NULL, "blktap%d", tap->minor);
++	if (IS_ERR(dev))
++		return PTR_ERR(dev);
++
++	ring->dev       = dev;
++	dev->class_data = tap;
++
++	mutex_init(&ring->sysfs_mutex);
++	atomic_set(&ring->sysfs_refcnt, 0);
++	set_bit(BLKTAP_SYSFS, &tap->dev_inuse);
++
++	class_device_create_file(dev, &class_device_attr_name);
++	class_device_create_file(dev, &class_device_attr_remove);
++	class_device_create_file(dev, &class_device_attr_pause);
++	class_device_create_file(dev, &class_device_attr_debug);
++
++	return 0;
++}
++
++int
++blktap_sysfs_destroy(struct blktap *tap)
++{
++	struct blktap_ring *ring;
++	struct class_device *dev;
++
++	ring = &tap->ring;
++	dev  = ring->dev;
++	if (!class || !dev)
++		return 0;
++
++	ring->dev = NULL;
++	if (wait_event_interruptible(sysfs_wq,
++				     !atomic_read(&tap->ring.sysfs_refcnt)))
++		return -EAGAIN;
++
++	/* XXX: is it safe to remove the class from a sysfs attribute? */
++	class_device_remove_file(dev, &class_device_attr_name);
++	class_device_remove_file(dev, &class_device_attr_remove);
++	class_device_remove_file(dev, &class_device_attr_pause);
++	class_device_remove_file(dev, &class_device_attr_resume);
++	class_device_remove_file(dev, &class_device_attr_debug);
++	class_device_destroy(class, ring->devno);
++
++	clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
++
++	return 0;
++}
++
++static ssize_t
++blktap_sysfs_show_verbosity(struct class *class, char *buf)
++{
++	return sprintf(buf, "%d\n", blktap_debug_level);
++}
++
++static ssize_t
++blktap_sysfs_set_verbosity(struct class *class, const char *buf, size_t size)
++{
++	int level;
++
++	if (sscanf(buf, "%d", &level) == 1) {
++		blktap_debug_level = level;
++		return size;
++	}
++
++	return -EINVAL;
++}
++CLASS_ATTR(verbosity, S_IRUSR | S_IWUSR,
++	   blktap_sysfs_show_verbosity, blktap_sysfs_set_verbosity);
++
++static ssize_t
++blktap_sysfs_show_devices(struct class *class, char *buf)
++{
++	int i, ret;
++	struct blktap *tap;
++
++	ret = 0;
++	for (i = 0; i < MAX_BLKTAP_DEVICE; i++) {
++		tap = blktaps[i];
++		if (!tap)
++			continue;
++
++		if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse))
++			continue;
++
++		ret += sprintf(buf + ret, "%d ", tap->minor);
++		ret += snprintf(buf + ret, sizeof(tap->params.name) - 1,
++				tap->params.name);
++		ret += sprintf(buf + ret, "\n");
++	}
++
++	return ret;
++}
++CLASS_ATTR(devices, S_IRUSR, blktap_sysfs_show_devices, NULL);
++
++void
++blktap_sysfs_free(void)
++{
++	if (!class)
++		return;
++
++	class_remove_file(class, &class_attr_verbosity);
++	class_remove_file(class, &class_attr_devices);
++
++	class_destroy(class);
++}
++
++int __init
++blktap_sysfs_init(void)
++{
++	struct class *cls;
++
++	if (class)
++		return -EEXIST;
++
++	cls = class_create(THIS_MODULE, "blktap2");
++	if (IS_ERR(cls))
++		return PTR_ERR(cls);
++
++	class_create_file(cls, &class_attr_verbosity);
++	class_create_file(cls, &class_attr_devices);
++
++	class = cls;
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/blktap2/wait_queue.c	2009-05-29 10:25:53.000000000 +0200
+@@ -0,0 +1,40 @@
++#include <linux/list.h>
++#include <linux/spinlock.h>
++
++#include "blktap.h"
++
++static LIST_HEAD(deferred_work_queue);
++static DEFINE_SPINLOCK(deferred_work_lock);
++
++void
++blktap_run_deferred(void)
++{
++	LIST_HEAD(queue);
++	struct blktap *tap;
++	unsigned long flags;
++
++	spin_lock_irqsave(&deferred_work_lock, flags);
++	list_splice_init(&deferred_work_queue, &queue);
++	list_for_each_entry(tap, &queue, deferred_queue)
++		clear_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
++	spin_unlock_irqrestore(&deferred_work_lock, flags);
++
++	while (!list_empty(&queue)) {
++		tap = list_entry(queue.next, struct blktap, deferred_queue);
++		list_del_init(&tap->deferred_queue);
++		blktap_device_restart(tap);
++	}
++}
++
++void
++blktap_defer(struct blktap *tap)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&deferred_work_lock, flags);
++	if (!test_bit(BLKTAP_DEFERRED, &tap->dev_inuse)) {
++		set_bit(BLKTAP_DEFERRED, &tap->dev_inuse);
++		list_add_tail(&tap->deferred_queue, &deferred_work_queue);
++	}
++	spin_unlock_irqrestore(&deferred_work_lock, flags);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/char/Makefile	2007-07-10 09:42:30.000000000 +0200
+@@ -0,0 +1 @@
++obj-$(CONFIG_XEN_DEVMEM)	:= mem.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/char/mem.c	2007-08-06 15:10:49.000000000 +0200
+@@ -0,0 +1,190 @@
++/*
++ *  Originally from linux/drivers/char/mem.c
++ *
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ *
++ *  Added devfs support. 
++ *    Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
++ *  Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
++ */
++
++#include <linux/mm.h>
++#include <linux/miscdevice.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/mman.h>
++#include <linux/random.h>
++#include <linux/init.h>
++#include <linux/raw.h>
++#include <linux/tty.h>
++#include <linux/capability.h>
++#include <linux/smp_lock.h>
++#include <linux/ptrace.h>
++#include <linux/device.h>
++#include <asm/pgalloc.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/hypervisor.h>
++
++static inline int uncached_access(struct file *file)
++{
++	if (file->f_flags & O_SYNC)
++		return 1;
++	/* Xen sets correct MTRR type on non-RAM for us. */
++	return 0;
++}
++
++/*
++ * This funcion reads the *physical* memory. The f_pos points directly to the 
++ * memory location. 
++ */
++static ssize_t read_mem(struct file * file, char __user * buf,
++			size_t count, loff_t *ppos)
++{
++	unsigned long p = *ppos, ignored;
++	ssize_t read = 0, sz;
++	void __iomem *v;
++
++	while (count > 0) {
++		/*
++		 * Handle first page in case it's not aligned
++		 */
++		if (-p & (PAGE_SIZE - 1))
++			sz = -p & (PAGE_SIZE - 1);
++		else
++			sz = PAGE_SIZE;
++
++		sz = min_t(unsigned long, sz, count);
++
++		v = ioremap(p, sz);
++		if (IS_ERR(v) || v == NULL) {
++			/*
++			 * Some programs (e.g., dmidecode) groove off into
++			 * weird RAM areas where no tables can possibly exist
++			 * (because Xen will have stomped on them!). These
++			 * programs get rather upset if we let them know that
++			 * Xen failed their access, so we fake out a read of
++			 * all zeroes.
++			 */
++			if (clear_user(buf, count))
++				return -EFAULT;
++			read += count;
++			break;
++		}
++
++		ignored = copy_to_user(buf, v, sz);
++		iounmap(v);
++		if (ignored)
++			return -EFAULT;
++		buf += sz;
++		p += sz;
++		count -= sz;
++		read += sz;
++	}
++
++	*ppos += read;
++	return read;
++}
++
++static ssize_t write_mem(struct file * file, const char __user * buf, 
++			 size_t count, loff_t *ppos)
++{
++	unsigned long p = *ppos, ignored;
++	ssize_t written = 0, sz;
++	void __iomem *v;
++
++	while (count > 0) {
++		/*
++		 * Handle first page in case it's not aligned
++		 */
++		if (-p & (PAGE_SIZE - 1))
++			sz = -p & (PAGE_SIZE - 1);
++		else
++			sz = PAGE_SIZE;
++
++		sz = min_t(unsigned long, sz, count);
++
++		v = ioremap(p, sz);
++		if (v == NULL)
++			break;
++		if (IS_ERR(v)) {
++			if (written == 0)
++				return PTR_ERR(v);
++			break;
++		}
++
++		ignored = copy_from_user(v, buf, sz);
++		iounmap(v);
++		if (ignored) {
++			written += sz - ignored;
++			if (written)
++				break;
++			return -EFAULT;
++		}
++		buf += sz;
++		p += sz;
++		count -= sz;
++		written += sz;
++	}
++
++	*ppos += written;
++	return written;
++}
++
++#ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
++static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma)
++{
++	size_t size = vma->vm_end - vma->vm_start;
++
++	if (uncached_access(file))
++		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++	/* We want to return the real error code, not EAGAIN. */
++	return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++				      size, vma->vm_page_prot, DOMID_IO);
++}
++#endif
++
++/*
++ * The memory devices use the full 32/64 bits of the offset, and so we cannot
++ * check against negative addresses: they are ok. The return value is weird,
++ * though, in that case (0).
++ *
++ * also note that seeking relative to the "end of file" isn't supported:
++ * it has no meaning, so it returns -EINVAL.
++ */
++static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
++{
++	loff_t ret;
++
++	mutex_lock(&file->f_dentry->d_inode->i_mutex);
++	switch (orig) {
++		case 0:
++			file->f_pos = offset;
++			ret = file->f_pos;
++			force_successful_syscall_return();
++			break;
++		case 1:
++			file->f_pos += offset;
++			ret = file->f_pos;
++			force_successful_syscall_return();
++			break;
++		default:
++			ret = -EINVAL;
++	}
++	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++	return ret;
++}
++
++static int open_mem(struct inode * inode, struct file * filp)
++{
++	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
++}
++
++const struct file_operations mem_fops = {
++	.llseek		= memory_lseek,
++	.read		= read_mem,
++	.write		= write_mem,
++	.mmap		= xen_mmap_mem,
++	.open		= open_mem,
++};
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/console/Makefile	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y	:= console.o xencons_ring.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/console/console.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,753 @@
++/******************************************************************************
++ * console.c
++ * 
++ * Virtual console driver.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser.
++ * 
++ * 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 <linux/module.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/major.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/bootmem.h>
++#include <linux/sysrq.h>
++#include <linux/screen_info.h>
++#include <linux/vt.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/event_channel.h>
++#include <asm/hypervisor.h>
++#include <xen/evtchn.h>
++#include <xen/xenbus.h>
++#include <xen/xencons.h>
++
++/*
++ * Modes:
++ *  'xencons=off'  [XC_OFF]:     Console is disabled.
++ *  'xencons=tty'  [XC_TTY]:     Console attached to '/dev/tty[0-9]+'.
++ *  'xencons=ttyS' [XC_SERIAL]:  Console attached to '/dev/ttyS[0-9]+'.
++ *  'xencons=xvc'  [XC_XVC]:     Console attached to '/dev/xvc0'.
++ *  'xencons=hvc'  [XC_HVC]:     Console attached to '/dev/hvc0'.
++ *  default:                     XC_XVC
++ * 
++ * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
++ * warnings from standard distro startup scripts.
++ */
++static enum {
++	XC_OFF, XC_TTY, XC_SERIAL, XC_XVC, XC_HVC
++} xc_mode = XC_XVC;
++static int xc_num = -1;
++
++/* /dev/xvc0 device number allocated by lanana.org. */
++#define XEN_XVC_MAJOR 204
++#define XEN_XVC_MINOR 191
++
++/* /dev/hvc0 device number */
++#define XEN_HVC_MAJOR 229
++#define XEN_HVC_MINOR 0
++
++#ifdef CONFIG_MAGIC_SYSRQ
++static unsigned long sysrq_requested;
++extern int sysrq_enabled;
++#endif
++
++static int __init xencons_setup(char *str)
++{
++	char *q;
++	int n;
++	extern int console_use_vt;
++
++	console_use_vt = 1;
++	if (!strncmp(str, "ttyS", 4)) {
++		xc_mode = XC_SERIAL;
++		str += 4;
++	} else if (!strncmp(str, "tty", 3)) {
++		xc_mode = XC_TTY;
++		str += 3;
++		console_use_vt = 0;
++	} else if (!strncmp(str, "xvc", 3)) {
++		xc_mode = XC_XVC;
++		str += 3;
++	} else if (!strncmp(str, "hvc", 3)) {
++		xc_mode = XC_HVC;
++		str += 3;
++	} else if (!strncmp(str, "off", 3)) {
++		xc_mode = XC_OFF;
++		str += 3;
++	}
++
++	n = simple_strtol(str, &q, 10);
++	if (q != str)
++		xc_num = n;
++
++	return 1;
++}
++__setup("xencons=", xencons_setup);
++
++/* The kernel and user-land drivers share a common transmit buffer. */
++static unsigned int wbuf_size = 4096;
++#define WBUF_MASK(_i) ((_i)&(wbuf_size-1))
++static char *wbuf;
++static unsigned int wc, wp; /* write_cons, write_prod */
++
++static int __init xencons_bufsz_setup(char *str)
++{
++	unsigned int goal;
++	goal = simple_strtoul(str, NULL, 0);
++	if (goal) {
++		goal = roundup_pow_of_two(goal);
++		if (wbuf_size < goal)
++			wbuf_size = goal;
++	}
++	return 1;
++}
++__setup("xencons_bufsz=", xencons_bufsz_setup);
++
++/* This lock protects accesses to the common transmit buffer. */
++static DEFINE_SPINLOCK(xencons_lock);
++
++/* Common transmit-kick routine. */
++static void __xencons_tx_flush(void);
++
++static struct tty_driver *xencons_driver;
++
++/******************** Kernel console driver ********************************/
++
++static void kcons_write(struct console *c, const char *s, unsigned int count)
++{
++	int           i = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++
++	while (i < count) {
++		for (; i < count; i++) {
++			if ((wp - wc) >= (wbuf_size - 1))
++				break;
++			if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n')
++				wbuf[WBUF_MASK(wp++)] = '\r';
++		}
++
++		__xencons_tx_flush();
++	}
++
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static void kcons_write_dom0(struct console *c, const char *s, unsigned int count)
++{
++
++	while (count > 0) {
++		int rc;
++		rc = HYPERVISOR_console_io( CONSOLEIO_write, count, (char *)s);
++		if (rc <= 0)
++			break;
++		count -= rc;
++		s += rc;
++	}
++}
++
++static struct tty_driver *kcons_device(struct console *c, int *index)
++{
++	*index = 0;
++	return xencons_driver;
++}
++
++static struct console kcons_info = {
++	.device	= kcons_device,
++	.flags	= CON_PRINTBUFFER | CON_ENABLED,
++	.index	= -1,
++};
++
++static int __init xen_console_init(void)
++{
++	if (!is_running_on_xen())
++		goto out;
++
++	if (is_initial_xendomain()) {
++		kcons_info.write = kcons_write_dom0;
++	} else {
++		if (!xen_start_info->console.domU.evtchn)
++			goto out;
++		kcons_info.write = kcons_write;
++	}
++
++	switch (xc_mode) {
++	case XC_XVC:
++		strcpy(kcons_info.name, "xvc");
++		if (xc_num == -1)
++			xc_num = 0;
++		break;
++
++	case XC_HVC:
++		strcpy(kcons_info.name, "hvc");
++		if (xc_num == -1)
++			xc_num = 0;
++		if (!is_initial_xendomain())
++			add_preferred_console(kcons_info.name, xc_num, NULL);
++		break;
++
++	case XC_SERIAL:
++		strcpy(kcons_info.name, "ttyS");
++		if (xc_num == -1)
++			xc_num = 0;
++		break;
++
++	case XC_TTY:
++		strcpy(kcons_info.name, "tty");
++		if (xc_num == -1)
++			xc_num = 1;
++		break;
++
++	default:
++		goto out;
++	}
++
++	wbuf = alloc_bootmem(wbuf_size);
++
++	register_console(&kcons_info);
++
++ out:
++	return 0;
++}
++console_initcall(xen_console_init);
++
++/*** Useful function for console debugging -- goes straight to Xen. ***/
++asmlinkage int xprintk(const char *fmt, ...)
++{
++	va_list args;
++	int printk_len;
++	static char printk_buf[1024];
++
++	/* Emit the output into the temporary buffer */
++	va_start(args, fmt);
++	printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
++	va_end(args);
++
++	/* Send the processed output directly to Xen. */
++	kcons_write_dom0(NULL, printk_buf, printk_len);
++
++	return 0;
++}
++
++/*** Forcibly flush console data before dying. ***/
++void xencons_force_flush(void)
++{
++	int sz;
++
++	/* Emergency console is synchronous, so there's nothing to flush. */
++	if (!is_running_on_xen() ||
++	    is_initial_xendomain() ||
++	    !xen_start_info->console.domU.evtchn)
++		return;
++
++	/* Spin until console data is flushed through to the daemon. */
++	while (wc != wp) {
++		int sent = 0;
++		if ((sz = wp - wc) == 0)
++			continue;
++		sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
++		if (sent > 0)
++			wc += sent;
++	}
++}
++
++
++void __init dom0_init_screen_info(const struct dom0_vga_console_info *info, size_t size)
++{
++	/* This is drawn from a dump from vgacon:startup in
++	 * standard Linux. */
++	screen_info.orig_video_mode = 3;
++	screen_info.orig_video_isVGA = 1;
++	screen_info.orig_video_lines = 25;
++	screen_info.orig_video_cols = 80;
++	screen_info.orig_video_ega_bx = 3;
++	screen_info.orig_video_points = 16;
++	screen_info.orig_y = screen_info.orig_video_lines - 1;
++
++	switch (info->video_type) {
++	case XEN_VGATYPE_TEXT_MODE_3:
++		if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
++		           + sizeof(info->u.text_mode_3))
++			break;
++		screen_info.orig_video_lines = info->u.text_mode_3.rows;
++		screen_info.orig_video_cols = info->u.text_mode_3.columns;
++		screen_info.orig_x = info->u.text_mode_3.cursor_x;
++		screen_info.orig_y = info->u.text_mode_3.cursor_y;
++		screen_info.orig_video_points =
++			info->u.text_mode_3.font_height;
++		break;
++
++	case XEN_VGATYPE_VESA_LFB:
++		if (size < offsetof(struct dom0_vga_console_info,
++		                    u.vesa_lfb.gbl_caps))
++			break;
++		screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
++		screen_info.lfb_width = info->u.vesa_lfb.width;
++		screen_info.lfb_height = info->u.vesa_lfb.height;
++		screen_info.lfb_depth = info->u.vesa_lfb.bits_per_pixel;
++		screen_info.lfb_base = info->u.vesa_lfb.lfb_base;
++		screen_info.lfb_size = info->u.vesa_lfb.lfb_size;
++		screen_info.lfb_linelength = info->u.vesa_lfb.bytes_per_line;
++		screen_info.red_size = info->u.vesa_lfb.red_size;
++		screen_info.red_pos = info->u.vesa_lfb.red_pos;
++		screen_info.green_size = info->u.vesa_lfb.green_size;
++		screen_info.green_pos = info->u.vesa_lfb.green_pos;
++		screen_info.blue_size = info->u.vesa_lfb.blue_size;
++		screen_info.blue_pos = info->u.vesa_lfb.blue_pos;
++		screen_info.rsvd_size = info->u.vesa_lfb.rsvd_size;
++		screen_info.rsvd_pos = info->u.vesa_lfb.rsvd_pos;
++		if (size >= offsetof(struct dom0_vga_console_info,
++		                     u.vesa_lfb.gbl_caps)
++		            + sizeof(info->u.vesa_lfb.gbl_caps))
++			screen_info.capabilities = info->u.vesa_lfb.gbl_caps;
++		if (size >= offsetof(struct dom0_vga_console_info,
++		                     u.vesa_lfb.mode_attrs)
++		            + sizeof(info->u.vesa_lfb.mode_attrs))
++			screen_info.vesa_attributes = info->u.vesa_lfb.mode_attrs;
++		break;
++	}
++}
++
++
++/******************** User-space console driver (/dev/console) ************/
++
++#define DRV(_d)         (_d)
++#define DUMMY_TTY(_tty) ((xc_mode == XC_TTY) &&		\
++			 ((_tty)->index != (xc_num - 1)))
++
++static struct termios *xencons_termios[MAX_NR_CONSOLES];
++static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
++static struct tty_struct *xencons_tty;
++static int xencons_priv_irq;
++static char x_char;
++
++void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
++{
++	int           i;
++	unsigned long flags;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	if (xencons_tty == NULL)
++		goto out;
++
++	for (i = 0; i < len; i++) {
++#ifdef CONFIG_MAGIC_SYSRQ
++		if (sysrq_enabled) {
++			if (buf[i] == '\x0f') { /* ^O */
++				if (!sysrq_requested) {
++					sysrq_requested = jiffies;
++					continue; /* don't print sysrq key */
++				}
++				sysrq_requested = 0;
++			} else if (sysrq_requested) {
++				unsigned long sysrq_timeout =
++					sysrq_requested + HZ*2;
++				sysrq_requested = 0;
++				if (time_before(jiffies, sysrq_timeout)) {
++					spin_unlock_irqrestore(
++						&xencons_lock, flags);
++					handle_sysrq(
++						buf[i], regs, xencons_tty);
++					spin_lock_irqsave(
++						&xencons_lock, flags);
++					continue;
++				}
++			}
++		}
++#endif
++		tty_insert_flip_char(xencons_tty, buf[i], 0);
++	}
++	tty_flip_buffer_push(xencons_tty);
++
++ out:
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static void __xencons_tx_flush(void)
++{
++	int sent, sz, work_done = 0;
++
++	if (x_char) {
++		if (is_initial_xendomain())
++			kcons_write_dom0(NULL, &x_char, 1);
++		else
++			while (x_char)
++				if (xencons_ring_send(&x_char, 1) == 1)
++					break;
++		x_char = 0;
++		work_done = 1;
++	}
++
++	while (wc != wp) {
++		sz = wp - wc;
++		if (sz > (wbuf_size - WBUF_MASK(wc)))
++			sz = wbuf_size - WBUF_MASK(wc);
++		if (is_initial_xendomain()) {
++			kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
++			wc += sz;
++		} else {
++			sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
++			if (sent == 0)
++				break;
++			wc += sent;
++		}
++		work_done = 1;
++	}
++
++	if (work_done && (xencons_tty != NULL)) {
++		wake_up_interruptible(&xencons_tty->write_wait);
++		if ((xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++		    (xencons_tty->ldisc.write_wakeup != NULL))
++			(xencons_tty->ldisc.write_wakeup)(xencons_tty);
++	}
++}
++
++void xencons_tx(void)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	__xencons_tx_flush();
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++/* Privileged receive callback and transmit kicker. */
++static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
++					  struct pt_regs *regs)
++{
++	static char rbuf[16];
++	int         l;
++
++	while ((l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0)
++		xencons_rx(rbuf, l, regs);
++
++	xencons_tx();
++
++	return IRQ_HANDLED;
++}
++
++static int xencons_write_room(struct tty_struct *tty)
++{
++	return wbuf_size - (wp - wc);
++}
++
++static int xencons_chars_in_buffer(struct tty_struct *tty)
++{
++	return wp - wc;
++}
++
++static void xencons_send_xchar(struct tty_struct *tty, char ch)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	x_char = ch;
++	__xencons_tx_flush();
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static void xencons_throttle(struct tty_struct *tty)
++{
++	if (DUMMY_TTY(tty))
++		return;
++
++	if (I_IXOFF(tty))
++		xencons_send_xchar(tty, STOP_CHAR(tty));
++}
++
++static void xencons_unthrottle(struct tty_struct *tty)
++{
++	if (DUMMY_TTY(tty))
++		return;
++
++	if (I_IXOFF(tty)) {
++		if (x_char != 0)
++			x_char = 0;
++		else
++			xencons_send_xchar(tty, START_CHAR(tty));
++	}
++}
++
++static void xencons_flush_buffer(struct tty_struct *tty)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	wc = wp = 0;
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static inline int __xencons_put_char(int ch)
++{
++	char _ch = (char)ch;
++	if ((wp - wc) == wbuf_size)
++		return 0;
++	wbuf[WBUF_MASK(wp++)] = _ch;
++	return 1;
++}
++
++static int xencons_write(
++	struct tty_struct *tty,
++	const unsigned char *buf,
++	int count)
++{
++	int i;
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return count;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++
++	for (i = 0; i < count; i++)
++		if (!__xencons_put_char(buf[i]))
++			break;
++
++	if (i != 0)
++		__xencons_tx_flush();
++
++	spin_unlock_irqrestore(&xencons_lock, flags);
++
++	return i;
++}
++
++static void xencons_put_char(struct tty_struct *tty, u_char ch)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	(void)__xencons_put_char(ch);
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static void xencons_flush_chars(struct tty_struct *tty)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	__xencons_tx_flush();
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
++{
++	unsigned long orig_jiffies = jiffies;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	while (DRV(tty->driver)->chars_in_buffer(tty)) {
++		set_current_state(TASK_INTERRUPTIBLE);
++		schedule_timeout(1);
++		if (signal_pending(current))
++			break;
++		if (timeout && time_after(jiffies, orig_jiffies + timeout))
++			break;
++	}
++
++	set_current_state(TASK_RUNNING);
++}
++
++static int xencons_open(struct tty_struct *tty, struct file *filp)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return 0;
++
++	spin_lock_irqsave(&xencons_lock, flags);
++	tty->driver_data = NULL;
++	if (xencons_tty == NULL)
++		xencons_tty = tty;
++	__xencons_tx_flush();
++	spin_unlock_irqrestore(&xencons_lock, flags);
++
++	return 0;
++}
++
++static void xencons_close(struct tty_struct *tty, struct file *filp)
++{
++	unsigned long flags;
++
++	if (DUMMY_TTY(tty))
++		return;
++
++	mutex_lock(&tty_mutex);
++
++	if (tty->count != 1) {
++		mutex_unlock(&tty_mutex);
++		return;
++	}
++
++	/* Prevent other threads from re-opening this tty. */
++	set_bit(TTY_CLOSING, &tty->flags);
++	mutex_unlock(&tty_mutex);
++
++	tty->closing = 1;
++	tty_wait_until_sent(tty, 0);
++	if (DRV(tty->driver)->flush_buffer != NULL)
++		DRV(tty->driver)->flush_buffer(tty);
++	if (tty->ldisc.flush_buffer != NULL)
++		tty->ldisc.flush_buffer(tty);
++	tty->closing = 0;
++	spin_lock_irqsave(&xencons_lock, flags);
++	xencons_tty = NULL;
++	spin_unlock_irqrestore(&xencons_lock, flags);
++}
++
++static struct tty_operations xencons_ops = {
++	.open = xencons_open,
++	.close = xencons_close,
++	.write = xencons_write,
++	.write_room = xencons_write_room,
++	.put_char = xencons_put_char,
++	.flush_chars = xencons_flush_chars,
++	.chars_in_buffer = xencons_chars_in_buffer,
++	.send_xchar = xencons_send_xchar,
++	.flush_buffer = xencons_flush_buffer,
++	.throttle = xencons_throttle,
++	.unthrottle = xencons_unthrottle,
++	.wait_until_sent = xencons_wait_until_sent,
++};
++
++static int __init xencons_init(void)
++{
++	int rc;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	if (xc_mode == XC_OFF)
++		return 0;
++
++	if (!is_initial_xendomain()) {
++		rc = xencons_ring_init();
++		if (rc)
++			return rc;
++	}
++
++	xencons_driver = alloc_tty_driver((xc_mode == XC_TTY) ?
++					  MAX_NR_CONSOLES : 1);
++	if (xencons_driver == NULL)
++		return -ENOMEM;
++
++	DRV(xencons_driver)->name            = "xencons";
++	DRV(xencons_driver)->major           = TTY_MAJOR;
++	DRV(xencons_driver)->type            = TTY_DRIVER_TYPE_SERIAL;
++	DRV(xencons_driver)->subtype         = SERIAL_TYPE_NORMAL;
++	DRV(xencons_driver)->init_termios    = tty_std_termios;
++	DRV(xencons_driver)->flags           =
++		TTY_DRIVER_REAL_RAW |
++		TTY_DRIVER_RESET_TERMIOS;
++	DRV(xencons_driver)->termios         = xencons_termios;
++	DRV(xencons_driver)->termios_locked  = xencons_termios_locked;
++
++	switch (xc_mode) {
++	case XC_XVC:
++		DRV(xencons_driver)->name        = "xvc";
++		DRV(xencons_driver)->major       = XEN_XVC_MAJOR;
++		DRV(xencons_driver)->minor_start = XEN_XVC_MINOR;
++		DRV(xencons_driver)->name_base   = xc_num;
++		break;
++	case XC_HVC:
++		DRV(xencons_driver)->name        = "hvc";
++		DRV(xencons_driver)->major       = XEN_HVC_MAJOR;
++		DRV(xencons_driver)->minor_start = XEN_HVC_MINOR;
++		DRV(xencons_driver)->name_base   = xc_num;
++		break;
++	case XC_SERIAL:
++		DRV(xencons_driver)->name        = "ttyS";
++		DRV(xencons_driver)->minor_start = 64 + xc_num;
++		DRV(xencons_driver)->name_base   = xc_num;
++		break;
++	default:
++		DRV(xencons_driver)->name        = "tty";
++		DRV(xencons_driver)->minor_start = 1;
++		DRV(xencons_driver)->name_base   = 1;
++		break;
++	}
++
++	tty_set_operations(xencons_driver, &xencons_ops);
++
++	if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) {
++		printk("WARNING: Failed to register Xen virtual "
++		       "console driver as '%s%d'\n",
++		       DRV(xencons_driver)->name,
++		       DRV(xencons_driver)->name_base);
++		put_tty_driver(xencons_driver);
++		xencons_driver = NULL;
++		return rc;
++	}
++
++	if (is_initial_xendomain()) {
++		xencons_priv_irq = bind_virq_to_irqhandler(
++			VIRQ_CONSOLE,
++			0,
++			xencons_priv_interrupt,
++			0,
++			"console",
++			NULL);
++		BUG_ON(xencons_priv_irq < 0);
++	}
++
++	printk("Xen virtual console successfully installed as %s%d\n",
++	       DRV(xencons_driver)->name, xc_num);
++
++	return 0;
++}
++
++module_init(xencons_init);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/console/xencons_ring.c	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,143 @@
++/* 
++ * 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 <linux/module.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/major.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++
++#include <asm/hypervisor.h>
++#include <xen/evtchn.h>
++#include <xen/xencons.h>
++#include <linux/wait.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/err.h>
++#include <xen/interface/io/console.h>
++
++static int xencons_irq;
++
++static inline struct xencons_interface *xencons_interface(void)
++{
++	return mfn_to_virt(xen_start_info->console.domU.mfn);
++}
++
++static inline void notify_daemon(void)
++{
++	/* Use evtchn: this is called early, before irq is set up. */
++	notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
++}
++
++int xencons_ring_send(const char *data, unsigned len)
++{
++	int sent = 0;
++	struct xencons_interface *intf = xencons_interface();
++	XENCONS_RING_IDX cons, prod;
++
++	cons = intf->out_cons;
++	prod = intf->out_prod;
++	mb();
++	BUG_ON((prod - cons) > sizeof(intf->out));
++
++	while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
++		intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
++
++	wmb();
++	intf->out_prod = prod;
++
++	notify_daemon();
++
++	return sent;
++}
++
++static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
++{
++	struct xencons_interface *intf = xencons_interface();
++	XENCONS_RING_IDX cons, prod;
++
++	cons = intf->in_cons;
++	prod = intf->in_prod;
++	mb();
++	BUG_ON((prod - cons) > sizeof(intf->in));
++
++	while (cons != prod) {
++		xencons_rx(intf->in+MASK_XENCONS_IDX(cons,intf->in), 1, regs);
++		cons++;
++	}
++
++	mb();
++	intf->in_cons = cons;
++
++	notify_daemon();
++
++	xencons_tx();
++
++	return IRQ_HANDLED;
++}
++
++int xencons_ring_init(void)
++{
++	int irq;
++
++	if (xencons_irq)
++		unbind_from_irqhandler(xencons_irq, NULL);
++	xencons_irq = 0;
++
++	if (!is_running_on_xen() ||
++	    is_initial_xendomain() ||
++	    !xen_start_info->console.domU.evtchn)
++		return -ENODEV;
++
++	irq = bind_caller_port_to_irqhandler(
++		xen_start_info->console.domU.evtchn,
++		handle_input, 0, "xencons", NULL);
++	if (irq < 0) {
++		printk(KERN_ERR "XEN console request irq failed %i\n", irq);
++		return irq;
++	}
++
++	xencons_irq = irq;
++
++	/* In case we have in-flight data after save/restore... */
++	notify_daemon();
++
++	return 0;
++}
++
++void xencons_resume(void)
++{
++	(void)xencons_ring_init();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/Makefile	2008-07-21 11:00:33.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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/cpu_hotplug.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,176 @@
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/notifier.h>
++#include <linux/cpu.h>
++#include <xen/cpu_hotplug.h>
++#include <xen/xenbus.h>
++
++/*
++ * Set of CPUs that remote admin software will allow us to bring online.
++ * Notified to us via xenbus.
++ */
++static cpumask_t xenbus_allowed_cpumask;
++
++/* Set of CPUs that local admin will allow us to bring online. */
++static cpumask_t local_allowed_cpumask = CPU_MASK_ALL;
++
++static int local_cpu_hotplug_request(void)
++{
++	/*
++	 * We assume a CPU hotplug request comes from local admin if it is made
++	 * via a userspace process (i.e., one with a real mm_struct).
++	 */
++	return (current->mm != NULL);
++}
++
++static void vcpu_hotplug(unsigned int cpu)
++{
++	int err;
++	char dir[32], state[32];
++
++	if ((cpu >= NR_CPUS) || !cpu_possible(cpu))
++		return;
++
++	sprintf(dir, "cpu/%u", cpu);
++	err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
++	if (err != 1) {
++		printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
++		return;
++	}
++
++	if (strcmp(state, "online") == 0) {
++		cpu_set(cpu, xenbus_allowed_cpumask);
++		(void)cpu_up(cpu);
++	} else if (strcmp(state, "offline") == 0) {
++		cpu_clear(cpu, xenbus_allowed_cpumask);
++		(void)cpu_down(cpu);
++	} else {
++		printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
++		       state, cpu);
++	}
++}
++
++static void handle_vcpu_hotplug_event(
++	struct xenbus_watch *watch, const char **vec, unsigned int len)
++{
++	unsigned int cpu;
++	char *cpustr;
++	const char *node = vec[XS_WATCH_PATH];
++
++	if ((cpustr = strstr(node, "cpu/")) != NULL) {
++		sscanf(cpustr, "cpu/%u", &cpu);
++		vcpu_hotplug(cpu);
++	}
++}
++
++static int smpboot_cpu_notify(struct notifier_block *notifier,
++			      unsigned long action, void *hcpu)
++{
++	unsigned int cpu = (long)hcpu;
++
++	/*
++	 * We do this in a callback notifier rather than __cpu_disable()
++	 * because local_cpu_hotplug_request() does not work in the latter
++	 * as it's always executed from within a stopmachine kthread.
++	 */
++	if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
++		cpu_clear(cpu, local_allowed_cpumask);
++
++	return NOTIFY_OK;
++}
++
++static int setup_cpu_watcher(struct notifier_block *notifier,
++			      unsigned long event, void *data)
++{
++	unsigned int i;
++
++	static struct xenbus_watch cpu_watch = {
++		.node = "cpu",
++		.callback = handle_vcpu_hotplug_event,
++		.flags = XBWF_new_thread };
++	(void)register_xenbus_watch(&cpu_watch);
++
++	if (!is_initial_xendomain()) {
++		for_each_possible_cpu(i)
++			vcpu_hotplug(i);
++		printk(KERN_INFO "Brought up %ld CPUs\n",
++		       (long)num_online_cpus());
++	}
++
++	return NOTIFY_DONE;
++}
++
++static int __init setup_vcpu_hotplug_event(void)
++{
++	static struct notifier_block hotplug_cpu = {
++		.notifier_call = smpboot_cpu_notify };
++	static struct notifier_block xsn_cpu = {
++		.notifier_call = setup_cpu_watcher };
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	register_cpu_notifier(&hotplug_cpu);
++	register_xenstore_notifier(&xsn_cpu);
++
++	return 0;
++}
++
++arch_initcall(setup_vcpu_hotplug_event);
++
++int smp_suspend(void)
++{
++	unsigned int cpu;
++	int err;
++
++	for_each_online_cpu(cpu) {
++		if (cpu == 0)
++			continue;
++		err = cpu_down(cpu);
++		if (err) {
++			printk(KERN_CRIT "Failed to take all CPUs "
++			       "down: %d.\n", err);
++			for_each_possible_cpu(cpu)
++				vcpu_hotplug(cpu);
++			return err;
++		}
++	}
++
++	return 0;
++}
++
++void smp_resume(void)
++{
++	unsigned int cpu;
++
++	for_each_possible_cpu(cpu) {
++		if (cpu == 0)
++			continue;
++		vcpu_hotplug(cpu);
++	}
++}
++
++int cpu_up_check(unsigned int cpu)
++{
++	int rc = 0;
++
++	if (local_cpu_hotplug_request()) {
++		cpu_set(cpu, local_allowed_cpumask);
++		if (!cpu_isset(cpu, xenbus_allowed_cpumask)) {
++			printk("%s: attempt to bring up CPU %u disallowed by "
++			       "remote admin.\n", __FUNCTION__, cpu);
++			rc = -EBUSY;
++		}
++	} else if (!cpu_isset(cpu, local_allowed_cpumask) ||
++		   !cpu_isset(cpu, xenbus_allowed_cpumask)) {
++		rc = -EBUSY;
++	}
++
++	return rc;
++}
++
++void init_xenbus_allowed_cpumask(void)
++{
++	xenbus_allowed_cpumask = cpu_present_map;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,1181 @@
++/******************************************************************************
++ * evtchn.c
++ * 
++ * Communication via Xen event channels.
++ * 
++ * Copyright (c) 2002-2005, K A Fraser
++ * 
++ * 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/module.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/kernel_stat.h>
++#include <linux/bootmem.h>
++#include <linux/version.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/ptrace.h>
++#include <asm/synch_bitops.h>
++#include <xen/evtchn.h>
++#include <xen/interface/event_channel.h>
++#include <xen/interface/physdev.h>
++#include <asm/hypervisor.h>
++#include <linux/mc146818rtc.h> /* RTC_IRQ */
++
++/*
++ * This lock protects updates to the following mapping and reference-count
++ * arrays. The lock does not need to be acquired to read the mapping tables.
++ */
++static DEFINE_SPINLOCK(irq_mapping_update_lock);
++
++/* IRQ <-> event-channel mappings. */
++static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
++	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
++
++/* Packed IRQ information: binding type, sub-type index, and event channel. */
++static u32 irq_info[NR_IRQS];
++
++/* Binding types. */
++enum {
++	IRQT_UNBOUND,
++	IRQT_PIRQ,
++	IRQT_VIRQ,
++	IRQT_IPI,
++	IRQT_LOCAL_PORT,
++	IRQT_CALLER_PORT,
++	_IRQT_COUNT
++};
++
++#define _IRQT_BITS 4
++#define _EVTCHN_BITS 12
++#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
++
++/* Constructor for packed IRQ information. */
++static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn)
++{
++	BUILD_BUG_ON(_IRQT_COUNT > (1U << _IRQT_BITS));
++
++	BUILD_BUG_ON(NR_PIRQS > (1U << _INDEX_BITS));
++	BUILD_BUG_ON(NR_VIRQS > (1U << _INDEX_BITS));
++	BUILD_BUG_ON(NR_IPIS > (1U << _INDEX_BITS));
++	BUG_ON(index >> _INDEX_BITS);
++
++	BUILD_BUG_ON(NR_EVENT_CHANNELS > (1U << _EVTCHN_BITS));
++
++	return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
++}
++
++/* Convenient shorthand for packed representation of an unbound IRQ. */
++#define IRQ_UNBOUND	mk_irq_info(IRQT_UNBOUND, 0, 0)
++
++/*
++ * Accessors for packed IRQ information.
++ */
++
++static inline unsigned int evtchn_from_irq(int irq)
++{
++	return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
++}
++
++static inline unsigned int index_from_irq(int irq)
++{
++	return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
++}
++
++static inline unsigned int type_from_irq(int irq)
++{
++	return irq_info[irq] >> (32 - _IRQT_BITS);
++}
++
++/* IRQ <-> VIRQ mapping. */
++DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
++
++/* IRQ <-> IPI mapping. */
++#ifndef NR_IPIS
++#define NR_IPIS 1
++#endif
++DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1};
++
++/* Reference counts for bindings to IRQs. */
++static int irq_bindcount[NR_IRQS];
++
++#ifdef CONFIG_SMP
++
++static u8 cpu_evtchn[NR_EVENT_CHANNELS];
++static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
++
++static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
++					   unsigned int idx)
++{
++	return (sh->evtchn_pending[idx] &
++		cpu_evtchn_mask[cpu][idx] &
++		~sh->evtchn_mask[idx]);
++}
++
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	int irq = evtchn_to_irq[chn];
++
++	BUG_ON(!test_bit(chn, s->evtchn_mask));
++
++	if (irq != -1)
++		set_native_irq_info(irq, cpumask_of_cpu(cpu));
++
++	clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
++	set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
++	cpu_evtchn[chn] = cpu;
++}
++
++static void init_evtchn_cpu_bindings(void)
++{
++	int i;
++
++	/* By default all event channels notify CPU#0. */
++	for (i = 0; i < NR_IRQS; i++)
++		set_native_irq_info(i, cpumask_of_cpu(0));
++
++	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
++	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++	return cpu_evtchn[evtchn];
++}
++
++#else
++
++static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh,
++					   unsigned int idx)
++{
++	return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
++}
++
++static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
++{
++}
++
++static void init_evtchn_cpu_bindings(void)
++{
++}
++
++static inline unsigned int cpu_from_evtchn(unsigned int evtchn)
++{
++	return 0;
++}
++
++#endif
++
++/* Upcall to generic IRQ layer. */
++#ifdef CONFIG_X86
++extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
++void __init xen_init_IRQ(void);
++void __init init_IRQ(void)
++{
++	irq_ctx_init(0);
++	xen_init_IRQ();
++}
++#if defined (__i386__)
++static inline void exit_idle(void) {}
++#define IRQ_REG orig_eax
++#elif defined (__x86_64__)
++#include <asm/idle.h>
++#define IRQ_REG orig_rax
++#endif
++#define do_IRQ(irq, regs) do {		\
++	(regs)->IRQ_REG = ~(irq);	\
++	do_IRQ((regs));			\
++} while (0)
++#endif
++
++/* Xen will never allocate port zero for any purpose. */
++#define VALID_EVTCHN(chn)	((chn) != 0)
++
++/*
++ * Force a proper event-channel callback from Xen after clearing the
++ * callback mask. We do this in a very simple manner, by making a call
++ * down into Xen. The pending flag will be checked by Xen on return.
++ */
++void force_evtchn_callback(void)
++{
++	VOID(HYPERVISOR_xen_version(0, NULL));
++}
++/* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */
++EXPORT_SYMBOL(force_evtchn_callback);
++
++static DEFINE_PER_CPU(unsigned int, upcall_count) = { 0 };
++static DEFINE_PER_CPU(unsigned int, last_processed_l1i) = { BITS_PER_LONG - 1 };
++static DEFINE_PER_CPU(unsigned int, last_processed_l2i) = { BITS_PER_LONG - 1 };
++
++/* NB. Interrupts are disabled on entry. */
++asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
++{
++	unsigned long       l1, l2;
++	unsigned long       masked_l1, masked_l2;
++	unsigned int        l1i, l2i, port, count;
++	int                 irq;
++	unsigned int        cpu = smp_processor_id();
++	shared_info_t      *s = HYPERVISOR_shared_info;
++	vcpu_info_t        *vcpu_info = &s->vcpu_info[cpu];
++
++	exit_idle();
++	irq_enter();
++
++	do {
++		/* Avoid a callback storm when we reenable delivery. */
++		vcpu_info->evtchn_upcall_pending = 0;
++
++		/* Nested invocations bail immediately. */
++		if (unlikely(per_cpu(upcall_count, cpu)++))
++			break;
++
++#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
++		/* Clear master flag /before/ clearing selector flag. */
++		wmb();
++#endif
++		l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
++
++		l1i = per_cpu(last_processed_l1i, cpu);
++		l2i = per_cpu(last_processed_l2i, cpu);
++
++		while (l1 != 0) {
++
++			l1i = (l1i + 1) % BITS_PER_LONG;
++			masked_l1 = l1 & ((~0UL) << l1i);
++
++			if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */
++				l1i = BITS_PER_LONG - 1;
++				l2i = BITS_PER_LONG - 1;
++				continue;
++			}
++			l1i = __ffs(masked_l1);
++
++			do {
++				l2 = active_evtchns(cpu, s, l1i);
++
++				l2i = (l2i + 1) % BITS_PER_LONG;
++				masked_l2 = l2 & ((~0UL) << l2i);
++
++				if (masked_l2 == 0) { /* if we masked out all events, move on */
++					l2i = BITS_PER_LONG - 1;
++					break;
++				}
++
++				l2i = __ffs(masked_l2);
++
++				/* process port */
++				port = (l1i * BITS_PER_LONG) + l2i;
++				if ((irq = evtchn_to_irq[port]) != -1)
++					do_IRQ(irq, regs);
++				else
++					evtchn_device_upcall(port);
++
++				/* if this is the final port processed, we'll pick up here+1 next time */
++				per_cpu(last_processed_l1i, cpu) = l1i;
++				per_cpu(last_processed_l2i, cpu) = l2i;
++
++			} while (l2i != BITS_PER_LONG - 1);
++
++			l2 = active_evtchns(cpu, s, l1i);
++			if (l2 == 0) /* we handled all ports, so we can clear the selector bit */
++				l1 &= ~(1UL << l1i);
++
++		}
++
++		/* If there were nested callbacks then we have more to do. */
++		count = per_cpu(upcall_count, cpu);
++		per_cpu(upcall_count, cpu) = 0;
++	} while (unlikely(count != 1));
++
++	irq_exit();
++}
++
++static int find_unbound_irq(void)
++{
++	static int warned;
++	int irq;
++
++	for (irq = DYNIRQ_BASE; irq < (DYNIRQ_BASE + NR_DYNIRQS); irq++)
++		if (irq_bindcount[irq] == 0)
++			return irq;
++
++	if (!warned) {
++		warned = 1;
++		printk(KERN_WARNING "No available IRQ to bind to: "
++		       "increase NR_DYNIRQS.\n");
++	}
++
++	return -ENOSPC;
++}
++
++static int bind_caller_port_to_irq(unsigned int caller_port)
++{
++	int irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if ((irq = evtchn_to_irq[caller_port]) == -1) {
++		if ((irq = find_unbound_irq()) < 0)
++			goto out;
++
++		evtchn_to_irq[caller_port] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_CALLER_PORT, 0, caller_port);
++	}
++
++	irq_bindcount[irq]++;
++
++ out:
++	spin_unlock(&irq_mapping_update_lock);
++	return irq;
++}
++
++static int bind_local_port_to_irq(unsigned int local_port)
++{
++	int irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	BUG_ON(evtchn_to_irq[local_port] != -1);
++
++	if ((irq = find_unbound_irq()) < 0) {
++		struct evtchn_close close = { .port = local_port };
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
++			BUG();
++		goto out;
++	}
++
++	evtchn_to_irq[local_port] = irq;
++	irq_info[irq] = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
++	irq_bindcount[irq]++;
++
++ out:
++	spin_unlock(&irq_mapping_update_lock);
++	return irq;
++}
++
++static int bind_listening_port_to_irq(unsigned int remote_domain)
++{
++	struct evtchn_alloc_unbound alloc_unbound;
++	int err;
++
++	alloc_unbound.dom        = DOMID_SELF;
++	alloc_unbound.remote_dom = remote_domain;
++
++	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
++					  &alloc_unbound);
++
++	return err ? : bind_local_port_to_irq(alloc_unbound.port);
++}
++
++static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
++					  unsigned int remote_port)
++{
++	struct evtchn_bind_interdomain bind_interdomain;
++	int err;
++
++	bind_interdomain.remote_dom  = remote_domain;
++	bind_interdomain.remote_port = remote_port;
++
++	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
++					  &bind_interdomain);
++
++	return err ? : bind_local_port_to_irq(bind_interdomain.local_port);
++}
++
++static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
++{
++	struct evtchn_bind_virq bind_virq;
++	int evtchn, irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
++		if ((irq = find_unbound_irq()) < 0)
++			goto out;
++
++		bind_virq.virq = virq;
++		bind_virq.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++						&bind_virq) != 0)
++			BUG();
++		evtchn = bind_virq.port;
++
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++
++		per_cpu(virq_to_irq, cpu)[virq] = irq;
++
++		bind_evtchn_to_cpu(evtchn, cpu);
++	}
++
++	irq_bindcount[irq]++;
++
++ out:
++	spin_unlock(&irq_mapping_update_lock);
++	return irq;
++}
++
++static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
++{
++	struct evtchn_bind_ipi bind_ipi;
++	int evtchn, irq;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
++		if ((irq = find_unbound_irq()) < 0)
++			goto out;
++
++		bind_ipi.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++						&bind_ipi) != 0)
++			BUG();
++		evtchn = bind_ipi.port;
++
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++
++		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
++
++		bind_evtchn_to_cpu(evtchn, cpu);
++	}
++
++	irq_bindcount[irq]++;
++
++ out:
++	spin_unlock(&irq_mapping_update_lock);
++	return irq;
++}
++
++static void unbind_from_irq(unsigned int irq)
++{
++	struct evtchn_close close;
++	unsigned int cpu;
++	int evtchn = evtchn_from_irq(irq);
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
++		close.port = evtchn;
++		if ((type_from_irq(irq) != IRQT_CALLER_PORT) &&
++		    HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
++			BUG();
++
++		switch (type_from_irq(irq)) {
++		case IRQT_VIRQ:
++			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
++				[index_from_irq(irq)] = -1;
++			break;
++		case IRQT_IPI:
++			per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
++				[index_from_irq(irq)] = -1;
++			break;
++		default:
++			break;
++		}
++
++		/* Closed ports are implicitly re-bound to VCPU0. */
++		bind_evtchn_to_cpu(evtchn, 0);
++
++		evtchn_to_irq[evtchn] = -1;
++		irq_info[irq] = IRQ_UNBOUND;
++
++		/* Zap stats across IRQ changes of use. */
++		for_each_possible_cpu(cpu)
++			kstat_cpu(cpu).irqs[irq] = 0;
++	}
++
++	spin_unlock(&irq_mapping_update_lock);
++}
++
++int bind_caller_port_to_irqhandler(
++	unsigned int caller_port,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_caller_port_to_irq(caller_port);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_caller_port_to_irqhandler);
++
++int bind_listening_port_to_irqhandler(
++	unsigned int remote_domain,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_listening_port_to_irq(remote_domain);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_listening_port_to_irqhandler);
++
++int bind_interdomain_evtchn_to_irqhandler(
++	unsigned int remote_domain,
++	unsigned int remote_port,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler);
++
++int bind_virq_to_irqhandler(
++	unsigned int virq,
++	unsigned int cpu,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_virq_to_irq(virq, cpu);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
++
++int bind_ipi_to_irqhandler(
++	unsigned int ipi,
++	unsigned int cpu,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id)
++{
++	int irq, retval;
++
++	irq = bind_ipi_to_irq(ipi, cpu);
++	if (irq < 0)
++		return irq;
++
++	retval = request_irq(irq, handler, irqflags, devname, dev_id);
++	if (retval != 0) {
++		unbind_from_irq(irq);
++		return retval;
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_ipi_to_irqhandler);
++
++void unbind_from_irqhandler(unsigned int irq, void *dev_id)
++{
++	free_irq(irq, dev_id);
++	unbind_from_irq(irq);
++}
++EXPORT_SYMBOL_GPL(unbind_from_irqhandler);
++
++#ifdef CONFIG_SMP
++void rebind_evtchn_to_cpu(int port, unsigned int cpu)
++{
++	struct evtchn_bind_vcpu ebv = { .port = port, .vcpu = cpu };
++	int masked;
++
++	masked = test_and_set_evtchn_mask(port);
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &ebv) == 0)
++		bind_evtchn_to_cpu(port, cpu);
++	if (!masked)
++		unmask_evtchn(port);
++}
++
++static void rebind_irq_to_cpu(unsigned int irq, unsigned int tcpu)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		rebind_evtchn_to_cpu(evtchn, tcpu);
++}
++
++static void set_affinity_irq(unsigned int irq, cpumask_t dest)
++{
++	unsigned tcpu = first_cpu(dest);
++	rebind_irq_to_cpu(irq, tcpu);
++}
++#endif
++
++int resend_irq_on_evtchn(unsigned int irq)
++{
++	int masked, evtchn = evtchn_from_irq(irq);
++	shared_info_t *s = HYPERVISOR_shared_info;
++
++	if (!VALID_EVTCHN(evtchn))
++		return 1;
++
++	masked = test_and_set_evtchn_mask(evtchn);
++	synch_set_bit(evtchn, s->evtchn_pending);
++	if (!masked)
++		unmask_evtchn(evtchn);
++
++	return 1;
++}
++
++/*
++ * Interface to generic handling in irq.c
++ */
++
++static unsigned int startup_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		unmask_evtchn(evtchn);
++	return 0;
++}
++
++static void shutdown_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		mask_evtchn(evtchn);
++}
++
++static void enable_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		unmask_evtchn(evtchn);
++}
++
++static void disable_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		mask_evtchn(evtchn);
++}
++
++static void ack_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	move_native_irq(irq);
++
++	if (VALID_EVTCHN(evtchn)) {
++		mask_evtchn(evtchn);
++		clear_evtchn(evtchn);
++	}
++}
++
++static void end_dynirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED))
++		unmask_evtchn(evtchn);
++}
++
++static struct hw_interrupt_type dynirq_type = {
++	.typename = "Dynamic-irq",
++	.startup  = startup_dynirq,
++	.shutdown = shutdown_dynirq,
++	.enable   = enable_dynirq,
++	.disable  = disable_dynirq,
++	.ack      = ack_dynirq,
++	.end      = end_dynirq,
++#ifdef CONFIG_SMP
++	.set_affinity = set_affinity_irq,
++#endif
++	.retrigger = resend_irq_on_evtchn,
++};
++
++/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
++static int pirq_eoi_does_unmask;
++static unsigned long *pirq_needs_eoi;
++
++static void pirq_unmask_and_notify(unsigned int evtchn, unsigned int irq)
++{
++	struct physdev_eoi eoi = { .irq = evtchn_get_xen_pirq(irq) };
++
++	if (pirq_eoi_does_unmask) {
++		if (test_bit(eoi.irq, pirq_needs_eoi))
++			VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
++		else
++			unmask_evtchn(evtchn);
++	} else if (test_bit(irq - PIRQ_BASE, pirq_needs_eoi)) {
++		if (smp_processor_id() != cpu_from_evtchn(evtchn)) {
++			struct evtchn_unmask unmask = { .port = evtchn };
++			struct multicall_entry mcl[2];
++
++			mcl[0].op = __HYPERVISOR_event_channel_op;
++			mcl[0].args[0] = EVTCHNOP_unmask;
++			mcl[0].args[1] = (unsigned long)&unmask;
++			mcl[1].op = __HYPERVISOR_physdev_op;
++			mcl[1].args[0] = PHYSDEVOP_eoi;
++			mcl[1].args[1] = (unsigned long)&eoi;
++
++			if (HYPERVISOR_multicall(mcl, 2))
++				BUG();
++		} else {
++			unmask_evtchn(evtchn);
++			VOID(HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi));
++		}
++	} else
++		unmask_evtchn(evtchn);
++}
++
++static inline void pirq_query_unmask(int irq)
++{
++	struct physdev_irq_status_query irq_status;
++
++	if (pirq_eoi_does_unmask)
++		return;
++	irq_status.irq = evtchn_get_xen_pirq(irq);
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
++		irq_status.flags = 0;
++	clear_bit(irq - PIRQ_BASE, pirq_needs_eoi);
++	if (irq_status.flags & XENIRQSTAT_needs_eoi)
++		set_bit(irq - PIRQ_BASE, pirq_needs_eoi);
++}
++
++/*
++ * On startup, if there is no action associated with the IRQ then we are
++ * probing. In this case we should not share with others as it will confuse us.
++ */
++#define probing_irq(_irq) (irq_desc[(_irq)].action == NULL)
++
++static unsigned int startup_pirq(unsigned int irq)
++{
++	struct evtchn_bind_pirq bind_pirq;
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		goto out;
++
++	bind_pirq.pirq = evtchn_get_xen_pirq(irq);
++	/* NB. We are happy to share unless we are probing. */
++	bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
++		if (!probing_irq(irq))
++			printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
++			       irq);
++		return 0;
++	}
++	evtchn = bind_pirq.port;
++
++	pirq_query_unmask(irq);
++
++	evtchn_to_irq[evtchn] = irq;
++	bind_evtchn_to_cpu(evtchn, 0);
++	irq_info[irq] = mk_irq_info(IRQT_PIRQ, bind_pirq.pirq, evtchn);
++
++ out:
++	pirq_unmask_and_notify(evtchn, irq);
++
++	return 0;
++}
++
++static void shutdown_pirq(unsigned int irq)
++{
++	struct evtchn_close close;
++	int evtchn = evtchn_from_irq(irq);
++
++	if (!VALID_EVTCHN(evtchn))
++		return;
++
++	mask_evtchn(evtchn);
++
++	close.port = evtchn;
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
++		BUG();
++
++	bind_evtchn_to_cpu(evtchn, 0);
++	evtchn_to_irq[evtchn] = -1;
++	irq_info[irq] = mk_irq_info(IRQT_PIRQ, index_from_irq(irq), 0);
++}
++
++static void enable_pirq(unsigned int irq)
++{
++	startup_pirq(irq);
++}
++
++static void disable_pirq(unsigned int irq)
++{
++}
++
++static void ack_pirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	move_native_irq(irq);
++
++	if (VALID_EVTCHN(evtchn)) {
++		mask_evtchn(evtchn);
++		clear_evtchn(evtchn);
++	}
++}
++
++static void end_pirq(unsigned int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if ((irq_desc[irq].status & (IRQ_DISABLED|IRQ_PENDING)) ==
++	    (IRQ_DISABLED|IRQ_PENDING)) {
++		shutdown_pirq(irq);
++	} else if (VALID_EVTCHN(evtchn))
++		pirq_unmask_and_notify(evtchn, irq);
++}
++
++static struct hw_interrupt_type pirq_type = {
++	.typename = "Phys-irq",
++	.startup  = startup_pirq,
++	.shutdown = shutdown_pirq,
++	.enable   = enable_pirq,
++	.disable  = disable_pirq,
++	.ack      = ack_pirq,
++	.end      = end_pirq,
++#ifdef CONFIG_SMP
++	.set_affinity = set_affinity_irq,
++#endif
++	.retrigger = resend_irq_on_evtchn,
++};
++
++int irq_ignore_unhandled(unsigned int irq)
++{
++	struct physdev_irq_status_query irq_status = { .irq = irq };
++
++	if (!is_running_on_xen())
++		return 0;
++
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
++		return 0;
++	return !!(irq_status.flags & XENIRQSTAT_shared);
++}
++
++void notify_remote_via_irq(int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		notify_remote_via_evtchn(evtchn);
++}
++EXPORT_SYMBOL_GPL(notify_remote_via_irq);
++
++int irq_to_evtchn_port(int irq)
++{
++	return evtchn_from_irq(irq);
++}
++EXPORT_SYMBOL_GPL(irq_to_evtchn_port);
++
++void mask_evtchn(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	synch_set_bit(port, s->evtchn_mask);
++}
++EXPORT_SYMBOL_GPL(mask_evtchn);
++
++void unmask_evtchn(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	unsigned int cpu = smp_processor_id();
++	vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
++
++	BUG_ON(!irqs_disabled());
++
++	/* Slow path (hypercall) if this is a non-local port. */
++	if (unlikely(cpu != cpu_from_evtchn(port))) {
++		struct evtchn_unmask unmask = { .port = port };
++		VOID(HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask));
++		return;
++	}
++
++	synch_clear_bit(port, s->evtchn_mask);
++
++	/* Did we miss an interrupt 'edge'? Re-fire if so. */
++	if (synch_test_bit(port, s->evtchn_pending) &&
++	    !synch_test_and_set_bit(port / BITS_PER_LONG,
++				    &vcpu_info->evtchn_pending_sel))
++		vcpu_info->evtchn_upcall_pending = 1;
++}
++EXPORT_SYMBOL_GPL(unmask_evtchn);
++
++void disable_all_local_evtchn(void)
++{
++	unsigned i, cpu = smp_processor_id();
++	shared_info_t *s = HYPERVISOR_shared_info;
++
++	for (i = 0; i < NR_EVENT_CHANNELS; ++i)
++		if (cpu_from_evtchn(i) == cpu)
++			synch_set_bit(i, &s->evtchn_mask[0]);
++}
++
++static void restore_cpu_virqs(unsigned int cpu)
++{
++	struct evtchn_bind_virq bind_virq;
++	int virq, irq, evtchn;
++
++	for (virq = 0; virq < NR_VIRQS; virq++) {
++		if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
++			continue;
++
++		BUG_ON(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0));
++
++		/* Get a new binding from Xen. */
++		bind_virq.virq = virq;
++		bind_virq.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++						&bind_virq) != 0)
++			BUG();
++		evtchn = bind_virq.port;
++
++		/* Record the new mapping. */
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++		bind_evtchn_to_cpu(evtchn, cpu);
++
++		/* Ready for use. */
++		unmask_evtchn(evtchn);
++	}
++}
++
++static void restore_cpu_ipis(unsigned int cpu)
++{
++	struct evtchn_bind_ipi bind_ipi;
++	int ipi, irq, evtchn;
++
++	for (ipi = 0; ipi < NR_IPIS; ipi++) {
++		if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
++			continue;
++
++		BUG_ON(irq_info[irq] != mk_irq_info(IRQT_IPI, ipi, 0));
++
++		/* Get a new binding from Xen. */
++		bind_ipi.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++						&bind_ipi) != 0)
++			BUG();
++		evtchn = bind_ipi.port;
++
++		/* Record the new mapping. */
++		evtchn_to_irq[evtchn] = irq;
++		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
++		bind_evtchn_to_cpu(evtchn, cpu);
++
++		/* Ready for use. */
++		unmask_evtchn(evtchn);
++
++	}
++}
++
++void irq_resume(void)
++{
++	unsigned int cpu, irq, evtchn;
++
++	init_evtchn_cpu_bindings();
++
++	if (pirq_eoi_does_unmask) {
++		struct physdev_pirq_eoi_gmfn eoi_gmfn;
++
++		eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
++		if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn))
++			BUG();
++	}
++
++	/* New event-channel space is not 'live' yet. */
++	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
++		mask_evtchn(evtchn);
++
++	/* Check that no PIRQs are still bound. */
++	for (irq = PIRQ_BASE; irq < (PIRQ_BASE + NR_PIRQS); irq++)
++		BUG_ON(irq_info[irq] != IRQ_UNBOUND);
++
++	/* No IRQ <-> event-channel mappings. */
++	for (irq = 0; irq < NR_IRQS; irq++)
++		irq_info[irq] &= ~((1U << _EVTCHN_BITS) - 1);
++	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
++		evtchn_to_irq[evtchn] = -1;
++
++	for_each_possible_cpu(cpu) {
++		restore_cpu_virqs(cpu);
++		restore_cpu_ipis(cpu);
++	}
++
++}
++
++#if defined(CONFIG_X86_IO_APIC)
++#define identity_mapped_irq(irq) (!IO_APIC_IRQ((irq) - PIRQ_BASE))
++#elif defined(CONFIG_X86)
++#define identity_mapped_irq(irq) (((irq) - PIRQ_BASE) < 16)
++#else
++#define identity_mapped_irq(irq) (1)
++#endif
++
++void evtchn_register_pirq(int irq)
++{
++	BUG_ON(irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS);
++	if (identity_mapped_irq(irq) || type_from_irq(irq) != IRQT_UNBOUND)
++		return;
++	irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, 0);
++	irq_desc[irq].chip = &pirq_type;
++}
++
++int evtchn_map_pirq(int irq, int xen_pirq)
++{
++	if (irq < 0) {
++		static DEFINE_SPINLOCK(irq_alloc_lock);
++
++		irq = PIRQ_BASE + NR_PIRQS - 1;
++		spin_lock(&irq_alloc_lock);
++		do {
++			if (identity_mapped_irq(irq))
++				continue;
++			if (!index_from_irq(irq)) {
++				BUG_ON(type_from_irq(irq) != IRQT_UNBOUND);
++				irq_info[irq] = mk_irq_info(IRQT_PIRQ,
++							    xen_pirq, 0);
++				break;
++			}
++		} while (--irq >= PIRQ_BASE);
++		spin_unlock(&irq_alloc_lock);
++		if (irq < PIRQ_BASE)
++			return -ENOSPC;
++		irq_desc[irq].chip = &pirq_type;
++	} else if (!xen_pirq) {
++		if (unlikely(type_from_irq(irq) != IRQT_PIRQ))
++			return -EINVAL;
++		irq_desc[irq].chip = &no_irq_type;
++		irq_info[irq] = IRQ_UNBOUND;
++		return 0;
++	} else if (type_from_irq(irq) != IRQT_PIRQ
++		   || index_from_irq(irq) != xen_pirq) {
++		printk(KERN_ERR "IRQ#%d is already mapped to %d:%u - "
++				"cannot map to PIRQ#%u\n",
++		       irq, type_from_irq(irq), index_from_irq(irq), xen_pirq);
++		return -EINVAL;
++	}
++	return index_from_irq(irq) ? irq : -EINVAL;
++}
++
++int evtchn_get_xen_pirq(int irq)
++{
++	if (identity_mapped_irq(irq))
++		return irq;
++	BUG_ON(type_from_irq(irq) != IRQT_PIRQ);
++	return index_from_irq(irq);
++}
++
++void __init xen_init_IRQ(void)
++{
++	unsigned int i;
++	struct physdev_pirq_eoi_gmfn eoi_gmfn;
++
++	init_evtchn_cpu_bindings();
++
++	pirq_needs_eoi = alloc_bootmem_pages(sizeof(unsigned long)
++		* BITS_TO_LONGS(ALIGN(NR_PIRQS, PAGE_SIZE * 8)));
++ 	eoi_gmfn.gmfn = virt_to_machine(pirq_needs_eoi) >> PAGE_SHIFT;
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_pirq_eoi_gmfn, &eoi_gmfn) == 0)
++		pirq_eoi_does_unmask = 1;
++
++	/* No event channels are 'live' right now. */
++	for (i = 0; i < NR_EVENT_CHANNELS; i++)
++		mask_evtchn(i);
++
++	/* No IRQ -> event-channel mappings. */
++	for (i = 0; i < NR_IRQS; i++)
++		irq_info[i] = IRQ_UNBOUND;
++
++	/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
++	for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
++		irq_bindcount[i] = 0;
++
++		irq_desc[i].status = IRQ_DISABLED|IRQ_NOPROBE;
++		irq_desc[i].action = NULL;
++		irq_desc[i].depth = 1;
++		irq_desc[i].chip = &dynirq_type;
++	}
++
++	/* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
++	for (i = PIRQ_BASE; i < (PIRQ_BASE + NR_PIRQS); i++) {
++		irq_bindcount[i] = 1;
++
++		if (!identity_mapped_irq(i))
++			continue;
++
++#ifdef RTC_IRQ
++		/* If not domain 0, force our RTC driver to fail its probe. */
++		if (i - PIRQ_BASE == RTC_IRQ && !is_initial_xendomain())
++			continue;
++#endif
++
++		irq_desc[i].status = IRQ_DISABLED;
++		irq_desc[i].action = NULL;
++		irq_desc[i].depth = 1;
++		irq_desc[i].chip = &pirq_type;
++	}
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/features.c	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,34 @@
++/******************************************************************************
++ * features.c
++ *
++ * Xen feature flags.
++ *
++ * Copyright (c) 2006, Ian Campbell, XenSource Inc.
++ */
++#include <linux/types.h>
++#include <linux/cache.h>
++#include <linux/module.h>
++#include <asm/hypervisor.h>
++#include <xen/features.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly;
++/* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */
++EXPORT_SYMBOL(xen_features);
++
++void setup_xen_features(void)
++{
++	xen_feature_info_t fi;
++	int i, j;
++
++	for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) {
++		fi.submap_idx = i;
++		if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
++			break;
++		for (j=0; j<32; j++)
++			xen_features[i*32+j] = !!(fi.submap & 1<<j);
++	}
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/firmware.c	2007-06-22 09:08:06.000000000 +0200
+@@ -0,0 +1,74 @@
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/edd.h>
++#include <video/edid.h>
++#include <xen/interface/platform.h>
++#include <asm/hypervisor.h>
++
++#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
++void __init copy_edd(void)
++{
++	int ret;
++	struct xen_platform_op op;
++
++	if (!is_initial_xendomain())
++		return;
++
++	op.cmd = XENPF_firmware_info;
++
++	op.u.firmware_info.type = XEN_FW_DISK_INFO;
++	for (op.u.firmware_info.index = 0;
++	     edd.edd_info_nr < EDDMAXNR;
++	     op.u.firmware_info.index++) {
++		struct edd_info *info = edd.edd_info + edd.edd_info_nr;
++
++		info->params.length = sizeof(info->params);
++		set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
++				     &info->params);
++		ret = HYPERVISOR_platform_op(&op);
++		if (ret)
++			break;
++
++#define C(x) info->x = op.u.firmware_info.u.disk_info.x
++		C(device);
++		C(version);
++		C(interface_support);
++		C(legacy_max_cylinder);
++		C(legacy_max_head);
++		C(legacy_sectors_per_track);
++#undef C
++
++		edd.edd_info_nr++;
++	}
++
++	op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
++	for (op.u.firmware_info.index = 0;
++	     edd.mbr_signature_nr < EDD_MBR_SIG_MAX;
++	     op.u.firmware_info.index++) {
++		ret = HYPERVISOR_platform_op(&op);
++		if (ret)
++			break;
++		edd.mbr_signature[edd.mbr_signature_nr++] =
++			op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
++	}
++}
++#endif
++
++void __init copy_edid(void)
++{
++#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
++	struct xen_platform_op op;
++
++	if (!is_initial_xendomain())
++		return;
++
++	op.cmd = XENPF_firmware_info;
++	op.u.firmware_info.index = 0;
++	op.u.firmware_info.type = XEN_FW_VBEDDC_INFO;
++	set_xen_guest_handle(op.u.firmware_info.u.vbeddc_info.edid,
++			     edid_info.dummy);
++	if (HYPERVISOR_platform_op(&op) != 0)
++		memset(edid_info.dummy, 0x13, sizeof(edid_info.dummy));
++#endif
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/gnttab.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,773 @@
++/******************************************************************************
++ * gnttab.c
++ *
++ * Granting foreign access to our memory reservation.
++ *
++ * Copyright (c) 2005-2006, Christopher Clark
++ * Copyright (c) 2004-2005, K A Fraser
++ *
++ * 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/module.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/seqlock.h>
++#include <xen/interface/xen.h>
++#include <xen/gnttab.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/synch_bitops.h>
++#include <asm/io.h>
++#include <xen/interface/memory.h>
++#include <xen/driver_util.h>
++#include <asm/gnttab_dma.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++/* External tools reserve first few grant table entries. */
++#define NR_RESERVED_ENTRIES 8
++#define GNTTAB_LIST_END 0xffffffff
++#define ENTRIES_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
++
++static grant_ref_t **gnttab_list;
++static unsigned int nr_grant_frames;
++static unsigned int boot_max_nr_grant_frames;
++static int gnttab_free_count;
++static grant_ref_t gnttab_free_head;
++static DEFINE_SPINLOCK(gnttab_list_lock);
++
++static struct grant_entry *shared;
++
++static struct gnttab_free_callback *gnttab_free_callback_list;
++
++static int gnttab_expand(unsigned int req_entries);
++
++#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;
++	int ref, rc;
++	grant_ref_t head;
++
++	spin_lock_irqsave(&gnttab_list_lock, flags);
++
++	if ((gnttab_free_count < count) &&
++	    ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
++		spin_unlock_irqrestore(&gnttab_list_lock, flags);
++		return rc;
++	}
++
++	ref = head = gnttab_free_head;
++	gnttab_free_count -= count;
++	while (count-- > 1)
++		head = gnttab_entry(head);
++ 	gnttab_free_head = gnttab_entry(head);
++	gnttab_entry(head) = GNTTAB_LIST_END;
++
++	spin_unlock_irqrestore(&gnttab_list_lock, flags);
++
++	return ref;
++}
++
++#define get_free_entry() get_free_entries(1)
++
++static void do_free_callbacks(void)
++{
++	struct gnttab_free_callback *callback, *next;
++
++	callback = gnttab_free_callback_list;
++	gnttab_free_callback_list = NULL;
++
++	while (callback != NULL) {
++		next = callback->next;
++		if (gnttab_free_count >= callback->count) {
++			callback->next = NULL;
++			callback->queued = 0;
++			callback->fn(callback->arg);
++		} else {
++			callback->next = gnttab_free_callback_list;
++			gnttab_free_callback_list = callback;
++		}
++		callback = next;
++	}
++}
++
++static inline void check_free_callbacks(void)
++{
++	if (unlikely(gnttab_free_callback_list))
++		do_free_callbacks();
++}
++
++static void put_free_entry(grant_ref_t ref)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&gnttab_list_lock, flags);
++	gnttab_entry(ref) = gnttab_free_head;
++	gnttab_free_head = ref;
++	gnttab_free_count++;
++	check_free_callbacks();
++	spin_unlock_irqrestore(&gnttab_list_lock, flags);
++}
++
++/*
++ * Public grant-issuing interface functions
++ */
++
++int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
++				int flags)
++{
++	int ref;
++
++	if (unlikely((ref = get_free_entry()) < 0))
++		return -ENOSPC;
++
++	shared[ref].frame = frame;
++	shared[ref].domid = domid;
++	wmb();
++	BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
++	shared[ref].flags = GTF_permit_access | flags;
++
++	return ref;
++}
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
++
++void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
++				     unsigned long frame, int flags)
++{
++	shared[ref].frame = frame;
++	shared[ref].domid = domid;
++	wmb();
++	BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
++	shared[ref].flags = GTF_permit_access | flags;
++}
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
++
++
++int gnttab_query_foreign_access(grant_ref_t ref)
++{
++	u16 nflags;
++
++	nflags = shared[ref].flags;
++
++	return (nflags & (GTF_reading|GTF_writing));
++}
++EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
++
++int gnttab_end_foreign_access_ref(grant_ref_t ref)
++{
++	u16 flags, nflags;
++
++	nflags = shared[ref].flags;
++	do {
++		if ((flags = nflags) & (GTF_reading|GTF_writing)) {
++			printk(KERN_DEBUG "WARNING: g.e. still in use!\n");
++			return 0;
++		}
++	} while ((nflags = synch_cmpxchg_subword(&shared[ref].flags, flags, 0)) !=
++		 flags);
++
++	return 1;
++}
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
++
++void gnttab_end_foreign_access(grant_ref_t ref, unsigned long page)
++{
++	if (gnttab_end_foreign_access_ref(ref)) {
++		put_free_entry(ref);
++		if (page != 0)
++			free_page(page);
++	} else {
++		/* XXX This needs to be fixed so that the ref and page are
++		   placed on a list to be freed up later. */
++		printk(KERN_DEBUG
++		       "WARNING: leaking g.e. and page still in use!\n");
++	}
++}
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
++
++int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
++{
++	int ref;
++
++	if (unlikely((ref = get_free_entry()) < 0))
++		return -ENOSPC;
++	gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
++
++	return ref;
++}
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
++
++void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
++				       unsigned long pfn)
++{
++	shared[ref].frame = pfn;
++	shared[ref].domid = domid;
++	wmb();
++	shared[ref].flags = GTF_accept_transfer;
++}
++EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
++
++unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
++{
++	unsigned long frame;
++	u16           flags;
++
++	/*
++	 * If a transfer is not even yet started, try to reclaim the grant
++	 * reference and return failure (== 0).
++	 */
++	while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
++		if (synch_cmpxchg_subword(&shared[ref].flags, flags, 0) == flags)
++			return 0;
++		cpu_relax();
++	}
++
++	/* If a transfer is in progress then wait until it is completed. */
++	while (!(flags & GTF_transfer_completed)) {
++		flags = shared[ref].flags;
++		cpu_relax();
++	}
++
++	/* Read the frame number /after/ reading completion status. */
++	rmb();
++	frame = shared[ref].frame;
++	BUG_ON(frame == 0);
++
++	return frame;
++}
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
++
++unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
++{
++	unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
++	put_free_entry(ref);
++	return frame;
++}
++EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
++
++void gnttab_free_grant_reference(grant_ref_t ref)
++{
++	put_free_entry(ref);
++}
++EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
++
++void gnttab_free_grant_references(grant_ref_t head)
++{
++	grant_ref_t ref;
++	unsigned long flags;
++	int count = 1;
++	if (head == GNTTAB_LIST_END)
++		return;
++	spin_lock_irqsave(&gnttab_list_lock, flags);
++	ref = head;
++	while (gnttab_entry(ref) != GNTTAB_LIST_END) {
++		ref = gnttab_entry(ref);
++		count++;
++	}
++	gnttab_entry(ref) = gnttab_free_head;
++	gnttab_free_head = head;
++	gnttab_free_count += count;
++	check_free_callbacks();
++	spin_unlock_irqrestore(&gnttab_list_lock, flags);
++}
++EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
++
++int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
++{
++	int h = get_free_entries(count);
++
++	if (h < 0)
++		return -ENOSPC;
++
++	*head = h;
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
++
++int gnttab_empty_grant_references(const grant_ref_t *private_head)
++{
++	return (*private_head == GNTTAB_LIST_END);
++}
++EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
++
++int gnttab_claim_grant_reference(grant_ref_t *private_head)
++{
++	grant_ref_t g = *private_head;
++	if (unlikely(g == GNTTAB_LIST_END))
++		return -ENOSPC;
++	*private_head = gnttab_entry(g);
++	return g;
++}
++EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
++
++void gnttab_release_grant_reference(grant_ref_t *private_head,
++				    grant_ref_t release)
++{
++	gnttab_entry(release) = *private_head;
++	*private_head = release;
++}
++EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
++
++void gnttab_request_free_callback(struct gnttab_free_callback *callback,
++				  void (*fn)(void *), void *arg, u16 count)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&gnttab_list_lock, flags);
++	if (callback->queued)
++		goto out;
++	callback->fn = fn;
++	callback->arg = arg;
++	callback->count = count;
++	callback->queued = 1;
++	callback->next = gnttab_free_callback_list;
++	gnttab_free_callback_list = callback;
++	check_free_callbacks();
++out:
++	spin_unlock_irqrestore(&gnttab_list_lock, flags);
++}
++EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
++
++void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
++{
++	struct gnttab_free_callback **pcb;
++	unsigned long flags;
++
++	spin_lock_irqsave(&gnttab_list_lock, flags);
++	for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
++		if (*pcb == callback) {
++			*pcb = callback->next;
++			callback->queued = 0;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&gnttab_list_lock, flags);
++}
++EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
++
++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 * ENTRIES_PER_GRANT_FRAME;
++
++	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 = 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 = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
++	gnttab_free_count += extra_entries;
++
++	nr_grant_frames = new_nr_grant_frames;
++
++	check_free_callbacks();
++
++	return 0;
++	
++grow_nomem:
++	for ( ; i >= nr_glist_frames; i--)
++		free_page((unsigned long) gnttab_list[i]);
++	return -ENOMEM;
++}
++
++static unsigned int __max_nr_grant_frames(void)
++{
++	struct gnttab_query_size query;
++	int rc;
++
++	query.dom = DOMID_SELF;
++
++	rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
++	if ((rc < 0) || (query.status != GNTST_okay))
++		return 4; /* Legacy max supported number of frames */
++
++	return query.max_nr_frames;
++}
++
++static inline unsigned int max_nr_grant_frames(void)
++{
++	unsigned int xen_max = __max_nr_grant_frames();
++
++	if (xen_max > boot_max_nr_grant_frames)
++		return boot_max_nr_grant_frames;
++	return xen_max;
++}
++
++#ifdef CONFIG_XEN
++
++static DEFINE_SEQLOCK(gnttab_dma_lock);
++
++#ifdef CONFIG_X86
++static int map_pte_fn(pte_t *pte, struct page *pmd_page,
++		      unsigned long addr, void *data)
++{
++	unsigned long **frames = (unsigned long **)data;
++
++	set_pte_at(&init_mm, addr, pte, pfn_pte_ma((*frames)[0], PAGE_KERNEL));
++	(*frames)++;
++	return 0;
++}
++
++static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
++			unsigned long addr, void *data)
++{
++
++	set_pte_at(&init_mm, addr, pte, __pte(0));
++	return 0;
++}
++
++void *arch_gnttab_alloc_shared(unsigned long *frames)
++{
++	struct vm_struct *area;
++	area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
++	BUG_ON(area == NULL);
++	return area->addr;
++}
++#endif /* CONFIG_X86 */
++
++static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
++{
++	struct gnttab_setup_table setup;
++	unsigned long *frames;
++	unsigned int nr_gframes = end_idx + 1;
++	int rc;
++
++	frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
++	if (!frames)
++		return -ENOMEM;
++
++	setup.dom        = DOMID_SELF;
++	setup.nr_frames  = nr_gframes;
++	set_xen_guest_handle(setup.frame_list, frames);
++
++	rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
++	if (rc == -ENOSYS) {
++		kfree(frames);
++		return -ENOSYS;
++	}
++
++	BUG_ON(rc || setup.status);
++
++	if (shared == NULL)
++		shared = arch_gnttab_alloc_shared(frames);
++
++#ifdef CONFIG_X86
++	rc = apply_to_page_range(&init_mm, (unsigned long)shared,
++				 PAGE_SIZE * nr_gframes,
++				 map_pte_fn, &frames);
++	BUG_ON(rc);
++	frames -= nr_gframes; /* adjust after map_pte_fn() */
++#endif /* CONFIG_X86 */
++
++	kfree(frames);
++
++	return 0;
++}
++
++static void gnttab_page_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	ClearPageForeign(page);
++	gnttab_reset_grant_page(page);
++	put_page(page);
++}
++
++/*
++ * Must not be called with IRQs off.  This should only be used on the
++ * slow path.
++ *
++ * Copy a foreign granted page to local memory.
++ */
++int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep)
++{
++	struct gnttab_unmap_and_replace unmap;
++	mmu_update_t mmu;
++	struct page *page;
++	struct page *new_page;
++	void *new_addr;
++	void *addr;
++	paddr_t pfn;
++	maddr_t mfn;
++	maddr_t new_mfn;
++	int err;
++
++	page = *pagep;
++	if (!get_page_unless_zero(page))
++		return -ENOENT;
++
++	err = -ENOMEM;
++	new_page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
++	if (!new_page)
++		goto out;
++
++	new_addr = page_address(new_page);
++	addr = page_address(page);
++	memcpy(new_addr, addr, PAGE_SIZE);
++
++	pfn = page_to_pfn(page);
++	mfn = pfn_to_mfn(pfn);
++	new_mfn = virt_to_mfn(new_addr);
++
++	write_seqlock(&gnttab_dma_lock);
++
++	/* Make seq visible before checking page_mapped. */
++	smp_mb();
++
++	/* Has the page been DMA-mapped? */
++	if (unlikely(page_mapped(page))) {
++		write_sequnlock(&gnttab_dma_lock);
++		put_page(new_page);
++		err = -EBUSY;
++		goto out;
++	}
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap))
++		set_phys_to_machine(pfn, new_mfn);
++
++	gnttab_set_replace_op(&unmap, (unsigned long)addr,
++			      (unsigned long)new_addr, ref);
++
++	err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
++					&unmap, 1);
++	BUG_ON(err);
++	BUG_ON(unmap.status);
++
++	write_sequnlock(&gnttab_dma_lock);
++
++	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY);
++
++		mmu.ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
++		mmu.val = pfn;
++		err = HYPERVISOR_mmu_update(&mmu, 1, NULL, DOMID_SELF);
++		BUG_ON(err);
++	}
++
++	new_page->mapping = page->mapping;
++	new_page->index = page->index;
++	set_bit(PG_foreign, &new_page->flags);
++	*pagep = new_page;
++
++	SetPageForeign(page, gnttab_page_free);
++	page->mapping = NULL;
++
++out:
++	put_page(page);
++	return err;
++}
++EXPORT_SYMBOL_GPL(gnttab_copy_grant_page);
++
++void gnttab_reset_grant_page(struct page *page)
++{
++	init_page_count(page);
++	reset_page_mapcount(page);
++}
++EXPORT_SYMBOL_GPL(gnttab_reset_grant_page);
++
++/*
++ * Keep track of foreign pages marked as PageForeign so that we don't
++ * return them to the remote domain prematurely.
++ *
++ * PageForeign pages are pinned down by increasing their mapcount.
++ *
++ * All other pages are simply returned as is.
++ */
++void __gnttab_dma_map_page(struct page *page)
++{
++	unsigned int seq;
++
++	if (!is_running_on_xen() || !PageForeign(page))
++		return;
++
++	do {
++		seq = read_seqbegin(&gnttab_dma_lock);
++
++		if (gnttab_dma_local_pfn(page))
++			break;
++
++		atomic_set(&page->_mapcount, 0);
++
++		/* Make _mapcount visible before read_seqretry. */
++		smp_mb();
++	} while (unlikely(read_seqretry(&gnttab_dma_lock, seq)));
++}
++
++int gnttab_resume(void)
++{
++	if (max_nr_grant_frames() < nr_grant_frames)
++		return -ENOSYS;
++	return gnttab_map(0, nr_grant_frames - 1);
++}
++
++int gnttab_suspend(void)
++{
++#ifdef CONFIG_X86
++	apply_to_page_range(&init_mm, (unsigned long)shared,
++			    PAGE_SIZE * nr_grant_frames,
++			    unmap_pte_fn, NULL);
++#endif
++	return 0;
++}
++
++#else /* !CONFIG_XEN */
++
++#include <platform-pci.h>
++
++static unsigned long resume_frames;
++
++static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
++{
++	struct xen_add_to_physmap xatp;
++	unsigned int i = end_idx;
++
++	/* Loop backwards, so that the first hypercall has the largest index,
++	 * ensuring that the table will grow only once.
++	 */
++	do {
++		xatp.domid = DOMID_SELF;
++		xatp.idx = i;
++		xatp.space = XENMAPSPACE_grant_table;
++		xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i;
++		if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
++			BUG();
++	} while (i-- > start_idx);
++
++	return 0;
++}
++
++int gnttab_resume(void)
++{
++	unsigned int max_nr_gframes, nr_gframes;
++
++	nr_gframes = nr_grant_frames;
++	max_nr_gframes = max_nr_grant_frames();
++	if (max_nr_gframes < nr_gframes)
++		return -ENOSYS;
++
++	if (!resume_frames) {
++		resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
++		shared = ioremap(resume_frames, PAGE_SIZE * max_nr_gframes);
++		if (shared == NULL) {
++			printk("error to ioremap gnttab share frames\n");
++			return -1;
++		}
++	}
++
++	gnttab_map(0, nr_gframes - 1);
++
++	return 0;
++}
++
++#endif /* !CONFIG_XEN */
++
++static int gnttab_expand(unsigned int req_entries)
++{
++	int rc;
++	unsigned int cur, extra;
++
++	cur = nr_grant_frames;
++	extra = ((req_entries + (ENTRIES_PER_GRANT_FRAME-1)) /
++		 ENTRIES_PER_GRANT_FRAME);
++	if (cur + extra > max_nr_grant_frames())
++		return -ENOSPC;
++
++	if ((rc = gnttab_map(cur, cur + extra - 1)) == 0)
++		rc = grow_gnttab_list(extra);
++
++	return rc;
++}
++
++int __devinit gnttab_init(void)
++{
++	int i;
++	unsigned int max_nr_glist_frames, nr_glist_frames;
++	unsigned int nr_init_grefs;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	nr_grant_frames = 1;
++	boot_max_nr_grant_frames = __max_nr_grant_frames();
++
++	/* Determine the maximum number of frames required for the
++	 * grant reference free list on the current hypervisor.
++	 */
++	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;
++
++	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;
++	}
++
++	if (gnttab_resume() < 0)
++		return -ENODEV;
++
++	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;
++
++	gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
++	gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
++	gnttab_free_head  = NR_RESERVED_ENTRIES;
++
++	return 0;
++
++ ini_nomem:
++	for (i--; i >= 0; i--)
++		free_page((unsigned long)gnttab_list[i]);
++	kfree(gnttab_list);
++	return -ENOMEM;
++}
++
++#ifdef CONFIG_XEN
++core_initcall(gnttab_init);
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/hypervisor_sysfs.c	2007-07-10 09:42:30.000000000 +0200
+@@ -0,0 +1,57 @@
++/*
++ *  copyright (c) 2006 IBM Corporation
++ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/kobject.h>
++#include <xen/hypervisor_sysfs.h>
++#include <asm/hypervisor.h>
++
++static ssize_t hyp_sysfs_show(struct kobject *kobj,
++			      struct attribute *attr,
++			      char *buffer)
++{
++	struct hyp_sysfs_attr *hyp_attr;
++	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
++	if (hyp_attr->show)
++		return hyp_attr->show(hyp_attr, buffer);
++	return 0;
++}
++
++static ssize_t hyp_sysfs_store(struct kobject *kobj,
++			       struct attribute *attr,
++			       const char *buffer,
++			       size_t len)
++{
++	struct hyp_sysfs_attr *hyp_attr;
++	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
++	if (hyp_attr->store)
++		return hyp_attr->store(hyp_attr, buffer, len);
++	return 0;
++}
++
++static struct sysfs_ops hyp_sysfs_ops = {
++	.show = hyp_sysfs_show,
++	.store = hyp_sysfs_store,
++};
++
++static struct kobj_type hyp_sysfs_kobj_type = {
++	.sysfs_ops = &hyp_sysfs_ops,
++};
++
++static int __init hypervisor_subsys_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	hypervisor_subsys.kset.kobj.ktype = &hyp_sysfs_kobj_type;
++	return 0;
++}
++
++device_initcall(hypervisor_subsys_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/machine_kexec.c	2009-07-13 14:25:35.000000000 +0200
+@@ -0,0 +1,230 @@
++/*
++ * drivers/xen/core/machine_kexec.c 
++ * handle transition of Linux booting another kernel
++ */
++
++#include <linux/kexec.h>
++#include <xen/interface/kexec.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++
++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;
++	struct resource *res;
++	int k = 0;
++	int rc;
++
++	if (!is_initial_xendomain())
++		return;
++
++	/* determine maximum number of physical cpus */
++
++	while (1) {
++		memset(&range, 0, sizeof(range));
++		range.range = KEXEC_RANGE_MA_CPU;
++		range.nr = k;
++
++		if(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++			break;
++
++		k++;
++	}
++
++	if (k == 0)
++		return;
++
++	xen_max_nr_phys_cpus = k;
++
++	/* allocate xen_phys_cpus */
++
++	xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
++	BUG_ON(xen_phys_cpus == NULL);
++
++	/* fill in xen_phys_cpus with per-cpu crash note information */
++
++	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
++		memset(&range, 0, sizeof(range));
++		range.range = KEXEC_RANGE_MA_CPU;
++		range.nr = k;
++
++		if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++			goto err;
++
++		res = xen_phys_cpus + k;
++
++		memset(res, 0, sizeof(*res));
++		res->name = "Crash note";
++		res->start = range.start;
++		res->end = range.start + range.size - 1;
++		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
++	}
++
++	/* fill in xen_hypervisor_res with hypervisor machine address range */
++
++	memset(&range, 0, sizeof(range));
++	range.range = KEXEC_RANGE_MA_XEN;
++
++	if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++		goto err;
++
++	xen_hypervisor_res.name = "Hypervisor code and data";
++	xen_hypervisor_res.start = range.start;
++	xen_hypervisor_res.end = range.start + range.size - 1;
++	xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
++
++	/* fill in crashk_res if range is reserved by hypervisor */
++
++	memset(&range, 0, sizeof(range));
++	range.range = KEXEC_RANGE_MA_CRASH;
++
++	if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
++		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;
++
++	rc = HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range);
++
++	if (rc == 0) {
++		/* Hypercall succeeded */
++		vmcoreinfo_size_xen = range.size;
++		paddr_vmcoreinfo_xen = range.start;
++
++	} else {
++		/* Hypercall failed.
++		 * Indicate not to create sysfs file by resetting globals
++		 */
++		vmcoreinfo_size_xen = 0;
++		paddr_vmcoreinfo_xen = 0;
++		
++		/* The KEXEC_CMD_kexec_get_range hypercall did not implement
++		 * KEXEC_RANGE_MA_VMCOREINFO until Xen 3.3.
++		 * Do not bail out if it fails for this reason.
++		 */
++		if (rc != -EINVAL)
++			return;
++	}
++
++	if (machine_kexec_setup_resources(&xen_hypervisor_res, xen_phys_cpus,
++					  xen_max_nr_phys_cpus))
++		goto err;
++
++	return;
++
++ err:
++	/*
++	 * It isn't possible to free xen_phys_cpus this early in the
++	 * boot. Failure at this stage is unexpected and the amount of
++	 * memory is small therefore we tolerate the potential leak.
++         */
++	xen_max_nr_phys_cpus = 0;
++	return;
++}
++
++void __init xen_machine_kexec_register_resources(struct resource *res)
++{
++	int k;
++	struct resource *r;
++
++	request_resource(res, &xen_hypervisor_res);
++	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
++		r = xen_phys_cpus + k;
++		if (r->parent == NULL) /* out of xen_hypervisor_res range */
++			request_resource(res, r);
++	} 
++	machine_kexec_register_resources(res);
++}
++
++static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
++{
++	machine_kexec_setup_load_arg(xki, image);
++
++	xki->indirection_page = image->head;
++	xki->start_address = image->start;
++}
++
++/*
++ * Load the image into xen so xen can kdump itself
++ * This might have been done in prepare, but prepare
++ * is currently called too early. It might make sense
++ * to move prepare, but for now, just add an extra hook.
++ */
++int xen_machine_kexec_load(struct kimage *image)
++{
++	xen_kexec_load_t xkl;
++
++	memset(&xkl, 0, sizeof(xkl));
++	xkl.type = image->type;
++	setup_load_arg(&xkl.image, image);
++	return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
++}
++
++/*
++ * Unload the image that was stored by machine_kexec_load()
++ * This might have been done in machine_kexec_cleanup() but it
++ * is called too late, and its possible xen could try and kdump
++ * using resources that have been freed.
++ */
++void xen_machine_kexec_unload(struct kimage *image)
++{
++	xen_kexec_load_t xkl;
++
++	memset(&xkl, 0, sizeof(xkl));
++	xkl.type = image->type;
++	WARN_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl));
++}
++
++/*
++ * Do not allocate memory (or fail in any way) in machine_kexec().
++ * We are past the point of no return, committed to rebooting now.
++ *
++ * This has the hypervisor move to the prefered reboot CPU, 
++ * stop all CPUs and kexec. That is it combines machine_shutdown()
++ * and machine_kexec() in Linux kexec terms.
++ */
++NORET_TYPE void machine_kexec(struct kimage *image)
++{
++	xen_kexec_exec_t xke;
++
++	memset(&xke, 0, sizeof(xke));
++	xke.type = image->type;
++	VOID(HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke));
++	panic("KEXEC_CMD_kexec hypercall should not return\n");
++}
++
++void machine_shutdown(void)
++{
++	/* do nothing */
++}
++
++
++/*
++ * Local variables:
++ *  c-file-style: "linux"
++ *  indent-tabs-mode: t
++ *  c-indent-level: 8
++ *  c-basic-offset: 8
++ *  tab-width: 8
++ * End:
++ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/machine_reboot.c	2008-09-01 12:07:31.000000000 +0200
+@@ -0,0 +1,247 @@
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/unistd.h>
++#include <linux/module.h>
++#include <linux/reboot.h>
++#include <linux/sysrq.h>
++#include <linux/stringify.h>
++#include <linux/stop_machine.h>
++#include <asm/irq.h>
++#include <asm/mmu_context.h>
++#include <xen/evtchn.h>
++#include <asm/hypervisor.h>
++#include <xen/xenbus.h>
++#include <linux/cpu.h>
++#include <xen/gnttab.h>
++#include <xen/xencons.h>
++#include <xen/cpu_hotplug.h>
++#include <xen/interface/vcpu.h>
++
++#if defined(__i386__) || defined(__x86_64__)
++
++/*
++ * Power off function, if any
++ */
++void (*pm_power_off)(void);
++EXPORT_SYMBOL(pm_power_off);
++
++void machine_emergency_restart(void)
++{
++	/* We really want to get pending console data out before we die. */
++	xencons_force_flush();
++	HYPERVISOR_shutdown(SHUTDOWN_reboot);
++}
++
++void machine_restart(char * __unused)
++{
++	machine_emergency_restart();
++}
++
++void machine_halt(void)
++{
++	machine_power_off();
++}
++
++void machine_power_off(void)
++{
++	/* We really want to get pending console data out before we die. */
++	xencons_force_flush();
++	if (pm_power_off)
++		pm_power_off();
++	HYPERVISOR_shutdown(SHUTDOWN_poweroff);
++}
++
++int reboot_thru_bios = 0;	/* for dmi_scan.c */
++EXPORT_SYMBOL(machine_restart);
++EXPORT_SYMBOL(machine_halt);
++EXPORT_SYMBOL(machine_power_off);
++
++static void pre_suspend(void)
++{
++	HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
++	WARN_ON(HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO),
++					     __pte_ma(0), 0));
++
++	xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
++	xen_start_info->console.domU.mfn =
++		mfn_to_pfn(xen_start_info->console.domU.mfn);
++}
++
++static void post_suspend(int suspend_cancelled)
++{
++	int i, j, k, fpp;
++	unsigned long shinfo_mfn;
++	extern unsigned long max_pfn;
++	extern unsigned long *pfn_to_mfn_frame_list_list;
++	extern unsigned long *pfn_to_mfn_frame_list[];
++
++	if (suspend_cancelled) {
++		xen_start_info->store_mfn =
++			pfn_to_mfn(xen_start_info->store_mfn);
++		xen_start_info->console.domU.mfn =
++			pfn_to_mfn(xen_start_info->console.domU.mfn);
++	} else {
++#ifdef CONFIG_SMP
++		cpu_initialized_map = cpu_online_map;
++#endif
++	}
++
++	shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT;
++	if (HYPERVISOR_update_va_mapping(fix_to_virt(FIX_SHARED_INFO),
++					 pfn_pte_ma(shinfo_mfn, PAGE_KERNEL),
++					 0))
++		BUG();
++	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
++
++	memset(empty_zero_page, 0, PAGE_SIZE);
++
++	fpp = PAGE_SIZE/sizeof(unsigned long);
++	for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) {
++		if ((j % fpp) == 0) {
++			k++;
++			pfn_to_mfn_frame_list_list[k] =
++				virt_to_mfn(pfn_to_mfn_frame_list[k]);
++			j = 0;
++		}
++		pfn_to_mfn_frame_list[k][j] =
++			virt_to_mfn(&phys_to_machine_mapping[i]);
++	}
++	HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
++	HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
++		virt_to_mfn(pfn_to_mfn_frame_list_list);
++}
++
++#else /* !(defined(__i386__) || defined(__x86_64__)) */
++
++#ifndef HAVE_XEN_PRE_SUSPEND
++#define xen_pre_suspend()	((void)0)
++#endif
++
++#ifndef HAVE_XEN_POST_SUSPEND
++#define xen_post_suspend(x)	((void)0)
++#endif
++
++#define switch_idle_mm()	((void)0)
++#define mm_pin_all()		((void)0)
++#define pre_suspend()		xen_pre_suspend()
++#define post_suspend(x)		xen_post_suspend(x)
++
++#endif
++
++struct suspend {
++	int fast_suspend;
++	void (*resume_notifier)(int);
++};
++
++static int take_machine_down(void *_suspend)
++{
++	struct suspend *suspend = _suspend;
++	int suspend_cancelled, err;
++	extern void time_resume(void);
++
++	if (suspend->fast_suspend) {
++		BUG_ON(!irqs_disabled());
++	} else {
++		BUG_ON(irqs_disabled());
++
++		for (;;) {
++			err = smp_suspend();
++			if (err)
++				return err;
++
++			xenbus_suspend();
++			preempt_disable();
++
++			if (num_online_cpus() == 1)
++				break;
++
++			preempt_enable();
++			xenbus_suspend_cancel();
++		}
++
++		local_irq_disable();
++	}
++
++	mm_pin_all();
++	gnttab_suspend();
++	pre_suspend();
++
++	/*
++	 * This hypercall returns 1 if suspend was cancelled or the domain was
++	 * merely checkpointed, and 0 if it is resuming in a new domain.
++	 */
++	suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
++
++	suspend->resume_notifier(suspend_cancelled);
++	post_suspend(suspend_cancelled);
++	gnttab_resume();
++	if (!suspend_cancelled) {
++		irq_resume();
++#ifdef __x86_64__
++		/*
++		 * Older versions of Xen do not save/restore the user %cr3.
++		 * 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 (!suspend->fast_suspend)
++			xen_new_user_pt(__pa(__user_pgd(
++				current->active_mm->pgd)));
++#endif
++	}
++	time_resume();
++
++	if (!suspend->fast_suspend)
++		local_irq_enable();
++
++	return suspend_cancelled;
++}
++
++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());
++
++#if defined(__i386__) || defined(__x86_64__)
++	if (xen_feature(XENFEAT_auto_translated_physmap)) {
++		printk(KERN_WARNING "Cannot suspend in "
++		       "auto_translated_physmap mode.\n");
++		return -EOPNOTSUPP;
++	}
++#endif
++
++	/* If we are definitely UP then 'slow mode' is actually faster. */
++	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, &suspend, 0);
++		if (err < 0)
++			xenbus_suspend_cancel();
++	} else {
++		err = take_machine_down(&suspend);
++	}
++
++	if (err < 0)
++		return err;
++
++	suspend_cancelled = err;
++	if (!suspend_cancelled) {
++		xencons_resume();
++		xenbus_resume();
++	} else {
++		xenbus_suspend_cancel();
++	}
++
++	if (!fast_suspend)
++		smp_resume();
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/pci.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,83 @@
++/*
++ * vim:shiftwidth=8:noexpandtab
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <xen/interface/physdev.h>
++#include "../../pci/pci.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;
++	struct physdev_manage_pci_ext manage_pci_ext;
++
++#ifdef CONFIG_PCI_IOV
++	if (pci_dev->is_virtfn) {
++		memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
++		manage_pci_ext.bus = pci_dev->bus->number;
++		manage_pci_ext.devfn = pci_dev->devfn;
++		manage_pci_ext.is_virtfn = 1;
++		manage_pci_ext.physfn.bus = pci_dev->physfn->bus->number;
++		manage_pci_ext.physfn.devfn = pci_dev->physfn->devfn;
++		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
++					  &manage_pci_ext);
++	} else
++#endif
++	if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
++		memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
++		manage_pci_ext.bus = pci_dev->bus->number;
++		manage_pci_ext.devfn = pci_dev->devfn;
++		manage_pci_ext.is_extfn = 1;
++		r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
++					  &manage_pci_ext);
++	} else {
++		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);
++	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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/reboot.c	2008-08-07 12:44:36.000000000 +0200
+@@ -0,0 +1,335 @@
++#define __KERNEL_SYSCALLS__
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/unistd.h>
++#include <linux/module.h>
++#include <linux/reboot.h>
++#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>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++MODULE_LICENSE("Dual BSD/GPL");
++
++#define SHUTDOWN_INVALID  -1
++#define SHUTDOWN_POWEROFF  0
++#define SHUTDOWN_SUSPEND   2
++#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);
++
++static int setup_suspend_evtchn(void);
++
++int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
++
++static int shutdown_process(void *__unused)
++{
++	static char *envp[] = { "HOME=/", "TERM=linux",
++				"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
++	static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
++
++	extern asmlinkage long sys_reboot(int magic1, int magic2,
++					  unsigned int cmd, void *arg);
++
++	if ((shutting_down == SHUTDOWN_POWEROFF) ||
++	    (shutting_down == SHUTDOWN_HALT)) {
++		if (call_usermodehelper("/sbin/poweroff", poweroff_argv,
++					envp, 0) < 0) {
++#ifdef CONFIG_XEN
++			sys_reboot(LINUX_REBOOT_MAGIC1,
++				   LINUX_REBOOT_MAGIC2,
++				   LINUX_REBOOT_CMD_POWER_OFF,
++				   NULL);
++#endif /* CONFIG_XEN */
++		}
++	}
++
++	shutting_down = SHUTDOWN_INVALID; /* could try again */
++
++	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, 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 fail;
++	}
++
++	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;
++	}
++
++	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)
++{
++	int err;
++
++	err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
++			    xen_suspend : shutdown_process,
++			    NULL, CLONE_FS | CLONE_FILES);
++
++	if (err < 0) {
++		printk(KERN_WARNING "Error creating shutdown process (%d): "
++		       "retrying...\n", -err);
++		schedule_delayed_work(&shutdown_work, HZ/2);
++	}
++}
++
++static void shutdown_handler(struct xenbus_watch *watch,
++			     const char **vec, unsigned int len)
++{
++	extern void ctrl_alt_del(void);
++	char *str;
++	struct xenbus_transaction xbt;
++	int err, new_state = SHUTDOWN_INVALID;
++
++	if ((shutting_down != SHUTDOWN_INVALID) &&
++	    (shutting_down != SHUTDOWN_RESUMING))
++		return;
++
++ again:
++	err = xenbus_transaction_start(&xbt);
++	if (err)
++		return;
++
++	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
++	/* Ignore read errors and empty reads. */
++	if (XENBUS_IS_ERR_READ(str)) {
++		xenbus_transaction_end(xbt, 1);
++		return;
++	}
++
++	xenbus_write(xbt, "control", "shutdown", "");
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN) {
++		kfree(str);
++		goto again;
++	}
++
++	if (strcmp(str, "poweroff") == 0)
++		new_state = SHUTDOWN_POWEROFF;
++	else if (strcmp(str, "reboot") == 0)
++		ctrl_alt_del();
++	else if (strcmp(str, "suspend") == 0)
++		new_state = SHUTDOWN_SUSPEND;
++	else if (strcmp(str, "halt") == 0)
++		new_state = SHUTDOWN_HALT;
++	else
++		printk("Ignoring shutdown request: %s\n", str);
++
++	switch_shutdown_state(new_state);
++
++	kfree(str);
++}
++
++static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
++			  unsigned int len)
++{
++	char sysrq_key = '\0';
++	struct xenbus_transaction xbt;
++	int err;
++
++ again:
++	err = xenbus_transaction_start(&xbt);
++	if (err)
++		return;
++	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
++		printk(KERN_ERR "Unable to read sysrq code in "
++		       "control/sysrq\n");
++		xenbus_transaction_end(xbt, 1);
++		return;
++	}
++
++	if (sysrq_key != '\0')
++		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++
++#ifdef CONFIG_MAGIC_SYSRQ
++	if (sysrq_key != '\0')
++		handle_sysrq(sysrq_key, NULL, NULL);
++#endif
++}
++
++static struct xenbus_watch shutdown_watch = {
++	.node = "control/shutdown",
++	.callback = shutdown_handler
++};
++
++static struct xenbus_watch sysrq_watch = {
++	.node = "control/sysrq",
++	.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;
++
++	xenbus_scanf(XBT_NIL, "control",
++		     "platform-feature-multiprocessor-suspend",
++		     "%d", &fast_suspend);
++
++	err = register_xenbus_watch(&shutdown_watch);
++	if (err) {
++		printk(KERN_ERR "Failed to set shutdown watcher\n");
++		return err;
++	}
++
++	err = register_xenbus_watch(&sysrq_watch);
++	if (err) {
++		printk(KERN_ERR "Failed to set sysrq watcher\n");
++		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;
++}
++
++#ifdef CONFIG_XEN
++
++static int shutdown_event(struct notifier_block *notifier,
++			  unsigned long event,
++			  void *data)
++{
++	setup_shutdown_watcher();
++	return NOTIFY_DONE;
++}
++
++static int __init setup_shutdown_event(void)
++{
++	static struct notifier_block xenstore_notifier = {
++		.notifier_call = shutdown_event
++	};
++	register_xenstore_notifier(&xenstore_notifier);
++
++	return 0;
++}
++
++subsys_initcall(setup_shutdown_event);
++
++#else /* !defined(CONFIG_XEN) */
++
++int xen_reboot_init(void)
++{
++	return setup_shutdown_watcher();
++}
++
++#endif /* !defined(CONFIG_XEN) */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-05-19 09:16:41.000000000 +0200
+@@ -0,0 +1,460 @@
++/*
++ *	Xen SMP booting functions
++ *
++ *	See arch/i386/kernel/smpboot.c for copyright and credits for derived
++ *	portions of this file.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/kernel_stat.h>
++#include <linux/smp_lock.h>
++#include <linux/irq.h>
++#include <linux/bootmem.h>
++#include <linux/notifier.h>
++#include <linux/cpu.h>
++#include <linux/percpu.h>
++#include <asm/desc.h>
++#include <asm/arch_hooks.h>
++#include <asm/pgalloc.h>
++#include <xen/evtchn.h>
++#include <xen/interface/vcpu.h>
++#include <xen/cpu_hotplug.h>
++#include <xen/xenbus.h>
++
++extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
++extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
++
++extern int local_setup_timer(unsigned int cpu);
++extern void local_teardown_timer(unsigned int cpu);
++
++extern void hypervisor_callback(void);
++extern void failsafe_callback(void);
++extern void system_call(void);
++extern void smp_trap_init(trap_info_t *);
++
++/* Number of siblings per CPU package */
++int smp_num_siblings = 1;
++
++cpumask_t cpu_online_map;
++EXPORT_SYMBOL(cpu_online_map);
++cpumask_t cpu_possible_map;
++EXPORT_SYMBOL(cpu_possible_map);
++cpumask_t cpu_initialized_map;
++
++struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
++EXPORT_SYMBOL(cpu_data);
++
++static DEFINE_PER_CPU(int, resched_irq);
++static DEFINE_PER_CPU(int, callfunc_irq);
++static char resched_name[NR_CPUS][15];
++static char callfunc_name[NR_CPUS][15];
++
++u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
++
++cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
++cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
++EXPORT_SYMBOL(cpu_core_map);
++
++#if defined(__i386__)
++u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
++EXPORT_SYMBOL(x86_cpu_to_apicid);
++#elif !defined(CONFIG_X86_IO_APIC)
++unsigned int maxcpus = NR_CPUS;
++#endif
++
++void __init prefill_possible_map(void)
++{
++	int i, rc;
++
++	for_each_possible_cpu(i)
++	    if (i != smp_processor_id())
++		return;
++
++	for (i = 0; i < NR_CPUS; i++) {
++		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
++		if (rc >= 0)
++			cpu_set(i, cpu_possible_map);
++	}
++}
++
++void __init smp_alloc_memory(void)
++{
++}
++
++static inline void
++set_cpu_sibling_map(unsigned int cpu)
++{
++	cpu_data[cpu].phys_proc_id = cpu;
++	cpu_data[cpu].cpu_core_id  = 0;
++
++	cpu_sibling_map[cpu] = cpumask_of_cpu(cpu);
++	cpu_core_map[cpu]    = cpumask_of_cpu(cpu);
++
++	cpu_data[cpu].booted_cores = 1;
++}
++
++static void
++remove_siblinginfo(unsigned int cpu)
++{
++	cpu_data[cpu].phys_proc_id = BAD_APICID;
++	cpu_data[cpu].cpu_core_id  = BAD_APICID;
++
++	cpus_clear(cpu_sibling_map[cpu]);
++	cpus_clear(cpu_core_map[cpu]);
++
++	cpu_data[cpu].booted_cores = 0;
++}
++
++static int __cpuinit xen_smp_intr_init(unsigned int cpu)
++{
++	int rc;
++
++	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
++
++	sprintf(resched_name[cpu], "resched%u", cpu);
++	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
++				    cpu,
++				    smp_reschedule_interrupt,
++				    SA_INTERRUPT,
++				    resched_name[cpu],
++				    NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(resched_irq, cpu) = rc;
++
++	sprintf(callfunc_name[cpu], "callfunc%u", cpu);
++	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
++				    cpu,
++				    smp_call_function_interrupt,
++				    SA_INTERRUPT,
++				    callfunc_name[cpu],
++				    NULL);
++	if (rc < 0)
++		goto fail;
++	per_cpu(callfunc_irq, cpu) = rc;
++
++	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
++		goto fail;
++
++	return 0;
++
++ fail:
++	if (per_cpu(resched_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
++	if (per_cpu(callfunc_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	return rc;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void xen_smp_intr_exit(unsigned int cpu)
++{
++	if (cpu != 0)
++		local_teardown_timer(cpu);
++
++	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
++	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++}
++#endif
++
++void __cpuinit cpu_bringup(void)
++{
++	cpu_init();
++	identify_cpu(cpu_data + smp_processor_id());
++	touch_softlockup_watchdog();
++	preempt_disable();
++	local_irq_enable();
++}
++
++static void __cpuinit cpu_bringup_and_idle(void)
++{
++	cpu_bringup();
++	cpu_idle();
++}
++
++static void __cpuinit cpu_initialize_context(unsigned int cpu)
++{
++	/* vcpu_guest_context_t is too large to allocate on the stack.
++	 * Hence we allocate statically and protect it with a lock */
++	static vcpu_guest_context_t ctxt;
++	static DEFINE_SPINLOCK(ctxt_lock);
++
++	struct task_struct *idle = idle_task(cpu);
++#ifdef __x86_64__
++	struct desc_ptr *gdt_descr = &cpu_gdt_descr[cpu];
++#else
++	struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++#endif
++
++	if (cpu_test_and_set(cpu, cpu_initialized_map))
++		return;
++
++	spin_lock(&ctxt_lock);
++
++	memset(&ctxt, 0, sizeof(ctxt));
++
++	ctxt.flags = VGCF_IN_KERNEL;
++	ctxt.user_regs.ds = __USER_DS;
++	ctxt.user_regs.es = __USER_DS;
++	ctxt.user_regs.fs = 0;
++	ctxt.user_regs.gs = 0;
++	ctxt.user_regs.ss = __KERNEL_DS;
++	ctxt.user_regs.eip = (unsigned long)cpu_bringup_and_idle;
++	ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
++
++	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
++
++	smp_trap_init(ctxt.trap_ctxt);
++
++	ctxt.ldt_ents = 0;
++
++	ctxt.gdt_frames[0] = virt_to_mfn(gdt_descr->address);
++	ctxt.gdt_ents      = gdt_descr->size / 8;
++
++#ifdef __i386__
++	ctxt.user_regs.cs = __KERNEL_CS;
++	ctxt.user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs);
++
++	ctxt.kernel_ss = __KERNEL_DS;
++	ctxt.kernel_sp = idle->thread.esp0;
++
++	ctxt.event_callback_cs     = __KERNEL_CS;
++	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
++	ctxt.failsafe_callback_cs  = __KERNEL_CS;
++	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
++
++	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
++#else /* __x86_64__ */
++	ctxt.user_regs.cs = __KERNEL_CS;
++	ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs);
++
++	ctxt.kernel_ss = __KERNEL_DS;
++	ctxt.kernel_sp = idle->thread.rsp0;
++
++	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
++	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
++	ctxt.syscall_callback_eip  = (unsigned long)system_call;
++
++	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
++
++	ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu));
++#endif
++
++	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt))
++		BUG();
++
++	spin_unlock(&ctxt_lock);
++}
++
++void __init smp_prepare_cpus(unsigned int max_cpus)
++{
++	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
++
++	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] = apicid;
++	x86_cpu_to_apicid[0] = apicid;
++
++	current_thread_info()->cpu = 0;
++
++	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++		cpus_clear(cpu_sibling_map[cpu]);
++		cpus_clear(cpu_core_map[cpu]);
++	}
++
++	set_cpu_sibling_map(0);
++
++	if (xen_smp_intr_init(0))
++		BUG();
++
++	cpu_initialized_map = cpumask_of_cpu(0);
++
++	/* Restrict the possible_map according to max_cpus. */
++	while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
++		for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--)
++			continue;
++		cpu_clear(cpu, cpu_possible_map);
++	}
++
++	for_each_possible_cpu (cpu) {
++		if (cpu == 0)
++			continue;
++
++#ifdef __x86_64__
++		gdt_descr = &cpu_gdt_descr[cpu];
++#else
++		gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++#endif
++		gdt_descr->address = get_zeroed_page(GFP_KERNEL);
++		if (unlikely(!gdt_descr->address)) {
++			printk(KERN_CRIT "CPU%d failed to allocate GDT\n",
++			       cpu);
++			continue;
++		}
++		gdt_descr->size = GDT_SIZE;
++		memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
++		make_page_readonly(
++			(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 = apicid;
++
++		cpu_2_logical_apicid[cpu] = apicid;
++		x86_cpu_to_apicid[cpu] = apicid;
++
++		idle = fork_idle(cpu);
++		if (IS_ERR(idle))
++			panic("failed fork for CPU %d", cpu);
++
++#ifdef __x86_64__
++		cpu_pda(cpu)->pcurrent = idle;
++		cpu_pda(cpu)->cpunumber = cpu;
++		clear_tsk_thread_flag(idle, TIF_FORK);
++#endif
++
++		irq_ctx_init(cpu);
++
++#ifdef CONFIG_HOTPLUG_CPU
++		if (is_initial_xendomain())
++			cpu_set(cpu, cpu_present_map);
++#else
++		cpu_set(cpu, cpu_present_map);
++#endif
++	}
++
++	init_xenbus_allowed_cpumask();
++
++#ifdef CONFIG_X86_IO_APIC
++	/*
++	 * Here we can be sure that there is an IO-APIC in the system. Let's
++	 * go and set it up:
++	 */
++	if (!skip_ioapic_setup && nr_ioapics)
++		setup_IO_APIC();
++#endif
++}
++
++void __devinit smp_prepare_boot_cpu(void)
++{
++	prefill_possible_map();
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++/*
++ * Initialize cpu_present_map late to skip SMP boot code in init/main.c.
++ * But do it early enough to catch critical for_each_present_cpu() loops
++ * in i386-specific code.
++ */
++static int __init initialize_cpu_present_map(void)
++{
++	cpu_present_map = cpu_possible_map;
++	return 0;
++}
++core_initcall(initialize_cpu_present_map);
++
++int __cpu_disable(void)
++{
++	cpumask_t map = cpu_online_map;
++	unsigned int cpu = smp_processor_id();
++
++	if (cpu == 0)
++		return -EBUSY;
++
++	remove_siblinginfo(cpu);
++
++	cpu_clear(cpu, map);
++	fixup_irqs(map);
++	cpu_clear(cpu, cpu_online_map);
++
++	return 0;
++}
++
++void __cpu_die(unsigned int cpu)
++{
++	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
++		current->state = TASK_UNINTERRUPTIBLE;
++		schedule_timeout(HZ/10);
++	}
++
++	xen_smp_intr_exit(cpu);
++
++	if (num_online_cpus() == 1)
++		alternatives_smp_switch(0);
++}
++
++#endif /* CONFIG_HOTPLUG_CPU */
++
++int __cpuinit __cpu_up(unsigned int cpu)
++{
++	int rc;
++
++	rc = cpu_up_check(cpu);
++	if (rc)
++		return rc;
++
++	cpu_initialize_context(cpu);
++
++	if (num_online_cpus() == 1)
++		alternatives_smp_switch(1);
++
++	/* This must be done before setting cpu_online_map */
++	set_cpu_sibling_map(cpu);
++	wmb();
++
++	rc = xen_smp_intr_init(cpu);
++	if (rc) {
++		remove_siblinginfo(cpu);
++		return rc;
++	}
++
++	cpu_set(cpu, cpu_online_map);
++
++	rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
++	BUG_ON(rc);
++
++	return 0;
++}
++
++void __init smp_cpus_done(unsigned int max_cpus)
++{
++}
++
++#ifndef CONFIG_X86_LOCAL_APIC
++int setup_profiling_timer(unsigned int multiplier)
++{
++	return -EINVAL;
++}
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/xen_proc.c	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,23 @@
++
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <xen/xen_proc.h>
++
++static struct proc_dir_entry *xen_base;
++
++struct proc_dir_entry *create_xen_proc_entry(const char *name, mode_t mode)
++{
++	if ( xen_base == NULL )
++		if ( (xen_base = proc_mkdir("xen", &proc_root)) == NULL )
++			panic("Couldn't create /proc/xen");
++	return create_proc_entry(name, mode, xen_base);
++}
++
++EXPORT_SYMBOL_GPL(create_xen_proc_entry); 
++
++void remove_xen_proc_entry(const char *name)
++{
++	remove_proc_entry(name, xen_base);
++}
++
++EXPORT_SYMBOL_GPL(remove_xen_proc_entry); 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/xen_sysfs.c	2009-05-29 10:25:53.000000000 +0200
+@@ -0,0 +1,427 @@
++/*
++ *  copyright (c) 2006 IBM Corporation
++ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
++ */
++
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <asm/hypervisor.h>
++#include <xen/features.h>
++#include <xen/hypervisor_sysfs.h>
++#include <xen/xenbus.h>
++#include <xen/interface/kexec.h>
++#include "../xenbus/xenbus_comms.h"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Mike D. Day <ncmike@us.ibm.com>");
++
++static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	return sprintf(buffer, "xen\n");
++}
++
++HYPERVISOR_ATTR_RO(type);
++
++static int __init xen_sysfs_type_init(void)
++{
++	return sysfs_create_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++}
++
++static void xen_sysfs_type_destroy(void)
++{
++	sysfs_remove_file(&hypervisor_subsys.kset.kobj, &type_attr.attr);
++}
++
++/* xen version attributes */
++static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
++	if (version)
++		return sprintf(buffer, "%d\n", version >> 16);
++	return -ENODEV;
++}
++
++HYPERVISOR_ATTR_RO(major);
++
++static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
++	if (version)
++		return sprintf(buffer, "%d\n", version & 0xff);
++	return -ENODEV;
++}
++
++HYPERVISOR_ATTR_RO(minor);
++
++static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	char *extra;
++
++	extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
++	if (extra) {
++		ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", extra);
++		kfree(extra);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(extra);
++
++static struct attribute *version_attrs[] = {
++	&major_attr.attr,
++	&minor_attr.attr,
++	&extra_attr.attr,
++	NULL
++};
++
++static struct attribute_group version_group = {
++	.name = "version",
++	.attrs = version_attrs,
++};
++
++static int __init xen_sysfs_version_init(void)
++{
++	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++				  &version_group);
++}
++
++static void xen_sysfs_version_destroy(void)
++{
++	sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group);
++}
++
++/* UUID */
++
++static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	char *vm, *val;
++	int ret;
++
++	if (!is_xenstored_ready())
++		return -EBUSY;
++
++	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
++	if (IS_ERR(vm))
++		return PTR_ERR(vm);
++	val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
++	kfree(vm);
++	if (IS_ERR(val))
++		return PTR_ERR(val);
++	ret = sprintf(buffer, "%s\n", val);
++	kfree(val);
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(uuid);
++
++static int __init xen_sysfs_uuid_init(void)
++{
++	return sysfs_create_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
++}
++
++static void xen_sysfs_uuid_destroy(void)
++{
++	sysfs_remove_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
++}
++
++/* xen compilation attributes */
++
++static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	struct xen_compile_info *info;
++
++	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++	if (info) {
++		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", info->compiler);
++		kfree(info);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(compiler);
++
++static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	struct xen_compile_info *info;
++
++	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++	if (info) {
++		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", info->compile_by);
++		kfree(info);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(compiled_by);
++
++static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	struct xen_compile_info *info;
++
++	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
++	if (info) {
++		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", info->compile_date);
++		kfree(info);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(compile_date);
++
++static struct attribute *xen_compile_attrs[] = {
++	&compiler_attr.attr,
++	&compiled_by_attr.attr,
++	&compile_date_attr.attr,
++	NULL
++};
++
++static struct attribute_group xen_compilation_group = {
++	.name = "compilation",
++	.attrs = xen_compile_attrs,
++};
++
++int __init static xen_compilation_init(void)
++{
++	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++				  &xen_compilation_group);
++}
++
++static void xen_compilation_destroy(void)
++{
++	sysfs_remove_group(&hypervisor_subsys.kset.kobj,
++			   &xen_compilation_group);
++}
++
++/* xen properties info */
++
++static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	char *caps;
++
++	caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
++	if (caps) {
++		ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", caps);
++		kfree(caps);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(capabilities);
++
++static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	char *cset;
++
++	cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
++	if (cset) {
++		ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
++		if (!ret)
++			ret = sprintf(buffer, "%s\n", cset);
++		kfree(cset);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(changeset);
++
++static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret = -ENOMEM;
++	struct xen_platform_parameters *parms;
++
++	parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
++	if (parms) {
++		ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
++					     parms);
++		if (!ret)
++			ret = sprintf(buffer, "%lx\n", parms->virt_start);
++		kfree(parms);
++	}
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(virtual_start);
++
++static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	int ret;
++
++	ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
++	if (ret > 0)
++		ret = sprintf(buffer, "%x\n", ret);
++
++	return ret;
++}
++
++HYPERVISOR_ATTR_RO(pagesize);
++
++/* eventually there will be several more features to export */
++static ssize_t xen_feature_show(int index, char *buffer)
++{
++	int ret = -ENOMEM;
++	struct xen_feature_info *info;
++
++	info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL);
++	if (info) {
++		info->submap_idx = index;
++		ret = HYPERVISOR_xen_version(XENVER_get_features, info);
++		if (!ret)
++			ret = sprintf(buffer, "%d\n", info->submap);
++		kfree(info);
++	}
++
++	return ret;
++}
++
++static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer)
++{
++	return xen_feature_show(XENFEAT_writable_page_tables, buffer);
++}
++
++HYPERVISOR_ATTR_RO(writable_pt);
++
++static struct attribute *xen_properties_attrs[] = {
++	&capabilities_attr.attr,
++	&changeset_attr.attr,
++	&virtual_start_attr.attr,
++	&pagesize_attr.attr,
++	&writable_pt_attr.attr,
++	NULL
++};
++
++static struct attribute_group xen_properties_group = {
++	.name = "properties",
++	.attrs = xen_properties_attrs,
++};
++
++static int __init xen_properties_init(void)
++{
++	return sysfs_create_group(&hypervisor_subsys.kset.kobj,
++				  &xen_properties_group);
++}
++
++static void xen_properties_destroy(void)
++{
++	sysfs_remove_group(&hypervisor_subsys.kset.kobj,
++			   &xen_properties_group);
++}
++
++#ifdef CONFIG_KEXEC
++
++extern size_t vmcoreinfo_size_xen;
++extern unsigned long paddr_vmcoreinfo_xen;
++
++static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
++{
++	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);
++}
++
++#endif
++
++static int __init hyper_sysfs_init(void)
++{
++	int ret;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	ret = xen_sysfs_type_init();
++	if (ret)
++		goto out;
++	ret = xen_sysfs_version_init();
++	if (ret)
++		goto version_out;
++	ret = xen_compilation_init();
++	if (ret)
++		goto comp_out;
++	ret = xen_sysfs_uuid_init();
++	if (ret)
++		goto uuid_out;
++	ret = xen_properties_init();
++	if (ret)
++		goto prop_out;
++#ifdef CONFIG_KEXEC
++	if (vmcoreinfo_size_xen != 0) {
++		ret = xen_sysfs_vmcoreinfo_init();
++		if (ret)
++			goto vmcoreinfo_out;
++	}
++#endif
++
++	goto out;
++
++#ifdef CONFIG_KEXEC
++vmcoreinfo_out:
++#endif
++	xen_properties_destroy();
++prop_out:
++	xen_sysfs_uuid_destroy();
++uuid_out:
++	xen_compilation_destroy();
++comp_out:
++	xen_sysfs_version_destroy();
++version_out:
++	xen_sysfs_type_destroy();
++out:
++	return ret;
++}
++
++static void __exit hyper_sysfs_exit(void)
++{
++#ifdef CONFIG_KEXEC
++	if (vmcoreinfo_size_xen != 0)
++		xen_sysfs_vmcoreinfo_destroy();
++#endif
++	xen_properties_destroy();
++	xen_compilation_destroy();
++	xen_sysfs_uuid_destroy();
++	xen_sysfs_version_destroy();
++	xen_sysfs_type_destroy();
++
++}
++
++module_init(hyper_sysfs_init);
++module_exit(hyper_sysfs_exit);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/xencomm.c	2007-11-12 08:41:05.000000000 +0100
+@@ -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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/evtchn/Makefile	2007-06-12 13:13:44.000000000 +0200
+@@ -0,0 +1,2 @@
++
++obj-y	:= evtchn.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/evtchn/evtchn.c	2009-03-18 10:39:31.000000000 +0100
+@@ -0,0 +1,562 @@
++/******************************************************************************
++ * evtchn.c
++ * 
++ * Driver for receiving and demuxing event-channel signals.
++ * 
++ * Copyright (c) 2004-2005, K A Fraser
++ * Multi-process extensions Copyright (c) 2004, Steven Smith
++ * 
++ * 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/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/errno.h>
++#include <linux/miscdevice.h>
++#include <linux/major.h>
++#include <linux/proc_fs.h>
++#include <linux/stat.h>
++#include <linux/poll.h>
++#include <linux/irq.h>
++#include <linux/init.h>
++#include <linux/gfp.h>
++#include <linux/mutex.h>
++#include <linux/cpu.h>
++#include <xen/evtchn.h>
++#include <xen/public/evtchn.h>
++
++struct per_user_data {
++	/* Notification ring, accessed via /dev/xen/evtchn. */
++#define EVTCHN_RING_SIZE     (PAGE_SIZE / sizeof(evtchn_port_t))
++#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
++	evtchn_port_t *ring;
++	unsigned int ring_cons, ring_prod, ring_overflow;
++	struct mutex ring_cons_mutex; /* protect against concurrent readers */
++
++	/* Processes wait on this queue when ring is empty. */
++	wait_queue_head_t evtchn_wait;
++	struct fasync_struct *evtchn_async_queue;
++
++	int bind_cpu;
++	int nr_event_wrong_delivery;
++};
++
++/* Who's bound to each port? */
++static struct per_user_data *port_user[NR_EVENT_CHANNELS];
++static spinlock_t port_user_lock;
++
++void evtchn_device_upcall(int port)
++{
++	struct per_user_data *u;
++
++	spin_lock(&port_user_lock);
++
++	mask_evtchn(port);
++	clear_evtchn(port);
++
++	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,
++					    SIGIO, POLL_IN);
++			}
++		} else {
++			u->ring_overflow = 1;
++		}
++	}
++
++	spin_unlock(&port_user_lock);
++}
++
++static void evtchn_check_wrong_delivery(struct per_user_data *u)
++{
++	evtchn_port_t port;
++	unsigned int current_cpu = smp_processor_id();
++
++	/* Delivered to correct CPU? All is good. */
++	if (u->bind_cpu == current_cpu) {
++		u->nr_event_wrong_delivery = 0;
++		return;
++	}
++
++	/* Tolerate up to 100 consecutive misdeliveries. */
++	if (++u->nr_event_wrong_delivery < 100)
++		return;
++
++	spin_lock_irq(&port_user_lock);
++
++	for (port = 0; port < NR_EVENT_CHANNELS; port++)
++		if (port_user[port] == u)
++			rebind_evtchn_to_cpu(port, current_cpu);
++
++	u->bind_cpu = current_cpu;
++	u->nr_event_wrong_delivery = 0;
++
++	spin_unlock_irq(&port_user_lock);
++}
++
++static ssize_t evtchn_read(struct file *file, char __user *buf,
++			   size_t count, loff_t *ppos)
++{
++	int rc;
++	unsigned int c, p, bytes1 = 0, bytes2 = 0;
++	struct per_user_data *u = file->private_data;
++
++	/* Whole number of ports. */
++	count &= ~(sizeof(evtchn_port_t)-1);
++
++	if (count == 0)
++		return 0;
++
++	if (count > PAGE_SIZE)
++		count = PAGE_SIZE;
++
++	for (;;) {
++		mutex_lock(&u->ring_cons_mutex);
++
++		rc = -EFBIG;
++		if (u->ring_overflow)
++			goto unlock_out;
++
++		if ((c = u->ring_cons) != (p = u->ring_prod))
++			break;
++
++		mutex_unlock(&u->ring_cons_mutex);
++
++		if (file->f_flags & O_NONBLOCK)
++			return -EAGAIN;
++
++		rc = wait_event_interruptible(
++			u->evtchn_wait, u->ring_cons != u->ring_prod);
++		if (rc)
++			return rc;
++	}
++
++	/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
++	if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
++		bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
++			sizeof(evtchn_port_t);
++		bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
++	} else {
++		bytes1 = (p - c) * sizeof(evtchn_port_t);
++		bytes2 = 0;
++	}
++
++	/* Truncate chunks according to caller's maximum byte count. */
++	if (bytes1 > count) {
++		bytes1 = count;
++		bytes2 = 0;
++	} else if ((bytes1 + bytes2) > count) {
++		bytes2 = count - bytes1;
++	}
++
++	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)))
++		goto unlock_out;
++	
++	evtchn_check_wrong_delivery(u);
++
++	u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
++	rc = bytes1 + bytes2;
++
++ unlock_out:
++	mutex_unlock(&u->ring_cons_mutex);
++	return rc;
++}
++
++static ssize_t evtchn_write(struct file *file, const char __user *buf,
++			    size_t count, loff_t *ppos)
++{
++	int rc, i;
++	evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
++	struct per_user_data *u = file->private_data;
++
++	if (kbuf == NULL)
++		return -ENOMEM;
++
++	/* Whole number of ports. */
++	count &= ~(sizeof(evtchn_port_t)-1);
++
++	rc = 0;
++	if (count == 0)
++		goto out;
++
++	if (count > PAGE_SIZE)
++		count = PAGE_SIZE;
++
++	rc = -EFAULT;
++	if (copy_from_user(kbuf, buf, count) != 0)
++		goto out;
++
++	spin_lock_irq(&port_user_lock);
++	for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
++		if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
++			unmask_evtchn(kbuf[i]);
++	spin_unlock_irq(&port_user_lock);
++
++	rc = count;
++
++ out:
++	free_page((unsigned long)kbuf);
++	return rc;
++}
++
++static unsigned int next_bind_cpu(cpumask_t map)
++{
++	static unsigned int bind_cpu;
++	bind_cpu = next_cpu(bind_cpu, map);
++	if (bind_cpu >= NR_CPUS)
++		bind_cpu = first_cpu(map);
++	return bind_cpu;
++}
++
++static void evtchn_bind_to_user(struct per_user_data *u, int port)
++{
++	spin_lock_irq(&port_user_lock);
++
++	BUG_ON(port_user[port] != NULL);
++	port_user[port] = u;
++
++	if (u->bind_cpu == -1)
++		u->bind_cpu = next_bind_cpu(cpu_online_map);
++
++	rebind_evtchn_to_cpu(port, u->bind_cpu);
++
++	unmask_evtchn(port);
++
++	spin_unlock_irq(&port_user_lock);
++}
++
++static long evtchn_ioctl(struct file *file,
++			 unsigned int cmd, unsigned long arg)
++{
++	int rc;
++	struct per_user_data *u = file->private_data;
++	void __user *uarg = (void __user *) arg;
++
++	switch (cmd) {
++	case IOCTL_EVTCHN_BIND_VIRQ: {
++		struct ioctl_evtchn_bind_virq bind;
++		struct evtchn_bind_virq bind_virq;
++
++		rc = -EFAULT;
++		if (copy_from_user(&bind, uarg, sizeof(bind)))
++			break;
++
++		bind_virq.virq = bind.virq;
++		bind_virq.vcpu = 0;
++		rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++						 &bind_virq);
++		if (rc != 0)
++			break;
++
++		rc = bind_virq.port;
++		evtchn_bind_to_user(u, rc);
++		break;
++	}
++
++	case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
++		struct ioctl_evtchn_bind_interdomain bind;
++		struct evtchn_bind_interdomain bind_interdomain;
++
++		rc = -EFAULT;
++		if (copy_from_user(&bind, uarg, sizeof(bind)))
++			break;
++
++		bind_interdomain.remote_dom  = bind.remote_domain;
++		bind_interdomain.remote_port = bind.remote_port;
++		rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
++						 &bind_interdomain);
++		if (rc != 0)
++			break;
++
++		rc = bind_interdomain.local_port;
++		evtchn_bind_to_user(u, rc);
++		break;
++	}
++
++	case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
++		struct ioctl_evtchn_bind_unbound_port bind;
++		struct evtchn_alloc_unbound alloc_unbound;
++
++		rc = -EFAULT;
++		if (copy_from_user(&bind, uarg, sizeof(bind)))
++			break;
++
++		alloc_unbound.dom        = DOMID_SELF;
++		alloc_unbound.remote_dom = bind.remote_domain;
++		rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
++						 &alloc_unbound);
++		if (rc != 0)
++			break;
++
++		rc = alloc_unbound.port;
++		evtchn_bind_to_user(u, rc);
++		break;
++	}
++
++	case IOCTL_EVTCHN_UNBIND: {
++		struct ioctl_evtchn_unbind unbind;
++		struct evtchn_close close;
++		int ret;
++
++		rc = -EFAULT;
++		if (copy_from_user(&unbind, uarg, sizeof(unbind)))
++			break;
++
++		rc = -EINVAL;
++		if (unbind.port >= NR_EVENT_CHANNELS)
++			break;
++
++		spin_lock_irq(&port_user_lock);
++    
++		rc = -ENOTCONN;
++		if (port_user[unbind.port] != u) {
++			spin_unlock_irq(&port_user_lock);
++			break;
++		}
++
++		port_user[unbind.port] = NULL;
++		mask_evtchn(unbind.port);
++		rebind_evtchn_to_cpu(unbind.port, 0);
++
++		spin_unlock_irq(&port_user_lock);
++
++		close.port = unbind.port;
++		ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
++		BUG_ON(ret);
++
++		rc = 0;
++		break;
++	}
++
++	case IOCTL_EVTCHN_NOTIFY: {
++		struct ioctl_evtchn_notify notify;
++
++		rc = -EFAULT;
++		if (copy_from_user(&notify, uarg, sizeof(notify)))
++			break;
++
++		if (notify.port >= NR_EVENT_CHANNELS) {
++			rc = -EINVAL;
++		} else if (port_user[notify.port] != u) {
++			rc = -ENOTCONN;
++		} else {
++			notify_remote_via_evtchn(notify.port);
++			rc = 0;
++		}
++		break;
++	}
++
++	case IOCTL_EVTCHN_RESET: {
++		/* Initialise the ring to empty. Clear errors. */
++		mutex_lock(&u->ring_cons_mutex);
++		spin_lock_irq(&port_user_lock);
++		u->ring_cons = u->ring_prod = u->ring_overflow = 0;
++		spin_unlock_irq(&port_user_lock);
++		mutex_unlock(&u->ring_cons_mutex);
++		rc = 0;
++		break;
++	}
++
++	default:
++		rc = -ENOSYS;
++		break;
++	}
++
++	return rc;
++}
++
++static unsigned int evtchn_poll(struct file *file, poll_table *wait)
++{
++	unsigned int mask = POLLOUT | POLLWRNORM;
++	struct per_user_data *u = file->private_data;
++
++	poll_wait(file, &u->evtchn_wait, wait);
++	if (u->ring_cons != u->ring_prod)
++		mask |= POLLIN | POLLRDNORM;
++	if (u->ring_overflow)
++		mask = POLLERR;
++	return mask;
++}
++
++static int evtchn_fasync(int fd, struct file *filp, int on)
++{
++	struct per_user_data *u = filp->private_data;
++	return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
++}
++
++static int evtchn_open(struct inode *inode, struct file *filp)
++{
++	struct per_user_data *u;
++
++	if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL)
++		return -ENOMEM;
++
++	memset(u, 0, sizeof(*u));
++	init_waitqueue_head(&u->evtchn_wait);
++
++	u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
++	if (u->ring == NULL) {
++		kfree(u);
++		return -ENOMEM;
++	}
++
++	mutex_init(&u->ring_cons_mutex);
++
++	filp->private_data = u;
++
++	u->bind_cpu = -1;
++
++	return 0;
++}
++
++static int evtchn_release(struct inode *inode, struct file *filp)
++{
++	int i;
++	struct per_user_data *u = filp->private_data;
++	struct evtchn_close close;
++
++	spin_lock_irq(&port_user_lock);
++
++	free_page((unsigned long)u->ring);
++
++	for (i = 0; i < NR_EVENT_CHANNELS; i++) {
++		int ret;
++		if (port_user[i] != u)
++			continue;
++
++		port_user[i] = NULL;
++		mask_evtchn(i);
++		rebind_evtchn_to_cpu(i, 0);
++
++		close.port = i;
++		ret = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
++		BUG_ON(ret);
++	}
++
++	spin_unlock_irq(&port_user_lock);
++
++	kfree(u);
++
++	return 0;
++}
++
++static const struct file_operations evtchn_fops = {
++	.owner   = THIS_MODULE,
++	.read    = evtchn_read,
++	.write   = evtchn_write,
++	.unlocked_ioctl = evtchn_ioctl,
++	.poll    = evtchn_poll,
++	.fasync  = evtchn_fasync,
++	.open    = evtchn_open,
++	.release = evtchn_release,
++};
++
++static struct miscdevice evtchn_miscdev = {
++	.minor        = MISC_DYNAMIC_MINOR,
++	.name         = "evtchn",
++	.fops         = &evtchn_fops,
++};
++
++static int __cpuinit evtchn_cpu_notify(struct notifier_block *nfb,
++			unsigned long action, void *hcpu)
++{
++	int hotcpu = (unsigned long)hcpu;
++	cpumask_t map = cpu_online_map;
++	int i, j, newcpu;
++	struct per_user_data *u;
++
++	switch (action) {
++	case CPU_DOWN_PREPARE:
++		cpu_clear(hotcpu, map);
++		spin_lock_irq(&port_user_lock);
++		for (i = 0; i < NR_EVENT_CHANNELS; i++) {
++			u = port_user[i];
++			if ((u == NULL) || (u->bind_cpu != hotcpu))
++				continue;
++			newcpu = next_bind_cpu(map);
++			for (j = i; j < NR_EVENT_CHANNELS; j++)
++				if (port_user[j] == u)
++					rebind_evtchn_to_cpu(j, newcpu);
++			u->bind_cpu = newcpu;
++		}
++		spin_unlock_irq(&port_user_lock);
++		break;
++	default:
++		return NOTIFY_DONE;
++	}
++	return NOTIFY_OK;
++}
++
++static struct notifier_block __cpuinitdata evtchn_cpu_nfb = {
++	.notifier_call = evtchn_cpu_notify
++};
++
++static int __init evtchn_init(void)
++{
++	int err;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	spin_lock_init(&port_user_lock);
++	memset(port_user, 0, sizeof(port_user));
++
++	/* Create '/dev/misc/evtchn'. */
++	err = misc_register(&evtchn_miscdev);
++	if (err != 0) {
++		printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
++		return err;
++	}
++
++	register_cpu_notifier(&evtchn_cpu_nfb);
++
++	printk("Event-channel device installed.\n");
++
++	return 0;
++}
++
++static void __exit evtchn_cleanup(void)
++{
++	misc_deregister(&evtchn_miscdev);
++	unregister_cpu_notifier(&evtchn_cpu_nfb);
++}
++
++module_init(evtchn_init);
++module_exit(evtchn_cleanup);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/fbfront/Makefile	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_XEN_FRAMEBUFFER)	:= xenfb.o
++obj-$(CONFIG_XEN_KEYBOARD)	+= xenkbd.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-12-04 08:45:56.000000000 +0100
+@@ -0,0 +1,888 @@
++/*
++ * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device
++ *
++ * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
++ *
++ *  Based on linux/drivers/video/q40fb.c
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License. See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables when they become capable of dealing with the
++ * frame buffer.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/fb.h>
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
++#include <linux/mutex.h>
++#include <asm/hypervisor.h>
++#include <xen/evtchn.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/protocols.h>
++#include <xen/xenbus.h>
++#include <linux/kthread.h>
++
++struct xenfb_mapping
++{
++	struct list_head	link;
++	struct vm_area_struct	*vma;
++	atomic_t		map_refs;
++	int			faults;
++	struct xenfb_info	*info;
++};
++
++struct xenfb_info
++{
++	struct task_struct	*kthread;
++	wait_queue_head_t	wq;
++
++	unsigned char		*fb;
++	struct fb_info		*fb_info;
++	struct timer_list	refresh;
++	int			dirty;
++	int			x1, y1, x2, y2;	/* dirty rectangle,
++						   protected by dirty_lock */
++	spinlock_t		dirty_lock;
++	struct mutex		mm_lock;
++	int			nr_pages;
++	struct page		**pages;
++	struct list_head	mappings; /* protected by mm_lock */
++
++	int			irq;
++	struct xenfb_page	*page;
++	unsigned long 		*mfns;
++	int			feature_resize; /* Backend has resize feature */
++	struct xenfb_resize	resize;
++	int			resize_dpy;
++	spinlock_t		resize_lock;
++
++	struct xenbus_device	*xbdev;
++};
++
++/*
++ * There are three locks:
++ *    spinlock resize_lock protecting resize_dpy and resize
++ *    spinlock dirty_lock protecting the dirty rectangle
++ *    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
++ * mappings.  We need to prove that our locking maintains this
++ * invariant.
++ *
++ * There are several kinds of critical regions:
++ *
++ * 1. Holding only dirty_lock: xenfb_refresh().  May run in
++ *    interrupts.  Extends the dirty rectangle.  Trivially preserves
++ *    invariant.
++ *
++ * 2. Holding only mm_lock: xenfb_mmap() and xenfb_vm_close().  Touch
++ *    only mappings.  The former creates unfaulted pages.  Preserves
++ *    invariant.  The latter removes pages.  Preserves invariant.
++ *
++ * 3. Holding both locks: xenfb_vm_nopage().  Extends the dirty
++ *    rectangle and updates mappings consistently.  Preserves
++ *    invariant.
++ *
++ * 4. The ugliest one: xenfb_update_screen().  Clear the dirty
++ *    rectangle and update mappings consistently.
++ *
++ *    We can't simply hold both locks, because zap_page_range() cannot
++ *    be called with a spinlock held.
++ *
++ *    Therefore, we first clear the dirty rectangle with both locks
++ *    held.  Then we unlock dirty_lock and update the mappings.
++ *    Critical regions that hold only dirty_lock may interfere with
++ *    that.  This can only be region 1: xenfb_refresh().  But that
++ *    just extends the dirty rectangle, which can't harm the
++ *    invariant.
++ *
++ * But FIXME: the invariant is too weak.  It misses that the fault
++ * record in mappings must be consistent with the mapping of pages in
++ * the associated address space!  do_no_page() updates the PTE after
++ * xenfb_vm_nopage() returns, i.e. outside the critical region.  This
++ * allows the following race:
++ *
++ * X writes to some address in the Xen frame buffer
++ * Fault - call do_no_page()
++ *     call xenfb_vm_nopage()
++ *         grab mm_lock
++ *         map->faults++;
++ *         release mm_lock
++ *     return back to do_no_page()
++ * (preempted, or SMP)
++ * Xen worker thread runs.
++ *      grab mm_lock
++ *      look at mappings
++ *          find this mapping, zaps its pages (but page not in pte yet)
++ *          clear map->faults
++ *      releases mm_lock
++ * (back to X process)
++ *     put page in X's pte
++ *
++ * 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 int xenfb_remove(struct xenbus_device *);
++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;
++
++	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;
++
++	/* caller ensures !xenfb_queue_full() */
++	xenfb_send_event(info, &event);
++}
++
++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)
++{
++	__u32 cons, prod;
++
++	prod = info->page->out_prod;
++	cons = info->page->out_cons;
++	return prod - cons == XENFB_OUT_RING_LEN;
++}
++
++static void xenfb_update_screen(struct xenfb_info *info)
++{
++	unsigned long flags;
++	int y1, y2, x1, x2;
++	struct xenfb_mapping *map;
++
++	if (xenfb_queue_full(info))
++		return;
++
++	mutex_lock(&info->mm_lock);
++
++	spin_lock_irqsave(&info->dirty_lock, flags);
++	if (info->dirty){
++		info->dirty = 0;
++		y1 = info->y1;
++		y2 = info->y2;
++		x1 = info->x1;
++		x2 = info->x2;
++		info->x1 = info->y1 = INT_MAX;
++		info->x2 = info->y2 = 0;
++	} else {
++		spin_unlock_irqrestore(&info->dirty_lock, flags);
++		mutex_unlock(&info->mm_lock);
++		return;
++	}
++	spin_unlock_irqrestore(&info->dirty_lock, flags);
++
++	list_for_each_entry(map, &info->mappings, link) {
++		if (!map->faults)
++			continue;
++		zap_page_range(map->vma, map->vma->vm_start,
++			       map->vma->vm_end - map->vma->vm_start, NULL);
++		map->faults = 0;
++	}
++
++	mutex_unlock(&info->mm_lock);
++
++	if (x2 < x1 || y2 < y1) {
++		printk("xenfb_update_screen bogus rect %d %d %d %d\n",
++		       x1, x2, y1, y2);
++		WARN_ON(1);
++	}
++	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);
++		xenfb_update_screen(info);
++		wait_event_interruptible(info->wq,
++			kthread_should_stop() || info->dirty);
++		try_to_freeze();
++	}
++	return 0;
++}
++
++static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
++			   unsigned blue, unsigned transp,
++			   struct fb_info *info)
++{
++	u32 v;
++
++	if (regno > info->cmap.len)
++		return 1;
++
++	red   >>= (16 - info->var.red.length);
++	green >>= (16 - info->var.green.length);
++	blue  >>= (16 - info->var.blue.length);
++
++	v = (red << info->var.red.offset) |
++	    (green << info->var.green.offset) |
++	    (blue << info->var.blue.offset);
++
++	/* FIXME is this sane?  check against xxxfb_setcolreg()!  */
++	switch (info->var.bits_per_pixel) {
++	case 16:
++	case 24:
++	case 32:
++		((u32 *)info->pseudo_palette)[regno] = v;
++		break;
++	}
++	
++	return 0;
++}
++
++static void xenfb_timer(unsigned long data)
++{
++	struct xenfb_info *info = (struct xenfb_info *)data;
++	wake_up(&info->wq);
++}
++
++static void __xenfb_refresh(struct xenfb_info *info,
++			    int x1, int y1, int w, int h)
++{
++	int y2, x2;
++
++	y2 = y1 + h;
++	x2 = x1 + w;
++
++	if (info->y1 > y1)
++		info->y1 = y1;
++	if (info->y2 < y2)
++		info->y2 = y2;
++	if (info->x1 > x1)
++		info->x1 = x1;
++	if (info->x2 < x2)
++		info->x2 = x2;
++	info->dirty = 1;
++
++	if (timer_pending(&info->refresh))
++		return;
++
++	mod_timer(&info->refresh, jiffies + HZ/xenfb_fps);
++}
++
++static void xenfb_refresh(struct xenfb_info *info,
++			  int x1, int y1, int w, int h)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&info->dirty_lock, flags);
++	__xenfb_refresh(info, x1, y1, w, h);
++	spin_unlock_irqrestore(&info->dirty_lock, flags);
++}
++
++static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
++{
++	struct xenfb_info *info = p->par;
++
++	cfb_fillrect(p, rect);
++	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
++}
++
++static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
++{
++	struct xenfb_info *info = p->par;
++
++	cfb_imageblit(p, image);
++	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
++}
++
++static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
++{
++	struct xenfb_info *info = p->par;
++
++	cfb_copyarea(p, area);
++	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
++}
++
++static void xenfb_vm_open(struct vm_area_struct *vma)
++{
++	struct xenfb_mapping *map = vma->vm_private_data;
++	atomic_inc(&map->map_refs);
++}
++
++static void xenfb_vm_close(struct vm_area_struct *vma)
++{
++	struct xenfb_mapping *map = vma->vm_private_data;
++	struct xenfb_info *info = map->info;
++
++	mutex_lock(&info->mm_lock);
++	if (atomic_dec_and_test(&map->map_refs)) {
++		list_del(&map->link);
++		kfree(map);
++	}
++	mutex_unlock(&info->mm_lock);
++}
++
++static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
++				    unsigned long vaddr, int *type)
++{
++	struct xenfb_mapping *map = vma->vm_private_data;
++	struct xenfb_info *info = map->info;
++	int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT;
++	unsigned long flags;
++	struct page *page;
++	int y1, y2;
++
++	if (pgnr >= info->nr_pages)
++		return NOPAGE_SIGBUS;
++
++	mutex_lock(&info->mm_lock);
++	spin_lock_irqsave(&info->dirty_lock, flags);
++	page = info->pages[pgnr];
++	get_page(page);
++	map->faults++;
++
++	y1 = pgnr * PAGE_SIZE / info->fb_info->fix.line_length;
++	y2 = (pgnr * PAGE_SIZE + PAGE_SIZE - 1) / info->fb_info->fix.line_length;
++	if (y2 > info->fb_info->var.yres)
++		y2 = info->fb_info->var.yres;
++	__xenfb_refresh(info, 0, y1, info->fb_info->var.xres, y2 - y1);
++	spin_unlock_irqrestore(&info->dirty_lock, flags);
++	mutex_unlock(&info->mm_lock);
++
++	if (type)
++		*type = VM_FAULT_MINOR;
++
++	return page;
++}
++
++static struct vm_operations_struct xenfb_vm_ops = {
++	.open	= xenfb_vm_open,
++	.close	= xenfb_vm_close,
++	.nopage	= xenfb_vm_nopage,
++};
++
++static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
++{
++	struct xenfb_info *info = fb_info->par;
++	struct xenfb_mapping *map;
++	int map_pages;
++
++	if (!(vma->vm_flags & VM_WRITE))
++		return -EINVAL;
++	if (!(vma->vm_flags & VM_SHARED))
++		return -EINVAL;
++	if (vma->vm_pgoff != 0)
++		return -EINVAL;
++
++	map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT;
++	if (map_pages > info->nr_pages)
++		return -EINVAL;
++
++	map = kzalloc(sizeof(*map), GFP_KERNEL);
++	if (map == NULL)
++		return -ENOMEM;
++
++	map->vma = vma;
++	map->faults = 0;
++	map->info = info;
++	atomic_set(&map->map_refs, 1);
++
++	mutex_lock(&info->mm_lock);
++	list_add(&map->link, &info->mappings);
++	mutex_unlock(&info->mm_lock);
++
++	vma->vm_ops = &xenfb_vm_ops;
++	vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
++	vma->vm_private_data = map;
++
++	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,
++	.fb_fillrect	= xenfb_fillrect,
++	.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,
++				       struct pt_regs *regs)
++{
++	/*
++	 * No in events recognized, simply ignore them all.
++	 * If you need to recognize some, see xenbkd's input_handler()
++	 * for how to do that.
++	 */
++	struct xenfb_info *info = dev_id;
++	struct xenfb_page *page = info->page;
++
++	if (page->in_cons != page->in_prod) {
++		info->page->in_cons = info->page->in_prod;
++		notify_remote_via_irq(info->irq);
++	}
++	return IRQ_HANDLED;
++}
++
++static unsigned long vmalloc_to_mfn(void *address)
++{
++	return pfn_to_mfn(vmalloc_to_pfn(address));
++}
++
++static int __devinit xenfb_probe(struct xenbus_device *dev,
++				 const struct xenbus_device_id *id)
++{
++	struct xenfb_info *info;
++	struct fb_info *fb_info;
++	int fb_size;
++	int val;
++	int ret;
++
++	info = kzalloc(sizeof(*info), GFP_KERNEL);
++	if (info == NULL) {
++		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);
++	info->refresh.function = xenfb_timer;
++	info->refresh.data = (unsigned long)info;
++	INIT_LIST_HEAD(&info->mappings);
++
++	info->fb = vmalloc(fb_size);
++	if (info->fb == NULL)
++		goto error_nomem;
++	memset(info->fb, 0, fb_size);
++
++	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
++
++	info->pages = kmalloc(sizeof(struct page *) * info->nr_pages,
++			      GFP_KERNEL);
++	if (info->pages == NULL)
++		goto error_nomem;
++
++	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
++	if (!info->mfns)
++		goto error_nomem;
++
++	/* set up shared page */
++	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++	if (!info->page)
++		goto error_nomem;
++
++	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
++				/* see fishy hackery below */
++	if (fb_info == NULL)
++		goto error_nomem;
++
++	/* FIXME fishy hackery */
++	fb_info->pseudo_palette = fb_info->par;
++	fb_info->par = info;
++	/* /FIXME */
++	fb_info->screen_base = info->fb;
++
++	fb_info->fbops = &xenfb_fb_ops;
++	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};
++	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
++
++	fb_info->var.activate = FB_ACTIVATE_NOW;
++	fb_info->var.height = -1;
++	fb_info->var.width = -1;
++	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
++
++	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
++	fb_info->fix.line_length = fb_info->var.xres * (XENFB_DEPTH / 8);
++	fb_info->fix.smem_start = 0;
++	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;
++
++	fb_info->flags = FBINFO_FLAG_DEFAULT;
++
++	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
++	if (ret < 0) {
++		framebuffer_release(fb_info);
++		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
++		goto error;
++	}
++
++	xenfb_init_shared_page(info, fb_info);
++
++	ret = register_framebuffer(fb_info);
++	if (ret) {
++		fb_dealloc_cmap(&info->fb_info->cmap);
++		framebuffer_release(fb_info);
++		xenbus_dev_fatal(dev, ret, "register_framebuffer");
++		goto error;
++	}
++	info->fb_info = fb_info;
++
++	ret = xenfb_connect_backend(dev, info);
++	if (ret < 0)
++		goto error;
++
++	return 0;
++
++ error_nomem:
++	ret = -ENOMEM;
++	xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++	xenfb_remove(dev);
++	return ret;
++}
++
++static int xenfb_resume(struct xenbus_device *dev)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++
++	xenfb_disconnect_backend(info);
++	xenfb_init_shared_page(info, info->fb_info);
++	return xenfb_connect_backend(dev, info);
++}
++
++static int xenfb_remove(struct xenbus_device *dev)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++
++	del_timer(&info->refresh);
++	if (info->kthread)
++		kthread_stop(info->kthread);
++	xenfb_disconnect_backend(info);
++	if (info->fb_info) {
++		unregister_framebuffer(info->fb_info);
++		fb_dealloc_cmap(&info->fb_info->cmap);
++		framebuffer_release(info->fb_info);
++	}
++	free_page((unsigned long)info->page);
++	vfree(info->mfns);
++	kfree(info->pages);
++	vfree(info->fb);
++	kfree(info);
++
++	return 0;
++}
++
++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);
++
++	for (i = 0; i < info->nr_pages; i++)
++		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
++
++	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;
++}
++
++static int xenfb_connect_backend(struct xenbus_device *dev,
++				 struct xenfb_info *info)
++{
++	int ret;
++	struct xenbus_transaction xbt;
++
++	ret = bind_listening_port_to_irqhandler(
++		dev->otherend_id, xenfb_event_handler, 0, "xenfb", info);
++	if (ret < 0) {
++		xenbus_dev_fatal(dev, ret,
++				 "bind_listening_port_to_irqhandler");
++		return ret;
++	}
++	info->irq = ret;
++
++ again:
++	ret = xenbus_transaction_start(&xbt);
++	if (ret) {
++		xenbus_dev_fatal(dev, ret, "starting transaction");
++		return ret;
++	}
++	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++			    virt_to_mfn(info->page));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    irq_to_evtchn_port(info->irq));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
++			    XEN_IO_PROTO_ABI_NATIVE);
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_transaction_end(xbt, 0);
++	if (ret) {
++		if (ret == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, ret, "completing transaction");
++		return ret;
++	}
++
++	xenbus_switch_state(dev, XenbusStateInitialised);
++	return 0;
++
++ error_xenbus:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, ret, "writing xenstore");
++	return ret;
++}
++
++static void xenfb_disconnect_backend(struct xenfb_info *info)
++{
++	if (info->irq >= 0)
++		unbind_from_irqhandler(info->irq, info);
++	info->irq = -1;
++}
++
++static void xenfb_backend_changed(struct xenbus_device *dev,
++				  enum xenbus_state backend_state)
++{
++	struct xenfb_info *info = dev->dev.driver_data;
++	int val;
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++	InitWait:
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateConnected:
++		/*
++		 * Work around xenbus race condition: If backend goes
++		 * through InitWait to Connected fast enough, we can
++		 * get Connected twice here.
++		 */
++		if (dev->state != XenbusStateConnected)
++			goto InitWait; /* no InitWait seen yet, fudge it */
++
++
++		if (xenbus_scanf(XBT_NIL, dev->otherend,
++					"feature-resize", "%d", &val) < 0)
++			val = 0;
++		info->feature_resize = val;
++
++		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++				 "request-update", "%d", &val) < 0)
++			val = 0;
++
++		if (val && !info->kthread) {
++			info->kthread = kthread_run(xenfb_thread, info,
++						    "xenfb thread");
++			if (IS_ERR(info->kthread)) {
++				info->kthread = NULL;
++				xenbus_dev_fatal(dev, PTR_ERR(info->kthread),
++						"xenfb_thread");
++			}
++		}
++		break;
++
++	case XenbusStateClosing:
++		// FIXME is this safe in any dev->state?
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++static const struct xenbus_device_id xenfb_ids[] = {
++	{ "vfb" },
++	{ "" }
++};
++MODULE_ALIAS("xen:vfb");
++
++static struct xenbus_driver xenfb_driver = {
++	.name = "vfb",
++	.owner = THIS_MODULE,
++	.ids = xenfb_ids,
++	.probe = xenfb_probe,
++	.remove = xenfb_remove,
++	.resume = xenfb_resume,
++	.otherend_changed = xenfb_backend_changed,
++};
++
++static int __init xenfb_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	/* Nothing to do if running in dom0. */
++	if (is_initial_xendomain())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&xenfb_driver);
++}
++
++static void __exit xenfb_cleanup(void)
++{
++	return xenbus_unregister_driver(&xenfb_driver);
++}
++
++module_init(xenfb_init);
++module_exit(xenfb_cleanup);
++
++MODULE_LICENSE("GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/fbfront/xenkbd.c	2008-04-02 12:34:02.000000000 +0200
+@@ -0,0 +1,354 @@
++/*
++ * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device
++ *
++ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
++ * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
++ *
++ *  Based on linux/drivers/input/mouse/sermouse.c
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License. See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++
++/*
++ * TODO:
++ *
++ * Switch to grant tables together with xenfb.c.
++ */
++
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <asm/hypervisor.h>
++#include <xen/evtchn.h>
++#include <xen/interface/io/fbif.h>
++#include <xen/interface/io/kbdif.h>
++#include <xen/xenbus.h>
++
++struct xenkbd_info
++{
++	struct input_dev *kbd;
++	struct input_dev *ptr;
++	struct xenkbd_page *page;
++	int irq;
++	struct xenbus_device *xbdev;
++	char phys[32];
++};
++
++static int xenkbd_remove(struct xenbus_device *);
++static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
++static void xenkbd_disconnect_backend(struct xenkbd_info *);
++
++/*
++ * Note: if you need to send out events, see xenfb_do_update() for how
++ * to do that.
++ */
++
++static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs)
++{
++	struct xenkbd_info *info = dev_id;
++	struct xenkbd_page *page = info->page;
++	__u32 cons, prod;
++
++	prod = page->in_prod;
++	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++) {
++		union xenkbd_in_event *event;
++		struct input_dev *dev;
++		event = &XENKBD_IN_RING_REF(page, cons);
++
++		dev = info->ptr;
++		switch (event->type) {
++		case XENKBD_TYPE_MOTION:
++			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;
++			if (test_bit(event->key.keycode, info->kbd->keybit))
++				dev = info->kbd;
++			if (test_bit(event->key.keycode, info->ptr->keybit))
++				dev = info->ptr;
++			if (dev)
++				input_report_key(dev, event->key.keycode,
++						 event->key.pressed);
++			else
++				printk("xenkbd: unhandled keycode 0x%x\n",
++				       event->key.keycode);
++			break;
++		case XENKBD_TYPE_POS:
++			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)
++			input_sync(dev);
++	}
++	mb();			/* ensure we got ring contents */
++	page->in_cons = cons;
++	notify_remote_via_irq(info->irq);
++
++	return IRQ_HANDLED;
++}
++
++int __devinit xenkbd_probe(struct xenbus_device *dev,
++			   const struct xenbus_device_id *id)
++{
++	int ret, i;
++	struct xenkbd_info *info;
++	struct input_dev *kbd, *ptr;
++
++	info = kzalloc(sizeof(*info), GFP_KERNEL);
++	if (!info) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
++		return -ENOMEM;
++	}
++	dev->dev.driver_data = info;
++	info->xbdev = dev;
++	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
++
++	info->page = (void *)__get_free_page(GFP_KERNEL);
++	if (!info->page)
++		goto error_nomem;
++	info->page->in_cons = info->page->in_prod = 0;
++	info->page->out_cons = info->page->out_prod = 0;
++
++	/* keyboard */
++	kbd = input_allocate_device();
++	if (!kbd)
++		goto error_nomem;
++	kbd->name = "Xen Virtual Keyboard";
++	kbd->phys = info->phys;
++	kbd->id.bustype = BUS_PCI;
++	kbd->id.vendor = 0x5853;
++	kbd->id.product = 0xffff;
++	kbd->evbit[0] = BIT(EV_KEY);
++	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
++		set_bit(i, kbd->keybit);
++	for (i = KEY_OK; i < KEY_MAX; i++)
++		set_bit(i, kbd->keybit);
++
++	ret = input_register_device(kbd);
++	if (ret) {
++		input_free_device(kbd);
++		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
++		goto error;
++	}
++	info->kbd = kbd;
++
++	/* pointing device */
++	ptr = input_allocate_device();
++	if (!ptr)
++		goto error_nomem;
++	ptr->name = "Xen Virtual Pointer";
++	ptr->phys = info->phys;
++	ptr->id.bustype = BUS_PCI;
++	ptr->id.vendor = 0x5853;
++	ptr->id.product = 0xfffe;
++	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
++	for (i = BTN_LEFT; i <= BTN_TASK; i++)
++		set_bit(i, ptr->keybit);
++	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
++	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
++	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
++
++	ret = input_register_device(ptr);
++	if (ret) {
++		input_free_device(ptr);
++		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
++		goto error;
++	}
++	info->ptr = ptr;
++
++	ret = xenkbd_connect_backend(dev, info);
++	if (ret < 0)
++		goto error;
++
++	return 0;
++
++ error_nomem:
++	ret = -ENOMEM;
++	xenbus_dev_fatal(dev, ret, "allocating device memory");
++ error:
++	xenkbd_remove(dev);
++	return ret;
++}
++
++static int xenkbd_resume(struct xenbus_device *dev)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++
++	xenkbd_disconnect_backend(info);
++	info->page->in_cons = info->page->in_prod = 0;
++	info->page->out_cons = info->page->out_prod = 0;
++	return xenkbd_connect_backend(dev, info);
++}
++
++static int xenkbd_remove(struct xenbus_device *dev)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++
++	xenkbd_disconnect_backend(info);
++	input_unregister_device(info->kbd);
++	input_unregister_device(info->ptr);
++	free_page((unsigned long)info->page);
++	kfree(info);
++	return 0;
++}
++
++static int xenkbd_connect_backend(struct xenbus_device *dev,
++				  struct xenkbd_info *info)
++{
++	int ret;
++	struct xenbus_transaction xbt;
++
++	ret = bind_listening_port_to_irqhandler(
++		dev->otherend_id, input_handler, 0, "xenkbd", info);
++	if (ret < 0) {
++		xenbus_dev_fatal(dev, ret,
++				 "bind_listening_port_to_irqhandler");
++		return ret;
++	}
++	info->irq = ret;
++
++ again:
++	ret = xenbus_transaction_start(&xbt);
++	if (ret) {
++		xenbus_dev_fatal(dev, ret, "starting transaction");
++		return ret;
++	}
++	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
++			    virt_to_mfn(info->page));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    irq_to_evtchn_port(info->irq));
++	if (ret)
++		goto error_xenbus;
++	ret = xenbus_transaction_end(xbt, 0);
++	if (ret) {
++		if (ret == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, ret, "completing transaction");
++		return ret;
++	}
++
++	xenbus_switch_state(dev, XenbusStateInitialised);
++	return 0;
++
++ error_xenbus:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, ret, "writing xenstore");
++	return ret;
++}
++
++static void xenkbd_disconnect_backend(struct xenkbd_info *info)
++{
++	if (info->irq >= 0)
++		unbind_from_irqhandler(info->irq, info);
++	info->irq = -1;
++}
++
++static void xenkbd_backend_changed(struct xenbus_device *dev,
++				   enum xenbus_state backend_state)
++{
++	struct xenkbd_info *info = dev->dev.driver_data;
++	int ret, val;
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++	InitWait:
++		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
++				   "feature-abs-pointer", "%d", &val);
++		if (ret < 0)
++			val = 0;
++		if (val) {
++			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
++					    "request-abs-pointer", "1");
++			if (ret)
++				; /* FIXME */
++		}
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateConnected:
++		/*
++		 * Work around xenbus race condition: If backend goes
++		 * through InitWait to Connected fast enough, we can
++		 * get Connected twice here.
++		 */
++		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:
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++static const struct xenbus_device_id xenkbd_ids[] = {
++	{ "vkbd" },
++	{ "" }
++};
++MODULE_ALIAS("xen:vkbd");
++
++static struct xenbus_driver xenkbd_driver = {
++	.name = "vkbd",
++	.owner = THIS_MODULE,
++	.ids = xenkbd_ids,
++	.probe = xenkbd_probe,
++	.remove = xenkbd_remove,
++	.resume = xenkbd_resume,
++	.otherend_changed = xenkbd_backend_changed,
++};
++
++static int __init xenkbd_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	/* Nothing to do if running in dom0. */
++	if (is_initial_xendomain())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&xenkbd_driver);
++}
++
++static void __exit xenkbd_cleanup(void)
++{
++	return xenbus_unregister_driver(&xenkbd_driver);
++}
++
++module_init(xenkbd_init);
++module_exit(xenkbd_cleanup);
++
++MODULE_LICENSE("GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/gntdev/Makefile	2008-01-07 13:19:18.000000000 +0100
+@@ -0,0 +1 @@
++obj-$(CONFIG_XEN_GRANT_DEV) := gntdev.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/gntdev/gntdev.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,1083 @@
++/******************************************************************************
++ * gntdev.c
++ * 
++ * Device for accessing (in user-space) pages that have been granted by other
++ * domains.
++ *
++ * Copyright (c) 2006-2007, D G Murray.
++ * 
++ * 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 <asm/atomic.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <xen/gnttab.h>
++#include <asm/hypervisor.h>
++#include <xen/balloon.h>
++#include <xen/evtchn.h>
++#include <xen/driver_util.h>
++
++#include <linux/types.h>
++#include <xen/public/gntdev.h>
++
++
++#define DRIVER_AUTHOR "Derek G. Murray <Derek.Murray@cl.cam.ac.uk>"
++#define DRIVER_DESC   "User-space granted page access driver"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++
++#define MAX_GRANTS_LIMIT   1024
++#define DEFAULT_MAX_GRANTS 128
++
++/* A slot can be in one of three states:
++ *
++ * 0. GNTDEV_SLOT_INVALID:
++ *    This slot is not associated with a grant reference, and is therefore free
++ *    to be overwritten by a new grant reference.
++ *
++ * 1. GNTDEV_SLOT_NOT_YET_MAPPED:
++ *    This slot is associated with a grant reference (via the 
++ *    IOCTL_GNTDEV_MAP_GRANT_REF ioctl), but it has not yet been mmap()-ed.
++ *
++ * 2. GNTDEV_SLOT_MAPPED:
++ *    This slot is associated with a grant reference, and has been mmap()-ed.
++ */
++typedef enum gntdev_slot_state {
++	GNTDEV_SLOT_INVALID = 0,
++	GNTDEV_SLOT_NOT_YET_MAPPED,
++	GNTDEV_SLOT_MAPPED
++} gntdev_slot_state_t;
++
++#define GNTDEV_INVALID_HANDLE    -1
++#define GNTDEV_FREE_LIST_INVALID -1
++/* Each opened instance of gntdev is associated with a list of grants,
++ * represented by an array of elements of the following type,
++ * gntdev_grant_info_t.
++ */
++typedef struct gntdev_grant_info {
++	gntdev_slot_state_t state;
++	union {
++		uint32_t free_list_index;
++		struct {
++			domid_t domid;
++			grant_ref_t ref;
++			grant_handle_t kernel_handle;
++			grant_handle_t user_handle;
++			uint64_t dev_bus_addr;
++		} valid;
++	} u;
++} gntdev_grant_info_t;
++
++/* Private data structure, which is stored in the file pointer for files
++ * associated with this device.
++ */
++typedef struct gntdev_file_private_data {
++  
++	/* Array of grant information. */
++	gntdev_grant_info_t *grants;
++	uint32_t grants_size;
++
++	/* Read/write semaphore used to protect the grants array. */
++	struct rw_semaphore grants_sem;
++
++	/* An array of indices of free slots in the grants array.
++	 * N.B. An entry in this list may temporarily have the value
++	 * GNTDEV_FREE_LIST_INVALID if the corresponding slot has been removed
++	 * from the list by the contiguous allocator, but the list has not yet
++	 * been compressed. However, this is not visible across invocations of
++	 * the device.
++	 */
++	int32_t *free_list;
++	
++	/* The number of free slots in the grants array. */
++	uint32_t free_list_size;
++
++	/* Read/write semaphore used to protect the free list. */
++	struct rw_semaphore free_list_sem;
++	
++	/* Index of the next slot after the most recent contiguous allocation, 
++	 * for use in a next-fit allocator.
++	 */
++	uint32_t next_fit_index;
++
++	/* Used to map grants into the kernel, before mapping them into user
++	 * space.
++	 */
++	struct page **foreign_pages;
++
++} gntdev_file_private_data_t;
++
++/* Module lifecycle operations. */
++static int __init gntdev_init(void);
++static void __exit gntdev_exit(void);
++
++module_init(gntdev_init);
++module_exit(gntdev_exit);
++
++/* File operations. */
++static int gntdev_open(struct inode *inode, struct file *flip);
++static int gntdev_release(struct inode *inode, struct file *flip);
++static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma);
++static long gntdev_ioctl(struct file *flip,
++			 unsigned int cmd, unsigned long arg);
++
++static const struct file_operations gntdev_fops = {
++	.owner = THIS_MODULE,
++	.open = gntdev_open,
++	.release = gntdev_release,
++	.mmap = gntdev_mmap,
++	.unlocked_ioctl = gntdev_ioctl
++};
++
++/* VM operations. */
++static void gntdev_vma_close(struct vm_area_struct *vma);
++static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr,
++			      pte_t *ptep, int is_fullmm);
++
++static struct vm_operations_struct gntdev_vmops = {
++	.close = gntdev_vma_close,
++	.zap_pte = gntdev_clear_pte
++};
++
++/* Global variables. */
++
++/* The driver major number, for use when unregistering the driver. */
++static int gntdev_major;
++
++#define GNTDEV_NAME "gntdev"
++
++/* Memory mapping functions
++ * ------------------------
++ *
++ * Every granted page is mapped into both kernel and user space, and the two
++ * following functions return the respective virtual addresses of these pages.
++ *
++ * When shadow paging is disabled, the granted page is mapped directly into
++ * user space; when it is enabled, it is mapped into the kernel and remapped
++ * into user space using vm_insert_page() (see gntdev_mmap(), below).
++ */
++
++/* Returns the virtual address (in user space) of the @page_index'th page
++ * in the given VM area.
++ */
++static inline unsigned long get_user_vaddr (struct vm_area_struct *vma,
++					    int page_index)
++{
++	return (unsigned long) vma->vm_start + (page_index << PAGE_SHIFT);
++}
++
++/* Returns the virtual address (in kernel space) of the @slot_index'th page
++ * mapped by the gntdev instance that owns the given private data struct.
++ */
++static inline unsigned long get_kernel_vaddr (gntdev_file_private_data_t *priv,
++					      int slot_index)
++{
++	unsigned long pfn;
++	void *kaddr;
++	pfn = page_to_pfn(priv->foreign_pages[slot_index]);
++	kaddr = pfn_to_kaddr(pfn);
++	return (unsigned long) kaddr;
++}
++
++/* Helper functions. */
++
++/* Adds information about a grant reference to the list of grants in the file's
++ * private data structure. Returns non-zero on failure. On success, sets the
++ * value of *offset to the offset that should be mmap()-ed in order to map the
++ * grant reference.
++ */
++static int add_grant_reference(struct file *flip,
++			       struct ioctl_gntdev_grant_ref *op,
++			       uint64_t *offset)
++{
++	gntdev_file_private_data_t *private_data 
++		= (gntdev_file_private_data_t *) flip->private_data;
++
++	uint32_t slot_index;
++
++	if (unlikely(private_data->free_list_size == 0)) {
++		return -ENOMEM;
++	}
++
++	slot_index = private_data->free_list[--private_data->free_list_size];
++	private_data->free_list[private_data->free_list_size]
++		= GNTDEV_FREE_LIST_INVALID;
++
++	/* Copy the grant information into file's private data. */
++	private_data->grants[slot_index].state = GNTDEV_SLOT_NOT_YET_MAPPED;
++	private_data->grants[slot_index].u.valid.domid = op->domid;
++	private_data->grants[slot_index].u.valid.ref = op->ref;
++
++	/* The offset is calculated as the index of the chosen entry in the
++	 * file's private data's array of grant information. This is then
++	 * shifted to give an offset into the virtual "file address space".
++	 */
++	*offset = slot_index << PAGE_SHIFT;
++
++	return 0;
++}
++
++/* Adds the @count grant references to the contiguous range in the slot array
++ * beginning at @first_slot. It is assumed that @first_slot was returned by a
++ * previous invocation of find_contiguous_free_range(), during the same
++ * invocation of the driver.
++ */
++static int add_grant_references(struct file *flip,
++				int count,
++				struct ioctl_gntdev_grant_ref *ops,
++				uint32_t first_slot)
++{
++	gntdev_file_private_data_t *private_data 
++		= (gntdev_file_private_data_t *) flip->private_data;
++	int i;
++	
++	for (i = 0; i < count; ++i) {
++
++		/* First, mark the slot's entry in the free list as invalid. */
++		int free_list_index = 
++			private_data->grants[first_slot+i].u.free_list_index;
++		private_data->free_list[free_list_index] = 
++			GNTDEV_FREE_LIST_INVALID;
++
++		/* Now, update the slot. */
++		private_data->grants[first_slot+i].state = 
++			GNTDEV_SLOT_NOT_YET_MAPPED;
++		private_data->grants[first_slot+i].u.valid.domid =
++			ops[i].domid;
++		private_data->grants[first_slot+i].u.valid.ref = ops[i].ref;
++	}
++
++	return 0;	
++}
++
++/* Scans through the free list for @flip, removing entries that are marked as
++ * GNTDEV_SLOT_INVALID. This will reduce the recorded size of the free list to
++ * the number of valid entries.
++ */
++static void compress_free_list(struct file *flip) 
++{
++	gntdev_file_private_data_t *private_data 
++		= (gntdev_file_private_data_t *) flip->private_data;
++	int i, j = 0, old_size, slot_index;
++	
++	old_size = private_data->free_list_size;
++	for (i = 0; i < old_size; ++i) {
++		if (private_data->free_list[i] != GNTDEV_FREE_LIST_INVALID) {
++			if (i > j) {
++				slot_index = private_data->free_list[i];
++				private_data->free_list[j] = slot_index;
++				private_data->grants[slot_index].u
++					.free_list_index = j;
++				private_data->free_list[i] 
++					= GNTDEV_FREE_LIST_INVALID;
++			}
++			++j;
++		} else {
++			--private_data->free_list_size;
++		}
++	}
++}
++
++/* Searches the grant array in the private data of @flip for a range of
++ * @num_slots contiguous slots in the GNTDEV_SLOT_INVALID state.
++ *
++ * Returns the index of the first slot if a range is found, otherwise -ENOMEM.
++ */
++static int find_contiguous_free_range(struct file *flip,
++				      uint32_t num_slots) 
++{
++	gntdev_file_private_data_t *private_data 
++		= (gntdev_file_private_data_t *) flip->private_data;
++	
++	int i;
++	int start_index = private_data->next_fit_index;
++	int range_start = 0, range_length;
++
++	if (private_data->free_list_size < num_slots) {
++		return -ENOMEM;
++	}
++
++	/* First search from the start_index to the end of the array. */
++	range_length = 0;
++	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;
++			}
++			++range_length;
++			if (range_length == num_slots) {
++				return range_start;
++			}
++		}
++	}
++	
++	/* Now search from the start of the array to the start_index. */
++	range_length = 0;
++	for (i = 0; i < start_index; ++i) {
++		if (private_data->grants[i].state == GNTDEV_SLOT_INVALID) {
++			if (range_length == 0) {
++				range_start = i;
++			}
++			++range_length;
++			if (range_length == num_slots) {
++				return range_start;
++			}
++		}
++	}
++	
++	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. */
++static int __init gntdev_init(void)
++{
++	struct class *class;
++	struct class_device *device;
++
++	if (!is_running_on_xen()) {
++		printk(KERN_ERR "You must be running Xen to use gntdev\n");
++		return -ENODEV;
++	}
++
++	gntdev_major = register_chrdev(0, GNTDEV_NAME, &gntdev_fops);
++	if (gntdev_major < 0)
++	{
++		printk(KERN_ERR "Could not register gntdev device\n");
++		return -ENOMEM;
++	}
++
++	/* Note that if the sysfs code fails, we will still initialise the
++	 * device, and output the major number so that the device can be
++	 * created manually using mknod.
++	 */
++	if ((class = get_xen_class()) == NULL) {
++		printk(KERN_ERR "Error setting up xen_class\n");
++		printk(KERN_ERR "gntdev created with major number = %d\n", 
++		       gntdev_major);
++		return 0;
++	}
++
++	device = class_device_create(class, NULL, MKDEV(gntdev_major, 0),
++				     NULL, GNTDEV_NAME);
++	if (IS_ERR(device)) {
++		printk(KERN_ERR "Error creating gntdev device in xen_class\n");
++		printk(KERN_ERR "gntdev created with major number = %d\n",
++		       gntdev_major);
++		return 0;
++	}
++
++	return 0;
++}
++
++/* Cleans up and unregisters the driver. Called when the driver is unloaded.
++ */
++static void __exit gntdev_exit(void)
++{
++	struct class *class;
++	if ((class = get_xen_class()) != NULL)
++		class_device_destroy(class, MKDEV(gntdev_major, 0));
++	unregister_chrdev(gntdev_major, GNTDEV_NAME);
++}
++
++/* Called when the device is opened. */
++static int gntdev_open(struct inode *inode, struct file *flip)
++{
++	gntdev_file_private_data_t *private_data;
++
++	try_module_get(THIS_MODULE);
++
++	/* Allocate space for the per-instance private data. */
++	private_data = kmalloc(sizeof(*private_data), GFP_KERNEL);
++	if (!private_data)
++		goto nomem_out;
++
++	/* 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);
++
++	flip->private_data = private_data;
++
++	return 0;
++
++nomem_out:
++	return -ENOMEM;
++}
++
++/* Called when the device is closed.
++ */
++static int gntdev_release(struct inode *inode, struct file *flip)
++{
++	if (flip->private_data) {
++		gntdev_file_private_data_t *private_data = 
++			(gntdev_file_private_data_t *) flip->private_data;
++		if (private_data->foreign_pages)
++			free_empty_pages_and_pagevec
++				(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);
++	return 0;
++}
++
++/* Called when an attempt is made to mmap() the device. The private data from
++ * @flip contains the list of grant references that can be mapped. The vm_pgoff
++ * field of @vma contains the index into that list that refers to the grant
++ * reference that will be mapped. Only mappings that are a multiple of
++ * PAGE_SIZE are handled.
++ */
++static int gntdev_mmap (struct file *flip, struct vm_area_struct *vma) 
++{
++	struct gnttab_map_grant_ref op;
++	unsigned long slot_index = vma->vm_pgoff;
++	unsigned long kernel_vaddr, user_vaddr;
++	uint32_t size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++	uint64_t ptep;
++	int ret, exit_ret;
++	int flags;
++	int i;
++	struct page *page;
++	gntdev_file_private_data_t *private_data = flip->private_data;
++
++	if (unlikely(!private_data)) {
++		printk(KERN_ERR "File's private data is NULL.\n");
++		return -EINVAL;
++	}
++
++	/* 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);
++		return -ENXIO;
++	}
++
++	if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
++		printk(KERN_ERR "Writable mappings must be shared.\n");
++		return -EINVAL;
++	}
++
++	/* Slots must be in the NOT_YET_MAPPED state. */
++	down_write(&private_data->grants_sem);
++	for (i = 0; i < size; ++i) {
++		if (private_data->grants[slot_index + i].state != 
++		    GNTDEV_SLOT_NOT_YET_MAPPED) {
++			printk(KERN_ERR "Slot (index = %ld) is in the wrong "
++			       "state (%d).\n", slot_index + i, 
++			       private_data->grants[slot_index + i].state);
++			up_write(&private_data->grants_sem);
++			return -EINVAL;
++		}
++	}
++
++	/* Install the hook for unmapping. */
++	vma->vm_ops = &gntdev_vmops;
++    
++	/* The VM area contains pages from another VM. */
++	vma->vm_flags |= VM_FOREIGN;
++	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 "
++		       "area.\n");
++		return -ENOMEM;
++	}
++
++	/* This flag prevents Bad PTE errors when the memory is unmapped. */
++	vma->vm_flags |= VM_RESERVED;
++
++	/* This flag prevents this VM area being copied on a fork(). A better
++	 * behaviour might be to explicitly carry out the appropriate mappings
++	 * on fork(), but I don't know if there's a hook for this.
++	 */
++	vma->vm_flags |= VM_DONTCOPY;
++
++#ifdef CONFIG_X86
++	/* This flag ensures that the page tables are not unpinned before the
++	 * VM area is unmapped. Therefore Xen still recognises the PTE as
++	 * belonging to an L1 pagetable, and the grant unmap operation will
++	 * succeed, even if the process does not exit cleanly.
++	 */
++	vma->vm_mm->context.has_foreign_mappings = 1;
++#endif
++
++    exit_ret = -ENOMEM;
++	for (i = 0; i < size; ++i) {
++
++		flags = GNTMAP_host_map;
++		if (!(vma->vm_flags & VM_WRITE))
++			flags |= GNTMAP_readonly;
++
++		kernel_vaddr = get_kernel_vaddr(private_data, slot_index + i);
++		user_vaddr = get_user_vaddr(vma, i);
++		page = private_data->foreign_pages[slot_index + i];
++
++		gnttab_set_map_op(&op, kernel_vaddr, flags,   
++				  private_data->grants[slot_index+i]
++				  .u.valid.ref, 
++				  private_data->grants[slot_index+i]
++				  .u.valid.domid);
++
++		/* Carry out the mapping of the grant reference. */
++		ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, 
++						&op, 1);
++		BUG_ON(ret);
++		if (op.status) {
++            if(op.status != GNTST_eagain)
++				printk(KERN_ERR "Error mapping the grant reference "
++				       "into the kernel (%d). domid = %d; ref = %d\n",
++				       op.status,
++				       private_data->grants[slot_index+i]
++				       .u.valid.domid,
++				       private_data->grants[slot_index+i]
++				       .u.valid.ref);
++            else 
++                /* Propagate eagain instead of trying to fix it up */
++                exit_ret = -EAGAIN;
++			goto undo_map_out;
++		}
++
++		/* Store a reference to the page that will be mapped into user
++		 * space.
++		 */
++		((struct page **) vma->vm_private_data)[i] = page;
++
++		/* Mark mapped page as reserved. */
++		SetPageReserved(page);
++
++		/* Record the grant handle, for use in the unmap operation. */
++		private_data->grants[slot_index+i].u.valid.kernel_handle = 
++			op.handle;
++		private_data->grants[slot_index+i].u.valid.dev_bus_addr = 
++			op.dev_bus_addr;
++		
++		private_data->grants[slot_index+i].state = GNTDEV_SLOT_MAPPED;
++		private_data->grants[slot_index+i].u.valid.user_handle =
++			GNTDEV_INVALID_HANDLE;
++
++		/* Now perform the mapping to user space. */
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++
++			/* NOT USING SHADOW PAGE TABLES. */
++			/* In this case, we map the grant(s) straight into user
++			 * space.
++			 */
++
++			/* Get the machine address of the PTE for the user 
++			 *  page.
++			 */
++			if ((ret = create_lookup_pte_addr(vma->vm_mm, 
++							  vma->vm_start 
++							  + (i << PAGE_SHIFT), 
++							  &ptep)))
++			{
++				printk(KERN_ERR "Error obtaining PTE pointer "
++				       "(%d).\n", ret);
++				goto undo_map_out;
++			}
++			
++			/* Configure the map operation. */
++		
++			/* The reference is to be used by host CPUs. */
++			flags = GNTMAP_host_map;
++			
++			/* Specifies a user space mapping. */
++			flags |= GNTMAP_application_map;
++			
++			/* The map request contains the machine address of the
++			 * PTE to update.
++			 */
++			flags |= GNTMAP_contains_pte;
++			
++			if (!(vma->vm_flags & VM_WRITE))
++				flags |= GNTMAP_readonly;
++
++			gnttab_set_map_op(&op, ptep, flags, 
++					  private_data->grants[slot_index+i]
++					  .u.valid.ref, 
++					  private_data->grants[slot_index+i]
++					  .u.valid.domid);
++
++			/* Carry out the mapping of the grant reference. */
++			ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++							&op, 1);
++			BUG_ON(ret);
++			if (op.status) {
++				printk(KERN_ERR "Error mapping the grant "
++				       "reference into user space (%d). domid "
++				       "= %d; ref = %d\n", op.status,
++				       private_data->grants[slot_index+i].u
++				       .valid.domid,
++				       private_data->grants[slot_index+i].u
++				       .valid.ref);
++                /* This should never happen after we've mapped into 
++                 * the kernel space. */
++                BUG_ON(op.status == GNTST_eagain);
++				goto undo_map_out;
++			}
++			
++			/* Record the grant handle, for use in the unmap 
++			 * operation. 
++			 */
++			private_data->grants[slot_index+i].u.
++				valid.user_handle = op.handle;
++
++			/* Update p2m structure with the new mapping. */
++			set_phys_to_machine(__pa(kernel_vaddr) >> PAGE_SHIFT,
++					    FOREIGN_FRAME(private_data->
++							  grants[slot_index+i]
++							  .u.valid.dev_bus_addr
++							  >> PAGE_SHIFT));
++		} else {
++			/* USING SHADOW PAGE TABLES. */
++			/* In this case, we simply insert the page into the VM
++			 * area. */
++			ret = vm_insert_page(vma, user_vaddr, page);
++		}
++
++	}
++    exit_ret = 0;
++
++	up_write(&private_data->grants_sem);
++	return exit_ret;
++
++undo_map_out:
++	/* If we have a mapping failure, the unmapping will be taken care of
++	 * by do_mmap_pgoff(), which will eventually call gntdev_clear_pte().
++	 * All we need to do here is free the vma_private_data.
++	 */
++	kfree(vma->vm_private_data);
++
++	/* THIS IS VERY UNPLEASANT: do_mmap_pgoff() will set the vma->vm_file
++	 * to NULL on failure. However, we need this in gntdev_clear_pte() to
++	 * unmap the grants. Therefore, we smuggle a reference to the file's
++	 * private data in the VM area's private data pointer.
++	 */
++	vma->vm_private_data = private_data;
++	
++	up_write(&private_data->grants_sem);
++
++	return exit_ret;
++}
++
++static pte_t gntdev_clear_pte(struct vm_area_struct *vma, unsigned long addr,
++			      pte_t *ptep, int is_fullmm)
++{
++	int slot_index, ret;
++	pte_t copy;
++	struct gnttab_unmap_grant_ref op;
++	gntdev_file_private_data_t *private_data;
++
++	/* THIS IS VERY UNPLEASANT: do_mmap_pgoff() will set the vma->vm_file
++	 * to NULL on failure. However, we need this in gntdev_clear_pte() to
++	 * unmap the grants. Therefore, we smuggle a reference to the file's
++	 * private data in the VM area's private data pointer.
++	 */
++	if (vma->vm_file) {
++		private_data = (gntdev_file_private_data_t *)
++			vma->vm_file->private_data;
++	} else if (vma->vm_private_data) {
++		private_data = (gntdev_file_private_data_t *)
++			vma->vm_private_data;
++	} else {
++		private_data = NULL; /* gcc warning */
++		BUG();
++	}
++
++	/* Copy the existing value of the PTE for returning. */
++	copy = *ptep;
++
++	/* Calculate the grant relating to this PTE. */
++	slot_index = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
++
++	/* Only unmap grants if the slot has been mapped. This could be being
++	 * called from a failing mmap().
++	 */
++	if (private_data->grants[slot_index].state == GNTDEV_SLOT_MAPPED) {
++
++		/* First, we clear the user space mapping, if it has been made.
++		 */
++		if (private_data->grants[slot_index].u.valid.user_handle !=
++		    GNTDEV_INVALID_HANDLE && 
++		    !xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* NOT USING SHADOW PAGE TABLES. */
++			gnttab_set_unmap_op(&op, ptep_to_machine(ptep), 
++					    GNTMAP_contains_pte,
++					    private_data->grants[slot_index]
++					    .u.valid.user_handle);
++			ret = HYPERVISOR_grant_table_op(
++				GNTTABOP_unmap_grant_ref, &op, 1);
++			BUG_ON(ret);
++			if (op.status)
++				printk("User unmap grant status = %d\n", 
++				       op.status);
++		} else {
++			/* USING SHADOW PAGE TABLES. */
++			pte_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++		}
++
++		/* Finally, we unmap the grant from kernel space. */
++		gnttab_set_unmap_op(&op, 
++				    get_kernel_vaddr(private_data, slot_index),
++				    GNTMAP_host_map, 
++				    private_data->grants[slot_index].u.valid
++				    .kernel_handle);
++		ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 
++						&op, 1);
++		BUG_ON(ret);
++		if (op.status)
++			printk("Kernel unmap grant status = %d\n", op.status);
++
++
++		/* Return slot to the not-yet-mapped state, so that it may be
++		 * mapped again, or removed by a subsequent ioctl.
++		 */
++		private_data->grants[slot_index].state = 
++			GNTDEV_SLOT_NOT_YET_MAPPED;
++
++		/* Invalidate the physical to machine mapping for this page. */
++		set_phys_to_machine(
++			page_to_pfn(private_data->foreign_pages[slot_index]),
++			INVALID_P2M_ENTRY);
++
++	} else {
++		pte_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++	}
++
++	return copy;
++}
++
++/* "Destructor" for a VM area.
++ */
++static void gntdev_vma_close(struct vm_area_struct *vma) {
++	if (vma->vm_private_data) {
++		kfree(vma->vm_private_data);
++	}
++}
++
++/* Called when an ioctl is made on the device.
++ */
++static long gntdev_ioctl(struct file *flip,
++			 unsigned int cmd, unsigned long arg)
++{
++	int rc = 0;
++	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:
++	{
++		struct ioctl_gntdev_map_grant_ref op;
++		down_write(&private_data->grants_sem);
++		down_write(&private_data->free_list_sem);
++
++		if ((rc = copy_from_user(&op, (void __user *) arg, 
++					 sizeof(op)))) {
++			rc = -EFAULT;
++			goto map_out;
++		}
++		if (unlikely(op.count <= 0)) {
++			rc = -EINVAL;
++			goto map_out;
++		}
++
++		if (op.count == 1) {
++			if ((rc = add_grant_reference(flip, &op.refs[0],
++						      &op.index)) < 0) {
++				printk(KERN_ERR "Adding grant reference "
++				       "failed (%d).\n", rc);
++				goto map_out;
++			}
++		} else {
++			struct ioctl_gntdev_grant_ref *refs, *u;
++			refs = kmalloc(op.count * sizeof(*refs), GFP_KERNEL);
++			if (!refs) {
++				rc = -ENOMEM;
++				goto map_out;
++			}
++			u = ((struct ioctl_gntdev_map_grant_ref *)arg)->refs;
++			if ((rc = copy_from_user(refs,
++						 (void __user *)u,
++						 sizeof(*refs) * op.count))) {
++				printk(KERN_ERR "Copying refs from user failed"
++				       " (%d).\n", rc);
++				rc = -EINVAL;
++				goto map_out;
++			}
++			if ((rc = find_contiguous_free_range(flip, op.count))
++			    < 0) {
++				printk(KERN_ERR "Finding contiguous range "
++				       "failed (%d).\n", rc);
++				kfree(refs);
++				goto map_out;
++			}
++			op.index = rc << PAGE_SHIFT;
++			if ((rc = add_grant_references(flip, op.count,
++						       refs, rc))) {
++				printk(KERN_ERR "Adding grant references "
++				       "failed (%d).\n", rc);
++				kfree(refs);
++				goto map_out;
++			}
++			compress_free_list(flip);
++			kfree(refs);
++		}
++		if ((rc = copy_to_user((void __user *) arg, 
++				       &op, 
++				       sizeof(op)))) {
++			printk(KERN_ERR "Copying result back to user failed "
++			       "(%d)\n", rc);
++			rc = -EFAULT;
++			goto map_out;
++		}
++	map_out:
++		up_write(&private_data->grants_sem);
++		up_write(&private_data->free_list_sem);
++		return rc;
++	}
++	case IOCTL_GNTDEV_UNMAP_GRANT_REF:
++	{
++		struct ioctl_gntdev_unmap_grant_ref op;
++		int i, start_index;
++
++		down_write(&private_data->grants_sem);
++		down_write(&private_data->free_list_sem);
++
++		if ((rc = copy_from_user(&op, 
++					 (void __user *) arg, 
++					 sizeof(op)))) {
++			rc = -EFAULT;
++			goto unmap_out;
++		}
++
++		start_index = op.index >> PAGE_SHIFT;
++
++		/* First, check that all pages are in the NOT_YET_MAPPED
++		 * state.
++		 */
++		for (i = 0; i < op.count; ++i) {
++			if (unlikely
++			    (private_data->grants[start_index + i].state
++			     != GNTDEV_SLOT_NOT_YET_MAPPED)) {
++				if (private_data->grants[start_index + i].state
++				    == GNTDEV_SLOT_INVALID) {
++					printk(KERN_ERR
++					       "Tried to remove an invalid "
++					       "grant at offset 0x%x.",
++					       (start_index + i) 
++					       << PAGE_SHIFT);
++					rc = -EINVAL;
++				} else {
++					printk(KERN_ERR
++					       "Tried to remove a grant which "
++					       "is currently mmap()-ed at "
++					       "offset 0x%x.",
++					       (start_index + i) 
++					       << PAGE_SHIFT);
++					rc = -EBUSY;
++				}
++				goto unmap_out;
++			}
++		}
++
++		/* Unmap pages and add them to the free list.
++		 */
++		for (i = 0; i < op.count; ++i) {
++			private_data->grants[start_index+i].state = 
++				GNTDEV_SLOT_INVALID;
++			private_data->grants[start_index+i].u.free_list_index =
++				private_data->free_list_size;
++			private_data->free_list[private_data->free_list_size] =
++				start_index + i;
++			++private_data->free_list_size;
++		}
++
++	unmap_out:
++		up_write(&private_data->grants_sem);
++		up_write(&private_data->free_list_sem);
++		return rc;
++	}
++	case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR:
++	{
++		struct ioctl_gntdev_get_offset_for_vaddr op;
++		struct vm_area_struct *vma;
++		unsigned long vaddr;
++
++		if ((rc = copy_from_user(&op, 
++					 (void __user *) arg, 
++					 sizeof(op)))) {
++			rc = -EFAULT;
++			goto get_offset_out;
++		}
++		vaddr = (unsigned long)op.vaddr;
++
++		down_read(&current->mm->mmap_sem);		
++		vma = find_vma(current->mm, vaddr);
++		if (vma == NULL) {
++			rc = -EFAULT;
++			goto get_offset_unlock_out;
++		}
++		if ((!vma->vm_ops) || (vma->vm_ops != &gntdev_vmops)) {
++			printk(KERN_ERR "The vaddr specified does not belong "
++			       "to a gntdev instance: %#lx\n", vaddr);
++			rc = -EFAULT;
++			goto get_offset_unlock_out;
++		}
++		if (vma->vm_start != vaddr) {
++			printk(KERN_ERR "The vaddr specified in an "
++			       "IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR must be at "
++			       "the start of the VM area. vma->vm_start = "
++			       "%#lx; vaddr = %#lx\n",
++			       vma->vm_start, vaddr);
++			rc = -EFAULT;
++			goto get_offset_unlock_out;
++		}
++		op.offset = vma->vm_pgoff << PAGE_SHIFT;
++		op.count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++		up_read(&current->mm->mmap_sem);
++		if ((rc = copy_to_user((void __user *) arg, 
++				       &op, 
++				       sizeof(op)))) {
++			rc = -EFAULT;
++			goto get_offset_out;
++		}
++		goto get_offset_out;
++	get_offset_unlock_out:
++		up_read(&current->mm->mmap_sem);
++	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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/Makefile	2007-07-12 08:54:23.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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/accel.c	2008-01-07 13:19:18.000000000 +0100
+@@ -0,0 +1,269 @@
++/******************************************************************************
++ * drivers/xen/netback/accel.c
++ *
++ * Interface between backend virtual network device and accelerated plugin. 
++ * 
++ * 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.
++ */
++
++#include <linux/list.h>
++#include <asm/atomic.h>
++#include <xen/xenbus.h>
++#include <linux/mutex.h>
++
++#include "common.h"
++
++#if 0
++#undef DPRINTK
++#define DPRINTK(fmt, args...)						\
++	printk("netback/accel (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
++#endif
++
++/* 
++ * A list of available netback accelerator plugin modules (each list
++ * entry is of type struct netback_accelerator) 
++ */ 
++static struct list_head accelerators_list;
++/* Lock used to protect access to accelerators_list */
++DEFINE_MUTEX(accelerators_mutex);
++
++/* 
++ * Compare a backend to an accelerator, and decide if they are
++ * compatible (i.e. if the accelerator should be used by the
++ * backend) 
++ */
++static int match_accelerator(struct xenbus_device *xendev,
++			     struct backend_info *be, 
++			     struct netback_accelerator *accelerator)
++{
++	int rc = 0;
++	char *eth_name = xenbus_read(XBT_NIL, xendev->nodename, "accel", NULL);
++	
++	if (IS_ERR(eth_name)) {
++		/* Probably means not present */
++		DPRINTK("%s: no match due to xenbus_read accel error %d\n", 
++			__FUNCTION__, PTR_ERR(eth_name));
++		return 0;
++	} else {
++		if (!strcmp(eth_name, accelerator->eth_name))
++			rc = 1;
++		kfree(eth_name);
++		return rc;
++	}
++}
++
++
++static void do_probe(struct backend_info *be, 
++		     struct netback_accelerator *accelerator,
++		     struct xenbus_device *xendev) 
++{
++	be->accelerator = accelerator;
++	atomic_inc(&be->accelerator->use_count);
++	if (be->accelerator->hooks->probe(xendev) != 0) {
++		atomic_dec(&be->accelerator->use_count);
++		module_put(be->accelerator->hooks->owner);
++		be->accelerator = NULL;
++	}
++}
++
++
++/*
++ * Notify suitable backends that a new accelerator is available and
++ * connected.  This will also notify the accelerator plugin module
++ * that it is being used for a device through the probe hook.
++ */
++static int netback_accelerator_probe_backend(struct device *dev, void *arg)
++{
++	struct netback_accelerator *accelerator = 
++		(struct netback_accelerator *)arg;
++	struct xenbus_device *xendev = to_xenbus_device(dev);
++
++	if (!strcmp("vif", xendev->devicetype)) {
++		struct backend_info *be = xendev->dev.driver_data;
++
++		if (match_accelerator(xendev, be, accelerator) &&
++		    try_module_get(accelerator->hooks->owner)) {
++			do_probe(be, accelerator, xendev);
++		}
++	}
++	return 0;
++}
++
++
++/*
++ * Notify suitable backends that an accelerator is unavailable.
++ */
++static int netback_accelerator_remove_backend(struct device *dev, void *arg)
++{
++	struct xenbus_device *xendev = to_xenbus_device(dev);
++	struct netback_accelerator *accelerator = 
++		(struct netback_accelerator *)arg;
++	
++	if (!strcmp("vif", xendev->devicetype)) {
++		struct backend_info *be = xendev->dev.driver_data;
++
++		if (be->accelerator == accelerator) {
++			be->accelerator->hooks->remove(xendev);
++			atomic_dec(&be->accelerator->use_count);
++			module_put(be->accelerator->hooks->owner);
++			be->accelerator = NULL;
++		}
++	}
++	return 0;
++}
++
++
++
++/*
++ * Entry point for an netback accelerator plugin module.  Called to
++ * advertise its presence, and connect to any suitable backends.
++ */
++int netback_connect_accelerator(unsigned version, int id, const char *eth_name, 
++				struct netback_accel_hooks *hooks)
++{
++	struct netback_accelerator *new_accelerator;
++	unsigned eth_name_len;
++
++	if (version != NETBACK_ACCEL_VERSION) {
++		if (version > NETBACK_ACCEL_VERSION) {
++			/* Caller has higher version number, leave it
++			   up to them to decide whether to continue.
++			   They can recall with a lower number if
++			   they're happy to be compatible with us */
++			return NETBACK_ACCEL_VERSION;
++		} else {
++			/* We have a more recent version than caller.
++			   Currently reject, but may in future be able
++			   to be backwardly compatible */
++			return -EPROTO;
++		}
++	}
++
++	new_accelerator = 
++		kmalloc(sizeof(struct netback_accelerator), GFP_KERNEL);
++	if (!new_accelerator) {
++		DPRINTK("%s: failed to allocate memory for accelerator\n",
++			__FUNCTION__);
++		return -ENOMEM;
++	}
++
++	new_accelerator->id = id;
++	
++	eth_name_len = strlen(eth_name)+1;
++	new_accelerator->eth_name = kmalloc(eth_name_len, GFP_KERNEL);
++	if (!new_accelerator->eth_name) {
++		DPRINTK("%s: failed to allocate memory for eth_name string\n",
++			__FUNCTION__);
++		kfree(new_accelerator);
++		return -ENOMEM;
++	}
++	strlcpy(new_accelerator->eth_name, eth_name, eth_name_len);
++	
++	new_accelerator->hooks = hooks;
++
++	atomic_set(&new_accelerator->use_count, 0);
++	
++	mutex_lock(&accelerators_mutex);
++	list_add(&new_accelerator->link, &accelerators_list);
++	
++	/* tell existing backends about new plugin */
++	xenbus_for_each_backend(new_accelerator, 
++				netback_accelerator_probe_backend);
++
++	mutex_unlock(&accelerators_mutex);
++
++	return 0;
++
++}
++EXPORT_SYMBOL_GPL(netback_connect_accelerator);
++
++
++/* 
++ * Disconnect an accelerator plugin module that has previously been
++ * connected.
++ */
++void netback_disconnect_accelerator(int id, const char *eth_name)
++{
++	struct netback_accelerator *accelerator, *next;
++
++	mutex_lock(&accelerators_mutex);
++	list_for_each_entry_safe(accelerator, next, &accelerators_list, link) {
++		if (!strcmp(eth_name, accelerator->eth_name)) {
++			xenbus_for_each_backend
++				(accelerator, netback_accelerator_remove_backend);
++			BUG_ON(atomic_read(&accelerator->use_count) != 0);
++			list_del(&accelerator->link);				
++			kfree(accelerator->eth_name);
++			kfree(accelerator);
++			break;
++		}
++	}
++	mutex_unlock(&accelerators_mutex);
++}
++EXPORT_SYMBOL_GPL(netback_disconnect_accelerator);
++
++
++void netback_probe_accelerators(struct backend_info *be,
++				struct xenbus_device *dev)
++{
++	struct netback_accelerator *accelerator;
++
++	/* 
++	 * Check list of accelerators to see if any is suitable, and
++	 * use it if it is.
++	 */
++	mutex_lock(&accelerators_mutex);
++	list_for_each_entry(accelerator, &accelerators_list, link) { 
++		if (match_accelerator(dev, be, accelerator) &&
++		    try_module_get(accelerator->hooks->owner)) {
++			do_probe(be, accelerator, dev);
++			break;
++		}
++	}
++	mutex_unlock(&accelerators_mutex);
++}
++
++
++void netback_remove_accelerators(struct backend_info *be,
++				 struct xenbus_device *dev)
++{
++	mutex_lock(&accelerators_mutex);
++	/* Notify the accelerator (if any) of this device's removal */
++	if (be->accelerator != NULL) {
++		be->accelerator->hooks->remove(dev);
++		atomic_dec(&be->accelerator->use_count);
++		module_put(be->accelerator->hooks->owner);
++		be->accelerator = NULL;
++	}
++	mutex_unlock(&accelerators_mutex);
++}
++
++
++void netif_accel_init(void)
++{
++	INIT_LIST_HEAD(&accelerators_list);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/common.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,220 @@
++/******************************************************************************
++ * arch/xen/drivers/netif/backend/common.h
++ * 
++ * 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 __NETIF__BACKEND__COMMON_H__
++#define __NETIF__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/ip.h>
++#include <linux/in.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/wait.h>
++#include <xen/evtchn.h>
++#include <xen/interface/io/netif.h>
++#include <asm/io.h>
++#include <asm/pgalloc.h>
++#include <xen/interface/grant_table.h>
++#include <xen/gnttab.h>
++#include <xen/driver_util.h>
++#include <xen/xenbus.h>
++
++#define DPRINTK(_f, _a...)			\
++	pr_debug("(file=%s, line=%d) " _f,	\
++		 __FILE__ , __LINE__ , ## _a )
++#define IPRINTK(fmt, args...)				\
++	printk(KERN_INFO "xen_net: " fmt, ##args)
++#define WPRINTK(fmt, args...)				\
++	printk(KERN_WARNING "xen_net: " fmt, ##args)
++
++typedef struct netif_st {
++	/* Unique identifier for this interface. */
++	domid_t          domid;
++	unsigned int     handle;
++
++	u8               fe_dev_addr[6];
++
++	/* Physical parameters of the comms window. */
++	grant_handle_t   tx_shmem_handle;
++	grant_ref_t      tx_shmem_ref;
++	grant_handle_t   rx_shmem_handle;
++	grant_ref_t      rx_shmem_ref;
++	unsigned int     irq;
++
++	/* The shared rings and indexes. */
++	netif_tx_back_ring_t tx;
++	netif_rx_back_ring_t rx;
++	struct vm_struct *tx_comms_area;
++	struct vm_struct *rx_comms_area;
++
++	/* Set of features that can be turned on in dev->features. */
++	int features;
++
++	/* Internal feature information. */
++	u8 can_queue:1;	/* can queue packets for receiver? */
++	u8 copying_receiver:1;	/* copy packets to receiver?       */
++
++	/* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */
++	RING_IDX rx_req_cons_peek;
++
++	/* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
++	unsigned long   credit_bytes;
++	unsigned long   credit_usec;
++	unsigned long   remaining_credit;
++	struct timer_list credit_timeout;
++
++	/* Enforce draining of the transmit queue. */
++	struct timer_list tx_queue_timeout;
++
++	/* Statistics */
++	int nr_copied_skbs;
++
++	/* Miscellaneous private stuff. */
++	struct list_head list;  /* scheduling list */
++	atomic_t         refcnt;
++	struct net_device *dev;
++	struct net_device_stats stats;
++
++	unsigned int carrier;
++
++	wait_queue_head_t waiting_to_free;
++} netif_t;
++
++/*
++ * Implement our own carrier flag: the network stack's version causes delays
++ * when the carrier is re-enabled (in particular, dev_activate() may not
++ * immediately be called, which can cause packet loss; also the etherbridge
++ * can be rather lazy in activating its port).
++ */
++#define netback_carrier_on(netif)	((netif)->carrier = 1)
++#define netback_carrier_off(netif)	((netif)->carrier = 0)
++#define netback_carrier_ok(netif)	((netif)->carrier)
++
++enum {
++	NETBK_DONT_COPY_SKB,
++	NETBK_DELAYED_COPY_SKB,
++	NETBK_ALWAYS_COPY_SKB,
++};
++
++extern int netbk_copy_skb_mode;
++
++/* Function pointers into netback accelerator plugin modules */
++struct netback_accel_hooks {
++	struct module *owner;
++	int  (*probe)(struct xenbus_device *dev);
++	int (*remove)(struct xenbus_device *dev);
++};
++
++/* Structure to track the state of a netback accelerator plugin */
++struct netback_accelerator {
++	struct list_head link;
++	int id;
++	char *eth_name;
++	atomic_t use_count;
++	struct netback_accel_hooks *hooks;
++};
++
++struct backend_info {
++	struct xenbus_device *dev;
++	netif_t *netif;
++	enum xenbus_state frontend_state;
++
++	/* State relating to the netback accelerator */
++	void *netback_accel_priv;
++	/* The accelerator that this backend is currently using */
++	struct netback_accelerator *accelerator;
++};
++
++#define NETBACK_ACCEL_VERSION 0x00010001
++
++/* 
++ * Connect an accelerator plugin module to netback.  Returns zero on
++ * success, < 0 on error, > 0 (with highest version number supported)
++ * if version mismatch.
++ */
++extern int netback_connect_accelerator(unsigned version,
++				       int id, const char *eth_name, 
++				       struct netback_accel_hooks *hooks);
++/* Disconnect a previously connected accelerator plugin module */
++extern void netback_disconnect_accelerator(int id, const char *eth_name);
++
++
++extern
++void netback_probe_accelerators(struct backend_info *be,
++				struct xenbus_device *dev);
++extern
++void netback_remove_accelerators(struct backend_info *be,
++				 struct xenbus_device *dev);
++extern
++void netif_accel_init(void);
++
++
++#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
++#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
++
++void netif_disconnect(netif_t *netif);
++
++netif_t *netif_alloc(struct device *parent, domid_t domid, unsigned int handle);
++int netif_map(netif_t *netif, unsigned long tx_ring_ref,
++	      unsigned long rx_ring_ref, unsigned int evtchn);
++
++#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
++#define netif_put(_b)						\
++	do {							\
++		if ( atomic_dec_and_test(&(_b)->refcnt) )	\
++			wake_up(&(_b)->waiting_to_free);	\
++	} while (0)
++
++void netif_xenbus_init(void);
++
++#define netif_schedulable(netif)				\
++	(netif_running((netif)->dev) && netback_carrier_ok(netif))
++
++void netif_schedule_work(netif_t *netif);
++void netif_deschedule_work(netif_t *netif);
++
++int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
++struct net_device_stats *netif_be_get_stats(struct net_device *dev);
++irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++
++static inline int netbk_can_queue(struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++	return netif->can_queue;
++}
++
++static inline int netbk_can_sg(struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++	return netif->features & NETIF_F_SG;
++}
++
++#endif /* __NETIF__BACKEND__COMMON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,398 @@
++/******************************************************************************
++ * arch/xen/drivers/netif/backend/interface.c
++ * 
++ * Network-device interface management.
++ * 
++ * Copyright (c) 2004-2005, Keir Fraser
++ * 
++ * 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 "common.h"
++#include <linux/ethtool.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++
++/*
++ * Module parameter 'queue_length':
++ * 
++ * Enables queuing in the network stack when a client has run out of receive
++ * descriptors. Although this feature can improve receive bandwidth by avoiding
++ * packet loss, it can also result in packets sitting in the 'tx_queue' for
++ * unbounded time. This is bad if those packets hold onto foreign resources.
++ * For example, consider a packet that holds onto resources belonging to the
++ * guest for which it is queued (e.g., packet received on vif1.0, destined for
++ * vif1.1 which is not activated in the guest): in this situation the guest
++ * will never be destroyed, unless vif1.1 is taken down. To avoid this, we
++ * run a timer (tx_queue_timeout) to drain the queue when the interface is
++ * blocked.
++ */
++static unsigned long netbk_queue_length = 32;
++module_param_named(queue_length, netbk_queue_length, ulong, 0644);
++
++static void __netif_up(netif_t *netif)
++{
++	enable_irq(netif->irq);
++	netif_schedule_work(netif);
++}
++
++static void __netif_down(netif_t *netif)
++{
++	disable_irq(netif->irq);
++	netif_deschedule_work(netif);
++}
++
++static int net_open(struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++	if (netback_carrier_ok(netif)) {
++		__netif_up(netif);
++		netif_start_queue(dev);
++	}
++	return 0;
++}
++
++static int net_close(struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++	if (netback_carrier_ok(netif))
++		__netif_down(netif);
++	netif_stop_queue(dev);
++	return 0;
++}
++
++static int netbk_change_mtu(struct net_device *dev, int mtu)
++{
++	int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
++
++	if (mtu > max)
++		return -EINVAL;
++	dev->mtu = mtu;
++	return 0;
++}
++
++static int netbk_set_sg(struct net_device *dev, u32 data)
++{
++	if (data) {
++		netif_t *netif = netdev_priv(dev);
++
++		if (!(netif->features & NETIF_F_SG))
++			return -ENOSYS;
++	}
++
++	return ethtool_op_set_sg(dev, data);
++}
++
++static int netbk_set_tso(struct net_device *dev, u32 data)
++{
++	if (data) {
++		netif_t *netif = netdev_priv(dev);
++
++		if (!(netif->features & NETIF_F_TSO))
++			return -ENOSYS;
++	}
++
++	return ethtool_op_set_tso(dev, data);
++}
++
++static void netbk_get_drvinfo(struct net_device *dev,
++			      struct ethtool_drvinfo *info)
++{
++	strcpy(info->driver, "netbk");
++	strcpy(info->bus_info, dev->class_dev.dev->bus_id);
++}
++
++static const struct netif_stat {
++	char name[ETH_GSTRING_LEN];
++	u16 offset;
++} netbk_stats[] = {
++	{ "copied_skbs", offsetof(netif_t, nr_copied_skbs) },
++};
++
++static int netbk_get_stats_count(struct net_device *dev)
++{
++	return ARRAY_SIZE(netbk_stats);
++}
++
++static void netbk_get_ethtool_stats(struct net_device *dev,
++				   struct ethtool_stats *stats, u64 * data)
++{
++	void *netif = netdev_priv(dev);
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(netbk_stats); i++)
++		data[i] = *(int *)(netif + netbk_stats[i].offset);
++}
++
++static void netbk_get_strings(struct net_device *dev, u32 stringset, u8 * data)
++{
++	int i;
++
++	switch (stringset) {
++	case ETH_SS_STATS:
++		for (i = 0; i < ARRAY_SIZE(netbk_stats); i++)
++			memcpy(data + i * ETH_GSTRING_LEN,
++			       netbk_stats[i].name, ETH_GSTRING_LEN);
++		break;
++	}
++}
++
++static struct ethtool_ops network_ethtool_ops =
++{
++	.get_drvinfo = netbk_get_drvinfo,
++
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.set_tx_csum = ethtool_op_set_tx_csum,
++	.get_sg = ethtool_op_get_sg,
++	.set_sg = netbk_set_sg,
++	.get_tso = ethtool_op_get_tso,
++	.set_tso = netbk_set_tso,
++	.get_link = ethtool_op_get_link,
++
++	.get_stats_count = netbk_get_stats_count,
++	.get_ethtool_stats = netbk_get_ethtool_stats,
++	.get_strings = netbk_get_strings,
++};
++
++netif_t *netif_alloc(struct device *parent, domid_t domid, unsigned int handle)
++{
++	int err = 0;
++	struct net_device *dev;
++	netif_t *netif;
++	char name[IFNAMSIZ] = {};
++
++	snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
++	dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
++	if (dev == NULL) {
++		DPRINTK("Could not create netif: out of memory\n");
++		return ERR_PTR(-ENOMEM);
++	}
++
++	SET_NETDEV_DEV(dev, parent);
++
++	netif = netdev_priv(dev);
++	memset(netif, 0, sizeof(*netif));
++	netif->domid  = domid;
++	netif->handle = handle;
++	atomic_set(&netif->refcnt, 1);
++	init_waitqueue_head(&netif->waiting_to_free);
++	netif->dev = dev;
++
++	netback_carrier_off(netif);
++
++	netif->credit_bytes = netif->remaining_credit = ~0UL;
++	netif->credit_usec  = 0UL;
++	init_timer(&netif->credit_timeout);
++	/* Initialize 'expires' now: it's used to track the credit window. */
++	netif->credit_timeout.expires = jiffies;
++
++	init_timer(&netif->tx_queue_timeout);
++
++	dev->hard_start_xmit = netif_be_start_xmit;
++	dev->get_stats       = netif_be_get_stats;
++	dev->open            = net_open;
++	dev->stop            = net_close;
++	dev->change_mtu	     = netbk_change_mtu;
++	dev->features        = NETIF_F_IP_CSUM;
++
++	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
++
++	dev->tx_queue_len = netbk_queue_length;
++
++	/*
++	 * Initialise a dummy MAC address. We choose the numerically
++	 * largest non-broadcast address to prevent the address getting
++	 * stolen by an Ethernet bridge for STP purposes.
++	 * (FE:FF:FF:FF:FF:FF)
++	 */ 
++	memset(dev->dev_addr, 0xFF, ETH_ALEN);
++	dev->dev_addr[0] &= ~0x01;
++
++	rtnl_lock();
++	err = register_netdevice(dev);
++	rtnl_unlock();
++	if (err) {
++		DPRINTK("Could not register new net device %s: err=%d\n",
++			dev->name, err);
++		free_netdev(dev);
++		return ERR_PTR(err);
++	}
++
++	DPRINTK("Successfully created netif\n");
++	return netif;
++}
++
++static int map_frontend_pages(
++	netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
++{
++	struct gnttab_map_grant_ref op;
++
++	gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
++			  GNTMAP_host_map, tx_ring_ref, netif->domid);
++    do {
++		if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++			BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status) { 
++		DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
++		return op.status;
++	}
++
++	netif->tx_shmem_ref    = tx_ring_ref;
++	netif->tx_shmem_handle = op.handle;
++
++	gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
++			  GNTMAP_host_map, rx_ring_ref, netif->domid);
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status) {
++		struct gnttab_unmap_grant_ref unop;
++
++		gnttab_set_unmap_op(&unop,
++				    (unsigned long)netif->tx_comms_area->addr,
++				    GNTMAP_host_map, netif->tx_shmem_handle);
++		VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
++					       &unop, 1));
++		DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
++		return op.status;
++	}
++
++	netif->rx_shmem_ref    = rx_ring_ref;
++	netif->rx_shmem_handle = op.handle;
++
++	return 0;
++}
++
++static void unmap_frontend_pages(netif_t *netif)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
++			    GNTMAP_host_map, netif->tx_shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
++			    GNTMAP_host_map, netif->rx_shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++}
++
++int netif_map(netif_t *netif, unsigned long tx_ring_ref,
++	      unsigned long rx_ring_ref, unsigned int evtchn)
++{
++	int err = -ENOMEM;
++	netif_tx_sring_t *txs;
++	netif_rx_sring_t *rxs;
++
++	/* Already connected through? */
++	if (netif->irq)
++		return 0;
++
++	netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
++	if (netif->tx_comms_area == NULL)
++		return -ENOMEM;
++	netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
++	if (netif->rx_comms_area == NULL)
++		goto err_rx;
++
++	err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
++	if (err)
++		goto err_map;
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++		netif->domid, evtchn, netif_be_int, 0,
++		netif->dev->name, netif);
++	if (err < 0)
++		goto err_hypervisor;
++	netif->irq = err;
++	disable_irq(netif->irq);
++
++	txs = (netif_tx_sring_t *)netif->tx_comms_area->addr;
++	BACK_RING_INIT(&netif->tx, txs, PAGE_SIZE);
++
++	rxs = (netif_rx_sring_t *)
++		((char *)netif->rx_comms_area->addr);
++	BACK_RING_INIT(&netif->rx, rxs, PAGE_SIZE);
++
++	netif->rx_req_cons_peek = 0;
++
++	netif_get(netif);
++
++	rtnl_lock();
++	netback_carrier_on(netif);
++	if (netif_running(netif->dev))
++		__netif_up(netif);
++	rtnl_unlock();
++
++	return 0;
++err_hypervisor:
++	unmap_frontend_pages(netif);
++err_map:
++	free_vm_area(netif->rx_comms_area);
++err_rx:
++	free_vm_area(netif->tx_comms_area);
++	return err;
++}
++
++void netif_disconnect(netif_t *netif)
++{
++	if (netback_carrier_ok(netif)) {
++		rtnl_lock();
++		netback_carrier_off(netif);
++		netif_carrier_off(netif->dev); /* discard queued packets */
++		if (netif_running(netif->dev))
++			__netif_down(netif);
++		rtnl_unlock();
++		netif_put(netif);
++	}
++
++	atomic_dec(&netif->refcnt);
++	wait_event(netif->waiting_to_free, atomic_read(&netif->refcnt) == 0);
++
++	del_timer_sync(&netif->credit_timeout);
++	del_timer_sync(&netif->tx_queue_timeout);
++
++	if (netif->irq)
++		unbind_from_irqhandler(netif->irq, netif);
++	
++	unregister_netdev(netif->dev);
++
++	if (netif->tx.sring) {
++		unmap_frontend_pages(netif);
++		free_vm_area(netif->tx_comms_area);
++		free_vm_area(netif->rx_comms_area);
++	}
++
++	free_netdev(netif->dev);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/loopback.c	2007-08-06 15:10:49.000000000 +0200
+@@ -0,0 +1,324 @@
++/******************************************************************************
++ * netback/loopback.c
++ * 
++ * A two-interface loopback device to emulate a local netfront-netback
++ * connection. This ensures that local packet delivery looks identical
++ * to inter-domain delivery. Most importantly, packets delivered locally
++ * originating from other domains will get *copied* when they traverse this
++ * driver. This prevents unbounded delays in socket-buffer queues from
++ * causing the netback driver to "seize up".
++ * 
++ * This driver creates a symmetric pair of loopback interfaces with names
++ * vif0.0 and veth0. The intention is that 'vif0.0' is bound to an Ethernet
++ * bridge, just like a proper netback interface, while a local IP interface
++ * is configured on 'veth0'.
++ * 
++ * As with a real netback interface, vif0.0 is configured with a suitable
++ * dummy MAC address. No default is provided for veth0: a reasonable strategy
++ * is to transfer eth0's MAC address to veth0, and give eth0 a dummy address
++ * (to avoid confusing the Etherbridge).
++ * 
++ * Copyright (c) 2005 K A Fraser
++ * 
++ * 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/module.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/ethtool.h>
++#include <net/dst.h>
++#include <net/xfrm.h>		/* secpath_reset() */
++#include <asm/hypervisor.h>	/* is_initial_xendomain() */
++
++static int nloopbacks = -1;
++module_param(nloopbacks, int, 0);
++MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
++
++struct net_private {
++	struct net_device *loopback_dev;
++	struct net_device_stats stats;
++};
++
++static int loopback_open(struct net_device *dev)
++{
++	struct net_private *np = netdev_priv(dev);
++	memset(&np->stats, 0, sizeof(np->stats));
++	netif_start_queue(dev);
++	return 0;
++}
++
++static int loopback_close(struct net_device *dev)
++{
++	netif_stop_queue(dev);
++	return 0;
++}
++
++#ifdef CONFIG_X86
++static int is_foreign(unsigned long pfn)
++{
++	/* NB. Play it safe for auto-translation mode. */
++	return (xen_feature(XENFEAT_auto_translated_physmap) ||
++		(phys_to_machine_mapping[pfn] & FOREIGN_FRAME_BIT));
++}
++#else
++/* How to detect a foreign mapping? Play it safe. */
++#define is_foreign(pfn)	(1)
++#endif
++
++static int skb_remove_foreign_references(struct sk_buff *skb)
++{
++	struct page *page;
++	unsigned long pfn;
++	int i, off;
++	char *vaddr;
++
++	BUG_ON(skb_shinfo(skb)->frag_list);
++
++	if (skb_cloned(skb) &&
++	    unlikely(pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
++		return 0;
++
++	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++		pfn = page_to_pfn(skb_shinfo(skb)->frags[i].page);
++		if (!is_foreign(pfn))
++			continue;
++		
++		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
++		if (unlikely(!page))
++			return 0;
++
++		vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
++		off = skb_shinfo(skb)->frags[i].page_offset;
++		memcpy(page_address(page) + off,
++		       vaddr + off,
++		       skb_shinfo(skb)->frags[i].size);
++		kunmap_skb_frag(vaddr);
++
++		put_page(skb_shinfo(skb)->frags[i].page);
++		skb_shinfo(skb)->frags[i].page = page;
++	}
++
++	return 1;
++}
++
++static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	struct net_private *np = netdev_priv(dev);
++
++	if (!skb_remove_foreign_references(skb)) {
++		np->stats.tx_dropped++;
++		dev_kfree_skb(skb);
++		return 0;
++	}
++
++	dst_release(skb->dst);
++	skb->dst = NULL;
++
++	skb_orphan(skb);
++
++	np->stats.tx_bytes += skb->len;
++	np->stats.tx_packets++;
++
++	/* Switch to loopback context. */
++	dev = np->loopback_dev;
++	np  = netdev_priv(dev);
++
++	np->stats.rx_bytes += skb->len;
++	np->stats.rx_packets++;
++
++	if (skb->ip_summed == CHECKSUM_HW) {
++		/* Defer checksum calculation. */
++		skb->proto_csum_blank = 1;
++		/* Must be a local packet: assert its integrity. */
++		skb->proto_data_valid = 1;
++	}
++
++	skb->ip_summed = skb->proto_data_valid ?
++		CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
++
++	skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
++	skb->protocol = eth_type_trans(skb, dev);
++	skb->dev      = dev;
++	dev->last_rx  = jiffies;
++
++	/* Flush netfilter context: rx'ed skbuffs not expected to have any. */
++	nf_reset(skb);
++	secpath_reset(skb);
++
++	netif_rx(skb);
++
++	return 0;
++}
++
++static struct net_device_stats *loopback_get_stats(struct net_device *dev)
++{
++	struct net_private *np = netdev_priv(dev);
++	return &np->stats;
++}
++
++static struct ethtool_ops network_ethtool_ops =
++{
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.set_tx_csum = ethtool_op_set_tx_csum,
++	.get_sg = ethtool_op_get_sg,
++	.set_sg = ethtool_op_set_sg,
++	.get_tso = ethtool_op_get_tso,
++	.set_tso = ethtool_op_set_tso,
++	.get_link = ethtool_op_get_link,
++};
++
++/*
++ * Nothing to do here. Virtual interface is point-to-point and the
++ * physical interface is probably promiscuous anyway.
++ */
++static void loopback_set_multicast_list(struct net_device *dev)
++{
++}
++
++static void loopback_construct(struct net_device *dev, struct net_device *lo)
++{
++	struct net_private *np = netdev_priv(dev);
++
++	np->loopback_dev     = lo;
++
++	dev->open            = loopback_open;
++	dev->stop            = loopback_close;
++	dev->hard_start_xmit = loopback_start_xmit;
++	dev->get_stats       = loopback_get_stats;
++	dev->set_multicast_list = loopback_set_multicast_list;
++	dev->change_mtu	     = NULL; /* allow arbitrary mtu */
++
++	dev->tx_queue_len    = 0;
++
++	dev->features        = (NETIF_F_HIGHDMA |
++				NETIF_F_LLTX |
++				NETIF_F_TSO |
++				NETIF_F_SG |
++				NETIF_F_IP_CSUM);
++
++	SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
++
++	/*
++	 * We do not set a jumbo MTU on the interface. Otherwise the network
++	 * stack will try to send large packets that will get dropped by the
++	 * Ethernet bridge (unless the physical Ethernet interface is
++	 * configured to transfer jumbo packets). If a larger MTU is desired
++	 * then the system administrator can specify it using the 'ifconfig'
++	 * command.
++	 */
++	/*dev->mtu             = 16*1024;*/
++}
++
++static int __init make_loopback(int i)
++{
++	struct net_device *dev1, *dev2;
++	char dev_name[IFNAMSIZ];
++	int err = -ENOMEM;
++
++	sprintf(dev_name, "vif0.%d", i);
++	dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
++	if (!dev1)
++		return err;
++
++	sprintf(dev_name, "veth%d", i);
++	dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
++	if (!dev2)
++		goto fail_netdev2;
++
++	loopback_construct(dev1, dev2);
++	loopback_construct(dev2, dev1);
++
++	/*
++	 * Initialise a dummy MAC address for the 'dummy backend' interface. We
++	 * choose the numerically largest non-broadcast address to prevent the
++	 * address getting stolen by an Ethernet bridge for STP purposes.
++	 */
++	memset(dev1->dev_addr, 0xFF, ETH_ALEN);
++	dev1->dev_addr[0] &= ~0x01;
++
++	if ((err = register_netdev(dev1)) != 0)
++		goto fail;
++
++	if ((err = register_netdev(dev2)) != 0) {
++		unregister_netdev(dev1);
++		goto fail;
++	}
++
++	return 0;
++
++ fail:
++	free_netdev(dev2);
++ fail_netdev2:
++	free_netdev(dev1);
++	return err;
++}
++
++static void __exit clean_loopback(int i)
++{
++	struct net_device *dev1, *dev2;
++	char dev_name[IFNAMSIZ];
++
++	sprintf(dev_name, "vif0.%d", i);
++	dev1 = dev_get_by_name(dev_name);
++	sprintf(dev_name, "veth%d", i);
++	dev2 = dev_get_by_name(dev_name);
++	if (dev1 && dev2) {
++		unregister_netdev(dev2);
++		unregister_netdev(dev1);
++		free_netdev(dev2);
++		free_netdev(dev1);
++	}
++}
++
++static int __init loopback_init(void)
++{
++	int i, err = 0;
++
++	if (nloopbacks == -1)
++		nloopbacks = is_initial_xendomain() ? 4 : 0;
++
++	for (i = 0; i < nloopbacks; i++)
++		if ((err = make_loopback(i)) != 0)
++			break;
++
++	return err;
++}
++
++module_init(loopback_init);
++
++static void __exit loopback_exit(void)
++{
++	int i;
++
++	for (i = nloopbacks; i-- > 0; )
++		clean_loopback(i);
++}
++
++module_exit(loopback_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/netback.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,1691 @@
++/******************************************************************************
++ * drivers/xen/netback/netback.c
++ * 
++ * Back-end of the driver for virtual network devices. This portion of the
++ * driver exports a 'unified' network-device interface that can be accessed
++ * by any operating system that implements a compatible front end. A 
++ * reference front-end implementation can be found in:
++ *  drivers/xen/netfront/netfront.c
++ * 
++ * Copyright (c) 2002-2005, K A Fraser
++ * 
++ * 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 "common.h"
++#include <xen/balloon.h>
++#include <xen/interface/memory.h>
++
++/*define NETBE_DEBUG_INTERRUPT*/
++
++struct netbk_rx_meta {
++	skb_frag_t frag;
++	int id;
++	u8 copy:1;
++};
++
++struct netbk_tx_pending_inuse {
++	struct list_head list;
++	unsigned long alloc_time;
++};
++
++static void netif_idx_release(u16 pending_idx);
++static void make_tx_response(netif_t *netif, 
++			     netif_tx_request_t *txp,
++			     s8       st);
++static netif_rx_response_t *make_rx_response(netif_t *netif, 
++					     u16      id, 
++					     s8       st,
++					     u16      offset,
++					     u16      size,
++					     u16      flags);
++
++static void net_tx_action(unsigned long unused);
++static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
++
++static void net_rx_action(unsigned long unused);
++static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
++
++static struct timer_list net_timer;
++static struct timer_list netbk_tx_pending_timer;
++
++#define MAX_PENDING_REQS 256
++
++static struct sk_buff_head rx_queue;
++
++static struct page **mmap_pages;
++static inline unsigned long idx_to_pfn(unsigned int idx)
++{
++	return page_to_pfn(mmap_pages[idx]);
++}
++
++static inline unsigned long idx_to_kaddr(unsigned int idx)
++{
++	return (unsigned long)pfn_to_kaddr(idx_to_pfn(idx));
++}
++
++/* extra field used in struct page */
++static inline void netif_set_page_index(struct page *pg, unsigned int index)
++{
++	*(unsigned long *)&pg->mapping = index;
++}
++
++static inline int netif_page_index(struct page *pg)
++{
++	unsigned long idx = (unsigned long)pg->mapping;
++
++	if (!PageForeign(pg))
++		return -1;
++
++	if ((idx >= MAX_PENDING_REQS) || (mmap_pages[idx] != pg))
++		return -1;
++
++	return idx;
++}
++
++#define PKT_PROT_LEN 64
++
++static struct pending_tx_info {
++	netif_tx_request_t req;
++	netif_t *netif;
++} pending_tx_info[MAX_PENDING_REQS];
++static u16 pending_ring[MAX_PENDING_REQS];
++typedef unsigned int PEND_RING_IDX;
++#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
++static PEND_RING_IDX pending_prod, pending_cons;
++#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
++
++/* Freed TX SKBs get batched on this ring before return to pending_ring. */
++static u16 dealloc_ring[MAX_PENDING_REQS];
++static PEND_RING_IDX dealloc_prod, dealloc_cons;
++
++/* Doubly-linked list of in-use pending entries. */
++static struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS];
++static LIST_HEAD(pending_inuse_head);
++
++static struct sk_buff_head tx_queue;
++
++static grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
++static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
++static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
++
++static struct list_head net_schedule_list;
++static spinlock_t net_schedule_list_lock;
++
++#define MAX_MFN_ALLOC 64
++static unsigned long mfn_list[MAX_MFN_ALLOC];
++static unsigned int alloc_index = 0;
++
++/* Setting this allows the safe use of this driver without netloop. */
++static int MODPARM_copy_skb = 1;
++module_param_named(copy_skb, MODPARM_copy_skb, bool, 0);
++MODULE_PARM_DESC(copy_skb, "Copy data received from netfront without netloop");
++static int MODPARM_permute_returns = 0;
++module_param_named(permute_returns, MODPARM_permute_returns, bool, S_IRUSR|S_IWUSR);
++MODULE_PARM_DESC(permute_returns, "Randomly permute the order in which TX responses are sent to the frontend");
++
++int netbk_copy_skb_mode;
++
++static inline unsigned long alloc_mfn(void)
++{
++	BUG_ON(alloc_index == 0);
++	return mfn_list[--alloc_index];
++}
++
++static int check_mfn(int nr)
++{
++	struct xen_memory_reservation reservation = {
++		.extent_order = 0,
++		.domid        = DOMID_SELF
++	};
++	int rc;
++
++	if (likely(alloc_index >= nr))
++		return 0;
++
++	set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index);
++	reservation.nr_extents = MAX_MFN_ALLOC - alloc_index;
++	rc = HYPERVISOR_memory_op(XENMEM_increase_reservation, &reservation);
++	if (likely(rc > 0))
++		alloc_index += rc;
++
++	return alloc_index >= nr ? 0 : -ENOMEM;
++}
++
++static inline void maybe_schedule_tx_action(void)
++{
++	smp_mb();
++	if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
++	    !list_empty(&net_schedule_list))
++		tasklet_schedule(&net_tx_tasklet);
++}
++
++static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
++{
++	struct skb_shared_info *ninfo;
++	struct sk_buff *nskb;
++	unsigned long offset;
++	int ret;
++	int len;
++	int headlen;
++
++	BUG_ON(skb_shinfo(skb)->frag_list != NULL);
++
++	nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC | __GFP_NOWARN);
++	if (unlikely(!nskb))
++		goto err;
++
++	skb_reserve(nskb, 16 + NET_IP_ALIGN);
++	headlen = nskb->end - nskb->data;
++	if (headlen > skb_headlen(skb))
++		headlen = skb_headlen(skb);
++	ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen);
++	BUG_ON(ret);
++
++	ninfo = skb_shinfo(nskb);
++	ninfo->gso_size = skb_shinfo(skb)->gso_size;
++	ninfo->gso_type = skb_shinfo(skb)->gso_type;
++
++	offset = headlen;
++	len = skb->len - headlen;
++
++	nskb->len = skb->len;
++	nskb->data_len = len;
++	nskb->truesize += len;
++
++	while (len) {
++		struct page *page;
++		int copy;
++		int zero;
++
++		if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) {
++			dump_stack();
++			goto err_free;
++		}
++
++		copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
++		zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
++
++		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | zero);
++		if (unlikely(!page))
++			goto err_free;
++
++		ret = skb_copy_bits(skb, offset, page_address(page), copy);
++		BUG_ON(ret);
++
++		ninfo->frags[ninfo->nr_frags].page = page;
++		ninfo->frags[ninfo->nr_frags].page_offset = 0;
++		ninfo->frags[ninfo->nr_frags].size = copy;
++		ninfo->nr_frags++;
++
++		offset += copy;
++		len -= copy;
++	}
++
++	offset = nskb->data - skb->data;
++
++	nskb->h.raw = skb->h.raw + offset;
++	nskb->nh.raw = skb->nh.raw + offset;
++	nskb->mac.raw = skb->mac.raw + offset;
++
++	return nskb;
++
++ err_free:
++	kfree_skb(nskb);
++ err:
++	return NULL;
++}
++
++static inline int netbk_max_required_rx_slots(netif_t *netif)
++{
++	if (netif->features & (NETIF_F_SG|NETIF_F_TSO))
++		return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */
++	return 1; /* all in one */
++}
++
++static inline int netbk_queue_full(netif_t *netif)
++{
++	RING_IDX peek   = netif->rx_req_cons_peek;
++	RING_IDX needed = netbk_max_required_rx_slots(netif);
++
++	return ((netif->rx.sring->req_prod - peek) < needed) ||
++	       ((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed);
++}
++
++static void tx_queue_callback(unsigned long data)
++{
++	netif_t *netif = (netif_t *)data;
++	if (netif_schedulable(netif))
++		netif_wake_queue(netif->dev);
++}
++
++int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++
++	BUG_ON(skb->dev != dev);
++
++	/* Drop the packet if the target domain has no receive buffers. */
++	if (unlikely(!netif_schedulable(netif) || netbk_queue_full(netif)))
++		goto drop;
++
++	/*
++	 * Copy the packet here if it's destined for a flipping interface
++	 * but isn't flippable (e.g. extra references to data).
++	 * XXX For now we also copy skbuffs whose head crosses a page
++	 * boundary, because netbk_gop_skb can't handle them.
++	 */
++	if (!netif->copying_receiver ||
++	    ((skb_headlen(skb) + offset_in_page(skb->data)) >= PAGE_SIZE)) {
++		struct sk_buff *nskb = netbk_copy_skb(skb);
++		if ( unlikely(nskb == NULL) )
++			goto drop;
++		/* Copy only the header fields we use in this driver. */
++		nskb->dev = skb->dev;
++		nskb->ip_summed = skb->ip_summed;
++		nskb->proto_data_valid = skb->proto_data_valid;
++		dev_kfree_skb(skb);
++		skb = nskb;
++	}
++
++	netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
++				   !!skb_shinfo(skb)->gso_size;
++	netif_get(netif);
++
++	if (netbk_can_queue(dev) && netbk_queue_full(netif)) {
++		netif->rx.sring->req_event = netif->rx_req_cons_peek +
++			netbk_max_required_rx_slots(netif);
++		mb(); /* request notification /then/ check & stop the queue */
++		if (netbk_queue_full(netif)) {
++			netif_stop_queue(dev);
++			/*
++			 * Schedule 500ms timeout to restart the queue, thus
++			 * ensuring that an inactive queue will be drained.
++			 * Packets will be immediately be dropped until more
++			 * receive buffers become available (see
++			 * netbk_queue_full() check above).
++			 */
++			netif->tx_queue_timeout.data = (unsigned long)netif;
++			netif->tx_queue_timeout.function = tx_queue_callback;
++			__mod_timer(&netif->tx_queue_timeout, jiffies + HZ/2);
++		}
++	}
++
++	skb_queue_tail(&rx_queue, skb);
++	tasklet_schedule(&net_rx_tasklet);
++
++	return 0;
++
++ drop:
++	netif->stats.tx_dropped++;
++	dev_kfree_skb(skb);
++	return 0;
++}
++
++#if 0
++static void xen_network_done_notify(void)
++{
++	static struct net_device *eth0_dev = NULL;
++	if (unlikely(eth0_dev == NULL))
++		eth0_dev = __dev_get_by_name("eth0");
++	netif_rx_schedule(eth0_dev);
++}
++/* 
++ * Add following to poll() function in NAPI driver (Tigon3 is example):
++ *  if ( xen_network_done() )
++ *      tg3_enable_ints(tp);
++ */
++int xen_network_done(void)
++{
++	return skb_queue_empty(&rx_queue);
++}
++#endif
++
++struct netrx_pending_operations {
++	unsigned trans_prod, trans_cons;
++	unsigned mmu_prod, mmu_mcl;
++	unsigned mcl_prod, mcl_cons;
++	unsigned copy_prod, copy_cons;
++	unsigned meta_prod, meta_cons;
++	mmu_update_t *mmu;
++	gnttab_transfer_t *trans;
++	gnttab_copy_t *copy;
++	multicall_entry_t *mcl;
++	struct netbk_rx_meta *meta;
++};
++
++/* Set up the grant operations for this fragment.  If it's a flipping
++   interface, we also set up the unmap request from here. */
++static u16 netbk_gop_frag(netif_t *netif, struct netbk_rx_meta *meta,
++			  int i, struct netrx_pending_operations *npo,
++			  struct page *page, unsigned long size,
++			  unsigned long offset)
++{
++	mmu_update_t *mmu;
++	gnttab_transfer_t *gop;
++	gnttab_copy_t *copy_gop;
++	multicall_entry_t *mcl;
++	netif_rx_request_t *req;
++	unsigned long old_mfn, new_mfn;
++	int idx = netif_page_index(page);
++
++	old_mfn = virt_to_mfn(page_address(page));
++
++	req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i);
++	if (netif->copying_receiver) {
++		/* The fragment needs to be copied rather than
++		   flipped. */
++		meta->copy = 1;
++		copy_gop = npo->copy + npo->copy_prod++;
++		copy_gop->flags = GNTCOPY_dest_gref;
++		if (idx > -1) {
++			struct pending_tx_info *src_pend = &pending_tx_info[idx];
++			copy_gop->source.domid = src_pend->netif->domid;
++			copy_gop->source.u.ref = src_pend->req.gref;
++			copy_gop->flags |= GNTCOPY_source_gref;
++		} else {
++			copy_gop->source.domid = DOMID_SELF;
++			copy_gop->source.u.gmfn = old_mfn;
++		}
++		copy_gop->source.offset = offset;
++		copy_gop->dest.domid = netif->domid;
++		copy_gop->dest.offset = 0;
++		copy_gop->dest.u.ref = req->gref;
++		copy_gop->len = size;
++	} else {
++		meta->copy = 0;
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			new_mfn = alloc_mfn();
++
++			/*
++			 * Set the new P2M table entry before
++			 * reassigning the old data page. Heed the
++			 * comment in pgtable-2level.h:pte_page(). :-)
++			 */
++			set_phys_to_machine(page_to_pfn(page), new_mfn);
++
++			mcl = npo->mcl + npo->mcl_prod++;
++			MULTI_update_va_mapping(mcl,
++					     (unsigned long)page_address(page),
++					     pfn_pte_ma(new_mfn, PAGE_KERNEL),
++					     0);
++
++			mmu = npo->mmu + npo->mmu_prod++;
++			mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
++				MMU_MACHPHYS_UPDATE;
++			mmu->val = page_to_pfn(page);
++		}
++
++		gop = npo->trans + npo->trans_prod++;
++		gop->mfn = old_mfn;
++		gop->domid = netif->domid;
++		gop->ref = req->gref;
++	}
++	return req->id;
++}
++
++static void netbk_gop_skb(struct sk_buff *skb,
++			  struct netrx_pending_operations *npo)
++{
++	netif_t *netif = netdev_priv(skb->dev);
++	int nr_frags = skb_shinfo(skb)->nr_frags;
++	int i;
++	int extra;
++	struct netbk_rx_meta *head_meta, *meta;
++
++	head_meta = npo->meta + npo->meta_prod++;
++	head_meta->frag.page_offset = skb_shinfo(skb)->gso_type;
++	head_meta->frag.size = skb_shinfo(skb)->gso_size;
++	extra = !!head_meta->frag.size + 1;
++
++	for (i = 0; i < nr_frags; i++) {
++		meta = npo->meta + npo->meta_prod++;
++		meta->frag = skb_shinfo(skb)->frags[i];
++		meta->id = netbk_gop_frag(netif, meta, i + extra, npo,
++					  meta->frag.page,
++					  meta->frag.size,
++					  meta->frag.page_offset);
++	}
++
++	/*
++	 * This must occur at the end to ensure that we don't trash skb_shinfo
++	 * until we're done. We know that the head doesn't cross a page
++	 * boundary because such packets get copied in netif_be_start_xmit.
++	 */
++	head_meta->id = netbk_gop_frag(netif, head_meta, 0, npo,
++				       virt_to_page(skb->data),
++				       skb_headlen(skb),
++				       offset_in_page(skb->data));
++
++	netif->rx.req_cons += nr_frags + extra;
++}
++
++static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta)
++{
++	int i;
++
++	for (i = 0; i < nr_frags; i++)
++		put_page(meta[i].frag.page);
++}
++
++/* This is a twin to netbk_gop_skb.  Assume that netbk_gop_skb was
++   used to set up the operations on the top of
++   netrx_pending_operations, which have since been done.  Check that
++   they didn't give any errors and advance over them. */
++static int netbk_check_gop(int nr_frags, domid_t domid,
++			   struct netrx_pending_operations *npo, int *eagain)
++{
++	multicall_entry_t *mcl;
++	gnttab_transfer_t *gop;
++	gnttab_copy_t     *copy_op;
++	int status = NETIF_RSP_OKAY;
++	int i;
++
++    *eagain = 0;
++
++	for (i = 0; i <= nr_frags; i++) {
++		if (npo->meta[npo->meta_cons + i].copy) {
++			copy_op = npo->copy + npo->copy_cons++;
++			if (copy_op->status != GNTST_okay) {
++				DPRINTK("Bad status %d from copy to DOM%d.\n",
++					copy_op->status, domid);
++				status = NETIF_RSP_ERROR;
++                if(copy_op->status == GNTST_eagain)
++                    *eagain = 1;
++			}
++		} else {
++			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++				mcl = npo->mcl + npo->mcl_cons++;
++				/* The update_va_mapping() must not fail. */
++				BUG_ON(mcl->result != 0);
++			}
++
++			gop = npo->trans + npo->trans_cons++;
++			/* Check the reassignment error code. */
++			if (gop->status != 0) {
++				DPRINTK("Bad status %d from grant transfer to DOM%u\n",
++					gop->status, domid);
++				/*
++				 * Page no longer belongs to us unless
++				 * GNTST_bad_page, but that should be
++				 * a fatal error anyway.
++				 */
++				BUG_ON(gop->status == GNTST_bad_page);
++                if(gop->status == GNTST_eagain)
++                    *eagain = 1;
++				status = NETIF_RSP_ERROR;
++			}
++		}
++	}
++
++	return status;
++}
++
++static void netbk_add_frag_responses(netif_t *netif, int status,
++				     struct netbk_rx_meta *meta, int nr_frags)
++{
++	int i;
++	unsigned long offset;
++
++	for (i = 0; i < nr_frags; i++) {
++		int id = meta[i].id;
++		int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data;
++
++		if (meta[i].copy)
++			offset = 0;
++		else
++			offset = meta[i].frag.page_offset;
++		make_rx_response(netif, id, status, offset,
++				 meta[i].frag.size, flags);
++	}
++}
++
++static void net_rx_action(unsigned long unused)
++{
++	netif_t *netif = NULL;
++	s8 status;
++	u16 id, irq, flags;
++	netif_rx_response_t *resp;
++	multicall_entry_t *mcl;
++	struct sk_buff_head rxq;
++	struct sk_buff *skb;
++	int notify_nr = 0;
++	int ret;
++	int nr_frags;
++	int count;
++	unsigned long offset;
++    int eagain;
++
++	/*
++	 * Putting hundreds of bytes on the stack is considered rude.
++	 * Static works because a tasklet can only be on one CPU at any time.
++	 */
++	static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+3];
++	static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
++	static gnttab_transfer_t grant_trans_op[NET_RX_RING_SIZE];
++	static gnttab_copy_t grant_copy_op[NET_RX_RING_SIZE];
++	static unsigned char rx_notify[NR_IRQS];
++	static u16 notify_list[NET_RX_RING_SIZE];
++	static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
++
++	struct netrx_pending_operations npo = {
++		mmu: rx_mmu,
++		trans: grant_trans_op,
++		copy: grant_copy_op,
++		mcl: rx_mcl,
++		meta: meta};
++
++	skb_queue_head_init(&rxq);
++
++	count = 0;
++
++	while ((skb = skb_dequeue(&rx_queue)) != NULL) {
++		nr_frags = skb_shinfo(skb)->nr_frags;
++		*(int *)skb->cb = nr_frags;
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap) &&
++		    !((netif_t *)netdev_priv(skb->dev))->copying_receiver &&
++		    check_mfn(nr_frags + 1)) {
++			/* Memory squeeze? Back off for an arbitrary while. */
++			if ( net_ratelimit() )
++				WPRINTK("Memory squeeze in netback "
++					"driver.\n");
++			mod_timer(&net_timer, jiffies + HZ);
++			skb_queue_head(&rx_queue, skb);
++			break;
++		}
++
++		netbk_gop_skb(skb, &npo);
++
++		count += nr_frags + 1;
++
++		__skb_queue_tail(&rxq, skb);
++
++		/* Filled the batch queue? */
++		if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE)
++			break;
++	}
++
++	BUG_ON(npo.meta_prod > ARRAY_SIZE(meta));
++
++	npo.mmu_mcl = npo.mcl_prod;
++	if (npo.mcl_prod) {
++		BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
++		BUG_ON(npo.mmu_prod > ARRAY_SIZE(rx_mmu));
++		mcl = npo.mcl + npo.mcl_prod++;
++
++		BUG_ON(mcl[-1].op != __HYPERVISOR_update_va_mapping);
++		mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
++
++		mcl->op = __HYPERVISOR_mmu_update;
++		mcl->args[0] = (unsigned long)rx_mmu;
++		mcl->args[1] = npo.mmu_prod;
++		mcl->args[2] = 0;
++		mcl->args[3] = DOMID_SELF;
++	}
++
++	if (npo.trans_prod) {
++		BUG_ON(npo.trans_prod > ARRAY_SIZE(grant_trans_op));
++		mcl = npo.mcl + npo.mcl_prod++;
++		mcl->op = __HYPERVISOR_grant_table_op;
++		mcl->args[0] = GNTTABOP_transfer;
++		mcl->args[1] = (unsigned long)grant_trans_op;
++		mcl->args[2] = npo.trans_prod;
++	}
++
++	if (npo.copy_prod) {
++		BUG_ON(npo.copy_prod > ARRAY_SIZE(grant_copy_op));
++		mcl = npo.mcl + npo.mcl_prod++;
++		mcl->op = __HYPERVISOR_grant_table_op;
++		mcl->args[0] = GNTTABOP_copy;
++		mcl->args[1] = (unsigned long)grant_copy_op;
++		mcl->args[2] = npo.copy_prod;
++	}
++
++	/* Nothing to do? */
++	if (!npo.mcl_prod)
++		return;
++
++	BUG_ON(npo.mcl_prod > ARRAY_SIZE(rx_mcl));
++
++	ret = HYPERVISOR_multicall(npo.mcl, npo.mcl_prod);
++	BUG_ON(ret != 0);
++	/* The mmu_machphys_update() must not fail. */
++	BUG_ON(npo.mmu_mcl && npo.mcl[npo.mmu_mcl].result != 0);
++
++	while ((skb = __skb_dequeue(&rxq)) != NULL) {
++		nr_frags = *(int *)skb->cb;
++
++		netif = netdev_priv(skb->dev);
++
++		status = netbk_check_gop(nr_frags, netif->domid, &npo, &eagain);
++
++		/* We can't rely on skb_release_data to release the
++		   pages used by fragments for us, since it tries to
++		   touch the pages in the fraglist.  If we're in
++		   flipping mode, that doesn't work.  In copying mode,
++		   we still have access to all of the pages, and so
++		   it's safe to let release_data deal with it. */
++		/* (Freeing the fragments is safe since we copy
++		   non-linear skbs destined for flipping interfaces) */
++		if (!netif->copying_receiver) {
++            /* 
++             * Cannot handle failed grant transfers at the moment (because
++             * mmu_updates likely completed)
++             */
++            BUG_ON(eagain);
++			atomic_set(&(skb_shinfo(skb)->dataref), 1);
++			skb_shinfo(skb)->frag_list = NULL;
++			skb_shinfo(skb)->nr_frags = 0;
++			netbk_free_pages(nr_frags, meta + npo.meta_cons + 1);
++		}
++
++        if(!eagain)
++        {
++		    netif->stats.tx_bytes += skb->len;
++		    netif->stats.tx_packets++;
++        }
++
++		id = meta[npo.meta_cons].id;
++		flags = nr_frags ? NETRXF_more_data : 0;
++
++		if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
++			flags |= NETRXF_csum_blank | NETRXF_data_validated;
++		else if (skb->proto_data_valid) /* remote but checksummed? */
++			flags |= NETRXF_data_validated;
++
++		if (meta[npo.meta_cons].copy)
++			offset = 0;
++		else
++			offset = offset_in_page(skb->data);
++		resp = make_rx_response(netif, id, status, offset,
++					skb_headlen(skb), flags);
++
++		if (meta[npo.meta_cons].frag.size) {
++			struct netif_extra_info *gso =
++				(struct netif_extra_info *)
++				RING_GET_RESPONSE(&netif->rx,
++						  netif->rx.rsp_prod_pvt++);
++
++			resp->flags |= NETRXF_extra_info;
++
++			gso->u.gso.size = meta[npo.meta_cons].frag.size;
++			gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
++			gso->u.gso.pad = 0;
++			gso->u.gso.features = 0;
++
++			gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
++			gso->flags = 0;
++		}
++
++		netbk_add_frag_responses(netif, status,
++					 meta + npo.meta_cons + 1,
++					 nr_frags);
++
++		RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
++		irq = netif->irq;
++		if (ret && !rx_notify[irq]) {
++			rx_notify[irq] = 1;
++			notify_list[notify_nr++] = irq;
++		}
++
++		if (netif_queue_stopped(netif->dev) &&
++		    netif_schedulable(netif) &&
++		    !netbk_queue_full(netif))
++			netif_wake_queue(netif->dev);
++
++        if(!eagain || netbk_queue_full(netif))
++        {
++		    netif_put(netif);
++		    dev_kfree_skb(skb);
++		    netif->stats.tx_dropped += !!eagain;
++        } 
++        else
++        {
++	        netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
++				   !!skb_shinfo(skb)->gso_size;
++            skb_queue_head(&rx_queue, skb);
++        }
++
++		npo.meta_cons += nr_frags + 1;
++	}
++
++	while (notify_nr != 0) {
++		irq = notify_list[--notify_nr];
++		rx_notify[irq] = 0;
++		notify_remote_via_irq(irq);
++	}
++
++	/* More work to do? */
++	if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer))
++		tasklet_schedule(&net_rx_tasklet);
++#if 0
++	else
++		xen_network_done_notify();
++#endif
++}
++
++static void net_alarm(unsigned long unused)
++{
++	tasklet_schedule(&net_rx_tasklet);
++}
++
++static void netbk_tx_pending_timeout(unsigned long unused)
++{
++	tasklet_schedule(&net_tx_tasklet);
++}
++
++struct net_device_stats *netif_be_get_stats(struct net_device *dev)
++{
++	netif_t *netif = netdev_priv(dev);
++	return &netif->stats;
++}
++
++static int __on_net_schedule_list(netif_t *netif)
++{
++	return netif->list.next != NULL;
++}
++
++static void remove_from_net_schedule_list(netif_t *netif)
++{
++	spin_lock_irq(&net_schedule_list_lock);
++	if (likely(__on_net_schedule_list(netif))) {
++		list_del(&netif->list);
++		netif->list.next = NULL;
++		netif_put(netif);
++	}
++	spin_unlock_irq(&net_schedule_list_lock);
++}
++
++static void add_to_net_schedule_list_tail(netif_t *netif)
++{
++	if (__on_net_schedule_list(netif))
++		return;
++
++	spin_lock_irq(&net_schedule_list_lock);
++	if (!__on_net_schedule_list(netif) &&
++	    likely(netif_schedulable(netif))) {
++		list_add_tail(&netif->list, &net_schedule_list);
++		netif_get(netif);
++	}
++	spin_unlock_irq(&net_schedule_list_lock);
++}
++
++/*
++ * Note on CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER:
++ * If this driver is pipelining transmit requests then we can be very
++ * aggressive in avoiding new-packet notifications -- frontend only needs to
++ * send a notification if there are no outstanding unreceived responses.
++ * If we may be buffer transmit buffers for any reason then we must be rather
++ * more conservative and treat this as the final check for pending work.
++ */
++void netif_schedule_work(netif_t *netif)
++{
++	int more_to_do;
++
++#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER
++	more_to_do = RING_HAS_UNCONSUMED_REQUESTS(&netif->tx);
++#else
++	RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do);
++#endif
++
++	if (more_to_do) {
++		add_to_net_schedule_list_tail(netif);
++		maybe_schedule_tx_action();
++	}
++}
++
++void netif_deschedule_work(netif_t *netif)
++{
++	remove_from_net_schedule_list(netif);
++}
++
++
++static void tx_add_credit(netif_t *netif)
++{
++	unsigned long max_burst, max_credit;
++
++	/*
++	 * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
++	 * Otherwise the interface can seize up due to insufficient credit.
++	 */
++	max_burst = RING_GET_REQUEST(&netif->tx, netif->tx.req_cons)->size;
++	max_burst = min(max_burst, 131072UL);
++	max_burst = max(max_burst, netif->credit_bytes);
++
++	/* Take care that adding a new chunk of credit doesn't wrap to zero. */
++	max_credit = netif->remaining_credit + netif->credit_bytes;
++	if (max_credit < netif->remaining_credit)
++		max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
++
++	netif->remaining_credit = min(max_credit, max_burst);
++}
++
++static void tx_credit_callback(unsigned long data)
++{
++	netif_t *netif = (netif_t *)data;
++	tx_add_credit(netif);
++	netif_schedule_work(netif);
++}
++
++static inline int copy_pending_req(PEND_RING_IDX pending_idx)
++{
++	return gnttab_copy_grant_page(grant_tx_handle[pending_idx],
++				      &mmap_pages[pending_idx]);
++}
++
++static void permute_dealloc_ring(PEND_RING_IDX dc, PEND_RING_IDX dp)
++{
++	static unsigned random_src = 0x12345678;
++	unsigned dst_offset;
++	PEND_RING_IDX dest;
++	u16 tmp;
++
++	while (dc != dp) {
++		dst_offset = (random_src / 256) % (dp - dc);
++		dest = dc + dst_offset;
++		tmp = dealloc_ring[MASK_PEND_IDX(dest)];
++		dealloc_ring[MASK_PEND_IDX(dest)] =
++			dealloc_ring[MASK_PEND_IDX(dc)];
++		dealloc_ring[MASK_PEND_IDX(dc)] = tmp;
++		dc++;
++		random_src *= 68389;
++	}
++}
++
++inline static void net_tx_action_dealloc(void)
++{
++	struct netbk_tx_pending_inuse *inuse, *n;
++	gnttab_unmap_grant_ref_t *gop;
++	u16 pending_idx;
++	PEND_RING_IDX dc, dp;
++	netif_t *netif;
++	int ret;
++	LIST_HEAD(list);
++
++	dc = dealloc_cons;
++	gop = tx_unmap_ops;
++
++	/*
++	 * Free up any grants we have finished using
++	 */
++	do {
++		dp = dealloc_prod;
++
++		/* Ensure we see all indices enqueued by netif_idx_release(). */
++		smp_rmb();
++
++		if (MODPARM_permute_returns)
++			permute_dealloc_ring(dc, dp);
++
++		while (dc != dp) {
++			unsigned long pfn;
++
++			pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
++			list_move_tail(&pending_inuse[pending_idx].list, &list);
++
++			pfn = idx_to_pfn(pending_idx);
++			/* Already unmapped? */
++			if (!phys_to_machine_mapping_valid(pfn))
++				continue;
++
++			gnttab_set_unmap_op(gop, idx_to_kaddr(pending_idx),
++					    GNTMAP_host_map,
++					    grant_tx_handle[pending_idx]);
++			gop++;
++		}
++
++		if (netbk_copy_skb_mode != NETBK_DELAYED_COPY_SKB ||
++		    list_empty(&pending_inuse_head))
++			break;
++
++		/* Copy any entries that have been pending for too long. */
++		list_for_each_entry_safe(inuse, n, &pending_inuse_head, list) {
++			if (time_after(inuse->alloc_time + HZ / 2, jiffies))
++				break;
++
++			pending_idx = inuse - pending_inuse;
++
++			pending_tx_info[pending_idx].netif->nr_copied_skbs++;
++
++			switch (copy_pending_req(pending_idx)) {
++			case 0:
++				list_move_tail(&inuse->list, &list);
++				continue;
++			case -EBUSY:
++				list_del_init(&inuse->list);
++				continue;
++			case -ENOENT:
++				continue;
++			}
++
++			break;
++		}
++	} while (dp != dealloc_prod);
++
++	dealloc_cons = dc;
++
++	ret = HYPERVISOR_grant_table_op(
++		GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops);
++	BUG_ON(ret);
++
++	list_for_each_entry_safe(inuse, n, &list, list) {
++		pending_idx = inuse - pending_inuse;
++
++		netif = pending_tx_info[pending_idx].netif;
++
++		make_tx_response(netif, &pending_tx_info[pending_idx].req, 
++				 NETIF_RSP_OKAY);
++
++		/* Ready for next use. */
++		gnttab_reset_grant_page(mmap_pages[pending_idx]);
++
++		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
++
++		netif_put(netif);
++
++		list_del_init(&inuse->list);
++	}
++}
++
++static void netbk_tx_err(netif_t *netif, netif_tx_request_t *txp, RING_IDX end)
++{
++	RING_IDX cons = netif->tx.req_cons;
++
++	do {
++		make_tx_response(netif, txp, NETIF_RSP_ERROR);
++		if (cons >= end)
++			break;
++		txp = RING_GET_REQUEST(&netif->tx, cons++);
++	} while (1);
++	netif->tx.req_cons = cons;
++	netif_schedule_work(netif);
++	netif_put(netif);
++}
++
++static int netbk_count_requests(netif_t *netif, netif_tx_request_t *first,
++				netif_tx_request_t *txp, int work_to_do)
++{
++	RING_IDX cons = netif->tx.req_cons;
++	int frags = 0;
++
++	if (!(first->flags & NETTXF_more_data))
++		return 0;
++
++	do {
++		if (frags >= work_to_do) {
++			DPRINTK("Need more frags\n");
++			return -frags;
++		}
++
++		if (unlikely(frags >= MAX_SKB_FRAGS)) {
++			DPRINTK("Too many frags\n");
++			return -frags;
++		}
++
++		memcpy(txp, RING_GET_REQUEST(&netif->tx, cons + frags),
++		       sizeof(*txp));
++		if (txp->size > first->size) {
++			DPRINTK("Frags galore\n");
++			return -frags;
++		}
++
++		first->size -= txp->size;
++		frags++;
++
++		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
++			DPRINTK("txp->offset: %x, size: %u\n",
++				txp->offset, txp->size);
++			return -frags;
++		}
++	} while ((txp++)->flags & NETTXF_more_data);
++
++	return frags;
++}
++
++static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif,
++						  struct sk_buff *skb,
++						  netif_tx_request_t *txp,
++						  gnttab_map_grant_ref_t *mop)
++{
++	struct skb_shared_info *shinfo = skb_shinfo(skb);
++	skb_frag_t *frags = shinfo->frags;
++	unsigned long pending_idx = *((u16 *)skb->data);
++	int i, start;
++
++	/* Skip first skb fragment if it is on same page as header fragment. */
++	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
++
++	for (i = start; i < shinfo->nr_frags; i++, txp++) {
++		pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)];
++
++		gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx),
++				  GNTMAP_host_map | GNTMAP_readonly,
++				  txp->gref, netif->domid);
++
++		memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
++		netif_get(netif);
++		pending_tx_info[pending_idx].netif = netif;
++		frags[i].page = (void *)pending_idx;
++	}
++
++	return mop;
++}
++
++static int netbk_tx_check_mop(struct sk_buff *skb,
++			       gnttab_map_grant_ref_t **mopp)
++{
++	gnttab_map_grant_ref_t *mop = *mopp;
++	int pending_idx = *((u16 *)skb->data);
++	netif_t *netif = pending_tx_info[pending_idx].netif;
++	netif_tx_request_t *txp;
++	struct skb_shared_info *shinfo = skb_shinfo(skb);
++	int nr_frags = shinfo->nr_frags;
++	int i, err, start;
++
++	/* Check status of header. */
++	err = mop->status;
++	if (unlikely(err)) {
++		txp = &pending_tx_info[pending_idx].req;
++		make_tx_response(netif, txp, NETIF_RSP_ERROR);
++		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
++		netif_put(netif);
++	} else {
++		set_phys_to_machine(idx_to_pfn(pending_idx),
++			FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
++		grant_tx_handle[pending_idx] = mop->handle;
++	}
++
++	/* Skip first skb fragment if it is on same page as header fragment. */
++	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
++
++	for (i = start; i < nr_frags; i++) {
++		int j, newerr;
++
++		pending_idx = (unsigned long)shinfo->frags[i].page;
++
++		/* Check error status: if okay then remember grant handle. */
++		newerr = (++mop)->status;
++		if (likely(!newerr)) {
++			set_phys_to_machine(idx_to_pfn(pending_idx),
++				FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT));
++			grant_tx_handle[pending_idx] = mop->handle;
++			/* Had a previous error? Invalidate this fragment. */
++			if (unlikely(err))
++				netif_idx_release(pending_idx);
++			continue;
++		}
++
++		/* Error on this fragment: respond to client with an error. */
++		txp = &pending_tx_info[pending_idx].req;
++		make_tx_response(netif, txp, NETIF_RSP_ERROR);
++		pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
++		netif_put(netif);
++
++		/* Not the first error? Preceding frags already invalidated. */
++		if (err)
++			continue;
++
++		/* First error: invalidate header and preceding fragments. */
++		pending_idx = *((u16 *)skb->data);
++		netif_idx_release(pending_idx);
++		for (j = start; j < i; j++) {
++			pending_idx = (unsigned long)shinfo->frags[i].page;
++			netif_idx_release(pending_idx);
++		}
++
++		/* Remember the error: invalidate all subsequent fragments. */
++		err = newerr;
++	}
++
++	*mopp = mop + 1;
++	return err;
++}
++
++static void netbk_fill_frags(struct sk_buff *skb)
++{
++	struct skb_shared_info *shinfo = skb_shinfo(skb);
++	int nr_frags = shinfo->nr_frags;
++	int i;
++
++	for (i = 0; i < nr_frags; i++) {
++		skb_frag_t *frag = shinfo->frags + i;
++		netif_tx_request_t *txp;
++		unsigned long pending_idx;
++
++		pending_idx = (unsigned long)frag->page;
++
++		pending_inuse[pending_idx].alloc_time = jiffies;
++		list_add_tail(&pending_inuse[pending_idx].list,
++			      &pending_inuse_head);
++
++		txp = &pending_tx_info[pending_idx].req;
++		frag->page = mmap_pages[pending_idx];
++		frag->size = txp->size;
++		frag->page_offset = txp->offset;
++
++		skb->len += txp->size;
++		skb->data_len += txp->size;
++		skb->truesize += txp->size;
++	}
++}
++
++int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras,
++		     int work_to_do)
++{
++	struct netif_extra_info extra;
++	RING_IDX cons = netif->tx.req_cons;
++
++	do {
++		if (unlikely(work_to_do-- <= 0)) {
++			DPRINTK("Missing extra info\n");
++			return -EBADR;
++		}
++
++		memcpy(&extra, RING_GET_REQUEST(&netif->tx, cons),
++		       sizeof(extra));
++		if (unlikely(!extra.type ||
++			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
++			netif->tx.req_cons = ++cons;
++			DPRINTK("Invalid extra type: %d\n", extra.type);
++			return -EINVAL;
++		}
++
++		memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
++		netif->tx.req_cons = ++cons;
++	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
++
++	return work_to_do;
++}
++
++static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso)
++{
++	if (!gso->u.gso.size) {
++		DPRINTK("GSO size must not be zero.\n");
++		return -EINVAL;
++	}
++
++	/* Currently only TCPv4 S.O. is supported. */
++	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
++		DPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
++		return -EINVAL;
++	}
++
++	skb_shinfo(skb)->gso_size = gso->u.gso.size;
++	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
++
++	/* Header must be checked, and gso_segs computed. */
++	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
++	skb_shinfo(skb)->gso_segs = 0;
++
++	return 0;
++}
++
++/* Called after netfront has transmitted */
++static void net_tx_action(unsigned long unused)
++{
++	struct list_head *ent;
++	struct sk_buff *skb;
++	netif_t *netif;
++	netif_tx_request_t txreq;
++	netif_tx_request_t txfrags[MAX_SKB_FRAGS];
++	struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
++	u16 pending_idx;
++	RING_IDX i;
++	gnttab_map_grant_ref_t *mop;
++	unsigned int data_len;
++	int ret, work_to_do;
++
++	net_tx_action_dealloc();
++
++	mop = tx_map_ops;
++	while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
++		!list_empty(&net_schedule_list)) {
++		/* Get a netif from the list with work to do. */
++		ent = net_schedule_list.next;
++		netif = list_entry(ent, netif_t, list);
++		netif_get(netif);
++		remove_from_net_schedule_list(netif);
++
++		RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, work_to_do);
++		if (!work_to_do) {
++			netif_put(netif);
++			continue;
++		}
++
++		i = netif->tx.req_cons;
++		rmb(); /* Ensure that we see the request before we copy it. */
++		memcpy(&txreq, RING_GET_REQUEST(&netif->tx, i), sizeof(txreq));
++
++		/* Credit-based scheduling. */
++		if (txreq.size > netif->remaining_credit) {
++			unsigned long now = jiffies;
++			unsigned long next_credit = 
++				netif->credit_timeout.expires +
++				msecs_to_jiffies(netif->credit_usec / 1000);
++
++			/* Timer could already be pending in rare cases. */
++			if (timer_pending(&netif->credit_timeout)) {
++				netif_put(netif);
++				continue;
++			}
++
++			/* Passed the point where we can replenish credit? */
++			if (time_after_eq(now, next_credit)) {
++				netif->credit_timeout.expires = now;
++				tx_add_credit(netif);
++			}
++
++			/* Still too big to send right now? Set a callback. */
++			if (txreq.size > netif->remaining_credit) {
++				netif->credit_timeout.data     =
++					(unsigned long)netif;
++				netif->credit_timeout.function =
++					tx_credit_callback;
++				__mod_timer(&netif->credit_timeout,
++					    next_credit);
++				netif_put(netif);
++				continue;
++			}
++		}
++		netif->remaining_credit -= txreq.size;
++
++		work_to_do--;
++		netif->tx.req_cons = ++i;
++
++		memset(extras, 0, sizeof(extras));
++		if (txreq.flags & NETTXF_extra_info) {
++			work_to_do = netbk_get_extras(netif, extras,
++						      work_to_do);
++			i = netif->tx.req_cons;
++			if (unlikely(work_to_do < 0)) {
++				netbk_tx_err(netif, &txreq, i);
++				continue;
++			}
++		}
++
++		ret = netbk_count_requests(netif, &txreq, txfrags, work_to_do);
++		if (unlikely(ret < 0)) {
++			netbk_tx_err(netif, &txreq, i - ret);
++			continue;
++		}
++		i += ret;
++
++		if (unlikely(txreq.size < ETH_HLEN)) {
++			DPRINTK("Bad packet size: %d\n", txreq.size);
++			netbk_tx_err(netif, &txreq, i);
++			continue;
++		}
++
++		/* No crossing a page as the payload mustn't fragment. */
++		if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
++			DPRINTK("txreq.offset: %x, size: %u, end: %lu\n", 
++				txreq.offset, txreq.size, 
++				(txreq.offset &~PAGE_MASK) + txreq.size);
++			netbk_tx_err(netif, &txreq, i);
++			continue;
++		}
++
++		pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
++
++		data_len = (txreq.size > PKT_PROT_LEN &&
++			    ret < MAX_SKB_FRAGS) ?
++			PKT_PROT_LEN : txreq.size;
++
++		skb = alloc_skb(data_len + 16 + NET_IP_ALIGN,
++				GFP_ATOMIC | __GFP_NOWARN);
++		if (unlikely(skb == NULL)) {
++			DPRINTK("Can't allocate a skb in start_xmit.\n");
++			netbk_tx_err(netif, &txreq, i);
++			break;
++		}
++
++		/* Packets passed to netif_rx() must have some headroom. */
++		skb_reserve(skb, 16 + NET_IP_ALIGN);
++
++		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
++			struct netif_extra_info *gso;
++			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
++
++			if (netbk_set_skb_gso(skb, gso)) {
++				kfree_skb(skb);
++				netbk_tx_err(netif, &txreq, i);
++				continue;
++			}
++		}
++
++		gnttab_set_map_op(mop, idx_to_kaddr(pending_idx),
++				  GNTMAP_host_map | GNTMAP_readonly,
++				  txreq.gref, netif->domid);
++		mop++;
++
++		memcpy(&pending_tx_info[pending_idx].req,
++		       &txreq, sizeof(txreq));
++		pending_tx_info[pending_idx].netif = netif;
++		*((u16 *)skb->data) = pending_idx;
++
++		__skb_put(skb, data_len);
++
++		skb_shinfo(skb)->nr_frags = ret;
++		if (data_len < txreq.size) {
++			skb_shinfo(skb)->nr_frags++;
++			skb_shinfo(skb)->frags[0].page =
++				(void *)(unsigned long)pending_idx;
++		} else {
++			/* Discriminate from any valid pending_idx value. */
++			skb_shinfo(skb)->frags[0].page = (void *)~0UL;
++		}
++
++		__skb_queue_tail(&tx_queue, skb);
++
++		pending_cons++;
++
++		mop = netbk_get_requests(netif, skb, txfrags, mop);
++
++		netif->tx.req_cons = i;
++		netif_schedule_work(netif);
++
++		if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
++			break;
++	}
++
++	if (mop == tx_map_ops)
++		goto out;
++
++    /* NOTE: some maps may fail with GNTST_eagain, which could be successfully
++     * retried in the backend after a delay. However, we can also fail the tx
++     * req and let the frontend resend the relevant packet again. This is fine
++     * because it is unlikely that a network buffer will be paged out or shared,
++     * and therefore it is unlikely to fail with GNTST_eagain. */
++	ret = HYPERVISOR_grant_table_op(
++		GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops);
++	BUG_ON(ret);
++
++	mop = tx_map_ops;
++	while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
++		netif_tx_request_t *txp;
++
++		pending_idx = *((u16 *)skb->data);
++		netif       = pending_tx_info[pending_idx].netif;
++		txp         = &pending_tx_info[pending_idx].req;
++
++		/* Check the remap error code. */
++		if (unlikely(netbk_tx_check_mop(skb, &mop))) {
++			DPRINTK("netback grant failed.\n");
++			skb_shinfo(skb)->nr_frags = 0;
++			kfree_skb(skb);
++			continue;
++		}
++
++		data_len = skb->len;
++		memcpy(skb->data,
++		       (void *)(idx_to_kaddr(pending_idx)|txp->offset),
++		       data_len);
++		if (data_len < txp->size) {
++			/* Append the packet payload as a fragment. */
++			txp->offset += data_len;
++			txp->size -= data_len;
++		} else {
++			/* Schedule a response immediately. */
++			netif_idx_release(pending_idx);
++		}
++
++		/*
++		 * Old frontends do not assert data_validated but we
++		 * can infer it from csum_blank so test both flags.
++		 */
++		if (txp->flags & (NETTXF_data_validated|NETTXF_csum_blank)) {
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++			skb->proto_data_valid = 1;
++		} else {
++			skb->ip_summed = CHECKSUM_NONE;
++			skb->proto_data_valid = 0;
++		}
++		skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank);
++
++		netbk_fill_frags(skb);
++
++		skb->dev      = netif->dev;
++		skb->protocol = eth_type_trans(skb, skb->dev);
++
++		netif->stats.rx_bytes += skb->len;
++		netif->stats.rx_packets++;
++
++		if (unlikely(netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB) &&
++		    unlikely(skb_linearize(skb))) {
++			DPRINTK("Can't linearize skb in net_tx_action.\n");
++			kfree_skb(skb);
++			continue;
++		}
++
++		netif_rx(skb);
++		netif->dev->last_rx = jiffies;
++	}
++
++ out:
++	if (netbk_copy_skb_mode == NETBK_DELAYED_COPY_SKB &&
++	    !list_empty(&pending_inuse_head)) {
++		struct netbk_tx_pending_inuse *oldest;
++
++		oldest = list_entry(pending_inuse_head.next,
++				    struct netbk_tx_pending_inuse, list);
++		mod_timer(&netbk_tx_pending_timer, oldest->alloc_time + HZ);
++	}
++}
++
++static void netif_idx_release(u16 pending_idx)
++{
++	static DEFINE_SPINLOCK(_lock);
++	unsigned long flags;
++
++	spin_lock_irqsave(&_lock, flags);
++	dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx;
++	/* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */
++	smp_wmb();
++	dealloc_prod++;
++	spin_unlock_irqrestore(&_lock, flags);
++
++	tasklet_schedule(&net_tx_tasklet);
++}
++
++static void netif_page_release(struct page *page, unsigned int order)
++{
++	int idx = netif_page_index(page);
++	BUG_ON(order);
++	BUG_ON(idx < 0);
++	netif_idx_release(idx);
++}
++
++irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	netif_t *netif = dev_id;
++
++	add_to_net_schedule_list_tail(netif);
++	maybe_schedule_tx_action();
++
++	if (netif_schedulable(netif) && !netbk_queue_full(netif))
++		netif_wake_queue(netif->dev);
++
++	return IRQ_HANDLED;
++}
++
++static void make_tx_response(netif_t *netif, 
++			     netif_tx_request_t *txp,
++			     s8       st)
++{
++	RING_IDX i = netif->tx.rsp_prod_pvt;
++	netif_tx_response_t *resp;
++	int notify;
++
++	resp = RING_GET_RESPONSE(&netif->tx, i);
++	resp->id     = txp->id;
++	resp->status = st;
++
++	if (txp->flags & NETTXF_extra_info)
++		RING_GET_RESPONSE(&netif->tx, ++i)->status = NETIF_RSP_NULL;
++
++	netif->tx.rsp_prod_pvt = ++i;
++	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->tx, notify);
++	if (notify)
++		notify_remote_via_irq(netif->irq);
++
++#ifdef CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER
++	if (i == netif->tx.req_cons) {
++		int more_to_do;
++		RING_FINAL_CHECK_FOR_REQUESTS(&netif->tx, more_to_do);
++		if (more_to_do)
++			add_to_net_schedule_list_tail(netif);
++	}
++#endif
++}
++
++static netif_rx_response_t *make_rx_response(netif_t *netif, 
++					     u16      id, 
++					     s8       st,
++					     u16      offset,
++					     u16      size,
++					     u16      flags)
++{
++	RING_IDX i = netif->rx.rsp_prod_pvt;
++	netif_rx_response_t *resp;
++
++	resp = RING_GET_RESPONSE(&netif->rx, i);
++	resp->offset     = offset;
++	resp->flags      = flags;
++	resp->id         = id;
++	resp->status     = (s16)size;
++	if (st < 0)
++		resp->status = (s16)st;
++
++	netif->rx.rsp_prod_pvt = ++i;
++
++	return resp;
++}
++
++#ifdef NETBE_DEBUG_INTERRUPT
++static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
++{
++	struct list_head *ent;
++	netif_t *netif;
++	int i = 0;
++
++	printk(KERN_ALERT "netif_schedule_list:\n");
++	spin_lock_irq(&net_schedule_list_lock);
++
++	list_for_each (ent, &net_schedule_list) {
++		netif = list_entry(ent, netif_t, list);
++		printk(KERN_ALERT " %d: private(rx_req_cons=%08x "
++		       "rx_resp_prod=%08x\n",
++		       i, netif->rx.req_cons, netif->rx.rsp_prod_pvt);
++		printk(KERN_ALERT "   tx_req_cons=%08x tx_resp_prod=%08x)\n",
++		       netif->tx.req_cons, netif->tx.rsp_prod_pvt);
++		printk(KERN_ALERT "   shared(rx_req_prod=%08x "
++		       "rx_resp_prod=%08x\n",
++		       netif->rx.sring->req_prod, netif->rx.sring->rsp_prod);
++		printk(KERN_ALERT "   rx_event=%08x tx_req_prod=%08x\n",
++		       netif->rx.sring->rsp_event, netif->tx.sring->req_prod);
++		printk(KERN_ALERT "   tx_resp_prod=%08x, tx_event=%08x)\n",
++		       netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event);
++		i++;
++	}
++
++	spin_unlock_irq(&net_schedule_list_lock);
++	printk(KERN_ALERT " ** End of netif_schedule_list **\n");
++
++	return IRQ_HANDLED;
++}
++#endif
++
++static int __init netback_init(void)
++{
++	int i;
++	struct page *page;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	/* We can increase reservation by this much in net_rx_action(). */
++	balloon_update_driver_allowance(NET_RX_RING_SIZE);
++
++	skb_queue_head_init(&rx_queue);
++	skb_queue_head_init(&tx_queue);
++
++	init_timer(&net_timer);
++	net_timer.data = 0;
++	net_timer.function = net_alarm;
++
++	init_timer(&netbk_tx_pending_timer);
++	netbk_tx_pending_timer.data = 0;
++	netbk_tx_pending_timer.function = netbk_tx_pending_timeout;
++
++	mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS);
++	if (mmap_pages == NULL) {
++		printk("%s: out of memory\n", __FUNCTION__);
++		return -ENOMEM;
++	}
++
++	for (i = 0; i < MAX_PENDING_REQS; i++) {
++		page = mmap_pages[i];
++		SetPageForeign(page, netif_page_release);
++		netif_set_page_index(page, i);
++		INIT_LIST_HEAD(&pending_inuse[i].list);
++	}
++
++	pending_cons = 0;
++	pending_prod = MAX_PENDING_REQS;
++	for (i = 0; i < MAX_PENDING_REQS; i++)
++		pending_ring[i] = i;
++
++	spin_lock_init(&net_schedule_list_lock);
++	INIT_LIST_HEAD(&net_schedule_list);
++
++	netbk_copy_skb_mode = NETBK_DONT_COPY_SKB;
++	if (MODPARM_copy_skb) {
++		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
++					      NULL, 0))
++			netbk_copy_skb_mode = NETBK_ALWAYS_COPY_SKB;
++		else
++			netbk_copy_skb_mode = NETBK_DELAYED_COPY_SKB;
++	}
++
++	netif_accel_init();
++
++	netif_xenbus_init();
++
++#ifdef NETBE_DEBUG_INTERRUPT
++	(void)bind_virq_to_irqhandler(VIRQ_DEBUG,
++				      0,
++				      netif_be_dbg,
++				      SA_SHIRQ, 
++				      "net-be-dbg",
++				      &netif_be_dbg);
++#endif
++
++	return 0;
++}
++
++module_init(netback_init);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netback/xenbus.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,454 @@
++/*  Xenbus code for netif backend
++    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
++    Copyright (C) 2005 XenSource Ltd
++
++    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 <stdarg.h>
++#include <linux/module.h>
++#include <xen/xenbus.h>
++#include "common.h"
++
++#if 0
++#undef DPRINTK
++#define DPRINTK(fmt, args...) \
++    printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
++#endif
++
++
++static int connect_rings(struct backend_info *);
++static void connect(struct backend_info *);
++static void backend_create_netif(struct backend_info *be);
++
++static int netback_remove(struct xenbus_device *dev)
++{
++	struct backend_info *be = dev->dev.driver_data;
++
++	netback_remove_accelerators(be, dev);
++
++	if (be->netif) {
++		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
++		netif_disconnect(be->netif);
++		be->netif = NULL;
++	}
++	kfree(be);
++	dev->dev.driver_data = NULL;
++	return 0;
++}
++
++
++/**
++ * Entry point to this code when a new device is created.  Allocate the basic
++ * structures and switch to InitWait.
++ */
++static int netback_probe(struct xenbus_device *dev,
++			 const struct xenbus_device_id *id)
++{
++	const char *message;
++	struct xenbus_transaction xbt;
++	int err;
++	int sg;
++	struct backend_info *be = kzalloc(sizeof(struct backend_info),
++					  GFP_KERNEL);
++	if (!be) {
++		xenbus_dev_fatal(dev, -ENOMEM,
++				 "allocating backend structure");
++		return -ENOMEM;
++	}
++
++	be->dev = dev;
++	dev->dev.driver_data = be;
++
++	sg = 1;
++	if (netbk_copy_skb_mode == NETBK_ALWAYS_COPY_SKB)
++		sg = 0;
++
++	do {
++		err = xenbus_transaction_start(&xbt);
++		if (err) {
++			xenbus_dev_fatal(dev, err, "starting transaction");
++			goto fail;
++		}
++
++		err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", sg);
++		if (err) {
++			message = "writing feature-sg";
++			goto abort_transaction;
++		}
++
++		err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
++				    "%d", sg);
++		if (err) {
++			message = "writing feature-gso-tcpv4";
++			goto abort_transaction;
++		}
++
++		/* We support rx-copy path. */
++		err = xenbus_printf(xbt, dev->nodename,
++				    "feature-rx-copy", "%d", 1);
++		if (err) {
++			message = "writing feature-rx-copy";
++			goto abort_transaction;
++		}
++
++		/*
++		 * We don't support rx-flip path (except old guests who don't
++		 * grok this feature flag).
++		 */
++		err = xenbus_printf(xbt, dev->nodename,
++				    "feature-rx-flip", "%d", 0);
++		if (err) {
++			message = "writing feature-rx-flip";
++			goto abort_transaction;
++		}
++
++		err = xenbus_transaction_end(xbt, 0);
++	} while (err == -EAGAIN);
++
++	if (err) {
++		xenbus_dev_fatal(dev, err, "completing transaction");
++		goto fail;
++	}
++
++	netback_probe_accelerators(be, dev);
++
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err)
++		goto fail;
++
++	/* This kicks hotplug scripts, so do it immediately. */
++	backend_create_netif(be);
++
++	return 0;
++
++abort_transaction:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, err, "%s", message);
++fail:
++	DPRINTK("failed");
++	netback_remove(dev);
++	return err;
++}
++
++
++/**
++ * Handle the creation of the hotplug script environment.  We add the script
++ * and vif variables to the environment, for the benefit of the vif-* hotplug
++ * scripts.
++ */
++static int netback_uevent(struct xenbus_device *xdev, char **envp,
++			  int num_envp, char *buffer, int buffer_size)
++{
++	struct backend_info *be = xdev->dev.driver_data;
++	netif_t *netif = be->netif;
++	int i = 0, length = 0;
++	char *val;
++
++	DPRINTK("netback_uevent");
++
++	val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
++	if (IS_ERR(val)) {
++		int err = PTR_ERR(val);
++		xenbus_dev_fatal(xdev, err, "reading script");
++		return err;
++	}
++	else {
++		add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
++			       &length, "script=%s", val);
++		kfree(val);
++	}
++
++	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
++		       "vif=%s", netif->dev->name);
++
++	envp[i] = NULL;
++
++	return 0;
++}
++
++
++static void backend_create_netif(struct backend_info *be)
++{
++	int err;
++	long handle;
++	struct xenbus_device *dev = be->dev;
++
++	if (be->netif != NULL)
++		return;
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading handle");
++		return;
++	}
++
++	be->netif = netif_alloc(&dev->dev, dev->otherend_id, handle);
++	if (IS_ERR(be->netif)) {
++		err = PTR_ERR(be->netif);
++		be->netif = NULL;
++		xenbus_dev_fatal(dev, err, "creating interface");
++		return;
++	}
++
++	kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
++}
++
++
++/**
++ * Callback received when the frontend's state changes.
++ */
++static void frontend_changed(struct xenbus_device *dev,
++			     enum xenbus_state frontend_state)
++{
++	struct backend_info *be = dev->dev.driver_data;
++
++	DPRINTK("%s", xenbus_strstate(frontend_state));
++
++	be->frontend_state = frontend_state;
++
++	switch (frontend_state) {
++	case XenbusStateInitialising:
++		if (dev->state == XenbusStateClosed) {
++			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
++			       __FUNCTION__, dev->nodename);
++			xenbus_switch_state(dev, XenbusStateInitWait);
++		}
++		break;
++
++	case XenbusStateInitialised:
++		break;
++
++	case XenbusStateConnected:
++		if (dev->state == XenbusStateConnected)
++			break;
++		backend_create_netif(be);
++		if (be->netif)
++			connect(be);
++		break;
++
++	case XenbusStateClosing:
++		if (be->netif) {
++			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
++			netif_disconnect(be->netif);
++			be->netif = NULL;
++		}
++		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;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++				 frontend_state);
++		break;
++	}
++}
++
++
++static void xen_net_read_rate(struct xenbus_device *dev,
++			      unsigned long *bytes, unsigned long *usec)
++{
++	char *s, *e;
++	unsigned long b, u;
++	char *ratestr;
++
++	/* Default to unlimited bandwidth. */
++	*bytes = ~0UL;
++	*usec = 0;
++
++	ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
++	if (IS_ERR(ratestr))
++		return;
++
++	s = ratestr;
++	b = simple_strtoul(s, &e, 10);
++	if ((s == e) || (*e != ','))
++		goto fail;
++
++	s = e + 1;
++	u = simple_strtoul(s, &e, 10);
++	if ((s == e) || (*e != '\0'))
++		goto fail;
++
++	*bytes = b;
++	*usec = u;
++
++	kfree(ratestr);
++	return;
++
++ fail:
++	WPRINTK("Failed to parse network rate limit. Traffic unlimited.\n");
++	kfree(ratestr);
++}
++
++static int 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;
++}
++
++static void connect(struct backend_info *be)
++{
++	int err;
++	struct xenbus_device *dev = be->dev;
++
++	err = connect_rings(be);
++	if (err)
++		return;
++
++	err = xen_net_read_mac(dev, be->netif->fe_dev_addr);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
++		return;
++	}
++
++	xen_net_read_rate(dev, &be->netif->credit_bytes,
++			  &be->netif->credit_usec);
++	be->netif->remaining_credit = be->netif->credit_bytes;
++
++	xenbus_switch_state(dev, XenbusStateConnected);
++
++	netif_wake_queue(be->netif->dev);
++}
++
++
++static int connect_rings(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	unsigned long tx_ring_ref, rx_ring_ref;
++	unsigned int evtchn, rx_copy;
++	int err;
++	int val;
++
++	DPRINTK("");
++
++	err = xenbus_gather(XBT_NIL, dev->otherend,
++			    "tx-ring-ref", "%lu", &tx_ring_ref,
++			    "rx-ring-ref", "%lu", &rx_ring_ref,
++			    "event-channel", "%u", &evtchn, NULL);
++	if (err) {
++		xenbus_dev_fatal(dev, err,
++				 "reading %s/ring-ref and event-channel",
++				 dev->otherend);
++		return err;
++	}
++
++	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
++			   &rx_copy);
++	if (err == -ENOENT) {
++		err = 0;
++		rx_copy = 0;
++	}
++	if (err < 0) {
++		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
++				 dev->otherend);
++		return err;
++	}
++	be->netif->copying_receiver = !!rx_copy;
++
++	if (be->netif->dev->tx_queue_len != 0) {
++		if (xenbus_scanf(XBT_NIL, dev->otherend,
++				 "feature-rx-notify", "%d", &val) < 0)
++			val = 0;
++		if (val)
++			be->netif->can_queue = 1;
++		else
++			/* Must be non-zero for pfifo_fast to work. */
++			be->netif->dev->tx_queue_len = 1;
++	}
++
++	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
++		val = 0;
++	if (val) {
++		be->netif->features |= NETIF_F_SG;
++		be->netif->dev->features |= NETIF_F_SG;
++	}
++
++	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
++			 &val) < 0)
++		val = 0;
++	if (val) {
++		be->netif->features |= NETIF_F_TSO;
++		be->netif->dev->features |= NETIF_F_TSO;
++	}
++
++	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
++			 "%d", &val) < 0)
++		val = 0;
++	if (val) {
++		be->netif->features &= ~NETIF_F_IP_CSUM;
++		be->netif->dev->features &= ~NETIF_F_IP_CSUM;
++	}
++
++	/* Map the shared frame, irq etc. */
++	err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
++	if (err) {
++		xenbus_dev_fatal(dev, err,
++				 "mapping shared-frames %lu/%lu port %u",
++				 tx_ring_ref, rx_ring_ref, evtchn);
++		return err;
++	}
++	return 0;
++}
++
++
++/* ** Driver Registration ** */
++
++
++static const struct xenbus_device_id netback_ids[] = {
++	{ "vif" },
++	{ "" }
++};
++
++
++static struct xenbus_driver netback = {
++	.name = "vif",
++	.owner = THIS_MODULE,
++	.ids = netback_ids,
++	.probe = netback_probe,
++	.remove = netback_remove,
++	.uevent = netback_uevent,
++	.otherend_changed = frontend_changed,
++};
++
++
++void netif_xenbus_init(void)
++{
++	xenbus_register_backend(&netback);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netfront/Makefile	2007-07-12 08:54:23.000000000 +0200
+@@ -0,0 +1,4 @@
++
++obj-$(CONFIG_XEN_NETDEV_FRONTEND)	:= xennet.o
++
++xennet-objs := netfront.o accel.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netfront/accel.c	2009-05-04 10:01:03.000000000 +0200
+@@ -0,0 +1,827 @@
++/******************************************************************************
++ * Virtual network driver for conversing with remote driver backends.
++ *
++ * 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.
++ */
++
++#include <linux/netdevice.h>
++#include <linux/skbuff.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <asm/hypervisor.h>
++#include <xen/xenbus.h>
++
++#include "netfront.h"
++
++#define DPRINTK(fmt, args...)				\
++	pr_debug("netfront/accel (%s:%d) " fmt,		\
++	       __FUNCTION__, __LINE__, ##args)
++#define IPRINTK(fmt, args...)				\
++	printk(KERN_INFO "netfront/accel: " fmt, ##args)
++#define WPRINTK(fmt, args...)				\
++	printk(KERN_WARNING "netfront/accel: " fmt, ##args)
++
++static int netfront_remove_accelerator(struct netfront_info *np,
++				       struct xenbus_device *dev);
++static int netfront_load_accelerator(struct netfront_info *np, 
++				     struct xenbus_device *dev, 
++				     const char *frontend);
++
++static void netfront_accelerator_remove_watch(struct netfront_info *np);
++
++/*
++ * List of all netfront accelerator plugin modules available.  Each
++ * list entry is of type struct netfront_accelerator.
++ */ 
++static struct list_head accelerators_list;
++
++/* Workqueue to process acceleration configuration changes */
++struct workqueue_struct *accel_watch_workqueue;
++
++/* Mutex to prevent concurrent loads and suspends, etc. */
++DEFINE_MUTEX(accelerator_mutex);
++
++void netif_init_accel(void)
++{
++	INIT_LIST_HEAD(&accelerators_list);
++
++	accel_watch_workqueue = create_workqueue("net_accel");
++}
++
++void netif_exit_accel(void)
++{
++	struct netfront_accelerator *accelerator, *tmp;
++
++	flush_workqueue(accel_watch_workqueue);
++	destroy_workqueue(accel_watch_workqueue);
++
++	/* No lock required as everything else should be quiet by now */
++	list_for_each_entry_safe(accelerator, tmp, &accelerators_list, link) {
++		BUG_ON(!list_empty(&accelerator->vif_states));
++
++		list_del(&accelerator->link);
++		kfree(accelerator->frontend);
++		kfree(accelerator);
++	}
++}
++
++
++/* 
++ * Watch the configured accelerator and change plugin if it's modified 
++ */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++static void accel_watch_work(struct work_struct *context)
++#else
++static void accel_watch_work(void *context)
++#endif
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++	struct netfront_accel_vif_state *vif_state = 
++		container_of(context, struct netfront_accel_vif_state, 
++			     accel_work);
++#else
++        struct netfront_accel_vif_state *vif_state = 
++		(struct netfront_accel_vif_state *)context;
++#endif
++	struct netfront_info *np = vif_state->np;
++	char *accel_frontend;
++	int accel_len, rc = -1;
++
++	mutex_lock(&accelerator_mutex);
++
++	accel_frontend = xenbus_read(XBT_NIL, np->xbdev->otherend, 
++				     "accel-frontend", &accel_len);
++	if (IS_ERR(accel_frontend)) {
++		accel_frontend = NULL;
++		netfront_remove_accelerator(np, np->xbdev);
++	} else {
++		/* If this is the first time, request the accelerator,
++		   otherwise only request one if it has changed */
++		if (vif_state->accel_frontend == NULL) {
++			rc = netfront_load_accelerator(np, np->xbdev, 
++						       accel_frontend);
++		} else {
++			if (strncmp(vif_state->accel_frontend, accel_frontend,
++				    accel_len)) {
++				netfront_remove_accelerator(np, np->xbdev);
++				rc = netfront_load_accelerator(np, np->xbdev, 
++							       accel_frontend);
++			}
++		}
++	}
++
++	/* Get rid of previous state and replace with the new name */
++	if (vif_state->accel_frontend != NULL)
++		kfree(vif_state->accel_frontend);
++	vif_state->accel_frontend = accel_frontend;
++
++	mutex_unlock(&accelerator_mutex);
++
++	if (rc == 0) {
++		DPRINTK("requesting module %s\n", accel_frontend);
++		request_module("%s", accel_frontend);
++		/*
++		 * Module should now call netfront_accelerator_loaded() once
++		 * it's up and running, and we can continue from there 
++		 */
++	}
++}
++
++
++static void accel_watch_changed(struct xenbus_watch *watch,
++				const char **vec, unsigned int len)
++{
++	struct netfront_accel_vif_state *vif_state = 
++		container_of(watch, struct netfront_accel_vif_state,
++			     accel_watch);
++	queue_work(accel_watch_workqueue, &vif_state->accel_work);
++}
++
++
++void netfront_accelerator_add_watch(struct netfront_info *np)
++{
++	int err;
++	
++	/* 
++	 * If old watch exists, e.g. from before suspend/resume,
++	 * remove it now 
++	 */
++	netfront_accelerator_remove_watch(np);
++
++	/* Get a watch on the accelerator plugin */
++	err = xenbus_watch_path2(np->xbdev, np->xbdev->otherend, 
++				 "accel-frontend", 
++				 &np->accel_vif_state.accel_watch,
++				 accel_watch_changed);
++	if (err) {
++		DPRINTK("%s: Failed to register accel watch: %d\n",
++                        __FUNCTION__, err);
++		np->accel_vif_state.accel_watch.node = NULL;
++        }
++}
++
++
++static void 
++netfront_accelerator_purge_watch(struct netfront_accel_vif_state *vif_state)
++{
++	flush_workqueue(accel_watch_workqueue);
++
++	/* Clean up any state left from watch */
++	if (vif_state->accel_frontend != NULL) {
++		kfree(vif_state->accel_frontend);
++		vif_state->accel_frontend = NULL;
++	}
++}
++
++
++static
++void netfront_accelerator_remove_watch(struct netfront_info *np)
++{
++	struct netfront_accel_vif_state *vif_state = &np->accel_vif_state;
++
++	/* Get rid of watch on accelerator plugin */
++	if (vif_state->accel_watch.node != NULL) {
++		unregister_xenbus_watch(&vif_state->accel_watch);
++		kfree(vif_state->accel_watch.node);
++		vif_state->accel_watch.node = NULL;
++
++		netfront_accelerator_purge_watch(vif_state);
++	}	
++}
++
++
++/* 
++ * Initialise the accel_vif_state field in the netfront state
++ */ 
++void init_accelerator_vif(struct netfront_info *np,
++			  struct xenbus_device *dev)
++{
++	np->accelerator = NULL;
++
++	/* It's assumed that these things don't change */
++	np->accel_vif_state.np = np;
++	np->accel_vif_state.dev = dev;
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++	INIT_WORK(&np->accel_vif_state.accel_work, accel_watch_work);
++#else
++	INIT_WORK(&np->accel_vif_state.accel_work, accel_watch_work, 
++		  &np->accel_vif_state);
++#endif
++}
++
++
++/*
++ * Compare a frontend description string against an accelerator to see
++ * if they match.  Would ultimately be nice to replace the string with
++ * a unique numeric identifier for each accelerator.
++ */
++static int match_accelerator(const char *frontend, 
++			     struct netfront_accelerator *accelerator)
++{
++	return strcmp(frontend, accelerator->frontend) == 0;
++}
++
++
++/* 
++ * Add a frontend vif to the list of vifs that is using a netfront
++ * accelerator plugin module.  Must be called with the accelerator
++ * mutex held.
++ */
++static void add_accelerator_vif(struct netfront_accelerator *accelerator,
++				struct netfront_info *np)
++{
++	if (np->accelerator == NULL) {
++		np->accelerator = accelerator;
++		
++		list_add(&np->accel_vif_state.link, &accelerator->vif_states);
++	} else {
++		/* 
++		 * May get here legitimately if suspend_cancel is
++		 * called, but in that case configuration should not
++		 * have changed
++		 */
++		BUG_ON(np->accelerator != accelerator);
++	}
++}
++
++
++/*
++ * Initialise the state to track an accelerator plugin module.  
++ * 
++ * Must be called with the accelerator mutex held.
++ */ 
++static int init_accelerator(const char *frontend, 
++			    struct netfront_accelerator **result,
++			    struct netfront_accel_hooks *hooks)
++{
++	struct netfront_accelerator *accelerator = 
++		kmalloc(sizeof(struct netfront_accelerator), GFP_KERNEL);
++	int frontend_len;
++
++	if (!accelerator) {
++		DPRINTK("no memory for accelerator\n");
++		return -ENOMEM;
++	}
++
++	frontend_len = strlen(frontend) + 1;
++	accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
++	if (!accelerator->frontend) {
++		DPRINTK("no memory for accelerator\n");
++		kfree(accelerator);
++		return -ENOMEM;
++	}
++	strlcpy(accelerator->frontend, frontend, frontend_len);
++	
++	INIT_LIST_HEAD(&accelerator->vif_states);
++	spin_lock_init(&accelerator->vif_states_lock);
++
++	accelerator->hooks = hooks;
++
++	list_add(&accelerator->link, &accelerators_list);
++
++	*result = accelerator;
++
++	return 0;
++}					
++
++
++/* 
++ * Modify the hooks stored in the per-vif state to match that in the
++ * netfront accelerator's state.
++ * 
++ * Takes the vif_states_lock spinlock and may sleep.
++ */
++static void 
++accelerator_set_vif_state_hooks(struct netfront_accel_vif_state *vif_state)
++{
++	struct netfront_accelerator *accelerator;
++	unsigned long flags;
++
++	DPRINTK("%p\n",vif_state);
++
++	/* Make sure there are no data path operations going on */
++	netif_poll_disable(vif_state->np->netdev);
++	netif_tx_lock_bh(vif_state->np->netdev);
++
++	accelerator = vif_state->np->accelerator;
++	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
++	vif_state->hooks = accelerator->hooks;
++	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
++
++	netif_tx_unlock_bh(vif_state->np->netdev);
++	netif_poll_enable(vif_state->np->netdev);
++}
++
++
++/* 
++ * Must be called with the accelerator mutex held.  Takes the
++ * vif_states_lock spinlock.
++ */
++static void accelerator_probe_new_vif(struct netfront_info *np,
++				      struct xenbus_device *dev, 
++				      struct netfront_accelerator *accelerator)
++{
++	struct netfront_accel_hooks *hooks;
++
++	DPRINTK("\n");
++
++	/* Include this frontend device on the accelerator's list */
++	add_accelerator_vif(accelerator, np);
++	
++	hooks = accelerator->hooks;
++	
++	if (hooks && hooks->new_device(np->netdev, dev) == 0)
++		accelerator_set_vif_state_hooks(&np->accel_vif_state);
++
++	return;
++}
++
++
++/*  
++ * Request that a particular netfront accelerator plugin is loaded.
++ * Usually called as a result of the vif configuration specifying
++ * which one to use.
++ *
++ * Must be called with accelerator_mutex held.  Takes the
++ * vif_states_lock spinlock.
++ */
++static int netfront_load_accelerator(struct netfront_info *np, 
++				     struct xenbus_device *dev, 
++				     const char *frontend)
++{
++	struct netfront_accelerator *accelerator;
++	int rc = 0;
++
++	DPRINTK(" %s\n", frontend);
++
++	/* 
++	 * Look at list of loaded accelerators to see if the requested
++	 * one is already there 
++	 */
++	list_for_each_entry(accelerator, &accelerators_list, link) {
++		if (match_accelerator(frontend, accelerator)) {
++			accelerator_probe_new_vif(np, dev, accelerator);
++			return 0;
++		}
++	}
++
++	/* Couldn't find it, so create a new one and load the module */
++	if ((rc = init_accelerator(frontend, &accelerator, NULL)) < 0) {
++		return rc;
++	}
++
++	/* Include this frontend device on the accelerator's list */
++	add_accelerator_vif(accelerator, np);
++
++	return rc;
++}
++
++
++/*
++ * Go through all the netfront vifs and see if they have requested
++ * this accelerator.  Notify the accelerator plugin of the relevant
++ * device if so.  Called when an accelerator plugin module is first
++ * loaded and connects to netfront.
++ *
++ * Must be called with accelerator_mutex held.  Takes the
++ * vif_states_lock spinlock.
++ */
++static void 
++accelerator_probe_vifs(struct netfront_accelerator *accelerator,
++		       struct netfront_accel_hooks *hooks)
++{
++	struct netfront_accel_vif_state *vif_state, *tmp;
++
++	DPRINTK("%p\n", accelerator);
++
++	/* 
++	 * Store the hooks for future calls to probe a new device, and
++	 * to wire into the vif_state once the accelerator plugin is
++	 * ready to accelerate each vif
++	 */
++	BUG_ON(hooks == NULL);
++	accelerator->hooks = hooks;
++
++	/* Holds accelerator_mutex to iterate list */
++	list_for_each_entry_safe(vif_state, tmp, &accelerator->vif_states,
++				 link) {
++		struct netfront_info *np = vif_state->np;
++		
++		if (hooks->new_device(np->netdev, vif_state->dev) == 0)
++			accelerator_set_vif_state_hooks(vif_state);
++	}
++}
++
++
++/* 
++ * Called by the netfront accelerator plugin module when it has
++ * loaded.
++ *
++ * Takes the accelerator_mutex and vif_states_lock spinlock.
++ */
++int netfront_accelerator_loaded(int version, const char *frontend, 
++				struct netfront_accel_hooks *hooks)
++{
++	struct netfront_accelerator *accelerator;
++
++	if (is_initial_xendomain())
++		return -EINVAL;
++
++	if (version != NETFRONT_ACCEL_VERSION) {
++		if (version > NETFRONT_ACCEL_VERSION) {
++			/* Caller has higher version number, leave it
++			   up to them to decide whether to continue.
++			   They can re-call with a lower number if
++			   they're happy to be compatible with us */
++			return NETFRONT_ACCEL_VERSION;
++		} else {
++			/* We have a more recent version than caller.
++			   Currently reject, but may in future be able
++			   to be backwardly compatible */
++			return -EPROTO;
++		}
++	}
++
++	mutex_lock(&accelerator_mutex);
++
++	/* 
++	 * Look through list of accelerators to see if it has already
++	 * been requested
++	 */
++	list_for_each_entry(accelerator, &accelerators_list, link) {
++		if (match_accelerator(frontend, accelerator)) {
++			accelerator_probe_vifs(accelerator, hooks);
++			goto out;
++		}
++	}
++
++	/*
++	 * If it wasn't in the list, add it now so that when it is
++	 * requested the caller will find it
++	 */
++	DPRINTK("Couldn't find matching accelerator (%s)\n",
++		frontend);
++
++	init_accelerator(frontend, &accelerator, hooks);
++
++ out:
++	mutex_unlock(&accelerator_mutex);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(netfront_accelerator_loaded);
++
++
++/* 
++ * Remove the hooks from a single vif state.
++ * 
++ * Takes the vif_states_lock spinlock and may sleep.
++ */
++static void 
++accelerator_remove_single_hook(struct netfront_accelerator *accelerator,
++			       struct netfront_accel_vif_state *vif_state)
++{
++	unsigned long flags;
++
++	/* Make sure there are no data path operations going on */
++	netif_poll_disable(vif_state->np->netdev);
++	netif_tx_lock_bh(vif_state->np->netdev);
++
++	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
++
++	/* 
++	 * Remove the hooks, but leave the vif_state on the
++	 * accelerator's list as that signifies this vif is
++	 * interested in using that accelerator if it becomes
++	 * available again
++	 */
++	vif_state->hooks = NULL;
++	
++	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
++
++	netif_tx_unlock_bh(vif_state->np->netdev);
++	netif_poll_enable(vif_state->np->netdev);		       
++}
++
++
++/* 
++ * Safely remove the accelerator function hooks from a netfront state.
++ * 
++ * Must be called with the accelerator mutex held.  Takes the
++ * vif_states_lock spinlock.
++ */
++static void accelerator_remove_hooks(struct netfront_accelerator *accelerator)
++{
++	struct netfront_accel_vif_state *vif_state, *tmp;
++	unsigned long flags;
++
++	/* Mutex is held to iterate list */
++	list_for_each_entry_safe(vif_state, tmp,
++				 &accelerator->vif_states,
++				 link) {
++		if(vif_state->hooks) {
++			spin_lock_irqsave(&accelerator->vif_states_lock, flags);
++
++			/* Last chance to get statistics from the accelerator */
++			vif_state->hooks->get_stats(vif_state->np->netdev,
++						    &vif_state->np->stats);
++
++			spin_unlock_irqrestore(&accelerator->vif_states_lock,
++					       flags);
++
++			accelerator_remove_single_hook(accelerator, vif_state);
++
++			accelerator->hooks->remove(vif_state->dev);
++		}
++	}
++	
++	accelerator->hooks = NULL;
++}
++
++
++/* 
++ * Called by a netfront accelerator when it is unloaded.  This safely
++ * removes the hooks into the plugin and blocks until all devices have
++ * finished using it, so on return it is safe to unload.
++ *
++ * Takes the accelerator mutex, and vif_states_lock spinlock.
++ */
++void netfront_accelerator_stop(const char *frontend)
++{
++	struct netfront_accelerator *accelerator;
++
++	mutex_lock(&accelerator_mutex);
++
++	list_for_each_entry(accelerator, &accelerators_list, link) {
++		if (match_accelerator(frontend, accelerator)) {
++			accelerator_remove_hooks(accelerator);
++			goto out;
++		}
++	}
++ out:
++	mutex_unlock(&accelerator_mutex);
++}
++EXPORT_SYMBOL_GPL(netfront_accelerator_stop);
++
++
++/* 
++ * Helper for call_remove and do_suspend
++ * 
++ * Must be called with the accelerator mutex held.  Takes the
++ * vif_states_lock spinlock.
++ */
++static int do_remove(struct netfront_info *np, struct xenbus_device *dev)
++{
++	struct netfront_accelerator *accelerator = np->accelerator;
++	unsigned long flags;
++ 	int rc = 0;
++ 
++	if (np->accel_vif_state.hooks) {
++		spin_lock_irqsave(&accelerator->vif_states_lock, flags);
++
++		/* Last chance to get statistics from the accelerator */
++		np->accel_vif_state.hooks->get_stats(np->netdev, &np->stats);
++
++		spin_unlock_irqrestore(&accelerator->vif_states_lock, 
++				       flags);
++
++ 		/* 
++ 		 * Try and do the opposite of accelerator_probe_new_vif
++ 		 * to ensure there's no state pointing back at the 
++ 		 * netdev 
++ 		 */
++		accelerator_remove_single_hook(accelerator, 
++ 					       &np->accel_vif_state);
++
++		rc = accelerator->hooks->remove(dev);
++	}
++ 
++ 	return rc;
++}
++
++
++/*
++ * Must be called with the accelerator mutex held.  Takes the
++ * vif_states_lock spinlock
++ */
++static int netfront_remove_accelerator(struct netfront_info *np,
++				       struct xenbus_device *dev)
++{
++	struct netfront_accelerator *accelerator;
++ 	struct netfront_accel_vif_state *tmp_vif_state;
++	int rc = 0; 
++
++ 	/* Check that we've got a device that was accelerated */
++ 	if (np->accelerator == NULL)
++		return rc;
++
++	accelerator = np->accelerator;
++
++	list_for_each_entry(tmp_vif_state, &accelerator->vif_states,
++			    link) {
++		if (tmp_vif_state == &np->accel_vif_state) {
++			list_del(&np->accel_vif_state.link);
++			break;
++		}
++	}
++
++	rc = do_remove(np, dev);
++
++	np->accelerator = NULL;
++
++	return rc;
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the accelerator mutex and the
++ * vif_states_lock spinlock.
++ */
++int netfront_accelerator_call_remove(struct netfront_info *np,
++				     struct xenbus_device *dev)
++{
++	int rc;
++	netfront_accelerator_remove_watch(np);
++	mutex_lock(&accelerator_mutex);
++	rc = netfront_remove_accelerator(np, dev);
++	mutex_unlock(&accelerator_mutex);
++	return rc;
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the accelerator mutex and the
++ * vif_states_lock spinlock.
++ */
++int netfront_accelerator_suspend(struct netfront_info *np,
++ 				 struct xenbus_device *dev)
++{
++	int rc = 0;
++	
++	mutex_lock(&accelerator_mutex);
++
++ 	/* Check that we've got a device that was accelerated */
++ 	if (np->accelerator == NULL)
++		goto out;
++
++	/* 
++	 * Call the remove accelerator hook, but leave the vif_state
++	 * on the accelerator's list in case there is a suspend_cancel.
++	 */
++	rc = do_remove(np, dev);
++ out:
++	mutex_unlock(&accelerator_mutex);
++	return rc;
++}
++  
++  
++int netfront_accelerator_suspend_cancel(struct netfront_info *np,
++ 					struct xenbus_device *dev)
++{
++	netfront_accelerator_purge_watch(&np->accel_vif_state);
++
++	/* 
++	 * Gratuitously fire the watch handler to reinstate the
++	 * configured accelerator
++	 */
++	if (dev->state == XenbusStateConnected)
++		queue_work(accel_watch_workqueue, 
++			   &np->accel_vif_state.accel_work);
++
++	return 0;
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the accelerator mutex
++ */
++void netfront_accelerator_resume(struct netfront_info *np,
++ 				 struct xenbus_device *dev)
++{
++ 	struct netfront_accel_vif_state *accel_vif_state = NULL;
++
++ 	mutex_lock(&accelerator_mutex);
++
++	/* Check that we've got a device that was accelerated */
++ 	if(np->accelerator == NULL)
++		goto out;
++
++ 	/* Find the vif_state from the accelerator's list */
++ 	list_for_each_entry(accel_vif_state, &np->accelerator->vif_states, 
++ 			    link) {
++ 		if (accel_vif_state->dev == dev) {
++ 			BUG_ON(accel_vif_state != &np->accel_vif_state);
++ 
++ 			/* 
++ 			 * Remove it from the accelerator's list so
++ 			 * state is consistent for probing new vifs
++ 			 * when they get connected
++ 			 */
++ 			list_del(&accel_vif_state->link);
++ 			np->accelerator = NULL;
++
++			break;
++ 		}
++ 	}
++
++ out:
++	mutex_unlock(&accelerator_mutex);
++	return;
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the vif_states_lock spinlock
++ */
++int netfront_check_accelerator_queue_ready(struct net_device *dev,
++					   struct netfront_info *np)
++{
++	struct netfront_accelerator *accelerator;
++	int rc = 1;
++	unsigned long flags;
++
++	accelerator = np->accelerator;
++
++	/* Call the check_ready accelerator hook. */ 
++	if (np->accel_vif_state.hooks && accelerator) {
++		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
++		if (np->accel_vif_state.hooks &&
++		    np->accelerator == accelerator)
++			rc = np->accel_vif_state.hooks->check_ready(dev);
++		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
++	}
++
++	return rc;
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the vif_states_lock spinlock
++ */
++void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
++					     struct net_device *dev)
++{
++	struct netfront_accelerator *accelerator;
++	unsigned long flags;
++
++	accelerator = np->accelerator;
++
++	/* Call the stop_napi_interrupts accelerator hook. */
++	if (np->accel_vif_state.hooks && accelerator != NULL) {
++		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
++		if (np->accel_vif_state.hooks &&
++		    np->accelerator == accelerator)
++ 			np->accel_vif_state.hooks->stop_napi_irq(dev);
++		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
++	}
++}
++
++
++/*
++ * No lock pre-requisites.  Takes the vif_states_lock spinlock
++ */
++int netfront_accelerator_call_get_stats(struct netfront_info *np,
++					struct net_device *dev)
++{
++	struct netfront_accelerator *accelerator;
++	unsigned long flags;
++	int rc = 0;
++
++	accelerator = np->accelerator;
++
++	/* Call the get_stats accelerator hook. */
++	if (np->accel_vif_state.hooks && accelerator != NULL) {
++		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
++		if (np->accel_vif_state.hooks && 
++		    np->accelerator == accelerator)
++ 			rc = np->accel_vif_state.hooks->get_stats(dev,
++								  &np->stats);
++		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
++	}
++	return rc;
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,2247 @@
++/******************************************************************************
++ * Virtual network driver for conversing with remote driver backends.
++ *
++ * Copyright (c) 2002-2005, K A Fraser
++ * Copyright (c) 2005, 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.
++ */
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/init.h>
++#include <linux/bitops.h>
++#include <linux/ethtool.h>
++#include <linux/in.h>
++#include <linux/if_ether.h>
++#include <linux/io.h>
++#include <linux/moduleparam.h>
++#include <net/sock.h>
++#include <net/pkt_sched.h>
++#include <net/arp.h>
++#include <net/route.h>
++#include <asm/uaccess.h>
++#include <xen/evtchn.h>
++#include <xen/xenbus.h>
++#include <xen/interface/io/netif.h>
++#include <xen/interface/memory.h>
++#include <xen/balloon.h>
++#include <asm/page.h>
++#include <asm/maddr.h>
++#include <asm/uaccess.h>
++#include <xen/interface/grant_table.h>
++#include <xen/gnttab.h>
++
++struct netfront_cb {
++	struct page *page;
++	unsigned offset;
++};
++
++#define NETFRONT_SKB_CB(skb)	((struct netfront_cb *)((skb)->cb))
++
++#include "netfront.h"
++
++/*
++ * Mutually-exclusive module options to select receive data path:
++ *  rx_copy : Packets are copied by network backend into local memory
++ *  rx_flip : Page containing packet data is transferred to our ownership
++ * For fully-virtualised guests there is no option - copying must be used.
++ * For paravirtualised guests, flipping is the default.
++ */
++#ifdef CONFIG_XEN
++static int MODPARM_rx_copy = 0;
++module_param_named(rx_copy, MODPARM_rx_copy, bool, 0);
++MODULE_PARM_DESC(rx_copy, "Copy packets from network card (rather than flip)");
++static int MODPARM_rx_flip = 0;
++module_param_named(rx_flip, MODPARM_rx_flip, bool, 0);
++MODULE_PARM_DESC(rx_flip, "Flip packets from network card (rather than copy)");
++#else
++static const int MODPARM_rx_copy = 1;
++static const int MODPARM_rx_flip = 0;
++#endif
++
++#define RX_COPY_THRESHOLD 256
++
++/* If we don't have GSO, fake things up so that we never try to use it. */
++#if defined(NETIF_F_GSO)
++#define HAVE_GSO			1
++#define HAVE_TSO			1 /* TSO is a subset of GSO */
++#define HAVE_CSUM_OFFLOAD		1
++static inline void dev_disable_gso_features(struct net_device *dev)
++{
++	/* Turn off all GSO bits except ROBUST. */
++	dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
++	dev->features |= NETIF_F_GSO_ROBUST;
++}
++#elif defined(NETIF_F_TSO)
++#define HAVE_GSO		       0
++#define HAVE_TSO                       1
++
++/* Some older kernels cannot cope with incorrect checksums,
++ * particularly in netfilter. I'm not sure there is 100% correlation
++ * with the presence of NETIF_F_TSO but it appears to be a good first
++ * approximiation.
++ */
++#define HAVE_CSUM_OFFLOAD              0
++
++#define gso_size tso_size
++#define gso_segs tso_segs
++static inline void dev_disable_gso_features(struct net_device *dev)
++{
++       /* Turn off all TSO bits. */
++       dev->features &= ~NETIF_F_TSO;
++}
++static inline int skb_is_gso(const struct sk_buff *skb)
++{
++        return skb_shinfo(skb)->tso_size;
++}
++static inline int skb_gso_ok(struct sk_buff *skb, int features)
++{
++        return (features & NETIF_F_TSO);
++}
++
++static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
++{
++        return skb_is_gso(skb) &&
++               (!skb_gso_ok(skb, dev->features) ||
++                unlikely(skb->ip_summed != CHECKSUM_HW));
++}
++#else
++#define HAVE_GSO			0
++#define HAVE_TSO			0
++#define HAVE_CSUM_OFFLOAD		0
++#define netif_needs_gso(dev, skb)	0
++#define dev_disable_gso_features(dev)	((void)0)
++#define ethtool_op_set_tso(dev, data)	(-ENOSYS)
++#endif
++
++#define GRANT_INVALID_REF	0
++
++struct netfront_rx_info {
++	struct netif_rx_response rx;
++	struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
++};
++
++/*
++ * Implement our own carrier flag: the network stack's version causes delays
++ * when the carrier is re-enabled (in particular, dev_activate() may not
++ * immediately be called, which can cause packet loss).
++ */
++#define netfront_carrier_on(netif)	((netif)->carrier = 1)
++#define netfront_carrier_off(netif)	((netif)->carrier = 0)
++#define netfront_carrier_ok(netif)	((netif)->carrier)
++
++/*
++ * Access macros for acquiring freeing slots in tx_skbs[].
++ */
++
++static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id)
++{
++	list[id] = list[0];
++	list[0]  = (void *)(unsigned long)id;
++}
++
++static inline unsigned short get_id_from_freelist(struct sk_buff **list)
++{
++	unsigned int id = (unsigned int)(unsigned long)list[0];
++	list[0] = list[id];
++	return id;
++}
++
++static inline int xennet_rxidx(RING_IDX idx)
++{
++	return idx & (NET_RX_RING_SIZE - 1);
++}
++
++static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np,
++						RING_IDX ri)
++{
++	int i = xennet_rxidx(ri);
++	struct sk_buff *skb = np->rx_skbs[i];
++	np->rx_skbs[i] = NULL;
++	return skb;
++}
++
++static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np,
++					    RING_IDX ri)
++{
++	int i = xennet_rxidx(ri);
++	grant_ref_t ref = np->grant_rx_ref[i];
++	np->grant_rx_ref[i] = GRANT_INVALID_REF;
++	return ref;
++}
++
++#define DPRINTK(fmt, args...)				\
++	pr_debug("netfront (%s:%d) " fmt,		\
++		 __FUNCTION__, __LINE__, ##args)
++#define IPRINTK(fmt, args...)				\
++	printk(KERN_INFO "netfront: " fmt, ##args)
++#define WPRINTK(fmt, args...)				\
++	printk(KERN_WARNING "netfront: " fmt, ##args)
++
++static int setup_device(struct xenbus_device *, struct netfront_info *);
++static struct net_device *create_netdev(struct xenbus_device *);
++
++static void end_access(int, void *);
++static void netif_disconnect_backend(struct netfront_info *);
++
++static int network_connect(struct net_device *);
++static void network_tx_buf_gc(struct net_device *);
++static void network_alloc_rx_buffers(struct net_device *);
++static void send_fake_arp(struct net_device *);
++
++static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs);
++
++#ifdef CONFIG_SYSFS
++static int xennet_sysfs_addif(struct net_device *netdev);
++static void xennet_sysfs_delif(struct net_device *netdev);
++#else /* !CONFIG_SYSFS */
++#define xennet_sysfs_addif(dev) (0)
++#define xennet_sysfs_delif(dev) do { } while(0)
++#endif
++
++static inline int xennet_can_sg(struct net_device *dev)
++{
++	return dev->features & NETIF_F_SG;
++}
++
++/**
++ * Entry point to this code when a new device is created.  Allocate the basic
++ * structures and the ring buffers for communication with the backend, and
++ * inform the backend of the appropriate details for those.
++ */
++static int __devinit netfront_probe(struct xenbus_device *dev,
++				    const struct xenbus_device_id *id)
++{
++	int err;
++	struct net_device *netdev;
++	struct netfront_info *info;
++
++	netdev = create_netdev(dev);
++	if (IS_ERR(netdev)) {
++		err = PTR_ERR(netdev);
++		xenbus_dev_fatal(dev, err, "creating netdev");
++		return err;
++	}
++
++	info = netdev_priv(netdev);
++	dev->dev.driver_data = info;
++
++	err = register_netdev(info->netdev);
++	if (err) {
++		printk(KERN_WARNING "%s: register_netdev err=%d\n",
++		       __FUNCTION__, err);
++		goto fail;
++	}
++
++	err = xennet_sysfs_addif(info->netdev);
++	if (err) {
++		unregister_netdev(info->netdev);
++		printk(KERN_WARNING "%s: add sysfs failed err=%d\n",
++		       __FUNCTION__, err);
++		goto fail;
++	}
++
++	return 0;
++
++ fail:
++	free_netdev(netdev);
++	dev->dev.driver_data = NULL;
++	return err;
++}
++
++static int __devexit netfront_remove(struct xenbus_device *dev)
++{
++	struct netfront_info *info = dev->dev.driver_data;
++
++	DPRINTK("%s\n", dev->nodename);
++
++	netfront_accelerator_call_remove(info, dev);
++
++	netif_disconnect_backend(info);
++
++	del_timer_sync(&info->rx_refill_timer);
++
++	xennet_sysfs_delif(info->netdev);
++
++	unregister_netdev(info->netdev);
++
++	free_netdev(info->netdev);
++
++	return 0;
++}
++
++
++static int netfront_suspend(struct xenbus_device *dev)
++{
++	struct netfront_info *info = dev->dev.driver_data;
++	return netfront_accelerator_suspend(info, dev);
++}
++
++
++static int netfront_suspend_cancel(struct xenbus_device *dev)
++{
++	struct netfront_info *info = dev->dev.driver_data;
++	return netfront_accelerator_suspend_cancel(info, dev);
++}
++
++
++/**
++ * We are reconnecting to the backend, due to a suspend/resume, or a backend
++ * driver restart.  We tear down our netif structure and recreate it, but
++ * leave the device-layer structures intact so that this is transparent to the
++ * rest of the kernel.
++ */
++static int netfront_resume(struct xenbus_device *dev)
++{
++	struct netfront_info *info = dev->dev.driver_data;
++
++	DPRINTK("%s\n", dev->nodename);
++
++	netfront_accelerator_resume(info, dev);
++
++	netif_disconnect_backend(info);
++	return 0;
++}
++
++static int 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;
++}
++
++/* Common code used when first setting up, and when resuming. */
++static int talk_to_backend(struct xenbus_device *dev,
++			   struct netfront_info *info)
++{
++	const char *message;
++	struct xenbus_transaction xbt;
++	int err;
++
++	/* 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. */
++	err = setup_device(dev, info);
++	if (err)
++		goto out;
++
++	/* This will load an accelerator if one is configured when the
++	 * watch fires */
++	netfront_accelerator_add_watch(info);
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		goto destroy_ring;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
++			    info->tx_ring_ref);
++	if (err) {
++		message = "writing tx ring-ref";
++		goto abort_transaction;
++	}
++	err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
++			    info->rx_ring_ref);
++	if (err) {
++		message = "writing rx ring-ref";
++		goto abort_transaction;
++	}
++	err = xenbus_printf(xbt, dev->nodename,
++			    "event-channel", "%u",
++			    irq_to_evtchn_port(info->irq));
++	if (err) {
++		message = "writing event-channel";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
++			    info->copying_receiver);
++	if (err) {
++		message = "writing request-rx-copy";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
++	if (err) {
++		message = "writing feature-rx-notify";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-no-csum-offload",
++			    "%d", !HAVE_CSUM_OFFLOAD);
++	if (err) {
++		message = "writing feature-no-csum-offload";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
++	if (err) {
++		message = "writing feature-sg";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d",
++			    HAVE_TSO);
++	if (err) {
++		message = "writing feature-gso-tcpv4";
++		goto abort_transaction;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err) {
++		if (err == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, err, "completing transaction");
++		goto destroy_ring;
++	}
++
++	return 0;
++
++ abort_transaction:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, err, "%s", message);
++ destroy_ring:
++	netfront_accelerator_call_remove(info, dev);
++	netif_disconnect_backend(info);
++ out:
++	return err;
++}
++
++static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
++{
++	struct netif_tx_sring *txs;
++	struct netif_rx_sring *rxs;
++	int err;
++	struct net_device *netdev = info->netdev;
++
++	info->tx_ring_ref = GRANT_INVALID_REF;
++	info->rx_ring_ref = GRANT_INVALID_REF;
++	info->rx.sring = NULL;
++	info->tx.sring = NULL;
++	info->irq = 0;
++
++	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");
++		goto fail;
++	}
++	SHARED_RING_INIT(txs);
++	FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(txs));
++	if (err < 0) {
++		free_page((unsigned long)txs);
++		goto fail;
++	}
++	info->tx_ring_ref = err;
++
++	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");
++		goto fail;
++	}
++	SHARED_RING_INIT(rxs);
++	FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
++	if (err < 0) {
++		free_page((unsigned long)rxs);
++		goto fail;
++	}
++	info->rx_ring_ref = err;
++
++	memcpy(netdev->dev_addr, info->mac, ETH_ALEN);
++
++	err = bind_listening_port_to_irqhandler(
++		dev->otherend_id, netif_int, SA_SAMPLE_RANDOM, netdev->name,
++		netdev);
++	if (err < 0)
++		goto fail;
++	info->irq = err;
++
++	return 0;
++
++ fail:
++	return err;
++}
++
++/**
++ * Callback received when the backend's state changes.
++ */
++static void backend_changed(struct xenbus_device *dev,
++			    enum xenbus_state backend_state)
++{
++	struct netfront_info *np = dev->dev.driver_data;
++	struct net_device *netdev = np->netdev;
++
++	DPRINTK("%s\n", xenbus_strstate(backend_state));
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateConnected:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++		if (dev->state != XenbusStateInitialising)
++			break;
++		if (network_connect(netdev) != 0)
++			break;
++		xenbus_switch_state(dev, XenbusStateConnected);
++		send_fake_arp(netdev);
++		break;
++
++	case XenbusStateClosing:
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++/** Send a packet on a net device to encourage switches to learn the
++ * MAC. We send a fake ARP request.
++ *
++ * @param dev device
++ * @return 0 on success, error code otherwise
++ */
++static void send_fake_arp(struct net_device *dev)
++{
++#ifdef CONFIG_INET
++	struct sk_buff *skb;
++	u32             src_ip, dst_ip;
++
++	dst_ip = INADDR_BROADCAST;
++	src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK);
++
++	/* No IP? Then nothing to do. */
++	if (src_ip == 0)
++		return;
++
++	skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
++			 dst_ip, dev, src_ip,
++			 /*dst_hw*/ NULL, /*src_hw*/ NULL,
++			 /*target_hw*/ dev->dev_addr);
++	if (skb == NULL)
++		return;
++
++	dev_queue_xmit(skb);
++#endif
++}
++
++static inline int netfront_tx_slot_available(struct netfront_info *np)
++{
++	return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
++		(TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
++}
++
++
++static inline void network_maybe_wake_tx(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++
++	if (unlikely(netif_queue_stopped(dev)) &&
++	    netfront_tx_slot_available(np) &&
++	    likely(netif_running(dev)) &&
++	    netfront_check_accelerator_queue_ready(dev, np))
++		netif_wake_queue(dev);
++}
++
++
++int netfront_check_queue_ready(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++
++	return unlikely(netif_queue_stopped(dev)) &&
++		netfront_tx_slot_available(np) &&
++		likely(netif_running(dev));
++}
++EXPORT_SYMBOL(netfront_check_queue_ready);
++
++
++static int network_open(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++
++	memset(&np->stats, 0, sizeof(np->stats));
++
++	spin_lock_bh(&np->rx_lock);
++	if (netfront_carrier_ok(np)) {
++		network_alloc_rx_buffers(dev);
++		np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
++		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
++			netfront_accelerator_call_stop_napi_irq(np, dev);
++
++			netif_rx_schedule(dev);
++		}
++	}
++	spin_unlock_bh(&np->rx_lock);
++
++	network_maybe_wake_tx(dev);
++
++	return 0;
++}
++
++static void network_tx_buf_gc(struct net_device *dev)
++{
++	RING_IDX cons, prod;
++	unsigned short id;
++	struct netfront_info *np = netdev_priv(dev);
++	struct sk_buff *skb;
++
++	BUG_ON(!netfront_carrier_ok(np));
++
++	do {
++		prod = np->tx.sring->rsp_prod;
++		rmb(); /* Ensure we see responses up to 'rp'. */
++
++		for (cons = np->tx.rsp_cons; cons != prod; cons++) {
++			struct netif_tx_response *txrsp;
++
++			txrsp = RING_GET_RESPONSE(&np->tx, cons);
++			if (txrsp->status == NETIF_RSP_NULL)
++				continue;
++
++			id  = txrsp->id;
++			skb = np->tx_skbs[id];
++			if (unlikely(gnttab_query_foreign_access(
++				np->grant_tx_ref[id]) != 0)) {
++				printk(KERN_ALERT "network_tx_buf_gc: warning "
++				       "-- grant still in use by backend "
++				       "domain.\n");
++				BUG();
++			}
++			gnttab_end_foreign_access_ref(np->grant_tx_ref[id]);
++			gnttab_release_grant_reference(
++				&np->gref_tx_head, np->grant_tx_ref[id]);
++			np->grant_tx_ref[id] = GRANT_INVALID_REF;
++			add_id_to_freelist(np->tx_skbs, id);
++			dev_kfree_skb_irq(skb);
++		}
++
++		np->tx.rsp_cons = prod;
++
++		/*
++		 * Set a new event, then check for race with update of tx_cons.
++		 * Note that it is essential to schedule a callback, no matter
++		 * how few buffers are pending. Even if there is space in the
++		 * transmit ring, higher layers may be blocked because too much
++		 * data is outstanding: in such cases notification from Xen is
++		 * likely to be the only kick that we'll get.
++		 */
++		np->tx.sring->rsp_event =
++			prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
++		mb();
++	} while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
++
++	network_maybe_wake_tx(dev);
++}
++
++static void rx_refill_timeout(unsigned long data)
++{
++	struct net_device *dev = (struct net_device *)data;
++	struct netfront_info *np = netdev_priv(dev);
++
++	netfront_accelerator_call_stop_napi_irq(np, dev);
++
++	netif_rx_schedule(dev);
++}
++
++static void network_alloc_rx_buffers(struct net_device *dev)
++{
++	unsigned short id;
++	struct netfront_info *np = netdev_priv(dev);
++	struct sk_buff *skb;
++	struct page *page;
++	int i, batch_target, notify;
++	RING_IDX req_prod = np->rx.req_prod_pvt;
++	struct xen_memory_reservation reservation;
++	grant_ref_t ref;
++ 	unsigned long pfn;
++ 	void *vaddr;
++	int nr_flips;
++	netif_rx_request_t *req;
++
++	if (unlikely(!netfront_carrier_ok(np)))
++		return;
++
++	/*
++	 * Allocate skbuffs greedily, even though we batch updates to the
++	 * receive ring. This creates a less bursty demand on the memory
++	 * allocator, so should reduce the chance of failed allocation requests
++	 * both for ourself and for other kernel subsystems.
++	 */
++	batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
++	for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
++		/*
++		 * Allocate an skb and a page. Do not use __dev_alloc_skb as
++		 * that will allocate page-sized buffers which is not
++		 * necessary here.
++		 * 16 bytes added as necessary headroom for netif_receive_skb.
++		 */
++		skb = alloc_skb(RX_COPY_THRESHOLD + 16 + NET_IP_ALIGN,
++				GFP_ATOMIC | __GFP_NOWARN);
++		if (unlikely(!skb))
++			goto no_skb;
++
++		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
++		if (!page) {
++			kfree_skb(skb);
++no_skb:
++			/* Any skbuffs queued for refill? Force them out. */
++			if (i != 0)
++				goto refill;
++			/* Could not allocate any skbuffs. Try again later. */
++			mod_timer(&np->rx_refill_timer,
++				  jiffies + (HZ/10));
++			break;
++		}
++
++		skb_reserve(skb, 16 + NET_IP_ALIGN); /* mimic dev_alloc_skb() */
++		skb_shinfo(skb)->frags[0].page = page;
++		skb_shinfo(skb)->nr_frags = 1;
++		__skb_queue_tail(&np->rx_batch, skb);
++	}
++
++	/* Is the batch large enough to be worthwhile? */
++	if (i < (np->rx_target/2)) {
++		if (req_prod > np->rx.sring->req_prod)
++			goto push;
++		return;
++	}
++
++	/* Adjust our fill target if we risked running out of buffers. */
++	if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
++	    ((np->rx_target *= 2) > np->rx_max_target))
++		np->rx_target = np->rx_max_target;
++
++ refill:
++	for (nr_flips = i = 0; ; i++) {
++		if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
++			break;
++
++		skb->dev = dev;
++
++		id = xennet_rxidx(req_prod + i);
++
++		BUG_ON(np->rx_skbs[id]);
++		np->rx_skbs[id] = skb;
++
++		ref = gnttab_claim_grant_reference(&np->gref_rx_head);
++		BUG_ON((signed short)ref < 0);
++		np->grant_rx_ref[id] = ref;
++
++		pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
++		vaddr = page_address(skb_shinfo(skb)->frags[0].page);
++
++		req = RING_GET_REQUEST(&np->rx, req_prod + i);
++		if (!np->copying_receiver) {
++			gnttab_grant_foreign_transfer_ref(ref,
++							  np->xbdev->otherend_id,
++							  pfn);
++			np->rx_pfn_array[nr_flips] = pfn_to_mfn(pfn);
++			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++				/* Remove this page before passing
++				 * back to Xen. */
++				set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
++				MULTI_update_va_mapping(np->rx_mcl+i,
++							(unsigned long)vaddr,
++							__pte(0), 0);
++			}
++			nr_flips++;
++		} else {
++			gnttab_grant_foreign_access_ref(ref,
++							np->xbdev->otherend_id,
++							pfn_to_mfn(pfn),
++							0);
++		}
++
++		req->id = id;
++		req->gref = ref;
++	}
++
++	if ( nr_flips != 0 ) {
++		/* Tell the ballon driver what is going on. */
++		balloon_update_driver_allowance(i);
++
++		set_xen_guest_handle(reservation.extent_start,
++				     np->rx_pfn_array);
++		reservation.nr_extents   = nr_flips;
++		reservation.extent_order = 0;
++		reservation.address_bits = 0;
++		reservation.domid        = DOMID_SELF;
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* After all PTEs have been zapped, flush the TLB. */
++			np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
++				UVMF_TLB_FLUSH|UVMF_ALL;
++
++			/* Give away a batch of pages. */
++			np->rx_mcl[i].op = __HYPERVISOR_memory_op;
++			np->rx_mcl[i].args[0] = XENMEM_decrease_reservation;
++			np->rx_mcl[i].args[1] = (unsigned long)&reservation;
++
++			/* Zap PTEs and give away pages in one big
++			 * multicall. */
++			if (unlikely(HYPERVISOR_multicall(np->rx_mcl, i+1)))
++				BUG();
++
++			/* Check return status of HYPERVISOR_memory_op(). */
++			if (unlikely(np->rx_mcl[i].result != i))
++				panic("Unable to reduce memory reservation\n");
++			while (nr_flips--)
++				BUG_ON(np->rx_mcl[nr_flips].result);
++		} else {
++			if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
++						 &reservation) != i)
++				panic("Unable to reduce memory reservation\n");
++		}
++	} else {
++		wmb();
++	}
++
++	/* Above is a suitable barrier to ensure backend will see requests. */
++	np->rx.req_prod_pvt = req_prod + i;
++ push:
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
++	if (notify)
++		notify_remote_via_irq(np->irq);
++}
++
++static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
++			      struct netif_tx_request *tx)
++{
++	struct netfront_info *np = netdev_priv(dev);
++	char *data = skb->data;
++	unsigned long mfn;
++	RING_IDX prod = np->tx.req_prod_pvt;
++	int frags = skb_shinfo(skb)->nr_frags;
++	unsigned int offset = offset_in_page(data);
++	unsigned int len = skb_headlen(skb);
++	unsigned int id;
++	grant_ref_t ref;
++	int i;
++
++	while (len > PAGE_SIZE - offset) {
++		tx->size = PAGE_SIZE - offset;
++		tx->flags |= NETTXF_more_data;
++		len -= tx->size;
++		data += tx->size;
++		offset = 0;
++
++		id = get_id_from_freelist(np->tx_skbs);
++		np->tx_skbs[id] = skb_get(skb);
++		tx = RING_GET_REQUEST(&np->tx, prod++);
++		tx->id = id;
++		ref = gnttab_claim_grant_reference(&np->gref_tx_head);
++		BUG_ON((signed short)ref < 0);
++
++		mfn = virt_to_mfn(data);
++		gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
++						mfn, GTF_readonly);
++
++		tx->gref = np->grant_tx_ref[id] = ref;
++		tx->offset = offset;
++		tx->size = len;
++		tx->flags = 0;
++	}
++
++	for (i = 0; i < frags; i++) {
++		skb_frag_t *frag = skb_shinfo(skb)->frags + i;
++
++		tx->flags |= NETTXF_more_data;
++
++		id = get_id_from_freelist(np->tx_skbs);
++		np->tx_skbs[id] = skb_get(skb);
++		tx = RING_GET_REQUEST(&np->tx, prod++);
++		tx->id = id;
++		ref = gnttab_claim_grant_reference(&np->gref_tx_head);
++		BUG_ON((signed short)ref < 0);
++
++		mfn = pfn_to_mfn(page_to_pfn(frag->page));
++		gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
++						mfn, GTF_readonly);
++
++		tx->gref = np->grant_tx_ref[id] = ref;
++		tx->offset = frag->page_offset;
++		tx->size = frag->size;
++		tx->flags = 0;
++	}
++
++	np->tx.req_prod_pvt = prod;
++}
++
++static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	unsigned short id;
++	struct netfront_info *np = netdev_priv(dev);
++	struct netif_tx_request *tx;
++	struct netif_extra_info *extra;
++	char *data = skb->data;
++	RING_IDX i;
++	grant_ref_t ref;
++	unsigned long mfn;
++	int notify;
++	int frags = skb_shinfo(skb)->nr_frags;
++	unsigned int offset = offset_in_page(data);
++	unsigned int len = skb_headlen(skb);
++
++	/* Check the fast path, if hooks are available */
++ 	if (np->accel_vif_state.hooks && 
++ 	    np->accel_vif_state.hooks->start_xmit(skb, dev)) { 
++ 		/* Fast path has sent this packet */ 
++ 		return 0; 
++ 	} 
++
++	frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
++	if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
++		printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
++		       frags);
++		dump_stack();
++		goto drop;
++	}
++
++	spin_lock_irq(&np->tx_lock);
++
++	if (unlikely(!netfront_carrier_ok(np) ||
++		     (frags > 1 && !xennet_can_sg(dev)) ||
++		     netif_needs_gso(dev, skb))) {
++		spin_unlock_irq(&np->tx_lock);
++		goto drop;
++	}
++
++	i = np->tx.req_prod_pvt;
++
++	id = get_id_from_freelist(np->tx_skbs);
++	np->tx_skbs[id] = skb;
++
++	tx = RING_GET_REQUEST(&np->tx, i);
++
++	tx->id   = id;
++	ref = gnttab_claim_grant_reference(&np->gref_tx_head);
++	BUG_ON((signed short)ref < 0);
++	mfn = virt_to_mfn(data);
++	gnttab_grant_foreign_access_ref(
++		ref, np->xbdev->otherend_id, mfn, GTF_readonly);
++	tx->gref = np->grant_tx_ref[id] = ref;
++	tx->offset = offset;
++	tx->size = len;
++
++	tx->flags = 0;
++	extra = NULL;
++
++	if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
++		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
++#ifdef CONFIG_XEN
++	if (skb->proto_data_valid) /* remote but checksummed? */
++		tx->flags |= NETTXF_data_validated;
++#endif
++
++#if HAVE_TSO
++	if (skb_shinfo(skb)->gso_size) {
++		struct netif_extra_info *gso = (struct netif_extra_info *)
++			RING_GET_REQUEST(&np->tx, ++i);
++
++		if (extra)
++			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
++		else
++			tx->flags |= NETTXF_extra_info;
++
++		gso->u.gso.size = skb_shinfo(skb)->gso_size;
++		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
++		gso->u.gso.pad = 0;
++		gso->u.gso.features = 0;
++
++		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
++		gso->flags = 0;
++		extra = gso;
++	}
++#endif
++
++	np->tx.req_prod_pvt = i + 1;
++
++	xennet_make_frags(skb, dev, tx);
++	tx->size = skb->len;
++
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
++	if (notify)
++		notify_remote_via_irq(np->irq);
++
++	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);
++
++	if (!netfront_tx_slot_available(np))
++		netif_stop_queue(dev);
++
++	spin_unlock_irq(&np->tx_lock);
++
++	return 0;
++
++ drop:
++	np->stats.tx_dropped++;
++	dev_kfree_skb(skb);
++	return 0;
++}
++
++static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
++{
++	struct net_device *dev = dev_id;
++	struct netfront_info *np = netdev_priv(dev);
++	unsigned long flags;
++
++	spin_lock_irqsave(&np->tx_lock, flags);
++
++	if (likely(netfront_carrier_ok(np))) {
++		network_tx_buf_gc(dev);
++		/* Under tx_lock: protects access to rx shared-ring indexes. */
++		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
++			netfront_accelerator_call_stop_napi_irq(np, dev);
++
++			netif_rx_schedule(dev);
++			dev->last_rx = jiffies;
++		}
++	}
++
++	spin_unlock_irqrestore(&np->tx_lock, flags);
++
++	return IRQ_HANDLED;
++}
++
++static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
++				grant_ref_t ref)
++{
++	int new = xennet_rxidx(np->rx.req_prod_pvt);
++
++	BUG_ON(np->rx_skbs[new]);
++	np->rx_skbs[new] = skb;
++	np->grant_rx_ref[new] = ref;
++	RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new;
++	RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref;
++	np->rx.req_prod_pvt++;
++}
++
++int xennet_get_extras(struct netfront_info *np,
++		      struct netif_extra_info *extras, RING_IDX rp)
++
++{
++	struct netif_extra_info *extra;
++	RING_IDX cons = np->rx.rsp_cons;
++	int err = 0;
++
++	do {
++		struct sk_buff *skb;
++		grant_ref_t ref;
++
++		if (unlikely(cons + 1 == rp)) {
++			if (net_ratelimit())
++				WPRINTK("Missing extra info\n");
++			err = -EBADR;
++			break;
++		}
++
++		extra = (struct netif_extra_info *)
++			RING_GET_RESPONSE(&np->rx, ++cons);
++
++		if (unlikely(!extra->type ||
++			     extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
++			if (net_ratelimit())
++				WPRINTK("Invalid extra type: %d\n",
++					extra->type);
++			err = -EINVAL;
++		} else {
++			memcpy(&extras[extra->type - 1], extra,
++			       sizeof(*extra));
++		}
++
++		skb = xennet_get_rx_skb(np, cons);
++		ref = xennet_get_rx_ref(np, cons);
++		xennet_move_rx_slot(np, skb, ref);
++	} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
++
++	np->rx.rsp_cons = cons;
++	return err;
++}
++
++static int xennet_get_responses(struct netfront_info *np,
++				struct netfront_rx_info *rinfo, RING_IDX rp,
++				struct sk_buff_head *list,
++				int *pages_flipped_p)
++{
++	int pages_flipped = *pages_flipped_p;
++	struct mmu_update *mmu;
++	struct multicall_entry *mcl;
++	struct netif_rx_response *rx = &rinfo->rx;
++	struct netif_extra_info *extras = rinfo->extras;
++	RING_IDX cons = np->rx.rsp_cons;
++	struct sk_buff *skb = xennet_get_rx_skb(np, cons);
++	grant_ref_t ref = xennet_get_rx_ref(np, cons);
++	int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
++	int frags = 1;
++	int err = 0;
++	unsigned long ret;
++
++	if (rx->flags & NETRXF_extra_info) {
++		err = xennet_get_extras(np, extras, rp);
++		cons = np->rx.rsp_cons;
++	}
++
++	for (;;) {
++		unsigned long mfn;
++
++		if (unlikely(rx->status < 0 ||
++			     rx->offset + rx->status > PAGE_SIZE)) {
++			if (net_ratelimit())
++				WPRINTK("rx->offset: %x, size: %u\n",
++					rx->offset, rx->status);
++			xennet_move_rx_slot(np, skb, ref);
++			err = -EINVAL;
++			goto next;
++		}
++
++		/*
++		 * This definitely indicates a bug, either in this driver or in
++		 * the backend driver. In future this should flag the bad
++		 * situation to the system controller to reboot the backed.
++		 */
++		if (ref == GRANT_INVALID_REF) {
++			if (net_ratelimit())
++				WPRINTK("Bad rx response id %d.\n", rx->id);
++			err = -EINVAL;
++			goto next;
++		}
++
++		if (!np->copying_receiver) {
++			/* Memory pressure, insufficient buffer
++			 * headroom, ... */
++			if (!(mfn = gnttab_end_foreign_transfer_ref(ref))) {
++				if (net_ratelimit())
++					WPRINTK("Unfulfilled rx req "
++						"(id=%d, st=%d).\n",
++						rx->id, rx->status);
++				xennet_move_rx_slot(np, skb, ref);
++				err = -ENOMEM;
++				goto next;
++			}
++
++			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++				/* Remap the page. */
++				struct page *page =
++					skb_shinfo(skb)->frags[0].page;
++				unsigned long pfn = page_to_pfn(page);
++				void *vaddr = page_address(page);
++
++				mcl = np->rx_mcl + pages_flipped;
++				mmu = np->rx_mmu + pages_flipped;
++
++				MULTI_update_va_mapping(mcl,
++							(unsigned long)vaddr,
++							pfn_pte_ma(mfn,
++								   PAGE_KERNEL),
++							0);
++				mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
++					| MMU_MACHPHYS_UPDATE;
++				mmu->val = pfn;
++
++				set_phys_to_machine(pfn, mfn);
++			}
++			pages_flipped++;
++		} else {
++			ret = gnttab_end_foreign_access_ref(ref);
++			BUG_ON(!ret);
++		}
++
++		gnttab_release_grant_reference(&np->gref_rx_head, ref);
++
++		__skb_queue_tail(list, skb);
++
++next:
++		if (!(rx->flags & NETRXF_more_data))
++			break;
++
++		if (cons + frags == rp) {
++			if (net_ratelimit())
++				WPRINTK("Need more frags\n");
++			err = -ENOENT;
++			break;
++		}
++
++		rx = RING_GET_RESPONSE(&np->rx, cons + frags);
++		skb = xennet_get_rx_skb(np, cons + frags);
++		ref = xennet_get_rx_ref(np, cons + frags);
++		frags++;
++	}
++
++	if (unlikely(frags > max)) {
++		if (net_ratelimit())
++			WPRINTK("Too many frags\n");
++		err = -E2BIG;
++	}
++
++	if (unlikely(err))
++		np->rx.rsp_cons = cons + frags;
++
++	*pages_flipped_p = pages_flipped;
++
++	return err;
++}
++
++static RING_IDX xennet_fill_frags(struct netfront_info *np,
++				  struct sk_buff *skb,
++				  struct sk_buff_head *list)
++{
++	struct skb_shared_info *shinfo = skb_shinfo(skb);
++	int nr_frags = shinfo->nr_frags;
++	RING_IDX cons = np->rx.rsp_cons;
++	skb_frag_t *frag = shinfo->frags + nr_frags;
++	struct sk_buff *nskb;
++
++	while ((nskb = __skb_dequeue(list))) {
++		struct netif_rx_response *rx =
++			RING_GET_RESPONSE(&np->rx, ++cons);
++
++		frag->page = skb_shinfo(nskb)->frags[0].page;
++		frag->page_offset = rx->offset;
++		frag->size = rx->status;
++
++		skb->data_len += rx->status;
++
++		skb_shinfo(nskb)->nr_frags = 0;
++		kfree_skb(nskb);
++
++		frag++;
++		nr_frags++;
++	}
++
++	shinfo->nr_frags = nr_frags;
++	return cons;
++}
++
++static int xennet_set_skb_gso(struct sk_buff *skb,
++			      struct netif_extra_info *gso)
++{
++	if (!gso->u.gso.size) {
++		if (net_ratelimit())
++			WPRINTK("GSO size must not be zero.\n");
++		return -EINVAL;
++	}
++
++	/* Currently only TCPv4 S.O. is supported. */
++	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
++		if (net_ratelimit())
++			WPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
++		return -EINVAL;
++	}
++
++#if HAVE_TSO
++	skb_shinfo(skb)->gso_size = gso->u.gso.size;
++#if HAVE_GSO
++	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
++
++	/* Header must be checked, and gso_segs computed. */
++	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
++#endif
++	skb_shinfo(skb)->gso_segs = 0;
++
++	return 0;
++#else
++	if (net_ratelimit())
++		WPRINTK("GSO unsupported by this kernel.\n");
++	return -EINVAL;
++#endif
++}
++
++static int netif_poll(struct net_device *dev, int *pbudget)
++{
++	struct netfront_info *np = netdev_priv(dev);
++	struct sk_buff *skb;
++	struct netfront_rx_info rinfo;
++	struct netif_rx_response *rx = &rinfo.rx;
++	struct netif_extra_info *extras = rinfo.extras;
++	RING_IDX i, rp;
++	struct multicall_entry *mcl;
++	int work_done, budget, more_to_do = 1, accel_more_to_do = 1;
++	struct sk_buff_head rxq;
++	struct sk_buff_head errq;
++	struct sk_buff_head tmpq;
++	unsigned long flags;
++	unsigned int len;
++	int pages_flipped = 0;
++	int err;
++
++	spin_lock(&np->rx_lock); /* no need for spin_lock_bh() in ->poll() */
++
++	if (unlikely(!netfront_carrier_ok(np))) {
++		spin_unlock(&np->rx_lock);
++		return 0;
++	}
++
++	skb_queue_head_init(&rxq);
++	skb_queue_head_init(&errq);
++	skb_queue_head_init(&tmpq);
++
++	if ((budget = *pbudget) > dev->quota)
++		budget = dev->quota;
++	rp = np->rx.sring->rsp_prod;
++	rmb(); /* Ensure we see queued responses up to 'rp'. */
++
++	i = np->rx.rsp_cons;
++	work_done = 0;
++	while ((i != rp) && (work_done < budget)) {
++		memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
++		memset(extras, 0, sizeof(rinfo.extras));
++
++		err = xennet_get_responses(np, &rinfo, rp, &tmpq,
++					   &pages_flipped);
++
++		if (unlikely(err)) {
++err:	
++			while ((skb = __skb_dequeue(&tmpq)))
++				__skb_queue_tail(&errq, skb);
++			np->stats.rx_errors++;
++			i = np->rx.rsp_cons;
++			continue;
++		}
++
++		skb = __skb_dequeue(&tmpq);
++
++		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
++			struct netif_extra_info *gso;
++			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
++
++			if (unlikely(xennet_set_skb_gso(skb, gso))) {
++				__skb_queue_head(&tmpq, skb);
++				np->rx.rsp_cons += skb_queue_len(&tmpq);
++				goto err;
++			}
++		}
++
++		NETFRONT_SKB_CB(skb)->page = skb_shinfo(skb)->frags[0].page;
++		NETFRONT_SKB_CB(skb)->offset = rx->offset;
++
++		len = rx->status;
++		if (len > RX_COPY_THRESHOLD)
++			len = RX_COPY_THRESHOLD;
++		skb_put(skb, len);
++
++		if (rx->status > len) {
++			skb_shinfo(skb)->frags[0].page_offset =
++				rx->offset + len;
++			skb_shinfo(skb)->frags[0].size = rx->status - len;
++			skb->data_len = rx->status - len;
++		} else {
++			skb_shinfo(skb)->frags[0].page = NULL;
++			skb_shinfo(skb)->nr_frags = 0;
++		}
++
++		i = xennet_fill_frags(np, skb, &tmpq);
++
++		/*
++		 * Truesize must approximates the size of true data plus
++		 * any supervisor overheads. Adding hypervisor overheads
++		 * has been shown to significantly reduce achievable
++		 * bandwidth with the default receive buffer size. It is
++		 * therefore not wise to account for it here.
++		 *
++		 * After alloc_skb(RX_COPY_THRESHOLD), truesize is set to
++		 * RX_COPY_THRESHOLD + the supervisor overheads. Here, we
++		 * add the size of the data pulled in xennet_fill_frags().
++		 *
++		 * We also adjust for any unused space in the main data
++		 * area by subtracting (RX_COPY_THRESHOLD - len). This is
++		 * especially important with drivers which split incoming
++		 * packets into header and data, using only 66 bytes of
++		 * the main data area (see the e1000 driver for example.)
++		 * On such systems, without this last adjustement, our
++		 * achievable receive throughout using the standard receive
++		 * buffer size was cut by 25%(!!!).
++		 */
++		skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
++		skb->len += skb->data_len;
++
++		/*
++		 * Old backends do not assert data_validated but we
++		 * can infer it from csum_blank so test both flags.
++		 */
++		if (rx->flags & (NETRXF_data_validated|NETRXF_csum_blank))
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++		else
++			skb->ip_summed = CHECKSUM_NONE;
++#ifdef CONFIG_XEN
++		skb->proto_data_valid = (skb->ip_summed != CHECKSUM_NONE);
++		skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
++#endif
++		np->stats.rx_packets++;
++		np->stats.rx_bytes += skb->len;
++
++		__skb_queue_tail(&rxq, skb);
++
++		np->rx.rsp_cons = ++i;
++		work_done++;
++	}
++
++	if (pages_flipped) {
++		/* Some pages are no longer absent... */
++		balloon_update_driver_allowance(-pages_flipped);
++
++		/* Do all the remapping work and M2P updates. */
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			mcl = np->rx_mcl + pages_flipped;
++			mcl->op = __HYPERVISOR_mmu_update;
++			mcl->args[0] = (unsigned long)np->rx_mmu;
++			mcl->args[1] = pages_flipped;
++			mcl->args[2] = 0;
++			mcl->args[3] = DOMID_SELF;
++			err = HYPERVISOR_multicall_check(np->rx_mcl,
++							 pages_flipped + 1,
++							 NULL);
++			BUG_ON(err);
++		}
++	}
++
++	while ((skb = __skb_dequeue(&errq)))
++		kfree_skb(skb);
++
++	while ((skb = __skb_dequeue(&rxq)) != NULL) {
++		struct page *page = NETFRONT_SKB_CB(skb)->page;
++		void *vaddr = page_address(page);
++		unsigned offset = NETFRONT_SKB_CB(skb)->offset;
++
++		memcpy(skb->data, vaddr + offset, skb_headlen(skb));
++
++		if (page != skb_shinfo(skb)->frags[0].page)
++			__free_page(page);
++
++		/* Ethernet work: Delayed to here as it peeks the header. */
++		skb->protocol = eth_type_trans(skb, dev);
++
++		/* Pass it up. */
++		netif_receive_skb(skb);
++		dev->last_rx = jiffies;
++	}
++
++	/* If we get a callback with very few responses, reduce fill target. */
++	/* NB. Note exponential increase, linear decrease. */
++	if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) >
++	     ((3*np->rx_target) / 4)) &&
++	    (--np->rx_target < np->rx_min_target))
++		np->rx_target = np->rx_min_target;
++
++	network_alloc_rx_buffers(dev);
++
++	if (work_done < budget) {
++		/* there's some spare capacity, try the accelerated path */
++		int accel_budget = budget - work_done;
++		int accel_budget_start = accel_budget;
++
++ 		if (np->accel_vif_state.hooks) { 
++ 			accel_more_to_do =  
++ 				np->accel_vif_state.hooks->netdev_poll 
++ 				(dev, &accel_budget); 
++ 			work_done += (accel_budget_start - accel_budget); 
++ 		} else
++			accel_more_to_do = 0;
++	}
++
++	*pbudget   -= work_done;
++	dev->quota -= work_done;
++
++	if (work_done < budget) {
++		local_irq_save(flags);
++
++		RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
++
++		if (!more_to_do && !accel_more_to_do && 
++		    np->accel_vif_state.hooks) {
++			/* 
++			 *  Slow path has nothing more to do, see if
++			 *  fast path is likewise
++			 */
++			accel_more_to_do = 
++				np->accel_vif_state.hooks->start_napi_irq(dev);
++		}
++
++		if (!more_to_do && !accel_more_to_do)
++			__netif_rx_complete(dev);
++
++		local_irq_restore(flags);
++	}
++
++	spin_unlock(&np->rx_lock);
++	
++	return more_to_do | accel_more_to_do;
++}
++
++static void netif_release_tx_bufs(struct netfront_info *np)
++{
++	struct sk_buff *skb;
++	int i;
++
++	for (i = 1; i <= NET_TX_RING_SIZE; i++) {
++		if ((unsigned long)np->tx_skbs[i] < PAGE_OFFSET)
++			continue;
++
++		skb = np->tx_skbs[i];
++		gnttab_end_foreign_access_ref(np->grant_tx_ref[i]);
++		gnttab_release_grant_reference(
++			&np->gref_tx_head, np->grant_tx_ref[i]);
++		np->grant_tx_ref[i] = GRANT_INVALID_REF;
++		add_id_to_freelist(np->tx_skbs, i);
++		dev_kfree_skb_irq(skb);
++	}
++}
++
++static void netif_release_rx_bufs_flip(struct netfront_info *np)
++{
++	struct mmu_update      *mmu = np->rx_mmu;
++	struct multicall_entry *mcl = np->rx_mcl;
++	struct sk_buff_head free_list;
++	struct sk_buff *skb;
++	unsigned long mfn;
++	int xfer = 0, noxfer = 0, unused = 0;
++	int id, ref, rc;
++
++	skb_queue_head_init(&free_list);
++
++	spin_lock_bh(&np->rx_lock);
++
++	for (id = 0; id < NET_RX_RING_SIZE; id++) {
++		if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
++			unused++;
++			continue;
++		}
++
++		skb = np->rx_skbs[id];
++		mfn = gnttab_end_foreign_transfer_ref(ref);
++		gnttab_release_grant_reference(&np->gref_rx_head, ref);
++		np->grant_rx_ref[id] = GRANT_INVALID_REF;
++		add_id_to_freelist(np->rx_skbs, id);
++
++		if (0 == mfn) {
++			struct page *page = skb_shinfo(skb)->frags[0].page;
++			balloon_release_driver_page(page);
++			skb_shinfo(skb)->nr_frags = 0;
++			dev_kfree_skb(skb);
++			noxfer++;
++			continue;
++		}
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* Remap the page. */
++			struct page *page = skb_shinfo(skb)->frags[0].page;
++			unsigned long pfn = page_to_pfn(page);
++			void *vaddr = page_address(page);
++
++			MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
++						pfn_pte_ma(mfn, PAGE_KERNEL),
++						0);
++			mcl++;
++			mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
++				| MMU_MACHPHYS_UPDATE;
++			mmu->val = pfn;
++			mmu++;
++
++			set_phys_to_machine(pfn, mfn);
++		}
++		__skb_queue_tail(&free_list, skb);
++		xfer++;
++	}
++
++	DPRINTK("%s: %d xfer, %d noxfer, %d unused\n",
++		__FUNCTION__, xfer, noxfer, unused);
++
++	if (xfer) {
++		/* Some pages are no longer absent... */
++		balloon_update_driver_allowance(-xfer);
++
++		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++			/* Do all the remapping work and M2P updates. */
++			mcl->op = __HYPERVISOR_mmu_update;
++			mcl->args[0] = (unsigned long)np->rx_mmu;
++			mcl->args[1] = mmu - np->rx_mmu;
++			mcl->args[2] = 0;
++			mcl->args[3] = DOMID_SELF;
++			mcl++;
++			rc = HYPERVISOR_multicall_check(
++				np->rx_mcl, mcl - np->rx_mcl, NULL);
++			BUG_ON(rc);
++		}
++	}
++
++	while ((skb = __skb_dequeue(&free_list)) != NULL)
++		dev_kfree_skb(skb);
++
++	spin_unlock_bh(&np->rx_lock);
++}
++
++static void netif_release_rx_bufs_copy(struct netfront_info *np)
++{
++	struct sk_buff *skb;
++	int i, ref;
++	int busy = 0, inuse = 0;
++
++	spin_lock_bh(&np->rx_lock);
++
++	for (i = 0; i < NET_RX_RING_SIZE; i++) {
++		ref = np->grant_rx_ref[i];
++
++		if (ref == GRANT_INVALID_REF)
++			continue;
++
++		inuse++;
++
++		skb = np->rx_skbs[i];
++
++		if (!gnttab_end_foreign_access_ref(ref))
++		{
++			busy++;
++			continue;
++		}
++
++		gnttab_release_grant_reference(&np->gref_rx_head, ref);
++		np->grant_rx_ref[i] = GRANT_INVALID_REF;
++		add_id_to_freelist(np->rx_skbs, i);
++
++		dev_kfree_skb(skb);
++	}
++
++	if (busy)
++		DPRINTK("%s: Unable to release %d of %d inuse grant references out of %ld total.\n",
++			__FUNCTION__, busy, inuse, NET_RX_RING_SIZE);
++
++	spin_unlock_bh(&np->rx_lock);
++}
++
++static int network_close(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++	netif_stop_queue(np->netdev);
++	return 0;
++}
++
++
++static struct net_device_stats *network_get_stats(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++
++	netfront_accelerator_call_get_stats(np, dev);
++	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;
++
++	if (mtu > max)
++		return -EINVAL;
++	dev->mtu = mtu;
++	return 0;
++}
++
++static int xennet_set_sg(struct net_device *dev, u32 data)
++{
++	if (data) {
++		struct netfront_info *np = netdev_priv(dev);
++		int val;
++
++		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg",
++				 "%d", &val) < 0)
++			val = 0;
++		if (!val)
++			return -ENOSYS;
++	} else if (dev->mtu > ETH_DATA_LEN)
++		dev->mtu = ETH_DATA_LEN;
++
++	return ethtool_op_set_sg(dev, data);
++}
++
++static int xennet_set_tso(struct net_device *dev, u32 data)
++{
++	if (data) {
++		struct netfront_info *np = netdev_priv(dev);
++		int val;
++
++		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
++				 "feature-gso-tcpv4", "%d", &val) < 0)
++			val = 0;
++		if (!val)
++			return -ENOSYS;
++	}
++
++	return ethtool_op_set_tso(dev, data);
++}
++
++static void xennet_set_features(struct net_device *dev)
++{
++	dev_disable_gso_features(dev);
++	xennet_set_sg(dev, 0);
++
++	/* We need checksum offload to enable scatter/gather and TSO. */
++	if (!(dev->features & NETIF_F_IP_CSUM))
++		return;
++
++	if (xennet_set_sg(dev, 1))
++		return;
++
++	/* Before 2.6.9 TSO seems to be unreliable so do not enable it
++	 * on older kernels.
++	 */
++	if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9))
++		xennet_set_tso(dev, 1);
++}
++
++static int network_connect(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++	int i, requeue_idx, err;
++	struct sk_buff *skb;
++	grant_ref_t ref;
++	netif_rx_request_t *req;
++	unsigned int feature_rx_copy, feature_rx_flip;
++
++	err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
++			   "feature-rx-copy", "%u", &feature_rx_copy);
++	if (err != 1)
++		feature_rx_copy = 0;
++	err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
++			   "feature-rx-flip", "%u", &feature_rx_flip);
++	if (err != 1)
++		feature_rx_flip = 1;
++
++	/*
++	 * Copy packets on receive path if:
++	 *  (a) This was requested by user, and the backend supports it; or
++	 *  (b) Flipping was requested, but this is unsupported by the backend.
++	 */
++	np->copying_receiver = ((MODPARM_rx_copy && feature_rx_copy) ||
++				(MODPARM_rx_flip && !feature_rx_flip));
++
++	err = talk_to_backend(np->xbdev, np);
++	if (err)
++		return err;
++
++	xennet_set_features(dev);
++
++	DPRINTK("device %s has %sing receive path.\n",
++		dev->name, np->copying_receiver ? "copy" : "flipp");
++
++	spin_lock_bh(&np->rx_lock);
++	spin_lock_irq(&np->tx_lock);
++
++	/*
++	 * Recovery procedure:
++	 *  NB. Freelist index entries are always going to be less than
++	 *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
++	 *  greater than PAGE_OFFSET: we use this property to distinguish
++	 *  them.
++	 */
++
++	/* Step 1: Discard all pending TX packet fragments. */
++	netif_release_tx_bufs(np);
++
++	/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
++	for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
++		if (!np->rx_skbs[i])
++			continue;
++
++		skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
++		ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
++		req = RING_GET_REQUEST(&np->rx, requeue_idx);
++
++		if (!np->copying_receiver) {
++			gnttab_grant_foreign_transfer_ref(
++				ref, np->xbdev->otherend_id,
++				page_to_pfn(skb_shinfo(skb)->frags->page));
++		} else {
++			gnttab_grant_foreign_access_ref(
++				ref, np->xbdev->otherend_id,
++				pfn_to_mfn(page_to_pfn(skb_shinfo(skb)->
++						       frags->page)),
++				0);
++		}
++		req->gref = ref;
++		req->id   = requeue_idx;
++
++		requeue_idx++;
++	}
++
++	np->rx.req_prod_pvt = requeue_idx;
++
++	/*
++	 * Step 3: All public and private state should now be sane.  Get
++	 * ready to start sending and receiving packets and give the driver
++	 * domain a kick because we've probably just requeued some
++	 * packets.
++	 */
++	netfront_carrier_on(np);
++	notify_remote_via_irq(np->irq);
++	network_tx_buf_gc(dev);
++	network_alloc_rx_buffers(dev);
++
++	spin_unlock_irq(&np->tx_lock);
++	spin_unlock_bh(&np->rx_lock);
++
++	return 0;
++}
++
++static void netif_uninit(struct net_device *dev)
++{
++	struct netfront_info *np = netdev_priv(dev);
++	netif_release_tx_bufs(np);
++	if (np->copying_receiver)
++		netif_release_rx_bufs_copy(np);
++	else
++		netif_release_rx_bufs_flip(np);
++	gnttab_free_grant_references(np->gref_tx_head);
++	gnttab_free_grant_references(np->gref_rx_head);
++}
++
++static struct ethtool_ops network_ethtool_ops =
++{
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.set_tx_csum = ethtool_op_set_tx_csum,
++	.get_sg = ethtool_op_get_sg,
++	.set_sg = xennet_set_sg,
++#if HAVE_TSO
++	.get_tso = ethtool_op_get_tso,
++	.set_tso = xennet_set_tso,
++#endif
++	.get_link = ethtool_op_get_link,
++};
++
++#ifdef CONFIG_SYSFS
++static ssize_t show_rxbuf_min(struct class_device *cd, char *buf)
++{
++	struct net_device *netdev = container_of(cd, struct net_device,
++						 class_dev);
++	struct netfront_info *info = netdev_priv(netdev);
++
++	return sprintf(buf, "%u\n", info->rx_min_target);
++}
++
++static ssize_t store_rxbuf_min(struct class_device *cd,
++			       const char *buf, size_t len)
++{
++	struct net_device *netdev = container_of(cd, struct net_device,
++						 class_dev);
++	struct netfront_info *np = netdev_priv(netdev);
++	char *endp;
++	unsigned long target;
++
++	if (!capable(CAP_NET_ADMIN))
++		return -EPERM;
++
++	target = simple_strtoul(buf, &endp, 0);
++	if (endp == buf)
++		return -EBADMSG;
++
++	if (target < RX_MIN_TARGET)
++		target = RX_MIN_TARGET;
++	if (target > RX_MAX_TARGET)
++		target = RX_MAX_TARGET;
++
++	spin_lock_bh(&np->rx_lock);
++	if (target > np->rx_max_target)
++		np->rx_max_target = target;
++	np->rx_min_target = target;
++	if (target > np->rx_target)
++		np->rx_target = target;
++
++	network_alloc_rx_buffers(netdev);
++
++	spin_unlock_bh(&np->rx_lock);
++	return len;
++}
++
++static ssize_t show_rxbuf_max(struct class_device *cd, char *buf)
++{
++	struct net_device *netdev = container_of(cd, struct net_device,
++						 class_dev);
++	struct netfront_info *info = netdev_priv(netdev);
++
++	return sprintf(buf, "%u\n", info->rx_max_target);
++}
++
++static ssize_t store_rxbuf_max(struct class_device *cd,
++			       const char *buf, size_t len)
++{
++	struct net_device *netdev = container_of(cd, struct net_device,
++						 class_dev);
++	struct netfront_info *np = netdev_priv(netdev);
++	char *endp;
++	unsigned long target;
++
++	if (!capable(CAP_NET_ADMIN))
++		return -EPERM;
++
++	target = simple_strtoul(buf, &endp, 0);
++	if (endp == buf)
++		return -EBADMSG;
++
++	if (target < RX_MIN_TARGET)
++		target = RX_MIN_TARGET;
++	if (target > RX_MAX_TARGET)
++		target = RX_MAX_TARGET;
++
++	spin_lock_bh(&np->rx_lock);
++	if (target < np->rx_min_target)
++		np->rx_min_target = target;
++	np->rx_max_target = target;
++	if (target < np->rx_target)
++		np->rx_target = target;
++
++	network_alloc_rx_buffers(netdev);
++
++	spin_unlock_bh(&np->rx_lock);
++	return len;
++}
++
++static ssize_t show_rxbuf_cur(struct class_device *cd, char *buf)
++{
++	struct net_device *netdev = container_of(cd, struct net_device,
++						 class_dev);
++	struct netfront_info *info = netdev_priv(netdev);
++
++	return sprintf(buf, "%u\n", info->rx_target);
++}
++
++static const struct class_device_attribute xennet_attrs[] = {
++	__ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
++	__ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
++	__ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
++};
++
++static int xennet_sysfs_addif(struct net_device *netdev)
++{
++	int i;
++	int error = 0;
++
++	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
++		error = class_device_create_file(&netdev->class_dev, 
++						 &xennet_attrs[i]);
++		if (error)
++			goto fail;
++	}
++	return 0;
++
++ fail:
++	while (--i >= 0)
++		class_device_remove_file(&netdev->class_dev,
++					 &xennet_attrs[i]);
++	return error;
++}
++
++static void xennet_sysfs_delif(struct net_device *netdev)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
++		class_device_remove_file(&netdev->class_dev,
++					 &xennet_attrs[i]);
++	}
++}
++
++#endif /* CONFIG_SYSFS */
++
++
++/*
++ * Nothing to do here. Virtual interface is point-to-point and the
++ * physical interface is probably promiscuous anyway.
++ */
++static void network_set_multicast_list(struct net_device *dev)
++{
++}
++
++static struct net_device * __devinit create_netdev(struct xenbus_device *dev)
++{
++	int i, err = 0;
++	struct net_device *netdev = NULL;
++	struct netfront_info *np = NULL;
++
++	netdev = alloc_etherdev(sizeof(struct netfront_info));
++	if (!netdev) {
++		printk(KERN_WARNING "%s> alloc_etherdev failed.\n",
++		       __FUNCTION__);
++		return ERR_PTR(-ENOMEM);
++	}
++
++	np                   = netdev_priv(netdev);
++	np->xbdev            = dev;
++
++	spin_lock_init(&np->tx_lock);
++	spin_lock_init(&np->rx_lock);
++
++	init_accelerator_vif(np, dev);
++
++	skb_queue_head_init(&np->rx_batch);
++	np->rx_target     = RX_DFL_MIN_TARGET;
++	np->rx_min_target = RX_DFL_MIN_TARGET;
++	np->rx_max_target = RX_MAX_TARGET;
++
++	init_timer(&np->rx_refill_timer);
++	np->rx_refill_timer.data = (unsigned long)netdev;
++	np->rx_refill_timer.function = rx_refill_timeout;
++
++	/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
++	for (i = 0; i <= NET_TX_RING_SIZE; i++) {
++		np->tx_skbs[i] = (void *)((unsigned long) i+1);
++		np->grant_tx_ref[i] = GRANT_INVALID_REF;
++	}
++
++	for (i = 0; i < NET_RX_RING_SIZE; i++) {
++		np->rx_skbs[i] = NULL;
++		np->grant_rx_ref[i] = GRANT_INVALID_REF;
++	}
++
++	/* A grant for every tx ring slot */
++	if (gnttab_alloc_grant_references(TX_MAX_TARGET,
++					  &np->gref_tx_head) < 0) {
++		printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
++		err = -ENOMEM;
++		goto exit;
++	}
++	/* A grant for every rx ring slot */
++	if (gnttab_alloc_grant_references(RX_MAX_TARGET,
++					  &np->gref_rx_head) < 0) {
++		printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
++		err = -ENOMEM;
++		goto exit_free_tx;
++	}
++
++	netdev->open            = network_open;
++	netdev->hard_start_xmit = network_start_xmit;
++	netdev->stop            = network_close;
++	netdev->get_stats       = network_get_stats;
++	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;
++
++	SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
++	SET_MODULE_OWNER(netdev);
++	SET_NETDEV_DEV(netdev, &dev->dev);
++
++	np->netdev = netdev;
++
++	netfront_carrier_off(np);
++
++	return netdev;
++
++ exit_free_tx:
++	gnttab_free_grant_references(np->gref_tx_head);
++ exit:
++	free_netdev(netdev);
++	return ERR_PTR(err);
++}
++
++#ifdef CONFIG_INET
++/*
++ * We use this notifier to send out a fake ARP reply to reset switches and
++ * router ARP caches when an IP interface is brought up on a VIF.
++ */
++static int
++inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr)
++{
++	struct in_ifaddr  *ifa = (struct in_ifaddr *)ptr;
++	struct net_device *dev = ifa->ifa_dev->dev;
++
++	/* UP event and is it one of our devices? */
++	if (event == NETDEV_UP && dev->open == network_open)
++		send_fake_arp(dev);
++
++	return NOTIFY_DONE;
++}
++
++static struct notifier_block notifier_inetdev = {
++	.notifier_call  = inetdev_notify,
++	.next           = NULL,
++	.priority       = 0
++};
++#endif
++
++
++static void netif_disconnect_backend(struct netfront_info *info)
++{
++	/* Stop old i/f to prevent errors whilst we rebuild the state. */
++	spin_lock_bh(&info->rx_lock);
++	spin_lock_irq(&info->tx_lock);
++	netfront_carrier_off(info);
++	spin_unlock_irq(&info->tx_lock);
++	spin_unlock_bh(&info->rx_lock);
++
++	if (info->irq)
++		unbind_from_irqhandler(info->irq, info->netdev);
++	info->irq = 0;
++
++	end_access(info->tx_ring_ref, info->tx.sring);
++	end_access(info->rx_ring_ref, info->rx.sring);
++	info->tx_ring_ref = GRANT_INVALID_REF;
++	info->rx_ring_ref = GRANT_INVALID_REF;
++	info->tx.sring = NULL;
++	info->rx.sring = NULL;
++}
++
++
++static void end_access(int ref, void *page)
++{
++	if (ref != GRANT_INVALID_REF)
++		gnttab_end_foreign_access(ref, (unsigned long)page);
++}
++
++
++/* ** Driver registration ** */
++
++
++static const struct xenbus_device_id netfront_ids[] = {
++	{ "vif" },
++	{ "" }
++};
++MODULE_ALIAS("xen:vif");
++
++
++static struct xenbus_driver netfront_driver = {
++	.name = "vif",
++	.owner = THIS_MODULE,
++	.ids = netfront_ids,
++	.probe = netfront_probe,
++	.remove = __devexit_p(netfront_remove),
++	.suspend = netfront_suspend,
++	.suspend_cancel = netfront_suspend_cancel,
++	.resume = netfront_resume,
++	.otherend_changed = backend_changed,
++};
++
++
++static int __init netif_init(void)
++{
++	int err;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++#ifdef CONFIG_XEN
++	if (MODPARM_rx_flip && MODPARM_rx_copy) {
++		WPRINTK("Cannot specify both rx_copy and rx_flip.\n");
++		return -EINVAL;
++	}
++
++	if (!MODPARM_rx_flip && !MODPARM_rx_copy)
++		MODPARM_rx_flip = 1; /* Default is to flip. */
++#endif
++
++	netif_init_accel();
++
++	IPRINTK("Initialising virtual ethernet driver.\n");
++
++#ifdef CONFIG_INET
++	(void)register_inetaddr_notifier(&notifier_inetdev);
++#endif
++
++	err = xenbus_register_frontend(&netfront_driver);
++	if (err) {
++#ifdef CONFIG_INET
++		unregister_inetaddr_notifier(&notifier_inetdev);
++#endif
++	}
++	return err;
++}
++module_init(netif_init);
++
++
++static void __exit netif_exit(void)
++{
++#ifdef CONFIG_INET
++	unregister_inetaddr_notifier(&notifier_inetdev);
++#endif
++	xenbus_unregister_driver(&netfront_driver);
++
++	netif_exit_accel();
++}
++module_exit(netif_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/netfront/netfront.h	2008-01-07 13:19:18.000000000 +0100
+@@ -0,0 +1,274 @@
++/******************************************************************************
++ * Virtual network driver for conversing with remote driver backends.
++ *
++ * Copyright (c) 2002-2005, K A Fraser
++ * Copyright (c) 2005, 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.
++ */
++
++#ifndef NETFRONT_H
++#define NETFRONT_H
++
++#include <xen/interface/io/netif.h>
++#include <linux/netdevice.h>
++#include <linux/skbuff.h>
++#include <linux/list.h>
++
++#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
++#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
++
++#include <xen/xenbus.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++/* 
++ * Function pointer table for hooks into a network acceleration
++ * plugin.  These are called at appropriate points from the netfront
++ * driver 
++ */
++struct netfront_accel_hooks {
++	/* 
++	 * new_device: Accelerator hook to ask the plugin to support a
++	 * new network interface
++	 */
++	int (*new_device)(struct net_device *net_dev, struct xenbus_device *dev);
++	/*
++	 * remove: Opposite of new_device
++	 */
++	int (*remove)(struct xenbus_device *dev);
++	/*
++	 * The net_device is being polled, check the accelerated
++	 * hardware for any pending packets
++	 */
++	int (*netdev_poll)(struct net_device *dev, int *pbudget);
++	/*
++	 * start_xmit: Used to give the accelerated plugin the option
++	 * of sending a packet.  Returns non-zero if has done so, or
++	 * zero to decline and force the packet onto normal send
++	 * path
++	 */
++	int (*start_xmit)(struct sk_buff *skb, struct net_device *dev);
++	/* 
++	 * start/stop_napi_interrupts Used by netfront to indicate
++	 * when napi interrupts should be enabled or disabled 
++	 */
++	int (*start_napi_irq)(struct net_device *dev);
++	void (*stop_napi_irq)(struct net_device *dev);
++	/* 
++	 * Called before re-enabling the TX queue to check the fast
++	 * path has slots too
++	 */
++	int (*check_ready)(struct net_device *dev);
++	/*
++	 * Get the fastpath network statistics
++	 */
++	int (*get_stats)(struct net_device *dev,
++			 struct net_device_stats *stats);
++};
++
++
++/* Version of API/protocol for communication between netfront and
++   acceleration plugin supported */
++#define NETFRONT_ACCEL_VERSION 0x00010003
++
++/* 
++ * Per-netfront device state for the accelerator.  This is used to
++ * allow efficient per-netfront device access to the accelerator
++ * hooks 
++ */
++struct netfront_accel_vif_state {
++	struct list_head link;
++
++	struct xenbus_device *dev;
++	struct netfront_info *np;
++	struct netfront_accel_hooks *hooks;
++
++	/* Watch on the accelerator configuration value */
++	struct xenbus_watch accel_watch;
++	/* Work item to process change in accelerator */
++	struct work_struct accel_work;
++	/* The string from xenbus last time accel_watch fired */
++	char *accel_frontend;
++}; 
++
++/* 
++ * Per-accelerator state stored in netfront.  These form a list that
++ * is used to track which devices are accelerated by which plugins,
++ * and what plugins are available/have been requested 
++ */
++struct netfront_accelerator {
++	/* Used to make a list */
++	struct list_head link;
++	/* ID of the accelerator */
++	int id;
++	/*
++	 * String describing the accelerator.  Currently this is the
++	 * name of the accelerator module.  This is provided by the
++	 * backend accelerator through xenstore 
++	 */
++	char *frontend;
++	/* The hooks into the accelerator plugin module */
++	struct netfront_accel_hooks *hooks;
++
++	/* 
++	 * List of per-netfront device state (struct
++	 * netfront_accel_vif_state) for each netfront device that is
++	 * using this accelerator
++	 */
++	struct list_head vif_states;
++	spinlock_t vif_states_lock;
++};
++
++struct netfront_info {
++	struct list_head list;
++	struct net_device *netdev;
++
++	struct net_device_stats stats;
++
++	struct netif_tx_front_ring tx;
++	struct netif_rx_front_ring rx;
++
++	spinlock_t   tx_lock;
++	spinlock_t   rx_lock;
++
++	unsigned int irq;
++	unsigned int copying_receiver;
++	unsigned int carrier;
++
++	/* Receive-ring batched refills. */
++#define RX_MIN_TARGET 8
++#define RX_DFL_MIN_TARGET 64
++#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
++	unsigned rx_min_target, rx_max_target, rx_target;
++	struct sk_buff_head rx_batch;
++
++	struct timer_list rx_refill_timer;
++
++	/*
++	 * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs
++	 * is an index into a chain of free entries.
++	 */
++	struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
++	struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
++
++#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
++	grant_ref_t gref_tx_head;
++	grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
++	grant_ref_t gref_rx_head;
++	grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
++
++	struct xenbus_device *xbdev;
++	int tx_ring_ref;
++	int rx_ring_ref;
++	u8 mac[ETH_ALEN];
++
++	unsigned long rx_pfn_array[NET_RX_RING_SIZE];
++	struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
++	struct mmu_update rx_mmu[NET_RX_RING_SIZE];
++
++	/* Private pointer to state internal to accelerator module */
++	void *accel_priv;
++	/* The accelerator used by this netfront device */
++	struct netfront_accelerator *accelerator;
++	/* The accelerator state for this netfront device */
++	struct netfront_accel_vif_state accel_vif_state;
++};
++
++
++/* Exported Functions */
++
++/*
++ * Called by an accelerator plugin module when it has loaded.
++ *
++ * frontend: the string describing the accelerator, currently the module name 
++ * hooks: the hooks for netfront to use to call into the accelerator
++ * version: the version of API between frontend and plugin requested
++ * 
++ * return: 0 on success, <0 on error, >0 (with version supported) on
++ * version mismatch
++ */
++extern int netfront_accelerator_loaded(int version, const char *frontend, 
++				       struct netfront_accel_hooks *hooks);
++
++/* 
++ * Called by an accelerator plugin module when it is about to unload.
++ *
++ * frontend: the string describing the accelerator.  Must match the
++ * one passed to netfront_accelerator_loaded()
++ */ 
++extern void netfront_accelerator_stop(const char *frontend);
++
++/* 
++ * Called by an accelerator before waking the net device's TX queue to
++ * ensure the slow path has available slots.  Returns true if OK to
++ * wake, false if still busy 
++ */
++extern int netfront_check_queue_ready(struct net_device *net_dev);
++
++
++/* Internal-to-netfront Functions */
++
++/* 
++ * Call into accelerator and check to see if it has tx space before we
++ * wake the net device's TX queue.  Returns true if OK to wake, false
++ * if still busy
++ */ 
++extern 
++int netfront_check_accelerator_queue_ready(struct net_device *dev,
++					   struct netfront_info *np);
++extern
++int netfront_accelerator_call_remove(struct netfront_info *np,
++				     struct xenbus_device *dev);
++extern
++int netfront_accelerator_suspend(struct netfront_info *np,
++				 struct xenbus_device *dev);
++extern
++int netfront_accelerator_suspend_cancel(struct netfront_info *np,
++					struct xenbus_device *dev);
++extern
++void netfront_accelerator_resume(struct netfront_info *np,
++				 struct xenbus_device *dev);
++extern
++void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
++					     struct net_device *dev);
++extern
++int netfront_accelerator_call_get_stats(struct netfront_info *np,
++					struct net_device *dev);
++extern
++void netfront_accelerator_add_watch(struct netfront_info *np);
++
++extern
++void netif_init_accel(void);
++extern
++void netif_exit_accel(void);
++
++extern
++void init_accelerator_vif(struct netfront_info *np,
++			  struct xenbus_device *dev);
++#endif /* NETFRONT_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/Makefile	2008-07-21 11:00:33.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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space.c	2009-05-04 10:01:03.000000000 +0200
+@@ -0,0 +1,435 @@
++/*
++ * PCI Backend - Functions for creating a virtual configuration space for
++ *               exported PCI Devices.
++ *               It's dangerous to allow PCI Driver Domains to change their
++ *               device's resources (memory, i/o ports, interrupts). We need to
++ *               restrict changes to certain PCI Configuration registers:
++ *               BARs, INTERRUPT_PIN, most registers in the header...
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include "pciback.h"
++#include "conf_space.h"
++#include "conf_space_quirks.h"
++
++static int permissive;
++module_param(permissive, bool, 0644);
++
++#define DEFINE_PCI_CONFIG(op,size,type) 			\
++int pciback_##op##_config_##size 				\
++(struct pci_dev *dev, int offset, type value, void *data)	\
++{								\
++	return pci_##op##_config_##size (dev, offset, value);	\
++}
++
++DEFINE_PCI_CONFIG(read, byte, u8 *)
++DEFINE_PCI_CONFIG(read, word, u16 *)
++DEFINE_PCI_CONFIG(read, dword, u32 *)
++
++DEFINE_PCI_CONFIG(write, byte, u8)
++DEFINE_PCI_CONFIG(write, word, u16)
++DEFINE_PCI_CONFIG(write, dword, u32)
++
++static int conf_space_read(struct pci_dev *dev,
++			   const struct config_field_entry *entry,
++			   int offset, u32 *value)
++{
++	int ret = 0;
++	const struct config_field *field = entry->field;
++
++	*value = 0;
++
++	switch (field->size) {
++	case 1:
++		if (field->u.b.read)
++			ret = field->u.b.read(dev, offset, (u8 *) value,
++					      entry->data);
++		break;
++	case 2:
++		if (field->u.w.read)
++			ret = field->u.w.read(dev, offset, (u16 *) value,
++					      entry->data);
++		break;
++	case 4:
++		if (field->u.dw.read)
++			ret = field->u.dw.read(dev, offset, value, entry->data);
++		break;
++	}
++	return ret;
++}
++
++static int conf_space_write(struct pci_dev *dev,
++			    const struct config_field_entry *entry,
++			    int offset, u32 value)
++{
++	int ret = 0;
++	const struct config_field *field = entry->field;
++
++	switch (field->size) {
++	case 1:
++		if (field->u.b.write)
++			ret = field->u.b.write(dev, offset, (u8) value,
++					       entry->data);
++		break;
++	case 2:
++		if (field->u.w.write)
++			ret = field->u.w.write(dev, offset, (u16) value,
++					       entry->data);
++		break;
++	case 4:
++		if (field->u.dw.write)
++			ret = field->u.dw.write(dev, offset, value,
++						entry->data);
++		break;
++	}
++	return ret;
++}
++
++static inline u32 get_mask(int size)
++{
++	if (size == 1)
++		return 0xff;
++	else if (size == 2)
++		return 0xffff;
++	else
++		return 0xffffffff;
++}
++
++static inline int valid_request(int offset, int size)
++{
++	/* Validate request (no un-aligned requests) */
++	if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
++		return 1;
++	return 0;
++}
++
++static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
++			      int offset)
++{
++	if (offset >= 0) {
++		new_val_mask <<= (offset * 8);
++		new_val <<= (offset * 8);
++	} else {
++		new_val_mask >>= (offset * -8);
++		new_val >>= (offset * -8);
++	}
++	val = (val & ~new_val_mask) | (new_val & new_val_mask);
++
++	return val;
++}
++
++static int pcibios_err_to_errno(int err)
++{
++	switch (err) {
++	case PCIBIOS_SUCCESSFUL:
++		return XEN_PCI_ERR_success;
++	case PCIBIOS_DEVICE_NOT_FOUND:
++		return XEN_PCI_ERR_dev_not_found;
++	case PCIBIOS_BAD_REGISTER_NUMBER:
++		return XEN_PCI_ERR_invalid_offset;
++	case PCIBIOS_FUNC_NOT_SUPPORTED:
++		return XEN_PCI_ERR_not_implemented;
++	case PCIBIOS_SET_FAILED:
++		return XEN_PCI_ERR_access_denied;
++	}
++	return err;
++}
++
++int pciback_config_read(struct pci_dev *dev, int offset, int size,
++			u32 * ret_val)
++{
++	int err = 0;
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	const struct config_field_entry *cfg_entry;
++	const struct config_field *field;
++	int req_start, req_end, field_start, field_end;
++	/* if read fails for any reason, return 0 (as if device didn't respond) */
++	u32 value = 0, tmp_val;
++
++	if (unlikely(verbose_request))
++		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x\n",
++		       pci_name(dev), size, offset);
++
++	if (!valid_request(offset, size)) {
++		err = XEN_PCI_ERR_invalid_offset;
++		goto out;
++	}
++
++	/* Get the real value first, then modify as appropriate */
++	switch (size) {
++	case 1:
++		err = pci_read_config_byte(dev, offset, (u8 *) & value);
++		break;
++	case 2:
++		err = pci_read_config_word(dev, offset, (u16 *) & value);
++		break;
++	case 4:
++		err = pci_read_config_dword(dev, offset, &value);
++		break;
++	}
++
++	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
++		field = cfg_entry->field;
++
++		req_start = offset;
++		req_end = offset + size;
++		field_start = OFFSET(cfg_entry);
++		field_end = OFFSET(cfg_entry) + field->size;
++
++		if ((req_start >= field_start && req_start < field_end)
++		    || (req_end > field_start && req_end <= field_end)) {
++			err = conf_space_read(dev, cfg_entry, field_start,
++					      &tmp_val);
++			if (err)
++				goto out;
++
++			value = merge_value(value, tmp_val,
++					    get_mask(field->size),
++					    field_start - req_start);
++		}
++	}
++
++      out:
++	if (unlikely(verbose_request))
++		printk(KERN_DEBUG "pciback: %s: read %d bytes at 0x%x = %x\n",
++		       pci_name(dev), size, offset, value);
++
++	*ret_val = value;
++	return pcibios_err_to_errno(err);
++}
++
++int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
++{
++	int err = 0, handled = 0;
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	const struct config_field_entry *cfg_entry;
++	const struct config_field *field;
++	u32 tmp_val;
++	int req_start, req_end, field_start, field_end;
++
++	if (unlikely(verbose_request))
++		printk(KERN_DEBUG
++		       "pciback: %s: write request %d bytes at 0x%x = %x\n",
++		       pci_name(dev), size, offset, value);
++
++	if (!valid_request(offset, size))
++		return XEN_PCI_ERR_invalid_offset;
++
++	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
++		field = cfg_entry->field;
++
++		req_start = offset;
++		req_end = offset + size;
++		field_start = OFFSET(cfg_entry);
++		field_end = OFFSET(cfg_entry) + field->size;
++
++		if ((req_start >= field_start && req_start < field_end)
++		    || (req_end > field_start && req_end <= field_end)) {
++			tmp_val = 0;
++
++			err = pciback_config_read(dev, field_start,
++						  field->size, &tmp_val);
++			if (err)
++				break;
++
++			tmp_val = merge_value(tmp_val, value, get_mask(size),
++					      req_start - field_start);
++
++			err = conf_space_write(dev, cfg_entry, field_start,
++					       tmp_val);
++
++			/* handled is set true here, but not every byte
++			 * may have been written! Properly detecting if
++			 * every byte is handled is unnecessary as the
++			 * flag is used to detect devices that need
++			 * special helpers to work correctly.
++			 */
++			handled = 1;
++		}
++	}
++
++	if (!handled && !err) {
++		/* By default, anything not specificially handled above is
++		 * read-only. The permissive flag changes this behavior so
++		 * that anything not specifically handled above is writable.
++		 * This means that some fields may still be read-only because
++		 * they have entries in the config_field list that intercept
++		 * the write and do nothing. */
++		if (dev_data->permissive || permissive) {
++			switch (size) {
++			case 1:
++				err = pci_write_config_byte(dev, offset,
++							    (u8) value);
++				break;
++			case 2:
++				err = pci_write_config_word(dev, offset,
++							    (u16) value);
++				break;
++			case 4:
++				err = pci_write_config_dword(dev, offset,
++							     (u32) value);
++				break;
++			}
++		} else if (!dev_data->warned_on_write) {
++			dev_data->warned_on_write = 1;
++			dev_warn(&dev->dev, "Driver tried to write to a "
++				 "read-only configuration space field at offset "
++				 "0x%x, size %d. This may be harmless, but if "
++				 "you have problems with your device:\n"
++				 "1) see permissive attribute in sysfs\n"
++				 "2) report problems to the xen-devel "
++				 "mailing list along with details of your "
++				 "device obtained from lspci.\n", offset, size);
++		}
++	}
++
++	return pcibios_err_to_errno(err);
++}
++
++void pciback_config_free_dyn_fields(struct pci_dev *dev)
++{
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	struct config_field_entry *cfg_entry, *t;
++	const struct config_field *field;
++
++	dev_dbg(&dev->dev,
++		"free-ing dynamically allocated virtual configuration space fields\n");
++	if (!dev_data)
++		return;
++
++	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
++		field = cfg_entry->field;
++
++		if (field->clean) {
++			field->clean((struct config_field *)field);
++
++			if (cfg_entry->data)
++				kfree(cfg_entry->data);
++
++			list_del(&cfg_entry->list);
++			kfree(cfg_entry);
++		}
++
++	}
++}
++
++void pciback_config_reset_dev(struct pci_dev *dev)
++{
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	const struct config_field_entry *cfg_entry;
++	const struct config_field *field;
++
++	dev_dbg(&dev->dev, "resetting virtual configuration space\n");
++	if (!dev_data)
++		return;
++
++	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
++		field = cfg_entry->field;
++
++		if (field->reset)
++			field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
++	}
++}
++
++void pciback_config_free_dev(struct pci_dev *dev)
++{
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	struct config_field_entry *cfg_entry, *t;
++	const struct config_field *field;
++
++	dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
++	if (!dev_data)
++		return;
++
++	list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
++		list_del(&cfg_entry->list);
++
++		field = cfg_entry->field;
++
++		if (field->release)
++			field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
++
++		kfree(cfg_entry);
++	}
++}
++
++int pciback_config_add_field_offset(struct pci_dev *dev,
++				    const struct config_field *field,
++				    unsigned int base_offset)
++{
++	int err = 0;
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	struct config_field_entry *cfg_entry;
++	void *tmp;
++
++	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
++	if (!cfg_entry) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	cfg_entry->data = NULL;
++	cfg_entry->field = field;
++	cfg_entry->base_offset = base_offset;
++
++	/* silently ignore duplicate fields */
++	err = pciback_field_is_dup(dev,OFFSET(cfg_entry));
++	if (err)
++		goto out;
++
++	if (field->init) {
++		tmp = field->init(dev, OFFSET(cfg_entry));
++
++		if (IS_ERR(tmp)) {
++			err = PTR_ERR(tmp);
++			goto out;
++		}
++
++		cfg_entry->data = tmp;
++	}
++
++	dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
++		OFFSET(cfg_entry));
++	list_add_tail(&cfg_entry->list, &dev_data->config_fields);
++
++      out:
++	if (err)
++		kfree(cfg_entry);
++
++	return err;
++}
++
++/* This sets up the device's virtual configuration space to keep track of 
++ * certain registers (like the base address registers (BARs) so that we can
++ * keep the client from manipulating them directly.
++ */
++int pciback_config_init_dev(struct pci_dev *dev)
++{
++	int err = 0;
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++
++	dev_dbg(&dev->dev, "initializing virtual configuration space\n");
++
++	INIT_LIST_HEAD(&dev_data->config_fields);
++
++	err = pciback_config_header_add_fields(dev);
++	if (err)
++		goto out;
++
++	err = pciback_config_capability_add_fields(dev);
++	if (err)
++		goto out;
++
++	err = pciback_config_quirks_init(dev);
++
++      out:
++	return err;
++}
++
++int pciback_config_init(void)
++{
++	return pciback_config_capability_init();
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space.h	2008-10-29 09:55:56.000000000 +0100
+@@ -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;
++	const 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,
++				    const struct config_field *field,
++				    unsigned int offset);
++
++static inline int pciback_config_add_field(struct pci_dev *dev,
++					   const struct config_field *field)
++{
++	return pciback_config_add_field_offset(dev, field, 0);
++}
++
++static inline int pciback_config_add_fields(struct pci_dev *dev,
++					    const 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,
++						   const 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_capability.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,69 @@
++/*
++ * PCI Backend - Handles the virtual fields found on the capability lists
++ *               in the configuration space.
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include "pciback.h"
++#include "conf_space.h"
++#include "conf_space_capability.h"
++
++static LIST_HEAD(capabilities);
++
++static const struct config_field caplist_header[] = {
++	{
++	 .offset    = PCI_CAP_LIST_ID,
++	 .size      = 2, /* encompass PCI_CAP_LIST_ID & PCI_CAP_LIST_NEXT */
++	 .u.w.read  = pciback_read_config_word,
++	 .u.w.write = NULL,
++	},
++	{}
++};
++
++static inline void register_capability(struct pciback_config_capability *cap)
++{
++	list_add_tail(&cap->cap_list, &capabilities);
++}
++
++int pciback_config_capability_add_fields(struct pci_dev *dev)
++{
++	int err = 0;
++	struct pciback_config_capability *cap;
++	int cap_offset;
++
++	list_for_each_entry(cap, &capabilities, cap_list) {
++		cap_offset = pci_find_capability(dev, cap->capability);
++		if (cap_offset) {
++			dev_dbg(&dev->dev, "Found capability 0x%x at 0x%x\n",
++				cap->capability, cap_offset);
++
++			err = pciback_config_add_fields_offset(dev,
++							       caplist_header,
++							       cap_offset);
++			if (err)
++				goto out;
++			err = pciback_config_add_fields_offset(dev,
++							       cap->fields,
++							       cap_offset);
++			if (err)
++				goto out;
++		}
++	}
++
++      out:
++	return err;
++}
++
++extern struct pciback_config_capability pciback_config_capability_vpd;
++extern struct pciback_config_capability pciback_config_capability_pm;
++
++int pciback_config_capability_init(void)
++{
++	register_capability(&pciback_config_capability_vpd);
++	register_capability(&pciback_config_capability_pm);
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_capability.h	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,23 @@
++/*
++ * PCI Backend - Data structures for special overlays for structures on
++ *               the capability list.
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#ifndef __PCIBACK_CONFIG_CAPABILITY_H__
++#define __PCIBACK_CONFIG_CAPABILITY_H__
++
++#include <linux/pci.h>
++#include <linux/list.h>
++
++struct pciback_config_capability {
++	struct list_head cap_list;
++
++	int capability;
++
++	/* If the device has the capability found above, add these fields */
++	const struct config_field *fields;
++};
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_capability_msi.c	2008-09-15 13:40:15.000000000 +0200
+@@ -0,0 +1,79 @@
++/*
++ * PCI Backend -- Configuration overlay for MSI capability
++ */
++#include <linux/pci.h>
++#include <linux/slab.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 i, result;
++	struct msix_entry *entries;
++
++	if (op->value > SH_INFO_MAX_VEC)
++		return -EINVAL;
++
++	entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
++	if (entries == NULL)
++		return -ENOMEM;
++
++	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);
++
++	for (i = 0; i < op->value; i++) {
++		op->msix_entries[i].entry = entries[i].entry;
++		op->msix_entries[i].vector = entries[i].vector;
++	}
++
++	kfree(entries);
++
++	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;
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_capability_pm.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,126 @@
++/*
++ * PCI Backend - Configuration space overlay for power management
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/pci.h>
++#include "conf_space.h"
++#include "conf_space_capability.h"
++
++static int pm_caps_read(struct pci_dev *dev, int offset, u16 *value,
++			void *data)
++{
++	int err;
++	u16 real_value;
++
++	err = pci_read_config_word(dev, offset, &real_value);
++	if (err)
++		goto out;
++
++	*value = real_value & ~PCI_PM_CAP_PME_MASK;
++
++      out:
++	return err;
++}
++
++/* PM_OK_BITS specifies the bits that the driver domain is allowed to change.
++ * Can't allow driver domain to enable PMEs - they're shared */
++#define PM_OK_BITS (PCI_PM_CTRL_PME_STATUS|PCI_PM_CTRL_DATA_SEL_MASK)
++
++static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
++			 void *data)
++{
++	int err;
++	u16 old_value;
++	pci_power_t new_state, old_state;
++
++	err = pci_read_config_word(dev, offset, &old_value);
++	if (err)
++		goto out;
++
++	old_state = (pci_power_t)(old_value & PCI_PM_CTRL_STATE_MASK);
++	new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
++
++	new_value &= PM_OK_BITS;
++	if ((old_value & PM_OK_BITS) != new_value) {
++		new_value = (old_value & ~PM_OK_BITS) | new_value;
++		err = pci_write_config_word(dev, offset, new_value);
++		if (err)
++			goto out;
++	}
++
++	/* Let pci core handle the power management change */
++	dev_dbg(&dev->dev, "set power state to %x\n", new_state);
++	err = pci_set_power_state(dev, new_state);
++	if (err) {
++		err = PCIBIOS_SET_FAILED;
++		goto out;
++	}
++
++	/*
++	 * Device may lose PCI config info on D3->D0 transition. This
++	 * is a problem for some guests which will not reset BARs. Even
++	 * those that have a go will be foiled by our BAR-write handler
++	 * which will discard the write! Since Linux won't re-init
++	 * the config space automatically in all cases, we do it here.
++	 * Future: Should we re-initialise all first 64 bytes of config space?
++	 */
++	if (new_state == PCI_D0 &&
++	    (old_state == PCI_D3hot || old_state == PCI_D3cold) &&
++	    !(old_value & PCI_PM_CTRL_NO_SOFT_RESET))
++		pci_restore_bars(dev);
++
++ out:
++	return err;
++}
++
++/* Ensure PMEs are disabled */
++static void *pm_ctrl_init(struct pci_dev *dev, int offset)
++{
++	int err;
++	u16 value;
++
++	err = pci_read_config_word(dev, offset, &value);
++	if (err)
++		goto out;
++
++	if (value & PCI_PM_CTRL_PME_ENABLE) {
++		value &= ~PCI_PM_CTRL_PME_ENABLE;
++		err = pci_write_config_word(dev, offset, value);
++	}
++
++      out:
++	return ERR_PTR(err);
++}
++
++static const struct config_field caplist_pm[] = {
++	{
++		.offset     = PCI_PM_PMC,
++		.size       = 2,
++		.u.w.read   = pm_caps_read,
++	},
++	{
++		.offset     = PCI_PM_CTRL,
++		.size       = 2,
++		.init       = pm_ctrl_init,
++		.u.w.read   = pciback_read_config_word,
++		.u.w.write  = pm_ctrl_write,
++	},
++	{
++		.offset     = PCI_PM_PPB_EXTENSIONS,
++		.size       = 1,
++		.u.b.read   = pciback_read_config_byte,
++	},
++	{
++		.offset     = PCI_PM_DATA_REGISTER,
++		.size       = 1,
++		.u.b.read   = pciback_read_config_byte,
++	},
++	{}
++};
++
++struct pciback_config_capability pciback_config_capability_pm = {
++	.capability = PCI_CAP_ID_PM,
++	.fields = caplist_pm,
++};
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_capability_vpd.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,40 @@
++/*
++ * PCI Backend - Configuration space overlay for Vital Product Data
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/pci.h>
++#include "conf_space.h"
++#include "conf_space_capability.h"
++
++static int vpd_address_write(struct pci_dev *dev, int offset, u16 value,
++			     void *data)
++{
++	/* Disallow writes to the vital product data */
++	if (value & PCI_VPD_ADDR_F)
++		return PCIBIOS_SET_FAILED;
++	else
++		return pci_write_config_word(dev, offset, value);
++}
++
++static const struct config_field caplist_vpd[] = {
++	{
++	 .offset    = PCI_VPD_ADDR,
++	 .size      = 2,
++	 .u.w.read  = pciback_read_config_word,
++	 .u.w.write = vpd_address_write,
++	 },
++	{
++	 .offset     = PCI_VPD_DATA,
++	 .size       = 4,
++	 .u.dw.read  = pciback_read_config_dword,
++	 .u.dw.write = NULL,
++	 },
++	{}
++};
++ 
++struct pciback_config_capability pciback_config_capability_vpd = {
++	.capability = PCI_CAP_ID_VPD,
++	.fields = caplist_vpd,
++};
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_header.c	2008-10-29 09:55:56.000000000 +0100
+@@ -0,0 +1,317 @@
++/*
++ * PCI Backend - Handles the virtual fields in the configuration space headers.
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include "pciback.h"
++#include "conf_space.h"
++
++struct pci_bar_info {
++	u32 val;
++	u32 len_val;
++	int which;
++};
++
++#define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
++#define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
++
++static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
++{
++	int err;
++
++	if (!dev->is_enabled && is_enable_cmd(value)) {
++		if (unlikely(verbose_request))
++			printk(KERN_DEBUG "pciback: %s: enable\n",
++			       pci_name(dev));
++		err = pci_enable_device(dev);
++		if (err)
++			return err;
++	} else if (dev->is_enabled && !is_enable_cmd(value)) {
++		if (unlikely(verbose_request))
++			printk(KERN_DEBUG "pciback: %s: disable\n",
++			       pci_name(dev));
++		pci_disable_device(dev);
++	}
++
++	if (!dev->is_busmaster && is_master_cmd(value)) {
++		if (unlikely(verbose_request))
++			printk(KERN_DEBUG "pciback: %s: set bus master\n",
++			       pci_name(dev));
++		pci_set_master(dev);
++	}
++
++	if (value & PCI_COMMAND_INVALIDATE) {
++		if (unlikely(verbose_request))
++			printk(KERN_DEBUG
++			       "pciback: %s: enable memory-write-invalidate\n",
++			       pci_name(dev));
++		err = pci_set_mwi(dev);
++		if (err) {
++			printk(KERN_WARNING
++			       "pciback: %s: cannot enable memory-write-invalidate (%d)\n",
++			       pci_name(dev), err);
++			value &= ~PCI_COMMAND_INVALIDATE;
++		}
++	}
++
++	return pci_write_config_word(dev, offset, value);
++}
++
++static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
++{
++	struct pci_bar_info *bar = data;
++
++	if (unlikely(!bar)) {
++		printk(KERN_WARNING "pciback: driver data not found for %s\n",
++		       pci_name(dev));
++		return XEN_PCI_ERR_op_failed;
++	}
++
++	/* A write to obtain the length must happen as a 32-bit write.
++	 * This does not (yet) support writing individual bytes
++	 */
++	if (value == ~PCI_ROM_ADDRESS_ENABLE)
++		bar->which = 1;
++	else {
++		u32 tmpval;
++		pci_read_config_dword(dev, offset, &tmpval);
++		if (tmpval != bar->val && value == bar->val) {
++			/* Allow restoration of bar value. */
++			pci_write_config_dword(dev, offset, bar->val);
++		}
++		bar->which = 0;
++	}
++
++	/* Do we need to support enabling/disabling the rom address here? */
++
++	return 0;
++}
++
++/* For the BARs, only allow writes which write ~0 or
++ * the correct resource information
++ * (Needed for when the driver probes the resource usage)
++ */
++static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
++{
++	struct pci_bar_info *bar = data;
++
++	if (unlikely(!bar)) {
++		printk(KERN_WARNING "pciback: driver data not found for %s\n",
++		       pci_name(dev));
++		return XEN_PCI_ERR_op_failed;
++	}
++
++	/* A write to obtain the length must happen as a 32-bit write.
++	 * This does not (yet) support writing individual bytes
++	 */
++	if (value == ~0)
++		bar->which = 1;
++	else {
++		u32 tmpval;
++		pci_read_config_dword(dev, offset, &tmpval);
++		if (tmpval != bar->val && value == bar->val) {
++			/* Allow restoration of bar value. */
++			pci_write_config_dword(dev, offset, bar->val);
++		}
++		bar->which = 0;
++	}
++
++	return 0;
++}
++
++static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
++{
++	struct pci_bar_info *bar = data;
++
++	if (unlikely(!bar)) {
++		printk(KERN_WARNING "pciback: driver data not found for %s\n",
++		       pci_name(dev));
++		return XEN_PCI_ERR_op_failed;
++	}
++
++	*value = bar->which ? bar->len_val : bar->val;
++
++	return 0;
++}
++
++static inline void read_dev_bar(struct pci_dev *dev,
++				struct pci_bar_info *bar_info, int offset,
++				u32 len_mask)
++{
++	pci_read_config_dword(dev, offset, &bar_info->val);
++	pci_write_config_dword(dev, offset, len_mask);
++	pci_read_config_dword(dev, offset, &bar_info->len_val);
++	pci_write_config_dword(dev, offset, bar_info->val);
++}
++
++static void *bar_init(struct pci_dev *dev, int offset)
++{
++	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
++
++	if (!bar)
++		return ERR_PTR(-ENOMEM);
++
++	read_dev_bar(dev, bar, offset, ~0);
++	bar->which = 0;
++
++	return bar;
++}
++
++static void *rom_init(struct pci_dev *dev, int offset)
++{
++	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
++
++	if (!bar)
++		return ERR_PTR(-ENOMEM);
++
++	read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
++	bar->which = 0;
++
++	return bar;
++}
++
++static void bar_reset(struct pci_dev *dev, int offset, void *data)
++{
++	struct pci_bar_info *bar = data;
++
++	bar->which = 0;
++}
++
++static void bar_release(struct pci_dev *dev, int offset, void *data)
++{
++	kfree(data);
++}
++
++static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
++			  void *data)
++{
++	*value = (u8) dev->irq;
++
++	return 0;
++}
++
++static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
++{
++	u8 cur_value;
++	int err;
++
++	err = pci_read_config_byte(dev, offset, &cur_value);
++	if (err)
++		goto out;
++
++	if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
++	    || value == PCI_BIST_START)
++		err = pci_write_config_byte(dev, offset, value);
++
++      out:
++	return err;
++}
++
++static const struct config_field header_common[] = {
++	{
++	 .offset    = PCI_COMMAND,
++	 .size      = 2,
++	 .u.w.read  = pciback_read_config_word,
++	 .u.w.write = command_write,
++	},
++	{
++	 .offset    = PCI_INTERRUPT_LINE,
++	 .size      = 1,
++	 .u.b.read  = interrupt_read,
++	},
++	{
++	 .offset    = PCI_INTERRUPT_PIN,
++	 .size      = 1,
++	 .u.b.read  = pciback_read_config_byte,
++	},
++	{
++	 /* Any side effects of letting driver domain control cache line? */
++	 .offset    = PCI_CACHE_LINE_SIZE,
++	 .size      = 1,
++	 .u.b.read  = pciback_read_config_byte,
++	 .u.b.write = pciback_write_config_byte,
++	},
++	{
++	 .offset    = PCI_LATENCY_TIMER,
++	 .size      = 1,
++	 .u.b.read  = pciback_read_config_byte,
++	},
++	{
++	 .offset    = PCI_BIST,
++	 .size      = 1,
++	 .u.b.read  = pciback_read_config_byte,
++	 .u.b.write = bist_write,
++	},
++	{}
++};
++
++#define CFG_FIELD_BAR(reg_offset) 			\
++	{ 						\
++	 .offset     = reg_offset, 			\
++	 .size       = 4, 				\
++	 .init       = bar_init, 			\
++	 .reset      = bar_reset, 			\
++	 .release    = bar_release, 			\
++	 .u.dw.read  = bar_read, 			\
++	 .u.dw.write = bar_write, 			\
++	 }
++
++#define CFG_FIELD_ROM(reg_offset) 			\
++	{ 						\
++	 .offset     = reg_offset, 			\
++	 .size       = 4, 				\
++	 .init       = rom_init, 			\
++	 .reset      = bar_reset, 			\
++	 .release    = bar_release, 			\
++	 .u.dw.read  = bar_read, 			\
++	 .u.dw.write = rom_write, 			\
++	 }
++
++static const struct config_field header_0[] = {
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
++	CFG_FIELD_ROM(PCI_ROM_ADDRESS),
++	{}
++};
++
++static const struct config_field header_1[] = {
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
++	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
++	CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
++	{}
++};
++
++int pciback_config_header_add_fields(struct pci_dev *dev)
++{
++	int err;
++
++	err = pciback_config_add_fields(dev, header_common);
++	if (err)
++		goto out;
++
++	switch (dev->hdr_type) {
++	case PCI_HEADER_TYPE_NORMAL:
++		err = pciback_config_add_fields(dev, header_0);
++		break;
++
++	case PCI_HEADER_TYPE_BRIDGE:
++		err = pciback_config_add_fields(dev, header_1);
++		break;
++
++	default:
++		err = -EINVAL;
++		printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n",
++		       pci_name(dev), dev->hdr_type);
++		break;
++	}
++
++      out:
++	return err;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_quirks.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,138 @@
++/*
++ * PCI Backend - Handle special overlays for broken devices.
++ *
++ * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include "pciback.h"
++#include "conf_space.h"
++#include "conf_space_quirks.h"
++
++LIST_HEAD(pciback_quirks);
++
++static inline const struct pci_device_id *
++match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
++{
++	if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
++	    (id->device == PCI_ANY_ID || id->device == dev->device) &&
++	    (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
++	    (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
++	    !((id->class ^ dev->class) & id->class_mask))
++		return id;
++	return NULL;
++}
++
++struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev)
++{
++	struct pciback_config_quirk *tmp_quirk;
++
++	list_for_each_entry(tmp_quirk, &pciback_quirks, quirks_list)
++		if (match_one_device(&tmp_quirk->devid, dev) != NULL)
++			goto out;
++	tmp_quirk = NULL;
++	printk(KERN_DEBUG
++	       "quirk didn't match any device pciback knows about\n");
++      out:
++	return tmp_quirk;
++}
++
++static inline void register_quirk(struct pciback_config_quirk *quirk)
++{
++	list_add_tail(&quirk->quirks_list, &pciback_quirks);
++}
++
++int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
++{
++	int ret = 0;
++	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
++	struct config_field_entry *cfg_entry;
++
++	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
++		if ( OFFSET(cfg_entry) == reg) {
++			ret = 1;
++			break;
++		}
++	}
++	return ret;
++}
++
++int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
++				    *field)
++{
++	int err = 0;
++
++	switch (field->size) {
++	case 1:
++		field->u.b.read = pciback_read_config_byte;
++		field->u.b.write = pciback_write_config_byte;
++		break;
++	case 2:
++		field->u.w.read = pciback_read_config_word;
++		field->u.w.write = pciback_write_config_word;
++		break;
++	case 4:
++		field->u.dw.read = pciback_read_config_dword;
++		field->u.dw.write = pciback_write_config_dword;
++		break;
++	default:
++		err = -EINVAL;
++		goto out;
++	}
++
++	pciback_config_add_field(dev, field);
++
++      out:
++	return err;
++}
++
++int pciback_config_quirks_init(struct pci_dev *dev)
++{
++	struct pciback_config_quirk *quirk;
++	int ret = 0;
++
++	quirk = kzalloc(sizeof(*quirk), GFP_ATOMIC);
++	if (!quirk) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	quirk->devid.vendor = dev->vendor;
++	quirk->devid.device = dev->device;
++	quirk->devid.subvendor = dev->subsystem_vendor;
++	quirk->devid.subdevice = dev->subsystem_device;
++	quirk->devid.class = 0;
++	quirk->devid.class_mask = 0;
++	quirk->devid.driver_data = 0UL;
++
++	quirk->pdev = dev;
++
++	register_quirk(quirk);
++      out:
++	return ret;
++}
++
++void pciback_config_field_free(struct config_field *field)
++{
++	kfree(field);
++}
++
++int pciback_config_quirk_release(struct pci_dev *dev)
++{
++	struct pciback_config_quirk *quirk;
++	int ret = 0;
++
++	quirk = pciback_find_quirk(dev);
++	if (!quirk) {
++		ret = -ENXIO;
++		goto out;
++	}
++
++	list_del(&quirk->quirks_list);
++	kfree(quirk);
++
++      out:
++	return ret;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/conf_space_quirks.h	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,35 @@
++/*
++ * PCI Backend - Data structures for special overlays for broken devices.
++ *
++ * Ryan Wilson <hap9@epoch.ncsc.mil>
++ * Chris Bookholt <hap10@epoch.ncsc.mil>
++ */
++
++#ifndef __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
++#define __XEN_PCIBACK_CONF_SPACE_QUIRKS_H__
++
++#include <linux/pci.h>
++#include <linux/list.h>
++
++struct pciback_config_quirk {
++	struct list_head quirks_list;
++	struct pci_device_id devid;
++	struct pci_dev *pdev;
++};
++
++struct pciback_config_quirk *pciback_find_quirk(struct pci_dev *dev);
++
++int pciback_config_quirks_add_field(struct pci_dev *dev, struct config_field
++				    *field);
++
++int pciback_config_quirks_remove_field(struct pci_dev *dev, int reg);
++
++int pciback_config_quirks_init(struct pci_dev *dev);
++
++void pciback_config_field_free(struct config_field *field);
++
++int pciback_config_quirk_release(struct pci_dev *dev);
++
++int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/controller.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,443 @@
++/*
++ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
++ *      Alex Williamson <alex.williamson@hp.com>
++ *
++ * PCI "Controller" Backend - virtualize PCI bus topology based on PCI
++ * controllers.  Devices under the same PCI controller are exposed on the
++ * same virtual domain:bus.  Within a bus, device slots are virtualized
++ * to compact the bus.
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ * 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/acpi.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include "pciback.h"
++
++#define PCI_MAX_BUSSES	255
++#define PCI_MAX_SLOTS	32
++
++struct controller_dev_entry {
++	struct list_head list;
++	struct pci_dev *dev;
++	unsigned int devfn;
++};
++
++struct controller_list_entry {
++	struct list_head list;
++	struct pci_controller *controller;
++	unsigned int domain;
++	unsigned int bus;
++	unsigned int next_devfn;
++	struct list_head dev_list;
++};
++
++struct controller_dev_data {
++	struct list_head list;
++	unsigned int next_domain;
++	unsigned int next_bus;
++	spinlock_t lock;
++};
++
++struct walk_info {
++	struct pciback_device *pdev;
++	int resource_count;
++	int root_num;
++};
++
++struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
++				    unsigned int domain, unsigned int bus,
++				    unsigned int devfn)
++{
++	struct controller_dev_data *dev_data = pdev->pci_dev_data;
++	struct controller_dev_entry *dev_entry;
++	struct controller_list_entry *cntrl_entry;
++	struct pci_dev *dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
++		if (cntrl_entry->domain != domain ||
++		    cntrl_entry->bus != bus)
++			continue;
++
++		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
++			if (devfn == dev_entry->devfn) {
++				dev = dev_entry->dev;
++				goto found;
++			}
++		}
++	}
++found:
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++
++	return 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;
++	struct controller_list_entry *cntrl_entry;
++	struct pci_controller *dev_controller = PCI_CONTROLLER(dev);
++	unsigned long flags;
++	int ret = 0, found = 0;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	/* Look to see if we already have a domain:bus for this controller */
++	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
++		if (cntrl_entry->controller == dev_controller) {
++			found = 1;
++			break;
++		}
++	}
++
++	if (!found) {
++		cntrl_entry = kmalloc(sizeof(*cntrl_entry), GFP_ATOMIC);
++		if (!cntrl_entry) {
++			ret =  -ENOMEM;
++			goto out;
++		}
++
++		cntrl_entry->controller = dev_controller;
++		cntrl_entry->next_devfn = PCI_DEVFN(0, 0);
++
++		cntrl_entry->domain = dev_data->next_domain;
++		cntrl_entry->bus = dev_data->next_bus++;
++		if (dev_data->next_bus > PCI_MAX_BUSSES) {
++			dev_data->next_domain++;
++			dev_data->next_bus = 0;
++		}
++
++		INIT_LIST_HEAD(&cntrl_entry->dev_list);
++
++		list_add_tail(&cntrl_entry->list, &dev_data->list);
++	}
++
++	if (PCI_SLOT(cntrl_entry->next_devfn) > PCI_MAX_SLOTS) {
++		/*
++		 * While it seems unlikely, this can actually happen if
++		 * a controller has P2P bridges under it.
++		 */
++		xenbus_dev_fatal(pdev->xdev, -ENOSPC, "Virtual bus %04x:%02x "
++				 "is full, no room to export %04x:%02x:%02x.%x",
++				 cntrl_entry->domain, cntrl_entry->bus,
++				 pci_domain_nr(dev->bus), dev->bus->number,
++				 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
++		ret = -ENOSPC;
++		goto out;
++	}
++
++	dev_entry = kmalloc(sizeof(*dev_entry), GFP_ATOMIC);
++	if (!dev_entry) {
++		if (list_empty(&cntrl_entry->dev_list)) {
++			list_del(&cntrl_entry->list);
++			kfree(cntrl_entry);
++		}
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	dev_entry->dev = dev;
++	dev_entry->devfn = cntrl_entry->next_devfn;
++
++	list_add_tail(&dev_entry->list, &cntrl_entry->dev_list);
++
++	cntrl_entry->next_devfn += PCI_DEVFN(1, 0);
++
++out:
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++
++	/* TODO: Publish virtual domain:bus:slot.func here. */
++
++	return ret;
++}
++
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++{
++	struct controller_dev_data *dev_data = pdev->pci_dev_data;
++	struct controller_list_entry *cntrl_entry;
++	struct controller_dev_entry *dev_entry = NULL;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
++		if (cntrl_entry->controller != PCI_CONTROLLER(dev))
++			continue;
++
++		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
++			if (dev_entry->dev == dev) {
++				found_dev = dev_entry->dev;
++				break;
++			}
++		}
++	}
++
++	if (!found_dev) {
++		spin_unlock_irqrestore(&dev_data->lock, flags);
++		return;
++	}
++
++	list_del(&dev_entry->list);
++	kfree(dev_entry);
++
++	if (list_empty(&cntrl_entry->dev_list)) {
++		list_del(&cntrl_entry->list);
++		kfree(cntrl_entry);
++	}
++
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++	pcistub_put_pci_dev(found_dev);
++}
++
++int pciback_init_devices(struct pciback_device *pdev)
++{
++	struct controller_dev_data *dev_data;
++
++	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
++	if (!dev_data)
++		return -ENOMEM;
++
++	spin_lock_init(&dev_data->lock);
++
++	INIT_LIST_HEAD(&dev_data->list);
++
++	/* Starting domain:bus numbers */
++	dev_data->next_domain = 0;
++	dev_data->next_bus = 0;
++
++	pdev->pci_dev_data = dev_data;
++
++	return 0;
++}
++
++static acpi_status write_xenbus_resource(struct acpi_resource *res, void *data)
++{
++	struct walk_info *info = data;
++	struct acpi_resource_address64 addr;
++	acpi_status status;
++	int i, len, err;
++	char str[32], tmp[3];
++	unsigned char *ptr, *buf;
++
++	status = acpi_resource_to_address64(res, &addr);
++
++	/* Do we care about this range?  Let's check. */
++	if (!ACPI_SUCCESS(status) ||
++	    !(addr.resource_type == ACPI_MEMORY_RANGE ||
++	      addr.resource_type == ACPI_IO_RANGE) ||
++	    !addr.address_length || addr.producer_consumer != ACPI_PRODUCER)
++		return AE_OK;
++
++	/*
++	 * Furthermore, we really only care to tell the guest about
++	 * address ranges that require address translation of some sort.
++	 */
++	if (!(addr.resource_type == ACPI_MEMORY_RANGE &&
++	      addr.info.mem.translation) &&
++	    !(addr.resource_type == ACPI_IO_RANGE &&
++	      addr.info.io.translation))
++		return AE_OK;
++	   
++	/* Store the resource in xenbus for the guest */
++	len = snprintf(str, sizeof(str), "root-%d-resource-%d",
++		       info->root_num, info->resource_count);
++	if (unlikely(len >= (sizeof(str) - 1)))
++		return AE_OK;
++
++	buf = kzalloc((sizeof(*res) * 2) + 1, GFP_KERNEL);
++	if (!buf)
++		return AE_OK;
++
++	/* Clean out resource_source */
++	res->data.address64.resource_source.index = 0xFF;
++	res->data.address64.resource_source.string_length = 0;
++	res->data.address64.resource_source.string_ptr = NULL;
++
++	ptr = (unsigned char *)res;
++
++	/* Turn the acpi_resource into an ASCII byte stream */
++	for (i = 0; i < sizeof(*res); i++) {
++		snprintf(tmp, sizeof(tmp), "%02x", ptr[i]);
++		strncat(buf, tmp, 2);
++	}
++
++	err = xenbus_printf(XBT_NIL, info->pdev->xdev->nodename,
++			    str, "%s", buf);
++
++	if (!err)
++		info->resource_count++;
++
++	kfree(buf);
++
++	return AE_OK;
++}
++
++int pciback_publish_pci_roots(struct pciback_device *pdev,
++			      publish_pci_root_cb publish_root_cb)
++{
++	struct controller_dev_data *dev_data = pdev->pci_dev_data;
++	struct controller_list_entry *cntrl_entry;
++	int i, root_num, len, err = 0;
++	unsigned int domain, bus;
++	char str[64];
++	struct walk_info info;
++
++	spin_lock(&dev_data->lock);
++
++	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
++		/* First publish all the domain:bus info */
++		err = publish_root_cb(pdev, cntrl_entry->domain,
++				      cntrl_entry->bus);
++		if (err)
++			goto out;
++
++		/*
++ 		 * Now figure out which root-%d this belongs to
++		 * so we can associate resources with it.
++		 */
++		err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
++				   "root_num", "%d", &root_num);
++
++		if (err != 1)
++			goto out;
++
++		for (i = 0; i < root_num; 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->nodename,
++					   str, "%x:%x", &domain, &bus);
++			if (err != 2)
++				goto out;
++
++			/* Is this the one we just published? */
++			if (domain == cntrl_entry->domain &&
++			    bus == cntrl_entry->bus)
++				break;
++		}
++
++		if (i == root_num)
++			goto out;
++
++		info.pdev = pdev;
++		info.resource_count = 0;
++		info.root_num = i;
++
++		/* Let ACPI do the heavy lifting on decoding resources */
++		acpi_walk_resources(cntrl_entry->controller->acpi_handle,
++				    METHOD_NAME__CRS, write_xenbus_resource,
++				    &info);
++
++		/* No resouces.  OK.  On to the next one */
++		if (!info.resource_count)
++			continue;
++
++		/* Store the number of resources we wrote for this root-%d */
++		len = snprintf(str, sizeof(str), "root-%d-resources", i);
++		if (unlikely(len >= (sizeof(str) - 1))) {
++			err = -ENOMEM;
++			goto out;
++		}
++
++		err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
++				    "%d", info.resource_count);
++		if (err)
++			goto out;
++	}
++
++	/* Finally, write some magic to synchronize with the guest. */
++	len = snprintf(str, sizeof(str), "root-resource-magic");
++	if (unlikely(len >= (sizeof(str) - 1))) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
++			    "%lx", (sizeof(struct acpi_resource) * 2) + 1);
++
++out:
++	spin_unlock(&dev_data->lock);
++
++	return err;
++}
++
++void pciback_release_devices(struct pciback_device *pdev)
++{
++	struct controller_dev_data *dev_data = pdev->pci_dev_data;
++	struct controller_list_entry *cntrl_entry, *c;
++	struct controller_dev_entry *dev_entry, *d;
++
++	list_for_each_entry_safe(cntrl_entry, c, &dev_data->list, list) {
++		list_for_each_entry_safe(dev_entry, d,
++					 &cntrl_entry->dev_list, list) {
++			list_del(&dev_entry->list);
++			pcistub_put_pci_dev(dev_entry->dev);
++			kfree(dev_entry);
++		}
++		list_del(&cntrl_entry->list);
++		kfree(cntrl_entry);
++	}
++
++	kfree(dev_data);
++	pdev->pci_dev_data = NULL;
++}
++
++int pciback_get_pcifront_dev(struct pci_dev *pcidev, 
++		struct pciback_device *pdev, 
++		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
++{
++	struct controller_dev_data *dev_data = pdev->pci_dev_data;
++	struct controller_dev_entry *dev_entry;
++	struct controller_list_entry *cntrl_entry;
++	unsigned long flags;
++	int found = 0;
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	list_for_each_entry(cntrl_entry, &dev_data->list, list) {
++		list_for_each_entry(dev_entry, &cntrl_entry->dev_list, list) {
++			if ( (dev_entry->dev->bus->number == 
++					pcidev->bus->number) &&
++			  	(dev_entry->dev->devfn ==
++					pcidev->devfn) &&
++				(pci_domain_nr(dev_entry->dev->bus) ==
++					pci_domain_nr(pcidev->bus)))
++			{
++				found = 1;
++				*domain = cntrl_entry->domain;
++				*bus = cntrl_entry->bus;
++				*devfn = dev_entry->devfn;
++				goto out;
++			}
++		}
++	}
++out:
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++	return found;
++
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/passthrough.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,176 @@
++/*
++ * PCI Backend - Provides restricted access to the real PCI bus topology
++ *               to the frontend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include "pciback.h"
++
++struct passthrough_dev_data {
++	/* Access to dev_list must be protected by lock */
++	struct list_head dev_list;
++	spinlock_t lock;
++};
++
++struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
++				    unsigned int domain, unsigned int bus,
++				    unsigned int devfn)
++{
++	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
++	struct pci_dev_entry *dev_entry;
++	struct pci_dev *dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
++		if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus)
++		    && bus == (unsigned int)dev_entry->dev->bus->number
++		    && devfn == dev_entry->dev->devfn) {
++			dev = dev_entry->dev;
++			break;
++		}
++	}
++
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++
++	return 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)
++		return -ENOMEM;
++	dev_entry->dev = dev;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++	list_add_tail(&dev_entry->list, &dev_data->dev_list);
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++
++	/* 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)
++{
++	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
++	struct pci_dev_entry *dev_entry, *t;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&dev_data->lock, flags);
++
++	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
++		if (dev_entry->dev == dev) {
++			list_del(&dev_entry->list);
++			found_dev = dev_entry->dev;
++			kfree(dev_entry);
++		}
++	}
++
++	spin_unlock_irqrestore(&dev_data->lock, flags);
++
++	if (found_dev)
++		pcistub_put_pci_dev(found_dev);
++}
++
++int pciback_init_devices(struct pciback_device *pdev)
++{
++	struct passthrough_dev_data *dev_data;
++
++	dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL);
++	if (!dev_data)
++		return -ENOMEM;
++
++	spin_lock_init(&dev_data->lock);
++
++	INIT_LIST_HEAD(&dev_data->dev_list);
++
++	pdev->pci_dev_data = dev_data;
++
++	return 0;
++}
++
++int pciback_publish_pci_roots(struct pciback_device *pdev,
++			      publish_pci_root_cb publish_root_cb)
++{
++	int err = 0;
++	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
++	struct pci_dev_entry *dev_entry, *e;
++	struct pci_dev *dev;
++	int found;
++	unsigned int domain, bus;
++
++	spin_lock(&dev_data->lock);
++
++	list_for_each_entry(dev_entry, &dev_data->dev_list, list) {
++		/* Only publish this device as a root if none of its
++		 * parent bridges are exported
++		 */
++		found = 0;
++		dev = dev_entry->dev->bus->self;
++		for (; !found && dev != NULL; dev = dev->bus->self) {
++			list_for_each_entry(e, &dev_data->dev_list, list) {
++				if (dev == e->dev) {
++					found = 1;
++					break;
++				}
++			}
++		}
++
++		domain = (unsigned int)pci_domain_nr(dev_entry->dev->bus);
++		bus = (unsigned int)dev_entry->dev->bus->number;
++
++		if (!found) {
++			err = publish_root_cb(pdev, domain, bus);
++			if (err)
++				break;
++		}
++	}
++
++	spin_unlock(&dev_data->lock);
++
++	return err;
++}
++
++void pciback_release_devices(struct pciback_device *pdev)
++{
++	struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
++	struct pci_dev_entry *dev_entry, *t;
++
++	list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
++		list_del(&dev_entry->list);
++		pcistub_put_pci_dev(dev_entry->dev);
++		kfree(dev_entry);
++	}
++
++	kfree(dev_data);
++	pdev->pci_dev_data = NULL;
++}
++
++int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
++		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
++
++{
++	*domain = pci_domain_nr(pcidev->bus);
++	*bus = pcidev->bus->number;
++	*devfn = pcidev->devfn;
++	return 1;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/pci_stub.c	2009-06-09 15:01:37.000000000 +0200
+@@ -0,0 +1,1316 @@
++/*
++ * PCI Stub Driver - Grabs devices in backend to be exported later
++ *
++ * Ryan Wilson <hap9@epoch.ncsc.mil>
++ * Chris Bookholt <hap10@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/rwsem.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/kref.h>
++#include <linux/pci.h>
++#include <linux/wait.h>
++#include <asm/atomic.h>
++#include <xen/evtchn.h>
++#include "pciback.h"
++#include "conf_space.h"
++#include "conf_space_quirks.h"
++
++static char *pci_devs_to_hide = NULL;
++wait_queue_head_t aer_wait_queue;
++/*Add sem for sync AER handling and pciback remove/reconfigue ops,
++* We want to avoid in middle of AER ops, pciback devices is being removed
++*/
++static DECLARE_RWSEM(pcistub_sem);
++module_param_named(hide, pci_devs_to_hide, charp, 0444);
++
++struct pcistub_device_id {
++	struct list_head slot_list;
++	int domain;
++	unsigned char bus;
++	unsigned int devfn;
++};
++static LIST_HEAD(pcistub_device_ids);
++static DEFINE_SPINLOCK(device_ids_lock);
++
++struct pcistub_device {
++	struct kref kref;
++	struct list_head dev_list;
++	spinlock_t lock;
++
++	struct pci_dev *dev;
++	struct pciback_device *pdev;	/* non-NULL if struct pci_dev is in use */
++};
++
++/* Access to pcistub_devices & seized_devices lists and the initialize_devices
++ * flag must be locked with pcistub_devices_lock
++ */
++static DEFINE_SPINLOCK(pcistub_devices_lock);
++static LIST_HEAD(pcistub_devices);
++
++/* wait for device_initcall before initializing our devices
++ * (see pcistub_init_devices_late)
++ */
++static int initialize_devices = 0;
++static LIST_HEAD(seized_devices);
++
++static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++
++	dev_dbg(&dev->dev, "pcistub_device_alloc\n");
++
++	psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
++	if (!psdev)
++		return NULL;
++
++	psdev->dev = pci_dev_get(dev);
++	if (!psdev->dev) {
++		kfree(psdev);
++		return NULL;
++	}
++
++	kref_init(&psdev->kref);
++	spin_lock_init(&psdev->lock);
++
++	return psdev;
++}
++
++/* Don't call this directly as it's called by pcistub_device_put */
++static void pcistub_device_release(struct kref *kref)
++{
++	struct pcistub_device *psdev;
++
++	psdev = container_of(kref, struct pcistub_device, kref);
++
++	dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
++
++	/* Clean-up the device */
++	pciback_reset_device(psdev->dev);
++	pciback_config_free_dyn_fields(psdev->dev);
++	pciback_config_free_dev(psdev->dev);
++	kfree(pci_get_drvdata(psdev->dev));
++	pci_set_drvdata(psdev->dev, NULL);
++
++	pci_dev_put(psdev->dev);
++
++	kfree(psdev);
++}
++
++static inline void pcistub_device_get(struct pcistub_device *psdev)
++{
++	kref_get(&psdev->kref);
++}
++
++static inline void pcistub_device_put(struct pcistub_device *psdev)
++{
++	kref_put(&psdev->kref, pcistub_device_release);
++}
++
++static struct pcistub_device *pcistub_device_find(int domain, int bus,
++						  int slot, int func)
++{
++	struct pcistub_device *psdev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (psdev->dev != NULL
++		    && domain == pci_domain_nr(psdev->dev->bus)
++		    && bus == psdev->dev->bus->number
++		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
++			pcistub_device_get(psdev);
++			goto out;
++		}
++	}
++
++	/* didn't find it */
++	psdev = NULL;
++
++      out:
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++	return psdev;
++}
++
++static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev,
++						  struct pcistub_device *psdev)
++{
++	struct pci_dev *pci_dev = NULL;
++	unsigned long flags;
++
++	pcistub_device_get(psdev);
++
++	spin_lock_irqsave(&psdev->lock, flags);
++	if (!psdev->pdev) {
++		psdev->pdev = pdev;
++		pci_dev = psdev->dev;
++	}
++	spin_unlock_irqrestore(&psdev->lock, flags);
++
++	if (!pci_dev)
++		pcistub_device_put(psdev);
++
++	return pci_dev;
++}
++
++struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev,
++					    int domain, int bus,
++					    int slot, int func)
++{
++	struct pcistub_device *psdev;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (psdev->dev != NULL
++		    && domain == pci_domain_nr(psdev->dev->bus)
++		    && bus == psdev->dev->bus->number
++		    && PCI_DEVFN(slot, func) == psdev->dev->devfn) {
++			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
++			break;
++		}
++	}
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++	return found_dev;
++}
++
++struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev,
++				    struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (psdev->dev == dev) {
++			found_dev = pcistub_device_get_pci_dev(pdev, psdev);
++			break;
++		}
++	}
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++	return found_dev;
++}
++
++void pcistub_put_pci_dev(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev, *found_psdev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (psdev->dev == dev) {
++			found_psdev = psdev;
++			break;
++		}
++	}
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++	/*hold this lock for avoiding breaking link between
++	* pcistub and pciback when AER is in processing
++	*/
++	down_write(&pcistub_sem);
++	/* Cleanup our device
++	 * (so it's ready for the next domain)
++	 */
++	pciback_reset_device(found_psdev->dev);
++	pciback_config_free_dyn_fields(found_psdev->dev);
++	pciback_config_reset_dev(found_psdev->dev);
++
++	spin_lock_irqsave(&found_psdev->lock, flags);
++	found_psdev->pdev = NULL;
++	spin_unlock_irqrestore(&found_psdev->lock, flags);
++
++	pcistub_device_put(found_psdev);
++	up_write(&pcistub_sem);
++}
++
++static int __devinit pcistub_match_one(struct pci_dev *dev,
++				       struct pcistub_device_id *pdev_id)
++{
++	/* Match the specified device by domain, bus, slot, func and also if
++	 * any of the device's parent bridges match.
++	 */
++	for (; dev != NULL; dev = dev->bus->self) {
++		if (pci_domain_nr(dev->bus) == pdev_id->domain
++		    && dev->bus->number == pdev_id->bus
++		    && dev->devfn == pdev_id->devfn)
++			return 1;
++
++		/* Sometimes topmost bridge links to itself. */
++		if (dev == dev->bus->self)
++			break;
++	}
++
++	return 0;
++}
++
++static int __devinit pcistub_match(struct pci_dev *dev)
++{
++	struct pcistub_device_id *pdev_id;
++	unsigned long flags;
++	int found = 0;
++
++	spin_lock_irqsave(&device_ids_lock, flags);
++	list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
++		if (pcistub_match_one(dev, pdev_id)) {
++			found = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&device_ids_lock, flags);
++
++	return found;
++}
++
++static int __devinit pcistub_init_device(struct pci_dev *dev)
++{
++	struct pciback_dev_data *dev_data;
++	int err = 0;
++
++	dev_dbg(&dev->dev, "initializing...\n");
++
++	/* The PCI backend is not intended to be a module (or to work with
++	 * removable PCI devices (yet). If it were, pciback_config_free()
++	 * would need to be called somewhere to free the memory allocated
++	 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
++	 */
++	dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
++	if (!dev_data) {
++		err = -ENOMEM;
++		goto out;
++	}
++	pci_set_drvdata(dev, dev_data);
++
++	dev_dbg(&dev->dev, "initializing config\n");
++
++	init_waitqueue_head(&aer_wait_queue);
++	err = pciback_config_init_dev(dev);
++	if (err)
++		goto out;
++
++	/* HACK: Force device (& ACPI) to determine what IRQ it's on - we
++	 * must do this here because pcibios_enable_device may specify
++	 * the pci device's true irq (and possibly its other resources)
++	 * if they differ from what's in the configuration space.
++	 * This makes the assumption that the device's resources won't
++	 * change after this point (otherwise this code may break!)
++	 */
++	dev_dbg(&dev->dev, "enabling device\n");
++	err = pci_enable_device(dev);
++	if (err)
++		goto config_release;
++
++	/* Now disable the device (this also ensures some private device
++	 * data is setup before we export)
++	 */
++	dev_dbg(&dev->dev, "reset device\n");
++	pciback_reset_device(dev);
++
++	return 0;
++
++      config_release:
++	pciback_config_free_dev(dev);
++
++      out:
++	pci_set_drvdata(dev, NULL);
++	kfree(dev_data);
++	return err;
++}
++
++/*
++ * Because some initialization still happens on
++ * devices during fs_initcall, we need to defer
++ * full initialization of our devices until
++ * device_initcall.
++ */
++static int __init pcistub_init_devices_late(void)
++{
++	struct pcistub_device *psdev;
++	unsigned long flags;
++	int err = 0;
++
++	pr_debug("pciback: pcistub_init_devices_late\n");
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	while (!list_empty(&seized_devices)) {
++		psdev = container_of(seized_devices.next,
++				     struct pcistub_device, dev_list);
++		list_del(&psdev->dev_list);
++
++		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++		err = pcistub_init_device(psdev->dev);
++		if (err) {
++			dev_err(&psdev->dev->dev,
++				"error %d initializing device\n", err);
++			kfree(psdev);
++			psdev = NULL;
++		}
++
++		spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++		if (psdev)
++			list_add_tail(&psdev->dev_list, &pcistub_devices);
++	}
++
++	initialize_devices = 1;
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++	return 0;
++}
++
++static int __devinit pcistub_seize(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++	unsigned long flags;
++	int err = 0;
++
++	psdev = pcistub_device_alloc(dev);
++	if (!psdev)
++		return -ENOMEM;
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	if (initialize_devices) {
++		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++		/* don't want irqs disabled when calling pcistub_init_device */
++		err = pcistub_init_device(psdev->dev);
++
++		spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++		if (!err)
++			list_add(&psdev->dev_list, &pcistub_devices);
++	} else {
++		dev_dbg(&dev->dev, "deferring initialization\n");
++		list_add(&psdev->dev_list, &seized_devices);
++	}
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++	if (err)
++		pcistub_device_put(psdev);
++
++	return err;
++}
++
++static int __devinit pcistub_probe(struct pci_dev *dev,
++				   const struct pci_device_id *id)
++{
++	int err = 0;
++
++	dev_dbg(&dev->dev, "probing...\n");
++
++	if (pcistub_match(dev)) {
++
++		if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
++		    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
++			dev_err(&dev->dev, "can't export pci devices that "
++				"don't have a normal (0) or bridge (1) "
++				"header type!\n");
++			err = -ENODEV;
++			goto out;
++		}
++
++		dev_info(&dev->dev, "seizing device\n");
++		err = pcistub_seize(dev);
++#ifdef CONFIG_PCI_GUESTDEV
++	} else if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
++		if (!pci_is_guestdev(dev)) {
++			err = -ENODEV;
++			goto out;
++		}
++
++		dev_info(&dev->dev, "seizing device\n");
++		err = pcistub_seize(dev);
++#endif /* CONFIG_PCI_GUESTDEV */
++	} else
++		/* Didn't find the device */
++		err = -ENODEV;
++
++      out:
++	return err;
++}
++
++static void pcistub_remove(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev, *found_psdev = NULL;
++	unsigned long flags;
++
++	dev_dbg(&dev->dev, "removing\n");
++
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++
++	pciback_config_quirk_release(dev);
++
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (psdev->dev == dev) {
++			found_psdev = psdev;
++			break;
++		}
++	}
++
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++	if (found_psdev) {
++		dev_dbg(&dev->dev, "found device to remove - in use? %p\n",
++			found_psdev->pdev);
++
++		if (found_psdev->pdev) {
++			printk(KERN_WARNING "pciback: ****** removing device "
++			       "%s while still in-use! ******\n",
++			       pci_name(found_psdev->dev));
++			printk(KERN_WARNING "pciback: ****** driver domain may "
++			       "still access this device's i/o resources!\n");
++			printk(KERN_WARNING "pciback: ****** shutdown driver "
++			       "domain before binding device\n");
++			printk(KERN_WARNING "pciback: ****** to other drivers "
++			       "or domains\n");
++
++			pciback_release_pci_dev(found_psdev->pdev,
++						found_psdev->dev);
++		}
++
++		spin_lock_irqsave(&pcistub_devices_lock, flags);
++		list_del(&found_psdev->dev_list);
++		spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++
++		/* the final put for releasing from the list */
++		pcistub_device_put(found_psdev);
++	}
++}
++
++static const struct pci_device_id pcistub_ids[] = {
++	{
++	 .vendor = PCI_ANY_ID,
++	 .device = PCI_ANY_ID,
++	 .subvendor = PCI_ANY_ID,
++	 .subdevice = PCI_ANY_ID,
++	 },
++	{0,},
++};
++
++static void kill_domain_by_device(struct pcistub_device *psdev)
++{
++	struct xenbus_transaction xbt;
++	int err;
++	char nodename[1024];
++
++	if (!psdev) 
++		dev_err(&psdev->dev->dev,
++			"device is NULL when do AER recovery/kill_domain\n");
++	sprintf(nodename, "/local/domain/0/backend/pci/%d/0", 
++		psdev->pdev->xdev->otherend_id);
++	nodename[strlen(nodename)] = '\0';
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err)
++	{
++		dev_err(&psdev->dev->dev,
++			"error %d when start xenbus transaction\n", err);
++		return;
++	}
++	/*PV AER handlers will set this flag*/
++	xenbus_printf(xbt, nodename, "aerState" , "aerfail" );
++	err = xenbus_transaction_end(xbt, 0);
++	if (err)
++	{
++		if (err == -EAGAIN)
++			goto again;
++		dev_err(&psdev->dev->dev,
++			"error %d when end xenbus transaction\n", err);
++		return;
++	}
++}
++
++/* For each aer recovery step error_detected, mmio_enabled, etc, front_end and
++ * backend need to have cooperation. In pciback, those steps will do similar
++ * jobs: send service request and waiting for front_end response. 
++*/
++static pci_ers_result_t common_process(struct pcistub_device *psdev, 
++		pci_channel_state_t state, int aer_cmd, pci_ers_result_t result)
++{
++	pci_ers_result_t res = result;
++	struct xen_pcie_aer_op *aer_op;
++	int ret;
++
++	/*with PV AER drivers*/
++	aer_op = &(psdev->pdev->sh_info->aer_op);
++	aer_op->cmd = aer_cmd ;
++	/*useful for error_detected callback*/
++	aer_op->err = state;
++	/*pcifront_end BDF*/
++	ret = pciback_get_pcifront_dev(psdev->dev, psdev->pdev,
++		&aer_op->domain, &aer_op->bus, &aer_op->devfn);
++	if (!ret) {
++		dev_err(&psdev->dev->dev,
++			"pciback: failed to get pcifront device\n");
++		return PCI_ERS_RESULT_NONE; 
++	}
++	wmb();
++
++	dev_dbg(&psdev->dev->dev, 
++			"pciback: aer_op %x dom %x bus %x devfn %x\n",  
++			aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
++	/*local flag to mark there's aer request, pciback callback will use this
++	* flag to judge whether we need to check pci-front give aer service
++	* ack signal
++	*/
++	set_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
++
++	/*It is possible that a pcifront conf_read_write ops request invokes
++	* the callback which cause the spurious execution of wake_up. 
++	* Yet it is harmless and better than a spinlock here
++	*/
++	set_bit(_XEN_PCIB_active, 
++		(unsigned long *)&psdev->pdev->sh_info->flags);
++	wmb();
++	notify_remote_via_irq(psdev->pdev->evtchn_irq);
++
++	ret = wait_event_timeout(aer_wait_queue, !(test_bit(_XEN_PCIB_active,
++                (unsigned long *)&psdev->pdev->sh_info->flags)), 300*HZ);
++
++	if (!ret) {
++		if (test_bit(_XEN_PCIB_active, 
++			(unsigned long *)&psdev->pdev->sh_info->flags)) {
++			dev_err(&psdev->dev->dev, 
++				"pcifront aer process not responding!\n");
++			clear_bit(_XEN_PCIB_active,
++			  (unsigned long *)&psdev->pdev->sh_info->flags);
++			aer_op->err = PCI_ERS_RESULT_NONE;
++			return res;
++		}
++	}
++	clear_bit(_PCIB_op_pending, (unsigned long *)&psdev->pdev->flags);
++
++	if ( test_bit( _XEN_PCIF_active,
++		(unsigned long*)&psdev->pdev->sh_info->flags)) {
++		dev_dbg(&psdev->dev->dev, 
++			"schedule pci_conf service in pciback \n");
++		test_and_schedule_op(psdev->pdev);
++	}
++
++	res = (pci_ers_result_t)aer_op->err;
++	return res;
++} 
++
++/*
++* pciback_slot_reset: it will send the slot_reset request to  pcifront in case
++* of the device driver could provide this service, and then wait for pcifront
++* ack.
++* @dev: pointer to PCI devices
++* return value is used by aer_core do_recovery policy
++*/
++static pci_ers_result_t pciback_slot_reset(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++	pci_ers_result_t result;
++
++	result = PCI_ERS_RESULT_RECOVERED;
++	dev_dbg(&dev->dev, "pciback_slot_reset(bus:%x,devfn:%x)\n",
++		dev->bus->number, dev->devfn);
++
++	down_write(&pcistub_sem);
++	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
++				dev->bus->number,
++				PCI_SLOT(dev->devfn),
++				PCI_FUNC(dev->devfn));
++
++	if ( !psdev || !psdev->pdev )
++	{
++		dev_err(&dev->dev, 
++			"pciback device is not found/assigned\n");
++		goto end;
++	}
++
++	if ( !psdev->pdev->sh_info )
++	{
++		dev_err(&dev->dev, "pciback device is not connected or owned"
++			" by HVM, kill it\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++
++	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
++		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
++		dev_err(&dev->dev, 
++			"guest with no AER driver should have been killed\n");
++		goto release;
++	}
++	result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
++
++	if (result == PCI_ERS_RESULT_NONE ||
++		result == PCI_ERS_RESULT_DISCONNECT) {
++		dev_dbg(&dev->dev, 
++			"No AER slot_reset service or disconnected!\n");
++		kill_domain_by_device(psdev);
++	}
++release:
++	pcistub_device_put(psdev);
++end:
++	up_write(&pcistub_sem);
++	return result;
++
++}
++
++
++/*pciback_mmio_enabled: it will send the mmio_enabled request to  pcifront 
++* in case of the device driver could provide this service, and then wait 
++* for pcifront ack.
++* @dev: pointer to PCI devices
++* return value is used by aer_core do_recovery policy
++*/
++
++static pci_ers_result_t pciback_mmio_enabled(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++	pci_ers_result_t result;
++
++	result = PCI_ERS_RESULT_RECOVERED;
++	dev_dbg(&dev->dev, "pciback_mmio_enabled(bus:%x,devfn:%x)\n",
++		dev->bus->number, dev->devfn);
++
++	down_write(&pcistub_sem);
++	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
++				dev->bus->number,
++				PCI_SLOT(dev->devfn),
++				PCI_FUNC(dev->devfn));
++
++	if ( !psdev || !psdev->pdev )
++	{
++		dev_err(&dev->dev, 
++			"pciback device is not found/assigned\n");
++		goto end;
++	}
++
++	if ( !psdev->pdev->sh_info )
++	{
++		dev_err(&dev->dev, "pciback device is not connected or owned"
++			" by HVM, kill it\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++
++	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
++		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
++		dev_err(&dev->dev, 
++			"guest with no AER driver should have been killed\n");
++		goto release;
++	}
++	result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
++
++	if (result == PCI_ERS_RESULT_NONE ||
++		result == PCI_ERS_RESULT_DISCONNECT) {
++		dev_dbg(&dev->dev, 
++			"No AER mmio_enabled service or disconnected!\n");
++		kill_domain_by_device(psdev);
++	}
++release:
++	pcistub_device_put(psdev);
++end:
++	up_write(&pcistub_sem);
++	return result;
++}
++
++/*pciback_error_detected: it will send the error_detected request to  pcifront 
++* in case of the device driver could provide this service, and then wait 
++* for pcifront ack.
++* @dev: pointer to PCI devices
++* @error: the current PCI connection state
++* return value is used by aer_core do_recovery policy
++*/
++
++static pci_ers_result_t pciback_error_detected(struct pci_dev *dev,
++	pci_channel_state_t error)
++{
++	struct pcistub_device *psdev;
++	pci_ers_result_t result;
++
++	result = PCI_ERS_RESULT_CAN_RECOVER;
++	dev_dbg(&dev->dev, "pciback_error_detected(bus:%x,devfn:%x)\n",
++		dev->bus->number, dev->devfn);
++
++	down_write(&pcistub_sem);
++	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
++				dev->bus->number,
++				PCI_SLOT(dev->devfn),
++				PCI_FUNC(dev->devfn));
++
++	if ( !psdev || !psdev->pdev )
++	{
++		dev_err(&dev->dev, 
++			"pciback device is not found/assigned\n");
++		goto end;
++	}
++
++	if ( !psdev->pdev->sh_info )
++	{
++		dev_err(&dev->dev, "pciback device is not connected or owned"
++			" by HVM, kill it\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++
++	/*Guest owns the device yet no aer handler regiested, kill guest*/
++	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
++		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
++		dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++	result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
++
++	if (result == PCI_ERS_RESULT_NONE ||
++		result == PCI_ERS_RESULT_DISCONNECT) {
++		dev_dbg(&dev->dev, 
++			"No AER error_detected service or disconnected!\n");
++		kill_domain_by_device(psdev);
++	}
++release:
++	pcistub_device_put(psdev);
++end:
++	up_write(&pcistub_sem);
++	return result;
++}
++
++/*pciback_error_resume: it will send the error_resume request to  pcifront 
++* in case of the device driver could provide this service, and then wait 
++* for pcifront ack.
++* @dev: pointer to PCI devices
++*/
++
++static void pciback_error_resume(struct pci_dev *dev)
++{
++	struct pcistub_device *psdev;
++
++	dev_dbg(&dev->dev, "pciback_error_resume(bus:%x,devfn:%x)\n",
++		dev->bus->number, dev->devfn);
++
++	down_write(&pcistub_sem);
++	psdev = pcistub_device_find(pci_domain_nr(dev->bus),
++				dev->bus->number,
++				PCI_SLOT(dev->devfn),
++				PCI_FUNC(dev->devfn));
++
++	if ( !psdev || !psdev->pdev )
++	{
++		dev_err(&dev->dev, 
++			"pciback device is not found/assigned\n");
++		goto end;
++	}
++
++	if ( !psdev->pdev->sh_info )
++	{
++		dev_err(&dev->dev, "pciback device is not connected or owned"
++			" by HVM, kill it\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++
++	if ( !test_bit(_XEN_PCIB_AERHANDLER, 
++		(unsigned long *)&psdev->pdev->sh_info->flags) ) {
++		dev_err(&dev->dev, 
++			"guest with no AER driver should have been killed\n");
++		kill_domain_by_device(psdev);
++		goto release;
++	}
++	common_process(psdev, 1, XEN_PCI_OP_aer_resume, PCI_ERS_RESULT_RECOVERED);
++release:
++	pcistub_device_put(psdev);
++end:
++	up_write(&pcistub_sem);
++	return;
++}
++
++/*add pciback AER handling*/
++static struct pci_error_handlers pciback_error_handler = {
++	.error_detected = pciback_error_detected,
++	.mmio_enabled = pciback_mmio_enabled,
++	.slot_reset = pciback_slot_reset,
++	.resume = pciback_error_resume,
++};
++
++/*
++ * Note: There is no MODULE_DEVICE_TABLE entry here because this isn't
++ * for a normal device. I don't want it to be loaded automatically.
++ */
++
++static struct pci_driver pciback_pci_driver = {
++	.name = "pciback",
++	.id_table = pcistub_ids,
++	.probe = pcistub_probe,
++	.remove = pcistub_remove,
++	.err_handler = &pciback_error_handler,
++};
++
++static inline int str_to_slot(const char *buf, int *domain, int *bus,
++			      int *slot, int *func)
++{
++	int err;
++
++	err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
++	if (err == 4)
++		return 0;
++	else if (err < 0)
++		return -EINVAL;
++
++	/* try again without domain */
++	*domain = 0;
++	err = sscanf(buf, " %x:%x.%x", bus, slot, func);
++	if (err == 3)
++		return 0;
++
++	return -EINVAL;
++}
++
++static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
++			       *slot, int *func, int *reg, int *size, int *mask)
++{
++	int err;
++
++	err =
++	    sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot,
++		   func, reg, size, mask);
++	if (err == 7)
++		return 0;
++	return -EINVAL;
++}
++
++static int pcistub_device_id_add(int domain, int bus, int slot, int func)
++{
++	struct pcistub_device_id *pci_dev_id;
++	unsigned long flags;
++
++	pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
++	if (!pci_dev_id)
++		return -ENOMEM;
++
++	pci_dev_id->domain = domain;
++	pci_dev_id->bus = bus;
++	pci_dev_id->devfn = PCI_DEVFN(slot, func);
++
++	pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
++		 domain, bus, slot, func);
++
++	spin_lock_irqsave(&device_ids_lock, flags);
++	list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
++	spin_unlock_irqrestore(&device_ids_lock, flags);
++
++	return 0;
++}
++
++static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
++{
++	struct pcistub_device_id *pci_dev_id, *t;
++	int devfn = PCI_DEVFN(slot, func);
++	int err = -ENOENT;
++	unsigned long flags;
++
++	spin_lock_irqsave(&device_ids_lock, flags);
++	list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, slot_list) {
++
++		if (pci_dev_id->domain == domain
++		    && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) {
++			/* Don't break; here because it's possible the same
++			 * slot could be in the list more than once
++			 */
++			list_del(&pci_dev_id->slot_list);
++			kfree(pci_dev_id);
++
++			err = 0;
++
++			pr_debug("pciback: removed %04x:%02x:%02x.%01x from "
++				 "seize list\n", domain, bus, slot, func);
++		}
++	}
++	spin_unlock_irqrestore(&device_ids_lock, flags);
++
++	return err;
++}
++
++static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
++			   int size, int mask)
++{
++	int err = 0;
++	struct pcistub_device *psdev;
++	struct pci_dev *dev;
++	struct config_field *field;
++
++	psdev = pcistub_device_find(domain, bus, slot, func);
++	if (!psdev || !psdev->dev) {
++		err = -ENODEV;
++		goto out;
++	}
++	dev = psdev->dev;
++
++	field = kzalloc(sizeof(*field), GFP_ATOMIC);
++	if (!field) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	field->offset = reg;
++	field->size = size;
++	field->mask = mask;
++	field->init = NULL;
++	field->reset = NULL;
++	field->release = NULL;
++	field->clean = pciback_config_field_free;
++
++	err = pciback_config_quirks_add_field(dev, field);
++	if (err)
++		kfree(field);
++      out:
++	return err;
++}
++
++static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
++				size_t count)
++{
++	int domain, bus, slot, func;
++	int err;
++
++	err = str_to_slot(buf, &domain, &bus, &slot, &func);
++	if (err)
++		goto out;
++
++	err = pcistub_device_id_add(domain, bus, slot, func);
++
++      out:
++	if (!err)
++		err = count;
++	return err;
++}
++
++DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
++
++static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
++				   size_t count)
++{
++	int domain, bus, slot, func;
++	int err;
++
++	err = str_to_slot(buf, &domain, &bus, &slot, &func);
++	if (err)
++		goto out;
++
++	err = pcistub_device_id_remove(domain, bus, slot, func);
++
++      out:
++	if (!err)
++		err = count;
++	return err;
++}
++
++DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
++
++static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
++{
++	struct pcistub_device_id *pci_dev_id;
++	size_t count = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&device_ids_lock, flags);
++	list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) {
++		if (count >= PAGE_SIZE)
++			break;
++
++		count += scnprintf(buf + count, PAGE_SIZE - count,
++				   "%04x:%02x:%02x.%01x\n",
++				   pci_dev_id->domain, pci_dev_id->bus,
++				   PCI_SLOT(pci_dev_id->devfn),
++				   PCI_FUNC(pci_dev_id->devfn));
++	}
++	spin_unlock_irqrestore(&device_ids_lock, flags);
++
++	return count;
++}
++
++DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
++
++static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
++				 size_t count)
++{
++	int domain, bus, slot, func, reg, size, mask;
++	int err;
++
++	err = str_to_quirk(buf, &domain, &bus, &slot, &func, &reg, &size,
++			   &mask);
++	if (err)
++		goto out;
++
++	err = pcistub_reg_add(domain, bus, slot, func, reg, size, mask);
++
++      out:
++	if (!err)
++		err = count;
++	return err;
++}
++
++static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
++{
++	int count = 0;
++	unsigned long flags;
++	extern struct list_head pciback_quirks;
++	struct pciback_config_quirk *quirk;
++	struct pciback_dev_data *dev_data;
++	const struct config_field *field;
++	const struct config_field_entry *cfg_entry;
++
++	spin_lock_irqsave(&device_ids_lock, flags);
++	list_for_each_entry(quirk, &pciback_quirks, quirks_list) {
++		if (count >= PAGE_SIZE)
++			goto out;
++
++		count += scnprintf(buf + count, PAGE_SIZE - count,
++				   "%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
++				   quirk->pdev->bus->number,
++				   PCI_SLOT(quirk->pdev->devfn),
++				   PCI_FUNC(quirk->pdev->devfn),
++				   quirk->devid.vendor, quirk->devid.device,
++				   quirk->devid.subvendor,
++				   quirk->devid.subdevice);
++
++		dev_data = pci_get_drvdata(quirk->pdev);
++
++		list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
++			field = cfg_entry->field;
++			if (count >= PAGE_SIZE)
++				goto out;
++
++			count += scnprintf(buf + count, PAGE_SIZE - count,
++					   "\t\t%08x:%01x:%08x\n",
++					   cfg_entry->base_offset + field->offset, 
++					   field->size, field->mask);
++		}
++	}
++
++      out:
++	spin_unlock_irqrestore(&device_ids_lock, flags);
++
++	return count;
++}
++
++DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
++
++static ssize_t permissive_add(struct device_driver *drv, const char *buf,
++			      size_t count)
++{
++	int domain, bus, slot, func;
++	int err;
++	struct pcistub_device *psdev;
++	struct pciback_dev_data *dev_data;
++	err = str_to_slot(buf, &domain, &bus, &slot, &func);
++	if (err)
++		goto out;
++	psdev = pcistub_device_find(domain, bus, slot, func);
++	if (!psdev) {
++		err = -ENODEV;
++		goto out;
++	}
++	if (!psdev->dev) {
++		err = -ENODEV;
++		goto release;
++	}
++	dev_data = pci_get_drvdata(psdev->dev);
++	/* the driver data for a device should never be null at this point */
++	if (!dev_data) {
++		err = -ENXIO;
++		goto release;
++	}
++	if (!dev_data->permissive) {
++		dev_data->permissive = 1;
++		/* Let user know that what they're doing could be unsafe */
++		dev_warn(&psdev->dev->dev,
++			 "enabling permissive mode configuration space accesses!\n");
++		dev_warn(&psdev->dev->dev,
++			 "permissive mode is potentially unsafe!\n");
++	}
++      release:
++	pcistub_device_put(psdev);
++      out:
++	if (!err)
++		err = count;
++	return err;
++}
++
++static ssize_t permissive_show(struct device_driver *drv, char *buf)
++{
++	struct pcistub_device *psdev;
++	struct pciback_dev_data *dev_data;
++	size_t count = 0;
++	unsigned long flags;
++	spin_lock_irqsave(&pcistub_devices_lock, flags);
++	list_for_each_entry(psdev, &pcistub_devices, dev_list) {
++		if (count >= PAGE_SIZE)
++			break;
++		if (!psdev->dev)
++			continue;
++		dev_data = pci_get_drvdata(psdev->dev);
++		if (!dev_data || !dev_data->permissive)
++			continue;
++		count +=
++		    scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
++			      pci_name(psdev->dev));
++	}
++	spin_unlock_irqrestore(&pcistub_devices_lock, flags);
++	return count;
++}
++
++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);
++	driver_remove_file(&pciback_pci_driver.driver,
++			   &driver_attr_remove_slot);
++	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
++	driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
++	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)
++{
++	int pos = 0;
++	int err = 0;
++	int domain, bus, slot, func;
++	int parsed;
++
++	if (pci_devs_to_hide && *pci_devs_to_hide) {
++		do {
++			parsed = 0;
++
++			err = sscanf(pci_devs_to_hide + pos,
++				     " (%x:%x:%x.%x) %n",
++				     &domain, &bus, &slot, &func, &parsed);
++			if (err != 4) {
++				domain = 0;
++				err = sscanf(pci_devs_to_hide + pos,
++					     " (%x:%x.%x) %n",
++					     &bus, &slot, &func, &parsed);
++				if (err != 3)
++					goto parse_error;
++			}
++
++			err = pcistub_device_id_add(domain, bus, slot, func);
++			if (err)
++				goto out;
++
++			/* if parsed<=0, we've reached the end of the string */
++			pos += parsed;
++		} while (parsed > 0 && pci_devs_to_hide[pos]);
++	}
++
++	/* If we're the first PCI Device Driver to register, we're the
++	 * first one to get offered PCI devices as they become
++	 * available (and thus we can be the first to grab them)
++	 */
++	err = pci_register_driver(&pciback_pci_driver);
++	if (err < 0)
++		goto out;
++
++	err = driver_create_file(&pciback_pci_driver.driver,
++				 &driver_attr_new_slot);
++	if (!err)
++		err = driver_create_file(&pciback_pci_driver.driver,
++					 &driver_attr_remove_slot);
++	if (!err)
++		err = driver_create_file(&pciback_pci_driver.driver,
++					 &driver_attr_slots);
++	if (!err)
++		err = driver_create_file(&pciback_pci_driver.driver,
++					 &driver_attr_quirks);
++	if (!err)
++		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();
++
++      out:
++	return err;
++
++      parse_error:
++	printk(KERN_ERR "pciback: Error parsing pci_devs_to_hide at \"%s\"\n",
++	       pci_devs_to_hide + pos);
++	return -EINVAL;
++}
++
++#ifndef MODULE
++/*
++ * fs_initcall happens before device_initcall
++ * so pciback *should* get called first (b/c we 
++ * want to suck up any device before other drivers
++ * get a chance by being the first pci device
++ * driver to register)
++ */
++fs_initcall(pcistub_init);
++#endif
++
++static int __init pciback_init(void)
++{
++	int err;
++
++	err = pciback_config_init();
++	if (err)
++		return err;
++
++#ifdef MODULE
++	err = pcistub_init();
++	if (err < 0)
++		return err;
++#endif
++
++	pcistub_init_devices_late();
++	err = pciback_xenbus_register();
++	if (err)
++		pcistub_exit();
++
++	return err;
++}
++
++static void __exit pciback_cleanup(void)
++{
++	pciback_xenbus_unregister();
++	pcistub_exit();
++}
++
++module_init(pciback_init);
++module_exit(pciback_cleanup);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/pciback.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,126 @@
++/*
++ * 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))
++#define _PCIB_op_pending	(1)
++#define PCIB_op_pending		(1<<(_PCIB_op_pending))
++
++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);
++
++/** 
++* Add for domain0 PCIE-AER handling. Get guest domain/bus/devfn in pciback
++* before sending aer request to pcifront, so that guest could identify 
++* device, coopearte with pciback to finish aer recovery job if device driver
++* has the capability
++*/
++
++int pciback_get_pcifront_dev(struct pci_dev *pcidev, 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;
++
++void test_and_schedule_op(struct pciback_device *pdev);
++#endif
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/pciback_ops.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,134 @@
++/*
++ * PCI Backend Operations - respond to PCI requests from Frontend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/wait.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;
++		}
++	}
++}
++extern wait_queue_head_t aer_wait_queue;
++extern struct workqueue_struct *pciback_wq;
++/*
++* Now the same evtchn is used for both pcifront conf_read_write request
++* as well as pcie aer front end ack. We use a new work_queue to schedule
++* pciback conf_read_write service for avoiding confict with aer_core 
++* do_recovery job which also use the system default work_queue
++*/
++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))
++	{
++		queue_work(pciback_wq, &pdev->op_work);
++	}
++	/*_XEN_PCIB_active should have been cleared by pcifront. And also make
++	sure pciback is waiting for ack by checking _PCIB_op_pending*/
++	if (!test_bit(_XEN_PCIB_active,(unsigned long *)&pdev->sh_info->flags)
++	    &&test_bit(_PCIB_op_pending, &pdev->flags)) {
++		wake_up(&aer_wait_queue);
++	}
++}
++
++/* 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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/slot.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,187 @@
++/*
++ * PCI Backend - Provides a Virtual PCI bus (with real devices)
++ *               to the frontend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
++ *   Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
++ */
++
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include "pciback.h"
++
++/* There are at most 32 slots in a pci bus.  */
++#define PCI_SLOT_MAX 32
++
++#define PCI_BUS_NBR 2
++
++struct slot_dev_data {
++	/* Access to dev_list must be protected by lock */
++	struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
++	spinlock_t lock;
++};
++
++struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
++				    unsigned int domain, unsigned int bus,
++				    unsigned int devfn)
++{
++	struct pci_dev *dev = NULL;
++	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
++	unsigned long flags;
++
++	if (domain != 0 || PCI_FUNC(devfn) != 0)
++		return NULL;
++
++	if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
++		return NULL;
++
++	spin_lock_irqsave(&slot_dev->lock, flags);
++	dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
++	spin_unlock_irqrestore(&slot_dev->lock, flags);
++
++	return 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;
++	unsigned long flags;
++
++	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
++		err = -EFAULT;
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Can't export bridges on the virtual PCI bus");
++		goto out;
++	}
++
++	spin_lock_irqsave(&slot_dev->lock, flags);
++
++	/* Assign to a new slot on the virtual PCI bus */
++	for (bus = 0; bus < PCI_BUS_NBR; bus++)
++		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++			if (slot_dev->slots[bus][slot] == NULL) {
++				printk(KERN_INFO
++				       "pciback: slot: %s: assign to virtual slot %d, bus %d\n",
++				       pci_name(dev), slot, bus);
++				slot_dev->slots[bus][slot] = dev;
++				goto unlock;
++			}
++		}
++
++	err = -ENOMEM;
++	xenbus_dev_fatal(pdev->xdev, err,
++			 "No more space on root virtual PCI bus");
++
++      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;
++}
++
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++{
++	int slot, bus;
++	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&slot_dev->lock, flags);
++
++	for (bus = 0; bus < PCI_BUS_NBR; bus++)
++		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++			if (slot_dev->slots[bus][slot] == dev) {
++				slot_dev->slots[bus][slot] = NULL;
++				found_dev = dev;
++				goto out;
++			}
++		}
++
++      out:
++	spin_unlock_irqrestore(&slot_dev->lock, flags);
++
++	if (found_dev)
++		pcistub_put_pci_dev(found_dev);
++}
++
++int pciback_init_devices(struct pciback_device *pdev)
++{
++	int slot, bus;
++	struct slot_dev_data *slot_dev;
++
++	slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
++	if (!slot_dev)
++		return -ENOMEM;
++
++	spin_lock_init(&slot_dev->lock);
++
++	for (bus = 0; bus < PCI_BUS_NBR; bus++)
++		for (slot = 0; slot < PCI_SLOT_MAX; slot++)
++			slot_dev->slots[bus][slot] = NULL;
++
++	pdev->pci_dev_data = slot_dev;
++
++	return 0;
++}
++
++int pciback_publish_pci_roots(struct pciback_device *pdev,
++			      publish_pci_root_cb publish_cb)
++{
++	/* The Virtual PCI bus has only one root */
++	return publish_cb(pdev, 0, 0);
++}
++
++void pciback_release_devices(struct pciback_device *pdev)
++{
++	int slot, bus;
++	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
++	struct pci_dev *dev;
++
++	for (bus = 0; bus < PCI_BUS_NBR; bus++)
++		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++			dev = slot_dev->slots[bus][slot];
++			if (dev != NULL)
++				pcistub_put_pci_dev(dev);
++		}
++
++	kfree(slot_dev);
++	pdev->pci_dev_data = NULL;
++}
++
++int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
++		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
++{
++	int slot, busnr;
++	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
++	struct pci_dev *dev;
++	int found = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&slot_dev->lock, flags);
++
++	for (busnr = 0; busnr < PCI_BUS_NBR; bus++)
++		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++			dev = slot_dev->slots[busnr][slot];
++			if (dev && dev->bus->number == pcidev->bus->number
++				&& dev->devfn == pcidev->devfn
++				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)) {
++				found = 1;
++				*domain = 0;
++				*bus = busnr;
++				*devfn = PCI_DEVFN(slot,0);
++				goto out;
++			}
++		}
++out:
++	spin_unlock_irqrestore(&slot_dev->lock, flags);
++	return found;
++
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/vpci.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,242 @@
++/*
++ * PCI Backend - Provides a Virtual PCI bus (with real devices)
++ *               to the frontend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include "pciback.h"
++
++#define PCI_SLOT_MAX 32
++
++struct vpci_dev_data {
++	/* Access to dev_list must be protected by lock */
++	struct list_head dev_list[PCI_SLOT_MAX];
++	spinlock_t lock;
++};
++
++static inline struct list_head *list_first(struct list_head *head)
++{
++	return head->next;
++}
++
++struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
++				    unsigned int domain, unsigned int bus,
++				    unsigned int devfn)
++{
++	struct pci_dev_entry *entry;
++	struct pci_dev *dev = NULL;
++	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++	unsigned long flags;
++
++	if (domain != 0 || bus != 0)
++		return NULL;
++
++	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
++		spin_lock_irqsave(&vpci_dev->lock, flags);
++
++		list_for_each_entry(entry,
++				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
++				    list) {
++			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
++				dev = entry->dev;
++				break;
++			}
++		}
++
++		spin_unlock_irqrestore(&vpci_dev->lock, flags);
++	}
++	return dev;
++}
++
++static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
++{
++	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
++	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
++		return 1;
++
++	return 0;
++}
++
++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, func;
++	struct pci_dev_entry *t, *dev_entry;
++	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++	unsigned long flags;
++
++	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
++		err = -EFAULT;
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Can't export bridges on the virtual PCI bus");
++		goto out;
++	}
++
++	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
++	if (!dev_entry) {
++		err = -ENOMEM;
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error adding entry to virtual PCI bus");
++		goto out;
++	}
++
++	dev_entry->dev = dev;
++
++	spin_lock_irqsave(&vpci_dev->lock, flags);
++
++	/* Keep multi-function devices together on the virtual PCI bus */
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		if (!list_empty(&vpci_dev->dev_list[slot])) {
++			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
++				       struct pci_dev_entry, list);
++
++			if (match_slot(dev, t->dev)) {
++				pr_info("pciback: vpci: %s: "
++					"assign to virtual slot %d func %d\n",
++					pci_name(dev), slot,
++					PCI_FUNC(dev->devfn));
++				list_add_tail(&dev_entry->list,
++					      &vpci_dev->dev_list[slot]);
++				func = PCI_FUNC(dev->devfn);
++				goto unlock;
++			}
++		}
++	}
++
++	/* Assign to a new slot on the virtual PCI bus */
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		if (list_empty(&vpci_dev->dev_list[slot])) {
++			printk(KERN_INFO
++			       "pciback: vpci: %s: assign to virtual slot %d\n",
++			       pci_name(dev), slot);
++			list_add_tail(&dev_entry->list,
++				      &vpci_dev->dev_list[slot]);
++			func = PCI_FUNC(dev->devfn);
++			goto unlock;
++		}
++	}
++
++	err = -ENOMEM;
++	xenbus_dev_fatal(pdev->xdev, err,
++			 "No more space on root virtual PCI bus");
++
++      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;
++}
++
++void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
++{
++	int slot;
++	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++	struct pci_dev *found_dev = NULL;
++	unsigned long flags;
++
++	spin_lock_irqsave(&vpci_dev->lock, flags);
++
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		struct pci_dev_entry *e, *tmp;
++		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
++					 list) {
++			if (e->dev == dev) {
++				list_del(&e->list);
++				found_dev = e->dev;
++				kfree(e);
++				goto out;
++			}
++		}
++	}
++
++      out:
++	spin_unlock_irqrestore(&vpci_dev->lock, flags);
++
++	if (found_dev)
++		pcistub_put_pci_dev(found_dev);
++}
++
++int pciback_init_devices(struct pciback_device *pdev)
++{
++	int slot;
++	struct vpci_dev_data *vpci_dev;
++
++	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
++	if (!vpci_dev)
++		return -ENOMEM;
++
++	spin_lock_init(&vpci_dev->lock);
++
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
++	}
++
++	pdev->pci_dev_data = vpci_dev;
++
++	return 0;
++}
++
++int pciback_publish_pci_roots(struct pciback_device *pdev,
++			      publish_pci_root_cb publish_cb)
++{
++	/* The Virtual PCI bus has only one root */
++	return publish_cb(pdev, 0, 0);
++}
++
++void pciback_release_devices(struct pciback_device *pdev)
++{
++	int slot;
++	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		struct pci_dev_entry *e, *tmp;
++		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
++					 list) {
++			list_del(&e->list);
++			pcistub_put_pci_dev(e->dev);
++			kfree(e);
++		}
++	}
++
++	kfree(vpci_dev);
++	pdev->pci_dev_data = NULL;
++}
++
++int pciback_get_pcifront_dev(struct pci_dev *pcidev, struct pciback_device *pdev, 
++		unsigned int *domain, unsigned int *bus, unsigned int *devfn)
++{
++	struct pci_dev_entry *entry;
++	struct pci_dev *dev = NULL;
++	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
++	unsigned long flags;
++	int found = 0, slot;
++
++	spin_lock_irqsave(&vpci_dev->lock, flags);
++	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
++		list_for_each_entry(entry,
++			    &vpci_dev->dev_list[slot],
++			    list) {
++			dev = entry->dev;
++			if (dev && dev->bus->number == pcidev->bus->number
++				&& pci_domain_nr(dev->bus) == pci_domain_nr(pcidev->bus)
++				&& dev->devfn == pcidev->devfn)
++			{
++				found = 1;
++				*domain = 0;
++				*bus = 0;
++				*devfn = PCI_DEVFN(slot, PCI_FUNC(pcidev->devfn));
++			}
++		}		
++	}
++	spin_unlock_irqrestore(&vpci_dev->lock, flags);
++	return found;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pciback/xenbus.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,710 @@
++/*
++ * PCI Backend Xenbus Setup - handles setup with frontend and xend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/vmalloc.h>
++#include <xen/xenbus.h>
++#include <xen/evtchn.h>
++#include "pciback.h"
++
++#define INVALID_EVTCHN_IRQ  (-1)
++struct workqueue_struct *pciback_wq;
++
++static struct pciback_device *alloc_pdev(struct xenbus_device *xdev)
++{
++	struct pciback_device *pdev;
++
++	pdev = kzalloc(sizeof(struct pciback_device), GFP_KERNEL);
++	if (pdev == NULL)
++		goto out;
++	dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
++
++	pdev->xdev = xdev;
++	xdev->dev.driver_data = pdev;
++
++	spin_lock_init(&pdev->dev_lock);
++
++	pdev->sh_area = NULL;
++	pdev->sh_info = NULL;
++	pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
++	pdev->be_watching = 0;
++
++	INIT_WORK(&pdev->op_work, pciback_do_op, pdev);
++
++	if (pciback_init_devices(pdev)) {
++		kfree(pdev);
++		pdev = NULL;
++	}
++      out:
++	return pdev;
++}
++
++static void pciback_disconnect(struct pciback_device *pdev)
++{
++	spin_lock(&pdev->dev_lock);
++
++	/* Ensure the guest can't trigger our handler before removing devices */
++	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
++	 * before releasing the shared memory */
++	flush_workqueue(pciback_wq);
++
++	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);
++
++	pdev->xdev->dev.driver_data = NULL;
++	pdev->xdev = NULL;
++
++	kfree(pdev);
++}
++
++static int pciback_do_attach(struct pciback_device *pdev, int gnt_ref,
++			     int remote_evtchn)
++{
++	int err = 0;
++	struct vm_struct *area;
++
++	dev_dbg(&pdev->xdev->dev,
++		"Attaching to frontend resources - gnt_ref=%d evtchn=%d\n",
++		gnt_ref, remote_evtchn);
++
++	area = xenbus_map_ring_valloc(pdev->xdev, gnt_ref);
++	if (IS_ERR(area)) {
++		err = PTR_ERR(area);
++		goto out;
++	}
++	pdev->sh_area = area;
++	pdev->sh_info = area->addr;
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++		pdev->xdev->otherend_id, remote_evtchn, pciback_handle_event,
++		SA_SAMPLE_RANDOM, "pciback", pdev);
++	if (err < 0) {
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error binding event channel to IRQ");
++		goto out;
++	}
++	pdev->evtchn_irq = err;
++	err = 0;
++
++	dev_dbg(&pdev->xdev->dev, "Attached!\n");
++      out:
++	return err;
++}
++
++static int pciback_attach(struct pciback_device *pdev)
++{
++	int err = 0;
++	int gnt_ref, remote_evtchn;
++	char *magic = NULL;
++
++	spin_lock(&pdev->dev_lock);
++
++	/* Make sure we only do this setup once */
++	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++	    XenbusStateInitialised)
++		goto out;
++
++	/* Wait for frontend to state that it has published the configuration */
++	if (xenbus_read_driver_state(pdev->xdev->otherend) !=
++	    XenbusStateInitialised)
++		goto out;
++
++	dev_dbg(&pdev->xdev->dev, "Reading frontend config\n");
++
++	err = xenbus_gather(XBT_NIL, pdev->xdev->otherend,
++			    "pci-op-ref", "%u", &gnt_ref,
++			    "event-channel", "%u", &remote_evtchn,
++			    "magic", NULL, &magic, NULL);
++	if (err) {
++		/* If configuration didn't get read correctly, wait longer */
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error reading configuration from frontend");
++		goto out;
++	}
++
++	if (magic == NULL || strcmp(magic, XEN_PCI_MAGIC) != 0) {
++		xenbus_dev_fatal(pdev->xdev, -EFAULT,
++				 "version mismatch (%s/%s) with pcifront - "
++				 "halting pciback",
++				 magic, XEN_PCI_MAGIC);
++		goto out;
++	}
++
++	err = pciback_do_attach(pdev, gnt_ref, remote_evtchn);
++	if (err)
++		goto out;
++
++	dev_dbg(&pdev->xdev->dev, "Connecting...\n");
++
++	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
++	if (err)
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error switching to connected state!");
++
++	dev_dbg(&pdev->xdev->dev, "Connected? %d\n", err);
++      out:
++	spin_unlock(&pdev->dev_lock);
++
++	if (magic)
++		kfree(magic);
++
++	return err;
++}
++
++static int pciback_publish_pci_dev(struct pciback_device *pdev,
++				   unsigned int domain, unsigned int bus,
++				   unsigned int devfn, unsigned int devid)
++{
++	int err;
++	int len;
++	char str[64];
++
++	len = snprintf(str, sizeof(str), "vdev-%d", devid);
++	if (unlikely(len >= (sizeof(str) - 1))) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
++			    "%04x:%02x:%02x.%02x", domain, bus,
++			    PCI_SLOT(devfn), PCI_FUNC(devfn));
++
++      out:
++	return err;
++}
++
++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;
++
++	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,
++				    unsigned int domain, unsigned int bus)
++{
++	unsigned int d, b;
++	int i, root_num, len, err;
++	char str[64];
++
++	dev_dbg(&pdev->xdev->dev, "Publishing pci roots\n");
++
++	err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename,
++			   "root_num", "%d", &root_num);
++	if (err == 0 || err == -ENOENT)
++		root_num = 0;
++	else if (err < 0)
++		goto out;
++
++	/* Verify that we haven't already published this pci root */
++	for (i = 0; i < root_num; 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->nodename,
++				   str, "%x:%x", &d, &b);
++		if (err < 0)
++			goto out;
++		if (err != 2) {
++			err = -EINVAL;
++			goto out;
++		}
++
++		if (d == domain && b == bus) {
++			err = 0;
++			goto out;
++		}
++	}
++
++	len = snprintf(str, sizeof(str), "root-%d", root_num);
++	if (unlikely(len >= (sizeof(str) - 1))) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	dev_dbg(&pdev->xdev->dev, "writing root %d at %04x:%02x\n",
++		root_num, domain, bus);
++
++	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str,
++			    "%04x:%02x", domain, bus);
++	if (err)
++		goto out;
++
++	err = xenbus_printf(XBT_NIL, pdev->xdev->nodename,
++			    "root_num", "%d", (root_num + 1));
++
++      out:
++	return err;
++}
++
++static int pciback_reconfigure(struct pciback_device *pdev)
++{
++	int err = 0;
++	int num_devs;
++	int domain, bus, slot, func;
++	int substate;
++	int i, len;
++	char state_str[64];
++	char dev_str[64];
++
++	spin_lock(&pdev->dev_lock);
++
++	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,
++				 "Error reading number of devices");
++		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;
++
++		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:
++	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)
++{
++	/* Get configuration from xend (if available now) */
++	int domain, bus, slot, func;
++	int err = 0;
++	int i, num_devs;
++	char dev_str[64];
++	char state_str[64];
++
++	spin_lock(&pdev->dev_lock);
++
++	/* It's possible we could get the call to setup twice, so make sure
++	 * we're not already connected.
++	 */
++	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++	    XenbusStateInitWait)
++		goto out;
++
++	dev_dbg(&pdev->xdev->dev, "getting be setup\n");
++
++	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,
++				 "Error reading number of devices");
++		goto out;
++	}
++
++	for (i = 0; i < num_devs; i++) {
++		int l = snprintf(dev_str, sizeof(dev_str), "dev-%d", i);
++		if (unlikely(l >= (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;
++
++		/* 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);
++	if (err) {
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error while publish PCI root buses "
++				 "for frontend");
++		goto out;
++	}
++
++	err = xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
++	if (err)
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error switching to initialised state!");
++
++      out:
++	spin_unlock(&pdev->dev_lock);
++
++	if (!err)
++		/* see if pcifront is already configured (if not, we'll wait) */
++		pciback_attach(pdev);
++
++	return err;
++}
++
++static void pciback_be_watch(struct xenbus_watch *watch,
++			     const char **vec, unsigned int len)
++{
++	struct pciback_device *pdev =
++	    container_of(watch, struct pciback_device, be_watch);
++
++	switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
++	case XenbusStateInitWait:
++		pciback_setup_backend(pdev);
++		break;
++
++	default:
++		break;
++	}
++}
++
++static int pciback_xenbus_probe(struct xenbus_device *dev,
++				const struct xenbus_device_id *id)
++{
++	int err = 0;
++	struct pciback_device *pdev = alloc_pdev(dev);
++
++	if (pdev == NULL) {
++		err = -ENOMEM;
++		xenbus_dev_fatal(dev, err,
++				 "Error allocating pciback_device struct");
++		goto out;
++	}
++
++	/* wait for xend to configure us */
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err)
++		goto out;
++
++	/* watch the backend node for backend configuration information */
++	err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
++				pciback_be_watch);
++	if (err)
++		goto out;
++	pdev->be_watching = 1;
++
++	/* We need to force a call to our callback here in case
++	 * xend already configured us!
++	 */
++	pciback_be_watch(&pdev->be_watch, NULL, 0);
++
++      out:
++	return err;
++}
++
++static int pciback_xenbus_remove(struct xenbus_device *dev)
++{
++	struct pciback_device *pdev = dev->dev.driver_data;
++
++	if (pdev != NULL)
++		free_pdev(pdev);
++
++	return 0;
++}
++
++static const struct xenbus_device_id xenpci_ids[] = {
++	{"pci"},
++	{{0}},
++};
++
++static struct xenbus_driver xenbus_pciback_driver = {
++	.name 			= "pciback",
++	.owner 			= THIS_MODULE,
++	.ids 			= xenpci_ids,
++	.probe 			= pciback_xenbus_probe,
++	.remove 		= pciback_xenbus_remove,
++	.otherend_changed 	= pciback_frontend_changed,
++};
++
++int __init pciback_xenbus_register(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++	pciback_wq = create_workqueue("pciback_workqueue");
++	if (!pciback_wq) {
++		printk(KERN_ERR "pciback_xenbus_register: create"
++			"pciback_workqueue failed\n");
++		return -EFAULT;
++	}
++	return xenbus_register_backend(&xenbus_pciback_driver);
++}
++
++void __exit pciback_xenbus_unregister(void)
++{
++	destroy_workqueue(pciback_wq);
++	xenbus_unregister_driver(&xenbus_pciback_driver);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pcifront/Makefile	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,7 @@
++obj-y += pcifront.o
++
++pcifront-y := pci_op.o xenbus.o pci.o
++
++ifeq ($(CONFIG_XEN_PCIDEV_FE_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pcifront/pci.c	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,46 @@
++/*
++ * PCI Frontend Operations - ensure only one PCI frontend runs at a time
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include "pcifront.h"
++
++DEFINE_SPINLOCK(pcifront_dev_lock);
++static struct pcifront_device *pcifront_dev = NULL;
++
++int pcifront_connect(struct pcifront_device *pdev)
++{
++	int err = 0;
++
++	spin_lock(&pcifront_dev_lock);
++
++	if (!pcifront_dev) {
++		dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
++		pcifront_dev = pdev;
++	}
++	else {
++		dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n");
++		err = -EEXIST;
++	}
++
++	spin_unlock(&pcifront_dev_lock);
++
++	return err;
++}
++
++void pcifront_disconnect(struct pcifront_device *pdev)
++{
++	spin_lock(&pcifront_dev_lock);
++
++	if (pdev == pcifront_dev) {
++		dev_info(&pdev->xdev->dev,
++			 "Disconnecting PCI Frontend Buses\n");
++		pcifront_dev = NULL;
++	}
++
++	spin_unlock(&pcifront_dev_lock);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pcifront/pci_op.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,666 @@
++/*
++ * PCI Frontend Operations - Communicates with frontend
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <linux/spinlock.h>
++#include <asm/bitops.h>
++#include <linux/time.h>
++#include <xen/evtchn.h>
++#include "pcifront.h"
++
++static int verbose_request = 0;
++module_param(verbose_request, int, 0644);
++
++#ifdef __ia64__
++static void pcifront_init_sd(struct pcifront_sd *sd,
++			     unsigned int domain, unsigned int bus,
++			     struct pcifront_device *pdev)
++{
++	int err, i, j, k, len, root_num, res_count;
++	struct acpi_resource res;
++	unsigned int d, b, byte;
++	unsigned long magic;
++	char str[64], tmp[3];
++	unsigned char *buf, *bufp;
++	u8 *ptr;
++
++	memset(sd, 0, sizeof(*sd));
++
++	sd->segment = domain;
++	sd->node = -1;	/* Revisit for NUMA */
++	sd->platform_data = pdev;
++
++	/* Look for resources for this controller in xenbus. */
++	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, "root_num",
++			   "%d", &root_num);
++	if (err != 1)
++		return;
++
++	for (i = 0; i < root_num; i++) {
++		len = snprintf(str, sizeof(str), "root-%d", i);
++		if (unlikely(len >= (sizeof(str) - 1)))
++			return;
++
++		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
++				   str, "%x:%x", &d, &b);
++		if (err != 2)
++			return;
++
++		if (d == domain && b == bus)
++			break;
++	}
++
++	if (i == root_num)
++		return;
++
++	len = snprintf(str, sizeof(str), "root-resource-magic");
++
++	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
++			   str, "%lx", &magic);
++
++	if (err != 1)
++		return; /* No resources, nothing to do */
++
++	if (magic != (sizeof(res) * 2) + 1) {
++		printk(KERN_WARNING "pcifront: resource magic mismatch\n");
++		return;
++	}
++
++	len = snprintf(str, sizeof(str), "root-%d-resources", i);
++	if (unlikely(len >= (sizeof(str) - 1)))
++		return;
++
++	err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend,
++			   str, "%d", &res_count);
++
++	if (err != 1)
++		return; /* No resources, nothing to do */
++
++	sd->window = kzalloc(sizeof(*sd->window) * res_count, GFP_KERNEL);
++	if (!sd->window)
++		return;
++
++	/* magic is also the size of the byte stream in xenbus */
++	buf = kmalloc(magic, GFP_KERNEL);
++	if (!buf) {
++		kfree(sd->window);
++		sd->window = NULL;
++		return;
++	}
++
++	/* Read the resources out of xenbus */
++	for (j = 0; j < res_count; j++) {
++		memset(&res, 0, sizeof(res));
++		memset(buf, 0, magic);
++
++		len = snprintf(str, sizeof(str), "root-%d-resource-%d", i, j);
++		if (unlikely(len >= (sizeof(str) - 1)))
++			return;
++
++		err = xenbus_scanf(XBT_NIL, pdev->xdev->otherend, str,
++				   "%s", buf);
++		if (err != 1) {
++			printk(KERN_WARNING "pcifront: error reading "
++			       "resource %d on bus %04x:%02x\n",
++			       j, domain, bus);
++			continue;
++		}
++
++		bufp = buf;
++		ptr = (u8 *)&res;
++		memset(tmp, 0, sizeof(tmp));
++
++		/* Copy ASCII byte stream into structure */
++		for (k = 0; k < magic - 1; k += 2) {
++			memcpy(tmp, bufp, 2);
++			bufp += 2;
++
++			sscanf(tmp, "%02x", &byte);
++			*ptr = byte;
++			ptr++;
++		}
++
++		xen_add_resource(sd, domain, bus, &res);
++		sd->windows++;
++	}
++	kfree(buf);
++}
++#endif
++
++static int errno_to_pcibios_err(int errno)
++{
++	switch (errno) {
++	case XEN_PCI_ERR_success:
++		return PCIBIOS_SUCCESSFUL;
++
++	case XEN_PCI_ERR_dev_not_found:
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	case XEN_PCI_ERR_invalid_offset:
++	case XEN_PCI_ERR_op_failed:
++		return PCIBIOS_BAD_REGISTER_NUMBER;
++
++	case XEN_PCI_ERR_not_implemented:
++		return PCIBIOS_FUNC_NOT_SUPPORTED;
++
++	case XEN_PCI_ERR_access_denied:
++		return PCIBIOS_SET_FAILED;
++	}
++	return errno;
++}
++
++static inline void schedule_pcifront_aer_op(struct pcifront_device *pdev)
++{
++	if (test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags)
++		&& !test_and_set_bit(_PDEVB_op_active, &pdev->flags)) {
++		dev_dbg(&pdev->xdev->dev, "schedule aer frontend job\n");
++		schedule_work(&pdev->op_work);
++	}
++}
++
++static int do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
++{
++	int err = 0;
++	struct xen_pci_op *active_op = &pdev->sh_info->op;
++	unsigned long irq_flags;
++	evtchn_port_t port = pdev->evtchn;
++	s64 ns, ns_timeout;
++	struct timeval tv;
++
++	spin_lock_irqsave(&pdev->sh_info_lock, irq_flags);
++
++	memcpy(active_op, op, sizeof(struct xen_pci_op));
++
++	/* Go */
++	wmb();
++	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
++	notify_remote_via_evtchn(port);
++
++	/*
++	 * We set a poll timeout of 3 seconds but give up on return after
++	 * 2 seconds. It is better to time out too late rather than too early
++	 * (in the latter case we end up continually re-executing poll() with a
++	 * timeout in the past). 1s difference gives plenty of slack for error.
++	 */
++	do_gettimeofday(&tv);
++	ns_timeout = timeval_to_ns(&tv) + 2 * (s64)NSEC_PER_SEC;
++
++	clear_evtchn(port);
++
++	while (test_bit(_XEN_PCIF_active,
++			(unsigned long *)&pdev->sh_info->flags)) {
++		if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ))
++			BUG();
++		clear_evtchn(port);
++		do_gettimeofday(&tv);
++		ns = timeval_to_ns(&tv);
++		if (ns > ns_timeout) {
++			dev_err(&pdev->xdev->dev,
++				"pciback not responding!!!\n");
++			clear_bit(_XEN_PCIF_active,
++				  (unsigned long *)&pdev->sh_info->flags);
++			err = XEN_PCI_ERR_dev_not_found;
++			goto out;
++		}
++	}
++
++	/*
++	* We might lose backend service request since we 
++	* reuse same evtchn with pci_conf backend response. So re-schedule
++	* aer pcifront service.
++	*/
++	if (test_bit(_XEN_PCIB_active, 
++			(unsigned long*)&pdev->sh_info->flags)) {
++		dev_err(&pdev->xdev->dev, 
++			"schedule aer pcifront service\n");
++		schedule_pcifront_aer_op(pdev);
++	}
++
++	memcpy(op, active_op, sizeof(struct xen_pci_op));
++
++	err = op->err;
++      out:
++	spin_unlock_irqrestore(&pdev->sh_info_lock, irq_flags);
++	return err;
++}
++
++/* Access to this function is spinlocked in drivers/pci/access.c */
++static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
++			     int where, int size, u32 * val)
++{
++	int err = 0;
++	struct xen_pci_op op = {
++		.cmd    = XEN_PCI_OP_conf_read,
++		.domain = pci_domain_nr(bus),
++		.bus    = bus->number,
++		.devfn  = devfn,
++		.offset = where,
++		.size   = size,
++	};
++	struct pcifront_sd *sd = bus->sysdata;
++	struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++	if (verbose_request)
++		dev_info(&pdev->xdev->dev,
++			 "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n",
++			 pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
++			 PCI_FUNC(devfn), where, size);
++
++	err = do_pci_op(pdev, &op);
++
++	if (likely(!err)) {
++		if (verbose_request)
++			dev_info(&pdev->xdev->dev, "read got back value %x\n",
++				 op.value);
++
++		*val = op.value;
++	} else if (err == -ENODEV) {
++		/* No device here, pretend that it just returned 0 */
++		err = 0;
++		*val = 0;
++	}
++
++	return errno_to_pcibios_err(err);
++}
++
++/* Access to this function is spinlocked in drivers/pci/access.c */
++static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
++			      int where, int size, u32 val)
++{
++	struct xen_pci_op op = {
++		.cmd    = XEN_PCI_OP_conf_write,
++		.domain = pci_domain_nr(bus),
++		.bus    = bus->number,
++		.devfn  = devfn,
++		.offset = where,
++		.size   = size,
++		.value  = val,
++	};
++	struct pcifront_sd *sd = bus->sysdata;
++	struct pcifront_device *pdev = pcifront_get_pdev(sd);
++
++	if (verbose_request)
++		dev_info(&pdev->xdev->dev,
++			 "write dev=%04x:%02x:%02x.%01x - "
++			 "offset %x size %d val %x\n",
++			 pci_domain_nr(bus), bus->number,
++			 PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val);
++
++	return errno_to_pcibios_err(do_pci_op(pdev, &op));
++}
++
++struct pci_ops pcifront_bus_ops = {
++	.read = pcifront_bus_read,
++	.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)
++{
++	struct pcifront_device *pdev = data;
++	int i;
++	struct resource *r;
++
++	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++		r = &dev->resource[i];
++
++		if (!r->parent && r->start && r->flags) {
++			dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n",
++				pci_name(dev), i);
++			pci_claim_resource(dev, i);
++		}
++	}
++}
++
++int __devinit pcifront_scan_root(struct pcifront_device *pdev,
++				 unsigned int domain, unsigned int bus)
++{
++	struct pci_bus *b;
++	struct pcifront_sd *sd = NULL;
++	struct pci_bus_entry *bus_entry = NULL;
++	int err = 0;
++
++#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");
++		err = -EINVAL;
++		goto err_out;
++	}
++#endif
++
++	dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
++		 domain, bus);
++
++	bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
++	sd = kmalloc(sizeof(*sd), GFP_KERNEL);
++	if (!bus_entry || !sd) {
++		err = -ENOMEM;
++		goto err_out;
++	}
++	pcifront_init_sd(sd, domain, bus, pdev);
++
++	b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
++				  &pcifront_bus_ops, sd);
++	if (!b) {
++		dev_err(&pdev->xdev->dev,
++			"Error creating PCI Frontend Bus!\n");
++		err = -ENOMEM;
++		goto err_out;
++	}
++
++	pcifront_setup_root_resources(b, sd);
++	bus_entry->bus = b;
++
++	list_add(&bus_entry->list, &pdev->root_buses);
++
++	/* Claim resources before going "live" with our devices */
++	pci_walk_bus(b, pcifront_claim_resource, pdev);
++
++	pci_bus_add_devices(b);
++
++	return 0;
++
++      err_out:
++	kfree(bus_entry);
++	kfree(sd);
++
++	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;
++
++	while (!list_empty(&bus->devices)) {
++		dev = container_of(bus->devices.next, struct pci_dev,
++				   bus_list);
++		dev_dbg(&dev->dev, "removing device\n");
++		pci_remove_bus_device(dev);
++	}
++}
++
++void pcifront_free_roots(struct pcifront_device *pdev)
++{
++	struct pci_bus_entry *bus_entry, *t;
++
++	dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
++
++	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
++		list_del(&bus_entry->list);
++
++		free_root_bus_devs(bus_entry->bus);
++
++		kfree(bus_entry->bus->sysdata);
++
++		device_unregister(bus_entry->bus->bridge);
++		pci_remove_bus(bus_entry->bus);
++
++		kfree(bus_entry);
++	}
++}
++
++static pci_ers_result_t pcifront_common_process( int cmd, struct pcifront_device *pdev,
++	pci_channel_state_t state)
++{
++	pci_ers_result_t result;
++	struct pci_driver *pdrv;
++	int bus = pdev->sh_info->aer_op.bus;
++	int devfn = pdev->sh_info->aer_op.devfn;
++	struct pci_dev *pcidev;
++	int flag = 0;
++
++	dev_dbg(&pdev->xdev->dev, 
++		"pcifront AER process: cmd %x (bus:%x, devfn%x)",
++		cmd, bus, devfn);
++	result = PCI_ERS_RESULT_NONE;
++
++	pcidev = pci_get_bus_and_slot(bus, devfn);
++	if (!pcidev || !pcidev->driver){
++		dev_err(&pcidev->dev, 
++			"device or driver is NULL\n");
++		return result;
++	}
++	pdrv = pcidev->driver;
++
++	if (get_driver(&pdrv->driver)) {
++		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
++			dev_dbg(&pcidev->dev,
++				"trying to call AER service\n");
++			if (pcidev) {
++				flag = 1;
++				switch(cmd) {
++				case XEN_PCI_OP_aer_detected:
++					result = pdrv->err_handler->error_detected(pcidev, state);
++					break;
++				case XEN_PCI_OP_aer_mmio:
++					result = pdrv->err_handler->mmio_enabled(pcidev);
++					break;
++				case XEN_PCI_OP_aer_slotreset:
++					result = pdrv->err_handler->slot_reset(pcidev);
++					break;
++				case XEN_PCI_OP_aer_resume:
++					pdrv->err_handler->resume(pcidev);
++					break;
++				default:
++					dev_err(&pdev->xdev->dev,
++						"bad request in aer recovery operation!\n");
++
++				}
++			}
++		}
++		put_driver(&pdrv->driver);
++	}
++	if (!flag)
++		result = PCI_ERS_RESULT_NONE;
++
++	return result;
++}
++
++
++void pcifront_do_aer(void *data)
++{
++	struct pcifront_device *pdev = data;
++	int cmd = pdev->sh_info->aer_op.cmd;
++	pci_channel_state_t state = 
++		(pci_channel_state_t)pdev->sh_info->aer_op.err;
++
++	/*If a pci_conf op is in progress, 
++		we have to wait until it is done before service aer op*/
++	dev_dbg(&pdev->xdev->dev, 
++		"pcifront service aer bus %x devfn %x\n", pdev->sh_info->aer_op.bus,
++		pdev->sh_info->aer_op.devfn);
++
++	pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state);
++
++	wmb();
++	clear_bit(_XEN_PCIB_active, (unsigned long*)&pdev->sh_info->flags);
++	notify_remote_via_evtchn(pdev->evtchn);
++
++	/*in case of we lost an aer request in four lines time_window*/
++	smp_mb__before_clear_bit();
++	clear_bit( _PDEVB_op_active, &pdev->flags);
++	smp_mb__after_clear_bit();
++
++	schedule_pcifront_aer_op(pdev);
++
++}
++
++irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs)
++{
++	struct pcifront_device *pdev = dev;
++	schedule_pcifront_aer_op(pdev);
++	return IRQ_HANDLED;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pcifront/pcifront.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,55 @@
++/*
++ * 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 <linux/interrupt.h>
++#include <xen/pcifront.h>
++#include <asm/atomic.h>
++#include <linux/workqueue.h>
++
++struct pci_bus_entry {
++	struct list_head list;
++	struct pci_bus *bus;
++};
++
++#define _PDEVB_op_active		(0)
++#define PDEVB_op_active 		(1 << (_PDEVB_op_active))
++
++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;
++	struct work_struct op_work;
++	unsigned long flags;
++
++};
++
++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);
++
++void pcifront_do_aer( void *data);
++
++irqreturn_t pcifront_handler_aer(int irq, void *dev, struct pt_regs *regs);
++
++#endif	/* __XEN_PCIFRONT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/pcifront/xenbus.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,468 @@
++/*
++ * PCI Frontend Xenbus Setup - handles setup with backend (imports page/evtchn)
++ *
++ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <xen/xenbus.h>
++#include <xen/evtchn.h>
++#include <xen/gnttab.h>
++#include "pcifront.h"
++
++#ifndef __init_refok
++#define __init_refok
++#endif
++
++#define INVALID_GRANT_REF (0)
++#define INVALID_EVTCHN    (-1)
++
++static struct pcifront_device *alloc_pdev(struct xenbus_device *xdev)
++{
++	struct pcifront_device *pdev;
++
++	pdev = kzalloc(sizeof(struct pcifront_device), GFP_KERNEL);
++	if (pdev == NULL)
++		goto out;
++
++	pdev->sh_info =
++	    (struct xen_pci_sharedinfo *)__get_free_page(GFP_KERNEL);
++	if (pdev->sh_info == NULL) {
++		kfree(pdev);
++		pdev = NULL;
++		goto out;
++	}
++	pdev->sh_info->flags = 0;
++
++	/*Flag for registering PV AER handler*/
++	set_bit(_XEN_PCIB_AERHANDLER, (void*)&pdev->sh_info->flags);
++
++	xdev->dev.driver_data = pdev;
++	pdev->xdev = xdev;
++
++	INIT_LIST_HEAD(&pdev->root_buses);
++
++	spin_lock_init(&pdev->dev_lock);
++	spin_lock_init(&pdev->sh_info_lock);
++
++	pdev->evtchn = INVALID_EVTCHN;
++	pdev->gnt_ref = INVALID_GRANT_REF;
++
++	INIT_WORK(&pdev->op_work, pcifront_do_aer, pdev);
++
++	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
++		pdev, pdev->sh_info);
++      out:
++	return pdev;
++}
++
++static void free_pdev(struct pcifront_device *pdev)
++{
++	dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev);
++
++	pcifront_free_roots(pdev);
++
++	/*For PCIE_AER error handling job*/
++	flush_scheduled_work();
++	unbind_from_irqhandler(pdev->evtchn, pdev);
++
++	if (pdev->evtchn != INVALID_EVTCHN)
++		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
++
++	if (pdev->gnt_ref != INVALID_GRANT_REF)
++		gnttab_end_foreign_access(pdev->gnt_ref,
++					  (unsigned long)pdev->sh_info);
++
++	pdev->xdev->dev.driver_data = NULL;
++
++	kfree(pdev);
++}
++
++static int pcifront_publish_info(struct pcifront_device *pdev)
++{
++	int err = 0;
++	struct xenbus_transaction trans;
++
++	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
++	if (err < 0)
++		goto out;
++
++	pdev->gnt_ref = err;
++
++	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
++	if (err)
++		goto out;
++
++	bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, 
++		SA_SAMPLE_RANDOM, "pcifront", pdev); 
++
++      do_publish:
++	err = xenbus_transaction_start(&trans);
++	if (err) {
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error writing configuration for backend "
++				 "(start transaction)");
++		goto out;
++	}
++
++	err = xenbus_printf(trans, pdev->xdev->nodename,
++			    "pci-op-ref", "%u", pdev->gnt_ref);
++	if (!err)
++		err = xenbus_printf(trans, pdev->xdev->nodename,
++				    "event-channel", "%u", pdev->evtchn);
++	if (!err)
++		err = xenbus_printf(trans, pdev->xdev->nodename,
++				    "magic", XEN_PCI_MAGIC);
++
++	if (err) {
++		xenbus_transaction_end(trans, 1);
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error writing configuration for backend");
++		goto out;
++	} else {
++		err = xenbus_transaction_end(trans, 0);
++		if (err == -EAGAIN)
++			goto do_publish;
++		else if (err) {
++			xenbus_dev_fatal(pdev->xdev, err,
++					 "Error completing transaction "
++					 "for backend");
++			goto out;
++		}
++	}
++
++	xenbus_switch_state(pdev->xdev, XenbusStateInitialised);
++
++	dev_dbg(&pdev->xdev->dev, "publishing successful!\n");
++
++      out:
++	return err;
++}
++
++static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
++{
++	int err = -EFAULT;
++	int i, num_roots, len;
++	char str[64];
++	unsigned int domain, bus;
++
++	spin_lock(&pdev->dev_lock);
++
++	/* Only connect once */
++	if (xenbus_read_driver_state(pdev->xdev->nodename) !=
++	    XenbusStateInitialised)
++		goto out;
++
++	err = pcifront_connect(pdev);
++	if (err) {
++		xenbus_dev_fatal(pdev->xdev, err,
++				 "Error connecting PCI Frontend");
++		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_scan_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_scan_root(pdev, domain, bus);
++		if (err) {
++			xenbus_dev_fatal(pdev->xdev, err,
++					 "Error scanning PCI root %04x:%02x",
++					 domain, bus);
++			goto out;
++		}
++	}
++
++	err = xenbus_switch_state(pdev->xdev, XenbusStateConnected);
++	if (err)
++		goto out;
++
++      out:
++	spin_unlock(&pdev->dev_lock);
++	return err;
++}
++
++static int pcifront_try_disconnect(struct pcifront_device *pdev)
++{
++	int err = 0;
++	enum xenbus_state prev_state;
++
++	spin_lock(&pdev->dev_lock);
++
++	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
++
++	if (prev_state >= XenbusStateClosing)
++		goto out;
++
++	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 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 XenbusStateUnknown:
++	case XenbusStateInitialising:
++	case XenbusStateInitWait:
++	case XenbusStateInitialised:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateConnected:
++		pcifront_try_connect(pdev);
++		break;
++
++	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;
++	}
++}
++
++static int pcifront_xenbus_probe(struct xenbus_device *xdev,
++				 const struct xenbus_device_id *id)
++{
++	int err = 0;
++	struct pcifront_device *pdev = alloc_pdev(xdev);
++
++	if (pdev == NULL) {
++		err = -ENOMEM;
++		xenbus_dev_fatal(xdev, err,
++				 "Error allocating pcifront_device struct");
++		goto out;
++	}
++
++	err = pcifront_publish_info(pdev);
++
++      out:
++	return err;
++}
++
++static int pcifront_xenbus_remove(struct xenbus_device *xdev)
++{
++	if (xdev->dev.driver_data)
++		free_pdev(xdev->dev.driver_data);
++
++	return 0;
++}
++
++static const struct xenbus_device_id xenpci_ids[] = {
++	{"pci"},
++	{{0}},
++};
++MODULE_ALIAS("xen:pci");
++
++static struct xenbus_driver xenbus_pcifront_driver = {
++	.name 			= "pcifront",
++	.owner 			= THIS_MODULE,
++	.ids 			= xenpci_ids,
++	.probe 			= pcifront_xenbus_probe,
++	.remove 		= pcifront_xenbus_remove,
++	.otherend_changed 	= pcifront_backend_changed,
++};
++
++static int __init pcifront_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	return xenbus_register_frontend(&xenbus_pcifront_driver);
++}
++
++/* Initialize after the Xen PCI Frontend Stub is initialized */
++subsys_initcall(pcifront_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/privcmd/Makefile	2007-07-10 09:42:30.000000000 +0200
+@@ -0,0 +1,3 @@
++
++obj-y	+= privcmd.o
++obj-$(CONFIG_COMPAT)	+= compat_privcmd.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/privcmd/compat_privcmd.c	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,155 @@
++/*
++ * 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>
++ */
++
++#include <linux/config.h>
++#include <linux/compat.h>
++#include <linux/ioctl.h>
++#include <linux/syscalls.h>
++#include <asm/hypervisor.h>
++#include <asm/uaccess.h>
++#include <xen/public/privcmd.h>
++#include <xen/compat_ioctl.h>
++
++int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg)
++{
++	int ret;
++
++	switch (cmd) {
++	case IOCTL_PRIVCMD_MMAP_32: {
++		struct privcmd_mmap *p;
++		struct privcmd_mmap_32 *p32;
++		struct privcmd_mmap_32 n32;
++
++		p32 = compat_ptr(arg);
++		p = compat_alloc_user_space(sizeof(*p));
++		if (copy_from_user(&n32, p32, sizeof(n32)) ||
++		    put_user(n32.num, &p->num) ||
++		    put_user(n32.dom, &p->dom) ||
++		    put_user(compat_ptr(n32.entry), &p->entry))
++			return -EFAULT;
++		
++		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAP, (unsigned long)p);
++	}
++		break;
++	case IOCTL_PRIVCMD_MMAPBATCH_32: {
++		struct privcmd_mmapbatch *p;
++		struct privcmd_mmapbatch_32 *p32;
++		struct privcmd_mmapbatch_32 n32;
++#ifdef xen_pfn32_t
++		xen_pfn_t *__user arr;
++		xen_pfn32_t *__user arr32;
++		unsigned int i;
++#endif
++
++		p32 = compat_ptr(arg);
++		p = compat_alloc_user_space(sizeof(*p));
++		if (copy_from_user(&n32, p32, sizeof(n32)) ||
++		    put_user(n32.num, &p->num) ||
++		    put_user(n32.dom, &p->dom) ||
++		    put_user(n32.addr, &p->addr))
++			return -EFAULT;
++#ifdef xen_pfn32_t
++		arr = compat_alloc_user_space(n32.num * sizeof(*arr)
++					      + sizeof(*p));
++		arr32 = compat_ptr(n32.arr);
++		for (i = 0; i < n32.num; ++i) {
++			xen_pfn32_t mfn;
++
++			if (get_user(mfn, arr32 + i) || put_user(mfn, arr + i))
++				return -EFAULT;
++		}
++
++		if (put_user(arr, &p->arr))
++			return -EFAULT;
++#else
++		if (put_user(compat_ptr(n32.arr), &p->arr))
++			return -EFAULT;
++#endif
++		
++		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, (unsigned long)p);
++
++#ifdef xen_pfn32_t
++		for (i = 0; !ret && i < n32.num; ++i) {
++			xen_pfn_t mfn;
++
++			if (get_user(mfn, arr + i) || put_user(mfn, arr32 + i))
++				ret = -EFAULT;
++			else if (mfn != (xen_pfn32_t)mfn)
++				ret = -ERANGE;
++		}
++#endif
++	}
++		break;
++	case IOCTL_PRIVCMD_MMAPBATCH_V2_32: {
++		struct privcmd_mmapbatch_v2 *p;
++		struct privcmd_mmapbatch_v2_32 *p32;
++		struct privcmd_mmapbatch_v2_32 n32;
++#ifdef xen_pfn32_t
++		xen_pfn_t *__user arr;
++		xen_pfn32_t *__user arr32;
++		unsigned int i;
++#endif
++
++		p32 = compat_ptr(arg);
++		p = compat_alloc_user_space(sizeof(*p));
++		if (copy_from_user(&n32, p32, sizeof(n32)) ||
++		    put_user(n32.num, &p->num) ||
++		    put_user(n32.dom, &p->dom) ||
++		    put_user(n32.addr, &p->addr) ||
++		    put_user(compat_ptr(n32.err), &p->err))
++			return -EFAULT;
++#ifdef xen_pfn32_t
++		arr = compat_alloc_user_space(n32.num * sizeof(*arr)
++					      + sizeof(*p));
++		arr32 = compat_ptr(n32.arr);
++		for (i = 0; i < n32.num; ++i) {
++			xen_pfn32_t mfn;
++
++			if (get_user(mfn, arr32 + i) || put_user(mfn, arr + i))
++				return -EFAULT;
++		}
++
++		if (put_user(arr, &p->arr))
++			return -EFAULT;
++#else
++		if (put_user(compat_ptr(n32.arr), &p->arr))
++			return -EFAULT;
++#endif
++
++		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, (unsigned long)p);
++
++#ifdef xen_pfn32_t
++		for (i = 0; !ret && i < n32.num; ++i) {
++			xen_pfn_t mfn;
++
++			if (get_user(mfn, arr + i) || put_user(mfn, arr32 + i))
++				ret = -EFAULT;
++			else if (mfn != (xen_pfn32_t)mfn)
++				ret = -ERANGE;
++		}
++#endif
++	}
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++	return ret;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/privcmd/privcmd.c	2010-01-19 10:14:18.000000000 +0100
+@@ -0,0 +1,490 @@
++/******************************************************************************
++ * privcmd.c
++ * 
++ * Interface to privileged domain-0 commands.
++ * 
++ * Copyright (c) 2002-2004, K A Fraser, B Dragovic
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/swap.h>
++#include <linux/smp_lock.h>
++#include <linux/highmem.h>
++#include <linux/pagemap.h>
++#include <linux/seq_file.h>
++#include <asm/hypervisor.h>
++
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/tlb.h>
++#include <asm/hypervisor.h>
++#include <xen/public/privcmd.h>
++#include <xen/interface/xen.h>
++#include <xen/xen_proc.h>
++#include <xen/features.h>
++
++static struct proc_dir_entry *privcmd_intf;
++static struct proc_dir_entry *capabilities_intf;
++
++#ifndef HAVE_ARCH_PRIVCMD_MMAP
++static int enforce_singleshot_mapping_fn(pte_t *pte, struct page *pmd_page,
++					 unsigned long addr, void *data)
++{
++	return pte_none(*pte) ? 0 : -EBUSY;
++}
++
++static inline int enforce_singleshot_mapping(struct vm_area_struct *vma,
++					     unsigned long addr,
++					     unsigned long npages)
++{
++	return apply_to_page_range(vma->vm_mm, addr, npages << PAGE_SHIFT,
++				   enforce_singleshot_mapping_fn, NULL) == 0;
++}
++#else
++#define enforce_singleshot_mapping(vma, addr, npages) \
++	privcmd_enforce_singleshot_mapping(vma)
++#endif
++
++static long privcmd_ioctl(struct file *file,
++			  unsigned int cmd, unsigned long data)
++{
++	long ret;
++	void __user *udata = (void __user *) data;
++	unsigned long i, addr, nr, nr_pages;
++	int paged_out;
++	struct mm_struct *mm = current->mm;
++	struct vm_area_struct *vma;
++	LIST_HEAD(pagelist);
++	struct list_head *l, *l2;
++
++	switch (cmd) {
++	case IOCTL_PRIVCMD_HYPERCALL: {
++		privcmd_hypercall_t hypercall;
++  
++		if (copy_from_user(&hypercall, udata, sizeof(hypercall)))
++			return -EFAULT;
++
++		ret = -ENOSYS;
++#if defined(__i386__)
++		if (hypercall.op >= (PAGE_SIZE >> 5))
++			break;
++		__asm__ __volatile__ (
++			"pushl %%ebx; pushl %%ecx; pushl %%edx; "
++			"pushl %%esi; pushl %%edi; "
++			"movl  8(%%eax),%%ebx ;"
++			"movl 16(%%eax),%%ecx ;"
++			"movl 24(%%eax),%%edx ;"
++			"movl 32(%%eax),%%esi ;"
++			"movl 40(%%eax),%%edi ;"
++			"movl   (%%eax),%%eax ;"
++			"shll $5,%%eax ;"
++			"addl $hypercall_page,%%eax ;"
++			"call *%%eax ;"
++			"popl %%edi; popl %%esi; popl %%edx; "
++			"popl %%ecx; popl %%ebx"
++			: "=a" (ret) : "0" (&hypercall) : "memory" );
++#elif defined (__x86_64__)
++		if (hypercall.op < (PAGE_SIZE >> 5)) {
++			long ign1, ign2, ign3;
++			__asm__ __volatile__ (
++				"movq %8,%%r10; movq %9,%%r8;"
++				"shll $5,%%eax ;"
++				"addq $hypercall_page,%%rax ;"
++				"call *%%rax"
++				: "=a" (ret), "=D" (ign1),
++				  "=S" (ign2), "=d" (ign3)
++				: "0" ((unsigned int)hypercall.op),
++				"1" (hypercall.arg[0]),
++				"2" (hypercall.arg[1]),
++				"3" (hypercall.arg[2]),
++				"g" (hypercall.arg[3]),
++				"g" (hypercall.arg[4])
++				: "r8", "r10", "memory" );
++		}
++#else
++		ret = privcmd_hypercall(&hypercall);
++#endif
++	}
++	break;
++
++	case IOCTL_PRIVCMD_MMAP: {
++#define MMAP_NR_PER_PAGE \
++	(unsigned long)((PAGE_SIZE - sizeof(*l)) / sizeof(*msg))
++		privcmd_mmap_t mmapcmd;
++		privcmd_mmap_entry_t *msg;
++		privcmd_mmap_entry_t __user *p;
++
++		if (!is_initial_xendomain())
++			return -EPERM;
++
++		if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
++			return -EFAULT;
++
++		if (mmapcmd.num <= 0)
++			return -EINVAL;
++
++		p = mmapcmd.entry;
++		for (i = 0; i < mmapcmd.num;) {
++			nr = min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
++
++			ret = -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);
++
++			ret = -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);
++		ret = -EINVAL;
++		if (!vma || (msg->va != vma->vm_start))
++			goto mmap_out;
++
++		addr = vma->vm_start;
++
++		i = 0;
++		list_for_each(l, &pagelist) {
++			nr = i + min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
++
++			msg = (privcmd_mmap_entry_t*)(l + 1);
++			while (i<nr) {
++
++				/* Do not allow range to wrap the address space. */
++				if ((msg->npages > (LONG_MAX >> PAGE_SHIFT)) ||
++				    (((unsigned long)msg->npages << PAGE_SHIFT) >= -addr))
++					goto mmap_out;
++
++				/* Range chunks must be contiguous in va space. */
++				if ((msg->va != addr) ||
++				    ((msg->va+(msg->npages<<PAGE_SHIFT)) > vma->vm_end))
++					goto mmap_out;
++
++				addr += msg->npages << PAGE_SHIFT;
++				msg++;
++				i++;
++			}
++		}
++
++		if (!enforce_singleshot_mapping(vma, vma->vm_start,
++						(addr - vma->vm_start) >> PAGE_SHIFT))
++			goto mmap_out;
++
++		addr = vma->vm_start;
++		i = 0;
++		list_for_each(l, &pagelist) {
++			nr = i + min(mmapcmd.num - i, MMAP_NR_PER_PAGE);
++
++			msg = (privcmd_mmap_entry_t*)(l + 1);
++			while (i < nr) {
++				if ((ret = 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;
++
++				addr += msg->npages << PAGE_SHIFT;
++				msg++;
++				i++;
++			}
++		}
++
++		ret = 0;
++
++	mmap_out:
++		up_write(&mm->mmap_sem);
++		list_for_each_safe(l,l2,&pagelist)
++			free_page((unsigned long)l);
++	}
++#undef MMAP_NR_PER_PAGE
++	break;
++
++	case IOCTL_PRIVCMD_MMAPBATCH: {
++#define MMAPBATCH_NR_PER_PAGE \
++	(unsigned long)((PAGE_SIZE - sizeof(*l)) / sizeof(*mfn))
++		privcmd_mmapbatch_t m;
++		xen_pfn_t __user *p;
++		xen_pfn_t *mfn;
++
++		if (!is_initial_xendomain())
++			return -EPERM;
++
++		if (copy_from_user(&m, udata, sizeof(m)))
++			return -EFAULT;
++
++		nr_pages = m.num;
++		addr = m.addr;
++		if (m.num <= 0 || nr_pages > (LONG_MAX >> PAGE_SHIFT) ||
++		    addr != m.addr || nr_pages > (-addr >> PAGE_SHIFT))
++			return -EINVAL;
++
++		p = m.arr;
++		for (i=0; i<nr_pages; )	{
++			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, addr);
++		ret = -EINVAL;
++		if (!vma ||
++		    addr < vma->vm_start ||
++		    addr + (nr_pages << PAGE_SHIFT) > vma->vm_end ||
++		    !enforce_singleshot_mapping(vma, addr, nr_pages)) {
++			up_write(&mm->mmap_sem);
++			goto mmapbatch_out;
++		}
++
++		i = 0;
++		ret = 0;
++		paged_out = 0;
++		list_for_each(l, &pagelist) {
++			nr = i + min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++			mfn = (unsigned long *)(l + 1);
++
++			while (i<nr) {
++				int rc;
++
++				rc = direct_remap_pfn_range(vma, addr & PAGE_MASK,
++				                            *mfn, PAGE_SIZE,
++				                            vma->vm_page_prot, m.dom);
++				if(rc < 0) {
++					if (rc == -ENOENT)
++					{
++						*mfn |= 0x80000000U;
++						paged_out = 1;
++					}
++					else
++						*mfn |= 0xf0000000U;
++					ret++;
++				}
++				mfn++; i++; addr += PAGE_SIZE;
++			}
++		}
++
++		up_write(&mm->mmap_sem);
++		if (ret > 0) {
++			p = m.arr;
++			i = 0;
++			if (paged_out)
++				ret = -ENOENT;
++			else
++				ret = 0;
++			list_for_each(l, &pagelist) {
++				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);
++	}
++	break;
++
++	case IOCTL_PRIVCMD_MMAPBATCH_V2: {
++		privcmd_mmapbatch_v2_t m;
++		const xen_pfn_t __user *p;
++		xen_pfn_t *mfn;
++		int *err;
++
++		if (!is_initial_xendomain())
++			return -EPERM;
++
++		if (copy_from_user(&m, udata, sizeof(m)))
++			return -EFAULT;
++
++		nr_pages = m.num;
++		addr = m.addr;
++		if (m.num <= 0 || nr_pages > (ULONG_MAX >> PAGE_SHIFT) ||
++		    addr != m.addr || nr_pages > (-addr >> PAGE_SHIFT))
++			return -EINVAL;
++
++		p = m.arr;
++		for (i = 0; i < nr_pages; i += nr, p += nr) {
++			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_v2_out;
++
++			INIT_LIST_HEAD(l);
++			list_add_tail(l, &pagelist);
++
++			mfn = (void *)(l + 1);
++			ret = -EFAULT;
++			if (copy_from_user(mfn, p, nr * sizeof(*mfn)))
++				goto mmapbatch_v2_out;
++		}
++
++		down_write(&mm->mmap_sem);
++
++		vma = find_vma(mm, addr);
++		ret = -EINVAL;
++		if (!vma ||
++		    addr < vma->vm_start ||
++		    addr + (nr_pages << PAGE_SHIFT) > vma->vm_end ||
++		    !enforce_singleshot_mapping(vma, addr, nr_pages)) {
++			up_write(&mm->mmap_sem);
++			goto mmapbatch_v2_out;
++		}
++
++		i = 0;
++		ret = 0;
++		paged_out = 0;
++		list_for_each(l, &pagelist) {
++			nr = i + min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++			mfn = (void *)(l + 1);
++			err = (void *)(l + 1);
++			BUILD_BUG_ON(sizeof(*err) > sizeof(*mfn));
++
++			while (i < nr) {
++				int rc;
++
++				rc = direct_remap_pfn_range(vma, addr & PAGE_MASK,
++				                            *mfn, PAGE_SIZE,
++				                            vma->vm_page_prot, m.dom);
++				if (rc < 0) {
++					if (rc == -ENOENT)
++						paged_out = 1;
++					ret++;
++				} else
++					BUG_ON(rc > 0);
++				*err++ = rc;
++				mfn++; i++; addr += PAGE_SIZE;
++			}
++		}
++
++		up_write(&mm->mmap_sem);
++
++		if (ret > 0) {
++			int __user *p = m.err;
++
++			ret = paged_out ? -ENOENT : 0;
++			i = 0;
++			list_for_each(l, &pagelist) {
++				nr = min(nr_pages - i, MMAPBATCH_NR_PER_PAGE);
++				err = (void *)(l + 1);
++				if (copy_to_user(p, err, nr * sizeof(*err)))
++					ret = -EFAULT;
++				i += nr; p += nr;
++			}
++		}
++
++	mmapbatch_v2_out:
++		list_for_each_safe(l, l2, &pagelist)
++			free_page((unsigned long)l);
++#undef MMAPBATCH_NR_PER_PAGE
++	}
++	break;
++
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++#ifndef HAVE_ARCH_PRIVCMD_MMAP
++static struct page *privcmd_nopage(struct vm_area_struct *vma,
++				   unsigned long address,
++				   int *type)
++{
++	return NOPAGE_SIGBUS;
++}
++
++static struct vm_operations_struct privcmd_vm_ops = {
++	.nopage = privcmd_nopage
++};
++
++static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
++{
++	/* Unsupported for auto-translate guests. */
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return -ENOSYS;
++
++	/* DONTCOPY is essential for Xen as copy_page_range is broken. */
++	vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
++	vma->vm_ops = &privcmd_vm_ops;
++	vma->vm_private_data = NULL;
++
++	return 0;
++}
++#endif
++
++static const struct file_operations privcmd_file_ops = {
++	.unlocked_ioctl = privcmd_ioctl,
++	.mmap = privcmd_mmap,
++};
++
++static int capabilities_read(char *page, char **start, off_t off,
++			     int count, int *eof, void *data)
++{
++	int len = 0;
++	*page = 0;
++
++	if (is_initial_xendomain())
++		len = sprintf( page, "control_d\n" );
++
++	*eof = 1;
++	return len;
++}
++
++static int __init privcmd_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	privcmd_intf = create_xen_proc_entry("privcmd", 0400);
++	if (privcmd_intf != NULL)
++		privcmd_intf->proc_fops = &privcmd_file_ops;
++
++	capabilities_intf = create_xen_proc_entry("capabilities", 0400 );
++	if (capabilities_intf != NULL)
++		capabilities_intf->read_proc = capabilities_read;
++
++	return 0;
++}
++
++__initcall(privcmd_init);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/Makefile	2008-07-21 11:00:33.000000000 +0200
+@@ -0,0 +1,4 @@
++obj-$(CONFIG_XEN_SCSI_BACKEND) := xen-scsibk.o
++
++xen-scsibk-y	:= interface.o scsiback.o xenbus.o translate.o emulate.o
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/common.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,186 @@
++/*
++ * 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;
++
++	int feature;
++
++	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;
++	
++	uint16_t v_chn, v_tgt;
++
++	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)
++
++#define VSCSI_TYPE_HOST		1
++
++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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/emulate.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,474 @@
++/*
++ * 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];
++
++#define NO_EMULATE(cmd) \
++	bitmap[cmd] = VSCSIIF_NEED_CMD_EXEC; \
++	pre_function[cmd] = NULL; \
++	post_function[cmd] = NULL
++
++
++
++/*
++  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->v_chn;
++	unsigned int        target  = pending_req->v_tgt;
++	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.)
++	*/
++
++	/*
++	  Following commands do not require emulation.
++	*/
++	NO_EMULATE(TEST_UNIT_READY);       /*0x00*/
++	NO_EMULATE(REZERO_UNIT);           /*0x01*/
++	NO_EMULATE(REQUEST_SENSE);         /*0x03*/
++	NO_EMULATE(FORMAT_UNIT);           /*0x04*/
++	NO_EMULATE(READ_BLOCK_LIMITS);     /*0x05*/
++	/*NO_EMULATE(REASSIGN_BLOCKS);       *//*0x07*/
++	/*NO_EMULATE(INITIALIZE_ELEMENT_STATUS); *//*0x07*/
++	NO_EMULATE(READ_6);                /*0x08*/
++	NO_EMULATE(WRITE_6);               /*0x0a*/
++	/*NO_EMULATE(SEEK_6);                *//*0x0b*/
++	/*NO_EMULATE(READ_REVERSE);          *//*0x0f*/
++	NO_EMULATE(WRITE_FILEMARKS);       /*0x10*/
++	NO_EMULATE(SPACE);                 /*0x11*/
++	NO_EMULATE(INQUIRY);               /*0x12*/
++	/*NO_EMULATE(RECOVER_BUFFERED_DATA); *//*0x14*/
++	/*NO_EMULATE(MODE_SELECT);           *//*0x15*/
++	/*NO_EMULATE(RESERVE);               *//*0x16*/
++	/*NO_EMULATE(RELEASE);               *//*0x17*/
++	/*NO_EMULATE(COPY);                  *//*0x18*/
++	NO_EMULATE(ERASE);                 /*0x19*/
++	NO_EMULATE(MODE_SENSE);            /*0x1a*/
++	/*NO_EMULATE(START_STOP);            *//*0x1b*/
++	/*NO_EMULATE(RECEIVE_DIAGNOSTIC);    *//*0x1c*/
++	NO_EMULATE(SEND_DIAGNOSTIC);       /*0x1d*/
++	/*NO_EMULATE(ALLOW_MEDIUM_REMOVAL);  *//*0x1e*/
++
++	/*NO_EMULATE(SET_WINDOW);            *//*0x24*/
++	NO_EMULATE(READ_CAPACITY);         /*0x25*/
++	NO_EMULATE(READ_10);               /*0x28*/
++	NO_EMULATE(WRITE_10);              /*0x2a*/
++	/*NO_EMULATE(SEEK_10);               *//*0x2b*/
++	/*NO_EMULATE(POSITION_TO_ELEMENT);   *//*0x2b*/
++	/*NO_EMULATE(WRITE_VERIFY);          *//*0x2e*/
++	/*NO_EMULATE(VERIFY);                *//*0x2f*/
++	/*NO_EMULATE(SEARCH_HIGH);           *//*0x30*/
++	/*NO_EMULATE(SEARCH_EQUAL);          *//*0x31*/
++	/*NO_EMULATE(SEARCH_LOW);            *//*0x32*/
++	/*NO_EMULATE(SET_LIMITS);            *//*0x33*/
++	/*NO_EMULATE(PRE_FETCH);             *//*0x34*/
++	/*NO_EMULATE(READ_POSITION);         *//*0x34*/
++	/*NO_EMULATE(SYNCHRONIZE_CACHE);     *//*0x35*/
++	/*NO_EMULATE(LOCK_UNLOCK_CACHE);     *//*0x36*/
++	/*NO_EMULATE(READ_DEFECT_DATA);      *//*0x37*/
++	/*NO_EMULATE(MEDIUM_SCAN);           *//*0x38*/
++	/*NO_EMULATE(COMPARE);               *//*0x39*/
++	/*NO_EMULATE(COPY_VERIFY);           *//*0x3a*/
++	/*NO_EMULATE(WRITE_BUFFER);          *//*0x3b*/
++	/*NO_EMULATE(READ_BUFFER);           *//*0x3c*/
++	/*NO_EMULATE(UPDATE_BLOCK);          *//*0x3d*/
++	/*NO_EMULATE(READ_LONG);             *//*0x3e*/
++	/*NO_EMULATE(WRITE_LONG);            *//*0x3f*/
++	/*NO_EMULATE(CHANGE_DEFINITION);     *//*0x40*/
++	/*NO_EMULATE(WRITE_SAME);            *//*0x41*/
++	/*NO_EMULATE(READ_TOC);              *//*0x43*/
++	/*NO_EMULATE(LOG_SELECT);            *//*0x4c*/
++	/*NO_EMULATE(LOG_SENSE);             *//*0x4d*/
++	/*NO_EMULATE(MODE_SELECT_10);        *//*0x55*/
++	/*NO_EMULATE(RESERVE_10);            *//*0x56*/
++	/*NO_EMULATE(RELEASE_10);            *//*0x57*/
++	/*NO_EMULATE(MODE_SENSE_10);         *//*0x5a*/
++	/*NO_EMULATE(PERSISTENT_RESERVE_IN); *//*0x5e*/
++	/*NO_EMULATE(PERSISTENT_RESERVE_OUT); *//*0x5f*/
++	/*           REPORT_LUNS             *//*0xa0*//*Full emulaiton*/
++	/*NO_EMULATE(MOVE_MEDIUM);           *//*0xa5*/
++	/*NO_EMULATE(EXCHANGE_MEDIUM);       *//*0xa6*/
++	/*NO_EMULATE(READ_12);               *//*0xa8*/
++	/*NO_EMULATE(WRITE_12);              *//*0xaa*/
++	/*NO_EMULATE(WRITE_VERIFY_12);       *//*0xae*/
++	/*NO_EMULATE(SEARCH_HIGH_12);        *//*0xb0*/
++	/*NO_EMULATE(SEARCH_EQUAL_12);       *//*0xb1*/
++	/*NO_EMULATE(SEARCH_LOW_12);         *//*0xb2*/
++	/*NO_EMULATE(READ_ELEMENT_STATUS);   *//*0xb8*/
++	/*NO_EMULATE(SEND_VOLUME_TAG);       *//*0xb6*/
++	/*NO_EMULATE(WRITE_LONG_2);          *//*0xea*/
++	/*NO_EMULATE(READ_16);               *//*0x88*/
++	/*NO_EMULATE(WRITE_16);              *//*0x8a*/
++	/*NO_EMULATE(VERIFY_16);	      *//*0x8f*/
++	/*NO_EMULATE(SERVICE_ACTION_IN);     *//*0x9e*/
++
++	/*
++	  Following commands require emulation.
++	*/
++	pre_function[REPORT_LUNS] = __report_luns;
++	bitmap[REPORT_LUNS] = (VSCSIIF_NEED_EMULATE_REQBUF | 
++					VSCSIIF_NEED_EMULATE_RSPBUF);
++
++	return;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,186 @@
++/*
++ * 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>
++#include <linux/delay.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);
++
++    do {
++	    err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
++	    BUG_ON(err);
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/scsiback.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,755 @@
++/*
++ * 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;
++	struct scsi_sense_hdr sshdr;
++	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) {
++		if (scsi_normalize_sense(sense_buffer,
++			sizeof(sense_buffer), &sshdr)) {
++
++			int len = 8 + sense_buffer[7];
++
++			if (len > VSCSIIF_SENSE_BUFFERSIZE)
++				len = VSCSIIF_SENSE_BUFFERSIZE;
++
++			memcpy(ring_res->sense_buffer, sense_buffer, len);
++			ring_res->sense_len = len;
++		}
++	} 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 uptodate)
++{
++	pending_req_t *pending_req = req->end_io_data;
++	unsigned char *sense_buffer;
++	unsigned int resid;
++	int errors;
++
++	sense_buffer = req->sense;
++	resid        = req->data_len;
++	errors       = req->errors;
++
++	if (errors != 0) {
++		if (log_print_stat)
++			scsiback_print_status(sense_buffer, errors, pending_req);
++	}
++
++	/* The Host mode is through as for Emulation. */
++	if (pending_req->info->feature != VSCSI_TYPE_HOST)
++		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);
++        /* Retry maps with GNTST_eagain */
++        for(i=0; i < nr_segments; i++) {
++            while(unlikely(map[i].status == GNTST_eagain))
++            {
++                msleep(10);
++		        err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, 
++                                                &map[i], 
++                                                1);
++		        BUG_ON(err);
++            }
++        }
++
++		for (i = 0; i < nr_segments; i++) {
++			struct page *pg;
++
++			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;
++
++			pg = pending_pages[vaddr_pagenr(pending_req, i)];
++
++			set_phys_to_machine(page_to_pfn(pg),
++				FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
++
++			pending_req->sgl[i].page   = pg;
++			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;
++
++	pending_req->v_chn = vir.chn = ring_req->channel;
++	pending_req->v_tgt = 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) {
++
++			/* The Host mode is through as for Emulation. */
++			if (info->feature == VSCSI_TYPE_HOST)
++				scsiback_cmd_exec(pending_req);
++			else
++				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;
++}
++
++#if 0
++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));
++
++}
++#endif
++
++module_init(scsiback_init);
++
++#if 0
++module_exit(scsiback_exit);
++#endif
++
++MODULE_DESCRIPTION("Xen SCSI backend driver");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/translate.c	2008-07-21 11:00:33.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;
++
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsiback/xenbus.c	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,378 @@
++/*
++ * 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;
++	unsigned val = 0;
++
++	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;
++	be->info->feature = 0;	/*default not HOSTMODE.*/
++
++	scsiback_init_translation_table(be->info);
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++				"feature-host", "%d", &val);
++	if (XENBUS_EXIST_ERR(err))
++		val = 0;
++
++	if (val)
++		be->info->feature = VSCSI_TYPE_HOST;
++
++	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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsifront/Makefile	2008-07-21 11:00:33.000000000 +0200
+@@ -0,0 +1,3 @@
++
++obj-$(CONFIG_XEN_SCSI_FRONTEND)	:= xenscsi.o
++xenscsi-objs := scsifront.o xenbus.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsifront/common.h	2009-03-18 10:39:32.000000000 +0100
+@@ -0,0 +1,136 @@
++/*
++ * 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 <xen/interface/grant_table.h>
++#include <xen/interface/io/protocols.h>
++#include <asm/delay.h>
++#include <asm/hypervisor.h>
++#include <asm/maddr.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#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__  */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2008-07-21 11:00:33.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");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/scsifront/xenbus.c	2008-07-21 11:00:33.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);
++}
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/Makefile	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,12 @@
++EXTRA_CFLAGS += -Idrivers/xen/sfc_netback -Idrivers/xen/sfc_netutil -Idrivers/xen/netback -Idrivers/net/sfc -Idrivers/net/sfc/sfc_resource
++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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,147 @@
++/****************************************************************************
++ * 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) ||
++	    (event == NETDEV_CHANGE)) {
++		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) {
++				int ok;
++				if (event == NETDEV_CHANGE)
++					ok = (netif_carrier_ok(net_dev) && 
++					      (net_dev->flags & IFF_UP));
++				else
++					ok = (netif_carrier_ok(net_dev) && 
++					      (event == NETDEV_UP));
++				netback_accel_set_interface_state(bend, ok);
++			}
++
++		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)
++		goto fail0;
++
++	netback_accel_debugfs_init();
++
++	rc = netback_accel_sf_init();
++	if (rc != 0)
++		goto fail1;
++
++	rc = register_netdevice_notifier
++		(&netback_accel_netdev_notifier);
++	if (rc != 0)
++		goto fail2;
++
++	return 0;
++
++ fail2:
++	netback_accel_sf_shutdown();
++ fail1:
++	netback_accel_debugfs_fini();
++	netback_accel_shutdown_fwd();
++ fail0:
++#ifdef EFX_GCOV
++	gcov_provider_fini(THIS_MODULE);
++#endif
++	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");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,391 @@
++/****************************************************************************
++ * 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;
++	/*! 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 */
++
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_debugfs.c	2008-02-26 10:54:11.000000000 +0100
+@@ -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;
++}
++
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_fwd.c	2008-04-02 12:34:02.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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_msg.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_solarflare.c	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,1293 @@
++/****************************************************************************
++ * 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;
++	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
++};
++
++
++/* 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 if (strcmp(silicon_rev, "siena/a0") == 0)
++		type = NET_ACCEL_MSG_HWTYPE_SIENA_A;
++	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->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 void bend_dl_reset_suspend(struct efx_dl_device *efx_dl_dev)
++{
++	struct driverlink_port *port;
++
++	DPRINTK("Driverlink reset suspend.\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);
++	mutex_unlock(&accel_mutex);
++}
++
++
++static void bend_dl_reset_resume(struct efx_dl_device *efx_dl_dev, int ok)
++{
++	int rc;
++	struct driverlink_port *port;
++
++	DPRINTK("Driverlink reset resume.\n");
++	
++	if (!ok)
++		return;
++
++	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);
++
++	rc = netback_connect_accelerator(NETBACK_ACCEL_VERSION, 0,
++					 port->net_dev->name, &accel_hooks);
++	if (rc != 0) {
++		EPRINTK("Xen netback accelerator version mismatch\n");
++
++		mutex_lock(&accel_mutex);
++		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);
++	}
++}
++
++
++static struct efx_dl_driver bend_dl_driver = 
++	{
++		.name = "SFC Xen backend",
++		.probe = bend_dl_probe,
++		.remove = bend_dl_remove,
++		.reset_suspend = bend_dl_reset_suspend,
++		.reset_resume = bend_dl_reset_resume
++	};
++
++
++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;
++			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->net_dev->ifindex);
++	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;
++	}
++
++	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);
++	rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(txdmaq_pfn), 0);
++	if (rc < 0)
++		goto fail0;
++	accel_hw_priv->txdmaq_gnt = hwinfo->txdmaq_gnt = rc;
++
++	VPRINTK("Passing rxdmaq page pfn %lx\n", rxdmaq_pfn);
++	rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(rxdmaq_pfn), 0);
++	if (rc < 0)
++		goto fail1;
++	accel_hw_priv->rxdmaq_gnt = hwinfo->rxdmaq_gnt = rc;
++
++	VPRINTK("Passing doorbell page mfn %x\n", hwinfo->doorbell_mfn);
++	/* Make the relevant H/W pages mappable by the far end */
++	rc = net_accel_grant_page(bend->hdev_data, hwinfo->doorbell_mfn, 1);
++	if (rc < 0)
++		goto fail2;
++	accel_hw_priv->doorbell_gnt = hwinfo->doorbell_gnt = rc;
++	
++	/* 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++) {
++		rc = net_accel_grant_page(bend->hdev_data, pfn_to_mfn(pfn), 0);
++		if (rc < 0)
++			goto fail3;
++		accel_hw_priv->evq_mem_gnts[i] = hwinfo->evq_mem_gnts[i] = rc;
++
++		VPRINTK("Got grant %u for evq pfn %x\n", hwinfo->evq_mem_gnts[i], 
++			pfn);
++		pfn++;
++	}
++
++	return 0;
++
++ fail3:
++	for (i = i - 1; i >= 0; i--) {
++		ungrant_or_crash(accel_hw_priv->evq_mem_gnts[i], bend->far_end);
++	}
++	ungrant_or_crash(accel_hw_priv->doorbell_gnt, bend->far_end);
++ fail2:
++	ungrant_or_crash(accel_hw_priv->rxdmaq_gnt, bend->far_end);
++ fail1:
++	ungrant_or_crash(accel_hw_priv->txdmaq_gnt, bend->far_end);	
++ fail0:
++	return rc;
++}
++
++
++static int ef_bend_hwinfo_falcon_a(struct netback_accel *bend, 
++				   struct net_accel_hw_falcon_a *hwinfo)
++{
++	int rc, i;
++	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) {
++		/* Undo ef_bend_hwinfo_falcon_common() */
++		ungrant_or_crash(accel_hw_priv->txdmaq_gnt, bend->far_end);
++		ungrant_or_crash(accel_hw_priv->rxdmaq_gnt, bend->far_end);
++		ungrant_or_crash(accel_hw_priv->doorbell_gnt, bend->far_end);
++		for (i = 0; i < accel_hw_priv->evq_npages; i++) {
++			ungrant_or_crash(accel_hw_priv->evq_mem_gnts[i],
++					 bend->far_end);
++		}
++		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:
++	case NET_ACCEL_MSG_HWTYPE_SIENA_A:
++		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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_solarflare.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_xenbus.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,833 @@
++/****************************************************************************
++ * 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>
++#include <linux/delay.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) && 
++				(netif_carrier_ok(bend->net_dev)));
++
++	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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/gcc.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/gcc_x86.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/primitive.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/sysdep.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/utils.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/x86.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/compat/x86_64.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/config.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/debug.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/log.h	2009-04-07 13:58:48.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  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.
++  */
++
++#if defined(__unix__) && ! defined(__KERNEL__)
++extern int ci_format_select_set(char* s, int len_s, int nfds, const fd_set*);
++extern int ci_format_select(char* s, int len_s,
++			    int nfds, const fd_set* rds, const fd_set* wrs,
++			    const fd_set* exs, struct timeval* timeout);
++#endif
++
++
++/**********************************************************************
++ * 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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/platform/gcc_x86.h	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,370 @@
++/****************************************************************************
++ * 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)); }
++
++ci_inline void ci_atomic32_inc(volatile ci_uint32* p)
++{ __asm__ __volatile__("lock; incl %0" : "+m" (*p)); }
++
++ci_inline int ci_atomic32_dec_and_test(volatile ci_uint32* p) {
++  char r;
++  __asm__ __volatile__("lock; decl %0; sete %1" : "+m" (*p), "=qm" (r));
++  return r;
++}
++
++#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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/platform/linux_kernel.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netback/ci/tools/sysdep.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/Makefile	2008-02-26 10:54:11.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel.h	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,495 @@
++/****************************************************************************
++ * 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 rx discard (bad crc) events seen on fastpath */
++	u64 fastpath_crc_bad;
++
++	/** Number of rx discard (bad csum) events seen on fastpath */
++	u64 fastpath_csum_bad;
++
++	/** Number of rx discard (bad rights) events seen on fastpath */
++	u64 fastpath_rights_bad;
++
++	/** Number of rx discard ("other") events seen on fastpath */
++	u64 fastpath_discard_other;
++
++	/** Number of no rx descriptor trunc events seen on fastpath */
++	u64 rx_no_desc_trunc;
++
++	/** The number of misc bad events 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 *fastpath_crc_bad;
++	struct dentry *fastpath_csum_bad;
++	struct dentry *fastpath_rights_bad;
++	struct dentry *fastpath_discard_other;
++	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.  Reads require either
++	 * netfront's tx_lock or the vnic tx_lock; writes require both
++	 * locks */
++	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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_bufs.c	2008-02-26 10:54:12.000000000 +0100
+@@ -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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_bufs.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_debugfs.c	2009-04-07 13:58:48.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
++ ****************************************************************************
++ */
++
++#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.fastpath_crc_bad = debugfs_create_u64
++		("fastpath_crc_bad", S_IRUSR | S_IRGRP | S_IROTH,
++		 vnic->dbfs_dir, &vnic->stats.fastpath_crc_bad);
++	vnic->dbfs.fastpath_csum_bad = debugfs_create_u64
++		("fastpath_csum_bad", S_IRUSR | S_IRGRP | S_IROTH,
++		 vnic->dbfs_dir, &vnic->stats.fastpath_csum_bad);
++	vnic->dbfs.fastpath_rights_bad = debugfs_create_u64
++		("fastpath_rights_bad", S_IRUSR | S_IRGRP | S_IROTH,
++		 vnic->dbfs_dir, &vnic->stats.fastpath_rights_bad);
++	vnic->dbfs.fastpath_discard_other = debugfs_create_u64
++		("fastpath_discard_other", S_IRUSR | S_IRGRP | S_IROTH,
++		 vnic->dbfs_dir, &vnic->stats.fastpath_discard_other);
++	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.fastpath_crc_bad);
++		debugfs_remove(vnic->dbfs.fastpath_csum_bad);
++		debugfs_remove(vnic->dbfs.fastpath_rights_bad);
++		debugfs_remove(vnic->dbfs.fastpath_discard_other);
++		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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_msg.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,564 @@
++/****************************************************************************
++ * 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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_netfront.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,328 @@
++/****************************************************************************
++ * 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__);
++
++		/* Need netfront's tx_lock and vnic tx_lock to write 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);
++
++	/* Read of tx_skb is protected by netfront's tx_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");
++		goto fail;
++	}
++
++	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");
++		goto fail;
++	}
++
++	return 0;
++
++ fail:
++	netfront_accel_debugfs_fini();
++	flush_workqueue(netfront_accel_workqueue);
++	destroy_workqueue(netfront_accel_workqueue);
++#ifdef EFX_GCOV
++ 	gcov_provider_fini(THIS_MODULE);
++#endif
++	return -EINVAL;
++}
++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");
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_ssr.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_ssr.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_tso.c	2008-02-26 10:54:12.000000000 +0100
+@@ -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;
++}
++
++
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_tso.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,1202 @@
++/****************************************************************************
++ * 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:
++	case NET_ACCEL_MSG_HWTYPE_SIENA_A:
++		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 and Siena we get the rptr from the doorbell page */
++	if (hw_msg->type == NET_ACCEL_MSG_HWTYPE_FALCON_B ||
++	    hw_msg->type == NET_ACCEL_MSG_HWTYPE_SIENA_A) {
++		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) );
++			NETFRONT_ACCEL_STATS_OP(++vnic->stats.fastpath_discard_other);
++		} else if (EF_EVENT_RX_DISCARD_TYPE(*ev) ==
++			   EF_EVENT_RX_DISCARD_CSUM_BAD) {
++			DPRINTK("%s: " EF_EVENT_FMT 
++				" buffer %d DISCARD CSUM_BAD 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_csum_bad);
++		} else if (EF_EVENT_RX_DISCARD_TYPE(*ev) ==
++			   EF_EVENT_RX_DISCARD_CRC_BAD) {
++			DPRINTK("%s: " EF_EVENT_FMT 
++				" buffer %d DISCARD CRC_BAD 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_crc_bad);
++		} else {
++			BUG_ON(EF_EVENT_RX_DISCARD_TYPE(*ev) !=
++			       EF_EVENT_RX_DISCARD_RIGHTS);
++			DPRINTK("%s: " EF_EVENT_FMT 
++				" buffer %d DISCARD RIGHTS 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_rights_bad);
++		}
++	}
++
++	/* 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));
++	int handled;
++	unsigned long flags;
++
++	/*
++	 * We hold the vnic tx_lock which is sufficient to exclude
++	 * writes to tx_skb
++	 */
++
++	if (vnic->tx_skb != NULL) {
++		DPRINTK("%s trying to send spare buffer\n", __FUNCTION__);
++		
++		handled = netfront_accel_vi_tx_post(vnic, vnic->tx_skb);
++		
++		if (handled != NETFRONT_ACCEL_STATUS_BUSY) {
++			DPRINTK("%s restarting tx\n", __FUNCTION__);
++
++			/* Need netfront tx_lock and vnic tx_lock to
++			 * write tx_skb */
++			spin_lock_irqsave(&np->tx_lock, flags);
++
++			vnic->tx_skb = NULL;
++
++			if (netfront_check_queue_ready(vnic->net_dev)) {
++				netif_wake_queue(vnic->net_dev);
++				NETFRONT_ACCEL_STATS_OP
++					(vnic->stats.queue_wakes++);
++			}
++			spin_unlock_irqrestore(&np->tx_lock, flags);
++
++		}
++		
++		/*
++		 * Should never get a CANT, as it checks that before
++		 * deciding it was BUSY first time round 
++		 */
++		BUG_ON(handled == NETFRONT_ACCEL_STATUS_CANT);
++	}
++}
++
++
++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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_xenbus.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/ef_vi_falcon.h	2009-04-07 13:58:48.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) 
++
++
++/* ---- ef_vi_event 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/ef_vi_falcon_core.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/ef_vi_falcon_desc.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/ef_vi_falcon_event.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/ef_vi_internal.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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__ */
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/etherfabric/ef_vi.h	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,647 @@
++/****************************************************************************
++ * 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_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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/falcon_event.c	2009-04-07 13:58:48.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);
++	uint16_t 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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/falcon_vi.c	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,473 @@
++/****************************************************************************
++ * 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;
++}
++
++
++int ef_vi_receive_post(ef_vi* vi, ef_addr addr, ef_request_id dma_id)
++{
++  int rc = ef_vi_receive_init(vi, addr, dma_id, 0);
++  if( rc == 0 )  ef_vi_receive_push(vi);
++  return rc;
++}
++
++
++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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/pt_tx.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/sysdep.h	2009-04-07 13:58:48.000000000 +0200
+@@ -0,0 +1,185 @@
++/****************************************************************************
++ * 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__
++
++
++#define ef_vi_wiob()  mmiowb()
++
++
++/**********************************************************************
++ * 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; 
++# endif
++#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
++
++#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;
++
++#  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;
++# 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
++# 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__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netfront/vi_init.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/Makefile	2008-02-26 10:54:12.000000000 +0100
+@@ -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 
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_cuckoo_hash.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_cuckoo_hash.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_msg_iface.c	2008-02-20 09:32:49.000000000 +0100
+@@ -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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_msg_iface.h	2010-01-18 15:23:12.000000000 +0100
+@@ -0,0 +1,415 @@
++/****************************************************************************
++ * 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,
++	NET_ACCEL_MSG_HWTYPE_SIENA_A = 3,
++};
++
++/*! 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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_shared_fifo.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_util.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,355 @@
++/****************************************************************************
++ * 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/delay.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, int *errno)
++{
++	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;
++    if(errno != NULL) *errno = 0;
++	for (i = 0; i < npages; i++) {
++		rc = net_accel_map_grant(dev, grants[i], map->grant_handles + i, 
++					 addr, NULL, flags);
++		if (rc != 0)
++        {
++            if(errno != NULL) 
++                *errno = (rc == GNTST_eagain ? -EAGAIN : -EINVAL);
++			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)
++{
++    int errno;
++    void *ret;
++
++    do {
++	    ret = net_accel_map_grants_valloc(dev, grants, npages,
++					   GNTMAP_host_map, priv, &errno);
++        if(errno) msleep(10);
++    } while(errno == -EAGAIN);
++
++    return ret;
++}
++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)
++{
++    int errno;
++    void *ret;
++
++	do {
++        ret = net_accel_map_grants_valloc(dev, &gnt_ref, 1, 
++					   GNTMAP_host_map, priv, &errno);
++        if(errno) msleep(10);
++    } while(errno == -EAGAIN);
++
++    return ret;
++}
++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");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_util.h	2008-02-20 09:32:49.000000000 +0100
+@@ -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
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/tpmback/Makefile	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,4 @@
++
++obj-$(CONFIG_XEN_TPMDEV_BACKEND)	+= tpmbk.o
++
++tpmbk-y += tpmback.o interface.o xenbus.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/tpmback/common.h	2007-06-12 13:13:45.000000000 +0200
+@@ -0,0 +1,85 @@
++/******************************************************************************
++ * drivers/xen/tpmback/common.h
++ */
++
++#ifndef __TPM__BACKEND__COMMON_H__
++#define __TPM__BACKEND__COMMON_H__
++
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <xen/evtchn.h>
++#include <xen/driver_util.h>
++#include <xen/interface/grant_table.h>
++#include <xen/interface/io/tpmif.h>
++#include <asm/io.h>
++#include <asm/pgalloc.h>
++
++#define DPRINTK(_f, _a...)			\
++	pr_debug("(file=%s, line=%d) " _f,	\
++		 __FILE__ , __LINE__ , ## _a )
++
++struct backend_info;
++
++typedef struct tpmif_st {
++	struct list_head tpmif_list;
++	/* Unique identifier for this interface. */
++	domid_t domid;
++	unsigned int handle;
++
++	/* Physical parameters of the comms window. */
++	unsigned int irq;
++
++	/* The shared rings and indexes. */
++	tpmif_tx_interface_t *tx;
++	struct vm_struct *tx_area;
++
++	/* Miscellaneous private stuff. */
++	enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
++	int active;
++
++	struct tpmif_st *hash_next;
++	struct list_head list;	/* scheduling list */
++	atomic_t refcnt;
++
++	struct backend_info *bi;
++
++	grant_handle_t shmem_handle;
++	grant_ref_t shmem_ref;
++	struct page **mmap_pages;
++
++	char devname[20];
++} tpmif_t;
++
++void tpmif_disconnect_complete(tpmif_t * tpmif);
++tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi);
++void tpmif_interface_init(void);
++void tpmif_interface_exit(void);
++void tpmif_schedule_work(tpmif_t * tpmif);
++void tpmif_deschedule_work(tpmif_t * tpmif);
++void tpmif_xenbus_init(void);
++void tpmif_xenbus_exit(void);
++int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
++irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs);
++
++long int tpmback_get_instance(struct backend_info *bi);
++
++int vtpm_release_packets(tpmif_t * tpmif, int send_msgs);
++
++
++#define tpmif_get(_b) (atomic_inc(&(_b)->refcnt))
++#define tpmif_put(_b)					\
++	do {						\
++		if (atomic_dec_and_test(&(_b)->refcnt))	\
++			tpmif_disconnect_complete(_b);	\
++	} while (0)
++
++extern int num_frontends;
++
++static inline unsigned long idx_to_kaddr(tpmif_t *t, unsigned int idx)
++{
++	return (unsigned long)pfn_to_kaddr(page_to_pfn(t->mmap_pages[idx]));
++}
++
++#endif /* __TPMIF__BACKEND__COMMON_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/tpmback/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,172 @@
++ /*****************************************************************************
++ * drivers/xen/tpmback/interface.c
++ *
++ * Vritual TPM interface management.
++ *
++ * Copyright (c) 2005, IBM Corporation
++ *
++ * Author: Stefan Berger, stefanb@us.ibm.com
++ *
++ * This code has been derived from drivers/xen/netback/interface.c
++ * Copyright (c) 2004, Keir Fraser
++ */
++
++#include "common.h"
++#include <linux/delay.h>
++#include <xen/balloon.h>
++#include <xen/gnttab.h>
++
++static kmem_cache_t *tpmif_cachep;
++int num_frontends = 0;
++
++LIST_HEAD(tpmif_list);
++
++static tpmif_t *alloc_tpmif(domid_t domid, struct backend_info *bi)
++{
++	tpmif_t *tpmif;
++
++	tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
++	if (tpmif == NULL)
++		goto out_of_memory;
++
++	memset(tpmif, 0, sizeof (*tpmif));
++	tpmif->domid = domid;
++	tpmif->status = DISCONNECTED;
++	tpmif->bi = bi;
++	snprintf(tpmif->devname, sizeof(tpmif->devname), "tpmif%d", domid);
++	atomic_set(&tpmif->refcnt, 1);
++
++	tpmif->mmap_pages = alloc_empty_pages_and_pagevec(TPMIF_TX_RING_SIZE);
++	if (tpmif->mmap_pages == NULL)
++		goto out_of_memory;
++
++	list_add(&tpmif->tpmif_list, &tpmif_list);
++	num_frontends++;
++
++	return tpmif;
++
++ out_of_memory:
++	if (tpmif != NULL)
++		kmem_cache_free(tpmif_cachep, tpmif);
++	printk("%s: out of memory\n", __FUNCTION__);
++	return ERR_PTR(-ENOMEM);
++}
++
++static void free_tpmif(tpmif_t * tpmif)
++{
++	num_frontends--;
++	list_del(&tpmif->tpmif_list);
++	free_empty_pages_and_pagevec(tpmif->mmap_pages, TPMIF_TX_RING_SIZE);
++	kmem_cache_free(tpmif_cachep, tpmif);
++}
++
++tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi)
++{
++	tpmif_t *tpmif;
++
++	list_for_each_entry(tpmif, &tpmif_list, tpmif_list) {
++		if (tpmif->bi == bi) {
++			if (tpmif->domid == domid) {
++				tpmif_get(tpmif);
++				return tpmif;
++			} else {
++				return ERR_PTR(-EEXIST);
++			}
++		}
++	}
++
++	return alloc_tpmif(domid, bi);
++}
++
++static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
++{
++	struct gnttab_map_grant_ref op;
++
++	gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
++			  GNTMAP_host_map, shared_page, tpmif->domid);
++
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status) {
++		DPRINTK(" Grant table operation failure !\n");
++		return op.status;
++	}
++
++	tpmif->shmem_ref = shared_page;
++	tpmif->shmem_handle = op.handle;
++
++	return 0;
++}
++
++static void unmap_frontend_page(tpmif_t *tpmif)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr,
++			    GNTMAP_host_map, tpmif->shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++}
++
++int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
++{
++	int err;
++
++	if (tpmif->irq)
++		return 0;
++
++	if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
++		return -ENOMEM;
++
++	err = map_frontend_page(tpmif, shared_page);
++	if (err) {
++		free_vm_area(tpmif->tx_area);
++		return err;
++	}
++
++	tpmif->tx = (tpmif_tx_interface_t *)tpmif->tx_area->addr;
++	memset(tpmif->tx, 0, PAGE_SIZE);
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++		tpmif->domid, evtchn, tpmif_be_int, 0, tpmif->devname, tpmif);
++	if (err < 0) {
++		unmap_frontend_page(tpmif);
++		free_vm_area(tpmif->tx_area);
++		return err;
++	}
++	tpmif->irq = err;
++
++	tpmif->shmem_ref = shared_page;
++	tpmif->active = 1;
++
++	return 0;
++}
++
++void tpmif_disconnect_complete(tpmif_t *tpmif)
++{
++	if (tpmif->irq)
++		unbind_from_irqhandler(tpmif->irq, tpmif);
++
++	if (tpmif->tx) {
++		unmap_frontend_page(tpmif);
++		free_vm_area(tpmif->tx_area);
++	}
++
++	free_tpmif(tpmif);
++}
++
++void __init tpmif_interface_init(void)
++{
++	tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
++					 0, 0, NULL, NULL);
++}
++
++void __exit tpmif_interface_exit(void)
++{
++	kmem_cache_destroy(tpmif_cachep);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/tpmback/tpmback.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,949 @@
++/******************************************************************************
++ * drivers/xen/tpmback/tpmback.c
++ *
++ * Copyright (c) 2005, IBM Corporation
++ *
++ * Author: Stefan Berger, stefanb@us.ibm.com
++ * Grant table support: Mahadevan Gomathisankaran
++ *
++ * This code has been derived from drivers/xen/netback/netback.c
++ * Copyright (c) 2002-2004, K A Fraser
++ *
++ */
++
++#include "common.h"
++#include <xen/evtchn.h>
++
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <xen/xenbus.h>
++#include <xen/interface/grant_table.h>
++#include <xen/gnttab.h>
++
++/* local data structures */
++struct data_exchange {
++	struct list_head pending_pak;
++	struct list_head current_pak;
++	unsigned int copied_so_far;
++	u8 has_opener:1;
++	u8 aborted:1;
++	rwlock_t pak_lock;	// protects all of the previous fields
++	wait_queue_head_t wait_queue;
++};
++
++struct vtpm_resp_hdr {
++	uint32_t instance_no;
++	uint16_t tag_no;
++	uint32_t len_no;
++	uint32_t ordinal_no;
++} __attribute__ ((packed));
++
++struct packet {
++	struct list_head next;
++	unsigned int data_len;
++	u8 *data_buffer;
++	tpmif_t *tpmif;
++	u32 tpm_instance;
++	u8 req_tag;
++	u32 last_read;
++	u8 flags;
++	struct timer_list processing_timer;
++};
++
++enum {
++	PACKET_FLAG_DISCARD_RESPONSE = 1,
++};
++
++/* local variables */
++static struct data_exchange dataex;
++
++/* local function prototypes */
++static int _packet_write(struct packet *pak,
++			 const char *data, size_t size, int userbuffer);
++static void processing_timeout(unsigned long ptr);
++static int packet_read_shmem(struct packet *pak,
++			     tpmif_t * tpmif,
++			     u32 offset,
++			     char *buffer, int isuserbuffer, u32 left);
++static int vtpm_queue_packet(struct packet *pak);
++
++/***************************************************************
++ Buffer copying fo user and kernel space buffes.
++***************************************************************/
++static inline int copy_from_buffer(void *to,
++				   const void *from, unsigned long size,
++				   int isuserbuffer)
++{
++	if (isuserbuffer) {
++		if (copy_from_user(to, (void __user *)from, size))
++			return -EFAULT;
++	} else {
++		memcpy(to, from, size);
++	}
++	return 0;
++}
++
++static inline int copy_to_buffer(void *to,
++				 const void *from, unsigned long size,
++				 int isuserbuffer)
++{
++	if (isuserbuffer) {
++		if (copy_to_user((void __user *)to, from, size))
++			return -EFAULT;
++	} else {
++		memcpy(to, from, size);
++	}
++	return 0;
++}
++
++
++static void dataex_init(struct data_exchange *dataex)
++{
++	INIT_LIST_HEAD(&dataex->pending_pak);
++	INIT_LIST_HEAD(&dataex->current_pak);
++	dataex->has_opener = 0;
++	rwlock_init(&dataex->pak_lock);
++	init_waitqueue_head(&dataex->wait_queue);
++}
++
++/***************************************************************
++ Packet-related functions
++***************************************************************/
++
++static struct packet *packet_find_instance(struct list_head *head,
++					   u32 tpm_instance)
++{
++	struct packet *pak;
++	struct list_head *p;
++
++	/*
++	 * traverse the list of packets and return the first
++	 * one with the given instance number
++	 */
++	list_for_each(p, head) {
++		pak = list_entry(p, struct packet, next);
++
++		if (pak->tpm_instance == tpm_instance) {
++			return pak;
++		}
++	}
++	return NULL;
++}
++
++static struct packet *packet_find_packet(struct list_head *head, void *packet)
++{
++	struct packet *pak;
++	struct list_head *p;
++
++	/*
++	 * traverse the list of packets and return the first
++	 * one with the given instance number
++	 */
++	list_for_each(p, head) {
++		pak = list_entry(p, struct packet, next);
++
++		if (pak == packet) {
++			return pak;
++		}
++	}
++	return NULL;
++}
++
++static struct packet *packet_alloc(tpmif_t * tpmif,
++				   u32 size, u8 req_tag, u8 flags)
++{
++	struct packet *pak = NULL;
++	pak = kzalloc(sizeof (struct packet), GFP_ATOMIC);
++	if (NULL != pak) {
++		if (tpmif) {
++			pak->tpmif = tpmif;
++			pak->tpm_instance = tpmback_get_instance(tpmif->bi);
++			tpmif_get(tpmif);
++		}
++		pak->data_len = size;
++		pak->req_tag = req_tag;
++		pak->last_read = 0;
++		pak->flags = flags;
++
++		/*
++		 * cannot do tpmif_get(tpmif); bad things happen
++		 * on the last tpmif_put()
++		 */
++		init_timer(&pak->processing_timer);
++		pak->processing_timer.function = processing_timeout;
++		pak->processing_timer.data = (unsigned long)pak;
++	}
++	return pak;
++}
++
++static void inline packet_reset(struct packet *pak)
++{
++	pak->last_read = 0;
++}
++
++static void packet_free(struct packet *pak)
++{
++	if (timer_pending(&pak->processing_timer)) {
++		BUG();
++	}
++
++	if (pak->tpmif)
++		tpmif_put(pak->tpmif);
++	kfree(pak->data_buffer);
++	/*
++	 * cannot do tpmif_put(pak->tpmif); bad things happen
++	 * on the last tpmif_put()
++	 */
++	kfree(pak);
++}
++
++
++/*
++ * Write data to the shared memory and send it to the FE.
++ */
++static int packet_write(struct packet *pak,
++			const char *data, size_t size, int isuserbuffer)
++{
++	int rc = 0;
++
++	if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
++		/* Don't send a respone to this packet. Just acknowledge it. */
++		rc = size;
++	} else {
++		rc = _packet_write(pak, data, size, isuserbuffer);
++	}
++
++	return rc;
++}
++
++int _packet_write(struct packet *pak,
++		  const char *data, size_t size, int isuserbuffer)
++{
++	/*
++	 * Write into the shared memory pages directly
++	 * and send it to the front end.
++	 */
++	tpmif_t *tpmif = pak->tpmif;
++	grant_handle_t handle;
++	int rc = 0;
++	unsigned int i = 0;
++	unsigned int offset = 0;
++
++	if (tpmif == NULL) {
++		return -EFAULT;
++	}
++
++	if (tpmif->status == DISCONNECTED) {
++		return size;
++	}
++
++	while (offset < size && i < TPMIF_TX_RING_SIZE) {
++		unsigned int tocopy;
++		struct gnttab_map_grant_ref map_op;
++		struct gnttab_unmap_grant_ref unmap_op;
++		tpmif_tx_request_t *tx;
++
++		tx = &tpmif->tx->ring[i].req;
++
++		if (0 == tx->addr) {
++			DPRINTK("ERROR: Buffer for outgoing packet NULL?! i=%d\n", i);
++			return 0;
++		}
++
++		gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
++				  GNTMAP_host_map, tx->ref, tpmif->domid);
++
++        do {
++		    if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++						       &map_op, 1)))
++			    BUG();
++            if(map_op.status) msleep(10);
++		} while(map_op.status == GNTST_eagain);
++
++		handle = map_op.handle;
++
++		if (map_op.status) {
++			DPRINTK(" Grant table operation failure !\n");
++			return 0;
++		}
++
++		tocopy = min_t(size_t, size - offset, PAGE_SIZE);
++
++		if (copy_from_buffer((void *)(idx_to_kaddr(tpmif, i) |
++					      (tx->addr & ~PAGE_MASK)),
++				     &data[offset], tocopy, isuserbuffer)) {
++			tpmif_put(tpmif);
++			return -EFAULT;
++		}
++		tx->size = tocopy;
++
++		gnttab_set_unmap_op(&unmap_op, idx_to_kaddr(tpmif, i),
++				    GNTMAP_host_map, handle);
++
++		if (unlikely
++		    (HYPERVISOR_grant_table_op
++		     (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
++			BUG();
++		}
++
++		offset += tocopy;
++		i++;
++	}
++
++	rc = offset;
++	DPRINTK("Notifying frontend via irq %d\n", tpmif->irq);
++	notify_remote_via_irq(tpmif->irq);
++
++	return rc;
++}
++
++/*
++ * Read data from the shared memory and copy it directly into the
++ * provided buffer. Advance the read_last indicator which tells
++ * how many bytes have already been read.
++ */
++static int packet_read(struct packet *pak, size_t numbytes,
++		       char *buffer, size_t buffersize, int isuserbuffer)
++{
++	tpmif_t *tpmif = pak->tpmif;
++
++	/*
++	 * Read 'numbytes' of data from the buffer. The first 4
++	 * bytes are the instance number in network byte order,
++	 * after that come the data from the shared memory buffer.
++	 */
++	u32 to_copy;
++	u32 offset = 0;
++	u32 room_left = buffersize;
++
++	if (pak->last_read < 4) {
++		/*
++		 * copy the instance number into the buffer
++		 */
++		u32 instance_no = htonl(pak->tpm_instance);
++		u32 last_read = pak->last_read;
++
++		to_copy = min_t(size_t, 4 - last_read, numbytes);
++
++		if (copy_to_buffer(&buffer[0],
++				   &(((u8 *) & instance_no)[last_read]),
++				   to_copy, isuserbuffer)) {
++			return -EFAULT;
++		}
++
++		pak->last_read += to_copy;
++		offset += to_copy;
++		room_left -= to_copy;
++	}
++
++	/*
++	 * If the packet has a data buffer appended, read from it...
++	 */
++
++	if (room_left > 0) {
++		if (pak->data_buffer) {
++			u32 to_copy = min_t(u32, pak->data_len - offset, room_left);
++			u32 last_read = pak->last_read - 4;
++
++			if (copy_to_buffer(&buffer[offset],
++					   &pak->data_buffer[last_read],
++					   to_copy, isuserbuffer)) {
++				return -EFAULT;
++			}
++			pak->last_read += to_copy;
++			offset += to_copy;
++		} else {
++			offset = packet_read_shmem(pak,
++						   tpmif,
++						   offset,
++						   buffer,
++						   isuserbuffer, room_left);
++		}
++	}
++	return offset;
++}
++
++static int packet_read_shmem(struct packet *pak,
++			     tpmif_t * tpmif,
++			     u32 offset, char *buffer, int isuserbuffer,
++			     u32 room_left)
++{
++	u32 last_read = pak->last_read - 4;
++	u32 i = (last_read / PAGE_SIZE);
++	u32 pg_offset = last_read & (PAGE_SIZE - 1);
++	u32 to_copy;
++	grant_handle_t handle;
++
++	tpmif_tx_request_t *tx;
++
++	tx = &tpmif->tx->ring[0].req;
++	/*
++	 * Start copying data at the page with index 'index'
++	 * and within that page at offset 'offset'.
++	 * Copy a maximum of 'room_left' bytes.
++	 */
++	to_copy = min_t(u32, PAGE_SIZE - pg_offset, room_left);
++	while (to_copy > 0) {
++		void *src;
++		struct gnttab_map_grant_ref map_op;
++		struct gnttab_unmap_grant_ref unmap_op;
++
++		tx = &tpmif->tx->ring[i].req;
++
++		gnttab_set_map_op(&map_op, idx_to_kaddr(tpmif, i),
++				  GNTMAP_host_map, tx->ref, tpmif->domid);
++
++        do {
++		    if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++						       &map_op, 1)))
++			    BUG();
++            if(map_op.status) msleep(10);
++		} while(map_op.status == GNTST_eagain);
++
++		if (map_op.status) {
++			DPRINTK(" Grant table operation failure !\n");
++			return -EFAULT;
++		}
++
++		handle = map_op.handle;
++
++		if (to_copy > tx->size) {
++			/*
++			 * User requests more than what's available
++			 */
++			to_copy = min_t(u32, tx->size, to_copy);
++		}
++
++		DPRINTK("Copying from mapped memory at %08lx\n",
++			(unsigned long)(idx_to_kaddr(tpmif, i) |
++					(tx->addr & ~PAGE_MASK)));
++
++		src = (void *)(idx_to_kaddr(tpmif, i) |
++			       ((tx->addr & ~PAGE_MASK) + pg_offset));
++		if (copy_to_buffer(&buffer[offset],
++				   src, to_copy, isuserbuffer)) {
++			return -EFAULT;
++		}
++
++		DPRINTK("Data from TPM-FE of domain %d are %d %d %d %d\n",
++			tpmif->domid, buffer[offset], buffer[offset + 1],
++			buffer[offset + 2], buffer[offset + 3]);
++
++		gnttab_set_unmap_op(&unmap_op, idx_to_kaddr(tpmif, i),
++				    GNTMAP_host_map, handle);
++
++		if (unlikely
++		    (HYPERVISOR_grant_table_op
++		     (GNTTABOP_unmap_grant_ref, &unmap_op, 1))) {
++			BUG();
++		}
++
++		offset += to_copy;
++		pg_offset = 0;
++		last_read += to_copy;
++		room_left -= to_copy;
++
++		to_copy = min_t(u32, PAGE_SIZE, room_left);
++		i++;
++	}			/* while (to_copy > 0) */
++	/*
++	 * Adjust the last_read pointer
++	 */
++	pak->last_read = last_read + 4;
++	return offset;
++}
++
++/* ============================================================
++ * The file layer for reading data from this device
++ * ============================================================
++ */
++static int vtpm_op_open(struct inode *inode, struct file *f)
++{
++	int rc = 0;
++	unsigned long flags;
++
++	write_lock_irqsave(&dataex.pak_lock, flags);
++	if (dataex.has_opener == 0) {
++		dataex.has_opener = 1;
++	} else {
++		rc = -EPERM;
++	}
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++	return rc;
++}
++
++static ssize_t vtpm_op_read(struct file *file,
++			    char __user * data, size_t size, loff_t * offset)
++{
++	int ret_size = -ENODATA;
++	struct packet *pak = NULL;
++	unsigned long flags;
++
++	write_lock_irqsave(&dataex.pak_lock, flags);
++	if (dataex.aborted) {
++		dataex.aborted = 0;
++		dataex.copied_so_far = 0;
++		write_unlock_irqrestore(&dataex.pak_lock, flags);
++		return -EIO;
++	}
++
++	if (list_empty(&dataex.pending_pak)) {
++		write_unlock_irqrestore(&dataex.pak_lock, flags);
++		wait_event_interruptible(dataex.wait_queue,
++					 !list_empty(&dataex.pending_pak));
++		write_lock_irqsave(&dataex.pak_lock, flags);
++		dataex.copied_so_far = 0;
++	}
++
++	if (!list_empty(&dataex.pending_pak)) {
++		unsigned int left;
++
++		pak = list_entry(dataex.pending_pak.next, struct packet, next);
++		left = pak->data_len - dataex.copied_so_far;
++		list_del(&pak->next);
++		write_unlock_irqrestore(&dataex.pak_lock, flags);
++
++		DPRINTK("size given by app: %d, available: %d\n", size, left);
++
++		ret_size = min_t(size_t, size, left);
++
++		ret_size = packet_read(pak, ret_size, data, size, 1);
++
++		write_lock_irqsave(&dataex.pak_lock, flags);
++
++		if (ret_size < 0) {
++			del_singleshot_timer_sync(&pak->processing_timer);
++			packet_free(pak);
++			dataex.copied_so_far = 0;
++		} else {
++			DPRINTK("Copied %d bytes to user buffer\n", ret_size);
++
++			dataex.copied_so_far += ret_size;
++			if (dataex.copied_so_far >= pak->data_len + 4) {
++				DPRINTK("All data from this packet given to app.\n");
++				/* All data given to app */
++
++				del_singleshot_timer_sync(&pak->
++							  processing_timer);
++				list_add_tail(&pak->next, &dataex.current_pak);
++				/*
++				 * The more fontends that are handled at the same time,
++				 * the more time we give the TPM to process the request.
++				 */
++				mod_timer(&pak->processing_timer,
++					  jiffies + (num_frontends * 60 * HZ));
++				dataex.copied_so_far = 0;
++			} else {
++				list_add(&pak->next, &dataex.pending_pak);
++			}
++		}
++	}
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++
++	DPRINTK("Returning result from read to app: %d\n", ret_size);
++
++	return ret_size;
++}
++
++/*
++ * Write operation - only works after a previous read operation!
++ */
++static ssize_t vtpm_op_write(struct file *file,
++			     const char __user * data, size_t size,
++			     loff_t * offset)
++{
++	struct packet *pak;
++	int rc = 0;
++	unsigned int off = 4;
++	unsigned long flags;
++	struct vtpm_resp_hdr vrh;
++
++	/*
++	 * Minimum required packet size is:
++	 * 4 bytes for instance number
++	 * 2 bytes for tag
++	 * 4 bytes for paramSize
++	 * 4 bytes for the ordinal
++	 * sum: 14 bytes
++	 */
++	if (size < sizeof (vrh))
++		return -EFAULT;
++
++	if (copy_from_user(&vrh, data, sizeof (vrh)))
++		return -EFAULT;
++
++	/* malformed packet? */
++	if ((off + ntohl(vrh.len_no)) != size)
++		return -EFAULT;
++
++	write_lock_irqsave(&dataex.pak_lock, flags);
++	pak = packet_find_instance(&dataex.current_pak,
++				   ntohl(vrh.instance_no));
++
++	if (pak == NULL) {
++		write_unlock_irqrestore(&dataex.pak_lock, flags);
++		DPRINTK(KERN_ALERT "No associated packet! (inst=%d)\n",
++		        ntohl(vrh.instance_no));
++		return -EFAULT;
++	}
++
++	del_singleshot_timer_sync(&pak->processing_timer);
++	list_del(&pak->next);
++
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++
++	/*
++	 * The first 'offset' bytes must be the instance number - skip them.
++	 */
++	size -= off;
++
++	rc = packet_write(pak, &data[off], size, 1);
++
++	if (rc > 0) {
++		/* I neglected the first 4 bytes */
++		rc += off;
++	}
++	packet_free(pak);
++	return rc;
++}
++
++static int vtpm_op_release(struct inode *inode, struct file *file)
++{
++	unsigned long flags;
++
++	vtpm_release_packets(NULL, 1);
++	write_lock_irqsave(&dataex.pak_lock, flags);
++	dataex.has_opener = 0;
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++	return 0;
++}
++
++static unsigned int vtpm_op_poll(struct file *file,
++				 struct poll_table_struct *pts)
++{
++	unsigned int flags = POLLOUT | POLLWRNORM;
++
++	poll_wait(file, &dataex.wait_queue, pts);
++	if (!list_empty(&dataex.pending_pak)) {
++		flags |= POLLIN | POLLRDNORM;
++	}
++	return flags;
++}
++
++static const struct file_operations vtpm_ops = {
++	.owner = THIS_MODULE,
++	.llseek = no_llseek,
++	.open = vtpm_op_open,
++	.read = vtpm_op_read,
++	.write = vtpm_op_write,
++	.release = vtpm_op_release,
++	.poll = vtpm_op_poll,
++};
++
++static struct miscdevice vtpms_miscdevice = {
++	.minor = 225,
++	.name = "vtpm",
++	.fops = &vtpm_ops,
++};
++
++/***************************************************************
++ Utility functions
++***************************************************************/
++
++static int tpm_send_fail_message(struct packet *pak, u8 req_tag)
++{
++	int rc;
++	static const unsigned char tpm_error_message_fail[] = {
++		0x00, 0x00,
++		0x00, 0x00, 0x00, 0x0a,
++		0x00, 0x00, 0x00, 0x09	/* TPM_FAIL */
++	};
++	unsigned char buffer[sizeof (tpm_error_message_fail)];
++
++	memcpy(buffer, tpm_error_message_fail,
++	       sizeof (tpm_error_message_fail));
++	/*
++	 * Insert the right response tag depending on the given tag
++	 * All response tags are '+3' to the request tag.
++	 */
++	buffer[1] = req_tag + 3;
++
++	/*
++	 * Write the data to shared memory and notify the front-end
++	 */
++	rc = packet_write(pak, buffer, sizeof (buffer), 0);
++
++	return rc;
++}
++
++static int _vtpm_release_packets(struct list_head *head,
++				 tpmif_t * tpmif, int send_msgs)
++{
++	int aborted = 0;
++	int c = 0;
++	struct packet *pak;
++	struct list_head *pos, *tmp;
++
++	list_for_each_safe(pos, tmp, head) {
++		pak = list_entry(pos, struct packet, next);
++		c += 1;
++
++		if (tpmif == NULL || pak->tpmif == tpmif) {
++			int can_send = 0;
++
++			del_singleshot_timer_sync(&pak->processing_timer);
++			list_del(&pak->next);
++
++			if (pak->tpmif && pak->tpmif->status == CONNECTED) {
++				can_send = 1;
++			}
++
++			if (send_msgs && can_send) {
++				tpm_send_fail_message(pak, pak->req_tag);
++			}
++			packet_free(pak);
++			if (c == 1)
++				aborted = 1;
++		}
++	}
++	return aborted;
++}
++
++int vtpm_release_packets(tpmif_t * tpmif, int send_msgs)
++{
++	unsigned long flags;
++
++	write_lock_irqsave(&dataex.pak_lock, flags);
++
++	dataex.aborted = _vtpm_release_packets(&dataex.pending_pak,
++					       tpmif,
++					       send_msgs);
++	_vtpm_release_packets(&dataex.current_pak, tpmif, send_msgs);
++
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++	return 0;
++}
++
++static int vtpm_queue_packet(struct packet *pak)
++{
++	int rc = 0;
++
++	if (dataex.has_opener) {
++		unsigned long flags;
++
++		write_lock_irqsave(&dataex.pak_lock, flags);
++		list_add_tail(&pak->next, &dataex.pending_pak);
++		/* give the TPM some time to pick up the request */
++		mod_timer(&pak->processing_timer, jiffies + (30 * HZ));
++		write_unlock_irqrestore(&dataex.pak_lock, flags);
++
++		wake_up_interruptible(&dataex.wait_queue);
++	} else {
++		rc = -EFAULT;
++	}
++	return rc;
++}
++
++static int vtpm_receive(tpmif_t * tpmif, u32 size)
++{
++	int rc = 0;
++	unsigned char buffer[10];
++	__be32 *native_size;
++	struct packet *pak = packet_alloc(tpmif, size, 0, 0);
++
++	if (!pak)
++		return -ENOMEM;
++	/*
++	 * Read 10 bytes from the received buffer to test its
++	 * content for validity.
++	 */
++	if (sizeof (buffer) != packet_read(pak,
++					   sizeof (buffer), buffer,
++					   sizeof (buffer), 0)) {
++		goto failexit;
++	}
++	/*
++	 * Reset the packet read pointer so we can read all its
++	 * contents again.
++	 */
++	packet_reset(pak);
++
++	native_size = (__force __be32 *) (&buffer[4 + 2]);
++	/*
++	 * Verify that the size of the packet is correct
++	 * as indicated and that there's actually someone reading packets.
++	 * The minimum size of the packet is '10' for tag, size indicator
++	 * and ordinal.
++	 */
++	if (size < 10 ||
++	    be32_to_cpu(*native_size) != size ||
++	    0 == dataex.has_opener || tpmif->status != CONNECTED) {
++		rc = -EINVAL;
++		goto failexit;
++	} else {
++		rc = vtpm_queue_packet(pak);
++		if (rc < 0)
++			goto failexit;
++	}
++	return 0;
++
++      failexit:
++	if (pak) {
++		tpm_send_fail_message(pak, buffer[4 + 1]);
++		packet_free(pak);
++	}
++	return rc;
++}
++
++/*
++ * Timeout function that gets invoked when a packet has not been processed
++ * during the timeout period.
++ * The packet must be on a list when this function is invoked. This
++ * also means that once its taken off a list, the timer must be
++ * destroyed as well.
++ */
++static void processing_timeout(unsigned long ptr)
++{
++	struct packet *pak = (struct packet *)ptr;
++	unsigned long flags;
++
++	write_lock_irqsave(&dataex.pak_lock, flags);
++	/*
++	 * The packet needs to be searched whether it
++	 * is still on the list.
++	 */
++	if (pak == packet_find_packet(&dataex.pending_pak, pak) ||
++	    pak == packet_find_packet(&dataex.current_pak, pak)) {
++		if ((pak->flags & PACKET_FLAG_DISCARD_RESPONSE) == 0) {
++			tpm_send_fail_message(pak, pak->req_tag);
++		}
++		/* discard future responses */
++		pak->flags |= PACKET_FLAG_DISCARD_RESPONSE;
++	}
++
++	write_unlock_irqrestore(&dataex.pak_lock, flags);
++}
++
++static void tpm_tx_action(unsigned long unused);
++static DECLARE_TASKLET(tpm_tx_tasklet, tpm_tx_action, 0);
++
++static struct list_head tpm_schedule_list;
++static spinlock_t tpm_schedule_list_lock;
++
++static inline void maybe_schedule_tx_action(void)
++{
++	smp_mb();
++	tasklet_schedule(&tpm_tx_tasklet);
++}
++
++static inline int __on_tpm_schedule_list(tpmif_t * tpmif)
++{
++	return tpmif->list.next != NULL;
++}
++
++static void remove_from_tpm_schedule_list(tpmif_t * tpmif)
++{
++	spin_lock_irq(&tpm_schedule_list_lock);
++	if (likely(__on_tpm_schedule_list(tpmif))) {
++		list_del(&tpmif->list);
++		tpmif->list.next = NULL;
++		tpmif_put(tpmif);
++	}
++	spin_unlock_irq(&tpm_schedule_list_lock);
++}
++
++static void add_to_tpm_schedule_list_tail(tpmif_t * tpmif)
++{
++	if (__on_tpm_schedule_list(tpmif))
++		return;
++
++	spin_lock_irq(&tpm_schedule_list_lock);
++	if (!__on_tpm_schedule_list(tpmif) && tpmif->active) {
++		list_add_tail(&tpmif->list, &tpm_schedule_list);
++		tpmif_get(tpmif);
++	}
++	spin_unlock_irq(&tpm_schedule_list_lock);
++}
++
++void tpmif_schedule_work(tpmif_t * tpmif)
++{
++	add_to_tpm_schedule_list_tail(tpmif);
++	maybe_schedule_tx_action();
++}
++
++void tpmif_deschedule_work(tpmif_t * tpmif)
++{
++	remove_from_tpm_schedule_list(tpmif);
++}
++
++static void tpm_tx_action(unsigned long unused)
++{
++	struct list_head *ent;
++	tpmif_t *tpmif;
++	tpmif_tx_request_t *tx;
++
++	DPRINTK("%s: Getting data from front-end(s)!\n", __FUNCTION__);
++
++	while (!list_empty(&tpm_schedule_list)) {
++		/* Get a tpmif from the list with work to do. */
++		ent = tpm_schedule_list.next;
++		tpmif = list_entry(ent, tpmif_t, list);
++		tpmif_get(tpmif);
++		remove_from_tpm_schedule_list(tpmif);
++
++		tx = &tpmif->tx->ring[0].req;
++
++		/* pass it up */
++		vtpm_receive(tpmif, tx->size);
++
++		tpmif_put(tpmif);
++	}
++}
++
++irqreturn_t tpmif_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	tpmif_t *tpmif = (tpmif_t *) dev_id;
++
++	add_to_tpm_schedule_list_tail(tpmif);
++	maybe_schedule_tx_action();
++	return IRQ_HANDLED;
++}
++
++static int __init tpmback_init(void)
++{
++	int rc;
++
++	if ((rc = misc_register(&vtpms_miscdevice)) != 0) {
++		printk(KERN_ALERT
++		       "Could not register misc device for TPM BE.\n");
++		return rc;
++	}
++
++	dataex_init(&dataex);
++
++	spin_lock_init(&tpm_schedule_list_lock);
++	INIT_LIST_HEAD(&tpm_schedule_list);
++
++	tpmif_interface_init();
++	tpmif_xenbus_init();
++
++	printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
++
++	return 0;
++}
++
++module_init(tpmback_init);
++
++void __exit tpmback_exit(void)
++{
++	vtpm_release_packets(NULL, 0);
++	tpmif_xenbus_exit();
++	tpmif_interface_exit();
++	misc_deregister(&vtpms_miscdevice);
++}
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/tpmback/xenbus.c	2008-03-06 08:54:32.000000000 +0100
+@@ -0,0 +1,289 @@
++/*  Xenbus code for tpmif backend
++    Copyright (C) 2005 IBM Corporation
++    Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
++
++    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 <stdarg.h>
++#include <linux/module.h>
++#include <xen/xenbus.h>
++#include "common.h"
++
++struct backend_info
++{
++	struct xenbus_device *dev;
++
++	/* our communications channel */
++	tpmif_t *tpmif;
++
++	long int frontend_id;
++	long int instance; // instance of TPM
++	u8 is_instance_set;// whether instance number has been set
++
++	/* watch front end for changes */
++	struct xenbus_watch backend_watch;
++};
++
++static void maybe_connect(struct backend_info *be);
++static void connect(struct backend_info *be);
++static int connect_ring(struct backend_info *be);
++static void backend_changed(struct xenbus_watch *watch,
++			    const char **vec, unsigned int len);
++static void frontend_changed(struct xenbus_device *dev,
++			     enum xenbus_state frontend_state);
++
++long int tpmback_get_instance(struct backend_info *bi)
++{
++	long int res = -1;
++	if (bi && bi->is_instance_set)
++		res = bi->instance;
++	return res;
++}
++
++static int tpmback_remove(struct xenbus_device *dev)
++{
++	struct backend_info *be = dev->dev.driver_data;
++
++	if (!be) return 0;
++
++	if (be->backend_watch.node) {
++		unregister_xenbus_watch(&be->backend_watch);
++		kfree(be->backend_watch.node);
++		be->backend_watch.node = NULL;
++	}
++	if (be->tpmif) {
++		be->tpmif->bi = NULL;
++		vtpm_release_packets(be->tpmif, 0);
++		tpmif_put(be->tpmif);
++		be->tpmif = NULL;
++	}
++	kfree(be);
++	dev->dev.driver_data = NULL;
++	return 0;
++}
++
++static int tpmback_probe(struct xenbus_device *dev,
++			 const struct xenbus_device_id *id)
++{
++	int err;
++	struct backend_info *be = kzalloc(sizeof(struct backend_info),
++					  GFP_KERNEL);
++
++	if (!be) {
++		xenbus_dev_fatal(dev, -ENOMEM,
++				 "allocating backend structure");
++		return -ENOMEM;
++	}
++
++	be->is_instance_set = 0;
++	be->dev = dev;
++	dev->dev.driver_data = be;
++
++	err = xenbus_watch_path2(dev, dev->nodename,
++				 "instance", &be->backend_watch,
++				 backend_changed);
++	if (err) {
++		goto fail;
++	}
++
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err) {
++		goto fail;
++	}
++	return 0;
++fail:
++	tpmback_remove(dev);
++	return err;
++}
++
++
++static void backend_changed(struct xenbus_watch *watch,
++			    const char **vec, unsigned int len)
++{
++	int err;
++	long instance;
++	struct backend_info *be
++		= container_of(watch, struct backend_info, backend_watch);
++	struct xenbus_device *dev = be->dev;
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++			   "instance","%li", &instance);
++	if (XENBUS_EXIST_ERR(err)) {
++		return;
++	}
++
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading instance");
++		return;
++	}
++
++	if (be->is_instance_set == 0) {
++		be->instance = instance;
++		be->is_instance_set = 1;
++	}
++}
++
++
++static void 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:
++	case XenbusStateInitialised:
++		break;
++
++	case XenbusStateConnected:
++		err = connect_ring(be);
++		if (err) {
++			return;
++		}
++		maybe_connect(be);
++		break;
++
++	case XenbusStateClosing:
++		be->instance = -1;
++		xenbus_switch_state(dev, XenbusStateClosing);
++		break;
++
++	case XenbusStateUnknown: /* keep it here */
++	case XenbusStateClosed:
++		xenbus_switch_state(dev, XenbusStateClosed);
++		device_unregister(&be->dev->dev);
++		tpmback_remove(dev);
++		break;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL,
++				 "saw state %d at frontend",
++				 frontend_state);
++		break;
++	}
++}
++
++
++
++static void maybe_connect(struct backend_info *be)
++{
++	if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
++		return;
++
++	connect(be);
++}
++
++
++static void connect(struct backend_info *be)
++{
++	struct xenbus_transaction xbt;
++	int err;
++	struct xenbus_device *dev = be->dev;
++	unsigned long ready = 1;
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(be->dev, err, "starting transaction");
++		return;
++	}
++
++	err = xenbus_printf(xbt, be->dev->nodename,
++			    "ready", "%lu", ready);
++	if (err) {
++		xenbus_dev_fatal(be->dev, err, "writing 'ready'");
++		goto abort;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++	if (err)
++		xenbus_dev_fatal(be->dev, err, "end of transaction");
++
++	err = xenbus_switch_state(dev, XenbusStateConnected);
++	if (!err)
++		be->tpmif->status = CONNECTED;
++	return;
++abort:
++	xenbus_transaction_end(xbt, 1);
++}
++
++
++static int connect_ring(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	unsigned long ring_ref;
++	unsigned int evtchn;
++	int err;
++
++	err = xenbus_gather(XBT_NIL, dev->otherend,
++			    "ring-ref", "%lu", &ring_ref,
++			    "event-channel", "%u", &evtchn, NULL);
++	if (err) {
++		xenbus_dev_error(dev, err,
++				 "reading %s/ring-ref and event-channel",
++				 dev->otherend);
++		return err;
++	}
++
++	if (!be->tpmif) {
++		be->tpmif = tpmif_find(dev->otherend_id, be);
++		if (IS_ERR(be->tpmif)) {
++			err = PTR_ERR(be->tpmif);
++			be->tpmif = NULL;
++			xenbus_dev_fatal(dev,err,"creating vtpm interface");
++			return err;
++		}
++	}
++
++	if (be->tpmif != NULL) {
++		err = tpmif_map(be->tpmif, ring_ref, evtchn);
++		if (err) {
++			xenbus_dev_error(dev, err,
++					 "mapping shared-frame %lu port %u",
++					 ring_ref, evtchn);
++			return err;
++		}
++	}
++	return 0;
++}
++
++
++static const struct xenbus_device_id tpmback_ids[] = {
++	{ "vtpm" },
++	{ "" }
++};
++
++
++static struct xenbus_driver tpmback = {
++	.name = "vtpm",
++	.owner = THIS_MODULE,
++	.ids = tpmback_ids,
++	.probe = tpmback_probe,
++	.remove = tpmback_remove,
++	.otherend_changed = frontend_changed,
++};
++
++
++void tpmif_xenbus_init(void)
++{
++	xenbus_register_backend(&tpmback);
++}
++
++void tpmif_xenbus_exit(void)
++{
++	xenbus_unregister_driver(&tpmback);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/Makefile	2009-04-07 13:58:49.000000000 +0200
+@@ -0,0 +1,4 @@
++obj-$(CONFIG_XEN_USB_BACKEND) := usbbk.o
++
++usbbk-y   := usbstub.o xenbus.o interface.o usbback.o
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/interface.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,257 @@
++/*
++ * interface.c
++ *
++ * Xen USB backend interface management.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include <linux/delay.h>
++#include "usbback.h"
++
++static LIST_HEAD(usbif_list);
++static DEFINE_SPINLOCK(usbif_list_lock);
++
++usbif_t *find_usbif(domid_t domid, unsigned int handle)
++{
++	usbif_t *usbif;
++	int found = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&usbif_list_lock, flags);
++	list_for_each_entry(usbif, &usbif_list, usbif_list) {
++		if (usbif->domid == domid
++			&& usbif->handle == handle) {
++			found = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&usbif_list_lock, flags);
++
++	if (found)
++		return usbif;
++
++	return NULL;
++}
++
++usbif_t *usbif_alloc(domid_t domid, unsigned int handle)
++{
++	usbif_t *usbif;
++	unsigned long flags;
++	int i;
++
++	usbif = kzalloc(sizeof(usbif_t), GFP_KERNEL);
++	if (!usbif)
++		return NULL;
++
++	usbif->domid = domid;
++	usbif->handle = handle;
++	spin_lock_init(&usbif->urb_ring_lock);
++	spin_lock_init(&usbif->conn_ring_lock);
++	atomic_set(&usbif->refcnt, 0);
++	init_waitqueue_head(&usbif->wq);
++	init_waitqueue_head(&usbif->waiting_to_free);
++	spin_lock_init(&usbif->stub_lock);
++	INIT_LIST_HEAD(&usbif->stub_list);
++	spin_lock_init(&usbif->addr_lock);
++	for (i = 0; i < USB_DEV_ADDR_SIZE; i++)
++		usbif->addr_table[i] = NULL;
++
++	spin_lock_irqsave(&usbif_list_lock, flags);
++	list_add(&usbif->usbif_list, &usbif_list);
++	spin_unlock_irqrestore(&usbif_list_lock, flags);
++
++	return usbif;
++}
++
++static int map_frontend_pages(usbif_t *usbif,
++				grant_ref_t urb_ring_ref,
++				grant_ref_t conn_ring_ref)
++{
++	struct gnttab_map_grant_ref op;
++
++	gnttab_set_map_op(&op, (unsigned long)usbif->urb_ring_area->addr,
++			  GNTMAP_host_map, urb_ring_ref, usbif->domid);
++
++
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while (op.status == GNTST_eagain);
++
++	if (op.status) {
++		printk(KERN_ERR "grant table failure mapping urb_ring_ref\n");
++		return op.status;
++	}
++
++	usbif->urb_shmem_ref = urb_ring_ref;
++	usbif->urb_shmem_handle = op.handle;
++
++	gnttab_set_map_op(&op, (unsigned long)usbif->conn_ring_area->addr,
++			  GNTMAP_host_map, conn_ring_ref, usbif->domid);
++
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while (op.status == GNTST_eagain);
++
++	if (op.status) {
++		struct gnttab_unmap_grant_ref unop;
++		gnttab_set_unmap_op(&unop,
++				(unsigned long) usbif->urb_ring_area->addr,
++				GNTMAP_host_map, usbif->urb_shmem_handle);
++		VOID(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unop,
++				1));
++		printk(KERN_ERR "grant table failure mapping conn_ring_ref\n");
++		return op.status;
++	}
++
++	usbif->conn_shmem_ref = conn_ring_ref;
++	usbif->conn_shmem_handle = op.handle;
++
++	return 0;
++}
++
++static void unmap_frontend_pages(usbif_t *usbif)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)usbif->urb_ring_area->addr,
++			    GNTMAP_host_map, usbif->urb_shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	gnttab_set_unmap_op(&op, (unsigned long)usbif->conn_ring_area->addr,
++			    GNTMAP_host_map, usbif->conn_shmem_handle);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++}
++
++int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref,
++		unsigned long conn_ring_ref, unsigned int evtchn)
++{
++	int err = -ENOMEM;
++
++	usbif_urb_sring_t *urb_sring;
++	usbif_conn_sring_t *conn_sring;
++
++	if (usbif->irq)
++		return 0;
++
++	if ((usbif->urb_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
++		return err;
++	if ((usbif->conn_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
++		goto fail_alloc;
++
++	err = map_frontend_pages(usbif, urb_ring_ref, conn_ring_ref);
++	if (err)
++		goto fail_map;
++
++	err = bind_interdomain_evtchn_to_irqhandler(
++			usbif->domid, evtchn, usbbk_be_int, 0,
++			"usbif-backend", usbif);
++	if (err < 0)
++		goto fail_evtchn;
++	usbif->irq = err;
++
++	urb_sring = (usbif_urb_sring_t *) usbif->urb_ring_area->addr;
++	BACK_RING_INIT(&usbif->urb_ring, urb_sring, PAGE_SIZE);
++
++	conn_sring = (usbif_conn_sring_t *) usbif->conn_ring_area->addr;
++	BACK_RING_INIT(&usbif->conn_ring, conn_sring, PAGE_SIZE);
++
++	return 0;
++
++fail_evtchn:
++	unmap_frontend_pages(usbif);
++fail_map:
++	free_vm_area(usbif->conn_ring_area);
++fail_alloc:
++	free_vm_area(usbif->urb_ring_area);
++
++	return err;
++}
++
++void usbif_disconnect(usbif_t *usbif)
++{
++	struct usbstub *stub, *tmp;
++	unsigned long flags;
++
++	if (usbif->xenusbd) {
++		kthread_stop(usbif->xenusbd);
++		usbif->xenusbd = NULL;
++	}
++
++	spin_lock_irqsave(&usbif->stub_lock, flags);
++	list_for_each_entry_safe(stub, tmp, &usbif->stub_list, dev_list) {
++		usbbk_unlink_urbs(stub);
++		detach_device_without_lock(usbif, stub);
++	}
++	spin_unlock_irqrestore(&usbif->stub_lock, flags);
++
++	wait_event(usbif->waiting_to_free, atomic_read(&usbif->refcnt) == 0);
++
++	if (usbif->irq) {
++		unbind_from_irqhandler(usbif->irq, usbif);
++		usbif->irq = 0;
++	}
++
++	if (usbif->urb_ring.sring) {
++		unmap_frontend_pages(usbif);
++		free_vm_area(usbif->urb_ring_area);
++		free_vm_area(usbif->conn_ring_area);
++		usbif->urb_ring.sring = NULL;
++		usbif->conn_ring.sring = NULL;
++	}
++}
++
++void usbif_free(usbif_t *usbif)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&usbif_list_lock, flags);
++	list_del(&usbif->usbif_list);
++	spin_unlock_irqrestore(&usbif_list_lock, flags);
++	kfree(usbif);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/usbback.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,1165 @@
++/*
++ * usbback.c
++ *
++ * Xen USB backend driver
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include <linux/mm.h>
++#include <xen/balloon.h>
++#include "usbback.h"
++
++#if 0
++#include "../../usb/core/hub.h"
++#endif
++
++int usbif_reqs = USBIF_BACK_MAX_PENDING_REQS;
++module_param_named(reqs, usbif_reqs, int, 0);
++MODULE_PARM_DESC(reqs, "Number of usbback requests to allocate");
++
++struct pending_req_segment {
++	uint16_t offset;
++	uint16_t length;
++};
++
++typedef struct {
++	usbif_t *usbif;
++
++	uint16_t id; /* request id */
++
++	struct usbstub *stub;
++	struct list_head urb_list;
++
++	/* urb */
++	struct urb *urb;
++	void *buffer;
++	dma_addr_t transfer_dma;
++	struct usb_ctrlrequest *setup;
++	dma_addr_t setup_dma;
++
++	/* request segments */
++	uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
++	uint16_t nr_extra_segs; /* number of iso_frame_desc segments (ISO) */
++	struct pending_req_segment *seg;
++
++	struct list_head free_list;
++} pending_req_t;
++
++static pending_req_t *pending_reqs;
++static struct list_head pending_free;
++static DEFINE_SPINLOCK(pending_free_lock);
++static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq);
++
++#define USBBACK_INVALID_HANDLE (~0)
++
++static struct page **pending_pages;
++static grant_handle_t *pending_grant_handles;
++
++static inline int vaddr_pagenr(pending_req_t *req, int seg)
++{
++	return (req - pending_reqs) * USBIF_MAX_SEGMENTS_PER_REQUEST + seg;
++}
++
++static inline 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)])
++
++static pending_req_t *alloc_req(void)
++{
++	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 inline void add_req_to_submitting_list(struct usbstub *stub, pending_req_t *pending_req)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&stub->submitting_lock, flags);
++	list_add_tail(&pending_req->urb_list, &stub->submitting_list);
++	spin_unlock_irqrestore(&stub->submitting_lock, flags);
++}
++
++static inline void remove_req_from_submitting_list(struct usbstub *stub, pending_req_t *pending_req)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&stub->submitting_lock, flags);
++	list_del_init(&pending_req->urb_list);
++	spin_unlock_irqrestore(&stub->submitting_lock, flags);
++}
++
++void usbbk_unlink_urbs(struct usbstub *stub)
++{
++	pending_req_t *req, *tmp;
++	unsigned long flags;
++
++	spin_lock_irqsave(&stub->submitting_lock, flags);
++	list_for_each_entry_safe(req, tmp, &stub->submitting_list, urb_list) {
++		usb_unlink_urb(req->urb);
++	}
++	spin_unlock_irqrestore(&stub->submitting_lock, flags);
++}
++
++static void fast_flush_area(pending_req_t *pending_req)
++{
++	struct gnttab_unmap_grant_ref unmap[USBIF_MAX_SEGMENTS_PER_REQUEST];
++	unsigned int i, nr_segs, invcount = 0;
++	grant_handle_t handle;
++	int ret;
++
++	nr_segs = pending_req->nr_buffer_segs + pending_req->nr_extra_segs;
++
++	if (nr_segs) {
++		for (i = 0; i < nr_segs; i++) {
++			handle = pending_handle(pending_req, i);
++			if (handle == USBBACK_INVALID_HANDLE)
++				continue;
++			gnttab_set_unmap_op(&unmap[invcount], vaddr(pending_req, i),
++					    GNTMAP_host_map, handle);
++			pending_handle(pending_req, i) = USBBACK_INVALID_HANDLE;
++			invcount++;
++		}
++
++		ret = HYPERVISOR_grant_table_op(
++			GNTTABOP_unmap_grant_ref, unmap, invcount);
++		BUG_ON(ret);
++
++		kfree(pending_req->seg);
++	}
++
++	return;
++}
++
++static void copy_buff_to_pages(void *buff, pending_req_t *pending_req,
++		int start, int nr_pages)
++{
++	unsigned long copied = 0;
++	int i;
++
++	for (i = start; i < start + nr_pages; i++) {
++		memcpy((void *) vaddr(pending_req, i) + pending_req->seg[i].offset,
++			buff + copied,
++			pending_req->seg[i].length);
++		copied += pending_req->seg[i].length;
++	}
++}
++
++static void copy_pages_to_buff(void *buff, pending_req_t *pending_req,
++		int start, int nr_pages)
++{
++	unsigned long copied = 0;
++	int i;
++
++	for (i = start; i < start + nr_pages; i++) {
++		memcpy(buff + copied,
++			(void *) vaddr(pending_req, i) + pending_req->seg[i].offset,
++			pending_req->seg[i].length);
++		copied += pending_req->seg[i].length;
++	}
++}
++
++static int usbbk_alloc_urb(usbif_urb_request_t *req, pending_req_t *pending_req)
++{
++	int ret;
++
++	if (usb_pipeisoc(req->pipe))
++		pending_req->urb = usb_alloc_urb(req->u.isoc.number_of_packets, GFP_KERNEL);
++	else
++		pending_req->urb = usb_alloc_urb(0, GFP_KERNEL);
++	if (!pending_req->urb) {
++		printk(KERN_ERR "usbback: can't alloc urb\n");
++		ret = -ENOMEM;
++		goto fail;
++	}
++
++	if (req->buffer_length) {
++		pending_req->buffer = usb_buffer_alloc(pending_req->stub->udev,
++				req->buffer_length, GFP_KERNEL,
++				&pending_req->transfer_dma);
++		if (!pending_req->buffer) {
++			printk(KERN_ERR "usbback: can't alloc urb buffer\n");
++			ret = -ENOMEM;
++			goto fail_free_urb;
++		}
++	}
++
++	if (usb_pipecontrol(req->pipe)) {
++		pending_req->setup = usb_buffer_alloc(pending_req->stub->udev,
++				sizeof(struct usb_ctrlrequest), GFP_KERNEL,
++				&pending_req->setup_dma);
++		if (!pending_req->setup) {
++			printk(KERN_ERR "usbback: can't alloc usb_ctrlrequest\n");
++			ret = -ENOMEM;
++			goto fail_free_buffer;
++		}
++	}
++
++	return 0;
++
++fail_free_buffer:
++	if (req->buffer_length)
++		usb_buffer_free(pending_req->stub->udev, req->buffer_length,
++				pending_req->buffer, pending_req->transfer_dma);
++fail_free_urb:
++	usb_free_urb(pending_req->urb);
++fail:
++	return ret;
++}
++
++static void usbbk_free_urb(struct urb *urb)
++{
++	if (usb_pipecontrol(urb->pipe))
++		usb_buffer_free(urb->dev, sizeof(struct usb_ctrlrequest),
++				urb->setup_packet, urb->setup_dma);
++	if (urb->transfer_buffer_length)
++		usb_buffer_free(urb->dev, urb->transfer_buffer_length,
++				urb->transfer_buffer, urb->transfer_dma);
++	barrier();
++	usb_free_urb(urb);
++}
++
++static void usbbk_notify_work(usbif_t *usbif)
++{
++	usbif->waiting_reqs = 1;
++	wake_up(&usbif->wq);
++}
++
++irqreturn_t usbbk_be_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++	usbbk_notify_work(dev_id);
++	return IRQ_HANDLED;
++}
++
++static void usbbk_do_response(pending_req_t *pending_req, int32_t status,
++					int32_t actual_length, int32_t error_count, uint16_t start_frame)
++{
++	usbif_t *usbif = pending_req->usbif;
++	usbif_urb_response_t *res;
++	unsigned long flags;
++	int notify;
++
++	spin_lock_irqsave(&usbif->urb_ring_lock, flags);
++	res = RING_GET_RESPONSE(&usbif->urb_ring, usbif->urb_ring.rsp_prod_pvt);
++	res->id = pending_req->id;
++	res->status = status;
++	res->actual_length = actual_length;
++	res->error_count = error_count;
++	res->start_frame = start_frame;
++	usbif->urb_ring.rsp_prod_pvt++;
++	barrier();
++	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usbif->urb_ring, notify);
++	spin_unlock_irqrestore(&usbif->urb_ring_lock, flags);
++
++	if (notify)
++		notify_remote_via_irq(usbif->irq);
++}
++
++static void usbbk_urb_complete(struct urb *urb, struct pt_regs *regs)
++{
++	pending_req_t *pending_req = (pending_req_t *)urb->context;
++
++	if (usb_pipein(urb->pipe) && urb->status == 0 && urb->actual_length > 0)
++		copy_buff_to_pages(pending_req->buffer, pending_req,
++					0, pending_req->nr_buffer_segs);
++
++	if (usb_pipeisoc(urb->pipe))
++		copy_buff_to_pages(&urb->iso_frame_desc[0], pending_req,
++					pending_req->nr_buffer_segs, pending_req->nr_extra_segs);
++
++	barrier();
++
++	fast_flush_area(pending_req);
++
++	usbbk_do_response(pending_req, urb->status, urb->actual_length,
++					urb->error_count, urb->start_frame);
++
++	remove_req_from_submitting_list(pending_req->stub, pending_req);
++
++	barrier();
++	usbbk_free_urb(urb);
++	usbif_put(pending_req->usbif);
++	free_req(pending_req);
++}
++
++static int usbbk_gnttab_map(usbif_t *usbif,
++			usbif_urb_request_t *req, pending_req_t *pending_req)
++{
++	int i, ret;
++	unsigned int nr_segs;
++	uint32_t flags;
++	struct gnttab_map_grant_ref map[USBIF_MAX_SEGMENTS_PER_REQUEST];
++
++	nr_segs = pending_req->nr_buffer_segs + pending_req->nr_extra_segs;
++
++	if (nr_segs > USBIF_MAX_SEGMENTS_PER_REQUEST) {
++		printk(KERN_ERR "Bad number of segments in request\n");
++		ret = -EINVAL;
++		goto fail;
++	}
++
++	if (nr_segs) {
++		pending_req->seg = kmalloc(sizeof(struct pending_req_segment)
++				* nr_segs, GFP_KERNEL);
++		if (!pending_req->seg) {
++			ret = -ENOMEM;
++			goto fail;
++		}
++
++		if (pending_req->nr_buffer_segs) {
++			flags = GNTMAP_host_map;
++			if (usb_pipeout(req->pipe))
++				flags |= GNTMAP_readonly;
++			for (i = 0; i < pending_req->nr_buffer_segs; i++)
++				gnttab_set_map_op(&map[i], vaddr(
++						pending_req, i), flags,
++						req->seg[i].gref,
++						usbif->domid);
++		}
++
++		if (pending_req->nr_extra_segs) {
++			flags = GNTMAP_host_map;
++			for (i = req->nr_buffer_segs; i < nr_segs; i++)
++				gnttab_set_map_op(&map[i], vaddr(
++						pending_req, i), flags,
++						req->seg[i].gref,
++						usbif->domid);
++		}
++
++		ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
++					map, nr_segs);
++		BUG_ON(ret);
++        /* Make sure than none of the map ops failed with GNTST_eagain */
++        for( i = 0; i < nr_segs; i++) {
++            while(map[i].status == GNTST_eagain) {
++                msleep(10);
++		        ret = HYPERVISOR_grant_table_op(
++                                GNTTABOP_map_grant_ref,
++				                &map[i], 1);
++		        BUG_ON(ret);
++            }
++        }
++
++		for (i = 0; i < nr_segs; i++) {
++			if (unlikely(map[i].status != 0)) {
++				printk(KERN_ERR "usbback: invalid buffer -- could not remap it\n");
++				map[i].handle = USBBACK_INVALID_HANDLE;
++				ret |= 1;
++			}
++
++			pending_handle(pending_req, i) = map[i].handle;
++
++			if (ret)
++				continue;
++
++			set_phys_to_machine(__pa(vaddr(
++				pending_req, i)) >> PAGE_SHIFT,
++				FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
++
++			pending_req->seg[i].offset = req->seg[i].offset;
++			pending_req->seg[i].length = req->seg[i].length;
++
++			barrier();
++
++			if (pending_req->seg[i].offset >= PAGE_SIZE ||
++					pending_req->seg[i].length > PAGE_SIZE ||
++					pending_req->seg[i].offset + pending_req->seg[i].length > PAGE_SIZE)
++					ret |= 1;
++		}
++
++		if (ret)
++			goto fail_flush;
++	}
++
++	return 0;
++
++fail_flush:
++	fast_flush_area(pending_req);
++	ret = -ENOMEM;
++
++fail:
++	return ret;
++}
++
++static void usbbk_init_urb(usbif_urb_request_t *req, pending_req_t *pending_req)
++{
++	unsigned int pipe;
++	struct usb_device *udev = pending_req->stub->udev;
++	struct urb *urb = pending_req->urb;
++
++	switch (usb_pipetype(req->pipe)) {
++	case PIPE_ISOCHRONOUS:
++		if (usb_pipein(req->pipe))
++			pipe = usb_rcvisocpipe(udev, usb_pipeendpoint(req->pipe));
++		else
++			pipe = usb_sndisocpipe(udev, usb_pipeendpoint(req->pipe));
++
++		urb->dev = udev;
++		urb->pipe = pipe;
++		urb->transfer_flags = req->transfer_flags;
++		urb->transfer_flags |= URB_ISO_ASAP;
++		urb->transfer_buffer = pending_req->buffer;
++		urb->transfer_buffer_length = req->buffer_length;
++		urb->complete = usbbk_urb_complete;
++		urb->context = pending_req;
++		urb->interval = req->u.isoc.interval;
++		urb->start_frame = req->u.isoc.start_frame;
++		urb->number_of_packets = req->u.isoc.number_of_packets;
++
++		break;
++	case PIPE_INTERRUPT:
++		if (usb_pipein(req->pipe))
++			pipe = usb_rcvintpipe(udev, usb_pipeendpoint(req->pipe));
++		else
++			pipe = usb_sndintpipe(udev, usb_pipeendpoint(req->pipe));
++
++		usb_fill_int_urb(urb, udev, pipe,
++				pending_req->buffer, req->buffer_length,
++				usbbk_urb_complete,
++				pending_req, req->u.intr.interval);
++		/*
++		 * high speed interrupt endpoints use a logarithmic encoding of
++		 * the endpoint interval, and usb_fill_int_urb() initializes a
++		 * interrupt urb with the encoded interval value.
++		 *
++		 * req->u.intr.interval is the interval value that already
++		 * encoded in the frontend part, and the above usb_fill_int_urb()
++		 * initializes the urb->interval with double encoded value.
++		 *
++		 * so, simply overwrite the urb->interval with original value.
++		 */
++		urb->interval = req->u.intr.interval;
++		urb->transfer_flags = req->transfer_flags;
++
++		break;
++	case PIPE_CONTROL:
++		if (usb_pipein(req->pipe))
++			pipe = usb_rcvctrlpipe(udev, 0);
++		else
++			pipe = usb_sndctrlpipe(udev, 0);
++
++		usb_fill_control_urb(urb, udev, pipe,
++				(unsigned char *) pending_req->setup,
++				pending_req->buffer, req->buffer_length,
++				usbbk_urb_complete, pending_req);
++		memcpy(pending_req->setup, req->u.ctrl, 8);
++		urb->setup_dma = pending_req->setup_dma;
++		urb->transfer_flags = req->transfer_flags;
++		urb->transfer_flags |= URB_NO_SETUP_DMA_MAP;
++
++		break;
++	case PIPE_BULK:
++		if (usb_pipein(req->pipe))
++			pipe = usb_rcvbulkpipe(udev, usb_pipeendpoint(req->pipe));
++		else
++			pipe = usb_sndbulkpipe(udev, usb_pipeendpoint(req->pipe));
++
++		usb_fill_bulk_urb(urb, udev, pipe,
++				pending_req->buffer, req->buffer_length,
++				usbbk_urb_complete, pending_req);
++		urb->transfer_flags = req->transfer_flags;
++
++		break;
++	default:
++		break;
++	}
++
++	if (req->buffer_length) {
++		urb->transfer_dma = pending_req->transfer_dma;
++		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++	}
++}
++
++struct set_interface_request {
++	pending_req_t *pending_req;
++	int interface;
++	int alternate;
++	struct work_struct work;
++};
++
++static void usbbk_set_interface_work(void *data)
++{
++	struct set_interface_request *req = (struct set_interface_request *) data;
++	pending_req_t *pending_req = req->pending_req;
++	struct usb_device *udev = req->pending_req->stub->udev;
++
++	int ret;
++
++	usb_lock_device(udev);
++	ret = usb_set_interface(udev, req->interface, req->alternate);
++	usb_unlock_device(udev);
++	usb_put_dev(udev);
++
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(pending_req->usbif);
++	free_req(pending_req);
++	kfree(req);
++}
++
++static int usbbk_set_interface(pending_req_t *pending_req, int interface, int alternate)
++{
++	struct set_interface_request *req;
++	struct usb_device *udev = pending_req->stub->udev;
++
++	req = kmalloc(sizeof(*req), GFP_KERNEL);
++	if (!req)
++		return -ENOMEM;
++	req->pending_req = pending_req;
++	req->interface = interface;
++	req->alternate = alternate;
++	INIT_WORK(&req->work, usbbk_set_interface_work, req);
++	usb_get_dev(udev);
++	schedule_work(&req->work);
++	return 0;
++}
++
++struct clear_halt_request {
++	pending_req_t *pending_req;
++	int pipe;
++	struct work_struct work;
++};
++
++static void usbbk_clear_halt_work(void *data)
++{
++	struct clear_halt_request *req = (struct clear_halt_request *) data;
++	pending_req_t *pending_req = req->pending_req;
++	struct usb_device *udev = req->pending_req->stub->udev;
++	int ret;
++
++	usb_lock_device(udev);
++	ret = usb_clear_halt(req->pending_req->stub->udev, req->pipe);
++	usb_unlock_device(udev);
++	usb_put_dev(udev);
++
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(pending_req->usbif);
++	free_req(pending_req);
++	kfree(req);
++}
++
++static int usbbk_clear_halt(pending_req_t *pending_req, int pipe)
++{
++	struct clear_halt_request *req;
++	struct usb_device *udev = pending_req->stub->udev;
++
++	req = kmalloc(sizeof(*req), GFP_KERNEL);
++	if (!req)
++		return -ENOMEM;
++	req->pending_req = pending_req;
++	req->pipe = pipe;
++	INIT_WORK(&req->work, usbbk_clear_halt_work, req);
++
++	usb_get_dev(udev);
++	schedule_work(&req->work);
++	return 0;
++}
++
++#if 0
++struct port_reset_request {
++	pending_req_t *pending_req;
++	struct work_struct work;
++};
++
++static void usbbk_port_reset_work(void *data)
++{
++	struct port_reset_request *req = (struct port_reset_request *) data;
++	pending_req_t *pending_req = req->pending_req;
++	struct usb_device *udev = pending_req->stub->udev;
++	int ret, ret_lock;
++
++	ret = ret_lock = usb_lock_device_for_reset(udev, NULL);
++	if (ret_lock >= 0) {
++		ret = usb_reset_device(udev);
++		if (ret_lock)
++			usb_unlock_device(udev);
++	}
++	usb_put_dev(udev);
++
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(pending_req->usbif);
++	free_req(pending_req);
++	kfree(req);
++}
++
++static int usbbk_port_reset(pending_req_t *pending_req)
++{
++	struct port_reset_request *req;
++	struct usb_device *udev = pending_req->stub->udev;
++
++	req = kmalloc(sizeof(*req), GFP_KERNEL);
++	if (!req)
++		return -ENOMEM;
++
++	req->pending_req = pending_req;
++	INIT_WORK(&req->work, usbbk_port_reset_work, req);
++
++	usb_get_dev(udev);
++	schedule_work(&req->work);
++	return 0;
++}
++#endif
++
++static void usbbk_set_address(usbif_t *usbif, struct usbstub *stub, int cur_addr, int new_addr)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&usbif->addr_lock, flags);
++	if (cur_addr)
++		usbif->addr_table[cur_addr] = NULL;
++	if (new_addr)
++		usbif->addr_table[new_addr] = stub;
++	stub->addr = new_addr;
++	spin_unlock_irqrestore(&usbif->addr_lock, flags);
++}
++
++struct usbstub *find_attached_device(usbif_t *usbif, int portnum)
++{
++	struct usbstub *stub;
++	int found = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&usbif->stub_lock, flags);
++	list_for_each_entry(stub, &usbif->stub_list, dev_list) {
++		if (stub->portid->portnum == portnum) {
++			found = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&usbif->stub_lock, flags);
++
++	if (found)
++		return stub;
++
++	return NULL;
++}
++
++static void process_unlink_req(usbif_t *usbif,
++		usbif_urb_request_t *req, pending_req_t *pending_req)
++{
++	pending_req_t *unlink_req = NULL;
++	int devnum;
++	int ret = 0;
++	unsigned long flags;
++
++	devnum = usb_pipedevice(req->pipe);
++	if (unlikely(devnum == 0)) {
++		pending_req->stub = find_attached_device(usbif, usbif_pipeportnum(req->pipe));
++		if (unlikely(!pending_req->stub)) {
++			ret = -ENODEV;
++			goto fail_response;
++		}
++	} else {
++		if (unlikely(!usbif->addr_table[devnum])) {
++			ret = -ENODEV;
++			goto fail_response;
++		}
++		pending_req->stub = usbif->addr_table[devnum];
++	}
++
++	spin_lock_irqsave(&pending_req->stub->submitting_lock, flags);
++	list_for_each_entry(unlink_req, &pending_req->stub->submitting_list, urb_list) {
++		if (unlink_req->id == req->u.unlink.unlink_id) {
++			ret = usb_unlink_urb(unlink_req->urb);
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&pending_req->stub->submitting_lock, flags);
++
++fail_response:
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(usbif);
++	free_req(pending_req);
++	return;
++}
++
++static int check_and_submit_special_ctrlreq(usbif_t *usbif,
++		usbif_urb_request_t *req, pending_req_t *pending_req)
++{
++	int devnum;
++	struct usbstub *stub = NULL;
++	struct usb_ctrlrequest *ctrl = (struct usb_ctrlrequest *) req->u.ctrl;
++	int ret;
++	int done = 0;
++
++	devnum = usb_pipedevice(req->pipe);
++
++	/*
++	 * When the device is first connected or reseted, USB device has no address.
++	 * In this initial state, following requests are send to device address (#0),
++	 *
++	 *  1. GET_DESCRIPTOR (with Descriptor Type is "DEVICE") is send,
++	 *     and OS knows what device is connected to.
++	 *
++	 *  2. SET_ADDRESS is send, and then, device has its address.
++	 *
++	 * In the next step, SET_CONFIGURATION is send to addressed device, and then,
++	 * the device is finally ready to use.
++	 */
++	if (unlikely(devnum == 0)) {
++		stub = find_attached_device(usbif, usbif_pipeportnum(req->pipe));
++		if (unlikely(!stub)) {
++			ret = -ENODEV;
++			goto fail_response;
++		}
++
++		switch (ctrl->bRequest) {
++		case USB_REQ_GET_DESCRIPTOR:
++			/*
++			 * GET_DESCRIPTOR request to device #0.
++			 * through to normal urb transfer.
++			 */
++			pending_req->stub = stub;
++			return 0;
++			break;
++		case USB_REQ_SET_ADDRESS:
++			/*
++			 * SET_ADDRESS request to device #0.
++			 * add attached device to addr_table.
++			 */
++			{
++				__u16 addr = le16_to_cpu(ctrl->wValue);
++				usbbk_set_address(usbif, stub, 0, addr);
++			}
++			ret = 0;
++			goto fail_response;
++			break;
++		default:
++			ret = -EINVAL;
++			goto fail_response;
++		}
++	} else {
++		if (unlikely(!usbif->addr_table[devnum])) {
++			ret = -ENODEV;
++			goto fail_response;
++		}
++		pending_req->stub = usbif->addr_table[devnum];
++	}
++
++	/*
++	 * Check special request
++	 */
++	switch (ctrl->bRequest) {
++	case USB_REQ_SET_ADDRESS:
++		/*
++		 * SET_ADDRESS request to addressed device.
++		 * change addr or remove from addr_table.
++		 */
++		{
++			__u16 addr = le16_to_cpu(ctrl->wValue);
++			usbbk_set_address(usbif, stub, devnum, addr);
++		}
++		ret = 0;
++		goto fail_response;
++		break;
++#if 0
++	case USB_REQ_SET_CONFIGURATION:
++		/*
++		 * linux 2.6.27 or later version only!
++		 */
++		if (ctrl->RequestType == USB_RECIP_DEVICE) {
++			__u16 config = le16_to_cpu(ctrl->wValue);
++			usb_driver_set_configuration(pending_req->stub->udev, config);
++			done = 1;
++		}
++		break;
++#endif
++	case USB_REQ_SET_INTERFACE:
++		if (ctrl->bRequestType == USB_RECIP_INTERFACE) {
++			__u16 alt = le16_to_cpu(ctrl->wValue);
++			__u16 intf = le16_to_cpu(ctrl->wIndex);
++			usbbk_set_interface(pending_req, intf, alt);
++			done = 1;
++		}
++		break;
++	case USB_REQ_CLEAR_FEATURE:
++		if (ctrl->bRequestType == USB_RECIP_ENDPOINT
++			&& ctrl->wValue == USB_ENDPOINT_HALT) {
++			int pipe;
++			int ep = le16_to_cpu(ctrl->wIndex) & 0x0f;
++			int dir = le16_to_cpu(ctrl->wIndex)
++					& USB_DIR_IN;
++			if (dir)
++				pipe = usb_rcvctrlpipe(pending_req->stub->udev, ep);
++			else
++				pipe = usb_sndctrlpipe(pending_req->stub->udev, ep);
++			usbbk_clear_halt(pending_req, pipe);
++			done = 1;
++		}
++		break;
++#if 0 /* not tested yet */
++	case USB_REQ_SET_FEATURE:
++		if (ctrl->bRequestType == USB_RT_PORT) {
++			__u16 feat = le16_to_cpu(ctrl->wValue);
++			if (feat == USB_PORT_FEAT_RESET) {
++				usbbk_port_reset(pending_req);
++				done = 1;
++			}
++		}
++		break;
++#endif
++	default:
++		break;
++	}
++
++	return done;
++
++fail_response:
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(usbif);
++	free_req(pending_req);
++	return 1;
++}
++
++static void dispatch_request_to_pending_reqs(usbif_t *usbif,
++		usbif_urb_request_t *req,
++		pending_req_t *pending_req)
++{
++	int ret;
++
++	pending_req->id = req->id;
++	pending_req->usbif = usbif;
++
++	barrier();
++
++	usbif_get(usbif);
++
++	/* unlink request */
++	if (unlikely(usbif_pipeunlink(req->pipe))) {
++		process_unlink_req(usbif, req, pending_req);
++		return;
++	}
++
++	if (usb_pipecontrol(req->pipe)) {
++		if (check_and_submit_special_ctrlreq(usbif, req, pending_req))
++			return;
++	} else {
++		int devnum = usb_pipedevice(req->pipe);
++		if (unlikely(!usbif->addr_table[devnum])) {
++			ret = -ENODEV;
++			goto fail_response;
++		}
++		pending_req->stub = usbif->addr_table[devnum];
++	}
++
++	barrier();
++
++	ret = usbbk_alloc_urb(req, pending_req);
++	if (ret) {
++		ret = -ESHUTDOWN;
++		goto fail_response;
++	}
++
++	add_req_to_submitting_list(pending_req->stub, pending_req);
++
++	barrier();
++
++	usbbk_init_urb(req, pending_req);
++
++	barrier();
++
++	pending_req->nr_buffer_segs = req->nr_buffer_segs;
++	if (usb_pipeisoc(req->pipe))
++		pending_req->nr_extra_segs = req->u.isoc.nr_frame_desc_segs;
++	else
++		pending_req->nr_extra_segs = 0;
++
++	barrier();
++
++	ret = usbbk_gnttab_map(usbif, req, pending_req);
++	if (ret) {
++		printk(KERN_ERR "usbback: invalid buffer\n");
++		ret = -ESHUTDOWN;
++		goto fail_free_urb;
++	}
++
++	barrier();
++
++	if (usb_pipeout(req->pipe) && req->buffer_length)
++		copy_pages_to_buff(pending_req->buffer,
++					pending_req,
++					0,
++					pending_req->nr_buffer_segs);
++	if (usb_pipeisoc(req->pipe)) {
++		copy_pages_to_buff(&pending_req->urb->iso_frame_desc[0],
++			pending_req,
++			pending_req->nr_buffer_segs,
++			pending_req->nr_extra_segs);
++	}
++
++	barrier();
++
++	ret = usb_submit_urb(pending_req->urb, GFP_KERNEL);
++	if (ret) {
++		printk(KERN_ERR "usbback: failed submitting urb, error %d\n", ret);
++		ret = -ESHUTDOWN;
++		goto fail_flush_area;
++	}
++	return;
++
++fail_flush_area:
++	fast_flush_area(pending_req);
++fail_free_urb:
++	remove_req_from_submitting_list(pending_req->stub, pending_req);
++	barrier();
++	usbbk_free_urb(pending_req->urb);
++fail_response:
++	usbbk_do_response(pending_req, ret, 0, 0, 0);
++	usbif_put(usbif);
++	free_req(pending_req);
++}
++
++static int usbbk_start_submit_urb(usbif_t *usbif)
++{
++	usbif_urb_back_ring_t *urb_ring = &usbif->urb_ring;
++	usbif_urb_request_t *req;
++	pending_req_t *pending_req;
++	RING_IDX rc, rp;
++	int more_to_do = 0;
++
++	rc = urb_ring->req_cons;
++	rp = urb_ring->sring->req_prod;
++	rmb();
++
++	while (rc != rp) {
++		if (RING_REQUEST_CONS_OVERFLOW(urb_ring, rc)) {
++			printk(KERN_WARNING "RING_REQUEST_CONS_OVERFLOW\n");
++			break;
++		}
++
++		pending_req = alloc_req();
++		if (NULL == pending_req) {
++			more_to_do = 1;
++			break;
++		}
++
++		req = RING_GET_REQUEST(urb_ring, rc);
++		urb_ring->req_cons = ++rc;
++
++		dispatch_request_to_pending_reqs(usbif, req,
++							pending_req);
++	}
++
++	RING_FINAL_CHECK_FOR_REQUESTS(&usbif->urb_ring, more_to_do);
++
++	cond_resched();
++
++	return more_to_do;
++}
++
++void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed)
++{
++	usbif_conn_back_ring_t *ring = &usbif->conn_ring;
++	usbif_conn_request_t *req;
++	usbif_conn_response_t *res;
++	unsigned long flags;
++	u16 id;
++	int notify;
++
++	spin_lock_irqsave(&usbif->conn_ring_lock, flags);
++
++	req = RING_GET_REQUEST(ring, ring->req_cons);;
++	id = req->id;
++	ring->req_cons++;
++	ring->sring->req_event = ring->req_cons + 1;
++
++	res = RING_GET_RESPONSE(ring, ring->rsp_prod_pvt);
++	res->id = id;
++	res->portnum = portnum;
++	res->speed = speed;
++	ring->rsp_prod_pvt++;
++	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(ring, notify);
++
++	spin_unlock_irqrestore(&usbif->conn_ring_lock, flags);
++
++	if (notify)
++		notify_remote_via_irq(usbif->irq);
++}
++
++int usbbk_schedule(void *arg)
++{
++	usbif_t *usbif = (usbif_t *) arg;
++
++	usbif_get(usbif);
++
++	while (!kthread_should_stop()) {
++		wait_event_interruptible(
++			usbif->wq,
++			usbif->waiting_reqs || kthread_should_stop());
++		wait_event_interruptible(
++			pending_free_wq,
++			!list_empty(&pending_free) || kthread_should_stop());
++		usbif->waiting_reqs = 0;
++		smp_mb();
++
++		if (usbbk_start_submit_urb(usbif))
++			usbif->waiting_reqs = 1;
++	}
++
++	usbif->xenusbd = NULL;
++	usbif_put(usbif);
++
++	return 0;
++}
++
++/*
++ * attach usbstub device to usbif.
++ */
++void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&usbif->stub_lock, flags);
++	list_add(&stub->dev_list, &usbif->stub_list);
++	spin_unlock_irqrestore(&usbif->stub_lock, flags);
++	stub->usbif = usbif;
++}
++
++/*
++ * detach usbstub device from usbif.
++ */
++void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub)
++{
++	unsigned long flags;
++
++	if (stub->addr)
++		usbbk_set_address(usbif, stub, stub->addr, 0);
++	spin_lock_irqsave(&usbif->stub_lock, flags);
++	list_del(&stub->dev_list);
++	spin_unlock_irqrestore(&usbif->stub_lock, flags);
++	stub->usbif = NULL;
++}
++
++void detach_device_without_lock(usbif_t *usbif, struct usbstub *stub)
++{
++	if (stub->addr)
++		usbbk_set_address(usbif, stub, stub->addr, 0);
++	list_del(&stub->dev_list);
++	stub->usbif = NULL;
++}
++
++static int __init usbback_init(void)
++{
++	int i, mmap_pages;
++	int err = 0;
++
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	mmap_pages = usbif_reqs * USBIF_MAX_SEGMENTS_PER_REQUEST;
++	pending_reqs = kmalloc(sizeof(pending_reqs[0]) *
++			usbif_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) {
++		err = -ENOMEM;
++		goto out_mem;
++	}
++
++	for (i = 0; i < mmap_pages; i++)
++		pending_grant_handles[i] = USBBACK_INVALID_HANDLE;
++
++	memset(pending_reqs, 0, sizeof(pending_reqs));
++	INIT_LIST_HEAD(&pending_free);
++
++	for (i = 0; i < usbif_reqs; i++)
++		list_add_tail(&pending_reqs[i].free_list, &pending_free);
++
++	err = usbstub_init();
++	if (err)
++		goto out_mem;
++
++	err = usbback_xenbus_init();
++	if (err)
++		goto out_xenbus;
++
++	return 0;
++
++out_xenbus:
++	usbstub_exit();
++out_mem:
++	kfree(pending_reqs);
++	kfree(pending_grant_handles);
++	free_empty_pages_and_pagevec(pending_pages, mmap_pages);
++	return err;
++}
++
++static void __exit usbback_exit(void)
++{
++	usbback_xenbus_exit();
++	usbstub_exit();
++	kfree(pending_reqs);
++	kfree(pending_grant_handles);
++	free_empty_pages_and_pagevec(pending_pages, usbif_reqs * USBIF_MAX_SEGMENTS_PER_REQUEST);
++}
++
++module_init(usbback_init);
++module_exit(usbback_exit);
++
++MODULE_AUTHOR("");
++MODULE_DESCRIPTION("Xen USB backend driver (usbback)");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/usbback.h	2009-11-06 10:23:23.000000000 +0100
+@@ -0,0 +1,173 @@
++/*
++ * usbback.h
++ *
++ * This file is part of Xen USB backend driver.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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_USBBACK_H__
++#define __XEN_USBBACK_H__
++
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++#include <linux/usb.h>
++#include <linux/vmalloc.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
++#include <linux/list.h>
++#include <linux/kref.h>
++#include <xen/evtchn.h>
++#include <xen/gnttab.h>
++#include <xen/driver_util.h>
++#include <xen/interface/xen.h>
++#include <xen/xenbus.h>
++#include <xen/interface/io/usbif.h>
++
++struct usbstub;
++
++#define USB_DEV_ADDR_SIZE 128
++
++typedef struct usbif_st {
++	domid_t domid;
++	unsigned int handle;
++	int num_ports;
++	enum usb_spec_version usb_ver;
++
++	struct xenbus_device *xbdev;
++	struct list_head usbif_list;
++
++	unsigned int      irq;
++
++	usbif_urb_back_ring_t urb_ring;
++	usbif_conn_back_ring_t conn_ring;
++	struct vm_struct *urb_ring_area;
++	struct vm_struct *conn_ring_area;
++
++	spinlock_t urb_ring_lock;
++	spinlock_t conn_ring_lock;
++	atomic_t refcnt;
++
++	grant_handle_t urb_shmem_handle;
++	grant_ref_t urb_shmem_ref;
++	grant_handle_t conn_shmem_handle;
++	grant_ref_t conn_shmem_ref;
++
++	struct xenbus_watch backend_watch;
++
++	/* device address lookup table */
++	struct usbstub *addr_table[USB_DEV_ADDR_SIZE];
++	spinlock_t addr_lock;
++
++	/* connected device list */
++	struct list_head stub_list;
++	spinlock_t stub_lock;
++
++	/* request schedule */
++	struct task_struct *xenusbd;
++	unsigned int waiting_reqs;
++	wait_queue_head_t waiting_to_free;
++	wait_queue_head_t wq;
++} usbif_t;
++
++struct vusb_port_id {
++	struct list_head id_list;
++
++	char phys_bus[BUS_ID_SIZE];
++	domid_t domid;
++	unsigned int handle;
++	int portnum;
++	unsigned is_connected:1;
++};
++
++struct usbstub {
++	struct kref kref;
++	struct list_head dev_list;
++
++	struct vusb_port_id *portid;
++	struct usb_device *udev;
++	usbif_t *usbif;
++	int addr;
++
++	struct list_head submitting_list;
++	spinlock_t submitting_lock;
++};
++
++usbif_t *usbif_alloc(domid_t domid, unsigned int handle);
++void usbif_disconnect(usbif_t *usbif);
++void usbif_free(usbif_t *usbif);
++int usbif_map(usbif_t *usbif, unsigned long urb_ring_ref,
++		unsigned long conn_ring_ref, unsigned int evtchn);
++
++#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
++#define usbif_put(_b) \
++	do { \
++		if (atomic_dec_and_test(&(_b)->refcnt)) \
++			wake_up(&(_b)->waiting_to_free); \
++	} while (0)
++
++usbif_t *find_usbif(domid_t domid, unsigned int handle);
++int usbback_xenbus_init(void);
++void usbback_xenbus_exit(void);
++struct vusb_port_id *find_portid_by_busid(const char *busid);
++struct vusb_port_id *find_portid(const domid_t domid,
++						const unsigned int handle,
++						const int portnum);
++int portid_add(const char *busid,
++					const domid_t domid,
++					const unsigned int handle,
++					const int portnum);
++int portid_remove(const domid_t domid,
++					const unsigned int handle,
++					const int portnum);
++irqreturn_t usbbk_be_int(int irq, void *dev_id, struct pt_regs *regs);
++int usbbk_schedule(void *arg);
++struct usbstub *find_attached_device(usbif_t *usbif, int port);
++void usbbk_attach_device(usbif_t *usbif, struct usbstub *stub);
++void usbbk_detach_device(usbif_t *usbif, struct usbstub *stub);
++void usbbk_hotplug_notify(usbif_t *usbif, int portnum, int speed);
++void detach_device_without_lock(usbif_t *usbif, struct usbstub *stub);
++void usbbk_unlink_urbs(struct usbstub *stub);
++
++int usbstub_init(void);
++void usbstub_exit(void);
++
++#endif /* __XEN_USBBACK_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/usbstub.c	2009-11-06 10:23:23.000000000 +0100
+@@ -0,0 +1,325 @@
++/*
++ * usbstub.c
++ *
++ * USB stub driver - grabbing and managing USB devices.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include "usbback.h"
++
++static LIST_HEAD(port_list);
++static DEFINE_SPINLOCK(port_list_lock);
++
++struct vusb_port_id *find_portid_by_busid(const char *busid)
++{
++	struct vusb_port_id *portid;
++	int found = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&port_list_lock, flags);
++	list_for_each_entry(portid, &port_list, id_list) {
++		if (!(strncmp(portid->phys_bus, busid, BUS_ID_SIZE))) {
++			found = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&port_list_lock, flags);
++
++	if (found)
++		return portid;
++
++	return NULL;
++}
++
++struct vusb_port_id *find_portid(const domid_t domid,
++						const unsigned int handle,
++						const int portnum)
++{
++	struct vusb_port_id *portid;
++	int found = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&port_list_lock, flags);
++	list_for_each_entry(portid, &port_list, id_list) {
++		if ((portid->domid == domid)
++				&& (portid->handle == handle)
++				&& (portid->portnum == portnum)) {
++				found = 1;
++				break;
++		}
++	}
++	spin_unlock_irqrestore(&port_list_lock, flags);
++
++	if (found)
++		return portid;
++
++	return NULL;
++}
++
++int portid_add(const char *busid,
++					const domid_t domid,
++					const unsigned int handle,
++					const int portnum)
++{
++	struct vusb_port_id *portid;
++	unsigned long flags;
++
++	portid = kzalloc(sizeof(*portid), GFP_KERNEL);
++	if (!portid)
++		return -ENOMEM;
++
++	portid->domid = domid;
++	portid->handle = handle;
++	portid->portnum = portnum;
++
++	strncpy(portid->phys_bus, busid, BUS_ID_SIZE);
++
++	spin_lock_irqsave(&port_list_lock, flags);
++	list_add(&portid->id_list, &port_list);
++	spin_unlock_irqrestore(&port_list_lock, flags);
++
++	return 0;
++}
++
++int portid_remove(const domid_t domid,
++					const unsigned int handle,
++					const int portnum)
++{
++	struct vusb_port_id *portid, *tmp;
++	int err = -ENOENT;
++	unsigned long flags;
++
++	spin_lock_irqsave(&port_list_lock, flags);
++	list_for_each_entry_safe(portid, tmp, &port_list, id_list) {
++		if (portid->domid == domid
++				&& portid->handle == handle
++				&& portid->portnum == portnum) {
++			list_del(&portid->id_list);
++			kfree(portid);
++
++			err = 0;
++		}
++	}
++	spin_unlock_irqrestore(&port_list_lock, flags);
++
++	return err;
++}
++
++static struct usbstub *usbstub_alloc(struct usb_device *udev,
++						struct vusb_port_id *portid)
++{
++	struct usbstub *stub;
++
++	stub = kzalloc(sizeof(*stub), GFP_KERNEL);
++	if (!stub) {
++		printk(KERN_ERR "no memory for alloc usbstub\n");
++		return NULL;
++	}
++	kref_init(&stub->kref);
++	stub->udev = usb_get_dev(udev);
++	stub->portid = portid;
++	spin_lock_init(&stub->submitting_lock);
++	INIT_LIST_HEAD(&stub->submitting_list);
++
++	return stub;
++}
++
++static void usbstub_release(struct kref *kref)
++{
++	struct usbstub *stub;
++
++	stub = container_of(kref, struct usbstub, kref);
++
++	usb_put_dev(stub->udev);
++	stub->udev = NULL;
++	stub->portid = NULL;
++	kfree(stub);
++}
++
++static inline void usbstub_get(struct usbstub *stub)
++{
++	kref_get(&stub->kref);
++}
++
++static inline void usbstub_put(struct usbstub *stub)
++{
++	kref_put(&stub->kref, usbstub_release);
++}
++
++static int usbstub_probe(struct usb_interface *intf,
++		const struct usb_device_id *id)
++{
++	struct usb_device *udev = interface_to_usbdev(intf);
++	char *busid = intf->dev.parent->bus_id;
++	struct vusb_port_id *portid = NULL;
++	struct usbstub *stub = NULL;
++	usbif_t *usbif = NULL;
++	int retval = -ENODEV;
++
++	/* hub currently not supported, so skip. */
++	if (udev->descriptor.bDeviceClass ==  USB_CLASS_HUB)
++		goto out;
++
++	portid = find_portid_by_busid(busid);
++	if (!portid)
++		goto out;
++
++	usbif = find_usbif(portid->domid, portid->handle);
++	if (!usbif)
++		goto out;
++
++	switch (udev->speed) {
++	case USB_SPEED_LOW:
++	case USB_SPEED_FULL:
++		break;
++	case USB_SPEED_HIGH:
++		if (usbif->usb_ver >= USB_VER_USB20)
++			break;
++		/* fall through */
++	default:
++		goto out;
++	}
++
++	stub = find_attached_device(usbif, portid->portnum);
++	if (!stub) {
++		/* new connection */
++		stub = usbstub_alloc(udev, portid);
++		if (!stub)
++			return -ENOMEM;
++		usbbk_attach_device(usbif, stub);
++		usbbk_hotplug_notify(usbif, portid->portnum, udev->speed);
++	} else {
++		/* maybe already called and connected by other intf */
++		if (strncmp(stub->portid->phys_bus, busid, BUS_ID_SIZE))
++			goto out; /* invalid call */
++	}
++
++	usbstub_get(stub);
++	usb_set_intfdata(intf, stub);
++	retval = 0;
++
++out:
++	return retval;
++}
++
++static void usbstub_disconnect(struct usb_interface *intf)
++{
++	struct usbstub *stub
++		= (struct usbstub *) usb_get_intfdata(intf);
++
++	usb_set_intfdata(intf, NULL);
++
++	if (!stub)
++		return;
++
++	if (stub->usbif) {
++		usbbk_hotplug_notify(stub->usbif, stub->portid->portnum, 0);
++		usbbk_detach_device(stub->usbif, stub);
++	}
++	usbbk_unlink_urbs(stub);
++	usbstub_put(stub);
++}
++
++static ssize_t usbstub_show_portids(struct device_driver *driver,
++		char *buf)
++{
++	struct vusb_port_id *portid;
++	size_t count = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&port_list_lock, flags);
++	list_for_each_entry(portid, &port_list, id_list) {
++		if (count >= PAGE_SIZE)
++			break;
++		count += scnprintf((char *)buf + count, PAGE_SIZE - count,
++				"%s:%d:%d:%d\n",
++				&portid->phys_bus[0],
++				portid->domid,
++				portid->handle,
++				portid->portnum);
++	}
++	spin_unlock_irqrestore(&port_list_lock, flags);
++
++	return count;
++}
++
++DRIVER_ATTR(port_ids, S_IRUSR, usbstub_show_portids, NULL);
++
++/* table of devices that matches any usbdevice */
++static struct usb_device_id usbstub_table[] = {
++		{ .driver_info = 1 }, /* wildcard, see usb_match_id() */
++		{ } /* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, usbstub_table);
++
++static struct usb_driver usbback_usb_driver = {
++		.name = "usbback",
++		.probe = usbstub_probe,
++		.disconnect = usbstub_disconnect,
++		.id_table = usbstub_table,
++		.no_dynamic_id = 1,
++};
++
++int __init usbstub_init(void)
++{
++	int err;
++
++	err = usb_register(&usbback_usb_driver);
++	if (err < 0) {
++		printk(KERN_ERR "usbback: usb_register failed (error %d)\n", err);
++		goto out;
++	}
++
++	err = driver_create_file(&usbback_usb_driver.driver,
++				&driver_attr_port_ids);
++	if (err)
++		usb_deregister(&usbback_usb_driver);
++
++out:
++	return err;
++}
++
++void usbstub_exit(void)
++{
++	driver_remove_file(&usbback_usb_driver.driver,
++				&driver_attr_port_ids);
++	usb_deregister(&usbback_usb_driver);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbback/xenbus.c	2009-11-06 10:23:23.000000000 +0100
+@@ -0,0 +1,338 @@
++/*
++ * xenbus.c
++ *
++ * Xenbus interface for USB backend driver.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include "usbback.h"
++
++static int start_xenusbd(usbif_t *usbif)
++{
++	int err = 0;
++	char name[TASK_COMM_LEN];
++
++	snprintf(name, TASK_COMM_LEN, "usbback.%d.%d", usbif->domid,
++			usbif->handle);
++	usbif->xenusbd = kthread_run(usbbk_schedule, usbif, name);
++	if (IS_ERR(usbif->xenusbd)) {
++		err = PTR_ERR(usbif->xenusbd);
++		usbif->xenusbd = NULL;
++		xenbus_dev_error(usbif->xbdev, err, "start xenusbd");
++	}
++
++	return err;
++}
++
++static void backend_changed(struct xenbus_watch *watch,
++			const char **vec, unsigned int len)
++{
++	struct xenbus_transaction xbt;
++	int err;
++	int i;
++	char node[8];
++	char *busid;
++	struct vusb_port_id *portid = NULL;
++
++	usbif_t *usbif = container_of(watch, usbif_t, backend_watch);
++	struct xenbus_device *dev = usbif->xbdev;
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		return;
++	}
++
++	for (i = 1; i <= usbif->num_ports; i++) {
++		sprintf(node, "port/%d", i);
++		busid = xenbus_read(xbt, dev->nodename, node, NULL);
++		if (IS_ERR(busid)) {
++			err = PTR_ERR(busid);
++			xenbus_dev_fatal(dev, err, "reading port/%d", i);
++			goto abort;
++		}
++
++		/*
++		 * remove portid, if the port is not connected,
++		 */
++		if (strlen(busid) == 0) {
++			portid = find_portid(usbif->domid, usbif->handle, i);
++			if (portid) {
++				if (portid->is_connected)
++					xenbus_dev_fatal(dev, err,
++						"can't remove port/%d, unbind first", i);
++				else
++					portid_remove(usbif->domid, usbif->handle, i);
++			}
++			continue; /* never configured, ignore */
++		}
++
++		/*
++		 * add portid,
++		 * if the port is not configured and not used from other usbif.
++		 */
++		portid = find_portid(usbif->domid, usbif->handle, i);
++		if (portid) {
++			if ((strncmp(portid->phys_bus, busid, BUS_ID_SIZE)))
++				xenbus_dev_fatal(dev, err,
++					"can't add port/%d, remove first", i);
++			else
++				continue; /* already configured, ignore */
++		} else {
++			if (find_portid_by_busid(busid))
++				xenbus_dev_fatal(dev, err,
++					"can't add port/%d, busid already used", i);
++			else
++				portid_add(busid, usbif->domid, usbif->handle, i);
++		}
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++	if (err)
++		xenbus_dev_fatal(dev, err, "completing transaction");
++
++	return;
++
++abort:
++	xenbus_transaction_end(xbt, 1);
++
++	return;
++}
++
++static int usbback_remove(struct xenbus_device *dev)
++{
++	usbif_t *usbif = dev->dev.driver_data;
++	int i;
++
++	if (usbif->backend_watch.node) {
++		unregister_xenbus_watch(&usbif->backend_watch);
++		kfree(usbif->backend_watch.node);
++		usbif->backend_watch.node = NULL;
++	}
++
++	if (usbif) {
++		/* remove all ports */
++		for (i = 1; i <= usbif->num_ports; i++)
++			portid_remove(usbif->domid, usbif->handle, i);
++		usbif_disconnect(usbif);
++		usbif_free(usbif);;
++	}
++	dev->dev.driver_data = NULL;
++
++	return 0;
++}
++
++static int usbback_probe(struct xenbus_device *dev,
++			  const struct xenbus_device_id *id)
++{
++	usbif_t *usbif;
++	unsigned int handle;
++	int num_ports;
++	int usb_ver;
++	int err;
++
++	if (usb_disabled())
++		return -ENODEV;
++
++	handle = simple_strtoul(strrchr(dev->otherend, '/') + 1, NULL, 0);
++	usbif = usbif_alloc(dev->otherend_id, handle);
++	if (!usbif) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating backend interface");
++		return -ENOMEM;
++	}
++	usbif->xbdev = dev;
++	dev->dev.driver_data = usbif;
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++				"num-ports", "%d", &num_ports);
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading num-ports");
++		goto fail;
++	}
++	if (num_ports < 1 || num_ports > USB_MAXCHILDREN) {
++		xenbus_dev_fatal(dev, err, "invalid num-ports");
++		goto fail;
++	}
++	usbif->num_ports = num_ports;
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++				"usb-ver", "%d", &usb_ver);
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading usb-ver");
++		goto fail;
++	}
++	switch (usb_ver) {
++	case USB_VER_USB11:
++	case USB_VER_USB20:
++		usbif->usb_ver = usb_ver;
++		break;
++	default:
++		xenbus_dev_fatal(dev, err, "invalid usb-ver");
++		goto fail;
++	}
++
++	err = xenbus_switch_state(dev, XenbusStateInitWait);
++	if (err)
++		goto fail;
++
++	return 0;
++
++fail:
++	usbback_remove(dev);
++	return err;
++}
++
++static int connect_rings(usbif_t *usbif)
++{
++	struct xenbus_device *dev = usbif->xbdev;
++	unsigned long urb_ring_ref;
++	unsigned long conn_ring_ref;
++	unsigned int evtchn;
++	int err;
++
++	err = xenbus_gather(XBT_NIL, dev->otherend,
++			    "urb-ring-ref", "%lu", &urb_ring_ref,
++			    "conn-ring-ref", "%lu", &conn_ring_ref,
++			    "event-channel", "%u", &evtchn, NULL);
++	if (err) {
++		xenbus_dev_fatal(dev, err,
++				 "reading %s/ring-ref and event-channel",
++				 dev->otherend);
++		return err;
++	}
++
++	printk("usbback: urb-ring-ref %ld, conn-ring-ref %ld, event-channel %d\n",
++	       urb_ring_ref, conn_ring_ref, evtchn);
++
++	err = usbif_map(usbif, urb_ring_ref, conn_ring_ref, evtchn);
++	if (err) {
++		xenbus_dev_fatal(dev, err,
++				"mapping urb-ring-ref %lu conn-ring-ref %lu port %u",
++				urb_ring_ref, conn_ring_ref, evtchn);
++		return err;
++	}
++
++	return 0;
++}
++
++static void frontend_changed(struct xenbus_device *dev,
++				     enum xenbus_state frontend_state)
++{
++	usbif_t *usbif = dev->dev.driver_data;
++	int err;
++
++	switch (frontend_state) {
++	case XenbusStateInitialised:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++		break;
++
++	case XenbusStateInitialising:
++		if (dev->state == XenbusStateClosed) {
++			printk("%s: %s: prepare for reconnect\n",
++			       __FUNCTION__, dev->nodename);
++			xenbus_switch_state(dev, XenbusStateInitWait);
++		}
++		break;
++
++	case XenbusStateConnected:
++		if (dev->state == XenbusStateConnected)
++			break;
++		err = connect_rings(usbif);
++		if (err)
++			break;
++		err = start_xenusbd(usbif);
++		if (err)
++			break;
++		err = xenbus_watch_path2(dev, dev->nodename, "port",
++					&usbif->backend_watch, backend_changed);
++		if (err)
++			break;
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateClosing:
++		usbif_disconnect(usbif);
++		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;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++				 frontend_state);
++		break;
++	}
++}
++
++static const struct xenbus_device_id usbback_ids[] = {
++	{ "vusb" },
++	{ "" },
++};
++
++static struct xenbus_driver usbback_driver = {
++	.name = "vusb",
++	.owner = THIS_MODULE,
++	.ids = usbback_ids,
++	.probe = usbback_probe,
++	.otherend_changed = frontend_changed,
++	.remove = usbback_remove,
++};
++
++int __init usbback_xenbus_init(void)
++{
++	return xenbus_register_backend(&usbback_driver);
++}
++
++void __exit usbback_xenbus_exit(void)
++{
++	xenbus_unregister_driver(&usbback_driver);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/Makefile	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,11 @@
++obj-$(CONFIG_XEN_USB_FRONTEND) := xen-hcd.o
++
++xen-hcd-y   := usbfront-hcd.o xenbus.o
++
++ifeq ($(CONFIG_XEN_USB_FRONTEND_HCD_STATS),y)
++EXTRA_CFLAGS += -DXENHCD_STATS
++endif
++
++ifeq ($(CONFIG_XEN_USB_FRONTEND_HCD_PM),y)
++EXTRA_CFLAGS += -DXENHCD_PM
++endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-dbg.c	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,100 @@
++/*
++ * usbfront-dbg.c
++ *
++ * Xen USB Virtual Host Controller - debugging
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++static ssize_t show_statistics(struct class_device *class_dev, char *buf)
++{
++	struct usb_bus *bus;
++	struct usb_hcd *hcd;
++	struct usbfront_info *info;
++	unsigned long flags;
++	unsigned temp, size;
++	char *next;
++
++	bus = class_get_devdata(class_dev);
++	hcd = bus->hcpriv;
++	info = hcd_to_info(hcd);
++	next = buf;
++	size = PAGE_SIZE;
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	temp = scnprintf(next, size,
++			"bus %s, device %s\n"
++			"%s\n"
++			"xenhcd, hcd state %d\n",
++			hcd->self.controller->bus->name,
++			hcd->self.controller->bus_id,
++			hcd->product_desc,
++			hcd->state);
++	size -= temp;
++	next += temp;
++
++#ifdef XENHCD_STATS
++	temp = scnprintf(next, size,
++		"complete %ld unlink %ld ring_full %ld\n",
++		info->stats.complete, info->stats.unlink,
++		info->stats.ring_full);
++	size -= temp;
++	next += temp;
++#endif
++
++	spin_unlock_irqrestore(&info->lock, flags);
++
++	return PAGE_SIZE - size;
++}
++
++static CLASS_DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
++
++static inline void create_debug_file(struct usbfront_info *info)
++{
++	struct class_device *cldev = info_to_hcd(info)->self.class_dev;
++	class_device_create_file(cldev, &class_device_attr_statistics);
++}
++
++static inline void remove_debug_file(struct usbfront_info *info)
++{
++	struct class_device *cldev = info_to_hcd(info)->self.class_dev;
++	class_device_remove_file(cldev, &class_device_attr_statistics);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-hcd.c	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,231 @@
++/*
++ * usbfront-hcd.c
++ *
++ * Xen USB Virtual Host Controller driver
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include "usbfront.h"
++#include "usbfront-dbg.c"
++#include "usbfront-hub.c"
++#include "usbfront-q.c"
++
++static void xenhcd_watchdog(unsigned long param)
++{
++	struct usbfront_info *info = (struct usbfront_info *) param;
++	unsigned long flags;
++
++	spin_lock_irqsave(&info->lock, flags);
++	if (likely(HC_IS_RUNNING(info_to_hcd(info)->state))) {
++		timer_action_done(info, TIMER_RING_WATCHDOG);
++		xenhcd_giveback_unlinked_urbs(info);
++		xenhcd_kick_pending_urbs(info);
++	}
++	spin_unlock_irqrestore(&info->lock, flags);
++}
++
++/*
++ * one-time HC init
++ */
++static int xenhcd_setup(struct usb_hcd *hcd)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++
++	spin_lock_init(&info->lock);
++	INIT_LIST_HEAD(&info->pending_submit_list);
++	INIT_LIST_HEAD(&info->pending_unlink_list);
++	INIT_LIST_HEAD(&info->in_progress_list);
++	INIT_LIST_HEAD(&info->giveback_waiting_list);
++	init_timer(&info->watchdog);
++	info->watchdog.function = xenhcd_watchdog;
++	info->watchdog.data = (unsigned long) info;
++	return 0;
++}
++
++/*
++ * start HC running
++ */
++static int xenhcd_run(struct usb_hcd *hcd)
++{
++	hcd->uses_new_polling = 1;
++	hcd->poll_rh = 0;
++	hcd->state = HC_STATE_RUNNING;
++	create_debug_file(hcd_to_info(hcd));
++	return 0;
++}
++
++/*
++ * stop running HC
++ */
++static void xenhcd_stop(struct usb_hcd *hcd)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++
++	del_timer_sync(&info->watchdog);
++	remove_debug_file(info);
++	spin_lock_irq(&info->lock);
++	/* cancel all urbs */
++	hcd->state = HC_STATE_HALT;
++	xenhcd_cancel_all_enqueued_urbs(info);
++	xenhcd_giveback_unlinked_urbs(info);
++	spin_unlock_irq(&info->lock);
++}
++
++/*
++ * called as .urb_enqueue()
++ * non-error returns are promise to giveback the urb later
++ */
++static int xenhcd_urb_enqueue(struct usb_hcd *hcd,
++				    struct usb_host_endpoint *ep,
++				    struct urb *urb,
++				    gfp_t mem_flags)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++	struct urb_priv *urbp;
++	unsigned long flags;
++	int ret = 0;
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	urbp = alloc_urb_priv(urb);
++	if (!urbp) {
++		ret = -ENOMEM;
++		goto done;
++	}
++
++	ret = xenhcd_submit_urb(info, urbp);
++	if (ret != 0)
++		free_urb_priv(urbp);
++
++done:
++	spin_unlock_irqrestore(&info->lock, flags);
++	return ret;
++}
++
++/*
++ * called as .urb_dequeue()
++ */
++static int xenhcd_urb_dequeue(struct usb_hcd *hcd,
++				    struct urb *urb)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++	struct urb_priv *urbp;
++	unsigned long flags;
++	int ret = 0;
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	urbp = urb->hcpriv;
++	if (!urbp)
++		goto done;
++
++	ret = xenhcd_unlink_urb(info, urbp);
++
++done:
++	spin_unlock_irqrestore(&info->lock, flags);
++	return ret;
++}
++
++/*
++ * called from usb_get_current_frame_number(),
++ * but, almost all drivers not use such function.
++ */
++static int xenhcd_get_frame(struct usb_hcd *hcd)
++{
++	/* it means error, but probably no problem :-) */
++	return 0;
++}
++
++static const char hcd_name[] = "xen_hcd";
++
++struct hc_driver xen_usb20_hc_driver = {
++	.description = hcd_name,
++	.product_desc = "Xen USB2.0 Virtual Host Controller",
++	.hcd_priv_size = sizeof(struct usbfront_info),
++	.flags = HCD_USB2,
++
++	/* basic HC lifecycle operations */
++	.reset = xenhcd_setup,
++	.start = xenhcd_run,
++	.stop = xenhcd_stop,
++
++	/* managing urb I/O */
++	.urb_enqueue = xenhcd_urb_enqueue,
++	.urb_dequeue = xenhcd_urb_dequeue,
++	.get_frame_number = xenhcd_get_frame,
++
++	/* root hub operations */
++	.hub_status_data = xenhcd_hub_status_data,
++	.hub_control = xenhcd_hub_control,
++#ifdef XENHCD_PM
++#ifdef CONFIG_PM
++	.bus_suspend = xenhcd_bus_suspend,
++	.bus_resume = xenhcd_bus_resume,
++#endif
++#endif
++};
++
++struct hc_driver xen_usb11_hc_driver = {
++	.description = hcd_name,
++	.product_desc = "Xen USB1.1 Virtual Host Controller",
++	.hcd_priv_size = sizeof(struct usbfront_info),
++	.flags = HCD_USB11,
++
++	/* basic HC lifecycle operations */
++	.reset = xenhcd_setup,
++	.start = xenhcd_run,
++	.stop = xenhcd_stop,
++
++	/* managing urb I/O */
++	.urb_enqueue = xenhcd_urb_enqueue,
++	.urb_dequeue = xenhcd_urb_dequeue,
++	.get_frame_number = xenhcd_get_frame,
++
++	/* root hub operations */
++	.hub_status_data = xenhcd_hub_status_data,
++	.hub_control = xenhcd_hub_control,
++#ifdef XENHCD_PM
++#ifdef CONFIG_PM
++	.bus_suspend = xenhcd_bus_suspend,
++	.bus_resume = xenhcd_bus_resume,
++#endif
++#endif
++};
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-hub.c	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,471 @@
++/*
++ * usbfront-hub.c
++ *
++ * Xen USB Virtual Host Controller - Root Hub Emulations
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++/*
++ * set virtual port connection status
++ */
++void set_connect_state(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	if (info->ports[port].status & USB_PORT_STAT_POWER) {
++		switch (info->devices[port].speed) {
++		case USB_SPEED_UNKNOWN:
++			info->ports[port].status &=
++				~(USB_PORT_STAT_CONNECTION |
++					USB_PORT_STAT_ENABLE |
++					USB_PORT_STAT_LOW_SPEED |
++					USB_PORT_STAT_HIGH_SPEED |
++					USB_PORT_STAT_SUSPEND);
++			break;
++		case USB_SPEED_LOW:
++			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
++			info->ports[port].status |= USB_PORT_STAT_LOW_SPEED;
++			break;
++		case USB_SPEED_FULL:
++			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
++			break;
++		case USB_SPEED_HIGH:
++			info->ports[port].status |= USB_PORT_STAT_CONNECTION;
++			info->ports[port].status |= USB_PORT_STAT_HIGH_SPEED;
++			break;
++		default: /* error */
++			return;
++		}
++		info->ports[port].status |= (USB_PORT_STAT_C_CONNECTION << 16);
++	}
++}
++
++/*
++ * set virtual device connection status
++ */
++void rhport_connect(struct usbfront_info *info,
++				int portnum, enum usb_device_speed speed)
++{
++	int port;
++
++	if (portnum < 1 || portnum > info->rh_numports)
++		return; /* invalid port number */
++
++	port = portnum - 1;
++	if (info->devices[port].speed != speed) {
++		switch (speed) {
++		case USB_SPEED_UNKNOWN: /* disconnect */
++			info->devices[port].status = USB_STATE_NOTATTACHED;
++			break;
++		case USB_SPEED_LOW:
++		case USB_SPEED_FULL:
++		case USB_SPEED_HIGH:
++			info->devices[port].status = USB_STATE_ATTACHED;
++			break;
++		default: /* error */
++			return;
++		}
++		info->devices[port].speed = speed;
++		info->ports[port].c_connection = 1;
++
++		set_connect_state(info, portnum);
++	}
++}
++
++/*
++ * SetPortFeature(PORT_SUSPENDED)
++ */
++void rhport_suspend(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	info->ports[port].status |= USB_PORT_STAT_SUSPEND;
++	info->devices[port].status = USB_STATE_SUSPENDED;
++}
++
++/*
++ * ClearPortFeature(PORT_SUSPENDED)
++ */
++void rhport_resume(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	if (info->ports[port].status & USB_PORT_STAT_SUSPEND) {
++		info->ports[port].resuming = 1;
++		info->ports[port].timeout = jiffies + msecs_to_jiffies(20);
++	}
++}
++
++/*
++ * SetPortFeature(PORT_POWER)
++ */
++void rhport_power_on(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	if ((info->ports[port].status & USB_PORT_STAT_POWER) == 0) {
++		info->ports[port].status |= USB_PORT_STAT_POWER;
++		if (info->devices[port].status != USB_STATE_NOTATTACHED)
++			info->devices[port].status = USB_STATE_POWERED;
++		if (info->ports[port].c_connection)
++			set_connect_state(info, portnum);
++	}
++}
++
++/*
++ * ClearPortFeature(PORT_POWER)
++ * SetConfiguration(non-zero)
++ * Power_Source_Off
++ * Over-current
++ */
++void rhport_power_off(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	if (info->ports[port].status & USB_PORT_STAT_POWER) {
++		info->ports[port].status = 0;
++		if (info->devices[port].status != USB_STATE_NOTATTACHED)
++			info->devices[port].status = USB_STATE_ATTACHED;
++	}
++}
++
++/*
++ * ClearPortFeature(PORT_ENABLE)
++ */
++void rhport_disable(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	info->ports[port].status &= ~USB_PORT_STAT_ENABLE;
++	info->ports[port].status &= ~USB_PORT_STAT_SUSPEND;
++	info->ports[port].resuming = 0;
++	if (info->devices[port].status != USB_STATE_NOTATTACHED)
++		info->devices[port].status = USB_STATE_POWERED;
++}
++
++/*
++ * SetPortFeature(PORT_RESET)
++ */
++void rhport_reset(struct usbfront_info *info, int portnum)
++{
++	int port;
++
++	port = portnum - 1;
++	info->ports[port].status &= ~(USB_PORT_STAT_ENABLE
++					| USB_PORT_STAT_LOW_SPEED
++					| USB_PORT_STAT_HIGH_SPEED);
++	info->ports[port].status |= USB_PORT_STAT_RESET;
++
++	if (info->devices[port].status != USB_STATE_NOTATTACHED)
++		info->devices[port].status = USB_STATE_ATTACHED;
++
++	/* 10msec reset signaling */
++	info->ports[port].timeout = jiffies + msecs_to_jiffies(10);
++}
++
++#ifdef XENHCD_PM
++#ifdef CONFIG_PM
++static int xenhcd_bus_suspend(struct usb_hcd *hcd)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++	int ret = 0;
++	int i, ports;
++
++	ports = info->rh_numports;
++
++	spin_lock_irq(&info->lock);
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++		ret = -ESHUTDOWN;
++	else {
++		/* suspend any active ports*/
++		for (i = 1; i <= ports; i++)
++			rhport_suspend(info, i);
++	}
++	spin_unlock_irq(&info->lock);
++
++	del_timer_sync(&info->watchdog);
++
++	return ret;
++}
++
++static int xenhcd_bus_resume(struct usb_hcd *hcd)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++	int ret = 0;
++	int i, ports;
++
++	ports = info->rh_numports;
++
++	spin_lock_irq(&info->lock);
++	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
++		ret = -ESHUTDOWN;
++	else {
++		/* resume any suspended ports*/
++		for (i = 1; i <= ports; i++)
++			rhport_resume(info, i);
++	}
++	spin_unlock_irq(&info->lock);
++
++	return ret;
++}
++#endif
++#endif
++
++static void xenhcd_hub_descriptor(struct usbfront_info *info,
++				  struct usb_hub_descriptor *desc)
++{
++	u16 temp;
++	int ports = info->rh_numports;
++
++	desc->bDescriptorType = 0x29;
++	desc->bPwrOn2PwrGood = 10; /* EHCI says 20ms max */
++	desc->bHubContrCurrent = 0;
++	desc->bNbrPorts = ports;
++
++	/* size of DeviceRemovable and PortPwrCtrlMask fields*/
++	temp = 1 + (ports / 8);
++	desc->bDescLength = 7 + 2 * temp;
++
++	/* bitmaps for DeviceRemovable and PortPwrCtrlMask */
++	memset(&desc->bitmap[0], 0, temp);
++	memset(&desc->bitmap[temp], 0xff, temp);
++
++	/* per-port over current reporting and no power switching */
++	temp = 0x000a;
++	desc->wHubCharacteristics = cpu_to_le16(temp);
++}
++
++/* port status change mask for hub_status_data */
++#define PORT_C_MASK \
++	((USB_PORT_STAT_C_CONNECTION \
++	| USB_PORT_STAT_C_ENABLE \
++	| USB_PORT_STAT_C_SUSPEND \
++	| USB_PORT_STAT_C_OVERCURRENT \
++	| USB_PORT_STAT_C_RESET) << 16)
++
++/*
++ * See USB 2.0 Spec, 11.12.4 Hub and Port Status Change Bitmap.
++ * If port status changed, writes the bitmap to buf and return
++ * that length(number of bytes).
++ * If Nothing changed, return 0.
++ */
++static int xenhcd_hub_status_data(struct usb_hcd *hcd, char *buf)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++
++	int ports;
++	int i;
++	int length;
++
++	unsigned long flags;
++	int ret = 0;
++
++	int changed = 0;
++
++	if (!HC_IS_RUNNING(hcd->state))
++		return 0;
++
++	/* initialize the status to no-changes */
++	ports = info->rh_numports;
++	length = 1 + (ports / 8);
++	for (i = 0; i < length; i++) {
++		buf[i] = 0;
++		ret++;
++	}
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	for (i = 0; i < ports; i++) {
++		/* check status for each port */
++		if (info->ports[i].status & PORT_C_MASK) {
++			if (i < 7)
++				buf[0] |= 1 << (i + 1);
++			else if (i < 15)
++				buf[1] |= 1 << (i - 7);
++			else if (i < 23)
++				buf[2] |= 1 << (i - 15);
++			else
++				buf[3] |= 1 << (i - 23);
++			changed = 1;
++		}
++	}
++
++	if (!changed)
++		ret = 0;
++
++	spin_unlock_irqrestore(&info->lock, flags);
++
++	return ret;
++}
++
++static int xenhcd_hub_control(struct usb_hcd *hcd,
++			       u16 typeReq,
++			       u16 wValue,
++			       u16 wIndex,
++			       char *buf,
++			       u16 wLength)
++{
++	struct usbfront_info *info = hcd_to_info(hcd);
++	int ports = info->rh_numports;
++	unsigned long flags;
++	int ret = 0;
++	int i;
++	int changed = 0;
++
++	spin_lock_irqsave(&info->lock, flags);
++	switch (typeReq) {
++	case ClearHubFeature:
++		/* ignore this request */
++		break;
++	case ClearPortFeature:
++		if (!wIndex || wIndex > ports)
++			goto error;
++
++		switch (wValue) {
++		case USB_PORT_FEAT_SUSPEND:
++			rhport_resume(info, wIndex);
++			break;
++		case USB_PORT_FEAT_POWER:
++			rhport_power_off(info, wIndex);
++			break;
++		case USB_PORT_FEAT_ENABLE:
++			rhport_disable(info, wIndex);
++			break;
++		case USB_PORT_FEAT_C_CONNECTION:
++			info->ports[wIndex-1].c_connection = 0;
++			/* falling through */
++		default:
++			info->ports[wIndex-1].status &= ~(1 << wValue);
++			break;
++		}
++		break;
++	case GetHubDescriptor:
++		xenhcd_hub_descriptor(info,
++				      (struct usb_hub_descriptor *) buf);
++		break;
++	case GetHubStatus:
++		/* always local power supply good and no over-current exists. */
++		*(__le32 *)buf = cpu_to_le32(0);
++		break;
++	case GetPortStatus:
++		if (!wIndex || wIndex > ports)
++			goto error;
++
++		wIndex--;
++
++		/* resume completion */
++		if (info->ports[wIndex].resuming &&
++			time_after_eq(jiffies, info->ports[wIndex].timeout)) {
++			info->ports[wIndex].status |= (USB_PORT_STAT_C_SUSPEND << 16);
++			info->ports[wIndex].status &= ~USB_PORT_STAT_SUSPEND;
++		}
++
++		/* reset completion */
++		if ((info->ports[wIndex].status & USB_PORT_STAT_RESET) != 0 &&
++			time_after_eq(jiffies, info->ports[wIndex].timeout)) {
++			info->ports[wIndex].status |= (USB_PORT_STAT_C_RESET << 16);
++			info->ports[wIndex].status &= ~USB_PORT_STAT_RESET;
++
++			if (info->devices[wIndex].status != USB_STATE_NOTATTACHED) {
++				info->ports[wIndex].status |= USB_PORT_STAT_ENABLE;
++				info->devices[wIndex].status = USB_STATE_DEFAULT;
++			}
++
++			switch (info->devices[wIndex].speed) {
++			case USB_SPEED_LOW:
++				info->ports[wIndex].status |= USB_PORT_STAT_LOW_SPEED;
++				break;
++			case USB_SPEED_HIGH:
++				info->ports[wIndex].status |= USB_PORT_STAT_HIGH_SPEED;
++				break;
++			default:
++				break;
++			}
++		}
++
++		((u16 *) buf)[0] = cpu_to_le16 (info->ports[wIndex].status);
++		((u16 *) buf)[1] = cpu_to_le16 (info->ports[wIndex].status >> 16);
++		break;
++	case SetHubFeature:
++		/* not supported */
++		goto error;
++	case SetPortFeature:
++		if (!wIndex || wIndex > ports)
++			goto error;
++
++		switch (wValue) {
++		case USB_PORT_FEAT_POWER:
++			rhport_power_on(info, wIndex);
++			break;
++		case USB_PORT_FEAT_RESET:
++			rhport_reset(info, wIndex);
++			break;
++		case USB_PORT_FEAT_SUSPEND:
++			rhport_suspend(info, wIndex);
++			break;
++		default:
++			if ((info->ports[wIndex-1].status & USB_PORT_STAT_POWER) != 0)
++				info->ports[wIndex-1].status |= (1 << wValue);
++		}
++		break;
++
++	default:
++error:
++		ret = -EPIPE;
++	}
++	spin_unlock_irqrestore(&info->lock, flags);
++
++	/* check status for each port */
++	for (i = 0; i < ports; i++) {
++		if (info->ports[i].status & PORT_C_MASK)
++			changed = 1;
++	}
++	if (changed)
++		usb_hcd_poll_rh_status(hcd);
++
++	return ret;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-q.c	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,541 @@
++/*
++ * usbfront-q.c
++ *
++ * Xen USB Virtual Host Controller - RING operations.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++struct kmem_cache *xenhcd_urbp_cachep;
++
++static struct urb_priv *alloc_urb_priv(struct urb *urb)
++{
++	struct urb_priv *urbp;
++
++	urbp = kmem_cache_zalloc(xenhcd_urbp_cachep, GFP_ATOMIC);
++	if (!urbp)
++		return NULL;
++
++	urbp->urb = urb;
++	urb->hcpriv = urbp;
++	urbp->req_id = ~0;
++	urbp->unlink_req_id = ~0;
++	INIT_LIST_HEAD(&urbp->list);
++
++	return urbp;
++}
++
++static void free_urb_priv(struct urb_priv *urbp)
++{
++	urbp->urb->hcpriv = NULL;
++	kmem_cache_free(xenhcd_urbp_cachep, urbp);
++}
++
++static inline int get_id_from_freelist(
++	struct usbfront_info *info)
++{
++	unsigned long free;
++	free = info->shadow_free;
++	BUG_ON(free >= USB_URB_RING_SIZE);
++	info->shadow_free = info->shadow[free].req.id;
++	info->shadow[free].req.id = (unsigned int)0x0fff; /* debug */
++	return free;
++}
++
++static inline void add_id_to_freelist(
++	struct usbfront_info *info, unsigned long id)
++{
++	info->shadow[id].req.id  = info->shadow_free;
++	info->shadow[id].urb = NULL;
++	info->shadow_free = id;
++}
++
++static inline int count_pages(void *addr, int length)
++{
++	unsigned long start = (unsigned long) addr >> PAGE_SHIFT;
++	unsigned long end = (unsigned long) (addr + length + PAGE_SIZE - 1) >> PAGE_SHIFT;
++	return end - start;
++}
++
++static inline void xenhcd_gnttab_map(struct usbfront_info *info,
++		void *addr, int length, grant_ref_t *gref_head,
++		struct usbif_request_segment *seg, int nr_pages, int flags)
++{
++	grant_ref_t ref;
++	struct page *page;
++	unsigned long buffer_pfn;
++	unsigned int offset;
++	unsigned int len;
++	unsigned int bytes;
++	int i;
++
++	len = length;
++
++	for (i = 0; i < nr_pages; i++) {
++		BUG_ON(!len);
++
++		page = virt_to_page(addr);
++		buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
++		offset = offset_in_page(addr);
++
++		bytes = PAGE_SIZE - offset;
++		if (bytes > len)
++			bytes = len;
++
++		ref = gnttab_claim_grant_reference(gref_head);
++		BUG_ON(ref == -ENOSPC);
++		gnttab_grant_foreign_access_ref(ref, info->xbdev->otherend_id, buffer_pfn, flags);
++		seg[i].gref = ref;
++		seg[i].offset = (uint16_t)offset;
++		seg[i].length = (uint16_t)bytes;
++
++		addr += bytes;
++		len -= bytes;
++	}
++}
++
++static int map_urb_for_request(struct usbfront_info *info, struct urb *urb,
++		usbif_urb_request_t *req)
++{
++	grant_ref_t gref_head;
++	int nr_buff_pages = 0;
++	int nr_isodesc_pages = 0;
++	int ret = 0;
++
++	if (urb->transfer_buffer_length) {
++		nr_buff_pages = count_pages(urb->transfer_buffer, urb->transfer_buffer_length);
++
++		if (usb_pipeisoc(urb->pipe))
++			nr_isodesc_pages = count_pages(&urb->iso_frame_desc[0],
++					sizeof(struct usb_iso_packet_descriptor) * urb->number_of_packets);
++
++		if (nr_buff_pages + nr_isodesc_pages > USBIF_MAX_SEGMENTS_PER_REQUEST)
++			return -E2BIG;
++
++		ret = gnttab_alloc_grant_references(USBIF_MAX_SEGMENTS_PER_REQUEST, &gref_head);
++		if (ret) {
++			printk(KERN_ERR "usbfront: gnttab_alloc_grant_references() error\n");
++			return -ENOMEM;
++		}
++
++		xenhcd_gnttab_map(info, urb->transfer_buffer,
++				urb->transfer_buffer_length,
++				&gref_head, &req->seg[0], nr_buff_pages,
++				usb_pipein(urb->pipe) ? 0 : GTF_readonly);
++
++		if (!usb_pipeisoc(urb->pipe))
++			gnttab_free_grant_references(gref_head);
++	}
++
++	req->pipe = usbif_setportnum_pipe(urb->pipe, urb->dev->portnum);
++	req->transfer_flags = urb->transfer_flags;
++	req->buffer_length = urb->transfer_buffer_length;
++	req->nr_buffer_segs = nr_buff_pages;
++
++	switch (usb_pipetype(urb->pipe)) {
++	case PIPE_ISOCHRONOUS:
++		req->u.isoc.interval = urb->interval;
++		req->u.isoc.start_frame = urb->start_frame;
++		req->u.isoc.number_of_packets = urb->number_of_packets;
++		req->u.isoc.nr_frame_desc_segs = nr_isodesc_pages;
++		/* urb->number_of_packets must be > 0 */
++		if (unlikely(urb->number_of_packets <= 0))
++			BUG();
++		xenhcd_gnttab_map(info, &urb->iso_frame_desc[0],
++			sizeof(struct usb_iso_packet_descriptor) * urb->number_of_packets,
++			&gref_head, &req->seg[nr_buff_pages], nr_isodesc_pages, 0);
++		gnttab_free_grant_references(gref_head);
++		break;
++	case PIPE_INTERRUPT:
++		req->u.intr.interval = urb->interval;
++		break;
++	case PIPE_CONTROL:
++		if (urb->setup_packet)
++			memcpy(req->u.ctrl, urb->setup_packet, 8);
++		break;
++	case PIPE_BULK:
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++static void xenhcd_gnttab_done(struct usb_shadow *shadow)
++{
++	int nr_segs = 0;
++	int i;
++
++	nr_segs = shadow->req.nr_buffer_segs;
++
++	if (usb_pipeisoc(shadow->req.pipe))
++		nr_segs +=  shadow->req.u.isoc.nr_frame_desc_segs;
++
++	for (i = 0; i < nr_segs; i++)
++		gnttab_end_foreign_access(shadow->req.seg[i].gref, 0UL);
++
++	shadow->req.nr_buffer_segs = 0;
++	shadow->req.u.isoc.nr_frame_desc_segs = 0;
++}
++
++static void xenhcd_giveback_urb(struct usbfront_info *info, struct urb *urb, int status)
++__releases(info->lock)
++__acquires(info->lock)
++{
++	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
++
++	list_del_init(&urbp->list);
++	free_urb_priv(urbp);
++	switch (urb->status) {
++	case -ECONNRESET:
++	case -ENOENT:
++		COUNT(info->stats.unlink);
++		break;
++	case -EINPROGRESS:
++		urb->status = status;
++		/* falling through */
++	default:
++		COUNT(info->stats.complete);
++	}
++	spin_unlock(&info->lock);
++	usb_hcd_giveback_urb(info_to_hcd(info), urb, NULL);
++	spin_lock(&info->lock);
++}
++
++static inline int xenhcd_do_request(struct usbfront_info *info, struct urb_priv *urbp)
++{
++	usbif_urb_request_t *req;
++	struct urb *urb = urbp->urb;
++	uint16_t id;
++	int notify;
++	int ret = 0;
++
++	req = RING_GET_REQUEST(&info->urb_ring, info->urb_ring.req_prod_pvt);
++	id = get_id_from_freelist(info);
++	req->id = id;
++
++	if (unlikely(urbp->unlinked)) {
++		req->u.unlink.unlink_id = urbp->req_id;
++		req->pipe = usbif_setunlink_pipe(usbif_setportnum_pipe(
++				urb->pipe, urb->dev->portnum));
++		urbp->unlink_req_id = id;
++	} else {
++		ret = map_urb_for_request(info, urb, req);
++		if (ret < 0) {
++			add_id_to_freelist(info, id);
++			return ret;
++		}
++		urbp->req_id = id;
++	}
++
++	info->urb_ring.req_prod_pvt++;
++	info->shadow[id].urb = urb;
++	info->shadow[id].req = *req;
++
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->urb_ring, notify);
++	if (notify)
++		notify_remote_via_irq(info->irq);
++
++	return ret;
++}
++
++static void xenhcd_kick_pending_urbs(struct usbfront_info *info)
++{
++	struct urb_priv *urbp;
++	int ret;
++
++	while (!list_empty(&info->pending_submit_list)) {
++		if (RING_FULL(&info->urb_ring)) {
++			COUNT(info->stats.ring_full);
++			timer_action(info, TIMER_RING_WATCHDOG);
++			goto done;
++		}
++
++		urbp = list_entry(info->pending_submit_list.next, struct urb_priv, list);
++		ret = xenhcd_do_request(info, urbp);
++		if (ret == 0)
++			list_move_tail(&urbp->list, &info->in_progress_list);
++		else
++			xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
++	}
++	timer_action_done(info, TIMER_SCAN_PENDING_URBS);
++
++done:
++	return;
++}
++
++/*
++ * caller must lock info->lock
++ */
++static void xenhcd_cancel_all_enqueued_urbs(struct usbfront_info *info)
++{
++	struct urb_priv *urbp, *tmp;
++
++	list_for_each_entry_safe(urbp, tmp, &info->in_progress_list, list) {
++		if (!urbp->unlinked) {
++			xenhcd_gnttab_done(&info->shadow[urbp->req_id]);
++			barrier();
++			if (urbp->urb->status == -EINPROGRESS)	/* not dequeued */
++				xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
++			else					/* dequeued */
++				xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status);
++		}
++		info->shadow[urbp->req_id].urb = NULL;
++	}
++
++	list_for_each_entry_safe(urbp, tmp, &info->pending_submit_list, list) {
++		xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
++	}
++
++	return;
++}
++
++/*
++ * caller must lock info->lock
++ */
++static void xenhcd_giveback_unlinked_urbs(struct usbfront_info *info)
++{
++	struct urb_priv *urbp, *tmp;
++
++	list_for_each_entry_safe(urbp, tmp, &info->giveback_waiting_list, list) {
++		xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status);
++	}
++}
++
++static int xenhcd_submit_urb(struct usbfront_info *info, struct urb_priv *urbp)
++{
++	int ret = 0;
++
++	if (RING_FULL(&info->urb_ring)) {
++		list_add_tail(&urbp->list, &info->pending_submit_list);
++		COUNT(info->stats.ring_full);
++		timer_action(info, TIMER_RING_WATCHDOG);
++		goto done;
++	}
++
++	if (!list_empty(&info->pending_submit_list)) {
++		list_add_tail(&urbp->list, &info->pending_submit_list);
++		timer_action(info, TIMER_SCAN_PENDING_URBS);
++		goto done;
++	}
++
++	ret = xenhcd_do_request(info, urbp);
++	if (ret == 0)
++		list_add_tail(&urbp->list, &info->in_progress_list);
++
++done:
++	return ret;
++}
++
++static int xenhcd_unlink_urb(struct usbfront_info *info, struct urb_priv *urbp)
++{
++	int ret = 0;
++
++	/* already unlinked? */
++	if (urbp->unlinked)
++		return -EBUSY;
++
++	urbp->unlinked = 1;
++
++	/* the urb is still in pending_submit queue */
++	if (urbp->req_id == ~0) {
++		list_move_tail(&urbp->list, &info->giveback_waiting_list);
++		timer_action(info, TIMER_SCAN_PENDING_URBS);
++		goto done;
++	}
++
++	/* send unlink request to backend */
++	if (RING_FULL(&info->urb_ring)) {
++		list_move_tail(&urbp->list, &info->pending_unlink_list);
++		COUNT(info->stats.ring_full);
++		timer_action(info, TIMER_RING_WATCHDOG);
++		goto done;
++	}
++
++	if (!list_empty(&info->pending_unlink_list)) {
++		list_move_tail(&urbp->list, &info->pending_unlink_list);
++		timer_action(info, TIMER_SCAN_PENDING_URBS);
++		goto done;
++	}
++
++	ret = xenhcd_do_request(info, urbp);
++	if (ret == 0)
++		list_move_tail(&urbp->list, &info->in_progress_list);
++
++done:
++	return ret;
++}
++
++static int xenhcd_urb_request_done(struct usbfront_info *info)
++{
++	usbif_urb_response_t *res;
++	struct urb *urb;
++
++	RING_IDX i, rp;
++	uint16_t id;
++	int more_to_do = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	rp = info->urb_ring.sring->rsp_prod;
++	rmb(); /* ensure we see queued responses up to "rp" */
++
++	for (i = info->urb_ring.rsp_cons; i != rp; i++) {
++		res = RING_GET_RESPONSE(&info->urb_ring, i);
++		id = res->id;
++
++		if (likely(usbif_pipesubmit(info->shadow[id].req.pipe))) {
++			xenhcd_gnttab_done(&info->shadow[id]);
++			urb = info->shadow[id].urb;
++			barrier();
++			if (likely(urb)) {
++				urb->actual_length = res->actual_length;
++				urb->error_count = res->error_count;
++				urb->start_frame = res->start_frame;
++				barrier();
++				xenhcd_giveback_urb(info, urb, res->status);
++			}
++		}
++
++		add_id_to_freelist(info, id);
++	}
++	info->urb_ring.rsp_cons = i;
++
++	if (i != info->urb_ring.req_prod_pvt)
++		RING_FINAL_CHECK_FOR_RESPONSES(&info->urb_ring, more_to_do);
++	else
++		info->urb_ring.sring->rsp_event = i + 1;
++
++	spin_unlock_irqrestore(&info->lock, flags);
++
++	cond_resched();
++
++	return more_to_do;
++}
++
++static int xenhcd_conn_notify(struct usbfront_info *info)
++{
++	usbif_conn_response_t *res;
++	usbif_conn_request_t *req;
++	RING_IDX rc, rp;
++	uint16_t id;
++	uint8_t portnum, speed;
++	int more_to_do = 0;
++	int notify;
++	int port_changed = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&info->lock, flags);
++
++	rc = info->conn_ring.rsp_cons;
++	rp = info->conn_ring.sring->rsp_prod;
++	rmb(); /* ensure we see queued responses up to "rp" */
++
++	while (rc != rp) {
++		res = RING_GET_RESPONSE(&info->conn_ring, rc);
++		id = res->id;
++		portnum = res->portnum;
++		speed = res->speed;
++		info->conn_ring.rsp_cons = ++rc;
++
++		rhport_connect(info, portnum, speed);
++		if (info->ports[portnum-1].c_connection)
++			port_changed = 1;
++
++		barrier();
++
++		req = RING_GET_REQUEST(&info->conn_ring, info->conn_ring.req_prod_pvt);
++		req->id = id;
++		info->conn_ring.req_prod_pvt++;
++	}
++
++	if (rc != info->conn_ring.req_prod_pvt)
++		RING_FINAL_CHECK_FOR_RESPONSES(&info->conn_ring, more_to_do);
++	else
++		info->conn_ring.sring->rsp_event = rc + 1;
++
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
++	if (notify)
++		notify_remote_via_irq(info->irq);
++
++	spin_unlock_irqrestore(&info->lock, flags);
++
++	if (port_changed)
++		usb_hcd_poll_rh_status(info_to_hcd(info));
++
++	cond_resched();
++
++	return more_to_do;
++}
++
++int xenhcd_schedule(void *arg)
++{
++	struct usbfront_info *info = (struct usbfront_info *) arg;
++
++	while (!kthread_should_stop()) {
++		wait_event_interruptible(
++				info->wq,
++				info->waiting_resp || kthread_should_stop());
++		info->waiting_resp = 0;
++		smp_mb();
++
++		if (xenhcd_urb_request_done(info))
++			info->waiting_resp = 1;
++
++		if (xenhcd_conn_notify(info))
++			info->waiting_resp = 1;
++	}
++
++	return 0;
++}
++
++static void xenhcd_notify_work(struct usbfront_info *info)
++{
++	info->waiting_resp = 1;
++	wake_up(&info->wq);
++}
++
++irqreturn_t xenhcd_int(int irq, void *dev_id, struct pt_regs *ptregs)
++{
++	xenhcd_notify_work((struct usbfront_info *) dev_id);
++	return IRQ_HANDLED;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/usbfront.h	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,203 @@
++/*
++ * usbfront.h
++ *
++ * This file is part of Xen USB Virtual Host Controller driver.
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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_USBFRONT_H__
++#define __XEN_USBFRONT_H__
++
++#include <linux/module.h>
++#include <linux/usb.h>
++#include <linux/list.h>
++#include <linux/kthread.h>
++#include <linux/wait.h>
++#include <asm/io.h>
++#include <xen/xenbus.h>
++#include <xen/evtchn.h>
++#include <xen/gnttab.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/io/usbif.h>
++
++/*
++ * usbfront needs USB HCD headers,
++ * drivers/usb/core/hcd.h and drivers/usb/core/hub.h,
++ * but, they are not in public include path.
++ */
++#include "../../usb/core/hcd.h"
++#include "../../usb/core/hub.h"
++
++static inline struct usbfront_info *hcd_to_info(struct usb_hcd *hcd)
++{
++	return (struct usbfront_info *) (hcd->hcd_priv);
++}
++
++static inline struct usb_hcd *info_to_hcd(struct usbfront_info *info)
++{
++	return container_of((void *) info, struct usb_hcd, hcd_priv);
++}
++
++/* Private per-URB data */
++struct urb_priv {
++	struct list_head list;
++	struct urb *urb;
++	int req_id;	/* RING_REQUEST id for submitting */
++	int unlink_req_id; /* RING_REQUEST id for unlinking */
++	unsigned unlinked:1; /* dequeued marker */
++};
++
++/* virtual roothub port status */
++struct rhport_status {
++	u32 status;
++	unsigned resuming:1; /* in resuming */
++	unsigned c_connection:1; /* connection changed */
++	unsigned long timeout;
++};
++
++/* status of attached device */
++struct vdevice_status {
++	int devnum;
++	enum usb_device_state status;
++	enum usb_device_speed speed;
++};
++
++/* RING request shadow */
++struct usb_shadow {
++	usbif_urb_request_t req;
++	struct urb *urb;
++};
++
++/* statistics for tuning, monitoring, ... */
++struct xenhcd_stats {
++	unsigned long ring_full; /* RING_FULL conditions */
++	unsigned long complete; /* normal givebacked urbs */
++	unsigned long unlink; /* unlinked urbs */
++};
++
++struct usbfront_info {
++	/* Virtual Host Controller has 4 urb queues */
++	struct list_head pending_submit_list;
++	struct list_head pending_unlink_list;
++	struct list_head in_progress_list;
++	struct list_head giveback_waiting_list;
++
++	spinlock_t lock;
++
++	/* timer that kick pending and giveback waiting urbs */
++	struct timer_list watchdog;
++	unsigned long actions;
++
++	/* virtual root hub */
++	int rh_numports;
++	struct rhport_status ports[USB_MAXCHILDREN];
++	struct vdevice_status devices[USB_MAXCHILDREN];
++
++	/* Xen related staff */
++	struct xenbus_device *xbdev;
++	int urb_ring_ref;
++	int conn_ring_ref;
++	usbif_urb_front_ring_t urb_ring;
++	usbif_conn_front_ring_t conn_ring;
++
++	unsigned int irq; /* event channel */
++	struct usb_shadow shadow[USB_URB_RING_SIZE];
++	unsigned long shadow_free;
++
++	/* RING_RESPONSE thread */
++	struct task_struct *kthread;
++	wait_queue_head_t wq;
++	unsigned int waiting_resp;
++
++	/* xmit statistics */
++#ifdef XENHCD_STATS
++	struct xenhcd_stats stats;
++#define COUNT(x) do { (x)++; } while (0)
++#else
++#define COUNT(x) do {} while (0)
++#endif
++};
++
++#define XENHCD_RING_JIFFIES (HZ/200)
++#define XENHCD_SCAN_JIFFIES 1
++
++enum xenhcd_timer_action {
++	TIMER_RING_WATCHDOG,
++	TIMER_SCAN_PENDING_URBS,
++};
++
++static inline void
++timer_action_done(struct usbfront_info *info, enum xenhcd_timer_action action)
++{
++	clear_bit(action, &info->actions);
++}
++
++static inline void
++timer_action(struct usbfront_info *info, enum xenhcd_timer_action action)
++{
++	if (timer_pending(&info->watchdog)
++			&& test_bit(TIMER_SCAN_PENDING_URBS, &info->actions))
++		return;
++
++	if (!test_and_set_bit(action, &info->actions)) {
++		unsigned long t;
++
++		switch (action) {
++		case TIMER_RING_WATCHDOG:
++			t = XENHCD_RING_JIFFIES;
++			break;
++		default:
++			t = XENHCD_SCAN_JIFFIES;
++			break;
++		}
++		mod_timer(&info->watchdog, t + jiffies);
++	}
++}
++
++extern struct kmem_cache *xenhcd_urbp_cachep;
++extern struct hc_driver xen_usb20_hc_driver;
++extern struct hc_driver xen_usb11_hc_driver;
++irqreturn_t xenhcd_int(int irq, void *dev_id, struct pt_regs *ptregs);
++void xenhcd_rhport_state_change(struct usbfront_info *info,
++				int port, enum usb_device_speed speed);
++int xenhcd_schedule(void *arg);
++
++#endif /* __XEN_USBFRONT_H__ */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/usbfront/xenbus.c	2009-10-15 11:45:41.000000000 +0200
+@@ -0,0 +1,412 @@
++/*
++ * xenbus.c
++ *
++ * Xenbus interface for Xen USB Virtual Host Controller
++ *
++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
++ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ *
++ * or, by your choice,
++ *
++ * 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 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.
++ */
++
++#include "usbfront.h"
++
++#define GRANT_INVALID_REF 0
++
++static void destroy_rings(struct usbfront_info *info)
++{
++	if (info->irq)
++		unbind_from_irqhandler(info->irq, info);
++	info->irq = 0;
++
++	if (info->urb_ring_ref != GRANT_INVALID_REF) {
++		gnttab_end_foreign_access(info->urb_ring_ref,
++					  (unsigned long)info->urb_ring.sring);
++		info->urb_ring_ref = GRANT_INVALID_REF;
++	}
++	info->urb_ring.sring = NULL;
++
++	if (info->conn_ring_ref != GRANT_INVALID_REF) {
++		gnttab_end_foreign_access(info->conn_ring_ref,
++					  (unsigned long)info->conn_ring.sring);
++		info->conn_ring_ref = GRANT_INVALID_REF;
++	}
++	info->conn_ring.sring = NULL;
++}
++
++static int setup_rings(struct xenbus_device *dev,
++			   struct usbfront_info *info)
++{
++	usbif_urb_sring_t *urb_sring;
++	usbif_conn_sring_t *conn_sring;
++	int err;
++
++	info->urb_ring_ref = GRANT_INVALID_REF;
++	info->conn_ring_ref = GRANT_INVALID_REF;
++
++	urb_sring = (usbif_urb_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
++	if (!urb_sring) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating urb ring");
++		return -ENOMEM;
++	}
++	SHARED_RING_INIT(urb_sring);
++	FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE);
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(info->urb_ring.sring));
++	if (err < 0) {
++		free_page((unsigned long)urb_sring);
++		info->urb_ring.sring = NULL;
++		goto fail;
++	}
++	info->urb_ring_ref = err;
++
++	conn_sring = (usbif_conn_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
++	if (!conn_sring) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating conn ring");
++		return -ENOMEM;
++	}
++	SHARED_RING_INIT(conn_sring);
++	FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE);
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(info->conn_ring.sring));
++	if (err < 0) {
++		free_page((unsigned long)conn_sring);
++		info->conn_ring.sring = NULL;
++		goto fail;
++	}
++	info->conn_ring_ref = err;
++
++	err = bind_listening_port_to_irqhandler(
++		dev->otherend_id, xenhcd_int, SA_SAMPLE_RANDOM, "usbif", info);
++	if (err <= 0) {
++		xenbus_dev_fatal(dev, err,
++				 "bind_listening_port_to_irqhandler");
++		goto fail;
++	}
++	info->irq = err;
++
++	return 0;
++fail:
++	destroy_rings(info);
++	return err;
++}
++
++static int talk_to_backend(struct xenbus_device *dev,
++			   struct usbfront_info *info)
++{
++	const char *message;
++	struct xenbus_transaction xbt;
++	int err;
++
++	err = setup_rings(dev, info);
++	if (err)
++		goto out;
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		goto destroy_ring;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "urb-ring-ref", "%u",
++			    info->urb_ring_ref);
++	if (err) {
++		message = "writing urb-ring-ref";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "conn-ring-ref", "%u",
++			    info->conn_ring_ref);
++	if (err) {
++		message = "writing conn-ring-ref";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    irq_to_evtchn_port(info->irq));
++	if (err) {
++		message = "writing event-channel";
++		goto abort_transaction;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err) {
++		if (err == -EAGAIN)
++			goto again;
++		xenbus_dev_fatal(dev, err, "completing transaction");
++		goto destroy_ring;
++	}
++
++	return 0;
++
++abort_transaction:
++	xenbus_transaction_end(xbt, 1);
++	xenbus_dev_fatal(dev, err, "%s", message);
++
++destroy_ring:
++	destroy_rings(info);
++
++out:
++	return err;
++}
++
++static int connect(struct xenbus_device *dev)
++{
++	struct usbfront_info *info = dev->dev.driver_data;
++
++	usbif_conn_request_t *req;
++	int i, idx, err;
++	int notify;
++
++	err = talk_to_backend(dev, info);
++	if (err)
++		return err;
++
++	/* prepare ring for hotplug notification */
++	for (idx = 0, i = 0; i < USB_CONN_RING_SIZE; i++) {
++		req = RING_GET_REQUEST(&info->conn_ring, idx);
++		req->id = idx;
++		idx++;
++	}
++	info->conn_ring.req_prod_pvt = idx;
++
++	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
++	if (notify)
++		notify_remote_via_irq(info->irq);
++
++	return 0;
++}
++
++static struct usb_hcd *create_hcd(struct xenbus_device *dev)
++{
++	int i;
++	int err = 0;
++	int num_ports;
++	int usb_ver;
++	struct usb_hcd *hcd = NULL;
++	struct usbfront_info *info = NULL;
++
++	err = xenbus_scanf(XBT_NIL, dev->otherend,
++					"num-ports", "%d", &num_ports);
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading num-ports");
++		return ERR_PTR(-EINVAL);
++	}
++	if (num_ports < 1 || num_ports > USB_MAXCHILDREN) {
++		xenbus_dev_fatal(dev, err, "invalid num-ports");
++		return ERR_PTR(-EINVAL);
++	}
++
++	err = xenbus_scanf(XBT_NIL, dev->otherend,
++					"usb-ver", "%d", &usb_ver);
++	if (err != 1) {
++		xenbus_dev_fatal(dev, err, "reading usb-ver");
++		return ERR_PTR(-EINVAL);
++	}
++	switch (usb_ver) {
++	case USB_VER_USB11:
++		hcd = usb_create_hcd(&xen_usb11_hc_driver, &dev->dev, dev->dev.bus_id);
++		break;
++	case USB_VER_USB20:
++		hcd = usb_create_hcd(&xen_usb20_hc_driver, &dev->dev, dev->dev.bus_id);
++		break;
++	default:
++		xenbus_dev_fatal(dev, err, "invalid usb-ver");
++		return ERR_PTR(-EINVAL);
++	}
++	if (!hcd) {
++		xenbus_dev_fatal(dev, err,
++				"fail to allocate USB host controller");
++		return ERR_PTR(-ENOMEM);
++	}
++
++	info = hcd_to_info(hcd);
++	info->xbdev = dev;
++	info->rh_numports = num_ports;
++
++	for (i = 0; i < USB_URB_RING_SIZE; i++) {
++		info->shadow[i].req.id = i + 1;
++		info->shadow[i].urb = NULL;
++	}
++	info->shadow[USB_URB_RING_SIZE-1].req.id = 0x0fff;
++
++	return hcd;
++}
++
++static int usbfront_probe(struct xenbus_device *dev,
++			  const struct xenbus_device_id *id)
++{
++	int err;
++	struct usb_hcd *hcd;
++	struct usbfront_info *info;
++	char name[TASK_COMM_LEN];
++
++	if (usb_disabled())
++		return -ENODEV;
++
++	hcd = create_hcd(dev);
++	if (IS_ERR(hcd)) {
++		err = PTR_ERR(hcd);
++		xenbus_dev_fatal(dev, err,
++				"fail to create usb host controller");
++		goto fail;
++	}
++
++	info = hcd_to_info(hcd);
++	dev->dev.driver_data = info;
++
++	err = usb_add_hcd(hcd, 0, 0);
++	if (err != 0) {
++		xenbus_dev_fatal(dev, err,
++				"fail to adding USB host controller");
++		goto fail;
++	}
++
++	init_waitqueue_head(&info->wq);
++	snprintf(name, TASK_COMM_LEN, "xenhcd.%d", hcd->self.busnum);
++	info->kthread = kthread_run(xenhcd_schedule, info, name);
++	if (IS_ERR(info->kthread)) {
++		err = PTR_ERR(info->kthread);
++		info->kthread = NULL;
++		goto fail;
++	}
++
++	return 0;
++
++fail:
++	usb_put_hcd(hcd);
++	dev->dev.driver_data = NULL;
++	return err;
++}
++
++static void usbfront_disconnect(struct xenbus_device *dev)
++{
++	struct usbfront_info *info = dev->dev.driver_data;
++	struct usb_hcd *hcd = info_to_hcd(info);
++
++	usb_remove_hcd(hcd);
++	if (info->kthread) {
++		kthread_stop(info->kthread);
++		info->kthread = NULL;
++	}
++	xenbus_frontend_closed(dev);
++}
++
++static void backend_changed(struct xenbus_device *dev,
++				     enum xenbus_state backend_state)
++{
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitialised:
++	case XenbusStateConnected:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++	case XenbusStateClosed:
++		break;
++
++	case XenbusStateInitWait:
++		if (dev->state != XenbusStateInitialising)
++			break;
++		connect(dev);
++		xenbus_switch_state(dev, XenbusStateConnected);
++		break;
++
++	case XenbusStateClosing:
++		usbfront_disconnect(dev);
++		break;
++
++	default:
++		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
++				 backend_state);
++		break;
++	}
++}
++
++static int usbfront_remove(struct xenbus_device *dev)
++{
++	struct usbfront_info *info = dev->dev.driver_data;
++	struct usb_hcd *hcd = info_to_hcd(info);
++
++	destroy_rings(info);
++	usb_put_hcd(hcd);
++
++	return 0;
++}
++
++static const struct xenbus_device_id usbfront_ids[] = {
++	{ "vusb" },
++	{ "" },
++};
++
++static struct xenbus_driver usbfront_driver = {
++	.name = "vusb",
++	.owner = THIS_MODULE,
++	.ids = usbfront_ids,
++	.probe = usbfront_probe,
++	.otherend_changed = backend_changed,
++	.remove = usbfront_remove,
++};
++
++static int __init usbfront_init(void)
++{
++	if (!is_running_on_xen())
++		return -ENODEV;
++
++	xenhcd_urbp_cachep = kmem_cache_create("xenhcd_urb_priv",
++			sizeof(struct urb_priv), 0, 0, NULL, NULL);
++	if (!xenhcd_urbp_cachep) {
++		printk(KERN_ERR "usbfront failed to create kmem cache\n");
++		return -ENOMEM;
++	}
++
++	return xenbus_register_frontend(&usbfront_driver);
++}
++
++static void __exit usbfront_exit(void)
++{
++	kmem_cache_destroy(xenhcd_urbp_cachep);
++	xenbus_unregister_driver(&usbfront_driver);
++}
++
++module_init(usbfront_init);
++module_exit(usbfront_exit);
++
++MODULE_AUTHOR("");
++MODULE_DESCRIPTION("Xen USB Virtual Host Controller driver (usbfront)");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/util.c	2007-07-10 09:42:30.000000000 +0200
+@@ -0,0 +1,65 @@
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
++#include <xen/driver_util.h>
++
++struct class *get_xen_class(void)
++{
++	static struct class *xen_class;
++
++	if (xen_class)
++		return xen_class;
++
++	xen_class = class_create(THIS_MODULE, "xen");
++	if (IS_ERR(xen_class)) {
++		printk("Failed to create xen sysfs class.\n");
++		xen_class = NULL;
++	}
++
++	return xen_class;
++}
++EXPORT_SYMBOL_GPL(get_xen_class);
++
++#ifdef CONFIG_X86
++static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	/* apply_to_page_range() does all the hard work. */
++	return 0;
++}
++
++struct vm_struct *alloc_vm_area(unsigned long size)
++{
++	struct vm_struct *area;
++
++	area = get_vm_area(size, VM_IOREMAP);
++	if (area == NULL)
++		return NULL;
++
++	/*
++	 * This ensures that page tables are constructed for this region
++	 * of kernel virtual address space and mapped into init_mm.
++	 */
++	if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
++				area->size, f, NULL)) {
++		free_vm_area(area);
++		return NULL;
++	}
++
++	/* Map page directories into every address space. */
++	vmalloc_sync_all();
++
++	return area;
++}
++EXPORT_SYMBOL_GPL(alloc_vm_area);
++
++void free_vm_area(struct vm_struct *area)
++{
++	struct vm_struct *ret;
++	ret = remove_vm_area(area->addr);
++	BUG_ON(ret != area);
++	kfree(area);
++}
++EXPORT_SYMBOL_GPL(free_vm_area);
++#endif /* CONFIG_X86 */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_backend_client.c	2010-01-04 11:56:34.000000000 +0100
+@@ -0,0 +1,154 @@
++/******************************************************************************
++ * Backend-client-facing interface for the Xenbus driver.  In other words, the
++ * interface between the Xenbus and the device-specific code in the backend
++ * driver.
++ *
++ * Copyright (C) 2005-2006 XenSource Ltd
++ * 
++ * 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/err.h>
++#include <linux/delay.h>
++#include <xen/gnttab.h>
++#include <xen/xenbus.h>
++#include <xen/driver_util.h>
++
++/* Based on Rusty Russell's skeleton driver's map_page */
++struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref)
++{
++	struct gnttab_map_grant_ref op;
++	struct vm_struct *area;
++
++	area = alloc_vm_area(PAGE_SIZE);
++	if (!area)
++		return ERR_PTR(-ENOMEM);
++
++	gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
++			  gnt_ref, dev->otherend_id);
++	
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status != GNTST_okay) {
++		free_vm_area(area);
++		xenbus_dev_fatal(dev, op.status,
++				 "mapping in shared page %d from domain %d",
++				 gnt_ref, dev->otherend_id);
++		BUG_ON(!IS_ERR(ERR_PTR(op.status)));
++		return ERR_PTR(op.status);
++	}
++
++	/* Stuff the handle in an unused field */
++	area->phys_addr = (unsigned long)op.handle;
++
++	return area;
++}
++EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
++
++
++int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
++		   grant_handle_t *handle, void *vaddr)
++{
++	struct gnttab_map_grant_ref op;
++	
++	gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
++			  gnt_ref, dev->otherend_id);
++    do {
++	    if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		    BUG();
++        msleep(10);
++    } while(op.status == GNTST_eagain);
++
++	if (op.status != GNTST_okay) {
++		xenbus_dev_fatal(dev, op.status,
++				 "mapping in shared page %d from domain %d",
++				 gnt_ref, dev->otherend_id);
++	} else
++		*handle = op.handle;
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_map_ring);
++
++
++/* Based on Rusty Russell's skeleton driver's unmap_page */
++int xenbus_unmap_ring_vfree(struct xenbus_device *dev, struct vm_struct *area)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
++			    (grant_handle_t)area->phys_addr);
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status == GNTST_okay)
++		free_vm_area(area);
++	else
++		xenbus_dev_error(dev, op.status,
++				 "unmapping page at handle %d error %d",
++				 (int16_t)area->phys_addr, op.status);
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
++
++
++int xenbus_unmap_ring(struct xenbus_device *dev,
++		     grant_handle_t handle, void *vaddr)
++{
++	struct gnttab_unmap_grant_ref op;
++
++	gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
++			    handle);
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status != GNTST_okay)
++		xenbus_dev_error(dev, op.status,
++				 "unmapping page at handle %d error %d",
++				 handle, op.status);
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
++
++int xenbus_dev_is_online(struct xenbus_device *dev)
++{
++	int rc, val;
++
++	rc = xenbus_scanf(XBT_NIL, dev->nodename, "online", "%d", &val);
++	if (rc != 1)
++		val = 0; /* no online node present */
++
++	return val;
++}
++EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_dev.c	2009-05-29 10:25:53.000000000 +0200
+@@ -0,0 +1,460 @@
++/*
++ * xenbus_dev.c
++ * 
++ * Driver giving user-space access to the kernel's xenbus connection
++ * to xenstore.
++ * 
++ * Copyright (c) 2005, Christian Limpach
++ * Copyright (c) 2005, Rusty Russell, IBM Corporation
++ * 
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/uio.h>
++#include <linux/notifier.h>
++#include <linux/wait.h>
++#include <linux/fs.h>
++#include <linux/poll.h>
++#include <linux/mutex.h>
++
++#include "xenbus_comms.h"
++
++#include <asm/uaccess.h>
++#include <asm/hypervisor.h>
++#include <xen/xenbus.h>
++#include <xen/xen_proc.h>
++#include <asm/hypervisor.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#include <xen/public/xenbus.h>
++
++struct xenbus_dev_transaction {
++	struct list_head list;
++	struct xenbus_transaction handle;
++};
++
++struct read_buffer {
++	struct list_head list;
++	unsigned int cons;
++	unsigned int len;
++	char msg[];
++};
++
++struct xenbus_dev_data {
++	/* In-progress transaction. */
++	struct list_head transactions;
++
++	/* Active watches. */
++	struct list_head watches;
++
++	/* Partial request. */
++	unsigned int len;
++	union {
++		struct xsd_sockmsg msg;
++		char buffer[PAGE_SIZE];
++	} u;
++
++	/* Response queue. */
++	struct list_head read_buffers;
++	wait_queue_head_t read_waitq;
++
++	struct mutex reply_mutex;
++};
++
++static struct proc_dir_entry *xenbus_dev_intf;
++
++static ssize_t xenbus_dev_read(struct file *filp,
++			       char __user *ubuf,
++			       size_t len, loff_t *ppos)
++{
++	struct xenbus_dev_data *u = filp->private_data;
++	struct read_buffer *rb;
++	int i, ret;
++
++	if (!is_xenstored_ready())
++		return -ENODEV;
++
++	mutex_lock(&u->reply_mutex);
++	while (list_empty(&u->read_buffers)) {
++		mutex_unlock(&u->reply_mutex);
++		ret = wait_event_interruptible(u->read_waitq,
++					       !list_empty(&u->read_buffers));
++		if (ret)
++			return ret;
++		mutex_lock(&u->reply_mutex);
++	}
++
++	rb = list_entry(u->read_buffers.next, struct read_buffer, list);
++	for (i = 0; i < len;) {
++		put_user(rb->msg[rb->cons], ubuf + i);
++		i++;
++		rb->cons++;
++		if (rb->cons == rb->len) {
++			list_del(&rb->list);
++			kfree(rb);
++			if (list_empty(&u->read_buffers))
++				break;
++			rb = list_entry(u->read_buffers.next,
++					struct read_buffer, list);
++		}
++	}
++	mutex_unlock(&u->reply_mutex);
++
++	return i;
++}
++
++static void queue_reply(struct xenbus_dev_data *u,
++			char *data, unsigned int len)
++{
++	struct read_buffer *rb;
++
++	if (len == 0)
++		return;
++
++	rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
++	BUG_ON(rb == NULL);
++
++	rb->cons = 0;
++	rb->len = len;
++
++	memcpy(rb->msg, data, len);
++
++	list_add_tail(&rb->list, &u->read_buffers);
++
++	wake_up(&u->read_waitq);
++}
++
++struct watch_adapter
++{
++	struct list_head list;
++	struct xenbus_watch watch;
++	struct xenbus_dev_data *dev_data;
++	char *token;
++};
++
++static void free_watch_adapter (struct watch_adapter *watch)
++{
++	kfree(watch->watch.node);
++	kfree(watch->token);
++	kfree(watch);
++}
++
++static void watch_fired(struct xenbus_watch *watch,
++			const char **vec,
++			unsigned int len)
++{
++	struct watch_adapter *adap =
++            container_of(watch, struct watch_adapter, watch);
++	struct xsd_sockmsg hdr;
++	const char *path, *token;
++	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;
++	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;
++
++	mutex_lock(&adap->dev_data->reply_mutex);
++	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);
++}
++
++static LIST_HEAD(watch_list);
++
++static ssize_t xenbus_dev_write(struct file *filp,
++				const char __user *ubuf,
++				size_t len, loff_t *ppos)
++{
++	struct xenbus_dev_data *u = filp->private_data;
++	struct xenbus_dev_transaction *trans = NULL;
++	uint32_t msg_type;
++	void *reply;
++	char *path, *token;
++	struct watch_adapter *watch, *tmp_watch;
++	int err, rc = len;
++
++	if (!is_xenstored_ready())
++		return -ENODEV;
++
++	if ((len + u->len) > sizeof(u->u.buffer)) {
++		rc = -EINVAL;
++		goto out;
++	}
++
++	if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) {
++		rc = -EFAULT;
++		goto out;
++	}
++
++	u->len += len;
++	if ((u->len < sizeof(u->u.msg)) ||
++	    (u->len < (sizeof(u->u.msg) + u->u.msg.len)))
++		return rc;
++
++	msg_type = u->u.msg.type;
++
++	switch (msg_type) {
++	case XS_WATCH:
++	case XS_UNWATCH: {
++		static const char *XS_RESP = "OK";
++		struct xsd_sockmsg hdr;
++
++		path = u->u.buffer + sizeof(u->u.msg);
++		token = memchr(path, 0, u->u.msg.len);
++		if (token == NULL) {
++			rc = -EILSEQ;
++			goto out;
++		}
++		token++;
++
++		if (msg_type == XS_WATCH) {
++			watch = kzalloc(sizeof(*watch), GFP_KERNEL);
++			watch->watch.node = kmalloc(strlen(path)+1,
++                                                    GFP_KERNEL);
++			strcpy((char *)watch->watch.node, path);
++			watch->watch.callback = watch_fired;
++			watch->token = kmalloc(strlen(token)+1, GFP_KERNEL);
++			strcpy(watch->token, token);
++			watch->dev_data = u;
++
++			err = register_xenbus_watch(&watch->watch);
++			if (err) {
++				free_watch_adapter(watch);
++				rc = err;
++				goto out;
++			}
++			
++			list_add(&watch->list, &u->watches);
++		} else {
++			list_for_each_entry_safe(watch, tmp_watch,
++                                                 &u->watches, list) {
++				if (!strcmp(watch->token, token) &&
++				    !strcmp(watch->watch.node, path))
++				{
++					unregister_xenbus_watch(&watch->watch);
++					list_del(&watch->list);
++					free_watch_adapter(watch);
++					break;
++				}
++			}
++		}
++
++		hdr.type = msg_type;
++		hdr.len = strlen(XS_RESP) + 1;
++		mutex_lock(&u->reply_mutex);
++		queue_reply(u, (char *)&hdr, sizeof(hdr));
++		queue_reply(u, (char *)XS_RESP, hdr.len);
++		mutex_unlock(&u->reply_mutex);
++		break;
++	}
++
++	default:
++		if (msg_type == XS_TRANSACTION_START) {
++			trans = kmalloc(sizeof(*trans), GFP_KERNEL);
++			if (!trans) {
++				rc = -ENOMEM;
++				goto out;
++			}
++		}
++
++		reply = xenbus_dev_request_and_reply(&u->u.msg);
++		if (IS_ERR(reply)) {
++			kfree(trans);
++			rc = PTR_ERR(reply);
++			goto out;
++		}
++
++		if (msg_type == XS_TRANSACTION_START) {
++			trans->handle.id = simple_strtoul(reply, NULL, 0);
++			list_add(&trans->list, &u->transactions);
++		} else if (msg_type == XS_TRANSACTION_END) {
++			list_for_each_entry(trans, &u->transactions, list)
++				if (trans->handle.id == u->u.msg.tx_id)
++					break;
++			BUG_ON(&trans->list == &u->transactions);
++			list_del(&trans->list);
++			kfree(trans);
++		}
++		mutex_lock(&u->reply_mutex);
++		queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
++		queue_reply(u, (char *)reply, u->u.msg.len);
++		mutex_unlock(&u->reply_mutex);
++		kfree(reply);
++		break;
++	}
++
++ out:
++	u->len = 0;
++	return rc;
++}
++
++static int xenbus_dev_open(struct inode *inode, struct file *filp)
++{
++	struct xenbus_dev_data *u;
++
++	if (xen_store_evtchn == 0)
++		return -ENOENT;
++
++	nonseekable_open(inode, filp);
++
++	u = kzalloc(sizeof(*u), GFP_KERNEL);
++	if (u == NULL)
++		return -ENOMEM;
++
++	INIT_LIST_HEAD(&u->transactions);
++	INIT_LIST_HEAD(&u->watches);
++	INIT_LIST_HEAD(&u->read_buffers);
++	init_waitqueue_head(&u->read_waitq);
++
++	mutex_init(&u->reply_mutex);
++
++	filp->private_data = u;
++
++	return 0;
++}
++
++static int xenbus_dev_release(struct inode *inode, struct file *filp)
++{
++	struct xenbus_dev_data *u = filp->private_data;
++	struct xenbus_dev_transaction *trans, *tmp;
++	struct watch_adapter *watch, *tmp_watch;
++
++	list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
++		xenbus_transaction_end(trans->handle, 1);
++		list_del(&trans->list);
++		kfree(trans);
++	}
++
++	list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
++		unregister_xenbus_watch(&watch->watch);
++		list_del(&watch->list);
++		free_watch_adapter(watch);
++	}
++
++	kfree(u);
++
++	return 0;
++}
++
++static unsigned int xenbus_dev_poll(struct file *file, poll_table *wait)
++{
++	struct xenbus_dev_data *u = file->private_data;
++
++	if (!is_xenstored_ready())
++		return -ENODEV;
++
++	poll_wait(file, &u->read_waitq, wait);
++	if (!list_empty(&u->read_buffers))
++		return POLLIN | POLLRDNORM;
++	return 0;
++}
++
++#ifdef HAVE_UNLOCKED_IOCTL
++static long xenbus_dev_ioctl(struct file *file,
++                             unsigned int cmd, unsigned long data)
++{
++	extern int xenbus_conn(domid_t remote_dom, int *grant_ref,
++	                       evtchn_port_t *local_port);
++	void __user *udata = (void __user *) data;
++	int ret = -ENOTTY;
++	
++	if (!is_initial_xendomain())
++		return -ENODEV;
++
++
++	switch (cmd) {
++	case IOCTL_XENBUS_ALLOC: {
++		xenbus_alloc_t xa;
++		int old;
++
++		old = atomic_cmpxchg(&xenbus_xsd_state,
++		                     XENBUS_XSD_UNCOMMITTED,
++		                     XENBUS_XSD_FOREIGN_INIT);
++		if (old != XENBUS_XSD_UNCOMMITTED)
++			return -EBUSY;
++
++		if (copy_from_user(&xa, udata, sizeof(xa))) {
++			ret = -EFAULT;
++			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
++			break;
++		}
++
++		ret = xenbus_conn(xa.dom, &xa.grant_ref, &xa.port);
++		if (ret != 0) {
++			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
++			break;
++		}
++
++		if (copy_to_user(udata, &xa, sizeof(xa))) {
++			ret = -EFAULT;
++			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
++			break;
++		}
++	}
++	break;
++
++	default:
++		break;
++	}
++
++	return ret;
++}
++#endif
++
++static const struct file_operations xenbus_dev_file_ops = {
++	.read = xenbus_dev_read,
++	.write = xenbus_dev_write,
++	.open = xenbus_dev_open,
++	.release = xenbus_dev_release,
++	.poll = xenbus_dev_poll,
++#ifdef HAVE_UNLOCKED_IOCTL
++	.unlocked_ioctl = xenbus_dev_ioctl
++#endif
++};
++
++int xenbus_dev_init(void)
++{
++	xenbus_dev_intf = create_xen_proc_entry("xenbus", 0400);
++	if (xenbus_dev_intf)
++		xenbus_dev_intf->proc_fops = &xenbus_dev_file_ops;
++
++	return 0;
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe_backend.c	2008-01-21 11:15:26.000000000 +0100
+@@ -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);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:38:29.000000000 +0100
+@@ -0,0 +1,587 @@
++/**
++ * @file xenoprofile.c
++ *
++ * @remark Copyright 2002 OProfile authors
++ * @remark Read the file COPYING
++ *
++ * @author John Levon <levon@movementarian.org>
++ *
++ * Modified by Aravind Menon and Jose Renato Santos for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
++ * Separated out arch-generic part
++ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
++ *                    VA Linux Systems Japan K.K.
++ */
++
++#include <linux/init.h>
++#include <linux/notifier.h>
++#include <linux/smp.h>
++#include <linux/oprofile.h>
++#include <linux/sysdev.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/vmalloc.h>
++#include <asm/pgtable.h>
++#include <xen/evtchn.h>
++#include <xen/xenoprof.h>
++#include <xen/driver_util.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/xenoprof.h>
++#include "../../../drivers/oprofile/cpu_buffer.h"
++#include "../../../drivers/oprofile/event_buffer.h"
++
++#define MAX_XENOPROF_SAMPLES 16
++
++/* sample buffers shared with Xen */
++static xenoprof_buf_t **__read_mostly xenoprof_buf;
++/* Shared buffer area */
++static struct xenoprof_shared_buffer shared_buffer;
++
++/* Passive sample buffers shared with Xen */
++static xenoprof_buf_t **__read_mostly p_xenoprof_buf[MAX_OPROF_DOMAINS];
++/* Passive shared buffer area */
++static struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS];
++
++static int xenoprof_start(void);
++static void xenoprof_stop(void);
++
++static int xenoprof_enabled = 0;
++static int xenoprof_is_primary = 0;
++static int active_defined;
++
++extern unsigned long backtrace_depth;
++
++/* Number of buffers in shared area (one per VCPU) */
++static int nbuf;
++/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
++static int ovf_irq[NR_CPUS];
++/* cpu model type string - copied from Xen on XENOPROF_init command */
++static char cpu_type[XENOPROF_CPU_TYPE_SIZE];
++
++#ifdef CONFIG_PM
++
++static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
++{
++	if (xenoprof_enabled == 1)
++		xenoprof_stop();
++	return 0;
++}
++
++
++static int xenoprof_resume(struct sys_device * dev)
++{
++	if (xenoprof_enabled == 1)
++		xenoprof_start();
++	return 0;
++}
++
++
++static struct sysdev_class oprofile_sysclass = {
++	set_kset_name("oprofile"),
++	.resume		= xenoprof_resume,
++	.suspend	= xenoprof_suspend
++};
++
++
++static struct sys_device device_oprofile = {
++	.id	= 0,
++	.cls	= &oprofile_sysclass,
++};
++
++
++static int __init init_driverfs(void)
++{
++	int error;
++	if (!(error = sysdev_class_register(&oprofile_sysclass)))
++		error = sysdev_register(&device_oprofile);
++	return error;
++}
++
++
++static void exit_driverfs(void)
++{
++	sysdev_unregister(&device_oprofile);
++	sysdev_class_unregister(&oprofile_sysclass);
++}
++
++#else
++#define init_driverfs() do { } while (0)
++#define exit_driverfs() do { } while (0)
++#endif /* CONFIG_PM */
++
++static unsigned long long oprofile_samples;
++static unsigned long long p_oprofile_samples;
++
++static unsigned int pdomains;
++static struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
++
++/* Check whether the given entry is an escape code */
++static int xenoprof_is_escape(xenoprof_buf_t * buf, int tail)
++{
++	return (buf->event_log[tail].eip == XENOPROF_ESCAPE_CODE);
++}
++
++/* Get the event at the given entry  */
++static uint8_t xenoprof_get_event(xenoprof_buf_t * buf, int tail)
++{
++	return (buf->event_log[tail].event);
++}
++
++static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
++{
++	int head, tail, size;
++	int tracing = 0;
++
++	head = buf->event_head;
++	tail = buf->event_tail;
++	size = buf->event_size;
++
++	while (tail != head) {
++		if (xenoprof_is_escape(buf, tail) &&
++		    xenoprof_get_event(buf, tail) == XENOPROF_TRACE_BEGIN) {
++			tracing=1;
++			oprofile_add_pc(ESCAPE_CODE, buf->event_log[tail].mode, 
++					CPU_TRACE_BEGIN); 
++			if (!is_passive)
++				oprofile_samples++;
++			else
++				p_oprofile_samples++;
++			
++		} else {
++			oprofile_add_pc(buf->event_log[tail].eip,
++					buf->event_log[tail].mode,
++					buf->event_log[tail].event);
++			if (!tracing) {
++				if (!is_passive)
++					oprofile_samples++;
++				else
++					p_oprofile_samples++;
++			}
++       
++		}
++		tail++;
++		if(tail==size)
++		    tail=0;
++	}
++	buf->event_tail = tail;
++}
++
++static void xenoprof_handle_passive(void)
++{
++	int i, j;
++	int flag_domain, flag_switch = 0;
++	
++	for (i = 0; i < pdomains; i++) {
++		flag_domain = 0;
++		for (j = 0; j < passive_domains[i].nbuf; j++) {
++			xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
++			if (buf->event_head == buf->event_tail)
++				continue;
++			if (!flag_domain) {
++				if (!oprofile_add_domain_switch(
++					passive_domains[i].domain_id))
++					goto done;
++				flag_domain = 1;
++			}
++			xenoprof_add_pc(buf, 1);
++			flag_switch = 1;
++		}
++	}
++done:
++	if (flag_switch)
++		oprofile_add_domain_switch(COORDINATOR_DOMAIN);
++}
++
++static irqreturn_t 
++xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
++{
++	struct xenoprof_buf * buf;
++	static unsigned long flag;
++
++	buf = xenoprof_buf[smp_processor_id()];
++
++	xenoprof_add_pc(buf, 0);
++
++	if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) {
++		xenoprof_handle_passive();
++		smp_mb__before_clear_bit();
++		clear_bit(0, &flag);
++	}
++
++	return IRQ_HANDLED;
++}
++
++
++static void unbind_virq(void)
++{
++	unsigned int i;
++
++	for_each_online_cpu(i) {
++		if (ovf_irq[i] >= 0) {
++			unbind_from_irqhandler(ovf_irq[i], NULL);
++			ovf_irq[i] = -1;
++		}
++	}
++}
++
++
++static int bind_virq(void)
++{
++	unsigned int i;
++	int result;
++
++	for_each_online_cpu(i) {
++		result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
++						 i,
++						 xenoprof_ovf_interrupt,
++						 SA_INTERRUPT,
++						 "xenoprof",
++						 NULL);
++
++		if (result < 0) {
++			unbind_virq();
++			return result;
++		}
++
++		ovf_irq[i] = result;
++	}
++		
++	return 0;
++}
++
++
++static xenoprof_buf_t **get_buffer_array(unsigned int nbuf)
++{
++	size_t size = nbuf * sizeof(xenoprof_buf_t);
++
++	if (size <= PAGE_SIZE)
++		return kmalloc(size, GFP_KERNEL);
++	return vmalloc(size);
++}
++
++static void release_buffer_array(xenoprof_buf_t **buf, unsigned int nbuf)
++{
++	if (nbuf * sizeof(xenoprof_buf_t) <= PAGE_SIZE)
++		kfree(buf);
++	else
++		vfree(buf);
++}
++
++
++static void unmap_passive_list(void)
++{
++	int i;
++	for (i = 0; i < pdomains; i++) {
++		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
++		release_buffer_array(p_xenoprof_buf[i],
++				     passive_domains[i].nbuf);
++	}
++	pdomains = 0;
++}
++
++
++static int map_xenoprof_buffer(int max_samples)
++{
++	struct xenoprof_get_buffer get_buffer;
++	struct xenoprof_buf *buf;
++	int ret, i;
++
++	if ( shared_buffer.buffer )
++		return 0;
++
++	get_buffer.max_samples = max_samples;
++	ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer);
++	if (ret)
++		return ret;
++	nbuf = get_buffer.nbuf;
++
++	xenoprof_buf = get_buffer_array(nbuf);
++	if (!xenoprof_buf) {
++		xenoprof_arch_unmap_shared_buffer(&shared_buffer);
++		return -ENOMEM;
++	}
++
++	for (i=0; i< nbuf; i++) {
++		buf = (struct xenoprof_buf*) 
++			&shared_buffer.buffer[i * get_buffer.bufsize];
++		BUG_ON(buf->vcpu_id >= nbuf);
++		xenoprof_buf[buf->vcpu_id] = buf;
++	}
++
++	return 0;
++}
++
++
++static int xenoprof_setup(void)
++{
++	int ret;
++
++	if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
++		return ret;
++
++	if ( (ret = bind_virq()) ) {
++		release_buffer_array(xenoprof_buf, nbuf);
++		return ret;
++	}
++
++	if (xenoprof_is_primary) {
++		/* Define dom0 as an active domain if not done yet */
++		if (!active_defined) {
++			domid_t domid;
++			ret = HYPERVISOR_xenoprof_op(
++				XENOPROF_reset_active_list, NULL);
++			if (ret)
++				goto err;
++			domid = 0;
++			ret = HYPERVISOR_xenoprof_op(
++				XENOPROF_set_active, &domid);
++			if (ret)
++				goto err;
++			active_defined = 1;
++		}
++
++		if (backtrace_depth > 0) {
++			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_backtrace, 
++						     &backtrace_depth);
++			if (ret)
++				backtrace_depth = 0;
++		}
++
++		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
++		if (ret)
++			goto err;
++		
++		xenoprof_arch_counter();
++		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
++		if (ret)
++			goto err;
++	}
++
++	ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
++	if (ret)
++		goto err;
++
++	xenoprof_enabled = 1;
++	return 0;
++ err:
++	unbind_virq();
++	release_buffer_array(xenoprof_buf, nbuf);
++	return ret;
++}
++
++
++static void xenoprof_shutdown(void)
++{
++	xenoprof_enabled = 0;
++
++	WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL));
++
++	if (xenoprof_is_primary) {
++		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_release_counters,
++					       NULL));
++		active_defined = 0;
++	}
++
++	unbind_virq();
++
++	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
++	if (xenoprof_is_primary)
++		unmap_passive_list();
++	release_buffer_array(xenoprof_buf, nbuf);
++}
++
++
++static int xenoprof_start(void)
++{
++	int ret = 0;
++
++	if (xenoprof_is_primary)
++		ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
++	if (!ret)
++		xenoprof_arch_start();
++	return ret;
++}
++
++
++static void xenoprof_stop(void)
++{
++	if (xenoprof_is_primary)
++		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL));
++	xenoprof_arch_stop();
++}
++
++
++static int xenoprof_set_active(int * active_domains,
++			       unsigned int adomains)
++{
++	int ret = 0;
++	int i;
++	int set_dom0 = 0;
++	domid_t domid;
++
++	if (!xenoprof_is_primary)
++		return 0;
++
++	if (adomains > MAX_OPROF_DOMAINS)
++		return -E2BIG;
++
++	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
++	if (ret)
++		return ret;
++
++	for (i=0; i<adomains; i++) {
++		domid = active_domains[i];
++		if (domid != active_domains[i]) {
++			ret = -EINVAL;
++			goto out;
++		}
++		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
++		if (ret)
++			goto out;
++		if (active_domains[i] == 0)
++			set_dom0 = 1;
++	}
++	/* dom0 must always be active but may not be in the list */ 
++	if (!set_dom0) {
++		domid = 0;
++		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
++	}
++
++out:
++	if (ret)
++		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list,
++					       NULL));
++	active_defined = !ret;
++	return ret;
++}
++
++static int xenoprof_set_passive(int * p_domains,
++                                unsigned int pdoms)
++{
++	int ret;
++	unsigned int i, j;
++	struct xenoprof_buf *buf;
++
++	if (!xenoprof_is_primary)
++        	return 0;
++
++	if (pdoms > MAX_OPROF_DOMAINS)
++		return -E2BIG;
++
++	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
++	if (ret)
++		return ret;
++	unmap_passive_list();
++
++	for (i = 0; i < pdoms; i++) {
++		passive_domains[i].domain_id = p_domains[i];
++		passive_domains[i].max_samples = 2048;
++		ret = xenoprof_arch_set_passive(&passive_domains[i],
++						&p_shared_buffer[i]);
++		if (ret)
++			goto out;
++
++		p_xenoprof_buf[i] = get_buffer_array(passive_domains[i].nbuf);
++		if (!p_xenoprof_buf[i]) {
++			++i;
++			ret = -ENOMEM;
++			goto out;
++		}
++
++		for (j = 0; j < passive_domains[i].nbuf; j++) {
++			buf = (struct xenoprof_buf *)
++				&p_shared_buffer[i].buffer[
++				j * passive_domains[i].bufsize];
++			BUG_ON(buf->vcpu_id >= passive_domains[i].nbuf);
++			p_xenoprof_buf[i][buf->vcpu_id] = buf;
++		}
++	}
++
++	pdomains = pdoms;
++	return 0;
++
++out:
++	for (j = 0; j < i; j++) {
++		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
++		release_buffer_array(p_xenoprof_buf[i],
++				     passive_domains[i].nbuf);
++	}
++
++	return ret;
++}
++
++
++/* The dummy backtrace function to keep oprofile happy
++ * The real backtrace is done in xen
++ */
++static void xenoprof_dummy_backtrace(struct pt_regs * const regs, 
++				     unsigned int depth)
++{
++	/* this should never be called */
++	BUG();
++	return;
++}
++
++
++static struct oprofile_operations xenoprof_ops = {
++#ifdef HAVE_XENOPROF_CREATE_FILES
++	.create_files 	= xenoprof_create_files,
++#endif
++	.set_active	= xenoprof_set_active,
++	.set_passive    = xenoprof_set_passive,
++	.setup 		= xenoprof_setup,
++	.shutdown	= xenoprof_shutdown,
++	.start		= xenoprof_start,
++	.stop		= xenoprof_stop,
++	.backtrace	= xenoprof_dummy_backtrace
++};
++
++
++/* in order to get driverfs right */
++static int using_xenoprof;
++
++int __init xenoprofile_init(struct oprofile_operations * ops)
++{
++	struct xenoprof_init init;
++	unsigned int i;
++	int ret;
++
++	ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
++	if (!ret) {
++		xenoprof_arch_init_counter(&init);
++		xenoprof_is_primary = init.is_primary;
++
++		/*  cpu_type is detected by Xen */
++		cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
++		strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
++		xenoprof_ops.cpu_type = cpu_type;
++
++		init_driverfs();
++		using_xenoprof = 1;
++		*ops = xenoprof_ops;
++
++		for (i=0; i<NR_CPUS; i++)
++			ovf_irq[i] = -1;
++
++		active_defined = 0;
++	}
++
++	printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n",
++	       __func__, ret, init.num_events, xenoprof_is_primary);
++	return ret;
++}
++
++
++void xenoprofile_exit(void)
++{
++	if (using_xenoprof)
++		exit_driverfs();
++
++	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
++	if (xenoprof_is_primary) {
++		unmap_passive_list();
++		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL));
++        }
++}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-blkback-cdrom
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-blkback-cdrom
@@ -0,0 +1,260 @@
+Subject: CDROM removable media-present attribute plus handling code
+From: plc@novell.com
+Patch-mainline: obsolete
+References: 159907
+
+--- head-2010-01-04.orig/drivers/xen/blkback/Makefile	2009-06-09 15:01:37.000000000 +0200
++++ head-2010-01-04/drivers/xen/blkback/Makefile	2009-06-09 15:50:31.000000000 +0200
+@@ -1,4 +1,4 @@
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o
+ obj-$(CONFIG_XEN_BLKBACK_PAGEMAP) += blkback-pagemap.o
+ 
+-blkbk-y	:= blkback.o xenbus.o interface.o vbd.o
++blkbk-y	:= blkback.o xenbus.o interface.o vbd.o cdrom.o
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-04/drivers/xen/blkback/cdrom.c	2009-06-09 15:50:31.000000000 +0200
+@@ -0,0 +1,162 @@
++/******************************************************************************
++ * blkback/cdrom.c
++ *
++ * Routines for managing cdrom watch and media-present attribute of a
++ * cdrom type virtual block device (VBD).
++ *
++ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand
++ * Copyright (c) 2007       Pat Campbell
++ *
++ * 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 "common.h"
++
++#undef DPRINTK
++#define DPRINTK(_f, _a...)			\
++	printk("(%s() file=%s, line=%d) " _f "\n",	\
++		 __PRETTY_FUNCTION__, __FILE__ , __LINE__ , ##_a )
++
++
++#define MEDIA_PRESENT "media-present"
++
++static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int);
++
++/**
++ * Writes media-present=1 attribute for the given vbd device if not
++ * already there
++ */
++static int cdrom_xenstore_write_media_present(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	struct xenbus_transaction xbt;
++	int err;
++	int media_present;
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
++			   &media_present);
++	if (0 < err) {
++		DPRINTK("already written err%d", err);
++		return(0);
++	}
++	media_present = 1;
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		return(-1);
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present );
++	if (err) {
++		xenbus_dev_fatal(dev, err, "writing %s/%s",
++			 dev->nodename, MEDIA_PRESENT);
++		goto abort;
++	}
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++	if (err)
++		xenbus_dev_fatal(dev, err, "ending transaction");
++	return 0;
++ abort:
++	xenbus_transaction_end(xbt, 1);
++	return -1;
++}
++
++/**
++ *
++ */
++static int cdrom_is_type(struct backend_info *be)
++{
++	DPRINTK("type:%x", be->blkif->vbd.type );
++	return (be->blkif->vbd.type & VDISK_CDROM)
++	       && (be->blkif->vbd.type & GENHD_FL_REMOVABLE);
++}
++
++/**
++ *
++ */
++void cdrom_add_media_watch(struct backend_info *be)
++{
++	struct xenbus_device *dev = be->dev;
++	int err;
++
++	DPRINTK("nodename:%s", dev->nodename);
++	if (cdrom_is_type(be)) {
++		DPRINTK("is a cdrom");
++		if ( cdrom_xenstore_write_media_present(be) == 0 ) {
++			DPRINTK( "xenstore wrote OK");
++			err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT,
++						 &be->backend_cdrom_watch,
++						 cdrom_media_changed);
++			if (err)
++				DPRINTK( "media_present watch add failed" );
++		}
++	}
++}
++
++/**
++ * Callback received when the "media_present" xenstore node is changed
++ */
++static void cdrom_media_changed(struct xenbus_watch *watch,
++				const char **vec, unsigned int len)
++{
++	int err;
++	unsigned media_present;
++	struct backend_info *be
++		= container_of(watch, struct backend_info, backend_cdrom_watch);
++	struct xenbus_device *dev = be->dev;
++
++	if (!cdrom_is_type(be)) {
++		DPRINTK("callback not for a cdrom" );
++		return;
++	}
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d",
++			   &media_present);
++	if (err == 0 || err == -ENOENT) {
++		DPRINTK("xenbus_read of cdrom media_present node error:%d",err);
++		return;
++	}
++
++	if (media_present == 0)
++		vbd_free(&be->blkif->vbd);
++	else {
++		char *p = strrchr(dev->otherend, '/') + 1;
++		long handle = simple_strtoul(p, NULL, 0);
++
++		if (!be->blkif->vbd.bdev) {
++			err = vbd_create(be->blkif, handle, be->major, be->minor,
++					 !strchr(be->mode, 'w'), 1);
++			if (err) {
++				be->major = be->minor = 0;
++				xenbus_dev_fatal(dev, err, "creating vbd structure");
++				return;
++			}
++		}
++	}
++}
+--- head-2010-01-04.orig/drivers/xen/blkback/common.h	2010-01-04 12:30:12.000000000 +0100
++++ head-2010-01-04/drivers/xen/blkback/common.h	2010-01-04 13:22:13.000000000 +0100
+@@ -100,6 +100,17 @@ typedef struct blkif_st {
+ 	grant_ref_t    shmem_ref;
+ } blkif_t;
+ 
++struct backend_info
++{
++	struct xenbus_device *dev;
++	blkif_t *blkif;
++	struct xenbus_watch backend_watch;
++	struct xenbus_watch backend_cdrom_watch;
++	unsigned major;
++	unsigned minor;
++	char *mode;
++};
++
+ blkif_t *blkif_alloc(domid_t domid);
+ void blkif_disconnect(blkif_t *blkif);
+ void blkif_free(blkif_t *blkif);
+@@ -140,4 +151,7 @@ int blkif_schedule(void *arg);
+ int blkback_barrier(struct xenbus_transaction xbt,
+ 		    struct backend_info *be, int state);
+ 
++/* cdrom media change */
++void cdrom_add_media_watch(struct backend_info *be);
++
+ #endif /* __BLKIF__BACKEND__COMMON_H__ */
+--- head-2010-01-04.orig/drivers/xen/blkback/vbd.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-04/drivers/xen/blkback/vbd.c	2009-06-09 15:50:31.000000000 +0200
+@@ -107,6 +107,9 @@ int vbd_translate(struct phys_req *req, 
+ 	if ((operation != READ) && vbd->readonly)
+ 		goto out;
+ 
++	if (vbd->bdev == NULL)
++		goto out;
++
+ 	if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
+ 		goto out;
+ 
+--- head-2010-01-04.orig/drivers/xen/blkback/xenbus.c	2008-09-15 15:10:39.000000000 +0200
++++ head-2010-01-04/drivers/xen/blkback/xenbus.c	2009-06-09 15:50:31.000000000 +0200
+@@ -28,16 +28,6 @@
+ 	pr_debug("blkback/xenbus (%s:%d) " fmt ".\n",	\
+ 		 __FUNCTION__, __LINE__, ##args)
+ 
+-struct backend_info
+-{
+-	struct xenbus_device *dev;
+-	blkif_t *blkif;
+-	struct xenbus_watch backend_watch;
+-	unsigned major;
+-	unsigned minor;
+-	char *mode;
+-};
+-
+ static void connect(struct backend_info *);
+ static int connect_ring(struct backend_info *);
+ static void backend_changed(struct xenbus_watch *, const char **,
+@@ -183,6 +173,12 @@ static int blkback_remove(struct xenbus_
+ 		be->backend_watch.node = NULL;
+ 	}
+ 
++	if (be->backend_cdrom_watch.node) {
++		unregister_xenbus_watch(&be->backend_cdrom_watch);
++		kfree(be->backend_cdrom_watch.node);
++		be->backend_cdrom_watch.node = NULL;
++	}
++
+ 	if (be->blkif) {
+ 		blkif_disconnect(be->blkif);
+ 		vbd_free(&be->blkif->vbd);
+@@ -339,6 +335,9 @@ static void backend_changed(struct xenbu
+ 
+ 		/* We're potentially connected now */
+ 		update_blkif_status(be->blkif);
++
++		/* Add watch for cdrom media status if necessay */
++		cdrom_add_media_watch(be);
+ 	}
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.13-14
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.13-14
@@ -0,0 +1,29 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.14
+Patch-mainline: 2.6.32.14
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.13-14" by xen-port-patches.py
+
+--- sle11sp1-2010-08-06.orig/arch/x86/kernel/process-xen.c	2010-04-12 14:52:38.000000000 +0200
++++ sle11sp1-2010-08-06/arch/x86/kernel/process-xen.c	2010-08-06 17:06:45.000000000 +0200
+@@ -443,11 +443,13 @@ static int __cpuinit check_c1e_idle(cons
+ 		 * check OSVW bit for CPUs that are not affected
+ 		 * by erratum #400
+ 		 */
+-		rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
+-		if (val >= 2) {
+-			rdmsrl(MSR_AMD64_OSVW_STATUS, val);
+-			if (!(val & BIT(1)))
+-				goto no_c1e_idle;
++		if (cpu_has(c, X86_FEATURE_OSVW)) {
++			rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
++			if (val >= 2) {
++				rdmsrl(MSR_AMD64_OSVW_STATUS, val);
++				if (!(val & BIT(1)))
++					goto no_c1e_idle;
++			}
+ 		}
+ 		return 1;
+ 	}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.20
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.20
@@ -0,0 +1,7156 @@
+From: www.kernel.org
+Subject: Linux 2.6.20
+Patch-mainline: 2.6.20
+
+Automatically created from "patches.kernel.org/patch-2.6.20" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:00:05.000000000 +0100
+@@ -1657,6 +1657,7 @@ config PHYSICAL_START
+ 
+ config RELOCATABLE
+ 	bool "Build a relocatable kernel"
++	depends on !X86_XEN
+ 	default y
+ 	---help---
+ 	  This builds a kernel image that retains relocation information
+@@ -1679,7 +1680,8 @@ config X86_NEED_RELOCS
+ 
+ config PHYSICAL_ALIGN
+ 	hex
+-	prompt "Alignment value to which kernel should be aligned" if X86_32
++	prompt "Alignment value to which kernel should be aligned" if X86_32 && !XEN
++	default 0x2000 if XEN
+ 	default "0x1000000"
+ 	range 0x2000 0x1000000
+ 	---help---
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_32.c	2009-12-04 10:44:46.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:46:27.000000000 +0100
+@@ -55,6 +55,7 @@ void foo(void)
+ 	OFFSET(TI_exec_domain, thread_info, exec_domain);
+ 	OFFSET(TI_flags, thread_info, flags);
+ 	OFFSET(TI_status, thread_info, status);
++	OFFSET(TI_cpu, thread_info, cpu);
+ 	OFFSET(TI_preempt_count, thread_info, preempt_count);
+ 	OFFSET(TI_addr_limit, thread_info, addr_limit);
+ 	OFFSET(TI_restart_block, thread_info, restart_block);
+@@ -110,6 +111,11 @@ void foo(void)
+ 
+ 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+ 
++#ifdef CONFIG_XEN
++	BLANK();
++	OFFSET(XEN_START_mfn_list, start_info, mfn_list);
++#endif
++
+ #ifdef CONFIG_PARAVIRT
+ 	BLANK();
+ 	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -22,6 +22,7 @@
+ #define phys_pkg_id(a,b) a
+ #endif
+ #endif
++#include <asm/pda.h>
+ #include <asm/hypervisor.h>
+ 
+ #include "cpu.h"
+@@ -29,10 +30,8 @@
+ DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
+ EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
+ 
+-#ifndef CONFIG_XEN
+-DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+-EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+-#endif
++struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly;
++EXPORT_SYMBOL(_cpu_pda);
+ 
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_fxsr __cpuinitdata;
+@@ -60,7 +59,7 @@ static struct cpu_dev __cpuinitdata defa
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
+ };
+-static struct cpu_dev * this_cpu = &default_cpu;
++static struct cpu_dev * this_cpu __cpuinitdata = &default_cpu;
+ 
+ static int __init cachesize_setup(char *str)
+ {
+@@ -242,29 +241,14 @@ static int __cpuinit have_cpuid_p(void)
+ 	return flag_is_changeable_p(X86_EFLAGS_ID);
+ }
+ 
+-/* Do minimum CPU detection early.
+-   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
+-   The others are not touched to avoid unwanted side effects.
+-
+-   WARNING: this function is only called on the BP.  Don't add code here
+-   that is supposed to run on all CPUs. */
+-static void __init early_cpu_detect(void)
++void __init cpu_detect(struct cpuinfo_x86 *c)
+ {
+-	struct cpuinfo_x86 *c = &boot_cpu_data;
+-
+-	c->x86_cache_alignment = 32;
+-
+-	if (!have_cpuid_p())
+-		return;
+-
+ 	/* Get vendor name */
+ 	cpuid(0x00000000, &c->cpuid_level,
+ 	      (int *)&c->x86_vendor_id[0],
+ 	      (int *)&c->x86_vendor_id[8],
+ 	      (int *)&c->x86_vendor_id[4]);
+ 
+-	get_cpu_vendor(c, 1);
+-
+ 	c->x86 = 4;
+ 	if (c->cpuid_level >= 0x00000001) {
+ 		u32 junk, tfms, cap0, misc;
+@@ -281,6 +265,26 @@ static void __init early_cpu_detect(void
+ 	}
+ }
+ 
++/* Do minimum CPU detection early.
++   Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
++   The others are not touched to avoid unwanted side effects.
++
++   WARNING: this function is only called on the BP.  Don't add code here
++   that is supposed to run on all CPUs. */
++static void __init early_cpu_detect(void)
++{
++	struct cpuinfo_x86 *c = &boot_cpu_data;
++
++	c->x86_cache_alignment = 32;
++
++	if (!have_cpuid_p())
++		return;
++
++	cpu_detect(c);
++
++	get_cpu_vendor(c, 1);
++}
++
+ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ {
+ 	u32 tfms, xlvl;
+@@ -317,6 +321,8 @@ static void __cpuinit generic_identify(s
+ 			c->apicid = (ebx >> 24) & 0xFF;
+ #endif
+ #endif
++			if (c->x86_capability[0] & (1<<19))
++				c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+ 		} else {
+ 			/* Have CPUID level 0 only - unheard of */
+ 			c->x86 = 4;
+@@ -381,6 +387,7 @@ void __cpuinit identify_cpu(struct cpuin
+ 	c->x86_vendor_id[0] = '\0'; /* Unset */
+ 	c->x86_model_id[0] = '\0';  /* Unset */
+ 	c->x86_max_cores = 1;
++	c->x86_clflush_size = 32;
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ 
+ 	if (!have_cpuid_p()) {
+@@ -601,61 +608,23 @@ void __init early_cpu_init(void)
+ #endif
+ }
+ 
+-static void __cpuinit cpu_gdt_init(const struct Xgt_desc_struct *gdt_descr)
++/* Make sure %gs is initialized properly in idle threads */
++struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+ {
+-	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_lowmem_page_readonly(
+-			(void *)va, XENFEAT_writable_descriptor_tables);
+-	}
+-	if (HYPERVISOR_set_gdt(frames, (gdt_descr->size + 1) / 8))
+-		BUG();
++	memset(regs, 0, sizeof(struct pt_regs));
++	regs->xgs = __KERNEL_PDA;
++	return regs;
+ }
+ 
+-/*
+- * 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.
+- */
+-void __cpuinit cpu_init(void)
++static __cpuinit int alloc_gdt(int cpu)
+ {
+-	int cpu = smp_processor_id();
+-#ifndef CONFIG_X86_NO_TSS
+-	struct tss_struct * t = &per_cpu(init_tss, cpu);
+-#endif
+-	struct thread_struct *thread = &current->thread;
+-	struct desc_struct *gdt;
+ 	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++	struct desc_struct *gdt;
++	struct i386_pda *pda;
+ 
+-	if (cpu_test_and_set(cpu, cpu_initialized)) {
+-		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+-		for (;;) local_irq_enable();
+-	}
+-	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+-
+-	if (cpu_has_vme || cpu_has_de)
+-		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+-	if (tsc_disable && cpu_has_tsc) {
+-		printk(KERN_NOTICE "Disabling TSC...\n");
+-		/**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
+-		clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+-		set_in_cr4(X86_CR4_TSD);
+-	}
++	gdt = (struct desc_struct *)cpu_gdt_descr->address;
++	pda = cpu_pda(cpu);
+ 
+-#ifndef CONFIG_XEN
+-	/* The CPU hotplug case */
+-	if (cpu_gdt_descr->address) {
+-		gdt = (struct desc_struct *)cpu_gdt_descr->address;
+-		memset(gdt, 0, PAGE_SIZE);
+-		goto old_gdt;
+-	}
+ 	/*
+ 	 * This is a horrible hack to allocate the GDT.  The problem
+ 	 * is that cpu_init() is called really early for the boot CPU
+@@ -663,54 +632,141 @@ void __cpuinit cpu_init(void)
+ 	 * CPUs, when bootmem will have gone away
+ 	 */
+ 	if (NODE_DATA(0)->bdata->node_bootmem_map) {
+-		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
+-		/* alloc_bootmem_pages panics on failure, so no check */
++		BUG_ON(gdt != NULL || pda != NULL);
++
++		gdt = alloc_bootmem_pages(PAGE_SIZE);
++		pda = alloc_bootmem(sizeof(*pda));
++		/* alloc_bootmem(_pages) panics on failure, so no check */
++
+ 		memset(gdt, 0, PAGE_SIZE);
++		memset(pda, 0, sizeof(*pda));
+ 	} else {
+-		gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
+-		if (unlikely(!gdt)) {
+-			printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
+-			for (;;)
+-				local_irq_enable();
++		/* GDT and PDA might already have been allocated if
++		   this is a CPU hotplug re-insertion. */
++		if (gdt == NULL)
++			gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
++
++		if (pda == NULL)
++			pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu));
++
++		if (unlikely(!gdt || !pda)) {
++			free_pages((unsigned long)gdt, 0);
++			kfree(pda);
++			return 0;
+ 		}
+ 	}
+-old_gdt:
++
++ 	cpu_gdt_descr->address = (unsigned long)gdt;
++	cpu_pda(cpu) = pda;
++
++	return 1;
++}
++
++/* Initial PDA used by boot CPU */
++struct i386_pda boot_pda = {
++	._pda = &boot_pda,
++	.cpu_number = 0,
++	.pcurrent = &init_task,
++};
++
++static inline void set_kernel_gs(void)
++{
++	/* Set %gs for this CPU's PDA.  Memory clobber is to create a
++	   barrier with respect to any PDA operations, so the compiler
++	   doesn't move any before here. */
++	asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
++}
++
++/* Initialize the CPU's GDT and PDA.  The boot CPU does this for
++   itself, but secondaries find this done for them. */
++__cpuinit int init_gdt(int cpu, struct task_struct *idle)
++{
++	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++	struct desc_struct *gdt;
++	struct i386_pda *pda;
++
++	/* For non-boot CPUs, the GDT and PDA should already have been
++	   allocated. */
++	if (!alloc_gdt(cpu)) {
++		printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu);
++		return 0;
++	}
++
++	gdt = (struct desc_struct *)cpu_gdt_descr->address;
++	pda = cpu_pda(cpu);
++
++	BUG_ON(gdt == NULL || pda == NULL);
++
+ 	/*
+ 	 * Initialize the per-CPU GDT with the boot GDT,
+ 	 * and set up the GDT descriptor:
+ 	 */
+  	memcpy(gdt, cpu_gdt_table, GDT_SIZE);
++	cpu_gdt_descr->size = GDT_SIZE - 1;
+ 
+-	/* Set up GDT entry for 16bit stack */
+- 	*(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
+-		((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
+-		((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
+-		(CPU_16BIT_STACK_SIZE - 1);
++	pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a,
++			(u32 *)&gdt[GDT_ENTRY_PDA].b,
++			(unsigned long)pda, sizeof(*pda) - 1,
++			0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */
++
++	memset(pda, 0, sizeof(*pda));
++	pda->_pda = pda;
++	pda->cpu_number = cpu;
++	pda->pcurrent = idle;
+ 
+-	cpu_gdt_descr->size = GDT_SIZE - 1;
+- 	cpu_gdt_descr->address = (unsigned long)gdt;
+-#else
+-	if (cpu == 0 && cpu_gdt_descr->address == 0) {
+-		gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
+-		/* alloc_bootmem_pages panics on failure, so no check */
+-		memset(gdt, 0, PAGE_SIZE);
++	return 1;
++}
+ 
+-		memcpy(gdt, cpu_gdt_table, GDT_SIZE);
+-		
+-		cpu_gdt_descr->size = GDT_SIZE;
+-		cpu_gdt_descr->address = (unsigned long)gdt;
++void __cpuinit cpu_set_gdt(int cpu)
++{
++	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++	unsigned long va, frames[16];
++	int f;
++
++	for (va = cpu_gdt_descr->address, f = 0;
++	     va < cpu_gdt_descr->address + cpu_gdt_descr->size;
++	     va += PAGE_SIZE, f++) {
++		frames[f] = virt_to_mfn(va);
++		make_lowmem_page_readonly(
++			(void *)va, XENFEAT_writable_descriptor_tables);
+ 	}
++	BUG_ON(HYPERVISOR_set_gdt(frames, (cpu_gdt_descr->size + 1) / 8));
++
++	set_kernel_gs();
++}
++
++/* Common CPU init for both boot and secondary CPUs */
++static void __cpuinit _cpu_init(int cpu, struct task_struct *curr)
++{
++#ifndef CONFIG_X86_NO_TSS
++	struct tss_struct * t = &per_cpu(init_tss, cpu);
+ #endif
++	struct thread_struct *thread = &curr->thread;
++
++	if (cpu_test_and_set(cpu, cpu_initialized)) {
++		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
++		for (;;) local_irq_enable();
++	}
+ 
+-	cpu_gdt_init(cpu_gdt_descr);
++	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
++
++	if (cpu_has_vme || cpu_has_de)
++		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
++	if (tsc_disable && cpu_has_tsc) {
++		printk(KERN_NOTICE "Disabling TSC...\n");
++		/**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
++		clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
++		set_in_cr4(X86_CR4_TSD);
++	}
+ 
+ 	/*
+ 	 * Set up and load the per-CPU TSS and LDT
+ 	 */
+ 	atomic_inc(&init_mm.mm_count);
+-	current->active_mm = &init_mm;
+-	BUG_ON(current->mm);
+-	enter_lazy_tlb(&init_mm, current);
++	curr->active_mm = &init_mm;
++	if (curr->mm)
++		BUG();
++	enter_lazy_tlb(&init_mm, curr);
+ 
+ 	load_esp0(t, thread);
+ 
+@@ -721,8 +777,8 @@ old_gdt:
+ 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+ #endif
+ 
+-	/* Clear %fs and %gs. */
+-	asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
++	/* Clear %fs. */
++	asm volatile ("mov %0, %%fs" : : "r" (0));
+ 
+ 	/* Clear all 6 debug registers: */
+ 	set_debugreg(0, 0);
+@@ -740,6 +796,38 @@ old_gdt:
+ 	mxcsr_feature_mask_init();
+ }
+ 
++/* Entrypoint to initialize secondary CPU */
++void __cpuinit secondary_cpu_init(void)
++{
++	int cpu = smp_processor_id();
++	struct task_struct *curr = current;
++
++	_cpu_init(cpu, curr);
++}
++
++/*
++ * 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.
++ */
++void __cpuinit cpu_init(void)
++{
++	int cpu = smp_processor_id();
++	struct task_struct *curr = current;
++
++	/* Set up the real GDT and PDA, so we can transition from the
++	   boot versions. */
++	if (!init_gdt(cpu, curr)) {
++		/* failed to allocate something; not much we can do... */
++		for (;;)
++			local_irq_enable();
++	}
++
++	cpu_set_gdt(cpu);
++	_cpu_init(cpu, curr);
++}
++
+ #ifdef CONFIG_HOTPLUG_CPU
+ void __cpuinit cpu_uninit(void)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2008-01-28 12:24:18.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -12,7 +12,7 @@
+ static DEFINE_MUTEX(mtrr_mutex);
+ 
+ void generic_get_mtrr(unsigned int reg, unsigned long *base,
+-		      unsigned int *size, mtrr_type * type)
++		      unsigned long *size, mtrr_type * type)
+ {
+ 	struct xen_platform_op op;
+ 
+@@ -115,8 +115,7 @@ int mtrr_del_page(int reg, unsigned long
+ {
+ 	unsigned i;
+ 	mtrr_type ltype;
+-	unsigned long lbase;
+-	unsigned int lsize;
++	unsigned long lbase, lsize;
+ 	int error = -EINVAL;
+ 	struct xen_platform_op op;
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -0,0 +1,1002 @@
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/string.h>
++#include <linux/kexec.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/efi.h>
++#include <linux/pfn.h>
++#include <linux/uaccess.h>
++
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/e820.h>
++#include <xen/interface/memory.h>
++
++#ifdef CONFIG_EFI
++int efi_enabled = 0;
++EXPORT_SYMBOL(efi_enabled);
++#endif
++
++struct e820map e820;
++struct change_member {
++	struct e820entry *pbios; /* pointer to original bios entry */
++	unsigned long long addr; /* address for this change point */
++};
++static struct change_member change_point_list[2*E820MAX] __initdata;
++static struct change_member *change_point[2*E820MAX] __initdata;
++static struct e820entry *overlap_list[E820MAX] __initdata;
++static struct e820entry new_bios[E820MAX] __initdata;
++/* For PCI or other memory-mapped resources */
++unsigned long pci_mem_start = 0x10000000;
++#ifdef CONFIG_PCI
++EXPORT_SYMBOL(pci_mem_start);
++#endif
++extern int user_defined_memmap;
++struct resource data_resource = {
++	.name	= "Kernel data",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++struct resource code_resource = {
++	.name	= "Kernel code",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource system_rom_resource = {
++	.name	= "System ROM",
++	.start	= 0xf0000,
++	.end	= 0xfffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource extension_rom_resource = {
++	.name	= "Extension ROM",
++	.start	= 0xe0000,
++	.end	= 0xeffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource adapter_rom_resources[] = { {
++	.name 	= "Adapter ROM",
++	.start	= 0xc8000,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++}, {
++	.name 	= "Adapter ROM",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++} };
++
++static struct resource video_rom_resource = {
++	.name 	= "Video ROM",
++	.start	= 0xc0000,
++	.end	= 0xc7fff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
++};
++
++static struct resource video_ram_resource = {
++	.name	= "Video RAM area",
++	.start	= 0xa0000,
++	.end	= 0xbffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource standard_io_resources[] = { {
++	.name	= "dma1",
++	.start	= 0x0000,
++	.end	= 0x001f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic1",
++	.start	= 0x0020,
++	.end	= 0x0021,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer0",
++	.start	= 0x0040,
++	.end    = 0x0043,
++	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer1",
++	.start  = 0x0050,
++	.end    = 0x0053,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "keyboard",
++	.start	= 0x0060,
++	.end	= 0x006f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma page reg",
++	.start	= 0x0080,
++	.end	= 0x008f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic2",
++	.start	= 0x00a0,
++	.end	= 0x00a1,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma2",
++	.start	= 0x00c0,
++	.end	= 0x00df,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "fpu",
++	.start	= 0x00f0,
++	.end	= 0x00ff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++} };
++
++static int romsignature(const unsigned char *x)
++{
++	unsigned short sig;
++	int ret = 0;
++	if (probe_kernel_address((const unsigned short *)x, sig) == 0)
++		ret = (sig == 0xaa55);
++	return ret;
++}
++
++static int __init romchecksum(unsigned char *rom, unsigned long length)
++{
++	unsigned char *p, sum = 0;
++
++	for (p = rom; p < rom + length; p++)
++		sum += *p;
++	return sum == 0;
++}
++
++static void __init probe_roms(void)
++{
++	unsigned long start, length, upper;
++	unsigned char *rom;
++	int	      i;
++
++#ifdef CONFIG_XEN
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return;
++#endif
++
++	/* video rom */
++	upper = adapter_rom_resources[0].start;
++	for (start = video_rom_resource.start; start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		video_rom_resource.start = start;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* if checksum okay, trust length byte */
++		if (length && romchecksum(rom, length))
++			video_rom_resource.end = start + length - 1;
++
++		request_resource(&iomem_resource, &video_rom_resource);
++		break;
++	}
++
++	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
++	if (start < upper)
++		start = upper;
++
++	/* system rom */
++	request_resource(&iomem_resource, &system_rom_resource);
++	upper = system_rom_resource.start;
++
++	/* check for extension rom (ignore length byte!) */
++	rom = isa_bus_to_virt((unsigned long)extension_rom_resource.start);
++	if (romsignature(rom)) {
++		length = extension_rom_resource.end - extension_rom_resource.start + 1;
++		if (romchecksum(rom, length)) {
++			request_resource(&iomem_resource, &extension_rom_resource);
++			upper = extension_rom_resource.start;
++		}
++	}
++
++	/* check for adapter roms on 2k boundaries */
++	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
++		rom = isa_bus_to_virt(start);
++		if (!romsignature(rom))
++			continue;
++
++		/* 0 < length <= 0x7f * 512, historically */
++		length = rom[2] * 512;
++
++		/* but accept any length that fits if checksum okay */
++		if (!length || start + length > upper || !romchecksum(rom, length))
++			continue;
++
++		adapter_rom_resources[i].start = start;
++		adapter_rom_resources[i].end = start + length - 1;
++		request_resource(&iomem_resource, &adapter_rom_resources[i]);
++
++		start = adapter_rom_resources[i++].end & ~2047UL;
++	}
++}
++
++#ifdef CONFIG_XEN
++static struct e820map machine_e820 __initdata;
++#define e820 machine_e820
++#endif
++
++/*
++ * Request address space for all standard RAM and ROM resources
++ * and also for regions reported as reserved by the e820.
++ */
++static void __init
++legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
++{
++	int i;
++
++	probe_roms();
++	for (i = 0; i < e820.nr_map; i++) {
++		struct resource *res;
++#ifndef CONFIG_RESOURCES_64BIT
++		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
++			continue;
++#endif
++		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
++		switch (e820.map[i].type) {
++		case E820_RAM:	res->name = "System RAM"; break;
++		case E820_ACPI:	res->name = "ACPI Tables"; break;
++		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
++		default:	res->name = "reserved";
++		}
++		res->start = e820.map[i].addr;
++		res->end = res->start + e820.map[i].size - 1;
++		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++		if (request_resource(&iomem_resource, res)) {
++			kfree(res);
++			continue;
++		}
++		if (e820.map[i].type == E820_RAM) {
++			/*
++			 *  We don't know which RAM region contains kernel data,
++			 *  so we try it repeatedly and let the resource manager
++			 *  test it.
++			 */
++#ifndef CONFIG_XEN
++			request_resource(res, code_resource);
++			request_resource(res, data_resource);
++#endif
++#ifdef CONFIG_KEXEC
++			request_resource(res, &crashk_res);
++#ifdef CONFIG_XEN
++			xen_machine_kexec_register_resources(res);
++#endif
++#endif
++		}
++	}
++}
++
++#undef e820
++
++/*
++ * Request address space for all standard resources
++ *
++ * This is called just before pcibios_init(), which is also a
++ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
++ */
++static int __init request_standard_resources(void)
++{
++	int i;
++
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return 0;
++
++	printk("Setting up standard PCI resources\n");
++	if (efi_enabled)
++		efi_initialize_iomem_resources(&code_resource, &data_resource);
++	else
++		legacy_init_iomem_resources(&code_resource, &data_resource);
++
++	/* EFI systems may still have VGA */
++	request_resource(&iomem_resource, &video_ram_resource);
++
++	/* request I/O space for devices used on all i[345]86 PCs */
++	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
++		request_resource(&ioport_resource, &standard_io_resources[i]);
++	return 0;
++}
++
++subsys_initcall(request_standard_resources);
++
++void __init add_memory_region(unsigned long long start,
++			      unsigned long long size, int type)
++{
++	int x;
++
++	if (!efi_enabled) {
++       		x = e820.nr_map;
++
++		if (x == E820MAX) {
++		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++		    return;
++		}
++
++		e820.map[x].addr = start;
++		e820.map[x].size = size;
++		e820.map[x].type = type;
++		e820.nr_map++;
++	}
++} /* add_memory_region */
++
++/*
++ * Sanitize the BIOS e820 map.
++ *
++ * Some e820 responses include overlapping entries.  The following
++ * replaces the original e820 map with a new one, removing overlaps.
++ *
++ */
++int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
++{
++	struct change_member *change_tmp;
++	unsigned long current_type, last_type;
++	unsigned long long last_addr;
++	int chgidx, still_changing;
++	int overlap_entries;
++	int new_bios_entry;
++	int old_nr, new_nr, chg_nr;
++	int i;
++
++	/*
++		Visually we're performing the following (1,2,3,4 = memory types)...
++
++		Sample memory map (w/overlaps):
++		   ____22__________________
++		   ______________________4_
++		   ____1111________________
++		   _44_____________________
++		   11111111________________
++		   ____________________33__
++		   ___________44___________
++		   __________33333_________
++		   ______________22________
++		   ___________________2222_
++		   _________111111111______
++		   _____________________11_
++		   _________________4______
++
++		Sanitized equivalent (no overlap):
++		   1_______________________
++		   _44_____________________
++		   ___1____________________
++		   ____22__________________
++		   ______11________________
++		   _________1______________
++		   __________3_____________
++		   ___________44___________
++		   _____________33_________
++		   _______________2________
++		   ________________1_______
++		   _________________4______
++		   ___________________2____
++		   ____________________33__
++		   ______________________4_
++	*/
++	printk("sanitize start\n");
++	/* if there's only one memory region, don't bother */
++	if (*pnr_map < 2) {
++		printk("sanitize bail 0\n");
++		return -1;
++	}
++
++	old_nr = *pnr_map;
++
++	/* bail out if we find any unreasonable addresses in bios map */
++	for (i=0; i<old_nr; i++)
++		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {
++			printk("sanitize bail 1\n");
++			return -1;
++		}
++
++	/* create pointers for initial change-point information (for sorting) */
++	for (i=0; i < 2*old_nr; i++)
++		change_point[i] = &change_point_list[i];
++
++	/* record all known change-points (starting and ending addresses),
++	   omitting those that are for empty memory regions */
++	chgidx = 0;
++	for (i=0; i < old_nr; i++)	{
++		if (biosmap[i].size != 0) {
++			change_point[chgidx]->addr = biosmap[i].addr;
++			change_point[chgidx++]->pbios = &biosmap[i];
++			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
++			change_point[chgidx++]->pbios = &biosmap[i];
++		}
++	}
++	chg_nr = chgidx;    	/* true number of change-points */
++
++	/* sort change-point list by memory addresses (low -> high) */
++	still_changing = 1;
++	while (still_changing)	{
++		still_changing = 0;
++		for (i=1; i < chg_nr; i++)  {
++			/* if <current_addr> > <last_addr>, swap */
++			/* or, if current=<start_addr> & last=<end_addr>, swap */
++			if ((change_point[i]->addr < change_point[i-1]->addr) ||
++				((change_point[i]->addr == change_point[i-1]->addr) &&
++				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
++				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
++			   )
++			{
++				change_tmp = change_point[i];
++				change_point[i] = change_point[i-1];
++				change_point[i-1] = change_tmp;
++				still_changing=1;
++			}
++		}
++	}
++
++	/* create a new bios memory map, removing overlaps */
++	overlap_entries=0;	 /* number of entries in the overlap table */
++	new_bios_entry=0;	 /* index for creating new bios map entries */
++	last_type = 0;		 /* start with undefined memory type */
++	last_addr = 0;		 /* start with 0 as last starting address */
++	/* loop through change-points, determining affect on the new bios map */
++	for (chgidx=0; chgidx < chg_nr; chgidx++)
++	{
++		/* keep track of all overlapping bios entries */
++		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
++		{
++			/* add map entry to overlap list (> 1 entry implies an overlap) */
++			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
++		}
++		else
++		{
++			/* remove entry from list (order independent, so swap with last) */
++			for (i=0; i<overlap_entries; i++)
++			{
++				if (overlap_list[i] == change_point[chgidx]->pbios)
++					overlap_list[i] = overlap_list[overlap_entries-1];
++			}
++			overlap_entries--;
++		}
++		/* if there are overlapping entries, decide which "type" to use */
++		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
++		current_type = 0;
++		for (i=0; i<overlap_entries; i++)
++			if (overlap_list[i]->type > current_type)
++				current_type = overlap_list[i]->type;
++		/* continue building up new bios map based on this information */
++		if (current_type != last_type)	{
++			if (last_type != 0)	 {
++				new_bios[new_bios_entry].size =
++					change_point[chgidx]->addr - last_addr;
++				/* move forward only if the new size was non-zero */
++				if (new_bios[new_bios_entry].size != 0)
++					if (++new_bios_entry >= E820MAX)
++						break; 	/* no more space left for new bios entries */
++			}
++			if (current_type != 0)	{
++				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
++				new_bios[new_bios_entry].type = current_type;
++				last_addr=change_point[chgidx]->addr;
++			}
++			last_type = current_type;
++		}
++	}
++	new_nr = new_bios_entry;   /* retain count for new bios entries */
++
++	/* copy new bios mapping into original location */
++	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
++	*pnr_map = new_nr;
++
++	printk("sanitize end\n");
++	return 0;
++}
++
++/*
++ * Copy the BIOS e820 map into a safe place.
++ *
++ * Sanity-check it while we're at it..
++ *
++ * If we're lucky and live on a modern system, the setup code
++ * will have given us a memory map that we can use to properly
++ * set up memory.  If we aren't, we'll fake a memory map.
++ *
++ * We check to see that the memory map contains at least 2 elements
++ * before we'll use it, because the detection code in setup.S may
++ * not be perfect and most every PC known to man has two memory
++ * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
++ * thinkpad 560x, for example, does not cooperate with the memory
++ * detection code.)
++ */
++int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++{
++#ifndef CONFIG_XEN
++	/* Only one memory region (or negative)? Ignore it */
++	if (nr_map < 2)
++		return -1;
++#else
++	BUG_ON(nr_map < 1);
++#endif
++
++	do {
++		unsigned long long start = biosmap->addr;
++		unsigned long long size = biosmap->size;
++		unsigned long long end = start + size;
++		unsigned long type = biosmap->type;
++		printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type);
++
++		/* Overflow in 64 bits? Ignore the memory map. */
++		if (start > end)
++			return -1;
++
++#ifndef CONFIG_XEN
++		/*
++		 * Some BIOSes claim RAM in the 640k - 1M region.
++		 * Not right. Fix it up.
++		 */
++		if (type == E820_RAM) {
++			printk("copy_e820_map() type is E820_RAM\n");
++			if (start < 0x100000ULL && end > 0xA0000ULL) {
++				printk("copy_e820_map() lies in range...\n");
++				if (start < 0xA0000ULL) {
++					printk("copy_e820_map() start < 0xA0000ULL\n");
++					add_memory_region(start, 0xA0000ULL-start, type);
++				}
++				if (end <= 0x100000ULL) {
++					printk("copy_e820_map() end <= 0x100000ULL\n");
++					continue;
++				}
++				start = 0x100000ULL;
++				size = end - start;
++			}
++		}
++#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;
++}
++
++/*
++ * Callback for efi_memory_walk.
++ */
++static int __init
++efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
++{
++	unsigned long *max_pfn = arg, pfn;
++
++	if (start < end) {
++		pfn = PFN_UP(end -1);
++		if (pfn > *max_pfn)
++			*max_pfn = pfn;
++	}
++	return 0;
++}
++
++static int __init
++efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
++{
++	memory_present(0, PFN_UP(start), PFN_DOWN(end));
++	return 0;
++}
++
++/*
++ * Find the highest page frame number we have available
++ */
++void __init find_max_pfn(void)
++{
++	int i;
++
++	max_pfn = 0;
++	if (efi_enabled) {
++		efi_memmap_walk(efi_find_max_pfn, &max_pfn);
++		efi_memmap_walk(efi_memory_present_wrapper, NULL);
++		return;
++	}
++
++	for (i = 0; i < e820.nr_map; i++) {
++		unsigned long start, end;
++		/* RAM? */
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		start = PFN_UP(e820.map[i].addr);
++		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
++		if (start >= end)
++			continue;
++		if (end > max_pfn)
++			max_pfn = end;
++		memory_present(0, start, end);
++	}
++}
++
++/*
++ * Free all available memory for boot time allocation.  Used
++ * as a callback function by efi_memory_walk()
++ */
++
++static int __init
++free_available_memory(unsigned long start, unsigned long end, void *arg)
++{
++	/* check max_low_pfn */
++	if (start >= (max_low_pfn << PAGE_SHIFT))
++		return 0;
++	if (end >= (max_low_pfn << PAGE_SHIFT))
++		end = max_low_pfn << PAGE_SHIFT;
++	if (start < end)
++		free_bootmem(start, end - start);
++
++	return 0;
++}
++/*
++ * Register fully available low RAM pages with the bootmem allocator.
++ */
++void __init register_bootmem_low_pages(unsigned long max_low_pfn)
++{
++	int i;
++
++	if (efi_enabled) {
++		efi_memmap_walk(free_available_memory, NULL);
++		return;
++	}
++	for (i = 0; i < e820.nr_map; i++) {
++		unsigned long curr_pfn, last_pfn, size;
++		/*
++		 * Reserve usable low memory
++		 */
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		/*
++		 * We are rounding up the start address of usable memory:
++		 */
++		curr_pfn = PFN_UP(e820.map[i].addr);
++		if (curr_pfn >= max_low_pfn)
++			continue;
++		/*
++		 * ... and at the end of the usable range downwards:
++		 */
++		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
++
++#ifdef CONFIG_XEN
++		/*
++		 * Truncate to the number of actual pages currently
++		 * present.
++		 */
++		if (last_pfn > xen_start_info->nr_pages)
++			last_pfn = xen_start_info->nr_pages;
++#endif
++
++		if (last_pfn > max_low_pfn)
++			last_pfn = max_low_pfn;
++
++		/*
++		 * .. finally, did all the rounding and playing
++		 * around just make the area go away?
++		 */
++		if (last_pfn <= curr_pfn)
++			continue;
++
++		size = last_pfn - curr_pfn;
++		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
++	}
++}
++
++void __init e820_register_memory(void)
++{
++	unsigned long gapstart, gapsize, round;
++	unsigned long long last;
++	int i;
++
++#ifdef CONFIG_XEN
++#define e820 machine_e820
++#endif
++	/*
++	 * Search for the bigest gap in the low 32 bits of the e820
++	 * memory space.
++	 */
++	last = 0x100000000ull;
++	gapstart = 0x10000000;
++	gapsize = 0x400000;
++	i = e820.nr_map;
++	while (--i >= 0) {
++		unsigned long long start = e820.map[i].addr;
++		unsigned long long end = start + e820.map[i].size;
++
++		/*
++		 * Since "last" is at most 4GB, we know we'll
++		 * fit in 32 bits if this condition is true
++		 */
++		if (last > end) {
++			unsigned long gap = last - end;
++
++			if (gap > gapsize) {
++				gapsize = gap;
++				gapstart = end;
++			}
++		}
++		if (start < last)
++			last = start;
++	}
++#undef e820
++
++	/*
++	 * See how much we want to round up: start off with
++	 * rounding to the next 1MB area.
++	 */
++	round = 0x100000;
++	while ((gapsize >> 4) > round)
++		round += round;
++	/* Fun with two's complement */
++	pci_mem_start = (gapstart + round) & -round;
++
++	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
++		pci_mem_start, gapstart, gapsize);
++}
++
++void __init print_memory_map(char *who)
++{
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		printk(" %s: %016Lx - %016Lx ", who,
++			e820.map[i].addr,
++			e820.map[i].addr + e820.map[i].size);
++		switch (e820.map[i].type) {
++		case E820_RAM:	printk("(usable)\n");
++				break;
++		case E820_RESERVED:
++				printk("(reserved)\n");
++				break;
++		case E820_ACPI:
++				printk("(ACPI data)\n");
++				break;
++		case E820_NVS:
++				printk("(ACPI NVS)\n");
++				break;
++		default:	printk("type %lu\n", e820.map[i].type);
++				break;
++		}
++	}
++}
++
++static __init __always_inline void efi_limit_regions(unsigned long long size)
++{
++	unsigned long long current_addr = 0;
++	efi_memory_desc_t *md, *next_md;
++	void *p, *p1;
++	int i, j;
++
++	j = 0;
++	p1 = memmap.map;
++	for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
++		md = p;
++		next_md = p1;
++		current_addr = md->phys_addr +
++			PFN_PHYS(md->num_pages);
++		if (is_available_memory(md)) {
++			if (md->phys_addr >= size) continue;
++			memcpy(next_md, md, memmap.desc_size);
++			if (current_addr >= size) {
++				next_md->num_pages -=
++					PFN_UP(current_addr-size);
++			}
++			p1 += memmap.desc_size;
++			next_md = p1;
++			j++;
++		} else if ((md->attribute & EFI_MEMORY_RUNTIME) ==
++			   EFI_MEMORY_RUNTIME) {
++			/* In order to make runtime services
++			 * available we have to include runtime
++			 * memory regions in memory map */
++			memcpy(next_md, md, memmap.desc_size);
++			p1 += memmap.desc_size;
++			next_md = p1;
++			j++;
++		}
++	}
++	memmap.nr_map = j;
++	memmap.map_end = memmap.map +
++		(memmap.nr_map * memmap.desc_size);
++}
++
++void __init limit_regions(unsigned long long size)
++{
++	unsigned long long current_addr = 0;
++	int i;
++
++	print_memory_map("limit_regions start");
++	if (efi_enabled) {
++		efi_limit_regions(size);
++		return;
++	}
++	for (i = 0; i < e820.nr_map; i++) {
++		current_addr = e820.map[i].addr + e820.map[i].size;
++		if (current_addr < size)
++			continue;
++
++		if (e820.map[i].type != E820_RAM)
++			continue;
++
++		if (e820.map[i].addr >= size) {
++			/*
++			 * This region starts past the end of the
++			 * requested size, skip it completely.
++			 */
++			e820.nr_map = i;
++		} else {
++			e820.nr_map = i + 1;
++			e820.map[i].size -= current_addr - size;
++		}
++		print_memory_map("limit_regions endfor");
++		return;
++	}
++#ifdef CONFIG_XEN
++	if (current_addr < size) {
++		/*
++		 * The e820 map finished before our requested size so
++		 * extend the final entry to the requested address.
++		 */
++		--i;
++		if (e820.map[i].type == E820_RAM)
++			e820.map[i].size -= current_addr - size;
++		else
++			add_memory_region(current_addr, size - current_addr, E820_RAM);
++	}
++#endif
++	print_memory_map("limit_regions endfunc");
++}
++
++/*
++ * 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;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		const struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		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.
++  *
++  * Note: this function only works correct if the e820 table is sorted and
++  * not-overlapping, which is the case
++  */
++int __init
++e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
++{
++	u64 start = s;
++	u64 end = e;
++	int i;
++
++#ifndef CONFIG_XEN
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++#else
++	if (!is_initial_xendomain())
++		return 0;
++	for (i = 0; i < machine_e820.nr_map; ++i) {
++		const struct e820entry *ei = &machine_e820.map[i];
++#endif
++
++		if (type && ei->type != type)
++			continue;
++		/* is the region (part) in overlap with the current region ?*/
++		if (ei->addr >= end || ei->addr + ei->size <= start)
++			continue;
++		/* if the region is at the beginning of <start,end> we move
++		 * start to the end of the region since it's ok until there
++		 */
++		if (ei->addr <= start)
++			start = ei->addr + ei->size;
++		/* if start is now at or beyond end, we're done, full
++		 * coverage */
++		if (start >= end)
++			return 1; /* we're done */
++	}
++	return 0;
++}
++
++static int __init parse_memmap(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++
++	if (strcmp(arg, "exactmap") == 0) {
++#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.
++		 */
++		find_max_pfn();
++		saved_max_pfn = max_pfn;
++#endif
++		e820.nr_map = 0;
++		user_defined_memmap = 1;
++	} else {
++		/* If the user specifies memory size, we
++		 * limit the BIOS-provided memory map to
++		 * that size. exactmap can be used to specify
++		 * the exact map. mem=number can be used to
++		 * trim the existing memory map.
++		 */
++		unsigned long long start_at, mem_size;
++
++		mem_size = memparse(arg, &arg);
++		if (*arg == '@') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_RAM);
++		} else if (*arg == '#') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_ACPI);
++		} else if (*arg == '$') {
++			start_at = memparse(arg+1, &arg);
++			add_memory_region(start_at, mem_size, E820_RESERVED);
++		} else {
++			limit_regions(mem_size);
++			user_defined_memmap = 1;
++		}
++	}
++	return 0;
++}
++early_param("memmap", parse_memmap);
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:46:27.000000000 +0100
+@@ -30,12 +30,13 @@
+  *	18(%esp) - %eax
+  *	1C(%esp) - %ds
+  *	20(%esp) - %es
+- *	24(%esp) - orig_eax
+- *	28(%esp) - %eip
+- *	2C(%esp) - %cs
+- *	30(%esp) - %eflags
+- *	34(%esp) - %oldesp
+- *	38(%esp) - %oldss
++ *	24(%esp) - %gs
++ *	28(%esp) - orig_eax
++ *	2C(%esp) - %eip
++ *	30(%esp) - %cs
++ *	34(%esp) - %eflags
++ *	38(%esp) - %oldesp
++ *	3C(%esp) - %oldss
+  *
+  * "current" is in register %ebx during any slow entries.
+  */
+@@ -48,27 +49,25 @@
+ #include <asm/smp.h>
+ #include <asm/page.h>
+ #include <asm/desc.h>
++#include <asm/percpu.h>
+ #include <asm/dwarf2.h>
+ #include "irq_vectors.h"
+ #include <xen/interface/xen.h>
+ 
+-#define nr_syscalls ((syscall_table_size)/4)
++/*
++ * We use macros for low-level operations which need to be overridden
++ * for paravirtualization.  The following will never clobber any registers:
++ *   INTERRUPT_RETURN (aka. "iret")
++ *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
++ *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
++ *
++ * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
++ * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
++ * Allowing a register to be clobbered can shrink the paravirt replacement
++ * enough to patch inline, increasing performance.
++ */
+ 
+-EBX		= 0x00
+-ECX		= 0x04
+-EDX		= 0x08
+-ESI		= 0x0C
+-EDI		= 0x10
+-EBP		= 0x14
+-EAX		= 0x18
+-DS		= 0x1C
+-ES		= 0x20
+-ORIG_EAX	= 0x24
+-EIP		= 0x28
+-CS		= 0x2C
+-EFLAGS		= 0x30
+-OLDESP		= 0x34
+-OLDSS		= 0x38
++#define nr_syscalls ((syscall_table_size)/4)
+ 
+ CF_MASK		= 0x00000001
+ TF_MASK		= 0x00000100
+@@ -79,61 +78,16 @@ VM_MASK		= 0x00020000
+ /* Pseudo-eflags. */
+ NMI_MASK	= 0x80000000
+ 
+-#ifndef CONFIG_XEN
+-/* These are replaces for paravirtualization */
+-#define DISABLE_INTERRUPTS		cli
+-#define ENABLE_INTERRUPTS		sti
+-#define ENABLE_INTERRUPTS_SYSEXIT	sti; sysexit
+-#define INTERRUPT_RETURN		iret
+-#define GET_CR0_INTO_EAX		movl %cr0, %eax
+-#else
+-/* Offsets into shared_info_t. */
+-#define evtchn_upcall_pending		/* 0 */
+-#define evtchn_upcall_mask		1
+-
+-#define sizeof_vcpu_shift		6
+-
+-#ifdef CONFIG_SMP
+-#define GET_VCPU_INFO		movl TI_cpu(%ebp),%esi			; \
+-				shl  $sizeof_vcpu_shift,%esi		; \
+-				addl HYPERVISOR_shared_info,%esi
+-#else
+-#define GET_VCPU_INFO		movl HYPERVISOR_shared_info,%esi
+-#endif
+-
+-#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(%esi)
+-#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(%esi)
+-#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
+-#define DISABLE_INTERRUPTS	GET_VCPU_INFO				; \
+-				__DISABLE_INTERRUPTS
+-#define ENABLE_INTERRUPTS	GET_VCPU_INFO				; \
+-				__ENABLE_INTERRUPTS
+-#define ENABLE_INTERRUPTS_SYSEXIT __ENABLE_INTERRUPTS			; \
+-sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
+-	__TEST_PENDING							; \
+-	jnz  14f		# process more events if necessary...	; \
+-	movl ESI(%esp), %esi						; \
+-	sysexit								; \
+-14:	__DISABLE_INTERRUPTS						; \
+-	TRACE_IRQS_OFF							; \
+-sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+-	push %esp							; \
+-	call evtchn_do_upcall						; \
+-	add  $4,%esp							; \
+-	jmp  ret_from_intr
+-#define INTERRUPT_RETURN	iret
+-#endif
+-
+ #ifdef CONFIG_PREEMPT
+-#define preempt_stop		DISABLE_INTERRUPTS; TRACE_IRQS_OFF
++#define preempt_stop(clobbers)	DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
+ #else
+-#define preempt_stop
++#define preempt_stop(clobbers)
+ #define resume_kernel		restore_nocheck
+ #endif
+ 
+ .macro TRACE_IRQS_IRET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+-	testl $IF_MASK,EFLAGS(%esp)     # interrupts off?
++	testl $IF_MASK,PT_EFLAGS(%esp)     # interrupts off?
+ 	jz 1f
+ 	TRACE_IRQS_ON
+ 1:
+@@ -148,6 +102,9 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ 
+ #define SAVE_ALL \
+ 	cld; \
++	pushl %gs; \
++	CFI_ADJUST_CFA_OFFSET 4;\
++	/*CFI_REL_OFFSET gs, 0;*/\
+ 	pushl %es; \
+ 	CFI_ADJUST_CFA_OFFSET 4;\
+ 	/*CFI_REL_OFFSET es, 0;*/\
+@@ -177,7 +134,9 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ 	CFI_REL_OFFSET ebx, 0;\
+ 	movl $(__USER_DS), %edx; \
+ 	movl %edx, %ds; \
+-	movl %edx, %es;
++	movl %edx, %es; \
++	movl $(__KERNEL_PDA), %edx; \
++	movl %edx, %gs
+ 
+ #define RESTORE_INT_REGS \
+ 	popl %ebx;	\
+@@ -210,17 +169,22 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ 2:	popl %es;	\
+ 	CFI_ADJUST_CFA_OFFSET -4;\
+ 	/*CFI_RESTORE es;*/\
+-.section .fixup,"ax";	\
+-3:	movl $0,(%esp);	\
+-	jmp 1b;		\
++3:	popl %gs;	\
++	CFI_ADJUST_CFA_OFFSET -4;\
++	/*CFI_RESTORE gs;*/\
++.pushsection .fixup,"ax";	\
+ 4:	movl $0,(%esp);	\
++	jmp 1b;		\
++5:	movl $0,(%esp);	\
+ 	jmp 2b;		\
+-.previous;		\
++6:	movl $0,(%esp);	\
++	jmp 3b;		\
+ .section __ex_table,"a";\
+ 	.align 4;	\
+-	.long 1b,3b;	\
+-	.long 2b,4b;	\
+-.previous
++	.long 1b,4b;	\
++	.long 2b,5b;	\
++	.long 3b,6b;	\
++.popsection
+ 
+ #define RING0_INT_FRAME \
+ 	CFI_STARTPROC simple;\
+@@ -239,18 +203,18 @@ sysexit_ecrit:	/**** END OF SYSEXIT CRIT
+ #define RING0_PTREGS_FRAME \
+ 	CFI_STARTPROC simple;\
+ 	CFI_SIGNAL_FRAME;\
+-	CFI_DEF_CFA esp, OLDESP-EBX;\
+-	/*CFI_OFFSET cs, CS-OLDESP;*/\
+-	CFI_OFFSET eip, EIP-OLDESP;\
+-	/*CFI_OFFSET es, ES-OLDESP;*/\
+-	/*CFI_OFFSET ds, DS-OLDESP;*/\
+-	CFI_OFFSET eax, EAX-OLDESP;\
+-	CFI_OFFSET ebp, EBP-OLDESP;\
+-	CFI_OFFSET edi, EDI-OLDESP;\
+-	CFI_OFFSET esi, ESI-OLDESP;\
+-	CFI_OFFSET edx, EDX-OLDESP;\
+-	CFI_OFFSET ecx, ECX-OLDESP;\
+-	CFI_OFFSET ebx, EBX-OLDESP
++	CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\
++	/*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\
++	CFI_OFFSET eip, PT_EIP-PT_OLDESP;\
++	/*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\
++	/*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\
++	CFI_OFFSET eax, PT_EAX-PT_OLDESP;\
++	CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\
++	CFI_OFFSET edi, PT_EDI-PT_OLDESP;\
++	CFI_OFFSET esi, PT_ESI-PT_OLDESP;\
++	CFI_OFFSET edx, PT_EDX-PT_OLDESP;\
++	CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\
++	CFI_OFFSET ebx, PT_EBX-PT_OLDESP
+ 
+ ENTRY(ret_from_fork)
+ 	CFI_STARTPROC
+@@ -278,17 +242,18 @@ ENTRY(ret_from_fork)
+ 	ALIGN
+ 	RING0_PTREGS_FRAME
+ ret_from_exception:
+-	preempt_stop
++	preempt_stop(CLBR_ANY)
+ ret_from_intr:
+ 	GET_THREAD_INFO(%ebp)
+ check_userspace:
+-	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
+-	movb CS(%esp), %al
++	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
++	movb PT_CS(%esp), %al
+ 	andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
+ 	cmpl $USER_RPL, %eax
+ 	jb resume_kernel		# not returning to v8086 or userspace
++
+ ENTRY(resume_userspace)
+-	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++ 	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	movl TI_flags(%ebp), %ecx
+@@ -299,14 +264,14 @@ ENTRY(resume_userspace)
+ 
+ #ifdef CONFIG_PREEMPT
+ ENTRY(resume_kernel)
+-	DISABLE_INTERRUPTS
++	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+ 	jnz restore_nocheck
+ need_resched:
+ 	movl TI_flags(%ebp), %ecx	# need_resched set ?
+ 	testb $_TIF_NEED_RESCHED, %cl
+ 	jz restore_all
+-	testl $IF_MASK,EFLAGS(%esp)     # interrupts off (exception path) ?
++	testl $IF_MASK,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
+ 	jz restore_all
+ 	call preempt_schedule_irq
+ 	jmp need_resched
+@@ -328,7 +293,7 @@ sysenter_past_esp:
+ 	 * No need to follow this irqs on/off section: the syscall
+ 	 * disabled irqs and here we enable it straight after entry:
+ 	 */
+-	ENABLE_INTERRUPTS
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushl $(__USER_DS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET ss, 0*/
+@@ -340,12 +305,16 @@ sysenter_past_esp:
+ 	pushl $(__USER_CS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET cs, 0*/
++#ifndef CONFIG_COMPAT_VDSO
+ 	/*
+ 	 * Push current_thread_info()->sysenter_return to the stack.
+ 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+ 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+ 	 */
+ 	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
++#else
++	pushl $SYSENTER_RETURN
++#endif
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eip, 0
+ 
+@@ -372,19 +341,27 @@ sysenter_past_esp:
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+ 	call *sys_call_table(,%eax,4)
+-	movl %eax,EAX(%esp)
+-	DISABLE_INTERRUPTS
++	movl %eax,PT_EAX(%esp)
++	DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+ 	testw $_TIF_ALLWORK_MASK, %cx
+ 	jne syscall_exit_work
+ /* if something modifies registers it must also disable sysexit */
+-	movl EIP(%esp), %edx
+-	movl OLDESP(%esp), %ecx
++	movl PT_EIP(%esp), %edx
++	movl PT_OLDESP(%esp), %ecx
+ 	xorl %ebp,%ebp
+ 	TRACE_IRQS_ON
++1:	mov  PT_GS(%esp), %gs
+ 	ENABLE_INTERRUPTS_SYSEXIT
+ 	CFI_ENDPROC
++.pushsection .fixup,"ax"
++2:	movl $0,PT_GS(%esp)
++	jmp 1b
++.section __ex_table,"a"
++	.align 4
++	.long 1b,2b
++.popsection
+ 
+ 	# pv sysenter call handler stub
+ ENTRY(sysenter_entry_pv)
+@@ -419,7 +396,7 @@ ENTRY(system_call)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	testl $TF_MASK,EFLAGS(%esp)
++	testl $TF_MASK,PT_EFLAGS(%esp)
+ 	jz no_singlestep
+ 	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+ no_singlestep:
+@@ -431,9 +408,9 @@ no_singlestep:
+ 	jae syscall_badsys
+ syscall_call:
+ 	call *sys_call_table(,%eax,4)
+-	movl %eax,EAX(%esp)		# store the return value
++	movl %eax,PT_EAX(%esp)		# store the return value
+ syscall_exit:
+-	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+@@ -443,12 +420,12 @@ syscall_exit:
+ 
+ restore_all:
+ #ifndef CONFIG_XEN
+-	movl EFLAGS(%esp), %eax		# mix EFLAGS, SS and CS
+-	# Warning: OLDSS(%esp) contains the wrong/random values if we
++	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
++	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
+ 	# are returning to the kernel.
+ 	# See comments in process.c:copy_thread() for details.
+-	movb OLDSS(%esp), %ah
+-	movb CS(%esp), %al
++	movb PT_OLDSS(%esp), %ah
++	movb PT_CS(%esp), %al
+ 	andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+ 	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+ 	CFI_REMEMBER_STATE
+@@ -456,7 +433,7 @@ restore_all:
+ restore_nocheck:
+ #else
+ restore_nocheck:
+-	movl EFLAGS(%esp), %eax
++	movl PT_EFLAGS(%esp), %eax
+ 	testl $(VM_MASK|NMI_MASK), %eax
+ 	CFI_REMEMBER_STATE
+ 	jnz hypervisor_iret
+@@ -470,13 +447,13 @@ restore_nocheck:
+ 	TRACE_IRQS_IRET
+ restore_nocheck_notrace:
+ 	RESTORE_REGS
+-	addl $4, %esp
++	addl $4, %esp			# skip orig_eax/error_code
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 1:	INTERRUPT_RETURN
+ .section .fixup,"ax"
+ iret_exc:
+ #ifndef CONFIG_XEN
+-	ENABLE_INTERRUPTS
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ #endif
+ 	pushl $0			# no error code
+ 	pushl $do_iret_error
+@@ -490,33 +467,42 @@ iret_exc:
+ 	CFI_RESTORE_STATE
+ #ifndef CONFIG_XEN
+ ldt_ss:
+-	larl OLDSS(%esp), %eax
++	larl PT_OLDSS(%esp), %eax
+ 	jnz restore_nocheck
+ 	testl $0x00400000, %eax		# returning to 32bit stack?
+ 	jnz restore_nocheck		# allright, normal return
++
++#ifdef CONFIG_PARAVIRT
++	/*
++	 * The kernel can't run on a non-flat stack if paravirt mode
++	 * is active.  Rather than try to fixup the high bits of
++	 * ESP, bypass this code entirely.  This may break DOSemu
++	 * and/or Wine support in a paravirt VM, although the option
++	 * is still available to implement the setting of the high
++	 * 16-bits in the INTERRUPT_RETURN paravirt-op.
++	 */
++	cmpl $0, paravirt_ops+PARAVIRT_enabled
++	jne restore_nocheck
++#endif
++
+ 	/* If returning to userspace with 16bit stack,
+ 	 * try to fix the higher word of ESP, as the CPU
+ 	 * won't restore it.
+ 	 * This is an "official" bug of all the x86-compatible
+ 	 * CPUs, which we can try to work around to make
+ 	 * dosemu and wine happy. */
+-	subl $8, %esp		# reserve space for switch16 pointer
+-	CFI_ADJUST_CFA_OFFSET 8
+-	DISABLE_INTERRUPTS
++	movl PT_OLDESP(%esp), %eax
++	movl %esp, %edx
++	call patch_espfix_desc
++	pushl $__ESPFIX_SS
++	CFI_ADJUST_CFA_OFFSET 4
++	pushl %eax
++	CFI_ADJUST_CFA_OFFSET 4
++	DISABLE_INTERRUPTS(CLBR_EAX)
+ 	TRACE_IRQS_OFF
+-	movl %esp, %eax
+-	/* Set up the 16bit stack frame with switch32 pointer on top,
+-	 * and a switch16 pointer on top of the current frame. */
+-	call setup_x86_bogus_stack
+-	CFI_ADJUST_CFA_OFFSET -8	# frame has moved
+-	TRACE_IRQS_IRET
+-	RESTORE_REGS
+-	lss 20+4(%esp), %esp	# switch to 16bit stack
+-1:	INTERRUPT_RETURN
+-.section __ex_table,"a"
+-	.align 4
+-	.long 1b,iret_exc
+-.previous
++	lss (%esp), %esp
++	CFI_ADJUST_CFA_OFFSET -8
++	jmp restore_nocheck
+ #else
+         ALIGN
+ restore_all_enable_events:
+@@ -540,7 +526,7 @@ ecrit:  /**** END OF CRITICAL REGION ***
+ 
+ 	CFI_RESTORE_STATE
+ hypervisor_iret:
+-	andl $~NMI_MASK, EFLAGS(%esp)
++	andl $~NMI_MASK, PT_EFLAGS(%esp)
+ 	RESTORE_REGS
+ 	addl $4, %esp
+ 	CFI_ADJUST_CFA_OFFSET -4
+@@ -556,7 +542,7 @@ work_pending:
+ 	jz work_notifysig
+ work_resched:
+ 	call schedule
+-	DISABLE_INTERRUPTS		# make sure we don't miss an interrupt
++	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+ 	TRACE_IRQS_OFF
+@@ -569,7 +555,8 @@ work_resched:
+ 
+ work_notifysig:				# deal with pending signals and
+ 					# notify-resume requests
+-	testl $VM_MASK, EFLAGS(%esp)
++#ifdef CONFIG_VM86
++	testl $VM_MASK, PT_EFLAGS(%esp)
+ 	movl %esp, %eax
+ 	jne work_notifysig_v86		# returning to kernel-space or
+ 					# vm86-space
+@@ -579,29 +566,30 @@ work_notifysig:				# deal with pending s
+ 
+ 	ALIGN
+ work_notifysig_v86:
+-#ifdef CONFIG_VM86
+ 	pushl %ecx			# save ti_flags for do_notify_resume
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	call save_v86_state		# %eax contains pt_regs pointer
+ 	popl %ecx
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	movl %eax, %esp
++#else
++	movl %esp, %eax
++#endif
+ 	xorl %edx, %edx
+ 	call do_notify_resume
+ 	jmp resume_userspace_sig
+-#endif
+ 
+ 	# perform syscall exit tracing
+ 	ALIGN
+ syscall_trace_entry:
+-	movl $-ENOSYS,EAX(%esp)
++	movl $-ENOSYS,PT_EAX(%esp)
+ 	movl %esp, %eax
+ 	xorl %edx,%edx
+ 	call do_syscall_trace
+ 	cmpl $0, %eax
+ 	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
+ 					# so must skip actual syscall
+-	movl ORIG_EAX(%esp), %eax
++	movl PT_ORIG_EAX(%esp), %eax
+ 	cmpl $(nr_syscalls), %eax
+ 	jnae syscall_call
+ 	jmp syscall_exit
+@@ -612,7 +600,7 @@ syscall_exit_work:
+ 	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
+ 	jz work_pending
+ 	TRACE_IRQS_ON
+-	ENABLE_INTERRUPTS		# could let do_syscall_trace() call
++	ENABLE_INTERRUPTS(CLBR_ANY)	# could let do_syscall_trace() call
+ 					# schedule() instead
+ 	movl %esp, %eax
+ 	movl $1, %edx
+@@ -626,40 +614,39 @@ syscall_fault:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-	movl $-EFAULT,EAX(%esp)
++	movl $-EFAULT,PT_EAX(%esp)
+ 	jmp resume_userspace
+ 
+ syscall_badsys:
+-	movl $-ENOSYS,EAX(%esp)
++	movl $-ENOSYS,PT_EAX(%esp)
+ 	jmp resume_userspace
+ 	CFI_ENDPROC
+ 
+ #ifndef CONFIG_XEN
+ #define FIXUP_ESPFIX_STACK \
+-	movl %esp, %eax; \
+-	/* switch to 32bit stack using the pointer on top of 16bit stack */ \
+-	lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+-	/* copy data from 16bit stack to 32bit stack */ \
+-	call fixup_x86_bogus_stack; \
+-	/* put ESP to the proper location */ \
+-	movl %eax, %esp;
+-#define UNWIND_ESPFIX_STACK \
++	/* since we are on a wrong stack, we cant make it a C code :( */ \
++	movl %gs:PDA_cpu, %ebx; \
++	PER_CPU(cpu_gdt_descr, %ebx); \
++	movl GDS_address(%ebx), %ebx; \
++	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
++	addl %esp, %eax; \
++	pushl $__KERNEL_DS; \
++	CFI_ADJUST_CFA_OFFSET 4; \
+ 	pushl %eax; \
+ 	CFI_ADJUST_CFA_OFFSET 4; \
++	lss (%esp), %esp; \
++	CFI_ADJUST_CFA_OFFSET -8;
++#define UNWIND_ESPFIX_STACK \
+ 	movl %ss, %eax; \
+-	/* see if on 16bit stack */ \
++	/* see if on espfix stack */ \
+ 	cmpw $__ESPFIX_SS, %ax; \
+-	je 28f; \
+-27:	popl %eax; \
+-	CFI_ADJUST_CFA_OFFSET -4; \
+-.section .fixup,"ax"; \
+-28:	movl $__KERNEL_DS, %eax; \
++	jne 27f; \
++	movl $__KERNEL_DS, %eax; \
+ 	movl %eax, %ds; \
+ 	movl %eax, %es; \
+-	/* switch to 32bit stack */ \
++	/* switch to normal stack */ \
+ 	FIXUP_ESPFIX_STACK; \
+-	jmp 27b; \
+-.previous
++27:;
+ 
+ /*
+  * Build the entry stubs and pointer table with
+@@ -723,13 +710,16 @@ KPROBE_ENTRY(page_fault)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	ALIGN
+ error_code:
++	/* the function address is in %gs's slot on the stack */
++	pushl %es
++	CFI_ADJUST_CFA_OFFSET 4
++	/*CFI_REL_OFFSET es, 0*/
+ 	pushl %ds
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET ds, 0*/
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET eax, 0
+-	xorl %eax, %eax
+ 	pushl %ebp
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET ebp, 0
+@@ -742,7 +732,6 @@ error_code:
+ 	pushl %edx
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET edx, 0
+-	decl %eax			# eax = -1
+ 	pushl %ecx
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET ecx, 0
+@@ -750,18 +739,20 @@ error_code:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET ebx, 0
+ 	cld
+-	pushl %es
++	pushl %gs
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET es, 0*/
++	/*CFI_REL_OFFSET gs, 0*/
++	movl $(__KERNEL_PDA), %ecx
++	movl %ecx, %gs
+ 	UNWIND_ESPFIX_STACK
+ 	popl %ecx
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	/*CFI_REGISTER es, ecx*/
+-	movl ES(%esp), %edi		# get the function address
+-	movl ORIG_EAX(%esp), %edx	# get the error code
+-	movl %eax, ORIG_EAX(%esp)
+-	movl %ecx, ES(%esp)
+-	/*CFI_REL_OFFSET es, ES*/
++	movl PT_GS(%esp), %edi		# get the function address
++	movl PT_ORIG_EAX(%esp), %edx	# get the error code
++	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
++	mov  %ecx, PT_GS(%esp)
++	/*CFI_REL_OFFSET gs, ES*/
+ 	movl $(__USER_DS), %ecx
+ 	movl %ecx, %ds
+ 	movl %ecx, %es
+@@ -793,8 +784,8 @@ ENTRY(hypervisor_callback)
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+-	movl CS(%esp),%ecx
+-	movl EIP(%esp),%eax
++	movl PT_CS(%esp),%ecx
++	movl PT_EIP(%esp),%eax
+ 	andl $SEGMENT_RPL_MASK,%ecx
+ 	cmpl $USER_RPL,%ecx
+ 	jae  .Ldo_upcall
+@@ -808,7 +799,7 @@ ENTRY(hypervisor_callback)
+ 	jb   .Ldo_upcall
+ 	cmpl $sysexit_ecrit,%eax
+ 	ja   .Ldo_upcall
+-	addl $OLDESP,%esp		# Remove eflags...ebx from stack frame.
++	addl $PT_OLDESP,%esp		# Remove eflags...ebx from stack frame.
+ #endif
+ .Ldo_upcall:
+ 	push %esp
+@@ -830,7 +821,7 @@ critical_region_fixup:
+ 	movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped
+ 	testl %ecx,%ecx
+ 	leal (%esp,%ecx,4),%esi		# %esi points at end of src region
+-	leal OLDESP(%esp),%edi		# %edi points at end of dst region
++	leal PT_OLDESP(%esp),%edi	# %edi points at end of dst region
+ 	jle   17f			# skip loop if nothing to copy
+ 16:	subl $4,%esi			# pre-decrementing copy loop
+ 	subl $4,%edi
+@@ -853,8 +844,9 @@ critical_fixup_table:
+ 	.byte 6				# pop  %eax
+ 	.byte 7				# pop  %ds
+ 	.byte 8				# pop  %es
+-	.byte 9,9,9			# add  $4,%esp
+-	.byte 10			# iret
++	.byte 9,9			# pop  %gs
++	.byte 10,10,10			# add  $4,%esp
++	.byte 11			# iret
+ 	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
+ .previous
+ 
+@@ -944,7 +936,7 @@ ENTRY(device_not_available)
+ 	jmp ret_from_exception
+ device_available_emulate:
+ #endif
+-	preempt_stop
++	preempt_stop(CLBR_ANY)
+ 	call math_state_restore
+ 	jmp ret_from_exception
+ 	CFI_ENDPROC
+@@ -1014,7 +1006,7 @@ KPROBE_ENTRY(nmi)
+ 	cmpw $__ESPFIX_SS, %ax
+ 	popl %eax
+ 	CFI_ADJUST_CFA_OFFSET -4
+-	je nmi_16bit_stack
++	je nmi_espfix_stack
+ 	cmpl $sysenter_entry,(%esp)
+ 	je nmi_stack_fixup
+ 	pushl %eax
+@@ -1057,7 +1049,7 @@ nmi_debug_stack_check:
+ 	FIX_STACK(24,nmi_stack_correct, 1)
+ 	jmp nmi_stack_correct
+ 
+-nmi_16bit_stack:
++nmi_espfix_stack:
+ 	/* We have a RING0_INT_FRAME here.
+ 	 *
+ 	 * create the pointer to lss back
+@@ -1066,7 +1058,6 @@ nmi_16bit_stack:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	pushl %esp
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	movzwl %sp, %esp
+ 	addw $4, (%esp)
+ 	/* copy the iret frame of 12 bytes */
+ 	.rept 3
+@@ -1077,11 +1068,11 @@ nmi_16bit_stack:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	FIXUP_ESPFIX_STACK		# %eax == %esp
+-	CFI_ADJUST_CFA_OFFSET -20	# the frame has now moved
+ 	xorl %edx,%edx			# zero error code
+ 	call do_nmi
+ 	RESTORE_REGS
+-	lss 12+4(%esp), %esp		# back to 16bit stack
++	lss 12+4(%esp), %esp		# back to espfix stack
++	CFI_ADJUST_CFA_OFFSET -24
+ 1:	INTERRUPT_RETURN
+ 	CFI_ENDPROC
+ .section __ex_table,"a"
+@@ -1097,12 +1088,25 @@ KPROBE_ENTRY(nmi)
+ 	xorl %edx,%edx		# zero error code
+ 	movl %esp,%eax		# pt_regs pointer
+ 	call do_nmi
+-	orl  $NMI_MASK, EFLAGS(%esp)
++	orl  $NMI_MASK, PT_EFLAGS(%esp)
+ 	jmp restore_all
+ 	CFI_ENDPROC
+ #endif
+ KPROBE_END(nmi)
+ 
++#ifdef CONFIG_PARAVIRT
++ENTRY(native_iret)
++1:	iret
++.section __ex_table,"a"
++	.align 4
++	.long 1b,iret_exc
++.previous
++
++ENTRY(native_irq_enable_sysexit)
++	sti
++	sysexit
++#endif
++
+ KPROBE_ENTRY(int3)
+ 	RING0_INT_FRAME
+ 	pushl $-1			# mark this as an int
+@@ -1218,37 +1222,6 @@ ENTRY(spurious_interrupt_bug)
+ 	CFI_ENDPROC
+ #endif /* !CONFIG_XEN */
+ 
+-#ifdef CONFIG_STACK_UNWIND
+-ENTRY(arch_unwind_init_running)
+-	CFI_STARTPROC
+-	movl	4(%esp), %edx
+-	movl	(%esp), %ecx
+-	leal	4(%esp), %eax
+-	movl	%ebx, EBX(%edx)
+-	xorl	%ebx, %ebx
+-	movl	%ebx, ECX(%edx)
+-	movl	%ebx, EDX(%edx)
+-	movl	%esi, ESI(%edx)
+-	movl	%edi, EDI(%edx)
+-	movl	%ebp, EBP(%edx)
+-	movl	%ebx, EAX(%edx)
+-	movl	$__USER_DS, DS(%edx)
+-	movl	$__USER_DS, ES(%edx)
+-	movl	%ebx, ORIG_EAX(%edx)
+-	movl	%ecx, EIP(%edx)
+-	movl	12(%esp), %ecx
+-	movl	$__KERNEL_CS, CS(%edx)
+-	movl	%ebx, EFLAGS(%edx)
+-	movl	%eax, OLDESP(%edx)
+-	movl	8(%esp), %eax
+-	movl	%ecx, 8(%esp)
+-	movl	EBX(%edx), %ebx
+-	movl	$__KERNEL_DS, OLDSS(%edx)
+-	jmpl	*%eax
+-	CFI_ENDPROC
+-ENDPROC(arch_unwind_init_running)
+-#endif
+-
+ ENTRY(fixup_4gb_segment)
+ 	RING0_EC_FRAME
+ 	pushl $do_fixup_4gb_segment
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:46:27.000000000 +0100
+@@ -9,6 +9,7 @@
+ #include <asm/cache.h>
+ #include <asm/thread_info.h>
+ #include <asm/asm-offsets.h>
++#include <asm/boot.h>
+ #include <asm/dwarf2.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/elfnote.h>
+@@ -35,6 +36,8 @@ ENTRY(startup_32)
+ 	/* Set up the stack pointer */
+ 	movl $(init_thread_union+THREAD_SIZE),%esp
+ 
++	call setup_pda
++
+ 	/* get vendor info */
+ 	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
+ 	XEN_CPUID
+@@ -57,14 +60,58 @@ ENTRY(startup_32)
+ 
+ 	movb $1,X86_HARD_MATH
+ 
+-	xorl %eax,%eax			# Clear FS/GS and LDT
++	xorl %eax,%eax			# Clear FS
+ 	movl %eax,%fs
+-	movl %eax,%gs
++
++	movl $(__KERNEL_PDA),%eax
++	mov  %eax,%gs
++
+ 	cld			# gcc2 wants the direction flag cleared at all times
+ 
+ 	pushl $0		# fake return address for unwinder
+ 	jmp start_kernel
+ 
++/*
++ * Point the GDT at this CPU's PDA.  This will be
++ * cpu_gdt_table and boot_pda.
++ */
++setup_pda:
++	/* get the PDA pointer */
++	movl $boot_pda, %eax
++
++	/* slot the PDA address into the GDT */
++	mov $cpu_gdt_table, %ecx
++	mov %ax, (__KERNEL_PDA+0+2)(%ecx)		/* base & 0x0000ffff */
++	shr $16, %eax
++	mov %al, (__KERNEL_PDA+4+0)(%ecx)		/* base & 0x00ff0000 */
++	mov %ah, (__KERNEL_PDA+4+3)(%ecx)		/* base & 0xff000000 */
++
++	# %esi still points to start_info, and no registers
++	# need to be preserved.
++
++	movl XEN_START_mfn_list(%esi), %ebx
++	movl $(cpu_gdt_table - __PAGE_OFFSET), %eax
++	shrl $PAGE_SHIFT, %eax
++	movl (%ebx,%eax,4), %ecx
++	pushl %ecx			# frame number for set_gdt below
++
++	xorl %esi, %esi
++	xorl %edx, %edx
++	shldl $PAGE_SHIFT, %ecx, %edx
++	shll $PAGE_SHIFT, %ecx
++	orl $0x61, %ecx
++	movl $cpu_gdt_table, %ebx
++	movl $__HYPERVISOR_update_va_mapping, %eax
++	int $0x82
++
++	movl $(PAGE_SIZE_asm / 8), %ecx
++	movl %esp, %ebx
++	movl $__HYPERVISOR_set_gdt, %eax
++	int $0x82
++
++	popl %ecx
++	ret
++
+ #define HYPERCALL_PAGE_OFFSET 0x1000
+ .org HYPERCALL_PAGE_OFFSET
+ ENTRY(hypercall_page)
+@@ -93,7 +140,8 @@ ENTRY(empty_zero_page)
+ /*
+  * The Global Descriptor Table contains 28 quadwords, per-CPU.
+  */
+-	.align L1_CACHE_BYTES
++	.section .data.page_aligned, "aw"
++	.align PAGE_SIZE_asm
+ ENTRY(cpu_gdt_table)
+ 	.quad 0x0000000000000000	/* NULL descriptor */
+ 	.quad 0x0000000000000000	/* 0x0b reserved */
+@@ -135,12 +183,13 @@ ENTRY(cpu_gdt_table)
+ 	.quad 0x0000000000000000	/* 0xc0 APM CS 16 code (16 bit) */
+ 	.quad 0x0000000000000000	/* 0xc8 APM DS    data */
+ 
+-	.quad 0x0000000000000000	/* 0xd0 - ESPFIX 16-bit SS */
+-	.quad 0x0000000000000000	/* 0xd8 - unused */
++	.quad 0x0000000000000000	/* 0xd0 - ESPFIX SS */
++	.quad 0x00cf92000000ffff	/* 0xd8 - PDA */
+ 	.quad 0x0000000000000000	/* 0xe0 - unused */
+ 	.quad 0x0000000000000000	/* 0xe8 - unused */
+ 	.quad 0x0000000000000000	/* 0xf0 - unused */
+ 	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
++	.align PAGE_SIZE_asm
+ 
+ #if CONFIG_XEN_COMPAT <= 0x030002
+ /*
+@@ -165,9 +214,9 @@ ENTRY(cpu_gdt_table)
+ 	.ascii	",ELF_PADDR_OFFSET=0x"
+ 		utoa __PAGE_OFFSET
+ 	.ascii	",VIRT_ENTRY=0x"
+-		utoa (__PAGE_OFFSET + __PHYSICAL_START + VIRT_ENTRY_OFFSET)
++		utoa (__PAGE_OFFSET + LOAD_PHYSICAL_ADDR + VIRT_ENTRY_OFFSET)
+ 	.ascii	",HYPERCALL_PAGE=0x"
+-		utoa ((__PHYSICAL_START+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
++		utoa ((LOAD_PHYSICAL_ADDR+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
+ 	.ascii  ",FEATURES=writable_page_tables"
+ 	.ascii	         "|writable_descriptor_tables"
+ 	.ascii	         "|auto_translated_physmap"
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -34,6 +34,7 @@
+ #include <linux/pci.h>
+ #include <linux/msi.h>
+ #include <linux/htirq.h>
++#include <linux/freezer.h>
+ 
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -199,14 +200,20 @@ static struct IO_APIC_route_entry ioapic
+  * the interrupt, and we need to make sure the entry is fully populated
+  * before that happens.
+  */
+-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++static void
++__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+ {
+-	unsigned long flags;
+ 	union entry_union eu;
+ 	eu.entry = e;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+ 	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+ 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++}
++
++static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__ioapic_write_entry(apic, pin, e);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+@@ -889,8 +896,7 @@ static int __init find_isa_irq_pin(int i
+ 
+ 		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+ 		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+ 		    ) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+@@ -909,8 +915,7 @@ static int __init find_isa_irq_apic(int 
+ 
+ 		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+ 		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+-		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
++		     mp_bus_id_to_type[lbus] == MP_BUS_MCA
+ 		    ) &&
+ 		    (mp_irqs[i].mpc_irqtype == type) &&
+ 		    (mp_irqs[i].mpc_srcbusirq == irq))
+@@ -1043,12 +1048,6 @@ static int EISA_ELCR(unsigned int irq)
+ #define default_MCA_trigger(idx)	(1)
+ #define default_MCA_polarity(idx)	(0)
+ 
+-/* NEC98 interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_NEC98_trigger(idx)     (0)
+-#define default_NEC98_polarity(idx)    (0)
+-
+ static int __init MPBIOS_polarity(int idx)
+ {
+ 	int bus = mp_irqs[idx].mpc_srcbus;
+@@ -1083,11 +1082,6 @@ static int __init MPBIOS_polarity(int id
+ 					polarity = default_MCA_polarity(idx);
+ 					break;
+ 				}
+-				case MP_BUS_NEC98: /* NEC 98 pin */
+-				{
+-					polarity = default_NEC98_polarity(idx);
+-					break;
+-				}
+ 				default:
+ 				{
+ 					printk(KERN_WARNING "broken BIOS!!\n");
+@@ -1157,11 +1151,6 @@ static int MPBIOS_trigger(int idx)
+ 					trigger = default_MCA_trigger(idx);
+ 					break;
+ 				}
+-				case MP_BUS_NEC98: /* NEC 98 pin */
+-				{
+-					trigger = default_NEC98_trigger(idx);
+-					break;
+-				}
+ 				default:
+ 				{
+ 					printk(KERN_WARNING "broken BIOS!!\n");
+@@ -1223,7 +1212,6 @@ static int pin_2_irq(int idx, int apic, 
+ 		case MP_BUS_ISA: /* ISA pin */
+ 		case MP_BUS_EISA:
+ 		case MP_BUS_MCA:
+-		case MP_BUS_NEC98:
+ 		{
+ 			irq = mp_irqs[idx].mpc_srcbusirq;
+ 			break;
+@@ -1291,7 +1279,7 @@ static inline int IO_APIC_irq_trigger(in
+ }
+ 
+ /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+-u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */
++static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */
+ 
+ static int __assign_irq_vector(int irq)
+ {
+@@ -1417,8 +1405,8 @@ static void __init setup_IO_APIC_irqs(vo
+ 			if (!apic && (irq < 16))
+ 				disable_8259A_irq(irq);
+ 		}
+-		ioapic_write_entry(apic, pin, entry);
+ 		spin_lock_irqsave(&ioapic_lock, flags);
++		__ioapic_write_entry(apic, pin, entry);
+ 		set_native_irq_info(irq, TARGET_CPUS);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+@@ -1988,6 +1976,15 @@ static void __init setup_ioapic_ids_from
+ #endif
+ 
+ #ifndef CONFIG_XEN
++static int no_timer_check __initdata;
++
++static int __init notimercheck(char *s)
++{
++	no_timer_check = 1;
++	return 1;
++}
++__setup("no_timer_check", notimercheck);
++
+ /*
+  * There is a nasty bug in some older SMP boards, their mptable lies
+  * about the timer IRQ. We do the following to work around the situation:
+@@ -1996,10 +1993,13 @@ static void __init setup_ioapic_ids_from
+  *	- if this function detects that timer IRQs are defunct, then we fall
+  *	  back to ISA timer IRQs
+  */
+-static int __init timer_irq_works(void)
++int __init timer_irq_works(void)
+ {
+ 	unsigned long t1 = jiffies;
+ 
++	if (no_timer_check)
++		return 1;
++
+ 	local_irq_enable();
+ 	/* Let ten ticks pass... */
+ 	mdelay((10 * 1000) / HZ);
+@@ -2226,9 +2226,15 @@ static inline void unlock_ExtINT_logic(v
+ 	unsigned char save_control, save_freq_select;
+ 
+ 	pin  = find_isa_irq_pin(8, mp_INT);
++	if (pin == -1) {
++		WARN_ON_ONCE(1);
++		return;
++	}
+ 	apic = find_isa_irq_apic(8, mp_INT);
+-	if (pin == -1)
++	if (apic == -1) {
++		WARN_ON_ONCE(1);
+ 		return;
++	}
+ 
+ 	entry0 = ioapic_read_entry(apic, pin);
+ 	clear_IO_APIC_pin(apic, pin);
+@@ -2273,7 +2279,7 @@ int timer_uses_ioapic_pin_0;
+  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
+  * fanatically on his truly buggy board.
+  */
+-static inline void check_timer(void)
++static inline void __init check_timer(void)
+ {
+ 	int apic1, pin1, apic2, pin2;
+ 	int vector;
+@@ -2558,7 +2564,7 @@ device_initcall(ioapic_init_sysfs);
+ int create_irq(void)
+ {
+ 	/* Allocate an unused irq */
+-	int irq, new, vector;
++	int irq, new, vector = 0;
+ 	unsigned long flags;
+ 
+ 	irq = -ENOSPC;
+@@ -2939,8 +2945,8 @@ int io_apic_set_pci_routing (int ioapic,
+ 	if (!ioapic && (irq < 16))
+ 		disable_8259A_irq(irq);
+ 
+-	ioapic_write_entry(ioapic, pin, entry);
+ 	spin_lock_irqsave(&ioapic_lock, flags);
++	__ioapic_write_entry(ioapic, pin, entry);
+ 	set_native_irq_info(irq, TARGET_CPUS);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -177,16 +177,14 @@ static int read_default_ldt(void __user 
+ {
+ 	int err;
+ 	unsigned long size;
+-	void *address;
+ 
+ 	err = 0;
+-	address = &default_ldt[0];
+ 	size = 5*sizeof(struct desc_struct);
+ 	if (size > bytecount)
+ 		size = bytecount;
+ 
+ 	err = size;
+-	if (copy_to_user(ptr, address, size))
++	if (clear_user(ptr, size))
+ 		err = -EFAULT;
+ 
+ 	return err;
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -1,7 +1,7 @@
+ /*
+  *	Intel CPU Microcode Update Driver for Linux
+  *
+- *	Copyright (C) 2000-2004 Tigran Aivazian
++ *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+  *		      2006	Shaohua Li <shaohua.li@intel.com>
+  *
+  *	This driver allows to upgrade microcode on Intel processors
+@@ -43,7 +43,7 @@
+ #include <asm/processor.h>
+ 
+ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
+-MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
++MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+ MODULE_LICENSE("GPL");
+ 
+ static int verbose;
+@@ -195,7 +195,7 @@ static int __init microcode_init (void)
+ 	request_microcode();
+ 
+ 	printk(KERN_INFO 
+-		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
++		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -36,7 +36,7 @@
+ 
+ /* Have we found an MP table */
+ int smp_found_config;
+-unsigned int __initdata maxcpus = NR_CPUS;
++unsigned int __cpuinitdata maxcpus = NR_CPUS;
+ 
+ /*
+  * Various Linux-internal data structures created from the
+@@ -102,10 +102,10 @@ static int __init mpf_checksum(unsigned 
+  */
+ 
+ static int mpc_record; 
+-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __cpuinitdata;
+ 
+ #ifndef CONFIG_XEN
+-static void __devinit MP_processor_info (struct mpc_config_processor *m)
++static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+ {
+  	int ver, apicid;
+ 	physid_mask_t phys_cpu;
+@@ -221,7 +221,7 @@ static void __devinit MP_processor_info 
+ 	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+ }
+ #else
+-void __init MP_processor_info (struct mpc_config_processor *m)
++static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
+ {
+ 	num_processors++;
+ }
+@@ -256,8 +256,6 @@ static void __init MP_bus_info (struct m
+ 		mp_current_pci_id++;
+ 	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
+ 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+-	} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
+-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
+ 	} else {
+ 		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+ 	}
+@@ -842,7 +840,7 @@ void __init mp_register_lapic_address(u6
+ #endif
+ }
+ 
+-void __devinit mp_register_lapic (u8 id, u8 enabled)
++void __cpuinit mp_register_lapic (u8 id, u8 enabled)
+ {
+ 	struct mpc_config_processor processor;
+ 	int boot_cpu = 0;
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -273,7 +273,7 @@ EXPORT_SYMBOL(dma_free_coherent);
+ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+ 				dma_addr_t device_addr, size_t size, int flags)
+ {
+-	void __iomem *mem_base;
++	void __iomem *mem_base = NULL;
+ 	int pages = size >> PAGE_SHIFT;
+ 	int bitmap_size = (pages + 31)/32;
+ 
+@@ -290,14 +290,12 @@ int dma_declare_coherent_memory(struct d
+ 	if (!mem_base)
+ 		goto out;
+ 
+-	dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
++	dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+ 	if (!dev->dma_mem)
+ 		goto out;
+-	memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
+-	dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL);
++	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ 	if (!dev->dma_mem->bitmap)
+ 		goto free1_out;
+-	memset(dev->dma_mem->bitmap, 0, bitmap_size);
+ 
+ 	dev->dma_mem->virt_base = mem_base;
+ 	dev->dma_mem->device_base = device_addr;
+@@ -312,6 +310,8 @@ int dma_declare_coherent_memory(struct d
+  free1_out:
+ 	kfree(dev->dma_mem->bitmap);
+  out:
++	if (mem_base)
++		iounmap(mem_base);
+ 	return 0;
+ }
+ EXPORT_SYMBOL(dma_declare_coherent_memory);
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -60,6 +60,7 @@
+ 
+ #include <asm/tlbflush.h>
+ #include <asm/cpu.h>
++#include <asm/pda.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ 
+@@ -104,28 +105,24 @@ EXPORT_SYMBOL(enable_hlt);
+  */
+ static void poll_idle (void)
+ {
+-	local_irq_enable();
+-
+-	asm volatile(
+-		"2:"
+-		"testl %0, %1;"
+-		"rep; nop;"
+-		"je 2b;"
+-		: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
++	cpu_relax();
+ }
+ 
+ static void xen_idle(void)
+ {
+-	local_irq_disable();
++	current_thread_info()->status &= ~TS_POLLING;
++	/*
++	 * TS_POLLING-cleared state must be visible before we
++	 * test NEED_RESCHED:
++	 */
++	smp_mb();
+ 
+-	if (need_resched())
++	local_irq_disable();
++	if (!need_resched())
++		safe_halt();	/* enables interrupts racelessly */
++	else
+ 		local_irq_enable();
+-	else {
+-		current_thread_info()->status &= ~TS_POLLING;
+-		smp_mb__after_clear_bit();
+-		safe_halt();
+-		current_thread_info()->status |= TS_POLLING;
+-	}
++	current_thread_info()->status |= TS_POLLING;
+ }
+ #ifdef CONFIG_APM_MODULE
+ EXPORT_SYMBOL(default_idle);
+@@ -250,8 +247,8 @@ void show_regs(struct pt_regs * regs)
+ 		regs->eax,regs->ebx,regs->ecx,regs->edx);
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+ 		regs->esi, regs->edi, regs->ebp);
+-	printk(" DS: %04x ES: %04x\n",
+-		0xffff & regs->xds,0xffff & regs->xes);
++	printk(" DS: %04x ES: %04x GS: %04x\n",
++	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
+ 
+ 	cr0 = read_cr0();
+ 	cr2 = read_cr2();
+@@ -282,6 +279,7 @@ int kernel_thread(int (*fn)(void *), voi
+ 
+ 	regs.xds = __USER_DS;
+ 	regs.xes = __USER_DS;
++	regs.xgs = __KERNEL_PDA;
+ 	regs.orig_eax = -1;
+ 	regs.eip = (unsigned long) kernel_thread_helper;
+ 	regs.xcs = __KERNEL_CS | get_kernel_rpl();
+@@ -359,7 +357,6 @@ int copy_thread(int nr, unsigned long cl
+ 	p->thread.eip = (unsigned long) ret_from_fork;
+ 
+ 	savesegment(fs,p->thread.fs);
+-	savesegment(gs,p->thread.gs);
+ 
+ 	tsk = current;
+ 	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+@@ -438,7 +435,7 @@ void dump_thread(struct pt_regs * regs, 
+ 	dump->regs.ds = regs->xds;
+ 	dump->regs.es = regs->xes;
+ 	savesegment(fs,dump->regs.fs);
+-	savesegment(gs,dump->regs.gs);
++	dump->regs.gs = regs->xgs;
+ 	dump->regs.orig_eax = regs->orig_eax;
+ 	dump->regs.eip = regs->eip;
+ 	dump->regs.cs = regs->xcs;
+@@ -635,17 +632,19 @@ struct task_struct fastcall * __switch_t
+ 	if (unlikely(HYPERVISOR_multicall_check(_mcl, mcl - _mcl, NULL)))
+ 		BUG();
+ 
++	/* we're going to use this soon, after a few expensive things */
++	if (next_p->fpu_counter > 5)
++		prefetch(&next->i387.fxsave);
++
+ 	/*
+-	 * Restore %fs and %gs if needed.
++	 * Restore %fs if needed.
+ 	 *
+-	 * Glibc normally makes %fs be zero, and %gs is one of
+-	 * the TLS segments.
++	 * Glibc normally makes %fs be zero.
+ 	 */
+ 	if (unlikely(next->fs))
+ 		loadsegment(fs, next->fs);
+ 
+-	if (next->gs)
+-		loadsegment(gs, next->gs);
++	write_pda(pcurrent, next_p);
+ 
+ 	/*
+ 	 * Now maybe handle debug registers
+@@ -655,6 +654,13 @@ struct task_struct fastcall * __switch_t
+ 
+ 	disable_tsc(prev_p, next_p);
+ 
++	/* If the task has used fpu the last 5 timeslices, just do a full
++	 * restore of the math state immediately to avoid the trap; the
++	 * chances of needing FPU soon are obviously high now
++	 */
++	if (next_p->fpu_counter > 5)
++		math_state_restore();
++
+ 	return prev_p;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2008-01-28 12:24:19.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -3,10 +3,12 @@
+  */
+ #include <linux/pci.h>
+ #include <linux/irq.h>
++#include <asm/pci-direct.h>
++#include <asm/genapic.h>
++#include <asm/cpu.h>
+ 
+ #if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI)
+-
+-static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
++static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev)
+ {
+ 	u8 config, rev;
+ 	u32 word;
+@@ -14,14 +16,12 @@ static void __devinit quirk_intel_irqbal
+ 	/* BIOS may enable hardware IRQ balancing for
+ 	 * E7520/E7320/E7525(revision ID 0x9 and below)
+ 	 * based platforms.
+-	 * Disable SW irqbalance/affinity on those platforms.
++	 * For those platforms, make sure that the genapic is set to 'flat'
+ 	 */
+ 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+ 	if (rev > 0x9)
+ 		return;
+ 
+-	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+-
+ 	/* enable access to config space*/
+ 	pci_read_config_byte(dev, 0xf4, &config);
+ 	pci_write_config_byte(dev, 0xf4, config|0x2);
+@@ -30,6 +30,46 @@ static void __devinit quirk_intel_irqbal
+ 	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+ 
+ 	if (!(word & (1 << 13))) {
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_64
++		if (genapic !=  &apic_flat)
++			panic("APIC mode must be flat on this system\n");
++#elif defined(CONFIG_X86_GENERICARCH)
++		if (genapic != &apic_default)
++			panic("APIC mode must be default(flat) on this system. Use apic=default\n");
++#endif
++#endif
++	}
++
++	/* put back the original value for config space*/
++	if (!(config & 0x2))
++		pci_write_config_byte(dev, 0xf4, config);
++}
++
++void __init quirk_intel_irqbalance(void)
++{
++	u8 config, rev;
++	u32 word;
++
++	/* BIOS may enable hardware IRQ balancing for
++	 * E7520/E7320/E7525(revision ID 0x9 and below)
++	 * based platforms.
++	 * Disable SW irqbalance/affinity on those platforms.
++	 */
++	rev = read_pci_config_byte(0, 0, 0, PCI_CLASS_REVISION);
++	if (rev > 0x9)
++		return;
++
++	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
++
++	/* enable access to config space */
++	config = read_pci_config_byte(0, 0, 0, 0xf4);
++	write_pci_config_byte(0, 0, 0, 0xf4, config|0x2);
++
++	/* read xTPR register */
++	word = read_pci_config_16(0, 0, 0x40, 0x4c);
++
++	if (!(word & (1 << 13))) {
+ 		struct xen_platform_op op;
+ 		printk(KERN_INFO "Disabling irq balancing and affinity\n");
+ 		op.cmd = XENPF_platform_quirk;
+@@ -37,11 +77,12 @@ static void __devinit quirk_intel_irqbal
+ 		WARN_ON(HYPERVISOR_platform_op(&op));
+ 	}
+ 
+-	/* put back the original value for config space*/
++	/* put back the original value for config space */
+ 	if (!(config & 0x2))
+-		pci_write_config_byte(dev, 0xf4, config);
++		write_pci_config_byte(0, 0, 0, 0xf4, config);
+ }
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
+-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);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7320_MCH,  verify_quirk_intel_irqbalance);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7525_MCH,  verify_quirk_intel_irqbalance);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_E7520_MCH,  verify_quirk_intel_irqbalance);
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -76,9 +76,6 @@
+ #include <xen/interface/kexec.h>
+ #endif
+ 
+-/* Forward Declaration. */
+-void __init find_max_pfn(void);
+-
+ static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+ static struct notifier_block xen_panic_block = {
+ 	xen_panic_event, NULL, 0 /* try to go last */
+@@ -89,14 +86,11 @@ int disable_pse __devinitdata = 0;
+ /*
+  * Machine setup..
+  */
+-
+-#ifdef CONFIG_EFI
+-int efi_enabled = 0;
+-EXPORT_SYMBOL(efi_enabled);
+-#endif
++extern struct resource code_resource;
++extern struct resource data_resource;
+ 
+ /* cpu data as detected by the assembly code in head.S */
+-struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
++struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ /* common cpu data for all cpus */
+ struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ EXPORT_SYMBOL(boot_cpu_data);
+@@ -112,12 +106,6 @@ unsigned int machine_submodel_id;
+ unsigned int BIOS_revision;
+ unsigned int mca_pentium_flag;
+ 
+-/* For PCI or other memory-mapped resources */
+-unsigned long pci_mem_start = 0x10000000;
+-#ifdef CONFIG_PCI
+-EXPORT_SYMBOL(pci_mem_start);
+-#endif
+-
+ /* Boot loader ID as an integer, for the benefit of proc_dointvec */
+ int bootloader_type;
+ 
+@@ -150,10 +138,6 @@ struct ist_info ist_info;
+ 	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+ EXPORT_SYMBOL(ist_info);
+ #endif
+-struct e820map e820;
+-#ifdef CONFIG_XEN
+-struct e820map machine_e820;
+-#endif
+ 
+ extern void early_cpu_init(void);
+ extern int root_mountflags;
+@@ -168,209 +152,6 @@ static char command_line[COMMAND_LINE_SI
+ 
+ unsigned char __initdata boot_params[PARAM_SIZE];
+ 
+-static struct resource data_resource = {
+-	.name	= "Kernel data",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource code_resource = {
+-	.name	= "Kernel code",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource system_rom_resource = {
+-	.name	= "System ROM",
+-	.start	= 0xf0000,
+-	.end	= 0xfffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-static struct resource extension_rom_resource = {
+-	.name	= "Extension ROM",
+-	.start	= 0xe0000,
+-	.end	= 0xeffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-static struct resource adapter_rom_resources[] = { {
+-	.name 	= "Adapter ROM",
+-	.start	= 0xc8000,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-}, {
+-	.name 	= "Adapter ROM",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-} };
+-
+-static struct resource video_rom_resource = {
+-	.name 	= "Video ROM",
+-	.start	= 0xc0000,
+-	.end	= 0xc7fff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+-};
+-
+-static struct resource video_ram_resource = {
+-	.name	= "Video RAM area",
+-	.start	= 0xa0000,
+-	.end	= 0xbffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource standard_io_resources[] = { {
+-	.name	= "dma1",
+-	.start	= 0x0000,
+-	.end	= 0x001f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic1",
+-	.start	= 0x0020,
+-	.end	= 0x0021,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer0",
+-	.start	= 0x0040,
+-	.end    = 0x0043,
+-	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer1",
+-	.start  = 0x0050,
+-	.end    = 0x0053,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "keyboard",
+-	.start	= 0x0060,
+-	.end	= 0x006f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma page reg",
+-	.start	= 0x0080,
+-	.end	= 0x008f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic2",
+-	.start	= 0x00a0,
+-	.end	= 0x00a1,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma2",
+-	.start	= 0x00c0,
+-	.end	= 0x00df,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "fpu",
+-	.start	= 0x00f0,
+-	.end	= 0x00ff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-} };
+-
+-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+-
+-static int __init romchecksum(unsigned char *rom, unsigned long length)
+-{
+-	unsigned char *p, sum = 0;
+-
+-	for (p = rom; p < rom + length; p++)
+-		sum += *p;
+-	return sum == 0;
+-}
+-
+-static void __init probe_roms(void)
+-{
+-	unsigned long start, length, upper;
+-	unsigned char *rom;
+-	int	      i;
+-
+-#ifdef CONFIG_XEN
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return;
+-#endif
+-
+-	/* video rom */
+-	upper = adapter_rom_resources[0].start;
+-	for (start = video_rom_resource.start; start < upper; start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		video_rom_resource.start = start;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
+-
+-		/* if checksum okay, trust length byte */
+-		if (length && romchecksum(rom, length))
+-			video_rom_resource.end = start + length - 1;
+-
+-		request_resource(&iomem_resource, &video_rom_resource);
+-		break;
+-	}
+-
+-	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+-	if (start < upper)
+-		start = upper;
+-
+-	/* system rom */
+-	request_resource(&iomem_resource, &system_rom_resource);
+-	upper = system_rom_resource.start;
+-
+-	/* check for extension rom (ignore length byte!) */
+-	rom = isa_bus_to_virt(extension_rom_resource.start);
+-	if (romsignature(rom)) {
+-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+-		if (romchecksum(rom, length)) {
+-			request_resource(&iomem_resource, &extension_rom_resource);
+-			upper = extension_rom_resource.start;
+-		}
+-	}
+-
+-	/* check for adapter roms on 2k boundaries */
+-	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
+-
+-		/* but accept any length that fits if checksum okay */
+-		if (!length || start + length > upper || !romchecksum(rom, length))
+-			continue;
+-
+-		adapter_rom_resources[i].start = start;
+-		adapter_rom_resources[i].end = start + length - 1;
+-		request_resource(&iomem_resource, &adapter_rom_resources[i]);
+-
+-		start = adapter_rom_resources[i++].end & ~2047UL;
+-	}
+-}
+-
+ /*
+  * Point at the empty zero page to start with. We map the real shared_info
+  * page as soon as fixmap is up and running.
+@@ -386,353 +167,6 @@ EXPORT_SYMBOL(phys_to_machine_mapping);
+ start_info_t *xen_start_info;
+ EXPORT_SYMBOL(xen_start_info);
+ 
+-void __init add_memory_region(unsigned long long start,
+-			      unsigned long long size, int type)
+-{
+-	int x;
+-
+-	if (!efi_enabled) {
+-       		x = e820.nr_map;
+-
+-		if (x == E820MAX) {
+-		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+-		    return;
+-		}
+-
+-		e820.map[x].addr = start;
+-		e820.map[x].size = size;
+-		e820.map[x].type = type;
+-		e820.nr_map++;
+-	}
+-} /* add_memory_region */
+-
+-static void __init limit_regions(unsigned long long size)
+-{
+-	unsigned long long current_addr = 0;
+-	int i;
+-
+-	if (efi_enabled) {
+-		efi_memory_desc_t *md;
+-		void *p;
+-
+-		for (p = memmap.map, i = 0; p < memmap.map_end;
+-			p += memmap.desc_size, i++) {
+-			md = p;
+-			current_addr = md->phys_addr + (md->num_pages << 12);
+-			if (md->type == EFI_CONVENTIONAL_MEMORY) {
+-				if (current_addr >= size) {
+-					md->num_pages -=
+-						(((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
+-					memmap.nr_map = i + 1;
+-					return;
+-				}
+-			}
+-		}
+-	}
+-	for (i = 0; i < e820.nr_map; i++) {
+-		current_addr = e820.map[i].addr + e820.map[i].size;
+-		if (current_addr < size)
+-			continue;
+-
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-
+-		if (e820.map[i].addr >= size) {
+-			/*
+-			 * This region starts past the end of the
+-			 * requested size, skip it completely.
+-			 */
+-			e820.nr_map = i;
+-		} else {
+-			e820.nr_map = i + 1;
+-			e820.map[i].size -= current_addr - size;
+-		}
+-		return;
+-	}
+-#ifdef CONFIG_XEN
+-	if (i==e820.nr_map && current_addr < size) {
+-		/*
+-                 * The e820 map finished before our requested size so
+-                 * extend the final entry to the requested address.
+-                 */
+-		--i;
+-		if (e820.map[i].type == E820_RAM)
+-			e820.map[i].size -= current_addr - size;
+-		else
+-			add_memory_region(current_addr, size - current_addr, E820_RAM);
+-	}
+-#endif
+-}
+-
+-#define E820_DEBUG	1
+-
+-static void __init print_memory_map(char *who)
+-{
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		printk(" %s: %016Lx - %016Lx ", who,
+-			e820.map[i].addr,
+-			e820.map[i].addr + e820.map[i].size);
+-		switch (e820.map[i].type) {
+-		case E820_RAM:	printk("(usable)\n");
+-				break;
+-		case E820_RESERVED:
+-				printk("(reserved)\n");
+-				break;
+-		case E820_ACPI:
+-				printk("(ACPI data)\n");
+-				break;
+-		case E820_NVS:
+-				printk("(ACPI NVS)\n");
+-				break;
+-		default:	printk("type %lu\n", e820.map[i].type);
+-				break;
+-		}
+-	}
+-}
+-
+-/*
+- * Sanitize the BIOS e820 map.
+- *
+- * Some e820 responses include overlapping entries.  The following 
+- * replaces the original e820 map with a new one, removing overlaps.
+- *
+- */
+-struct change_member {
+-	struct e820entry *pbios; /* pointer to original bios entry */
+-	unsigned long long addr; /* address for this change point */
+-};
+-static struct change_member change_point_list[2*E820MAX] __initdata;
+-static struct change_member *change_point[2*E820MAX] __initdata;
+-static struct e820entry *overlap_list[E820MAX] __initdata;
+-static struct e820entry new_bios[E820MAX] __initdata;
+-
+-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+-{
+-	struct change_member *change_tmp;
+-	unsigned long current_type, last_type;
+-	unsigned long long last_addr;
+-	int chgidx, still_changing;
+-	int overlap_entries;
+-	int new_bios_entry;
+-	int old_nr, new_nr, chg_nr;
+-	int i;
+-
+-	/*
+-		Visually we're performing the following (1,2,3,4 = memory types)...
+-
+-		Sample memory map (w/overlaps):
+-		   ____22__________________
+-		   ______________________4_
+-		   ____1111________________
+-		   _44_____________________
+-		   11111111________________
+-		   ____________________33__
+-		   ___________44___________
+-		   __________33333_________
+-		   ______________22________
+-		   ___________________2222_
+-		   _________111111111______
+-		   _____________________11_
+-		   _________________4______
+-
+-		Sanitized equivalent (no overlap):
+-		   1_______________________
+-		   _44_____________________
+-		   ___1____________________
+-		   ____22__________________
+-		   ______11________________
+-		   _________1______________
+-		   __________3_____________
+-		   ___________44___________
+-		   _____________33_________
+-		   _______________2________
+-		   ________________1_______
+-		   _________________4______
+-		   ___________________2____
+-		   ____________________33__
+-		   ______________________4_
+-	*/
+-
+-	/* if there's only one memory region, don't bother */
+-	if (*pnr_map < 2)
+-		return -1;
+-
+-	old_nr = *pnr_map;
+-
+-	/* bail out if we find any unreasonable addresses in bios map */
+-	for (i=0; i<old_nr; i++)
+-		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+-			return -1;
+-
+-	/* create pointers for initial change-point information (for sorting) */
+-	for (i=0; i < 2*old_nr; i++)
+-		change_point[i] = &change_point_list[i];
+-
+-	/* record all known change-points (starting and ending addresses),
+-	   omitting those that are for empty memory regions */
+-	chgidx = 0;
+-	for (i=0; i < old_nr; i++)	{
+-		if (biosmap[i].size != 0) {
+-			change_point[chgidx]->addr = biosmap[i].addr;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
+-			change_point[chgidx++]->pbios = &biosmap[i];
+-		}
+-	}
+-	chg_nr = chgidx;    	/* true number of change-points */
+-
+-	/* sort change-point list by memory addresses (low -> high) */
+-	still_changing = 1;
+-	while (still_changing)	{
+-		still_changing = 0;
+-		for (i=1; i < chg_nr; i++)  {
+-			/* if <current_addr> > <last_addr>, swap */
+-			/* or, if current=<start_addr> & last=<end_addr>, swap */
+-			if ((change_point[i]->addr < change_point[i-1]->addr) ||
+-				((change_point[i]->addr == change_point[i-1]->addr) &&
+-				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
+-				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+-			   )
+-			{
+-				change_tmp = change_point[i];
+-				change_point[i] = change_point[i-1];
+-				change_point[i-1] = change_tmp;
+-				still_changing=1;
+-			}
+-		}
+-	}
+-
+-	/* create a new bios memory map, removing overlaps */
+-	overlap_entries=0;	 /* number of entries in the overlap table */
+-	new_bios_entry=0;	 /* index for creating new bios map entries */
+-	last_type = 0;		 /* start with undefined memory type */
+-	last_addr = 0;		 /* start with 0 as last starting address */
+-	/* loop through change-points, determining affect on the new bios map */
+-	for (chgidx=0; chgidx < chg_nr; chgidx++)
+-	{
+-		/* keep track of all overlapping bios entries */
+-		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+-		{
+-			/* add map entry to overlap list (> 1 entry implies an overlap) */
+-			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+-		}
+-		else
+-		{
+-			/* remove entry from list (order independent, so swap with last) */
+-			for (i=0; i<overlap_entries; i++)
+-			{
+-				if (overlap_list[i] == change_point[chgidx]->pbios)
+-					overlap_list[i] = overlap_list[overlap_entries-1];
+-			}
+-			overlap_entries--;
+-		}
+-		/* if there are overlapping entries, decide which "type" to use */
+-		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+-		current_type = 0;
+-		for (i=0; i<overlap_entries; i++)
+-			if (overlap_list[i]->type > current_type)
+-				current_type = overlap_list[i]->type;
+-		/* continue building up new bios map based on this information */
+-		if (current_type != last_type)	{
+-			if (last_type != 0)	 {
+-				new_bios[new_bios_entry].size =
+-					change_point[chgidx]->addr - last_addr;
+-				/* move forward only if the new size was non-zero */
+-				if (new_bios[new_bios_entry].size != 0)
+-					if (++new_bios_entry >= E820MAX)
+-						break; 	/* no more space left for new bios entries */
+-			}
+-			if (current_type != 0)	{
+-				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
+-				new_bios[new_bios_entry].type = current_type;
+-				last_addr=change_point[chgidx]->addr;
+-			}
+-			last_type = current_type;
+-		}
+-	}
+-	new_nr = new_bios_entry;   /* retain count for new bios entries */
+-
+-	/* copy new bios mapping into original location */
+-	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
+-	*pnr_map = new_nr;
+-
+-	return 0;
+-}
+-
+-/*
+- * Copy the BIOS e820 map into a safe place.
+- *
+- * Sanity-check it while we're at it..
+- *
+- * If we're lucky and live on a modern system, the setup code
+- * will have given us a memory map that we can use to properly
+- * set up memory.  If we aren't, we'll fake a memory map.
+- *
+- * We check to see that the memory map contains at least 2 elements
+- * before we'll use it, because the detection code in setup.S may
+- * not be perfect and most every PC known to man has two memory
+- * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
+- * thinkpad 560x, for example, does not cooperate with the memory
+- * detection code.)
+- */
+-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+-{
+-#ifndef CONFIG_XEN
+-	/* Only one memory region (or negative)? Ignore it */
+-	if (nr_map < 2)
+-		return -1;
+-#else
+-	BUG_ON(nr_map < 1);
+-#endif
+-
+-	do {
+-		unsigned long long start = biosmap->addr;
+-		unsigned long long size = biosmap->size;
+-		unsigned long long end = start + size;
+-		unsigned long type = biosmap->type;
+-
+-		/* Overflow in 64 bits? Ignore the memory map. */
+-		if (start > end)
+-			return -1;
+-
+-#ifndef CONFIG_XEN
+-		/*
+-		 * Some BIOSes claim RAM in the 640k - 1M region.
+-		 * Not right. Fix it up.
+-		 */
+-		if (type == E820_RAM) {
+-			if (start < 0x100000ULL && end > 0xA0000ULL) {
+-				if (start < 0xA0000ULL)
+-					add_memory_region(start, 0xA0000ULL-start, type);
+-				if (end <= 0x100000ULL)
+-					continue;
+-				start = 0x100000ULL;
+-				size = end - start;
+-			}
+-		}
+-#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;
+-}
+-
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ struct edd edd;
+ #ifdef CONFIG_EDD_MODULE
+@@ -758,7 +192,7 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
+-static int __initdata user_defined_memmap = 0;
++int __initdata user_defined_memmap = 0;
+ 
+ /*
+  * "mem=nopentium" disables the 4MB page tables.
+@@ -795,51 +229,6 @@ static int __init parse_mem(char *arg)
+ }
+ early_param("mem", parse_mem);
+ 
+-static int __init parse_memmap(char *arg)
+-{
+-	if (!arg)
+-		return -EINVAL;
+-
+-	if (strcmp(arg, "exactmap") == 0) {
+-#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.
+-		 */
+-		find_max_pfn();
+-		saved_max_pfn = max_pfn;
+-#endif
+-		e820.nr_map = 0;
+-		user_defined_memmap = 1;
+-	} else {
+-		/* If the user specifies memory size, we
+-		 * limit the BIOS-provided memory map to
+-		 * that size. exactmap can be used to specify
+-		 * the exact map. mem=number can be used to
+-		 * trim the existing memory map.
+-		 */
+-		unsigned long long start_at, mem_size;
+-
+-		mem_size = memparse(arg, &arg);
+-		if (*arg == '@') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_RAM);
+-		} else if (*arg == '#') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_ACPI);
+-		} else if (*arg == '$') {
+-			start_at = memparse(arg+1, &arg);
+-			add_memory_region(start_at, mem_size, E820_RESERVED);
+-		} else {
+-			limit_regions(mem_size);
+-			user_defined_memmap = 1;
+-		}
+-	}
+-	return 0;
+-}
+-early_param("memmap", parse_memmap);
+-
+ #ifdef CONFIG_PROC_VMCORE
+ /* elfcorehdr= specifies the location of elf core header
+  * stored by the crashed kernel.
+@@ -906,127 +295,6 @@ early_param("reservetop", parse_reservet
+ #endif
+ 
+ /*
+- * Callback for efi_memory_walk.
+- */
+-static int __init
+-efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+-{
+-	unsigned long *max_pfn = arg, pfn;
+-
+-	if (start < end) {
+-		pfn = PFN_UP(end -1);
+-		if (pfn > *max_pfn)
+-			*max_pfn = pfn;
+-	}
+-	return 0;
+-}
+-
+-static int __init
+-efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
+-{
+-	memory_present(0, PFN_UP(start), PFN_DOWN(end));
+-	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;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		const struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; ++i) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-
+-		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.
+-  *
+-  * Note: this function only works correct if the e820 table is sorted and
+-  * not-overlapping, which is the case
+-  */
+-int __init
+-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
+-{
+-	u64 start = s;
+-	u64 end = e;
+-	int i;
+-
+-#ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-#else
+-	if (!is_initial_xendomain())
+-		return 0;
+-	for (i = 0; i < machine_e820.nr_map; ++i) {
+-		const struct e820entry *ei = &machine_e820.map[i];
+-#endif
+-		if (type && ei->type != type)
+-			continue;
+-		/* is the region (part) in overlap with the current region ?*/
+-		if (ei->addr >= end || ei->addr + ei->size <= start)
+-			continue;
+-		/* if the region is at the beginning of <start,end> we move
+-		 * start to the end of the region since it's ok until there
+-		 */
+-		if (ei->addr <= start)
+-			start = ei->addr + ei->size;
+-		/* if start is now at or beyond end, we're done, full
+-		 * coverage */
+-		if (start >= end)
+-			return 1; /* we're done */
+-	}
+-	return 0;
+-}
+-
+-/*
+- * Find the highest page frame number we have available
+- */
+-void __init find_max_pfn(void)
+-{
+-	int i;
+-
+-	max_pfn = 0;
+-	if (efi_enabled) {
+-		efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+-		efi_memmap_walk(efi_memory_present_wrapper, NULL);
+-		return;
+-	}
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		unsigned long start, end;
+-		/* RAM? */
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-		start = PFN_UP(e820.map[i].addr);
+-		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+-		if (start >= end)
+-			continue;
+-		if (end > max_pfn)
+-			max_pfn = end;
+-		memory_present(0, start, end);
+-	}
+-}
+-
+-/*
+  * Determine low and high memory ranges:
+  */
+ unsigned long __init find_max_low_pfn(void)
+@@ -1085,77 +353,6 @@ unsigned long __init find_max_low_pfn(vo
+ 	return max_low_pfn;
+ }
+ 
+-/*
+- * Free all available memory for boot time allocation.  Used
+- * as a callback function by efi_memory_walk()
+- */
+-
+-static int __init
+-free_available_memory(unsigned long start, unsigned long end, void *arg)
+-{
+-	/* check max_low_pfn */
+-	if (start >= (max_low_pfn << PAGE_SHIFT))
+-		return 0;
+-	if (end >= (max_low_pfn << PAGE_SHIFT))
+-		end = max_low_pfn << PAGE_SHIFT;
+-	if (start < end)
+-		free_bootmem(start, end - start);
+-
+-	return 0;
+-}
+-/*
+- * Register fully available low RAM pages with the bootmem allocator.
+- */
+-static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+-{
+-	int i;
+-
+-	if (efi_enabled) {
+-		efi_memmap_walk(free_available_memory, NULL);
+-		return;
+-	}
+-	for (i = 0; i < e820.nr_map; i++) {
+-		unsigned long curr_pfn, last_pfn, size;
+-		/*
+-		 * Reserve usable low memory
+-		 */
+-		if (e820.map[i].type != E820_RAM)
+-			continue;
+-		/*
+-		 * We are rounding up the start address of usable memory:
+-		 */
+-		curr_pfn = PFN_UP(e820.map[i].addr);
+-		if (curr_pfn >= max_low_pfn)
+-			continue;
+-		/*
+-		 * ... and at the end of the usable range downwards:
+-		 */
+-		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+-
+-#ifdef CONFIG_XEN
+-		/*
+-                 * Truncate to the number of actual pages currently
+-                 * present.
+-                 */
+-		if (last_pfn > xen_start_info->nr_pages)
+-			last_pfn = xen_start_info->nr_pages;
+-#endif
+-
+-		if (last_pfn > max_low_pfn)
+-			last_pfn = max_low_pfn;
+-
+-		/*
+-		 * .. finally, did all the rounding and playing
+-		 * around just make the area go away?
+-		 */
+-		if (last_pfn <= curr_pfn)
+-			continue;
+-
+-		size = last_pfn - curr_pfn;
+-		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+-	}
+-}
+-
+ #ifndef CONFIG_XEN
+ /*
+  * workaround for Dell systems that neglect to reserve EBDA
+@@ -1247,8 +444,8 @@ void __init setup_bootmem_allocator(void
+ 	 * the (very unlikely) case of us accidentally initializing the
+ 	 * bootmem allocator with an invalid RAM area.
+ 	 */
+-	reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
+-			 bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
++	reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
++			 bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text));
+ 
+ #ifndef CONFIG_XEN
+ 	/*
+@@ -1330,160 +527,6 @@ void __init remapped_pgdat_init(void)
+ 	}
+ }
+ 
+-/*
+- * Request address space for all standard RAM and ROM resources
+- * and also for regions reported as reserved by the e820.
+- */
+-static void __init
+-legacy_init_iomem_resources(struct e820entry *e820, int nr_map,
+-			    struct resource *code_resource,
+-			    struct resource *data_resource)
+-{
+-	int i;
+-
+-	probe_roms();
+-
+-	for (i = 0; i < nr_map; i++) {
+-		struct resource *res;
+-#ifndef CONFIG_RESOURCES_64BIT
+-		if (e820[i].addr + e820[i].size > 0x100000000ULL)
+-			continue;
+-#endif
+-		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+-		switch (e820[i].type) {
+-		case E820_RAM:	res->name = "System RAM"; break;
+-		case E820_ACPI:	res->name = "ACPI Tables"; break;
+-		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;
+-		default:	res->name = "reserved";
+-		}
+-		res->start = e820[i].addr;
+-		res->end = res->start + e820[i].size - 1;
+-		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		if (request_resource(&iomem_resource, res)) {
+-			kfree(res);
+-			continue;
+-		}
+-		if (e820[i].type == E820_RAM) {
+-			/*
+-			 *  We don't know which RAM region contains kernel data,
+-			 *  so we try it repeatedly and let the resource manager
+-			 *  test it.
+-			 */
+-#ifndef CONFIG_XEN
+-			request_resource(res, code_resource);
+-			request_resource(res, data_resource);
+-#endif
+-#ifdef CONFIG_KEXEC
+-			if (crashk_res.start != crashk_res.end)
+-			     request_resource(res, &crashk_res);
+-#ifdef CONFIG_XEN
+-			xen_machine_kexec_register_resources(res);
+-#endif
+-#endif
+-		}
+-	}
+-}
+-
+-/*
+- * Locate a unused range of the physical address space below 4G which
+- * can be used for PCI mappings.
+- */
+-static void __init
+-e820_setup_gap(struct e820entry *e820, int nr_map)
+-{
+-	unsigned long gapstart, gapsize, round;
+-	unsigned long long last;
+-	int i;
+-
+-	/*
+-	 * Search for the bigest gap in the low 32 bits of the e820
+-	 * memory space.
+-	 */
+-	last = 0x100000000ull;
+-	gapstart = 0x10000000;
+-	gapsize = 0x400000;
+-	i = nr_map;
+-	while (--i >= 0) {
+-		unsigned long long start = e820[i].addr;
+-		unsigned long long end = start + e820[i].size;
+-
+-		/*
+-		 * Since "last" is at most 4GB, we know we'll
+-		 * fit in 32 bits if this condition is true
+-		 */
+-		if (last > end) {
+-			unsigned long gap = last - end;
+-
+-			if (gap > gapsize) {
+-				gapsize = gap;
+-				gapstart = end;
+-			}
+-		}
+-		if (start < last)
+-			last = start;
+-	}
+-
+-	/*
+-	 * See how much we want to round up: start off with
+-	 * rounding to the next 1MB area.
+-	 */
+-	round = 0x100000;
+-	while ((gapsize >> 4) > round)
+-		round += round;
+-	/* Fun with two's complement */
+-	pci_mem_start = (gapstart + round) & -round;
+-
+-	printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
+-		pci_mem_start, gapstart, gapsize);
+-}
+-
+-/*
+- * Request address space for all standard resources
+- *
+- * This is called just before pcibios_init(), which is also a
+- * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
+- */
+-static int __init request_standard_resources(void)
+-{
+-	int	      i;
+-
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return 0;
+-
+-	printk("Setting up standard PCI resources\n");
+-#ifdef CONFIG_XEN
+-	legacy_init_iomem_resources(machine_e820.map, machine_e820.nr_map,
+-				    &code_resource, &data_resource);
+-#else
+-	if (efi_enabled)
+-		efi_initialize_iomem_resources(&code_resource, &data_resource);
+-	else
+-		legacy_init_iomem_resources(e820.map, e820.nr_map,
+-					    &code_resource, &data_resource);
+-#endif
+-
+-	/* EFI systems may still have VGA */
+-	request_resource(&iomem_resource, &video_ram_resource);
+-
+-	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+-		request_resource(&ioport_resource, &standard_io_resources[i]);
+-	return 0;
+-}
+-
+-subsys_initcall(request_standard_resources);
+-
+-static void __init register_memory(void)
+-{
+-#ifdef CONFIG_XEN
+-	if (is_initial_xendomain())
+-		e820_setup_gap(machine_e820.map, machine_e820.nr_map);
+-	else
+-#endif
+-		e820_setup_gap(e820.map, e820.nr_map);
+-}
+-
+ #ifdef CONFIG_MCA
+ static void set_mca_bus(int x)
+ {
+@@ -1493,6 +536,12 @@ static void set_mca_bus(int x)
+ static void set_mca_bus(int x) { }
+ #endif
+ 
++/* Overridden in paravirt.c if CONFIG_PARAVIRT */
++char * __init __attribute__((weak)) memory_setup(void)
++{
++	return machine_specific_memory_setup();
++}
++
+ /*
+  * Determine if we were loaded by an EFI loader.  If so, then we have also been
+  * passed the efi memmap, systab, etc., so we should use these data structures
+@@ -1580,7 +629,7 @@ void __init setup_arch(char **cmdline_p)
+ 		efi_init();
+ 	else {
+ 		printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-		print_memory_map(machine_specific_memory_setup());
++		print_memory_map(memory_setup());
+ 	}
+ 
+ 	copy_edd();
+@@ -1759,7 +808,7 @@ void __init setup_arch(char **cmdline_p)
+ 		get_smp_config();
+ #endif
+ 
+-	register_memory();
++	e820_register_memory();
+ 
+ 	if (is_initial_xendomain()) {
+ #ifdef CONFIG_VT
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -659,6 +659,10 @@ int smp_call_function_single(int cpu, vo
+ 		put_cpu();
+ 		return -EBUSY;
+ 	}
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
+ 	spin_lock_bh(&call_lock);
+ 	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+ 	spin_unlock_bh(&call_lock);
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -61,6 +61,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/processor.h>
+ #include <asm/timer.h>
++#include <asm/time.h>
+ #include <asm/sections.h>
+ 
+ #include "mach_time.h"
+@@ -129,11 +130,11 @@ static DEFINE_PER_CPU(struct vcpu_runsta
+ /* Must be signed, as it's compared with s64 quantities which can be -ve. */
+ #define NS_PER_TICK (1000000000LL/HZ)
+ 
+-static void __clock_was_set(void *unused)
++static void __clock_was_set(struct work_struct *unused)
+ {
+ 	clock_was_set();
+ }
+-static DECLARE_WORK(clock_was_set_work, __clock_was_set, NULL);
++static DECLARE_WORK(clock_was_set_work, __clock_was_set);
+ 
+ /*
+  * GCC 4.3 can turn loops over an induction variable into division. We do
+@@ -528,10 +529,7 @@ static int set_rtc_mmss(unsigned long no
+ 	/* gets recalled with irq locally disabled */
+ 	/* XXX - does irqsave resolve this? -johnstul */
+ 	spin_lock_irqsave(&rtc_lock, flags);
+-	if (efi_enabled)
+-		retval = efi_set_rtc_mmss(nowtime);
+-	else
+-		retval = mach_set_rtc_mmss(nowtime);
++	retval = set_wallclock(nowtime);
+ 	spin_unlock_irqrestore(&rtc_lock, flags);
+ 
+ 	return retval;
+@@ -859,10 +857,7 @@ unsigned long get_cmos_time(void)
+ 
+ 	spin_lock_irqsave(&rtc_lock, flags);
+ 
+-	if (efi_enabled)
+-		retval = efi_get_time();
+-	else
+-		retval = mach_get_cmos_time();
++	retval = get_wallclock();
+ 
+ 	spin_unlock_irqrestore(&rtc_lock, flags);
+ 
+@@ -964,7 +959,7 @@ static void __init hpet_time_init(void)
+ 		printk("Using HPET for base-timer\n");
+ 	}
+ 
+-	time_init_hook();
++	do_time_init();
+ }
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -29,6 +29,8 @@
+ #include <linux/kexec.h>
+ #include <linux/unwind.h>
+ #include <linux/uaccess.h>
++#include <linux/nmi.h>
++#include <linux/bug.h>
+ 
+ #ifdef CONFIG_EISA
+ #include <linux/ioport.h>
+@@ -61,9 +63,6 @@ int panic_on_unrecovered_nmi;
+ 
+ asmlinkage int system_call(void);
+ 
+-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+-		{ 0, 0 }, { 0, 0 } };
+-
+ /* Do we ignore FPU interrupts ? */
+ char ignore_fpu_irq = 0;
+ 
+@@ -100,12 +99,7 @@ asmlinkage void fixup_4gb_segment(void);
+ #endif
+ asmlinkage void machine_check(void);
+ 
+-static int kstack_depth_to_print = 24;
+-#ifdef CONFIG_STACK_UNWIND
+-static int call_trace = 1;
+-#else
+-#define call_trace (-1)
+-#endif
++int kstack_depth_to_print = 24;
+ ATOMIC_NOTIFIER_HEAD(i386die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+@@ -159,25 +153,7 @@ static inline unsigned long print_contex
+ 	return ebp;
+ }
+ 
+-struct ops_and_data {
+-	struct stacktrace_ops *ops;
+-	void *data;
+-};
+-
+-static asmlinkage int
+-dump_trace_unwind(struct unwind_frame_info *info, void *data)
+-{
+-	struct ops_and_data *oad = (struct ops_and_data *)data;
+-	int n = 0;
+-
+-	while (unwind(info) == 0 && UNW_PC(info)) {
+-		n++;
+-		oad->ops->address(oad->data, UNW_PC(info));
+-		if (arch_unw_user_mode(info))
+-			break;
+-	}
+-	return n;
+-}
++#define MSG(msg) ops->warning(data, msg)
+ 
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 	        unsigned long *stack,
+@@ -188,39 +164,6 @@ void dump_trace(struct task_struct *task
+ 	if (!task)
+ 		task = current;
+ 
+-	if (call_trace >= 0) {
+-		int unw_ret = 0;
+-		struct unwind_frame_info info;
+-		struct ops_and_data oad = { .ops = ops, .data = data };
+-
+-		if (regs) {
+-			if (unwind_init_frame_info(&info, task, regs) == 0)
+-				unw_ret = dump_trace_unwind(&info, &oad);
+-		} else if (task == current)
+-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+-		else {
+-			if (unwind_init_blocked(&info, task) == 0)
+-				unw_ret = dump_trace_unwind(&info, &oad);
+-		}
+-		if (unw_ret > 0) {
+-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+-					     UNW_PC(&info));
+-				if (UNW_SP(&info) >= PAGE_OFFSET) {
+-					ops->warning(data, "Leftover inexact backtrace:\n");
+-					stack = (void *)UNW_SP(&info);
+-					if (!stack)
+-						return;
+-					ebp = UNW_FP(&info);
+-				} else
+-					ops->warning(data, "Full inexact backtrace again:\n");
+-			} else if (call_trace >= 1)
+-				return;
+-			else
+-				ops->warning(data, "Full inexact backtrace again:\n");
+-		} else
+-			ops->warning(data, "Inexact backtrace:\n");
+-	}
+ 	if (!stack) {
+ 		unsigned long dummy;
+ 		stack = &dummy;
+@@ -253,6 +196,7 @@ void dump_trace(struct task_struct *task
+ 		stack = (unsigned long*)context->previous_esp;
+ 		if (!stack)
+ 			break;
++		touch_nmi_watchdog();
+ 	}
+ }
+ EXPORT_SYMBOL(dump_trace);
+@@ -385,7 +329,7 @@ void show_registers(struct pt_regs *regs
+ 	 * time of the fault..
+ 	 */
+ 	if (in_kernel) {
+-		u8 __user *eip;
++		u8 *eip;
+ 		int code_bytes = 64;
+ 		unsigned char c;
+ 
+@@ -394,18 +338,20 @@ void show_registers(struct pt_regs *regs
+ 
+ 		printk(KERN_EMERG "Code: ");
+ 
+-		eip = (u8 __user *)regs->eip - 43;
+-		if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
++		eip = (u8 *)regs->eip - 43;
++		if (eip < (u8 *)PAGE_OFFSET ||
++			probe_kernel_address(eip, c)) {
+ 			/* try starting at EIP */
+-			eip = (u8 __user *)regs->eip;
++			eip = (u8 *)regs->eip;
+ 			code_bytes = 32;
+ 		}
+ 		for (i = 0; i < code_bytes; i++, eip++) {
+-			if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
++			if (eip < (u8 *)PAGE_OFFSET ||
++				probe_kernel_address(eip, c)) {
+ 				printk(" Bad EIP value.");
+ 				break;
+ 			}
+-			if (eip == (u8 __user *)regs->eip)
++			if (eip == (u8 *)regs->eip)
+ 				printk("<%02x> ", c);
+ 			else
+ 				printk("%02x ", c);
+@@ -414,43 +360,22 @@ void show_registers(struct pt_regs *regs
+ 	printk("\n");
+ }	
+ 
+-static void handle_BUG(struct pt_regs *regs)
++int is_valid_bugaddr(unsigned long eip)
+ {
+-	unsigned long eip = regs->eip;
+ 	unsigned short ud2;
+ 
+ 	if (eip < PAGE_OFFSET)
+-		return;
+-	if (probe_kernel_address((unsigned short __user *)eip, ud2))
+-		return;
+-	if (ud2 != 0x0b0f)
+-		return;
++		return 0;
++	if (probe_kernel_address((unsigned short *)eip, ud2))
++		return 0;
+ 
+-	printk(KERN_EMERG "------------[ cut here ]------------\n");
+-
+-#ifdef CONFIG_DEBUG_BUGVERBOSE
+-	do {
+-		unsigned short line;
+-		char *file;
+-		char c;
+-
+-		if (probe_kernel_address((unsigned short __user *)(eip + 2),
+-					line))
+-			break;
+-		if (__get_user(file, (char * __user *)(eip + 4)) ||
+-		    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
+-			file = "<bad filename>";
+-
+-		printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
+-		return;
+-	} while (0);
+-#endif
+-	printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
++	return ud2 == 0x0b0f;
+ }
+ 
+-/* This is gone through when something in the kernel
+- * has done something bad and is about to be terminated.
+-*/
++/*
++ * This is gone through when something in the kernel has done something bad and
++ * is about to be terminated.
++ */
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+ 	static struct {
+@@ -458,7 +383,7 @@ void die(const char * str, struct pt_reg
+ 		u32 lock_owner;
+ 		int lock_owner_depth;
+ 	} die = {
+-		.lock =			SPIN_LOCK_UNLOCKED,
++		.lock =			__SPIN_LOCK_UNLOCKED(die.lock),
+ 		.lock_owner =		-1,
+ 		.lock_owner_depth =	0
+ 	};
+@@ -482,7 +407,8 @@ void die(const char * str, struct pt_reg
+ 		unsigned long esp;
+ 		unsigned short ss;
+ 
+-		handle_BUG(regs);
++		report_bug(regs->eip);
++
+ 		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+ 		printk(KERN_EMERG "PREEMPT ");
+@@ -682,8 +608,7 @@ mem_parity_error(unsigned char reason, s
+ {
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+ 		"CPU %d.\n", reason, smp_processor_id());
+-	printk(KERN_EMERG "You probably have a hardware problem with your RAM "
+-			"chips\n");
++	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
+ 	if (panic_on_unrecovered_nmi)
+                 panic("NMI: Not continuing");
+ 
+@@ -741,7 +666,6 @@ void __kprobes die_nmi(struct pt_regs *r
+ 	printk(" on CPU%d, eip %08lx, registers:\n",
+ 		smp_processor_id(), regs->eip);
+ 	show_registers(regs);
+-	printk(KERN_EMERG "console shuts up ...\n");
+ 	console_silent();
+ 	spin_unlock(&nmi_print_lock);
+ 	bust_spinlocks(0);
+@@ -1057,49 +981,24 @@ fastcall void do_spurious_interrupt_bug(
+ #endif
+ }
+ 
+-fastcall void setup_x86_bogus_stack(unsigned char * stk)
++fastcall unsigned long patch_espfix_desc(unsigned long uesp,
++					  unsigned long kesp)
+ {
+-	unsigned long *switch16_ptr, *switch32_ptr;
+-	struct pt_regs *regs;
+-	unsigned long stack_top, stack_bot;
+-	unsigned short iret_frame16_off;
+-	int cpu = smp_processor_id();
+-	/* reserve the space on 32bit stack for the magic switch16 pointer */
+-	memmove(stk, stk + 8, sizeof(struct pt_regs));
+-	switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
+-	regs = (struct pt_regs *)stk;
+-	/* now the switch32 on 16bit stack */
+-	stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+-	stack_top = stack_bot +	CPU_16BIT_STACK_SIZE;
+-	switch32_ptr = (unsigned long *)(stack_top - 8);
+-	iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
+-	/* copy iret frame on 16bit stack */
+-	memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
+-	/* fill in the switch pointers */
+-	switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
+-	switch16_ptr[1] = __ESPFIX_SS;
+-	switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
+-		8 - CPU_16BIT_STACK_SIZE;
+-	switch32_ptr[1] = __KERNEL_DS;
+-}
+-
+-fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
+-{
+-	unsigned long *switch32_ptr;
+-	unsigned char *stack16, *stack32;
+-	unsigned long stack_top, stack_bot;
+-	int len;
+ 	int cpu = smp_processor_id();
+-	stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+-	stack_top = stack_bot +	CPU_16BIT_STACK_SIZE;
+-	switch32_ptr = (unsigned long *)(stack_top - 8);
+-	/* copy the data from 16bit stack to 32bit stack */
+-	len = CPU_16BIT_STACK_SIZE - 8 - sp;
+-	stack16 = (unsigned char *)(stack_bot + sp);
+-	stack32 = (unsigned char *)
+-		(switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
+-	memcpy(stack32, stack16, len);
+-	return stack32;
++	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++	struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
++	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
++	unsigned long new_kesp = kesp - base;
++	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
++	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
++	/* Set up base for espfix segment */
++ 	desc &= 0x00f0ff0000000000ULL;
++ 	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
++		((((__u64)base) << 32) & 0xff00000000000000ULL) |
++		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
++		(lim_pages & 0xffff);
++	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
++	return new_kesp;
+ }
+ #endif
+ 
+@@ -1113,7 +1012,7 @@ fastcall unsigned char * fixup_x86_bogus
+  * Must be called with kernel preemption disabled (in this case,
+  * local interrupts are disabled at the call-site in entry.S).
+  */
+-asmlinkage void math_state_restore(struct pt_regs regs)
++asmlinkage void math_state_restore(void)
+ {
+ 	struct thread_info *thread = current_thread_info();
+ 	struct task_struct *tsk = thread->task;
+@@ -1123,6 +1022,7 @@ asmlinkage void math_state_restore(struc
+ 		init_fpu(tsk);
+ 	restore_fpu(tsk);
+ 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
++	tsk->fpu_counter++;
+ }
+ 
+ #ifndef CONFIG_MATH_EMULATION
+@@ -1234,19 +1134,3 @@ static int __init kstack_setup(char *s)
+ 	return 1;
+ }
+ __setup("kstack=", kstack_setup);
+-
+-#ifdef CONFIG_STACK_UNWIND
+-static int __init call_trace_setup(char *s)
+-{
+-	if (strcmp(s, "old") == 0)
+-		call_trace = -1;
+-	else if (strcmp(s, "both") == 0)
+-		call_trace = 0;
+-	else if (strcmp(s, "newfallback") == 0)
+-		call_trace = 1;
+-	else if (strcmp(s, "new") == 2)
+-		call_trace = 2;
+-	return 1;
+-}
+-__setup("call_trace=", call_trace_setup);
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/vmlinux.lds.S	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vmlinux.lds.S	2009-12-04 10:51:06.000000000 +0100
+@@ -84,6 +84,10 @@ SECTIONS
+ {
+ #ifdef CONFIG_X86_32
+         . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
++#if defined(CONFIG_XEN) && CONFIG_XEN_COMPAT <= 0x030002
++#undef LOAD_OFFSET
++#define LOAD_OFFSET 0
++#endif
+         phys_startup_32 = startup_32 - LOAD_OFFSET;
+ #else
+         . = __START_KERNEL;
+--- head-2010-01-18.orig/arch/x86/kvm/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kvm/Kconfig	2009-11-06 10:46:27.000000000 +0100
+@@ -7,6 +7,7 @@ source "virt/kvm/Kconfig"
+ menuconfig VIRTUALIZATION
+ 	bool "Virtualization"
+ 	depends on HAVE_KVM || X86
++	depends on !XEN
+ 	default y
+ 	---help---
+ 	  Say Y here to get to see options for using your Linux host to run other
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -22,9 +22,9 @@
+ #include <linux/highmem.h>
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
++#include <linux/uaccess.h>
+ 
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+ #include <asm/desc.h>
+ #include <asm/kdebug.h>
+ #include <asm/segment.h>
+@@ -167,7 +167,7 @@ static inline unsigned long get_segment_
+ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
+ { 
+ 	unsigned long limit;
+-	unsigned long instr = get_segment_eip (regs, &limit);
++	unsigned char *instr = (unsigned char *)get_segment_eip (regs, &limit);
+ 	int scan_more = 1;
+ 	int prefetch = 0; 
+ 	int i;
+@@ -177,9 +177,9 @@ static int __is_prefetch(struct pt_regs 
+ 		unsigned char instr_hi;
+ 		unsigned char instr_lo;
+ 
+-		if (instr > limit)
++		if (instr > (unsigned char *)limit)
+ 			break;
+-		if (__get_user(opcode, (unsigned char __user *) instr))
++		if (probe_kernel_address(instr, opcode))
+ 			break; 
+ 
+ 		instr_hi = opcode & 0xf0; 
+@@ -204,9 +204,9 @@ static int __is_prefetch(struct pt_regs 
+ 		case 0x00:
+ 			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+ 			scan_more = 0;
+-			if (instr > limit)
++			if (instr > (unsigned char *)limit)
+ 				break;
+-			if (__get_user(opcode, (unsigned char __user *) instr))
++			if (probe_kernel_address(instr, opcode))
+ 				break;
+ 			prefetch = (instr_lo == 0xF) &&
+ 				(opcode == 0x0D || opcode == 0x18);
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -32,7 +32,7 @@ static void *__kmap_atomic(struct page *
+ 	unsigned long vaddr;
+ 
+ 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+-	inc_preempt_count();
++	pagefault_disable();
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
+@@ -63,26 +63,22 @@ void kunmap_atomic(void *kvaddr, enum km
+ 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+ 	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+ 
+-#ifdef CONFIG_DEBUG_HIGHMEM
+-	if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
+-		dec_preempt_count();
+-		preempt_check_resched();
+-		return;
+-	}
+-
+-	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+-		BUG();
+-#endif
+ 	/*
+ 	 * Force other mappings to Oops if they'll try to access this pte
+ 	 * without first remap it.  Keeping stale mappings around is a bad idea
+ 	 * also, in case the page changes cacheability attributes or becomes
+ 	 * a protected page in a hypervisor.
+ 	 */
+-	kpte_clear_flush(kmap_pte-idx, vaddr);
++	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
++		kpte_clear_flush(kmap_pte-idx, vaddr);
++	else {
++#ifdef CONFIG_DEBUG_HIGHMEM
++		BUG_ON(vaddr < PAGE_OFFSET);
++		BUG_ON(vaddr >= (unsigned long)high_memory);
++#endif
++	}
+ 
+-	dec_preempt_count();
+-	preempt_check_resched();
++	pagefault_enable();
+ }
+ 
+ /* This is the same as kmap_atomic() but can map memory that doesn't
+@@ -93,7 +89,7 @@ void *kmap_atomic_pfn(unsigned long pfn,
+ 	enum fixed_addresses idx;
+ 	unsigned long vaddr;
+ 
+-	inc_preempt_count();
++	pagefault_disable();
+ 
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -233,8 +233,6 @@ static inline int page_kills_ppro(unsign
+ 
+ #endif
+ 
+-extern int is_available_memory(efi_memory_desc_t *);
+-
+ int page_is_ram(unsigned long pagenr)
+ {
+ 	int i;
+@@ -326,7 +324,7 @@ void __init add_one_highpage_init(struct
+ 		SetPageReserved(page);
+ }
+ 
+-static int add_one_highpage_hotplug(struct page *page, unsigned long pfn)
++static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+ {
+ 	free_new_highpage(page, pfn);
+ 	totalram_pages++;
+@@ -343,7 +341,7 @@ static int add_one_highpage_hotplug(stru
+  * has been added dynamically that would be
+  * onlined here is in HIGHMEM
+  */
+-void online_page(struct page *page)
++void __meminit online_page(struct page *page)
+ {
+ 	ClearPageReserved(page);
+ 	add_one_highpage_hotplug(page, page_to_pfn(page));
+@@ -738,16 +736,10 @@ void __init mem_init(void)
+ 	set_bit(PG_pinned, &virt_to_page(init_mm.pgd)->flags);
+ }
+ 
+-/*
+- * this is for the non-NUMA, single node SMP system case.
+- * Specifically, in the case of x86, we will always add
+- * memory to the highmem for now.
+- */
+ #ifdef CONFIG_MEMORY_HOTPLUG
+-#ifndef CONFIG_NEED_MULTIPLE_NODES
+ int arch_add_memory(int nid, u64 start, u64 size)
+ {
+-	struct pglist_data *pgdata = &contig_page_data;
++	struct pglist_data *pgdata = NODE_DATA(nid);
+ 	struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
+ 	unsigned long start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+@@ -759,11 +751,11 @@ int remove_memory(u64 start, u64 size)
+ {
+ 	return -EINVAL;
+ }
+-#endif
++EXPORT_SYMBOL_GPL(remove_memory);
+ #endif
+ 
+-kmem_cache_t *pgd_cache;
+-kmem_cache_t *pmd_cache;
++struct kmem_cache *pgd_cache;
++struct kmem_cache *pmd_cache;
+ 
+ void __init pgtable_cache_init(void)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -203,7 +203,7 @@ void pte_free(struct page *pte)
+ 	__free_page(pte);
+ }
+ 
+-void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags)
++void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags)
+ {
+ 	memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+ }
+@@ -243,7 +243,7 @@ static inline void pgd_list_del(pgd_t *p
+ 		set_page_private(next, (unsigned long)pprev);
+ }
+ 
+-void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
++void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+ {
+ 	unsigned long flags;
+ 
+@@ -264,7 +264,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
+ }
+ 
+ /* never called when PTRS_PER_PMD > 1 */
+-void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
++void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused)
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -768,7 +768,7 @@ static void __init pirq_find_router(stru
+ 	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
+ 	    rt->rtr_vendor, rt->rtr_device);
+ 
+-	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
++	pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
+ 	if (!pirq_router_dev) {
+ 		DBG(KERN_DEBUG "PCI: Interrupt router not found at "
+ 			"%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+@@ -788,6 +788,8 @@ static void __init pirq_find_router(stru
+ 		pirq_router_dev->vendor,
+ 		pirq_router_dev->device,
+ 		pci_name(pirq_router_dev));
++
++	/* The device remains referenced for the kernel lifetime */
+ }
+ 
+ static struct irq_info *pirq_get_info(struct pci_dev *dev)
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:46:27.000000000 +0100
+@@ -261,7 +261,6 @@ ENTRY(system_call)
+ 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
+ 	GET_THREAD_INFO(%rcx)
+ 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+-	CFI_REMEMBER_STATE
+ 	jnz tracesys
+ 	cmpq $__NR_syscall_max,%rax
+ 	ja badsys
+@@ -272,7 +271,6 @@ ENTRY(system_call)
+  * Syscall return path ending with SYSRET (fast path)
+  * Has incomplete stack frame and undefined top of stack. 
+  */		
+-	.globl ret_from_sys_call
+ ret_from_sys_call:
+ 	movl $_TIF_ALLWORK_MASK,%edi
+ 	/* edi:	flagmask */
+@@ -282,8 +280,8 @@ sysret_check:		
+ 	TRACE_IRQS_OFF
+ 	movl threadinfo_flags(%rcx),%edx
+ 	andl %edi,%edx
+-	CFI_REMEMBER_STATE
+ 	jnz  sysret_careful 
++	CFI_REMEMBER_STATE
+ 	/*
+ 	 * sysretq will re-enable interrupts:
+ 	 */
+@@ -292,10 +290,10 @@ sysret_check:		
+ 	RESTORE_ARGS 0,8,0
+         HYPERVISOR_IRET VGCF_IN_SYSCALL
+ 
++	CFI_RESTORE_STATE
+ 	/* Handle reschedules */
+ 	/* edx:	work, edi: workmask */	
+ sysret_careful:
+-	CFI_RESTORE_STATE
+ 	bt $TIF_NEED_RESCHED,%edx
+ 	jnc sysret_signal
+ 	TRACE_IRQS_ON
+@@ -334,7 +332,6 @@ badsys:
+ 
+ 	/* Do syscall tracing */
+ tracesys:			 
+-	CFI_RESTORE_STATE
+ 	SAVE_REST
+ 	movq $-ENOSYS,RAX(%rsp)
+ 	FIXUP_TOP_OF_STACK %rdi
+@@ -350,32 +347,13 @@ tracesys:			 
+ 	call *sys_call_table(,%rax,8)
+ 1:	movq %rax,RAX-ARGOFFSET(%rsp)
+ 	/* Use IRET because user could have changed frame */
+-	jmp int_ret_from_sys_call
+-	CFI_ENDPROC
+-END(system_call)
+ 		
+ /* 
+  * Syscall return path ending with IRET.
+  * Has correct top of stack, but partial stack frame.
+- */ 	
+-ENTRY(int_ret_from_sys_call)
+-	CFI_STARTPROC	simple
+-	CFI_SIGNAL_FRAME
+-	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
+-	/*CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
+-	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
+-	/*CFI_REL_OFFSET	rflags,EFLAGS-ARGOFFSET*/
+-	/*CFI_REL_OFFSET	cs,CS-ARGOFFSET*/
+-	CFI_REL_OFFSET	rip,RIP-ARGOFFSET
+-	CFI_REL_OFFSET	rdx,RDX-ARGOFFSET
+-	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
+-	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
+-	CFI_REL_OFFSET	rdi,RDI-ARGOFFSET
+-	CFI_REL_OFFSET	rsi,RSI-ARGOFFSET
+-	CFI_REL_OFFSET	r8,R8-ARGOFFSET
+-	CFI_REL_OFFSET	r9,R9-ARGOFFSET
+-	CFI_REL_OFFSET	r10,R10-ARGOFFSET
+-	CFI_REL_OFFSET	r11,R11-ARGOFFSET
++ */
++	.globl int_ret_from_sys_call
++int_ret_from_sys_call:
+         XEN_BLOCK_EVENTS(%rsi)
+ 	TRACE_IRQS_OFF
+ 	testb $3,CS-ARGOFFSET(%rsp)
+@@ -428,8 +406,6 @@ int_very_careful:
+ 	popq %rdi
+ 	CFI_ADJUST_CFA_OFFSET -8
+ 	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
+-	XEN_BLOCK_EVENTS(%rsi)
+-	TRACE_IRQS_OFF
+ 	jmp int_restore_rest
+ 	
+ int_signal:
+@@ -445,7 +421,7 @@ int_restore_rest:
+ 	TRACE_IRQS_OFF
+ 	jmp int_with_check
+ 	CFI_ENDPROC
+-END(int_ret_from_sys_call)
++END(system_call)
+ 		
+ /* 
+  * Certain special system calls that need to save a complete full stack frame.
+@@ -1270,36 +1246,3 @@ ENTRY(call_softirq)
+ 	ret
+ 	CFI_ENDPROC
+ ENDPROC(call_softirq)
+-
+-#ifdef CONFIG_STACK_UNWIND
+-ENTRY(arch_unwind_init_running)
+-	CFI_STARTPROC
+-	movq	%r15, R15(%rdi)
+-	movq	%r14, R14(%rdi)
+-	xchgq	%rsi, %rdx
+-	movq	%r13, R13(%rdi)
+-	movq	%r12, R12(%rdi)
+-	xorl	%eax, %eax
+-	movq	%rbp, RBP(%rdi)
+-	movq	%rbx, RBX(%rdi)
+-	movq	(%rsp), %rcx
+-	movq	%rax, R11(%rdi)
+-	movq	%rax, R10(%rdi)
+-	movq	%rax, R9(%rdi)
+-	movq	%rax, R8(%rdi)
+-	movq	%rax, RAX(%rdi)
+-	movq	%rax, RCX(%rdi)
+-	movq	%rax, RDX(%rdi)
+-	movq	%rax, RSI(%rdi)
+-	movq	%rax, RDI(%rdi)
+-	movq	%rax, ORIG_RAX(%rdi)
+-	movq	%rcx, RIP(%rdi)
+-	leaq	8(%rsp), %rcx
+-	movq	$__KERNEL_CS, CS(%rdi)
+-	movq	%rax, EFLAGS(%rdi)
+-	movq	%rcx, RSP(%rdi)
+-	movq	$__KERNEL_DS, SS(%rdi)
+-	jmpq	*%rdx
+-	CFI_ENDPROC
+-ENDPROC(arch_unwind_init_running)
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -104,7 +104,10 @@ void __init x86_64_start_kernel(char * r
+ 		machine_to_phys_order++;
+ 
+ #if 0
+-	for (i = 0; i < 256; i++)
++	/* clear bss before set_intr_gate with early_idt_handler */
++	clear_bss();
++
++	for (i = 0; i < IDT_ENTRIES; i++)
+ 		set_intr_gate(i, early_idt_handler);
+ 	asm volatile("lidt %0" :: "m" (idt_descr));
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -202,14 +202,20 @@ static struct IO_APIC_route_entry ioapic
+  * the interrupt, and we need to make sure the entry is fully populated
+  * before that happens.
+  */
+-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++static void
++__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+ {
+-	unsigned long flags;
+ 	union entry_union eu;
+ 	eu.entry = e;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+ 	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+ 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++}
++
++static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__ioapic_write_entry(apic, pin, e);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+@@ -720,6 +726,22 @@ static int assign_irq_vector(int irq, cp
+ }
+ 
+ #ifndef CONFIG_XEN
++static void __clear_irq_vector(int irq)
++{
++	cpumask_t mask;
++	int cpu, vector;
++
++	BUG_ON(!irq_vector[irq]);
++
++	vector = irq_vector[irq];
++	cpus_and(mask, irq_domain[irq], cpu_online_map);
++	for_each_cpu_mask(cpu, mask)
++		per_cpu(vector_irq, cpu)[vector] = -1;
++
++	irq_vector[irq] = 0;
++	irq_domain[irq] = CPU_MASK_NONE;
++}
++
+ void __setup_vector_irq(int cpu)
+ {
+ 	/* Initialize vector_irq on a new cpu */
+@@ -767,26 +789,65 @@ static void ioapic_register_intr(int irq
+ #define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
+ #endif /* !CONFIG_XEN */
+ 
+-static void __init setup_IO_APIC_irqs(void)
++static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
+ {
+ 	struct IO_APIC_route_entry entry;
+-	int apic, pin, idx, irq, first_notcon = 1, vector;
++	int vector;
+ 	unsigned long flags;
+ 
+-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++	/*
++	 * add it to the IO-APIC irq-routing table:
++	 */
++	memset(&entry,0,sizeof(entry));
+ 
+-		/*
+-		 * add it to the IO-APIC irq-routing table:
+-		 */
+-		memset(&entry,0,sizeof(entry));
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.dest_mode = INT_DEST_MODE;
++	entry.mask = 0;				/* enable IRQ */
++	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+ 
+-		entry.delivery_mode = INT_DELIVERY_MODE;
+-		entry.dest_mode = INT_DEST_MODE;
+-		entry.mask = 0;				/* enable IRQ */
++	entry.trigger = irq_trigger(idx);
++	entry.polarity = irq_polarity(idx);
++
++	if (irq_trigger(idx)) {
++		entry.trigger = 1;
++		entry.mask = 1;
+ 		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	}
++
++	if (/* !apic && */ !IO_APIC_IRQ(irq))
++		return;
++
++	if (IO_APIC_IRQ(irq)) {
++		cpumask_t mask;
++		vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
++		if (vector < 0)
++			return;
++
++		entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
++		entry.vector = vector;
++
++		ioapic_register_intr(irq, vector, IOAPIC_AUTO);
++		if (!apic && (irq < 16))
++			disable_8259A_irq(irq);
++	}
++
++	ioapic_write_entry(apic, pin, entry);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	set_native_irq_info(irq, TARGET_CPUS);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++}
++
++static void __init setup_IO_APIC_irqs(void)
++{
++	int apic, pin, idx, irq, first_notcon = 1;
++
++	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ 
+ 		idx = find_irq_entry(apic,pin,mp_INT);
+ 		if (idx == -1) {
+@@ -798,39 +859,11 @@ static void __init setup_IO_APIC_irqs(vo
+ 			continue;
+ 		}
+ 
+-		entry.trigger = irq_trigger(idx);
+-		entry.polarity = irq_polarity(idx);
+-
+-		if (irq_trigger(idx)) {
+-			entry.trigger = 1;
+-			entry.mask = 1;
+-			entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+-		}
+-
+ 		irq = pin_2_irq(idx, apic, pin);
+ 		add_pin_to_irq(irq, apic, pin);
+ 
+-		if (/* !apic && */ !IO_APIC_IRQ(irq))
+-			continue;
+-
+-		if (IO_APIC_IRQ(irq)) {
+-			cpumask_t mask;
+-			vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
+-			if (vector < 0)
+-				continue;
+-
+-			entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+-			entry.vector = vector;
++		setup_IO_APIC_irq(apic, pin, idx, irq);
+ 
+-			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+-			if (!apic && (irq < 16))
+-				disable_8259A_irq(irq);
+-		}
+-		ioapic_write_entry(apic, pin, entry);
+-
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		set_native_irq_info(irq, TARGET_CPUS);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+ 	}
+ 
+@@ -1826,7 +1859,7 @@ void destroy_irq(unsigned int irq)
+ 	dynamic_irq_cleanup(irq);
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	irq_vector[irq] = 0;
++	__clear_irq_vector(irq);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ }
+ 
+@@ -2131,7 +2164,15 @@ void __init setup_ioapic_dest(void)
+ 			if (irq_entry == -1)
+ 				continue;
+ 			irq = pin_2_irq(irq_entry, ioapic, pin);
+-			set_ioapic_affinity_irq(irq, TARGET_CPUS);
++
++			/* setup_IO_APIC_irqs could fail to get vector for some device
++			 * when you have too many devices, because at that time only boot
++			 * cpu is online.
++			 */
++			if(!irq_vector[irq])
++				setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
++			else
++				set_ioapic_affinity_irq(irq, TARGET_CPUS);
+ 		}
+ 
+ 	}
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -120,7 +120,7 @@ asmlinkage unsigned int do_IRQ(struct pt
+ 
+ 	if (likely(irq < NR_IRQS))
+ 		generic_handle_irq(irq);
+-	else
++	else if (printk_ratelimit())
+ 		printk(KERN_EMERG "%s: %d.%d No irq handler for irq\n",
+ 			__func__, smp_processor_id(), irq);
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -35,8 +35,6 @@
+ int smp_found_config;
+ unsigned int __initdata maxcpus = NR_CPUS;
+ 
+-int acpi_found_madt;
+-
+ /*
+  * Various Linux-internal data structures created from the
+  * MP-table.
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -119,29 +119,23 @@ void exit_idle(void)
+ static void poll_idle (void)
+ {
+ 	local_irq_enable();
+-
+-	asm volatile(
+-		"2:"
+-		"testl %0,%1;"
+-		"rep; nop;"
+-		"je 2b;"
+-		: :
+-		"i" (_TIF_NEED_RESCHED),
+-		"m" (current_thread_info()->flags));
++	cpu_relax();
+ }
+ 
+ static void xen_idle(void)
+ {
++	current_thread_info()->status &= ~TS_POLLING;
++	/*
++	 * TS_POLLING-cleared state must be visible before we
++	 * test NEED_RESCHED:
++	 */
++	smp_mb();
+ 	local_irq_disable();
+-
+-	if (need_resched())
+-		local_irq_enable();
+-	else {
+-		current_thread_info()->status &= ~TS_POLLING;
+-		smp_mb__after_clear_bit();
++	if (!need_resched())
+ 		safe_halt();
+-		current_thread_info()->status |= TS_POLLING;
+-	}
++	else
++		local_irq_enable();
++	current_thread_info()->status |= TS_POLLING;
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+@@ -181,6 +175,12 @@ void cpu_idle (void)
+ 			idle = xen_idle; /* no alternatives */
+ 			if (cpu_is_offline(smp_processor_id()))
+ 				play_dead();
++			/*
++			 * Idle routines should keep interrupts disabled
++			 * from here on, until they go to idle.
++			 * Otherwise, idle callbacks can misfire.
++			 */
++			local_irq_disable();
+ 			enter_idle();
+ 			idle();
+ 			/* In many cases the interrupt that ended idle
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -574,8 +574,7 @@ void __init setup_arch(char **cmdline_p)
+ 	if (LOADER_TYPE && INITRD_START) {
+ 		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
+ 			reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
+-			initrd_start =
+-				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
++			initrd_start = INITRD_START + PAGE_OFFSET;
+ 			initrd_end = initrd_start+INITRD_SIZE;
+ 		}
+ 		else {
+@@ -991,11 +990,8 @@ static void __cpuinit init_amd(struct cp
+ 	/* Fix cpuid4 emulation for more */
+ 	num_cache_leaves = 3;
+ 
+-	/* When there is only one core no need to synchronize RDTSC */
+-	if (num_possible_cpus() == 1)
+-	        set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+-	else
+-	        clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++	/* RDTSC can be speculated around */
++	clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+ }
+ 
+ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -1094,6 +1090,15 @@ static void __cpuinit init_intel(struct 
+ 			set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
+ 	}
+ 
++	if (cpu_has_ds) {
++		unsigned int l1, l2;
++		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
++		if (!(l1 & (1<<11)))
++			set_bit(X86_FEATURE_BTS, c->x86_capability);
++		if (!(l1 & (1<<12)))
++			set_bit(X86_FEATURE_PEBS, c->x86_capability);
++	}
++
+ 	n = c->extended_cpuid_level;
+ 	if (n >= 0x80000008) {
+ 		unsigned eax = cpuid_eax(0x80000008);
+@@ -1113,7 +1118,10 @@ static void __cpuinit init_intel(struct 
+ 		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+ 	if (c->x86 == 6)
+ 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+-	set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++	if (c->x86 == 15)
++		set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++	else
++		clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+  	c->x86_max_cores = intel_num_cpu_cores(c);
+ 
+ 	srat_detect_node();
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -384,12 +384,17 @@ int smp_call_function_single (int cpu, v
+ 		put_cpu();
+ 		return 0;
+ 	}
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
+ 	spin_lock_bh(&call_lock);
+ 	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+ 	spin_unlock_bh(&call_lock);
+ 	put_cpu();
+ 	return 0;
+ }
++EXPORT_SYMBOL(smp_call_function_single);
+ 
+ /*
+  * this function sends a 'generic call function' IPI to all other CPUs
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -30,9 +30,10 @@
+ #include <linux/kprobes.h>
+ #include <linux/kexec.h>
+ #include <linux/unwind.h>
++#include <linux/uaccess.h>
++#include <linux/bug.h>
+ 
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+ #include <asm/debugreg.h>
+@@ -108,12 +109,7 @@ static inline void preempt_conditional_c
+ 	preempt_enable_no_resched();
+ }
+ 
+-static int kstack_depth_to_print = 12;
+-#ifdef CONFIG_STACK_UNWIND
+-static int call_trace = 1;
+-#else
+-#define call_trace (-1)
+-#endif
++int kstack_depth_to_print = 12;
+ 
+ #ifdef CONFIG_KALLSYMS
+ void printk_address(unsigned long address)
+@@ -218,24 +214,7 @@ static unsigned long *in_exception_stack
+ 	return NULL;
+ }
+ 
+-struct ops_and_data {
+-	struct stacktrace_ops *ops;
+-	void *data;
+-};
+-
+-static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
+-{
+-	struct ops_and_data *oad = (struct ops_and_data *)context;
+-	int n = 0;
+-
+-	while (unwind(info) == 0 && UNW_PC(info)) {
+-		n++;
+-		oad->ops->address(oad->data, UNW_PC(info));
+-		if (arch_unw_user_mode(info))
+-			break;
+-	}
+-	return n;
+-}
++#define MSG(txt) ops->warning(data, txt)
+ 
+ /*
+  * x86-64 can have upto three kernel stacks: 
+@@ -250,61 +229,24 @@ static inline int valid_stack_ptr(struct
+         return p > t && p < t + THREAD_SIZE - 3;
+ }
+ 
+-void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack,
++void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
++		unsigned long *stack,
+ 		struct stacktrace_ops *ops, void *data)
+ {
+-	const unsigned cpu = smp_processor_id();
+-	unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
++	const unsigned cpu = get_cpu();
++	unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
+ 	unsigned used = 0;
+ 	struct thread_info *tinfo;
+ 
+ 	if (!tsk)
+ 		tsk = current;
+ 
+-	if (call_trace >= 0) {
+-		int unw_ret = 0;
+-		struct unwind_frame_info info;
+-		struct ops_and_data oad = { .ops = ops, .data = data };
+-
+-		if (regs) {
+-			if (unwind_init_frame_info(&info, tsk, regs) == 0)
+-				unw_ret = dump_trace_unwind(&info, &oad);
+-		} else if (tsk == current)
+-			unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
+-		else {
+-			if (unwind_init_blocked(&info, tsk) == 0)
+-				unw_ret = dump_trace_unwind(&info, &oad);
+-		}
+-		if (unw_ret > 0) {
+-			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+-				ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
+-					     UNW_PC(&info));
+-				if ((long)UNW_SP(&info) < 0) {
+-					ops->warning(data, "Leftover inexact backtrace:\n");
+-					stack = (unsigned long *)UNW_SP(&info);
+-					if (!stack)
+-						return;
+-				} else
+-					ops->warning(data, "Full inexact backtrace again:\n");
+-			} else if (call_trace >= 1)
+-				return;
+-			else
+-				ops->warning(data, "Full inexact backtrace again:\n");
+-		} else
+-			ops->warning(data, "Inexact backtrace:\n");
+-	}
+ 	if (!stack) {
+ 		unsigned long dummy;
+ 		stack = &dummy;
+ 		if (tsk && tsk != current)
+ 			stack = (unsigned long *)tsk->thread.rsp;
+ 	}
+-	/*
+-	 * Align the stack pointer on word boundary, later loops
+-	 * rely on that (and corruption / debug info bugs can cause
+-	 * unaligned values here):
+-	 */
+-	stack = (unsigned long *)((unsigned long)stack & ~(sizeof(long)-1));
+ 
+ 	/*
+ 	 * Print function call entries within a stack. 'cond' is the
+@@ -314,9 +256,9 @@ void dump_trace(struct task_struct *tsk,
+ #define HANDLE_STACK(cond) \
+ 	do while (cond) { \
+ 		unsigned long addr = *stack++; \
+-		if (oops_in_progress ? 		\
+-			__kernel_text_address(addr) : \
+-			kernel_text_address(addr)) { \
++		/* Use unlocked access here because except for NMIs	\
++		   we should be already protected against module unloads */ \
++		if (__kernel_text_address(addr)) { \
+ 			/* \
+ 			 * If the address is either in the text segment of the \
+ 			 * kernel, or in the region which contains vmalloc'ed \
+@@ -379,9 +321,10 @@ void dump_trace(struct task_struct *tsk,
+ 	/*
+ 	 * This handles the process stack:
+ 	 */
+-	tinfo = current_thread_info();
++	tinfo = task_thread_info(tsk);
+ 	HANDLE_STACK (valid_stack_ptr(tinfo, stack));
+ #undef HANDLE_STACK
++	put_cpu();
+ }
+ EXPORT_SYMBOL(dump_trace);
+ 
+@@ -518,30 +461,15 @@ bad:
+ 	printk("\n");
+ }	
+ 
+-void handle_BUG(struct pt_regs *regs)
+-{ 
+-	struct bug_frame f;
+-	long len;
+-	const char *prefix = "";
++int is_valid_bugaddr(unsigned long rip)
++{
++	unsigned short ud2;
+ 
+-	if (user_mode(regs))
+-		return; 
+-	if (__copy_from_user(&f, (const void __user *) regs->rip,
+-			     sizeof(struct bug_frame)))
+-		return; 
+-	if (f.filename >= 0 ||
+-	    f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
+-		return;
+-	len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
+-	if (len < 0 || len >= PATH_MAX)
+-		f.filename = (int)(long)"unmapped filename";
+-	else if (len > 50) {
+-		f.filename += len - 50;
+-		prefix = "...";
+-	}
+-	printk("----------- [cut here ] --------- [please bite here ] ---------\n");
+-	printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
+-} 
++	if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2)))
++		return 0;
++
++	return ud2 == 0x0b0f;
++}
+ 
+ #ifdef CONFIG_BUG
+ void out_of_line_bug(void)
+@@ -621,7 +549,9 @@ void die(const char * str, struct pt_reg
+ {
+ 	unsigned long flags = oops_begin();
+ 
+-	handle_BUG(regs);
++	if (!user_mode(regs))
++		report_bug(regs->rip);
++
+ 	__die(str, regs, err);
+ 	oops_end(flags);
+ 	do_exit(SIGSEGV); 
+@@ -790,8 +720,7 @@ mem_parity_error(unsigned char reason, s
+ {
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+ 		reason);
+-	printk(KERN_EMERG "You probably have a hardware problem with your "
+-		"RAM chips\n");
++	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
+ 
+ 	if (panic_on_unrecovered_nmi)
+ 		panic("NMI: Not continuing");
+@@ -1227,21 +1156,3 @@ static int __init kstack_setup(char *s)
+ 	return 0;
+ }
+ early_param("kstack", kstack_setup);
+-
+-#ifdef CONFIG_STACK_UNWIND
+-static int __init call_trace_setup(char *s)
+-{
+-	if (!s)
+-		return -EINVAL;
+-	if (strcmp(s, "old") == 0)
+-		call_trace = -1;
+-	else if (strcmp(s, "both") == 0)
+-		call_trace = 0;
+-	else if (strcmp(s, "newfallback") == 0)
+-		call_trace = 1;
+-	else if (strcmp(s, "new") == 0)
+-		call_trace = 2;
+-	return 0;
+-}
+-early_param("call_trace", call_trace_setup);
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include <asm/topology.h>
+ 
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
++#define __syscall_clobber "r11","rcx","memory"
+ 
+ int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
+ seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
+@@ -224,8 +225,7 @@ out:
+ 
+ static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
+ 				void __user *oldval, size_t __user *oldlenp,
+-				void __user *newval, size_t newlen,
+-				void **context)
++				void __user *newval, size_t newlen)
+ {
+ 	return -ENOSYS;
+ }
+@@ -277,7 +277,6 @@ static void __cpuinit cpu_vsyscall_init(
+ 	vsyscall_set_cpu(raw_smp_processor_id());
+ }
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+ static int __cpuinit
+ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
+ {
+@@ -286,13 +285,13 @@ cpu_vsyscall_notifier(struct notifier_bl
+ 		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1);
+ 	return NOTIFY_DONE;
+ }
+-#endif
+ 
+ static void __init map_vsyscall(void)
+ {
+ 	extern char __vsyscall_0;
+ 	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+ 
++	/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
+ 	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -23,9 +23,9 @@
+ #include <linux/compiler.h>
+ #include <linux/module.h>
+ #include <linux/kprobes.h>
++#include <linux/uaccess.h>
+ 
+ #include <asm/system.h>
+-#include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/smp.h>
+ #include <asm/tlbflush.h>
+@@ -96,7 +96,7 @@ void bust_spinlocks(int yes)
+ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+ 				unsigned long error_code)
+ { 
+-	unsigned char __user *instr;
++	unsigned char *instr;
+ 	int scan_more = 1;
+ 	int prefetch = 0; 
+ 	unsigned char *max_instr;
+@@ -116,7 +116,7 @@ static noinline int is_prefetch(struct p
+ 		unsigned char instr_hi;
+ 		unsigned char instr_lo;
+ 
+-		if (__get_user(opcode, (char __user *)instr))
++		if (probe_kernel_address(instr, opcode))
+ 			break; 
+ 
+ 		instr_hi = opcode & 0xf0; 
+@@ -154,7 +154,7 @@ static noinline int is_prefetch(struct p
+ 		case 0x00:
+ 			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+ 			scan_more = 0;
+-			if (__get_user(opcode, (char __user *)instr))
++			if (probe_kernel_address(instr, opcode))
+ 				break;
+ 			prefetch = (instr_lo == 0xF) &&
+ 				(opcode == 0x0D || opcode == 0x18);
+@@ -170,7 +170,7 @@ static noinline int is_prefetch(struct p
+ static int bad_address(void *p) 
+ { 
+ 	unsigned long dummy;
+-	return __get_user(dummy, (unsigned long __user *)p);
++	return probe_kernel_address((unsigned long *)p, dummy);
+ } 
+ 
+ void dump_pagetable(unsigned long address)
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -1151,14 +1151,15 @@ static __init int x8664_sysctl_init(void
+ __initcall(x8664_sysctl_init);
+ #endif
+ 
+-/* A pseudo VMAs to allow ptrace access for the vsyscall page.   This only
++/* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
+    covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+    not need special handling anymore. */
+ 
+ static struct vm_area_struct gate_vma = {
+ 	.vm_start = VSYSCALL_START,
+-	.vm_end = VSYSCALL_END,
+-	.vm_page_prot = PAGE_READONLY
++	.vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES << PAGE_SHIFT),
++	.vm_page_prot = PAGE_READONLY_EXEC,
++	.vm_flags = VM_READ | VM_EXEC
+ };
+ 
+ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -330,34 +330,40 @@ static struct page *split_large_page(uns
+ 	return base;
+ } 
+ 
+-
+-static void flush_kernel_map(void *address) 
++static void cache_flush_page(void *adr)
+ {
+-	if (0 && address && cpu_has_clflush) {
+-		/* is this worth it? */ 
+-		int i;
+-		for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) 
+-			asm volatile("clflush (%0)" :: "r" (address + i)); 
+-	} else
+-		asm volatile("wbinvd":::"memory"); 
+-	if (address)
+-		__flush_tlb_one(address);
+-	else
+-		__flush_tlb_all();
++	int i;
++	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
++		asm volatile("clflush (%0)" :: "r" (adr + i));
+ }
+ 
++static void flush_kernel_map(void *arg)
++{
++	struct list_head *l = (struct list_head *)arg;
++	struct page *pg;
+ 
+-static inline void flush_map(unsigned long address)
++	/* When clflush is available always use it because it is
++	   much cheaper than WBINVD */
++	if (!cpu_has_clflush)
++		asm volatile("wbinvd" ::: "memory");
++	list_for_each_entry(pg, l, lru) {
++		void *adr = page_address(pg);
++		if (cpu_has_clflush)
++			cache_flush_page(adr);
++		__flush_tlb_one(adr);
++	}
++}
++
++static inline void flush_map(struct list_head *l)
+ {	
+-	on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
++	on_each_cpu(flush_kernel_map, l, 1, 1);
+ }
+ 
+-static struct page *deferred_pages; /* protected by init_mm.mmap_sem */
++static LIST_HEAD(deferred_pages); /* protected by init_mm.mmap_sem */
+ 
+ static inline void save_page(struct page *fpage)
+ {
+-	fpage->lru.next = (struct list_head *)deferred_pages;
+-	deferred_pages = fpage;
++	list_add(&fpage->lru, &deferred_pages);
+ }
+ 
+ /* 
+@@ -487,18 +493,18 @@ int change_page_attr(struct page *page, 
+ 
+ void global_flush_tlb(void)
+ { 
+-	struct page *dpage;
++	struct page *pg, *next;
++	struct list_head l;
+ 
+ 	down_read(&init_mm.mmap_sem);
+-	dpage = xchg(&deferred_pages, NULL);
++	list_replace_init(&deferred_pages, &l);
+ 	up_read(&init_mm.mmap_sem);
+ 
+-	flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0);
+-	while (dpage) {
+-		struct page *tmp = dpage;
+-		dpage = (struct page *)dpage->lru.next;
+-		ClearPagePrivate(tmp);
+-		__free_page(tmp);
++	flush_map(&l);
++
++	list_for_each_entry_safe(pg, next, &l, lru) {
++		ClearPagePrivate(pg);
++		__free_page(pg);
+ 	} 
+ } 
+ 
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 10:49:14.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-11-06 10:46:27.000000000 +0100
+@@ -273,10 +273,8 @@ void disable_msi_mode(struct pci_dev *de
+ 		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 */
+-	}
++
++	pci_intx(dev, 1);  /* enable intx */
+ }
+ 
+ static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
+@@ -294,10 +292,8 @@ static void enable_msi_mode(struct pci_d
+ 		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 */
+-	}
++
++	pci_intx(dev, 0);  /* disable intx */
+ }
+ 
+ #ifdef CONFIG_PM
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2010-01-04 12:19:20.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2009-11-06 10:46:27.000000000 +0100
+@@ -94,8 +94,8 @@ static unsigned long frame_list[PAGE_SIZ
+ static LIST_HEAD(ballooned_pages);
+ 
+ /* Main work function, always executed in process context. */
+-static void balloon_process(void *unused);
+-static DECLARE_WORK(balloon_worker, balloon_process, NULL);
++static void balloon_process(struct work_struct *unused);
++static DECLARE_WORK(balloon_worker, balloon_process);
+ static struct timer_list balloon_timer;
+ 
+ /* When ballooning out (allocating memory to return to Xen) we don't really 
+@@ -402,7 +402,7 @@ static int decrease_reservation(unsigned
+  * by the balloon lock), or with changes to the Xen hard limit, but we will
+  * recover from these in time.
+  */
+-static void balloon_process(void *unused)
++static void balloon_process(struct work_struct *unused)
+ {
+ 	int need_sleep = 0;
+ 	long credit;
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2010-01-04 12:22:06.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2009-11-06 10:46:27.000000000 +0100
+@@ -37,6 +37,7 @@
+ 
+ #include <linux/spinlock.h>
+ #include <linux/kthread.h>
++#include <linux/freezer.h>
+ #include <linux/list.h>
+ #include <linux/delay.h>
+ #include <xen/balloon.h>
+--- head-2010-01-18.orig/drivers/xen/blkback/interface.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/interface.c	2010-01-04 12:24:22.000000000 +0100
+@@ -35,7 +35,7 @@
+ #include <linux/kthread.h>
+ #include <linux/delay.h>
+ 
+-static kmem_cache_t *blkif_cachep;
++static struct kmem_cache *blkif_cachep;
+ 
+ blkif_t *blkif_alloc(domid_t domid)
+ {
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:17:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:17:45.000000000 +0100
+@@ -71,7 +71,7 @@ static int setup_blkring(struct xenbus_d
+ static void kick_pending_request_queues(struct blkfront_info *);
+ 
+ static irqreturn_t blkif_int(int irq, void *dev_id);
+-static void blkif_restart_queue(void *arg);
++static void blkif_restart_queue(struct work_struct *arg);
+ static void blkif_recover(struct blkfront_info *);
+ static void blkif_completion(struct blk_shadow *);
+ static void blkif_free(struct blkfront_info *, int);
+@@ -111,7 +111,7 @@ static int blkfront_probe(struct xenbus_
+ 	info->xbdev = dev;
+ 	info->vdevice = vdevice;
+ 	info->connected = BLKIF_STATE_DISCONNECTED;
+-	INIT_WORK(&info->work, blkif_restart_queue, (void *)info);
++	INIT_WORK(&info->work, blkif_restart_queue);
+ 
+ 	for (i = 0; i < BLK_RING_SIZE; i++)
+ 		info->shadow[i].req.id = i+1;
+@@ -465,9 +465,9 @@ static void kick_pending_request_queues(
+ 	}
+ }
+ 
+-static void blkif_restart_queue(void *arg)
++static void blkif_restart_queue(struct work_struct *arg)
+ {
+-	struct blkfront_info *info = (struct blkfront_info *)arg;
++	struct blkfront_info *info = container_of(arg, struct blkfront_info, work);
+ 	spin_lock_irq(&blkif_io_lock);
+ 	if (info->connected == BLKIF_STATE_CONNECTED)
+ 		kick_pending_request_queues(info);
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2010-01-04 12:22:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2009-11-06 10:46:27.000000000 +0100
+@@ -40,6 +40,7 @@
+ 
+ #include <linux/spinlock.h>
+ #include <linux/kthread.h>
++#include <linux/freezer.h>
+ #include <linux/list.h>
+ #include <asm/hypervisor.h>
+ #include "common.h"
+--- head-2010-01-18.orig/drivers/xen/blktap/interface.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/interface.c	2010-01-04 12:24:32.000000000 +0100
+@@ -35,7 +35,7 @@
+ #include <xen/evtchn.h>
+ #include <linux/delay.h>
+ 
+-static kmem_cache_t *blkif_cachep;
++static struct kmem_cache *blkif_cachep;
+ 
+ blkif_t *tap_alloc_blkif(domid_t domid)
+ {
+--- head-2010-01-18.orig/drivers/xen/char/mem.c	2007-08-06 15:10:49.000000000 +0200
++++ head-2010-01-18/drivers/xen/char/mem.c	2009-11-06 10:46:27.000000000 +0100
+@@ -157,7 +157,7 @@ static loff_t memory_lseek(struct file *
+ {
+ 	loff_t ret;
+ 
+-	mutex_lock(&file->f_dentry->d_inode->i_mutex);
++	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
+ 	switch (orig) {
+ 		case 0:
+ 			file->f_pos = offset;
+@@ -172,7 +172,7 @@ static loff_t memory_lseek(struct file *
+ 		default:
+ 			ret = -EINVAL;
+ 	}
+-	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
++	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
+ 	return ret;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/console/console.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/console/console.c	2009-11-06 10:46:27.000000000 +0100
+@@ -85,11 +85,6 @@ static int xc_num = -1;
+ #define XEN_HVC_MAJOR 229
+ #define XEN_HVC_MINOR 0
+ 
+-#ifdef CONFIG_MAGIC_SYSRQ
+-static unsigned long sysrq_requested;
+-extern int sysrq_enabled;
+-#endif
+-
+ static int __init xencons_setup(char *str)
+ {
+ 	char *q;
+@@ -354,8 +349,8 @@ void __init dom0_init_screen_info(const 
+ #define DUMMY_TTY(_tty) ((xc_mode == XC_TTY) &&		\
+ 			 ((_tty)->index != (xc_num - 1)))
+ 
+-static struct termios *xencons_termios[MAX_NR_CONSOLES];
+-static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
++static struct ktermios *xencons_termios[MAX_NR_CONSOLES];
++static struct ktermios *xencons_termios_locked[MAX_NR_CONSOLES];
+ static struct tty_struct *xencons_tty;
+ static int xencons_priv_irq;
+ static char x_char;
+@@ -371,7 +366,9 @@ void xencons_rx(char *buf, unsigned len)
+ 
+ 	for (i = 0; i < len; i++) {
+ #ifdef CONFIG_MAGIC_SYSRQ
+-		if (sysrq_enabled) {
++		if (sysrq_on()) {
++			static unsigned long sysrq_requested;
++
+ 			if (buf[i] == '\x0f') { /* ^O */
+ 				if (!sysrq_requested) {
+ 					sysrq_requested = jiffies;
+--- head-2010-01-18.orig/drivers/xen/core/reboot.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/reboot.c	2009-11-06 10:46:27.000000000 +0100
+@@ -34,8 +34,8 @@ 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);
++static void __shutdown_handler(struct work_struct *unused);
++static DECLARE_DELAYED_WORK(shutdown_work, __shutdown_handler);
+ 
+ static int setup_suspend_evtchn(void);
+ 
+@@ -105,7 +105,7 @@ static int xen_suspend(void *__unused)
+ 	case SHUTDOWN_RESUMING:
+ 		break;
+ 	default:
+-		schedule_work(&shutdown_work);
++		schedule_delayed_work(&shutdown_work, 0);
+ 		break;
+ 	}
+ 
+@@ -137,12 +137,12 @@ static void switch_shutdown_state(int ne
+ 
+ 	/* Either we kick off the work, or we leave it to xen_suspend(). */
+ 	if (old_state == SHUTDOWN_INVALID)
+-		schedule_work(&shutdown_work);
++		schedule_delayed_work(&shutdown_work, 0);
+ 	else
+ 		BUG_ON(old_state != SHUTDOWN_RESUMING);
+ }
+ 
+-static void __shutdown_handler(void *unused)
++static void __shutdown_handler(struct work_struct *unused)
+ {
+ 	int err;
+ 
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:46:27.000000000 +0100
+@@ -160,7 +160,12 @@ static void xen_smp_intr_exit(unsigned i
+ 
+ void __cpuinit cpu_bringup(void)
+ {
++#ifdef __i386__
++	cpu_set_gdt(current_thread_info()->cpu);
++	secondary_cpu_init();
++#else
+ 	cpu_init();
++#endif
+ 	identify_cpu(cpu_data + smp_processor_id());
+ 	touch_softlockup_watchdog();
+ 	preempt_disable();
+@@ -299,11 +304,12 @@ void __init smp_prepare_cpus(unsigned in
+ 		if (cpu == 0)
+ 			continue;
+ 
++		idle = fork_idle(cpu);
++		if (IS_ERR(idle))
++			panic("failed fork for CPU %d", cpu);
++
+ #ifdef __x86_64__
+ 		gdt_descr = &cpu_gdt_descr[cpu];
+-#else
+-		gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+-#endif
+ 		gdt_descr->address = get_zeroed_page(GFP_KERNEL);
+ 		if (unlikely(!gdt_descr->address)) {
+ 			printk(KERN_CRIT "CPU%d failed to allocate GDT\n",
+@@ -312,6 +318,11 @@ void __init smp_prepare_cpus(unsigned in
+ 		}
+ 		gdt_descr->size = GDT_SIZE;
+ 		memcpy((void *)gdt_descr->address, cpu_gdt_table, GDT_SIZE);
++#else
++		if (unlikely(!init_gdt(cpu, idle)))
++			continue;
++		gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
++#endif
+ 		make_page_readonly(
+ 			(void *)gdt_descr->address,
+ 			XENFEAT_writable_descriptor_tables);
+@@ -331,10 +342,6 @@ void __init smp_prepare_cpus(unsigned in
+ 		cpu_2_logical_apicid[cpu] = apicid;
+ 		x86_cpu_to_apicid[cpu] = apicid;
+ 
+-		idle = fork_idle(cpu);
+-		if (IS_ERR(idle))
+-			panic("failed fork for CPU %d", cpu);
+-
+ #ifdef __x86_64__
+ 		cpu_pda(cpu)->pcurrent = idle;
+ 		cpu_pda(cpu)->cpunumber = cpu;
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenfb.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-11-06 10:46:27.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/mm.h>
+ #include <linux/mutex.h>
++#include <linux/freezer.h>
+ #include <asm/hypervisor.h>
+ #include <xen/evtchn.h>
+ #include <xen/interface/io/fbif.h>
+--- head-2010-01-18.orig/drivers/xen/netback/loopback.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/loopback.c	2009-11-06 10:46:27.000000000 +0100
+@@ -54,6 +54,7 @@
+ #include <net/dst.h>
+ #include <net/xfrm.h>		/* secpath_reset() */
+ #include <asm/hypervisor.h>	/* is_initial_xendomain() */
++#include <../net/core/kmap_skb.h> /* k{,un}map_skb_frag() */
+ 
+ static int nloopbacks = -1;
+ module_param(nloopbacks, int, 0);
+--- head-2010-01-18.orig/drivers/xen/pciback/conf_space_header.c	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/conf_space_header.c	2009-11-06 10:46:27.000000000 +0100
+@@ -22,14 +22,14 @@ static int command_write(struct pci_dev 
+ {
+ 	int err;
+ 
+-	if (!dev->is_enabled && is_enable_cmd(value)) {
++	if (!atomic_read(&dev->enable_cnt) && is_enable_cmd(value)) {
+ 		if (unlikely(verbose_request))
+ 			printk(KERN_DEBUG "pciback: %s: enable\n",
+ 			       pci_name(dev));
+ 		err = pci_enable_device(dev);
+ 		if (err)
+ 			return err;
+-	} else if (dev->is_enabled && !is_enable_cmd(value)) {
++	} else if (atomic_read(&dev->enable_cnt) && !is_enable_cmd(value)) {
+ 		if (unlikely(verbose_request))
+ 			printk(KERN_DEBUG "pciback: %s: disable\n",
+ 			       pci_name(dev));
+--- head-2010-01-18.orig/drivers/xen/pciback/pciback.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/pciback.h	2009-11-06 10:46:27.000000000 +0100
+@@ -100,7 +100,7 @@ void pciback_release_devices(struct pcib
+ 
+ /* Handles events from front-end */
+ irqreturn_t pciback_handle_event(int irq, void *dev_id);
+-void pciback_do_op(void *data);
++void pciback_do_op(struct work_struct *work);
+ 
+ int pciback_xenbus_register(void);
+ void pciback_xenbus_unregister(void);
+--- head-2010-01-18.orig/drivers/xen/pciback/pciback_ops.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/pciback_ops.c	2009-11-06 10:46:27.000000000 +0100
+@@ -26,7 +26,7 @@ void pciback_reset_device(struct pci_dev
+ 
+ 		pci_write_config_word(dev, PCI_COMMAND, 0);
+ 
+-		dev->is_enabled = 0;
++		atomic_set(&dev->enable_cnt, 0);
+ 		dev->is_busmaster = 0;
+ 	} else {
+ 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+@@ -67,9 +67,9 @@ void test_and_schedule_op(struct pciback
+  * 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)
++void pciback_do_op(struct work_struct *work)
+ {
+-	struct pciback_device *pdev = data;
++	struct pciback_device *pdev = container_of(work, struct pciback_device, op_work);
+ 	struct pci_dev *dev;
+ 	struct xen_pci_op *op = &pdev->sh_info->op;
+ 
+--- head-2010-01-18.orig/drivers/xen/pciback/xenbus.c	2009-04-07 13:58:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/pciback/xenbus.c	2009-11-06 10:46:27.000000000 +0100
+@@ -33,7 +33,7 @@ static struct pciback_device *alloc_pdev
+ 	pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
+ 	pdev->be_watching = 0;
+ 
+-	INIT_WORK(&pdev->op_work, pciback_do_op, pdev);
++	INIT_WORK(&pdev->op_work, pciback_do_op);
+ 
+ 	if (pciback_init_devices(pdev)) {
+ 		kfree(pdev);
+--- head-2010-01-18.orig/drivers/xen/pcifront/pci_op.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/pci_op.c	2009-11-06 10:46:27.000000000 +0100
+@@ -636,9 +636,9 @@ static pci_ers_result_t pcifront_common_
+ }
+ 
+ 
+-void pcifront_do_aer(void *data)
++void pcifront_do_aer(struct work_struct *data)
+ {
+-	struct pcifront_device *pdev = data;
++	struct pcifront_device *pdev = container_of(data, struct pcifront_device, op_work);
+ 	int cmd = pdev->sh_info->aer_op.cmd;
+ 	pci_channel_state_t state = 
+ 		(pci_channel_state_t)pdev->sh_info->aer_op.err;
+--- head-2010-01-18.orig/drivers/xen/pcifront/pcifront.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/pcifront.h	2009-11-06 10:46:27.000000000 +0100
+@@ -48,7 +48,7 @@ int pcifront_rescan_root(struct pcifront
+ 			 unsigned int domain, unsigned int bus);
+ void pcifront_free_roots(struct pcifront_device *pdev);
+ 
+-void pcifront_do_aer( void *data);
++void pcifront_do_aer(struct work_struct *data);
+ 
+ irqreturn_t pcifront_handler_aer(int irq, void *dev);
+ 
+--- head-2010-01-18.orig/drivers/xen/pcifront/xenbus.c	2009-04-07 13:58:48.000000000 +0200
++++ head-2010-01-18/drivers/xen/pcifront/xenbus.c	2009-11-06 10:46:27.000000000 +0100
+@@ -49,7 +49,7 @@ static struct pcifront_device *alloc_pde
+ 	pdev->evtchn = INVALID_EVTCHN;
+ 	pdev->gnt_ref = INVALID_GRANT_REF;
+ 
+-	INIT_WORK(&pdev->op_work, pcifront_do_aer, pdev);
++	INIT_WORK(&pdev->op_work, pcifront_do_aer);
+ 
+ 	dev_dbg(&xdev->dev, "Allocated pdev @ 0x%p pdev->sh_info @ 0x%p\n",
+ 		pdev, pdev->sh_info);
+--- head-2010-01-18.orig/drivers/xen/scsiback/interface.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/interface.c	2010-01-04 12:24:50.000000000 +0100
+@@ -40,7 +40,7 @@
+ #include <linux/delay.h>
+ 
+ 
+-static kmem_cache_t *scsiback_cachep;
++static struct kmem_cache *scsiback_cachep;
+ 
+ struct vscsibk_info *vscsibk_info_alloc(domid_t domid)
+ {
+--- head-2010-01-18.orig/drivers/xen/scsiback/scsiback.c	2010-01-04 12:23:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/scsiback.c	2009-11-06 10:46:27.000000000 +0100
+@@ -349,13 +349,11 @@ static int scsiback_merge_bio(struct req
+ 
+ 	if (!rq->bio)
+ 		blk_rq_bio_prep(q, rq, bio);
+-	else if (!q->back_merge_fn(q, rq, bio))
++	else if (!ll_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;
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:17:16.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:17:54.000000000 +0100
+@@ -465,7 +465,7 @@ netfront_accel_enqueue_skb_multi(netfron
+ 
+ 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+-		*(u16*)(skb->h.raw + skb->csum) = 0;
++		*(u16*)(skb->h.raw + skb->csum_offset) = 0;
+ 	}
+ 
+ 	if (multi_post_start_new_buffer(vnic, &state)) {
+@@ -584,7 +584,7 @@ netfront_accel_enqueue_skb_single(netfro
+ 
+ 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		/* Set to zero to encourage falcon to work it out for us */
+-		*(u16*)(skb->h.raw + skb->csum) = 0;
++		*(u16*)(skb->h.raw + skb->csum_offset) = 0;
+ 	}
+ 	NETFRONT_ACCEL_PKTBUFF_FOR_EACH_FRAGMENT
+ 		(skb, idx, frag_data, frag_len, {
+--- head-2010-01-18.orig/drivers/xen/tpmback/interface.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/interface.c	2010-01-04 12:25:38.000000000 +0100
+@@ -16,7 +16,7 @@
+ #include <xen/balloon.h>
+ #include <xen/gnttab.h>
+ 
+-static kmem_cache_t *tpmif_cachep;
++static struct kmem_cache *tpmif_cachep;
+ int num_frontends = 0;
+ 
+ LIST_HEAD(tpmif_list);
+--- head-2010-01-18.orig/drivers/xen/usbback/usbback.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/usbback.c	2010-01-04 12:25:52.000000000 +0100
+@@ -540,9 +540,10 @@ struct set_interface_request {
+ 	struct work_struct work;
+ };
+ 
+-static void usbbk_set_interface_work(void *data)
++static void usbbk_set_interface_work(struct work_struct *arg)
+ {
+-	struct set_interface_request *req = (struct set_interface_request *) data;
++	struct set_interface_request *req
++		= container_of(arg, struct set_interface_request, work);
+ 	pending_req_t *pending_req = req->pending_req;
+ 	struct usb_device *udev = req->pending_req->stub->udev;
+ 
+@@ -570,7 +571,7 @@ static int usbbk_set_interface(pending_r
+ 	req->pending_req = pending_req;
+ 	req->interface = interface;
+ 	req->alternate = alternate;
+-	INIT_WORK(&req->work, usbbk_set_interface_work, req);
++	INIT_WORK(&req->work, usbbk_set_interface_work);
+ 	usb_get_dev(udev);
+ 	schedule_work(&req->work);
+ 	return 0;
+@@ -582,9 +583,10 @@ struct clear_halt_request {
+ 	struct work_struct work;
+ };
+ 
+-static void usbbk_clear_halt_work(void *data)
++static void usbbk_clear_halt_work(struct work_struct *arg)
+ {
+-	struct clear_halt_request *req = (struct clear_halt_request *) data;
++	struct clear_halt_request *req
++		= container_of(arg, struct clear_halt_request, work);
+ 	pending_req_t *pending_req = req->pending_req;
+ 	struct usb_device *udev = req->pending_req->stub->udev;
+ 	int ret;
+@@ -610,7 +612,7 @@ static int usbbk_clear_halt(pending_req_
+ 		return -ENOMEM;
+ 	req->pending_req = pending_req;
+ 	req->pipe = pipe;
+-	INIT_WORK(&req->work, usbbk_clear_halt_work, req);
++	INIT_WORK(&req->work, usbbk_clear_halt_work);
+ 
+ 	usb_get_dev(udev);
+ 	schedule_work(&req->work);
+@@ -623,9 +625,10 @@ struct port_reset_request {
+ 	struct work_struct work;
+ };
+ 
+-static void usbbk_port_reset_work(void *data)
++static void usbbk_port_reset_work(struct work_struct *arg)
+ {
+-	struct port_reset_request *req = (struct port_reset_request *) data;
++	struct port_reset_request *req
++		= container_of(arg, struct port_reset_request, work);
+ 	pending_req_t *pending_req = req->pending_req;
+ 	struct usb_device *udev = pending_req->stub->udev;
+ 	int ret, ret_lock;
+@@ -654,7 +657,7 @@ static int usbbk_port_reset(pending_req_
+ 		return -ENOMEM;
+ 
+ 	req->pending_req = pending_req;
+-	INIT_WORK(&req->work, usbbk_port_reset_work, req);
++	INIT_WORK(&req->work, usbbk_port_reset_work);
+ 
+ 	usb_get_dev(udev);
+ 	schedule_work(&req->work);
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:46:27.000000000 +0100
+@@ -49,8 +49,8 @@
+ 
+ static int xenbus_irq;
+ 
+-extern void xenbus_probe(void *);
+-static DECLARE_WORK(probe_work, xenbus_probe, NULL);
++extern void xenbus_probe(struct work_struct *);
++static DECLARE_WORK(probe_work, xenbus_probe);
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+ 
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2010-01-07 09:53:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 10:51:20.000000000 +0100
+@@ -856,7 +856,7 @@ void unregister_xenstore_notifier(struct
+ EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
+ 
+ 
+-void xenbus_probe(void *unused)
++void xenbus_probe(struct work_struct *unused)
+ {
+ 	BUG_ON(!is_xenstored_ready());
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -4,8 +4,6 @@
+ #include <asm/ldt.h>
+ #include <asm/segment.h>
+ 
+-#define CPU_16BIT_STACK_SIZE 1024
+-
+ #ifndef __ASSEMBLY__
+ 
+ #include <linux/preempt.h>
+@@ -15,8 +13,6 @@
+ 
+ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+ 
+-DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+-
+ struct Xgt_desc_struct {
+ 	unsigned short size;
+ 	unsigned long address __attribute__((packed));
+@@ -32,11 +28,6 @@ static inline struct desc_struct *get_cp
+ 	return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
+ }
+ 
+-/*
+- * This is the ldt that every process will get unless we need
+- * something other than this.
+- */
+-extern struct desc_struct default_ldt[];
+ extern struct desc_struct idt_table[];
+ extern void set_intr_gate(unsigned int irq, void * addr);
+ 
+@@ -63,8 +54,8 @@ static inline void pack_gate(__u32 *a, _
+ #define DESCTYPE_DPL3	0x60	/* DPL-3 */
+ #define DESCTYPE_S	0x10	/* !system */
+ 
++#ifndef CONFIG_XEN
+ #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
+-#define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
+ 
+ #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+ #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+@@ -75,6 +66,7 @@ static inline void pack_gate(__u32 *a, _
+ #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
+ #define store_tr(tr) __asm__ ("str %0":"=m" (tr))
+ #define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
++#endif
+ 
+ #if TLS_SIZE != 24
+ # error update this code.
+@@ -90,22 +82,43 @@ static inline void load_TLS(struct threa
+ }
+ 
+ #ifndef CONFIG_XEN
++#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++
+ static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
+ {
+ 	__u32 *lp = (__u32 *)((char *)dt + entry*8);
+ 	*lp = entry_a;
+ 	*(lp+1) = entry_b;
+ }
+-
+-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
++#define set_ldt native_set_ldt
+ #else
+ extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
+ extern int write_gdt_entry(void *gdt, int entry, __u32 entry_a, __u32 entry_b);
++#define set_ldt xen_set_ldt
++#endif
++
++#ifndef CONFIG_XEN
++static inline fastcall void native_set_ldt(const void *addr,
++					   unsigned int entries)
++{
++	if (likely(entries == 0))
++		__asm__ __volatile__("lldt %w0"::"q" (0));
++	else {
++		unsigned cpu = smp_processor_id();
++		__u32 a, b;
++
++		pack_descriptor(&a, &b, (unsigned long)addr,
++				entries * sizeof(struct desc_struct) - 1,
++				DESCTYPE_LDT, 0);
++		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
++		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
++	}
++}
+ #endif
+-#ifndef CONFIG_X86_NO_IDT
+-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+ 
++#ifndef CONFIG_X86_NO_IDT
+ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
+ {
+ 	__u32 a, b;
+@@ -125,14 +138,6 @@ static inline void __set_tss_desc(unsign
+ }
+ #endif
+ 
+-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entries)
+-{
+-	__u32 a, b;
+-	pack_descriptor(&a, &b, (unsigned long)addr,
+-			entries * sizeof(struct desc_struct) - 1,
+-			DESCTYPE_LDT, 0);
+-	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+-}
+ 
+ #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+ 
+@@ -163,36 +168,22 @@ static inline void set_ldt_desc(unsigned
+ 
+ static inline void clear_LDT(void)
+ {
+-	int cpu = get_cpu();
+-
+-	/*
+-	 * NB. We load the default_ldt for lcall7/27 handling on demand, as
+-	 * it slows down context switching. Noone uses it anyway.
+-	 */
+-	cpu = cpu;		/* XXX avoid compiler warning */
+-	xen_set_ldt(NULL, 0);
+-	put_cpu();
++	set_ldt(NULL, 0);
+ }
+ 
+ /*
+  * load one particular LDT into the current CPU
+  */
+-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
++static inline void load_LDT_nolock(mm_context_t *pc)
+ {
+-	void *segments = pc->ldt;
+-	int count = pc->size;
+-
+-	if (likely(!count))
+-		segments = NULL;
+-
+-	xen_set_ldt(segments, count);
++	set_ldt(pc->ldt, pc->size);
+ }
+ 
+ static inline void load_LDT(mm_context_t *pc)
+ {
+-	int cpu = get_cpu();
+-	load_LDT_nolock(pc, cpu);
+-	put_cpu();
++	preempt_disable();
++	load_LDT_nolock(pc);
++	preempt_enable();
+ }
+ 
+ static inline unsigned long get_desc_base(unsigned long *desc)
+@@ -204,6 +195,29 @@ static inline unsigned long get_desc_bas
+ 	return base;
+ }
+ 
++#else /* __ASSEMBLY__ */
++
++/*
++ * GET_DESC_BASE reads the descriptor base of the specified segment.
++ *
++ * Args:
++ *    idx - descriptor index
++ *    gdt - GDT pointer
++ *    base - 32bit register to which the base will be written
++ *    lo_w - lo word of the "base" register
++ *    lo_b - lo byte of the "base" register
++ *    hi_b - hi byte of the low word of the "base" register
++ *
++ * Example:
++ *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
++ *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
++ */
++#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
++	movb idx*8+4(gdt), lo_b; \
++	movb idx*8+7(gdt), hi_b; \
++	shll $16, base; \
++	movw idx*8+2(gdt), lo_w;
++
+ #endif /* !__ASSEMBLY__ */
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -13,13 +13,16 @@
+ #ifndef _ASM_FIXMAP_H
+ #define _ASM_FIXMAP_H
+ 
+-
+ /* used by vmalloc.c, vsyscall.lds.S.
+  *
+  * Leave one empty page between vmalloc'ed areas and
+  * the start of the fixmap.
+  */
+ extern unsigned long __FIXADDR_TOP;
++#ifdef CONFIG_COMPAT_VDSO
++#define FIXADDR_USER_START	__fix_to_virt(FIX_VDSO)
++#define FIXADDR_USER_END	__fix_to_virt(FIX_VDSO - 1)
++#endif
+ 
+ #ifndef __ASSEMBLY__
+ #include <linux/kernel.h>
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2008-10-29 09:55:56.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:46:27.000000000 +0100
+@@ -85,7 +85,7 @@ static inline void clear_user_highpage(s
+ 
+ void copy_highpage(struct page *to, struct page *from);
+ static inline void copy_user_highpage(struct page *to, struct page *from,
+-	unsigned long vaddr)
++	unsigned long vaddr, struct vm_area_struct *vma)
+ {
+ 	copy_highpage(to, from);
+ }
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:46:27.000000000 +0100
+@@ -47,15 +47,6 @@
+ #include <asm/percpu.h>
+ #include <asm/ptrace.h>
+ #include <asm/page.h>
+-#if defined(__i386__)
+-#  ifdef CONFIG_X86_PAE
+-#   include <asm-generic/pgtable-nopud.h>
+-#  else
+-#   include <asm-generic/pgtable-nopmd.h>
+-#  endif
+-#elif defined(__x86_64__) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+-#  include <asm-generic/pgtable-nopud.h>
+-#endif
+ 
+ extern shared_info_t *HYPERVISOR_shared_info;
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_32.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -22,9 +22,6 @@
+ 
+ #define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask)
+ 
+-#define raw_local_save_flags(flags) \
+-		do { (flags) = __raw_local_save_flags(); } while (0)
+-
+ #define raw_local_irq_restore(x)					\
+ do {									\
+ 	vcpu_info_t *_vcpu;						\
+@@ -66,18 +63,6 @@ void raw_safe_halt(void);
+  */
+ void halt(void);
+ 
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+-	return (flags != 0);
+-}
+-
+-#define raw_irqs_disabled()						\
+-({									\
+-	unsigned long flags = __raw_local_save_flags();			\
+-									\
+-	raw_irqs_disabled_flags(flags);					\
+-})
+-
+ /*
+  * For spinlocks, etc:
+  */
+@@ -90,9 +75,64 @@ static inline int raw_irqs_disabled_flag
+ 	flags;								\
+ })
+ 
++#else
++/* Offsets into shared_info_t. */
++#define evtchn_upcall_pending		/* 0 */
++#define evtchn_upcall_mask		1
++
++#define sizeof_vcpu_shift		6
++
++#ifdef CONFIG_SMP
++#define GET_VCPU_INFO		movl TI_cpu(%ebp),%esi			; \
++				shl  $sizeof_vcpu_shift,%esi		; \
++				addl HYPERVISOR_shared_info,%esi
++#else
++#define GET_VCPU_INFO		movl HYPERVISOR_shared_info,%esi
++#endif
++
++#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(%esi)
++#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(%esi)
++#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
++#define DISABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
++				__DISABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
++				__ENABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS_SYSEXIT __ENABLE_INTERRUPTS			; \
++sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
++	__TEST_PENDING							; \
++	jnz  14f	/* process more events if necessary... */	; \
++	movl PT_ESI(%esp), %esi						; \
++	sysexit								; \
++14:	__DISABLE_INTERRUPTS						; \
++	TRACE_IRQS_OFF							; \
++sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
++	mov  $__KERNEL_PDA, %ecx					; \
++	push %esp							; \
++	mov  %ecx, %gs							; \
++	call evtchn_do_upcall						; \
++	add  $4,%esp							; \
++	jmp  ret_from_intr
++#define INTERRUPT_RETURN	iret
++#endif /* __ASSEMBLY__ */
++
++#ifndef __ASSEMBLY__
++#define raw_local_save_flags(flags) \
++		do { (flags) = __raw_local_save_flags(); } while (0)
++
+ #define raw_local_irq_save(flags) \
+ 		do { (flags) = __raw_local_irq_save(); } while (0)
+ 
++static inline int raw_irqs_disabled_flags(unsigned long flags)
++{
++	return (flags != 0);
++}
++
++#define raw_irqs_disabled()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_irqs_disabled_flags(flags);					\
++})
+ #endif /* __ASSEMBLY__ */
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2007-06-12 13:14:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -27,14 +27,13 @@ static inline void enter_lazy_tlb(struct
+ static inline void __prepare_arch_switch(void)
+ {
+ 	/*
+-	 * Save away %fs and %gs. No need to save %es and %ds, as those
+-	 * are always kernel segments while inside the kernel. Must
+-	 * happen before reload of cr3/ldt (i.e., not in __switch_to).
++	 * Save away %fs. No need to save %gs, as it was saved on the
++	 * stack on entry.  No need to save %es and %ds, as those are
++	 * always kernel segments while inside the kernel.
+ 	 */
+-	asm volatile ( "mov %%fs,%0 ; mov %%gs,%1"
+-		: "=m" (current->thread.fs),
+-		  "=m" (current->thread.gs));
+-	asm volatile ( "movl %0,%%fs ; movl %0,%%gs"
++	asm volatile ( "mov %%fs,%0"
++		: "=m" (current->thread.fs));
++	asm volatile ( "movl %0,%%fs"
+ 		: : "r" (0) );
+ }
+ 
+@@ -89,14 +88,14 @@ static inline void switch_mm(struct mm_s
+ 			 * tlb flush IPI delivery. We must reload %cr3.
+ 			 */
+ 			load_cr3(next->pgd);
+-			load_LDT_nolock(&next->context, cpu);
++			load_LDT_nolock(&next->context);
+ 		}
+ 	}
+ #endif
+ }
+ 
+-#define deactivate_mm(tsk, mm) \
+-	asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
++#define deactivate_mm(tsk, mm)			\
++	asm("movl %0,%%fs": :"r" (0));
+ 
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:46:27.000000000 +0100
+@@ -1,8 +1,6 @@
+ #ifndef _I386_PGTABLE_3LEVEL_H
+ #define _I386_PGTABLE_3LEVEL_H
+ 
+-#include <asm-generic/pgtable-nopud.h>
+-
+ /*
+  * Intel Physical Address Extension (PAE) Mode - three-level page
+  * tables on PPro+ CPUs.
+@@ -75,6 +73,23 @@ static inline void set_pte(pte_t *ptep, 
+ 		xen_l3_entry_update((pudptr), (pudval))
+ 
+ /*
++ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
++ * entry, so clear the bottom half first and enforce ordering with a compiler
++ * barrier.
++ */
++static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	if ((mm != current->mm && mm != &init_mm)
++	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
++		ptep->pte_low = 0;
++		smp_wmb();
++		ptep->pte_high = 0;
++	}
++}
++
++#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
++
++/*
+  * Pentium-II erratum A13: in PAE mode we explicitly have to flush
+  * the TLB via cr3 if the top-level pgd is changed...
+  * We do not let the generic code free and clear pgd entries due to
+@@ -93,45 +108,16 @@ static inline void pud_clear (pud_t * pu
+ #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
+ 			pmd_index(address))
+ 
+-static inline int pte_none(pte_t pte)
+-{
+-	return !(pte.pte_low | pte.pte_high);
+-}
+-
+-/*
+- * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+- * entry, so clear the bottom half first and enforce ordering with a compiler
+- * barrier.
+- */
+-static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline pte_t raw_ptep_get_and_clear(pte_t *ptep, pte_t res)
+ {
+-	if ((mm != current->mm && mm != &init_mm)
+-	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+-		ptep->pte_low = 0;
+-		smp_wmb();
++	uint64_t val = __pte_val(res);
++	if (__cmpxchg64(ptep, val, 0) != val) {
++		/* xchg acts as a barrier before the setting of the high bits */
++		res.pte_low = xchg(&ptep->pte_low, 0);
++		res.pte_high = ptep->pte_high;
+ 		ptep->pte_high = 0;
+ 	}
+-}
+-
+-#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+-
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+-	pte_t pte = *ptep;
+-	if (!pte_none(pte)) {
+-		if ((mm != &init_mm) ||
+-		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+-			uint64_t val = __pte_val(pte);
+-			if (__cmpxchg64(ptep, val, 0) != val) {
+-				/* xchg acts as a barrier before the setting of the high bits */
+-				pte.pte_low = xchg(&ptep->pte_low, 0);
+-				pte.pte_high = ptep->pte_high;
+-				ptep->pte_high = 0;
+-			}
+-		}
+-	}
+-	return pte;
++	return res;
+ }
+ 
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+@@ -160,6 +146,11 @@ static inline int pte_same(pte_t a, pte_
+ 
+ #define pte_page(x)	pfn_to_page(pte_pfn(x))
+ 
++static inline int pte_none(pte_t pte)
++{
++	return !(pte.pte_low | pte.pte_high);
++}
++
+ #define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+ 			 ((_pte).pte_high << (32-PAGE_SHIFT)))
+ #define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -38,14 +38,14 @@ struct vm_area_struct;
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ extern unsigned long empty_zero_page[1024];
+ extern pgd_t *swapper_pg_dir;
+-extern kmem_cache_t *pgd_cache;
+-extern kmem_cache_t *pmd_cache;
++extern struct kmem_cache *pgd_cache;
++extern struct kmem_cache *pmd_cache;
+ extern spinlock_t pgd_lock;
+ extern struct page *pgd_list;
+ 
+-void pmd_ctor(void *, kmem_cache_t *, unsigned long);
+-void pgd_ctor(void *, kmem_cache_t *, unsigned long);
+-void pgd_dtor(void *, kmem_cache_t *, unsigned long);
++void pmd_ctor(void *, struct kmem_cache *, unsigned long);
++void pgd_ctor(void *, struct kmem_cache *, unsigned long);
++void pgd_dtor(void *, struct kmem_cache *, unsigned long);
+ void pgtable_cache_init(void);
+ void paging_init(void);
+ 
+@@ -276,7 +276,6 @@ static inline pte_t pte_mkhuge(pte_t pte
+ #define pte_update(mm, addr, ptep)		do { } while (0)
+ #define pte_update_defer(mm, addr, ptep)	do { } while (0)
+ 
+-
+ /*
+  * We only update the dirty/accessed state if we set
+  * the dirty bit by hand in the kernel, since the hardware
+@@ -342,6 +341,19 @@ do {									\
+ 	__young;							\
+ })
+ 
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (!pte_none(pte)
++	    && (mm != &init_mm
++	        || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))) {
++		pte = raw_ptep_get_and_clear(ptep, pte);
++		pte_update(mm, addr, ptep);
++	}
++	return pte;
++}
++
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+ #define ptep_get_and_clear_full(mm, addr, ptep, full)			\
+ 	((full) ? ({							\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -20,6 +20,7 @@
+ #include <linux/threads.h>
+ #include <asm/percpu.h>
+ #include <linux/cpumask.h>
++#include <linux/init.h>
+ #include <xen/interface/physdev.h>
+ 
+ /* flag for disabling the tsc */
+@@ -73,6 +74,7 @@ struct cpuinfo_x86 {
+ #endif
+ 	unsigned char x86_max_cores;	/* cpuid returned max cores value */
+ 	unsigned char apicid;
++	unsigned short x86_clflush_size;
+ #ifdef CONFIG_SMP
+ 	unsigned char booted_cores;	/* number of cores as seen by OS */
+ 	__u8 phys_proc_id; 		/* Physical processor id. */
+@@ -114,6 +116,8 @@ extern struct cpuinfo_x86 cpu_data[];
+ extern	int cpu_llc_id[NR_CPUS];
+ extern char ignore_fpu_irq;
+ 
++void __init cpu_detect(struct cpuinfo_x86 *c);
++
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+@@ -146,8 +150,8 @@ static inline void detect_ht(struct cpui
+ #define X86_EFLAGS_VIP	0x00100000 /* Virtual Interrupt Pending */
+ #define X86_EFLAGS_ID	0x00200000 /* CPUID detection flag */
+ 
+-static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+-			   unsigned int *ecx, unsigned int *edx)
++static inline fastcall void xen_cpuid(unsigned int *eax, unsigned int *ebx,
++				      unsigned int *ecx, unsigned int *edx)
+ {
+ 	/* ecx is often an input as well as an output. */
+ 	__asm__(XEN_CPUID
+@@ -158,59 +162,6 @@ static inline void __cpuid(unsigned int 
+ 		: "0" (*eax), "2" (*ecx));
+ }
+ 
+-/*
+- * Generic CPUID function
+- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+- * resulting in stale register contents being returned.
+- */
+-static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
+-{
+-	*eax = op;
+-	*ecx = 0;
+-	__cpuid(eax, ebx, ecx, edx);
+-}
+-
+-/* Some CPUID calls want 'count' to be placed in ecx */
+-static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+-			       int *edx)
+-{
+-	*eax = op;
+-	*ecx = count;
+-	__cpuid(eax, ebx, ecx, edx);
+-}
+-
+-/*
+- * CPUID functions returning a single datum
+- */
+-static inline unsigned int cpuid_eax(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return eax;
+-}
+-static inline unsigned int cpuid_ebx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return ebx;
+-}
+-static inline unsigned int cpuid_ecx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return ecx;
+-}
+-static inline unsigned int cpuid_edx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return edx;
+-}
+-
+ #define load_cr3(pgdir) write_cr3(__pa(pgdir))
+ 
+ /*
+@@ -480,9 +431,9 @@ struct thread_struct {
+ 	.vm86_info = NULL,						\
+ 	.sysenter_cs = __KERNEL_CS,					\
+ 	.io_bitmap_ptr = NULL,						\
++	.gs = __KERNEL_PDA,						\
+ }
+ 
+-#ifndef CONFIG_X86_NO_TSS
+ /*
+  * Note that the .io_bitmap member must be extra-big. This is because
+  * the CPU will access an additional byte beyond the end of the IO
+@@ -497,26 +448,9 @@ struct thread_struct {
+ 	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
+ }
+ 
+-static inline void __load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+-{
+-	tss->esp0 = thread->esp0;
+-	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+-	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
+-		tss->ss1 = thread->sysenter_cs;
+-		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+-	}
+-}
+-#define load_esp0(tss, thread) \
+-	__load_esp0(tss, thread)
+-#else
+-#define load_esp0(tss, thread) do { \
+-	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)) \
+-		BUG(); \
+-} while (0)
+-#endif
+-
+ #define start_thread(regs, new_eip, new_esp) do {		\
+-	__asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));	\
++	__asm__("movl %0,%%fs": :"r" (0));			\
++	regs->xgs = 0;						\
+ 	set_fs(USER_DS);					\
+ 	regs->xds = __USER_DS;					\
+ 	regs->xes = __USER_DS;					\
+@@ -526,26 +460,6 @@ static inline void __load_esp0(struct ts
+ 	regs->esp = new_esp;					\
+ } while (0)
+ 
+-/*
+- * These special macros can be used to get or set a debugging register
+- */
+-#define get_debugreg(var, register)				\
+-		(var) = HYPERVISOR_get_debugreg((register))
+-#define set_debugreg(value, register)			\
+-		WARN_ON(HYPERVISOR_set_debugreg((register), (value)))
+-
+-/*
+- * Set IOPL bits in EFLAGS from given mask
+- */
+-static inline void set_iopl_mask(unsigned mask)
+-{
+-	struct physdev_set_iopl set_iopl;
+-
+-	/* Force the change at ring 0. */
+-	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+-}
+-
+ /* Forward declaration, a strange C thing */
+ struct task_struct;
+ struct mm_struct;
+@@ -637,6 +551,105 @@ static inline void rep_nop(void)
+ 
+ #define cpu_relax()	rep_nop()
+ 
++#define paravirt_enabled() 0
++#define __cpuid xen_cpuid
++
++#ifndef CONFIG_X86_NO_TSS
++static inline void __load_esp0(struct tss_struct *tss, struct thread_struct *thread)
++{
++	tss->esp0 = thread->esp0;
++	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
++	if (unlikely(tss->ss1 != thread->sysenter_cs)) {
++		tss->ss1 = thread->sysenter_cs;
++		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
++	}
++}
++#define load_esp0(tss, thread) \
++	__load_esp0(tss, thread)
++#else
++#define load_esp0(tss, thread) do { \
++	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)) \
++		BUG(); \
++} while (0)
++#endif
++
++
++/*
++ * These special macros can be used to get or set a debugging register
++ */
++#define get_debugreg(var, register)				\
++		(var) = HYPERVISOR_get_debugreg(register)
++#define set_debugreg(value, register)				\
++		WARN_ON(HYPERVISOR_set_debugreg(register, value))
++
++#define set_iopl_mask xen_set_iopl_mask
++
++/*
++ * Set IOPL bits in EFLAGS from given mask
++ */
++static inline void xen_set_iopl_mask(unsigned mask)
++{
++	struct physdev_set_iopl set_iopl;
++
++	/* Force the change at ring 0. */
++	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++}
++
++
++/*
++ * Generic CPUID function
++ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
++ * resulting in stale register contents being returned.
++ */
++static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
++{
++	*eax = op;
++	*ecx = 0;
++	__cpuid(eax, ebx, ecx, edx);
++}
++
++/* Some CPUID calls want 'count' to be placed in ecx */
++static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
++			       int *edx)
++{
++	*eax = op;
++	*ecx = count;
++	__cpuid(eax, ebx, ecx, edx);
++}
++
++/*
++ * CPUID functions returning a single datum
++ */
++static inline unsigned int cpuid_eax(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return eax;
++}
++static inline unsigned int cpuid_ebx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return ebx;
++}
++static inline unsigned int cpuid_ecx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return ecx;
++}
++static inline unsigned int cpuid_edx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return edx;
++}
++
+ /* generic versions from gas */
+ #define GENERIC_NOP1	".byte 0x90\n"
+ #define GENERIC_NOP2    	".byte 0x89,0xf6\n"
+@@ -736,4 +749,8 @@ extern unsigned long boot_option_idle_ov
+ extern void enable_sep_cpu(void);
+ extern int sysenter_setup(void);
+ 
++extern int init_gdt(int cpu, struct task_struct *idle);
++extern void cpu_set_gdt(int);
++extern void secondary_cpu_init(void);
++
+ #endif /* __ASM_I386_PROCESSOR_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -8,6 +8,7 @@
+ #include <linux/kernel.h>
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
++#include <asm/pda.h>
+ #endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -56,7 +57,7 @@ extern void cpu_uninit(void);
+  * from the initial startup. We map APIC_BASE very early in page_setup(),
+  * so this is correct in the x86 case.
+  */
+-#define raw_smp_processor_id() (current_thread_info()->cpu)
++#define raw_smp_processor_id() (read_pda(cpu_number))
+ 
+ extern cpumask_t cpu_possible_map;
+ #define cpu_callin_map cpu_possible_map
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:46:27.000000000 +0100
+@@ -139,17 +139,17 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"
+ #define write_cr4(x) \
+ 	__asm__ __volatile__("movl %0,%%cr4": :"r" (x))
+ 
+-/*
+- * Clear and set 'TS' bit respectively
+- */
++#define wbinvd() \
++	__asm__ __volatile__ ("wbinvd": : :"memory")
++
++/* Clear the 'TS' bit */
+ #define clts() (HYPERVISOR_fpu_taskswitch(0))
++
++/* Set the 'TS' bit */
+ #define stts() (HYPERVISOR_fpu_taskswitch(1))
+ 
+ #endif	/* __KERNEL__ */
+ 
+-#define wbinvd() \
+-	__asm__ __volatile__ ("wbinvd": : :"memory")
+-
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ 	unsigned long __limit;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_64.h	2008-01-28 12:24:19.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:46:27.000000000 +0100
+@@ -9,62 +9,11 @@
+ 
+ #include <linux/string.h>
+ #include <linux/smp.h>
++#include <asm/desc_defs.h>
+ 
+ #include <asm/segment.h>
+ #include <asm/mmu.h>
+ 
+-// 8 byte segment descriptor
+-struct desc_struct { 
+-	u16 limit0;
+-	u16 base0;
+-	unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
+-	unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
+-} __attribute__((packed)); 
+-
+-struct n_desc_struct { 
+-	unsigned int a,b;
+-}; 	
+-
+-enum { 
+-	GATE_INTERRUPT = 0xE, 
+-	GATE_TRAP = 0xF, 	
+-	GATE_CALL = 0xC,
+-}; 	
+-
+-// 16byte gate
+-struct gate_struct {          
+-	u16 offset_low;
+-	u16 segment; 
+-	unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
+-	u16 offset_middle;
+-	u32 offset_high;
+-	u32 zero1; 
+-} __attribute__((packed));
+-
+-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF) 
+-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
+-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+-
+-enum { 
+-	DESC_TSS = 0x9,
+-	DESC_LDT = 0x2,
+-}; 
+-
+-// LDT or TSS descriptor in the GDT. 16 bytes.
+-struct ldttss_desc { 
+-	u16 limit0;
+-	u16 base0;
+-	unsigned base1 : 8, type : 5, dpl : 2, p : 1;
+-	unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
+-	u32 base3;
+-	u32 zero1; 
+-} __attribute__((packed)); 
+-
+-struct desc_ptr {
+-	unsigned short size;
+-	unsigned long address;
+-} __attribute__((packed)) ;
+-
+ extern struct desc_ptr idt_descr, cpu_gdt_descr[NR_CPUS];
+ 
+ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:46:27.000000000 +0100
+@@ -237,19 +237,18 @@ extern unsigned int __kernel_page_user;
+ 
+ static inline unsigned long pgd_bad(pgd_t pgd)
+ {
+-       unsigned long val = __pgd_val(pgd);
+-       val &= ~PTE_MASK;
+-       val &= ~(_PAGE_USER | _PAGE_DIRTY);
+-       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);
++	return __pgd_val(pgd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
+ }
+ 
+-static inline unsigned long pud_bad(pud_t pud) 
+-{ 
+-       unsigned long val = __pud_val(pud);
+-       val &= ~PTE_MASK; 
+-       val &= ~(_PAGE_USER | _PAGE_DIRTY); 
+-       return val & ~(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED);      
+-} 
++static inline unsigned long pud_bad(pud_t pud)
++{
++	return __pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++}
++
++static inline unsigned long pmd_bad(pmd_t pmd)
++{
++	return __pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
++}
+ 
+ #define set_pte_at(_mm,addr,ptep,pteval) do {				\
+ 	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
+@@ -404,8 +403,6 @@ static inline int pmd_large(pmd_t pte) {
+ #define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+ #endif
+ #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+-#define pmd_bad(x) ((__pmd_val(x) & ~(PTE_MASK | _PAGE_USER | _PAGE_PRESENT)) \
+-		    != (_KERNPG_TABLE & ~(_PAGE_USER | _PAGE_PRESENT)))
+ #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
+ #define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:46:27.000000000 +0100
+@@ -484,6 +484,14 @@ static inline void __mwait(unsigned long
+ 		: :"a" (eax), "c" (ecx));
+ }
+ 
++static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
++{
++	/* "mwait %eax,%ecx;" */
++	asm volatile(
++		"sti; .byte 0x0f,0x01,0xc9;"
++		: :"a" (eax), "c" (ecx));
++}
++
+ extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+ 
+ #define stack_current() \
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:46:27.000000000 +0100
+@@ -88,11 +88,6 @@ extern u8 x86_cpu_to_log_apicid[NR_CPUS]
+ extern u8 bios_cpu_apicid[];
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+-{
+-	return cpus_addr(cpumask)[0];
+-}
+-
+ static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+ 	if (mps_cpu < NR_CPUS)
+@@ -127,13 +122,6 @@ static __inline int logical_smp_processo
+ #define cpu_physical_id(cpu)		x86_cpu_to_apicid[cpu]
+ #else
+ #define cpu_physical_id(cpu)		boot_cpu_id
+-static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
+-				void *info, int retry, int wait)
+-{
+-	/* Disable interrupts here? */
+-	func(info);
+-	return 0;
+-}
+ #endif /* !CONFIG_SMP */
+ #endif
+ 
+--- head-2010-01-18.orig/kernel/kexec.c	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/kernel/kexec.c	2009-11-06 10:46:27.000000000 +0100
+@@ -375,7 +375,7 @@ static struct page *kimage_alloc_pages(g
+ 		if (limit == ~0UL)
+ 			address_bits = BITS_PER_LONG;
+ 		else
+-			address_bits = long_log2(limit);
++			address_bits = ilog2(limit);
+ 
+ 		if (xen_limit_pages_to_max_mfn(pages, order, address_bits) < 0) {
+ 			__free_pages(pages, order);
+--- head-2010-01-18.orig/net/core/dev.c	2009-12-04 10:49:48.000000000 +0100
++++ head-2010-01-18/net/core/dev.c	2009-12-04 10:51:26.000000000 +0100
+@@ -1834,10 +1834,10 @@ inline int skb_checksum_setup(struct sk_
+ 			goto out;
+ 		switch (skb->nh.iph->protocol) {
+ 		case IPPROTO_TCP:
+-			skb->csum = offsetof(struct tcphdr, check);
++			skb->csum_offset = offsetof(struct tcphdr, check);
+ 			break;
+ 		case IPPROTO_UDP:
+-			skb->csum = offsetof(struct udphdr, check);
++			skb->csum_offset = offsetof(struct udphdr, check);
+ 			break;
+ 		default:
+ 			if (net_ratelimit())
+@@ -1846,7 +1846,7 @@ inline int skb_checksum_setup(struct sk_
+ 				       " %d packet", skb->nh.iph->protocol);
+ 			goto out;
+ 		}
+-		if ((skb->h.raw + skb->csum + 2) > skb->tail)
++		if ((skb->h.raw + skb->csum_offset + 2) > skb->tail)
+ 			goto out;
+ 		skb->ip_summed = CHECKSUM_PARTIAL;
+ 		skb->proto_csum_blank = 0;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-dcdbas
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-dcdbas
@@ -0,0 +1,280 @@
+From: jbeulich@novell.com
+Subject: force proper address translation in DCDBAS
+Patch-mainline: n/a
+
+The only caveat is that this doesn't work when Dom0 has its vCPU-s pinned.
+
+--- head-2010-01-04.orig/drivers/firmware/Kconfig	2009-11-06 11:10:32.000000000 +0100
++++ head-2010-01-04/drivers/firmware/Kconfig	2009-10-21 12:05:13.000000000 +0200
+@@ -90,6 +90,7 @@ config DELL_RBU
+ config DCDBAS
+ 	tristate "Dell Systems Management Base Driver"
+ 	depends on X86
++	select XEN_DOMCTL if XEN
+ 	help
+ 	  The Dell Systems Management Base Driver provides a sysfs interface
+ 	  for systems management software to perform System Management
+--- head-2010-01-04.orig/drivers/firmware/dcdbas.c	2010-01-04 16:15:10.000000000 +0100
++++ head-2010-01-04/drivers/firmware/dcdbas.c	2009-10-21 14:18:16.000000000 +0200
+@@ -36,6 +36,10 @@
+ #include <linux/mutex.h>
+ #include <asm/io.h>
+ 
++#ifdef CONFIG_XEN
++#include "../xen/core/domctl.h"
++#endif
++
+ #include "dcdbas.h"
+ 
+ #define DRIVER_NAME		"dcdbas"
+@@ -106,7 +110,7 @@ static int smi_data_buf_realloc(unsigned
+ 	/* set up new buffer for use */
+ 	smi_data_buf = buf;
+ 	smi_data_buf_handle = handle;
+-	smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
++	smi_data_buf_phys_addr = (u32) handle;
+ 	smi_data_buf_size = size;
+ 
+ 	dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+@@ -244,7 +248,9 @@ static ssize_t host_control_on_shutdown_
+  */
+ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
+ {
++#ifndef CONFIG_XEN
+ 	cpumask_var_t old_mask;
++#endif
+ 	int ret = 0;
+ 
+ 	if (smi_cmd->magic != SMI_CMD_MAGIC) {
+@@ -254,6 +260,7 @@ int dcdbas_smi_request(struct smi_cmd *s
+ 	}
+ 
+ 	/* SMI requires CPU 0 */
++#ifndef CONFIG_XEN
+ 	if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
+ 		return -ENOMEM;
+ 
+@@ -265,6 +272,14 @@ int dcdbas_smi_request(struct smi_cmd *s
+ 		ret = -EBUSY;
+ 		goto out;
+ 	}
++#else
++	ret = xen_set_physical_cpu_affinity(0);
++	if (ret) {
++		dev_dbg(&dcdbas_pdev->dev, "%s: failed (%d) to get CPU 0\n",
++			__func__, ret);
++		return ret;
++	}
++#endif
+ 
+ 	/* generate SMI */
+ 	asm volatile (
+@@ -277,9 +292,13 @@ int dcdbas_smi_request(struct smi_cmd *s
+ 		: "memory"
+ 	);
+ 
++#ifndef CONFIG_XEN
+ out:
+ 	set_cpus_allowed_ptr(current, old_mask);
+ 	free_cpumask_var(old_mask);
++#else
++	xen_set_physical_cpu_affinity(-1);
++#endif
+ 	return ret;
+ }
+ 
+@@ -319,7 +338,7 @@ static ssize_t smi_request_store(struct 
+ 		break;
+ 	case 1:
+ 		/* Calling Interface SMI */
+-		smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
++		smi_cmd->ebx = (u32) virt_to_bus(smi_cmd->command_buffer);
+ 		ret = dcdbas_smi_request(smi_cmd);
+ 		if (!ret)
+ 			ret = count;
+@@ -600,6 +619,11 @@ static int __init dcdbas_init(void)
+ {
+ 	int error;
+ 
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return -ENODEV;
++#endif
++
+ 	error = platform_driver_register(&dcdbas_driver);
+ 	if (error)
+ 		return error;
+--- head-2010-01-04.orig/drivers/xen/core/domctl.c	2010-01-04 16:15:58.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/domctl.c	2010-01-04 16:17:59.000000000 +0100
+@@ -20,6 +20,8 @@
+ #undef __XEN_TOOLS__
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/gfp.h>
++#include <linux/percpu.h>
+ #include <asm/hypervisor.h>
+ #include <xen/blkif.h>
+ 
+@@ -34,6 +36,29 @@ typedef struct xen_domctl_address_size {
+ 
+ typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t;
+ 
++struct xenctl_cpumap_v4 {
++	XEN_GUEST_HANDLE(uint8) bitmap;
++	uint32_t nr_cpus;
++};
++
++struct xenctl_cpumap_v5 {
++	union {
++		XEN_GUEST_HANDLE(uint8) bitmap;
++		uint64_aligned_t _align;
++	};
++	uint32_t nr_cpus;
++};
++
++struct xen_domctl_vcpuaffinity_v4 {
++    uint32_t vcpu;
++    struct xenctl_cpumap_v4 cpumap;
++};
++
++struct xen_domctl_vcpuaffinity_v5 {
++    uint32_t vcpu;
++    struct xenctl_cpumap_v5 cpumap;
++};
++
+ union xen_domctl {
+ 	/* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */
+ 	struct {
+@@ -43,6 +68,7 @@ union xen_domctl {
+ 		union {
+ 			/* left out lots of other struct xen_domctl_foobar */
+ 			struct xen_domctl_address_size       address_size;
++			struct xen_domctl_vcpuaffinity_v4    vcpu_affinity;
+ 			uint64_t                             dummy_align;
+ 			uint8_t                              dummy_pad[128];
+ 		};
+@@ -55,6 +81,7 @@ union xen_domctl {
+ 		domid_t  domain;
+ 		union {
+ 			struct xen_domctl_address_size       address_size;
++			struct xen_domctl_vcpuaffinity_v5    vcpu_affinity;
+ 			uint64_aligned_t                     dummy_align;
+ 			uint8_t                              dummy_pad[128];
+ 		};
+@@ -117,4 +144,110 @@ int xen_guest_blkif_protocol(int domid)
+ }
+ EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol);
+ 
++#ifdef CONFIG_X86
++
++#define vcpuaffinity(what, ver) ({					\
++	memset(&domctl, 0, sizeof(domctl));				\
++	domctl.v##ver.cmd = XEN_DOMCTL_##what##vcpuaffinity;		\
++	domctl.v##ver.interface_version = ver;				\
++	/* domctl.v##ver.domain = 0; */					\
++	domctl.v##ver.vcpu_affinity.vcpu = smp_processor_id();		\
++	domctl.v##ver.vcpu_affinity.cpumap.nr_cpus = nr;		\
++	set_xen_guest_handle(domctl.v##ver.vcpu_affinity.cpumap.bitmap, \
++			     mask);					\
++	hypervisor_domctl(&domctl);					\
++})
++
++static inline int get_vcpuaffinity(unsigned int nr, void *mask)
++{
++	union xen_domctl domctl;
++	int rc;
++
++	BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6);
++	rc = vcpuaffinity(get, 6);
++#if CONFIG_XEN_COMPAT < 0x040000
++	if (rc)
++		rc = vcpuaffinity(get, 5);
++#endif
++#if CONFIG_XEN_COMPAT < 0x030100
++	if (rc)
++		rc = vcpuaffinity(get, 4);
++#endif
++	return rc;
++}
++
++static inline int set_vcpuaffinity(unsigned int nr, void *mask)
++{
++	union xen_domctl domctl;
++	int rc;
++
++	BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6);
++	rc = vcpuaffinity(set, 6);
++#if CONFIG_XEN_COMPAT < 0x040000
++	if (rc)
++		rc = vcpuaffinity(set, 5);
++#endif
++#if CONFIG_XEN_COMPAT < 0x030100
++	if (rc)
++		rc = vcpuaffinity(set, 4);
++#endif
++	return rc;
++}
++
++static DEFINE_PER_CPU(void *, saved_pcpu_affinity);
++
++#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_LONG / sizeof(long))
++
++int xen_set_physical_cpu_affinity(int pcpu)
++{
++	int rc;
++
++	if (!is_initial_xendomain())
++		return -EPERM;
++
++	if (pcpu >= 0) {
++		void *oldmap;
++
++		if (pcpu > BITS_PER_PAGE)
++			return -ERANGE;
++
++		if (percpu_read(saved_pcpu_affinity))
++			return -EBUSY;
++
++		oldmap = (void *)get_zeroed_page(GFP_KERNEL);
++		if (!oldmap)
++			return -ENOMEM;
++
++		rc = get_vcpuaffinity(BITS_PER_PAGE, oldmap);
++		if (!rc) {
++			void *newmap = kzalloc(BITS_TO_LONGS(pcpu + 1)
++					       * sizeof(long), GFP_KERNEL);
++
++			if (newmap) {
++				__set_bit(pcpu, newmap);
++				rc = set_vcpuaffinity(pcpu + 1, newmap);
++				kfree(newmap);
++			} else
++				rc = -ENOMEM;
++		}
++
++		if (!rc)
++			percpu_write(saved_pcpu_affinity, oldmap);
++		else
++			free_page((unsigned long)oldmap);
++	} else {
++		if (!percpu_read(saved_pcpu_affinity))
++			return 0;
++		rc = set_vcpuaffinity(BITS_PER_PAGE,
++				      percpu_read(saved_pcpu_affinity));
++		free_page((unsigned long)percpu_read(saved_pcpu_affinity));
++		percpu_write(saved_pcpu_affinity, NULL);
++	}
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(xen_set_physical_cpu_affinity);
++
++#endif /* CONFIG_X86 */
++
+ MODULE_LICENSE("GPL");
+--- head-2010-01-04.orig/drivers/xen/core/domctl.h	2008-09-15 15:10:39.000000000 +0200
++++ head-2010-01-04/drivers/xen/core/domctl.h	2009-10-21 13:24:42.000000000 +0200
+@@ -1,2 +1,3 @@
+ int xen_guest_address_size(int domid);
+ int xen_guest_blkif_protocol(int domid);
++int xen_set_physical_cpu_affinity(int pcpu);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-fixup-kconfig
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-fixup-kconfig
@@ -0,0 +1,54 @@
+Subject: Fix xen configuration.
+From: jbeulich@novell.com
+Patch-mainline: obsolete
+
+--- head-2009-12-16.orig/arch/x86/Kconfig	2009-12-04 10:44:40.000000000 +0100
++++ head-2009-12-16/arch/x86/Kconfig	2009-10-15 11:53:21.000000000 +0200
+@@ -158,6 +158,7 @@ config HAVE_CPUMASK_OF_CPU_MAP
+ 
+ config ARCH_HIBERNATION_POSSIBLE
+ 	def_bool y
++	depends on !XEN
+ 
+ config ARCH_SUSPEND_POSSIBLE
+ 	def_bool y
+--- head-2009-12-16.orig/arch/x86/Kconfig.debug	2009-12-04 10:44:40.000000000 +0100
++++ head-2009-12-16/arch/x86/Kconfig.debug	2009-10-15 11:53:21.000000000 +0200
+@@ -289,7 +289,7 @@ config OPTIMIZE_INLINING
+ 
+ config KDB
+ 	bool "Built-in Kernel Debugger support"
+-	depends on DEBUG_KERNEL
++	depends on DEBUG_KERNEL && !XEN
+ 	select KALLSYMS
+ 	select KALLSYMS_ALL
+ 	help
+--- head-2009-12-16.orig/drivers/xen/Kconfig	2009-12-04 10:44:40.000000000 +0100
++++ head-2009-12-16/drivers/xen/Kconfig	2009-12-18 12:08:28.000000000 +0100
+@@ -22,6 +22,7 @@ config XEN_PRIVILEGED_GUEST
+ 
+ config XEN_UNPRIVILEGED_GUEST
+ 	def_bool !XEN_PRIVILEGED_GUEST
++	select PM
+ 
+ config XEN_PRIVCMD
+ 	def_bool y
+@@ -116,7 +117,7 @@ config XEN_NETDEV_LOOPBACK
+ 
+ config XEN_PCIDEV_BACKEND
+ 	tristate "PCI-device backend driver"
+-	depends on PCI && XEN_BACKEND
++	depends on PCI && XEN_PRIVILEGED_GUEST && XEN_BACKEND
+ 	default XEN_BACKEND
+ 	help
+ 	  The PCI device backend driver allows the kernel to export arbitrary
+@@ -127,8 +128,8 @@ config XEN_PCIDEV_BACKEND
+ choice
+ 	prompt "PCI Backend Mode"
+ 	depends on XEN_PCIDEV_BACKEND
+-	default XEN_PCIDEV_BACKEND_VPCI if !IA64
+ 	default XEN_PCIDEV_BACKEND_CONTROLLER if IA64
++	default XEN_PCIDEV_BACKEND_VPCI
+ 
+ config XEN_PCIDEV_BACKEND_VPCI
+ 	bool "Virtual PCI"
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.18-19
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.18-19
@@ -0,0 +1,316 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.19
+Patch-mainline: 2.6.32.19
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.18-19" by xen-port-patches.py
+
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-08-06 17:02:25.000000000 +0200
++++ sle11sp1-2010-09-22/arch/x86/kernel/apic/io_apic-xen.c	2010-08-23 12:10:22.000000000 +0200
+@@ -1556,7 +1556,7 @@ static struct {
+ 
+ static void __init setup_IO_APIC_irqs(void)
+ {
+-	int apic_id = 0, pin, idx, irq;
++	int apic_id, pin, idx, irq;
+ 	int notcon = 0;
+ 	struct irq_desc *desc;
+ 	struct irq_cfg *cfg;
+@@ -1564,14 +1564,7 @@ static void __init setup_IO_APIC_irqs(vo
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+ 
+-#ifdef CONFIG_ACPI
+-	if (!acpi_disabled && acpi_ioapic) {
+-		apic_id = mp_find_ioapic(0);
+-		if (apic_id < 0)
+-			apic_id = 0;
+-	}
+-#endif
+-
++	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
+ 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+ 		idx = find_irq_entry(apic_id, pin, mp_INT);
+ 		if (idx == -1) {
+@@ -1593,6 +1586,9 @@ static void __init setup_IO_APIC_irqs(vo
+ 
+ 		irq = pin_2_irq(idx, apic_id, pin);
+ 
++		if ((apic_id > 0) && (irq > 16))
++			continue;
++
+ #ifdef CONFIG_XEN
+ 		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+ 			continue;
+@@ -4208,27 +4204,23 @@ int acpi_get_override_irq(int bus_irq, i
+ #ifdef CONFIG_SMP
+ void __init setup_ioapic_dest(void)
+ {
+-	int pin, ioapic = 0, irq, irq_entry;
++	int pin, ioapic, irq, irq_entry;
+ 	struct irq_desc *desc;
+ 	const struct cpumask *mask;
+ 
+ 	if (skip_ioapic_setup == 1)
+ 		return;
+ 
+-#ifdef CONFIG_ACPI
+-	if (!acpi_disabled && acpi_ioapic) {
+-		ioapic = mp_find_ioapic(0);
+-		if (ioapic < 0)
+-			ioapic = 0;
+-	}
+-#endif
+-
++	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
+ 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+ 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+ 		if (irq_entry == -1)
+ 			continue;
+ 		irq = pin_2_irq(irq_entry, ioapic, pin);
+ 
++		if ((ioapic > 0) && (irq > 16))
++			continue;
++
+ 		desc = irq_to_desc(irq);
+ 
+ 		/*
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/kernel/vsyscall_64-xen.c	2010-08-23 12:10:22.000000000 +0200
+@@ -73,7 +73,8 @@ void update_vsyscall_tz(void)
+ 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+ 
+-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
++void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
++		     u32 mult)
+ {
+ 	unsigned long flags;
+ 
+@@ -82,7 +83,7 @@ void update_vsyscall(struct timespec *wa
+ 	vsyscall_gtod_data.clock.vread = clock->vread;
+ 	vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+ 	vsyscall_gtod_data.clock.mask = clock->mask;
+-	vsyscall_gtod_data.clock.mult = clock->mult;
++	vsyscall_gtod_data.clock.mult = mult;
+ 	vsyscall_gtod_data.clock.shift = clock->shift;
+ 	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+ 	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+--- sle11sp1-2010-09-22.orig/arch/x86/mm/fault-xen.c	2010-09-22 16:14:50.000000000 +0200
++++ sle11sp1-2010-09-22/arch/x86/mm/fault-xen.c	2010-09-22 16:16:42.000000000 +0200
+@@ -820,8 +820,10 @@ do_sigbus(struct pt_regs *regs, unsigned
+ 	up_read(&mm->mmap_sem);
+ 
+ 	/* Kernel mode? Handle exceptions or die: */
+-	if (!(error_code & PF_USER))
++	if (!(error_code & PF_USER)) {
+ 		no_context(regs, error_code, address);
++		return;
++	}
+ 
+ 	/* User-space => ok to do another page fault: */
+ 	if (is_prefetch(regs, error_code, address))
+--- sle11sp1-2010-09-22.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/mm/init_64-xen.c	2010-08-23 12:10:22.000000000 +0200
+@@ -862,6 +862,21 @@ void __init paging_init(void)
+  */
+ #ifdef CONFIG_MEMORY_HOTPLUG
+ /*
++ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
++ * updating.
++ */
++static void  update_end_of_memory_vars(u64 start, u64 size)
++{
++	unsigned long end_pfn = PFN_UP(start + size);
++
++	if (end_pfn > max_pfn) {
++		max_pfn = end_pfn;
++		max_low_pfn = end_pfn;
++		high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
++	}
++}
++
++/*
+  * Memory is added always to NORMAL zone. This means you will never get
+  * additional DMA/DMA32 memory.
+  */
+@@ -880,6 +895,9 @@ int arch_add_memory(int nid, u64 start, 
+ 	ret = __add_pages(nid, zone, start_pfn, nr_pages);
+ 	WARN_ON_ONCE(ret);
+ 
++	/* update max_pfn, max_low_pfn and high_memory */
++	update_end_of_memory_vars(start, size);
++
+ 	return ret;
+ }
+ EXPORT_SYMBOL_GPL(arch_add_memory);
+--- sle11sp1-2010-09-22.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:52:23.000000000 +0100
++++ sle11sp1-2010-09-22/drivers/xen/netfront/netfront.c	2010-09-22 11:32:21.000000000 +0200
+@@ -50,7 +50,6 @@
+ #include <linux/moduleparam.h>
+ #include <net/sock.h>
+ #include <net/pkt_sched.h>
+-#include <net/arp.h>
+ #include <net/route.h>
+ #include <asm/uaccess.h>
+ #include <xen/evtchn.h>
+@@ -220,7 +219,6 @@ static void netif_disconnect_backend(str
+ static int network_connect(struct net_device *);
+ static void network_tx_buf_gc(struct net_device *);
+ static void network_alloc_rx_buffers(struct net_device *);
+-static void send_fake_arp(struct net_device *);
+ 
+ static irqreturn_t netif_int(int irq, void *dev_id);
+ 
+@@ -237,6 +235,25 @@ static inline int xennet_can_sg(struct n
+ 	return dev->features & NETIF_F_SG;
+ }
+ 
++/*
++ * Work around net.ipv4.conf.*.arp_notify no being enabled by default.
++ */
++static void __devinit netfront_enable_arp_notify(struct netfront_info *info)
++{
++#ifdef CONFIG_INET
++	struct in_device *in_dev;
++
++	rtnl_lock();
++	in_dev = __in_dev_get_rtnl(info->netdev);
++	if (in_dev && !IN_DEV_CONF_GET(in_dev, ARP_NOTIFY))
++		IN_DEV_CONF_SET(in_dev, ARP_NOTIFY, 1);
++	rtnl_unlock();
++	if (!in_dev)
++		printk(KERN_WARNING "Cannot enable ARP notification on %s\n",
++		       info->xbdev->nodename);
++#endif
++}
++
+ /**
+  * Entry point to this code when a new device is created.  Allocate the basic
+  * structures and the ring buffers for communication with the backend, and
+@@ -266,6 +283,8 @@ static int __devinit netfront_probe(stru
+ 		goto fail;
+ 	}
+ 
++	netfront_enable_arp_notify(info);
++
+ 	err = xennet_sysfs_addif(info->netdev);
+ 	if (err) {
+ 		unregister_netdev(info->netdev);
+@@ -552,7 +571,7 @@ static void backend_changed(struct xenbu
+ 		if (network_connect(netdev) != 0)
+ 			break;
+ 		xenbus_switch_state(dev, XenbusStateConnected);
+-		send_fake_arp(netdev);
++		netif_notify_peers(netdev);
+ 		break;
+ 
+ 	case XenbusStateClosing:
+@@ -561,36 +580,6 @@ static void backend_changed(struct xenbu
+ 	}
+ }
+ 
+-/** Send a packet on a net device to encourage switches to learn the
+- * MAC. We send a fake ARP request.
+- *
+- * @param dev device
+- * @return 0 on success, error code otherwise
+- */
+-static void send_fake_arp(struct net_device *dev)
+-{
+-#ifdef CONFIG_INET
+-	struct sk_buff *skb;
+-	u32             src_ip, dst_ip;
+-
+-	dst_ip = INADDR_BROADCAST;
+-	src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK);
+-
+-	/* No IP? Then nothing to do. */
+-	if (src_ip == 0)
+-		return;
+-
+-	skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+-			 dst_ip, dev, src_ip,
+-			 /*dst_hw*/ NULL, /*src_hw*/ NULL,
+-			 /*target_hw*/ dev->dev_addr);
+-	if (skb == NULL)
+-		return;
+-
+-	dev_queue_xmit(skb);
+-#endif
+-}
+-
+ static inline int netfront_tx_slot_available(struct netfront_info *np)
+ {
+ 	return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
+@@ -2110,32 +2099,6 @@ static struct net_device * __devinit cre
+ 	return ERR_PTR(err);
+ }
+ 
+-#ifdef CONFIG_INET
+-/*
+- * We use this notifier to send out a fake ARP reply to reset switches and
+- * router ARP caches when an IP interface is brought up on a VIF.
+- */
+-static int
+-inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr)
+-{
+-	struct in_ifaddr  *ifa = (struct in_ifaddr *)ptr;
+-	struct net_device *dev = ifa->ifa_dev->dev;
+-
+-	/* UP event and is it one of our devices? */
+-	if (event == NETDEV_UP && dev->netdev_ops->ndo_open == network_open)
+-		send_fake_arp(dev);
+-
+-	return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block notifier_inetdev = {
+-	.notifier_call  = inetdev_notify,
+-	.next           = NULL,
+-	.priority       = 0
+-};
+-#endif
+-
+-
+ static void netif_disconnect_backend(struct netfront_info *info)
+ {
+ 	/* Stop old i/f to prevent errors whilst we rebuild the state. */
+@@ -2189,8 +2152,6 @@ static struct xenbus_driver netfront_dri
+ 
+ static int __init netif_init(void)
+ {
+-	int err;
+-
+ 	if (!is_running_on_xen())
+ 		return -ENODEV;
+ 
+@@ -2208,26 +2169,13 @@ static int __init netif_init(void)
+ 
+ 	IPRINTK("Initialising virtual ethernet driver.\n");
+ 
+-#ifdef CONFIG_INET
+-	(void)register_inetaddr_notifier(&notifier_inetdev);
+-#endif
+-
+-	err = xenbus_register_frontend(&netfront_driver);
+-	if (err) {
+-#ifdef CONFIG_INET
+-		unregister_inetaddr_notifier(&notifier_inetdev);
+-#endif
+-	}
+-	return err;
++	return xenbus_register_frontend(&netfront_driver);
+ }
+ module_init(netif_init);
+ 
+ 
+ static void __exit netif_exit(void)
+ {
+-#ifdef CONFIG_INET
+-	unregister_inetaddr_notifier(&notifier_inetdev);
+-#endif
+ 	xenbus_unregister_driver(&netfront_driver);
+ 
+ 	netif_exit_accel();
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/pci-reserve
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/pci-reserve
@@ -0,0 +1,241 @@
+Subject: linux/pci: reserve io/memory space for bridge
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 898:ca12928cdafe)
+Patch-mainline: obsolete
+
+reserve io/memory space for bridge which will be used later
+by PCI hotplug.
+
+Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/Documentation/kernel-parameters.txt	2009-12-04 10:27:46.000000000 +0100
++++ head-2010-01-18/Documentation/kernel-parameters.txt	2009-12-04 10:27:49.000000000 +0100
+@@ -1988,6 +1988,13 @@ and is between 256 and 4096 characters. 
+ 				off: Turn ECRC off
+ 				on: Turn ECRC on.
+ 
++	pci_reserve=	[PCI]
++			Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
++			Format of sbdf: [<segment>:]<bus>:<dev>.<func>
++			Specifies the least reserved io size or memory size
++			which is assigned to PCI bridge even when no child
++			pci device exists. This is useful with PCI hotplug.
++
+ 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
+ 			Management.
+ 		off	Disable ASPM.
+--- head-2010-01-18.orig/drivers/pci/Kconfig	2009-12-04 10:27:46.000000000 +0100
++++ head-2010-01-18/drivers/pci/Kconfig	2009-12-04 10:27:49.000000000 +0100
+@@ -56,6 +56,13 @@ config PCI_IOMULTI
+ 	help
+ 	  Say Y here if you need io multiplexing.
+ 
++config PCI_RESERVE
++	bool "PCI IO/MEMORY space reserve"
++	depends on PCI && XEN_PRIVILEGED_GUEST
++	default y
++	help
++	  Say Y here if you need PCI IO/MEMORY space reserve
++
+ config PCI_STUB
+ 	tristate "PCI Stub driver"
+ 	depends on PCI
+--- head-2010-01-18.orig/drivers/pci/Makefile	2009-12-04 10:27:46.000000000 +0100
++++ head-2010-01-18/drivers/pci/Makefile	2009-12-04 10:27:49.000000000 +0100
+@@ -9,6 +9,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
+ obj-$(CONFIG_SYSFS) += slot.o
+ obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
+ obj-$(CONFIG_PCI_IOMULTI) += iomulti.o
++obj-$(CONFIG_PCI_RESERVE) += reserve.o
+ 
+ obj-$(CONFIG_PCI_LEGACY) += legacy.o
+ CFLAGS_legacy.o += -Wno-deprecated-declarations
+--- head-2010-01-18.orig/drivers/pci/pci.h	2009-12-04 10:27:46.000000000 +0100
++++ head-2010-01-18/drivers/pci/pci.h	2009-12-04 10:27:49.000000000 +0100
+@@ -318,4 +318,19 @@ extern int pci_is_iomuldev(struct pci_de
+ #define pci_is_iomuldev(dev)	0
+ #endif
+ 
++#ifdef CONFIG_PCI_RESERVE
++unsigned long pci_reserve_size_io(struct pci_bus *bus);
++unsigned long pci_reserve_size_mem(struct pci_bus *bus);
++#else
++static inline unsigned long pci_reserve_size_io(struct pci_bus *bus)
++{
++	return 0;
++}
++
++static inline unsigned long pci_reserve_size_mem(struct pci_bus *bus)
++{
++	return 0;
++}
++#endif /* CONFIG_PCI_RESERVE */
++
+ #endif /* DRIVERS_PCI_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/pci/reserve.c	2009-12-04 10:27:49.000000000 +0100
+@@ -0,0 +1,143 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ *
++ * Copyright (c) 2009 Isaku Yamahata
++ *                    VA Linux Systems Japan K.K.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/pci.h>
++
++#include <asm/setup.h>
++
++static char pci_reserve_param[COMMAND_LINE_SIZE];
++
++/* pci_reserve=	[PCI]
++ * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
++ * Format of sbdf: [<segment>:]<bus>:<dev>.<func>
++ */
++static int pci_reserve_parse_size(const char *str,
++				  unsigned long *io_size,
++				  unsigned long *mem_size)
++{
++	if (sscanf(str, "io%lx", io_size) == 1 ||
++	    sscanf(str, "IO%lx", io_size) == 1)
++		return 0;
++
++	if (sscanf(str, "mem%lx", mem_size) == 1 ||
++	    sscanf(str, "MEM%lx", mem_size) == 1)
++		return 0;
++
++	return -EINVAL;
++}
++
++static int pci_reserve_parse_one(const char *str,
++				 int *seg, int *bus, int *dev, int *func,
++				 unsigned long *io_size,
++				 unsigned long *mem_size)
++{
++	char *p;
++
++	*io_size = 0;
++	*mem_size = 0;
++
++	if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) {
++		*seg = 0;
++		if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) {
++			return -EINVAL;
++		}
++	}
++
++	p = strchr(str, '+');
++	if (p == NULL)
++		return -EINVAL;
++	p++;
++	if (pci_reserve_parse_size(p, io_size, mem_size))
++		return -EINVAL;
++
++	p = strchr(str, '+');
++	if (p != NULL) {
++		p++;
++		pci_reserve_parse_size(p, io_size, mem_size);
++	}
++	return 0;
++}
++
++static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags)
++{
++	char *sp;
++	char *ep;
++
++	int seg;
++	int bus;
++	int dev;
++	int func;
++
++	unsigned long io_size;
++	unsigned long mem_size;
++
++	sp = pci_reserve_param;
++
++	do {
++		ep = strchr(sp, ',');
++		if (ep)
++			*ep = '\0';	/* chomp */
++
++		if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func,
++					  &io_size, &mem_size) == 0) {
++			if (pci_domain_nr(pbus) == seg &&
++			    pbus->number == bus &&
++			    PCI_SLOT(pbus->self->devfn) == dev &&
++			    PCI_FUNC(pbus->self->devfn) == func) {
++				switch (flags) {
++				case IORESOURCE_IO:
++					return io_size;
++				case IORESOURCE_MEM:
++					return mem_size;
++				default:
++					break;
++				}
++			}
++		}
++
++		if (ep) {
++			*ep = ',';	/* restore chomp'ed ',' for later */
++			ep++;
++		}
++		sp = ep;
++	} while (ep);
++
++	return 0;
++}
++
++unsigned long pci_reserve_size_io(struct pci_bus *pbus)
++{
++	return pci_reserve_size(pbus, IORESOURCE_IO);
++}
++
++unsigned long pci_reserve_size_mem(struct pci_bus *pbus)
++{
++	return pci_reserve_size(pbus, IORESOURCE_MEM);
++}
++
++static int __init pci_reserve_setup(char *str)
++{
++	if (strlen(str) >= sizeof(pci_reserve_param))
++		return 0;
++	strlcpy(pci_reserve_param, str, sizeof(pci_reserve_param));
++	return 1;
++}
++__setup("pci_reserve=", pci_reserve_setup);
+--- head-2010-01-18.orig/drivers/pci/setup-bus.c	2010-01-19 10:52:45.000000000 +0100
++++ head-2010-01-18/drivers/pci/setup-bus.c	2010-01-18 15:40:30.000000000 +0100
+@@ -338,7 +338,7 @@ static void pbus_size_io(struct pci_bus 
+ #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+ 	size = (size & 0xff) + ((size & ~0xffUL) << 2);
+ #endif
+-	size = ALIGN(size + size1, 4096);
++	size = ALIGN(max(size + size1, pci_reserve_size_io(bus)), 4096);
+ 	if (!size) {
+ 		b_res->flags = 0;
+ 		return;
+@@ -418,7 +418,8 @@ static int pbus_size_mem(struct pci_bus 
+ 			min_align = align1 >> 1;
+ 		align += aligns[order];
+ 	}
+-	size = ALIGN(size, min_align);
++	size = ALIGN(max(size, (resource_size_t)pci_reserve_size_mem(bus)),
++		     min_align);
+ 	if (!size) {
+ 		b_res->flags = 0;
+ 		return 1;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.23
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.23
@@ -0,0 +1,5197 @@
+From: www.kernel.org
+Subject: Update to 2.6.23
+Patch-mainline: 2.6.23
+
+Automatically created from "patches.kernel.org/patch-2.6.23" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kbuild	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/Kbuild	2009-11-06 10:51:07.000000000 +0100
+@@ -2,7 +2,7 @@
+ obj-$(CONFIG_KVM) += kvm/
+ 
+ # Xen paravirtualization support
+-obj-$(CONFIG_XEN) += xen/
++obj-$(CONFIG_PARAVIRT_XEN) += xen/
+ 
+ # lguest paravirtualization support
+ obj-$(CONFIG_LGUEST_GUEST) += lguest/
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_32-xen.c	2008-04-15 09:29:41.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -15,7 +15,7 @@
+ #ifndef CONFIG_ACPI_PV_SLEEP
+ /* address in low memory of the wakeup routine. */
+ unsigned long acpi_wakeup_address = 0;
+-unsigned long acpi_video_flags;
++unsigned long acpi_realmode_flags;
+ extern char wakeup_start, wakeup_end;
+ 
+ extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+@@ -74,9 +74,11 @@ static int __init acpi_sleep_setup(char 
+ {
+ 	while ((str != NULL) && (*str != '\0')) {
+ 		if (strncmp(str, "s3_bios", 7) == 0)
+-			acpi_video_flags = 1;
++			acpi_realmode_flags |= 1;
+ 		if (strncmp(str, "s3_mode", 7) == 0)
+-			acpi_video_flags |= 2;
++			acpi_realmode_flags |= 2;
++		if (strncmp(str, "s3_beep", 7) == 0)
++			acpi_realmode_flags |= 4;
+ 		str = strchr(str, ',');
+ 		if (str != NULL)
+ 			str += strspn(str, ", \t");
+@@ -86,9 +88,11 @@ static int __init acpi_sleep_setup(char 
+ 
+ __setup("acpi_sleep=", acpi_sleep_setup);
+ 
++/* Ouch, we want to delete this. We already have better version in userspace, in
++   s2ram from suspend.sf.net project */
+ static __init int reset_videomode_after_s3(struct dmi_system_id *d)
+ {
+-	acpi_video_flags |= 2;
++	acpi_realmode_flags |= 2;
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:51:07.000000000 +0100
+@@ -20,7 +20,9 @@
+ #include <asm/elf.h>
+ #include <asm/suspend.h>
+ 
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ #include <xen/interface/xen.h>
++#endif
+ 
+ #include <linux/lguest.h>
+ #include "../../../drivers/lguest/lg.h"
+@@ -123,7 +125,7 @@ void foo(void)
+ 	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
+ #endif
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ 	BLANK();
+ 	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+ 	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -362,6 +362,8 @@ static void __cpuinit generic_identify(s
+ 			if ( xlvl >= 0x80000004 )
+ 				get_model_name(c); /* Default name */
+ 		}
++
++		init_scattered_cpuid_features(c);
+ 	}
+ 
+ 	early_intel_workaround(c);
+@@ -613,7 +615,6 @@ extern int nsc_init_cpu(void);
+ extern int amd_init_cpu(void);
+ extern int centaur_init_cpu(void);
+ extern int transmeta_init_cpu(void);
+-extern int rise_init_cpu(void);
+ extern int nexgen_init_cpu(void);
+ extern int umc_init_cpu(void);
+ 
+@@ -625,7 +626,6 @@ void __init early_cpu_init(void)
+ 	amd_init_cpu();
+ 	centaur_init_cpu();
+ 	transmeta_init_cpu();
+-	rise_init_cpu();
+ 	nexgen_init_cpu();
+ 	umc_init_cpu();
+ 	early_cpu_detect();
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -167,7 +167,7 @@ mtrr_del(int reg, unsigned long base, un
+ EXPORT_SYMBOL(mtrr_add);
+ EXPORT_SYMBOL(mtrr_del);
+ 
+-__init void mtrr_bp_init(void)
++void __init mtrr_bp_init(void)
+ {
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -10,6 +10,7 @@
+ #include <linux/efi.h>
+ #include <linux/pfn.h>
+ #include <linux/uaccess.h>
++#include <linux/suspend.h>
+ 
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
+@@ -343,6 +344,37 @@ static int __init request_standard_resou
+ 
+ subsys_initcall(request_standard_resources);
+ 
++#if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)
++/**
++ * e820_mark_nosave_regions - Find the ranges of physical addresses that do not
++ * correspond to e820 RAM areas and mark the corresponding pages as nosave for
++ * hibernation.
++ *
++ * This function requires the e820 map to be sorted and without any
++ * overlapping entries and assumes the first e820 area to be RAM.
++ */
++void __init e820_mark_nosave_regions(void)
++{
++	int i;
++	unsigned long pfn;
++
++	pfn = PFN_DOWN(e820.map[0].addr + e820.map[0].size);
++	for (i = 1; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++
++		if (pfn < PFN_UP(ei->addr))
++			register_nosave_region(pfn, PFN_UP(ei->addr));
++
++		pfn = PFN_DOWN(ei->addr + ei->size);
++		if (ei->type != E820_RAM)
++			register_nosave_region(PFN_UP(ei->addr), pfn);
++
++		if (pfn >= max_low_pfn)
++			break;
++	}
++}
++#endif
++
+ void __init add_memory_region(unsigned long long start,
+ 			      unsigned long long size, int type)
+ {
+@@ -791,7 +823,7 @@ void __init print_memory_map(char *who)
+ 		case E820_NVS:
+ 				printk("(ACPI NVS)\n");
+ 				break;
+-		default:	printk("type %lu\n", e820.map[i].type);
++		default:	printk("type %u\n", e820.map[i].type);
+ 				break;
+ 		}
+ 	}
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32.S	2009-12-04 10:44:46.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32.S	2009-11-06 10:51:07.000000000 +0100
+@@ -1050,7 +1050,7 @@ ENTRY(kernel_thread_helper)
+ 	CFI_ENDPROC
+ ENDPROC(kernel_thread_helper)
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ /* Xen doesn't set %esp to be precisely what the normal sysenter
+    entrypoint expects, so fix it up before using the normal path. */
+ ENTRY(xen_sysenter_target)
+@@ -1143,7 +1143,7 @@ ENTRY(xen_failsafe_callback)
+ .previous
+ ENDPROC(xen_failsafe_callback)
+ 
+-#endif	/* CONFIG_XEN */
++#endif	/* CONFIG_PARAVIRT_XEN */
+ 
+ #ifdef CONFIG_FUNCTION_TRACER
+ #ifdef CONFIG_DYNAMIC_FTRACE
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:07.000000000 +0100
+@@ -452,9 +452,6 @@ restore_nocheck_notrace:
+ 1:	INTERRUPT_RETURN
+ .section .fixup,"ax"
+ iret_exc:
+-#ifndef CONFIG_XEN
+-	ENABLE_INTERRUPTS(CLBR_NONE)
+-#endif
+ 	pushl $0			# no error code
+ 	pushl $do_iret_error
+ 	jmp error_code
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:07.000000000 +0100
+@@ -86,7 +86,10 @@ ENTRY(_stext)
+ /*
+  * BSS section
+  */
+-.section ".bss.page_aligned","w"
++.section ".bss.page_aligned","wa"
++	.align PAGE_SIZE_asm
++ENTRY(swapper_pg_pmd)
++	.fill 1024,4,0
+ ENTRY(empty_zero_page)
+ 	.fill 4096,1,0
+ 
+@@ -136,25 +139,25 @@ ENTRY(empty_zero_page)
+ #endif /* CONFIG_XEN_COMPAT <= 0x030002 */
+ 
+ 
+-	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")	
+-	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
+-	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
+-	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long,  __PAGE_OFFSET)
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
++	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
++	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long __PAGE_OFFSET)
+ #if CONFIG_XEN_COMPAT <= 0x030002
+-	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  __PAGE_OFFSET)
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long __PAGE_OFFSET)
+ #else
+-	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  0)
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long 0)
+ #endif
+-	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long,  startup_32)
+-	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long,  hypercall_page)
+-	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long,  HYPERVISOR_VIRT_START)
+-	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_ENTRY,          .long startup_32)
++	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long hypercall_page)
++	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long HYPERVISOR_VIRT_START)
++	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
+ #ifdef CONFIG_X86_PAE
+-	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "yes")
+-	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  _PAGE_PRESENT,_PAGE_PRESENT)
++	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad _PAGE_PRESENT, _PAGE_PRESENT)
+ #else
+-	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz, "no")
+-	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .long,  _PAGE_PRESENT,_PAGE_PRESENT)
++	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "no")
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .long _PAGE_PRESENT, _PAGE_PRESENT)
+ #endif
+-	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz, "generic")
+-	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long,  1)
++	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
++	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -402,14 +402,6 @@ static void set_ioapic_affinity_irq(unsi
+ # include <linux/slab.h>		/* kmalloc() */
+ # include <linux/timer.h>	/* time_after() */
+  
+-#ifdef CONFIG_BALANCED_IRQ_DEBUG
+-#  define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
+-#  define Dprintk(x...) do { TDprintk(x); } while (0)
+-# else
+-#  define TDprintk(x...) 
+-#  define Dprintk(x...) 
+-# endif
+-
+ #define IRQBALANCE_CHECK_ARCH -999
+ #define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+ #define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
+@@ -492,7 +484,7 @@ static inline void balance_irq(int cpu, 
+ static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
+ {
+ 	int i, j;
+-	Dprintk("Rotating IRQs among CPUs.\n");
++
+ 	for_each_online_cpu(i) {
+ 		for (j = 0; j < NR_IRQS; j++) {
+ 			if (!irq_desc[j].action)
+@@ -609,19 +601,11 @@ tryanothercpu:
+ 	max_loaded = tmp_loaded;	/* processor */
+ 	imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+ 	
+-	Dprintk("max_loaded cpu = %d\n", max_loaded);
+-	Dprintk("min_loaded cpu = %d\n", min_loaded);
+-	Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq);
+-	Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq);
+-	Dprintk("load imbalance = %lu\n", imbalance);
+-
+ 	/* if imbalance is less than approx 10% of max load, then
+ 	 * observe diminishing returns action. - quit
+ 	 */
+-	if (imbalance < (max_cpu_irq >> 3)) {
+-		Dprintk("Imbalance too trivial\n");
++	if (imbalance < (max_cpu_irq >> 3))
+ 		goto not_worth_the_effort;
+-	}
+ 
+ tryanotherirq:
+ 	/* if we select an IRQ to move that can't go where we want, then
+@@ -678,9 +662,6 @@ tryanotherirq:
+ 	cpus_and(tmp, target_cpu_mask, allowed_mask);
+ 
+ 	if (!cpus_empty(tmp)) {
+-
+-		Dprintk("irq = %d moved to cpu = %d\n",
+-				selected_irq, min_loaded);
+ 		/* mark for change destination */
+ 		set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+ 
+@@ -700,7 +681,6 @@ not_worth_the_effort:
+ 	 */
+ 	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
+ 		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);	
+-	Dprintk("IRQ worth rotating not found\n");
+ 	return;
+ }
+ 
+@@ -716,6 +696,7 @@ static int balanced_irq(void *unused)
+ 		set_pending_irq(i, cpumask_of_cpu(0));
+ 	}
+ 
++	set_freezable();
+ 	for ( ; ; ) {
+ 		time_remaining = schedule_timeout_interruptible(time_remaining);
+ 		try_to_freeze();
+@@ -825,14 +806,6 @@ static int pirq_entries [MAX_PIRQS];
+ static int pirqs_enabled;
+ int skip_ioapic_setup;
+ 
+-static int __init ioapic_setup(char *str)
+-{
+-	skip_ioapic_setup = 1;
+-	return 1;
+-}
+-
+-__setup("noapic", ioapic_setup);
+-
+ static int __init ioapic_pirq_setup(char *str)
+ {
+ 	int i, max;
+@@ -1323,12 +1296,15 @@ static struct irq_chip ioapic_chip;
+ static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+ {
+ 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+-			trigger == IOAPIC_LEVEL)
++	    trigger == IOAPIC_LEVEL) {
++		irq_desc[irq].status |= IRQ_LEVEL;
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					 handle_fasteoi_irq, "fasteoi");
+-	else
++	} else {
++		irq_desc[irq].status &= ~IRQ_LEVEL;
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					 handle_edge_irq, "edge");
++	}
+ 	set_intr_gate(vector, interrupt[irq]);
+ }
+ #else
+@@ -1957,7 +1933,7 @@ __setup("no_timer_check", notimercheck);
+  *	- if this function detects that timer IRQs are defunct, then we fall
+  *	  back to ISA timer IRQs
+  */
+-int __init timer_irq_works(void)
++static int __init timer_irq_works(void)
+ {
+ 	unsigned long t1 = jiffies;
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -21,7 +21,7 @@
+ #include <asm/apic.h>
+ #include <asm/uaccess.h>
+ 
+-DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
++DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+ EXPORT_PER_CPU_SYMBOL(irq_stat);
+ 
+ DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+@@ -149,15 +149,11 @@ fastcall unsigned int do_IRQ(struct pt_r
+ 
+ #ifdef CONFIG_4KSTACKS
+ 
+-/*
+- * These should really be __section__(".bss.page_aligned") as well, but
+- * gcc's 3.0 and earlier don't handle that correctly.
+- */
+ static char softirq_stack[NR_CPUS * THREAD_SIZE]
+-		__attribute__((__aligned__(THREAD_SIZE)));
++		__attribute__((__section__(".bss.page_aligned")));
+ 
+ static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+-		__attribute__((__aligned__(THREAD_SIZE)));
++		__attribute__((__section__(".bss.page_aligned")));
+ 
+ /*
+  * allocate per-cpu stacks for hardirq and for softirq processing
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include <linux/miscdevice.h>
+ #include <linux/spinlock.h>
+ #include <linux/mm.h>
++#include <linux/fs.h>
+ #include <linux/mutex.h>
+ #include <linux/cpu.h>
+ #include <linux/firmware.h>
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -24,7 +24,7 @@
+ #include <asm/bug.h>
+ 
+ #ifdef __x86_64__
+-#include <asm/proto.h>
++#include <asm/iommu.h>
+ 
+ int iommu_merge __read_mostly = 0;
+ EXPORT_SYMBOL(iommu_merge);
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -241,6 +241,7 @@ early_param("idle", idle_setup);
+ void show_regs(struct pt_regs * regs)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
++	unsigned long d0, d1, d2, d3, d6, d7;
+ 
+ 	printk("\n");
+ 	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+@@ -265,6 +266,17 @@ void show_regs(struct pt_regs * regs)
+ 	cr3 = read_cr3();
+ 	cr4 = read_cr4_safe();
+ 	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
++
++	get_debugreg(d0, 0);
++	get_debugreg(d1, 1);
++	get_debugreg(d2, 2);
++	get_debugreg(d3, 3);
++	printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
++			d0, d1, d2, d3);
++	get_debugreg(d6, 6);
++	get_debugreg(d7, 7);
++	printk("DR6: %08lx DR7: %08lx\n", d6, d7);
++
+ 	show_trace(NULL, regs, &regs->esp);
+ }
+ 
+@@ -473,7 +485,30 @@ int dump_task_regs(struct task_struct *t
+ 	return 1;
+ }
+ 
+-static noinline void __switch_to_xtra(struct task_struct *next_p)
++#ifdef CONFIG_SECCOMP
++void hard_disable_TSC(void)
++{
++	write_cr4(read_cr4() | X86_CR4_TSD);
++}
++void disable_TSC(void)
++{
++	preempt_disable();
++	if (!test_and_set_thread_flag(TIF_NOTSC))
++		/*
++		 * Must flip the CPU state synchronously with
++		 * TIF_NOTSC in the current running context.
++		 */
++		hard_disable_TSC();
++	preempt_enable();
++}
++void hard_enable_TSC(void)
++{
++	write_cr4(read_cr4() & ~X86_CR4_TSD);
++}
++#endif /* CONFIG_SECCOMP */
++
++static noinline void
++__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *next;
+ 
+@@ -488,33 +523,17 @@ static noinline void __switch_to_xtra(st
+ 		set_debugreg(next->debugreg[6], 6);
+ 		set_debugreg(next->debugreg[7], 7);
+ 	}
+-}
+ 
+-/*
+- * This function selects if the context switch from prev to next
+- * has to tweak the TSC disable bit in the cr4.
+- */
+-static inline void disable_tsc(struct task_struct *prev_p,
+-			       struct task_struct *next_p)
+-{
+-	struct thread_info *prev, *next;
+-
+-	/*
+-	 * gcc should eliminate the ->thread_info dereference if
+-	 * has_secure_computing returns 0 at compile time (SECCOMP=n).
+-	 */
+-	prev = task_thread_info(prev_p);
+-	next = task_thread_info(next_p);
+-
+-	if (has_secure_computing(prev) || has_secure_computing(next)) {
+-		/* slow path here */
+-		if (has_secure_computing(prev) &&
+-		    !has_secure_computing(next)) {
+-			write_cr4(read_cr4() & ~X86_CR4_TSD);
+-		} else if (!has_secure_computing(prev) &&
+-			   has_secure_computing(next))
+-			write_cr4(read_cr4() | X86_CR4_TSD);
++#ifdef CONFIG_SECCOMP
++	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
++	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
++		/* prev and next are different */
++		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
++			hard_disable_TSC();
++		else
++			hard_enable_TSC();
+ 	}
++#endif
+ }
+ 
+ /*
+@@ -649,10 +668,9 @@ struct task_struct fastcall * __switch_t
+ 	/*
+ 	 * Now maybe handle debug registers
+ 	 */
+-	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
+-		__switch_to_xtra(next_p);
+-
+-	disable_tsc(prev_p, next_p);
++	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
++		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
++		__switch_to_xtra(prev_p, next_p);
+ 
+ 	/*
+ 	 * Leave lazy mode, flushing any hypercalls made here.
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -114,19 +114,10 @@ static unsigned int highmem_pages = -1;
+ /*
+  * Setup options
+  */
+-struct drive_info_struct { char dummy[32]; } drive_info;
+-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
+-    defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+-EXPORT_SYMBOL(drive_info);
+-#endif
+ struct screen_info screen_info;
+ EXPORT_SYMBOL(screen_info);
+ struct apm_info apm_info;
+ EXPORT_SYMBOL(apm_info);
+-struct sys_desc_table_struct {
+-	unsigned short length;
+-	unsigned char table[0];
+-};
+ struct edid_info edid_info;
+ EXPORT_SYMBOL_GPL(edid_info);
+ #ifndef CONFIG_XEN
+@@ -149,7 +140,7 @@ unsigned long saved_videomode;
+ 
+ static char __initdata command_line[COMMAND_LINE_SIZE];
+ 
+-unsigned char __initdata boot_params[PARAM_SIZE];
++struct boot_params __initdata boot_params;
+ 
+ /*
+  * Point at the empty zero page to start with. We map the real shared_info
+@@ -316,18 +307,18 @@ unsigned long __init find_max_low_pfn(vo
+ 		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+ 					MAXMEM>>20);
+ 		if (max_pfn > MAX_NONPAE_PFN)
+-			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
++			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
+ 		else
+ 			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+ 		max_pfn = MAXMEM_PFN;
+ #else /* !CONFIG_HIGHMEM */
+-#ifndef CONFIG_X86_PAE
++#ifndef CONFIG_HIGHMEM64G
+ 		if (max_pfn > MAX_NONPAE_PFN) {
+ 			max_pfn = MAX_NONPAE_PFN;
+ 			printk(KERN_WARNING "Warning only 4GB will be used.\n");
+-			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
++			printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
+ 		}
+-#endif /* !CONFIG_X86_PAE */
++#endif /* !CONFIG_HIGHMEM64G */
+ #endif /* !CONFIG_HIGHMEM */
+ 	} else {
+ 		if (highmem_pages == -1)
+@@ -516,7 +507,7 @@ void __init setup_bootmem_allocator(void
+  *
+  * This should all compile down to nothing when NUMA is off.
+  */
+-void __init remapped_pgdat_init(void)
++static void __init remapped_pgdat_init(void)
+ {
+ 	int nid;
+ 
+@@ -591,7 +582,6 @@ void __init setup_arch(char **cmdline_p)
+ 	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
+ 	*/
+ 	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
+- 	drive_info = DRIVE_INFO;
+  	screen_info = SCREEN_INFO;
+ 	copy_edid();
+ 	apm_info.bios = APM_BIOS_INFO;
+@@ -769,6 +759,8 @@ void __init setup_arch(char **cmdline_p)
+ 	 * NOTE: at this point the bootmem allocator is fully available.
+ 	 */
+ 
++	paravirt_post_allocator_init();
++
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
+@@ -816,6 +808,7 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ 	e820_register_memory();
++	e820_mark_nosave_regions();
+ 
+ 	if (is_initial_xendomain()) {
+ #ifdef CONFIG_VT
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -22,6 +22,7 @@
+ 
+ #include <asm/mtrr.h>
+ #include <asm/tlbflush.h>
++#include <asm/mmu_context.h>
+ #if 0
+ #include <mach_apic.h>
+ #endif
+@@ -217,13 +218,13 @@ static unsigned long flush_va;
+ static DEFINE_SPINLOCK(tlbstate_lock);
+ 
+ /*
+- * We cannot call mmdrop() because we are in interrupt context, 
++ * We cannot call mmdrop() because we are in interrupt context,
+  * instead update mm->cpu_vm_mask.
+  *
+  * We need to reload %cr3 since the page tables may be going
+  * away from under us..
+  */
+-static inline void leave_mm (unsigned long cpu)
++void leave_mm(unsigned long cpu)
+ {
+ 	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+ 		BUG();
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:27:26.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:31:38.000000000 +0100
+@@ -76,11 +76,12 @@
+ #include <xen/evtchn.h>
+ #include <xen/interface/vcpu.h>
+ 
+-#ifdef CONFIG_X86_32
+ #include <asm/i8253.h>
+ DEFINE_SPINLOCK(i8253_lock);
+ EXPORT_SYMBOL(i8253_lock);
+-#else
++
++#ifdef CONFIG_X86_64
++#include <asm/vsyscall.h>
+ volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+ #endif
+ 
+@@ -748,56 +749,10 @@ unsigned long read_persistent_clock(void
+ 	return retval;
+ }
+ 
+-static void sync_cmos_clock(unsigned long dummy);
+-
+-static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
+-int no_sync_cmos_clock;
+-
+-static void sync_cmos_clock(unsigned long dummy)
+-{
+-	struct timeval now, next;
+-	int fail = 1;
+-
+-	/*
+-	 * If we have an externally synchronized Linux clock, then update
+-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+-	 * called as close as possible to 500 ms before the new second starts.
+-	 * This code is run on a timer.  If the clock is set, that timer
+-	 * may not expire at the correct time.  Thus, we adjust...
+-	 */
+-	if (!ntp_synced())
+-		/*
+-		 * Not synced, exit, do not restart a timer (if one is
+-		 * running, let it run out).
+-		 */
+-		return;
+-
+-	do_gettimeofday(&now);
+-	if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
+-	    now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
+-		fail = set_rtc_mmss(now.tv_sec);
+-
+-	next.tv_usec = USEC_AFTER - now.tv_usec;
+-	if (next.tv_usec <= 0)
+-		next.tv_usec += USEC_PER_SEC;
+-
+-	if (!fail)
+-		next.tv_sec = 659;
+-	else
+-		next.tv_sec = 0;
+-
+-	if (next.tv_usec >= USEC_PER_SEC) {
+-		next.tv_sec++;
+-		next.tv_usec -= USEC_PER_SEC;
+-	}
+-	mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
+-}
+-
+-void notify_arch_cmos_timer(void)
++int update_persistent_clock(struct timespec now)
+ {
+-	if (!no_sync_cmos_clock)
+-		mod_timer(&sync_cmos_timer, jiffies + 1);
+ 	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
++	return set_rtc_mmss(now.tv_sec);
+ }
+ 
+ extern void (*late_time_init)(void);
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -41,6 +41,10 @@
+ #include <linux/mca.h>
+ #endif
+ 
++#if defined(CONFIG_EDAC)
++#include <linux/edac.h>
++#endif
++
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+@@ -102,36 +106,45 @@ asmlinkage void machine_check(void);
+ int kstack_depth_to_print = 24;
+ static unsigned int code_bytes = 64;
+ 
+-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
++static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size)
+ {
+ 	return	p > (void *)tinfo &&
+-		p < (void *)tinfo + THREAD_SIZE - 3;
++		p <= (void *)tinfo + THREAD_SIZE - size;
+ }
+ 
++/* The form of the top of the frame on the stack */
++struct stack_frame {
++	struct stack_frame *next_frame;
++	unsigned long return_address;
++};
++
+ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ 				unsigned long *stack, unsigned long ebp,
+ 				struct stacktrace_ops *ops, void *data)
+ {
+-	unsigned long addr;
+-
+ #ifdef	CONFIG_FRAME_POINTER
+-	while (valid_stack_ptr(tinfo, (void *)ebp)) {
+-		unsigned long new_ebp;
+-		addr = *(unsigned long *)(ebp + 4);
++	struct stack_frame *frame = (struct stack_frame *)ebp;
++	while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) {
++		struct stack_frame *next;
++		unsigned long addr;
++
++		addr = frame->return_address;
+ 		ops->address(data, addr);
+ 		/*
+ 		 * break out of recursive entries (such as
+ 		 * end_of_stack_stop_unwind_function). Also,
+ 		 * we can never allow a frame pointer to
+ 		 * move downwards!
+-	 	 */
+-	 	new_ebp = *(unsigned long *)ebp;
+-		if (new_ebp <= ebp)
++		 */
++		next = frame->next_frame;
++		if (next <= frame)
+ 			break;
+-		ebp = new_ebp;
++		frame = next;
+ 	}
+ #else
+-	while (valid_stack_ptr(tinfo, stack)) {
++	while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) {
++		unsigned long addr;
++
+ 		addr = *stack++;
+ 		if (__kernel_text_address(addr))
+ 			ops->address(data, addr);
+@@ -154,7 +167,7 @@ void dump_trace(struct task_struct *task
+ 	if (!stack) {
+ 		unsigned long dummy;
+ 		stack = &dummy;
+-		if (task && task != current)
++		if (task != current)
+ 			stack = (unsigned long *)task->thread.esp;
+ 	}
+ 
+@@ -213,6 +226,7 @@ static void print_trace_address(void *da
+ {
+ 	printk("%s [<%08lx>] ", (char *)data, addr);
+ 	print_symbol("%s\n", addr);
++	touch_nmi_watchdog();
+ }
+ 
+ static struct stacktrace_ops print_trace_ops = {
+@@ -396,7 +410,7 @@ void die(const char * str, struct pt_reg
+ 		unsigned long esp;
+ 		unsigned short ss;
+ 
+-		report_bug(regs->eip);
++		report_bug(regs->eip, regs);
+ 
+ 		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ #ifdef CONFIG_PREEMPT
+@@ -439,6 +453,7 @@ void die(const char * str, struct pt_reg
+ 
+ 	bust_spinlocks(0);
+ 	die.lock_owner = -1;
++	add_taint(TAINT_DIE);
+ 	spin_unlock_irqrestore(&die.lock, flags);
+ 
+ 	if (!regs)
+@@ -523,10 +538,12 @@ fastcall void do_##name(struct pt_regs *
+ 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+ 
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+ fastcall void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ 	siginfo_t info; \
++	if (irq) \
++		local_irq_enable(); \
+ 	info.si_signo = signr; \
+ 	info.si_errno = 0; \
+ 	info.si_code = sicode; \
+@@ -566,13 +583,13 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+ #endif
+ DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
++DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0)
+ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
+-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
++DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
++DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ 
+ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
+ 					      long error_code)
+@@ -585,6 +602,13 @@ fastcall void __kprobes do_general_prote
+ 
+ 	current->thread.error_code = error_code;
+ 	current->thread.trap_no = 13;
++	if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
++	    printk_ratelimit())
++		printk(KERN_INFO
++		    "%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
++		    current->comm, current->pid,
++		    regs->eip, regs->esp, error_code);
++
+ 	force_sig(SIGSEGV, current);
+ 	return;
+ 
+@@ -610,6 +634,14 @@ mem_parity_error(unsigned char reason, s
+ 	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+ 		"CPU %d.\n", reason, smp_processor_id());
+ 	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
++
++#if defined(CONFIG_EDAC)
++	if(edac_handler_set()) {
++		edac_atomic_assert_error();
++		return;
++	}
++#endif
++
+ 	if (panic_on_unrecovered_nmi)
+                 panic("NMI: Not continuing");
+ 
+@@ -720,6 +752,8 @@ static __kprobes void default_do_nmi(str
+ 	reassert_nmi();
+ }
+ 
++static int ignore_nmis;
++
+ fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code)
+ {
+ 	int cpu;
+@@ -730,11 +764,24 @@ fastcall __kprobes void do_nmi(struct pt
+ 
+ 	++nmi_count(cpu);
+ 
+-	default_do_nmi(regs);
++	if (!ignore_nmis)
++		default_do_nmi(regs);
+ 
+ 	nmi_exit();
+ }
+ 
++void stop_nmi(void)
++{
++	acpi_nmi_disable();
++	ignore_nmis++;
++}
++
++void restart_nmi(void)
++{
++	ignore_nmis--;
++	acpi_nmi_enable();
++}
++
+ #ifdef CONFIG_KPROBES
+ fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ {
+@@ -1023,6 +1070,7 @@ asmlinkage void math_state_restore(void)
+ 	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+ 	tsk->fpu_counter++;
+ }
++EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+ #ifndef CONFIG_MATH_EMULATION
+ 
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2009-11-06 10:51:07.000000000 +0100
+@@ -12,6 +12,7 @@
+ #include <asm/e820.h>
+ #include <asm/setup.h>
+ #include <asm/fixmap.h>
++#include <asm/pgtable.h>
+ 
+ #include <xen/interface/callback.h>
+ #include <xen/interface/memory.h>
+@@ -101,7 +102,7 @@ void __init pre_setup_arch_hook(void)
+ 
+ 	init_mm.pgd = swapper_pg_dir = (pgd_t *)xen_start_info->pt_base;
+ 
+-	setup_xen_features();
++	xen_setup_features();
+ 
+ 	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) {
+ 		hypervisor_virt_start = pp.virt_start;
+@@ -157,4 +158,18 @@ void __init machine_specific_arch_setup(
+ 		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+ 	}
+ #endif
++
++	/* Do an early initialization of the fixmap area */
++	{
++		extern pte_t swapper_pg_pmd[PTRS_PER_PTE];
++		unsigned long addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
++		pgd_t *pgd = (pgd_t *)xen_start_info->pt_base;
++		pud_t *pud = pud_offset(pgd + pgd_index(addr), addr);
++		pmd_t *pmd = pmd_offset(pud, addr);
++
++		swapper_pg_dir = pgd;
++		init_mm.pgd    = pgd;
++		make_lowmem_page_readonly(swapper_pg_pmd, XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa_symbol(swapper_pg_pmd) | _PAGE_TABLE));
++	}
+ }
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -346,7 +346,10 @@ static inline pmd_t *vmalloc_sync_one(pg
+ 	pmd_k = pmd_offset(pud_k, address);
+ 	if (!pmd_present(*pmd_k))
+ 		return NULL;
+-	if (!pmd_present(*pmd))
++	if (!pmd_present(*pmd)) {
++		bool lazy = x86_read_percpu(xen_lazy_mmu);
++
++		x86_write_percpu(xen_lazy_mmu, false);
+ #if CONFIG_XEN_COMPAT > 0x030002
+ 		set_pmd(pmd, *pmd_k);
+ #else
+@@ -356,7 +359,8 @@ static inline pmd_t *vmalloc_sync_one(pg
+ 		 */
+ 		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+ #endif
+-	else
++		x86_write_percpu(xen_lazy_mmu, lazy);
++	} else
+ 		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+ 	return pmd_k;
+ }
+@@ -388,6 +392,8 @@ static inline int vmalloc_fault(unsigned
+ 	return 0;
+ }
+ 
++int show_unhandled_signals = 1;
++
+ /*
+  * This routine handles page faults.  It determines the address,
+  * and the problem, and then passes it off to one of the appropriate
+@@ -408,6 +414,7 @@ fastcall void __kprobes do_page_fault(st
+ 	struct vm_area_struct * vma;
+ 	unsigned long address;
+ 	int write, si_code;
++	int fault;
+ 
+ 	/* get the address */
+         address = read_cr2();
+@@ -541,20 +548,18 @@ good_area:
+ 	 * make sure we exit gracefully rather than endlessly redo
+ 	 * the fault.
+ 	 */
+-	switch (handle_mm_fault(mm, vma, address, write)) {
+-		case VM_FAULT_MINOR:
+-			tsk->min_flt++;
+-			break;
+-		case VM_FAULT_MAJOR:
+-			tsk->maj_flt++;
+-			break;
+-		case VM_FAULT_SIGBUS:
+-			goto do_sigbus;
+-		case VM_FAULT_OOM:
++	fault = handle_mm_fault(mm, vma, address, write);
++	if (unlikely(fault & VM_FAULT_ERROR)) {
++		if (fault & VM_FAULT_OOM)
+ 			goto out_of_memory;
+-		default:
+-			BUG();
++		else if (fault & VM_FAULT_SIGBUS)
++			goto do_sigbus;
++		BUG();
+ 	}
++	if (fault & VM_FAULT_MAJOR)
++		tsk->maj_flt++;
++	else
++		tsk->min_flt++;
+ 
+ 	/*
+ 	 * Did it hit the DOS screen memory VA from vm86 mode?
+@@ -589,6 +594,14 @@ bad_area_nosemaphore:
+ 		if (is_prefetch(regs, address, error_code))
+ 			return;
+ 
++		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++		    printk_ratelimit()) {
++			printk("%s%s[%d]: segfault at %08lx eip %08lx "
++			    "esp %08lx error %lx\n",
++			    tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
++			    tsk->comm, tsk->pid, address, regs->eip,
++			    regs->esp, error_code);
++		}
+ 		tsk->thread.cr2 = address;
+ 		/* Kernel addresses are always protection faults */
+ 		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -34,17 +34,16 @@ void *kmap_atomic_prot(struct page *page
+ 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+ 	pagefault_disable();
+ 
+-	idx = type + KM_TYPE_NR*smp_processor_id();
+-	BUG_ON(!pte_none(*(kmap_pte-idx)));
+-
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
++	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++	BUG_ON(!pte_none(*(kmap_pte-idx)));
+ 	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+ 	/*arch_flush_lazy_mmu_mode();*/
+ 
+-	return (void*) vaddr;
++	return (void *)vaddr;
+ }
+ 
+ void *kmap_atomic(struct page *page, enum km_type type)
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -96,7 +96,7 @@ static pte_t * __init one_page_table_ini
+ #endif
+ 		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ 
+-		paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
++		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+ 					  XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+@@ -453,7 +453,7 @@ static void __init pagetable_init (void)
+ 	xen_pagetable_setup_done(pgd_base);
+ }
+ 
+-#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
++#if defined(CONFIG_HIBERNATION) || defined(CONFIG_ACPI)
+ /*
+  * Swap suspend & friends need this for resume because things like the intel-agp
+  * driver might have split up a kernel 4MB mapping.
+@@ -492,9 +492,13 @@ void zap_low_mappings (void)
+ 	flush_tlb_all();
+ }
+ 
++int nx_enabled = 0;
++
++#ifdef CONFIG_X86_PAE
++
+ static int disable_nx __initdata = 0;
+ u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
+-EXPORT_SYMBOL(__supported_pte_mask);
++EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+ /*
+  * noexec = on|off
+@@ -521,9 +525,6 @@ static int __init noexec_setup(char *str
+ }
+ early_param("noexec", noexec_setup);
+ 
+-int nx_enabled = 0;
+-#ifdef CONFIG_X86_PAE
+-
+ static void __init set_nx(void)
+ {
+ 	unsigned int v[4], l, h;
+@@ -770,7 +771,7 @@ void __init mem_init(void)
+ 	zap_low_mappings();
+ #endif
+ 
+-	set_bit(PG_pinned, &virt_to_page(init_mm.pgd)->flags);
++	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+ 
+ #ifdef CONFIG_MEMORY_HOTPLUG
+@@ -802,8 +803,7 @@ void __init pgtable_cache_init(void)
+ 					PTRS_PER_PMD*sizeof(pmd_t),
+ 					PTRS_PER_PMD*sizeof(pmd_t),
+ 					SLAB_PANIC,
+-					pmd_ctor,
+-					NULL);
++					pmd_ctor);
+ 		if (!SHARED_KERNEL_PMD) {
+ 			/* If we're in PAE mode and have a non-shared
+ 			   kernel pmd, then the pgd size must be a
+--- head-2010-01-18.orig/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -363,9 +363,8 @@ void iounmap(volatile void __iomem *addr
+ 
+ 	/* Reset the direct mapping. Can block */
+ 	if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
+-		/* p->size includes the guard page, but cpa doesn't like that */
+ 		change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
+-				 (p->size - PAGE_SIZE) >> PAGE_SHIFT,
++				 get_vm_area_size(p) >> PAGE_SHIFT,
+ 				 PAGE_KERNEL);
+ 		global_flush_tlb();
+ 	} 
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -198,7 +198,7 @@ void pte_free(struct page *pte)
+ 				va, pfn_pte(pfn, PAGE_KERNEL), 0))
+ 				BUG();
+ 	} else
+-		clear_bit(PG_pinned, &pte->flags);
++		ClearPagePinned(pte);
+ 
+ 	ClearPageForeign(pte);
+ 	init_page_count(pte);
+@@ -248,7 +248,7 @@ static inline void pgd_list_del(pgd_t *p
+ 
+ #if (PTRS_PER_PMD == 1)
+ /* Non-PAE pgd constructor */
+-void pgd_ctor(void *pgd)
++static void pgd_ctor(void *pgd)
+ {
+ 	unsigned long flags;
+ 
+@@ -271,7 +271,7 @@ void pgd_ctor(void *pgd)
+ }
+ #else  /* PTRS_PER_PMD > 1 */
+ /* PAE pgd constructor */
+-void pgd_ctor(void *pgd)
++static void pgd_ctor(void *pgd)
+ {
+ 	/* PAE, kernel PMD may be shared */
+ 
+@@ -285,7 +285,7 @@ void pgd_ctor(void *pgd)
+ }
+ #endif	/* PTRS_PER_PMD */
+ 
+-void pgd_dtor(void *pgd)
++static void pgd_dtor(void *pgd)
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
+@@ -637,9 +637,9 @@ static inline unsigned int pgd_walk_set_
+ 
+ 	if (PageHighMem(page)) {
+ 		if (pgprot_val(flags) & _PAGE_RW)
+-			clear_bit(PG_pinned, &page->flags);
++			ClearPagePinned(page);
+ 		else
+-			set_bit(PG_pinned, &page->flags);
++			SetPagePinned(page);
+ 	} else {
+ 		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+ 				(unsigned long)__va(pfn << PAGE_SHIFT),
+@@ -709,19 +709,19 @@ static void __pgd_pin(pgd_t *pgd)
+ 	pgd_walk(pgd, PAGE_KERNEL_RO);
+ 	kmap_flush_unused();
+ 	xen_pgd_pin(__pa(pgd));
+-	set_bit(PG_pinned, &virt_to_page(pgd)->flags);
++	SetPagePinned(virt_to_page(pgd));
+ }
+ 
+ static void __pgd_unpin(pgd_t *pgd)
+ {
+ 	xen_pgd_unpin(__pa(pgd));
+ 	pgd_walk(pgd, PAGE_KERNEL);
+-	clear_bit(PG_pinned, &virt_to_page(pgd)->flags);
++	ClearPagePinned(virt_to_page(pgd));
+ }
+ 
+ static void pgd_test_and_unpin(pgd_t *pgd)
+ {
+-	if (test_bit(PG_pinned, &virt_to_page(pgd)->flags))
++	if (PagePinned(virt_to_page(pgd)))
+ 		__pgd_unpin(pgd);
+ }
+ 
+@@ -759,7 +759,7 @@ void mm_pin_all(void)
+ 	 */
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 	for (page = pgd_list; page; page = (struct page *)page->index) {
+-		if (!test_bit(PG_pinned, &page->flags))
++		if (!PagePinned(page))
+ 			__pgd_pin((pgd_t *)page_address(page));
+ 	}
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+@@ -767,7 +767,7 @@ void mm_pin_all(void)
+ 
+ void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+ {
+-	if (!test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags))
++	if (!PagePinned(virt_to_page(mm->pgd)))
+ 		mm_pin(mm);
+ }
+ 
+@@ -793,7 +793,7 @@ void arch_exit_mmap(struct mm_struct *mm
+ 
+ 	task_unlock(tsk);
+ 
+-	if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
++	if (PagePinned(virt_to_page(mm->pgd)) &&
+ 	    (atomic_read(&mm->mm_count) == 1) &&
+ 	    !mm->context.has_foreign_mappings)
+ 		mm_unpin(mm);
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -142,8 +142,9 @@ static void __init pirq_peer_trick(void)
+ 	for(i = 1; i < 256; i++) {
+ 		if (!busmap[i] || pci_find_bus(0, i))
+ 			continue;
+-		if (pci_scan_bus(i, &pci_root_ops, NULL))
+-			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
++		if (pci_scan_bus_with_sysdata(i))
++			printk(KERN_INFO "PCI: Discovered primary peer "
++			       "bus %02x [IRQ]\n", i);
+ 	}
+ 	pcibios_last_bus = -1;
+ }
+@@ -553,6 +554,7 @@ static __init int intel_router_probe(str
+ 		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_TOLAPAI_0:
+ 			r->name = "PIIX/ICH";
+ 			r->get = pirq_piix_get;
+ 			r->set = pirq_piix_set;
+--- head-2010-01-18.orig/arch/x86/xen/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/xen/Kconfig	2009-11-20 11:01:03.000000000 +0100
+@@ -2,7 +2,7 @@
+ # This Kconfig describes xen options
+ #
+ 
+-config XEN
++config PARAVIRT_XEN
+ 	bool "Xen guest support"
+ 	select PARAVIRT_ALL
+ 	select PARAVIRT_CLOCK
+--- head-2010-01-18.orig/arch/x86/xen/xen-head.S	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/xen/xen-head.S	2009-11-06 10:51:07.000000000 +0100
+@@ -1,7 +1,7 @@
+ /* Xen-specific pieces of head.S, intended to be included in the right
+ 	place in head.S */
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ 
+ #include <linux/elfnote.h>
+ #include <linux/init.h>
+@@ -52,4 +52,4 @@ ENTRY(hypercall_page)
+ 	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   _ASM_PTR __HYPERVISOR_VIRT_START)
+ 	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
+ 
+-#endif /*CONFIG_XEN */
++#endif /* CONFIG_PARAVIRT_XEN */
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:07.000000000 +0100
+@@ -105,7 +105,7 @@ ENTRY(ia32_sysenter_target)
+ 	movl	$VSYSCALL32_SYSEXIT,8(%rsp)
+ 	movq	%rax,(%rsp)
+ 	cld
+-	SAVE_ARGS 0,0,0
++	SAVE_ARGS 0,0,1
+  	/* no need to do an access_ok check here because rbp has been
+  	   32bit zero extended */ 
+ 1:	movl	(%rbp),%r9d
+@@ -244,7 +244,7 @@ ia32_badarg:
+  */ 				
+ 
+ ENTRY(ia32_syscall)
+-	CFI_STARTPROC	simple
++	CFI_STARTPROC32	simple
+ 	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA	rsp,SS+8-RIP+16
+ 	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+@@ -280,6 +280,7 @@ ia32_sysret:
+ 
+ ia32_tracesys:			 
+ 	SAVE_REST
++	CLEAR_RREGS
+ 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+@@ -476,7 +477,7 @@ ia32_sys_call_table:
+ 	.quad sys_init_module
+ 	.quad sys_delete_module
+ 	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
+-	.quad sys_quotactl
++	.quad sys32_quotactl
+ 	.quad sys_getpgid
+ 	.quad sys_fchdir
+ 	.quad quiet_ni_syscall	/* bdflush */
+@@ -669,4 +670,5 @@ ia32_sys_call_table:
+ 	.quad compat_sys_signalfd
+ 	.quad compat_sys_timerfd
+ 	.quad sys_eventfd
++	.quad sys32_fallocate
+ ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -51,12 +51,10 @@
+                               Low-Level Sleep Support
+    -------------------------------------------------------------------------- */
+ 
+-#ifdef CONFIG_ACPI_SLEEP
+-
+ #ifndef CONFIG_ACPI_PV_SLEEP
+ /* address in low memory of the wakeup routine. */
+ unsigned long acpi_wakeup_address = 0;
+-unsigned long acpi_video_flags;
++unsigned long acpi_realmode_flags;
+ extern char wakeup_start, wakeup_end;
+ 
+ extern unsigned long acpi_copy_wakeup_routine(unsigned long);
+@@ -109,9 +107,11 @@ static int __init acpi_sleep_setup(char 
+ {
+ 	while ((str != NULL) && (*str != '\0')) {
+ 		if (strncmp(str, "s3_bios", 7) == 0)
+-			acpi_video_flags = 1;
++			acpi_realmode_flags |= 1;
+ 		if (strncmp(str, "s3_mode", 7) == 0)
+-			acpi_video_flags |= 2;
++			acpi_realmode_flags |= 2;
++		if (strncmp(str, "s3_beep", 7) == 0)
++			acpi_realmode_flags |= 4;
+ 		str = strchr(str, ',');
+ 		if (str != NULL)
+ 			str += strspn(str, ", \t");
+@@ -123,8 +123,6 @@ static int __init acpi_sleep_setup(char 
+ __setup("acpi_sleep=", acpi_sleep_setup);
+ #endif				/* CONFIG_ACPI_PV_SLEEP */
+ 
+-#endif				/*CONFIG_ACPI_SLEEP */
+-
+ void acpi_pci_link_exit(void)
+ {
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -50,7 +50,7 @@ void ack_bad_irq(unsigned int irq)
+ 	 * holds up an irq slot - in excessive cases (when multiple
+ 	 * unexpected vectors occur) that might lock up the APIC
+ 	 * completely.
+-  	 * But don't ack when the APIC is disabled. -AK
++	 * But don't ack when the APIC is disabled. -AK
+ 	 */
+ 	if (!disable_apic)
+ 		ack_APIC_irq();
+@@ -132,20 +132,6 @@ asmlinkage void smp_spurious_interrupt(v
+ 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+ 		ack_APIC_irq();
+ 
+-#if 0
+-	static unsigned long last_warning; 
+-	static unsigned long skipped; 
+-
+-	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
+-	if (time_before(last_warning+30*HZ,jiffies)) { 
+-		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
+-		       smp_processor_id(), skipped);
+-		last_warning = jiffies; 
+-		skipped = 0;
+-	} else { 
+-		skipped++; 
+-	} 
+-#endif 
+ 	irq_exit();
+ }
+ 
+@@ -177,7 +163,7 @@ asmlinkage void smp_error_interrupt(void
+ 	   7: Illegal register address
+ 	*/
+ 	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
+-	        smp_processor_id(), v , v1);
++		smp_processor_id(), v , v1);
+ 	irq_exit();
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:57:54.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:00:18.000000000 +0100
+@@ -224,37 +224,6 @@ unsigned long __init e820_end_of_ram(voi
+ }
+ 
+ /*
+- * Find the hole size in the range.
+- */
+-unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
+-{
+-	unsigned long ram = 0;
+-	int i;
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		unsigned long last, addr;
+-
+-		if (ei->type != E820_RAM ||
+-		    ei->addr+ei->size <= start ||
+-		    ei->addr >= end)
+-			continue;
+-
+-		addr = round_up(ei->addr, PAGE_SIZE);
+-		if (addr < start)
+-			addr = start;
+-
+-		last = round_down(ei->addr + ei->size, PAGE_SIZE);
+-		if (last >= end)
+-			last = end;
+-
+-		if (last > addr)
+-			ram += last - addr;
+-	}
+-	return ((end - start) - ram);
+-}
+-
+-/*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+ void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
+@@ -327,54 +296,66 @@ void __init e820_mark_nosave_regions(voi
+ }
+ #endif
+ 
++/*
++ * Finds an active region in the address range from start_pfn to end_pfn and
++ * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
++ */
++static int __init e820_find_active_region(const struct e820entry *ei,
++					  unsigned long start_pfn,
++					  unsigned long end_pfn,
++					  unsigned long *ei_startpfn,
++					  unsigned long *ei_endpfn)
++{
++#ifdef CONFIG_XEN
++	if (end_pfn > xen_start_info->nr_pages)
++		end_pfn = xen_start_info->nr_pages;
++#endif
++
++	*ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
++	*ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE) >> PAGE_SHIFT;
++
++	/* Skip map entries smaller than a page */
++	if (*ei_startpfn >= *ei_endpfn)
++		return 0;
++
++	/* Check if end_pfn_map should be updated */
++	if (ei->type != E820_RAM && *ei_endpfn > end_pfn_map)
++		end_pfn_map = *ei_endpfn;
++
++	/* Skip if map is outside the node */
++	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
++				    *ei_startpfn >= end_pfn)
++		return 0;
++
++	/* Check for overlaps */
++	if (*ei_startpfn < start_pfn)
++		*ei_startpfn = start_pfn;
++	if (*ei_endpfn > end_pfn)
++		*ei_endpfn = end_pfn;
++
++	/* Obey end_user_pfn to save on memmap */
++	if (*ei_startpfn >= end_user_pfn)
++		return 0;
++	if (*ei_endpfn > end_user_pfn)
++		*ei_endpfn = end_user_pfn;
++
++	return 1;
++}
++
+ /* Walk the e820 map and register active regions within a node */
+ void __init
+ e820_register_active_regions(int nid, unsigned long start_pfn,
+ 							unsigned long end_pfn)
+ {
++	unsigned long ei_startpfn;
++	unsigned long ei_endpfn;
+ 	int i;
+-	unsigned long ei_startpfn, ei_endpfn;
+-	for (i = 0; i < e820.nr_map; i++) {
+-		struct e820entry *ei = &e820.map[i];
+-		ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
+-		ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
+-								>> PAGE_SHIFT;
+-
+-		/* Skip map entries smaller than a page */
+-		if (ei_startpfn >= ei_endpfn)
+-			continue;
+-
+-		/* Check if end_pfn_map should be updated */
+-		if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
+-			end_pfn_map = ei_endpfn;
+-
+-		/* Skip if map is outside the node */
+-		if (ei->type != E820_RAM ||
+-				ei_endpfn <= start_pfn ||
+-				ei_startpfn >= end_pfn)
+-			continue;
+-
+-		/* Check for overlaps */
+-		if (ei_startpfn < start_pfn)
+-			ei_startpfn = start_pfn;
+-		if (ei_endpfn > end_pfn)
+-			ei_endpfn = end_pfn;
+-
+-		/* Obey end_user_pfn to save on memmap */
+-		if (ei_startpfn >= end_user_pfn)
+-			continue;
+-		if (ei_endpfn > end_user_pfn)
+-			ei_endpfn = end_user_pfn;
+-
+-#ifdef CONFIG_XEN
+-		if (ei_startpfn >= xen_start_info->nr_pages)
+-			continue;
+-		if (ei_endpfn > xen_start_info->nr_pages)
+-			ei_endpfn = xen_start_info->nr_pages;
+-#endif
+ 
+-		add_active_range(nid, ei_startpfn, ei_endpfn);
+-	}
++	for (i = 0; i < e820.nr_map; i++)
++		if (e820_find_active_region(&e820.map[i],
++					    start_pfn, end_pfn,
++					    &ei_startpfn, &ei_endpfn))
++			add_active_range(nid, ei_startpfn, ei_endpfn);
+ #ifdef CONFIG_XEN
+ 	BUG_ON(nid);
+ 	add_active_range(nid, end_pfn, end_pfn);
+@@ -399,12 +380,35 @@ void __init add_memory_region(unsigned l
+ 	e820.nr_map++;
+ }
+ 
++/*
++ * Find the hole size (in bytes) in the memory range.
++ * @start: starting address of the memory range to scan
++ * @end: ending address of the memory range to scan
++ */
++unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
++{
++	unsigned long start_pfn = start >> PAGE_SHIFT;
++	unsigned long end_pfn = end >> PAGE_SHIFT;
++	unsigned long ei_startpfn;
++	unsigned long ei_endpfn;
++	unsigned long ram = 0;
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		if (e820_find_active_region(&e820.map[i],
++					    start_pfn, end_pfn,
++					    &ei_startpfn, &ei_endpfn))
++			ram += ei_endpfn - ei_startpfn;
++	}
++	return end - start - (ram << PAGE_SHIFT);
++}
++
+ void __init e820_print_map(char *who)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+-		printk(" %s: %016Lx - %016Lx ", who,
++		printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
+ 			(unsigned long long) e820.map[i].addr,
+ 			(unsigned long long) (e820.map[i].addr + e820.map[i].size));
+ 		switch (e820.map[i].type) {
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -174,6 +174,7 @@ static __init void early_serial_init(cha
+  * mappings. Someone should fix this for domain 0. For now, use fake serial.
+  */
+ #define early_vga_console early_serial_console
++#define xenboot_console early_serial_console
+ 
+ #endif
+ 
+@@ -261,20 +262,22 @@ static int __init setup_early_printk(cha
+ 	} else if (!strncmp(buf, "ttyS", 4)) {
+ 		early_serial_init(buf);
+ 		early_console = &early_serial_console;
+-	} else if (!strncmp(buf, "vga", 3)
++	} else if (!strncmp(buf, "vga", 3)) {
+ #ifndef CONFIG_XEN
+ 	           && SCREEN_INFO.orig_video_isVGA == 1) {
+ 		max_xpos = SCREEN_INFO.orig_video_cols;
+ 		max_ypos = SCREEN_INFO.orig_video_lines;
+ 		current_ypos = SCREEN_INFO.orig_y;
+-#else
+-	           || !strncmp(buf, "xen", 3)) {
+ #endif
+ 		early_console = &early_vga_console;
+  	} else if (!strncmp(buf, "simnow", 6)) {
+  		simnow_init(buf + 6);
+  		early_console = &simnow_console;
+  		keep_early = 1;
++#ifdef CONFIG_XEN
++	} else if (!strncmp(buf, "xen", 3)) {
++		early_console = &xenboot_console;
++#endif
+ 	}
+ 
+ 	if (keep_early)
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:07.000000000 +0100
+@@ -310,7 +310,7 @@ sysret_signal:
+ 	TRACE_IRQS_ON
+ /*	sti */
+         XEN_UNBLOCK_EVENTS(%rsi)        
+-	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
++	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
+ 	jz    1f
+ 
+ 	/* Really a signal */
+@@ -409,7 +409,7 @@ int_very_careful:
+ 	jmp int_restore_rest
+ 	
+ int_signal:
+-	testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
++	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
+ 	jz 1f
+ 	movq %rsp,%rdi		# &ptregs -> arg1
+ 	xorl %esi,%esi		# oldset -> arg2
+@@ -552,7 +552,7 @@ retint_careful:
+ 	jmp retint_check
+ 	
+ retint_signal:
+-	testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
++	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
+ 	jz    retint_restore_args
+ 	TRACE_IRQS_ON
+         XEN_UNBLOCK_EVENTS(%rsi)
+--- head-2010-01-18.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_64-xen.S	2009-11-06 10:51:07.000000000 +0100
+@@ -23,7 +23,7 @@
+ #include <asm/dwarf2.h>
+ #include <xen/interface/elfnote.h>
+ 
+-	.section .bootstrap.text, "ax", @progbits
++	.section .text.head, "ax", @progbits
+ 	.code64
+ 	.globl startup_64
+ startup_64:
+@@ -39,7 +39,7 @@ startup_64:
+ 
+ #define NEXT_PAGE(name) \
+ 	.balign	PAGE_SIZE; \
+-	phys_##name = . - .bootstrap.text; \
++	phys_##name = . - .text.head; \
+ ENTRY(name)
+ 
+ NEXT_PAGE(init_level4_pgt)
+@@ -63,6 +63,12 @@ NEXT_PAGE(level3_kernel_pgt)
+ NEXT_PAGE(level3_user_pgt)
+         .fill	512,8,0
+ 
++NEXT_PAGE(level2_fixmap_pgt)
++	.fill	512,8,0
++
++NEXT_PAGE(level1_fixmap_pgt)
++	.fill	512,8,0
++
+ NEXT_PAGE(hypercall_page)
+ 	CFI_STARTPROC
+ 	.rept 0x1000 / 0x20
+@@ -169,18 +175,18 @@ ENTRY(empty_zero_page)
+ 	.byte	0
+ #endif /* CONFIG_XEN_COMPAT <= 0x030002 */
+ 	
+-	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")
+-	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
+-	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
+-	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad,  __START_KERNEL_map)
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
++	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
++	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
++	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad __START_KERNEL_map)
+ #if CONFIG_XEN_COMPAT <= 0x030002
+-	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  __START_KERNEL_map)
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad __START_KERNEL_map)
+ #else
+-	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  0)
++	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad 0)
+ #endif
+-	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad,  startup_64)
+-	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad,  hypercall_page)
+-	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  _PAGE_PRESENT,_PAGE_PRESENT)
+-	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)
++	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad startup_64)
++	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad hypercall_page)
++	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad _PAGE_PRESENT, _PAGE_PRESENT)
++	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)
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -90,7 +90,7 @@ void __init x86_64_start_kernel(char * r
+ 	unsigned long machine_to_phys_nr_ents;
+ 	int i;
+ 
+-	setup_xen_features();
++	xen_setup_features();
+ 
+ 	xen_start_info = (struct start_info *)real_mode_data;
+ 	if (!xen_feature(XENFEAT_auto_translated_physmap))
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -165,7 +165,9 @@ static inline void io_apic_write(unsigne
+ #endif
+ }
+ 
+-#ifndef CONFIG_XEN
++#ifdef CONFIG_XEN
++#define io_apic_modify io_apic_write
++#else
+ /*
+  * Re-write a value: to be used for read-modify-write
+  * cycles where the read already set up the index register.
+@@ -175,8 +177,32 @@ static inline void io_apic_modify(unsign
+ 	struct io_apic __iomem *io_apic = io_apic_base(apic);
+ 	writel(value, &io_apic->data);
+ }
+-#else
+-#define io_apic_modify io_apic_write
++
++static int io_apic_level_ack_pending(unsigned int irq)
++{
++	struct irq_pin_list *entry;
++	unsigned long flags;
++	int pending = 0;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	entry = irq_2_pin + irq;
++	for (;;) {
++		unsigned int reg;
++		int pin;
++
++		pin = entry->pin;
++		if (pin == -1)
++			break;
++		reg = io_apic_read(entry->apic, 0x10 + pin*2);
++		/* Is the remote IRR bit set? */
++		pending |= (reg >> 14) & 1;
++		if (!entry->next)
++			break;
++		entry = irq_2_pin + entry->next;
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	return pending;
++}
+ #endif
+ 
+ /*
+@@ -406,14 +432,12 @@ static void clear_IO_APIC (void)
+ int skip_ioapic_setup;
+ int ioapic_force;
+ 
+-/* dummy parsing: see setup.c */
+-
+-static int __init disable_ioapic_setup(char *str)
++static int __init parse_noapic(char *str)
+ {
+-	skip_ioapic_setup = 1;
++	disable_ioapic_setup();
+ 	return 0;
+ }
+-early_param("noapic", disable_ioapic_setup);
++early_param("noapic", parse_noapic);
+ 
+ /* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+ static int __init disable_timer_pin_setup(char *arg)
+@@ -765,12 +789,15 @@ static struct irq_chip ioapic_chip;
+ 
+ static void ioapic_register_intr(int irq, unsigned long trigger)
+ {
+-	if (trigger)
++	if (trigger) {
++		irq_desc[irq].status |= IRQ_LEVEL;
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					      handle_fasteoi_irq, "fasteoi");
+-	else
++	} else {
++		irq_desc[irq].status &= ~IRQ_LEVEL;
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					      handle_edge_irq, "edge");
++	}
+ }
+ #else
+ #define ioapic_register_intr(irq, trigger) evtchn_register_pirq(irq)
+@@ -1419,9 +1446,37 @@ static void ack_apic_level(unsigned int 
+ 	ack_APIC_irq();
+ 
+ 	/* Now we can move and renable the irq */
+-	move_masked_irq(irq);
+-	if (unlikely(do_unmask_irq))
++	if (unlikely(do_unmask_irq)) {
++		/* Only migrate the irq if the ack has been received.
++		 *
++		 * On rare occasions the broadcast level triggered ack gets
++		 * delayed going to ioapics, and if we reprogram the
++		 * vector while Remote IRR is still set the irq will never
++		 * fire again.
++		 *
++		 * To prevent this scenario we read the Remote IRR bit
++		 * of the ioapic.  This has two effects.
++		 * - On any sane system the read of the ioapic will
++		 *   flush writes (and acks) going to the ioapic from
++		 *   this cpu.
++		 * - We get to see if the ACK has actually been delivered.
++		 *
++		 * Based on failed experiments of reprogramming the
++		 * ioapic entry from outside of irq context starting
++		 * with masking the ioapic entry and then polling until
++		 * Remote IRR was clear before reprogramming the
++		 * ioapic I don't trust the Remote IRR bit to be
++		 * completey accurate.
++		 *
++		 * However there appears to be no other way to plug
++		 * this race, so if the Remote IRR bit is not
++		 * accurate and is causing problems then it is a hardware bug
++		 * and you can go talk to the chipset vendor about it.
++		 */
++		if (!io_apic_level_ack_pending(irq))
++			move_masked_irq(irq);
+ 		unmask_IO_APIC_irq(irq);
++	}
+ }
+ 
+ static struct irq_chip ioapic_chip __read_mostly = {
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -114,6 +114,8 @@ int init_new_context(struct task_struct 
+ 	memset(&mm->context, 0, sizeof(mm->context));
+ 	init_MUTEX(&mm->context.sem);
+ 	old_mm = current->mm;
++	if (old_mm)
++		mm->context.vdso = old_mm->context.vdso;
+ 	if (old_mm && old_mm->context.size > 0) {
+ 		down(&old_mm->context.sem);
+ 		retval = copy_ldt(&mm->context, &old_mm->context);
+@@ -146,7 +148,7 @@ void destroy_context(struct mm_struct *m
+ 			kfree(mm->context.ldt);
+ 		mm->context.size = 0;
+ 	}
+-	if (!mm->context.pinned) {
++	if (!PagePinned(virt_to_page(mm->pgd))) {
+ 		spin_lock(&mm_unpinned_lock);
+ 		list_del(&mm->context.unpinned);
+ 		spin_unlock(&mm_unpinned_lock);
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -32,7 +32,6 @@
+ 
+ /* Have we found an MP table */
+ int smp_found_config;
+-unsigned int __initdata maxcpus = NR_CPUS;
+ 
+ /*
+  * Various Linux-internal data structures created from the
+@@ -657,6 +656,20 @@ static int mp_find_ioapic(int gsi)
+ 	return -1;
+ }
+ 
++static u8 uniq_ioapic_id(u8 id)
++{
++	int i;
++	DECLARE_BITMAP(used, 256);
++	bitmap_zero(used, 256);
++	for (i = 0; i < nr_ioapics; i++) {
++		struct mpc_config_ioapic *ia = &mp_ioapics[i];
++		__set_bit(ia->mpc_apicid, used);
++	}
++	if (!test_bit(id, used))
++		return id;
++	return find_first_zero_bit(used, 256);
++}
++
+ void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
+ {
+ 	int idx = 0;
+@@ -664,7 +677,7 @@ void __init mp_register_ioapic(u8 id, u3
+ 	if (bad_ioapic(address))
+ 		return;
+ 
+-	idx = nr_ioapics++;
++	idx = nr_ioapics;
+ 
+ 	mp_ioapics[idx].mpc_type = MP_IOAPIC;
+ 	mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
+@@ -673,7 +686,7 @@ void __init mp_register_ioapic(u8 id, u3
+ #ifndef CONFIG_XEN
+ 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+ #endif
+-	mp_ioapics[idx].mpc_apicid = id;
++	mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
+ 	mp_ioapics[idx].mpc_apicver = 0;
+ 	
+ 	/* 
+@@ -690,6 +703,8 @@ void __init mp_register_ioapic(u8 id, u3
+ 		mp_ioapics[idx].mpc_apicaddr,
+ 		mp_ioapic_routing[idx].gsi_start,
+ 		mp_ioapic_routing[idx].gsi_end);
++
++	nr_ioapics++;
+ }
+ 
+ void __init
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -26,6 +26,7 @@
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
++#include <linux/fs.h>
+ #include <linux/elfcore.h>
+ #include <linux/smp.h>
+ #include <linux/slab.h>
+@@ -249,6 +250,7 @@ early_param("idle", idle_setup);
+ void __show_regs(struct pt_regs * regs)
+ {
+ 	unsigned long fs, gs, shadowgs;
++	unsigned long d0, d1, d2, d3, d6, d7;
+ 	unsigned int fsindex,gsindex;
+ 	unsigned int ds,cs,es; 
+ 
+@@ -288,6 +290,14 @@ void __show_regs(struct pt_regs * regs)
+ 	       fs,fsindex,gs,gsindex,shadowgs); 
+ 	printk("CS:  %04x DS: %04x ES: %04x\n", cs, ds, es); 
+ 
++	get_debugreg(d0, 0);
++	get_debugreg(d1, 1);
++	get_debugreg(d2, 2);
++	printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
++	get_debugreg(d3, 3);
++	get_debugreg(d6, 6);
++	get_debugreg(d7, 7);
++	printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+ }
+ 
+ void show_regs(struct pt_regs *regs)
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -828,6 +828,8 @@ static void __cpuinit init_amd(struct cp
+ 	level = cpuid_eax(1);
+ 	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+ 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
++	if (c->x86 == 0x10)
++		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ 
+ 	/* Enable workaround for FXSAVE leak */
+ 	if (c->x86 >= 6)
+@@ -853,8 +855,14 @@ static void __cpuinit init_amd(struct cp
+ 	if (c->extended_cpuid_level >= 0x80000008)
+ 		amd_detect_cmp(c);
+ 
+-	/* Fix cpuid4 emulation for more */
+-	num_cache_leaves = 3;
++	if (c->extended_cpuid_level >= 0x80000006 &&
++		(cpuid_edx(0x80000006) & 0xf000))
++		num_cache_leaves = 4;
++	else
++		num_cache_leaves = 3;
++
++	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
++		set_bit(X86_FEATURE_K8, &c->x86_capability);
+ 
+ 	/* RDTSC can be speculated around */
+ 	clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+@@ -1099,6 +1107,8 @@ void __cpuinit identify_cpu(struct cpuin
+ 			c->x86_capability[2] = cpuid_edx(0x80860001);
+ 	}
+ 
++	init_scattered_cpuid_features(c);
++
+ #ifndef CONFIG_XEN
+ 	c->apicid = phys_pkg_id(0);
+ #endif
+@@ -1186,7 +1196,7 @@ static int show_cpuinfo(struct seq_file 
+ 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+ 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+ 	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
++	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
+ 
+ 		/* AMD-defined */
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+@@ -1202,10 +1212,11 @@ static int show_cpuinfo(struct seq_file 
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* Other (Linux-defined) */
+-		"cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
+-		"constant_tsc", NULL, NULL,
+-		"up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
++		NULL, NULL, NULL, NULL,
++		"constant_tsc", "up", NULL, "arch_perfmon",
++		"pebs", "bts", NULL, "sync_rdtsc",
++		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* Intel-defined (#2) */
+@@ -1216,7 +1227,7 @@ static int show_cpuinfo(struct seq_file 
+ 
+ 		/* VIA/Cyrix/Centaur-defined */
+ 		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+@@ -1227,6 +1238,12 @@ static int show_cpuinfo(struct seq_file 
+ 		"osvw", "ibs", NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++		/* Auxiliary (Linux-defined) */
++		"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 	};
+ 	static char *x86_power_flags[] = { 
+ 		"ts",	/* temperature sensor */
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -125,11 +125,14 @@ void __init setup_per_cpu_areas(void)
+ } 
+ 
+ #ifdef CONFIG_XEN
+-static void switch_pt(void)
++static void __init_refok switch_pt(int cpu)
+ {
++	if (cpu == 0)
++		xen_init_pt();
+ 	xen_pt_switch(__pa_symbol(init_level4_pgt));
+ 	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
+ }
++#define switch_pt() switch_pt(cpu)
+ 
+ static void __cpuinit cpu_gdt_init(const struct desc_ptr *gdt_descr)
+ {
+@@ -185,9 +188,6 @@ void pda_init(int cpu)
+ 	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; 
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -362,7 +362,7 @@ __smp_call_function_single(int cpu, void
+ }
+ 
+ /*
+- * smp_call_function_single - Run a function on another CPU
++ * smp_call_function_single - Run a function on a specific CPU
+  * @func: The function to run. This must be fast and non-blocking.
+  * @info: An arbitrary pointer to pass to the function.
+  * @nonatomic: Currently unused.
+@@ -379,17 +379,21 @@ int smp_call_function_single (int cpu, v
+ {
+ 	/* prevent preemption and reschedule on another processor */
+ 	int me = get_cpu();
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
+ 	if (cpu == me) {
++		local_irq_disable();
++		func(info);
++		local_irq_enable();
+ 		put_cpu();
+ 		return 0;
+ 	}
+ 
+-	/* Can deadlock when called with interrupts disabled */
+-	WARN_ON(irqs_disabled());
+-
+-	spin_lock_bh(&call_lock);
++	spin_lock(&call_lock);
+ 	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+-	spin_unlock_bh(&call_lock);
++	spin_unlock(&call_lock);
+ 	put_cpu();
+ 	return 0;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -34,6 +34,10 @@
+ #include <linux/bug.h>
+ #include <linux/kdebug.h>
+ 
++#if defined(CONFIG_EDAC)
++#include <linux/edac.h>
++#endif
++
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+@@ -332,6 +336,7 @@ static int print_trace_stack(void *data,
+ 
+ static void print_trace_address(void *data, unsigned long addr)
+ {
++	touch_nmi_watchdog();
+ 	printk_address(addr);
+ }
+ 
+@@ -520,6 +525,7 @@ void __kprobes __die(const char * str, s
+ 	printk("\n");
+ 	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
+ 	show_registers(regs);
++	add_taint(TAINT_DIE);
+ 	/* Executive summary in case the oops scrolled away */
+ 	printk(KERN_ALERT "RIP ");
+ 	printk_address(regs->rip); 
+@@ -533,7 +539,7 @@ void die(const char * str, struct pt_reg
+ 	unsigned long flags = oops_begin();
+ 
+ 	if (!user_mode(regs))
+-		report_bug(regs->rip);
++		report_bug(regs->rip, regs);
+ 
+ 	__die(str, regs, err);
+ 	oops_end(flags);
+@@ -582,7 +588,8 @@ static void __kprobes do_trap(int trapnr
+ 		tsk->thread.error_code = error_code;
+ 		tsk->thread.trap_no = trapnr;
+ 
+-		if (exception_trace && unhandled_signal(tsk, signr))
++		if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
++		    printk_ratelimit())
+ 			printk(KERN_INFO
+ 			       "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
+ 			       tsk->comm, tsk->pid, str,
+@@ -686,7 +693,8 @@ asmlinkage void __kprobes do_general_pro
+ 		tsk->thread.error_code = error_code;
+ 		tsk->thread.trap_no = 13;
+ 
+-		if (exception_trace && unhandled_signal(tsk, SIGSEGV))
++		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++		    printk_ratelimit())
+ 			printk(KERN_INFO
+ 		       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
+ 			       tsk->comm, tsk->pid,
+@@ -721,6 +729,13 @@ mem_parity_error(unsigned char reason, s
+ 		reason);
+ 	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
+ 
++#if defined(CONFIG_EDAC)
++	if(edac_handler_set()) {
++		edac_atomic_assert_error();
++		return;
++	}
++#endif
++
+ 	if (panic_on_unrecovered_nmi)
+ 		panic("NMI: Not continuing");
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include <asm/segment.h>
+ #include <asm/desc.h>
+ #include <asm/topology.h>
++#include <asm/vgtod.h>
+ 
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+ #define __syscall_clobber "r11","rcx","memory"
+@@ -57,26 +58,9 @@
+  * - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
+  * Try to keep this structure as small as possible to avoid cache line ping pongs
+  */
+-struct vsyscall_gtod_data_t {
+-	seqlock_t	lock;
+-
+-	/* open coded 'struct timespec' */
+-	time_t		wall_time_sec;
+-	u32		wall_time_nsec;
+-
+-	int		sysctl_enabled;
+-	struct timezone sys_tz;
+-	struct { /* extract of a clocksource struct */
+-		cycle_t (*vread)(void);
+-		cycle_t	cycle_last;
+-		cycle_t	mask;
+-		u32	mult;
+-		u32	shift;
+-	} clock;
+-};
+ int __vgetcpu_mode __section_vgetcpu_mode;
+ 
+-struct vsyscall_gtod_data_t __vsyscall_gtod_data __section_vsyscall_gtod_data =
++struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data =
+ {
+ 	.lock = SEQLOCK_UNLOCKED,
+ 	.sysctl_enabled = 1,
+@@ -96,6 +80,8 @@ void update_vsyscall(struct timespec *wa
+ 	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+ 	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+ 	vsyscall_gtod_data.sys_tz = sys_tz;
++	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
++	vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;
+ 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -159,7 +159,9 @@ void dump_pagetable(unsigned long addres
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+ 
+-	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
++	pgd = (pgd_t *)read_cr3();
++
++	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
+ 	pgd += pgd_index(address);
+ 	if (bad_address(pgd)) goto bad;
+ 	printk("PGD %lx ", pgd_val(*pgd));
+@@ -219,16 +221,6 @@ static int is_errata93(struct pt_regs *r
+ 	return 0;
+ } 
+ 
+-int unhandled_signal(struct task_struct *tsk, int sig)
+-{
+-	if (is_init(tsk))
+-		return 1;
+-	if (tsk->ptrace & PT_PTRACED)
+-		return 0;
+-	return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
+-		(tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
+-}
+-
+ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
+ 				 unsigned long error_code)
+ {
+@@ -302,8 +294,8 @@ static int vmalloc_fault(unsigned long a
+ 	return 0;
+ }
+ 
+-int page_fault_trace = 0;
+-int exception_trace = 1;
++static int page_fault_trace;
++int show_unhandled_signals = 1;
+ 
+ 
+ #define MEM_VERBOSE 1
+@@ -372,7 +364,7 @@ asmlinkage void __kprobes do_page_fault(
+ 	struct vm_area_struct * vma;
+ 	unsigned long address;
+ 	const struct exception_table_entry *fixup;
+-	int write;
++	int write, fault;
+ 	unsigned long flags;
+ 	siginfo_t info;
+ 
+@@ -384,7 +376,7 @@ asmlinkage void __kprobes do_page_fault(
+ 	prefetchw(&mm->mmap_sem);
+ 
+ 	/* get the address */
+-	address = current_vcpu_info()->arch.cr2;
++	address = read_cr2();
+ 
+ 	info.si_code = SEGV_MAPERR;
+ 
+@@ -445,6 +437,13 @@ asmlinkage void __kprobes do_page_fault(
+ 	if (unlikely(in_atomic() || !mm))
+ 		goto bad_area_nosemaphore;
+ 
++	/*
++	 * User-mode registers count as a user access even for any
++	 * potential system fault or CPU buglet.
++	 */
++	if (user_mode_vm(regs))
++		error_code |= PF_USER;
++
+  again:
+ 	/* When running in the kernel we expect faults to occur only to
+ 	 * addresses in user space.  All other faults represent errors in the
+@@ -511,19 +510,18 @@ good_area:
+ 	 * make sure we exit gracefully rather than endlessly redo
+ 	 * the fault.
+ 	 */
+-	switch (handle_mm_fault(mm, vma, address, write)) {
+-	case VM_FAULT_MINOR:
+-		tsk->min_flt++;
+-		break;
+-	case VM_FAULT_MAJOR:
+-		tsk->maj_flt++;
+-		break;
+-	case VM_FAULT_SIGBUS:
+-		goto do_sigbus;
+-	default:
+-		goto out_of_memory;
++	fault = handle_mm_fault(mm, vma, address, write);
++	if (unlikely(fault & VM_FAULT_ERROR)) {
++		if (fault & VM_FAULT_OOM)
++			goto out_of_memory;
++		else if (fault & VM_FAULT_SIGBUS)
++			goto do_sigbus;
++		BUG();
+ 	}
+-
++	if (fault & VM_FAULT_MAJOR)
++		tsk->maj_flt++;
++	else
++		tsk->min_flt++;
+ 	up_read(&mm->mmap_sem);
+ 	return;
+ 
+@@ -556,7 +554,8 @@ bad_area_nosemaphore:
+ 		    (address >> 32))
+ 			return;
+ 
+-		if (exception_trace && unhandled_signal(tsk, SIGSEGV)) {
++		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++		    printk_ratelimit()) {
+ 			printk(
+ 		       "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
+ 					tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
+@@ -630,7 +629,7 @@ out_of_memory:
+ 	}
+ 	printk("VM: killing process %s\n", tsk->comm);
+ 	if (error_code & 4)
+-		do_exit(SIGKILL);
++		do_group_exit(SIGKILL);
+ 	goto no_context;
+ 
+ do_sigbus:
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -66,6 +66,9 @@ int after_bootmem;
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ extern unsigned long start_pfn;
+ 
++extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
++extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
++
+ /*
+  * Use this until direct mapping is established, i.e. before __va() is 
+  * available in init_memory_mapping().
+@@ -362,6 +365,10 @@ __set_fixmap (enum fixed_addresses idx, 
+ 		set_pte_phys(address, phys, prot, 0);
+ 		set_pte_phys(address, phys, prot, 1);
+ 		break;
++	case FIX_EARLYCON_MEM_BASE:
++		xen_l1_entry_update(level1_fixmap_pgt + pte_index(address),
++				    pfn_pte_ma(phys >> PAGE_SHIFT, prot));
++		break;
+ 	default:
+ 		set_pte_phys_ma(address, phys, prot);
+ 		break;
+@@ -595,6 +602,19 @@ void __init xen_init_pt(void)
+ 	__user_pgd(init_level4_pgt)[pgd_index(VSYSCALL_START)] =
+ 		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
+ 
++	/* Do an early initialization of the fixmap area. */
++	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
++	if (pud_present(level3_kernel_pgt[pud_index(addr)])) {
++		unsigned long adr = page[pud_index(addr)];
++
++		addr_to_page(adr, page);
++		memcpy(level2_fixmap_pgt, page, PAGE_SIZE);
++	}
++	level3_kernel_pgt[pud_index(addr)] =
++		__pud(__pa_symbol(level2_fixmap_pgt) | _PAGE_TABLE);
++	level2_fixmap_pgt[pmd_index(addr)] =
++		__pmd(__pa_symbol(level1_fixmap_pgt) | _PAGE_TABLE);
++
+ 	early_make_page_readonly(init_level4_pgt,
+ 				 XENFEAT_writable_page_tables);
+ 	early_make_page_readonly(__user_pgd(init_level4_pgt),
+@@ -603,6 +623,10 @@ void __init xen_init_pt(void)
+ 				 XENFEAT_writable_page_tables);
+ 	early_make_page_readonly(level3_user_pgt,
+ 				 XENFEAT_writable_page_tables);
++	early_make_page_readonly(level2_fixmap_pgt,
++				 XENFEAT_writable_page_tables);
++	early_make_page_readonly(level1_fixmap_pgt,
++				 XENFEAT_writable_page_tables);
+ 
+ 	if (!xen_feature(XENFEAT_writable_page_tables)) {
+ 		xen_pgd_pin(__pa_symbol(init_level4_pgt));
+@@ -832,7 +856,7 @@ void __init paging_init(void)
+ 	sparse_init();
+ 	free_area_init_nodes(max_zone_pfns);
+ 
+-	init_mm.context.pinned = 1;
++	SetPagePinned(virt_to_page(init_mm.pgd));
+ }
+ #endif
+ 
+@@ -1142,41 +1166,6 @@ int kern_addr_valid(unsigned long addr) 
+ 	return pfn_valid(pte_pfn(*pte));
+ }
+ 
+-#ifdef CONFIG_SYSCTL
+-#include <linux/sysctl.h>
+-
+-extern int exception_trace, page_fault_trace;
+-
+-static ctl_table debug_table2[] = {
+-	{
+-		.ctl_name	= 99,
+-		.procname	= "exception-trace",
+-		.data		= &exception_trace,
+-		.maxlen		= sizeof(int),
+-		.mode		= 0644,
+-		.proc_handler	= proc_dointvec
+-	},
+-	{}
+-}; 
+-
+-static ctl_table debug_root_table2[] = { 
+-	{
+-		.ctl_name = CTL_DEBUG,
+-		.procname = "debug",
+-		.mode = 0555,
+-		.child = debug_table2
+-	},
+-	{}
+-}; 
+-
+-static __init int x8664_sysctl_init(void)
+-{ 
+-	register_sysctl_table(debug_root_table2);
+-	return 0;
+-}
+-__initcall(x8664_sysctl_init);
+-#endif
+-
+ /* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
+    covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+    not need special handling anymore. */
+@@ -1215,9 +1204,18 @@ int in_gate_area_no_task(unsigned long a
+ }
+ 
+ #ifndef CONFIG_XEN
+-void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
++void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+ {
+ 	return __alloc_bootmem_core(pgdat->bdata, size,
+ 			SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+ }
+ #endif
++
++const char *arch_vma_name(struct vm_area_struct *vma)
++{
++	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
++		return "[vdso]";
++	if (vma == &gate_vma)
++		return "[vsyscall]";
++	return NULL;
++}
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:51:07.000000000 +0100
+@@ -171,7 +171,7 @@ void mm_pin(struct mm_struct *mm)
+ 	mm_walk(mm, PAGE_KERNEL_RO);
+ 	xen_pgd_pin(__pa(mm->pgd)); /* kernel */
+ 	xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
+-	mm->context.pinned = 1;
++	SetPagePinned(virt_to_page(mm->pgd));
+ 	spin_lock(&mm_unpinned_lock);
+ 	list_del(&mm->context.unpinned);
+ 	spin_unlock(&mm_unpinned_lock);
+@@ -189,7 +189,7 @@ void mm_unpin(struct mm_struct *mm)
+ 	xen_pgd_unpin(__pa(mm->pgd));
+ 	xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
+ 	mm_walk(mm, PAGE_KERNEL);
+-	mm->context.pinned = 0;
++	ClearPagePinned(virt_to_page(mm->pgd));
+ 	spin_lock(&mm_unpinned_lock);
+ 	list_add(&mm->context.unpinned, &mm_unpinned);
+ 	spin_unlock(&mm_unpinned_lock);
+@@ -217,7 +217,7 @@ void mm_pin_all(void)
+ 
+ void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+ {
+-	if (!mm->context.pinned)
++	if (!PagePinned(virt_to_page(mm->pgd)))
+ 		mm_pin(mm);
+ }
+ 
+@@ -243,8 +243,9 @@ void arch_exit_mmap(struct mm_struct *mm
+ 
+ 	task_unlock(tsk);
+ 
+-	if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+-	     !mm->context.has_foreign_mappings )
++	if (PagePinned(virt_to_page(mm->pgd))
++	    && (atomic_read(&mm->mm_count) == 1)
++	    && !mm->context.has_foreign_mappings)
+ 		mm_unpin(mm);
+ }
+ 
+@@ -343,14 +344,13 @@ static void flush_kernel_map(void *arg)
+ 	struct page *pg;
+ 
+ 	/* When clflush is available always use it because it is
+-	   much cheaper than WBINVD. Disable clflush for now because
+-	   the high level code is not ready yet */
++	   much cheaper than WBINVD. */
++	/* clflush is still broken. Disable for now. */
+ 	if (1 || !cpu_has_clflush)
+ 		asm volatile("wbinvd" ::: "memory");
+ 	else list_for_each_entry(pg, l, lru) {
+ 		void *adr = page_address(pg);
+-		if (cpu_has_clflush)
+-			cache_flush_page(adr);
++		cache_flush_page(adr);
+ 	}
+ 	__flush_tlb_all();
+ }
+@@ -364,7 +364,8 @@ static LIST_HEAD(deferred_pages); /* pro
+ 
+ static inline void save_page(struct page *fpage)
+ {
+-	list_add(&fpage->lru, &deferred_pages);
++	if (!test_and_set_bit(PG_arch_1, &fpage->flags))
++		list_add(&fpage->lru, &deferred_pages);
+ }
+ 
+ /* 
+@@ -398,9 +399,12 @@ __change_page_attr(unsigned long address
+ 	pte_t *kpte; 
+ 	struct page *kpte_page;
+ 	pgprot_t ref_prot2;
++
+ 	kpte = lookup_address(address);
+ 	if (!kpte) return 0;
+ 	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
++	BUG_ON(PageLRU(kpte_page));
++	BUG_ON(PageCompound(kpte_page));
+ 	if (pgprot_val(prot) != pgprot_val(ref_prot)) { 
+ 		if (!pte_huge(*kpte)) {
+ 			set_pte(kpte, pfn_pte(pfn, prot));
+@@ -439,10 +443,9 @@ __change_page_attr(unsigned long address
+ 		return 0;
+ #endif
+ 
+-	if (page_private(kpte_page) == 0) {
+-		save_page(kpte_page);
++	save_page(kpte_page);
++	if (page_private(kpte_page) == 0)
+ 		revert_page(address, ref_prot);
+-	}
+ 	return 0;
+ } 
+ 
+@@ -514,6 +517,10 @@ void global_flush_tlb(void)
+ 	flush_map(&l);
+ 
+ 	list_for_each_entry_safe(pg, next, &l, lru) {
++		list_del(&pg->lru);
++		clear_bit(PG_arch_1, &pg->flags);
++		if (page_private(pg) != 0)
++			continue;
+ 		ClearPagePrivate(pg);
+ 		__free_page(pg);
+ 	} 
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32/note.S	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32/note.S	2009-11-06 10:51:07.000000000 +0100
+@@ -13,7 +13,7 @@ ELFNOTE_START(Linux, 0, "a")
+ 	.long LINUX_VERSION_CODE
+ ELFNOTE_END
+ 
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_X86_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ /*
+  * Add a special note telling glibc's dynamic linker a fake hardware
+  * flavor that it will use to choose the search path for libraries in the
+@@ -37,8 +37,12 @@ ELFNOTE_END
+ 
+ ELFNOTE_START(GNU, 2, "a")
+ 	.long 1			/* ncaps */
++#ifdef CONFIG_PARAVIRT_XEN
+ VDSO32_NOTE_MASK:		/* Symbol used by arch/x86/xen/setup.c */
+ 	.long 0			/* mask */
++#else
++	.long 1 << VDSO_NOTE_NONEGSEG_BIT /* mask */
++#endif
+ 	.byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg"	/* bit, name */
+ ELFNOTE_END
+ #endif
+--- head-2010-01-18.orig/drivers/Makefile	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/Makefile	2009-11-06 10:51:07.000000000 +0100
+@@ -17,7 +17,7 @@ obj-$(CONFIG_SFI)		+= sfi/
+ obj-$(CONFIG_PNP)		+= pnp/
+ obj-$(CONFIG_ARM_AMBA)		+= amba/
+ 
+-obj-$(CONFIG_XEN)		+= xen/
++obj-$(CONFIG_PARAVIRT_XEN)	+= xen/
+ 
+ # regulators early, since some subsystems rely on them to initialize
+ obj-$(CONFIG_REGULATOR)		+= regulator/
+--- head-2010-01-18.orig/drivers/block/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/block/Kconfig	2009-11-06 10:51:07.000000000 +0100
+@@ -464,9 +464,9 @@ config XILINX_SYSACE
+ 	help
+ 	  Include support for the Xilinx SystemACE CompactFlash interface
+ 
+-config XEN_BLKDEV_FRONTEND
++config XEN_BLKFRONT
+ 	tristate "Xen virtual block device support"
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	default y
+ 	help
+ 	  This driver implements the front-end of the Xen virtual
+--- head-2010-01-18.orig/drivers/block/Makefile	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/block/Makefile	2009-11-06 10:51:07.000000000 +0100
+@@ -35,7 +35,7 @@ obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
+ obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
+ obj-$(CONFIG_BLK_DEV_HD)	+= hd.o
+ 
+-obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen-blkfront.o
++obj-$(CONFIG_XEN_BLKFRONT)	+= xen-blkfront.o
+ obj-$(CONFIG_CIPHER_TWOFISH)	+= loop_fish2.o
+ 
+ swim_mod-objs	:= swim.o swim_asm.o
+--- head-2010-01-18.orig/drivers/block/xen-blkfront.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/block/xen-blkfront.c	2009-11-06 10:51:07.000000000 +0100
+@@ -1056,7 +1056,6 @@ static struct xenbus_device_id blkfront_
+ 
+ static struct xenbus_driver blkfront = {
+ 	.name = "vbd",
+-	.owner = THIS_MODULE,
+ 	.ids = blkfront_ids,
+ 	.probe = blkfront_probe,
+ 	.remove = blkfront_remove,
+--- head-2010-01-18.orig/drivers/char/Kconfig	2009-12-04 10:44:40.000000000 +0100
++++ head-2010-01-18/drivers/char/Kconfig	2009-11-06 10:51:07.000000000 +0100
+@@ -659,7 +659,7 @@ config HVC_IUCV
+ 
+ config HVC_XEN
+ 	bool "Xen Hypervisor Console support"
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	select HVC_DRIVER
+ 	select HVC_IRQ
+ 	default y
+--- head-2010-01-18.orig/drivers/net/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/net/Kconfig	2009-11-06 10:51:07.000000000 +0100
+@@ -2784,9 +2784,9 @@ source "drivers/ieee802154/Kconfig"
+ 
+ source "drivers/s390/net/Kconfig"
+ 
+-config XEN_NETDEV_FRONTEND
++config XEN_NETFRONT
+ 	tristate "Xen network device frontend driver"
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	default y
+ 	help
+ 	  The network device frontend driver allows the kernel to
+--- head-2010-01-18.orig/drivers/net/Makefile	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/net/Makefile	2009-11-06 10:51:07.000000000 +0100
+@@ -162,7 +162,7 @@ obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2
+ obj-$(CONFIG_SLIP) += slip.o
+ obj-$(CONFIG_SLHC) += slhc.o
+ 
+-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
++obj-$(CONFIG_XEN_NETFRONT) += xen-netfront.o
+ 
+ obj-$(CONFIG_DUMMY) += dummy.o
+ obj-$(CONFIG_IFB) += ifb.o
+--- head-2010-01-18.orig/drivers/net/xen-netfront.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/net/xen-netfront.c	2009-11-06 10:51:07.000000000 +0100
+@@ -36,8 +36,6 @@
+ #include <linux/skbuff.h>
+ #include <linux/ethtool.h>
+ #include <linux/if_ether.h>
+-#include <linux/tcp.h>
+-#include <linux/udp.h>
+ #include <linux/moduleparam.h>
+ #include <linux/mm.h>
+ #include <net/ip.h>
+@@ -768,45 +766,6 @@ static RING_IDX xennet_fill_frags(struct
+ 	return cons;
+ }
+ 
+-static int skb_checksum_setup(struct sk_buff *skb)
+-{
+-	struct iphdr *iph;
+-	unsigned char *th;
+-	int err = -EPROTO;
+-
+-	if (skb->protocol != htons(ETH_P_IP))
+-		goto out;
+-
+-	iph = (void *)skb->data;
+-	th = skb->data + 4 * iph->ihl;
+-	if (th >= skb_tail_pointer(skb))
+-		goto out;
+-
+-	skb->csum_start = th - skb->head;
+-	switch (iph->protocol) {
+-	case IPPROTO_TCP:
+-		skb->csum_offset = offsetof(struct tcphdr, check);
+-		break;
+-	case IPPROTO_UDP:
+-		skb->csum_offset = offsetof(struct udphdr, check);
+-		break;
+-	default:
+-		if (net_ratelimit())
+-			printk(KERN_ERR "Attempting to checksum a non-"
+-			       "TCP/UDP packet, dropping a protocol"
+-			       " %d packet", iph->protocol);
+-		goto out;
+-	}
+-
+-	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+-		goto out;
+-
+-	err = 0;
+-
+-out:
+-	return err;
+-}
+-
+ static int handle_incoming_queue(struct net_device *dev,
+ 				 struct sk_buff_head *rxq)
+ {
+@@ -1793,7 +1752,6 @@ static int __devexit xennet_remove(struc
+ 
+ static struct xenbus_driver netfront_driver = {
+ 	.name = "vif",
+-	.owner = THIS_MODULE,
+ 	.ids = netfront_ids,
+ 	.probe = netfront_probe,
+ 	.remove = __devexit_p(xennet_remove),
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:13:35.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-18 12:16:29.000000000 +0100
+@@ -23,6 +23,9 @@ config XEN_PRIVILEGED_GUEST
+ config XEN_UNPRIVILEGED_GUEST
+ 	def_bool !XEN_PRIVILEGED_GUEST
+ 	select PM
++	select PM_SLEEP
++	select PM_SLEEP_SMP if SMP
++	select SUSPEND
+ 
+ config XEN_PRIVCMD
+ 	def_bool y
+--- head-2010-01-18.orig/drivers/xen/Makefile	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/Makefile	2009-11-06 10:51:07.000000000 +0100
+@@ -1,10 +1,12 @@
+-obj-y	+= core/
+-obj-y	+= console/
+-obj-y	+= evtchn/
+-obj-y	+= xenbus/
+-obj-y	+= char/
++obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o
+ 
+-obj-y	+= util.o
++obj-$(CONFIG_XEN)		+= core/
++obj-$(CONFIG_XEN)		+= console/
++obj-$(CONFIG_XEN)		+= evtchn/
++obj-y				+= xenbus/
++obj-$(CONFIG_XEN)		+= char/
++
++obj-$(CONFIG_XEN)		+= util.o
+ obj-$(CONFIG_XEN_BALLOON)		+= balloon/
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+ obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2009-11-06 10:51:07.000000000 +0100
+@@ -312,13 +312,9 @@ static int increase_reservation(unsigned
+ 
+ #ifndef MODULE
+ 	setup_per_zone_pages_min();
+-# if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+-     || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
+-	 /* build_all_zonelists() is __meminit */
+ 	if (need_zonelists_rebuild)
+ 		build_all_zonelists();
+ 	else
+-# endif
+ 		vm_total_pages = nr_free_pagecache_pages();
+ #endif
+ 
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 12:31:12.000000000 +0100
+@@ -156,7 +156,7 @@ static void unplug_queue(blkif_t *blkif)
+ 
+ static void plug_queue(blkif_t *blkif, struct block_device *bdev)
+ {
+-	request_queue_t *q = bdev_get_queue(bdev);
++	struct request_queue *q = bdev_get_queue(bdev);
+ 
+ 	if (q == blkif->plug)
+ 		return;
+--- head-2010-01-18.orig/drivers/xen/blkback/common.h	2010-01-04 12:22:14.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/common.h	2010-01-04 12:30:12.000000000 +0100
+@@ -81,7 +81,7 @@ typedef struct blkif_st {
+ 	wait_queue_head_t   wq;
+ 	struct task_struct  *xenblkd;
+ 	unsigned int        waiting_reqs;
+-	request_queue_t     *plug;
++	struct request_queue *plug;
+     int                 is_suspended_req;
+     blkif_request_t     suspended_req;
+ 
+--- head-2010-01-18.orig/drivers/xen/blkback/interface.c	2010-01-04 12:24:22.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/interface.c	2010-01-04 12:31:10.000000000 +0100
+@@ -181,5 +181,5 @@ void blkif_free(blkif_t *blkif)
+ void __init blkif_interface_init(void)
+ {
+ 	blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
+-					 0, 0, NULL, NULL);
++					 0, 0, NULL);
+ }
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:18:57.000000000 +0100
+@@ -671,7 +671,7 @@ static int blkif_queue_request(struct re
+  * do_blkif_request
+  *  read a block; request is in a request queue
+  */
+-void do_blkif_request(request_queue_t *rq)
++void do_blkif_request(struct request_queue *rq)
+ {
+ 	struct blkfront_info *info = NULL;
+ 	struct request *req;
+--- head-2010-01-18.orig/drivers/xen/blkfront/block.h	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/block.h	2010-01-18 16:18:59.000000000 +0100
+@@ -107,7 +107,7 @@ struct blkfront_info
+ 	struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ 	unsigned int irq;
+ 	struct xlbd_major_info *mi;
+-	request_queue_t *rq;
++	struct request_queue *rq;
+ 	struct work_struct work;
+ 	struct gnttab_free_callback callback;
+ 	struct blk_shadow shadow[BLK_RING_SIZE];
+@@ -131,7 +131,7 @@ extern int blkif_ioctl(struct inode *ino
+ extern int blkif_getgeo(struct block_device *, struct hd_geometry *);
+ extern int blkif_check(dev_t dev);
+ extern int blkif_revalidate(dev_t dev);
+-extern void do_blkif_request (request_queue_t *rq);
++extern void do_blkif_request (struct request_queue *rq);
+ 
+ /* Virtual block-device subsystem. */
+ /* Note that xlvbd_add doesn't call add_disk for you: you're expected
+--- head-2010-01-18.orig/drivers/xen/blkfront/vbd.c	2010-01-18 15:23:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 16:19:01.000000000 +0100
+@@ -298,7 +298,7 @@ xlbd_release_minors(struct xlbd_major_in
+ static int
+ xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
+ {
+-	request_queue_t *rq;
++	struct request_queue *rq;
+ 
+ 	rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
+ 	if (rq == NULL)
+--- head-2010-01-18.orig/drivers/xen/blktap/common.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/common.h	2009-11-06 10:51:07.000000000 +0100
+@@ -68,7 +68,7 @@ typedef struct blkif_st {
+ 	wait_queue_head_t   wq;
+ 	struct task_struct  *xenblkd;
+ 	unsigned int        waiting_reqs;
+-	request_queue_t     *plug;
++	struct request_queue *plug;
+ 
+ 	/* statistics */
+ 	unsigned long       st_print;
+--- head-2010-01-18.orig/drivers/xen/blktap/interface.c	2010-01-04 12:24:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/interface.c	2010-01-04 12:31:01.000000000 +0100
+@@ -181,5 +181,5 @@ void tap_blkif_kmem_cache_free(blkif_t *
+ void __init tap_blkif_interface_init(void)
+ {
+ 	blkif_cachep = kmem_cache_create("blktapif_cache", sizeof(blkif_t), 
+-					 0, 0, NULL, NULL);
++					 0, 0, NULL);
+ }
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2010-01-04 12:30:58.000000000 +0100
+@@ -836,7 +836,7 @@ static void
+ blktap_device_run_queue(struct blktap *tap)
+ {
+ 	int queued, err;
+-	request_queue_t *rq;
++	struct request_queue *rq;
+ 	struct request *req;
+ 	struct blktap_ring *ring;
+ 	struct blktap_device *dev;
+@@ -913,7 +913,7 @@ blktap_device_run_queue(struct blktap *t
+  * dev->lock held on entry
+  */
+ static void
+-blktap_device_do_request(request_queue_t *rq)
++blktap_device_do_request(struct request_queue *rq)
+ {
+ 	struct request *req;
+ 	struct blktap *tap;
+@@ -1187,6 +1187,5 @@ void
+ blktap_device_free(void)
+ {
+ 	if (blktap_device_major)
+-		if (unregister_blkdev(blktap_device_major, "tapdev"))
+-			BTERR("blktap device unregister failed\n");
++		unregister_blkdev(blktap_device_major, "tapdev");
+ }
+--- head-2010-01-18.orig/drivers/xen/blktap2/sysfs.c	2009-12-09 15:32:16.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/sysfs.c	2009-12-09 15:58:48.000000000 +0100
+@@ -334,6 +334,22 @@ blktap_sysfs_create(struct blktap *tap)
+ 	return err;
+ }
+ 
++static void
++_blktap_sysfs_destroy(struct device *_dev)
++{
++	struct class_device *dev = _dev->???;
++	struct blktap *tap = dev->class_data;
++
++	class_device_remove_file(dev, &class_device_attr_name);
++	class_device_remove_file(dev, &class_device_attr_remove);
++	class_device_remove_file(dev, &class_device_attr_pause);
++	class_device_remove_file(dev, &class_device_attr_resume);
++	class_device_remove_file(dev, &class_device_attr_debug);
++	class_device_unregister(dev);
++
++	clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
++}
++
+ int
+ blktap_sysfs_destroy(struct blktap *tap)
+ {
+@@ -350,17 +366,7 @@ blktap_sysfs_destroy(struct blktap *tap)
+ 				     !atomic_read(&tap->ring.sysfs_refcnt)))
+ 		return -EAGAIN;
+ 
+-	/* XXX: is it safe to remove the class from a sysfs attribute? */
+-	class_device_remove_file(dev, &class_device_attr_name);
+-	class_device_remove_file(dev, &class_device_attr_remove);
+-	class_device_remove_file(dev, &class_device_attr_pause);
+-	class_device_remove_file(dev, &class_device_attr_resume);
+-	class_device_remove_file(dev, &class_device_attr_debug);
+-	class_device_destroy(class, ring->devno);
+-
+-	clear_bit(BLKTAP_SYSFS, &tap->dev_inuse);
+-
+-	return 0;
++	return device_schedule_callback(dev->???, _blktap_sysfs_destroy);
+ }
+ 
+ static ssize_t
+--- head-2010-01-18.orig/drivers/xen/core/features.c	2007-06-12 13:13:44.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/features.c	2009-11-06 10:51:07.000000000 +0100
+@@ -19,7 +19,7 @@ u8 xen_features[XENFEAT_NR_SUBMAPS * 32]
+ /* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */
+ EXPORT_SYMBOL(xen_features);
+ 
+-void setup_xen_features(void)
++void xen_setup_features(void)
+ {
+ 	xen_feature_info_t fi;
+ 	int i, j;
+--- head-2010-01-18.orig/drivers/xen/core/reboot.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/reboot.c	2009-11-06 10:51:07.000000000 +0100
+@@ -4,6 +4,7 @@
+ #include <linux/unistd.h>
+ #include <linux/module.h>
+ #include <linux/reboot.h>
++#include <linux/sched.h>
+ #include <linux/sysrq.h>
+ #include <asm/hypervisor.h>
+ #include <xen/xenbus.h>
+--- head-2010-01-18.orig/drivers/xen/scsiback/interface.c	2010-01-04 12:24:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/interface.c	2010-01-04 12:30:46.000000000 +0100
+@@ -171,7 +171,7 @@ void scsiback_free(struct vscsibk_info *
+ int __init scsiback_interface_init(void)
+ {
+ 	scsiback_cachep = kmem_cache_create("vscsiif_cache",
+-		sizeof(struct vscsibk_info), 0, 0, NULL, NULL);
++		sizeof(struct vscsibk_info), 0, 0, NULL);
+ 	if (!scsiback_cachep) {
+ 		printk(KERN_ERR "scsiback: can't init scsi cache\n");
+ 		return -ENOMEM;
+--- head-2010-01-18.orig/drivers/xen/scsifront/scsifront.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:07.000000000 +0100
+@@ -147,7 +147,7 @@ static void scsifront_cdb_cmd_done(struc
+ 	add_id_to_freelist(info, id);
+ 
+ 	sc->result = ring_res->rslt;
+-	sc->resid  = ring_res->residual_len;
++	scsi_set_resid(sc, ring_res->residual_len);
+ 
+ 	if (ring_res->sense_len > VSCSIIF_SENSE_BUFFERSIZE)
+ 		sense_len = VSCSIIF_SENSE_BUFFERSIZE;
+--- head-2010-01-18.orig/drivers/xen/tpmback/interface.c	2010-01-04 12:26:29.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/interface.c	2010-01-04 12:30:04.000000000 +0100
+@@ -13,6 +13,7 @@
+ 
+ #include "common.h"
+ #include <linux/delay.h>
++#include <linux/err.h>
+ #include <xen/balloon.h>
+ #include <xen/gnttab.h>
+ 
+@@ -163,7 +164,7 @@ void tpmif_disconnect_complete(tpmif_t *
+ int __init tpmif_interface_init(void)
+ {
+ 	tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
+-					 0, 0, NULL, NULL);
++					 0, 0, NULL);
+ 	return tpmif_cachep ? 0 : -ENOMEM;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/usbfront/xenbus.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/xenbus.c	2009-11-06 10:51:07.000000000 +0100
+@@ -388,7 +388,7 @@ static int __init usbfront_init(void)
+ 		return -ENODEV;
+ 
+ 	xenhcd_urbp_cachep = kmem_cache_create("xenhcd_urb_priv",
+-			sizeof(struct urb_priv), 0, 0, NULL, NULL);
++			sizeof(struct urb_priv), 0, 0, NULL);
+ 	if (!xenhcd_urbp_cachep) {
+ 		printk(KERN_ERR "usbfront failed to create kmem cache\n");
+ 		return -ENOMEM;
+--- head-2010-01-18.orig/drivers/xen/util.c	2007-07-10 09:42:30.000000000 +0200
++++ head-2010-01-18/drivers/xen/util.c	2009-11-06 10:51:07.000000000 +0100
+@@ -1,8 +1,5 @@
+-#include <linux/mm.h>
++#include <linux/err.h>
+ #include <linux/module.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <asm/uaccess.h>
+ #include <xen/driver_util.h>
+ 
+ struct class *get_xen_class(void)
+@@ -21,45 +18,3 @@ struct class *get_xen_class(void)
+ 	return xen_class;
+ }
+ EXPORT_SYMBOL_GPL(get_xen_class);
+-
+-#ifdef CONFIG_X86
+-static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+-{
+-	/* apply_to_page_range() does all the hard work. */
+-	return 0;
+-}
+-
+-struct vm_struct *alloc_vm_area(unsigned long size)
+-{
+-	struct vm_struct *area;
+-
+-	area = get_vm_area(size, VM_IOREMAP);
+-	if (area == NULL)
+-		return NULL;
+-
+-	/*
+-	 * This ensures that page tables are constructed for this region
+-	 * of kernel virtual address space and mapped into init_mm.
+-	 */
+-	if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
+-				area->size, f, NULL)) {
+-		free_vm_area(area);
+-		return NULL;
+-	}
+-
+-	/* Map page directories into every address space. */
+-	vmalloc_sync_all();
+-
+-	return area;
+-}
+-EXPORT_SYMBOL_GPL(alloc_vm_area);
+-
+-void free_vm_area(struct vm_struct *area)
+-{
+-	struct vm_struct *ret;
+-	ret = remove_vm_area(area->addr);
+-	BUG_ON(ret != area);
+-	kfree(area);
+-}
+-EXPORT_SYMBOL_GPL(free_vm_area);
+-#endif /* CONFIG_X86 */
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_client.c	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_client.c	2009-11-06 10:51:07.000000000 +0100
+@@ -30,19 +30,26 @@
+  * IN THE SOFTWARE.
+  */
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ #include <linux/slab.h>
+ #include <xen/evtchn.h>
+ #include <xen/gnttab.h>
+-#include <xen/xenbus.h>
+ #include <xen/driver_util.h>
++#else
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++#include <asm/xen/hypervisor.h>
++#include <xen/interface/xen.h>
++#include <xen/interface/event_channel.h>
++#include <xen/events.h>
++#include <xen/grant_table.h>
++#endif
++#include <xen/xenbus.h>
+ 
+ #ifdef HAVE_XEN_PLATFORM_COMPAT_H
+ #include <xen/platform-compat.h>
+ #endif
+ 
+-#define DPRINTK(fmt, args...) \
+-    pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
+-
+ const char *xenbus_strstate(enum xenbus_state state)
+ {
+ 	static const char *const name[] = {
+@@ -60,6 +67,20 @@ const char *xenbus_strstate(enum xenbus_
+ }
+ EXPORT_SYMBOL_GPL(xenbus_strstate);
+ 
++/**
++ * xenbus_watch_path - register a watch
++ * @dev: xenbus device
++ * @path: path to watch
++ * @watch: watch to register
++ * @callback: callback to register
++ *
++ * Register a @watch on the given path, using the given xenbus_watch structure
++ * for storage, and the given @callback function as the callback.  Return 0 on
++ * success, or -errno on error.  On success, the given @path will be saved as
++ * @watch->node, and remains the caller's to free.  On error, @watch->node will
++ * be NULL, the device will switch to %XenbusStateClosing, and the error will
++ * be saved in the store.
++ */
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+ 		      struct xenbus_watch *watch,
+ 		      void (*callback)(struct xenbus_watch *,
+@@ -83,6 +104,7 @@ int xenbus_watch_path(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_watch_path);
+ 
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+ 		       const char *path2, struct xenbus_watch *watch,
+ 		       void (*callback)(struct xenbus_watch *,
+@@ -101,8 +123,60 @@ int xenbus_watch_path2(struct xenbus_dev
+ 	return err;
+ }
+ EXPORT_SYMBOL_GPL(xenbus_watch_path2);
++#else
++/**
++ * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path
++ * @dev: xenbus device
++ * @watch: watch to register
++ * @callback: callback to register
++ * @pathfmt: format of path to watch
++ *
++ * Register a watch on the given @path, using the given xenbus_watch
++ * structure for storage, and the given @callback function as the callback.
++ * Return 0 on success, or -errno on error.  On success, the watched path
++ * (@path/@path2) will be saved as @watch->node, and becomes the caller's to
++ * kfree().  On error, watch->node will be NULL, so the caller has nothing to
++ * free, the device will switch to %XenbusStateClosing, and the error will be
++ * saved in the store.
++ */
++int xenbus_watch_pathfmt(struct xenbus_device *dev,
++			 struct xenbus_watch *watch,
++			 void (*callback)(struct xenbus_watch *,
++					const char **, unsigned int),
++			 const char *pathfmt, ...)
++{
++	int err;
++	va_list ap;
++	char *path;
+ 
++	va_start(ap, pathfmt);
++	path = kvasprintf(GFP_KERNEL, pathfmt, ap);
++	va_end(ap);
+ 
++	if (!path) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
++		return -ENOMEM;
++	}
++	err = xenbus_watch_path(dev, path, watch, callback);
++
++	if (err)
++		kfree(path);
++	return err;
++}
++EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
++#endif
++
++
++/**
++ * xenbus_switch_state
++ * @dev: xenbus device
++ * @xbt: transaction handle
++ * @state: new state
++ *
++ * Advertise in the store a change of the given driver to the given new_state.
++ * Return 0 on success, or -errno on error.  On error, the device will switch
++ * to XenbusStateClosing, and the error will be saved in the store.
++ */
+ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
+ {
+ 	/* We check whether the state is currently set to the given value, and
+@@ -161,8 +235,8 @@ static char *error_path(struct xenbus_de
+ }
+ 
+ 
+-void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
+-		va_list ap)
++static void _dev_error(struct xenbus_device *dev, int err,
++			const char *fmt, va_list ap)
+ {
+ 	int ret;
+ 	unsigned int len;
+@@ -183,14 +257,16 @@ void _dev_error(struct xenbus_device *de
+ 	path_buffer = error_path(dev);
+ 
+ 	if (path_buffer == NULL) {
+-		printk("xenbus: failed to write error node for %s (%s)\n",
+-		       dev->nodename, printf_buffer);
++		dev_err(&dev->dev,
++		        "xenbus: failed to write error node for %s (%s)\n",
++		        dev->nodename, printf_buffer);
+ 		goto fail;
+ 	}
+ 
+ 	if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
+-		printk("xenbus: failed to write error node for %s (%s)\n",
+-		       dev->nodename, printf_buffer);
++		dev_err(&dev->dev,
++		        "xenbus: failed to write error node for %s (%s)\n",
++		        dev->nodename, printf_buffer);
+ 		goto fail;
+ 	}
+ 
+@@ -200,6 +276,15 @@ fail:
+ }
+ 
+ 
++/**
++ * xenbus_dev_error
++ * @dev: xenbus device
++ * @err: error to report
++ * @fmt: error message format
++ *
++ * Report the given negative errno into the store, along with the given
++ * formatted message.
++ */
+ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
+ 		      ...)
+ {
+@@ -212,6 +297,16 @@ void xenbus_dev_error(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_dev_error);
+ 
+ 
++/**
++ * xenbus_dev_fatal
++ * @dev: xenbus device
++ * @err: error to report
++ * @fmt: error message format
++ *
++ * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
++ * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
++ * closedown of this driver and its peer.
++ */
+ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+ 		      ...)
+ {
+@@ -226,6 +321,15 @@ void xenbus_dev_fatal(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
+ 
+ 
++/**
++ * xenbus_grant_ring
++ * @dev: xenbus device
++ * @ring_mfn: mfn of ring to grant
++ *
++ * Grant access to the given @ring_mfn to the peer of the given device.  Return
++ * 0 on success, or -errno on error.  On error, the device will switch to
++ * XenbusStateClosing, and the error will be saved in the store.
++ */
+ int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
+ {
+ 	int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
+@@ -236,6 +340,12 @@ int xenbus_grant_ring(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_grant_ring);
+ 
+ 
++/**
++ * Allocate an event channel for the given xenbus_device, assigning the newly
++ * created local port to *port.  Return 0 on success, or -errno on error.  On
++ * error, the device will switch to XenbusStateClosing, and the error will be
++ * saved in the store.
++ */
+ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
+ {
+ 	struct evtchn_alloc_unbound alloc_unbound;
+@@ -256,6 +366,38 @@ int xenbus_alloc_evtchn(struct xenbus_de
+ EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
+ 
+ 
++#if 0 /* !defined(CONFIG_XEN) && !defined(MODULE) */
++/**
++ * Bind to an existing interdomain event channel in another domain. Returns 0
++ * on success and stores the local port in *port. On error, returns -errno,
++ * switches the device to XenbusStateClosing, and saves the error in XenStore.
++ */
++int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
++{
++	struct evtchn_bind_interdomain bind_interdomain;
++	int err;
++
++	bind_interdomain.remote_dom = dev->otherend_id;
++	bind_interdomain.remote_port = remote_port;
++
++	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
++					  &bind_interdomain);
++	if (err)
++		xenbus_dev_fatal(dev, err,
++				 "binding to event channel %d from domain %d",
++				 remote_port, dev->otherend_id);
++	else
++		*port = bind_interdomain.local_port;
++
++	return err;
++}
++EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
++#endif
++
++
++/**
++ * Free an existing event channel. Returns 0 on success or -errno on error.
++ */
+ int xenbus_free_evtchn(struct xenbus_device *dev, int port)
+ {
+ 	struct evtchn_close close;
+@@ -272,6 +414,191 @@ int xenbus_free_evtchn(struct xenbus_dev
+ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
+ 
+ 
++#if 0 /* !defined(CONFIG_XEN) && !defined(MODULE) */
++/**
++ * xenbus_map_ring_valloc
++ * @dev: xenbus device
++ * @gnt_ref: grant reference
++ * @vaddr: pointer to address to be filled out by mapping
++ *
++ * Based on Rusty Russell's skeleton driver's map_page.
++ * Map a page of memory into this domain from another domain's grant table.
++ * xenbus_map_ring_valloc allocates a page of virtual address space, maps the
++ * page to that address, and sets *vaddr to that address.
++ * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
++ * or -ENOMEM on error. If an error is returned, device will switch to
++ * XenbusStateClosing and the error message will be saved in XenStore.
++ */
++int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
++{
++	struct gnttab_map_grant_ref op = {
++		.flags = GNTMAP_host_map,
++		.ref   = gnt_ref,
++		.dom   = dev->otherend_id,
++	};
++	struct vm_struct *area;
++
++	*vaddr = NULL;
++
++	area = alloc_vm_area(PAGE_SIZE);
++	if (!area)
++		return -ENOMEM;
++
++	op.host_addr = (unsigned long)area->addr;
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status != GNTST_okay) {
++		free_vm_area(area);
++		xenbus_dev_fatal(dev, op.status,
++				 "mapping in shared page %d from domain %d",
++				 gnt_ref, dev->otherend_id);
++		return op.status;
++	}
++
++	/* Stuff the handle in an unused field */
++	area->phys_addr = (unsigned long)op.handle;
++
++	*vaddr = area->addr;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
++
++
++/**
++ * xenbus_map_ring
++ * @dev: xenbus device
++ * @gnt_ref: grant reference
++ * @handle: pointer to grant handle to be filled
++ * @vaddr: address to be mapped to
++ *
++ * Map a page of memory into this domain from another domain's grant table.
++ * xenbus_map_ring does not allocate the virtual address space (you must do
++ * this yourself!). It only maps in the page to the specified address.
++ * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
++ * or -ENOMEM on error. If an error is returned, device will switch to
++ * XenbusStateClosing and the error message will be saved in XenStore.
++ */
++int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
++		    grant_handle_t *handle, void *vaddr)
++{
++	struct gnttab_map_grant_ref op = {
++		.host_addr = (unsigned long)vaddr,
++		.flags     = GNTMAP_host_map,
++		.ref       = gnt_ref,
++		.dom       = dev->otherend_id,
++	};
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status != GNTST_okay) {
++		xenbus_dev_fatal(dev, op.status,
++				 "mapping in shared page %d from domain %d",
++				 gnt_ref, dev->otherend_id);
++	} else
++		*handle = op.handle;
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_map_ring);
++
++
++/**
++ * xenbus_unmap_ring_vfree
++ * @dev: xenbus device
++ * @vaddr: addr to unmap
++ *
++ * Based on Rusty Russell's skeleton driver's unmap_page.
++ * Unmap a page of memory in this domain that was imported from another domain.
++ * Use xenbus_unmap_ring_vfree if you mapped in your memory with
++ * xenbus_map_ring_valloc (it will free the virtual address space).
++ * Returns 0 on success and returns GNTST_* on error
++ * (see xen/include/interface/grant_table.h).
++ */
++int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
++{
++	struct vm_struct *area;
++	struct gnttab_unmap_grant_ref op = {
++		.host_addr = (unsigned long)vaddr,
++	};
++
++	/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
++	 * method so that we don't have to muck with vmalloc internals here.
++	 * We could force the user to hang on to their struct vm_struct from
++	 * xenbus_map_ring_valloc, but these 6 lines considerably simplify
++	 * this API.
++	 */
++	read_lock(&vmlist_lock);
++	for (area = vmlist; area != NULL; area = area->next) {
++		if (area->addr == vaddr)
++			break;
++	}
++	read_unlock(&vmlist_lock);
++
++	if (!area) {
++		xenbus_dev_error(dev, -ENOENT,
++				 "can't find mapped virtual address %p", vaddr);
++		return GNTST_bad_virt_addr;
++	}
++
++	op.handle = (grant_handle_t)area->phys_addr;
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status == GNTST_okay)
++		free_vm_area(area);
++	else
++		xenbus_dev_error(dev, op.status,
++				 "unmapping page at handle %d error %d",
++				 (int16_t)area->phys_addr, op.status);
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
++
++
++/**
++ * xenbus_unmap_ring
++ * @dev: xenbus device
++ * @handle: grant handle
++ * @vaddr: addr to unmap
++ *
++ * Unmap a page of memory in this domain that was imported from another domain.
++ * Returns 0 on success and returns GNTST_* on error
++ * (see xen/include/interface/grant_table.h).
++ */
++int xenbus_unmap_ring(struct xenbus_device *dev,
++		      grant_handle_t handle, void *vaddr)
++{
++	struct gnttab_unmap_grant_ref op = {
++		.host_addr = (unsigned long)vaddr,
++		.handle    = handle,
++	};
++
++	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
++		BUG();
++
++	if (op.status != GNTST_okay)
++		xenbus_dev_error(dev, op.status,
++				 "unmapping page at handle %d error %d",
++				 handle, op.status);
++
++	return op.status;
++}
++EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
++#endif
++
++
++/**
++ * xenbus_read_driver_state
++ * @path: path for driver
++ *
++ * Return the state of the driver rooted at the given store path, or
++ * XenbusStateUnknown if no state can be read.
++ */
+ enum xenbus_state xenbus_read_driver_state(const char *path)
+ {
+ 	enum xenbus_state result;
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_comms.c	2009-11-06 10:51:07.000000000 +0100
+@@ -34,12 +34,15 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ #include <linux/err.h>
+-#include <linux/ptrace.h>
+-#include <linux/workqueue.h>
+-#include <xen/evtchn.h>
+ #include <xen/xenbus.h>
+-
++#if defined(CONFIG_XEN) || defined(MODULE)
++#include <xen/evtchn.h>
+ #include <asm/hypervisor.h>
++#else
++#include <asm/xen/hypervisor.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#endif
+ 
+ #include "xenbus_comms.h"
+ 
+@@ -112,6 +115,13 @@ static const void *get_input_chunk(XENST
+ 	return buf + MASK_XENSTORE_IDX(cons);
+ }
+ 
++/**
++ * xb_write - low level write
++ * @data: buffer to send
++ * @len: length of buffer
++ *
++ * Returns 0 on success, error otherwise.
++ */
+ int xb_write(const void *data, unsigned len)
+ {
+ 	struct xenstore_domain_interface *intf = xen_store_interface;
+@@ -220,7 +230,9 @@ int xb_read(void *data, unsigned len)
+ 	return 0;
+ }
+ 
+-/* Set up interrupt handler off store event channel. */
++/**
++ * xb_init_comms - Set up interrupt handler off store event channel.
++ */
+ int xb_init_comms(void)
+ {
+ 	struct xenstore_domain_interface *intf = xen_store_interface;
+@@ -240,7 +252,11 @@ int xb_init_comms(void)
+ 	if (xenbus_irq)
+ 		unbind_from_irqhandler(xenbus_irq, &xb_waitq);
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	err = bind_caller_port_to_irqhandler(
++#else
++	err = bind_evtchn_to_irqhandler(
++#endif
+ 		xen_store_evtchn, wake_waiting,
+ 		0, "xenbus", &xb_waitq);
+ 	if (err <= 0) {
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 10:52:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:00:10.000000000 +0100
+@@ -43,21 +43,26 @@
+ #include <linux/mm.h>
+ #include <linux/notifier.h>
+ #include <linux/mutex.h>
+-#include <linux/module.h>
+-#include <xen/gnttab.h>
++#include <linux/io.h>
+ 
+-#include <asm/io.h>
+ #include <asm/page.h>
+-#include <asm/maddr.h>
+ #include <asm/pgtable.h>
++#if defined(CONFIG_XEN) || defined(MODULE)
+ #include <asm/hypervisor.h>
+ #include <xen/xenbus.h>
+ #include <xen/xen_proc.h>
+ #include <xen/evtchn.h>
+ #include <xen/features.h>
++#include <xen/gnttab.h>
+ #ifdef MODULE
+ #include <xen/hvm.h>
+ #endif
++#else
++#include <asm/xen/hypervisor.h>
++#include <xen/xenbus.h>
++#include <xen/events.h>
++#include <xen/page.h>
++#endif
+ 
+ #include "xenbus_comms.h"
+ #include "xenbus_probe.h"
+@@ -169,7 +174,7 @@ static int read_backend_details(struct x
+ 	return read_otherend_details(xendev, "backend-id", "backend");
+ }
+ 
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) && (defined(CONFIG_XEN) || defined(MODULE))
+ static int xenbus_uevent_frontend(struct device *dev, char **envp,
+ 				  int num_envp, char *buffer, int buffer_size)
+ {
+@@ -208,12 +213,16 @@ static struct xen_bus_type xenbus_fronte
+ 		.probe    = xenbus_dev_probe,
+ 		.remove   = xenbus_dev_remove,
+ 		.shutdown = xenbus_dev_shutdown,
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 		.uevent   = xenbus_uevent_frontend,
+ #endif
++#endif
+ 	},
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	.dev = {
+ 		.bus_id = "xen",
+ 	},
++#endif
+ };
+ 
+ static void otherend_changed(struct xenbus_watch *watch,
+@@ -229,14 +238,15 @@ static void otherend_changed(struct xenb
+ 	if (!dev->otherend ||
+ 	    strncmp(dev->otherend, vec[XS_WATCH_PATH],
+ 		    strlen(dev->otherend))) {
+-		DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
++		dev_dbg(&dev->dev, "Ignoring watch at %s", vec[XS_WATCH_PATH]);
+ 		return;
+ 	}
+ 
+ 	state = xenbus_read_driver_state(dev->otherend);
+ 
+-	DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state),
+-		dev->otherend_watch.node, vec[XS_WATCH_PATH]);
++	dev_dbg(&dev->dev, "state is %d (%s), %s, %s",
++		state, xenbus_strstate(state), dev->otherend_watch.node,
++		vec[XS_WATCH_PATH]);
+ 
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ 	/*
+@@ -272,8 +282,13 @@ static int talk_to_otherend(struct xenbu
+ 
+ static int watch_otherend(struct xenbus_device *dev)
+ {
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	return xenbus_watch_path2(dev, dev->otherend, "state",
+ 				  &dev->otherend_watch, otherend_changed);
++#else
++	return xenbus_watch_pathfmt(dev, &dev->otherend_watch, otherend_changed,
++				    "%s/%s", dev->otherend, "state");
++#endif
+ }
+ 
+ 
+@@ -299,9 +314,9 @@ int xenbus_dev_probe(struct device *_dev
+ 
+ 	err = talk_to_otherend(dev);
+ 	if (err) {
+-		printk(KERN_WARNING
+-		       "xenbus_probe: talk_to_otherend on %s failed.\n",
+-		       dev->nodename);
++		dev_warn(&dev->dev,
++		         "xenbus_probe: talk_to_otherend on %s failed.\n",
++		         dev->nodename);
+ 		return err;
+ 	}
+ 
+@@ -311,9 +326,9 @@ int xenbus_dev_probe(struct device *_dev
+ 
+ 	err = watch_otherend(dev);
+ 	if (err) {
+-		printk(KERN_WARNING
+-		       "xenbus_probe: watch_otherend on %s failed.\n",
+-		       dev->nodename);
++		dev_warn(&dev->dev,
++		         "xenbus_probe: watch_otherend on %s failed.\n",
++		         dev->nodename);
+ 		return err;
+ 	}
+ 
+@@ -358,8 +373,8 @@ static void xenbus_dev_shutdown(struct d
+ 
+ 	get_device(&dev->dev);
+ 	if (dev->state != XenbusStateConnected) {
+-		printk("%s: %s: %s != Connected, skipping\n", __FUNCTION__,
+-		       dev->nodename, xenbus_strstate(dev->state));
++		dev_info(&dev->dev, "%s: %s: %s != Connected, skipping\n", __FUNCTION__,
++		         dev->nodename, xenbus_strstate(dev->state));
+ 		goto out;
+ 	}
+ 	xenbus_switch_state(dev, XenbusStateClosing);
+@@ -369,7 +384,8 @@ static void xenbus_dev_shutdown(struct d
+ 
+ 	timeout = wait_for_completion_timeout(&dev->down, timeout);
+ 	if (!timeout)
+-		printk("%s: %s timeout closing device\n", __FUNCTION__, dev->nodename);
++		dev_info(&dev->dev, "%s: %s timeout closing device\n",
++		         __FUNCTION__, dev->nodename);
+  out:
+ 	put_device(&dev->dev);
+ }
+@@ -557,7 +573,9 @@ int xenbus_probe_node(struct xen_bus_typ
+ 	xendev->devicetype = tmpstring;
+ 	init_completion(&xendev->down);
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	xendev->dev.parent = &bus->dev;
++#endif
+ 	xendev->dev.bus = &bus->bus;
+ 	xendev->dev.release = xenbus_dev_release;
+ 
+@@ -572,15 +590,16 @@ int xenbus_probe_node(struct xen_bus_typ
+ 
+ 	err = device_create_file(&xendev->dev, &dev_attr_nodename);
+ 	if (err)
+-		goto unregister;
++		goto fail_unregister;
++
+ 	err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ 	if (err)
+-		goto unregister;
++		goto fail_remove_file;
+ 
+ 	return 0;
+-unregister:
++fail_remove_file:
+ 	device_remove_file(&xendev->dev, &dev_attr_nodename);
+-	device_remove_file(&xendev->dev, &dev_attr_devtype);
++fail_unregister:
+ 	device_unregister(&xendev->dev);
+ fail:
+ 	kfree(xendev);
+@@ -596,7 +615,8 @@ static int xenbus_probe_frontend(const c
+ 	if (!strcmp(type, "console"))
+ 		return 0;
+ 
+-	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_frontend.root, type, name);
++	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s",
++			     xenbus_frontend.root, type, name);
+ 	if (!nodename)
+ 		return -ENOMEM;
+ 
+@@ -672,7 +692,7 @@ static int strsep_len(const char *str, c
+ 	return (len == 0) ? i : -ERANGE;
+ }
+ 
+-void dev_changed(const char *node, struct xen_bus_type *bus)
++void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
+ {
+ 	int exists, rootlen;
+ 	struct xenbus_device *dev;
+@@ -680,7 +700,7 @@ void dev_changed(const char *node, struc
+ 	const char *p, *root;
+ 
+ 	if (bus->error || char_count(node, '/') < 2)
+- 		return;
++		return;
+ 
+ 	exists = xenbus_exists(XBT_NIL, node, "");
+ 	if (!exists) {
+@@ -714,7 +734,7 @@ static void frontend_changed(struct xenb
+ {
+ 	DPRINTK("");
+ 
+-	dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
++	xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
+ }
+ 
+ /* We watch for devices appearing and vanishing. */
+@@ -939,6 +959,7 @@ static int xsd_port_read(char *page, cha
+ }
+ #endif
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ static int xb_free_port(evtchn_port_t port)
+ {
+ 	struct evtchn_close close;
+@@ -994,11 +1015,18 @@ fail0:
+ 	xen_store_evtchn = -1;
+ 	return rc;
+ }
++#endif
+ 
+-static int xenbus_probe_init(void)
++#ifndef MODULE
++static int __init xenbus_probe_init(void)
++#else
++static int __devinit xenbus_probe_init(void)
++#endif
+ {
+ 	int err = 0;
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	unsigned long page = 0;
++#endif
+ 
+ 	DPRINTK("");
+ 
+@@ -1017,6 +1045,7 @@ static int xenbus_probe_init(void)
+ 	 * Domain0 doesn't have a store_evtchn or store_mfn yet.
+ 	 */
+ 	if (is_initial_xendomain()) {
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 		struct evtchn_alloc_unbound alloc_unbound;
+ 
+ 		/* Allocate page. */
+@@ -1054,10 +1083,13 @@ static int xenbus_probe_init(void)
+ 		if (xsd_port_intf)
+ 			xsd_port_intf->read_proc = xsd_port_read;
+ #endif
++#else
++		/* dom0 not yet supported */
++#endif
+ 		xen_store_interface = mfn_to_virt(xen_store_mfn);
+ 	} else {
+ 		atomic_set(&xenbus_xsd_state, XENBUS_XSD_FOREIGN_READY);
+-#ifdef CONFIG_XEN
++#ifndef MODULE
+ 		xen_store_evtchn = xen_start_info->store_evtchn;
+ 		xen_store_mfn = xen_start_info->store_mfn;
+ 		xen_store_interface = mfn_to_virt(xen_store_mfn);
+@@ -1073,7 +1105,9 @@ static int xenbus_probe_init(void)
+ 			goto err;
+ 	}
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	xenbus_dev_init();
++#endif
+ 
+ 	/* Initialize the interface to xenstore. */
+ 	err = xs_init();
+@@ -1083,6 +1117,7 @@ static int xenbus_probe_init(void)
+ 		goto err;
+ 	}
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	/* Register ourselves with the kernel device subsystem */
+ 	if (!xenbus_frontend.error) {
+ 		xenbus_frontend.error = device_register(&xenbus_frontend.dev);
+@@ -1093,6 +1128,7 @@ static int xenbus_probe_init(void)
+ 			       xenbus_frontend.error);
+ 		}
+ 	}
++#endif
+ 	xenbus_backend_device_register();
+ 
+ 	if (!is_initial_xendomain())
+@@ -1101,8 +1137,10 @@ static int xenbus_probe_init(void)
+ 	return 0;
+ 
+  err:
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	if (page)
+ 		free_page(page);
++#endif
+ 
+ 	/*
+ 	 * Do not unregister the xenbus front/backend buses here. The buses
+@@ -1113,11 +1151,15 @@ static int xenbus_probe_init(void)
+ 	return err;
+ }
+ 
+-#ifdef CONFIG_XEN
++#ifndef MODULE
+ postcore_initcall(xenbus_probe_init);
++#ifdef CONFIG_XEN
+ MODULE_LICENSE("Dual BSD/GPL");
+ #else
+-int xenbus_init(void)
++MODULE_LICENSE("GPL");
++#endif
++#else
++int __devinit xenbus_init(void)
+ {
+ 	return xenbus_probe_init();
+ }
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:51:07.000000000 +0100
+@@ -62,7 +62,9 @@ struct xen_bus_type
+ 	int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
+ 	int (*probe)(const char *type, const char *dir);
+ 	struct bus_type bus;
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	struct device dev;
++#endif
+ };
+ 
+ extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
+@@ -77,6 +79,6 @@ extern int xenbus_probe_node(struct xen_
+ 			     const char *nodename);
+ extern int xenbus_probe_devices(struct xen_bus_type *bus);
+ 
+-extern void dev_changed(const char *node, struct xen_bus_type *bus);
++extern void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
+ 
+ #endif
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:07.000000000 +0100
+@@ -236,7 +236,7 @@ static void backend_changed(struct xenbu
+ {
+ 	DPRINTK("");
+ 
+-	dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
++	xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
+ }
+ 
+ static struct xenbus_watch be_watch = {
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_xs.c	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_xs.c	2009-11-06 10:51:07.000000000 +0100
+@@ -256,7 +256,7 @@ static void *xs_talkv(struct xenbus_tran
+ 	}
+ 
+ 	for (i = 0; i < num_vecs; i++) {
+-		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
++		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
+ 		if (err) {
+ 			mutex_unlock(&xs_state.request_mutex);
+ 			return ERR_PTR(err);
+@@ -665,7 +665,9 @@ void unregister_xenbus_watch(struct xenb
+ 	char token[sizeof(watch) * 2 + 1];
+ 	int err;
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 	BUG_ON(watch->flags & XBWF_new_thread);
++#endif
+ 
+ 	sprintf(token, "%lX", (long)watch);
+ 
+@@ -684,6 +686,11 @@ void unregister_xenbus_watch(struct xenb
+ 
+ 	up_read(&xs_state.watch_mutex);
+ 
++	/* Make sure there are no callbacks running currently (unless
++	   its us) */
++	if (current->pid != xenwatch_pid)
++		mutex_lock(&xenwatch_mutex);
++
+ 	/* Cancel pending watch events. */
+ 	spin_lock(&watch_events_lock);
+ 	list_for_each_entry_safe(msg, tmp, &watch_events, list) {
+@@ -695,11 +702,8 @@ void unregister_xenbus_watch(struct xenb
+ 	}
+ 	spin_unlock(&watch_events_lock);
+ 
+-	/* Flush any currently-executing callback, unless we are it. :-) */
+-	if (current->pid != xenwatch_pid) {
+-		mutex_lock(&xenwatch_mutex);
++	if (current->pid != xenwatch_pid)
+ 		mutex_unlock(&xenwatch_mutex);
+-	}
+ }
+ EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
+ 
+@@ -737,6 +741,7 @@ void xs_suspend_cancel(void)
+ 	mutex_unlock(&xs_state.transaction_mutex);
+ }
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ static int xenwatch_handle_callback(void *data)
+ {
+ 	struct xs_stored_msg *msg = data;
+@@ -754,6 +759,7 @@ static int xenwatch_handle_callback(void
+ 
+ 	return 0;
+ }
++#endif
+ 
+ static int xenwatch_thread(void *unused)
+ {
+@@ -783,6 +789,7 @@ static int xenwatch_thread(void *unused)
+ 
+ 		msg = list_entry(ent, struct xs_stored_msg, list);
+ 
++#if defined(CONFIG_XEN) || defined(MODULE)
+ 		/*
+ 		 * Unlock the mutex before running an XBWF_new_thread
+ 		 * handler. kthread_run can block which can deadlock
+@@ -799,6 +806,15 @@ static int xenwatch_thread(void *unused)
+ 			xenwatch_handle_callback(msg);
+ 			mutex_unlock(&xenwatch_mutex);
+ 		}
++#else
++		msg->u.watch.handle->callback(
++			msg->u.watch.handle,
++			(const char **)msg->u.watch.vec,
++			msg->u.watch.vec_size);
++		mutex_unlock(&xenwatch_mutex);
++		kfree(msg->u.watch.vec);
++		kfree(msg);
++#endif
+ 	}
+ 
+ 	return 0;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -53,6 +53,8 @@ extern unsigned long __FIXADDR_TOP;
+ enum fixed_addresses {
+ 	FIX_HOLE,
+ 	FIX_VDSO,
++	FIX_DBGP_BASE,
++	FIX_EARLYCON_MEM_BASE,
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:07.000000000 +0100
+@@ -76,8 +76,7 @@ struct page *kmap_atomic_to_page(void *p
+ 
+ #define kmap_atomic_pte(page, type) \
+ 	kmap_atomic_prot(page, type, \
+-	                 test_bit(PG_pinned, &(page)->flags) \
+-	                 ? PAGE_KERNEL_RO : kmap_prot)
++	                 PagePinned(page) ? PAGE_KERNEL_RO : kmap_prot)
+ 
+ #define flush_cache_kmaps()	do { } while (0)
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/maddr_32.h	2008-04-02 12:34:02.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -155,6 +155,7 @@ static inline paddr_t pte_machine_to_phy
+ 
+ #ifdef CONFIG_X86_PAE
+ #define __pte_ma(x)	((pte_t) { (x), (maddr_t)(x) >> 32 } )
++extern unsigned long long __supported_pte_mask;
+ static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+ {
+ 	pte_t pte;
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -16,7 +16,7 @@ void mm_pin_all(void);
+ static inline void xen_activate_mm(struct mm_struct *prev,
+ 				   struct mm_struct *next)
+ {
+-	if (!test_bit(PG_pinned, &virt_to_page(next->pgd)->flags))
++	if (!PagePinned(virt_to_page(next->pgd)))
+ 		mm_pin(next);
+ }
+ 
+@@ -51,6 +51,8 @@ static inline void __prepare_arch_switch
+ 		: : "r" (0) );
+ }
+ 
++void leave_mm(unsigned long cpu);
++
+ static inline void switch_mm(struct mm_struct *prev,
+ 			     struct mm_struct *next,
+ 			     struct task_struct *tsk)
+@@ -60,7 +62,7 @@ static inline void switch_mm(struct mm_s
+ 
+ 	if (likely(prev != next)) {
+ 		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+-		       !test_bit(PG_pinned, &virt_to_page(next->pgd)->flags));
++		       !PagePinned(virt_to_page(next->pgd)));
+ 
+ 		/* stop flush ipis for the previous mm */
+ 		cpu_clear(cpu, prev->cpu_vm_mask);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -5,7 +5,7 @@
+ #include <linux/mm.h>		/* for struct page */
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+ 
+-#define paravirt_alloc_pt(pfn) do { } while (0)
++#define paravirt_alloc_pt(mm, pfn) do { } while (0)
+ #define paravirt_alloc_pd(pfn) do { } while (0)
+ #define paravirt_alloc_pd(pfn) do { } while (0)
+ #define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+@@ -14,15 +14,15 @@
+ 
+ #define pmd_populate_kernel(mm, pmd, pte)			\
+ do {								\
+-	paravirt_alloc_pt(__pa(pte) >> PAGE_SHIFT);		\
++	paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);		\
+ 	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));		\
+ } while (0)
+ 
+ #define pmd_populate(mm, pmd, pte) 					\
+ do {									\
+ 	unsigned long pfn = page_to_pfn(pte);				\
+-	paravirt_alloc_pt(pfn);						\
+-	if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) {	\
++	paravirt_alloc_pt(mm, pfn);					\
++	if (PagePinned(virt_to_page((mm)->pgd))) {			\
+ 		if (!PageHighMem(pte))					\
+ 			BUG_ON(HYPERVISOR_update_va_mapping(		\
+ 			  (unsigned long)__va(pfn << PAGE_SHIFT),	\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -26,9 +26,6 @@
+ #include <linux/spinlock.h>
+ #include <linux/sched.h>
+ 
+-/* Is this pagetable pinned? */
+-#define PG_pinned	PG_arch_1
+-
+ struct vm_area_struct;
+ 
+ /*
+@@ -82,7 +79,7 @@ void paging_init(void);
+  * area for the same reason. ;)
+  */
+ #define VMALLOC_OFFSET	(8*1024*1024)
+-#define VMALLOC_START	(((unsigned long) high_memory + vmalloc_earlyreserve + \
++#define VMALLOC_START	(((unsigned long) high_memory + \
+ 			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
+ #ifdef CONFIG_HIGHMEM
+ # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
+@@ -231,8 +228,6 @@ extern unsigned long pg0[];
+  * The following only work if pte_present() is true.
+  * Undefined behaviour if not..
+  */
+-static inline int pte_user(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
+-static inline int pte_read(pte_t pte)		{ return (pte).pte_low & _PAGE_USER; }
+ static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
+ static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
+@@ -243,13 +238,9 @@ static inline int pte_huge(pte_t pte)		{
+  */
+ static inline int pte_file(pte_t pte)		{ return (pte).pte_low & _PAGE_FILE; }
+ 
+-static inline pte_t pte_rdprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
+-static inline pte_t pte_exprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_USER; return pte; }
+ static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
+-static inline pte_t pte_mkread(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
+-static inline pte_t pte_mkexec(pte_t pte)	{ (pte).pte_low |= _PAGE_USER; return pte; }
+ static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
+@@ -295,22 +286,20 @@ static inline pte_t xen_local_ptep_get_a
+ #define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+ ({									\
+ 	int __changed = !pte_same(*(ptep), entry);			\
+-	if (__changed && (dirty))					\
+-		ptep_establish(vma, address, ptep, entry);		\
++	if (__changed && (dirty)) {					\
++		if ( likely((vma)->vm_mm == current->mm) ) {		\
++			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
++				entry,					\
++				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
++					UVMF_INVLPG|UVMF_MULTI));	\
++		} else {						\
++			xen_l1_entry_update(ptep, entry);		\
++			flush_tlb_page(vma, address);			\
++		}							\
++	}								\
+ 	__changed;							\
+ })
+ 
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+-#define ptep_test_and_clear_dirty(vma, addr, ptep) ({			\
+-	int __ret = 0;							\
+-	if (pte_dirty(*(ptep)))						\
+-		__ret = test_and_clear_bit(_PAGE_BIT_DIRTY,		\
+-						&(ptep)->pte_low);	\
+-	if (__ret)							\
+-		pte_update((vma)->vm_mm, addr, ptep);			\
+-	__ret;								\
+-})
+-
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+ #define ptep_test_and_clear_young(vma, addr, ptep) ({			\
+ 	int __ret = 0;							\
+@@ -322,44 +311,13 @@ static inline pte_t xen_local_ptep_get_a
+ 	__ret;								\
+ })
+ 
+-/*
+- * Rules for using ptep_establish: the pte MUST be a user pte, and
+- * must be a present->present transition.
+- */
+-#define __HAVE_ARCH_PTEP_ESTABLISH
+-#define ptep_establish(vma, address, ptep, pteval)			\
+-do {									\
+-	if ( likely((vma)->vm_mm == current->mm) ) {			\
+-		BUG_ON(HYPERVISOR_update_va_mapping(address,		\
+-			pteval,						\
+-			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits|	\
+-				UVMF_INVLPG|UVMF_MULTI));		\
+-	} else {							\
+-		xen_l1_entry_update(ptep, pteval);			\
+-		flush_tlb_page(vma, address);				\
+-	}								\
+-} while (0)
+-
+-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+-#define ptep_clear_flush_dirty(vma, address, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __dirty = pte_dirty(__pte);					\
+-	__pte = pte_mkclean(__pte);					\
+-	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
+-		(void)ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
+-	else if (__dirty)						\
+-		(ptep)->pte_low = __pte.pte_low;			\
+-	__dirty;							\
+-})
+-
+ #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+ #define ptep_clear_flush_young(vma, address, ptep)			\
+ ({									\
+ 	pte_t __pte = *(ptep);						\
+ 	int __young = pte_young(__pte);					\
+ 	__pte = pte_mkold(__pte);					\
+-	if (test_bit(PG_pinned, &virt_to_page((vma)->vm_mm->pgd)->flags)) \
++	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
+ 		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+ 	else if (__young)						\
+ 		(ptep)->pte_low = __pte.pte_low;			\
+@@ -383,7 +341,7 @@ static inline pte_t ptep_get_and_clear(s
+ #define ptep_get_and_clear_full(mm, addr, ptep, full)			\
+ 	((full) ? ({							\
+ 		pte_t __res = *(ptep);					\
+-		if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) \
++		if (PagePinned(virt_to_page((mm)->pgd)))		\
+ 			xen_l1_entry_update(ptep, __pte(0));		\
+ 		else							\
+ 			*(ptep) = __pte(0);				\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:07.000000000 +0100
+@@ -23,26 +23,11 @@
+ #define pud_present(pud)			1
+ 
+ /*
+- * Is the pte executable?
+- */
+-static inline int pte_x(pte_t pte)
+-{
+-	return !(__pte_val(pte) & _PAGE_NX);
+-}
+-
+-/*
+- * All present user-pages with !NX bit are user-executable:
+- */
+-static inline int pte_exec(pte_t pte)
+-{
+-	return pte_user(pte) && pte_x(pte);
+-}
+-/*
+  * All present pages with !NX bit are kernel-executable:
+  */
+ static inline int pte_exec_kernel(pte_t pte)
+ {
+-	return pte_x(pte);
++	return !(__pte_val(pte) & _PAGE_NX);
+ }
+ 
+ /* Rules for using set_pte: the pte being assigned *must* be
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -89,7 +89,6 @@ struct cpuinfo_x86 {
+ #define X86_VENDOR_UMC 3
+ #define X86_VENDOR_NEXGEN 4
+ #define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_RISE 6
+ #define X86_VENDOR_TRANSMETA 7
+ #define X86_VENDOR_NSC 8
+ #define X86_VENDOR_NUM 9
+@@ -122,6 +121,7 @@ void __init cpu_detect(struct cpuinfo_x8
+ extern void identify_boot_cpu(void);
+ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
++extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+ 
+@@ -171,17 +171,6 @@ static inline void clear_in_cr4 (unsigne
+ 	write_cr4(cr4);
+ }
+ 
+-/*
+- *      NSC/Cyrix CPU indexed register access macros
+- */
+-
+-#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
+-
+-#define setCx86(reg, data) do { \
+-	outb((reg), 0x22); \
+-	outb((data), 0x23); \
+-} while (0)
+-
+ /* Stop speculative execution */
+ static inline void sync_core(void)
+ {
+@@ -230,6 +219,10 @@ extern int bootloader_type;
+ 
+ #define HAVE_ARCH_PICK_MMAP_LAYOUT
+ 
++extern void hard_disable_TSC(void);
++extern void disable_TSC(void);
++extern void hard_enable_TSC(void);
++
+ /*
+  * Size of io_bitmap.
+  */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -205,11 +205,6 @@ static inline unsigned long get_limit(un
+  */
+  
+ 
+-/* 
+- * Actually only lfence would be needed for mb() because all stores done 
+- * by the kernel should be already ordered. But keep a full barrier for now. 
+- */
+-
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+ #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+ 
+@@ -301,15 +296,6 @@ void enable_hlt(void);
+ extern int es7000_plat;
+ void cpu_idle_wait(void);
+ 
+-/*
+- * On SMP systems, when the scheduler does migration-cost autodetection,
+- * it needs a way to flush as much of the CPU's caches as possible:
+- */
+-static inline void sched_cacheflush(void)
+-{
+-	wbinvd();
+-}
+-
+ extern unsigned long arch_align_stack(unsigned long sp);
+ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:51:07.000000000 +0100
+@@ -91,7 +91,11 @@ struct tlb_state
+ DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
+ #endif	/* SMP */
+ 
+-#define flush_tlb_kernel_range(start, end) flush_tlb_all()
++static inline void flush_tlb_kernel_range(unsigned long start,
++					unsigned long end)
++{
++	flush_tlb_all();
++}
+ 
+ static inline void flush_tlb_pgtables(struct mm_struct *mm,
+ 				      unsigned long start, unsigned long end)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -23,9 +23,9 @@
+  * compile time, but to set the physical address only
+  * in the boot process.
+  *
+- * these 'compile-time allocated' memory buffers are
+- * fixed-size 4k pages. (or larger if used with an increment
+- * highger than 1) use fixmap_set(idx,phys) to associate
++ * These 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages (or larger if used with an increment
++ * higher than 1). Use set_fixmap(idx,phys) to associate
+  * physical memory with fixmap indices.
+  *
+  * TLB entries of such buffers will not be flushed across
+@@ -36,6 +36,8 @@ enum fixed_addresses {
+ 	VSYSCALL_LAST_PAGE,
+ 	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+ 	VSYSCALL_HPET,
++	FIX_DBGP_BASE,
++	FIX_EARLYCON_MEM_BASE,
+ 	FIX_HPET_BASE,
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+@@ -105,7 +107,7 @@ static __always_inline unsigned long fix
+ 	if (idx >= __end_of_fixed_addresses)
+ 		__this_fixmap_does_not_exist();
+ 
+-        return __fix_to_virt(idx);
++	return __fix_to_virt(idx);
+ }
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -76,7 +76,7 @@ static inline void switch_mm(struct mm_s
+ 
+ 	if (likely(prev != next)) {
+ 		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+-		       !next->context.pinned);
++		       !PagePinned(virt_to_page(next->pgd)));
+ 
+ 		/* stop flush ipis for the previous mm */
+ 		cpu_clear(cpu, prev->cpu_vm_mask);
+@@ -131,7 +131,7 @@ static inline void switch_mm(struct mm_s
+ 
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
+-	if (!next->context.pinned)
++	if (!PagePinned(virt_to_page(next->pgd)))
+ 		mm_pin(next);
+ 	switch_mm(prev, next, NULL);
+ }
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -21,7 +21,7 @@ static inline void pmd_populate_kernel(s
+ 
+ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+ {
+-	if (unlikely((mm)->context.pinned)) {
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+ 		BUG_ON(HYPERVISOR_update_va_mapping(
+ 			       (unsigned long)__va(page_to_pfn(pte) << PAGE_SHIFT),
+ 			       pfn_pte(page_to_pfn(pte), PAGE_KERNEL_RO), 0));
+@@ -33,7 +33,7 @@ static inline void pmd_populate(struct m
+ 
+ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+ {
+-	if (unlikely((mm)->context.pinned)) {
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+ 		BUG_ON(HYPERVISOR_update_va_mapping(
+ 			       (unsigned long)pmd,
+ 			       pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, 
+@@ -50,7 +50,7 @@ static inline void pud_populate(struct m
+  */
+ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+ {
+-	if (unlikely((mm)->context.pinned)) {
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+ 		BUG_ON(HYPERVISOR_update_va_mapping(
+ 			       (unsigned long)pud,
+ 			       pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -304,7 +304,7 @@ static inline pte_t ptep_get_and_clear_f
+ {
+ 	if (full) {
+ 		pte_t pte = *ptep;
+-		if (mm->context.pinned)
++		if (PagePinned(virt_to_page(mm->pgd)))
+ 			xen_l1_entry_update(ptep, __pte(0));
+ 		else
+ 			*ptep = __pte(0);
+@@ -333,21 +333,15 @@ static inline pte_t ptep_get_and_clear_f
+  * Undefined behaviour if not..
+  */
+ #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
+-static inline int pte_user(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
+-static inline int pte_read(pte_t pte)		{ return __pte_val(pte) & _PAGE_USER; }
+-static inline int pte_exec(pte_t pte)		{ return !(__pte_val(pte) & _PAGE_NX); }
+ static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
+ static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
+ static inline int pte_file(pte_t pte)		{ return __pte_val(pte) & _PAGE_FILE; }
+ static inline int pte_huge(pte_t pte)		{ return __pte_val(pte) & _PAGE_PSE; }
+ 
+-static inline pte_t pte_rdprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_USER; return pte; }
+-static inline pte_t pte_exprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_USER; return pte; }
+ static inline pte_t pte_mkclean(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkold(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_wrprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_RW; return pte; }
+-static inline pte_t pte_mkread(pte_t pte)	{ __pte_val(pte) |= _PAGE_USER; return pte; }
+ static inline pte_t pte_mkexec(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_NX; return pte; }
+ static inline pte_t pte_mkdirty(pte_t pte)	{ __pte_val(pte) |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte)	{ __pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+@@ -355,13 +349,6 @@ static inline pte_t pte_mkwrite(pte_t pt
+ static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
+ static inline pte_t pte_clrhuge(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_PSE; return pte; }
+ 
+-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+-{
+-	if (!pte_dirty(*ptep))
+-		return 0;
+-	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte);
+-}
+-
+ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+ {
+ 	if (!pte_young(*ptep))
+@@ -500,26 +487,13 @@ static inline pte_t pte_modify(pte_t pte
+ 	__changed;							\
+ })
+ 
+-#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
+-#define ptep_clear_flush_dirty(vma, address, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __dirty = pte_dirty(__pte);					\
+-	__pte = pte_mkclean(__pte);					\
+-	if ((vma)->vm_mm->context.pinned)				\
+-		(void)ptep_set_access_flags(vma, address, ptep, __pte, __dirty); \
+-	else if (__dirty)						\
+-		set_pte(ptep, __pte);					\
+-	__dirty;							\
+-})
+-
+ #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+ #define ptep_clear_flush_young(vma, address, ptep)			\
+ ({									\
+ 	pte_t __pte = *(ptep);						\
+ 	int __young = pte_young(__pte);					\
+ 	__pte = pte_mkold(__pte);					\
+-	if ((vma)->vm_mm->context.pinned)				\
++	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
+ 		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+ 	else if (__young)						\
+ 		set_pte(ptep, __pte);					\
+@@ -570,6 +544,8 @@ int xen_change_pte_range(struct mm_struc
+ #define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
+ 	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+ 
++pte_t *lookup_address(unsigned long addr);
++
+ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+ 		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
+ 
+@@ -587,7 +563,6 @@ int xen_change_pte_range(struct mm_struc
+    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
+ 
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+ #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+ #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -83,7 +83,6 @@ struct cpuinfo_x86 {
+ #define X86_VENDOR_UMC 3
+ #define X86_VENDOR_NEXGEN 4
+ #define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_RISE 6
+ #define X86_VENDOR_TRANSMETA 7
+ #define X86_VENDOR_NUM 8
+ #define X86_VENDOR_UNKNOWN 0xff
+@@ -100,6 +99,7 @@ extern char ignore_irq13;
+ 
+ extern void identify_cpu(struct cpuinfo_x86 *);
+ extern void print_cpu_info(struct cpuinfo_x86 *);
++extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+ 
+@@ -377,12 +377,10 @@ static inline void sync_core(void)
+ 	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
+ } 
+ 
+-#define cpu_has_fpu 1
+-
+ #define ARCH_HAS_PREFETCH
+ static inline void prefetch(void *x) 
+ { 
+-	asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x));
++	asm volatile("prefetcht0 (%0)" :: "r" (x));
+ } 
+ 
+ #define ARCH_HAS_PREFETCHW 1
+@@ -400,17 +398,6 @@ static inline void prefetchw(void *x) 
+ 
+ #define cpu_relax()   rep_nop()
+ 
+-/*
+- *      NSC/Cyrix CPU indexed register access macros
+- */
+-
+-#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
+-
+-#define setCx86(reg, data) do { \
+-	outb((reg), 0x22); \
+-	outb((data), 0x23); \
+-} while (0)
+-
+ static inline void serialize_cpu(void)
+ {
+ 	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -79,12 +79,16 @@ static inline unsigned long read_cr0(voi
+ 	unsigned long cr0;
+ 	asm volatile("movq %%cr0,%0" : "=r" (cr0));
+ 	return cr0;
+-} 
++}
+ 
+ static inline void write_cr0(unsigned long val) 
+ { 
+ 	asm volatile("movq %0,%%cr0" :: "r" (val));
+-} 
++}
++
++#define read_cr2() current_vcpu_info()->arch.cr2
++
++#define write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val)))
+ 
+ #define read_cr3() ({ \
+ 	unsigned long __dummy; \
+@@ -103,27 +107,28 @@ static inline unsigned long read_cr4(voi
+ 	unsigned long cr4;
+ 	asm("movq %%cr4,%0" : "=r" (cr4));
+ 	return cr4;
+-} 
++}
+ 
+ static inline void write_cr4(unsigned long val)
+ { 
+ 	asm volatile("movq %0,%%cr4" :: "r" (val) : "memory");
+-} 
+-
+-#define stts() (HYPERVISOR_fpu_taskswitch(1))
++}
+ 
+-#define wbinvd() \
+-	__asm__ __volatile__ ("wbinvd": : :"memory");
++static inline unsigned long read_cr8(void)
++{
++	return 0;
++}
+ 
+-/*
+- * On SMP systems, when the scheduler does migration-cost autodetection,
+- * it needs a way to flush as much of the CPU's caches as possible.
+- */
+-static inline void sched_cacheflush(void)
++static inline void write_cr8(unsigned long val)
+ {
+-	wbinvd();
++	BUG_ON(val);
+ }
+ 
++#define stts() (HYPERVISOR_fpu_taskswitch(1))
++
++#define wbinvd() \
++	__asm__ __volatile__ ("wbinvd": : :"memory")
++
+ #endif	/* __KERNEL__ */
+ 
+ #define nop() __asm__ __volatile__ ("nop")
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:51:07.000000000 +0100
+@@ -89,7 +89,11 @@ static inline void flush_tlb_range(struc
+ 
+ #endif
+ 
+-#define flush_tlb_kernel_range(start, end) flush_tlb_all()
++static inline void flush_tlb_kernel_range(unsigned long start,
++					unsigned long end)
++{
++	flush_tlb_all();
++}
+ 
+ static inline void flush_tlb_pgtables(struct mm_struct *mm,
+ 				      unsigned long start, unsigned long end)
+--- head-2010-01-18.orig/arch/x86/include/asm/thread_info.h	2009-11-06 10:45:44.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/thread_info.h	2009-11-06 10:51:07.000000000 +0100
+@@ -152,7 +152,8 @@ struct thread_info {
+ #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
+ #else
+-#define _TIF_WORK_CTXSW _TIF_DEBUG
++#define _TIF_WORK_CTXSW_NEXT (_TIF_NOTSC | _TIF_DEBUG)
++#define _TIF_WORK_CTXSW_PREV (_TIF_NOTSC)
+ #endif
+ 
+ #define PREEMPT_ACTIVE		0x10000000
+--- head-2010-01-18.orig/arch/x86/include/asm/xen/interface.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/xen/interface.h	2009-11-06 10:51:07.000000000 +0100
+@@ -10,17 +10,20 @@
+ #define _ASM_X86_XEN_INTERFACE_H
+ 
+ #ifdef __XEN__
+-#define __DEFINE_GUEST_HANDLE(name, type) \
++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+     typedef struct { type *p; } __guest_handle_ ## name
+ #else
+-#define __DEFINE_GUEST_HANDLE(name, type) \
++#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_GUEST_HANDLE_STRUCT(name) \
+-	__DEFINE_GUEST_HANDLE(name, struct name)
+-#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
+-#define GUEST_HANDLE(name)        __guest_handle_ ## name
++	__DEFINE_XEN_GUEST_HANDLE(name, struct name)
++#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
++#define XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
+ 
+ #ifdef __XEN__
+ #if defined(__i386__)
+@@ -47,14 +50,8 @@
+ #endif
+ 
+ #ifndef __ASSEMBLY__
+-/* Guest handles for primitive C types. */
+-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
+-__DEFINE_GUEST_HANDLE(uint,  unsigned int);
+-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
+-DEFINE_GUEST_HANDLE(char);
+-DEFINE_GUEST_HANDLE(int);
+-DEFINE_GUEST_HANDLE(long);
+-DEFINE_GUEST_HANDLE(void);
++typedef unsigned long xen_pfn_t;
++typedef unsigned long xen_ulong_t;
+ #endif
+ 
+ #ifndef HYPERVISOR_VIRT_START
+@@ -66,7 +63,7 @@ DEFINE_GUEST_HANDLE(void);
+ #endif
+ 
+ /* Maximum number of virtual CPUs in multi-processor guests. */
+-#define MAX_VIRT_CPUS 32
++#define XEN_LEGACY_MAX_VCPUS 32
+ 
+ /*
+  * SEGMENT DESCRIPTOR TABLES
+--- head-2010-01-18.orig/include/linux/elfnote.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/include/linux/elfnote.h	2009-11-06 10:51:07.000000000 +0100
+@@ -52,7 +52,7 @@
+ 4484:.balign 4				;	\
+ .popsection				;
+ 
+-#define ELFNOTE(name, type, desc)		\
++#define ELFNOTE(name, type, desc...)		\
+ 	ELFNOTE_START(name, type, "")		\
+ 		desc			;	\
+ 	ELFNOTE_END
+--- head-2010-01-18.orig/include/linux/page-flags.h	2009-12-16 11:49:19.000000000 +0100
++++ head-2010-01-18/include/linux/page-flags.h	2009-12-16 11:50:02.000000000 +0100
+@@ -127,8 +127,15 @@ enum pageflags {
+ 	PG_fscache = PG_private_2,	/* page backed by cache */
+ 
+ 	/* XEN */
++#ifdef CONFIG_XEN
++	PG_pinned = PG_locked,	/* Cannot alias with PG_owner_priv_1 since
++				 * bad_page() checks should include this bit.
++				 * Also cannot use PG_arch_1 since that now
++				 * has a different purpose on x86. */
++#else
+ 	PG_pinned = PG_owner_priv_1,
+ 	PG_savepinned = PG_dirty,
++#endif
+ 
+ 	/* SLOB */
+ 	PG_slob_free = PG_private,
+@@ -443,10 +450,8 @@ PAGEFLAG_FALSE(MemError)
+ #define __PG_MLOCKED		0
+ #endif
+ 
+-#if !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
+ # define __PG_XEN		0
+-#elif defined(CONFIG_X86)
+-# define __PG_XEN		((1 << PG_pinned) | (1 << PG_foreign))
+ #else
+ # define __PG_XEN		(1 << PG_foreign)
+ #endif
+--- head-2010-01-18.orig/include/linux/skbuff.h	2009-12-16 11:49:35.000000000 +0100
++++ head-2010-01-18/include/linux/skbuff.h	2009-12-16 11:49:58.000000000 +0100
+@@ -2122,7 +2122,7 @@ static inline void skb_forward_csum(stru
+ 
+ bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
+ 
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ int skb_checksum_setup(struct sk_buff *skb);
+ #else
+ static inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
+--- head-2010-01-18.orig/include/xen/driver_util.h	2007-06-12 13:14:19.000000000 +0200
++++ head-2010-01-18/include/xen/driver_util.h	2009-11-06 10:51:07.000000000 +0100
+@@ -5,10 +5,6 @@
+ #include <linux/vmalloc.h>
+ #include <linux/device.h>
+ 
+-/* Allocate/destroy a 'vmalloc' VM area. */
+-extern struct vm_struct *alloc_vm_area(unsigned long size);
+-extern void free_vm_area(struct vm_struct *area);
+-
+ extern struct class *get_xen_class(void);
+ 
+ #endif /* __ASM_XEN_DRIVER_UTIL_H__ */
+--- head-2010-01-18.orig/include/xen/features.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/include/xen/features.h	2009-11-06 10:51:07.000000000 +0100
+@@ -10,6 +10,7 @@
+ #define __XEN_FEATURES_H__
+ 
+ #include <xen/interface/features.h>
++#include <xen/interface/version.h>
+ 
+ void xen_setup_features(void);
+ 
+@@ -20,4 +21,4 @@ static inline int xen_feature(int flag)
+ 	return xen_features[flag];
+ }
+ 
+-#endif /* __ASM_XEN_FEATURES_H__ */
++#endif /* __XEN_FEATURES_H__ */
+--- head-2010-01-18.orig/include/xen/interface/arch-x86/xen.h	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/include/xen/interface/arch-x86/xen.h	2009-11-06 10:51:07.000000000 +0100
+@@ -49,6 +49,9 @@
+ #define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+ #endif
+ 
++/* Allow co-existing Linux 2.6.23+ Xen interface definitions. */
++#define DEFINE_GUEST_HANDLE_STRUCT(name) struct name
++
+ #if defined(__i386__)
+ #include "xen-x86_32.h"
+ #elif defined(__x86_64__)
+--- head-2010-01-18.orig/include/xen/interface/event_channel.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/event_channel.h	2009-11-06 10:51:07.000000000 +0100
+@@ -250,6 +250,7 @@ struct evtchn_op {
+         struct evtchn_unmask           unmask;
+     } u;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(evtchn_op);
+ typedef struct evtchn_op evtchn_op_t;
+ DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
+ 
+--- head-2010-01-18.orig/include/xen/interface/io/netif.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/io/netif.h	2009-11-06 10:51:07.000000000 +0100
+@@ -183,8 +183,22 @@ typedef struct netif_rx_response netif_r
+  * Generate netif ring structures and types.
+  */
+ 
++#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
+ DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
++#else
++#define xen_netif_tx_request netif_tx_request
++#define xen_netif_rx_request netif_rx_request
++#define xen_netif_tx_response netif_tx_response
++#define xen_netif_rx_response netif_rx_response
++DEFINE_RING_TYPES(xen_netif_tx,
++		  struct xen_netif_tx_request,
++		  struct xen_netif_tx_response);
++DEFINE_RING_TYPES(xen_netif_rx,
++		  struct xen_netif_rx_request,
++		  struct xen_netif_rx_response);
++#define xen_netif_extra_info netif_extra_info
++#endif
+ 
+ #define NETIF_RSP_DROPPED         -2
+ #define NETIF_RSP_ERROR           -1
+--- head-2010-01-18.orig/include/xen/interface/memory.h	2010-01-04 12:17:29.000000000 +0100
++++ head-2010-01-18/include/xen/interface/memory.h	2010-01-04 12:30:24.000000000 +0100
+@@ -85,6 +85,7 @@ struct xen_memory_reservation {
+      */
+     domid_t        domid;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+ typedef struct xen_memory_reservation xen_memory_reservation_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+ 
+@@ -178,6 +179,7 @@ struct xen_machphys_mfn_list {
+      */
+     unsigned int nr_extents;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+ 
+@@ -219,6 +221,7 @@ struct xen_add_to_physmap {
+     /* GPFN where the source mapping page should appear. */
+     xen_pfn_t     gpfn;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+ typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+ DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+ 
+--- head-2010-01-18.orig/include/xen/interface/sched.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/sched.h	2009-11-06 10:51:07.000000000 +0100
+@@ -67,6 +67,7 @@
+ struct sched_shutdown {
+     unsigned int reason; /* SHUTDOWN_* */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(sched_shutdown);
+ typedef struct sched_shutdown sched_shutdown_t;
+ DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
+ 
+@@ -81,6 +82,7 @@ struct sched_poll {
+     unsigned int nr_ports;
+     uint64_t timeout;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(sched_poll);
+ typedef struct sched_poll sched_poll_t;
+ DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
+ 
+--- head-2010-01-18.orig/include/xen/interface/version.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/interface/version.h	2009-11-06 10:51:07.000000000 +0100
+@@ -36,6 +36,9 @@
+ /* arg == xen_extraversion_t. */
+ #define XENVER_extraversion 1
+ typedef char xen_extraversion_t[16];
++struct xen_extraversion {
++    xen_extraversion_t extraversion;
++};
+ #define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+ 
+ /* arg == xen_compile_info_t. */
+@@ -50,10 +53,16 @@ typedef struct xen_compile_info xen_comp
+ 
+ #define XENVER_capabilities 3
+ typedef char xen_capabilities_info_t[1024];
++struct xen_capabilities_info {
++    xen_capabilities_info_t info;
++};
+ #define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+ 
+ #define XENVER_changeset 4
+ typedef char xen_changeset_info_t[64];
++struct xen_changeset_info {
++    xen_changeset_info_t info;
++};
+ #define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
+ 
+ #define XENVER_platform_parameters 5
+--- head-2010-01-18.orig/include/xen/interface/xen.h	2010-01-04 12:13:58.000000000 +0100
++++ head-2010-01-18/include/xen/interface/xen.h	2010-01-04 12:30:37.000000000 +0100
+@@ -32,7 +32,9 @@
+ #include <asm/pvclock-abi.h>
+ #endif
+ 
+-#if defined(__i386__) || defined(__x86_64__)
++#if defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H)
++#include <asm/xen/interface.h>
++#elif defined(__i386__) || defined(__x86_64__)
+ #include "arch-x86/xen.h"
+ #elif defined(__ia64__)
+ #include "arch-ia64.h"
+@@ -112,7 +114,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+  */
+ 
+ /* New sched_op hypercall introduced in 0x00030101. */
+-#if __XEN_INTERFACE_VERSION__ < 0x00030101
++#if __XEN_INTERFACE_VERSION__ < 0x00030101 || (defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H))
+ #undef __HYPERVISOR_sched_op
+ #define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+ #else
+@@ -128,7 +130,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+ #endif
+ 
+ /* New platform_op hypercall introduced in 0x00030204. */
+-#if __XEN_INTERFACE_VERSION__ < 0x00030204
++#if __XEN_INTERFACE_VERSION__ < 0x00030204 || (defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H))
+ #define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+ #endif
+ 
+@@ -297,6 +299,7 @@ struct mmuext_op {
+         xen_pfn_t src_mfn;
+     } arg2;
+ };
++DEFINE_GUEST_HANDLE_STRUCT(mmuext_op);
+ typedef struct mmuext_op mmuext_op_t;
+ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
+ #endif
+@@ -386,6 +389,7 @@ struct mmu_update {
+     uint64_t ptr;       /* Machine address of PTE. */
+     uint64_t val;       /* New contents of PTE.    */
+ };
++DEFINE_GUEST_HANDLE_STRUCT(mmu_update);
+ typedef struct mmu_update mmu_update_t;
+ DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
+ 
+@@ -394,9 +398,15 @@ DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
+  * NB. The fields are natural register size for this architecture.
+  */
+ struct multicall_entry {
+-    unsigned long op, result;
++    unsigned long op;
++#if !defined(CONFIG_PARAVIRT_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
++    unsigned long result;
++#else
++    long result;
++#endif
+     unsigned long args[6];
+ };
++DEFINE_GUEST_HANDLE_STRUCT(multicall_entry);
+ typedef struct multicall_entry multicall_entry_t;
+ DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
+ 
+--- head-2010-01-18.orig/include/xen/xenbus.h	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/include/xen/xenbus.h	2009-11-06 10:51:07.000000000 +0100
+@@ -57,16 +57,20 @@ struct xenbus_watch
+ 	void (*callback)(struct xenbus_watch *,
+ 			 const char **vec, unsigned int len);
+ 
++#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ 	/* See XBWF_ definitions below. */
+ 	unsigned long flags;
++#endif
+ };
+ 
++#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ /*
+  * Execute callback in its own kthread. Useful if the callback is long
+  * running or heavily serialised, to avoid taking out the main xenwatch thread
+  * for a long period of time (or even unwittingly causing a deadlock).
+  */
+ #define XBWF_new_thread	1
++#endif
+ 
+ /* A xenbus device. */
+ struct xenbus_device {
+@@ -214,6 +218,7 @@ int xenbus_watch_path(struct xenbus_devi
+ 				       const char **, unsigned int));
+ 
+ 
++#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+ /**
+  * Register a watch on the given path/path2, using the given xenbus_watch
+  * structure for storage, and the given callback function as the callback.
+@@ -227,7 +232,13 @@ int xenbus_watch_path2(struct xenbus_dev
+ 		       const char *path2, struct xenbus_watch *watch,
+ 		       void (*callback)(struct xenbus_watch *,
+ 					const char **, unsigned int));
+-
++#else
++int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
++			 void (*callback)(struct xenbus_watch *,
++					  const char **, unsigned int),
++			 const char *pathfmt, ...)
++	__attribute__ ((format (printf, 4, 5)));
++#endif
+ 
+ /**
+  * Advertise in the store a change of the given driver to the given new_state.
+--- head-2010-01-18.orig/net/core/dev.c	2009-12-04 10:55:51.000000000 +0100
++++ head-2010-01-18/net/core/dev.c	2009-12-04 11:00:38.000000000 +0100
+@@ -137,7 +137,7 @@
+ /* This should be increased if a protocol with a bigger head is added. */
+ #define GRO_MAX_HEAD (MAX_HEADER + 128)
+ 
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ #include <net/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/udp.h>
+@@ -1823,42 +1823,54 @@ static struct netdev_queue *dev_pick_tx(
+ 	return netdev_get_tx_queue(dev, queue_index);
+ }
+ 
+-#ifdef CONFIG_XEN
++#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+ inline int skb_checksum_setup(struct sk_buff *skb)
+ {
+-	if (skb->proto_csum_blank) {
+-		struct iphdr *iph;
+-		unsigned char *th;
++	struct iphdr *iph;
++	unsigned char *th;
++	int err = -EPROTO;
+ 
+-		if (skb->protocol != htons(ETH_P_IP))
+-			goto out;
+-		iph = ip_hdr(skb);
+-		th = skb_network_header(skb) + 4 * iph->ihl;
+-		if (th >= skb_tail_pointer(skb))
+-			goto out;
+-		skb->csum_start = th - skb->head;
+-		switch (iph->protocol) {
+-		case IPPROTO_TCP:
+-			skb->csum_offset = offsetof(struct tcphdr, check);
+-			break;
+-		case IPPROTO_UDP:
+-			skb->csum_offset = offsetof(struct udphdr, check);
+-			break;
+-		default:
+-			if (net_ratelimit())
+-				printk(KERN_ERR "Attempting to checksum a non-"
+-				       "TCP/UDP packet, dropping a protocol"
+-				       " %d packet", iph->protocol);
+-			goto out;
+-		}
+-		if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+-			goto out;
+-		skb->ip_summed = CHECKSUM_PARTIAL;
+-		skb->proto_csum_blank = 0;
++#ifdef CONFIG_XEN
++	if (!skb->proto_csum_blank)
++		return 0;
++#endif
++
++	if (skb->protocol != htons(ETH_P_IP))
++		goto out;
++
++	iph = ip_hdr(skb);
++	th = skb_network_header(skb) + 4 * iph->ihl;
++	if (th >= skb_tail_pointer(skb))
++		goto out;
++
++	skb->csum_start = th - skb->head;
++	switch (iph->protocol) {
++	case IPPROTO_TCP:
++		skb->csum_offset = offsetof(struct tcphdr, check);
++		break;
++	case IPPROTO_UDP:
++		skb->csum_offset = offsetof(struct udphdr, check);
++		break;
++	default:
++		if (net_ratelimit())
++			printk(KERN_ERR "Attempting to checksum a non-"
++			       "TCP/UDP packet, dropping a protocol"
++			       " %d packet", iph->protocol);
++		goto out;
+ 	}
+-	return 0;
++
++	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
++		goto out;
++
++#ifdef CONFIG_XEN
++	skb->ip_summed = CHECKSUM_PARTIAL;
++	skb->proto_csum_blank = 0;
++#endif
++
++	err = 0;
++
+ out:
+-	return -EPROTO;
++	return err;
+ }
+ EXPORT_SYMBOL(skb_checksum_setup);
+ #endif
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.25
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.25
@@ -0,0 +1,28729 @@
+From: kernel.org
+Subject: 2.6.25
+Patch-mainline: 2.6.25
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.25" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:01:19.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:01:53.000000000 +0100
+@@ -39,7 +39,7 @@ config X86
+ 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+ 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
+ 	select HAVE_SYSCALL_TRACEPOINTS
+-	select HAVE_KVM
++	select HAVE_KVM if !XEN
+ 	select HAVE_ARCH_KGDB
+ 	select HAVE_ARCH_TRACEHOOK
+ 	select HAVE_GENERIC_DMA_COHERENT if X86_32
+@@ -227,14 +227,12 @@ config X86_TRAMPOLINE
+ 	default y
+ 
+ config X86_NO_TSS
+-	bool
++	def_bool y
+ 	depends on XEN
+-	default y
+ 
+ config X86_NO_IDT
+-	bool
++	def_bool y
+ 	depends on XEN
+-	default y
+ 
+ config X86_32_LAZY_GS
+ 	def_bool y
+@@ -880,9 +878,8 @@ config X86_VISWS_APIC
+ 	depends on X86_32 && X86_VISWS
+ 
+ config X86_XEN_GENAPIC
+-	bool
++	def_bool y
+ 	depends on X86_64_XEN
+-	default y
+ 
+ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
+ 	bool "Reroute for broken boot IRQs"
+@@ -1329,7 +1326,7 @@ config ARCH_PROC_KCORE_TEXT
+ 
+ config ARCH_SPARSEMEM_DEFAULT
+ 	def_bool y
+-	depends on X86_64
++	depends on X86_64 && !X86_64_XEN
+ 
+ config ARCH_SPARSEMEM_ENABLE
+ 	def_bool y
+@@ -2023,10 +2020,10 @@ config PCI_MMCONFIG
+ 	depends on X86_64 && PCI && ACPI
+ 
+ config XEN_PCIDEV_FRONTEND
+-	bool "Xen PCI Frontend" if X86_64
++	def_bool y
++	prompt "Xen PCI Frontend" if X86_64
+ 	depends on PCI && XEN && (PCI_GOXEN_FE || PCI_GOANY || X86_64)
+  	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.
+@@ -2034,7 +2031,6 @@ config XEN_PCIDEV_FRONTEND
+ 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.
+ 
+--- head-2010-01-18.orig/arch/x86/Kconfig.debug	2009-10-15 11:53:21.000000000 +0200
++++ head-2010-01-18/arch/x86/Kconfig.debug	2009-11-06 10:51:25.000000000 +0100
+@@ -264,6 +264,7 @@ config DEBUG_BOOT_PARAMS
+ 	bool "Debug boot parameters"
+ 	depends on DEBUG_KERNEL
+ 	depends on DEBUG_FS
++	depends on !XEN
+ 	---help---
+ 	  This option will cause struct boot_params to be exported via debugfs.
+ 
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:25.000000000 +0100
+@@ -12,7 +12,6 @@
+ #include <asm/ia32_unistd.h>	
+ #include <asm/thread_info.h>	
+ #include <asm/segment.h>
+-#include <asm/vsyscall32.h>
+ #include <asm/irqflags.h>
+ #include <linux/linkage.h>
+ 
+@@ -99,10 +98,11 @@ ENTRY(ia32_sysenter_target)
+ 	CFI_RESTORE	rcx
+  	movl	%ebp,%ebp		/* zero extension */
+ 	movl	%eax,%eax
++	movl	48-THREAD_SIZE+threadinfo_sysenter_return(%rsp),%r10d
+ 	movl	$__USER32_DS,40(%rsp)
+ 	movq	%rbp,32(%rsp)
+ 	movl	$__USER32_CS,16(%rsp)
+-	movl	$VSYSCALL32_SYSEXIT,8(%rsp)
++	movq	%r10,8(%rsp)
+ 	movq	%rax,(%rsp)
+ 	cld
+ 	SAVE_ARGS 0,0,1
+@@ -582,8 +582,8 @@ ia32_sys_call_table:
+ 	.quad compat_sys_futex		/* 240 */
+ 	.quad compat_sys_sched_setaffinity
+ 	.quad compat_sys_sched_getaffinity
+-	.quad sys32_set_thread_area
+-	.quad sys32_get_thread_area
++	.quad sys_set_thread_area
++	.quad sys_get_thread_area
+ 	.quad compat_sys_io_setup	/* 245 */
+ 	.quad sys_io_destroy
+ 	.quad compat_sys_io_getevents
+@@ -661,7 +661,9 @@ ia32_sys_call_table:
+ 	.quad sys_epoll_pwait
+ 	.quad compat_sys_utimensat	/* 320 */
+ 	.quad compat_sys_signalfd
+-	.quad compat_sys_timerfd
++	.quad sys_timerfd_create
+ 	.quad sys_eventfd
+ 	.quad sys32_fallocate
++	.quad compat_sys_timerfd_settime	/* 325 */
++	.quad compat_sys_timerfd_gettime
+ ia32_syscall_end:
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:51:25.000000000 +0100
+@@ -134,11 +134,10 @@ ifeq ($(CONFIG_X86_64),y)
+ 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
+ 	obj-y				+= vsmp_64.o
+ 
++	obj-$(CONFIG_XEN)		+= nmi_64.o
+ 	time_64-$(CONFIG_XEN)		+= time_32.o
+ 	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
+ 
+ disabled-obj-$(CONFIG_XEN) := early-quirks.o hpet.o i8253.o i8259_$(BITS).o reboot.o \
+ 	smpboot_$(BITS).o tsc_$(BITS).o tsc_sync.o
+-disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += mpparse_64.o
+-%/head_64.o %/head_64.s: asflags-$(CONFIG_XEN) :=
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/boot.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/boot.c	2009-11-06 10:51:25.000000000 +0100
+@@ -112,6 +112,11 @@ char *__init __acpi_map_table(unsigned l
+ 	if (!phys || !size)
+ 		return NULL;
+ 
++#ifdef CONFIG_XEN
++	if (phys + size <= (NR_FIX_ISAMAPS << PAGE_SHIFT))
++		return isa_bus_to_virt(phys);
++#endif
++
+ 	return early_ioremap(phys, size);
+ }
+ void __init __acpi_unmap_table(char *map, unsigned long size)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,95 @@
++/*
++ * sleep.c - x86-specific ACPI sleep support.
++ *
++ *  Copyright (C) 2001-2003 Patrick Mochel
++ *  Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
++ */
++
++#include <linux/acpi.h>
++#include <linux/bootmem.h>
++#include <linux/dmi.h>
++#include <linux/cpumask.h>
++
++#include <asm/smp.h>
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++/* address in low memory of the wakeup routine. */
++unsigned long acpi_wakeup_address = 0;
++unsigned long acpi_realmode_flags;
++extern char wakeup_start, wakeup_end;
++
++extern unsigned long acpi_copy_wakeup_routine(unsigned long);
++#endif
++
++/**
++ * acpi_save_state_mem - save kernel state
++ *
++ * Create an identity mapped page table and copy the wakeup routine to
++ * low memory.
++ */
++int acpi_save_state_mem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	if (!acpi_wakeup_address) {
++		printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
++		return -ENOMEM;
++	}
++	memcpy((void *)acpi_wakeup_address, &wakeup_start,
++	       &wakeup_end - &wakeup_start);
++	acpi_copy_wakeup_routine(acpi_wakeup_address);
++#endif
++
++	return 0;
++}
++
++/*
++ * acpi_restore_state - undo effects of acpi_save_state_mem
++ */
++void acpi_restore_state_mem(void)
++{
++}
++
++
++/**
++ * acpi_reserve_bootmem - do _very_ early ACPI initialisation
++ *
++ * We allocate a page from the first 1MB of memory for the wakeup
++ * routine for when we come back from a sleep state. The
++ * runtime allocator allows specification of <16MB pages, but not
++ * <1MB pages.
++ */
++void __init acpi_reserve_bootmem(void)
++{
++#ifndef CONFIG_ACPI_PV_SLEEP
++	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE*2) {
++		printk(KERN_ERR
++		       "ACPI: Wakeup code way too big, S3 disabled.\n");
++		return;
++	}
++
++	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
++	if (!acpi_wakeup_address)
++		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
++#endif
++}
++
++
++#ifndef CONFIG_ACPI_PV_SLEEP
++static int __init acpi_sleep_setup(char *str)
++{
++	while ((str != NULL) && (*str != '\0')) {
++		if (strncmp(str, "s3_bios", 7) == 0)
++			acpi_realmode_flags |= 1;
++		if (strncmp(str, "s3_mode", 7) == 0)
++			acpi_realmode_flags |= 2;
++		if (strncmp(str, "s3_beep", 7) == 0)
++			acpi_realmode_flags |= 4;
++		str = strchr(str, ',');
++		if (str != NULL)
++			str += strspn(str, ", \t");
++	}
++	return 1;
++}
++
++__setup("acpi_sleep=", acpi_sleep_setup);
++#endif /* CONFIG_ACPI_PV_SLEEP */
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,117 +0,0 @@
+-/*
+- * sleep.c - x86-specific ACPI sleep support.
+- *
+- *  Copyright (C) 2001-2003 Patrick Mochel
+- *  Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
+- */
+-
+-#include <linux/acpi.h>
+-#include <linux/bootmem.h>
+-#include <linux/dmi.h>
+-#include <linux/cpumask.h>
+-
+-#include <asm/smp.h>
+-
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-/* address in low memory of the wakeup routine. */
+-unsigned long acpi_wakeup_address = 0;
+-unsigned long acpi_realmode_flags;
+-extern char wakeup_start, wakeup_end;
+-
+-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+-#endif
+-
+-/**
+- * acpi_save_state_mem - save kernel state
+- *
+- * Create an identity mapped page table and copy the wakeup routine to
+- * low memory.
+- */
+-int acpi_save_state_mem(void)
+-{
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-	if (!acpi_wakeup_address)
+-		return 1;
+-	memcpy((void *)acpi_wakeup_address, &wakeup_start,
+-	       &wakeup_end - &wakeup_start);
+-	acpi_copy_wakeup_routine(acpi_wakeup_address);
+-#endif
+-	return 0;
+-}
+-
+-/*
+- * acpi_restore_state - undo effects of acpi_save_state_mem
+- */
+-void acpi_restore_state_mem(void)
+-{
+-}
+-
+-/**
+- * acpi_reserve_bootmem - do _very_ early ACPI initialisation
+- *
+- * We allocate a page from the first 1MB of memory for the wakeup
+- * routine for when we come back from a sleep state. The
+- * runtime allocator allows specification of <16MB pages, but not
+- * <1MB pages.
+- */
+-void __init acpi_reserve_bootmem(void)
+-{
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-	if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) {
+-		printk(KERN_ERR
+-		       "ACPI: Wakeup code way too big, S3 disabled.\n");
+-		return;
+-	}
+-
+-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
+-	if (!acpi_wakeup_address)
+-		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
+-#endif
+-}
+-
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-static int __init acpi_sleep_setup(char *str)
+-{
+-	while ((str != NULL) && (*str != '\0')) {
+-		if (strncmp(str, "s3_bios", 7) == 0)
+-			acpi_realmode_flags |= 1;
+-		if (strncmp(str, "s3_mode", 7) == 0)
+-			acpi_realmode_flags |= 2;
+-		if (strncmp(str, "s3_beep", 7) == 0)
+-			acpi_realmode_flags |= 4;
+-		str = strchr(str, ',');
+-		if (str != NULL)
+-			str += strspn(str, ", \t");
+-	}
+-	return 1;
+-}
+-
+-__setup("acpi_sleep=", acpi_sleep_setup);
+-
+-/* Ouch, we want to delete this. We already have better version in userspace, in
+-   s2ram from suspend.sf.net project */
+-static __init int reset_videomode_after_s3(const struct dmi_system_id *d)
+-{
+-	acpi_realmode_flags |= 2;
+-	return 0;
+-}
+-
+-static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
+-	{			/* Reset video mode after returning from ACPI S3 sleep */
+-	 .callback = reset_videomode_after_s3,
+-	 .ident = "Toshiba Satellite 4030cdt",
+-	 .matches = {
+-		     DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+-		     },
+-	 },
+-	{}
+-};
+-
+-static int __init acpisleep_dmi_init(void)
+-{
+-	dmi_check_system(acpisleep_dmi_table);
+-	return 0;
+-}
+-
+-core_initcall(acpisleep_dmi_init);
+-#endif /* CONFIG_ACPI_PV_SLEEP */
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,125 +0,0 @@
+-/*
+- *  acpi.c - Architecture-Specific Low-Level ACPI Support
+- *
+- *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+- *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
+- *  Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
+- *  Copyright (C) 2002 Andi Kleen, SuSE Labs (x86-64 port)
+- *  Copyright (C) 2003 Pavel Machek, SuSE Labs
+- *
+- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- *
+- *  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/stddef.h>
+-#include <linux/slab.h>
+-#include <linux/pci.h>
+-#include <linux/bootmem.h>
+-#include <linux/acpi.h>
+-#include <linux/cpumask.h>
+-
+-#include <asm/mpspec.h>
+-#include <asm/io.h>
+-#include <asm/apic.h>
+-#include <asm/apicdef.h>
+-#include <asm/page.h>
+-#include <asm/pgtable.h>
+-#include <asm/pgalloc.h>
+-#include <asm/io_apic.h>
+-#include <asm/proto.h>
+-#include <asm/tlbflush.h>
+-
+-/* --------------------------------------------------------------------------
+-                              Low-Level Sleep Support
+-   -------------------------------------------------------------------------- */
+-
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-/* address in low memory of the wakeup routine. */
+-unsigned long acpi_wakeup_address = 0;
+-unsigned long acpi_realmode_flags;
+-extern char wakeup_start, wakeup_end;
+-
+-extern unsigned long acpi_copy_wakeup_routine(unsigned long);
+-#endif
+-
+-/**
+- * acpi_save_state_mem - save kernel state
+- *
+- * Create an identity mapped page table and copy the wakeup routine to
+- * low memory.
+- */
+-int acpi_save_state_mem(void)
+-{
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-	memcpy((void *)acpi_wakeup_address, &wakeup_start,
+-	       &wakeup_end - &wakeup_start);
+-	acpi_copy_wakeup_routine(acpi_wakeup_address);
+-#endif
+-	return 0;
+-}
+-
+-/*
+- * acpi_restore_state
+- */
+-void acpi_restore_state_mem(void)
+-{
+-}
+-
+-/**
+- * acpi_reserve_bootmem - do _very_ early ACPI initialisation
+- *
+- * We allocate a page in low memory for the wakeup
+- * routine for when we come back from a sleep state. The
+- * runtime allocator allows specification of <16M pages, but not
+- * <1M pages.
+- */
+-void __init acpi_reserve_bootmem(void)
+-{
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE*2);
+-	if ((&wakeup_end - &wakeup_start) > (PAGE_SIZE*2))
+-		printk(KERN_CRIT
+-		       "ACPI: Wakeup code way too big, will crash on attempt"
+-		       " to suspend\n");
+-#endif
+-}
+-
+-#ifndef CONFIG_ACPI_PV_SLEEP
+-static int __init acpi_sleep_setup(char *str)
+-{
+-	while ((str != NULL) && (*str != '\0')) {
+-		if (strncmp(str, "s3_bios", 7) == 0)
+-			acpi_realmode_flags |= 1;
+-		if (strncmp(str, "s3_mode", 7) == 0)
+-			acpi_realmode_flags |= 2;
+-		if (strncmp(str, "s3_beep", 7) == 0)
+-			acpi_realmode_flags |= 4;
+-		str = strchr(str, ',');
+-		if (str != NULL)
+-			str += strspn(str, ", \t");
+-	}
+-
+-	return 1;
+-}
+-
+-__setup("acpi_sleep=", acpi_sleep_setup);
+-#endif				/* CONFIG_ACPI_PV_SLEEP */
+-
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -86,7 +86,7 @@ int setup_profiling_timer(unsigned int m
+  * This initializes the IO-APIC and APIC hardware if this is
+  * a UP kernel.
+  */
+-int __init APIC_init_uniprocessor (void)
++int __init APIC_init_uniprocessor(void)
+ {
+ #ifdef CONFIG_X86_IO_APIC
+ 	if (smp_found_config)
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -34,34 +34,17 @@
+ #include <asm/hpet.h>
+ #include <asm/idle.h>
+ 
+-int apic_verbosity;
++int disable_apic;
+ 
+ /*
+- * 'what should we do if we get a hw irq event on an illegal vector'.
+- * each architecture has to answer this themselves.
++ * Debug level, exported for io_apic.c
+  */
+-void ack_bad_irq(unsigned int irq)
+-{
+-	printk("unexpected IRQ trap at irq %02x\n", irq);
+-	/*
+-	 * Currently unexpected vectors happen only on SMP and APIC.
+-	 * We _must_ ack these because every local APIC has only N
+-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+-	 * holds up an irq slot - in excessive cases (when multiple
+-	 * unexpected vectors occur) that might lock up the APIC
+-	 * completely.
+-	 * But don't ack when the APIC is disabled. -AK
+-	 */
+-	if (!disable_apic)
+-		ack_APIC_irq();
+-}
+-
+-int setup_profiling_timer(unsigned int multiplier)
+-{
+-	return -EINVAL;
+-}
++int apic_verbosity;
+ 
+-void smp_local_timer_interrupt(void)
++/*
++ * The guts of the apic timer interrupt
++ */
++static void local_apic_timer_interrupt(void)
+ {
+ #ifndef CONFIG_XEN
+ 	int cpu = smp_processor_id();
+@@ -121,11 +104,34 @@ void smp_apic_timer_interrupt(struct pt_
+ 	 */
+ 	exit_idle();
+ 	irq_enter();
+-	smp_local_timer_interrupt();
++	local_apic_timer_interrupt();
+ 	irq_exit();
+ 	set_irq_regs(old_regs);
+ }
+ 
++int setup_profiling_timer(unsigned int multiplier)
++{
++	return -EINVAL;
++}
++
++/*
++ * This initializes the IO-APIC and APIC hardware if this is
++ * a UP kernel.
++ */
++int __init APIC_init_uniprocessor(void)
++{
++#ifdef CONFIG_X86_IO_APIC
++	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
++		setup_IO_APIC();
++#endif
++
++	return 1;
++}
++
++/*
++ * Local APIC interrupts
++ */
++
+ /*
+  * This interrupt should _never_ happen with our APIC/SMP architecture
+  */
+@@ -150,7 +156,6 @@ asmlinkage void smp_spurious_interrupt(v
+ /*
+  * This interrupt should never happen with our APIC/SMP architecture
+  */
+-
+ asmlinkage void smp_error_interrupt(void)
+ {
+ 	unsigned int v, v1;
+@@ -178,19 +183,3 @@ asmlinkage void smp_error_interrupt(void
+ 		smp_processor_id(), v , v1);
+ 	irq_exit();
+ }
+-
+-int disable_apic;
+-
+-/*
+- * This initializes the IO-APIC and APIC hardware if this is
+- * a UP kernel.
+- */
+-int __init APIC_init_uniprocessor (void)
+-{
+-#ifdef CONFIG_X86_IO_APIC
+-	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
+-		setup_IO_APIC();
+-#endif
+-
+-	return 1;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/asm-offsets_32.c	2009-11-06 10:51:25.000000000 +0100
+@@ -24,8 +24,10 @@
+ #include <xen/interface/xen.h>
+ #endif
+ 
++#ifdef CONFIG_LGUEST_GUEST
+ #include <linux/lguest.h>
+ #include "../../../drivers/lguest/lg.h"
++#endif
+ 
+ /* workaround for a warning with -Wmissing-prototypes */
+ void foo(void);
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -27,45 +27,50 @@
+ #include "cpu.h"
+ 
+ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+-	[GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },
+-	[GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },
+-	[GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },
+-	[GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },
++	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
++	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
++	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
++	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
+ #ifndef CONFIG_XEN
+ 	/*
+ 	 * Segments used for calling PnP BIOS have byte granularity.
+ 	 * They code segments and data segments have fixed 64k limits,
+ 	 * the transfer segment sizes are set at run time.
+ 	 */
+-	[GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+-	[GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */
+-	[GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */
+-	[GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */
++	/* 32-bit code */
++	[GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } },
++	/* 16-bit code */
++	[GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
++	/* 16-bit data */
++	[GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
++	/* 16-bit data */
++	[GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
++	/* 16-bit data */
++	[GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
+ 	/*
+ 	 * The APM segments have byte granularity and their bases
+ 	 * are set at run time.  All have 64k limits.
+ 	 */
+-	[GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
++	/* 32-bit code */
++	[GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } },
+ 	/* 16-bit code */
+-	[GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
+-	[GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
++	[GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
++	/* data */
++	[GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },
+ 
+-	[GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
++	[GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
+ #endif
+-	[GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
++	[GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
+ } };
+ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+ 
++__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
++
+ static int cachesize_override __cpuinitdata = -1;
+-static int disable_x86_fxsr __cpuinitdata;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+-static int disable_x86_sep __cpuinitdata;
+ 
+ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
+ 
+-extern int disable_pse;
+-
+ static void __cpuinit default_init(struct cpuinfo_x86 * c)
+ {
+ 	/* Not much we can do here... */
+@@ -214,16 +219,8 @@ static void __cpuinit get_cpu_vendor(str
+ 
+ static int __init x86_fxsr_setup(char * s)
+ {
+-	/* Tell all the other CPUs to not use it... */
+-	disable_x86_fxsr = 1;
+-
+-	/*
+-	 * ... and clear the bits early in the boot_cpu_data
+-	 * so that the bootup process doesn't try to do this
+-	 * either.
+-	 */
+-	clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability);
+-	clear_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability);
++	setup_clear_cpu_cap(X86_FEATURE_FXSR);
++	setup_clear_cpu_cap(X86_FEATURE_XMM);
+ 	return 1;
+ }
+ __setup("nofxsr", x86_fxsr_setup);
+@@ -231,7 +228,7 @@ __setup("nofxsr", x86_fxsr_setup);
+ 
+ static int __init x86_sep_setup(char * s)
+ {
+-	disable_x86_sep = 1;
++	setup_clear_cpu_cap(X86_FEATURE_SEP);
+ 	return 1;
+ }
+ __setup("nosep", x86_sep_setup);
+@@ -268,10 +265,10 @@ static int __cpuinit have_cpuid_p(void)
+ void __init cpu_detect(struct cpuinfo_x86 *c)
+ {
+ 	/* Get vendor name */
+-	cpuid(0x00000000, &c->cpuid_level,
+-	      (int *)&c->x86_vendor_id[0],
+-	      (int *)&c->x86_vendor_id[8],
+-	      (int *)&c->x86_vendor_id[4]);
++	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
++	      (unsigned int *)&c->x86_vendor_id[0],
++	      (unsigned int *)&c->x86_vendor_id[8],
++	      (unsigned int *)&c->x86_vendor_id[4]);
+ 
+ 	c->x86 = 4;
+ 	if (c->cpuid_level >= 0x00000001) {
+@@ -284,9 +281,38 @@ void __init cpu_detect(struct cpuinfo_x8
+ 		if (c->x86 >= 0x6)
+ 			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+ 		c->x86_mask = tfms & 15;
+-		if (cap0 & (1<<19))
++		if (cap0 & (1<<19)) {
+ 			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
++			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
++		}
++	}
++}
++static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
++{
++	u32 tfms, xlvl;
++	unsigned int ebx;
++
++	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++	if (have_cpuid_p()) {
++		/* Intel-defined flags: level 0x00000001 */
++		if (c->cpuid_level >= 0x00000001) {
++			u32 capability, excap;
++			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
++			c->x86_capability[0] = capability;
++			c->x86_capability[4] = excap;
++		}
++
++		/* AMD-defined flags: level 0x80000001 */
++		xlvl = cpuid_eax(0x80000000);
++		if ((xlvl & 0xffff0000) == 0x80000000) {
++			if (xlvl >= 0x80000001) {
++				c->x86_capability[1] = cpuid_edx(0x80000001);
++				c->x86_capability[6] = cpuid_ecx(0x80000001);
++			}
++		}
++
+ 	}
++
+ }
+ 
+ /* Do minimum CPU detection early.
+@@ -300,6 +326,7 @@ static void __init early_cpu_detect(void
+ 	struct cpuinfo_x86 *c = &boot_cpu_data;
+ 
+ 	c->x86_cache_alignment = 32;
++	c->x86_clflush_size = 32;
+ 
+ 	if (!have_cpuid_p())
+ 		return;
+@@ -307,19 +334,30 @@ static void __init early_cpu_detect(void
+ 	cpu_detect(c);
+ 
+ 	get_cpu_vendor(c, 1);
++
++	switch (c->x86_vendor) {
++	case X86_VENDOR_AMD:
++		early_init_amd(c);
++		break;
++	case X86_VENDOR_INTEL:
++		early_init_intel(c);
++		break;
++	}
++
++	early_get_cap(c);
+ }
+ 
+ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+ {
+ 	u32 tfms, xlvl;
+-	int ebx;
++	unsigned int ebx;
+ 
+ 	if (have_cpuid_p()) {
+ 		/* Get vendor name */
+-		cpuid(0x00000000, &c->cpuid_level,
+-		      (int *)&c->x86_vendor_id[0],
+-		      (int *)&c->x86_vendor_id[8],
+-		      (int *)&c->x86_vendor_id[4]);
++		cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
++		      (unsigned int *)&c->x86_vendor_id[0],
++		      (unsigned int *)&c->x86_vendor_id[8],
++		      (unsigned int *)&c->x86_vendor_id[4]);
+ 		
+ 		get_cpu_vendor(c, 0);
+ 		/* Initialize the standard set of capabilities */
+@@ -366,8 +404,6 @@ static void __cpuinit generic_identify(s
+ 		init_scattered_cpuid_features(c);
+ 	}
+ 
+-	early_intel_workaround(c);
+-
+ #ifdef CONFIG_X86_HT
+ 	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+ #endif
+@@ -401,7 +437,7 @@ __setup("serialnumber", x86_serial_nr_se
+ /*
+  * This does the hard work of actually picking apart the CPU stuff...
+  */
+-static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+ {
+ 	int i;
+ 
+@@ -427,20 +463,9 @@ static void __cpuinit identify_cpu(struc
+ 
+ 	generic_identify(c);
+ 
+-	printk(KERN_DEBUG "CPU: After generic identify, caps:");
+-	for (i = 0; i < NCAPINTS; i++)
+-		printk(" %08lx", c->x86_capability[i]);
+-	printk("\n");
+-
+-	if (this_cpu->c_identify) {
++	if (this_cpu->c_identify)
+ 		this_cpu->c_identify(c);
+ 
+-		printk(KERN_DEBUG "CPU: After vendor identify, caps:");
+-		for (i = 0; i < NCAPINTS; i++)
+-			printk(" %08lx", c->x86_capability[i]);
+-		printk("\n");
+-	}
+-
+ 	/*
+ 	 * Vendor-specific initialization.  In this section we
+ 	 * canonicalize the feature flags, meaning if there are
+@@ -462,23 +487,6 @@ static void __cpuinit identify_cpu(struc
+ 	 * we do "generic changes."
+ 	 */
+ 
+-	/* TSC disabled? */
+-	if ( tsc_disable )
+-		clear_bit(X86_FEATURE_TSC, c->x86_capability);
+-
+-	/* FXSR disabled? */
+-	if (disable_x86_fxsr) {
+-		clear_bit(X86_FEATURE_FXSR, c->x86_capability);
+-		clear_bit(X86_FEATURE_XMM, c->x86_capability);
+-	}
+-
+-	/* SEP disabled? */
+-	if (disable_x86_sep)
+-		clear_bit(X86_FEATURE_SEP, c->x86_capability);
+-
+-	if (disable_pse)
+-		clear_bit(X86_FEATURE_PSE, c->x86_capability);
+-
+ 	/* If the model name is still unset, do table lookup. */
+ 	if ( !c->x86_model_id[0] ) {
+ 		char *p;
+@@ -491,13 +499,6 @@ static void __cpuinit identify_cpu(struc
+ 				c->x86, c->x86_model);
+ 	}
+ 
+-	/* Now the feature flags better reflect actual CPU features! */
+-
+-	printk(KERN_DEBUG "CPU: After all inits, caps:");
+-	for (i = 0; i < NCAPINTS; i++)
+-		printk(" %08lx", c->x86_capability[i]);
+-	printk("\n");
+-
+ 	/*
+ 	 * On SMP, boot_cpu_data holds the common feature set between
+ 	 * all CPUs; so make sure that we indicate which features are
+@@ -510,8 +511,14 @@ static void __cpuinit identify_cpu(struc
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
++	/* Clear all flags overriden by options */
++	for (i = 0; i < NCAPINTS; i++)
++		c->x86_capability[i] &= ~cleared_cpu_caps[i];
++
+ 	/* Init Machine Check Exception if available. */
+ 	mcheck_init(c);
++
++	select_idle_routine(c);
+ }
+ 
+ void __init identify_boot_cpu(void)
+@@ -519,7 +526,6 @@ void __init identify_boot_cpu(void)
+ 	identify_cpu(&boot_cpu_data);
+ 	sysenter_setup();
+ 	enable_sep_cpu();
+-	mtrr_bp_init();
+ }
+ 
+ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+@@ -576,6 +582,13 @@ void __cpuinit detect_ht(struct cpuinfo_
+ }
+ #endif
+ 
++static __init int setup_noclflush(char *arg)
++{
++	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
++	return 1;
++}
++__setup("noclflush", setup_noclflush);
++
+ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+ {
+ 	char *vendor = NULL;
+@@ -599,6 +612,17 @@ void __cpuinit print_cpu_info(struct cpu
+ 		printk("\n");
+ }
+ 
++static __init int setup_disablecpuid(char *arg)
++{
++	int bit;
++	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
++		setup_clear_cpu_cap(bit);
++	else
++		return 0;
++	return 1;
++}
++__setup("clearcpuid=", setup_disablecpuid);
++
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+ /* This is hacky. :)
+@@ -608,16 +632,6 @@ cpumask_t cpu_initialized __cpuinitdata 
+  * They will insert themselves into the cpu_devs structure.
+  * Then, when cpu_init() is called, we can just iterate over that array.
+  */
+-
+-extern int intel_cpu_init(void);
+-extern int cyrix_init_cpu(void);
+-extern int nsc_init_cpu(void);
+-extern int amd_init_cpu(void);
+-extern int centaur_init_cpu(void);
+-extern int transmeta_init_cpu(void);
+-extern int nexgen_init_cpu(void);
+-extern int umc_init_cpu(void);
+-
+ void __init early_cpu_init(void)
+ {
+ 	intel_cpu_init();
+@@ -629,21 +643,13 @@ void __init early_cpu_init(void)
+ 	nexgen_init_cpu();
+ 	umc_init_cpu();
+ 	early_cpu_detect();
+-
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	/* pse is not compatible with on-the-fly unmapping,
+-	 * disable it even if the cpus claim to support it.
+-	 */
+-	clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+-	disable_pse = 1;
+-#endif
+ }
+ 
+ /* Make sure %fs is initialized properly in idle threads */
+-struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
++struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+ {
+ 	memset(regs, 0, sizeof(struct pt_regs));
+-	regs->xfs = __KERNEL_PERCPU;
++	regs->fs = __KERNEL_PERCPU;
+ 	return regs;
+ }
+ 
+@@ -651,7 +657,7 @@ struct pt_regs * __devinit idle_regs(str
+  * it's on the real one. */
+ void switch_to_new_gdt(void)
+ {
+-	struct Xgt_desc_struct gdt_descr;
++	struct desc_ptr gdt_descr;
+ 	unsigned long va, frames[16];
+ 	int f;
+ 
+@@ -694,12 +700,6 @@ void __cpuinit cpu_init(void)
+ 
+ 	if (cpu_has_vme || cpu_has_de)
+ 		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+-	if (tsc_disable && cpu_has_tsc) {
+-		printk(KERN_NOTICE "Disabling TSC...\n");
+-		/**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/
+-		clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
+-		set_in_cr4(X86_CR4_TSD);
+-	}
+ 
+ 	switch_to_new_gdt();
+ 
+@@ -712,7 +712,7 @@ void __cpuinit cpu_init(void)
+ 		BUG();
+ 	enter_lazy_tlb(&init_mm, curr);
+ 
+-	load_esp0(t, thread);
++	load_sp0(t, thread);
+ 
+ 	load_LDT(&init_mm.context);
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/mtrr/main-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -33,7 +33,7 @@ struct mtrr_ops generic_mtrr_ops = {
+ 
+ struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
+ unsigned int num_var_ranges;
+-unsigned int *usage_table;
++unsigned int mtrr_usage_table[MAX_VAR_RANGES];
+ 
+ static void __init set_num_var_ranges(void)
+ {
+@@ -52,17 +52,12 @@ static void __init init_table(void)
+ 	int i, max;
+ 
+ 	max = num_var_ranges;
+-	if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
+-	    == NULL) {
+-		printk(KERN_ERR "mtrr: could not allocate\n");
+-		return;
+-	}
+ 	for (i = 0; i < max; i++)
+-		usage_table[i] = 0;
++		mtrr_usage_table[i] = 0;
+ }
+ 
+ int mtrr_add_page(unsigned long base, unsigned long size, 
+-		  unsigned int type, char increment)
++		  unsigned int type, bool increment)
+ {
+ 	int error;
+ 	struct xen_platform_op op;
+@@ -81,7 +76,7 @@ int mtrr_add_page(unsigned long base, un
+ 	}
+ 
+ 	if (increment)
+-		++usage_table[op.u.add_memtype.reg];
++		++mtrr_usage_table[op.u.add_memtype.reg];
+ 
+ 	mutex_unlock(&mtrr_mutex);
+ 
+@@ -103,7 +98,7 @@ static int mtrr_check(unsigned long base
+ 
+ int
+ mtrr_add(unsigned long base, unsigned long size, unsigned int type,
+-	 char increment)
++	 bool increment)
+ {
+ 	if (mtrr_check(base, size))
+ 		return -EINVAL;
+@@ -136,11 +131,11 @@ int mtrr_del_page(int reg, unsigned long
+ 			goto out;
+ 		}
+ 	}
+-	if (usage_table[reg] < 1) {
++	if (mtrr_usage_table[reg] < 1) {
+ 		printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
+ 		goto out;
+ 	}
+-	if (--usage_table[reg] < 1) {
++	if (--mtrr_usage_table[reg] < 1) {
+ 		op.cmd = XENPF_del_memtype;
+ 		op.u.del_memtype.handle = 0;
+ 		op.u.del_memtype.reg    = reg;
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -7,7 +7,6 @@
+ #include <linux/kexec.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+-#include <linux/efi.h>
+ #include <linux/pfn.h>
+ #include <linux/uaccess.h>
+ #include <linux/suspend.h>
+@@ -18,11 +17,6 @@
+ #include <asm/setup.h>
+ #include <xen/interface/memory.h>
+ 
+-#ifdef CONFIG_EFI
+-int efi_enabled = 0;
+-EXPORT_SYMBOL(efi_enabled);
+-#endif
+-
+ struct e820map e820;
+ struct change_member {
+ 	struct e820entry *pbios; /* pointer to original bios entry */
+@@ -38,26 +32,6 @@ unsigned long pci_mem_start = 0x10000000
+ EXPORT_SYMBOL(pci_mem_start);
+ #endif
+ extern int user_defined_memmap;
+-struct resource data_resource = {
+-	.name	= "Kernel data",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-struct resource code_resource = {
+-	.name	= "Kernel code",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-struct resource bss_resource = {
+-	.name	= "Kernel bss",
+-	.start	= 0,
+-	.end	= 0,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+ 
+ static struct resource system_rom_resource = {
+ 	.name	= "System ROM",
+@@ -112,60 +86,6 @@ static struct resource video_rom_resourc
+ 	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
+ };
+ 
+-static struct resource video_ram_resource = {
+-	.name	= "Video RAM area",
+-	.start	= 0xa0000,
+-	.end	= 0xbffff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+-};
+-
+-static struct resource standard_io_resources[] = { {
+-	.name	= "dma1",
+-	.start	= 0x0000,
+-	.end	= 0x001f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic1",
+-	.start	= 0x0020,
+-	.end	= 0x0021,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer0",
+-	.start	= 0x0040,
+-	.end    = 0x0043,
+-	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name   = "timer1",
+-	.start  = 0x0050,
+-	.end    = 0x0053,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "keyboard",
+-	.start	= 0x0060,
+-	.end	= 0x006f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma page reg",
+-	.start	= 0x0080,
+-	.end	= 0x008f,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "pic2",
+-	.start	= 0x00a0,
+-	.end	= 0x00a1,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "dma2",
+-	.start	= 0x00c0,
+-	.end	= 0x00df,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-}, {
+-	.name	= "fpu",
+-	.start	= 0x00f0,
+-	.end	= 0x00ff,
+-	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+-} };
+-
+ #define ROMSIGNATURE 0xaa55
+ 
+ static int __init romsignature(const unsigned char *rom)
+@@ -272,10 +192,9 @@ static struct e820map machine_e820;
+  * Request address space for all standard RAM and ROM resources
+  * and also for regions reported as reserved by the e820.
+  */
+-static void __init
+-legacy_init_iomem_resources(struct resource *code_resource,
+-			    struct resource *data_resource,
+-			    struct resource *bss_resource)
++void __init init_iomem_resources(struct resource *code_resource,
++		struct resource *data_resource,
++		struct resource *bss_resource)
+ {
+ 	int i;
+ 
+@@ -324,39 +243,6 @@ legacy_init_iomem_resources(struct resou
+ 
+ #undef e820
+ 
+-/*
+- * Request address space for all standard resources
+- *
+- * This is called just before pcibios_init(), which is also a
+- * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
+- */
+-static int __init request_standard_resources(void)
+-{
+-	int i;
+-
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return 0;
+-
+-	printk("Setting up standard PCI resources\n");
+-	if (efi_enabled)
+-		efi_initialize_iomem_resources(&code_resource,
+-				&data_resource, &bss_resource);
+-	else
+-		legacy_init_iomem_resources(&code_resource,
+-				&data_resource, &bss_resource);
+-
+-	/* EFI systems may still have VGA */
+-	request_resource(&iomem_resource, &video_ram_resource);
+-
+-	/* request I/O space for devices used on all i[345]86 PCs */
+-	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+-		request_resource(&ioport_resource, &standard_io_resources[i]);
+-	return 0;
+-}
+-
+-subsys_initcall(request_standard_resources);
+-
+ #if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)
+ /**
+  * e820_mark_nosave_regions - Find the ranges of physical addresses that do not
+@@ -393,19 +279,17 @@ void __init add_memory_region(unsigned l
+ {
+ 	int x;
+ 
+-	if (!efi_enabled) {
+-       		x = e820.nr_map;
++	x = e820.nr_map;
+ 
+-		if (x == E820MAX) {
+-		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+-		    return;
+-		}
+-
+-		e820.map[x].addr = start;
+-		e820.map[x].size = size;
+-		e820.map[x].type = type;
+-		e820.nr_map++;
++	if (x == E820MAX) {
++		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++		return;
+ 	}
++
++	e820.map[x].addr = start;
++	e820.map[x].size = size;
++	e820.map[x].type = type;
++	e820.nr_map++;
+ } /* add_memory_region */
+ 
+ /*
+@@ -642,29 +526,6 @@ int __init copy_e820_map(struct e820entr
+ }
+ 
+ /*
+- * Callback for efi_memory_walk.
+- */
+-static int __init
+-efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
+-{
+-	unsigned long *max_pfn = arg, pfn;
+-
+-	if (start < end) {
+-		pfn = PFN_UP(end -1);
+-		if (pfn > *max_pfn)
+-			*max_pfn = pfn;
+-	}
+-	return 0;
+-}
+-
+-static int __init
+-efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
+-{
+-	memory_present(0, PFN_UP(start), PFN_DOWN(end));
+-	return 0;
+-}
+-
+-/*
+  * Find the highest page frame number we have available
+  */
+ void __init find_max_pfn(void)
+@@ -672,11 +533,6 @@ void __init find_max_pfn(void)
+ 	int i;
+ 
+ 	max_pfn = 0;
+-	if (efi_enabled) {
+-		efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+-		efi_memmap_walk(efi_memory_present_wrapper, NULL);
+-		return;
+-	}
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		unsigned long start, end;
+@@ -694,34 +550,12 @@ void __init find_max_pfn(void)
+ }
+ 
+ /*
+- * Free all available memory for boot time allocation.  Used
+- * as a callback function by efi_memory_walk()
+- */
+-
+-static int __init
+-free_available_memory(unsigned long start, unsigned long end, void *arg)
+-{
+-	/* check max_low_pfn */
+-	if (start >= (max_low_pfn << PAGE_SHIFT))
+-		return 0;
+-	if (end >= (max_low_pfn << PAGE_SHIFT))
+-		end = max_low_pfn << PAGE_SHIFT;
+-	if (start < end)
+-		free_bootmem(start, end - start);
+-
+-	return 0;
+-}
+-/*
+  * Register fully available low RAM pages with the bootmem allocator.
+  */
+ void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+ {
+ 	int i;
+ 
+-	if (efi_enabled) {
+-		efi_memmap_walk(free_available_memory, NULL);
+-		return;
+-	}
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		unsigned long curr_pfn, last_pfn, size;
+ 		/*
+@@ -842,56 +676,12 @@ void __init print_memory_map(char *who)
+ 	}
+ }
+ 
+-static __init __always_inline void efi_limit_regions(unsigned long long size)
+-{
+-	unsigned long long current_addr = 0;
+-	efi_memory_desc_t *md, *next_md;
+-	void *p, *p1;
+-	int i, j;
+-
+-	j = 0;
+-	p1 = memmap.map;
+-	for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
+-		md = p;
+-		next_md = p1;
+-		current_addr = md->phys_addr +
+-			PFN_PHYS(md->num_pages);
+-		if (is_available_memory(md)) {
+-			if (md->phys_addr >= size) continue;
+-			memcpy(next_md, md, memmap.desc_size);
+-			if (current_addr >= size) {
+-				next_md->num_pages -=
+-					PFN_UP(current_addr-size);
+-			}
+-			p1 += memmap.desc_size;
+-			next_md = p1;
+-			j++;
+-		} else if ((md->attribute & EFI_MEMORY_RUNTIME) ==
+-			   EFI_MEMORY_RUNTIME) {
+-			/* In order to make runtime services
+-			 * available we have to include runtime
+-			 * memory regions in memory map */
+-			memcpy(next_md, md, memmap.desc_size);
+-			p1 += memmap.desc_size;
+-			next_md = p1;
+-			j++;
+-		}
+-	}
+-	memmap.nr_map = j;
+-	memmap.map_end = memmap.map +
+-		(memmap.nr_map * memmap.desc_size);
+-}
+-
+ void __init limit_regions(unsigned long long size)
+ {
+ 	unsigned long long current_addr = 0;
+ 	int i;
+ 
+ 	print_memory_map("limit_regions start");
+-	if (efi_enabled) {
+-		efi_limit_regions(size);
+-		return;
+-	}
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		current_addr = e820.map[i].addr + e820.map[i].size;
+ 		if (current_addr < size)
+@@ -1043,3 +833,44 @@ static int __init parse_memmap(char *arg
+ 	return 0;
+ }
+ early_param("memmap", parse_memmap);
++
++#ifndef CONFIG_XEN
++void __init update_memory_range(u64 start, u64 size, unsigned old_type,
++				unsigned new_type)
++{
++	int i;
++
++	BUG_ON(old_type == new_type);
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		u64 final_start, final_end;
++		if (ei->type != old_type)
++			continue;
++		/* totally covered? */
++		if (ei->addr >= start && ei->size <= size) {
++			ei->type = new_type;
++			continue;
++		}
++		/* partially covered */
++		final_start = max(start, ei->addr);
++		final_end = min(start + size, ei->addr + ei->size);
++		if (final_start >= final_end)
++			continue;
++		add_memory_region(final_start, final_end - final_start,
++					 new_type);
++	}
++}
++
++void __init update_e820(void)
++{
++	u8 nr_map;
++
++	nr_map = e820.nr_map;
++	if (sanitize_e820_map(e820.map, &nr_map))
++		return;
++	e820.nr_map = nr_map;
++	printk(KERN_INFO "modified physical RAM map:\n");
++	print_memory_map("modified");
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:01:22.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:03:21.000000000 +0100
+@@ -1,4 +1,4 @@
+-/* 
++/*
+  * Handle the memory map.
+  * The functions here do the job until bootmem takes over.
+  *
+@@ -26,6 +26,7 @@
+ #include <asm/proto.h>
+ #include <asm/setup.h>
+ #include <asm/sections.h>
++#include <asm/kdebug.h>
+ #include <xen/interface/memory.h>
+ 
+ struct e820map e820 __initdata;
+@@ -33,98 +34,105 @@ struct e820map e820 __initdata;
+ struct e820map machine_e820;
+ #endif
+ 
+-/* 
++/*
+  * PFN of last memory page.
+  */
+-unsigned long end_pfn; 
+-EXPORT_SYMBOL(end_pfn);
++unsigned long end_pfn;
+ 
+ #ifndef CONFIG_XEN
+-/* 
++/*
+  * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
+  * The direct mapping extends to end_pfn_map, so that we can directly access
+  * apertures, ACPI and other tables without having to play with fixmaps.
+- */ 
+-unsigned long end_pfn_map; 
++ */
++unsigned long end_pfn_map;
+ #endif
+ 
+-/* 
++/*
+  * Last pfn which the user wants to use.
+  */
+ static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
+ 
+-extern struct resource code_resource, data_resource, bss_resource;
+-
+-/* 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)
+-{ 
+-	unsigned long addr = *addrp, last = addr + size; 
++/*
++ * Early reserved memory areas.
++ */
++#define MAX_EARLY_RES 20
+ 
++struct early_res {
++	unsigned long start, end;
++	char name[16];
++};
++static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+ #ifndef CONFIG_XEN
+-	/* various gunk below that needed for SMP startup */
+-	if (addr < 0x8000) { 
+-		*addrp = PAGE_ALIGN(0x8000);
+-		return 1; 
+-	}
+-
+-	/* direct mapping tables of the kernel */
+-	if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 
+-		*addrp = PAGE_ALIGN(table_end << PAGE_SHIFT);
+-		return 1;
+-	} 
+-
+-	/* initrd */ 
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+-		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
+-		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
+-		unsigned long ramdisk_end   = ramdisk_image+ramdisk_size;
+-
+-		if (last >= ramdisk_image && addr < ramdisk_end) {
+-			*addrp = PAGE_ALIGN(ramdisk_end);
+-			return 1;
+-		}
+-	} 
++	{ 0, PAGE_SIZE, "BIOS data page" },			/* BIOS data page */
++#ifdef CONFIG_SMP
++	{ SMP_TRAMPOLINE_BASE, SMP_TRAMPOLINE_BASE + 2*PAGE_SIZE, "SMP_TRAMPOLINE" },
+ #endif
+-	/* kernel code */
+-	if (last >= __pa_symbol(&_text) && addr < __pa_symbol(&_end)) {
+-		*addrp = PAGE_ALIGN(__pa_symbol(&_end));
+-		return 1;
+-	}
++#endif
++	{}
++};
+ 
+-	if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
+-		*addrp = PAGE_ALIGN(ebda_addr + ebda_size);
+-		return 1;
++void __init reserve_early(unsigned long start, unsigned long end, char *name)
++{
++	int i;
++	struct early_res *r;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		r = &early_res[i];
++		if (end > r->start && start < r->end)
++			panic("Overlapping early reservations %lx-%lx %s to %lx-%lx %s\n",
++			      start, end - 1, name?name:"", r->start, r->end - 1, r->name);
+ 	}
++	if (i >= MAX_EARLY_RES)
++		panic("Too many early reservations");
++	r = &early_res[i];
++	r->start = start;
++	r->end = end;
++	if (name)
++		strncpy(r->name, name, sizeof(r->name) - 1);
++}
+ 
+-#ifdef CONFIG_NUMA
+-	/* NUMA memory to node map */
+-	if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
+-		*addrp = nodemap_addr + nodemap_size;
+-		return 1;
++void __init early_res_to_bootmem(void)
++{
++	int i;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		struct early_res *r = &early_res[i];
++		printk(KERN_INFO "early res: %d [%lx-%lx] %s\n", i,
++			r->start, r->end - 1, r->name);
++		reserve_bootmem_generic(r->start, r->end - r->start);
+ 	}
+-#endif
+-	/* XXX ramdisk image here? */ 
+-#else
+-	if (last < (table_end<<PAGE_SHIFT)) {
+-		*addrp = table_end << PAGE_SHIFT;
+-		return 1;
++}
++
++/* Check for already reserved areas */
++static inline int bad_addr(unsigned long *addrp, unsigned long size)
++{
++	int i;
++	unsigned long addr = *addrp, last;
++	int changed = 0;
++again:
++	last = addr + size;
++	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
++		struct early_res *r = &early_res[i];
++		if (last >= r->start && addr < r->end) {
++			*addrp = addr = r->end;
++			changed = 1;
++			goto again;
++		}
+ 	}
+-#endif
+-	return 0;
+-} 
++	return changed;
++}
+ 
+ /*
+  * This function checks if any part of the range <start,end> is mapped
+  * with type.
+  */
+-int e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
+-{ 
++int
++e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
++{
+ 	int i;
+ 
+ #ifndef CONFIG_XEN
+-	for (i = 0; i < e820.nr_map; i++) { 
+-		struct e820entry *ei = &e820.map[i]; 
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
+ #else
+ 	if (!is_initial_xendomain())
+ 		return 0;
+@@ -132,12 +140,12 @@ int e820_any_mapped(unsigned long start,
+ 		const struct e820entry *ei = &machine_e820.map[i];
+ #endif
+ 
+-		if (type && ei->type != type) 
++		if (type && ei->type != type)
+ 			continue;
+ 		if (ei->addr >= end || ei->addr + ei->size <= start)
+-			continue; 
+-		return 1; 
+-	} 
++			continue;
++		return 1;
++	}
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(e820_any_mapped);
+@@ -148,7 +156,8 @@ EXPORT_SYMBOL_GPL(e820_any_mapped);
+  * Note: this function only works correct if the e820 table is sorted and
+  * not-overlapping, which is the case
+  */
+-int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
++int __init e820_all_mapped(unsigned long start, unsigned long end,
++			   unsigned type)
+ {
+ 	int i;
+ 
+@@ -173,65 +182,77 @@ int __init e820_all_mapped(unsigned long
+ 		 */
+ 		if (ei->addr <= start)
+ 			start = ei->addr + ei->size;
+-		/* if start is now at or beyond end, we're done, full coverage */
++		/*
++		 * if start is now at or beyond end, we're done, full
++		 * coverage
++		 */
+ 		if (start >= end)
+-			return 1; /* we're done */
++			return 1;
+ 	}
+ 	return 0;
+ }
+ 
+-/* 
+- * Find a free area in a specific range. 
+- */ 
+-unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsigned size) 
+-{ 
+-	int i; 
+-	for (i = 0; i < e820.nr_map; i++) { 
+-		struct e820entry *ei = &e820.map[i]; 
+-		unsigned long addr = ei->addr, last; 
+-		if (ei->type != E820_RAM) 
+-			continue; 
+-		if (addr < start) 
++/*
++ * Find a free area with specified alignment in a specific range.
++ */
++unsigned long __init find_e820_area(unsigned long start, unsigned long end,
++				    unsigned size, unsigned long align)
++{
++	int i;
++	unsigned long mask = ~(align - 1);
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long addr = ei->addr, last;
++
++		if (ei->type != E820_RAM)
++			continue;
++		if (addr < start)
+ 			addr = start;
+-		if (addr > ei->addr + ei->size) 
+-			continue; 
++		if (addr > ei->addr + ei->size)
++			continue;
+ 		while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
+ 			;
+-		last = PAGE_ALIGN(addr) + size;
++		addr = (addr + align - 1) & mask;
++		last = addr + size;
+ 		if (last > ei->addr + ei->size)
+ 			continue;
+-		if (last > end) 
++		if (last > end)
+ 			continue;
+-		return addr; 
+-	} 
+-	return -1UL;		
+-} 
++		return addr;
++	}
++	return -1UL;
++}
+ 
+ /*
+  * Find the highest page frame number we have available
+  */
+ unsigned long __init e820_end_of_ram(void)
+ {
+-	unsigned long end_pfn = 0;
++	unsigned long end_pfn;
++
+ 	end_pfn = find_max_pfn_with_active_regions();
+-	
+-	if (end_pfn > end_pfn_map) 
++
++	if (end_pfn > end_pfn_map)
+ 		end_pfn_map = end_pfn;
+ 	if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
+ 		end_pfn_map = MAXMEM>>PAGE_SHIFT;
+ 	if (end_pfn > end_user_pfn)
+ 		end_pfn = end_user_pfn;
+-	if (end_pfn > end_pfn_map) 
+-		end_pfn = end_pfn_map; 
++	if (end_pfn > end_pfn_map)
++		end_pfn = end_pfn_map;
+ 
+-	printk("end_pfn_map = %lu\n", end_pfn_map);
+-	return end_pfn;	
++	printk(KERN_INFO "end_pfn_map = %lu\n", end_pfn_map);
++	return end_pfn;
+ }
+ 
+ /*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+-void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
++void __init e820_reserve_resources(struct e820entry *e820, int nr_map,
++				   struct resource *code_resource,
++				   struct resource *data_resource,
++				   struct resource *bss_resource)
+ {
+ 	int i;
+ 	for (i = 0; i < nr_map; i++) {
+@@ -249,14 +270,14 @@ void __init e820_reserve_resources(struc
+ 		request_resource(&iomem_resource, res);
+ 		if (e820[i].type == E820_RAM) {
+ 			/*
+-			 *  We don't know which RAM region contains kernel data,
+-			 *  so we try it repeatedly and let the resource manager
+-			 *  test it.
++			 * We don't know which RAM region contains kernel data,
++			 * so we try it repeatedly and let the resource manager
++			 * test it.
+ 			 */
+ #ifndef CONFIG_XEN
+-			request_resource(res, &code_resource);
+-			request_resource(res, &data_resource);
+-			request_resource(res, &bss_resource);
++			request_resource(res, code_resource);
++			request_resource(res, data_resource);
++			request_resource(res, bss_resource);
+ #endif
+ #ifdef CONFIG_KEXEC
+ 			if (crashk_res.start != crashk_res.end)
+@@ -368,9 +389,9 @@ e820_register_active_regions(int nid, un
+ #endif
+ }
+ 
+-/* 
++/*
+  * Add a memory region to the kernel e820 map.
+- */ 
++ */
+ void __init add_memory_region(unsigned long start, unsigned long size, int type)
+ {
+ 	int x = e820.nr_map;
+@@ -395,9 +416,7 @@ unsigned long __init e820_hole_size(unsi
+ {
+ 	unsigned long start_pfn = start >> PAGE_SHIFT;
+ 	unsigned long end_pfn = end >> PAGE_SHIFT;
+-	unsigned long ei_startpfn;
+-	unsigned long ei_endpfn;
+-	unsigned long ram = 0;
++	unsigned long ei_startpfn, ei_endpfn, ram = 0;
+ 	int i;
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+@@ -409,28 +428,31 @@ unsigned long __init e820_hole_size(unsi
+ 	return end - start - (ram << PAGE_SHIFT);
+ }
+ 
+-void __init e820_print_map(char *who)
++static void __init e820_print_map(char *who)
+ {
+ 	int i;
+ 
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
+-			(unsigned long long) e820.map[i].addr,
+-			(unsigned long long) (e820.map[i].addr + e820.map[i].size));
++		       (unsigned long long) e820.map[i].addr,
++		       (unsigned long long)
++		       (e820.map[i].addr + e820.map[i].size));
+ 		switch (e820.map[i].type) {
+-		case E820_RAM:	printk("(usable)\n");
+-				break;
++		case E820_RAM:
++			printk(KERN_CONT "(usable)\n");
++			break;
+ 		case E820_RESERVED:
+-				printk("(reserved)\n");
+-				break;
++			printk(KERN_CONT "(reserved)\n");
++			break;
+ 		case E820_ACPI:
+-				printk("(ACPI data)\n");
+-				break;
++			printk(KERN_CONT "(ACPI data)\n");
++			break;
+ 		case E820_NVS:
+-				printk("(ACPI NVS)\n");
+-				break;
+-		default:	printk("type %u\n", e820.map[i].type);
+-				break;
++			printk(KERN_CONT "(ACPI NVS)\n");
++			break;
++		default:
++			printk(KERN_CONT "type %u\n", e820.map[i].type);
++			break;
+ 		}
+ 	}
+ }
+@@ -438,11 +460,11 @@ void __init e820_print_map(char *who)
+ /*
+  * Sanitize the BIOS e820 map.
+  *
+- * Some e820 responses include overlapping entries.  The following 
++ * Some e820 responses include overlapping entries. The following
+  * replaces the original e820 map with a new one, removing overlaps.
+  *
+  */
+-static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
++static int __init sanitize_e820_map(struct e820entry *biosmap, char *pnr_map)
+ {
+ 	struct change_member {
+ 		struct e820entry *pbios; /* pointer to original bios entry */
+@@ -462,7 +484,8 @@ static int __init sanitize_e820_map(stru
+ 	int i;
+ 
+ 	/*
+-		Visually we're performing the following (1,2,3,4 = memory types)...
++		Visually we're performing the following
++		(1,2,3,4 = memory types)...
+ 
+ 		Sample memory map (w/overlaps):
+ 		   ____22__________________
+@@ -504,22 +527,23 @@ static int __init sanitize_e820_map(stru
+ 	old_nr = *pnr_map;
+ 
+ 	/* bail out if we find any unreasonable addresses in bios map */
+-	for (i=0; i<old_nr; i++)
++	for (i = 0; i < old_nr; i++)
+ 		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+ 			return -1;
+ 
+ 	/* create pointers for initial change-point information (for sorting) */
+-	for (i=0; i < 2*old_nr; i++)
++	for (i = 0; i < 2 * old_nr; i++)
+ 		change_point[i] = &change_point_list[i];
+ 
+ 	/* record all known change-points (starting and ending addresses),
+ 	   omitting those that are for empty memory regions */
+ 	chgidx = 0;
+-	for (i=0; i < old_nr; i++)	{
++	for (i = 0; i < old_nr; i++)	{
+ 		if (biosmap[i].size != 0) {
+ 			change_point[chgidx]->addr = biosmap[i].addr;
+ 			change_point[chgidx++]->pbios = &biosmap[i];
+-			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
++			change_point[chgidx]->addr = biosmap[i].addr +
++				biosmap[i].size;
+ 			change_point[chgidx++]->pbios = &biosmap[i];
+ 		}
+ 	}
+@@ -529,75 +553,106 @@ static int __init sanitize_e820_map(stru
+ 	still_changing = 1;
+ 	while (still_changing)	{
+ 		still_changing = 0;
+-		for (i=1; i < chg_nr; i++)  {
+-			/* if <current_addr> > <last_addr>, swap */
+-			/* or, if current=<start_addr> & last=<end_addr>, swap */
+-			if ((change_point[i]->addr < change_point[i-1]->addr) ||
+-				((change_point[i]->addr == change_point[i-1]->addr) &&
+-				 (change_point[i]->addr == change_point[i]->pbios->addr) &&
+-				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
+-			   )
+-			{
++		for (i = 1; i < chg_nr; i++)  {
++			unsigned long long curaddr, lastaddr;
++			unsigned long long curpbaddr, lastpbaddr;
++
++			curaddr = change_point[i]->addr;
++			lastaddr = change_point[i - 1]->addr;
++			curpbaddr = change_point[i]->pbios->addr;
++			lastpbaddr = change_point[i - 1]->pbios->addr;
++
++			/*
++			 * swap entries, when:
++			 *
++			 * curaddr > lastaddr or
++			 * curaddr == lastaddr and curaddr == curpbaddr and
++			 * lastaddr != lastpbaddr
++			 */
++			if (curaddr < lastaddr ||
++			    (curaddr == lastaddr && curaddr == curpbaddr &&
++			     lastaddr != lastpbaddr)) {
+ 				change_tmp = change_point[i];
+ 				change_point[i] = change_point[i-1];
+ 				change_point[i-1] = change_tmp;
+-				still_changing=1;
++				still_changing = 1;
+ 			}
+ 		}
+ 	}
+ 
+ 	/* create a new bios memory map, removing overlaps */
+-	overlap_entries=0;	 /* number of entries in the overlap table */
+-	new_bios_entry=0;	 /* index for creating new bios map entries */
++	overlap_entries = 0;	 /* number of entries in the overlap table */
++	new_bios_entry = 0;	 /* index for creating new bios map entries */
+ 	last_type = 0;		 /* start with undefined memory type */
+ 	last_addr = 0;		 /* start with 0 as last starting address */
++
+ 	/* loop through change-points, determining affect on the new bios map */
+-	for (chgidx=0; chgidx < chg_nr; chgidx++)
+-	{
++	for (chgidx = 0; chgidx < chg_nr; chgidx++) {
+ 		/* keep track of all overlapping bios entries */
+-		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
+-		{
+-			/* add map entry to overlap list (> 1 entry implies an overlap) */
+-			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
+-		}
+-		else
+-		{
+-			/* remove entry from list (order independent, so swap with last) */
+-			for (i=0; i<overlap_entries; i++)
+-			{
+-				if (overlap_list[i] == change_point[chgidx]->pbios)
+-					overlap_list[i] = overlap_list[overlap_entries-1];
++		if (change_point[chgidx]->addr ==
++		    change_point[chgidx]->pbios->addr) {
++			/*
++			 * add map entry to overlap list (> 1 entry
++			 * implies an overlap)
++			 */
++			overlap_list[overlap_entries++] =
++				change_point[chgidx]->pbios;
++		} else {
++			/*
++			 * remove entry from list (order independent,
++			 * so swap with last)
++			 */
++			for (i = 0; i < overlap_entries; i++) {
++				if (overlap_list[i] ==
++				    change_point[chgidx]->pbios)
++					overlap_list[i] =
++						overlap_list[overlap_entries-1];
+ 			}
+ 			overlap_entries--;
+ 		}
+-		/* if there are overlapping entries, decide which "type" to use */
+-		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
++		/*
++		 * if there are overlapping entries, decide which
++		 * "type" to use (larger value takes precedence --
++		 * 1=usable, 2,3,4,4+=unusable)
++		 */
+ 		current_type = 0;
+-		for (i=0; i<overlap_entries; i++)
++		for (i = 0; i < overlap_entries; i++)
+ 			if (overlap_list[i]->type > current_type)
+ 				current_type = overlap_list[i]->type;
+-		/* continue building up new bios map based on this information */
++		/*
++		 * continue building up new bios map based on this
++		 * information
++		 */
+ 		if (current_type != last_type)	{
+ 			if (last_type != 0)	 {
+ 				new_bios[new_bios_entry].size =
+ 					change_point[chgidx]->addr - last_addr;
+-				/* move forward only if the new size was non-zero */
++				/*
++				 * move forward only if the new size
++				 * was non-zero
++				 */
+ 				if (new_bios[new_bios_entry].size != 0)
++					/*
++					 * no more space left for new
++					 * bios entries ?
++					 */
+ 					if (++new_bios_entry >= E820MAX)
+-						break; 	/* no more space left for new bios entries */
++						break;
+ 			}
+ 			if (current_type != 0)	{
+-				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
++				new_bios[new_bios_entry].addr =
++					change_point[chgidx]->addr;
+ 				new_bios[new_bios_entry].type = current_type;
+-				last_addr=change_point[chgidx]->addr;
++				last_addr = change_point[chgidx]->addr;
+ 			}
+ 			last_type = current_type;
+ 		}
+ 	}
+-	new_nr = new_bios_entry;   /* retain count for new bios entries */
++	/* retain count for new bios entries */
++	new_nr = new_bios_entry;
+ 
+ 	/* copy new bios mapping into original location */
+-	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
++	memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry));
+ 	*pnr_map = new_nr;
+ 
+ 	return 0;
+@@ -612,7 +667,7 @@ static int __init sanitize_e820_map(stru
+  * will have given us a memory map that we can use to properly
+  * set up memory.  If we aren't, we'll fake a memory map.
+  */
+-static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
++static int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
+ {
+ #ifndef CONFIG_XEN
+ 	/* Only one memory region (or negative)? Ignore it */
+@@ -633,7 +688,7 @@ static int __init copy_e820_map(struct e
+ 			return -1;
+ 
+ 		add_memory_region(start, size, type);
+-	} while (biosmap++,--nr_map);
++	} while (biosmap++, --nr_map);
+ 
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain()) {
+@@ -652,15 +707,17 @@ static int __init copy_e820_map(struct e
+ 	return 0;
+ }
+ 
+-void early_panic(char *msg)
++static void early_panic(char *msg)
+ {
+ 	early_printk(msg);
+ 	panic(msg);
+ }
+ 
+-#ifndef CONFIG_XEN
+-void __init setup_memory_region(void)
++/* We're not void only for x86 32-bit compat */
++char * __init machine_specific_memory_setup(void)
+ {
++#ifndef CONFIG_XEN
++	char *who = "BIOS-e820";
+ 	/*
+ 	 * Try to copy the BIOS-supplied E820-map.
+ 	 *
+@@ -670,14 +727,8 @@ void __init setup_memory_region(void)
+ 	sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
+ 	if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0)
+ 		early_panic("Cannot find a valid memory map");
+-	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-	e820_print_map("BIOS-e820");
+-}
+-
+ #else  /* CONFIG_XEN */
+-
+-void __init setup_memory_region(void)
+-{
++	char *who = "Xen";
+ 	int rc;
+ 	struct xen_memory_map memmap;
+ 	/*
+@@ -705,11 +756,13 @@ void __init setup_memory_region(void)
+ 
+ 	if (copy_e820_map(map, (char)memmap.nr_entries) < 0)
+ 		early_panic("Cannot find a valid memory map");
+-
++#endif
+ 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-	e820_print_map("Xen");
++	e820_print_map(who);
++
++	/* In case someone cares... */
++	return who;
+ }
+-#endif
+ 
+ static int __init parse_memopt(char *p)
+ {
+@@ -720,7 +773,7 @@ static int __init parse_memopt(char *p)
+ 	if (!p)
+ 		return -EINVAL;
+ 	end_user_pfn = memparse(p, &p);
+-	end_user_pfn >>= PAGE_SHIFT;	
++	end_user_pfn >>= PAGE_SHIFT;
+ 
+ 	end = end_user_pfn<<PAGE_SHIFT;
+ 	i = e820.nr_map-1;
+@@ -738,7 +791,7 @@ static int __init parse_memopt(char *p)
+ 	}
+ 
+ 	return 0;
+-} 
++}
+ early_param("mem", parse_memopt);
+ 
+ static int userdef __initdata;
+@@ -750,9 +803,9 @@ static int __init parse_memmap_opt(char 
+ 
+ 	if (!strcmp(p, "exactmap")) {
+ #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
++		/*
++		 * If we are doing a crash dump, we still need to know
++		 * the real mem size before original memory map is
+ 		 * reset.
+ 		 */
+ 		e820_register_active_regions(0, 0, -1UL);
+@@ -769,6 +822,8 @@ static int __init parse_memmap_opt(char 
+ 	mem_size = memparse(p, &p);
+ 	if (p == oldp)
+ 		return -EINVAL;
++
++	userdef = 1;
+ 	if (*p == '@') {
+ 		start_at = memparse(p+1, &p);
+ 		add_memory_region(start_at, mem_size, E820_RAM);
+@@ -788,11 +843,58 @@ early_param("memmap", parse_memmap_opt);
+ void __init finish_e820_parsing(void)
+ {
+ 	if (userdef) {
++		char nr = e820.nr_map;
++
++		if (sanitize_e820_map(e820.map, &nr) < 0)
++			early_panic("Invalid user supplied memory map");
++		e820.nr_map = nr;
++
+ 		printk(KERN_INFO "user-defined physical RAM map:\n");
+ 		e820_print_map("user");
+ 	}
+ }
+ 
++#ifndef CONFIG_XEN
++void __init update_memory_range(u64 start, u64 size, unsigned old_type,
++				unsigned new_type)
++{
++	int i;
++
++	BUG_ON(old_type == new_type);
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		u64 final_start, final_end;
++		if (ei->type != old_type)
++			continue;
++		/* totally covered? */
++		if (ei->addr >= start && ei->size <= size) {
++			ei->type = new_type;
++			continue;
++		}
++		/* partially covered */
++		final_start = max(start, ei->addr);
++		final_end = min(start + size, ei->addr + ei->size);
++		if (final_start >= final_end)
++			continue;
++		add_memory_region(final_start, final_end - final_start,
++					 new_type);
++	}
++}
++
++void __init update_e820(void)
++{
++	u8 nr_map;
++
++	nr_map = e820.nr_map;
++	if (sanitize_e820_map(e820.map, &nr_map))
++		return;
++	e820.nr_map = nr_map;
++	printk(KERN_INFO "modified physical RAM map:\n");
++	e820_print_map("modified");
++}
++#endif
++
+ unsigned long pci_mem_start = 0xaeedbabe;
+ EXPORT_SYMBOL(pci_mem_start);
+ 
+@@ -836,8 +938,10 @@ __init void e820_setup_gap(struct e820en
+ 
+ 	if (!found) {
+ 		gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+-		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n"
+-		       KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n");
++		printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
++		       "address range\n"
++		       KERN_ERR "PCI: Unassigned devices with 32bit resource "
++		       "registers may break!\n");
+ 	}
+ 
+ 	/*
+@@ -850,8 +954,9 @@ __init void e820_setup_gap(struct e820en
+ 	/* Fun with two's complement */
+ 	pci_mem_start = (gapstart + round) & -round;
+ 
+-	printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+-		pci_mem_start, gapstart, gapsize);
++	printk(KERN_INFO
++	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
++	       pci_mem_start, gapstart, gapsize);
+ }
+ 
+ int __init arch_get_ram_range(int slot, u64 *addr, u64 *size)
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -222,7 +222,7 @@ static struct console simnow_console = {
+ };
+ 
+ /* Direct interface for emergencies */
+-struct console *early_console = &early_vga_console;
++static struct console *early_console = &early_vga_console;
+ static int early_console_initialized = 0;
+ 
+ void early_printk(const char *fmt, ...)
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:25.000000000 +0100
+@@ -59,7 +59,7 @@
+  * for paravirtualization.  The following will never clobber any registers:
+  *   INTERRUPT_RETURN (aka. "iret")
+  *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
+- *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
++ *   ENABLE_INTERRUPTS_SYSCALL_RET (aka "sti; sysexit").
+  *
+  * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
+  * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
+@@ -282,16 +282,21 @@ END(resume_kernel)
+ #endif
+ 	CFI_ENDPROC
+ 
++	.macro test_tif ti_reg		# system call tracing in operation / emulation
++	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
++	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(\ti_reg)
++	.endm
++
+ /* SYSENTER_RETURN points to after the "sysenter" instruction in
+    the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
+ 
+ 	# sysenter call handler stub
+-ENTRY(sysenter_entry)
++ENTRY(ia32_sysenter_target)
+ 	CFI_STARTPROC simple
+ 	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA esp, 0
+ 	CFI_REGISTER esp, ebp
+-	movl SYSENTER_stack_esp0(%esp),%esp
++	movl SYSENTER_stack_sp0(%esp),%esp
+ sysenter_past_esp:
+ 	/*
+ 	 * No need to follow this irqs on/off section: the syscall
+@@ -334,9 +339,7 @@ sysenter_past_esp:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-
+-	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+-	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	test_tif %ebp
+ 	jnz syscall_trace_entry
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+@@ -354,7 +357,7 @@ sysenter_past_esp:
+ 	xorl %ebp,%ebp
+ 	TRACE_IRQS_ON
+ 1:	mov  PT_FS(%esp), %fs
+-	ENABLE_INTERRUPTS_SYSEXIT
++	ENABLE_INTERRUPTS_SYSCALL_RET
+ 	CFI_ENDPROC
+ .pushsection .fixup,"ax"
+ 2:	movl $0,PT_FS(%esp)
+@@ -363,10 +366,10 @@ sysenter_past_esp:
+ 	.align 4
+ 	.long 1b,2b
+ .popsection
+-ENDPROC(sysenter_entry)
++ENDPROC(ia32_sysenter_target)
+ 
+ 	# pv sysenter call handler stub
+-ENTRY(sysenter_entry_pv)
++ENTRY(ia32pv_sysenter_target)
+ 	RING0_INT_FRAME
+ 	movl $__USER_DS,16(%esp)
+ 	movl %ebp,12(%esp)
+@@ -389,7 +392,7 @@ ENTRY(sysenter_entry_pv)
+ .previous
+ 	/* fall through */
+ 	CFI_ENDPROC
+-ENDPROC(sysenter_entry_pv)
++ENDPROC(ia32pv_sysenter_target)
+ 
+ 	# system call handler stub
+ ENTRY(system_call)
+@@ -398,9 +401,7 @@ ENTRY(system_call)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
+ 	GET_THREAD_INFO(%ebp)
+-					# system call tracing in operation / emulation
+-	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+-	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++	test_tif %ebp
+ 	jnz syscall_trace_entry
+ 	cmpl $(nr_syscalls), %eax
+ 	jae syscall_badsys
+@@ -452,7 +453,8 @@ restore_nocheck_notrace:
+ 	RESTORE_REGS
+ 	addl $4, %esp			# skip orig_eax/error_code
+ 	CFI_ADJUST_CFA_OFFSET -4
+-1:	INTERRUPT_RETURN
++irq_return:
++	INTERRUPT_RETURN
+ .section .fixup,"ax"
+ iret_exc:
+ 	pushl $0			# no error code
+@@ -461,7 +463,7 @@ iret_exc:
+ .previous
+ .section __ex_table,"a"
+ 	.align 4
+-	.long 1b,iret_exc
++	.long irq_return,iret_exc
+ .previous
+ 
+ 	CFI_RESTORE_STATE
+@@ -657,7 +659,7 @@ END(syscall_badsys)
+  * Build the entry stubs and pointer table with
+  * some assembler magic.
+  */
+-.data
++.section .rodata,"a"
+ ENTRY(interrupt)
+ .text
+ 
+@@ -963,7 +965,7 @@ END(device_not_available)
+  * that sets up the real kernel stack. Check here, since we can't
+  * allow the wrong stack to be used.
+  *
+- * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have
++ * "SYSENTER_stack_sp0+12" is because the NMI/debug handler will have
+  * already pushed 3 words if it hits on the sysenter instruction:
+  * eflags, cs and eip.
+  *
+@@ -975,7 +977,7 @@ END(device_not_available)
+ 	cmpw $__KERNEL_CS,4(%esp);		\
+ 	jne ok;					\
+ label:						\
+-	movl SYSENTER_stack_esp0+offset(%esp),%esp;	\
++	movl SYSENTER_stack_sp0+offset(%esp),%esp;	\
+ 	CFI_DEF_CFA esp, 0;			\
+ 	CFI_UNDEFINED eip;			\
+ 	pushfl;					\
+@@ -990,7 +992,7 @@ label:						\
+ KPROBE_ENTRY(debug)
+ 	RING0_INT_FRAME
+ #ifndef CONFIG_XEN
+-	cmpl $sysenter_entry,(%esp)
++	cmpl $ia32_sysenter_target,(%esp)
+ 	jne debug_stack_correct
+ 	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
+ debug_stack_correct:
+@@ -1023,7 +1025,7 @@ KPROBE_ENTRY(nmi)
+ 	popl %eax
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	je nmi_espfix_stack
+-	cmpl $sysenter_entry,(%esp)
++	cmpl $ia32_sysenter_target,(%esp)
+ 	je nmi_stack_fixup
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+@@ -1036,7 +1038,7 @@ KPROBE_ENTRY(nmi)
+ 	popl %eax
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	jae nmi_stack_correct
+-	cmpl $sysenter_entry,12(%esp)
++	cmpl $ia32_sysenter_target,12(%esp)
+ 	je nmi_debug_stack_check
+ nmi_stack_correct:
+ 	/* We have a RING0_INT_FRAME here */
+@@ -1089,12 +1091,8 @@ nmi_espfix_stack:
+ 	RESTORE_REGS
+ 	lss 12+4(%esp), %esp		# back to espfix stack
+ 	CFI_ADJUST_CFA_OFFSET -24
+-1:	INTERRUPT_RETURN
++	jmp irq_return
+ 	CFI_ENDPROC
+-.section __ex_table,"a"
+-	.align 4
+-	.long 1b,iret_exc
+-.previous
+ #else
+ KPROBE_ENTRY(nmi)
+ 	RING0_INT_FRAME
+@@ -1112,17 +1110,17 @@ KPROBE_END(nmi)
+ 
+ #ifdef CONFIG_PARAVIRT
+ ENTRY(native_iret)
+-1:	iret
++	iret
+ .section __ex_table,"a"
+ 	.align 4
+-	.long 1b,iret_exc
++	.long native_iret, iret_exc
+ .previous
+ END(native_iret)
+ 
+-ENTRY(native_irq_enable_sysexit)
++ENTRY(native_irq_enable_syscall_ret)
+ 	sti
+ 	sysexit
+-END(native_irq_enable_sysexit)
++END(native_irq_enable_syscall_ret)
+ #endif
+ 
+ KPROBE_ENTRY(int3)
+@@ -1271,7 +1269,144 @@ ENTRY(kernel_thread_helper)
+ 	CFI_ENDPROC
+ ENDPROC(kernel_thread_helper)
+ 
++#include <asm/alternative-asm.h>
++
++	# pv syscall call handler stub
++ENTRY(ia32pv_cstar_target)
++	RING0_INT_FRAME
++	movl $__USER_DS,16(%esp)
++	movl %ebp,%ecx
++	movl $__USER_CS,4(%esp)
++	movl 12(%esp),%ebp
++	pushl %eax			# save orig_eax
++	CFI_ADJUST_CFA_OFFSET 4
++/*
++ * Load the potential sixth argument from user stack.
++ * Careful about security.
++ */
++	cmpl $__PAGE_OFFSET-4,%ebp
++	CFI_REMEMBER_STATE
++	ja cstar_fault
++1:	movl (%ebp),%ebp
++.section __ex_table,"a"
++	.align 4
++	.long 1b,cstar_fault
++.previous
++	SAVE_ALL
++	GET_THREAD_INFO(%ebp)
++	test_tif %ebp
++	jnz cstar_trace_entry
++	cmpl $nr_syscalls,%eax
++	jae cstar_badsys
++.Lcstar_call:
++	btl %eax,cstar_special
++	jc .Lcstar_special
++	call *cstar_call_table(,%eax,4)
++	movl %eax,PT_EAX(%esp)		# store the return value
++.Lcstar_exit:
++	movl PT_ECX(%esp),%ecx
++	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
++	jmp syscall_exit
++.Lcstar_special:
++	movl PT_ECX(%esp),%ecx
++	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
++	jmp syscall_call
++cstar_set_tif:
++	movl $cstar_clear_tif,(%esp)	# replace return address
++	LOCK_PREFIX
++	orl $_TIF_CSTAR,TI_flags(%ebp)
++	jmp *sys_call_table(,%eax,4)
++cstar_clear_tif:
++	movl %eax,PT_EAX(%esp)		# store the return value
++	LOCK_PREFIX
++	andl $~_TIF_CSTAR,TI_flags(%ebp)
++	jmp .Lcstar_exit
++cstar_trace_entry:
++	movl $-ENOSYS,PT_EAX(%esp)
++	cmpl $nr_syscalls,%eax
++	jae 1f
++	btl %eax,cstar_special
++	jc .Lcstar_trace_special
++1:	movl %esp,%eax
++	xorl %edx,%edx
++	LOCK_PREFIX
++	orl $_TIF_CSTAR,TI_flags(%ebp)
++	call do_syscall_trace
++	LOCK_PREFIX
++	andl $~_TIF_CSTAR,TI_flags(%ebp)
++	testl %eax,%eax
++	jne .Lcstar_resume		# ret != 0 -> running under PTRACE_SYSEMU,
++					# so must skip actual syscall
++	movl PT_ORIG_EAX(%esp),%eax
++	cmpl $nr_syscalls,%eax
++	jb .Lcstar_call
++	jmp .Lcstar_exit
++.Lcstar_trace_special:
++	movl PT_ECX(%esp),%ecx
++	movl %esp,%eax
++	xorl %edx,%edx
++	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
++	call do_syscall_trace
++	testl %eax,%eax
++	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
++					# so must skip actual syscall
++	movl PT_ORIG_EAX(%esp),%eax
++	cmpl $nr_syscalls,%eax
++	jb syscall_call
++	jmp syscall_exit
++cstar_badsys:
++	movl $-ENOSYS,PT_EAX(%esp)
++.Lcstar_resume:
++	movl PT_ECX(%esp),%ecx
++	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
++	jmp resume_userspace
++	CFI_RESTORE_STATE
++cstar_fault:
++	movl $-EFAULT,%eax
++	SAVE_ALL
++	GET_THREAD_INFO(%ebp)
++	jmp .Lcstar_resume
++	CFI_ENDPROC
++ENDPROC(ia32pv_cstar_target)
++
++ENTRY(cstar_ret_from_fork)
++	CFI_STARTPROC
++	movl PT_ECX(%esp),%ecx
++	GET_THREAD_INFO(%ebp)
++	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
++	LOCK_PREFIX
++	andl $~_TIF_CSTAR,TI_flags(%ebp)
++	jmp ret_from_fork
++	CFI_ENDPROC
++END(ret_from_fork)
++
+ .section .rodata,"a"
+ #include "syscall_table_32.S"
+ 
+ syscall_table_size=(.-sys_call_table)
++
++#include <asm/unistd.h>
++cstar_special:
++nr=0
++mask=0
++.rept nr_syscalls+31
++ .irp n, __NR_sigreturn, __NR_rt_sigreturn
++  .if nr == \n
++   mask = mask | (1 << (\n & 31))
++  .endif
++ .endr
++ nr = nr + 1
++ .if (nr & 31) == 0
++  .long mask
++  mask = 0
++ .endif
++.endr
++#define	sys_call_table cstar_call_table
++#define	sys_fork cstar_set_tif
++#define	sys_clone cstar_set_tif
++#define	sys_vfork cstar_set_tif
++#include "syscall_table_32.S"
++#undef	sys_call_table
++#undef	sys_fork
++#undef	sys_clone
++#undef	sys_vfork
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:25.000000000 +0100
+@@ -54,17 +54,22 @@
+ #include <asm/page.h>
+ #include <asm/irqflags.h>
+ #include <asm/errno.h>
+-#include <xen/interface/arch-x86_64.h>
++#include <xen/interface/xen.h>
+ #include <xen/interface/features.h>
+ 
+-#include "xen_entry_64.S"
+-	
+ 	.code64
+ 
+ #ifndef CONFIG_PREEMPT
+ #define retint_kernel retint_restore_args
+ #endif	
+ 
++#ifdef CONFIG_PARAVIRT
++ENTRY(native_irq_enable_syscall_ret)
++	movq	%gs:pda_oldrsp,%rsp
++	swapgs
++	sysretq
++#endif /* CONFIG_PARAVIRT */
++
+ 
+ .macro TRACE_IRQS_IRETQ offset=ARGOFFSET
+ #ifdef CONFIG_TRACE_IRQFLAGS
+@@ -277,7 +282,7 @@ ret_from_sys_call:
+ sysret_check:		
+ 	LOCKDEP_SYS_EXIT
+ 	GET_THREAD_INFO(%rcx)
+-        XEN_BLOCK_EVENTS(%rsi)        
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	movl threadinfo_flags(%rcx),%edx
+ 	andl %edi,%edx
+@@ -287,7 +292,7 @@ sysret_check:		
+ 	 * sysretq will re-enable interrupts:
+ 	 */
+ 	TRACE_IRQS_ON
+-        XEN_UNBLOCK_EVENTS(%rsi)                
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	RESTORE_ARGS 0,8,0
+         HYPERVISOR_IRET VGCF_IN_SYSCALL
+ 
+@@ -298,7 +303,7 @@ sysret_careful:
+ 	bt $TIF_NEED_RESCHED,%edx
+ 	jnc sysret_signal
+ 	TRACE_IRQS_ON
+-	XEN_UNBLOCK_EVENTS(%rsi)
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET 8
+ 	call schedule
+@@ -309,9 +314,8 @@ sysret_careful:
+ 	/* Handle a signal */ 
+ sysret_signal:
+ 	TRACE_IRQS_ON
+-/*	sti */
+-        XEN_UNBLOCK_EVENTS(%rsi)        
+-	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
++	ENABLE_INTERRUPTS(CLBR_NONE)
++	testl $_TIF_DO_NOTIFY_MASK,%edx
+ 	jz    1f
+ 
+ 	/* Really a signal */
+@@ -323,7 +327,7 @@ sysret_signal:
+ 1:	movl $_TIF_NEED_RESCHED,%edi
+ 	/* Use IRET because user could have changed frame. This
+ 	   works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
+-	XEN_BLOCK_EVENTS(%rsi)
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp int_with_check
+ 	
+@@ -355,7 +359,7 @@ tracesys:			 
+  */
+ 	.globl int_ret_from_sys_call
+ int_ret_from_sys_call:
+-        XEN_BLOCK_EVENTS(%rsi)
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	testb $3,CS-ARGOFFSET(%rsp)
+         jnz 1f
+@@ -381,22 +385,20 @@ int_careful:
+ 	bt $TIF_NEED_RESCHED,%edx
+ 	jnc  int_very_careful
+ 	TRACE_IRQS_ON
+-/*	sti */
+-        XEN_UNBLOCK_EVENTS(%rsi)
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET 8
+ 	call schedule
+ 	popq %rdi
+ 	CFI_ADJUST_CFA_OFFSET -8
+-	XEN_BLOCK_EVENTS(%rsi)
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp int_with_check
+ 
+ 	/* handle signals and tracing -- both require a full stack frame */
+ int_very_careful:
+ 	TRACE_IRQS_ON
+-/*	sti */
+-        XEN_UNBLOCK_EVENTS(%rsi)
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	SAVE_REST
+ 	/* Check for syscall exit trace */	
+ 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
+@@ -411,7 +413,7 @@ int_very_careful:
+ 	jmp int_restore_rest
+ 	
+ int_signal:
+-	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
++	testl $_TIF_DO_NOTIFY_MASK,%edx
+ 	jz 1f
+ 	movq %rsp,%rdi		# &ptregs -> arg1
+ 	xorl %esi,%esi		# oldset -> arg2
+@@ -419,7 +421,7 @@ int_signal:
+ 1:	movl $_TIF_NEED_RESCHED,%edi	
+ int_restore_rest:
+ 	RESTORE_REST
+-	XEN_BLOCK_EVENTS(%rsi)
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp int_with_check
+ 	CFI_ENDPROC
+@@ -474,6 +476,7 @@ ENTRY(stub_execve)
+ 	CFI_REGISTER rip, r11
+ 	SAVE_REST
+ 	FIXUP_TOP_OF_STACK %r11
++	movq %rsp, %rcx
+ 	call sys_execve
+ 	RESTORE_TOP_OF_STACK %r11
+ 	movq %rax,RAX(%rsp)
+@@ -526,11 +529,10 @@ retint_check:
+ retint_restore_args:	/* return to kernel space */
+ 	movl EFLAGS-REST_SKIP(%rsp), %eax
+ 	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
+-	XEN_GET_VCPU_INFO(%rsi)
++	GET_VCPU_INFO
+ 	andb evtchn_upcall_mask(%rsi),%al
+ 	andb $1,%al			# EAX[0] == IRET_EFLAGS.IF & event_mask
+ 	jnz restore_all_enable_events	#        != 0 => enable event delivery
+-	XEN_PUT_VCPU_INFO(%rsi)
+ 		
+ 	RESTORE_ARGS 0,8,0
+ 	HYPERVISOR_IRET 0
+@@ -541,31 +543,29 @@ retint_careful:
+ 	bt    $TIF_NEED_RESCHED,%edx
+ 	jnc   retint_signal
+ 	TRACE_IRQS_ON
+-	XEN_UNBLOCK_EVENTS(%rsi)
+-/*	sti */        
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	pushq %rdi
+ 	CFI_ADJUST_CFA_OFFSET	8
+ 	call  schedule
+ 	popq %rdi		
+ 	CFI_ADJUST_CFA_OFFSET	-8
+ 	GET_THREAD_INFO(%rcx)
+-	XEN_BLOCK_EVENTS(%rsi)		
+-/*	cli */
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	jmp retint_check
+ 	
+ retint_signal:
+-	testl $(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY),%edx
++	testl $_TIF_DO_NOTIFY_MASK,%edx
+ 	jz    retint_restore_args
+ 	TRACE_IRQS_ON
+-        XEN_UNBLOCK_EVENTS(%rsi)
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	SAVE_REST
+ 	movq $-1,ORIG_RAX(%rsp) 			
+ 	xorl %esi,%esi		# oldset
+ 	movq %rsp,%rdi		# &pt_regs
+ 	call do_notify_resume
+ 	RESTORE_REST
+-        XEN_BLOCK_EVENTS(%rsi)		
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	movl $_TIF_NEED_RESCHED,%edi
+ 	GET_THREAD_INFO(%rcx)
+@@ -702,7 +702,7 @@ END(spurious_interrupt)
+ 	rdmsr
+ 	testl %edx,%edx
+ 	js    1f
+-	swapgs
++	SWAPGS
+ 	xorl  %ebx,%ebx
+ 1:
+ #endif
+@@ -719,8 +719,7 @@ END(spurious_interrupt)
+ 	.if \ist
+ 	addq	$EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+ 	.endif
+-/*	cli */
+-	XEN_BLOCK_EVENTS(%rsi)		
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	.if \irqtrace
+ 	TRACE_IRQS_OFF
+ 	.endif
+@@ -749,10 +748,10 @@ paranoid_swapgs\trace:
+ 	.if \trace
+ 	TRACE_IRQS_IRETQ 0
+ 	.endif
+-	swapgs
++	SWAPGS_UNSAFE_STACK
+ paranoid_restore\trace:
+ 	RESTORE_ALL 8
+-	iretq
++	jmp irq_return
+ paranoid_userspace\trace:
+ 	GET_THREAD_INFO(%rcx)
+ 	movl threadinfo_flags(%rcx),%ebx
+@@ -767,11 +766,11 @@ paranoid_userspace\trace:
+ 	.if \trace
+ 	TRACE_IRQS_ON
+ 	.endif
+-	sti
++	ENABLE_INTERRUPTS(CLBR_NONE)
+ 	xorl %esi,%esi 			/* arg2: oldset */
+ 	movq %rsp,%rdi 			/* arg1: &pt_regs */
+ 	call do_notify_resume
+-	cli
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	.if \trace
+ 	TRACE_IRQS_OFF
+ 	.endif
+@@ -780,9 +779,9 @@ paranoid_schedule\trace:
+ 	.if \trace
+ 	TRACE_IRQS_ON
+ 	.endif
+-	sti
++	ENABLE_INTERRUPTS(CLBR_ANY)
+ 	call schedule
+-	cli
++	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	.if \trace
+ 	TRACE_IRQS_OFF
+ 	.endif
+@@ -846,8 +845,7 @@ error_call_handler:
+ 	call *%rax
+ error_exit:
+ 	RESTORE_REST
+-/*	cli */
+-	XEN_BLOCK_EVENTS(%rsi)		
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	GET_THREAD_INFO(%rcx)	
+ 	testb $3,CS-ARGOFFSET(%rsp)
+@@ -875,7 +873,7 @@ error_kernelspace:
+ 	   iret run with kernel gs again, so don't set the user space flag.
+ 	   B stepping K8s sometimes report an truncated RIP for IRET 
+ 	   exceptions returning to compat mode. Check for these here too. */
+-	leaq iret_label(%rip),%rbp
++	leaq irq_return(%rip),%rbp
+ 	cmpq %rbp,RIP(%rsp) 
+ 	je   error_swapgs
+ 	movl %ebp,%ebp	/* zero extend */
+@@ -930,19 +928,17 @@ END(do_hypervisor_callback)
+ restore_all_enable_events:  
+ 	CFI_DEFAULT_STACK adj=1
+ 	TRACE_IRQS_ON
+-	XEN_UNBLOCK_EVENTS(%rsi)        # %rsi is already set up...
++	__ENABLE_INTERRUPTS
+ 
+ scrit:	/**** START OF CRITICAL REGION ****/
+-	XEN_TEST_PENDING(%rsi)
++	__TEST_PENDING
+ 	CFI_REMEMBER_STATE
+ 	jnz  14f			# process more events if necessary...
+-	XEN_PUT_VCPU_INFO(%rsi)
+         RESTORE_ARGS 0,8,0
+         HYPERVISOR_IRET 0
+         
+ 	CFI_RESTORE_STATE
+-14:	XEN_LOCKED_BLOCK_EVENTS(%rsi)
+-	XEN_PUT_VCPU_INFO(%rsi)
++14:	__DISABLE_INTERRUPTS
+ 	SAVE_REST
+         movq %rsp,%rdi                  # set the argument again
+ 	jmp  11b
+@@ -1086,15 +1082,16 @@ ENDPROC(child_rip)
+  *	rdi: name, rsi: argv, rdx: envp
+  *
+  * We want to fallback into:
+- *	extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
++ *	extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs)
+  *
+  * do_sys_execve asm fallback arguments:
+- *	rdi: name, rsi: argv, rdx: envp, fake frame on the stack
++ *	rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
+  */
+ ENTRY(kernel_execve)
+ 	CFI_STARTPROC
+ 	FAKE_STACK_FRAME $0
+ 	SAVE_ALL	
++	movq %rsp,%rcx
+ 	call sys_execve
+ 	movq %rax, RAX(%rsp)	
+ 	RESTORE_REST
+@@ -1144,7 +1141,7 @@ do_nmi_callback:
+ 	call do_nmi
+ 	orl  $NMI_MASK,EFLAGS(%rsp)
+ 	RESTORE_REST
+-	XEN_BLOCK_EVENTS(%rsi)
++	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	GET_THREAD_INFO(%rcx)
+ 	jmp  retint_restore_args
+--- head-2010-01-18.orig/arch/x86/kernel/fixup.c	2008-01-28 12:24:18.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/fixup.c	2009-11-06 10:51:25.000000000 +0100
+@@ -36,7 +36,7 @@
+ 
+ #define DP(_f, _args...) printk(KERN_ALERT "  " _f "\n" , ## _args )
+ 
+-fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
++void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
+ {
+ 	static unsigned long printed = 0;
+ 	char info[100];
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -16,6 +16,7 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/percpu.h>
++#include <linux/start_kernel.h>
+ #include <linux/module.h>
+ 
+ #include <asm/processor.h>
+@@ -26,6 +27,8 @@
+ #include <asm/pgtable.h>
+ #include <asm/tlbflush.h>
+ #include <asm/sections.h>
++#include <asm/kdebug.h>
++#include <asm/e820.h>
+ 
+ unsigned long start_pfn;
+ 
+@@ -34,7 +37,7 @@ static void __init zap_identity_mappings
+ {
+ 	pgd_t *pgd = pgd_offset_k(0UL);
+ 	pgd_clear(pgd);
+-	__flush_tlb();
++	__flush_tlb_all();
+ }
+ 
+ /* Don't add a printk in there. printk relies on the PDA which is not initialized 
+@@ -72,6 +75,37 @@ EXPORT_SYMBOL(machine_to_phys_mapping);
+ unsigned int machine_to_phys_order;
+ EXPORT_SYMBOL(machine_to_phys_order);
+ 
++#define EBDA_ADDR_POINTER 0x40E
++
++static __init void reserve_ebda(void)
++{
++#ifndef CONFIG_XEN
++	unsigned ebda_addr, ebda_size;
++
++	/*
++	 * there is a real-mode segmented pointer pointing to the
++	 * 4K EBDA area at 0x40E
++	 */
++	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
++	ebda_addr <<= 4;
++
++	if (!ebda_addr)
++		return;
++
++	ebda_size = *(unsigned short *)__va(ebda_addr);
++
++	/* Round EBDA up to pages */
++	if (ebda_size == 0)
++		ebda_size = 1;
++	ebda_size <<= 10;
++	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
++	if (ebda_size > 64*1024)
++		ebda_size = 64*1024;
++
++	reserve_early(ebda_addr, ebda_addr + ebda_size, "EBDA");
++#endif
++}
++
+ void __init x86_64_start_kernel(char * real_mode_data)
+ {
+ 	struct xen_machphys_mapping mapping;
+@@ -103,8 +137,16 @@ void __init x86_64_start_kernel(char * r
+ 	/* Make NULL pointers segfault */
+ 	zap_identity_mappings();
+ 
+-	for (i = 0; i < IDT_ENTRIES; i++)
++	/* Cleanup the over mapped high alias */
++	cleanup_highmap();
++
++	for (i = 0; i < IDT_ENTRIES; i++) {
++#ifdef CONFIG_EARLY_PRINTK
++		set_intr_gate(i, &early_idt_handlers[i]);
++#else
+ 		set_intr_gate(i, early_idt_handler);
++#endif
++	}
+ 	load_idt((const struct desc_ptr *)&idt_descr);
+ #endif
+ 
+@@ -115,8 +157,19 @@ void __init x86_64_start_kernel(char * r
+ 
+ 	pda_init(0);
+ 	copy_bootdata(__va(real_mode_data));
+-#ifdef CONFIG_SMP
+-	cpu_set(0, cpu_online_map);
+-#endif
++
++	reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS");
++
++	reserve_early(round_up(__pa_symbol(&_end), PAGE_SIZE),
++		      start_pfn << PAGE_SHIFT, "Xen provided");
++
++	reserve_ebda();
++
++	/*
++	 * At this point everything still needed from the boot loader
++	 * or BIOS or kernel text should be early reserved or marked not
++	 * RAM in e820. All other memory is free game.
++	 */
++
+ 	start_kernel();
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:51:25.000000000 +0100
+@@ -3,6 +3,7 @@
+ .text
+ #include <linux/elfnote.h>
+ #include <linux/threads.h>
++#include <linux/init.h>
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
+@@ -88,7 +89,7 @@ ENTRY(_stext)
+  */
+ .section ".bss.page_aligned","wa"
+ 	.align PAGE_SIZE_asm
+-ENTRY(swapper_pg_pmd)
++ENTRY(swapper_pg_fixmap)
+ 	.fill 1024,4,0
+ ENTRY(empty_zero_page)
+ 	.fill 4096,1,0
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <linux/htirq.h>
+ #include <linux/freezer.h>
+ #include <linux/kthread.h>
++#include <linux/jiffies.h>	/* time_after() */
+ 
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -48,8 +49,6 @@
+ #include <mach_apic.h>
+ #include <mach_apicdef.h>
+ 
+-#include "io_ports.h"
+-
+ #ifdef CONFIG_XEN
+ #include <xen/interface/xen.h>
+ #include <xen/interface/physdev.h>
+@@ -400,7 +399,7 @@ static void set_ioapic_affinity_irq(unsi
+ # include <asm/processor.h>	/* kernel_thread() */
+ # include <linux/kernel_stat.h>	/* kstat */
+ # include <linux/slab.h>		/* kmalloc() */
+-# include <linux/timer.h>	/* time_after() */
++# include <linux/timer.h>
+  
+ #define IRQBALANCE_CHECK_ARCH -999
+ #define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+@@ -777,7 +776,7 @@ late_initcall(balanced_irq_init);
+ #endif
+ 
+ #ifndef CONFIG_SMP
+-void fastcall send_IPI_self(int vector)
++void send_IPI_self(int vector)
+ {
+ #ifndef CONFIG_XEN
+ 	unsigned int cfg;
+@@ -1959,7 +1958,7 @@ static int __init timer_irq_works(void)
+ 	 * might have cached one ExtINT interrupt.  Finally, at
+ 	 * least one tick may be lost due to delays.
+ 	 */
+-	if (jiffies - t1 > 4)
++	if (time_after(jiffies, t1 + 4))
+ 		return 1;
+ 
+ 	return 0;
+@@ -2142,7 +2141,7 @@ static struct irq_chip lapic_chip __read
+ 	.eoi		= ack_apic,
+ };
+ 
+-static void setup_nmi (void)
++static void __init setup_nmi(void)
+ {
+ 	/*
+  	 * Dirty trick to enable the NMI watchdog ...
+@@ -2155,7 +2154,7 @@ static void setup_nmi (void)
+ 	 */ 
+ 	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+ 
+-	on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
++	enable_NMI_through_LVT0();
+ 
+ 	apic_printk(APIC_VERBOSE, " done.\n");
+ }
+@@ -2479,7 +2478,7 @@ static int ioapic_resume(struct sys_devi
+ }
+ 
+ static struct sysdev_class ioapic_sysdev_class = {
+-	set_kset_name("ioapic"),
++	.name = "ioapic",
+ 	.suspend = ioapic_suspend,
+ 	.resume = ioapic_resume,
+ };
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -32,9 +32,11 @@
+ #include <linux/msi.h>
+ #include <linux/htirq.h>
+ #include <linux/dmar.h>
++#include <linux/jiffies.h>
+ #ifdef CONFIG_ACPI
+ #include <acpi/acpi_bus.h>
+ #endif
++#include <linux/bootmem.h>
+ 
+ #include <asm/idle.h>
+ #include <asm/io.h>
+@@ -1064,7 +1066,7 @@ void __apicdebuginit print_local_APIC(vo
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+-	maxlvt = get_maxlvt();
++	maxlvt = lapic_get_maxlvt();
+ 
+ 	v = apic_read(APIC_TASKPRI);
+ 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+@@ -1165,7 +1167,7 @@ void __apicdebuginit print_PIC(void)
+ }
+ #endif /* !CONFIG_XEN */
+ 
+-static void __init enable_IO_APIC(void)
++void __init enable_IO_APIC(void)
+ {
+ 	union IO_APIC_reg_01 reg_01;
+ #ifndef CONFIG_XEN
+@@ -1299,7 +1301,7 @@ static int __init timer_irq_works(void)
+ 	 */
+ 
+ 	/* jiffies wrap? */
+-	if (jiffies - t1 > 4)
++	if (time_after(jiffies, t1 + 4))
+ 		return 1;
+ 	return 0;
+ }
+@@ -1412,7 +1414,7 @@ static void irq_complete_move(unsigned i
+ 	if (likely(!cfg->move_in_progress))
+ 		return;
+ 
+-	vector = ~get_irq_regs()->orig_rax;
++	vector = ~get_irq_regs()->orig_ax;
+ 	me = smp_processor_id();
+ 	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
+ 		cpumask_t cleanup_mask;
+@@ -1439,7 +1441,7 @@ static void ack_apic_level(unsigned int 
+ 	int do_unmask_irq = 0;
+ 
+ 	irq_complete_move(irq);
+-#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
++#ifdef CONFIG_GENERIC_PENDING_IRQ
+ 	/* If we are moving the irq we need to mask it */
+ 	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+ 		do_unmask_irq = 1;
+@@ -1570,7 +1572,7 @@ static struct hw_interrupt_type lapic_ir
+ 	.end = end_lapic_irq,
+ };
+ 
+-static void setup_nmi (void)
++static void __init setup_nmi(void)
+ {
+ 	/*
+  	 * Dirty trick to enable the NMI watchdog ...
+@@ -1583,7 +1585,7 @@ static void setup_nmi (void)
+ 	 */ 
+ 	printk(KERN_INFO "activating NMI Watchdog ...");
+ 
+-	enable_NMI_through_LVT0(NULL);
++	enable_NMI_through_LVT0();
+ 
+ 	printk(" done.\n");
+ }
+@@ -1659,7 +1661,7 @@ static inline void unlock_ExtINT_logic(v
+  *
+  * FIXME: really need to revamp this for modern platforms only.
+  */
+-static inline void check_timer(void)
++static inline void __init check_timer(void)
+ {
+ 	struct irq_cfg *cfg = irq_cfg + 0;
+ 	int apic1, pin1, apic2, pin2;
+@@ -1863,7 +1865,7 @@ static int ioapic_resume(struct sys_devi
+ }
+ 
+ static struct sysdev_class ioapic_sysdev_class = {
+-	set_kset_name("ioapic"),
++	.name = "ioapic",
+ 	.suspend = ioapic_suspend,
+ 	.resume = ioapic_resume,
+ };
+@@ -2303,5 +2305,93 @@ void __init setup_ioapic_dest(void)
+ 	}
+ }
+ #endif
+-#endif /* !CONFIG_XEN */
+ 
++#define IOAPIC_RESOURCE_NAME_SIZE 11
++
++static struct resource *ioapic_resources;
++
++static struct resource * __init ioapic_setup_resources(void)
++{
++	unsigned long n;
++	struct resource *res;
++	char *mem;
++	int i;
++
++	if (nr_ioapics <= 0)
++		return NULL;
++
++	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
++	n *= nr_ioapics;
++
++	mem = alloc_bootmem(n);
++	res = (void *)mem;
++
++	if (mem != NULL) {
++		memset(mem, 0, n);
++		mem += sizeof(struct resource) * nr_ioapics;
++
++		for (i = 0; i < nr_ioapics; i++) {
++			res[i].name = mem;
++			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++			sprintf(mem,  "IOAPIC %u", i);
++			mem += IOAPIC_RESOURCE_NAME_SIZE;
++		}
++	}
++
++	ioapic_resources = res;
++
++	return res;
++}
++
++void __init ioapic_init_mappings(void)
++{
++	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
++	struct resource *ioapic_res;
++	int i;
++
++	ioapic_res = ioapic_setup_resources();
++	for (i = 0; i < nr_ioapics; i++) {
++		if (smp_found_config) {
++			ioapic_phys = mp_ioapics[i].mpc_apicaddr;
++		} else {
++			ioapic_phys = (unsigned long)
++				alloc_bootmem_pages(PAGE_SIZE);
++			ioapic_phys = __pa(ioapic_phys);
++		}
++		set_fixmap_nocache(idx, ioapic_phys);
++		apic_printk(APIC_VERBOSE,
++			    "mapped IOAPIC to %016lx (%016lx)\n",
++			    __fix_to_virt(idx), ioapic_phys);
++		idx++;
++
++		if (ioapic_res != NULL) {
++			ioapic_res->start = ioapic_phys;
++			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
++			ioapic_res++;
++		}
++	}
++}
++
++static int __init ioapic_insert_resources(void)
++{
++	int i;
++	struct resource *r = ioapic_resources;
++
++	if (!r) {
++		printk(KERN_ERR
++		       "IO APIC resources could be not be allocated.\n");
++		return -1;
++	}
++
++	for (i = 0; i < nr_ioapics; i++) {
++		insert_resource(&iomem_resource, r);
++		r++;
++	}
++
++	return 0;
++}
++
++/* Insert the IO APIC resources after PCI initialization has occured to handle
++ * IO APICS that are mapped in on a BAR in PCI space. */
++late_initcall(ioapic_insert_resources);
++#endif /* !CONFIG_XEN */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,112 @@
++/*
++ * This contains the io-permission bitmap code - written by obz, with changes
++ * by Linus. 32/64 bits code unification by Miguel Botón.
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/capability.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/ioport.h>
++#include <linux/smp.h>
++#include <linux/stddef.h>
++#include <linux/slab.h>
++#include <linux/thread_info.h>
++#include <linux/syscalls.h>
++#include <xen/interface/physdev.h>
++
++/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
++static void set_bitmap(unsigned long *bitmap, unsigned int base,
++		       unsigned int extent, int new_value)
++{
++	unsigned int i;
++
++	for (i = base; i < base + extent; i++) {
++		if (new_value)
++			__set_bit(i, bitmap);
++		else
++			__clear_bit(i, bitmap);
++	}
++}
++
++/*
++ * this changes the io permissions bitmap in the current task.
++ */
++asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
++{
++	struct thread_struct * t = &current->thread;
++	struct physdev_set_iobitmap set_iobitmap;
++
++	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
++		return -EINVAL;
++	if (turn_on && !capable(CAP_SYS_RAWIO))
++		return -EPERM;
++
++	/*
++	 * If it's the first ioperm() call in this thread's lifetime, set the
++	 * IO bitmap up. ioperm() is much less timing critical than clone(),
++	 * this is why we delay this operation until now:
++	 */
++	if (!t->io_bitmap_ptr) {
++		unsigned long *bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
++
++		if (!bitmap)
++			return -ENOMEM;
++
++		memset(bitmap, 0xff, IO_BITMAP_BYTES);
++		t->io_bitmap_ptr = bitmap;
++		set_thread_flag(TIF_IO_BITMAP);
++
++		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
++		set_iobitmap.nr_ports = IO_BITMAP_BITS;
++		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
++					      &set_iobitmap));
++	}
++
++	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
++
++	return 0;
++}
++
++/*
++ * sys_iopl has to be used when you want to access the IO ports
++ * beyond the 0x3ff range: to get the full 65536 ports bitmapped
++ * you'd need 8kB of bitmaps/process, which is a bit excessive.
++ */
++static int do_iopl(unsigned int level, struct thread_struct *t)
++{
++	unsigned int old = t->iopl >> 12;
++
++	if (level > 3)
++		return -EINVAL;
++	/* Trying to gain more privileges? */
++	if (level > old) {
++		if (!capable(CAP_SYS_RAWIO))
++			return -EPERM;
++	}
++
++	return 0;
++}
++
++#ifdef CONFIG_X86_32
++asmlinkage long sys_iopl(unsigned long regsp)
++{
++	struct pt_regs *regs = (struct pt_regs *)&regsp;
++	unsigned int level = regs->bx;
++#else
++asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
++{
++#endif
++	struct thread_struct *t = &current->thread;
++	int rc;
++
++	rc = do_iopl(level, t);
++	if (rc < 0)
++		goto out;
++
++	t->iopl = level << 12;
++	set_iopl_mask(t->iopl);
++out:
++	return rc;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,121 +0,0 @@
+-/*
+- * This contains the io-permission bitmap code - written by obz, with changes
+- * by Linus.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/capability.h>
+-#include <linux/errno.h>
+-#include <linux/types.h>
+-#include <linux/ioport.h>
+-#include <linux/smp.h>
+-#include <linux/stddef.h>
+-#include <linux/slab.h>
+-#include <linux/thread_info.h>
+-#include <linux/syscalls.h>
+-#include <xen/interface/physdev.h>
+-
+-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+-static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
+-{
+-	unsigned long mask;
+-	unsigned long *bitmap_base = bitmap + (base / BITS_PER_LONG);
+-	unsigned int low_index = base & (BITS_PER_LONG-1);
+-	int length = low_index + extent;
+-
+-	if (low_index != 0) {
+-		mask = (~0UL << low_index);
+-		if (length < BITS_PER_LONG)
+-			mask &= ~(~0UL << length);
+-		if (new_value)
+-			*bitmap_base++ |= mask;
+-		else
+-			*bitmap_base++ &= ~mask;
+-		length -= BITS_PER_LONG;
+-	}
+-
+-	mask = (new_value ? ~0UL : 0UL);
+-	while (length >= BITS_PER_LONG) {
+-		*bitmap_base++ = mask;
+-		length -= BITS_PER_LONG;
+-	}
+-
+-	if (length > 0) {
+-		mask = ~(~0UL << length);
+-		if (new_value)
+-			*bitmap_base++ |= mask;
+-		else
+-			*bitmap_base++ &= ~mask;
+-	}
+-}
+-
+-
+-/*
+- * this changes the io permissions bitmap in the current task.
+- */
+-asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+-{
+-	struct thread_struct * t = &current->thread;
+-	unsigned long *bitmap;
+-	struct physdev_set_iobitmap set_iobitmap;
+-
+-	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
+-		return -EINVAL;
+-	if (turn_on && !capable(CAP_SYS_RAWIO))
+-		return -EPERM;
+-
+-	/*
+-	 * If it's the first ioperm() call in this thread's lifetime, set the
+-	 * IO bitmap up. ioperm() is much less timing critical than clone(),
+-	 * this is why we delay this operation until now:
+-	 */
+-	if (!t->io_bitmap_ptr) {
+-		bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+-		if (!bitmap)
+-			return -ENOMEM;
+-
+-		memset(bitmap, 0xff, IO_BITMAP_BYTES);
+-		t->io_bitmap_ptr = bitmap;
+-		set_thread_flag(TIF_IO_BITMAP);
+-
+-		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
+-		set_iobitmap.nr_ports = IO_BITMAP_BITS;
+-		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+-					      &set_iobitmap));
+-	}
+-
+-	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+-
+-	return 0;
+-}
+-
+-/*
+- * sys_iopl has to be used when you want to access the IO ports
+- * beyond the 0x3ff range: to get the full 65536 ports bitmapped
+- * you'd need 8kB of bitmaps/process, which is a bit excessive.
+- *
+- * Here we just change the eflags value on the stack: we allow
+- * only the super-user to do it. This depends on the stack-layout
+- * on system-call entry - see also fork() and the signal handling
+- * code.
+- */
+-
+-asmlinkage long sys_iopl(unsigned long unused)
+-{
+-	volatile struct pt_regs * regs = (struct pt_regs *) &unused;
+-	unsigned int level = regs->ebx;
+-	struct thread_struct *t = &current->thread;
+-	unsigned int old = (t->iopl >> 12) & 3;
+-
+-	if (level > 3)
+-		return -EINVAL;
+-	/* Trying to gain more privileges? */
+-	if (level > old) {
+-		if (!capable(CAP_SYS_RAWIO))
+-			return -EPERM;
+-	}
+-	t->iopl = level << 12;
+-	set_iopl_mask(t->iopl);
+-	return 0;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,99 +0,0 @@
+-/*
+- * This contains the io-permission bitmap code - written by obz, with changes
+- * by Linus.
+- */
+-
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/capability.h>
+-#include <linux/errno.h>
+-#include <linux/types.h>
+-#include <linux/ioport.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/stddef.h>
+-#include <linux/slab.h>
+-#include <linux/thread_info.h>
+-#include <linux/syscalls.h>
+-#include <xen/interface/physdev.h>
+-
+-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+-static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
+-{
+-	int i;
+-
+-	if (new_value)
+-		for (i = base; i < base + extent; i++)
+-			__set_bit(i, bitmap);
+-	else
+-		for (i = base; i < base + extent; i++)
+-			clear_bit(i, bitmap);
+-}
+-
+-/*
+- * this changes the io permissions bitmap in the current task.
+- */
+-asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+-{
+-	struct thread_struct * t = &current->thread;
+-	unsigned long *bitmap;
+-	struct physdev_set_iobitmap set_iobitmap;
+-
+-	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
+-		return -EINVAL;
+-	if (turn_on && !capable(CAP_SYS_RAWIO))
+-		return -EPERM;
+-
+-	/*
+-	 * If it's the first ioperm() call in this thread's lifetime, set the
+-	 * IO bitmap up. ioperm() is much less timing critical than clone(),
+-	 * this is why we delay this operation until now:
+-	 */
+-	if (!t->io_bitmap_ptr) {
+-		bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+-		if (!bitmap)
+-			return -ENOMEM;
+-
+-		memset(bitmap, 0xff, IO_BITMAP_BYTES);
+-		t->io_bitmap_ptr = bitmap;
+-		set_thread_flag(TIF_IO_BITMAP);
+-
+-		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
+-		set_iobitmap.nr_ports = IO_BITMAP_BITS;
+-		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+-					      &set_iobitmap));
+-	}
+-
+-	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+-
+-	return 0;
+-}
+-
+-/*
+- * sys_iopl has to be used when you want to access the IO ports
+- * beyond the 0x3ff range: to get the full 65536 ports bitmapped
+- * you'd need 8kB of bitmaps/process, which is a bit excessive.
+- *
+- */
+-
+-asmlinkage long sys_iopl(unsigned int new_iopl, struct pt_regs *regs)
+-{
+-	unsigned int old_iopl = current->thread.iopl;
+-	struct physdev_set_iopl set_iopl;
+-
+-	if (new_iopl > 3)
+-		return -EINVAL;
+-
+-	/* Need "raw I/O" privileges for direct port access. */
+-	if ((new_iopl > old_iopl) && !capable(CAP_SYS_RAWIO))
+-		return -EPERM;
+-
+-	/* Change our version of the privilege levels. */
+-	current->thread.iopl = new_iopl;
+-
+-	/* Force the change at ring 0. */
+-	set_iopl.iopl = (new_iopl == 0) ? 1 : new_iopl;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+-
+-	return 0;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -66,11 +66,11 @@ static union irq_ctx *softirq_ctx[NR_CPU
+  * SMP cross-CPU interrupts have their own specific
+  * handlers).
+  */
+-fastcall unsigned int do_IRQ(struct pt_regs *regs)
++unsigned int do_IRQ(struct pt_regs *regs)
+ {	
+ 	struct pt_regs *old_regs;
+ 	/* high bit used in ret_from_ code */
+-	int irq = ~regs->orig_eax;
++	int irq = ~regs->orig_ax;
+ 	struct irq_desc *desc = irq_desc + irq;
+ #ifdef CONFIG_4KSTACKS
+ 	union irq_ctx *curctx, *irqctx;
+@@ -88,13 +88,13 @@ fastcall unsigned int do_IRQ(struct pt_r
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ 	/* Debugging check for stack overflow: is there less than 1KB free? */
+ 	{
+-		long esp;
++		long sp;
+ 
+ 		__asm__ __volatile__("andl %%esp,%0" :
+-					"=r" (esp) : "0" (THREAD_SIZE - 1));
+-		if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
++					"=r" (sp) : "0" (THREAD_SIZE - 1));
++		if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+ 			printk("do_IRQ: stack overflow: %ld\n",
+-				esp - sizeof(struct thread_info));
++				sp - sizeof(struct thread_info));
+ 			dump_stack();
+ 		}
+ 	}
+@@ -112,7 +112,7 @@ fastcall unsigned int do_IRQ(struct pt_r
+ 	 * current stack (which is the irq stack already after all)
+ 	 */
+ 	if (curctx != irqctx) {
+-		int arg1, arg2, ebx;
++		int arg1, arg2, bx;
+ 
+ 		/* build the stack frame on the IRQ stack */
+ 		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
+@@ -128,10 +128,10 @@ fastcall unsigned int do_IRQ(struct pt_r
+ 			(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+ 
+ 		asm volatile(
+-			"       xchgl  %%ebx,%%esp      \n"
+-			"       call   *%%edi           \n"
+-			"       movl   %%ebx,%%esp      \n"
+-			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
++			"       xchgl  %%ebx,%%esp    \n"
++			"       call   *%%edi         \n"
++			"       movl   %%ebx,%%esp    \n"
++			: "=a" (arg1), "=d" (arg2), "=b" (bx)
+ 			:  "0" (irq),   "1" (desc),  "2" (isp),
+ 			   "D" (desc->handle_irq)
+ 			: "memory", "cc"
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -20,6 +20,28 @@
+ 
+ atomic_t irq_err_count;
+ 
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++	printk(KERN_WARNING "unexpected IRQ trap at irq %02x\n", irq);
++#ifdef CONFIG_X86_LOCAL_APIC
++	/*
++	 * Currently unexpected vectors happen only on SMP and APIC.
++	 * We _must_ ack these because every local APIC has only N
++	 * irq slots per priority level, and a 'hanging, unacked' IRQ
++	 * holds up an irq slot - in excessive cases (when multiple
++	 * unexpected vectors occur) that might lock up the APIC
++	 * completely.
++	 * But don't ack when the APIC is disabled. -AK
++	 */
++	if (!disable_apic)
++		ack_APIC_irq();
++#endif
++}
++
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /*
+  * Probabilistic stack overflow check:
+@@ -33,11 +55,11 @@ static inline void stack_overflow_check(
+ 	u64 curbase = (u64)task_stack_page(current);
+ 	static unsigned long warned = -60*HZ;
+ 
+-	if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
+-	    regs->rsp <  curbase + sizeof(struct thread_info) + 128 &&
++	if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
++	    regs->sp <  curbase + sizeof(struct thread_info) + 128 &&
+ 	    time_after(jiffies, warned + 60*HZ)) {
+-		printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n",
+-		       current->comm, curbase, regs->rsp);
++		printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
++		       current->comm, curbase, regs->sp);
+ 		show_stack(NULL,NULL);
+ 		warned = jiffies;
+ 	}
+@@ -150,7 +172,7 @@ asmlinkage unsigned int do_IRQ(struct pt
+ 	struct pt_regs *old_regs = set_irq_regs(regs);
+ 
+ 	/* high bit used in ret_from_ code  */
+-	unsigned irq = ~regs->orig_rax;
++	unsigned irq = ~regs->orig_ax;
+ 
+ 	/*exit_idle();*/
+ 	/*irq_enter();*/
+@@ -251,14 +273,3 @@ asmlinkage void do_softirq(void)
+ 	}
+  	local_irq_restore(flags);
+ }
+-
+-#ifndef CONFIG_X86_LOCAL_APIC
+-/*
+- * 'what should we do if we get a hw irq event on an illegal vector'.
+- * each architecture has to answer this themselves.
+- */
+-void ack_bad_irq(unsigned int irq)
+-{
+-        printk("unexpected IRQ trap at irq %02x\n", irq);
+-}
+-#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,272 @@
++/*
++ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
++ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ * Copyright (C) 2002 Andi Kleen
++ *
++ * This handles calls from both 32bit and 64bit mode.
++ */
++
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/vmalloc.h>
++
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/ldt.h>
++#include <asm/desc.h>
++#include <asm/mmu_context.h>
++
++#ifdef CONFIG_SMP
++static void flush_ldt(void *null)
++{
++	if (current->active_mm)
++		load_LDT(&current->active_mm->context);
++}
++#endif
++
++static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
++{
++	void *oldldt, *newldt;
++	int oldsize;
++
++	if (mincount <= pc->size)
++		return 0;
++	oldsize = pc->size;
++	mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
++			(~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
++	if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
++		newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
++	else
++		newldt = (void *)__get_free_page(GFP_KERNEL);
++
++	if (!newldt)
++		return -ENOMEM;
++
++	if (oldsize)
++		memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
++	oldldt = pc->ldt;
++	memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
++	       (mincount - oldsize) * LDT_ENTRY_SIZE);
++
++#ifdef CONFIG_X86_64
++	/* CHECKME: Do we really need this ? */
++	wmb();
++#endif
++	pc->ldt = newldt;
++	wmb();
++	pc->size = mincount;
++	wmb();
++
++	if (reload) {
++#ifdef CONFIG_SMP
++		cpumask_t mask;
++
++		preempt_disable();
++#endif
++		make_pages_readonly(newldt,
++				    (mincount * LDT_ENTRY_SIZE) / PAGE_SIZE,
++				    XENFEAT_writable_descriptor_tables);
++		load_LDT(pc);
++#ifdef CONFIG_SMP
++		mask = cpumask_of_cpu(smp_processor_id());
++		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
++			smp_call_function(flush_ldt, NULL, 1, 1);
++		preempt_enable();
++#endif
++	}
++	if (oldsize) {
++		make_pages_writable(oldldt,
++				    (oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
++				    XENFEAT_writable_descriptor_tables);
++		if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(oldldt);
++		else
++			put_page(virt_to_page(oldldt));
++	}
++	return 0;
++}
++
++static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
++{
++	int err = alloc_ldt(new, old->size, 0);
++
++	if (err < 0)
++		return err;
++	memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE);
++	make_pages_readonly(new->ldt,
++			    (new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++			    XENFEAT_writable_descriptor_tables);
++	return 0;
++}
++
++/*
++ * we do not have to muck with descriptors here, that is
++ * done in switch_mm() as needed.
++ */
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++	struct mm_struct *old_mm;
++	int retval = 0;
++
++	memset(&mm->context, 0, sizeof(mm->context));
++	mutex_init(&mm->context.lock);
++	old_mm = current->mm;
++	if (old_mm)
++		mm->context.vdso = old_mm->context.vdso;
++	if (old_mm && old_mm->context.size > 0) {
++		mutex_lock(&old_mm->context.lock);
++		retval = copy_ldt(&mm->context, &old_mm->context);
++		mutex_unlock(&old_mm->context.lock);
++	}
++	return retval;
++}
++
++/*
++ * No need to lock the MM as we are the last user
++ *
++ * 64bit: Don't touch the LDT register - we're already in the next thread.
++ */
++void destroy_context(struct mm_struct *mm)
++{
++	if (mm->context.size) {
++		/* CHECKME: Can this ever happen ? */
++		if (mm == current->active_mm)
++			clear_LDT();
++		make_pages_writable(mm->context.ldt,
++				    (mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
++				    XENFEAT_writable_descriptor_tables);
++		if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
++			vfree(mm->context.ldt);
++		else
++			put_page(virt_to_page(mm->context.ldt));
++		mm->context.size = 0;
++	}
++}
++
++static int read_ldt(void __user *ptr, unsigned long bytecount)
++{
++	int err;
++	unsigned long size;
++	struct mm_struct *mm = current->mm;
++
++	if (!mm->context.size)
++		return 0;
++	if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
++		bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
++
++	mutex_lock(&mm->context.lock);
++	size = mm->context.size * LDT_ENTRY_SIZE;
++	if (size > bytecount)
++		size = bytecount;
++
++	err = 0;
++	if (copy_to_user(ptr, mm->context.ldt, size))
++		err = -EFAULT;
++	mutex_unlock(&mm->context.lock);
++	if (err < 0)
++		goto error_return;
++	if (size != bytecount) {
++		/* zero-fill the rest */
++		if (clear_user(ptr + size, bytecount - size) != 0) {
++			err = -EFAULT;
++			goto error_return;
++		}
++	}
++	return bytecount;
++error_return:
++	return err;
++}
++
++static int read_default_ldt(void __user *ptr, unsigned long bytecount)
++{
++	/* CHECKME: Can we use _one_ random number ? */
++#ifdef CONFIG_X86_32
++	unsigned long size = 5 * sizeof(struct desc_struct);
++#else
++	unsigned long size = 128;
++#endif
++	if (bytecount > size)
++		bytecount = size;
++	if (clear_user(ptr, bytecount))
++		return -EFAULT;
++	return bytecount;
++}
++
++static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
++{
++	struct mm_struct *mm = current->mm;
++	struct desc_struct ldt;
++	int error;
++	struct user_desc ldt_info;
++
++	error = -EINVAL;
++	if (bytecount != sizeof(ldt_info))
++		goto out;
++	error = -EFAULT;
++	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
++		goto out;
++
++	error = -EINVAL;
++	if (ldt_info.entry_number >= LDT_ENTRIES)
++		goto out;
++	if (ldt_info.contents == 3) {
++		if (oldmode)
++			goto out;
++		if (ldt_info.seg_not_present == 0)
++			goto out;
++	}
++
++	mutex_lock(&mm->context.lock);
++	if (ldt_info.entry_number >= mm->context.size) {
++		error = alloc_ldt(&current->mm->context,
++				  ldt_info.entry_number + 1, 1);
++		if (error < 0)
++			goto out_unlock;
++	}
++
++	/* Allow LDTs to be cleared by the user. */
++	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
++		if (oldmode || LDT_empty(&ldt_info)) {
++			memset(&ldt, 0, sizeof(ldt));
++			goto install;
++		}
++	}
++
++	fill_ldt(&ldt, &ldt_info);
++	if (oldmode)
++		ldt.avl = 0;
++
++	/* Install the new entry ...  */
++install:
++	error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
++
++out_unlock:
++	mutex_unlock(&mm->context.lock);
++out:
++	return error;
++}
++
++asmlinkage int sys_modify_ldt(int func, void __user *ptr,
++			      unsigned long bytecount)
++{
++	int ret = -ENOSYS;
++
++	switch (func) {
++	case 0:
++		ret = read_ldt(ptr, bytecount);
++		break;
++	case 1:
++		ret = write_ldt(ptr, bytecount, 1);
++		break;
++	case 2:
++		ret = read_default_ldt(ptr, bytecount);
++		break;
++	case 0x11:
++		ret = write_ldt(ptr, bytecount, 0);
++		break;
++	}
++	return ret;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,265 +0,0 @@
+-/*
+- * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/vmalloc.h>
+-#include <linux/slab.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/ldt.h>
+-#include <asm/desc.h>
+-#include <asm/mmu_context.h>
+-
+-#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
+-static void flush_ldt(void *null)
+-{
+-	if (current->active_mm)
+-		load_LDT(&current->active_mm->context);
+-}
+-#endif
+-
+-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+-{
+-	void *oldldt;
+-	void *newldt;
+-	int oldsize;
+-
+-	if (mincount <= pc->size)
+-		return 0;
+-	oldsize = pc->size;
+-	mincount = (mincount+511)&(~511);
+-	if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
+-		newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
+-	else
+-		newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
+-
+-	if (!newldt)
+-		return -ENOMEM;
+-
+-	if (oldsize)
+-		memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
+-	oldldt = pc->ldt;
+-	memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
+-	pc->ldt = newldt;
+-	wmb();
+-	pc->size = mincount;
+-	wmb();
+-
+-	if (reload) {
+-#ifdef CONFIG_SMP
+-		cpumask_t mask;
+-		preempt_disable();
+-#endif
+-		make_pages_readonly(
+-			pc->ldt,
+-			(pc->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		load_LDT(pc);
+-#ifdef CONFIG_SMP
+-		mask = cpumask_of_cpu(smp_processor_id());
+-		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
+-			smp_call_function(flush_ldt, NULL, 1, 1);
+-		preempt_enable();
+-#endif
+-	}
+-	if (oldsize) {
+-		make_pages_writable(
+-			oldldt,
+-			(oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
+-			vfree(oldldt);
+-		else
+-			kfree(oldldt);
+-	}
+-	return 0;
+-}
+-
+-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+-{
+-	int err = alloc_ldt(new, old->size, 0);
+-	if (err < 0)
+-		return err;
+-	memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
+-	make_pages_readonly(
+-		new->ldt,
+-		(new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-		XENFEAT_writable_descriptor_tables);
+-	return 0;
+-}
+-
+-/*
+- * we do not have to muck with descriptors here, that is
+- * done in switch_mm() as needed.
+- */
+-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+-{
+-	struct mm_struct * old_mm;
+-	int retval = 0;
+-
+-	mutex_init(&mm->context.lock);
+-	mm->context.size = 0;
+-	mm->context.has_foreign_mappings = 0;
+-	old_mm = current->mm;
+-	if (old_mm && old_mm->context.size > 0) {
+-		mutex_lock(&old_mm->context.lock);
+-		retval = copy_ldt(&mm->context, &old_mm->context);
+-		mutex_unlock(&old_mm->context.lock);
+-	}
+-	return retval;
+-}
+-
+-/*
+- * No need to lock the MM as we are the last user
+- */
+-void destroy_context(struct mm_struct *mm)
+-{
+-	if (mm->context.size) {
+-		if (mm == current->active_mm)
+-			clear_LDT();
+-		make_pages_writable(
+-			mm->context.ldt,
+-			(mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
+-			vfree(mm->context.ldt);
+-		else
+-			kfree(mm->context.ldt);
+-		mm->context.size = 0;
+-	}
+-}
+-
+-static int read_ldt(void __user * ptr, unsigned long bytecount)
+-{
+-	int err;
+-	unsigned long size;
+-	struct mm_struct * mm = current->mm;
+-
+-	if (!mm->context.size)
+-		return 0;
+-	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+-		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+-
+-	mutex_lock(&mm->context.lock);
+-	size = mm->context.size*LDT_ENTRY_SIZE;
+-	if (size > bytecount)
+-		size = bytecount;
+-
+-	err = 0;
+-	if (copy_to_user(ptr, mm->context.ldt, size))
+-		err = -EFAULT;
+-	mutex_unlock(&mm->context.lock);
+-	if (err < 0)
+-		goto error_return;
+-	if (size != bytecount) {
+-		/* zero-fill the rest */
+-		if (clear_user(ptr+size, bytecount-size) != 0) {
+-			err = -EFAULT;
+-			goto error_return;
+-		}
+-	}
+-	return bytecount;
+-error_return:
+-	return err;
+-}
+-
+-static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+-{
+-	int err;
+-	unsigned long size;
+-
+-	err = 0;
+-	size = 5*sizeof(struct desc_struct);
+-	if (size > bytecount)
+-		size = bytecount;
+-
+-	err = size;
+-	if (clear_user(ptr, size))
+-		err = -EFAULT;
+-
+-	return err;
+-}
+-
+-static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
+-{
+-	struct mm_struct * mm = current->mm;
+-	__u32 entry_1, entry_2;
+-	int error;
+-	struct user_desc ldt_info;
+-
+-	error = -EINVAL;
+-	if (bytecount != sizeof(ldt_info))
+-		goto out;
+-	error = -EFAULT; 	
+-	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (ldt_info.entry_number >= LDT_ENTRIES)
+-		goto out;
+-	if (ldt_info.contents == 3) {
+-		if (oldmode)
+-			goto out;
+-		if (ldt_info.seg_not_present == 0)
+-			goto out;
+-	}
+-
+-	mutex_lock(&mm->context.lock);
+-	if (ldt_info.entry_number >= mm->context.size) {
+-		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
+-		if (error < 0)
+-			goto out_unlock;
+-	}
+-
+-   	/* Allow LDTs to be cleared by the user. */
+-   	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+-		if (oldmode || LDT_empty(&ldt_info)) {
+-			entry_1 = 0;
+-			entry_2 = 0;
+-			goto install;
+-		}
+-	}
+-
+-	entry_1 = LDT_entry_a(&ldt_info);
+-	entry_2 = LDT_entry_b(&ldt_info);
+-	if (oldmode)
+-		entry_2 &= ~(1 << 20);
+-
+-	/* Install the new entry ...  */
+-install:
+-	error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+-				entry_1, entry_2);
+-
+-out_unlock:
+-	mutex_unlock(&mm->context.lock);
+-out:
+-	return error;
+-}
+-
+-asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+-{
+-	int ret = -ENOSYS;
+-
+-	switch (func) {
+-	case 0:
+-		ret = read_ldt(ptr, bytecount);
+-		break;
+-	case 1:
+-		ret = write_ldt(ptr, bytecount, 1);
+-		break;
+-	case 2:
+-		ret = read_default_ldt(ptr, bytecount);
+-		break;
+-	case 0x11:
+-		ret = write_ldt(ptr, bytecount, 0);
+-		break;
+-	}
+-	return ret;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,271 +0,0 @@
+-/*
+- * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+- * Copyright (C) 2002 Andi Kleen
+- * 
+- * This handles calls from both 32bit and 64bit mode.
+- */
+-
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/vmalloc.h>
+-#include <linux/slab.h>
+-
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <asm/ldt.h>
+-#include <asm/desc.h>
+-#include <asm/proto.h>
+-#include <asm/pgalloc.h>
+-
+-#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
+-static void flush_ldt(void *null)
+-{
+-	if (current->active_mm)
+-               load_LDT(&current->active_mm->context);
+-}
+-#endif
+-
+-static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload)
+-{
+-	void *oldldt;
+-	void *newldt;
+-	unsigned oldsize;
+-
+-	if (mincount <= (unsigned)pc->size)
+-		return 0;
+-	oldsize = pc->size;
+-	mincount = (mincount+511)&(~511);
+-	if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
+-		newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
+-	else
+-		newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
+-
+-	if (!newldt)
+-		return -ENOMEM;
+-
+-	if (oldsize)
+-		memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
+-	oldldt = pc->ldt;
+-	memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
+-	wmb();
+-	pc->ldt = newldt;
+-	wmb();
+-	pc->size = mincount;
+-	wmb();
+-	if (reload) {
+-#ifdef CONFIG_SMP
+-		cpumask_t mask;
+-
+-		preempt_disable();
+-#endif
+-		make_pages_readonly(
+-			pc->ldt,
+-			(pc->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		load_LDT(pc);
+-#ifdef CONFIG_SMP
+-		mask = cpumask_of_cpu(smp_processor_id());
+-		if (!cpus_equal(current->mm->cpu_vm_mask, mask))
+-			smp_call_function(flush_ldt, NULL, 1, 1);
+-		preempt_enable();
+-#endif
+-	}
+-	if (oldsize) {
+-		make_pages_writable(
+-			oldldt,
+-			(oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
+-			vfree(oldldt);
+-		else
+-			kfree(oldldt);
+-	}
+-	return 0;
+-}
+-
+-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+-{
+-	int err = alloc_ldt(new, old->size, 0);
+-	if (err < 0)
+-		return err;
+-	memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
+-	make_pages_readonly(
+-		new->ldt,
+-		(new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-		XENFEAT_writable_descriptor_tables);
+-	return 0;
+-}
+-
+-/*
+- * we do not have to muck with descriptors here, that is
+- * done in switch_mm() as needed.
+- */
+-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+-{
+-	struct mm_struct * old_mm;
+-	int retval = 0;
+-
+-	memset(&mm->context, 0, sizeof(mm->context));
+-	mutex_init(&mm->context.lock);
+-	old_mm = current->mm;
+-	if (old_mm)
+-		mm->context.vdso = old_mm->context.vdso;
+-	if (old_mm && old_mm->context.size > 0) {
+-		mutex_lock(&old_mm->context.lock);
+-		retval = copy_ldt(&mm->context, &old_mm->context);
+-		mutex_unlock(&old_mm->context.lock);
+-	}
+-	return retval;
+-}
+-
+-/*
+- * 
+- * Don't touch the LDT register - we're already in the next thread.
+- */
+-void destroy_context(struct mm_struct *mm)
+-{
+-	if (mm->context.size) {
+-		if (mm == current->active_mm)
+-			clear_LDT();
+-		make_pages_writable(
+-			mm->context.ldt,
+-			(mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+-			XENFEAT_writable_descriptor_tables);
+-		if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
+-			vfree(mm->context.ldt);
+-		else
+-			kfree(mm->context.ldt);
+-		mm->context.size = 0;
+-	}
+-}
+-
+-static int read_ldt(void __user * ptr, unsigned long bytecount)
+-{
+-	int err;
+-	unsigned long size;
+-	struct mm_struct * mm = current->mm;
+-
+-	if (!mm->context.size)
+-		return 0;
+-	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+-		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+-
+-	mutex_lock(&mm->context.lock);
+-	size = mm->context.size*LDT_ENTRY_SIZE;
+-	if (size > bytecount)
+-		size = bytecount;
+-
+-	err = 0;
+-	if (copy_to_user(ptr, mm->context.ldt, size))
+-		err = -EFAULT;
+-	mutex_unlock(&mm->context.lock);
+-	if (err < 0)
+-		goto error_return;
+-	if (size != bytecount) {
+-		/* zero-fill the rest */
+-		if (clear_user(ptr+size, bytecount-size) != 0) {
+-			err = -EFAULT;
+-			goto error_return;
+-		}
+-	}
+-	return bytecount;
+-error_return:
+-	return err;
+-}
+-
+-static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+-{
+-	/* Arbitrary number */ 
+-	/* x86-64 default LDT is all zeros */
+-	if (bytecount > 128) 
+-		bytecount = 128; 	
+-	if (clear_user(ptr, bytecount))
+-		return -EFAULT;
+-	return bytecount; 
+-}
+-
+-static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
+-{
+-	struct task_struct *me = current;
+-	struct mm_struct * mm = me->mm;
+-	__u32 entry_1, entry_2, *lp;
+-	unsigned long mach_lp;
+-	int error;
+-	struct user_desc ldt_info;
+-
+-	error = -EINVAL;
+-
+-	if (bytecount != sizeof(ldt_info))
+-		goto out;
+-	error = -EFAULT; 	
+-	if (copy_from_user(&ldt_info, ptr, bytecount))
+-		goto out;
+-
+-	error = -EINVAL;
+-	if (ldt_info.entry_number >= LDT_ENTRIES)
+-		goto out;
+-	if (ldt_info.contents == 3) {
+-		if (oldmode)
+-			goto out;
+-		if (ldt_info.seg_not_present == 0)
+-			goto out;
+-	}
+-
+-	mutex_lock(&mm->context.lock);
+-	if (ldt_info.entry_number >= (unsigned)mm->context.size) {
+-		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
+-		if (error < 0)
+-			goto out_unlock;
+-	}
+-
+-	lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
+- 	mach_lp = arbitrary_virt_to_machine(lp);
+-
+-   	/* Allow LDTs to be cleared by the user. */
+-   	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+-		if (oldmode || LDT_empty(&ldt_info)) {
+-			entry_1 = 0;
+-			entry_2 = 0;
+-			goto install;
+-		}
+-	}
+-
+-	entry_1 = LDT_entry_a(&ldt_info);
+-	entry_2 = LDT_entry_b(&ldt_info);
+-	if (oldmode)
+-		entry_2 &= ~(1 << 20);
+-
+-	/* Install the new entry ...  */
+-install:
+-	error = HYPERVISOR_update_descriptor(mach_lp, (unsigned long)((entry_1 | (unsigned long) entry_2 << 32)));
+-
+-out_unlock:
+-	mutex_unlock(&mm->context.lock);
+-out:
+-	return error;
+-}
+-
+-asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+-{
+-	int ret = -ENOSYS;
+-
+-	switch (func) {
+-	case 0:
+-		ret = read_ldt(ptr, bytecount);
+-		break;
+-	case 1:
+-		ret = write_ldt(ptr, bytecount, 1);
+-		break;
+-	case 2:
+-		ret = read_default_ldt(ptr, bytecount);
+-		break;
+-	case 0x11:
+-		ret = write_ldt(ptr, bytecount, 0);
+-		break;
+-	}
+-	return ret;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/machine_kexec_64.c	2009-12-04 10:44:49.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/machine_kexec_64.c	2009-11-06 10:51:25.000000000 +0100
+@@ -404,7 +404,9 @@ void machine_kexec(struct kimage *image)
+ 
+ void arch_crash_save_vmcoreinfo(void)
+ {
++#ifndef CONFIG_XEN /* could really be CONFIG_RELOCATABLE */
+ 	VMCOREINFO_SYMBOL(phys_base);
++#endif
+ 	VMCOREINFO_SYMBOL(init_level4_pgt);
+ 
+ #ifdef CONFIG_NUMA
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -167,7 +167,7 @@ static int request_microcode(void)
+ 	}
+ 
+ 	op.cmd = XENPF_microcode_update;
+-	set_xen_guest_handle(op.u.microcode.data, (void *)firmware->data);
++	set_xen_guest_handle(op.u.microcode.data, firmware->data);
+ 	op.u.microcode.length = firmware->size;
+ 	error = HYPERVISOR_platform_op(&op);
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -68,7 +68,7 @@ unsigned int def_to_bigsmp = 0;
+ /* Processor that is doing the boot up */
+ unsigned int boot_cpu_physical_apicid = -1U;
+ /* Internal processor count */
+-unsigned int __cpuinitdata num_processors;
++unsigned int num_processors;
+ 
+ /* Bitmask of physically existing CPUs */
+ physid_mask_t phys_cpu_present_map;
+@@ -265,7 +265,7 @@ static void __init MP_ioapic_info (struc
+ 	if (!(m->mpc_flags & MPC_APIC_USABLE))
+ 		return;
+ 
+-	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
++	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+ 		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+ 	if (nr_ioapics >= MAX_IO_APICS) {
+ 		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
+@@ -412,9 +412,9 @@ static int __init smp_read_mpc(struct mp
+ 
+ 	mps_oem_check(mpc, oem, str);
+ 
+-	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
++	printk("APIC at: 0x%X\n", mpc->mpc_lapic);
+ 
+-	/* 
++	/*
+ 	 * Save the local APIC address (it might be non-default) -- but only
+ 	 * if we're not using ACPI.
+ 	 */
+@@ -728,7 +728,7 @@ static int __init smp_scan_config (unsig
+ 	unsigned long *bp = isa_bus_to_virt(base);
+ 	struct intel_mp_floating *mpf;
+ 
+-	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
++	printk(KERN_INFO "Scan SMP from %p for %ld bytes.\n", bp,length);
+ 	if (sizeof(*mpf) != 16)
+ 		printk("Error: MPF size\n");
+ 
+@@ -742,9 +742,10 @@ static int __init smp_scan_config (unsig
+ 
+ 			smp_found_config = 1;
+ #ifndef CONFIG_XEN
+-			printk(KERN_INFO "found SMP MP-table at %08lx\n",
+-						virt_to_phys(mpf));
+-			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
++			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++				mpf, virt_to_phys(mpf));
++			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE,
++					BOOTMEM_DEFAULT);
+ 			if (mpf->mpf_physptr) {
+ 				/*
+ 				 * We cannot access to MPC table to compute
+@@ -759,11 +760,12 @@ static int __init smp_scan_config (unsig
+ 				unsigned long end = max_low_pfn * PAGE_SIZE;
+ 				if (mpf->mpf_physptr + size > end)
+ 					size = end - mpf->mpf_physptr;
+-				reserve_bootmem(mpf->mpf_physptr, size);
++				reserve_bootmem(mpf->mpf_physptr, size,
++						BOOTMEM_DEFAULT);
+ 			}
+ #else
+-			printk(KERN_INFO "found SMP MP-table at %08lx\n",
+-				((unsigned long)bp - (unsigned long)isa_bus_to_virt(base)) + base);
++			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
++				mpf, ((void *)bp - isa_bus_to_virt(base)) + base);
+ #endif
+ 
+ 			mpf_found = mpf;
+@@ -940,14 +942,14 @@ void __init mp_register_ioapic(u8 id, u3
+ 	 */
+ 	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid;
+ 	mp_ioapic_routing[idx].gsi_base = gsi_base;
+-	mp_ioapic_routing[idx].gsi_end = gsi_base + 
++	mp_ioapic_routing[idx].gsi_end = gsi_base +
+ 		io_apic_get_redir_entries(idx);
+ 
+-	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, "
+-		"GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
+-		mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+-		mp_ioapic_routing[idx].gsi_base,
+-		mp_ioapic_routing[idx].gsi_end);
++	printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
++	       "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid,
++	       mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
++	       mp_ioapic_routing[idx].gsi_base,
++	       mp_ioapic_routing[idx].gsi_end);
+ }
+ 
+ void __init
+@@ -1063,15 +1065,16 @@ void __init mp_config_acpi_legacy_irqs (
+ }
+ 
+ #define MAX_GSI_NUM	4096
++#define IRQ_COMPRESSION_START	64
+ 
+ int mp_register_gsi(u32 gsi, int triggering, int polarity)
+ {
+ 	int ioapic = -1;
+ 	int ioapic_pin = 0;
+ 	int idx, bit = 0;
+-	static int pci_irq = 16;
++	static int pci_irq = IRQ_COMPRESSION_START;
+ 	/*
+-	 * Mapping between Global System Interrups, which
++	 * Mapping between Global System Interrupts, which
+ 	 * represent all possible interrupts, and IRQs
+ 	 * assigned to actual devices.
+ 	 */
+@@ -1108,12 +1111,16 @@ int mp_register_gsi(u32 gsi, int trigger
+ 	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+ 		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
+ 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+-		return gsi_to_irq[gsi];
++		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+ 	}
+ 
+ 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ 
+-	if (triggering == ACPI_LEVEL_SENSITIVE) {
++	/*
++	 * For GSI >= 64, use IRQ compression
++	 */
++	if ((gsi >= IRQ_COMPRESSION_START)
++		&& (triggering == ACPI_LEVEL_SENSITIVE)) {
+ 		/*
+ 		 * For PCI devices assign IRQs in order, avoiding gaps
+ 		 * due to unused I/O APIC pins.
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -60,14 +60,20 @@ unsigned int boot_cpu_id = -1U;
+ EXPORT_SYMBOL(boot_cpu_id);
+ 
+ /* Internal processor count */
+-unsigned int num_processors __cpuinitdata = 0;
++unsigned int num_processors;
+ 
+ unsigned disabled_cpus __cpuinitdata;
+ 
+ /* Bitmask of physically existing CPUs */
+ physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+ 
+-u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
++#ifndef CONFIG_XEN
++u16 x86_bios_cpu_apicid_init[NR_CPUS] __initdata
++				= { [0 ... NR_CPUS-1] = BAD_APICID };
++void *x86_bios_cpu_apicid_early_ptr;
++#endif
++DEFINE_PER_CPU(u16, x86_bios_cpu_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
+ 
+ 
+ /*
+@@ -119,24 +125,22 @@ static void __cpuinit MP_processor_info(
+ 	physid_set(m->mpc_apicid, phys_cpu_present_map);
+  	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+  		/*
+- 		 * bios_cpu_apicid is required to have processors listed
++		 * x86_bios_cpu_apicid is required to have processors listed
+  		 * in same order as logical cpu numbers. Hence the first
+  		 * entry is BSP, and so on.
+  		 */
+ 		cpu = 0;
+  	}
+-	bios_cpu_apicid[cpu] = m->mpc_apicid;
+-	/*
+-	 * We get called early in the the start_kernel initialization
+-	 * process when the per_cpu data area is not yet setup, so we
+-	 * use a static array that is removed after the per_cpu data
+-	 * area is created.
+-	 */
+-	if (x86_cpu_to_apicid_ptr) {
+-		u8 *x86_cpu_to_apicid = (u8 *)x86_cpu_to_apicid_ptr;
+-		x86_cpu_to_apicid[cpu] = m->mpc_apicid;
++	/* are we being called early in kernel startup? */
++	if (x86_cpu_to_apicid_early_ptr) {
++		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
++		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;
++
++		cpu_to_apicid[cpu] = m->mpc_apicid;
++		bios_cpu_apicid[cpu] = m->mpc_apicid;
+ 	} else {
+ 		per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
++		per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
+ 	}
+ 
+ 	cpu_set(cpu, cpu_possible_map);
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -431,3 +431,23 @@ dma_sync_single_for_device(struct device
+ 		swiotlb_sync_single_for_device(dev, dma_handle, size, direction);
+ }
+ EXPORT_SYMBOL(dma_sync_single_for_device);
++
++void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++		    enum dma_data_direction direction)
++{
++	if (swiotlb)
++		swiotlb_sync_sg_for_cpu(dev,sg,nelems,direction);
++	flush_write_buffers();
++}
++EXPORT_SYMBOL(dma_sync_sg_for_cpu);
++
++void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++		    enum dma_data_direction direction)
++{
++	if (swiotlb)
++		swiotlb_sync_sg_for_device(dev,sg,nelems,direction);
++	flush_write_buffers();
++}
++EXPORT_SYMBOL(dma_sync_sg_for_device);
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -23,7 +23,6 @@
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/user.h>
+-#include <linux/a.out.h>
+ #include <linux/interrupt.h>
+ #include <linux/utsname.h>
+ #include <linux/delay.h>
+@@ -59,8 +58,10 @@
+ 
+ #include <asm/tlbflush.h>
+ #include <asm/cpu.h>
++#include <asm/kdebug.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+ 
+ static int hlt_counter;
+ 
+@@ -78,7 +79,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_number);
+  */
+ unsigned long thread_saved_pc(struct task_struct *tsk)
+ {
+-	return ((unsigned long *)tsk->thread.esp)[3];
++	return ((unsigned long *)tsk->thread.sp)[3];
+ }
+ 
+ /*
+@@ -86,7 +87,6 @@ unsigned long thread_saved_pc(struct tas
+  */
+ void (*pm_idle)(void);
+ EXPORT_SYMBOL(pm_idle);
+-static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
+ 
+ void disable_hlt(void)
+ {
+@@ -107,7 +107,7 @@ EXPORT_SYMBOL(enable_hlt);
+  * to poll the ->work.need_resched flag instead of waiting for the
+  * cross-CPU IPI to arrive. Use this option with caution.
+  */
+-static void poll_idle (void)
++static void poll_idle(void)
+ {
+ 	cpu_relax();
+ }
+@@ -122,10 +122,19 @@ static void xen_idle(void)
+ 	smp_mb();
+ 
+ 	local_irq_disable();
+-	if (!need_resched())
++	if (!need_resched()) {
++		ktime_t t0, t1;
++		u64 t0n, t1n;
++
++		t0 = ktime_get();
++		t0n = ktime_to_ns(t0);
+ 		safe_halt();	/* enables interrupts racelessly */
+-	else
+-		local_irq_enable();
++		local_irq_disable();
++		t1 = ktime_get();
++		t1n = ktime_to_ns(t1);
++		sched_clock_idle_wakeup_event(t1n - t0n);
++	}
++	local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+ }
+ #ifdef CONFIG_APM_MODULE
+@@ -168,13 +177,13 @@ void cpu_idle(void)
+ 		while (!need_resched()) {
+ 			void (*idle)(void);
+ 
+-			if (__get_cpu_var(cpu_idle_state))
+-				__get_cpu_var(cpu_idle_state) = 0;
+-
+ 			check_pgt_cache();
+ 			rmb();
+ 			idle = xen_idle; /* no alternatives */
+ 
++			if (rcu_pending(cpu))
++				rcu_check_callbacks(cpu, 0);
++
+ 			if (cpu_is_offline(cpu))
+ 				play_dead();
+ 
+@@ -192,40 +201,19 @@ static void do_nothing(void *unused)
+ {
+ }
+ 
++/*
++ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
++ * pm_idle and update to new pm_idle value. Required while changing pm_idle
++ * handler on SMP systems.
++ *
++ * Caller must have changed pm_idle to the new value before the call. Old
++ * pm_idle value will not be used by any CPU after the return of this function.
++ */
+ void cpu_idle_wait(void)
+ {
+-	unsigned int cpu, this_cpu = get_cpu();
+-	cpumask_t map, tmp = current->cpus_allowed;
+-
+-	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+-	put_cpu();
+-
+-	cpus_clear(map);
+-	for_each_online_cpu(cpu) {
+-		per_cpu(cpu_idle_state, cpu) = 1;
+-		cpu_set(cpu, map);
+-	}
+-
+-	__get_cpu_var(cpu_idle_state) = 0;
+-
+-	wmb();
+-	do {
+-		ssleep(1);
+-		for_each_online_cpu(cpu) {
+-			if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+-				cpu_clear(cpu, map);
+-		}
+-		cpus_and(map, map, cpu_online_map);
+-		/*
+-		 * We waited 1 sec, if a CPU still did not call idle
+-		 * it may be because it is in idle and not waking up
+-		 * because it has nothing to do.
+-		 * Give all the remaining CPUS a kick.
+-		 */
+-		smp_call_function_mask(map, do_nothing, 0, 0);
+-	} while (!cpus_empty(map));
+-
+-	set_cpus_allowed(current, tmp);
++	smp_mb();
++	/* kick all the CPUs so that they exit out of pm_idle */
++	smp_call_function(do_nothing, NULL, 0, 1);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+@@ -251,15 +239,15 @@ void __show_registers(struct pt_regs *re
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+ 	unsigned long d0, d1, d2, d3, d6, d7;
+-	unsigned long esp;
++	unsigned long sp;
+ 	unsigned short ss, gs;
+ 
+ 	if (user_mode_vm(regs)) {
+-		esp = regs->esp;
+-		ss = regs->xss & 0xffff;
++		sp = regs->sp;
++		ss = regs->ss & 0xffff;
+ 		savesegment(gs, gs);
+ 	} else {
+-		esp = (unsigned long) (&regs->esp);
++		sp = (unsigned long) (&regs->sp);
+ 		savesegment(ss, ss);
+ 		savesegment(gs, gs);
+ 	}
+@@ -272,17 +260,17 @@ void __show_registers(struct pt_regs *re
+ 			init_utsname()->version);
+ 
+ 	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+-			0xffff & regs->xcs, regs->eip, regs->eflags,
++			0xffff & regs->cs, regs->ip, regs->flags,
+ 			smp_processor_id());
+-	print_symbol("EIP is at %s\n", regs->eip);
++	print_symbol("EIP is at %s\n", regs->ip);
+ 
+ 	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+-		regs->eax, regs->ebx, regs->ecx, regs->edx);
++		regs->ax, regs->bx, regs->cx, regs->dx);
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+-		regs->esi, regs->edi, regs->ebp, esp);
++		regs->si, regs->di, regs->bp, sp);
+ 	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+-	       regs->xds & 0xffff, regs->xes & 0xffff,
+-	       regs->xfs & 0xffff, gs, ss);
++	       regs->ds & 0xffff, regs->es & 0xffff,
++	       regs->fs & 0xffff, gs, ss);
+ 
+ 	if (!all)
+ 		return;
+@@ -310,12 +298,12 @@ void __show_registers(struct pt_regs *re
+ void show_regs(struct pt_regs *regs)
+ {
+ 	__show_registers(regs, 1);
+-	show_trace(NULL, regs, &regs->esp);
++	show_trace(NULL, regs, &regs->sp, regs->bp);
+ }
+ 
+ /*
+- * This gets run with %ebx containing the
+- * function to call, and %edx containing
++ * This gets run with %bx containing the
++ * function to call, and %dx containing
+  * the "args".
+  */
+ extern void kernel_thread_helper(void);
+@@ -329,16 +317,16 @@ int kernel_thread(int (*fn)(void *), voi
+ 
+ 	memset(&regs, 0, sizeof(regs));
+ 
+-	regs.ebx = (unsigned long) fn;
+-	regs.edx = (unsigned long) arg;
++	regs.bx = (unsigned long) fn;
++	regs.dx = (unsigned long) arg;
+ 
+-	regs.xds = __USER_DS;
+-	regs.xes = __USER_DS;
+-	regs.xfs = __KERNEL_PERCPU;
+-	regs.orig_eax = -1;
+-	regs.eip = (unsigned long) kernel_thread_helper;
+-	regs.xcs = __KERNEL_CS | get_kernel_rpl();
+-	regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
++	regs.ds = __USER_DS;
++	regs.es = __USER_DS;
++	regs.fs = __KERNEL_PERCPU;
++	regs.orig_ax = -1;
++	regs.ip = (unsigned long) kernel_thread_helper;
++	regs.cs = __KERNEL_CS | get_kernel_rpl();
++	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
+ 
+ 	/* Ok, create the new process.. */
+ 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+@@ -368,7 +356,12 @@ void flush_thread(void)
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
++	tsk->thread.debugreg0 = 0;
++	tsk->thread.debugreg1 = 0;
++	tsk->thread.debugreg2 = 0;
++	tsk->thread.debugreg3 = 0;
++	tsk->thread.debugreg6 = 0;
++	tsk->thread.debugreg7 = 0;
+ 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
+ 	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+ 	/*
+@@ -393,7 +386,7 @@ void prepare_to_copy(struct task_struct 
+ 	unlazy_fpu(tsk);
+ }
+ 
+-int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
++int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 	unsigned long unused,
+ 	struct task_struct * p, struct pt_regs * regs)
+ {
+@@ -403,17 +396,19 @@ int copy_thread(int nr, unsigned long cl
+ 
+ 	childregs = task_pt_regs(p);
+ 	*childregs = *regs;
+-	childregs->eax = 0;
+-	childregs->esp = esp;
++	childregs->ax = 0;
++	childregs->sp = sp;
+ 
+-	p->thread.esp = (unsigned long) childregs;
+-	p->thread.esp0 = (unsigned long) (childregs+1);
++	p->thread.sp = (unsigned long) childregs;
++	p->thread.sp0 = (unsigned long) (childregs+1);
+ 
+-	p->thread.eip = (unsigned long) ret_from_fork;
++	p->thread.ip = (unsigned long) ret_from_fork;
+ 
+-	savesegment(gs,p->thread.gs);
++	savesegment(gs, p->thread.gs);
+ 
+ 	tsk = current;
++	if (test_tsk_thread_flag(tsk, TIF_CSTAR))
++		p->thread.ip = (unsigned long) cstar_ret_from_fork;
+ 	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+ 		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
+ 						IO_BITMAP_BYTES, GFP_KERNEL);
+@@ -424,34 +419,17 @@ int copy_thread(int nr, unsigned long cl
+ 		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+ 	}
+ 
++	err = 0;
++
+ 	/*
+ 	 * Set a new TLS for the child thread?
+ 	 */
+-	if (clone_flags & CLONE_SETTLS) {
+-		struct desc_struct *desc;
+-		struct user_desc info;
+-		int idx;
+-
+-		err = -EFAULT;
+-		if (copy_from_user(&info, (void __user *)childregs->esi, sizeof(info)))
+-			goto out;
+-		err = -EINVAL;
+-		if (LDT_empty(&info))
+-			goto out;
+-
+-		idx = info.entry_number;
+-		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+-			goto out;
+-
+-		desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+-		desc->a = LDT_entry_a(&info);
+-		desc->b = LDT_entry_b(&info);
+-	}
++	if (clone_flags & CLONE_SETTLS)
++		err = do_set_thread_area(p, -1,
++			(struct user_desc __user *)childregs->si, 0);
+ 
+ 	p->thread.iopl = current->thread.iopl;
+ 
+-	err = 0;
+- out:
+ 	if (err && p->thread.io_bitmap_ptr) {
+ 		kfree(p->thread.io_bitmap_ptr);
+ 		p->thread.io_bitmap_max = 0;
+@@ -459,67 +437,8 @@ int copy_thread(int nr, unsigned long cl
+ 	return err;
+ }
+ 
+-/*
+- * fill in the user structure for a core dump..
+- */
+-void dump_thread(struct pt_regs * regs, struct user * dump)
+-{
+-	int i;
+-
+-/* changed the size calculations - should hopefully work better. lbt */
+-	dump->magic = CMAGIC;
+-	dump->start_code = 0;
+-	dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
+-	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+-	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+-	dump->u_dsize -= dump->u_tsize;
+-	dump->u_ssize = 0;
+-	for (i = 0; i < 8; i++)
+-		dump->u_debugreg[i] = current->thread.debugreg[i];  
+-
+-	if (dump->start_stack < TASK_SIZE)
+-		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+-
+-	dump->regs.ebx = regs->ebx;
+-	dump->regs.ecx = regs->ecx;
+-	dump->regs.edx = regs->edx;
+-	dump->regs.esi = regs->esi;
+-	dump->regs.edi = regs->edi;
+-	dump->regs.ebp = regs->ebp;
+-	dump->regs.eax = regs->eax;
+-	dump->regs.ds = regs->xds;
+-	dump->regs.es = regs->xes;
+-	dump->regs.fs = regs->xfs;
+-	savesegment(gs,dump->regs.gs);
+-	dump->regs.orig_eax = regs->orig_eax;
+-	dump->regs.eip = regs->eip;
+-	dump->regs.cs = regs->xcs;
+-	dump->regs.eflags = regs->eflags;
+-	dump->regs.esp = regs->esp;
+-	dump->regs.ss = regs->xss;
+-
+-	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
+-}
+-EXPORT_SYMBOL(dump_thread);
+-
+-/* 
+- * Capture the user space registers if the task is not running (in user space)
+- */
+-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+-{
+-	struct pt_regs ptregs = *task_pt_regs(tsk);
+-	ptregs.xcs &= 0xffff;
+-	ptregs.xds &= 0xffff;
+-	ptregs.xes &= 0xffff;
+-	ptregs.xss &= 0xffff;
+-
+-	elf_core_copy_regs(regs, &ptregs);
+-
+-	return 1;
+-}
+-
+ #ifdef CONFIG_SECCOMP
+-void hard_disable_TSC(void)
++static void hard_disable_TSC(void)
+ {
+ 	write_cr4(read_cr4() | X86_CR4_TSD);
+ }
+@@ -534,7 +453,7 @@ void disable_TSC(void)
+ 		hard_disable_TSC();
+ 	preempt_enable();
+ }
+-void hard_enable_TSC(void)
++static void hard_enable_TSC(void)
+ {
+ 	write_cr4(read_cr4() & ~X86_CR4_TSD);
+ }
+@@ -543,18 +462,32 @@ void hard_enable_TSC(void)
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+-	struct thread_struct *next;
++	struct thread_struct *prev, *next;
++	unsigned long debugctl;
+ 
++	prev = &prev_p->thread;
+ 	next = &next_p->thread;
+ 
++	debugctl = prev->debugctlmsr;
++	if (next->ds_area_msr != prev->ds_area_msr) {
++		/* we clear debugctl to make sure DS
++		 * is not in use when we change it */
++		debugctl = 0;
++		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
++	}
++
++	if (next->debugctlmsr != debugctl)
++		wrmsr(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr, 0);
++
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+-		set_debugreg(next->debugreg[0], 0);
+-		set_debugreg(next->debugreg[1], 1);
+-		set_debugreg(next->debugreg[2], 2);
+-		set_debugreg(next->debugreg[3], 3);
++		set_debugreg(next->debugreg0, 0);
++		set_debugreg(next->debugreg1, 1);
++		set_debugreg(next->debugreg2, 2);
++		set_debugreg(next->debugreg3, 3);
+ 		/* no 4 and 5 */
+-		set_debugreg(next->debugreg[6], 6);
+-		set_debugreg(next->debugreg[7], 7);
++		set_debugreg(next->debugreg6, 6);
++		set_debugreg(next->debugreg7, 7);
+ 	}
+ 
+ #ifdef CONFIG_SECCOMP
+@@ -567,6 +500,14 @@ __switch_to_xtra(struct task_struct *pre
+ 			hard_enable_TSC();
+ 	}
+ #endif
++
++#ifdef X86_BTS
++	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
++		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
++
++	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
++		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
++#endif
+ }
+ 
+ /*
+@@ -592,11 +533,11 @@ __switch_to_xtra(struct task_struct *pre
+  * More important, however, is the fact that this allows us much
+  * more flexibility.
+  *
+- * The return value (in %eax) will be the "prev" task after
++ * The return value (in %ax) will be the "prev" task after
+  * the task-switch, and shows up in ret_from_fork in entry.S,
+  * for example.
+  */
+-struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
++struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev = &prev_p->thread,
+ 				 *next = &next_p->thread;
+@@ -632,12 +573,12 @@ struct task_struct fastcall * __switch_t
+ #endif
+ 
+ 	/*
+-	 * Reload esp0.
+-	 * This is load_esp0(tss, next) with a multicall.
++	 * Reload sp0.
++	 * This is load_sp0(tss, next) with a multicall.
+ 	 */
+ 	mcl->op      = __HYPERVISOR_stack_switch;
+ 	mcl->args[0] = __KERNEL_DS;
+-	mcl->args[1] = next->esp0;
++	mcl->args[1] = next->sp0;
+ 	mcl++;
+ 
+ 	/*
+@@ -734,7 +675,7 @@ struct task_struct fastcall * __switch_t
+ 
+ asmlinkage int sys_fork(struct pt_regs regs)
+ {
+-	return do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
++	return do_fork(SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
+ }
+ 
+ asmlinkage int sys_clone(struct pt_regs regs)
+@@ -743,12 +684,12 @@ asmlinkage int sys_clone(struct pt_regs 
+ 	unsigned long newsp;
+ 	int __user *parent_tidptr, *child_tidptr;
+ 
+-	clone_flags = regs.ebx;
+-	newsp = regs.ecx;
+-	parent_tidptr = (int __user *)regs.edx;
+-	child_tidptr = (int __user *)regs.edi;
++	clone_flags = regs.bx;
++	newsp = regs.cx;
++	parent_tidptr = (int __user *)regs.dx;
++	child_tidptr = (int __user *)regs.di;
+ 	if (!newsp)
+-		newsp = regs.esp;
++		newsp = regs.sp;
+ 	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
+ }
+ 
+@@ -764,7 +705,7 @@ asmlinkage int sys_clone(struct pt_regs 
+  */
+ asmlinkage int sys_vfork(struct pt_regs regs)
+ {
+-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
++	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs, 0, NULL, NULL);
+ }
+ 
+ /*
+@@ -775,18 +716,15 @@ asmlinkage int sys_execve(struct pt_regs
+ 	int error;
+ 	char * filename;
+ 
+-	filename = getname((char __user *) regs.ebx);
++	filename = getname((char __user *) regs.bx);
+ 	error = PTR_ERR(filename);
+ 	if (IS_ERR(filename))
+ 		goto out;
+ 	error = do_execve(filename,
+-			(char __user * __user *) regs.ecx,
+-			(char __user * __user *) regs.edx,
++			(char __user * __user *) regs.cx,
++			(char __user * __user *) regs.dx,
+ 			&regs);
+ 	if (error == 0) {
+-		task_lock(current);
+-		current->ptrace &= ~PT_DTRACE;
+-		task_unlock(current);
+ 		/* Make sure we don't return using sysenter.. */
+ 		set_thread_flag(TIF_IRET);
+ 	}
+@@ -800,145 +738,37 @@ out:
+ 
+ unsigned long get_wchan(struct task_struct *p)
+ {
+-	unsigned long ebp, esp, eip;
++	unsigned long bp, sp, ip;
+ 	unsigned long stack_page;
+ 	int count = 0;
+ 	if (!p || p == current || p->state == TASK_RUNNING)
+ 		return 0;
+ 	stack_page = (unsigned long)task_stack_page(p);
+-	esp = p->thread.esp;
+-	if (!stack_page || esp < stack_page || esp > top_esp+stack_page)
++	sp = p->thread.sp;
++	if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
+ 		return 0;
+-	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
+-	ebp = *(unsigned long *) esp;
++	/* include/asm-i386/system.h:switch_to() pushes bp last. */
++	bp = *(unsigned long *) sp;
+ 	do {
+-		if (ebp < stack_page || ebp > top_ebp+stack_page)
++		if (bp < stack_page || bp > top_ebp+stack_page)
+ 			return 0;
+-		eip = *(unsigned long *) (ebp+4);
+-		if (!in_sched_functions(eip))
+-			return eip;
+-		ebp = *(unsigned long *) ebp;
++		ip = *(unsigned long *) (bp+4);
++		if (!in_sched_functions(ip))
++			return ip;
++		bp = *(unsigned long *) bp;
+ 	} while (count++ < 16);
+ 	return 0;
+ }
+ 
+-/*
+- * sys_alloc_thread_area: get a yet unused TLS descriptor index.
+- */
+-static int get_free_idx(void)
+-{
+-	struct thread_struct *t = &current->thread;
+-	int idx;
+-
+-	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
+-		if (desc_empty(t->tls_array + idx))
+-			return idx + GDT_ENTRY_TLS_MIN;
+-	return -ESRCH;
+-}
+-
+-/*
+- * Set a given TLS descriptor:
+- */
+-asmlinkage int sys_set_thread_area(struct user_desc __user *u_info)
+-{
+-	struct thread_struct *t = &current->thread;
+-	struct user_desc info;
+-	struct desc_struct *desc;
+-	int cpu, idx;
+-
+-	if (copy_from_user(&info, u_info, sizeof(info)))
+-		return -EFAULT;
+-	idx = info.entry_number;
+-
+-	/*
+-	 * index -1 means the kernel should try to find and
+-	 * allocate an empty descriptor:
+-	 */
+-	if (idx == -1) {
+-		idx = get_free_idx();
+-		if (idx < 0)
+-			return idx;
+-		if (put_user(idx, &u_info->entry_number))
+-			return -EFAULT;
+-	}
+-
+-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+-		return -EINVAL;
+-
+-	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+-	/*
+-	 * We must not get preempted while modifying the TLS.
+-	 */
+-	cpu = get_cpu();
+-
+-	if (LDT_empty(&info)) {
+-		desc->a = 0;
+-		desc->b = 0;
+-	} else {
+-		desc->a = LDT_entry_a(&info);
+-		desc->b = LDT_entry_b(&info);
+-	}
+-	load_TLS(t, cpu);
+-
+-	put_cpu();
+-
+-	return 0;
+-}
+-
+-/*
+- * Get the current Thread-Local Storage area:
+- */
+-
+-#define GET_BASE(desc) ( \
+-	(((desc)->a >> 16) & 0x0000ffff) | \
+-	(((desc)->b << 16) & 0x00ff0000) | \
+-	( (desc)->b        & 0xff000000)   )
+-
+-#define GET_LIMIT(desc) ( \
+-	((desc)->a & 0x0ffff) | \
+-	 ((desc)->b & 0xf0000) )
+-	
+-#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)
+-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
+-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
+-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
+-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
+-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+-
+-asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
+-{
+-	struct user_desc info;
+-	struct desc_struct *desc;
+-	int idx;
+-
+-	if (get_user(idx, &u_info->entry_number))
+-		return -EFAULT;
+-	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
+-		return -EINVAL;
+-
+-	memset(&info, 0, sizeof(info));
+-
+-	desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+-
+-	info.entry_number = idx;
+-	info.base_addr = GET_BASE(desc);
+-	info.limit = GET_LIMIT(desc);
+-	info.seg_32bit = GET_32BIT(desc);
+-	info.contents = GET_CONTENTS(desc);
+-	info.read_exec_only = !GET_WRITABLE(desc);
+-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
+-	info.seg_not_present = !GET_PRESENT(desc);
+-	info.useable = GET_USEABLE(desc);
+-
+-	if (copy_to_user(u_info, &info, sizeof(info)))
+-		return -EFAULT;
+-	return 0;
+-}
+-
+ unsigned long arch_align_stack(unsigned long sp)
+ {
+ 	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ 		sp -= get_random_int() % 8192;
+ 	return sp & ~0xf;
+ }
++
++unsigned long arch_randomize_brk(struct mm_struct *mm)
++{
++	unsigned long range_end = mm->brk + 0x02000000;
++	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -3,7 +3,7 @@
+  *
+  *  Pentium III FXSR, SSE support
+  *	Gareth Hughes <gareth@valinux.com>, May 2000
+- * 
++ *
+  *  X86-64 port
+  *	Andi Kleen.
+  *
+@@ -22,19 +22,18 @@
+ #include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
++#include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+-#include <linux/fs.h>
+ #include <linux/elfcore.h>
+ #include <linux/smp.h>
+ #include <linux/slab.h>
+ #include <linux/user.h>
+-#include <linux/module.h>
+-#include <linux/a.out.h>
+ #include <linux/interrupt.h>
++#include <linux/utsname.h>
+ #include <linux/delay.h>
++#include <linux/module.h>
+ #include <linux/ptrace.h>
+-#include <linux/utsname.h>
+ #include <linux/random.h>
+ #include <linux/notifier.h>
+ #include <linux/kprobes.h>
+@@ -73,7 +72,6 @@ EXPORT_SYMBOL(boot_option_idle_override)
+  */
+ void (*pm_idle)(void);
+ EXPORT_SYMBOL(pm_idle);
+-static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
+ 
+ static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+ 
+@@ -81,13 +79,6 @@ void idle_notifier_register(struct notif
+ {
+ 	atomic_notifier_chain_register(&idle_notifier, n);
+ }
+-EXPORT_SYMBOL_GPL(idle_notifier_register);
+-
+-void idle_notifier_unregister(struct notifier_block *n)
+-{
+-	atomic_notifier_chain_unregister(&idle_notifier, n);
+-}
+-EXPORT_SYMBOL(idle_notifier_unregister);
+ 
+ void enter_idle(void)
+ {
+@@ -116,7 +107,7 @@ void exit_idle(void)
+  * to poll the ->need_resched flag instead of waiting for the
+  * cross-CPU IPI to arrive. Use this option with caution.
+  */
+-static void poll_idle (void)
++static void poll_idle(void)
+ {
+ 	local_irq_enable();
+ 	cpu_relax();
+@@ -131,10 +122,19 @@ static void xen_idle(void)
+ 	 */
+ 	smp_mb();
+ 	local_irq_disable();
+-	if (!need_resched())
+-		safe_halt();
+-	else
+-		local_irq_enable();
++	if (!need_resched()) {
++		ktime_t t0, t1;
++		u64 t0n, t1n;
++
++		t0 = ktime_get();
++		t0n = ktime_to_ns(t0);
++		safe_halt();	/* enables interrupts racelessly */
++		local_irq_disable();
++		t1 = ktime_get();
++		t1n = ktime_to_ns(t1);
++		sched_clock_idle_wakeup_event(t1n - t0n);
++	}
++	local_irq_enable();
+ 	current_thread_info()->status |= TS_POLLING;
+ }
+ 
+@@ -161,19 +161,15 @@ static inline void play_dead(void)
+  * low exit latency (ie sit in a loop waiting for
+  * somebody to say that they'd like to reschedule)
+  */
+-void cpu_idle (void)
++void cpu_idle(void)
+ {
+ 	current_thread_info()->status |= TS_POLLING;
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
++		tick_nohz_stop_sched_tick();
+ 		while (!need_resched()) {
+ 			void (*idle)(void);
+ 
+-			if (__get_cpu_var(cpu_idle_state))
+-				__get_cpu_var(cpu_idle_state) = 0;
+-
+-			tick_nohz_stop_sched_tick();
+-
+ 			rmb();
+ 			idle = xen_idle; /* no alternatives */
+ 			if (cpu_is_offline(smp_processor_id()))
+@@ -203,49 +199,27 @@ static void do_nothing(void *unused)
+ {
+ }
+ 
++/*
++ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
++ * pm_idle and update to new pm_idle value. Required while changing pm_idle
++ * handler on SMP systems.
++ *
++ * Caller must have changed pm_idle to the new value before the call. Old
++ * pm_idle value will not be used by any CPU after the return of this function.
++ */
+ void cpu_idle_wait(void)
+ {
+-	unsigned int cpu, this_cpu = get_cpu();
+-	cpumask_t map, tmp = current->cpus_allowed;
+-
+-	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+-	put_cpu();
+-
+- 	cpus_clear(map);
+-	for_each_online_cpu(cpu) {
+-		per_cpu(cpu_idle_state, cpu) = 1;
+-		cpu_set(cpu, map);
+-	}
+-
+-	__get_cpu_var(cpu_idle_state) = 0;
+-
+-	wmb();
+-	do {
+-		ssleep(1);
+-		for_each_online_cpu(cpu) {
+-			if (cpu_isset(cpu, map) &&
+-					!per_cpu(cpu_idle_state, cpu))
+-				cpu_clear(cpu, map);
+-		}
+-		cpus_and(map, map, cpu_online_map);
+-		/*
+-		 * We waited 1 sec, if a CPU still did not call idle
+-		 * it may be because it is in idle and not waking up
+-		 * because it has nothing to do.
+-		 * Give all the remaining CPUS a kick.
+-		 */
+-		smp_call_function_mask(map, do_nothing, 0, 0);
+-	} while (!cpus_empty(map));
+-
+-	set_cpus_allowed(current, tmp);
++	smp_mb();
++	/* kick all the CPUs so that they exit out of pm_idle */
++	smp_call_function(do_nothing, NULL, 0, 1);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+-void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) 
++void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+ {
+ }
+ 
+-static int __init idle_setup (char *str)
++static int __init idle_setup(char *str)
+ {
+ 	if (!strcmp(str, "poll")) {
+ 		printk("using polling idle threads.\n");
+@@ -260,13 +234,13 @@ static int __init idle_setup (char *str)
+ }
+ early_param("idle", idle_setup);
+ 
+-/* Prints also some state that isn't saved in the pt_regs */ 
++/* Prints also some state that isn't saved in the pt_regs */
+ void __show_regs(struct pt_regs * regs)
+ {
+ 	unsigned long fs, gs, shadowgs;
+ 	unsigned long d0, d1, d2, d3, d6, d7;
+-	unsigned int fsindex,gsindex;
+-	unsigned int ds,cs,es; 
++	unsigned int fsindex, gsindex;
++	unsigned int ds, cs, es;
+ 
+ 	printk("\n");
+ 	print_modules();
+@@ -275,16 +249,16 @@ void __show_regs(struct pt_regs * regs)
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
+-	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
+-	printk_address(regs->rip); 
+-	printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp,
+-		regs->eflags);
++	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
++	printk_address(regs->ip, 1);
++	printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->sp,
++		regs->flags);
+ 	printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
+-	       regs->rax, regs->rbx, regs->rcx);
++	       regs->ax, regs->bx, regs->cx);
+ 	printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
+-	       regs->rdx, regs->rsi, regs->rdi); 
++	       regs->dx, regs->si, regs->di);
+ 	printk("RBP: %016lx R08: %016lx R09: %016lx\n",
+-	       regs->rbp, regs->r8, regs->r9); 
++	       regs->bp, regs->r8, regs->r9);
+ 	printk("R10: %016lx R11: %016lx R12: %016lx\n",
+ 	       regs->r10, regs->r11, regs->r12); 
+ 	printk("R13: %016lx R14: %016lx R15: %016lx\n",
+@@ -318,7 +292,7 @@ void show_regs(struct pt_regs *regs)
+ {
+ 	printk("CPU %d:", smp_processor_id());
+ 	__show_regs(regs);
+-	show_trace(NULL, regs, (void *)(regs + 1));
++	show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
+ }
+ 
+ /*
+@@ -329,7 +303,7 @@ void exit_thread(void)
+ 	struct task_struct *me = current;
+ 	struct thread_struct *t = &me->thread;
+ 
+-	if (me->thread.io_bitmap_ptr) { 
++	if (me->thread.io_bitmap_ptr) {
+ #ifndef CONFIG_X86_NO_TSS
+ 		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
+ #endif
+@@ -382,7 +356,7 @@ void flush_thread(void)
+ 	tsk->thread.debugreg3 = 0;
+ 	tsk->thread.debugreg6 = 0;
+ 	tsk->thread.debugreg7 = 0;
+-	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
++	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+ 	/*
+ 	 * Forget coprocessor state..
+ 	 */
+@@ -405,26 +379,21 @@ void release_thread(struct task_struct *
+ 
+ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
+ {
+-	struct user_desc ud = { 
++	struct user_desc ud = {
+ 		.base_addr = addr,
+ 		.limit = 0xfffff,
+ 		.seg_32bit = 1,
+ 		.limit_in_pages = 1,
+ 		.useable = 1,
+ 	};
+-	struct n_desc_struct *desc = (void *)t->thread.tls_array;
++	struct desc_struct *desc = t->thread.tls_array;
+ 	desc += tls;
+-	desc->a = LDT_entry_a(&ud); 
+-	desc->b = LDT_entry_b(&ud); 
++	fill_ldt(desc, &ud);
+ }
+ 
+ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
+ {
+-	struct desc_struct *desc = (void *)t->thread.tls_array;
+-	desc += tls;
+-	return desc->base0 | 
+-		(((u32)desc->base1) << 16) | 
+-		(((u32)desc->base2) << 24);
++	return get_desc_base(&t->thread.tls_array[tls]);
+ }
+ 
+ /*
+@@ -436,7 +405,7 @@ void prepare_to_copy(struct task_struct 
+ 	unlazy_fpu(tsk);
+ }
+ 
+-int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, 
++int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 		unsigned long unused,
+ 	struct task_struct * p, struct pt_regs * regs)
+ {
+@@ -448,14 +417,14 @@ int copy_thread(int nr, unsigned long cl
+ 			(THREAD_SIZE + task_stack_page(p))) - 1;
+ 	*childregs = *regs;
+ 
+-	childregs->rax = 0;
+-	childregs->rsp = rsp;
+-	if (rsp == ~0UL)
+-		childregs->rsp = (unsigned long)childregs;
+-
+-	p->thread.rsp = (unsigned long) childregs;
+-	p->thread.rsp0 = (unsigned long) (childregs+1);
+-	p->thread.userrsp = me->thread.userrsp; 
++	childregs->ax = 0;
++	childregs->sp = sp;
++	if (sp == ~0UL)
++		childregs->sp = (unsigned long)childregs;
++
++	p->thread.sp = (unsigned long) childregs;
++	p->thread.sp0 = (unsigned long) (childregs+1);
++	p->thread.usersp = me->thread.usersp;
+ 
+ 	set_tsk_thread_flag(p, TIF_FORK);
+ 
+@@ -476,7 +445,7 @@ int copy_thread(int nr, unsigned long cl
+ 		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
+ 				IO_BITMAP_BYTES);
+ 		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+-	} 
++	}
+ 
+ 	/*
+ 	 * Set a new TLS for the child thread?
+@@ -484,7 +453,8 @@ int copy_thread(int nr, unsigned long cl
+ 	if (clone_flags & CLONE_SETTLS) {
+ #ifdef CONFIG_IA32_EMULATION
+ 		if (test_thread_flag(TIF_IA32))
+-			err = ia32_child_tls(p, childregs); 
++			err = do_set_thread_area(p, -1,
++				(struct user_desc __user *)childregs->si, 0);
+ 		else 			
+ #endif	 
+ 			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 
+@@ -502,26 +472,32 @@ out:
+ 	return err;
+ }
+ 
+-static inline void __save_init_fpu( struct task_struct *tsk )
+-{
+-	asm volatile( "rex64 ; fxsave %0 ; fnclex"
+-		      : "=m" (tsk->thread.i387.fxsave));
+-	tsk->thread_info->status &= ~TS_USEDFPU;
+-}
+-
+ /*
+  * This special macro can be used to load a debugging register
+  */
+-#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
++#define loaddebug(thread, r) set_debugreg(thread->debugreg ## r, r)
+ 
+ static inline void __switch_to_xtra(struct task_struct *prev_p,
+-			     	    struct task_struct *next_p)
++				    struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev, *next;
++	unsigned long debugctl;
+ 
+ 	prev = &prev_p->thread,
+ 	next = &next_p->thread;
+ 
++	debugctl = prev->debugctlmsr;
++	if (next->ds_area_msr != prev->ds_area_msr) {
++		/* we clear debugctl to make sure DS
++		 * is not in use when we change it */
++		debugctl = 0;
++		wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
++		wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
++	}
++
++	if (next->debugctlmsr != debugctl)
++		wrmsrl(MSR_IA32_DEBUGCTLMSR, next->debugctlmsr);
++
+ 	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+ 		loaddebug(next, 0);
+ 		loaddebug(next, 1);
+@@ -531,12 +507,20 @@ static inline void __switch_to_xtra(stru
+ 		loaddebug(next, 6);
+ 		loaddebug(next, 7);
+ 	}
++
++#ifdef X86_BTS
++	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
++		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
++
++	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
++		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
++#endif
+ }
+ 
+ /*
+  *	switch_to(x,y) should switch tasks from x to y.
+  *
+- * This could still be optimized: 
++ * This could still be optimized:
+  * - fold all the options into a flag word and test it with a single test.
+  * - could test fs/gs bitsliced
+  *
+@@ -547,7 +531,7 @@ __switch_to(struct task_struct *prev_p, 
+ {
+ 	struct thread_struct *prev = &prev_p->thread,
+ 				 *next = &next_p->thread;
+-	int cpu = smp_processor_id();  
++	int cpu = smp_processor_id();
+ #ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ #endif
+@@ -581,11 +565,12 @@ __switch_to(struct task_struct *prev_p, 
+ 		prev_p->fpu_counter = 0;
+ 
+ 	/*
+-	 * Reload esp0, LDT and the page table pointer:
++	 * Reload sp0.
++	 * This is load_sp0(tss, next) with a multicall.
+ 	 */
+ 	mcl->op      = __HYPERVISOR_stack_switch;
+ 	mcl->args[0] = __KERNEL_DS;
+-	mcl->args[1] = next->rsp0;
++	mcl->args[1] = next->sp0;
+ 	mcl++;
+ 
+ 	/*
+@@ -593,11 +578,12 @@ __switch_to(struct task_struct *prev_p, 
+ 	 * This is load_TLS(next, cpu) with multicalls.
+ 	 */
+ #define C(i) do {							\
+-	if (unlikely(next->tls_array[i] != prev->tls_array[i])) {	\
++	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
++		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
+ 		mcl->op      = __HYPERVISOR_update_descriptor;		\
+ 		mcl->args[0] = virt_to_machine(				\
+-			&cpu_gdt(cpu)[GDT_ENTRY_TLS_MIN + i]);		\
+-		mcl->args[1] = next->tls_array[i];			\
++			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
++		mcl->args[1] = *(u64 *)&next->tls_array[i];		\
+ 		mcl++;							\
+ 	}								\
+ } while (0)
+@@ -605,7 +591,7 @@ __switch_to(struct task_struct *prev_p, 
+ #undef C
+ 
+ 	if (unlikely(prev->iopl != next->iopl)) {
+-		iopl_op.iopl = (next->iopl == 0) ? 1 : 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;
+@@ -669,8 +655,8 @@ __switch_to(struct task_struct *prev_p, 
+ 	/* 
+ 	 * Switch the PDA context.
+ 	 */
+-	prev->userrsp = read_pda(oldrsp); 
+-	write_pda(oldrsp, next->userrsp); 
++	prev->usersp = read_pda(oldrsp);
++	write_pda(oldrsp, next->usersp);
+ 	write_pda(pcurrent, next_p); 
+ 	write_pda(kernelstack,
+ 	(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
+@@ -687,7 +673,8 @@ __switch_to(struct task_struct *prev_p, 
+ 	/*
+ 	 * Now maybe reload the debug registers
+ 	 */
+-	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
++	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
++		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
+ 		__switch_to_xtra(prev_p, next_p);
+ 
+ 	/* If the task has used fpu the last 5 timeslices, just do a full
+@@ -702,23 +689,18 @@ __switch_to(struct task_struct *prev_p, 
+ /*
+  * sys_execve() executes a new program.
+  */
+-asmlinkage 
++asmlinkage
+ long sys_execve(char __user *name, char __user * __user *argv,
+-		char __user * __user *envp, struct pt_regs regs)
++		char __user * __user *envp, struct pt_regs *regs)
+ {
+ 	long error;
+ 	char * filename;
+ 
+ 	filename = getname(name);
+ 	error = PTR_ERR(filename);
+-	if (IS_ERR(filename)) 
++	if (IS_ERR(filename))
+ 		return error;
+-	error = do_execve(filename, argv, envp, &regs); 
+-	if (error == 0) {
+-		task_lock(current);
+-		current->ptrace &= ~PT_DTRACE;
+-		task_unlock(current);
+-	}
++	error = do_execve(filename, argv, envp, regs);
+ 	putname(filename);
+ 	return error;
+ }
+@@ -728,18 +710,18 @@ void set_personality_64bit(void)
+ 	/* inherit personality from parent */
+ 
+ 	/* Make sure to be in 64bit mode */
+-	clear_thread_flag(TIF_IA32); 
++	clear_thread_flag(TIF_IA32);
+ 
+ 	/* TBD: overwrites user setup. Should have two bits.
+ 	   But 64bit processes have always behaved this way,
+ 	   so it's not too bad. The main problem is just that
+-   	   32bit childs are affected again. */
++	   32bit childs are affected again. */
+ 	current->personality &= ~READ_IMPLIES_EXEC;
+ }
+ 
+ asmlinkage long sys_fork(struct pt_regs *regs)
+ {
+-	return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
++	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+ }
+ 
+ asmlinkage long
+@@ -747,7 +729,7 @@ sys_clone(unsigned long clone_flags, uns
+ 	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
+ {
+ 	if (!newsp)
+-		newsp = regs->rsp;
++		newsp = regs->sp;
+ 	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+ }
+ 
+@@ -763,29 +745,29 @@ sys_clone(unsigned long clone_flags, uns
+  */
+ asmlinkage long sys_vfork(struct pt_regs *regs)
+ {
+-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
++	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
+ 		    NULL, NULL);
+ }
+ 
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ 	unsigned long stack;
+-	u64 fp,rip;
++	u64 fp,ip;
+ 	int count = 0;
+ 
+ 	if (!p || p == current || p->state==TASK_RUNNING)
+ 		return 0; 
+ 	stack = (unsigned long)task_stack_page(p);
+-	if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE)
++	if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE)
+ 		return 0;
+-	fp = *(u64 *)(p->thread.rsp);
++	fp = *(u64 *)(p->thread.sp);
+ 	do { 
+ 		if (fp < (unsigned long)stack ||
+ 		    fp > (unsigned long)stack+THREAD_SIZE)
+ 			return 0; 
+-		rip = *(u64 *)(fp+8); 
+-		if (!in_sched_functions(rip))
+-			return rip; 
++		ip = *(u64 *)(fp+8);
++		if (!in_sched_functions(ip))
++			return ip;
+ 		fp = *(u64 *)fp; 
+ 	} while (count++ < 16); 
+ 	return 0;
+@@ -827,19 +809,19 @@ long do_arch_prctl(struct task_struct *t
+ 		/* Not strictly needed for fs, but do it for symmetry
+ 		   with gs */
+ 		if (addr >= TASK_SIZE_OF(task))
+-			return -EPERM; 
++			return -EPERM;
+ 		cpu = get_cpu();
+-		/* handle small bases via the GDT because that's faster to 
++		/* handle small bases via the GDT because that's faster to
+ 		   switch. */
+-		if (addr <= 0xffffffff) { 
++		if (addr <= 0xffffffff) {
+ 			set_32bit_tls(task, FS_TLS, addr);
+-			if (doit) { 
+-				load_TLS(&task->thread, cpu); 
++			if (doit) {
++				load_TLS(&task->thread, cpu);
+ 				asm volatile("movl %0,%%fs" :: "r"(FS_TLS_SEL));
+ 			}
+ 			task->thread.fsindex = FS_TLS_SEL;
+ 			task->thread.fs = 0;
+-		} else { 
++		} else {
+ 			task->thread.fsindex = 0;
+ 			task->thread.fs = addr;
+ 			if (doit) {
+@@ -852,24 +834,24 @@ long do_arch_prctl(struct task_struct *t
+ 		}
+ 		put_cpu();
+ 		break;
+-	case ARCH_GET_FS: { 
+-		unsigned long base; 
++	case ARCH_GET_FS: {
++		unsigned long base;
+ 		if (task->thread.fsindex == FS_TLS_SEL)
+ 			base = read_32bit_tls(task, FS_TLS);
+ 		else if (doit)
+ 			rdmsrl(MSR_FS_BASE, base);
+ 		else
+ 			base = task->thread.fs;
+-		ret = put_user(base, (unsigned long __user *)addr); 
+-		break; 
++		ret = put_user(base, (unsigned long __user *)addr);
++		break;
+ 	}
+-	case ARCH_GET_GS: { 
++	case ARCH_GET_GS: {
+ 		unsigned long base;
+ 		unsigned gsindex;
+ 		if (task->thread.gsindex == GS_TLS_SEL)
+ 			base = read_32bit_tls(task, GS_TLS);
+ 		else if (doit) {
+- 			asm("movl %%gs,%0" : "=r" (gsindex));
++			asm("movl %%gs,%0" : "=r" (gsindex));
+ 			if (gsindex)
+ 				rdmsrl(MSR_KERNEL_GS_BASE, base);
+ 			else
+@@ -877,40 +859,21 @@ long do_arch_prctl(struct task_struct *t
+ 		}
+ 		else
+ 			base = task->thread.gs;
+-		ret = put_user(base, (unsigned long __user *)addr); 
++		ret = put_user(base, (unsigned long __user *)addr);
+ 		break;
+ 	}
+ 
+ 	default:
+ 		ret = -EINVAL;
+ 		break;
+-	} 
++	}
+ 
+-	return ret;	
+-} 
++	return ret;
++}
+ 
+ long sys_arch_prctl(int code, unsigned long addr)
+ {
+ 	return do_arch_prctl(current, code, addr);
+-} 
+-
+-/* 
+- * Capture the user space registers if the task is not running (in user space)
+- */
+-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
+-{
+-	struct pt_regs *pp, ptregs;
+-
+-	pp = task_pt_regs(tsk);
+-
+-	ptregs = *pp; 
+-	ptregs.cs &= 0xffff;
+-	ptregs.ss &= 0xffff;
+-
+-	elf_core_copy_regs(regs, &ptregs);
+- 
+-        boot_option_idle_override = 1;
+-	return 1;
+ }
+ 
+ unsigned long arch_align_stack(unsigned long sp)
+@@ -919,3 +882,9 @@ unsigned long arch_align_stack(unsigned 
+ 		sp -= get_random_int() % 8192;
+ 	return sp & ~0xf;
+ }
++
++unsigned long arch_randomize_brk(struct mm_struct *mm)
++{
++	unsigned long range_end = mm->brk + 0x02000000;
++	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -9,7 +9,7 @@
+ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+ {
+ 	u8 config, rev;
+-	u32 word;
++	u16 word;
+ 
+ 	/* BIOS may enable hardware IRQ balancing for
+ 	 * E7520/E7320/E7525(revision ID 0x9 and below)
+@@ -24,14 +24,17 @@ static void __devinit quirk_intel_irqbal
+ 	pci_read_config_byte(dev, 0xf4, &config);
+ 	pci_write_config_byte(dev, 0xf4, config|0x2);
+ 
+-	/* read xTPR register */
+-	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
++	/*
++	 * read xTPR register.  We may not have a pci_dev for device 8
++	 * because it might be hidden until the above write.
++	 */
++	pci_bus_read_config_word(dev->bus, PCI_DEVFN(8, 0), 0x4c, &word);
+ 
+ 	if (!(word & (1 << 13))) {
+ 		struct xen_platform_op op;
+ 
+-		printk(KERN_INFO "Intel E7520/7320/7525 detected. "
+-			"Disabling irq balancing and affinity\n");
++		dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
++			"disabling irq balancing and affinity\n");
+ 		op.cmd = XENPF_platform_quirk;
+ 		op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
+ 		WARN_ON(HYPERVISOR_platform_op(&op));
+@@ -102,14 +105,16 @@ static void ich_force_enable_hpet(struct
+ 	pci_read_config_dword(dev, 0xF0, &rcba);
+ 	rcba &= 0xFFFFC000;
+ 	if (rcba == 0) {
+-		printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
++		dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
++			"cannot force enable HPET\n");
+ 		return;
+ 	}
+ 
+ 	/* use bits 31:14, 16 kB aligned */
+ 	rcba_base = ioremap_nocache(rcba, 0x4000);
+ 	if (rcba_base == NULL) {
+-		printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
++		dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
++			"cannot force enable HPET\n");
+ 		return;
+ 	}
+ 
+@@ -120,8 +125,8 @@ static void ich_force_enable_hpet(struct
+ 		/* HPET is enabled in HPTC. Just not reported by BIOS */
+ 		val = val & 0x3;
+ 		force_hpet_address = 0xFED00000 | (val << 12);
+-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
++			"0x%lx\n", force_hpet_address);
+ 		iounmap(rcba_base);
+ 		return;
+ 	}
+@@ -140,11 +145,12 @@ static void ich_force_enable_hpet(struct
+ 	if (err) {
+ 		force_hpet_address = 0;
+ 		iounmap(rcba_base);
+-		printk(KERN_DEBUG "Failed to force enable HPET\n");
++		dev_printk(KERN_DEBUG, &dev->dev,
++			"Failed to force enable HPET\n");
+ 	} else {
+ 		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
+-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
++			"0x%lx\n", force_hpet_address);
+ 	}
+ }
+ 
+@@ -160,6 +166,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
+ 			 ich_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
+ 			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
++			 ich_force_enable_hpet);
+ 
+ 
+ static struct pci_dev *cached_dev;
+@@ -204,8 +212,8 @@ static void old_ich_force_enable_hpet(st
+ 	if (val & 0x4) {
+ 		val &= 0x3;
+ 		force_hpet_address = 0xFED00000 | (val << 12);
+-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
++			force_hpet_address);
+ 		return;
+ 	}
+ 
+@@ -225,14 +233,14 @@ static void old_ich_force_enable_hpet(st
+ 		/* HPET is enabled in HPTC. Just not reported by BIOS */
+ 		val &= 0x3;
+ 		force_hpet_address = 0xFED00000 | (val << 12);
+-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
++			"0x%lx\n", force_hpet_address);
+ 		cached_dev = dev;
+ 		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
+ 		return;
+ 	}
+ 
+-	printk(KERN_DEBUG "Failed to force enable HPET\n");
++	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
+ }
+ 
+ /*
+@@ -290,8 +298,8 @@ static void vt8237_force_enable_hpet(str
+ 	 */
+ 	if (val & 0x80) {
+ 		force_hpet_address = (val & ~0x3ff);
+-		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
++			force_hpet_address);
+ 		return;
+ 	}
+ 
+@@ -305,14 +313,14 @@ static void vt8237_force_enable_hpet(str
+ 	pci_read_config_dword(dev, 0x68, &val);
+ 	if (val & 0x80) {
+ 		force_hpet_address = (val & ~0x3ff);
+-		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+-			       force_hpet_address);
++		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
++			"0x%lx\n", force_hpet_address);
+ 		cached_dev = dev;
+ 		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
+ 		return;
+ 	}
+ 
+-	printk(KERN_DEBUG "Failed to force enable HPET\n");
++	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
+ }
+ 
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
+@@ -340,7 +348,7 @@ static void nvidia_force_enable_hpet(str
+ 	pci_read_config_dword(dev, 0x44, &val);
+ 	force_hpet_address = val & 0xfffffffe;
+ 	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
+-	printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
+ 		force_hpet_address);
+ 	cached_dev = dev;
+ 	return;
+@@ -353,6 +361,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_N
+ 			nvidia_force_enable_hpet);
+ 
+ /* LPC bridges */
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0260,
++			nvidia_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0360,
+ 			nvidia_force_enable_hpet);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0361,
+@@ -373,19 +383,19 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_N
+ void force_hpet_resume(void)
+ {
+ 	switch (force_hpet_resume_type) {
+-	    case ICH_FORCE_HPET_RESUME:
+-		return ich_force_hpet_resume();
+-
+-	    case OLD_ICH_FORCE_HPET_RESUME:
+-		return old_ich_force_hpet_resume();
+-
+-	    case VT8237_FORCE_HPET_RESUME:
+-		return vt8237_force_hpet_resume();
+-
+-	    case NVIDIA_FORCE_HPET_RESUME:
+-		return nvidia_force_hpet_resume();
+-
+-	    default:
++	case ICH_FORCE_HPET_RESUME:
++		ich_force_hpet_resume();
++		return;
++	case OLD_ICH_FORCE_HPET_RESUME:
++		old_ich_force_hpet_resume();
++		return;
++	case VT8237_FORCE_HPET_RESUME:
++		vt8237_force_hpet_resume();
++		return;
++	case NVIDIA_FORCE_HPET_RESUME:
++		nvidia_force_hpet_resume();
++		return;
++	default:
+ 		break;
+ 	}
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/rtc.c	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/rtc.c	2009-11-06 10:51:25.000000000 +0100
+@@ -171,6 +171,11 @@ int update_persistent_clock(struct times
+ 	unsigned long flags;
+ 	int retval;
+ 
++#ifdef CONFIG_XEN
++	if (xen_update_persistent_clock() < 0 || xen_independent_wallclock())
++		return 0;
++#endif
++
+ 	spin_lock_irqsave(&rtc_lock, flags);
+ 	retval = x86_platform.set_wallclock(now.tv_sec);
+ 	spin_unlock_irqrestore(&rtc_lock, flags);
+@@ -183,6 +188,10 @@ void read_persistent_clock(struct timesp
+ {
+ 	unsigned long retval, flags;
+ 
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return xen_read_persistent_clock();
++#endif
+ 	spin_lock_irqsave(&rtc_lock, flags);
+ 	retval = x86_platform.get_wallclock();
+ 	spin_unlock_irqrestore(&rtc_lock, flags);
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -31,7 +31,11 @@
+ #include <asm/hypervisor.h>
+ #endif
+ 
++#ifndef CONFIG_DEBUG_BOOT_PARAMS
+ struct boot_params __initdata boot_params;
++#else
++struct boot_params boot_params;
++#endif
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+@@ -47,6 +51,7 @@ char boot_cpu_stack[IRQSTACKSIZE] __attr
+ 
+ unsigned long __supported_pte_mask __read_mostly = ~0UL;
+ EXPORT_SYMBOL(__supported_pte_mask);
++
+ static int do_not_nx __cpuinitdata = 0;
+ 
+ /* noexec=on|off
+@@ -90,6 +95,45 @@ static int __init nonx32_setup(char *str
+ __setup("noexec32=", nonx32_setup);
+ 
+ /*
++ * Copy data used in early init routines from the initial arrays to the
++ * per cpu data areas.  These arrays then become expendable and the
++ * *_early_ptr's are zeroed indicating that the static arrays are gone.
++ */
++static void __init setup_per_cpu_maps(void)
++{
++#ifndef CONFIG_XEN
++	int cpu;
++
++	for_each_possible_cpu(cpu) {
++#ifdef CONFIG_SMP
++		if (per_cpu_offset(cpu)) {
++#endif
++			per_cpu(x86_cpu_to_apicid, cpu) =
++						x86_cpu_to_apicid_init[cpu];
++			per_cpu(x86_bios_cpu_apicid, cpu) =
++						x86_bios_cpu_apicid_init[cpu];
++#ifdef CONFIG_NUMA
++			per_cpu(x86_cpu_to_node_map, cpu) =
++						x86_cpu_to_node_map_init[cpu];
++#endif
++#ifdef CONFIG_SMP
++		}
++		else
++			printk(KERN_NOTICE "per_cpu_offset zero for cpu %d\n",
++									cpu);
++#endif
++	}
++
++	/* indicate the early static arrays will soon be gone */
++	x86_cpu_to_apicid_early_ptr = NULL;
++	x86_bios_cpu_apicid_early_ptr = NULL;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = NULL;
++#endif
++#endif
++}
++
++/*
+  * Great future plan:
+  * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
+  * Always point %gs to its beginning
+@@ -109,19 +153,24 @@ void __init setup_per_cpu_areas(void)
+ 	printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
+ 	for_each_cpu_mask (i, cpu_possible_map) {
+ 		char *ptr;
++#ifndef CONFIG_NEED_MULTIPLE_NODES
++		ptr = alloc_bootmem_pages(size);
++#else
++		int node = early_cpu_to_node(i);
+ 
+-		if (!NODE_DATA(cpu_to_node(i))) {
+-			printk("cpu with no node %d, num_online_nodes %d\n",
+-			       i, num_online_nodes());
++		if (!node_online(node) || !NODE_DATA(node))
+ 			ptr = alloc_bootmem_pages(size);
+-		} else { 
+-			ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
+-		}
++		else
++			ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
++#endif
+ 		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);
+ 	}
++
++	/* setup percpu data maps early */
++	setup_per_cpu_maps();
+ } 
+ 
+ #ifdef CONFIG_XEN
+@@ -224,7 +273,8 @@ void syscall_init(void)
+ 	wrmsrl(MSR_CSTAR, ignore_sysret);
+ 
+ 	/* Flags to clear on syscall */
+-	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
++	wrmsrl(MSR_SYSCALL_MASK,
++	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
+ #endif
+ #ifdef CONFIG_IA32_EMULATION   		
+ 	syscall32_cpu_init ();
+@@ -303,7 +353,7 @@ void __cpuinit cpu_init (void)
+ 	 */
+ #ifndef CONFIG_XEN 
+ 	if (cpu)
+- 		memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
++		memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);
+ #endif
+ 
+ 	cpu_gdt_descr[cpu].size = GDT_SIZE;
+@@ -334,10 +384,10 @@ void __cpuinit cpu_init (void)
+ 				      v, cpu); 
+ 		}
+ 		estacks += PAGE_SIZE << order[v];
+-		orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
++		orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks;
+ 	}
+ 
+-	t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
++	t->x86_tss.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.
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -47,9 +47,12 @@
+ #include <linux/crash_dump.h>
+ #include <linux/dmi.h>
+ #include <linux/pfn.h>
++#include <linux/pci.h>
++#include <linux/init_ohci1394_dma.h>
+ 
+ #include <video/edid.h>
+ 
++#include <asm/mtrr.h>
+ #include <asm/apic.h>
+ #include <asm/e820.h>
+ #include <asm/mpspec.h>
+@@ -79,14 +82,83 @@ static struct notifier_block xen_panic_b
+ 	xen_panic_event, NULL, 0 /* try to go last */
+ };
+ 
+-int disable_pse __cpuinitdata = 0;
+-
+ /*
+  * Machine setup..
+  */
+-extern struct resource code_resource;
+-extern struct resource data_resource;
+-extern struct resource bss_resource;
++static struct resource data_resource = {
++	.name	= "Kernel data",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource code_resource = {
++	.name	= "Kernel code",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource bss_resource = {
++	.name	= "Kernel bss",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource video_ram_resource = {
++	.name	= "Video RAM area",
++	.start	= 0xa0000,
++	.end	= 0xbffff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++static struct resource standard_io_resources[] = { {
++	.name	= "dma1",
++	.start	= 0x0000,
++	.end	= 0x001f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic1",
++	.start	= 0x0020,
++	.end	= 0x0021,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer0",
++	.start	= 0x0040,
++	.end    = 0x0043,
++	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name   = "timer1",
++	.start  = 0x0050,
++	.end    = 0x0053,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "keyboard",
++	.start	= 0x0060,
++	.end	= 0x006f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma page reg",
++	.start	= 0x0080,
++	.end	= 0x008f,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "pic2",
++	.start	= 0x00a0,
++	.end	= 0x00a1,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "dma2",
++	.start	= 0x00c0,
++	.end	= 0x00df,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++}, {
++	.name	= "fpu",
++	.start	= 0x00f0,
++	.end	= 0x00ff,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
++} };
+ 
+ /* cpu data as detected by the assembly code in head.S */
+ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+@@ -94,13 +166,16 @@ struct cpuinfo_x86 new_cpu_data __cpuini
+ struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ EXPORT_SYMBOL(boot_cpu_data);
+ 
++#ifndef CONFIG_X86_PAE
+ unsigned long mmu_cr4_features;
++#else
++unsigned long mmu_cr4_features = X86_CR4_PAE;
++#endif
+ 
+ /* for MCA, but anyone else can use it if they want */
+ unsigned int machine_id;
+ unsigned int machine_submodel_id;
+ unsigned int BIOS_revision;
+-unsigned int mca_pentium_flag;
+ 
+ /* Boot loader ID as an integer, for the benefit of proc_dointvec */
+ int bootloader_type;
+@@ -131,13 +206,17 @@ extern int root_mountflags;
+ 
+ unsigned long saved_videomode;
+ 
+-#define RAMDISK_IMAGE_START_MASK  	0x07FF
++#define RAMDISK_IMAGE_START_MASK	0x07FF
+ #define RAMDISK_PROMPT_FLAG		0x8000
+-#define RAMDISK_LOAD_FLAG		0x4000	
++#define RAMDISK_LOAD_FLAG		0x4000
+ 
+ static char __initdata command_line[COMMAND_LINE_SIZE];
+ 
++#ifndef CONFIG_DEBUG_BOOT_PARAMS
+ struct boot_params __initdata boot_params;
++#else
++struct boot_params boot_params;
++#endif
+ 
+ /*
+  * Point at the empty zero page to start with. We map the real shared_info
+@@ -198,8 +277,7 @@ static int __init parse_mem(char *arg)
+ 		return -EINVAL;
+ 
+ 	if (strcmp(arg, "nopentium") == 0) {
+-		clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+-		disable_pse = 1;
++		setup_clear_cpu_cap(X86_FEATURE_PSE);
+ 	} else {
+ 		/* If the user specifies memory size, we
+ 		 * limit the BIOS-provided memory map to
+@@ -208,7 +286,7 @@ static int __init parse_mem(char *arg)
+ 		 * trim the existing memory map.
+ 		 */
+ 		unsigned long long mem_size;
+- 
++
+ 		mem_size = memparse(arg, &arg);
+ 		limit_regions(mem_size);
+ 		user_defined_memmap = 1;
+@@ -350,7 +428,7 @@ static void __init reserve_ebda_region(v
+ 	unsigned int addr;
+ 	addr = get_bios_ebda();
+ 	if (addr)
+-		reserve_bootmem(addr, PAGE_SIZE);	
++		reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT);
+ }
+ #endif
+ 
+@@ -365,8 +443,6 @@ static unsigned long __init setup_memory
+  	min_low_pfn = PFN_UP(__pa(xen_start_info->pt_base)) +
+ 		xen_start_info->nr_pt_frames;
+ 
+-	find_max_pfn();
+-
+ 	max_low_pfn = find_max_low_pfn();
+ 
+ #ifdef CONFIG_HIGHMEM
+@@ -449,7 +525,8 @@ static void __init reserve_crashkernel(v
+ 					(unsigned long)(total_mem >> 20));
+ 			crashk_res.start = crash_base;
+ 			crashk_res.end   = crash_base + crash_size - 1;
+-			reserve_bootmem(crash_base, crash_size);
++			reserve_bootmem(crash_base, crash_size,
++					BOOTMEM_DEFAULT);
+ 		} else
+ 			printk(KERN_INFO "crashkernel reservation failed - "
+ 					"you have to specify a base address\n");
+@@ -463,6 +540,99 @@ static inline void __init reserve_crashk
+ {}
+ #endif
+ 
++#ifdef CONFIG_BLK_DEV_INITRD
++
++static bool do_relocate_initrd = false;
++
++static void __init reserve_initrd(void)
++{
++	unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
++	unsigned long ramdisk_size  = xen_start_info->mod_len;
++	unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
++	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	unsigned long ramdisk_here;
++
++	initrd_start = 0;
++
++	if (!xen_start_info->mod_start || !ramdisk_size)
++		return;		/* No initrd provided by bootloader */
++
++	if (ramdisk_end < ramdisk_image) {
++		printk(KERN_ERR "initrd wraps around end of memory, "
++		       "disabling initrd\n");
++		return;
++	}
++	if (ramdisk_size >= end_of_lowmem/2) {
++		printk(KERN_ERR "initrd too large to handle, "
++		       "disabling initrd\n");
++		return;
++	}
++	if (ramdisk_end <= end_of_lowmem) {
++		/* All in lowmem, easy case */
++		reserve_bootmem(ramdisk_image, ramdisk_size, BOOTMEM_DEFAULT);
++		initrd_start = ramdisk_image + PAGE_OFFSET;
++		initrd_end = initrd_start+ramdisk_size;
++		return;
++	}
++
++	/* We need to move the initrd down into lowmem */
++	ramdisk_here = (end_of_lowmem - ramdisk_size) & PAGE_MASK;
++
++	/* Note: this includes all the lowmem currently occupied by
++	   the initrd, we rely on that fact to keep the data intact. */
++	reserve_bootmem(ramdisk_here, ramdisk_size, BOOTMEM_DEFAULT);
++	initrd_start = ramdisk_here + PAGE_OFFSET;
++	initrd_end   = initrd_start + ramdisk_size;
++
++	do_relocate_initrd = true;
++}
++
++#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
++
++static void __init relocate_initrd(void)
++{
++	unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
++	unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
++	unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++	unsigned long ramdisk_here;
++	unsigned long slop, clen, mapaddr;
++	char *p, *q;
++
++	if (!do_relocate_initrd)
++		return;
++
++	ramdisk_here = initrd_start - PAGE_OFFSET;
++
++	q = (char *)initrd_start;
++
++	/* Copy any lowmem portion of the initrd */
++	if (ramdisk_image < end_of_lowmem) {
++		clen = end_of_lowmem - ramdisk_image;
++		p = (char *)__va(ramdisk_image);
++		memcpy(q, p, clen);
++		q += clen;
++		ramdisk_image += clen;
++		ramdisk_size  -= clen;
++	}
++
++	/* Copy the highmem portion of the initrd */
++	while (ramdisk_size) {
++		slop = ramdisk_image & ~PAGE_MASK;
++		clen = ramdisk_size;
++		if (clen > MAX_MAP_CHUNK-slop)
++			clen = MAX_MAP_CHUNK-slop;
++		mapaddr = ramdisk_image & PAGE_MASK;
++		p = early_ioremap(mapaddr, clen+slop);
++		memcpy(q, p+slop, clen);
++		early_iounmap(p, clen+slop);
++		q += clen;
++		ramdisk_image += clen;
++		ramdisk_size  -= clen;
++	}
++}
++
++#endif /* CONFIG_BLK_DEV_INITRD */
++
+ void __init setup_bootmem_allocator(void)
+ {
+ 	unsigned long bootmap_size;
+@@ -480,14 +650,15 @@ void __init setup_bootmem_allocator(void
+ 	 * bootmem allocator with an invalid RAM area.
+ 	 */
+ 	reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) +
+-			 bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text));
++			 bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text),
++			 BOOTMEM_DEFAULT);
+ 
+ #ifndef CONFIG_XEN
+ 	/*
+ 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+ 	 * enabling clean reboots, SMP operation, laptop functions.
+ 	 */
+-	reserve_bootmem(0, PAGE_SIZE);
++	reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+ 
+ 	/* reserve EBDA region, it's a 4K region */
+ 	reserve_ebda_region();
+@@ -497,7 +668,7 @@ void __init setup_bootmem_allocator(void
+        unless you have no PS/2 mouse plugged in. */
+ 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ 	    boot_cpu_data.x86 == 6)
+-	     reserve_bootmem(0xa0000 - 4096, 4096);
++	     reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
+ 
+ #ifdef CONFIG_SMP
+ 	/*
+@@ -505,7 +676,7 @@ void __init setup_bootmem_allocator(void
+ 	 * FIXME: Don't need the extra page at 4K, but need to fix
+ 	 * trampoline before removing it. (see the GDT stuff)
+ 	 */
+-	reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
++	reserve_bootmem(PAGE_SIZE, PAGE_SIZE, BOOTMEM_DEFAULT);
+ #endif
+ #ifdef CONFIG_ACPI_SLEEP
+ 	/*
+@@ -513,29 +684,12 @@ void __init setup_bootmem_allocator(void
+ 	 */
+ 	acpi_reserve_bootmem();
+ #endif
+-	numa_kva_reserve();
+ #endif /* !CONFIG_XEN */
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+-	if (xen_start_info->mod_start) {
+-		unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
+-		unsigned long ramdisk_size  = xen_start_info->mod_len;
+-		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+-		unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
+-
+-		if (ramdisk_end <= end_of_lowmem) {
+-			/*reserve_bootmem(ramdisk_image, ramdisk_size);*/
+-			initrd_start = ramdisk_image + PAGE_OFFSET;
+-			initrd_end = initrd_start+ramdisk_size;
+-			initrd_below_start_ok = 1;
+-		} else {
+-			printk(KERN_ERR "initrd extends beyond end of memory "
+-			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-			       ramdisk_end, end_of_lowmem);
+-			initrd_start = 0;
+-		}
+-	}
++	reserve_initrd();
+ #endif
++	numa_kva_reserve();
+ 	reserve_crashkernel();
+ }
+ 
+@@ -602,20 +756,14 @@ void __init setup_arch(char **cmdline_p)
+ 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+ 	pre_setup_arch_hook();
+ 	early_cpu_init();
++	early_ioremap_init();
+ #ifdef CONFIG_SMP
+ 	prefill_possible_map();
+ #endif
+ 
+-	/*
+-	 * FIXME: This isn't an official loader_type right
+-	 * now but does currently work with elilo.
+-	 * If we were configured as an EFI kernel, check to make
+-	 * sure that we were loaded correctly from elilo and that
+-	 * the system table is valid.  If not, then initialize normally.
+-	 */
+ #ifdef CONFIG_EFI
+-	if ((boot_params.hdr.type_of_loader == 0x50) &&
+-	    boot_params.efi_info.efi_systab)
++	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
++		     "EL32", 4))
+ 		efi_enabled = 1;
+ #endif
+ 
+@@ -655,12 +803,9 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ 	ARCH_SETUP
+-	if (efi_enabled)
+-		efi_init();
+-	else {
+-		printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+-		print_memory_map(memory_setup());
+-	}
++
++	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
++	print_memory_map(memory_setup());
+ 
+ 	copy_edd();
+ 
+@@ -693,6 +838,17 @@ void __init setup_arch(char **cmdline_p)
+ 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
++	if (efi_enabled)
++		efi_init();
++
++	/* update e820 for memory not covered by WB MTRRs */
++	find_max_pfn();
++	mtrr_bp_init();
++#ifndef CONFIG_XEN
++	if (mtrr_trim_uncached_memory(max_pfn))
++		find_max_pfn();
++#endif
++
+ 	max_low_pfn = setup_memory();
+ 
+ #ifdef CONFIG_VMI
+@@ -717,6 +873,16 @@ void __init setup_arch(char **cmdline_p)
+ 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+ #endif
+ 	paging_init();
++
++	/*
++	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
++	 */
++
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	if (init_ohci1394_dma_early)
++		init_ohci1394_dma_on_all_controllers();
++#endif
++
+ 	remapped_pgdat_init();
+ 	sparse_init();
+ 	zone_sizes_init();
+@@ -802,16 +968,20 @@ void __init setup_arch(char **cmdline_p)
+ 	 * NOTE: at this point the bootmem allocator is fully available.
+ 	 */
+ 
++#ifdef CONFIG_BLK_DEV_INITRD
++	relocate_initrd();
++#endif
++
+ 	paravirt_post_allocator_init();
+ 
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
++	io_delay_init();
++
+ #ifdef CONFIG_X86_GENERICARCH
+ 	generic_apic_probe();
+-#endif	
+-	if (efi_enabled)
+-		efi_map_memmap();
++#endif
+ 
+ 	set_iopl.iopl = 1;
+ 	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+@@ -829,7 +999,7 @@ void __init setup_arch(char **cmdline_p)
+ 	acpi_boot_table_init();
+ #endif
+ 
+-#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
+ 	early_quirks();
+ #endif
+ 
+@@ -875,3 +1045,30 @@ xen_panic_event(struct notifier_block *t
+ 	/* we're never actually going to get here... */
+ 	return NOTIFY_DONE;
+ }
++
++/*
++ * Request address space for all standard resources
++ *
++ * This is called just before pcibios_init(), which is also a
++ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
++ */
++static int __init request_standard_resources(void)
++{
++	int i;
++
++	/* Nothing to do if not running in dom0. */
++	if (!is_initial_xendomain())
++		return 0;
++
++	printk(KERN_INFO "Setting up standard PCI resources\n");
++	init_iomem_resources(&code_resource, &data_resource, &bss_resource);
++
++	request_resource(&iomem_resource, &video_ram_resource);
++
++	/* request I/O space for devices used on all i[345]86 PCs */
++	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
++		request_resource(&ioport_resource, &standard_io_resources[i]);
++	return 0;
++}
++
++subsys_initcall(request_standard_resources);
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -15,7 +15,6 @@
+ #include <linux/ptrace.h>
+ #include <linux/slab.h>
+ #include <linux/user.h>
+-#include <linux/a.out.h>
+ #include <linux/screen_info.h>
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+@@ -30,6 +29,7 @@
+ #include <linux/crash_dump.h>
+ #include <linux/root_dev.h>
+ #include <linux/pci.h>
++#include <linux/efi.h>
+ #include <linux/acpi.h>
+ #include <linux/kallsyms.h>
+ #include <linux/edd.h>
+@@ -39,10 +39,13 @@
+ #include <linux/dmi.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/ctype.h>
++#include <linux/uaccess.h>
++#include <linux/init_ohci1394_dma.h>
+ 
+ #include <asm/mtrr.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
++#include <asm/vsyscall.h>
+ #include <asm/io.h>
+ #include <asm/smp.h>
+ #include <asm/msr.h>
+@@ -50,6 +53,7 @@
+ #include <video/edid.h>
+ #include <asm/e820.h>
+ #include <asm/dma.h>
++#include <asm/gart.h>
+ #include <asm/mpspec.h>
+ #include <asm/mmu_context.h>
+ #include <asm/proto.h>
+@@ -59,6 +63,9 @@
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
+ #include <asm/cacheflush.h>
++#include <asm/mce.h>
++#include <asm/ds.h>
++#include <asm/topology.h>
+ #ifdef CONFIG_XEN
+ #include <linux/percpu.h>
+ #include <xen/interface/physdev.h>
+@@ -108,6 +115,8 @@ EXPORT_SYMBOL(xen_start_info);
+ struct cpuinfo_x86 boot_cpu_data __read_mostly;
+ EXPORT_SYMBOL(boot_cpu_data);
+ 
++__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
++
+ unsigned long mmu_cr4_features;
+ 
+ /* Boot loader ID as an integer, for the benefit of proc_dointvec */
+@@ -117,7 +126,7 @@ unsigned long saved_video_mode;
+ 
+ int force_mwait __cpuinitdata;
+ 
+-/* 
++/*
+  * Early DMI memory
+  */
+ int dmi_alloc_index;
+@@ -163,25 +172,27 @@ struct resource standard_io_resources[] 
+ 
+ #define IORESOURCE_RAM (IORESOURCE_BUSY | IORESOURCE_MEM)
+ 
+-struct resource data_resource = {
++static struct resource data_resource = {
+ 	.name = "Kernel data",
+ 	.start = 0,
+ 	.end = 0,
+ 	.flags = IORESOURCE_RAM,
+ };
+-struct resource code_resource = {
++static struct resource code_resource = {
+ 	.name = "Kernel code",
+ 	.start = 0,
+ 	.end = 0,
+ 	.flags = IORESOURCE_RAM,
+ };
+-struct resource bss_resource = {
++static struct resource bss_resource = {
+ 	.name = "Kernel bss",
+ 	.start = 0,
+ 	.end = 0,
+ 	.flags = IORESOURCE_RAM,
+ };
+ 
++static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
++
+ #ifdef CONFIG_PROC_VMCORE
+ /* elfcorehdr= specifies the location of elf core header
+  * stored by the crashed kernel. This option will be passed
+@@ -205,9 +216,10 @@ contig_initmem_init(unsigned long start_
+ 	unsigned long bootmap_size, bootmap;
+ 
+ 	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+-	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
++	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
++				 PAGE_SIZE);
+ 	if (bootmap == -1L)
+-		panic("Cannot find bootmem map of size %ld\n",bootmap_size);
++		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+ 	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+ 	e820_register_active_regions(0, start_pfn, end_pfn);
+ #ifdef CONFIG_XEN
+@@ -216,8 +228,8 @@ contig_initmem_init(unsigned long start_
+ 	else
+ #endif
+ 	free_bootmem_with_active_regions(0, end_pfn);
+-	reserve_bootmem(bootmap, bootmap_size);
+-} 
++	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
++}
+ #endif
+ 
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+@@ -250,27 +262,35 @@ static inline void copy_edd(void)
+ #ifndef CONFIG_XEN
+ static void __init reserve_crashkernel(void)
+ {
+-	unsigned long long free_mem;
++	unsigned long long total_mem;
+ 	unsigned long long crash_size, crash_base;
+ 	int ret;
+ 
+-	free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
++	total_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
+ 
+-	ret = parse_crashkernel(boot_command_line, free_mem,
++	ret = parse_crashkernel(boot_command_line, total_mem,
+ 			&crash_size, &crash_base);
+ 	if (ret == 0 && crash_size) {
+-		if (crash_base > 0) {
+-			printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+-					"for crashkernel (System RAM: %ldMB)\n",
+-					(unsigned long)(crash_size >> 20),
+-					(unsigned long)(crash_base >> 20),
+-					(unsigned long)(free_mem >> 20));
+-			crashk_res.start = crash_base;
+-			crashk_res.end   = crash_base + crash_size - 1;
+-			reserve_bootmem(crash_base, crash_size);
+-		} else
++		if (crash_base <= 0) {
+ 			printk(KERN_INFO "crashkernel reservation failed - "
+ 					"you have to specify a base address\n");
++			return;
++		}
++
++		if (reserve_bootmem(crash_base, crash_size,
++					BOOTMEM_EXCLUSIVE) < 0) {
++			printk(KERN_INFO "crashkernel reservation failed - "
++					"memory is in use\n");
++			return;
++		}
++
++		printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
++				"for crashkernel (System RAM: %ldMB)\n",
++				(unsigned long)(crash_size >> 20),
++				(unsigned long)(crash_base >> 20),
++				(unsigned long)(total_mem >> 20));
++		crashk_res.start = crash_base;
++		crashk_res.end   = crash_base + crash_size - 1;
+ 	}
+ }
+ #else
+@@ -281,37 +301,21 @@ static inline void __init reserve_crashk
+ {}
+ #endif
+ 
+-#ifndef CONFIG_XEN
+-#define EBDA_ADDR_POINTER 0x40E
+-
+-unsigned __initdata ebda_addr;
+-unsigned __initdata ebda_size;
+-
+-static void discover_ebda(void)
++/* Overridden in paravirt.c if CONFIG_PARAVIRT */
++void __attribute__((weak)) __init memory_setup(void)
+ {
+-	/*
+-	 * there is a real-mode segmented pointer pointing to the 
+-	 * 4K EBDA area at 0x40E
+-	 */
+-	ebda_addr = *(unsigned short *)__va(EBDA_ADDR_POINTER);
+-	ebda_addr <<= 4;
+-
+-	ebda_size = *(unsigned short *)__va(ebda_addr);
+-
+-	/* Round EBDA up to pages */
+-	if (ebda_size == 0)
+-		ebda_size = 1;
+-	ebda_size <<= 10;
+-	ebda_size = round_up(ebda_size + (ebda_addr & ~PAGE_MASK), PAGE_SIZE);
+-	if (ebda_size > 64*1024)
+-		ebda_size = 64*1024;
++       machine_specific_memory_setup();
+ }
+-#else
+-#define discover_ebda() ((void)0)
+-#endif
+ 
++/*
++ * setup_arch - architecture-specific boot-time initializations
++ *
++ * Note: On x86_64, fixmaps are ready for use even before this is called.
++ */
+ void __init setup_arch(char **cmdline_p)
+ {
++	unsigned i;
++
+ #ifdef CONFIG_XEN
+ 	extern struct e820map machine_e820;
+ 
+@@ -320,6 +324,11 @@ void __init setup_arch(char **cmdline_p)
+ 	/* Register a call for panic conditions. */
+ 	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+ 
++	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
++				     VMASST_TYPE_writable_pagetables));
++
++	early_ioremap_init();
++
+  	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); 
+ 	screen_info = boot_params.screen_info;
+ 
+@@ -336,11 +345,6 @@ void __init setup_arch(char **cmdline_p)
+ 		screen_info.orig_video_isVGA = 0;
+ 
+ 	copy_edid();
+-
+-	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+-				     VMASST_TYPE_writable_pagetables));
+-
+-	ARCH_SETUP
+ #else
+ 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ 
+@@ -356,7 +360,15 @@ void __init setup_arch(char **cmdline_p)
+ 	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+ 	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+ #endif
+-	setup_memory_region();
++#ifdef CONFIG_EFI
++	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
++		     "EL64", 4))
++		efi_enabled = 1;
++#endif
++
++	ARCH_SETUP
++
++	memory_setup();
+ 	copy_edd();
+ 
+ 	if (!boot_params.hdr.root_flags)
+@@ -380,28 +392,51 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	parse_early_param();
+ 
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	if (init_ohci1394_dma_early)
++		init_ohci1394_dma_on_all_controllers();
++#endif
++
+ 	finish_e820_parsing();
+ 
++	early_gart_iommu_check();
++
+ 	e820_register_active_regions(0, 0, -1UL);
+ 	/*
+ 	 * partially used pages are not usable - thus
+ 	 * we are rounding upwards:
+ 	 */
+ 	end_pfn = e820_end_of_ram();
++	/* update e820 for memory not covered by WB MTRRs */
++	mtrr_bp_init();
++#ifndef CONFIG_XEN
++	if (mtrr_trim_uncached_memory(end_pfn)) {
++		e820_register_active_regions(0, 0, -1UL);
++		end_pfn = e820_end_of_ram();
++	}
++#endif
++
+ 	num_physpages = end_pfn;
++	max_mapnr = end_pfn;
+ 
+ 	check_efer();
+ 
+-	discover_ebda();
+-
+ 	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
++	if (efi_enabled)
++		efi_init();
+ 
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
++	io_delay_init();
++
+ #if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+-	/* setup to use the static apicid table during kernel startup */
+-	x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
++	/* setup to use the early static init tables during kernel startup */
++	x86_cpu_to_apicid_early_ptr = (void *)x86_cpu_to_apicid_init;
++	x86_bios_cpu_apicid_early_ptr = (void *)x86_bios_cpu_apicid_init;
++#ifdef CONFIG_NUMA
++	x86_cpu_to_node_map_early_ptr = (void *)x86_cpu_to_node_map_init;
++#endif
+ #endif
+ 
+ 	/* How many end-of-memory variables you have, grandma! */
+@@ -420,54 +455,25 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ #ifdef CONFIG_NUMA
+-	numa_initmem_init(0, end_pfn); 
++	numa_initmem_init(0, end_pfn);
+ #else
+ 	contig_initmem_init(0, end_pfn);
+ #endif
+ 
+-#ifdef CONFIG_XEN
+-	/*
+-	 * Reserve kernel, physmap, start info, initial page tables, and
+-	 * direct mapping.
+-	 */
+-	reserve_bootmem_generic(__pa_symbol(&_text),
+-	                        (table_end << PAGE_SHIFT) - __pa_symbol(&_text));
+-#else
+-	/* Reserve direct mapping */
+-	reserve_bootmem_generic(table_start << PAGE_SHIFT, 
+-				(table_end - table_start) << PAGE_SHIFT);
+-
+-	/* reserve kernel */
+-	reserve_bootmem_generic(__pa_symbol(&_text),
+-				__pa_symbol(&_end) - __pa_symbol(&_text));
++	early_res_to_bootmem();
+ 
++#ifndef CONFIG_XEN
++#ifdef CONFIG_ACPI_SLEEP
+ 	/*
+-	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+-	 * enabling clean reboots, SMP operation, laptop functions.
++	 * Reserve low memory region for sleep support.
+ 	 */
+-	reserve_bootmem_generic(0, PAGE_SIZE);
+-
+-	/* reserve ebda region */
+-	if (ebda_addr)
+-		reserve_bootmem_generic(ebda_addr, ebda_size);
+-#ifdef CONFIG_NUMA
+-	/* reserve nodemap region */
+-	if (nodemap_addr)
+-		reserve_bootmem_generic(nodemap_addr, nodemap_size);
++       acpi_reserve_bootmem();
+ #endif
+ 
+-#ifdef CONFIG_SMP
+-	/* Reserve SMP trampoline */
+-	reserve_bootmem_generic(SMP_TRAMPOLINE_BASE, 2*PAGE_SIZE);
+-#endif
++	if (efi_enabled)
++		efi_reserve_bootmem();
+ #endif
+ 
+-#ifdef CONFIG_ACPI_SLEEP
+-       /*
+-        * Reserve low memory region for sleep support.
+-        */
+-       acpi_reserve_bootmem();
+-#endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+ #ifdef CONFIG_XEN
+ 	if (xen_start_info->mod_start) {
+@@ -491,6 +497,8 @@ void __init setup_arch(char **cmdline_p)
+ 			initrd_below_start_ok = 1;
+ #endif
+ 		} else {
++			/* Assumes everything on node 0 */
++			free_bootmem(ramdisk_image, ramdisk_size);
+ 			printk(KERN_ERR "initrd extends beyond end of memory "
+ 			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ 			       ramdisk_end, end_of_mem);
+@@ -500,10 +508,11 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 	reserve_crashkernel();
+ 	paging_init();
++	map_vsyscall();
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	/*
+-	 * Find and reserve possible boot-time SMP configuration:
+-	 */
++	* Find and reserve possible boot-time SMP configuration:
++	*/
+ 	find_smp_config();
+ #endif
+ #ifdef CONFIG_XEN
+@@ -591,16 +600,10 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ #endif
+ 
+-#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
+ 	early_quirks();
+ #endif
+ 
+-	/*
+-	 * set this early, so we dont allocate cpu0
+-	 * if MADT list doesnt list BSP first
+-	 * mpparse.c/MP_processor_info() allocates logical cpu numbers.
+-	 */
+-	cpu_set(0, cpu_present_map);
+ #ifdef CONFIG_ACPI
+ 	/*
+ 	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
+@@ -624,6 +627,7 @@ void __init setup_arch(char **cmdline_p)
+ 		get_smp_config();
+ #ifndef CONFIG_XEN
+ 	init_apic_mappings();
++	ioapic_init_mappings();
+ #endif
+ #endif
+ #if defined(CONFIG_XEN) && defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
+@@ -635,18 +639,17 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain())
+-		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
++		e820_reserve_resources(machine_e820.map, machine_e820.nr_map,
++				       &code_resource, &data_resource, &bss_resource);
+ #else
+-	e820_reserve_resources(e820.map, e820.nr_map);
++	e820_reserve_resources(e820.map, e820.nr_map,
++			       &code_resource, &data_resource, &bss_resource);
+ 	e820_mark_nosave_regions();
+ #endif
+ 
+-	{
+-	unsigned i;
+ 	/* request I/O space for devices used on all i[345]86 PCs */
+ 	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+ 		request_resource(&ioport_resource, &standard_io_resources[i]);
+-	}
+ 
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain())
+@@ -680,7 +683,8 @@ void __init setup_arch(char **cmdline_p)
+ 
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+-	conswitchp = &vga_con;
++	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
++		conswitchp = &vga_con;
+ #elif defined(CONFIG_DUMMY_CONSOLE)
+ 	conswitchp = &dummy_con;
+ #endif
+@@ -724,9 +728,10 @@ static void __cpuinit display_cacheinfo(
+ 
+ 	if (n >= 0x80000005) {
+ 		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
+-		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+-			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size=(ecx>>24)+(edx>>24);
++		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
++		       "D cache %dK (%d bytes/line)\n",
++		       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
++		c->x86_cache_size = (ecx>>24) + (edx>>24);
+ 		/* On K8 L1 TLB is inclusive, so don't count it */
+ 		c->x86_tlbsize = 0;
+ 	}
+@@ -740,27 +745,25 @@ static void __cpuinit display_cacheinfo(
+ 		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+ 		c->x86_cache_size, ecx & 0xFF);
+ 	}
+-
+-	if (n >= 0x80000007)
+-		cpuid(0x80000007, &dummy, &dummy, &dummy, &c->x86_power); 
+ 	if (n >= 0x80000008) {
+-		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy); 
++		cpuid(0x80000008, &eax, &dummy, &dummy, &dummy);
+ 		c->x86_virt_bits = (eax >> 8) & 0xff;
+ 		c->x86_phys_bits = eax & 0xff;
+ 	}
+ }
+ 
+ #ifdef CONFIG_NUMA
+-static int nearby_node(int apicid)
++static int __cpuinit nearby_node(int apicid)
+ {
+-	int i;
++	int i, node;
++
+ 	for (i = apicid - 1; i >= 0; i--) {
+-		int node = apicid_to_node[i];
++		node = apicid_to_node[i];
+ 		if (node != NUMA_NO_NODE && node_online(node))
+ 			return node;
+ 	}
+ 	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+-		int node = apicid_to_node[i];
++		node = apicid_to_node[i];
+ 		if (node != NUMA_NO_NODE && node_online(node))
+ 			return node;
+ 	}
+@@ -772,7 +775,7 @@ static int nearby_node(int apicid)
+  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
+  * Assumes number of cores is a power of two.
+  */
+-static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
++static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
+ {
+ #ifdef CONFIG_SMP
+ 	unsigned bits;
+@@ -781,7 +784,54 @@ static void __init amd_detect_cmp(struct
+ 	int node = 0;
+ 	unsigned apicid = hard_smp_processor_id();
+ #endif
+-	unsigned ecx = cpuid_ecx(0x80000008);
++	bits = c->x86_coreid_bits;
++
++	/* Low order bits define the core id (index of core in socket) */
++	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
++	/* Convert the APIC ID into the socket ID */
++	c->phys_proc_id = phys_pkg_id(bits);
++
++#ifdef CONFIG_NUMA
++	node = c->phys_proc_id;
++	if (apicid_to_node[apicid] != NUMA_NO_NODE)
++		node = apicid_to_node[apicid];
++	if (!node_online(node)) {
++		/* Two possibilities here:
++		   - The CPU is missing memory and no node was created.
++		   In that case try picking one from a nearby CPU
++		   - The APIC IDs differ from the HyperTransport node IDs
++		   which the K8 northbridge parsing fills in.
++		   Assume they are all increased by a constant offset,
++		   but in the same order as the HT nodeids.
++		   If that doesn't result in a usable node fall back to the
++		   path for the previous case.  */
++
++		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
++
++		if (ht_nodeid >= 0 &&
++		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
++			node = apicid_to_node[ht_nodeid];
++		/* Pick a nearby node */
++		if (!node_online(node))
++			node = nearby_node(apicid);
++	}
++	numa_set_node(cpu, node);
++
++	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
++#endif
++#endif
++}
++
++static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_SMP
++	unsigned bits, ecx;
++
++	/* Multi core CPU? */
++	if (c->extended_cpuid_level < 0x80000008)
++		return;
++
++	ecx = cpuid_ecx(0x80000008);
+ 
+ 	c->x86_max_cores = (ecx & 0xff) + 1;
+ 
+@@ -794,37 +844,8 @@ static void __init amd_detect_cmp(struct
+ 			bits++;
+ 	}
+ 
+-	/* Low order bits define the core id (index of core in socket) */
+-	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
+-	/* Convert the APIC ID into the socket ID */
+-	c->phys_proc_id = phys_pkg_id(bits);
+-
+-#ifdef CONFIG_NUMA
+-  	node = c->phys_proc_id;
+- 	if (apicid_to_node[apicid] != NUMA_NO_NODE)
+- 		node = apicid_to_node[apicid];
+- 	if (!node_online(node)) {
+- 		/* Two possibilities here:
+- 		   - The CPU is missing memory and no node was created.
+- 		   In that case try picking one from a nearby CPU
+- 		   - The APIC IDs differ from the HyperTransport node IDs
+- 		   which the K8 northbridge parsing fills in.
+- 		   Assume they are all increased by a constant offset,
+- 		   but in the same order as the HT nodeids.
+- 		   If that doesn't result in a usable node fall back to the
+- 		   path for the previous case.  */
+-		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
+- 		if (ht_nodeid >= 0 &&
+- 		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+- 			node = apicid_to_node[ht_nodeid];
+- 		/* Pick a nearby node */
+- 		if (!node_online(node))
+- 			node = nearby_node(apicid);
+- 	}
+-	numa_set_node(cpu, node);
++	c->x86_coreid_bits = bits;
+ 
+-	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+-#endif
+ #endif
+ }
+ 
+@@ -841,8 +862,8 @@ static void __init amd_detect_cmp(struct
+ /* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
+ static __cpuinit int amd_apic_timer_broken(void)
+ {
+-	u32 lo, hi;
+-	u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
++	u32 lo, hi, eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
++
+ 	switch (eax & CPUID_XFAM) {
+ 	case CPUID_XFAM_K8:
+ 		if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
+@@ -861,6 +882,15 @@ static __cpuinit int amd_apic_timer_brok
+ }
+ #endif
+ 
++static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
++{
++	early_init_amd_mc(c);
++
++ 	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
++	if (c->x86_power & (1<<8))
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
++}
++
+ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ {
+ 	unsigned level;
+@@ -871,7 +901,7 @@ static void __cpuinit init_amd(struct cp
+ 	/*
+ 	 * Disable TLB flush filter by setting HWCR.FFDIS on K8
+ 	 * bit 6 of msr C001_0015
+- 	 *
++	 *
+ 	 * Errata 63 for SH-B3 steppings
+ 	 * Errata 122 for all steppings (F+ have it disabled by default)
+ 	 */
+@@ -884,35 +914,32 @@ static void __cpuinit init_amd(struct cp
+ 
+ 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+-	clear_bit(0*32+31, &c->x86_capability);
+-	
++	clear_bit(0*32+31, (unsigned long *)&c->x86_capability);
++
+ 	/* On C+ stepping K8 rep microcode works well for copy/memset */
+ 	level = cpuid_eax(1);
+-	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+-		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
++	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
++			     level >= 0x0f58))
++		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ 	if (c->x86 == 0x10 || c->x86 == 0x11)
+-		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ 
+ 	/* Enable workaround for FXSAVE leak */
+ 	if (c->x86 >= 6)
+-		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_FXSAVE_LEAK);
+ 
+ 	level = get_model_name(c);
+ 	if (!level) {
+-		switch (c->x86) { 
++		switch (c->x86) {
+ 		case 15:
+ 			/* Should distinguish Models here, but this is only
+ 			   a fallback anyways. */
+ 			strcpy(c->x86_model_id, "Hammer");
+-			break; 
+-		} 
+-	} 
++			break;
++		}
++	}
+ 	display_cacheinfo(c);
+ 
+-	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
+-	if (c->x86_power & (1<<8))
+-		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+-
+ 	/* Multi core CPU? */
+ 	if (c->extended_cpuid_level >= 0x80000008)
+ 		amd_detect_cmp(c);
+@@ -924,14 +951,10 @@ static void __cpuinit init_amd(struct cp
+ 		num_cache_leaves = 3;
+ 
+ 	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
+-		set_bit(X86_FEATURE_K8, &c->x86_capability);
+-
+-	/* RDTSC can be speculated around */
+-	clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_K8);
+ 
+-	/* Family 10 doesn't support C states in MWAIT so don't use it */
+-	if (c->x86 == 0x10 && !force_mwait)
+-		clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
++	/* MFENCE stops RDTSC speculation */
++	set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
+ 
+ #ifndef CONFIG_XEN
+ 	if (amd_apic_timer_broken())
+@@ -939,28 +962,29 @@ static void __cpuinit init_amd(struct cp
+ #endif
+ }
+ 
+-static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
++void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ {
+ #ifdef CONFIG_SMP
+-	u32 	eax, ebx, ecx, edx;
+-	int 	index_msb, core_bits;
++	u32 eax, ebx, ecx, edx;
++	int index_msb, core_bits;
+ 
+ 	cpuid(1, &eax, &ebx, &ecx, &edx);
+ 
+ 
+ 	if (!cpu_has(c, X86_FEATURE_HT))
+ 		return;
+- 	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
++	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+ 		goto out;
+ 
+ 	smp_num_siblings = (ebx & 0xff0000) >> 16;
+ 
+ 	if (smp_num_siblings == 1) {
+ 		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1 ) {
++	} else if (smp_num_siblings > 1) {
+ 
+ 		if (smp_num_siblings > NR_CPUS) {
+-			printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
++			printk(KERN_WARNING "CPU: Unsupported number of "
++			       "siblings %d", smp_num_siblings);
+ 			smp_num_siblings = 1;
+ 			return;
+ 		}
+@@ -970,7 +994,7 @@ static void __cpuinit detect_ht(struct c
+ 
+ 		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+ 
+-		index_msb = get_count_order(smp_num_siblings) ;
++		index_msb = get_count_order(smp_num_siblings);
+ 
+ 		core_bits = get_count_order(c->x86_max_cores);
+ 
+@@ -979,8 +1003,10 @@ static void __cpuinit detect_ht(struct c
+ 	}
+ out:
+ 	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+-		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n", c->phys_proc_id);
+-		printk(KERN_INFO  "CPU: Processor Core ID: %d\n", c->cpu_core_id);
++		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
++		       c->phys_proc_id);
++		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
++		       c->cpu_core_id);
+ 	}
+ 
+ #endif
+@@ -1004,7 +1030,7 @@ static int __cpuinit intel_num_cpu_cores
+ 		return 1;
+ }
+ 
+-static void srat_detect_node(void)
++static void __cpuinit srat_detect_node(void)
+ {
+ #ifdef CONFIG_NUMA
+ 	unsigned node;
+@@ -1014,7 +1040,7 @@ static void srat_detect_node(void)
+ 	/* Don't do the funky fallback heuristics the AMD version employs
+ 	   for now. */
+ 	node = apicid_to_node[apicid];
+-	if (node == NUMA_NO_NODE)
++	if (node == NUMA_NO_NODE || !node_online(node))
+ 		node = first_node(node_online_map);
+ 	numa_set_node(cpu, node);
+ 
+@@ -1022,28 +1048,39 @@ static void srat_detect_node(void)
+ #endif
+ }
+ 
++static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
++{
++	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
++	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
++		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++}
++
+ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+ {
+ 	/* Cache sizes */
+ 	unsigned n;
+ 
+ 	init_intel_cacheinfo(c);
+-	if (c->cpuid_level > 9 ) {
++	if (c->cpuid_level > 9) {
+ 		unsigned eax = cpuid_eax(10);
+ 		/* Check for version and the number of counters */
+ 		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+-			set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
+ 	}
+ 
+ 	if (cpu_has_ds) {
+ 		unsigned int l1, l2;
+ 		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
+ 		if (!(l1 & (1<<11)))
+-			set_bit(X86_FEATURE_BTS, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_BTS);
+ 		if (!(l1 & (1<<12)))
+-			set_bit(X86_FEATURE_PEBS, c->x86_capability);
++			set_cpu_cap(c, X86_FEATURE_PEBS);
+ 	}
+ 
++
++	if (cpu_has_bts)
++		ds_init_intel(c);
++
+ 	n = c->extended_cpuid_level;
+ 	if (n >= 0x80000008) {
+ 		unsigned eax = cpuid_eax(0x80000008);
+@@ -1060,14 +1097,11 @@ static void __cpuinit init_intel(struct 
+ 		c->x86_cache_alignment = c->x86_clflush_size * 2;
+ 	if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ 	    (c->x86 == 0x6 && c->x86_model >= 0x0e))
+-		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
++		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+ 	if (c->x86 == 6)
+-		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+-	if (c->x86 == 15)
+-		set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+-	else
+-		clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+- 	c->x86_max_cores = intel_num_cpu_cores(c);
++		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
++	set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
++	c->x86_max_cores = intel_num_cpu_cores(c);
+ 
+ 	srat_detect_node();
+ }
+@@ -1084,18 +1118,12 @@ static void __cpuinit get_cpu_vendor(str
+ 		c->x86_vendor = X86_VENDOR_UNKNOWN;
+ }
+ 
+-struct cpu_model_info {
+-	int vendor;
+-	int family;
+-	char *model_names[16];
+-};
+-
+ /* Do some early cpuid on the boot CPU to get some parameter that are
+    needed before check_bugs. Everything advanced is in identify_cpu
+    below. */
+-void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
++static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+ {
+-	u32 tfms;
++	u32 tfms, xlvl;
+ 
+ 	c->loops_per_jiffy = loops_per_jiffy;
+ 	c->x86_cache_size = -1;
+@@ -1106,6 +1134,7 @@ void __cpuinit early_identify_cpu(struct
+ 	c->x86_clflush_size = 64;
+ 	c->x86_cache_alignment = c->x86_clflush_size;
+ 	c->x86_max_cores = 1;
++	c->x86_coreid_bits = 0;
+ 	c->extended_cpuid_level = 0;
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ 
+@@ -1114,7 +1143,7 @@ void __cpuinit early_identify_cpu(struct
+ 	      (unsigned int *)&c->x86_vendor_id[0],
+ 	      (unsigned int *)&c->x86_vendor_id[8],
+ 	      (unsigned int *)&c->x86_vendor_id[4]);
+-		
++
+ 	get_cpu_vendor(c);
+ 
+ 	/* Initialize the standard set of capabilities */
+@@ -1132,7 +1161,7 @@ void __cpuinit early_identify_cpu(struct
+ 			c->x86 += (tfms >> 20) & 0xff;
+ 		if (c->x86 >= 0x6)
+ 			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		if (c->x86_capability[0] & (1<<19)) 
++		if (c->x86_capability[0] & (1<<19))
+ 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+ 	} else {
+ 		/* Have CPUID level 0 only - unheard of */
+@@ -1142,18 +1171,6 @@ void __cpuinit early_identify_cpu(struct
+ #ifdef CONFIG_SMP
+ 	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+ #endif
+-}
+-
+-/*
+- * This does the hard work of actually picking apart the CPU stuff...
+- */
+-void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+-{
+-	int i;
+-	u32 xlvl;
+-
+-	early_identify_cpu(c);
+-
+ 	/* AMD-defined flags: level 0x80000001 */
+ 	xlvl = cpuid_eax(0x80000000);
+ 	c->extended_cpuid_level = xlvl;
+@@ -1174,6 +1191,30 @@ void __cpuinit identify_cpu(struct cpuin
+ 			c->x86_capability[2] = cpuid_edx(0x80860001);
+ 	}
+ 
++	c->extended_cpuid_level = cpuid_eax(0x80000000);
++	if (c->extended_cpuid_level >= 0x80000007)
++		c->x86_power = cpuid_edx(0x80000007);
++
++	switch (c->x86_vendor) {
++	case X86_VENDOR_AMD:
++		early_init_amd(c);
++		break;
++	case X86_VENDOR_INTEL:
++		early_init_intel(c);
++		break;
++	}
++
++}
++
++/*
++ * This does the hard work of actually picking apart the CPU stuff...
++ */
++void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
++{
++	int i;
++
++	early_identify_cpu(c);
++
+ 	init_scattered_cpuid_features(c);
+ 
+ #ifndef CONFIG_XEN
+@@ -1205,8 +1246,7 @@ void __cpuinit identify_cpu(struct cpuin
+ 		break;
+ 	}
+ 
+-	select_idle_routine(c);
+-	detect_ht(c); 
++	detect_ht(c);
+ 
+ 	/*
+ 	 * On SMP, boot_cpu_data holds the common feature set between
+@@ -1216,31 +1256,55 @@ void __cpuinit identify_cpu(struct cpuin
+ 	 */
+ 	if (c != &boot_cpu_data) {
+ 		/* AND the already accumulated flags with these */
+-		for (i = 0 ; i < NCAPINTS ; i++)
++		for (i = 0; i < NCAPINTS; i++)
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
++	/* Clear all flags overriden by options */
++	for (i = 0; i < NCAPINTS; i++)
++		c->x86_capability[i] &= ~cleared_cpu_caps[i];
++
+ #ifdef CONFIG_X86_MCE
+ 	mcheck_init(c);
+ #endif
++	select_idle_routine(c);
++
+ 	if (c != &boot_cpu_data)
+ 		mtrr_ap_init();
+ #ifdef CONFIG_NUMA
+ 	numa_add_cpu(smp_processor_id());
+ #endif
++
+ }
+- 
++
++static __init int setup_noclflush(char *arg)
++{
++	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
++	return 1;
++}
++__setup("noclflush", setup_noclflush);
+ 
+ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+ {
+ 	if (c->x86_model_id[0])
+-		printk("%s", c->x86_model_id);
++		printk(KERN_CONT "%s", c->x86_model_id);
++
++	if (c->x86_mask || c->cpuid_level >= 0)
++		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
++	else
++		printk(KERN_CONT "\n");
++}
+ 
+-	if (c->x86_mask || c->cpuid_level >= 0) 
+-		printk(" stepping %02x\n", c->x86_mask);
++static __init int setup_disablecpuid(char *arg)
++{
++	int bit;
++	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
++		setup_clear_cpu_cap(bit);
+ 	else
+-		printk("\n");
++		return 0;
++	return 1;
+ }
++__setup("clearcpuid=", setup_disablecpuid);
+ 
+ /*
+  *	Get CPU information for use by the procfs.
+@@ -1249,116 +1313,41 @@ void __cpuinit print_cpu_info(struct cpu
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ 	struct cpuinfo_x86 *c = v;
+-	int cpu = 0;
+-
+-	/* 
+-	 * These flag bits must match the definitions in <asm/cpufeature.h>.
+-	 * NULL means this bit is undefined or reserved; either way it doesn't
+-	 * have meaning as far as Linux is concerned.  Note that it's important
+-	 * to realize there is a difference between this table and CPUID -- if
+-	 * applications want to get the raw CPUID data, they should access
+-	 * /dev/cpu/<cpu_nr>/cpuid instead.
+-	 */
+-	static const char *const x86_cap_flags[] = {
+-		/* Intel-defined */
+-	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+-	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+-	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
+-
+-		/* AMD-defined */
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
+-		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+-		"3dnowext", "3dnow",
+-
+-		/* Transmeta-defined */
+-		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Other (Linux-defined) */
+-		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+-		NULL, NULL, NULL, NULL,
+-		"constant_tsc", "up", NULL, "arch_perfmon",
+-		"pebs", "bts", NULL, "sync_rdtsc",
+-		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Intel-defined (#2) */
+-		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+-		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* VIA/Cyrix/Centaur-defined */
+-		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+-		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* AMD-defined (#2) */
+-		"lahf_lm", "cmp_legacy", "svm", "extapic",
+-		"cr8_legacy", "abm", "sse4a", "misalignsse",
+-		"3dnowprefetch", "osvw", "ibs", "sse5",
+-		"skinit", "wdt", NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Auxiliary (Linux-defined) */
+-		"ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-	};
+-	static const char *const x86_power_flags[] = {
+-		"ts",	/* temperature sensor */
+-		"fid",  /* frequency id control */
+-		"vid",  /* voltage id control */
+-		"ttp",  /* thermal trip */
+-		"tm",
+-		"stc",
+-		"100mhzsteps",
+-		"hwpstate",
+-		"",	/* tsc invariant mapped to constant_tsc */
+-		/* nothing */
+-	};
+-
++	int cpu = 0, i;
+ 
+ #ifdef CONFIG_SMP
+ 	cpu = c->cpu_index;
+ #endif
+ 
+-	seq_printf(m,"processor\t: %u\n"
+-		     "vendor_id\t: %s\n"
+-		     "cpu family\t: %d\n"
+-		     "model\t\t: %d\n"
+-		     "model name\t: %s\n",
+-		     (unsigned)cpu,
+-		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+-		     c->x86,
+-		     (int)c->x86_model,
+-		     c->x86_model_id[0] ? c->x86_model_id : "unknown");
+-	
++	seq_printf(m, "processor\t: %u\n"
++		   "vendor_id\t: %s\n"
++		   "cpu family\t: %d\n"
++		   "model\t\t: %d\n"
++		   "model name\t: %s\n",
++		   (unsigned)cpu,
++		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
++		   c->x86,
++		   (int)c->x86_model,
++		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
++
+ 	if (c->x86_mask || c->cpuid_level >= 0)
+ 		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+ 	else
+ 		seq_printf(m, "stepping\t: unknown\n");
+-	
+-	if (cpu_has(c,X86_FEATURE_TSC)) {
++
++	if (cpu_has(c, X86_FEATURE_TSC)) {
+ 		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
++
+ 		if (!freq)
+ 			freq = cpu_khz;
+ 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+-			     freq / 1000, (freq % 1000));
++			   freq / 1000, (freq % 1000));
+ 	}
+ 
+ 	/* Cache size */
+-	if (c->x86_cache_size >= 0) 
++	if (c->x86_cache_size >= 0)
+ 		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+-	
++
+ #ifdef CONFIG_SMP
+ 	if (smp_num_siblings * c->x86_max_cores > 1) {
+ 		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+@@ -1367,48 +1356,43 @@ static int show_cpuinfo(struct seq_file 
+ 		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+ 		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+ 	}
+-#endif	
++#endif
+ 
+ 	seq_printf(m,
+-	        "fpu\t\t: yes\n"
+-	        "fpu_exception\t: yes\n"
+-	        "cpuid level\t: %d\n"
+-	        "wp\t\t: yes\n"
+-	        "flags\t\t:",
++		   "fpu\t\t: yes\n"
++		   "fpu_exception\t: yes\n"
++		   "cpuid level\t: %d\n"
++		   "wp\t\t: yes\n"
++		   "flags\t\t:",
+ 		   c->cpuid_level);
+ 
+-	{ 
+-		int i; 
+-		for ( i = 0 ; i < 32*NCAPINTS ; i++ )
+-			if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
+-				seq_printf(m, " %s", x86_cap_flags[i]);
+-	}
+-		
++	for (i = 0; i < 32*NCAPINTS; i++)
++		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
++			seq_printf(m, " %s", x86_cap_flags[i]);
++
+ 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
+ 		   c->loops_per_jiffy/(500000/HZ),
+ 		   (c->loops_per_jiffy/(5000/HZ)) % 100);
+ 
+-	if (c->x86_tlbsize > 0) 
++	if (c->x86_tlbsize > 0)
+ 		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
+ 	seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
+ 	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
+ 
+-	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 
++	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
+ 		   c->x86_phys_bits, c->x86_virt_bits);
+ 
+ 	seq_printf(m, "power management:");
+-	{
+-		unsigned i;
+-		for (i = 0; i < 32; i++) 
+-			if (c->x86_power & (1 << i)) {
+-				if (i < ARRAY_SIZE(x86_power_flags) &&
+-					x86_power_flags[i])
+-					seq_printf(m, "%s%s",
+-						x86_power_flags[i][0]?" ":"",
+-						x86_power_flags[i]);
+-				else
+-					seq_printf(m, " [%d]", i);
+-			}
++	for (i = 0; i < 32; i++) {
++		if (c->x86_power & (1 << i)) {
++			if (i < ARRAY_SIZE(x86_power_flags) &&
++			    x86_power_flags[i])
++				seq_printf(m, "%s%s",
++					   x86_power_flags[i][0]?" ":"",
++					   x86_power_flags[i]);
++			else
++				seq_printf(m, " [%d]", i);
++		}
+ 	}
+ 
+ 	seq_printf(m, "\n\n");
+@@ -1435,8 +1419,8 @@ static void c_stop(struct seq_file *m, v
+ {
+ }
+ 
+-struct seq_operations cpuinfo_op = {
+-	.start =c_start,
++const struct seq_operations cpuinfo_op = {
++	.start = c_start,
+ 	.next =	c_next,
+ 	.stop =	c_stop,
+ 	.show =	show_cpuinfo,
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -168,7 +168,7 @@ void __send_IPI_shortcut(unsigned int sh
+ 	}
+ }
+ 
+-void fastcall send_IPI_self(int vector)
++void send_IPI_self(int vector)
+ {
+ 	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+ }
+@@ -224,13 +224,14 @@ static DEFINE_SPINLOCK(tlbstate_lock);
+  * We need to reload %cr3 since the page tables may be going
+  * away from under us..
+  */
+-void leave_mm(unsigned long cpu)
++void leave_mm(int cpu)
+ {
+ 	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+ 		BUG();
+ 	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
+ 	load_cr3(swapper_pg_dir);
+ }
++EXPORT_SYMBOL_GPL(leave_mm);
+ 
+ /*
+  *
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -33,7 +33,7 @@
+ 
+ #ifndef CONFIG_XEN
+ /*
+- *	Smarter SMP flushing macros. 
++ *	Smarter SMP flushing macros.
+  *		c/o Linus Torvalds.
+  *
+  *	These mean you can really definitely utterly forget about
+@@ -41,15 +41,15 @@
+  *
+  *	Optimizations Manfred Spraul <manfred@colorfullife.com>
+  *
+- * 	More scalable flush, from Andi Kleen
++ *	More scalable flush, from Andi Kleen
+  *
+- * 	To avoid global state use 8 different call vectors.
+- * 	Each CPU uses a specific vector to trigger flushes on other
+- * 	CPUs. Depending on the received vector the target CPUs look into
++ *	To avoid global state use 8 different call vectors.
++ *	Each CPU uses a specific vector to trigger flushes on other
++ *	CPUs. Depending on the received vector the target CPUs look into
+  *	the right per cpu variable for the flush data.
+  *
+- * 	With more than 8 CPUs they are hashed to the 8 available
+- * 	vectors. The limited global vector space forces us to this right now.
++ *	With more than 8 CPUs they are hashed to the 8 available
++ *	vectors. The limited global vector space forces us to this right now.
+  *	In future when interrupts are split into per CPU domains this could be
+  *	fixed, at the cost of triggering multiple IPIs in some cases.
+  */
+@@ -59,7 +59,6 @@ union smp_flush_state {
+ 		cpumask_t flush_cpumask;
+ 		struct mm_struct *flush_mm;
+ 		unsigned long flush_va;
+-#define FLUSH_ALL	-1ULL
+ 		spinlock_t tlbstate_lock;
+ 	};
+ 	char pad[SMP_CACHE_BYTES];
+@@ -71,16 +70,17 @@ union smp_flush_state {
+ static DEFINE_PER_CPU(union smp_flush_state, flush_state);
+ 
+ /*
+- * We cannot call mmdrop() because we are in interrupt context, 
++ * We cannot call mmdrop() because we are in interrupt context,
+  * instead update mm->cpu_vm_mask.
+  */
+-static inline void leave_mm(unsigned long cpu)
++void leave_mm(int cpu)
+ {
+ 	if (read_pda(mmu_state) == TLBSTATE_OK)
+ 		BUG();
+ 	cpu_clear(cpu, read_pda(active_mm)->cpu_vm_mask);
+ 	load_cr3(swapper_pg_dir);
+ }
++EXPORT_SYMBOL_GPL(leave_mm);
+ 
+ /*
+  *
+@@ -89,25 +89,25 @@ static inline void leave_mm(unsigned lon
+  * 1) switch_mm() either 1a) or 1b)
+  * 1a) thread switch to a different mm
+  * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+- * 	Stop ipi delivery for the old mm. This is not synchronized with
+- * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * 	for the wrong mm, and in the worst case we perform a superfluous
+- * 	tlb flush.
++ *	Stop ipi delivery for the old mm. This is not synchronized with
++ *	the other cpus, but smp_invalidate_interrupt ignore flush ipis
++ *	for the wrong mm, and in the worst case we perform a superfluous
++ *	tlb flush.
+  * 1a2) set cpu mmu_state to TLBSTATE_OK
+- * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
++ *	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+  *	was in lazy tlb mode.
+  * 1a3) update cpu active_mm
+- * 	Now cpu0 accepts tlb flushes for the new mm.
++ *	Now cpu0 accepts tlb flushes for the new mm.
+  * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
+- * 	Now the other cpus will send tlb flush ipis.
++ *	Now the other cpus will send tlb flush ipis.
+  * 1a4) change cr3.
+  * 1b) thread switch without mm change
+  *	cpu active_mm is correct, cpu0 already handles
+  *	flush ipis.
+  * 1b1) set cpu mmu_state to TLBSTATE_OK
+  * 1b2) test_and_set the cpu bit in cpu_vm_mask.
+- * 	Atomically set the bit [other cpus will start sending flush ipis],
+- * 	and test the bit.
++ *	Atomically set the bit [other cpus will start sending flush ipis],
++ *	and test the bit.
+  * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
+  * 2) switch %%esp, ie current
+  *
+@@ -141,12 +141,12 @@ asmlinkage void smp_invalidate_interrupt
+ 	 * orig_rax contains the negated interrupt vector.
+ 	 * Use that to determine where the sender put the data.
+ 	 */
+-	sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
++	sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
+ 	f = &per_cpu(flush_state, sender);
+ 
+ 	if (!cpu_isset(cpu, f->flush_cpumask))
+ 		goto out;
+-		/* 
++		/*
+ 		 * This was a BUG() but until someone can quote me the
+ 		 * line from the intel manual that guarantees an IPI to
+ 		 * multiple CPUs is retried _only_ on the erroring CPUs
+@@ -154,10 +154,10 @@ asmlinkage void smp_invalidate_interrupt
+ 		 *
+ 		 * BUG();
+ 		 */
+-		 
++
+ 	if (f->flush_mm == read_pda(active_mm)) {
+ 		if (read_pda(mmu_state) == TLBSTATE_OK) {
+-			if (f->flush_va == FLUSH_ALL)
++			if (f->flush_va == TLB_FLUSH_ALL)
+ 				local_flush_tlb();
+ 			else
+ 				__flush_tlb_one(f->flush_va);
+@@ -170,19 +170,22 @@ out:
+ 	add_pda(irq_tlb_count, 1);
+ }
+ 
+-static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+-						unsigned long va)
++void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
++			     unsigned long va)
+ {
+ 	int sender;
+ 	union smp_flush_state *f;
++	cpumask_t cpumask = *cpumaskp;
+ 
+ 	/* Caller has disabled preemption */
+ 	sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+ 	f = &per_cpu(flush_state, sender);
+ 
+-	/* Could avoid this lock when
+-	   num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+-	   probably not worth checking this for a cache-hot lock. */
++	/*
++	 * Could avoid this lock when
++	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
++	 * probably not worth checking this for a cache-hot lock.
++	 */
+ 	spin_lock(&f->tlbstate_lock);
+ 
+ 	f->flush_mm = mm;
+@@ -206,14 +209,14 @@ static void flush_tlb_others(cpumask_t c
+ int __cpuinit init_smp_flush(void)
+ {
+ 	int i;
++
+ 	for_each_cpu_mask(i, cpu_possible_map) {
+ 		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
+ 	}
+ 	return 0;
+ }
+-
+ core_initcall(init_smp_flush);
+-	
++
+ void flush_tlb_current_task(void)
+ {
+ 	struct mm_struct *mm = current->mm;
+@@ -225,10 +228,9 @@ void flush_tlb_current_task(void)
+ 
+ 	local_flush_tlb();
+ 	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+ 	preempt_enable();
+ }
+-EXPORT_SYMBOL(flush_tlb_current_task);
+ 
+ void flush_tlb_mm (struct mm_struct * mm)
+ {
+@@ -245,11 +247,10 @@ void flush_tlb_mm (struct mm_struct * mm
+ 			leave_mm(smp_processor_id());
+ 	}
+ 	if (!cpus_empty(cpu_mask))
+-		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
++		flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
+ 
+ 	preempt_enable();
+ }
+-EXPORT_SYMBOL(flush_tlb_mm);
+ 
+ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+ {
+@@ -263,8 +264,8 @@ void flush_tlb_page(struct vm_area_struc
+ 	if (current->active_mm == mm) {
+ 		if(current->mm)
+ 			__flush_tlb_one(va);
+-		 else
+-		 	leave_mm(smp_processor_id());
++		else
++			leave_mm(smp_processor_id());
+ 	}
+ 
+ 	if (!cpus_empty(cpu_mask))
+@@ -272,7 +273,6 @@ void flush_tlb_page(struct vm_area_struc
+ 
+ 	preempt_enable();
+ }
+-EXPORT_SYMBOL(flush_tlb_page);
+ 
+ static void do_flush_tlb_all(void* info)
+ {
+@@ -330,11 +330,9 @@ void unlock_ipi_call_lock(void)
+  * this function sends a 'generic call function' IPI to all other CPU
+  * of the system defined in the mask.
+  */
+-
+-static int
+-__smp_call_function_mask(cpumask_t mask,
+-			 void (*func)(void *), void *info,
+-			 int wait)
++static int __smp_call_function_mask(cpumask_t mask,
++				    void (*func)(void *), void *info,
++				    int wait)
+ {
+ 	struct call_data_struct data;
+ 	cpumask_t allbutself;
+@@ -422,11 +420,10 @@ EXPORT_SYMBOL(smp_call_function_mask);
+  */
+ 
+ int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+-	int nonatomic, int wait)
++			      int nonatomic, int wait)
+ {
+ 	/* prevent preemption and reschedule on another processor */
+-	int ret;
+-	int me = get_cpu();
++	int ret, me = get_cpu();
+ 
+ 	/* Can deadlock when called with interrupts disabled */
+ 	WARN_ON(irqs_disabled());
+@@ -476,9 +473,9 @@ static void stop_this_cpu(void *dummy)
+ 	 */
+ 	cpu_clear(smp_processor_id(), cpu_online_map);
+ 	disable_all_local_evtchn();
+-	for (;;) 
++	for (;;)
+ 		halt();
+-} 
++}
+ 
+ void smp_send_stop(void)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:32:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:32:56.000000000 +0100
+@@ -28,21 +28,9 @@
+  *	serialize accesses to xtime/lost_ticks).
+  */
+ 
+-#include <linux/errno.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/param.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
++#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/time.h>
+-#include <linux/delay.h>
+-#include <linux/init.h>
+-#include <linux/smp.h>
+-#include <linux/module.h>
+-#include <linux/sysdev.h>
+-#include <linux/bcd.h>
+-#include <linux/efi.h>
+ #include <linux/mca.h>
+ #include <linux/sysctl.h>
+ #include <linux/percpu.h>
+@@ -50,26 +38,10 @@
+ #include <linux/posix-timers.h>
+ #include <linux/cpufreq.h>
+ #include <linux/clocksource.h>
++#include <linux/sysdev.h>
+ 
+-#include <asm/io.h>
+-#include <asm/smp.h>
+-#include <asm/irq.h>
+-#include <asm/msr.h>
+ #include <asm/delay.h>
+-#include <asm/mpspec.h>
+-#include <asm/uaccess.h>
+-#include <asm/processor.h>
+-#include <asm/timer.h>
+ #include <asm/time.h>
+-#include <asm/sections.h>
+-
+-#include "mach_time.h"
+-
+-#include <linux/timex.h>
+-
+-#include <asm/hpet.h>
+-
+-#include <asm/arch_hooks.h>
+ 
+ #include <xen/evtchn.h>
+ #include <xen/sysctl.h>
+@@ -89,9 +61,6 @@ volatile unsigned long __jiffies __secti
+ unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
+ EXPORT_SYMBOL(cpu_khz);
+ 
+-DEFINE_SPINLOCK(rtc_lock);
+-EXPORT_SYMBOL(rtc_lock);
+-
+ /* These are peridically updated in shared_info, and then copied here. */
+ struct shadow_time_info {
+ 	u64 tsc_timestamp;     /* TSC at last update of time vals.  */
+@@ -154,6 +123,11 @@ static int __init __independent_wallcloc
+ }
+ __setup("independent_wallclock", __independent_wallclock);
+ 
++int xen_independent_wallclock(void)
++{
++	return independent_wallclock;
++}
++
+ /* Permitted clock jitter, in nsecs, beyond which a warning will be printed. */
+ static unsigned long permitted_clock_jitter = 10000000UL; /* 10ms */
+ static int __init __permitted_clock_jitter(char *str)
+@@ -205,7 +179,6 @@ static inline u64 get64(volatile u64 *pt
+ 	return cmpxchg64(ptr, 0, 0);
+ #else
+ 	return *ptr;
+-#define cmpxchg64 cmpxchg
+ #endif
+ }
+ 
+@@ -215,7 +188,6 @@ static inline u64 get64_local(volatile u
+ 	return cmpxchg64_local(ptr, 0, 0);
+ #else
+ 	return *ptr;
+-#define cmpxchg64_local cmpxchg_local
+ #endif
+ }
+ 
+@@ -321,35 +293,6 @@ static inline int time_values_up_to_date
+ 	return (dst->version == src->version);
+ }
+ 
+-/*
+- * This is a special lock that is owned by the CPU and holds the index
+- * register we are working with.  It is required for NMI access to the
+- * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
+- */
+-volatile unsigned long cmos_lock = 0;
+-EXPORT_SYMBOL(cmos_lock);
+-
+-/* Routines for accessing the CMOS RAM/RTC. */
+-unsigned char rtc_cmos_read(unsigned char addr)
+-{
+-	unsigned char val;
+-	lock_cmos_prefix(addr);
+-	outb_p(addr, RTC_PORT(0));
+-	val = inb_p(RTC_PORT(1));
+-	lock_cmos_suffix(addr);
+-	return val;
+-}
+-EXPORT_SYMBOL(rtc_cmos_read);
+-
+-void rtc_cmos_write(unsigned char val, unsigned char addr)
+-{
+-	lock_cmos_prefix(addr);
+-	outb_p(addr, RTC_PORT(0));
+-	outb_p(val, RTC_PORT(1));
+-	lock_cmos_suffix(addr);
+-}
+-EXPORT_SYMBOL(rtc_cmos_write);
+-
+ static void sync_xen_wallclock(unsigned long dummy);
+ static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
+ static void sync_xen_wallclock(unsigned long dummy)
+@@ -358,7 +301,8 @@ static void sync_xen_wallclock(unsigned 
+ 	s64 nsec;
+ 	struct xen_platform_op op;
+ 
+-	if (!ntp_synced() || independent_wallclock || !is_initial_xendomain())
++	BUG_ON(!is_initial_xendomain());
++	if (!ntp_synced() || independent_wallclock)
+ 		return;
+ 
+ 	write_seqlock_irq(&xtime_lock);
+@@ -381,23 +325,6 @@ static void sync_xen_wallclock(unsigned 
+ 	mod_timer(&sync_xen_wallclock_timer, jiffies + 60*HZ);
+ }
+ 
+-static int set_rtc_mmss(unsigned long nowtime)
+-{
+-	int retval;
+-	unsigned long flags;
+-
+-	if (independent_wallclock || !is_initial_xendomain())
+-		return 0;
+-
+-	/* gets recalled with irq locally disabled */
+-	/* XXX - does irqsave resolve this? -johnstul */
+-	spin_lock_irqsave(&rtc_lock, flags);
+-	retval = set_wallclock(nowtime);
+-	spin_unlock_irqrestore(&rtc_lock, flags);
+-
+-	return retval;
+-}
+-
+ static unsigned long long local_clock(void)
+ {
+ 	unsigned int cpu = get_cpu();
+@@ -407,7 +334,7 @@ static unsigned long long local_clock(vo
+ 
+ 	do {
+ 		local_time_version = shadow->version;
+-		barrier();
++		rdtsc_barrier();
+ 		time = shadow->system_timestamp + get_nsec_offset(shadow);
+ 		if (!time_values_up_to_date(cpu))
+ 			get_time_values_from_xen(cpu);
+@@ -480,28 +407,24 @@ unsigned long profile_pc(struct pt_regs 
+ 
+ #if defined(CONFIG_SMP) || defined(__x86_64__)
+ # ifdef __i386__
+-	if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs)
++	if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->cs)
+ # else
+ 	if (!user_mode(regs)
+ # endif
+ 	    && in_lock_functions(pc)) {
+ # ifdef CONFIG_FRAME_POINTER
+-#  ifdef __i386__
+-		return ((unsigned long *)regs->ebp)[1];
+-#  else
+-		return ((unsigned long *)regs->rbp)[1];
+-#  endif
++		return ((unsigned long *)regs->bp)[1];
+ # else
+ #  ifdef __i386__
+-		unsigned long *sp = (unsigned long *)&regs->esp;
++		unsigned long *sp = (unsigned long *)&regs->sp;
+ #  else
+-		unsigned long *sp = (unsigned long *)regs->rsp;
++		unsigned long *sp = (unsigned long *)regs->sp;
+ #  endif
+ 
+ 		/* Return address is either directly at stack pointer
+-		   or above a saved eflags. Eflags has bits 22-31 zero,
++		   or above a saved flags. Eflags has bits 22-31 zero,
+ 		   kernel addresses don't. */
+- 		if (sp[0] >> 22)
++		if (sp[0] >> 22)
+ 			return sp[0];
+ 		if (sp[1] >> 22)
+ 			return sp[1];
+@@ -740,25 +663,32 @@ static void init_missing_ticks_accountin
+ 		runstate->time[RUNSTATE_offline];
+ }
+ 
+-/* not static: needed by APM */
+-unsigned long read_persistent_clock(void)
++unsigned long xen_read_persistent_clock(void)
+ {
+-	unsigned long retval;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&rtc_lock, flags);
++	const shared_info_t *s = HYPERVISOR_shared_info;
++	u32 version, sec, nsec;
++	u64 delta;
+ 
+-	retval = get_wallclock();
++	do {
++		version = s->wc_version;
++		rmb();
++		sec     = s->wc_sec;
++		nsec    = s->wc_nsec;
++		rmb();
++	} while ((s->wc_version & 1) | (version ^ s->wc_version));
+ 
+-	spin_unlock_irqrestore(&rtc_lock, flags);
++	delta = local_clock() + (u64)sec * NSEC_PER_SEC + nsec;
++	do_div(delta, NSEC_PER_SEC);
+ 
+-	return retval;
++	return delta;
+ }
+ 
+-int update_persistent_clock(struct timespec now)
++int xen_update_persistent_clock(void)
+ {
++	if (!is_initial_xendomain())
++		return -1;
+ 	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
+-	return set_rtc_mmss(now.tv_sec);
++	return 0;
+ }
+ 
+ extern void (*late_time_init)(void);
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -79,7 +79,8 @@ char ignore_fpu_irq = 0;
+  * F0 0F bug workaround.. We have a special link segment
+  * for this.
+  */
+-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
++gate_desc idt_table[256]
++	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
+ #endif
+ 
+ asmlinkage void divide_error(void);
+@@ -109,6 +110,34 @@ asmlinkage void machine_check(void);
+ int kstack_depth_to_print = 24;
+ static unsigned int code_bytes = 64;
+ 
++void printk_address(unsigned long address, int reliable)
++{
++#ifdef CONFIG_KALLSYMS
++	unsigned long offset = 0, symsize;
++	const char *symname;
++	char *modname;
++	char *delim = ":";
++	char namebuf[128];
++	char reliab[4] = "";
++
++	symname = kallsyms_lookup(address, &symsize, &offset,
++					&modname, namebuf);
++	if (!symname) {
++		printk(" [<%08lx>]\n", address);
++		return;
++	}
++	if (!reliable)
++		strcpy(reliab, "? ");
++
++	if (!modname)
++		modname = delim = "";
++	printk(" [<%08lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
++		address, reliab, delim, modname, delim, symname, offset, symsize);
++#else
++	printk(" [<%08lx>]\n", address);
++#endif
++}
++
+ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size)
+ {
+ 	return	p > (void *)tinfo &&
+@@ -122,48 +151,35 @@ struct stack_frame {
+ };
+ 
+ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+-				unsigned long *stack, unsigned long ebp,
++				unsigned long *stack, unsigned long bp,
+ 				const struct stacktrace_ops *ops, void *data)
+ {
+-#ifdef	CONFIG_FRAME_POINTER
+-	struct stack_frame *frame = (struct stack_frame *)ebp;
+-	while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) {
+-		struct stack_frame *next;
+-		unsigned long addr;
++	struct stack_frame *frame = (struct stack_frame *)bp;
+ 
+-		addr = frame->return_address;
+-		ops->address(data, addr);
+-		/*
+-		 * break out of recursive entries (such as
+-		 * end_of_stack_stop_unwind_function). Also,
+-		 * we can never allow a frame pointer to
+-		 * move downwards!
+-		 */
+-		next = frame->next_frame;
+-		if (next <= frame)
+-			break;
+-		frame = next;
+-	}
+-#else
+ 	while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) {
+ 		unsigned long addr;
+ 
+-		addr = *stack++;
+-		if (__kernel_text_address(addr))
+-			ops->address(data, addr);
++		addr = *stack;
++		if (__kernel_text_address(addr)) {
++			if ((unsigned long) stack == bp + 4) {
++				ops->address(data, addr, 1);
++				frame = frame->next_frame;
++				bp = (unsigned long) frame;
++			} else {
++				ops->address(data, addr, bp == 0);
++			}
++		}
++		stack++;
+ 	}
+-#endif
+-	return ebp;
++	return bp;
+ }
+ 
+ #define MSG(msg) ops->warning(data, msg)
+ 
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+-	        unsigned long *stack,
++		unsigned long *stack, unsigned long bp,
+ 		const struct stacktrace_ops *ops, void *data)
+ {
+-	unsigned long ebp = 0;
+-
+ 	if (!task)
+ 		task = current;
+ 
+@@ -171,17 +187,17 @@ void dump_trace(struct task_struct *task
+ 		unsigned long dummy;
+ 		stack = &dummy;
+ 		if (task != current)
+-			stack = (unsigned long *)task->thread.esp;
++			stack = (unsigned long *)task->thread.sp;
+ 	}
+ 
+ #ifdef CONFIG_FRAME_POINTER
+-	if (!ebp) {
++	if (!bp) {
+ 		if (task == current) {
+-			/* Grab ebp right from our regs */
+-			asm ("movl %%ebp, %0" : "=r" (ebp) : );
++			/* Grab bp right from our regs */
++			asm ("movl %%ebp, %0" : "=r" (bp) : );
+ 		} else {
+-			/* ebp is the last reg pushed by switch_to */
+-			ebp = *(unsigned long *) task->thread.esp;
++			/* bp is the last reg pushed by switch_to */
++			bp = *(unsigned long *) task->thread.sp;
+ 		}
+ 	}
+ #endif
+@@ -190,7 +206,7 @@ void dump_trace(struct task_struct *task
+ 		struct thread_info *context;
+ 		context = (struct thread_info *)
+ 			((unsigned long)stack & (~(THREAD_SIZE - 1)));
+-		ebp = print_context_stack(context, stack, ebp, ops, data);
++		bp = print_context_stack(context, stack, bp, ops, data);
+ 		/* Should be after the line below, but somewhere
+ 		   in early boot context comes out corrupted and we
+ 		   can't reference it -AK */
+@@ -225,9 +241,11 @@ static int print_trace_stack(void *data,
+ /*
+  * Print one address/symbol entries per line.
+  */
+-static void print_trace_address(void *data, unsigned long addr)
++static void print_trace_address(void *data, unsigned long addr, int reliable)
+ {
+ 	printk("%s [<%08lx>] ", (char *)data, addr);
++	if (!reliable)
++		printk("? ");
+ 	print_symbol("%s\n", addr);
+ 	touch_nmi_watchdog();
+ }
+@@ -241,32 +259,32 @@ static const struct stacktrace_ops print
+ 
+ static void
+ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		   unsigned long * stack, char *log_lvl)
++		unsigned long *stack, unsigned long bp, char *log_lvl)
+ {
+-	dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
++	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+ 	printk("%s =======================\n", log_lvl);
+ }
+ 
+ void show_trace(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long * stack)
++		unsigned long *stack, unsigned long bp)
+ {
+-	show_trace_log_lvl(task, regs, stack, "");
++	show_trace_log_lvl(task, regs, stack, bp, "");
+ }
+ 
+ static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-			       unsigned long *esp, char *log_lvl)
++		       unsigned long *sp, unsigned long bp, char *log_lvl)
+ {
+ 	unsigned long *stack;
+ 	int i;
+ 
+-	if (esp == NULL) {
++	if (sp == NULL) {
+ 		if (task)
+-			esp = (unsigned long*)task->thread.esp;
++			sp = (unsigned long*)task->thread.sp;
+ 		else
+-			esp = (unsigned long *)&esp;
++			sp = (unsigned long *)&sp;
+ 	}
+ 
+-	stack = esp;
++	stack = sp;
+ 	for(i = 0; i < kstack_depth_to_print; i++) {
+ 		if (kstack_end(stack))
+ 			break;
+@@ -275,13 +293,13 @@ static void show_stack_log_lvl(struct ta
+ 		printk("%08lx ", *stack++);
+ 	}
+ 	printk("\n%sCall Trace:\n", log_lvl);
+-	show_trace_log_lvl(task, regs, esp, log_lvl);
++	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+ }
+ 
+-void show_stack(struct task_struct *task, unsigned long *esp)
++void show_stack(struct task_struct *task, unsigned long *sp)
+ {
+ 	printk("       ");
+-	show_stack_log_lvl(task, NULL, esp, "");
++	show_stack_log_lvl(task, NULL, sp, 0, "");
+ }
+ 
+ /*
+@@ -290,13 +308,19 @@ void show_stack(struct task_struct *task
+ void dump_stack(void)
+ {
+ 	unsigned long stack;
++	unsigned long bp = 0;
++
++#ifdef CONFIG_FRAME_POINTER
++	if (!bp)
++		asm("movl %%ebp, %0" : "=r" (bp):);
++#endif
+ 
+ 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+ 		current->pid, current->comm, print_tainted(),
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
+-	show_trace(current, NULL, &stack);
++	show_trace(current, NULL, &stack, bp);
+ }
+ 
+ EXPORT_SYMBOL(dump_stack);
+@@ -315,30 +339,30 @@ void show_registers(struct pt_regs *regs
+ 	 * time of the fault..
+ 	 */
+ 	if (!user_mode_vm(regs)) {
+-		u8 *eip;
++		u8 *ip;
+ 		unsigned int code_prologue = code_bytes * 43 / 64;
+ 		unsigned int code_len = code_bytes;
+ 		unsigned char c;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+-		show_stack_log_lvl(NULL, regs, &regs->esp, KERN_EMERG);
++		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
+ 
+ 		printk(KERN_EMERG "Code: ");
+ 
+-		eip = (u8 *)regs->eip - code_prologue;
+-		if (eip < (u8 *)PAGE_OFFSET ||
+-			probe_kernel_address(eip, c)) {
++		ip = (u8 *)regs->ip - code_prologue;
++		if (ip < (u8 *)PAGE_OFFSET ||
++			probe_kernel_address(ip, c)) {
+ 			/* try starting at EIP */
+-			eip = (u8 *)regs->eip;
++			ip = (u8 *)regs->ip;
+ 			code_len = code_len - code_prologue + 1;
+ 		}
+-		for (i = 0; i < code_len; i++, eip++) {
+-			if (eip < (u8 *)PAGE_OFFSET ||
+-				probe_kernel_address(eip, c)) {
++		for (i = 0; i < code_len; i++, ip++) {
++			if (ip < (u8 *)PAGE_OFFSET ||
++				probe_kernel_address(ip, c)) {
+ 				printk(" Bad EIP value.");
+ 				break;
+ 			}
+-			if (eip == (u8 *)regs->eip)
++			if (ip == (u8 *)regs->ip)
+ 				printk("<%02x> ", c);
+ 			else
+ 				printk("%02x ", c);
+@@ -347,18 +371,57 @@ void show_registers(struct pt_regs *regs
+ 	printk("\n");
+ }	
+ 
+-int is_valid_bugaddr(unsigned long eip)
++int is_valid_bugaddr(unsigned long ip)
+ {
+ 	unsigned short ud2;
+ 
+-	if (eip < PAGE_OFFSET)
++	if (ip < PAGE_OFFSET)
+ 		return 0;
+-	if (probe_kernel_address((unsigned short *)eip, ud2))
++	if (probe_kernel_address((unsigned short *)ip, ud2))
+ 		return 0;
+ 
+ 	return ud2 == 0x0b0f;
+ }
+ 
++static int die_counter;
++
++int __kprobes __die(const char * str, struct pt_regs * regs, long err)
++{
++	unsigned long sp;
++	unsigned short ss;
++
++	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
++#ifdef CONFIG_PREEMPT
++	printk("PREEMPT ");
++#endif
++#ifdef CONFIG_SMP
++	printk("SMP ");
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	printk("DEBUG_PAGEALLOC");
++#endif
++	printk("\n");
++
++	if (notify_die(DIE_OOPS, str, regs, err,
++				current->thread.trap_no, SIGSEGV) !=
++			NOTIFY_STOP) {
++		show_registers(regs);
++		/* Executive summary in case the oops scrolled away */
++		sp = (unsigned long) (&regs->sp);
++		savesegment(ss, ss);
++		if (user_mode(regs)) {
++			sp = regs->sp;
++			ss = regs->ss & 0xffff;
++		}
++		printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
++		print_symbol("%s", regs->ip);
++		printk(" SS:ESP %04x:%08lx\n", ss, sp);
++		return 0;
++	} else {
++		return 1;
++	}
++}
++
+ /*
+  * This is gone through when something in the kernel has done something bad and
+  * is about to be terminated.
+@@ -374,7 +437,6 @@ void die(const char * str, struct pt_reg
+ 		.lock_owner =		-1,
+ 		.lock_owner_depth =	0
+ 	};
+-	static int die_counter;
+ 	unsigned long flags;
+ 
+ 	oops_enter();
+@@ -390,43 +452,13 @@ void die(const char * str, struct pt_reg
+ 		raw_local_irq_save(flags);
+ 
+ 	if (++die.lock_owner_depth < 3) {
+-		unsigned long esp;
+-		unsigned short ss;
+-
+-		report_bug(regs->eip, regs);
+-
+-		printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff,
+-		       ++die_counter);
+-#ifdef CONFIG_PREEMPT
+-		printk("PREEMPT ");
+-#endif
+-#ifdef CONFIG_SMP
+-		printk("SMP ");
+-#endif
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-		printk("DEBUG_PAGEALLOC");
+-#endif
+-		printk("\n");
++		report_bug(regs->ip, regs);
+ 
+-		if (notify_die(DIE_OOPS, str, regs, err,
+-					current->thread.trap_no, SIGSEGV) !=
+-				NOTIFY_STOP) {
+-			show_registers(regs);
+-			/* Executive summary in case the oops scrolled away */
+-			esp = (unsigned long) (&regs->esp);
+-			savesegment(ss, ss);
+-			if (user_mode(regs)) {
+-				esp = regs->esp;
+-				ss = regs->xss & 0xffff;
+-			}
+-			printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+-			print_symbol("%s", regs->eip);
+-			printk(" SS:ESP %04x:%08lx\n", ss, esp);
+-		}
+-		else
++		if (__die(str, regs, err))
+ 			regs = NULL;
+-  	} else
++	} else {
+ 		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
++	}
+ 
+ 	bust_spinlocks(0);
+ 	die.lock_owner = -1;
+@@ -462,7 +494,7 @@ static void __kprobes do_trap(int trapnr
+ {
+ 	struct task_struct *tsk = current;
+ 
+-	if (regs->eflags & VM_MASK) {
++	if (regs->flags & VM_MASK) {
+ 		if (vm86)
+ 			goto vm86_trap;
+ 		goto trap_signal;
+@@ -508,7 +540,7 @@ static void __kprobes do_trap(int trapnr
+ }
+ 
+ #define DO_ERROR(trapnr, signr, str, name) \
+-fastcall void do_##name(struct pt_regs * regs, long error_code) \
++void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+ 						== NOTIFY_STOP) \
+@@ -517,7 +549,7 @@ fastcall void do_##name(struct pt_regs *
+ }
+ 
+ #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \
+-fastcall void do_##name(struct pt_regs * regs, long error_code) \
++void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ 	siginfo_t info; \
+ 	if (irq) \
+@@ -533,7 +565,7 @@ fastcall void do_##name(struct pt_regs *
+ }
+ 
+ #define DO_VM86_ERROR(trapnr, signr, str, name) \
+-fastcall void do_##name(struct pt_regs * regs, long error_code) \
++void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+ 						== NOTIFY_STOP) \
+@@ -542,7 +574,7 @@ fastcall void do_##name(struct pt_regs *
+ }
+ 
+ #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+-fastcall void do_##name(struct pt_regs * regs, long error_code) \
++void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ 	siginfo_t info; \
+ 	info.si_signo = signr; \
+@@ -556,13 +588,13 @@ fastcall void do_##name(struct pt_regs *
+ 	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
+ }
+ 
+-DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
++DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
+ #ifndef CONFIG_KPROBES
+ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+ #endif
+ DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0)
++DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
+@@ -570,10 +602,10 @@ DO_ERROR(12, SIGBUS,  "stack segment", s
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+ DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ 
+-fastcall void __kprobes do_general_protection(struct pt_regs * regs,
++void __kprobes do_general_protection(struct pt_regs * regs,
+ 					      long error_code)
+ {
+-	if (regs->eflags & VM_MASK)
++	if (regs->flags & VM_MASK)
+ 		goto gp_in_vm86;
+ 
+ 	if (!user_mode(regs))
+@@ -582,11 +614,14 @@ fastcall void __kprobes do_general_prote
+ 	current->thread.error_code = error_code;
+ 	current->thread.trap_no = 13;
+ 	if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) &&
+-	    printk_ratelimit())
++	    printk_ratelimit()) {
+ 		printk(KERN_INFO
+-		    "%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
++		    "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+ 		    current->comm, task_pid_nr(current),
+-		    regs->eip, regs->esp, error_code);
++		    regs->ip, regs->sp, error_code);
++		print_vma_addr(" in ", regs->ip);
++		printk("\n");
++	}
+ 
+ 	force_sig(SIGSEGV, current);
+ 	return;
+@@ -675,8 +710,8 @@ void __kprobes die_nmi(struct pt_regs *r
+ 	*/
+ 	bust_spinlocks(1);
+ 	printk(KERN_EMERG "%s", msg);
+-	printk(" on CPU%d, eip %08lx, registers:\n",
+-		smp_processor_id(), regs->eip);
++	printk(" on CPU%d, ip %08lx, registers:\n",
++		smp_processor_id(), regs->ip);
+ 	show_registers(regs);
+ 	console_silent();
+ 	spin_unlock(&nmi_print_lock);
+@@ -733,7 +768,7 @@ static __kprobes void default_do_nmi(str
+ 
+ static int ignore_nmis;
+ 
+-fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code)
++__kprobes void do_nmi(struct pt_regs * regs, long error_code)
+ {
+ 	int cpu;
+ 
+@@ -762,7 +797,7 @@ void restart_nmi(void)
+ }
+ 
+ #ifdef CONFIG_KPROBES
+-fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
++void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ {
+ 	trace_hardirqs_fixup();
+ 
+@@ -798,7 +833,7 @@ fastcall void __kprobes do_int3(struct p
+  * find every occurrence of the TF bit that could be saved away even
+  * by user code)
+  */
+-fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code)
++void __kprobes do_debug(struct pt_regs * regs, long error_code)
+ {
+ 	unsigned int condition;
+ 	struct task_struct *tsk = current;
+@@ -807,24 +842,30 @@ fastcall void __kprobes do_debug(struct 
+ 
+ 	get_debugreg(condition, 6);
+ 
++	/*
++	 * The processor cleared BTF, so don't mark that we need it set.
++	 */
++	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
++	tsk->thread.debugctlmsr = 0;
++
+ 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+ 					SIGTRAP) == NOTIFY_STOP)
+ 		return;
+ 	/* It's safe to allow irq's after DR6 has been saved */
+-	if (regs->eflags & X86_EFLAGS_IF)
++	if (regs->flags & X86_EFLAGS_IF)
+ 		local_irq_enable();
+ 
+ 	/* Mask out spurious debug traps due to lazy DR7 setting */
+ 	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+-		if (!tsk->thread.debugreg[7])
++		if (!tsk->thread.debugreg7)
+ 			goto clear_dr7;
+ 	}
+ 
+-	if (regs->eflags & VM_MASK)
++	if (regs->flags & VM_MASK)
+ 		goto debug_vm86;
+ 
+ 	/* Save debug status register where ptrace can see it */
+-	tsk->thread.debugreg[6] = condition;
++	tsk->thread.debugreg6 = condition;
+ 
+ 	/*
+ 	 * Single-stepping through TF: make sure we ignore any events in
+@@ -856,7 +897,7 @@ debug_vm86:
+ 
+ clear_TF_reenable:
+ 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->eflags &= ~TF_MASK;
++	regs->flags &= ~TF_MASK;
+ 	return;
+ }
+ 
+@@ -865,7 +906,7 @@ clear_TF_reenable:
+  * the correct behaviour even in the presence of the asynchronous
+  * IRQ13 behaviour
+  */
+-void math_error(void __user *eip)
++void math_error(void __user *ip)
+ {
+ 	struct task_struct * task;
+ 	siginfo_t info;
+@@ -881,7 +922,7 @@ void math_error(void __user *eip)
+ 	info.si_signo = SIGFPE;
+ 	info.si_errno = 0;
+ 	info.si_code = __SI_FAULT;
+-	info.si_addr = eip;
++	info.si_addr = ip;
+ 	/*
+ 	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ 	 * status.  0x3f is the exception bits in these regs, 0x200 is the
+@@ -924,13 +965,13 @@ void math_error(void __user *eip)
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code)
++void do_coprocessor_error(struct pt_regs * regs, long error_code)
+ {
+ 	ignore_fpu_irq = 1;
+-	math_error((void __user *)regs->eip);
++	math_error((void __user *)regs->ip);
+ }
+ 
+-static void simd_math_error(void __user *eip)
++static void simd_math_error(void __user *ip)
+ {
+ 	struct task_struct * task;
+ 	siginfo_t info;
+@@ -946,7 +987,7 @@ static void simd_math_error(void __user 
+ 	info.si_signo = SIGFPE;
+ 	info.si_errno = 0;
+ 	info.si_code = __SI_FAULT;
+-	info.si_addr = eip;
++	info.si_addr = ip;
+ 	/*
+ 	 * The SIMD FPU exceptions are handled a little differently, as there
+ 	 * is only a single status/control register.  Thus, to determine which
+@@ -978,19 +1019,19 @@ static void simd_math_error(void __user 
+ 	force_sig_info(SIGFPE, &info, task);
+ }
+ 
+-fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
++void do_simd_coprocessor_error(struct pt_regs * regs,
+ 					  long error_code)
+ {
+ 	if (cpu_has_xmm) {
+ 		/* Handle SIMD FPU exceptions on PIII+ processors. */
+ 		ignore_fpu_irq = 1;
+-		simd_math_error((void __user *)regs->eip);
++		simd_math_error((void __user *)regs->ip);
+ 	} else {
+ 		/*
+ 		 * Handle strange cache flush from user space exception
+ 		 * in all other cases.  This is undocumented behaviour.
+ 		 */
+-		if (regs->eflags & VM_MASK) {
++		if (regs->flags & VM_MASK) {
+ 			handle_vm86_fault((struct kernel_vm86_regs *)regs,
+ 					  error_code);
+ 			return;
+@@ -1003,7 +1044,7 @@ fastcall void do_simd_coprocessor_error(
+ }
+ 
+ #ifndef CONFIG_XEN
+-fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
++void do_spurious_interrupt_bug(struct pt_regs * regs,
+ 					  long error_code)
+ {
+ #if 0
+@@ -1012,7 +1053,7 @@ fastcall void do_spurious_interrupt_bug(
+ #endif
+ }
+ 
+-fastcall unsigned long patch_espfix_desc(unsigned long uesp,
++unsigned long patch_espfix_desc(unsigned long uesp,
+ 					  unsigned long kesp)
+ {
+ 	struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt;
+@@ -1072,7 +1113,7 @@ asmlinkage void math_emulate(long arg)
+  * 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 __cpuinitdata trap_table[] = {
++static const trap_info_t __cpuinitconst 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			},
+@@ -1105,17 +1146,12 @@ void __init trap_init(void)
+ 	if (ret)
+ 		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+ 
++	/*
++	 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
++	 * Generate a build-time error if the alignment is wrong.
++	 */
++	BUILD_BUG_ON(offsetof(struct task_struct, thread.i387.fxsave) & 15);
+ 	if (cpu_has_fxsr) {
+-		/*
+-		 * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+-		 * Generates a compile-time "error: zero width for bit-field" if
+-		 * the alignment is wrong.
+-		 */
+-		struct fxsrAlignAssert {
+-			int _:!(offsetof(struct task_struct,
+-					thread.i387.fxsave) & 15);
+-		};
+-
+ 		printk(KERN_INFO "Enabling fast FPU save and restore... ");
+ 		set_in_cr4(X86_CR4_OSFXSR);
+ 		printk("done.\n");
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -74,38 +74,41 @@ asmlinkage void alignment_check(void);
+ asmlinkage void machine_check(void);
+ asmlinkage void spurious_interrupt_bug(void);
+ 
++static unsigned int code_bytes = 64;
++
+ static inline void conditional_sti(struct pt_regs *regs)
+ {
+-	if (regs->eflags & X86_EFLAGS_IF)
++	if (regs->flags & X86_EFLAGS_IF)
+ 		local_irq_enable();
+ }
+ 
+ static inline void preempt_conditional_sti(struct pt_regs *regs)
+ {
+-	preempt_disable();
+-	if (regs->eflags & X86_EFLAGS_IF)
++	inc_preempt_count();
++	if (regs->flags & X86_EFLAGS_IF)
+ 		local_irq_enable();
+ }
+ 
+ static inline void preempt_conditional_cli(struct pt_regs *regs)
+ {
+-	if (regs->eflags & X86_EFLAGS_IF)
++	if (regs->flags & X86_EFLAGS_IF)
+ 		local_irq_disable();
+ 	/* Make sure to not schedule here because we could be running
+ 	   on an exception stack. */
+-	preempt_enable_no_resched();
++	dec_preempt_count();
+ }
+ 
+ int kstack_depth_to_print = 12;
+ 
+-#ifdef CONFIG_KALLSYMS
+-void printk_address(unsigned long address)
++void printk_address(unsigned long address, int reliable)
+ {
++#ifdef CONFIG_KALLSYMS
+ 	unsigned long offset = 0, symsize;
+ 	const char *symname;
+ 	char *modname;
+ 	char *delim = ":";
+-	char namebuf[128];
++	char namebuf[KSYM_NAME_LEN];
++	char reliab[4] = "";
+ 
+ 	symname = kallsyms_lookup(address, &symsize, &offset,
+ 					&modname, namebuf);
+@@ -113,17 +116,17 @@ void printk_address(unsigned long addres
+ 		printk(" [<%016lx>]\n", address);
+ 		return;
+ 	}
++	if (!reliable)
++		strcpy(reliab, "? ");
++
+ 	if (!modname)
+-		modname = delim = ""; 		
+-	printk(" [<%016lx>] %s%s%s%s+0x%lx/0x%lx\n",
+-		address, delim, modname, delim, symname, offset, symsize);
+-}
++		modname = delim = "";
++	printk(" [<%016lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
++		address, reliab, delim, modname, delim, symname, offset, symsize);
+ #else
+-void printk_address(unsigned long address)
+-{
+ 	printk(" [<%016lx>]\n", address);
+-}
+ #endif
++}
+ 
+ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+ 					unsigned *usedp, char **idp)
+@@ -210,14 +213,53 @@ static unsigned long *in_exception_stack
+  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+  */
+ 
+-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
++static inline int valid_stack_ptr(struct thread_info *tinfo,
++			void *p, unsigned int size, void *end)
+ {
+-	void *t = (void *)tinfo;
+-        return p > t && p < t + THREAD_SIZE - 3;
++	void *t = tinfo;
++	if (end) {
++		if (p < end && p >= (end-THREAD_SIZE))
++			return 1;
++		else
++			return 0;
++	}
++	return p > t && p < t + THREAD_SIZE - size;
++}
++
++/* The form of the top of the frame on the stack */
++struct stack_frame {
++	struct stack_frame *next_frame;
++	unsigned long return_address;
++};
++
++
++static inline unsigned long print_context_stack(struct thread_info *tinfo,
++				unsigned long *stack, unsigned long bp,
++				const struct stacktrace_ops *ops, void *data,
++				unsigned long *end)
++{
++	struct stack_frame *frame = (struct stack_frame *)bp;
++
++	while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
++		unsigned long addr;
++
++		addr = *stack;
++		if (__kernel_text_address(addr)) {
++			if ((unsigned long) stack == bp + 8) {
++				ops->address(data, addr, 1);
++				frame = frame->next_frame;
++				bp = (unsigned long) frame;
++			} else {
++				ops->address(data, addr, bp == 0);
++			}
++		}
++		stack++;
++	}
++	return bp;
+ }
+ 
+ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+-		unsigned long *stack,
++		unsigned long *stack, unsigned long bp,
+ 		const struct stacktrace_ops *ops, void *data)
+ {
+ 	const unsigned cpu = get_cpu();
+@@ -227,36 +269,28 @@ void dump_trace(struct task_struct *tsk,
+ 
+ 	if (!tsk)
+ 		tsk = current;
++	tinfo = task_thread_info(tsk);
+ 
+ 	if (!stack) {
+ 		unsigned long dummy;
+ 		stack = &dummy;
+ 		if (tsk && tsk != current)
+-			stack = (unsigned long *)tsk->thread.rsp;
++			stack = (unsigned long *)tsk->thread.sp;
+ 	}
+ 
+-	/*
+-	 * Print function call entries within a stack. 'cond' is the
+-	 * "end of stackframe" condition, that the 'stack++'
+-	 * iteration will eventually trigger.
+-	 */
+-#define HANDLE_STACK(cond) \
+-	do while (cond) { \
+-		unsigned long addr = *stack++; \
+-		/* Use unlocked access here because except for NMIs	\
+-		   we should be already protected against module unloads */ \
+-		if (__kernel_text_address(addr)) { \
+-			/* \
+-			 * If the address is either in the text segment of the \
+-			 * kernel, or in the region which contains vmalloc'ed \
+-			 * memory, it *may* be the address of a calling \
+-			 * routine; if so, print it so that someone tracing \
+-			 * down the cause of the crash will be able to figure \
+-			 * out the call path that was taken. \
+-			 */ \
+-			ops->address(data, addr);   \
+-		} \
+-	} while (0)
++#ifdef CONFIG_FRAME_POINTER
++	if (!bp) {
++		if (tsk == current) {
++			/* Grab bp right from our regs */
++			asm("movq %%rbp, %0" : "=r" (bp):);
++		} else {
++			/* bp is the last reg pushed by switch_to */
++			bp = *(unsigned long *) tsk->thread.sp;
++		}
++	}
++#endif
++
++
+ 
+ 	/*
+ 	 * Print function call entries in all stacks, starting at the
+@@ -272,7 +306,9 @@ void dump_trace(struct task_struct *tsk,
+ 		if (estack_end) {
+ 			if (ops->stack(data, id) < 0)
+ 				break;
+-			HANDLE_STACK (stack < estack_end);
++
++			bp = print_context_stack(tinfo, stack, bp, ops,
++							data, estack_end);
+ 			ops->stack(data, "<EOE>");
+ 			/*
+ 			 * We link to the next stack via the
+@@ -290,7 +326,8 @@ void dump_trace(struct task_struct *tsk,
+ 			if (stack >= irqstack && stack < irqstack_end) {
+ 				if (ops->stack(data, "IRQ") < 0)
+ 					break;
+-				HANDLE_STACK (stack < irqstack_end);
++				bp = print_context_stack(tinfo, stack, bp,
++						ops, data, irqstack_end);
+ 				/*
+ 				 * We link to the next stack (which would be
+ 				 * the process stack normally) the last
+@@ -308,9 +345,7 @@ void dump_trace(struct task_struct *tsk,
+ 	/*
+ 	 * This handles the process stack:
+ 	 */
+-	tinfo = task_thread_info(tsk);
+-	HANDLE_STACK (valid_stack_ptr(tinfo, stack));
+-#undef HANDLE_STACK
++	bp = print_context_stack(tinfo, stack, bp, ops, data, NULL);
+ 	put_cpu();
+ }
+ EXPORT_SYMBOL(dump_trace);
+@@ -333,10 +368,10 @@ static int print_trace_stack(void *data,
+ 	return 0;
+ }
+ 
+-static void print_trace_address(void *data, unsigned long addr)
++static void print_trace_address(void *data, unsigned long addr, int reliable)
+ {
+ 	touch_nmi_watchdog();
+-	printk_address(addr);
++	printk_address(addr, reliable);
+ }
+ 
+ static const struct stacktrace_ops print_trace_ops = {
+@@ -347,15 +382,17 @@ static const struct stacktrace_ops print
+ };
+ 
+ void
+-show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack)
++show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
++		unsigned long bp)
+ {
+ 	printk("\nCall Trace:\n");
+-	dump_trace(tsk, regs, stack, &print_trace_ops, NULL);
++	dump_trace(tsk, regs, stack, bp, &print_trace_ops, NULL);
+ 	printk("\n");
+ }
+ 
+ static void
+-_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *rsp)
++_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *sp,
++							unsigned long bp)
+ {
+ 	unsigned long *stack;
+ 	int i;
+@@ -366,14 +403,14 @@ _show_stack(struct task_struct *tsk, str
+ 	// debugging aid: "show_stack(NULL, NULL);" prints the
+ 	// back trace for this cpu.
+ 
+-	if (rsp == NULL) {
++	if (sp == NULL) {
+ 		if (tsk)
+-			rsp = (unsigned long *)tsk->thread.rsp;
++			sp = (unsigned long *)tsk->thread.sp;
+ 		else
+-			rsp = (unsigned long *)&rsp;
++			sp = (unsigned long *)&sp;
+ 	}
+ 
+-	stack = rsp;
++	stack = sp;
+ 	for(i=0; i < kstack_depth_to_print; i++) {
+ 		if (stack >= irqstack && stack <= irqstack_end) {
+ 			if (stack == irqstack_end) {
+@@ -389,12 +426,12 @@ _show_stack(struct task_struct *tsk, str
+ 		printk(" %016lx", *stack++);
+ 		touch_nmi_watchdog();
+ 	}
+-	show_trace(tsk, regs, rsp);
++	show_trace(tsk, regs, sp, bp);
+ }
+ 
+-void show_stack(struct task_struct *tsk, unsigned long * rsp)
++void show_stack(struct task_struct *tsk, unsigned long * sp)
+ {
+-	_show_stack(tsk, NULL, rsp);
++	_show_stack(tsk, NULL, sp, 0);
+ }
+ 
+ /*
+@@ -403,13 +440,19 @@ void show_stack(struct task_struct *tsk,
+ void dump_stack(void)
+ {
+ 	unsigned long dummy;
++	unsigned long bp = 0;
++
++#ifdef CONFIG_FRAME_POINTER
++	if (!bp)
++		asm("movq %%rbp, %0" : "=r" (bp):);
++#endif
+ 
+ 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+ 		current->pid, current->comm, print_tainted(),
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
+-	show_trace(NULL, NULL, &dummy);
++	show_trace(NULL, NULL, &dummy, bp);
+ }
+ 
+ EXPORT_SYMBOL(dump_stack);
+@@ -417,12 +460,15 @@ EXPORT_SYMBOL(dump_stack);
+ void show_registers(struct pt_regs *regs)
+ {
+ 	int i;
+-	int in_kernel = !user_mode(regs);
+-	unsigned long rsp;
++	unsigned long sp;
+ 	const int cpu = smp_processor_id();
+ 	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
++	u8 *ip;
++	unsigned int code_prologue = code_bytes * 43 / 64;
++	unsigned int code_len = code_bytes;
+ 
+-	rsp = regs->rsp;
++	sp = regs->sp;
++	ip = (u8 *) regs->ip - code_prologue;
+ 	printk("CPU %d ", cpu);
+ 	__show_regs(regs);
+ 	printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
+@@ -432,45 +478,43 @@ void show_registers(struct pt_regs *regs
+ 	 * When in-kernel, we also print out the stack and code at the
+ 	 * time of the fault..
+ 	 */
+-	if (in_kernel) {
++	if (!user_mode(regs)) {
++		unsigned char c;
+ 		printk("Stack: ");
+-		_show_stack(NULL, regs, (unsigned long*)rsp);
++		_show_stack(NULL, regs, (unsigned long *)sp, regs->bp);
++		printk("\n");
+ 
+-		printk("\nCode: ");
+-		if (regs->rip < PAGE_OFFSET)
+-			goto bad;
+-
+-		for (i=0; i<20; i++) {
+-			unsigned char c;
+-			if (__get_user(c, &((unsigned char*)regs->rip)[i])) {
+-bad:
++		printk(KERN_EMERG "Code: ");
++		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
++			/* try starting at RIP */
++			ip = (u8 *) regs->ip;
++			code_len = code_len - code_prologue + 1;
++		}
++		for (i = 0; i < code_len; i++, ip++) {
++			if (ip < (u8 *)PAGE_OFFSET ||
++					probe_kernel_address(ip, c)) {
+ 				printk(" Bad RIP value.");
+ 				break;
+ 			}
+-			printk("%02x ", c);
++			if (ip == (u8 *)regs->ip)
++				printk("<%02x> ", c);
++			else
++				printk("%02x ", c);
+ 		}
+ 	}
+ 	printk("\n");
+ }	
+ 
+-int is_valid_bugaddr(unsigned long rip)
++int is_valid_bugaddr(unsigned long ip)
+ {
+ 	unsigned short ud2;
+ 
+-	if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2)))
++	if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
+ 		return 0;
+ 
+ 	return ud2 == 0x0b0f;
+ }
+ 
+-#ifdef CONFIG_BUG
+-void out_of_line_bug(void)
+-{ 
+-	BUG(); 
+-} 
+-EXPORT_SYMBOL(out_of_line_bug);
+-#endif
+-
+ static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+ static int die_owner = -1;
+ static unsigned int die_nest_count;
+@@ -498,7 +542,7 @@ unsigned __kprobes long oops_begin(void)
+ 	return flags;
+ }
+ 
+-void __kprobes oops_end(unsigned long flags)
++void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+ { 
+ 	die_owner = -1;
+ 	bust_spinlocks(0);
+@@ -507,12 +551,17 @@ void __kprobes oops_end(unsigned long fl
+ 		/* Nest count reaches zero, release the lock. */
+ 		__raw_spin_unlock(&die_lock);
+ 	raw_local_irq_restore(flags);
++	if (!regs) {
++		oops_exit();
++		return;
++	}
+ 	if (panic_on_oops)
+ 		panic("Fatal exception");
+ 	oops_exit();
++	do_exit(signr);
+ }
+ 
+-void __kprobes __die(const char * str, struct pt_regs * regs, long err)
++int __kprobes __die(const char * str, struct pt_regs * regs, long err)
+ {
+ 	static int die_counter;
+ 	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
+@@ -526,15 +575,17 @@ void __kprobes __die(const char * str, s
+ 	printk("DEBUG_PAGEALLOC");
+ #endif
+ 	printk("\n");
+-	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
++	if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
++		return 1;
+ 	show_registers(regs);
+ 	add_taint(TAINT_DIE);
+ 	/* Executive summary in case the oops scrolled away */
+ 	printk(KERN_ALERT "RIP ");
+-	printk_address(regs->rip); 
+-	printk(" RSP <%016lx>\n", regs->rsp); 
++	printk_address(regs->ip, 1);
++	printk(" RSP <%016lx>\n", regs->sp);
+ 	if (kexec_should_crash(current))
+ 		crash_kexec(regs);
++	return 0;
+ }
+ 
+ void die(const char * str, struct pt_regs * regs, long err)
+@@ -542,11 +593,11 @@ void die(const char * str, struct pt_reg
+ 	unsigned long flags = oops_begin();
+ 
+ 	if (!user_mode(regs))
+-		report_bug(regs->rip, regs);
++		report_bug(regs->ip, regs);
+ 
+-	__die(str, regs, err);
+-	oops_end(flags);
+-	do_exit(SIGSEGV); 
++	if (__die(str, regs, err))
++		regs = NULL;
++	oops_end(flags, regs, SIGSEGV);
+ }
+ 
+ #if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_SYSCTL)
+@@ -564,10 +615,10 @@ void __kprobes die_nmi(char *str, struct
+ 		crash_kexec(regs);
+ 	if (do_panic || panic_on_oops)
+ 		panic("Non maskable interrupt");
+-	oops_end(flags);
++	oops_end(flags, NULL, SIGBUS);
+ 	nmi_exit();
+ 	local_irq_enable();
+-	do_exit(SIGSEGV);
++	do_exit(SIGBUS);
+ }
+ #endif
+ 
+@@ -592,11 +643,14 @@ static void __kprobes do_trap(int trapnr
+ 		tsk->thread.trap_no = trapnr;
+ 
+ 		if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+-		    printk_ratelimit())
++		    printk_ratelimit()) {
+ 			printk(KERN_INFO
+-			       "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
++			       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+ 			       tsk->comm, tsk->pid, str,
+-			       regs->rip, regs->rsp, error_code); 
++			       regs->ip, regs->sp, error_code);
++			print_vma_addr(" in ", regs->ip);
++			printk("\n");
++		}
+ 
+ 		if (info)
+ 			force_sig_info(signr, info, tsk);
+@@ -606,19 +660,12 @@ static void __kprobes do_trap(int trapnr
+ 	}
+ 
+ 
+-	/* kernel trap */ 
+-	{	     
+-		const struct exception_table_entry *fixup;
+-		fixup = search_exception_tables(regs->rip);
+-		if (fixup)
+-			regs->rip = fixup->fixup;
+-		else {
+-			tsk->thread.error_code = error_code;
+-			tsk->thread.trap_no = trapnr;
+-			die(str, regs, error_code);
+-		}
+-		return;
++	if (!fixup_exception(regs)) {
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++		die(str, regs, error_code);
+ 	}
++	return;
+ }
+ 
+ #define DO_ERROR(trapnr, signr, str, name) \
+@@ -647,10 +694,10 @@ asmlinkage void do_##name(struct pt_regs
+ 	do_trap(trapnr, signr, str, regs, error_code, &info); \
+ }
+ 
+-DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->rip)
++DO_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->ip)
+ DO_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_ERROR( 5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->rip)
++DO_ERROR_INFO( 6, SIGILL,  "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
+ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
+ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+@@ -698,32 +745,28 @@ asmlinkage void __kprobes do_general_pro
+ 		tsk->thread.trap_no = 13;
+ 
+ 		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-		    printk_ratelimit())
++		    printk_ratelimit()) {
+ 			printk(KERN_INFO
+-		       "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
++		       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+ 			       tsk->comm, tsk->pid,
+-			       regs->rip, regs->rsp, error_code); 
++			       regs->ip, regs->sp, error_code);
++			print_vma_addr(" in ", regs->ip);
++			printk("\n");
++		}
+ 
+ 		force_sig(SIGSEGV, tsk);
+ 		return;
+ 	} 
+ 
+-	/* kernel gp */
+-	{
+-		const struct exception_table_entry *fixup;
+-		fixup = search_exception_tables(regs->rip);
+-		if (fixup) {
+-			regs->rip = fixup->fixup;
+-			return;
+-		}
++	if (fixup_exception(regs))
++		return;
+ 
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = 13;
+-		if (notify_die(DIE_GPF, "general protection fault", regs,
+-					error_code, 13, SIGSEGV) == NOTIFY_STOP)
+-			return;
+-		die("general protection fault", regs, error_code);
+-	}
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
++	if (notify_die(DIE_GPF, "general protection fault", regs,
++				error_code, 13, SIGSEGV) == NOTIFY_STOP)
++		return;
++	die("general protection fault", regs, error_code);
+ }
+ 
+ static __kprobes void
+@@ -833,15 +876,15 @@ asmlinkage __kprobes struct pt_regs *syn
+ {
+ 	struct pt_regs *regs = eregs;
+ 	/* Did already sync */
+-	if (eregs == (struct pt_regs *)eregs->rsp)
++	if (eregs == (struct pt_regs *)eregs->sp)
+ 		;
+ 	/* Exception from user space */
+ 	else if (user_mode(eregs))
+ 		regs = task_pt_regs(current);
+ 	/* Exception from kernel and interrupts are enabled. Move to
+  	   kernel process stack. */
+-	else if (eregs->eflags & X86_EFLAGS_IF)
+-		regs = (struct pt_regs *)(eregs->rsp -= sizeof(struct pt_regs));
++	else if (eregs->flags & X86_EFLAGS_IF)
++		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
+ 	if (eregs != regs)
+ 		*regs = *eregs;
+ 	return regs;
+@@ -859,6 +902,12 @@ asmlinkage void __kprobes do_debug(struc
+ 
+ 	get_debugreg(condition, 6);
+ 
++	/*
++	 * The processor cleared BTF, so don't mark that we need it set.
++	 */
++	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
++	tsk->thread.debugctlmsr = 0;
++
+ 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+ 						SIGTRAP) == NOTIFY_STOP)
+ 		return;
+@@ -874,27 +923,14 @@ asmlinkage void __kprobes do_debug(struc
+ 
+ 	tsk->thread.debugreg6 = condition;
+ 
+-	/* Mask out spurious TF errors due to lazy TF clearing */
++
++	/*
++	 * Single-stepping through TF: make sure we ignore any events in
++	 * kernel space (but re-enable TF when returning to user mode).
++	 */
+ 	if (condition & DR_STEP) {
+-		/*
+-		 * The TF error should be masked out only if the current
+-		 * process is not traced and if the TRAP flag has been set
+-		 * previously by a tracing process (condition detected by
+-		 * the PT_DTRACE flag); remember that the i386 TRAP flag
+-		 * can be modified by the process itself in user mode,
+-		 * allowing programs to debug themselves without the ptrace()
+-		 * interface.
+-		 */
+                 if (!user_mode(regs))
+                        goto clear_TF_reenable;
+-		/*
+-		 * Was the TF flag set by a debugger? If so, clear it now,
+-		 * so that register information is correct.
+-		 */
+-		if (tsk->ptrace & PT_DTRACE) {
+-			regs->eflags &= ~TF_MASK;
+-			tsk->ptrace &= ~PT_DTRACE;
+-		}
+ 	}
+ 
+ 	/* Ok, finally something we can handle */
+@@ -903,7 +939,7 @@ asmlinkage void __kprobes do_debug(struc
+ 	info.si_signo = SIGTRAP;
+ 	info.si_errno = 0;
+ 	info.si_code = TRAP_BRKPT;
+-	info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL;
++	info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
+ 	force_sig_info(SIGTRAP, &info, tsk);
+ 
+ clear_dr7:
+@@ -913,18 +949,15 @@ clear_dr7:
+ 
+ clear_TF_reenable:
+ 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->eflags &= ~TF_MASK;
++	regs->flags &= ~X86_EFLAGS_TF;
+ 	preempt_conditional_cli(regs);
+ }
+ 
+ static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
+ {
+-	const struct exception_table_entry *fixup;
+-	fixup = search_exception_tables(regs->rip);
+-	if (fixup) {
+-		regs->rip = fixup->fixup;
++	if (fixup_exception(regs))
+ 		return 1;
+-	}
++
+ 	notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
+ 	/* Illegal floating point operation in the kernel */
+ 	current->thread.trap_no = trapnr;
+@@ -939,7 +972,7 @@ static int kernel_math_error(struct pt_r
+  */
+ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
+ {
+-	void __user *rip = (void __user *)(regs->rip);
++	void __user *ip = (void __user *)(regs->ip);
+ 	struct task_struct * task;
+ 	siginfo_t info;
+ 	unsigned short cwd, swd;
+@@ -959,7 +992,7 @@ asmlinkage void do_coprocessor_error(str
+ 	info.si_signo = SIGFPE;
+ 	info.si_errno = 0;
+ 	info.si_code = __SI_FAULT;
+-	info.si_addr = rip;
++	info.si_addr = ip;
+ 	/*
+ 	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ 	 * status.  0x3f is the exception bits in these regs, 0x200 is the
+@@ -1008,7 +1041,7 @@ asmlinkage void bad_intr(void)
+ 
+ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
+ {
+-	void __user *rip = (void __user *)(regs->rip);
++	void __user *ip = (void __user *)(regs->ip);
+ 	struct task_struct * task;
+ 	siginfo_t info;
+ 	unsigned short mxcsr;
+@@ -1028,7 +1061,7 @@ asmlinkage void do_simd_coprocessor_erro
+ 	info.si_signo = SIGFPE;
+ 	info.si_errno = 0;
+ 	info.si_code = __SI_FAULT;
+-	info.si_addr = rip;
++	info.si_addr = ip;
+ 	/*
+ 	 * The SIMD FPU exceptions are handled a little differently, as there
+ 	 * is only a single status/control register.  Thus, to determine which
+@@ -1092,13 +1125,14 @@ asmlinkage void math_state_restore(void)
+ 	task_thread_info(me)->status |= TS_USEDFPU;
+ 	me->fpu_counter++;
+ }
++EXPORT_SYMBOL_GPL(math_state_restore);
+ 
+ 
+ /*
+  * 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 __cpuinitdata trap_table[] = {
++static const trap_info_t __cpuinitconst 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                       },
+@@ -1169,3 +1203,14 @@ static int __init kstack_setup(char *s)
+ 	return 0;
+ }
+ early_param("kstack", kstack_setup);
++
++
++static int __init code_bytes_setup(char *s)
++{
++	code_bytes = simple_strtoul(s, NULL, 0);
++	if (code_bytes > 8192)
++		code_bytes = 8192;
++
++	return 1;
++}
++__setup("code_bytes=", code_bytes_setup);
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -43,12 +43,7 @@
+ #include <asm/vgtod.h>
+ 
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+-#define __syscall_clobber "r11","rcx","memory"
+-#define __pa_vsymbol(x)			\
+-	({unsigned long v;  		\
+-	extern char __vsyscall_0; 	\
+-	  asm("" : "=r" (v) : "0" (x)); \
+-	  ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); })
++#define __syscall_clobber "r11","cx","memory"
+ 
+ /*
+  * vsyscall_gtod_data contains data that is :
+@@ -102,7 +97,7 @@ static __always_inline void do_get_tz(st
+ static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ 	int ret;
+-	asm volatile("vsysc2: syscall"
++	asm volatile("syscall"
+ 		: "=a" (ret)
+ 		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
+ 		: __syscall_clobber );
+@@ -112,7 +107,7 @@ static __always_inline int gettimeofday(
+ static __always_inline long time_syscall(long *t)
+ {
+ 	long secs;
+-	asm volatile("vsysc1: syscall"
++	asm volatile("syscall"
+ 		: "=a" (secs)
+ 		: "0" (__NR_time),"D" (t) : __syscall_clobber);
+ 	return secs;
+@@ -190,7 +185,7 @@ time_t __vsyscall(1) vtime(time_t *t)
+ long __vsyscall(2)
+ vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+ {
+-	unsigned int dummy, p;
++	unsigned int p;
+ 	unsigned long j = 0;
+ 
+ 	/* Fast cache - only recompute value once per jiffies and avoid
+@@ -205,7 +200,7 @@ vgetcpu(unsigned *cpu, unsigned *node, s
+ 		p = tcache->blob[1];
+ 	} else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+ 		/* Load per CPU data from RDTSCP */
+-		rdtscp(dummy, dummy, p);
++		native_read_tscp(&p);
+ 	} else {
+ 		/* Load per CPU data from GDT */
+ 		asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+@@ -228,42 +223,11 @@ long __vsyscall(3) venosys_1(void)
+ 
+ #ifdef CONFIG_SYSCTL
+ 
+-#define SYSCALL 0x050f
+-#define NOP2    0x9090
+-
+-/*
+- * NOP out syscall in vsyscall page when not needed.
+- */
+-static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
+-                        void __user *buffer, size_t *lenp, loff_t *ppos)
++static int
++vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
++		       void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+-	extern u16 vsysc1, vsysc2;
+-	u16 __iomem *map1;
+-	u16 __iomem *map2;
+-	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+-	if (!write)
+-		return ret;
+-	/* gcc has some trouble with __va(__pa()), so just do it this
+-	   way. */
+-	map1 = ioremap(__pa_vsymbol(&vsysc1), 2);
+-	if (!map1)
+-		return -ENOMEM;
+-	map2 = ioremap(__pa_vsymbol(&vsysc2), 2);
+-	if (!map2) {
+-		ret = -ENOMEM;
+-		goto out;
+-	}
+-	if (!vsyscall_gtod_data.sysctl_enabled) {
+-		writew(SYSCALL, map1);
+-		writew(SYSCALL, map2);
+-	} else {
+-		writew(NOP2, map1);
+-		writew(NOP2, map2);
+-	}
+-	iounmap(map2);
+-out:
+-	iounmap(map1);
+-	return ret;
++	return proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+ }
+ 
+ static ctl_table kernel_table2[] = {
+@@ -279,7 +243,6 @@ static ctl_table kernel_root_table2[] = 
+ 	  .child = kernel_table2 },
+ 	{}
+ };
+-
+ #endif
+ 
+ /* Assume __initcall executes before all user space. Hopefully kmod
+@@ -301,7 +264,7 @@ static void __cpuinit vsyscall_set_cpu(i
+ 	d |= cpu;
+ 	d |= (node & 0xf) << 12;
+ 	d |= (node >> 4) << 48;
+-	if (HYPERVISOR_update_descriptor(virt_to_machine(cpu_gdt(cpu)
++	if (HYPERVISOR_update_descriptor(virt_to_machine(get_cpu_gdt_table(cpu)
+ 							 + GDT_ENTRY_PER_CPU),
+ 					 d))
+ 		BUG();
+@@ -322,7 +285,7 @@ cpu_vsyscall_notifier(struct notifier_bl
+ 	return NOTIFY_DONE;
+ }
+ 
+-static void __init map_vsyscall(void)
++void __init map_vsyscall(void)
+ {
+ 	extern char __vsyscall_0;
+ 	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+@@ -338,7 +301,6 @@ static int __init vsyscall_init(void)
+ 	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
+ 	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
+ 	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
+-	map_vsyscall();
+ #ifdef CONFIG_XEN
+ 	vsyscall_gtod_data.sysctl_enabled = 0; /* disable vgettimeofay() */
+  	if (boot_cpu_has(X86_FEATURE_RDTSCP))
+--- head-2010-01-18.orig/arch/x86/kernel/xen_entry_64.S	2008-04-02 12:34:02.000000000 +0200
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,36 +0,0 @@
+-/*
+- * Copied from arch/xen/i386/kernel/entry.S
+- */                        
+-/* Offsets into shared_info_t. */                
+-#define evtchn_upcall_pending		/* 0 */
+-#define evtchn_upcall_mask		1
+-
+-#define sizeof_vcpu_shift		6
+-
+-#ifdef CONFIG_SMP
+-//#define preempt_disable(reg)	incl threadinfo_preempt_count(reg)
+-//#define preempt_enable(reg)	decl threadinfo_preempt_count(reg)
+-#define preempt_disable(reg)
+-#define preempt_enable(reg)
+-#define XEN_GET_VCPU_INFO(reg)	preempt_disable(%rbp)			; \
+-				movq %gs:pda_cpunumber,reg		; \
+-				shl  $32, reg				; \
+-				shr  $32-sizeof_vcpu_shift,reg		; \
+-				addq HYPERVISOR_shared_info,reg
+-#define XEN_PUT_VCPU_INFO(reg)	preempt_enable(%rbp)			; \
+-#define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff
+-#else
+-#define XEN_GET_VCPU_INFO(reg)	movq HYPERVISOR_shared_info,reg
+-#define XEN_PUT_VCPU_INFO(reg)
+-#define XEN_PUT_VCPU_INFO_fixup
+-#endif
+-
+-#define XEN_LOCKED_BLOCK_EVENTS(reg)	movb $1,evtchn_upcall_mask(reg)
+-#define XEN_LOCKED_UNBLOCK_EVENTS(reg)	movb $0,evtchn_upcall_mask(reg)
+-#define XEN_BLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
+-				XEN_LOCKED_BLOCK_EVENTS(reg)		; \
+-    				XEN_PUT_VCPU_INFO(reg)
+-#define XEN_UNBLOCK_EVENTS(reg)	XEN_GET_VCPU_INFO(reg)			; \
+-				XEN_LOCKED_UNBLOCK_EVENTS(reg)		; \
+-    				XEN_PUT_VCPU_INFO(reg)
+-#define XEN_TEST_PENDING(reg)	testb $0xFF,evtchn_upcall_pending(reg)
+--- head-2010-01-18.orig/arch/x86/mach-xen/setup.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mach-xen/setup.c	2009-11-06 10:51:25.000000000 +0100
+@@ -161,15 +161,12 @@ void __init machine_specific_arch_setup(
+ 
+ 	/* Do an early initialization of the fixmap area */
+ 	{
+-		extern pte_t swapper_pg_pmd[PTRS_PER_PTE];
++		extern pte_t swapper_pg_fixmap[PTRS_PER_PTE];
+ 		unsigned long addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+-		pgd_t *pgd = (pgd_t *)xen_start_info->pt_base;
+-		pud_t *pud = pud_offset(pgd + pgd_index(addr), addr);
++		pud_t *pud = pud_offset(swapper_pg_dir + pgd_index(addr), addr);
+ 		pmd_t *pmd = pmd_offset(pud, addr);
+ 
+-		swapper_pg_dir = pgd;
+-		init_mm.pgd    = pgd;
+-		make_lowmem_page_readonly(swapper_pg_pmd, XENFEAT_writable_page_tables);
+-		set_pmd(pmd, __pmd(__pa_symbol(swapper_pg_pmd) | _PAGE_TABLE));
++		make_lowmem_page_readonly(swapper_pg_fixmap, XENFEAT_writable_page_tables);
++		set_pmd(pmd, __pmd(__pa_symbol(swapper_pg_fixmap) | _PAGE_TABLE));
+ 	}
+ }
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,1025 @@
++/*
++ *  Copyright (C) 1995  Linus Torvalds
++ *  Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
++ */
++
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/mman.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/vt_kern.h>		/* For unblank_screen() */
++#include <linux/compiler.h>
++#include <linux/highmem.h>
++#include <linux/bootmem.h>		/* for max_low_pfn */
++#include <linux/vmalloc.h>
++#include <linux/module.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/kdebug.h>
++
++#include <asm/system.h>
++#include <asm/desc.h>
++#include <asm/segment.h>
++#include <asm/pgalloc.h>
++#include <asm/smp.h>
++#include <asm/tlbflush.h>
++#include <asm/proto.h>
++#include <asm-generic/sections.h>
++
++/*
++ * Page fault error code bits
++ *	bit 0 == 0 means no page found, 1 means protection fault
++ *	bit 1 == 0 means read, 1 means write
++ *	bit 2 == 0 means kernel, 1 means user-mode
++ *	bit 3 == 1 means use of reserved bit detected
++ *	bit 4 == 1 means fault was an instruction fetch
++ */
++#define PF_PROT		(1<<0)
++#define PF_WRITE	(1<<1)
++#define PF_USER		(1<<2)
++#define PF_RSVD		(1<<3)
++#define PF_INSTR	(1<<4)
++
++static inline int notify_page_fault(struct pt_regs *regs)
++{
++#ifdef CONFIG_KPROBES
++	int ret = 0;
++
++	/* kprobe_running() needs smp_processor_id() */
++#ifdef CONFIG_X86_32
++	if (!user_mode_vm(regs)) {
++#else
++	if (!user_mode(regs)) {
++#endif
++		preempt_disable();
++		if (kprobe_running() && kprobe_fault_handler(regs, 14))
++			ret = 1;
++		preempt_enable();
++	}
++
++	return ret;
++#else
++	return 0;
++#endif
++}
++
++/*
++ * X86_32
++ * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
++ * Check that here and ignore it.
++ *
++ * X86_64
++ * Sometimes the CPU reports invalid exceptions on prefetch.
++ * Check that here and ignore it.
++ *
++ * Opcode checker based on code by Richard Brunner
++ */
++static int is_prefetch(struct pt_regs *regs, unsigned long addr,
++		       unsigned long error_code)
++{
++	unsigned char *instr;
++	int scan_more = 1;
++	int prefetch = 0;
++	unsigned char *max_instr;
++
++	/*
++	 * If it was a exec (instruction fetch) fault on NX page, then
++	 * do not ignore the fault:
++	 */
++	if (error_code & PF_INSTR)
++		return 0;
++
++	instr = (unsigned char *)convert_ip_to_linear(current, regs);
++	max_instr = instr + 15;
++
++	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
++		return 0;
++
++	while (scan_more && instr < max_instr) {
++		unsigned char opcode;
++		unsigned char instr_hi;
++		unsigned char instr_lo;
++
++		if (probe_kernel_address(instr, opcode))
++			break;
++
++		instr_hi = opcode & 0xf0;
++		instr_lo = opcode & 0x0f;
++		instr++;
++
++		switch (instr_hi) {
++		case 0x20:
++		case 0x30:
++			/*
++			 * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
++			 * In X86_64 long mode, the CPU will signal invalid
++			 * opcode if some of these prefixes are present so
++			 * X86_64 will never get here anyway
++			 */
++			scan_more = ((instr_lo & 7) == 0x6);
++			break;
++#ifdef CONFIG_X86_64
++		case 0x40:
++			/*
++			 * In AMD64 long mode 0x40..0x4F are valid REX prefixes
++			 * Need to figure out under what instruction mode the
++			 * instruction was issued. Could check the LDT for lm,
++			 * but for now it's good enough to assume that long
++			 * mode only uses well known segments or kernel.
++			 */
++			scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
++			break;
++#endif
++		case 0x60:
++			/* 0x64 thru 0x67 are valid prefixes in all modes. */
++			scan_more = (instr_lo & 0xC) == 0x4;
++			break;
++		case 0xF0:
++			/* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
++			scan_more = !instr_lo || (instr_lo>>1) == 1;
++			break;
++		case 0x00:
++			/* Prefetch instruction is 0x0F0D or 0x0F18 */
++			scan_more = 0;
++
++			if (probe_kernel_address(instr, opcode))
++				break;
++			prefetch = (instr_lo == 0xF) &&
++				(opcode == 0x0D || opcode == 0x18);
++			break;
++		default:
++			scan_more = 0;
++			break;
++		}
++	}
++	return prefetch;
++}
++
++static void force_sig_info_fault(int si_signo, int si_code,
++	unsigned long address, struct task_struct *tsk)
++{
++	siginfo_t info;
++
++	info.si_signo = si_signo;
++	info.si_errno = 0;
++	info.si_code = si_code;
++	info.si_addr = (void __user *)address;
++	force_sig_info(si_signo, &info, tsk);
++}
++
++#ifdef CONFIG_X86_64
++static int bad_address(void *p)
++{
++	unsigned long dummy;
++	return probe_kernel_address((unsigned long *)p, dummy);
++}
++#endif
++
++static void dump_pagetable(unsigned long address)
++{
++#ifdef CONFIG_X86_32
++	__typeof__(pte_val(__pte(0))) page;
++
++	page = read_cr3();
++	page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
++#ifdef CONFIG_X86_PAE
++	printk("*pdpt = %016Lx ", page);
++	if ((page & _PAGE_PRESENT)
++	    && mfn_to_local_pfn(page >> PAGE_SHIFT) < max_low_pfn) {
++		page = mfn_to_pfn(page >> PAGE_SHIFT);
++		page <<= PAGE_SHIFT;
++		page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
++		                                         & (PTRS_PER_PMD - 1)];
++		printk(KERN_CONT "*pde = %016Lx ", page);
++		page &= ~_PAGE_NX;
++	}
++#else
++	printk("*pde = %08lx ", page);
++#endif
++
++	/*
++	 * We must not directly access the pte in the highpte
++	 * case if the page table is located in highmem.
++	 * And let's rather not kmap-atomic the pte, just in case
++	 * it's allocated already.
++	 */
++	if ((page & _PAGE_PRESENT)
++	    && mfn_to_local_pfn(page >> PAGE_SHIFT) < max_low_pfn
++	    && !(page & _PAGE_PSE)) {
++		page = mfn_to_pfn(page >> PAGE_SHIFT);
++		page <<= PAGE_SHIFT;
++		page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
++		                                         & (PTRS_PER_PTE - 1)];
++		printk(KERN_CONT "*pte = %0*Lx ", sizeof(page)*2, (u64)page);
++	}
++
++	printk(KERN_CONT "\n");
++#else /* CONFIG_X86_64 */
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	pgd = (pgd_t *)read_cr3();
++
++	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
++	pgd += pgd_index(address);
++	if (bad_address(pgd)) goto bad;
++	printk("PGD %lx ", pgd_val(*pgd));
++	if (!pgd_present(*pgd)) goto ret;
++
++	pud = pud_offset(pgd, address);
++	if (bad_address(pud)) goto bad;
++	printk(KERN_CONT "PUD %lx ", pud_val(*pud));
++	if (!pud_present(*pud) || pud_large(*pud))
++		goto ret;
++
++	pmd = pmd_offset(pud, address);
++	if (bad_address(pmd)) goto bad;
++	printk(KERN_CONT "PMD %lx ", pmd_val(*pmd));
++	if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
++
++	pte = pte_offset_kernel(pmd, address);
++	if (bad_address(pte)) goto bad;
++	printk(KERN_CONT "PTE %lx", pte_val(*pte));
++ret:
++	printk(KERN_CONT "\n");
++	return;
++bad:
++	printk("BAD\n");
++#endif
++}
++
++#ifdef CONFIG_X86_32
++static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
++{
++	unsigned index = pgd_index(address);
++	pgd_t *pgd_k;
++	pud_t *pud, *pud_k;
++	pmd_t *pmd, *pmd_k;
++
++	pgd += index;
++	pgd_k = init_mm.pgd + index;
++
++	if (!pgd_present(*pgd_k))
++		return NULL;
++
++	/*
++	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
++	 * and redundant with the set_pmd() on non-PAE. As would
++	 * set_pud.
++	 */
++
++	pud = pud_offset(pgd, address);
++	pud_k = pud_offset(pgd_k, address);
++	if (!pud_present(*pud_k))
++		return NULL;
++
++	pmd = pmd_offset(pud, address);
++	pmd_k = pmd_offset(pud_k, address);
++	if (!pmd_present(*pmd_k))
++		return NULL;
++	if (!pmd_present(*pmd)) {
++		bool lazy = x86_read_percpu(xen_lazy_mmu);
++
++		x86_write_percpu(xen_lazy_mmu, false);
++#if CONFIG_XEN_COMPAT > 0x030002
++		set_pmd(pmd, *pmd_k);
++#else
++		/*
++		 * When running on older Xen we must launder *pmd_k through
++		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
++		 */
++		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
++#endif
++		x86_write_percpu(xen_lazy_mmu, lazy);
++	} else
++		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
++	return pmd_k;
++}
++#endif
++
++#ifdef CONFIG_X86_64
++static const char errata93_warning[] =
++KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
++KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
++KERN_ERR "******* Please consider a BIOS update.\n"
++KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
++#endif
++
++/* Workaround for K8 erratum #93 & buggy BIOS.
++   BIOS SMM functions are required to use a specific workaround
++   to avoid corruption of the 64bit RIP register on C stepping K8.
++   A lot of BIOS that didn't get tested properly miss this.
++   The OS sees this as a page fault with the upper 32bits of RIP cleared.
++   Try to work around it here.
++   Note we only handle faults in kernel here.
++   Does nothing for X86_32
++ */
++static int is_errata93(struct pt_regs *regs, unsigned long address)
++{
++#ifdef CONFIG_X86_64
++	static int warned;
++	if (address != regs->ip)
++		return 0;
++	if ((address >> 32) != 0)
++		return 0;
++	address |= 0xffffffffUL << 32;
++	if ((address >= (u64)_stext && address <= (u64)_etext) ||
++	    (address >= MODULES_VADDR && address <= MODULES_END)) {
++		if (!warned) {
++			printk(errata93_warning);
++			warned = 1;
++		}
++		regs->ip = address;
++		return 1;
++	}
++#endif
++	return 0;
++}
++
++/*
++ * Work around K8 erratum #100 K8 in compat mode occasionally jumps to illegal
++ * addresses >4GB.  We catch this in the page fault handler because these
++ * addresses are not reachable. Just detect this case and return.  Any code
++ * segment in LDT is compatibility mode.
++ */
++static int is_errata100(struct pt_regs *regs, unsigned long address)
++{
++#ifdef CONFIG_X86_64
++	if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
++	    (address >> 32))
++		return 1;
++#endif
++	return 0;
++}
++
++void do_invalid_op(struct pt_regs *, unsigned long);
++
++static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
++{
++#ifdef CONFIG_X86_F00F_BUG
++	unsigned long nr;
++	/*
++	 * Pentium F0 0F C7 C8 bug workaround.
++	 */
++	if (boot_cpu_data.f00f_bug) {
++		nr = (address - idt_descr.address) >> 3;
++
++		if (nr == 6) {
++			do_invalid_op(regs, 0);
++			return 1;
++		}
++	}
++#endif
++	return 0;
++}
++
++static void show_fault_oops(struct pt_regs *regs, unsigned long error_code,
++			    unsigned long address)
++{
++#ifdef CONFIG_X86_32
++	if (!oops_may_print())
++		return;
++#endif
++
++#ifdef CONFIG_X86_PAE
++	if (error_code & PF_INSTR) {
++		unsigned int level;
++		pte_t *pte = lookup_address(address, &level);
++
++		if (pte && pte_present(*pte) && !pte_exec(*pte))
++			printk(KERN_CRIT "kernel tried to execute "
++				"NX-protected page - exploit attempt? "
++				"(uid: %d)\n", current->uid);
++	}
++#endif
++
++	printk(KERN_ALERT "BUG: unable to handle kernel ");
++	if (address < PAGE_SIZE)
++		printk(KERN_CONT "NULL pointer dereference");
++	else
++		printk(KERN_CONT "paging request");
++#ifdef CONFIG_X86_32
++	printk(KERN_CONT " at %08lx\n", address);
++#else
++	printk(KERN_CONT " at %016lx\n", address);
++#endif
++	printk(KERN_ALERT "IP:");
++	printk_address(regs->ip, 1);
++	dump_pagetable(address);
++}
++
++#ifdef CONFIG_X86_64
++static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
++				 unsigned long error_code)
++{
++	unsigned long flags = oops_begin();
++	struct task_struct *tsk;
++
++	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
++	       current->comm, address);
++	dump_pagetable(address);
++	tsk = current;
++	tsk->thread.cr2 = address;
++	tsk->thread.trap_no = 14;
++	tsk->thread.error_code = error_code;
++	if (__die("Bad pagetable", regs, error_code))
++		regs = NULL;
++	oops_end(flags, regs, SIGKILL);
++}
++#endif
++
++static int spurious_fault_check(unsigned long error_code, pte_t *pte)
++{
++	if ((error_code & PF_WRITE) && !pte_write(*pte))
++		return 0;
++	if ((error_code & PF_INSTR) && !pte_exec(*pte))
++		return 0;
++
++	return 1;
++}
++
++/*
++ * Handle a spurious fault caused by a stale TLB entry.  This allows
++ * us to lazily refresh the TLB when increasing the permissions of a
++ * kernel page (RO -> RW or NX -> X).  Doing it eagerly is very
++ * expensive since that implies doing a full cross-processor TLB
++ * flush, even if no stale TLB entries exist on other processors.
++ * There are no security implications to leaving a stale TLB when
++ * increasing the permissions on a page.
++ */
++static int spurious_fault(unsigned long address,
++			  unsigned long error_code)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++
++	/* Reserved-bit violation or user access to kernel space? */
++	if (error_code & (PF_USER | PF_RSVD))
++		return 0;
++
++	pgd = init_mm.pgd + pgd_index(address);
++	if (!pgd_present(*pgd))
++		return 0;
++
++	pud = pud_offset(pgd, address);
++	if (!pud_present(*pud))
++		return 0;
++
++	if (pud_large(*pud))
++		return spurious_fault_check(error_code, (pte_t *) pud);
++
++	pmd = pmd_offset(pud, address);
++	if (!pmd_present(*pmd))
++		return 0;
++
++	if (pmd_large(*pmd))
++		return spurious_fault_check(error_code, (pte_t *) pmd);
++
++	pte = pte_offset_kernel(pmd, address);
++	if (!pte_present(*pte))
++		return 0;
++
++	return spurious_fault_check(error_code, pte);
++}
++
++/*
++ * X86_32
++ * Handle a fault on the vmalloc or module mapping area
++ *
++ * X86_64
++ * Handle a fault on the vmalloc area
++ *
++ * This assumes no large pages in there.
++ */
++static int vmalloc_fault(unsigned long address)
++{
++#ifdef CONFIG_X86_32
++	unsigned long pgd_paddr;
++	pmd_t *pmd_k;
++	pte_t *pte_k;
++	/*
++	 * Synchronize this task's top level page-table
++	 * with the 'reference' page table.
++	 *
++	 * Do _not_ use "current" here. We might be inside
++	 * an interrupt in the middle of a task switch..
++	 */
++	pgd_paddr = read_cr3();
++	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
++	if (!pmd_k)
++		return -1;
++	pte_k = pte_offset_kernel(pmd_k, address);
++	if (!pte_present(*pte_k))
++		return -1;
++	return 0;
++#else
++	pgd_t *pgd, *pgd_ref;
++	pud_t *pud, *pud_ref;
++	pmd_t *pmd, *pmd_ref;
++	pte_t *pte, *pte_ref;
++
++	/* Make sure we are in vmalloc area */
++	if (!(address >= VMALLOC_START && address < VMALLOC_END))
++		return -1;
++
++	/* Copy kernel mappings over when needed. This can also
++	   happen within a race in page table update. In the later
++	   case just flush. */
++
++	/* On Xen the line below does not always work. Needs investigating! */
++	/*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
++	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
++	pgd += pgd_index(address);
++	pgd_ref = pgd_offset_k(address);
++	if (pgd_none(*pgd_ref))
++		return -1;
++	if (pgd_none(*pgd))
++		set_pgd(pgd, *pgd_ref);
++	else
++		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
++
++	/* Below here mismatches are bugs because these lower tables
++	   are shared */
++
++	pud = pud_offset(pgd, address);
++	pud_ref = pud_offset(pgd_ref, address);
++	if (pud_none(*pud_ref))
++		return -1;
++	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
++		BUG();
++	pmd = pmd_offset(pud, address);
++	pmd_ref = pmd_offset(pud_ref, address);
++	if (pmd_none(*pmd_ref))
++		return -1;
++	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
++		BUG();
++	pte_ref = pte_offset_kernel(pmd_ref, address);
++	if (!pte_present(*pte_ref))
++		return -1;
++	pte = pte_offset_kernel(pmd, address);
++	/* Don't use pte_page here, because the mappings can point
++	   outside mem_map, and the NUMA hash lookup cannot handle
++	   that. */
++	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
++		BUG();
++	return 0;
++#endif
++}
++
++int show_unhandled_signals = 1;
++
++/*
++ * This routine handles page faults.  It determines the address,
++ * and the problem, and then passes it off to one of the appropriate
++ * routines.
++ */
++#ifdef CONFIG_X86_64
++asmlinkage
++#endif
++void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
++{
++	struct task_struct *tsk;
++	struct mm_struct *mm;
++	struct vm_area_struct *vma;
++	unsigned long address;
++	int write, si_code;
++	int fault;
++#ifdef CONFIG_X86_64
++	unsigned long flags;
++#endif
++
++	/*
++	 * We can fault from pretty much anywhere, with unknown IRQ state.
++	 */
++	trace_hardirqs_fixup();
++
++	/* Set the "privileged fault" bit to something sane. */
++	if (user_mode_vm(regs))
++		error_code |= PF_USER;
++	else
++		error_code &= ~PF_USER;
++
++	tsk = current;
++	mm = tsk->mm;
++	prefetchw(&mm->mmap_sem);
++
++	/* get the address */
++	address = read_cr2();
++
++	si_code = SEGV_MAPERR;
++
++	if (notify_page_fault(regs))
++		return;
++
++	/*
++	 * We fault-in kernel-space virtual memory on-demand. The
++	 * 'reference' page table is init_mm.pgd.
++	 *
++	 * NOTE! We MUST NOT take any locks for this case. We may
++	 * be in an interrupt or a critical region, and should
++	 * only copy the information from the master page table,
++	 * nothing more.
++	 *
++	 * This verifies that the fault happens in kernel space
++	 * (error_code & 4) == 0, and that the fault was not a
++	 * protection error (error_code & 9) == 0.
++	 */
++#ifdef CONFIG_X86_32
++	if (unlikely(address >= TASK_SIZE)) {
++#else
++	if (unlikely(address >= TASK_SIZE64)) {
++#endif
++		/* Faults in hypervisor area can never be patched up. */
++#if defined(CONFIG_X86_XEN)
++		if (address >= hypervisor_virt_start)
++			goto bad_area_nosemaphore;
++#elif defined(CONFIG_X86_64_XEN)
++		if (address >= HYPERVISOR_VIRT_START
++		    && address < HYPERVISOR_VIRT_END)
++			goto bad_area_nosemaphore;
++#endif
++		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
++		    vmalloc_fault(address) >= 0)
++			return;
++
++		/* Can handle a stale RO->RW TLB */
++		if (spurious_fault(address, error_code))
++			return;
++
++		/*
++		 * Don't take the mm semaphore here. If we fixup a prefetch
++		 * fault we could otherwise deadlock.
++		 */
++		goto bad_area_nosemaphore;
++	}
++
++
++#ifdef CONFIG_X86_32
++	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
++	   fault has been handled. */
++	if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
++		local_irq_enable();
++
++	/*
++	 * If we're in an interrupt, have no user context or are running in an
++	 * atomic region then we must not take the fault.
++	 */
++	if (in_atomic() || !mm)
++		goto bad_area_nosemaphore;
++#else /* CONFIG_X86_64 */
++	if (likely(regs->flags & X86_EFLAGS_IF))
++		local_irq_enable();
++
++	if (unlikely(error_code & PF_RSVD))
++		pgtable_bad(address, regs, error_code);
++
++	/*
++	 * If we're in an interrupt, have no user context or are running in an
++	 * atomic region then we must not take the fault.
++	 */
++	if (unlikely(in_atomic() || !mm))
++		goto bad_area_nosemaphore;
++
++	/*
++	 * User-mode registers count as a user access even for any
++	 * potential system fault or CPU buglet.
++	 */
++	if (user_mode_vm(regs))
++		error_code |= PF_USER;
++again:
++#endif
++	/* When running in the kernel we expect faults to occur only to
++	 * addresses in user space.  All other faults represent errors in the
++	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
++	 * erroneous fault occurring in a code path which already holds mmap_sem
++	 * we will deadlock attempting to validate the fault against the
++	 * address space.  Luckily the kernel only validly references user
++	 * space from well defined areas of code, which are listed in the
++	 * exceptions table.
++	 *
++	 * As the vast majority of faults will be valid we will only perform
++	 * the source reference check when there is a possibility of a deadlock.
++	 * Attempt to lock the address space, if we cannot we then validate the
++	 * source.  If this is invalid we can skip the address space check,
++	 * thus avoiding the deadlock.
++	 */
++	if (!down_read_trylock(&mm->mmap_sem)) {
++		if ((error_code & PF_USER) == 0 &&
++		    !search_exception_tables(regs->ip))
++			goto bad_area_nosemaphore;
++		down_read(&mm->mmap_sem);
++	}
++
++	vma = find_vma(mm, address);
++	if (!vma)
++		goto bad_area;
++	if (vma->vm_start <= address)
++		goto good_area;
++	if (!(vma->vm_flags & VM_GROWSDOWN))
++		goto bad_area;
++	if (error_code & PF_USER) {
++		/*
++		 * Accessing the stack below %sp is always a bug.
++		 * The large cushion allows instructions like enter
++		 * and pusha to work.  ("enter $65535,$31" pushes
++		 * 32 pointers and then decrements %sp by 65535.)
++		 */
++		if (address + 65536 + 32 * sizeof(unsigned long) < regs->sp)
++			goto bad_area;
++	}
++	if (expand_stack(vma, address))
++		goto bad_area;
++/*
++ * Ok, we have a good vm_area for this memory access, so
++ * we can handle it..
++ */
++good_area:
++	si_code = SEGV_ACCERR;
++	write = 0;
++	switch (error_code & (PF_PROT|PF_WRITE)) {
++	default:	/* 3: write, present */
++		/* fall through */
++	case PF_WRITE:		/* write, not present */
++		if (!(vma->vm_flags & VM_WRITE))
++			goto bad_area;
++		write++;
++		break;
++	case PF_PROT:		/* read, present */
++		goto bad_area;
++	case 0:			/* read, not present */
++		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
++			goto bad_area;
++	}
++
++#ifdef CONFIG_X86_32
++survive:
++#endif
++	/*
++	 * If for any reason at all we couldn't handle the fault,
++	 * make sure we exit gracefully rather than endlessly redo
++	 * the fault.
++	 */
++	fault = handle_mm_fault(mm, vma, address, write);
++	if (unlikely(fault & VM_FAULT_ERROR)) {
++		if (fault & VM_FAULT_OOM)
++			goto out_of_memory;
++		else if (fault & VM_FAULT_SIGBUS)
++			goto do_sigbus;
++		BUG();
++	}
++	if (fault & VM_FAULT_MAJOR)
++		tsk->maj_flt++;
++	else
++		tsk->min_flt++;
++
++#ifdef CONFIG_X86_32
++	/*
++	 * Did it hit the DOS screen memory VA from vm86 mode?
++	 */
++	if (v8086_mode(regs)) {
++		unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
++		if (bit < 32)
++			tsk->thread.screen_bitmap |= 1 << bit;
++	}
++#endif
++	up_read(&mm->mmap_sem);
++	return;
++
++/*
++ * Something tried to access memory that isn't in our memory map..
++ * Fix it, but check if it's kernel or user first..
++ */
++bad_area:
++	up_read(&mm->mmap_sem);
++
++bad_area_nosemaphore:
++	/* User mode accesses just cause a SIGSEGV */
++	if (error_code & PF_USER) {
++		/*
++		 * It's possible to have interrupts off here.
++		 */
++		local_irq_enable();
++
++		/*
++		 * Valid to do another page fault here because this one came
++		 * from user space.
++		 */
++		if (is_prefetch(regs, address, error_code))
++			return;
++
++		if (is_errata100(regs, address))
++			return;
++
++		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++		    printk_ratelimit()) {
++			printk(
++#ifdef CONFIG_X86_32
++			"%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx",
++#else
++			"%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx",
++#endif
++			task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
++			tsk->comm, task_pid_nr(tsk), address, regs->ip,
++			regs->sp, error_code);
++			print_vma_addr(" in ", regs->ip);
++			printk("\n");
++		}
++
++		tsk->thread.cr2 = address;
++		/* Kernel addresses are always protection faults */
++		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
++		tsk->thread.trap_no = 14;
++		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
++		return;
++	}
++
++	if (is_f00f_bug(regs, address))
++		return;
++
++no_context:
++	/* Are we prepared to handle this kernel fault?  */
++	if (fixup_exception(regs))
++		return;
++
++	/*
++	 * X86_32
++	 * Valid to do another page fault here, because if this fault
++	 * had been triggered by is_prefetch fixup_exception would have
++	 * handled it.
++	 *
++	 * X86_64
++	 * Hall of shame of CPU/BIOS bugs.
++	 */
++	if (is_prefetch(regs, address, error_code))
++		return;
++
++	if (is_errata93(regs, address))
++		return;
++
++/*
++ * Oops. The kernel tried to access some bad page. We'll have to
++ * terminate things with extreme prejudice.
++ */
++#ifdef CONFIG_X86_32
++	bust_spinlocks(1);
++#else
++	flags = oops_begin();
++#endif
++
++	show_fault_oops(regs, error_code, address);
++
++	tsk->thread.cr2 = address;
++	tsk->thread.trap_no = 14;
++	tsk->thread.error_code = error_code;
++
++#ifdef CONFIG_X86_32
++	die("Oops", regs, error_code);
++	bust_spinlocks(0);
++	do_exit(SIGKILL);
++#else
++	if (__die("Oops", regs, error_code))
++		regs = NULL;
++	/* Executive summary in case the body of the oops scrolled away */
++	printk(KERN_EMERG "CR2: %016lx\n", address);
++	oops_end(flags, regs, SIGKILL);
++#endif
++
++/*
++ * We ran out of memory, or some other thing happened to us that made
++ * us unable to handle the page fault gracefully.
++ */
++out_of_memory:
++	up_read(&mm->mmap_sem);
++	if (is_global_init(tsk)) {
++		yield();
++#ifdef CONFIG_X86_32
++		down_read(&mm->mmap_sem);
++		goto survive;
++#else
++		goto again;
++#endif
++	}
++
++	printk("VM: killing process %s\n", tsk->comm);
++	if (error_code & PF_USER)
++		do_group_exit(SIGKILL);
++	goto no_context;
++
++do_sigbus:
++	up_read(&mm->mmap_sem);
++
++	/* Kernel mode? Handle exceptions or die */
++	if (!(error_code & PF_USER))
++		goto no_context;
++#ifdef CONFIG_X86_32
++	/* User space => ok to do another page fault */
++	if (is_prefetch(regs, address, error_code))
++		return;
++#endif
++	tsk->thread.cr2 = address;
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 14;
++	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
++}
++
++DEFINE_SPINLOCK(pgd_lock);
++LIST_HEAD(pgd_list);
++
++void vmalloc_sync_all(void)
++{
++#ifdef CONFIG_X86_32
++	/*
++	 * Note that races in the updates of insync and start aren't
++	 * problematic: insync can only get set bits added, and updates to
++	 * start are only improving performance (without affecting correctness
++	 * if undone).
++	 * XEN: To work on PAE, we need to iterate over PMDs rather than PGDs.
++	 *      This change works just fine with 2-level paging too.
++	 */
++#define sync_index(a) ((a) >> PMD_SHIFT)
++	static DECLARE_BITMAP(insync, PTRS_PER_PGD*PTRS_PER_PMD);
++	static unsigned long start = TASK_SIZE;
++	unsigned long address;
++
++	if (SHARED_KERNEL_PMD)
++		return;
++
++	BUILD_BUG_ON(TASK_SIZE & ~PMD_MASK);
++	for (address = start;
++	     address < hypervisor_virt_start;
++	     address += PMD_SIZE) {
++		if (!test_bit(sync_index(address), insync)) {
++			unsigned long flags;
++			struct page *page;
++
++			spin_lock_irqsave(&pgd_lock, flags);
++			/* XEN: failure path assumes non-empty pgd_list. */
++			if (unlikely(list_empty(&pgd_list))) {
++				spin_unlock_irqrestore(&pgd_lock, flags);
++				return;
++			}
++			list_for_each_entry(page, &pgd_list, lru) {
++				if (!vmalloc_sync_one(page_address(page),
++						      address))
++					break;
++			}
++			spin_unlock_irqrestore(&pgd_lock, flags);
++			if (!page)
++				set_bit(sync_index(address), insync);
++		}
++		if (address == start && test_bit(sync_index(address), insync))
++			start = address + PMD_SIZE;
++	}
++#else /* CONFIG_X86_64 */
++	/*
++	 * Note that races in the updates of insync and start aren't
++	 * problematic: insync can only get set bits added, and updates to
++	 * start are only improving performance (without affecting correctness
++	 * if undone).
++	 */
++	static DECLARE_BITMAP(insync, PTRS_PER_PGD);
++	static unsigned long start = VMALLOC_START & PGDIR_MASK;
++	unsigned long address;
++
++	for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
++		if (!test_bit(pgd_index(address), insync)) {
++			const pgd_t *pgd_ref = pgd_offset_k(address);
++			unsigned long flags;
++			struct page *page;
++
++			if (pgd_none(*pgd_ref))
++				continue;
++			spin_lock_irqsave(&pgd_lock, flags);
++			list_for_each_entry(page, &pgd_list, lru) {
++				pgd_t *pgd;
++				pgd = (pgd_t *)page_address(page) + pgd_index(address);
++				if (pgd_none(*pgd))
++					set_pgd(pgd, *pgd_ref);
++				else
++					BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
++			}
++			spin_unlock_irqrestore(&pgd_lock, flags);
++			set_bit(pgd_index(address), insync);
++		}
++		if (address == start)
++			start = address + PGDIR_SIZE;
++	}
++	/* Check that there is no need to do the same for the modules area. */
++	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
++	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
++				(__START_KERNEL & PGDIR_MASK)));
++#endif
++}
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,757 +0,0 @@
+-/*
+- *  linux/arch/i386/mm/fault.c
+- *
+- *  Copyright (C) 1995  Linus Torvalds
+- */
+-
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+-#include <linux/ptrace.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/tty.h>
+-#include <linux/vt_kern.h>		/* For unblank_screen() */
+-#include <linux/highmem.h>
+-#include <linux/bootmem.h>		/* for max_low_pfn */
+-#include <linux/vmalloc.h>
+-#include <linux/module.h>
+-#include <linux/kprobes.h>
+-#include <linux/uaccess.h>
+-#include <linux/kdebug.h>
+-#include <linux/kprobes.h>
+-
+-#include <asm/system.h>
+-#include <asm/desc.h>
+-#include <asm/segment.h>
+-
+-extern void die(const char *,struct pt_regs *,long);
+-
+-#ifdef CONFIG_KPROBES
+-static inline int notify_page_fault(struct pt_regs *regs)
+-{
+-	int ret = 0;
+-
+-	/* kprobe_running() needs smp_processor_id() */
+-	if (!user_mode_vm(regs)) {
+-		preempt_disable();
+-		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+-			ret = 1;
+-		preempt_enable();
+-	}
+-
+-	return ret;
+-}
+-#else
+-static inline int notify_page_fault(struct pt_regs *regs)
+-{
+-	return 0;
+-}
+-#endif
+-
+-/*
+- * Return EIP plus the CS segment base.  The segment limit is also
+- * adjusted, clamped to the kernel/user address space (whichever is
+- * appropriate), and returned in *eip_limit.
+- *
+- * The segment is checked, because it might have been changed by another
+- * task between the original faulting instruction and here.
+- *
+- * If CS is no longer a valid code segment, or if EIP is beyond the
+- * limit, or if it is a kernel address when CS is not a kernel segment,
+- * then the returned value will be greater than *eip_limit.
+- * 
+- * This is slow, but is very rarely executed.
+- */
+-static inline unsigned long get_segment_eip(struct pt_regs *regs,
+-					    unsigned long *eip_limit)
+-{
+-	unsigned long eip = regs->eip;
+-	unsigned seg = regs->xcs & 0xffff;
+-	u32 seg_ar, seg_limit, base, *desc;
+-
+-	/* Unlikely, but must come before segment checks. */
+-	if (unlikely(regs->eflags & VM_MASK)) {
+-		base = seg << 4;
+-		*eip_limit = base + 0xffff;
+-		return base + (eip & 0xffff);
+-	}
+-
+-	/* The standard kernel/user address space limit. */
+-	*eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;
+-	
+-	/* By far the most common cases. */
+-	if (likely(SEGMENT_IS_FLAT_CODE(seg)))
+-		return eip;
+-
+-	/* Check the segment exists, is within the current LDT/GDT size,
+-	   that kernel/user (ring 0..3) has the appropriate privilege,
+-	   that it's a code segment, and get the limit. */
+-	__asm__ ("larl %3,%0; lsll %3,%1"
+-		 : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg));
+-	if ((~seg_ar & 0x9800) || eip > seg_limit) {
+-		*eip_limit = 0;
+-		return 1;	 /* So that returned eip > *eip_limit. */
+-	}
+-
+-	/* Get the GDT/LDT descriptor base. 
+-	   When you look for races in this code remember that
+-	   LDT and other horrors are only used in user space. */
+-	if (seg & (1<<2)) {
+-		/* Must lock the LDT while reading it. */
+-		mutex_lock(&current->mm->context.lock);
+-		desc = current->mm->context.ldt;
+-		desc = (void *)desc + (seg & ~7);
+-	} else {
+-		/* Must disable preemption while reading the GDT. */
+- 		desc = (u32 *)get_cpu_gdt_table(get_cpu());
+-		desc = (void *)desc + (seg & ~7);
+-	}
+-
+-	/* Decode the code segment base from the descriptor */
+-	base = get_desc_base((unsigned long *)desc);
+-
+-	if (seg & (1<<2)) { 
+-		mutex_unlock(&current->mm->context.lock);
+-	} else
+-		put_cpu();
+-
+-	/* Adjust EIP and segment limit, and clamp at the kernel limit.
+-	   It's legitimate for segments to wrap at 0xffffffff. */
+-	seg_limit += base;
+-	if (seg_limit < *eip_limit && seg_limit >= base)
+-		*eip_limit = seg_limit;
+-	return eip + base;
+-}
+-
+-/* 
+- * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
+- * Check that here and ignore it.
+- */
+-static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
+-{ 
+-	unsigned long limit;
+-	unsigned char *instr = (unsigned char *)get_segment_eip (regs, &limit);
+-	int scan_more = 1;
+-	int prefetch = 0; 
+-	int i;
+-
+-	for (i = 0; scan_more && i < 15; i++) { 
+-		unsigned char opcode;
+-		unsigned char instr_hi;
+-		unsigned char instr_lo;
+-
+-		if (instr > (unsigned char *)limit)
+-			break;
+-		if (probe_kernel_address(instr, opcode))
+-			break; 
+-
+-		instr_hi = opcode & 0xf0; 
+-		instr_lo = opcode & 0x0f; 
+-		instr++;
+-
+-		switch (instr_hi) { 
+-		case 0x20:
+-		case 0x30:
+-			/* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */
+-			scan_more = ((instr_lo & 7) == 0x6);
+-			break;
+-			
+-		case 0x60:
+-			/* 0x64 thru 0x67 are valid prefixes in all modes. */
+-			scan_more = (instr_lo & 0xC) == 0x4;
+-			break;		
+-		case 0xF0:
+-			/* 0xF0, 0xF2, and 0xF3 are valid prefixes */
+-			scan_more = !instr_lo || (instr_lo>>1) == 1;
+-			break;			
+-		case 0x00:
+-			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+-			scan_more = 0;
+-			if (instr > (unsigned char *)limit)
+-				break;
+-			if (probe_kernel_address(instr, opcode))
+-				break;
+-			prefetch = (instr_lo == 0xF) &&
+-				(opcode == 0x0D || opcode == 0x18);
+-			break;			
+-		default:
+-			scan_more = 0;
+-			break;
+-		} 
+-	}
+-	return prefetch;
+-}
+-
+-static inline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+-			      unsigned long error_code)
+-{
+-	if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+-		     boot_cpu_data.x86 >= 6)) {
+-		/* Catch an obscure case of prefetch inside an NX page. */
+-		if (nx_enabled && (error_code & 16))
+-			return 0;
+-		return __is_prefetch(regs, addr);
+-	}
+-	return 0;
+-} 
+-
+-static noinline void force_sig_info_fault(int si_signo, int si_code,
+-	unsigned long address, struct task_struct *tsk)
+-{
+-	siginfo_t info;
+-
+-	info.si_signo = si_signo;
+-	info.si_errno = 0;
+-	info.si_code = si_code;
+-	info.si_addr = (void __user *)address;
+-	force_sig_info(si_signo, &info, tsk);
+-}
+-
+-fastcall void do_invalid_op(struct pt_regs *, unsigned long);
+-
+-#ifdef CONFIG_X86_PAE
+-static void dump_fault_path(unsigned long address)
+-{
+-	unsigned long *p, page;
+-	unsigned long mfn; 
+-
+-	page = read_cr3();
+-	p  = (unsigned long *)__va(page);
+-	p += (address >> 30) * 2;
+-	printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
+-	if (p[0] & _PAGE_PRESENT) {
+-		mfn  = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
+-		page = mfn_to_pfn(mfn) << PAGE_SHIFT; 
+-		p  = (unsigned long *)__va(page);
+-		address &= 0x3fffffff;
+-		p += (address >> 21) * 2;
+-		printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n", 
+-		       page, p[1], p[0]);
+-		mfn  = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
+-#ifdef CONFIG_HIGHPTE
+-		if (mfn_to_pfn(mfn) >= highstart_pfn)
+-			return;
+-#endif
+-		if ((p[0] & _PAGE_PRESENT) && !(p[0] & _PAGE_PSE)) {
+-			page = mfn_to_pfn(mfn) << PAGE_SHIFT; 
+-			p  = (unsigned long *) __va(page);
+-			address &= 0x001fffff;
+-			p += (address >> 12) * 2;
+-			printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n",
+-			       page, p[1], p[0]);
+-		}
+-	}
+-}
+-#else
+-static void dump_fault_path(unsigned long address)
+-{
+-	unsigned long page;
+-
+-	page = read_cr3();
+-	page = ((unsigned long *) __va(page))[address >> PGDIR_SHIFT];
+-	printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
+-	       machine_to_phys(page));
+-	/*
+-	 * We must not directly access the pte in the highpte
+-	 * case if the page table is located in highmem.
+-	 * And lets rather not kmap-atomic the pte, just in case
+-	 * it's allocated already.
+-	 */
+-	if ((machine_to_phys(page) >> PAGE_SHIFT) < max_low_pfn
+-	    && (page & _PAGE_PRESENT)
+-	    && !(page & _PAGE_PSE)) {
+-		page = machine_to_phys(page & PAGE_MASK);
+-		page = ((unsigned long *) __va(page))[(address >> PAGE_SHIFT)
+-		                                      & (PTRS_PER_PTE - 1)];
+-		printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
+-		       machine_to_phys(page));
+-	}
+-}
+-#endif
+-
+-static int spurious_fault(struct pt_regs *regs,
+-			  unsigned long address,
+-			  unsigned long error_code)
+-{
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
+-
+-	/* Reserved-bit violation or user access to kernel space? */
+-	if (error_code & 0x0c)
+-		return 0;
+-
+-	pgd = init_mm.pgd + pgd_index(address);
+-	if (!pgd_present(*pgd))
+-		return 0;
+-
+-	pud = pud_offset(pgd, address);
+-	if (!pud_present(*pud))
+-		return 0;
+-
+-	pmd = pmd_offset(pud, address);
+-	if (!pmd_present(*pmd))
+-		return 0;
+-
+-	pte = pte_offset_kernel(pmd, address);
+-	if (!pte_present(*pte))
+-		return 0;
+-	if ((error_code & 0x02) && !pte_write(*pte))
+-		return 0;
+-#ifdef CONFIG_X86_PAE
+-	if ((error_code & 0x10) && (__pte_val(*pte) & _PAGE_NX))
+-		return 0;
+-#endif
+-
+-	return 1;
+-}
+-
+-static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+-{
+-	unsigned index = pgd_index(address);
+-	pgd_t *pgd_k;
+-	pud_t *pud, *pud_k;
+-	pmd_t *pmd, *pmd_k;
+-
+-	pgd += index;
+-	pgd_k = init_mm.pgd + index;
+-
+-	if (!pgd_present(*pgd_k))
+-		return NULL;
+-
+-	/*
+-	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
+-	 * and redundant with the set_pmd() on non-PAE. As would
+-	 * set_pud.
+-	 */
+-
+-	pud = pud_offset(pgd, address);
+-	pud_k = pud_offset(pgd_k, address);
+-	if (!pud_present(*pud_k))
+-		return NULL;
+-
+-	pmd = pmd_offset(pud, address);
+-	pmd_k = pmd_offset(pud_k, address);
+-	if (!pmd_present(*pmd_k))
+-		return NULL;
+-	if (!pmd_present(*pmd)) {
+-		bool lazy = x86_read_percpu(xen_lazy_mmu);
+-
+-		x86_write_percpu(xen_lazy_mmu, false);
+-#if CONFIG_XEN_COMPAT > 0x030002
+-		set_pmd(pmd, *pmd_k);
+-#else
+-		/*
+-		 * When running on older Xen we must launder *pmd_k through
+-		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
+-		 */
+-		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+-#endif
+-		x86_write_percpu(xen_lazy_mmu, lazy);
+-	} else
+-		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+-	return pmd_k;
+-}
+-
+-/*
+- * Handle a fault on the vmalloc or module mapping area
+- *
+- * This assumes no large pages in there.
+- */
+-static inline int vmalloc_fault(unsigned long address)
+-{
+-	unsigned long pgd_paddr;
+-	pmd_t *pmd_k;
+-	pte_t *pte_k;
+-	/*
+-	 * Synchronize this task's top level page-table
+-	 * with the 'reference' page table.
+-	 *
+-	 * Do _not_ use "current" here. We might be inside
+-	 * an interrupt in the middle of a task switch..
+-	 */
+-	pgd_paddr = read_cr3();
+-	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
+-	if (!pmd_k)
+-		return -1;
+-	pte_k = pte_offset_kernel(pmd_k, address);
+-	if (!pte_present(*pte_k))
+-		return -1;
+-	return 0;
+-}
+-
+-int show_unhandled_signals = 1;
+-
+-/*
+- * This routine handles page faults.  It determines the address,
+- * and the problem, and then passes it off to one of the appropriate
+- * routines.
+- *
+- * error_code:
+- *	bit 0 == 0 means no page found, 1 means protection fault
+- *	bit 1 == 0 means read, 1 means write
+- *	bit 2 == 0 means kernel, 1 means user-mode
+- *	bit 3 == 1 means use of reserved bit detected
+- *	bit 4 == 1 means fault was an instruction fetch
+- */
+-fastcall void __kprobes do_page_fault(struct pt_regs *regs,
+-				      unsigned long error_code)
+-{
+-	struct task_struct *tsk;
+-	struct mm_struct *mm;
+-	struct vm_area_struct * vma;
+-	unsigned long address;
+-	int write, si_code;
+-	int fault;
+-
+-	/*
+-	 * We can fault from pretty much anywhere, with unknown IRQ state.
+-	 */
+-	trace_hardirqs_fixup();
+-
+-	/* get the address */
+-        address = read_cr2();
+-
+-	/* Set the "privileged fault" bit to something sane. */
+-	error_code &= ~4;
+-	error_code |= (regs->xcs & 2) << 1;
+-	if (regs->eflags & X86_EFLAGS_VM)
+-		error_code |= 4;
+-
+-	tsk = current;
+-
+-	si_code = SEGV_MAPERR;
+-
+-	/*
+-	 * We fault-in kernel-space virtual memory on-demand. The
+-	 * 'reference' page table is init_mm.pgd.
+-	 *
+-	 * NOTE! We MUST NOT take any locks for this case. We may
+-	 * be in an interrupt or a critical region, and should
+-	 * only copy the information from the master page table,
+-	 * nothing more.
+-	 *
+-	 * This verifies that the fault happens in kernel space
+-	 * (error_code & 4) == 0, and that the fault was not a
+-	 * protection error (error_code & 9) == 0.
+-	 */
+-	if (unlikely(address >= TASK_SIZE)) {
+-#ifdef CONFIG_XEN
+-		/* Faults in hypervisor area can never be patched up. */
+-		if (address >= hypervisor_virt_start)
+-			goto bad_area_nosemaphore;
+-#endif
+-		if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
+-			return;
+-		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+-		if (spurious_fault(regs, address, error_code))
+-			return;
+-		if (notify_page_fault(regs))
+-			return;
+-		/* 
+-		 * Don't take the mm semaphore here. If we fixup a prefetch
+-		 * fault we could otherwise deadlock.
+-		 */
+-		goto bad_area_nosemaphore;
+-	}
+-
+-	if (notify_page_fault(regs))
+-		return;
+-
+-	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+-	   fault has been handled. */
+-	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
+-		local_irq_enable();
+-
+-	mm = tsk->mm;
+-
+-	/*
+-	 * If we're in an interrupt, have no user context or are running in an
+-	 * atomic region then we must not take the fault..
+-	 */
+-	if (in_atomic() || !mm)
+-		goto bad_area_nosemaphore;
+-
+-	/* When running in the kernel we expect faults to occur only to
+-	 * addresses in user space.  All other faults represent errors in the
+-	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+-	 * erroneous fault occurring in a code path which already holds mmap_sem
+-	 * we will deadlock attempting to validate the fault against the
+-	 * address space.  Luckily the kernel only validly references user
+-	 * space from well defined areas of code, which are listed in the
+-	 * exceptions table.
+-	 *
+-	 * As the vast majority of faults will be valid we will only perform
+-	 * the source reference check when there is a possibility of a deadlock.
+-	 * Attempt to lock the address space, if we cannot we then validate the
+-	 * source.  If this is invalid we can skip the address space check,
+-	 * thus avoiding the deadlock.
+-	 */
+-	if (!down_read_trylock(&mm->mmap_sem)) {
+-		if ((error_code & 4) == 0 &&
+-		    !search_exception_tables(regs->eip))
+-			goto bad_area_nosemaphore;
+-		down_read(&mm->mmap_sem);
+-	}
+-
+-	vma = find_vma(mm, address);
+-	if (!vma)
+-		goto bad_area;
+-	if (vma->vm_start <= address)
+-		goto good_area;
+-	if (!(vma->vm_flags & VM_GROWSDOWN))
+-		goto bad_area;
+-	if (error_code & 4) {
+-		/*
+-		 * Accessing the stack below %esp is always a bug.
+-		 * The large cushion allows instructions like enter
+-		 * and pusha to work.  ("enter $65535,$31" pushes
+-		 * 32 pointers and then decrements %esp by 65535.)
+-		 */
+-		if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp)
+-			goto bad_area;
+-	}
+-	if (expand_stack(vma, address))
+-		goto bad_area;
+-/*
+- * Ok, we have a good vm_area for this memory access, so
+- * we can handle it..
+- */
+-good_area:
+-	si_code = SEGV_ACCERR;
+-	write = 0;
+-	switch (error_code & 3) {
+-		default:	/* 3: write, present */
+-				/* fall through */
+-		case 2:		/* write, not present */
+-			if (!(vma->vm_flags & VM_WRITE))
+-				goto bad_area;
+-			write++;
+-			break;
+-		case 1:		/* read, present */
+-			goto bad_area;
+-		case 0:		/* read, not present */
+-			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+-				goto bad_area;
+-	}
+-
+- survive:
+-	/*
+-	 * If for any reason at all we couldn't handle the fault,
+-	 * make sure we exit gracefully rather than endlessly redo
+-	 * the fault.
+-	 */
+-	fault = handle_mm_fault(mm, vma, address, write);
+-	if (unlikely(fault & VM_FAULT_ERROR)) {
+-		if (fault & VM_FAULT_OOM)
+-			goto out_of_memory;
+-		else if (fault & VM_FAULT_SIGBUS)
+-			goto do_sigbus;
+-		BUG();
+-	}
+-	if (fault & VM_FAULT_MAJOR)
+-		tsk->maj_flt++;
+-	else
+-		tsk->min_flt++;
+-
+-	/*
+-	 * Did it hit the DOS screen memory VA from vm86 mode?
+-	 */
+-	if (regs->eflags & VM_MASK) {
+-		unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
+-		if (bit < 32)
+-			tsk->thread.screen_bitmap |= 1 << bit;
+-	}
+-	up_read(&mm->mmap_sem);
+-	return;
+-
+-/*
+- * Something tried to access memory that isn't in our memory map..
+- * Fix it, but check if it's kernel or user first..
+- */
+-bad_area:
+-	up_read(&mm->mmap_sem);
+-
+-bad_area_nosemaphore:
+-	/* User mode accesses just cause a SIGSEGV */
+-	if (error_code & 4) {
+-		/*
+-		 * It's possible to have interrupts off here.
+-		 */
+-		local_irq_enable();
+-
+-		/* 
+-		 * Valid to do another page fault here because this one came 
+-		 * from user space.
+-		 */
+-		if (is_prefetch(regs, address, error_code))
+-			return;
+-
+-		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-		    printk_ratelimit()) {
+-			printk("%s%s[%d]: segfault at %08lx eip %08lx "
+-			    "esp %08lx error %lx\n",
+-			    task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+-			    tsk->comm, task_pid_nr(tsk), address, regs->eip,
+-			    regs->esp, error_code);
+-		}
+-		tsk->thread.cr2 = address;
+-		/* Kernel addresses are always protection faults */
+-		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+-		tsk->thread.trap_no = 14;
+-		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+-		return;
+-	}
+-
+-#ifdef CONFIG_X86_F00F_BUG
+-	/*
+-	 * Pentium F0 0F C7 C8 bug workaround.
+-	 */
+-	if (boot_cpu_data.f00f_bug) {
+-		unsigned long nr;
+-		
+-		nr = (address - idt_descr.address) >> 3;
+-
+-		if (nr == 6) {
+-			do_invalid_op(regs, 0);
+-			return;
+-		}
+-	}
+-#endif
+-
+-no_context:
+-	/* Are we prepared to handle this kernel fault?  */
+-	if (fixup_exception(regs))
+-		return;
+-
+-	/* 
+-	 * Valid to do another page fault here, because if this fault
+-	 * had been triggered by is_prefetch fixup_exception would have 
+-	 * handled it.
+-	 */
+- 	if (is_prefetch(regs, address, error_code))
+- 		return;
+-
+-/*
+- * Oops. The kernel tried to access some bad page. We'll have to
+- * terminate things with extreme prejudice.
+- */
+-
+-	bust_spinlocks(1);
+-
+-	if (oops_may_print()) {
+-#ifdef CONFIG_X86_PAE
+-		if (error_code & 16) {
+-			pte_t *pte = lookup_address(address);
+-
+-			if (pte && pte_present(*pte) && !pte_exec_kernel(*pte))
+-				printk(KERN_CRIT "kernel tried to execute "
+-					"NX-protected page - exploit attempt? "
+-					"(uid: %d)\n", current->uid);
+-		}
+-#endif
+-		if (address < PAGE_SIZE)
+-			printk(KERN_ALERT "BUG: unable to handle kernel NULL "
+-					"pointer dereference");
+-		else
+-			printk(KERN_ALERT "BUG: unable to handle kernel paging"
+-					" request");
+-		printk(" at virtual address %08lx\n",address);
+-		printk(KERN_ALERT "printing eip: %08lx\n", regs->eip);
+-		dump_fault_path(address);
+-	}
+-	tsk->thread.cr2 = address;
+-	tsk->thread.trap_no = 14;
+-	tsk->thread.error_code = error_code;
+-	die("Oops", regs, error_code);
+-	bust_spinlocks(0);
+-	do_exit(SIGKILL);
+-
+-/*
+- * We ran out of memory, or some other thing happened to us that made
+- * us unable to handle the page fault gracefully.
+- */
+-out_of_memory:
+-	up_read(&mm->mmap_sem);
+-	if (is_global_init(tsk)) {
+-		yield();
+-		down_read(&mm->mmap_sem);
+-		goto survive;
+-	}
+-	printk("VM: killing process %s\n", tsk->comm);
+-	if (error_code & 4)
+-		do_group_exit(SIGKILL);
+-	goto no_context;
+-
+-do_sigbus:
+-	up_read(&mm->mmap_sem);
+-
+-	/* Kernel mode? Handle exceptions or die */
+-	if (!(error_code & 4))
+-		goto no_context;
+-
+-	/* User space => ok to do another page fault */
+-	if (is_prefetch(regs, address, error_code))
+-		return;
+-
+-	tsk->thread.cr2 = address;
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 14;
+-	force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
+-}
+-
+-void vmalloc_sync_all(void)
+-{
+-	/*
+-	 * Note that races in the updates of insync and start aren't
+-	 * problematic: insync can only get set bits added, and updates to
+-	 * start are only improving performance (without affecting correctness
+-	 * if undone).
+-	 * XEN: To work on PAE, we need to iterate over PMDs rather than PGDs.
+-	 *      This change works just fine with 2-level paging too.
+-	 */
+-#define sync_index(a) ((a) >> PMD_SHIFT)
+-	static DECLARE_BITMAP(insync, PTRS_PER_PGD*PTRS_PER_PMD);
+-	static unsigned long start = TASK_SIZE;
+-	unsigned long address;
+-
+-	if (SHARED_KERNEL_PMD)
+-		return;
+-
+-	BUILD_BUG_ON(TASK_SIZE & ~PGDIR_MASK);
+-	for (address = start;
+-	     address >= TASK_SIZE && address < hypervisor_virt_start;
+-	     address += 1UL << PMD_SHIFT) {
+-		if (!test_bit(sync_index(address), insync)) {
+-			unsigned long flags;
+-			struct page *page;
+-
+-			spin_lock_irqsave(&pgd_lock, flags);
+-			/* XEN: failure path assumes non-empty pgd_list. */
+-			if (unlikely(!pgd_list)) {
+-				spin_unlock_irqrestore(&pgd_lock, flags);
+-				return;
+-			}
+-			for (page = pgd_list; page; page =
+-					(struct page *)page->index)
+-				if (!vmalloc_sync_one(page_address(page),
+-								address)) {
+-					BUG_ON(page != pgd_list);
+-					break;
+-				}
+-			spin_unlock_irqrestore(&pgd_lock, flags);
+-			if (!page)
+-				set_bit(sync_index(address), insync);
+-		}
+-		if (address == start && test_bit(sync_index(address), insync))
+-			start = address + (1UL << PMD_SHIFT);
+-	}
+-}
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,686 +0,0 @@
+-/*
+- *  linux/arch/x86-64/mm/fault.c
+- *
+- *  Copyright (C) 1995  Linus Torvalds
+- *  Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
+- */
+-
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/kernel.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+-#include <linux/ptrace.h>
+-#include <linux/mman.h>
+-#include <linux/mm.h>
+-#include <linux/smp.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/tty.h>
+-#include <linux/vt_kern.h>		/* For unblank_screen() */
+-#include <linux/compiler.h>
+-#include <linux/vmalloc.h>
+-#include <linux/module.h>
+-#include <linux/kprobes.h>
+-#include <linux/uaccess.h>
+-#include <linux/kdebug.h>
+-#include <linux/kprobes.h>
+-
+-#include <asm/system.h>
+-#include <asm/pgalloc.h>
+-#include <asm/smp.h>
+-#include <asm/tlbflush.h>
+-#include <asm/proto.h>
+-#include <asm-generic/sections.h>
+-
+-/* Page fault error code bits */
+-#define PF_PROT	(1<<0)		/* or no page found */
+-#define PF_WRITE	(1<<1)
+-#define PF_USER	(1<<2)
+-#define PF_RSVD	(1<<3)
+-#define PF_INSTR	(1<<4)
+-
+-#ifdef CONFIG_KPROBES
+-static inline int notify_page_fault(struct pt_regs *regs)
+-{
+-	int ret = 0;
+-
+-	/* kprobe_running() needs smp_processor_id() */
+-	if (!user_mode(regs)) {
+-		preempt_disable();
+-		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+-			ret = 1;
+-		preempt_enable();
+-	}
+-
+-	return ret;
+-}
+-#else
+-static inline int notify_page_fault(struct pt_regs *regs)
+-{
+-	return 0;
+-}
+-#endif
+-
+-/* Sometimes the CPU reports invalid exceptions on prefetch.
+-   Check that here and ignore.
+-   Opcode checker based on code by Richard Brunner */
+-static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+-				unsigned long error_code)
+-{ 
+-	unsigned char *instr;
+-	int scan_more = 1;
+-	int prefetch = 0; 
+-	unsigned char *max_instr;
+-
+-	/* If it was a exec fault ignore */
+-	if (error_code & PF_INSTR)
+-		return 0;
+-	
+-	instr = (unsigned char __user *)convert_rip_to_linear(current, regs);
+-	max_instr = instr + 15;
+-
+-	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+-		return 0;
+-
+-	while (scan_more && instr < max_instr) { 
+-		unsigned char opcode;
+-		unsigned char instr_hi;
+-		unsigned char instr_lo;
+-
+-		if (probe_kernel_address(instr, opcode))
+-			break; 
+-
+-		instr_hi = opcode & 0xf0; 
+-		instr_lo = opcode & 0x0f; 
+-		instr++;
+-
+-		switch (instr_hi) { 
+-		case 0x20:
+-		case 0x30:
+-			/* Values 0x26,0x2E,0x36,0x3E are valid x86
+-			   prefixes.  In long mode, the CPU will signal
+-			   invalid opcode if some of these prefixes are
+-			   present so we will never get here anyway */
+-			scan_more = ((instr_lo & 7) == 0x6);
+-			break;
+-			
+-		case 0x40:
+-			/* In AMD64 long mode, 0x40 to 0x4F are valid REX prefixes
+-			   Need to figure out under what instruction mode the
+-			   instruction was issued ... */
+-			/* Could check the LDT for lm, but for now it's good
+-			   enough to assume that long mode only uses well known
+-			   segments or kernel. */
+-			scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
+-			break;
+-			
+-		case 0x60:
+-			/* 0x64 thru 0x67 are valid prefixes in all modes. */
+-			scan_more = (instr_lo & 0xC) == 0x4;
+-			break;		
+-		case 0xF0:
+-			/* 0xF0, 0xF2, and 0xF3 are valid prefixes in all modes. */
+-			scan_more = !instr_lo || (instr_lo>>1) == 1;
+-			break;			
+-		case 0x00:
+-			/* Prefetch instruction is 0x0F0D or 0x0F18 */
+-			scan_more = 0;
+-			if (probe_kernel_address(instr, opcode))
+-				break;
+-			prefetch = (instr_lo == 0xF) &&
+-				(opcode == 0x0D || opcode == 0x18);
+-			break;			
+-		default:
+-			scan_more = 0;
+-			break;
+-		} 
+-	}
+-	return prefetch;
+-}
+-
+-static int bad_address(void *p) 
+-{ 
+-	unsigned long dummy;
+-	return probe_kernel_address((unsigned long *)p, dummy);
+-} 
+-
+-void dump_pagetable(unsigned long address)
+-{
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
+-
+-	pgd = (pgd_t *)read_cr3();
+-
+-	pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
+-	pgd += pgd_index(address);
+-	if (bad_address(pgd)) goto bad;
+-	printk("PGD %lx ", pgd_val(*pgd));
+-	if (!pgd_present(*pgd)) goto ret; 
+-
+-	pud = pud_offset(pgd, address);
+-	if (bad_address(pud)) goto bad;
+-	printk("PUD %lx ", pud_val(*pud));
+-	if (!pud_present(*pud))	goto ret;
+-
+-	pmd = pmd_offset(pud, address);
+-	if (bad_address(pmd)) goto bad;
+-	printk("PMD %lx ", pmd_val(*pmd));
+-	if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
+-
+-	pte = pte_offset_kernel(pmd, address);
+-	if (bad_address(pte)) goto bad;
+-	printk("PTE %lx", pte_val(*pte)); 
+-ret:
+-	printk("\n");
+-	return;
+-bad:
+-	printk("BAD\n");
+-}
+-
+-static const char errata93_warning[] = 
+-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
+-KERN_ERR "******* Please consider a BIOS update.\n"
+-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+-
+-/* Workaround for K8 erratum #93 & buggy BIOS.
+-   BIOS SMM functions are required to use a specific workaround
+-   to avoid corruption of the 64bit RIP register on C stepping K8. 
+-   A lot of BIOS that didn't get tested properly miss this. 
+-   The OS sees this as a page fault with the upper 32bits of RIP cleared.
+-   Try to work around it here.
+-   Note we only handle faults in kernel here. */
+-
+-static int is_errata93(struct pt_regs *regs, unsigned long address) 
+-{
+-	static int warned;
+-	if (address != regs->rip)
+-		return 0;
+-	if ((address >> 32) != 0) 
+-		return 0;
+-	address |= 0xffffffffUL << 32;
+-	if ((address >= (u64)_stext && address <= (u64)_etext) || 
+-	    (address >= MODULES_VADDR && address <= MODULES_END)) { 
+-		if (!warned) {
+-			printk(errata93_warning); 		
+-			warned = 1;
+-		}
+-		regs->rip = address;
+-		return 1;
+-	}
+-	return 0;
+-} 
+-
+-static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
+-				 unsigned long error_code)
+-{
+-	unsigned long flags = oops_begin();
+-	struct task_struct *tsk;
+-
+-	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+-	       current->comm, address);
+-	dump_pagetable(address);
+-	tsk = current;
+-	tsk->thread.cr2 = address;
+-	tsk->thread.trap_no = 14;
+-	tsk->thread.error_code = error_code;
+-	__die("Bad pagetable", regs, error_code);
+-	oops_end(flags);
+-	do_exit(SIGKILL);
+-}
+-
+-/*
+- * Handle a fault on the vmalloc area
+- *
+- * This assumes no large pages in there.
+- */
+-static int vmalloc_fault(unsigned long address)
+-{
+-	pgd_t *pgd, *pgd_ref;
+-	pud_t *pud, *pud_ref;
+-	pmd_t *pmd, *pmd_ref;
+-	pte_t *pte, *pte_ref;
+-
+-	/* Copy kernel mappings over when needed. This can also
+-	   happen within a race in page table update. In the later
+-	   case just flush. */
+-
+-	/* On Xen the line below does not always work. Needs investigating! */
+-	/*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
+-	pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+-	pgd += pgd_index(address);
+-	pgd_ref = pgd_offset_k(address);
+-	if (pgd_none(*pgd_ref))
+-		return -1;
+-	if (pgd_none(*pgd))
+-		set_pgd(pgd, *pgd_ref);
+-	else
+-		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+-
+-	/* Below here mismatches are bugs because these lower tables
+-	   are shared */
+-
+-	pud = pud_offset(pgd, address);
+-	pud_ref = pud_offset(pgd_ref, address);
+-	if (pud_none(*pud_ref))
+-		return -1;
+-	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+-		BUG();
+-	pmd = pmd_offset(pud, address);
+-	pmd_ref = pmd_offset(pud_ref, address);
+-	if (pmd_none(*pmd_ref))
+-		return -1;
+-	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
+-		BUG();
+-	pte_ref = pte_offset_kernel(pmd_ref, address);
+-	if (!pte_present(*pte_ref))
+-		return -1;
+-	pte = pte_offset_kernel(pmd, address);
+-	/* Don't use pte_page here, because the mappings can point
+-	   outside mem_map, and the NUMA hash lookup cannot handle
+-	   that. */
+-	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
+-		BUG();
+-	return 0;
+-}
+-
+-int show_unhandled_signals = 1;
+-
+-
+-#define MEM_VERBOSE 1
+-
+-#ifdef MEM_VERBOSE
+-#define MEM_LOG(_f, _a...)			\
+-	printk("fault.c:[%d]-> " _f "\n",	\
+-	__LINE__ , ## _a )
+-#else
+-#define MEM_LOG(_f, _a...) ((void)0)
+-#endif
+-
+-static int spurious_fault(struct pt_regs *regs,
+-			  unsigned long address,
+-			  unsigned long error_code)
+-{
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
+-
+-#ifdef CONFIG_XEN
+-	/* Faults in hypervisor area are never spurious. */
+-	if ((address >= HYPERVISOR_VIRT_START) &&
+-	    (address < HYPERVISOR_VIRT_END))
+-		return 0;
+-#endif
+-
+-	/* Reserved-bit violation or user access to kernel space? */
+-	if (error_code & (PF_RSVD|PF_USER))
+-		return 0;
+-
+-	pgd = init_mm.pgd + pgd_index(address);
+-	if (!pgd_present(*pgd))
+-		return 0;
+-
+-	pud = pud_offset(pgd, address);
+-	if (!pud_present(*pud))
+-		return 0;
+-
+-	pmd = pmd_offset(pud, address);
+-	if (!pmd_present(*pmd))
+-		return 0;
+-
+-	pte = pte_offset_kernel(pmd, address);
+-	if (!pte_present(*pte))
+-		return 0;
+-	if ((error_code & PF_WRITE) && !pte_write(*pte))
+-		return 0;
+-	if ((error_code & PF_INSTR) && (__pte_val(*pte) & _PAGE_NX))
+-		return 0;
+-
+-	return 1;
+-}
+-
+-/*
+- * This routine handles page faults.  It determines the address,
+- * and the problem, and then passes it off to one of the appropriate
+- * routines.
+- */
+-asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+-					unsigned long error_code)
+-{
+-	struct task_struct *tsk;
+-	struct mm_struct *mm;
+-	struct vm_area_struct * vma;
+-	unsigned long address;
+-	const struct exception_table_entry *fixup;
+-	int write, fault;
+-	unsigned long flags;
+-	siginfo_t info;
+-
+-	if (!user_mode(regs))
+-		error_code &= ~PF_USER; /* means kernel */
+-
+-	/*
+-	 * We can fault from pretty much anywhere, with unknown IRQ state.
+-	 */
+-	trace_hardirqs_fixup();
+-
+-	tsk = current;
+-	mm = tsk->mm;
+-	prefetchw(&mm->mmap_sem);
+-
+-	/* get the address */
+-	address = read_cr2();
+-
+-	info.si_code = SEGV_MAPERR;
+-
+-
+-	/*
+-	 * We fault-in kernel-space virtual memory on-demand. The
+-	 * 'reference' page table is init_mm.pgd.
+-	 *
+-	 * NOTE! We MUST NOT take any locks for this case. We may
+-	 * be in an interrupt or a critical region, and should
+-	 * only copy the information from the master page table,
+-	 * nothing more.
+-	 *
+-	 * This verifies that the fault happens in kernel space
+-	 * (error_code & 4) == 0, and that the fault was not a
+-	 * protection error (error_code & 9) == 0.
+-	 */
+-	if (unlikely(address >= TASK_SIZE64)) {
+-		/*
+-		 * Don't check for the module range here: its PML4
+-		 * is always initialized because it's shared with the main
+-		 * kernel text. Only vmalloc may need PML4 syncups.
+-		 */
+-		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
+-		      ((address >= VMALLOC_START && address < VMALLOC_END))) {
+-			if (vmalloc_fault(address) >= 0)
+-				return;
+-		}
+-		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+-		if (spurious_fault(regs, address, error_code))
+-			return;
+-		if (notify_page_fault(regs))
+-			return;
+-		/*
+-		 * Don't take the mm semaphore here. If we fixup a prefetch
+-		 * fault we could otherwise deadlock.
+-		 */
+-		goto bad_area_nosemaphore;
+-	}
+-
+-	if (notify_page_fault(regs))
+-		return;
+-
+-	if (likely(regs->eflags & X86_EFLAGS_IF))
+-		local_irq_enable();
+-
+-	if (unlikely(error_code & PF_RSVD))
+-		pgtable_bad(address, regs, error_code);
+-
+-	/*
+-	 * If we're in an interrupt or have no user
+-	 * context, we must not take the fault..
+-	 */
+-	if (unlikely(in_atomic() || !mm))
+-		goto bad_area_nosemaphore;
+-
+-	/*
+-	 * User-mode registers count as a user access even for any
+-	 * potential system fault or CPU buglet.
+-	 */
+-	if (user_mode_vm(regs))
+-		error_code |= PF_USER;
+-
+- again:
+-	/* When running in the kernel we expect faults to occur only to
+-	 * addresses in user space.  All other faults represent errors in the
+-	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+-	 * erroneous fault occurring in a code path which already holds mmap_sem
+-	 * we will deadlock attempting to validate the fault against the
+-	 * address space.  Luckily the kernel only validly references user
+-	 * space from well defined areas of code, which are listed in the
+-	 * exceptions table.
+-	 *
+-	 * As the vast majority of faults will be valid we will only perform
+-	 * the source reference check when there is a possibility of a deadlock.
+-	 * Attempt to lock the address space, if we cannot we then validate the
+-	 * source.  If this is invalid we can skip the address space check,
+-	 * thus avoiding the deadlock.
+-	 */
+-	if (!down_read_trylock(&mm->mmap_sem)) {
+-		if ((error_code & PF_USER) == 0 &&
+-		    !search_exception_tables(regs->rip))
+-			goto bad_area_nosemaphore;
+-		down_read(&mm->mmap_sem);
+-	}
+-
+-	vma = find_vma(mm, address);
+-	if (!vma)
+-		goto bad_area;
+-	if (likely(vma->vm_start <= address))
+-		goto good_area;
+-	if (!(vma->vm_flags & VM_GROWSDOWN))
+-		goto bad_area;
+-	if (error_code & 4) {
+-		/* Allow userspace just enough access below the stack pointer
+-		 * to let the 'enter' instruction work.
+-		 */
+-		if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp)
+-			goto bad_area;
+-	}
+-	if (expand_stack(vma, address))
+-		goto bad_area;
+-/*
+- * Ok, we have a good vm_area for this memory access, so
+- * we can handle it..
+- */
+-good_area:
+-	info.si_code = SEGV_ACCERR;
+-	write = 0;
+-	switch (error_code & (PF_PROT|PF_WRITE)) {
+-		default:	/* 3: write, present */
+-			/* fall through */
+-		case PF_WRITE:		/* write, not present */
+-			if (!(vma->vm_flags & VM_WRITE))
+-				goto bad_area;
+-			write++;
+-			break;
+-		case PF_PROT:		/* read, present */
+-			goto bad_area;
+-		case 0:			/* read, not present */
+-			if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+-				goto bad_area;
+-	}
+-
+-	/*
+-	 * If for any reason at all we couldn't handle the fault,
+-	 * make sure we exit gracefully rather than endlessly redo
+-	 * the fault.
+-	 */
+-	fault = handle_mm_fault(mm, vma, address, write);
+-	if (unlikely(fault & VM_FAULT_ERROR)) {
+-		if (fault & VM_FAULT_OOM)
+-			goto out_of_memory;
+-		else if (fault & VM_FAULT_SIGBUS)
+-			goto do_sigbus;
+-		BUG();
+-	}
+-	if (fault & VM_FAULT_MAJOR)
+-		tsk->maj_flt++;
+-	else
+-		tsk->min_flt++;
+-	up_read(&mm->mmap_sem);
+-	return;
+-
+-/*
+- * Something tried to access memory that isn't in our memory map..
+- * Fix it, but check if it's kernel or user first..
+- */
+-bad_area:
+-	up_read(&mm->mmap_sem);
+-
+-bad_area_nosemaphore:
+-	/* User mode accesses just cause a SIGSEGV */
+-	if (error_code & PF_USER) {
+-
+-		/*
+-		 * It's possible to have interrupts off here.
+-		 */
+-		local_irq_enable();
+-
+-		if (is_prefetch(regs, address, error_code))
+-			return;
+-
+-		/* Work around K8 erratum #100 K8 in compat mode
+-		   occasionally jumps to illegal addresses >4GB.  We
+-		   catch this here in the page fault handler because
+-		   these addresses are not reachable. Just detect this
+-		   case and return.  Any code segment in LDT is
+-		   compatibility mode. */
+-		if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
+-		    (address >> 32))
+-			return;
+-
+-		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-		    printk_ratelimit()) {
+-			printk(
+-		       "%s%s[%d]: segfault at %lx rip %lx rsp %lx error %lx\n",
+-					tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
+-					tsk->comm, tsk->pid, address, regs->rip,
+-					regs->rsp, error_code);
+-		}
+-       
+-		tsk->thread.cr2 = address;
+-		/* Kernel addresses are always protection faults */
+-		tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+-		tsk->thread.trap_no = 14;
+-		info.si_signo = SIGSEGV;
+-		info.si_errno = 0;
+-		/* info.si_code has been set above */
+-		info.si_addr = (void __user *)address;
+-		force_sig_info(SIGSEGV, &info, tsk);
+-		return;
+-	}
+-
+-no_context:
+-	
+-	/* Are we prepared to handle this kernel fault?  */
+-	fixup = search_exception_tables(regs->rip);
+-	if (fixup) {
+-		regs->rip = fixup->fixup;
+-		return;
+-	}
+-
+-	/* 
+-	 * Hall of shame of CPU/BIOS bugs.
+-	 */
+-
+- 	if (is_prefetch(regs, address, error_code))
+- 		return;
+-
+-	if (is_errata93(regs, address))
+-		return; 
+-
+-/*
+- * Oops. The kernel tried to access some bad page. We'll have to
+- * terminate things with extreme prejudice.
+- */
+-
+-	flags = oops_begin();
+-
+-	if (address < PAGE_SIZE)
+-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+-	else
+-		printk(KERN_ALERT "Unable to handle kernel paging request");
+-	printk(" at %016lx RIP: \n" KERN_ALERT,address);
+-	printk_address(regs->rip);
+-	dump_pagetable(address);
+-	tsk->thread.cr2 = address;
+-	tsk->thread.trap_no = 14;
+-	tsk->thread.error_code = error_code;
+-	__die("Oops", regs, error_code);
+-	/* Executive summary in case the body of the oops scrolled away */
+-	printk(KERN_EMERG "CR2: %016lx\n", address);
+-	oops_end(flags);
+-	do_exit(SIGKILL);
+-
+-/*
+- * We ran out of memory, or some other thing happened to us that made
+- * us unable to handle the page fault gracefully.
+- */
+-out_of_memory:
+-	up_read(&mm->mmap_sem);
+-	if (is_global_init(current)) {
+-		yield();
+-		goto again;
+-	}
+-	printk("VM: killing process %s\n", tsk->comm);
+-	if (error_code & 4)
+-		do_group_exit(SIGKILL);
+-	goto no_context;
+-
+-do_sigbus:
+-	up_read(&mm->mmap_sem);
+-
+-	/* Kernel mode? Handle exceptions or die */
+-	if (!(error_code & PF_USER))
+-		goto no_context;
+-
+-	tsk->thread.cr2 = address;
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 14;
+-	info.si_signo = SIGBUS;
+-	info.si_errno = 0;
+-	info.si_code = BUS_ADRERR;
+-	info.si_addr = (void __user *)address;
+-	force_sig_info(SIGBUS, &info, tsk);
+-	return;
+-}
+-
+-DEFINE_SPINLOCK(pgd_lock);
+-LIST_HEAD(pgd_list);
+-
+-void vmalloc_sync_all(void)
+-{
+-	/* Note that races in the updates of insync and start aren't 
+-	   problematic:
+-	   insync can only get set bits added, and updates to start are only
+-	   improving performance (without affecting correctness if undone). */
+-	static DECLARE_BITMAP(insync, PTRS_PER_PGD);
+-	static unsigned long start = VMALLOC_START & PGDIR_MASK;
+-	unsigned long address;
+-
+-	for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
+-		if (!test_bit(pgd_index(address), insync)) {
+-			const pgd_t *pgd_ref = pgd_offset_k(address);
+-			struct page *page;
+-
+-			if (pgd_none(*pgd_ref))
+-				continue;
+-			spin_lock(&pgd_lock);
+-			list_for_each_entry(page, &pgd_list, lru) {
+-				pgd_t *pgd;
+-				pgd = (pgd_t *)page_address(page) + pgd_index(address);
+-				if (pgd_none(*pgd))
+-					set_pgd(pgd, *pgd_ref);
+-				else
+-					BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+-			}
+-			spin_unlock(&pgd_lock);
+-			set_bit(pgd_index(address), insync);
+-		}
+-		if (address == start)
+-			start = address + PGDIR_SIZE;
+-	}
+-	/* Check that there is no need to do the same for the modules area. */
+-	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+-	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == 
+-				(__START_KERNEL & PGDIR_MASK)));
+-}
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -18,6 +18,49 @@ void kunmap(struct page *page)
+ 	kunmap_high(page);
+ }
+ 
++static void debug_kmap_atomic_prot(enum km_type type)
++{
++#ifdef CONFIG_DEBUG_HIGHMEM
++	static unsigned warn_count = 10;
++
++	if (unlikely(warn_count == 0))
++		return;
++
++	if (unlikely(in_interrupt())) {
++		if (in_irq()) {
++			if (type != KM_IRQ0 && type != KM_IRQ1 &&
++			    type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ &&
++			    type != KM_BOUNCE_READ) {
++				WARN_ON(1);
++				warn_count--;
++			}
++		} else if (!irqs_disabled()) {	/* softirq */
++			if (type != KM_IRQ0 && type != KM_IRQ1 &&
++			    type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
++			    type != KM_SKB_SUNRPC_DATA &&
++			    type != KM_SKB_DATA_SOFTIRQ &&
++			    type != KM_BOUNCE_READ) {
++				WARN_ON(1);
++				warn_count--;
++			}
++		}
++	}
++
++	if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
++			type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ) {
++		if (!irqs_disabled()) {
++			WARN_ON(1);
++			warn_count--;
++		}
++	} else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
++		if (irq_count() == 0 && !irqs_disabled()) {
++			WARN_ON(1);
++			warn_count--;
++		}
++	}
++#endif
++}
++
+ /*
+  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+  * no global lock is needed and because the kmap code must perform a global TLB
+@@ -37,6 +80,8 @@ void *kmap_atomic_prot(struct page *page
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
++	debug_kmap_atomic_prot(type);
++
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	BUG_ON(!pte_none(*(kmap_pte-idx)));
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:51:25.000000000 +0100
+@@ -873,15 +873,11 @@ int xen_limit_pages_to_max_mfn(
+ }
+ EXPORT_SYMBOL_GPL(xen_limit_pages_to_max_mfn);
+ 
+-#ifdef __i386__
+-int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
++int write_ldt_entry(struct desc_struct *ldt, int entry, const void *desc)
+ {
+-	__u32 *lp = (__u32 *)((char *)ldt + entry * 8);
+-	maddr_t mach_lp = arbitrary_virt_to_machine(lp);
+-	return HYPERVISOR_update_descriptor(
+-		mach_lp, (u64)entry_a | ((u64)entry_b<<32));
++	maddr_t mach_lp = arbitrary_virt_to_machine(ldt + entry);
++	return HYPERVISOR_update_descriptor(mach_lp, *(const u64*)desc);
+ }
+-#endif
+ 
+ #define MAX_BATCHED_FULL_PTES 32
+ 
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -27,13 +27,13 @@
+ #include <linux/bootmem.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
+-#include <linux/efi.h>
+ #include <linux/memory_hotplug.h>
+ #include <linux/initrd.h>
+ #include <linux/cpumask.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/scatterlist.h>
+ 
++#include <asm/asm.h>
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -42,18 +42,22 @@
+ #include <asm/fixmap.h>
+ #include <asm/e820.h>
+ #include <asm/apic.h>
++#include <asm/bugs.h>
+ #include <asm/tlb.h>
+ #include <asm/tlbflush.h>
++#include <asm/pgalloc.h>
+ #include <asm/sections.h>
+ #include <asm/hypervisor.h>
+ #include <asm/swiotlb.h>
++#include <asm/setup.h>
++#include <asm/cacheflush.h>
+ 
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+ 
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+ 
+-static int noinline do_test_wp_bit(void);
++static noinline int do_test_wp_bit(void);
+ 
+ /*
+  * Creates a middle page table and puts a pointer to it in the
+@@ -64,17 +68,16 @@ static pmd_t * __init one_md_table_init(
+ {
+ 	pud_t *pud;
+ 	pmd_t *pmd_table;
+-		
++
+ #ifdef CONFIG_X86_PAE
+ 	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+ 		pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ 
+-		paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
++		paravirt_alloc_pd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+ 		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ 		pud = pud_offset(pgd, 0);
+-		if (pmd_table != pmd_offset(pud, 0))
+-			BUG();
++		BUG_ON(pmd_table != pmd_offset(pud, 0));
+ 	}
+ #endif
+ 	pud = pud_offset(pgd, 0);
+@@ -85,7 +88,7 @@ static pmd_t * __init one_md_table_init(
+ 
+ /*
+  * Create a page table and place a pointer to it in a middle page
+- * directory entry.
++ * directory entry:
+  */
+ static pte_t * __init one_page_table_init(pmd_t *pmd)
+ {
+@@ -99,9 +102,10 @@ static pte_t * __init one_page_table_ini
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+ 		page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+ #endif
+-		if (!page_table)
++		if (!page_table) {
+ 			page_table =
+ 				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
++		}
+ 
+ 		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+@@ -114,22 +118,21 @@ static pte_t * __init one_page_table_ini
+ }
+ 
+ /*
+- * This function initializes a certain range of kernel virtual memory 
++ * This function initializes a certain range of kernel virtual memory
+  * with new bootmem page tables, everywhere page tables are missing in
+  * the given range.
+- */
+-
+-/*
+- * NOTE: The pagetables are allocated contiguous on the physical space 
+- * so we can cache the place of the first one and move around without 
++ *
++ * NOTE: The pagetables are allocated contiguous on the physical space
++ * so we can cache the place of the first one and move around without
+  * checking the pgd every time.
+  */
+-static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
++static void __init
++page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
+ {
+-	pgd_t *pgd;
+-	pmd_t *pmd;
+ 	int pgd_idx, pmd_idx;
+ 	unsigned long vaddr;
++	pgd_t *pgd;
++	pmd_t *pmd;
+ 
+ 	vaddr = start;
+ 	pgd_idx = pgd_index(vaddr);
+@@ -139,7 +142,8 @@ static void __init page_table_range_init
+ 	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+ 		pmd = one_md_table_init(pgd);
+ 		pmd = pmd + pmd_index(vaddr);
+-		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
++		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
++							pmd++, pmd_idx++) {
+ 			if (vaddr < hypervisor_virt_start)
+ 				one_page_table_init(pmd);
+ 
+@@ -157,17 +161,17 @@ static inline int is_kernel_text(unsigne
+ }
+ 
+ /*
+- * This maps the physical memory to kernel virtual address space, a total 
+- * of max_low_pfn pages, by creating page tables starting from address 
+- * PAGE_OFFSET.
++ * This maps the physical memory to kernel virtual address space, a total
++ * of max_low_pfn pages, by creating page tables starting from address
++ * PAGE_OFFSET:
+  */
+ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+ {
++	int pgd_idx, pmd_idx, pte_ofs;
+ 	unsigned long pfn;
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+-	int pgd_idx, pmd_idx, pte_ofs;
+ 
+ 	unsigned long max_ram_pfn = xen_start_info->nr_pages;
+ 	if (max_ram_pfn > max_low_pfn)
+@@ -195,36 +199,49 @@ static void __init kernel_physical_mappi
+ 		if (pfn >= max_low_pfn)
+ 			continue;
+ 		pmd += pmd_idx;
+-		for (; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
+-			unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
+-			if (address >= hypervisor_virt_start)
++		for (; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn;
++		     pmd++, pmd_idx++) {
++			unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET;
++
++			if (addr >= hypervisor_virt_start)
+ 				continue;
+ 
+-			/* Map with big pages if possible, otherwise create normal page tables. */
++			/*
++			 * Map with big pages if possible, otherwise
++			 * create normal page tables:
++			 */
+ 			if (cpu_has_pse) {
+-				unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
+-				if (is_kernel_text(address) || is_kernel_text(address2))
+-					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
+-				else
+-					set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
++				unsigned int addr2;
++				pgprot_t prot = PAGE_KERNEL_LARGE;
++
++				addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE +
++					PAGE_OFFSET + PAGE_SIZE-1;
++
++				if (is_kernel_text(addr) ||
++				    is_kernel_text(addr2))
++					prot = PAGE_KERNEL_LARGE_EXEC;
++
++				set_pmd(pmd, pfn_pmd(pfn, prot));
+ 
+ 				pfn += PTRS_PER_PTE;
+-			} else {
+-				pte = one_page_table_init(pmd);
++				continue;
++			}
++			pte = one_page_table_init(pmd);
++
++			for (pte += pte_ofs;
++			     pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
++			     pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) {
++				pgprot_t prot = PAGE_KERNEL;
++
++				/* XEN: Only map initial RAM allocation. */
++				if ((pfn >= max_ram_pfn) || pte_present(*pte))
++					continue;
++				if (is_kernel_text(addr))
++					prot = PAGE_KERNEL_EXEC;
+ 
+-				for (pte += pte_ofs;
+-				     pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
+-				     pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
+-					/* XEN: Only map initial RAM allocation. */
+-					if ((pfn >= max_ram_pfn) || pte_present(*pte))
+-						continue;
+-					if (is_kernel_text(address))
+-						set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+-					else
+-						set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
+-				}
+-				pte_ofs = 0;
++				set_pte(pte, pfn_pte(pfn, prot));
+ 			}
++			pte_ofs = 0;
+ 		}
+ 		pmd_idx = 0;
+ 	}
+@@ -245,57 +262,23 @@ static inline int page_kills_ppro(unsign
+ 
+ #endif
+ 
+-int page_is_ram(unsigned long pagenr)
+-{
+-	int i;
+-	unsigned long addr, end;
+-
+-	if (efi_enabled) {
+-		efi_memory_desc_t *md;
+-		void *p;
+-
+-		for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+-			md = p;
+-			if (!is_available_memory(md))
+-				continue;
+-			addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
+-			end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT;
+-
+-			if ((pagenr >= addr) && (pagenr < end))
+-				return 1;
+-		}
+-		return 0;
+-	}
+-
+-	for (i = 0; i < e820.nr_map; i++) {
+-
+-		if (e820.map[i].type != E820_RAM)	/* not usable memory */
+-			continue;
+-		/*
+-		 *	!!!FIXME!!! Some BIOSen report areas as RAM that
+-		 *	are not. Notably the 640->1Mb area. We need a sanity
+-		 *	check here.
+-		 */
+-		addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
+-		end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
+-		if  ((pagenr >= addr) && (pagenr < end))
+-			return 1;
+-	}
+-	return 0;
+-}
+-
+ #ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+ 
+-#define kmap_get_fixmap_pte(vaddr)					\
+-	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
++static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr)
++{
++	return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
++			vaddr), vaddr), vaddr);
++}
+ 
+ static void __init kmap_init(void)
+ {
+ 	unsigned long kmap_vstart;
+ 
+-	/* cache the first kmap pte */
++	/*
++	 * Cache the first kmap pte:
++	 */
+ 	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ 	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+ 
+@@ -304,11 +287,11 @@ static void __init kmap_init(void)
+ 
+ static void __init permanent_kmaps_init(pgd_t *pgd_base)
+ {
++	unsigned long vaddr;
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+-	unsigned long vaddr;
+ 
+ 	vaddr = PKMAP_BASE;
+ 	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+@@ -317,7 +300,7 @@ static void __init permanent_kmaps_init(
+ 	pud = pud_offset(pgd, vaddr);
+ 	pmd = pmd_offset(pud, vaddr);
+ 	pte = pte_offset_kernel(pmd, vaddr);
+-	pkmap_page_table = pte;	
++	pkmap_page_table = pte;
+ }
+ 
+ static void __meminit free_new_highpage(struct page *page, int pfn)
+@@ -336,7 +319,8 @@ void __init add_one_highpage_init(struct
+ 		SetPageReserved(page);
+ }
+ 
+-static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long pfn)
++static int __meminit
++add_one_highpage_hotplug(struct page *page, unsigned long pfn)
+ {
+ 	free_new_highpage(page, pfn);
+ 	totalram_pages++;
+@@ -344,6 +328,7 @@ static int __meminit add_one_highpage_ho
+ 	max_mapnr = max(pfn, max_mapnr);
+ #endif
+ 	num_physpages++;
++
+ 	return 0;
+ }
+ 
+@@ -351,7 +336,7 @@ static int __meminit add_one_highpage_ho
+  * Not currently handling the NUMA case.
+  * Assuming single node and all memory that
+  * has been added dynamically that would be
+- * onlined here is in HIGHMEM
++ * onlined here is in HIGHMEM.
+  */
+ void __meminit online_page(struct page *page)
+ {
+@@ -359,13 +344,11 @@ void __meminit online_page(struct page *
+ 	add_one_highpage_hotplug(page, page_to_pfn(page));
+ }
+ 
+-
+-#ifdef CONFIG_NUMA
+-extern void set_highmem_pages_init(int);
+-#else
++#ifndef CONFIG_NUMA
+ static void __init set_highmem_pages_init(int bad_ppro)
+ {
+ 	int pfn;
++
+ 	for (pfn = highstart_pfn; pfn < highend_pfn
+ 				  && pfn < xen_start_info->nr_pages; pfn++) {
+ 		/*
+@@ -383,23 +366,18 @@ static void __init set_highmem_pages_ini
+ 
+ 	totalram_pages += totalhigh_pages;
+ }
+-#endif /* CONFIG_FLATMEM */
++#endif /* !CONFIG_NUMA */
+ 
+ #else
+-#define kmap_init() do { } while (0)
+-#define permanent_kmaps_init(pgd_base) do { } while (0)
+-#define set_highmem_pages_init(bad_ppro) do { } while (0)
++# define kmap_init()				do { } while (0)
++# define permanent_kmaps_init(pgd_base)		do { } while (0)
++# define set_highmem_pages_init(bad_ppro)	do { } while (0)
+ #endif /* CONFIG_HIGHMEM */
+ 
+-unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;
++pteval_t __PAGE_KERNEL = _PAGE_KERNEL;
+ EXPORT_SYMBOL(__PAGE_KERNEL);
+-unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
+ 
+-#ifdef CONFIG_NUMA
+-extern void __init remap_numa_kva(void);
+-#else
+-#define remap_numa_kva() do {} while (0)
+-#endif
++pteval_t __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
+ 
+ pgd_t *swapper_pg_dir;
+ 
+@@ -417,9 +395,8 @@ static void __init xen_pagetable_setup_d
+  * the boot process.
+  *
+  * If we're booting on native hardware, this will be a pagetable
+- * constructed in arch/i386/kernel/head.S, and not running in PAE mode
+- * (even if we'll end up running in PAE).  The root of the pagetable
+- * will be swapper_pg_dir.
++ * constructed in arch/x86/kernel/head_32.S.  The root of the
++ * pagetable will be swapper_pg_dir.
+  *
+  * If we're booting paravirtualized under a hypervisor, then there are
+  * more options: we may already be running PAE, and the pagetable may
+@@ -431,10 +408,10 @@ static void __init xen_pagetable_setup_d
+  * be partially populated, and so it avoids stomping on any existing
+  * mappings.
+  */
+-static void __init pagetable_init (void)
++static void __init pagetable_init(void)
+ {
+-	unsigned long vaddr, end;
+ 	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
++	unsigned long vaddr, end;
+ 
+ 	xen_pagetable_setup_start(pgd_base);
+ 
+@@ -456,34 +433,36 @@ static void __init pagetable_init (void)
+ 	 * Fixed mappings, only the page table structure has to be
+ 	 * created - mappings will be set by set_fixmap():
+ 	 */
++	early_ioremap_clear();
+ 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ 	end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+ 	page_table_range_init(vaddr, end, pgd_base);
++	early_ioremap_reset();
+ 
+ 	permanent_kmaps_init(pgd_base);
+ 
+ 	xen_pagetable_setup_done(pgd_base);
+ }
+ 
+-#if defined(CONFIG_HIBERNATION) || defined(CONFIG_ACPI)
++#if defined(CONFIG_ACPI_SLEEP) && !defined(CONFIG_XEN)
+ /*
+- * Swap suspend & friends need this for resume because things like the intel-agp
++ * ACPI suspend needs this for resume, because things like the intel-agp
+  * driver might have split up a kernel 4MB mapping.
+  */
+-char __nosavedata swsusp_pg_dir[PAGE_SIZE]
+-	__attribute__ ((aligned (PAGE_SIZE)));
++char swsusp_pg_dir[PAGE_SIZE]
++	__attribute__ ((aligned(PAGE_SIZE)));
+ 
+ static inline void save_pg_dir(void)
+ {
+ 	memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
+ }
+-#else
++#else /* !CONFIG_ACPI_SLEEP */
+ static inline void save_pg_dir(void)
+ {
+ }
+-#endif
++#endif /* !CONFIG_ACPI_SLEEP */
+ 
+-void zap_low_mappings (void)
++void zap_low_mappings(void)
+ {
+ 	int i;
+ 
+@@ -495,22 +474,24 @@ void zap_low_mappings (void)
+ 	 * Note that "pgd_clear()" doesn't do it for
+ 	 * us, because pgd_clear() is a no-op on i386.
+ 	 */
+-	for (i = 0; i < USER_PTRS_PER_PGD; i++)
++	for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+ #if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
+ 		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
+ #else
+ 		set_pgd(swapper_pg_dir+i, __pgd(0));
+ #endif
++	}
+ 	flush_tlb_all();
+ }
+ 
+-int nx_enabled = 0;
++int nx_enabled;
++
++pteval_t __supported_pte_mask __read_mostly = ~_PAGE_NX;
++EXPORT_SYMBOL_GPL(__supported_pte_mask);
+ 
+ #ifdef CONFIG_X86_PAE
+ 
+-static int disable_nx __initdata = 0;
+-u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
+-EXPORT_SYMBOL_GPL(__supported_pte_mask);
++static int disable_nx __initdata;
+ 
+ /*
+  * noexec = on|off
+@@ -527,11 +508,14 @@ static int __init noexec_setup(char *str
+ 			__supported_pte_mask |= _PAGE_NX;
+ 			disable_nx = 0;
+ 		}
+-	} else if (!strcmp(str,"off")) {
+-		disable_nx = 1;
+-		__supported_pte_mask &= ~_PAGE_NX;
+-	} else
+-		return -EINVAL;
++	} else {
++		if (!strcmp(str, "off")) {
++			disable_nx = 1;
++			__supported_pte_mask &= ~_PAGE_NX;
++		} else {
++			return -EINVAL;
++		}
++	}
+ 
+ 	return 0;
+ }
+@@ -543,6 +527,7 @@ static void __init set_nx(void)
+ 
+ 	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
+ 		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
++
+ 		if ((v[3] & (1 << 20)) && !disable_nx) {
+ 			rdmsr(MSR_EFER, l, h);
+ 			l |= EFER_NX;
+@@ -552,35 +537,6 @@ static void __init set_nx(void)
+ 		}
+ 	}
+ }
+-
+-/*
+- * Enables/disables executability of a given kernel page and
+- * returns the previous setting.
+- */
+-int __init set_kernel_exec(unsigned long vaddr, int enable)
+-{
+-	pte_t *pte;
+-	int ret = 1;
+-
+-	if (!nx_enabled)
+-		goto out;
+-
+-	pte = lookup_address(vaddr);
+-	BUG_ON(!pte);
+-
+-	if (!pte_exec_kernel(*pte))
+-		ret = 0;
+-
+-	if (enable)
+-		pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));
+-	else
+-		pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);
+-	pte_update_defer(&init_mm, vaddr, pte);
+-	__flush_tlb_all();
+-out:
+-	return ret;
+-}
+-
+ #endif
+ 
+ /*
+@@ -597,21 +553,10 @@ void __init paging_init(void)
+ #ifdef CONFIG_X86_PAE
+ 	set_nx();
+ 	if (nx_enabled)
+-		printk("NX (Execute Disable) protection: active\n");
++		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+ #endif
+-
+ 	pagetable_init();
+ 
+-#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
+-	/*
+-	 * We will bail out later - printk doesn't work right now so
+-	 * the user would just see a hanging kernel.
+-	 * when running as xen domain we are already in PAE mode at
+-	 * this point.
+-	 */
+-	if (cpu_has_pae)
+-		set_in_cr4(X86_CR4_PAE);
+-#endif
+ 	__flush_tlb_all();
+ 
+ 	kmap_init();
+@@ -638,10 +583,10 @@ void __init paging_init(void)
+  * used to involve black magic jumps to work around some nasty CPU bugs,
+  * but fortunately the switch to using exceptions got rid of all that.
+  */
+-
+ static void __init test_wp_bit(void)
+ {
+-	printk("Checking if this processor honours the WP bit even in supervisor mode... ");
++	printk(KERN_INFO
++  "Checking if this processor honours the WP bit even in supervisor mode...");
+ 
+ 	/* Any page-aligned address will do, the test is non-destructive */
+ 	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
+@@ -649,23 +594,22 @@ static void __init test_wp_bit(void)
+ 	clear_fixmap(FIX_WP_TEST);
+ 
+ 	if (!boot_cpu_data.wp_works_ok) {
+-		printk("No.\n");
++		printk(KERN_CONT "No.\n");
+ #ifdef CONFIG_X86_WP_WORKS_OK
+-		panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
++		panic(
++  "This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
+ #endif
+ 	} else {
+-		printk("Ok.\n");
++		printk(KERN_CONT "Ok.\n");
+ 	}
+ }
+ 
+-static struct kcore_list kcore_mem, kcore_vmalloc; 
++static struct kcore_list kcore_mem, kcore_vmalloc;
+ 
+ void __init mem_init(void)
+ {
+-	extern int ppro_with_ram_bug(void);
+ 	int codesize, reservedpages, datasize, initsize;
+-	int tmp;
+-	int bad_ppro;
++	int tmp, bad_ppro;
+ 	unsigned long pfn;
+ 
+ #if defined(CONFIG_SWIOTLB)
+@@ -675,19 +619,19 @@ void __init mem_init(void)
+ #ifdef CONFIG_FLATMEM
+ 	BUG_ON(!mem_map);
+ #endif
+-	
+ 	bad_ppro = ppro_with_ram_bug();
+ 
+ #ifdef CONFIG_HIGHMEM
+ 	/* check that fixmap and pkmap do not overlap */
+-	if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+-		printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
++	if (PKMAP_BASE + LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
++		printk(KERN_ERR
++			"fixmap and kmap areas overlap - this will crash\n");
+ 		printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+-				PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
++				PKMAP_BASE, PKMAP_BASE + LAST_PKMAP*PAGE_SIZE,
++				FIXADDR_START);
+ 		BUG();
+ 	}
+ #endif
+- 
+ 	/* this will put all low memory onto the freelists */
+ 	totalram_pages += free_all_bootmem();
+ 	/* XEN: init low-mem pages outside initial allocation. */
+@@ -699,7 +643,7 @@ void __init mem_init(void)
+ 	reservedpages = 0;
+ 	for (tmp = 0; tmp < max_low_pfn; tmp++)
+ 		/*
+-		 * Only count reserved RAM pages
++		 * Only count reserved RAM pages:
+ 		 */
+ 		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
+ 			reservedpages++;
+@@ -710,11 +654,12 @@ void __init mem_init(void)
+ 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+ 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+ 
+-	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
+-	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, 
++	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
++	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+ 		   VMALLOC_END-VMALLOC_START);
+ 
+-	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
++	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
++			"%dk reserved, %dk data, %dk init, %ldk highmem)\n",
+ 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ 		num_physpages << (PAGE_SHIFT-10),
+ 		codesize >> 10,
+@@ -725,54 +670,53 @@ void __init mem_init(void)
+ 	       );
+ 
+ #if 1 /* double-sanity-check paranoia */
+-	printk("virtual kernel memory layout:\n"
+-	       "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++	printk(KERN_INFO "virtual kernel memory layout:\n"
++		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+ #ifdef CONFIG_HIGHMEM
+-	       "    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++		"    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+ #endif
+-	       "    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+-	       "    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+-	       "      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-	       "      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+-	       "      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
+-	       FIXADDR_START, FIXADDR_TOP,
+-	       (FIXADDR_TOP - FIXADDR_START) >> 10,
++		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
++		"      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++		"      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
++		"      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
++		FIXADDR_START, FIXADDR_TOP,
++		(FIXADDR_TOP - FIXADDR_START) >> 10,
+ 
+ #ifdef CONFIG_HIGHMEM
+-	       PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
+-	       (LAST_PKMAP*PAGE_SIZE) >> 10,
++		PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
++		(LAST_PKMAP*PAGE_SIZE) >> 10,
+ #endif
+ 
+-	       VMALLOC_START, VMALLOC_END,
+-	       (VMALLOC_END - VMALLOC_START) >> 20,
++		VMALLOC_START, VMALLOC_END,
++		(VMALLOC_END - VMALLOC_START) >> 20,
+ 
+-	       (unsigned long)__va(0), (unsigned long)high_memory,
+-	       ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
++		(unsigned long)__va(0), (unsigned long)high_memory,
++		((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+ 
+-	       (unsigned long)&__init_begin, (unsigned long)&__init_end,
+-	       ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10,
++		(unsigned long)&__init_begin, (unsigned long)&__init_end,
++		((unsigned long)&__init_end -
++		 (unsigned long)&__init_begin) >> 10,
+ 
+-	       (unsigned long)&_etext, (unsigned long)&_edata,
+-	       ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
++		(unsigned long)&_etext, (unsigned long)&_edata,
++		((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+ 
+-	       (unsigned long)&_text, (unsigned long)&_etext,
+-	       ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
++		(unsigned long)&_text, (unsigned long)&_etext,
++		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+ 
+ #ifdef CONFIG_HIGHMEM
+-	BUG_ON(PKMAP_BASE+LAST_PKMAP*PAGE_SIZE > FIXADDR_START);
+-	BUG_ON(VMALLOC_END                     > PKMAP_BASE);
++	BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
++	BUG_ON(VMALLOC_END				> PKMAP_BASE);
+ #endif
+-	BUG_ON(VMALLOC_START                   > VMALLOC_END);
+-	BUG_ON((unsigned long)high_memory      > VMALLOC_START);
++	BUG_ON(VMALLOC_START				> VMALLOC_END);
++	BUG_ON((unsigned long)high_memory		> VMALLOC_START);
+ #endif /* double-sanity-check paranoia */
+ 
+-#ifdef CONFIG_X86_PAE
+-	if (!cpu_has_pae)
+-		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
+-#endif
+ 	if (boot_cpu_data.wp_works_ok < 0)
+ 		test_wp_bit();
+ 
++	cpa_init();
++
+ 	/*
+ 	 * Subtle. SMP is doing it's boot stuff late (because it has to
+ 	 * fork idle threads) - but it also needs low mappings for the
+@@ -796,49 +740,35 @@ int arch_add_memory(int nid, u64 start, 
+ 
+ 	return __add_pages(zone, start_pfn, nr_pages);
+ }
+-
+ #endif
+ 
+-struct kmem_cache *pmd_cache;
+-
+-void __init pgtable_cache_init(void)
+-{
+-	if (PTRS_PER_PMD > 1)
+-		pmd_cache = kmem_cache_create("pmd",
+-					      PTRS_PER_PMD*sizeof(pmd_t),
+-					      PTRS_PER_PMD*sizeof(pmd_t),
+-					      SLAB_PANIC,
+-					      pmd_ctor);
+-}
+-
+ /*
+  * This function cannot be __init, since exceptions don't work in that
+  * section.  Put this after the callers, so that it cannot be inlined.
+  */
+-static int noinline do_test_wp_bit(void)
++static noinline int do_test_wp_bit(void)
+ {
+ 	char tmp_reg;
+ 	int flag;
+ 
+ 	__asm__ __volatile__(
+-		"	movb %0,%1	\n"
+-		"1:	movb %1,%0	\n"
+-		"	xorl %2,%2	\n"
++		"	movb %0, %1	\n"
++		"1:	movb %1, %0	\n"
++		"	xorl %2, %2	\n"
+ 		"2:			\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4	\n"
+-		"	.long 1b,2b	\n"
+-		".previous		\n"
++		_ASM_EXTABLE(1b,2b)
+ 		:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
+ 		 "=q" (tmp_reg),
+ 		 "=r" (flag)
+ 		:"2" (1)
+ 		:"memory");
+-	
++
+ 	return flag;
+ }
+ 
+ #ifdef CONFIG_DEBUG_RODATA
++const int rodata_test_data = 0xC3;
++EXPORT_SYMBOL_GPL(rodata_test_data);
+ 
+ void mark_rodata_ro(void)
+ {
+@@ -851,32 +781,58 @@ void mark_rodata_ro(void)
+ 	if (num_possible_cpus() <= 1)
+ #endif
+ 	{
+-		change_page_attr(virt_to_page(start),
+-		                 size >> PAGE_SHIFT, PAGE_KERNEL_RX);
+-		printk("Write protecting the kernel text: %luk\n", size >> 10);
++		set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++		printk(KERN_INFO "Write protecting the kernel text: %luk\n",
++			size >> 10);
++
++#ifdef CONFIG_CPA_DEBUG
++		printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
++			start, start+size);
++		set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
++
++		printk(KERN_INFO "Testing CPA: write protecting again\n");
++		set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
++#endif
+ 	}
+ #endif
+ 	start += size;
+ 	size = (unsigned long)__end_rodata - start;
+-	change_page_attr(virt_to_page(start),
+-	                 size >> PAGE_SHIFT, PAGE_KERNEL_RO);
+-	printk("Write protecting the kernel read-only data: %luk\n",
+-	       size >> 10);
++	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
++		size >> 10);
++	rodata_test();
++
++#ifdef CONFIG_CPA_DEBUG
++	printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, start + size);
++	set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
+ 
+-	/*
+-	 * change_page_attr() requires a global_flush_tlb() call after it.
+-	 * We do this after the printk so that if something went wrong in the
+-	 * change, the printk gets out at least to give a better debug hint
+-	 * of who is the culprit.
+-	 */
+-	global_flush_tlb();
++	printk(KERN_INFO "Testing CPA: write protecting again\n");
++	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
++#endif
+ }
+ #endif
+ 
+ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+ {
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/*
++	 * If debugging page accesses then do not free this memory but
++	 * mark them not present - any buggy init-section access will
++	 * create a kernel page fault:
++	 */
++	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
++		begin, PAGE_ALIGN(end));
++	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
++#else
+ 	unsigned long addr;
+ 
++	/*
++	 * We just marked the kernel text read only above, now that
++	 * we are going to free part of that, we need to make that
++	 * writeable first.
++	 */
++	set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
++
+ 	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ 		ClearPageReserved(virt_to_page(addr));
+ 		init_page_count(virt_to_page(addr));
+@@ -885,6 +841,7 @@ void free_init_pages(char *what, unsigne
+ 		totalram_pages++;
+ 	}
+ 	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
++#endif
+ }
+ 
+ void free_initmem(void)
+@@ -900,4 +857,3 @@ void free_initrd_mem(unsigned long start
+ 	free_init_pages("initrd memory", start, end);
+ }
+ #endif
+-
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -46,14 +46,13 @@
+ #include <asm/proto.h>
+ #include <asm/smp.h>
+ #include <asm/sections.h>
++#include <asm/kdebug.h>
++#include <asm/numa.h>
++#include <asm/cacheflush.h>
+ 
+ #include <xen/features.h>
+ 
+-#ifndef Dprintk
+-#define Dprintk(x...)
+-#endif
+-
+-const struct dma_mapping_ops* dma_ops;
++const struct dma_mapping_ops *dma_ops;
+ EXPORT_SYMBOL(dma_ops);
+ 
+ #if CONFIG_XEN_COMPAT <= 0x030002
+@@ -80,7 +79,21 @@ extern pte_t level1_fixmap_pgt[PTRS_PER_
+ 	(((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) +	\
+ 	__START_KERNEL_map)))
+ 
+-static void __meminit early_make_page_readonly(void *va, unsigned int feature)
++pmd_t *__init early_get_pmd(unsigned long va)
++{
++	unsigned long addr;
++	unsigned long *page = (unsigned long *)init_level4_pgt;
++
++	addr = page[pgd_index(va)];
++	addr_to_page(addr, page);
++
++	addr = page[pud_index(va)];
++	addr_to_page(addr, page);
++
++	return (pmd_t *)&page[pmd_index(va)];
++}
++
++void __meminit early_make_page_readonly(void *va, unsigned int feature)
+ {
+ 	unsigned long addr, _va = (unsigned long)va;
+ 	pte_t pte, *ptep;
+@@ -107,76 +120,6 @@ static void __meminit early_make_page_re
+ 		BUG();
+ }
+ 
+-static void __make_page_readonly(void *va)
+-{
+-	pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
+-	unsigned long addr = (unsigned long) va;
+-
+-	pgd = pgd_offset_k(addr);
+-	pud = pud_offset(pgd, addr);
+-	pmd = pmd_offset(pud, addr);
+-	ptep = pte_offset_kernel(pmd, addr);
+-
+-	pte.pte = ptep->pte & ~_PAGE_RW;
+-	if (HYPERVISOR_update_va_mapping(addr, pte, 0))
+-		xen_l1_entry_update(ptep, pte); /* fallback */
+-
+-	if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
+-		__make_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT));
+-}
+-
+-static void __make_page_writable(void *va)
+-{
+-	pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
+-	unsigned long addr = (unsigned long) va;
+-
+-	pgd = pgd_offset_k(addr);
+-	pud = pud_offset(pgd, addr);
+-	pmd = pmd_offset(pud, addr);
+-	ptep = pte_offset_kernel(pmd, addr);
+-
+-	pte.pte = ptep->pte | _PAGE_RW;
+-	if (HYPERVISOR_update_va_mapping(addr, pte, 0))
+-		xen_l1_entry_update(ptep, pte); /* fallback */
+-
+-	if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
+-		__make_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT));
+-}
+-
+-void make_page_readonly(void *va, unsigned int feature)
+-{
+-	if (!xen_feature(feature))
+-		__make_page_readonly(va);
+-}
+-
+-void make_page_writable(void *va, unsigned int feature)
+-{
+-	if (!xen_feature(feature))
+-		__make_page_writable(va);
+-}
+-
+-void make_pages_readonly(void *va, unsigned nr, unsigned int feature)
+-{
+-	if (xen_feature(feature))
+-		return;
+-
+-	while (nr-- != 0) {
+-		__make_page_readonly(va);
+-		va = (void*)((unsigned long)va + PAGE_SIZE);
+-	}
+-}
+-
+-void make_pages_writable(void *va, unsigned nr, unsigned int feature)
+-{
+-	if (xen_feature(feature))
+-		return;
+-
+-	while (nr-- != 0) {
+-		__make_page_writable(va);
+-		va = (void*)((unsigned long)va + PAGE_SIZE);
+-	}
+-}
+-
+ /*
+  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+  * physical space so we can cache the place of the first one and move
+@@ -187,22 +130,26 @@ void show_mem(void)
+ {
+ 	long i, total = 0, reserved = 0;
+ 	long shared = 0, cached = 0;
+-	pg_data_t *pgdat;
+ 	struct page *page;
++	pg_data_t *pgdat;
+ 
+ 	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
++	printk(KERN_INFO "Free swap:       %6ldkB\n",
++		nr_swap_pages << (PAGE_SHIFT-10));
+ 
+ 	for_each_online_pgdat(pgdat) {
+-               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+-			/* this loop can take a while with 256 GB and 4k pages
+-			   so update the NMI watchdog */
+-			if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
++		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
++			/*
++			 * This loop can take a while with 256 GB and
++			 * 4k pages so defer the NMI watchdog:
++			 */
++			if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
+ 				touch_nmi_watchdog();
+-			}
++
+ 			if (!pfn_valid(pgdat->node_start_pfn + i))
+ 				continue;
++
+ 			page = pfn_to_page(pgdat->node_start_pfn + i);
+ 			total++;
+ 			if (PageReserved(page))
+@@ -211,58 +158,67 @@ void show_mem(void)
+ 				cached++;
+ 			else if (page_count(page))
+ 				shared += page_count(page) - 1;
+-               }
++		}
+ 	}
+-	printk(KERN_INFO "%lu pages of RAM\n", total);
+-	printk(KERN_INFO "%lu reserved pages\n",reserved);
+-	printk(KERN_INFO "%lu pages shared\n",shared);
+-	printk(KERN_INFO "%lu pages swap cached\n",cached);
++	printk(KERN_INFO "%lu pages of RAM\n",		total);
++	printk(KERN_INFO "%lu reserved pages\n",	reserved);
++	printk(KERN_INFO "%lu pages shared\n",		shared);
++	printk(KERN_INFO "%lu pages swap cached\n",	cached);
+ }
+ 
++static unsigned long __meminitdata table_start;
++static unsigned long __meminitdata table_end;
+ 
+ static __init void *spp_getpage(void)
+-{ 
++{
+ 	void *ptr;
++
+ 	if (after_bootmem)
+-		ptr = (void *) get_zeroed_page(GFP_ATOMIC); 
++		ptr = (void *) get_zeroed_page(GFP_ATOMIC);
+ 	else if (start_pfn < table_end) {
+ 		ptr = __va(start_pfn << PAGE_SHIFT);
+ 		start_pfn++;
+ 		memset(ptr, 0, PAGE_SIZE);
+ 	} else
+ 		ptr = alloc_bootmem_pages(PAGE_SIZE);
+-	if (!ptr || ((unsigned long)ptr & ~PAGE_MASK))
+-		panic("set_pte_phys: cannot allocate page data %s\n", after_bootmem?"after bootmem":"");
+ 
+-	Dprintk("spp_getpage %p\n", ptr);
++	if (!ptr || ((unsigned long)ptr & ~PAGE_MASK)) {
++		panic("set_pte_phys: cannot allocate page data %s\n",
++			after_bootmem ? "after bootmem" : "");
++	}
++
++	pr_debug("spp_getpage %p\n", ptr);
++
+ 	return ptr;
+-} 
++}
+ 
+ #define pgd_offset_u(address) (__user_pgd(init_level4_pgt) + pgd_index(address))
+ #define pud_offset_u(address) (level3_user_pgt + pud_index(address))
+ 
+-static __init void set_pte_phys(unsigned long vaddr,
+-			 unsigned long phys, pgprot_t prot, int user_mode)
++static __init void
++set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot, int user_mode)
+ {
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte, new_pte;
+ 
+-	Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys);
++	pr_debug("set_pte_phys %lx to %lx\n", vaddr, phys);
+ 
+ 	pgd = (user_mode ? pgd_offset_u(vaddr) : pgd_offset_k(vaddr));
+ 	if (pgd_none(*pgd)) {
+-		printk("PGD FIXMAP MISSING, it should be setup in head.S!\n");
++		printk(KERN_ERR
++			"PGD FIXMAP MISSING, it should be setup in head.S!\n");
+ 		return;
+ 	}
+ 	pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr));
+ 	if (pud_none(*pud)) {
+-		pmd = (pmd_t *) spp_getpage(); 
++		pmd = (pmd_t *) spp_getpage();
+ 		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+ 		if (pmd != pmd_offset(pud, 0)) {
+-			printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0));
++			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
++				pmd, pmd_offset(pud, 0));
+ 			return;
+ 		}
+ 	}
+@@ -272,7 +228,7 @@ static __init void set_pte_phys(unsigned
+ 		make_page_readonly(pte, XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+ 		if (pte != pte_offset_kernel(pmd, 0)) {
+-			printk("PAGETABLE BUG #02!\n");
++			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+ 			return;
+ 		}
+ 	}
+@@ -294,30 +250,30 @@ static __init void set_pte_phys(unsigned
+ 	__flush_tlb_one(vaddr);
+ }
+ 
+-static __init void set_pte_phys_ma(unsigned long vaddr,
+-				   unsigned long phys, pgprot_t prot)
++static __init void
++set_pte_phys_ma(unsigned long vaddr, unsigned long phys, pgprot_t prot)
+ {
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte, new_pte;
+ 
+-	Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys);
++	pr_debug("set_pte_phys_ma %lx to %lx\n", vaddr, phys);
+ 
+ 	pgd = pgd_offset_k(vaddr);
+ 	if (pgd_none(*pgd)) {
+-		printk("PGD FIXMAP MISSING, it should be setup in head.S!\n");
++		printk(KERN_ERR
++			"PGD FIXMAP MISSING, it should be setup in head.S!\n");
+ 		return;
+ 	}
+ 	pud = pud_offset(pgd, vaddr);
+ 	if (pud_none(*pud)) {
+-
+-		pmd = (pmd_t *) spp_getpage(); 
++		pmd = (pmd_t *) spp_getpage();
+ 		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+ 		if (pmd != pmd_offset(pud, 0)) {
+-			printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0));
+-			return;
++			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
++				pmd, pmd_offset(pud, 0));
+ 		}
+ 	}
+ 	pmd = pmd_offset(pud, vaddr);
+@@ -326,7 +282,7 @@ static __init void set_pte_phys_ma(unsig
+ 		make_page_readonly(pte, XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
+ 		if (pte != pte_offset_kernel(pmd, 0)) {
+-			printk("PAGETABLE BUG #02!\n");
++			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+ 			return;
+ 		}
+ 	}
+@@ -350,14 +306,44 @@ static __init void set_pte_phys_ma(unsig
+ 	__flush_tlb_one(vaddr);
+ }
+ 
++#ifndef CONFIG_XEN
++/*
++ * The head.S code sets up the kernel high mapping:
++ *
++ *   from __START_KERNEL_map to __START_KERNEL_map + size (== _end-_text)
++ *
++ * phys_addr holds the negative offset to the kernel, which is added
++ * to the compile time generated pmds. This results in invalid pmds up
++ * to the point where we hit the physaddr 0 mapping.
++ *
++ * We limit the mappings to the region from _text to _end.  _end is
++ * rounded up to the 2MB boundary. This catches the invalid pmds as
++ * well, as they are located before _text:
++ */
++void __init cleanup_highmap(void)
++{
++	unsigned long vaddr = __START_KERNEL_map;
++	unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1;
++	pmd_t *pmd = level2_kernel_pgt;
++	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
++
++	for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
++		if (!pmd_present(*pmd))
++			continue;
++		if (vaddr < (unsigned long) _text || vaddr > end)
++			set_pmd(pmd, __pmd(0));
++	}
++}
++#endif
++
+ /* NOTE: this is meant to be run only at boot */
+-void __init 
+-__set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
++void __init
++__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+ {
+ 	unsigned long address = __fix_to_virt(idx);
+ 
+ 	if (idx >= __end_of_fixed_addresses) {
+-		printk("Invalid __set_fixmap\n");
++		printk(KERN_ERR "Invalid __set_fixmap\n");
+ 		return;
+ 	}
+ 	switch (idx) {
+@@ -375,16 +361,14 @@ __set_fixmap (enum fixed_addresses idx, 
+ 	}
+ }
+ 
+-unsigned long __meminitdata table_start, table_end;
+-
+ static __meminit void *alloc_static_page(unsigned long *phys)
+ {
+ 	unsigned long va = (start_pfn << PAGE_SHIFT) + __START_KERNEL_map;
+ 
+ 	if (after_bootmem) {
+ 		void *adr = (void *)get_zeroed_page(GFP_ATOMIC);
+-
+ 		*phys = __pa(adr);
++
+ 		return adr;
+ 	}
+ 
+@@ -396,7 +380,7 @@ static __meminit void *alloc_static_page
+ 
+ #define PTE_SIZE PAGE_SIZE
+ 
+-static inline int make_readonly(unsigned long paddr)
++static inline int __meminit make_readonly(unsigned long paddr)
+ {
+ 	extern char __vsyscall_0;
+ 	int readonly = 0;
+@@ -430,33 +414,38 @@ static inline int make_readonly(unsigned
+ /* Must run before zap_low_mappings */
+ __meminit void *early_ioremap(unsigned long addr, unsigned long size)
+ {
+-	unsigned long vaddr;
+ 	pmd_t *pmd, *last_pmd;
++	unsigned long vaddr;
+ 	int i, pmds;
+ 
+ 	pmds = ((addr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+ 	vaddr = __START_KERNEL_map;
+ 	pmd = level2_kernel_pgt;
+ 	last_pmd = level2_kernel_pgt + PTRS_PER_PMD - 1;
++
+ 	for (; pmd <= last_pmd; pmd++, vaddr += PMD_SIZE) {
+ 		for (i = 0; i < pmds; i++) {
+ 			if (pmd_present(pmd[i]))
+-				goto next;
++				goto continue_outer_loop;
+ 		}
+ 		vaddr += addr & ~PMD_MASK;
+ 		addr &= PMD_MASK;
++
+ 		for (i = 0; i < pmds; i++, addr += PMD_SIZE)
+-			set_pmd(pmd + i,__pmd(addr | _KERNPG_TABLE | _PAGE_PSE));
+-		__flush_tlb();
++			set_pmd(pmd+i, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
++		__flush_tlb_all();
++
+ 		return (void *)vaddr;
+-	next:
++continue_outer_loop:
+ 		;
+ 	}
+ 	printk("early_ioremap(0x%lx, %lu) failed\n", addr, size);
+ 	return NULL;
+ }
+ 
+-/* To avoid virtual aliases later */
++/*
++ * To avoid virtual aliases later:
++ */
+ __meminit void early_iounmap(void *addr, unsigned long size)
+ {
+ 	unsigned long vaddr;
+@@ -466,9 +455,11 @@ __meminit void early_iounmap(void *addr,
+ 	vaddr = (unsigned long)addr;
+ 	pmds = ((vaddr & ~PMD_MASK) + size + ~PMD_MASK) / PMD_SIZE;
+ 	pmd = level2_kernel_pgt + pmd_index(vaddr);
++
+ 	for (i = 0; i < pmds; i++)
+ 		pmd_clear(pmd + i);
+-	__flush_tlb();
++
++	__flush_tlb_all();
+ }
+ #endif
+ 
+@@ -517,18 +508,19 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ static void __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+ {
+-	pmd_t *pmd = pmd_offset(pud,0);
++	pmd_t *pmd = pmd_offset(pud, 0);
+ 	spin_lock(&init_mm.page_table_lock);
+ 	phys_pmd_init(pmd, address, end);
+ 	spin_unlock(&init_mm.page_table_lock);
+ 	__flush_tlb_all();
+ }
+ 
+-static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
+-{ 
++static void __meminit
++phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
++{
+ 	int i = pud_index(addr);
+ 
+-	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE ) {
++	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+ 		unsigned long pmd_phys;
+ 		pud_t *pud = pud_page + pud_index(addr);
+ 		pmd_t *pmd;
+@@ -550,8 +542,8 @@ static void __meminit phys_pud_init(pud_
+ 
+ 		early_make_page_readonly(pmd, XENFEAT_writable_page_tables);
+ 	}
+-	__flush_tlb();
+-} 
++	__flush_tlb_all();
++}
+ 
+ void __init xen_init_pt(void)
+ {
+@@ -637,6 +629,7 @@ void __init xen_init_pt(void)
+ static void __init extend_init_mapping(unsigned long tables_space)
+ {
+ 	unsigned long va = __START_KERNEL_map;
++	unsigned long start = start_pfn;
+ 	unsigned long phys, addr, *pte_page;
+ 	pmd_t *pmd;
+ 	pte_t *pte, new_pte;
+@@ -713,6 +706,10 @@ static void __init extend_init_mapping(u
+ 			BUG();
+ 		va += PAGE_SIZE;
+ 	}
++
++	if (start_pfn > start)
++		reserve_early(start << PAGE_SHIFT,
++			      start_pfn << PAGE_SHIFT, "INITMAP");
+ }
+ 
+ static void __init find_early_table_space(unsigned long end)
+@@ -737,7 +734,7 @@ static void __init find_early_table_spac
+ 		(table_start << PAGE_SHIFT) + tables);
+ }
+ 
+-static void xen_finish_init_mapping(void)
++static void __init xen_finish_init_mapping(void)
+ {
+ 	unsigned long i, start, end;
+ 
+@@ -769,13 +766,6 @@ static void xen_finish_init_mapping(void
+ 	/* Allocate pte's for initial fixmaps from 'start_pfn' allocator. */
+ 	table_end = ~0UL;
+ 
+-	/*
+-	 * Prefetch pte's for the bt_ioremap() area. It gets used before the
+-	 * boot-time allocator is online, so allocate-on-demand would fail.
+-	 */
+-	for (i = FIX_BTMAP_END; i <= FIX_BTMAP_BEGIN; i++)
+-		__set_fixmap(i, 0, __pgprot(0));
+-
+ 	/* Switch to the real shared_info page, and clear the dummy page. */
+ 	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+ 	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+@@ -795,20 +785,23 @@ static void xen_finish_init_mapping(void
+ 	table_end = start_pfn;
+ }
+ 
+-/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
+-   This runs before bootmem is initialized and gets pages directly from the 
+-   physical memory. To access them they are temporarily mapped. */
++/*
++ * Setup the direct mapping of the physical memory at PAGE_OFFSET.
++ * This runs before bootmem is initialized and gets pages directly from
++ * the physical memory. To access them they are temporarily mapped.
++ */
+ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+-{ 
++{
+ 	unsigned long next;
+ 
+-	Dprintk("init_memory_mapping\n");
++	pr_debug("init_memory_mapping\n");
+ 
+-	/* 
++	/*
+ 	 * Find space for the kernel direct mapping tables.
+-	 * Later we should allocate these tables in the local node of the memory
+-	 * mapped.  Unfortunately this is done currently before the nodes are 
+-	 * discovered.
++	 *
++	 * Later we should allocate these tables in the local node of the
++	 * memory mapped. Unfortunately this is done currently before the
++	 * nodes are discovered.
+ 	 */
+ 	if (!after_bootmem)
+ 		find_early_table_space(end);
+@@ -817,8 +810,8 @@ void __init_refok init_memory_mapping(un
+ 	end = (unsigned long)__va(end);
+ 
+ 	for (; start < end; start = next) {
+-		unsigned long pud_phys; 
+ 		pgd_t *pgd = pgd_offset_k(start);
++		unsigned long pud_phys;
+ 		pud_t *pud;
+ 
+ 		if (after_bootmem)
+@@ -826,8 +819,8 @@ void __init_refok init_memory_mapping(un
+ 		else
+ 			pud = alloc_static_page(&pud_phys);
+ 		next = start + PGDIR_SIZE;
+-		if (next > end) 
+-			next = end; 
++		if (next > end)
++			next = end;
+ 		phys_pud_init(pud, __pa(start), __pa(next));
+ 		if (!after_bootmem) {
+ 			early_make_page_readonly(pud, XENFEAT_writable_page_tables);
+@@ -841,12 +834,17 @@ void __init_refok init_memory_mapping(un
+ 	}
+ 
+ 	__flush_tlb_all();
++
++	if (!after_bootmem)
++		reserve_early(table_start << PAGE_SHIFT,
++			      table_end << PAGE_SHIFT, "PGTABLE");
+ }
+ 
+ #ifndef CONFIG_NUMA
+ void __init paging_init(void)
+ {
+ 	unsigned long max_zone_pfns[MAX_NR_ZONES];
++
+ 	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ 	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+ 	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+@@ -860,40 +858,6 @@ void __init paging_init(void)
+ }
+ #endif
+ 
+-/* Unmap a kernel mapping if it exists. This is useful to avoid prefetches
+-   from the CPU leading to inconsistent cache lines. address and size
+-   must be aligned to 2MB boundaries. 
+-   Does nothing when the mapping doesn't exist. */
+-void __init clear_kernel_mapping(unsigned long address, unsigned long size) 
+-{
+-	unsigned long end = address + size;
+-
+-	BUG_ON(address & ~LARGE_PAGE_MASK);
+-	BUG_ON(size & ~LARGE_PAGE_MASK); 
+-	
+-	for (; address < end; address += LARGE_PAGE_SIZE) { 
+-		pgd_t *pgd = pgd_offset_k(address);
+-		pud_t *pud;
+-		pmd_t *pmd;
+-		if (pgd_none(*pgd))
+-			continue;
+-		pud = pud_offset(pgd, address);
+-		if (pud_none(*pud))
+-			continue; 
+-		pmd = pmd_offset(pud, address);
+-		if (!pmd || pmd_none(*pmd))
+-			continue; 
+-		if (0 == (__pmd_val(*pmd) & _PAGE_PSE)) {
+-			/* Could handle this, but it should not happen currently. */
+-			printk(KERN_ERR 
+-	       "clear_kernel_mapping: mapping has been split. will leak memory\n"); 
+-			pmd_ERROR(*pmd); 
+-		}
+-		set_pmd(pmd, __pmd(0)); 		
+-	}
+-	__flush_tlb_all();
+-} 
+-
+ /*
+  * Memory hotplug specific functions
+  */
+@@ -919,16 +883,12 @@ int arch_add_memory(int nid, u64 start, 
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 	int ret;
+ 
+-	init_memory_mapping(start, (start + size -1));
++	init_memory_mapping(start, start + size-1);
+ 
+ 	ret = __add_pages(zone, start_pfn, nr_pages);
+-	if (ret)
+-		goto error;
++	WARN_ON(1);
+ 
+ 	return ret;
+-error:
+-	printk("%s: Problem encountered in __add_pages!\n", __func__);
+-	return ret;
+ }
+ EXPORT_SYMBOL_GPL(arch_add_memory);
+ 
+@@ -942,36 +902,8 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to
+ 
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
+-#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+-/*
+- * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
+- * just online the pages.
+- */
+-int __add_pages(struct zone *z, unsigned long start_pfn, unsigned long nr_pages)
+-{
+-	int err = -EIO;
+-	unsigned long pfn;
+-	unsigned long total = 0, mem = 0;
+-	for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
+-		if (pfn_valid(pfn)) {
+-			online_page(pfn_to_page(pfn));
+-			err = 0;
+-			mem++;
+-		}
+-		total++;
+-	}
+-	if (!err) {
+-		z->spanned_pages += total;
+-		z->present_pages += mem;
+-		z->zone_pgdat->node_spanned_pages += total;
+-		z->zone_pgdat->node_present_pages += mem;
+-	}
+-	return err;
+-}
+-#endif
+-
+-static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
+-			 kcore_vsyscall;
++static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
++			 kcore_modules, kcore_vsyscall;
+ 
+ void __init mem_init(void)
+ {
+@@ -980,8 +912,7 @@ void __init mem_init(void)
+ 
+ 	pci_iommu_alloc();
+ 
+-	/* clear the zero-page */
+-	memset(empty_zero_page, 0, PAGE_SIZE);
++	/* clear_bss() already clear the empty_zero_page */
+ 
+ 	reservedpages = 0;
+ 
+@@ -998,7 +929,6 @@ void __init mem_init(void)
+ 	}
+ 	reservedpages = end_pfn - totalram_pages -
+ 					absent_pages_in_range(0, end_pfn);
+-
+ 	after_bootmem = 1;
+ 
+ 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+@@ -1006,46 +936,64 @@ void __init mem_init(void)
+ 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+ 
+ 	/* Register memory areas for /proc/kcore */
+-	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
+-	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, 
++	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
++	kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+ 		   VMALLOC_END-VMALLOC_START);
+ 	kclist_add(&kcore_kernel, &_stext, _end - _stext);
+ 	kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN);
+-	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 
++	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START,
+ 				 VSYSCALL_END - VSYSCALL_START);
+ 
+-	printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
++	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
++				"%ldk reserved, %ldk data, %ldk init)\n",
+ 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ 		end_pfn << (PAGE_SHIFT-10),
+ 		codesize >> 10,
+ 		reservedpages << (PAGE_SHIFT-10),
+ 		datasize >> 10,
+ 		initsize >> 10);
++
++	cpa_init();
+ }
+ 
+ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+ {
+-	unsigned long addr;
++	unsigned long addr = begin;
+ 
+-	if (begin >= end)
++	if (addr >= end)
+ 		return;
+ 
++	/*
++	 * If debugging page accesses then do not free this memory but
++	 * mark them not present - any buggy init-section access will
++	 * create a kernel page fault:
++	 */
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
++		begin, PAGE_ALIGN(end));
++	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
++#else
+ 	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
+-	for (addr = begin; addr < end; addr += PAGE_SIZE) {
++
++	for (; addr < end; addr += PAGE_SIZE) {
+ 		ClearPageReserved(virt_to_page(addr));
+ 		init_page_count(virt_to_page(addr));
+ 		memset((void *)(addr & ~(PAGE_SIZE-1)),
+ 		       POISON_FREE_INITMEM, PAGE_SIZE); 
+ 		if (addr >= __START_KERNEL_map) {
+ 			/* make_readonly() reports all kernel addresses. */
+-			__make_page_writable(__va(__pa(addr)));
+-			change_page_attr_addr(addr, 1, __pgprot(0));
++			if (HYPERVISOR_update_va_mapping((unsigned long)__va(__pa(addr)),
++							 pfn_pte(__pa(addr) >> PAGE_SHIFT,
++								 PAGE_KERNEL),
++							 0))
++				BUG();
++			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
++				BUG();
+ 		}
+ 		free_page(addr);
+ 		totalram_pages++;
+ 	}
+-	if (addr > __START_KERNEL_map)
+-		global_flush_tlb();
++#endif
+ }
+ 
+ void free_initmem(void)
+@@ -1056,6 +1004,8 @@ void free_initmem(void)
+ }
+ 
+ #ifdef CONFIG_DEBUG_RODATA
++const int rodata_test_data = 0xC3;
++EXPORT_SYMBOL_GPL(rodata_test_data);
+ 
+ void mark_rodata_ro(void)
+ {
+@@ -1077,18 +1027,27 @@ void mark_rodata_ro(void)
+ 	if (end <= start)
+ 		return;
+ 
+-	change_page_attr_addr(start, (end - start) >> PAGE_SHIFT, PAGE_KERNEL_RO);
+ 
+ 	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+ 	       (end - start) >> 10);
++	set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+ 
+ 	/*
+-	 * change_page_attr_addr() requires a global_flush_tlb() call after it.
+-	 * We do this after the printk so that if something went wrong in the
+-	 * change, the printk gets out at least to give a better debug hint
+-	 * of who is the culprit.
++	 * The rodata section (but not the kernel text!) should also be
++	 * not-executable.
+ 	 */
+-	global_flush_tlb();
++	start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
++	set_memory_nx(start, (end - start) >> PAGE_SHIFT);
++
++	rodata_test();
++
++#ifdef CONFIG_CPA_DEBUG
++	printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end);
++	set_memory_rw(start, (end-start) >> PAGE_SHIFT);
++
++	printk(KERN_INFO "Testing CPA: again\n");
++	set_memory_ro(start, (end-start) >> PAGE_SHIFT);
++#endif
+ }
+ #endif
+ 
+@@ -1099,17 +1058,21 @@ void free_initrd_mem(unsigned long start
+ }
+ #endif
+ 
+-void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
+-{ 
++void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
++{
+ #ifdef CONFIG_NUMA
+ 	int nid = phys_to_nid(phys);
+ #endif
+ 	unsigned long pfn = phys >> PAGE_SHIFT;
++
+ 	if (pfn >= end_pfn) {
+-		/* This can happen with kdump kernels when accessing firmware
+-		   tables. */
++		/*
++		 * This can happen with kdump kernels when accessing
++		 * firmware tables:
++		 */
+ 		if (pfn < end_pfn_map)
+ 			return;
++
+ 		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
+ 				phys, len);
+ 		return;
+@@ -1117,9 +1080,9 @@ void __init reserve_bootmem_generic(unsi
+ 
+ 	/* Should check here against the e820 map to avoid double free */
+ #ifdef CONFIG_NUMA
+-  	reserve_bootmem_node(NODE_DATA(nid), phys, len);
+-#else       		
+-	reserve_bootmem(phys, len);    
++	reserve_bootmem_node(NODE_DATA(nid), phys, len, BOOTMEM_DEFAULT);
++#else
++	reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+ #endif
+ #ifndef CONFIG_XEN
+ 	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
+@@ -1129,46 +1092,49 @@ void __init reserve_bootmem_generic(unsi
+ #endif
+ }
+ 
+-int kern_addr_valid(unsigned long addr) 
+-{ 
++int kern_addr_valid(unsigned long addr)
++{
+ 	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
+-       pgd_t *pgd;
+-       pud_t *pud;
+-       pmd_t *pmd;
+-       pte_t *pte;
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
+ 
+ 	if (above != 0 && above != -1UL)
+-		return 0; 
+-	
++		return 0;
++
+ 	pgd = pgd_offset_k(addr);
+ 	if (pgd_none(*pgd))
+ 		return 0;
+ 
+ 	pud = pud_offset(pgd, addr);
+ 	if (pud_none(*pud))
+-		return 0; 
++		return 0;
+ 
+ 	pmd = pmd_offset(pud, addr);
+ 	if (pmd_none(*pmd))
+ 		return 0;
++
+ 	if (pmd_large(*pmd))
+ 		return pfn_valid(pmd_pfn(*pmd));
+ 
+ 	pte = pte_offset_kernel(pmd, addr);
+ 	if (pte_none(*pte))
+ 		return 0;
++
+ 	return pfn_valid(pte_pfn(*pte));
+ }
+ 
+-/* A pseudo VMA to allow ptrace access for the vsyscall page.  This only
+-   covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+-   not need special handling anymore. */
+-
++/*
++ * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
++ * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
++ * not need special handling anymore:
++ */
+ static struct vm_area_struct gate_vma = {
+-	.vm_start = VSYSCALL_START,
+-	.vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES << PAGE_SHIFT),
+-	.vm_page_prot = PAGE_READONLY_EXEC,
+-	.vm_flags = VM_READ | VM_EXEC
++	.vm_start	= VSYSCALL_START,
++	.vm_end		= VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE),
++	.vm_page_prot	= PAGE_READONLY_EXEC,
++	.vm_flags	= VM_READ | VM_EXEC
+ };
+ 
+ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+@@ -1183,14 +1149,17 @@ struct vm_area_struct *get_gate_vma(stru
+ int in_gate_area(struct task_struct *task, unsigned long addr)
+ {
+ 	struct vm_area_struct *vma = get_gate_vma(task);
++
+ 	if (!vma)
+ 		return 0;
++
+ 	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+ }
+ 
+-/* Use this when you have no reliable task/vma, typically from interrupt
+- * context.  It is less reliable than using the task's vma and may give
+- * false positives.
++/*
++ * Use this when you have no reliable task/vma, typically from interrupt
++ * context. It is less reliable than using the task's vma and may give
++ * false positives:
+  */
+ int in_gate_area_no_task(unsigned long addr)
+ {
+@@ -1210,8 +1179,8 @@ const char *arch_vma_name(struct vm_area
+ /*
+  * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
+  */
+-int __meminit vmemmap_populate(struct page *start_page,
+-						unsigned long size, int node)
++int __meminit
++vmemmap_populate(struct page *start_page, unsigned long size, int node)
+ {
+ 	unsigned long addr = (unsigned long)start_page;
+ 	unsigned long end = (unsigned long)(start_page + size);
+@@ -1226,6 +1195,7 @@ int __meminit vmemmap_populate(struct pa
+ 		pgd = vmemmap_pgd_populate(addr, node);
+ 		if (!pgd)
+ 			return -ENOMEM;
++
+ 		pud = vmemmap_pud_populate(pgd, addr, node);
+ 		if (!pud)
+ 			return -ENOMEM;
+@@ -1233,20 +1203,22 @@ int __meminit vmemmap_populate(struct pa
+ 		pmd = pmd_offset(pud, addr);
+ 		if (pmd_none(*pmd)) {
+ 			pte_t entry;
+-			void *p = vmemmap_alloc_block(PMD_SIZE, node);
++			void *p;
++
++			p = vmemmap_alloc_block(PMD_SIZE, node);
+ 			if (!p)
+ 				return -ENOMEM;
+ 
+-			entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
+-			mk_pte_huge(entry);
+-			set_pmd(pmd, __pmd(pte_val(entry)));
++			entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
++							PAGE_KERNEL_LARGE);
++			set_pmd(pmd, __pmd_ma(__pte_val(entry)));
+ 
+ 			printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
+ 				addr, addr + PMD_SIZE - 1, p, node);
+-		} else
++		} else {
+ 			vmemmap_verify((pte_t *)pmd, node, addr, next);
++		}
+ 	}
+-
+ 	return 0;
+ }
+ #endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,687 @@
++/*
++ * Re-map IO memory to kernel address space so that we can access it.
++ * This is needed for high PCI addresses that aren't mapped in the
++ * 640k-1MB IO memory area on PC's
++ *
++ * (C) Copyright 1995 1996 Linus Torvalds
++ */
++
++#include <linux/bootmem.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/pfn.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++
++#include <asm/cacheflush.h>
++#include <asm/e820.h>
++#include <asm/fixmap.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/pgalloc.h>
++
++enum ioremap_mode {
++	IOR_MODE_UNCACHED,
++	IOR_MODE_CACHED,
++};
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++
++unsigned long __phys_addr(unsigned long x)
++{
++	if (x >= __START_KERNEL_map)
++		return x - __START_KERNEL_map + phys_base;
++	return x - PAGE_OFFSET;
++}
++EXPORT_SYMBOL(__phys_addr);
++
++#endif
++
++static int direct_remap_area_pte_fn(pte_t *pte,
++				    struct page *pmd_page,
++				    unsigned long address,
++				    void *data)
++{
++	mmu_update_t **v = (mmu_update_t **)data;
++
++	BUG_ON(!pte_none(*pte));
++
++	(*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
++		     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
++	(*v)++;
++
++	return 0;
++}
++
++static int __direct_remap_pfn_range(struct mm_struct *mm,
++				    unsigned long address,
++				    unsigned long mfn,
++				    unsigned long size,
++				    pgprot_t prot,
++				    domid_t  domid)
++{
++	int rc;
++	unsigned long i, start_address;
++	mmu_update_t *u, *v, *w;
++
++	u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
++	if (u == NULL)
++		return -ENOMEM;
++
++	start_address = address;
++
++	flush_cache_all();
++
++	for (i = 0; i < size; i += PAGE_SIZE) {
++		if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
++			/* Flush a full batch after filling in the PTE ptrs. */
++			rc = apply_to_page_range(mm, start_address,
++						 address - start_address,
++						 direct_remap_area_pte_fn, &w);
++			if (rc)
++				goto out;
++			rc = -EFAULT;
++			if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)
++				goto out;
++			v = w = u;
++			start_address = address;
++		}
++
++		/*
++		 * Fill in the machine address: PTE ptr is done later by
++		 * apply_to_page_range().
++		 */
++		v->val = __pte_val(pfn_pte_ma(mfn, prot)) | _PAGE_IO;
++
++		mfn++;
++		address += PAGE_SIZE;
++		v++;
++	}
++
++	if (v != u) {
++		/* Final batch. */
++		rc = apply_to_page_range(mm, start_address,
++					 address - start_address,
++					 direct_remap_area_pte_fn, &w);
++		if (rc)
++			goto out;
++		rc = -EFAULT;
++		if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0))
++			goto out;
++	}
++
++	rc = 0;
++
++ out:
++	flush_tlb_all();
++
++	free_page((unsigned long)u);
++
++	return rc;
++}
++
++int direct_remap_pfn_range(struct vm_area_struct *vma,
++			   unsigned long address,
++			   unsigned long mfn,
++			   unsigned long size,
++			   pgprot_t prot,
++			   domid_t  domid)
++{
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return remap_pfn_range(vma, address, mfn, size, prot);
++
++	if (domid == DOMID_SELF)
++		return -EINVAL;
++
++	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
++
++	vma->vm_mm->context.has_foreign_mappings = 1;
++
++	return __direct_remap_pfn_range(
++		vma->vm_mm, address, mfn, size, prot, domid);
++}
++EXPORT_SYMBOL(direct_remap_pfn_range);
++
++int direct_kernel_remap_pfn_range(unsigned long address,
++				  unsigned long mfn,
++				  unsigned long size,
++				  pgprot_t prot,
++				  domid_t  domid)
++{
++	return __direct_remap_pfn_range(
++		&init_mm, address, mfn, size, prot, domid);
++}
++EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
++
++static int lookup_pte_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	uint64_t *ptep = (uint64_t *)data;
++	if (ptep)
++		*ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
++			 PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
++	return 0;
++}
++
++int create_lookup_pte_addr(struct mm_struct *mm,
++			   unsigned long address,
++			   uint64_t *ptep)
++{
++	return apply_to_page_range(mm, address, PAGE_SIZE,
++				   lookup_pte_fn, ptep);
++}
++
++EXPORT_SYMBOL(create_lookup_pte_addr);
++
++static int noop_fn(
++	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
++{
++	return 0;
++}
++
++int touch_pte_range(struct mm_struct *mm,
++		    unsigned long address,
++		    unsigned long size)
++{
++	return apply_to_page_range(mm, address, size, noop_fn, NULL);
++}
++
++EXPORT_SYMBOL(touch_pte_range);
++
++#ifdef CONFIG_X86_32
++int page_is_ram(unsigned long pagenr)
++{
++	unsigned long addr, end;
++	int i;
++
++#ifndef CONFIG_XEN
++	/*
++	 * A special case is the first 4Kb of memory;
++	 * This is a BIOS owned area, not kernel ram, but generally
++	 * not listed as such in the E820 table.
++	 */
++	if (pagenr == 0)
++		return 0;
++
++	/*
++	 * Second special case: Some BIOSen report the PC BIOS
++	 * area (640->1Mb) as ram even though it is not.
++	 */
++	if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) &&
++		    pagenr < (BIOS_END >> PAGE_SHIFT))
++		return 0;
++#endif
++
++	for (i = 0; i < e820.nr_map; i++) {
++		/*
++		 * Not usable memory:
++		 */
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT;
++		end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
++
++
++		if ((pagenr >= addr) && (pagenr < end))
++			return 1;
++	}
++	return 0;
++}
++#endif
++
++/*
++ * Fix up the linear direct mapping of the kernel to avoid cache attribute
++ * conflicts.
++ */
++static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
++			       enum ioremap_mode mode)
++{
++	unsigned long nrpages = size >> PAGE_SHIFT;
++	int err;
++
++	switch (mode) {
++	case IOR_MODE_UNCACHED:
++	default:
++		err = set_memory_uc(vaddr, nrpages);
++		break;
++	case IOR_MODE_CACHED:
++		err = set_memory_wb(vaddr, nrpages);
++		break;
++	}
++
++	return err;
++}
++
++/*
++ * Remap an arbitrary physical address space into the kernel virtual
++ * address space. Needed when the kernel wants to access high addresses
++ * directly.
++ *
++ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
++ * have to convert them into an offset in a page-aligned mapping, but the
++ * caller shouldn't need to know that small detail.
++ */
++static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
++			       enum ioremap_mode mode)
++{
++	unsigned long mfn, offset, last_addr, vaddr;
++	struct vm_struct *area;
++	pgprot_t prot;
++	domid_t domid = DOMID_IO;
++
++	/* Don't allow wraparound or zero size */
++	last_addr = phys_addr + size - 1;
++	if (!size || last_addr < phys_addr)
++		return NULL;
++
++	/*
++	 * Don't remap the low PCI/ISA area, it's always mapped..
++	 */
++	if (is_initial_xendomain() && last_addr < ISA_END_ADDRESS)
++		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
++
++	/*
++	 * Don't allow anybody to remap normal RAM that we're using..
++	 */
++	for (mfn = PFN_DOWN(phys_addr); mfn < PFN_UP(last_addr); mfn++) {
++		unsigned long pfn = mfn_to_local_pfn(mfn);
++
++		if (pfn >= max_pfn)
++			continue;
++
++		domid = DOMID_SELF;
++
++		if (pfn >= max_pfn_mapped) /* bogus */
++			continue;
++
++		if (pfn_valid(pfn) && !PageReserved(pfn_to_page(pfn)))
++			return NULL;
++	}
++
++	switch (mode) {
++	case IOR_MODE_UNCACHED:
++	default:
++		/*
++		 * FIXME: we will use UC MINUS for now, as video fb drivers
++		 * depend on it. Upcoming ioremap_wc() will fix this behavior.
++		 */
++		prot = PAGE_KERNEL_UC_MINUS;
++		break;
++	case IOR_MODE_CACHED:
++		prot = PAGE_KERNEL;
++		break;
++	}
++
++	/*
++	 * Mappings have to be page-aligned
++	 */
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
++	size = PAGE_ALIGN(last_addr+1) - phys_addr;
++
++	/*
++	 * Ok, go for it..
++	 */
++	area = get_vm_area(size, VM_IOREMAP | (mode << 20));
++	if (!area)
++		return NULL;
++	area->phys_addr = phys_addr;
++	vaddr = (unsigned long) area->addr;
++	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
++				     size, prot, domid)) {
++		free_vm_area(area);
++		return NULL;
++	}
++
++	if (ioremap_change_attr(vaddr, size, mode) < 0) {
++		iounmap((void __iomem *) vaddr);
++		return NULL;
++	}
++
++	return (void __iomem *) (vaddr + offset);
++}
++
++/**
++ * ioremap_nocache     -   map bus memory into CPU space
++ * @offset:    bus address of the memory
++ * @size:      size of the resource to map
++ *
++ * ioremap_nocache performs a platform specific sequence of operations to
++ * make bus memory CPU accessible via the readb/readw/readl/writeb/
++ * writew/writel functions and the other mmio helpers. The returned
++ * address is not guaranteed to be usable directly as a virtual
++ * address.
++ *
++ * This version of ioremap ensures that the memory is marked uncachable
++ * on the CPU as well as honouring existing caching rules from things like
++ * the PCI bus. Note that there are other caches and buffers on many
++ * busses. In particular driver authors should read up on PCI writes
++ *
++ * It's useful if some control registers are in such an area and
++ * write combining or read caching is not desirable:
++ *
++ * Must be freed with iounmap.
++ */
++void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
++{
++	return __ioremap(phys_addr, size, IOR_MODE_UNCACHED);
++}
++EXPORT_SYMBOL(ioremap_nocache);
++
++void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
++{
++	return __ioremap(phys_addr, size, IOR_MODE_CACHED);
++}
++EXPORT_SYMBOL(ioremap_cache);
++
++/**
++ * iounmap - Free a IO remapping
++ * @addr: virtual address from ioremap_*
++ *
++ * Caller must ensure there is only one unmapping for the same pointer.
++ */
++void iounmap(volatile void __iomem *addr)
++{
++	struct vm_struct *p, *o;
++
++	if ((void __force *)addr <= high_memory)
++		return;
++
++	/*
++	 * __ioremap special-cases the PCI/ISA range by not instantiating a
++	 * vm_area and by simply returning an address into the kernel mapping
++	 * of ISA space.   So handle that here.
++	 */
++	if ((unsigned long)addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
++		return;
++
++	addr = (volatile void __iomem *)
++		(PAGE_MASK & (unsigned long __force)addr);
++
++	/* Use the vm area unlocked, assuming the caller
++	   ensures there isn't another iounmap for the same address
++	   in parallel. Reuse of the virtual address is prevented by
++	   leaving it in the global lists until we're done with it.
++	   cpa takes care of the direct mappings. */
++	read_lock(&vmlist_lock);
++	for (p = vmlist; p; p = p->next) {
++		if (p->addr == addr)
++			break;
++	}
++	read_unlock(&vmlist_lock);
++
++	if (!p) {
++		printk(KERN_ERR "iounmap: bad address %p\n", addr);
++		dump_stack();
++		return;
++	}
++
++	if ((p->flags >> 20) != IOR_MODE_CACHED) {
++		unsigned long n = get_vm_area_size(p) >> PAGE_SHIFT;
++		unsigned long mfn = p->phys_addr;
++		unsigned long va = (unsigned long)addr;
++
++		for (; n > 0; n--, mfn++, va += PAGE_SIZE)
++			if (mfn_to_local_pfn(mfn) < max_pfn)
++				set_memory_wb(va, 1);
++	}
++
++	/* Finally remove it */
++	o = remove_vm_area((void *)addr);
++	BUG_ON(p != o || o == NULL);
++	kfree(p);
++}
++EXPORT_SYMBOL(iounmap);
++
++int __initdata early_ioremap_debug;
++
++static int __init early_ioremap_debug_setup(char *str)
++{
++	early_ioremap_debug = 1;
++
++	return 0;
++}
++early_param("early_ioremap_debug", early_ioremap_debug_setup);
++
++static __initdata int after_paging_init;
++static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
++				__attribute__((aligned(PAGE_SIZE)));
++
++#ifdef CONFIG_X86_32
++static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
++{
++	/* Don't assume we're using swapper_pg_dir at this point */
++	pgd_t *base = __va(read_cr3());
++	pgd_t *pgd = &base[pgd_index(addr)];
++	pud_t *pud = pud_offset(pgd, addr);
++	pmd_t *pmd = pmd_offset(pud, addr);
++
++	return pmd;
++}
++#else
++#define early_ioremap_pmd early_get_pmd
++#define make_lowmem_page_readonly early_make_page_readonly
++#define make_lowmem_page_writable make_page_writable
++#endif
++
++static inline pte_t * __init early_ioremap_pte(unsigned long addr)
++{
++	return &bm_pte[pte_index(addr)];
++}
++
++void __init early_ioremap_init(void)
++{
++	pmd_t *pmd;
++
++	if (early_ioremap_debug)
++		printk(KERN_INFO "early_ioremap_init()\n");
++
++	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
++	memset(bm_pte, 0, sizeof(bm_pte));
++	make_lowmem_page_readonly(bm_pte, XENFEAT_writable_page_tables);
++	pmd_populate_kernel(&init_mm, pmd, bm_pte);
++
++	/*
++	 * The boot-ioremap range spans multiple pmds, for which
++	 * we are not prepared:
++	 */
++	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
++		WARN_ON(1);
++		printk(KERN_WARNING "pmd %p != %p\n",
++		       pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
++		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
++			fix_to_virt(FIX_BTMAP_BEGIN));
++		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END):   %08lx\n",
++			fix_to_virt(FIX_BTMAP_END));
++
++		printk(KERN_WARNING "FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
++		printk(KERN_WARNING "FIX_BTMAP_BEGIN:     %d\n",
++		       FIX_BTMAP_BEGIN);
++	}
++}
++
++#ifdef CONFIG_X86_32
++void __init early_ioremap_clear(void)
++{
++	pmd_t *pmd;
++
++	if (early_ioremap_debug)
++		printk(KERN_INFO "early_ioremap_clear()\n");
++
++	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
++	pmd_clear(pmd);
++	make_lowmem_page_writable(bm_pte, XENFEAT_writable_page_tables);
++	/* paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT); */
++	__flush_tlb_all();
++}
++
++void __init early_ioremap_reset(void)
++{
++	enum fixed_addresses idx;
++	unsigned long addr, phys;
++	pte_t *pte;
++
++	after_paging_init = 1;
++	for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
++		addr = fix_to_virt(idx);
++		pte = early_ioremap_pte(addr);
++		if (pte_present(*pte)) {
++			phys = __pte_val(*pte) & PAGE_MASK;
++			set_fixmap(idx, phys);
++		}
++	}
++}
++#endif /* CONFIG_X86_32 */
++
++static void __init __early_set_fixmap(enum fixed_addresses idx,
++				   unsigned long phys, pgprot_t flags)
++{
++	unsigned long addr = __fix_to_virt(idx);
++	pte_t *pte;
++
++	if (idx >= __end_of_fixed_addresses) {
++		BUG();
++		return;
++	}
++	pte = early_ioremap_pte(addr);
++	if (pgprot_val(flags))
++		set_pte(pte, pfn_pte_ma(phys >> PAGE_SHIFT, flags));
++	else
++		pte_clear(NULL, addr, pte);
++	__flush_tlb_one(addr);
++}
++
++static inline void __init early_set_fixmap(enum fixed_addresses idx,
++					unsigned long phys)
++{
++	if (after_paging_init)
++		set_fixmap(idx, phys);
++	else
++		__early_set_fixmap(idx, phys, PAGE_KERNEL);
++}
++
++static inline void __init early_clear_fixmap(enum fixed_addresses idx)
++{
++	if (after_paging_init)
++		clear_fixmap(idx);
++	else
++		__early_set_fixmap(idx, 0, __pgprot(0));
++}
++
++
++int __initdata early_ioremap_nested;
++
++static int __init check_early_ioremap_leak(void)
++{
++	if (!early_ioremap_nested)
++		return 0;
++
++	printk(KERN_WARNING
++	       "Debug warning: early ioremap leak of %d areas detected.\n",
++	       early_ioremap_nested);
++	printk(KERN_WARNING
++	       "please boot with early_ioremap_debug and report the dmesg.\n");
++	WARN_ON(1);
++
++	return 1;
++}
++late_initcall(check_early_ioremap_leak);
++
++void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
++{
++	unsigned long offset, last_addr;
++	unsigned int nrpages, nesting;
++	enum fixed_addresses idx0, idx;
++
++	WARN_ON(system_state != SYSTEM_BOOTING);
++
++	nesting = early_ioremap_nested;
++	if (early_ioremap_debug) {
++		printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
++		       phys_addr, size, nesting);
++		dump_stack();
++	}
++
++	/* Don't allow wraparound or zero size */
++	last_addr = phys_addr + size - 1;
++	if (!size || last_addr < phys_addr) {
++		WARN_ON(1);
++		return NULL;
++	}
++
++	if (nesting >= FIX_BTMAPS_NESTING) {
++		WARN_ON(1);
++		return NULL;
++	}
++	early_ioremap_nested++;
++	/*
++	 * Mappings have to be page-aligned
++	 */
++	offset = phys_addr & ~PAGE_MASK;
++	phys_addr &= PAGE_MASK;
++	size = PAGE_ALIGN(last_addr) - phys_addr;
++
++	/*
++	 * Mappings have to fit in the FIX_BTMAP area.
++	 */
++	nrpages = size >> PAGE_SHIFT;
++	if (nrpages > NR_FIX_BTMAPS) {
++		WARN_ON(1);
++		return NULL;
++	}
++
++	/*
++	 * Ok, go for it..
++	 */
++	idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
++	idx = idx0;
++	while (nrpages > 0) {
++		early_set_fixmap(idx, phys_addr);
++		phys_addr += PAGE_SIZE;
++		--idx;
++		--nrpages;
++	}
++	if (early_ioremap_debug)
++		printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
++
++	return (void *) (offset + fix_to_virt(idx0));
++}
++
++void __init early_iounmap(void *addr, unsigned long size)
++{
++	unsigned long virt_addr;
++	unsigned long offset;
++	unsigned int nrpages;
++	enum fixed_addresses idx;
++	unsigned int nesting;
++
++	nesting = --early_ioremap_nested;
++	WARN_ON(nesting < 0);
++
++	if (early_ioremap_debug) {
++		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
++		       size, nesting);
++		dump_stack();
++	}
++
++	virt_addr = (unsigned long)addr;
++	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
++		WARN_ON(1);
++		return;
++	}
++	offset = virt_addr & ~PAGE_MASK;
++	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
++
++	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
++	while (nrpages > 0) {
++		early_clear_fixmap(idx);
++		--idx;
++		--nrpages;
++	}
++}
++
++void __this_fixmap_does_not_exist(void)
++{
++	WARN_ON(1);
++}
+--- head-2010-01-18.orig/arch/x86/mm/ioremap_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,445 +0,0 @@
+-/*
+- * arch/i386/mm/ioremap.c
+- *
+- * Re-map IO memory to kernel address space so that we can access it.
+- * This is needed for high PCI addresses that aren't mapped in the
+- * 640k-1MB IO memory area on PC's
+- *
+- * (C) Copyright 1995 1996 Linus Torvalds
+- */
+-
+-#include <linux/vmalloc.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-#include <linux/io.h>
+-#include <linux/sched.h>
+-#include <asm/fixmap.h>
+-#include <asm/cacheflush.h>
+-#include <asm/tlbflush.h>
+-#include <asm/pgtable.h>
+-#include <asm/pgalloc.h>
+-
+-#define ISA_START_ADDRESS	0x0
+-#define ISA_END_ADDRESS		0x100000
+-
+-static int direct_remap_area_pte_fn(pte_t *pte, 
+-				    struct page *pmd_page,
+-				    unsigned long address, 
+-				    void *data)
+-{
+-	mmu_update_t **v = (mmu_update_t **)data;
+-
+-	BUG_ON(!pte_none(*pte));
+-
+-	(*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+-		     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+-	(*v)++;
+-
+-	return 0;
+-}
+-
+-static int __direct_remap_pfn_range(struct mm_struct *mm,
+-				    unsigned long address, 
+-				    unsigned long mfn,
+-				    unsigned long size, 
+-				    pgprot_t prot,
+-				    domid_t  domid)
+-{
+-	int rc;
+-	unsigned long i, start_address;
+-	mmu_update_t *u, *v, *w;
+-
+-	u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+-	if (u == NULL)
+-		return -ENOMEM;
+-
+-	start_address = address;
+-
+-	flush_cache_all();
+-
+-	for (i = 0; i < size; i += PAGE_SIZE) {
+-		if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
+-			/* Flush a full batch after filling in the PTE ptrs. */
+-			rc = apply_to_page_range(mm, start_address, 
+-						 address - start_address,
+-						 direct_remap_area_pte_fn, &w);
+-			if (rc)
+-				goto out;
+-			rc = -EFAULT;
+-			if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)
+-				goto out;
+-			v = w = u;
+-			start_address = address;
+-		}
+-
+-		/*
+-		 * Fill in the machine address: PTE ptr is done later by
+-		 * apply_to_page_range(). 
+-		 */
+-		v->val = __pte_val(pfn_pte_ma(mfn, prot)) | _PAGE_IO;
+-
+-		mfn++;
+-		address += PAGE_SIZE; 
+-		v++;
+-	}
+-
+-	if (v != u) {
+-		/* Final batch. */
+-		rc = apply_to_page_range(mm, start_address,
+-					 address - start_address,
+-					 direct_remap_area_pte_fn, &w);
+-		if (rc)
+-			goto out;
+-		rc = -EFAULT;
+-		if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0))
+-			goto out;
+-	}
+-
+-	rc = 0;
+-
+- out:
+-	flush_tlb_all();
+-
+-	free_page((unsigned long)u);
+-
+-	return rc;
+-}
+-
+-int direct_remap_pfn_range(struct vm_area_struct *vma,
+-			   unsigned long address, 
+-			   unsigned long mfn,
+-			   unsigned long size, 
+-			   pgprot_t prot,
+-			   domid_t  domid)
+-{
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return remap_pfn_range(vma, address, mfn, size, prot);
+-
+-	if (domid == DOMID_SELF)
+-		return -EINVAL;
+-
+-	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+-
+-	vma->vm_mm->context.has_foreign_mappings = 1;
+-
+-	return __direct_remap_pfn_range(
+-		vma->vm_mm, address, mfn, size, prot, domid);
+-}
+-EXPORT_SYMBOL(direct_remap_pfn_range);
+-
+-int direct_kernel_remap_pfn_range(unsigned long address, 
+-				  unsigned long mfn,
+-				  unsigned long size, 
+-				  pgprot_t prot,
+-				  domid_t  domid)
+-{
+-	return __direct_remap_pfn_range(
+-		&init_mm, address, mfn, size, prot, domid);
+-}
+-EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
+-
+-static int lookup_pte_fn(
+-	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+-{
+-	uint64_t *ptep = (uint64_t *)data;
+-	if (ptep)
+-		*ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+-			 PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+-	return 0;
+-}
+-
+-int create_lookup_pte_addr(struct mm_struct *mm, 
+-			   unsigned long address,
+-			   uint64_t *ptep)
+-{
+-	return apply_to_page_range(mm, address, PAGE_SIZE,
+-				   lookup_pte_fn, ptep);
+-}
+-
+-EXPORT_SYMBOL(create_lookup_pte_addr);
+-
+-static int noop_fn(
+-	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+-{
+-	return 0;
+-}
+-
+-int touch_pte_range(struct mm_struct *mm,
+-		    unsigned long address,
+-		    unsigned long size)
+-{
+-	return apply_to_page_range(mm, address, size, noop_fn, NULL);
+-} 
+-
+-EXPORT_SYMBOL(touch_pte_range);
+-
+-/*
+- * Does @address reside within a non-highmem page that is local to this virtual
+- * machine (i.e., not an I/O page, nor a memory page belonging to another VM).
+- * See the comment that accompanies mfn_to_local_pfn() in page.h to understand
+- * why this works.
+- */
+-static inline int is_local_lowmem(unsigned long address)
+-{
+-	extern unsigned long max_low_pfn;
+-	return (mfn_to_local_pfn(address >> PAGE_SHIFT) < max_low_pfn);
+-}
+-
+-/*
+- * Generic mapping function (not visible outside):
+- */
+-
+-/*
+- * Remap an arbitrary physical address space into the kernel virtual
+- * address space. Needed when the kernel wants to access high addresses
+- * directly.
+- *
+- * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+- * have to convert them into an offset in a page-aligned mapping, but the
+- * caller shouldn't need to know that small detail.
+- */
+-void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+-{
+-	void __iomem * addr;
+-	struct vm_struct * area;
+-	unsigned long offset, last_addr;
+-	pgprot_t prot;
+-	domid_t domid = DOMID_IO;
+-
+-	/* Don't allow wraparound or zero size */
+-	last_addr = phys_addr + size - 1;
+-	if (!size || last_addr < phys_addr)
+-		return NULL;
+-
+-	/*
+-	 * Don't remap the low PCI/ISA area, it's always mapped..
+-	 */
+-	if (is_initial_xendomain() &&
+-	    phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+-		return (void __iomem *) isa_bus_to_virt(phys_addr);
+-
+-	/*
+-	 * Don't allow anybody to remap normal RAM that we're using..
+-	 */
+-	if (is_local_lowmem(phys_addr)) {
+-		char *t_addr, *t_end;
+-		struct page *page;
+-
+-		t_addr = bus_to_virt(phys_addr);
+-		t_end = t_addr + (size - 1);
+-	   
+-		for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+-			if(!PageReserved(page))
+-				return NULL;
+-
+-		domid = DOMID_SELF;
+-	}
+-
+-	prot = __pgprot(_KERNPG_TABLE | flags);
+-
+-	/*
+-	 * Mappings have to be page-aligned
+-	 */
+-	offset = phys_addr & ~PAGE_MASK;
+-	phys_addr &= PAGE_MASK;
+-	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+-
+-	/*
+-	 * Ok, go for it..
+-	 */
+-	area = get_vm_area(size, VM_IOREMAP | (flags << 20));
+-	if (!area)
+-		return NULL;
+-	area->phys_addr = phys_addr;
+-	addr = (void __iomem *) area->addr;
+-	if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr,
+-				     phys_addr>>PAGE_SHIFT,
+-				     size, prot, domid)) {
+-		vunmap((void __force *) addr);
+-		return NULL;
+-	}
+-	return (void __iomem *) (offset + (char __iomem *)addr);
+-}
+-EXPORT_SYMBOL(__ioremap);
+-
+-/**
+- * ioremap_nocache     -   map bus memory into CPU space
+- * @offset:    bus address of the memory
+- * @size:      size of the resource to map
+- *
+- * ioremap_nocache performs a platform specific sequence of operations to
+- * make bus memory CPU accessible via the readb/readw/readl/writeb/
+- * writew/writel functions and the other mmio helpers. The returned
+- * address is not guaranteed to be usable directly as a virtual
+- * address. 
+- *
+- * This version of ioremap ensures that the memory is marked uncachable
+- * on the CPU as well as honouring existing caching rules from things like
+- * the PCI bus. Note that there are other caches and buffers on many 
+- * busses. In particular driver authors should read up on PCI writes
+- *
+- * It's useful if some control registers are in such an area and
+- * write combining or read caching is not desirable:
+- * 
+- * Must be freed with iounmap.
+- */
+-
+-void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+-{
+-	unsigned long last_addr;
+-	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
+-	if (!p) 
+-		return p; 
+-
+-	/* Guaranteed to be > phys_addr, as per __ioremap() */
+-	last_addr = phys_addr + size - 1;
+-
+-	if (is_local_lowmem(last_addr)) { 
+-		struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
+-		unsigned long npages;
+-
+-		phys_addr &= PAGE_MASK;
+-
+-		/* This might overflow and become zero.. */
+-		last_addr = PAGE_ALIGN(last_addr);
+-
+-		/* .. but that's ok, because modulo-2**n arithmetic will make
+-	 	* the page-aligned "last - first" come out right.
+-	 	*/
+-		npages = (last_addr - phys_addr) >> PAGE_SHIFT;
+-
+-		if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { 
+-			iounmap(p); 
+-			p = NULL;
+-		}
+-		global_flush_tlb();
+-	}
+-
+-	return p;					
+-}
+-EXPORT_SYMBOL(ioremap_nocache);
+-
+-/**
+- * iounmap - Free a IO remapping
+- * @addr: virtual address from ioremap_*
+- *
+- * Caller must ensure there is only one unmapping for the same pointer.
+- */
+-void iounmap(volatile void __iomem *addr)
+-{
+-	struct vm_struct *p, *o;
+-
+-	if ((void __force *)addr <= high_memory)
+-		return;
+-
+-	/*
+-	 * __ioremap special-cases the PCI/ISA range by not instantiating a
+-	 * vm_area and by simply returning an address into the kernel mapping
+-	 * of ISA space.   So handle that here.
+-	 */
+-	if ((unsigned long) addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+-		return;
+-
+-	addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
+-
+-	/* Use the vm area unlocked, assuming the caller
+-	   ensures there isn't another iounmap for the same address
+-	   in parallel. Reuse of the virtual address is prevented by
+-	   leaving it in the global lists until we're done with it.
+-	   cpa takes care of the direct mappings. */
+-	read_lock(&vmlist_lock);
+-	for (p = vmlist; p; p = p->next) {
+-		if (p->addr == addr)
+-			break;
+-	}
+-	read_unlock(&vmlist_lock);
+-
+-	if (!p) {
+-		printk("iounmap: bad address %p\n", addr);
+-		dump_stack();
+-		return;
+-	}
+-
+-	/* Reset the direct mapping. Can block */
+-	if ((p->flags >> 20) && is_local_lowmem(p->phys_addr)) {
+-		change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
+-				 get_vm_area_size(p) >> PAGE_SHIFT,
+-				 PAGE_KERNEL);
+-		global_flush_tlb();
+-	} 
+-
+-	/* Finally remove it */
+-	o = remove_vm_area((void *)addr);
+-	BUG_ON(p != o || o == NULL);
+-	kfree(p); 
+-}
+-EXPORT_SYMBOL(iounmap);
+-
+-void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
+-{
+-	unsigned long offset, last_addr;
+-	unsigned int nrpages;
+-	enum fixed_addresses idx;
+-
+-	/* Don't allow wraparound or zero size */
+-	last_addr = phys_addr + size - 1;
+-	if (!size || last_addr < phys_addr)
+-		return NULL;
+-
+-	/*
+-	 * Don't remap the low PCI/ISA area, it's always mapped..
+-	 */
+-	if (is_initial_xendomain() &&
+-	    phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
+-		return isa_bus_to_virt(phys_addr);
+-
+-	/*
+-	 * Mappings have to be page-aligned
+-	 */
+-	offset = phys_addr & ~PAGE_MASK;
+-	phys_addr &= PAGE_MASK;
+-	size = PAGE_ALIGN(last_addr) - phys_addr;
+-
+-	/*
+-	 * Mappings have to fit in the FIX_BTMAP area.
+-	 */
+-	nrpages = size >> PAGE_SHIFT;
+-	if (nrpages > NR_FIX_BTMAPS)
+-		return NULL;
+-
+-	/*
+-	 * Ok, go for it..
+-	 */
+-	idx = FIX_BTMAP_BEGIN;
+-	while (nrpages > 0) {
+-		set_fixmap(idx, phys_addr);
+-		phys_addr += PAGE_SIZE;
+-		--idx;
+-		--nrpages;
+-	}
+-	return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
+-}
+-
+-void __init bt_iounmap(void *addr, unsigned long size)
+-{
+-	unsigned long virt_addr;
+-	unsigned long offset;
+-	unsigned int nrpages;
+-	enum fixed_addresses idx;
+-
+-	virt_addr = (unsigned long)addr;
+-	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN))
+-		return;
+-	if (virt_addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+-		return;
+-	offset = virt_addr & ~PAGE_MASK;
+-	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+-
+-	idx = FIX_BTMAP_BEGIN;
+-	while (nrpages > 0) {
+-		clear_fixmap(idx);
+-		--idx;
+-		--nrpages;
+-	}
+-}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,1414 @@
++/*
++ * Copyright 2002 Andi Kleen, SuSE Labs.
++ * Thanks to Ben LaHaise for precious feedback.
++ */
++#include <linux/highmem.h>
++#include <linux/bootmem.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++
++#include <asm/e820.h>
++#include <asm/processor.h>
++#include <asm/tlbflush.h>
++#include <asm/sections.h>
++#include <asm/uaccess.h>
++#include <asm/pgalloc.h>
++#include <asm/proto.h>
++#include <asm/mmu_context.h>
++
++#ifndef CONFIG_X86_64
++#define TASK_SIZE64 TASK_SIZE
++#endif
++
++static void _pin_lock(struct mm_struct *mm, int lock) {
++	if (lock)
++		spin_lock(&mm->page_table_lock);
++#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
++	/* While mm->page_table_lock protects us against insertions and
++	 * removals of higher level page table pages, it doesn't protect
++	 * against updates of pte-s. Such updates, however, require the
++	 * pte pages to be in consistent state (unpinned+writable or
++	 * pinned+readonly). The pinning and attribute changes, however
++	 * cannot be done atomically, which is why such updates must be
++	 * prevented from happening concurrently.
++	 * Note that no pte lock can ever elsewhere be acquired nesting
++	 * with an already acquired one in the same mm, or with the mm's
++	 * page_table_lock already acquired, as that would break in the
++	 * non-split case (where all these are actually resolving to the
++	 * one page_table_lock). Thus acquiring all of them here is not
++	 * going to result in dead locks, and the order of acquires
++	 * doesn't matter.
++	 */
++	{
++		pgd_t *pgd = mm->pgd;
++		unsigned g;
++
++		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++			pud_t *pud;
++			unsigned u;
++
++			if (pgd_none(*pgd))
++				continue;
++			pud = pud_offset(pgd, 0);
++			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++				pmd_t *pmd;
++				unsigned m;
++
++				if (pud_none(*pud))
++					continue;
++				pmd = pmd_offset(pud, 0);
++				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++					spinlock_t *ptl;
++
++					if (pmd_none(*pmd))
++						continue;
++					ptl = pte_lockptr(0, pmd);
++					if (lock)
++						spin_lock(ptl);
++					else
++						spin_unlock(ptl);
++				}
++			}
++		}
++	}
++#endif
++	if (!lock)
++		spin_unlock(&mm->page_table_lock);
++}
++#define pin_lock(mm) _pin_lock(mm, 1)
++#define pin_unlock(mm) _pin_lock(mm, 0)
++
++#define PIN_BATCH sizeof(void *)
++static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
++
++static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
++					     unsigned int cpu, unsigned int seq)
++{
++	unsigned long pfn = page_to_pfn(page);
++
++	if (PageHighMem(page)) {
++		if (pgprot_val(flags) & _PAGE_RW)
++			ClearPagePinned(page);
++		else
++			SetPagePinned(page);
++	} else {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++					(unsigned long)__va(pfn << PAGE_SHIFT),
++					pfn_pte(pfn, flags), 0);
++		if (unlikely(++seq == PIN_BATCH)) {
++			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++								PIN_BATCH, NULL)))
++				BUG();
++			seq = 0;
++		}
++	}
++
++	return seq;
++}
++
++static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
++{
++	pgd_t       *pgd = pgd_base;
++	pud_t       *pud;
++	pmd_t       *pmd;
++	int          g,u,m;
++	unsigned int cpu, seq;
++	multicall_entry_t *mcl;
++
++	if (xen_feature(XENFEAT_auto_translated_physmap))
++		return;
++
++	cpu = get_cpu();
++
++	/*
++	 * Cannot iterate up to USER_PTRS_PER_PGD on x86-64 as these pagetables
++	 * may not be the 'current' task's pagetables (e.g., current may be
++	 * 32-bit, but the pagetables may be for a 64-bit task).
++	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
++	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
++	 */
++	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
++		if (pgd_none(*pgd))
++			continue;
++		pud = pud_offset(pgd, 0);
++		if (PTRS_PER_PUD > 1) /* not folded */
++			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
++		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
++			if (pud_none(*pud))
++				continue;
++			pmd = pmd_offset(pud, 0);
++			if (PTRS_PER_PMD > 1) /* not folded */
++				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
++			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
++				if (pmd_none(*pmd))
++					continue;
++				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
++			}
++		}
++	}
++
++	mcl = per_cpu(pb_mcl, cpu);
++#ifdef CONFIG_X86_64
++	if (unlikely(seq > PIN_BATCH - 2)) {
++		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
++			BUG();
++		seq = 0;
++	}
++	MULTI_update_va_mapping(mcl + seq,
++	       (unsigned long)__user_pgd(pgd_base),
++	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
++	       0);
++	MULTI_update_va_mapping(mcl + seq + 1,
++	       (unsigned long)pgd_base,
++	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++	       UVMF_TLB_FLUSH);
++	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
++		BUG();
++#else
++	if (likely(seq != 0)) {
++		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
++			(unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH);
++		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
++		                                        seq + 1, NULL)))
++			BUG();
++	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
++			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
++			UVMF_TLB_FLUSH))
++		BUG();
++#endif
++
++	put_cpu();
++}
++
++static void __pgd_pin(pgd_t *pgd)
++{
++	pgd_walk(pgd, PAGE_KERNEL_RO);
++	kmap_flush_unused();
++	xen_pgd_pin(__pa(pgd)); /* kernel */
++#ifdef CONFIG_X86_64
++	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
++#endif
++	SetPagePinned(virt_to_page(pgd));
++}
++
++static void __pgd_unpin(pgd_t *pgd)
++{
++	xen_pgd_unpin(__pa(pgd));
++#ifdef CONFIG_X86_64
++	xen_pgd_unpin(__pa(__user_pgd(pgd)));
++#endif
++	pgd_walk(pgd, PAGE_KERNEL);
++	ClearPagePinned(virt_to_page(pgd));
++}
++
++void pgd_test_and_unpin(pgd_t *pgd)
++{
++	if (PagePinned(virt_to_page(pgd)))
++		__pgd_unpin(pgd);
++}
++
++void mm_pin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++	__pgd_pin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_unpin(struct mm_struct *mm)
++{
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	pin_lock(mm);
++	__pgd_unpin(mm->pgd);
++	pin_unlock(mm);
++}
++
++void mm_pin_all(void)
++{
++	struct page *page;
++	unsigned long flags;
++
++	if (xen_feature(XENFEAT_writable_page_tables))
++		return;
++
++	/*
++	 * Allow uninterrupted access to the pgd_list. Also protects
++	 * __pgd_pin() by disabling preemption.
++	 * All other CPUs must be at a safe point (e.g., in stop_machine
++	 * or offlined entirely).
++	 */
++	spin_lock_irqsave(&pgd_lock, flags);
++	list_for_each_entry(page, &pgd_list, lru) {
++		if (!PagePinned(page))
++			__pgd_pin((pgd_t *)page_address(page));
++	}
++	spin_unlock_irqrestore(&pgd_lock, flags);
++}
++
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
++{
++	if (!PagePinned(virt_to_page(mm->pgd)))
++		mm_pin(mm);
++}
++
++void arch_exit_mmap(struct mm_struct *mm)
++{
++	struct task_struct *tsk = current;
++
++	task_lock(tsk);
++
++	/*
++	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
++	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
++	 */
++	if (tsk->active_mm == mm) {
++		tsk->active_mm = &init_mm;
++		atomic_inc(&init_mm.mm_count);
++
++		switch_mm(mm, &init_mm, tsk);
++
++		atomic_dec(&mm->mm_count);
++		BUG_ON(atomic_read(&mm->mm_count) == 0);
++	}
++
++	task_unlock(tsk);
++
++	if (PagePinned(virt_to_page(mm->pgd))
++	    && atomic_read(&mm->mm_count) == 1
++	    && !mm->context.has_foreign_mappings)
++		mm_unpin(mm);
++}
++
++static void _pte_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	__pte_free(page);
++}
++
++pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pte;
++
++#ifdef CONFIG_HIGHPTE
++	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
++#else
++	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++#endif
++	if (pte) {
++		pgtable_page_ctor(pte);
++		SetPageForeign(pte, _pte_free);
++		init_page_count(pte);
++	}
++	return pte;
++}
++
++void __pte_free(pgtable_t pte)
++{
++	if (!PageHighMem(pte)) {
++		unsigned long va = (unsigned long)page_address(pte);
++		unsigned int level;
++		pte_t *ptep = lookup_address(va, &level);
++
++		BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
++		if (!pte_write(*ptep)
++		    && HYPERVISOR_update_va_mapping(va,
++						    mk_pte(pte, PAGE_KERNEL),
++						    0))
++			BUG();
++	} else
++#ifdef CONFIG_HIGHPTE
++		ClearPagePinned(pte);
++#else
++		BUG();
++#endif
++
++	ClearPageForeign(pte);
++	init_page_count(pte);
++	pgtable_page_dtor(pte);
++	__free_page(pte);
++}
++
++#if PAGETABLE_LEVELS >= 3
++static void _pmd_free(struct page *page, unsigned int order)
++{
++	BUG_ON(order);
++	__pmd_free(page);
++}
++
++pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	struct page *pmd;
++
++	pmd = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++	if (!pmd)
++		return NULL;
++	SetPageForeign(pmd, _pmd_free);
++	init_page_count(pmd);
++	return page_address(pmd);
++}
++
++void __pmd_free(pgtable_t pmd)
++{
++	unsigned long va = (unsigned long)page_address(pmd);
++	unsigned int level;
++	pte_t *ptep = lookup_address(va, &level);
++
++	BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep));
++	if (!pte_write(*ptep)
++	    && HYPERVISOR_update_va_mapping(va, mk_pte(pmd, PAGE_KERNEL), 0))
++		BUG();
++
++	ClearPageForeign(pmd);
++	init_page_count(pmd);
++	__free_page(pmd);
++}
++#endif
++
++/* blktap and gntdev need this, as otherwise they would implicitly (and
++ * needlessly, as they never use it) reference init_mm. */
++pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *vma,
++				  unsigned long addr, pte_t *ptep, int full)
++{
++	return ptep_get_and_clear_full(vma ? vma->vm_mm : &init_mm,
++				       addr, ptep, full);
++}
++EXPORT_SYMBOL_GPL(xen_ptep_get_and_clear_full);
++
++/*
++ * The current flushing context - we pass it instead of 5 arguments:
++ */
++struct cpa_data {
++	unsigned long	vaddr;
++	pgprot_t	mask_set;
++	pgprot_t	mask_clr;
++	int		numpages;
++	int		flushtlb;
++	unsigned long	pfn;
++};
++
++#ifdef CONFIG_X86_64
++
++static inline unsigned long highmap_start_pfn(void)
++{
++	return __pa(_text) >> PAGE_SHIFT;
++}
++
++static inline unsigned long highmap_end_pfn(void)
++{
++	return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
++}
++
++#endif
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++# define debug_pagealloc 1
++#else
++# define debug_pagealloc 0
++#endif
++
++static inline int
++within(unsigned long addr, unsigned long start, unsigned long end)
++{
++	return addr >= start && addr < end;
++}
++
++/*
++ * Flushing functions
++ */
++
++/**
++ * clflush_cache_range - flush a cache range with clflush
++ * @addr:	virtual start address
++ * @size:	number of bytes to flush
++ *
++ * clflush is an unordered instruction which needs fencing with mfence
++ * to avoid ordering issues.
++ */
++void clflush_cache_range(void *vaddr, unsigned int size)
++{
++	void *vend = vaddr + size - 1;
++
++	mb();
++
++	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
++		clflush(vaddr);
++	/*
++	 * Flush any possible final partial cacheline:
++	 */
++	clflush(vend);
++
++	mb();
++}
++
++static void __cpa_flush_all(void *arg)
++{
++	unsigned long cache = (unsigned long)arg;
++
++	/*
++	 * Flush all to work around Errata in early athlons regarding
++	 * large page flushing.
++	 */
++	__flush_tlb_all();
++
++	if (cache && boot_cpu_data.x86_model >= 4)
++		wbinvd();
++}
++
++static void cpa_flush_all(unsigned long cache)
++{
++	BUG_ON(irqs_disabled());
++
++	on_each_cpu(__cpa_flush_all, (void *) cache, 1, 1);
++}
++
++static void __cpa_flush_range(void *arg)
++{
++	/*
++	 * We could optimize that further and do individual per page
++	 * tlb invalidates for a low number of pages. Caveat: we must
++	 * flush the high aliases on 64bit as well.
++	 */
++	__flush_tlb_all();
++}
++
++static void cpa_flush_range(unsigned long start, int numpages, int cache)
++{
++	unsigned int i, level;
++	unsigned long addr;
++
++	BUG_ON(irqs_disabled());
++	WARN_ON(PAGE_ALIGN(start) != start);
++
++	on_each_cpu(__cpa_flush_range, NULL, 1, 1);
++
++	if (!cache)
++		return;
++
++	/*
++	 * We only need to flush on one CPU,
++	 * clflush is a MESI-coherent instruction that
++	 * will cause all other CPUs to flush the same
++	 * cachelines:
++	 */
++	for (i = 0, addr = start; i < numpages; i++, addr += PAGE_SIZE) {
++		pte_t *pte = lookup_address(addr, &level);
++
++		/*
++		 * Only flush present addresses:
++		 */
++		if (pte && (__pte_val(*pte) & _PAGE_PRESENT))
++			clflush_cache_range((void *) addr, PAGE_SIZE);
++	}
++}
++
++/*
++ * Certain areas of memory on x86 require very specific protection flags,
++ * for example the BIOS area or kernel text. Callers don't always get this
++ * right (again, ioremap() on BIOS memory is not uncommon) so this function
++ * checks and fixes these known static required protection bits.
++ */
++static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
++				   unsigned long pfn)
++{
++	pgprot_t forbidden = __pgprot(0);
++
++#ifndef CONFIG_XEN
++	/*
++	 * The BIOS area between 640k and 1Mb needs to be executable for
++	 * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
++	 */
++	if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
++		pgprot_val(forbidden) |= _PAGE_NX;
++#endif
++
++	/*
++	 * The kernel text needs to be executable for obvious reasons
++	 * Does not cover __inittext since that is gone later on. On
++	 * 64bit we do not enforce !NX on the low mapping
++	 */
++	if (within(address, (unsigned long)_text, (unsigned long)_etext))
++		pgprot_val(forbidden) |= _PAGE_NX;
++
++	/*
++	 * The .rodata section needs to be read-only. Using the pfn
++	 * catches all aliases.
++	 */
++	if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
++		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
++		pgprot_val(forbidden) |= _PAGE_RW;
++
++	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
++
++	return prot;
++}
++
++/*
++ * Lookup the page table entry for a virtual address. Return a pointer
++ * to the entry and the level of the mapping.
++ *
++ * Note: We return pud and pmd either when the entry is marked large
++ * or when the present bit is not set. Otherwise we would return a
++ * pointer to a nonexisting mapping.
++ */
++pte_t *lookup_address(unsigned long address, unsigned int *level)
++{
++	pgd_t *pgd = pgd_offset_k(address);
++	pud_t *pud;
++	pmd_t *pmd;
++
++	*level = PG_LEVEL_NONE;
++
++	if (pgd_none(*pgd))
++		return NULL;
++
++	pud = pud_offset(pgd, address);
++	if (pud_none(*pud))
++		return NULL;
++
++	*level = PG_LEVEL_1G;
++	if (pud_large(*pud) || !pud_present(*pud))
++		return (pte_t *)pud;
++
++	pmd = pmd_offset(pud, address);
++	if (pmd_none(*pmd))
++		return NULL;
++
++	*level = PG_LEVEL_2M;
++	if (pmd_large(*pmd) || !pmd_present(*pmd))
++		return (pte_t *)pmd;
++
++	*level = PG_LEVEL_4K;
++
++	return pte_offset_kernel(pmd, address);
++}
++
++/*
++ * Set the new pmd in all the pgds we know about:
++ */
++static void __set_pmd_pte(pte_t *kpte, unsigned long address,
++			  unsigned int level, pte_t pte)
++{
++	/* change init_mm */
++	switch(level) {
++	case PG_LEVEL_2M:
++		xen_l2_entry_update((pmd_t *)kpte, __pmd_ma(__pte_val(pte)));
++		break;
++#ifdef CONFIG_X86_64
++	case PG_LEVEL_1G:
++		xen_l3_entry_update((pud_t *)kpte, __pud_ma(__pte_val(pte)));
++		break;
++#endif
++	default:
++		BUG();
++	}
++#ifdef CONFIG_X86_32
++	if (!SHARED_KERNEL_PMD) {
++		struct page *page;
++
++		list_for_each_entry(page, &pgd_list, lru) {
++			pgd_t *pgd;
++			pud_t *pud;
++			pmd_t *pmd;
++
++			pgd = (pgd_t *)page_address(page) + pgd_index(address);
++			pud = pud_offset(pgd, address);
++			pmd = pmd_offset(pud, address);
++			xen_l2_entry_update(pmd, __pmd_ma(__pte_val(pte)));
++		}
++	}
++#endif
++}
++
++static int
++try_preserve_large_page(pte_t *kpte, unsigned long address,
++			struct cpa_data *cpa)
++{
++	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
++	pte_t new_pte, old_pte, *tmp;
++	pgprot_t old_prot, new_prot;
++	int i, do_split = 1;
++	unsigned int level;
++
++	spin_lock_irqsave(&pgd_lock, flags);
++	/*
++	 * Check for races, another CPU might have split this page
++	 * up already:
++	 */
++	tmp = lookup_address(address, &level);
++	if (tmp != kpte)
++		goto out_unlock;
++
++	switch (level) {
++	case PG_LEVEL_2M:
++		psize = PMD_PAGE_SIZE;
++		pmask = PMD_PAGE_MASK;
++		break;
++#ifdef CONFIG_X86_64
++	case PG_LEVEL_1G:
++		psize = PUD_PAGE_SIZE;
++		pmask = PUD_PAGE_MASK;
++		break;
++#endif
++	default:
++		do_split = -EINVAL;
++		goto out_unlock;
++	}
++
++	/*
++	 * Calculate the number of pages, which fit into this large
++	 * page starting at address:
++	 */
++	nextpage_addr = (address + psize) & pmask;
++	numpages = (nextpage_addr - address) >> PAGE_SHIFT;
++	if (numpages < cpa->numpages)
++		cpa->numpages = numpages;
++
++	/*
++	 * We are safe now. Check whether the new pgprot is the same:
++	 */
++	old_pte = *kpte;
++	old_prot = new_prot = pte_pgprot(old_pte);
++
++	pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
++	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
++
++	/*
++	 * old_pte points to the large page base address. So we need
++	 * to add the offset of the virtual address:
++	 */
++	pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT);
++	cpa->pfn = pfn;
++
++	new_prot = static_protections(new_prot, address, pfn);
++
++	/*
++	 * We need to check the full range, whether
++	 * static_protection() requires a different pgprot for one of
++	 * the pages in the range we try to preserve:
++	 */
++	if (pfn < max_mapnr) {
++		addr = address + PAGE_SIZE;
++		for (i = 1; i < cpa->numpages && ++pfn < max_mapnr;
++		     i++, addr += PAGE_SIZE) {
++			pgprot_t chk_prot = static_protections(new_prot, addr, pfn);
++
++			if (pgprot_val(chk_prot) != pgprot_val(new_prot))
++				goto out_unlock;
++		}
++	}
++
++	/*
++	 * If there are no changes, return. maxpages has been updated
++	 * above:
++	 */
++	if (pgprot_val(new_prot) == pgprot_val(old_prot)) {
++		do_split = 0;
++		goto out_unlock;
++	}
++
++	/*
++	 * We need to change the attributes. Check, whether we can
++	 * change the large page in one go. We request a split, when
++	 * the address is not aligned and the number of pages is
++	 * smaller than the number of pages in the large page. Note
++	 * that we limited the number of possible pages already to
++	 * the number of pages in the large page.
++	 */
++	if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
++		/*
++		 * The address is aligned and the number of pages
++		 * covers the full page.
++		 */
++		new_pte = pfn_pte_ma(__pte_mfn(old_pte), canon_pgprot(new_prot));
++		__set_pmd_pte(kpte, address, level, new_pte);
++		cpa->flushtlb = 1;
++		do_split = 0;
++	}
++
++out_unlock:
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	return do_split;
++}
++
++static LIST_HEAD(page_pool);
++static unsigned long pool_size, pool_pages, pool_low;
++static unsigned long pool_used, pool_failed;
++
++static void cpa_fill_pool(struct page **ret)
++{
++	gfp_t gfp = GFP_KERNEL;
++	unsigned long flags;
++	struct page *p;
++
++	/*
++	 * Avoid recursion (on debug-pagealloc) and also signal
++	 * our priority to get to these pagetables:
++	 */
++	if (current->flags & PF_MEMALLOC)
++		return;
++	current->flags |= PF_MEMALLOC;
++
++	/*
++	 * Allocate atomically from atomic contexts:
++	 */
++	if (in_atomic() || irqs_disabled() || debug_pagealloc)
++		gfp =  GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
++
++	while (pool_pages < pool_size || (ret && !*ret)) {
++		p = alloc_pages(gfp, 0);
++		if (!p) {
++			pool_failed++;
++			break;
++		}
++		/*
++		 * If the call site needs a page right now, provide it:
++		 */
++		if (ret && !*ret) {
++			*ret = p;
++			continue;
++		}
++		spin_lock_irqsave(&pgd_lock, flags);
++		list_add(&p->lru, &page_pool);
++		pool_pages++;
++		spin_unlock_irqrestore(&pgd_lock, flags);
++	}
++
++	current->flags &= ~PF_MEMALLOC;
++}
++
++#define SHIFT_MB		(20 - PAGE_SHIFT)
++#define ROUND_MB_GB		((1 << 10) - 1)
++#define SHIFT_MB_GB		10
++#define POOL_PAGES_PER_GB	16
++
++void __init cpa_init(void)
++{
++	struct sysinfo si;
++	unsigned long gb;
++
++	si_meminfo(&si);
++	/*
++	 * Calculate the number of pool pages:
++	 *
++	 * Convert totalram (nr of pages) to MiB and round to the next
++	 * GiB. Shift MiB to Gib and multiply the result by
++	 * POOL_PAGES_PER_GB:
++	 */
++	if (debug_pagealloc) {
++		gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB;
++		pool_size = POOL_PAGES_PER_GB * gb;
++	} else {
++		pool_size = 1;
++	}
++	pool_low = pool_size;
++
++	cpa_fill_pool(NULL);
++	printk(KERN_DEBUG
++	       "CPA: page pool initialized %lu of %lu pages preallocated\n",
++	       pool_pages, pool_size);
++}
++
++static int split_large_page(pte_t *kpte, unsigned long address)
++{
++	unsigned long flags, mfn, mfninc = 1;
++	unsigned int i, level;
++	pte_t *pbase, *tmp;
++	pgprot_t ref_prot;
++	struct page *base;
++
++	/*
++	 * Get a page from the pool. The pool list is protected by the
++	 * pgd_lock, which we have to take anyway for the split
++	 * operation:
++	 */
++	spin_lock_irqsave(&pgd_lock, flags);
++	if (list_empty(&page_pool)) {
++		spin_unlock_irqrestore(&pgd_lock, flags);
++		base = NULL;
++		cpa_fill_pool(&base);
++		if (!base)
++			return -ENOMEM;
++		spin_lock_irqsave(&pgd_lock, flags);
++	} else {
++		base = list_first_entry(&page_pool, struct page, lru);
++		list_del(&base->lru);
++		pool_pages--;
++
++		if (pool_pages < pool_low)
++			pool_low = pool_pages;
++	}
++
++	/*
++	 * Check for races, another CPU might have split this page
++	 * up for us already:
++	 */
++	tmp = lookup_address(address, &level);
++	if (tmp != kpte)
++		goto out_unlock;
++
++	pbase = (pte_t *)page_address(base);
++#ifdef CONFIG_X86_32
++	paravirt_alloc_pt(&init_mm, page_to_pfn(base));
++#endif
++	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
++
++#ifdef CONFIG_X86_64
++	if (level == PG_LEVEL_1G) {
++		mfninc = PMD_PAGE_SIZE >> PAGE_SHIFT;
++		pgprot_val(ref_prot) |= _PAGE_PSE;
++	}
++#endif
++
++	/*
++	 * Get the target mfn from the original entry:
++	 */
++	mfn = __pte_mfn(*kpte);
++	for (i = 0; i < PTRS_PER_PTE; i++, mfn += mfninc)
++		set_pte(&pbase[i], pfn_pte_ma(mfn, ref_prot));
++
++	/*
++	 * Install the new, split up pagetable. Important details here:
++	 *
++	 * On Intel the NX bit of all levels must be cleared to make a
++	 * page executable. See section 4.13.2 of Intel 64 and IA-32
++	 * Architectures Software Developer's Manual).
++	 *
++	 * Mark the entry present. The current mapping might be
++	 * set to not present, which we preserved above.
++	 */
++	if (!xen_feature(XENFEAT_writable_page_tables) &&
++	    HYPERVISOR_update_va_mapping((unsigned long)pbase,
++					 mk_pte(base, PAGE_KERNEL_RO), 0))
++		BUG();
++	ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
++	pgprot_val(ref_prot) |= _PAGE_PRESENT;
++	__set_pmd_pte(kpte, address, level, mk_pte(base, ref_prot));
++	base = NULL;
++
++out_unlock:
++	/*
++	 * If we dropped out via the lookup_address check under
++	 * pgd_lock then stick the page back into the pool:
++	 */
++	if (base) {
++		list_add(&base->lru, &page_pool);
++		pool_pages++;
++	} else
++		pool_used++;
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	return 0;
++}
++
++static int __change_page_attr(struct cpa_data *cpa, int primary)
++{
++	unsigned long address = cpa->vaddr;
++	int do_split, err;
++	unsigned int level;
++	pte_t *kpte, old_pte;
++
++repeat:
++	kpte = lookup_address(address, &level);
++	if (!kpte)
++		return primary ? -EINVAL : 0;
++
++	old_pte = *kpte;
++	if (!__pte_val(old_pte)) {
++		if (!primary)
++			return 0;
++		printk(KERN_WARNING "CPA: called for zero pte. "
++		       "vaddr = %lx cpa->vaddr = %lx\n", address,
++		       cpa->vaddr);
++		WARN_ON(1);
++		return -EINVAL;
++	}
++
++	if (level == PG_LEVEL_4K) {
++		pte_t new_pte;
++		pgprot_t new_prot = pte_pgprot(old_pte);
++		unsigned long mfn = __pte_mfn(old_pte);
++
++		pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
++		pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
++
++		new_prot = static_protections(new_prot, address,
++					      mfn_to_local_pfn(mfn));
++
++		/*
++		 * We need to keep the mfn from the existing PTE,
++		 * after all we're only going to change it's attributes
++		 * not the memory it points to
++		 */
++		new_pte = pfn_pte_ma(mfn, canon_pgprot(new_prot));
++		cpa->pfn = mfn_to_local_pfn(mfn);
++		/*
++		 * Do we really change anything ?
++		 */
++		if (__pte_val(old_pte) != __pte_val(new_pte)) {
++			set_pte_atomic(kpte, new_pte);
++			cpa->flushtlb = 1;
++		}
++		cpa->numpages = 1;
++		return 0;
++	}
++
++	/*
++	 * Check, whether we can keep the large page intact
++	 * and just change the pte:
++	 */
++	do_split = try_preserve_large_page(kpte, address, cpa);
++	/*
++	 * When the range fits into the existing large page,
++	 * return. cp->numpages and cpa->tlbflush have been updated in
++	 * try_large_page:
++	 */
++	if (do_split <= 0)
++		return do_split;
++
++	/*
++	 * We have to split the large page:
++	 */
++	err = split_large_page(kpte, address);
++	if (!err) {
++		cpa->flushtlb = 1;
++		goto repeat;
++	}
++
++	return err;
++}
++
++static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias);
++
++static int cpa_process_alias(struct cpa_data *cpa)
++{
++	struct cpa_data alias_cpa;
++	int ret = 0;
++
++	if (cpa->pfn > max_pfn_mapped)
++		return 0;
++
++	/*
++	 * No need to redo, when the primary call touched the direct
++	 * mapping already:
++	 */
++	if (!within(cpa->vaddr, PAGE_OFFSET,
++		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
++
++		alias_cpa = *cpa;
++		alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
++
++		ret = __change_page_attr_set_clr(&alias_cpa, 0);
++	}
++
++#ifdef CONFIG_X86_64
++	if (ret)
++		return ret;
++	/*
++	 * No need to redo, when the primary call touched the high
++	 * mapping already:
++	 */
++	if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end))
++		return 0;
++
++	/*
++	 * If the physical address is inside the kernel map, we need
++	 * to touch the high mapped kernel as well:
++	 */
++	if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
++		return 0;
++
++	alias_cpa = *cpa;
++	alias_cpa.vaddr =
++		(cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
++
++	/*
++	 * The high mapping range is imprecise, so ignore the return value.
++	 */
++	__change_page_attr_set_clr(&alias_cpa, 0);
++#endif
++	return ret;
++}
++
++static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
++{
++	int ret, numpages = cpa->numpages;
++
++	while (numpages) {
++		/*
++		 * Store the remaining nr of pages for the large page
++		 * preservation check.
++		 */
++		cpa->numpages = numpages;
++
++		ret = __change_page_attr(cpa, checkalias);
++		if (ret)
++			return ret;
++
++		if (checkalias) {
++			ret = cpa_process_alias(cpa);
++			if (ret)
++				return ret;
++		}
++
++		/*
++		 * Adjust the number of pages with the result of the
++		 * CPA operation. Either a large page has been
++		 * preserved or a single page update happened.
++		 */
++		BUG_ON(cpa->numpages > numpages);
++		numpages -= cpa->numpages;
++		cpa->vaddr += cpa->numpages * PAGE_SIZE;
++	}
++	return 0;
++}
++
++static inline int cache_attr(pgprot_t attr)
++{
++	return pgprot_val(attr) &
++		(_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
++}
++
++static int change_page_attr_set_clr(unsigned long addr, int numpages,
++				    pgprot_t mask_set, pgprot_t mask_clr)
++{
++	struct cpa_data cpa;
++	int ret, cache, checkalias;
++
++	/*
++	 * Check, if we are requested to change a not supported
++	 * feature:
++	 */
++	mask_set = canon_pgprot(mask_set);
++	mask_clr = canon_pgprot(mask_clr);
++	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
++		return 0;
++
++	/* Ensure we are PAGE_SIZE aligned */
++	if (addr & ~PAGE_MASK) {
++		addr &= PAGE_MASK;
++		/*
++		 * People should not be passing in unaligned addresses:
++		 */
++		WARN_ON_ONCE(1);
++	}
++
++	cpa.vaddr = addr;
++	cpa.numpages = numpages;
++	cpa.mask_set = mask_set;
++	cpa.mask_clr = mask_clr;
++	cpa.flushtlb = 0;
++
++	/* No alias checking for _NX bit modifications */
++	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
++
++	ret = __change_page_attr_set_clr(&cpa, checkalias);
++
++	/*
++	 * Check whether we really changed something:
++	 */
++	if (!cpa.flushtlb)
++		goto out;
++
++	/*
++	 * No need to flush, when we did not set any of the caching
++	 * attributes:
++	 */
++	cache = cache_attr(mask_set);
++
++	/*
++	 * On success we use clflush, when the CPU supports it to
++	 * avoid the wbindv. If the CPU does not support it and in the
++	 * error case we fall back to cpa_flush_all (which uses
++	 * wbindv):
++	 */
++	if (!ret && cpu_has_clflush)
++		cpa_flush_range(addr, numpages, cache);
++	else
++		cpa_flush_all(cache);
++
++out:
++	cpa_fill_pool(NULL);
++
++	return ret;
++}
++
++static inline int change_page_attr_set(unsigned long addr, int numpages,
++				       pgprot_t mask)
++{
++	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
++}
++
++static inline int change_page_attr_clear(unsigned long addr, int numpages,
++					 pgprot_t mask)
++{
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
++}
++
++int set_memory_uc(unsigned long addr, int numpages)
++{
++	return change_page_attr_set(addr, numpages,
++				    __pgprot(_PAGE_PCD));
++}
++EXPORT_SYMBOL(set_memory_uc);
++
++int set_memory_wb(unsigned long addr, int numpages)
++{
++	return change_page_attr_clear(addr, numpages,
++				      __pgprot(_PAGE_PCD | _PAGE_PWT));
++}
++EXPORT_SYMBOL(set_memory_wb);
++
++int set_memory_x(unsigned long addr, int numpages)
++{
++	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX));
++}
++EXPORT_SYMBOL(set_memory_x);
++
++int set_memory_nx(unsigned long addr, int numpages)
++{
++	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX));
++}
++EXPORT_SYMBOL(set_memory_nx);
++
++int set_memory_ro(unsigned long addr, int numpages)
++{
++	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW));
++}
++
++int set_memory_rw(unsigned long addr, int numpages)
++{
++	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW));
++}
++
++int set_memory_np(unsigned long addr, int numpages)
++{
++	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
++}
++
++int set_pages_uc(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_uc(addr, numpages);
++}
++EXPORT_SYMBOL(set_pages_uc);
++
++int set_pages_wb(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_wb(addr, numpages);
++}
++EXPORT_SYMBOL(set_pages_wb);
++
++int set_pages_x(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_x(addr, numpages);
++}
++EXPORT_SYMBOL(set_pages_x);
++
++int set_pages_nx(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_nx(addr, numpages);
++}
++EXPORT_SYMBOL(set_pages_nx);
++
++int set_pages_ro(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_ro(addr, numpages);
++}
++
++int set_pages_rw(struct page *page, int numpages)
++{
++	unsigned long addr = (unsigned long)page_address(page);
++
++	return set_memory_rw(addr, numpages);
++}
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++
++static int __set_pages_p(struct page *page, int numpages)
++{
++	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++				.numpages = numpages,
++				.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
++				.mask_clr = __pgprot(0)};
++
++	return __change_page_attr_set_clr(&cpa, 1);
++}
++
++static int __set_pages_np(struct page *page, int numpages)
++{
++	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++				.numpages = numpages,
++				.mask_set = __pgprot(0),
++				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)};
++
++	return __change_page_attr_set_clr(&cpa, 1);
++}
++
++void kernel_map_pages(struct page *page, int numpages, int enable)
++{
++	if (PageHighMem(page))
++		return;
++	if (!enable) {
++		debug_check_no_locks_freed(page_address(page),
++					   numpages * PAGE_SIZE);
++	}
++
++	/*
++	 * If page allocator is not up yet then do not call c_p_a():
++	 */
++	if (!debug_pagealloc_enabled)
++		return;
++
++	/*
++	 * The return value is ignored as the calls cannot fail.
++	 * Large pages are kept enabled at boot time, and are
++	 * split up quickly with DEBUG_PAGEALLOC. If a splitup
++	 * fails here (due to temporary memory shortage) no damage
++	 * is done because we just keep the largepage intact up
++	 * to the next attempt when it will likely be split up:
++	 */
++	if (enable)
++		__set_pages_p(page, numpages);
++	else
++		__set_pages_np(page, numpages);
++
++	/*
++	 * We should perform an IPI and flush all tlbs,
++	 * but that can deadlock->flush only current cpu:
++	 */
++	__flush_tlb_all();
++
++	/*
++	 * Try to refill the page pool here. We can do this only after
++	 * the tlb flush.
++	 */
++	cpa_fill_pool(NULL);
++}
++
++#ifdef CONFIG_HIBERNATION
++
++bool kernel_page_present(struct page *page)
++{
++	unsigned int level;
++	pte_t *pte;
++
++	if (PageHighMem(page))
++		return false;
++
++	pte = lookup_address((unsigned long)page_address(page), &level);
++	return (__pte_val(*pte) & _PAGE_PRESENT);
++}
++
++#endif /* CONFIG_HIBERNATION */
++
++#endif /* CONFIG_DEBUG_PAGEALLOC */
++
++static inline int in_secondary_range(unsigned long va)
++{
++#ifdef CONFIG_X86_64
++	return va >= VMALLOC_START && va < VMALLOC_END;
++#else
++	return va >= (unsigned long)high_memory;
++#endif
++}
++
++static void __make_page_readonly(unsigned long va)
++{
++	pte_t *pte;
++	unsigned int level;
++
++	pte = lookup_address(va, &level);
++	BUG_ON(!pte || level != PG_LEVEL_4K);
++	if (HYPERVISOR_update_va_mapping(va, pte_wrprotect(*pte), 0))
++		BUG();
++	if (in_secondary_range(va)) {
++		unsigned long pfn = pte_pfn(*pte);
++
++#ifdef CONFIG_HIGHMEM
++		if (pfn >= highstart_pfn)
++			kmap_flush_unused(); /* flush stale writable kmaps */
++		else
++#endif
++			__make_page_readonly((unsigned long)__va(pfn << PAGE_SHIFT));
++	}
++}
++
++static void __make_page_writable(unsigned long va)
++{
++	pte_t *pte;
++	unsigned int level;
++
++	pte = lookup_address(va, &level);
++	BUG_ON(!pte || level != PG_LEVEL_4K);
++	if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), 0))
++		BUG();
++	if (in_secondary_range(va)) {
++		unsigned long pfn = pte_pfn(*pte);
++
++#ifdef CONFIG_HIGHMEM
++		if (pfn < highstart_pfn)
++#endif
++			__make_page_writable((unsigned long)__va(pfn << PAGE_SHIFT));
++	}
++}
++
++void make_page_readonly(void *va, unsigned int feature)
++{
++	if (!xen_feature(feature))
++		__make_page_readonly((unsigned long)va);
++}
++
++void make_page_writable(void *va, unsigned int feature)
++{
++	if (!xen_feature(feature))
++		__make_page_writable((unsigned long)va);
++}
++
++void make_pages_readonly(void *va, unsigned int nr, unsigned int feature)
++{
++	unsigned long addr;
++
++	if (xen_feature(feature))
++		return;
++
++	for (addr = (unsigned long)va; nr--; addr += PAGE_SIZE)
++		__make_page_readonly(addr);
++}
++
++void make_pages_writable(void *va, unsigned int nr, unsigned int feature)
++{
++	unsigned long addr;
++
++	if (xen_feature(feature))
++		return;
++
++	for (addr = (unsigned long)va; nr--; addr += PAGE_SIZE)
++		__make_page_writable(addr);
++}
++
++/*
++ * The testcases use internal knowledge of the implementation that shouldn't
++ * be exposed to the rest of the kernel. Include these directly here.
++ */
++#ifdef CONFIG_CPA_DEBUG
++#include "pageattr-test.c"
++#endif
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,542 +0,0 @@
+-/* 
+- * Copyright 2002 Andi Kleen, SuSE Labs. 
+- * Thanks to Ben LaHaise for precious feedback.
+- */ 
+-
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <linux/highmem.h>
+-#include <linux/module.h>
+-#include <linux/slab.h>
+-#include <asm/uaccess.h>
+-#include <asm/processor.h>
+-#include <asm/tlbflush.h>
+-#include <asm/io.h>
+-
+-#ifdef CONFIG_XEN
+-#include <asm/pgalloc.h>
+-#include <asm/mmu_context.h>
+-
+-static void _pin_lock(struct mm_struct *mm, int lock) {
+-	if (lock)
+-		spin_lock(&mm->page_table_lock);
+-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+-	/* While mm->page_table_lock protects us against insertions and
+-	 * removals of higher level page table pages, it doesn't protect
+-	 * against updates of pte-s. Such updates, however, require the
+-	 * pte pages to be in consistent state (unpinned+writable or
+-	 * pinned+readonly). The pinning and attribute changes, however
+-	 * cannot be done atomically, which is why such updates must be
+-	 * prevented from happening concurrently.
+-	 * Note that no pte lock can ever elsewhere be acquired nesting
+-	 * with an already acquired one in the same mm, or with the mm's
+-	 * page_table_lock already acquired, as that would break in the
+-	 * non-split case (where all these are actually resolving to the
+-	 * one page_table_lock). Thus acquiring all of them here is not
+-	 * going to result in dead locks, and the order of acquires
+-	 * doesn't matter.
+-	 */
+-	{
+-		pgd_t *pgd = mm->pgd;
+-		unsigned g;
+-
+-		for (g = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
+-			pud_t *pud;
+-			unsigned u;
+-
+-			if (pgd_none(*pgd))
+-				continue;
+-			pud = pud_offset(pgd, 0);
+-			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-				pmd_t *pmd;
+-				unsigned m;
+-
+-				if (pud_none(*pud))
+-					continue;
+-				pmd = pmd_offset(pud, 0);
+-				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-					spinlock_t *ptl;
+-
+-					if (pmd_none(*pmd))
+-						continue;
+-					ptl = pte_lockptr(0, pmd);
+-					if (lock)
+-						spin_lock(ptl);
+-					else
+-						spin_unlock(ptl);
+-				}
+-			}
+-		}
+-	}
+-#endif
+-	if (!lock)
+-		spin_unlock(&mm->page_table_lock);
+-}
+-#define pin_lock(mm) _pin_lock(mm, 1)
+-#define pin_unlock(mm) _pin_lock(mm, 0)
+-
+-#define PIN_BATCH 8
+-static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+-
+-static inline unsigned int pgd_walk_set_prot(void *pt, pgprot_t flags,
+-					     unsigned int cpu, unsigned int seq)
+-{
+-	struct page *page = virt_to_page(pt);
+-	unsigned long pfn = page_to_pfn(page);
+-
+-	MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-		(unsigned long)__va(pfn << PAGE_SHIFT),
+-		pfn_pte(pfn, flags), 0);
+-	if (unlikely(++seq == PIN_BATCH)) {
+-		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-	                                                PIN_BATCH, NULL)))
+-			BUG();
+-		seq = 0;
+-	}
+-
+-	return seq;
+-}
+-
+-static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
+-{
+-	pgd_t       *pgd = pgd_base;
+-	pud_t       *pud;
+-	pmd_t       *pmd;
+-	pte_t       *pte;
+-	int          g,u,m;
+-	unsigned int cpu, seq;
+-	multicall_entry_t *mcl;
+-
+-	cpu = get_cpu();
+-
+-	/*
+-	 * Cannot iterate up to USER_PTRS_PER_PGD as these pagetables may not
+-	 * be the 'current' task's pagetables (e.g., current may be 32-bit,
+-	 * but the pagetables may be for a 64-bit task).
+-	 * Subtracting 1 from TASK_SIZE64 means the loop limit is correct
+-	 * regardless of whether TASK_SIZE64 is a multiple of PGDIR_SIZE.
+-	 */
+-	for (g = 0, seq = 0; g <= ((TASK_SIZE64-1) / PGDIR_SIZE); g++, pgd++) {
+-		if (pgd_none(*pgd))
+-			continue;
+-		pud = pud_offset(pgd, 0);
+-		if (PTRS_PER_PUD > 1) /* not folded */ 
+-			seq = pgd_walk_set_prot(pud,flags,cpu,seq);
+-		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-			if (pud_none(*pud))
+-				continue;
+-			pmd = pmd_offset(pud, 0);
+-			if (PTRS_PER_PMD > 1) /* not folded */ 
+-				seq = pgd_walk_set_prot(pmd,flags,cpu,seq);
+-			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-				if (pmd_none(*pmd))
+-					continue;
+-				pte = pte_offset_kernel(pmd,0);
+-				seq = pgd_walk_set_prot(pte,flags,cpu,seq);
+-			}
+-		}
+-	}
+-
+-	mcl = per_cpu(pb_mcl, cpu);
+-	if (unlikely(seq > PIN_BATCH - 2)) {
+-		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
+-			BUG();
+-		seq = 0;
+-	}
+-	MULTI_update_va_mapping(mcl + seq,
+-	       (unsigned long)__user_pgd(pgd_base),
+-	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
+-	       0);
+-	MULTI_update_va_mapping(mcl + seq + 1,
+-	       (unsigned long)pgd_base,
+-	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-	       UVMF_TLB_FLUSH);
+-	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
+-		BUG();
+-
+-	put_cpu();
+-}
+-
+-static void __pgd_pin(pgd_t *pgd)
+-{
+-	pgd_walk(pgd, PAGE_KERNEL_RO);
+-	xen_pgd_pin(__pa(pgd)); /* kernel */
+-	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
+-	SetPagePinned(virt_to_page(pgd));
+-}
+-
+-static void __pgd_unpin(pgd_t *pgd)
+-{
+-	xen_pgd_unpin(__pa(pgd));
+-	xen_pgd_unpin(__pa(__user_pgd(pgd)));
+-	pgd_walk(pgd, PAGE_KERNEL);
+-	ClearPagePinned(virt_to_page(pgd));
+-}
+-
+-void pgd_test_and_unpin(pgd_t *pgd)
+-{
+-	if (PagePinned(virt_to_page(pgd)))
+-		__pgd_unpin(pgd);
+-}
+-
+-void mm_pin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	pin_lock(mm);
+-	__pgd_pin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_unpin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	pin_lock(mm);
+-	__pgd_unpin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_pin_all(void)
+-{
+-	struct page *page;
+-	unsigned long flags;
+-
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	/*
+-	 * Allow uninterrupted access to the pgd_list. Also protects
+-	 * __pgd_pin() by disabling preemption.
+-	 * All other CPUs must be at a safe point (e.g., in stop_machine
+-	 * or offlined entirely).
+-	 */
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	list_for_each_entry(page, &pgd_list, lru) {
+-		if (!PagePinned(page))
+-			__pgd_pin((pgd_t *)page_address(page));
+-	}
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+-{
+-	if (!PagePinned(virt_to_page(mm->pgd)))
+-		mm_pin(mm);
+-}
+-
+-void arch_exit_mmap(struct mm_struct *mm)
+-{
+-	struct task_struct *tsk = current;
+-
+-	task_lock(tsk);
+-
+-	/*
+-	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+-	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+-	 */
+-	if (tsk->active_mm == mm) {
+-		tsk->active_mm = &init_mm;
+-		atomic_inc(&init_mm.mm_count);
+-
+-		switch_mm(mm, &init_mm, tsk);
+-
+-		atomic_dec(&mm->mm_count);
+-		BUG_ON(atomic_read(&mm->mm_count) == 0);
+-	}
+-
+-	task_unlock(tsk);
+-
+-	if (PagePinned(virt_to_page(mm->pgd))
+-	    && (atomic_read(&mm->mm_count) == 1)
+-	    && !mm->context.has_foreign_mappings)
+-		mm_unpin(mm);
+-}
+-
+-static void _pte_free(struct page *page, unsigned int order)
+-{
+-	BUG_ON(order);
+-	pte_free(page);
+-}
+-
+-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-	struct page *pte;
+-
+-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-	if (pte) {
+-		SetPageForeign(pte, _pte_free);
+-		init_page_count(pte);
+-	}
+-	return pte;
+-}
+-
+-void pte_free(struct page *pte)
+-{
+-	unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
+-
+-	if (!pte_write(*virt_to_ptep(va)))
+-		if (HYPERVISOR_update_va_mapping(
+-			va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0))
+-			BUG();
+-
+-	ClearPageForeign(pte);
+-	init_page_count(pte);
+-
+-	__free_page(pte);
+-}
+-#endif	/* CONFIG_XEN */
+-
+-pte_t *lookup_address(unsigned long address) 
+-{ 
+-	pgd_t *pgd = pgd_offset_k(address);
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
+-	if (pgd_none(*pgd))
+-		return NULL;
+-	pud = pud_offset(pgd, address);
+-	if (!pud_present(*pud))
+-		return NULL; 
+-	pmd = pmd_offset(pud, address);
+-	if (!pmd_present(*pmd))
+-		return NULL; 
+-	if (pmd_large(*pmd))
+-		return (pte_t *)pmd;
+-	pte = pte_offset_kernel(pmd, address);
+-	if (pte && !pte_present(*pte))
+-		pte = NULL; 
+-	return pte;
+-} 
+-
+-static struct page *split_large_page(unsigned long address, pgprot_t prot,
+-				     pgprot_t ref_prot)
+-{ 
+-	int i; 
+-	unsigned long addr;
+-	struct page *base = alloc_pages(GFP_KERNEL, 0);
+-	pte_t *pbase;
+-	if (!base) 
+-		return NULL;
+-	/*
+-	 * page_private is used to track the number of entries in
+-	 * the page table page have non standard attributes.
+-	 */
+-	SetPagePrivate(base);
+-	page_private(base) = 0;
+-
+-	address = __pa(address);
+-	addr = address & LARGE_PAGE_MASK; 
+-	pbase = (pte_t *)page_address(base);
+-	for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
+-		pbase[i] = pfn_pte(addr >> PAGE_SHIFT, 
+-				   addr == address ? prot : ref_prot);
+-	}
+-	return base;
+-} 
+-
+-void clflush_cache_range(void *adr, int size)
+-{
+-	int i;
+-	for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size)
+-		clflush(adr+i);
+-}
+-
+-static void flush_kernel_map(void *arg)
+-{
+-	struct list_head *l = (struct list_head *)arg;
+-	struct page *pg;
+-
+-	/* When clflush is available always use it because it is
+-	   much cheaper than WBINVD. */
+-	/* clflush is still broken. Disable for now. */
+-	if (1 || !cpu_has_clflush)
+-		asm volatile("wbinvd" ::: "memory");
+-	else list_for_each_entry(pg, l, lru) {
+-		void *adr = page_address(pg);
+-		clflush_cache_range(adr, PAGE_SIZE);
+-	}
+-	__flush_tlb_all();
+-}
+-
+-static inline void flush_map(struct list_head *l)
+-{	
+-	on_each_cpu(flush_kernel_map, l, 1, 1);
+-}
+-
+-static LIST_HEAD(deferred_pages); /* protected by init_mm.mmap_sem */
+-
+-static inline void save_page(struct page *fpage)
+-{
+-	if (!test_and_set_bit(PG_arch_1, &fpage->flags))
+-		list_add(&fpage->lru, &deferred_pages);
+-}
+-
+-/* 
+- * No more special protections in this 2/4MB area - revert to a
+- * large page again. 
+- */
+-static void revert_page(unsigned long address, pgprot_t ref_prot)
+-{
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t large_pte;
+-	unsigned long pfn;
+-
+-	pgd = pgd_offset_k(address);
+-	BUG_ON(pgd_none(*pgd));
+-	pud = pud_offset(pgd,address);
+-	BUG_ON(pud_none(*pud));
+-	pmd = pmd_offset(pud, address);
+-	BUG_ON(__pmd_val(*pmd) & _PAGE_PSE);
+-	pfn = (__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT;
+-	large_pte = pfn_pte(pfn, ref_prot);
+-	large_pte = pte_mkhuge(large_pte);
+-	set_pte((pte_t *)pmd, large_pte);
+-}      
+-
+-static int
+-__change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
+-				   pgprot_t ref_prot)
+-{ 
+-	pte_t *kpte; 
+-	struct page *kpte_page;
+-	pgprot_t ref_prot2;
+-
+-	kpte = lookup_address(address);
+-	if (!kpte) return 0;
+-	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
+-	BUG_ON(PageLRU(kpte_page));
+-	BUG_ON(PageCompound(kpte_page));
+-	if (pgprot_val(prot) != pgprot_val(ref_prot)) { 
+-		if (!pte_huge(*kpte)) {
+-			set_pte(kpte, pfn_pte(pfn, prot));
+-		} else {
+- 			/*
+-			 * split_large_page will take the reference for this
+-			 * change_page_attr on the split page.
+- 			 */
+-			struct page *split;
+-			ref_prot2 = pte_pgprot(pte_clrhuge(*kpte));
+-			split = split_large_page(address, prot, ref_prot2);
+-			if (!split)
+-				return -ENOMEM;
+-			pgprot_val(ref_prot2) &= ~_PAGE_NX;
+-			set_pte(kpte, mk_pte(split, ref_prot2));
+-			kpte_page = split;
+-		}
+-		page_private(kpte_page)++;
+-	} else if (!pte_huge(*kpte)) {
+-		set_pte(kpte, pfn_pte(pfn, ref_prot));
+-		BUG_ON(page_private(kpte_page) == 0);
+-		page_private(kpte_page)--;
+-	} else
+-		BUG();
+-
+-	/* on x86-64 the direct mapping set at boot is not using 4k pages */
+-	/*
+-	 * ..., but the XEN guest kernels (currently) do:
+-	 * If the pte was reserved, it means it was created at boot
+-	 * time (not via split_large_page) and in turn we must not
+-	 * replace it with a large page.
+-	 */
+-#ifndef CONFIG_XEN
+- 	BUG_ON(PageReserved(kpte_page));
+-#else
+-	if (PageReserved(kpte_page))
+-		return 0;
+-#endif
+-
+-	save_page(kpte_page);
+-	if (page_private(kpte_page) == 0)
+-		revert_page(address, ref_prot);
+-	return 0;
+-} 
+-
+-/*
+- * Change the page attributes of an page in the linear mapping.
+- *
+- * This should be used when a page is mapped with a different caching policy
+- * than write-back somewhere - some CPUs do not like it when mappings with
+- * different caching policies exist. This changes the page attributes of the
+- * in kernel linear mapping too.
+- * 
+- * The caller needs to ensure that there are no conflicting mappings elsewhere.
+- * This function only deals with the kernel linear map.
+- * 
+- * Caller must call global_flush_tlb() after this.
+- */
+-int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
+-{
+-	int err = 0, kernel_map = 0;
+-	int i; 
+-
+-	if (address >= __START_KERNEL_map
+-	    && address < __START_KERNEL_map + KERNEL_TEXT_SIZE) {
+-		address = (unsigned long)__va(__pa(address));
+-		kernel_map = 1;
+-	}
+-
+-	down_write(&init_mm.mmap_sem);
+-	for (i = 0; i < numpages; i++, address += PAGE_SIZE) {
+-		unsigned long pfn = __pa(address) >> PAGE_SHIFT;
+-
+-		if (!kernel_map || pte_present(pfn_pte(0, prot))) {
+-			err = __change_page_attr(address, pfn, prot, PAGE_KERNEL);
+-			if (err)
+-				break;
+-		}
+-		/* Handle kernel mapping too which aliases part of the
+-		 * lowmem */
+-		if (__pa(address) < KERNEL_TEXT_SIZE) {
+-			unsigned long addr2;
+-			pgprot_t prot2;
+-			addr2 = __START_KERNEL_map + __pa(address);
+-			/* Make sure the kernel mappings stay executable */
+-			prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
+-			err = __change_page_attr(addr2, pfn, prot2,
+-						 PAGE_KERNEL_EXEC);
+-		} 
+-	} 	
+-	up_write(&init_mm.mmap_sem); 
+-	return err;
+-}
+-
+-/* Don't call this for MMIO areas that may not have a mem_map entry */
+-int change_page_attr(struct page *page, int numpages, pgprot_t prot)
+-{
+-	unsigned long addr = (unsigned long)page_address(page);
+-	return change_page_attr_addr(addr, numpages, prot);
+-}
+-
+-void global_flush_tlb(void)
+-{ 
+-	struct page *pg, *next;
+-	struct list_head l;
+-
+-	/*
+-	 * Write-protect the semaphore, to exclude two contexts
+-	 * doing a list_replace_init() call in parallel and to
+-	 * exclude new additions to the deferred_pages list:
+-	 */
+-	down_write(&init_mm.mmap_sem);
+-	list_replace_init(&deferred_pages, &l);
+-	up_write(&init_mm.mmap_sem);
+-
+-	flush_map(&l);
+-
+-	list_for_each_entry_safe(pg, next, &l, lru) {
+-		list_del(&pg->lru);
+-		clear_bit(PG_arch_1, &pg->flags);
+-		if (page_private(pg) != 0)
+-			continue;
+-		ClearPagePrivate(pg);
+-		__free_page(pg);
+-	} 
+-} 
+-
+-EXPORT_SYMBOL(change_page_attr);
+-EXPORT_SYMBOL(global_flush_tlb);
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -29,8 +29,6 @@
+ #include <xen/features.h>
+ #include <asm/hypervisor.h>
+ 
+-static void pgd_test_and_unpin(pgd_t *pgd);
+-
+ void show_mem(void)
+ {
+ 	int total = 0, reserved = 0;
+@@ -167,53 +165,6 @@ pte_t *pte_alloc_one_kernel(struct mm_st
+ 	return pte;
+ }
+ 
+-static void _pte_free(struct page *page, unsigned int order)
+-{
+-	BUG_ON(order);
+-	pte_free(page);
+-}
+-
+-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-	struct page *pte;
+-
+-#ifdef CONFIG_HIGHPTE
+-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+-#else
+-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+-#endif
+-	if (pte) {
+-		SetPageForeign(pte, _pte_free);
+-		init_page_count(pte);
+-	}
+-	return pte;
+-}
+-
+-void pte_free(struct page *pte)
+-{
+-	unsigned long pfn = page_to_pfn(pte);
+-
+-	if (!PageHighMem(pte)) {
+-		unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
+-
+-		if (!pte_write(*virt_to_ptep(va)))
+-			if (HYPERVISOR_update_va_mapping(
+-				va, pfn_pte(pfn, PAGE_KERNEL), 0))
+-				BUG();
+-	} else
+-		ClearPagePinned(pte);
+-
+-	ClearPageForeign(pte);
+-	init_page_count(pte);
+-
+-	__free_page(pte);
+-}
+-
+-void pmd_ctor(struct kmem_cache *cache, void *pmd)
+-{
+-	memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+-}
+-
+ /*
+  * List of all pgd's needed for non-PAE so it can invalidate entries
+  * in both cached and uncached pgd's; not needed for PAE since the
+@@ -224,224 +175,191 @@ void pmd_ctor(struct kmem_cache *cache, 
+  * vmalloc faults work because attached pagetables are never freed.
+  * -- wli
+  */
+-DEFINE_SPINLOCK(pgd_lock);
+-struct page *pgd_list;
+-
+ static inline void pgd_list_add(pgd_t *pgd)
+ {
+ 	struct page *page = virt_to_page(pgd);
+-	page->index = (unsigned long)pgd_list;
+-	if (pgd_list)
+-		set_page_private(pgd_list, (unsigned long)&page->index);
+-	pgd_list = page;
+-	set_page_private(page, (unsigned long)&pgd_list);
++
++	list_add(&page->lru, &pgd_list);
+ }
+ 
+ static inline void pgd_list_del(pgd_t *pgd)
+ {
+-	struct page *next, **pprev, *page = virt_to_page(pgd);
+-	next = (struct page *)page->index;
+-	pprev = (struct page **)page_private(page);
+-	*pprev = next;
+-	if (next)
+-		set_page_private(next, (unsigned long)pprev);
+-}
++	struct page *page = virt_to_page(pgd);
+ 
++	list_del(&page->lru);
++}
+ 
++#define UNSHARED_PTRS_PER_PGD				\
++	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+ 
+-#if (PTRS_PER_PMD == 1)
+-/* Non-PAE pgd constructor */
+-static void pgd_ctor(void *pgd)
++static void pgd_ctor(void *p)
+ {
++	pgd_t *pgd = p;
+ 	unsigned long flags;
+ 
+-	/* !PAE, no pagetable sharing */
++	pgd_test_and_unpin(pgd);
++
++	/* Clear usermode parts of PGD */
+ 	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+ 
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 
+-	/* must happen under lock */
+-	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+-			swapper_pg_dir + USER_PTRS_PER_PGD,
+-			KERNEL_PGD_PTRS);
+-
+-	paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+-				__pa(swapper_pg_dir) >> PAGE_SHIFT,
+-				USER_PTRS_PER_PGD,
+-				KERNEL_PGD_PTRS);
+-	pgd_list_add(pgd);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-#else  /* PTRS_PER_PMD > 1 */
+-/* PAE pgd constructor */
+-static void pgd_ctor(void *pgd)
+-{
+-	/* PAE, kernel PMD may be shared */
+-
+-	if (SHARED_KERNEL_PMD) {
+-		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
++	/* If the pgd points to a shared pagetable level (either the
++	   ptes in non-PAE, or shared PMD in PAE), then just copy the
++	   references from swapper_pg_dir. */
++	if (PAGETABLE_LEVELS == 2 ||
++	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
++		clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+ 				swapper_pg_dir + USER_PTRS_PER_PGD,
+ 				KERNEL_PGD_PTRS);
+-	} else {
+-		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
++					__pa(swapper_pg_dir) >> PAGE_SHIFT,
++					USER_PTRS_PER_PGD,
++					KERNEL_PGD_PTRS);
+ 	}
++
++	/* list required to sync kernel mapping updates */
++	if (PAGETABLE_LEVELS == 2)
++		pgd_list_add(pgd);
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+-#endif	/* PTRS_PER_PMD */
+ 
+ static void pgd_dtor(void *pgd)
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
+-	if (SHARED_KERNEL_PMD)
+-		return;
+-
+-	paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	pgd_list_del(pgd);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	if (!SHARED_KERNEL_PMD) {
++		spin_lock_irqsave(&pgd_lock, flags);
++		pgd_list_del(pgd);
++		spin_unlock_irqrestore(&pgd_lock, flags);
++	}
+ 
+ 	pgd_test_and_unpin(pgd);
+ }
+ 
+-#define UNSHARED_PTRS_PER_PGD				\
+-	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+-
+-/* If we allocate a pmd for part of the kernel address space, then
+-   make sure its initialized with the appropriate kernel mappings.
+-   Otherwise use a cached zeroed pmd.  */
+-static pmd_t *pmd_cache_alloc(int idx)
++#ifdef CONFIG_X86_PAE
++/*
++ * Mop up any pmd pages which may still be attached to the pgd.
++ * Normally they will be freed by munmap/exit_mmap, but any pmd we
++ * preallocate which never got a corresponding vma will need to be
++ * freed manually.
++ */
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+ {
+-	pmd_t *pmd;
++	int i;
+ 
+-	if (idx >= USER_PTRS_PER_PGD) {
+-		pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
++	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
++		pgd_t pgd = pgdp[i];
+ 
+-#ifndef CONFIG_XEN
+-		if (pmd)
+-			memcpy(pmd,
+-			       (void *)pgd_page_vaddr(swapper_pg_dir[idx]),
+-			       sizeof(pmd_t) * PTRS_PER_PMD);
+-#endif
+-	} else
+-		pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++		if (__pgd_val(pgd) != 0) {
++			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+ 
+-	return pmd;
+-}
++			pgdp[i] = xen_make_pgd(0);
+ 
+-static void pmd_cache_free(pmd_t *pmd, int idx)
+-{
+-	if (idx >= USER_PTRS_PER_PGD) {
+-		make_lowmem_page_writable(pmd, XENFEAT_writable_page_tables);
+-		memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+-		free_page((unsigned long)pmd);
+-	} else
+-		kmem_cache_free(pmd_cache, pmd);
++			paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
++			pmd_free(mm, pmd);
++		}
++	}
+ }
+ 
+-pgd_t *pgd_alloc(struct mm_struct *mm)
++/*
++ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
++ * updating the top-level pagetable entries to guarantee the
++ * processor notices the update.  Since this is expensive, and
++ * all 4 top-level entries are used almost immediately in a
++ * new process's life, we just pre-populate them here.
++ *
++ * Also, if we're in a paravirt environment where the kernel pmd is
++ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
++ * and initialize the kernel pmds here.
++ */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
+ {
++	pud_t *pud;
++	pmd_t *pmds[UNSHARED_PTRS_PER_PGD];
++	unsigned long addr, flags;
+ 	int i;
+-	pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
+-	pmd_t **pmds = NULL;
+-	unsigned long flags;
+-
+-	pgd_test_and_unpin(pgd);
+-
+-	if (PTRS_PER_PMD == 1 || !pgd)
+-		return pgd;
+-
+-#ifdef CONFIG_XEN
+-	if (!SHARED_KERNEL_PMD) {
+-		/*
+-		 * We can race save/restore (if we sleep during a GFP_KERNEL memory
+-		 * allocation). We therefore store virtual addresses of pmds as they
+-		 * do not change across save/restore, and poke the machine addresses
+-		 * into the pgdir under the pgd_lock.
+-		 */
+-		pmds = kmalloc(PTRS_PER_PGD * sizeof(pmd_t *), GFP_KERNEL);
+-		if (!pmds) {
+-			quicklist_free(0, pgd_dtor, pgd);
+-			return NULL;
+-		}
+-	}
+-#endif
+ 
+-	/* Allocate pmds, remember virtual addresses. */
+-	for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
+-		pmd_t *pmd = pmd_cache_alloc(i);
+-
+-		if (!pmd)
++	/*
++	 * We can race save/restore (if we sleep during a GFP_KERNEL memory
++	 * allocation). We therefore store virtual addresses of pmds as they
++	 * do not change across save/restore, and poke the machine addresses
++	 * into the pgdir under the pgd_lock.
++	 */
++ 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD; i++, addr += PUD_SIZE) {
++		pmds[i] = pmd_alloc_one(mm, addr);
++		if (!pmds[i])
+ 			goto out_oom;
+-
+-		paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
+-		if (pmds)
+-			pmds[i] = pmd;
+-		else
+-			set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+ 	}
+ 
+-#ifdef CONFIG_XEN
+-	if (SHARED_KERNEL_PMD)
+-		return pgd;
+-
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 
+ 	/* Protect against save/restore: move below 4GB under pgd_lock. */
+-	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)) {
+-		int rc = xen_create_contiguous_region(
+-			(unsigned long)pgd, 0, 32);
+-		if (rc) {
+-			spin_unlock_irqrestore(&pgd_lock, flags);
+-			goto out_oom;
+-		}
++	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
++	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
++		spin_unlock_irqrestore(&pgd_lock, flags);
++out_oom:
++		while (i--)
++			pmd_free(mm, pmds[i]);
++		return 0;
+ 	}
+ 
+ 	/* Copy kernel pmd contents and write-protect the new pmds. */
+-	for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
+-		memcpy(pmds[i],
+-		       (void *)pgd_page_vaddr(swapper_pg_dir[i]),
+-		       sizeof(pmd_t) * PTRS_PER_PMD);
+-		make_lowmem_page_readonly(
+-			pmds[i], XENFEAT_writable_page_tables);
+-	}
++	pud = pud_offset(pgd, 0);
++ 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
++	     i++, pud++, addr += PUD_SIZE) {
++		if (i >= USER_PTRS_PER_PGD) {
++			memcpy(pmds[i],
++			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
++			       sizeof(pmd_t) * PTRS_PER_PMD);
++			make_lowmem_page_readonly(
++				pmds[i], XENFEAT_writable_page_tables);
++		}
+ 
+-	/* It is safe to poke machine addresses of pmds under the pmd_lock. */
+-	for (i = 0; i < PTRS_PER_PGD; i++)
+-		set_pgd(&pgd[i], __pgd(1 + __pa(pmds[i])));
++		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
++		pud_populate(mm, pud, pmds[i]);
++	}
+ 
+-	/* Ensure this pgd gets picked up and pinned on save/restore. */
++	/* List required to sync kernel mapping updates and
++	 * to pin/unpin on save/restore. */
+ 	pgd_list_add(pgd);
+ 
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+ 
+-	kfree(pmds);
+-#endif
++	return 1;
++}
++#else  /* !CONFIG_X86_PAE */
++/* No need to prepopulate any pagetable entries in non-PAE modes. */
++static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
++{
++	return 1;
++}
+ 
+-	return pgd;
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
++}
++#endif	/* CONFIG_X86_PAE */
+ 
+-out_oom:
+-	if (!pmds) {
+-		for (i--; i >= 0; i--) {
+-			pgd_t pgdent = pgd[i];
+-			void* pmd = (void *)__va(pgd_val(pgdent)-1);
+-			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-			pmd_cache_free(pmd, i);
+-		}
+-	} else {
+-		for (i--; i >= 0; i--) {
+-			paravirt_release_pd(__pa(pmds[i]) >> PAGE_SHIFT);
+-			pmd_cache_free(pmds[i], i);
+-		}
+-		kfree(pmds);
++pgd_t *pgd_alloc(struct mm_struct *mm)
++{
++	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
++
++	/* so that alloc_pd can use it */
++	mm->pgd = pgd;
++	if (pgd)
++		pgd_ctor(pgd);
++
++	if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
++		free_page((unsigned long)pgd);
++		pgd = NULL;
+ 	}
+-	quicklist_free(0, pgd_dtor, pgd);
+-	return NULL;
++
++	return pgd;
+ }
+ 
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+-	int i;
+-
+ 	/*
+ 	 * After this the pgd should not be pinned for the duration of this
+ 	 * function's execution. We should never sleep and thus never race:
+@@ -450,39 +368,43 @@ void pgd_free(pgd_t *pgd)
+ 	 *  2. The machine addresses in PGD entries will not become invalid
+ 	 *     due to a concurrent save/restore.
+ 	 */
+-	pgd_test_and_unpin(pgd);
++	pgd_dtor(pgd);
+ 
+-	/* in the PAE case user pgd entries are overwritten before usage */
+-	if (PTRS_PER_PMD > 1) {
+-		for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) {
+-			pgd_t pgdent = pgd[i];
+-			void* pmd = (void *)__va(pgd_val(pgdent)-1);
+-			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+-			pmd_cache_free(pmd, i);
+-		}
++	if (PTRS_PER_PMD > 1 && !xen_feature(XENFEAT_pae_pgdir_above_4gb))
++		xen_destroy_contiguous_region((unsigned long)pgd, 0);
+ 
+-		if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
+-			xen_destroy_contiguous_region((unsigned long)pgd, 0);
+-	}
++	pgd_mop_up_pmds(mm, pgd);
++	free_page((unsigned long)pgd);
++}
+ 
+-	/* in the non-PAE case, free_pgtables() clears user pgd entries */
+-	quicklist_free(0, pgd_dtor, pgd);
++void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
++{
++	pgtable_page_dtor(pte);
++	paravirt_release_pt(page_to_pfn(pte));
++	tlb_remove_page(tlb, pte);
+ }
+ 
+-void check_pgt_cache(void)
++#ifdef CONFIG_X86_PAE
++
++void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+ {
+-	quicklist_trim(0, pgd_dtor, 25, 16);
++	paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
++	tlb_remove_page(tlb, virt_to_page(pmd));
+ }
+ 
++#endif
++
+ void make_lowmem_page_readonly(void *va, unsigned int feature)
+ {
+ 	pte_t *pte;
++	unsigned int level;
+ 	int rc;
+ 
+ 	if (xen_feature(feature))
+ 		return;
+ 
+-	pte = virt_to_ptep(va);
++	pte = lookup_address((unsigned long)va, &level);
++	BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte));
+ 	rc = HYPERVISOR_update_va_mapping(
+ 		(unsigned long)va, pte_wrprotect(*pte), 0);
+ 	BUG_ON(rc);
+@@ -491,313 +413,15 @@ void make_lowmem_page_readonly(void *va,
+ void make_lowmem_page_writable(void *va, unsigned int feature)
+ {
+ 	pte_t *pte;
++	unsigned int level;
+ 	int rc;
+ 
+ 	if (xen_feature(feature))
+ 		return;
+ 
+-	pte = virt_to_ptep(va);
++	pte = lookup_address((unsigned long)va, &level);
++	BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte));
+ 	rc = HYPERVISOR_update_va_mapping(
+ 		(unsigned long)va, pte_mkwrite(*pte), 0);
+ 	BUG_ON(rc);
+ }
+-
+-void make_page_readonly(void *va, unsigned int feature)
+-{
+-	pte_t *pte;
+-	int rc;
+-
+-	if (xen_feature(feature))
+-		return;
+-
+-	pte = virt_to_ptep(va);
+-	rc = HYPERVISOR_update_va_mapping(
+-		(unsigned long)va, pte_wrprotect(*pte), 0);
+-	if (rc) /* fallback? */
+-		xen_l1_entry_update(pte, pte_wrprotect(*pte));
+-	if ((unsigned long)va >= (unsigned long)high_memory) {
+-		unsigned long pfn = pte_pfn(*pte);
+-#ifdef CONFIG_HIGHMEM
+-		if (pfn >= highstart_pfn)
+-			kmap_flush_unused(); /* flush stale writable kmaps */
+-		else
+-#endif
+-			make_lowmem_page_readonly(
+-				phys_to_virt(pfn << PAGE_SHIFT), feature); 
+-	}
+-}
+-
+-void make_page_writable(void *va, unsigned int feature)
+-{
+-	pte_t *pte;
+-	int rc;
+-
+-	if (xen_feature(feature))
+-		return;
+-
+-	pte = virt_to_ptep(va);
+-	rc = HYPERVISOR_update_va_mapping(
+-		(unsigned long)va, pte_mkwrite(*pte), 0);
+-	if (rc) /* fallback? */
+-		xen_l1_entry_update(pte, pte_mkwrite(*pte));
+-	if ((unsigned long)va >= (unsigned long)high_memory) {
+-		unsigned long pfn = pte_pfn(*pte); 
+-#ifdef CONFIG_HIGHMEM
+-		if (pfn < highstart_pfn)
+-#endif
+-			make_lowmem_page_writable(
+-				phys_to_virt(pfn << PAGE_SHIFT), feature);
+-	}
+-}
+-
+-void make_pages_readonly(void *va, unsigned int nr, unsigned int feature)
+-{
+-	if (xen_feature(feature))
+-		return;
+-
+-	while (nr-- != 0) {
+-		make_page_readonly(va, feature);
+-		va = (void *)((unsigned long)va + PAGE_SIZE);
+-	}
+-}
+-
+-void make_pages_writable(void *va, unsigned int nr, unsigned int feature)
+-{
+-	if (xen_feature(feature))
+-		return;
+-
+-	while (nr-- != 0) {
+-		make_page_writable(va, feature);
+-		va = (void *)((unsigned long)va + PAGE_SIZE);
+-	}
+-}
+-
+-static void _pin_lock(struct mm_struct *mm, int lock) {
+-	if (lock)
+-		spin_lock(&mm->page_table_lock);
+-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+-	/* While mm->page_table_lock protects us against insertions and
+-	 * removals of higher level page table pages, it doesn't protect
+-	 * against updates of pte-s. Such updates, however, require the
+-	 * pte pages to be in consistent state (unpinned+writable or
+-	 * pinned+readonly). The pinning and attribute changes, however
+-	 * cannot be done atomically, which is why such updates must be
+-	 * prevented from happening concurrently.
+-	 * Note that no pte lock can ever elsewhere be acquired nesting
+-	 * with an already acquired one in the same mm, or with the mm's
+-	 * page_table_lock already acquired, as that would break in the
+-	 * non-split case (where all these are actually resolving to the
+-	 * one page_table_lock). Thus acquiring all of them here is not
+-	 * going to result in dead locks, and the order of acquires
+-	 * doesn't matter.
+-	 */
+-	{
+-		pgd_t *pgd = mm->pgd;
+-		unsigned g;
+-
+-		for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
+-			pud_t *pud;
+-			unsigned u;
+-
+-			if (pgd_none(*pgd))
+-				continue;
+-			pud = pud_offset(pgd, 0);
+-			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-				pmd_t *pmd;
+-				unsigned m;
+-
+-				if (pud_none(*pud))
+-					continue;
+-				pmd = pmd_offset(pud, 0);
+-				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-					spinlock_t *ptl;
+-
+-					if (pmd_none(*pmd))
+-						continue;
+-					ptl = pte_lockptr(0, pmd);
+-					if (lock)
+-						spin_lock(ptl);
+-					else
+-						spin_unlock(ptl);
+-				}
+-			}
+-		}
+-	}
+-#endif
+-	if (!lock)
+-		spin_unlock(&mm->page_table_lock);
+-}
+-#define pin_lock(mm) _pin_lock(mm, 1)
+-#define pin_unlock(mm) _pin_lock(mm, 0)
+-
+-#define PIN_BATCH 4
+-static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+-
+-static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
+-                                             unsigned int cpu, unsigned seq)
+-{
+-	unsigned long pfn = page_to_pfn(page);
+-
+-	if (PageHighMem(page)) {
+-		if (pgprot_val(flags) & _PAGE_RW)
+-			ClearPagePinned(page);
+-		else
+-			SetPagePinned(page);
+-	} else {
+-		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-				(unsigned long)__va(pfn << PAGE_SHIFT),
+-				pfn_pte(pfn, flags), 0);
+-		if (unlikely(++seq == PIN_BATCH)) {
+-			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-		                                                PIN_BATCH, NULL)))
+-				BUG();
+-			seq = 0;
+-		}
+-	}
+-
+-	return seq;
+-}
+-
+-static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
+-{
+-	pgd_t *pgd = pgd_base;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	int    g, u, m;
+-	unsigned int cpu, seq;
+-
+-	if (xen_feature(XENFEAT_auto_translated_physmap))
+-		return;
+-
+-	cpu = get_cpu();
+-
+-	for (g = 0, seq = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
+-		if (pgd_none(*pgd))
+-			continue;
+-		pud = pud_offset(pgd, 0);
+-		if (PTRS_PER_PUD > 1) /* not folded */
+-			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
+-		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+-			if (pud_none(*pud))
+-				continue;
+-			pmd = pmd_offset(pud, 0);
+-			if (PTRS_PER_PMD > 1) /* not folded */
+-				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
+-			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+-				if (pmd_none(*pmd))
+-					continue;
+-				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
+-			}
+-		}
+-	}
+-
+-	if (likely(seq != 0)) {
+-		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+-			(unsigned long)pgd_base,
+-			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-			UVMF_TLB_FLUSH);
+-		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+-		                                        seq + 1, NULL)))
+-			BUG();
+-	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
+-			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+-			UVMF_TLB_FLUSH))
+-		BUG();
+-
+-	put_cpu();
+-}
+-
+-static void __pgd_pin(pgd_t *pgd)
+-{
+-	pgd_walk(pgd, PAGE_KERNEL_RO);
+-	kmap_flush_unused();
+-	xen_pgd_pin(__pa(pgd));
+-	SetPagePinned(virt_to_page(pgd));
+-}
+-
+-static void __pgd_unpin(pgd_t *pgd)
+-{
+-	xen_pgd_unpin(__pa(pgd));
+-	pgd_walk(pgd, PAGE_KERNEL);
+-	ClearPagePinned(virt_to_page(pgd));
+-}
+-
+-static void pgd_test_and_unpin(pgd_t *pgd)
+-{
+-	if (PagePinned(virt_to_page(pgd)))
+-		__pgd_unpin(pgd);
+-}
+-
+-void mm_pin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-	pin_lock(mm);
+-	__pgd_pin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_unpin(struct mm_struct *mm)
+-{
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-	pin_lock(mm);
+-	__pgd_unpin(mm->pgd);
+-	pin_unlock(mm);
+-}
+-
+-void mm_pin_all(void)
+-{
+-	struct page *page;
+-	unsigned long flags;
+-
+-	if (xen_feature(XENFEAT_writable_page_tables))
+-		return;
+-
+-	/*
+-	 * Allow uninterrupted access to the pgd_list. Also protects
+-	 * __pgd_pin() by disabling preemption.
+-	 * All other CPUs must be at a safe point (e.g., in stop_machine
+-	 * or offlined entirely).
+-	 */
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	for (page = pgd_list; page; page = (struct page *)page->index) {
+-		if (!PagePinned(page))
+-			__pgd_pin((pgd_t *)page_address(page));
+-	}
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-
+-void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+-{
+-	if (!PagePinned(virt_to_page(mm->pgd)))
+-		mm_pin(mm);
+-}
+-
+-void arch_exit_mmap(struct mm_struct *mm)
+-{
+-	struct task_struct *tsk = current;
+-
+-	task_lock(tsk);
+-
+-	/*
+-	 * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+-	 * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+-	 */
+-	if (tsk->active_mm == mm) {
+-		tsk->active_mm = &init_mm;
+-		atomic_inc(&init_mm.mm_count);
+-
+-		switch_mm(mm, &init_mm, tsk);
+-
+-		atomic_dec(&mm->mm_count);
+-		BUG_ON(atomic_read(&mm->mm_count) == 0);
+-	}
+-
+-	task_unlock(tsk);
+-
+-	if (PagePinned(virt_to_page(mm->pgd)) &&
+-	    (atomic_read(&mm->mm_count) == 1) &&
+-	    !mm->context.has_foreign_mappings)
+-		mm_unpin(mm);
+-}
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -204,6 +204,7 @@ static int pirq_ali_get(struct pci_dev *
+ {
+ 	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ 
++	WARN_ON_ONCE(pirq >= 16);
+ 	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+ }
+ 
+@@ -211,7 +212,8 @@ static int pirq_ali_set(struct pci_dev *
+ {
+ 	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+ 	unsigned int val = irqmap[irq];
+-		
++
++	WARN_ON_ONCE(pirq >= 16);
+ 	if (val) {
+ 		write_config_nybble(router, 0x48, pirq-1, val);
+ 		return 1;
+@@ -261,12 +263,16 @@ static int pirq_via_set(struct pci_dev *
+ static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ 	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
++
++	WARN_ON_ONCE(pirq >= 5);
+ 	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[5] = { 3, 2, 5, 1, 1 };
++
++	WARN_ON_ONCE(pirq >= 5);
+ 	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+@@ -279,12 +285,16 @@ static int pirq_via586_set(struct pci_de
+ static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
++
++	WARN_ON_ONCE(pirq >= 4);
+ 	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+ }
+ 
+ static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+ {
+ 	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
++
++	WARN_ON_ONCE(pirq >= 4);
+ 	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+ 	return 1;
+ }
+@@ -423,6 +433,7 @@ static int pirq_sis_set(struct pci_dev *
+ 
+ static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
++	WARN_ON_ONCE(pirq >= 9);
+ 	if (pirq > 8) {
+ 		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+ 		return 0;
+@@ -432,6 +443,7 @@ static int pirq_vlsi_get(struct pci_dev 
+ 
+ static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+ {
++	WARN_ON_ONCE(pirq >= 9);
+ 	if (pirq > 8) {
+ 		printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq);
+ 		return 0;
+@@ -453,14 +465,14 @@ static int pirq_vlsi_set(struct pci_dev 
+  */
+ static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+ {
+-	outb_p(pirq, 0xc00);
++	outb(pirq, 0xc00);
+ 	return inb(0xc01) & 0xf;
+ }
+ 
+ static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+ {
+-	outb_p(pirq, 0xc00);
+-	outb_p(irq, 0xc01);
++	outb(pirq, 0xc00);
++	outb(irq, 0xc01);
+ 	return 1;
+ }
+ 
+@@ -575,6 +587,10 @@ static __init int intel_router_probe(str
+ 		case PCI_DEVICE_ID_INTEL_ICH9_4:
+ 		case PCI_DEVICE_ID_INTEL_ICH9_5:
+ 		case PCI_DEVICE_ID_INTEL_TOLAPAI_0:
++		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;
+--- head-2010-01-18.orig/arch/x86/vdso/Makefile	2009-12-04 10:44:49.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/Makefile	2009-11-06 10:51:25.000000000 +0100
+@@ -66,6 +66,7 @@ vdso32.so-$(VDSO32-y)		+= int80
+ vdso32.so-$(CONFIG_COMPAT)	+= syscall
+ vdso32.so-$(VDSO32-y)		+= sysenter
+ xen-vdso32-$(subst 1,$(CONFIG_COMPAT),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80
++xen-vdso32-$(CONFIG_X86_32)	+= syscall
+ vdso32.so-$(CONFIG_XEN)		+= $(xen-vdso32-y)
+ 
+ vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32/syscall.S	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32/syscall.S	2009-11-06 10:51:25.000000000 +0100
+@@ -19,8 +19,10 @@ __kernel_vsyscall:
+ .Lpush_ebp:
+ 	movl	%ecx, %ebp
+ 	syscall
++#ifndef CONFIG_XEN
+ 	movl	$__USER32_DS, %ecx
+ 	movl	%ecx, %ss
++#endif
+ 	movl	%ebp, %ecx
+ 	popl	%ebp
+ .Lpop_ebp:
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32.S	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32.S	2009-11-06 10:51:25.000000000 +0100
+@@ -19,4 +19,16 @@ vdso32_sysenter_start:
+ 	.incbin "arch/x86/vdso/vdso32-sysenter.so"
+ vdso32_sysenter_end:
+ 
++#if defined(CONFIG_X86_64_XEN) && CONFIG_XEN_COMPAT < 0x030200
++	.globl vdso32_int80_start, vdso32_int80_end
++vdso32_int80_start:
++	.incbin "arch/x86/vdso/vdso32-int80.so"
++vdso32_int80_end:
++#elif defined(CONFIG_X86_XEN)
++	.globl vdso32_syscall_start, vdso32_syscall_end
++vdso32_syscall_start:
++	.incbin "arch/x86/vdso/vdso32-syscall.so"
++vdso32_syscall_end:
++#endif
++
+ __FINIT
+--- head-2010-01-18.orig/arch/x86/vdso/vdso32-setup.c	2009-12-04 10:44:46.000000000 +0100
++++ head-2010-01-18/arch/x86/vdso/vdso32-setup.c	2009-11-06 10:51:25.000000000 +0100
+@@ -26,10 +26,6 @@
+ #include <asm/vdso.h>
+ #include <asm/proto.h>
+ 
+-#ifdef CONFIG_XEN
+-#include <xen/interface/callback.h>
+-#endif
+-
+ enum {
+ 	VDSO_DISABLED = 0,
+ 	VDSO_ENABLED = 1,
+@@ -229,7 +225,6 @@ static inline void map_compat_vdso(int m
+ 
+ void enable_sep_cpu(void)
+ {
+-#ifndef CONFIG_XEN
+ 	int cpu = get_cpu();
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ 
+@@ -244,35 +239,6 @@ void enable_sep_cpu(void)
+ 	wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0);
+ 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0);
+ 	put_cpu();	
+-#else
+-	extern asmlinkage void ia32pv_sysenter_target(void);
+-	static struct callback_register sysenter = {
+-		.type = CALLBACKTYPE_sysenter,
+-		.address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target },
+-	};
+-
+-	if (!boot_cpu_has(X86_FEATURE_SEP))
+-		return;
+-
+-	get_cpu();
+-
+-	if (xen_feature(XENFEAT_supervisor_mode_kernel))
+-		sysenter.address.eip = (unsigned long)ia32_sysenter_target;
+-
+-	switch (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter)) {
+-	case 0:
+-		break;
+-#if CONFIG_XEN_COMPAT < 0x030200
+-	case -ENOSYS:
+-		sysenter.type = CALLBACKTYPE_sysenter_deprecated;
+-		if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) == 0)
+-			break;
+-#endif
+-	default:
+-		clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
+-		break;
+-	}
+-#endif
+ }
+ 
+ static struct vm_area_struct gate_vma;
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/vdso/vdso32-setup-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -0,0 +1,506 @@
++/*
++ * (C) Copyright 2002 Linus Torvalds
++ * Portions based on the vdso-randomization code from exec-shield:
++ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
++ *
++ * This file contains the needed initializations to support sysenter.
++ */
++
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/thread_info.h>
++#include <linux/sched.h>
++#include <linux/gfp.h>
++#include <linux/string.h>
++#include <linux/elf.h>
++#include <linux/mm.h>
++#include <linux/err.h>
++#include <linux/module.h>
++
++#include <asm/cpufeature.h>
++#include <asm/msr.h>
++#include <asm/pgtable.h>
++#include <asm/unistd.h>
++#include <asm/elf.h>
++#include <asm/tlbflush.h>
++#include <asm/vdso.h>
++#include <asm/proto.h>
++
++#include <xen/interface/callback.h>
++
++enum {
++	VDSO_DISABLED = 0,
++	VDSO_ENABLED = 1,
++	VDSO_COMPAT = 2,
++};
++
++#ifdef CONFIG_COMPAT_VDSO
++#define VDSO_DEFAULT	VDSO_COMPAT
++#else
++#define VDSO_DEFAULT	VDSO_ENABLED
++#endif
++
++#ifdef CONFIG_X86_64
++#define vdso_enabled			sysctl_vsyscall32
++#define arch_setup_additional_pages	syscall32_setup_pages
++#endif
++
++/*
++ * This is the difference between the prelinked addresses in the vDSO images
++ * and the VDSO_HIGH_BASE address where CONFIG_COMPAT_VDSO places the vDSO
++ * in the user address space.
++ */
++#define VDSO_ADDR_ADJUST	(VDSO_HIGH_BASE - (unsigned long)VDSO32_PRELINK)
++
++/*
++ * Should the kernel map a VDSO page into processes and pass its
++ * address down to glibc upon exec()?
++ */
++unsigned int __read_mostly vdso_enabled = VDSO_DEFAULT;
++
++static int __init vdso_setup(char *s)
++{
++	vdso_enabled = simple_strtoul(s, NULL, 0);
++
++	return 1;
++}
++
++/*
++ * For consistency, the argument vdso32=[012] affects the 32-bit vDSO
++ * behavior on both 64-bit and 32-bit kernels.
++ * On 32-bit kernels, vdso=[012] means the same thing.
++ */
++__setup("vdso32=", vdso_setup);
++
++#ifdef CONFIG_X86_32
++__setup_param("vdso=", vdso32_setup, vdso_setup, 0);
++
++EXPORT_SYMBOL_GPL(vdso_enabled);
++#endif
++
++static __init void reloc_symtab(Elf32_Ehdr *ehdr,
++				unsigned offset, unsigned size)
++{
++	Elf32_Sym *sym = (void *)ehdr + offset;
++	unsigned nsym = size / sizeof(*sym);
++	unsigned i;
++
++	for(i = 0; i < nsym; i++, sym++) {
++		if (sym->st_shndx == SHN_UNDEF ||
++		    sym->st_shndx == SHN_ABS)
++			continue;  /* skip */
++
++		if (sym->st_shndx > SHN_LORESERVE) {
++			printk(KERN_INFO "VDSO: unexpected st_shndx %x\n",
++			       sym->st_shndx);
++			continue;
++		}
++
++		switch(ELF_ST_TYPE(sym->st_info)) {
++		case STT_OBJECT:
++		case STT_FUNC:
++		case STT_SECTION:
++		case STT_FILE:
++			sym->st_value += VDSO_ADDR_ADJUST;
++		}
++	}
++}
++
++static __init void reloc_dyn(Elf32_Ehdr *ehdr, unsigned offset)
++{
++	Elf32_Dyn *dyn = (void *)ehdr + offset;
++
++	for(; dyn->d_tag != DT_NULL; dyn++)
++		switch(dyn->d_tag) {
++		case DT_PLTGOT:
++		case DT_HASH:
++		case DT_STRTAB:
++		case DT_SYMTAB:
++		case DT_RELA:
++		case DT_INIT:
++		case DT_FINI:
++		case DT_REL:
++		case DT_DEBUG:
++		case DT_JMPREL:
++		case DT_VERSYM:
++		case DT_VERDEF:
++		case DT_VERNEED:
++		case DT_ADDRRNGLO ... DT_ADDRRNGHI:
++			/* definitely pointers needing relocation */
++			dyn->d_un.d_ptr += VDSO_ADDR_ADJUST;
++			break;
++
++		case DT_ENCODING ... OLD_DT_LOOS-1:
++		case DT_LOOS ... DT_HIOS-1:
++			/* Tags above DT_ENCODING are pointers if
++			   they're even */
++			if (dyn->d_tag >= DT_ENCODING &&
++			    (dyn->d_tag & 1) == 0)
++				dyn->d_un.d_ptr += VDSO_ADDR_ADJUST;
++			break;
++
++		case DT_VERDEFNUM:
++		case DT_VERNEEDNUM:
++		case DT_FLAGS_1:
++		case DT_RELACOUNT:
++		case DT_RELCOUNT:
++		case DT_VALRNGLO ... DT_VALRNGHI:
++			/* definitely not pointers */
++			break;
++
++		case OLD_DT_LOOS ... DT_LOOS-1:
++		case DT_HIOS ... DT_VALRNGLO-1:
++		default:
++			if (dyn->d_tag > DT_ENCODING)
++				printk(KERN_INFO "VDSO: unexpected DT_tag %x\n",
++				       dyn->d_tag);
++			break;
++		}
++}
++
++static __init void relocate_vdso(Elf32_Ehdr *ehdr)
++{
++	Elf32_Phdr *phdr;
++	Elf32_Shdr *shdr;
++	int i;
++
++	BUG_ON(memcmp(ehdr->e_ident, ELFMAG, 4) != 0 ||
++	       !elf_check_arch_ia32(ehdr) ||
++	       ehdr->e_type != ET_DYN);
++
++	ehdr->e_entry += VDSO_ADDR_ADJUST;
++
++	/* rebase phdrs */
++	phdr = (void *)ehdr + ehdr->e_phoff;
++	for (i = 0; i < ehdr->e_phnum; i++) {
++		phdr[i].p_vaddr += VDSO_ADDR_ADJUST;
++
++		/* relocate dynamic stuff */
++		if (phdr[i].p_type == PT_DYNAMIC)
++			reloc_dyn(ehdr, phdr[i].p_offset);
++	}
++
++	/* rebase sections */
++	shdr = (void *)ehdr + ehdr->e_shoff;
++	for(i = 0; i < ehdr->e_shnum; i++) {
++		if (!(shdr[i].sh_flags & SHF_ALLOC))
++			continue;
++
++		shdr[i].sh_addr += VDSO_ADDR_ADJUST;
++
++		if (shdr[i].sh_type == SHT_SYMTAB ||
++		    shdr[i].sh_type == SHT_DYNSYM)
++			reloc_symtab(ehdr, shdr[i].sh_offset,
++				     shdr[i].sh_size);
++	}
++}
++
++/*
++ * These symbols are defined by vdso32.S to mark the bounds
++ * of the ELF DSO images included therein.
++ */
++extern const char vdso32_default_start, vdso32_default_end;
++extern const char vdso32_sysenter_start, vdso32_sysenter_end;
++static struct page *vdso32_pages[1];
++
++#ifdef CONFIG_X86_64
++
++#if CONFIG_XEN_COMPAT < 0x030200
++static int use_int80 = 1;
++#endif
++static int use_sysenter __read_mostly = -1;
++
++#define	vdso32_sysenter()	(use_sysenter > 0)
++
++/* May not be __init: called during resume */
++void syscall32_cpu_init(void)
++{
++	static const struct callback_register cstar = {
++		.type = CALLBACKTYPE_syscall32,
++		.address = (unsigned long)ia32_cstar_target
++	};
++	static const struct callback_register sysenter = {
++		.type = CALLBACKTYPE_sysenter,
++		.address = (unsigned long)ia32_sysenter_target
++	};
++
++	if ((HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0) ||
++	    (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) < 0))
++#if CONFIG_XEN_COMPAT < 0x030200
++		return;
++	use_int80 = 0;
++#else
++		BUG();
++#endif
++
++	if (use_sysenter < 0)
++		use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
++}
++
++#define compat_uses_vma		1
++
++static inline void map_compat_vdso(int map)
++{
++}
++
++#else  /* CONFIG_X86_32 */
++
++#define vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SEP))
++
++extern asmlinkage void ia32pv_cstar_target(void);
++static const struct callback_register __cpuinitconst cstar = {
++	.type = CALLBACKTYPE_syscall32,
++	.address = { __KERNEL_CS, (unsigned long)ia32pv_cstar_target },
++};
++
++void __cpuinit enable_sep_cpu(void)
++{
++	extern asmlinkage void ia32pv_sysenter_target(void);
++	static struct callback_register __cpuinitdata sysenter = {
++		.type = CALLBACKTYPE_sysenter,
++		.address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target },
++	};
++
++	if (boot_cpu_has(X86_FEATURE_SYSCALL)) {
++		if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) != 0)
++			BUG();
++		return;
++	}
++
++	if (!boot_cpu_has(X86_FEATURE_SEP))
++		return;
++
++	if (xen_feature(XENFEAT_supervisor_mode_kernel))
++		sysenter.address.eip = (unsigned long)ia32_sysenter_target;
++
++	switch (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter)) {
++	case 0:
++		break;
++#if CONFIG_XEN_COMPAT < 0x030200
++	case -ENOSYS:
++		sysenter.type = CALLBACKTYPE_sysenter_deprecated;
++		if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) == 0)
++			break;
++#endif
++	default:
++		setup_clear_cpu_cap(X86_FEATURE_SEP);
++		break;
++	}
++}
++
++static struct vm_area_struct gate_vma;
++
++static int __init gate_vma_init(void)
++{
++	gate_vma.vm_mm = NULL;
++	gate_vma.vm_start = FIXADDR_USER_START;
++	gate_vma.vm_end = FIXADDR_USER_END;
++	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
++	gate_vma.vm_page_prot = __P101;
++	/*
++	 * 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.
++	 */
++	gate_vma.vm_flags |= VM_ALWAYSDUMP;
++	return 0;
++}
++
++#define compat_uses_vma		0
++
++static void map_compat_vdso(int map)
++{
++	static int vdso_mapped;
++
++	if (map == vdso_mapped)
++		return;
++
++	vdso_mapped = map;
++
++	__set_fixmap(FIX_VDSO, page_to_pfn(vdso32_pages[0]) << PAGE_SHIFT,
++		     map ? PAGE_READONLY_EXEC : PAGE_NONE);
++
++	/* flush stray tlbs */
++	flush_tlb_all();
++}
++
++#endif	/* CONFIG_X86_64 */
++
++int __init sysenter_setup(void)
++{
++	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
++	const void *vsyscall;
++	size_t vsyscall_len;
++
++	vdso32_pages[0] = virt_to_page(syscall_page);
++
++#ifdef CONFIG_X86_32
++	gate_vma_init();
++
++	printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
++#endif
++
++#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT < 0x030200
++	if (use_int80) {
++		extern const char vdso32_int80_start, vdso32_int80_end;
++
++		vsyscall = &vdso32_int80_start;
++		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
++	} else
++#elif defined(CONFIG_X86_32)
++	if (boot_cpu_has(X86_FEATURE_SYSCALL)
++	    && (boot_cpu_data.x86_vendor != X86_VENDOR_AMD
++		|| HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) != 0))
++		setup_clear_cpu_cap(X86_FEATURE_SYSCALL);
++	barrier(); /* until clear_bit()'s constraints are correct ... */
++	if (boot_cpu_has(X86_FEATURE_SYSCALL)) {
++		extern const char vdso32_syscall_start, vdso32_syscall_end;
++
++		vsyscall = &vdso32_syscall_start;
++		vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
++	} else
++#endif
++	if (!vdso32_sysenter()) {
++		vsyscall = &vdso32_default_start;
++		vsyscall_len = &vdso32_default_end - &vdso32_default_start;
++	} else {
++		vsyscall = &vdso32_sysenter_start;
++		vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
++	}
++
++	memcpy(syscall_page, vsyscall, vsyscall_len);
++	relocate_vdso(syscall_page);
++
++	return 0;
++}
++
++/* Setup a VMA at program startup for the vsyscall page */
++int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
++{
++	struct mm_struct *mm = current->mm;
++	unsigned long addr;
++	int ret = 0;
++	bool compat;
++
++	down_write(&mm->mmap_sem);
++
++	/* Test compat mode once here, in case someone
++	   changes it via sysctl */
++	compat = (vdso_enabled == VDSO_COMPAT);
++
++	map_compat_vdso(compat);
++
++	if (compat)
++		addr = VDSO_HIGH_BASE;
++	else {
++		addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
++		if (IS_ERR_VALUE(addr)) {
++			ret = addr;
++			goto up_fail;
++		}
++	}
++
++	if (compat_uses_vma || !compat) {
++		/*
++		 * MAYWRITE to allow gdb to COW and set breakpoints
++		 *
++		 * 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.
++		 */
++		ret = install_special_mapping(mm, addr, PAGE_SIZE,
++					      VM_READ|VM_EXEC|
++					      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
++					      VM_ALWAYSDUMP,
++					      vdso32_pages);
++
++		if (ret)
++			goto up_fail;
++	}
++
++	current->mm->context.vdso = (void *)addr;
++	current_thread_info()->sysenter_return =
++		VDSO32_SYMBOL(addr, SYSENTER_RETURN);
++
++  up_fail:
++	up_write(&mm->mmap_sem);
++
++	return ret;
++}
++
++#ifdef CONFIG_X86_64
++
++/*
++ * This must be done early in case we have an initrd containing 32-bit
++ * binaries (e.g., hotplug). This could be pushed upstream.
++ */
++core_initcall(sysenter_setup);
++
++#ifdef CONFIG_SYSCTL
++/* Register vsyscall32 into the ABI table */
++#include <linux/sysctl.h>
++
++static ctl_table abi_table2[] = {
++	{
++		.procname	= "vsyscall32",
++		.data		= &sysctl_vsyscall32,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec
++	},
++	{}
++};
++
++static ctl_table abi_root_table2[] = {
++	{
++		.ctl_name = CTL_ABI,
++		.procname = "abi",
++		.mode = 0555,
++		.child = abi_table2
++	},
++	{}
++};
++
++static __init int ia32_binfmt_init(void)
++{
++	register_sysctl_table(abi_root_table2);
++	return 0;
++}
++__initcall(ia32_binfmt_init);
++#endif
++
++#else  /* CONFIG_X86_32 */
++
++const char *arch_vma_name(struct vm_area_struct *vma)
++{
++	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
++		return "[vdso]";
++	return NULL;
++}
++
++struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
++{
++	struct mm_struct *mm = tsk->mm;
++
++	/* Check to see if this task was created in compat vdso mode */
++	if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE)
++		return &gate_vma;
++	return NULL;
++}
++
++int in_gate_area(struct task_struct *task, unsigned long addr)
++{
++	const struct vm_area_struct *vma = get_gate_vma(task);
++
++	return vma && addr >= vma->vm_start && addr < vma->vm_end;
++}
++
++int in_gate_area_no_task(unsigned long addr)
++{
++	return 0;
++}
++
++#endif	/* CONFIG_X86_64 */
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:01:50.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:03:15.000000000 +0100
+@@ -45,6 +45,53 @@ struct msi_pirq_entry {
+ 	int entry_nr;
+ };
+ 
++/* Arch hooks */
++
++int __attribute__ ((weak))
++arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
++{
++	return 0;
++}
++
++#ifndef CONFIG_XEN
++int __attribute__ ((weak))
++arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
++{
++	return 0;
++}
++
++int __attribute__ ((weak))
++arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
++{
++	struct msi_desc *entry;
++	int ret;
++
++	list_for_each_entry(entry, &dev->msi_list, list) {
++		ret = arch_setup_msi_irq(dev, entry);
++		if (ret)
++			return ret;
++	}
++
++	return 0;
++}
++
++void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
++{
++	return;
++}
++
++void __attribute__ ((weak))
++arch_teardown_msi_irqs(struct pci_dev *dev)
++{
++	struct msi_desc *entry;
++
++	list_for_each_entry(entry, &dev->msi_list, list) {
++		if (entry->irq != 0)
++			arch_teardown_msi_irq(entry->irq);
++	}
++}
++#endif
++
+ static void msi_set_enable(struct pci_dev *dev, int enable)
+ {
+ 	int pos;
+@@ -266,7 +313,6 @@ static void pci_intx_for_msi(struct pci_
+ 		pci_intx(dev, enable);
+ }
+ 
+-#ifdef CONFIG_PM
+ void pci_restore_msi_state(struct pci_dev *dev)
+ {
+ 	int rc;
+@@ -286,7 +332,7 @@ void pci_restore_msi_state(struct pci_de
+ 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
+ 	WARN(rc && rc != -ENOSYS, "restore_msi -> %d\n", rc);
+ }
+-#endif	/* CONFIG_PM */
++EXPORT_SYMBOL_GPL(pci_restore_msi_state);
+ 
+ /**
+  * msi_capability_init - configure device's MSI capability structure
+@@ -707,51 +753,3 @@ void pci_msi_init_pci_dev(struct pci_dev
+ 	INIT_LIST_HEAD(&dev->msi_list);
+ #endif
+ }
+-
+-
+-/* Arch hooks */
+-
+-int __attribute__ ((weak))
+-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
+-{
+-	return 0;
+-}
+-
+-#ifndef CONFIG_XEN
+-int __attribute__ ((weak))
+-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+-{
+-	return 0;
+-}
+-
+-int __attribute__ ((weak))
+-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+-{
+-	struct msi_desc *entry;
+-	int ret;
+-
+-	list_for_each_entry(entry, &dev->msi_list, list) {
+-		ret = arch_setup_msi_irq(dev, entry);
+-		if (ret)
+-			return ret;
+-	}
+-
+-	return 0;
+-}
+-
+-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+-{
+-	return;
+-}
+-
+-void __attribute__ ((weak))
+-arch_teardown_msi_irqs(struct pci_dev *dev)
+-{
+-	struct msi_desc *entry;
+-
+-	list_for_each_entry(entry, &dev->msi_list, list) {
+-		if (entry->irq != 0)
+-			arch_teardown_msi_irq(entry->irq);
+-	}
+-}
+-#endif
+--- head-2010-01-18.orig/drivers/pci/pci.c	2009-12-04 10:27:46.000000000 +0100
++++ head-2010-01-18/drivers/pci/pci.c	2009-11-06 10:51:25.000000000 +0100
+@@ -386,7 +386,12 @@ pci_find_parent_resource(const struct pc
+  * Restore the BAR values for a given device, so as to make it
+  * accessible by its driver.
+  */
++#ifndef CONFIG_XEN
+ static void
++#else
++EXPORT_SYMBOL_GPL(pci_restore_bars);
++void
++#endif
+ pci_restore_bars(struct pci_dev *dev)
+ {
+ 	int i;
+--- head-2010-01-18.orig/drivers/xen/balloon/sysfs.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/sysfs.c	2009-11-06 10:51:25.000000000 +0100
+@@ -104,7 +104,7 @@ static struct attribute_group balloon_in
+ };
+ 
+ static struct sysdev_class balloon_sysdev_class = {
+-	set_kset_name(BALLOON_CLASS_NAME),
++	.name = BALLOON_CLASS_NAME,
+ };
+ 
+ static struct sys_device balloon_sysdev;
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2010-01-04 12:35:54.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 12:38:24.000000000 +0100
+@@ -150,7 +150,7 @@ static void unplug_queue(blkif_t *blkif)
+ 		return;
+ 	if (blkif->plug->unplug_fn)
+ 		blkif->plug->unplug_fn(blkif->plug);
+-	blk_put_queue(blkif->plug);
++	kobject_put(&blkif->plug->kobj);
+ 	blkif->plug = NULL;
+ }
+ 
+@@ -161,7 +161,8 @@ static void plug_queue(blkif_t *blkif, s
+ 	if (q == blkif->plug)
+ 		return;
+ 	unplug_queue(blkif);
+-	blk_get_queue(q);
++	WARN_ON(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags));
++	kobject_get(&q->kobj);
+ 	blkif->plug = q;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:19:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:19:36.000000000 +0100
+@@ -722,7 +722,6 @@ static irqreturn_t blkif_int(int irq, vo
+ 	RING_IDX i, rp;
+ 	unsigned long flags;
+ 	struct blkfront_info *info = (struct blkfront_info *)dev_id;
+-	int uptodate;
+ 
+ 	spin_lock_irqsave(&blkif_io_lock, flags);
+ 
+@@ -747,13 +746,13 @@ static irqreturn_t blkif_int(int irq, vo
+ 
+ 		ADD_ID_TO_FREELIST(info, id);
+ 
+-		uptodate = (bret->status == BLKIF_RSP_OKAY);
++		ret = bret->status == BLKIF_RSP_OKAY ? 0 : -EIO;
+ 		switch (bret->operation) {
+ 		case BLKIF_OP_WRITE_BARRIER:
+ 			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+ 				printk("blkfront: %s: write barrier op failed\n",
+ 				       info->gd->disk_name);
+-				uptodate = -EOPNOTSUPP;
++				ret = -EOPNOTSUPP;
+ 				info->feature_barrier = 0;
+ 			        xlvbd_barrier(info);
+ 			}
+@@ -764,10 +763,8 @@ static irqreturn_t blkif_int(int irq, vo
+ 				DPRINTK("Bad return from blkdev data "
+ 					"request: %x\n", bret->status);
+ 
+-			ret = end_that_request_first(req, uptodate,
+-				req->hard_nr_sectors);
++			ret = __blk_end_request(req, ret, blk_rq_bytes(req));
+ 			BUG_ON(ret);
+-			end_that_request_last(req, uptodate);
+ 			break;
+ 		default:
+ 			BUG();
+--- head-2010-01-18.orig/drivers/xen/blktap/blktap.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap/blktap.c	2010-01-04 12:38:20.000000000 +0100
+@@ -336,8 +336,8 @@ static pte_t blktap_clear_pte(struct vm_
+ 		uvstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT);
+ 	}
+ 	if (vma->vm_file == NULL || uvaddr < uvstart)
+-		return ptep_get_and_clear_full(vma->vm_mm, uvaddr, 
+-					       ptep, is_fullmm);
++		return xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
++						   is_fullmm);
+ 
+ 	/* TODO Should these be changed to if statements? */
+ 	BUG_ON(!info);
+@@ -380,8 +380,8 @@ static pte_t blktap_clear_pte(struct vm_
+ 		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap));
+ 
+ 		/* USING SHADOW PAGE TABLES. */
+-		copy = ptep_get_and_clear_full(vma->vm_mm, uvaddr, ptep,
+-					       is_fullmm);
++		copy = xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
++						   is_fullmm);
+ 	}
+ 
+ 	if (count) {
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2010-01-04 12:36:00.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2010-01-04 12:37:57.000000000 +0100
+@@ -163,9 +163,9 @@ blktap_map_uaddr_fn(pte_t *ptep, struct 
+ }
+ 
+ static int
+-blktap_map_uaddr(struct mm_struct *mm, unsigned long address, pte_t pte)
++blktap_map_uaddr(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+ {
+-	return apply_to_page_range(mm, address,
++	return apply_to_page_range(vma ? vma->vm_mm : NULL, address,
+ 				   PAGE_SIZE, blktap_map_uaddr_fn, &pte);
+ }
+ 
+@@ -173,18 +173,29 @@ static int
+ blktap_umap_uaddr_fn(pte_t *ptep, struct page *pmd_page,
+ 		     unsigned long addr, void *data)
+ {
+-	struct mm_struct *mm = (struct mm_struct *)data;
++	struct vm_area_struct *vma = data;
+ 
+ 	BTDBG("ptep %p\n", ptep);
+-	pte_clear(mm, addr, ptep);
++	xen_ptep_get_and_clear_full(vma, addr, ptep, 1);
+ 	return 0;
+ }
+ 
+ static int
+-blktap_umap_uaddr(struct mm_struct *mm, unsigned long address)
++blktap_umap_uaddr(struct vm_area_struct *vma, unsigned long address)
+ {
++	struct mm_struct *mm = NULL;
++
++	if (!vma) {
++#ifdef CONFIG_X86
++		if (HYPERVISOR_update_va_mapping(address, __pte(0),
++						 UVMF_INVLPG|UVMF_ALL))
++			BUG();
++		return 1;
++#endif
++	} else
++		mm = vma->vm_mm;
+ 	return apply_to_page_range(mm, address,
+-				   PAGE_SIZE, blktap_umap_uaddr_fn, mm);
++				   PAGE_SIZE, blktap_umap_uaddr_fn, vma);
+ }
+ 
+ static inline void
+@@ -198,17 +209,10 @@ flush_tlb_kernel_page(unsigned long kvad
+ }
+ 
+ static void
+-blktap_device_end_dequeued_request(struct blktap_device *dev,
+-				   struct request *req, int uptodate)
++blktap_device_end_dequeued_request(struct request *req, int ret)
+ {
+-	int ret;
+-
+-	ret = end_that_request_first(req, uptodate, req->hard_nr_sectors);
+-	BUG_ON(ret);
+-
+-	spin_lock_irq(&dev->lock);
+-	end_that_request_last(req, uptodate);
+-	spin_unlock_irq(&dev->lock);
++	if (blk_end_request(req, ret, blk_rq_bytes(req)))
++		BUG();
+ }
+ 
+ /*
+@@ -336,8 +340,8 @@ blktap_unmap(struct blktap *tap, struct 
+ 
+ 		if (!xen_feature(XENFEAT_auto_translated_physmap) &&
+ 		    request->handles[i].kernel == INVALID_GRANT_HANDLE) {
+-			blktap_umap_uaddr(&init_mm, kvaddr);
+-			flush_tlb_kernel_page(kvaddr);
++			if (blktap_umap_uaddr(NULL, kvaddr) == 0)
++				flush_tlb_kernel_page(kvaddr);
+ 			set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
+ 					    INVALID_P2M_ENTRY);
+ 		}
+@@ -377,7 +381,7 @@ blktap_device_fail_pending_requests(stru
+ 
+ 		blktap_unmap(tap, request);
+ 		req = (struct request *)(unsigned long)request->id;
+-		blktap_device_end_dequeued_request(dev, req, 0);
++		blktap_device_end_dequeued_request(req, -ENODEV);
+ 		blktap_request_free(tap, request);
+ 	}
+ 
+@@ -400,16 +404,11 @@ blktap_device_finish_request(struct blkt
+ 			     blkif_response_t *res,
+ 			     struct blktap_request *request)
+ {
+-	int uptodate;
+ 	struct request *req;
+-	struct blktap_device *dev;
+-
+-	dev = &tap->device;
+ 
+ 	blktap_unmap(tap, request);
+ 
+ 	req = (struct request *)(unsigned long)request->id;
+-	uptodate = (res->status == BLKIF_RSP_OKAY);
+ 
+ 	BTDBG("req %p res status %d operation %d/%d id %lld\n", req,
+ 	      res->status, res->operation, request->operation,
+@@ -421,7 +420,8 @@ blktap_device_finish_request(struct blkt
+ 		if (unlikely(res->status != BLKIF_RSP_OKAY))
+ 			BTERR("Bad return from device data "
+ 				"request: %x\n", res->status);
+-		blktap_device_end_dequeued_request(dev, req, uptodate);
++		blktap_device_end_dequeued_request(req,
++			res->status == BLKIF_RSP_OKAY ? 0 : -EIO);
+ 		break;
+ 	default:
+ 		BUG();
+@@ -571,9 +571,9 @@ blktap_map(struct blktap *tap,
+ 
+ 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ 		pte = mk_pte(page, ring->vma->vm_page_prot);
+-		blktap_map_uaddr(ring->vma->vm_mm, uvaddr, pte_mkwrite(pte));
++		blktap_map_uaddr(ring->vma, uvaddr, pte_mkwrite(pte));
+ 		flush_tlb_page(ring->vma, uvaddr);
+-		blktap_map_uaddr(&init_mm, kvaddr, mk_pte(page, PAGE_KERNEL));
++		blktap_map_uaddr(NULL, kvaddr, mk_pte(page, PAGE_KERNEL));
+ 		flush_tlb_kernel_page(kvaddr);
+ 
+ 		set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, pte_mfn(pte));
+@@ -896,7 +896,7 @@ blktap_device_run_queue(struct blktap *t
+ 		if (!err)
+ 			queued++;
+ 		else {
+-			blktap_device_end_dequeued_request(dev, req, 0);
++			blktap_device_end_dequeued_request(req, err);
+ 			blktap_request_free(tap, request);
+ 		}
+ 
+--- head-2010-01-18.orig/drivers/xen/blktap2/ring.c	2009-12-16 11:43:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/ring.c	2009-11-06 10:51:25.000000000 +0100
+@@ -103,8 +103,8 @@ blktap_ring_clear_pte(struct vm_area_str
+ 	 * mapped region.
+ 	 */
+ 	if (uvaddr < ring->user_vstart)
+-		return ptep_get_and_clear_full(vma->vm_mm, uvaddr,
+-					       ptep, is_fullmm);
++		return xen_ptep_get_and_clear_full(vma, uvaddr,
++						   ptep, is_fullmm);
+ 
+ 	offset  = (int)((uvaddr - ring->user_vstart) >> PAGE_SHIFT);
+ 	usr_idx = offset / BLKIF_MAX_SEGMENTS_PER_REQUEST;
+@@ -146,8 +146,8 @@ blktap_ring_clear_pte(struct vm_area_str
+ 				    khandle->user);
+ 		count++;
+ 	} else
+-		copy = ptep_get_and_clear_full(vma->vm_mm, uvaddr, ptep,
+-					       is_fullmm);
++		copy = xen_ptep_get_and_clear_full(vma, uvaddr, ptep,
++						   is_fullmm);
+ 
+ 	if (count)
+ 		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+--- head-2010-01-18.orig/drivers/xen/core/Makefile	2008-07-21 11:00:33.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/Makefile	2009-11-06 10:51:25.000000000 +0100
+@@ -10,5 +10,6 @@ obj-$(CONFIG_SYS_HYPERVISOR)	+= hypervis
+ obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
+ obj-$(CONFIG_XEN_SYSFS)		+= xen_sysfs.o
+ obj-$(CONFIG_XEN_SMPBOOT)	+= smpboot.o
++obj-$(CONFIG_X86_SMP)		+= spinlock.o
+ obj-$(CONFIG_KEXEC)		+= machine_kexec.o
+ obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:51:25.000000000 +0100
+@@ -194,7 +194,7 @@ static inline unsigned int cpu_from_evtc
+ 
+ /* Upcall to generic IRQ layer. */
+ #ifdef CONFIG_X86
+-extern fastcall unsigned int do_IRQ(struct pt_regs *regs);
++extern unsigned int do_IRQ(struct pt_regs *regs);
+ void __init xen_init_IRQ(void);
+ void __init init_IRQ(void)
+ {
+@@ -203,13 +203,11 @@ void __init init_IRQ(void)
+ }
+ #if defined (__i386__)
+ static inline void exit_idle(void) {}
+-#define IRQ_REG orig_eax
+ #elif defined (__x86_64__)
+ #include <asm/idle.h>
+-#define IRQ_REG orig_rax
+ #endif
+ #define do_IRQ(irq, regs) do {		\
+-	(regs)->IRQ_REG = ~(irq);	\
++	(regs)->orig_ax = ~(irq);	\
+ 	do_IRQ((regs));			\
+ } while (0)
+ #endif
+@@ -670,13 +668,12 @@ static void set_affinity_irq(unsigned in
+ int resend_irq_on_evtchn(unsigned int irq)
+ {
+ 	int masked, evtchn = evtchn_from_irq(irq);
+-	shared_info_t *s = HYPERVISOR_shared_info;
+ 
+ 	if (!VALID_EVTCHN(evtchn))
+ 		return 1;
+ 
+ 	masked = test_and_set_evtchn_mask(evtchn);
+-	synch_set_bit(evtchn, s->evtchn_pending);
++	set_evtchn(evtchn);
+ 	if (!masked)
+ 		unmask_evtchn(evtchn);
+ 
+@@ -969,6 +966,43 @@ void disable_all_local_evtchn(void)
+ 			synch_set_bit(i, &s->evtchn_mask[0]);
+ }
+ 
++/* Clear an irq's pending state, in preparation for polling on it. */
++void xen_clear_irq_pending(int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		clear_evtchn(evtchn);
++}
++
++/* Set an irq's pending state, to avoid blocking on it. */
++void xen_set_irq_pending(int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn))
++		set_evtchn(evtchn);
++}
++
++/* Test an irq's pending state. */
++int xen_test_irq_pending(int irq)
++{
++	int evtchn = evtchn_from_irq(irq);
++
++	return VALID_EVTCHN(evtchn) && test_evtchn(evtchn);
++}
++
++/* Poll waiting for an irq to become pending.  In the usual case, the
++   irq will be disabled so it won't deliver an interrupt. */
++void xen_poll_irq(int irq)
++{
++	evtchn_port_t evtchn = evtchn_from_irq(irq);
++
++	if (VALID_EVTCHN(evtchn)
++	    && HYPERVISOR_poll_no_timeout(&evtchn, 1))
++		BUG();
++}
++
+ static void restore_cpu_virqs(unsigned int cpu)
+ {
+ 	struct evtchn_bind_virq bind_virq;
+@@ -1022,8 +1056,8 @@ static void restore_cpu_ipis(unsigned in
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+-		unmask_evtchn(evtchn);
+-
++		if (!(irq_desc[irq].status & IRQ_DISABLED))
++			unmask_evtchn(evtchn);
+ 	}
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/hypervisor_sysfs.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/hypervisor_sysfs.c	2009-11-06 10:51:25.000000000 +0100
+@@ -50,7 +50,7 @@ static int __init hypervisor_subsys_init
+ 	if (!is_running_on_xen())
+ 		return -ENODEV;
+ 
+-	hypervisor_subsys.kobj.ktype = &hyp_sysfs_kobj_type;
++	hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
+ 	return 0;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:51:25.000000000 +0100
+@@ -134,6 +134,10 @@ static int __cpuinit xen_smp_intr_init(u
+ 		goto fail;
+ 	per_cpu(callfunc_irq, cpu) = rc;
+ 
++	rc = xen_spinlock_init(cpu);
++	if (rc < 0)
++		goto fail;
++
+ 	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
+ 		goto fail;
+ 
+@@ -144,6 +148,7 @@ static int __cpuinit xen_smp_intr_init(u
+ 		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	if (per_cpu(callfunc_irq, cpu) >= 0)
+ 		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	xen_spinlock_cleanup(cpu);
+ 	return rc;
+ }
+ 
+@@ -155,6 +160,7 @@ static void xen_smp_intr_exit(unsigned i
+ 
+ 	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+ 	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
++	xen_spinlock_cleanup(cpu);
+ }
+ #endif
+ 
+@@ -207,36 +213,25 @@ static void __cpuinit cpu_initialize_con
+ 	smp_trap_init(ctxt.trap_ctxt);
+ 
+ 	ctxt.ldt_ents = 0;
+-	ctxt.gdt_ents = GDT_SIZE / 8;
+-
+-#ifdef __i386__
+ 	ctxt.gdt_frames[0] = virt_to_mfn(get_cpu_gdt_table(cpu));
++	ctxt.gdt_ents = GDT_SIZE / 8;
+ 
+ 	ctxt.user_regs.cs = __KERNEL_CS;
+-	ctxt.user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs);
++	ctxt.user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+ 
+ 	ctxt.kernel_ss = __KERNEL_DS;
+-	ctxt.kernel_sp = idle->thread.esp0;
++	ctxt.kernel_sp = idle->thread.sp0;
+ 
+-	ctxt.event_callback_cs     = __KERNEL_CS;
+ 	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
+-	ctxt.failsafe_callback_cs  = __KERNEL_CS;
+ 	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
++#ifdef __i386__
++	ctxt.event_callback_cs     = __KERNEL_CS;
++	ctxt.failsafe_callback_cs  = __KERNEL_CS;
+ 
+ 	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
+ 
+ 	ctxt.user_regs.fs = __KERNEL_PERCPU;
+ #else /* __x86_64__ */
+-	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[cpu].address);
+-
+-	ctxt.user_regs.cs = __KERNEL_CS;
+-	ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs);
+-
+-	ctxt.kernel_ss = __KERNEL_DS;
+-	ctxt.kernel_sp = idle->thread.rsp0;
+-
+-	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
+-	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
+ 	ctxt.syscall_callback_eip  = (unsigned long)system_call;
+ 
+ 	ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt));
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/xen/core/spinlock.c	2010-01-18 17:10:16.000000000 +0100
+@@ -0,0 +1,228 @@
++/*
++ *	Xen spinlock functions
++ *
++ *	See arch/x86/xen/smp.c for copyright and credits for derived
++ *	portions of this file.
++ */
++
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/kernel.h>
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <xen/evtchn.h>
++
++extern irqreturn_t smp_reschedule_interrupt(int, void *);
++
++static DEFINE_PER_CPU(int, spinlock_irq) = -1;
++static char spinlock_name[NR_CPUS][15];
++
++struct spinning {
++	raw_spinlock_t *lock;
++	unsigned int ticket;
++	struct spinning *prev;
++};
++static DEFINE_PER_CPU(struct spinning *, spinning);
++/*
++ * Protect removal of objects: Addition can be done lockless, and even
++ * removal itself doesn't need protection - what needs to be prevented is
++ * removed objects going out of scope (as they're allocated on the stack.
++ */
++static DEFINE_PER_CPU(raw_rwlock_t, spinning_rm_lock) = __RAW_RW_LOCK_UNLOCKED;
++
++int __cpuinit xen_spinlock_init(unsigned int cpu)
++{
++	int rc;
++
++	sprintf(spinlock_name[cpu], "spinlock%u", cpu);
++	rc = bind_ipi_to_irqhandler(SPIN_UNLOCK_VECTOR,
++				    cpu,
++				    smp_reschedule_interrupt,
++				    IRQF_DISABLED|IRQF_NOBALANCING,
++				    spinlock_name[cpu],
++				    NULL);
++ 	if (rc < 0)
++ 		return rc;
++
++	disable_irq(rc); /* make sure it's never delivered */
++	per_cpu(spinlock_irq, cpu) = rc;
++
++	return 0;
++}
++
++void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
++{
++	if (per_cpu(spinlock_irq, cpu) >= 0)
++		unbind_from_irqhandler(per_cpu(spinlock_irq, cpu), NULL);
++	per_cpu(spinlock_irq, cpu) = -1;
++}
++
++int xen_spin_wait(raw_spinlock_t *lock, unsigned int token)
++{
++	int rc = 0, irq = __get_cpu_var(spinlock_irq);
++	raw_rwlock_t *rm_lock;
++	unsigned long flags;
++	struct spinning spinning;
++
++	/* If kicker interrupt not initialized yet, just spin. */
++	if (unlikely(irq < 0) || unlikely(!cpu_online(raw_smp_processor_id())))
++		return 0;
++
++	token >>= TICKET_SHIFT;
++
++	/* announce we're spinning */
++	spinning.ticket = token;
++	spinning.lock = lock;
++	spinning.prev = __get_cpu_var(spinning);
++	smp_wmb();
++	__get_cpu_var(spinning) = &spinning;
++
++	/* clear pending */
++	xen_clear_irq_pending(irq);
++
++	do {
++		/* Check again to make sure it didn't become free while
++		 * we weren't looking. */
++		if (lock->cur == token) {
++			/* If we interrupted another spinlock while it was
++			 * blocking, make sure it doesn't block (again)
++			 * without rechecking the lock. */
++			if (spinning.prev)
++				xen_set_irq_pending(irq);
++			rc = 1;
++			break;
++		}
++
++		/* block until irq becomes pending */
++		xen_poll_irq(irq);
++	} while (!xen_test_irq_pending(irq));
++
++	/* Leave the irq pending so that any interrupted blocker will
++	 * re-check. */
++	kstat_this_cpu.irqs[irq] += !rc;
++
++	/* announce we're done */
++	__get_cpu_var(spinning) = spinning.prev;
++	rm_lock = &__get_cpu_var(spinning_rm_lock);
++	raw_local_irq_save(flags);
++	__raw_write_lock(rm_lock);
++	__raw_write_unlock(rm_lock);
++	raw_local_irq_restore(flags);
++
++	return rc;
++}
++
++unsigned int xen_spin_adjust(raw_spinlock_t *lock, unsigned int token)
++{
++	struct spinning *spinning;
++
++	for (spinning = __get_cpu_var(spinning); spinning; spinning = spinning->prev)
++		if (spinning->lock == lock) {
++			unsigned int ticket = spinning->ticket;
++
++			spinning->ticket = token >> TICKET_SHIFT;
++			token = (token & ((1 << TICKET_SHIFT) - 1))
++				| (ticket << TICKET_SHIFT);
++			break;
++		}
++
++	return token;
++}
++
++int xen_spin_wait_flags(raw_spinlock_t *lock, unsigned int *ptok,
++			unsigned int flags)
++{
++	int rc = 0, irq = __get_cpu_var(spinlock_irq);
++	raw_rwlock_t *rm_lock;
++	struct spinning spinning, *nested;
++
++	/* If kicker interrupt not initialized yet, just spin. */
++	if (unlikely(irq < 0) || unlikely(!cpu_online(raw_smp_processor_id())))
++		return 0;
++
++	/* announce we're spinning */
++	spinning.ticket = *ptok >> TICKET_SHIFT;
++	spinning.lock = lock;
++	spinning.prev = __get_cpu_var(spinning);
++	smp_wmb();
++	__get_cpu_var(spinning) = &spinning;
++
++	for (nested = spinning.prev; nested; nested = nested->prev)
++		if (nested->lock == lock)
++			break;
++
++	/* clear pending */
++	xen_clear_irq_pending(irq);
++
++	do {
++		/* Check again to make sure it didn't become free while
++		 * we weren't looking. */
++		if (lock->cur == spinning.ticket) {
++			/* If we interrupted another spinlock while it was
++			 * blocking, make sure it doesn't block (again)
++			 * without rechecking the lock. */
++			if (spinning.prev)
++				xen_set_irq_pending(irq);
++			rc = 1;
++			break;
++		}
++
++		if (!nested)
++			/* No need to use raw_local_irq_restore() here, as the
++			 * intended wakeup will happen with the poll call. */
++			vcpu_info_write(evtchn_upcall_mask, flags);
++
++		/* block until irq becomes pending */
++		xen_poll_irq(irq);
++
++		raw_local_irq_disable();
++	} while (!xen_test_irq_pending(irq));
++
++	/* Leave the irq pending so that any interrupted blocker will
++	 * re-check. */
++	if (!rc)
++		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
++
++	/* announce we're done */
++	__get_cpu_var(spinning) = spinning.prev;
++	rm_lock = &__get_cpu_var(spinning_rm_lock);
++	__raw_write_lock(rm_lock);
++	__raw_write_unlock(rm_lock);
++	*ptok = lock->cur | (spinning.ticket << TICKET_SHIFT);
++
++	return rc;
++}
++
++void xen_spin_kick(raw_spinlock_t *lock, unsigned int token)
++{
++	unsigned int cpu;
++
++	token &= (1U << TICKET_SHIFT) - 1;
++	for_each_online_cpu(cpu) {
++		raw_rwlock_t *rm_lock;
++		unsigned long flags;
++		struct spinning *spinning;
++
++		if (cpu == raw_smp_processor_id() || !per_cpu(spinning, cpu))
++			continue;
++
++		rm_lock = &per_cpu(spinning_rm_lock, cpu);
++		raw_local_irq_save(flags);
++		__raw_read_lock(rm_lock);
++
++		spinning = per_cpu(spinning, cpu);
++		smp_rmb();
++		if (spinning
++		    && (spinning->lock != lock || spinning->ticket != token))
++			spinning = NULL;
++
++		__raw_read_unlock(rm_lock);
++		raw_local_irq_restore(flags);
++
++		if (unlikely(spinning)) {
++			notify_remote_via_irq(per_cpu(spinlock_irq, cpu));
++			return;
++		}
++	}
++}
++EXPORT_SYMBOL(xen_spin_kick);
+--- head-2010-01-18.orig/drivers/xen/core/xen_sysfs.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/xen_sysfs.c	2009-11-06 10:51:25.000000000 +0100
+@@ -30,12 +30,12 @@ HYPERVISOR_ATTR_RO(type);
+ 
+ static int __init xen_sysfs_type_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kobj, &type_attr.attr);
++	return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
+ }
+ 
+ static void xen_sysfs_type_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kobj, &type_attr.attr);
++	sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
+ }
+ 
+ /* xen version attributes */
+@@ -91,13 +91,12 @@ static struct attribute_group version_gr
+ 
+ static int __init xen_sysfs_version_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kobj,
+-				  &version_group);
++	return sysfs_create_group(hypervisor_kobj, &version_group);
+ }
+ 
+ static void xen_sysfs_version_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kobj, &version_group);
++	sysfs_remove_group(hypervisor_kobj, &version_group);
+ }
+ 
+ /* UUID */
+@@ -126,12 +125,12 @@ HYPERVISOR_ATTR_RO(uuid);
+ 
+ static int __init xen_sysfs_uuid_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kobj, &uuid_attr.attr);
++	return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
+ }
+ 
+ static void xen_sysfs_uuid_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kobj, &uuid_attr.attr);
++	sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
+ }
+ 
+ /* xen compilation attributes */
+@@ -204,14 +203,12 @@ static struct attribute_group xen_compil
+ 
+ int __init static xen_compilation_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kobj,
+-				  &xen_compilation_group);
++	return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
+ }
+ 
+ static void xen_compilation_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kobj,
+-			   &xen_compilation_group);
++	sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
+ }
+ 
+ /* xen properties info */
+@@ -325,14 +322,12 @@ static struct attribute_group xen_proper
+ 
+ static int __init xen_properties_init(void)
+ {
+-	return sysfs_create_group(&hypervisor_subsys.kobj,
+-				  &xen_properties_group);
++	return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
+ }
+ 
+ static void xen_properties_destroy(void)
+ {
+-	sysfs_remove_group(&hypervisor_subsys.kobj,
+-			   &xen_properties_group);
++	sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
+ }
+ 
+ #ifdef CONFIG_KEXEC
+@@ -350,13 +345,12 @@ HYPERVISOR_ATTR_RO(vmcoreinfo);
+ 
+ static int __init xen_sysfs_vmcoreinfo_init(void)
+ {
+-	return sysfs_create_file(&hypervisor_subsys.kobj,
+-				 &vmcoreinfo_attr.attr);
++	return sysfs_create_file(hypervisor_kobj, &vmcoreinfo_attr.attr);
+ }
+ 
+ static void xen_sysfs_vmcoreinfo_destroy(void)
+ {
+-	sysfs_remove_file(&hypervisor_subsys.kobj, &vmcoreinfo_attr.attr);
++	sysfs_remove_file(hypervisor_kobj, &vmcoreinfo_attr.attr);
+ }
+ 
+ #endif
+--- head-2010-01-18.orig/drivers/xen/gntdev/gntdev.c	2010-01-04 12:22:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/gntdev/gntdev.c	2010-01-04 12:38:10.000000000 +0100
+@@ -791,7 +791,7 @@ static pte_t gntdev_clear_pte(struct vm_
+ 				       op.status);
+ 		} else {
+ 			/* USING SHADOW PAGE TABLES. */
+-			copy = ptep_get_and_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++			copy = xen_ptep_get_and_clear_full(vma, addr, ptep, is_fullmm);
+ 		}
+ 
+ 		/* Finally, we unmap the grant from kernel space. */
+@@ -819,7 +819,7 @@ static pte_t gntdev_clear_pte(struct vm_
+ 			INVALID_P2M_ENTRY);
+ 
+ 	} else {
+-		copy = ptep_get_and_clear_full(vma->vm_mm, addr, ptep, is_fullmm);
++		copy = xen_ptep_get_and_clear_full(vma, addr, ptep, is_fullmm);
+ 	}
+ 
+ 	return copy;
+--- head-2010-01-18.orig/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:25.000000000 +0100
+@@ -260,19 +260,19 @@ static int map_data_for_request(struct v
+ 		return -ENOMEM;
+ 	}
+ 
+-	if (sc->use_sg) {
++	if (scsi_bufflen(sc)) {
+ 		/* quoted scsi_lib.c/scsi_req_map_sg . */
+-		struct scatterlist *sg, *sgl = (struct scatterlist *)sc->request_buffer;
+-		unsigned int data_len = sc->request_bufflen;
++		struct scatterlist *sg, *sgl = scsi_sglist(sc);
++		unsigned int data_len = scsi_bufflen(sc);
+ 
+-		nr_pages = (sc->request_bufflen + sgl->offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
++		nr_pages = (data_len + sgl->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_each_sg (sgl, sg, sc->use_sg, i) {
++		for_each_sg (sgl, sg, scsi_sg_count(sc), i) {
+ 			page = sg_page(sg);
+ 			off = sg->offset;
+ 			len = sg->length;
+@@ -306,45 +306,6 @@ static int map_data_for_request(struct v
+ 				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:
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-dbg.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-dbg.c	2009-11-06 10:51:25.000000000 +0100
+@@ -43,17 +43,16 @@
+  * DEALINGS IN THE SOFTWARE.
+  */
+ 
+-static ssize_t show_statistics(struct class_device *class_dev, char *buf)
++static ssize_t show_statistics(struct device *dev,
++			       struct device_attribute *attr, char *buf)
+ {
+-	struct usb_bus *bus;
+ 	struct usb_hcd *hcd;
+ 	struct usbfront_info *info;
+ 	unsigned long flags;
+ 	unsigned temp, size;
+ 	char *next;
+ 
+-	bus = class_get_devdata(class_dev);
+-	hcd = bus->hcpriv;
++	hcd = dev_get_drvdata(dev);
+ 	info = hcd_to_info(hcd);
+ 	next = buf;
+ 	size = PAGE_SIZE;
+@@ -85,18 +84,18 @@ static ssize_t show_statistics(struct cl
+ 	return PAGE_SIZE - size;
+ }
+ 
+-static CLASS_DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
++static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
+ 
+ static inline void create_debug_file(struct usbfront_info *info)
+ {
+-	struct class_device *cldev = info_to_hcd(info)->self.class_dev;
+-	if (class_device_create_file(cldev, &class_device_attr_statistics))
++	struct device *dev = info_to_hcd(info)->self.controller;
++	if (device_create_file(dev, &dev_attr_statistics))
+ 		printk(KERN_WARNING "statistics file not created for %s\n",
+ 		       info_to_hcd(info)->self.bus_name);
+ }
+ 
+ static inline void remove_debug_file(struct usbfront_info *info)
+ {
+-	struct class_device *cldev = info_to_hcd(info)->self.class_dev;
+-	class_device_remove_file(cldev, &class_device_attr_statistics);
++	struct device *dev = info_to_hcd(info)->self.controller;
++	device_remove_file(dev, &dev_attr_statistics);
+ }
+--- head-2010-01-18.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:35.000000000 +0100
+@@ -78,7 +78,7 @@ static int xenoprof_resume(struct sys_de
+ 
+ 
+ static struct sysdev_class oprofile_sysclass = {
+-	set_kset_name("oprofile"),
++	.name		= "oprofile",
+ 	.resume		= xenoprof_resume,
+ 	.suspend	= xenoprof_suspend
+ };
+--- head-2010-01-18.orig/arch/x86/include/asm/e820.h	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/e820.h	2009-11-06 10:51:25.000000000 +0100
+@@ -129,7 +129,11 @@ extern char *default_machine_specific_me
+ #endif /* __KERNEL__ */
+ #endif /* __ASSEMBLY__ */
+ 
++#ifndef CONFIG_XEN
+ #define ISA_START_ADDRESS	0xa0000
++#else
++#define ISA_START_ADDRESS	0
++#endif
+ #define ISA_END_ADDRESS		0x100000
+ #define is_ISA_range(s, e) ((s) >= ISA_START_ADDRESS && (e) < ISA_END_ADDRESS)
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:25.000000000 +0100
+@@ -13,18 +13,13 @@
+  * page. This avoids data corruption on some CPUs.
+  */
+ 
+-/*
+- * Caller's responsibility to call global_flush_tlb() for performance
+- * reasons
+- */
+ #define map_page_into_agp(page) ( \
+ 	xen_create_contiguous_region((unsigned long)page_address(page), 0, 32) \
+-	?: change_page_attr(page, 1, PAGE_KERNEL_NOCACHE))
++	?: set_pages_uc(page, 1))
+ #define unmap_page_from_agp(page) ( \
+ 	xen_destroy_contiguous_region((unsigned long)page_address(page), 0), \
+ 	/* only a fallback: xen_destroy_contiguous_region uses PAGE_KERNEL */ \
+-	change_page_attr(page, 1, PAGE_KERNEL))
+-#define flush_agp_mappings() global_flush_tlb()
++	set_pages_wb(page, 1))
+ 
+ /*
+  * Could use CLFLUSH here if the cpu supports it. But then it would
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,404 @@
++#ifndef _ASM_DESC_H_
++#define _ASM_DESC_H_
++
++#ifndef __ASSEMBLY__
++#include <asm/desc_defs.h>
++#include <asm/ldt.h>
++#include <asm/mmu.h>
++#include <linux/smp.h>
++
++static inline void fill_ldt(struct desc_struct *desc,
++			    const struct user_desc *info)
++{
++	desc->limit0 = info->limit & 0x0ffff;
++	desc->base0 = info->base_addr & 0x0000ffff;
++
++	desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
++	desc->type = (info->read_exec_only ^ 1) << 1;
++	desc->type |= info->contents << 2;
++	desc->s = 1;
++	desc->dpl = 0x3;
++	desc->p = info->seg_not_present ^ 1;
++	desc->limit = (info->limit & 0xf0000) >> 16;
++	desc->avl = info->useable;
++	desc->d = info->seg_32bit;
++	desc->g = info->limit_in_pages;
++	desc->base2 = (info->base_addr & 0xff000000) >> 24;
++}
++
++#ifndef CONFIG_X86_NO_IDT
++extern struct desc_ptr idt_descr;
++extern gate_desc idt_table[];
++#endif
++
++#ifdef CONFIG_X86_64
++extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
++extern struct desc_ptr cpu_gdt_descr[];
++/* the cpu gdt accessor */
++#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
++
++static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
++			     unsigned dpl, unsigned ist, unsigned seg)
++{
++	gate->offset_low = PTR_LOW(func);
++	gate->segment = __KERNEL_CS;
++	gate->ist = ist;
++	gate->p = 1;
++	gate->dpl = dpl;
++	gate->zero0 = 0;
++	gate->zero1 = 0;
++	gate->type = type;
++	gate->offset_middle = PTR_MIDDLE(func);
++	gate->offset_high = PTR_HIGH(func);
++}
++
++#else
++struct gdt_page {
++	struct desc_struct gdt[GDT_ENTRIES];
++} __attribute__((aligned(PAGE_SIZE)));
++DECLARE_PER_CPU(struct gdt_page, gdt_page);
++
++static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
++{
++	return per_cpu(gdt_page, cpu).gdt;
++}
++
++static inline void pack_gate(gate_desc *gate, unsigned char type,
++       unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
++
++{
++	gate->a = (seg << 16) | (base & 0xffff);
++	gate->b = (base & 0xffff0000) |
++		  (((0x80 | type | (dpl << 5)) & 0xff) << 8);
++}
++
++#endif
++
++static inline int desc_empty(const void *ptr)
++{
++	const u32 *desc = ptr;
++	return !(desc[0] | desc[1]);
++}
++
++#ifndef CONFIG_XEN
++#define load_TR_desc() native_load_tr_desc()
++#define load_gdt(dtr) native_load_gdt(dtr)
++#define load_idt(dtr) native_load_idt(dtr)
++#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
++#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
++
++#define store_gdt(dtr) native_store_gdt(dtr)
++#define store_idt(dtr) native_store_idt(dtr)
++#define store_tr(tr) (tr = native_store_tr())
++#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
++
++#define load_TLS(t, cpu) native_load_tls(t, cpu)
++#define set_ldt native_set_ldt
++
++#define write_ldt_entry(dt, entry, desc) \
++				native_write_ldt_entry(dt, entry, desc)
++#define write_gdt_entry(dt, entry, desc, type) \
++				native_write_gdt_entry(dt, entry, desc, type)
++#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
++
++static inline void native_write_idt_entry(gate_desc *idt, int entry,
++					  const gate_desc *gate)
++{
++	memcpy(&idt[entry], gate, sizeof(*gate));
++}
++
++static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
++					  const void *desc)
++{
++	memcpy(&ldt[entry], desc, 8);
++}
++
++static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
++					  const void *desc, int type)
++{
++	unsigned int size;
++	switch (type) {
++	case DESC_TSS:
++		size = sizeof(tss_desc);
++		break;
++	case DESC_LDT:
++		size = sizeof(ldt_desc);
++		break;
++	default:
++		size = sizeof(struct desc_struct);
++		break;
++	}
++	memcpy(&gdt[entry], desc, size);
++}
++#endif
++
++static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
++				   unsigned long limit, unsigned char type,
++				   unsigned char flags)
++{
++	desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
++	desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
++		  (limit & 0x000f0000) | ((type & 0xff) << 8) |
++		  ((flags & 0xf) << 20);
++	desc->p = 1;
++}
++
++
++#ifndef CONFIG_XEN
++static inline void set_tssldt_descriptor(void *d, unsigned long addr,
++					 unsigned type, unsigned size)
++{
++#ifdef CONFIG_X86_64
++	struct ldttss_desc64 *desc = d;
++	memset(desc, 0, sizeof(*desc));
++	desc->limit0 = size & 0xFFFF;
++	desc->base0 = PTR_LOW(addr);
++	desc->base1 = PTR_MIDDLE(addr) & 0xFF;
++	desc->type = type;
++	desc->p = 1;
++	desc->limit1 = (size >> 16) & 0xF;
++	desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
++	desc->base3 = PTR_HIGH(addr);
++#else
++
++	pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
++#endif
++}
++
++static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
++{
++	struct desc_struct *d = get_cpu_gdt_table(cpu);
++	tss_desc tss;
++
++	/*
++	 * sizeof(unsigned long) coming from an extra "long" at the end
++	 * of the iobitmap. See tss_struct definition in processor.h
++	 *
++	 * -1? seg base+limit should be pointing to the address of the
++	 * last valid byte
++	 */
++	set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
++		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
++	write_gdt_entry(d, entry, &tss, DESC_TSS);
++}
++
++#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
++
++static inline void native_set_ldt(const void *addr, unsigned int entries)
++{
++	if (likely(entries == 0))
++		__asm__ __volatile__("lldt %w0"::"q" (0));
++	else {
++		unsigned cpu = smp_processor_id();
++		ldt_desc ldt;
++
++		set_tssldt_descriptor(&ldt, (unsigned long)addr,
++				      DESC_LDT, entries * sizeof(ldt) - 1);
++		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
++				&ldt, DESC_LDT);
++		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
++	}
++}
++
++static inline void native_load_tr_desc(void)
++{
++	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
++}
++
++static inline void native_load_gdt(const struct desc_ptr *dtr)
++{
++	asm volatile("lgdt %0"::"m" (*dtr));
++}
++
++static inline void native_load_idt(const struct desc_ptr *dtr)
++{
++	asm volatile("lidt %0"::"m" (*dtr));
++}
++
++static inline void native_store_gdt(struct desc_ptr *dtr)
++{
++	asm volatile("sgdt %0":"=m" (*dtr));
++}
++
++static inline void native_store_idt(struct desc_ptr *dtr)
++{
++	asm volatile("sidt %0":"=m" (*dtr));
++}
++
++static inline unsigned long native_store_tr(void)
++{
++	unsigned long tr;
++	asm volatile("str %0":"=r" (tr));
++	return tr;
++}
++
++static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
++{
++	unsigned int i;
++	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
++
++	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
++		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
++}
++#else
++#define load_TLS(t, cpu) xen_load_tls(t, cpu)
++#define set_ldt xen_set_ldt
++
++extern int write_ldt_entry(struct desc_struct *ldt, int entry,
++			   const void *desc);
++extern int write_gdt_entry(struct desc_struct *gdt, int entry,
++			   const void *desc, int type);
++
++static inline void xen_load_tls(struct thread_struct *t, unsigned int cpu)
++{
++	unsigned int i;
++	struct desc_struct *gdt = get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN;
++
++	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
++		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
++						 *(u64 *)&t->tls_array[i]))
++			BUG();
++}
++#endif
++
++#define _LDT_empty(info) (\
++	(info)->base_addr	== 0	&& \
++	(info)->limit		== 0	&& \
++	(info)->contents	== 0	&& \
++	(info)->read_exec_only	== 1	&& \
++	(info)->seg_32bit	== 0	&& \
++	(info)->limit_in_pages	== 0	&& \
++	(info)->seg_not_present	== 1	&& \
++	(info)->useable		== 0)
++
++#ifdef CONFIG_X86_64
++#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
++#else
++#define LDT_empty(info) (_LDT_empty(info))
++#endif
++
++static inline void clear_LDT(void)
++{
++	set_ldt(NULL, 0);
++}
++
++/*
++ * load one particular LDT into the current CPU
++ */
++static inline void load_LDT_nolock(mm_context_t *pc)
++{
++	set_ldt(pc->ldt, pc->size);
++}
++
++static inline void load_LDT(mm_context_t *pc)
++{
++	preempt_disable();
++	load_LDT_nolock(pc);
++	preempt_enable();
++}
++
++static inline unsigned long get_desc_base(const struct desc_struct *desc)
++{
++	return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
++}
++
++static inline unsigned long get_desc_limit(const struct desc_struct *desc)
++{
++	return desc->limit0 | (desc->limit << 16);
++}
++
++#ifndef CONFIG_X86_NO_IDT
++static inline void _set_gate(int gate, unsigned type, void *addr,
++			      unsigned dpl, unsigned ist, unsigned seg)
++{
++	gate_desc s;
++	pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
++	/*
++	 * does not need to be atomic because it is only done once at
++	 * setup time
++	 */
++	write_idt_entry(idt_table, gate, &s);
++}
++
++/*
++ * This needs to use 'idt_table' rather than 'idt', and
++ * thus use the _nonmapped_ version of the IDT, as the
++ * Pentium F0 0F bugfix can have resulted in the mapped
++ * IDT being write-protected.
++ */
++static inline void set_intr_gate(unsigned int n, void *addr)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
++}
++
++/*
++ * This routine sets up an interrupt gate at directory privilege level 3.
++ */
++static inline void set_system_intr_gate(unsigned int n, void *addr)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
++}
++
++static inline void set_trap_gate(unsigned int n, void *addr)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
++}
++
++static inline void set_system_gate(unsigned int n, void *addr)
++{
++	BUG_ON((unsigned)n > 0xFF);
+ #ifdef CONFIG_X86_32
+-# include "desc_32.h"
++	_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
++#else
++	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
++#endif
++}
++
++static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
++}
++
++static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
++}
++
++static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
++{
++	BUG_ON((unsigned)n > 0xFF);
++	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
++}
++#endif
++
+ #else
+-# include "desc_64.h"
++/*
++ * GET_DESC_BASE reads the descriptor base of the specified segment.
++ *
++ * Args:
++ *    idx - descriptor index
++ *    gdt - GDT pointer
++ *    base - 32bit register to which the base will be written
++ *    lo_w - lo word of the "base" register
++ *    lo_b - lo byte of the "base" register
++ *    hi_b - hi byte of the low word of the "base" register
++ *
++ * Example:
++ *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
++ *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
++ */
++#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
++	movb idx*8+4(gdt), lo_b; \
++	movb idx*8+7(gdt), hi_b; \
++	shll $16, base; \
++	movw idx*8+2(gdt), lo_w;
++
++
++#endif /* __ASSEMBLY__ */
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:49:47.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,262 +0,0 @@
+-#ifndef __ARCH_DESC_H
+-#define __ARCH_DESC_H
+-
+-#include <asm/ldt.h>
+-#include <asm/segment.h>
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/preempt.h>
+-#include <linux/smp.h>
+-
+-#include <asm/mmu.h>
+-
+-struct Xgt_desc_struct {
+-	unsigned short size;
+-	unsigned long address __attribute__((packed));
+-	unsigned short pad;
+-} __attribute__ ((packed));
+-
+-struct gdt_page
+-{
+-	struct desc_struct gdt[GDT_ENTRIES];
+-} __attribute__((aligned(PAGE_SIZE)));
+-DECLARE_PER_CPU(struct gdt_page, gdt_page);
+-
+-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+-{
+-	return per_cpu(gdt_page, cpu).gdt;
+-}
+-
+-extern struct Xgt_desc_struct idt_descr;
+-extern struct desc_struct idt_table[];
+-extern void set_intr_gate(unsigned int irq, void * addr);
+-
+-static inline void pack_descriptor(__u32 *a, __u32 *b,
+-	unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
+-{
+-	*a = ((base & 0xffff) << 16) | (limit & 0xffff);
+-	*b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+-		(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
+-}
+-
+-static inline void pack_gate(__u32 *a, __u32 *b,
+-	unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
+-{
+-	*a = (seg << 16) | (base & 0xffff);
+-	*b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+-}
+-
+-#define DESCTYPE_LDT 	0x82	/* present, system, DPL-0, LDT */
+-#define DESCTYPE_TSS 	0x89	/* present, system, DPL-0, 32-bit TSS */
+-#define DESCTYPE_TASK	0x85	/* present, system, DPL-0, task gate */
+-#define DESCTYPE_INT	0x8e	/* present, system, DPL-0, interrupt gate */
+-#define DESCTYPE_TRAP	0x8f	/* present, system, DPL-0, trap gate */
+-#define DESCTYPE_DPL3	0x60	/* DPL-3 */
+-#define DESCTYPE_S	0x10	/* !system */
+-
+-#ifndef CONFIG_XEN
+-#define load_TR_desc() native_load_tr_desc()
+-#define load_gdt(dtr) native_load_gdt(dtr)
+-#define load_idt(dtr) native_load_idt(dtr)
+-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+-
+-#define store_gdt(dtr) native_store_gdt(dtr)
+-#define store_idt(dtr) native_store_idt(dtr)
+-#define store_tr(tr) (tr = native_store_tr())
+-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+-
+-#define load_TLS(t, cpu) native_load_tls(t, cpu)
+-#define set_ldt native_set_ldt
+-
+-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+-
+-static inline void write_dt_entry(struct desc_struct *dt,
+-				  int entry, u32 entry_low, u32 entry_high)
+-{
+-	dt[entry].a = entry_low;
+-	dt[entry].b = entry_high;
+-}
+-
+-static inline void native_set_ldt(const void *addr, unsigned int entries)
+-{
+-	if (likely(entries == 0))
+-		__asm__ __volatile__("lldt %w0"::"q" (0));
+-	else {
+-		unsigned cpu = smp_processor_id();
+-		__u32 a, b;
+-
+-		pack_descriptor(&a, &b, (unsigned long)addr,
+-				entries * sizeof(struct desc_struct) - 1,
+-				DESCTYPE_LDT, 0);
+-		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+-		__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+-	}
+-}
+-
+-
+-static inline void native_load_tr_desc(void)
+-{
+-	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+-}
+-
+-static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+-{
+-	asm volatile("lgdt %0"::"m" (*dtr));
+-}
+-
+-static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+-{
+-	asm volatile("lidt %0"::"m" (*dtr));
+-}
+-
+-static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+-{
+-	asm ("sgdt %0":"=m" (*dtr));
+-}
+-
+-static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+-{
+-	asm ("sidt %0":"=m" (*dtr));
+-}
+-
+-static inline unsigned long native_store_tr(void)
+-{
+-	unsigned long tr;
+-	asm ("str %0":"=r" (tr));
+-	return tr;
+-}
+-
+-static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+-{
+-	unsigned int i;
+-	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+-
+-	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+-		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+-}
+-#else
+-#define load_TLS(t, cpu) xen_load_tls(t, cpu)
+-#define set_ldt xen_set_ldt
+-
+-extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
+-extern int write_gdt_entry(void *gdt, int entry, __u32 entry_a, __u32 entry_b);
+-
+-static inline void xen_load_tls(struct thread_struct *t, unsigned int cpu)
+-{
+-	unsigned int i;
+-	struct desc_struct *gdt = get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN;
+-
+-	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+-		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
+-						 *(u64 *)&t->tls_array[i]))
+-			BUG();
+-}
+-#endif
+-
+-#ifndef CONFIG_X86_NO_IDT
+-static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
+-{
+-	__u32 a, b;
+-	pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
+-	write_idt_entry(idt_table, gate, a, b);
+-}
+-#endif
+-
+-#ifndef CONFIG_X86_NO_TSS
+-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
+-{
+-	__u32 a, b;
+-	pack_descriptor(&a, &b, (unsigned long)addr,
+-			offsetof(struct tss_struct, __cacheline_filler) - 1,
+-			DESCTYPE_TSS, 0);
+-	write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
+-}
+-#endif
+-
+-
+-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+-
+-#define LDT_entry_a(info) \
+-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+-
+-#define LDT_entry_b(info) \
+-	(((info)->base_addr & 0xff000000) | \
+-	(((info)->base_addr & 0x00ff0000) >> 16) | \
+-	((info)->limit & 0xf0000) | \
+-	(((info)->read_exec_only ^ 1) << 9) | \
+-	((info)->contents << 10) | \
+-	(((info)->seg_not_present ^ 1) << 15) | \
+-	((info)->seg_32bit << 22) | \
+-	((info)->limit_in_pages << 23) | \
+-	((info)->useable << 20) | \
+-	0x7000)
+-
+-#define LDT_empty(info) (\
+-	(info)->base_addr	== 0	&& \
+-	(info)->limit		== 0	&& \
+-	(info)->contents	== 0	&& \
+-	(info)->read_exec_only	== 1	&& \
+-	(info)->seg_32bit	== 0	&& \
+-	(info)->limit_in_pages	== 0	&& \
+-	(info)->seg_not_present	== 1	&& \
+-	(info)->useable		== 0	)
+-
+-static inline void clear_LDT(void)
+-{
+-	set_ldt(NULL, 0);
+-}
+-
+-/*
+- * load one particular LDT into the current CPU
+- */
+-static inline void load_LDT_nolock(mm_context_t *pc)
+-{
+-	set_ldt(pc->ldt, pc->size);
+-}
+-
+-static inline void load_LDT(mm_context_t *pc)
+-{
+-	preempt_disable();
+-	load_LDT_nolock(pc);
+-	preempt_enable();
+-}
+-
+-static inline unsigned long get_desc_base(unsigned long *desc)
+-{
+-	unsigned long base;
+-	base = ((desc[0] >> 16)  & 0x0000ffff) |
+-		((desc[1] << 16) & 0x00ff0000) |
+-		(desc[1] & 0xff000000);
+-	return base;
+-}
+-
+-#else /* __ASSEMBLY__ */
+-
+-/*
+- * GET_DESC_BASE reads the descriptor base of the specified segment.
+- *
+- * Args:
+- *    idx - descriptor index
+- *    gdt - GDT pointer
+- *    base - 32bit register to which the base will be written
+- *    lo_w - lo word of the "base" register
+- *    lo_b - lo byte of the "base" register
+- *    hi_b - hi byte of the low word of the "base" register
+- *
+- * Example:
+- *    GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+- *    Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+- */
+-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+-	movb idx*8+4(gdt), lo_b; \
+-	movb idx*8+7(gdt), hi_b; \
+-	shll $16, base; \
+-	movw idx*8+2(gdt), lo_w;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,228 +0,0 @@
+-/* Written 2000 by Andi Kleen */ 
+-#ifndef __ARCH_DESC_H
+-#define __ARCH_DESC_H
+-
+-#include <linux/threads.h>
+-#include <asm/ldt.h>
+-
+-#ifndef __ASSEMBLY__
+-
+-#include <linux/string.h>
+-#include <linux/smp.h>
+-#include <asm/desc_defs.h>
+-
+-#include <asm/segment.h>
+-#include <asm/mmu.h>
+-
+-extern struct desc_ptr idt_descr, cpu_gdt_descr[NR_CPUS];
+-
+-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+-
+-#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
+-#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
+-
+-static inline void clear_LDT(void)
+-{
+-	int cpu = get_cpu();
+-
+-	/*
+-	 * NB. We load the default_ldt for lcall7/27 handling on demand, as
+-	 * it slows down context switching. Noone uses it anyway.
+-	 */
+-	cpu = cpu;              /* XXX avoid compiler warning */
+-	xen_set_ldt(NULL, 0);
+-	put_cpu();
+-}
+-
+-#ifndef CONFIG_X86_NO_TSS
+-static inline unsigned long __store_tr(void)
+-{
+-       unsigned long tr;
+-
+-       asm volatile ("str %w0":"=r" (tr));
+-       return tr;
+-}
+-
+-#define store_tr(tr) (tr) = __store_tr()
+-#endif
+-
+-/*
+- * This is the ldt that every process will get unless we need
+- * something other than this.
+- */
+-extern struct desc_struct default_ldt[];
+-#ifndef CONFIG_X86_NO_IDT
+-extern struct gate_struct idt_table[]; 
+-#endif
+-extern struct desc_ptr cpu_gdt_descr[];
+-
+-/* the cpu gdt accessor */
+-#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+-
+-#ifndef CONFIG_XEN
+-static inline void load_gdt(const struct desc_ptr *ptr)
+-{
+-	asm volatile("lgdt %w0"::"m" (*ptr));
+-}
+-
+-static inline void store_gdt(struct desc_ptr *ptr)
+-{
+-       asm("sgdt %w0":"=m" (*ptr));
+-}
+-#endif
+-
+-static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)  
+-{
+-	struct gate_struct s; 	
+-	s.offset_low = PTR_LOW(func); 
+-	s.segment = __KERNEL_CS;
+-	s.ist = ist; 
+-	s.p = 1;
+-	s.dpl = dpl; 
+-	s.zero0 = 0;
+-	s.zero1 = 0; 
+-	s.type = type; 
+-	s.offset_middle = PTR_MIDDLE(func); 
+-	s.offset_high = PTR_HIGH(func); 
+-	/* does not need to be atomic because it is only done once at setup time */ 
+-	memcpy(adr, &s, 16); 
+-} 
+-
+-#ifndef CONFIG_X86_NO_IDT
+-static inline void set_intr_gate(int nr, void *func) 
+-{ 
+-	BUG_ON((unsigned)nr > 0xFF);
+-	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0); 
+-} 
+-
+-static inline void set_intr_gate_ist(int nr, void *func, unsigned ist) 
+-{ 
+-	BUG_ON((unsigned)nr > 0xFF);
+-	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist); 
+-} 
+-
+-static inline void set_system_gate(int nr, void *func) 
+-{ 
+-	BUG_ON((unsigned)nr > 0xFF);
+-	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0); 
+-} 
+-
+-static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
+-{
+-	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
+-}
+-
+-static inline void load_idt(const struct desc_ptr *ptr)
+-{
+-	asm volatile("lidt %w0"::"m" (*ptr));
+-}
+-
+-static inline void store_idt(struct desc_ptr *dtr)
+-{
+-       asm("sidt %w0":"=m" (*dtr));
+-}
+-#endif
+-
+-static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
+-					 unsigned size) 
+-{ 
+-	struct ldttss_desc d;
+-	memset(&d,0,sizeof(d)); 
+-	d.limit0 = size & 0xFFFF;
+-	d.base0 = PTR_LOW(tss); 
+-	d.base1 = PTR_MIDDLE(tss) & 0xFF; 
+-	d.type = type;
+-	d.p = 1; 
+-	d.limit1 = (size >> 16) & 0xF;
+-	d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF; 
+-	d.base3 = PTR_HIGH(tss); 
+-	memcpy(ptr, &d, 16); 
+-}
+-
+-#ifndef CONFIG_X86_NO_TSS
+-static inline void set_tss_desc(unsigned cpu, void *addr)
+-{ 
+-	/*
+-	 * sizeof(unsigned long) coming from an extra "long" at the end
+-	 * of the iobitmap. See tss_struct definition in processor.h
+-	 *
+-	 * -1? seg base+limit should be pointing to the address of the
+-	 * last valid byte
+-	 */
+-	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS], 
+-		(unsigned long)addr, DESC_TSS,
+-		IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
+-} 
+-#endif
+-
+-static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
+-{ 
+-	set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
+-			      DESC_LDT, size * 8 - 1);
+-}
+-
+-#define LDT_entry_a(info) \
+-	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+-/* Don't allow setting of the lm bit. It is useless anyways because 
+-   64bit system calls require __USER_CS. */ 
+-#define LDT_entry_b(info) \
+-	(((info)->base_addr & 0xff000000) | \
+-	(((info)->base_addr & 0x00ff0000) >> 16) | \
+-	((info)->limit & 0xf0000) | \
+-	(((info)->read_exec_only ^ 1) << 9) | \
+-	((info)->contents << 10) | \
+-	(((info)->seg_not_present ^ 1) << 15) | \
+-	((info)->seg_32bit << 22) | \
+-	((info)->limit_in_pages << 23) | \
+-	((info)->useable << 20) | \
+-	/* ((info)->lm << 21) | */ \
+-	0x7000)
+-
+-#define LDT_empty(info) (\
+-	(info)->base_addr	== 0	&& \
+-	(info)->limit		== 0	&& \
+-	(info)->contents	== 0	&& \
+-	(info)->read_exec_only	== 1	&& \
+-	(info)->seg_32bit	== 0	&& \
+-	(info)->limit_in_pages	== 0	&& \
+-	(info)->seg_not_present	== 1	&& \
+-	(info)->useable		== 0	&& \
+-	(info)->lm		== 0)
+-
+-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
+-{
+-	unsigned int i;
+-	u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
+-
+-	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+-		if (HYPERVISOR_update_descriptor(virt_to_machine(&gdt[i]),
+-						 t->tls_array[i]))
+-			BUG();
+-} 
+-
+-/*
+- * load one particular LDT into the current CPU
+- */
+-static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
+-{
+-	void *segments = pc->ldt;
+-	int count = pc->size;
+-
+-	if (likely(!count))
+-		segments = NULL;
+-
+-	xen_set_ldt(segments, count);
+-}
+-
+-static inline void load_LDT(mm_context_t *pc)
+-{
+-	int cpu = get_cpu();
+-	load_LDT_nolock(pc, cpu);
+-	put_cpu();
+-}
+-
+-extern struct desc_ptr idt_descr;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:25.000000000 +0100
+@@ -64,7 +64,7 @@ enum fixed_addresses {
+ #endif
+ #ifdef CONFIG_X86_VISWS_APIC
+ 	FIX_CO_CPU,	/* Cobalt timer */
+-	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */ 
++	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
+ 	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
+ 	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
+ #endif
+@@ -73,7 +73,7 @@ enum fixed_addresses {
+ #endif
+ #ifdef CONFIG_X86_CYCLONE_TIMER
+ 	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+-#endif 
++#endif
+ #ifdef CONFIG_HIGHMEM
+ 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+ 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+@@ -93,11 +93,23 @@ enum fixed_addresses {
+ 	FIX_ISAMAP_END,
+ 	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ 	__end_of_permanent_fixed_addresses,
+-	/* temporary boot-time mappings, used before ioremap() is functional */
+-#define NR_FIX_BTMAPS	16
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
++	/*
++	 * 256 temporary boot-time mappings, used by early_ioremap(),
++	 * before ioremap() is functional.
++	 *
++	 * We round it up to the next 512 pages boundary so that we
++	 * can have a single pgd entry and a single pte table:
++	 */
++#define NR_FIX_BTMAPS		64
++#define FIX_BTMAPS_NESTING	4
++	FIX_BTMAP_END =
++		__end_of_permanent_fixed_addresses + 512 -
++			(__end_of_permanent_fixed_addresses & 511),
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
+ 	FIX_WP_TEST,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
+ 	__end_of_fixed_addresses
+ };
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+ #include <asm/vsyscall.h>
++#include <asm/efi.h>
+ #include <asm/acpi.h>
+ 
+ /*
+@@ -46,6 +47,10 @@ enum fixed_addresses {
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
+ #endif
++#ifdef CONFIG_EFI
++	FIX_EFI_IO_MAP_LAST_PAGE,
++	FIX_EFI_IO_MAP_FIRST_PAGE = FIX_EFI_IO_MAP_LAST_PAGE+MAX_EFI_IO_PAGES-1,
++#endif
+ #ifdef CONFIG_ACPI
+ 	FIX_ACPI_BEGIN,
+ 	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+@@ -55,10 +60,22 @@ enum fixed_addresses {
+ 	FIX_ISAMAP_END,
+ 	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ 	__end_of_permanent_fixed_addresses,
+-	/* temporary boot-time mappings, used before ioremap() is functional */
+-#define NR_FIX_BTMAPS	16
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
++	/*
++	 * 256 temporary boot-time mappings, used by early_ioremap(),
++	 * before ioremap() is functional.
++	 *
++	 * We round it up to the next 512 pages boundary so that we
++	 * can have a single pgd entry and a single pte table:
++	 */
++#define NR_FIX_BTMAPS		64
++#define FIX_BTMAPS_NESTING	4
++	FIX_BTMAP_END =
++		__end_of_permanent_fixed_addresses + 512 -
++			(__end_of_permanent_fixed_addresses & 511),
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
+ 	__end_of_fixed_addresses
+ };
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:25.000000000 +0100
+@@ -37,11 +37,6 @@ extern pte_t *pkmap_page_table;
+  * easily, subsequent pte tables have to be allocated in one physical
+  * chunk of RAM.
+  */
+-#ifdef CONFIG_X86_PAE
+-#define LAST_PKMAP 512
+-#else
+-#define LAST_PKMAP 1024
+-#endif
+ /*
+  * Ordering is:
+  *
+@@ -57,13 +52,12 @@ extern pte_t *pkmap_page_table;
+  * VMALLOC_START
+  * high_memory
+  */
+-#define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK )
+ #define LAST_PKMAP_MASK (LAST_PKMAP-1)
+ #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+ #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+ 
+-extern void * FASTCALL(kmap_high(struct page *page));
+-extern void FASTCALL(kunmap_high(struct page *page));
++extern void *kmap_high(struct page *page);
++extern void kunmap_high(struct page *page);
+ 
+ void *kmap(struct page *page);
+ void kunmap(struct page *page);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:32:11.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:32:34.000000000 +0100
+@@ -271,6 +271,25 @@ HYPERVISOR_poll(
+ 	return rc;
+ }
+ 
++static inline int __must_check
++HYPERVISOR_poll_no_timeout(
++	evtchn_port_t *ports, unsigned int nr_ports)
++{
++	int rc;
++	struct sched_poll sched_poll = {
++		.nr_ports = nr_ports
++	};
++	set_xen_guest_handle(sched_poll.ports, ports);
++
++	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
++#endif
++
++	return rc;
++}
++
+ #ifdef CONFIG_XEN
+ 
+ static inline void
+@@ -310,4 +329,6 @@ MULTI_grant_table_op(multicall_entry_t *
+ 
+ #endif
+ 
++#define uvm_multi(cpumask) ((unsigned long)cpus_addr(cpumask) | UVMF_MULTI)
++
+ #endif /* __HYPERVISOR_H__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,249 @@
+-#ifdef CONFIG_X86_32
+-# include "irqflags_32.h"
++#ifndef _X86_IRQFLAGS_H_
++#define _X86_IRQFLAGS_H_
++
++#include <asm/processor-flags.h>
++
++#ifndef __ASSEMBLY__
++/*
++ * The use of 'barrier' in the following reflects their use as local-lock
++ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
++ * critical operations are executed. All critical operations must complete
++ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
++ * includes these barriers, for example.
++ */
++
++#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask)
++
++#define xen_restore_fl(f)					\
++do {								\
++	vcpu_info_t *_vcpu;					\
++	barrier();						\
++	_vcpu = current_vcpu_info();				\
++	if ((_vcpu->evtchn_upcall_mask = (f)) == 0) {		\
++		barrier(); /* unmask then check (avoid races) */\
++		if (unlikely(_vcpu->evtchn_upcall_pending))	\
++			force_evtchn_callback();		\
++	}							\
++} while (0)
++
++#define xen_irq_disable()					\
++do {								\
++	current_vcpu_info()->evtchn_upcall_mask = 1;		\
++	barrier();						\
++} while (0)
++
++#define xen_irq_enable()					\
++do {								\
++	vcpu_info_t *_vcpu;					\
++	barrier();						\
++	_vcpu = current_vcpu_info();				\
++	_vcpu->evtchn_upcall_mask = 0;				\
++	barrier(); /* unmask then check (avoid races) */	\
++	if (unlikely(_vcpu->evtchn_upcall_pending))		\
++		force_evtchn_callback();			\
++} while (0)
++
++void xen_safe_halt(void);
++
++void xen_halt(void);
++
++#define __raw_local_save_flags() xen_save_fl()
++
++#define raw_local_irq_restore(flags) xen_restore_fl(flags)
++
++#define raw_local_irq_disable()	xen_irq_disable()
++
++#define raw_local_irq_enable() xen_irq_enable()
++
++/*
++ * Used in the idle loop; sti takes one instruction cycle
++ * to complete:
++ */
++static inline void raw_safe_halt(void)
++{
++	xen_safe_halt();
++}
++
++/*
++ * Used when interrupts are already enabled or to
++ * shutdown the processor:
++ */
++static inline void halt(void)
++{
++	xen_halt();
++}
++
++/*
++ * For spinlocks, etc:
++ */
++#define __raw_local_irq_save()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_local_irq_disable();					\
++									\
++	flags;								\
++})
+ #else
+-# include "irqflags_64.h"
++
++/* Offsets into shared_info_t. */
++#define evtchn_upcall_pending		/* 0 */
++#define evtchn_upcall_mask		1
++
++#define sizeof_vcpu_shift		6
++
++#ifdef CONFIG_X86_64
++# define __REG_si %rsi
++# define __CPU_num %gs:pda_cpunumber
++#else
++# define __REG_si %esi
++# define __CPU_num TI_cpu(%ebp)
++#endif
++
++#ifdef CONFIG_SMP
++#define GET_VCPU_INFO		movl __CPU_num,%esi			; \
++				shl $sizeof_vcpu_shift,%esi		; \
++				add HYPERVISOR_shared_info,__REG_si
++#else
++#define GET_VCPU_INFO		mov HYPERVISOR_shared_info,__REG_si
++#endif
++
++#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(__REG_si)
++#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(__REG_si)
++#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(__REG_si)
++#define DISABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
++				__DISABLE_INTERRUPTS
++#define ENABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
++				__ENABLE_INTERRUPTS
++
++#ifndef CONFIG_X86_64
++#define INTERRUPT_RETURN		iret
++#define ENABLE_INTERRUPTS_SYSCALL_RET __ENABLE_INTERRUPTS		; \
++sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
++	__TEST_PENDING							; \
++	jnz  14f	/* process more events if necessary... */	; \
++	movl PT_ESI(%esp), %esi						; \
++	sysexit								; \
++14:	__DISABLE_INTERRUPTS						; \
++	TRACE_IRQS_OFF							; \
++sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
++	mov  $__KERNEL_PERCPU, %ecx					; \
++	push %esp							; \
++	mov  %ecx, %fs							; \
++	call evtchn_do_upcall						; \
++	add  $4,%esp							; \
++	jmp  ret_from_intr
++#endif
++
++
++#endif /* __ASSEMBLY__ */
++
++#ifndef __ASSEMBLY__
++#define raw_local_save_flags(flags) \
++		do { (flags) = __raw_local_save_flags(); } while (0)
++
++#define raw_local_irq_save(flags) \
++		do { (flags) = __raw_local_irq_save(); } while (0)
++
++static inline int raw_irqs_disabled_flags(unsigned long flags)
++{
++	return (flags != 0);
++}
++
++#define raw_irqs_disabled()						\
++({									\
++	unsigned long flags = __raw_local_save_flags();			\
++									\
++	raw_irqs_disabled_flags(flags);					\
++})
++
++/*
++ * makes the traced hardirq state match with the machine state
++ *
++ * should be a rarely used function, only in places where its
++ * otherwise impossible to know the irq state, like in traps.
++ */
++static inline void trace_hardirqs_fixup_flags(unsigned long flags)
++{
++	if (raw_irqs_disabled_flags(flags))
++		trace_hardirqs_off();
++	else
++		trace_hardirqs_on();
++}
++
++#define trace_hardirqs_fixup() \
++	trace_hardirqs_fixup_flags(__raw_local_save_flags())
++
++#else
++
++#ifdef CONFIG_X86_64
++/*
++ * Currently paravirt can't handle swapgs nicely when we
++ * don't have a stack we can rely on (such as a user space
++ * stack).  So we either find a way around these or just fault
++ * and emulate if a guest tries to call swapgs directly.
++ *
++ * Either way, this is a good way to document that we don't
++ * have a reliable stack. x86_64 only.
++ */
++#define SWAPGS_UNSAFE_STACK	swapgs
++#define ARCH_TRACE_IRQS_ON		call trace_hardirqs_on_thunk
++#define ARCH_TRACE_IRQS_OFF		call trace_hardirqs_off_thunk
++#define ARCH_LOCKDEP_SYS_EXIT		call lockdep_sys_exit_thunk
++#define ARCH_LOCKDEP_SYS_EXIT_IRQ	\
++	TRACE_IRQS_ON; \
++	ENABLE_INTERRUPTS(CLBR_NONE); \
++	SAVE_REST; \
++	LOCKDEP_SYS_EXIT; \
++	RESTORE_REST; \
++	__DISABLE_INTERRUPTS; \
++	TRACE_IRQS_OFF;
++
++#else
++#define ARCH_TRACE_IRQS_ON			\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call trace_hardirqs_on;			\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++
++#define ARCH_TRACE_IRQS_OFF			\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call trace_hardirqs_off;		\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++
++#define ARCH_LOCKDEP_SYS_EXIT			\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call lockdep_sys_exit;			\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++
++#define ARCH_LOCKDEP_SYS_EXIT_IRQ
++#endif
++
++#ifdef CONFIG_TRACE_IRQFLAGS
++#  define TRACE_IRQS_ON		ARCH_TRACE_IRQS_ON
++#  define TRACE_IRQS_OFF	ARCH_TRACE_IRQS_OFF
++#else
++#  define TRACE_IRQS_ON
++#  define TRACE_IRQS_OFF
++#endif
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++#  define LOCKDEP_SYS_EXIT	ARCH_LOCKDEP_SYS_EXIT
++#  define LOCKDEP_SYS_EXIT_IRQ	ARCH_LOCKDEP_SYS_EXIT_IRQ
++# else
++#  define LOCKDEP_SYS_EXIT
++#  define LOCKDEP_SYS_EXIT_IRQ
++# endif
++
++#endif /* __ASSEMBLY__ */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,214 +0,0 @@
+-/*
+- * include/asm-i386/irqflags.h
+- *
+- * IRQ flags handling
+- *
+- * This file gets included from lowlevel asm headers too, to provide
+- * wrapped versions of the local_irq_*() APIs, based on the
+- * raw_local_irq_*() functions from the lowlevel headers.
+- */
+-#ifndef _ASM_IRQFLAGS_H
+-#define _ASM_IRQFLAGS_H
+-
+-#ifndef __ASSEMBLY__
+-#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask)
+-
+-#define xen_restore_fl(f)					\
+-do {								\
+-	vcpu_info_t *_vcpu;					\
+-	barrier();						\
+-	_vcpu = current_vcpu_info();				\
+-	if ((_vcpu->evtchn_upcall_mask = (f)) == 0) {		\
+-		barrier(); /* unmask then check (avoid races) */\
+-		if (unlikely(_vcpu->evtchn_upcall_pending))	\
+-			force_evtchn_callback();		\
+-	}							\
+-} while (0)
+-
+-#define xen_irq_disable()					\
+-do {								\
+-	current_vcpu_info()->evtchn_upcall_mask = 1;		\
+-	barrier();						\
+-} while (0)
+-
+-#define xen_irq_enable()					\
+-do {								\
+-	vcpu_info_t *_vcpu;					\
+-	barrier();						\
+-	_vcpu = current_vcpu_info();				\
+-	_vcpu->evtchn_upcall_mask = 0;				\
+-	barrier(); /* unmask then check (avoid races) */	\
+-	if (unlikely(_vcpu->evtchn_upcall_pending))		\
+-		force_evtchn_callback();			\
+-} while (0)
+-
+-void xen_safe_halt(void);
+-
+-void xen_halt(void);
+-
+-/* 
+- * The use of 'barrier' in the following reflects their use as local-lock
+- * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+- * critical operations are executed. All critical operations must complete
+- * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+- * includes these barriers, for example.
+- */
+-
+-#define __raw_local_save_flags() xen_save_fl()
+-
+-#define raw_local_irq_restore(flags) xen_restore_fl(flags)
+-
+-#define raw_local_irq_disable()	xen_irq_disable()
+-
+-#define raw_local_irq_enable() xen_irq_enable()
+-
+-/*
+- * Used in the idle loop; sti takes one instruction cycle
+- * to complete:
+- */
+-static inline void raw_safe_halt(void)
+-{
+-	xen_safe_halt();
+-}
+-
+-/*
+- * Used when interrupts are already enabled or to
+- * shutdown the processor:
+- */
+-static inline void halt(void)
+-{
+-	xen_halt();
+-}
+-
+-/*
+- * For spinlocks, etc:
+- */
+-#define __raw_local_irq_save()						\
+-({									\
+-	unsigned long flags = __raw_local_save_flags();			\
+-									\
+-	raw_local_irq_disable();					\
+-									\
+-	flags;								\
+-})
+-
+-#else
+-/* Offsets into shared_info_t. */
+-#define evtchn_upcall_pending		/* 0 */
+-#define evtchn_upcall_mask		1
+-
+-#define sizeof_vcpu_shift		6
+-
+-#ifdef CONFIG_SMP
+-#define GET_VCPU_INFO		movl TI_cpu(%ebp),%esi			; \
+-				shl  $sizeof_vcpu_shift,%esi		; \
+-				addl HYPERVISOR_shared_info,%esi
+-#else
+-#define GET_VCPU_INFO		movl HYPERVISOR_shared_info,%esi
+-#endif
+-
+-#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(%esi)
+-#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(%esi)
+-#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(%esi)
+-#define DISABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
+-				__DISABLE_INTERRUPTS
+-#define ENABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
+-				__ENABLE_INTERRUPTS
+-#define ENABLE_INTERRUPTS_SYSEXIT __ENABLE_INTERRUPTS			; \
+-sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
+-	__TEST_PENDING							; \
+-	jnz  14f	/* process more events if necessary... */	; \
+-	movl PT_ESI(%esp), %esi						; \
+-	sysexit								; \
+-14:	__DISABLE_INTERRUPTS						; \
+-	TRACE_IRQS_OFF							; \
+-sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+-	mov  $__KERNEL_PERCPU, %ecx					; \
+-	push %esp							; \
+-	mov  %ecx, %fs							; \
+-	call evtchn_do_upcall						; \
+-	add  $4,%esp							; \
+-	jmp  ret_from_intr
+-#define INTERRUPT_RETURN	iret
+-#endif /* __ASSEMBLY__ */
+-
+-#ifndef __ASSEMBLY__
+-#define raw_local_save_flags(flags) \
+-		do { (flags) = __raw_local_save_flags(); } while (0)
+-
+-#define raw_local_irq_save(flags) \
+-		do { (flags) = __raw_local_irq_save(); } while (0)
+-
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+-	return (flags != 0);
+-}
+-
+-#define raw_irqs_disabled()						\
+-({									\
+-	unsigned long flags = __raw_local_save_flags();			\
+-									\
+-	raw_irqs_disabled_flags(flags);					\
+-})
+-
+-/*
+- * makes the traced hardirq state match with the machine state
+- *
+- * should be a rarely used function, only in places where its
+- * otherwise impossible to know the irq state, like in traps.
+- */
+-static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+-{
+-	if (raw_irqs_disabled_flags(flags))
+-		trace_hardirqs_off();
+-	else
+-		trace_hardirqs_on();
+-}
+-
+-#define trace_hardirqs_fixup() \
+-	trace_hardirqs_fixup_flags(__raw_local_save_flags())
+-#endif /* __ASSEMBLY__ */
+-
+-/*
+- * Do the CPU's IRQ-state tracing from assembly code. We call a
+- * C function, so save all the C-clobbered registers:
+- */
+-#ifdef CONFIG_TRACE_IRQFLAGS
+-
+-# define TRACE_IRQS_ON				\
+-	pushl %eax;				\
+-	pushl %ecx;				\
+-	pushl %edx;				\
+-	call trace_hardirqs_on;			\
+-	popl %edx;				\
+-	popl %ecx;				\
+-	popl %eax;
+-
+-# define TRACE_IRQS_OFF				\
+-	pushl %eax;				\
+-	pushl %ecx;				\
+-	pushl %edx;				\
+-	call trace_hardirqs_off;		\
+-	popl %edx;				\
+-	popl %ecx;				\
+-	popl %eax;
+-
+-#else
+-# define TRACE_IRQS_ON
+-# define TRACE_IRQS_OFF
+-#endif
+-
+-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+-# define LOCKDEP_SYS_EXIT			\
+-	pushl %eax;				\
+-	pushl %ecx;				\
+-	pushl %edx;				\
+-	call lockdep_sys_exit;			\
+-	popl %edx;				\
+-	popl %ecx;				\
+-	popl %eax;
+-#else
+-# define LOCKDEP_SYS_EXIT
+-#endif
+-
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_64.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,178 +0,0 @@
+-/*
+- * include/asm-x86_64/irqflags.h
+- *
+- * IRQ flags handling
+- *
+- * This file gets included from lowlevel asm headers too, to provide
+- * wrapped versions of the local_irq_*() APIs, based on the
+- * raw_local_irq_*() functions from the lowlevel headers.
+- */
+-#ifndef _ASM_IRQFLAGS_H
+-#define _ASM_IRQFLAGS_H
+-#include <asm/processor-flags.h>
+-
+-#ifndef __ASSEMBLY__
+-/*
+- * Interrupt control:
+- */
+-
+-/*
+- * The use of 'barrier' in the following reflects their use as local-lock
+- * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+- * critical operations are executed. All critical operations must complete
+- * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+- * includes these barriers, for example.
+- */
+-
+-#define __raw_local_save_flags() (current_vcpu_info()->evtchn_upcall_mask)
+-
+-#define raw_local_save_flags(flags) \
+-		do { (flags) = __raw_local_save_flags(); } while (0)
+-
+-#define raw_local_irq_restore(x)					\
+-do {									\
+-	vcpu_info_t *_vcpu;						\
+-	barrier();							\
+-	_vcpu = current_vcpu_info();		\
+-	if ((_vcpu->evtchn_upcall_mask = (x)) == 0) {			\
+-		barrier(); /* unmask then check (avoid races) */	\
+-		if ( unlikely(_vcpu->evtchn_upcall_pending) )		\
+-			force_evtchn_callback();			\
+-	}								\
+-} while (0)
+-
+-#ifdef CONFIG_X86_VSMP
+-
+-/*
+- * Interrupt control for the VSMP architecture:
+- */
+-
+-static inline void raw_local_irq_disable(void)
+-{
+-	unsigned long flags = __raw_local_save_flags();
+-
+-	raw_local_irq_restore((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+-}
+-
+-static inline void raw_local_irq_enable(void)
+-{
+-	unsigned long flags = __raw_local_save_flags();
+-
+-	raw_local_irq_restore((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
+-}
+-
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+-	return !(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC);
+-}
+-
+-#else /* CONFIG_X86_VSMP */
+-
+-#define raw_local_irq_disable()						\
+-do {									\
+-	current_vcpu_info()->evtchn_upcall_mask = 1;					\
+-	barrier();							\
+-} while (0)
+-
+-#define raw_local_irq_enable()						\
+-do {									\
+-	vcpu_info_t *_vcpu;						\
+-	barrier();							\
+-	_vcpu = current_vcpu_info();		\
+-	_vcpu->evtchn_upcall_mask = 0;					\
+-	barrier(); /* unmask then check (avoid races) */		\
+-	if ( unlikely(_vcpu->evtchn_upcall_pending) )			\
+-		force_evtchn_callback();				\
+-} while (0)
+-
+-static inline int raw_irqs_disabled_flags(unsigned long flags)
+-{
+-	return (flags != 0);
+-}
+-
+-#endif
+-
+-/*
+- * For spinlocks, etc.:
+- */
+-
+-#define __raw_local_irq_save()						\
+-({									\
+-	unsigned long flags = __raw_local_save_flags();			\
+-									\
+-	raw_local_irq_disable();					\
+-									\
+-	flags;								\
+-})
+-
+-#define raw_local_irq_save(flags) \
+-		do { (flags) = __raw_local_irq_save(); } while (0)
+-
+-#define raw_irqs_disabled()						\
+-({									\
+-	unsigned long flags = __raw_local_save_flags();			\
+-									\
+-	raw_irqs_disabled_flags(flags);					\
+-})
+-
+-/*
+- * makes the traced hardirq state match with the machine state
+- *
+- * should be a rarely used function, only in places where its
+- * otherwise impossible to know the irq state, like in traps.
+- */
+-static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+-{
+-	if (raw_irqs_disabled_flags(flags))
+-		trace_hardirqs_off();
+-	else
+-		trace_hardirqs_on();
+-}
+-
+-#define trace_hardirqs_fixup() \
+-	trace_hardirqs_fixup_flags(__raw_local_save_flags())
+-/*
+- * Used in the idle loop; sti takes one instruction cycle
+- * to complete:
+- */
+-void xen_safe_halt(void);
+-static inline void raw_safe_halt(void)
+-{
+-	xen_safe_halt();
+-}
+-
+-/*
+- * Used when interrupts are already enabled or to
+- * shutdown the processor:
+- */
+-void xen_halt(void);
+-static inline void halt(void)
+-{
+-	xen_halt();
+-}
+-
+-#else /* __ASSEMBLY__: */
+-# ifdef CONFIG_TRACE_IRQFLAGS
+-#  define TRACE_IRQS_ON		call trace_hardirqs_on_thunk
+-#  define TRACE_IRQS_OFF	call trace_hardirqs_off_thunk
+-# else
+-#  define TRACE_IRQS_ON
+-#  define TRACE_IRQS_OFF
+-# endif
+-# ifdef CONFIG_DEBUG_LOCK_ALLOC
+-#  define LOCKDEP_SYS_EXIT	call lockdep_sys_exit_thunk
+-#  define LOCKDEP_SYS_EXIT_IRQ	\
+-	TRACE_IRQS_ON; \
+-	sti; \
+-	SAVE_REST; \
+-	LOCKDEP_SYS_EXIT; \
+-	RESTORE_REST; \
+-	cli; \
+-	TRACE_IRQS_OFF;
+-# else
+-#  define LOCKDEP_SYS_EXIT
+-#  define LOCKDEP_SYS_EXIT_IRQ
+-# endif
+-#endif
+-
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/maddr_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr_32.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,6 +1,7 @@
+ #ifndef _I386_MADDR_H
+ #define _I386_MADDR_H
+ 
++#include <asm/bug.h>
+ #include <xen/features.h>
+ #include <xen/interface/xen.h>
+ 
+@@ -151,25 +152,9 @@ static inline paddr_t pte_machine_to_phy
+ 	phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
+ 	return phys;
+ }
+-#endif
+-
+-#ifdef CONFIG_X86_PAE
+-#define __pte_ma(x)	((pte_t) { (x), (maddr_t)(x) >> 32 } )
+-extern unsigned long long __supported_pte_mask;
+-static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+-{
+-	pte_t pte;
+-
+-	pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \
+-					(pgprot_val(pgprot) >> 32);
+-	pte.pte_high &= (__supported_pte_mask >> 32);
+-	pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \
+-							__supported_pte_mask;
+-	return pte;
+-}
+ #else
+-#define __pte_ma(x)	((pte_t) { (x) } )
+-#define pfn_pte_ma(pfn, prot)	__pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
++#define pte_phys_to_machine phys_to_machine
++#define pte_machine_to_phys machine_to_phys
+ #endif
+ 
+ #else /* !CONFIG_XEN */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/maddr_64.h	2007-06-12 13:14:13.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,6 +1,7 @@
+ #ifndef _X86_64_MADDR_H
+ #define _X86_64_MADDR_H
+ 
++#include <asm/bug.h>
+ #include <xen/features.h>
+ #include <xen/interface/xen.h>
+ 
+@@ -16,6 +17,7 @@ typedef unsigned long maddr_t;
+ #ifdef CONFIG_XEN
+ 
+ extern unsigned long *phys_to_machine_mapping;
++extern unsigned long  max_mapnr;
+ 
+ #undef machine_to_phys_mapping
+ extern unsigned long *machine_to_phys_mapping;
+@@ -25,7 +27,7 @@ static inline unsigned long pfn_to_mfn(u
+ {
+ 	if (xen_feature(XENFEAT_auto_translated_physmap))
+ 		return pfn;
+-	BUG_ON(end_pfn && pfn >= end_pfn);
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
+ 	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
+ }
+ 
+@@ -33,7 +35,7 @@ static inline int phys_to_machine_mappin
+ {
+ 	if (xen_feature(XENFEAT_auto_translated_physmap))
+ 		return 1;
+-	BUG_ON(end_pfn && pfn >= end_pfn);
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
+ 	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+ }
+ 
+@@ -45,7 +47,7 @@ static inline unsigned long mfn_to_pfn(u
+ 		return mfn;
+ 
+ 	if (unlikely((mfn >> machine_to_phys_order) != 0))
+-		return end_pfn;
++		return max_mapnr;
+ 
+ 	/* The array access can fail (e.g., device space beyond end of RAM). */
+ 	asm (
+@@ -60,7 +62,7 @@ static inline unsigned long mfn_to_pfn(u
+ 		"	.quad 1b,3b\n"
+ 		".previous"
+ 		: "=r" (pfn)
+-		: "m" (machine_to_phys_mapping[mfn]), "m" (end_pfn) );
++		: "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
+ 
+ 	return pfn;
+ }
+@@ -88,16 +90,16 @@ static inline unsigned long mfn_to_pfn(u
+ static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+ {
+ 	unsigned long pfn = mfn_to_pfn(mfn);
+-	if ((pfn < end_pfn)
++	if ((pfn < max_mapnr)
+ 	    && !xen_feature(XENFEAT_auto_translated_physmap)
+ 	    && (phys_to_machine_mapping[pfn] != mfn))
+-		return end_pfn; /* force !pfn_valid() */
++		return max_mapnr; /* force !pfn_valid() */
+ 	return pfn;
+ }
+ 
+ static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+ {
+-	BUG_ON(end_pfn && pfn >= end_pfn);
++	BUG_ON(max_mapnr && pfn >= max_mapnr);
+ 	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ 		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ 		return;
+@@ -135,9 +137,6 @@ static inline paddr_t pte_machine_to_phy
+ 	return phys;
+ }
+ 
+-#define __pte_ma(x)     ((pte_t) { (x) } )
+-#define pfn_pte_ma(pfn, prot)	__pte_ma((((pfn) << PAGE_SHIFT) | pgprot_val(prot)) & __supported_pte_mask)
+-
+ #else /* !CONFIG_XEN */
+ 
+ #define pfn_to_mfn(pfn) (pfn)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:25.000000000 +0100
+@@ -51,8 +51,6 @@ static inline void __prepare_arch_switch
+ 		: : "r" (0) );
+ }
+ 
+-void leave_mm(unsigned long cpu);
+-
+ static inline void switch_mm(struct mm_struct *prev,
+ 			     struct mm_struct *next,
+ 			     struct task_struct *tsk)
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -62,12 +62,6 @@ extern void mm_pin(struct mm_struct *mm)
+ extern void mm_unpin(struct mm_struct *mm);
+ void mm_pin_all(void);
+ 
+-static inline void load_cr3(pgd_t *pgd)
+-{
+-	asm volatile("movq %0,%%cr3" :: "r" (phys_to_machine(__pa(pgd))) :
+-		     "memory");
+-}
+-
+ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
+ 			     struct task_struct *tsk)
+ {
+@@ -97,7 +91,7 @@ static inline void switch_mm(struct mm_s
+ 		op++;
+ 		
+ 		if (unlikely(next->context.ldt != prev->context.ldt)) {
+-			/* load_LDT_nolock(&next->context, cpu) */
++			/* load_LDT_nolock(&next->context) */
+ 			op->cmd = MMUEXT_SET_LDT;
+ 			op->arg1.linear_addr = (unsigned long)next->context.ldt;
+ 			op->arg2.nr_ents     = next->context.size;
+@@ -110,7 +104,7 @@ static inline void switch_mm(struct mm_s
+ 	else {
+ 		write_pda(mmu_state, TLBSTATE_OK);
+ 		if (read_pda(active_mm) != next)
+-			out_of_line_bug();
++			BUG();
+ 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+ 			/* We were in lazy tlb mode and leave_mm disabled 
+ 			 * tlb flush IPI delivery. We must reload CR3
+@@ -118,7 +112,7 @@ static inline void switch_mm(struct mm_s
+ 			 */
+                         load_cr3(next->pgd);
+                         xen_new_user_pt(__pa(__user_pgd(next->pgd)));		
+-			load_LDT_nolock(&next->context, cpu);
++			load_LDT_nolock(&next->context);
+ 		}
+ 	}
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:25.000000000 +0100
+@@ -71,6 +71,7 @@ extern int pci_mmap_page_range(struct pc
+ 
+ 
+ #ifdef CONFIG_PCI
++extern void early_quirks(void);
+ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+ 					enum pci_dma_burst_strategy *strat,
+ 					unsigned long *strategy_parameter)
+@@ -78,9 +79,10 @@ static inline void pci_dma_burst_advice(
+ 	*strat = PCI_DMA_BURST_INFINITY;
+ 	*strategy_parameter = ~0UL;
+ }
++#else
++static inline void early_quirks(void) { }
+ #endif
+ 
+-
+ #endif  /* __KERNEL__ */
+ 
+ #ifdef CONFIG_X86_32
+@@ -95,6 +97,19 @@ static inline void pci_dma_burst_advice(
+ /* generic pci stuff */
+ #include <asm-generic/pci.h>
+ 
++#ifdef CONFIG_NUMA
++/* Returns the node based on pci bus */
++static inline int __pcibus_to_node(struct pci_bus *bus)
++{
++	struct pci_sysdata *sd = bus->sysdata;
++
++	return sd->node;
++}
+ 
++static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus)
++{
++	return node_to_cpumask(__pcibus_to_node(bus));
++}
++#endif
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:51:25.000000000 +0100
+@@ -3,69 +3,109 @@
+ 
+ #include <linux/threads.h>
+ #include <linux/mm.h>		/* for struct page */
++#include <linux/pagemap.h>
++#include <asm/tlb.h>
++#include <asm-generic/tlb.h>
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+ 
+ #define paravirt_alloc_pt(mm, pfn) do { } while (0)
+-#define paravirt_alloc_pd(pfn) do { } while (0)
+-#define paravirt_alloc_pd(pfn) do { } while (0)
++#define paravirt_alloc_pd(mm, pfn) do { } while (0)
+ #define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+ #define paravirt_release_pt(pfn) do { } while (0)
+ #define paravirt_release_pd(pfn) do { } while (0)
+ 
+-#define pmd_populate_kernel(mm, pmd, pte)			\
+-do {								\
+-	paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);		\
+-	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));		\
+-} while (0)
+-
+-#define pmd_populate(mm, pmd, pte) 					\
+-do {									\
+-	unsigned long pfn = page_to_pfn(pte);				\
+-	paravirt_alloc_pt(mm, pfn);					\
+-	if (PagePinned(virt_to_page((mm)->pgd))) {			\
+-		if (!PageHighMem(pte))					\
+-			BUG_ON(HYPERVISOR_update_va_mapping(		\
+-			  (unsigned long)__va(pfn << PAGE_SHIFT),	\
+-			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));		\
+-		else if (!test_and_set_bit(PG_pinned, &pte->flags))	\
+-			kmap_flush_unused();				\
+-		set_pmd(pmd,						\
+-		        __pmd(_PAGE_TABLE + ((paddr_t)pfn << PAGE_SHIFT))); \
+-	} else							\
+-		*(pmd) = __pmd(_PAGE_TABLE + ((paddr_t)pfn << PAGE_SHIFT)); \
+-} while (0)
++static inline void pmd_populate_kernel(struct mm_struct *mm,
++				       pmd_t *pmd, pte_t *pte)
++{
++	paravirt_alloc_pt(mm, __pa(pte) >> PAGE_SHIFT);
++	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
++}
++
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
++{
++	unsigned long pfn = page_to_pfn(pte);
++
++	paravirt_alloc_pt(mm, pfn);
++	if (PagePinned(virt_to_page(mm->pgd))) {
++		if (!PageHighMem(pte))
++			BUG_ON(HYPERVISOR_update_va_mapping(
++			  (unsigned long)__va(pfn << PAGE_SHIFT),
++			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
++		else if (!test_and_set_bit(PG_pinned, &pte->flags))
++			kmap_flush_unused();
++		set_pmd(pmd, __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE));
++	} else
++		*pmd = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
++}
++#define pmd_pgtable(pmd) pmd_page(pmd)
+ 
+ /*
+  * Allocate and free page tables.
+  */
++extern void pgd_test_and_unpin(pgd_t *);
+ extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(pgd_t *pgd);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+-extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
++extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
+ 	free_page((unsigned long)pte);
+ }
+ 
+-extern void pte_free(struct page *pte);
++extern void __pte_free(pgtable_t);
++static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
++{
++	__pte_free(pte);
++}
++
+ 
+-#define __pte_free_tlb(tlb,pte) 					\
+-do {									\
+-	paravirt_release_pt(page_to_pfn(pte));				\
+-	tlb_remove_page((tlb),(pte));					\
+-} while (0)
++extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+ 
+ #ifdef CONFIG_X86_PAE
+ /*
+  * In the PAE case we free the pmds as part of the pgd.
+  */
+-#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(x)			do { } while (0)
+-#define __pmd_free_tlb(tlb,x)		do { } while (0)
+-#define pud_populate(mm, pmd, pte)	BUG()
+-#endif
++extern pmd_t *pmd_alloc_one(struct mm_struct *, unsigned long);
++
++extern void __pmd_free(pgtable_t);
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
++{
++	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
++	__pmd_free(virt_to_page(pmd));
++}
++
++extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
++
++static inline void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
++{
++	struct page *page = virt_to_page(pmd);
++	unsigned long pfn = page_to_pfn(page);
++
++	paravirt_alloc_pd(mm, pfn);
++
++	/* Note: almost everything apart from _PAGE_PRESENT is
++	   reserved at the pmd (PDPT) level. */
++	if (PagePinned(virt_to_page(mm->pgd))) {
++		BUG_ON(PageHighMem(page));
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			  (unsigned long)__va(pfn << PAGE_SHIFT),
++			  pfn_pte(pfn, PAGE_KERNEL_RO), 0));
++		set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
++	} else
++		*pudp = __pud(__pa(pmd) | _PAGE_PRESENT);
++
++	/*
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
++	 */
++	if (mm == current->active_mm)
++		xen_tlb_flush();
++}
++#endif	/* CONFIG_X86_PAE */
+ 
+ #endif /* _I386_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -6,30 +6,13 @@
+ #include <linux/mm.h>
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+ 
+-#include <xen/features.h>
+-void make_page_readonly(void *va, unsigned int feature);
+-void make_page_writable(void *va, unsigned int feature);
+-void make_pages_readonly(void *va, unsigned int nr, unsigned int feature);
+-void make_pages_writable(void *va, unsigned int nr, unsigned int feature);
++pmd_t *early_get_pmd(unsigned long va);
++void early_make_page_readonly(void *va, unsigned int feature);
+ 
+ #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+ 
+-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
+-{
+-	set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)));
+-}
+-
+-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+-{
+-	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)__va(page_to_pfn(pte) << PAGE_SHIFT),
+-			       pfn_pte(page_to_pfn(pte), PAGE_KERNEL_RO), 0));
+-		set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
+-	} else {
+-		*(pmd) = __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT));
+-	}
+-}
++#define pmd_populate_kernel(mm, pmd, pte) \
++		set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
+ 
+ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+ {
+@@ -63,53 +46,58 @@ static inline void pgd_populate(struct m
+ 	}
+ }
+ 
+-extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+-extern void pte_free(struct page *pte);
++#define pmd_pgtable(pmd) pmd_page(pmd)
+ 
+-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
++static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
+ {
+-	struct page *pg;
+-
+-	pg = pte_alloc_one(mm, addr);
+-	return pg ? page_address(pg) : NULL;
++	if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) {
++		BUG_ON(HYPERVISOR_update_va_mapping(
++			       (unsigned long)__va(page_to_pfn(pte) << PAGE_SHIFT),
++			       pfn_pte(page_to_pfn(pte), PAGE_KERNEL_RO), 0));
++		set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
++	} else {
++		*(pmd) = __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT));
++	}
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++extern void __pmd_free(pgtable_t);
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+-	pte_free(virt_to_page(pmd));
++	__pmd_free(virt_to_page(pmd));
+ }
+ 
++extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr);
++
+ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+ {
+-	struct page *pg;
+-
+-	pg = pte_alloc_one(mm, addr);
+-	return pg ? page_address(pg) : NULL;
++	return (pud_t *)pmd_alloc_one(mm, addr);
+ }
+ 
+-static inline void pud_free(pud_t *pud)
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+ {
+ 	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+-	pte_free(virt_to_page(pud));
++	__pmd_free(virt_to_page(pud));
+ }
+ 
+ static inline void pgd_list_add(pgd_t *pgd)
+ {
+ 	struct page *page = virt_to_page(pgd);
++	unsigned long flags;
+ 
+-	spin_lock(&pgd_lock);
++	spin_lock_irqsave(&pgd_lock, flags);
+ 	list_add(&page->lru, &pgd_list);
+-	spin_unlock(&pgd_lock);
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+ 
+ static inline void pgd_list_del(pgd_t *pgd)
+ {
+ 	struct page *page = virt_to_page(pgd);
++	unsigned long flags;
+ 
+-	spin_lock(&pgd_lock);
++	spin_lock_irqsave(&pgd_lock, flags);
+ 	list_del(&page->lru);
+-	spin_unlock(&pgd_lock);
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+ 
+ extern void pgd_test_and_unpin(pgd_t *);
+@@ -145,7 +133,7 @@ static inline pgd_t *pgd_alloc(struct mm
+ 	return pgd;
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	pgd_test_and_unpin(pgd);
+ 	pgd_list_del(pgd);
+@@ -161,17 +149,30 @@ static inline pte_t *pte_alloc_one_kerne
+ 	return pte;
+ }
+ 
++extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
++
+ /* Should really implement gc for free page table pages. This could be
+    done with a reference count in struct page. */
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+ 	make_page_writable(pte, XENFEAT_writable_page_tables);
+ 	free_page((unsigned long)pte); 
+ }
+ 
+-#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
++extern void __pte_free(pgtable_t);
++static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
++{
++	__pte_free(pte);
++}
++
++#define __pte_free_tlb(tlb,pte)				\
++do {							\
++	pgtable_page_dtor((pte));				\
++	tlb_remove_page((tlb), (pte));			\
++} while (0)
++
+ #define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+ #define __pud_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,467 @@
++#ifndef _ASM_X86_PGTABLE_H
++#define _ASM_X86_PGTABLE_H
++
++#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
++#define FIRST_USER_ADDRESS	0
++
++#define _PAGE_BIT_PRESENT	0
++#define _PAGE_BIT_RW		1
++#define _PAGE_BIT_USER		2
++#define _PAGE_BIT_PWT		3
++#define _PAGE_BIT_PCD		4
++#define _PAGE_BIT_ACCESSED	5
++#define _PAGE_BIT_DIRTY		6
++#define _PAGE_BIT_FILE		6
++#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
++#define _PAGE_BIT_PAT		7	/* on 4KB pages */
++#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
++#define _PAGE_BIT_IO		9	/* Mapped page is I/O or foreign and
++					 * has no associated page struct. */
++#define _PAGE_BIT_UNUSED2	10	/* available for programmer */
++#define _PAGE_BIT_UNUSED3	11
++#define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
++#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
++
++/*
++ * Note: we use _AC(1, L) instead of _AC(1, UL) so that we get a
++ * sign-extended value on 32-bit with all 1's in the upper word,
++ * which preserves the upper pte values on 64-bit ptes:
++ */
++#define _PAGE_PRESENT	(_AC(1, L)<<_PAGE_BIT_PRESENT)
++#define _PAGE_RW	(_AC(1, L)<<_PAGE_BIT_RW)
++#define _PAGE_USER	(_AC(1, L)<<_PAGE_BIT_USER)
++#define _PAGE_PWT	(_AC(1, L)<<_PAGE_BIT_PWT)
++#define _PAGE_PCD	(_AC(1, L)<<_PAGE_BIT_PCD)
++#define _PAGE_ACCESSED	(_AC(1, L)<<_PAGE_BIT_ACCESSED)
++#define _PAGE_DIRTY	(_AC(1, L)<<_PAGE_BIT_DIRTY)
++#define _PAGE_PSE	(_AC(1, L)<<_PAGE_BIT_PSE)	/* 2MB page */
++#define _PAGE_GLOBAL	(_AC(1, L)<<_PAGE_BIT_GLOBAL)	/* Global TLB entry */
++#define _PAGE_IO	(_AC(1, L)<<_PAGE_BIT_IO)
++#define _PAGE_UNUSED2	(_AC(1, L)<<_PAGE_BIT_UNUSED2)
++#define _PAGE_UNUSED3	(_AC(1, L)<<_PAGE_BIT_UNUSED3)
++#define _PAGE_PAT	(_AC(1, L)<<_PAGE_BIT_PAT)
++#define _PAGE_PAT_LARGE (_AC(1, L)<<_PAGE_BIT_PAT_LARGE)
++
++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
++#define _PAGE_NX	(_AC(1, ULL) << _PAGE_BIT_NX)
++#else
++#define _PAGE_NX	0
++#endif
++
++/* If _PAGE_PRESENT is clear, we use these: */
++#define _PAGE_FILE	_PAGE_DIRTY	/* nonlinear file mapping, saved PTE; unset:swap */
++#define _PAGE_PROTNONE	_PAGE_PSE	/* if the user mapped it with PROT_NONE;
++					   pte_present gives true */
++
++#ifndef __ASSEMBLY__
++#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
++extern unsigned int __kernel_page_user;
++#else
++#define __kernel_page_user 0
++#endif
++#endif
++
++#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 | _PAGE_IO)
++
++#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
++#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++
++#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++#define PAGE_COPY		PAGE_COPY_NOEXEC
++#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
++#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
++
++#ifdef CONFIG_X86_32
++#define _PAGE_KERNEL_EXEC \
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
++#define _PAGE_KERNEL (_PAGE_KERNEL_EXEC | _PAGE_NX)
++
++#ifndef __ASSEMBLY__
++extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
++#endif	/* __ASSEMBLY__ */
++#else
++#define __PAGE_KERNEL_EXEC						\
++	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
++#define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
++#endif
++
++#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
++#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
++#define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
++#define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
++#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
++#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
++#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
++
++/*
++ * We don't support GLOBAL page in xenolinux64
++ */
++#define MAKE_GLOBAL(x)			__pgprot((x))
++
++#define PAGE_KERNEL			MAKE_GLOBAL(__PAGE_KERNEL)
++#define PAGE_KERNEL_RO			MAKE_GLOBAL(__PAGE_KERNEL_RO)
++#define PAGE_KERNEL_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
++#define PAGE_KERNEL_RX			MAKE_GLOBAL(__PAGE_KERNEL_RX)
++#define PAGE_KERNEL_NOCACHE		MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
++#define PAGE_KERNEL_UC_MINUS		MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS)
++#define PAGE_KERNEL_EXEC_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE)
++#define PAGE_KERNEL_LARGE		MAKE_GLOBAL(__PAGE_KERNEL_LARGE)
++#define PAGE_KERNEL_LARGE_EXEC		MAKE_GLOBAL(__PAGE_KERNEL_LARGE_EXEC)
++#define PAGE_KERNEL_VSYSCALL		MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL)
++#define PAGE_KERNEL_VSYSCALL_NOCACHE	MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL_NOCACHE)
++
++/*         xwr */
++#define __P000	PAGE_NONE
++#define __P001	PAGE_READONLY
++#define __P010	PAGE_COPY
++#define __P011	PAGE_COPY
++#define __P100	PAGE_READONLY_EXEC
++#define __P101	PAGE_READONLY_EXEC
++#define __P110	PAGE_COPY_EXEC
++#define __P111	PAGE_COPY_EXEC
++
++#define __S000	PAGE_NONE
++#define __S001	PAGE_READONLY
++#define __S010	PAGE_SHARED
++#define __S011	PAGE_SHARED
++#define __S100	PAGE_READONLY_EXEC
++#define __S101	PAGE_READONLY_EXEC
++#define __S110	PAGE_SHARED_EXEC
++#define __S111	PAGE_SHARED_EXEC
++
++#ifndef __ASSEMBLY__
++
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
++#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
++
++extern spinlock_t pgd_lock;
++extern struct list_head pgd_list;
++
++/*
++ * The following only work if pte_present() is true.
++ * Undefined behaviour if not..
++ */
++static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
++static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
++static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
++static inline int pte_file(pte_t pte)		{ return __pte_val(pte) & _PAGE_FILE; }
++static inline int pte_huge(pte_t pte)		{ return __pte_val(pte) & _PAGE_PSE; }
++static inline int pte_global(pte_t pte) 	{ return 0; }
++static inline int pte_exec(pte_t pte)		{ return !(__pte_val(pte) & _PAGE_NX); }
++
++static inline int pmd_large(pmd_t pte) {
++	return (__pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
++		(_PAGE_PSE|_PAGE_PRESENT);
++}
++
++static inline pte_t pte_mkclean(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); }
++static inline pte_t pte_mkold(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); }
++static inline pte_t pte_wrprotect(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_RW); }
++static inline pte_t pte_mkexec(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_NX); }
++static inline pte_t pte_mkdirty(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_DIRTY); }
++static inline pte_t pte_mkyoung(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_ACCESSED); }
++static inline pte_t pte_mkwrite(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_RW); }
++static inline pte_t pte_mkhuge(pte_t pte)	{ return __pte_ma(__pte_val(pte) | _PAGE_PSE); }
++static inline pte_t pte_clrhuge(pte_t pte)	{ return __pte_ma(__pte_val(pte) & ~(pteval_t)_PAGE_PSE); }
++static inline pte_t pte_mkglobal(pte_t pte)	{ return pte; }
++static inline pte_t pte_clrglobal(pte_t pte)	{ return pte; }
++
++extern pteval_t __supported_pte_mask;
++
++static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) |
++		      pgprot_val(pgprot)) & __supported_pte_mask);
++}
++
++static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pte_ma((((phys_addr_t)page_nr << PAGE_SHIFT) |
++			 pgprot_val(pgprot)) & __supported_pte_mask);
++}
++
++static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
++{
++	return __pmd((((phys_addr_t)page_nr << PAGE_SHIFT) |
++		      pgprot_val(pgprot)) & __supported_pte_mask);
++}
++
++static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
++{
++	pteval_t val = pte_val(pte);
++
++	val &= _PAGE_CHG_MASK;
++	val |= pgprot_val(newprot) & __supported_pte_mask;
++
++	return __pte(val);
++}
++
++#define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX))
++
++#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
++
++#define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
++#define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
++
++#define set_pte_atomic(ptep, pte)					\
++	xen_set_pte_atomic(ptep, pte)
++
++#define set_pmd(pmdp, pmd)		xen_set_pmd(pmdp, pmd)
++
++#ifndef __PAGETABLE_PUD_FOLDED
++#define set_pgd(pgdp, pgd)		xen_set_pgd(pgdp, pgd)
++#define pgd_clear(pgd)			xen_pgd_clear(pgd)
++#endif
++
++#ifndef set_pud
++# define set_pud(pudp, pud)		xen_set_pud(pudp, pud)
++#endif
++
++#ifndef __PAGETABLE_PMD_FOLDED
++#define pud_clear(pud)			xen_pud_clear(pud)
++#endif
++
++#define pte_clear(mm, addr, ptep)	xen_pte_clear(mm, addr, ptep)
++#define pmd_clear(pmd)			xen_pmd_clear(pmd)
++
++#define pte_update(mm, addr, ptep)              do { } while (0)
++#define pte_update_defer(mm, addr, ptep)        do { } while (0)
++
++#endif	/* __ASSEMBLY__ */
++
+ #ifdef CONFIG_X86_32
+ # include "pgtable_32.h"
+ #else
+ # include "pgtable_64.h"
+ #endif
++
++#ifndef __ASSEMBLY__
++
++enum {
++	PG_LEVEL_NONE,
++	PG_LEVEL_4K,
++	PG_LEVEL_2M,
++	PG_LEVEL_1G,
++};
++
++/*
++ * Helper function that returns the kernel pagetable entry controlling
++ * the virtual address 'address'. NULL means no pagetable entry present.
++ * NOTE: the return type is pte_t but if the pmd is PSE then we return it
++ * as a pte too.
++ */
++extern pte_t *lookup_address(unsigned long address, unsigned int *level);
++
++/* local pte updates need not use xchg for locking */
++static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
++{
++	xen_set_pte(ptep, __pte(0));
++	return res;
++}
++
++static inline void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
++				  pte_t *ptep , pte_t pte)
++{
++	if ((mm != current->mm && mm != &init_mm) ||
++	    HYPERVISOR_update_va_mapping(addr, pte, 0))
++		xen_set_pte(ptep, pte);
++}
++
++static inline void xen_pte_clear(struct mm_struct *mm, unsigned long addr,
++				 pte_t *ptep)
++{
++	if ((mm != current->mm && mm != &init_mm)
++	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
++		__xen_pte_clear(ptep);
++}
++
++#ifndef CONFIG_PARAVIRT
++/*
++ * Rules for using pte_update - it must be called after any PTE update which
++ * has not been done using the set_pte / clear_pte interfaces.  It is used by
++ * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
++ * updates should either be sets, clears, or set_pte_atomic for P->P
++ * transitions, which means this hook should only be called for user PTEs.
++ * This hook implies a P->P protection or access change has taken place, which
++ * requires a subsequent TLB flush.  The notification can optionally be delayed
++ * until the TLB flush event by using the pte_update_defer form of the
++ * interface, but care must be taken to assure that the flush happens while
++ * still holding the same page table lock so that the shadow and primary pages
++ * do not become out of sync on SMP.
++ */
++#define pte_update(mm, addr, ptep)		do { } while (0)
++#define pte_update_defer(mm, addr, ptep)	do { } while (0)
++#endif
++
++/*
++ * We only update the dirty/accessed state if we set
++ * the dirty bit by hand in the kernel, since the hardware
++ * will do the accessed bit for us, and we don't want to
++ * race with other CPU's that might be updating the dirty
++ * bit at the same time.
++ */
++#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
++#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
++({									\
++	int __changed = !pte_same(*(ptep), entry);			\
++	if (__changed && (dirty)) {					\
++		if ( likely((vma)->vm_mm == current->mm) ) {		\
++			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
++				entry,					\
++				uvm_multi((vma)->vm_mm->cpu_vm_mask) |	\
++					UVMF_INVLPG));			\
++		} else {						\
++			xen_l1_entry_update(ptep, entry);		\
++			flush_tlb_page(vma, address);			\
++		}							\
++	}								\
++	__changed;							\
++})
++
++#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
++#define ptep_test_and_clear_young(vma, addr, ptep) ({			\
++	int __ret = 0;							\
++	if (pte_young(*(ptep)))						\
++		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
++					   &(ptep)->pte);		\
++	if (__ret)							\
++		pte_update((vma)->vm_mm, addr, ptep);			\
++	__ret;								\
++})
++
++#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define ptep_clear_flush_young(vma, address, ptep)			\
++({									\
++	pte_t __pte = *(ptep);						\
++	int __young = pte_young(__pte);					\
++	__pte = pte_mkold(__pte);					\
++	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
++		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
++	else if (__young)						\
++		(ptep)->pte_low = __pte.pte_low;			\
++	__young;							\
++})
++
++#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
++#define ptep_clear_flush(vma, addr, ptep)			\
++({								\
++	pte_t *__ptep = (ptep);					\
++	pte_t __res = *__ptep;					\
++	if (!pte_none(__res) &&					\
++	    ((vma)->vm_mm != current->mm ||			\
++	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
++			uvm_multi((vma)->vm_mm->cpu_vm_mask) |	\
++				UVMF_INVLPG))) {		\
++		__xen_pte_clear(__ptep);			\
++		flush_tlb_page(vma, addr);			\
++	}							\
++	__res;							\
++})
++
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
++static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (!pte_none(pte)
++	    && (mm != &init_mm
++	        || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))) {
++		pte = xen_ptep_get_and_clear(ptep, pte);
++		pte_update(mm, addr, ptep);
++	}
++	return pte;
++}
++
++#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
++#define ptep_get_and_clear_full(mm, addr, ptep, full)		\
++	((full) ? ({						\
++		pte_t *__ptep = (ptep);				\
++		pte_t __res = *__ptep;				\
++		if (!PagePinned(virt_to_page((mm)->pgd)))	\
++			__xen_pte_clear(__ptep);		\
++		else if (!pte_none(__res))			\
++			xen_l1_entry_update(__ptep, __pte(0));	\
++		__res;						\
++	 }) :							\
++	 ptep_get_and_clear(mm, addr, ptep))
++
++pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *, unsigned long, pte_t *, int);
++
++#define __HAVE_ARCH_PTEP_SET_WRPROTECT
++static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++{
++	pte_t pte = *ptep;
++	if (pte_write(pte))
++		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
++}
++
++#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
++	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
++
++#define arbitrary_virt_to_machine(va)					\
++({									\
++	unsigned int __lvl;						\
++	pte_t *__ptep = lookup_address((unsigned long)(va), &__lvl);	\
++	BUG_ON(!__ptep || __lvl != PG_LEVEL_4K || !pte_present(*__ptep));\
++	(((maddr_t)pte_mfn(*__ptep) << PAGE_SHIFT)			\
++	 | ((unsigned long)(va) & (PAGE_SIZE - 1)));			\
++})
++
++#ifdef CONFIG_HIGHPTE
++#include <asm/io.h>
++struct page *kmap_atomic_to_page(void *);
++#define ptep_to_machine(ptep)						\
++({									\
++	pte_t *__ptep = (ptep);						\
++	page_to_phys(kmap_atomic_to_page(__ptep))			\
++		| ((unsigned long)__ptep & (PAGE_SIZE - 1));		\
++})
++#else
++#define ptep_to_machine(ptep)	virt_to_machine(ptep)
++#endif
++
++#include <asm-generic/pgtable.h>
++
++#include <xen/features.h>
++void make_page_readonly(void *va, unsigned int feature);
++void make_page_writable(void *va, unsigned int feature);
++void make_pages_readonly(void *va, unsigned int nr, unsigned int feature);
++void make_pages_writable(void *va, unsigned int nr, unsigned int feature);
++
++struct vm_area_struct;
++
++int direct_remap_pfn_range(struct vm_area_struct *vma,
++                           unsigned long address,
++                           unsigned long mfn,
++                           unsigned long size,
++                           pgprot_t prot,
++                           domid_t  domid);
++int direct_kernel_remap_pfn_range(unsigned long address,
++				  unsigned long mfn,
++				  unsigned long size,
++				  pgprot_t prot,
++				  domid_t  domid);
++int create_lookup_pte_addr(struct mm_struct *mm,
++                           unsigned long address,
++                           uint64_t *ptep);
++int touch_pte_range(struct mm_struct *mm,
++                    unsigned long address,
++                    unsigned long size);
++
++int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
++		unsigned long addr, unsigned long end, pgprot_t newprot,
++		int dirty_accountable);
++
++#endif	/* __ASSEMBLY__ */
++
++#endif	/* _ASM_X86_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:25.000000000 +0100
+@@ -18,16 +18,18 @@
+ 	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n", __FILE__, __LINE__, \
+ 	       &(e), __pgd_val(e), (pgd_val(e) & PTE_MASK) >> PAGE_SHIFT)
+ 
+-#define pud_none(pud)				0
+-#define pud_bad(pud)				0
+-#define pud_present(pud)			1
+ 
+-/*
+- * All present pages with !NX bit are kernel-executable:
+- */
+-static inline int pte_exec_kernel(pte_t pte)
++static inline int pud_none(pud_t pud)
++{
++	return __pud_val(pud) == 0;
++}
++static inline int pud_bad(pud_t pud)
+ {
+-	return !(__pte_val(pte) & _PAGE_NX);
++	return (__pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
++}
++static inline int pud_present(pud_t pud)
++{
++	return __pud_val(pud) & _PAGE_PRESENT;
+ }
+ 
+ /* Rules for using set_pte: the pte being assigned *must* be
+@@ -44,14 +46,6 @@ static inline void xen_set_pte(pte_t *pt
+ 	ptep->pte_low = pte.pte_low;
+ }
+ 
+-static inline void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+-				  pte_t *ptep , pte_t pte)
+-{
+-	if ((mm != current->mm && mm != &init_mm) ||
+-	    HYPERVISOR_update_va_mapping(addr, pte, 0))
+-		xen_set_pte(ptep, pte);
+-}
+-
+ static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
+ {
+ 	set_64bit((unsigned long long *)(ptep),__pte_val(pte));
+@@ -70,14 +64,11 @@ static inline void xen_set_pud(pud_t *pu
+  * entry, so clear the bottom half first and enforce ordering with a compiler
+  * barrier.
+  */
+-static inline void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
++static inline void __xen_pte_clear(pte_t *ptep)
+ {
+-	if ((mm != current->mm && mm != &init_mm)
+-	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+-		ptep->pte_low = 0;
+-		smp_wmb();
+-		ptep->pte_high = 0;
+-	}
++	ptep->pte_low = 0;
++	smp_wmb();
++	ptep->pte_high = 0;
+ }
+ 
+ static inline void xen_pmd_clear(pmd_t *pmd)
+@@ -85,21 +76,25 @@ static inline void xen_pmd_clear(pmd_t *
+ 	xen_l2_entry_update(pmd, __pmd(0));
+ }
+ 
+-#define set_pte(ptep, pte)			xen_set_pte(ptep, pte)
+-#define set_pte_at(mm, addr, ptep, pte)		xen_set_pte_at(mm, addr, ptep, pte)
+-#define set_pte_atomic(ptep, pte)		xen_set_pte_atomic(ptep, pte)
+-#define set_pmd(pmdp, pmd)			xen_set_pmd(pmdp, pmd)
+-#define set_pud(pudp, pud)			xen_set_pud(pudp, pud)
+-#define pte_clear(mm, addr, ptep)		xen_pte_clear(mm, addr, ptep)
+-#define pmd_clear(pmd)				xen_pmd_clear(pmd)
++static inline void pud_clear(pud_t *pudp)
++{
++	pgdval_t pgd;
++
++	set_pud(pudp, __pud(0));
+ 
+-/*
+- * Pentium-II erratum A13: in PAE mode we explicitly have to flush
+- * the TLB via cr3 if the top-level pgd is changed...
+- * We do not let the generic code free and clear pgd entries due to
+- * this erratum.
+- */
+-static inline void pud_clear (pud_t * pud) { }
++	/*
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
++	 *
++	 * Make sure the pud entry we're updating is within the
++	 * current pgd to avoid unnecessary TLB flushes.
++	 */
++	pgd = read_cr3();
++	if (__pa(pudp) >= pgd && __pa(pudp) < (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
++		xen_tlb_flush();
++}
+ 
+ #define pud_page(pud) \
+ ((struct page *) __va(pud_val(pud) & PAGE_MASK))
+@@ -128,24 +123,6 @@ static inline pte_t xen_ptep_get_and_cle
+ #define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
+ #endif
+ 
+-#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+-#define ptep_clear_flush(vma, addr, ptep)			\
+-({								\
+-	pte_t *__ptep = (ptep);					\
+-	pte_t __res = *__ptep;					\
+-	if (!pte_none(__res) &&					\
+-	    ((vma)->vm_mm != current->mm ||			\
+-	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
+-			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+-				UVMF_INVLPG|UVMF_MULTI))) {	\
+-		__ptep->pte_low = 0;				\
+-		smp_wmb();					\
+-		__ptep->pte_high = 0;				\
+-		flush_tlb_page(vma, addr);			\
+-	}							\
+-	__res;							\
+-})
+-
+ #define __HAVE_ARCH_PTE_SAME
+ static inline int pte_same(pte_t a, pte_t b)
+ {
+@@ -168,26 +145,12 @@ static inline int pte_none(pte_t pte)
+ 		       mfn_to_local_pfn(__pte_mfn(_pte)) :	\
+ 		       __pte_mfn(_pte))
+ 
+-extern unsigned long long __supported_pte_mask;
+-
+-static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+-{
+-	return __pte((((unsigned long long)page_nr << PAGE_SHIFT) |
+-		      pgprot_val(pgprot)) & __supported_pte_mask);
+-}
+-
+-static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+-{
+-	return __pmd((((unsigned long long)page_nr << PAGE_SHIFT) |
+-		      pgprot_val(pgprot)) & __supported_pte_mask);
+-}
+-
+ /*
+  * Bits 0, 6 and 7 are taken in the low part of the pte,
+  * put the 32 bits of offset into the high part.
+  */
+ #define pte_to_pgoff(pte) ((pte).pte_high)
+-#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
++#define pgoff_to_pte(off) ((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
+ #define PTE_FILE_MAX_BITS       32
+ 
+ /* Encode and de-code a swap entry */
+@@ -195,8 +158,6 @@ static inline pmd_t pfn_pmd(unsigned lon
+ #define __swp_offset(x)			((x).val >> 5)
+ #define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
+ #define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+-#define __swp_entry_to_pte(x)		((pte_t){ 0, (x).val })
+-
+-#define __pmd_free_tlb(tlb, x)		do { } while (0)
++#define __swp_entry_to_pte(x)		((pte_t){ { .pte_high = (x).val } })
+ 
+ #endif /* _I386_PGTABLE_3LEVEL_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,8 +1,6 @@
+ #ifndef _I386_PGTABLE_H
+ #define _I386_PGTABLE_H
+ 
+-#include <asm/hypervisor.h>
+-
+ /*
+  * The Linux memory management assumes a three-level page table setup. On
+  * the i386, we use that, but "fold" the mid level into the top-level page
+@@ -25,20 +23,10 @@
+ 
+ struct vm_area_struct;
+ 
+-/*
+- * ZERO_PAGE is a global shared page that is always zero: used
+- * for zero-mapped memory areas etc..
+- */
+-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+-extern unsigned long empty_zero_page[1024];
+ extern pgd_t *swapper_pg_dir;
+-extern struct kmem_cache *pmd_cache;
+-extern spinlock_t pgd_lock;
+-extern struct page *pgd_list;
+-void check_pgt_cache(void);
+ 
+-void pmd_ctor(struct kmem_cache *, void *);
+-void pgtable_cache_init(void);
++static inline void pgtable_cache_init(void) { }
++static inline void check_pgt_cache(void) { }
+ void paging_init(void);
+ 
+ 
+@@ -58,16 +46,9 @@ void paging_init(void);
+ #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE-1))
+ 
+-#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+-#define FIRST_USER_ADDRESS	0
+-
+ #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+ #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+ 
+-#define TWOLEVEL_PGDIR_SHIFT	22
+-#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
+-#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
+-
+ /* Just any arbitrary offset to the start of the vmalloc VM area: the
+  * current 8MB value just means that there will be a 8MB "hole" after the
+  * physical memory until the kernel virtual memory starts.  That means that
+@@ -78,121 +59,19 @@ void paging_init(void);
+ #define VMALLOC_OFFSET	(8*1024*1024)
+ #define VMALLOC_START	(((unsigned long) high_memory + \
+ 			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
+-#ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
+-#else
+-# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
+-#endif
+-
+-/*
+- * _PAGE_PSE set in the page directory entry just means that
+- * the page directory entry points directly to a 4MB-aligned block of
+- * memory. 
+- */
+-#define _PAGE_BIT_PRESENT	0
+-#define _PAGE_BIT_RW		1
+-#define _PAGE_BIT_USER		2
+-#define _PAGE_BIT_PWT		3
+-#define _PAGE_BIT_PCD		4
+-#define _PAGE_BIT_ACCESSED	5
+-#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_UNUSED2	10
+-#define _PAGE_BIT_UNUSED3	11
+-#define _PAGE_BIT_NX		63
+-
+-#define _PAGE_PRESENT	0x001
+-#define _PAGE_RW	0x002
+-#define _PAGE_USER	0x004
+-#define _PAGE_PWT	0x008
+-#define _PAGE_PCD	0x010
+-#define _PAGE_ACCESSED	0x020
+-#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_UNUSED2	0x400
+-#define _PAGE_UNUSED3	0x800
+-
+-/* If _PAGE_PRESENT is clear, we use these: */
+-#define _PAGE_FILE	0x040	/* nonlinear file mapping, saved PTE; unset:swap */
+-#define _PAGE_PROTNONE	0x080	/* if the user mapped it with PROT_NONE;
+-				   pte_present gives true */
+ #ifdef CONFIG_X86_PAE
+-#define _PAGE_NX	(1ULL<<_PAGE_BIT_NX)
++#define LAST_PKMAP 512
+ #else
+-#define _PAGE_NX	0
++#define LAST_PKMAP 1024
+ #endif
+ 
+-/* Mapped page is I/O or foreign and has no associated page struct. */
+-#define _PAGE_IO	0x200
++#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
+ 
+-#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 | _PAGE_IO)
+-
+-#define PAGE_NONE \
+-	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED \
+-	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-
+-#define PAGE_SHARED_EXEC \
+-	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC \
+-	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY_EXEC \
+-	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY \
+-	PAGE_COPY_NOEXEC
+-#define PAGE_READONLY \
+-	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC \
+-	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+-
+-#define _PAGE_KERNEL \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
+-#define _PAGE_KERNEL_EXEC \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+-
+-extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+-#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+-#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+-#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD)
+-#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
+-#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+-
+-#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL)
+-#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO)
+-#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC)
+-#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX)
+-#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
+-#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
+-#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+-
+-/*
+- * The i386 can't do page protection for execute, and considers that
+- * the same are read. Also, write permissions imply read permissions.
+- * This is the closest we can get..
+- */
+-#define __P000	PAGE_NONE
+-#define __P001	PAGE_READONLY
+-#define __P010	PAGE_COPY
+-#define __P011	PAGE_COPY
+-#define __P100	PAGE_READONLY_EXEC
+-#define __P101	PAGE_READONLY_EXEC
+-#define __P110	PAGE_COPY_EXEC
+-#define __P111	PAGE_COPY_EXEC
+-
+-#define __S000	PAGE_NONE
+-#define __S001	PAGE_READONLY
+-#define __S010	PAGE_SHARED
+-#define __S011	PAGE_SHARED
+-#define __S100	PAGE_READONLY_EXEC
+-#define __S101	PAGE_READONLY_EXEC
+-#define __S110	PAGE_SHARED_EXEC
+-#define __S111	PAGE_SHARED_EXEC
++#ifdef CONFIG_HIGHMEM
++# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
++#else
++# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
++#endif
+ 
+ /*
+  * Define this if things work differently on an i386 and an i486:
+@@ -221,28 +100,6 @@ extern unsigned long pg0[];
+ 
+ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+ 
+-/*
+- * The following only work if pte_present() is true.
+- * Undefined behaviour if not..
+- */
+-static inline int pte_dirty(pte_t pte)		{ return (pte).pte_low & _PAGE_DIRTY; }
+-static inline int pte_young(pte_t pte)		{ return (pte).pte_low & _PAGE_ACCESSED; }
+-static inline int pte_write(pte_t pte)		{ return (pte).pte_low & _PAGE_RW; }
+-static inline int pte_huge(pte_t pte)		{ return (pte).pte_low & _PAGE_PSE; }
+-
+-/*
+- * The following only works if pte_present() is not true.
+- */
+-static inline int pte_file(pte_t pte)		{ return (pte).pte_low & _PAGE_FILE; }
+-
+-static inline pte_t pte_mkclean(pte_t pte)	{ (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
+-static inline pte_t pte_mkold(pte_t pte)	{ (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
+-static inline pte_t pte_wrprotect(pte_t pte)	{ (pte).pte_low &= ~_PAGE_RW; return pte; }
+-static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
+-static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
+-static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
+-static inline pte_t pte_mkhuge(pte_t pte)	{ (pte).pte_low |= _PAGE_PSE; return pte; }
+-
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level.h>
+ #else
+@@ -250,111 +107,6 @@ static inline pte_t pte_mkhuge(pte_t pte
+ #endif
+ 
+ /*
+- * Rules for using pte_update - it must be called after any PTE update which
+- * has not been done using the set_pte / clear_pte interfaces.  It is used by
+- * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
+- * updates should either be sets, clears, or set_pte_atomic for P->P
+- * transitions, which means this hook should only be called for user PTEs.
+- * This hook implies a P->P protection or access change has taken place, which
+- * requires a subsequent TLB flush.  The notification can optionally be delayed
+- * until the TLB flush event by using the pte_update_defer form of the
+- * interface, but care must be taken to assure that the flush happens while
+- * still holding the same page table lock so that the shadow and primary pages
+- * do not become out of sync on SMP.
+- */
+-#define pte_update(mm, addr, ptep)		do { } while (0)
+-#define pte_update_defer(mm, addr, ptep)	do { } while (0)
+-
+-/* local pte updates need not use xchg for locking */
+-static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
+-{
+-	xen_set_pte(ptep, __pte(0));
+-	return res;
+-}
+-
+-/*
+- * We only update the dirty/accessed state if we set
+- * the dirty bit by hand in the kernel, since the hardware
+- * will do the accessed bit for us, and we don't want to
+- * race with other CPU's that might be updating the dirty
+- * bit at the same time.
+- */
+-#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-({									\
+-	int __changed = !pte_same(*(ptep), entry);			\
+-	if (__changed && (dirty)) {					\
+-		if ( likely((vma)->vm_mm == current->mm) ) {		\
+-			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
+-				entry,					\
+-				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+-					UVMF_INVLPG|UVMF_MULTI));	\
+-		} else {						\
+-			xen_l1_entry_update(ptep, entry);		\
+-			flush_tlb_page(vma, address);			\
+-		}							\
+-	}								\
+-	__changed;							\
+-})
+-
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define ptep_test_and_clear_young(vma, addr, ptep) ({			\
+-	int __ret = 0;							\
+-	if (pte_young(*(ptep)))						\
+-		__ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,		\
+-						&(ptep)->pte_low);	\
+-	if (__ret)							\
+-		pte_update((vma)->vm_mm, addr, ptep);			\
+-	__ret;								\
+-})
+-
+-#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+-#define ptep_clear_flush_young(vma, address, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __young = pte_young(__pte);					\
+-	__pte = pte_mkold(__pte);					\
+-	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
+-		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+-	else if (__young)						\
+-		(ptep)->pte_low = __pte.pte_low;			\
+-	__young;							\
+-})
+-
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+-	pte_t pte = *ptep;
+-	if (!pte_none(pte)
+-	    && (mm != &init_mm
+-	        || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))) {
+-		pte = xen_ptep_get_and_clear(ptep, pte);
+-		pte_update(mm, addr, ptep);
+-	}
+-	return pte;
+-}
+-
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+-#define ptep_get_and_clear_full(mm, addr, ptep, full)			\
+-	((full) ? ({							\
+-		pte_t __res = *(ptep);					\
+-		if (PagePinned(virt_to_page((mm)->pgd)))		\
+-			xen_l1_entry_update(ptep, __pte(0));		\
+-		else							\
+-			*(ptep) = __pte(0);				\
+-		__res;							\
+-	 }) :								\
+-	 ptep_get_and_clear(mm, addr, ptep))
+-
+-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+-	pte_t pte = *ptep;
+-	if (pte_write(pte))
+-		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
+-}
+-
+-/*
+  * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+  *
+  *  dst - pointer to pgd range anwhere on a pgd page
+@@ -383,26 +135,6 @@ static inline void clone_pgd_range(pgd_t
+ 
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+ 
+-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+-{
+-	/*
+-	 * Since this might change the present bit (which controls whether
+-	 * a pte_t object has undergone p2m translation), we must use
+-	 * pte_val() on the input pte and __pte() for the return value.
+-	 */
+-	paddr_t pteval = pte_val(pte);
+-
+-	pteval &= _PAGE_CHG_MASK;
+-	pteval |= pgprot_val(newprot);
+-#ifdef CONFIG_X86_PAE
+-	pteval &= __supported_pte_mask;
+-#endif
+-	return __pte(pteval);
+-}
+-
+-#define pmd_large(pmd) \
+-((__pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
+-
+ /*
+  * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+  *
+@@ -424,6 +156,8 @@ static inline pte_t pte_modify(pte_t pte
+  */
+ #define pgd_offset_k(address) pgd_offset(&init_mm, address)
+ 
++static inline int pud_large(pud_t pud) { return 0; }
++
+ /*
+  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+  *
+@@ -449,26 +183,6 @@ static inline pte_t pte_modify(pte_t pte
+ #define pmd_page_vaddr(pmd) \
+ 		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+ 
+-/*
+- * Helper function that returns the kernel pagetable entry controlling
+- * the virtual address 'address'. NULL means no pagetable entry present.
+- * NOTE: the return type is pte_t but if the pmd is PSE then we return it
+- * as a pte too.
+- */
+-extern pte_t *lookup_address(unsigned long address);
+-
+-/*
+- * Make a given kernel text page executable/non-executable.
+- * Returns the previous executability setting of that page (which
+- * is used to restore the previous state). Used by the SMP bootup code.
+- * NOTE: this is an __init function for security reasons.
+- */
+-#ifdef CONFIG_X86_PAE
+- extern int set_kernel_exec(unsigned long vaddr, int enable);
+-#else
+- static inline int set_kernel_exec(unsigned long vaddr, int enable) { return 0;}
+-#endif
+-
+ #if defined(CONFIG_HIGHPTE)
+ #define pte_offset_map(dir, address) \
+ 	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
+@@ -496,72 +210,22 @@ extern pte_t *lookup_address(unsigned lo
+  */
+ #define update_mmu_cache(vma,address,pte) do { } while (0)
+ 
+-#include <xen/features.h>
+ void make_lowmem_page_readonly(void *va, unsigned int feature);
+ void make_lowmem_page_writable(void *va, unsigned int feature);
+-void make_page_readonly(void *va, unsigned int feature);
+-void make_page_writable(void *va, unsigned int feature);
+-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)						\
+-({									\
+-	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)))
+-
+-#ifdef CONFIG_HIGHPTE
+-#include <asm/io.h>
+-struct page *kmap_atomic_to_page(void *);
+-#define ptep_to_machine(ptep)						\
+-({									\
+-	pte_t *__ptep = (ptep);						\
+-	page_to_phys(kmap_atomic_to_page(__ptep))			\
+-		| ((unsigned long)__ptep & (PAGE_SIZE - 1));		\
+-})
+-#else
+-#define ptep_to_machine(ptep)	virt_to_machine(ptep)
+-#endif
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
++/*
++ * kern_addr_valid() is (1) for FLATMEM and (0) for
++ * SPARSEMEM and DISCONTIGMEM
++ */
+ #ifdef CONFIG_FLATMEM
+ #define kern_addr_valid(addr)	(1)
+-#endif /* CONFIG_FLATMEM */
+-
+-int direct_remap_pfn_range(struct vm_area_struct *vma,
+-                           unsigned long address, 
+-                           unsigned long mfn,
+-                           unsigned long size, 
+-                           pgprot_t prot,
+-                           domid_t  domid);
+-int direct_kernel_remap_pfn_range(unsigned long address, 
+-				  unsigned long mfn,
+-				  unsigned long size, 
+-				  pgprot_t prot,
+-				  domid_t  domid);
+-int create_lookup_pte_addr(struct mm_struct *mm,
+-                           unsigned long address,
+-                           uint64_t *ptep);
+-int touch_pte_range(struct mm_struct *mm,
+-                    unsigned long address,
+-                    unsigned long size);
+-
+-int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-		unsigned long addr, unsigned long end, pgprot_t newprot,
+-		int dirty_accountable);
+-
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
+-	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
++#else
++#define kern_addr_valid(kaddr)	(0)
++#endif
+ 
+ #define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO)
+ 
+-#include <asm-generic/pgtable.h>
+-
+ #endif /* _I386_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -13,49 +13,26 @@
+ #include <linux/threads.h>
+ #include <linux/sched.h>
+ #include <asm/pda.h>
+-#ifdef CONFIG_XEN
+-#include <asm/hypervisor.h>
+ 
++#ifdef CONFIG_XEN
+ extern pud_t level3_user_pgt[512];
+ 
+ extern void xen_init_pt(void);
+-
+-extern pte_t *lookup_address(unsigned long address);
+-
+-#define virt_to_ptep(va)						\
+-({									\
+-	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)))
+-
+-#define ptep_to_machine(ptep)	virt_to_machine(ptep)
+ #endif
+ 
+ extern pud_t level3_kernel_pgt[512];
+ extern pud_t level3_ident_pgt[512];
+ extern pmd_t level2_kernel_pgt[512];
+ extern pgd_t init_level4_pgt[];
+-extern unsigned long __supported_pte_mask;
+ 
+ #define swapper_pg_dir init_level4_pgt
+ 
+ extern void paging_init(void);
+-extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
+-
+-/*
+- * ZERO_PAGE is a global shared page that is always zero: used
+- * for zero-mapped memory areas etc..
+- */
+-extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
+-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
++#define SHARED_KERNEL_PMD	1
++
+ /*
+  * PGDIR_SHIFT determines what a top-level page table entry can map
+  */
+@@ -98,31 +75,63 @@ extern unsigned long empty_zero_page[PAG
+ #define pgd_none(x)	(!__pgd_val(x))
+ #define pud_none(x)	(!__pud_val(x))
+ 
+-static inline void set_pte(pte_t *dst, pte_t val)
++struct mm_struct;
++
++#define __xen_pte_clear(ptep) xen_set_pte(ptep, __pte(0))
++
++static inline void xen_set_pte(pte_t *ptep, pte_t pte)
++{
++	*ptep = pte;
++}
++
++static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
+ {
+-	*dst = val;
++	xen_set_pte(ptep, pte);
+ }
+ 
+-#define set_pmd(pmdptr, pmdval) xen_l2_entry_update(pmdptr, (pmdval))
+-#define set_pud(pudptr, pudval) xen_l3_entry_update(pudptr, (pudval))
+-#define set_pgd(pgdptr, pgdval) xen_l4_entry_update(pgdptr, (pgdval))
++#ifdef CONFIG_SMP
++static inline pte_t xen_ptep_get_and_clear(pte_t *xp, pte_t ret)
++{
++	return __pte_ma(xchg(&xp->pte, 0));
++}
++#else
++#define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
++#endif
+ 
+-static inline void pud_clear (pud_t * pud)
++static inline void xen_set_pmd(pmd_t *pmdp, pmd_t pmd)
+ {
+-	set_pud(pud, __pud(0));
++	xen_l2_entry_update(pmdp, pmd);
++}
++
++static inline void xen_pmd_clear(pmd_t *pmd)
++{
++	xen_set_pmd(pmd, xen_make_pmd(0));
++}
++
++static inline void xen_set_pud(pud_t *pudp, pud_t pud)
++{
++	xen_l3_entry_update(pudp, pud);
++}
++
++static inline void xen_pud_clear(pud_t *pud)
++{
++	xen_set_pud(pud, xen_make_pud(0));
+ }
+ 
+ #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
+ 
+-static inline void pgd_clear (pgd_t * pgd)
++static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd)
+ {
+-        set_pgd(pgd, __pgd(0));
+-        set_pgd(__user_pgd(pgd), __pgd(0));
++	xen_l4_entry_update(pgdp, pgd);
+ }
+ 
+-#define pte_same(a, b)		((a).pte == (b).pte)
++static inline void xen_pgd_clear(pgd_t * pgd)
++{
++	xen_set_pgd(pgd, xen_make_pgd(0));
++	xen_set_pgd(__user_pgd(pgd), xen_make_pgd(0));
++}
+ 
+-#define pte_pgprot(a)	(__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
++#define pte_same(a, b)		((a).pte == (b).pte)
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
+@@ -133,8 +142,6 @@ static inline void pgd_clear (pgd_t * pg
+ #define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE-1))
+ 
+-#define USER_PTRS_PER_PGD	((TASK_SIZE-1)/PGDIR_SIZE+1)
+-#define FIRST_USER_ADDRESS	0
+ 
+ #define MAXMEM		 _AC(0x6fffffffff, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+@@ -144,105 +151,6 @@ static inline void pgd_clear (pgd_t * pg
+ #define MODULES_END      _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+ 
+-#define _PAGE_BIT_PRESENT	0
+-#define _PAGE_BIT_RW		1
+-#define _PAGE_BIT_USER		2
+-#define _PAGE_BIT_PWT		3
+-#define _PAGE_BIT_PCD		4
+-#define _PAGE_BIT_ACCESSED	5
+-#define _PAGE_BIT_DIRTY		6
+-#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+-#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+-#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+-
+-#define _PAGE_PRESENT	0x001
+-#define _PAGE_RW	0x002
+-#define _PAGE_USER	0x004
+-#define _PAGE_PWT	0x008
+-#define _PAGE_PCD	0x010
+-#define _PAGE_ACCESSED	0x020
+-#define _PAGE_DIRTY	0x040
+-#define _PAGE_PSE	0x080	/* 2MB page */
+-#define _PAGE_FILE	0x040	/* nonlinear file mapping, saved PTE; unset:swap */
+-#define _PAGE_GLOBAL	0x100	/* Global TLB entry */
+-
+-#define _PAGE_PROTNONE	0x080	/* If not present */
+-#define _PAGE_NX        (_AC(1,UL)<<_PAGE_BIT_NX)
+-
+-/* Mapped page is I/O or foreign and has no associated page struct. */
+-#define _PAGE_IO	0x200
+-
+-#ifndef __ASSEMBLY__
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-extern unsigned int __kernel_page_user;
+-#else
+-#define __kernel_page_user 0
+-#endif
+-#endif
+-
+-#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 | _PAGE_IO)
+-
+-#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+-#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_COPY PAGE_COPY_NOEXEC
+-#define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+-#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
+-#define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+-#define __PAGE_KERNEL \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
+-#define __PAGE_KERNEL_EXEC \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
+-#define __PAGE_KERNEL_NOCACHE \
+-	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
+-#define __PAGE_KERNEL_RO \
+-	(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | __kernel_page_user)
+-#define __PAGE_KERNEL_VSYSCALL \
+-	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+-#define __PAGE_KERNEL_VSYSCALL_NOCACHE \
+-	(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_PCD)
+-#define __PAGE_KERNEL_LARGE \
+-	(__PAGE_KERNEL | _PAGE_PSE)
+-#define __PAGE_KERNEL_LARGE_EXEC \
+-	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+-
+-/*
+- * We don't support GLOBAL page in xenolinux64
+- */
+-#define MAKE_GLOBAL(x) __pgprot((x))
+-
+-#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
+-#define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC)
+-#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
+-#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+-#define PAGE_KERNEL_VSYSCALL32 __pgprot(__PAGE_KERNEL_VSYSCALL)
+-#define PAGE_KERNEL_VSYSCALL MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL)
+-#define PAGE_KERNEL_LARGE MAKE_GLOBAL(__PAGE_KERNEL_LARGE)
+-#define PAGE_KERNEL_VSYSCALL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+-
+-/*         xwr */
+-#define __P000	PAGE_NONE
+-#define __P001	PAGE_READONLY
+-#define __P010	PAGE_COPY
+-#define __P011	PAGE_COPY
+-#define __P100	PAGE_READONLY_EXEC
+-#define __P101	PAGE_READONLY_EXEC
+-#define __P110	PAGE_COPY_EXEC
+-#define __P111	PAGE_COPY_EXEC
+-
+-#define __S000	PAGE_NONE
+-#define __S001	PAGE_READONLY
+-#define __S010	PAGE_SHARED
+-#define __S011	PAGE_SHARED
+-#define __S100	PAGE_READONLY_EXEC
+-#define __S101	PAGE_READONLY_EXEC
+-#define __S110	PAGE_SHARED_EXEC
+-#define __S111	PAGE_SHARED_EXEC
+-
+ #ifndef __ASSEMBLY__
+ 
+ static inline unsigned long pgd_bad(pgd_t pgd)
+@@ -260,119 +168,26 @@ static inline unsigned long pmd_bad(pmd_
+ 	return __pmd_val(pmd) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER);
+ }
+ 
+-#define set_pte_at(_mm,addr,ptep,pteval) do {				\
+-	if (((_mm) != current->mm && (_mm) != &init_mm) ||		\
+-	    HYPERVISOR_update_va_mapping((addr), (pteval), 0))		\
+-		set_pte((ptep), (pteval));				\
+-} while (0)
+-
+ #define pte_none(x)	(!(x).pte)
+ #define pte_present(x)	((x).pte & (_PAGE_PRESENT | _PAGE_PROTNONE))
+-#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
+ 
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
++#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))	/* FIXME: is this right? */
+ 
+ #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_IO ? end_pfn :	\
++#define pte_pfn(_pte) ((_pte).pte & _PAGE_IO ? max_mapnr :	\
+ 		       (_pte).pte & _PAGE_PRESENT ?		\
+ 		       mfn_to_local_pfn(__pte_mfn(_pte)) :	\
+ 		       __pte_mfn(_pte))
+ 
+ #define pte_page(x)	pfn_to_page(pte_pfn(x))
+ 
+-static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+-{
+-	unsigned long pte = page_nr << PAGE_SHIFT;
+-	pte |= pgprot_val(pgprot);
+-	pte &= __supported_pte_mask;
+-	return __pte(pte);
+-}
+-
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+-	pte_t pte = *ptep;
+-	if (!pte_none(pte)) {
+-		if ((mm != &init_mm) ||
+-		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
+-			pte = __pte_ma(xchg(&ptep->pte, 0));
+-	}
+-	return pte;
+-}
+-
+-static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
+-{
+-	if (full) {
+-		pte_t pte = *ptep;
+-		if (PagePinned(virt_to_page(mm->pgd)))
+-			xen_l1_entry_update(ptep, __pte(0));
+-		else
+-			*ptep = __pte(0);
+-		return pte;
+-	}
+-	return ptep_get_and_clear(mm, addr, ptep);
+-}
+-
+-#define ptep_clear_flush(vma, addr, ptep)			\
+-({								\
+-	pte_t *__ptep = (ptep);					\
+-	pte_t __res = *__ptep;					\
+-	if (!pte_none(__res) &&					\
+-	    ((vma)->vm_mm != current->mm ||			\
+-	     HYPERVISOR_update_va_mapping(addr,	__pte(0), 	\
+-			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+-				UVMF_INVLPG|UVMF_MULTI))) {	\
+-		__ptep->pte = 0;				\
+-		flush_tlb_page(vma, addr);			\
+-	}							\
+-	__res;							\
+-})
+-
+-/*
+- * The following only work if pte_present() is true.
+- * Undefined behaviour if not..
+- */
+-#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
+-static inline int pte_dirty(pte_t pte)		{ return __pte_val(pte) & _PAGE_DIRTY; }
+-static inline int pte_young(pte_t pte)		{ return __pte_val(pte) & _PAGE_ACCESSED; }
+-static inline int pte_write(pte_t pte)		{ return __pte_val(pte) & _PAGE_RW; }
+-static inline int pte_file(pte_t pte)		{ return __pte_val(pte) & _PAGE_FILE; }
+-static inline int pte_huge(pte_t pte)		{ return __pte_val(pte) & _PAGE_PSE; }
+-
+-static inline pte_t pte_mkclean(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+-static inline pte_t pte_mkold(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+-static inline pte_t pte_wrprotect(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_RW; return pte; }
+-static inline pte_t pte_mkexec(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_NX; return pte; }
+-static inline pte_t pte_mkdirty(pte_t pte)	{ __pte_val(pte) |= _PAGE_DIRTY; return pte; }
+-static inline pte_t pte_mkyoung(pte_t pte)	{ __pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+-static inline pte_t pte_mkwrite(pte_t pte)	{ __pte_val(pte) |= _PAGE_RW; return pte; }
+-static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
+-static inline pte_t pte_clrhuge(pte_t pte)	{ __pte_val(pte) &= ~_PAGE_PSE; return pte; }
+-
+-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+-{
+-	if (!pte_young(*ptep))
+-		return 0;
+-	return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte);
+-}
+-
+-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+-	pte_t pte = *ptep;
+-	if (pte_write(pte))
+-		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
+-}
+-
+ /*
+  * Macro to mark a page protection value as "uncacheable".
+  */
+ #define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
+ 
+-static inline int pmd_large(pmd_t pte) { 
+-	return (__pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE;
+-} 	
+-
+ 
+ /*
+  * Conversion functions: convert a page and protection to a page entry,
+@@ -388,6 +203,7 @@ static inline int pmd_large(pmd_t pte) {
+ #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr))
+ #define pgd_offset_k(address) (init_level4_pgt + pgd_index(address))
+ #define pgd_present(pgd) (__pgd_val(pgd) & _PAGE_PRESENT)
++static inline int pgd_large(pgd_t pgd) { return 0; }
+ #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
+ 
+ /* PUD - Level3 access */
+@@ -398,6 +214,12 @@ static inline int pmd_large(pmd_t pte) {
+ #define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
+ #define pud_present(pud) (__pud_val(pud) & _PAGE_PRESENT)
+ 
++static inline int pud_large(pud_t pte)
++{
++	return (__pud_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
++		(_PAGE_PSE|_PAGE_PRESENT);
++}
++
+ /* PMD  - Level 2 access */
+ #define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+ #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+@@ -413,36 +235,18 @@ static inline int pmd_large(pmd_t pte) {
+ #else
+ #define pmd_present(x)	(__pmd_val(x) & _PAGE_PRESENT)
+ #endif
+-#define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
+ #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
+ #define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+ #define pte_to_pgoff(pte) ((__pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+-#define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE })
++#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) | _PAGE_FILE })
+ #define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
+ 
+ /* PTE - Level 1 access. */
+ 
+ /* page, protection -> pte */
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+-#define mk_pte_huge(entry) (__pte_val(entry) |= _PAGE_PRESENT | _PAGE_PSE)
+  
+-/* Change flags of a PTE */
+-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+-{ 
+-	/*
+-	 * Since this might change the present bit (which controls whether
+-	 * a pte_t object has undergone p2m translation), we must use
+-	 * pte_val() on the input pte and __pte() for the return value.
+-	 */
+-	unsigned long pteval = pte_val(pte);
+-
+-	pteval &= _PAGE_CHG_MASK;
+-	pteval |= pgprot_val(newprot);
+-	pteval &= __supported_pte_mask;
+-	return __pte(pteval);
+-}
+-
+ #define pte_index(address) \
+ 		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
+@@ -456,101 +260,21 @@ static inline pte_t pte_modify(pte_t pte
+ 
+ #define update_mmu_cache(vma,address,pte) do { } while (0)
+ 
+-/*
+- * Rules for using ptep_establish: the pte MUST be a user pte, and
+- * must be a present->present transition.
+- */
+-#define __HAVE_ARCH_PTEP_ESTABLISH
+-#define ptep_establish(vma, address, ptep, pteval)			\
+-	do {								\
+-		if ( likely((vma)->vm_mm == current->mm) ) {		\
+-			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
+-				pteval,					\
+-				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+-					UVMF_INVLPG|UVMF_MULTI));	\
+-		} else {						\
+-			xen_l1_entry_update(ptep, pteval);		\
+-			flush_tlb_page(vma, address);			\
+-		}							\
+-	} while (0)
+-
+-/* We only update the dirty/accessed state if we set
+- * the dirty bit by hand in the kernel, since the hardware
+- * will do the accessed bit for us, and we don't want to
+- * race with other CPU's that might be updating the dirty
+- * bit at the same time. */
+-#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+-#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
+-({									\
+-	int __changed = !pte_same(*(ptep), entry);			\
+-	if (__changed && (dirty))					\
+-		ptep_establish(vma, address, ptep, entry);		\
+-	__changed;							\
+-})
+-
+-#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+-#define ptep_clear_flush_young(vma, address, ptep)			\
+-({									\
+-	pte_t __pte = *(ptep);						\
+-	int __young = pte_young(__pte);					\
+-	__pte = pte_mkold(__pte);					\
+-	if (PagePinned(virt_to_page((vma)->vm_mm->pgd)))		\
+-		(void)ptep_set_access_flags(vma, address, ptep, __pte, __young); \
+-	else if (__young)						\
+-		set_pte(ptep, __pte);					\
+-	__young;							\
+-})
+-
+ /* Encode and de-code a swap entry */
+ #define __swp_type(x)			(((x).val >> 1) & 0x3f)
+ #define __swp_offset(x)			((x).val >> 8)
+ #define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+ #define __pte_to_swp_entry(pte)		((swp_entry_t) { __pte_val(pte) })
+-#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+-
+-extern spinlock_t pgd_lock;
+-extern struct list_head pgd_list;
++#define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
+ 
+ extern int kern_addr_valid(unsigned long addr); 
+-
+-#define DOMID_LOCAL (0xFFFFU)
+-
+-struct vm_area_struct;
+-
+-int direct_remap_pfn_range(struct vm_area_struct *vma,
+-                            unsigned long address,
+-                            unsigned long mfn,
+-                            unsigned long size,
+-                            pgprot_t prot,
+-                            domid_t  domid);
+-
+-int direct_kernel_remap_pfn_range(unsigned long address, 
+-				  unsigned long mfn,
+-				  unsigned long size, 
+-				  pgprot_t prot,
+-				  domid_t  domid);
+-
+-int create_lookup_pte_addr(struct mm_struct *mm,
+-                           unsigned long address,
+-                           uint64_t *ptep);
+-
+-int touch_pte_range(struct mm_struct *mm,
+-                    unsigned long address,
+-                    unsigned long size);
+-
+-int xen_change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+-		unsigned long addr, unsigned long end, pgprot_t newprot,
+-		int dirty_accountable);
+-
+-#define arch_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable) \
+-	xen_change_pte_range(mm, pmd, addr, end, newprot, dirty_accountable)
+-
+-pte_t *lookup_address(unsigned long addr);
++extern void cleanup_highmap(void);
+ 
+ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)		\
+ 		direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO)
+ 
+ #define HAVE_ARCH_UNMAPPED_AREA
++#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+ 
+ #define pgtable_cache_init()   do { } while (0)
+ #define check_pgt_cache()      do { } while (0)
+@@ -563,13 +287,7 @@ pte_t *lookup_address(unsigned long addr
+ #define	kc_offset_to_vaddr(o) \
+    (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
+ 
+-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+-#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+ #define __HAVE_ARCH_PTE_SAME
+-#include <asm-generic/pgtable.h>
+ #endif /* !__ASSEMBLY__ */
+ 
+ #endif /* _X86_64_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,793 @@
++#ifndef __ASM_X86_PROCESSOR_H
++#define __ASM_X86_PROCESSOR_H
++
++#include <asm/processor-flags.h>
++
++/* migration helpers, for KVM - will be removed in 2.6.25: */
++#include <asm/vm86.h>
++#define Xgt_desc_struct	desc_ptr
++
++/* Forward declaration, a strange C thing */
++struct task_struct;
++struct mm_struct;
++
++#include <asm/vm86.h>
++#include <asm/math_emu.h>
++#include <asm/segment.h>
++#include <asm/types.h>
++#include <asm/sigcontext.h>
++#include <asm/current.h>
++#include <asm/cpufeature.h>
++#include <asm/system.h>
++#include <asm/page.h>
++#include <asm/percpu.h>
++#include <asm/msr.h>
++#include <asm/desc_defs.h>
++#include <asm/nops.h>
++#include <linux/personality.h>
++#include <linux/cpumask.h>
++#include <linux/cache.h>
++#include <linux/threads.h>
++#include <linux/init.h>
++#include <xen/interface/physdev.h>
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++static inline void *current_text_addr(void)
++{
++	void *pc;
++	asm volatile("mov $1f,%0\n1:":"=r" (pc));
++	return pc;
++}
++
++#ifdef CONFIG_X86_VSMP
++#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
++#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
++#else
++#define ARCH_MIN_TASKALIGN	16
++#define ARCH_MIN_MMSTRUCT_ALIGN	0
++#endif
++
++/*
++ *  CPU type and hardware bug flags. Kept separately for each CPU.
++ *  Members of this structure are referenced in head.S, so think twice
++ *  before touching them. [mj]
++ */
++
++struct cpuinfo_x86 {
++	__u8	x86;		/* CPU family */
++	__u8	x86_vendor;	/* CPU vendor */
++	__u8	x86_model;
++	__u8	x86_mask;
++#ifdef CONFIG_X86_32
++	char	wp_works_ok;	/* It doesn't on 386's */
++	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */
++	char	hard_math;
++	char	rfu;
++	char	fdiv_bug;
++	char	f00f_bug;
++	char	coma_bug;
++	char	pad0;
++#else
++	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
++	int     x86_tlbsize;
++	__u8    x86_virt_bits, x86_phys_bits;
++	/* cpuid returned core id bits */
++	__u8    x86_coreid_bits;
++	/* Max extended CPUID function supported */
++	__u32   extended_cpuid_level;
++#endif
++	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
++	__u32	x86_capability[NCAPINTS];
++	char	x86_vendor_id[16];
++	char	x86_model_id[64];
++	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
++				    call  */
++	int 	x86_cache_alignment;	/* In bytes */
++	int	x86_power;
++	unsigned long loops_per_jiffy;
++#ifdef CONFIG_SMP
++	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
++#endif
++	u16 x86_max_cores;		/* cpuid returned max cores value */
++	u16 apicid;
++	u16 x86_clflush_size;
++#ifdef CONFIG_SMP
++	u16 booted_cores;		/* number of cores as seen by OS */
++	u16 phys_proc_id; 		/* Physical processor id. */
++	u16 cpu_core_id;  		/* Core id */
++	u16 cpu_index;			/* index into per_cpu list */
++#endif
++} __attribute__((__aligned__(SMP_CACHE_BYTES)));
++
++#define X86_VENDOR_INTEL 0
++#define X86_VENDOR_CYRIX 1
++#define X86_VENDOR_AMD 2
++#define X86_VENDOR_UMC 3
++#define X86_VENDOR_NEXGEN 4
++#define X86_VENDOR_CENTAUR 5
++#define X86_VENDOR_TRANSMETA 7
++#define X86_VENDOR_NSC 8
++#define X86_VENDOR_NUM 9
++#define X86_VENDOR_UNKNOWN 0xff
++
++/*
++ * capabilities of CPUs
++ */
++extern struct cpuinfo_x86 boot_cpu_data;
++extern struct cpuinfo_x86 new_cpu_data;
++extern __u32 cleared_cpu_caps[NCAPINTS];
++
++#ifdef CONFIG_SMP
++DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
++#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
++#define current_cpu_data	cpu_data(smp_processor_id())
++#else
++#define cpu_data(cpu)		boot_cpu_data
++#define current_cpu_data	boot_cpu_data
++#endif
++
++void cpu_detect(struct cpuinfo_x86 *c);
++
++extern void identify_cpu(struct cpuinfo_x86 *);
++extern void identify_boot_cpu(void);
++extern void identify_secondary_cpu(struct cpuinfo_x86 *);
++extern void print_cpu_info(struct cpuinfo_x86 *);
++extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
++extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
++extern unsigned short num_cache_leaves;
++
++#if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64)
++extern void detect_ht(struct cpuinfo_x86 *c);
++#else
++static inline void detect_ht(struct cpuinfo_x86 *c) {}
++#endif
++
++static inline void xen_cpuid(unsigned int *eax, unsigned int *ebx,
++			     unsigned int *ecx, unsigned int *edx)
++{
++	/* ecx is often an input as well as an output. */
++	__asm__(XEN_CPUID
++		: "=a" (*eax),
++		  "=b" (*ebx),
++		  "=c" (*ecx),
++		  "=d" (*edx)
++		: "0" (*eax), "2" (*ecx));
++}
++
++static inline void load_cr3(pgd_t *pgdir)
++{
++	write_cr3(__pa(pgdir));
++}
++
++#ifndef CONFIG_X86_NO_TSS
++#ifdef CONFIG_X86_32
++/* This is the TSS defined by the hardware. */
++struct x86_hw_tss {
++	unsigned short	back_link, __blh;
++	unsigned long	sp0;
++	unsigned short	ss0, __ss0h;
++	unsigned long	sp1;
++	unsigned short	ss1, __ss1h;	/* ss1 caches MSR_IA32_SYSENTER_CS */
++	unsigned long	sp2;
++	unsigned short	ss2, __ss2h;
++	unsigned long	__cr3;
++	unsigned long	ip;
++	unsigned long	flags;
++	unsigned long	ax, cx, dx, bx;
++	unsigned long	sp, bp, si, di;
++	unsigned short	es, __esh;
++	unsigned short	cs, __csh;
++	unsigned short	ss, __ssh;
++	unsigned short	ds, __dsh;
++	unsigned short	fs, __fsh;
++	unsigned short	gs, __gsh;
++	unsigned short	ldt, __ldth;
++	unsigned short	trace, io_bitmap_base;
++} __attribute__((packed));
++extern struct tss_struct doublefault_tss;
++#else
++struct x86_hw_tss {
++	u32 reserved1;
++	u64 sp0;
++	u64 sp1;
++	u64 sp2;
++	u64 reserved2;
++	u64 ist[7];
++	u32 reserved3;
++	u32 reserved4;
++	u16 reserved5;
++	u16 io_bitmap_base;
++} __attribute__((packed)) ____cacheline_aligned;
++#endif
++#endif /* CONFIG_X86_NO_TSS */
++
++/*
++ * Size of io_bitmap.
++ */
++#define IO_BITMAP_BITS  65536
++#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
++#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
++#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
++#define INVALID_IO_BITMAP_OFFSET 0x8000
++#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
++
++#ifndef CONFIG_X86_NO_TSS
++struct tss_struct {
++	struct x86_hw_tss x86_tss;
++
++	/*
++	 * The extra 1 is there because the CPU will access an
++	 * additional byte beyond the end of the IO permission
++	 * bitmap. The extra byte must be all 1 bits, and must
++	 * be within the limit.
++	 */
++	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
++	/*
++	 * Cache the current maximum and the last task that used the bitmap:
++	 */
++	unsigned long io_bitmap_max;
++	struct thread_struct *io_bitmap_owner;
++	/*
++	 * pads the TSS to be cacheline-aligned (size is 0x100)
++	 */
++	unsigned long __cacheline_filler[35];
++	/*
++	 * .. and then another 0x100 bytes for emergency kernel stack
++	 */
++	unsigned long stack[64];
++} __attribute__((packed));
++
++DECLARE_PER_CPU(struct tss_struct, init_tss);
++
++/* Save the original ist values for checking stack pointers during debugging */
++struct orig_ist {
++	unsigned long ist[7];
++};
++#endif /* CONFIG_X86_NO_TSS */
++
++#define	MXCSR_DEFAULT		0x1f80
++
++struct i387_fsave_struct {
++	u32	cwd;
++	u32	swd;
++	u32	twd;
++	u32	fip;
++	u32	fcs;
++	u32	foo;
++	u32	fos;
++	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
++	u32	status;		/* software status information */
++};
++
++struct i387_fxsave_struct {
++	u16	cwd;
++	u16	swd;
++	u16	twd;
++	u16	fop;
++	union {
++		struct {
++			u64	rip;
++			u64	rdp;
++		};
++		struct {
++			u32	fip;
++			u32	fcs;
++			u32	foo;
++			u32	fos;
++		};
++	};
++	u32	mxcsr;
++	u32	mxcsr_mask;
++	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
++	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
++	u32	padding[24];
++} __attribute__((aligned(16)));
++
++struct i387_soft_struct {
++	u32	cwd;
++	u32	swd;
++	u32	twd;
++	u32	fip;
++	u32	fcs;
++	u32	foo;
++	u32	fos;
++	u32	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
++	u8	ftop, changed, lookahead, no_update, rm, alimit;
++	struct info	*info;
++	u32	entry_eip;
++};
++
++union i387_union {
++	struct i387_fsave_struct	fsave;
++	struct i387_fxsave_struct	fxsave;
++	struct i387_soft_struct 	soft;
++};
++
++#ifdef CONFIG_X86_32
++DECLARE_PER_CPU(u8, cpu_llc_id);
++#elif !defined(CONFIG_X86_NO_TSS)
++DECLARE_PER_CPU(struct orig_ist, orig_ist);
++#endif
++
++extern void print_cpu_info(struct cpuinfo_x86 *);
++extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
++extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
++extern unsigned short num_cache_leaves;
++
++struct thread_struct {
++/* cached TLS descriptors. */
++	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
++	unsigned long	sp0;
++	unsigned long	sp;
++#ifdef CONFIG_X86_32
++	unsigned long	sysenter_cs;
++#else
++	unsigned long 	usersp;	/* Copy from PDA */
++	unsigned short	es, ds, fsindex, gsindex;
++#endif
++	unsigned long	ip;
++	unsigned long	fs;
++	unsigned long	gs;
++/* Hardware debugging registers */
++	unsigned long	debugreg0;
++	unsigned long	debugreg1;
++	unsigned long	debugreg2;
++	unsigned long	debugreg3;
++	unsigned long	debugreg6;
++	unsigned long	debugreg7;
++/* fault info */
++	unsigned long	cr2, trap_no, error_code;
++/* floating point info */
++	union i387_union	i387 __attribute__((aligned(16)));;
++#ifdef CONFIG_X86_32
++/* virtual 86 mode info */
++	struct vm86_struct __user *vm86_info;
++	unsigned long		screen_bitmap;
++	unsigned long		v86flags, v86mask, saved_sp0;
++	unsigned int		saved_fs, saved_gs;
++#endif
++/* IO permissions */
++	unsigned long	*io_bitmap_ptr;
++	unsigned long	iopl;
++/* max allowed port in the bitmap, in bytes: */
++	unsigned io_bitmap_max;
++/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
++	unsigned long	debugctlmsr;
++/* Debug Store - if not 0 points to a DS Save Area configuration;
++ *               goes into MSR_IA32_DS_AREA */
++	unsigned long	ds_area_msr;
++};
++
++static inline unsigned long xen_get_debugreg(int regno)
++{
++	return HYPERVISOR_get_debugreg(regno);
++}
++
++static inline void xen_set_debugreg(int regno, unsigned long value)
++{
++	WARN_ON(HYPERVISOR_set_debugreg(regno, value));
++}
++
++/*
++ * Set IOPL bits in EFLAGS from given mask
++ */
++static inline void xen_set_iopl_mask(unsigned mask)
++{
++	struct physdev_set_iopl set_iopl;
++
++	/* Force the change at ring 0. */
++	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
++}
++
++#ifndef CONFIG_X86_NO_TSS
++static inline void native_load_sp0(struct tss_struct *tss,
++				   struct thread_struct *thread)
++{
++	tss->x86_tss.sp0 = thread->sp0;
++#ifdef CONFIG_X86_32
++	/* Only happens when SEP is enabled, no need to test "SEP"arately */
++	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
++		tss->x86_tss.ss1 = thread->sysenter_cs;
++		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
++	}
++#endif
++}
++#else
++#define xen_load_sp0(tss, thread) do { \
++	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->sp0)) \
++		BUG(); \
++} while (0)
++#endif
++
++#define __cpuid xen_cpuid
++#define paravirt_enabled() 0
++
++/*
++ * These special macros can be used to get or set a debugging register
++ */
++#define get_debugreg(var, register)				\
++	(var) = xen_get_debugreg(register)
++#define set_debugreg(value, register)				\
++	xen_set_debugreg(register, value)
++
++#define load_sp0 xen_load_sp0
++
++#define set_iopl_mask xen_set_iopl_mask
++
++/*
++ * Save the cr4 feature set we're using (ie
++ * Pentium 4MB enable and PPro Global page
++ * enable), so that any CPU's that boot up
++ * after us can get the correct flags.
++ */
++extern unsigned long mmu_cr4_features;
++
++static inline void set_in_cr4(unsigned long mask)
++{
++	unsigned cr4;
++	mmu_cr4_features |= mask;
++	cr4 = read_cr4();
++	cr4 |= mask;
++	write_cr4(cr4);
++}
++
++static inline void clear_in_cr4(unsigned long mask)
++{
++	unsigned cr4;
++	mmu_cr4_features &= ~mask;
++	cr4 = read_cr4();
++	cr4 &= ~mask;
++	write_cr4(cr4);
++}
++
++struct microcode_header {
++	unsigned int hdrver;
++	unsigned int rev;
++	unsigned int date;
++	unsigned int sig;
++	unsigned int cksum;
++	unsigned int ldrver;
++	unsigned int pf;
++	unsigned int datasize;
++	unsigned int totalsize;
++	unsigned int reserved[3];
++};
++
++struct microcode {
++	struct microcode_header hdr;
++	unsigned int bits[0];
++};
++
++typedef struct microcode microcode_t;
++typedef struct microcode_header microcode_header_t;
++
++/* microcode format is extended from prescott processors */
++struct extended_signature {
++	unsigned int sig;
++	unsigned int pf;
++	unsigned int cksum;
++};
++
++struct extended_sigtable {
++	unsigned int count;
++	unsigned int cksum;
++	unsigned int reserved[3];
++	struct extended_signature sigs[0];
++};
++
++typedef struct {
++	unsigned long seg;
++} mm_segment_t;
++
++
++/*
++ * create a kernel thread without removing it from tasklists
++ */
++extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++
++/* Prepare to copy thread state - unlazy all lazy status */
++extern void prepare_to_copy(struct task_struct *tsk);
++
++unsigned long get_wchan(struct task_struct *p);
++
++/*
++ * Generic CPUID function
++ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
++ * resulting in stale register contents being returned.
++ */
++static inline void cpuid(unsigned int op,
++			 unsigned int *eax, unsigned int *ebx,
++			 unsigned int *ecx, unsigned int *edx)
++{
++	*eax = op;
++	*ecx = 0;
++	__cpuid(eax, ebx, ecx, edx);
++}
++
++/* Some CPUID calls want 'count' to be placed in ecx */
++static inline void cpuid_count(unsigned int op, int count,
++			       unsigned int *eax, unsigned int *ebx,
++			       unsigned int *ecx, unsigned int *edx)
++{
++	*eax = op;
++	*ecx = count;
++	__cpuid(eax, ebx, ecx, edx);
++}
++
++/*
++ * CPUID functions returning a single datum
++ */
++static inline unsigned int cpuid_eax(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return eax;
++}
++static inline unsigned int cpuid_ebx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return ebx;
++}
++static inline unsigned int cpuid_ecx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return ecx;
++}
++static inline unsigned int cpuid_edx(unsigned int op)
++{
++	unsigned int eax, ebx, ecx, edx;
++
++	cpuid(op, &eax, &ebx, &ecx, &edx);
++	return edx;
++}
++
++/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
++static inline void rep_nop(void)
++{
++	__asm__ __volatile__("rep;nop": : :"memory");
++}
++
++/* Stop speculative execution */
++static inline void sync_core(void)
++{
++	int tmp;
++	asm volatile("cpuid" : "=a" (tmp) : "0" (1)
++					  : "ebx", "ecx", "edx", "memory");
++}
++
++#define cpu_relax()   rep_nop()
++
++static inline void __monitor(const void *eax, unsigned long ecx,
++		unsigned long edx)
++{
++	/* "monitor %eax,%ecx,%edx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc8;"
++		: :"a" (eax), "c" (ecx), "d"(edx));
++}
++
++static inline void __mwait(unsigned long eax, unsigned long ecx)
++{
++	/* "mwait %eax,%ecx;" */
++	asm volatile(
++		".byte 0x0f,0x01,0xc9;"
++		: :"a" (eax), "c" (ecx));
++}
++
++static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
++{
++	/* "mwait %eax,%ecx;" */
++	asm volatile(
++		"sti; .byte 0x0f,0x01,0xc9;"
++		: :"a" (eax), "c" (ecx));
++}
++
++extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
++
++extern int force_mwait;
++
++extern void select_idle_routine(const struct cpuinfo_x86 *c);
++
++extern unsigned long boot_option_idle_override;
++
++extern void enable_sep_cpu(void);
++extern int sysenter_setup(void);
++
++/* Defined in head.S */
++extern struct desc_ptr early_gdt_descr;
++
++extern void cpu_set_gdt(int);
++extern void switch_to_new_gdt(void);
++extern void cpu_init(void);
++extern void init_gdt(int cpu);
++
++/* from system description table in BIOS.  Mostly for MCA use, but
++ * others may find it useful. */
++extern unsigned int machine_id;
++extern unsigned int machine_submodel_id;
++extern unsigned int BIOS_revision;
++
++/* Boot loader type from the setup header */
++extern int bootloader_type;
++
++extern char ignore_fpu_irq;
++#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
++
++#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
++#define ARCH_HAS_PREFETCHW
++#define ARCH_HAS_SPINLOCK_PREFETCH
++
++#ifdef CONFIG_X86_32
++#define BASE_PREFETCH	ASM_NOP4
++#define ARCH_HAS_PREFETCH
++#else
++#define BASE_PREFETCH	"prefetcht0 (%1)"
++#endif
++
++/* Prefetch instructions for Pentium III and AMD Athlon */
++/* It's not worth to care about 3dnow! prefetches for the K6
++   because they are microcoded there and very slow.
++   However we don't do prefetches for pre XP Athlons currently
++   That should be fixed. */
++static inline void prefetch(const void *x)
++{
++	alternative_input(BASE_PREFETCH,
++			  "prefetchnta (%1)",
++			  X86_FEATURE_XMM,
++			  "r" (x));
++}
++
++/* 3dnow! prefetch to get an exclusive cache line. Useful for
++   spinlocks to avoid one state transition in the cache coherency protocol. */
++static inline void prefetchw(const void *x)
++{
++	alternative_input(BASE_PREFETCH,
++			  "prefetchw (%1)",
++			  X86_FEATURE_3DNOW,
++			  "r" (x));
++}
++
++#define spin_lock_prefetch(x)	prefetchw(x)
+ #ifdef CONFIG_X86_32
+-# include "processor_32.h"
++/*
++ * User space process size: 3GB (default).
++ */
++#define TASK_SIZE	(PAGE_OFFSET)
++#define STACK_TOP	TASK_SIZE
++#define STACK_TOP_MAX	STACK_TOP
++
++#define INIT_THREAD  {							\
++	.sp0 = sizeof(init_stack) + (long)&init_stack,			\
++	.vm86_info = NULL,						\
++	.sysenter_cs = __KERNEL_CS,					\
++	.io_bitmap_ptr = NULL,						\
++	.fs = __KERNEL_PERCPU,						\
++}
++
++/*
++ * Note that the .io_bitmap member must be extra-big. This is because
++ * the CPU will access an additional byte beyond the end of the IO
++ * permission bitmap. The extra byte must be all 1 bits, and must
++ * be within the limit.
++ */
++#define INIT_TSS  {							\
++	.x86_tss = {							\
++		.sp0		= sizeof(init_stack) + (long)&init_stack, \
++		.ss0		= __KERNEL_DS,				\
++		.ss1		= __KERNEL_CS,				\
++		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
++	 },								\
++	.io_bitmap	= { [0 ... IO_BITMAP_LONGS] = ~0 },		\
++}
++
++#define start_thread(regs, new_eip, new_esp) do {		\
++	__asm__("movl %0,%%gs": :"r" (0));			\
++	regs->fs = 0;						\
++	set_fs(USER_DS);					\
++	regs->ds = __USER_DS;					\
++	regs->es = __USER_DS;					\
++	regs->ss = __USER_DS;					\
++	regs->cs = __USER_CS;					\
++	regs->ip = new_eip;					\
++	regs->sp = new_esp;					\
++} while (0)
++
++
++extern unsigned long thread_saved_pc(struct task_struct *tsk);
++
++#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
++#define KSTK_TOP(info)                                                 \
++({                                                                     \
++       unsigned long *__ptr = (unsigned long *)(info);                 \
++       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
++})
++
++/*
++ * The below -8 is to reserve 8 bytes on top of the ring0 stack.
++ * This is necessary to guarantee that the entire "struct pt_regs"
++ * is accessable even if the CPU haven't stored the SS/ESP registers
++ * on the stack (interrupt gate does not save these registers
++ * when switching to the same priv ring).
++ * Therefore beware: accessing the ss/esp fields of the
++ * "struct pt_regs" is possible, but they may contain the
++ * completely wrong values.
++ */
++#define task_pt_regs(task)                                             \
++({                                                                     \
++       struct pt_regs *__regs__;                                       \
++       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
++       __regs__ - 1;                                                   \
++})
++
++#define KSTK_ESP(task) (task_pt_regs(task)->sp)
++
+ #else
+-# include "processor_64.h"
++/*
++ * User space process size. 47bits minus one guard page.
++ */
++#define TASK_SIZE64	(0x800000000000UL - 4096)
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \
++			   0xc0000000 : 0xFFFFe000)
++
++#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? \
++				 IA32_PAGE_OFFSET : TASK_SIZE64)
++#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? \
++				  IA32_PAGE_OFFSET : TASK_SIZE64)
++
++#define STACK_TOP		TASK_SIZE
++#define STACK_TOP_MAX		TASK_SIZE64
++
++#define INIT_THREAD  { \
++	.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++}
++
++#define INIT_TSS  { \
++	.x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
++}
++
++#define start_thread(regs, new_rip, new_rsp) do { 			     \
++	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));  \
++	load_gs_index(0);						     \
++	(regs)->ip = (new_rip);						     \
++	(regs)->sp = (new_rsp);						     \
++	write_pda(oldrsp, (new_rsp));					     \
++	(regs)->cs = __USER_CS;						     \
++	(regs)->ss = __USER_DS;						     \
++	(regs)->flags = 0x200;						     \
++	set_fs(USER_DS);						     \
++} while (0)
++
++/*
++ * Return saved PC of a blocked thread.
++ * What is this good for? it will be always the scheduler or ret_from_fork.
++ */
++#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.sp - 8))
++
++#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1)
++#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
++#endif /* CONFIG_X86_64 */
++
++/* This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
++
++#define KSTK_EIP(task) (task_pt_regs(task)->ip)
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,751 +0,0 @@
+-/*
+- * include/asm-i386/processor.h
+- *
+- * Copyright (C) 1994 Linus Torvalds
+- */
+-
+-#ifndef __ASM_I386_PROCESSOR_H
+-#define __ASM_I386_PROCESSOR_H
+-
+-#include <asm/vm86.h>
+-#include <asm/math_emu.h>
+-#include <asm/segment.h>
+-#include <asm/page.h>
+-#include <asm/types.h>
+-#include <asm/sigcontext.h>
+-#include <asm/cpufeature.h>
+-#include <asm/msr.h>
+-#include <asm/system.h>
+-#include <linux/cache.h>
+-#include <linux/threads.h>
+-#include <asm/percpu.h>
+-#include <linux/cpumask.h>
+-#include <linux/init.h>
+-#include <asm/processor-flags.h>
+-#include <xen/interface/physdev.h>
+-
+-/* flag for disabling the tsc */
+-#define tsc_disable 0
+-
+-struct desc_struct {
+-	unsigned long a,b;
+-};
+-
+-#define desc_empty(desc) \
+-		(!((desc)->a | (desc)->b))
+-
+-#define desc_equal(desc1, desc2) \
+-		(((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
+-/*
+- * Default implementation of macro that returns current
+- * instruction pointer ("program counter").
+- */
+-#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+-
+-/*
+- *  CPU type and hardware bug flags. Kept separately for each CPU.
+- *  Members of this structure are referenced in head.S, so think twice
+- *  before touching them. [mj]
+- */
+-
+-struct cpuinfo_x86 {
+-	__u8	x86;		/* CPU family */
+-	__u8	x86_vendor;	/* CPU vendor */
+-	__u8	x86_model;
+-	__u8	x86_mask;
+-	char	wp_works_ok;	/* It doesn't on 386's */
+-	char	hlt_works_ok;	/* Problems on some 486Dx4's and old 386's */
+-	char	hard_math;
+-	char	rfu;
+-       	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
+-	unsigned long	x86_capability[NCAPINTS];
+-	char	x86_vendor_id[16];
+-	char	x86_model_id[64];
+-	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
+-				    call  */
+-	int 	x86_cache_alignment;	/* In bytes */
+-	char	fdiv_bug;
+-	char	f00f_bug;
+-	char	coma_bug;
+-	char	pad0;
+-	int	x86_power;
+-	unsigned long loops_per_jiffy;
+-#ifdef CONFIG_SMP
+-	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
+-#endif
+-	unsigned char x86_max_cores;	/* cpuid returned max cores value */
+-	unsigned char apicid;
+-	unsigned short x86_clflush_size;
+-#ifdef CONFIG_SMP
+-	unsigned char booted_cores;	/* number of cores as seen by OS */
+-	__u8 phys_proc_id; 		/* Physical processor id. */
+-	__u8 cpu_core_id;  		/* Core id */
+-	__u8 cpu_index;			/* index into per_cpu list */
+-#endif
+-} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+-
+-#define X86_VENDOR_INTEL 0
+-#define X86_VENDOR_CYRIX 1
+-#define X86_VENDOR_AMD 2
+-#define X86_VENDOR_UMC 3
+-#define X86_VENDOR_NEXGEN 4
+-#define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_TRANSMETA 7
+-#define X86_VENDOR_NSC 8
+-#define X86_VENDOR_NUM 9
+-#define X86_VENDOR_UNKNOWN 0xff
+-
+-/*
+- * capabilities of CPUs
+- */
+-
+-extern struct cpuinfo_x86 boot_cpu_data;
+-extern struct cpuinfo_x86 new_cpu_data;
+-#ifndef CONFIG_X86_NO_TSS
+-extern struct tss_struct doublefault_tss;
+-DECLARE_PER_CPU(struct tss_struct, init_tss);
+-#endif
+-
+-#ifdef CONFIG_SMP
+-DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+-#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+-#define current_cpu_data	cpu_data(smp_processor_id())
+-#else
+-#define cpu_data(cpu)		boot_cpu_data
+-#define current_cpu_data	boot_cpu_data
+-#endif
+-
+-/*
+- * the following now lives in the per cpu area:
+- * extern	int cpu_llc_id[NR_CPUS];
+- */
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-extern char ignore_fpu_irq;
+-
+-void __init cpu_detect(struct cpuinfo_x86 *c);
+-
+-extern void identify_boot_cpu(void);
+-extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+-extern void print_cpu_info(struct cpuinfo_x86 *);
+-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+-extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+-extern unsigned short num_cache_leaves;
+-
+-#ifdef CONFIG_X86_HT
+-extern void detect_ht(struct cpuinfo_x86 *c);
+-#else
+-static inline void detect_ht(struct cpuinfo_x86 *c) {}
+-#endif
+-
+-static inline void xen_cpuid(unsigned int *eax, unsigned int *ebx,
+-			     unsigned int *ecx, unsigned int *edx)
+-{
+-	/* ecx is often an input as well as an output. */
+-	__asm__(XEN_CPUID
+-		: "=a" (*eax),
+-		  "=b" (*ebx),
+-		  "=c" (*ecx),
+-		  "=d" (*edx)
+-		: "0" (*eax), "2" (*ecx));
+-}
+-
+-#define load_cr3(pgdir) write_cr3(__pa(pgdir))
+-
+-/*
+- * Save the cr4 feature set we're using (ie
+- * Pentium 4MB enable and PPro Global page
+- * enable), so that any CPU's that boot up
+- * after us can get the correct flags.
+- */
+-extern unsigned long mmu_cr4_features;
+-
+-static inline void set_in_cr4 (unsigned long mask)
+-{
+-	unsigned cr4;
+-	mmu_cr4_features |= mask;
+-	cr4 = read_cr4();
+-	cr4 |= mask;
+-	write_cr4(cr4);
+-}
+-
+-static inline void clear_in_cr4 (unsigned long mask)
+-{
+-	unsigned cr4;
+-	mmu_cr4_features &= ~mask;
+-	cr4 = read_cr4();
+-	cr4 &= ~mask;
+-	write_cr4(cr4);
+-}
+-
+-/* Stop speculative execution */
+-static inline void sync_core(void)
+-{
+-	int tmp;
+-	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
+-}
+-
+-static inline void __monitor(const void *eax, unsigned long ecx,
+-		unsigned long edx)
+-{
+-	/* "monitor %eax,%ecx,%edx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc8;"
+-		: :"a" (eax), "c" (ecx), "d"(edx));
+-}
+-
+-static inline void __mwait(unsigned long eax, unsigned long ecx)
+-{
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
+-}
+-
+-extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+-
+-/* from system description table in BIOS.  Mostly for MCA use, but
+-others may find it useful. */
+-extern unsigned int machine_id;
+-extern unsigned int machine_submodel_id;
+-extern unsigned int BIOS_revision;
+-extern unsigned int mca_pentium_flag;
+-
+-/* Boot loader type from the setup header */
+-extern int bootloader_type;
+-
+-/*
+- * User space process size: 3GB (default).
+- */
+-#define TASK_SIZE	(PAGE_OFFSET)
+-
+-/* This decides where the kernel will search for a free chunk of vm
+- * space during mmap's.
+- */
+-#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+-
+-#define HAVE_ARCH_PICK_MMAP_LAYOUT
+-
+-extern void hard_disable_TSC(void);
+-extern void disable_TSC(void);
+-extern void hard_enable_TSC(void);
+-
+-/*
+- * Size of io_bitmap.
+- */
+-#define IO_BITMAP_BITS  65536
+-#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+-#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+-#ifndef CONFIG_X86_NO_TSS
+-#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
+-#endif
+-#define INVALID_IO_BITMAP_OFFSET 0x8000
+-#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
+-
+-struct i387_fsave_struct {
+-	long	cwd;
+-	long	swd;
+-	long	twd;
+-	long	fip;
+-	long	fcs;
+-	long	foo;
+-	long	fos;
+-	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	long	status;		/* software status information */
+-};
+-
+-struct i387_fxsave_struct {
+-	unsigned short	cwd;
+-	unsigned short	swd;
+-	unsigned short	twd;
+-	unsigned short	fop;
+-	long	fip;
+-	long	fcs;
+-	long	foo;
+-	long	fos;
+-	long	mxcsr;
+-	long	mxcsr_mask;
+-	long	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
+-	long	xmm_space[32];	/* 8*16 bytes for each XMM-reg = 128 bytes */
+-	long	padding[56];
+-} __attribute__ ((aligned (16)));
+-
+-struct i387_soft_struct {
+-	long	cwd;
+-	long	swd;
+-	long	twd;
+-	long	fip;
+-	long	fcs;
+-	long	foo;
+-	long	fos;
+-	long	st_space[20];	/* 8*10 bytes for each FP-reg = 80 bytes */
+-	unsigned char	ftop, changed, lookahead, no_update, rm, alimit;
+-	struct info	*info;
+-	unsigned long	entry_eip;
+-};
+-
+-union i387_union {
+-	struct i387_fsave_struct	fsave;
+-	struct i387_fxsave_struct	fxsave;
+-	struct i387_soft_struct soft;
+-};
+-
+-typedef struct {
+-	unsigned long seg;
+-} mm_segment_t;
+-
+-struct thread_struct;
+-
+-#ifndef CONFIG_X86_NO_TSS
+-/* This is the TSS defined by the hardware. */
+-struct i386_hw_tss {
+-	unsigned short	back_link,__blh;
+-	unsigned long	esp0;
+-	unsigned short	ss0,__ss0h;
+-	unsigned long	esp1;
+-	unsigned short	ss1,__ss1h;	/* ss1 is used to cache MSR_IA32_SYSENTER_CS */
+-	unsigned long	esp2;
+-	unsigned short	ss2,__ss2h;
+-	unsigned long	__cr3;
+-	unsigned long	eip;
+-	unsigned long	eflags;
+-	unsigned long	eax,ecx,edx,ebx;
+-	unsigned long	esp;
+-	unsigned long	ebp;
+-	unsigned long	esi;
+-	unsigned long	edi;
+-	unsigned short	es, __esh;
+-	unsigned short	cs, __csh;
+-	unsigned short	ss, __ssh;
+-	unsigned short	ds, __dsh;
+-	unsigned short	fs, __fsh;
+-	unsigned short	gs, __gsh;
+-	unsigned short	ldt, __ldth;
+-	unsigned short	trace, io_bitmap_base;
+-} __attribute__((packed));
+-
+-struct tss_struct {
+-	struct i386_hw_tss x86_tss;
+-
+-	/*
+-	 * The extra 1 is there because the CPU will access an
+-	 * additional byte beyond the end of the IO permission
+-	 * bitmap. The extra byte must be all 1 bits, and must
+-	 * be within the limit.
+-	 */
+-	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
+-	/*
+-	 * Cache the current maximum and the last task that used the bitmap:
+-	 */
+-	unsigned long io_bitmap_max;
+-	struct thread_struct *io_bitmap_owner;
+-	/*
+-	 * pads the TSS to be cacheline-aligned (size is 0x100)
+-	 */
+-	unsigned long __cacheline_filler[35];
+-	/*
+-	 * .. and then another 0x100 bytes for emergency kernel stack
+-	 */
+-	unsigned long stack[64];
+-} __attribute__((packed));
+-#endif
+-
+-#define ARCH_MIN_TASKALIGN	16
+-
+-struct thread_struct {
+-/* cached TLS descriptors. */
+-	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
+-	unsigned long	esp0;
+-	unsigned long	sysenter_cs;
+-	unsigned long	eip;
+-	unsigned long	esp;
+-	unsigned long	fs;
+-	unsigned long	gs;
+-/* Hardware debugging registers */
+-	unsigned long	debugreg[8];  /* %%db0-7 debug registers */
+-/* fault info */
+-	unsigned long	cr2, trap_no, error_code;
+-/* floating point info */
+-	union i387_union	i387;
+-/* virtual 86 mode info */
+-	struct vm86_struct __user * vm86_info;
+-	unsigned long		screen_bitmap;
+-	unsigned long		v86flags, v86mask, saved_esp0;
+-	unsigned int		saved_fs, saved_gs;
+-/* IO permissions */
+-	unsigned long	*io_bitmap_ptr;
+- 	unsigned long	iopl;
+-/* max allowed port in the bitmap, in bytes: */
+-	unsigned long	io_bitmap_max;
+-};
+-
+-#define INIT_THREAD  {							\
+-	.esp0 = sizeof(init_stack) + (long)&init_stack,			\
+-	.vm86_info = NULL,						\
+-	.sysenter_cs = __KERNEL_CS,					\
+-	.io_bitmap_ptr = NULL,						\
+-	.fs = __KERNEL_PERCPU,						\
+-}
+-
+-/*
+- * Note that the .io_bitmap member must be extra-big. This is because
+- * the CPU will access an additional byte beyond the end of the IO
+- * permission bitmap. The extra byte must be all 1 bits, and must
+- * be within the limit.
+- */
+-#define INIT_TSS  {							\
+-	.x86_tss = {							\
+-		.esp0		= sizeof(init_stack) + (long)&init_stack, \
+-		.ss0		= __KERNEL_DS,				\
+-		.ss1		= __KERNEL_CS,				\
+-		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		\
+-	 },								\
+-	.io_bitmap	= { [ 0 ... IO_BITMAP_LONGS] = ~0 },		\
+-}
+-
+-#define start_thread(regs, new_eip, new_esp) do {		\
+-	__asm__("movl %0,%%gs": :"r" (0));			\
+-	regs->xfs = 0;						\
+-	set_fs(USER_DS);					\
+-	regs->xds = __USER_DS;					\
+-	regs->xes = __USER_DS;					\
+-	regs->xss = __USER_DS;					\
+-	regs->xcs = __USER_CS;					\
+-	regs->eip = new_eip;					\
+-	regs->esp = new_esp;					\
+-} while (0)
+-
+-/* Forward declaration, a strange C thing */
+-struct task_struct;
+-struct mm_struct;
+-
+-/* Free all resources held by a thread. */
+-extern void release_thread(struct task_struct *);
+-
+-/* Prepare to copy thread state - unlazy all lazy status */
+-extern void prepare_to_copy(struct task_struct *tsk);
+-
+-/*
+- * create a kernel thread without removing it from tasklists
+- */
+-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+-
+-extern unsigned long thread_saved_pc(struct task_struct *tsk);
+-void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack);
+-
+-unsigned long get_wchan(struct task_struct *p);
+-
+-#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
+-#define KSTK_TOP(info)                                                 \
+-({                                                                     \
+-       unsigned long *__ptr = (unsigned long *)(info);                 \
+-       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
+-})
+-
+-/*
+- * The below -8 is to reserve 8 bytes on top of the ring0 stack.
+- * This is necessary to guarantee that the entire "struct pt_regs"
+- * is accessable even if the CPU haven't stored the SS/ESP registers
+- * on the stack (interrupt gate does not save these registers
+- * when switching to the same priv ring).
+- * Therefore beware: accessing the xss/esp fields of the
+- * "struct pt_regs" is possible, but they may contain the
+- * completely wrong values.
+- */
+-#define task_pt_regs(task)                                             \
+-({                                                                     \
+-       struct pt_regs *__regs__;                                       \
+-       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
+-       __regs__ - 1;                                                   \
+-})
+-
+-#define KSTK_EIP(task) (task_pt_regs(task)->eip)
+-#define KSTK_ESP(task) (task_pt_regs(task)->esp)
+-
+-
+-struct microcode_header {
+-	unsigned int hdrver;
+-	unsigned int rev;
+-	unsigned int date;
+-	unsigned int sig;
+-	unsigned int cksum;
+-	unsigned int ldrver;
+-	unsigned int pf;
+-	unsigned int datasize;
+-	unsigned int totalsize;
+-	unsigned int reserved[3];
+-};
+-
+-struct microcode {
+-	struct microcode_header hdr;
+-	unsigned int bits[0];
+-};
+-
+-typedef struct microcode microcode_t;
+-typedef struct microcode_header microcode_header_t;
+-
+-/* microcode format is extended from prescott processors */
+-struct extended_signature {
+-	unsigned int sig;
+-	unsigned int pf;
+-	unsigned int cksum;
+-};
+-
+-struct extended_sigtable {
+-	unsigned int count;
+-	unsigned int cksum;
+-	unsigned int reserved[3];
+-	struct extended_signature sigs[0];
+-};
+-
+-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+-static inline void rep_nop(void)
+-{
+-	__asm__ __volatile__("rep;nop": : :"memory");
+-}
+-
+-#define cpu_relax()	rep_nop()
+-
+-#ifndef CONFIG_X86_NO_TSS
+-static inline void native_load_esp0(struct tss_struct *tss, struct thread_struct *thread)
+-{
+-	tss->x86_tss.esp0 = thread->esp0;
+-	/* This can only happen when SEP is enabled, no need to test "SEP"arately */
+-	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+-		tss->x86_tss.ss1 = thread->sysenter_cs;
+-		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+-	}
+-}
+-#else
+-#define xen_load_esp0(tss, thread) do { \
+-	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->esp0)) \
+-		BUG(); \
+-} while (0)
+-#endif
+-
+-
+-static inline unsigned long xen_get_debugreg(int regno)
+-{
+-	return HYPERVISOR_get_debugreg(regno);
+-}
+-
+-static inline void xen_set_debugreg(int regno, unsigned long value)
+-{
+-	WARN_ON(HYPERVISOR_set_debugreg(regno, value));
+-}
+-
+-/*
+- * Set IOPL bits in EFLAGS from given mask
+- */
+-static inline void xen_set_iopl_mask(unsigned mask)
+-{
+-	struct physdev_set_iopl set_iopl;
+-
+-	/* Force the change at ring 0. */
+-	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+-}
+-
+-
+-#define paravirt_enabled() 0
+-#define __cpuid xen_cpuid
+-
+-#define load_esp0 xen_load_esp0
+-
+-/*
+- * These special macros can be used to get or set a debugging register
+- */
+-#define get_debugreg(var, register)				\
+-	(var) = xen_get_debugreg(register)
+-#define set_debugreg(value, register)				\
+-	xen_set_debugreg(register, value)
+-
+-#define set_iopl_mask xen_set_iopl_mask
+-
+-/*
+- * Generic CPUID function
+- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+- * resulting in stale register contents being returned.
+- */
+-static inline void cpuid(unsigned int op,
+-			 unsigned int *eax, unsigned int *ebx,
+-			 unsigned int *ecx, unsigned int *edx)
+-{
+-	*eax = op;
+-	*ecx = 0;
+-	__cpuid(eax, ebx, ecx, edx);
+-}
+-
+-/* Some CPUID calls want 'count' to be placed in ecx */
+-static inline void cpuid_count(unsigned int op, int count,
+-			       unsigned int *eax, unsigned int *ebx,
+-			       unsigned int *ecx, unsigned int *edx)
+-{
+-	*eax = op;
+-	*ecx = count;
+-	__cpuid(eax, ebx, ecx, edx);
+-}
+-
+-/*
+- * CPUID functions returning a single datum
+- */
+-static inline unsigned int cpuid_eax(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return eax;
+-}
+-static inline unsigned int cpuid_ebx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return ebx;
+-}
+-static inline unsigned int cpuid_ecx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return ecx;
+-}
+-static inline unsigned int cpuid_edx(unsigned int op)
+-{
+-	unsigned int eax, ebx, ecx, edx;
+-
+-	cpuid(op, &eax, &ebx, &ecx, &edx);
+-	return edx;
+-}
+-
+-/* generic versions from gas */
+-#define GENERIC_NOP1	".byte 0x90\n"
+-#define GENERIC_NOP2    	".byte 0x89,0xf6\n"
+-#define GENERIC_NOP3        ".byte 0x8d,0x76,0x00\n"
+-#define GENERIC_NOP4        ".byte 0x8d,0x74,0x26,0x00\n"
+-#define GENERIC_NOP5        GENERIC_NOP1 GENERIC_NOP4
+-#define GENERIC_NOP6	".byte 0x8d,0xb6,0x00,0x00,0x00,0x00\n"
+-#define GENERIC_NOP7	".byte 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00\n"
+-#define GENERIC_NOP8	GENERIC_NOP1 GENERIC_NOP7
+-
+-/* Opteron nops */
+-#define K8_NOP1 GENERIC_NOP1
+-#define K8_NOP2	".byte 0x66,0x90\n" 
+-#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
+-#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
+-#define K8_NOP5	K8_NOP3 K8_NOP2 
+-#define K8_NOP6	K8_NOP3 K8_NOP3
+-#define K8_NOP7	K8_NOP4 K8_NOP3
+-#define K8_NOP8	K8_NOP4 K8_NOP4
+-
+-/* K7 nops */
+-/* uses eax dependencies (arbitary choice) */
+-#define K7_NOP1  GENERIC_NOP1
+-#define K7_NOP2	".byte 0x8b,0xc0\n" 
+-#define K7_NOP3	".byte 0x8d,0x04,0x20\n"
+-#define K7_NOP4	".byte 0x8d,0x44,0x20,0x00\n"
+-#define K7_NOP5	K7_NOP4 ASM_NOP1
+-#define K7_NOP6	".byte 0x8d,0x80,0,0,0,0\n"
+-#define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
+-#define K7_NOP8        K7_NOP7 ASM_NOP1
+-
+-/* P6 nops */
+-/* uses eax dependencies (Intel-recommended choice) */
+-#define P6_NOP1	GENERIC_NOP1
+-#define P6_NOP2	".byte 0x66,0x90\n"
+-#define P6_NOP3	".byte 0x0f,0x1f,0x00\n"
+-#define P6_NOP4	".byte 0x0f,0x1f,0x40,0\n"
+-#define P6_NOP5	".byte 0x0f,0x1f,0x44,0x00,0\n"
+-#define P6_NOP6	".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
+-#define P6_NOP7	".byte 0x0f,0x1f,0x80,0,0,0,0\n"
+-#define P6_NOP8	".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
+-
+-#ifdef CONFIG_MK8
+-#define ASM_NOP1 K8_NOP1
+-#define ASM_NOP2 K8_NOP2
+-#define ASM_NOP3 K8_NOP3
+-#define ASM_NOP4 K8_NOP4
+-#define ASM_NOP5 K8_NOP5
+-#define ASM_NOP6 K8_NOP6
+-#define ASM_NOP7 K8_NOP7
+-#define ASM_NOP8 K8_NOP8
+-#elif defined(CONFIG_MK7)
+-#define ASM_NOP1 K7_NOP1
+-#define ASM_NOP2 K7_NOP2
+-#define ASM_NOP3 K7_NOP3
+-#define ASM_NOP4 K7_NOP4
+-#define ASM_NOP5 K7_NOP5
+-#define ASM_NOP6 K7_NOP6
+-#define ASM_NOP7 K7_NOP7
+-#define ASM_NOP8 K7_NOP8
+-#elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
+-      defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \
+-      defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4)
+-#define ASM_NOP1 P6_NOP1
+-#define ASM_NOP2 P6_NOP2
+-#define ASM_NOP3 P6_NOP3
+-#define ASM_NOP4 P6_NOP4
+-#define ASM_NOP5 P6_NOP5
+-#define ASM_NOP6 P6_NOP6
+-#define ASM_NOP7 P6_NOP7
+-#define ASM_NOP8 P6_NOP8
+-#else
+-#define ASM_NOP1 GENERIC_NOP1
+-#define ASM_NOP2 GENERIC_NOP2
+-#define ASM_NOP3 GENERIC_NOP3
+-#define ASM_NOP4 GENERIC_NOP4
+-#define ASM_NOP5 GENERIC_NOP5
+-#define ASM_NOP6 GENERIC_NOP6
+-#define ASM_NOP7 GENERIC_NOP7
+-#define ASM_NOP8 GENERIC_NOP8
+-#endif
+-
+-#define ASM_NOP_MAX 8
+-
+-/* Prefetch instructions for Pentium III and AMD Athlon */
+-/* It's not worth to care about 3dnow! prefetches for the K6
+-   because they are microcoded there and very slow.
+-   However we don't do prefetches for pre XP Athlons currently
+-   That should be fixed. */
+-#define ARCH_HAS_PREFETCH
+-static inline void prefetch(const void *x)
+-{
+-	alternative_input(ASM_NOP4,
+-			  "prefetchnta (%1)",
+-			  X86_FEATURE_XMM,
+-			  "r" (x));
+-}
+-
+-#define ARCH_HAS_PREFETCH
+-#define ARCH_HAS_PREFETCHW
+-#define ARCH_HAS_SPINLOCK_PREFETCH
+-
+-/* 3dnow! prefetch to get an exclusive cache line. Useful for 
+-   spinlocks to avoid one state transition in the cache coherency protocol. */
+-static inline void prefetchw(const void *x)
+-{
+-	alternative_input(ASM_NOP4,
+-			  "prefetchw (%1)",
+-			  X86_FEATURE_3DNOW,
+-			  "r" (x));
+-}
+-#define spin_lock_prefetch(x)	prefetchw(x)
+-
+-extern void select_idle_routine(const struct cpuinfo_x86 *c);
+-
+-#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
+-
+-extern unsigned long boot_option_idle_override;
+-extern void enable_sep_cpu(void);
+-extern int sysenter_setup(void);
+-
+-/* Defined in head.S */
+-extern struct Xgt_desc_struct early_gdt_descr;
+-
+-extern void cpu_set_gdt(int);
+-extern void switch_to_new_gdt(void);
+-extern void cpu_init(void);
+-extern void init_gdt(int cpu);
+-
+-extern int force_mwait;
+-
+-#endif /* __ASM_I386_PROCESSOR_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,461 +0,0 @@
+-/*
+- * include/asm-x86_64/processor.h
+- *
+- * Copyright (C) 1994 Linus Torvalds
+- */
+-
+-#ifndef __ASM_X86_64_PROCESSOR_H
+-#define __ASM_X86_64_PROCESSOR_H
+-
+-#include <asm/segment.h>
+-#include <asm/page.h>
+-#include <asm/types.h>
+-#include <asm/sigcontext.h>
+-#include <asm/cpufeature.h>
+-#include <linux/threads.h>
+-#include <asm/msr.h>
+-#include <asm/current.h>
+-#include <asm/system.h>
+-#include <asm/mmsegment.h>
+-#include <asm/percpu.h>
+-#include <linux/personality.h>
+-#include <linux/cpumask.h>
+-#include <asm/processor-flags.h>
+-
+-#define TF_MASK		0x00000100
+-#define IF_MASK		0x00000200
+-#define IOPL_MASK	0x00003000
+-#define NT_MASK		0x00004000
+-#define VM_MASK		0x00020000
+-#define AC_MASK		0x00040000
+-#define VIF_MASK	0x00080000	/* virtual interrupt flag */
+-#define VIP_MASK	0x00100000	/* virtual interrupt pending */
+-#define ID_MASK		0x00200000
+-
+-#define desc_empty(desc) \
+-               (!((desc)->a | (desc)->b))
+-
+-#define desc_equal(desc1, desc2) \
+-               (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
+-
+-/*
+- * Default implementation of macro that returns current
+- * instruction pointer ("program counter").
+- */
+-#define current_text_addr() ({ void *pc; asm volatile("leaq 1f(%%rip),%0\n1:":"=r"(pc)); pc; })
+-
+-/*
+- *  CPU type and hardware bug flags. Kept separately for each CPU.
+- */
+-
+-struct cpuinfo_x86 {
+-	__u8	x86;		/* CPU family */
+-	__u8	x86_vendor;	/* CPU vendor */
+-	__u8	x86_model;
+-	__u8	x86_mask;
+-	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
+-	__u32	x86_capability[NCAPINTS];
+-	char	x86_vendor_id[16];
+-	char	x86_model_id[64];
+-	int 	x86_cache_size;  /* in KB */
+-	int	x86_clflush_size;
+-	int	x86_cache_alignment;
+-	int	x86_tlbsize;	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
+-        __u8    x86_virt_bits, x86_phys_bits;
+-	__u8	x86_max_cores;	/* cpuid returned max cores value */
+-        __u32   x86_power; 	
+-	__u32   extended_cpuid_level;	/* Max extended CPUID function supported */
+-	unsigned long loops_per_jiffy;
+-#ifdef CONFIG_SMP
+-	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
+-#endif
+-	__u8	apicid;
+-#ifdef CONFIG_SMP
+-	__u8	booted_cores;	/* number of cores as seen by OS */
+-	__u8	phys_proc_id;	/* Physical Processor id. */
+-	__u8	cpu_core_id;	/* Core id. */
+-	__u8	cpu_index;	/* index into per_cpu list */
+-#endif
+-} ____cacheline_aligned;
+-
+-#define X86_VENDOR_INTEL 0
+-#define X86_VENDOR_CYRIX 1
+-#define X86_VENDOR_AMD 2
+-#define X86_VENDOR_UMC 3
+-#define X86_VENDOR_NEXGEN 4
+-#define X86_VENDOR_CENTAUR 5
+-#define X86_VENDOR_TRANSMETA 7
+-#define X86_VENDOR_NUM 8
+-#define X86_VENDOR_UNKNOWN 0xff
+-
+-#ifdef CONFIG_SMP
+-DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+-#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+-#define current_cpu_data	cpu_data(smp_processor_id())
+-#else
+-#define cpu_data(cpu)		boot_cpu_data
+-#define current_cpu_data	boot_cpu_data
+-#endif
+-
+-extern char ignore_irq13;
+-
+-extern void identify_cpu(struct cpuinfo_x86 *);
+-extern void print_cpu_info(struct cpuinfo_x86 *);
+-extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+-extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+-extern unsigned short num_cache_leaves;
+-
+-/*
+- * Save the cr4 feature set we're using (ie
+- * Pentium 4MB enable and PPro Global page
+- * enable), so that any CPU's that boot up
+- * after us can get the correct flags.
+- */
+-extern unsigned long mmu_cr4_features;
+-
+-static inline void set_in_cr4 (unsigned long mask)
+-{
+-	mmu_cr4_features |= mask;
+-	__asm__("movq %%cr4,%%rax\n\t"
+-		"orq %0,%%rax\n\t"
+-		"movq %%rax,%%cr4\n"
+-		: : "irg" (mask)
+-		:"ax");
+-}
+-
+-static inline void clear_in_cr4 (unsigned long mask)
+-{
+-	mmu_cr4_features &= ~mask;
+-	__asm__("movq %%cr4,%%rax\n\t"
+-		"andq %0,%%rax\n\t"
+-		"movq %%rax,%%cr4\n"
+-		: : "irg" (~mask)
+-		:"ax");
+-}
+-
+-
+-/*
+- * User space process size. 47bits minus one guard page.
+- */
+-#define TASK_SIZE64	(0x800000000000UL - 4096)
+-
+-/* This decides where the kernel will search for a free chunk of vm
+- * space during mmap's.
+- */
+-#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
+-
+-#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+-#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+-
+-#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE/3)
+-
+-/*
+- * Size of io_bitmap.
+- */
+-#define IO_BITMAP_BITS  65536
+-#define IO_BITMAP_BYTES (IO_BITMAP_BITS/8)
+-#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
+-#ifndef CONFIG_X86_NO_TSS
+-#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
+-#endif
+-#define INVALID_IO_BITMAP_OFFSET 0x8000
+-
+-struct i387_fxsave_struct {
+-	u16	cwd;
+-	u16	swd;
+-	u16	twd;
+-	u16	fop;
+-	u64	rip;
+-	u64	rdp; 
+-	u32	mxcsr;
+-	u32	mxcsr_mask;
+-	u32	st_space[32];	/* 8*16 bytes for each FP-reg = 128 bytes */
+-	u32	xmm_space[64];	/* 16*16 bytes for each XMM-reg = 256 bytes */
+-	u32	padding[24];
+-} __attribute__ ((aligned (16)));
+-
+-union i387_union {
+-	struct i387_fxsave_struct	fxsave;
+-};
+-
+-#ifndef CONFIG_X86_NO_TSS
+-struct tss_struct {
+-	u32 reserved1;
+-	u64 rsp0;	
+-	u64 rsp1;
+-	u64 rsp2;
+-	u64 reserved2;
+-	u64 ist[7];
+-	u32 reserved3;
+-	u32 reserved4;
+-	u16 reserved5;
+-	u16 io_bitmap_base;
+-	/*
+-	 * The extra 1 is there because the CPU will access an
+-	 * additional byte beyond the end of the IO permission
+-	 * bitmap. The extra byte must be all 1 bits, and must
+-	 * be within the limit. Thus we have:
+-	 *
+-	 * 128 bytes, the bitmap itself, for ports 0..0x3ff
+-	 * 8 bytes, for an extra "long" of ~0UL
+-	 */
+-	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
+-} __attribute__((packed)) ____cacheline_aligned;
+-
+-DECLARE_PER_CPU(struct tss_struct,init_tss);
+-#endif
+-
+-
+-extern struct cpuinfo_x86 boot_cpu_data;
+-#ifndef CONFIG_X86_NO_TSS
+-/* Save the original ist values for checking stack pointers during debugging */
+-struct orig_ist {
+-	unsigned long ist[7];
+-};
+-DECLARE_PER_CPU(struct orig_ist, orig_ist);
+-#endif
+-
+-#ifdef CONFIG_X86_VSMP
+-#define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
+-#define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
+-#else
+-#define ARCH_MIN_TASKALIGN	16
+-#define ARCH_MIN_MMSTRUCT_ALIGN	0
+-#endif
+-
+-struct thread_struct {
+-	unsigned long	rsp0;
+-	unsigned long	rsp;
+-	unsigned long 	userrsp;	/* Copy from PDA */ 
+-	unsigned long	fs;
+-	unsigned long	gs;
+-	unsigned short	es, ds, fsindex, gsindex;	
+-/* Hardware debugging registers */
+-	unsigned long	debugreg0;  
+-	unsigned long	debugreg1;  
+-	unsigned long	debugreg2;  
+-	unsigned long	debugreg3;  
+-	unsigned long	debugreg6;  
+-	unsigned long	debugreg7;  
+-/* fault info */
+-	unsigned long	cr2, trap_no, error_code;
+-/* floating point info */
+-	union i387_union	i387  __attribute__((aligned(16)));
+-/* IO permissions. the bitmap could be moved into the GDT, that would make
+-   switch faster for a limited number of ioperm using tasks. -AK */
+-	int		ioperm;
+-	unsigned long	*io_bitmap_ptr;
+-	unsigned io_bitmap_max;
+-/* cached TLS descriptors. */
+-	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
+-	unsigned int	iopl;
+-} __attribute__((aligned(16)));
+-
+-#define INIT_THREAD  { \
+-	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+-}
+-
+-#ifndef CONFIG_X86_NO_TSS
+-#define INIT_TSS  { \
+-	.rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+-}
+-#endif
+-
+-#define INIT_MMAP \
+-{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+-
+-#define start_thread(regs,new_rip,new_rsp) do { \
+-	asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));	 \
+-	load_gs_index(0);							\
+-	(regs)->rip = (new_rip);						 \
+-	(regs)->rsp = (new_rsp);						 \
+-	write_pda(oldrsp, (new_rsp));						 \
+-	(regs)->cs = __USER_CS;							 \
+-	(regs)->ss = __USER_DS;							 \
+-	(regs)->eflags = 0x200;							 \
+-	set_fs(USER_DS);							 \
+-} while(0) 
+-
+-#define get_debugreg(var, register)				\
+-	var = HYPERVISOR_get_debugreg(register)
+-#define set_debugreg(value, register) do {			\
+-	if (HYPERVISOR_set_debugreg(register, value))		\
+-		BUG();						\
+-} while (0)
+-
+-struct task_struct;
+-struct mm_struct;
+-
+-/* Free all resources held by a thread. */
+-extern void release_thread(struct task_struct *);
+-
+-/* Prepare to copy thread state - unlazy all lazy status */
+-extern void prepare_to_copy(struct task_struct *tsk);
+-
+-/*
+- * create a kernel thread without removing it from tasklists
+- */
+-extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+-
+-/*
+- * Return saved PC of a blocked thread.
+- * What is this good for? it will be always the scheduler or ret_from_fork.
+- */
+-#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8))
+-
+-extern unsigned long get_wchan(struct task_struct *p);
+-#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1)
+-#define KSTK_EIP(tsk) (task_pt_regs(tsk)->rip)
+-#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
+-
+-
+-struct microcode_header {
+-	unsigned int hdrver;
+-	unsigned int rev;
+-	unsigned int date;
+-	unsigned int sig;
+-	unsigned int cksum;
+-	unsigned int ldrver;
+-	unsigned int pf;
+-	unsigned int datasize;
+-	unsigned int totalsize;
+-	unsigned int reserved[3];
+-};
+-
+-struct microcode {
+-	struct microcode_header hdr;
+-	unsigned int bits[0];
+-};
+-
+-typedef struct microcode microcode_t;
+-typedef struct microcode_header microcode_header_t;
+-
+-/* microcode format is extended from prescott processors */
+-struct extended_signature {
+-	unsigned int sig;
+-	unsigned int pf;
+-	unsigned int cksum;
+-};
+-
+-struct extended_sigtable {
+-	unsigned int count;
+-	unsigned int cksum;
+-	unsigned int reserved[3];
+-	struct extended_signature sigs[0];
+-};
+-
+-
+-#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2)
+-#define ASM_NOP1 P6_NOP1
+-#define ASM_NOP2 P6_NOP2
+-#define ASM_NOP3 P6_NOP3
+-#define ASM_NOP4 P6_NOP4
+-#define ASM_NOP5 P6_NOP5
+-#define ASM_NOP6 P6_NOP6
+-#define ASM_NOP7 P6_NOP7
+-#define ASM_NOP8 P6_NOP8
+-#else
+-#define ASM_NOP1 K8_NOP1
+-#define ASM_NOP2 K8_NOP2
+-#define ASM_NOP3 K8_NOP3
+-#define ASM_NOP4 K8_NOP4
+-#define ASM_NOP5 K8_NOP5
+-#define ASM_NOP6 K8_NOP6
+-#define ASM_NOP7 K8_NOP7
+-#define ASM_NOP8 K8_NOP8
+-#endif
+-
+-/* Opteron nops */
+-#define K8_NOP1 ".byte 0x90\n"
+-#define K8_NOP2	".byte 0x66,0x90\n" 
+-#define K8_NOP3	".byte 0x66,0x66,0x90\n" 
+-#define K8_NOP4	".byte 0x66,0x66,0x66,0x90\n" 
+-#define K8_NOP5	K8_NOP3 K8_NOP2 
+-#define K8_NOP6	K8_NOP3 K8_NOP3
+-#define K8_NOP7	K8_NOP4 K8_NOP3
+-#define K8_NOP8	K8_NOP4 K8_NOP4
+-
+-/* P6 nops */
+-/* uses eax dependencies (Intel-recommended choice) */
+-#define P6_NOP1	".byte 0x90\n"
+-#define P6_NOP2	".byte 0x66,0x90\n"
+-#define P6_NOP3	".byte 0x0f,0x1f,0x00\n"
+-#define P6_NOP4	".byte 0x0f,0x1f,0x40,0\n"
+-#define P6_NOP5	".byte 0x0f,0x1f,0x44,0x00,0\n"
+-#define P6_NOP6	".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
+-#define P6_NOP7	".byte 0x0f,0x1f,0x80,0,0,0,0\n"
+-#define P6_NOP8	".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
+-
+-#define ASM_NOP_MAX 8
+-
+-/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+-static inline void rep_nop(void)
+-{
+-	__asm__ __volatile__("rep;nop": : :"memory");
+-}
+-
+-/* Stop speculative execution */
+-static inline void sync_core(void)
+-{ 
+-	int tmp;
+-	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
+-} 
+-
+-#define ARCH_HAS_PREFETCHW 1
+-static inline void prefetchw(void *x) 
+-{ 
+-	alternative_input("prefetcht0 (%1)",
+-			  "prefetchw (%1)",
+-			  X86_FEATURE_3DNOW,
+-			  "r" (x));
+-} 
+-
+-#define ARCH_HAS_SPINLOCK_PREFETCH 1
+-
+-#define spin_lock_prefetch(x)  prefetchw(x)
+-
+-#define cpu_relax()   rep_nop()
+-
+-static inline void __monitor(const void *eax, unsigned long ecx,
+-		unsigned long edx)
+-{
+-	/* "monitor %eax,%ecx,%edx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc8;"
+-		: :"a" (eax), "c" (ecx), "d"(edx));
+-}
+-
+-static inline void __mwait(unsigned long eax, unsigned long ecx)
+-{
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		".byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
+-}
+-
+-static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+-{
+-	/* "mwait %eax,%ecx;" */
+-	asm volatile(
+-		"sti; .byte 0x0f,0x01,0xc9;"
+-		: :"a" (eax), "c" (ecx));
+-}
+-
+-extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+-
+-#define stack_current() \
+-({								\
+-	struct thread_info *ti;					\
+-	asm("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+-	ti->task;					\
+-})
+-
+-#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
+-
+-extern unsigned long boot_option_idle_override;
+-/* Boot loader type from the setup header */
+-extern int bootloader_type;
+-
+-#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+-
+-#endif /* __ASM_X86_64_PROCESSOR_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-20 11:12:22.000000000 +0100
+@@ -1,56 +1,51 @@
+ #ifndef __ASM_SMP_H
+ #define __ASM_SMP_H
+ 
++#ifndef __ASSEMBLY__
++#include <linux/cpumask.h>
++#include <linux/init.h>
++
+ /*
+  * We need the APIC definitions automatically as part of 'smp.h'
+  */
+-#ifndef __ASSEMBLY__
+-#include <linux/kernel.h>
+-#include <linux/threads.h>
+-#include <linux/cpumask.h>
++#ifdef CONFIG_X86_LOCAL_APIC
++# include <asm/mpspec.h>
++# include <asm/apic.h>
++# ifdef CONFIG_X86_IO_APIC
++#  include <asm/io_apic.h>
++# endif
+ #endif
+ 
+-#if defined(CONFIG_X86_LOCAL_APIC) && !defined(__ASSEMBLY__)
+-#include <linux/bitops.h>
+-#include <asm/mpspec.h>
+-#include <asm/apic.h>
+-#ifdef CONFIG_X86_IO_APIC
+-#include <asm/io_apic.h>
+-#endif
+-#endif
++#define cpu_callout_map cpu_possible_map
++#define cpu_callin_map cpu_possible_map
+ 
+-#define BAD_APICID 0xFFu
+-#ifdef CONFIG_SMP
+-#ifndef __ASSEMBLY__
++extern int smp_num_siblings;
++extern unsigned int num_processors;
+ 
+-/*
+- * Private routines/data
+- */
+- 
+ extern void smp_alloc_memory(void);
+-extern int pic_mode;
+-extern int smp_num_siblings;
+-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+-DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++extern void lock_ipi_call_lock(void);
++extern void unlock_ipi_call_lock(void);
+ 
+ extern void (*mtrr_hook) (void);
+ extern void zap_low_mappings (void);
+-extern void lock_ipi_call_lock(void);
+-extern void unlock_ipi_call_lock(void);
+ 
+-#define MAX_APICID 256
+-extern u8 __initdata x86_cpu_to_apicid_init[];
+-extern void *x86_cpu_to_apicid_ptr;
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(u8, cpu_llc_id);
+ DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
+ 
+-#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ extern void cpu_exit_clear(void);
+ extern void cpu_uninit(void);
+ #endif
+ 
++#ifdef CONFIG_SMP
++
+ #ifndef CONFIG_XEN
++
++/* Globals due to paravirt */
++extern void set_cpu_sibling_map(int cpu);
++
+ struct smp_ops
+ {
+ 	void (*smp_prepare_boot_cpu)(void);
+@@ -104,11 +99,7 @@ void native_smp_prepare_cpus(unsigned in
+ int native_cpu_up(unsigned int cpunum);
+ void native_smp_cpus_done(unsigned int max_cpus);
+ 
+-#define startup_ipi_hook(phys_apicid, start_eip, start_esp) 		\
+-do { } while (0)
+-
+-#else
+-
++#else /* CONFIG_XEN */
+ 
+ void xen_smp_send_stop(void);
+ void xen_smp_send_reschedule(int cpu);
+@@ -120,7 +111,12 @@ int xen_smp_call_function_mask(cpumask_t
+ #define smp_send_reschedule	xen_smp_send_reschedule
+ #define smp_call_function_mask	xen_smp_call_function_mask
+ 
+-#endif
++extern void prefill_possible_map(void);
++
++#endif /* CONFIG_XEN */
++
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
+ 
+ /*
+  * This function is needed by all SMP systems. It must _always_ be valid
+@@ -130,64 +126,49 @@ int xen_smp_call_function_mask(cpumask_t
+ DECLARE_PER_CPU(int, cpu_number);
+ #define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+ 
+-extern cpumask_t cpu_possible_map;
+-#define cpu_callin_map cpu_possible_map
++#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
++
++#define safe_smp_processor_id() smp_processor_id()
+ 
+ /* We don't mark CPUs online until __cpu_up(), so we need another measure */
+ static inline int num_booting_cpus(void)
+ {
+-	return cpus_weight(cpu_possible_map);
++	return cpus_weight(cpu_callout_map);
+ }
+ 
+-#define safe_smp_processor_id() smp_processor_id()
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
+-extern void prefill_possible_map(void);
+-extern unsigned int num_processors;
+-
+-#endif /* !__ASSEMBLY__ */
+-
+ #else /* CONFIG_SMP */
+ 
+ #define safe_smp_processor_id()		0
+ #define cpu_physical_id(cpu)		boot_cpu_physical_apicid
+ 
+-#define NO_PROC_ID		0xFF		/* No processor magic marker */
+-
+-#endif /* CONFIG_SMP */
+-
+-#ifndef __ASSEMBLY__
++#endif /* !CONFIG_SMP */
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 
+-#ifdef APIC_DEFINITION
++static __inline int logical_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++}
++
++# ifdef APIC_DEFINITION
+ extern int hard_smp_processor_id(void);
+-#else
+-#include <mach_apicdef.h>
++# else
++#  include <mach_apicdef.h>
+ static inline int hard_smp_processor_id(void)
+ {
+ 	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
++	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+ }
+-#endif /* APIC_DEFINITION */
++# endif /* APIC_DEFINITION */
+ 
+ #else /* CONFIG_X86_LOCAL_APIC */
+ 
+-#ifndef CONFIG_SMP
+-#define hard_smp_processor_id()		0
+-#endif
++# ifndef CONFIG_SMP
++#  define hard_smp_processor_id()	0
++# endif
+ 
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ 
+-extern u8 apicid_2_node[];
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static __inline int logical_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+-}
+-#endif
+-#endif
+-
++#endif /* !ASSEMBLY */
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,139 +1,103 @@
+ #ifndef __ASM_SMP_H
+ #define __ASM_SMP_H
+ 
+-/*
+- * We need the APIC definitions automatically as part of 'smp.h'
+- */
+-#include <linux/threads.h>
+ #include <linux/cpumask.h>
+-#include <linux/bitops.h>
+ #include <linux/init.h>
+-extern int disable_apic;
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+-#include <asm/mpspec.h>
++/*
++ * We need the APIC definitions automatically as part of 'smp.h'
++ */
+ #include <asm/apic.h>
+ #ifdef CONFIG_X86_IO_APIC
+ #include <asm/io_apic.h>
+ #endif
+-#include <asm/thread_info.h>
++#include <asm/mpspec.h>
+ #endif
+-
+-#ifdef CONFIG_SMP
+-
+ #include <asm/pda.h>
++#include <asm/thread_info.h>
+ 
+-struct pt_regs;
+-
+-extern cpumask_t cpu_present_mask;
+-extern cpumask_t cpu_possible_map;
+-extern cpumask_t cpu_online_map;
+ extern cpumask_t cpu_initialized;
+ 
+-/*
+- * Private routines/data
+- */
+- 
++extern int smp_num_siblings;
++extern unsigned int num_processors;
++
+ extern void smp_alloc_memory(void);
+-extern volatile unsigned long smp_invalidate_needed;
+ extern void lock_ipi_call_lock(void);
+ extern void unlock_ipi_call_lock(void);
+-extern int smp_num_siblings;
+-extern void smp_send_reschedule(int cpu);
++
+ extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
+ 				  void *info, int wait);
+ 
+-/*
+- * cpu_sibling_map and cpu_core_map now live
+- * in the per cpu area
+- *
+- * extern cpumask_t cpu_sibling_map[NR_CPUS];
+- * extern cpumask_t cpu_core_map[NR_CPUS];
+- */
+ DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+ DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+-DECLARE_PER_CPU(u8, cpu_llc_id);
+-
+-#define SMP_TRAMPOLINE_BASE 0x6000
++DECLARE_PER_CPU(u16, cpu_llc_id);
++DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
++DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+ 
+-/*
+- * On x86 all CPUs are mapped 1:1 to the APIC space.
+- * This simplifies scheduling and IPI sending and
+- * compresses data structures.
+- */
+-
+-static inline int num_booting_cpus(void)
++#ifdef CONFIG_X86_LOCAL_APIC
++static inline int cpu_present_to_apicid(int mps_cpu)
+ {
+-	return cpus_weight(cpu_possible_map);
++	if (cpu_present(mps_cpu))
++		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
++	else
++		return BAD_APICID;
+ }
++#endif
+ 
+-#define raw_smp_processor_id() read_pda(cpunumber)
++#ifdef CONFIG_SMP
++
++#define SMP_TRAMPOLINE_BASE 0x6000
+ 
+ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void prefill_possible_map(void);
+-extern unsigned num_processors;
+ extern unsigned __cpuinitdata disabled_cpus;
+ 
+-#define NO_PROC_ID		0xFF		/* No processor magic marker */
+-
+-#endif /* CONFIG_SMP */
++#define raw_smp_processor_id()	read_pda(cpunumber)
++#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+ 
+-#define safe_smp_processor_id()		smp_processor_id()
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static inline int hard_smp_processor_id(void)
+-{
+-	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
+-}
+-#endif
++#define stack_smp_processor_id()					\
++	({								\
++	struct thread_info *ti;						\
++	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
++	ti->cpu;							\
++})
+ 
+ /*
+- * Some lowlevel functions might want to know about
+- * the real APIC ID <-> CPU # mapping.
++ * On x86 all CPUs are mapped 1:1 to the APIC space. This simplifies
++ * scheduling and IPI sending and compresses data structures.
+  */
+-extern u8 __initdata x86_cpu_to_apicid_init[];
+-extern void *x86_cpu_to_apicid_ptr;
+-DECLARE_PER_CPU(u8, x86_cpu_to_apicid);	/* physical ID */
+-extern u8 bios_cpu_apicid[];
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-static inline int cpu_present_to_apicid(int mps_cpu)
++static inline int num_booting_cpus(void)
+ {
+-	if (mps_cpu < NR_CPUS)
+-		return (int)bios_cpu_apicid[mps_cpu];
+-	else
+-		return BAD_APICID;
++	return cpus_weight(cpu_possible_map);
+ }
+-#endif
+ 
+-#ifndef CONFIG_SMP
++extern void smp_send_reschedule(int cpu);
++
++#else /* CONFIG_SMP */
++
++extern unsigned int boot_cpu_id;
++#define cpu_physical_id(cpu)	boot_cpu_id
+ #define stack_smp_processor_id() 0
+-#define cpu_logical_map(x) (x)
+-#else
+-#include <asm/thread_info.h>
+-#define stack_smp_processor_id() \
+-({ 								\
+-	struct thread_info *ti;					\
+-	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+-	ti->cpu;						\
+-})
+-#endif
++
++#endif /* !CONFIG_SMP */
++
++#define safe_smp_processor_id()		smp_processor_id()
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static __inline int logical_smp_processor_id(void)
+ {
+ 	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
++	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
++}
++
++static inline int hard_smp_processor_id(void)
++{
++	/* we don't want to mark this access volatile - bad code generation */
++	return GET_APIC_ID(*(u32 *)(APIC_BASE + APIC_ID));
+ }
+ #endif
+ 
+-#ifdef CONFIG_SMP
+-#define cpu_physical_id(cpu)		per_cpu(x86_cpu_to_apicid, cpu)
+-#else
+-extern unsigned int boot_cpu_id;
+-#define cpu_physical_id(cpu)		boot_cpu_id
+-#endif /* !CONFIG_SMP */
+ #endif
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 14:20:36.000000000 +0100
+@@ -0,0 +1,336 @@
++#ifndef _X86_SPINLOCK_H_
++#define _X86_SPINLOCK_H_
++
++#include <asm/atomic.h>
++#include <asm/rwlock.h>
++#include <asm/page.h>
++#include <asm/processor.h>
++#include <linux/compiler.h>
++
++/*
++ * Your basic SMP spinlocks, allowing only a single CPU anywhere
++ *
++ * Simple spin lock operations.  There are two variants, one clears IRQ's
++ * on the local processor, one does not.
++ *
++ * These are fair FIFO ticket locks, which are currently limited to 256
++ * CPUs.
++ *
++ * (the type definitions are in asm/spinlock_types.h)
++ */
++
++#ifdef CONFIG_X86_32
++# define LOCK_PTR_REG "a"
++# define REG_PTR_MODE "k"
++#else
++# define LOCK_PTR_REG "D"
++# define REG_PTR_MODE "q"
++#endif
++
++#if defined(CONFIG_X86_32) && \
++	(defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE))
++/*
++ * On PPro SMP or if we are using OOSTORE, we use a locked operation to unlock
++ * (PPro errata 66, 92)
++ */
++# define UNLOCK_LOCK_PREFIX LOCK_PREFIX
++#else
++# define UNLOCK_LOCK_PREFIX
++#endif
++
++int xen_spinlock_init(unsigned int cpu);
++void xen_spinlock_cleanup(unsigned int cpu);
++int xen_spin_wait(raw_spinlock_t *, unsigned int token);
++int xen_spin_wait_flags(raw_spinlock_t *, unsigned int *token,
++			unsigned int flags);
++unsigned int xen_spin_adjust(raw_spinlock_t *, unsigned int token);
++void xen_spin_kick(raw_spinlock_t *, unsigned int token);
++
++/*
++ * Ticket locks are conceptually two parts, one indicating the current head of
++ * the queue, and the other indicating the current tail. The lock is acquired
++ * by atomically noting the tail and incrementing it by one (thus adding
++ * ourself to the queue and noting our position), then waiting until the head
++ * becomes equal to the the initial value of the tail.
++ *
++ * We use an xadd covering *both* parts of the lock, to increment the tail and
++ * also load the position of the head, which takes care of memory ordering
++ * issues and should be optimal for the uncontended case. Note the tail must be
++ * in the high part, because a wide xadd increment of the low part would carry
++ * up and contaminate the high part.
++ *
++ * With fewer than 2^8 possible CPUs, we can use x86's partial registers to
++ * save some instructions and make the code more elegant. There really isn't
++ * much between them in performance though, especially as locks are out of line.
++ */
++#if TICKET_SHIFT == 8
++#define __raw_spin_lock_preamble \
++	asm(LOCK_PREFIX "xaddw %w0, %2\n\t" \
++	    "cmpb %h0, %b0\n\t" \
++	    "sete %1" \
++	    : "=&Q" (token), "=qm" (free), "+m" (lock->slock) \
++	    : "0" (0x0100) \
++	    : "memory", "cc")
++#define __raw_spin_lock_body \
++	asm("1:\t" \
++	    "cmpb %h0, %b0\n\t" \
++	    "je 2f\n\t" \
++	    "decl %1\n\t" \
++	    "jz 2f\n\t" \
++	    "rep ; nop\n\t" \
++	    "movb %2, %b0\n\t" \
++	    /* don't need lfence here, because loads are in-order */ \
++	    "jmp 1b\n" \
++	    "2:" \
++	    : "+Q" (token), "+g" (count) \
++	    : "m" (lock->slock) \
++	    : "memory", "cc")
++
++
++static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++{
++	int tmp, new;
++
++	asm("movzwl %2, %0\n\t"
++	    "cmpb %h0, %b0\n\t"
++	    "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
++	    "jne 1f\n\t"
++	    LOCK_PREFIX "cmpxchgw %w1, %2\n\t"
++	    "1:\t"
++	    "sete %b1\n\t"
++	    "movzbl %b1, %0\n\t"
++	    : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
++	    :
++	    : "memory", "cc");
++
++	return tmp;
++}
++
++static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++{
++	unsigned int token;
++	unsigned char kick;
++
++	asm(UNLOCK_LOCK_PREFIX "incb %2\n\t"
++	    "movzwl %2, %0\n\t"
++	    "cmpb %h0, %b0\n\t"
++	    "setne %1"
++	    : "=&Q" (token), "=qm" (kick), "+m" (lock->slock)
++	    :
++	    : "memory", "cc");
++	if (kick)
++		xen_spin_kick(lock, token);
++}
++#elif TICKET_SHIFT == 16
++#define __raw_spin_lock_preamble \
++	do { \
++		unsigned int tmp; \
++		asm(LOCK_PREFIX "xaddl %0, %2\n\t" \
++		    "shldl $16, %0, %3\n\t" \
++		    "cmpw %w3, %w0\n\t" \
++		    "sete %1" \
++		    : "=&r" (token), "=qm" (free), "+m" (lock->slock), \
++		      "=&g" (tmp) \
++		    : "0" (0x00010000) \
++		    : "memory", "cc"); \
++	} while (0)
++#define __raw_spin_lock_body \
++	do { \
++		unsigned int tmp; \
++		asm("shldl $16, %0, %2\n" \
++		    "1:\t" \
++		    "cmpw %w2, %w0\n\t" \
++		    "je 2f\n\t" \
++		    "decl %1\n\t" \
++		    "jz 2f\n\t" \
++		    "rep ; nop\n\t" \
++		    "movw %3, %w0\n\t" \
++		    /* don't need lfence here, because loads are in-order */ \
++		    "jmp 1b\n" \
++		    "2:" \
++		    : "+r" (token), "+g" (count), "=&g" (tmp) \
++		    : "m" (lock->slock) \
++		    : "memory", "cc"); \
++	} while (0)
++
++static inline int __raw_spin_trylock(raw_spinlock_t *lock)
++{
++	int tmp;
++	int new;
++
++	asm("movl %2, %0\n\t"
++	    "movl %0, %1\n\t"
++	    "roll $16, %0\n\t"
++	    "cmpl %0, %1\n\t"
++	    "leal 0x00010000(%" REG_PTR_MODE "0), %1\n\t"
++	    "jne 1f\n\t"
++	    LOCK_PREFIX "cmpxchgl %1, %2\n"
++	    "1:\t"
++	    "sete %b1\n\t"
++	    "movzbl %b1, %0\n\t"
++	    : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
++	    :
++	    : "memory", "cc");
++
++	return tmp;
++}
++
++static inline void __raw_spin_unlock(raw_spinlock_t *lock)
++{
++	unsigned int token, tmp;
++	bool kick;
++
++	asm(UNLOCK_LOCK_PREFIX "incw %2\n\t"
++	    "movl %2, %0\n\t"
++	    "shldl $16, %0, %3\n\t"
++	    "cmpw %w3, %w0\n\t"
++	    "setne %1"
++	    : "=&r" (token), "=qm" (kick), "+m" (lock->slock), "=&r" (tmp)
++	    :
++	    : "memory", "cc");
++	if (kick)
++		xen_spin_kick(lock, token);
++}
++#endif
++
++static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
++{
++	int tmp = *(volatile signed int *)(&(lock)->slock);
++
++	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
++}
++
++static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
++{
++	int tmp = *(volatile signed int *)(&(lock)->slock);
++
++	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
++}
++
++static inline void __raw_spin_lock(raw_spinlock_t *lock)
++{
++	unsigned int token, count;
++	bool free;
++
++	__raw_spin_lock_preamble;
++	if (likely(free))
++		return;
++	token = xen_spin_adjust(lock, token);
++	do {
++		count = 1 << 10;
++		__raw_spin_lock_body;
++	} while (unlikely(!count) && !xen_spin_wait(lock, token));
++}
++
++static inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
++					 unsigned long flags)
++{
++	unsigned int token, count;
++	bool free;
++
++	__raw_spin_lock_preamble;
++	if (likely(free))
++		return;
++	token = xen_spin_adjust(lock, token);
++	do {
++		count = 1 << 10;
++		__raw_spin_lock_body;
++	} while (unlikely(!count) && !xen_spin_wait_flags(lock, &token, flags));
++}
++
++static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
++{
++	while (__raw_spin_is_locked(lock))
++		cpu_relax();
++}
++
++#undef __raw_spin_lock_preamble
++#undef __raw_spin_lock_body
++
++/*
++ * Read-write spinlocks, allowing multiple readers
++ * but only one writer.
++ *
++ * NOTE! it is quite common to have readers in interrupts
++ * but no interrupt writers. For those circumstances we
++ * can "mix" irq-safe locks - any writer needs to get a
++ * irq-safe write-lock, but readers can get non-irqsafe
++ * read-locks.
++ *
++ * On x86, we implement read-write locks as a 32-bit counter
++ * with the high bit (sign) being the "contended" bit.
++ */
++
++/**
++ * read_can_lock - would read_trylock() succeed?
++ * @lock: the rwlock in question.
++ */
++static inline int __raw_read_can_lock(raw_rwlock_t *lock)
++{
++	return (int)(lock)->lock > 0;
++}
++
++/**
++ * write_can_lock - would write_trylock() succeed?
++ * @lock: the rwlock in question.
++ */
++static inline int __raw_write_can_lock(raw_rwlock_t *lock)
++{
++	return (lock)->lock == RW_LOCK_BIAS;
++}
++
++static inline void __raw_read_lock(raw_rwlock_t *rw)
++{
++	asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
++		     "jns 1f\n"
++		     "call __read_lock_failed\n\t"
++		     "1:\n"
++		     ::LOCK_PTR_REG (rw) : "memory");
++}
++
++static inline void __raw_write_lock(raw_rwlock_t *rw)
++{
++	asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"
++		     "jz 1f\n"
++		     "call __write_lock_failed\n\t"
++		     "1:\n"
++		     ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");
++}
++
++static inline int __raw_read_trylock(raw_rwlock_t *lock)
++{
++	atomic_t *count = (atomic_t *)lock;
++
++	atomic_dec(count);
++	if (atomic_read(count) >= 0)
++		return 1;
++	atomic_inc(count);
++	return 0;
++}
++
++static inline int __raw_write_trylock(raw_rwlock_t *lock)
++{
++	atomic_t *count = (atomic_t *)lock;
++
++	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
++		return 1;
++	atomic_add(RW_LOCK_BIAS, count);
++	return 0;
++}
++
++static inline void __raw_read_unlock(raw_rwlock_t *rw)
++{
++	asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory");
++}
++
++static inline void __raw_write_unlock(raw_rwlock_t *rw)
++{
++	asm volatile(LOCK_PREFIX "addl %1, %0"
++		     : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
++}
++
++#define _raw_spin_relax(lock)	cpu_relax()
++#define _raw_read_relax(lock)	cpu_relax()
++#define _raw_write_relax(lock)	cpu_relax()
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:22:42.000000000 +0100
+@@ -0,0 +1,34 @@
++#ifndef __ASM_SPINLOCK_TYPES_H
++#define __ASM_SPINLOCK_TYPES_H
++
++#ifndef __LINUX_SPINLOCK_TYPES_H
++# error "please don't include this file directly"
++#endif
++
++typedef union {
++	unsigned int slock;
++	struct {
++/*
++ * On Xen we support a single level of interrupt re-enabling per lock. Hence
++ * we can have twice as many outstanding tickets. Thus the cut-off for using
++ * byte register pairs must be at half the number of CPUs.
++ */
++#if 2 * CONFIG_NR_CPUS < 256
++# define TICKET_SHIFT 8
++		u8 cur, seq;
++#else
++# define TICKET_SHIFT 16
++		u16 cur, seq;
++#endif
++	};
++} raw_spinlock_t;
++
++#define __RAW_SPIN_LOCK_UNLOCKED	{ 0 }
++
++typedef struct {
++	unsigned int lock;
++} raw_rwlock_t;
++
++#define __RAW_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
++
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,393 @@
++#ifndef _ASM_X86_SYSTEM_H_
++#define _ASM_X86_SYSTEM_H_
++
++#include <asm/asm.h>
++#include <asm/segment.h>
++#include <asm/cpufeature.h>
++#include <asm/cmpxchg.h>
++#include <asm/nops.h>
++#include <asm/hypervisor.h>
++
++#include <linux/kernel.h>
++#include <linux/irqflags.h>
++
++/* entries in ARCH_DLINFO: */
++#ifdef CONFIG_IA32_EMULATION
++# define AT_VECTOR_SIZE_ARCH 2
++#else
++# define AT_VECTOR_SIZE_ARCH 1
++#endif
++
++#ifdef CONFIG_X86_32
++
++struct task_struct; /* one of the stranger aspects of C forward declarations */
++struct task_struct *__switch_to(struct task_struct *prev,
++				struct task_struct *next);
++
++/*
++ * Saving eflags is important. It switches not only IOPL between tasks,
++ * it also protects other tasks from NT leaking through sysenter etc.
++ */
++#define switch_to(prev, next, last) do {				\
++	unsigned long esi, edi;						\
++	asm volatile("pushfl\n\t"		/* Save flags */	\
++		     "pushl %%ebp\n\t"					\
++		     "movl %%esp,%0\n\t"	/* save ESP */		\
++		     "movl %5,%%esp\n\t"	/* restore ESP */	\
++		     "movl $1f,%1\n\t"		/* save EIP */		\
++		     "pushl %6\n\t"		/* restore EIP */	\
++		     "jmp __switch_to\n"				\
++		     "1:\t"						\
++		     "popl %%ebp\n\t"					\
++		     "popfl"						\
++		     :"=m" (prev->thread.sp), "=m" (prev->thread.ip),	\
++		      "=a" (last), "=S" (esi), "=D" (edi)		\
++		     :"m" (next->thread.sp), "m" (next->thread.ip),	\
++		      "2" (prev), "d" (next));				\
++} while (0)
++
++/*
++ * disable hlt during certain critical i/o operations
++ */
++#define HAVE_DISABLE_HLT
++#else
++#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
++#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
++
++/* frame pointer must be last for get_wchan */
++#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
++#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
++
++#define __EXTRA_CLOBBER  \
++	, "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
++	  "r12", "r13", "r14", "r15"
++
++/* Save restore flags to clear handle leaking NT */
++#define switch_to(prev, next, last) \
++	asm volatile(SAVE_CONTEXT						    \
++	     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
++	     "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */	  \
++	     "call __switch_to\n\t"					  \
++	     ".globl thread_return\n"					  \
++	     "thread_return:\n\t"					  \
++	     "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"			  \
++	     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
++	     LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"	  \
++	     "movq %%rax,%%rdi\n\t" 					  \
++	     "jc   ret_from_fork\n\t"					  \
++	     RESTORE_CONTEXT						  \
++	     : "=a" (last)					  	  \
++	     : [next] "S" (next), [prev] "D" (prev),			  \
++	       [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
++	       [ti_flags] "i" (offsetof(struct thread_info, flags)),	  \
++	       [tif_fork] "i" (TIF_FORK),			  	  \
++	       [thread_info] "i" (offsetof(struct task_struct, stack)),   \
++	       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))  \
++	     : "memory", "cc" __EXTRA_CLOBBER)
++#endif
++
++#ifdef __KERNEL__
++#define _set_base(addr, base) do { unsigned long __pr; \
++__asm__ __volatile__ ("movw %%dx,%1\n\t" \
++	"rorl $16,%%edx\n\t" \
++	"movb %%dl,%2\n\t" \
++	"movb %%dh,%3" \
++	:"=&d" (__pr) \
++	:"m" (*((addr)+2)), \
++	 "m" (*((addr)+4)), \
++	 "m" (*((addr)+7)), \
++	 "0" (base) \
++	); } while (0)
++
++#define _set_limit(addr, limit) do { unsigned long __lr; \
++__asm__ __volatile__ ("movw %%dx,%1\n\t" \
++	"rorl $16,%%edx\n\t" \
++	"movb %2,%%dh\n\t" \
++	"andb $0xf0,%%dh\n\t" \
++	"orb %%dh,%%dl\n\t" \
++	"movb %%dl,%2" \
++	:"=&d" (__lr) \
++	:"m" (*(addr)), \
++	 "m" (*((addr)+6)), \
++	 "0" (limit) \
++	); } while (0)
++
++#define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base))
++#define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1))
++
++extern void load_gs_index(unsigned);
++
++/*
++ * Load a segment. Fall back on loading the zero
++ * segment if something goes wrong..
++ */
++#define loadsegment(seg, value)			\
++	asm volatile("\n"			\
++		"1:\t"				\
++		"movl %k0,%%" #seg "\n"		\
++		"2:\n"				\
++		".section .fixup,\"ax\"\n"	\
++		"3:\t"				\
++		"movl %k1, %%" #seg "\n\t"	\
++		"jmp 2b\n"			\
++		".previous\n"			\
++		_ASM_EXTABLE(1b,3b)		\
++		: :"r" (value), "r" (0))
++
++
++/*
++ * Save a segment register away
++ */
++#define savesegment(seg, value) \
++	asm volatile("mov %%" #seg ",%0":"=rm" (value))
++
++static inline unsigned long get_limit(unsigned long segment)
++{
++	unsigned long __limit;
++	__asm__("lsll %1,%0"
++		:"=r" (__limit):"r" (segment));
++	return __limit+1;
++}
++
++static inline void xen_clts(void)
++{
++	HYPERVISOR_fpu_taskswitch(0);
++}
++
++static inline void xen_stts(void)
++{
++	HYPERVISOR_fpu_taskswitch(1);
++}
++
++/*
++ * Volatile isn't enough to prevent the compiler from reordering the
++ * read/write functions for the control registers and messing everything up.
++ * A memory clobber would solve the problem, but would prevent reordering of
++ * all loads stores around it, which can hurt performance. Solution is to
++ * use a variable and mimic reads and writes to it to enforce serialization
++ */
++static unsigned long __force_order;
++
++static inline unsigned long xen_read_cr0(void)
++{
++	unsigned long val;
++	asm volatile("mov %%cr0,%0\n\t" :"=r" (val), "=m" (__force_order));
++	return val;
++}
++
++static inline void xen_write_cr0(unsigned long val)
++{
++	asm volatile("mov %0,%%cr0": :"r" (val), "m" (__force_order));
++}
++
++#define xen_read_cr2() (current_vcpu_info()->arch.cr2)
++#define xen_write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val)))
++
++static inline unsigned long xen_read_cr3(void)
++{
++	unsigned long val;
++	asm volatile("mov %%cr3,%0\n\t" :"=r" (val), "=m" (__force_order));
++#ifdef CONFIG_X86_32
++	return mfn_to_pfn(xen_cr3_to_pfn(val)) << PAGE_SHIFT;
++#else
++	return machine_to_phys(val);
++#endif
++}
++
++static inline void xen_write_cr3(unsigned long val)
++{
++#ifdef CONFIG_X86_32
++	val = xen_pfn_to_cr3(pfn_to_mfn(val >> PAGE_SHIFT));
++#else
++	val = phys_to_machine(val);
++#endif
++	asm volatile("mov %0,%%cr3": :"r" (val), "m" (__force_order));
++}
++
++static inline unsigned long xen_read_cr4(void)
++{
++	unsigned long val;
++	asm volatile("mov %%cr4,%0\n\t" :"=r" (val), "=m" (__force_order));
++	return val;
++}
++
++#define xen_read_cr4_safe() xen_read_cr4()
++
++static inline void xen_write_cr4(unsigned long val)
++{
++	asm volatile("mov %0,%%cr4": :"r" (val), "m" (__force_order));
++}
++
++#ifdef CONFIG_X86_64
++static inline unsigned long xen_read_cr8(void)
++{
++	return 0;
++}
++
++static inline void xen_write_cr8(unsigned long val)
++{
++	BUG_ON(val);
++}
++#endif
++
++static inline void xen_wbinvd(void)
++{
++	asm volatile("wbinvd": : :"memory");
++}
++#define read_cr0()	(xen_read_cr0())
++#define write_cr0(x)	(xen_write_cr0(x))
++#define read_cr2()	(xen_read_cr2())
++#define write_cr2(x)	(xen_write_cr2(x))
++#define read_cr3()	(xen_read_cr3())
++#define write_cr3(x)	(xen_write_cr3(x))
++#define read_cr4()	(xen_read_cr4())
++#define read_cr4_safe()	(xen_read_cr4_safe())
++#define write_cr4(x)	(xen_write_cr4(x))
++#define wbinvd()	(xen_wbinvd())
++#ifdef CONFIG_X86_64
++#define read_cr8()	(xen_read_cr8())
++#define write_cr8(x)	(xen_write_cr8(x))
++#endif
++
++/* Clear the 'TS' bit */
++#define clts()		(xen_clts())
++#define stts()		(xen_stts())
++
++#endif /* __KERNEL__ */
++
++static inline void clflush(volatile void *__p)
++{
++	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
++}
++
++#define nop() __asm__ __volatile__ ("nop")
++
++void disable_hlt(void);
++void enable_hlt(void);
++
++extern int es7000_plat;
++void cpu_idle_wait(void);
++
++extern unsigned long arch_align_stack(unsigned long sp);
++extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
++
++void default_idle(void);
++
++/*
++ * Force strict CPU ordering.
++ * And yes, this is required on UP too when we're talking
++ * to devices.
++ */
+ #ifdef CONFIG_X86_32
+-# include "system_32.h"
++/*
++ * For now, "wmb()" doesn't actually do anything, as all
++ * Intel CPU's follow what Intel calls a *Processor Order*,
++ * in which all writes are seen in the program order even
++ * outside the CPU.
++ *
++ * I expect future Intel CPU's to have a weaker ordering,
++ * but I'd also expect them to finally get their act together
++ * and add some real memory barriers if so.
++ *
++ * Some non intel clones support out of order store. wmb() ceases to be a
++ * nop for these.
++ */
++#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
++#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
++#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
++#else
++#define mb() 	asm volatile("mfence":::"memory")
++#define rmb()	asm volatile("lfence":::"memory")
++#define wmb()	asm volatile("sfence" ::: "memory")
++#endif
++
++/**
++ * read_barrier_depends - Flush all pending reads that subsequents reads
++ * depend on.
++ *
++ * No data-dependent reads from memory-like regions are ever reordered
++ * over this barrier.  All reads preceding this primitive are guaranteed
++ * to access memory (but not necessarily other CPUs' caches) before any
++ * reads following this primitive that depend on the data return by
++ * any of the preceding reads.  This primitive is much lighter weight than
++ * rmb() on most CPUs, and is never heavier weight than is
++ * rmb().
++ *
++ * These ordering constraints are respected by both the local CPU
++ * and the compiler.
++ *
++ * Ordering is not guaranteed by anything other than these primitives,
++ * not even by data dependencies.  See the documentation for
++ * memory_barrier() for examples and URLs to more information.
++ *
++ * For example, the following code would force ordering (the initial
++ * value of "a" is zero, "b" is one, and "p" is "&a"):
++ *
++ * <programlisting>
++ *	CPU 0				CPU 1
++ *
++ *	b = 2;
++ *	memory_barrier();
++ *	p = &b;				q = p;
++ *					read_barrier_depends();
++ *					d = *q;
++ * </programlisting>
++ *
++ * because the read of "*q" depends on the read of "p" and these
++ * two reads are separated by a read_barrier_depends().  However,
++ * the following code, with the same initial values for "a" and "b":
++ *
++ * <programlisting>
++ *	CPU 0				CPU 1
++ *
++ *	a = 2;
++ *	memory_barrier();
++ *	b = 3;				y = b;
++ *					read_barrier_depends();
++ *					x = a;
++ * </programlisting>
++ *
++ * does not enforce ordering, since there is no data dependency between
++ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
++ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
++ * in cases like this where there are no data dependencies.
++ **/
++
++#define read_barrier_depends()	do { } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb()	mb()
++#ifdef CONFIG_X86_PPRO_FENCE
++# define smp_rmb()	rmb()
+ #else
+-# include "system_64.h"
++# define smp_rmb()	barrier()
++#endif
++#ifdef CONFIG_X86_OOSTORE
++# define smp_wmb() 	wmb()
++#else
++# define smp_wmb()	barrier()
++#endif
++#define smp_read_barrier_depends()	read_barrier_depends()
++#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#else
++#define smp_mb()	barrier()
++#define smp_rmb()	barrier()
++#define smp_wmb()	barrier()
++#define smp_read_barrier_depends()	do { } while (0)
++#define set_mb(var, value) do { var = value; barrier(); } while (0)
++#endif
++
++/*
++ * Stop RDTSC speculation. This is needed when you need to use RDTSC
++ * (or get_cycles or vread that possibly accesses the TSC) in a defined
++ * code region.
++ *
++ * (Could use an alternative three way for this if there was one.)
++ */
++static inline void rdtsc_barrier(void)
++{
++	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
++	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
++}
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,312 +0,0 @@
+-#ifndef __ASM_SYSTEM_H
+-#define __ASM_SYSTEM_H
+-
+-#include <linux/kernel.h>
+-#include <asm/segment.h>
+-#include <asm/cpufeature.h>
+-#include <asm/cmpxchg.h>
+-#include <asm/synch_bitops.h>
+-#include <asm/hypervisor.h>
+-
+-#ifdef __KERNEL__
+-#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
+-
+-struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
+-extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
+-
+-/*
+- * Saving eflags is important. It switches not only IOPL between tasks,
+- * it also protects other tasks from NT leaking through sysenter etc.
+- */
+-#define switch_to(prev,next,last) do {					\
+-	unsigned long esi,edi;						\
+-	asm volatile("pushfl\n\t"		/* Save flags */	\
+-		     "pushl %%ebp\n\t"					\
+-		     "movl %%esp,%0\n\t"	/* save ESP */		\
+-		     "movl %5,%%esp\n\t"	/* restore ESP */	\
+-		     "movl $1f,%1\n\t"		/* save EIP */		\
+-		     "pushl %6\n\t"		/* restore EIP */	\
+-		     "jmp __switch_to\n"				\
+-		     "1:\t"						\
+-		     "popl %%ebp\n\t"					\
+-		     "popfl"						\
+-		     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\
+-		      "=a" (last),"=S" (esi),"=D" (edi)			\
+-		     :"m" (next->thread.esp),"m" (next->thread.eip),	\
+-		      "2" (prev), "d" (next));				\
+-} while (0)
+-
+-#define _set_base(addr,base) do { unsigned long __pr; \
+-__asm__ __volatile__ ("movw %%dx,%1\n\t" \
+-	"rorl $16,%%edx\n\t" \
+-	"movb %%dl,%2\n\t" \
+-	"movb %%dh,%3" \
+-	:"=&d" (__pr) \
+-	:"m" (*((addr)+2)), \
+-	 "m" (*((addr)+4)), \
+-	 "m" (*((addr)+7)), \
+-         "0" (base) \
+-        ); } while(0)
+-
+-#define _set_limit(addr,limit) do { unsigned long __lr; \
+-__asm__ __volatile__ ("movw %%dx,%1\n\t" \
+-	"rorl $16,%%edx\n\t" \
+-	"movb %2,%%dh\n\t" \
+-	"andb $0xf0,%%dh\n\t" \
+-	"orb %%dh,%%dl\n\t" \
+-	"movb %%dl,%2" \
+-	:"=&d" (__lr) \
+-	:"m" (*(addr)), \
+-	 "m" (*((addr)+6)), \
+-	 "0" (limit) \
+-        ); } while(0)
+-
+-#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
+-#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1) )
+-
+-/*
+- * Load a segment. Fall back on loading the zero
+- * segment if something goes wrong..
+- */
+-#define loadsegment(seg,value)			\
+-	asm volatile("\n"			\
+-		"1:\t"				\
+-		"mov %0,%%" #seg "\n"		\
+-		"2:\n"				\
+-		".section .fixup,\"ax\"\n"	\
+-		"3:\t"				\
+-		"pushl $0\n\t"			\
+-		"popl %%" #seg "\n\t"		\
+-		"jmp 2b\n"			\
+-		".previous\n"			\
+-		".section __ex_table,\"a\"\n\t"	\
+-		".align 4\n\t"			\
+-		".long 1b,3b\n"			\
+-		".previous"			\
+-		: :"rm" (value))
+-
+-/*
+- * Save a segment register away
+- */
+-#define savesegment(seg, value) \
+-	asm volatile("mov %%" #seg ",%0":"=rm" (value))
+-
+-static inline void xen_clts(void)
+-{
+-	HYPERVISOR_fpu_taskswitch(0);
+-}
+-
+-static inline unsigned long xen_read_cr0(void)
+-{
+-	unsigned long val;
+-	asm volatile("movl %%cr0,%0\n\t" :"=r" (val));
+-	return val;
+-}
+-
+-static inline void xen_write_cr0(unsigned long val)
+-{
+-	asm volatile("movl %0,%%cr0": :"r" (val));
+-}
+-
+-#define xen_read_cr2() (current_vcpu_info()->arch.cr2)
+-
+-static inline void xen_write_cr2(unsigned long val)
+-{
+-	asm volatile("movl %0,%%cr2": :"r" (val));
+-}
+-
+-static inline unsigned long xen_read_cr3(void)
+-{
+-	unsigned long val;
+-	asm volatile("movl %%cr3,%0\n\t" :"=r" (val));
+-	return mfn_to_pfn(xen_cr3_to_pfn(val)) << PAGE_SHIFT;
+-}
+-
+-static inline void xen_write_cr3(unsigned long val)
+-{
+-	val = xen_pfn_to_cr3(pfn_to_mfn(val >> PAGE_SHIFT));
+-	asm volatile("movl %0,%%cr3": :"r" (val));
+-}
+-
+-static inline unsigned long xen_read_cr4(void)
+-{
+-	unsigned long val;
+-	asm volatile("movl %%cr4,%0\n\t" :"=r" (val));
+-	return val;
+-}
+-
+-static inline unsigned long xen_read_cr4_safe(void)
+-{
+-	unsigned long val;
+-	/* This could fault if %cr4 does not exist */
+-	asm volatile("1: movl %%cr4, %0		\n"
+-		"2:				\n"
+-		".section __ex_table,\"a\"	\n"
+-		".long 1b,2b			\n"
+-		".previous			\n"
+-		: "=r" (val): "0" (0));
+-	return val;
+-}
+-
+-static inline void xen_write_cr4(unsigned long val)
+-{
+-	asm volatile("movl %0,%%cr4": :"r" (val));
+-}
+-
+-static inline void xen_wbinvd(void)
+-{
+-	asm volatile("wbinvd": : :"memory");
+-}
+-
+-static inline void clflush(volatile void *__p)
+-{
+-	asm volatile("clflush %0" : "+m" (*(char __force *)__p));
+-}
+-
+-#define read_cr0()	(xen_read_cr0())
+-#define write_cr0(x)	(xen_write_cr0(x))
+-#define read_cr2()	(xen_read_cr2())
+-#define write_cr2(x)	(xen_write_cr2(x))
+-#define read_cr3()	(xen_read_cr3())
+-#define write_cr3(x)	(xen_write_cr3(x))
+-#define read_cr4()	(xen_read_cr4())
+-#define read_cr4_safe()	(xen_read_cr4_safe())
+-#define write_cr4(x)	(xen_write_cr4(x))
+-#define wbinvd()	(xen_wbinvd())
+-
+-/* Clear the 'TS' bit */
+-#define clts()		(xen_clts())
+-
+-/* Set the 'TS' bit */
+-#define stts() (HYPERVISOR_fpu_taskswitch(1))
+-
+-#endif	/* __KERNEL__ */
+-
+-static inline unsigned long get_limit(unsigned long segment)
+-{
+-	unsigned long __limit;
+-	__asm__("lsll %1,%0"
+-		:"=r" (__limit):"r" (segment));
+-	return __limit+1;
+-}
+-
+-#define nop() __asm__ __volatile__ ("nop")
+-
+-/*
+- * Force strict CPU ordering.
+- * And yes, this is required on UP too when we're talking
+- * to devices.
+- *
+- * For now, "wmb()" doesn't actually do anything, as all
+- * Intel CPU's follow what Intel calls a *Processor Order*,
+- * in which all writes are seen in the program order even
+- * outside the CPU.
+- *
+- * I expect future Intel CPU's to have a weaker ordering,
+- * but I'd also expect them to finally get their act together
+- * and add some real memory barriers if so.
+- *
+- * Some non intel clones support out of order store. wmb() ceases to be a
+- * nop for these.
+- */
+- 
+-
+-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+-
+-/**
+- * read_barrier_depends - Flush all pending reads that subsequents reads
+- * depend on.
+- *
+- * No data-dependent reads from memory-like regions are ever reordered
+- * over this barrier.  All reads preceding this primitive are guaranteed
+- * to access memory (but not necessarily other CPUs' caches) before any
+- * reads following this primitive that depend on the data return by
+- * any of the preceding reads.  This primitive is much lighter weight than
+- * rmb() on most CPUs, and is never heavier weight than is
+- * rmb().
+- *
+- * These ordering constraints are respected by both the local CPU
+- * and the compiler.
+- *
+- * Ordering is not guaranteed by anything other than these primitives,
+- * not even by data dependencies.  See the documentation for
+- * memory_barrier() for examples and URLs to more information.
+- *
+- * For example, the following code would force ordering (the initial
+- * value of "a" is zero, "b" is one, and "p" is "&a"):
+- *
+- * <programlisting>
+- *	CPU 0				CPU 1
+- *
+- *	b = 2;
+- *	memory_barrier();
+- *	p = &b;				q = p;
+- *					read_barrier_depends();
+- *					d = *q;
+- * </programlisting>
+- *
+- * because the read of "*q" depends on the read of "p" and these
+- * two reads are separated by a read_barrier_depends().  However,
+- * the following code, with the same initial values for "a" and "b":
+- *
+- * <programlisting>
+- *	CPU 0				CPU 1
+- *
+- *	a = 2;
+- *	memory_barrier();
+- *	b = 3;				y = b;
+- *					read_barrier_depends();
+- *					x = a;
+- * </programlisting>
+- *
+- * does not enforce ordering, since there is no data dependency between
+- * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+- * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+- * in cases like this where there are no data dependencies.
+- **/
+-
+-#define read_barrier_depends()	do { } while(0)
+-
+-#ifdef CONFIG_SMP
+-#define smp_mb()	mb()
+-#ifdef CONFIG_X86_PPRO_FENCE
+-# define smp_rmb()	rmb()
+-#else
+-# define smp_rmb()	barrier()
+-#endif
+-#ifdef CONFIG_X86_OOSTORE
+-# define smp_wmb() 	wmb()
+-#else
+-# define smp_wmb()	barrier()
+-#endif
+-#define smp_read_barrier_depends()	read_barrier_depends()
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+-#else
+-#define smp_mb()	barrier()
+-#define smp_rmb()	barrier()
+-#define smp_wmb()	barrier()
+-#define smp_read_barrier_depends()	do { } while(0)
+-#define set_mb(var, value) do { var = value; barrier(); } while (0)
+-#endif
+-
+-#include <linux/irqflags.h>
+-
+-/*
+- * disable hlt during certain critical i/o operations
+- */
+-#define HAVE_DISABLE_HLT
+-void disable_hlt(void);
+-void enable_hlt(void);
+-
+-extern int es7000_plat;
+-void cpu_idle_wait(void);
+-
+-extern unsigned long arch_align_stack(unsigned long sp);
+-extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+-
+-void default_idle(void);
+-void __show_registers(struct pt_regs *, int all);
+-
+-#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,122 +1,9 @@
+ #ifndef __ASM_SYSTEM_H
+ #define __ASM_SYSTEM_H
+ 
+-#include <linux/kernel.h>
+ #include <asm/segment.h>
+ #include <asm/cmpxchg.h>
+ 
+-#include <asm/synch_bitops.h>
+-#include <asm/hypervisor.h>
+-#include <xen/interface/arch-x86_64.h>
+-
+-#ifdef __KERNEL__
+-
+-/* entries in ARCH_DLINFO: */
+-#ifdef CONFIG_IA32_EMULATION
+-# define AT_VECTOR_SIZE_ARCH 2
+-#else
+-# define AT_VECTOR_SIZE_ARCH 1
+-#endif
+-
+-#define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
+-#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
+-
+-/* frame pointer must be last for get_wchan */
+-#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\n\t"
+-
+-#define __EXTRA_CLOBBER  \
+-	,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
+-
+-/* Save restore flags to clear handle leaking NT */
+-#define switch_to(prev,next,last) \
+-	asm volatile(SAVE_CONTEXT						    \
+-		     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
+-		     "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */	  \
+-		     "call __switch_to\n\t"					  \
+-		     ".globl thread_return\n"					\
+-		     "thread_return:\n\t"					    \
+-		     "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"			  \
+-		     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
+-		     LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"	  \
+-		     "movq %%rax,%%rdi\n\t" 					  \
+-		     "jc   ret_from_fork\n\t"					  \
+-		     RESTORE_CONTEXT						    \
+-		     : "=a" (last)					  	  \
+-		     : [next] "S" (next), [prev] "D" (prev),			  \
+-		       [threadrsp] "i" (offsetof(struct task_struct, thread.rsp)), \
+-		       [ti_flags] "i" (offsetof(struct thread_info, flags)),\
+-		       [tif_fork] "i" (TIF_FORK),			  \
+-		       [thread_info] "i" (offsetof(struct task_struct, stack)), \
+-		       [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent))   \
+-		     : "memory", "cc" __EXTRA_CLOBBER)
+-    
+-extern void load_gs_index(unsigned); 
+-
+-/*
+- * Load a segment. Fall back on loading the zero
+- * segment if something goes wrong..
+- */
+-#define loadsegment(seg,value)	\
+-	asm volatile("\n"			\
+-		"1:\t"				\
+-		"movl %k0,%%" #seg "\n"		\
+-		"2:\n"				\
+-		".section .fixup,\"ax\"\n"	\
+-		"3:\t"				\
+-		"movl %1,%%" #seg "\n\t" 	\
+-		"jmp 2b\n"			\
+-		".previous\n"			\
+-		".section __ex_table,\"a\"\n\t"	\
+-		".align 8\n\t"			\
+-		".quad 1b,3b\n"			\
+-		".previous"			\
+-		: :"r" (value), "r" (0))
+-
+-/*
+- * Clear and set 'TS' bit respectively
+- */
+-#define clts() (HYPERVISOR_fpu_taskswitch(0))
+-
+-static inline unsigned long read_cr0(void)
+-{ 
+-	unsigned long cr0;
+-	asm volatile("movq %%cr0,%0" : "=r" (cr0));
+-	return cr0;
+-}
+-
+-static inline void write_cr0(unsigned long val) 
+-{ 
+-	asm volatile("movq %0,%%cr0" :: "r" (val));
+-}
+-
+-#define read_cr2() current_vcpu_info()->arch.cr2
+-
+-#define write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val)))
+-
+-#define read_cr3() ({ \
+-	unsigned long __dummy; \
+-	asm volatile("movq %%cr3,%0" : "=r" (__dummy)); \
+-	machine_to_phys(__dummy); \
+-})
+-
+-static inline void write_cr3(unsigned long val)
+-{
+-	val = phys_to_machine(val);
+-	asm volatile("movq %0,%%cr3" :: "r" (val) : "memory");
+-}
+-
+-static inline unsigned long read_cr4(void)
+-{ 
+-	unsigned long cr4;
+-	asm volatile("movq %%cr4,%0" : "=r" (cr4));
+-	return cr4;
+-}
+-
+-static inline void write_cr4(unsigned long val)
+-{ 
+-	asm volatile("movq %0,%%cr4" :: "r" (val) : "memory");
+-}
+ 
+ static inline unsigned long read_cr8(void)
+ {
+@@ -128,52 +15,6 @@ static inline void write_cr8(unsigned lo
+ 	BUG_ON(val);
+ }
+ 
+-#define stts() (HYPERVISOR_fpu_taskswitch(1))
+-
+-#define wbinvd() \
+-	__asm__ __volatile__ ("wbinvd": : :"memory")
+-
+-#endif	/* __KERNEL__ */
+-
+-static inline void clflush(volatile void *__p)
+-{
+-	asm volatile("clflush %0" : "+m" (*(char __force *)__p));
+-}
+-
+-#define nop() __asm__ __volatile__ ("nop")
+-
+-#ifdef CONFIG_SMP
+-#define smp_mb()	mb()
+-#define smp_rmb()	barrier()
+-#define smp_wmb()	barrier()
+-#define smp_read_barrier_depends()	do {} while(0)
+-#else
+-#define smp_mb()	barrier()
+-#define smp_rmb()	barrier()
+-#define smp_wmb()	barrier()
+-#define smp_read_barrier_depends()	do {} while(0)
+-#endif
+-
+-    
+-/*
+- * Force strict CPU ordering.
+- * And yes, this is required on UP too when we're talking
+- * to devices.
+- */
+-#define mb() 	asm volatile("mfence":::"memory")
+-#define rmb()	asm volatile("lfence":::"memory")
+-#define wmb()	asm volatile("sfence" ::: "memory")
+-
+-#define read_barrier_depends()	do {} while(0)
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+-
+-#define warn_if_not_ulong(x) do { unsigned long foo; (void) (&(x) == &foo); } while (0)
+-
+ #include <linux/irqflags.h>
+ 
+-void cpu_idle_wait(void);
+-
+-extern unsigned long arch_align_stack(unsigned long sp);
+-extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+-
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:25.000000000 +0100
+@@ -1,5 +1,106 @@
++#ifndef _ASM_X86_TLBFLUSH_H
++#define _ASM_X86_TLBFLUSH_H
++
++#include <linux/mm.h>
++#include <linux/sched.h>
++
++#include <asm/processor.h>
++#include <asm/system.h>
++
++#define __flush_tlb() xen_tlb_flush()
++#define __flush_tlb_global() xen_tlb_flush()
++#define __flush_tlb_single(addr) xen_invlpg(addr)
++#define __flush_tlb_all() xen_tlb_flush()
++#define __flush_tlb_one(addr) xen_invlpg(addr)
++
+ #ifdef CONFIG_X86_32
+-# include "tlbflush_32.h"
++# define TLB_FLUSH_ALL	0xffffffff
+ #else
+-# include "tlbflush_64.h"
++# define TLB_FLUSH_ALL	-1ULL
+ #endif
++
++/*
++ * TLB flushing:
++ *
++ *  - flush_tlb() flushes the current mm struct TLBs
++ *  - flush_tlb_all() flushes all processes TLBs
++ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
++ *  - flush_tlb_page(vma, vmaddr) flushes one page
++ *  - flush_tlb_range(vma, start, end) flushes a range of pages
++ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
++ *
++ * ..but the i386 has somewhat limited tlb flushing capabilities,
++ * and page-granular flushes are available only on i486 and up.
++ *
++ * x86-64 can only flush individual pages or full VMs. For a range flush
++ * we always do the full VM. Might be worth trying if for a small
++ * range a few INVLPGs in a row are a win.
++ */
++
++#ifndef CONFIG_SMP
++
++#define flush_tlb() __flush_tlb()
++#define flush_tlb_all() __flush_tlb_all()
++#define local_flush_tlb() __flush_tlb()
++
++static inline void flush_tlb_mm(struct mm_struct *mm)
++{
++	if (mm == current->active_mm)
++		__flush_tlb();
++}
++
++static inline void flush_tlb_page(struct vm_area_struct *vma,
++				  unsigned long addr)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb_one(addr);
++}
++
++static inline void flush_tlb_range(struct vm_area_struct *vma,
++				   unsigned long start, unsigned long end)
++{
++	if (vma->vm_mm == current->active_mm)
++		__flush_tlb();
++}
++
++#else  /* SMP */
++
++#include <asm/smp.h>
++
++#define local_flush_tlb() __flush_tlb()
++
++#define flush_tlb_all xen_tlb_flush_all
++#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
++#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
++#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
++
++#define flush_tlb()	flush_tlb_current_task()
++
++static inline void flush_tlb_range(struct vm_area_struct *vma,
++				   unsigned long start, unsigned long end)
++{
++	flush_tlb_mm(vma->vm_mm);
++}
++
++#define TLBSTATE_OK	1
++#define TLBSTATE_LAZY	2
++
++#ifdef CONFIG_X86_32
++struct tlb_state
++{
++	struct mm_struct *active_mm;
++	int state;
++	char __cacheline_padding[L1_CACHE_BYTES-8];
++};
++DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
++#endif
++
++#endif	/* SMP */
++
++static inline void flush_tlb_kernel_range(unsigned long start,
++					  unsigned long end)
++{
++	flush_tlb_all();
++}
++
++#endif /* _ASM_X86_TLBFLUSH_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,99 +0,0 @@
+-#ifndef _I386_TLBFLUSH_H
+-#define _I386_TLBFLUSH_H
+-
+-#include <linux/mm.h>
+-#include <asm/processor.h>
+-
+-#define __flush_tlb() xen_tlb_flush()
+-#define __flush_tlb_global() xen_tlb_flush()
+-#define __flush_tlb_all() xen_tlb_flush()
+-
+-#define cpu_has_invlpg	(boot_cpu_data.x86 > 3)
+-
+-#define __flush_tlb_single(addr) xen_invlpg(addr)
+-
+-#define __flush_tlb_one(addr) __flush_tlb_single(addr)
+-
+-/*
+- * TLB flushing:
+- *
+- *  - flush_tlb() flushes the current mm struct TLBs
+- *  - flush_tlb_all() flushes all processes TLBs
+- *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+- *  - flush_tlb_page(vma, vmaddr) flushes one page
+- *  - flush_tlb_range(vma, start, end) flushes a range of pages
+- *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+- *
+- * ..but the i386 has somewhat limited tlb flushing capabilities,
+- * and page-granular flushes are available only on i486 and up.
+- */
+-
+-#define TLB_FLUSH_ALL	0xffffffff
+-
+-
+-#ifndef CONFIG_SMP
+-
+-#include <linux/sched.h>
+-
+-#define flush_tlb() __flush_tlb()
+-#define flush_tlb_all() __flush_tlb_all()
+-#define local_flush_tlb() __flush_tlb()
+-
+-static inline void flush_tlb_mm(struct mm_struct *mm)
+-{
+-	if (mm == current->active_mm)
+-		__flush_tlb();
+-}
+-
+-static inline void flush_tlb_page(struct vm_area_struct *vma,
+-	unsigned long addr)
+-{
+-	if (vma->vm_mm == current->active_mm)
+-		__flush_tlb_one(addr);
+-}
+-
+-static inline void flush_tlb_range(struct vm_area_struct *vma,
+-	unsigned long start, unsigned long end)
+-{
+-	if (vma->vm_mm == current->active_mm)
+-		__flush_tlb();
+-}
+-
+-#else  /* SMP */
+-
+-#include <asm/smp.h>
+-
+-#define local_flush_tlb() \
+-	__flush_tlb()
+-
+-#define flush_tlb_all xen_tlb_flush_all
+-#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
+-#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
+-#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
+-
+-#define flush_tlb()	flush_tlb_current_task()
+-
+-static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
+-{
+-	flush_tlb_mm(vma->vm_mm);
+-}
+-
+-#define TLBSTATE_OK	1
+-#define TLBSTATE_LAZY	2
+-
+-struct tlb_state
+-{
+-	struct mm_struct *active_mm;
+-	int state;
+-	char __cacheline_padding[L1_CACHE_BYTES-8];
+-};
+-DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
+-#endif	/* SMP */
+-
+-static inline void flush_tlb_kernel_range(unsigned long start,
+-					unsigned long end)
+-{
+-	flush_tlb_all();
+-}
+-
+-#endif /* _I386_TLBFLUSH_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:51:17.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,97 +0,0 @@
+-#ifndef _X8664_TLBFLUSH_H
+-#define _X8664_TLBFLUSH_H
+-
+-#include <linux/mm.h>
+-#include <linux/sched.h>
+-#include <asm/processor.h>
+-#include <asm/system.h>
+-
+-#define __flush_tlb()	xen_tlb_flush()
+-
+-/*
+- * Global pages have to be flushed a bit differently. Not a real
+- * performance problem because this does not happen often.
+- */
+-#define __flush_tlb_global()	xen_tlb_flush()
+-
+-#define __flush_tlb_all() __flush_tlb_global()
+-
+-#define __flush_tlb_one(addr)	xen_invlpg((unsigned long)addr)
+-
+-
+-/*
+- * TLB flushing:
+- *
+- *  - flush_tlb() flushes the current mm struct TLBs
+- *  - flush_tlb_all() flushes all processes TLBs
+- *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+- *  - flush_tlb_page(vma, vmaddr) flushes one page
+- *  - flush_tlb_range(vma, start, end) flushes a range of pages
+- *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+- *
+- * x86-64 can only flush individual pages or full VMs. For a range flush
+- * we always do the full VM. Might be worth trying if for a small
+- * range a few INVLPGs in a row are a win.
+- */
+-
+-#ifndef CONFIG_SMP
+-
+-#define flush_tlb() __flush_tlb()
+-#define flush_tlb_all() __flush_tlb_all()
+-#define local_flush_tlb() __flush_tlb()
+-
+-static inline void flush_tlb_mm(struct mm_struct *mm)
+-{
+-	if (mm == current->active_mm)
+-		__flush_tlb();
+-}
+-
+-static inline void flush_tlb_page(struct vm_area_struct *vma,
+-	unsigned long addr)
+-{
+-	if (vma->vm_mm == current->active_mm)
+-		__flush_tlb_one(addr);
+-}
+-
+-static inline void flush_tlb_range(struct vm_area_struct *vma,
+-	unsigned long start, unsigned long end)
+-{
+-	if (vma->vm_mm == current->active_mm)
+-		__flush_tlb();
+-}
+-
+-#else
+-
+-#include <asm/smp.h>
+-
+-#define local_flush_tlb() \
+-	__flush_tlb()
+-
+-#define flush_tlb_all xen_tlb_flush_all
+-#define flush_tlb_current_task() xen_tlb_flush_mask(&current->mm->cpu_vm_mask)
+-#define flush_tlb_mm(mm) xen_tlb_flush_mask(&(mm)->cpu_vm_mask)
+-#define flush_tlb_page(vma, va) xen_invlpg_mask(&(vma)->vm_mm->cpu_vm_mask, va)
+-
+-#define flush_tlb()	flush_tlb_current_task()
+-
+-static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
+-{
+-	flush_tlb_mm(vma->vm_mm);
+-}
+-
+-#define TLBSTATE_OK	1
+-#define TLBSTATE_LAZY	2
+-
+-/* Roughly an IPI every 20MB with 4k pages for freeing page table
+-   ranges. Cost is about 42k of memory for each CPU. */
+-#define ARCH_FREE_PTE_NR 5350	
+-
+-#endif
+-
+-static inline void flush_tlb_kernel_range(unsigned long start,
+-					unsigned long end)
+-{
+-	flush_tlb_all();
+-}
+-
+-#endif /* _X8664_TLBFLUSH_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/irq_vectors.h	2008-09-25 13:55:32.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/irq_vectors.h	2009-11-06 10:51:25.000000000 +0100
+@@ -82,7 +82,8 @@
+ 
+ #define RESCHEDULE_VECTOR	0
+ #define CALL_FUNCTION_VECTOR	1
+-#define NR_IPIS			2
++#define SPIN_UNLOCK_VECTOR	2
++#define NR_IPIS			3
+ 
+ /*
+  * The maximum number of vectors supported by i386 processors
+--- head-2010-01-18.orig/arch/x86/include/asm/mmu.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/mmu.h	2009-11-06 10:51:25.000000000 +0100
+@@ -18,7 +18,7 @@ typedef struct {
+ 	void *vdso;
+ } mm_context_t;
+ 
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ void leave_mm(int cpu);
+ #else
+ static inline void leave_mm(int cpu)
+--- head-2010-01-18.orig/arch/x86/include/asm/ptrace.h	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/ptrace.h	2009-11-06 10:51:25.000000000 +0100
+@@ -247,7 +247,9 @@ extern void user_enable_single_step(stru
+ extern void user_disable_single_step(struct task_struct *);
+ 
+ extern void user_enable_block_step(struct task_struct *);
+-#ifdef CONFIG_X86_DEBUGCTLMSR
++#if defined(CONFIG_XEN)
++#define arch_has_block_step()	(0)
++#elif defined(CONFIG_X86_DEBUGCTLMSR)
+ #define arch_has_block_step()	(1)
+ #else
+ #define arch_has_block_step()	(boot_cpu_data.x86 >= 6)
+--- head-2010-01-18.orig/arch/x86/include/asm/thread_info.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/thread_info.h	2009-11-06 10:51:25.000000000 +0100
+@@ -96,6 +96,9 @@ struct thread_info {
+ #define TIF_DS_AREA_MSR		26      /* uses thread_struct.ds_area_msr */
+ #define TIF_LAZY_MMU_UPDATES	27	/* task is updating the mmu lazily */
+ #define TIF_SYSCALL_TRACEPOINT	28	/* syscall tracepoint instrumentation */
++#ifdef CONFIG_X86_XEN
++#define TIF_CSTAR		31      /* cstar-based syscall (special handling) */
++#endif
+ 
+ #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+ #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+@@ -119,6 +122,7 @@ struct thread_info {
+ #define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
+ #define _TIF_LAZY_MMU_UPDATES	(1 << TIF_LAZY_MMU_UPDATES)
+ #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
++#define _TIF_CSTAR		(1 << TIF_CSTAR)
+ 
+ /* work to do in syscall_trace_enter() */
+ #define _TIF_WORK_SYSCALL_ENTRY	\
+@@ -149,12 +153,12 @@ struct thread_info {
+ #define _TIF_WORK_CTXSW							\
+ 	(_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_NOTSC)
+ 
+-#define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
+-#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
+ #else
+-#define _TIF_WORK_CTXSW_NEXT (_TIF_NOTSC | _TIF_DEBUG)
+-#define _TIF_WORK_CTXSW_PREV (_TIF_NOTSC)
++#define _TIF_WORK_CTXSW (_TIF_NOTSC \
++     /*todo | _TIF_DEBUGCTLMSR | _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS*/)
+ #endif
++#define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
++#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
+ 
+ #define PREEMPT_ACTIVE		0x10000000
+ 
+--- head-2010-01-18.orig/arch/x86/include/asm/time.h	2010-01-18 17:09:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/time.h	2009-11-06 10:51:25.000000000 +0100
+@@ -7,4 +7,10 @@ extern void hpet_time_init(void);
+ 
+ extern void time_init(void);
+ 
++#ifdef CONFIG_XEN
++extern int xen_independent_wallclock(void);
++extern unsigned long xen_read_persistent_clock(void);
++extern int xen_update_persistent_clock(void);
++#endif
++
+ #endif /* _ASM_X86_TIME_H */
+--- head-2010-01-18.orig/include/linux/page-flags.h	2009-12-16 11:50:02.000000000 +0100
++++ head-2010-01-18/include/linux/page-flags.h	2009-12-16 11:50:48.000000000 +0100
+@@ -130,8 +130,8 @@ enum pageflags {
+ #ifdef CONFIG_XEN
+ 	PG_pinned = PG_locked,	/* Cannot alias with PG_owner_priv_1 since
+ 				 * bad_page() checks should include this bit.
+-				 * Also cannot use PG_arch_1 since that now
+-				 * has a different purpose on x86. */
++				 * Should not use PG_arch_1 as that may have
++				 * a different purpose elsewhere. */
+ #else
+ 	PG_pinned = PG_owner_priv_1,
+ 	PG_savepinned = PG_dirty,
+--- head-2010-01-18.orig/include/linux/pci.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/include/linux/pci.h	2009-11-06 10:51:25.000000000 +0100
+@@ -721,6 +721,9 @@ int pci_reset_function(struct pci_dev *d
+ void pci_update_resource(struct pci_dev *dev, int resno);
+ int __must_check pci_assign_resource(struct pci_dev *dev, int i);
+ int pci_select_bars(struct pci_dev *dev, unsigned long flags);
++#ifdef CONFIG_XEN
++void pci_restore_bars(struct pci_dev *);
++#endif
+ 
+ /* ROM control related routines */
+ int pci_enable_rom(struct pci_dev *pdev);
+--- head-2010-01-18.orig/include/xen/evtchn.h	2009-12-18 10:09:29.000000000 +0100
++++ head-2010-01-18/include/xen/evtchn.h	2009-12-18 10:09:52.000000000 +0100
+@@ -133,12 +133,37 @@ static inline void clear_evtchn(int port
+ 	synch_clear_bit(port, s->evtchn_pending);
+ }
+ 
++static inline void set_evtchn(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	synch_set_bit(port, s->evtchn_pending);
++}
++
++static inline int test_evtchn(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	return synch_test_bit(port, s->evtchn_pending);
++}
++
+ static inline void notify_remote_via_evtchn(int port)
+ {
+ 	struct evtchn_send send = { .port = port };
+ 	VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send));
+ }
+ 
++/* Clear an irq's pending state, in preparation for polling on it. */
++void xen_clear_irq_pending(int irq);
++
++/* Set an irq's pending state, to avoid blocking on it. */
++void xen_set_irq_pending(int irq);
++
++/* Test an irq's pending state. */
++int xen_test_irq_pending(int irq);
++
++/* Poll waiting for an irq to become pending.  In the usual case, the
++   irq will be disabled so it won't deliver an interrupt. */
++void xen_poll_irq(int irq);
++
+ /*
+  * Use these to access the event channel underlying the IRQ handle returned
+  * by bind_*_to_irqhandler().
+--- head-2010-01-18.orig/kernel/sysctl_check.c	2009-12-16 11:50:26.000000000 +0100
++++ head-2010-01-18/kernel/sysctl_check.c	2009-12-16 11:50:55.000000000 +0100
+@@ -898,7 +898,7 @@ static const struct trans_ctl_table tran
+ };
+ 
+ #ifdef CONFIG_XEN
+-static struct trans_ctl_table trans_xen_table[] = {
++static const struct trans_ctl_table trans_xen_table[] = {
+ 	{ CTL_XEN_INDEPENDENT_WALLCLOCK,	"independent_wallclock" },
+ 	{ CTL_XEN_PERMITTED_CLOCK_JITTER,	"permitted_clock_jitter" },
+ 	{}
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:51:25.000000000 +0100
+@@ -30,7 +30,6 @@
+ #include <asm/gnttab_dma.h>
+ 
+ int swiotlb;
+-EXPORT_SYMBOL(swiotlb);
+ 
+ #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
+ 
+@@ -289,6 +288,15 @@ __sync_single(struct phys_addr buffer, c
+ 	}
+ }
+ 
++static inline unsigned int is_span_boundary(unsigned int index,
++					    unsigned int nslots,
++					    unsigned long offset_slots,
++					    unsigned long max_slots)
++{
++	unsigned long offset = (offset_slots + index) & (max_slots - 1);
++	return offset + nslots > max_slots;
++}
++
+ /*
+  * Allocates bounce buffer and returns its kernel virtual address.
+  */
+@@ -300,6 +308,15 @@ map_single(struct device *hwdev, struct 
+ 	unsigned int nslots, stride, index, wrap;
+ 	struct phys_addr slot_buf;
+ 	int i;
++	unsigned long mask;
++	unsigned long offset_slots;
++	unsigned long max_slots;
++
++	mask = dma_get_seg_boundary(hwdev);
++	offset_slots = -IO_TLB_SEGSIZE;
++	max_slots = mask + 1
++		    ? ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT
++		    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+ 
+ 	/*
+ 	 * For mappings greater than a page, we limit the stride (and
+@@ -319,12 +336,21 @@ map_single(struct device *hwdev, struct 
+ 	 */
+ 	spin_lock_irqsave(&io_tlb_lock, flags);
+ 	{
+-		wrap = index = ALIGN(io_tlb_index, stride);
+-
++		index = ALIGN(io_tlb_index, stride);
+ 		if (index >= iotlb_nslabs)
+-			wrap = index = 0;
++			index = 0;
++		wrap = index;
+ 
+ 		do {
++			while (is_span_boundary(index, nslots, offset_slots,
++						max_slots)) {
++				index += stride;
++				if (index >= iotlb_nslabs)
++					index = 0;
++				if (index == wrap)
++					goto not_found;
++			}
++
+ 			/*
+ 			 * If we find a slot that indicates we have 'nslots'
+ 			 * number of contiguous buffers, we allocate the
+@@ -359,6 +385,7 @@ map_single(struct device *hwdev, struct 
+ 				index = 0;
+ 		} while (index != wrap);
+ 
++  not_found:
+ 		spin_unlock_irqrestore(&io_tlb_lock, flags);
+ 		return NULL;
+ 	}
+--- head-2010-01-18.orig/mm/memory.c	2009-12-04 10:48:12.000000000 +0100
++++ head-2010-01-18/mm/memory.c	2009-12-16 11:50:45.000000000 +0100
+@@ -2017,6 +2017,10 @@ int apply_to_page_range(struct mm_struct
+ 	unsigned long start = addr, end = addr + size;
+ 	int err;
+ 
++#ifdef CONFIG_XEN
++	if (!mm)
++		mm = &init_mm;
++#endif
+ 	BUG_ON(addr >= end);
+ 	mmu_notifier_invalidate_range_start(mm, start, end);
+ 	pgd = pgd_offset(mm, addr);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-spinlock-poll-early
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-spinlock-poll-early
@@ -0,0 +1,118 @@
+From: jbeulich@novell.com
+Subject: Go into polling mode early if lock owner is not running
+Patch-mainline: n/a
+
+This could be merged into the original ticket spinlock code once
+validated, if there wasn't the dependency on smp-processor-id.h, which
+only gets introduced in the 2.6.32 merge.
+
+--- head-2009-11-20.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:31:08.000000000 +0100
++++ head-2009-11-20/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-23 10:58:32.000000000 +0100
+@@ -40,6 +40,11 @@
+ 
+ #ifdef TICKET_SHIFT
+ 
++#include <asm/smp-processor-id.h>
++#include <xen/interface/vcpu.h>
++
++DECLARE_PER_CPU(struct vcpu_runstate_info, runstate);
++
+ int xen_spinlock_init(unsigned int cpu);
+ void xen_spinlock_cleanup(unsigned int cpu);
+ int xen_spin_wait(raw_spinlock_t *, unsigned int token);
+@@ -105,6 +110,9 @@ static __always_inline int __ticket_spin
+ 	    :
+ 	    : "memory", "cc");
+ 
++	if (tmp)
++		lock->owner = raw_smp_processor_id();
++
+ 	return tmp;
+ }
+ 
+@@ -174,6 +182,9 @@ static __always_inline int __ticket_spin
+ 	    :
+ 	    : "memory", "cc");
+ 
++	if (tmp)
++		lock->owner = raw_smp_processor_id();
++
+ 	return tmp;
+ }
+ 
+@@ -195,6 +206,10 @@ static __always_inline void __ticket_spi
+ }
+ #endif
+ 
++#define __ticket_spin_count(lock) \
++	(per_cpu(runstate.state, (lock)->owner) == RUNSTATE_running \
++	 ? 1 << 10 : 1)
++
+ static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
+ {
+ 	int tmp = ACCESS_ONCE(lock->slock);
+@@ -219,9 +234,10 @@ static __always_inline void __ticket_spi
+ 		return;
+ 	token = xen_spin_adjust(lock, token);
+ 	do {
+-		count = 1 << 10;
++		count = __ticket_spin_count(lock);
+ 		__ticket_spin_lock_body;
+ 	} while (unlikely(!count) && !xen_spin_wait(lock, token));
++	lock->owner = raw_smp_processor_id();
+ }
+ 
+ static __always_inline void __ticket_spin_lock_flags(raw_spinlock_t *lock,
+@@ -235,13 +251,15 @@ static __always_inline void __ticket_spi
+ 		return;
+ 	token = xen_spin_adjust(lock, token);
+ 	do {
+-		count = 1 << 10;
++		count = __ticket_spin_count(lock);
+ 		__ticket_spin_lock_body;
+ 	} while (unlikely(!count) && !xen_spin_wait_flags(lock, &token, flags));
++	lock->owner = raw_smp_processor_id();
+ }
+ 
+ #undef __ticket_spin_lock_preamble
+ #undef __ticket_spin_lock_body
++#undef __ticket_spin_count
+ 
+ #define __raw_spin(n) __ticket_spin_##n
+ 
+--- head-2009-11-20.orig/arch/x86/include/mach-xen/asm/spinlock_types.h	2009-11-17 15:20:36.000000000 +0100
++++ head-2009-11-20/arch/x86/include/mach-xen/asm/spinlock_types.h	2009-11-17 15:21:37.000000000 +0100
+@@ -39,6 +39,11 @@ typedef union raw_spinlock {
+ # error NR_CPUS >= 256 not implemented
+ #endif
+ #endif
++#if CONFIG_NR_CPUS <= 256
++		u8 owner;
++#else
++		u16 owner;
++#endif
+ 	};
+ } raw_spinlock_t;
+ 
+--- head-2009-11-20.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:53:51.000000000 +0100
++++ head-2009-11-20/arch/x86/kernel/time-xen.c	2009-11-23 10:58:42.000000000 +0100
+@@ -65,7 +65,7 @@ static DEFINE_PER_CPU(u64, processed_sto
+ static DEFINE_PER_CPU(u64, processed_blocked_time);
+ 
+ /* Current runstate of each CPU (updated automatically by the hypervisor). */
+-static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
++DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+ 
+ /* Must be signed, as it's compared with s64 quantities which can be -ve. */
+ #define NS_PER_TICK (1000000000LL/HZ)
+--- head-2009-11-20.orig/drivers/xen/core/spinlock.c	2009-11-17 11:47:19.000000000 +0100
++++ head-2009-11-20/drivers/xen/core/spinlock.c	2009-11-23 10:58:19.000000000 +0100
+@@ -38,6 +38,8 @@ int __cpuinit xen_spinlock_init(unsigned
+ 	};
+ 	int rc;
+ 
++	setup_runstate_area(cpu);
++
+ 	rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR,
+ 				   cpu,
+ 				   &spinlock_action);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-x86_64-unwind-annotations
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-x86_64-unwind-annotations
@@ -0,0 +1,319 @@
+From: jbeulich@novell.com
+Subject: fix unwind annotations
+Patch-mainline: tbd
+References: bnc#472783
+
+Automatically created from "patches.arch/x86_64-unwind-annotations" by xen-port-patches.py
+
+--- head-2009-10-12.orig/arch/x86/kernel/entry_64-xen.S	2009-10-14 18:35:25.000000000 +0200
++++ head-2009-10-12/arch/x86/kernel/entry_64-xen.S	2009-10-14 18:35:30.000000000 +0200
+@@ -41,6 +41,7 @@
+  */
+ 
+ #include <linux/linkage.h>
++#include <linux/stringify.h>
+ #include <asm/segment.h>
+ #include <asm/cache.h>
+ #include <asm/errno.h>
+@@ -238,21 +239,21 @@ NMI_MASK = 0x80000000
+ /*
+  * initial frame state for interrupts (and exceptions without error code)
+  */
+-	.macro EMPTY_FRAME start=1 offset=0
+-	.if \start
++	.macro EMPTY_FRAME offset=0
+ 	CFI_STARTPROC simple
+ 	CFI_SIGNAL_FRAME
+-	CFI_DEF_CFA rsp,8+\offset
+-	.else
+-	CFI_DEF_CFA_OFFSET 8+\offset
+-	.endif
++	CFI_DEF_CFA rsp,\offset
+ 	.endm
+ 
+ /*
+  * initial frame state for syscall
+  */
+ 	.macro BASIC_FRAME start=1 offset=0
+-	EMPTY_FRAME \start, SS+8+\offset-RIP
++	.if \start
++	EMPTY_FRAME __stringify(SS+8+\offset-RIP)
++	.else
++	CFI_DEF_CFA_OFFSET SS+8+\offset-RIP
++	.endif
+ 	/*CFI_REL_OFFSET ss, SS+\offset-RIP*/
+ 	CFI_REL_OFFSET rsp, RSP+\offset-RIP
+ 	/*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
+@@ -278,15 +279,16 @@ NMI_MASK = 0x80000000
+  * with vector already pushed)
+  */
+ 	.macro XCPT_FRAME start=1 offset=0
+-	INTR_FRAME \start, RIP+\offset-ORIG_RAX
+-	/*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/
++	INTR_FRAME \start, __stringify(RIP+\offset-ORIG_RAX)
+ 	.endm
+ 
+ /*
+  * frame that enables calling into C.
+  */
+ 	.macro PARTIAL_FRAME start=1 offset=0
+-	XCPT_FRAME 2*\start, ORIG_RAX+\offset-ARGOFFSET
++	.if \start >= 0
++	XCPT_FRAME 2*\start, __stringify(ORIG_RAX+\offset-ARGOFFSET)
++	.endif
+ 	CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
+ 	CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
+ 	CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
+@@ -302,7 +304,9 @@ NMI_MASK = 0x80000000
+  * frame that enables passing a complete pt_regs to a C function.
+  */
+ 	.macro DEFAULT_FRAME start=1 offset=0
+-	PARTIAL_FRAME \start, R11+\offset-R15
++	.if \start >= -1
++	PARTIAL_FRAME \start, __stringify(R11+\offset-R15)
++	.endif
+ 	CFI_REL_OFFSET rbx, RBX+\offset
+ 	CFI_REL_OFFSET rbp, RBP+\offset
+ 	CFI_REL_OFFSET r12, R12+\offset
+@@ -341,21 +345,23 @@ NMI_MASK = 0x80000000
+ #ifndef CONFIG_XEN
+ /* save partial stack frame */
+ ENTRY(save_args)
+-	XCPT_FRAME
++	XCPT_FRAME offset=__stringify(ORIG_RAX-ARGOFFSET+16)
+ 	cld
+-	movq_cfi rdi, RDI+16-ARGOFFSET
+-	movq_cfi rsi, RSI+16-ARGOFFSET
+-	movq_cfi rdx, RDX+16-ARGOFFSET
+-	movq_cfi rcx, RCX+16-ARGOFFSET
+-	movq_cfi rax, RAX+16-ARGOFFSET
+-	movq_cfi  r8,  R8+16-ARGOFFSET
+-	movq_cfi  r9,  R9+16-ARGOFFSET
+-	movq_cfi r10, R10+16-ARGOFFSET
+-	movq_cfi r11, R11+16-ARGOFFSET
++	movq %rdi, RDI+16-ARGOFFSET(%rsp)
++	movq %rsi, RSI+16-ARGOFFSET(%rsp)
++	movq %rdx, RDX+16-ARGOFFSET(%rsp)
++	movq %rcx, RCX+16-ARGOFFSET(%rsp)
++	movq_cfi rax, __stringify(RAX+16-ARGOFFSET)
++	movq  %r8,  R8+16-ARGOFFSET(%rsp)
++	movq  %r9,  R9+16-ARGOFFSET(%rsp)
++	movq %r10, R10+16-ARGOFFSET(%rsp)
++	movq_cfi r11, __stringify(R11+16-ARGOFFSET)
+ 
+ 	leaq -ARGOFFSET+16(%rsp),%rdi	/* arg1 for handler */
+ 	movq_cfi rbp, 8		/* push %rbp */
+ 	leaq 8(%rsp), %rbp		/* mov %rsp, %ebp */
++	CFI_DEF_CFA_REGISTER rbp
++	CFI_ADJUST_CFA_OFFSET -8
+ 	testl $3, CS(%rdi)
+ 	je 1f
+ 	SWAPGS
+@@ -367,11 +373,10 @@ ENTRY(save_args)
+ 	 */
+ 1:	incl PER_CPU_VAR(irq_count)
+ 	jne 2f
+-	popq_cfi %rax			/* move return address... */
++	popq %rax			/* move return address... */
+ 	mov PER_CPU_VAR(irq_stack_ptr),%rsp
+-	EMPTY_FRAME 0
+-	pushq_cfi %rbp			/* backlink for unwinder */
+-	pushq_cfi %rax			/* ... to the new stack */
++	pushq %rbp			/* backlink for unwinder */
++	pushq %rax			/* ... to the new stack */
+ 	/*
+ 	 * We entered an interrupt context - irqs are off:
+ 	 */
+@@ -382,14 +387,14 @@ END(save_args)
+ #endif
+ 
+ ENTRY(save_rest)
+-	PARTIAL_FRAME 1 REST_SKIP+8
++	CFI_STARTPROC
+ 	movq 5*8+16(%rsp), %r11	/* save return address */
+-	movq_cfi rbx, RBX+16
+-	movq_cfi rbp, RBP+16
+-	movq_cfi r12, R12+16
+-	movq_cfi r13, R13+16
+-	movq_cfi r14, R14+16
+-	movq_cfi r15, R15+16
++	movq %rbx, RBX+16(%rsp)
++	movq %rbp, RBP+16(%rsp)
++	movq %r12, R12+16(%rsp)
++	movq %r13, R13+16(%rsp)
++	movq %r14, R14+16(%rsp)
++	movq %r15, R15+16(%rsp)
+ 	movq %r11, 8(%rsp)	/* return address */
+ 	FIXUP_TOP_OF_STACK %r11, 16
+ 	ret
+@@ -400,23 +405,23 @@ END(save_rest)
+ /* save complete stack frame */
+ 	.pushsection .kprobes.text, "ax"
+ ENTRY(save_paranoid)
+-	XCPT_FRAME 1 RDI+8
++	XCPT_FRAME offset=__stringify(ORIG_RAX-R15+8)
+ 	cld
+-	movq_cfi rdi, RDI+8
+-	movq_cfi rsi, RSI+8
+-	movq_cfi rdx, RDX+8
+-	movq_cfi rcx, RCX+8
+-	movq_cfi rax, RAX+8
+-	movq_cfi r8, R8+8
+-	movq_cfi r9, R9+8
+-	movq_cfi r10, R10+8
+-	movq_cfi r11, R11+8
+-	movq_cfi rbx, RBX+8
+-	movq_cfi rbp, RBP+8
+-	movq_cfi r12, R12+8
+-	movq_cfi r13, R13+8
+-	movq_cfi r14, R14+8
+-	movq_cfi r15, R15+8
++	movq %rdi, RDI+8(%rsp)
++	movq %rsi, RSI+8(%rsp)
++	movq_cfi rdx, __stringify(RDX+8)
++	movq_cfi rcx, __stringify(RCX+8)
++	movq_cfi rax, __stringify(RAX+8)
++	movq %r8, R8+8(%rsp)
++	movq %r9, R9+8(%rsp)
++	movq %r10, R10+8(%rsp)
++	movq %r11, R11+8(%rsp)
++	movq_cfi rbx, __stringify(RBX+8)
++	movq %rbp, RBP+8(%rsp)
++	movq %r12, R12+8(%rsp)
++	movq %r13, R13+8(%rsp)
++	movq %r14, R14+8(%rsp)
++	movq %r15, R15+8(%rsp)
+ 	movl $1,%ebx
+ 	movl $MSR_GS_BASE,%ecx
+ 	rdmsr
+@@ -707,7 +712,7 @@ ENTRY(\label)
+ 	subq $REST_SKIP, %rsp
+ 	CFI_ADJUST_CFA_OFFSET REST_SKIP
+ 	call save_rest
+-	DEFAULT_FRAME 0 8		/* offset 8: return address */
++	DEFAULT_FRAME -2 8		/* offset 8: return address */
+ 	leaq 8(%rsp), \arg	/* pt_regs pointer */
+ 	call \func
+ 	jmp ptregscall_common
+@@ -724,12 +729,12 @@ END(\label)
+ ENTRY(ptregscall_common)
+ 	DEFAULT_FRAME 1 8	/* offset 8: return address */
+ 	RESTORE_TOP_OF_STACK %r11, 8
+-	movq_cfi_restore R15+8, r15
+-	movq_cfi_restore R14+8, r14
+-	movq_cfi_restore R13+8, r13
+-	movq_cfi_restore R12+8, r12
+-	movq_cfi_restore RBP+8, rbp
+-	movq_cfi_restore RBX+8, rbx
++	movq_cfi_restore __stringify(R15+8), r15
++	movq_cfi_restore __stringify(R14+8), r14
++	movq_cfi_restore __stringify(R13+8), r13
++	movq_cfi_restore __stringify(R12+8), r12
++	movq_cfi_restore __stringify(RBP+8), rbp
++	movq_cfi_restore __stringify(RBX+8), rbx
+ 	ret $REST_SKIP		/* pop extended registers */
+ 	CFI_ENDPROC
+ END(ptregscall_common)
+@@ -933,10 +938,10 @@ ENTRY(\sym)
+         movq 8(%rsp),%r11
+ 	CFI_RESTORE r11
+ 	movq $-1,8(%rsp)	/* ORIG_RAX: no syscall to restart */
+-	subq $(15-1)*8,%rsp
+-	CFI_ADJUST_CFA_OFFSET (15-1)*8
++	subq $ORIG_RAX-R15-8, %rsp
++	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15-8
+ 	call error_entry
+-	DEFAULT_FRAME 0
++	DEFAULT_FRAME -1
+ 	movq %rsp,%rdi		/* pt_regs pointer */
+ 	xorl %esi,%esi		/* no error code */
+ 	call \do_sym
+@@ -960,10 +965,10 @@ ENTRY(\sym)
+ 	CFI_RESTORE rcx
+         movq 8(%rsp),%r11
+ 	CFI_RESTORE r11
+-	subq $(15-2)*8,%rsp
+-	CFI_ADJUST_CFA_OFFSET (15-2)*8
++	subq $ORIG_RAX-R15-2*8, %rsp
++	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15-2*8
+ 	call error_entry
+-	DEFAULT_FRAME 0
++	DEFAULT_FRAME -1
+ 	movq %rsp,%rdi			/* pt_regs pointer */
+ 	movq ORIG_RAX(%rsp),%rsi	/* get error code */
+ 	movq $-1,ORIG_RAX(%rsp)		/* no syscall to restart */
+@@ -1275,7 +1280,7 @@ paranoidzeroentry machine_check *machine
+ 
+ 	/* ebx:	no swapgs flag */
+ ENTRY(paranoid_exit)
+-	INTR_FRAME
++	DEFAULT_FRAME
+ 	DISABLE_INTERRUPTS(CLBR_NONE)
+ 	TRACE_IRQS_OFF
+ 	testl %ebx,%ebx				/* swapgs needed? */
+@@ -1326,25 +1331,24 @@ END(paranoid_exit)
+  * returns in "no swapgs flag" in %ebx.
+  */
+ ENTRY(error_entry)
+-	XCPT_FRAME 2
+-	CFI_ADJUST_CFA_OFFSET 15*8
++	XCPT_FRAME start=2 offset=__stringify(ORIG_RAX-R15+8)
+ 	/* oldrax contains error code */
+ 	cld
+-	movq_cfi rdi, RDI+8
+-	movq_cfi rsi, RSI+8
+-	movq_cfi rdx, RDX+8
+-	movq_cfi rcx, RCX+8
+-	movq_cfi rax, RAX+8
+-	movq_cfi  r8,  R8+8
+-	movq_cfi  r9,  R9+8
+-	movq_cfi r10, R10+8
+-	movq_cfi r11, R11+8
+-	movq_cfi rbx, RBX+8
+-	movq_cfi rbp, RBP+8
+-	movq_cfi r12, R12+8
+-	movq_cfi r13, R13+8
+-	movq_cfi r14, R14+8
+-	movq_cfi r15, R15+8
++	movq %rdi, RDI+8(%rsp)
++	movq %rsi, RSI+8(%rsp)
++	movq %rdx, RDX+8(%rsp)
++	movq %rcx, RCX+8(%rsp)
++	movq %rax, RAX+8(%rsp)
++	movq  %r8,  R8+8(%rsp)
++	movq  %r9,  R9+8(%rsp)
++	movq %r10, R10+8(%rsp)
++	movq %r11, R11+8(%rsp)
++	movq_cfi rbx, __stringify(RBX+8)
++	movq %rbp, RBP+8(%rsp)
++	movq %r12, R12+8(%rsp)
++	movq %r13, R13+8(%rsp)
++	movq %r14, R14+8(%rsp)
++	movq %r15, R15+8(%rsp)
+ #ifndef CONFIG_XEN
+ 	xorl %ebx,%ebx
+ 	testl $3,CS+8(%rsp)
+@@ -1355,7 +1359,6 @@ error_sti:
+ #endif
+ 	TRACE_IRQS_OFF
+ 	ret
+-	CFI_ENDPROC
+ 
+ #ifndef CONFIG_XEN
+ /*
+@@ -1366,6 +1369,7 @@ error_sti:
+  * compat mode. Check for these here too.
+  */
+ error_kernelspace:
++	CFI_REL_OFFSET rcx, RCX+8
+ 	incl %ebx
+ 	leaq irq_return(%rip),%rcx
+ 	cmpq %rcx,RIP+8(%rsp)
+@@ -1377,6 +1381,7 @@ error_kernelspace:
+ 	je error_swapgs
+ 	jmp error_sti
+ #endif
++	CFI_ENDPROC
+ END(error_entry)
+ 
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-fixup-xen
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-fixup-xen
@@ -0,0 +1,6372 @@
+Subject: Fix Xen build wrt. Xen files coming from mainline.
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-07.orig/drivers/xen/Makefile	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/Makefile	2009-12-04 10:44:50.000000000 +0100
+@@ -1,12 +1,28 @@
+-obj-y	+= grant-table.o features.o events.o manage.o
++obj-y	+= core/
++obj-y	+= console/
++obj-y	+= evtchn/
+ obj-y	+= xenbus/
++obj-y	+= char/
+ 
+-nostackp := $(call cc-option, -fno-stack-protector)
+-CFLAGS_features.o			:= $(nostackp)
+-
+-obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
+-obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
+-obj-$(CONFIG_XEN_BALLOON)	+= balloon.o
+-obj-$(CONFIG_XEN_DEV_EVTCHN)	+= evtchn.o
+-obj-$(CONFIG_XENFS)		+= xenfs/
+-obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
+\ No newline at end of file
++obj-y	+= util.o
++obj-$(CONFIG_XEN_BALLOON)		+= balloon/
++obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
++obj-$(CONFIG_XEN_BLKDEV_TAP)		+= blktap/
++obj-$(CONFIG_XEN_BLKDEV_TAP2)           += blktap2/
++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_USB_BACKEND)		+= usbback/
++obj-$(CONFIG_XEN_USB_FRONTEND)		+= usbfront/
++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/
+--- head-2010-01-07.orig/drivers/xen/xenbus/Makefile	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/Makefile	2009-12-04 10:44:50.000000000 +0100
+@@ -1,7 +1,9 @@
+-obj-y	+= xenbus.o
++obj-y += xenbus_client.o xenbus_comms.o xenbus_xs.o xenbus_probe.o
++obj-$(CONFIG_XEN_BACKEND) += xenbus_be.o
+ 
+-xenbus-objs =
+-xenbus-objs += xenbus_client.o
+-xenbus-objs += xenbus_comms.o
+-xenbus-objs += xenbus_xs.o
+-xenbus-objs += xenbus_probe.o
++xenbus_be-objs =
++xenbus_be-objs += xenbus_backend_client.o
++
++xenbus-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o
++obj-y += $(xenbus-y) $(xenbus-m)
++obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_client.c	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_client.c	2009-12-04 10:44:50.000000000 +0100
+@@ -30,14 +30,18 @@
+  * IN THE SOFTWARE.
+  */
+ 
+-#include <linux/types.h>
+-#include <linux/vmalloc.h>
+-#include <asm/xen/hypervisor.h>
+-#include <xen/interface/xen.h>
+-#include <xen/interface/event_channel.h>
+-#include <xen/events.h>
+-#include <xen/grant_table.h>
++#include <linux/slab.h>
++#include <xen/evtchn.h>
++#include <xen/gnttab.h>
+ #include <xen/xenbus.h>
++#include <xen/driver_util.h>
++
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#define DPRINTK(fmt, args...) \
++    pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
+ 
+ const char *xenbus_strstate(enum xenbus_state state)
+ {
+@@ -49,25 +53,13 @@ const char *xenbus_strstate(enum xenbus_
+ 		[ XenbusStateConnected    ] = "Connected",
+ 		[ XenbusStateClosing      ] = "Closing",
+ 		[ XenbusStateClosed	  ] = "Closed",
++		[ XenbusStateReconfiguring ] = "Reconfiguring",
++		[ XenbusStateReconfigured ] = "Reconfigured",
+ 	};
+ 	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
+ }
+ EXPORT_SYMBOL_GPL(xenbus_strstate);
+ 
+-/**
+- * xenbus_watch_path - register a watch
+- * @dev: xenbus device
+- * @path: path to watch
+- * @watch: watch to register
+- * @callback: callback to register
+- *
+- * Register a @watch on the given path, using the given xenbus_watch structure
+- * for storage, and the given @callback function as the callback.  Return 0 on
+- * success, or -errno on error.  On success, the given @path will be saved as
+- * @watch->node, and remains the caller's to free.  On error, @watch->node will
+- * be NULL, the device will switch to %XenbusStateClosing, and the error will
+- * be saved in the store.
+- */
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+ 		      struct xenbus_watch *watch,
+ 		      void (*callback)(struct xenbus_watch *,
+@@ -91,57 +83,26 @@ int xenbus_watch_path(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_watch_path);
+ 
+ 
+-/**
+- * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path
+- * @dev: xenbus device
+- * @watch: watch to register
+- * @callback: callback to register
+- * @pathfmt: format of path to watch
+- *
+- * Register a watch on the given @path, using the given xenbus_watch
+- * structure for storage, and the given @callback function as the callback.
+- * Return 0 on success, or -errno on error.  On success, the watched path
+- * (@path/@path2) will be saved as @watch->node, and becomes the caller's to
+- * kfree().  On error, watch->node will be NULL, so the caller has nothing to
+- * free, the device will switch to %XenbusStateClosing, and the error will be
+- * saved in the store.
+- */
+-int xenbus_watch_pathfmt(struct xenbus_device *dev,
+-			 struct xenbus_watch *watch,
+-			 void (*callback)(struct xenbus_watch *,
+-					const char **, unsigned int),
+-			 const char *pathfmt, ...)
++int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
++		       const char *path2, struct xenbus_watch *watch,
++		       void (*callback)(struct xenbus_watch *,
++					const char **, unsigned int))
+ {
+ 	int err;
+-	va_list ap;
+-	char *path;
+-
+-	va_start(ap, pathfmt);
+-	path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap);
+-	va_end(ap);
+-
+-	if (!path) {
++	char *state = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/%s", path, path2);
++	if (!state) {
+ 		xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
+ 		return -ENOMEM;
+ 	}
+-	err = xenbus_watch_path(dev, path, watch, callback);
++	err = xenbus_watch_path(dev, state, watch, callback);
+ 
+ 	if (err)
+-		kfree(path);
++		kfree(state);
+ 	return err;
+ }
+-EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
++EXPORT_SYMBOL_GPL(xenbus_watch_path2);
+ 
+ 
+-/**
+- * xenbus_switch_state
+- * @dev: xenbus device
+- * @state: new state
+- *
+- * Advertise in the store a change of the given driver to the given new_state.
+- * Return 0 on success, or -errno on error.  On error, the device will switch
+- * to XenbusStateClosing, and the error will be saved in the store.
+- */
+ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
+ {
+ 	/* We check whether the state is currently set to the given value, and
+@@ -200,13 +161,12 @@ static char *error_path(struct xenbus_de
+ }
+ 
+ 
+-static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
+-				const char *fmt, va_list ap)
++void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
++		va_list ap)
+ {
+ 	int ret;
+ 	unsigned int len;
+-	char *printf_buffer = NULL;
+-	char *path_buffer = NULL;
++	char *printf_buffer = NULL, *path_buffer = NULL;
+ 
+ #define PRINTF_BUFFER_SIZE 4096
+ 	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+@@ -223,13 +183,13 @@ static void xenbus_va_dev_error(struct x
+ 	path_buffer = error_path(dev);
+ 
+ 	if (path_buffer == NULL) {
+-		dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
++		printk("xenbus: failed to write error node for %s (%s)\n",
+ 		       dev->nodename, printf_buffer);
+ 		goto fail;
+ 	}
+ 
+ 	if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
+-		dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
++		printk("xenbus: failed to write error node for %s (%s)\n",
+ 		       dev->nodename, printf_buffer);
+ 		goto fail;
+ 	}
+@@ -240,57 +200,32 @@ fail:
+ }
+ 
+ 
+-/**
+- * xenbus_dev_error
+- * @dev: xenbus device
+- * @err: error to report
+- * @fmt: error message format
+- *
+- * Report the given negative errno into the store, along with the given
+- * formatted message.
+- */
+-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
++void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
++		      ...)
+ {
+ 	va_list ap;
+ 
+ 	va_start(ap, fmt);
+-	xenbus_va_dev_error(dev, err, fmt, ap);
++	_dev_error(dev, err, fmt, ap);
+ 	va_end(ap);
+ }
+ EXPORT_SYMBOL_GPL(xenbus_dev_error);
+ 
+-/**
+- * xenbus_dev_fatal
+- * @dev: xenbus device
+- * @err: error to report
+- * @fmt: error message format
+- *
+- * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
+- * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly
+- * closedown of this driver and its peer.
+- */
+ 
+-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
++void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
++		      ...)
+ {
+ 	va_list ap;
+ 
+ 	va_start(ap, fmt);
+-	xenbus_va_dev_error(dev, err, fmt, ap);
++	_dev_error(dev, err, fmt, ap);
+ 	va_end(ap);
+ 
+ 	xenbus_switch_state(dev, XenbusStateClosing);
+ }
+ EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
+ 
+-/**
+- * xenbus_grant_ring
+- * @dev: xenbus device
+- * @ring_mfn: mfn of ring to grant
+-
+- * Grant access to the given @ring_mfn to the peer of the given device.  Return
+- * 0 on success, or -errno on error.  On error, the device will switch to
+- * XenbusStateClosing, and the error will be saved in the store.
+- */
++
+ int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
+ {
+ 	int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
+@@ -301,18 +236,12 @@ int xenbus_grant_ring(struct xenbus_devi
+ EXPORT_SYMBOL_GPL(xenbus_grant_ring);
+ 
+ 
+-/**
+- * Allocate an event channel for the given xenbus_device, assigning the newly
+- * created local port to *port.  Return 0 on success, or -errno on error.  On
+- * error, the device will switch to XenbusStateClosing, and the error will be
+- * saved in the store.
+- */
+ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
+ {
+ 	struct evtchn_alloc_unbound alloc_unbound;
+ 	int err;
+ 
+-	alloc_unbound.dom = DOMID_SELF;
++	alloc_unbound.dom        = DOMID_SELF;
+ 	alloc_unbound.remote_dom = dev->otherend_id;
+ 
+ 	err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+@@ -327,36 +256,6 @@ int xenbus_alloc_evtchn(struct xenbus_de
+ EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
+ 
+ 
+-/**
+- * Bind to an existing interdomain event channel in another domain. Returns 0
+- * on success and stores the local port in *port. On error, returns -errno,
+- * switches the device to XenbusStateClosing, and saves the error in XenStore.
+- */
+-int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
+-{
+-	struct evtchn_bind_interdomain bind_interdomain;
+-	int err;
+-
+-	bind_interdomain.remote_dom = dev->otherend_id;
+-	bind_interdomain.remote_port = remote_port;
+-
+-	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+-					  &bind_interdomain);
+-	if (err)
+-		xenbus_dev_fatal(dev, err,
+-				 "binding to event channel %d from domain %d",
+-				 remote_port, dev->otherend_id);
+-	else
+-		*port = bind_interdomain.local_port;
+-
+-	return err;
+-}
+-EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
+-
+-
+-/**
+- * Free an existing event channel. Returns 0 on success or -errno on error.
+- */
+ int xenbus_free_evtchn(struct xenbus_device *dev, int port)
+ {
+ 	struct evtchn_close close;
+@@ -373,189 +272,6 @@ int xenbus_free_evtchn(struct xenbus_dev
+ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
+ 
+ 
+-/**
+- * xenbus_map_ring_valloc
+- * @dev: xenbus device
+- * @gnt_ref: grant reference
+- * @vaddr: pointer to address to be filled out by mapping
+- *
+- * Based on Rusty Russell's skeleton driver's map_page.
+- * Map a page of memory into this domain from another domain's grant table.
+- * xenbus_map_ring_valloc allocates a page of virtual address space, maps the
+- * page to that address, and sets *vaddr to that address.
+- * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
+- * or -ENOMEM on error. If an error is returned, device will switch to
+- * XenbusStateClosing and the error message will be saved in XenStore.
+- */
+-int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
+-{
+-	struct gnttab_map_grant_ref op = {
+-		.flags = GNTMAP_host_map,
+-		.ref   = gnt_ref,
+-		.dom   = dev->otherend_id,
+-	};
+-	struct vm_struct *area;
+-
+-	*vaddr = NULL;
+-
+-	area = xen_alloc_vm_area(PAGE_SIZE);
+-	if (!area)
+-		return -ENOMEM;
+-
+-	op.host_addr = (unsigned long)area->addr;
+-
+-	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+-		BUG();
+-
+-	if (op.status != GNTST_okay) {
+-		xen_free_vm_area(area);
+-		xenbus_dev_fatal(dev, op.status,
+-				 "mapping in shared page %d from domain %d",
+-				 gnt_ref, dev->otherend_id);
+-		return op.status;
+-	}
+-
+-	/* Stuff the handle in an unused field */
+-	area->phys_addr = (unsigned long)op.handle;
+-
+-	*vaddr = area->addr;
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
+-
+-
+-/**
+- * xenbus_map_ring
+- * @dev: xenbus device
+- * @gnt_ref: grant reference
+- * @handle: pointer to grant handle to be filled
+- * @vaddr: address to be mapped to
+- *
+- * Map a page of memory into this domain from another domain's grant table.
+- * xenbus_map_ring does not allocate the virtual address space (you must do
+- * this yourself!). It only maps in the page to the specified address.
+- * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
+- * or -ENOMEM on error. If an error is returned, device will switch to
+- * XenbusStateClosing and the error message will be saved in XenStore.
+- */
+-int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
+-		    grant_handle_t *handle, void *vaddr)
+-{
+-	struct gnttab_map_grant_ref op = {
+-		.host_addr = (unsigned long)vaddr,
+-		.flags     = GNTMAP_host_map,
+-		.ref       = gnt_ref,
+-		.dom       = dev->otherend_id,
+-	};
+-
+-	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+-		BUG();
+-
+-	if (op.status != GNTST_okay) {
+-		xenbus_dev_fatal(dev, op.status,
+-				 "mapping in shared page %d from domain %d",
+-				 gnt_ref, dev->otherend_id);
+-	} else
+-		*handle = op.handle;
+-
+-	return op.status;
+-}
+-EXPORT_SYMBOL_GPL(xenbus_map_ring);
+-
+-
+-/**
+- * xenbus_unmap_ring_vfree
+- * @dev: xenbus device
+- * @vaddr: addr to unmap
+- *
+- * Based on Rusty Russell's skeleton driver's unmap_page.
+- * Unmap a page of memory in this domain that was imported from another domain.
+- * Use xenbus_unmap_ring_vfree if you mapped in your memory with
+- * xenbus_map_ring_valloc (it will free the virtual address space).
+- * Returns 0 on success and returns GNTST_* on error
+- * (see xen/include/interface/grant_table.h).
+- */
+-int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
+-{
+-	struct vm_struct *area;
+-	struct gnttab_unmap_grant_ref op = {
+-		.host_addr = (unsigned long)vaddr,
+-	};
+-
+-	/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
+-	 * method so that we don't have to muck with vmalloc internals here.
+-	 * We could force the user to hang on to their struct vm_struct from
+-	 * xenbus_map_ring_valloc, but these 6 lines considerably simplify
+-	 * this API.
+-	 */
+-	read_lock(&vmlist_lock);
+-	for (area = vmlist; area != NULL; area = area->next) {
+-		if (area->addr == vaddr)
+-			break;
+-	}
+-	read_unlock(&vmlist_lock);
+-
+-	if (!area) {
+-		xenbus_dev_error(dev, -ENOENT,
+-				 "can't find mapped virtual address %p", vaddr);
+-		return GNTST_bad_virt_addr;
+-	}
+-
+-	op.handle = (grant_handle_t)area->phys_addr;
+-
+-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+-		BUG();
+-
+-	if (op.status == GNTST_okay)
+-		xen_free_vm_area(area);
+-	else
+-		xenbus_dev_error(dev, op.status,
+-				 "unmapping page at handle %d error %d",
+-				 (int16_t)area->phys_addr, op.status);
+-
+-	return op.status;
+-}
+-EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
+-
+-
+-/**
+- * xenbus_unmap_ring
+- * @dev: xenbus device
+- * @handle: grant handle
+- * @vaddr: addr to unmap
+- *
+- * Unmap a page of memory in this domain that was imported from another domain.
+- * Returns 0 on success and returns GNTST_* on error
+- * (see xen/include/interface/grant_table.h).
+- */
+-int xenbus_unmap_ring(struct xenbus_device *dev,
+-		      grant_handle_t handle, void *vaddr)
+-{
+-	struct gnttab_unmap_grant_ref op = {
+-		.host_addr = (unsigned long)vaddr,
+-		.handle    = handle,
+-	};
+-
+-	if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+-		BUG();
+-
+-	if (op.status != GNTST_okay)
+-		xenbus_dev_error(dev, op.status,
+-				 "unmapping page at handle %d error %d",
+-				 handle, op.status);
+-
+-	return op.status;
+-}
+-EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
+-
+-
+-/**
+- * xenbus_read_driver_state
+- * @path: path for driver
+- *
+- * Return the state of the driver rooted at the given store path, or
+- * XenbusStateUnknown if no state can be read.
+- */
+ enum xenbus_state xenbus_read_driver_state(const char *path)
+ {
+ 	enum xenbus_state result;
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_comms.c	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_comms.c	2009-12-04 10:44:50.000000000 +0100
+@@ -34,25 +34,55 @@
+ #include <linux/interrupt.h>
+ #include <linux/sched.h>
+ #include <linux/err.h>
++#include <linux/ptrace.h>
++#include <linux/workqueue.h>
++#include <xen/evtchn.h>
+ #include <xen/xenbus.h>
+-#include <asm/xen/hypervisor.h>
+-#include <xen/events.h>
+-#include <xen/page.h>
++
++#include <asm/hypervisor.h>
++
+ #include "xenbus_comms.h"
+ 
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
+ static int xenbus_irq;
+ 
+-static DECLARE_WORK(probe_work, xenbus_probe);
++extern void xenbus_probe(void *);
++static DECLARE_WORK(probe_work, xenbus_probe, NULL);
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+ 
+-static irqreturn_t wake_waiting(int irq, void *unused)
++static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
+ {
+-	if (unlikely(xenstored_ready == 0)) {
+-		xenstored_ready = 1;
+-		schedule_work(&probe_work);
++	int old, new;
++
++	old = atomic_read(&xenbus_xsd_state);
++	switch (old) {
++		case XENBUS_XSD_UNCOMMITTED:
++			BUG();
++			return IRQ_HANDLED;
++
++		case XENBUS_XSD_FOREIGN_INIT:
++			new = XENBUS_XSD_FOREIGN_READY;
++			break;
++
++		case XENBUS_XSD_LOCAL_INIT:
++			new = XENBUS_XSD_LOCAL_READY;
++			break;
++
++		case XENBUS_XSD_FOREIGN_READY:
++		case XENBUS_XSD_LOCAL_READY:
++		default:
++			goto wake;
+ 	}
+ 
++	old = atomic_cmpxchg(&xenbus_xsd_state, old, new);
++	if (old != new)
++		schedule_work(&probe_work);
++
++wake:
+ 	wake_up(&xb_waitq);
+ 	return IRQ_HANDLED;
+ }
+@@ -82,13 +112,6 @@ static const void *get_input_chunk(XENST
+ 	return buf + MASK_XENSTORE_IDX(cons);
+ }
+ 
+-/**
+- * xb_write - low level write
+- * @data: buffer to send
+- * @len: length of buffer
+- *
+- * Returns 0 on success, error otherwise.
+- */
+ int xb_write(const void *data, unsigned len)
+ {
+ 	struct xenstore_domain_interface *intf = xen_store_interface;
+@@ -197,12 +220,11 @@ int xb_read(void *data, unsigned len)
+ 	return 0;
+ }
+ 
+-/**
+- * xb_init_comms - Set up interrupt handler off store event channel.
+- */
++/* Set up interrupt handler off store event channel. */
+ int xb_init_comms(void)
+ {
+ 	struct xenstore_domain_interface *intf = xen_store_interface;
++	int err;
+ 
+ 	if (intf->req_prod != intf->req_cons)
+ 		printk(KERN_ERR "XENBUS request ring is not quiescent "
+@@ -215,20 +237,18 @@ int xb_init_comms(void)
+ 		intf->rsp_cons = intf->rsp_prod;
+ 	}
+ 
+-	if (xenbus_irq) {
+-		/* Already have an irq; assume we're resuming */
+-		rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
+-	} else {
+-		int err;
+-		err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
+-						0, "xenbus", &xb_waitq);
+-		if (err <= 0) {
+-			printk(KERN_ERR "XENBUS request irq failed %i\n", err);
+-			return err;
+-		}
++	if (xenbus_irq)
++		unbind_from_irqhandler(xenbus_irq, &xb_waitq);
+ 
+-		xenbus_irq = err;
++	err = bind_caller_port_to_irqhandler(
++		xen_store_evtchn, wake_waiting,
++		0, "xenbus", &xb_waitq);
++	if (err <= 0) {
++		printk(KERN_ERR "XENBUS request irq failed %i\n", err);
++		return err;
+ 	}
+ 
++	xenbus_irq = err;
++
+ 	return 0;
+ }
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_comms.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_comms.h	2009-12-04 10:44:50.000000000 +0100
+@@ -43,4 +43,20 @@ int xs_input_avail(void);
+ extern struct xenstore_domain_interface *xen_store_interface;
+ extern int xen_store_evtchn;
+ 
++/* For xenbus internal use. */
++enum {
++	XENBUS_XSD_UNCOMMITTED = 0,
++	XENBUS_XSD_FOREIGN_INIT,
++	XENBUS_XSD_FOREIGN_READY,
++	XENBUS_XSD_LOCAL_INIT,
++	XENBUS_XSD_LOCAL_READY,
++};
++extern atomic_t xenbus_xsd_state;
++
++static inline int is_xenstored_ready(void)
++{
++	int s = atomic_read(&xenbus_xsd_state);
++	return s == XENBUS_XSD_FOREIGN_READY || s == XENBUS_XSD_LOCAL_READY;
++}
++
+ #endif /* _XENBUS_COMMS_H */
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_probe.c	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_probe.c	2010-01-07 09:53:42.000000000 +0100
+@@ -4,6 +4,7 @@
+  * 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
+@@ -32,7 +33,7 @@
+ 
+ #define DPRINTK(fmt, args...)				\
+ 	pr_debug("xenbus_probe (%s:%d) " fmt ".\n",	\
+-		 __func__, __LINE__, ##args)
++		 __FUNCTION__, __LINE__, ##args)
+ 
+ #include <linux/kernel.h>
+ #include <linux/err.h>
+@@ -40,29 +41,37 @@
+ #include <linux/ctype.h>
+ #include <linux/fcntl.h>
+ #include <linux/mm.h>
+-#include <linux/proc_fs.h>
+ #include <linux/notifier.h>
+-#include <linux/kthread.h>
+ #include <linux/mutex.h>
+-#include <linux/io.h>
++#include <linux/module.h>
++#include <xen/gnttab.h>
+ 
++#include <asm/io.h>
+ #include <asm/page.h>
++#include <asm/maddr.h>
+ #include <asm/pgtable.h>
+-#include <asm/xen/hypervisor.h>
++#include <asm/hypervisor.h>
+ #include <xen/xenbus.h>
+-#include <xen/events.h>
+-#include <xen/page.h>
++#include <xen/xen_proc.h>
++#include <xen/evtchn.h>
++#include <xen/features.h>
++#ifdef MODULE
++#include <xen/hvm.h>
++#endif
+ 
+ #include "xenbus_comms.h"
+ #include "xenbus_probe.h"
+ 
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
+ 
+ int xen_store_evtchn;
+-EXPORT_SYMBOL(xen_store_evtchn);
+-
+ struct xenstore_domain_interface *xen_store_interface;
+ static unsigned long xen_store_mfn;
+ 
++extern struct mutex xenwatch_mutex;
++
+ static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
+ 
+ static void wait_for_devices(struct xenbus_driver *xendrv);
+@@ -71,9 +80,6 @@ static int xenbus_probe_frontend(const c
+ 
+ static void xenbus_dev_shutdown(struct device *_dev);
+ 
+-static int xenbus_dev_suspend(struct device *dev, pm_message_t state);
+-static int xenbus_dev_resume(struct device *dev);
+-
+ /* If something in array of ids matches this device, return it. */
+ static const struct xenbus_device_id *
+ match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
+@@ -95,16 +101,6 @@ int xenbus_match(struct device *_dev, st
+ 	return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
+ }
+ 
+-static int xenbus_uevent(struct device *_dev, struct kobj_uevent_env *env)
+-{
+-	struct xenbus_device *dev = to_xenbus_device(_dev);
+-
+-	if (add_uevent_var(env, "MODALIAS=xen:%s", dev->devicetype))
+-		return -ENOMEM;
+-
+-	return 0;
+-}
+-
+ /* device/<type>/<id> => <type>-<id> */
+ static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
+ {
+@@ -173,9 +169,30 @@ static int read_backend_details(struct x
+ 	return read_otherend_details(xendev, "backend-id", "backend");
+ }
+ 
+-static struct device_attribute xenbus_dev_attrs[] = {
+-	__ATTR_NULL
+-};
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++static int xenbus_uevent_frontend(struct device *dev, char **envp,
++				  int num_envp, char *buffer, int buffer_size)
++{
++	struct xenbus_device *xdev;
++	int length = 0, i = 0;
++
++	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,
++		       "MODALIAS=xen:%s", xdev->devicetype);
++
++	return 0;
++}
++#endif
+ 
+ /* Bus type for frontend drivers. */
+ static struct xen_bus_type xenbus_frontend = {
+@@ -183,17 +200,19 @@ static struct xen_bus_type xenbus_fronte
+ 	.levels = 2, 		/* device/type/<id> */
+ 	.get_bus_id = frontend_bus_id,
+ 	.probe = xenbus_probe_frontend,
++	.error = -ENODEV,
+ 	.bus = {
+-		.name      = "xen",
+-		.match     = xenbus_match,
+-		.uevent    = xenbus_uevent,
+-		.probe     = xenbus_dev_probe,
+-		.remove    = xenbus_dev_remove,
+-		.shutdown  = xenbus_dev_shutdown,
+-		.dev_attrs = xenbus_dev_attrs,
+-
+-		.suspend   = xenbus_dev_suspend,
+-		.resume    = xenbus_dev_resume,
++		.name     = "xen",
++		.match    = xenbus_match,
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
++		.probe    = xenbus_dev_probe,
++		.remove   = xenbus_dev_remove,
++		.shutdown = xenbus_dev_shutdown,
++		.uevent   = xenbus_uevent_frontend,
++#endif
++	},
++	.dev = {
++		.bus_id = "xen",
+ 	},
+ };
+ 
+@@ -210,17 +229,16 @@ static void otherend_changed(struct xenb
+ 	if (!dev->otherend ||
+ 	    strncmp(dev->otherend, vec[XS_WATCH_PATH],
+ 		    strlen(dev->otherend))) {
+-		dev_dbg(&dev->dev, "Ignoring watch at %s\n",
+-			vec[XS_WATCH_PATH]);
++		DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
+ 		return;
+ 	}
+ 
+ 	state = xenbus_read_driver_state(dev->otherend);
+ 
+-	dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
+-		state, xenbus_strstate(state), dev->otherend_watch.node,
+-		vec[XS_WATCH_PATH]);
++	DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state),
++		dev->otherend_watch.node, vec[XS_WATCH_PATH]);
+ 
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ 	/*
+ 	 * Ignore xenbus transitions during shutdown. This prevents us doing
+ 	 * work that can fail e.g., when the rootfs is gone.
+@@ -234,6 +252,7 @@ static void otherend_changed(struct xenb
+ 			xenbus_frontend_closed(dev);
+ 		return;
+ 	}
++#endif
+ 
+ 	if (drv->otherend_changed)
+ 		drv->otherend_changed(dev, state);
+@@ -253,8 +272,8 @@ static int talk_to_otherend(struct xenbu
+ 
+ static int watch_otherend(struct xenbus_device *dev)
+ {
+-	return xenbus_watch_pathfmt(dev, &dev->otherend_watch, otherend_changed,
+-				    "%s/%s", dev->otherend, "state");
++	return xenbus_watch_path2(dev, dev->otherend, "state",
++				  &dev->otherend_watch, otherend_changed);
+ }
+ 
+ 
+@@ -280,8 +299,9 @@ int xenbus_dev_probe(struct device *_dev
+ 
+ 	err = talk_to_otherend(dev);
+ 	if (err) {
+-		dev_warn(&dev->dev, "talk_to_otherend on %s failed.\n",
+-			 dev->nodename);
++		printk(KERN_WARNING
++		       "xenbus_probe: talk_to_otherend on %s failed.\n",
++		       dev->nodename);
+ 		return err;
+ 	}
+ 
+@@ -291,7 +311,8 @@ int xenbus_dev_probe(struct device *_dev
+ 
+ 	err = watch_otherend(dev);
+ 	if (err) {
+-		dev_warn(&dev->dev, "watch_otherend on %s failed.\n",
++		printk(KERN_WARNING
++		       "xenbus_probe: watch_otherend on %s failed.\n",
+ 		       dev->nodename);
+ 		return err;
+ 	}
+@@ -327,43 +348,64 @@ static void xenbus_dev_shutdown(struct d
+ 
+ 	DPRINTK("%s", dev->nodename);
+ 
++/* Commented out since xenstored stubdom is now minios based not linux based
++#define XENSTORE_DOMAIN_SHARES_THIS_KERNEL
++*/
++#ifndef XENSTORE_DOMAIN_SHARES_THIS_KERNEL
++	if (is_initial_xendomain())
++#endif
++		return;
++
+ 	get_device(&dev->dev);
+ 	if (dev->state != XenbusStateConnected) {
+-		printk(KERN_INFO "%s: %s: %s != Connected, skipping\n", __func__,
++		printk("%s: %s: %s != Connected, skipping\n", __FUNCTION__,
+ 		       dev->nodename, xenbus_strstate(dev->state));
+ 		goto out;
+ 	}
+ 	xenbus_switch_state(dev, XenbusStateClosing);
++
++	if (!strcmp(dev->devicetype, "vfb"))
++		goto out;
++
+ 	timeout = wait_for_completion_timeout(&dev->down, timeout);
+ 	if (!timeout)
+-		printk(KERN_INFO "%s: %s timeout closing device\n",
+-		       __func__, dev->nodename);
++		printk("%s: %s timeout closing device\n", __FUNCTION__, dev->nodename);
+  out:
+ 	put_device(&dev->dev);
+ }
+ 
+ int xenbus_register_driver_common(struct xenbus_driver *drv,
+-				  struct xen_bus_type *bus,
+-				  struct module *owner,
+-				  const char *mod_name)
++				  struct xen_bus_type *bus)
+ {
++	int ret;
++
++	if (bus->error)
++		return bus->error;
++
+ 	drv->driver.name = drv->name;
+ 	drv->driver.bus = &bus->bus;
+-	drv->driver.owner = owner;
+-	drv->driver.mod_name = mod_name;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
++	drv->driver.owner = drv->owner;
++#endif
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
++	drv->driver.probe = xenbus_dev_probe;
++	drv->driver.remove = xenbus_dev_remove;
++	drv->driver.shutdown = xenbus_dev_shutdown;
++#endif
+ 
+-	return driver_register(&drv->driver);
++	mutex_lock(&xenwatch_mutex);
++	ret = driver_register(&drv->driver);
++	mutex_unlock(&xenwatch_mutex);
++	return ret;
+ }
+ 
+-int __xenbus_register_frontend(struct xenbus_driver *drv,
+-			       struct module *owner, const char *mod_name)
++int xenbus_register_frontend(struct xenbus_driver *drv)
+ {
+ 	int ret;
+ 
+ 	drv->read_otherend_details = read_backend_details;
+ 
+-	ret = xenbus_register_driver_common(drv, &xenbus_frontend,
+-					    owner, mod_name);
++	ret = xenbus_register_driver_common(drv, &xenbus_frontend);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -372,7 +414,7 @@ int __xenbus_register_frontend(struct xe
+ 
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
++EXPORT_SYMBOL_GPL(xenbus_register_frontend);
+ 
+ void xenbus_unregister_driver(struct xenbus_driver *drv)
+ {
+@@ -450,31 +492,30 @@ static void xenbus_dev_release(struct de
+ }
+ 
+ static ssize_t xendev_show_nodename(struct device *dev,
+-				    struct device_attribute *attr, char *buf)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
++				    struct device_attribute *attr,
++#endif
++				    char *buf)
+ {
+ 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
+ }
+ static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
+ 
+ static ssize_t xendev_show_devtype(struct device *dev,
+-				   struct device_attribute *attr, char *buf)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
++				   struct device_attribute *attr,
++#endif
++				   char *buf)
+ {
+ 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
+ }
+ static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
+ 
+-static ssize_t xendev_show_modalias(struct device *dev,
+-				    struct device_attribute *attr, char *buf)
+-{
+-	return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
+-}
+-static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
+ 
+ int xenbus_probe_node(struct xen_bus_type *bus,
+ 		      const char *type,
+ 		      const char *nodename)
+ {
+-	char devname[XEN_BUS_ID_SIZE];
+ 	int err;
+ 	struct xenbus_device *xendev;
+ 	size_t stringlen;
+@@ -482,6 +523,9 @@ int xenbus_probe_node(struct xen_bus_typ
+ 
+ 	enum xenbus_state state = xenbus_read_driver_state(nodename);
+ 
++	if (bus->error)
++		return bus->error;
++
+ 	if (state != XenbusStateInitialising) {
+ 		/* Device is not new, so ignore it.  This can happen if a
+ 		   device is going away after switching to Closed.  */
+@@ -506,15 +550,14 @@ int xenbus_probe_node(struct xen_bus_typ
+ 	xendev->devicetype = tmpstring;
+ 	init_completion(&xendev->down);
+ 
++	xendev->dev.parent = &bus->dev;
+ 	xendev->dev.bus = &bus->bus;
+ 	xendev->dev.release = xenbus_dev_release;
+ 
+-	err = bus->get_bus_id(devname, xendev->nodename);
++	err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
+ 	if (err)
+ 		goto fail;
+ 
+-	dev_set_name(&xendev->dev, devname);
+-
+ 	/* Register with generic device framework. */
+ 	err = device_register(&xendev->dev);
+ 	if (err)
+@@ -522,22 +565,15 @@ int xenbus_probe_node(struct xen_bus_typ
+ 
+ 	err = device_create_file(&xendev->dev, &dev_attr_nodename);
+ 	if (err)
+-		goto fail_unregister;
+-
++		goto unregister;
+ 	err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ 	if (err)
+-		goto fail_remove_nodename;
+-
+-	err = device_create_file(&xendev->dev, &dev_attr_modalias);
+-	if (err)
+-		goto fail_remove_devtype;
++		goto unregister;
+ 
+ 	return 0;
+-fail_remove_devtype:
+-	device_remove_file(&xendev->dev, &dev_attr_devtype);
+-fail_remove_nodename:
++unregister:
+ 	device_remove_file(&xendev->dev, &dev_attr_nodename);
+-fail_unregister:
++	device_remove_file(&xendev->dev, &dev_attr_devtype);
+ 	device_unregister(&xendev->dev);
+ fail:
+ 	kfree(xendev);
+@@ -550,8 +586,10 @@ static int xenbus_probe_frontend(const c
+ 	char *nodename;
+ 	int err;
+ 
+-	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s",
+-			     xenbus_frontend.root, type, name);
++	if (!strcmp(type, "console"))
++		return 0;
++
++	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_frontend.root, type, name);
+ 	if (!nodename)
+ 		return -ENOMEM;
+ 
+@@ -588,6 +626,9 @@ int xenbus_probe_devices(struct xen_bus_
+ 	char **dir;
+ 	unsigned int i, dir_n;
+ 
++	if (bus->error)
++		return bus->error;
++
+ 	dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n);
+ 	if (IS_ERR(dir))
+ 		return PTR_ERR(dir);
+@@ -624,15 +665,15 @@ static int strsep_len(const char *str, c
+ 	return (len == 0) ? i : -ERANGE;
+ }
+ 
+-void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
++void dev_changed(const char *node, struct xen_bus_type *bus)
+ {
+ 	int exists, rootlen;
+ 	struct xenbus_device *dev;
+ 	char type[XEN_BUS_ID_SIZE];
+ 	const char *p, *root;
+ 
+-	if (char_count(node, '/') < 2)
+-		return;
++	if (bus->error || char_count(node, '/') < 2)
++ 		return;
+ 
+ 	exists = xenbus_exists(XBT_NIL, node, "");
+ 	if (!exists) {
+@@ -660,14 +701,13 @@ void xenbus_dev_changed(const char *node
+ 
+ 	kfree(root);
+ }
+-EXPORT_SYMBOL_GPL(xenbus_dev_changed);
+ 
+ static void frontend_changed(struct xenbus_watch *watch,
+ 			     const char **vec, unsigned int len)
+ {
+ 	DPRINTK("");
+ 
+-	xenbus_dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
++	dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
+ }
+ 
+ /* We watch for devices appearing and vanishing. */
+@@ -676,7 +716,7 @@ static struct xenbus_watch fe_watch = {
+ 	.callback = frontend_changed,
+ };
+ 
+-static int xenbus_dev_suspend(struct device *dev, pm_message_t state)
++static int suspend_dev(struct device *dev, void *data)
+ {
+ 	int err = 0;
+ 	struct xenbus_driver *drv;
+@@ -689,14 +729,35 @@ static int xenbus_dev_suspend(struct dev
+ 	drv = to_xenbus_driver(dev->driver);
+ 	xdev = container_of(dev, struct xenbus_device, dev);
+ 	if (drv->suspend)
+-		err = drv->suspend(xdev, state);
++		err = drv->suspend(xdev);
++	if (err)
++		printk(KERN_WARNING
++		       "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
++	return 0;
++}
++
++static int suspend_cancel_dev(struct device *dev, void *data)
++{
++	int err = 0;
++	struct xenbus_driver *drv;
++	struct xenbus_device *xdev;
++
++	DPRINTK("");
++
++	if (dev->driver == NULL)
++		return 0;
++	drv = to_xenbus_driver(dev->driver);
++	xdev = container_of(dev, struct xenbus_device, dev);
++	if (drv->suspend_cancel)
++		err = drv->suspend_cancel(xdev);
+ 	if (err)
+ 		printk(KERN_WARNING
+-		       "xenbus: suspend %s failed: %i\n", dev_name(dev), err);
++		       "xenbus: suspend_cancel %s failed: %i\n",
++		       dev->bus_id, err);
+ 	return 0;
+ }
+ 
+-static int xenbus_dev_resume(struct device *dev)
++static int resume_dev(struct device *dev, void *data)
+ {
+ 	int err;
+ 	struct xenbus_driver *drv;
+@@ -714,7 +775,7 @@ static int xenbus_dev_resume(struct devi
+ 	if (err) {
+ 		printk(KERN_WARNING
+ 		       "xenbus: resume (talk_to_otherend) %s failed: %i\n",
+-		       dev_name(dev), err);
++		       dev->bus_id, err);
+ 		return err;
+ 	}
+ 
+@@ -725,7 +786,7 @@ static int xenbus_dev_resume(struct devi
+ 		if (err) {
+ 			printk(KERN_WARNING
+ 			       "xenbus: resume %s failed: %i\n",
+-			       dev_name(dev), err);
++			       dev->bus_id, err);
+ 			return err;
+ 		}
+ 	}
+@@ -734,22 +795,52 @@ static int xenbus_dev_resume(struct devi
+ 	if (err) {
+ 		printk(KERN_WARNING
+ 		       "xenbus_probe: resume (watch_otherend) %s failed: "
+-		       "%d.\n", dev_name(dev), err);
++		       "%d.\n", dev->bus_id, err);
+ 		return err;
+ 	}
+ 
+ 	return 0;
+ }
+ 
++void xenbus_suspend(void)
++{
++	DPRINTK("");
++
++	if (!xenbus_frontend.error)
++		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
++	xenbus_backend_suspend(suspend_dev);
++	xs_suspend();
++}
++EXPORT_SYMBOL_GPL(xenbus_suspend);
++
++void xenbus_resume(void)
++{
++	xb_init_comms();
++	xs_resume();
++	if (!xenbus_frontend.error)
++		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
++	xenbus_backend_resume(resume_dev);
++}
++EXPORT_SYMBOL_GPL(xenbus_resume);
++
++void xenbus_suspend_cancel(void)
++{
++	xs_suspend_cancel();
++	if (!xenbus_frontend.error)
++		bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev);
++	xenbus_backend_resume(suspend_cancel_dev);
++}
++EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
++
+ /* A flag to determine if xenstored is 'ready' (i.e. has started) */
+-int xenstored_ready = 0;
++atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED);
+ 
+ 
+ int register_xenstore_notifier(struct notifier_block *nb)
+ {
+ 	int ret = 0;
+ 
+-	if (xenstored_ready > 0)
++	if (is_xenstored_ready())
+ 		ret = nb->notifier_call(nb, 0, NULL);
+ 	else
+ 		blocking_notifier_chain_register(&xenstore_chain, nb);
+@@ -764,9 +855,10 @@ void unregister_xenstore_notifier(struct
+ }
+ EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
+ 
+-void xenbus_probe(struct work_struct *unused)
++
++void xenbus_probe(void *unused)
+ {
+-	BUG_ON((xenstored_ready <= 0));
++	BUG_ON(!is_xenstored_ready());
+ 
+ 	/* Enumerate devices in xenstore and watch for changes. */
+ 	xenbus_probe_devices(&xenbus_frontend);
+@@ -777,71 +869,252 @@ void xenbus_probe(struct work_struct *un
+ 	blocking_notifier_call_chain(&xenstore_chain, 0, NULL);
+ }
+ 
+-static int __init xenbus_probe_init(void)
++
++#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
++static struct file_operations xsd_kva_fops;
++static struct proc_dir_entry *xsd_kva_intf;
++static struct proc_dir_entry *xsd_port_intf;
++
++static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma)
++{
++	size_t size = vma->vm_end - vma->vm_start;
++	int old;
++	int rc;
++
++	old = atomic_cmpxchg(&xenbus_xsd_state,
++	                   XENBUS_XSD_UNCOMMITTED,
++	                   XENBUS_XSD_LOCAL_INIT);
++	switch (old) {
++		case XENBUS_XSD_UNCOMMITTED:
++			rc = xb_init_comms();
++			if (rc != 0)
++				return rc;
++			break;
++
++		case XENBUS_XSD_FOREIGN_INIT:
++		case XENBUS_XSD_FOREIGN_READY:
++			return -EBUSY;
++
++		case XENBUS_XSD_LOCAL_INIT:
++		case XENBUS_XSD_LOCAL_READY:
++		default:
++			break;
++	}
++
++	if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
++		return -EINVAL;
++
++	if (remap_pfn_range(vma, vma->vm_start, mfn_to_pfn(xen_store_mfn),
++			    size, vma->vm_page_prot))
++		return -EAGAIN;
++
++	return 0;
++}
++
++static int xsd_kva_read(char *page, char **start, off_t off,
++			int count, int *eof, void *data)
++{
++	int len;
++
++	len  = sprintf(page, "0x%p", xen_store_interface);
++	*eof = 1;
++	return len;
++}
++
++static int xsd_port_read(char *page, char **start, off_t off,
++			 int count, int *eof, void *data)
++{
++	int len;
++
++	len  = sprintf(page, "%d", xen_store_evtchn);
++	*eof = 1;
++	return len;
++}
++#endif
++
++static int xb_free_port(evtchn_port_t port)
++{
++	struct evtchn_close close;
++	close.port = port;
++	return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
++}
++
++int xenbus_conn(domid_t remote_dom, unsigned long *grant_ref, evtchn_port_t *local_port)
++{
++	struct evtchn_alloc_unbound alloc_unbound;
++	int rc, rc2;
++
++	BUG_ON(atomic_read(&xenbus_xsd_state) != XENBUS_XSD_FOREIGN_INIT);
++	BUG_ON(!is_initial_xendomain());
++
++#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
++	remove_xen_proc_entry("xsd_kva");
++	remove_xen_proc_entry("xsd_port");
++#endif
++
++	rc = xb_free_port(xen_store_evtchn);
++	if (rc != 0)
++		goto fail0;
++
++	alloc_unbound.dom = DOMID_SELF;
++	alloc_unbound.remote_dom = remote_dom;
++	rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
++	                                 &alloc_unbound);
++	if (rc != 0)
++		goto fail0;
++	*local_port = xen_store_evtchn = alloc_unbound.port;
++
++	/* keep the old page (xen_store_mfn, xen_store_interface) */
++	rc = gnttab_grant_foreign_access(remote_dom, xen_store_mfn,
++	                                 GTF_permit_access);
++	if (rc < 0)
++		goto fail1;
++	*grant_ref = rc;
++
++	rc = xb_init_comms();
++	if (rc != 0)
++		goto fail1;
++
++	return 0;
++
++fail1:
++	rc2 = xb_free_port(xen_store_evtchn);
++	if (rc2 != 0)
++		printk(KERN_WARNING
++		       "XENBUS: Error freeing xenstore event channel: %d\n",
++		       rc2);
++fail0:
++	xen_store_evtchn = -1;
++	return rc;
++}
++
++static int xenbus_probe_init(void)
+ {
+ 	int err = 0;
++	unsigned long page = 0;
+ 
+ 	DPRINTK("");
+ 
+-	err = -ENODEV;
+-	if (!xen_domain())
+-		goto out_error;
++	if (!is_running_on_xen())
++		return -ENODEV;
+ 
+ 	/* Register ourselves with the kernel bus subsystem */
+-	err = bus_register(&xenbus_frontend.bus);
+-	if (err)
+-		goto out_error;
+-
+-	err = xenbus_backend_bus_register();
+-	if (err)
+-		goto out_unreg_front;
++	xenbus_frontend.error = bus_register(&xenbus_frontend.bus);
++	if (xenbus_frontend.error)
++		printk(KERN_WARNING
++		       "XENBUS: Error registering frontend bus: %i\n",
++		       xenbus_frontend.error);
++	xenbus_backend_bus_register();
+ 
+ 	/*
+ 	 * Domain0 doesn't have a store_evtchn or store_mfn yet.
+ 	 */
+-	if (xen_initial_domain()) {
+-		/* dom0 not yet supported */
++	if (is_initial_xendomain()) {
++		struct evtchn_alloc_unbound alloc_unbound;
++
++		/* Allocate page. */
++		page = get_zeroed_page(GFP_KERNEL);
++		if (!page)
++			return -ENOMEM;
++
++		xen_store_mfn = xen_start_info->store_mfn =
++			pfn_to_mfn(virt_to_phys((void *)page) >>
++				   PAGE_SHIFT);
++
++		/* Next allocate a local port which xenstored can bind to */
++		alloc_unbound.dom        = DOMID_SELF;
++		alloc_unbound.remote_dom = DOMID_SELF;
++
++		err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
++						  &alloc_unbound);
++		if (err == -ENOSYS)
++			goto err;
++		BUG_ON(err);
++		xen_store_evtchn = xen_start_info->store_evtchn =
++			alloc_unbound.port;
++
++#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
++		/* And finally publish the above info in /proc/xen */
++		xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0600);
++		if (xsd_kva_intf) {
++			memcpy(&xsd_kva_fops, xsd_kva_intf->proc_fops,
++			       sizeof(xsd_kva_fops));
++			xsd_kva_fops.mmap = xsd_kva_mmap;
++			xsd_kva_intf->proc_fops = &xsd_kva_fops;
++			xsd_kva_intf->read_proc = xsd_kva_read;
++		}
++		xsd_port_intf = create_xen_proc_entry("xsd_port", 0400);
++		if (xsd_port_intf)
++			xsd_port_intf->read_proc = xsd_port_read;
++#endif
++		xen_store_interface = mfn_to_virt(xen_store_mfn);
+ 	} else {
+-		xenstored_ready = 1;
++		atomic_set(&xenbus_xsd_state, XENBUS_XSD_FOREIGN_READY);
++#ifdef CONFIG_XEN
+ 		xen_store_evtchn = xen_start_info->store_evtchn;
+ 		xen_store_mfn = xen_start_info->store_mfn;
++		xen_store_interface = mfn_to_virt(xen_store_mfn);
++#else
++		xen_store_evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
++		xen_store_mfn = hvm_get_parameter(HVM_PARAM_STORE_PFN);
++		xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT,
++					      PAGE_SIZE);
++#endif
++		/* Initialize the shared memory rings to talk to xenstored */
++		err = xb_init_comms();
++		if (err)
++			goto err;
+ 	}
+-	xen_store_interface = mfn_to_virt(xen_store_mfn);
++
++	xenbus_dev_init();
+ 
+ 	/* Initialize the interface to xenstore. */
+ 	err = xs_init();
+ 	if (err) {
+ 		printk(KERN_WARNING
+ 		       "XENBUS: Error initializing xenstore comms: %i\n", err);
+-		goto out_unreg_back;
++		goto err;
+ 	}
+ 
+-	if (!xen_initial_domain())
+-		xenbus_probe(NULL);
++	/* Register ourselves with the kernel device subsystem */
++	if (!xenbus_frontend.error) {
++		xenbus_frontend.error = device_register(&xenbus_frontend.dev);
++		if (xenbus_frontend.error) {
++			bus_unregister(&xenbus_frontend.bus);
++			printk(KERN_WARNING
++			       "XENBUS: Error registering frontend device: %i\n",
++			       xenbus_frontend.error);
++		}
++	}
++	xenbus_backend_device_register();
+ 
+-#ifdef CONFIG_XEN_COMPAT_XENFS
+-	/*
+-	 * Create xenfs mountpoint in /proc for compatibility with
+-	 * utilities that expect to find "xenbus" under "/proc/xen".
+-	 */
+-	proc_mkdir("xen", NULL);
+-#endif
++	if (!is_initial_xendomain())
++		xenbus_probe(NULL);
+ 
+ 	return 0;
+ 
+-  out_unreg_back:
+-	xenbus_backend_bus_unregister();
++ err:
++	if (page)
++		free_page(page);
+ 
+-  out_unreg_front:
+-	bus_unregister(&xenbus_frontend.bus);
++	/*
++	 * Do not unregister the xenbus front/backend buses here. The buses
++	 * must exist because front/backend drivers will use them when they are
++	 * registered.
++	 */
+ 
+-  out_error:
+ 	return err;
+ }
+ 
++#ifdef CONFIG_XEN
+ postcore_initcall(xenbus_probe_init);
+-
+-MODULE_LICENSE("GPL");
++MODULE_LICENSE("Dual BSD/GPL");
++#else
++int xenbus_init(void)
++{
++	return xenbus_probe_init();
++}
++#endif
+ 
+ static int is_device_connecting(struct device *dev, void *data)
+ {
+@@ -868,6 +1141,8 @@ static int is_device_connecting(struct d
+ 
+ static int exists_connecting_device(struct device_driver *drv)
+ {
++	if (xenbus_frontend.error)
++		return xenbus_frontend.error;
+ 	return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
+ 				is_device_connecting);
+ }
+@@ -876,6 +1151,7 @@ static int print_device_status(struct de
+ {
+ 	struct xenbus_device *xendev = to_xenbus_device(dev);
+ 	struct device_driver *drv = data;
++	struct xenbus_driver *xendrv;
+ 
+ 	/* Is this operation limited to a particular driver? */
+ 	if (drv && (dev->driver != drv))
+@@ -885,7 +1161,10 @@ static int print_device_status(struct de
+ 		/* Information only: is this too noisy? */
+ 		printk(KERN_INFO "XENBUS: Device with no driver: %s\n",
+ 		       xendev->nodename);
+-	} else if (xendev->state < XenbusStateConnected) {
++		return 0;
++	}
++
++	if (xendev->state < XenbusStateConnected) {
+ 		enum xenbus_state rstate = XenbusStateUnknown;
+ 		if (xendev->otherend)
+ 			rstate = xenbus_read_driver_state(xendev->otherend);
+@@ -894,6 +1173,11 @@ static int print_device_status(struct de
+ 		       xendev->nodename, xendev->state, rstate);
+ 	}
+ 
++	xendrv = to_xenbus_driver(dev->driver);
++	if (xendrv->is_ready && !xendrv->is_ready(xendev))
++		printk(KERN_WARNING "XENBUS: Device not ready: %s\n",
++		       xendev->nodename);
++
+ 	return 0;
+ }
+ 
+@@ -920,7 +1204,7 @@ static void wait_for_devices(struct xenb
+ 	struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
+ 	unsigned int seconds_waited = 0;
+ 
+-	if (!ready_to_wait_for_devices || !xen_domain())
++	if (!ready_to_wait_for_devices || !is_running_on_xen())
+ 		return;
+ 
+ 	while (exists_connecting_device(drv)) {
+@@ -947,10 +1231,18 @@ static void wait_for_devices(struct xenb
+ #ifndef MODULE
+ static int __init boot_wait_for_devices(void)
+ {
+-	ready_to_wait_for_devices = 1;
+-	wait_for_devices(NULL);
++	if (!xenbus_frontend.error) {
++		ready_to_wait_for_devices = 1;
++		wait_for_devices(NULL);
++	}
+ 	return 0;
+ }
+ 
+ late_initcall(boot_wait_for_devices);
+ #endif
++
++int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *))
++{
++	return bus_for_each_dev(&xenbus_frontend.bus, NULL, arg, fn);
++}
++EXPORT_SYMBOL_GPL(xenbus_for_each_frontend);
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_probe.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_probe.h	2009-12-04 10:44:50.000000000 +0100
+@@ -34,43 +34,47 @@
+ #ifndef _XENBUS_PROBE_H
+ #define _XENBUS_PROBE_H
+ 
++#ifndef BUS_ID_SIZE
+ #define XEN_BUS_ID_SIZE			20
++#else
++#define XEN_BUS_ID_SIZE			BUS_ID_SIZE
++#endif
+ 
+-#ifdef CONFIG_XEN_BACKEND
++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
+ extern void xenbus_backend_suspend(int (*fn)(struct device *, void *));
+ extern void xenbus_backend_resume(int (*fn)(struct device *, void *));
+ extern void xenbus_backend_probe_and_watch(void);
+-extern int xenbus_backend_bus_register(void);
+-extern void xenbus_backend_bus_unregister(void);
++extern void xenbus_backend_bus_register(void);
++extern void xenbus_backend_device_register(void);
+ #else
+ static inline void xenbus_backend_suspend(int (*fn)(struct device *, void *)) {}
+ static inline void xenbus_backend_resume(int (*fn)(struct device *, void *)) {}
+ static inline void xenbus_backend_probe_and_watch(void) {}
+-static inline int xenbus_backend_bus_register(void) { return 0; }
+-static inline void xenbus_backend_bus_unregister(void) {}
++static inline void xenbus_backend_bus_register(void) {}
++static inline void xenbus_backend_device_register(void) {}
+ #endif
+ 
+ struct xen_bus_type
+ {
+ 	char *root;
++	int error;
+ 	unsigned int levels;
+ 	int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
+ 	int (*probe)(const char *type, const char *dir);
+ 	struct bus_type bus;
++	struct device dev;
+ };
+ 
+ extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
+ extern int xenbus_dev_probe(struct device *_dev);
+ extern int xenbus_dev_remove(struct device *_dev);
+ extern int xenbus_register_driver_common(struct xenbus_driver *drv,
+-					 struct xen_bus_type *bus,
+-					 struct module *owner,
+-					 const char *mod_name);
++					 struct xen_bus_type *bus);
+ extern int xenbus_probe_node(struct xen_bus_type *bus,
+ 			     const char *type,
+ 			     const char *nodename);
+ extern int xenbus_probe_devices(struct xen_bus_type *bus);
+ 
+-extern void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
++extern void dev_changed(const char *node, struct xen_bus_type *bus);
+ 
+ #endif
+--- head-2010-01-07.orig/drivers/xen/xenbus/xenbus_xs.c	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenbus/xenbus_xs.c	2009-12-04 10:44:50.000000000 +0100
+@@ -47,6 +47,14 @@
+ #include <xen/xenbus.h>
+ #include "xenbus_comms.h"
+ 
++#ifdef HAVE_XEN_PLATFORM_COMPAT_H
++#include <xen/platform-compat.h>
++#endif
++
++#ifndef PF_NOFREEZE /* Old kernel (pre-2.6.6). */
++#define PF_NOFREEZE	0
++#endif
++
+ struct xs_stored_msg {
+ 	struct list_head list;
+ 
+@@ -76,6 +84,14 @@ struct xs_handle {
+ 	/*
+ 	 * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex.
+ 	 * response_mutex is never taken simultaneously with the other three.
++	 *
++	 * transaction_mutex must be held before incrementing
++	 * transaction_count. The mutex is held when a suspend is in
++	 * progress to prevent new transactions starting.
++	 *
++	 * When decrementing transaction_count to zero the wait queue
++	 * should be woken up, the suspend code waits for count to
++	 * reach zero.
+ 	 */
+ 
+ 	/* One request at a time. */
+@@ -85,7 +101,9 @@ struct xs_handle {
+ 	struct mutex response_mutex;
+ 
+ 	/* Protect transactions against save/restore. */
+-	struct rw_semaphore transaction_mutex;
++	struct mutex transaction_mutex;
++	atomic_t transaction_count;
++	wait_queue_head_t transaction_wq;
+ 
+ 	/* Protect watch (de)register against save/restore. */
+ 	struct rw_semaphore watch_mutex;
+@@ -108,7 +126,7 @@ static DEFINE_SPINLOCK(watch_events_lock
+  * carrying out work.
+  */
+ static pid_t xenwatch_pid;
+-static DEFINE_MUTEX(xenwatch_mutex);
++/* static */ DEFINE_MUTEX(xenwatch_mutex);
+ static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
+ 
+ static int get_error(const char *errorstring)
+@@ -157,6 +175,31 @@ static void *read_reply(enum xsd_sockmsg
+ 	return body;
+ }
+ 
++static void transaction_start(void)
++{
++	mutex_lock(&xs_state.transaction_mutex);
++	atomic_inc(&xs_state.transaction_count);
++	mutex_unlock(&xs_state.transaction_mutex);
++}
++
++static void transaction_end(void)
++{
++	if (atomic_dec_and_test(&xs_state.transaction_count))
++		wake_up(&xs_state.transaction_wq);
++}
++
++static void transaction_suspend(void)
++{
++	mutex_lock(&xs_state.transaction_mutex);
++	wait_event(xs_state.transaction_wq,
++		   atomic_read(&xs_state.transaction_count) == 0);
++}
++
++static void transaction_resume(void)
++{
++	mutex_unlock(&xs_state.transaction_mutex);
++}
++
+ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
+ {
+ 	void *ret;
+@@ -164,7 +207,7 @@ void *xenbus_dev_request_and_reply(struc
+ 	int err;
+ 
+ 	if (req_msg.type == XS_TRANSACTION_START)
+-		down_read(&xs_state.transaction_mutex);
++		transaction_start();
+ 
+ 	mutex_lock(&xs_state.request_mutex);
+ 
+@@ -177,14 +220,13 @@ void *xenbus_dev_request_and_reply(struc
+ 
+ 	mutex_unlock(&xs_state.request_mutex);
+ 
+-	if ((msg->type == XS_TRANSACTION_END) ||
++	if ((req_msg.type == XS_TRANSACTION_END) ||
+ 	    ((req_msg.type == XS_TRANSACTION_START) &&
+ 	     (msg->type == XS_ERROR)))
+-		up_read(&xs_state.transaction_mutex);
++		transaction_end();
+ 
+ 	return ret;
+ }
+-EXPORT_SYMBOL(xenbus_dev_request_and_reply);
+ 
+ /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
+ static void *xs_talkv(struct xenbus_transaction t,
+@@ -214,7 +256,7 @@ static void *xs_talkv(struct xenbus_tran
+ 	}
+ 
+ 	for (i = 0; i < num_vecs; i++) {
+-		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
++		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
+ 		if (err) {
+ 			mutex_unlock(&xs_state.request_mutex);
+ 			return ERR_PTR(err);
+@@ -295,7 +337,7 @@ static char **split(char *strings, unsig
+ 	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_NOIO | __GFP_HIGH);
+@@ -309,6 +351,7 @@ static char **split(char *strings, unsig
+ 	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;
+ }
+@@ -432,11 +475,11 @@ int xenbus_transaction_start(struct xenb
+ {
+ 	char *id_str;
+ 
+-	down_read(&xs_state.transaction_mutex);
++	transaction_start();
+ 
+ 	id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
+ 	if (IS_ERR(id_str)) {
+-		up_read(&xs_state.transaction_mutex);
++		transaction_end();
+ 		return PTR_ERR(id_str);
+ 	}
+ 
+@@ -461,7 +504,7 @@ int xenbus_transaction_end(struct xenbus
+ 
+ 	err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
+ 
+-	up_read(&xs_state.transaction_mutex);
++	transaction_end();
+ 
+ 	return err;
+ }
+@@ -499,7 +542,7 @@ int xenbus_printf(struct xenbus_transact
+ #define PRINTF_BUFFER_SIZE 4096
+ 	char *printf_buffer;
+ 
+-	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
++	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_NOIO | __GFP_HIGH);
+ 	if (printf_buffer == NULL)
+ 		return -ENOMEM;
+ 
+@@ -622,6 +665,8 @@ void unregister_xenbus_watch(struct xenb
+ 	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);
+@@ -639,11 +684,6 @@ void unregister_xenbus_watch(struct xenb
+ 
+ 	up_read(&xs_state.watch_mutex);
+ 
+-	/* Make sure there are no callbacks running currently (unless
+-	   its us) */
+-	if (current->pid != xenwatch_pid)
+-		mutex_lock(&xenwatch_mutex);
+-
+ 	/* Cancel pending watch events. */
+ 	spin_lock(&watch_events_lock);
+ 	list_for_each_entry_safe(msg, tmp, &watch_events, list) {
+@@ -655,14 +695,17 @@ void unregister_xenbus_watch(struct xenb
+ 	}
+ 	spin_unlock(&watch_events_lock);
+ 
+-	if (current->pid != xenwatch_pid)
++	/* Flush any currently-executing callback, unless we are it. :-) */
++	if (current->pid != xenwatch_pid) {
++		mutex_lock(&xenwatch_mutex);
+ 		mutex_unlock(&xenwatch_mutex);
++	}
+ }
+ EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
+ 
+ void xs_suspend(void)
+ {
+-	down_write(&xs_state.transaction_mutex);
++	transaction_suspend();
+ 	down_write(&xs_state.watch_mutex);
+ 	mutex_lock(&xs_state.request_mutex);
+ 	mutex_lock(&xs_state.response_mutex);
+@@ -673,11 +716,9 @@ void xs_resume(void)
+ 	struct xenbus_watch *watch;
+ 	char token[sizeof(watch) * 2 + 1];
+ 
+-	xb_init_comms();
+-
+ 	mutex_unlock(&xs_state.response_mutex);
+ 	mutex_unlock(&xs_state.request_mutex);
+-	up_write(&xs_state.transaction_mutex);
++	transaction_resume();
+ 
+ 	/* No need for watches_lock: the watch_mutex is sufficient. */
+ 	list_for_each_entry(watch, &watches, list) {
+@@ -693,7 +734,25 @@ void xs_suspend_cancel(void)
+ 	mutex_unlock(&xs_state.response_mutex);
+ 	mutex_unlock(&xs_state.request_mutex);
+ 	up_write(&xs_state.watch_mutex);
+-	up_write(&xs_state.transaction_mutex);
++	mutex_unlock(&xs_state.transaction_mutex);
++}
++
++static int xenwatch_handle_callback(void *data)
++{
++	struct xs_stored_msg *msg = data;
++
++	msg->u.watch.handle->callback(msg->u.watch.handle,
++				      (const char **)msg->u.watch.vec,
++				      msg->u.watch.vec_size);
++
++	kfree(msg->u.watch.vec);
++	kfree(msg);
++
++	/* Kill this kthread if we were spawned just for this callback. */
++	if (current->pid != xenwatch_pid)
++		do_exit(0);
++
++	return 0;
+ }
+ 
+ static int xenwatch_thread(void *unused)
+@@ -701,6 +760,7 @@ static int xenwatch_thread(void *unused)
+ 	struct list_head *ent;
+ 	struct xs_stored_msg *msg;
+ 
++	current->flags |= PF_NOFREEZE;
+ 	for (;;) {
+ 		wait_event_interruptible(watch_events_waitq,
+ 					 !list_empty(&watch_events));
+@@ -716,17 +776,29 @@ static int xenwatch_thread(void *unused)
+ 			list_del(ent);
+ 		spin_unlock(&watch_events_lock);
+ 
+-		if (ent != &watch_events) {
+-			msg = list_entry(ent, struct xs_stored_msg, list);
+-			msg->u.watch.handle->callback(
+-				msg->u.watch.handle,
+-				(const char **)msg->u.watch.vec,
+-				msg->u.watch.vec_size);
+-			kfree(msg->u.watch.vec);
+-			kfree(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;
+@@ -820,6 +892,7 @@ static int xenbus_thread(void *unused)
+ {
+ 	int err;
+ 
++	current->flags |= PF_NOFREEZE;
+ 	for (;;) {
+ 		err = process_msg();
+ 		if (err)
+@@ -834,7 +907,6 @@ static int xenbus_thread(void *unused)
+ 
+ int xs_init(void)
+ {
+-	int err;
+ 	struct task_struct *task;
+ 
+ 	INIT_LIST_HEAD(&xs_state.reply_list);
+@@ -843,13 +915,10 @@ int xs_init(void)
+ 
+ 	mutex_init(&xs_state.request_mutex);
+ 	mutex_init(&xs_state.response_mutex);
+-	init_rwsem(&xs_state.transaction_mutex);
++	mutex_init(&xs_state.transaction_mutex);
+ 	init_rwsem(&xs_state.watch_mutex);
+-
+-	/* Initialize the shared memory rings to talk to xenstored */
+-	err = xb_init_comms();
+-	if (err)
+-		return err;
++	atomic_set(&xs_state.transaction_count, 0);
++	init_waitqueue_head(&xs_state.transaction_wq);
+ 
+ 	task = kthread_run(xenwatch_thread, NULL, "xenwatch");
+ 	if (IS_ERR(task))
+--- head-2010-01-07.orig/include/xen/evtchn.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/evtchn.h	2009-12-18 10:08:33.000000000 +0100
+@@ -1,7 +1,11 @@
++#if defined(CONFIG_PARAVIRT_XEN) || !defined(__KERNEL__)
++#include "public/evtchn.h"
++#else
+ /******************************************************************************
+  * evtchn.h
+  *
+- * Interface to /dev/xen/evtchn.
++ * Communication via Xen event channels.
++ * Also definitions for the device that demuxes notifications to userspace.
+  *
+  * Copyright (c) 2003-2005, K A Fraser
+  *
+@@ -30,59 +34,117 @@
+  * IN THE SOFTWARE.
+  */
+ 
+-#ifndef __LINUX_PUBLIC_EVTCHN_H__
+-#define __LINUX_PUBLIC_EVTCHN_H__
++#ifndef __ASM_EVTCHN_H__
++#define __ASM_EVTCHN_H__
+ 
+-/*
+- * Bind a fresh port to VIRQ @virq.
+- * Return allocated port.
+- */
+-#define IOCTL_EVTCHN_BIND_VIRQ				\
+-	_IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
+-struct ioctl_evtchn_bind_virq {
+-	unsigned int virq;
+-};
++#include <linux/interrupt.h>
++#include <asm/hypervisor.h>
++#include <asm/ptrace.h>
++#include <asm/synch_bitops.h>
++#include <xen/interface/event_channel.h>
++#include <linux/smp.h>
+ 
+ /*
+- * Bind a fresh port to remote <@remote_domain, @remote_port>.
+- * Return allocated port.
++ * LOW-LEVEL DEFINITIONS
+  */
+-#define IOCTL_EVTCHN_BIND_INTERDOMAIN			\
+-	_IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
+-struct ioctl_evtchn_bind_interdomain {
+-	unsigned int remote_domain, remote_port;
+-};
+ 
+ /*
+- * Allocate a fresh port for binding to @remote_domain.
+- * Return allocated port.
+- */
+-#define IOCTL_EVTCHN_BIND_UNBOUND_PORT			\
+-	_IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
+-struct ioctl_evtchn_bind_unbound_port {
+-	unsigned int remote_domain;
+-};
++ * Dynamically bind an event source to an IRQ-like callback handler.
++ * On some platforms this may not be implemented via the Linux IRQ subsystem.
++ * The IRQ argument passed to the callback handler is the same as returned
++ * from the bind call. It may not correspond to a Linux IRQ number.
++ * Returns IRQ or negative errno.
++ */
++int bind_caller_port_to_irqhandler(
++	unsigned int caller_port,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id);
++int bind_listening_port_to_irqhandler(
++	unsigned int remote_domain,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id);
++int bind_interdomain_evtchn_to_irqhandler(
++	unsigned int remote_domain,
++	unsigned int remote_port,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id);
++int bind_virq_to_irqhandler(
++	unsigned int virq,
++	unsigned int cpu,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id);
++int bind_ipi_to_irqhandler(
++	unsigned int ipi,
++	unsigned int cpu,
++	irqreturn_t (*handler)(int, void *, struct pt_regs *),
++	unsigned long irqflags,
++	const char *devname,
++	void *dev_id);
+ 
+ /*
+- * Unbind previously allocated @port.
+- */
+-#define IOCTL_EVTCHN_UNBIND				\
+-	_IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
+-struct ioctl_evtchn_unbind {
+-	unsigned int port;
+-};
++ * Common unbind function for all event sources. Takes IRQ to unbind from.
++ * Automatically closes the underlying event channel (except for bindings
++ * made with bind_caller_port_to_irqhandler()).
++ */
++void unbind_from_irqhandler(unsigned int irq, void *dev_id);
++
++void irq_resume(void);
++
++/* Entry point for notifications into Linux subsystems. */
++asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
++
++/* Entry point for notifications into the userland character device. */
++void evtchn_device_upcall(int port);
++
++/* Mark a PIRQ as unavailable for dynamic allocation. */
++void evtchn_register_pirq(int irq);
++/* Map a Xen-supplied PIRQ to a dynamically allocated one. */
++int evtchn_map_pirq(int irq, int xen_pirq);
++/* Look up a Xen-supplied PIRQ for a dynamically allocated one. */
++int evtchn_get_xen_pirq(int irq);
++
++void mask_evtchn(int port);
++void disable_all_local_evtchn(void);
++void unmask_evtchn(int port);
++
++#ifdef CONFIG_SMP
++void rebind_evtchn_to_cpu(int port, unsigned int cpu);
++#else
++#define rebind_evtchn_to_cpu(port, cpu)	((void)0)
++#endif
++
++static inline int test_and_set_evtchn_mask(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	return synch_test_and_set_bit(port, s->evtchn_mask);
++}
++
++static inline void clear_evtchn(int port)
++{
++	shared_info_t *s = HYPERVISOR_shared_info;
++	synch_clear_bit(port, s->evtchn_pending);
++}
++
++static inline void notify_remote_via_evtchn(int port)
++{
++	struct evtchn_send send = { .port = port };
++	VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send));
++}
+ 
+ /*
+- * Unbind previously allocated @port.
++ * Use these to access the event channel underlying the IRQ handle returned
++ * by bind_*_to_irqhandler().
+  */
+-#define IOCTL_EVTCHN_NOTIFY				\
+-	_IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify))
+-struct ioctl_evtchn_notify {
+-	unsigned int port;
+-};
+-
+-/* Clear and reinitialise the event buffer. Clear error condition. */
+-#define IOCTL_EVTCHN_RESET				\
+-	_IOC(_IOC_NONE, 'E', 5, 0)
++void notify_remote_via_irq(int irq);
++int irq_to_evtchn_port(int irq);
+ 
+-#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
++#endif /* __ASM_EVTCHN_H__ */
++#endif /* CONFIG_PARAVIRT_XEN */
+--- head-2010-01-07.orig/include/xen/interface/callback.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/callback.h	2009-12-04 10:44:50.000000000 +0100
+@@ -86,6 +86,8 @@ struct callback_register {
+ 	uint16_t flags;
+ 	xen_callback_t address;
+ };
++typedef struct callback_register callback_register_t;
++DEFINE_XEN_GUEST_HANDLE(callback_register_t);
+ 
+ /*
+  * Unregister a callback.
+@@ -98,5 +100,12 @@ struct callback_unregister {
+     uint16_t type;
+     uint16_t _unused;
+ };
++typedef struct callback_unregister callback_unregister_t;
++DEFINE_XEN_GUEST_HANDLE(callback_unregister_t);
++
++#if __XEN_INTERFACE_VERSION__ < 0x00030207
++#undef CALLBACKTYPE_sysenter
++#define CALLBACKTYPE_sysenter CALLBACKTYPE_sysenter_deprecated
++#endif
+ 
+ #endif /* __XEN_PUBLIC_CALLBACK_H__ */
+--- head-2010-01-07.orig/include/xen/interface/elfnote.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/elfnote.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Definitions used for the Xen ELF notes.
+  *
++ * 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) 2006, Ian Campbell, XenSource Ltd.
+  */
+ 
+@@ -10,7 +28,7 @@
+ #define __XEN_PUBLIC_ELFNOTE_H__
+ 
+ /*
+- * The notes should live in a SHT_NOTE segment and have "Xen" in the
++ * The notes should live in a PT_NOTE segment and have "Xen" in the
+  * name field.
+  *
+  * Numeric types are either 4 or 8 bytes depending on the content of
+@@ -22,8 +40,6 @@
+ 
+ /*
+  * NAME=VALUE pair (string).
+- *
+- * LEGACY: FEATURES and PAE
+  */
+ #define XEN_ELFNOTE_INFO           0
+ 
+@@ -90,7 +106,12 @@
+ #define XEN_ELFNOTE_LOADER         8
+ 
+ /*
+- * The kernel supports PAE (x86/32 only, string = "yes" or "no").
++ * The kernel supports PAE (x86/32 only, string = "yes", "no" or
++ * "bimodal").
++ *
++ * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting
++ * may be given as "yes,bimodal" which will cause older Xen to treat
++ * this kernel as PAE.
+  *
+  * LEGACY: PAE (n.b. The legacy interface included a provision to
+  * indicate 'extended-cr3' support allowing L3 page tables to be
+@@ -140,6 +161,76 @@
+  */
+ #define XEN_ELFNOTE_SUSPEND_CANCEL 14
+ 
++/*
++ * The (non-default) location the initial phys-to-machine map should be
++ * placed at by the hypervisor (Dom0) or the tools (DomU).
++ * The kernel must be prepared for this mapping to be established using
++ * large pages, despite such otherwise not being available to guests.
++ * The kernel must also be able to handle the page table pages used for
++ * this mapping not being accessible through the initial mapping.
++ * (Only x86-64 supports this at present.)
++ */
++#define XEN_ELFNOTE_INIT_P2M      15
++
++/*
++ * The number of the highest elfnote defined.
++ */
++#define XEN_ELFNOTE_MAX XEN_ELFNOTE_INIT_P2M
++
++/*
++ * System information exported through crash notes.
++ *
++ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO
++ * note in case of a system crash. This note will contain various
++ * information about the system, see xen/include/xen/elfcore.h.
++ */
++#define XEN_ELFNOTE_CRASH_INFO 0x1000001
++
++/*
++ * System registers exported through crash notes.
++ *
++ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS
++ * note per cpu in case of a system crash. This note is architecture
++ * specific and will contain registers not saved in the "CORE" note.
++ * See xen/include/xen/elfcore.h for more information.
++ */
++#define XEN_ELFNOTE_CRASH_REGS 0x1000002
++
++
++/*
++ * xen dump-core none note.
++ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE
++ * in its dump file to indicate that the file is xen dump-core
++ * file. This note doesn't have any other information.
++ * See tools/libxc/xc_core.h for more information.
++ */
++#define XEN_ELFNOTE_DUMPCORE_NONE               0x2000000
++
++/*
++ * xen dump-core header note.
++ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER
++ * in its dump file.
++ * See tools/libxc/xc_core.h for more information.
++ */
++#define XEN_ELFNOTE_DUMPCORE_HEADER             0x2000001
++
++/*
++ * xen dump-core xen version note.
++ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION
++ * in its dump file. It contains the xen version obtained via the
++ * XENVER hypercall.
++ * See tools/libxc/xc_core.h for more information.
++ */
++#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION        0x2000002
++
++/*
++ * xen dump-core format version note.
++ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION
++ * in its dump file. It contains a format version identifier.
++ * See tools/libxc/xc_core.h for more information.
++ */
++#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION     0x2000003
++
+ #endif /* __XEN_PUBLIC_ELFNOTE_H__ */
+ 
+ /*
+--- head-2010-01-07.orig/include/xen/interface/event_channel.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/event_channel.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Event channels between domains.
+  *
++ * 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) 2003-2004, K A Fraser.
+  */
+ 
+@@ -11,8 +29,15 @@
+ 
+ #include <xen/interface/xen.h>
+ 
++/*
++ * Prototype for this hypercall is:
++ *  int event_channel_op(int cmd, void *args)
++ * @cmd  == EVTCHNOP_??? (event-channel operation).
++ * @args == Operation-specific extra arguments (NULL if none).
++ */
++
+ typedef uint32_t evtchn_port_t;
+-DEFINE_GUEST_HANDLE(evtchn_port_t);
++DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+ 
+ /*
+  * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
+@@ -22,13 +47,14 @@ DEFINE_GUEST_HANDLE(evtchn_port_t);
+  *  1. If the caller is unprivileged then <dom> must be DOMID_SELF.
+  *  2. <rdom> may be DOMID_SELF, allowing loopback connections.
+  */
+-#define EVTCHNOP_alloc_unbound	  6
++#define EVTCHNOP_alloc_unbound    6
+ struct evtchn_alloc_unbound {
+-	/* IN parameters */
+-	domid_t dom, remote_dom;
+-	/* OUT parameters */
+-	evtchn_port_t port;
++    /* IN parameters */
++    domid_t dom, remote_dom;
++    /* OUT parameters */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
+ 
+ /*
+  * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
+@@ -41,29 +67,35 @@ struct evtchn_alloc_unbound {
+  */
+ #define EVTCHNOP_bind_interdomain 0
+ struct evtchn_bind_interdomain {
+-	/* IN parameters. */
+-	domid_t remote_dom;
+-	evtchn_port_t remote_port;
+-	/* OUT parameters. */
+-	evtchn_port_t local_port;
++    /* IN parameters. */
++    domid_t remote_dom;
++    evtchn_port_t remote_port;
++    /* OUT parameters. */
++    evtchn_port_t local_port;
+ };
++typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
+ 
+ /*
+  * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
+  * vcpu.
+  * NOTES:
+- *  1. A virtual IRQ may be bound to at most one event channel per vcpu.
+- *  2. The allocated event channel is bound to the specified vcpu. The binding
+- *     may not be changed.
++ *  1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
++ *     in xen.h for the classification of each VIRQ.
++ *  2. Global VIRQs must be allocated on VCPU0 but can subsequently be
++ *     re-bound via EVTCHNOP_bind_vcpu.
++ *  3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
++ *     The allocated event channel is bound to the specified vcpu and the
++ *     binding cannot be changed.
+  */
+-#define EVTCHNOP_bind_virq	  1
++#define EVTCHNOP_bind_virq        1
+ struct evtchn_bind_virq {
+-	/* IN parameters. */
+-	uint32_t virq;
+-	uint32_t vcpu;
+-	/* OUT parameters. */
+-	evtchn_port_t port;
++    /* IN parameters. */
++    uint32_t virq;
++    uint32_t vcpu;
++    /* OUT parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_bind_virq evtchn_bind_virq_t;
+ 
+ /*
+  * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ <irq>.
+@@ -71,15 +103,16 @@ struct evtchn_bind_virq {
+  *  1. A physical IRQ may be bound to at most one event channel per domain.
+  *  2. Only a sufficiently-privileged domain may bind to a physical IRQ.
+  */
+-#define EVTCHNOP_bind_pirq	  2
++#define EVTCHNOP_bind_pirq        2
+ struct evtchn_bind_pirq {
+-	/* IN parameters. */
+-	uint32_t pirq;
++    /* IN parameters. */
++    uint32_t pirq;
+ #define BIND_PIRQ__WILL_SHARE 1
+-	uint32_t flags; /* BIND_PIRQ__* */
+-	/* OUT parameters. */
+-	evtchn_port_t port;
++    uint32_t flags; /* BIND_PIRQ__* */
++    /* OUT parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
+ 
+ /*
+  * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
+@@ -87,33 +120,36 @@ struct evtchn_bind_pirq {
+  *  1. The allocated event channel is bound to the specified vcpu. The binding
+  *     may not be changed.
+  */
+-#define EVTCHNOP_bind_ipi	  7
++#define EVTCHNOP_bind_ipi         7
+ struct evtchn_bind_ipi {
+-	uint32_t vcpu;
+-	/* OUT parameters. */
+-	evtchn_port_t port;
++    uint32_t vcpu;
++    /* OUT parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
+ 
+ /*
+  * EVTCHNOP_close: Close a local event channel <port>. If the channel is
+  * interdomain then the remote end is placed in the unbound state
+  * (EVTCHNSTAT_unbound), awaiting a new connection.
+  */
+-#define EVTCHNOP_close		  3
++#define EVTCHNOP_close            3
+ struct evtchn_close {
+-	/* IN parameters. */
+-	evtchn_port_t port;
++    /* IN parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_close evtchn_close_t;
+ 
+ /*
+  * EVTCHNOP_send: Send an event to the remote end of the channel whose local
+  * endpoint is <port>.
+  */
+-#define EVTCHNOP_send		  4
++#define EVTCHNOP_send             4
+ struct evtchn_send {
+-	/* IN parameters. */
+-	evtchn_port_t port;
++    /* IN parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_send evtchn_send_t;
+ 
+ /*
+  * EVTCHNOP_status: Get the current status of the communication channel which
+@@ -123,75 +159,98 @@ struct evtchn_send {
+  *  2. Only a sufficiently-privileged domain may obtain the status of an event
+  *     channel for which <dom> is not DOMID_SELF.
+  */
+-#define EVTCHNOP_status		  5
++#define EVTCHNOP_status           5
+ struct evtchn_status {
+-	/* IN parameters */
+-	domid_t  dom;
+-	evtchn_port_t port;
+-	/* OUT parameters */
+-#define EVTCHNSTAT_closed	0  /* Channel is not in use.		     */
+-#define EVTCHNSTAT_unbound	1  /* Channel is waiting interdom connection.*/
+-#define EVTCHNSTAT_interdomain	2  /* Channel is connected to remote domain. */
+-#define EVTCHNSTAT_pirq		3  /* Channel is bound to a phys IRQ line.   */
+-#define EVTCHNSTAT_virq		4  /* Channel is bound to a virtual IRQ line */
+-#define EVTCHNSTAT_ipi		5  /* Channel is bound to a virtual IPI line */
+-	uint32_t status;
+-	uint32_t vcpu;		   /* VCPU to which this channel is bound.   */
+-	union {
+-		struct {
+-			domid_t dom;
+-		} unbound; /* EVTCHNSTAT_unbound */
+-		struct {
+-			domid_t dom;
+-			evtchn_port_t port;
+-		} interdomain; /* EVTCHNSTAT_interdomain */
+-		uint32_t pirq;	    /* EVTCHNSTAT_pirq	      */
+-		uint32_t virq;	    /* EVTCHNSTAT_virq	      */
+-	} u;
++    /* IN parameters */
++    domid_t  dom;
++    evtchn_port_t port;
++    /* OUT parameters */
++#define EVTCHNSTAT_closed       0  /* Channel is not in use.                 */
++#define EVTCHNSTAT_unbound      1  /* Channel is waiting interdom connection.*/
++#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
++#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
++#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
++#define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */
++    uint32_t status;
++    uint32_t vcpu;                 /* VCPU to which this channel is bound.   */
++    union {
++        struct {
++            domid_t dom;
++        } unbound; /* EVTCHNSTAT_unbound */
++        struct {
++            domid_t dom;
++            evtchn_port_t port;
++        } interdomain; /* EVTCHNSTAT_interdomain */
++        uint32_t pirq;      /* EVTCHNSTAT_pirq        */
++        uint32_t virq;      /* EVTCHNSTAT_virq        */
++    } u;
+ };
++typedef struct evtchn_status evtchn_status_t;
+ 
+ /*
+  * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
+  * event is pending.
+  * NOTES:
+- *  1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
+- *     the binding. This binding cannot be changed.
+- *  2. All other channels notify vcpu0 by default. This default is set when
++ *  1. IPI-bound channels always notify the vcpu specified at bind time.
++ *     This binding cannot be changed.
++ *  2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
++ *     This binding cannot be changed.
++ *  3. All other channels notify vcpu0 by default. This default is set when
+  *     the channel is allocated (a port that is freed and subsequently reused
+  *     has its binding reset to vcpu0).
+  */
+-#define EVTCHNOP_bind_vcpu	  8
++#define EVTCHNOP_bind_vcpu        8
+ struct evtchn_bind_vcpu {
+-	/* IN parameters. */
+-	evtchn_port_t port;
+-	uint32_t vcpu;
++    /* IN parameters. */
++    evtchn_port_t port;
++    uint32_t vcpu;
+ };
++typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
+ 
+ /*
+  * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
+  * a notification to the appropriate VCPU if an event is pending.
+  */
+-#define EVTCHNOP_unmask		  9
++#define EVTCHNOP_unmask           9
+ struct evtchn_unmask {
+-	/* IN parameters. */
+-	evtchn_port_t port;
++    /* IN parameters. */
++    evtchn_port_t port;
+ };
++typedef struct evtchn_unmask evtchn_unmask_t;
+ 
++/*
++ * EVTCHNOP_reset: Close all event channels associated with specified domain.
++ * NOTES:
++ *  1. <dom> may be specified as DOMID_SELF.
++ *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
++ */
++#define EVTCHNOP_reset           10
++struct evtchn_reset {
++    /* IN parameters. */
++    domid_t dom;
++};
++typedef struct evtchn_reset evtchn_reset_t;
++
++/*
++ * Argument to event_channel_op_compat() hypercall. Superceded by new
++ * event_channel_op() hypercall since 0x00030202.
++ */
+ struct evtchn_op {
+-	uint32_t cmd; /* EVTCHNOP_* */
+-	union {
+-		struct evtchn_alloc_unbound    alloc_unbound;
+-		struct evtchn_bind_interdomain bind_interdomain;
+-		struct evtchn_bind_virq	       bind_virq;
+-		struct evtchn_bind_pirq	       bind_pirq;
+-		struct evtchn_bind_ipi	       bind_ipi;
+-		struct evtchn_close	       close;
+-		struct evtchn_send	       send;
+-		struct evtchn_status	       status;
+-		struct evtchn_bind_vcpu	       bind_vcpu;
+-		struct evtchn_unmask	       unmask;
+-	} u;
++    uint32_t cmd; /* EVTCHNOP_* */
++    union {
++        struct evtchn_alloc_unbound    alloc_unbound;
++        struct evtchn_bind_interdomain bind_interdomain;
++        struct evtchn_bind_virq        bind_virq;
++        struct evtchn_bind_pirq        bind_pirq;
++        struct evtchn_bind_ipi         bind_ipi;
++        struct evtchn_close            close;
++        struct evtchn_send             send;
++        struct evtchn_status           status;
++        struct evtchn_bind_vcpu        bind_vcpu;
++        struct evtchn_unmask           unmask;
++    } u;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(evtchn_op);
++typedef struct evtchn_op evtchn_op_t;
++DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
+ 
+ #endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
+--- head-2010-01-07.orig/include/xen/interface/features.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/features.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Feature flags, reported by XENVER_get_features.
+  *
++ * 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) 2006, Keir Fraser <keir@xensource.com>
+  */
+ 
+@@ -41,6 +59,15 @@
+ /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
+ #define XENFEAT_mmu_pt_update_preserve_ad  5
+ 
++/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
++#define XENFEAT_highmem_assist             6
++
++/*
++ * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
++ * available pte bits.
++ */
++#define XENFEAT_gnttab_map_avail_bits      7
++
+ #define XENFEAT_NR_SUBMAPS 1
+ 
+ #endif /* __XEN_PUBLIC_FEATURES_H__ */
+--- head-2010-01-07.orig/include/xen/interface/grant_table.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/grant_table.h	2010-01-04 12:17:40.000000000 +0100
+@@ -28,6 +28,7 @@
+ #ifndef __XEN_PUBLIC_GRANT_TABLE_H__
+ #define __XEN_PUBLIC_GRANT_TABLE_H__
+ 
++#include "xen.h"
+ 
+ /***********************************
+  * GRANT TABLE REPRESENTATION
+@@ -84,12 +85,26 @@
+  */
+ 
+ /*
++ * Reference to a grant entry in a specified domain's grant table.
++ */
++typedef uint32_t grant_ref_t;
++
++/*
+  * A grant table comprises a packed array of grant entries in one or more
+  * page frames shared between Xen and a guest.
+  * [XEN]: This field is written by Xen and read by the sharing guest.
+  * [GST]: This field is written by the guest and read by Xen.
+  */
+-struct grant_entry {
++
++/*
++ * Version 1 of the grant table entry structure is maintained purely
++ * for backwards compatibility.  New guests should use version 2.
++ */
++#if __XEN_INTERFACE_VERSION__ < 0x0003020a
++#define grant_entry_v1 grant_entry
++#define grant_entry_v1_t grant_entry_t
++#endif
++struct grant_entry_v1 {
+     /* GTF_xxx: various type and flag information.  [XEN,GST] */
+     uint16_t flags;
+     /* The domain being granted foreign privileges. [GST] */
+@@ -100,6 +115,7 @@ struct grant_entry {
+      */
+     uint32_t frame;
+ };
++typedef struct grant_entry_v1 grant_entry_v1_t;
+ 
+ /*
+  * Type of grant entry.
+@@ -107,10 +123,13 @@ struct grant_entry {
+  *  GTF_permit_access: Allow @domid to map/access @frame.
+  *  GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
+  *                       to this guest. Xen writes the page number to @frame.
++ *  GTF_transitive: Allow @domid to transitively access a subrange of
++ *                  @trans_grant in @trans_domid.  No mappings are allowed.
+  */
+ #define GTF_invalid         (0U<<0)
+ #define GTF_permit_access   (1U<<0)
+ #define GTF_accept_transfer (2U<<0)
++#define GTF_transitive      (3U<<0)
+ #define GTF_type_mask       (3U<<0)
+ 
+ /*
+@@ -118,6 +137,10 @@ struct grant_entry {
+  *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
+  *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
+  *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
++ *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
++ *  GTF_sub_page: Grant access to only a subrange of the page.  @domid
++ *                will only be allowed to copy from the grant, and not
++ *                map it. [GST]
+  */
+ #define _GTF_readonly       (2)
+ #define GTF_readonly        (1U<<_GTF_readonly)
+@@ -125,6 +148,14 @@ struct grant_entry {
+ #define GTF_reading         (1U<<_GTF_reading)
+ #define _GTF_writing        (4)
+ #define GTF_writing         (1U<<_GTF_writing)
++#define _GTF_PWT            (5)
++#define GTF_PWT             (1U<<_GTF_PWT)
++#define _GTF_PCD            (6)
++#define GTF_PCD             (1U<<_GTF_PCD)
++#define _GTF_PAT            (7)
++#define GTF_PAT             (1U<<_GTF_PAT)
++#define _GTF_sub_page       (8)
++#define GTF_sub_page        (1U<<_GTF_sub_page)
+ 
+ /*
+  * Subflags for GTF_accept_transfer:
+@@ -141,15 +172,87 @@ struct grant_entry {
+ #define _GTF_transfer_completed (3)
+ #define GTF_transfer_completed  (1U<<_GTF_transfer_completed)
+ 
+-
+-/***********************************
+- * GRANT TABLE QUERIES AND USES
++/*
++ * Version 2 grant table entries.  These fulfil the same role as
++ * version 1 entries, but can represent more complicated operations.
++ * Any given domain will have either a version 1 or a version 2 table,
++ * and every entry in the table will be the same version.
++ *
++ * The interface by which domains use grant references does not depend
++ * on the grant table version in use by the other domain.
+  */
++#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
++/*
++ * Version 1 and version 2 grant entries share a common prefix.  The
++ * fields of the prefix are documented as part of struct
++ * grant_entry_v1.
++ */
++struct grant_entry_header {
++    uint16_t flags;
++    domid_t  domid;
++};
++typedef struct grant_entry_header grant_entry_header_t;
+ 
+ /*
+- * Reference to a grant entry in a specified domain's grant table.
++ * Version 2 of the grant entry structure.
++ */
++union grant_entry_v2 {
++    grant_entry_header_t hdr;
++
++    /*
++     * This member is used for V1-style full page grants, where either:
++     *
++     * -- hdr.type is GTF_accept_transfer, or
++     * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
++     *
++     * In that case, the frame field has the same semantics as the
++     * field of the same name in the V1 entry structure.
++     */
++    struct {
++        grant_entry_header_t hdr;
++        uint32_t pad0;
++        uint64_t frame;
++    } full_page;
++
++    /*
++     * If the grant type is GTF_grant_access and GTF_sub_page is set,
++     * @domid is allowed to access bytes [@page_off,@page_off+@length)
++     * in frame @frame.
++     */
++    struct {
++        grant_entry_header_t hdr;
++        uint16_t page_off;
++        uint16_t length;
++        uint64_t frame;
++    } sub_page;
++
++    /*
++     * If the grant is GTF_transitive, @domid is allowed to use the
++     * grant @gref in domain @trans_domid, as if it was the local
++     * domain.  Obviously, the transitive access must be compatible
++     * with the original grant.
++     *
++     * The current version of Xen does not allow transitive grants
++     * to be mapped.
++     */
++    struct {
++        grant_entry_header_t hdr;
++        domid_t trans_domid;
++        uint16_t pad0;
++        grant_ref_t gref;
++    } transitive;
++
++    uint32_t __spacer[4]; /* Pad to a power of two */
++};
++typedef union grant_entry_v2 grant_entry_v2_t;
++
++typedef uint16_t grant_status_t;
++
++#endif /* __XEN_INTERFACE_VERSION__ */
++
++/***********************************
++ * GRANT TABLE QUERIES AND USES
+  */
+-typedef uint32_t grant_ref_t;
+ 
+ /*
+  * Handle to track a mapping created via a grant reference.
+@@ -185,7 +288,8 @@ struct gnttab_map_grant_ref {
+     grant_handle_t handle;
+     uint64_t dev_bus_addr;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
++typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
+ 
+ /*
+  * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+@@ -207,7 +311,8 @@ struct gnttab_unmap_grant_ref {
+     /* OUT parameters. */
+     int16_t  status;              /* GNTST_* */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
++typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+ 
+ /*
+  * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
+@@ -225,9 +330,10 @@ struct gnttab_setup_table {
+     uint32_t nr_frames;
+     /* OUT parameters. */
+     int16_t  status;              /* GNTST_* */
+-    GUEST_HANDLE(ulong) frame_list;
++    XEN_GUEST_HANDLE(ulong) frame_list;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
++typedef struct gnttab_setup_table gnttab_setup_table_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
+ 
+ /*
+  * GNTTABOP_dump_table: Dump the contents of the grant table to the
+@@ -240,7 +346,8 @@ struct gnttab_dump_table {
+     /* OUT parameters. */
+     int16_t status;               /* GNTST_* */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
++typedef struct gnttab_dump_table gnttab_dump_table_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
+ 
+ /*
+  * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
+@@ -253,13 +360,15 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_t
+ #define GNTTABOP_transfer                4
+ struct gnttab_transfer {
+     /* IN parameters. */
+-    unsigned long mfn;
++    xen_pfn_t     mfn;
+     domid_t       domid;
+     grant_ref_t   ref;
+     /* OUT parameters. */
+     int16_t       status;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
++typedef struct gnttab_transfer gnttab_transfer_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
++
+ 
+ /*
+  * GNTTABOP_copy: Hypervisor based copy
+@@ -283,24 +392,26 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_transf
+ #define GNTCOPY_source_gref       (1<<_GNTCOPY_source_gref)
+ #define _GNTCOPY_dest_gref        (1)
+ #define GNTCOPY_dest_gref         (1<<_GNTCOPY_dest_gref)
++#define _GNTCOPY_can_fail         (2)
++#define GNTCOPY_can_fail          (1<<_GNTCOPY_can_fail)
+ 
+ #define GNTTABOP_copy                 5
+-struct gnttab_copy {
+-	/* IN parameters. */
+-	struct {
+-		union {
+-			grant_ref_t ref;
+-			unsigned long   gmfn;
+-		} u;
+-		domid_t  domid;
+-		uint16_t offset;
+-	} source, dest;
+-	uint16_t      len;
+-	uint16_t      flags;          /* GNTCOPY_* */
+-	/* OUT parameters. */
+-	int16_t       status;
+-};
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
++typedef struct gnttab_copy {
++    /* IN parameters. */
++    struct {
++        union {
++            grant_ref_t ref;
++            xen_pfn_t   gmfn;
++        } u;
++        domid_t  domid;
++        uint16_t offset;
++    } source, dest;
++    uint16_t      len;
++    uint16_t      flags;          /* GNTCOPY_* */
++    /* OUT parameters. */
++    int16_t       status;
++} gnttab_copy_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
+ 
+ /*
+  * GNTTABOP_query_size: Query the current and maximum sizes of the shared
+@@ -318,10 +429,92 @@ struct gnttab_query_size {
+     uint32_t max_nr_frames;
+     int16_t  status;              /* GNTST_* */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
++typedef struct gnttab_query_size gnttab_query_size_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
++
++/*
++ * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
++ * tracked by <handle> but atomically replace the page table entry with one
++ * pointing to the machine address under <new_addr>.  <new_addr> will be
++ * redirected to the null entry.
++ * NOTES:
++ *  1. The call may fail in an undefined manner if either mapping is not
++ *     tracked by <handle>.
++ *  2. After executing a batch of unmaps, it is guaranteed that no stale
++ *     mappings will remain in the device or host TLBs.
++ */
++#define GNTTABOP_unmap_and_replace    7
++struct gnttab_unmap_and_replace {
++    /* IN parameters. */
++    uint64_t host_addr;
++    uint64_t new_addr;
++    grant_handle_t handle;
++    /* OUT parameters. */
++    int16_t  status;              /* GNTST_* */
++};
++typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
++
++#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
++/*
++ * GNTTABOP_set_version: Request a particular version of the grant
++ * table shared table structure.  This operation can only be performed
++ * once in any given domain.  It must be performed before any grants
++ * are activated; otherwise, the domain will be stuck with version 1.
++ * The only defined versions are 1 and 2.
++ */
++#define GNTTABOP_set_version          8
++struct gnttab_set_version {
++    /* IN/OUT parameters */
++    uint32_t version;
++};
++typedef struct gnttab_set_version gnttab_set_version_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
++
++
++/*
++ * GNTTABOP_get_status_frames: Get the list of frames used to store grant
++ * status for <dom>. In grant format version 2, the status is separated
++ * from the other shared grant fields to allow more efficient synchronization
++ * using barriers instead of atomic cmpexch operations.
++ * <nr_frames> specify the size of vector <frame_list>.
++ * The frame addresses are returned in the <frame_list>.
++ * Only <nr_frames> addresses are returned, even if the table is larger.
++ * NOTES:
++ *  1. <dom> may be specified as DOMID_SELF.
++ *  2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
++ */
++#define GNTTABOP_get_status_frames     9
++struct gnttab_get_status_frames {
++    /* IN parameters. */
++    uint32_t nr_frames;
++    domid_t  dom;
++    /* OUT parameters. */
++    int16_t  status;              /* GNTST_* */
++    XEN_GUEST_HANDLE(uint64_t) frame_list;
++};
++typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
+ 
+ /*
+- * Bitfield values for update_pin_status.flags.
++ * GNTTABOP_get_version: Get the grant table version which is in
++ * effect for domain <dom>.
++ */
++#define GNTTABOP_get_version          10
++struct gnttab_get_version {
++    /* IN parameters */
++    domid_t dom;
++    uint16_t pad;
++    /* OUT parameters */
++    uint32_t version;
++};
++typedef struct gnttab_get_version gnttab_get_version_t;
++DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
++
++#endif /* __XEN_INTERFACE_VERSION__ */
++
++/*
++ * Bitfield values for gnttab_map_grant_ref.flags.
+  */
+  /* Map the grant entry for access by I/O devices. */
+ #define _GNTMAP_device_map      (0)
+@@ -348,6 +541,16 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_
+ #define _GNTMAP_contains_pte    (4)
+ #define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
+ 
++#define _GNTMAP_can_fail        (5)
++#define GNTMAP_can_fail         (1<<_GNTMAP_can_fail)
++
++/*
++ * Bits to be placed in guest kernel available PTE bits (architecture
++ * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
++ */
++#define _GNTMAP_guest_avail0    (16)
++#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
++
+ /*
+  * Values for error status returns. All errors are -ve.
+  */
+@@ -361,7 +564,9 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_
+ #define GNTST_no_device_space  (-7) /* Out of space in I/O MMU.              */
+ #define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
+ #define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
+-#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary */
++#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary.   */
++#define GNTST_address_too_big (-11) /* transfer page address too large.      */
++#define GNTST_eagain          (-12) /* Could not map at the moment. Retry.   */
+ 
+ #define GNTTABOP_error_msgs {                   \
+     "okay",                                     \
+@@ -374,7 +579,9 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_
+     "no spare translation slot in the I/O MMU", \
+     "permission denied",                        \
+     "bad page",                                 \
+-    "copy arguments cross page boundary"        \
++    "copy arguments cross page boundary",       \
++    "page address size too large",              \
++    "could not map at the moment, retry"        \
+ }
+ 
+ #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
+--- head-2010-01-07.orig/include/xen/interface/io/blkif.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/blkif.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Unified block-device I/O interface for Xen guest OSes.
+  *
++ * 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) 2003-2004, Keir Fraser
+  */
+ 
+@@ -24,8 +42,10 @@
+  * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
+  */
+ 
+-typedef uint16_t blkif_vdev_t;
+-typedef uint64_t blkif_sector_t;
++#ifndef blkif_vdev_t
++#define blkif_vdev_t   uint16_t
++#endif
++#define blkif_sector_t uint64_t
+ 
+ /*
+  * REQUEST CODES.
+@@ -34,7 +54,7 @@ typedef uint64_t blkif_sector_t;
+ #define BLKIF_OP_WRITE             1
+ /*
+  * Recognised only if "feature-barrier" is present in backend xenbus info.
+- * The "feature_barrier" node contains a boolean indicating whether barrier
++ * The "feature-barrier" node contains a boolean indicating whether barrier
+  * requests are likely to succeed or fail. Either way, a barrier request
+  * may fail at any time with BLKIF_RSP_EOPNOTSUPP if it is unsupported by
+  * the underlying block-device hardware. The boolean simply indicates whether
+@@ -43,33 +63,57 @@ typedef uint64_t blkif_sector_t;
+  * create the "feature-barrier" node!
+  */
+ #define BLKIF_OP_WRITE_BARRIER     2
++/*
++ * Recognised if "feature-flush-cache" is present in backend xenbus
++ * info.  A flush will ask the underlying storage hardware to flush its
++ * non-volatile caches as appropriate.  The "feature-flush-cache" node
++ * contains a boolean indicating whether flush requests are likely to
++ * succeed or fail. Either way, a flush request may fail at any time
++ * with BLKIF_RSP_EOPNOTSUPP if it is unsupported by the underlying
++ * block-device hardware. The boolean simply indicates whether or not it
++ * is worthwhile for the frontend to attempt flushes.  If a backend does
++ * not recognise BLKIF_OP_WRITE_FLUSH_CACHE, it should *not* create the
++ * "feature-flush-cache" node!
++ */
++#define BLKIF_OP_FLUSH_DISKCACHE   3
+ 
+ /*
+  * Maximum scatter/gather segments per request.
+- * This is carefully chosen so that sizeof(struct blkif_ring) <= PAGE_SIZE.
++ * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
+  * NB. This could be 12 if the ring indexes weren't stored in the same page.
+  */
+ #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
+ 
++/*
++ * NB. first_sect and last_sect in blkif_request_segment, as well as
++ * sector_number in blkif_request, are always expressed in 512-byte units.
++ * However they must be properly aligned to the real sector size of the
++ * physical disk, which is reported in the "sector-size" node in the backend
++ * xenbus info. Also the xenbus "sectors" node is expressed in 512-byte units.
++ */
++struct blkif_request_segment {
++    grant_ref_t gref;        /* reference to I/O buffer frame        */
++    /* @first_sect: first sector in frame to transfer (inclusive).   */
++    /* @last_sect: last sector in frame to transfer (inclusive).     */
++    uint8_t     first_sect, last_sect;
++};
++
+ struct blkif_request {
+-	uint8_t        operation;    /* BLKIF_OP_???                         */
+-	uint8_t        nr_segments;  /* number of segments                   */
+-	blkif_vdev_t   handle;       /* only for read/write requests         */
+-	uint64_t       id;           /* private guest value, echoed in resp  */
+-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+-	struct blkif_request_segment {
+-		grant_ref_t gref;        /* reference to I/O buffer frame        */
+-		/* @first_sect: first sector in frame to transfer (inclusive).   */
+-		/* @last_sect: last sector in frame to transfer (inclusive).     */
+-		uint8_t     first_sect, last_sect;
+-	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
++    uint8_t        operation;    /* BLKIF_OP_???                         */
++    uint8_t        nr_segments;  /* number of segments                   */
++    blkif_vdev_t   handle;       /* only for read/write requests         */
++    uint64_t       id;           /* private guest value, echoed in resp  */
++    blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
++    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ };
++typedef struct blkif_request blkif_request_t;
+ 
+ struct blkif_response {
+-	uint64_t        id;              /* copied from request */
+-	uint8_t         operation;       /* copied from request */
+-	int16_t         status;          /* BLKIF_RSP_???       */
++    uint64_t        id;              /* copied from request */
++    uint8_t         operation;       /* copied from request */
++    int16_t         status;          /* BLKIF_RSP_???       */
+ };
++typedef struct blkif_response blkif_response_t;
+ 
+ /*
+  * STATUS RETURN CODES.
+--- head-2010-01-07.orig/include/xen/interface/io/console.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/console.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Console I/O interface for Xen guest OSes.
+  *
++ * 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) 2005, Keir Fraser
+  */
+ 
+--- head-2010-01-07.orig/include/xen/interface/io/fbif.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/fbif.h	2009-12-04 10:44:50.000000000 +0100
+@@ -41,12 +41,13 @@
+  */
+ #define XENFB_TYPE_UPDATE 2
+ 
+-struct xenfb_update {
+-	uint8_t type;		/* XENFB_TYPE_UPDATE */
+-	int32_t x;		/* source x */
+-	int32_t y;		/* source y */
+-	int32_t width;		/* rect width */
+-	int32_t height;		/* rect height */
++struct xenfb_update
++{
++    uint8_t type;    /* XENFB_TYPE_UPDATE */
++    int32_t x;      /* source x */
++    int32_t y;      /* source y */
++    int32_t width;  /* rect width */
++    int32_t height; /* rect height */
+ };
+ 
+ /*
+@@ -55,36 +56,58 @@ struct xenfb_update {
+  */
+ #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;		/* start offset within framebuffer */
++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];
++union xenfb_out_event
++{
++    uint8_t type;
++    struct xenfb_update update;
++    struct xenfb_resize resize;
++    char pad[XENFB_OUT_EVENT_SIZE];
+ };
+ 
+ /* In events (backend -> frontend) */
+ 
+ /*
+  * 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;
+-	char pad[XENFB_IN_EVENT_SIZE];
++union xenfb_in_event
++{
++    uint8_t type;
++    struct xenfb_refresh_period refresh_period;
++    char pad[XENFB_IN_EVENT_SIZE];
+ };
+ 
+ /* shared page */
+@@ -93,41 +116,41 @@ union xenfb_in_event {
+ #define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+ #define XENFB_IN_RING_OFFS 1024
+ #define XENFB_IN_RING(page) \
+-	((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
++    ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+ #define XENFB_IN_RING_REF(page, idx) \
+-	(XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
++    (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+ 
+ #define XENFB_OUT_RING_SIZE 2048
+ #define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+ #define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+ #define XENFB_OUT_RING(page) \
+-	((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
++    ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+ #define XENFB_OUT_RING_REF(page, idx) \
+-	(XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
++    (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+ 
+-struct xenfb_page {
+-	uint32_t in_cons, in_prod;
+-	uint32_t out_cons, out_prod;
+-
+-	int32_t width;          /* width of the framebuffer (in pixels) */
+-	int32_t height;         /* height of the framebuffer (in pixels) */
+-	uint32_t line_length;   /* length of a row of pixels (in bytes) */
+-	uint32_t mem_length;    /* length of the framebuffer (in bytes) */
+-	uint8_t depth;          /* depth of a pixel (in bits) */
+-
+-	/*
+-	 * Framebuffer page directory
+-	 *
+-	 * 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/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[256];
++struct xenfb_page
++{
++    uint32_t in_cons, in_prod;
++    uint32_t out_cons, out_prod;
++
++    int32_t width;          /* the width of the framebuffer (in pixels) */
++    int32_t height;         /* the height of the framebuffer (in pixels) */
++    uint32_t line_length;   /* the length of a row of pixels (in bytes) */
++    uint32_t mem_length;    /* the length of the framebuffer (in bytes) */
++    uint8_t depth;          /* the depth of a pixel (in bits) */
++
++    /*
++     * Framebuffer page directory
++     *
++     * 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/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[256];
+ };
+ 
+ /*
+--- head-2010-01-07.orig/include/xen/interface/io/kbdif.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/kbdif.h	2009-12-04 10:44:50.000000000 +0100
+@@ -45,34 +45,38 @@
+  */
+ #define XENKBD_TYPE_POS     4
+ 
+-struct xenkbd_motion {
+-	uint8_t type;		/* XENKBD_TYPE_MOTION */
+-	int32_t rel_x;		/* relative X motion */
+-	int32_t rel_y;		/* relative Y motion */
+-	int32_t rel_z;		/* relative Z motion (wheel) */
+-};
+-
+-struct xenkbd_key {
+-	uint8_t type;		/* XENKBD_TYPE_KEY */
+-	uint8_t pressed;	/* 1 if pressed; 0 otherwise */
+-	uint32_t keycode;	/* KEY_* from linux/input.h */
+-};
+-
+-struct xenkbd_position {
+-	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 rel_z;		/* relative Z motion (wheel) */
++struct xenkbd_motion
++{
++    uint8_t type;        /* XENKBD_TYPE_MOTION */
++    int32_t rel_x;       /* relative X motion */
++    int32_t rel_y;       /* relative Y motion */
++    int32_t rel_z;       /* relative Z motion (wheel) */
++};
++
++struct xenkbd_key
++{
++    uint8_t type;         /* XENKBD_TYPE_KEY */
++    uint8_t pressed;      /* 1 if pressed; 0 otherwise */
++    uint32_t keycode;     /* KEY_* from linux/input.h */
++};
++
++struct xenkbd_position
++{
++    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 rel_z;       /* relative Z motion (wheel) */
+ };
+ 
+ #define XENKBD_IN_EVENT_SIZE 40
+ 
+-union xenkbd_in_event {
+-	uint8_t type;
+-	struct xenkbd_motion motion;
+-	struct xenkbd_key key;
+-	struct xenkbd_position pos;
+-	char pad[XENKBD_IN_EVENT_SIZE];
++union xenkbd_in_event
++{
++    uint8_t type;
++    struct xenkbd_motion motion;
++    struct xenkbd_key key;
++    struct xenkbd_position pos;
++    char pad[XENKBD_IN_EVENT_SIZE];
+ };
+ 
+ /* Out events (frontend -> backend) */
+@@ -85,9 +89,10 @@ union xenkbd_in_event {
+ 
+ #define XENKBD_OUT_EVENT_SIZE 40
+ 
+-union xenkbd_out_event {
+-	uint8_t type;
+-	char pad[XENKBD_OUT_EVENT_SIZE];
++union xenkbd_out_event
++{
++    uint8_t type;
++    char pad[XENKBD_OUT_EVENT_SIZE];
+ };
+ 
+ /* shared page */
+@@ -96,21 +101,22 @@ union xenkbd_out_event {
+ #define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+ #define XENKBD_IN_RING_OFFS 1024
+ #define XENKBD_IN_RING(page) \
+-	((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
++    ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+ #define XENKBD_IN_RING_REF(page, idx) \
+-	(XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
++    (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+ 
+ #define XENKBD_OUT_RING_SIZE 1024
+ #define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+ #define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+ #define XENKBD_OUT_RING(page) \
+-	((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
++    ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+ #define XENKBD_OUT_RING_REF(page, idx) \
+-	(XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
++    (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+ 
+-struct xenkbd_page {
+-	uint32_t in_cons, in_prod;
+-	uint32_t out_cons, out_prod;
++struct xenkbd_page
++{
++    uint32_t in_cons, in_prod;
++    uint32_t out_cons, out_prod;
+ };
+ 
+ #endif
+--- head-2010-01-07.orig/include/xen/interface/io/netif.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/netif.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Unified network-device I/O interface for Xen guest OSes.
+  *
++ * 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) 2003-2004, Keir Fraser
+  */
+ 
+@@ -47,18 +65,21 @@
+ #define _NETTXF_extra_info     (3)
+ #define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
+ 
+-struct xen_netif_tx_request {
++struct netif_tx_request {
+     grant_ref_t gref;      /* Reference to buffer page */
+     uint16_t offset;       /* Offset within buffer page */
+     uint16_t flags;        /* NETTXF_* */
+     uint16_t id;           /* Echoed in response message. */
+     uint16_t size;         /* Packet size in bytes.       */
+ };
++typedef struct netif_tx_request netif_tx_request_t;
+ 
+ /* Types of netif_extra_info descriptors. */
+-#define XEN_NETIF_EXTRA_TYPE_NONE  (0)  /* Never used - invalid */
+-#define XEN_NETIF_EXTRA_TYPE_GSO   (1)  /* u.gso */
+-#define XEN_NETIF_EXTRA_TYPE_MAX   (2)
++#define XEN_NETIF_EXTRA_TYPE_NONE      (0)  /* Never used - invalid */
++#define XEN_NETIF_EXTRA_TYPE_GSO       (1)  /* u.gso */
++#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2)  /* u.mcast */
++#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3)  /* u.mcast */
++#define XEN_NETIF_EXTRA_TYPE_MAX       (4)
+ 
+ /* netif_extra_info flags. */
+ #define _XEN_NETIF_EXTRA_FLAG_MORE (0)
+@@ -71,49 +92,68 @@ struct xen_netif_tx_request {
+  * This structure needs to fit within both netif_tx_request and
+  * netif_rx_response for compatibility.
+  */
+-struct xen_netif_extra_info {
+-	uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
+-	uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
+-
+-	union {
+-		struct {
+-			/*
+-			 * Maximum payload size of each segment. For
+-			 * example, for TCP this is just the path MSS.
+-			 */
+-			uint16_t size;
+-
+-			/*
+-			 * GSO type. This determines the protocol of
+-			 * the packet and any extra features required
+-			 * to segment the packet properly.
+-			 */
+-			uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
+-
+-			/* Future expansion. */
+-			uint8_t pad;
+-
+-			/*
+-			 * GSO features. This specifies any extra GSO
+-			 * features required to process this packet,
+-			 * such as ECN support for TCPv4.
+-			 */
+-			uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
+-		} gso;
++struct netif_extra_info {
++    uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
++    uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
++
++    union {
++        /*
++         * XEN_NETIF_EXTRA_TYPE_GSO:
++         */
++        struct {
++            /*
++             * Maximum payload size of each segment. For example, for TCP this
++             * is just the path MSS.
++             */
++            uint16_t size;
++
++            /*
++             * GSO type. This determines the protocol of the packet and any
++             * extra features required to segment the packet properly.
++             */
++            uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
++
++            /* Future expansion. */
++            uint8_t pad;
++
++            /*
++             * GSO features. This specifies any extra GSO features required
++             * to process this packet, such as ECN support for TCPv4.
++             */
++            uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
++        } gso;
++
++        /*
++         * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}:
++         * Backend advertises availability via 'feature-multicast-control'
++         * xenbus node containing value '1'.
++         * Frontend requests this feature by advertising
++         * 'request-multicast-control' xenbus node containing value '1'.
++         * If multicast control is requested then multicast flooding is
++         * disabled and the frontend must explicitly register its interest
++         * in multicast groups using dummy transmit requests containing
++         * MCAST_{ADD,DEL} extra-info fragments.
++         */
++        struct {
++            uint8_t addr[6]; /* Address to add/remove. */
++        } mcast;
+ 
+-		uint16_t pad[3];
+-	} u;
++        uint16_t pad[3];
++    } u;
+ };
++typedef struct netif_extra_info netif_extra_info_t;
+ 
+-struct xen_netif_tx_response {
+-	uint16_t id;
+-	int16_t  status;       /* NETIF_RSP_* */
++struct netif_tx_response {
++    uint16_t id;
++    int16_t  status;       /* NETIF_RSP_* */
+ };
++typedef struct netif_tx_response netif_tx_response_t;
+ 
+-struct xen_netif_rx_request {
+-	uint16_t    id;        /* Echoed in response message.        */
+-	grant_ref_t gref;      /* Reference to incoming granted frame */
++struct netif_rx_request {
++    uint16_t    id;        /* Echoed in response message.        */
++    grant_ref_t gref;      /* Reference to incoming granted frame */
+ };
++typedef struct netif_rx_request netif_rx_request_t;
+ 
+ /* Packet data has been validated against protocol checksum. */
+ #define _NETRXF_data_validated (0)
+@@ -131,23 +171,20 @@ struct xen_netif_rx_request {
+ #define _NETRXF_extra_info     (3)
+ #define  NETRXF_extra_info     (1U<<_NETRXF_extra_info)
+ 
+-struct xen_netif_rx_response {
++struct netif_rx_response {
+     uint16_t id;
+     uint16_t offset;       /* Offset in page of start of received packet  */
+     uint16_t flags;        /* NETRXF_* */
+     int16_t  status;       /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
+ };
++typedef struct netif_rx_response netif_rx_response_t;
+ 
+ /*
+  * Generate netif ring structures and types.
+  */
+ 
+-DEFINE_RING_TYPES(xen_netif_tx,
+-		  struct xen_netif_tx_request,
+-		  struct xen_netif_tx_response);
+-DEFINE_RING_TYPES(xen_netif_rx,
+-		  struct xen_netif_rx_request,
+-		  struct xen_netif_rx_response);
++DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
++DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
+ 
+ #define NETIF_RSP_DROPPED         -2
+ #define NETIF_RSP_ERROR           -1
+--- head-2010-01-07.orig/include/xen/interface/io/protocols.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/protocols.h	2009-12-04 10:44:50.000000000 +0100
+@@ -1,10 +1,31 @@
++/******************************************************************************
++ * 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
+@@ -12,8 +33,6 @@
+ # 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
+--- head-2010-01-07.orig/include/xen/interface/io/ring.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/ring.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,16 +3,42 @@
+  *
+  * Shared producer-consumer ring macros.
+  *
++ * 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.
++ *
+  * Tim Deegan and Andrew Warfield November 2004.
+  */
+ 
+ #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. */
+-#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2		       : ((_x) & 0x1))
++#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2                  : ((_x) & 0x1))
+ #define __RD4(_x)  (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2    : __RD2(_x))
+ #define __RD8(_x)  (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4    : __RD4(_x))
+ #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8    : __RD8(_x))
+@@ -25,73 +51,77 @@ typedef unsigned int RING_IDX;
+  * power of two (so we can mask with (size-1) to loop around).
+  */
+ #define __RING_SIZE(_s, _sz) \
+-    (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
++    (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+ 
+ /*
+  * Macros to make the correct C datatypes for a new kind of ring.
+  *
+  * To make a new ring datatype, you need to have two message structures,
+- * let's say struct request, and struct response already defined.
++ * let's say request_t, and response_t already defined.
+  *
+  * In a header where you want the ring datatype declared, you then do:
+  *
+- *     DEFINE_RING_TYPES(mytag, struct request, struct response);
++ *     DEFINE_RING_TYPES(mytag, request_t, response_t);
+  *
+  * These expand out to give you a set of types, as you can see below.
+  * The most important of these are:
+  *
+- *     struct mytag_sring      - The shared ring.
+- *     struct mytag_front_ring - The 'front' half of the ring.
+- *     struct mytag_back_ring  - The 'back' half of the ring.
++ *     mytag_sring_t      - The shared ring.
++ *     mytag_front_ring_t - The 'front' half of the ring.
++ *     mytag_back_ring_t  - The 'back' half of the ring.
+  *
+  * To initialize a ring in your code you need to know the location and size
+  * of the shared memory area (PAGE_SIZE, for instance). To initialise
+  * the front half:
+  *
+- *     struct mytag_front_ring front_ring;
+- *     SHARED_RING_INIT((struct mytag_sring *)shared_page);
+- *     FRONT_RING_INIT(&front_ring, (struct mytag_sring *)shared_page,
+- *		       PAGE_SIZE);
++ *     mytag_front_ring_t front_ring;
++ *     SHARED_RING_INIT((mytag_sring_t *)shared_page);
++ *     FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+  *
+  * Initializing the back follows similarly (note that only the front
+  * initializes the shared ring):
+  *
+- *     struct mytag_back_ring back_ring;
+- *     BACK_RING_INIT(&back_ring, (struct mytag_sring *)shared_page,
+- *		      PAGE_SIZE);
++ *     mytag_back_ring_t back_ring;
++ *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+  */
+ 
+-#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)			\
+-									\
+-/* Shared ring entry */							\
+-union __name##_sring_entry {						\
+-    __req_t req;							\
+-    __rsp_t rsp;							\
+-};									\
+-									\
+-/* Shared ring page */							\
+-struct __name##_sring {							\
+-    RING_IDX req_prod, req_event;					\
+-    RING_IDX rsp_prod, rsp_event;					\
+-    uint8_t  pad[48];							\
+-    union __name##_sring_entry ring[1]; /* variable-length */		\
+-};									\
+-									\
+-/* "Front" end's private variables */					\
+-struct __name##_front_ring {						\
+-    RING_IDX req_prod_pvt;						\
+-    RING_IDX rsp_cons;							\
+-    unsigned int nr_ents;						\
+-    struct __name##_sring *sring;					\
+-};									\
+-									\
+-/* "Back" end's private variables */					\
+-struct __name##_back_ring {						\
+-    RING_IDX rsp_prod_pvt;						\
+-    RING_IDX req_cons;							\
+-    unsigned int nr_ents;						\
+-    struct __name##_sring *sring;					\
+-};
++#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
++                                                                        \
++/* Shared ring entry */                                                 \
++union __name##_sring_entry {                                            \
++    __req_t req;                                                        \
++    __rsp_t rsp;                                                        \
++};                                                                      \
++                                                                        \
++/* Shared ring page */                                                  \
++struct __name##_sring {                                                 \
++    RING_IDX req_prod, req_event;                                       \
++    RING_IDX rsp_prod, rsp_event;                                       \
++    uint8_t  netfront_smartpoll_active;                                 \
++    uint8_t  pad[47];                                                   \
++    union __name##_sring_entry ring[1]; /* variable-length */           \
++};                                                                      \
++                                                                        \
++/* "Front" end's private variables */                                   \
++struct __name##_front_ring {                                            \
++    RING_IDX req_prod_pvt;                                              \
++    RING_IDX rsp_cons;                                                  \
++    unsigned int nr_ents;                                               \
++    struct __name##_sring *sring;                                       \
++};                                                                      \
++                                                                        \
++/* "Back" end's private variables */                                    \
++struct __name##_back_ring {                                             \
++    RING_IDX rsp_prod_pvt;                                              \
++    RING_IDX req_cons;                                                  \
++    unsigned int nr_ents;                                               \
++    struct __name##_sring *sring;                                       \
++};                                                                      \
++                                                                        \
++/* Syntactic sugar */                                                   \
++typedef struct __name##_sring __name##_sring_t;                         \
++typedef struct __name##_front_ring __name##_front_ring_t;               \
++typedef struct __name##_back_ring __name##_back_ring_t
+ 
+ /*
+  * Macros for manipulating rings.
+@@ -109,86 +139,94 @@ struct __name##_back_ring {						\
+  */
+ 
+ /* Initialising empty rings */
+-#define SHARED_RING_INIT(_s) do {					\
+-    (_s)->req_prod  = (_s)->rsp_prod  = 0;				\
+-    (_s)->req_event = (_s)->rsp_event = 1;				\
+-    memset((_s)->pad, 0, sizeof((_s)->pad));				\
++#define SHARED_RING_INIT(_s) do {                                       \
++    (_s)->req_prod  = (_s)->rsp_prod  = 0;                              \
++    (_s)->req_event = (_s)->rsp_event = 1;                              \
++    (void)memset((_s)->pad, 0, sizeof((_s)->pad));                      \
+ } while(0)
+ 
+-#define FRONT_RING_INIT(_r, _s, __size) do {				\
+-    (_r)->req_prod_pvt = 0;						\
+-    (_r)->rsp_cons = 0;							\
+-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
+-    (_r)->sring = (_s);							\
++#define FRONT_RING_INIT(_r, _s, __size) do {                            \
++    (_r)->req_prod_pvt = 0;                                             \
++    (_r)->rsp_cons = 0;                                                 \
++    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
++    (_r)->sring = (_s);                                                 \
+ } while (0)
+ 
+-#define BACK_RING_INIT(_r, _s, __size) do {				\
+-    (_r)->rsp_prod_pvt = 0;						\
+-    (_r)->req_cons = 0;							\
+-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
+-    (_r)->sring = (_s);							\
++#define BACK_RING_INIT(_r, _s, __size) do {                             \
++    (_r)->rsp_prod_pvt = 0;                                             \
++    (_r)->req_cons = 0;                                                 \
++    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
++    (_r)->sring = (_s);                                                 \
+ } while (0)
+ 
+ /* Initialize to existing shared indexes -- for recovery */
+-#define FRONT_RING_ATTACH(_r, _s, __size) do {				\
+-    (_r)->sring = (_s);							\
+-    (_r)->req_prod_pvt = (_s)->req_prod;				\
+-    (_r)->rsp_cons = (_s)->rsp_prod;					\
+-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
++#define FRONT_RING_ATTACH(_r, _s, __size) do {                          \
++    (_r)->sring = (_s);                                                 \
++    (_r)->req_prod_pvt = (_s)->req_prod;                                \
++    (_r)->rsp_cons = (_s)->rsp_prod;                                    \
++    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+ } while (0)
+ 
+-#define BACK_RING_ATTACH(_r, _s, __size) do {				\
+-    (_r)->sring = (_s);							\
+-    (_r)->rsp_prod_pvt = (_s)->rsp_prod;				\
+-    (_r)->req_cons = (_s)->req_prod;					\
+-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
++#define BACK_RING_ATTACH(_r, _s, __size) do {                           \
++    (_r)->sring = (_s);                                                 \
++    (_r)->rsp_prod_pvt = (_s)->rsp_prod;                                \
++    (_r)->req_cons = (_s)->req_prod;                                    \
++    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+ } while (0)
+ 
+ /* How big is this ring? */
+-#define RING_SIZE(_r)							\
++#define RING_SIZE(_r)                                                   \
+     ((_r)->nr_ents)
+ 
+ /* Number of free requests (for use on front side only). */
+-#define RING_FREE_REQUESTS(_r)						\
++#define RING_FREE_REQUESTS(_r)                                          \
+     (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+ 
+ /* Test if there is an empty slot available on the front ring.
+  * (This is only meaningful from the front. )
+  */
+-#define RING_FULL(_r)							\
++#define RING_FULL(_r)                                                   \
+     (RING_FREE_REQUESTS(_r) == 0)
+ 
+ /* Test if there are outstanding messages to be processed on a ring. */
+-#define RING_HAS_UNCONSUMED_RESPONSES(_r)				\
++#define RING_HAS_UNCONSUMED_RESPONSES(_r)                               \
+     ((_r)->sring->rsp_prod - (_r)->rsp_cons)
+ 
+-#define RING_HAS_UNCONSUMED_REQUESTS(_r)				\
+-    ({									\
+-	unsigned int req = (_r)->sring->req_prod - (_r)->req_cons;	\
+-	unsigned int rsp = RING_SIZE(_r) -				\
+-			   ((_r)->req_cons - (_r)->rsp_prod_pvt);	\
+-	req < rsp ? req : rsp;						\
+-    })
++#ifdef __GNUC__
++#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({                             \
++    unsigned int req = (_r)->sring->req_prod - (_r)->req_cons;          \
++    unsigned int rsp = RING_SIZE(_r) -                                  \
++        ((_r)->req_cons - (_r)->rsp_prod_pvt);                          \
++    req < rsp ? req : rsp;                                              \
++})
++#else
++/* Same as above, but without the nice GCC ({ ... }) syntax. */
++#define RING_HAS_UNCONSUMED_REQUESTS(_r)                                \
++    ((((_r)->sring->req_prod - (_r)->req_cons) <                        \
++      (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ?        \
++     ((_r)->sring->req_prod - (_r)->req_cons) :                         \
++     (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
++#endif
+ 
+ /* Direct access to individual ring elements, by index. */
+-#define RING_GET_REQUEST(_r, _idx)					\
++#define RING_GET_REQUEST(_r, _idx)                                      \
+     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+ 
+-#define RING_GET_RESPONSE(_r, _idx)					\
++#define RING_GET_RESPONSE(_r, _idx)                                     \
+     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+ 
+ /* Loop termination condition: Would the specified index overflow the ring? */
+-#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)				\
++#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)                           \
+     (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+ 
+-#define RING_PUSH_REQUESTS(_r) do {					\
+-    wmb(); /* back sees requests /before/ updated producer index */	\
+-    (_r)->sring->req_prod = (_r)->req_prod_pvt;				\
++#define RING_PUSH_REQUESTS(_r) do {                                     \
++    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 */	\
+-    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;				\
++#define RING_PUSH_RESPONSES(_r) do {                                    \
++    xen_wmb(); /* front sees resps /before/ updated producer index */   \
++    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;                         \
+ } while (0)
+ 
+ /*
+@@ -221,40 +259,40 @@ struct __name##_back_ring {						\
+  *  field appropriately.
+  */
+ 
+-#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 */	\
+-    (_r)->sring->req_prod = __new;					\
+-    mb(); /* back sees new requests /before/ we check req_event */	\
+-    (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) <		\
+-		 (RING_IDX)(__new - __old));				\
++#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do {           \
++    RING_IDX __old = (_r)->sring->req_prod;                             \
++    RING_IDX __new = (_r)->req_prod_pvt;                                \
++    xen_wmb(); /* back sees requests /before/ updated producer index */ \
++    (_r)->sring->req_prod = __new;                                      \
++    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)
+ 
+-#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 */	\
+-    (_r)->sring->rsp_prod = __new;					\
+-    mb(); /* front sees new responses /before/ we check rsp_event */	\
+-    (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) <		\
+-		 (RING_IDX)(__new - __old));				\
++#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do {          \
++    RING_IDX __old = (_r)->sring->rsp_prod;                             \
++    RING_IDX __new = (_r)->rsp_prod_pvt;                                \
++    xen_wmb(); /* front sees resps /before/ updated producer index */   \
++    (_r)->sring->rsp_prod = __new;                                      \
++    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)
+ 
+-#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {		\
+-    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);			\
+-    if (_work_to_do) break;						\
+-    (_r)->sring->req_event = (_r)->req_cons + 1;			\
+-    mb();								\
+-    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);			\
++#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {             \
++    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
++    if (_work_to_do) break;                                             \
++    (_r)->sring->req_event = (_r)->req_cons + 1;                        \
++    xen_mb();                                                           \
++    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+ } while (0)
+ 
+-#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {		\
+-    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);			\
+-    if (_work_to_do) break;						\
+-    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;			\
+-    mb();								\
+-    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);			\
++#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {            \
++    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
++    if (_work_to_do) break;                                             \
++    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;                        \
++    xen_mb();                                                           \
++    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+ } while (0)
+ 
+ #endif /* __XEN_PUBLIC_IO_RING_H__ */
+--- head-2010-01-07.orig/include/xen/interface/io/xenbus.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/xenbus.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,42 +3,68 @@
+  *
+  * Xenbus protocol details.
+  *
++ * 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) 2005 XenSource Ltd.
+  */
+ 
+ #ifndef _XEN_PUBLIC_IO_XENBUS_H
+ #define _XEN_PUBLIC_IO_XENBUS_H
+ 
+-/* The state of either end of the Xenbus, i.e. the current communication
+-   status of initialisation across the bus.  States here imply nothing about
+-   the state of the connection between the driver and the kernel's device
+-   layers.  */
+-enum xenbus_state
+-{
+-	XenbusStateUnknown      = 0,
+-	XenbusStateInitialising = 1,
+-	XenbusStateInitWait     = 2,  /* Finished early
+-					 initialisation, but waiting
+-					 for information from the peer
+-					 or hotplug scripts. */
+-	XenbusStateInitialised  = 3,  /* Initialised and waiting for a
+-					 connection from the peer. */
+-	XenbusStateConnected    = 4,
+-	XenbusStateClosing      = 5,  /* The device is being closed
+-					 due to an error or an unplug
+-					 event. */
+-	XenbusStateClosed       = 6
++/*
++ * The state of either end of the Xenbus, i.e. the current communication
++ * status of initialisation across the bus.  States here imply nothing about
++ * the state of the connection between the driver and the kernel's device
++ * layers.
++ */
++enum xenbus_state {
++    XenbusStateUnknown       = 0,
++
++    XenbusStateInitialising  = 1,
++
++    /*
++     * InitWait: Finished early initialisation but waiting for information
++     * from the peer or hotplug scripts.
++     */
++    XenbusStateInitWait      = 2,
++
++    /*
++     * Initialised: Waiting for a connection from the peer.
++     */
++    XenbusStateInitialised   = 3,
+ 
++    XenbusStateConnected     = 4,
++
++    /*
++     * Closing: The device is being closed due to an error or an unplug event.
++     */
++    XenbusStateClosing       = 5,
++
++    XenbusStateClosed        = 6,
++
++    /*
++     * Reconfiguring: The device is being reconfigured.
++     */
++    XenbusStateReconfiguring = 7,
++
++    XenbusStateReconfigured  = 8
+ };
++typedef enum xenbus_state XenbusState;
+ 
+ #endif /* _XEN_PUBLIC_IO_XENBUS_H */
+-
+-/*
+- * Local variables:
+- *  c-file-style: "linux"
+- *  indent-tabs-mode: t
+- *  c-indent-level: 8
+- *  c-basic-offset: 8
+- *  tab-width: 8
+- * End:
+- */
+--- head-2010-01-07.orig/include/xen/interface/io/xs_wire.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/io/xs_wire.h	2009-12-04 10:44:50.000000000 +0100
+@@ -1,6 +1,25 @@
+ /*
+  * Details of the "wire" protocol between Xen Store Daemon and client
+  * library or guest kernel.
++ *
++ * 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) 2005 Rusty Russell IBM Corporation
+  */
+ 
+@@ -26,7 +45,9 @@ enum xsd_sockmsg_type
+     XS_SET_PERMS,
+     XS_WATCH_EVENT,
+     XS_ERROR,
+-    XS_IS_DOMAIN_INTRODUCED
++    XS_IS_DOMAIN_INTRODUCED,
++    XS_RESUME,
++    XS_SET_TARGET
+ };
+ 
+ #define XS_WRITE_NONE "NONE"
+@@ -39,8 +60,14 @@ struct xsd_errors
+     int errnum;
+     const char *errstring;
+ };
++#ifdef EINVAL
+ #define XSD_ERROR(x) { x, #x }
+-static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
++/* LINTED: static unused */
++static struct xsd_errors xsd_errors[]
++#if defined(__GNUC__)
++__attribute__((unused))
++#endif
++    = {
+     XSD_ERROR(EINVAL),
+     XSD_ERROR(EACCES),
+     XSD_ERROR(EEXIST),
+@@ -56,6 +83,7 @@ static struct xsd_errors xsd_errors[] __
+     XSD_ERROR(EAGAIN),
+     XSD_ERROR(EISCONN)
+ };
++#endif
+ 
+ struct xsd_sockmsg
+ {
+@@ -84,4 +112,11 @@ struct xenstore_domain_interface {
+     XENSTORE_RING_IDX rsp_cons, rsp_prod;
+ };
+ 
++/* Violating this is very bad.  See docs/misc/xenstore.txt. */
++#define XENSTORE_PAYLOAD_MAX 4096
++
++/* Violating these just gets you an error back */
++#define XENSTORE_ABS_PATH_MAX 3072
++#define XENSTORE_REL_PATH_MAX 2048
++
+ #endif /* _XS_WIRE_H */
+--- head-2010-01-07.orig/include/xen/interface/memory.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/memory.h	2010-01-04 12:17:29.000000000 +0100
+@@ -3,20 +3,57 @@
+  *
+  * Memory reservation and information.
+  *
++ * 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) 2005, Keir Fraser <keir@xensource.com>
+  */
+ 
+ #ifndef __XEN_PUBLIC_MEMORY_H__
+ #define __XEN_PUBLIC_MEMORY_H__
+ 
++#include "xen.h"
++
+ /*
+- * Increase or decrease the specified domain's memory reservation. Returns a
+- * -ve errcode on failure, or the # extents successfully allocated or freed.
++ * Increase or decrease the specified domain's memory reservation. Returns the
++ * number of extents successfully allocated or freed.
+  * arg == addr of struct xen_memory_reservation.
+  */
+ #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)
++/* Flag to populate physmap with populate-on-demand entries */
++#define XENMEMF_populate_on_demand (1<<16)
++#endif
++
+ struct xen_memory_reservation {
+ 
+     /*
+@@ -29,28 +66,70 @@ struct xen_memory_reservation {
+      *   OUT: GMFN bases of extents that were allocated
+      *   (NB. This command also updates the mach_to_phys translation table)
+      */
+-    GUEST_HANDLE(ulong) extent_start;
++    XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+ 
+     /* Number of extents, and size/alignment of each (2^extent_order pages). */
+-    unsigned long  nr_extents;
++    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.
+      * Unprivileged domains can specify only DOMID_SELF.
+      */
+     domid_t        domid;
++};
++typedef struct xen_memory_reservation xen_memory_reservation_t;
++DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+ 
++/*
++ * An atomic exchange of memory pages. If return code is zero then
++ * @out.extent_list provides GMFNs of the newly-allocated memory.
++ * Returns zero on complete success, otherwise a negative error code.
++ * On complete success then always @nr_exchanged == @in.nr_extents.
++ * On partial success @nr_exchanged indicates how much work was done.
++ */
++#define XENMEM_exchange             11
++struct xen_memory_exchange {
++    /*
++     * [IN] Details of memory extents to be exchanged (GMFN bases).
++     * Note that @in.address_bits is ignored and unused.
++     */
++    struct xen_memory_reservation in;
++
++    /*
++     * [IN/OUT] Details of new memory extents.
++     * We require that:
++     *  1. @in.domid == @out.domid
++     *  2. @in.nr_extents  << @in.extent_order ==
++     *     @out.nr_extents << @out.extent_order
++     *  3. @in.extent_start and @out.extent_start lists must not overlap
++     *  4. @out.extent_start lists GPFN bases to be populated
++     *  5. @out.extent_start is overwritten with allocated GMFN bases
++     */
++    struct xen_memory_reservation out;
++
++    /*
++     * [OUT] Number of input extents that were successfully exchanged:
++     *  1. The first @nr_exchanged input extents were successfully
++     *     deallocated.
++     *  2. The corresponding first entries in the output extent list correctly
++     *     indicate the GMFNs that were successfully exchanged.
++     *  3. All other input and output extents are untouched.
++     *  4. If not all input exents are exchanged then the return code of this
++     *     command will be non-zero.
++     *  5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
++     */
++    xen_ulong_t nr_exchanged;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
++typedef struct xen_memory_exchange xen_memory_exchange_t;
++DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
+ 
+ /*
+  * Returns the maximum machine frame number of mapped RAM in this system.
+@@ -68,6 +147,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_re
+ #define XENMEM_maximum_reservation  4
+ 
+ /*
++ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
++ */
++#define XENMEM_maximum_gpfn         14
++
++/*
+  * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
+  * mapping table. Architectures which do not have a m2p table do not implement
+  * this command.
+@@ -86,7 +170,7 @@ struct xen_machphys_mfn_list {
+      * any large discontiguities in the machine address space, 2MB gaps in
+      * the machphys table will be represented by an MFN base of zero.
+      */
+-    GUEST_HANDLE(ulong) extent_start;
++    XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
+ 
+     /*
+      * Number of extents written to the above array. This will be smaller
+@@ -94,7 +178,22 @@ struct xen_machphys_mfn_list {
+      */
+     unsigned int nr_extents;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
++typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
++DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
++
++/*
++ * Returns the location in virtual address space of the machine_to_phys
++ * mapping table. Architectures which do not have a m2p table, or which do not
++ * map it by default into guest address space, do not implement this command.
++ * arg == addr of xen_machphys_mapping_t.
++ */
++#define XENMEM_machphys_mapping     12
++struct xen_machphys_mapping {
++    xen_ulong_t v_start, v_end; /* Start and end virtual addresses.   */
++    xen_ulong_t max_mfn;        /* Maximum MFN that can be looked up. */
++};
++typedef struct xen_machphys_mapping xen_machphys_mapping_t;
++DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
+ 
+ /*
+  * Sets the GPFN at which a particular page appears in the specified guest's
+@@ -109,37 +208,84 @@ struct xen_add_to_physmap {
+     /* Source mapping space. */
+ #define XENMAPSPACE_shared_info 0 /* shared info page */
+ #define XENMAPSPACE_grant_table 1 /* grant table page */
++#define XENMAPSPACE_gmfn        2 /* GMFN */
+     unsigned int space;
+ 
++#define XENMAPIDX_grant_table_status 0x80000000
++
+     /* Index into source mapping space. */
+-    unsigned long idx;
++    xen_ulong_t idx;
+ 
+     /* GPFN where the source mapping page should appear. */
+-    unsigned long gpfn;
++    xen_pfn_t     gpfn;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
++typedef struct xen_add_to_physmap xen_add_to_physmap_t;
++DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
++
++/*** REMOVED ***/
++/*#define XENMEM_translate_gpfn_list  8*/
+ 
+ /*
+- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
+- * code on failure. This call only works for auto-translated guests.
++ * Returns the pseudo-physical memory map as it was when the domain
++ * was started (specified by XENMEM_set_memory_map).
++ * arg == addr of xen_memory_map_t.
+  */
+-#define XENMEM_translate_gpfn_list  8
+-struct xen_translate_gpfn_list {
+-    /* Which domain to translate for? */
+-    domid_t domid;
+-
+-    /* Length of list. */
+-    unsigned long nr_gpfns;
+-
+-    /* List of GPFNs to translate. */
+-    GUEST_HANDLE(ulong) gpfn_list;
++#define XENMEM_memory_map           9
++struct xen_memory_map {
++    /*
++     * On call the number of entries which can be stored in buffer. On
++     * return the number of entries which have been stored in
++     * buffer.
++     */
++    unsigned int nr_entries;
+ 
+     /*
+-     * Output list to contain MFN translations. May be the same as the input
+-     * list (in which case each input GPFN is overwritten with the output MFN).
++     * Entries in the buffer are in the same format as returned by the
++     * BIOS INT 0x15 EAX=0xE820 call.
+      */
+-    GUEST_HANDLE(ulong) mfn_list;
++    XEN_GUEST_HANDLE(void) buffer;
++};
++typedef struct xen_memory_map xen_memory_map_t;
++DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
++
++/*
++ * Returns the real physical memory map. Passes the same structure as
++ * XENMEM_memory_map.
++ * arg == addr of xen_memory_map_t.
++ */
++#define XENMEM_machine_memory_map   10
++
++/*
++ * Set the pseudo-physical memory map of a domain, as returned by
++ * XENMEM_memory_map.
++ * arg == addr of xen_foreign_memory_map_t.
++ */
++#define XENMEM_set_memory_map       13
++struct xen_foreign_memory_map {
++    domid_t domid;
++    struct xen_memory_map map;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
++typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
++DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
++
++#define XENMEM_set_pod_target       16
++#define XENMEM_get_pod_target       17
++struct xen_pod_target {
++    /* IN */
++    uint64_t target_pages;
++    /* OUT */
++    uint64_t tot_pages;
++    uint64_t pod_cache_pages;
++    uint64_t pod_entries;
++    /* IN */
++    domid_t domid;
++};
++typedef struct xen_pod_target xen_pod_target_t;
++
++/*
++ * Get the number of MFNs saved through memory sharing.
++ * The call never fails.
++ */
++#define XENMEM_get_sharing_freed_pages    18
+ 
+ #endif /* __XEN_PUBLIC_MEMORY_H__ */
+--- head-2010-01-07.orig/include/xen/interface/physdev.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/physdev.h	2010-01-04 11:56:34.000000000 +0100
+@@ -21,10 +21,12 @@
+ #ifndef __XEN_PUBLIC_PHYSDEV_H__
+ #define __XEN_PUBLIC_PHYSDEV_H__
+ 
++#include "xen.h"
++
+ /*
+  * Prototype for this hypercall is:
+  *  int physdev_op(int cmd, void *args)
+- * @cmd	 == PHYSDEVOP_??? (physdev operation).
++ * @cmd  == PHYSDEVOP_??? (physdev operation).
+  * @args == Operation-specific extra arguments (NULL if none).
+  */
+ 
+@@ -32,114 +34,231 @@
+  * Notify end-of-interrupt (EOI) for the specified IRQ.
+  * @arg == pointer to physdev_eoi structure.
+  */
+-#define PHYSDEVOP_eoi			12
++#define PHYSDEVOP_eoi                   12
+ struct physdev_eoi {
+-	/* IN */
+-	uint32_t irq;
++    /* IN */
++    uint32_t irq;
++};
++typedef struct physdev_eoi physdev_eoi_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
++
++/*
++ * Register a shared page for the hypervisor to indicate whether the guest
++ * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
++ * once the guest used this function in that the associated event channel
++ * will automatically get unmasked. The page registered is used as a bit
++ * array indexed by Xen's PIRQ value.
++ */
++#define PHYSDEVOP_pirq_eoi_gmfn         17
++struct physdev_pirq_eoi_gmfn {
++    /* IN */
++    xen_pfn_t gmfn;
+ };
++typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
+ 
+ /*
+  * Query the status of an IRQ line.
+  * @arg == pointer to physdev_irq_status_query structure.
+  */
+-#define PHYSDEVOP_irq_status_query	 5
++#define PHYSDEVOP_irq_status_query       5
+ struct physdev_irq_status_query {
+-	/* IN */
+-	uint32_t irq;
+-	/* OUT */
+-	uint32_t flags; /* XENIRQSTAT_* */
++    /* IN */
++    uint32_t irq;
++    /* OUT */
++    uint32_t flags; /* XENIRQSTAT_* */
+ };
++typedef struct physdev_irq_status_query physdev_irq_status_query_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t);
+ 
+ /* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */
+-#define _XENIRQSTAT_needs_eoi	(0)
+-#define	 XENIRQSTAT_needs_eoi	(1U<<_XENIRQSTAT_needs_eoi)
++#define _XENIRQSTAT_needs_eoi   (0)
++#define  XENIRQSTAT_needs_eoi   (1U<<_XENIRQSTAT_needs_eoi)
+ 
+ /* IRQ shared by multiple guests? */
+-#define _XENIRQSTAT_shared	(1)
+-#define	 XENIRQSTAT_shared	(1U<<_XENIRQSTAT_shared)
++#define _XENIRQSTAT_shared      (1)
++#define  XENIRQSTAT_shared      (1U<<_XENIRQSTAT_shared)
+ 
+ /*
+  * Set the current VCPU's I/O privilege level.
+  * @arg == pointer to physdev_set_iopl structure.
+  */
+-#define PHYSDEVOP_set_iopl		 6
++#define PHYSDEVOP_set_iopl               6
+ struct physdev_set_iopl {
+-	/* IN */
+-	uint32_t iopl;
++    /* IN */
++    uint32_t iopl;
+ };
++typedef struct physdev_set_iopl physdev_set_iopl_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t);
+ 
+ /*
+  * Set the current VCPU's I/O-port permissions bitmap.
+  * @arg == pointer to physdev_set_iobitmap structure.
+  */
+-#define PHYSDEVOP_set_iobitmap		 7
++#define PHYSDEVOP_set_iobitmap           7
+ struct physdev_set_iobitmap {
+-	/* IN */
+-	uint8_t * bitmap;
+-	uint32_t nr_ports;
++    /* IN */
++#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;
++DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t);
+ 
+ /*
+  * Read or write an IO-APIC register.
+  * @arg == pointer to physdev_apic structure.
+  */
+-#define PHYSDEVOP_apic_read		 8
+-#define PHYSDEVOP_apic_write		 9
++#define PHYSDEVOP_apic_read              8
++#define PHYSDEVOP_apic_write             9
+ struct physdev_apic {
+-	/* IN */
+-	unsigned long apic_physbase;
+-	uint32_t reg;
+-	/* IN or OUT */
+-	uint32_t value;
++    /* IN */
++    unsigned long apic_physbase;
++    uint32_t reg;
++    /* IN or OUT */
++    uint32_t value;
+ };
++typedef struct physdev_apic physdev_apic_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_apic_t);
+ 
+ /*
+  * Allocate or free a physical upcall vector for the specified IRQ line.
+  * @arg == pointer to physdev_irq structure.
+  */
+-#define PHYSDEVOP_alloc_irq_vector	10
+-#define PHYSDEVOP_free_irq_vector	11
++#define PHYSDEVOP_alloc_irq_vector      10
++#define PHYSDEVOP_free_irq_vector       11
+ struct physdev_irq {
+-	/* IN */
+-	uint32_t irq;
+-	/* IN or OUT */
+-	uint32_t vector;
++    /* IN */
++    uint32_t irq;
++    /* IN or OUT */
++    uint32_t vector;
++};
++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);
++
++#define PHYSDEVOP_restore_msi            19
++struct physdev_restore_msi {
++    /* IN */
++    uint8_t bus;
++    uint8_t devfn;
++};
++typedef struct physdev_restore_msi physdev_restore_msi_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
++
++#define PHYSDEVOP_manage_pci_add_ext     20
++struct physdev_manage_pci_ext {
++    /* IN */
++    uint8_t bus;
++    uint8_t devfn;
++    unsigned is_extfn;
++    unsigned is_virtfn;
++    struct {
++        uint8_t bus;
++        uint8_t devfn;
++    } physfn;
+ };
+ 
++typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
++
+ /*
+  * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
+  * hypercall since 0x00030202.
+  */
+ struct physdev_op {
+-	uint32_t cmd;
+-	union {
+-		struct physdev_irq_status_query	     irq_status_query;
+-		struct physdev_set_iopl		     set_iopl;
+-		struct physdev_set_iobitmap	     set_iobitmap;
+-		struct physdev_apic		     apic_op;
+-		struct physdev_irq		     irq_op;
+-	} u;
++    uint32_t cmd;
++    union {
++        struct physdev_irq_status_query      irq_status_query;
++        struct physdev_set_iopl              set_iopl;
++        struct physdev_set_iobitmap          set_iobitmap;
++        struct physdev_apic                  apic_op;
++        struct physdev_irq                   irq_op;
++    } u;
++};
++typedef struct physdev_op physdev_op_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
++
++#define PHYSDEVOP_setup_gsi    21
++struct physdev_setup_gsi {
++    int gsi;
++    /* IN */
++    uint8_t triggering;
++    /* IN */
++    uint8_t polarity;
++    /* IN */
+ };
+ 
++typedef struct physdev_setup_gsi physdev_setup_gsi_t;
++DEFINE_XEN_GUEST_HANDLE(physdev_setup_gsi_t);
++
+ /*
+  * Notify that some PIRQ-bound event channels have been unmasked.
+  * ** This command is obsolete since interface version 0x00030202 and is **
+- * ** unsupported by newer versions of Xen.				 **
++ * ** unsupported by newer versions of Xen.                              **
+  */
+-#define PHYSDEVOP_IRQ_UNMASK_NOTIFY	 4
++#define PHYSDEVOP_IRQ_UNMASK_NOTIFY      4
+ 
+ /*
+  * These all-capitals physdev operation names are superceded by the new names
+  * (defined above) since interface version 0x00030202.
+  */
+-#define PHYSDEVOP_IRQ_STATUS_QUERY	 PHYSDEVOP_irq_status_query
+-#define PHYSDEVOP_SET_IOPL		 PHYSDEVOP_set_iopl
+-#define PHYSDEVOP_SET_IOBITMAP		 PHYSDEVOP_set_iobitmap
+-#define PHYSDEVOP_APIC_READ		 PHYSDEVOP_apic_read
+-#define PHYSDEVOP_APIC_WRITE		 PHYSDEVOP_apic_write
+-#define PHYSDEVOP_ASSIGN_VECTOR		 PHYSDEVOP_alloc_irq_vector
+-#define PHYSDEVOP_FREE_VECTOR		 PHYSDEVOP_free_irq_vector
++#define PHYSDEVOP_IRQ_STATUS_QUERY       PHYSDEVOP_irq_status_query
++#define PHYSDEVOP_SET_IOPL               PHYSDEVOP_set_iopl
++#define PHYSDEVOP_SET_IOBITMAP           PHYSDEVOP_set_iobitmap
++#define PHYSDEVOP_APIC_READ              PHYSDEVOP_apic_read
++#define PHYSDEVOP_APIC_WRITE             PHYSDEVOP_apic_write
++#define PHYSDEVOP_ASSIGN_VECTOR          PHYSDEVOP_alloc_irq_vector
++#define PHYSDEVOP_FREE_VECTOR            PHYSDEVOP_free_irq_vector
+ #define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi
+-#define PHYSDEVOP_IRQ_SHARED		 XENIRQSTAT_shared
++#define PHYSDEVOP_IRQ_SHARED             XENIRQSTAT_shared
+ 
+ #endif /* __XEN_PUBLIC_PHYSDEV_H__ */
+--- head-2010-01-07.orig/include/xen/interface/sched.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/sched.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Scheduler state interactions
+  *
++ * 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) 2005, Keir Fraser <keir@xensource.com>
+  */
+ 
+@@ -13,17 +31,17 @@
+ 
+ /*
+  * The prototype for this hypercall is:
+- *  long sched_op_new(int cmd, void *arg)
++ *  long sched_op(int cmd, void *arg)
+  * @cmd == SCHEDOP_??? (scheduler operation).
+  * @arg == Operation-specific extra argument(s), as described below.
+  *
+- * **NOTE**:
+- * Versions of Xen prior to 3.0.2 provide only the following legacy version
++ * Versions of Xen prior to 3.0.2 provided only the following legacy version
+  * of this hypercall, supporting only the commands yield, block and shutdown:
+  *  long sched_op(int cmd, unsigned long arg)
+  * @cmd == SCHEDOP_??? (scheduler operation).
+  * @arg == 0               (SCHEDOP_yield and SCHEDOP_block)
+  *      == SHUTDOWN_* code (SCHEDOP_shutdown)
++ * This legacy version is available to new guests as sched_op_compat().
+  */
+ 
+ /*
+@@ -49,7 +67,8 @@
+ struct sched_shutdown {
+     unsigned int reason; /* SHUTDOWN_* */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(sched_shutdown);
++typedef struct sched_shutdown sched_shutdown_t;
++DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
+ 
+ /*
+  * Poll a set of event-channel ports. Return when one or more are pending. An
+@@ -58,11 +77,26 @@ DEFINE_GUEST_HANDLE_STRUCT(sched_shutdow
+  */
+ #define SCHEDOP_poll        3
+ struct sched_poll {
+-    GUEST_HANDLE(evtchn_port_t) ports;
++    XEN_GUEST_HANDLE(evtchn_port_t) ports;
+     unsigned int nr_ports;
+     uint64_t timeout;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(sched_poll);
++typedef struct sched_poll sched_poll_t;
++DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
++
++/*
++ * Declare a shutdown for another domain. The main use of this function is
++ * in interpreting shutdown requests and reasons for fully-virtualized
++ * domains.  A para-virtualized domain may use SCHEDOP_shutdown directly.
++ * @arg == pointer to sched_remote_shutdown structure.
++ */
++#define SCHEDOP_remote_shutdown        4
++struct sched_remote_shutdown {
++    domid_t domain_id;         /* Remote domain ID */
++    unsigned int reason;       /* SHUTDOWN_xxx reason */
++};
++typedef struct sched_remote_shutdown sched_remote_shutdown_t;
++DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
+ 
+ /*
+  * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
+--- head-2010-01-07.orig/include/xen/interface/vcpu.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/vcpu.h	2010-01-04 12:17:50.000000000 +0100
+@@ -27,11 +27,13 @@
+ #ifndef __XEN_PUBLIC_VCPU_H__
+ #define __XEN_PUBLIC_VCPU_H__
+ 
++#include "xen.h"
++
+ /*
+  * Prototype for this hypercall is:
+- *	int vcpu_op(int cmd, int vcpuid, void *extra_args)
+- * @cmd		   == VCPUOP_??? (VCPU operation).
+- * @vcpuid	   == VCPU to operate on.
++ *  int vcpu_op(int cmd, int vcpuid, void *extra_args)
++ * @cmd        == VCPUOP_??? (VCPU operation).
++ * @vcpuid     == VCPU to operate on.
+  * @extra_args == Operation-specific extra arguments (NULL if none).
+  */
+ 
+@@ -40,52 +42,53 @@
+  * newly-initialised VCPU will not run until it is brought up by VCPUOP_up.
+  *
+  * @extra_arg == pointer to vcpu_guest_context structure containing initial
+- *				 state for the VCPU.
++ *               state for the VCPU.
+  */
+-#define VCPUOP_initialise			 0
++#define VCPUOP_initialise            0
+ 
+ /*
+  * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
+  * if the VCPU has not been initialised (VCPUOP_initialise).
+  */
+-#define VCPUOP_up					 1
++#define VCPUOP_up                    1
+ 
+ /*
+  * Bring down a VCPU (i.e., make it non-runnable).
+  * There are a few caveats that callers should observe:
+- *	1. This operation may return, and VCPU_is_up may return false, before the
+- *	   VCPU stops running (i.e., the command is asynchronous). It is a good
+- *	   idea to ensure that the VCPU has entered a non-critical loop before
+- *	   bringing it down. Alternatively, this operation is guaranteed
+- *	   synchronous if invoked by the VCPU itself.
+- *	2. After a VCPU is initialised, there is currently no way to drop all its
+- *	   references to domain memory. Even a VCPU that is down still holds
+- *	   memory references via its pagetable base pointer and GDT. It is good
+- *	   practise to move a VCPU onto an 'idle' or default page table, LDT and
+- *	   GDT before bringing it down.
++ *  1. This operation may return, and VCPU_is_up may return false, before the
++ *     VCPU stops running (i.e., the command is asynchronous). It is a good
++ *     idea to ensure that the VCPU has entered a non-critical loop before
++ *     bringing it down. Alternatively, this operation is guaranteed
++ *     synchronous if invoked by the VCPU itself.
++ *  2. After a VCPU is initialised, there is currently no way to drop all its
++ *     references to domain memory. Even a VCPU that is down still holds
++ *     memory references via its pagetable base pointer and GDT. It is good
++ *     practise to move a VCPU onto an 'idle' or default page table, LDT and
++ *     GDT before bringing it down.
+  */
+-#define VCPUOP_down					 2
++#define VCPUOP_down                  2
+ 
+ /* Returns 1 if the given VCPU is up. */
+-#define VCPUOP_is_up				 3
++#define VCPUOP_is_up                 3
+ 
+ /*
+  * Return information about the state and running time of a VCPU.
+  * @extra_arg == pointer to vcpu_runstate_info structure.
+  */
+-#define VCPUOP_get_runstate_info	 4
++#define VCPUOP_get_runstate_info     4
+ struct vcpu_runstate_info {
+-		/* VCPU's current state (RUNSTATE_*). */
+-		int		 state;
+-		/* When was current state entered (system time, ns)? */
+-		uint64_t state_entry_time;
+-		/*
+-		 * Time spent in each RUNSTATE_* (ns). The sum of these times is
+-		 * guaranteed not to drift from system time.
+-		 */
+-		uint64_t time[4];
++    /* VCPU's current state (RUNSTATE_*). */
++    int      state;
++    /* When was current state entered (system time, ns)? */
++    uint64_t state_entry_time;
++    /*
++     * Time spent in each RUNSTATE_* (ns). The sum of these times is
++     * guaranteed not to drift from system time.
++     */
++    uint64_t time[4];
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
++typedef struct vcpu_runstate_info vcpu_runstate_info_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
+ 
+ /* VCPU is currently running on a physical CPU. */
+ #define RUNSTATE_running  0
+@@ -108,47 +111,52 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate
+  * Register a shared memory area from which the guest may obtain its own
+  * runstate information without needing to execute a hypercall.
+  * Notes:
+- *	1. The registered address may be virtual or physical, depending on the
+- *	   platform. The virtual address should be registered on x86 systems.
+- *	2. Only one shared area may be registered per VCPU. The shared area is
+- *	   updated by the hypervisor each time the VCPU is scheduled. Thus
+- *	   runstate.state will always be RUNSTATE_running and
+- *	   runstate.state_entry_time will indicate the system time at which the
+- *	   VCPU was last scheduled to run.
++ *  1. The registered address may be virtual or physical or guest handle,
++ *     depending on the platform. Virtual address or guest handle should be
++ *     registered on x86 systems.
++ *  2. Only one shared area may be registered per VCPU. The shared area is
++ *     updated by the hypervisor each time the VCPU is scheduled. Thus
++ *     runstate.state will always be RUNSTATE_running and
++ *     runstate.state_entry_time will indicate the system time at which the
++ *     VCPU was last scheduled to run.
+  * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
+  */
+ #define VCPUOP_register_runstate_memory_area 5
+ struct vcpu_register_runstate_memory_area {
+-		union {
+-				GUEST_HANDLE(vcpu_runstate_info) h;
+-				struct vcpu_runstate_info *v;
+-				uint64_t p;
+-		} addr;
++    union {
++        XEN_GUEST_HANDLE(vcpu_runstate_info_t) h;
++        struct vcpu_runstate_info *v;
++        uint64_t p;
++    } addr;
+ };
++typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+ 
+ /*
+  * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+  * which can be set via these commands. Periods smaller than one millisecond
+  * may not be supported.
+  */
+-#define VCPUOP_set_periodic_timer	 6 /* arg == vcpu_set_periodic_timer_t */
+-#define VCPUOP_stop_periodic_timer	 7 /* arg == NULL */
++#define VCPUOP_set_periodic_timer    6 /* arg == vcpu_set_periodic_timer_t */
++#define VCPUOP_stop_periodic_timer   7 /* arg == NULL */
+ struct vcpu_set_periodic_timer {
+-		uint64_t period_ns;
++    uint64_t period_ns;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
++typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+ 
+ /*
+  * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+  * timer which can be set via these commands.
+  */
+-#define VCPUOP_set_singleshot_timer	 8 /* arg == vcpu_set_singleshot_timer_t */
++#define VCPUOP_set_singleshot_timer  8 /* arg == vcpu_set_singleshot_timer_t */
+ #define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+ struct vcpu_set_singleshot_timer {
+-		uint64_t timeout_abs_ns;
+-		uint32_t flags;			   /* VCPU_SSHOTTMR_??? */
++    uint64_t timeout_abs_ns;   /* Absolute system time value in nanoseconds. */
++    uint32_t flags;            /* VCPU_SSHOTTMR_??? */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
++typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+ 
+ /* Flags to VCPUOP_set_singleshot_timer. */
+  /* Require the timeout to be in the future (return -ETIME if it's passed). */
+@@ -161,13 +169,65 @@ DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_sing
+  * structure in a convenient place, such as in a per-cpu data area.
+  * The pointer need not be page aligned, but the structure must not
+  * cross a page boundary.
++ *
++ * 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 */
+     uint32_t rsvd;   /* unused */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
++typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
++
++/* 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)))
++
++/*
++ * Register a memory location to get a secondary copy of the vcpu time
++ * parameters.  The master copy still exists as part of the vcpu shared
++ * memory area, and this secondary copy is updated whenever the master copy
++ * is updated (and using the same versioning scheme for synchronisation).
++ *
++ * The intent is that this copy may be mapped (RO) into userspace so
++ * that usermode can compute system time using the time info and the
++ * tsc.  Usermode will see an array of vcpu_time_info structures, one
++ * for each vcpu, and choose the right one by an existing mechanism
++ * which allows it to get the current vcpu number (such as via a
++ * segment limit).  It can then apply the normal algorithm to compute
++ * system time from the tsc.
++ *
++ * @extra_arg == pointer to vcpu_register_time_info_memory_area structure.
++ */
++#define VCPUOP_register_vcpu_time_memory_area   13
++DEFINE_XEN_GUEST_HANDLE(vcpu_time_info_t);
++struct vcpu_register_time_memory_area {
++    union {
++        XEN_GUEST_HANDLE(vcpu_time_info_t) h;
++        struct vcpu_time_info *v;
++        uint64_t p;
++    } addr;
++};
++typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
++DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
+ 
+ #endif /* __XEN_PUBLIC_VCPU_H__ */
+--- head-2010-01-07.orig/include/xen/interface/version.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/version.h	2009-12-04 10:44:50.000000000 +0100
+@@ -3,6 +3,24 @@
+  *
+  * Xen version, type, and compile information.
+  *
++ * 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) 2005, Nguyen Anh Quynh <aquynh@gmail.com>
+  * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+  */
+@@ -10,17 +28,15 @@
+ #ifndef __XEN_PUBLIC_VERSION_H__
+ #define __XEN_PUBLIC_VERSION_H__
+ 
+-/* NB. All ops return zero on success, except XENVER_version. */
++/* NB. All ops return zero on success, except XENVER_{version,pagesize} */
+ 
+ /* arg == NULL; returns major:minor (16:16). */
+ #define XENVER_version      0
+ 
+ /* arg == xen_extraversion_t. */
+ #define XENVER_extraversion 1
+-struct xen_extraversion {
+-    char extraversion[16];
+-};
+-#define XEN_EXTRAVERSION_LEN (sizeof(struct xen_extraversion))
++typedef char xen_extraversion_t[16];
++#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
+ 
+ /* arg == xen_compile_info_t. */
+ #define XENVER_compile_info 2
+@@ -30,29 +46,28 @@ struct xen_compile_info {
+     char compile_domain[32];
+     char compile_date[32];
+ };
++typedef struct xen_compile_info xen_compile_info_t;
+ 
+ #define XENVER_capabilities 3
+-struct xen_capabilities_info {
+-    char info[1024];
+-};
+-#define XEN_CAPABILITIES_INFO_LEN (sizeof(struct xen_capabilities_info))
++typedef char xen_capabilities_info_t[1024];
++#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
+ 
+ #define XENVER_changeset 4
+-struct xen_changeset_info {
+-    char info[64];
+-};
+-#define XEN_CHANGESET_INFO_LEN (sizeof(struct xen_changeset_info))
++typedef char xen_changeset_info_t[64];
++#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
+ 
+ #define XENVER_platform_parameters 5
+ struct xen_platform_parameters {
+     unsigned long virt_start;
+ };
++typedef struct xen_platform_parameters xen_platform_parameters_t;
+ 
+ #define XENVER_get_features 6
+ struct xen_feature_info {
+     unsigned int submap_idx;    /* IN: which 32-bit submap to return */
+     uint32_t     submap;        /* OUT: 32-bit submap */
+ };
++typedef struct xen_feature_info xen_feature_info_t;
+ 
+ /* Declares the features reported by XENVER_get_features. */
+ #include "features.h"
+@@ -60,4 +75,10 @@ struct xen_feature_info {
+ /* arg == NULL; returns host memory page size. */
+ #define XENVER_pagesize 7
+ 
++/* arg == xen_domain_handle_t. */
++#define XENVER_guest_handle 8
++
++#define XENVER_commandline 9
++typedef char xen_commandline_t[1024];
++
+ #endif /* __XEN_PUBLIC_VERSION_H__ */
+--- head-2010-01-07.orig/include/xen/interface/xen.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/interface/xen.h	2010-01-04 12:13:58.000000000 +0100
+@@ -3,35 +3,69 @@
+  *
+  * Guest OS interface to 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, K A Fraser
+  */
+ 
+ #ifndef __XEN_PUBLIC_XEN_H__
+ #define __XEN_PUBLIC_XEN_H__
+ 
+-#include <asm/xen/interface.h>
++#include "xen-compat.h"
++#ifdef CONFIG_PARAVIRT_XEN
+ #include <asm/pvclock-abi.h>
++#endif
+ 
+-/*
+- * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS).
+- */
++#if defined(__i386__) || defined(__x86_64__)
++#include "arch-x86/xen.h"
++#elif defined(__ia64__)
++#include "arch-ia64.h"
++#else
++#error "Unsupported architecture"
++#endif
++
++#ifndef __ASSEMBLY__
++/* Guest handles for primitive C types. */
++DEFINE_XEN_GUEST_HANDLE(char);
++__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
++DEFINE_XEN_GUEST_HANDLE(int);
++__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
++DEFINE_XEN_GUEST_HANDLE(long);
++__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
++DEFINE_XEN_GUEST_HANDLE(void);
++
++DEFINE_XEN_GUEST_HANDLE(uint64_t);
++DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
++#endif
+ 
+ /*
+- * x86_32: EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5.
+- *         EAX = return value
+- *         (argument registers may be clobbered on return)
+- * x86_64: RAX = vector; RDI, RSI, RDX, R10, R8, R9 = args 1, 2, 3, 4, 5, 6.
+- *         RAX = return value
+- *         (argument registers not clobbered on return; RCX, R11 are)
++ * HYPERCALLS
+  */
++
+ #define __HYPERVISOR_set_trap_table        0
+ #define __HYPERVISOR_mmu_update            1
+ #define __HYPERVISOR_set_gdt               2
+ #define __HYPERVISOR_stack_switch          3
+ #define __HYPERVISOR_set_callbacks         4
+ #define __HYPERVISOR_fpu_taskswitch        5
+-#define __HYPERVISOR_sched_op              6
+-#define __HYPERVISOR_dom0_op               7
++#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
++#define __HYPERVISOR_platform_op           7
+ #define __HYPERVISOR_set_debugreg          8
+ #define __HYPERVISOR_get_debugreg          9
+ #define __HYPERVISOR_update_descriptor    10
+@@ -39,10 +73,10 @@
+ #define __HYPERVISOR_multicall            13
+ #define __HYPERVISOR_update_va_mapping    14
+ #define __HYPERVISOR_set_timer_op         15
+-#define __HYPERVISOR_event_channel_op_compat 16
++#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+ #define __HYPERVISOR_xen_version          17
+ #define __HYPERVISOR_console_io           18
+-#define __HYPERVISOR_physdev_op_compat    19
++#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
+ #define __HYPERVISOR_grant_table_op       20
+ #define __HYPERVISOR_vm_assist            21
+ #define __HYPERVISOR_update_va_mapping_otherdomain 22
+@@ -50,7 +84,7 @@
+ #define __HYPERVISOR_vcpu_op              24
+ #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
+ #define __HYPERVISOR_mmuext_op            26
+-#define __HYPERVISOR_acm_op               27
++#define __HYPERVISOR_xsm_op               27
+ #define __HYPERVISOR_nmi_op               28
+ #define __HYPERVISOR_sched_op_new         29
+ #define __HYPERVISOR_callback_op          30
+@@ -58,6 +92,10 @@
+ #define __HYPERVISOR_event_channel_op     32
+ #define __HYPERVISOR_physdev_op           33
+ #define __HYPERVISOR_hvm_op               34
++#define __HYPERVISOR_sysctl               35
++#define __HYPERVISOR_domctl               36
++#define __HYPERVISOR_kexec_op             37
++#define __HYPERVISOR_tmem_op              38
+ 
+ /* Architecture-specific hypercall definitions. */
+ #define __HYPERVISOR_arch_0               48
+@@ -70,15 +108,50 @@
+ #define __HYPERVISOR_arch_7               55
+ 
+ /*
++ * HYPERCALL COMPATIBILITY.
++ */
++
++/* New sched_op hypercall introduced in 0x00030101. */
++#if __XEN_INTERFACE_VERSION__ < 0x00030101
++#undef __HYPERVISOR_sched_op
++#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
++#else
++#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_new
++#endif
++
++/* New event-channel and physdev hypercalls introduced in 0x00030202. */
++#if __XEN_INTERFACE_VERSION__ < 0x00030202
++#undef __HYPERVISOR_event_channel_op
++#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
++#undef __HYPERVISOR_physdev_op
++#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
++#endif
++
++/* New platform_op hypercall introduced in 0x00030204. */
++#if __XEN_INTERFACE_VERSION__ < 0x00030204
++#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
++#endif
++
++/*
+  * VIRTUAL INTERRUPTS
+  *
+  * Virtual interrupts that a guest OS may receive from Xen.
+- */
+-#define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
+-#define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
+-#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
+-#define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
+-#define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
++ *
++ * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
++ * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
++ * The latter can be allocated only once per guest: they must initially be
++ * allocated to VCPU0 but can subsequently be re-bound.
++ */
++#define VIRQ_TIMER      0  /* V. Timebase update, and/or requested timeout.  */
++#define VIRQ_DEBUG      1  /* V. Request guest to dump debug info.           */
++#define VIRQ_CONSOLE    2  /* G. (DOM0) Bytes received on emergency console. */
++#define VIRQ_DOM_EXC    3  /* G. (DOM0) Exceptional event for some domain.   */
++#define VIRQ_TBUF       4  /* G. (DOM0) Trace buffer has records available.  */
++#define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
++#define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
++#define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
++#define VIRQ_PCPU_STATE 9  /* G. (DOM0) PCPU state changed                   */
++#define VIRQ_MEM_EVENT  10 /* G. (DOM0) A memory event has occured           */
+ 
+ /* Architecture-specific VIRQ definitions. */
+ #define VIRQ_ARCH_0    16
+@@ -91,19 +164,28 @@
+ #define VIRQ_ARCH_7    23
+ 
+ #define NR_VIRQS       24
++
+ /*
+- * MMU-UPDATE REQUESTS
++ * HYPERVISOR_mmu_update(reqs, count, pdone, foreigndom)
+  *
+- * HYPERVISOR_mmu_update() accepts a list of (ptr, val) pairs.
+- * A foreigndom (FD) can be specified (or DOMID_SELF for none).
+- * Where the FD has some effect, it is described below.
+- * ptr[1:0] specifies the appropriate MMU_* command.
++ * @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
++ * @count is the length of the above array.
++ * @pdone is an output parameter indicating number of completed operations
++ * @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
++ *                    hypercall invocation. Can be DOMID_SELF.
++ * @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
++ *                     in this hypercall invocation. The value of this field
++ *                     (x) encodes the PFD as follows:
++ *                     x == 0 => PFD == DOMID_SELF
++ *                     x != 0 => PFD == x - 1
+  *
++ * Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
++ * -------------
+  * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
+- * Updates an entry in a page table. If updating an L1 table, and the new
+- * table entry is valid/present, the mapped frame must belong to the FD, if
+- * an FD has been specified. If attempting to map an I/O page then the
+- * caller assumes the privilege of the FD.
++ * Updates an entry in a page table belonging to PFD. If updating an L1 table,
++ * and the new table entry is valid/present, the mapped frame must belong to
++ * FD. If attempting to map an I/O page then the caller assumes the privilege
++ * of the FD.
+  * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
+  * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
+  * ptr[:2]  -- Machine address of the page-table entry to modify.
+@@ -119,8 +201,8 @@
+  * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
+  * with those in @val.
+  */
+-#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.       */
+-#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for  */
++#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.      */
++#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for */
+ #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+ 
+ /*
+@@ -166,6 +248,13 @@
+  * cmd: MMUEXT_SET_LDT
+  * linear_addr: Linear address of LDT base (NB. must be page-aligned).
+  * nr_ents: Number of entries in LDT.
++ *
++ * cmd: MMUEXT_CLEAR_PAGE
++ * mfn: Machine frame number to be cleared.
++ *
++ * cmd: MMUEXT_COPY_PAGE
++ * mfn: Machine frame number of the destination page.
++ * src_mfn: Machine frame number of the source page.
+  */
+ #define MMUEXT_PIN_L1_TABLE      0
+ #define MMUEXT_PIN_L2_TABLE      1
+@@ -182,24 +271,34 @@
+ #define MMUEXT_FLUSH_CACHE      12
+ #define MMUEXT_SET_LDT          13
+ #define MMUEXT_NEW_USER_BASEPTR 15
++#define MMUEXT_CLEAR_PAGE       16
++#define MMUEXT_COPY_PAGE        17
+ 
+ #ifndef __ASSEMBLY__
+ struct mmuext_op {
+-	unsigned int cmd;
+-	union {
+-		/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */
+-		unsigned long mfn;
+-		/* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
+-		unsigned long linear_addr;
+-	} arg1;
+-	union {
+-		/* SET_LDT */
+-		unsigned int nr_ents;
+-		/* TLB_FLUSH_MULTI, INVLPG_MULTI */
+-		void *vcpumask;
+-	} arg2;
++    unsigned int cmd;
++    union {
++        /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
++         * CLEAR_PAGE, COPY_PAGE */
++        xen_pfn_t     mfn;
++        /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
++        unsigned long linear_addr;
++    } arg1;
++    union {
++        /* SET_LDT */
++        unsigned int nr_ents;
++        /* TLB_FLUSH_MULTI, INVLPG_MULTI */
++#if __XEN_INTERFACE_VERSION__ >= 0x00030205
++        XEN_GUEST_HANDLE(const_void) vcpumask;
++#else
++        const void *vcpumask;
++#endif
++        /* COPY_PAGE */
++        xen_pfn_t src_mfn;
++    } arg2;
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(mmuext_op);
++typedef struct mmuext_op mmuext_op_t;
++DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
+ #endif
+ 
+ /* These are passed as 'flags' to update_va_mapping. They can be ORed. */
+@@ -224,11 +323,24 @@ DEFINE_GUEST_HANDLE_STRUCT(mmuext_op);
+  */
+ #define VMASST_CMD_enable                0
+ #define VMASST_CMD_disable               1
++
++/* x86/32 guests: simulate full 4GB segment limits. */
+ #define VMASST_TYPE_4gb_segments         0
++
++/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
+ #define VMASST_TYPE_4gb_segments_notify  1
++
++/*
++ * x86 guests: support writes to bottom-level PTEs.
++ * NB1. Page-directory entries cannot be written.
++ * NB2. Guest must continue to remove all writable mappings of PTEs.
++ */
+ #define VMASST_TYPE_writable_pagetables  2
++
++/* x86/PAE guests: support PDPTs above 4GB. */
+ #define VMASST_TYPE_pae_extended_cr3     3
+-#define MAX_VMASST_TYPE 3
++
++#define MAX_VMASST_TYPE                  3
+ 
+ #ifndef __ASSEMBLY__
+ 
+@@ -260,6 +372,13 @@ typedef uint16_t domid_t;
+ #define DOMID_XEN  (0x7FF2U)
+ 
+ /*
++ * DOMID_COW is used as the owner of sharable pages */
++#define DOMID_COW  (0x7FF3U)
++
++/* DOMID_INVALID is used to identity invalid domid */
++#define DOMID_INVALID (0x7FFFU)
++
++/*
+  * Send an array of these to HYPERVISOR_mmu_update().
+  * NB. The fields are natural pointer/address size for this architecture.
+  */
+@@ -267,18 +386,19 @@ struct mmu_update {
+     uint64_t ptr;       /* Machine address of PTE. */
+     uint64_t val;       /* New contents of PTE.    */
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(mmu_update);
++typedef struct mmu_update mmu_update_t;
++DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
+ 
+ /*
+  * Send an array of these to HYPERVISOR_multicall().
+  * NB. The fields are natural register size for this architecture.
+  */
+ struct multicall_entry {
+-    unsigned long op;
+-    long result;
++    unsigned long op, result;
+     unsigned long args[6];
+ };
+-DEFINE_GUEST_HANDLE_STRUCT(multicall_entry);
++typedef struct multicall_entry multicall_entry_t;
++DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
+ 
+ /*
+  * Event channel endpoints per domain:
+@@ -287,173 +407,271 @@ DEFINE_GUEST_HANDLE_STRUCT(multicall_ent
+ #define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
+ 
+ struct vcpu_time_info {
+-	/*
+-	 * Updates to the following values are preceded and followed
+-	 * by an increment of 'version'. The guest can therefore
+-	 * detect updates by looking for changes to 'version'. If the
+-	 * least-significant bit of the version number is set then an
+-	 * update is in progress and the guest must wait to read a
+-	 * consistent set of values.  The correct way to interact with
+-	 * the version number is similar to Linux's seqlock: see the
+-	 * implementations of read_seqbegin/read_seqretry.
+-	 */
+-	uint32_t version;
+-	uint32_t pad0;
+-	uint64_t tsc_timestamp;   /* TSC at last update of time vals.  */
+-	uint64_t system_time;     /* Time, in nanosecs, since boot.    */
+-	/*
+-	 * Current system time:
+-	 *   system_time + ((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul
+-	 * CPU frequency (Hz):
+-	 *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
+-	 */
+-	uint32_t tsc_to_system_mul;
+-	int8_t   tsc_shift;
+-	int8_t   pad1[3];
++    /*
++     * Updates to the following values are preceded and followed by an
++     * increment of 'version'. The guest can therefore detect updates by
++     * looking for changes to 'version'. If the least-significant bit of
++     * the version number is set then an update is in progress and the guest
++     * must wait to read a consistent set of values.
++     * The correct way to interact with the version number is similar to
++     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
++     */
++    uint32_t version;
++    uint32_t pad0;
++    uint64_t tsc_timestamp;   /* TSC at last update of time vals.  */
++    uint64_t system_time;     /* Time, in nanosecs, since boot.    */
++    /*
++     * Current system time:
++     *   system_time +
++     *   ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
++     * CPU frequency (Hz):
++     *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
++     */
++    uint32_t tsc_to_system_mul;
++    int8_t   tsc_shift;
++    int8_t   pad1[3];
+ }; /* 32 bytes */
++typedef struct vcpu_time_info vcpu_time_info_t;
+ 
+ struct vcpu_info {
+-	/*
+-	 * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
+-	 * a pending notification for a particular VCPU. It is then cleared
+-	 * by the guest OS /before/ checking for pending work, thus avoiding
+-	 * a set-and-check race. Note that the mask is only accessed by Xen
+-	 * on the CPU that is currently hosting the VCPU. This means that the
+-	 * pending and mask flags can be updated by the guest without special
+-	 * synchronisation (i.e., no need for the x86 LOCK prefix).
+-	 * This may seem suboptimal because if the pending flag is set by
+-	 * a different CPU then an IPI may be scheduled even when the mask
+-	 * is set. However, note:
+-	 *  1. The task of 'interrupt holdoff' is covered by the per-event-
+-	 *     channel mask bits. A 'noisy' event that is continually being
+-	 *     triggered can be masked at source at this very precise
+-	 *     granularity.
+-	 *  2. The main purpose of the per-VCPU mask is therefore to restrict
+-	 *     reentrant execution: whether for concurrency control, or to
+-	 *     prevent unbounded stack usage. Whatever the purpose, we expect
+-	 *     that the mask will be asserted only for short periods at a time,
+-	 *     and so the likelihood of a 'spurious' IPI is suitably small.
+-	 * The mask is read before making an event upcall to the guest: a
+-	 * non-zero mask therefore guarantees that the VCPU will not receive
+-	 * an upcall activation. The mask is cleared when the VCPU requests
+-	 * to block: this avoids wakeup-waiting races.
+-	 */
+-	uint8_t evtchn_upcall_pending;
+-	uint8_t evtchn_upcall_mask;
+-	unsigned long evtchn_pending_sel;
+-	struct arch_vcpu_info arch;
+-	struct pvclock_vcpu_time_info time;
++    /*
++     * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
++     * a pending notification for a particular VCPU. It is then cleared
++     * by the guest OS /before/ checking for pending work, thus avoiding
++     * a set-and-check race. Note that the mask is only accessed by Xen
++     * on the CPU that is currently hosting the VCPU. This means that the
++     * pending and mask flags can be updated by the guest without special
++     * synchronisation (i.e., no need for the x86 LOCK prefix).
++     * This may seem suboptimal because if the pending flag is set by
++     * a different CPU then an IPI may be scheduled even when the mask
++     * is set. However, note:
++     *  1. The task of 'interrupt holdoff' is covered by the per-event-
++     *     channel mask bits. A 'noisy' event that is continually being
++     *     triggered can be masked at source at this very precise
++     *     granularity.
++     *  2. The main purpose of the per-VCPU mask is therefore to restrict
++     *     reentrant execution: whether for concurrency control, or to
++     *     prevent unbounded stack usage. Whatever the purpose, we expect
++     *     that the mask will be asserted only for short periods at a time,
++     *     and so the likelihood of a 'spurious' IPI is suitably small.
++     * The mask is read before making an event upcall to the guest: a
++     * non-zero mask therefore guarantees that the VCPU will not receive
++     * an upcall activation. The mask is cleared when the VCPU requests
++     * to block: this avoids wakeup-waiting races.
++     */
++    uint8_t evtchn_upcall_pending;
++    uint8_t evtchn_upcall_mask;
++    unsigned long evtchn_pending_sel;
++    struct arch_vcpu_info arch;
++#ifdef CONFIG_PARAVIRT_XEN
++    struct pvclock_vcpu_time_info time;
++#else
++    struct vcpu_time_info time;
++#endif
+ }; /* 64 bytes (x86) */
++#ifndef __XEN__
++typedef struct vcpu_info vcpu_info_t;
++#endif
+ 
+ /*
+  * Xen/kernel shared data -- pointer provided in start_info.
+- * NB. We expect that this struct is smaller than a page.
++ *
++ * This structure is defined to be both smaller than a page, and the
++ * only data on the shared page, but may vary in actual size even within
++ * compatible Xen versions; guests should not rely on the size
++ * of this structure remaining constant.
+  */
+ struct shared_info {
+-	struct vcpu_info vcpu_info[MAX_VIRT_CPUS];
++    struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
+ 
+-	/*
+-	 * A domain can create "event channels" on which it can send and receive
+-	 * asynchronous event notifications. There are three classes of event that
+-	 * are delivered by this mechanism:
+-	 *  1. Bi-directional inter- and intra-domain connections. Domains must
+-	 *     arrange out-of-band to set up a connection (usually by allocating
+-	 *     an unbound 'listener' port and avertising that via a storage service
+-	 *     such as xenstore).
+-	 *  2. Physical interrupts. A domain with suitable hardware-access
+-	 *     privileges can bind an event-channel port to a physical interrupt
+-	 *     source.
+-	 *  3. Virtual interrupts ('events'). A domain can bind an event-channel
+-	 *     port to a virtual interrupt source, such as the virtual-timer
+-	 *     device or the emergency console.
+-	 *
+-	 * Event channels are addressed by a "port index". Each channel is
+-	 * associated with two bits of information:
+-	 *  1. PENDING -- notifies the domain that there is a pending notification
+-	 *     to be processed. This bit is cleared by the guest.
+-	 *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
+-	 *     will cause an asynchronous upcall to be scheduled. This bit is only
+-	 *     updated by the guest. It is read-only within Xen. If a channel
+-	 *     becomes pending while the channel is masked then the 'edge' is lost
+-	 *     (i.e., when the channel is unmasked, the guest must manually handle
+-	 *     pending notifications as no upcall will be scheduled by Xen).
+-	 *
+-	 * To expedite scanning of pending notifications, any 0->1 pending
+-	 * transition on an unmasked channel causes a corresponding bit in a
+-	 * per-vcpu selector word to be set. Each bit in the selector covers a
+-	 * 'C long' in the PENDING bitfield array.
+-	 */
+-	unsigned long evtchn_pending[sizeof(unsigned long) * 8];
+-	unsigned long evtchn_mask[sizeof(unsigned long) * 8];
+-
+-	/*
+-	 * Wallclock time: updated only by control software. Guests should base
+-	 * their gettimeofday() syscall on this wallclock-base value.
+-	 */
+-	struct pvclock_wall_clock wc;
++    /*
++     * A domain can create "event channels" on which it can send and receive
++     * asynchronous event notifications. There are three classes of event that
++     * are delivered by this mechanism:
++     *  1. Bi-directional inter- and intra-domain connections. Domains must
++     *     arrange out-of-band to set up a connection (usually by allocating
++     *     an unbound 'listener' port and avertising that via a storage service
++     *     such as xenstore).
++     *  2. Physical interrupts. A domain with suitable hardware-access
++     *     privileges can bind an event-channel port to a physical interrupt
++     *     source.
++     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
++     *     port to a virtual interrupt source, such as the virtual-timer
++     *     device or the emergency console.
++     *
++     * Event channels are addressed by a "port index". Each channel is
++     * associated with two bits of information:
++     *  1. PENDING -- notifies the domain that there is a pending notification
++     *     to be processed. This bit is cleared by the guest.
++     *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
++     *     will cause an asynchronous upcall to be scheduled. This bit is only
++     *     updated by the guest. It is read-only within Xen. If a channel
++     *     becomes pending while the channel is masked then the 'edge' is lost
++     *     (i.e., when the channel is unmasked, the guest must manually handle
++     *     pending notifications as no upcall will be scheduled by Xen).
++     *
++     * To expedite scanning of pending notifications, any 0->1 pending
++     * transition on an unmasked channel causes a corresponding bit in a
++     * per-vcpu selector word to be set. Each bit in the selector covers a
++     * 'C long' in the PENDING bitfield array.
++     */
++    unsigned long evtchn_pending[sizeof(unsigned long) * 8];
++    unsigned long evtchn_mask[sizeof(unsigned long) * 8];
++
++    /*
++     * Wallclock time: updated only by control software. Guests should base
++     * their gettimeofday() syscall on this wallclock-base value.
++     */
++#ifdef CONFIG_PARAVIRT_XEN
++    struct pvclock_wall_clock wc;
++#else
++    uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */
++    uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
++    uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
++#endif
+ 
+-	struct arch_shared_info arch;
++    struct arch_shared_info arch;
+ 
+ };
++#ifndef __XEN__
++typedef struct shared_info shared_info_t;
++#endif
+ 
+ /*
+- * Start-of-day memory layout for the initial domain (DOM0):
++ * Start-of-day memory layout:
+  *  1. The domain is started within contiguous virtual-memory region.
+- *  2. The contiguous region begins and ends on an aligned 4MB boundary.
+- *  3. The region start corresponds to the load address of the OS image.
+- *     If the load address is not 4MB aligned then the address is rounded down.
+- *  4. This the order of bootstrap elements in the initial virtual region:
++ *  2. The contiguous region ends on an aligned 4MB boundary.
++ *  3. This the order of bootstrap elements in the initial virtual region:
+  *      a. relocated kernel image
+  *      b. initial ram disk              [mod_start, mod_len]
+  *      c. list of allocated page frames [mfn_list, nr_pages]
++ *         (unless relocated due to XEN_ELFNOTE_INIT_P2M)
+  *      d. start_info_t structure        [register ESI (x86)]
+  *      e. bootstrap page tables         [pt_base, CR3 (x86)]
+  *      f. bootstrap stack               [register ESP (x86)]
+- *  5. Bootstrap elements are packed together, but each is 4kB-aligned.
+- *  6. The initial ram disk may be omitted.
+- *  7. The list of page frames forms a contiguous 'pseudo-physical' memory
++ *  4. Bootstrap elements are packed together, but each is 4kB-aligned.
++ *  5. The initial ram disk may be omitted.
++ *  6. The list of page frames forms a contiguous 'pseudo-physical' memory
+  *     layout for the domain. In particular, the bootstrap virtual-memory
+  *     region is a 1:1 mapping to the first section of the pseudo-physical map.
+- *  8. All bootstrap elements are mapped read-writable for the guest OS. The
++ *  7. All bootstrap elements are mapped read-writable for the guest OS. The
+  *     only exception is the bootstrap page table, which is mapped read-only.
+- *  9. There is guaranteed to be at least 512kB padding after the final
++ *  8. There is guaranteed to be at least 512kB padding after the final
+  *     bootstrap element. If necessary, the bootstrap virtual region is
+  *     extended by an extra 4MB to ensure this.
+  */
+ 
+ #define MAX_GUEST_CMDLINE 1024
+ struct start_info {
+-	/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
+-	char magic[32];             /* "xen-<version>-<platform>".            */
+-	unsigned long nr_pages;     /* Total pages allocated to this domain.  */
+-	unsigned long shared_info;  /* MACHINE address of shared info struct. */
+-	uint32_t flags;             /* SIF_xxx flags.                         */
+-	unsigned long store_mfn;    /* MACHINE page number of shared page.    */
+-	uint32_t store_evtchn;      /* Event channel for store communication. */
+-	union {
+-		struct {
+-			unsigned long mfn;  /* MACHINE page number of console page.   */
+-			uint32_t  evtchn;   /* Event channel for console page.        */
+-		} domU;
+-		struct {
+-			uint32_t info_off;  /* Offset of console_info struct.         */
+-			uint32_t info_size; /* Size of console_info struct from start.*/
+-		} dom0;
+-	} console;
+-	/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
+-	unsigned long pt_base;      /* VIRTUAL address of page directory.     */
+-	unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
+-	unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
+-	unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
+-	unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
+-	int8_t cmd_line[MAX_GUEST_CMDLINE];
++    /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
++    char magic[32];             /* "xen-<version>-<platform>".            */
++    unsigned long nr_pages;     /* Total pages allocated to this domain.  */
++    unsigned long shared_info;  /* MACHINE address of shared info struct. */
++    uint32_t flags;             /* SIF_xxx flags.                         */
++    xen_pfn_t store_mfn;        /* MACHINE page number of shared page.    */
++    uint32_t store_evtchn;      /* Event channel for store communication. */
++    union {
++        struct {
++            xen_pfn_t mfn;      /* MACHINE page number of console page.   */
++            uint32_t  evtchn;   /* Event channel for console page.        */
++        } domU;
++        struct {
++            uint32_t info_off;  /* Offset of console_info struct.         */
++            uint32_t info_size; /* Size of console_info struct from start.*/
++        } dom0;
++    } console;
++    /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
++    unsigned long pt_base;      /* VIRTUAL address of page directory.     */
++    unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
++    unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
++    unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
++    unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
++    int8_t cmd_line[MAX_GUEST_CMDLINE];
++    /* The pfn range here covers both page table and p->m table frames.   */
++    unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table.    */
++    unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table.  */
+ };
++typedef struct start_info start_info_t;
++
++/* New console union for dom0 introduced in 0x00030203. */
++#if __XEN_INTERFACE_VERSION__ < 0x00030203
++#define console_mfn    console.domU.mfn
++#define console_evtchn console.domU.evtchn
++#endif
+ 
+ /* 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_MULTIBOOT_MOD (1<<2)  /* Is mod_start a multiboot module? */
++#define SIF_PM_MASK       (0xFF<<8) /* reserve 1 byte for xen-pm options */
+ 
+-typedef uint64_t cpumap_t;
++/*
++ * A multiboot module is a package containing modules very similar to a
++ * multiboot module array. The only differences are:
++ * - the array of module descriptors is by convention simply at the beginning
++ *   of the multiboot module,
++ * - addresses in the module descriptors are based on the beginning of the
++ *   multiboot module,
++ * - the number of modules is determined by a termination descriptor that has
++ *   mod_start == 0.
++ *
++ * This permits to both build it statically and reference it in a configuration
++ * file, and let the PV guest easily rebase the addresses to virtual addresses
++ * and at the same time count the number of modules.
++ */
++struct xen_multiboot_mod_list
++{
++    /* Address of first byte of the module */
++    uint32_t mod_start;
++    /* Address of last byte of the module (inclusive) */
++    uint32_t mod_end;
++    /* Address of zero-terminated command line */
++    uint32_t cmdline;
++    /* Unused, must be zero */
++    uint32_t pad;
++};
++
++typedef struct dom0_vga_console_info {
++    uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
++#define XEN_VGATYPE_TEXT_MODE_3 0x03
++#define XEN_VGATYPE_VESA_LFB    0x23
++
++    union {
++        struct {
++            /* Font height, in pixels. */
++            uint16_t font_height;
++            /* Cursor location (column, row). */
++            uint16_t cursor_x, cursor_y;
++            /* Number of rows and columns (dimensions in characters). */
++            uint16_t rows, columns;
++        } text_mode_3;
++
++        struct {
++            /* Width and height, in pixels. */
++            uint16_t width, height;
++            /* Bytes per scan line. */
++            uint16_t bytes_per_line;
++            /* Bits per pixel. */
++            uint16_t bits_per_pixel;
++            /* LFB physical address, and size (in units of 64kB). */
++            uint32_t lfb_base;
++            uint32_t lfb_size;
++            /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
++            uint8_t  red_pos, red_size;
++            uint8_t  green_pos, green_size;
++            uint8_t  blue_pos, blue_size;
++            uint8_t  rsvd_pos, rsvd_size;
++#if __XEN_INTERFACE_VERSION__ >= 0x00030206
++            /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
++            uint32_t gbl_caps;
++            /* Mode attributes (offset 0x0, VESA command 0x4f01). */
++            uint16_t mode_attrs;
++#endif
++        } vesa_lfb;
++    } u;
++} dom0_vga_console_info_t;
++#define xen_vga_console_info dom0_vga_console_info
++#define xen_vga_console_info_t dom0_vga_console_info_t
+ 
+ typedef uint8_t xen_domain_handle_t[16];
+ 
+@@ -461,6 +679,11 @@ typedef uint8_t xen_domain_handle_t[16];
+ #define __mk_unsigned_long(x) x ## UL
+ #define mk_unsigned_long(x) __mk_unsigned_long(x)
+ 
++__DEFINE_XEN_GUEST_HANDLE(uint8,  uint8_t);
++__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
++__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
++__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
++
+ #else /* __ASSEMBLY__ */
+ 
+ /* In assembly code we cannot use C numeric constant suffixes. */
+@@ -468,4 +691,14 @@ typedef uint8_t xen_domain_handle_t[16];
+ 
+ #endif /* !__ASSEMBLY__ */
+ 
++/* Default definitions for macros used by domctl/sysctl. */
++#if defined(__XEN__) || defined(__XEN_TOOLS__)
++#ifndef uint64_aligned_t
++#define uint64_aligned_t uint64_t
++#endif
++#ifndef XEN_GUEST_HANDLE_64
++#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
++#endif
++#endif
++
+ #endif /* __XEN_PUBLIC_XEN_H__ */
+--- head-2010-01-07.orig/include/xen/xenbus.h	2010-01-07 09:35:20.000000000 +0100
++++ head-2010-01-07/include/xen/xenbus.h	2009-12-04 10:44:50.000000000 +0100
+@@ -39,6 +39,7 @@
+ #include <linux/mutex.h>
+ #include <linux/completion.h>
+ #include <linux/init.h>
++#include <linux/err.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/grant_table.h>
+ #include <xen/interface/io/xenbus.h>
+@@ -55,8 +56,17 @@ struct xenbus_watch
+ 	/* Callback (executed in a process context with no locks held). */
+ 	void (*callback)(struct xenbus_watch *,
+ 			 const char **vec, unsigned int len);
++
++	/* See XBWF_ definitions below. */
++	unsigned long flags;
+ };
+ 
++/*
++ * Execute callback in its own kthread. Useful if the callback is long
++ * running or heavily serialised, to avoid taking out the main xenwatch thread
++ * for a long period of time (or even unwittingly causing a deadlock).
++ */
++#define XBWF_new_thread	1
+ 
+ /* A xenbus device. */
+ struct xenbus_device {
+@@ -91,7 +101,8 @@ struct xenbus_driver {
+ 	void (*otherend_changed)(struct xenbus_device *dev,
+ 				 enum xenbus_state backend_state);
+ 	int (*remove)(struct xenbus_device *dev);
+-	int (*suspend)(struct xenbus_device *dev, pm_message_t state);
++	int (*suspend)(struct xenbus_device *dev);
++	int (*suspend_cancel)(struct xenbus_device *dev);
+ 	int (*resume)(struct xenbus_device *dev);
+ 	int (*uevent)(struct xenbus_device *, char **, int, char *, int);
+ 	struct device_driver driver;
+@@ -104,27 +115,8 @@ static inline struct xenbus_driver *to_x
+ 	return container_of(drv, struct xenbus_driver, driver);
+ }
+ 
+-int __must_check __xenbus_register_frontend(struct xenbus_driver *drv,
+-					    struct module *owner,
+-					    const char *mod_name);
+-
+-static inline int __must_check
+-xenbus_register_frontend(struct xenbus_driver *drv)
+-{
+-	WARN_ON(drv->owner != THIS_MODULE);
+-	return __xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME);
+-}
+-
+-int __must_check __xenbus_register_backend(struct xenbus_driver *drv,
+-					   struct module *owner,
+-					   const char *mod_name);
+-static inline int __must_check
+-xenbus_register_backend(struct xenbus_driver *drv)
+-{
+-	WARN_ON(drv->owner != THIS_MODULE);
+-	return __xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME);
+-}
+-
++int xenbus_register_frontend(struct xenbus_driver *drv);
++int xenbus_register_backend(struct xenbus_driver *drv);
+ void xenbus_unregister_driver(struct xenbus_driver *drv);
+ 
+ struct xenbus_transaction
+@@ -164,7 +156,6 @@ int xenbus_printf(struct xenbus_transact
+ int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
+ 
+ /* notifer routines for when the xenstore comes up */
+-extern int xenstored_ready;
+ int register_xenstore_notifier(struct notifier_block *nb);
+ void unregister_xenstore_notifier(struct notifier_block *nb);
+ 
+@@ -177,12 +168,9 @@ void xs_suspend_cancel(void);
+ /* Used by xenbus_dev to borrow kernel's store connection. */
+ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
+ 
+-struct work_struct;
+-
+ /* Prepare for domain suspend: then resume or cancel the suspend. */
+ void xenbus_suspend(void);
+ void xenbus_resume(void);
+-void xenbus_probe(struct work_struct *);
+ void xenbus_suspend_cancel(void);
+ 
+ #define XENBUS_IS_ERR_READ(str) ({			\
+@@ -195,38 +183,125 @@ void xenbus_suspend_cancel(void);
+ 
+ #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
+ 
++
++/**
++ * Register a watch on the given path, using the given xenbus_watch structure
++ * for storage, and the given callback function as the callback.  Return 0 on
++ * success, or -errno on error.  On success, the given path will be saved as
++ * watch->node, and remains the caller's to free.  On error, watch->node will
++ * be NULL, the device will switch to XenbusStateClosing, and the error will
++ * be saved in the store.
++ */
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+ 		      struct xenbus_watch *watch,
+ 		      void (*callback)(struct xenbus_watch *,
+ 				       const char **, unsigned int));
+-int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
+-			 void (*callback)(struct xenbus_watch *,
+-					  const char **, unsigned int),
+-			 const char *pathfmt, ...)
+-	__attribute__ ((format (printf, 4, 5)));
+ 
++
++/**
++ * Register a watch on the given path/path2, using the given xenbus_watch
++ * structure for storage, and the given callback function as the callback.
++ * Return 0 on success, or -errno on error.  On success, the watched path
++ * (path/path2) will be saved as watch->node, and becomes the caller's to
++ * kfree().  On error, watch->node will be NULL, so the caller has nothing to
++ * free, the device will switch to XenbusStateClosing, and the error will be
++ * saved in the store.
++ */
++int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
++		       const char *path2, struct xenbus_watch *watch,
++		       void (*callback)(struct xenbus_watch *,
++					const char **, unsigned int));
++
++
++/**
++ * Advertise in the store a change of the given driver to the given new_state.
++ * Return 0 on success, or -errno on error.  On error, the device will switch
++ * to XenbusStateClosing, and the error will be saved in the store.
++ */
+ int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state new_state);
++
++
++/**
++ * Grant access to the given ring_mfn to the peer of the given device.  Return
++ * 0 on success, or -errno on error.  On error, the device will switch to
++ * XenbusStateClosing, and the error will be saved in the store.
++ */
+ int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn);
+-int xenbus_map_ring_valloc(struct xenbus_device *dev,
+-			   int gnt_ref, void **vaddr);
++
++
++/**
++ * Map a page of memory into this domain from another domain's grant table.
++ * xenbus_map_ring_valloc allocates a page of virtual address space, maps the
++ * page to that address, and sets *vaddr to that address.
++ * xenbus_map_ring does not allocate the virtual address space (you must do
++ * this yourself!). It only maps in the page to the specified address.
++ * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
++ * or -ENOMEM on error. If an error is returned, device will switch to
++ * XenbusStateClosing and the error message will be saved in XenStore.
++ */
++struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev,
++					 int gnt_ref);
+ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
+ 			   grant_handle_t *handle, void *vaddr);
+ 
+-int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
++
++/**
++ * Unmap a page of memory in this domain that was imported from another domain.
++ * Use xenbus_unmap_ring_vfree if you mapped in your memory with
++ * xenbus_map_ring_valloc (it will free the virtual address space).
++ * Returns 0 on success and returns GNTST_* on error
++ * (see xen/include/interface/grant_table.h).
++ */
++int xenbus_unmap_ring_vfree(struct xenbus_device *dev, struct vm_struct *);
+ int xenbus_unmap_ring(struct xenbus_device *dev,
+ 		      grant_handle_t handle, void *vaddr);
+ 
++
++/**
++ * Allocate an event channel for the given xenbus_device, assigning the newly
++ * created local port to *port.  Return 0 on success, or -errno on error.  On
++ * error, the device will switch to XenbusStateClosing, and the error will be
++ * saved in the store.
++ */
+ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
+-int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port);
++
++
++/**
++ * Free an existing event channel. Returns 0 on success or -errno on error.
++ */
+ int xenbus_free_evtchn(struct xenbus_device *dev, int port);
+ 
++
++/**
++ * Return the state of the driver rooted at the given store path, or
++ * XenbusStateUnknown if no state can be read.
++ */
+ enum xenbus_state xenbus_read_driver_state(const char *path);
+ 
+-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
+-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...);
++
++/***
++ * Report the given negative errno into the store, along with the given
++ * formatted message.
++ */
++void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
++		      ...);
++
++
++/***
++ * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
++ * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
++ * closedown of this driver and its peer.
++ */
++void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
++		      ...);
++
++int xenbus_dev_init(void);
+ 
+ const char *xenbus_strstate(enum xenbus_state state);
+ int xenbus_dev_is_online(struct xenbus_device *dev);
+ int xenbus_frontend_closed(struct xenbus_device *dev);
+ 
++int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *));
++int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *));
++
+ #endif /* _XEN_XENBUS_H */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-balloon-max-target
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-balloon-max-target
@@ -0,0 +1,78 @@
+From: ccoffing@novell.com
+Subject: Expose min/max limits of domain ballooning
+Patch-mainline: obsolete
+References: 152667, 184727
+
+jb: Also added this to the sysfs representation.
+
+--- head-2009-10-12.orig/drivers/xen/balloon/balloon.c	2009-10-14 16:16:37.000000000 +0200
++++ head-2009-10-12/drivers/xen/balloon/balloon.c	2009-10-14 16:19:48.000000000 +0200
+@@ -227,7 +227,7 @@ static unsigned long current_target(void
+ 	return target;
+ }
+ 
+-static unsigned long minimum_target(void)
++unsigned long balloon_minimum_target(void)
+ {
+ #ifndef CONFIG_XEN
+ #define max_pfn num_physpages
+@@ -449,7 +449,7 @@ static void balloon_process(struct work_
+ void balloon_set_new_target(unsigned long target)
+ {
+ 	/* No need for lock. Not read-modify-write updates. */
+-	bs.target_pages = max(target, minimum_target());
++	bs.target_pages = max(target, balloon_minimum_target());
+ 	schedule_work(&balloon_worker);
+ }
+ 
+@@ -524,10 +524,13 @@ static int balloon_read(char *page, char
+ 		page,
+ 		"Current allocation: %8lu kB\n"
+ 		"Requested target:   %8lu kB\n"
++		"Minimum target:     %8lu kB\n"
++		"Maximum target:     %8lu kB\n"
+ 		"Low-mem balloon:    %8lu kB\n"
+ 		"High-mem balloon:   %8lu kB\n"
+ 		"Driver pages:       %8lu kB\n",
+ 		PAGES2KB(bs.current_pages), PAGES2KB(bs.target_pages), 
++		PAGES2KB(balloon_minimum_target()), PAGES2KB(num_physpages),
+ 		PAGES2KB(bs.balloon_low), PAGES2KB(bs.balloon_high),
+ 		PAGES2KB(bs.driver_pages));
+ 
+--- head-2009-10-12.orig/drivers/xen/balloon/common.h	2009-06-09 15:01:37.000000000 +0200
++++ head-2009-10-12/drivers/xen/balloon/common.h	2009-08-19 10:36:49.000000000 +0200
+@@ -52,5 +52,6 @@ int balloon_sysfs_init(void);
+ void balloon_sysfs_exit(void);
+ 
+ void balloon_set_new_target(unsigned long target);
++unsigned long balloon_minimum_target(void);
+ 
+ #endif /* __XEN_BALLOON_COMMON_H__ */
+--- head-2009-10-12.orig/drivers/xen/balloon/sysfs.c	2009-10-12 16:30:07.000000000 +0200
++++ head-2009-10-12/drivers/xen/balloon/sysfs.c	2009-08-19 10:36:47.000000000 +0200
+@@ -31,6 +31,7 @@
+ #include <linux/capability.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
++#include <linux/mm.h>
+ #include <linux/stat.h>
+ #include <linux/string.h>
+ #include <linux/sysdev.h>
+@@ -53,6 +54,8 @@
+ 	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+ 
+ BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages));
++BALLOON_SHOW(min_kb, "%lu\n", PAGES2KB(balloon_minimum_target()));
++BALLOON_SHOW(max_kb, "%lu\n", PAGES2KB(num_physpages));
+ BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low));
+ BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high));
+ BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages));
+@@ -123,6 +126,8 @@ static struct sysdev_attribute *balloon_
+ 
+ static struct attribute *balloon_info_attrs[] = {
+ 	&attr_current_kb.attr,
++	&attr_min_kb.attr,
++	&attr_max_kb.attr,
+ 	&attr_low_kb.attr,
+ 	&attr_high_kb.attr,
+ 	&attr_driver_kb.attr,
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.21-22
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.21-22
@@ -0,0 +1,106 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.22
+Patch-mainline: 2.6.32.22
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.21-22" by xen-port-patches.py
+
+--- sle11sp1-2010-09-22.orig/arch/x86/ia32/ia32entry-xen.S	2010-01-20 10:28:42.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/ia32/ia32entry-xen.S	2010-09-22 11:35:36.000000000 +0200
+@@ -47,7 +47,12 @@ ia32_common:
+ 	/*
+ 	 * Reload arg registers from stack in case ptrace changed them.
+ 	 * We don't reload %eax because syscall_trace_enter() returned
+-	 * the value it wants us to use in the table lookup.
++	 * the %rax value we should see.  Instead, we just truncate that
++	 * value to 32 bits again as we did on entry from user mode.
++	 * If it's a new value set by user_regset during entry tracing,
++	 * this matches the normal truncation of the user-mode value.
++	 * If it's -1 to make us punt the syscall, then (u32)-1 is still
++	 * an appropriately invalid value.
+ 	 */
+ 	.macro LOAD_ARGS32 offset, _r9=0
+ 	.if \_r9
+@@ -57,6 +62,7 @@ ia32_common:
+ 	movl \offset+48(%rsp),%edx
+ 	movl \offset+56(%rsp),%esi
+ 	movl \offset+64(%rsp),%edi
++	movl %eax,%eax			/* zero extension */
+ 	.endm
+ 
+ 	.macro CFI_STARTPROC32 simple
+@@ -139,7 +145,7 @@ ENTRY(ia32_sysenter_target)
+ 	orl    $TS_COMPAT,TI_status(%r10)
+ 	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz  sysenter_tracesys
+-	cmpl	$(IA32_NR_syscalls-1),%eax
++	cmpq	$(IA32_NR_syscalls-1),%rax
+ 	ja	ia32_badsys
+ 	jmp	ia32_do_call
+ 
+@@ -153,7 +159,7 @@ ENTRY(ia32_sysenter_target)
+ 	movl $AUDIT_ARCH_I386,%edi	/* 1st arg: audit arch */
+ 	call audit_syscall_entry
+ 	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall number */
+-	cmpl $(IA32_NR_syscalls-1),%eax
++	cmpq $(IA32_NR_syscalls-1),%rax
+ 	ja ia32_badsys
+ 	movl %ebx,%edi			/* reload 1st syscall arg */
+ 	movl RCX-ARGOFFSET(%rsp),%esi	/* reload 2nd syscall arg */
+@@ -180,7 +186,7 @@ sysenter_tracesys:
+ 	call	syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+-	cmpl	$(IA32_NR_syscalls-1),%eax
++	cmpq	$(IA32_NR_syscalls-1),%rax
+ 	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+ 	jmp	ia32_do_call
+ 	CFI_ENDPROC
+@@ -234,7 +240,7 @@ ENTRY(ia32_cstar_target)
+ 	orl   $TS_COMPAT,TI_status(%r10)
+ 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz   cstar_tracesys
+-	cmpl $IA32_NR_syscalls-1,%eax
++	cmpq $IA32_NR_syscalls-1,%rax
+ 	ja  ia32_badsys
+ cstar_do_call:
+ 	IA32_ARG_FIXUP 1
+@@ -261,7 +267,7 @@ cstar_tracesys:
+ 	LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl %ebp,%r9d
+-	cmpl $(IA32_NR_syscalls-1),%eax
++	cmpq $(IA32_NR_syscalls-1),%rax
+ 	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+ 	jmp cstar_do_call
+ END(ia32_cstar_target)
+@@ -318,7 +324,7 @@ ENTRY(ia32_syscall)
+ 	orl   $TS_COMPAT,TI_status(%r10)
+ 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz ia32_tracesys
+-	cmpl $(IA32_NR_syscalls-1),%eax
++	cmpq $(IA32_NR_syscalls-1),%rax
+ 	ja ia32_badsys
+ ia32_do_call:
+ 	IA32_ARG_FIXUP
+@@ -337,7 +343,7 @@ ia32_tracesys:			 
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+-	cmpl $(IA32_NR_syscalls-1),%eax
++	cmpq $(IA32_NR_syscalls-1),%rax
+ 	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+ 	jmp ia32_do_call
+ END(ia32_syscall)
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-09-22 11:35:28.000000000 +0200
++++ sle11sp1-2010-09-22/arch/x86/kernel/apic/io_apic-xen.c	2010-09-22 11:35:36.000000000 +0200
+@@ -3451,7 +3451,7 @@ static int set_msi_irq_affinity(unsigned
+ 
+ 	cfg = desc->chip_data;
+ 
+-	read_msi_msg_desc(desc, &msg);
++	get_cached_msi_msg_desc(desc, &msg);
+ 
+ 	msg.data &= ~MSI_DATA_VECTOR_MASK;
+ 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-common.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-common.diff
@@ -0,0 +1,4158 @@
+Subject: xen3 common
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+List of files that don't require modification anymore (and hence
+removed from this patch), for reference and in case upstream wants to
+take the forward porting patches:
+2.6.22/include/linux/sched.h
+2.6.22/kernel/softlockup.c
+2.6.22/kernel/timer.c
+2.6.25/mm/highmem.c
+2.6.30/include/linux/pci_regs.h
+
+--- sle11sp1-2010-01-20.orig/drivers/Makefile	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/Makefile	2009-12-04 10:44:41.000000000 +0100
+@@ -33,6 +33,7 @@ obj-$(CONFIG_PARPORT)		+= parport/
+ obj-y				+= base/ block/ misc/ mfd/
+ obj-$(CONFIG_NUBUS)		+= nubus/
+ obj-y				+= macintosh/
++obj-$(CONFIG_XEN)		+= xen/
+ obj-$(CONFIG_SCSI)		+= scsi/
+ obj-$(CONFIG_ATA)		+= ata/
+ obj-$(CONFIG_MTD)		+= mtd/
+--- sle11sp1-2010-01-20.orig/drivers/acpi/Makefile	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/Makefile	2009-12-04 10:44:41.000000000 +0100
+@@ -62,5 +62,8 @@ obj-$(CONFIG_ACPI_POWER_METER)	+= power_
+ processor-y			:= processor_core.o processor_throttling.o
+ processor-y			+= processor_idle.o processor_thermal.o
+ processor-$(CONFIG_CPU_FREQ)	+= processor_perflib.o
++ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
++processor-objs	+= processor_perflib.o processor_extcntl.o
++endif
+ 
+ obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
+--- sle11sp1-2010-01-20.orig/drivers/acpi/acpica/hwsleep.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/acpica/hwsleep.c	2009-12-04 10:44:41.000000000 +0100
+@@ -236,7 +236,11 @@ acpi_status asmlinkage acpi_enter_sleep_
+ 	u32 pm1b_control;
+ 	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
+ 	struct acpi_object_list arg_list;
+ 	union acpi_object arg;
+ 	acpi_status status;
+@@ -347,6 +351,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+ 
+ 	/* Write #2: Write both SLP_TYP + SLP_EN */
+ 
++#if !(defined(CONFIG_XEN) && defined(CONFIG_X86))
+ 	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
+ 	if (ACPI_FAILURE(status)) {
+ 		return_ACPI_STATUS(status);
+@@ -386,6 +391,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);
+ }
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_core.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_core.c	2009-12-07 10:38:01.000000000 +0100
+@@ -660,7 +660,8 @@ static int acpi_processor_get_info(struc
+ 	 */
+ 	if (pr->id == -1) {
+ 		if (ACPI_FAILURE
+-		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
++		    (acpi_processor_hotadd_init(pr->handle, &pr->id)) &&
++		    !processor_cntl_external()) {
+ 			return -ENODEV;
+ 		}
+ 	}
+@@ -711,7 +712,11 @@ static int acpi_processor_get_info(struc
+ 	return 0;
+ }
+ 
++#ifndef CONFIG_XEN
+ static DEFINE_PER_CPU(void *, processor_device_array);
++#else
++static void *processor_device_array[NR_ACPI_CPUS];
++#endif
+ 
+ static void acpi_processor_notify(struct acpi_device *device, u32 event)
+ {
+@@ -792,29 +797,45 @@ static int __cpuinit acpi_processor_add(
+ 	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
+ 	device->driver_data = pr;
+ 
++ 	processor_extcntl_init();
++
+ 	result = acpi_processor_get_info(device);
+-	if (result) {
++	if (result ||
++	    ((pr->id == -1) && !processor_cntl_external())) {
+ 		/* Processor is physically not present */
+ 		return 0;
+ 	}
+ 
+-	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
++	BUG_ON(!processor_cntl_external() &&
++	       ((pr->id >= nr_cpu_ids) || (pr->id < 0)));
+ 
+ 	/*
+ 	 * Buggy BIOS check
+ 	 * ACPI id of processors can be reported wrongly by the BIOS.
+ 	 * Don't trust it blindly
+ 	 */
++#ifndef CONFIG_XEN
+ 	if (per_cpu(processor_device_array, pr->id) != NULL &&
+ 	    per_cpu(processor_device_array, pr->id) != device) {
++#else
++	BUG_ON(pr->acpi_id >= NR_ACPI_CPUS);
++	if (processor_device_array[pr->acpi_id] != NULL &&
++	    processor_device_array[pr->acpi_id] != device) {
++#endif
+ 		printk(KERN_WARNING "BIOS reported wrong ACPI id "
+ 			"for the processor\n");
+ 		result = -ENODEV;
+ 		goto err_free_cpumask;
+ 	}
++#ifndef CONFIG_XEN
+ 	per_cpu(processor_device_array, pr->id) = device;
+ 
+ 	per_cpu(processors, pr->id) = pr;
++#else
++	processor_device_array[pr->acpi_id] = device;
++	if (pr->id != -1)
++		per_cpu(processors, pr->id) = pr;
++#endif
+ 
+ 	result = acpi_processor_add_fs(device);
+ 	if (result)
+@@ -831,15 +852,27 @@ static int __cpuinit acpi_processor_add(
+ 	acpi_processor_set_pdc(pr);
+ 	arch_acpi_processor_cleanup_pdc(pr);
+ 
+-#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);
+-	acpi_processor_get_limit_info(pr);
+ 
++	/*
++	 * pr->id may equal to -1 while processor_cntl_external enabled.
++	 * throttle and thermal module don't support this case.
++	 * Tx only works when dom0 vcpu == pcpu num by far, as we give
++	 * control to dom0.
++	 */
++	if (pr->id != -1) {
++		acpi_processor_get_throttling_info(pr);
++		acpi_processor_get_limit_info(pr);
++	}
+ 
+ 	acpi_processor_power_init(pr, device);
+ 
++	result = processor_extcntl_prepare(pr);
++	if (result)
++		goto end;
++
+ 	pr->cdev = thermal_cooling_device_register("Processor", device,
+ 						&processor_cooling_ops);
+ 	if (IS_ERR(pr->cdev)) {
+@@ -891,7 +924,7 @@ static int acpi_processor_remove(struct 
+ 
+ 	pr = acpi_driver_data(device);
+ 
+-	if (pr->id >= nr_cpu_ids)
++	if (!processor_cntl_external() && pr->id >= nr_cpu_ids)
+ 		goto free;
+ 
+ 	if (type == ACPI_BUS_REMOVAL_EJECT) {
+@@ -912,8 +945,14 @@ static int acpi_processor_remove(struct 
+ 		pr->cdev = NULL;
+ 	}
+ 
++#ifndef CONFIG_XEN
+ 	per_cpu(processors, pr->id) = NULL;
+ 	per_cpu(processor_device_array, pr->id) = NULL;
++#else
++	if (pr->id != -1)
++		per_cpu(processors, pr->id) = NULL;
++	processor_device_array[pr->acpi_id] = NULL;
++#endif
+ 
+ free:
+ 	free_cpumask_var(pr->throttling.shared_cpu_map);
+@@ -969,6 +1008,10 @@ int acpi_processor_device_add(acpi_handl
+ 		return -ENODEV;
+ 	}
+ 
++	if (processor_cntl_external() && acpi_driver_data(*device))
++		processor_notify_external(acpi_driver_data(*device),
++			PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
++
+ 	return 0;
+ }
+ 
+@@ -998,6 +1041,10 @@ static void __ref acpi_processor_hotplug
+ 					    "Unable to add the device\n");
+ 			break;
+ 		}
++		pr = acpi_driver_data(device);
++		if (processor_cntl_external() && pr)
++			processor_notify_external(pr,
++					PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
+ 		break;
+ 	case ACPI_NOTIFY_EJECT_REQUEST:
+ 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+@@ -1014,6 +1061,9 @@ static void __ref acpi_processor_hotplug
+ 				    "Driver data is NULL, dropping EJECT\n");
+ 			return;
+ 		}
++		if (processor_cntl_external())
++			processor_notify_external(pr, PROCESSOR_HOTPLUG,
++						HOTPLUG_TYPE_REMOVE);
+ 		break;
+ 	default:
+ 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+@@ -1078,6 +1128,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
++
+ 	if (cpu_online(pr->id))
+ 		cpu_down(pr->id);
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ sle11sp1-2010-01-20/drivers/acpi/processor_extcntl.c	2009-12-04 10:44:41.000000000 +0100
+@@ -0,0 +1,241 @@
++/*
++ * 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.
++	 */
++	pdomain = &pr->performance->domain_info;
++	pdomain->num_processors = 0;
++	ret = acpi_processor_get_psd(pr);
++	if (ret < 0) {
++		/*
++		 * _PSD is optional - assume no coordination if absent (or
++		 * broken), matching native kernels' behavior.
++		 */
++		pdomain->num_entries = ACPI_PSD_REV0_ENTRIES;
++		pdomain->revision = ACPI_PSD_REV0_REVISION;
++		pdomain->domain = pr->acpi_id;
++		pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL;
++		pdomain->num_processors = 1;
++	}
++
++	/* Some sanity check */
++	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;
++}
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_idle.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_idle.c	2009-12-04 10:44:41.000000000 +0100
+@@ -419,7 +419,8 @@ static int acpi_processor_get_power_info
+ 				 */
+ 				cx.entry_method = ACPI_CSTATE_HALT;
+ 				snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
+-			} else {
++			/* This doesn't apply to external control case */
++			} else if (!processor_pm_external()) {
+ 				continue;
+ 			}
+ 			if (cx.type == ACPI_STATE_C1 &&
+@@ -458,6 +459,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));
+ 
+@@ -1223,6 +1230,11 @@ int __cpuinit acpi_processor_power_init(
+ 	if (!entry)
+ 		return -EIO;
+ #endif
++
++	if (processor_pm_external())
++		processor_notify_external(pr,
++			PROCESSOR_PM_INIT, PM_TYPE_IDLE);
++
+ 	return 0;
+ }
+ 
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_perflib.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_perflib.c	2009-12-04 10:44:41.000000000 +0100
+@@ -78,6 +78,7 @@ MODULE_PARM_DESC(ignore_ppc, "If the fre
+ 
+ static int acpi_processor_ppc_status;
+ 
++#ifdef CONFIG_CPU_FREQ
+ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
+ 				       unsigned long event, void *data)
+ {
+@@ -120,6 +121,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)
+ {
+@@ -164,9 +166,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
+@@ -185,6 +193,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)
+ {
+@@ -332,7 +341,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;
+@@ -373,6 +385,7 @@ static int acpi_processor_get_performanc
+ 	return result;
+ }
+ 
++#ifdef CONFIG_CPU_FREQ
+ int acpi_processor_notify_smm(struct module *calling_module)
+ {
+ 	acpi_status status;
+@@ -433,8 +446,12 @@ int acpi_processor_notify_smm(struct mod
+ }
+ 
+ EXPORT_SYMBOL(acpi_processor_notify_smm);
++#endif	/* CONFIG_CPU_FREQ */
+ 
+-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;
+--- sle11sp1-2010-01-20.orig/drivers/acpi/sleep.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/sleep.c	2009-12-04 10:44:41.000000000 +0100
+@@ -60,6 +60,7 @@ static struct notifier_block tts_notifie
+ static int acpi_sleep_prepare(u32 acpi_state)
+ {
+ #ifdef CONFIG_ACPI_SLEEP
++#ifndef CONFIG_ACPI_PV_SLEEP
+ 	/* do we have a wakeup address for S2 and S3? */
+ 	if (acpi_state == ACPI_STATE_S3) {
+ 		if (!acpi_wakeup_address) {
+@@ -69,6 +70,7 @@ static int acpi_sleep_prepare(u32 acpi_s
+ 				(acpi_physical_address)acpi_wakeup_address);
+ 
+ 	}
++#endif
+ 	ACPI_FLUSH_CPU_CACHE();
+ 	acpi_enable_wakeup_device_prep(acpi_state);
+ #endif
+@@ -244,7 +246,14 @@ static int acpi_suspend_enter(suspend_st
+ 		break;
+ 
+ 	case ACPI_STATE_S3:
++#ifdef CONFIG_ACPI_PV_SLEEP
++		/* Hyperviosr will save and restore CPU context
++		 * and then we can skip low level housekeeping here.
++		 */
++		acpi_enter_sleep_state(acpi_state);
++#else
+ 		do_suspend_lowlevel();
++#endif
+ 		break;
+ 	}
+ 
+--- sle11sp1-2010-01-20.orig/drivers/char/agp/intel-agp.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/agp/intel-agp.c	2010-01-20 10:22:01.000000000 +0100
+@@ -400,6 +400,13 @@ static struct page *i8xx_alloc_pages(voi
+ 	if (page == NULL)
+ 		return NULL;
+ 
++#ifdef CONFIG_XEN
++	if (xen_create_contiguous_region((unsigned long)page_address(page), 2, 32)) {
++		__free_pages(page, 2);
++		return NULL;
++	}
++#endif
++
+ 	if (set_pages_uc(page, 4) < 0) {
+ 		set_pages_wb(page, 4);
+ 		__free_pages(page, 2);
+@@ -416,6 +423,9 @@ static void i8xx_destroy_pages(struct pa
+ 		return;
+ 
+ 	set_pages_wb(page, 4);
++#ifdef CONFIG_XEN
++	xen_destroy_contiguous_region((unsigned long)page_address(page), 2);
++#endif
+ 	put_page(page);
+ 	__free_pages(page, 2);
+ 	atomic_dec(&agp_bridge->current_memory_agp);
+--- sle11sp1-2010-01-20.orig/drivers/char/mem.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/mem.c	2009-12-16 11:48:20.000000000 +0100
+@@ -110,6 +110,7 @@ void __attribute__((weak)) unxlate_dev_m
+ {
+ }
+ 
++#ifndef ARCH_HAS_DEV_MEM
+ /*
+  * This funcion reads the *physical* memory. The f_pos points directly to the 
+  * memory location. 
+@@ -254,6 +255,7 @@ static ssize_t write_mem(struct file * f
+ 	*ppos += written;
+ 	return written;
+ }
++#endif
+ 
+ int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
+ 	unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
+@@ -345,6 +347,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;
+@@ -359,6 +364,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);
+ }
+@@ -877,6 +889,7 @@ static int open_port(struct inode * inod
+ #define open_kmem	open_mem
+ #define open_oldmem	open_mem
+ 
++#ifndef ARCH_HAS_DEV_MEM
+ static const struct file_operations mem_fops = {
+ 	.llseek		= memory_lseek,
+ 	.read		= read_mem,
+@@ -885,6 +898,9 @@ static const struct file_operations mem_
+ 	.open		= open_mem,
+ 	.get_unmapped_area = get_unmapped_area_mem,
+ };
++#else
++extern const struct file_operations mem_fops;
++#endif
+ 
+ #ifdef CONFIG_DEVKMEM
+ static const struct file_operations kmem_fops = {
+--- sle11sp1-2010-01-20.orig/drivers/char/tpm/Makefile	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/tpm/Makefile	2009-12-04 10:44:41.000000000 +0100
+@@ -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
+--- sle11sp1-2010-01-20.orig/drivers/char/tpm/tpm.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/char/tpm/tpm.h	2009-12-04 10:44:41.000000000 +0100
+@@ -108,6 +108,9 @@ struct tpm_chip {
+ 	struct dentry **bios_dir;
+ 
+ 	struct list_head list;
++#ifdef CONFIG_XEN
++	void *priv;
++#endif
+ 	void (*release) (struct device *);
+ };
+ 
+@@ -266,6 +269,18 @@ struct tpm_cmd_t {
+ 
+ ssize_t	tpm_getcap(struct device *, __be32, cap_t *, const char *);
+ 
++#ifdef CONFIG_XEN
++static inline void *chip_get_private(const struct tpm_chip *chip)
++{
++	return chip->priv;
++}
++
++static inline void chip_set_private(struct tpm_chip *chip, void *priv)
++{
++	chip->priv = priv;
++}
++#endif
++
+ extern void tpm_get_timeouts(struct tpm_chip *);
+ extern void tpm_gen_interrupt(struct tpm_chip *);
+ extern void tpm_continue_selftest(struct tpm_chip *);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ sle11sp1-2010-01-20/drivers/char/tpm/tpm_vtpm.c	2009-12-04 10:44:41.000000000 +0100
+@@ -0,0 +1,542 @@
++/*
++ * Copyright (C) 2006 IBM Corporation
++ *
++ * Authors:
++ * Stefan Berger <stefanb@us.ibm.com>
++ *
++ * Generic device driver part for device drivers in a virtualized
++ * environment.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation, version 2 of the
++ * License.
++ *
++ */
++
++#include <asm/uaccess.h>
++#include <linux/list.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include "tpm.h"
++#include "tpm_vtpm.h"
++
++/* read status bits */
++enum {
++	STATUS_BUSY = 0x01,
++	STATUS_DATA_AVAIL = 0x02,
++	STATUS_READY = 0x04
++};
++
++struct transmission {
++	struct list_head next;
++
++	unsigned char *request;
++	size_t  request_len;
++	size_t  request_buflen;
++
++	unsigned char *response;
++	size_t  response_len;
++	size_t  response_buflen;
++
++	unsigned int flags;
++};
++
++enum {
++	TRANSMISSION_FLAG_WAS_QUEUED = 0x1
++};
++
++
++enum {
++	DATAEX_FLAG_QUEUED_ONLY = 0x1
++};
++
++
++/* local variables */
++
++/* local function prototypes */
++static int _vtpm_send_queued(struct tpm_chip *chip);
++
++
++/* =============================================================
++ * Some utility functions
++ * =============================================================
++ */
++static void vtpm_state_init(struct vtpm_state *vtpms)
++{
++	vtpms->current_request = NULL;
++	spin_lock_init(&vtpms->req_list_lock);
++	init_waitqueue_head(&vtpms->req_wait_queue);
++	INIT_LIST_HEAD(&vtpms->queued_requests);
++
++	vtpms->current_response = NULL;
++	spin_lock_init(&vtpms->resp_list_lock);
++	init_waitqueue_head(&vtpms->resp_wait_queue);
++
++	vtpms->disconnect_time = jiffies;
++}
++
++
++static inline struct transmission *transmission_alloc(void)
++{
++	return kzalloc(sizeof(struct transmission), GFP_ATOMIC);
++}
++
++static unsigned char *
++transmission_set_req_buffer(struct transmission *t,
++                            unsigned char *buffer, size_t len)
++{
++	if (t->request_buflen < len) {
++		kfree(t->request);
++		t->request = kmalloc(len, GFP_KERNEL);
++		if (!t->request) {
++			t->request_buflen = 0;
++			return NULL;
++		}
++		t->request_buflen = len;
++	}
++
++	memcpy(t->request, buffer, len);
++	t->request_len = len;
++
++	return t->request;
++}
++
++static unsigned char *
++transmission_set_res_buffer(struct transmission *t,
++                            const unsigned char *buffer, size_t len)
++{
++	if (t->response_buflen < len) {
++		kfree(t->response);
++		t->response = kmalloc(len, GFP_ATOMIC);
++		if (!t->response) {
++			t->response_buflen = 0;
++			return NULL;
++		}
++		t->response_buflen = len;
++	}
++
++	memcpy(t->response, buffer, len);
++	t->response_len = len;
++
++	return t->response;
++}
++
++static inline void transmission_free(struct transmission *t)
++{
++	kfree(t->request);
++	kfree(t->response);
++	kfree(t);
++}
++
++/* =============================================================
++ * Interface with the lower layer driver
++ * =============================================================
++ */
++/*
++ * Lower layer uses this function to make a response available.
++ */
++int vtpm_vd_recv(const struct tpm_chip *chip,
++                 const unsigned char *buffer, size_t count,
++                 void *ptr)
++{
++	unsigned long flags;
++	int ret_size = 0;
++	struct transmission *t;
++	struct vtpm_state *vtpms;
++
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	/*
++	 * The list with requests must contain one request
++	 * only and the element there must be the one that
++	 * was passed to me from the front-end.
++	 */
++	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
++	if (vtpms->current_request != ptr) {
++		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++		return 0;
++	}
++
++	if ((t = vtpms->current_request)) {
++		transmission_free(t);
++		vtpms->current_request = NULL;
++	}
++
++	t = transmission_alloc();
++	if (t) {
++		if (!transmission_set_res_buffer(t, buffer, count)) {
++			transmission_free(t);
++			spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++			return -ENOMEM;
++		}
++		ret_size = count;
++		vtpms->current_response = t;
++		wake_up_interruptible(&vtpms->resp_wait_queue);
++	}
++	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++
++	return ret_size;
++}
++
++
++/*
++ * Lower layer indicates its status (connected/disconnected)
++ */
++void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status)
++{
++	struct vtpm_state *vtpms;
++
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	vtpms->vd_status = vd_status;
++	if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
++		vtpms->disconnect_time = jiffies;
++	}
++}
++
++/* =============================================================
++ * Interface with the generic TPM driver
++ * =============================================================
++ */
++static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++	int rc = 0;
++	unsigned long flags;
++	struct vtpm_state *vtpms;
++
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	/*
++	 * Check if the previous operation only queued the command
++	 * In this case there won't be a response, so I just
++	 * return from here and reset that flag. In any other
++	 * case I should receive a response from the back-end.
++	 */
++	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
++	if ((vtpms->flags & DATAEX_FLAG_QUEUED_ONLY) != 0) {
++		vtpms->flags &= ~DATAEX_FLAG_QUEUED_ONLY;
++		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++		/*
++		 * The first few commands (measurements) must be
++		 * queued since it might not be possible to talk to the
++		 * TPM, yet.
++		 * Return a response of up to 30 '0's.
++		 */
++
++		count = min_t(size_t, count, 30);
++		memset(buf, 0x0, count);
++		return count;
++	}
++	/*
++	 * Check whether something is in the responselist and if
++	 * there's nothing in the list wait for something to appear.
++	 */
++
++	if (!vtpms->current_response) {
++		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++		interruptible_sleep_on_timeout(&vtpms->resp_wait_queue,
++		                               1000);
++		spin_lock_irqsave(&vtpms->resp_list_lock ,flags);
++	}
++
++	if (vtpms->current_response) {
++		struct transmission *t = vtpms->current_response;
++		vtpms->current_response = NULL;
++		rc = min(count, t->response_len);
++		memcpy(buf, t->response, rc);
++		transmission_free(t);
++	}
++
++	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++	return rc;
++}
++
++static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++	int rc = 0;
++	unsigned long flags;
++	struct transmission *t = transmission_alloc();
++	struct vtpm_state *vtpms;
++
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	if (!t)
++		return -ENOMEM;
++	/*
++	 * If there's a current request, it must be the
++	 * previous request that has timed out.
++	 */
++	spin_lock_irqsave(&vtpms->req_list_lock, flags);
++	if (vtpms->current_request != NULL) {
++		printk("WARNING: Sending although there is a request outstanding.\n"
++		       "         Previous request must have timed out.\n");
++		transmission_free(vtpms->current_request);
++		vtpms->current_request = NULL;
++	}
++	spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
++
++	/*
++	 * Queue the packet if the driver below is not
++	 * ready, yet, or there is any packet already
++	 * in the queue.
++	 * If the driver below is ready, unqueue all
++	 * packets first before sending our current
++	 * packet.
++	 * For each unqueued packet, except for the
++	 * last (=current) packet, call the function
++	 * tpm_xen_recv to wait for the response to come
++	 * back.
++	 */
++	if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
++		if (time_after(jiffies,
++		               vtpms->disconnect_time + HZ * 10)) {
++			rc = -ENOENT;
++		} else {
++			goto queue_it;
++		}
++	} else {
++		/*
++		 * Send all queued packets.
++		 */
++		if (_vtpm_send_queued(chip) == 0) {
++
++			vtpms->current_request = t;
++
++			rc = vtpm_vd_send(vtpms->tpm_private,
++			                  buf,
++			                  count,
++			                  t);
++			/*
++			 * The generic TPM driver will call
++			 * the function to receive the response.
++			 */
++			if (rc < 0) {
++				vtpms->current_request = NULL;
++				goto queue_it;
++			}
++		} else {
++queue_it:
++			if (!transmission_set_req_buffer(t, buf, count)) {
++				transmission_free(t);
++				rc = -ENOMEM;
++				goto exit;
++			}
++			/*
++			 * An error occurred. Don't event try
++			 * to send the current request. Just
++			 * queue it.
++			 */
++			spin_lock_irqsave(&vtpms->req_list_lock, flags);
++			vtpms->flags |= DATAEX_FLAG_QUEUED_ONLY;
++			list_add_tail(&t->next, &vtpms->queued_requests);
++			spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
++		}
++	}
++
++exit:
++	return rc;
++}
++
++
++/*
++ * Send all queued requests.
++ */
++static int _vtpm_send_queued(struct tpm_chip *chip)
++{
++	int rc;
++	int error = 0;
++	long flags;
++	unsigned char buffer[1];
++	struct vtpm_state *vtpms;
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	spin_lock_irqsave(&vtpms->req_list_lock, flags);
++
++	while (!list_empty(&vtpms->queued_requests)) {
++		/*
++		 * Need to dequeue them.
++		 * Read the result into a dummy buffer.
++		 */
++		struct transmission *qt = (struct transmission *)
++		                          vtpms->queued_requests.next;
++		list_del(&qt->next);
++		vtpms->current_request = qt;
++		spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
++
++		rc = vtpm_vd_send(vtpms->tpm_private,
++		                  qt->request,
++		                  qt->request_len,
++		                  qt);
++
++		if (rc < 0) {
++			spin_lock_irqsave(&vtpms->req_list_lock, flags);
++			if ((qt = vtpms->current_request) != NULL) {
++				/*
++				 * requeue it at the beginning
++				 * of the list
++				 */
++				list_add(&qt->next,
++				         &vtpms->queued_requests);
++			}
++			vtpms->current_request = NULL;
++			error = 1;
++			break;
++		}
++		/*
++		 * After this point qt is not valid anymore!
++		 * It is freed when the front-end is delivering
++		 * the data by calling tpm_recv
++		 */
++		/*
++		 * Receive response into provided dummy buffer
++		 */
++		rc = vtpm_recv(chip, buffer, sizeof(buffer));
++		spin_lock_irqsave(&vtpms->req_list_lock, flags);
++	}
++
++	spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
++
++	return error;
++}
++
++static void vtpm_cancel(struct tpm_chip *chip)
++{
++	unsigned long flags;
++	struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	spin_lock_irqsave(&vtpms->resp_list_lock,flags);
++
++	if (!vtpms->current_response && vtpms->current_request) {
++		spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++		interruptible_sleep_on(&vtpms->resp_wait_queue);
++		spin_lock_irqsave(&vtpms->resp_list_lock,flags);
++	}
++
++	if (vtpms->current_response) {
++		struct transmission *t = vtpms->current_response;
++		vtpms->current_response = NULL;
++		transmission_free(t);
++	}
++
++	spin_unlock_irqrestore(&vtpms->resp_list_lock,flags);
++}
++
++static u8 vtpm_status(struct tpm_chip *chip)
++{
++	u8 rc = 0;
++	unsigned long flags;
++	struct vtpm_state *vtpms;
++
++	vtpms = (struct vtpm_state *)chip_get_private(chip);
++
++	spin_lock_irqsave(&vtpms->resp_list_lock, flags);
++	/*
++	 * Data are available if:
++	 *  - there's a current response
++	 *  - the last packet was queued only (this is fake, but necessary to
++	 *      get the generic TPM layer to call the receive function.)
++	 */
++	if (vtpms->current_response ||
++	    0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) {
++		rc = STATUS_DATA_AVAIL;
++	} else if (!vtpms->current_response && !vtpms->current_request) {
++		rc = STATUS_READY;
++	}
++
++	spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
++	return rc;
++}
++
++static struct file_operations vtpm_ops = {
++	.owner = THIS_MODULE,
++	.llseek = no_llseek,
++	.open = tpm_open,
++	.read = tpm_read,
++	.write = tpm_write,
++	.release = tpm_release,
++};
++
++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
++		   NULL);
++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
++static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
++
++static struct attribute *vtpm_attrs[] = {
++	&dev_attr_pubek.attr,
++	&dev_attr_pcrs.attr,
++	&dev_attr_enabled.attr,
++	&dev_attr_active.attr,
++	&dev_attr_owned.attr,
++	&dev_attr_temp_deactivated.attr,
++	&dev_attr_caps.attr,
++	&dev_attr_cancel.attr,
++	NULL,
++};
++
++static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs };
++
++#define TPM_LONG_TIMEOUT   (10 * 60 * HZ)
++
++static struct tpm_vendor_specific tpm_vtpm = {
++	.recv = vtpm_recv,
++	.send = vtpm_send,
++	.cancel = vtpm_cancel,
++	.status = vtpm_status,
++	.req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
++	.req_complete_val  = STATUS_DATA_AVAIL,
++	.req_canceled = STATUS_READY,
++	.attr_group = &vtpm_attr_grp,
++	.miscdev = {
++		.fops = &vtpm_ops,
++	},
++	.duration = {
++		TPM_LONG_TIMEOUT,
++		TPM_LONG_TIMEOUT,
++		TPM_LONG_TIMEOUT,
++	},
++};
++
++struct tpm_chip *init_vtpm(struct device *dev,
++                           struct tpm_private *tp)
++{
++	long rc;
++	struct tpm_chip *chip;
++	struct vtpm_state *vtpms;
++
++	vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL);
++	if (!vtpms)
++		return ERR_PTR(-ENOMEM);
++
++	vtpm_state_init(vtpms);
++	vtpms->tpm_private = tp;
++
++	chip = tpm_register_hardware(dev, &tpm_vtpm);
++	if (!chip) {
++		rc = -ENODEV;
++		goto err_free_mem;
++	}
++
++	chip_set_private(chip, vtpms);
++
++	return chip;
++
++err_free_mem:
++	kfree(vtpms);
++
++	return ERR_PTR(rc);
++}
++
++void cleanup_vtpm(struct device *dev)
++{
++	struct tpm_chip *chip = dev_get_drvdata(dev);
++	struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip);
++	tpm_remove_hardware(dev);
++	kfree(vtpms);
++}
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ sle11sp1-2010-01-20/drivers/char/tpm/tpm_vtpm.h	2009-12-04 10:44:41.000000000 +0100
+@@ -0,0 +1,55 @@
++#ifndef TPM_VTPM_H
++#define TPM_VTPM_H
++
++struct tpm_chip;
++struct tpm_private;
++
++struct vtpm_state {
++	struct transmission *current_request;
++	spinlock_t           req_list_lock;
++	wait_queue_head_t    req_wait_queue;
++
++	struct list_head     queued_requests;
++
++	struct transmission *current_response;
++	spinlock_t           resp_list_lock;
++	wait_queue_head_t    resp_wait_queue;     // processes waiting for responses
++
++	u8                   vd_status;
++	u8                   flags;
++
++	unsigned long        disconnect_time;
++
++	/*
++	 * The following is a private structure of the underlying
++	 * driver. It is passed as parameter in the send function.
++	 */
++	struct tpm_private *tpm_private;
++};
++
++
++enum vdev_status {
++	TPM_VD_STATUS_DISCONNECTED = 0x0,
++	TPM_VD_STATUS_CONNECTED = 0x1
++};
++
++/* this function is called from tpm_vtpm.c */
++int vtpm_vd_send(struct tpm_private * tp,
++                 const u8 * buf, size_t count, void *ptr);
++
++/* these functions are offered by tpm_vtpm.c */
++struct tpm_chip *init_vtpm(struct device *,
++                           struct tpm_private *);
++void cleanup_vtpm(struct device *);
++int vtpm_vd_recv(const struct tpm_chip* chip,
++                 const unsigned char *buffer, size_t count, void *ptr);
++void vtpm_vd_status(const struct tpm_chip *, u8 status);
++
++static inline struct tpm_private *tpm_private_from_dev(struct device *dev)
++{
++	struct tpm_chip *chip = dev_get_drvdata(dev);
++	struct vtpm_state *vtpms = chip_get_private(chip);
++	return vtpms->tpm_private;
++}
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ sle11sp1-2010-01-20/drivers/char/tpm/tpm_xen.c	2009-12-04 10:44:41.000000000 +0100
+@@ -0,0 +1,722 @@
++/*
++ * Copyright (c) 2005, IBM Corporation
++ *
++ * Author: Stefan Berger, stefanb@us.ibm.com
++ * Grant table support: Mahadevan Gomathisankaran
++ *
++ * This code has been derived from drivers/xen/netfront/netfront.c
++ *
++ * Copyright (c) 2002-2004, K A Fraser
++ *
++ * 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/errno.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/mutex.h>
++#include <asm/uaccess.h>
++#include <xen/evtchn.h>
++#include <xen/interface/grant_table.h>
++#include <xen/interface/io/tpmif.h>
++#include <xen/gnttab.h>
++#include <xen/xenbus.h>
++#include "tpm.h"
++#include "tpm_vtpm.h"
++
++#undef DEBUG
++
++/* local structures */
++struct tpm_private {
++	struct tpm_chip *chip;
++
++	tpmif_tx_interface_t *tx;
++	atomic_t refcnt;
++	unsigned int irq;
++	u8 is_connected;
++	u8 is_suspended;
++
++	spinlock_t tx_lock;
++
++	struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE];
++
++	atomic_t tx_busy;
++	void *tx_remember;
++
++	domid_t backend_id;
++	wait_queue_head_t wait_q;
++
++	struct xenbus_device *dev;
++	int ring_ref;
++};
++
++struct tx_buffer {
++	unsigned int size;	// available space in data
++	unsigned int len;	// used space in data
++	unsigned char *data;	// pointer to a page
++};
++
++
++/* locally visible variables */
++static grant_ref_t gref_head;
++static struct tpm_private *my_priv;
++
++/* local function prototypes */
++static irqreturn_t tpmif_int(int irq,
++                             void *tpm_priv,
++                             struct pt_regs *ptregs);
++static void tpmif_rx_action(unsigned long unused);
++static int tpmif_connect(struct xenbus_device *dev,
++                         struct tpm_private *tp,
++                         domid_t domid);
++static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0);
++static int tpmif_allocate_tx_buffers(struct tpm_private *tp);
++static void tpmif_free_tx_buffers(struct tpm_private *tp);
++static void tpmif_set_connected_state(struct tpm_private *tp,
++                                      u8 newstate);
++static int tpm_xmit(struct tpm_private *tp,
++                    const u8 * buf, size_t count, int userbuffer,
++                    void *remember);
++static void destroy_tpmring(struct tpm_private *tp);
++void __exit tpmif_exit(void);
++
++#define DPRINTK(fmt, args...) \
++    pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
++#define IPRINTK(fmt, args...) \
++    printk(KERN_INFO "xen_tpm_fr: " fmt, ##args)
++#define WPRINTK(fmt, args...) \
++    printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args)
++
++#define GRANT_INVALID_REF	0
++
++
++static inline int
++tx_buffer_copy(struct tx_buffer *txb, const u8 *src, int len,
++               int isuserbuffer)
++{
++	int copied = len;
++
++	if (len > txb->size)
++		copied = txb->size;
++	if (isuserbuffer) {
++		if (copy_from_user(txb->data, src, copied))
++			return -EFAULT;
++	} else {
++		memcpy(txb->data, src, copied);
++	}
++	txb->len = len;
++	return copied;
++}
++
++static inline struct tx_buffer *tx_buffer_alloc(void)
++{
++	struct tx_buffer *txb;
++
++	txb = kzalloc(sizeof(struct tx_buffer), GFP_KERNEL);
++	if (!txb)
++		return NULL;
++
++	txb->len = 0;
++	txb->size = PAGE_SIZE;
++	txb->data = (unsigned char *)__get_free_page(GFP_KERNEL);
++	if (txb->data == NULL) {
++		kfree(txb);
++		txb = NULL;
++	}
++
++	return txb;
++}
++
++
++static inline void tx_buffer_free(struct tx_buffer *txb)
++{
++	if (txb) {
++		free_page((long)txb->data);
++		kfree(txb);
++	}
++}
++
++/**************************************************************
++ Utility function for the tpm_private structure
++**************************************************************/
++static void tpm_private_init(struct tpm_private *tp)
++{
++	spin_lock_init(&tp->tx_lock);
++	init_waitqueue_head(&tp->wait_q);
++	atomic_set(&tp->refcnt, 1);
++}
++
++static void tpm_private_put(void)
++{
++	if (!atomic_dec_and_test(&my_priv->refcnt))
++		return;
++
++	tpmif_free_tx_buffers(my_priv);
++	kfree(my_priv);
++	my_priv = NULL;
++}
++
++static struct tpm_private *tpm_private_get(void)
++{
++	int err;
++
++	if (my_priv) {
++		atomic_inc(&my_priv->refcnt);
++		return my_priv;
++	}
++
++	my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL);
++	if (!my_priv)
++		return NULL;
++
++	tpm_private_init(my_priv);
++	err = tpmif_allocate_tx_buffers(my_priv);
++	if (err < 0)
++		tpm_private_put();
++
++	return my_priv;
++}
++
++/**************************************************************
++
++ The interface to let the tpm plugin register its callback
++ function and send data to another partition using this module
++
++**************************************************************/
++
++static DEFINE_MUTEX(suspend_lock);
++/*
++ * Send data via this module by calling this function
++ */
++int vtpm_vd_send(struct tpm_private *tp,
++                 const u8 * buf, size_t count, void *ptr)
++{
++	int sent;
++
++	mutex_lock(&suspend_lock);
++	sent = tpm_xmit(tp, buf, count, 0, ptr);
++	mutex_unlock(&suspend_lock);
++
++	return sent;
++}
++
++/**************************************************************
++ XENBUS support code
++**************************************************************/
++
++static int setup_tpmring(struct xenbus_device *dev,
++                         struct tpm_private *tp)
++{
++	tpmif_tx_interface_t *sring;
++	int err;
++
++	tp->ring_ref = GRANT_INVALID_REF;
++
++	sring = (void *)__get_free_page(GFP_KERNEL);
++	if (!sring) {
++		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
++		return -ENOMEM;
++	}
++	tp->tx = sring;
++
++	err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx));
++	if (err < 0) {
++		free_page((unsigned long)sring);
++		tp->tx = NULL;
++		xenbus_dev_fatal(dev, err, "allocating grant reference");
++		goto fail;
++	}
++	tp->ring_ref = err;
++
++	err = tpmif_connect(dev, tp, dev->otherend_id);
++	if (err)
++		goto fail;
++
++	return 0;
++fail:
++	destroy_tpmring(tp);
++	return err;
++}
++
++
++static void destroy_tpmring(struct tpm_private *tp)
++{
++	tpmif_set_connected_state(tp, 0);
++
++	if (tp->ring_ref != GRANT_INVALID_REF) {
++		gnttab_end_foreign_access(tp->ring_ref, (unsigned long)tp->tx);
++		tp->ring_ref = GRANT_INVALID_REF;
++		tp->tx = NULL;
++	}
++
++	if (tp->irq)
++		unbind_from_irqhandler(tp->irq, tp);
++
++	tp->irq = 0;
++}
++
++
++static int talk_to_backend(struct xenbus_device *dev,
++                           struct tpm_private *tp)
++{
++	const char *message = NULL;
++	int err;
++	struct xenbus_transaction xbt;
++
++	err = setup_tpmring(dev, tp);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "setting up ring");
++		goto out;
++	}
++
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		goto destroy_tpmring;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename,
++	                    "ring-ref","%u", tp->ring_ref);
++	if (err) {
++		message = "writing ring-ref";
++		goto abort_transaction;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
++			    irq_to_evtchn_port(tp->irq));
++	if (err) {
++		message = "writing event-channel";
++		goto abort_transaction;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++	if (err) {
++		xenbus_dev_fatal(dev, err, "completing transaction");
++		goto destroy_tpmring;
++	}
++
++	xenbus_switch_state(dev, XenbusStateConnected);
++
++	return 0;
++
++abort_transaction:
++	xenbus_transaction_end(xbt, 1);
++	if (message)
++		xenbus_dev_error(dev, err, "%s", message);
++destroy_tpmring:
++	destroy_tpmring(tp);
++out:
++	return err;
++}
++
++/**
++ * Callback received when the backend's state changes.
++ */
++static void backend_changed(struct xenbus_device *dev,
++			    enum xenbus_state backend_state)
++{
++	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
++	DPRINTK("\n");
++
++	switch (backend_state) {
++	case XenbusStateInitialising:
++	case XenbusStateInitWait:
++	case XenbusStateInitialised:
++	case XenbusStateReconfiguring:
++	case XenbusStateReconfigured:
++	case XenbusStateUnknown:
++		break;
++
++	case XenbusStateConnected:
++		tpmif_set_connected_state(tp, 1);
++		break;
++
++	case XenbusStateClosing:
++		tpmif_set_connected_state(tp, 0);
++		xenbus_frontend_closed(dev);
++		break;
++
++	case XenbusStateClosed:
++		tpmif_set_connected_state(tp, 0);
++		if (tp->is_suspended == 0)
++			device_unregister(&dev->dev);
++		xenbus_frontend_closed(dev);
++		break;
++	}
++}
++
++static int tpmfront_probe(struct xenbus_device *dev,
++                          const struct xenbus_device_id *id)
++{
++	int err;
++	int handle;
++	struct tpm_private *tp = tpm_private_get();
++
++	if (!tp)
++		return -ENOMEM;
++
++	tp->chip = init_vtpm(&dev->dev, tp);
++	if (IS_ERR(tp->chip))
++		return PTR_ERR(tp->chip);
++
++	err = xenbus_scanf(XBT_NIL, dev->nodename,
++	                   "handle", "%i", &handle);
++	if (XENBUS_EXIST_ERR(err))
++		return err;
++
++	if (err < 0) {
++		xenbus_dev_fatal(dev,err,"reading virtual-device");
++		return err;
++	}
++
++	tp->dev = dev;
++
++	err = talk_to_backend(dev, tp);
++	if (err) {
++		tpm_private_put();
++		return err;
++	}
++
++	return 0;
++}
++
++
++static int tpmfront_remove(struct xenbus_device *dev)
++{
++	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
++	destroy_tpmring(tp);
++	cleanup_vtpm(&dev->dev);
++	return 0;
++}
++
++static int tpmfront_suspend(struct xenbus_device *dev)
++{
++	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
++	u32 ctr;
++
++	/* Take the lock, preventing any application from sending. */
++	mutex_lock(&suspend_lock);
++	tp->is_suspended = 1;
++
++	for (ctr = 0; atomic_read(&tp->tx_busy); ctr++) {
++		if ((ctr % 10) == 0)
++			printk("TPM-FE [INFO]: Waiting for outstanding "
++			       "request.\n");
++		/* Wait for a request to be responded to. */
++		interruptible_sleep_on_timeout(&tp->wait_q, 100);
++	}
++
++	return 0;
++}
++
++static int tpmfront_suspend_finish(struct tpm_private *tp)
++{
++	tp->is_suspended = 0;
++	/* Allow applications to send again. */
++	mutex_unlock(&suspend_lock);
++	return 0;
++}
++
++static int tpmfront_suspend_cancel(struct xenbus_device *dev)
++{
++	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
++	return tpmfront_suspend_finish(tp);
++}
++
++static int tpmfront_resume(struct xenbus_device *dev)
++{
++	struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
++	destroy_tpmring(tp);
++	return talk_to_backend(dev, tp);
++}
++
++static int tpmif_connect(struct xenbus_device *dev,
++                         struct tpm_private *tp,
++                         domid_t domid)
++{
++	int err;
++
++	tp->backend_id = domid;
++
++	err = bind_listening_port_to_irqhandler(
++		domid, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
++	if (err <= 0) {
++		WPRINTK("bind_listening_port_to_irqhandler failed "
++			"(err=%d)\n", err);
++		return err;
++	}
++	tp->irq = err;
++
++	return 0;
++}
++
++static struct xenbus_device_id tpmfront_ids[] = {
++	{ "vtpm" },
++	{ "" }
++};
++
++static struct xenbus_driver tpmfront = {
++	.name = "vtpm",
++	.owner = THIS_MODULE,
++	.ids = tpmfront_ids,
++	.probe = tpmfront_probe,
++	.remove =  tpmfront_remove,
++	.resume = tpmfront_resume,
++	.otherend_changed = backend_changed,
++	.suspend = tpmfront_suspend,
++	.suspend_cancel = tpmfront_suspend_cancel,
++};
++
++static void __init init_tpm_xenbus(void)
++{
++	xenbus_register_frontend(&tpmfront);
++}
++
++static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
++{
++	unsigned int i;
++
++	for (i = 0; i < TPMIF_TX_RING_SIZE; i++) {
++		tp->tx_buffers[i] = tx_buffer_alloc();
++		if (!tp->tx_buffers[i]) {
++			tpmif_free_tx_buffers(tp);
++			return -ENOMEM;
++		}
++	}
++	return 0;
++}
++
++static void tpmif_free_tx_buffers(struct tpm_private *tp)
++{
++	unsigned int i;
++
++	for (i = 0; i < TPMIF_TX_RING_SIZE; i++)
++		tx_buffer_free(tp->tx_buffers[i]);
++}
++
++static void tpmif_rx_action(unsigned long priv)
++{
++	struct tpm_private *tp = (struct tpm_private *)priv;
++	int i = 0;
++	unsigned int received;
++	unsigned int offset = 0;
++	u8 *buffer;
++	tpmif_tx_request_t *tx = &tp->tx->ring[i].req;
++
++	atomic_set(&tp->tx_busy, 0);
++	wake_up_interruptible(&tp->wait_q);
++
++	received = tx->size;
++
++	buffer = kmalloc(received, GFP_ATOMIC);
++	if (!buffer)
++		return;
++
++	for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
++		struct tx_buffer *txb = tp->tx_buffers[i];
++		tpmif_tx_request_t *tx;
++		unsigned int tocopy;
++
++		tx = &tp->tx->ring[i].req;
++		tocopy = tx->size;
++		if (tocopy > PAGE_SIZE)
++			tocopy = PAGE_SIZE;
++
++		memcpy(&buffer[offset], txb->data, tocopy);
++
++		gnttab_release_grant_reference(&gref_head, tx->ref);
++
++		offset += tocopy;
++	}
++
++	vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
++	kfree(buffer);
++}
++
++
++static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs)
++{
++	struct tpm_private *tp = tpm_priv;
++	unsigned long flags;
++
++	spin_lock_irqsave(&tp->tx_lock, flags);
++	tpmif_rx_tasklet.data = (unsigned long)tp;
++	tasklet_schedule(&tpmif_rx_tasklet);
++	spin_unlock_irqrestore(&tp->tx_lock, flags);
++
++	return IRQ_HANDLED;
++}
++
++
++static int tpm_xmit(struct tpm_private *tp,
++                    const u8 * buf, size_t count, int isuserbuffer,
++                    void *remember)
++{
++	tpmif_tx_request_t *tx;
++	TPMIF_RING_IDX i;
++	unsigned int offset = 0;
++
++	spin_lock_irq(&tp->tx_lock);
++
++	if (unlikely(atomic_read(&tp->tx_busy))) {
++		printk("tpm_xmit: There's an outstanding request/response "
++		       "on the way!\n");
++		spin_unlock_irq(&tp->tx_lock);
++		return -EBUSY;
++	}
++
++	if (tp->is_connected != 1) {
++		spin_unlock_irq(&tp->tx_lock);
++		return -EIO;
++	}
++
++	for (i = 0; count > 0 && i < TPMIF_TX_RING_SIZE; i++) {
++		struct tx_buffer *txb = tp->tx_buffers[i];
++		int copied;
++
++		if (!txb) {
++			DPRINTK("txb (i=%d) is NULL. buffers initilized?\n"
++				"Not transmitting anything!\n", i);
++			spin_unlock_irq(&tp->tx_lock);
++			return -EFAULT;
++		}
++
++		copied = tx_buffer_copy(txb, &buf[offset], count,
++		                        isuserbuffer);
++		if (copied < 0) {
++			/* An error occurred */
++			spin_unlock_irq(&tp->tx_lock);
++			return copied;
++		}
++		count -= copied;
++		offset += copied;
++
++		tx = &tp->tx->ring[i].req;
++		tx->addr = virt_to_machine(txb->data);
++		tx->size = txb->len;
++		tx->unused = 0;
++
++		DPRINTK("First 4 characters sent by TPM-FE are "
++			"0x%02x 0x%02x 0x%02x 0x%02x\n",
++		        txb->data[0],txb->data[1],txb->data[2],txb->data[3]);
++
++		/* Get the granttable reference for this page. */
++		tx->ref = gnttab_claim_grant_reference(&gref_head);
++		if (tx->ref == -ENOSPC) {
++			spin_unlock_irq(&tp->tx_lock);
++			DPRINTK("Grant table claim reference failed in "
++				"func:%s line:%d file:%s\n",
++				__FUNCTION__, __LINE__, __FILE__);
++			return -ENOSPC;
++		}
++		gnttab_grant_foreign_access_ref(tx->ref,
++						tp->backend_id,
++						virt_to_mfn(txb->data),
++						0 /*RW*/);
++		wmb();
++	}
++
++	atomic_set(&tp->tx_busy, 1);
++	tp->tx_remember = remember;
++
++	mb();
++
++	notify_remote_via_irq(tp->irq);
++
++	spin_unlock_irq(&tp->tx_lock);
++	return offset;
++}
++
++
++static void tpmif_notify_upperlayer(struct tpm_private *tp)
++{
++	/* Notify upper layer about the state of the connection to the BE. */
++	vtpm_vd_status(tp->chip, (tp->is_connected
++				  ? TPM_VD_STATUS_CONNECTED
++				  : TPM_VD_STATUS_DISCONNECTED));
++}
++
++
++static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
++{
++	/*
++	 * Don't notify upper layer if we are in suspend mode and
++	 * should disconnect - assumption is that we will resume
++	 * The mutex keeps apps from sending.
++	 */
++	if (is_connected == 0 && tp->is_suspended == 1)
++		return;
++
++	/*
++	 * Unlock the mutex if we are connected again
++	 * after being suspended - now resuming.
++	 * This also removes the suspend state.
++	 */
++	if (is_connected == 1 && tp->is_suspended == 1)
++		tpmfront_suspend_finish(tp);
++
++	if (is_connected != tp->is_connected) {
++		tp->is_connected = is_connected;
++		tpmif_notify_upperlayer(tp);
++	}
++}
++
++
++
++/* =================================================================
++ * Initialization function.
++ * =================================================================
++ */
++
++
++static int __init tpmif_init(void)
++{
++	struct tpm_private *tp;
++
++	if (is_initial_xendomain())
++		return -EPERM;
++
++	tp = tpm_private_get();
++	if (!tp)
++		return -ENOMEM;
++
++	IPRINTK("Initialising the vTPM driver.\n");
++	if (gnttab_alloc_grant_references(TPMIF_TX_RING_SIZE,
++					  &gref_head) < 0) {
++		tpm_private_put();
++		return -EFAULT;
++	}
++
++	init_tpm_xenbus();
++	return 0;
++}
++
++
++module_init(tpmif_init);
++
++MODULE_LICENSE("Dual BSD/GPL");
+--- sle11sp1-2010-01-20.orig/drivers/edac/edac_mc.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/edac/edac_mc.c	2009-12-04 10:44:41.000000000 +0100
+@@ -578,6 +578,10 @@ static void edac_mc_scrub_block(unsigned
+ 
+ 	debugf3("%s()\n", __func__);
+ 
++#ifdef CONFIG_XEN
++	page = mfn_to_local_pfn(page);
++#endif
++
+ 	/* ECC error page was not in our memory. Ignore it. */
+ 	if (!pfn_valid(page))
+ 		return;
+--- sle11sp1-2010-01-20.orig/drivers/firmware/dell_rbu.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/firmware/dell_rbu.c	2009-12-04 10:44:41.000000000 +0100
+@@ -169,9 +169,28 @@ static int create_packet(void *data, siz
+ 			spin_lock(&rbu_data.lock);
+ 			goto out_alloc_packet_array;
+ 		}
++#ifdef CONFIG_XEN
++		if (ordernum && xen_create_contiguous_region(
++			(unsigned long)packet_data_temp_buf, ordernum, 0)) {
++			free_pages((unsigned long)packet_data_temp_buf,
++				   ordernum);
++			printk(KERN_WARNING
++				"dell_rbu:%s: failed to adjust new "
++				"packet\n", __func__);
++			retval = -ENOMEM;
++			spin_lock(&rbu_data.lock);
++			goto out_alloc_packet_array;
++		}
++#endif
+ 
+-		if ((unsigned long)virt_to_phys(packet_data_temp_buf)
++		if ((unsigned long)virt_to_bus(packet_data_temp_buf)
+ 				< allocation_floor) {
++#ifdef CONFIG_XEN
++			if (ordernum)
++				xen_destroy_contiguous_region(
++					(unsigned long)packet_data_temp_buf,
++					ordernum);
++#endif
+ 			pr_debug("packet 0x%lx below floor at 0x%lx.\n",
+ 					(unsigned long)virt_to_phys(
+ 						packet_data_temp_buf),
+@@ -185,7 +204,7 @@ static int create_packet(void *data, siz
+ 	newpacket->data = packet_data_temp_buf;
+ 
+ 	pr_debug("create_packet: newpacket at physical addr %lx\n",
+-		(unsigned long)virt_to_phys(newpacket->data));
++		(unsigned long)virt_to_bus(newpacket->data));
+ 
+ 	/* packets may not have fixed size */
+ 	newpacket->length = length;
+@@ -204,7 +223,7 @@ out_alloc_packet_array:
+ 	/* always free packet array */
+ 	for (;idx>0;idx--) {
+ 		pr_debug("freeing unused packet below floor 0x%lx.\n",
+-			(unsigned long)virt_to_phys(
++			(unsigned long)virt_to_bus(
+ 				invalid_addr_packet_array[idx-1]));
+ 		free_pages((unsigned long)invalid_addr_packet_array[idx-1],
+ 			ordernum);
+@@ -348,6 +367,13 @@ static void packet_empty_list(void)
+ 		 * to make sure there are no stale RBU packets left in memory
+ 		 */
+ 		memset(newpacket->data, 0, rbu_data.packetsize);
++#ifdef CONFIG_XEN
++		if (newpacket->ordernum)
++			xen_destroy_contiguous_region(
++				(unsigned long)newpacket->data,
++				newpacket->ordernum);
++#endif
++
+ 		free_pages((unsigned long) newpacket->data,
+ 			newpacket->ordernum);
+ 		kfree(newpacket);
+@@ -402,7 +428,9 @@ static int img_update_realloc(unsigned l
+ {
+ 	unsigned char *image_update_buffer = NULL;
+ 	unsigned long rc;
++#ifndef CONFIG_XEN
+ 	unsigned long img_buf_phys_addr;
++#endif
+ 	int ordernum;
+ 	int dma_alloc = 0;
+ 
+@@ -433,15 +461,19 @@ static int img_update_realloc(unsigned l
+ 
+ 	spin_unlock(&rbu_data.lock);
+ 
++#ifndef CONFIG_XEN
+ 	ordernum = get_order(size);
+ 	image_update_buffer =
+ 		(unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
+ 
+ 	img_buf_phys_addr =
+-		(unsigned long) virt_to_phys(image_update_buffer);
++		(unsigned long) virt_to_bus(image_update_buffer);
+ 
+ 	if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+ 		free_pages((unsigned long) image_update_buffer, ordernum);
++#else
++	{
++#endif
+ 		ordernum = -1;
+ 		image_update_buffer = dma_alloc_coherent(NULL, size,
+ 			&dell_rbu_dmaaddr, GFP_KERNEL);
+@@ -689,6 +721,12 @@ static struct bin_attribute rbu_packet_s
+ static int __init dcdrbu_init(void)
+ {
+ 	int rc;
++
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return -ENODEV;
++#endif
++
+ 	spin_lock_init(&rbu_data.lock);
+ 
+ 	init_packet_head();
+--- sle11sp1-2010-01-20.orig/drivers/ide/ide-lib.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/ide/ide-lib.c	2009-12-04 10:44:41.000000000 +0100
+@@ -18,12 +18,12 @@ void ide_toggle_bounce(ide_drive_t *driv
+ {
+ 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
+ 
+-	if (!PCI_DMA_BUS_IS_PHYS) {
+-		addr = BLK_BOUNCE_ANY;
+-	} else if (on && drive->media == ide_disk) {
++	if (on && drive->media == ide_disk) {
+ 		struct device *dev = drive->hwif->dev;
+ 
+-		if (dev && dev->dma_mask)
++		if (!PCI_DMA_BUS_IS_PHYS)
++			addr = BLK_BOUNCE_ANY;
++		else if (dev && dev->dma_mask)
+ 			addr = *dev->dma_mask;
+ 	}
+ 
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/buffer_sync.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/buffer_sync.c	2009-12-04 10:44:41.000000000 +0100
+@@ -8,6 +8,10 @@
+  * @author Barry Kasindorf
+  * @author Robert Richter <robert.richter@amd.com>
+  *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
+  * This is the core of the buffer management. Each
+  * CPU buffer is processed and entered into the
+  * global event buffer. Such processing is necessary
+@@ -42,6 +46,8 @@ static cpumask_var_t marked_cpus;
+ static DEFINE_SPINLOCK(task_mortuary);
+ static void process_task_mortuary(void);
+ 
++static int cpu_current_domain[NR_CPUS];
++
+ /* Take ownership of the task struct and place it on the
+  * list for processing. Only after two full buffer syncs
+  * does the task eventually get freed, because by then
+@@ -60,7 +66,6 @@ task_free_notify(struct notifier_block *
+ 	return NOTIFY_OK;
+ }
+ 
+-
+ /* The task is on its way out. A sync of the buffer means we can catch
+  * any remaining samples for this task.
+  */
+@@ -153,6 +158,11 @@ static void end_sync(void)
+ int sync_start(void)
+ {
+ 	int err;
++	int i;
++
++	for (i = 0; i < NR_CPUS; i++) {
++		cpu_current_domain[i] = COORDINATOR_DOMAIN;
++	}
+ 
+ 	if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
+ 		return -ENOMEM;
+@@ -284,13 +294,29 @@ static void add_cpu_switch(int i)
+ 	last_cookie = INVALID_COOKIE;
+ }
+ 
+-static void add_kernel_ctx_switch(unsigned int in_kernel)
++static void add_cpu_mode_switch(unsigned int cpu_mode)
+ {
+ 	add_event_entry(ESCAPE_CODE);
+-	if (in_kernel)
++	switch (cpu_mode) {
++	case CPU_MODE_USER:
++		add_event_entry(USER_ENTER_SWITCH_CODE);
++		break;
++	case CPU_MODE_KERNEL:
+ 		add_event_entry(KERNEL_ENTER_SWITCH_CODE);
+-	else
+-		add_event_entry(KERNEL_EXIT_SWITCH_CODE);
++		break;
++	case CPU_MODE_XEN:
++		add_event_entry(XEN_ENTER_SWITCH_CODE);
++	  	break;
++	default:
++		break;
++	}
++}
++
++static void add_domain_switch(unsigned long domain_id)
++{
++	add_event_entry(ESCAPE_CODE);
++	add_event_entry(DOMAIN_SWITCH_CODE);
++	add_event_entry(domain_id);
+ }
+ 
+ static void
+@@ -371,12 +397,12 @@ static inline void add_sample_entry(unsi
+  * for later lookup from userspace. Return 0 on failure.
+  */
+ static int
+-add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
++add_sample(struct mm_struct *mm, struct op_sample *s, int cpu_mode)
+ {
+ 	unsigned long cookie;
+ 	off_t offset;
+ 
+-	if (in_kernel) {
++	if (cpu_mode >= CPU_MODE_KERNEL) {
+ 		add_sample_entry(s->eip, s->event);
+ 		return 1;
+ 	}
+@@ -501,9 +527,10 @@ void sync_buffer(int cpu)
+ 	unsigned long val;
+ 	struct task_struct *new;
+ 	unsigned long cookie = 0;
+-	int in_kernel = 1;
++	int cpu_mode = CPU_MODE_KERNEL;
+ 	sync_buffer_state state = sb_buffer_start;
+ 	unsigned int i;
++	int domain_switch = 0;
+ 	unsigned long available;
+ 	unsigned long flags;
+ 	struct op_entry entry;
+@@ -513,6 +540,11 @@ void sync_buffer(int cpu)
+ 
+ 	add_cpu_switch(cpu);
+ 
++	/* We need to assign the first samples in this CPU buffer to the
++	   same domain that we were processing at the last sync_buffer */
++	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
++		add_domain_switch(cpu_current_domain[cpu]);
++
+ 	op_cpu_buffer_reset(cpu);
+ 	available = op_cpu_buffer_entries(cpu);
+ 
+@@ -521,6 +553,13 @@ void sync_buffer(int cpu)
+ 		if (!sample)
+ 			break;
+ 
++		if (domain_switch) {
++			cpu_current_domain[cpu] = sample->eip;
++			add_domain_switch(sample->eip);
++			domain_switch = 0;
++			continue;
++		}
++
+ 		if (is_code(sample->eip)) {
+ 			flags = sample->event;
+ 			if (flags & TRACE_BEGIN) {
+@@ -529,10 +568,10 @@ void sync_buffer(int cpu)
+ 			}
+ 			if (flags & KERNEL_CTX_SWITCH) {
+ 				/* kernel/userspace switch */
+-				in_kernel = flags & IS_KERNEL;
++				cpu_mode = flags & CPU_MODE_MASK;
+ 				if (state == sb_buffer_start)
+ 					state = sb_sample_start;
+-				add_kernel_ctx_switch(flags & IS_KERNEL);
++				add_cpu_mode_switch(cpu_mode);
+ 			}
+ 			if (flags & USER_CTX_SWITCH
+ 			    && op_cpu_buffer_get_data(&entry, &val)) {
+@@ -545,16 +584,23 @@ void sync_buffer(int cpu)
+ 					cookie = get_exec_dcookie(mm);
+ 				add_user_ctx_switch(new, cookie);
+ 			}
++			if (flags & DOMAIN_SWITCH)
++				domain_switch = 1;
+ 			if (op_cpu_buffer_get_size(&entry))
+ 				add_data(&entry, mm);
+ 			continue;
+ 		}
+ 
++		if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) {
++			add_sample_entry(sample->eip, sample->event);
++			continue;
++		}
++
+ 		if (state < sb_bt_start)
+ 			/* ignore sample */
+ 			continue;
+ 
+-		if (add_sample(mm, sample, in_kernel))
++		if (add_sample(mm, sample, cpu_mode))
+ 			continue;
+ 
+ 		/* ignore backtraces if failed to add a sample */
+@@ -565,6 +611,10 @@ void sync_buffer(int cpu)
+ 	}
+ 	release_mm(mm);
+ 
++	/* We reset domain to COORDINATOR at each CPU switch */
++	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
++		add_domain_switch(COORDINATOR_DOMAIN);
++
+ 	mark_done(cpu);
+ 
+ 	mutex_unlock(&buffer_mutex);
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/cpu_buffer.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/cpu_buffer.c	2009-12-04 10:44:41.000000000 +0100
+@@ -8,6 +8,10 @@
+  * @author Barry Kasindorf <barry.kasindorf@amd.com>
+  * @author Robert Richter <robert.richter@amd.com>
+  *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
+  * Each CPU has a local buffer that stores PC value/event
+  * pairs. We also log context switches when we notice them.
+  * Eventually each CPU's buffer is processed into the global
+@@ -54,6 +58,8 @@ static void wq_sync_buffer(struct work_s
+ #define DEFAULT_TIMER_EXPIRE (HZ / 10)
+ static int work_enabled;
+ 
++static int32_t current_domain = COORDINATOR_DOMAIN;
++
+ unsigned long oprofile_get_cpu_buffer_size(void)
+ {
+ 	return oprofile_cpu_buffer_size;
+@@ -98,7 +104,7 @@ int alloc_cpu_buffers(void)
+ 		struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+ 
+ 		b->last_task = NULL;
+-		b->last_is_kernel = -1;
++		b->last_cpu_mode = -1;
+ 		b->tracing = 0;
+ 		b->buffer_size = buffer_size;
+ 		b->sample_received = 0;
+@@ -216,7 +222,7 @@ unsigned long op_cpu_buffer_entries(int 
+ 
+ static int
+ op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace,
+-	    int is_kernel, struct task_struct *task)
++	    int cpu_mode, struct task_struct *task)
+ {
+ 	struct op_entry entry;
+ 	struct op_sample *sample;
+@@ -229,16 +235,15 @@ op_add_code(struct oprofile_cpu_buffer *
+ 		flags |= TRACE_BEGIN;
+ 
+ 	/* notice a switch from user->kernel or vice versa */
+-	is_kernel = !!is_kernel;
+-	if (cpu_buf->last_is_kernel != is_kernel) {
+-		cpu_buf->last_is_kernel = is_kernel;
+-		flags |= KERNEL_CTX_SWITCH;
+-		if (is_kernel)
+-			flags |= IS_KERNEL;
++	if (cpu_buf->last_cpu_mode != cpu_mode) {
++		cpu_buf->last_cpu_mode = cpu_mode;
++		flags |= KERNEL_CTX_SWITCH | cpu_mode;
+ 	}
+ 
+ 	/* notice a task switch */
+-	if (cpu_buf->last_task != task) {
++	/* if not processing other domain samples */
++	if (cpu_buf->last_task != task &&
++	    current_domain == COORDINATOR_DOMAIN) {
+ 		cpu_buf->last_task = task;
+ 		flags |= USER_CTX_SWITCH;
+ 	}
+@@ -287,14 +292,14 @@ op_add_sample(struct oprofile_cpu_buffer
+ /*
+  * This must be safe from any context.
+  *
+- * is_kernel is needed because on some architectures you cannot
++ * cpu_mode is needed because on some architectures you cannot
+  * tell if you are in kernel or user space simply by looking at
+- * pc. We tag this in the buffer by generating kernel enter/exit
+- * events whenever is_kernel changes
++ * pc. We tag this in the buffer by generating kernel/user (and
++ * xen) enter events whenever cpu_mode changes
+  */
+ static int
+ log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
+-	   unsigned long backtrace, int is_kernel, unsigned long event)
++	   unsigned long backtrace, int cpu_mode, unsigned long event)
+ {
+ 	cpu_buf->sample_received++;
+ 
+@@ -303,7 +308,7 @@ log_sample(struct oprofile_cpu_buffer *c
+ 		return 0;
+ 	}
+ 
+-	if (op_add_code(cpu_buf, backtrace, is_kernel, current))
++	if (op_add_code(cpu_buf, backtrace, cpu_mode, current))
+ 		goto fail;
+ 
+ 	if (op_add_sample(cpu_buf, pc, event))
+@@ -458,6 +463,25 @@ fail:
+ 	return;
+ }
+ 
++int oprofile_add_domain_switch(int32_t domain_id)
++{
++	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++
++	/* should have space for switching into and out of domain
++	   (2 slots each) plus one sample and one cpu mode switch */
++	if (((nr_available_slots(cpu_buf) < 6) &&
++	     (domain_id != COORDINATOR_DOMAIN)) ||
++	    (nr_available_slots(cpu_buf) < 2))
++		return 0;
++
++	add_code(cpu_buf, DOMAIN_SWITCH);
++	add_sample(cpu_buf, domain_id, 0);
++
++	current_domain = domain_id;
++
++	return 1;
++}
++
+ /*
+  * This serves to avoid cpu buffer overflow, and makes sure
+  * the task mortuary progresses
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/cpu_buffer.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/cpu_buffer.h	2009-12-04 10:44:41.000000000 +0100
+@@ -40,7 +40,7 @@ struct op_entry;
+ struct oprofile_cpu_buffer {
+ 	unsigned long buffer_size;
+ 	struct task_struct *last_task;
+-	int last_is_kernel;
++	int last_cpu_mode;
+ 	int tracing;
+ 	unsigned long sample_received;
+ 	unsigned long sample_lost_overflow;
+@@ -62,7 +62,7 @@ static inline void op_cpu_buffer_reset(i
+ {
+ 	struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
+ 
+-	cpu_buf->last_is_kernel = -1;
++	cpu_buf->last_cpu_mode = -1;
+ 	cpu_buf->last_task = NULL;
+ }
+ 
+@@ -112,9 +112,13 @@ int op_cpu_buffer_get_data(struct op_ent
+ }
+ 
+ /* extra data flags */
+-#define KERNEL_CTX_SWITCH	(1UL << 0)
+-#define IS_KERNEL		(1UL << 1)
++#define CPU_MODE_USER		0
++#define CPU_MODE_KERNEL		1
++#define CPU_MODE_XEN		2
++#define CPU_MODE_MASK		3
+ #define TRACE_BEGIN		(1UL << 2)
+ #define USER_CTX_SWITCH		(1UL << 3)
++#define KERNEL_CTX_SWITCH	(1UL << 4)
++#define DOMAIN_SWITCH		(1UL << 5)
+ 
+ #endif /* OPROFILE_CPU_BUFFER_H */
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/event_buffer.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/event_buffer.h	2009-12-04 10:44:41.000000000 +0100
+@@ -30,6 +30,9 @@ void wake_up_buffer_waiter(void);
+ #define INVALID_COOKIE ~0UL
+ #define NO_COOKIE 0UL
+ 
++/* Constant used to refer to coordinator domain (Xen) */
++#define COORDINATOR_DOMAIN -1
++
+ extern const struct file_operations event_buffer_fops;
+ 
+ /* mutex between sync_cpu_buffers() and the
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/oprof.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/oprof.c	2009-12-04 10:44:41.000000000 +0100
+@@ -5,6 +5,10 @@
+  * @remark Read the file COPYING
+  *
+  * @author John Levon <levon@movementarian.org>
++ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
+  */
+ 
+ #include <linux/kernel.h>
+@@ -35,6 +39,32 @@ static DEFINE_MUTEX(start_mutex);
+  */
+ static int timer = 0;
+ 
++int oprofile_set_active(int active_domains[], unsigned int adomains)
++{
++	int err;
++
++	if (!oprofile_ops.set_active)
++		return -EINVAL;
++
++	mutex_lock(&start_mutex);
++	err = oprofile_ops.set_active(active_domains, adomains);
++	mutex_unlock(&start_mutex);
++	return err;
++}
++
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
++{
++	int err;
++
++	if (!oprofile_ops.set_passive)
++		return -EINVAL;
++
++	mutex_lock(&start_mutex);
++	err = oprofile_ops.set_passive(passive_domains, pdomains);
++	mutex_unlock(&start_mutex);
++	return err;
++}
++
+ int oprofile_setup(void)
+ {
+ 	int err;
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/oprof.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/oprof.h	2009-12-04 10:44:41.000000000 +0100
+@@ -39,4 +39,7 @@ void oprofile_timer_init(struct oprofile
+ int oprofile_set_backtrace(unsigned long depth);
+ int oprofile_set_timeout(unsigned long time);
+ 
++int oprofile_set_active(int active_domains[], unsigned int adomains);
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
++
+ #endif /* OPROF_H */
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/oprofile_files.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/oprofile_files.c	2009-12-04 10:44:41.000000000 +0100
+@@ -5,11 +5,17 @@
+  * @remark Read the file COPYING
+  *
+  * @author John Levon <levon@movementarian.org>
++ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
+  */
+ 
+ #include <linux/fs.h>
+ #include <linux/oprofile.h>
+ #include <linux/jiffies.h>
++#include <asm/uaccess.h>
++#include <linux/ctype.h>
+ 
+ #include "event_buffer.h"
+ #include "oprofile_stats.h"
+@@ -165,6 +171,195 @@ static const struct file_operations dump
+ 	.write		= dump_write,
+ };
+ 
++#define TMPBUFSIZE 512
++
++static unsigned int adomains = 0;
++static int active_domains[MAX_OPROF_DOMAINS + 1];
++static DEFINE_MUTEX(adom_mutex);
++
++static ssize_t adomain_write(struct file * file, char const __user * buf,
++			     size_t count, loff_t * offset)
++{
++	char *tmpbuf;
++	char *startp, *endp;
++	int i;
++	unsigned long val;
++	ssize_t retval = count;
++
++	if (*offset)
++		return -EINVAL;
++	if (count > TMPBUFSIZE - 1)
++		return -EINVAL;
++
++	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++		return -ENOMEM;
++
++	if (copy_from_user(tmpbuf, buf, count)) {
++		kfree(tmpbuf);
++		return -EFAULT;
++	}
++	tmpbuf[count] = 0;
++
++	mutex_lock(&adom_mutex);
++
++	startp = tmpbuf;
++	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++		val = simple_strtoul(startp, &endp, 0);
++		if (endp == startp)
++			break;
++		while (ispunct(*endp) || isspace(*endp))
++			endp++;
++		active_domains[i] = val;
++		if (active_domains[i] != val)
++			/* Overflow, force error below */
++			i = MAX_OPROF_DOMAINS + 1;
++		startp = endp;
++	}
++	/* Force error on trailing junk */
++	adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++	kfree(tmpbuf);
++
++	if (adomains > MAX_OPROF_DOMAINS
++	    || oprofile_set_active(active_domains, adomains)) {
++		adomains = 0;
++		retval = -EINVAL;
++	}
++
++	mutex_unlock(&adom_mutex);
++	return retval;
++}
++
++static ssize_t adomain_read(struct file * file, char __user * buf,
++			    size_t count, loff_t * offset)
++{
++	char * tmpbuf;
++	size_t len;
++	int i;
++	ssize_t retval;
++
++	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++		return -ENOMEM;
++
++	mutex_lock(&adom_mutex);
++
++	len = 0;
++	for (i = 0; i < adomains; i++)
++		len += snprintf(tmpbuf + len,
++				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++				"%u ", active_domains[i]);
++	WARN_ON(len > TMPBUFSIZE);
++	if (len != 0 && len <= TMPBUFSIZE)
++		tmpbuf[len-1] = '\n';
++
++	mutex_unlock(&adom_mutex);
++
++	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++	kfree(tmpbuf);
++	return retval;
++}
++
++
++static const struct file_operations active_domain_ops = {
++	.read		= adomain_read,
++	.write		= adomain_write,
++};
++
++static unsigned int pdomains = 0;
++static int passive_domains[MAX_OPROF_DOMAINS];
++static DEFINE_MUTEX(pdom_mutex);
++
++static ssize_t pdomain_write(struct file * file, char const __user * buf,
++			     size_t count, loff_t * offset)
++{
++	char *tmpbuf;
++	char *startp, *endp;
++	int i;
++	unsigned long val;
++	ssize_t retval = count;
++
++	if (*offset)
++		return -EINVAL;
++	if (count > TMPBUFSIZE - 1)
++		return -EINVAL;
++
++	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++		return -ENOMEM;
++
++	if (copy_from_user(tmpbuf, buf, count)) {
++		kfree(tmpbuf);
++		return -EFAULT;
++	}
++	tmpbuf[count] = 0;
++
++	mutex_lock(&pdom_mutex);
++
++	startp = tmpbuf;
++	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++		val = simple_strtoul(startp, &endp, 0);
++		if (endp == startp)
++			break;
++		while (ispunct(*endp) || isspace(*endp))
++			endp++;
++		passive_domains[i] = val;
++		if (passive_domains[i] != val)
++			/* Overflow, force error below */
++			i = MAX_OPROF_DOMAINS + 1;
++		startp = endp;
++	}
++	/* Force error on trailing junk */
++	pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++	kfree(tmpbuf);
++
++	if (pdomains > MAX_OPROF_DOMAINS
++	    || oprofile_set_passive(passive_domains, pdomains)) {
++		pdomains = 0;
++		retval = -EINVAL;
++	}
++
++	mutex_unlock(&pdom_mutex);
++	return retval;
++}
++
++static ssize_t pdomain_read(struct file * file, char __user * buf,
++			    size_t count, loff_t * offset)
++{
++	char * tmpbuf;
++	size_t len;
++	int i;
++	ssize_t retval;
++
++	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++		return -ENOMEM;
++
++	mutex_lock(&pdom_mutex);
++
++	len = 0;
++	for (i = 0; i < pdomains; i++)
++		len += snprintf(tmpbuf + len,
++				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++				"%u ", passive_domains[i]);
++	WARN_ON(len > TMPBUFSIZE);
++	if (len != 0 && len <= TMPBUFSIZE)
++		tmpbuf[len-1] = '\n';
++
++	mutex_unlock(&pdom_mutex);
++
++	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++	kfree(tmpbuf);
++	return retval;
++}
++
++static const struct file_operations passive_domain_ops = {
++	.read		= pdomain_read,
++	.write		= pdomain_write,
++};
++
+ void oprofile_create_files(struct super_block *sb, struct dentry *root)
+ {
+ 	/* reinitialize default values */
+@@ -175,6 +370,8 @@ void oprofile_create_files(struct super_
+ 
+ 	oprofilefs_create_file(sb, root, "enable", &enable_fops);
+ 	oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
++	oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
++	oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops);
+ 	oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
+ 	oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size);
+ 	oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed);
+--- sle11sp1-2010-01-20.orig/fs/aio.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/fs/aio.c	2009-12-04 10:44:41.000000000 +0100
+@@ -36,6 +36,11 @@
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+ 
++#ifdef CONFIG_EPOLL
++#include <linux/poll.h>
++#include <linux/eventpoll.h>
++#endif
++
+ #if DEBUG > 1
+ #define dprintk		printk
+ #else
+@@ -992,6 +997,11 @@ put_rq:
+ 	if (waitqueue_active(&ctx->wait))
+ 		wake_up(&ctx->wait);
+ 
++#ifdef CONFIG_EPOLL
++	if (ctx->file && waitqueue_active(&ctx->poll_wait))
++		wake_up(&ctx->poll_wait);
++#endif
++
+ 	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+ 	return ret;
+ }
+@@ -1000,6 +1010,8 @@ EXPORT_SYMBOL(aio_complete);
+ /* aio_read_evt
+  *	Pull an event off of the ioctx's event ring.  Returns the number of 
+  *	events fetched (0 or 1 ;-)
++ *	If ent parameter is 0, just returns the number of events that would
++ *	be fetched.
+  *	FIXME: make this use cmpxchg.
+  *	TODO: make the ringbuffer user mmap()able (requires FIXME).
+  */
+@@ -1022,13 +1034,18 @@ static int aio_read_evt(struct kioctx *i
+ 
+ 	head = ring->head % info->nr;
+ 	if (head != ring->tail) {
+-		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
+-		*ent = *evp;
+-		head = (head + 1) % info->nr;
+-		smp_mb(); /* finish reading the event before updatng the head */
+-		ring->head = head;
+-		ret = 1;
+-		put_aio_ring_event(evp, KM_USER1);
++		if (ent) { /* event requested */
++			struct io_event *evp =
++				aio_ring_event(info, head, KM_USER1);
++			*ent = *evp;
++			head = (head + 1) % info->nr;
++			/* finish reading the event before updatng the head */
++			smp_mb();
++			ring->head = head;
++			ret = 1;
++			put_aio_ring_event(evp, KM_USER1);
++		} else /* only need to know availability */
++			ret = 1;
+ 	}
+ 	spin_unlock(&info->ring_lock);
+ 
+@@ -1213,6 +1230,13 @@ static void io_destroy(struct kioctx *io
+ 
+ 	aio_cancel_all(ioctx);
+ 	wait_for_all_aios(ioctx);
++#ifdef CONFIG_EPOLL
++	/* forget the poll file, but it's up to the user to close it */
++	if (ioctx->file) {
++		ioctx->file->private_data = 0;
++		ioctx->file = 0;
++	}
++#endif
+ 
+ 	/*
+ 	 * Wake up any waiters.  The setting of ctx->dead must be seen
+@@ -1223,6 +1247,67 @@ static void io_destroy(struct kioctx *io
+ 	put_ioctx(ioctx);	/* once for the lookup */
+ }
+ 
++#ifdef CONFIG_EPOLL
++
++static int aio_queue_fd_close(struct inode *inode, struct file *file)
++{
++	struct kioctx *ioctx = file->private_data;
++	if (ioctx) {
++		file->private_data = 0;
++		spin_lock_irq(&ioctx->ctx_lock);
++		ioctx->file = 0;
++		spin_unlock_irq(&ioctx->ctx_lock);
++	}
++	return 0;
++}
++
++static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
++{	unsigned int pollflags = 0;
++	struct kioctx *ioctx = file->private_data;
++
++	if (ioctx) {
++
++		spin_lock_irq(&ioctx->ctx_lock);
++		/* Insert inside our poll wait queue */
++		poll_wait(file, &ioctx->poll_wait, wait);
++
++		/* Check our condition */
++		if (aio_read_evt(ioctx, 0))
++			pollflags = POLLIN | POLLRDNORM;
++		spin_unlock_irq(&ioctx->ctx_lock);
++	}
++
++	return pollflags;
++}
++
++static const struct file_operations aioq_fops = {
++	.release	= aio_queue_fd_close,
++	.poll		= aio_queue_fd_poll
++};
++
++/* make_aio_fd:
++ *  Create a file descriptor that can be used to poll the event queue.
++ *  Based and piggybacked on the excellent epoll code.
++ */
++
++static int make_aio_fd(struct kioctx *ioctx)
++{
++	int error, fd;
++	struct inode *inode;
++	struct file *file;
++
++	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
++	if (error)
++		return error;
++
++	/* associate the file with the IO context */
++	file->private_data = ioctx;
++	ioctx->file = file;
++	init_waitqueue_head(&ioctx->poll_wait);
++	return fd;
++}
++#endif
++
+ /* sys_io_setup:
+  *	Create an aio_context capable of receiving at least nr_events.
+  *	ctxp must not point to an aio_context that already exists, and
+@@ -1235,18 +1320,30 @@ static void io_destroy(struct kioctx *io
+  *	resources are available.  May fail with -EFAULT if an invalid
+  *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
+  *	implemented.
++ *
++ *	To request a selectable fd, the user context has to be initialized
++ *	to 1, instead of 0, and the return value is the fd.
++ *	This keeps the system call compatible, since a non-zero value
++ *	was not allowed so far.
+  */
+ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
+ {
+ 	struct kioctx *ioctx = NULL;
+ 	unsigned long ctx;
+ 	long ret;
++	int make_fd = 0;
+ 
+ 	ret = get_user(ctx, ctxp);
+ 	if (unlikely(ret))
+ 		goto out;
+ 
+ 	ret = -EINVAL;
++#ifdef CONFIG_EPOLL
++	if (ctx == 1) {
++		make_fd = 1;
++		ctx = 0;
++	}
++#endif
+ 	if (unlikely(ctx || nr_events == 0)) {
+ 		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
+ 		         ctx, nr_events);
+@@ -1257,8 +1354,12 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_e
+ 	ret = PTR_ERR(ioctx);
+ 	if (!IS_ERR(ioctx)) {
+ 		ret = put_user(ioctx->user_id, ctxp);
+-		if (!ret)
+-			return 0;
++#ifdef CONFIG_EPOLL
++		if (make_fd && ret >= 0)
++			ret = make_aio_fd(ioctx);
++#endif
++		if (ret >= 0)
++			return ret;
+ 
+ 		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
+ 		io_destroy(ioctx);
+--- sle11sp1-2010-01-20.orig/fs/compat_ioctl.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/fs/compat_ioctl.c	2010-01-18 15:23:12.000000000 +0100
+@@ -115,6 +115,13 @@
+ #include <asm/fbio.h>
+ #endif
+ 
++#ifdef CONFIG_XEN
++#include <xen/interface/xen.h>
++#include <xen/public/evtchn.h>
++#include <xen/public/privcmd.h>
++#include <xen/compat_ioctl.h>
++#endif
++
+ static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
+ 			      unsigned long arg, struct file *f)
+ {
+@@ -2726,6 +2733,19 @@ IGNORE_IOCTL(FBIOGETCMAP32)
+ IGNORE_IOCTL(FBIOSCURSOR32)
+ IGNORE_IOCTL(FBIOGCURSOR32)
+ #endif
++
++#ifdef CONFIG_XEN
++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32)
++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32)
++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_V2_32, privcmd_ioctl_32)
++COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_UNBOUND_PORT)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_UNBIND)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_NOTIFY)
++COMPATIBLE_IOCTL(IOCTL_EVTCHN_RESET)
++#endif
+ };
+ 
+ #define IOCTL_HASHSIZE 256
+--- sle11sp1-2010-01-20.orig/include/acpi/processor.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/acpi/processor.h	2009-12-04 10:44:41.000000000 +0100
+@@ -17,6 +17,12 @@
+ #define ACPI_PROCESSOR_MAX_THROTTLE	250	/* 25% */
+ #define ACPI_PROCESSOR_MAX_DUTY_WIDTH	4
+ 
++#ifdef CONFIG_XEN
++#define NR_ACPI_CPUS			(NR_CPUS < 256 ? 256 : NR_CPUS)
++#else
++#define NR_ACPI_CPUS			NR_CPUS
++#endif /* CONFIG_XEN */
++
+ #define ACPI_PDC_REVISION_ID		0x1
+ 
+ #define ACPI_PSD_REV0_REVISION		0	/* Support for _PSD as in ACPI 3.0 */
+@@ -42,6 +48,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;
+@@ -74,6 +91,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;
+ 	char desc[ACPI_CX_DESC_LEN];
+@@ -304,6 +327,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;
+@@ -316,6 +342,7 @@ static inline int acpi_processor_ppc_has
+ 	}
+ 	return 0;
+ }
++#endif				/* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
+ #endif				/* CONFIG_CPU_FREQ */
+ 
+ /* in processor_throttling.c */
+@@ -353,4 +380,120 @@ 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 type);
++};
++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 */
++
++#ifdef CONFIG_XEN
++static inline void xen_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 inline void xen_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 inline void xen_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;
++}
++
++#endif /* CONFIG_XEN */
++
+ #endif
+--- sle11sp1-2010-01-20.orig/include/asm-generic/pgtable.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/asm-generic/pgtable.h	2009-12-04 10:44:41.000000000 +0100
+@@ -99,6 +99,10 @@ static inline void ptep_set_wrprotect(st
+ }
+ #endif
+ 
++#ifndef arch_change_pte_range
++#define arch_change_pte_range(mm, pmd, addr, end, newprot) 0
++#endif
++
+ #ifndef __HAVE_ARCH_PTE_SAME
+ #define pte_same(A,B)	(pte_val(A) == pte_val(B))
+ #endif
+--- sle11sp1-2010-01-20.orig/include/linux/aio.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/aio.h	2009-12-04 10:44:41.000000000 +0100
+@@ -201,6 +201,12 @@ struct kioctx {
+ 
+ 	struct delayed_work	wq;
+ 
++#ifdef CONFIG_EPOLL
++	/* poll integration */
++	wait_queue_head_t       poll_wait;
++	struct file		*file;
++#endif
++
+ 	struct rcu_head		rcu_head;
+ };
+ 
+--- sle11sp1-2010-01-20.orig/include/linux/highmem.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/highmem.h	2009-12-04 10:44:41.000000000 +0100
+@@ -130,12 +130,14 @@ alloc_zeroed_user_highpage_movable(struc
+ 	return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
+ }
+ 
++#ifndef __HAVE_ARCH_CLEAR_HIGHPAGE
+ static inline void clear_highpage(struct page *page)
+ {
+ 	void *kaddr = kmap_atomic(page, KM_USER0);
+ 	clear_page(kaddr);
+ 	kunmap_atomic(kaddr, KM_USER0);
+ }
++#endif
+ 
+ static inline void zero_user_segments(struct page *page,
+ 	unsigned start1, unsigned end1,
+@@ -189,6 +191,8 @@ static inline void copy_user_highpage(st
+ 
+ #endif
+ 
++#ifndef __HAVE_ARCH_COPY_HIGHPAGE
++
+ static inline void copy_highpage(struct page *to, struct page *from)
+ {
+ 	char *vfrom, *vto;
+@@ -200,4 +204,6 @@ static inline void copy_highpage(struct 
+ 	kunmap_atomic(vto, KM_USER1);
+ }
+ 
++#endif
++
+ #endif /* _LINUX_HIGHMEM_H */
+--- sle11sp1-2010-01-20.orig/include/linux/interrupt.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/interrupt.h	2009-12-04 10:44:41.000000000 +0100
+@@ -317,6 +317,12 @@ static inline int disable_irq_wake(unsig
+ }
+ #endif /* CONFIG_GENERIC_HARDIRQS */
+ 
++#ifdef CONFIG_HAVE_IRQ_IGNORE_UNHANDLED
++int irq_ignore_unhandled(unsigned int irq);
++#else
++#define irq_ignore_unhandled(irq) 0
++#endif
++
+ #ifndef __ARCH_SET_SOFTIRQ_PENDING
+ #define set_softirq_pending(x) (local_softirq_pending() = (x))
+ #define or_softirq_pending(x)  (local_softirq_pending() |= (x))
+--- sle11sp1-2010-01-20.orig/include/linux/kexec.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/kexec.h	2009-12-04 10:44:41.000000000 +0100
+@@ -46,6 +46,13 @@
+ 			    KEXEC_CORE_NOTE_NAME_BYTES +		\
+ 			    KEXEC_CORE_NOTE_DESC_BYTES )
+ 
++#ifndef KEXEC_ARCH_HAS_PAGE_MACROS
++#define kexec_page_to_pfn(page)  page_to_pfn(page)
++#define kexec_pfn_to_page(pfn)   pfn_to_page(pfn)
++#define kexec_virt_to_phys(addr) virt_to_phys(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(addr)
++#endif
++
+ /*
+  * This structure is used to hold the arguments that are used when loading
+  * kernel binaries.
+@@ -112,6 +119,12 @@ struct kimage {
+ extern void machine_kexec(struct kimage *image);
+ extern int machine_kexec_prepare(struct kimage *image);
+ extern void machine_kexec_cleanup(struct kimage *image);
++#ifdef CONFIG_XEN
++extern int xen_machine_kexec_load(struct kimage *image);
++extern void xen_machine_kexec_unload(struct kimage *image);
++extern void xen_machine_kexec_setup_resources(void);
++extern void xen_machine_kexec_register_resources(struct resource *res);
++#endif
+ extern asmlinkage long sys_kexec_load(unsigned long entry,
+ 					unsigned long nr_segments,
+ 					struct kexec_segment __user *segments,
+--- sle11sp1-2010-01-20.orig/include/linux/mm.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/mm.h	2009-12-04 10:44:41.000000000 +0100
+@@ -102,7 +102,12 @@ extern unsigned int kobjsize(const void 
+ 
+ #define VM_CAN_NONLINEAR 0x08000000	/* Has ->fault & does nonlinear pages */
+ #define VM_MIXEDMAP	0x10000000	/* Can contain "struct page" and pure PFN pages */
++#ifndef CONFIG_XEN
+ #define VM_SAO		0x20000000	/* Strong Access Ordering (powerpc) */
++#else
++#define VM_SAO		0
++#define VM_FOREIGN	0x20000000	/* Has pages belonging to another VM */
++#endif
+ #define VM_PFN_AT_MMAP	0x40000000	/* PFNMAP vma that is fully mapped at mmap time */
+ #define VM_MERGEABLE	0x80000000	/* KSM may merge identical pages */
+ 
+@@ -127,6 +132,12 @@ extern unsigned int kobjsize(const void 
+  */
+ #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
+ 
++#ifdef CONFIG_XEN
++struct vm_foreign_map {
++	struct page **map;
++};
++#endif
++
+ /*
+  * mapping from the currently active vm_flags protection bits (the
+  * low four bits) to a page protection mask..
+@@ -198,6 +209,15 @@ struct vm_operations_struct {
+ 	 */
+ 	int (*access)(struct vm_area_struct *vma, unsigned long addr,
+ 		      void *buf, int len, int write);
++
++	/* Area-specific function for clearing the PTE at @ptep. Returns the
++	 * original value of @ptep. */
++	pte_t (*zap_pte)(struct vm_area_struct *vma,
++			 unsigned long addr, pte_t *ptep, int is_fullmm);
++
++	/* called before close() to indicate no more pages should be mapped */
++	void (*unmap)(struct vm_area_struct *area);
++
+ #ifdef CONFIG_NUMA
+ 	/*
+ 	 * set_policy() op must add a reference to any non-NULL @new mempolicy
+--- sle11sp1-2010-01-20.orig/include/linux/oprofile.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/oprofile.h	2009-12-04 10:44:41.000000000 +0100
+@@ -16,6 +16,8 @@
+ #include <linux/types.h>
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
++
++#include <xen/interface/xenoprof.h>
+  
+ /* Each escaped entry is prefixed by ESCAPE_CODE
+  * then one of the following codes, then the
+@@ -28,14 +30,18 @@
+ #define CPU_SWITCH_CODE			2
+ #define COOKIE_SWITCH_CODE		3
+ #define KERNEL_ENTER_SWITCH_CODE	4
+-#define KERNEL_EXIT_SWITCH_CODE		5
++#define USER_ENTER_SWITCH_CODE		5
+ #define MODULE_LOADED_CODE		6
+ #define CTX_TGID_CODE			7
+ #define TRACE_BEGIN_CODE		8
+ #define TRACE_END_CODE			9
+ #define XEN_ENTER_SWITCH_CODE		10
++#ifndef CONFIG_XEN
+ #define SPU_PROFILING_CODE		11
+ #define SPU_CTX_SWITCH_CODE		12
++#else
++#define DOMAIN_SWITCH_CODE		11
++#endif
+ #define IBS_FETCH_CODE			13
+ #define IBS_OP_CODE			14
+ 
+@@ -49,6 +55,11 @@ struct oprofile_operations {
+ 	/* create any necessary configuration files in the oprofile fs.
+ 	 * Optional. */
+ 	int (*create_files)(struct super_block * sb, struct dentry * root);
++	/* setup active domains with Xen */
++	int (*set_active)(int *active_domains, unsigned int adomains);
++	/* setup passive domains with Xen */
++	int (*set_passive)(int *passive_domains, unsigned int pdomains);
++
+ 	/* Do any necessary interrupt setup. Optional. */
+ 	int (*setup)(void);
+ 	/* Do any necessary interrupt shutdown. Optional. */
+@@ -110,6 +121,9 @@ void oprofile_add_pc(unsigned long pc, i
+ /* add a backtrace entry, to be called from the ->backtrace callback */
+ void oprofile_add_trace(unsigned long eip);
+ 
++/* add a domain switch entry */
++int oprofile_add_domain_switch(int32_t domain_id);
++
+ 
+ /**
+  * Create a file of the given name as a child of the given root, with
+--- sle11sp1-2010-01-20.orig/include/linux/page-flags.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/page-flags.h	2009-12-16 11:48:10.000000000 +0100
+@@ -110,6 +110,11 @@ enum pageflags {
+ #ifdef CONFIG_MEMORY_FAILURE
+ 	PG_hwpoison,		/* hardware poisoned page. Don't touch */
+ #endif
++#ifdef CONFIG_XEN
++	PG_foreign,		/* Page is owned by foreign allocator. */
++	PG_netback,		/* Page is owned by netback */
++	PG_blkback,		/* Page is owned by blkback */
++#endif
+ 	__NR_PAGEFLAGS,
+ 
+ 	/* Filesystems */
+@@ -339,6 +344,27 @@ static inline void SetPageUptodate(struc
+ 
+ CLEARPAGEFLAG(Uptodate, uptodate)
+ 
++#define PageForeign(page)	test_bit(PG_foreign, &(page)->flags)
++#define SetPageForeign(_page, dtor) do {		\
++	set_bit(PG_foreign, &(_page)->flags);		\
++	BUG_ON((dtor) == (void (*)(struct page *, unsigned int))0); \
++	(_page)->index = (long)(dtor);			\
++} while (0)
++#define ClearPageForeign(page) do {			\
++	clear_bit(PG_foreign, &(page)->flags);		\
++	(page)->index = 0;				\
++} while (0)
++#define PageForeignDestructor(_page, order)		\
++	((void (*)(struct page *, unsigned int))(_page)->index)(_page, order)
++
++#define PageNetback(page)       test_bit(PG_netback, &(page)->flags)
++#define SetPageNetback(page)    set_bit(PG_netback, &(page)->flags)
++#define ClearPageNetback(page)  clear_bit(PG_netback, &(page)->flags)
++
++#define PageBlkback(page)       test_bit(PG_blkback, &(page)->flags)
++#define SetPageBlkback(page)    set_bit(PG_blkback, &(page)->flags)
++#define ClearPageBlkback(page)  clear_bit(PG_blkback, &(page)->flags)
++
+ extern void cancel_dirty_page(struct page *page, unsigned int account_size);
+ 
+ int test_clear_page_writeback(struct page *page);
+@@ -415,6 +441,14 @@ PAGEFLAG_FALSE(MemError)
+ #define __PG_MLOCKED		0
+ #endif
+ 
++#if !defined(CONFIG_XEN)
++# define __PG_XEN		0
++#elif defined(CONFIG_X86)
++# define __PG_XEN		((1 << PG_pinned) | (1 << PG_foreign))
++#else
++# define __PG_XEN		(1 << PG_foreign)
++#endif
++
+ /*
+  * Flags checked when a page is freed.  Pages being freed should not have
+  * these flags set.  It they are, there is a problem.
+@@ -424,7 +458,8 @@ PAGEFLAG_FALSE(MemError)
+ 	 1 << PG_private | 1 << PG_private_2 | \
+ 	 1 << PG_buddy	 | 1 << PG_writeback | 1 << PG_reserved | \
+ 	 1 << PG_slab	 | 1 << PG_swapcache | 1 << PG_active | \
+-	 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | 1 << PG_waiters)
++	 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | \
++	 __PG_XEN | 1 << PG_waiters)
+ 
+ /*
+  * Flags checked when a page is prepped for return by the page allocator.
+--- sle11sp1-2010-01-20.orig/include/linux/pci.h	2009-12-04 10:27:46.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/pci.h	2009-12-04 10:44:41.000000000 +0100
+@@ -877,6 +877,11 @@ static inline int pci_msi_enabled(void)
+ {
+ 	return 0;
+ }
++
++#ifdef CONFIG_XEN
++#define register_msi_get_owner(func) 0
++#define unregister_msi_get_owner(func) 0
++#endif
+ #else
+ extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
+ extern void pci_msi_shutdown(struct pci_dev *dev);
+@@ -889,6 +894,10 @@ extern void pci_disable_msix(struct pci_
+ extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+ extern void pci_restore_msi_state(struct pci_dev *dev);
+ extern int pci_msi_enabled(void);
++#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
+ 
+ #ifndef CONFIG_PCIEASPM
+--- sle11sp1-2010-01-20.orig/include/linux/skbuff.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/skbuff.h	2009-12-07 12:13:58.000000000 +0100
+@@ -278,6 +278,8 @@ typedef unsigned char *sk_buff_data_t;
+  *	@local_df: allow local fragmentation
+  *	@cloned: Head may be cloned (check refcnt to be sure)
+  *	@nohdr: Payload reference only, must not modify header
++ *	@proto_data_valid: Protocol data validated since arriving at localhost
++ *	@proto_csum_blank: Protocol csum must be added before leaving localhost
+  *	@pkt_type: Packet class
+  *	@fclone: skbuff clone status
+  *	@ip_summed: Driver fed us an IP checksum
+@@ -382,9 +384,13 @@ struct sk_buff {
+ #ifdef	CONFIG_NETVM
+ 	__u8			emergency:1;
+ #endif
++#ifdef CONFIG_XEN
++	__u8			proto_data_valid:1,
++				proto_csum_blank:1;
++#endif
+ 	kmemcheck_bitfield_end(flags2);
+ 
+-	/* 0/14 bit hole */
++	/* 0/9...15 bit hole */
+ 
+ #ifdef CONFIG_NET_DMA
+ 	dma_cookie_t		dma_cookie;
+--- sle11sp1-2010-01-20.orig/include/linux/vermagic.h	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/vermagic.h	2009-12-04 10:44:41.000000000 +0100
+@@ -22,6 +22,11 @@
+ #else
+ #define MODULE_VERMAGIC_MODVERSIONS ""
+ #endif
++#ifdef CONFIG_XEN
++#define MODULE_VERMAGIC_XEN "Xen "
++#else
++#define MODULE_VERMAGIC_XEN
++#endif
+ #ifndef MODULE_ARCH_VERMAGIC
+ #define MODULE_ARCH_VERMAGIC ""
+ #endif
+@@ -30,5 +35,5 @@
+ 	UTS_RELEASE " "							\
+ 	MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT 			\
+ 	MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS	\
+-	MODULE_ARCH_VERMAGIC
++	MODULE_VERMAGIC_XEN MODULE_ARCH_VERMAGIC
+ 
+--- sle11sp1-2010-01-20.orig/kernel/irq/spurious.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/kernel/irq/spurious.c	2009-12-04 10:44:41.000000000 +0100
+@@ -245,7 +245,7 @@ void note_interrupt(unsigned int irq, st
+ 		 */
+ 		if (time_after(jiffies, desc->last_unhandled + HZ/10))
+ 			desc->irqs_unhandled = 1;
+-		else
++		else if (!irq_ignore_unhandled(irq))
+ 			desc->irqs_unhandled++;
+ 		desc->last_unhandled = jiffies;
+ 		if (unlikely(action_ret != IRQ_NONE))
+--- sle11sp1-2010-01-20.orig/kernel/kexec.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/kernel/kexec.c	2009-12-04 10:44:41.000000000 +0100
+@@ -360,13 +360,26 @@ static int kimage_is_destination_range(s
+ 	return 0;
+ }
+ 
+-static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
++static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order, unsigned long limit)
+ {
+ 	struct page *pages;
+ 
+ 	pages = alloc_pages(gfp_mask, order);
+ 	if (pages) {
+ 		unsigned int count, i;
++#ifdef CONFIG_XEN
++		int address_bits;
++
++		if (limit == ~0UL)
++			address_bits = BITS_PER_LONG;
++		else
++			address_bits = long_log2(limit);
++
++		if (xen_limit_pages_to_max_mfn(pages, order, address_bits) < 0) {
++			__free_pages(pages, order);
++			return NULL;
++		}
++#endif
+ 		pages->mapping = NULL;
+ 		set_page_private(pages, order);
+ 		count = 1 << order;
+@@ -430,10 +443,10 @@ static struct page *kimage_alloc_normal_
+ 	do {
+ 		unsigned long pfn, epfn, addr, eaddr;
+ 
+-		pages = kimage_alloc_pages(GFP_KERNEL, order);
++		pages = kimage_alloc_pages(GFP_KERNEL, order, KEXEC_CONTROL_MEMORY_LIMIT);
+ 		if (!pages)
+ 			break;
+-		pfn   = page_to_pfn(pages);
++		pfn   = kexec_page_to_pfn(pages);
+ 		epfn  = pfn + count;
+ 		addr  = pfn << PAGE_SHIFT;
+ 		eaddr = epfn << PAGE_SHIFT;
+@@ -467,6 +480,7 @@ static struct page *kimage_alloc_normal_
+ 	return pages;
+ }
+ 
++#ifndef CONFIG_XEN
+ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+ 						      unsigned int order)
+ {
+@@ -520,7 +534,7 @@ static struct page *kimage_alloc_crash_c
+ 		}
+ 		/* If I don't overlap any segments I have found my hole! */
+ 		if (i == image->nr_segments) {
+-			pages = pfn_to_page(hole_start >> PAGE_SHIFT);
++			pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
+ 			break;
+ 		}
+ 	}
+@@ -547,6 +561,13 @@ struct page *kimage_alloc_control_pages(
+ 
+ 	return pages;
+ }
++#else /* !CONFIG_XEN */
++struct page *kimage_alloc_control_pages(struct kimage *image,
++					 unsigned int order)
++{
++	return kimage_alloc_normal_control_pages(image, order);
++}
++#endif
+ 
+ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+ {
+@@ -562,7 +583,7 @@ static int kimage_add_entry(struct kimag
+ 			return -ENOMEM;
+ 
+ 		ind_page = page_address(page);
+-		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
++		*image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
+ 		image->entry = ind_page;
+ 		image->last_entry = ind_page +
+ 				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+@@ -621,13 +642,13 @@ static void kimage_terminate(struct kima
+ #define for_each_kimage_entry(image, ptr, entry) \
+ 	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+ 		ptr = (entry & IND_INDIRECTION)? \
+-			phys_to_virt((entry & PAGE_MASK)): ptr +1)
++			kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
+ 
+ static void kimage_free_entry(kimage_entry_t entry)
+ {
+ 	struct page *page;
+ 
+-	page = pfn_to_page(entry >> PAGE_SHIFT);
++	page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
+ 	kimage_free_pages(page);
+ }
+ 
+@@ -639,6 +660,10 @@ static void kimage_free(struct kimage *i
+ 	if (!image)
+ 		return;
+ 
++#ifdef CONFIG_XEN
++	xen_machine_kexec_unload(image);
++#endif
++
+ 	kimage_free_extra_pages(image);
+ 	for_each_kimage_entry(image, ptr, entry) {
+ 		if (entry & IND_INDIRECTION) {
+@@ -714,7 +739,7 @@ static struct page *kimage_alloc_page(st
+ 	 * have a match.
+ 	 */
+ 	list_for_each_entry(page, &image->dest_pages, lru) {
+-		addr = page_to_pfn(page) << PAGE_SHIFT;
++		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+ 		if (addr == destination) {
+ 			list_del(&page->lru);
+ 			return page;
+@@ -725,16 +750,16 @@ static struct page *kimage_alloc_page(st
+ 		kimage_entry_t *old;
+ 
+ 		/* Allocate a page, if we run out of memory give up */
+-		page = kimage_alloc_pages(gfp_mask, 0);
++		page = kimage_alloc_pages(gfp_mask, 0, KEXEC_SOURCE_MEMORY_LIMIT);
+ 		if (!page)
+ 			return NULL;
+ 		/* If the page cannot be used file it away */
+-		if (page_to_pfn(page) >
++		if (kexec_page_to_pfn(page) >
+ 				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+ 			list_add(&page->lru, &image->unuseable_pages);
+ 			continue;
+ 		}
+-		addr = page_to_pfn(page) << PAGE_SHIFT;
++		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+ 
+ 		/* If it is the destination page we want use it */
+ 		if (addr == destination)
+@@ -757,7 +782,7 @@ static struct page *kimage_alloc_page(st
+ 			struct page *old_page;
+ 
+ 			old_addr = *old & PAGE_MASK;
+-			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
++			old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
+ 			copy_highpage(page, old_page);
+ 			*old = addr | (*old & ~PAGE_MASK);
+ 
+@@ -813,7 +838,7 @@ static int kimage_load_normal_segment(st
+ 			result  = -ENOMEM;
+ 			goto out;
+ 		}
+-		result = kimage_add_page(image, page_to_pfn(page)
++		result = kimage_add_page(image, kexec_page_to_pfn(page)
+ 								<< PAGE_SHIFT);
+ 		if (result < 0)
+ 			goto out;
+@@ -845,6 +870,7 @@ out:
+ 	return result;
+ }
+ 
++#ifndef CONFIG_XEN
+ static int kimage_load_crash_segment(struct kimage *image,
+ 					struct kexec_segment *segment)
+ {
+@@ -867,7 +893,7 @@ static int kimage_load_crash_segment(str
+ 		char *ptr;
+ 		size_t uchunk, mchunk;
+ 
+-		page = pfn_to_page(maddr >> PAGE_SHIFT);
++		page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
+ 		if (!page) {
+ 			result  = -ENOMEM;
+ 			goto out;
+@@ -916,6 +942,13 @@ static int kimage_load_segment(struct ki
+ 
+ 	return result;
+ }
++#else /* CONFIG_XEN */
++static int kimage_load_segment(struct kimage *image,
++				struct kexec_segment *segment)
++{
++	return kimage_load_normal_segment(image, segment);
++}
++#endif
+ 
+ /*
+  * Exec Kernel system call: for obvious reasons only root may call it.
+@@ -1019,6 +1052,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
+ 		}
+ 		kimage_terminate(image);
+ 	}
++#ifdef CONFIG_XEN
++	if (image) {
++		result = xen_machine_kexec_load(image);
++		if (result)
++			goto out;
++	}
++#endif
+ 	/* Install the new kernel, and  Uninstall the old */
+ 	image = xchg(dest_image, image);
+ 
+--- sle11sp1-2010-01-20.orig/kernel/sysctl.c	2010-01-07 09:36:42.000000000 +0100
++++ sle11sp1-2010-01-20/kernel/sysctl.c	2009-12-16 11:47:57.000000000 +0100
+@@ -876,7 +876,7 @@ static struct ctl_table kern_table[] = {
+ 		.proc_handler	= &proc_dointvec,
+ 	},
+ #endif
+-#if	defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
++#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) && !defined(CONFIG_ACPI_PV_SLEEP)
+ 	{
+ 		.procname	= "acpi_video_flags",
+ 		.data		= &acpi_realmode_flags,
+--- sle11sp1-2010-01-20.orig/mm/memory.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/mm/memory.c	2009-12-04 10:44:41.000000000 +0100
+@@ -526,6 +526,12 @@ struct page *vm_normal_page(struct vm_ar
+ {
+ 	unsigned long pfn = pte_pfn(pte);
+ 
++#if defined(CONFIG_XEN) && defined(CONFIG_X86)
++	/* XEN: Covers user-space grant mappings (even of local pages). */
++	if (unlikely(vma->vm_flags & VM_FOREIGN))
++		return NULL;
++#endif
++
+ 	if (HAVE_PTE_SPECIAL) {
+ 		if (likely(!pte_special(pte)))
+ 			goto check_pfn;
+@@ -557,6 +563,9 @@ struct page *vm_normal_page(struct vm_ar
+ 		return NULL;
+ check_pfn:
+ 	if (unlikely(pfn > highest_memmap_pfn)) {
++#ifdef CONFIG_XEN
++		if (!(vma->vm_flags & VM_RESERVED))
++#endif
+ 		print_bad_pte(vma, addr, pte, NULL);
+ 		return NULL;
+ 	}
+@@ -842,8 +851,12 @@ static unsigned long zap_pte_range(struc
+ 				     page->index > details->last_index))
+ 					continue;
+ 			}
+-			ptent = ptep_get_and_clear_full(mm, addr, pte,
+-							tlb->fullmm);
++			if (unlikely(vma->vm_ops && vma->vm_ops->zap_pte))
++				ptent = vma->vm_ops->zap_pte(vma, addr, pte,
++							     tlb->fullmm);
++			else
++				ptent = ptep_get_and_clear_full(mm, addr, pte,
++								tlb->fullmm);
+ 			tlb_remove_tlb_entry(tlb, pte, addr);
+ 			if (unlikely(!page))
+ 				continue;
+@@ -1103,6 +1116,7 @@ unsigned long zap_page_range(struct vm_a
+ 		tlb_finish_mmu(tlb, address, end);
+ 	return end;
+ }
++EXPORT_SYMBOL(zap_page_range);
+ 
+ /**
+  * zap_vma_ptes - remove ptes mapping the vma
+@@ -1299,6 +1313,28 @@ int __get_user_pages(struct task_struct 
+ 			continue;
+ 		}
+ 
++#ifdef CONFIG_XEN
++		if (vma && (vma->vm_flags & VM_FOREIGN)) {
++			struct vm_foreign_map *foreign_map =
++				vma->vm_private_data;
++			struct page **map = foreign_map->map;
++			int offset = (start - vma->vm_start) >> PAGE_SHIFT;
++			if (map[offset] != NULL) {
++			        if (pages) {
++			                struct page *page = map[offset];
++
++					pages[i] = page;
++					get_page(page);
++				}
++				if (vmas)
++					vmas[i] = vma;
++				i++;
++				start += PAGE_SIZE;
++				len--;
++				continue;
++			}
++		}
++#endif
+ 		if (!vma ||
+ 		    (vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
+ 		    !(vm_flags & vma->vm_flags))
+--- sle11sp1-2010-01-20.orig/mm/mmap.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/mm/mmap.c	2010-01-20 10:22:09.000000000 +0100
+@@ -1843,6 +1843,12 @@ static void unmap_region(struct mm_struc
+ 	tlb_finish_mmu(tlb, start, end);
+ }
+ 
++static inline void unmap_vma(struct vm_area_struct *vma)
++{
++	if (unlikely(vma->vm_ops && vma->vm_ops->unmap))
++		vma->vm_ops->unmap(vma);
++}
++
+ /*
+  * Create a list of vma's touched by the unmap, removing them from the mm's
+  * vma list as we go..
+@@ -1858,6 +1864,7 @@ detach_vmas_to_be_unmapped(struct mm_str
+ 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
+ 	do {
+ 		rb_erase(&vma->vm_rb, &mm->mm_rb);
++		unmap_vma(vma);
+ 		mm->map_count--;
+ 		tail_vma = vma;
+ 		vma = vma->vm_next;
+@@ -2152,6 +2159,9 @@ void exit_mmap(struct mm_struct *mm)
+ 
+ 	arch_exit_mmap(mm);
+ 
++	for (vma = mm->mmap; vma; vma = vma->vm_next)
++		unmap_vma(vma);
++
+ 	vma = mm->mmap;
+ 	if (!vma)	/* Can happen if dup_mmap() received an OOM */
+ 		return;
+--- sle11sp1-2010-01-20.orig/mm/mprotect.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/mm/mprotect.c	2009-12-04 10:44:41.000000000 +0100
+@@ -91,6 +91,8 @@ static inline void change_pmd_range(stru
+ 		next = pmd_addr_end(addr, end);
+ 		if (pmd_none_or_clear_bad(pmd))
+ 			continue;
++		if (arch_change_pte_range(mm, pmd, addr, next, newprot))
++			continue;
+ 		change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable);
+ 	} while (pmd++, addr = next, addr != end);
+ }
+--- sle11sp1-2010-01-20.orig/mm/page_alloc.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/mm/page_alloc.c	2009-12-04 10:44:41.000000000 +0100
+@@ -592,6 +592,13 @@ static void __free_pages_ok(struct page 
+ 	int bad = 0;
+ 	int wasMlocked = __TestClearPageMlocked(page);
+ 
++#ifdef CONFIG_XEN
++	if (PageForeign(page)) {
++		PageForeignDestructor(page, order);
++		return;
++	}
++#endif
++
+ 	kmemcheck_free_shadow(page, order);
+ 
+ 	trace_page_free(page, order);
+@@ -1093,6 +1100,13 @@ static void free_hot_cold_page(struct pa
+ 	int migratetype;
+ 	int wasMlocked = __TestClearPageMlocked(page);
+ 
++#ifdef CONFIG_XEN
++	if (PageForeign(page)) {
++		PageForeignDestructor(page, 0);
++		return;
++	}
++#endif
++
+ 	kmemcheck_free_shadow(page, 0);
+ 
+ 	trace_page_free(page, 0);
+--- sle11sp1-2010-01-20.orig/net/core/dev.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/net/core/dev.c	2009-12-04 10:44:41.000000000 +0100
+@@ -137,6 +137,12 @@
+ /* This should be increased if a protocol with a bigger head is added. */
+ #define GRO_MAX_HEAD (MAX_HEADER + 128)
+ 
++#ifdef CONFIG_XEN
++#include <net/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#endif
++
+ /*
+  *	The list of packet types we will receive (as opposed to discard)
+  *	and the routines to invoke.
+@@ -1817,6 +1823,43 @@ static struct netdev_queue *dev_pick_tx(
+ 	return netdev_get_tx_queue(dev, queue_index);
+ }
+ 
++#ifdef CONFIG_XEN
++inline int skb_checksum_setup(struct sk_buff *skb)
++{
++	if (skb->proto_csum_blank) {
++		if (skb->protocol != htons(ETH_P_IP))
++			goto out;
++		skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
++		if (skb->h.raw >= skb->tail)
++			goto out;
++		switch (skb->nh.iph->protocol) {
++		case IPPROTO_TCP:
++			skb->csum = offsetof(struct tcphdr, check);
++			break;
++		case IPPROTO_UDP:
++			skb->csum = offsetof(struct udphdr, check);
++			break;
++		default:
++			if (net_ratelimit())
++				printk(KERN_ERR "Attempting to checksum a non-"
++				       "TCP/UDP packet, dropping a protocol"
++				       " %d packet", skb->nh.iph->protocol);
++			goto out;
++		}
++		if ((skb->h.raw + skb->csum + 2) > skb->tail)
++			goto out;
++		skb->ip_summed = CHECKSUM_HW;
++		skb->proto_csum_blank = 0;
++	}
++	return 0;
++out:
++	return -EPROTO;
++}
++#else
++inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
++#endif
++EXPORT_SYMBOL(skb_checksum_setup);
++
+ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ 				 struct net_device *dev,
+ 				 struct netdev_queue *txq)
+@@ -1883,6 +1926,12 @@ int dev_queue_xmit(struct sk_buff *skb)
+ 	struct Qdisc *q;
+ 	int rc = -ENOMEM;
+ 
++ 	/* If a checksum-deferred packet is forwarded to a device that needs a
++ 	 * checksum, correct the pointers and force checksumming.
++ 	 */
++ 	if (skb_checksum_setup(skb))
++ 		goto out_kfree_skb;
++
+ 	/* GSO will handle the following emulations directly. */
+ 	if (netif_needs_gso(dev, skb))
+ 		goto gso;
+@@ -2380,6 +2429,19 @@ int netif_receive_skb(struct sk_buff *sk
+ 	}
+ #endif
+ 
++#ifdef CONFIG_XEN
++	switch (skb->ip_summed) {
++	case CHECKSUM_UNNECESSARY:
++		skb->proto_data_valid = 1;
++		break;
++	case CHECKSUM_HW:
++		/* XXX Implement me. */
++	default:
++		skb->proto_data_valid = 0;
++		break;
++	}
++#endif
++
+ 	if (skb_emergency(skb))
+ 		goto skip_taps;
+ 
+--- sle11sp1-2010-01-20.orig/net/core/skbuff.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/net/core/skbuff.c	2009-12-04 10:44:41.000000000 +0100
+@@ -642,6 +642,10 @@ static struct sk_buff *__skb_clone(struc
+ 	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
+ 	n->cloned = 1;
+ 	n->nohdr = 0;
++#ifdef CONFIG_XEN
++	C(proto_data_valid);
++	C(proto_csum_blank);
++#endif
+ 	n->destructor = NULL;
+ 	C(tail);
+ 	C(end);
+--- sle11sp1-2010-01-20.orig/net/ipv4/netfilter/nf_nat_proto_tcp.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/net/ipv4/netfilter/nf_nat_proto_tcp.c	2009-12-04 10:44:41.000000000 +0100
+@@ -75,6 +75,9 @@ tcp_manip_pkt(struct sk_buff *skb,
+ 	if (hdrsize < sizeof(*hdr))
+ 		return true;
+ 
++	if (skb_checksum_setup(skb))
++		return false;
++
+ 	inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ 	inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
+ 	return true;
+--- sle11sp1-2010-01-20.orig/net/ipv4/netfilter/nf_nat_proto_udp.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/net/ipv4/netfilter/nf_nat_proto_udp.c	2009-12-04 10:44:41.000000000 +0100
+@@ -60,6 +60,10 @@ udp_manip_pkt(struct sk_buff *skb,
+ 		newport = tuple->dst.u.udp.port;
+ 		portptr = &hdr->dest;
+ 	}
++
++	if (skb_checksum_setup(skb))
++		return false;
++
+ 	if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+ 		inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
+ 		inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
+--- sle11sp1-2010-01-20.orig/net/ipv4/xfrm4_output.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/net/ipv4/xfrm4_output.c	2009-12-04 10:44:41.000000000 +0100
+@@ -81,7 +81,7 @@ static int xfrm4_output_finish(struct sk
+ #endif
+ 
+ 	skb->protocol = htons(ETH_P_IP);
+-	return xfrm_output(skb);
++	return skb_checksum_setup(skb) ?: xfrm_output(skb);
+ }
+ 
+ int xfrm4_output(struct sk_buff *skb)
+--- sle11sp1-2010-01-20.orig/scripts/Makefile.build	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/scripts/Makefile.build	2009-12-04 10:44:41.000000000 +0100
+@@ -76,6 +76,21 @@ ifndef obj
+ $(warning kbuild: Makefile.build is included improperly)
+ endif
+ 
++ifeq ($(CONFIG_XEN),y)
++Makefile.xen := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(objtree)/scripts)/Makefile.xen
++$(Makefile.xen): $(srctree)/scripts/Makefile.xen.awk $(srctree)/scripts/Makefile.build
++	@echo '  Updating $@'
++	$(if $(shell echo a | $(AWK) '{ print gensub(/a/, "AA", "g"); }'),\
++        ,$(error 'Your awk program does not define gensub.  Use gawk or another awk with gensub'))
++	@$(AWK) -f $< $(filter-out $<,$^) >$@
++
++xen-src-single-used-m	:= $(patsubst $(srctree)/%,%,$(wildcard $(addprefix $(srctree)/,$(single-used-m:.o=-xen.c))))
++xen-single-used-m	:= $(xen-src-single-used-m:-xen.c=.o)
++single-used-m		:= $(filter-out $(xen-single-used-m),$(single-used-m))
++
++-include $(Makefile.xen)
++endif
++
+ # ===========================================================================
+ 
+ ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),)
+--- sle11sp1-2010-01-20.orig/scripts/Makefile.lib	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/scripts/Makefile.lib	2009-12-04 10:44:41.000000000 +0100
+@@ -22,6 +22,12 @@ obj-m := $(filter-out $(obj-y),$(obj-m))
+ 
+ lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
+ 
++# Remove objects forcibly disabled
++
++obj-y := $(filter-out $(disabled-obj-y),$(obj-y))
++obj-m := $(filter-out $(disabled-obj-y),$(obj-m))
++lib-y := $(filter-out $(disabled-obj-y),$(lib-y))
++
+ 
+ # Handle objects in subdirs
+ # ---------------------------------------------------------------------------
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/ipv6-no-autoconf
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/ipv6-no-autoconf
@@ -0,0 +1,37 @@
+From: Olaf Kirch <okir@suse.de>
+Subject: Allow to bring up network interface w/o ipv6 autoconf
+References: 161888
+
+When bringing up a xen bridge device, it will always be configured to
+use a MAC address of ff:ff:ff:ff:ff:fe.  This greatly confuses IPv6 DAD,
+which starts logging lots and lots of useless messages to syslog.
+
+We really want to disable IPv6 on these interfaces, and there doesn't
+seem to be a reliable way to do this without bringing the interface
+up first (and triggering IPv6 autoconf). 
+
+This patch makes autoconf (DAD and router discovery) depend on the
+interface's ability to do multicast. Turning off multicast for an
+interface before bringing it up will suppress autoconfiguration.
+
+ net/ipv6/addrconf.c |    2 ++
+ 1 files changed, 2 insertions(+)
+
+--- head-2009-12-04.orig/net/ipv6/addrconf.c	2009-12-04 10:25:14.000000000 +0100
++++ head-2009-12-04/net/ipv6/addrconf.c	2009-12-04 10:27:31.000000000 +0100
+@@ -2803,6 +2803,7 @@ static void addrconf_dad_start(struct in
+ 	spin_lock_bh(&ifp->lock);
+ 
+ 	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
++	    !(dev->flags&IFF_MULTICAST) ||
+ 	    idev->cnf.accept_dad < 1 ||
+ 	    !(ifp->flags&IFA_F_TENTATIVE) ||
+ 	    ifp->flags & IFA_F_NODAD) {
+@@ -2895,6 +2896,7 @@ static void addrconf_dad_completed(struc
+ 	if (ifp->idev->cnf.forwarding == 0 &&
+ 	    ifp->idev->cnf.rtr_solicits > 0 &&
+ 	    (dev->flags&IFF_LOOPBACK) == 0 &&
++	    (dev->flags & IFF_MULTICAST) &&
+ 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+ 		/*
+ 		 *	If a host as already performed a random delay
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-no-lapic
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-no-lapic
@@ -0,0 +1,374 @@
+From: jbeulich@novell.com
+Subject: Disallow all accesses to the local APIC page
+Patch-mainline: obsolete
+References: 191115
+
+--- head-2009-12-16.orig/arch/x86/include/asm/apic.h	2009-12-04 10:44:45.000000000 +0100
++++ head-2009-12-16/arch/x86/include/asm/apic.h	2009-10-13 17:19:31.000000000 +0200
+@@ -10,7 +10,9 @@
+ #include <asm/processor.h>
+ #include <asm/apicdef.h>
+ #include <asm/atomic.h>
++#ifndef CONFIG_XEN
+ #include <asm/fixmap.h>
++#endif
+ #include <asm/mpspec.h>
+ #include <asm/system.h>
+ #include <asm/msr.h>
+@@ -49,6 +51,7 @@ static inline void generic_apic_probe(vo
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 
+ extern unsigned int apic_verbosity;
++#ifndef CONFIG_XEN
+ extern int local_apic_timer_c2_ok;
+ 
+ extern int disable_apic;
+@@ -121,6 +124,8 @@ extern u64 native_apic_icr_read(void);
+ 
+ extern int x2apic_mode;
+ 
++#endif /* CONFIG_XEN */
++
+ #ifdef CONFIG_X86_X2APIC
+ /*
+  * Make previous memory operations globally visible before
+@@ -367,6 +372,8 @@ struct apic {
+  */
+ extern struct apic *apic;
+ 
++#ifndef CONFIG_XEN
++
+ /*
+  * APIC functionality to boot other CPUs - only used on SMP:
+  */
+@@ -460,6 +467,8 @@ static inline void default_wait_for_init
+ 
+ extern void generic_bigsmp_probe(void);
+ 
++#endif /* CONFIG_XEN */
++
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 
+@@ -479,6 +488,8 @@ static inline const struct cpumask *defa
+ DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
+ 
+ 
++#ifndef CONFIG_XEN
++
+ static inline unsigned int read_apic_id(void)
+ {
+ 	unsigned int reg;
+@@ -590,6 +601,8 @@ static inline physid_mask_t default_apic
+ 	return physid_mask_of_physid(phys_apicid);
+ }
+ 
++#endif /* CONFIG_XEN */
++
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ 
+ #ifdef CONFIG_X86_32
+--- head-2009-12-16.orig/arch/x86/include/asm/apicdef.h	2009-12-18 09:53:29.000000000 +0100
++++ head-2009-12-16/arch/x86/include/asm/apicdef.h	2009-10-14 17:01:50.000000000 +0200
+@@ -11,6 +11,8 @@
+ #define IO_APIC_DEFAULT_PHYS_BASE	0xfec00000
+ #define	APIC_DEFAULT_PHYS_BASE		0xfee00000
+ 
++#ifndef CONFIG_XEN
++
+ #define	APIC_ID		0x20
+ 
+ #define	APIC_LVR	0x30
+@@ -136,6 +138,16 @@
+ #define APIC_BASE_MSR	0x800
+ #define X2APIC_ENABLE	(1UL << 10)
+ 
++#else /* CONFIG_XEN */
++
++enum {
++	APIC_DEST_ALLBUT = 0x1,
++	APIC_DEST_SELF,
++	APIC_DEST_ALLINC
++};
++
++#endif /* CONFIG_XEN */
++
+ #ifdef CONFIG_X86_32
+ # define MAX_IO_APICS 64
+ #else
+@@ -143,6 +155,8 @@
+ # define MAX_LOCAL_APIC 32768
+ #endif
+ 
++#ifndef CONFIG_XEN
++
+ /*
+  * All x86-64 systems are xAPIC compatible.
+  * In the following, "apicid" is a physical APIC ID.
+@@ -413,6 +427,8 @@ struct local_apic {
+ 
+ #undef u32
+ 
++#endif /* CONFIG_XEN */
++
+ #ifdef CONFIG_X86_32
+  #define BAD_APICID 0xFFu
+ #else
+--- head-2009-12-16.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-16/arch/x86/include/mach-xen/asm/fixmap.h	2009-10-13 17:19:31.000000000 +0200
+@@ -17,7 +17,6 @@
+ #ifndef __ASSEMBLY__
+ #include <linux/kernel.h>
+ #include <asm/acpi.h>
+-#include <asm/apicdef.h>
+ #include <asm/page.h>
+ #ifdef CONFIG_X86_32
+ #include <linux/threads.h>
+@@ -82,10 +81,10 @@ enum fixed_addresses {
+ #endif
+ 	FIX_DBGP_BASE,
+ 	FIX_EARLYCON_MEM_BASE,
++#ifndef CONFIG_XEN
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+-#ifndef CONFIG_XEN
+ #ifdef CONFIG_X86_IO_APIC
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+--- head-2009-12-16.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:18:10.000000000 +0100
++++ head-2009-12-16/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:20:18.000000000 +0100
+@@ -15,7 +15,7 @@
+ #  include <asm/io_apic.h>
+ # endif
+ #endif
+-#include <asm/thread_info.h>
++#include <linux/thread_info.h>
+ #include <asm/cpumask.h>
+ 
+ extern int smp_num_siblings;
+@@ -168,7 +168,7 @@ extern unsigned disabled_cpus __cpuinitd
+ 
+ #include <asm/smp-processor-id.h>
+ 
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 
+ #ifndef CONFIG_X86_64
+ static inline int logical_smp_processor_id(void)
+--- head-2009-12-16.orig/arch/x86/kernel/acpi/boot.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/acpi/boot.c	2009-10-13 17:19:31.000000000 +0200
+@@ -71,13 +71,13 @@ int acpi_sci_override_gsi __initdata;
+ #ifndef CONFIG_XEN
+ int acpi_skip_timer_override __initdata;
+ int acpi_use_timer_override __initdata;
+-#else
+-#define acpi_skip_timer_override 0
+-#endif
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+ #endif
++#else
++#define acpi_skip_timer_override 0
++#endif
+ 
+ #ifndef __HAVE_ARCH_CMPXCHG
+ #warning ACPI uses CMPXCHG, i486 and later hardware
+@@ -136,6 +136,7 @@ static int __init acpi_parse_madt(struct
+ 		return -ENODEV;
+ 	}
+ 
++#ifndef CONFIG_XEN
+ 	if (madt->address) {
+ 		acpi_lapic_addr = (u64) madt->address;
+ 
+@@ -143,7 +144,6 @@ static int __init acpi_parse_madt(struct
+ 		       madt->address);
+ 	}
+ 
+-#ifndef CONFIG_XEN
+ 	default_acpi_madt_oem_check(madt->header.oem_id,
+ 				    madt->header.oem_table_id);
+ #endif
+@@ -244,6 +244,7 @@ static int __init
+ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
+ 			  const unsigned long end)
+ {
++#ifndef CONFIG_XEN
+ 	struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
+ 
+ 	lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
+@@ -252,6 +253,7 @@ acpi_parse_lapic_addr_ovr(struct acpi_su
+ 		return -EINVAL;
+ 
+ 	acpi_lapic_addr = lapic_addr_ovr->address;
++#endif
+ 
+ 	return 0;
+ }
+@@ -1055,7 +1057,7 @@ int mp_register_gsi(struct device *dev, 
+ 
+ 	ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
+ 
+-#ifdef CONFIG_X86_32
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+ 	if (ioapic_renumber_irq)
+ 		gsi = ioapic_renumber_irq(ioapic, gsi);
+ #endif
+--- head-2009-12-16.orig/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/apic/io_apic-xen.c	2009-10-14 17:01:38.000000000 +0200
+@@ -1093,7 +1093,9 @@ static inline int irq_trigger(int idx)
+ 	return MPBIOS_trigger(idx);
+ }
+ 
++#ifndef CONFIG_XEN
+ int (*ioapic_renumber_irq)(int ioapic, int irq);
++#endif
+ static int pin_2_irq(int idx, int apic, int pin)
+ {
+ 	int irq, i;
+@@ -1115,11 +1117,13 @@ static int pin_2_irq(int idx, int apic, 
+ 		while (i < apic)
+ 			irq += nr_ioapic_registers[i++];
+ 		irq += pin;
++#ifndef CONFIG_XEN
+ 		/*
+                  * For MPS mode, so far only needed by ES7000 platform
+                  */
+ 		if (ioapic_renumber_irq)
+ 			irq = ioapic_renumber_irq(apic, irq);
++#endif
+ 	}
+ 
+ #ifdef CONFIG_X86_32
+@@ -4025,10 +4029,12 @@ int io_apic_set_pci_routing(struct devic
+ u8 __init io_apic_unique_id(u8 id)
+ {
+ #ifdef CONFIG_X86_32
++#ifndef CONFIG_XEN
+ 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+ 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+ 		return io_apic_get_unique_id(nr_ioapics, id);
+ 	else
++#endif
+ 		return id;
+ #else
+ 	int i;
+--- head-2009-12-16.orig/arch/x86/kernel/irq-xen.c	2009-12-18 09:59:05.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/irq-xen.c	2009-12-18 10:14:24.000000000 +0100
+@@ -15,9 +15,9 @@
+ #include <asm/mce.h>
+ #include <asm/hw_irq.h>
+ 
++#ifndef CONFIG_XEN
+ atomic_t irq_err_count;
+ 
+-#ifndef CONFIG_XEN
+ /* Function pointer for generic interrupt vector handling */
+ void (*generic_interrupt_extension)(void) = NULL;
+ #endif
+@@ -57,7 +57,7 @@ static int show_other_interrupts(struct 
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
+ 	seq_printf(p, "  Non-maskable interrupts\n");
+-#ifdef CONFIG_X86_LOCAL_APIC
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+ 	seq_printf(p, "%*s: ", prec, "LOC");
+ 	for_each_online_cpu(j)
+ 		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
+@@ -122,10 +122,12 @@ static int show_other_interrupts(struct 
+ 		seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
+ 	seq_printf(p, "  Machine check polls\n");
+ #endif
++#ifndef CONFIG_XEN
+ 	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+ 	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
+ #endif
++#endif
+ 	return 0;
+ }
+ 
+@@ -221,12 +223,16 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
+ 
+ u64 arch_irq_stat(void)
+ {
++#ifndef CONFIG_XEN
+ 	u64 sum = atomic_read(&irq_err_count);
+ 
+ #ifdef CONFIG_X86_IO_APIC
+ 	sum += atomic_read(&irq_mis_count);
+ #endif
+ 	return sum;
++#else
++	return 0;
++#endif
+ }
+ 
+ 
+--- head-2009-12-16.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-16/arch/x86/kernel/mpparse-xen.c	2009-10-13 17:19:31.000000000 +0200
+@@ -288,7 +288,9 @@ static int __init smp_check_mpc(struct m
+ 
+ 	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+ 
++#ifndef CONFIG_XEN
+ 	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
++#endif
+ 
+ 	return 1;
+ }
+@@ -320,12 +322,14 @@ static int __init smp_read_mpc(struct mp
+ 	if (!smp_check_mpc(mpc, oem, str))
+ 		return 0;
+ 
+-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_32
+ 	generic_mps_oem_check(mpc, oem, str);
+ #endif
+ 	/* save the local APIC address, it might be non-default */
+ 	if (!acpi_lapic)
+ 		mp_lapic_addr = mpc->lapic;
++#endif
+ 
+ 	if (early)
+ 		return 1;
+@@ -519,10 +523,12 @@ static inline void __init construct_defa
+ 	int linttypes[2] = { mp_ExtINT, mp_NMI };
+ 	int i;
+ 
++#ifndef CONFIG_XEN
+ 	/*
+ 	 * local APIC has default address
+ 	 */
+ 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++#endif
+ 
+ 	/*
+ 	 * 2 CPUs, numbered 0 & 1.
+@@ -655,10 +661,12 @@ void __init default_get_smp_config(unsig
+ 	 */
+ 	if (mpf->feature1 != 0) {
+ 		if (early) {
++#ifndef CONFIG_XEN
+ 			/*
+ 			 * local APIC has default address
+ 			 */
+ 			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
++#endif
+ 			return;
+ 		}
+ 
+--- head-2009-12-16.orig/drivers/xen/core/smpboot.c	2009-11-06 11:10:22.000000000 +0100
++++ head-2009-12-16/drivers/xen/core/smpboot.c	2009-10-15 11:12:11.000000000 +0200
+@@ -354,7 +354,7 @@ void __init smp_prepare_cpus(unsigned in
+ 	 * Here we can be sure that there is an IO-APIC in the system. Let's
+ 	 * go and set it up:
+ 	 */
+-	if (!skip_ioapic_setup && nr_ioapics)
++	if (cpu_has_apic && !skip_ioapic_setup && nr_ioapics)
+ 		setup_IO_APIC();
+ #endif
+ }
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-blktap-write-barriers
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-blktap-write-barriers
@@ -0,0 +1,105 @@
+From: kwolf@suse.de
+Subject: blktap: Write Barriers
+Patch-mainline: obsolete
+
+--- head-2010-01-04.orig/drivers/xen/blktap/blktap.c	2010-01-04 12:41:47.000000000 +0100
++++ head-2010-01-04/drivers/xen/blktap/blktap.c	2010-01-04 13:22:24.000000000 +0100
+@@ -1366,6 +1366,9 @@ static int do_block_io_op(blkif_t *blkif
+ 			dispatch_rw_block_io(blkif, &req, pending_req);
+ 			break;
+ 
++		case BLKIF_OP_WRITE_BARRIER:
++			/* TODO Some counter? */
++			/* Fall through */
+ 		case BLKIF_OP_WRITE:
+ 			blkif->st_wr_req++;
+ 			dispatch_rw_block_io(blkif, &req, pending_req);
+@@ -1397,7 +1400,7 @@ static void dispatch_rw_block_io(blkif_t
+ 				 pending_req_t *pending_req)
+ {
+ 	extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+-	int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
++	int op, operation;
+ 	struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ 	unsigned int nseg;
+ 	int ret, i, nr_sects = 0;
+@@ -1409,6 +1412,21 @@ static void dispatch_rw_block_io(blkif_t
+ 	struct mm_struct *mm;
+ 	struct vm_area_struct *vma = NULL;
+ 
++	switch (req->operation) {
++	case BLKIF_OP_READ:
++		operation = READ;
++		break;
++	case BLKIF_OP_WRITE:
++		operation = WRITE;
++		break;
++	case BLKIF_OP_WRITE_BARRIER:
++		operation = WRITE_BARRIER;
++		break;
++	default:
++		operation = 0; /* make gcc happy */
++		BUG();
++	}
++
+ 	if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
+ 		goto fail_response;
+ 
+@@ -1448,7 +1466,7 @@ static void dispatch_rw_block_io(blkif_t
+ 
+ 	pending_req->blkif     = blkif;
+ 	pending_req->id        = req->id;
+-	pending_req->operation = operation;
++	pending_req->operation = req->operation;
+ 	pending_req->status    = BLKIF_RSP_OKAY;
+ 	pending_req->nr_pages  = nseg;
+ 	op = 0;
+@@ -1465,7 +1483,7 @@ static void dispatch_rw_block_io(blkif_t
+ 		kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i);
+ 
+ 		flags = GNTMAP_host_map;
+-		if (operation == WRITE)
++		if (operation != READ)
+ 			flags |= GNTMAP_readonly;
+ 		gnttab_set_map_op(&map[op], kvaddr, flags,
+ 				  req->seg[i].gref, blkif->domid);
+@@ -1482,7 +1500,7 @@ static void dispatch_rw_block_io(blkif_t
+ 
+ 			flags = GNTMAP_host_map | GNTMAP_application_map
+ 				| GNTMAP_contains_pte;
+-			if (operation == WRITE)
++			if (operation != READ)
+ 				flags |= GNTMAP_readonly;
+ 			gnttab_set_map_op(&map[op], ptep, flags,
+ 					  req->seg[i].gref, blkif->domid);
+--- head-2010-01-04.orig/drivers/xen/blktap/xenbus.c	2008-09-15 15:10:39.000000000 +0200
++++ head-2010-01-04/drivers/xen/blktap/xenbus.c	2009-05-19 10:10:06.000000000 +0200
+@@ -395,7 +395,28 @@ static void connect(struct backend_info 
+ 	int err;
+ 
+ 	struct xenbus_device *dev = be->dev;
++	struct xenbus_transaction xbt;
+ 
++	/* Write feature-barrier to xenstore */
++again:
++	err = xenbus_transaction_start(&xbt);
++	if (err) {
++		xenbus_dev_fatal(dev, err, "starting transaction");
++		return;
++	}
++
++	err = xenbus_printf(xbt, dev->nodename, "feature-barrier",  "1");
++	if (err) {
++		xenbus_dev_fatal(dev, err, "writing feature-barrier");
++		xenbus_transaction_end(xbt, 1);
++		return;
++	}
++
++	err = xenbus_transaction_end(xbt, 0);
++	if (err == -EAGAIN)
++		goto again;
++
++	/* Switch state */
+ 	err = xenbus_switch_state(dev, XenbusStateConnected);
+ 	if (err)
+ 		xenbus_dev_fatal(dev, err, "switching to Connected state",
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-x86-bigmem
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-x86-bigmem
@@ -0,0 +1,143 @@
+From: jbeulich@novell.com
+Subject: fix issues with the assignment of huge amounts of memory
+Patch-mainline: obsolete
+References: bnc#482614, bnc#537435
+
+--- head-2010-01-04.orig/arch/x86/kernel/e820-xen.c	2009-12-04 11:31:40.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/e820-xen.c	2009-12-04 12:11:12.000000000 +0100
+@@ -1350,6 +1350,26 @@ static int __init parse_memopt(char *p)
+ 
+ 	userdef = 1;
+ 	mem_size = memparse(p, &p);
++#ifdef CONFIG_XEN
++	/*
++	 * A little less than 2% of available memory are needed for page
++	 * tables, p2m map, and mem_map. Hence the maximum amount of memory
++	 * we can potentially balloon up to can in no case exceed about 50
++	 * times of what we've been given initially. Since even with that we
++	 * won't be able to boot (due to various calculations done based on
++	 * the total number of pages) we further restrict this to factor 32.
++	 */
++	if ((mem_size >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
++		u64 size = (u64)xen_start_info->nr_pages << 5;
++
++		printk(KERN_WARNING "mem=%Luk is invalid for an initial"
++				    " allocation of %luk, using %Luk\n",
++		       (unsigned long long)mem_size >> 10,
++		       xen_start_info->nr_pages << (PAGE_SHIFT - 10),
++		       (unsigned long long)size << (PAGE_SHIFT - 10));
++		mem_size = size << PAGE_SHIFT;
++	}
++#endif
+ 	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
+ 
+ 	i = e820.nr_map - 1;
+@@ -1546,6 +1566,7 @@ void __init e820_reserve_resources_late(
+ char *__init default_machine_specific_memory_setup(void)
+ {
+ 	int rc, nr_map;
++	unsigned long long maxmem;
+ 	struct xen_memory_map memmap;
+ 	static struct e820entry __initdata map[E820MAX];
+ 
+@@ -1571,6 +1592,22 @@ char *__init default_machine_specific_me
+ 		BUG();
+ 
+ #ifdef CONFIG_XEN
++	/* See the comment in parse_memopt(). */
++	for (maxmem = rc = 0; rc < e820.nr_map; ++rc)
++		if (e820.map[rc].type == E820_RAM)
++			maxmem += e820.map[rc].size;
++	if ((maxmem >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
++		unsigned long long size = (u64)xen_start_info->nr_pages << 5;
++
++		printk(KERN_WARNING "maxmem of %LuM is invalid for an initial"
++				    " allocation of %luM, using %LuM\n",
++		       maxmem >> 20,
++		       xen_start_info->nr_pages >> (20 - PAGE_SHIFT),
++		       size >> (20 - PAGE_SHIFT));
++		size <<= PAGE_SHIFT;
++		e820_remove_range(size, ULLONG_MAX - size, E820_RAM, 1);
++	}
++
+ 	if (is_initial_xendomain()) {
+ 		memmap.nr_entries = E820MAX;
+ 		set_xen_guest_handle(memmap.buffer, machine_e820.map);
+--- head-2010-01-04.orig/arch/x86/kernel/setup-xen.c	2010-01-04 13:32:45.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/setup-xen.c	2010-01-04 13:32:59.000000000 +0100
+@@ -129,12 +129,7 @@ static struct notifier_block xen_panic_b
+ unsigned long *phys_to_machine_mapping;
+ EXPORT_SYMBOL(phys_to_machine_mapping);
+ 
+-unsigned long *pfn_to_mfn_frame_list_list,
+-#ifdef CONFIG_X86_64
+-	*pfn_to_mfn_frame_list[512];
+-#else
+-	*pfn_to_mfn_frame_list[128];
+-#endif
++unsigned long *pfn_to_mfn_frame_list_list, **pfn_to_mfn_frame_list;
+ 
+ /* Raw start-of-day parameters from the hypervisor. */
+ start_info_t *xen_start_info;
+@@ -1145,17 +1140,17 @@ void __init setup_arch(char **cmdline_p)
+ 		p2m_pages = xen_start_info->nr_pages;
+ 
+ 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+-		unsigned long i, j;
++		unsigned long i, j, size;
+ 		unsigned int k, fpp;
+ 
+ 		/* Make sure we have a large enough P->M table. */
+ 		phys_to_machine_mapping = alloc_bootmem_pages(
+ 			max_pfn * sizeof(unsigned long));
+-		memset(phys_to_machine_mapping, ~0,
+-		       max_pfn * sizeof(unsigned long));
+ 		memcpy(phys_to_machine_mapping,
+ 		       (unsigned long *)xen_start_info->mfn_list,
+ 		       p2m_pages * sizeof(unsigned long));
++		memset(phys_to_machine_mapping + p2m_pages, ~0,
++		       (max_pfn - p2m_pages) * sizeof(unsigned long));
+ 		free_bootmem(
+ 			__pa(xen_start_info->mfn_list),
+ 			PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+@@ -1165,15 +1160,26 @@ void __init setup_arch(char **cmdline_p)
+ 		 * Initialise the list of the frames that specify the list of
+ 		 * frames that make up the p2m table. Used by save/restore.
+ 		 */
+-		pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE);
+-
+ 		fpp = PAGE_SIZE/sizeof(unsigned long);
++		size = (max_pfn + fpp - 1) / fpp;
++		size = (size + fpp - 1) / fpp;
++		++size; /* include a zero terminator for crash tools */
++		size *= sizeof(unsigned long);
++		pfn_to_mfn_frame_list_list = alloc_bootmem_pages(size);
++		if (size > PAGE_SIZE
++		    && xen_create_contiguous_region((unsigned long)
++						    pfn_to_mfn_frame_list_list,
++						    get_order(size), 0))
++			BUG();
++		size -= sizeof(unsigned long);
++		pfn_to_mfn_frame_list = alloc_bootmem(size);
++
+ 		for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) {
+ 			if (j == fpp)
+ 				j = 0;
+ 			if (j == 0) {
+ 				k++;
+-				BUG_ON(k>=ARRAY_SIZE(pfn_to_mfn_frame_list));
++				BUG_ON(k * sizeof(unsigned long) >= size);
+ 				pfn_to_mfn_frame_list[k] =
+ 					alloc_bootmem_pages(PAGE_SIZE);
+ 				pfn_to_mfn_frame_list_list[k] =
+--- head-2010-01-04.orig/drivers/xen/core/machine_reboot.c	2009-12-18 14:19:13.000000000 +0100
++++ head-2010-01-04/drivers/xen/core/machine_reboot.c	2009-12-18 14:15:04.000000000 +0100
+@@ -79,7 +79,7 @@ static void post_suspend(int suspend_can
+ 	unsigned long shinfo_mfn;
+ 	extern unsigned long max_pfn;
+ 	extern unsigned long *pfn_to_mfn_frame_list_list;
+-	extern unsigned long *pfn_to_mfn_frame_list[];
++	extern unsigned long **pfn_to_mfn_frame_list;
+ 
+ 	if (suspend_cancelled) {
+ 		xen_start_info->store_mfn =
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-kconfig-compat
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-kconfig-compat
@@ -0,0 +1,32 @@
+From: jbeulich@novell.com
+Subject: add 3.2.0-compatibility configure option
+Patch-mainline: obsolete
+
+--- head-2009-12-16.orig/drivers/xen/Kconfig	2009-12-18 12:30:34.000000000 +0100
++++ head-2009-12-16/drivers/xen/Kconfig	2009-12-18 12:30:46.000000000 +0100
+@@ -319,6 +319,15 @@ choice
+ 	config XEN_COMPAT_030100_AND_LATER
+ 		bool "3.1.0 and later"
+ 
++	config XEN_COMPAT_030200_AND_LATER
++		bool "3.2.0 and later"
++
++	config XEN_COMPAT_030300_AND_LATER
++		bool "3.3.0 and later"
++
++	config XEN_COMPAT_030400_AND_LATER
++		bool "3.4.0 and later"
++
+ 	config XEN_COMPAT_LATEST_ONLY
+ 		bool "no compatibility code"
+ 
+@@ -327,6 +336,9 @@ endchoice
+ config XEN_COMPAT
+ 	hex
+ 	default 0xffffff if XEN_COMPAT_LATEST_ONLY
++	default 0x030400 if XEN_COMPAT_030400_AND_LATER
++	default 0x030300 if XEN_COMPAT_030300_AND_LATER
++	default 0x030200 if XEN_COMPAT_030200_AND_LATER
+ 	default 0x030100 if XEN_COMPAT_030100_AND_LATER
+ 	default 0x030004 if XEN_COMPAT_030004_AND_LATER
+ 	default 0x030002 if XEN_COMPAT_030002_AND_LATER
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.2-3
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.2-3
@@ -0,0 +1,19 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.3
+Patch-mainline: 2.6.32.3
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.2-3" by xen-port-patches.py
+
+--- sle11sp1-2010-03-11.orig/arch/x86/include/mach-xen/asm/processor.h	2010-03-17 14:36:55.000000000 +0100
++++ sle11sp1-2010-03-11/arch/x86/include/mach-xen/asm/processor.h	2010-03-17 14:37:31.000000000 +0100
+@@ -181,7 +181,7 @@ static inline void xen_cpuid(unsigned in
+ 			     unsigned int *ecx, unsigned int *edx)
+ {
+ 	/* ecx is often an input as well as an output. */
+-	asm(XEN_CPUID
++	asm volatile(XEN_CPUID
+ 	    : "=a" (*eax),
+ 	      "=b" (*ebx),
+ 	      "=c" (*ecx),
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-virq-per-cpu-irq
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-virq-per-cpu-irq
@@ -0,0 +1,649 @@
+From: jbeulich@novell.com
+Subject: fold per-CPU VIRQs onto a single IRQ each
+Patch-mainline: obsolete
+
+--- head-2010-01-07.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:48:29.000000000 +0100
++++ head-2010-01-07/arch/x86/kernel/time-xen.c	2009-11-23 10:49:09.000000000 +0100
+@@ -688,19 +688,17 @@ int xen_update_persistent_clock(void)
+ }
+ 
+ /* Dynamically-mapped IRQ. */
+-DEFINE_PER_CPU(int, timer_irq);
++static int __read_mostly timer_irq = -1;
++static struct irqaction timer_action = {
++	.handler = timer_interrupt,
++	.flags   = IRQF_DISABLED|IRQF_TIMER,
++	.name    = "timer"
++};
+ 
+ static void __init setup_cpu0_timer_irq(void)
+ {
+-	per_cpu(timer_irq, 0) =
+-		bind_virq_to_irqhandler(
+-			VIRQ_TIMER,
+-			0,
+-			timer_interrupt,
+-			IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING,
+-			"timer0",
+-			NULL);
+-	BUG_ON(per_cpu(timer_irq, 0) < 0);
++	timer_irq = bind_virq_to_irqaction(VIRQ_TIMER, 0, &timer_action);
++	BUG_ON(timer_irq < 0);
+ }
+ 
+ void __init time_init(void)
+@@ -828,8 +826,6 @@ void xen_halt(void)
+ EXPORT_SYMBOL(xen_halt);
+ 
+ #ifdef CONFIG_SMP
+-static char timer_name[NR_CPUS][15];
+-
+ int __cpuinit local_setup_timer(unsigned int cpu)
+ {
+ 	int seq, irq;
+@@ -855,16 +851,10 @@ int __cpuinit local_setup_timer(unsigned
+ 		init_missing_ticks_accounting(cpu);
+ 	} while (read_seqretry(&xtime_lock, seq));
+ 
+-	sprintf(timer_name[cpu], "timer%u", cpu);
+-	irq = bind_virq_to_irqhandler(VIRQ_TIMER,
+-				      cpu,
+-				      timer_interrupt,
+-				      IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING,
+-				      timer_name[cpu],
+-				      NULL);
++	irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action);
+ 	if (irq < 0)
+ 		return irq;
+-	per_cpu(timer_irq, cpu) = irq;
++	BUG_ON(timer_irq != irq);
+ 
+ 	return 0;
+ }
+@@ -872,7 +862,7 @@ int __cpuinit local_setup_timer(unsigned
+ void __cpuinit local_teardown_timer(unsigned int cpu)
+ {
+ 	BUG_ON(cpu == 0);
+-	unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
++	unbind_from_per_cpu_irq(timer_irq, cpu, &timer_action);
+ }
+ #endif
+ 
+--- head-2010-01-07.orig/drivers/xen/core/evtchn.c	2009-11-06 11:10:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/core/evtchn.c	2009-11-06 11:10:22.000000000 +0100
+@@ -58,6 +58,23 @@ static DEFINE_SPINLOCK(irq_mapping_updat
+ static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+ 	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
+ 
++#if defined(CONFIG_SMP) && defined(CONFIG_X86)
++static struct per_cpu_irqaction {
++	struct irqaction action; /* must be first */
++	struct per_cpu_irqaction *next;
++	cpumask_t cpus;
++} *virq_actions[NR_VIRQS];
++/* IRQ <-> VIRQ mapping. */
++static DECLARE_BITMAP(virq_per_cpu, NR_VIRQS) __read_mostly;
++static DEFINE_PER_CPU(int[NR_VIRQS], virq_to_evtchn);
++#define BUG_IF_VIRQ_PER_CPU(irq) \
++	BUG_ON(type_from_irq(irq) == IRQT_VIRQ \
++	       && test_bit(index_from_irq(irq), virq_per_cpu))
++#else
++#define BUG_IF_VIRQ_PER_CPU(irq) ((void)(irq))
++#define PER_CPU_VIRQ_IRQ
++#endif
++
+ /* IRQ <-> IPI mapping. */
+ #ifndef NR_IPIS
+ #define NR_IPIS 1
+@@ -132,15 +149,6 @@ static inline u32 mk_irq_info(u32 type, 
+  * Accessors for packed IRQ information.
+  */
+ 
+-#ifdef PER_CPU_IPI_IRQ
+-static inline unsigned int evtchn_from_irq(int irq)
+-{
+-	const struct irq_cfg *cfg = irq_cfg(irq);
+-
+-	return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
+-}
+-#endif
+-
+ static inline unsigned int index_from_irq(int irq)
+ {
+ 	const struct irq_cfg *cfg = irq_cfg(irq);
+@@ -156,24 +164,39 @@ static inline unsigned int type_from_irq
+ 	return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
+ }
+ 
+-#ifndef PER_CPU_IPI_IRQ
+ static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq,
+ 						    unsigned int cpu)
+ {
+-	BUG_ON(type_from_irq(irq) != IRQT_IPI);
+-	return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)];
++	switch (type_from_irq(irq)) {
++#ifndef PER_CPU_VIRQ_IRQ
++	case IRQT_VIRQ:
++		return per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)];
++#endif
++#ifndef PER_CPU_IPI_IRQ
++	case IRQT_IPI:
++		return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)];
++#endif
++	}
++	BUG();
++	return 0;
+ }
+ 
+ static inline unsigned int evtchn_from_irq(unsigned int irq)
+ {
+-	if (type_from_irq(irq) != IRQT_IPI) {
+-		const struct irq_cfg *cfg = irq_cfg(irq);
++	const struct irq_cfg *cfg;
+ 
+-		return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
++	switch (type_from_irq(irq)) {
++#ifndef PER_CPU_VIRQ_IRQ
++	case IRQT_VIRQ:
++#endif
++#ifndef PER_CPU_IPI_IRQ
++	case IRQT_IPI:
++#endif
++		return evtchn_from_per_cpu_irq(irq, smp_processor_id());
+ 	}
+-	return evtchn_from_per_cpu_irq(irq, smp_processor_id());
++	cfg = irq_cfg(irq);
++	return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
+ }
+-#endif
+ 
+ /* IRQ <-> VIRQ mapping. */
+ DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
+@@ -510,6 +533,14 @@ static int bind_virq_to_irq(unsigned int
+ 		evtchn = bind_virq.port;
+ 
+ 		evtchn_to_irq[evtchn] = irq;
++#ifndef PER_CPU_VIRQ_IRQ
++		{
++			unsigned int cpu;
++
++			for_each_possible_cpu(cpu)
++				per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
++		}
++#endif
+ 		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+ 
+ 		per_cpu(virq_to_irq, cpu)[virq] = irq;
+@@ -564,7 +595,9 @@ static void unbind_from_irq(unsigned int
+ 	unsigned int cpu;
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_IF_VIRQ_PER_CPU(irq);
+ 	BUG_IF_IPI(irq);
++
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
+@@ -577,6 +610,11 @@ static void unbind_from_irq(unsigned int
+ 		case IRQT_VIRQ:
+ 			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
+ 				[index_from_irq(irq)] = -1;
++#ifndef PER_CPU_VIRQ_IRQ
++			for_each_possible_cpu(cpu)
++				per_cpu(virq_to_evtchn, cpu)
++					[index_from_irq(irq)] = 0;
++#endif
+ 			break;
+ #if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+ 		case IRQT_IPI:
+@@ -606,11 +644,13 @@ static void unbind_from_irq(unsigned int
+ 	spin_unlock(&irq_mapping_update_lock);
+ }
+ 
+-#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
+-void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu)
++#if defined(CONFIG_SMP) && (!defined(PER_CPU_IPI_IRQ) || !defined(PER_CPU_VIRQ_IRQ))
++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu,
++			     struct irqaction *action)
+ {
+ 	struct evtchn_close close;
+ 	int evtchn = evtchn_from_per_cpu_irq(irq, cpu);
++	struct irqaction *free_action = NULL;
+ 
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+@@ -621,6 +661,32 @@ void unbind_from_per_cpu_irq(unsigned in
+ 
+ 		BUG_ON(irq_cfg(irq)->bindcount <= 1);
+ 		irq_cfg(irq)->bindcount--;
++
++#ifndef PER_CPU_VIRQ_IRQ
++		if (type_from_irq(irq) == IRQT_VIRQ) {
++			unsigned int virq = index_from_irq(irq);
++			struct per_cpu_irqaction *cur, *prev = NULL;
++
++			cur = virq_actions[virq];
++			while (cur) {
++				if (cur->action.dev_id == action) {
++					cpu_clear(cpu, cur->cpus);
++					if (cpus_empty(cur->cpus)) {
++						if (prev)
++							prev->next = cur->next;
++						else
++							virq_actions[virq] = cur->next;
++						free_action = action;
++					}
++				} else if (cpu_isset(cpu, cur->cpus))
++					evtchn = 0;
++				cur = (prev = cur)->next;
++			}
++			if (!VALID_EVTCHN(evtchn))
++				goto done;
++		}
++#endif
++
+ 		cpumask_clear_cpu(cpu, desc->affinity);
+ 
+ 		close.port = evtchn;
+@@ -628,9 +694,16 @@ void unbind_from_per_cpu_irq(unsigned in
+ 			BUG();
+ 
+ 		switch (type_from_irq(irq)) {
++#ifndef PER_CPU_VIRQ_IRQ
++		case IRQT_VIRQ:
++			per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)] = 0;
++			break;
++#endif
++#ifndef PER_CPU_IPI_IRQ
+ 		case IRQT_IPI:
+ 			per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0;
+ 			break;
++#endif
+ 		default:
+ 			BUG();
+ 			break;
+@@ -642,9 +715,16 @@ void unbind_from_per_cpu_irq(unsigned in
+ 		evtchn_to_irq[evtchn] = -1;
+ 	}
+ 
++#ifndef PER_CPU_VIRQ_IRQ
++done:
++#endif
+ 	spin_unlock(&irq_mapping_update_lock);
++
++	if (free_action)
++		free_irq(irq, free_action);
+ }
+-#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */
++EXPORT_SYMBOL_GPL(unbind_from_per_cpu_irq);
++#endif /* CONFIG_SMP && (!PER_CPU_IPI_IRQ || !PER_CPU_VIRQ_IRQ) */
+ 
+ int bind_caller_port_to_irqhandler(
+ 	unsigned int caller_port,
+@@ -726,6 +806,8 @@ int bind_virq_to_irqhandler(
+ {
+ 	int irq, retval;
+ 
++	BUG_IF_VIRQ_PER_CPU(virq);
++
+ 	irq = bind_virq_to_irq(virq, cpu);
+ 	if (irq < 0)
+ 		return irq;
+@@ -741,6 +823,108 @@ int bind_virq_to_irqhandler(
+ EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+ 
+ #ifdef CONFIG_SMP
++#ifndef PER_CPU_VIRQ_IRQ
++int bind_virq_to_irqaction(
++	unsigned int virq,
++	unsigned int cpu,
++	struct irqaction *action)
++{
++	struct evtchn_bind_virq bind_virq;
++	int evtchn, irq, retval = 0;
++	struct per_cpu_irqaction *cur = NULL, *new;
++
++	BUG_ON(!test_bit(virq, virq_per_cpu));
++
++	if (action->dev_id)
++		return -EINVAL;
++
++	new = kzalloc(sizeof(*new), GFP_ATOMIC);
++	if (new) {
++		new->action = *action;
++		new->action.dev_id = action;
++	}
++
++	spin_lock(&irq_mapping_update_lock);
++
++	for (cur = virq_actions[virq]; cur; cur = cur->next)
++		if (cur->action.dev_id == action)
++			break;
++	if (!cur) {
++		if (!new) {
++			spin_unlock(&irq_mapping_update_lock);
++			return -ENOMEM;
++		}
++		new->next = virq_actions[virq];
++		virq_actions[virq] = cur = new;
++		retval = 1;
++	}
++	cpu_set(cpu, cur->cpus);
++	action = &cur->action;
++
++	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
++		unsigned int nr;
++
++		BUG_ON(!retval);
++
++		if ((irq = find_unbound_irq(cpu, true)) < 0) {
++			if (cur)
++				virq_actions[virq] = cur->next;
++			spin_unlock(&irq_mapping_update_lock);
++			if (cur != new)
++				kfree(new);
++			return irq;
++		}
++
++		/* Extra reference so count will never drop to zero. */
++		irq_cfg(irq)->bindcount++;
++
++		for_each_possible_cpu(nr)
++			per_cpu(virq_to_irq, nr)[virq] = irq;
++		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, 0);
++	}
++
++	evtchn = per_cpu(virq_to_evtchn, cpu)[virq];
++	if (!VALID_EVTCHN(evtchn)) {
++		bind_virq.virq = virq;
++		bind_virq.vcpu = cpu;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
++						&bind_virq) != 0)
++			BUG();
++		evtchn = bind_virq.port;
++		evtchn_to_irq[evtchn] = irq;
++		per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
++
++		bind_evtchn_to_cpu(evtchn, cpu);
++	}
++
++	irq_cfg(irq)->bindcount++;
++
++	spin_unlock(&irq_mapping_update_lock);
++
++	if (cur != new)
++		kfree(new);
++
++	if (retval == 0) {
++		unsigned long flags;
++
++		local_irq_save(flags);
++		unmask_evtchn(evtchn);
++		local_irq_restore(flags);
++	} else {
++		action->flags |= IRQF_PERCPU;
++		retval = setup_irq(irq, action);
++		if (retval) {
++			unbind_from_per_cpu_irq(irq, cpu, cur->action.dev_id);
++			BUG_ON(retval > 0);
++			irq = retval;
++		}
++	}
++
++	return irq;
++}
++EXPORT_SYMBOL_GPL(bind_virq_to_irqaction);
++#endif
++
+ #ifdef PER_CPU_IPI_IRQ
+ int bind_ipi_to_irqhandler(
+ 	unsigned int ipi,
+@@ -820,7 +1004,7 @@ int __cpuinit bind_ipi_to_irqaction(
+ 		action->flags |= IRQF_PERCPU | IRQF_NO_SUSPEND;
+ 		retval = setup_irq(irq, action);
+ 		if (retval) {
+-			unbind_from_per_cpu_irq(irq, cpu);
++			unbind_from_per_cpu_irq(irq, cpu, NULL);
+ 			BUG_ON(retval > 0);
+ 			irq = retval;
+ 		}
+@@ -855,7 +1039,9 @@ static void rebind_irq_to_cpu(unsigned i
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_IF_VIRQ_PER_CPU(irq);
+ 	BUG_IF_IPI(irq);
++
+ 	if (VALID_EVTCHN(evtchn))
+ 		rebind_evtchn_to_cpu(evtchn, tcpu);
+ }
+@@ -1135,7 +1321,9 @@ void notify_remote_via_irq(int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_ON(type_from_irq(irq) == IRQT_VIRQ);
+ 	BUG_IF_IPI(irq);
++
+ 	if (VALID_EVTCHN(evtchn))
+ 		notify_remote_via_evtchn(evtchn);
+ }
+@@ -1143,6 +1331,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq)
+ 
+ int irq_to_evtchn_port(int irq)
+ {
++	BUG_IF_VIRQ_PER_CPU(irq);
+ 	BUG_IF_IPI(irq);
+ 	return evtchn_from_irq(irq);
+ }
+@@ -1237,6 +1426,12 @@ static void restore_cpu_virqs(unsigned i
+ 		if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1)
+ 			continue;
+ 
++#ifndef PER_CPU_VIRQ_IRQ
++		if (test_bit(virq, virq_per_cpu)
++		    && !VALID_EVTCHN(per_cpu(virq_to_evtchn, cpu)[virq]))
++			continue;
++#endif
++
+ 		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_VIRQ, virq, 0));
+ 
+ 		/* Get a new binding from Xen. */
+@@ -1249,7 +1444,20 @@ static void restore_cpu_virqs(unsigned i
+ 
+ 		/* Record the new mapping. */
+ 		evtchn_to_irq[evtchn] = irq;
++#ifdef PER_CPU_VIRQ_IRQ
+ 		irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn);
++#else
++		if (test_bit(virq, virq_per_cpu))
++			per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
++		else {
++			unsigned int cpu;
++
++			irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq,
++							 evtchn);
++			for_each_possible_cpu(cpu)
++				per_cpu(virq_to_evtchn, cpu)[virq] = evtchn;
++		}
++#endif
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+@@ -1305,7 +1513,11 @@ static int evtchn_resume(struct sys_devi
+ 
+ 	/* Avoid doing anything in the 'suspend cancelled' case. */
+ 	status.dom = DOMID_SELF;
++#ifdef PER_CPU_VIRQ_IRQ
+ 	status.port = evtchn_from_irq(percpu_read(virq_to_irq[VIRQ_TIMER]));
++#else
++	status.port = percpu_read(virq_to_evtchn[VIRQ_TIMER]);
++#endif
+ 	if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status))
+ 		BUG();
+ 	if (status.status == EVTCHNSTAT_virq
+@@ -1534,6 +1746,15 @@ void __init xen_init_IRQ(void)
+ 	unsigned int i;
+ 	struct physdev_pirq_eoi_gmfn eoi_gmfn;
+ 
++#ifndef PER_CPU_VIRQ_IRQ
++	__set_bit(VIRQ_TIMER, virq_per_cpu);
++	__set_bit(VIRQ_DEBUG, virq_per_cpu);
++	__set_bit(VIRQ_XENOPROF, virq_per_cpu);
++#ifdef CONFIG_IA64
++	__set_bit(VIRQ_ITC, virq_per_cpu);
++#endif
++#endif
++
+ 	init_evtchn_cpu_bindings();
+ 
+ 	i = get_order(sizeof(unsigned long) * BITS_TO_LONGS(nr_pirqs));
+--- head-2010-01-07.orig/drivers/xen/core/smpboot.c	2009-11-06 11:10:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/core/smpboot.c	2009-11-06 11:10:22.000000000 +0100
+@@ -168,13 +168,13 @@ static int __cpuinit xen_smp_intr_init(u
+  fail:
+ 	xen_spinlock_cleanup(cpu);
+  unbind_reboot:
+-	unbind_from_per_cpu_irq(reboot_irq, cpu);
++	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
+  unbind_call1:
+-	unbind_from_per_cpu_irq(call1func_irq, cpu);
++	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
+  unbind_call:
+-	unbind_from_per_cpu_irq(callfunc_irq, cpu);
++	unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL);
+  unbind_resched:
+-	unbind_from_per_cpu_irq(resched_irq, cpu);
++	unbind_from_per_cpu_irq(resched_irq, cpu, NULL);
+ 	return rc;
+ }
+ 
+@@ -184,10 +184,10 @@ static void __cpuinit xen_smp_intr_exit(
+ 	if (cpu != 0)
+ 		local_teardown_timer(cpu);
+ 
+-	unbind_from_per_cpu_irq(resched_irq, cpu);
+-	unbind_from_per_cpu_irq(callfunc_irq, cpu);
+-	unbind_from_per_cpu_irq(call1func_irq, cpu);
+-	unbind_from_per_cpu_irq(reboot_irq, cpu);
++	unbind_from_per_cpu_irq(resched_irq, cpu, NULL);
++	unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL);
++	unbind_from_per_cpu_irq(call1func_irq, cpu, NULL);
++	unbind_from_per_cpu_irq(reboot_irq, cpu, NULL);
+ 	xen_spinlock_cleanup(cpu);
+ }
+ #endif
+--- head-2010-01-07.orig/drivers/xen/core/spinlock.c	2009-11-06 11:10:20.000000000 +0100
++++ head-2010-01-07/drivers/xen/core/spinlock.c	2009-11-06 11:10:22.000000000 +0100
+@@ -55,7 +55,7 @@ int __cpuinit xen_spinlock_init(unsigned
+ 
+ void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
+ {
+-	unbind_from_per_cpu_irq(spinlock_irq, cpu);
++	unbind_from_per_cpu_irq(spinlock_irq, cpu, NULL);
+ }
+ 
+ int xen_spin_wait(raw_spinlock_t *lock, unsigned int token)
+--- head-2010-01-07.orig/drivers/xen/netback/netback.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2010-01-07/drivers/xen/netback/netback.c	2010-01-04 13:31:26.000000000 +0100
+@@ -1619,6 +1619,12 @@ static irqreturn_t netif_be_dbg(int irq,
+ 
+ 	return IRQ_HANDLED;
+ }
++
++static struct irqaction netif_be_dbg_action = {
++	.handler = netif_be_dbg,
++	.flags   = IRQF_SHARED,
++	.name    = "net-be-dbg"
++};
+ #endif
+ 
+ static int __init netback_init(void)
+@@ -1678,12 +1684,9 @@ static int __init netback_init(void)
+ 	netif_xenbus_init();
+ 
+ #ifdef NETBE_DEBUG_INTERRUPT
+-	(void)bind_virq_to_irqhandler(VIRQ_DEBUG,
+-				      0,
+-				      netif_be_dbg,
+-				      IRQF_SHARED,
+-				      "net-be-dbg",
+-				      &netif_be_dbg);
++	(void)bind_virq_to_irqaction(VIRQ_DEBUG,
++				     0,
++				     &netif_be_dbg_action);
+ #endif
+ 
+ 	return 0;
+--- head-2010-01-07.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:59:32.000000000 +0100
++++ head-2010-01-07/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 11:04:10.000000000 +0100
+@@ -210,6 +210,11 @@ static irqreturn_t xenoprof_ovf_interrup
+ 	return IRQ_HANDLED;
+ }
+ 
++static struct irqaction ovf_action = {
++	.handler = xenoprof_ovf_interrupt,
++	.flags   = IRQF_DISABLED,
++	.name    = "xenoprof"
++};
+ 
+ static void unbind_virq(void)
+ {
+@@ -217,7 +222,7 @@ static void unbind_virq(void)
+ 
+ 	for_each_online_cpu(i) {
+ 		if (ovf_irq[i] >= 0) {
+-			unbind_from_irqhandler(ovf_irq[i], NULL);
++			unbind_from_per_cpu_irq(ovf_irq[i], i, &ovf_action);
+ 			ovf_irq[i] = -1;
+ 		}
+ 	}
+@@ -230,12 +235,7 @@ static int bind_virq(void)
+ 	int result;
+ 
+ 	for_each_online_cpu(i) {
+-		result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
+-						 i,
+-						 xenoprof_ovf_interrupt,
+-						 IRQF_DISABLED|IRQF_NOBALANCING,
+-						 "xenoprof",
+-						 NULL);
++		result = bind_virq_to_irqaction(VIRQ_XENOPROF, i, &ovf_action);
+ 
+ 		if (result < 0) {
+ 			unbind_virq();
+--- head-2010-01-07.orig/include/xen/evtchn.h	2009-12-18 10:13:26.000000000 +0100
++++ head-2010-01-07/include/xen/evtchn.h	2009-12-18 10:13:32.000000000 +0100
+@@ -92,6 +92,17 @@ int bind_virq_to_irqhandler(
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
++#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86)
++int bind_virq_to_irqaction(
++	unsigned int virq,
++	unsigned int cpu,
++	struct irqaction *action);
++#else
++#define bind_virq_to_irqaction(virq, cpu, action) \
++	bind_virq_to_irqhandler(virq, cpu, (action)->handler, \
++			 	(action)->flags | IRQF_NOBALANCING, \
++				(action)->name, action)
++#endif
+ #if defined(CONFIG_SMP) && !defined(MODULE)
+ #ifndef CONFIG_X86
+ int bind_ipi_to_irqhandler(
+@@ -116,9 +127,13 @@ int bind_ipi_to_irqaction(
+  */
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+ 
+-#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
++#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86)
+ /* Specialized unbind function for per-CPU IRQs. */
+-void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu);
++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu,
++			     struct irqaction *);
++#else
++#define unbind_from_per_cpu_irq(irq, cpu, action) \
++	unbind_from_irqhandler(irq, action)
+ #endif
+ 
+ #ifndef CONFIG_XEN
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-sections
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-sections
@@ -0,0 +1,127 @@
+From: jbeulich@novell.com
+Subject: fix placement of some routines/data
+Patch-mainline: obsolete
+
+--- head-2009-11-20.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:43:52.000000000 +0100
++++ head-2009-11-20/arch/x86/kernel/time-xen.c	2009-11-23 10:44:50.000000000 +0100
+@@ -665,7 +665,7 @@ int xen_update_persistent_clock(void)
+ /* Dynamically-mapped IRQ. */
+ DEFINE_PER_CPU(int, timer_irq);
+ 
+-static void setup_cpu0_timer_irq(void)
++static void __init setup_cpu0_timer_irq(void)
+ {
+ 	per_cpu(timer_irq, 0) =
+ 		bind_virq_to_irqhandler(
+@@ -877,7 +877,7 @@ int __cpuinit local_setup_timer(unsigned
+ 	return 0;
+ }
+ 
+-void __cpuexit local_teardown_timer(unsigned int cpu)
++void __cpuinit local_teardown_timer(unsigned int cpu)
+ {
+ 	BUG_ON(cpu == 0);
+ 	unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
+--- head-2009-11-20.orig/drivers/xen/core/cpu_hotplug.c	2009-11-06 10:51:55.000000000 +0100
++++ head-2009-11-20/drivers/xen/core/cpu_hotplug.c	2009-11-06 11:09:19.000000000 +0100
+@@ -24,7 +24,7 @@ static int local_cpu_hotplug_request(voi
+ 	return (current->mm != NULL);
+ }
+ 
+-static void vcpu_hotplug(unsigned int cpu)
++static void __cpuinit vcpu_hotplug(unsigned int cpu)
+ {
+ 	int err;
+ 	char dir[32], state[32];
+@@ -51,7 +51,7 @@ static void vcpu_hotplug(unsigned int cp
+ 	}
+ }
+ 
+-static void handle_vcpu_hotplug_event(
++static void __cpuinit handle_vcpu_hotplug_event(
+ 	struct xenbus_watch *watch, const char **vec, unsigned int len)
+ {
+ 	unsigned int cpu;
+@@ -80,12 +80,12 @@ static int smpboot_cpu_notify(struct not
+ 	return NOTIFY_OK;
+ }
+ 
+-static int setup_cpu_watcher(struct notifier_block *notifier,
+-			      unsigned long event, void *data)
++static int __cpuinit setup_cpu_watcher(struct notifier_block *notifier,
++				       unsigned long event, void *data)
+ {
+ 	unsigned int i;
+ 
+-	static struct xenbus_watch cpu_watch = {
++	static struct xenbus_watch __cpuinitdata cpu_watch = {
+ 		.node = "cpu",
+ 		.callback = handle_vcpu_hotplug_event,
+ 		.flags = XBWF_new_thread };
+@@ -105,7 +105,7 @@ static int __init setup_vcpu_hotplug_eve
+ {
+ 	static struct notifier_block hotplug_cpu = {
+ 		.notifier_call = smpboot_cpu_notify };
+-	static struct notifier_block xsn_cpu = {
++	static struct notifier_block __cpuinitdata xsn_cpu = {
+ 		.notifier_call = setup_cpu_watcher };
+ 
+ 	if (!is_running_on_xen())
+@@ -119,7 +119,7 @@ static int __init setup_vcpu_hotplug_eve
+ 
+ arch_initcall(setup_vcpu_hotplug_event);
+ 
+-int smp_suspend(void)
++int __ref smp_suspend(void)
+ {
+ 	unsigned int cpu;
+ 	int err;
+@@ -140,7 +140,7 @@ int smp_suspend(void)
+ 	return 0;
+ }
+ 
+-void smp_resume(void)
++void __ref smp_resume(void)
+ {
+ 	unsigned int cpu;
+ 
+--- head-2009-11-20.orig/drivers/xen/core/smpboot.c	2009-11-06 10:52:09.000000000 +0100
++++ head-2009-11-20/drivers/xen/core/smpboot.c	2009-11-06 11:09:19.000000000 +0100
+@@ -173,7 +173,7 @@ static int __cpuinit xen_smp_intr_init(u
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+-static void __cpuexit xen_smp_intr_exit(unsigned int cpu)
++static void __cpuinit xen_smp_intr_exit(unsigned int cpu)
+ {
+ 	if (cpu != 0)
+ 		local_teardown_timer(cpu);
+@@ -392,7 +392,7 @@ int __cpuexit __cpu_disable(void)
+ 	return 0;
+ }
+ 
+-void __cpuexit __cpu_die(unsigned int cpu)
++void __cpuinit __cpu_die(unsigned int cpu)
+ {
+ 	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+ 		current->state = TASK_UNINTERRUPTIBLE;
+--- head-2009-11-20.orig/drivers/xen/evtchn/evtchn.c	2009-03-18 10:39:31.000000000 +0100
++++ head-2009-11-20/drivers/xen/evtchn/evtchn.c	2009-11-06 11:09:19.000000000 +0100
+@@ -549,14 +549,15 @@ static int __init evtchn_init(void)
+ 
+ 	return 0;
+ }
++module_init(evtchn_init);
+ 
++#ifdef CONFIG_MODULE
+ static void __exit evtchn_cleanup(void)
+ {
+ 	misc_deregister(&evtchn_miscdev);
+ 	unregister_cpu_notifier(&evtchn_cpu_nfb);
+ }
+-
+-module_init(evtchn_init);
+ module_exit(evtchn_cleanup);
++#endif
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.8-9
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.8-9
@@ -0,0 +1,18 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.9
+Patch-mainline: 2.6.32.9
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.8-9" by xen-port-patches.py
+
+--- sle11sp1-2010-08-06.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-08-06 17:02:05.000000000 +0200
++++ sle11sp1-2010-08-06/arch/x86/kernel/apic/io_apic-xen.c	2010-08-06 17:02:21.000000000 +0200
+@@ -3265,6 +3265,7 @@ unsigned int create_irq_nr(unsigned int 
+ 			continue;
+ 
+ 		desc_new = move_irq_desc(desc_new, node);
++		cfg_new = desc_new->chip_data;
+ 
+ 		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
+ 			irq = new;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-x86-mcp51-no-dac
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-x86-mcp51-no-dac
@@ -0,0 +1,35 @@
+From: Tejun Heo <tj@kernel.org>
+Subject: x86: disallow DAC for MCP51 PCI bridge
+References: bnc#463829, bnc#482220
+
+MCP51 corrupts DAC transfers.  Disallow it.  Reported by pgnet on
+bnc#463829.
+
+  https://bugzilla.novell.com/show_bug.cgi?id=463829
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: pgnet <pgnet.trash@gmail.com>
+Signed-off-by: Tejun Heo <teheo@suse.de>
+Automatically created from "patches.arch/x86-mcp51-no-dac" by xen-port-patches.py
+
+--- head-2009-12-04.orig/arch/x86/kernel/pci-dma-xen.c	2009-12-04 12:04:14.000000000 +0100
++++ head-2009-12-04/arch/x86/kernel/pci-dma-xen.c	2009-12-04 12:04:18.000000000 +0100
+@@ -403,4 +403,18 @@ static __devinit void via_no_dac(struct 
+ 	}
+ }
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
++
++/*
++ * MCP51 PCI bridge corrupts data for DAC.  Disable it.  Reported in
++ * bnc#463829.
++ */
++static __devinit void mcp51_no_dac(struct pci_dev *dev)
++{
++	if (forbid_dac == 0) {
++		printk(KERN_INFO
++		       "PCI: MCP51 PCI bridge detected. Disabling DAC.\n");
++		forbid_dac = 1;
++	}
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x026f, mcp51_no_dac);
+ #endif
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.7-8
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.7-8
@@ -0,0 +1,104 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.8
+Patch-mainline: 2.6.32.8
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.7-8" by xen-port-patches.py
+
+--- sle11sp1-2010-03-11.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ sle11sp1-2010-03-11/arch/x86/kernel/process-xen.c	2010-02-09 17:12:56.000000000 +0100
+@@ -93,18 +93,6 @@ void flush_thread(void)
+ {
+ 	struct task_struct *tsk = current;
+ 
+-#ifdef CONFIG_X86_64
+-	if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
+-		clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
+-		if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+-			clear_tsk_thread_flag(tsk, TIF_IA32);
+-		} else {
+-			set_tsk_thread_flag(tsk, TIF_IA32);
+-			current_thread_info()->status |= TS_COMPAT;
+-		}
+-	}
+-#endif
+-
+ 	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+ 
+ 	tsk->thread.debugreg0 = 0;
+--- sle11sp1-2010-03-11.orig/arch/x86/kernel/process_64-xen.c	2010-03-17 14:37:05.000000000 +0100
++++ sle11sp1-2010-03-11/arch/x86/kernel/process_64-xen.c	2010-03-17 14:38:41.000000000 +0100
+@@ -615,6 +615,17 @@ sys_clone(unsigned long clone_flags, uns
+ 	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+ }
+ 
++void set_personality_ia32(void)
++{
++	/* inherit personality from parent */
++
++	/* Make sure to be in 32bit mode */
++	set_thread_flag(TIF_IA32);
++
++	/* Prepare the first "return" to user space */
++	current_thread_info()->status |= TS_COMPAT;
++}
++
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ 	unsigned long stack;
+--- sle11sp1-2010-03-11.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ sle11sp1-2010-03-11/arch/x86/kernel/quirks-xen.c	2010-02-09 17:12:56.000000000 +0100
+@@ -492,6 +492,19 @@ void force_hpet_resume(void)
+ 		break;
+ 	}
+ }
++
++/*
++ * HPET MSI on some boards (ATI SB700/SB800) has side effect on
++ * floppy DMA. Disable HPET MSI on such platforms.
++ */
++static void force_disable_hpet_msi(struct pci_dev *unused)
++{
++	hpet_msi_disable = 1;
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
++			 force_disable_hpet_msi);
++
+ #endif
+ 
+ #if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
+--- sle11sp1-2010-03-11.orig/arch/x86/kernel/setup-xen.c	2010-01-04 12:50:03.000000000 +0100
++++ sle11sp1-2010-03-11/arch/x86/kernel/setup-xen.c	2010-02-09 17:12:56.000000000 +0100
+@@ -736,19 +736,27 @@ static struct dmi_system_id __initdata b
+ 			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
+ 		},
+ 	},
+-	{
+ 	/*
+-	 * AMI BIOS with low memory corruption was found on Intel DG45ID board.
+-	 * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
++	 * AMI BIOS with low memory corruption was found on Intel DG45ID and
++	 * DG45FC boards.
++	 * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+ 	 * match only DMI_BOARD_NAME and see if there is more bad products
+ 	 * with this vendor.
+ 	 */
++	{
+ 		.callback = dmi_low_memory_corruption,
+ 		.ident = "AMI BIOS",
+ 		.matches = {
+ 			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
+ 		},
+ 	},
++	{
++		.callback = dmi_low_memory_corruption,
++		.ident = "AMI BIOS",
++		.matches = {
++			DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
++		},
++	},
+ #endif
+ 	{}
+ };
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-swiotlb-heuristics
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-swiotlb-heuristics
@@ -0,0 +1,32 @@
+From: jbeulich@novell.com
+Subject: adjust Xen's swiotlb default size setting
+Patch-mainline: obsolete
+
+--- head-2009-10-12.orig/lib/swiotlb-xen.c	2009-10-14 15:52:38.000000000 +0200
++++ head-2009-10-12/lib/swiotlb-xen.c	2009-10-14 16:20:35.000000000 +0200
+@@ -211,8 +211,8 @@ swiotlb_init_with_default_size(size_t de
+ void __init
+ swiotlb_init(void)
+ {
+-	long ram_end;
+-	size_t defsz = 64 * (1 << 20); /* 64MB default size */
++	unsigned long ram_end;
++	size_t defsz = 64 << 20; /* 64MB default size */
+ 
+ 	if (swiotlb_force == 1) {
+ 		swiotlb = 1;
+@@ -221,8 +221,12 @@ swiotlb_init(void)
+ 		   is_initial_xendomain()) {
+ 		/* Domain 0 always has a swiotlb. */
+ 		ram_end = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
+-		if (ram_end <= 0x7ffff)
+-			defsz = 2 * (1 << 20); /* 2MB on <2GB on systems. */
++		if (ram_end <= 0x1ffff)
++			defsz = 2 << 20; /* 2MB on <512MB systems. */
++		else if (ram_end <= 0x3ffff)
++			defsz = 4 << 20; /* 4MB on <1GB systems. */
++		else if (ram_end <= 0x7ffff)
++			defsz = 8 << 20; /* 8MB on <2GB systems. */
+ 		swiotlb = 1;
+ 	}
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-external-sram
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-external-sram
@@ -0,0 +1,298 @@
+From: Kieran Mansley <kmansley@solarflare.com>
+Subject: enable access to Falcon's external SRAM
+References: bnc#489105
+
+Include ability to reference external SRAM on Solarflare Falcon NICs to
+allow event queues to be accessed by virtualised guests.  
+
+Acked-by: jbeulich@novell.com
+
+--- head-2009-07-28.orig/drivers/net/sfc/falcon.c	2009-07-28 10:05:40.000000000 +0200
++++ head-2009-07-28/drivers/net/sfc/falcon.c	2009-07-28 10:06:53.000000000 +0200
+@@ -36,6 +36,9 @@
+ 
+ /**
+  * struct falcon_nic_data - Falcon NIC state
++ * @sram_cfg: SRAM configuration value
++ * @tx_dc_base: Base address in SRAM of TX queue descriptor caches
++ * @rx_dc_base: Base address in SRAM of RX queue descriptor caches
+  * @next_buffer_table: First available buffer table id
+  * @resources: Resource information for driverlink client
+  * @pci_dev2: The secondary PCI device if present
+@@ -44,6 +47,9 @@
+  * @int_error_expire: Time at which error count will be expired
+  */
+ struct falcon_nic_data {
++	int sram_cfg;
++	unsigned tx_dc_base;
++	unsigned rx_dc_base;
+ #ifndef CONFIG_SFC_DRIVERLINK
+ 	unsigned next_buffer_table;
+ #else
+@@ -74,11 +80,11 @@ static int disable_dma_stats;
+  */
+ #define TX_DC_ENTRIES 16
+ #define TX_DC_ENTRIES_ORDER 0
+-#define TX_DC_BASE 0x130000
++#define TX_DC_INTERNAL_BASE 0x130000
+ 
+ #define RX_DC_ENTRIES 64
+ #define RX_DC_ENTRIES_ORDER 2
+-#define RX_DC_BASE 0x100000
++#define RX_DC_INTERNAL_BASE 0x100000
+ 
+ static const unsigned int
+ /* "Large" EEPROM device: Atmel AT25640 or similar
+@@ -468,9 +474,17 @@ void falcon_push_buffers(struct efx_tx_q
+ int falcon_probe_tx(struct efx_tx_queue *tx_queue)
+ {
+ 	struct efx_nic *efx = tx_queue->efx;
+-	return falcon_alloc_special_buffer(efx, &tx_queue->txd,
+-					   FALCON_TXD_RING_SIZE *
+-					   sizeof(efx_qword_t));
++	int rc = falcon_alloc_special_buffer(efx, &tx_queue->txd,
++					    FALCON_TXD_RING_SIZE *
++					    sizeof(efx_qword_t));
++#ifdef CONFIG_SFC_DRIVERLINK
++	if (rc == 0) {
++		struct falcon_nic_data *nic_data = efx->nic_data;
++		nic_data->resources.txq_min = max(nic_data->resources.txq_min,
++						  (unsigned)tx_queue->queue + 1);
++	}
++#endif
++	return rc;
+ }
+ 
+ void falcon_init_tx(struct efx_tx_queue *tx_queue)
+@@ -610,9 +624,17 @@ void falcon_notify_rx_desc(struct efx_rx
+ int falcon_probe_rx(struct efx_rx_queue *rx_queue)
+ {
+ 	struct efx_nic *efx = rx_queue->efx;
+-	return falcon_alloc_special_buffer(efx, &rx_queue->rxd,
+-					   FALCON_RXD_RING_SIZE *
+-					   sizeof(efx_qword_t));
++	int rc = falcon_alloc_special_buffer(efx, &rx_queue->rxd,
++					    FALCON_RXD_RING_SIZE *
++					    sizeof(efx_qword_t));
++#ifdef CONFIG_SFC_DRIVERLINK
++	if (rc == 0) {
++		struct falcon_nic_data *nic_data = efx->nic_data;
++		nic_data->resources.rxq_min = max(nic_data->resources.rxq_min,
++						  (unsigned)rx_queue->queue + 1);
++	}
++#endif
++	return rc;
+ }
+ 
+ void falcon_init_rx(struct efx_rx_queue *rx_queue)
+@@ -1120,9 +1142,18 @@ int falcon_probe_eventq(struct efx_chann
+ {
+ 	struct efx_nic *efx = channel->efx;
+ 	unsigned int evq_size;
++	int rc;
+ 
+ 	evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t);
+-	return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
++	rc = falcon_alloc_special_buffer(efx, &channel->eventq, evq_size);
++#ifdef CONFIG_SFC_DRIVERLINK
++	if (rc == 0) {
++		struct falcon_nic_data *nic_data = efx->nic_data;
++		nic_data->resources.evq_int_min = max(nic_data->resources.evq_int_min,
++						      (unsigned)channel->channel + 1);
++	}
++#endif
++	return rc;
+ }
+ 
+ void falcon_init_eventq(struct efx_channel *channel)
+@@ -2618,19 +2649,22 @@ fail5:
+  */
+ static int falcon_reset_sram(struct efx_nic *efx)
+ {
++	struct falcon_nic_data *nic_data = efx->nic_data;
+ 	efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker;
+-	int count;
++	int count, onchip, sram_cfg_val;
+ 
+ 	/* Set the SRAM wake/sleep GPIO appropriately. */
++	onchip = (nic_data->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, 1);
++	EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, onchip);
+ 	falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER);
+ 
+ 	/* Initiate SRAM reset */
++	sram_cfg_val = onchip ? 0 : nic_data->sram_cfg;
+ 	EFX_POPULATE_OWORD_2(srm_cfg_reg_ker,
+ 			     SRAM_OOB_BT_INIT_EN, 1,
+-			     SRM_NUM_BANKS_AND_BANK_SIZE, 0);
++			     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 */
+@@ -2702,8 +2736,10 @@ static void falcon_remove_spi_devices(st
+ /* Extract non-volatile configuration */
+ static int falcon_probe_nvconfig(struct efx_nic *efx)
+ {
++	struct falcon_nic_data *nic_data = efx->nic_data;
+ 	struct falcon_nvconfig *nvconfig;
+ 	int board_rev;
++	bool onchip_sram;
+ 	int rc;
+ 
+ 	nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL);
+@@ -2716,6 +2752,7 @@ static int falcon_probe_nvconfig(struct 
+ 		efx->phy_type = PHY_TYPE_NONE;
+ 		efx->mdio.prtad = MDIO_PRTAD_NONE;
+ 		board_rev = 0;
++		onchip_sram = true;
+ 		rc = 0;
+ 	} else if (rc) {
+ 		goto fail1;
+@@ -2726,6 +2763,13 @@ static int falcon_probe_nvconfig(struct 
+ 		efx->phy_type = v2->port0_phy_type;
+ 		efx->mdio.prtad = v2->port0_phy_addr;
+ 		board_rev = le16_to_cpu(v2->board_revision);
++#ifdef CONFIG_SFC_DRIVERLINK
++		onchip_sram = EFX_OWORD_FIELD(nvconfig->nic_stat_reg,
++					      ONCHIP_SRAM);
++#else
++		/* We have no use for external SRAM */
++		onchip_sram = true;
++#endif
+ 
+ 		if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) {
+ 			__le32 fl = v3->spi_device_type[EE_SPI_FLASH];
+@@ -2750,6 +2794,21 @@ static int falcon_probe_nvconfig(struct 
+ 
+ 	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) {
++		nic_data->sram_cfg = SRM_NB_BSZ_ONCHIP_ONLY;
++	} else {
++		nic_data->sram_cfg =
++			EFX_OWORD_FIELD(nvconfig->srm_cfg_reg,
++					SRM_NUM_BANKS_AND_BANK_SIZE);
++		WARN_ON(nic_data->sram_cfg == SRM_NB_BSZ_RESERVED);
++		/* Replace invalid setting with the smallest defaults */
++		if (nic_data->sram_cfg == SRM_NB_BSZ_DEFAULT)
++			nic_data->sram_cfg = SRM_NB_BSZ_1BANKS_2M;
++	}
++
+ 	kfree(nvconfig);
+ 	return 0;
+ 
+@@ -2765,9 +2824,9 @@ static int falcon_probe_nvconfig(struct 
+  * should live. */
+ static int falcon_dimension_resources(struct efx_nic *efx)
+ {
++	struct falcon_nic_data *nic_data = efx->nic_data;
+ #ifdef CONFIG_SFC_DRIVERLINK
+ 	unsigned internal_dcs_entries;
+-	struct falcon_nic_data *nic_data = efx->nic_data;
+ 	struct efx_dl_falcon_resources *res = &nic_data->resources;
+ 
+ 	/* Fill out the driverlink resource list */
+@@ -2800,16 +2859,64 @@ static int falcon_dimension_resources(st
+ 		break;
+ 	}
+ 
+-	/* Internal SRAM only for now */
+-	res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES;
+-	res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES;
+-	res->buffer_table_lim = 8192;
++	if (nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY) {
++		res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES;
++		res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES;
++		res->buffer_table_lim = 8192;
++		nic_data->tx_dc_base = TX_DC_INTERNAL_BASE;
++		nic_data->rx_dc_base = RX_DC_INTERNAL_BASE;
++	} else {
++		unsigned sram_bytes, vnic_bytes, max_vnics, n_vnics, dcs;
++
++		/* Determine how much SRAM we have to play with.  We have
++		 * to fit buffer table and descriptor caches in.
++		 */
++		switch (nic_data->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 * 8 + RX_DC_ENTRIES * 8 + 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_lim = n_vnics;
++		res->txq_lim = n_vnics;
++
++		dcs = n_vnics * TX_DC_ENTRIES * 8;
++		nic_data->tx_dc_base = sram_bytes - dcs;
++		dcs = n_vnics * RX_DC_ENTRIES * 8;
++		nic_data->rx_dc_base = nic_data->tx_dc_base - dcs;
++		res->buffer_table_lim = nic_data->rx_dc_base / 8;
++	}
+ 
+ 	if (FALCON_IS_DUAL_FUNC(efx))
+ 		res->flags |= EFX_DL_FALCON_DUAL_FUNC;
+ 
+ 	if (EFX_INT_MODE_USE_MSI(efx))
+ 		res->flags |= EFX_DL_FALCON_USE_MSI;
++#else
++	/* We ignore external SRAM */
++	EFX_BUG_ON_PARANOID(nic_data->sram_cfg != SRM_NB_BSZ_ONCHIP_ONLY);
++	nic_data->tx_dc_base = TX_DC_INTERNAL_BASE;
++	nic_data->rx_dc_base = RX_DC_INTERNAL_BASE;
+ #endif
+ 
+ 	return 0;
+@@ -2998,13 +3105,15 @@ int falcon_probe_nic(struct efx_nic *efx
+  */
+ int falcon_init_nic(struct efx_nic *efx)
+ {
++	struct falcon_nic_data *nic_data = efx->nic_data;
+ 	efx_oword_t temp;
+ 	unsigned thresh;
+ 	int rc;
+ 
+-	/* Use on-chip SRAM */
++	/* Use on-chip SRAM if wanted. */
+ 	falcon_read(efx, &temp, NIC_STAT_REG);
+-	EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
++	EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM,
++			    nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY);
+ 	falcon_write(efx, &temp, NIC_STAT_REG);
+ 
+ 	/* Set the source of the GMAC clock */
+@@ -3023,9 +3132,9 @@ int falcon_init_nic(struct efx_nic *efx)
+ 		return rc;
+ 
+ 	/* Set positions of descriptor caches in SRAM. */
+-	EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, TX_DC_BASE / 8);
++	EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, nic_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, RX_DC_BASE / 8);
++	EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, nic_data->rx_dc_base / 8);
+ 	falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER);
+ 
+ 	/* Set TX descriptor cache size. */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/add-console-use-vt
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/add-console-use-vt
@@ -0,0 +1,51 @@
+Subject: add console_use_vt
+From: kraxel@suse.de
+Patch-mainline: no
+
+$subject says all
+
+---
+ drivers/char/tty_io.c   |    7 ++++++-
+ include/linux/console.h |    1 +
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+--- head-2009-10-12.orig/drivers/char/tty_io.c	2009-10-12 11:46:55.000000000 +0200
++++ head-2009-10-12/drivers/char/tty_io.c	2009-10-12 12:16:48.000000000 +0200
+@@ -136,6 +136,8 @@ LIST_HEAD(tty_drivers);			/* linked list
+ DEFINE_MUTEX(tty_mutex);
+ EXPORT_SYMBOL(tty_mutex);
+ 
++int console_use_vt = 1;
++
+ static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
+ static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
+ ssize_t redirected_tty_write(struct file *, const char __user *,
+@@ -1736,7 +1738,7 @@ retry_open:
+ 		goto got_driver;
+ 	}
+ #ifdef CONFIG_VT
+-	if (device == MKDEV(TTY_MAJOR, 0)) {
++	if (console_use_vt && device == MKDEV(TTY_MAJOR, 0)) {
+ 		extern struct tty_driver *console_driver;
+ 		driver = tty_driver_kref_get(console_driver);
+ 		index = fg_console;
+@@ -3136,7 +3138,8 @@ static int __init tty_init(void)
+ 			      "console");
+ 
+ #ifdef CONFIG_VT
+-	vty_init(&console_fops);
++	if (console_use_vt)
++		vty_init(&console_fops);
+ #endif
+ 	return 0;
+ }
+--- head-2009-10-12.orig/include/linux/console.h	2009-10-12 11:47:00.000000000 +0200
++++ head-2009-10-12/include/linux/console.h	2009-10-12 12:16:48.000000000 +0200
+@@ -63,6 +63,7 @@ extern const struct consw dummy_con;	/* 
+ extern const struct consw vga_con;	/* VGA text console */
+ extern const struct consw newport_con;	/* SGI Newport console  */
+ extern const struct consw prom_con;	/* SPARC PROM console */
++extern int console_use_vt;
+ 
+ int con_is_bound(const struct consw *csw);
+ int register_con_driver(const struct consw *csw, int first, int last);
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/pci-guestdev
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/pci-guestdev
@@ -0,0 +1,2638 @@
+Subject: xen/dom0: Reserve devices for guest use
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 898:ca12928cdafe)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/Documentation/kernel-parameters.txt	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/Documentation/kernel-parameters.txt	2009-12-04 10:27:46.000000000 +0100
+@@ -808,6 +808,24 @@ and is between 256 and 4096 characters. 
+ 	gpt		[EFI] Forces disk with valid GPT signature but
+ 			invalid Protective MBR to be treated as GPT.
+ 
++	guestdev=	[PCI,ACPI,XEN]
++			Format: {<device path>|<sbdf>}][,{<device path>|<sbdf>}[,...]]
++			Format of device path: <hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]][+iomul]
++			Format of sbdf: [<segment>:]<bus>:<dev>.<func>[+iomul]
++			Specifies PCI device for guest domain.
++			If PCI-PCI bridge is specified, all PCI devices
++			behind PCI-PCI bridge are reserved.
++			+iomul means that this PCI function will share
++			IO ports with other +iomul functions under same
++			switch. NOTE: if +iomul is specfied, all the functions
++			of the device will share IO ports.
++
++	guestiomuldev=	[PCI,ACPI,XEN]
++			Format: [sbd][,<sbd>][,...]
++			Format of sbdf: [<segment>:]<bus>:<dev>
++			Note: function shouldn't be specified.
++			Specifies PCI device for IO port multiplexing driver.
++
+ 	gvp11=		[HW,SCSI]
+ 
+ 	hashdist=	[KNL,NUMA] Large hashes allocated during boot
+@@ -2127,6 +2145,10 @@ and is between 256 and 4096 characters. 
+ 			Run specified binary instead of /init from the ramdisk,
+ 			used for early userspace startup. See initrd.
+ 
++	reassign_resources	[PCI,ACPI,XEN]
++			Use guestdev= parameter to reassign device's
++			resources.
++
+ 	reboot=		[BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
+ 			Format: <reboot_mode>[,<reboot_mode2>[,...]]
+ 			See arch/*/kernel/reboot.c or arch/*/kernel/process.c
+--- head-2010-01-18.orig/drivers/acpi/pci_root.c	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/acpi/pci_root.c	2009-12-04 10:27:46.000000000 +0100
+@@ -465,6 +465,40 @@ out:
+ }
+ EXPORT_SYMBOL(acpi_pci_osc_control_set);
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++#include <linux/sysfs.h>
++
++static ssize_t seg_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct list_head *entry;
++
++	list_for_each(entry, &acpi_pci_roots) {
++		struct acpi_pci_root *root;
++		root = list_entry(entry, struct acpi_pci_root, node);
++		if (&root->device->dev == dev)
++			return sprintf(buf, "%04x\n", root->segment);
++	}
++	return 0;
++}
++static DEVICE_ATTR(seg, 0444, seg_show, NULL);
++
++static ssize_t bbn_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
++{
++	struct list_head *entry;
++
++	list_for_each(entry, &acpi_pci_roots) {
++		struct acpi_pci_root *root;
++		root = list_entry(entry, struct acpi_pci_root, node);
++		if (&root->device->dev == dev)
++			return sprintf(buf, "%02x\n", root->bus_nr);
++	}
++	return 0;
++}
++static DEVICE_ATTR(bbn, 0444, bbn_show, NULL);
++#endif
++
+ static int __devinit acpi_pci_root_add(struct acpi_device *device)
+ {
+ 	unsigned long long segment, bus;
+@@ -576,6 +610,13 @@ static int __devinit acpi_pci_root_add(s
+ 	if (flags != base_flags)
+ 		acpi_pci_osc_support(root, flags);
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++	if (device_create_file(&device->dev, &dev_attr_seg))
++		dev_warn(&device->dev, "could not create seg attr\n");
++	if (device_create_file(&device->dev, &dev_attr_bbn))
++		dev_warn(&device->dev, "could not create bbn attr\n");
++#endif
++
+ 	return 0;
+ 
+ end:
+@@ -613,3 +654,31 @@ static int __init acpi_pci_root_init(voi
+ }
+ 
+ subsys_initcall(acpi_pci_root_init);
++
++#ifdef CONFIG_PCI_GUESTDEV
++int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn)
++{
++	struct list_head *entry;
++
++	list_for_each(entry, &acpi_pci_roots) {
++		struct acpi_pci_root *root;
++
++		root = list_entry(entry, struct acpi_pci_root, node);
++		if (strcmp(acpi_device_hid(root->device), hid))
++			continue;
++
++		if (!root->device->pnp.unique_id) {
++			if (strlen(uid))
++				continue;
++		} else {
++			if (strcmp(root->device->pnp.unique_id, uid))
++				continue;
++		}
++
++		*seg = (int)root->segment;
++		*bbn = (int)root->bus_nr;
++		return TRUE;
++	}
++	return FALSE;
++}
++#endif
+--- head-2010-01-18.orig/drivers/acpi/scan.c	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/acpi/scan.c	2009-12-04 10:27:46.000000000 +0100
+@@ -168,6 +168,16 @@ acpi_device_hid_show(struct device *dev,
+ }
+ static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++static ssize_t
++acpi_device_uid_show(struct device *dev, struct device_attribute *attr, char *buf) {
++	struct acpi_device *acpi_dev = to_acpi_device(dev);
++
++	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
++}
++static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
++#endif
++
+ static ssize_t
+ acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ 	struct acpi_device *acpi_dev = to_acpi_device(dev);
+@@ -208,6 +218,13 @@ static int acpi_device_setup_files(struc
+ 	if (result)
+ 		goto end;
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++	if(dev->pnp.unique_id) {
++		result = device_create_file(&dev->dev, &dev_attr_uid);
++		if(result)
++			goto end;
++	}
++#endif
+         /*
+          * If device has _EJ0, 'eject' file is created that is used to trigger
+          * hot-removal function from userland.
+@@ -271,6 +288,9 @@ static void acpi_free_ids(struct acpi_de
+ 		kfree(id->id);
+ 		kfree(id);
+ 	}
++#ifdef CONFIG_PCI_GUESTDEV
++	kfree(device->pnp.unique_id);
++#endif
+ }
+ 
+ static void acpi_device_release(struct device *dev)
+@@ -1047,6 +1067,11 @@ static void acpi_device_set_id(struct ac
+ 			for (i = 0; i < cid_list->count; i++)
+ 				acpi_add_id(device, cid_list->ids[i].string);
+ 		}
++#ifdef CONFIG_PCI_GUESTDEV
++		if (info->valid & ACPI_VALID_UID)
++			device->pnp.unique_id = kstrdup(info->unique_id.string,
++							GFP_KERNEL);
++#endif
+ 		if (info->valid & ACPI_VALID_ADR) {
+ 			device->pnp.bus_address = info->address;
+ 			device->flags.bus_address = 1;
+--- head-2010-01-18.orig/drivers/pci/Kconfig	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/pci/Kconfig	2009-12-04 10:27:46.000000000 +0100
+@@ -42,6 +42,20 @@ config PCI_DEBUG
+ 
+ 	  When in doubt, say N.
+ 
++config PCI_GUESTDEV
++	bool "PCI Device Reservation for Passthrough"
++	depends on PCI && ACPI && XEN
++	default y
++	help
++	  Say Y here if you want to reserve PCI device for passthrough.
++
++config PCI_IOMULTI
++	bool "PCI Device IO Multiplex for Passthrough"
++	depends on PCI && ACPI && XEN
++	default y
++	help
++	  Say Y here if you need io multiplexing.
++
+ config PCI_STUB
+ 	tristate "PCI Stub driver"
+ 	depends on PCI
+--- head-2010-01-18.orig/drivers/pci/Makefile	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/pci/Makefile	2009-12-04 10:27:46.000000000 +0100
+@@ -7,6 +7,8 @@ obj-y		+= access.o bus.o probe.o remove.
+ 			irq.o
+ obj-$(CONFIG_PROC_FS) += proc.o
+ obj-$(CONFIG_SYSFS) += slot.o
++obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
++obj-$(CONFIG_PCI_IOMULTI) += iomulti.o
+ 
+ obj-$(CONFIG_PCI_LEGACY) += legacy.o
+ CFLAGS_legacy.o += -Wno-deprecated-declarations
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/pci/guestdev.c	2009-12-04 10:27:46.000000000 +0100
+@@ -0,0 +1,887 @@
++/*
++ * Copyright (c) 2008, 2009 NEC Corporation.
++ * Copyright (c) 2009 Isaku Yamahata
++ *                    VA Linux Systems Japan K.K.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
++ * Place - Suite 330, Boston, MA 02111-1307 USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/mm.h>
++#include <linux/pci.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/acpi.h>
++#include <asm/setup.h>
++
++#define HID_LEN 8
++#define UID_LEN 8
++#define DEV_LEN 2
++#define FUNC_LEN 1
++#define DEV_NUM_MAX 31
++#define FUNC_NUM_MAX 7
++#define INVALID_SEG (-1)
++#define INVALID_BBN (-1)
++#define GUESTDEV_STR_MAX 128
++
++#define GUESTDEV_FLAG_TYPE_MASK 0x3
++#define GUESTDEV_FLAG_DEVICEPATH 0x1
++#define GUESTDEV_FLAG_SBDF 0x2
++
++#define GUESTDEV_OPT_IOMUL	0x1
++
++struct guestdev {
++	int flags;
++	int options;
++	struct list_head root_list;
++	union {
++		struct devicepath {
++			char hid[HID_LEN + 1];
++			char uid[UID_LEN + 1];
++			int seg;
++			int bbn;
++			struct devicepath_node *child;
++		} devicepath;
++		struct sbdf {
++			int seg;
++			int bus;
++			int dev;
++			int func;
++		} sbdf;
++	} u;
++};
++
++struct devicepath_node {
++	int dev;
++	int func;
++	struct devicepath_node *child;
++};
++
++struct pcidev_sbdf {
++	int seg;
++	int bus;
++	struct pcidev_sbdf_node *child;
++};
++
++struct pcidev_sbdf_node {
++	int dev;
++	int func;
++	struct pcidev_sbdf_node *child;
++};
++
++static char guestdev_param[COMMAND_LINE_SIZE];
++static LIST_HEAD(guestdev_list);
++
++/* Get hid and uid */
++static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
++{
++	char *sp, *ep;
++	int len;
++
++	sp = str;
++	ep = strchr(sp, ':');
++	if (!ep) {
++		ep = strchr(sp, '-');
++		if (!ep)
++			goto format_err_end;
++	}
++	/* hid length */
++	len = ep - sp;
++	if (len <= 0 || HID_LEN < len)
++		goto format_err_end;
++
++	strlcpy(hid, sp, len);
++
++	if (*ep == '-') { /* no uid */
++		uid[0] = '\0';
++		return TRUE;
++	}
++
++	sp = ep + 1;
++	ep = strchr(sp, '-');
++	if (!ep)
++		ep = strchr(sp, '\0');
++
++	/* uid length */
++	len = ep - sp;
++	if (len <= 0 || UID_LEN < len)
++		goto format_err_end;
++
++	strlcpy(uid, sp, len);
++	return TRUE;
++
++format_err_end:
++	return FALSE;
++}
++
++/* Get device and function */
++static int __init pci_get_dev_func(char *str, int *dev, int *func)
++{
++	if (sscanf(str, "%02x.%01x", dev, func) != 2)
++		goto format_err_end;
++
++	if (*dev < 0 || DEV_NUM_MAX < *dev)
++		goto format_err_end;
++
++	if (*func < 0 || FUNC_NUM_MAX < *func)
++		goto format_err_end;
++
++	return TRUE;
++
++format_err_end:
++	return FALSE;
++}
++
++/* Check extended guestdev parameter format error */
++static int __init pci_check_extended_guestdev_format(char *str)
++{
++	int flg;
++	char *p;
++
++	/* Check extended format */
++	if (strpbrk(str, "(|)") == NULL)
++		return TRUE;
++
++	flg = 0;
++	p = str;
++	while (*p) {
++		switch (*p) {
++		case '(':
++			/* Check nesting error */
++			if (flg != 0)
++				goto format_err_end;
++			flg = 1;
++			/* Check position of '(' is head or
++			   previos charactor of '(' is not '-'. */
++			if (p == str || *(p - 1) != '-')
++				goto format_err_end;
++			break;
++		case ')':
++			/* Check nesting error */
++			if (flg != 1)
++				goto format_err_end;
++			flg = 0;
++			/* Check next charactor of ')' is not '\0' */
++			if (*(p + 1) != '\0')
++				goto format_err_end;
++			break;
++		case '|':
++			/* Check position of '|' is outside of '(' and ')' */
++			if (flg != 1)
++				goto format_err_end;
++			break;
++		default:
++			break;
++		}
++		p++;
++	}
++	/* Check number of '(' and ')' are not equal */
++	if (flg != 0)
++		goto format_err_end;
++	return TRUE;
++
++format_err_end:
++	printk(KERN_ERR
++		"PCI: The format of the guestdev parameter is illegal. [%s]\n",
++		str);
++	return FALSE;
++}
++
++/* Make guestdev strings */
++static void pci_make_guestdev_str(struct guestdev *gdev,
++					char *gdev_str, int buf_size)
++{
++	struct devicepath_node *node;
++	int count;
++
++	switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
++	case GUESTDEV_FLAG_DEVICEPATH:
++		memset(gdev_str, 0, buf_size);
++
++		if (strlen(gdev->u.devicepath.uid))
++			count = snprintf(gdev_str, buf_size, "%s:%s",
++						gdev->u.devicepath.hid,
++						gdev->u.devicepath.uid);
++		else
++			count = snprintf(gdev_str, buf_size, "%s",
++						 gdev->u.devicepath.hid);
++		if (count < 0)
++			return;
++
++		node = gdev->u.devicepath.child;
++		while (node) {
++			gdev_str += count;
++			buf_size -= count;
++			if (buf_size <= 0)
++				return;
++			count = snprintf(gdev_str, buf_size, "-%02x.%01x",
++				node->dev, node->func);
++			if (count < 0)
++				return;
++			node = node->child;
++		}
++		break;
++	case GUESTDEV_FLAG_SBDF:
++		snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
++					gdev->u.sbdf.seg, gdev->u.sbdf.bus,
++					gdev->u.sbdf.dev, gdev->u.sbdf.func);
++		break;
++	default:
++		BUG();
++	}
++}
++
++/* Free guestdev and nodes */
++static void __init pci_free_guestdev(struct guestdev *gdev)
++{
++	struct devicepath_node *node, *next;
++
++	if (!gdev)
++		return;
++	if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
++		node = gdev->u.devicepath.child;
++		while (node) {
++			next = node->child;
++			kfree(node);
++			node = next;
++		}
++	}
++	list_del(&gdev->root_list);
++	kfree(gdev);
++}
++
++/* Copy guestdev and nodes */
++struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
++{
++	struct guestdev *gdev;
++	struct devicepath_node *node, *node_src, *node_upper;
++
++	BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
++
++	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
++	if (!gdev)
++		goto allocate_err_end;
++
++	memset(gdev, 0, sizeof(*gdev));
++	INIT_LIST_HEAD(&gdev->root_list);
++	gdev->flags = gdev_src->flags;
++	gdev->options = gdev_src->options;
++	strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
++	strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
++	gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
++	gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
++
++	node_upper = NULL;
++
++	node_src = gdev_src->u.devicepath.child;
++	while (node_src) {
++		node = kmalloc(sizeof(*node), GFP_KERNEL);
++		if (!node)
++			goto allocate_err_end;
++		memset(node, 0, sizeof(*node));
++		node->dev = node_src->dev;
++		node->func = node_src->func;
++		if (!node_upper)
++			gdev->u.devicepath.child = node;
++		else
++			node_upper->child = node;
++		node_upper = node;
++		node_src = node_src->child;
++	}
++
++	return gdev;
++
++allocate_err_end:
++	if (gdev)
++		pci_free_guestdev(gdev);
++	printk(KERN_ERR "PCI: Failed to allocate memory.\n");
++	return NULL;
++}
++
++/* Make guestdev from path strings */
++static int __init pci_make_devicepath_guestdev(char *path_str, int options)
++{
++	char hid[HID_LEN + 1], uid[UID_LEN + 1];
++	char *sp, *ep;
++	struct guestdev *gdev, *gdev_org;
++	struct devicepath_node *node, *node_tmp;
++	int dev, func, ret_val;
++
++	ret_val = 0;
++	gdev = gdev_org = NULL;
++	sp = path_str;
++	/* Look for end of hid:uid'-' */
++	ep = strchr(sp, '-');
++	/* Only hid, uid. (No dev, func) */
++	if (!ep)
++		goto format_err_end;
++
++	memset(hid, 0 ,sizeof(hid));
++	memset(uid, 0, sizeof(uid));
++	if (!pci_get_hid_uid(sp, hid, uid))
++		goto format_err_end;
++
++	gdev_org = kmalloc(sizeof(*gdev_org), GFP_KERNEL);
++	if (!gdev_org)
++		goto allocate_err_end;
++	memset(gdev_org, 0, sizeof(*gdev_org));
++	INIT_LIST_HEAD(&gdev_org->root_list);
++	gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
++	gdev_org->options = options;
++	strcpy(gdev_org->u.devicepath.hid, hid);
++	strcpy(gdev_org->u.devicepath.uid, uid);
++	gdev_org->u.devicepath.seg = INVALID_SEG;
++	gdev_org->u.devicepath.bbn = INVALID_BBN;
++
++	gdev = gdev_org;
++
++	sp = ep + 1;
++	ep = sp;
++	do {
++		if (*sp == '(') {
++			sp++;
++			if (strchr(sp, '|')) {
++				gdev = pci_copy_guestdev(gdev_org);
++				if (!gdev) {
++					ret_val = -ENOMEM;
++					goto end;
++				}
++			}
++			continue;
++		}
++		if (gdev && pci_get_dev_func(sp, &dev, &func)) {
++			node = kmalloc(sizeof(*node), GFP_KERNEL);
++			if (!node)
++				goto allocate_err_end;
++			memset(node, 0, sizeof(*node));
++			node->dev = dev;
++			node->func = func;
++			/* add node to end of guestdev */
++			if (gdev->u.devicepath.child) {
++				node_tmp = gdev->u.devicepath.child;
++				while (node_tmp->child) {
++					node_tmp = node_tmp->child;
++				}
++				node_tmp->child = node;
++			} else
++				gdev->u.devicepath.child = node;
++		} else if (gdev) {
++			printk(KERN_ERR
++				"PCI: Can't obtain dev# and #func# from %s.\n",
++				sp);
++			ret_val = -EINVAL;
++			if (gdev == gdev_org)
++				goto end;
++			pci_free_guestdev(gdev);
++			gdev = NULL;
++		}
++
++		ep = strpbrk(sp, "-|)");
++		if (!ep)
++			ep = strchr(sp, '\0');
++		/* Is *ep '|' OR ')' OR '\0' ? */
++		if (*ep != '-') {
++			if (gdev)
++				list_add_tail(&gdev->root_list, &guestdev_list);
++			if (*ep == '|') {
++				/* Between '|' and '|' ? */
++				if (strchr(ep + 1, '|')) {
++					gdev = pci_copy_guestdev(gdev_org);
++					if (!gdev) {
++						ret_val = -ENOMEM;
++						goto end;
++					}
++				} else {
++					gdev = gdev_org;
++					gdev_org = NULL;
++				}
++			} else {
++				gdev_org = NULL;
++				gdev = NULL;
++			}
++		}
++		if (*ep == ')')
++			ep++;
++		sp = ep + 1;
++	} while (*ep != '\0');
++
++	goto end;
++
++format_err_end:
++	printk(KERN_ERR
++		"PCI: The format of the guestdev parameter is illegal. [%s]\n",
++		path_str);
++	ret_val = -EINVAL;
++	goto end;
++
++allocate_err_end:
++	printk(KERN_ERR "PCI: Failed to allocate memory.\n");
++	ret_val = -ENOMEM;
++	goto end;
++
++end:
++	if (gdev_org && (gdev_org != gdev))
++		pci_free_guestdev(gdev_org);
++	if (gdev)
++		pci_free_guestdev(gdev);
++	return ret_val;
++}
++
++static int __init pci_make_sbdf_guestdev(char* str, int options)
++{
++	struct guestdev *gdev;
++	int seg, bus, dev, func;
++
++	if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
++		seg = 0;
++		if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
++			return -EINVAL;
++	}
++	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
++	if (!gdev) {
++		printk(KERN_ERR "PCI: Failed to allocate memory.\n");
++		return -ENOMEM;
++	}
++	INIT_LIST_HEAD(&gdev->root_list);
++	gdev->flags = GUESTDEV_FLAG_SBDF;
++	gdev->options = options;
++	gdev->u.sbdf.seg = seg;
++	gdev->u.sbdf.bus = bus;
++	gdev->u.sbdf.dev = dev;
++	gdev->u.sbdf.func = func;
++	list_add_tail(&gdev->root_list, &guestdev_list);
++	return 0;
++}
++
++static int __init pci_parse_options(const char *str)
++{
++	int options = 0;
++	char *ep;
++
++	while (str) {
++		str++;
++		ep = strchr(str, '+');
++		if (ep)
++			ep = '\0';	/* Chop */
++
++		if (!strcmp(str, "iomul"))
++			options |= GUESTDEV_OPT_IOMUL;
++
++		str = ep;
++	}
++	return options;
++}
++
++/* Parse guestdev parameter */
++static int __init pci_parse_guestdev(void)
++{
++	int len;
++	char *sp, *ep, *op;
++	int options;
++	struct list_head *head;
++	struct guestdev *gdev;
++	char path_str[GUESTDEV_STR_MAX];
++	int ret_val = 0;
++
++	len = strlen(guestdev_param);
++	if (len == 0)
++		return 0;
++
++	sp = guestdev_param;
++
++	do {
++		ep = strchr(sp, ',');
++		/* Chop */
++		if (ep)
++			*ep = '\0';
++		options = 0;
++		op = strchr(sp, '+');
++		if (op && (!ep || op < ep)) {
++			options = pci_parse_options(op);
++			*op = '\0';	/* Chop */
++		}
++		ret_val = pci_make_sbdf_guestdev(sp, options);
++		if (ret_val == -EINVAL) {
++			if (pci_check_extended_guestdev_format(sp)) {
++				ret_val = pci_make_devicepath_guestdev(
++					sp, options);
++				if (ret_val && ret_val != -EINVAL)
++					break;
++			}
++		} else if (ret_val)
++			break;
++
++		if (ep)
++			ep++;
++		sp = ep;
++	} while (ep);
++
++	list_for_each(head, &guestdev_list) {
++		gdev = list_entry(head, struct guestdev, root_list);
++		pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
++		printk(KERN_DEBUG
++			"PCI: %s has been reserved for guest domain.\n",
++			path_str);
++	}
++	return 0;
++}
++
++arch_initcall(pci_parse_guestdev);
++
++/* Get command line */
++static int __init pci_guestdev_setup(char *str)
++{
++	if (strlen(str) >= COMMAND_LINE_SIZE)
++		return 0;
++	strlcpy(guestdev_param, str, sizeof(guestdev_param));
++	return 1;
++}
++
++__setup("guestdev=", pci_guestdev_setup);
++
++/* Free sbdf and nodes */
++static void pci_free_sbdf(struct pcidev_sbdf *sbdf)
++{
++	struct pcidev_sbdf_node *node, *next;
++
++	node = sbdf->child;
++	while (node) {
++		next = node->child;
++		kfree(node);
++		node = next;
++	}
++	/* Skip kfree(sbdf) */
++}
++
++/* Does PCI device belong to sub tree specified by guestdev with device path? */
++typedef int (*pci_node_match_t)(const struct devicepath_node *gdev_node,
++				const struct pcidev_sbdf_node *sbdf_node,
++				int options);
++
++static int pci_node_match(const struct devicepath_node *gdev_node,
++			  const struct pcidev_sbdf_node *sbdf_node,
++			  int options_unused)
++{
++	return (gdev_node->dev == sbdf_node->dev &&
++		gdev_node->func == sbdf_node->func);
++}
++
++static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
++					 struct pcidev_sbdf *sbdf,
++					 pci_node_match_t match)
++{
++	int seg, bbn;
++	struct devicepath_node *gdev_node;
++	struct pcidev_sbdf_node *sbdf_node;
++
++	if (!gdev || !sbdf)
++		return FALSE;
++
++	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
++
++	/* Compare seg and bbn */
++	if (gdev->u.devicepath.seg == INVALID_SEG ||
++	    gdev->u.devicepath.bbn == INVALID_BBN) {
++		if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
++		    gdev->u.devicepath.uid, &seg, &bbn)) {
++			gdev->u.devicepath.seg = seg;
++			gdev->u.devicepath.bbn = bbn;
++		} else
++			return FALSE;
++	}
++
++	if (gdev->u.devicepath.seg != sbdf->seg ||
++	    gdev->u.devicepath.bbn != sbdf->bus)
++		return FALSE;
++
++	gdev_node = gdev->u.devicepath.child;
++	sbdf_node = sbdf->child;
++
++	/* Compare dev and func */
++	while (gdev_node) {
++		if (!sbdf_node)
++			return FALSE;
++		if (!match(gdev_node, sbdf_node, gdev->options))
++			return FALSE;
++		gdev_node = gdev_node->child;
++		sbdf_node = sbdf_node->child;
++	}
++	return TRUE;
++}
++
++/* Get sbdf from device */
++static int pci_get_sbdf_from_pcidev(
++	struct pci_dev *dev, struct pcidev_sbdf *sbdf)
++{
++	struct pcidev_sbdf_node *node;
++
++	if (!dev)
++		return FALSE;
++
++	for(;;) {
++		node = kmalloc(sizeof(*node), GFP_KERNEL);
++		if (!node) {
++			printk(KERN_ERR "PCI: Failed to allocate memory.\n");
++			goto err_end;
++		}
++		memset(node, 0, sizeof(*node));
++		node->dev = PCI_SLOT(dev->devfn);
++		node->func = PCI_FUNC(dev->devfn);
++
++		if (!sbdf->child)
++			sbdf->child = node;
++		else {
++			node->child = sbdf->child;
++			sbdf->child = node;
++		}
++		if (!dev->bus)
++			goto err_end;
++		if (!dev->bus->self)
++			break;
++		dev = dev->bus->self;
++	}
++	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &sbdf->seg, &sbdf->bus) != 2)
++		goto err_end;
++	return TRUE;
++
++err_end:
++	pci_free_sbdf(sbdf);
++	return FALSE;
++}
++
++/* Does PCI device belong to sub tree specified by guestdev with sbdf? */
++typedef int (*pci_sbdf_match_t)(const struct guestdev *gdev,
++				const  struct pci_dev *dev);
++
++static int pci_sbdf_match(const struct guestdev *gdev,
++			  const struct pci_dev *dev)
++{
++	int seg, bus;
++
++	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2)
++		return FALSE;
++
++	return gdev->u.sbdf.seg == seg &&
++		gdev->u.sbdf.bus == bus &&
++		gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
++		gdev->u.sbdf.func == PCI_FUNC(dev->devfn);
++}
++
++static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev,
++				   pci_sbdf_match_t match)
++{
++	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
++	for (;;) {
++		if (match(gdev, dev))
++			return TRUE;
++		if (!dev->bus || !dev->bus->self)
++			break;
++		dev = dev->bus->self;
++	}
++	return FALSE;
++}
++
++/* Does PCI device belong to sub tree specified by guestdev parameter? */
++static int __pci_is_guestdev(struct pci_dev *dev, pci_node_match_t node_match,
++			     pci_sbdf_match_t sbdf_match)
++{
++	struct guestdev *gdev;
++	struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
++	struct list_head *head;
++	int result = FALSE;
++
++	if (!dev)
++		return FALSE;
++
++	list_for_each(head, &guestdev_list) {
++		gdev = list_entry(head, struct guestdev, root_list);
++		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
++		case GUESTDEV_FLAG_DEVICEPATH:
++			if (sbdf == NULL) {
++				sbdf = &pcidev_sbdf;
++				memset(sbdf, 0 ,sizeof(*sbdf));
++				if (!pci_get_sbdf_from_pcidev(dev, sbdf))
++					goto out;
++			}
++			if (pci_is_in_devicepath_sub_tree(gdev, sbdf,
++							  node_match)) {
++				result = TRUE;
++				goto out;
++			}
++			break;
++		case GUESTDEV_FLAG_SBDF:
++			if (pci_is_in_sbdf_sub_tree(gdev, dev, sbdf_match)) {
++				result = TRUE;
++				goto out;
++			}
++			break;
++		default:
++			BUG();
++		}
++	}
++out:
++	if (sbdf)
++		pci_free_sbdf(sbdf);
++	return result;
++}
++
++int pci_is_guestdev(struct pci_dev *dev)
++{
++	return __pci_is_guestdev(dev, pci_node_match, pci_sbdf_match);
++}
++EXPORT_SYMBOL_GPL(pci_is_guestdev);
++
++static int reassign_resources;
++
++static int __init pci_set_reassign_resources(char *str)
++{
++	reassign_resources = 1;
++
++	return 1;
++}
++__setup("reassign_resources", pci_set_reassign_resources);
++
++int pci_is_guestdev_to_reassign(struct pci_dev *dev)
++{
++	if (reassign_resources)
++		return pci_is_guestdev(dev);
++	return FALSE;
++}
++
++#ifdef CONFIG_PCI_IOMULTI
++static int pci_iomul_node_match(const struct devicepath_node *gdev_node,
++				const struct pcidev_sbdf_node *sbdf_node,
++				int options)
++{
++	return (options & GUESTDEV_OPT_IOMUL) &&
++		((gdev_node->child != NULL &&
++		  sbdf_node->child != NULL &&
++		  gdev_node->dev == sbdf_node->dev &&
++		  gdev_node->func == sbdf_node->func) ||
++		 (gdev_node->child == NULL &&
++		  sbdf_node->child == NULL &&
++		  gdev_node->dev == sbdf_node->dev));
++}
++
++static int pci_iomul_sbdf_match(const struct guestdev *gdev,
++				const struct pci_dev *dev)
++{
++	int seg, bus;
++
++	if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2)
++		return FALSE;
++
++	return (gdev->options & GUESTDEV_OPT_IOMUL) &&
++		gdev->u.sbdf.seg == seg &&
++		gdev->u.sbdf.bus == bus &&
++		gdev->u.sbdf.dev == PCI_SLOT(dev->devfn);
++}
++
++int pci_is_iomuldev(struct pci_dev *dev)
++{
++	return __pci_is_guestdev(dev,
++				 pci_iomul_node_match, pci_iomul_sbdf_match);
++}
++#endif /* CONFIG_PCI_IOMULTI */
++
++/* Check whether the devicepath exists under the pci root bus */
++static int __init pci_check_devicepath_exists(
++		struct guestdev *gdev, struct pci_bus *bus)
++{
++	struct devicepath_node *node;
++	struct pci_dev *dev;
++
++	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
++
++	node = gdev->u.devicepath.child;
++	while (node) {
++		if (!bus)
++			return FALSE;
++		dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
++		if (!dev)
++			return FALSE;
++		bus = dev->subordinate;
++		node = node->child;
++		pci_dev_put(dev);
++	}
++	return TRUE;
++}
++
++/* Check whether the guestdev exists in the PCI device tree */
++static int __init pci_check_guestdev_exists(void)
++{
++	struct list_head *head;
++	struct guestdev *gdev;
++	int seg, bbn;
++	struct pci_bus *bus;
++	struct pci_dev *dev;
++	char path_str[GUESTDEV_STR_MAX];
++
++	list_for_each(head, &guestdev_list) {
++		gdev = list_entry(head, struct guestdev, root_list);
++		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
++		case GUESTDEV_FLAG_DEVICEPATH:
++			if (gdev->u.devicepath.seg == INVALID_SEG ||
++				gdev->u.devicepath.bbn == INVALID_BBN) {
++				if (acpi_pci_get_root_seg_bbn(
++					gdev->u.devicepath.hid,
++					gdev->u.devicepath.uid, &seg, &bbn)) {
++					gdev->u.devicepath.seg = seg;
++					gdev->u.devicepath.bbn = bbn;
++				} else {
++					pci_make_guestdev_str(gdev,
++						path_str, GUESTDEV_STR_MAX);
++					printk(KERN_INFO
++					"PCI: Device does not exist. %s\n",
++					path_str);
++					continue;
++				}
++			}
++
++			bus = pci_find_bus(gdev->u.devicepath.seg,
++						gdev->u.devicepath.bbn);
++			if (!bus ||
++				!pci_check_devicepath_exists(gdev, bus)) {
++				pci_make_guestdev_str(gdev, path_str,
++					GUESTDEV_STR_MAX);
++				printk(KERN_INFO
++					"PCI: Device does not exist. %s\n",
++					path_str);
++			}
++			break;
++		case GUESTDEV_FLAG_SBDF:
++			bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
++			if (bus) {
++				dev = pci_get_slot(bus,
++					PCI_DEVFN(gdev->u.sbdf.dev,
++							gdev->u.sbdf.func));
++				if (dev) {
++					pci_dev_put(dev);
++					continue;
++				}
++			}
++			pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
++			printk(KERN_INFO "PCI: Device does not exist. %s\n",
++								path_str);
++			break;
++		default:
++			BUG();
++		}
++	}
++	return 0;
++}
++
++fs_initcall(pci_check_guestdev_exists);
++
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/pci/iomulti.c	2009-12-04 10:27:46.000000000 +0100
+@@ -0,0 +1,1415 @@
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ *
++ * Copyright (c) 2009 Isaku Yamahata
++ *                    VA Linux Systems Japan K.K.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/pci.h>
++#include <linux/sort.h>
++
++#include <asm/setup.h>
++#include <asm/uaccess.h>
++
++#include "pci.h"
++#include "iomulti.h"
++
++#define PCI_NUM_BARS		6
++#define PCI_BUS_MAX		255
++#define PCI_DEV_MAX		31
++#define PCI_FUNC_MAX		7
++#define PCI_NUM_FUNC		8
++
++/* see pci_resource_len */
++static inline resource_size_t pci_iomul_len(const struct resource* r)
++{
++	if (r->start == 0 && r->start == r->end)
++		return 0;
++	return r->end - r->start + 1;
++}
++
++#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
++/* stolen from pbus_size_io() */
++static unsigned long pdev_size_io(struct pci_dev *pdev)
++{
++	unsigned long size = 0, size1 = 0;
++	int i;
++
++	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++		struct resource *r = &pdev->resource[i];
++		unsigned long r_size;
++
++		if (!(r->flags & IORESOURCE_IO))
++			continue;
++
++		r_size = r->end - r->start + 1;
++
++		if (r_size < 0x400)
++			/* Might be re-aligned for ISA */
++			size += r_size;
++		else
++			size1 += r_size;
++	}
++
++/* To be fixed in 2.5: we should have sort of HAVE_ISA
++   flag in the struct pci_bus. */
++#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
++	size = (size & 0xff) + ((size & ~0xffUL) << 2);
++#endif
++	size = ROUND_UP(size + size1, 4096);
++	return size;
++}
++
++/*
++ * primary bus number of PCI-PCI bridge in switch on which
++ * this slots sits.
++ * i.e. the primary bus number of PCI-PCI bridge of downstream port
++ *      or root port in switch.
++ *      the secondary bus number of PCI-PCI bridge of upstream port
++ *      in switch.
++ */
++static inline unsigned char pci_dev_switch_busnr(struct pci_dev *pdev)
++{
++	if (pci_find_capability(pdev, PCI_CAP_ID_EXP))
++		return pdev->bus->primary;
++	return pdev->bus->number;
++}
++
++struct pci_iomul_func {
++	int		segment;
++	uint8_t		bus;
++	uint8_t		devfn;
++
++	/* only start and end are used */
++	unsigned long	io_size;
++	uint8_t		io_bar;
++	struct resource	resource[PCI_NUM_BARS];
++	struct resource dummy_parent;
++};
++
++struct pci_iomul_switch {
++	struct list_head	list;	/* bus_list_lock protects */
++
++	/*
++	 * This lock the following entry and following
++	 * pci_iomul_slot/pci_iomul_func.
++	 */
++	struct mutex		lock;
++	struct kref		kref;
++
++	struct resource		io_resource;
++	struct resource		*io_region;
++	unsigned int		count;
++	struct pci_dev		*current_pdev;
++
++	int			segment;
++	uint8_t			bus;
++
++	uint32_t		io_base;
++	uint32_t		io_limit;
++
++	/* func which has the largeset io size*/
++	struct pci_iomul_func	*func;
++
++	struct list_head	slots;
++};
++
++struct pci_iomul_slot {
++	struct list_head	sibling;
++	struct kref		kref;
++	/*
++	 * busnr
++	 * when pcie, the primary busnr of the PCI-PCI bridge on which
++	 * this devices sits.
++	 */
++	uint8_t			switch_busnr;
++	struct resource		dummy_parent[PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES];
++
++	/* device */
++	int			segment;
++	uint8_t			bus;
++	uint8_t			dev;
++
++	struct pci_iomul_func	*func[PCI_NUM_FUNC];
++};
++
++static LIST_HEAD(switch_list);
++static DEFINE_MUTEX(switch_list_lock);
++
++/*****************************************************************************/
++static int inline pci_iomul_switch_io_allocated(
++	const struct pci_iomul_switch *sw)
++{
++	return !(sw->io_base == 0 || sw->io_base > sw->io_limit);
++}
++
++static struct pci_iomul_switch *pci_iomul_find_switch_locked(int segment,
++							     uint8_t bus)
++{
++	struct pci_iomul_switch *sw;
++
++	BUG_ON(!mutex_is_locked(&switch_list_lock));
++	list_for_each_entry(sw, &switch_list, list) {
++		if (sw->segment == segment && sw->bus == bus)
++			return sw;
++	}
++	return NULL;
++}
++
++static struct pci_iomul_slot *pci_iomul_find_slot_locked(
++	struct pci_iomul_switch *sw, uint8_t busnr, uint8_t dev)
++{
++	struct pci_iomul_slot *slot;
++
++	BUG_ON(!mutex_is_locked(&sw->lock));
++	list_for_each_entry(slot, &sw->slots, sibling) {
++		if (slot->bus == busnr && slot->dev == dev)
++			return slot;
++	}
++	return NULL;
++}
++
++static void pci_iomul_switch_get(struct pci_iomul_switch *sw);
++/* on successfull exit, sw->lock is locked for use slot and
++ * refrence count of sw is incremented.
++ */
++static void pci_iomul_get_lock_switch(struct pci_dev *pdev,
++				      struct pci_iomul_switch **swp,
++				      struct pci_iomul_slot **slot)
++{
++	mutex_lock(&switch_list_lock);
++
++	*swp = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
++					    pci_dev_switch_busnr(pdev));
++	if (*swp == NULL) {
++		*slot = NULL;
++		goto out;
++	}
++
++	mutex_lock(&(*swp)->lock);
++	*slot = pci_iomul_find_slot_locked(*swp, pdev->bus->number,
++					   PCI_SLOT(pdev->devfn));
++	if (*slot == NULL) {
++		mutex_unlock(&(*swp)->lock);
++		*swp = NULL;
++	} else {
++		pci_iomul_switch_get(*swp);
++	}
++out:
++	mutex_unlock(&switch_list_lock);
++}
++
++static struct pci_iomul_switch *pci_iomul_switch_alloc(int segment,
++						       uint8_t bus)
++{
++	struct pci_iomul_switch *sw;
++
++	BUG_ON(!mutex_is_locked(&switch_list_lock));
++
++	sw = kmalloc(sizeof(*sw), GFP_KERNEL);
++
++	mutex_init(&sw->lock);
++	kref_init(&sw->kref);
++	sw->io_region = NULL;
++	sw->count = 0;
++	sw->current_pdev = NULL;
++	sw->segment = segment;
++	sw->bus = bus;
++	sw->io_base = 0;
++	sw->io_limit = 0;
++	sw->func = NULL;
++	INIT_LIST_HEAD(&sw->slots);
++
++	return sw;
++}
++
++static void pci_iomul_switch_add_locked(struct pci_iomul_switch *sw)
++{
++	BUG_ON(!mutex_is_locked(&switch_list_lock));
++	list_add(&sw->list, &switch_list);
++}
++
++#ifdef CONFIG_HOTPLUG_PCI
++static void pci_iomul_switch_del_locked(struct pci_iomul_switch *sw)
++{
++	BUG_ON(!mutex_is_locked(&switch_list_lock));
++	list_del(&sw->list);
++}
++#endif
++
++static void pci_iomul_switch_get(struct pci_iomul_switch *sw)
++{
++	kref_get(&sw->kref);
++}
++
++static void pci_iomul_switch_release(struct kref *kref)
++{
++	struct pci_iomul_switch *sw = container_of(kref,
++						   struct pci_iomul_switch,
++						   kref);
++	kfree(sw);
++}
++
++static void pci_iomul_switch_put(struct pci_iomul_switch *sw)
++{
++	kref_put(&sw->kref, &pci_iomul_switch_release);
++}
++
++static int __devinit pci_iomul_slot_init(struct pci_dev *pdev,
++					 struct pci_iomul_slot *slot)
++{
++	u16 rpcap;
++	u16 cap;
++
++	rpcap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
++	if (!rpcap) {
++		/* pci device isn't supported */
++		printk(KERN_INFO
++		       "PCI: sharing io port of non PCIe device %s "
++		       "isn't supported. ignoring.\n",
++		       pci_name(pdev));
++		return -ENOSYS;
++	}
++
++        pci_read_config_word(pdev, rpcap + PCI_CAP_FLAGS, &cap);
++	switch ((cap & PCI_EXP_FLAGS_TYPE) >> 4) {
++	case PCI_EXP_TYPE_RC_END:
++		printk(KERN_INFO
++		       "PCI: io port sharing of root complex integrated "
++		       "endpoint %s isn't supported. ignoring.\n",
++		       pci_name(pdev));
++		return -ENOSYS;
++	case PCI_EXP_TYPE_ENDPOINT:
++	case PCI_EXP_TYPE_LEG_END:
++		break;
++	default:
++		printk(KERN_INFO
++		       "PCI: io port sharing of non endpoint %s "
++		       "doesn't make sense. ignoring.\n",
++		       pci_name(pdev));
++		return -EINVAL;
++	}
++
++	kref_init(&slot->kref);
++	slot->switch_busnr = pci_dev_switch_busnr(pdev);
++	slot->segment = pci_domain_nr(pdev->bus);
++	slot->bus = pdev->bus->number;
++	slot->dev = PCI_SLOT(pdev->devfn);
++
++	return 0;
++}
++
++static struct pci_iomul_slot *__devinit
++pci_iomul_slot_alloc(struct pci_dev *pdev)
++{
++	struct pci_iomul_slot *slot;
++
++	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
++	if (slot == NULL)
++		return NULL;
++
++	if (pci_iomul_slot_init(pdev, slot) != 0) {
++		kfree(slot);
++		return NULL;
++	}
++	return slot;
++}
++
++static void pci_iomul_slot_add_locked(struct pci_iomul_switch *sw,
++				      struct pci_iomul_slot *slot)
++{
++	BUG_ON(!mutex_is_locked(&sw->lock));
++	list_add(&slot->sibling, &sw->slots);
++}
++
++#ifdef CONFIG_HOTPLUG_PCI
++static void pci_iomul_slot_del_locked(struct pci_iomul_switch *sw,
++				       struct pci_iomul_slot *slot)
++{
++	BUG_ON(!mutex_is_locked(&sw->lock));
++	list_del(&slot->sibling);
++}
++#endif
++
++static void pci_iomul_slot_get(struct pci_iomul_slot *slot)
++{
++	kref_get(&slot->kref);
++}
++
++static void pci_iomul_slot_release(struct kref *kref)
++{
++	struct pci_iomul_slot *slot = container_of(kref, struct pci_iomul_slot,
++						   kref);
++	kfree(slot);
++}
++
++static void pci_iomul_slot_put(struct pci_iomul_slot *slot)
++{
++	kref_put(&slot->kref, &pci_iomul_slot_release);
++}
++
++/*****************************************************************************/
++static int pci_get_sbd(const char *str,
++		       int *segment__, uint8_t *bus__, uint8_t *dev__)
++{
++	int segment;
++	int bus;
++	int dev;
++
++	if (sscanf(str, "%x:%x:%x", &segment, &bus, &dev) != 3) {
++		if (sscanf(str, "%x:%x", &bus, &dev) == 2)
++			segment = 0;
++		else
++			return -EINVAL;
++	}
++
++	if (segment < 0 || INT_MAX <= segment)
++		return -EINVAL;
++	if (bus < 0 || PCI_BUS_MAX < bus)
++		return -EINVAL;
++	if (dev < 0 || PCI_DEV_MAX < dev)
++		return -EINVAL;
++
++	*segment__ = segment;
++	*bus__ = bus;
++	*dev__ = dev;
++	return 0;
++}
++
++static char iomul_param[COMMAND_LINE_SIZE];
++#define TOKEN_MAX	10	/* SSSS:BB:DD length is 10 */
++static int pci_is_iomul_dev_param(struct pci_dev *pdev)
++{
++        int len;
++        char *p;
++	char *next_str;
++
++	for (p = &iomul_param[0]; *p != '\0'; p = next_str + 1) {
++		next_str = strchr(p, ',');
++		if (next_str != NULL)
++			len = next_str - p;
++		else
++			len = strlen(p);
++
++		if (len > 0 && len <= TOKEN_MAX) {
++			char tmp[TOKEN_MAX+1];
++			int seg;
++			uint8_t bus;
++			uint8_t dev;
++
++			strlcpy(tmp, p, len);
++			if (pci_get_sbd(tmp, &seg, &bus, &dev) == 0 &&
++			    pci_domain_nr(pdev->bus) == seg &&
++			    pdev->bus->number == bus &&
++			    PCI_SLOT(pdev->devfn) == dev)
++				return 1;
++		}
++		if (next_str == NULL)
++			break;
++	}
++
++	/* check guestcev=<device>+iomul option */
++	return pci_is_iomuldev(pdev);
++}
++
++/*
++ * Format: [<segment>:]<bus>:<dev>[,[<segment>:]<bus>:<dev>[,...]
++ */
++static int __init pci_iomul_param_setup(char *str)
++{
++	if (strlen(str) >= COMMAND_LINE_SIZE)
++		return 0;
++
++	/* parse it after pci bus scanning */
++	strlcpy(iomul_param, str, sizeof(iomul_param));
++	return 1;
++}
++__setup("guestiomuldev=", pci_iomul_param_setup);
++
++/*****************************************************************************/
++static void __devinit pci_iomul_set_bridge_io_window(struct pci_dev *bridge,
++						     uint32_t io_base,
++						     uint32_t io_limit)
++{
++	uint16_t l;
++	uint32_t upper16;
++
++	io_base >>= 12;
++	io_base <<= 4;
++	io_limit >>= 12;
++	io_limit <<= 4;
++	l = (io_base & 0xff) | ((io_limit & 0xff) << 8);
++	upper16 = ((io_base & 0xffff00) >> 8) |
++		(((io_limit & 0xffff00) >> 8) << 16);
++
++        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
++        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
++        /* Update lower 16 bits of I/O base/limit. */
++        pci_write_config_word(bridge, PCI_IO_BASE, l);
++        /* Update upper 16 bits of I/O base/limit. */
++        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, upper16);
++}
++
++static void __devinit pci_disable_bridge_io_window(struct pci_dev *bridge)
++{
++	/* set base = 0xffffff limit = 0x0 */
++	pci_iomul_set_bridge_io_window(bridge, 0xffffff, 0);
++}
++
++static int __devinit pci_iomul_func_scan(struct pci_dev *pdev,
++					 struct pci_iomul_slot *slot,
++					 uint8_t func)
++{
++	struct pci_iomul_func *f;
++	unsigned int i;
++
++	f = kzalloc(sizeof(*f), GFP_KERNEL);
++	if (f == NULL)
++		return -ENOMEM;
++
++	f->segment = slot->segment;
++	f->bus = slot->bus;
++	f->devfn = PCI_DEVFN(slot->dev, func);
++	f->io_size = pdev_size_io(pdev);
++
++	for (i = 0; i < PCI_NUM_BARS; i++) {
++		if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO))
++			continue;
++		if (pci_resource_len(pdev, i) == 0)
++			continue;
++
++		f->io_bar |= 1 << i;
++		f->resource[i] = pdev->resource[i];
++	}
++
++	if (f->io_bar)
++		slot->func[func] = f;
++	else
++		kfree(f);
++	return 0;
++}
++
++/*
++ * This is tricky part.
++ * fake PCI resource assignment routines by setting flags to 0.
++ * PCI resource allocate routines think the resource should
++ * be allocated by checking flags. 0 means this resource isn't used.
++ * See pbus_size_io() and pdev_sort_resources().
++ *
++ * After allocated resources, flags (IORESOURCE_IO) is exported
++ * to other part including user process.
++ * So we have to set flags to IORESOURCE_IO, but at the same time
++ * we must prevent those resources from reassigning when pci hot plug.
++ * To achieve that, set r->parent to dummy resource.
++ */
++static void __devinit pci_iomul_disable_resource(struct resource *r)
++{
++	/* don't allocate this resource */
++	r->flags = 0;
++}
++
++static void __devinit pci_iomul_reenable_resource(
++	struct resource *dummy_parent, struct resource *r)
++{
++	int ret;
++
++	dummy_parent->start = r->start;
++	dummy_parent->end = r->end;
++	dummy_parent->flags = r->flags;
++	dummy_parent->name = "PCI IOMUL dummy resource";
++
++	ret = request_resource(dummy_parent, r);
++	BUG_ON(ret);
++}
++
++static void __devinit pci_iomul_fixup_ioresource(struct pci_dev *pdev,
++						 struct pci_iomul_func *func,
++						 int reassign, int dealloc)
++{
++	uint8_t i;
++	struct resource *r;
++
++	printk(KERN_INFO "PCI: deallocating io resource[%s]. io size 0x%lx\n",
++	       pci_name(pdev), func->io_size);
++	for (i = 0; i < PCI_NUM_BARS; i++) {
++		r = &pdev->resource[i];
++		if (!(func->io_bar & (1 << i)))
++			continue;
++
++		if (reassign) {
++			r->end -= r->start;
++			r->start = 0;
++			pci_update_resource(pdev, i);
++			func->resource[i] = *r;
++		}
++
++		if (dealloc)
++			/* don't allocate this resource */
++			pci_iomul_disable_resource(r);
++	}
++
++	/* parent PCI-PCI bridge */
++	if (!reassign)
++		return;
++	pdev = pdev->bus->self;
++	if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
++		return;
++	pci_disable_bridge_io_window(pdev);
++	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++		r = &pdev->resource[i];
++		if (!(r->flags & IORESOURCE_IO))
++			continue;
++
++		r->end -= r->start;
++		r->start = 0;
++		if (i < PCI_BRIDGE_RESOURCES)
++			pci_update_resource(pdev, i);
++	}
++}
++
++static void __devinit __quirk_iomul_dealloc_ioresource(
++	struct pci_iomul_switch *sw,
++	struct pci_dev *pdev, struct pci_iomul_slot *slot)
++{
++	struct pci_iomul_func *f;
++	struct pci_iomul_func *__f;
++
++	if (pci_iomul_func_scan(pdev, slot, PCI_FUNC(pdev->devfn)) != 0)
++		return;
++
++	f = slot->func[PCI_FUNC(pdev->devfn)];
++	if (f == NULL)
++		return;
++
++	__f = sw->func;
++	/* sw->io_base == 0 means that we are called at boot time.
++	 * != 0 means that we are called by php after boot. */
++	if (sw->io_base == 0 &&
++	    (__f == NULL || __f->io_size < f->io_size)) {
++		if (__f != NULL) {
++			struct pci_bus *__pbus;
++			struct pci_dev *__pdev;
++
++			__pbus = pci_find_bus(__f->segment, __f->bus);
++			BUG_ON(__pbus == NULL);
++			__pdev = pci_get_slot(__pbus, __f->devfn);
++			BUG_ON(__pdev == NULL);
++			pci_iomul_fixup_ioresource(__pdev, __f, 0, 1);
++			pci_dev_put(__pdev);
++		}
++
++		pci_iomul_fixup_ioresource(pdev, f, 1, 0);
++		sw->func = f;
++	} else {
++		pci_iomul_fixup_ioresource(pdev, f, 1, 1);
++	}
++}
++
++static void __devinit quirk_iomul_dealloc_ioresource(struct pci_dev *pdev)
++{
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_slot *slot;
++
++	if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
++		return;
++	if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
++		return;	/* PCI Host Bridge isn't a target device */
++	if (!pci_is_iomul_dev_param(pdev))
++		return;
++
++	mutex_lock(&switch_list_lock);
++	sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
++					  pci_dev_switch_busnr(pdev));
++	if (sw == NULL) {
++		sw = pci_iomul_switch_alloc(pci_domain_nr(pdev->bus),
++					    pci_dev_switch_busnr(pdev));
++		if (sw == NULL) {
++			mutex_unlock(&switch_list_lock);
++			printk(KERN_WARNING
++			       "PCI: can't allocate memory "
++			       "for sw of IO mulplexing %s", pci_name(pdev));
++			return;
++		}
++		pci_iomul_switch_add_locked(sw);
++	}
++	pci_iomul_switch_get(sw);
++	mutex_unlock(&switch_list_lock);
++
++	mutex_lock(&sw->lock);
++	slot = pci_iomul_find_slot_locked(sw, pdev->bus->number,
++					  PCI_SLOT(pdev->devfn));
++	if (slot == NULL) {
++		slot = pci_iomul_slot_alloc(pdev);
++		if (slot == NULL) {
++			mutex_unlock(&sw->lock);
++			pci_iomul_switch_put(sw);
++			printk(KERN_WARNING "PCI: can't allocate memory "
++			       "for IO mulplexing %s", pci_name(pdev));
++			return;
++		}
++		pci_iomul_slot_add_locked(sw, slot);
++	}
++
++	printk(KERN_INFO "PCI: disable device and release io resource[%s].\n",
++	       pci_name(pdev));
++	pci_disable_device(pdev);
++
++	__quirk_iomul_dealloc_ioresource(sw, pdev, slot);
++
++	mutex_unlock(&sw->lock);
++	pci_iomul_switch_put(sw);
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID,
++			 quirk_iomul_dealloc_ioresource);
++
++static void __devinit pci_iomul_read_bridge_io(struct pci_iomul_switch *sw)
++{
++	struct pci_iomul_func *f = sw->func;
++
++	struct pci_bus *pbus;
++	struct pci_dev *pdev;
++	struct pci_dev *bridge;
++
++	uint16_t l;
++	uint16_t base_upper16;
++	uint16_t limit_upper16;
++	uint32_t io_base;
++	uint32_t io_limit;
++
++	pbus = pci_find_bus(f->segment, f->bus);
++	BUG_ON(pbus == NULL);
++
++	pdev = pci_get_slot(pbus, f->devfn);
++	BUG_ON(pdev == NULL);
++
++	bridge = pdev->bus->self;
++	pci_read_config_word(bridge, PCI_IO_BASE, &l);
++	pci_read_config_word(bridge, PCI_IO_BASE_UPPER16, &base_upper16);
++	pci_read_config_word(bridge, PCI_IO_LIMIT_UPPER16, &limit_upper16);
++
++	io_base = (l & 0xf0) | ((uint32_t)base_upper16 << 8);
++	io_base <<= 8;
++	io_limit = (l >> 8) | ((uint32_t)limit_upper16 << 8);
++	io_limit <<= 8;
++	io_limit |= 0xfff;
++
++	sw->io_base = io_base;
++	sw->io_limit = io_limit;
++
++	pci_dev_put(pdev);
++	printk(KERN_INFO "PCI: bridge %s base 0x%x limit 0x%x\n",
++	       pci_name(bridge), sw->io_base, sw->io_limit);
++}
++
++static void __devinit pci_iomul_setup_brige(struct pci_dev *bridge,
++					    uint32_t io_base,
++					    uint32_t io_limit)
++{
++	uint16_t cmd;
++
++	if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_HOST)
++		return;
++
++	pci_iomul_set_bridge_io_window(bridge, io_base, io_limit);
++
++	/* and forcibly enables IO */
++	pci_read_config_word(bridge, PCI_COMMAND, &cmd);
++	if (!(cmd & PCI_COMMAND_IO)) {
++		cmd |= PCI_COMMAND_IO;
++                printk(KERN_INFO "PCI: Forcibly Enabling IO %s\n",
++		       pci_name(bridge));
++                pci_write_config_word(bridge, PCI_COMMAND, cmd);
++	}
++}
++
++struct __bar {
++	unsigned long size;
++	uint8_t bar;
++};
++
++/* decending order */
++static int __devinit pci_iomul_bar_cmp(const void *lhs__, const void *rhs__)
++{
++	const struct __bar *lhs = (struct __bar*)lhs__;
++	const struct __bar *rhs = (struct __bar*)rhs__;
++	return - (lhs->size - rhs->size);
++}
++
++static void __devinit pci_iomul_setup_dev(struct pci_dev *pdev,
++					  struct pci_iomul_func *f,
++					  uint32_t io_base)
++{
++	struct __bar bars[PCI_NUM_BARS];
++	int i;
++	uint8_t num_bars = 0;
++	struct resource *r;
++
++	printk(KERN_INFO "PCI: Forcibly assign IO %s from 0x%x\n",
++	       pci_name(pdev), io_base);
++
++	for (i = 0; i < PCI_NUM_BARS; i++) {
++		if (!(f->io_bar & (1 << i)))
++			continue;
++
++		r = &f->resource[i];
++		bars[num_bars].size = pci_iomul_len(r);
++		bars[num_bars].bar = i;
++
++		num_bars++;
++	}
++
++	sort(bars, num_bars, sizeof(bars[0]), &pci_iomul_bar_cmp, NULL);
++
++	for (i = 0; i < num_bars; i++) {
++		struct resource *fr = &f->resource[bars[i].bar];
++		r = &pdev->resource[bars[i].bar];
++
++		BUG_ON(r->start != 0);
++		r->start += io_base;
++		r->end += io_base;
++
++		fr->start = r->start;
++		fr->end = r->end;
++
++		/* pci_update_resource() check flags. */
++		r->flags = fr->flags;
++		pci_update_resource(pdev, bars[i].bar);
++		pci_iomul_reenable_resource(&f->dummy_parent, r);
++
++		io_base += bars[i].size;
++	}
++}
++
++static void __devinit pci_iomul_release_io_resource(
++	struct pci_dev *pdev, struct pci_iomul_switch *sw,
++	struct pci_iomul_slot *slot, struct pci_iomul_func *f)
++{
++	int i;
++	struct resource *r;
++
++	for (i = 0; i < PCI_NUM_BARS; i++) {
++		if (pci_resource_flags(pdev, i) & IORESOURCE_IO &&
++		    pdev->resource[i].parent != NULL) {
++			r = &pdev->resource[i];
++			f->resource[i] = *r;
++			release_resource(r);
++			pci_iomul_reenable_resource(&f->dummy_parent, r);
++		}
++	}
++
++	/* parent PCI-PCI bridge */
++	pdev = pdev->bus->self;
++	if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_HOST) {
++		for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
++			struct resource *parent = pdev->resource[i].parent;
++
++			if (pci_resource_flags(pdev, i) & IORESOURCE_IO &&
++			    parent != NULL) {
++				r = &pdev->resource[i];
++
++				sw->io_resource.flags = r->flags;
++				sw->io_resource.start = sw->io_base;
++				sw->io_resource.end = sw->io_limit;
++				sw->io_resource.name = "PCI IO Multiplexer";
++
++				release_resource(r);
++				pci_iomul_reenable_resource(
++					&slot->dummy_parent[i - PCI_BRIDGE_RESOURCES], r);
++
++				if (request_resource(parent,
++						     &sw->io_resource))
++					printk(KERN_ERR
++					       "PCI IOMul: can't allocate "
++					       "resource. [0x%x, 0x%x]",
++					       sw->io_base, sw->io_limit);
++			}
++		}
++	}
++}
++
++static void __devinit quirk_iomul_reassign_ioresource(struct pci_dev *pdev)
++{
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_slot *slot;
++	struct pci_iomul_func *sf;
++	struct pci_iomul_func *f;
++
++	pci_iomul_get_lock_switch(pdev, &sw, &slot);
++	if (sw == NULL || slot == NULL)
++		return;
++
++	if (sw->io_base == 0)
++		pci_iomul_read_bridge_io(sw);
++	if (!pci_iomul_switch_io_allocated(sw))
++		goto out;
++
++	sf = sw->func;
++	f = slot->func[PCI_FUNC(pdev->devfn)];
++	if (f == NULL)
++		/* (sf == NULL || f == NULL) case
++		 * can happen when all the specified devices
++		 * don't have io space
++		 */
++		goto out;
++
++	if (sf != NULL &&
++	    (pci_domain_nr(pdev->bus) != sf->segment ||
++	     pdev->bus->number != sf->bus ||
++	     PCI_SLOT(pdev->devfn) != PCI_SLOT(sf->devfn)) &&
++	    PCI_FUNC(pdev->devfn) == 0) {
++		pci_iomul_setup_brige(pdev->bus->self,
++				      sw->io_base, sw->io_limit);
++	}
++
++	BUG_ON(f->io_size > sw->io_limit - sw->io_base + 1);
++	if (/* f == sf */
++            sf != NULL &&
++	    pci_domain_nr(pdev->bus) == sf->segment &&
++	    pdev->bus->number == sf->bus &&
++	    pdev->devfn == sf->devfn)
++		pci_iomul_release_io_resource(pdev, sw, slot, f);
++	else
++		pci_iomul_setup_dev(pdev, f, sw->io_base);
++
++out:
++	mutex_unlock(&sw->lock);
++	pci_iomul_switch_put(sw);
++}
++
++DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID,
++			quirk_iomul_reassign_ioresource);
++
++/*****************************************************************************/
++#ifdef CONFIG_HOTPLUG_PCI
++static int __devinit __pci_iomul_notifier_del_device(struct pci_dev *pdev)
++{
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_slot *slot;
++	int i;
++
++	pci_iomul_get_lock_switch(pdev, &sw, &slot);
++	if (sw == NULL || slot == NULL)
++		return 0;
++
++	if (sw->func == slot->func[PCI_FUNC(pdev->devfn)])
++		sw->func = NULL;
++	kfree(slot->func[PCI_FUNC(pdev->devfn)]);
++	slot->func[PCI_FUNC(pdev->devfn)] = NULL;
++	for (i = 0; i < PCI_NUM_FUNC; i++) {
++		if (slot->func[i] != NULL)
++			goto out;
++	}
++
++	pci_iomul_slot_del_locked(sw, slot);
++	pci_iomul_slot_put(slot);
++
++out:
++	mutex_unlock(&sw->lock);
++	pci_iomul_switch_put(sw);
++	return 0;
++}
++
++static int __devinit __pci_iomul_notifier_del_switch(struct pci_dev *pdev)
++{
++	struct pci_iomul_switch *sw;
++
++	mutex_lock(&switch_list_lock);
++	sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus),
++					  pdev->bus->number);
++	if (sw == NULL)
++		goto out;
++
++	pci_iomul_switch_del_locked(sw);
++
++	mutex_lock(&sw->lock);
++	if (sw->io_resource.parent)
++		release_resource(&sw->io_resource);
++	sw->io_base = 0;	/* to tell this switch is removed */
++	sw->io_limit = 0;
++	BUG_ON(!list_empty(&sw->slots));
++	mutex_unlock(&sw->lock);
++
++out:
++	mutex_unlock(&switch_list_lock);
++	pci_iomul_switch_put(sw);
++	return 0;
++}
++
++static int __devinit pci_iomul_notifier_del_device(struct pci_dev *pdev)
++{
++	int ret;
++	switch (pdev->hdr_type) {
++	case PCI_HEADER_TYPE_NORMAL:
++		ret = __pci_iomul_notifier_del_device(pdev);
++		break;
++	case PCI_HEADER_TYPE_BRIDGE:
++		ret = __pci_iomul_notifier_del_switch(pdev);
++		break;
++	default:
++                printk(KERN_WARNING "PCI IOMUL: "
++		       "device %s has unknown header type %02x, ignoring.\n",
++		       pci_name(pdev), pdev->hdr_type);
++		ret = -EIO;
++		break;
++	}
++	return ret;
++}
++
++static int __devinit pci_iomul_notifier(struct notifier_block *nb,
++					unsigned long action, void *data)
++{
++        struct device *dev = data;
++        struct pci_dev *pdev = to_pci_dev(dev);
++
++        switch (action) {
++	case BUS_NOTIFY_ADD_DEVICE:
++		quirk_iomul_reassign_ioresource(pdev);
++		break;
++	case BUS_NOTIFY_DEL_DEVICE:
++		return pci_iomul_notifier_del_device(pdev);
++	default:
++		/* nothing */
++		break;
++	}
++
++	return 0;
++}
++
++static struct notifier_block pci_iomul_nb = {
++        .notifier_call = pci_iomul_notifier,
++};
++
++static int __init pci_iomul_hotplug_init(void)
++{
++        bus_register_notifier(&pci_bus_type, &pci_iomul_nb);
++	return 0;
++}
++
++late_initcall(pci_iomul_hotplug_init);
++#endif
++
++/*****************************************************************************/
++struct pci_iomul_data {
++	struct mutex lock;
++
++	struct pci_dev *pdev;
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_slot *slot;	/* slot::kref */
++	struct pci_iomul_func **func;	/* when dereferencing,
++					   sw->lock is necessary */
++};
++
++static int pci_iomul_func_ioport(struct pci_iomul_func *func,
++				 uint8_t bar, uint64_t offset, int *port)
++{
++	if (!(func->io_bar & (1 << bar)))
++		return -EINVAL;
++
++	*port = func->resource[bar].start + offset;
++	if (*port < func->resource[bar].start ||
++	    *port > func->resource[bar].end)
++		return -EINVAL;
++
++	return 0;
++}
++
++static inline int pci_iomul_valid(struct pci_iomul_data *iomul)
++{
++	BUG_ON(!mutex_is_locked(&iomul->lock));
++	BUG_ON(!mutex_is_locked(&iomul->sw->lock));
++	return pci_iomul_switch_io_allocated(iomul->sw) &&
++		*iomul->func != NULL;
++}
++
++static void __pci_iomul_enable_io(struct pci_dev *pdev)
++{
++	uint16_t cmd;
++
++	pci_dev_get(pdev);
++	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
++	cmd |= PCI_COMMAND_IO;
++	pci_write_config_word(pdev, PCI_COMMAND, cmd);
++}
++
++static void __pci_iomul_disable_io(struct pci_iomul_data *iomul,
++				   struct pci_dev *pdev)
++{
++	uint16_t cmd;
++
++	if (!pci_iomul_valid(iomul))
++		return;
++
++	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
++	cmd &= ~PCI_COMMAND_IO;
++	pci_write_config_word(pdev, PCI_COMMAND, cmd);
++	pci_dev_put(pdev);
++}
++
++static int pci_iomul_open(struct inode *inode, struct file *filp)
++{
++	struct pci_iomul_data *iomul;
++	iomul = kmalloc(sizeof(*iomul), GFP_KERNEL);
++	if (iomul == NULL)
++		return -ENOMEM;
++
++	mutex_init(&iomul->lock);
++	iomul->pdev = NULL;
++	iomul->sw = NULL;
++	iomul->slot = NULL;
++	iomul->func = NULL;
++	filp->private_data = (void*)iomul;
++
++	return 0;
++}
++
++static int pci_iomul_release(struct inode *inode, struct file *filp)
++{
++	struct pci_iomul_data *iomul =
++		(struct pci_iomul_data*)filp->private_data;
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_slot *slot = NULL;
++
++	mutex_lock(&iomul->lock);
++	sw = iomul->sw;
++	slot = iomul->slot;
++	if (iomul->pdev != NULL) {
++		if (sw != NULL) {
++			mutex_lock(&sw->lock);
++			if (sw->current_pdev == iomul->pdev) {
++				__pci_iomul_disable_io(iomul,
++						       sw->current_pdev);
++				sw->current_pdev = NULL;
++			}
++			sw->count--;
++			if (sw->count == 0) {
++				release_region(sw->io_region->start, sw->io_region->end - sw->io_region->start + 1);
++				sw->io_region = NULL;
++			}
++			mutex_unlock(&sw->lock);
++		}
++		pci_dev_put(iomul->pdev);
++	}
++	mutex_unlock(&iomul->lock);
++
++	if (slot != NULL)
++		pci_iomul_slot_put(slot);
++	if (sw != NULL)
++		pci_iomul_switch_put(sw);
++	kfree(iomul);
++	return 0;
++}
++
++static long pci_iomul_setup(struct pci_iomul_data *iomul,
++			    struct pci_iomul_setup __user *arg)
++{
++	long error = 0;
++	struct pci_iomul_setup setup;
++	struct pci_iomul_switch *sw = NULL;
++	struct pci_iomul_slot *slot;
++	struct pci_bus *pbus;
++	struct pci_dev *pdev;
++
++	if (copy_from_user(&setup, arg, sizeof(setup)))
++		return -EFAULT;
++
++	pbus = pci_find_bus(setup.segment, setup.bus);
++	if (pbus == NULL)
++		return -ENODEV;
++	pdev = pci_get_slot(pbus, setup.dev);
++	if (pdev == NULL)
++		return -ENODEV;
++
++	mutex_lock(&iomul->lock);
++	if (iomul->sw != NULL) {
++		error = -EBUSY;
++		goto out0;
++	}
++
++	pci_iomul_get_lock_switch(pdev, &sw, &slot);
++	if (sw == NULL || slot == NULL) {
++		error = -ENODEV;
++		goto out0;
++	}
++	if (!pci_iomul_switch_io_allocated(sw)) {
++		error = -ENODEV;
++		goto out;
++	}
++
++	if (slot->func[setup.func] == NULL) {
++		error = -ENODEV;
++		goto out;
++	}
++
++	if (sw->count == 0) {
++		BUG_ON(sw->io_region != NULL);
++		sw->io_region =
++			request_region(sw->io_base,
++				       sw->io_limit - sw->io_base + 1,
++				       "PCI IO Multiplexer driver");
++		if (sw->io_region == NULL) {
++			mutex_unlock(&sw->lock);
++			error = -EBUSY;
++			goto out;
++		}
++	}
++	sw->count++;
++	pci_iomul_slot_get(slot);
++
++	iomul->pdev = pdev;
++	iomul->sw = sw;
++	iomul->slot = slot;
++	iomul->func = &slot->func[setup.func];
++
++out:
++	mutex_unlock(&sw->lock);
++out0:
++	mutex_unlock(&iomul->lock);
++	if (error != 0) {
++		if (sw != NULL)
++			pci_iomul_switch_put(sw);
++		pci_dev_put(pdev);
++	}
++	return error;
++}
++
++static int pci_iomul_lock(struct pci_iomul_data *iomul,
++			  struct pci_iomul_switch **sw,
++			  struct pci_iomul_func **func)
++{
++	mutex_lock(&iomul->lock);
++	*sw = iomul->sw;
++	if (*sw == NULL) {
++		mutex_unlock(&iomul->lock);
++		return -ENODEV;
++	}
++	mutex_lock(&(*sw)->lock);
++	if (!pci_iomul_valid(iomul)) {
++		mutex_unlock(&(*sw)->lock);
++		mutex_unlock(&iomul->lock);
++		return -ENODEV;
++	}
++	*func = *iomul->func;
++
++	return 0;
++}
++
++static long pci_iomul_disable_io(struct pci_iomul_data *iomul)
++{
++	long error = 0;
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_func *dummy_func;
++	struct pci_dev *pdev;
++
++	if (pci_iomul_lock(iomul, &sw, &dummy_func) < 0)
++		return -ENODEV;
++
++	pdev = iomul->pdev;
++	if (pdev == NULL)
++		error = -ENODEV;
++
++	if (pdev != NULL && sw->current_pdev == pdev) {
++		__pci_iomul_disable_io(iomul, pdev);
++		sw->current_pdev = NULL;
++	}
++
++	mutex_unlock(&sw->lock);
++	mutex_unlock(&iomul->lock);
++	return error;
++}
++
++static void pci_iomul_switch_to(
++	struct pci_iomul_data *iomul, struct pci_iomul_switch *sw,
++	struct pci_dev *next_pdev)
++{
++	if (sw->current_pdev == next_pdev)
++		/* nothing to do */
++		return;
++
++	if (sw->current_pdev != NULL)
++		__pci_iomul_disable_io(iomul, sw->current_pdev);
++
++	__pci_iomul_enable_io(next_pdev);
++	sw->current_pdev = next_pdev;
++}
++
++static long pci_iomul_in(struct pci_iomul_data *iomul,
++			 struct pci_iomul_in __user *arg)
++{
++	struct pci_iomul_in in;
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_func *func;
++
++	long error = 0;
++	int port;
++	uint32_t value = 0;
++
++	if (copy_from_user(&in, arg, sizeof(in)))
++		return -EFAULT;
++
++	if (pci_iomul_lock(iomul, &sw, &func) < 0)
++		return -ENODEV;
++
++	error = pci_iomul_func_ioport(func, in.bar, in.offset, &port);
++	if (error)
++		goto out;
++
++	pci_iomul_switch_to(iomul, sw, iomul->pdev);
++	switch (in.size) {
++	case 4:
++		value = inl(port);
++		break;
++	case 2:
++		value = inw(port);
++		break;
++	case 1:
++		value = inb(port);
++		break;
++	default:
++		error = -EINVAL;
++		break;
++	}
++
++out:
++	mutex_unlock(&sw->lock);
++	mutex_unlock(&iomul->lock);
++
++	if (error == 0 && put_user(value, &arg->value))
++		return -EFAULT;
++	return error;
++}
++
++static long pci_iomul_out(struct pci_iomul_data *iomul,
++			  struct pci_iomul_out __user *arg)
++{
++	struct pci_iomul_in out;
++	struct pci_iomul_switch *sw;
++	struct pci_iomul_func *func;
++
++	long error = 0;
++	int port;
++
++	if (copy_from_user(&out, arg, sizeof(out)))
++		return -EFAULT;
++
++	if (pci_iomul_lock(iomul, &sw, &func) < 0)
++		return -ENODEV;
++
++	error = pci_iomul_func_ioport(func, out.bar, out.offset, &port);
++	if (error)
++		goto out;
++
++	pci_iomul_switch_to(iomul, sw, iomul->pdev);
++	switch (out.size) {
++	case 4:
++		outl(out.value, port);
++		break;
++	case 2:
++		outw(out.value, port);
++		break;
++	case 1:
++		outb(out.value, port);
++		break;
++	default:
++		error = -EINVAL;
++		break;
++	}
++
++out:
++	mutex_unlock(&sw->lock);
++	mutex_unlock(&iomul->lock);
++	return error;
++}
++
++static long pci_iomul_ioctl(struct file *filp,
++			    unsigned int cmd, unsigned long arg)
++{
++	long error;
++	struct pci_iomul_data *iomul =
++		(struct pci_iomul_data*)filp->private_data;
++
++	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
++		return -EPERM;
++
++	switch (cmd) {
++	case PCI_IOMUL_SETUP:
++		error = pci_iomul_setup(iomul,
++					(struct pci_iomul_setup __user *)arg);
++		break;
++	case PCI_IOMUL_DISABLE_IO:
++		error = pci_iomul_disable_io(iomul);
++		break;
++	case PCI_IOMUL_IN:
++		error = pci_iomul_in(iomul, (struct pci_iomul_in __user *)arg);
++		break;
++	case PCI_IOMUL_OUT:
++		error = pci_iomul_out(iomul,
++				      (struct pci_iomul_out __user *)arg);
++		break;
++	default:
++		error = -ENOSYS;
++		break;
++	}
++
++	return error;
++}
++
++static const struct file_operations pci_iomul_fops = {
++	.owner = THIS_MODULE,
++
++	.open = pci_iomul_open, /* nonseekable_open */
++	.release = pci_iomul_release,
++
++	.unlocked_ioctl = pci_iomul_ioctl,
++};
++
++static struct miscdevice pci_iomul_miscdev = {
++	.minor = MISC_DYNAMIC_MINOR,
++	.name = "pci_iomul",
++	.fops = &pci_iomul_fops,
++};
++
++static int pci_iomul_init(void)
++{
++	int error;
++	error = misc_register(&pci_iomul_miscdev);
++	if (error != 0) {
++		printk(KERN_ALERT "Couldn't register /dev/misc/pci_iomul");
++		return error;
++	}
++	printk("PCI IO multiplexer device installed.\n");
++	return 0;
++}
++
++#if 0
++static void pci_iomul_cleanup(void)
++{
++	misc_deregister(&pci_iomul_miscdev);
++}
++#endif
++
++/*
++ * This must be called after pci fixup final which is called by
++ * device_initcall(pci_init).
++ */
++late_initcall(pci_iomul_init);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Isaku Yamahata <yamahata@valinux.co.jp>");
++MODULE_DESCRIPTION("PCI IO space multiplexing driver");
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/drivers/pci/iomulti.h	2009-12-04 10:27:46.000000000 +0100
+@@ -0,0 +1,51 @@
++#ifndef PCI_IOMULTI_H
++#define PCI_IOMULTI_H
++/*
++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ *
++ * Copyright (c) 2009 Isaku Yamahata
++ *                    VA Linux Systems Japan K.K.
++ *
++ */
++
++struct pci_iomul_setup {
++	uint16_t	segment;
++	uint8_t		bus;
++	uint8_t		dev;
++	uint8_t		func;
++};
++
++struct pci_iomul_in {
++	uint8_t		bar;
++	uint64_t	offset;
++
++	uint8_t		size;
++	uint32_t	value;
++};
++
++struct pci_iomul_out {
++	uint8_t		bar;
++	uint64_t	offset;
++
++	uint8_t		size;
++	uint32_t	value;
++};
++
++#define PCI_IOMUL_SETUP		_IOW ('P', 0, struct pci_iomul_setup)
++#define PCI_IOMUL_DISABLE_IO	_IO  ('P', 1)
++#define PCI_IOMUL_IN		_IOWR('P', 2, struct pci_iomul_in)
++#define PCI_IOMUL_OUT		_IOW ('P', 3, struct pci_iomul_out)
++
++#endif /* PCI_IOMULTI_H */
+--- head-2010-01-18.orig/drivers/pci/pci.c	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/pci/pci.c	2009-12-04 10:27:46.000000000 +0100
+@@ -2658,6 +2658,13 @@ resource_size_t pci_specified_resource_a
+  */
+ int pci_is_reassigndev(struct pci_dev *dev)
+ {
++#ifdef CONFIG_PCI_GUESTDEV
++	int result;
++
++	result = pci_is_guestdev_to_reassign(dev);
++	if (result)
++		return result;
++#endif /* CONFIG_PCI_GUESTDEV */
+ 	return (pci_specified_resource_alignment(dev) != 0);
+ }
+ 
+--- head-2010-01-18.orig/drivers/pci/pci.h	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/drivers/pci/pci.h	2009-12-04 10:27:46.000000000 +0100
+@@ -311,4 +311,11 @@ static inline int pci_resource_alignment
+ 	return resource_alignment(res);
+ }
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++extern int pci_is_guestdev_to_reassign(struct pci_dev *dev);
++extern int pci_is_iomuldev(struct pci_dev *dev);
++#else
++#define pci_is_iomuldev(dev)	0
++#endif
++
+ #endif /* DRIVERS_PCI_H */
+--- head-2010-01-18.orig/include/linux/acpi.h	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/include/linux/acpi.h	2009-12-04 10:27:46.000000000 +0100
+@@ -247,6 +247,8 @@ int acpi_check_region(resource_size_t st
+ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
+ 		      const char *name);
+ 
++int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn);
++
+ #ifdef CONFIG_PM_SLEEP
+ void __init acpi_no_s4_hw_signature(void);
+ void __init acpi_old_suspend_ordering(void);
+--- head-2010-01-18.orig/include/linux/pci.h	2010-01-19 10:57:28.000000000 +0100
++++ head-2010-01-18/include/linux/pci.h	2009-12-04 10:27:46.000000000 +0100
+@@ -1290,5 +1290,11 @@ extern void pci_hp_create_module_link(st
+ extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
+ #endif
+ 
++#ifdef CONFIG_PCI_GUESTDEV
++int pci_is_guestdev(struct pci_dev *dev);
++#else
++#define pci_is_guestdev(dev)	0
++#endif
++
+ #endif /* __KERNEL__ */
+ #endif /* LINUX_PCI_H */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-pciback-sriov
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-pciback-sriov
@@ -0,0 +1,119 @@
+From: Zhao, Yu <yu.zhao@intel.com>
+Subject: guest SR-IOV support for PV guest
+Patch-mainline: obsolete
+
+These changes are for PV guest to use Virtual Function. Because the VF's
+vendor, device registers in cfg space are 0xffff, which are invalid and
+ignored by PCI device scan. Values in 'struct pci_dev' are fixed up by
+SR-IOV code, and using these values will present correct VID and DID to
+PV guest kernel.
+
+And command registers in the cfg space are read only 0, which means we
+have to emulate MMIO enable bit (VF only uses MMIO  resource) so PV
+kernel can work properly.
+
+Acked-by: jbeulich@novell.com
+
+--- head-2009-07-28.orig/drivers/xen/pciback/conf_space_header.c	2009-07-28 12:01:32.000000000 +0200
++++ head-2009-07-28/drivers/xen/pciback/conf_space_header.c	2009-07-29 11:03:07.000000000 +0200
+@@ -18,6 +18,25 @@ struct pci_bar_info {
+ #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
+ #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
+ 
++static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
++{
++	int i;
++	int ret;
++
++	ret = pciback_read_config_word(dev, offset, value, data);
++	if (!atomic_read(&dev->enable_cnt))
++		return ret;
++
++	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
++		if (dev->resource[i].flags & IORESOURCE_IO)
++			*value |= PCI_COMMAND_IO;
++		if (dev->resource[i].flags & IORESOURCE_MEM)
++			*value |= PCI_COMMAND_MEMORY;
++	}
++
++	return ret;
++}
++
+ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
+ {
+ 	int err;
+@@ -141,10 +160,26 @@ static inline void read_dev_bar(struct p
+ 				struct pci_bar_info *bar_info, int offset,
+ 				u32 len_mask)
+ {
+-	pci_read_config_dword(dev, offset, &bar_info->val);
+-	pci_write_config_dword(dev, offset, len_mask);
+-	pci_read_config_dword(dev, offset, &bar_info->len_val);
+-	pci_write_config_dword(dev, offset, bar_info->val);
++	int	pos;
++	struct resource	*res = dev->resource;
++
++	if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
++		pos = PCI_ROM_RESOURCE;
++	else {
++		pos = (offset - PCI_BASE_ADDRESS_0) / 4;
++		if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
++				PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
++			   (PCI_BASE_ADDRESS_SPACE_MEMORY |
++				PCI_BASE_ADDRESS_MEM_TYPE_64))) {
++			bar_info->val = res[pos - 1].start >> 32;
++			bar_info->len_val = res[pos - 1].end >> 32;
++			return;
++		}
++	}
++
++	bar_info->val = res[pos].start |
++			(res[pos].flags & PCI_REGION_FLAG_MASK);
++	bar_info->len_val = res[pos].end - res[pos].start + 1;
+ }
+ 
+ static void *bar_init(struct pci_dev *dev, int offset)
+@@ -185,6 +220,22 @@ static void bar_release(struct pci_dev *
+ 	kfree(data);
+ }
+ 
++static int pciback_read_vendor(struct pci_dev *dev, int offset,
++			       u16 *value, void *data)
++{
++	*value = dev->vendor;
++
++	return 0;
++}
++
++static int pciback_read_device(struct pci_dev *dev, int offset,
++			       u16 *value, void *data)
++{
++	*value = dev->device;
++
++	return 0;
++}
++
+ static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
+ 			  void *data)
+ {
+@@ -212,9 +263,19 @@ static int bist_write(struct pci_dev *de
+ 
+ static const struct config_field header_common[] = {
+ 	{
++	 .offset    = PCI_VENDOR_ID,
++	 .size      = 2,
++	 .u.w.read  = pciback_read_vendor,
++	},
++	{
++	 .offset    = PCI_DEVICE_ID,
++	 .size      = 2,
++	 .u.w.read  = pciback_read_device,
++	},
++	{
+ 	 .offset    = PCI_COMMAND,
+ 	 .size      = 2,
+-	 .u.w.read  = pciback_read_config_word,
++	 .u.w.read  = command_read,
+ 	 .u.w.write = command_write,
+ 	},
+ 	{
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-auto-arch-i386.diff
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-auto-arch-i386.diff
@@ -0,0 +1,250 @@
+Subject: xen3 arch-i386
+From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 983:3358caa6b3a3)
+Patch-mainline: obsolete
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-04.orig/arch/x86/kernel/asm-offsets_32.c	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/asm-offsets_32.c	2009-12-04 10:44:46.000000000 +0100
+@@ -93,9 +93,14 @@ void foo(void)
+ 	OFFSET(pbe_orig_address, pbe, orig_address);
+ 	OFFSET(pbe_next, pbe, next);
+ 
++#ifndef CONFIG_X86_NO_TSS
+ 	/* Offset from the sysenter stack to tss.sp0 */
+-	DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
++	DEFINE(SYSENTER_stack_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
+ 		 sizeof(struct tss_struct));
++#else
++	/* sysenter stack points directly to sp0 */
++	DEFINE(SYSENTER_stack_sp0, 0);
++#endif
+ 
+ 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+ 	DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
+--- head-2010-01-04.orig/arch/x86/kernel/entry_32.S	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/entry_32.S	2009-12-04 10:44:46.000000000 +0100
+@@ -393,7 +393,7 @@ ENTRY(ia32_sysenter_target)
+ 	CFI_SIGNAL_FRAME
+ 	CFI_DEF_CFA esp, 0
+ 	CFI_REGISTER esp, ebp
+-	movl TSS_sysenter_sp0(%esp),%esp
++	movl SYSENTER_stack_sp0(%esp),%esp
+ sysenter_past_esp:
+ 	/*
+ 	 * Interrupts are disabled here, but we can't trace it until
+@@ -1325,7 +1325,7 @@ END(page_fault)
+  * that sets up the real kernel stack. Check here, since we can't
+  * allow the wrong stack to be used.
+  *
+- * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
++ * "SYSENTER_stack_sp0+12" is because the NMI/debug handler will have
+  * already pushed 3 words if it hits on the sysenter instruction:
+  * eflags, cs and eip.
+  *
+@@ -1337,7 +1337,7 @@ END(page_fault)
+ 	cmpw $__KERNEL_CS, 4(%esp)
+ 	jne \ok
+ \label:
+-	movl TSS_sysenter_sp0 + \offset(%esp), %esp
++	movl SYSENTER_stack_sp0 + \offset(%esp), %esp
+ 	CFI_DEF_CFA esp, 0
+ 	CFI_UNDEFINED eip
+ 	pushfl
+--- head-2010-01-04.orig/arch/x86/kernel/machine_kexec_32.c	2009-04-21 10:33:15.000000000 +0200
++++ head-2010-01-04/arch/x86/kernel/machine_kexec_32.c	2009-12-04 10:44:46.000000000 +0100
+@@ -26,6 +26,10 @@
+ #include <asm/system.h>
+ #include <asm/cacheflush.h>
+ 
++#ifdef CONFIG_XEN
++#include <xen/interface/kexec.h>
++#endif
++
+ static void machine_kexec_free_page_tables(struct kimage *image)
+ {
+ 	free_page((unsigned long)image->arch.pgd);
+@@ -96,6 +100,55 @@ static void machine_kexec_prepare_page_t
+ 		__pa(control_page), __pa(control_page));
+ }
+ 
++#ifdef CONFIG_XEN
++
++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
++
++#if PAGES_NR > KEXEC_XEN_NO_PAGES
++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
++#endif
++
++#if PA_CONTROL_PAGE != 0
++#error PA_CONTROL_PAGE is non zero - Xen support will break
++#endif
++
++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
++{
++	void *control_page;
++
++	memset(xki->page_list, 0, sizeof(xki->page_list));
++
++	control_page = page_address(image->control_code_page);
++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
++
++	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 __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) { ; }
++
++#endif /* CONFIG_XEN */
++
+ /*
+  * A architecture hook called to validate the
+  * proposed image and prepare the control pages
+@@ -135,6 +188,7 @@ void machine_kexec_cleanup(struct kimage
+ 	machine_kexec_free_page_tables(image);
+ }
+ 
++#ifndef CONFIG_XEN
+ /*
+  * Do not allocate memory (or fail in any way) in machine_kexec().
+  * We are past the point of no return, committed to rebooting now.
+@@ -199,6 +253,7 @@ void machine_kexec(struct kimage *image)
+ 
+ 	__ftrace_enabled_restore(save_ftrace_enabled);
+ }
++#endif
+ 
+ void arch_crash_save_vmcoreinfo(void)
+ {
+--- head-2010-01-04.orig/arch/x86/kernel/vm86_32.c	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/kernel/vm86_32.c	2009-12-04 10:44:46.000000000 +0100
+@@ -125,7 +125,9 @@ static int copy_vm86_regs_from_user(stru
+ 
+ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
+ {
++#ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss;
++#endif
+ 	struct pt_regs *ret;
+ 	unsigned long tmp;
+ 
+@@ -148,12 +150,16 @@ struct pt_regs *save_v86_state(struct ke
+ 		do_exit(SIGSEGV);
+ 	}
+ 
++#ifndef CONFIG_X86_NO_TSS
+ 	tss = &per_cpu(init_tss, get_cpu());
++#endif
+ 	current->thread.sp0 = current->thread.saved_sp0;
+ 	current->thread.sysenter_cs = __KERNEL_CS;
+ 	load_sp0(tss, &current->thread);
+ 	current->thread.saved_sp0 = 0;
++#ifndef CONFIG_X86_NO_TSS
+ 	put_cpu();
++#endif
+ 
+ 	ret = KVM86->regs32;
+ 
+@@ -280,7 +286,9 @@ out:
+ 
+ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
+ {
++#ifndef CONFIG_X86_NO_TSS
+ 	struct tss_struct *tss;
++#endif
+ /*
+  * make sure the vm86() system call doesn't try to do anything silly
+  */
+@@ -324,12 +332,16 @@ static void do_sys_vm86(struct kernel_vm
+ 	tsk->thread.saved_fs = info->regs32->fs;
+ 	tsk->thread.saved_gs = get_user_gs(info->regs32);
+ 
++#ifndef CONFIG_X86_NO_TSS
+ 	tss = &per_cpu(init_tss, get_cpu());
++#endif
+ 	tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0;
+ 	if (cpu_has_sep)
+ 		tsk->thread.sysenter_cs = 0;
+ 	load_sp0(tss, &tsk->thread);
++#ifndef CONFIG_X86_NO_TSS
+ 	put_cpu();
++#endif
+ 
+ 	tsk->thread.screen_bitmap = info->screen_bitmap;
+ 	if (info->flags & VM86_SCREEN_BITMAP)
+--- head-2010-01-04.orig/arch/x86/vdso/vdso32-setup.c	2010-01-04 12:00:41.000000000 +0100
++++ head-2010-01-04/arch/x86/vdso/vdso32-setup.c	2009-12-04 10:44:46.000000000 +0100
+@@ -26,6 +26,10 @@
+ #include <asm/vdso.h>
+ #include <asm/proto.h>
+ 
++#ifdef CONFIG_XEN
++#include <xen/interface/callback.h>
++#endif
++
+ enum {
+ 	VDSO_DISABLED = 0,
+ 	VDSO_ENABLED = 1,
+@@ -225,6 +229,7 @@ static inline void map_compat_vdso(int m
+ 
+ void enable_sep_cpu(void)
+ {
++#ifndef CONFIG_XEN
+ 	int cpu = get_cpu();
+ 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ 
+@@ -239,6 +244,35 @@ void enable_sep_cpu(void)
+ 	wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0);
+ 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0);
+ 	put_cpu();	
++#else
++	extern asmlinkage void ia32pv_sysenter_target(void);
++	static struct callback_register sysenter = {
++		.type = CALLBACKTYPE_sysenter,
++		.address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target },
++	};
++
++	if (!boot_cpu_has(X86_FEATURE_SEP))
++		return;
++
++	get_cpu();
++
++	if (xen_feature(XENFEAT_supervisor_mode_kernel))
++		sysenter.address.eip = (unsigned long)ia32_sysenter_target;
++
++	switch (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter)) {
++	case 0:
++		break;
++#if CONFIG_XEN_COMPAT < 0x030200
++	case -ENOSYS:
++		sysenter.type = CALLBACKTYPE_sysenter_deprecated;
++		if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) == 0)
++			break;
++#endif
++	default:
++		clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability);
++		break;
++	}
++#endif
+ }
+ 
+ static struct vm_area_struct gate_vma;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.28
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.28
@@ -0,0 +1,24180 @@
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+Subject: [PATCH] Linux: Update to 2.6.28
+Patch-mainline: 2.6.28
+
+ This patch contains the differences between Linux 2.6.27 and 2.6.28.
+
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.kernel.org/patch-2.6.28" by xen-port-patches.py
+
+--- head-2010-01-18.orig/arch/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/Kconfig	2009-11-06 10:51:47.000000000 +0100
+@@ -20,7 +20,7 @@ config OPROFILE
+ config OPROFILE_IBS
+ 	bool "OProfile AMD IBS support (EXPERIMENTAL)"
+ 	default n
+-	depends on OPROFILE && SMP && X86
++	depends on OPROFILE && SMP && X86 && !XEN
+ 	help
+           Instruction-Based Sampling (IBS) is a new profiling
+           technique that provides rich, precise program performance
+--- head-2010-01-18.orig/arch/ia64/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/Kconfig	2009-11-06 10:51:47.000000000 +0100
+@@ -231,7 +231,7 @@ config IA64_HP_SIM
+ config IA64_XEN_GUEST
+ 	bool "Xen guest"
+ 	select SWIOTLB
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	help
+ 	  Build a kernel that runs on Xen guest domain. At this moment only
+ 	  16KB page size in supported.
+--- head-2010-01-18.orig/arch/ia64/Makefile	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/Makefile	2009-11-20 11:02:40.000000000 +0100
+@@ -57,7 +57,7 @@ core-$(CONFIG_IA64_SGI_SN2)	+= arch/ia64
+ core-$(CONFIG_PERFMON)		+= arch/ia64/perfmon/
+ core-$(CONFIG_IA64_SGI_UV)	+= arch/ia64/uv/
+ core-$(CONFIG_KVM) 		+= arch/ia64/kvm/
+-core-$(CONFIG_XEN)		+= arch/ia64/xen/
++core-$(CONFIG_PARAVIRT_XEN)	+= arch/ia64/xen/
+ 
+ drivers-$(CONFIG_KDB)		+= arch/$(ARCH)/kdb/
+ drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
+--- head-2010-01-18.orig/arch/ia64/include/asm/xen/hypervisor.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/include/asm/xen/hypervisor.h	2009-11-06 10:51:47.000000000 +0100
+@@ -46,7 +46,7 @@ enum xen_domain_type {
+ 	XEN_HVM_DOMAIN,	/* running in a Xen hvm domain*/
+ };
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ extern enum xen_domain_type xen_domain_type;
+ #else
+ #define xen_domain_type		XEN_NATIVE
+@@ -66,7 +66,7 @@ extern enum xen_domain_type xen_domain_t
+ #endif
+ 
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ extern struct shared_info *HYPERVISOR_shared_info;
+ extern struct start_info *xen_start_info;
+ 
+--- head-2010-01-18.orig/arch/ia64/include/asm/xen/interface.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/include/asm/xen/interface.h	2010-01-04 17:34:44.000000000 +0100
+@@ -56,29 +56,21 @@
+ #ifndef _ASM_IA64_XEN_INTERFACE_H
+ #define _ASM_IA64_XEN_INTERFACE_H
+ 
+-#define __DEFINE_GUEST_HANDLE(name, type)	\
++#define __DEFINE_XEN_GUEST_HANDLE(name, type)	\
+ 	typedef struct { type *p; } __guest_handle_ ## name
+ 
+ #define DEFINE_GUEST_HANDLE_STRUCT(name)	\
+-	__DEFINE_GUEST_HANDLE(name, struct name)
+-#define DEFINE_GUEST_HANDLE(name)	__DEFINE_GUEST_HANDLE(name, name)
+-#define GUEST_HANDLE(name)		__guest_handle_ ## name
+-#define GUEST_HANDLE_64(name)		GUEST_HANDLE(name)
++	__DEFINE_XEN_GUEST_HANDLE(name, struct name)
++#define DEFINE_XEN_GUEST_HANDLE(name)	__DEFINE_XEN_GUEST_HANDLE(name, name)
++#define XEN_GUEST_HANDLE(name)		__guest_handle_ ## name
++#define XEN_GUEST_HANDLE_64(name)	XEN_GUEST_HANDLE(name)
+ #define set_xen_guest_handle(hnd, val)	do { (hnd).p = val; } while (0)
+ 
+ #ifndef __ASSEMBLY__
+-/* Guest handles for primitive C types. */
+-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
+-__DEFINE_GUEST_HANDLE(uint, unsigned int);
+-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
+-__DEFINE_GUEST_HANDLE(u64, unsigned long);
+-DEFINE_GUEST_HANDLE(char);
+-DEFINE_GUEST_HANDLE(int);
+-DEFINE_GUEST_HANDLE(long);
+-DEFINE_GUEST_HANDLE(void);
++__DEFINE_XEN_GUEST_HANDLE(u64, unsigned long);
+ 
++typedef unsigned long xen_ulong_t;
+ typedef unsigned long xen_pfn_t;
+-DEFINE_GUEST_HANDLE(xen_pfn_t);
+ #define PRI_xen_pfn	"lx"
+ #endif
+ 
+@@ -90,7 +82,7 @@ DEFINE_GUEST_HANDLE(xen_pfn_t);
+ /* Maximum number of virtual CPUs in multi-processor guests. */
+ /* keep sizeof(struct shared_page) <= PAGE_SIZE.
+  * this is checked in arch/ia64/xen/hypervisor.c. */
+-#define MAX_VIRT_CPUS	64
++#define XEN_LEGACY_MAX_VCPUS 64
+ 
+ #ifndef __ASSEMBLY__
+ 
+--- head-2010-01-18.orig/arch/ia64/kernel/asm-offsets.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/kernel/asm-offsets.c	2009-11-06 10:51:47.000000000 +0100
+@@ -290,7 +290,7 @@ void foo(void)
+ 	DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
+ 		offsetof (struct itc_jitter_data_t, itc_lastcycle));
+ 
+-#ifdef CONFIG_XEN
++#ifdef CONFIG_PARAVIRT_XEN
+ 	BLANK();
+ 
+ 	DEFINE(XEN_NATIVE_ASM, XEN_NATIVE);
+--- head-2010-01-18.orig/arch/ia64/xen/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/xen/Kconfig	2009-11-06 10:51:47.000000000 +0100
+@@ -2,7 +2,7 @@
+ # This Kconfig describes xen/ia64 options
+ #
+ 
+-config XEN
++config PARAVIRT_XEN
+ 	bool "Xen hypervisor support"
+ 	default y
+ 	depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
+@@ -17,9 +17,9 @@ config XEN
+ 	  both as a guest OS on Xen and natively on hardware.
+ 
+ config XEN_XENCOMM
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	bool
+ 
+ config NO_IDLE_HZ
+-	depends on XEN
++	depends on PARAVIRT_XEN
+ 	bool
+--- head-2010-01-18.orig/arch/ia64/xen/xcom_hcall.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/ia64/xen/xcom_hcall.c	2009-11-06 10:51:47.000000000 +0100
+@@ -343,7 +343,7 @@ xencommize_memory_reservation(struct xen
+ int
+ xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
+ {
+-	GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
++	XEN_GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
+ 	struct xen_memory_reservation *xmr = NULL;
+ 	int rc;
+ 	struct xencomm_handle *desc;
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:02:09.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:02:23.000000000 +0100
+@@ -1045,7 +1045,7 @@ config MICROCODE
+ 
+ config MICROCODE_INTEL
+ 	bool "Intel microcode patch loading support"
+-	depends on MICROCODE
++	depends on MICROCODE && !XEN
+ 	default MICROCODE
+ 	select FW_LOADER
+ 	---help---
+@@ -1058,7 +1058,7 @@ config MICROCODE_INTEL
+ 
+ config MICROCODE_AMD
+ 	bool "AMD microcode patch loading support"
+-	depends on MICROCODE
++	depends on MICROCODE && !XEN
+ 	select FW_LOADER
+ 	---help---
+ 	  If you select this option, microcode patch loading support for AMD
+@@ -1357,6 +1357,7 @@ config HIGHPTE
+ 
+ config X86_CHECK_BIOS_CORRUPTION
+ 	bool "Check for low memory corruption"
++	depends on !XEN
+ 	---help---
+ 	  Periodically check for memory corruption in low memory, which
+ 	  is suspected to be caused by BIOS.  Even when enabled in the
+@@ -1387,6 +1388,7 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_C
+ 
+ config X86_RESERVE_LOW_64K
+ 	bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
++	depends on !XEN
+ 	default y
+ 	---help---
+ 	  Reserve the first 64K of physical RAM on BIOSes that are known
+@@ -2079,7 +2081,7 @@ config DMAR_FLOPPY_WA
+ 
+ config INTR_REMAP
+ 	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
+-	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
++	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && !XEN && EXPERIMENTAL
+ 	---help---
+ 	  Supports Interrupt remapping for IO-APIC and MSI devices.
+ 	  To use x2apic mode in the CPU's which support x2APIC enhancements or
+--- head-2010-01-18.orig/arch/x86/Kconfig.cpu	2009-12-04 10:44:40.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig.cpu	2009-11-06 10:51:47.000000000 +0100
+@@ -497,7 +497,7 @@ config CPU_SUP_TRANSMETA_32
+ config CPU_SUP_UMC_32
+ 	default y
+ 	bool "Support UMC processors" if PROCESSOR_SELECT
+-	depends on !64BIT
++	depends on !64BIT && !XEN
+ 	---help---
+ 	  This enables detection, tunings and quirks for UMC processors
+ 
+@@ -510,13 +510,13 @@ config CPU_SUP_UMC_32
+ 
+ config X86_DS
+ 	def_bool X86_PTRACE_BTS
+-	depends on X86_DEBUGCTLMSR
++	depends on X86_DEBUGCTLMSR && !XEN
+ 	select HAVE_HW_BRANCH_TRACER
+ 
+ config X86_PTRACE_BTS
+ 	bool "Branch Trace Store"
+ 	default y
+-	depends on X86_DEBUGCTLMSR
++	depends on X86_DEBUGCTLMSR && !XEN
+ 	depends on BROKEN
+ 	---help---
+ 	  This adds a ptrace interface to the hardware's branch trace store.
+--- head-2010-01-18.orig/arch/x86/Makefile	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/Makefile	2009-11-06 10:51:47.000000000 +0100
+@@ -112,7 +112,7 @@ endif
+ KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+ 
+ # Xen subarch support
+-mflags-$(CONFIG_XEN)		:= -Iinclude/asm-x86/mach-xen
++mflags-$(CONFIG_XEN)		:= -Iarch/x86/include/mach-xen
+ mcore-$(CONFIG_XEN)		:= arch/x86/mach-xen/
+ 
+ KBUILD_CFLAGS += $(mflags-y)
+@@ -159,7 +159,7 @@ PHONY += bzImage vmlinuz $(BOOT_TARGETS)
+ 
+ ifdef CONFIG_XEN
+ KBUILD_CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
+-	-Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(KBUILD_CPPFLAGS)
++	-I$(srctree)/arch/x86/include/mach-xen $(KBUILD_CPPFLAGS)
+ 
+ ifdef CONFIG_X86_64
+ LDFLAGS_vmlinux := -e startup_64
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:47.000000000 +0100
+@@ -39,11 +39,11 @@
+ 	.endm 
+ 
+ 	/* clobbers %eax */	
+-	.macro  CLEAR_RREGS
++	.macro  CLEAR_RREGS _r9=rax
+ 	xorl 	%eax,%eax
+ 	movq	%rax,R11(%rsp)
+ 	movq	%rax,R10(%rsp)
+-	movq	%rax,R9(%rsp)
++	movq	%\_r9,R9(%rsp)
+ 	movq	%rax,R8(%rsp)
+ 	.endm
+ 
+@@ -52,11 +52,10 @@
+ 	 * We don't reload %eax because syscall_trace_enter() returned
+ 	 * the value it wants us to use in the table lookup.
+ 	 */
+-	.macro LOAD_ARGS32 offset
+-	movl \offset(%rsp),%r11d
+-	movl \offset+8(%rsp),%r10d
++	.macro LOAD_ARGS32 offset, _r9=0
++	.if \_r9
+ 	movl \offset+16(%rsp),%r9d
+-	movl \offset+24(%rsp),%r8d
++	.endif
+ 	movl \offset+40(%rsp),%ecx
+ 	movl \offset+48(%rsp),%edx
+ 	movl \offset+56(%rsp),%esi
+@@ -135,7 +134,7 @@ ENTRY(ia32_sysenter_target)
+ 	SAVE_ARGS 0,0,1
+  	/* no need to do an access_ok check here because rbp has been
+  	   32bit zero extended */ 
+-1:	movl	(%rbp),%r9d
++1:	movl	(%rbp),%ebp
+  	.section __ex_table,"a"
+  	.quad 1b,ia32_badarg
+  	.previous	
+@@ -146,7 +145,7 @@ ENTRY(ia32_sysenter_target)
+ 	cmpl	$(IA32_NR_syscalls-1),%eax
+ 	ja	ia32_badsys
+ sysenter_do_call:
+-	IA32_ARG_FIXUP 1
++	IA32_ARG_FIXUP
+ sysenter_dispatch:
+ 	call	*ia32_sys_call_table(,%rax,8)
+ 	movq	%rax,RAX-ARGOFFSET(%rsp)
+@@ -204,20 +203,17 @@ sysexit_audit:
+ #endif
+ 
+ sysenter_tracesys:
+-	xchgl	%r9d,%ebp
+ #ifdef CONFIG_AUDITSYSCALL
+ 	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+ 	jz	sysenter_auditsys
+ #endif
+ 	SAVE_REST
+ 	CLEAR_RREGS
+-	movq	%r9,R9(%rsp)
+ 	movq	$-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+ 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call	syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+-	xchgl	%ebp,%r9d
+ 	cmpl	$(IA32_NR_syscalls-1),%eax
+ 	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+ 	jmp	sysenter_do_call
+@@ -272,9 +268,9 @@ ENTRY(ia32_cstar_target)
+ 	orl   $TS_COMPAT,TI_status(%r10)
+ 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+ 	jnz   cstar_tracesys
+-cstar_do_call:	
+ 	cmpl $IA32_NR_syscalls-1,%eax
+ 	ja  ia32_badsys
++cstar_do_call:
+ 	IA32_ARG_FIXUP 1
+ cstar_dispatch:
+ 	call *ia32_sys_call_table(,%rax,8)
+@@ -303,15 +299,13 @@ cstar_tracesys:
+ #endif
+ 	xchgl %r9d,%ebp
+ 	SAVE_REST
+-	CLEAR_RREGS
+-	movq %r9,R9(%rsp)
++	CLEAR_RREGS r9
+ 	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+-	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
++	LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+ 	xchgl %ebp,%r9d
+-	movl RSP-ARGOFFSET(%rsp), %r8d
+ 	cmpl $(IA32_NR_syscalls-1),%eax
+ 	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+ 	jmp cstar_do_call
+@@ -522,8 +516,8 @@ ia32_sys_call_table:
+ 	.quad compat_sys_setrlimit	/* 75 */
+ 	.quad compat_sys_old_getrlimit	/* old_getrlimit */
+ 	.quad compat_sys_getrusage
+-	.quad sys32_gettimeofday
+-	.quad sys32_settimeofday
++	.quad compat_sys_gettimeofday
++	.quad compat_sys_settimeofday
+ 	.quad sys_getgroups16	/* 80 */
+ 	.quad sys_setgroups16
+ 	.quad sys32_old_select
+--- head-2010-01-18.orig/arch/x86/include/asm/cpufeature.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/cpufeature.h	2009-11-18 14:49:48.000000000 +0100
+@@ -246,7 +246,11 @@ extern const char * const x86_power_flag
+ #define cpu_has_xmm4_1		boot_cpu_has(X86_FEATURE_XMM4_1)
+ #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
+ #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
++#ifndef CONFIG_XEN
+ #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
++#else
++#define cpu_has_xsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
++#endif
+ #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
+ #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
+ 
+--- head-2010-01-18.orig/arch/x86/include/asm/hw_irq.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/hw_irq.h	2009-11-06 10:51:47.000000000 +0100
+@@ -107,6 +107,7 @@ extern void smp_error_interrupt(struct p
+ extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
+ #endif
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_XEN
+ extern void smp_reschedule_interrupt(struct pt_regs *);
+ extern void smp_call_function_interrupt(struct pt_regs *);
+ extern void smp_call_function_single_interrupt(struct pt_regs *);
+@@ -115,6 +116,12 @@ extern void smp_invalidate_interrupt(str
+ #else
+ extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *);
+ #endif
++#else
++#include <linux/irqreturn.h>
++extern irqreturn_t smp_reschedule_interrupt(int, void *);
++extern irqreturn_t smp_call_function_interrupt(int, void *);
++extern irqreturn_t smp_call_function_single_interrupt(int, void *);
++#endif
+ #endif
+ 
+ extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
+--- head-2010-01-18.orig/arch/x86/include/asm/segment.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/segment.h	2009-11-06 10:51:47.000000000 +0100
+@@ -186,7 +186,9 @@
+ #define __KERNEL_DS	(GDT_ENTRY_KERNEL_DS * 8)
+ #define __USER_DS     (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
+ #define __USER_CS     (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
+-#ifndef CONFIG_PARAVIRT
++#if defined(CONFIG_X86_XEN)
++#define get_kernel_rpl()  (xen_feature(XENFEAT_supervisor_mode_kernel)?0:1)
++#elif !defined(CONFIG_PARAVIRT)
+ #define get_kernel_rpl()  0
+ #endif
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:47.000000000 +0100
+@@ -40,4 +40,4 @@
+ #define free_gatt_pages(table, order)	\
+ 	dma_free_coherent(NULL,PAGE_SIZE<<(order),(table),virt_to_bus(table))
+ 
+-#endif
++#endif /* _ASM_X86_AGP_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_DESC_H_
+-#define _ASM_DESC_H_
++#ifndef _ASM_X86_DESC_H
++#define _ASM_X86_DESC_H
+ 
+ #ifndef __ASSEMBLY__
+ #include <asm/desc_defs.h>
+@@ -24,6 +24,11 @@ static inline void fill_ldt(struct desc_
+ 	desc->d = info->seg_32bit;
+ 	desc->g = info->limit_in_pages;
+ 	desc->base2 = (info->base_addr & 0xff000000) >> 24;
++	/*
++	 * Don't allow setting of the lm bit. It is useless anyway
++	 * because 64bit system calls require __USER_CS:
++	 */
++	desc->l = 0;
+ }
+ 
+ #ifndef CONFIG_X86_NO_IDT
+@@ -98,6 +103,14 @@ static inline int desc_empty(const void 
+ #define write_idt_entry(dt, entry, g)		\
+ 	native_write_idt_entry(dt, entry, g)
+ 
++static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
++{
++}
++
++static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
++{
++}
++
+ static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ 					  const gate_desc *gate)
+ {
+@@ -360,20 +373,16 @@ static inline void set_system_intr_gate(
+ 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+ }
+ 
+-static inline void set_trap_gate(unsigned int n, void *addr)
++static inline void set_system_trap_gate(unsigned int n, void *addr)
+ {
+ 	BUG_ON((unsigned)n > 0xFF);
+-	_set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
++	_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+ }
+ 
+-static inline void set_system_gate(unsigned int n, void *addr)
++static inline void set_trap_gate(unsigned int n, void *addr)
+ {
+ 	BUG_ON((unsigned)n > 0xFF);
+-#ifdef CONFIG_X86_32
+-	_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+-#else
+-	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+-#endif
++	_set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+ }
+ 
+ static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+@@ -388,7 +397,7 @@ static inline void set_intr_gate_ist(int
+ 	_set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+ }
+ 
+-static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
++static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist)
+ {
+ 	BUG_ON((unsigned)n > 0xFF);
+ 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+@@ -420,4 +429,4 @@ static inline void set_system_gate_ist(i
+ 
+ #endif /* __ASSEMBLY__ */
+ 
+-#endif
++#endif /* _ASM_X86_DESC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,17 +1,12 @@
+-#ifndef _ASM_DMA_MAPPING_H_
++#ifndef _ASM_X86_DMA_MAPPING_H_
+ 
+ #include_next <asm/dma-mapping.h>
+ 
+-static inline int
+-address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+-{
+-	dma_addr_t mask = 0xffffffff;
+-	/* If the device has a mask, use it, otherwise default to 32 bits */
+-	if (hwdev && hwdev->dma_mask)
+-		mask = *hwdev->dma_mask;
+-	return (addr & ~mask) != 0;
+-}
++void dma_generic_free_coherent(struct device *, size_t, void *, dma_addr_t);
++
++#define address_needs_mapping(hwdev, addr, size) \
++	!is_buffer_dma_capable(dma_get_mask(hwdev), addr, size)
+ 
+ extern int range_straddles_page_boundary(paddr_t p, size_t size);
+ 
+-#endif /* _ASM_DMA_MAPPING_H_ */
++#endif /* _ASM_X86_DMA_MAPPING_H_ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_FIXMAP_H
+-#define _ASM_FIXMAP_H
++#ifndef _ASM_X86_FIXMAP_H
++#define _ASM_X86_FIXMAP_H
+ 
+ #ifdef CONFIG_X86_32
+ # include "fixmap_32.h"
+@@ -9,6 +9,10 @@
+ 
+ extern int fixmaps_set;
+ 
++extern pte_t *kmap_pte;
++extern pgprot_t kmap_prot;
++extern pte_t *pkmap_page_table;
++
+ void xen_set_fixmap(enum fixed_addresses, maddr_t, pgprot_t);
+ 
+ static inline void __set_fixmap(enum fixed_addresses idx,
+@@ -61,4 +65,4 @@ static inline unsigned long virt_to_fix(
+ 	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+ 	return __virt_to_fix(vaddr);
+ }
+-#endif
++#endif /* _ASM_X86_FIXMAP_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_32.h	2009-11-06 10:51:47.000000000 +0100
+@@ -10,8 +10,8 @@
+  * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+  */
+ 
+-#ifndef _ASM_FIXMAP_32_H
+-#define _ASM_FIXMAP_32_H
++#ifndef _ASM_X86_FIXMAP_32_H
++#define _ASM_X86_FIXMAP_32_H
+ 
+ /* used by vmalloc.c, vsyscall.lds.S.
+  *
+@@ -27,10 +27,8 @@ extern unsigned long __FIXADDR_TOP;
+ #include <asm/acpi.h>
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+-#ifdef CONFIG_HIGHMEM
+ #include <linux/threads.h>
+ #include <asm/kmap_types.h>
+-#endif
+ 
+ /*
+  * Here we define all the compile-time 'special' virtual
+@@ -81,10 +79,8 @@ enum fixed_addresses {
+ #ifdef CONFIG_X86_CYCLONE_TIMER
+ 	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+ #endif
+-#ifdef CONFIG_HIGHMEM
+ 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+ 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+-#endif
+ #ifdef CONFIG_PCI_MMCONFIG
+ 	FIX_PCIE_MCFG,
+ #endif
+@@ -100,10 +96,10 @@ enum fixed_addresses {
+ 	 * can have a single pgd entry and a single pte table:
+ 	 */
+ #define NR_FIX_BTMAPS		64
+-#define FIX_BTMAPS_NESTING	4
++#define FIX_BTMAPS_SLOTS	4
+ 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+ 			(__end_of_permanent_fixed_addresses & 255),
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+ 	FIX_WP_TEST,
+ #ifdef CONFIG_ACPI
+ 	FIX_ACPI_BEGIN,
+@@ -126,4 +122,4 @@ extern void reserve_top_address(unsigned
+ #define FIXADDR_BOOT_START	(FIXADDR_TOP - __FIXADDR_BOOT_SIZE)
+ 
+ #endif /* !__ASSEMBLY__ */
+-#endif
++#endif /* _ASM_X86_FIXMAP_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap_64.h	2009-11-06 10:51:47.000000000 +0100
+@@ -8,8 +8,8 @@
+  * Copyright (C) 1998 Ingo Molnar
+  */
+ 
+-#ifndef _ASM_FIXMAP_64_H
+-#define _ASM_FIXMAP_64_H
++#ifndef _ASM_X86_FIXMAP_64_H
++#define _ASM_X86_FIXMAP_64_H
+ 
+ #include <linux/kernel.h>
+ #include <asm/acpi.h>
+@@ -47,6 +47,10 @@ enum fixed_addresses {
+ #ifndef CONFIG_XEN
+ 	FIX_IO_APIC_BASE_0,
+ 	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
++#else
++#define NR_FIX_ISAMAPS	256
++	FIX_ISAMAP_END,
++	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ #endif
+ #ifdef CONFIG_EFI
+ 	FIX_EFI_IO_MAP_LAST_PAGE,
+@@ -58,29 +62,26 @@ enum fixed_addresses {
+ #else
+ 	FIX_SHARED_INFO,
+ #endif
++	__end_of_permanent_fixed_addresses,
+ #ifdef CONFIG_ACPI
+ 	FIX_ACPI_BEGIN,
+ 	FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+ #endif
+-#define NR_FIX_ISAMAPS	256
+-	FIX_ISAMAP_END,
+-	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+ #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+ 	FIX_OHCI1394_BASE,
+ #endif
+-	__end_of_permanent_fixed_addresses,
+ 	/*
+ 	 * 256 temporary boot-time mappings, used by early_ioremap(),
+ 	 * before ioremap() is functional.
+ 	 *
+-	 * We round it up to the next 512 pages boundary so that we
++	 * We round it up to the next 256 pages boundary so that we
+ 	 * can have a single pgd entry and a single pte table:
+ 	 */
+ #define NR_FIX_BTMAPS		64
+-#define FIX_BTMAPS_NESTING	4
+-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
+-			(__end_of_permanent_fixed_addresses & 511),
+-	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
++#define FIX_BTMAPS_SLOTS	4
++	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
++			(__end_of_permanent_fixed_addresses & 255),
++	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+ 	__end_of_fixed_addresses
+ };
+ 
+@@ -92,4 +93,4 @@ enum fixed_addresses {
+ #define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
+ #define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+ 
+-#endif
++#endif /* _ASM_X86_FIXMAP_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/highmem.h	2009-11-06 10:51:47.000000000 +0100
+@@ -15,8 +15,8 @@
+  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+  */
+ 
+-#ifndef _ASM_HIGHMEM_H
+-#define _ASM_HIGHMEM_H
++#ifndef _ASM_X86_HIGHMEM_H
++#define _ASM_X86_HIGHMEM_H
+ 
+ #ifdef __KERNEL__
+ 
+@@ -24,14 +24,11 @@
+ #include <linux/threads.h>
+ #include <asm/kmap_types.h>
+ #include <asm/tlbflush.h>
++#include <asm/fixmap.h>
+ 
+ /* declarations for highmem.c */
+ extern unsigned long highstart_pfn, highend_pfn;
+ 
+-extern pte_t *kmap_pte;
+-extern pgprot_t kmap_prot;
+-extern pte_t *pkmap_page_table;
+-
+ /*
+  * Right now we initialize only a single pte table. It can be extended
+  * easily, subsequent pte tables have to be allocated in one physical
+@@ -96,4 +93,4 @@ static inline void copy_user_highpage(st
+ 
+ #endif /* __KERNEL__ */
+ 
+-#endif /* _ASM_HIGHMEM_H */
++#endif /* _ASM_X86_HIGHMEM_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/io.h	2009-12-11 15:20:59.000000000 +0100
+@@ -5,20 +5,6 @@
+ 
+ #include <linux/compiler.h>
+ 
+-/*
+- * early_ioremap() and early_iounmap() are for temporary early boot-time
+- * mappings, before the real ioremap() is functional.
+- * A boot-time mapping is currently limited to at most 16 pages.
+- */
+-#ifndef __ASSEMBLY__
+-extern void early_ioremap_init(void);
+-extern void early_ioremap_clear(void);
+-extern void early_ioremap_reset(void);
+-extern void *early_ioremap(unsigned long offset, unsigned long size);
+-extern void early_iounmap(void *addr, unsigned long size);
+-extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
+-#endif
+-
+ #define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void __iomem *addr) \
+ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+@@ -73,12 +59,14 @@ build_mmio_write(__writeq, "q", unsigned
+ #define writeq writeq
+ #endif
+ 
++extern int iommu_bio_merge;
++
+ #define native_io_delay xen_io_delay
+ 
+ #ifdef CONFIG_X86_32
+-# include "../../io_32.h"
++# include "../../asm/io_32.h"
+ #else
+-# include "../../io_64.h"
++# include "../../asm/io_64.h"
+ #endif
+ 
+ #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+@@ -95,7 +83,7 @@ build_mmio_write(__writeq, "q", unsigned
+ 				  (unsigned long)(bv)->bv_offset)
+ 
+ #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
+-	(bvec_to_phys(vec1) + (vec1)->bv_len == bvec_to_phys(vec2) \
++	(__BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
+ 	 && bvec_to_pseudophys(vec1) + (vec1)->bv_len \
+ 	    == bvec_to_pseudophys(vec2))
+ 
+@@ -134,8 +122,9 @@ extern void __iomem *ioremap_wc(unsigned
+ extern void early_ioremap_init(void);
+ extern void early_ioremap_clear(void);
+ extern void early_ioremap_reset(void);
+-extern void *early_ioremap(unsigned long offset, unsigned long size);
+-extern void early_iounmap(void *addr, unsigned long size);
++extern void __iomem *early_ioremap(unsigned long offset, unsigned long size);
++extern void __iomem *early_memremap(unsigned long offset, unsigned long size);
++extern void early_iounmap(void __iomem *addr, unsigned long size);
+ extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys);
+ 
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_IRQ_VECTORS_H
+-#define _ASM_IRQ_VECTORS_H
++#ifndef _ASM_X86_IRQ_VECTORS_H
++#define _ASM_X86_IRQ_VECTORS_H
+ 
+ #ifdef CONFIG_X86_32
+ # define SYSCALL_VECTOR		0x80
+@@ -47,6 +47,5 @@
+ #define NR_DYNIRQS		256
+ 
+ #define NR_IRQS			(NR_PIRQS + NR_DYNIRQS)
+-#define NR_IRQ_VECTORS		NR_IRQS
+ 
+-#endif /* _ASM_IRQ_VECTORS_H */
++#endif /* _ASM_X86_IRQ_VECTORS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:47.000000000 +0100
+@@ -157,23 +157,6 @@ static inline int raw_irqs_disabled_flag
+ 	raw_irqs_disabled_flags(flags);					\
+ })
+ 
+-/*
+- * makes the traced hardirq state match with the machine state
+- *
+- * should be a rarely used function, only in places where its
+- * otherwise impossible to know the irq state, like in traps.
+- */
+-static inline void trace_hardirqs_fixup_flags(unsigned long flags)
+-{
+-	if (raw_irqs_disabled_flags(flags))
+-		trace_hardirqs_off();
+-	else
+-		trace_hardirqs_on();
+-}
+-
+-#define trace_hardirqs_fixup() \
+-	trace_hardirqs_fixup_flags(__raw_local_save_flags())
+-
+ #else
+ 
+ #ifdef CONFIG_X86_64
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __ASM_X86_MMU_CONTEXT_H
+-#define __ASM_X86_MMU_CONTEXT_H
++#ifndef _ASM_X86_MMU_CONTEXT_H
++#define _ASM_X86_MMU_CONTEXT_H
+ 
+ #include <asm/desc.h>
+ #include <asm/atomic.h>
+@@ -39,4 +39,4 @@ do {						\
+ } while (0);
+ 
+ 
+-#endif /* __ASM_X86_MMU_CONTEXT_H */
++#endif /* _ASM_X86_MMU_CONTEXT_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __I386_SCHED_H
+-#define __I386_SCHED_H
++#ifndef _ASM_X86_MMU_CONTEXT_32_H
++#define _ASM_X86_MMU_CONTEXT_32_H
+ 
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+@@ -81,4 +81,4 @@ static inline void switch_mm(struct mm_s
+ #define deactivate_mm(tsk, mm)			\
+ 	asm("movl %0,%%gs": :"r" (0));
+ 
+-#endif
++#endif /* _ASM_X86_MMU_CONTEXT_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_64.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __X86_64_MMU_CONTEXT_H
+-#define __X86_64_MMU_CONTEXT_H
++#ifndef _ASM_X86_MMU_CONTEXT_64_H
++#define _ASM_X86_MMU_CONTEXT_64_H
+ 
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+@@ -103,4 +103,4 @@ do {						\
+ 	asm volatile("movl %0,%%fs"::"r"(0));	\
+ } while (0)
+ 
+-#endif
++#endif /* _ASM_X86_MMU_CONTEXT_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __x86_PCI_H
+-#define __x86_PCI_H
++#ifndef _ASM_X86_PCI_H
++#define _ASM_X86_PCI_H
+ 
+ #include <linux/mm.h> /* for struct page */
+ #include <linux/types.h>
+@@ -93,7 +93,7 @@ static inline void early_quirks(void) { 
+ #ifdef CONFIG_X86_32
+ # include "pci_32.h"
+ #else
+-# include "pci_64.h"
++# include "../../asm/pci_64.h"
+ #endif
+ 
+ /* implement the pci_ DMA API in terms of the generic device dma_ one */
+@@ -117,4 +117,4 @@ static inline cpumask_t __pcibus_to_cpum
+ }
+ #endif
+ 
+-#endif
++#endif /* _ASM_X86_PCI_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:47.000000000 +0100
+@@ -149,4 +149,4 @@ extern void __pud_free_tlb(struct mmu_ga
+ #endif	/* PAGETABLE_LEVELS > 3 */
+ #endif	/* PAGETABLE_LEVELS > 2 */
+ 
+-#endif	/* _ASM_X86_PGALLOC_H */
++#endif /* _ASM_X86_PGALLOC_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:47.000000000 +0100
+@@ -14,11 +14,11 @@
+ #define _PAGE_BIT_PAT		7	/* on 4KB pages */
+ #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+ #define _PAGE_BIT_UNUSED1	9	/* available for programmer */
+-#define _PAGE_BIT_UNUSED2	10
+-#define _PAGE_BIT_IO		11	/* Mapped page is I/O or foreign and
+-					 * has no associated page struct. */
++#define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
++#define _PAGE_BIT_UNUSED3	11
+ #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
+ #define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
++#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
+ #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+ 
+ /* If _PAGE_BIT_PRESENT is clear, we use these: */
+@@ -39,11 +39,12 @@
+ #define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
+ #define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
+ #define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
+-#define _PAGE_UNUSED2	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2)
+-#define _PAGE_IO	(_AT(pteval_t, 1) << _PAGE_BIT_IO)
++#define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
++#define _PAGE_UNUSED3	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3)
+ #define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
+ #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+ #define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
++#define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
+ #define __HAVE_ARCH_PTE_SPECIAL
+ 
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+@@ -69,7 +70,7 @@ extern unsigned int __kernel_page_user;
+ 			 _PAGE_DIRTY | __kernel_page_user)
+ 
+ /* Set of bits not changed in pte_modify */
+-#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IO |	\
++#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IOMAP | \
+ 			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+ 
+ /*
+@@ -116,6 +117,11 @@ extern unsigned int __kernel_page_user;
+ #define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+ #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+ 
++#define __PAGE_KERNEL_IO		(__PAGE_KERNEL | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
++#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC | _PAGE_IOMAP)
++
+ #define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
+ #define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
+@@ -130,6 +136,11 @@ extern unsigned int __kernel_page_user;
+ #define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
+ #define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+ 
++#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
++#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
++#define PAGE_KERNEL_IO_UC_MINUS		__pgprot(__PAGE_KERNEL_IO_UC_MINUS)
++#define PAGE_KERNEL_IO_WC		__pgprot(__PAGE_KERNEL_IO_WC)
++
+ /*         xwr */
+ #define __P000	PAGE_NONE
+ #define __P001	PAGE_READONLY
+@@ -149,6 +160,22 @@ extern unsigned int __kernel_page_user;
+ #define __S110	PAGE_SHARED_EXEC
+ #define __S111	PAGE_SHARED_EXEC
+ 
++/*
++ * early identity mapping  pte attrib macros.
++ */
++#ifdef CONFIG_X86_64
++#define __PAGE_KERNEL_IDENT_LARGE_EXEC	__PAGE_KERNEL_LARGE_EXEC
++#else
++/*
++ * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
++ * bits are combined, this will alow user to access the high address mapped
++ * VDSO in the presence of CONFIG_COMPAT_VDSO
++ */
++#define PTE_IDENT_ATTR	 0x003		/* PRESENT+RW */
++#define PDE_IDENT_ATTR	 0x067		/* PRESENT+RW+USER+DIRTY+ACCESSED */
++#define PGD_IDENT_ATTR	 0x001		/* PRESENT (no other attributes) */
++#endif
++
+ #ifndef __ASSEMBLY__
+ 
+ /*
+@@ -205,6 +232,15 @@ static inline int pte_special(pte_t pte)
+ 	return pte_flags(pte) & _PAGE_SPECIAL;
+ }
+ 
++#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_IOMAP ? 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))
++
+ static inline int pmd_large(pmd_t pte)
+ {
+ 	return (__pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+@@ -347,6 +383,9 @@ static inline void xen_pagetable_setup_s
+ static inline void xen_pagetable_setup_done(pgd_t *base) {}
+ #endif
+ 
++struct seq_file;
++extern void arch_report_meminfo(struct seq_file *m);
++
+ #define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
+ #define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
+ 
+@@ -641,4 +680,4 @@ int touch_pte_range(struct mm_struct *mm
+ 
+ #endif	/* __ASSEMBLY__ */
+ 
+-#endif	/* _ASM_X86_PGTABLE_H */
++#endif /* _ASM_X86_PGTABLE_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _I386_PGTABLE_3LEVEL_H
+-#define _I386_PGTABLE_3LEVEL_H
++#ifndef _ASM_X86_PGTABLE_3LEVEL_H
++#define _ASM_X86_PGTABLE_3LEVEL_H
+ 
+ /*
+  * Intel Physical Address Extension (PAE) Mode - three-level page
+@@ -102,13 +102,13 @@ static inline void pud_clear(pud_t *pudp
+ 		xen_tlb_flush();
+ }
+ 
+-#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_PFN_MASK))
++#define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
+ 
+ #define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK))
+ 
+ 
+ /* Find an entry in the second-level page table.. */
+-#define pmd_offset(pud, address) ((pmd_t *)pud_page(*(pud)) +	\
++#define pmd_offset(pud, address) ((pmd_t *)pud_page_vaddr(*(pud)) +	\
+ 				  pmd_index(address))
+ 
+ #ifdef CONFIG_SMP
+@@ -133,8 +133,6 @@ static inline int pte_same(pte_t a, pte_
+ 	return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
+ }
+ 
+-#define pte_page(x)	pfn_to_page(pte_pfn(x))
+-
+ static inline int pte_none(pte_t pte)
+ {
+ 	return !(pte.pte_low | pte.pte_high);
+@@ -142,12 +140,6 @@ static inline int pte_none(pte_t pte)
+ 
+ #define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+ 			 ((_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_IO ? max_mapnr :	\
+-		       (_pte).pte_low & _PAGE_PRESENT ?		\
+-		       mfn_to_local_pfn(__pte_mfn(_pte)) :	\
+-		       __pte_mfn(_pte))
+ 
+ /*
+  * Bits 0, 6 and 7 are taken in the low part of the pte,
+@@ -165,4 +157,4 @@ static inline int pte_none(pte_t pte)
+ #define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+ #define __swp_entry_to_pte(x)		((pte_t){ { .pte_high = (x).val } })
+ 
+-#endif /* _I386_PGTABLE_3LEVEL_H */
++#endif /* _ASM_X86_PGTABLE_3LEVEL_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable-3level-defs.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _I386_PGTABLE_3LEVEL_DEFS_H
+-#define _I386_PGTABLE_3LEVEL_DEFS_H
++#ifndef _ASM_X86_PGTABLE_3LEVEL_DEFS_H
++#define _ASM_X86_PGTABLE_3LEVEL_DEFS_H
+ 
+ #define SHARED_KERNEL_PMD	0
+ 
+@@ -21,4 +21,4 @@
+  */
+ #define PTRS_PER_PTE	512
+ 
+-#endif /* _I386_PGTABLE_3LEVEL_DEFS_H */
++#endif /* _ASM_X86_PGTABLE_3LEVEL_DEFS_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _I386_PGTABLE_H
+-#define _I386_PGTABLE_H
++#ifndef _ASM_X86_PGTABLE_32_H
++#define _ASM_X86_PGTABLE_32_H
+ 
+ /*
+  * The Linux memory management assumes a three-level page table setup. On
+@@ -29,6 +29,7 @@ static inline void pgtable_cache_init(vo
+ static inline void check_pgt_cache(void) { }
+ void paging_init(void);
+ 
++extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t);
+ 
+ /*
+  * The Linux x86 paging architecture is 'compile-time dual-mode', it
+@@ -54,8 +55,7 @@ void paging_init(void);
+  * area for the same reason. ;)
+  */
+ #define VMALLOC_OFFSET	(8 * 1024 * 1024)
+-#define VMALLOC_START	(((unsigned long)high_memory + 2 * VMALLOC_OFFSET - 1) \
+-			 & ~(VMALLOC_OFFSET - 1))
++#define VMALLOC_START	((unsigned long)high_memory + VMALLOC_OFFSET)
+ #ifdef CONFIG_X86_PAE
+ #define LAST_PKMAP 512
+ #else
+@@ -71,6 +71,8 @@ void paging_init(void);
+ # define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
+ #endif
+ 
++#define MAXMEM	(VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE)
++
+ /*
+  * Define this if things work differently on an i386 and an i486:
+  * it will (on an i486) warn about kernel memory accesses that are
+@@ -195,4 +197,4 @@ void make_lowmem_page_writable(void *va,
+ #define io_remap_pfn_range(vma, from, pfn, size, prot)			\
+ 	direct_remap_pfn_range(vma, from, pfn, size, prot, DOMID_IO)
+ 
+-#endif /* _I386_PGTABLE_H */
++#endif /* _ASM_X86_PGTABLE_32_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _X86_64_PGTABLE_H
+-#define _X86_64_PGTABLE_H
++#ifndef _ASM_X86_PGTABLE_64_H
++#define _ASM_X86_PGTABLE_64_H
+ 
+ #include <linux/const.h>
+ #ifndef __ASSEMBLY__
+@@ -65,14 +65,14 @@ extern void paging_init(void);
+ 	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
+ #define pmd_ERROR(e)							\
+-	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n",		\
++	printk("%s:%d: bad pmd %p(%016lx pfn %010Lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pmd_val(e), pmd_pfn(e))
+ #define pud_ERROR(e)							\
+-	printk("%s:%d: bad pud %p(%016lx pfn %010lx).\n",		\
++	printk("%s:%d: bad pud %p(%016lx pfn %010Lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pud_val(e),			\
+ 	       (pud_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ #define pgd_ERROR(e)							\
+-	printk("%s:%d: bad pgd %p(%016lx pfn %010lx).\n",		\
++	printk("%s:%d: bad pgd %p(%016lx pfn %010Lx).\n",		\
+ 	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+ 	       (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+ 
+@@ -181,14 +181,6 @@ static inline int pmd_bad(pmd_t pmd)
+ #define pages_to_mb(x)	((x) >> (20 - PAGE_SHIFT))   /* FIXME: is this right? */
+ 
+ #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_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_IO ? max_mapnr :	\
+-		       (_pte).pte & _PAGE_PRESENT ?		\
+-		       mfn_to_local_pfn(__pte_mfn(_pte)) :	\
+-		       __pte_mfn(_pte))
+-
+-#define pte_page(x)	pfn_to_page(pte_pfn((x)))
+ 
+ /*
+  * Macro to mark a page protection value as "uncacheable".
+@@ -312,4 +304,4 @@ extern void cleanup_highmap(void);
+ #define __HAVE_ARCH_PTE_SAME
+ #endif /* !__ASSEMBLY__ */
+ 
+-#endif /* _X86_64_PGTABLE_H */
++#endif /* _ASM_X86_PGTABLE_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __ASM_X86_PROCESSOR_H
+-#define __ASM_X86_PROCESSOR_H
++#ifndef _ASM_X86_PROCESSOR_H
++#define _ASM_X86_PROCESSOR_H
+ 
+ #include <asm/processor-flags.h>
+ 
+@@ -20,6 +20,7 @@ struct mm_struct;
+ #include <asm/msr.h>
+ #include <asm/desc_defs.h>
+ #include <asm/nops.h>
++#include <asm/ds.h>
+ 
+ #include <linux/personality.h>
+ #include <linux/cpumask.h>
+@@ -76,11 +77,11 @@ struct cpuinfo_x86 {
+ 	int			 x86_tlbsize;
+ 	__u8			x86_virt_bits;
+ 	__u8			x86_phys_bits;
++#endif
+ 	/* CPUID returned core id bits: */
+ 	__u8			x86_coreid_bits;
+ 	/* Max extended CPUID function supported: */
+ 	__u32			extended_cpuid_level;
+-#endif
+ 	/* Maximum supported CPUID level, -1=no CPUID: */
+ 	int			cpuid_level;
+ 	__u32			x86_capability[NCAPINTS];
+@@ -140,6 +141,8 @@ DECLARE_PER_CPU(struct cpuinfo_x86, cpu_
+ #define current_cpu_data	boot_cpu_data
+ #endif
+ 
++extern const struct seq_operations cpuinfo_op;
++
+ static inline int hlt_works(int cpu)
+ {
+ #ifdef CONFIG_X86_32
+@@ -153,6 +156,8 @@ static inline int hlt_works(int cpu)
+ 
+ extern void cpu_detect(struct cpuinfo_x86 *c);
+ 
++extern struct pt_regs *idle_regs(struct pt_regs *);
++
+ extern void early_cpu_init(void);
+ extern void identify_boot_cpu(void);
+ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+@@ -161,11 +166,8 @@ extern void init_scattered_cpuid_feature
+ extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+ extern unsigned short num_cache_leaves;
+ 
+-#if defined(CONFIG_X86_HT) || defined(CONFIG_X86_64)
++extern void detect_extended_topology(struct cpuinfo_x86 *c);
+ extern void detect_ht(struct cpuinfo_x86 *c);
+-#else
+-static inline void detect_ht(struct cpuinfo_x86 *c) {}
+-#endif
+ 
+ static inline void xen_cpuid(unsigned int *eax, unsigned int *ebx,
+ 			     unsigned int *ecx, unsigned int *edx)
+@@ -327,7 +329,12 @@ struct i387_fxsave_struct {
+ 	/* 16*16 bytes for each XMM-reg = 256 bytes:			*/
+ 	u32			xmm_space[64];
+ 
+-	u32			padding[24];
++	u32			padding[12];
++
++	union {
++		u32		padding1[12];
++		u32		sw_reserved[12];
++	};
+ 
+ } __attribute__((aligned(16)));
+ 
+@@ -351,10 +358,23 @@ struct i387_soft_struct {
+ 	u32			entry_eip;
+ };
+ 
++struct xsave_hdr_struct {
++	u64 xstate_bv;
++	u64 reserved1[2];
++	u64 reserved2[5];
++} __attribute__((packed));
++
++struct xsave_struct {
++	struct i387_fxsave_struct i387;
++	struct xsave_hdr_struct xsave_hdr;
++	/* new processor state extensions will go here */
++} __attribute__ ((packed, aligned (64)));
++
+ union thread_xstate {
+ 	struct i387_fsave_struct	fsave;
+ 	struct i387_fxsave_struct	fxsave;
+ 	struct i387_soft_struct		soft;
++	struct xsave_struct		xsave;
+ };
+ 
+ #if defined(CONFIG_X86_64) && !defined(CONFIG_X86_NO_TSS)
+@@ -413,9 +433,14 @@ struct thread_struct {
+ 	unsigned		io_bitmap_max;
+ /* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
+ 	unsigned long	debugctlmsr;
+-/* Debug Store - if not 0 points to a DS Save Area configuration;
+- *               goes into MSR_IA32_DS_AREA */
+-	unsigned long	ds_area_msr;
++#ifdef CONFIG_X86_DS
++/* Debug Store context; see include/asm-x86/ds.h; goes into MSR_IA32_DS_AREA */
++	struct ds_context	*ds_ctx;
++#endif /* CONFIG_X86_DS */
++#ifdef CONFIG_X86_PTRACE_BTS
++/* the signal to send on a bts buffer overflow */
++	unsigned int	bts_ovfl_signal;
++#endif /* CONFIG_X86_PTRACE_BTS */
+ };
+ 
+ static inline unsigned long xen_get_debugreg(int regno)
+@@ -503,41 +528,6 @@ static inline void clear_in_cr4(unsigned
+ 	write_cr4(cr4);
+ }
+ 
+-struct microcode_header {
+-	unsigned int		hdrver;
+-	unsigned int		rev;
+-	unsigned int		date;
+-	unsigned int		sig;
+-	unsigned int		cksum;
+-	unsigned int		ldrver;
+-	unsigned int		pf;
+-	unsigned int		datasize;
+-	unsigned int		totalsize;
+-	unsigned int		reserved[3];
+-};
+-
+-struct microcode {
+-	struct microcode_header	hdr;
+-	unsigned int		bits[0];
+-};
+-
+-typedef struct microcode	microcode_t;
+-typedef struct microcode_header	microcode_header_t;
+-
+-/* microcode format is extended from prescott processors */
+-struct extended_signature {
+-	unsigned int		sig;
+-	unsigned int		pf;
+-	unsigned int		cksum;
+-};
+-
+-struct extended_sigtable {
+-	unsigned int		count;
+-	unsigned int		cksum;
+-	unsigned int		reserved[3];
+-	struct extended_signature sigs[0];
+-};
+-
+ typedef struct {
+ 	unsigned long		seg;
+ } mm_segment_t;
+@@ -887,4 +877,4 @@ extern void start_thread(struct pt_regs 
+ extern int get_tsc_mode(unsigned long adr);
+ extern int set_tsc_mode(unsigned int val);
+ 
+-#endif
++#endif /* _ASM_X86_PROCESSOR_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:24.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-20 11:14:43.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_X86_SMP_H_
+-#define _ASM_X86_SMP_H_
++#ifndef _ASM_X86_SMP_H
++#define _ASM_X86_SMP_H
+ #ifndef __ASSEMBLY__
+ #include <linux/cpumask.h>
+ #include <linux/init.h>
+@@ -34,6 +34,9 @@ extern cpumask_t cpu_initialized;
+ DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+ DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+ DECLARE_PER_CPU(u16, cpu_llc_id);
++#ifdef CONFIG_X86_32
++DECLARE_PER_CPU(int, cpu_number);
++#endif
+ 
+ DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+ DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+@@ -51,12 +54,16 @@ extern struct {
+ struct smp_ops {
+ 	void (*smp_prepare_boot_cpu)(void);
+ 	void (*smp_prepare_cpus)(unsigned max_cpus);
+-	int (*cpu_up)(unsigned cpu);
+ 	void (*smp_cpus_done)(unsigned max_cpus);
+ 
+ 	void (*smp_send_stop)(void);
+ 	void (*smp_send_reschedule)(int cpu);
+ 
++	int (*cpu_up)(unsigned cpu);
++	int (*cpu_disable)(void);
++	void (*cpu_die)(unsigned int cpu);
++	void (*play_dead)(void);
++
+ 	void (*send_call_func_ipi)(cpumask_t mask);
+ 	void (*send_call_func_single_ipi)(int cpu);
+ };
+@@ -91,6 +98,21 @@ static inline int __cpu_up(unsigned int 
+ 	return smp_ops.cpu_up(cpu);
+ }
+ 
++static inline int __cpu_disable(void)
++{
++	return smp_ops.cpu_disable();
++}
++
++static inline void __cpu_die(unsigned int cpu)
++{
++	smp_ops.cpu_die(cpu);
++}
++
++static inline void play_dead(void)
++{
++	smp_ops.play_dead();
++}
++
+ static inline void smp_send_reschedule(int cpu)
+ {
+ 	smp_ops.smp_send_reschedule(cpu);
+@@ -106,13 +128,20 @@ static inline void arch_send_call_functi
+ 	smp_ops.send_call_func_ipi(mask);
+ }
+ 
++void cpu_disable_common(void);
+ void native_smp_prepare_boot_cpu(void);
+ void native_smp_prepare_cpus(unsigned int max_cpus);
+ void native_smp_cpus_done(unsigned int max_cpus);
+ int native_cpu_up(unsigned int cpunum);
++int native_cpu_disable(void);
++void native_cpu_die(unsigned int cpu);
++void native_play_dead(void);
++void play_dead_common(void);
+ 
+ #else /* CONFIG_XEN */
+ 
++extern int __cpu_disable(void);
++extern void __cpu_die(unsigned int cpu);
+ void xen_smp_send_stop(void);
+ void xen_smp_send_reschedule(int cpu);
+ void xen_send_call_func_ipi(cpumask_t mask);
+@@ -123,10 +152,11 @@ void xen_send_call_func_single_ipi(int c
+ #define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
+ #define arch_send_call_function_ipi		xen_send_call_func_ipi
+ 
++void play_dead(void);
++
+ #endif /* CONFIG_XEN */
+ 
+-extern int __cpu_disable(void);
+-extern void __cpu_die(unsigned int cpu);
++extern void prefill_possible_map(void);
+ 
+ void smp_store_cpu_info(int id);
+ #define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+@@ -136,15 +166,11 @@ static inline int num_booting_cpus(void)
+ {
+ 	return cpus_weight(cpu_callout_map);
+ }
+-#endif /* CONFIG_SMP */
+-
+-#if defined(CONFIG_SMP) && (defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_XEN))
+-extern void prefill_possible_map(void);
+ #else
+ static inline void prefill_possible_map(void)
+ {
+ }
+-#endif
++#endif /* CONFIG_SMP */
+ 
+ extern unsigned disabled_cpus __cpuinitdata;
+ 
+@@ -154,7 +180,6 @@ extern unsigned disabled_cpus __cpuinitd
+  * from the initial startup. We map APIC_BASE very early in page_setup(),
+  * so this is correct in the x86 case.
+  */
+-DECLARE_PER_CPU(int, cpu_number);
+ #define raw_smp_processor_id() (x86_read_percpu(cpu_number))
+ #define safe_smp_processor_id() smp_processor_id()
+ 
+@@ -177,30 +202,33 @@ DECLARE_PER_CPU(int, cpu_number);
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 
++#ifndef CONFIG_X86_64
+ static inline int logical_smp_processor_id(void)
+ {
+ 	/* we don't want to mark this access volatile - bad code generation */
+ 	return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
+ }
+ 
+-#ifndef CONFIG_X86_64
++#include <mach_apicdef.h>
+ static inline unsigned int read_apic_id(void)
+ {
+-	return *(u32 *)(APIC_BASE + APIC_ID);
++	unsigned int reg;
++
++	reg = *(u32 *)(APIC_BASE + APIC_ID);
++
++	return GET_APIC_ID(reg);
+ }
+-#else
+-extern unsigned int read_apic_id(void);
+ #endif
+ 
+ 
+-# ifdef APIC_DEFINITION
++# if defined(APIC_DEFINITION) || defined(CONFIG_X86_64)
+ extern int hard_smp_processor_id(void);
+ # else
+-#  include <mach_apicdef.h>
++#include <mach_apicdef.h>
+ static inline int hard_smp_processor_id(void)
+ {
+ 	/* we don't want to mark this access volatile - bad code generation */
+-	return GET_APIC_ID(read_apic_id());
++	return read_apic_id();
+ }
+ # endif /* APIC_DEFINITION */
+ 
+@@ -212,9 +240,11 @@ static inline int hard_smp_processor_id(
+ 
+ #endif /* CONFIG_X86_LOCAL_APIC */
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+-extern void cpu_uninit(void);
++#ifdef CONFIG_X86_HAS_BOOT_CPU_ID
++extern unsigned char boot_cpu_id;
++#else
++#define boot_cpu_id	0
+ #endif
+ 
+ #endif /* __ASSEMBLY__ */
+-#endif
++#endif /* _ASM_X86_SMP_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock.h	2009-11-17 15:30:35.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _X86_SPINLOCK_H_
+-#define _X86_SPINLOCK_H_
++#ifndef _ASM_X86_SPINLOCK_H
++#define _ASM_X86_SPINLOCK_H
+ 
+ #include <asm/atomic.h>
+ #include <asm/rwlock.h>
+@@ -448,4 +448,4 @@ static inline void __raw_write_unlock(ra
+ #define _raw_read_relax(lock)	cpu_relax()
+ #define _raw_write_relax(lock)	cpu_relax()
+ 
+-#endif
++#endif /* _ASM_X86_SPINLOCK_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:47:41.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:48:59.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __ASM_SPINLOCK_TYPES_H
+-#define __ASM_SPINLOCK_TYPES_H
++#ifndef _ASM_X86_SPINLOCK_TYPES_H
++#define _ASM_X86_SPINLOCK_TYPES_H
+ 
+ #ifndef __LINUX_SPINLOCK_TYPES_H
+ # error "please don't include this file directly"
+@@ -36,4 +36,4 @@ typedef struct {
+ 
+ #define __RAW_RW_LOCK_UNLOCKED		{ RW_LOCK_BIAS }
+ 
+-#endif
++#endif /* _ASM_X86_SPINLOCK_TYPES_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_X86_SYSTEM_H_
+-#define _ASM_X86_SYSTEM_H_
++#ifndef _ASM_X86_SYSTEM_H
++#define _ASM_X86_SYSTEM_H
+ 
+ #include <asm/asm.h>
+ #include <asm/segment.h>
+@@ -65,7 +65,10 @@ do {									\
+ 		       							\
+ 		       /* regparm parameters for __switch_to(): */	\
+ 		       [prev]     "a" (prev),				\
+-		       [next]     "d" (next));				\
++		       [next]     "d" (next)				\
++									\
++		     : /* reloaded segment registers */			\
++			"memory");					\
+ } while (0)
+ 
+ /*
+@@ -403,4 +406,4 @@ static inline void rdtsc_barrier(void)
+ 	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+ }
+ 
+-#endif
++#endif /* _ASM_X86_SYSTEM_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef __ASM_SYSTEM_H
+-#define __ASM_SYSTEM_H
++#ifndef _ASM_X86_SYSTEM_64_H
++#define _ASM_X86_SYSTEM_64_H
+ 
+ #include <asm/segment.h>
+ #include <asm/cmpxchg.h>
+@@ -17,4 +17,4 @@ static inline void write_cr8(unsigned lo
+ 
+ #include <linux/irqflags.h>
+ 
+-#endif
++#endif /* _ASM_X86_SYSTEM_64_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:47.000000000 +0100
+@@ -63,6 +63,10 @@ static inline void flush_tlb_range(struc
+ 		__flush_tlb();
+ }
+ 
++static inline void reset_lazy_tlbstate(void)
++{
++}
++
+ #else  /* SMP */
+ 
+ #include <asm/smp.h>
+@@ -92,6 +96,12 @@ struct tlb_state {
+ 	char __cacheline_padding[L1_CACHE_BYTES-8];
+ };
+ DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
++
++void reset_lazy_tlbstate(void);
++#else
++static inline void reset_lazy_tlbstate(void)
++{
++}
+ #endif
+ 
+ #endif	/* SMP */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/vga.h	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/vga.h	2009-11-06 10:51:47.000000000 +0100
+@@ -4,8 +4,8 @@
+  *	(c) 1998 Martin Mares <mj@ucw.cz>
+  */
+ 
+-#ifndef _LINUX_ASM_VGA_H_
+-#define _LINUX_ASM_VGA_H_
++#ifndef _ASM_X86_VGA_H
++#define _ASM_X86_VGA_H
+ 
+ /*
+  *	On the PC, we can just recalculate addresses and then
+@@ -17,4 +17,4 @@
+ #define vga_readb(x) (*(x))
+ #define vga_writeb(x, y) (*(y) = (x))
+ 
+-#endif
++#endif /* _ASM_X86_VGA_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/xor.h	2009-11-06 10:51:17.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+ #ifdef CONFIG_X86_32
+-# include "../../xor_32.h"
++# include "../../asm/xor_32.h"
+ #else
+ # include "xor_64.h"
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/xor_64.h	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor_64.h	2009-11-06 10:51:47.000000000 +0100
+@@ -1,5 +1,5 @@
+-#ifndef ASM_X86__XOR_64_H
+-#define ASM_X86__XOR_64_H
++#ifndef _ASM_X86_XOR_64_H
++#define _ASM_X86_XOR_64_H
+ 
+ /*
+  * x86-64 changes / gcc fixes from Andi Kleen.
+@@ -334,4 +334,4 @@ do {						\
+    deals with a load to a line that is being prefetched.  */
+ #define XOR_SELECT_TEMPLATE(FASTEST) (&xor_block_sse)
+ 
+-#endif /* ASM_X86__XOR_64_H */
++#endif /* _ASM_X86_XOR_64_H */
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:51:47.000000000 +0100
+@@ -138,7 +138,7 @@ ifeq ($(CONFIG_X86_64),y)
+ 	time_64-$(CONFIG_XEN)		+= time_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
+-	i8259.o irqinit_$(BITS).o pci-swiotlb_64.o reboot.o smpboot.o \
+-	tlb_$(BITS).o tsc.o tsc_sync.o vsmp_64.o
++disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o genx2apic_%.o \
++	hpet.o i8253.o i8259.o irqinit_$(BITS).o pci-swiotlb_64.o reboot.o \
++	smpboot.o tlb_$(BITS).o tsc.o tsc_sync.o uv_%.o vsmp_64.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -10,6 +10,7 @@
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
+ #include <asm/segment.h>
++#include <asm/desc.h>
+ 
+ #include "realmode/wakeup.h"
+ #include "sleep.h"
+@@ -22,7 +23,7 @@ unsigned long acpi_realmode_flags;
+ static unsigned long acpi_realmode;
+ 
+ #if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
+-static char temp_stack[10240];
++static char temp_stack[4096];
+ #endif
+ #endif
+ 
+@@ -100,7 +101,9 @@ int acpi_save_state_mem(void)
+ #else /* CONFIG_64BIT */
+ 	header->trampoline_segment = setup_trampoline() >> 4;
+ #ifdef CONFIG_SMP
+-	stack_start.sp = temp_stack + 4096;
++	stack_start.sp = temp_stack + sizeof(temp_stack);
++	early_gdt_descr.address =
++			(unsigned long)get_cpu_gdt_table(smp_processor_id());
+ #endif
+ 	initial_code = (unsigned long)wakeup_long64;
+ 	saved_magic = 0x123456789abcdef0;
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic/apic-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,61 @@
++/*
++ *	Local APIC handling stubs
++ */
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++
++#include <asm/smp.h>
++#include <asm/proto.h>
++#include <asm/apic.h>
++
++/*
++ * Debug level, exported for io_apic.c
++ */
++unsigned int apic_verbosity;
++
++/* Have we found an MP table */
++int smp_found_config;
++
++static int __init apic_set_verbosity(char *arg)
++{
++	if (!arg)  {
++#ifdef CONFIG_X86_64
++		skip_ioapic_setup = 0;
++		return 0;
++#endif
++		return -EINVAL;
++	}
++
++	if (strcmp("debug", arg) == 0)
++		apic_verbosity = APIC_DEBUG;
++	else if (strcmp("verbose", arg) == 0)
++		apic_verbosity = APIC_VERBOSE;
++	else {
++		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
++			" use apic=verbose or apic=debug\n", arg);
++		return -EINVAL;
++	}
++
++	return 0;
++}
++early_param("apic", apic_set_verbosity);
++
++int setup_profiling_timer(unsigned int multiplier)
++{
++	return -EINVAL;
++}
++
++int __init APIC_init_uniprocessor(void)
++{
++#ifdef CONFIG_X86_IO_APIC
++	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
++		setup_IO_APIC();
++# ifdef CONFIG_X86_64
++	else
++		nr_ioapics = 0;
++# endif
++#endif
++
++	return 0;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,101 +0,0 @@
+-/*
+- *	Local APIC handling, local APIC timers
+- *
+- *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+- *					thanks to Eric Gilmore
+- *					and Rolf G. Tews
+- *					for testing these extensively.
+- *	Maciej W. Rozycki	:	Various updates and fixes.
+- *	Mikael Pettersson	:	Power Management for UP-APIC.
+- *	Pavel Machek and
+- *	Mikael Pettersson	:	PM converted to driver model.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/interrupt.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/sysdev.h>
+-#include <linux/cpu.h>
+-#include <linux/clockchips.h>
+-#include <linux/acpi_pmtmr.h>
+-#include <linux/module.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/desc.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/hpet.h>
+-#include <asm/i8253.h>
+-#include <asm/nmi.h>
+-
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
+-#include <mach_ipi.h>
+-
+-#include "io_ports.h"
+-
+-#ifndef CONFIG_XEN
+-/*
+- * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
+- * IPIs in place of local APIC timers
+- */
+-static cpumask_t timer_bcast_ipi;
+-#endif
+-
+-/*
+- * Knob to control our willingness to enable the local APIC.
+- */
+-
+-/*
+- * Debug level, exported for io_apic.c
+- */
+-unsigned int apic_verbosity;
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-#ifndef CONFIG_XEN
+-static int modern_apic(void)
+-{
+-	/* AMD systems use old APIC versions, so check the CPU */
+-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+-	    boot_cpu_data.x86 >= 0xf)
+-		return 1;
+-	return lapic_get_version() >= 0x14;
+-}
+-#endif /* !CONFIG_XEN */
+-
+-int get_physical_broadcast(void)
+-{
+-        return 0xff;
+-}
+-
+-int setup_profiling_timer(unsigned int multiplier)
+-{
+-	return -EINVAL;
+-}
+-
+-/*
+- * This initializes the IO-APIC and APIC hardware if this is
+- * a UP kernel.
+- */
+-int __init APIC_init_uniprocessor(void)
+-{
+-#ifdef CONFIG_X86_IO_APIC
+-	if (smp_found_config)
+-		if (!skip_ioapic_setup && nr_ioapics)
+-			setup_IO_APIC();
+-#endif
+-
+-	return 0;
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,188 +0,0 @@
+-/*
+- *	Local APIC handling, local APIC timers
+- *
+- *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+- *					thanks to Eric Gilmore
+- *					and Rolf G. Tews
+- *					for testing these extensively.
+- *	Maciej W. Rozycki	:	Various updates and fixes.
+- *	Mikael Pettersson	:	Power Management for UP-APIC.
+- *	Pavel Machek and
+- *	Mikael Pettersson	:	PM converted to driver model.
+- */
+-
+-#include <linux/init.h>
+-
+-#include <linux/mm.h>
+-#include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/interrupt.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/kernel_stat.h>
+-#include <linux/sysdev.h>
+-#include <linux/module.h>
+-
+-#include <asm/atomic.h>
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-#include <asm/desc.h>
+-#include <asm/arch_hooks.h>
+-#include <asm/hpet.h>
+-#include <asm/idle.h>
+-
+-int disable_apic;
+-
+-/*
+- * Debug level, exported for io_apic.c
+- */
+-unsigned int apic_verbosity;
+-
+-/* Have we found an MP table */
+-int smp_found_config;
+-
+-/*
+- * The guts of the apic timer interrupt
+- */
+-static void local_apic_timer_interrupt(void)
+-{
+-#ifndef CONFIG_XEN
+-	int cpu = smp_processor_id();
+-	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+-
+-	/*
+-	 * Normally we should not be here till LAPIC has been initialized but
+-	 * in some cases like kdump, its possible that there is a pending LAPIC
+-	 * timer interrupt from previous kernel's context and is delivered in
+-	 * new kernel the moment interrupts are enabled.
+-	 *
+-	 * Interrupts are enabled early and LAPIC is setup much later, hence
+-	 * its possible that when we get here evt->event_handler is NULL.
+-	 * Check for event_handler being NULL and discard the interrupt as
+-	 * spurious.
+-	 */
+-	if (!evt->event_handler) {
+-		printk(KERN_WARNING
+-		       "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
+-		/* Switch it off */
+-		lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
+-		return;
+-	}
+-#endif
+-
+-	/*
+-	 * the NMI deadlock-detector uses this.
+-	 */
+-	add_pda(apic_timer_irqs, 1);
+-
+-#ifndef CONFIG_XEN
+-	evt->event_handler(evt);
+-#endif
+-}
+-
+-/*
+- * Local APIC timer interrupt. This is the most natural way for doing
+- * local interrupts, but local timer interrupts can be emulated by
+- * broadcast interrupts too. [in case the hw doesn't support APIC timers]
+- *
+- * [ if a single-CPU system runs an SMP kernel then we call the local
+- *   interrupt as well. Thus we cannot inline the local irq ... ]
+- */
+-void smp_apic_timer_interrupt(struct pt_regs *regs)
+-{
+-	struct pt_regs *old_regs = set_irq_regs(regs);
+-
+-	/*
+-	 * NOTE! We'd better ACK the irq immediately,
+-	 * because timer handling can be slow.
+-	 */
+-	ack_APIC_irq();
+-	/*
+-	 * update_process_times() expects us to have done irq_enter().
+-	 * Besides, if we don't timer interrupts ignore the global
+-	 * interrupt lock, which is the WrongThing (tm) to do.
+-	 */
+-	exit_idle();
+-	irq_enter();
+-	local_apic_timer_interrupt();
+-	irq_exit();
+-	set_irq_regs(old_regs);
+-}
+-
+-int setup_profiling_timer(unsigned int multiplier)
+-{
+-	return -EINVAL;
+-}
+-
+-/*
+- * This initializes the IO-APIC and APIC hardware if this is
+- * a UP kernel.
+- */
+-int __init APIC_init_uniprocessor(void)
+-{
+-#ifdef CONFIG_X86_IO_APIC
+-	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
+-		setup_IO_APIC();
+-#endif
+-
+-	return 1;
+-}
+-
+-/*
+- * Local APIC interrupts
+- */
+-
+-/*
+- * This interrupt should _never_ happen with our APIC/SMP architecture
+- */
+-asmlinkage void smp_spurious_interrupt(void)
+-{
+-	unsigned int v;
+-	exit_idle();
+-	irq_enter();
+-	/*
+-	 * Check if this really is a spurious interrupt and ACK it
+-	 * if it is a vectored one.  Just in case...
+-	 * Spurious interrupts should not be ACKed.
+-	 */
+-	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
+-	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+-		ack_APIC_irq();
+-
+-	add_pda(irq_spurious_count, 1);
+-	irq_exit();
+-}
+-
+-/*
+- * This interrupt should never happen with our APIC/SMP architecture
+- */
+-asmlinkage void smp_error_interrupt(void)
+-{
+-	unsigned int v, v1;
+-
+-	exit_idle();
+-	irq_enter();
+-	/* First tickle the hardware, only then report what went on. -- REW */
+-	v = apic_read(APIC_ESR);
+-	apic_write(APIC_ESR, 0);
+-	v1 = apic_read(APIC_ESR);
+-	ack_APIC_irq();
+-	atomic_inc(&irq_err_count);
+-
+-	/* Here is what the APIC error bits mean:
+-	   0: Send CS error
+-	   1: Receive CS error
+-	   2: Send accept error
+-	   3: Receive accept error
+-	   4: Reserved
+-	   5: Send illegal vector
+-	   6: Received illegal vector
+-	   7: Illegal register address
+-	*/
+-	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
+-		smp_processor_id(), v , v1);
+-	irq_exit();
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/addon_cpuid_features.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/addon_cpuid_features.c	2009-11-06 10:51:47.000000000 +0100
+@@ -70,7 +70,7 @@ void __cpuinit init_scattered_cpuid_feat
+  */
+ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
+ {
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ 	unsigned int eax, ebx, ecx, edx, sub_index;
+ 	unsigned int ht_mask_width, core_plus_mask_width;
+ 	unsigned int core_select_mask, core_level_siblings;
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -1,33 +1,73 @@
+ #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 <linux/kgdb.h>
++#include <linux/topology.h>
+ #include <linux/delay.h>
+ #include <linux/smp.h>
+-#include <linux/module.h>
+ #include <linux/percpu.h>
+-#include <linux/bootmem.h>
+-#include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+ #include <asm/io.h>
++#include <asm/linkage.h>
+ #include <asm/mmu_context.h>
+ #include <asm/mtrr.h>
+ #include <asm/mce.h>
+ #include <asm/pat.h>
+ #include <asm/asm.h>
++#include <asm/numa.h>
++#include <asm/smp.h>
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #include <asm/mpspec.h>
+ #include <asm/apic.h>
+ #include <mach_apic.h>
+-#else
++#include <asm/genapic.h>
++#elif defined(CONFIG_X86_64_XEN)
++#include <mach_apic.h>
++#endif
++
++#include <asm/pda.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/desc.h>
++#include <asm/atomic.h>
++#include <asm/proto.h>
++#include <asm/sections.h>
++#include <asm/setup.h>
++
+ #ifdef CONFIG_XEN
++#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_LOCAL_APIC)
+ #define phys_pkg_id(a,b) a
+ #endif
+-#endif
+ #include <asm/hypervisor.h>
++#include <xen/interface/callback.h>
++#endif
+ 
+ #include "cpu.h"
+ 
++static struct cpu_dev *this_cpu __cpuinitdata;
++
++#ifdef CONFIG_X86_64
++/* We need valid kernel segments for data and code in long mode too
++ * IRET will check the segment types  kkeil 2000/10/28
++ * Also sysret mandates a special GDT layout
++ */
++/* The TLS descriptors are currently at a different place compared to i386.
++   Hopefully nobody expects them at a fixed place (Wine?) */
+ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
++	[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
++	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
++	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
++	[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
++	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
++	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
++} };
++#else
++DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+ 	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
+ 	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
+ 	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
+@@ -63,17 +103,168 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page
+ #endif
+ 	[GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
+ } };
++#endif
+ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+ 
+-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+-
++#ifdef CONFIG_X86_32
+ static int cachesize_override __cpuinitdata = -1;
+ static int disable_x86_serial_nr __cpuinitdata = 1;
+ 
+-struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
++static int __init cachesize_setup(char *str)
++{
++	get_option(&str, &cachesize_override);
++	return 1;
++}
++__setup("cachesize=", cachesize_setup);
++
++static int __init x86_fxsr_setup(char *s)
++{
++	setup_clear_cpu_cap(X86_FEATURE_FXSR);
++	setup_clear_cpu_cap(X86_FEATURE_XMM);
++	return 1;
++}
++__setup("nofxsr", x86_fxsr_setup);
++
++static int __init x86_sep_setup(char *s)
++{
++	setup_clear_cpu_cap(X86_FEATURE_SEP);
++	return 1;
++}
++__setup("nosep", x86_sep_setup);
++
++/* Standard macro to see if a specific flag is changeable */
++static inline int flag_is_changeable_p(u32 flag)
++{
++	u32 f1, f2;
++
++	/*
++	 * Cyrix and IDT cpus allow disabling of CPUID
++	 * so the code below may return different results
++	 * when it is executed before and after enabling
++	 * the CPUID. Add "volatile" to not allow gcc to
++	 * optimize the subsequent calls to this function.
++	 */
++	asm volatile ("pushfl\n\t"
++		      "pushfl\n\t"
++		      "popl %0\n\t"
++		      "movl %0,%1\n\t"
++		      "xorl %2,%0\n\t"
++		      "pushl %0\n\t"
++		      "popfl\n\t"
++		      "pushfl\n\t"
++		      "popl %0\n\t"
++		      "popfl\n\t"
++		      : "=&r" (f1), "=&r" (f2)
++		      : "ir" (flag));
++
++	return ((f1^f2) & flag) != 0;
++}
++
++/* Probe for the CPUID instruction */
++static int __cpuinit have_cpuid_p(void)
++{
++	return flag_is_changeable_p(X86_EFLAGS_ID);
++}
++
++static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
++{
++	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
++		/* Disable processor serial number */
++		unsigned long lo, hi;
++		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
++		lo |= 0x200000;
++		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
++		printk(KERN_NOTICE "CPU serial number disabled.\n");
++		clear_cpu_cap(c, X86_FEATURE_PN);
++
++		/* Disabling the serial number may affect the cpuid level */
++		c->cpuid_level = cpuid_eax(0);
++	}
++}
++
++static int __init x86_serial_nr_setup(char *s)
++{
++	disable_x86_serial_nr = 0;
++	return 1;
++}
++__setup("serialnumber", x86_serial_nr_setup);
++#else
++static inline int flag_is_changeable_p(u32 flag)
++{
++	return 1;
++}
++/* Probe for the CPUID instruction */
++static inline int have_cpuid_p(void)
++{
++	return 1;
++}
++static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
++{
++}
++#endif
++
++/*
++ * Naming convention should be: <Name> [(<Codename>)]
++ * This table only is used unless init_<vendor>() below doesn't set it;
++ * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
++ *
++ */
++
++/* Look up CPU names by table lookup. */
++static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
++{
++	struct cpu_model_info *info;
++
++	if (c->x86_model >= 16)
++		return NULL;	/* Range check */
++
++	if (!this_cpu)
++		return NULL;
++
++	info = this_cpu->c_models;
++
++	while (info && info->family) {
++		if (info->family == c->x86)
++			return info->model_names[c->x86_model];
++		info++;
++	}
++	return NULL;		/* Not found */
++}
++
++__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
++
++/* Current gdt points %fs at the "master" per-cpu area: after this,
++ * it's on the real one. */
++void switch_to_new_gdt(void)
++{
++	struct desc_ptr gdt_descr;
++	unsigned long va, frames[16];
++	int f;
++
++	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
++	gdt_descr.size = GDT_SIZE - 1;
++
++	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_lowmem_page_readonly(
++			(void *)va, XENFEAT_writable_descriptor_tables);
++	}
++	if (HYPERVISOR_set_gdt(frames, (gdt_descr.size + 1) / 8))
++		BUG();
++#ifdef CONFIG_X86_32
++	asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
++#endif
++}
++
++static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+ 
+ static void __cpuinit default_init(struct cpuinfo_x86 *c)
+ {
++#ifdef CONFIG_X86_64
++	display_cacheinfo(c);
++#else
+ 	/* Not much we can do here... */
+ 	/* Check if at least it has cpuid */
+ 	if (c->cpuid_level == -1) {
+@@ -83,28 +274,22 @@ static void __cpuinit default_init(struc
+ 		else if (c->x86 == 3)
+ 			strcpy(c->x86_model_id, "386");
+ 	}
++#endif
+ }
+ 
+ static struct cpu_dev __cpuinitdata default_cpu = {
+ 	.c_init	= default_init,
+ 	.c_vendor = "Unknown",
++	.c_x86_vendor = X86_VENDOR_UNKNOWN,
+ };
+-static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+-
+-static int __init cachesize_setup(char *str)
+-{
+-	get_option(&str, &cachesize_override);
+-	return 1;
+-}
+-__setup("cachesize=", cachesize_setup);
+ 
+-int __cpuinit get_model_name(struct cpuinfo_x86 *c)
++static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
+ {
+ 	unsigned int *v;
+ 	char *p, *q;
+ 
+-	if (cpuid_eax(0x80000000) < 0x80000004)
+-		return 0;
++	if (c->extended_cpuid_level < 0x80000004)
++		return;
+ 
+ 	v = (unsigned int *) c->x86_model_id;
+ 	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+@@ -123,30 +308,34 @@ int __cpuinit get_model_name(struct cpui
+ 	     while (q <= &c->x86_model_id[48])
+ 		  *q++ = '\0';	/* Zero-pad the rest */
+ 	}
+-
+-	return 1;
+ }
+ 
+-
+ void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+ {
+-	unsigned int n, dummy, ecx, edx, l2size;
++	unsigned int n, dummy, ebx, ecx, edx, l2size;
+ 
+-	n = cpuid_eax(0x80000000);
++	n = c->extended_cpuid_level;
+ 
+ 	if (n >= 0x80000005) {
+-		cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
++		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
+ 		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+-			edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size = (ecx>>24)+(edx>>24);
++				edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
++		c->x86_cache_size = (ecx>>24) + (edx>>24);
++#ifdef CONFIG_X86_64
++		/* On K8 L1 TLB is inclusive, so don't count it */
++		c->x86_tlbsize = 0;
++#endif
+ 	}
+ 
+ 	if (n < 0x80000006)	/* Some chips just has a large L1. */
+ 		return;
+ 
+-	ecx = cpuid_ecx(0x80000006);
++	cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
+ 	l2size = ecx >> 16;
+ 
++#ifdef CONFIG_X86_64
++	c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
++#else
+ 	/* do processor-specific cache resizing */
+ 	if (this_cpu->c_size_cache)
+ 		l2size = this_cpu->c_size_cache(c, l2size);
+@@ -157,116 +346,106 @@ void __cpuinit display_cacheinfo(struct 
+ 
+ 	if (l2size == 0)
+ 		return;		/* Again, no L2 cache is possible */
++#endif
+ 
+ 	c->x86_cache_size = l2size;
+ 
+ 	printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+-	       l2size, ecx & 0xFF);
++			l2size, ecx & 0xFF);
+ }
+ 
+-/*
+- * Naming convention should be: <Name> [(<Codename>)]
+- * This table only is used unless init_<vendor>() below doesn't set it;
+- * in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
+- *
+- */
+-
+-/* Look up CPU names by table lookup. */
+-static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c)
++void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+ {
+-	struct cpu_model_info *info;
++#ifdef CONFIG_X86_HT
++	u32 eax, ebx, ecx, edx;
++	int index_msb, core_bits;
+ 
+-	if (c->x86_model >= 16)
+-		return NULL;	/* Range check */
++	if (!cpu_has(c, X86_FEATURE_HT))
++		return;
+ 
+-	if (!this_cpu)
+-		return NULL;
++	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
++		goto out;
+ 
+-	info = this_cpu->c_models;
++	if (cpu_has(c, X86_FEATURE_XTOPOLOGY))
++		return;
+ 
+-	while (info && info->family) {
+-		if (info->family == c->x86)
+-			return info->model_names[c->x86_model];
+-		info++;
++	cpuid(1, &eax, &ebx, &ecx, &edx);
++
++	smp_num_siblings = (ebx & 0xff0000) >> 16;
++
++	if (smp_num_siblings == 1) {
++		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
++	} else if (smp_num_siblings > 1) {
++
++		if (smp_num_siblings > NR_CPUS) {
++			printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
++					smp_num_siblings);
++			smp_num_siblings = 1;
++			return;
++		}
++
++		index_msb = get_count_order(smp_num_siblings);
++#ifdef CONFIG_X86_64
++		c->phys_proc_id = phys_pkg_id(index_msb);
++#else
++		c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
++#endif
++
++		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
++
++		index_msb = get_count_order(smp_num_siblings);
++
++		core_bits = get_count_order(c->x86_max_cores);
++
++#ifdef CONFIG_X86_64
++		c->cpu_core_id = phys_pkg_id(index_msb) &
++					       ((1 << core_bits) - 1);
++#else
++		c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
++					       ((1 << core_bits) - 1);
++#endif
+ 	}
+-	return NULL;		/* Not found */
+-}
+ 
++out:
++	if ((c->x86_max_cores * smp_num_siblings) > 1) {
++		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
++		       c->phys_proc_id);
++		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
++		       c->cpu_core_id);
++	}
++#endif
++}
+ 
+-static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ 	char *v = c->x86_vendor_id;
+ 	int i;
+ 	static int printed;
+ 
+ 	for (i = 0; i < X86_VENDOR_NUM; i++) {
+-		if (cpu_devs[i]) {
+-			if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+-			    (cpu_devs[i]->c_ident[1] &&
+-			     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+-				c->x86_vendor = i;
+-				if (!early)
+-					this_cpu = cpu_devs[i];
+-				return;
+-			}
++		if (!cpu_devs[i])
++			break;
++
++		if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
++		    (cpu_devs[i]->c_ident[1] &&
++		     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
++			this_cpu = cpu_devs[i];
++			c->x86_vendor = this_cpu->c_x86_vendor;
++			return;
+ 		}
+ 	}
++
+ 	if (!printed) {
+ 		printed++;
+-		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
++		printk(KERN_ERR "CPU: vendor_id '%s' unknown, using generic init.\n", v);
+ 		printk(KERN_ERR "CPU: Your system may be unstable.\n");
+ 	}
++
+ 	c->x86_vendor = X86_VENDOR_UNKNOWN;
+ 	this_cpu = &default_cpu;
+ }
+ 
+-
+-static int __init x86_fxsr_setup(char *s)
+-{
+-	setup_clear_cpu_cap(X86_FEATURE_FXSR);
+-	setup_clear_cpu_cap(X86_FEATURE_XMM);
+-	return 1;
+-}
+-__setup("nofxsr", x86_fxsr_setup);
+-
+-
+-static int __init x86_sep_setup(char *s)
+-{
+-	setup_clear_cpu_cap(X86_FEATURE_SEP);
+-	return 1;
+-}
+-__setup("nosep", x86_sep_setup);
+-
+-
+-/* Standard macro to see if a specific flag is changeable */
+-static inline int flag_is_changeable_p(u32 flag)
+-{
+-	u32 f1, f2;
+-
+-	asm("pushfl\n\t"
+-	    "pushfl\n\t"
+-	    "popl %0\n\t"
+-	    "movl %0,%1\n\t"
+-	    "xorl %2,%0\n\t"
+-	    "pushl %0\n\t"
+-	    "popfl\n\t"
+-	    "pushfl\n\t"
+-	    "popl %0\n\t"
+-	    "popfl\n\t"
+-	    : "=&r" (f1), "=&r" (f2)
+-	    : "ir" (flag));
+-
+-	return ((f1^f2) & flag) != 0;
+-}
+-
+-
+-/* Probe for the CPUID instruction */
+-static int __cpuinit have_cpuid_p(void)
+-{
+-	return flag_is_changeable_p(X86_EFLAGS_ID);
+-}
+-
+-void __init cpu_detect(struct cpuinfo_x86 *c)
++void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
+ {
+ 	/* Get vendor name */
+ 	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+@@ -275,50 +454,87 @@ void __init cpu_detect(struct cpuinfo_x8
+ 	      (unsigned int *)&c->x86_vendor_id[4]);
+ 
+ 	c->x86 = 4;
++	/* Intel-defined flags: level 0x00000001 */
+ 	if (c->cpuid_level >= 0x00000001) {
+ 		u32 junk, tfms, cap0, misc;
+ 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+-		c->x86 = (tfms >> 8) & 15;
+-		c->x86_model = (tfms >> 4) & 15;
++		c->x86 = (tfms >> 8) & 0xf;
++		c->x86_model = (tfms >> 4) & 0xf;
++		c->x86_mask = tfms & 0xf;
+ 		if (c->x86 == 0xf)
+ 			c->x86 += (tfms >> 20) & 0xff;
+ 		if (c->x86 >= 0x6)
+-			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		c->x86_mask = tfms & 15;
++			c->x86_model += ((tfms >> 16) & 0xf) << 4;
+ 		if (cap0 & (1<<19)) {
+-			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
+ 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
++			c->x86_cache_alignment = c->x86_clflush_size;
+ 		}
+ 	}
+ }
+-static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
++
++static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+ {
+ 	u32 tfms, xlvl;
+-	unsigned int ebx;
++	u32 ebx;
+ 
+-	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+-	if (have_cpuid_p()) {
+-		/* Intel-defined flags: level 0x00000001 */
+-		if (c->cpuid_level >= 0x00000001) {
+-			u32 capability, excap;
+-			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+-			c->x86_capability[0] = capability;
+-			c->x86_capability[4] = excap;
+-		}
++	/* Intel-defined flags: level 0x00000001 */
++	if (c->cpuid_level >= 0x00000001) {
++		u32 capability, excap;
++		cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
++		c->x86_capability[0] = capability;
++		c->x86_capability[4] = excap;
++	}
+ 
+-		/* AMD-defined flags: level 0x80000001 */
+-		xlvl = cpuid_eax(0x80000000);
+-		if ((xlvl & 0xffff0000) == 0x80000000) {
+-			if (xlvl >= 0x80000001) {
+-				c->x86_capability[1] = cpuid_edx(0x80000001);
+-				c->x86_capability[6] = cpuid_ecx(0x80000001);
+-			}
++	/* AMD-defined flags: level 0x80000001 */
++	xlvl = cpuid_eax(0x80000000);
++	c->extended_cpuid_level = xlvl;
++	if ((xlvl & 0xffff0000) == 0x80000000) {
++		if (xlvl >= 0x80000001) {
++			c->x86_capability[1] = cpuid_edx(0x80000001);
++			c->x86_capability[6] = cpuid_ecx(0x80000001);
+ 		}
++	}
++
++#ifdef CONFIG_X86_64
++	if (c->extended_cpuid_level >= 0x80000008) {
++		u32 eax = cpuid_eax(0x80000008);
+ 
++		c->x86_virt_bits = (eax >> 8) & 0xff;
++		c->x86_phys_bits = eax & 0xff;
+ 	}
++#endif
++
++	if (c->extended_cpuid_level >= 0x80000007)
++		c->x86_power = cpuid_edx(0x80000007);
+ 
+ }
+ 
++static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
++{
++#ifdef CONFIG_X86_32
++	int i;
++
++	/*
++	 * First of all, decide if this is a 486 or higher
++	 * It's a 486 if we can modify the AC flag
++	 */
++	if (flag_is_changeable_p(X86_EFLAGS_AC))
++		c->x86 = 4;
++	else
++		c->x86 = 3;
++
++	for (i = 0; i < X86_VENDOR_NUM; i++)
++		if (cpu_devs[i] && cpu_devs[i]->c_identify) {
++			c->x86_vendor_id[0] = 0;
++			cpu_devs[i]->c_identify(c);
++			if (c->x86_vendor_id[0]) {
++				get_cpu_vendor(c);
++				break;
++			}
++		}
++#endif
++}
++
+ /*
+  * Do minimum CPU detection early.
+  * Fields really needed: vendor, cpuid_level, family, model, mask,
+@@ -328,25 +544,65 @@ static void __cpuinit early_get_cap(stru
+  * WARNING: this function is only called on the BP.  Don't add code here
+  * that is supposed to run on all CPUs.
+  */
+-static void __init early_cpu_detect(void)
++static void __init early_identify_cpu(struct cpuinfo_x86 *c)
+ {
+-	struct cpuinfo_x86 *c = &boot_cpu_data;
+-
+-	c->x86_cache_alignment = 32;
++#ifdef CONFIG_X86_64
++	c->x86_clflush_size = 64;
++#else
+ 	c->x86_clflush_size = 32;
++#endif
++	c->x86_cache_alignment = c->x86_clflush_size;
++
++	memset(&c->x86_capability, 0, sizeof c->x86_capability);
++	c->extended_cpuid_level = 0;
++
++	if (!have_cpuid_p())
++		identify_cpu_without_cpuid(c);
+ 
++	/* cyrix could have cpuid enabled via c_identify()*/
+ 	if (!have_cpuid_p())
+ 		return;
+ 
+ 	cpu_detect(c);
+ 
+-	get_cpu_vendor(c, 1);
++	get_cpu_vendor(c);
++
++	get_cpu_cap(c);
++
++	if (this_cpu->c_early_init)
++		this_cpu->c_early_init(c);
++
++	validate_pat_support(c);
++
++#ifdef CONFIG_SMP
++	c->cpu_index = boot_cpu_id;
++#endif
++}
++
++void __init early_cpu_init(void)
++{
++	struct cpu_dev **cdev;
++	int count = 0;
+ 
+-	early_get_cap(c);
++	printk("KERNEL supported cpus:\n");
++	for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
++		struct cpu_dev *cpudev = *cdev;
++		unsigned int j;
++
++		if (count >= X86_VENDOR_NUM)
++			break;
++		cpu_devs[count] = cpudev;
++		count++;
++
++		for (j = 0; j < 2; j++) {
++			if (!cpudev->c_ident[j])
++				continue;
++			printk("  %s %s\n", cpudev->c_vendor,
++				cpudev->c_ident[j]);
++		}
++	}
+ 
+-	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
+-	    cpu_devs[c->x86_vendor]->c_early_init)
+-		cpu_devs[c->x86_vendor]->c_early_init(c);
++	early_identify_cpu(&boot_cpu_data);
+ }
+ 
+ /*
+@@ -364,88 +620,41 @@ static void __cpuinit detect_nopl(struct
+ 
+ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+ {
+-	u32 tfms, xlvl;
+-	unsigned int ebx;
++	c->extended_cpuid_level = 0;
+ 
+-	if (have_cpuid_p()) {
+-		/* Get vendor name */
+-		cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+-		      (unsigned int *)&c->x86_vendor_id[0],
+-		      (unsigned int *)&c->x86_vendor_id[8],
+-		      (unsigned int *)&c->x86_vendor_id[4]);
+-
+-		get_cpu_vendor(c, 0);
+-		/* Initialize the standard set of capabilities */
+-		/* Note that the vendor-specific code below might override */
+-		/* Intel-defined flags: level 0x00000001 */
+-		if (c->cpuid_level >= 0x00000001) {
+-			u32 capability, excap;
+-			cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+-			c->x86_capability[0] = capability;
+-			c->x86_capability[4] = excap;
+-			c->x86 = (tfms >> 8) & 15;
+-			c->x86_model = (tfms >> 4) & 15;
+-			if (c->x86 == 0xf)
+-				c->x86 += (tfms >> 20) & 0xff;
+-			if (c->x86 >= 0x6)
+-				c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-			c->x86_mask = tfms & 15;
+-			c->initial_apicid = (ebx >> 24) & 0xFF;
+-#ifndef CONFIG_XEN
+-#ifdef CONFIG_X86_HT
+-			c->apicid = phys_pkg_id(c->initial_apicid, 0);
+-			c->phys_proc_id = c->initial_apicid;
+-#else
+-			c->apicid = c->initial_apicid;
+-#endif
+-#endif
+-			if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+-				c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8;
+-		} else {
+-			/* Have CPUID level 0 only - unheard of */
+-			c->x86 = 4;
+-		}
++	if (!have_cpuid_p())
++		identify_cpu_without_cpuid(c);
+ 
+-		/* AMD-defined flags: level 0x80000001 */
+-		xlvl = cpuid_eax(0x80000000);
+-		if ((xlvl & 0xffff0000) == 0x80000000) {
+-			if (xlvl >= 0x80000001) {
+-				c->x86_capability[1] = cpuid_edx(0x80000001);
+-				c->x86_capability[6] = cpuid_ecx(0x80000001);
+-			}
+-			if (xlvl >= 0x80000004)
+-				get_model_name(c); /* Default name */
+-		}
++	/* cyrix could have cpuid enabled via c_identify()*/
++	if (!have_cpuid_p())
++		return;
+ 
+-		init_scattered_cpuid_features(c);
+-		detect_nopl(c);
+-	}
+-}
++	cpu_detect(c);
+ 
+-static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+-{
+-	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr) {
+-		/* Disable processor serial number */
+-		unsigned long lo, hi;
+-		rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+-		lo |= 0x200000;
+-		wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+-		printk(KERN_NOTICE "CPU serial number disabled.\n");
+-		clear_cpu_cap(c, X86_FEATURE_PN);
++	get_cpu_vendor(c);
+ 
+-		/* Disabling the serial number may affect the cpuid level */
+-		c->cpuid_level = cpuid_eax(0);
+-	}
+-}
++	get_cpu_cap(c);
+ 
+-static int __init x86_serial_nr_setup(char *s)
+-{
+-	disable_x86_serial_nr = 0;
+-	return 1;
+-}
+-__setup("serialnumber", x86_serial_nr_setup);
++	if (c->cpuid_level >= 0x00000001) {
++		c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++# ifdef CONFIG_X86_HT
++		c->apicid = phys_pkg_id(c->initial_apicid, 0);
++# else
++		c->apicid = c->initial_apicid;
++# endif
++#endif
++
++#ifdef CONFIG_X86_HT
++		c->phys_proc_id = c->initial_apicid;
++#endif
++	}
+ 
++	get_model_name(c); /* Default name */
+ 
++	init_scattered_cpuid_features(c);
++	detect_nopl(c);
++}
+ 
+ /*
+  * This does the hard work of actually picking apart the CPU stuff...
+@@ -457,32 +666,31 @@ static void __cpuinit identify_cpu(struc
+ 	c->loops_per_jiffy = loops_per_jiffy;
+ 	c->x86_cache_size = -1;
+ 	c->x86_vendor = X86_VENDOR_UNKNOWN;
+-	c->cpuid_level = -1;	/* CPUID not detected */
+ 	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+ 	c->x86_vendor_id[0] = '\0'; /* Unset */
+ 	c->x86_model_id[0] = '\0';  /* Unset */
+ 	c->x86_max_cores = 1;
++	c->x86_coreid_bits = 0;
++#ifdef CONFIG_X86_64
++	c->x86_clflush_size = 64;
++#else
++	c->cpuid_level = -1;	/* CPUID not detected */
+ 	c->x86_clflush_size = 32;
++#endif
++	c->x86_cache_alignment = c->x86_clflush_size;
+ 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ 	if (boot_cpu_has(X86_FEATURE_SYSCALL32))
+ 		set_cpu_cap(c, X86_FEATURE_SYSCALL32);
+ 
+-	if (!have_cpuid_p()) {
+-		/*
+-		 * First of all, decide if this is a 486 or higher
+-		 * It's a 486 if we can modify the AC flag
+-		 */
+-		if (flag_is_changeable_p(X86_EFLAGS_AC))
+-			c->x86 = 4;
+-		else
+-			c->x86 = 3;
+-	}
+-
+ 	generic_identify(c);
+ 
+ 	if (this_cpu->c_identify)
+ 		this_cpu->c_identify(c);
+ 
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++	c->apicid = phys_pkg_id(0);
++#endif
++
+ 	/*
+ 	 * Vendor-specific initialization.  In this section we
+ 	 * canonicalize the feature flags, meaning if there are
+@@ -516,6 +724,10 @@ static void __cpuinit identify_cpu(struc
+ 				c->x86, c->x86_model);
+ 	}
+ 
++#ifdef CONFIG_X86_64
++	detect_ht(c);
++#endif
++
+ 	/*
+ 	 * On SMP, boot_cpu_data holds the common feature set between
+ 	 * all CPUs; so make sure that we indicate which features are
+@@ -524,7 +736,7 @@ static void __cpuinit identify_cpu(struc
+ 	 */
+ 	if (c != &boot_cpu_data) {
+ 		/* AND the already accumulated flags with these */
+-		for (i = 0 ; i < NCAPINTS ; i++)
++		for (i = 0; i < NCAPINTS; i++)
+ 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ 	}
+ 
+@@ -532,72 +744,91 @@ static void __cpuinit identify_cpu(struc
+ 	for (i = 0; i < NCAPINTS; i++)
+ 		c->x86_capability[i] &= ~cleared_cpu_caps[i];
+ 
++#ifdef CONFIG_X86_MCE
+ 	/* Init Machine Check Exception if available. */
+ 	mcheck_init(c);
++#endif
+ 
+ 	select_idle_routine(c);
++
++#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
++	numa_add_cpu(smp_processor_id());
++#endif
++}
++
++#ifdef CONFIG_X86_64
++static void vgetcpu_set_mode(void)
++{
++	if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
++		vgetcpu_mode = VGETCPU_RDTSCP;
++	else
++		vgetcpu_mode = VGETCPU_LSL;
+ }
++#endif
+ 
+ void __init identify_boot_cpu(void)
+ {
+ 	identify_cpu(&boot_cpu_data);
++#ifdef CONFIG_X86_32
+ 	sysenter_setup();
+ 	enable_sep_cpu();
++#else
++	vgetcpu_set_mode();
++#endif
+ }
+ 
+ void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+ {
+ 	BUG_ON(c == &boot_cpu_data);
+ 	identify_cpu(c);
++#ifdef CONFIG_X86_32
+ 	enable_sep_cpu();
++#endif
+ 	mtrr_ap_init();
+ }
+ 
+-#ifdef CONFIG_X86_HT
+-void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+-{
+-	u32 	eax, ebx, ecx, edx;
+-	int 	index_msb, core_bits;
+-
+-	cpuid(1, &eax, &ebx, &ecx, &edx);
+-
+-	if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
+-		return;
++struct msr_range {
++	unsigned min;
++	unsigned max;
++};
+ 
+-	smp_num_siblings = (ebx & 0xff0000) >> 16;
++static struct msr_range msr_range_array[] __cpuinitdata = {
++	{ 0x00000000, 0x00000418},
++	{ 0xc0000000, 0xc000040b},
++	{ 0xc0010000, 0xc0010142},
++	{ 0xc0011000, 0xc001103b},
++};
+ 
+-	if (smp_num_siblings == 1) {
+-		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1) {
++static void __cpuinit print_cpu_msr(void)
++{
++	unsigned index;
++	u64 val;
++	int i;
++	unsigned index_min, index_max;
+ 
+-		if (smp_num_siblings > NR_CPUS) {
+-			printk(KERN_WARNING "CPU: Unsupported number of the "
+-					"siblings %d", smp_num_siblings);
+-			smp_num_siblings = 1;
+-			return;
++	for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
++		index_min = msr_range_array[i].min;
++		index_max = msr_range_array[i].max;
++		for (index = index_min; index < index_max; index++) {
++			if (rdmsrl_amd_safe(index, &val))
++				continue;
++			printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
+ 		}
++	}
++}
+ 
+-		index_msb = get_count_order(smp_num_siblings);
+-		c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
+-
+-		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+-		       c->phys_proc_id);
+-
+-		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+-
+-		index_msb = get_count_order(smp_num_siblings) ;
+-
+-		core_bits = get_count_order(c->x86_max_cores);
++static int show_msr __cpuinitdata;
++static __init int setup_show_msr(char *arg)
++{
++	int num;
+ 
+-		c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+-					       ((1 << core_bits) - 1);
++	get_option(&arg, &num);
+ 
+-		if (c->x86_max_cores > 1)
+-			printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+-			       c->cpu_core_id);
+-	}
++	if (num > 0)
++		show_msr = num;
++	return 1;
+ }
+-#endif
++__setup("show_msr=", setup_show_msr);
+ 
+ static __init int setup_noclflush(char *arg)
+ {
+@@ -615,18 +846,26 @@ void __cpuinit print_cpu_info(struct cpu
+ 	else if (c->cpuid_level >= 0)
+ 		vendor = c->x86_vendor_id;
+ 
+-	if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
+-		printk("%s ", vendor);
++	if (vendor && !strstr(c->x86_model_id, vendor))
++		printk(KERN_CONT "%s ", vendor);
+ 
+-	if (!c->x86_model_id[0])
+-		printk("%d86", c->x86);
++	if (c->x86_model_id[0])
++		printk(KERN_CONT "%s", c->x86_model_id);
+ 	else
+-		printk("%s", c->x86_model_id);
++		printk(KERN_CONT "%d86", c->x86);
+ 
+ 	if (c->x86_mask || c->cpuid_level >= 0)
+-		printk(" stepping %02x\n", c->x86_mask);
++		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
+ 	else
+-		printk("\n");
++		printk(KERN_CONT "\n");
++
++#ifdef CONFIG_SMP
++	if (c->cpu_index < show_msr)
++		print_cpu_msr();
++#else
++	if (show_msr)
++		print_cpu_msr();
++#endif
+ }
+ 
+ static __init int setup_disablecpuid(char *arg)
+@@ -642,19 +881,124 @@ __setup("clearcpuid=", setup_disablecpui
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+-void __init early_cpu_init(void)
++#ifdef CONFIG_X86_64
++struct x8664_pda **_cpu_pda __read_mostly;
++EXPORT_SYMBOL(_cpu_pda);
++
++#ifndef CONFIG_X86_NO_IDT
++struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
++#endif
++
++char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
++
++static void __ref switch_pt(int cpu)
++{
++#ifdef CONFIG_XEN
++	if (cpu == 0)
++		xen_init_pt();
++	xen_pt_switch(__pa_symbol(init_level4_pgt));
++	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
++#endif
++}
++
++void __cpuinit pda_init(int cpu)
++{
++	struct x8664_pda *pda = cpu_pda(cpu);
++
++	/* Setup up data that may be needed in __get_free_pages early */
++	loadsegment(fs, 0);
++	loadsegment(gs, 0);
++#ifndef CONFIG_XEN
++	/* Memory clobbers used to order PDA accessed */
++	mb();
++	wrmsrl(MSR_GS_BASE, pda);
++	mb();
++#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) {
++		/* others are initialized in smpboot.c */
++		pda->pcurrent = &init_task;
++		pda->irqstackptr = boot_cpu_stack;
++		pda->irqstackptr += IRQSTACKSIZE - 64;
++	} else {
++		if (!pda->irqstackptr) {
++			pda->irqstackptr = (char *)
++				__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
++			if (!pda->irqstackptr)
++				panic("cannot allocate irqstack for cpu %d",
++				      cpu);
++			pda->irqstackptr += IRQSTACKSIZE - 64;
++		}
++
++		if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
++			pda->nodenumber = cpu_to_node(cpu);
++	}
++
++	switch_pt(cpu);
++}
++
++#ifndef CONFIG_X86_NO_TSS
++char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
++			   DEBUG_STKSZ] __page_aligned_bss;
++#endif
++
++extern asmlinkage void ignore_sysret(void);
++
++void __cpuinit syscall_init(void)
+ {
+-	struct cpu_vendor_dev *cvdev;
++#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);
++	wrmsrl(MSR_CSTAR, ignore_sysret);
++#endif
+ 
+-	for (cvdev = __x86cpuvendor_start ;
+-	     cvdev < __x86cpuvendor_end   ;
+-	     cvdev++)
+-		cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
++#ifdef CONFIG_IA32_EMULATION
++	syscall32_cpu_init();
++#elif defined(CONFIG_XEN)
++	static const struct callback_register __cpuinitconst cstar = {
++		.type = CALLBACKTYPE_syscall32,
++		.address = (unsigned long)ignore_sysret
++	};
+ 
+-	early_cpu_detect();
+-	validate_pat_support(&boot_cpu_data);
++	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
++		printk(KERN_WARNING "Unable to register CSTAR callback\n");
++#endif
++
++#ifndef CONFIG_XEN
++	/* Flags to clear on syscall */
++	wrmsrl(MSR_SYSCALL_MASK,
++	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
++#endif
+ }
+ 
++unsigned long kernel_eflags;
++
++#ifndef CONFIG_X86_NO_TSS
++/*
++ * Copies of the original ist values from the tss are only accessed during
++ * debugging, no special alignment required.
++ */
++DEFINE_PER_CPU(struct orig_ist, orig_ist);
++#endif
++
++#else
++
+ /* Make sure %fs is initialized properly in idle threads */
+ struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+ {
+@@ -662,36 +1006,154 @@ struct pt_regs * __cpuinit idle_regs(str
+ 	regs->fs = __KERNEL_PERCPU;
+ 	return regs;
+ }
++#endif
+ 
+-/* Current gdt points %fs at the "master" per-cpu area: after this,
+- * it's on the real one. */
+-void switch_to_new_gdt(void)
++/*
++ * 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 for 64 bit
++ */
++#ifdef CONFIG_X86_64
++void __cpuinit cpu_init(void)
+ {
+-	struct desc_ptr gdt_descr;
+-	unsigned long va, frames[16];
+-	int f;
++	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;
++	int i;
++#endif
++	struct task_struct *me;
+ 
+-	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+-	gdt_descr.size = GDT_SIZE - 1;
++	/* CPU 0 is initialised in head64.c */
++	if (cpu != 0)
++		pda_init(cpu);
++#ifndef CONFIG_X86_NO_TSS
++	else
++		estacks = boot_exception_stacks;
++#endif
+ 
+-	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_lowmem_page_readonly(
+-			(void *)va, XENFEAT_writable_descriptor_tables);
++	me = current;
++
++	if (cpu_test_and_set(cpu, cpu_initialized))
++		panic("CPU#%d already initialized!\n", cpu);
++
++	printk(KERN_INFO "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:
++	 */
++
++	switch_to_new_gdt();
++#ifndef CONFIG_X86_NO_IDT
++	load_idt((const struct desc_ptr *)&idt_descr);
++#endif
++
++	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_XEN
++	if (cpu != 0 && x2apic)
++		enable_x2apic();
++#endif
++
++#ifndef CONFIG_X86_NO_TSS
++	/*
++	 * set up and load the per-CPU TSS
++	 */
++	if (!orig_ist->ist[0]) {
++		static const unsigned int order[N_EXCEPTION_STACKS] = {
++		  [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
++		  [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
++		};
++		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
++			if (cpu) {
++				estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
++				if (!estacks)
++					panic("Cannot allocate exception "
++					      "stack %ld %d\n", v, cpu);
++			}
++			estacks += PAGE_SIZE << order[v];
++			orig_ist->ist[v] = t->x86_tss.ist[v] =
++					(unsigned long)estacks;
++		}
+ 	}
+-	if (HYPERVISOR_set_gdt(frames, (gdt_descr.size + 1) / 8))
++
++	t->x86_tss.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();
+-	asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
++	enter_lazy_tlb(&init_mm, me);
++
++	load_sp0(t, &current->thread);
++#ifndef CONFIG_X86_NO_TSS
++	set_tss_desc(cpu, t);
++	load_TR_desc();
++#endif
++	load_LDT(&init_mm.context);
++
++#ifdef CONFIG_KGDB
++	/*
++	 * If the kgdb is connected no debug regs should be altered.  This
++	 * is only applicable when KGDB and a KGDB I/O module are built
++	 * into the kernel and you are using early debugging with
++	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
++	 */
++	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
++		arch_kgdb_ops.correct_hw_break();
++	else {
++#endif
++	/*
++	 * 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);
++#ifdef CONFIG_KGDB
++	/* If the kgdb is connected no debug regs should be altered. */
++	}
++#endif
++
++	fpu_init();
++
++#ifndef CONFIG_XEN
++	raw_local_save_flags(kernel_eflags);
++#else
++	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
++	if (raw_irqs_disabled())
++		kernel_eflags &= ~X86_EFLAGS_IF;
++#endif
++
++	if (is_uv_system())
++		uv_cpu_init();
+ }
+ 
+-/*
+- * 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.
+- */
++#else
++
+ void __cpuinit cpu_init(void)
+ {
+ 	int cpu = smp_processor_id();
+@@ -745,19 +1207,21 @@ void __cpuinit cpu_init(void)
+ 	/*
+ 	 * Force FPU initialization:
+ 	 */
+-	current_thread_info()->status = 0;
++	if (cpu_has_xsave)
++		current_thread_info()->status = TS_XSAVE;
++	else
++		current_thread_info()->status = 0;
+ 	clear_used_math();
+ 	mxcsr_feature_mask_init();
+-}
+ 
+-#if defined(CONFIG_HOTPLUG_CPU) && !defined(CONFIG_XEN)
+-void __cpuinit cpu_uninit(void)
+-{
+-	int cpu = raw_smp_processor_id();
+-	cpu_clear(cpu, cpu_initialized);
++	/*
++	 * Boot processor to setup the FP and extended state context info.
++	 */
++	if (smp_processor_id() == boot_cpu_id)
++		init_thread_xstate();
+ 
+-	/* lazy TLB state */
+-	per_cpu(cpu_tlbstate, cpu).state = 0;
+-	per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
++	xsave_init();
+ }
++
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,773 +0,0 @@
+-#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 <linux/kgdb.h>
+-#include <linux/topology.h>
+-#include <linux/delay.h>
+-#include <linux/smp.h>
+-#include <linux/percpu.h>
+-#include <asm/i387.h>
+-#include <asm/msr.h>
+-#include <asm/io.h>
+-#include <asm/linkage.h>
+-#include <asm/mmu_context.h>
+-#include <asm/mtrr.h>
+-#include <asm/mce.h>
+-#include <asm/pat.h>
+-#include <asm/asm.h>
+-#include <asm/numa.h>
+-#ifdef CONFIG_X86_LOCAL_APIC
+-#include <asm/mpspec.h>
+-#include <asm/apic.h>
+-#include <mach_apic.h>
+-#elif defined(CONFIG_XEN)
+-#include <mach_apic.h>
+-#endif
+-#include <asm/pda.h>
+-#include <asm/pgtable.h>
+-#include <asm/processor.h>
+-#include <asm/desc.h>
+-#include <asm/atomic.h>
+-#include <asm/proto.h>
+-#include <asm/sections.h>
+-#include <asm/setup.h>
+-#include <asm/genapic.h>
+-
+-#include "cpu.h"
+-
+-/* We need valid kernel segments for data and code in long mode too
+- * IRET will check the segment types  kkeil 2000/10/28
+- * Also sysret mandates a special GDT layout
+- */
+-/* The TLS descriptors are currently at a different place compared to i386.
+-   Hopefully nobody expects them at a fixed place (Wine?) */
+-DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+-	[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
+-	[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
+-	[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
+-	[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
+-	[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
+-	[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
+-} };
+-EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+-
+-__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+-
+-/* Current gdt points %fs at the "master" per-cpu area: after this,
+- * it's on the real one. */
+-void switch_to_new_gdt(void)
+-{
+-#ifndef CONFIG_XEN
+-	struct desc_ptr gdt_descr;
+-
+-	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+-	gdt_descr.size = GDT_SIZE - 1;
+-	load_gdt(&gdt_descr);
+-#else
+-	void *va, *gdt_addr = get_cpu_gdt_table(smp_processor_id());
+-	unsigned long frames[16];
+-	unsigned int f = 0;
+-
+-	for (va = gdt_addr; va < gdt_addr + GDT_SIZE; va += PAGE_SIZE) {
+-		frames[f++] = virt_to_mfn(va);
+-		make_page_readonly(va, XENFEAT_writable_descriptor_tables);
+-	}
+-	if (HYPERVISOR_set_gdt(frames, GDT_SIZE / sizeof(struct desc_struct)))
+-		BUG();
+-#endif
+-}
+-
+-struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
+-
+-static void __cpuinit default_init(struct cpuinfo_x86 *c)
+-{
+-	display_cacheinfo(c);
+-}
+-
+-static struct cpu_dev __cpuinitdata default_cpu = {
+-	.c_init	= default_init,
+-	.c_vendor = "Unknown",
+-};
+-static struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+-
+-int __cpuinit get_model_name(struct cpuinfo_x86 *c)
+-{
+-	unsigned int *v;
+-
+-	if (c->extended_cpuid_level < 0x80000004)
+-		return 0;
+-
+-	v = (unsigned int *) c->x86_model_id;
+-	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+-	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+-	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+-	c->x86_model_id[48] = 0;
+-	return 1;
+-}
+-
+-
+-void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+-{
+-	unsigned int n, dummy, ebx, ecx, edx;
+-
+-	n = c->extended_cpuid_level;
+-
+-	if (n >= 0x80000005) {
+-		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
+-		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), "
+-		       "D cache %dK (%d bytes/line)\n",
+-		       edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+-		c->x86_cache_size = (ecx>>24) + (edx>>24);
+-		/* On K8 L1 TLB is inclusive, so don't count it */
+-		c->x86_tlbsize = 0;
+-	}
+-
+-	if (n >= 0x80000006) {
+-		cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
+-		ecx = cpuid_ecx(0x80000006);
+-		c->x86_cache_size = ecx >> 16;
+-		c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
+-
+-		printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+-		c->x86_cache_size, ecx & 0xFF);
+-	}
+-}
+-
+-void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+-{
+-#ifdef CONFIG_SMP
+-	u32 eax, ebx, ecx, edx;
+-	int index_msb, core_bits;
+-
+-	cpuid(1, &eax, &ebx, &ecx, &edx);
+-
+-
+-	if (!cpu_has(c, X86_FEATURE_HT))
+-		return;
+-	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+-		goto out;
+-
+-	smp_num_siblings = (ebx & 0xff0000) >> 16;
+-
+-	if (smp_num_siblings == 1) {
+-		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+-	} else if (smp_num_siblings > 1) {
+-
+-		if (smp_num_siblings > NR_CPUS) {
+-			printk(KERN_WARNING "CPU: Unsupported number of "
+-			       "siblings %d", smp_num_siblings);
+-			smp_num_siblings = 1;
+-			return;
+-		}
+-
+-		index_msb = get_count_order(smp_num_siblings);
+-		c->phys_proc_id = phys_pkg_id(index_msb);
+-
+-		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+-
+-		index_msb = get_count_order(smp_num_siblings);
+-
+-		core_bits = get_count_order(c->x86_max_cores);
+-
+-		c->cpu_core_id = phys_pkg_id(index_msb) &
+-					       ((1 << core_bits) - 1);
+-	}
+-out:
+-	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+-		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+-		       c->phys_proc_id);
+-		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+-		       c->cpu_core_id);
+-	}
+-
+-#endif
+-}
+-
+-static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+-{
+-	char *v = c->x86_vendor_id;
+-	int i;
+-	static int printed;
+-
+-	for (i = 0; i < X86_VENDOR_NUM; i++) {
+-		if (cpu_devs[i]) {
+-			if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+-			    (cpu_devs[i]->c_ident[1] &&
+-			    !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+-				c->x86_vendor = i;
+-				this_cpu = cpu_devs[i];
+-				return;
+-			}
+-		}
+-	}
+-	if (!printed) {
+-		printed++;
+-		printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n");
+-		printk(KERN_ERR "CPU: Your system may be unstable.\n");
+-	}
+-	c->x86_vendor = X86_VENDOR_UNKNOWN;
+-}
+-
+-static void __init early_cpu_support_print(void)
+-{
+-	int i,j;
+-	struct cpu_dev *cpu_devx;
+-
+-	printk("KERNEL supported cpus:\n");
+-	for (i = 0; i < X86_VENDOR_NUM; i++) {
+-		cpu_devx = cpu_devs[i];
+-		if (!cpu_devx)
+-			continue;
+-		for (j = 0; j < 2; j++) {
+-			if (!cpu_devx->c_ident[j])
+-				continue;
+-			printk("  %s %s\n", cpu_devx->c_vendor,
+-				cpu_devx->c_ident[j]);
+-		}
+-	}
+-}
+-
+-/*
+- * The NOPL instruction is supposed to exist on all CPUs with
+- * family >= 6, unfortunately, that's not true in practice because
+- * of early VIA chips and (more importantly) broken virtualizers that
+- * are not easy to detect.  Hence, probe for it based on first
+- * principles.
+- *
+- * Note: no 64-bit chip is known to lack these, but put the code here
+- * for consistency with 32 bits, and to make it utterly trivial to
+- * diagnose the problem should it ever surface.
+- */
+-static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+-{
+-	const u32 nopl_signature = 0x888c53b1; /* Random number */
+-	u32 has_nopl = nopl_signature;
+-
+-	clear_cpu_cap(c, X86_FEATURE_NOPL);
+-	if (c->x86 >= 6) {
+-		asm volatile("\n"
+-			     "1:      .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
+-			     "2:\n"
+-			     "        .section .fixup,\"ax\"\n"
+-			     "3:      xor %0,%0\n"
+-			     "        jmp 2b\n"
+-			     "        .previous\n"
+-			     _ASM_EXTABLE(1b,3b)
+-			     : "+a" (has_nopl));
+-
+-		if (has_nopl == nopl_signature)
+-			set_cpu_cap(c, X86_FEATURE_NOPL);
+-	}
+-}
+-
+-static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
+-
+-void __init early_cpu_init(void)
+-{
+-        struct cpu_vendor_dev *cvdev;
+-
+-        for (cvdev = __x86cpuvendor_start ;
+-             cvdev < __x86cpuvendor_end   ;
+-             cvdev++)
+-                cpu_devs[cvdev->vendor] = cvdev->cpu_dev;
+-	early_cpu_support_print();
+-	early_identify_cpu(&boot_cpu_data);
+-}
+-
+-/* Do some early cpuid on the boot CPU to get some parameter that are
+-   needed before check_bugs. Everything advanced is in identify_cpu
+-   below. */
+-static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
+-{
+-	u32 tfms, xlvl;
+-
+-	c->loops_per_jiffy = loops_per_jiffy;
+-	c->x86_cache_size = -1;
+-	c->x86_vendor = X86_VENDOR_UNKNOWN;
+-	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+-	c->x86_vendor_id[0] = '\0'; /* Unset */
+-	c->x86_model_id[0] = '\0';  /* Unset */
+-	c->x86_clflush_size = 64;
+-	c->x86_cache_alignment = c->x86_clflush_size;
+-	c->x86_max_cores = 1;
+-	c->x86_coreid_bits = 0;
+-	c->extended_cpuid_level = 0;
+-	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+-
+-	/* Get vendor name */
+-	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+-	      (unsigned int *)&c->x86_vendor_id[0],
+-	      (unsigned int *)&c->x86_vendor_id[8],
+-	      (unsigned int *)&c->x86_vendor_id[4]);
+-
+-	get_cpu_vendor(c);
+-
+-	/* Initialize the standard set of capabilities */
+-	/* Note that the vendor-specific code below might override */
+-
+-	/* Intel-defined flags: level 0x00000001 */
+-	if (c->cpuid_level >= 0x00000001) {
+-		__u32 misc;
+-		cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4],
+-		      &c->x86_capability[0]);
+-		c->x86 = (tfms >> 8) & 0xf;
+-		c->x86_model = (tfms >> 4) & 0xf;
+-		c->x86_mask = tfms & 0xf;
+-		if (c->x86 == 0xf)
+-			c->x86 += (tfms >> 20) & 0xff;
+-		if (c->x86 >= 0x6)
+-			c->x86_model += ((tfms >> 16) & 0xF) << 4;
+-		if (test_cpu_cap(c, X86_FEATURE_CLFLSH))
+-			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+-	} else {
+-		/* Have CPUID level 0 only - unheard of */
+-		c->x86 = 4;
+-	}
+-
+-	c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xff;
+-#ifdef CONFIG_SMP
+-	c->phys_proc_id = c->initial_apicid;
+-#endif
+-	/* AMD-defined flags: level 0x80000001 */
+-	xlvl = cpuid_eax(0x80000000);
+-	c->extended_cpuid_level = xlvl;
+-	if ((xlvl & 0xffff0000) == 0x80000000) {
+-		if (xlvl >= 0x80000001) {
+-			c->x86_capability[1] = cpuid_edx(0x80000001);
+-			c->x86_capability[6] = cpuid_ecx(0x80000001);
+-		}
+-		if (xlvl >= 0x80000004)
+-			get_model_name(c); /* Default name */
+-	}
+-
+-	/* Transmeta-defined flags: level 0x80860001 */
+-	xlvl = cpuid_eax(0x80860000);
+-	if ((xlvl & 0xffff0000) == 0x80860000) {
+-		/* Don't set x86_cpuid_level here for now to not confuse. */
+-		if (xlvl >= 0x80860001)
+-			c->x86_capability[2] = cpuid_edx(0x80860001);
+-	}
+-
+-	if (c->extended_cpuid_level >= 0x80000007)
+-		c->x86_power = cpuid_edx(0x80000007);
+-
+-	if (c->extended_cpuid_level >= 0x80000008) {
+-		u32 eax = cpuid_eax(0x80000008);
+-
+-		c->x86_virt_bits = (eax >> 8) & 0xff;
+-		c->x86_phys_bits = eax & 0xff;
+-	}
+-
+-	detect_nopl(c);
+-
+-	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
+-	    cpu_devs[c->x86_vendor]->c_early_init)
+-		cpu_devs[c->x86_vendor]->c_early_init(c);
+-
+-	validate_pat_support(c);
+-}
+-
+-/*
+- * This does the hard work of actually picking apart the CPU stuff...
+- */
+-static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+-{
+-	int i;
+-
+-	early_identify_cpu(c);
+-
+-	init_scattered_cpuid_features(c);
+-
+-#ifndef CONFIG_XEN
+-	c->apicid = phys_pkg_id(0);
+-#endif
+-
+-	/*
+-	 * Vendor-specific initialization.  In this section we
+-	 * canonicalize the feature flags, meaning if there are
+-	 * features a certain CPU supports which CPUID doesn't
+-	 * tell us, CPUID claiming incorrect flags, or other bugs,
+-	 * we handle them here.
+-	 *
+-	 * At the end of this section, c->x86_capability better
+-	 * indicate the features this CPU genuinely supports!
+-	 */
+-	if (this_cpu->c_init)
+-		this_cpu->c_init(c);
+-
+-	detect_ht(c);
+-
+-	/*
+-	 * On SMP, boot_cpu_data holds the common feature set between
+-	 * all CPUs; so make sure that we indicate which features are
+-	 * common between the CPUs.  The first time this routine gets
+-	 * executed, c == &boot_cpu_data.
+-	 */
+-	if (c != &boot_cpu_data) {
+-		/* AND the already accumulated flags with these */
+-		for (i = 0; i < NCAPINTS; i++)
+-			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+-	}
+-
+-	/* Clear all flags overriden by options */
+-	for (i = 0; i < NCAPINTS; i++)
+-		c->x86_capability[i] &= ~cleared_cpu_caps[i];
+-
+-#ifdef CONFIG_X86_MCE
+-	mcheck_init(c);
+-#endif
+-	select_idle_routine(c);
+-
+-#ifdef CONFIG_NUMA
+-	numa_add_cpu(smp_processor_id());
+-#endif
+-
+-}
+-
+-void __cpuinit identify_boot_cpu(void)
+-{
+-	identify_cpu(&boot_cpu_data);
+-}
+-
+-void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+-{
+-	BUG_ON(c == &boot_cpu_data);
+-	identify_cpu(c);
+-	mtrr_ap_init();
+-}
+-
+-static __init int setup_noclflush(char *arg)
+-{
+-	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+-	return 1;
+-}
+-__setup("noclflush", setup_noclflush);
+-
+-void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+-{
+-	if (c->x86_model_id[0])
+-		printk(KERN_CONT "%s", c->x86_model_id);
+-
+-	if (c->x86_mask || c->cpuid_level >= 0)
+-		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
+-	else
+-		printk(KERN_CONT "\n");
+-}
+-
+-static __init int setup_disablecpuid(char *arg)
+-{
+-	int bit;
+-	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+-		setup_clear_cpu_cap(bit);
+-	else
+-		return 0;
+-	return 1;
+-}
+-__setup("clearcpuid=", setup_disablecpuid);
+-
+-cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+-
+-struct x8664_pda **_cpu_pda __read_mostly;
+-EXPORT_SYMBOL(_cpu_pda);
+-
+-#ifndef CONFIG_X86_NO_IDT
+-struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
+-#endif
+-
+-char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
+-
+-unsigned long __supported_pte_mask __read_mostly = ~0UL;
+-EXPORT_SYMBOL_GPL(__supported_pte_mask);
+-
+-static int do_not_nx __cpuinitdata;
+-
+-/* noexec=on|off
+-Control non executable mappings for 64bit processes.
+-
+-on	Enable(default)
+-off	Disable
+-*/
+-static int __init nonx_setup(char *str)
+-{
+-	if (!str)
+-		return -EINVAL;
+-	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 0;
+-}
+-early_param("noexec", nonx_setup);
+-
+-int force_personality32;
+-
+-/* 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 (default)
+-off	PROT_READ implies PROT_EXEC
+-*/
+-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);
+-
+-static void __init_refok switch_pt(int cpu)
+-{
+-#ifdef CONFIG_XEN
+-	if (cpu == 0)
+-		xen_init_pt();
+-	xen_pt_switch(__pa_symbol(init_level4_pgt));
+-	xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt)));
+-#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 */
+-	loadsegment(fs, 0);
+-	loadsegment(gs, 0);
+-#ifndef CONFIG_XEN
+-	/* Memory clobbers used to order PDA accessed */
+-	mb();
+-	wrmsrl(MSR_GS_BASE, pda);
+-	mb();
+-#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) {
+-		/* others are initialized in smpboot.c */
+-		pda->pcurrent = &init_task;
+-		pda->irqstackptr = boot_cpu_stack;
+-		pda->irqstackptr += IRQSTACKSIZE - 64;
+-	} else {
+-		if (!pda->irqstackptr) {
+-			pda->irqstackptr = (char *)
+-				__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
+-			if (!pda->irqstackptr)
+-				panic("cannot allocate irqstack for cpu %d",
+-				      cpu);
+-			pda->irqstackptr += IRQSTACKSIZE - 64;
+-		}
+-
+-		if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
+-			pda->nodenumber = cpu_to_node(cpu);
+-	}
+-
+-	switch_pt(cpu);
+-}
+-
+-#ifndef CONFIG_X86_NO_TSS
+-char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
+-			   DEBUG_STKSZ] __page_aligned_bss;
+-#endif
+-
+-extern asmlinkage void ignore_sysret(void);
+-
+-void __cpuinit 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);
+-	wrmsrl(MSR_CSTAR, ignore_sysret);
+-
+-	/* Flags to clear on syscall */
+-	wrmsrl(MSR_SYSCALL_MASK,
+-	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
+-#endif
+-#ifdef CONFIG_IA32_EMULATION
+-	syscall32_cpu_init();
+-#else
+-	static const struct callback_register __cpuinitconst cstar = {
+-		.type = CALLBACKTYPE_syscall32,
+-		.address = (unsigned long)ignore_sysret
+-	};
+-
+-	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
+-		printk(KERN_WARNING "Unable to register CSTAR callback\n");
+-#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;
+-
+-#ifndef CONFIG_X86_NO_TSS
+-/*
+- * Copies of the original ist values from the tss are only accessed during
+- * debugging, no special alignment required.
+- */
+-DEFINE_PER_CPU(struct orig_ist, orig_ist);
+-#endif
+-
+-/*
+- * 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;
+-	int i;
+-#endif
+-	struct task_struct *me;
+-
+-	/* CPU 0 is initialised in head64.c */
+-	if (cpu != 0)
+-		pda_init(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(KERN_INFO "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:
+-	 */
+-
+-	switch_to_new_gdt();
+-#ifndef CONFIG_X86_NO_IDT
+-	load_idt((const struct desc_ptr *)&idt_descr);
+-#endif
+-
+-	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
+-	 */
+-	if (!orig_ist->ist[0]) {
+-		static const unsigned int order[N_EXCEPTION_STACKS] = {
+-		  [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+-		  [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+-		};
+-		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+-			if (cpu) {
+-				estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
+-				if (!estacks)
+-					panic("Cannot allocate exception "
+-					      "stack %ld %d\n", v, cpu);
+-			}
+-			estacks += PAGE_SIZE << order[v];
+-			orig_ist->ist[v] = t->x86_tss.ist[v] =
+-					(unsigned long)estacks;
+-		}
+-	}
+-
+-	t->x86_tss.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);
+-
+-	load_sp0(t, &current->thread);
+-#ifndef CONFIG_X86_NO_TSS
+-	set_tss_desc(cpu, t);
+-	load_TR_desc();
+-#endif
+-	load_LDT(&init_mm.context);
+-
+-#ifdef CONFIG_KGDB
+-	/*
+-	 * If the kgdb is connected no debug regs should be altered.  This
+-	 * is only applicable when KGDB and a KGDB I/O module are built
+-	 * into the kernel and you are using early debugging with
+-	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
+-	 */
+-	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
+-		arch_kgdb_ops.correct_hw_break();
+-	else {
+-#endif
+-	/*
+-	 * 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);
+-#ifdef CONFIG_KGDB
+-	/* If the kgdb is connected no debug regs should be altered. */
+-	}
+-#endif
+-
+-	fpu_init();
+-
+-	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
+-	if (raw_irqs_disabled())
+-		kernel_eflags &= ~X86_EFLAGS_IF;
+-
+-	if (is_uv_system())
+-		uv_cpu_init();
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/dumpstack_64.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/dumpstack_64.c	2009-11-06 10:51:47.000000000 +0100
+@@ -20,6 +20,7 @@
+ #include "dumpstack.h"
+ 
+ 
++#ifndef CONFIG_X86_NO_TSS
+ static char x86_stack_ids[][8] = {
+ 		[DEBUG_STACK - 1] = "#DB",
+ 		[NMI_STACK - 1] = "NMI",
+@@ -31,6 +32,7 @@ static char x86_stack_ids[][8] = {
+ 			N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
+ #endif
+ 	};
++#endif
+ 
+ int x86_is_stack_id(int id, char *name)
+ {
+@@ -40,6 +42,7 @@ int x86_is_stack_id(int id, char *name)
+ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+ 					unsigned *usedp, char **idp)
+ {
++#ifndef CONFIG_X86_NO_TSS
+ 	unsigned k;
+ 
+ 	/*
+@@ -99,6 +102,7 @@ static unsigned long *in_exception_stack
+ 		}
+ #endif
+ 	}
++#endif /* CONFIG_X86_NO_TSS */
+ 	return NULL;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -167,6 +167,9 @@ static void __init _e820_print_map(const
+ 		case E820_NVS:
+ 			printk(KERN_CONT "(ACPI NVS)\n");
+ 			break;
++		case E820_UNUSABLE:
++			printk("(unusable)\n");
++			break;
+ 		default:
+ 			printk(KERN_CONT "type %u\n", e820->map[i].type);
+ 			break;
+@@ -1399,6 +1402,7 @@ static inline const char *e820_type_to_s
+ 	case E820_RAM:	return "System RAM";
+ 	case E820_ACPI:	return "ACPI Tables";
+ 	case E820_NVS:	return "ACPI Non-volatile Storage";
++	case E820_UNUSABLE:	return "Unusable memory";
+ 	default:	return "reserved";
+ 	}
+ }
+@@ -1410,6 +1414,7 @@ static inline const char *e820_type_to_s
+ /*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
++static struct resource __initdata *e820_res;
+ void __init e820_reserve_resources(void)
+ {
+ 	int i;
+@@ -1417,20 +1422,28 @@ void __init e820_reserve_resources(void)
+ 	u64 end;
+ 
+ 	res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
++	e820_res = res;
+ 	for (i = 0; i < e820.nr_map; i++) {
+ 		end = e820.map[i].addr + e820.map[i].size - 1;
+-#ifndef CONFIG_RESOURCES_64BIT
+-		if (end > 0x100000000ULL) {
++		if (end != (resource_size_t)end) {
+ 			res++;
+ 			continue;
+ 		}
+-#endif
+ 		res->name = e820_type_to_string(e820.map[i].type);
+ 		res->start = e820.map[i].addr;
+ 		res->end = end;
+ 
+-		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-		insert_resource(&iomem_resource, res);
++		res->flags = IORESOURCE_MEM;
++
++		/*
++		 * don't register the region that could be conflicted with
++		 * pci device BAR resource and insert them later in
++		 * pcibios_resource_survey()
++		 */
++		if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) {
++			res->flags |= IORESOURCE_BUSY;
++			insert_resource(&iomem_resource, res);
++		}
+ 		res++;
+ 	}
+ 
+@@ -1442,6 +1455,19 @@ void __init e820_reserve_resources(void)
+ 	}
+ }
+ 
++void __init e820_reserve_resources_late(void)
++{
++	int i;
++	struct resource *res;
++
++	res = e820_res;
++	for (i = 0; i < e820.nr_map; i++) {
++		if (!res->parent && res->end)
++			insert_resource_expand_to_fit(&iomem_resource, res);
++		res++;
++	}
++}
++
+ #undef e820
+ 
+ #ifndef CONFIG_XEN
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -3,10 +3,18 @@
+ #include <linux/init.h>
+ #include <linux/string.h>
+ #include <linux/screen_info.h>
++#include <linux/usb/ch9.h>
++#include <linux/pci_regs.h>
++#include <linux/pci_ids.h>
++#include <linux/errno.h>
+ #include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/fcntl.h>
+ #include <asm/setup.h>
++#include <asm/pci-direct.h>
++#include <asm/pgtable.h>
++#include <asm/fixmap.h>
++#include <linux/usb/ehci_def.h>
+ 
+ #ifndef CONFIG_XEN
+ /* Simple VGA output */
+@@ -78,6 +86,7 @@ static int early_serial_base = 0x3f8;  /
+ static int early_serial_putc(unsigned char ch)
+ {
+ 	unsigned timeout = 0xffff;
++
+ 	while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
+ 		cpu_relax();
+ 	outb(ch, early_serial_base + TXR);
+@@ -111,7 +120,7 @@ static __init void early_serial_init(cha
+ 		if (!strncmp(s, "0x", 2)) {
+ 			early_serial_base = simple_strtoul(s, &e, 16);
+ 		} else {
+-			static int bases[] = { 0x3f8, 0x2f8 };
++			static const int __initconst bases[] = { 0x3f8, 0x2f8 };
+ 
+ 			if (!strncmp(s, "ttyS", 4))
+ 				s += 4;
+@@ -180,6 +189,721 @@ static struct console early_serial_conso
+ 	.index =	-1,
+ };
+ 
++#ifdef CONFIG_EARLY_PRINTK_DBGP
++
++static struct ehci_caps __iomem *ehci_caps;
++static struct ehci_regs __iomem *ehci_regs;
++static struct ehci_dbg_port __iomem *ehci_debug;
++static unsigned int dbgp_endpoint_out;
++
++struct ehci_dev {
++	u32 bus;
++	u32 slot;
++	u32 func;
++};
++
++static struct ehci_dev ehci_dev;
++
++#define USB_DEBUG_DEVNUM 127
++
++#define DBGP_DATA_TOGGLE	0x8800
++
++static inline u32 dbgp_pid_update(u32 x, u32 tok)
++{
++	return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff);
++}
++
++static inline u32 dbgp_len_update(u32 x, u32 len)
++{
++	return (x & ~0x0f) | (len & 0x0f);
++}
++
++/*
++ * USB Packet IDs (PIDs)
++ */
++
++/* token */
++#define USB_PID_OUT		0xe1
++#define USB_PID_IN		0x69
++#define USB_PID_SOF		0xa5
++#define USB_PID_SETUP		0x2d
++/* handshake */
++#define USB_PID_ACK		0xd2
++#define USB_PID_NAK		0x5a
++#define USB_PID_STALL		0x1e
++#define USB_PID_NYET		0x96
++/* data */
++#define USB_PID_DATA0		0xc3
++#define USB_PID_DATA1		0x4b
++#define USB_PID_DATA2		0x87
++#define USB_PID_MDATA		0x0f
++/* Special */
++#define USB_PID_PREAMBLE	0x3c
++#define USB_PID_ERR		0x3c
++#define USB_PID_SPLIT		0x78
++#define USB_PID_PING		0xb4
++#define USB_PID_UNDEF_0		0xf0
++
++#define USB_PID_DATA_TOGGLE	0x88
++#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE)
++
++#define PCI_CAP_ID_EHCI_DEBUG	0xa
++
++#define HUB_ROOT_RESET_TIME	50	/* times are in msec */
++#define HUB_SHORT_RESET_TIME	10
++#define HUB_LONG_RESET_TIME	200
++#define HUB_RESET_TIMEOUT	500
++
++#define DBGP_MAX_PACKET		8
++
++static int dbgp_wait_until_complete(void)
++{
++	u32 ctrl;
++	int loop = 0x100000;
++
++	do {
++		ctrl = readl(&ehci_debug->control);
++		/* Stop when the transaction is finished */
++		if (ctrl & DBGP_DONE)
++			break;
++	} while (--loop > 0);
++
++	if (!loop)
++		return -1;
++
++	/*
++	 * Now that we have observed the completed transaction,
++	 * clear the done bit.
++	 */
++	writel(ctrl | DBGP_DONE, &ehci_debug->control);
++	return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl);
++}
++
++static void dbgp_mdelay(int ms)
++{
++	int i;
++
++	while (ms--) {
++		for (i = 0; i < 1000; i++)
++			outb(0x1, 0x80);
++	}
++}
++
++static void dbgp_breath(void)
++{
++	/* Sleep to give the debug port a chance to breathe */
++}
++
++static int dbgp_wait_until_done(unsigned ctrl)
++{
++	u32 pids, lpid;
++	int ret;
++	int loop = 3;
++
++retry:
++	writel(ctrl | DBGP_GO, &ehci_debug->control);
++	ret = dbgp_wait_until_complete();
++	pids = readl(&ehci_debug->pids);
++	lpid = DBGP_PID_GET(pids);
++
++	if (ret < 0)
++		return ret;
++
++	/*
++	 * If the port is getting full or it has dropped data
++	 * start pacing ourselves, not necessary but it's friendly.
++	 */
++	if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET))
++		dbgp_breath();
++
++	/* If I get a NACK reissue the transmission */
++	if (lpid == USB_PID_NAK) {
++		if (--loop > 0)
++			goto retry;
++	}
++
++	return ret;
++}
++
++static void dbgp_set_data(const void *buf, int size)
++{
++	const unsigned char *bytes = buf;
++	u32 lo, hi;
++	int i;
++
++	lo = hi = 0;
++	for (i = 0; i < 4 && i < size; i++)
++		lo |= bytes[i] << (8*i);
++	for (; i < 8 && i < size; i++)
++		hi |= bytes[i] << (8*(i - 4));
++	writel(lo, &ehci_debug->data03);
++	writel(hi, &ehci_debug->data47);
++}
++
++static void dbgp_get_data(void *buf, int size)
++{
++	unsigned char *bytes = buf;
++	u32 lo, hi;
++	int i;
++
++	lo = readl(&ehci_debug->data03);
++	hi = readl(&ehci_debug->data47);
++	for (i = 0; i < 4 && i < size; i++)
++		bytes[i] = (lo >> (8*i)) & 0xff;
++	for (; i < 8 && i < size; i++)
++		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
++}
++
++static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
++			 const char *bytes, int size)
++{
++	u32 pids, addr, ctrl;
++	int ret;
++
++	if (size > DBGP_MAX_PACKET)
++		return -1;
++
++	addr = DBGP_EPADDR(devnum, endpoint);
++
++	pids = readl(&ehci_debug->pids);
++	pids = dbgp_pid_update(pids, USB_PID_OUT);
++
++	ctrl = readl(&ehci_debug->control);
++	ctrl = dbgp_len_update(ctrl, size);
++	ctrl |= DBGP_OUT;
++	ctrl |= DBGP_GO;
++
++	dbgp_set_data(bytes, size);
++	writel(addr, &ehci_debug->address);
++	writel(pids, &ehci_debug->pids);
++
++	ret = dbgp_wait_until_done(ctrl);
++	if (ret < 0)
++		return ret;
++
++	return ret;
++}
++
++static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
++				 int size)
++{
++	u32 pids, addr, ctrl;
++	int ret;
++
++	if (size > DBGP_MAX_PACKET)
++		return -1;
++
++	addr = DBGP_EPADDR(devnum, endpoint);
++
++	pids = readl(&ehci_debug->pids);
++	pids = dbgp_pid_update(pids, USB_PID_IN);
++
++	ctrl = readl(&ehci_debug->control);
++	ctrl = dbgp_len_update(ctrl, size);
++	ctrl &= ~DBGP_OUT;
++	ctrl |= DBGP_GO;
++
++	writel(addr, &ehci_debug->address);
++	writel(pids, &ehci_debug->pids);
++	ret = dbgp_wait_until_done(ctrl);
++	if (ret < 0)
++		return ret;
++
++	if (size > ret)
++		size = ret;
++	dbgp_get_data(data, size);
++	return ret;
++}
++
++static int dbgp_control_msg(unsigned devnum, int requesttype, int request,
++	int value, int index, void *data, int size)
++{
++	u32 pids, addr, ctrl;
++	struct usb_ctrlrequest req;
++	int read;
++	int ret;
++
++	read = (requesttype & USB_DIR_IN) != 0;
++	if (size > (read ? DBGP_MAX_PACKET:0))
++		return -1;
++
++	/* Compute the control message */
++	req.bRequestType = requesttype;
++	req.bRequest = request;
++	req.wValue = cpu_to_le16(value);
++	req.wIndex = cpu_to_le16(index);
++	req.wLength = cpu_to_le16(size);
++
++	pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP);
++	addr = DBGP_EPADDR(devnum, 0);
++
++	ctrl = readl(&ehci_debug->control);
++	ctrl = dbgp_len_update(ctrl, sizeof(req));
++	ctrl |= DBGP_OUT;
++	ctrl |= DBGP_GO;
++
++	/* Send the setup message */
++	dbgp_set_data(&req, sizeof(req));
++	writel(addr, &ehci_debug->address);
++	writel(pids, &ehci_debug->pids);
++	ret = dbgp_wait_until_done(ctrl);
++	if (ret < 0)
++		return ret;
++
++	/* Read the result */
++	return dbgp_bulk_read(devnum, 0, data, size);
++}
++
++
++/* Find a PCI capability */
++static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap)
++{
++	u8 pos;
++	int bytes;
++
++	if (!(read_pci_config_16(num, slot, func, PCI_STATUS) &
++		PCI_STATUS_CAP_LIST))
++		return 0;
++
++	pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST);
++	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
++		u8 id;
++
++		pos &= ~3;
++		id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID);
++		if (id == 0xff)
++			break;
++		if (id == cap)
++			return pos;
++
++		pos = read_pci_config_byte(num, slot, func,
++						 pos+PCI_CAP_LIST_NEXT);
++	}
++	return 0;
++}
++
++static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func)
++{
++	u32 class;
++
++	class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
++	if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI)
++		return 0;
++
++	return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG);
++}
++
++static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc)
++{
++	u32 bus, slot, func;
++
++	for (bus = 0; bus < 256; bus++) {
++		for (slot = 0; slot < 32; slot++) {
++			for (func = 0; func < 8; func++) {
++				unsigned cap;
++
++				cap = __find_dbgp(bus, slot, func);
++
++				if (!cap)
++					continue;
++				if (ehci_num-- != 0)
++					continue;
++				*rbus = bus;
++				*rslot = slot;
++				*rfunc = func;
++				return cap;
++			}
++		}
++	}
++	return 0;
++}
++
++static int ehci_reset_port(int port)
++{
++	u32 portsc;
++	u32 delay_time, delay;
++	int loop;
++
++	/* Reset the usb debug port */
++	portsc = readl(&ehci_regs->port_status[port - 1]);
++	portsc &= ~PORT_PE;
++	portsc |= PORT_RESET;
++	writel(portsc, &ehci_regs->port_status[port - 1]);
++
++	delay = HUB_ROOT_RESET_TIME;
++	for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT;
++	     delay_time += delay) {
++		dbgp_mdelay(delay);
++
++		portsc = readl(&ehci_regs->port_status[port - 1]);
++		if (portsc & PORT_RESET) {
++			/* force reset to complete */
++			loop = 2;
++			writel(portsc & ~(PORT_RWC_BITS | PORT_RESET),
++				&ehci_regs->port_status[port - 1]);
++			do {
++				portsc = readl(&ehci_regs->port_status[port-1]);
++			} while ((portsc & PORT_RESET) && (--loop > 0));
++		}
++
++		/* Device went away? */
++		if (!(portsc & PORT_CONNECT))
++			return -ENOTCONN;
++
++		/* bomb out completely if something weird happend */
++		if ((portsc & PORT_CSC))
++			return -EINVAL;
++
++		/* If we've finished resetting, then break out of the loop */
++		if (!(portsc & PORT_RESET) && (portsc & PORT_PE))
++			return 0;
++	}
++	return -EBUSY;
++}
++
++static int ehci_wait_for_port(int port)
++{
++	u32 status;
++	int ret, reps;
++
++	for (reps = 0; reps < 3; reps++) {
++		dbgp_mdelay(100);
++		status = readl(&ehci_regs->status);
++		if (status & STS_PCD) {
++			ret = ehci_reset_port(port);
++			if (ret == 0)
++				return 0;
++		}
++	}
++	return -ENOTCONN;
++}
++
++#ifdef DBGP_DEBUG
++# define dbgp_printk early_printk
++#else
++static inline void dbgp_printk(const char *fmt, ...) { }
++#endif
++
++typedef void (*set_debug_port_t)(int port);
++
++static void default_set_debug_port(int port)
++{
++}
++
++static set_debug_port_t set_debug_port = default_set_debug_port;
++
++static void nvidia_set_debug_port(int port)
++{
++	u32 dword;
++	dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
++				 0x74);
++	dword &= ~(0x0f<<12);
++	dword |= ((port & 0x0f)<<12);
++	write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74,
++				 dword);
++	dbgp_printk("set debug port to %d\n", port);
++}
++
++static void __init detect_set_debug_port(void)
++{
++	u32 vendorid;
++
++	vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
++		 0x00);
++
++	if ((vendorid & 0xffff) == 0x10de) {
++		dbgp_printk("using nvidia set_debug_port\n");
++		set_debug_port = nvidia_set_debug_port;
++	}
++}
++
++static int __init ehci_setup(void)
++{
++	struct usb_debug_descriptor dbgp_desc;
++	u32 cmd, ctrl, status, portsc, hcs_params;
++	u32 debug_port, new_debug_port = 0, n_ports;
++	u32  devnum;
++	int ret, i;
++	int loop;
++	int port_map_tried;
++	int playtimes = 3;
++
++try_next_time:
++	port_map_tried = 0;
++
++try_next_port:
++
++	hcs_params = readl(&ehci_caps->hcs_params);
++	debug_port = HCS_DEBUG_PORT(hcs_params);
++	n_ports    = HCS_N_PORTS(hcs_params);
++
++	dbgp_printk("debug_port: %d\n", debug_port);
++	dbgp_printk("n_ports:    %d\n", n_ports);
++
++	for (i = 1; i <= n_ports; i++) {
++		portsc = readl(&ehci_regs->port_status[i-1]);
++		dbgp_printk("portstatus%d: %08x\n", i, portsc);
++	}
++
++	if (port_map_tried && (new_debug_port != debug_port)) {
++		if (--playtimes) {
++			set_debug_port(new_debug_port);
++			goto try_next_time;
++		}
++		return -1;
++	}
++
++	loop = 10;
++	/* Reset the EHCI controller */
++	cmd = readl(&ehci_regs->command);
++	cmd |= CMD_RESET;
++	writel(cmd, &ehci_regs->command);
++	do {
++		cmd = readl(&ehci_regs->command);
++	} while ((cmd & CMD_RESET) && (--loop > 0));
++
++	if (!loop) {
++		dbgp_printk("can not reset ehci\n");
++		return -1;
++	}
++	dbgp_printk("ehci reset done\n");
++
++	/* Claim ownership, but do not enable yet */
++	ctrl = readl(&ehci_debug->control);
++	ctrl |= DBGP_OWNER;
++	ctrl &= ~(DBGP_ENABLED | DBGP_INUSE);
++	writel(ctrl, &ehci_debug->control);
++
++	/* Start the ehci running */
++	cmd = readl(&ehci_regs->command);
++	cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET);
++	cmd |= CMD_RUN;
++	writel(cmd, &ehci_regs->command);
++
++	/* Ensure everything is routed to the EHCI */
++	writel(FLAG_CF, &ehci_regs->configured_flag);
++
++	/* Wait until the controller is no longer halted */
++	loop = 10;
++	do {
++		status = readl(&ehci_regs->status);
++	} while ((status & STS_HALT) && (--loop > 0));
++
++	if (!loop) {
++		dbgp_printk("ehci can be started\n");
++		return -1;
++	}
++	dbgp_printk("ehci started\n");
++
++	/* Wait for a device to show up in the debug port */
++	ret = ehci_wait_for_port(debug_port);
++	if (ret < 0) {
++		dbgp_printk("No device found in debug port\n");
++		goto next_debug_port;
++	}
++	dbgp_printk("ehci wait for port done\n");
++
++	/* Enable the debug port */
++	ctrl = readl(&ehci_debug->control);
++	ctrl |= DBGP_CLAIM;
++	writel(ctrl, &ehci_debug->control);
++	ctrl = readl(&ehci_debug->control);
++	if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) {
++		dbgp_printk("No device in debug port\n");
++		writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control);
++		goto err;
++	}
++	dbgp_printk("debug ported enabled\n");
++
++	/* Completely transfer the debug device to the debug controller */
++	portsc = readl(&ehci_regs->port_status[debug_port - 1]);
++	portsc &= ~PORT_PE;
++	writel(portsc, &ehci_regs->port_status[debug_port - 1]);
++
++	dbgp_mdelay(100);
++
++	/* Find the debug device and make it device number 127 */
++	for (devnum = 0; devnum <= 127; devnum++) {
++		ret = dbgp_control_msg(devnum,
++			USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
++			USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0,
++			&dbgp_desc, sizeof(dbgp_desc));
++		if (ret > 0)
++			break;
++	}
++	if (devnum > 127) {
++		dbgp_printk("Could not find attached debug device\n");
++		goto err;
++	}
++	if (ret < 0) {
++		dbgp_printk("Attached device is not a debug device\n");
++		goto err;
++	}
++	dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
++
++	/* Move the device to 127 if it isn't already there */
++	if (devnum != USB_DEBUG_DEVNUM) {
++		ret = dbgp_control_msg(devnum,
++			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
++			USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0);
++		if (ret < 0) {
++			dbgp_printk("Could not move attached device to %d\n",
++				USB_DEBUG_DEVNUM);
++			goto err;
++		}
++		devnum = USB_DEBUG_DEVNUM;
++		dbgp_printk("debug device renamed to 127\n");
++	}
++
++	/* Enable the debug interface */
++	ret = dbgp_control_msg(USB_DEBUG_DEVNUM,
++		USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
++		USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0);
++	if (ret < 0) {
++		dbgp_printk(" Could not enable the debug device\n");
++		goto err;
++	}
++	dbgp_printk("debug interface enabled\n");
++
++	/* Perform a small write to get the even/odd data state in sync
++	 */
++	ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1);
++	if (ret < 0) {
++		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
++		goto err;
++	}
++	dbgp_printk("small write doned\n");
++
++	return 0;
++err:
++	/* Things didn't work so remove my claim */
++	ctrl = readl(&ehci_debug->control);
++	ctrl &= ~(DBGP_CLAIM | DBGP_OUT);
++	writel(ctrl, &ehci_debug->control);
++	return -1;
++
++next_debug_port:
++	port_map_tried |= (1<<(debug_port - 1));
++	new_debug_port = ((debug_port-1+1)%n_ports) + 1;
++	if (port_map_tried != ((1<<n_ports) - 1)) {
++		set_debug_port(new_debug_port);
++		goto try_next_port;
++	}
++	if (--playtimes) {
++		set_debug_port(new_debug_port);
++		goto try_next_time;
++	}
++
++	return -1;
++}
++
++static int __init early_dbgp_init(char *s)
++{
++	u32 debug_port, bar, offset;
++	u32 bus, slot, func, cap;
++	void __iomem *ehci_bar;
++	u32 dbgp_num;
++	u32 bar_val;
++	char *e;
++	int ret;
++	u8 byte;
++
++	if (!early_pci_allowed())
++		return -1;
++
++	dbgp_num = 0;
++	if (*s)
++		dbgp_num = simple_strtoul(s, &e, 10);
++	dbgp_printk("dbgp_num: %d\n", dbgp_num);
++
++	cap = find_dbgp(dbgp_num, &bus, &slot, &func);
++	if (!cap)
++		return -1;
++
++	dbgp_printk("Found EHCI debug port on %02x:%02x.%1x\n", bus, slot,
++			 func);
++
++	debug_port = read_pci_config(bus, slot, func, cap);
++	bar = (debug_port >> 29) & 0x7;
++	bar = (bar * 4) + 0xc;
++	offset = (debug_port >> 16) & 0xfff;
++	dbgp_printk("bar: %02x offset: %03x\n", bar, offset);
++	if (bar != PCI_BASE_ADDRESS_0) {
++		dbgp_printk("only debug ports on bar 1 handled.\n");
++
++		return -1;
++	}
++
++	bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
++	dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset);
++	if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) {
++		dbgp_printk("only simple 32bit mmio bars supported\n");
++
++		return -1;
++	}
++
++	/* double check if the mem space is enabled */
++	byte = read_pci_config_byte(bus, slot, func, 0x04);
++	if (!(byte & 0x2)) {
++		byte  |= 0x02;
++		write_pci_config_byte(bus, slot, func, 0x04, byte);
++		dbgp_printk("mmio for ehci enabled\n");
++	}
++
++	/*
++	 * FIXME I don't have the bar size so just guess PAGE_SIZE is more
++	 * than enough.  1K is the biggest I have seen.
++	 */
++	set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK);
++	ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE);
++	ehci_bar += bar_val & ~PAGE_MASK;
++	dbgp_printk("ehci_bar: %p\n", ehci_bar);
++
++	ehci_caps  = ehci_bar;
++	ehci_regs  = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
++	ehci_debug = ehci_bar + offset;
++	ehci_dev.bus = bus;
++	ehci_dev.slot = slot;
++	ehci_dev.func = func;
++
++	detect_set_debug_port();
++
++	ret = ehci_setup();
++	if (ret < 0) {
++		dbgp_printk("ehci_setup failed\n");
++		ehci_debug = NULL;
++
++		return -1;
++	}
++
++	return 0;
++}
++
++static void early_dbgp_write(struct console *con, const char *str, u32 n)
++{
++	int chunk, ret;
++
++	if (!ehci_debug)
++		return;
++	while (n > 0) {
++		chunk = n;
++		if (chunk > DBGP_MAX_PACKET)
++			chunk = DBGP_MAX_PACKET;
++		ret = dbgp_bulk_write(USB_DEBUG_DEVNUM,
++			dbgp_endpoint_out, str, chunk);
++		str += chunk;
++		n -= chunk;
++	}
++}
++
++static struct console early_dbgp_console = {
++	.name =		"earlydbg",
++	.write =	early_dbgp_write,
++	.flags =	CON_PRINTBUFFER,
++	.index =	-1,
++};
++#endif
++
+ /* Console interface to a host file on AMD's SimNow! */
+ 
+ static int simnow_fd;
+@@ -194,6 +918,7 @@ enum {
+ static noinline long simnow(long cmd, long a, long b, long c)
+ {
+ 	long ret;
++
+ 	asm volatile("cpuid" :
+ 		     "=a" (ret) :
+ 		     "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+@@ -203,6 +928,7 @@ static noinline long simnow(long cmd, lo
+ static void __init simnow_init(char *str)
+ {
+ 	char *fn = "klog";
++
+ 	if (*str == '=')
+ 		fn = ++str;
+ 	/* error ignored */
+@@ -223,7 +949,7 @@ static struct console simnow_console = {
+ 
+ /* Direct interface for emergencies */
+ static struct console *early_console = &early_vga_console;
+-static int early_console_initialized;
++static int __initdata early_console_initialized;
+ 
+ asmlinkage void early_printk(const char *fmt, ...)
+ {
+@@ -237,10 +963,11 @@ asmlinkage void early_printk(const char 
+ 	va_end(ap);
+ }
+ 
+-static int __initdata keep_early;
+ 
+ static int __init setup_early_printk(char *buf)
+ {
++	int keep_early;
++
+ 	if (!buf)
+ 		return 0;
+ 
+@@ -248,8 +975,7 @@ static int __init setup_early_printk(cha
+ 		return 0;
+ 	early_console_initialized = 1;
+ 
+-	if (strstr(buf, "keep"))
+-		keep_early = 1;
++	keep_early = (strstr(buf, "keep") != NULL);
+ 
+ 	if (!strncmp(buf, "serial", 6)) {
+ 		early_serial_init(buf + 6);
+@@ -269,6 +995,17 @@ static int __init setup_early_printk(cha
+ 		simnow_init(buf + 6);
+ 		early_console = &simnow_console;
+ 		keep_early = 1;
++#ifdef CONFIG_EARLY_PRINTK_DBGP
++	} else if (!strncmp(buf, "dbgp", 4)) {
++		if (early_dbgp_init(buf+4) < 0)
++			return 0;
++		early_console = &early_dbgp_console;
++		/*
++		 * usb subsys will reset ehci controller, so don't keep
++		 * that early console
++		 */
++		keep_early = 0;
++#endif
+ #ifdef CONFIG_XEN
+ 	} else if (!strncmp(buf, "xen", 3)) {
+ 		early_console = &xenboot_console;
+@@ -282,4 +1019,5 @@ static int __init setup_early_printk(cha
+ 	register_console(early_console);
+ 	return 0;
+ }
++
+ early_param("earlyprintk", setup_early_printk);
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:47.000000000 +0100
+@@ -700,7 +700,7 @@ ENTRY(interrupt)
+ ENTRY(irq_entries_start)
+ 	RING0_INT_FRAME
+ vector=0
+-.rept NR_IRQS
++.rept NR_VECTORS
+ 	ALIGN
+  .if vector
+ 	CFI_ADJUST_CFA_OFFSET -4
+@@ -805,6 +805,7 @@ error_code:
+ 	movl $(__USER_DS), %ecx
+ 	movl %ecx, %ds
+ 	movl %ecx, %es
++	TRACE_IRQS_OFF
+ 	movl %esp,%eax			# pt_regs pointer
+ 	call *%edi
+ 	jmp ret_from_exception
+@@ -974,22 +975,9 @@ ENTRY(device_not_available)
+ 	RING0_INT_FRAME
+ 	pushl $-1			# mark this as an int
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	SAVE_ALL
+-#ifndef CONFIG_XEN
+-	GET_CR0_INTO_EAX
+-	testl $0x4, %eax		# EM (math emulation bit)
+-	je device_available_emulate
+-	pushl $0			# temporary storage for ORIG_EIP
++	pushl $do_device_not_available
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	call math_emulate
+-	addl $4, %esp
+-	CFI_ADJUST_CFA_OFFSET -4
+-	jmp ret_from_exception
+-device_available_emulate:
+-#endif
+-	preempt_stop(CLBR_ANY)
+-	call math_state_restore
+-	jmp ret_from_exception
++	jmp error_code
+ 	CFI_ENDPROC
+ END(device_not_available)
+ 
+@@ -1034,6 +1022,7 @@ debug_stack_correct:
+ 	pushl $-1			# mark this as an int
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
++	TRACE_IRQS_OFF
+ 	xorl %edx,%edx			# error code 0
+ 	movl %esp,%eax			# pt_regs pointer
+ 	call do_debug
+@@ -1079,6 +1068,7 @@ nmi_stack_correct:
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
++	TRACE_IRQS_OFF
+ 	xorl %edx,%edx		# zero error code
+ 	movl %esp,%eax		# pt_regs pointer
+ 	call do_nmi
+@@ -1119,6 +1109,7 @@ nmi_espfix_stack:
+ 	pushl %eax
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
++	TRACE_IRQS_OFF
+ 	FIXUP_ESPFIX_STACK		# %eax == %esp
+ 	xorl %edx,%edx			# zero error code
+ 	call do_nmi
+@@ -1162,6 +1153,7 @@ KPROBE_ENTRY(int3)
+ 	pushl $-1			# mark this as an int
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	SAVE_ALL
++	TRACE_IRQS_OFF
+ 	xorl %edx,%edx		# zero error code
+ 	movl %esp,%eax		# pt_regs pointer
+ 	call do_int3
+@@ -1303,24 +1295,10 @@ ENTRY(kernel_thread_helper)
+ 	CFI_ENDPROC
+ ENDPROC(kernel_thread_helper)
+ 
+-#ifdef CONFIG_FTRACE
++#ifdef CONFIG_FUNCTION_TRACER
+ #ifdef CONFIG_DYNAMIC_FTRACE
+ 
+ ENTRY(mcount)
+-	pushl %eax
+-	pushl %ecx
+-	pushl %edx
+-	movl 0xc(%esp), %eax
+-	subl $MCOUNT_INSN_SIZE, %eax
+-
+-.globl mcount_call
+-mcount_call:
+-	call ftrace_stub
+-
+-	popl %edx
+-	popl %ecx
+-	popl %eax
+-
+ 	ret
+ END(mcount)
+ 
+@@ -1372,7 +1350,7 @@ trace:
+ 	jmp ftrace_stub
+ END(mcount)
+ #endif /* CONFIG_DYNAMIC_FTRACE */
+-#endif /* CONFIG_FTRACE */
++#endif /* CONFIG_FUNCTION_TRACER */
+ 
+ #include <asm/alternative-asm.h>
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:47.000000000 +0100
+@@ -66,35 +66,9 @@
+ 
+ 	.code64
+ 
+-#ifdef CONFIG_FTRACE
++#ifdef CONFIG_FUNCTION_TRACER
+ #ifdef CONFIG_DYNAMIC_FTRACE
+ ENTRY(mcount)
+-
+-	subq $0x38, %rsp
+-	movq %rax, (%rsp)
+-	movq %rcx, 8(%rsp)
+-	movq %rdx, 16(%rsp)
+-	movq %rsi, 24(%rsp)
+-	movq %rdi, 32(%rsp)
+-	movq %r8, 40(%rsp)
+-	movq %r9, 48(%rsp)
+-
+-	movq 0x38(%rsp), %rdi
+-	subq $MCOUNT_INSN_SIZE, %rdi
+-
+-.globl mcount_call
+-mcount_call:
+-	call ftrace_stub
+-
+-	movq 48(%rsp), %r9
+-	movq 40(%rsp), %r8
+-	movq 32(%rsp), %rdi
+-	movq 24(%rsp), %rsi
+-	movq 16(%rsp), %rdx
+-	movq 8(%rsp), %rcx
+-	movq (%rsp), %rax
+-	addq $0x38, %rsp
+-
+ 	retq
+ END(mcount)
+ 
+@@ -169,7 +143,7 @@ trace:
+ 	jmp ftrace_stub
+ END(mcount)
+ #endif /* CONFIG_DYNAMIC_FTRACE */
+-#endif /* CONFIG_FTRACE */
++#endif /* CONFIG_FUNCTION_TRACER */
+ 
+ #ifndef CONFIG_PREEMPT
+ #define retint_kernel retint_restore_args
+@@ -303,9 +277,9 @@ NMI_MASK = 0x80000000
+ ENTRY(ret_from_fork)
+ 	CFI_DEFAULT_STACK
+ 	push kernel_eflags(%rip)
+-	CFI_ADJUST_CFA_OFFSET 4
++	CFI_ADJUST_CFA_OFFSET 8
+ 	popf				# reset kernel eflags
+-	CFI_ADJUST_CFA_OFFSET -4
++	CFI_ADJUST_CFA_OFFSET -8
+ 	call schedule_tail
+ 	GET_THREAD_INFO(%rcx)
+ 	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+@@ -869,6 +843,9 @@ END(spurious_interrupt)
+ 	.if \ist
+ 	movq	%gs:pda_data_offset, %rbp
+ 	.endif
++	.if \irqtrace
++	TRACE_IRQS_OFF
++	.endif
+ 	movq %rsp,%rdi
+ 	movq ORIG_RAX(%rsp),%rsi
+ 	movq $-1,ORIG_RAX(%rsp)
+@@ -1277,7 +1254,7 @@ ENTRY(simd_coprocessor_error)
+ END(simd_coprocessor_error)
+ 
+ ENTRY(device_not_available)
+-	zeroentry math_state_restore
++	zeroentry do_device_not_available
+ END(device_not_available)
+ 
+ 	/* runs on exception stack */
+@@ -1376,9 +1353,11 @@ ENTRY(divide_error)
+ 	zeroentry do_divide_error
+ END(divide_error)
+ 
++#ifndef CONFIG_XEN
+ ENTRY(spurious_interrupt_bug)
+ 	zeroentry do_spurious_interrupt_bug
+ END(spurious_interrupt_bug)
++#endif
+ 
+ #ifdef CONFIG_X86_MCE
+ 	/* runs on exception stack */
+--- head-2010-01-18.orig/arch/x86/kernel/fixup.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/fixup.c	2009-11-06 10:51:47.000000000 +0100
+@@ -37,7 +37,7 @@
+ 
+ #define DP(_f, _args...) printk(KERN_ALERT "  " _f "\n" , ## _args )
+ 
+-void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
++dotraplinkage void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
+ {
+ 	static unsigned long printed = 0;
+ 	char info[100];
+--- head-2010-01-18.orig/arch/x86/kernel/head-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -36,6 +36,7 @@ void __init reserve_ebda_region(void)
+ 
+ 	/* start of EBDA area */
+ 	ebda_addr = get_bios_ebda();
++	printk(KERN_INFO "BIOS EBDA/lowmem at: %08x/%08x\n", ebda_addr, lowmem);
+ 
+ 	/* Fixup: bios puts an EBDA in the top 64K segment */
+ 	/* of conventional memory, but does not adjust lowmem. */
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -151,12 +151,11 @@ void __init x86_64_start_kernel(char * r
+ 	load_idt((const struct desc_ptr *)&idt_descr);
+ #endif
+ 
+-	early_printk("Kernel alive\n");
++	if (console_loglevel == 10)
++		early_printk("Kernel alive\n");
+ 
+ 	x86_64_init_pda();
+ 
+-	early_printk("Kernel really alive\n");
+-
+ 	x86_64_start_reservations(real_mode_data);
+ }
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/apic/io_apic-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,3949 @@
++/*
++ *	Intel IO-APIC support for multi-Pentium hosts.
++ *
++ *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
++ *
++ *	Many thanks to Stig Venaas for trying out countless experimental
++ *	patches and reporting/debugging problems patiently!
++ *
++ *	(c) 1999, Multiple IO-APIC support, developed by
++ *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
++ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
++ *	further tested and cleaned up by Zach Brown <zab@redhat.com>
++ *	and Ingo Molnar <mingo@redhat.com>
++ *
++ *	Fixes
++ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
++ *					thanks to Eric Gilmore
++ *					and Rolf G. Tews
++ *					for testing these extensively
++ *	Paul Diefenbaugh	:	Added full ACPI support
++ */
++
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/pci.h>
++#include <linux/mc146818rtc.h>
++#include <linux/compiler.h>
++#include <linux/acpi.h>
++#include <linux/module.h>
++#include <linux/sysdev.h>
++#include <linux/msi.h>
++#include <linux/htirq.h>
++#include <linux/freezer.h>
++#include <linux/kthread.h>
++#include <linux/jiffies.h>	/* time_after() */
++#ifdef CONFIG_ACPI
++#include <acpi/acpi_bus.h>
++#endif
++#include <linux/bootmem.h>
++#include <linux/dmar.h>
++#include <linux/hpet.h>
++
++#include <asm/idle.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/desc.h>
++#include <asm/proto.h>
++#include <asm/acpi.h>
++#include <asm/dma.h>
++#include <asm/timer.h>
++#include <asm/i8259.h>
++#include <asm/nmi.h>
++#include <asm/msidef.h>
++#include <asm/hypertransport.h>
++#include <asm/setup.h>
++#include <asm/irq_remapping.h>
++#include <asm/hpet.h>
++#include <asm/uv/uv_hub.h>
++#include <asm/uv/uv_irq.h>
++
++#include <mach_ipi.h>
++#include <mach_apic.h>
++#include <mach_apicdef.h>
++
++#ifdef CONFIG_XEN
++#include <xen/interface/xen.h>
++#include <xen/interface/physdev.h>
++#include <xen/evtchn.h>
++
++/* Fake i8259 */
++#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
++#define disable_8259A_irq(_irq)  ((void)0)
++#define i8259A_irq_pending(_irq) (0)
++
++unsigned long io_apic_irqs;
++#endif /* CONFIG_XEN */
++
++#define __apicdebuginit(type) static type __init
++
++/*
++ *      Is the SiS APIC rmw bug present ?
++ *      -1 = don't know, 0 = no, 1 = yes
++ */
++int sis_apic_bug = -1;
++
++static DEFINE_SPINLOCK(ioapic_lock);
++#ifndef CONFIG_XEN
++static DEFINE_SPINLOCK(vector_lock);
++#endif
++
++/*
++ * # of IRQ routing registers
++ */
++int nr_ioapic_registers[MAX_IO_APICS];
++
++/* I/O APIC entries */
++struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
++int nr_ioapics;
++
++/* MP IRQ source entries */
++struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
++
++/* # of MP IRQ source entries */
++int mp_irq_entries;
++
++#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
++int mp_bus_id_to_type[MAX_MP_BUSSES];
++#endif
++
++DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
++
++int skip_ioapic_setup;
++
++static int __init parse_noapic(char *str)
++{
++	/* disable IO-APIC */
++	disable_ioapic_setup();
++	return 0;
++}
++early_param("noapic", parse_noapic);
++
++struct irq_pin_list;
++struct irq_cfg {
++#ifndef CONFIG_XEN
++	unsigned int irq;
++	struct irq_pin_list *irq_2_pin;
++	cpumask_t domain;
++	cpumask_t old_domain;
++	unsigned move_cleanup_count;
++#endif
++	u8 vector;
++#ifndef CONFIG_XEN
++	u8 move_in_progress : 1;
++#endif
++};
++
++/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
++static struct irq_cfg irq_cfgx[NR_IRQS] = {
++	[0]  = { .irq =  0 },
++	[1]  = { .irq =  1 },
++	[2]  = { .irq =  2 },
++	[3]  = { .irq =  3 },
++	[4]  = { .irq =  4 },
++	[5]  = { .irq =  5 },
++	[6]  = { .irq =  6 },
++	[7]  = { .irq =  7 },
++	[8]  = { .irq =  8 },
++	[9]  = { .irq =  9 },
++	[10] = { .irq = 10 },
++	[11] = { .irq = 11 },
++	[12] = { .irq = 12 },
++	[13] = { .irq = 13 },
++	[14] = { .irq = 14 },
++	[15] = { .irq = 15 },
++};
++
++#define for_each_irq_cfg(irq, cfg)		\
++	for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)
++
++static struct irq_cfg *irq_cfg(unsigned int irq)
++{
++	return irq < nr_irqs ? irq_cfgx + irq : NULL;
++}
++
++static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
++{
++	return irq_cfg(irq);
++}
++
++#ifdef CONFIG_XEN
++#define irq_2_pin_init()
++#define add_pin_to_irq(irq, apic, pin)
++#else
++/*
++ * Rough estimation of how many shared IRQs there are, can be changed
++ * anytime.
++ */
++#define MAX_PLUS_SHARED_IRQS NR_IRQS
++#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
++
++/*
++ * This is performance-critical, we want to do it O(1)
++ *
++ * the indexing order of this array favors 1:1 mappings
++ * between pins and IRQs.
++ */
++
++struct irq_pin_list {
++	int apic, pin;
++	struct irq_pin_list *next;
++};
++
++static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];
++static struct irq_pin_list *irq_2_pin_ptr;
++
++static void __init irq_2_pin_init(void)
++{
++	struct irq_pin_list *pin = irq_2_pin_head;
++	int i;
++
++	for (i = 1; i < PIN_MAP_SIZE; i++)
++		pin[i-1].next = &pin[i];
++
++	irq_2_pin_ptr = &pin[0];
++}
++
++static struct irq_pin_list *get_one_free_irq_2_pin(void)
++{
++	struct irq_pin_list *pin = irq_2_pin_ptr;
++
++	if (!pin)
++		panic("can not get more irq_2_pin\n");
++
++	irq_2_pin_ptr = pin->next;
++	pin->next = NULL;
++	return pin;
++}
++
++struct io_apic {
++	unsigned int index;
++	unsigned int unused[3];
++	unsigned int data;
++};
++
++static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
++{
++	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
++		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
++}
++#endif
++
++static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
++{
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	return readl(&io_apic->data);
++#else
++	struct physdev_apic apic_op;
++	int ret;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
++	apic_op.reg = reg;
++	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
++	if (ret)
++		return ret;
++	return apic_op.value;
++#endif
++}
++
++static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
++{
++#ifndef CONFIG_XEN
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++	writel(reg, &io_apic->index);
++	writel(value, &io_apic->data);
++#else
++	struct physdev_apic apic_op;
++
++	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
++	apic_op.reg = reg;
++	apic_op.value = value;
++	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
++#endif
++}
++
++#ifdef CONFIG_XEN
++#define io_apic_modify io_apic_write
++#else
++/*
++ * Re-write a value: to be used for read-modify-write
++ * cycles where the read already set up the index register.
++ *
++ * Older SiS APIC requires we rewrite the index register
++ */
++static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
++{
++	struct io_apic __iomem *io_apic = io_apic_base(apic);
++
++	if (sis_apic_bug)
++		writel(reg, &io_apic->index);
++	writel(value, &io_apic->data);
++}
++
++static bool io_apic_level_ack_pending(unsigned int irq)
++{
++	struct irq_pin_list *entry;
++	unsigned long flags;
++	struct irq_cfg *cfg = irq_cfg(irq);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	entry = cfg->irq_2_pin;
++	for (;;) {
++		unsigned int reg;
++		int pin;
++
++		if (!entry)
++			break;
++		pin = entry->pin;
++		reg = io_apic_read(entry->apic, 0x10 + pin*2);
++		/* Is the remote IRR bit set? */
++		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
++			spin_unlock_irqrestore(&ioapic_lock, flags);
++			return true;
++		}
++		if (!entry->next)
++			break;
++		entry = entry->next;
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return false;
++}
++#endif /* CONFIG_XEN */
++
++union entry_union {
++	struct { u32 w1, w2; };
++	struct IO_APIC_route_entry entry;
++};
++
++#ifndef CONFIG_XEN
++static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
++{
++	union entry_union eu;
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
++	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	return eu.entry;
++}
++#endif
++
++/*
++ * When we write a new IO APIC routing entry, we need to write the high
++ * word first! If the mask bit in the low word is clear, we will enable
++ * the interrupt, and we need to make sure the entry is fully populated
++ * before that happens.
++ */
++static void
++__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	union entry_union eu;
++	eu.entry = e;
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++}
++
++static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
++{
++	unsigned long flags;
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__ioapic_write_entry(apic, pin, e);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#ifndef CONFIG_XEN
++/*
++ * When we mask an IO APIC routing entry, we need to write the low
++ * word first, in order to set the mask bit before we change the
++ * high bits!
++ */
++static void ioapic_mask_entry(int apic, int pin)
++{
++	unsigned long flags;
++	union entry_union eu = { .entry.mask = 1 };
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
++	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++#ifdef CONFIG_SMP
++static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
++{
++	int apic, pin;
++	struct irq_cfg *cfg;
++	struct irq_pin_list *entry;
++
++	cfg = irq_cfg(irq);
++	entry = cfg->irq_2_pin;
++	for (;;) {
++		unsigned int reg;
++
++		if (!entry)
++			break;
++
++		apic = entry->apic;
++		pin = entry->pin;
++#ifdef CONFIG_INTR_REMAP
++		/*
++		 * With interrupt-remapping, destination information comes
++		 * from interrupt-remapping table entry.
++		 */
++		if (!irq_remapped(irq))
++			io_apic_write(apic, 0x11 + pin*2, dest);
++#else
++		io_apic_write(apic, 0x11 + pin*2, dest);
++#endif
++		reg = io_apic_read(apic, 0x10 + pin*2);
++		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
++		reg |= vector;
++		io_apic_modify(apic, 0x10 + pin*2, reg);
++		if (!entry->next)
++			break;
++		entry = entry->next;
++	}
++}
++
++static int assign_irq_vector(int irq, cpumask_t mask);
++
++static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	unsigned long flags;
++	unsigned int dest;
++	cpumask_t tmp;
++	struct irq_desc *desc;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	cfg = irq_cfg(irq);
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++	/*
++	 * Only the high 8 bits are valid.
++	 */
++	dest = SET_APIC_LOGICAL_ID(dest);
++
++	desc = irq_to_desc(irq);
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__target_IO_APIC_irq(irq, dest, cfg->vector);
++	desc->affinity = mask;
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++#endif /* CONFIG_SMP */
++
++/*
++ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
++ * shared ISA-space IRQs, so we have to support them. We are super
++ * fast in the common case, and fast for shared ISA-space IRQs.
++ */
++static void add_pin_to_irq(unsigned int irq, int apic, int pin)
++{
++	struct irq_cfg *cfg;
++	struct irq_pin_list *entry;
++
++	/* first time to refer irq_cfg, so with new */
++	cfg = irq_cfg_alloc(irq);
++	entry = cfg->irq_2_pin;
++	if (!entry) {
++		entry = get_one_free_irq_2_pin();
++		cfg->irq_2_pin = entry;
++		entry->apic = apic;
++		entry->pin = pin;
++		return;
++	}
++
++	while (entry->next) {
++		/* not again, please */
++		if (entry->apic == apic && entry->pin == pin)
++			return;
++
++		entry = entry->next;
++	}
++
++	entry->next = get_one_free_irq_2_pin();
++	entry = entry->next;
++	entry->apic = apic;
++	entry->pin = pin;
++}
++
++/*
++ * Reroute an IRQ to a different pin.
++ */
++static void __init replace_pin_at_irq(unsigned int irq,
++				      int oldapic, int oldpin,
++				      int newapic, int newpin)
++{
++	struct irq_cfg *cfg = irq_cfg(irq);
++	struct irq_pin_list *entry = cfg->irq_2_pin;
++	int replaced = 0;
++
++	while (entry) {
++		if (entry->apic == oldapic && entry->pin == oldpin) {
++			entry->apic = newapic;
++			entry->pin = newpin;
++			replaced = 1;
++			/* every one is different, right? */
++			break;
++		}
++		entry = entry->next;
++	}
++
++	/* why? call replace before add? */
++	if (!replaced)
++		add_pin_to_irq(irq, newapic, newpin);
++}
++
++static inline void io_apic_modify_irq(unsigned int irq,
++				int mask_and, int mask_or,
++				void (*final)(struct irq_pin_list *entry))
++{
++	int pin;
++	struct irq_cfg *cfg;
++	struct irq_pin_list *entry;
++
++	cfg = irq_cfg(irq);
++	for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
++		unsigned int reg;
++		pin = entry->pin;
++		reg = io_apic_read(entry->apic, 0x10 + pin * 2);
++		reg &= mask_and;
++		reg |= mask_or;
++		io_apic_modify(entry->apic, 0x10 + pin * 2, reg);
++		if (final)
++			final(entry);
++	}
++}
++
++static void __unmask_IO_APIC_irq(unsigned int irq)
++{
++	io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL);
++}
++
++#ifdef CONFIG_X86_64
++void io_apic_sync(struct irq_pin_list *entry)
++{
++	/*
++	 * Synchronize the IO-APIC and the CPU by doing
++	 * a dummy read from the IO-APIC
++	 */
++	struct io_apic __iomem *io_apic;
++	io_apic = io_apic_base(entry->apic);
++	readl(&io_apic->data);
++}
++
++static void __mask_IO_APIC_irq(unsigned int irq)
++{
++	io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
++}
++#else /* CONFIG_X86_32 */
++static void __mask_IO_APIC_irq(unsigned int irq)
++{
++	io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL);
++}
++
++static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
++{
++	io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER,
++			IO_APIC_REDIR_MASKED, NULL);
++}
++
++static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
++{
++	io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED,
++			IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
++}
++#endif /* CONFIG_X86_32 */
++
++static void mask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__mask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void unmask_IO_APIC_irq (unsigned int irq)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++}
++
++static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
++{
++	struct IO_APIC_route_entry entry;
++
++	/* Check delivery_mode to be sure we're not clearing an SMI pin */
++	entry = ioapic_read_entry(apic, pin);
++	if (entry.delivery_mode == dest_SMI)
++		return;
++	/*
++	 * Disable it in the IO-APIC irq-routing table:
++	 */
++	ioapic_mask_entry(apic, pin);
++}
++
++static void clear_IO_APIC (void)
++{
++	int apic, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++)
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
++			clear_IO_APIC_pin(apic, pin);
++}
++
++#if !defined(CONFIG_SMP) && defined(CONFIG_X86_32)
++void send_IPI_self(int vector)
++{
++	unsigned int cfg;
++
++	/*
++	 * Wait for idle.
++	 */
++	apic_wait_icr_idle();
++	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
++	/*
++	 * Send the IPI. The write to APIC_ICR fires this off.
++	 */
++	apic_write(APIC_ICR, cfg);
++}
++#endif /* !CONFIG_SMP && CONFIG_X86_32*/
++#endif /* CONFIG_XEN */
++
++#ifdef CONFIG_X86_32
++/*
++ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
++ * specific CPU-side IRQs.
++ */
++
++#define MAX_PIRQS 8
++static int pirq_entries [MAX_PIRQS];
++static int pirqs_enabled;
++
++static int __init ioapic_pirq_setup(char *str)
++{
++	int i, max;
++	int ints[MAX_PIRQS+1];
++
++	get_options(str, ARRAY_SIZE(ints), ints);
++
++	for (i = 0; i < MAX_PIRQS; i++)
++		pirq_entries[i] = -1;
++
++	pirqs_enabled = 1;
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"PIRQ redirection, working around broken MP-BIOS.\n");
++	max = MAX_PIRQS;
++	if (ints[0] < MAX_PIRQS)
++		max = ints[0];
++
++	for (i = 0; i < max; i++) {
++		apic_printk(APIC_VERBOSE, KERN_DEBUG
++				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
++		/*
++		 * PIRQs are mapped upside down, usually.
++		 */
++		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
++	}
++	return 1;
++}
++
++__setup("pirq=", ioapic_pirq_setup);
++#endif /* CONFIG_X86_32 */
++
++#ifdef CONFIG_INTR_REMAP
++/* I/O APIC RTE contents at the OS boot up */
++static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
++
++/*
++ * Saves and masks all the unmasked IO-APIC RTE's
++ */
++int save_mask_IO_APIC_setup(void)
++{
++	union IO_APIC_reg_01 reg_01;
++	unsigned long flags;
++	int apic, pin;
++
++	/*
++	 * The number of IO-APIC IRQ registers (== #pins):
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_01.raw = io_apic_read(apic, 1);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
++	}
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		early_ioapic_entries[apic] =
++			kzalloc(sizeof(struct IO_APIC_route_entry) *
++				nr_ioapic_registers[apic], GFP_KERNEL);
++		if (!early_ioapic_entries[apic])
++			goto nomem;
++	}
++
++	for (apic = 0; apic < nr_ioapics; apic++)
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			struct IO_APIC_route_entry entry;
++
++			entry = early_ioapic_entries[apic][pin] =
++				ioapic_read_entry(apic, pin);
++			if (!entry.mask) {
++				entry.mask = 1;
++				ioapic_write_entry(apic, pin, entry);
++			}
++		}
++
++	return 0;
++
++nomem:
++	while (apic >= 0)
++		kfree(early_ioapic_entries[apic--]);
++	memset(early_ioapic_entries, 0,
++		ARRAY_SIZE(early_ioapic_entries));
++
++	return -ENOMEM;
++}
++
++void restore_IO_APIC_setup(void)
++{
++	int apic, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		if (!early_ioapic_entries[apic])
++			break;
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
++			ioapic_write_entry(apic, pin,
++					   early_ioapic_entries[apic][pin]);
++		kfree(early_ioapic_entries[apic]);
++		early_ioapic_entries[apic] = NULL;
++	}
++}
++
++void reinit_intr_remapped_IO_APIC(int intr_remapping)
++{
++	/*
++	 * for now plain restore of previous settings.
++	 * TBD: In the case of OS enabling interrupt-remapping,
++	 * IO-APIC RTE's need to be setup to point to interrupt-remapping
++	 * table entries. for now, do a plain restore, and wait for
++	 * the setup_IO_APIC_irqs() to do proper initialization.
++	 */
++	restore_IO_APIC_setup();
++}
++#endif
++
++/*
++ * Find the IRQ entry number of a certain pin.
++ */
++static int find_irq_entry(int apic, int pin, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mp_irqtype == type &&
++		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
++		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
++		    mp_irqs[i].mp_dstirq == pin)
++			return i;
++
++	return -1;
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Find the pin to which IRQ[irq] (ISA) is connected
++ */
++static int __init find_isa_irq_pin(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mp_srcbus;
++
++		if (test_bit(lbus, mp_bus_not_pci) &&
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
++
++			return mp_irqs[i].mp_dstirq;
++	}
++	return -1;
++}
++
++static int __init find_isa_irq_apic(int irq, int type)
++{
++	int i;
++
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mp_srcbus;
++
++		if (test_bit(lbus, mp_bus_not_pci) &&
++		    (mp_irqs[i].mp_irqtype == type) &&
++		    (mp_irqs[i].mp_srcbusirq == irq))
++			break;
++	}
++	if (i < mp_irq_entries) {
++		int apic;
++		for(apic = 0; apic < nr_ioapics; apic++) {
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
++				return apic;
++		}
++	}
++
++	return -1;
++}
++#endif
++
++/*
++ * Find a specific PCI IRQ entry.
++ * Not an __init, possibly needed by modules
++ */
++static int pin_2_irq(int idx, int apic, int pin);
++
++int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
++{
++	int apic, i, best_guess = -1;
++
++	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
++		bus, slot, pin);
++	if (test_bit(bus, mp_bus_not_pci)) {
++		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
++		return -1;
++	}
++	for (i = 0; i < mp_irq_entries; i++) {
++		int lbus = mp_irqs[i].mp_srcbus;
++
++		for (apic = 0; apic < nr_ioapics; apic++)
++			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
++			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
++				break;
++
++		if (!test_bit(lbus, mp_bus_not_pci) &&
++		    !mp_irqs[i].mp_irqtype &&
++		    (bus == lbus) &&
++		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
++			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
++
++			if (!(apic || IO_APIC_IRQ(irq)))
++				continue;
++
++			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
++				return irq;
++			/*
++			 * Use the first all-but-pin matching entry as a
++			 * best-guess fuzzy result for broken mptables.
++			 */
++			if (best_guess < 0)
++				best_guess = irq;
++		}
++	}
++	return best_guess;
++}
++
++EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
++
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
++/*
++ * EISA Edge/Level control register, ELCR
++ */
++static int EISA_ELCR(unsigned int irq)
++{
++	if (irq < 16) {
++		unsigned int port = 0x4d0 + (irq >> 3);
++		return (inb(port) >> (irq & 7)) & 1;
++	}
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"Broken MPtable reports ISA irq %d\n", irq);
++	return 0;
++}
++
++#endif
++
++/* ISA interrupts are always polarity zero edge triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_ISA_trigger(idx)	(0)
++#define default_ISA_polarity(idx)	(0)
++
++/* EISA interrupts are always polarity zero and can be edge or level
++ * trigger depending on the ELCR value.  If an interrupt is listed as
++ * EISA conforming in the MP table, that means its trigger type must
++ * be read in from the ELCR */
++
++#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
++#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
++
++/* PCI interrupts are always polarity one level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_PCI_trigger(idx)	(1)
++#define default_PCI_polarity(idx)	(1)
++
++/* MCA interrupts are always polarity zero level triggered,
++ * when listed as conforming in the MP table. */
++
++#define default_MCA_trigger(idx)	(1)
++#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
++
++static int MPBIOS_polarity(int idx)
++{
++	int bus = mp_irqs[idx].mp_srcbus;
++	int polarity;
++
++	/*
++	 * Determine IRQ line polarity (high active or low active):
++	 */
++	switch (mp_irqs[idx].mp_irqflag & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent polarity */
++			if (test_bit(bus, mp_bus_not_pci))
++				polarity = default_ISA_polarity(idx);
++			else
++				polarity = default_PCI_polarity(idx);
++			break;
++		case 1: /* high active */
++		{
++			polarity = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++		case 3: /* low active */
++		{
++			polarity = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			polarity = 1;
++			break;
++		}
++	}
++	return polarity;
++}
++
++static int MPBIOS_trigger(int idx)
++{
++	int bus = mp_irqs[idx].mp_srcbus;
++	int trigger;
++
++	/*
++	 * Determine IRQ trigger mode (edge or level sensitive):
++	 */
++	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
++	{
++		case 0: /* conforms, ie. bus-type dependent */
++			if (test_bit(bus, mp_bus_not_pci))
++				trigger = default_ISA_trigger(idx);
++			else
++				trigger = default_PCI_trigger(idx);
++#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
++			switch (mp_bus_id_to_type[bus]) {
++				case MP_BUS_ISA: /* ISA pin */
++				{
++					/* set before the switch */
++					break;
++				}
++				case MP_BUS_EISA: /* EISA pin */
++				{
++					trigger = default_EISA_trigger(idx);
++					break;
++				}
++				case MP_BUS_PCI: /* PCI pin */
++				{
++					/* set before the switch */
++					break;
++				}
++				case MP_BUS_MCA: /* MCA pin */
++				{
++					trigger = default_MCA_trigger(idx);
++					break;
++				}
++				default:
++				{
++					printk(KERN_WARNING "broken BIOS!!\n");
++					trigger = 1;
++					break;
++				}
++			}
++#endif
++			break;
++		case 1: /* edge */
++		{
++			trigger = 0;
++			break;
++		}
++		case 2: /* reserved */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 1;
++			break;
++		}
++		case 3: /* level */
++		{
++			trigger = 1;
++			break;
++		}
++		default: /* invalid */
++		{
++			printk(KERN_WARNING "broken BIOS!!\n");
++			trigger = 0;
++			break;
++		}
++	}
++	return trigger;
++}
++
++static inline int irq_polarity(int idx)
++{
++	return MPBIOS_polarity(idx);
++}
++
++static inline int irq_trigger(int idx)
++{
++	return MPBIOS_trigger(idx);
++}
++
++int (*ioapic_renumber_irq)(int ioapic, int irq);
++static int pin_2_irq(int idx, int apic, int pin)
++{
++	int irq, i;
++	int bus = mp_irqs[idx].mp_srcbus;
++
++	/*
++	 * Debugging check, we are in big trouble if this message pops up!
++	 */
++	if (mp_irqs[idx].mp_dstirq != pin)
++		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
++
++	if (test_bit(bus, mp_bus_not_pci)) {
++		irq = mp_irqs[idx].mp_srcbusirq;
++	} else {
++		/*
++		 * PCI IRQs are mapped in order
++		 */
++		i = irq = 0;
++		while (i < apic)
++			irq += nr_ioapic_registers[i++];
++		irq += pin;
++		/*
++                 * For MPS mode, so far only needed by ES7000 platform
++                 */
++		if (ioapic_renumber_irq)
++			irq = ioapic_renumber_irq(apic, irq);
++	}
++
++#ifdef CONFIG_X86_32
++	/*
++	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
++	 */
++	if ((pin >= 16) && (pin <= 23)) {
++		if (pirq_entries[pin-16] != -1) {
++			if (!pirq_entries[pin-16]) {
++				apic_printk(APIC_VERBOSE, KERN_DEBUG
++						"disabling PIRQ%d\n", pin-16);
++			} else {
++				irq = pirq_entries[pin-16];
++				apic_printk(APIC_VERBOSE, KERN_DEBUG
++						"using PIRQ%d -> IRQ %d\n",
++						pin-16, irq);
++			}
++		}
++	}
++#endif
++
++	return irq;
++}
++
++#ifndef CONFIG_XEN
++void lock_vector_lock(void)
++{
++	/* Used to the online set of cpus does not change
++	 * during assign_irq_vector.
++	 */
++	spin_lock(&vector_lock);
++}
++
++void unlock_vector_lock(void)
++{
++	spin_unlock(&vector_lock);
++}
++#endif
++
++static int assign_irq_vector(int irq, cpumask_t mask)
++{
++	struct physdev_irq irq_op;
++	struct irq_cfg *cfg;
++
++	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
++		return -EINVAL;
++
++	cfg = irq_cfg(irq);
++
++	if (cfg->vector)
++		return 0;
++
++	irq_op.irq = irq;
++	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
++		return -ENOSPC;
++
++	cfg->vector = irq_op.vector;
++
++	return 0;
++}
++
++#ifndef CONFIG_XEN
++static void __clear_irq_vector(int irq)
++{
++	struct irq_cfg *cfg;
++	cpumask_t mask;
++	int cpu, vector;
++
++	cfg = irq_cfg(irq);
++	BUG_ON(!cfg->vector);
++
++	vector = cfg->vector;
++	cpus_and(mask, cfg->domain, cpu_online_map);
++	for_each_cpu_mask_nr(cpu, mask)
++		per_cpu(vector_irq, cpu)[vector] = -1;
++
++	cfg->vector = 0;
++	cpus_clear(cfg->domain);
++
++	if (likely(!cfg->move_in_progress))
++		return;
++	cpus_and(mask, cfg->old_domain, cpu_online_map);
++	for_each_cpu_mask_nr(cpu, mask) {
++		for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
++								vector++) {
++			if (per_cpu(vector_irq, cpu)[vector] != irq)
++				continue;
++			per_cpu(vector_irq, cpu)[vector] = -1;
++			break;
++		}
++	}
++	cfg->move_in_progress = 0;
++}
++
++void __setup_vector_irq(int cpu)
++{
++	/* Initialize vector_irq on a new cpu */
++	/* This function must be called with vector_lock held */
++	int irq, vector;
++	struct irq_cfg *cfg;
++
++	/* Mark the inuse vectors */
++	for_each_irq_cfg(irq, cfg) {
++		if (!cpu_isset(cpu, cfg->domain))
++			continue;
++		vector = cfg->vector;
++		per_cpu(vector_irq, cpu)[vector] = irq;
++	}
++	/* Mark the free vectors */
++	for (vector = 0; vector < NR_VECTORS; ++vector) {
++		irq = per_cpu(vector_irq, cpu)[vector];
++		if (irq < 0)
++			continue;
++
++		cfg = irq_cfg(irq);
++		if (!cpu_isset(cpu, cfg->domain))
++			per_cpu(vector_irq, cpu)[vector] = -1;
++	}
++}
++
++static struct irq_chip ioapic_chip;
++#ifdef CONFIG_INTR_REMAP
++static struct irq_chip ir_ioapic_chip;
++#endif
++
++#define IOAPIC_AUTO     -1
++#define IOAPIC_EDGE     0
++#define IOAPIC_LEVEL    1
++
++#ifdef CONFIG_X86_32
++static inline int IO_APIC_irq_trigger(int irq)
++{
++	int apic, idx, pin;
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			idx = find_irq_entry(apic, pin, mp_INT);
++			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
++				return irq_trigger(idx);
++		}
++	}
++	/*
++         * nonexistent IRQs are edge default
++         */
++	return 0;
++}
++#else
++static inline int IO_APIC_irq_trigger(int irq)
++{
++	return 1;
++}
++#endif
++
++static void ioapic_register_intr(int irq, unsigned long trigger)
++{
++	struct irq_desc *desc;
++
++	desc = irq_to_desc(irq);
++
++	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++	    trigger == IOAPIC_LEVEL)
++		desc->status |= IRQ_LEVEL;
++	else
++		desc->status &= ~IRQ_LEVEL;
++
++#ifdef CONFIG_INTR_REMAP
++	if (irq_remapped(irq)) {
++		desc->status |= IRQ_MOVE_PCNTXT;
++		if (trigger)
++			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
++						      handle_fasteoi_irq,
++						     "fasteoi");
++		else
++			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
++						      handle_edge_irq, "edge");
++		return;
++	}
++#endif
++	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++	    trigger == IOAPIC_LEVEL)
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					      handle_fasteoi_irq,
++					      "fasteoi");
++	else
++		set_irq_chip_and_handler_name(irq, &ioapic_chip,
++					      handle_edge_irq, "edge");
++}
++#else /* !CONFIG_XEN */
++#define __clear_irq_vector(irq) ((void)(irq))
++#define ioapic_register_intr(irq, trigger) evtchn_register_pirq(irq)
++#endif
++
++static int setup_ioapic_entry(int apic, int irq,
++			      struct IO_APIC_route_entry *entry,
++			      unsigned int destination, int trigger,
++			      int polarity, int vector)
++{
++	/*
++	 * add it to the IO-APIC irq-routing table:
++	 */
++	memset(entry,0,sizeof(*entry));
++
++#ifdef CONFIG_INTR_REMAP
++	if (intr_remapping_enabled) {
++		struct intel_iommu *iommu = map_ioapic_to_ir(apic);
++		struct irte irte;
++		struct IR_IO_APIC_route_entry *ir_entry =
++			(struct IR_IO_APIC_route_entry *) entry;
++		int index;
++
++		if (!iommu)
++			panic("No mapping iommu for ioapic %d\n", apic);
++
++		index = alloc_irte(iommu, irq, 1);
++		if (index < 0)
++			panic("Failed to allocate IRTE for ioapic %d\n", apic);
++
++		memset(&irte, 0, sizeof(irte));
++
++		irte.present = 1;
++		irte.dst_mode = INT_DEST_MODE;
++		irte.trigger_mode = trigger;
++		irte.dlvry_mode = INT_DELIVERY_MODE;
++		irte.vector = vector;
++		irte.dest_id = IRTE_DEST(destination);
++
++		modify_irte(irq, &irte);
++
++		ir_entry->index2 = (index >> 15) & 0x1;
++		ir_entry->zero = 0;
++		ir_entry->format = 1;
++		ir_entry->index = (index & 0x7fff);
++	} else
++#endif
++	{
++		entry->delivery_mode = INT_DELIVERY_MODE;
++		entry->dest_mode = INT_DEST_MODE;
++		entry->dest = destination;
++	}
++
++	entry->mask = 0;				/* enable IRQ */
++	entry->trigger = trigger;
++	entry->polarity = polarity;
++	entry->vector = vector;
++
++	/* Mask level triggered irqs.
++	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
++	 */
++	if (trigger)
++		entry->mask = 1;
++	return 0;
++}
++
++static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
++			      int trigger, int polarity)
++{
++	struct irq_cfg *cfg;
++	struct IO_APIC_route_entry entry;
++	cpumask_t mask;
++
++	if (!IO_APIC_IRQ(irq))
++		return;
++
++	cfg = irq_cfg(irq);
++
++	mask = TARGET_CPUS;
++	if (assign_irq_vector(irq, mask))
++		return;
++
++#ifndef CONFIG_XEN
++	cpus_and(mask, cfg->domain, mask);
++#endif
++
++	apic_printk(APIC_VERBOSE,KERN_DEBUG
++		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
++		    "IRQ %d Mode:%i Active:%i)\n",
++		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
++		    irq, trigger, polarity);
++
++
++	if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
++			       cpu_mask_to_apicid(mask), trigger, polarity,
++			       cfg->vector)) {
++		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
++		       mp_ioapics[apic].mp_apicid, pin);
++		__clear_irq_vector(irq);
++		return;
++	}
++
++	ioapic_register_intr(irq, trigger);
++	if (irq < 16)
++		disable_8259A_irq(irq);
++
++	ioapic_write_entry(apic, pin, entry);
++}
++
++static void __init setup_IO_APIC_irqs(void)
++{
++	int apic, pin, idx, irq;
++	int notcon = 0;
++
++	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++
++			idx = find_irq_entry(apic, pin, mp_INT);
++			if (idx == -1) {
++				if (!notcon) {
++					notcon = 1;
++					apic_printk(APIC_VERBOSE,
++						KERN_DEBUG " %d-%d",
++						mp_ioapics[apic].mp_apicid,
++						pin);
++				} else
++					apic_printk(APIC_VERBOSE, " %d-%d",
++						mp_ioapics[apic].mp_apicid,
++						pin);
++				continue;
++			}
++			if (notcon) {
++				apic_printk(APIC_VERBOSE,
++					" (apicid-pin) not connected\n");
++				notcon = 0;
++			}
++
++			irq = pin_2_irq(idx, apic, pin);
++#if defined(CONFIG_XEN)
++			if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS)
++				continue;
++#elif defined(CONFIG_X86_32)
++			if (multi_timer_check(apic, irq))
++				continue;
++#endif
++			add_pin_to_irq(irq, apic, pin);
++
++			setup_IO_APIC_irq(apic, pin, irq,
++					irq_trigger(idx), irq_polarity(idx));
++		}
++	}
++
++	if (notcon)
++		apic_printk(APIC_VERBOSE,
++			" (apicid-pin) not connected\n");
++}
++
++#ifndef CONFIG_XEN
++/*
++ * Set up the timer pin, possibly with the 8259A-master behind.
++ */
++static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
++					int vector)
++{
++	struct IO_APIC_route_entry entry;
++
++#ifdef CONFIG_INTR_REMAP
++	if (intr_remapping_enabled)
++		return;
++#endif
++
++	memset(&entry, 0, sizeof(entry));
++
++	/*
++	 * We use logical delivery to get the timer IRQ
++	 * to the first CPU.
++	 */
++	entry.dest_mode = INT_DEST_MODE;
++	entry.mask = 1;					/* mask IRQ now */
++	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.delivery_mode = INT_DELIVERY_MODE;
++	entry.polarity = 0;
++	entry.trigger = 0;
++	entry.vector = vector;
++
++	/*
++	 * The timer IRQ doesn't have to know that behind the
++	 * scene we may have a 8259A-master in AEOI mode ...
++	 */
++	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
++
++	/*
++	 * Add it to the IO-APIC irq-routing table:
++	 */
++	ioapic_write_entry(apic, pin, entry);
++}
++
++
++__apicdebuginit(void) print_IO_APIC(void)
++{
++	int apic, i;
++	union IO_APIC_reg_00 reg_00;
++	union IO_APIC_reg_01 reg_01;
++	union IO_APIC_reg_02 reg_02;
++	union IO_APIC_reg_03 reg_03;
++	unsigned long flags;
++	struct irq_cfg *cfg;
++	unsigned int irq;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
++	for (i = 0; i < nr_ioapics; i++)
++		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
++		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
++
++	/*
++	 * We are a bit conservative about what we expect.  We have to
++	 * know about every hardware change ASAP.
++	 */
++	printk(KERN_INFO "testing the IO APIC.......................\n");
++
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(apic, 0);
++	reg_01.raw = io_apic_read(apic, 1);
++	if (reg_01.bits.version >= 0x10)
++		reg_02.raw = io_apic_read(apic, 2);
++	if (reg_01.bits.version >= 0x20)
++		reg_03.raw = io_apic_read(apic, 3);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	printk("\n");
++	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
++	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
++	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
++	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
++	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
++
++	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
++	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
++
++	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
++	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
++
++	/*
++	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
++	 * but the value of reg_02 is read as the previous read register
++	 * value, so ignore it if reg_02 == reg_01.
++	 */
++	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
++		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
++		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
++	}
++
++	/*
++	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
++	 * or reg_03, but the value of reg_0[23] is read as the previous read
++	 * register value, so ignore it if reg_03 == reg_0[12].
++	 */
++	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
++	    reg_03.raw != reg_01.raw) {
++		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
++		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
++	}
++
++	printk(KERN_DEBUG ".... IRQ redirection table:\n");
++
++	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
++			  " Stat Dmod Deli Vect:   \n");
++
++	for (i = 0; i <= reg_01.bits.entries; i++) {
++		struct IO_APIC_route_entry entry;
++
++		entry = ioapic_read_entry(apic, i);
++
++		printk(KERN_DEBUG " %02x %03X ",
++			i,
++			entry.dest
++		);
++
++		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
++			entry.mask,
++			entry.trigger,
++			entry.irr,
++			entry.polarity,
++			entry.delivery_status,
++			entry.dest_mode,
++			entry.delivery_mode,
++			entry.vector
++		);
++	}
++	}
++	printk(KERN_DEBUG "IRQ to pin mappings:\n");
++	for_each_irq_cfg(irq, cfg) {
++		struct irq_pin_list *entry = cfg->irq_2_pin;
++		if (!entry)
++			continue;
++		printk(KERN_DEBUG "IRQ%d ", irq);
++		for (;;) {
++			printk("-> %d:%d", entry->apic, entry->pin);
++			if (!entry->next)
++				break;
++			entry = entry->next;
++		}
++		printk("\n");
++	}
++
++	printk(KERN_INFO ".................................... done.\n");
++
++	return;
++}
++
++__apicdebuginit(void) print_APIC_bitfield(int base)
++{
++	unsigned int v;
++	int i, j;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
++	for (i = 0; i < 8; i++) {
++		v = apic_read(base + i*0x10);
++		for (j = 0; j < 32; j++) {
++			if (v & (1<<j))
++				printk("1");
++			else
++				printk("0");
++		}
++		printk("\n");
++	}
++}
++
++__apicdebuginit(void) print_local_APIC(void *dummy)
++{
++	unsigned int v, ver, maxlvt;
++	u64 icr;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
++		smp_processor_id(), hard_smp_processor_id());
++	v = apic_read(APIC_ID);
++	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
++	v = apic_read(APIC_LVR);
++	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
++	ver = GET_APIC_VERSION(v);
++	maxlvt = lapic_get_maxlvt();
++
++	v = apic_read(APIC_TASKPRI);
++	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
++
++	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
++		if (!APIC_XAPIC(ver)) {
++			v = apic_read(APIC_ARBPRI);
++			printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
++			       v & APIC_ARBPRI_MASK);
++		}
++		v = apic_read(APIC_PROCPRI);
++		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
++	}
++
++	/*
++	 * Remote read supported only in the 82489DX and local APIC for
++	 * Pentium processors.
++	 */
++	if (!APIC_INTEGRATED(ver) || maxlvt == 3) {
++		v = apic_read(APIC_RRR);
++		printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
++	}
++
++	v = apic_read(APIC_LDR);
++	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
++	if (!x2apic_enabled()) {
++		v = apic_read(APIC_DFR);
++		printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
++	}
++	v = apic_read(APIC_SPIV);
++	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
++
++	printk(KERN_DEBUG "... APIC ISR field:\n");
++	print_APIC_bitfield(APIC_ISR);
++	printk(KERN_DEBUG "... APIC TMR field:\n");
++	print_APIC_bitfield(APIC_TMR);
++	printk(KERN_DEBUG "... APIC IRR field:\n");
++	print_APIC_bitfield(APIC_IRR);
++
++	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
++		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
++			apic_write(APIC_ESR, 0);
++
++		v = apic_read(APIC_ESR);
++		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
++	}
++
++	icr = apic_icr_read();
++	printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr);
++	printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32));
++
++	v = apic_read(APIC_LVTT);
++	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
++
++	if (maxlvt > 3) {                       /* PC is LVT#4. */
++		v = apic_read(APIC_LVTPC);
++		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
++	}
++	v = apic_read(APIC_LVT0);
++	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
++	v = apic_read(APIC_LVT1);
++	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
++
++	if (maxlvt > 2) {			/* ERR is LVT#3. */
++		v = apic_read(APIC_LVTERR);
++		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
++	}
++
++	v = apic_read(APIC_TMICT);
++	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
++	v = apic_read(APIC_TMCCT);
++	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
++	v = apic_read(APIC_TDCR);
++	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
++	printk("\n");
++}
++
++__apicdebuginit(void) print_all_local_APICs(void)
++{
++	int cpu;
++
++	preempt_disable();
++	for_each_online_cpu(cpu)
++		smp_call_function_single(cpu, print_local_APIC, NULL, 1);
++	preempt_enable();
++}
++
++__apicdebuginit(void) print_PIC(void)
++{
++	unsigned int v;
++	unsigned long flags;
++
++	if (apic_verbosity == APIC_QUIET)
++		return;
++
++	printk(KERN_DEBUG "\nprinting PIC contents\n");
++
++	spin_lock_irqsave(&i8259A_lock, flags);
++
++	v = inb(0xa1) << 8 | inb(0x21);
++	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
++
++	v = inb(0xa0) << 8 | inb(0x20);
++	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
++
++	outb(0x0b,0xa0);
++	outb(0x0b,0x20);
++	v = inb(0xa0) << 8 | inb(0x20);
++	outb(0x0a,0xa0);
++	outb(0x0a,0x20);
++
++	spin_unlock_irqrestore(&i8259A_lock, flags);
++
++	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
++
++	v = inb(0x4d1) << 8 | inb(0x4d0);
++	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
++}
++
++__apicdebuginit(int) print_all_ICs(void)
++{
++	print_PIC();
++	print_all_local_APICs();
++	print_IO_APIC();
++
++	return 0;
++}
++
++fs_initcall(print_all_ICs);
++
++
++/* Where if anywhere is the i8259 connect in external int mode */
++static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
++#endif /* CONFIG_XEN */
++
++void __init enable_IO_APIC(void)
++{
++	union IO_APIC_reg_01 reg_01;
++#ifndef CONFIG_XEN
++	int i8259_apic, i8259_pin;
++#endif
++	int apic;
++	unsigned long flags;
++
++#ifdef CONFIG_X86_32
++	int i;
++	if (!pirqs_enabled)
++		for (i = 0; i < MAX_PIRQS; i++)
++			pirq_entries[i] = -1;
++#endif
++
++	/*
++	 * The number of IO-APIC IRQ registers (== #pins):
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_01.raw = io_apic_read(apic, 1);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
++	}
++#ifndef CONFIG_XEN
++	for(apic = 0; apic < nr_ioapics; apic++) {
++		int pin;
++		/* See if any of the pins is in ExtINT mode */
++		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
++			struct IO_APIC_route_entry entry;
++			entry = ioapic_read_entry(apic, pin);
++
++			/* If the interrupt line is enabled and in ExtInt mode
++			 * I have found the pin where the i8259 is connected.
++			 */
++			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
++				ioapic_i8259.apic = apic;
++				ioapic_i8259.pin  = pin;
++				goto found_i8259;
++			}
++		}
++	}
++ found_i8259:
++	/* Look to see what if the MP table has reported the ExtINT */
++	/* If we could not find the appropriate pin by looking at the ioapic
++	 * the i8259 probably is not connected the ioapic but give the
++	 * mptable a chance anyway.
++	 */
++	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
++	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
++	/* Trust the MP table if nothing is setup in the hardware */
++	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
++		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
++		ioapic_i8259.pin  = i8259_pin;
++		ioapic_i8259.apic = i8259_apic;
++	}
++	/* Complain if the MP table and the hardware disagree */
++	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
++		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
++	{
++		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
++	}
++
++	/*
++	 * Do not trust the IO-APIC being empty at bootup
++	 */
++	clear_IO_APIC();
++#endif
++}
++
++#ifdef CONFIG_XEN
++#define disable_IO_APIC() ((void)0)
++#else
++/*
++ * Not an __init, needed by the reboot code
++ */
++void disable_IO_APIC(void)
++{
++	/*
++	 * Clear the IO-APIC before rebooting:
++	 */
++	clear_IO_APIC();
++
++	/*
++	 * If the i8259 is routed through an IOAPIC
++	 * Put that IOAPIC in virtual wire mode
++	 * so legacy interrupts can be delivered.
++	 */
++	if (ioapic_i8259.pin != -1) {
++		struct IO_APIC_route_entry entry;
++
++		memset(&entry, 0, sizeof(entry));
++		entry.mask            = 0; /* Enabled */
++		entry.trigger         = 0; /* Edge */
++		entry.irr             = 0;
++		entry.polarity        = 0; /* High */
++		entry.delivery_status = 0;
++		entry.dest_mode       = 0; /* Physical */
++		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
++		entry.vector          = 0;
++		entry.dest            = read_apic_id();
++
++		/*
++		 * Add it to the IO-APIC irq-routing table:
++		 */
++		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
++	}
++
++	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
++}
++
++#ifdef CONFIG_X86_32
++/*
++ * function to set the IO-APIC physical IDs based on the
++ * values stored in the MPC table.
++ *
++ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
++ */
++
++static void __init setup_ioapic_ids_from_mpc(void)
++{
++	union IO_APIC_reg_00 reg_00;
++	physid_mask_t phys_id_present_map;
++	int apic;
++	int i;
++	unsigned char old_id;
++	unsigned long flags;
++
++	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids())
++		return;
++
++	/*
++	 * Don't check I/O APIC IDs for xAPIC systems.  They have
++	 * no meaning without the serial APIC bus.
++	 */
++	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
++		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
++		return;
++	/*
++	 * This is broken; anything with a real cpu count has to
++	 * circumvent this idiocy regardless.
++	 */
++	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
++
++	/*
++	 * Set the IOAPIC ID to the value stored in the MPC table.
++	 */
++	for (apic = 0; apic < nr_ioapics; apic++) {
++
++		/* Read the register 0 value */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		old_id = mp_ioapics[apic].mp_apicid;
++
++		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
++			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
++				apic, mp_ioapics[apic].mp_apicid);
++			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
++				reg_00.bits.ID);
++			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
++		}
++
++		/*
++		 * Sanity check, is the ID really free? Every APIC in a
++		 * system must have a unique ID or we get lots of nice
++		 * 'stuck on smp_invalidate_needed IPI wait' messages.
++		 */
++		if (check_apicid_used(phys_id_present_map,
++					mp_ioapics[apic].mp_apicid)) {
++			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
++				apic, mp_ioapics[apic].mp_apicid);
++			for (i = 0; i < get_physical_broadcast(); i++)
++				if (!physid_isset(i, phys_id_present_map))
++					break;
++			if (i >= get_physical_broadcast())
++				panic("Max APIC ID exceeded!\n");
++			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
++				i);
++			physid_set(i, phys_id_present_map);
++			mp_ioapics[apic].mp_apicid = i;
++		} else {
++			physid_mask_t tmp;
++			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
++			apic_printk(APIC_VERBOSE, "Setting %d in the "
++					"phys_id_present_map\n",
++					mp_ioapics[apic].mp_apicid);
++			physids_or(phys_id_present_map, phys_id_present_map, tmp);
++		}
++
++
++		/*
++		 * We need to adjust the IRQ routing table
++		 * if the ID changed.
++		 */
++		if (old_id != mp_ioapics[apic].mp_apicid)
++			for (i = 0; i < mp_irq_entries; i++)
++				if (mp_irqs[i].mp_dstapic == old_id)
++					mp_irqs[i].mp_dstapic
++						= mp_ioapics[apic].mp_apicid;
++
++		/*
++		 * Read the right value from the MPC table and
++		 * write it into the ID register.
++		 */
++		apic_printk(APIC_VERBOSE, KERN_INFO
++			"...changing IO-APIC physical APIC ID to %d ...",
++			mp_ioapics[apic].mp_apicid);
++
++		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(apic, 0, reg_00.raw);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		/*
++		 * Sanity check
++		 */
++		spin_lock_irqsave(&ioapic_lock, flags);
++		reg_00.raw = io_apic_read(apic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
++			printk("could not set ID!\n");
++		else
++			apic_printk(APIC_VERBOSE, " ok.\n");
++	}
++}
++#endif
++
++int no_timer_check __initdata;
++
++static int __init notimercheck(char *s)
++{
++	no_timer_check = 1;
++	return 1;
++}
++__setup("no_timer_check", notimercheck);
++
++/*
++ * There is a nasty bug in some older SMP boards, their mptable lies
++ * about the timer IRQ. We do the following to work around the situation:
++ *
++ *	- timer IRQ defaults to IO-APIC IRQ
++ *	- if this function detects that timer IRQs are defunct, then we fall
++ *	  back to ISA timer IRQs
++ */
++static int __init timer_irq_works(void)
++{
++	unsigned long t1 = jiffies;
++	unsigned long flags;
++
++	if (no_timer_check)
++		return 1;
++
++	local_save_flags(flags);
++	local_irq_enable();
++	/* Let ten ticks pass... */
++	mdelay((10 * 1000) / HZ);
++	local_irq_restore(flags);
++
++	/*
++	 * Expect a few ticks at least, to be sure some possible
++	 * glue logic does not lock up after one or two first
++	 * ticks in a non-ExtINT mode.  Also the local APIC
++	 * might have cached one ExtINT interrupt.  Finally, at
++	 * least one tick may be lost due to delays.
++	 */
++
++	/* jiffies wrap? */
++	if (time_after(jiffies, t1 + 4))
++		return 1;
++	return 0;
++}
++
++/*
++ * In the SMP+IOAPIC case it might happen that there are an unspecified
++ * number of pending IRQ events unhandled. These cases are very rare,
++ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
++ * better to do it this way as thus we do not have to be aware of
++ * 'pending' interrupts in the IRQ path, except at this point.
++ */
++/*
++ * Edge triggered needs to resend any interrupt
++ * that was delayed but this is now handled in the device
++ * independent code.
++ */
++
++/*
++ * Starting up a edge-triggered IO-APIC interrupt is
++ * nasty - we need to make sure that we get the edge.
++ * If it is already asserted for some reason, we need
++ * return 1 to indicate that is was pending.
++ *
++ * This is not complete - we should be able to fake
++ * an edge even if it isn't on the 8259A...
++ */
++
++static unsigned int startup_ioapic_irq(unsigned int irq)
++{
++	int was_pending = 0;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	if (irq < 16) {
++		disable_8259A_irq(irq);
++		if (i8259A_irq_pending(irq))
++			was_pending = 1;
++	}
++	__unmask_IO_APIC_irq(irq);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return was_pending;
++}
++
++#ifdef CONFIG_X86_64
++static int ioapic_retrigger_irq(unsigned int irq)
++{
++
++	struct irq_cfg *cfg = irq_cfg(irq);
++	unsigned long flags;
++
++	spin_lock_irqsave(&vector_lock, flags);
++	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	return 1;
++}
++#else
++static int ioapic_retrigger_irq(unsigned int irq)
++{
++	send_IPI_self(irq_cfg(irq)->vector);
++
++	return 1;
++}
++#endif
++
++/*
++ * Level and edge triggered IO-APIC interrupts need different handling,
++ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
++ * handled with the level-triggered descriptor, but that one has slightly
++ * more overhead. Level-triggered interrupts cannot be handled with the
++ * edge-triggered handler, without risking IRQ storms and other ugly
++ * races.
++ */
++
++#ifdef CONFIG_SMP
++
++#ifdef CONFIG_INTR_REMAP
++static void ir_irq_migration(struct work_struct *work);
++
++static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
++
++/*
++ * Migrate the IO-APIC irq in the presence of intr-remapping.
++ *
++ * For edge triggered, irq migration is a simple atomic update(of vector
++ * and cpu destination) of IRTE and flush the hardware cache.
++ *
++ * For level triggered, we need to modify the io-apic RTE aswell with the update
++ * vector information, along with modifying IRTE with vector and destination.
++ * So irq migration for level triggered is little  bit more complex compared to
++ * edge triggered migration. But the good news is, we use the same algorithm
++ * for level triggered migration as we have today, only difference being,
++ * we now initiate the irq migration from process context instead of the
++ * interrupt context.
++ *
++ * In future, when we do a directed EOI (combined with cpu EOI broadcast
++ * suppression) to the IO-APIC, level triggered irq migration will also be
++ * as simple as edge triggered migration and we can do the irq migration
++ * with a simple atomic update to IO-APIC RTE.
++ */
++static void migrate_ioapic_irq(int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	struct irq_desc *desc;
++	cpumask_t tmp, cleanup_mask;
++	struct irte irte;
++	int modify_ioapic_rte;
++	unsigned int dest;
++	unsigned long flags;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (get_irte(irq, &irte))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	desc = irq_to_desc(irq);
++	modify_ioapic_rte = desc->status & IRQ_LEVEL;
++	if (modify_ioapic_rte) {
++		spin_lock_irqsave(&ioapic_lock, flags);
++		__target_IO_APIC_irq(irq, dest, cfg->vector);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++	}
++
++	irte.vector = cfg->vector;
++	irte.dest_id = IRTE_DEST(dest);
++
++	/*
++	 * Modified the IRTE and flushes the Interrupt entry cache.
++	 */
++	modify_irte(irq, &irte);
++
++	if (cfg->move_in_progress) {
++		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
++		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
++		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		cfg->move_in_progress = 0;
++	}
++
++	desc->affinity = mask;
++}
++
++static int migrate_irq_remapped_level(int irq)
++{
++	int ret = -1;
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	mask_IO_APIC_irq(irq);
++
++	if (io_apic_level_ack_pending(irq)) {
++		/*
++		 * Interrupt in progress. Migrating irq now will change the
++		 * vector information in the IO-APIC RTE and that will confuse
++		 * the EOI broadcast performed by cpu.
++		 * So, delay the irq migration to the next instance.
++		 */
++		schedule_delayed_work(&ir_migration_work, 1);
++		goto unmask;
++	}
++
++	/* everthing is clear. we have right of way */
++	migrate_ioapic_irq(irq, desc->pending_mask);
++
++	ret = 0;
++	desc->status &= ~IRQ_MOVE_PENDING;
++	cpus_clear(desc->pending_mask);
++
++unmask:
++	unmask_IO_APIC_irq(irq);
++	return ret;
++}
++
++static void ir_irq_migration(struct work_struct *work)
++{
++	unsigned int irq;
++	struct irq_desc *desc;
++
++	for_each_irq_desc(irq, desc) {
++		if (desc->status & IRQ_MOVE_PENDING) {
++			unsigned long flags;
++
++			spin_lock_irqsave(&desc->lock, flags);
++			if (!desc->chip->set_affinity ||
++			    !(desc->status & IRQ_MOVE_PENDING)) {
++				desc->status &= ~IRQ_MOVE_PENDING;
++				spin_unlock_irqrestore(&desc->lock, flags);
++				continue;
++			}
++
++			desc->chip->set_affinity(irq, desc->pending_mask);
++			spin_unlock_irqrestore(&desc->lock, flags);
++		}
++	}
++}
++
++/*
++ * Migrates the IRQ destination in the process context.
++ */
++static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
++{
++	struct irq_desc *desc = irq_to_desc(irq);
++
++	if (desc->status & IRQ_LEVEL) {
++		desc->status |= IRQ_MOVE_PENDING;
++		desc->pending_mask = mask;
++		migrate_irq_remapped_level(irq);
++		return;
++	}
++
++	migrate_ioapic_irq(irq, mask);
++}
++#endif
++
++asmlinkage void smp_irq_move_cleanup_interrupt(void)
++{
++	unsigned vector, me;
++	ack_APIC_irq();
++#ifdef CONFIG_X86_64
++	exit_idle();
++#endif
++	irq_enter();
++
++	me = smp_processor_id();
++	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
++		unsigned int irq;
++		struct irq_desc *desc;
++		struct irq_cfg *cfg;
++		irq = __get_cpu_var(vector_irq)[vector];
++
++		desc = irq_to_desc(irq);
++		if (!desc)
++			continue;
++
++		cfg = irq_cfg(irq);
++		spin_lock(&desc->lock);
++		if (!cfg->move_cleanup_count)
++			goto unlock;
++
++		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
++			goto unlock;
++
++		__get_cpu_var(vector_irq)[vector] = -1;
++		cfg->move_cleanup_count--;
++unlock:
++		spin_unlock(&desc->lock);
++	}
++
++	irq_exit();
++}
++
++static void irq_complete_move(unsigned int irq)
++{
++	struct irq_cfg *cfg = irq_cfg(irq);
++	unsigned vector, me;
++
++	if (likely(!cfg->move_in_progress))
++		return;
++
++	vector = ~get_irq_regs()->orig_ax;
++	me = smp_processor_id();
++	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
++		cpumask_t cleanup_mask;
++
++		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
++		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
++		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		cfg->move_in_progress = 0;
++	}
++}
++#else
++static inline void irq_complete_move(unsigned int irq) {}
++#endif
++#ifdef CONFIG_INTR_REMAP
++static void ack_x2apic_level(unsigned int irq)
++{
++	ack_x2APIC_irq();
++}
++
++static void ack_x2apic_edge(unsigned int irq)
++{
++	ack_x2APIC_irq();
++}
++#endif
++
++static void ack_apic_edge(unsigned int irq)
++{
++	irq_complete_move(irq);
++	move_native_irq(irq);
++	ack_APIC_irq();
++}
++
++atomic_t irq_mis_count;
++
++static void ack_apic_level(unsigned int irq)
++{
++#ifdef CONFIG_X86_32
++	unsigned long v;
++	int i;
++#endif
++	int do_unmask_irq = 0;
++
++	irq_complete_move(irq);
++#ifdef CONFIG_GENERIC_PENDING_IRQ
++	/* If we are moving the irq we need to mask it */
++	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
++		do_unmask_irq = 1;
++		mask_IO_APIC_irq(irq);
++	}
++#endif
++
++#ifdef CONFIG_X86_32
++	/*
++	* It appears there is an erratum which affects at least version 0x11
++	* of I/O APIC (that's the 82093AA and cores integrated into various
++	* chipsets).  Under certain conditions a level-triggered interrupt is
++	* erroneously delivered as edge-triggered one but the respective IRR
++	* bit gets set nevertheless.  As a result the I/O unit expects an EOI
++	* message but it will never arrive and further interrupts are blocked
++	* from the source.  The exact reason is so far unknown, but the
++	* phenomenon was observed when two consecutive interrupt requests
++	* from a given source get delivered to the same CPU and the source is
++	* temporarily disabled in between.
++	*
++	* A workaround is to simulate an EOI message manually.  We achieve it
++	* by setting the trigger mode to edge and then to level when the edge
++	* trigger mode gets detected in the TMR of a local APIC for a
++	* level-triggered interrupt.  We mask the source for the time of the
++	* operation to prevent an edge-triggered interrupt escaping meanwhile.
++	* The idea is from Manfred Spraul.  --macro
++	*/
++	i = irq_cfg(irq)->vector;
++
++	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
++#endif
++
++	/*
++	 * We must acknowledge the irq before we move it or the acknowledge will
++	 * not propagate properly.
++	 */
++	ack_APIC_irq();
++
++	/* Now we can move and renable the irq */
++	if (unlikely(do_unmask_irq)) {
++		/* Only migrate the irq if the ack has been received.
++		 *
++		 * On rare occasions the broadcast level triggered ack gets
++		 * delayed going to ioapics, and if we reprogram the
++		 * vector while Remote IRR is still set the irq will never
++		 * fire again.
++		 *
++		 * To prevent this scenario we read the Remote IRR bit
++		 * of the ioapic.  This has two effects.
++		 * - On any sane system the read of the ioapic will
++		 *   flush writes (and acks) going to the ioapic from
++		 *   this cpu.
++		 * - We get to see if the ACK has actually been delivered.
++		 *
++		 * Based on failed experiments of reprogramming the
++		 * ioapic entry from outside of irq context starting
++		 * with masking the ioapic entry and then polling until
++		 * Remote IRR was clear before reprogramming the
++		 * ioapic I don't trust the Remote IRR bit to be
++		 * completey accurate.
++		 *
++		 * However there appears to be no other way to plug
++		 * this race, so if the Remote IRR bit is not
++		 * accurate and is causing problems then it is a hardware bug
++		 * and you can go talk to the chipset vendor about it.
++		 */
++		if (!io_apic_level_ack_pending(irq))
++			move_masked_irq(irq);
++		unmask_IO_APIC_irq(irq);
++	}
++
++#ifdef CONFIG_X86_32
++	if (!(v & (1 << (i & 0x1f)))) {
++		atomic_inc(&irq_mis_count);
++		spin_lock(&ioapic_lock);
++		__mask_and_edge_IO_APIC_irq(irq);
++		__unmask_and_level_IO_APIC_irq(irq);
++		spin_unlock(&ioapic_lock);
++	}
++#endif
++}
++
++static struct irq_chip ioapic_chip __read_mostly = {
++	.name		= "IO-APIC",
++	.startup	= startup_ioapic_irq,
++	.mask		= mask_IO_APIC_irq,
++	.unmask		= unmask_IO_APIC_irq,
++	.ack		= ack_apic_edge,
++	.eoi		= ack_apic_level,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_ioapic_affinity_irq,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++#ifdef CONFIG_INTR_REMAP
++static struct irq_chip ir_ioapic_chip __read_mostly = {
++	.name		= "IR-IO-APIC",
++	.startup	= startup_ioapic_irq,
++	.mask		= mask_IO_APIC_irq,
++	.unmask		= unmask_IO_APIC_irq,
++	.ack		= ack_x2apic_edge,
++	.eoi		= ack_x2apic_level,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_ir_ioapic_affinity_irq,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++#endif
++#endif /* CONFIG_XEN */
++
++static inline void init_IO_APIC_traps(void)
++{
++	int irq;
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++
++	/*
++	 * NOTE! The local APIC isn't very good at handling
++	 * multiple interrupts at the same interrupt level.
++	 * As the interrupt level is determined by taking the
++	 * vector number and shifting that right by 4, we
++	 * want to spread these out a bit so that they don't
++	 * all fall in the same interrupt level.
++	 *
++	 * Also, we've got to be careful not to trash gate
++	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
++	 */
++	for_each_irq_cfg(irq, cfg) {
++#ifdef CONFIG_XEN
++		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS)
++			continue;
++#endif
++		if (IO_APIC_IRQ(irq) && !cfg->vector) {
++			/*
++			 * Hmm.. We don't have an entry for this,
++			 * so default to an old-fashioned 8259
++			 * interrupt if we can..
++			 */
++			if (irq < 16)
++				make_8259A_irq(irq);
++			else {
++				desc = irq_to_desc(irq);
++				/* Strange. Oh, well.. */
++				desc->chip = &no_irq_chip;
++			}
++		}
++	}
++}
++
++#ifndef CONFIG_XEN
++/*
++ * The local APIC irq-chip implementation:
++ */
++
++static void mask_lapic_irq(unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
++}
++
++static void unmask_lapic_irq(unsigned int irq)
++{
++	unsigned long v;
++
++	v = apic_read(APIC_LVT0);
++	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
++}
++
++static void ack_lapic_irq (unsigned int irq)
++{
++	ack_APIC_irq();
++}
++
++static struct irq_chip lapic_chip __read_mostly = {
++	.name		= "local-APIC",
++	.mask		= mask_lapic_irq,
++	.unmask		= unmask_lapic_irq,
++	.ack		= ack_lapic_irq,
++};
++
++static void lapic_register_intr(int irq)
++{
++	struct irq_desc *desc;
++
++	desc = irq_to_desc(irq);
++	desc->status &= ~IRQ_LEVEL;
++	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
++				      "edge");
++}
++
++static void __init setup_nmi(void)
++{
++	/*
++	 * Dirty trick to enable the NMI watchdog ...
++	 * We put the 8259A master into AEOI mode and
++	 * unmask on all local APICs LVT0 as NMI.
++	 *
++	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
++	 * is from Maciej W. Rozycki - so we do not have to EOI from
++	 * the NMI handler or the timer interrupt.
++	 */
++	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
++
++	enable_NMI_through_LVT0();
++
++	apic_printk(APIC_VERBOSE, " done.\n");
++}
++
++/*
++ * This looks a bit hackish but it's about the only one way of sending
++ * a few INTA cycles to 8259As and any associated glue logic.  ICR does
++ * not support the ExtINT mode, unfortunately.  We need to send these
++ * cycles as some i82489DX-based boards have glue logic that keeps the
++ * 8259A interrupt line asserted until INTA.  --macro
++ */
++static inline void __init unlock_ExtINT_logic(void)
++{
++	int apic, pin, i;
++	struct IO_APIC_route_entry entry0, entry1;
++	unsigned char save_control, save_freq_select;
++
++	pin  = find_isa_irq_pin(8, mp_INT);
++	if (pin == -1) {
++		WARN_ON_ONCE(1);
++		return;
++	}
++	apic = find_isa_irq_apic(8, mp_INT);
++	if (apic == -1) {
++		WARN_ON_ONCE(1);
++		return;
++	}
++
++	entry0 = ioapic_read_entry(apic, pin);
++	clear_IO_APIC_pin(apic, pin);
++
++	memset(&entry1, 0, sizeof(entry1));
++
++	entry1.dest_mode = 0;			/* physical delivery */
++	entry1.mask = 0;			/* unmask IRQ now */
++	entry1.dest = hard_smp_processor_id();
++	entry1.delivery_mode = dest_ExtINT;
++	entry1.polarity = entry0.polarity;
++	entry1.trigger = 0;
++	entry1.vector = 0;
++
++	ioapic_write_entry(apic, pin, entry1);
++
++	save_control = CMOS_READ(RTC_CONTROL);
++	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
++	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
++		   RTC_FREQ_SELECT);
++	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
++
++	i = 100;
++	while (i-- > 0) {
++		mdelay(10);
++		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
++			i -= 10;
++	}
++
++	CMOS_WRITE(save_control, RTC_CONTROL);
++	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
++	clear_IO_APIC_pin(apic, pin);
++
++	ioapic_write_entry(apic, pin, entry0);
++}
++
++static int disable_timer_pin_1 __initdata;
++/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
++static int __init disable_timer_pin_setup(char *arg)
++{
++	disable_timer_pin_1 = 1;
++	return 0;
++}
++early_param("disable_timer_pin_1", disable_timer_pin_setup);
++
++int timer_through_8259 __initdata;
++
++/*
++ * This code may look a bit paranoid, but it's supposed to cooperate with
++ * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
++ * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
++ * fanatically on his truly buggy board.
++ *
++ * FIXME: really need to revamp this for all platforms.
++ */
++static inline void __init check_timer(void)
++{
++	struct irq_cfg *cfg = irq_cfg(0);
++	int apic1, pin1, apic2, pin2;
++	unsigned long flags;
++	unsigned int ver;
++	int no_pin1 = 0;
++
++	local_irq_save(flags);
++
++	ver = apic_read(APIC_LVR);
++	ver = GET_APIC_VERSION(ver);
++
++	/*
++	 * get/set the timer IRQ vector:
++	 */
++	disable_8259A_irq(0);
++	assign_irq_vector(0, TARGET_CPUS);
++
++	/*
++	 * As IRQ0 is to be enabled in the 8259A, the virtual
++	 * wire has to be disabled in the local APIC.  Also
++	 * timer interrupts need to be acknowledged manually in
++	 * the 8259A for the i82489DX when using the NMI
++	 * watchdog as that APIC treats NMIs as level-triggered.
++	 * The AEOI mode will finish them in the 8259A
++	 * automatically.
++	 */
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
++	init_8259A(1);
++#ifdef CONFIG_X86_32
++	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
++#endif
++
++	pin1  = find_isa_irq_pin(0, mp_INT);
++	apic1 = find_isa_irq_apic(0, mp_INT);
++	pin2  = ioapic_i8259.pin;
++	apic2 = ioapic_i8259.apic;
++
++	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
++		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
++		    cfg->vector, apic1, pin1, apic2, pin2);
++
++	/*
++	 * Some BIOS writers are clueless and report the ExtINTA
++	 * I/O APIC input from the cascaded 8259A as the timer
++	 * interrupt input.  So just in case, if only one pin
++	 * was found above, try it both directly and through the
++	 * 8259A.
++	 */
++	if (pin1 == -1) {
++#ifdef CONFIG_INTR_REMAP
++		if (intr_remapping_enabled)
++			panic("BIOS bug: timer not connected to IO-APIC");
++#endif
++		pin1 = pin2;
++		apic1 = apic2;
++		no_pin1 = 1;
++	} else if (pin2 == -1) {
++		pin2 = pin1;
++		apic2 = apic1;
++	}
++
++	if (pin1 != -1) {
++		/*
++		 * Ok, does IRQ0 through the IOAPIC work?
++		 */
++		if (no_pin1) {
++			add_pin_to_irq(0, apic1, pin1);
++			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
++		}
++		unmask_IO_APIC_irq(0);
++		if (timer_irq_works()) {
++			if (nmi_watchdog == NMI_IO_APIC) {
++				setup_nmi();
++				enable_8259A_irq(0);
++			}
++			if (disable_timer_pin_1 > 0)
++				clear_IO_APIC_pin(0, pin1);
++			goto out;
++		}
++#ifdef CONFIG_INTR_REMAP
++		if (intr_remapping_enabled)
++			panic("timer doesn't work through Interrupt-remapped IO-APIC");
++#endif
++		clear_IO_APIC_pin(apic1, pin1);
++		if (!no_pin1)
++			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
++				    "8254 timer not connected to IO-APIC\n");
++
++		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
++			    "(IRQ0) through the 8259A ...\n");
++		apic_printk(APIC_QUIET, KERN_INFO
++			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
++		/*
++		 * legacy devices should be connected to IO APIC #0
++		 */
++		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
++		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
++		unmask_IO_APIC_irq(0);
++		enable_8259A_irq(0);
++		if (timer_irq_works()) {
++			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
++			timer_through_8259 = 1;
++			if (nmi_watchdog == NMI_IO_APIC) {
++				disable_8259A_irq(0);
++				setup_nmi();
++				enable_8259A_irq(0);
++			}
++			goto out;
++		}
++		/*
++		 * Cleanup, just in case ...
++		 */
++		disable_8259A_irq(0);
++		clear_IO_APIC_pin(apic2, pin2);
++		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
++	}
++
++	if (nmi_watchdog == NMI_IO_APIC) {
++		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
++			    "through the IO-APIC - disabling NMI Watchdog!\n");
++		nmi_watchdog = NMI_NONE;
++	}
++#ifdef CONFIG_X86_32
++	timer_ack = 0;
++#endif
++
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as Virtual Wire IRQ...\n");
++
++	lapic_register_intr(0);
++	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
++	enable_8259A_irq(0);
++
++	if (timer_irq_works()) {
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
++		goto out;
++	}
++	disable_8259A_irq(0);
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
++
++	apic_printk(APIC_QUIET, KERN_INFO
++		    "...trying to set up timer as ExtINT IRQ...\n");
++
++	init_8259A(0);
++	make_8259A_irq(0);
++	apic_write(APIC_LVT0, APIC_DM_EXTINT);
++
++	unlock_ExtINT_logic();
++
++	if (timer_irq_works()) {
++		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
++		goto out;
++	}
++	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
++	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
++		"report.  Then try booting with the 'noapic' option.\n");
++out:
++	local_irq_restore(flags);
++}
++#else
++#define check_timer() ((void)0)
++#endif
++
++/*
++ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
++ * to devices.  However there may be an I/O APIC pin available for
++ * this interrupt regardless.  The pin may be left unconnected, but
++ * typically it will be reused as an ExtINT cascade interrupt for
++ * the master 8259A.  In the MPS case such a pin will normally be
++ * reported as an ExtINT interrupt in the MP table.  With ACPI
++ * there is no provision for ExtINT interrupts, and in the absence
++ * of an override it would be treated as an ordinary ISA I/O APIC
++ * interrupt, that is edge-triggered and unmasked by default.  We
++ * used to do this, but it caused problems on some systems because
++ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
++ * the same ExtINT cascade interrupt to drive the local APIC of the
++ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
++ * the I/O APIC in all cases now.  No actual device should request
++ * it anyway.  --macro
++ */
++#define PIC_IRQS	(1 << PIC_CASCADE_IR)
++
++void __init setup_IO_APIC(void)
++{
++
++#if defined(CONFIG_X86_32) || defined(CONFIG_XEN)
++	enable_IO_APIC();
++#else
++	/*
++	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
++	 */
++#endif
++
++	io_apic_irqs = ~PIC_IRQS;
++
++	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
++	/*
++         * Set up IO-APIC IRQ routing.
++         */
++#ifndef CONFIG_XEN
++#ifdef CONFIG_X86_32
++	if (!acpi_ioapic)
++		setup_ioapic_ids_from_mpc();
++#endif
++	sync_Arb_IDs();
++#endif
++	setup_IO_APIC_irqs();
++	init_IO_APIC_traps();
++	check_timer();
++}
++
++/*
++ *      Called after all the initialization is done. If we didnt find any
++ *      APIC bugs then we can allow the modify fast path
++ */
++
++static int __init io_apic_bug_finalize(void)
++{
++	if (sis_apic_bug == -1)
++		sis_apic_bug = 0;
++#ifdef CONFIG_XEN
++	if (is_initial_xendomain()) {
++		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
++		op.u.platform_quirk.quirk_id = sis_apic_bug ?
++			QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
++		VOID(HYPERVISOR_platform_op(&op));
++	}
++#endif
++	return 0;
++}
++
++late_initcall(io_apic_bug_finalize);
++
++#ifndef CONFIG_XEN
++struct sysfs_ioapic_data {
++	struct sys_device dev;
++	struct IO_APIC_route_entry entry[0];
++};
++static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
++
++static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	int i;
++
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
++		*entry = ioapic_read_entry(dev->id, i);
++
++	return 0;
++}
++
++static int ioapic_resume(struct sys_device *dev)
++{
++	struct IO_APIC_route_entry *entry;
++	struct sysfs_ioapic_data *data;
++	unsigned long flags;
++	union IO_APIC_reg_00 reg_00;
++	int i;
++
++	data = container_of(dev, struct sysfs_ioapic_data, dev);
++	entry = data->entry;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(dev->id, 0);
++	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
++		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
++		io_apic_write(dev->id, 0, reg_00.raw);
++	}
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
++		ioapic_write_entry(dev->id, i, entry[i]);
++
++	return 0;
++}
++
++static struct sysdev_class ioapic_sysdev_class = {
++	.name = "ioapic",
++	.suspend = ioapic_suspend,
++	.resume = ioapic_resume,
++};
++
++static int __init ioapic_init_sysfs(void)
++{
++	struct sys_device * dev;
++	int i, size, error;
++
++	error = sysdev_class_register(&ioapic_sysdev_class);
++	if (error)
++		return error;
++
++	for (i = 0; i < nr_ioapics; i++ ) {
++		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
++			* sizeof(struct IO_APIC_route_entry);
++		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
++		if (!mp_ioapic_data[i]) {
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++		dev = &mp_ioapic_data[i]->dev;
++		dev->id = i;
++		dev->cls = &ioapic_sysdev_class;
++		error = sysdev_register(dev);
++		if (error) {
++			kfree(mp_ioapic_data[i]);
++			mp_ioapic_data[i] = NULL;
++			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
++			continue;
++		}
++	}
++
++	return 0;
++}
++
++device_initcall(ioapic_init_sysfs);
++
++/*
++ * Dynamic irq allocate and deallocation
++ */
++unsigned int create_irq_nr(unsigned int irq_want)
++{
++	/* Allocate an unused irq */
++	unsigned int irq;
++	unsigned int new;
++	unsigned long flags;
++	struct irq_cfg *cfg_new;
++
++	irq_want = nr_irqs - 1;
++
++	irq = 0;
++	spin_lock_irqsave(&vector_lock, flags);
++	for (new = irq_want; new > 0; new--) {
++		if (platform_legacy_irq(new))
++			continue;
++		cfg_new = irq_cfg(new);
++		if (cfg_new && cfg_new->vector != 0)
++			continue;
++		/* check if need to create one */
++		if (!cfg_new)
++			cfg_new = irq_cfg_alloc(new);
++		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
++			irq = new;
++		break;
++	}
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	if (irq > 0) {
++		dynamic_irq_init(irq);
++	}
++	return irq;
++}
++
++int create_irq(void)
++{
++	int irq;
++
++	irq = create_irq_nr(nr_irqs - 1);
++
++	if (irq == 0)
++		irq = -1;
++
++	return irq;
++}
++
++void destroy_irq(unsigned int irq)
++{
++	unsigned long flags;
++
++	dynamic_irq_cleanup(irq);
++
++#ifdef CONFIG_INTR_REMAP
++	free_irte(irq);
++#endif
++	spin_lock_irqsave(&vector_lock, flags);
++	__clear_irq_vector(irq);
++	spin_unlock_irqrestore(&vector_lock, flags);
++}
++#endif /* CONFIG_XEN */
++
++/*
++ * MSI message composition
++ */
++#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
++static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
++{
++	struct irq_cfg *cfg;
++	int err;
++	unsigned dest;
++	cpumask_t tmp;
++
++	tmp = TARGET_CPUS;
++	err = assign_irq_vector(irq, tmp);
++	if (err)
++		return err;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, tmp);
++	dest = cpu_mask_to_apicid(tmp);
++
++#ifdef CONFIG_INTR_REMAP
++	if (irq_remapped(irq)) {
++		struct irte irte;
++		int ir_index;
++		u16 sub_handle;
++
++		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
++		BUG_ON(ir_index == -1);
++
++		memset (&irte, 0, sizeof(irte));
++
++		irte.present = 1;
++		irte.dst_mode = INT_DEST_MODE;
++		irte.trigger_mode = 0; /* edge */
++		irte.dlvry_mode = INT_DELIVERY_MODE;
++		irte.vector = cfg->vector;
++		irte.dest_id = IRTE_DEST(dest);
++
++		modify_irte(irq, &irte);
++
++		msg->address_hi = MSI_ADDR_BASE_HI;
++		msg->data = sub_handle;
++		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
++				  MSI_ADDR_IR_SHV |
++				  MSI_ADDR_IR_INDEX1(ir_index) |
++				  MSI_ADDR_IR_INDEX2(ir_index);
++	} else
++#endif
++	{
++		msg->address_hi = MSI_ADDR_BASE_HI;
++		msg->address_lo =
++			MSI_ADDR_BASE_LO |
++			((INT_DEST_MODE == 0) ?
++				MSI_ADDR_DEST_MODE_PHYSICAL:
++				MSI_ADDR_DEST_MODE_LOGICAL) |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_ADDR_REDIRECTION_CPU:
++				MSI_ADDR_REDIRECTION_LOWPRI) |
++			MSI_ADDR_DEST_ID(dest);
++
++		msg->data =
++			MSI_DATA_TRIGGER_EDGE |
++			MSI_DATA_LEVEL_ASSERT |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				MSI_DATA_DELIVERY_FIXED:
++				MSI_DATA_DELIVERY_LOWPRI) |
++			MSI_DATA_VECTOR(cfg->vector);
++	}
++	return err;
++}
++
++#ifdef CONFIG_SMP
++static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++	struct irq_desc *desc;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	read_msi_msg(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(cfg->vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++
++	write_msi_msg(irq, &msg);
++	desc = irq_to_desc(irq);
++	desc->affinity = mask;
++}
++
++#ifdef CONFIG_INTR_REMAP
++/*
++ * Migrate the MSI irq to another cpumask. This migration is
++ * done in the process context using interrupt-remapping hardware.
++ */
++static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	unsigned int dest;
++	cpumask_t tmp, cleanup_mask;
++	struct irte irte;
++	struct irq_desc *desc;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (get_irte(irq, &irte))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	irte.vector = cfg->vector;
++	irte.dest_id = IRTE_DEST(dest);
++
++	/*
++	 * atomically update the IRTE with the new destination and vector.
++	 */
++	modify_irte(irq, &irte);
++
++	/*
++	 * After this point, all the interrupts will start arriving
++	 * at the new destination. So, time to cleanup the previous
++	 * vector allocation.
++	 */
++	if (cfg->move_in_progress) {
++		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
++		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
++		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		cfg->move_in_progress = 0;
++	}
++
++	desc = irq_to_desc(irq);
++	desc->affinity = mask;
++}
++#endif
++#endif /* CONFIG_SMP */
++
++/*
++ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI or MSI-X Capability Structure.
++ */
++static struct irq_chip msi_chip = {
++	.name		= "PCI-MSI",
++	.unmask		= unmask_msi_irq,
++	.mask		= mask_msi_irq,
++	.ack		= ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_msi_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++#ifdef CONFIG_INTR_REMAP
++static struct irq_chip msi_ir_chip = {
++	.name		= "IR-PCI-MSI",
++	.unmask		= unmask_msi_irq,
++	.mask		= mask_msi_irq,
++	.ack		= ack_x2apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity	= ir_set_msi_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++/*
++ * Map the PCI dev to the corresponding remapping hardware unit
++ * and allocate 'nvec' consecutive interrupt-remapping table entries
++ * in it.
++ */
++static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
++{
++	struct intel_iommu *iommu;
++	int index;
++
++	iommu = map_dev_to_ir(dev);
++	if (!iommu) {
++		printk(KERN_ERR
++		       "Unable to map PCI %s to iommu\n", pci_name(dev));
++		return -ENOENT;
++	}
++
++	index = alloc_irte(iommu, irq, nvec);
++	if (index < 0) {
++		printk(KERN_ERR
++		       "Unable to allocate %d IRTE for PCI %s\n", nvec,
++		       pci_name(dev));
++		return -ENOSPC;
++	}
++	return index;
++}
++#endif
++
++static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
++{
++	int ret;
++	struct msi_msg msg;
++
++	ret = msi_compose_msg(dev, irq, &msg);
++	if (ret < 0)
++		return ret;
++
++	set_irq_msi(irq, desc);
++	write_msi_msg(irq, &msg);
++
++#ifdef CONFIG_INTR_REMAP
++	if (irq_remapped(irq)) {
++		struct irq_desc *desc = irq_to_desc(irq);
++		/*
++		 * irq migration in process context
++		 */
++		desc->status |= IRQ_MOVE_PCNTXT;
++		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
++	} else
++#endif
++		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
++
++	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
++
++	return 0;
++}
++
++static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
++{
++	unsigned int irq;
++
++	irq = dev->bus->number;
++	irq <<= 8;
++	irq |= dev->devfn;
++	irq <<= 12;
++
++	return irq;
++}
++
++int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
++{
++	unsigned int irq;
++	int ret;
++	unsigned int irq_want;
++
++	irq_want = build_irq_for_pci_dev(dev) + 0x100;
++
++	irq = create_irq_nr(irq_want);
++	if (irq == 0)
++		return -1;
++
++#ifdef CONFIG_INTR_REMAP
++	if (!intr_remapping_enabled)
++		goto no_ir;
++
++	ret = msi_alloc_irte(dev, irq, 1);
++	if (ret < 0)
++		goto error;
++no_ir:
++#endif
++	ret = setup_msi_irq(dev, desc, irq);
++	if (ret < 0) {
++		destroy_irq(irq);
++		return ret;
++	}
++	return 0;
++
++#ifdef CONFIG_INTR_REMAP
++error:
++	destroy_irq(irq);
++	return ret;
++#endif
++}
++
++int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
++{
++	unsigned int irq;
++	int ret, sub_handle;
++	struct msi_desc *desc;
++	unsigned int irq_want;
++
++#ifdef CONFIG_INTR_REMAP
++	struct intel_iommu *iommu = 0;
++	int index = 0;
++#endif
++
++	irq_want = build_irq_for_pci_dev(dev) + 0x100;
++	sub_handle = 0;
++	list_for_each_entry(desc, &dev->msi_list, list) {
++		irq = create_irq_nr(irq_want--);
++		if (irq == 0)
++			return -1;
++#ifdef CONFIG_INTR_REMAP
++		if (!intr_remapping_enabled)
++			goto no_ir;
++
++		if (!sub_handle) {
++			/*
++			 * allocate the consecutive block of IRTE's
++			 * for 'nvec'
++			 */
++			index = msi_alloc_irte(dev, irq, nvec);
++			if (index < 0) {
++				ret = index;
++				goto error;
++			}
++		} else {
++			iommu = map_dev_to_ir(dev);
++			if (!iommu) {
++				ret = -ENOENT;
++				goto error;
++			}
++			/*
++			 * setup the mapping between the irq and the IRTE
++			 * base index, the sub_handle pointing to the
++			 * appropriate interrupt remap table entry.
++			 */
++			set_irte_irq(irq, iommu, index, sub_handle);
++		}
++no_ir:
++#endif
++		ret = setup_msi_irq(dev, desc, irq);
++		if (ret < 0)
++			goto error;
++		sub_handle++;
++	}
++	return 0;
++
++error:
++	destroy_irq(irq);
++	return ret;
++}
++
++void arch_teardown_msi_irq(unsigned int irq)
++{
++	destroy_irq(irq);
++}
++
++#ifdef CONFIG_DMAR
++#ifdef CONFIG_SMP
++static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++	struct irq_desc *desc;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	dmar_msi_read(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(cfg->vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++
++	dmar_msi_write(irq, &msg);
++	desc = irq_to_desc(irq);
++	desc->affinity = mask;
++}
++#endif /* CONFIG_SMP */
++
++struct irq_chip dmar_msi_type = {
++	.name = "DMAR_MSI",
++	.unmask = dmar_msi_unmask,
++	.mask = dmar_msi_mask,
++	.ack = ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity = dmar_msi_set_affinity,
++#endif
++	.retrigger = ioapic_retrigger_irq,
++};
++
++int arch_setup_dmar_msi(unsigned int irq)
++{
++	int ret;
++	struct msi_msg msg;
++
++	ret = msi_compose_msg(NULL, irq, &msg);
++	if (ret < 0)
++		return ret;
++	dmar_msi_write(irq, &msg);
++	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
++		"edge");
++	return 0;
++}
++#endif
++
++#ifdef CONFIG_HPET_TIMER
++
++#ifdef CONFIG_SMP
++static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	struct irq_desc *desc;
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	hpet_msi_read(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(cfg->vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++
++	hpet_msi_write(irq, &msg);
++	desc = irq_to_desc(irq);
++	desc->affinity = mask;
++}
++#endif /* CONFIG_SMP */
++
++struct irq_chip hpet_msi_type = {
++	.name = "HPET_MSI",
++	.unmask = hpet_msi_unmask,
++	.mask = hpet_msi_mask,
++	.ack = ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity = hpet_msi_set_affinity,
++#endif
++	.retrigger = ioapic_retrigger_irq,
++};
++
++int arch_setup_hpet_msi(unsigned int irq)
++{
++	int ret;
++	struct msi_msg msg;
++
++	ret = msi_compose_msg(NULL, irq, &msg);
++	if (ret < 0)
++		return ret;
++
++	hpet_msi_write(irq, &msg);
++	set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq,
++		"edge");
++
++	return 0;
++}
++#endif
++
++#endif /* CONFIG_PCI_MSI */
++/*
++ * Hypertransport interrupt support
++ */
++#ifdef CONFIG_HT_IRQ
++
++#ifdef CONFIG_SMP
++
++static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
++{
++	struct ht_irq_msg msg;
++	fetch_ht_irq_msg(irq, &msg);
++
++	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
++	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
++
++	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
++	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
++
++	write_ht_irq_msg(irq, &msg);
++}
++
++static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg;
++	unsigned int dest;
++	cpumask_t tmp;
++	struct irq_desc *desc;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cfg = irq_cfg(irq);
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	target_ht_irq(irq, dest, cfg->vector);
++	desc = irq_to_desc(irq);
++	desc->affinity = mask;
++}
++#endif
++
++static struct irq_chip ht_irq_chip = {
++	.name		= "PCI-HT",
++	.mask		= mask_ht_irq,
++	.unmask		= unmask_ht_irq,
++	.ack		= ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity	= set_ht_irq_affinity,
++#endif
++	.retrigger	= ioapic_retrigger_irq,
++};
++
++int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
++{
++	struct irq_cfg *cfg;
++	int err;
++	cpumask_t tmp;
++
++	tmp = TARGET_CPUS;
++	err = assign_irq_vector(irq, tmp);
++	if (!err) {
++		struct ht_irq_msg msg;
++		unsigned dest;
++
++		cfg = irq_cfg(irq);
++		cpus_and(tmp, cfg->domain, tmp);
++		dest = cpu_mask_to_apicid(tmp);
++
++		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
++
++		msg.address_lo =
++			HT_IRQ_LOW_BASE |
++			HT_IRQ_LOW_DEST_ID(dest) |
++			HT_IRQ_LOW_VECTOR(cfg->vector) |
++			((INT_DEST_MODE == 0) ?
++				HT_IRQ_LOW_DM_PHYSICAL :
++				HT_IRQ_LOW_DM_LOGICAL) |
++			HT_IRQ_LOW_RQEOI_EDGE |
++			((INT_DELIVERY_MODE != dest_LowestPrio) ?
++				HT_IRQ_LOW_MT_FIXED :
++				HT_IRQ_LOW_MT_ARBITRATED) |
++			HT_IRQ_LOW_IRQ_MASKED;
++
++		write_ht_irq_msg(irq, &msg);
++
++		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
++					      handle_edge_irq, "edge");
++
++		dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
++	}
++	return err;
++}
++#endif /* CONFIG_HT_IRQ */
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++/*
++ * Re-target the irq to the specified CPU and enable the specified MMR located
++ * on the specified blade to allow the sending of MSIs to the specified CPU.
++ */
++int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
++		       unsigned long mmr_offset)
++{
++	const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
++	struct irq_cfg *cfg;
++	int mmr_pnode;
++	unsigned long mmr_value;
++	struct uv_IO_APIC_route_entry *entry;
++	unsigned long flags;
++	int err;
++
++	err = assign_irq_vector(irq, *eligible_cpu);
++	if (err != 0)
++		return err;
++
++	spin_lock_irqsave(&vector_lock, flags);
++	set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
++				      irq_name);
++	spin_unlock_irqrestore(&vector_lock, flags);
++
++	cfg = irq_cfg(irq);
++
++	mmr_value = 0;
++	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
++	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
++
++	entry->vector = cfg->vector;
++	entry->delivery_mode = INT_DELIVERY_MODE;
++	entry->dest_mode = INT_DEST_MODE;
++	entry->polarity = 0;
++	entry->trigger = 0;
++	entry->mask = 0;
++	entry->dest = cpu_mask_to_apicid(*eligible_cpu);
++
++	mmr_pnode = uv_blade_to_pnode(mmr_blade);
++	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
++
++	return irq;
++}
++
++/*
++ * Disable the specified MMR located on the specified blade so that MSIs are
++ * longer allowed to be sent.
++ */
++void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
++{
++	unsigned long mmr_value;
++	struct uv_IO_APIC_route_entry *entry;
++	int mmr_pnode;
++
++	mmr_value = 0;
++	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
++	BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
++
++	entry->mask = 1;
++
++	mmr_pnode = uv_blade_to_pnode(mmr_blade);
++	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
++}
++#endif /* CONFIG_X86_64 */
++
++int __init io_apic_get_redir_entries (int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.entries;
++}
++
++int __init probe_nr_irqs(void)
++{
++	return NR_IRQS;
++}
++
++/* --------------------------------------------------------------------------
++                          ACPI-based IOAPIC Configuration
++   -------------------------------------------------------------------------- */
++
++#ifdef CONFIG_ACPI
++
++#ifdef CONFIG_X86_32
++int __init io_apic_get_unique_id(int ioapic, int apic_id)
++{
++#ifndef CONFIG_XEN
++	union IO_APIC_reg_00 reg_00;
++	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
++	physid_mask_t tmp;
++	unsigned long flags;
++	int i = 0;
++
++	/*
++	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
++	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
++	 * supports up to 16 on one shared APIC bus.
++	 *
++	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
++	 *      advantage of new APIC bus architecture.
++	 */
++
++	if (physids_empty(apic_id_map))
++		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_00.raw = io_apic_read(ioapic, 0);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	if (apic_id >= get_physical_broadcast()) {
++		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
++			"%d\n", ioapic, apic_id, reg_00.bits.ID);
++		apic_id = reg_00.bits.ID;
++	}
++
++	/*
++	 * Every APIC in a system must have a unique ID or we get lots of nice
++	 * 'stuck on smp_invalidate_needed IPI wait' messages.
++	 */
++	if (check_apicid_used(apic_id_map, apic_id)) {
++
++		for (i = 0; i < get_physical_broadcast(); i++) {
++			if (!check_apicid_used(apic_id_map, i))
++				break;
++		}
++
++		if (i == get_physical_broadcast())
++			panic("Max apic_id exceeded!\n");
++
++		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
++			"trying %d\n", ioapic, apic_id, i);
++
++		apic_id = i;
++	}
++
++	tmp = apicid_to_cpu_present(apic_id);
++	physids_or(apic_id_map, apic_id_map, tmp);
++
++	if (reg_00.bits.ID != apic_id) {
++		reg_00.bits.ID = apic_id;
++
++		spin_lock_irqsave(&ioapic_lock, flags);
++		io_apic_write(ioapic, 0, reg_00.raw);
++		reg_00.raw = io_apic_read(ioapic, 0);
++		spin_unlock_irqrestore(&ioapic_lock, flags);
++
++		/* Sanity check */
++		if (reg_00.bits.ID != apic_id) {
++			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
++			return -1;
++		}
++	}
++
++	apic_printk(APIC_VERBOSE, KERN_INFO
++			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
++#endif /* !CONFIG_XEN */
++
++	return apic_id;
++}
++
++int __init io_apic_get_version(int ioapic)
++{
++	union IO_APIC_reg_01	reg_01;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ioapic_lock, flags);
++	reg_01.raw = io_apic_read(ioapic, 1);
++	spin_unlock_irqrestore(&ioapic_lock, flags);
++
++	return reg_01.bits.version;
++}
++#endif
++
++int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
++{
++#ifdef CONFIG_XEN
++	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + NR_PIRQS) {
++		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
++			    ioapic, irq);
++		return -EINVAL;
++	}
++#endif
++
++	if (!IO_APIC_IRQ(irq)) {
++		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
++			ioapic);
++		return -EINVAL;
++	}
++
++	/*
++	 * IRQs < 16 are already in the irq_2_pin[] map
++	 */
++	if (irq >= 16)
++		add_pin_to_irq(irq, ioapic, pin);
++
++	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
++
++	return 0;
++}
++
++
++int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
++{
++	int i;
++
++	if (skip_ioapic_setup)
++		return -1;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mp_irqtype == mp_INT &&
++		    mp_irqs[i].mp_srcbusirq == bus_irq)
++			break;
++	if (i >= mp_irq_entries)
++		return -1;
++
++	*trigger = irq_trigger(i);
++	*polarity = irq_polarity(i);
++	return 0;
++}
++
++#endif /* CONFIG_ACPI */
++
++#ifndef CONFIG_XEN
++/*
++ * This function currently is only a helper for the i386 smp boot process where
++ * we need to reprogram the ioredtbls to cater for the cpus which have come online
++ * so mask in all cases should simply be TARGET_CPUS
++ */
++#ifdef CONFIG_SMP
++void __init setup_ioapic_dest(void)
++{
++	int pin, ioapic, irq, irq_entry;
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++	cpumask_t mask;
++
++	if (skip_ioapic_setup == 1)
++		return;
++
++	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
++		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
++			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
++			if (irq_entry == -1)
++				continue;
++			irq = pin_2_irq(irq_entry, ioapic, pin);
++
++			/* setup_IO_APIC_irqs could fail to get vector for some device
++			 * when you have too many devices, because at that time only boot
++			 * cpu is online.
++			 */
++			cfg = irq_cfg(irq);
++			if (!cfg->vector) {
++				setup_IO_APIC_irq(ioapic, pin, irq,
++						  irq_trigger(irq_entry),
++						  irq_polarity(irq_entry));
++				continue;
++
++			}
++
++			/*
++			 * Honour affinities which have been set in early boot
++			 */
++			desc = irq_to_desc(irq);
++			if (desc->status &
++			    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
++				mask = desc->affinity;
++			else
++				mask = TARGET_CPUS;
++
++#ifdef CONFIG_INTR_REMAP
++			if (intr_remapping_enabled)
++				set_ir_ioapic_affinity_irq(irq, mask);
++			else
++#endif
++				set_ioapic_affinity_irq(irq, mask);
++		}
++
++	}
++}
++#endif
++
++#define IOAPIC_RESOURCE_NAME_SIZE 11
++
++static struct resource *ioapic_resources;
++
++static struct resource * __init ioapic_setup_resources(void)
++{
++	unsigned long n;
++	struct resource *res;
++	char *mem;
++	int i;
++
++	if (nr_ioapics <= 0)
++		return NULL;
++
++	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
++	n *= nr_ioapics;
++
++	mem = alloc_bootmem(n);
++	res = (void *)mem;
++
++	if (mem != NULL) {
++		mem += sizeof(struct resource) * nr_ioapics;
++
++		for (i = 0; i < nr_ioapics; i++) {
++			res[i].name = mem;
++			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++			sprintf(mem,  "IOAPIC %u", i);
++			mem += IOAPIC_RESOURCE_NAME_SIZE;
++		}
++	}
++
++	ioapic_resources = res;
++
++	return res;
++}
++
++void __init ioapic_init_mappings(void)
++{
++	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
++	struct resource *ioapic_res;
++	int i;
++
++	irq_2_pin_init();
++	ioapic_res = ioapic_setup_resources();
++	for (i = 0; i < nr_ioapics; i++) {
++		if (smp_found_config) {
++			ioapic_phys = mp_ioapics[i].mp_apicaddr;
++#ifdef CONFIG_X86_32
++			if (!ioapic_phys) {
++				printk(KERN_ERR
++				       "WARNING: bogus zero IO-APIC "
++				       "address found in MPTABLE, "
++				       "disabling IO/APIC support!\n");
++				smp_found_config = 0;
++				skip_ioapic_setup = 1;
++				goto fake_ioapic_page;
++			}
++#endif
++		} else {
++#ifdef CONFIG_X86_32
++fake_ioapic_page:
++#endif
++			ioapic_phys = (unsigned long)
++				alloc_bootmem_pages(PAGE_SIZE);
++			ioapic_phys = __pa(ioapic_phys);
++		}
++		set_fixmap_nocache(idx, ioapic_phys);
++		apic_printk(APIC_VERBOSE,
++			    "mapped IOAPIC to %08lx (%08lx)\n",
++			    __fix_to_virt(idx), ioapic_phys);
++		idx++;
++
++		if (ioapic_res != NULL) {
++			ioapic_res->start = ioapic_phys;
++			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
++			ioapic_res++;
++		}
++	}
++}
++
++static int __init ioapic_insert_resources(void)
++{
++	int i;
++	struct resource *r = ioapic_resources;
++
++	if (!r) {
++		printk(KERN_ERR
++		       "IO APIC resources could be not be allocated.\n");
++		return -1;
++	}
++
++	for (i = 0; i < nr_ioapics; i++) {
++		insert_resource(&iomem_resource, r);
++		r++;
++	}
++
++	return 0;
++}
++
++/* Insert the IO APIC resources after PCI initialization has occured to handle
++ * IO APICS that are mapped in on a BAR in PCI space. */
++late_initcall(ioapic_insert_resources);
++#endif /* !CONFIG_XEN */
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,2985 +0,0 @@
+-/*
+- *	Intel IO-APIC support for multi-Pentium hosts.
+- *
+- *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
+- *
+- *	Many thanks to Stig Venaas for trying out countless experimental
+- *	patches and reporting/debugging problems patiently!
+- *
+- *	(c) 1999, Multiple IO-APIC support, developed by
+- *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+- *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+- *	further tested and cleaned up by Zach Brown <zab@redhat.com>
+- *	and Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+- *					thanks to Eric Gilmore
+- *					and Rolf G. Tews
+- *					for testing these extensively
+- *	Paul Diefenbaugh	:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/sched.h>
+-#include <linux/bootmem.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/compiler.h>
+-#include <linux/acpi.h>
+-#include <linux/module.h>
+-#include <linux/sysdev.h>
+-#include <linux/pci.h>
+-#include <linux/msi.h>
+-#include <linux/htirq.h>
+-#include <linux/freezer.h>
+-#include <linux/kthread.h>
+-#include <linux/jiffies.h>	/* time_after() */
+-
+-#include <asm/io.h>
+-#include <asm/smp.h>
+-#include <asm/desc.h>
+-#include <asm/timer.h>
+-#include <asm/i8259.h>
+-#include <asm/nmi.h>
+-#include <asm/msidef.h>
+-#include <asm/hypertransport.h>
+-
+-#include <mach_apic.h>
+-#include <mach_apicdef.h>
+-
+-#ifdef CONFIG_XEN
+-#include <xen/interface/xen.h>
+-#include <xen/interface/physdev.h>
+-#include <xen/evtchn.h>
+-
+-/* Fake i8259 */
+-#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
+-#define disable_8259A_irq(_irq)  ((void)0)
+-#define i8259A_irq_pending(_irq) (0)
+-
+-unsigned long io_apic_irqs;
+-
+-#define clear_IO_APIC() ((void)0)
+-#endif /* CONFIG_XEN */
+-
+-int (*ioapic_renumber_irq)(int ioapic, int irq);
+-atomic_t irq_mis_count;
+-
+-#ifndef CONFIG_XEN
+-/* Where if anywhere is the i8259 connect in external int mode */
+-static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+-#endif
+-
+-static DEFINE_SPINLOCK(ioapic_lock);
+-static DEFINE_SPINLOCK(vector_lock);
+-
+-int timer_through_8259 __initdata;
+-
+-/*
+- *	Is the SiS APIC rmw bug present ?
+- *	-1 = don't know, 0 = no, 1 = yes
+- */
+-int sis_apic_bug = -1;
+-
+-/*
+- * # of IRQ routing registers
+- */
+-int nr_ioapic_registers[MAX_IO_APICS];
+-
+-/* I/O APIC entries */
+-struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
+-int nr_ioapics;
+-
+-/* MP IRQ source entries */
+-struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* # of MP IRQ source entries */
+-int mp_irq_entries;
+-
+-#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+-int mp_bus_id_to_type[MAX_MP_BUSSES];
+-#endif
+-
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-
+-static int disable_timer_pin_1 __initdata;
+-
+-/*
+- * Rough estimation of how many shared IRQs there are, can
+- * be changed anytime.
+- */
+-#define MAX_PLUS_SHARED_IRQS NR_IRQS
+-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
+-
+-/*
+- * This is performance-critical, we want to do it O(1)
+- *
+- * the indexing order of this array favors 1:1 mappings
+- * between pins and IRQs.
+- */
+-
+-static struct irq_pin_list {
+-	int apic, pin, next;
+-} irq_2_pin[PIN_MAP_SIZE];
+-
+-#ifndef CONFIG_XEN
+-struct io_apic {
+-	unsigned int index;
+-	unsigned int unused[3];
+-	unsigned int data;
+-};
+-
+-static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+-{
+-	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+-		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+-}
+-#endif
+-
+-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+-{
+-#ifndef CONFIG_XEN
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	writel(reg, &io_apic->index);
+-	return readl(&io_apic->data);
+-#else
+-	struct physdev_apic apic_op;
+-	int ret;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+-	apic_op.reg = reg;
+-	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+-	if (ret)
+-		return ret;
+-	return apic_op.value;
+-#endif
+-}
+-
+-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+-{
+-#ifndef CONFIG_XEN
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	writel(reg, &io_apic->index);
+-	writel(value, &io_apic->data);
+-#else
+-	struct physdev_apic apic_op;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+-	apic_op.reg = reg;
+-	apic_op.value = value;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+-#endif
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Re-write a value: to be used for read-modify-write
+- * cycles where the read already set up the index register.
+- *
+- * Older SiS APIC requires we rewrite the index register
+- */
+-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+-{
+-	volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	if (sis_apic_bug)
+-		writel(reg, &io_apic->index);
+-	writel(value, &io_apic->data);
+-}
+-#else
+-#define io_apic_modify io_apic_write
+-#endif
+-
+-union entry_union {
+-	struct { u32 w1, w2; };
+-	struct IO_APIC_route_entry entry;
+-};
+-
+-#ifndef CONFIG_XEN
+-static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+-{
+-	union entry_union eu;
+-	unsigned long flags;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	return eu.entry;
+-}
+-#endif
+-
+-/*
+- * When we write a new IO APIC routing entry, we need to write the high
+- * word first! If the mask bit in the low word is clear, we will enable
+- * the interrupt, and we need to make sure the entry is fully populated
+- * before that happens.
+- */
+-static void
+-__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+-{
+-	union entry_union eu;
+-	eu.entry = e;
+-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+-}
+-
+-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+-{
+-	unsigned long flags;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__ioapic_write_entry(apic, pin, e);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * When we mask an IO APIC routing entry, we need to write the low
+- * word first, in order to set the mask bit before we change the
+- * high bits!
+- */
+-static void ioapic_mask_entry(int apic, int pin)
+-{
+-	unsigned long flags;
+-	union entry_union eu = { .entry.mask = 1 };
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-#endif
+-
+-/*
+- * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+- * shared ISA-space IRQs, so we have to support them. We are super
+- * fast in the common case, and fast for shared ISA-space IRQs.
+- */
+-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
+-{
+-	static int first_free_entry = NR_IRQS;
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-
+-	while (entry->next)
+-		entry = irq_2_pin + entry->next;
+-
+-	if (entry->pin != -1) {
+-		entry->next = first_free_entry;
+-		entry = irq_2_pin + entry->next;
+-		if (++first_free_entry >= PIN_MAP_SIZE)
+-			panic("io_apic.c: whoops");
+-	}
+-	entry->apic = apic;
+-	entry->pin = pin;
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Reroute an IRQ to a different pin.
+- */
+-static void __init replace_pin_at_irq(unsigned int irq,
+-				      int oldapic, int oldpin,
+-				      int newapic, int newpin)
+-{
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-
+-	while (1) {
+-		if (entry->apic == oldapic && entry->pin == oldpin) {
+-			entry->apic = newapic;
+-			entry->pin = newpin;
+-		}
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-}
+-
+-static void __modify_IO_APIC_irq(unsigned int irq, unsigned long enable, unsigned long disable)
+-{
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-	unsigned int pin, reg;
+-
+-	for (;;) {
+-		pin = entry->pin;
+-		if (pin == -1)
+-			break;
+-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+-		reg &= ~disable;
+-		reg |= enable;
+-		io_apic_modify(entry->apic, 0x10 + pin*2, reg);
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-}
+-
+-/* mask = 1 */
+-static void __mask_IO_APIC_irq(unsigned int irq)
+-{
+-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED, 0);
+-}
+-
+-/* mask = 0 */
+-static void __unmask_IO_APIC_irq(unsigned int irq)
+-{
+-	__modify_IO_APIC_irq(irq, 0, IO_APIC_REDIR_MASKED);
+-}
+-
+-/* mask = 1, trigger = 0 */
+-static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
+-{
+-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_MASKED,
+-				IO_APIC_REDIR_LEVEL_TRIGGER);
+-}
+-
+-/* mask = 0, trigger = 1 */
+-static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
+-{
+-	__modify_IO_APIC_irq(irq, IO_APIC_REDIR_LEVEL_TRIGGER,
+-				IO_APIC_REDIR_MASKED);
+-}
+-
+-static void mask_IO_APIC_irq(unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__mask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-static void unmask_IO_APIC_irq(unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__unmask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+-{
+-	struct IO_APIC_route_entry entry;
+-
+-	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+-	entry = ioapic_read_entry(apic, pin);
+-	if (entry.delivery_mode == dest_SMI)
+-		return;
+-
+-	/*
+-	 * Disable it in the IO-APIC irq-routing table:
+-	 */
+-	ioapic_mask_entry(apic, pin);
+-}
+-
+-static void clear_IO_APIC(void)
+-{
+-	int apic, pin;
+-
+-	for (apic = 0; apic < nr_ioapics; apic++)
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+-			clear_IO_APIC_pin(apic, pin);
+-}
+-
+-#ifdef CONFIG_SMP
+-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
+-{
+-	unsigned long flags;
+-	int pin;
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-	unsigned int apicid_value;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, cpumask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	cpus_and(cpumask, tmp, CPU_MASK_ALL);
+-
+-	apicid_value = cpu_mask_to_apicid(cpumask);
+-	/* Prepare to do the io_apic_write */
+-	apicid_value = apicid_value << 24;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	for (;;) {
+-		pin = entry->pin;
+-		if (pin == -1)
+-			break;
+-		io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value);
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-	irq_desc[irq].affinity = cpumask;
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-#if defined(CONFIG_IRQBALANCE)
+-# include <asm/processor.h>	/* kernel_thread() */
+-# include <linux/kernel_stat.h>	/* kstat */
+-# include <linux/slab.h>		/* kmalloc() */
+-# include <linux/timer.h>
+-
+-#define IRQBALANCE_CHECK_ARCH -999
+-#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+-#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
+-#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
+-#define BALANCED_IRQ_LESS_DELTA		(HZ)
+-
+-static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
+-static int physical_balance __read_mostly;
+-static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
+-
+-static struct irq_cpu_info {
+-	unsigned long *last_irq;
+-	unsigned long *irq_delta;
+-	unsigned long irq;
+-} irq_cpu_data[NR_CPUS];
+-
+-#define CPU_IRQ(cpu)		(irq_cpu_data[cpu].irq)
+-#define LAST_CPU_IRQ(cpu, irq)   (irq_cpu_data[cpu].last_irq[irq])
+-#define IRQ_DELTA(cpu, irq) 	(irq_cpu_data[cpu].irq_delta[irq])
+-
+-#define IDLE_ENOUGH(cpu,now) \
+-	(idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1))
+-
+-#define IRQ_ALLOWED(cpu, allowed_mask)	cpu_isset(cpu, allowed_mask)
+-
+-#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i)))
+-
+-static cpumask_t balance_irq_affinity[NR_IRQS] = {
+-	[0 ... NR_IRQS-1] = CPU_MASK_ALL
+-};
+-
+-void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	balance_irq_affinity[irq] = mask;
+-}
+-
+-static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
+-			unsigned long now, int direction)
+-{
+-	int search_idle = 1;
+-	int cpu = curr_cpu;
+-
+-	goto inside;
+-
+-	do {
+-		if (unlikely(cpu == curr_cpu))
+-			search_idle = 0;
+-inside:
+-		if (direction == 1) {
+-			cpu++;
+-			if (cpu >= NR_CPUS)
+-				cpu = 0;
+-		} else {
+-			cpu--;
+-			if (cpu == -1)
+-				cpu = NR_CPUS-1;
+-		}
+-	} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu, allowed_mask) ||
+-			(search_idle && !IDLE_ENOUGH(cpu, now)));
+-
+-	return cpu;
+-}
+-
+-static inline void balance_irq(int cpu, int irq)
+-{
+-	unsigned long now = jiffies;
+-	cpumask_t allowed_mask;
+-	unsigned int new_cpu;
+-
+-	if (irqbalance_disabled)
+-		return;
+-
+-	cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
+-	new_cpu = move(cpu, allowed_mask, now, 1);
+-	if (cpu != new_cpu)
+-		set_pending_irq(irq, cpumask_of_cpu(new_cpu));
+-}
+-
+-static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
+-{
+-	int i, j;
+-
+-	for_each_online_cpu(i) {
+-		for (j = 0; j < NR_IRQS; j++) {
+-			if (!irq_desc[j].action)
+-				continue;
+-			/* Is it a significant load ?  */
+-			if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i), j) <
+-						useful_load_threshold)
+-				continue;
+-			balance_irq(i, j);
+-		}
+-	}
+-	balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+-		balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+-	return;
+-}
+-
+-static void do_irq_balance(void)
+-{
+-	int i, j;
+-	unsigned long max_cpu_irq = 0, min_cpu_irq = (~0);
+-	unsigned long move_this_load = 0;
+-	int max_loaded = 0, min_loaded = 0;
+-	int load;
+-	unsigned long useful_load_threshold = balanced_irq_interval + 10;
+-	int selected_irq;
+-	int tmp_loaded, first_attempt = 1;
+-	unsigned long tmp_cpu_irq;
+-	unsigned long imbalance = 0;
+-	cpumask_t allowed_mask, target_cpu_mask, tmp;
+-
+-	for_each_possible_cpu(i) {
+-		int package_index;
+-		CPU_IRQ(i) = 0;
+-		if (!cpu_online(i))
+-			continue;
+-		package_index = CPU_TO_PACKAGEINDEX(i);
+-		for (j = 0; j < NR_IRQS; j++) {
+-			unsigned long value_now, delta;
+-			/* Is this an active IRQ or balancing disabled ? */
+-			if (!irq_desc[j].action || irq_balancing_disabled(j))
+-				continue;
+-			if (package_index == i)
+-				IRQ_DELTA(package_index, j) = 0;
+-			/* Determine the total count per processor per IRQ */
+-			value_now = (unsigned long) kstat_cpu(i).irqs[j];
+-
+-			/* Determine the activity per processor per IRQ */
+-			delta = value_now - LAST_CPU_IRQ(i, j);
+-
+-			/* Update last_cpu_irq[][] for the next time */
+-			LAST_CPU_IRQ(i, j) = value_now;
+-
+-			/* Ignore IRQs whose rate is less than the clock */
+-			if (delta < useful_load_threshold)
+-				continue;
+-			/* update the load for the processor or package total */
+-			IRQ_DELTA(package_index, j) += delta;
+-
+-			/* Keep track of the higher numbered sibling as well */
+-			if (i != package_index)
+-				CPU_IRQ(i) += delta;
+-			/*
+-			 * We have sibling A and sibling B in the package
+-			 *
+-			 * cpu_irq[A] = load for cpu A + load for cpu B
+-			 * cpu_irq[B] = load for cpu B
+-			 */
+-			CPU_IRQ(package_index) += delta;
+-		}
+-	}
+-	/* Find the least loaded processor package */
+-	for_each_online_cpu(i) {
+-		if (i != CPU_TO_PACKAGEINDEX(i))
+-			continue;
+-		if (min_cpu_irq > CPU_IRQ(i)) {
+-			min_cpu_irq = CPU_IRQ(i);
+-			min_loaded = i;
+-		}
+-	}
+-	max_cpu_irq = ULONG_MAX;
+-
+-tryanothercpu:
+-	/*
+-	 * Look for heaviest loaded processor.
+-	 * We may come back to get the next heaviest loaded processor.
+-	 * Skip processors with trivial loads.
+-	 */
+-	tmp_cpu_irq = 0;
+-	tmp_loaded = -1;
+-	for_each_online_cpu(i) {
+-		if (i != CPU_TO_PACKAGEINDEX(i))
+-			continue;
+-		if (max_cpu_irq <= CPU_IRQ(i))
+-			continue;
+-		if (tmp_cpu_irq < CPU_IRQ(i)) {
+-			tmp_cpu_irq = CPU_IRQ(i);
+-			tmp_loaded = i;
+-		}
+-	}
+-
+-	if (tmp_loaded == -1) {
+-	 /*
+-	  * In the case of small number of heavy interrupt sources,
+-	  * loading some of the cpus too much. We use Ingo's original
+-	  * approach to rotate them around.
+-	  */
+-		if (!first_attempt && imbalance >= useful_load_threshold) {
+-			rotate_irqs_among_cpus(useful_load_threshold);
+-			return;
+-		}
+-		goto not_worth_the_effort;
+-	}
+-
+-	first_attempt = 0;		/* heaviest search */
+-	max_cpu_irq = tmp_cpu_irq;	/* load */
+-	max_loaded = tmp_loaded;	/* processor */
+-	imbalance = (max_cpu_irq - min_cpu_irq) / 2;
+-
+-	/*
+-	 * if imbalance is less than approx 10% of max load, then
+-	 * observe diminishing returns action. - quit
+-	 */
+-	if (imbalance < (max_cpu_irq >> 3))
+-		goto not_worth_the_effort;
+-
+-tryanotherirq:
+-	/* if we select an IRQ to move that can't go where we want, then
+-	 * see if there is another one to try.
+-	 */
+-	move_this_load = 0;
+-	selected_irq = -1;
+-	for (j = 0; j < NR_IRQS; j++) {
+-		/* Is this an active IRQ? */
+-		if (!irq_desc[j].action)
+-			continue;
+-		if (imbalance <= IRQ_DELTA(max_loaded, j))
+-			continue;
+-		/* Try to find the IRQ that is closest to the imbalance
+-		 * without going over.
+-		 */
+-		if (move_this_load < IRQ_DELTA(max_loaded, j)) {
+-			move_this_load = IRQ_DELTA(max_loaded, j);
+-			selected_irq = j;
+-		}
+-	}
+-	if (selected_irq == -1)
+-		goto tryanothercpu;
+-
+-	imbalance = move_this_load;
+-
+-	/* For physical_balance case, we accumulated both load
+-	 * values in the one of the siblings cpu_irq[],
+-	 * to use the same code for physical and logical processors
+-	 * as much as possible.
+-	 *
+-	 * NOTE: the cpu_irq[] array holds the sum of the load for
+-	 * sibling A and sibling B in the slot for the lowest numbered
+-	 * sibling (A), _AND_ the load for sibling B in the slot for
+-	 * the higher numbered sibling.
+-	 *
+-	 * We seek the least loaded sibling by making the comparison
+-	 * (A+B)/2 vs B
+-	 */
+-	load = CPU_IRQ(min_loaded) >> 1;
+-	for_each_cpu_mask(j, per_cpu(cpu_sibling_map, min_loaded)) {
+-		if (load > CPU_IRQ(j)) {
+-			/* This won't change cpu_sibling_map[min_loaded] */
+-			load = CPU_IRQ(j);
+-			min_loaded = j;
+-		}
+-	}
+-
+-	cpus_and(allowed_mask,
+-		cpu_online_map,
+-		balance_irq_affinity[selected_irq]);
+-	target_cpu_mask = cpumask_of_cpu(min_loaded);
+-	cpus_and(tmp, target_cpu_mask, allowed_mask);
+-
+-	if (!cpus_empty(tmp)) {
+-		/* mark for change destination */
+-		set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+-
+-		/* Since we made a change, come back sooner to
+-		 * check for more variation.
+-		 */
+-		balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL,
+-			balanced_irq_interval - BALANCED_IRQ_LESS_DELTA);
+-		return;
+-	}
+-	goto tryanotherirq;
+-
+-not_worth_the_effort:
+-	/*
+-	 * if we did not find an IRQ to move, then adjust the time interval
+-	 * upward
+-	 */
+-	balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
+-		balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
+-	return;
+-}
+-
+-static int balanced_irq(void *unused)
+-{
+-	int i;
+-	unsigned long prev_balance_time = jiffies;
+-	long time_remaining = balanced_irq_interval;
+-
+-	/* push everything to CPU 0 to give us a starting point.  */
+-	for (i = 0 ; i < NR_IRQS ; i++) {
+-		irq_desc[i].pending_mask = cpumask_of_cpu(0);
+-		set_pending_irq(i, cpumask_of_cpu(0));
+-	}
+-
+-	set_freezable();
+-	for ( ; ; ) {
+-		time_remaining = schedule_timeout_interruptible(time_remaining);
+-		try_to_freeze();
+-		if (time_after(jiffies,
+-				prev_balance_time+balanced_irq_interval)) {
+-			preempt_disable();
+-			do_irq_balance();
+-			prev_balance_time = jiffies;
+-			time_remaining = balanced_irq_interval;
+-			preempt_enable();
+-		}
+-	}
+-	return 0;
+-}
+-
+-static int __init balanced_irq_init(void)
+-{
+-	int i;
+-	struct cpuinfo_x86 *c;
+-	cpumask_t tmp;
+-
+-	cpus_shift_right(tmp, cpu_online_map, 2);
+-	c = &boot_cpu_data;
+-	/* When not overwritten by the command line ask subarchitecture. */
+-	if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH)
+-		irqbalance_disabled = NO_BALANCE_IRQ;
+-	if (irqbalance_disabled)
+-		return 0;
+-
+-	 /* disable irqbalance completely if there is only one processor online */
+-	if (num_online_cpus() < 2) {
+-		irqbalance_disabled = 1;
+-		return 0;
+-	}
+-	/*
+-	 * Enable physical balance only if more than 1 physical processor
+-	 * is present
+-	 */
+-	if (smp_num_siblings > 1 && !cpus_empty(tmp))
+-		physical_balance = 1;
+-
+-	for_each_online_cpu(i) {
+-		irq_cpu_data[i].irq_delta = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+-		irq_cpu_data[i].last_irq = kzalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
+-		if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
+-			printk(KERN_ERR "balanced_irq_init: out of memory");
+-			goto failed;
+-		}
+-	}
+-
+-	printk(KERN_INFO "Starting balanced_irq\n");
+-	if (!IS_ERR(kthread_run(balanced_irq, NULL, "kirqd")))
+-		return 0;
+-	printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
+-failed:
+-	for_each_possible_cpu(i) {
+-		kfree(irq_cpu_data[i].irq_delta);
+-		irq_cpu_data[i].irq_delta = NULL;
+-		kfree(irq_cpu_data[i].last_irq);
+-		irq_cpu_data[i].last_irq = NULL;
+-	}
+-	return 0;
+-}
+-
+-int __devinit irqbalance_disable(char *str)
+-{
+-	irqbalance_disabled = 1;
+-	return 1;
+-}
+-
+-__setup("noirqbalance", irqbalance_disable);
+-
+-late_initcall(balanced_irq_init);
+-#endif /* CONFIG_IRQBALANCE */
+-#endif /* CONFIG_SMP */
+-#endif
+-
+-#ifndef CONFIG_SMP
+-void send_IPI_self(int vector)
+-{
+-#ifndef CONFIG_XEN
+-	unsigned int cfg;
+-
+-	/*
+-	 * Wait for idle.
+-	 */
+-	apic_wait_icr_idle();
+-	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+-	/*
+-	 * Send the IPI. The write to APIC_ICR fires this off.
+-	 */
+-	apic_write(APIC_ICR, cfg);
+-#endif
+-}
+-#endif /* !CONFIG_SMP */
+-
+-
+-/*
+- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
+- * specific CPU-side IRQs.
+- */
+-
+-#define MAX_PIRQS 8
+-static int pirq_entries [MAX_PIRQS];
+-static int pirqs_enabled;
+-int skip_ioapic_setup;
+-
+-static int __init ioapic_pirq_setup(char *str)
+-{
+-	int i, max;
+-	int ints[MAX_PIRQS+1];
+-
+-	get_options(str, ARRAY_SIZE(ints), ints);
+-
+-	for (i = 0; i < MAX_PIRQS; i++)
+-		pirq_entries[i] = -1;
+-
+-	pirqs_enabled = 1;
+-	apic_printk(APIC_VERBOSE, KERN_INFO
+-			"PIRQ redirection, working around broken MP-BIOS.\n");
+-	max = MAX_PIRQS;
+-	if (ints[0] < MAX_PIRQS)
+-		max = ints[0];
+-
+-	for (i = 0; i < max; i++) {
+-		apic_printk(APIC_VERBOSE, KERN_DEBUG
+-				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+-		/*
+-		 * PIRQs are mapped upside down, usually.
+-		 */
+-		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+-	}
+-	return 1;
+-}
+-
+-__setup("pirq=", ioapic_pirq_setup);
+-
+-/*
+- * Find the IRQ entry number of a certain pin.
+- */
+-static int find_irq_entry(int apic, int pin, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == type &&
+-		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
+-		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
+-		    mp_irqs[i].mp_dstirq == pin)
+-			return i;
+-
+-	return -1;
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Find the pin to which IRQ[irq] (ISA) is connected
+- */
+-static int __init find_isa_irq_pin(int irq, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
+-
+-			return mp_irqs[i].mp_dstirq;
+-	}
+-	return -1;
+-}
+-
+-static int __init find_isa_irq_apic(int irq, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
+-			break;
+-	}
+-	if (i < mp_irq_entries) {
+-		int apic;
+-		for (apic = 0; apic < nr_ioapics; apic++) {
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
+-				return apic;
+-		}
+-	}
+-
+-	return -1;
+-}
+-#endif
+-
+-/*
+- * Find a specific PCI IRQ entry.
+- * Not an __init, possibly needed by modules
+- */
+-static int pin_2_irq(int idx, int apic, int pin);
+-
+-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+-{
+-	int apic, i, best_guess = -1;
+-
+-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
+-		"slot:%d, pin:%d.\n", bus, slot, pin);
+-	if (test_bit(bus, mp_bus_not_pci)) {
+-		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+-		return -1;
+-	}
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
+-			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
+-				break;
+-
+-		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].mp_irqtype &&
+-		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i, apic, mp_irqs[i].mp_dstirq);
+-
+-			if (!(apic || IO_APIC_IRQ(irq)))
+-				continue;
+-
+-			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
+-				return irq;
+-			/*
+-			 * Use the first all-but-pin matching entry as a
+-			 * best-guess fuzzy result for broken mptables.
+-			 */
+-			if (best_guess < 0)
+-				best_guess = irq;
+-		}
+-	}
+-	return best_guess;
+-}
+-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+-
+-/*
+- * This function currently is only a helper for the i386 smp boot process where
+- * we need to reprogram the ioredtbls to cater for the cpus which have come online
+- * so mask in all cases should simply be TARGET_CPUS
+- */
+-#ifdef CONFIG_SMP
+-#ifndef CONFIG_XEN
+-void __init setup_ioapic_dest(void)
+-{
+-	int pin, ioapic, irq, irq_entry;
+-
+-	if (skip_ioapic_setup == 1)
+-		return;
+-
+-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+-			if (irq_entry == -1)
+-				continue;
+-			irq = pin_2_irq(irq_entry, ioapic, pin);
+-			set_ioapic_affinity_irq(irq, TARGET_CPUS);
+-		}
+-
+-	}
+-}
+-#endif /* !CONFIG_XEN */
+-#endif
+-
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+-/*
+- * EISA Edge/Level control register, ELCR
+- */
+-static int EISA_ELCR(unsigned int irq)
+-{
+-	if (irq < 16) {
+-		unsigned int port = 0x4d0 + (irq >> 3);
+-		return (inb(port) >> (irq & 7)) & 1;
+-	}
+-	apic_printk(APIC_VERBOSE, KERN_INFO
+-			"Broken MPtable reports ISA irq %d\n", irq);
+-	return 0;
+-}
+-#endif
+-
+-/* ISA interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_ISA_trigger(idx)	(0)
+-#define default_ISA_polarity(idx)	(0)
+-
+-/* EISA interrupts are always polarity zero and can be edge or level
+- * trigger depending on the ELCR value.  If an interrupt is listed as
+- * EISA conforming in the MP table, that means its trigger type must
+- * be read in from the ELCR */
+-
+-#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mp_srcbusirq))
+-#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+-
+-/* PCI interrupts are always polarity one level triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_PCI_trigger(idx)	(1)
+-#define default_PCI_polarity(idx)	(1)
+-
+-/* MCA interrupts are always polarity zero level triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_MCA_trigger(idx)	(1)
+-#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
+-
+-static int MPBIOS_polarity(int idx)
+-{
+-	int bus = mp_irqs[idx].mp_srcbus;
+-	int polarity;
+-
+-	/*
+-	 * Determine IRQ line polarity (high active or low active):
+-	 */
+-	switch (mp_irqs[idx].mp_irqflag & 3) {
+-	case 0: /* conforms, ie. bus-type dependent polarity */
+-	{
+-		polarity = test_bit(bus, mp_bus_not_pci)?
+-			default_ISA_polarity(idx):
+-			default_PCI_polarity(idx);
+-		break;
+-	}
+-	case 1: /* high active */
+-	{
+-		polarity = 0;
+-		break;
+-	}
+-	case 2: /* reserved */
+-	{
+-		printk(KERN_WARNING "broken BIOS!!\n");
+-		polarity = 1;
+-		break;
+-	}
+-	case 3: /* low active */
+-	{
+-		polarity = 1;
+-		break;
+-	}
+-	default: /* invalid */
+-	{
+-		printk(KERN_WARNING "broken BIOS!!\n");
+-		polarity = 1;
+-		break;
+-	}
+-	}
+-	return polarity;
+-}
+-
+-static int MPBIOS_trigger(int idx)
+-{
+-	int bus = mp_irqs[idx].mp_srcbus;
+-	int trigger;
+-
+-	/*
+-	 * Determine IRQ trigger mode (edge or level sensitive):
+-	 */
+-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3) {
+-	case 0: /* conforms, ie. bus-type dependent */
+-	{
+-		trigger = test_bit(bus, mp_bus_not_pci)?
+-				default_ISA_trigger(idx):
+-				default_PCI_trigger(idx);
+-#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+-		switch (mp_bus_id_to_type[bus]) {
+-		case MP_BUS_ISA: /* ISA pin */
+-		{
+-			/* set before the switch */
+-			break;
+-		}
+-		case MP_BUS_EISA: /* EISA pin */
+-		{
+-			trigger = default_EISA_trigger(idx);
+-			break;
+-		}
+-		case MP_BUS_PCI: /* PCI pin */
+-		{
+-			/* set before the switch */
+-			break;
+-		}
+-		case MP_BUS_MCA: /* MCA pin */
+-		{
+-			trigger = default_MCA_trigger(idx);
+-			break;
+-		}
+-		default:
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			trigger = 1;
+-			break;
+-		}
+-	}
+-#endif
+-		break;
+-	}
+-	case 1: /* edge */
+-	{
+-		trigger = 0;
+-		break;
+-	}
+-	case 2: /* reserved */
+-	{
+-		printk(KERN_WARNING "broken BIOS!!\n");
+-		trigger = 1;
+-		break;
+-	}
+-	case 3: /* level */
+-	{
+-		trigger = 1;
+-		break;
+-	}
+-	default: /* invalid */
+-	{
+-		printk(KERN_WARNING "broken BIOS!!\n");
+-		trigger = 0;
+-		break;
+-	}
+-	}
+-	return trigger;
+-}
+-
+-static inline int irq_polarity(int idx)
+-{
+-	return MPBIOS_polarity(idx);
+-}
+-
+-static inline int irq_trigger(int idx)
+-{
+-	return MPBIOS_trigger(idx);
+-}
+-
+-static int pin_2_irq(int idx, int apic, int pin)
+-{
+-	int irq, i;
+-	int bus = mp_irqs[idx].mp_srcbus;
+-
+-	/*
+-	 * Debugging check, we are in big trouble if this message pops up!
+-	 */
+-	if (mp_irqs[idx].mp_dstirq != pin)
+-		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+-
+-	if (test_bit(bus, mp_bus_not_pci))
+-		irq = mp_irqs[idx].mp_srcbusirq;
+-	else {
+-		/*
+-		 * PCI IRQs are mapped in order
+-		 */
+-		i = irq = 0;
+-		while (i < apic)
+-			irq += nr_ioapic_registers[i++];
+-		irq += pin;
+-
+-		/*
+-		 * For MPS mode, so far only needed by ES7000 platform
+-		 */
+-		if (ioapic_renumber_irq)
+-			irq = ioapic_renumber_irq(apic, irq);
+-	}
+-
+-	/*
+-	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
+-	 */
+-	if ((pin >= 16) && (pin <= 23)) {
+-		if (pirq_entries[pin-16] != -1) {
+-			if (!pirq_entries[pin-16]) {
+-				apic_printk(APIC_VERBOSE, KERN_DEBUG
+-						"disabling PIRQ%d\n", pin-16);
+-			} else {
+-				irq = pirq_entries[pin-16];
+-				apic_printk(APIC_VERBOSE, KERN_DEBUG
+-						"using PIRQ%d -> IRQ %d\n",
+-						pin-16, irq);
+-			}
+-		}
+-	}
+-	return irq;
+-}
+-
+-static inline int IO_APIC_irq_trigger(int irq)
+-{
+-	int apic, idx, pin;
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-			idx = find_irq_entry(apic, pin, mp_INT);
+-			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+-				return irq_trigger(idx);
+-		}
+-	}
+-	/*
+-	 * nonexistent IRQs are edge default
+-	 */
+-	return 0;
+-}
+-
+-/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */
+-
+-static int __assign_irq_vector(int irq)
+-{
+-	int vector;
+-	struct physdev_irq irq_op;
+-
+-	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+-
+-	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+-		return -EINVAL;
+-
+-	if (irq_vector[irq] > 0)
+-		return irq_vector[irq];
+-
+-	irq_op.irq = irq;
+-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+-		return -ENOSPC;
+-
+-	vector = irq_op.vector;
+-	irq_vector[irq] = vector;
+-
+-	return vector;
+-}
+-
+-static int assign_irq_vector(int irq)
+-{
+-	unsigned long flags;
+-	int vector;
+-
+-	spin_lock_irqsave(&vector_lock, flags);
+-	vector = __assign_irq_vector(irq);
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-
+-	return vector;
+-}
+-
+-#ifndef CONFIG_XEN
+-static struct irq_chip ioapic_chip;
+-
+-#define IOAPIC_AUTO	-1
+-#define IOAPIC_EDGE	0
+-#define IOAPIC_LEVEL	1
+-
+-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+-{
+-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+-	    trigger == IOAPIC_LEVEL) {
+-		irq_desc[irq].status |= IRQ_LEVEL;
+-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+-					 handle_fasteoi_irq, "fasteoi");
+-	} else {
+-		irq_desc[irq].status &= ~IRQ_LEVEL;
+-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+-					 handle_edge_irq, "edge");
+-	}
+-	set_intr_gate(vector, interrupt[irq]);
+-}
+-#else
+-#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
+-#endif
+-
+-static void __init setup_IO_APIC_irqs(void)
+-{
+-	struct IO_APIC_route_entry entry;
+-	int apic, pin, idx, irq, first_notcon = 1, vector;
+-
+-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-
+-		/*
+-		 * add it to the IO-APIC irq-routing table:
+-		 */
+-		memset(&entry, 0, sizeof(entry));
+-
+-		entry.delivery_mode = INT_DELIVERY_MODE;
+-		entry.dest_mode = INT_DEST_MODE;
+-		entry.mask = 0;				/* enable IRQ */
+-		entry.dest.logical.logical_dest =
+-					cpu_mask_to_apicid(TARGET_CPUS);
+-
+-		idx = find_irq_entry(apic, pin, mp_INT);
+-		if (idx == -1) {
+-			if (first_notcon) {
+-				apic_printk(APIC_VERBOSE, KERN_DEBUG
+-						" IO-APIC (apicid-pin) %d-%d",
+-						mp_ioapics[apic].mp_apicid,
+-						pin);
+-				first_notcon = 0;
+-			} else
+-				apic_printk(APIC_VERBOSE, ", %d-%d",
+-					mp_ioapics[apic].mp_apicid, pin);
+-			continue;
+-		}
+-
+-		if (!first_notcon) {
+-			apic_printk(APIC_VERBOSE, " not connected.\n");
+-			first_notcon = 1;
+-		}
+-
+-		entry.trigger = irq_trigger(idx);
+-		entry.polarity = irq_polarity(idx);
+-
+-		if (irq_trigger(idx)) {
+-			entry.trigger = 1;
+-			entry.mask = 1;
+-		}
+-
+-		irq = pin_2_irq(idx, apic, pin);
+-		/*
+-		 * skip adding the timer int on secondary nodes, which causes
+-		 * a small but painful rift in the time-space continuum
+-		 */
+-		if (multi_timer_check(apic, irq))
+-			continue;
+-		else
+-			add_pin_to_irq(irq, apic, pin);
+-
+-		if (/*!apic &&*/ !IO_APIC_IRQ(irq))
+-			continue;
+-
+-		if (IO_APIC_IRQ(irq)) {
+-			vector = assign_irq_vector(irq);
+-			entry.vector = vector;
+-			ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+-
+-			if (!apic && (irq < 16))
+-				disable_8259A_irq(irq);
+-		}
+-		ioapic_write_entry(apic, pin, entry);
+-	}
+-	}
+-
+-	if (!first_notcon)
+-		apic_printk(APIC_VERBOSE, " not connected.\n");
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Set up the timer pin, possibly with the 8259A-master behind.
+- */
+-static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
+-					int vector)
+-{
+-	struct IO_APIC_route_entry entry;
+-
+-	memset(&entry, 0, sizeof(entry));
+-
+-	/*
+-	 * We use logical delivery to get the timer IRQ
+-	 * to the first CPU.
+-	 */
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.mask = 1;					/* mask IRQ now */
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+-	entry.delivery_mode = INT_DELIVERY_MODE;
+-	entry.polarity = 0;
+-	entry.trigger = 0;
+-	entry.vector = vector;
+-
+-	/*
+-	 * The timer IRQ doesn't have to know that behind the
+-	 * scene we may have a 8259A-master in AEOI mode ...
+-	 */
+-	ioapic_register_intr(0, vector, IOAPIC_EDGE);
+-
+-	/*
+-	 * Add it to the IO-APIC irq-routing table:
+-	 */
+-	ioapic_write_entry(apic, pin, entry);
+-}
+-
+-void __init print_IO_APIC(void)
+-{
+-	int apic, i;
+-	union IO_APIC_reg_00 reg_00;
+-	union IO_APIC_reg_01 reg_01;
+-	union IO_APIC_reg_02 reg_02;
+-	union IO_APIC_reg_03 reg_03;
+-	unsigned long flags;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+-	for (i = 0; i < nr_ioapics; i++)
+-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+-		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
+-
+-	/*
+-	 * We are a bit conservative about what we expect.  We have to
+-	 * know about every hardware change ASAP.
+-	 */
+-	printk(KERN_INFO "testing the IO APIC.......................\n");
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_00.raw = io_apic_read(apic, 0);
+-	reg_01.raw = io_apic_read(apic, 1);
+-	if (reg_01.bits.version >= 0x10)
+-		reg_02.raw = io_apic_read(apic, 2);
+-	if (reg_01.bits.version >= 0x20)
+-		reg_03.raw = io_apic_read(apic, 3);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
+-	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+-	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+-	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+-	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
+-
+-	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+-
+-	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+-
+-	/*
+-	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+-	 * but the value of reg_02 is read as the previous read register
+-	 * value, so ignore it if reg_02 == reg_01.
+-	 */
+-	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+-		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+-		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+-	}
+-
+-	/*
+-	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
+-	 * or reg_03, but the value of reg_0[23] is read as the previous read
+-	 * register value, so ignore it if reg_03 == reg_0[12].
+-	 */
+-	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+-	    reg_03.raw != reg_01.raw) {
+-		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+-		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+-	}
+-
+-	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+-
+-	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
+-			  " Stat Dest Deli Vect:   \n");
+-
+-	for (i = 0; i <= reg_01.bits.entries; i++) {
+-		struct IO_APIC_route_entry entry;
+-
+-		entry = ioapic_read_entry(apic, i);
+-
+-		printk(KERN_DEBUG " %02x %03X %02X  ",
+-			i,
+-			entry.dest.logical.logical_dest,
+-			entry.dest.physical.physical_dest
+-		);
+-
+-		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
+-			entry.mask,
+-			entry.trigger,
+-			entry.irr,
+-			entry.polarity,
+-			entry.delivery_status,
+-			entry.dest_mode,
+-			entry.delivery_mode,
+-			entry.vector
+-		);
+-	}
+-	}
+-	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+-	for (i = 0; i < NR_IRQS; i++) {
+-		struct irq_pin_list *entry = irq_2_pin + i;
+-		if (entry->pin < 0)
+-			continue;
+-		printk(KERN_DEBUG "IRQ%d ", i);
+-		for (;;) {
+-			printk("-> %d:%d", entry->apic, entry->pin);
+-			if (!entry->next)
+-				break;
+-			entry = irq_2_pin + entry->next;
+-		}
+-		printk("\n");
+-	}
+-
+-	printk(KERN_INFO ".................................... done.\n");
+-
+-	return;
+-}
+-
+-static void print_APIC_bitfield(int base)
+-{
+-	unsigned int v;
+-	int i, j;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
+-	for (i = 0; i < 8; i++) {
+-		v = apic_read(base + i*0x10);
+-		for (j = 0; j < 32; j++) {
+-			if (v & (1<<j))
+-				printk("1");
+-			else
+-				printk("0");
+-		}
+-		printk("\n");
+-	}
+-}
+-
+-void /*__init*/ print_local_APIC(void *dummy)
+-{
+-	unsigned int v, ver, maxlvt;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+-		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v,
+-			GET_APIC_ID(read_apic_id()));
+-	v = apic_read(APIC_LVR);
+-	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+-	ver = GET_APIC_VERSION(v);
+-	maxlvt = lapic_get_maxlvt();
+-
+-	v = apic_read(APIC_TASKPRI);
+-	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+-
+-	if (APIC_INTEGRATED(ver)) {			/* !82489DX */
+-		v = apic_read(APIC_ARBPRI);
+-		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+-			v & APIC_ARBPRI_MASK);
+-		v = apic_read(APIC_PROCPRI);
+-		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+-	}
+-
+-	v = apic_read(APIC_EOI);
+-	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
+-	v = apic_read(APIC_RRR);
+-	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+-	v = apic_read(APIC_LDR);
+-	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
+-	v = apic_read(APIC_DFR);
+-	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+-	v = apic_read(APIC_SPIV);
+-	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
+-
+-	printk(KERN_DEBUG "... APIC ISR field:\n");
+-	print_APIC_bitfield(APIC_ISR);
+-	printk(KERN_DEBUG "... APIC TMR field:\n");
+-	print_APIC_bitfield(APIC_TMR);
+-	printk(KERN_DEBUG "... APIC IRR field:\n");
+-	print_APIC_bitfield(APIC_IRR);
+-
+-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
+-		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
+-			apic_write(APIC_ESR, 0);
+-		v = apic_read(APIC_ESR);
+-		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+-	}
+-
+-	v = apic_read(APIC_ICR);
+-	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
+-	v = apic_read(APIC_ICR2);
+-	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
+-
+-	v = apic_read(APIC_LVTT);
+-	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
+-
+-	if (maxlvt > 3) {                       /* PC is LVT#4. */
+-		v = apic_read(APIC_LVTPC);
+-		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
+-	}
+-	v = apic_read(APIC_LVT0);
+-	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
+-	v = apic_read(APIC_LVT1);
+-	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
+-
+-	if (maxlvt > 2) {			/* ERR is LVT#3. */
+-		v = apic_read(APIC_LVTERR);
+-		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
+-	}
+-
+-	v = apic_read(APIC_TMICT);
+-	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
+-	v = apic_read(APIC_TMCCT);
+-	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
+-	v = apic_read(APIC_TDCR);
+-	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+-	printk("\n");
+-}
+-
+-void print_all_local_APICs(void)
+-{
+-	on_each_cpu(print_local_APIC, NULL, 1);
+-}
+-
+-void /*__init*/ print_PIC(void)
+-{
+-	unsigned int v;
+-	unsigned long flags;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "\nprinting PIC contents\n");
+-
+-	spin_lock_irqsave(&i8259A_lock, flags);
+-
+-	v = inb(0xa1) << 8 | inb(0x21);
+-	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
+-
+-	v = inb(0xa0) << 8 | inb(0x20);
+-	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
+-
+-	outb(0x0b, 0xa0);
+-	outb(0x0b, 0x20);
+-	v = inb(0xa0) << 8 | inb(0x20);
+-	outb(0x0a, 0xa0);
+-	outb(0x0a, 0x20);
+-
+-	spin_unlock_irqrestore(&i8259A_lock, flags);
+-
+-	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
+-
+-	v = inb(0x4d1) << 8 | inb(0x4d0);
+-	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+-}
+-#else
+-void __init print_IO_APIC(void) {}
+-#endif /* !CONFIG_XEN */
+-
+-static void __init enable_IO_APIC(void)
+-{
+-	union IO_APIC_reg_01 reg_01;
+-#ifndef CONFIG_XEN
+-	int i8259_apic, i8259_pin;
+-#endif
+-	int i, apic;
+-	unsigned long flags;
+-
+-	for (i = 0; i < PIN_MAP_SIZE; i++) {
+-		irq_2_pin[i].pin = -1;
+-		irq_2_pin[i].next = 0;
+-	}
+-	if (!pirqs_enabled)
+-		for (i = 0; i < MAX_PIRQS; i++)
+-			pirq_entries[i] = -1;
+-
+-	/*
+-	 * The number of IO-APIC IRQ registers (== #pins):
+-	 */
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_01.raw = io_apic_read(apic, 1);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+-	}
+-#ifndef CONFIG_XEN
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		int pin;
+-		/* See if any of the pins is in ExtINT mode */
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-			struct IO_APIC_route_entry entry;
+-			entry = ioapic_read_entry(apic, pin);
+-
+-
+-			/* If the interrupt line is enabled and in ExtInt mode
+-			 * I have found the pin where the i8259 is connected.
+-			 */
+-			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+-				ioapic_i8259.apic = apic;
+-				ioapic_i8259.pin  = pin;
+-				goto found_i8259;
+-			}
+-		}
+-	}
+- found_i8259:
+-	/* Look to see what if the MP table has reported the ExtINT */
+-	/* If we could not find the appropriate pin by looking at the ioapic
+-	 * the i8259 probably is not connected the ioapic but give the
+-	 * mptable a chance anyway.
+-	 */
+-	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
+-	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+-	/* Trust the MP table if nothing is setup in the hardware */
+-	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+-		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+-		ioapic_i8259.pin  = i8259_pin;
+-		ioapic_i8259.apic = i8259_apic;
+-	}
+-	/* Complain if the MP table and the hardware disagree */
+-	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+-		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+-	{
+-		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
+-	}
+-#endif
+-
+-	/*
+-	 * Do not trust the IO-APIC being empty at bootup
+-	 */
+-	clear_IO_APIC();
+-}
+-
+-/*
+- * Not an __init, needed by the reboot code
+- */
+-void disable_IO_APIC(void)
+-{
+-	/*
+-	 * Clear the IO-APIC before rebooting:
+-	 */
+-	clear_IO_APIC();
+-
+-#ifndef CONFIG_XEN
+-	/*
+-	 * If the i8259 is routed through an IOAPIC
+-	 * Put that IOAPIC in virtual wire mode
+-	 * so legacy interrupts can be delivered.
+-	 */
+-	if (ioapic_i8259.pin != -1) {
+-		struct IO_APIC_route_entry entry;
+-
+-		memset(&entry, 0, sizeof(entry));
+-		entry.mask            = 0; /* Enabled */
+-		entry.trigger         = 0; /* Edge */
+-		entry.irr             = 0;
+-		entry.polarity        = 0; /* High */
+-		entry.delivery_status = 0;
+-		entry.dest_mode       = 0; /* Physical */
+-		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+-		entry.vector          = 0;
+-		entry.dest.physical.physical_dest =
+-					GET_APIC_ID(read_apic_id());
+-
+-		/*
+-		 * Add it to the IO-APIC irq-routing table:
+-		 */
+-		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+-	}
+-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+-#endif
+-}
+-
+-/*
+- * function to set the IO-APIC physical IDs based on the
+- * values stored in the MPC table.
+- *
+- * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+- */
+-
+-#ifndef CONFIG_XEN
+-static void __init setup_ioapic_ids_from_mpc(void)
+-{
+-	union IO_APIC_reg_00 reg_00;
+-	physid_mask_t phys_id_present_map;
+-	int apic;
+-	int i;
+-	unsigned char old_id;
+-	unsigned long flags;
+-
+-#ifdef CONFIG_X86_NUMAQ
+-	if (found_numaq)
+-		return;
+-#endif
+-
+-	/*
+-	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+-	 * no meaning without the serial APIC bus.
+-	 */
+-	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+-		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+-		return;
+-	/*
+-	 * This is broken; anything with a real cpu count has to
+-	 * circumvent this idiocy regardless.
+-	 */
+-	phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map);
+-
+-	/*
+-	 * Set the IOAPIC ID to the value stored in the MPC table.
+-	 */
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-
+-		/* Read the register 0 value */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-		old_id = mp_ioapics[apic].mp_apicid;
+-
+-		if (mp_ioapics[apic].mp_apicid >= get_physical_broadcast()) {
+-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+-				apic, mp_ioapics[apic].mp_apicid);
+-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+-				reg_00.bits.ID);
+-			mp_ioapics[apic].mp_apicid = reg_00.bits.ID;
+-		}
+-
+-		/*
+-		 * Sanity check, is the ID really free? Every APIC in a
+-		 * system must have a unique ID or we get lots of nice
+-		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+-		 */
+-		if (check_apicid_used(phys_id_present_map,
+-					mp_ioapics[apic].mp_apicid)) {
+-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+-				apic, mp_ioapics[apic].mp_apicid);
+-			for (i = 0; i < get_physical_broadcast(); i++)
+-				if (!physid_isset(i, phys_id_present_map))
+-					break;
+-			if (i >= get_physical_broadcast())
+-				panic("Max APIC ID exceeded!\n");
+-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+-				i);
+-			physid_set(i, phys_id_present_map);
+-			mp_ioapics[apic].mp_apicid = i;
+-		} else {
+-			physid_mask_t tmp;
+-			tmp = apicid_to_cpu_present(mp_ioapics[apic].mp_apicid);
+-			apic_printk(APIC_VERBOSE, "Setting %d in the "
+-					"phys_id_present_map\n",
+-					mp_ioapics[apic].mp_apicid);
+-			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+-		}
+-
+-
+-		/*
+-		 * We need to adjust the IRQ routing table
+-		 * if the ID changed.
+-		 */
+-		if (old_id != mp_ioapics[apic].mp_apicid)
+-			for (i = 0; i < mp_irq_entries; i++)
+-				if (mp_irqs[i].mp_dstapic == old_id)
+-					mp_irqs[i].mp_dstapic
+-						= mp_ioapics[apic].mp_apicid;
+-
+-		/*
+-		 * Read the right value from the MPC table and
+-		 * write it into the ID register.
+-		 */
+-		apic_printk(APIC_VERBOSE, KERN_INFO
+-			"...changing IO-APIC physical APIC ID to %d ...",
+-			mp_ioapics[apic].mp_apicid);
+-
+-		reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(apic, 0, reg_00.raw);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-		/*
+-		 * Sanity check
+-		 */
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_00.raw = io_apic_read(apic, 0);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		if (reg_00.bits.ID != mp_ioapics[apic].mp_apicid)
+-			printk("could not set ID!\n");
+-		else
+-			apic_printk(APIC_VERBOSE, " ok.\n");
+-	}
+-}
+-
+-int no_timer_check __initdata;
+-
+-static int __init notimercheck(char *s)
+-{
+-	no_timer_check = 1;
+-	return 1;
+-}
+-__setup("no_timer_check", notimercheck);
+-
+-/*
+- * There is a nasty bug in some older SMP boards, their mptable lies
+- * about the timer IRQ. We do the following to work around the situation:
+- *
+- *	- timer IRQ defaults to IO-APIC IRQ
+- *	- if this function detects that timer IRQs are defunct, then we fall
+- *	  back to ISA timer IRQs
+- */
+-static int __init timer_irq_works(void)
+-{
+-	unsigned long t1 = jiffies;
+-	unsigned long flags;
+-
+-	if (no_timer_check)
+-		return 1;
+-
+-	local_save_flags(flags);
+-	local_irq_enable();
+-	/* Let ten ticks pass... */
+-	mdelay((10 * 1000) / HZ);
+-	local_irq_restore(flags);
+-
+-	/*
+-	 * Expect a few ticks at least, to be sure some possible
+-	 * glue logic does not lock up after one or two first
+-	 * ticks in a non-ExtINT mode.  Also the local APIC
+-	 * might have cached one ExtINT interrupt.  Finally, at
+-	 * least one tick may be lost due to delays.
+-	 */
+-	if (time_after(jiffies, t1 + 4))
+-		return 1;
+-
+-	return 0;
+-}
+-
+-/*
+- * In the SMP+IOAPIC case it might happen that there are an unspecified
+- * number of pending IRQ events unhandled. These cases are very rare,
+- * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
+- * better to do it this way as thus we do not have to be aware of
+- * 'pending' interrupts in the IRQ path, except at this point.
+- */
+-/*
+- * Edge triggered needs to resend any interrupt
+- * that was delayed but this is now handled in the device
+- * independent code.
+- */
+-
+-/*
+- * Startup quirk:
+- *
+- * Starting up a edge-triggered IO-APIC interrupt is
+- * nasty - we need to make sure that we get the edge.
+- * If it is already asserted for some reason, we need
+- * return 1 to indicate that is was pending.
+- *
+- * This is not complete - we should be able to fake
+- * an edge even if it isn't on the 8259A...
+- *
+- * (We do this for level-triggered IRQs too - it cannot hurt.)
+- */
+-static unsigned int startup_ioapic_irq(unsigned int irq)
+-{
+-	int was_pending = 0;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	if (irq < 16) {
+-		disable_8259A_irq(irq);
+-		if (i8259A_irq_pending(irq))
+-			was_pending = 1;
+-	}
+-	__unmask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return was_pending;
+-}
+-
+-static void ack_ioapic_irq(unsigned int irq)
+-{
+-	move_native_irq(irq);
+-	ack_APIC_irq();
+-}
+-
+-static void ack_ioapic_quirk_irq(unsigned int irq)
+-{
+-	unsigned long v;
+-	int i;
+-
+-	move_native_irq(irq);
+-/*
+- * It appears there is an erratum which affects at least version 0x11
+- * of I/O APIC (that's the 82093AA and cores integrated into various
+- * chipsets).  Under certain conditions a level-triggered interrupt is
+- * erroneously delivered as edge-triggered one but the respective IRR
+- * bit gets set nevertheless.  As a result the I/O unit expects an EOI
+- * message but it will never arrive and further interrupts are blocked
+- * from the source.  The exact reason is so far unknown, but the
+- * phenomenon was observed when two consecutive interrupt requests
+- * from a given source get delivered to the same CPU and the source is
+- * temporarily disabled in between.
+- *
+- * A workaround is to simulate an EOI message manually.  We achieve it
+- * by setting the trigger mode to edge and then to level when the edge
+- * trigger mode gets detected in the TMR of a local APIC for a
+- * level-triggered interrupt.  We mask the source for the time of the
+- * operation to prevent an edge-triggered interrupt escaping meanwhile.
+- * The idea is from Manfred Spraul.  --macro
+- */
+-	i = irq_vector[irq];
+-
+-	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+-
+-	ack_APIC_irq();
+-
+-	if (!(v & (1 << (i & 0x1f)))) {
+-		atomic_inc(&irq_mis_count);
+-		spin_lock(&ioapic_lock);
+-		__mask_and_edge_IO_APIC_irq(irq);
+-		__unmask_and_level_IO_APIC_irq(irq);
+-		spin_unlock(&ioapic_lock);
+-	}
+-}
+-
+-static int ioapic_retrigger_irq(unsigned int irq)
+-{
+-	send_IPI_self(irq_vector[irq]);
+-
+-	return 1;
+-}
+-
+-static struct irq_chip ioapic_chip __read_mostly = {
+-	.name 		= "IO-APIC",
+-	.startup 	= startup_ioapic_irq,
+-	.mask	 	= mask_IO_APIC_irq,
+-	.unmask	 	= unmask_IO_APIC_irq,
+-	.ack 		= ack_ioapic_irq,
+-	.eoi 		= ack_ioapic_quirk_irq,
+-#ifdef CONFIG_SMP
+-	.set_affinity 	= set_ioapic_affinity_irq,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-#endif /* !CONFIG_XEN */
+-
+-static inline void init_IO_APIC_traps(void)
+-{
+-	int irq;
+-
+-	/*
+-	 * NOTE! The local APIC isn't very good at handling
+-	 * multiple interrupts at the same interrupt level.
+-	 * As the interrupt level is determined by taking the
+-	 * vector number and shifting that right by 4, we
+-	 * want to spread these out a bit so that they don't
+-	 * all fall in the same interrupt level.
+-	 *
+-	 * Also, we've got to be careful not to trash gate
+-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+-	 */
+-	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		if (IO_APIC_IRQ(irq) && !irq_vector[irq]) {
+-			/*
+-			 * Hmm.. We don't have an entry for this,
+-			 * so default to an old-fashioned 8259
+-			 * interrupt if we can..
+-			 */
+-			if (irq < 16)
+-				make_8259A_irq(irq);
+-#ifndef CONFIG_XEN
+-			else
+-				/* Strange. Oh, well.. */
+-				irq_desc[irq].chip = &no_irq_chip;
+-#endif
+-		}
+-	}
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * The local APIC irq-chip implementation:
+- */
+-
+-static void ack_lapic_irq(unsigned int irq)
+-{
+-	ack_APIC_irq();
+-}
+-
+-static void mask_lapic_irq(unsigned int irq)
+-{
+-	unsigned long v;
+-
+-	v = apic_read(APIC_LVT0);
+-	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+-}
+-
+-static void unmask_lapic_irq(unsigned int irq)
+-{
+-	unsigned long v;
+-
+-	v = apic_read(APIC_LVT0);
+-	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+-}
+-
+-static struct irq_chip lapic_chip __read_mostly = {
+-	.name		= "local-APIC",
+-	.mask		= mask_lapic_irq,
+-	.unmask		= unmask_lapic_irq,
+-	.ack		= ack_lapic_irq,
+-};
+-
+-static void lapic_register_intr(int irq, int vector)
+-{
+-	irq_desc[irq].status &= ~IRQ_LEVEL;
+-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+-				      "edge");
+-	set_intr_gate(vector, interrupt[irq]);
+-}
+-
+-static void __init setup_nmi(void)
+-{
+-	/*
+-	 * Dirty trick to enable the NMI watchdog ...
+-	 * We put the 8259A master into AEOI mode and
+-	 * unmask on all local APICs LVT0 as NMI.
+-	 *
+-	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+-	 * is from Maciej W. Rozycki - so we do not have to EOI from
+-	 * the NMI handler or the timer interrupt.
+-	 */
+-	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+-
+-	enable_NMI_through_LVT0();
+-
+-	apic_printk(APIC_VERBOSE, " done.\n");
+-}
+-
+-/*
+- * This looks a bit hackish but it's about the only one way of sending
+- * a few INTA cycles to 8259As and any associated glue logic.  ICR does
+- * not support the ExtINT mode, unfortunately.  We need to send these
+- * cycles as some i82489DX-based boards have glue logic that keeps the
+- * 8259A interrupt line asserted until INTA.  --macro
+- */
+-static inline void __init unlock_ExtINT_logic(void)
+-{
+-	int apic, pin, i;
+-	struct IO_APIC_route_entry entry0, entry1;
+-	unsigned char save_control, save_freq_select;
+-
+-	pin  = find_isa_irq_pin(8, mp_INT);
+-	if (pin == -1) {
+-		WARN_ON_ONCE(1);
+-		return;
+-	}
+-	apic = find_isa_irq_apic(8, mp_INT);
+-	if (apic == -1) {
+-		WARN_ON_ONCE(1);
+-		return;
+-	}
+-
+-	entry0 = ioapic_read_entry(apic, pin);
+-	clear_IO_APIC_pin(apic, pin);
+-
+-	memset(&entry1, 0, sizeof(entry1));
+-
+-	entry1.dest_mode = 0;			/* physical delivery */
+-	entry1.mask = 0;			/* unmask IRQ now */
+-	entry1.dest.physical.physical_dest = hard_smp_processor_id();
+-	entry1.delivery_mode = dest_ExtINT;
+-	entry1.polarity = entry0.polarity;
+-	entry1.trigger = 0;
+-	entry1.vector = 0;
+-
+-	ioapic_write_entry(apic, pin, entry1);
+-
+-	save_control = CMOS_READ(RTC_CONTROL);
+-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+-	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
+-		   RTC_FREQ_SELECT);
+-	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
+-
+-	i = 100;
+-	while (i-- > 0) {
+-		mdelay(10);
+-		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
+-			i -= 10;
+-	}
+-
+-	CMOS_WRITE(save_control, RTC_CONTROL);
+-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+-	clear_IO_APIC_pin(apic, pin);
+-
+-	ioapic_write_entry(apic, pin, entry0);
+-}
+-
+-/*
+- * This code may look a bit paranoid, but it's supposed to cooperate with
+- * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+- * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
+- * fanatically on his truly buggy board.
+- */
+-static inline void __init check_timer(void)
+-{
+-	int apic1, pin1, apic2, pin2;
+-	int no_pin1 = 0;
+-	int vector;
+-	unsigned int ver;
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-
+-	ver = apic_read(APIC_LVR);
+-	ver = GET_APIC_VERSION(ver);
+-
+-	/*
+-	 * get/set the timer IRQ vector:
+-	 */
+-	disable_8259A_irq(0);
+-	vector = assign_irq_vector(0);
+-	set_intr_gate(vector, interrupt[0]);
+-
+-	/*
+-	 * As IRQ0 is to be enabled in the 8259A, the virtual
+-	 * wire has to be disabled in the local APIC.  Also
+-	 * timer interrupts need to be acknowledged manually in
+-	 * the 8259A for the i82489DX when using the NMI
+-	 * watchdog as that APIC treats NMIs as level-triggered.
+-	 * The AEOI mode will finish them in the 8259A
+-	 * automatically.
+-	 */
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+-	init_8259A(1);
+-	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+-
+-	pin1  = find_isa_irq_pin(0, mp_INT);
+-	apic1 = find_isa_irq_apic(0, mp_INT);
+-	pin2  = ioapic_i8259.pin;
+-	apic2 = ioapic_i8259.apic;
+-
+-	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+-		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+-		    vector, apic1, pin1, apic2, pin2);
+-
+-	/*
+-	 * Some BIOS writers are clueless and report the ExtINTA
+-	 * I/O APIC input from the cascaded 8259A as the timer
+-	 * interrupt input.  So just in case, if only one pin
+-	 * was found above, try it both directly and through the
+-	 * 8259A.
+-	 */
+-	if (pin1 == -1) {
+-		pin1 = pin2;
+-		apic1 = apic2;
+-		no_pin1 = 1;
+-	} else if (pin2 == -1) {
+-		pin2 = pin1;
+-		apic2 = apic1;
+-	}
+-
+-	if (pin1 != -1) {
+-		/*
+-		 * Ok, does IRQ0 through the IOAPIC work?
+-		 */
+-		if (no_pin1) {
+-			add_pin_to_irq(0, apic1, pin1);
+-			setup_timer_IRQ0_pin(apic1, pin1, vector);
+-		}
+-		unmask_IO_APIC_irq(0);
+-		if (timer_irq_works()) {
+-			if (nmi_watchdog == NMI_IO_APIC) {
+-				setup_nmi();
+-				enable_8259A_irq(0);
+-			}
+-			if (disable_timer_pin_1 > 0)
+-				clear_IO_APIC_pin(0, pin1);
+-			goto out;
+-		}
+-		clear_IO_APIC_pin(apic1, pin1);
+-		if (!no_pin1)
+-			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+-				    "8254 timer not connected to IO-APIC\n");
+-
+-		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+-			    "(IRQ0) through the 8259A ...\n");
+-		apic_printk(APIC_QUIET, KERN_INFO
+-			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+-		/*
+-		 * legacy devices should be connected to IO APIC #0
+-		 */
+-		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+-		setup_timer_IRQ0_pin(apic2, pin2, vector);
+-		unmask_IO_APIC_irq(0);
+-		enable_8259A_irq(0);
+-		if (timer_irq_works()) {
+-			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+-			timer_through_8259 = 1;
+-			if (nmi_watchdog == NMI_IO_APIC) {
+-				disable_8259A_irq(0);
+-				setup_nmi();
+-				enable_8259A_irq(0);
+-			}
+-			goto out;
+-		}
+-		/*
+-		 * Cleanup, just in case ...
+-		 */
+-		disable_8259A_irq(0);
+-		clear_IO_APIC_pin(apic2, pin2);
+-		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+-	}
+-
+-	if (nmi_watchdog == NMI_IO_APIC) {
+-		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+-			    "through the IO-APIC - disabling NMI Watchdog!\n");
+-		nmi_watchdog = NMI_NONE;
+-	}
+-	timer_ack = 0;
+-
+-	apic_printk(APIC_QUIET, KERN_INFO
+-		    "...trying to set up timer as Virtual Wire IRQ...\n");
+-
+-	lapic_register_intr(0, vector);
+-	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+-	enable_8259A_irq(0);
+-
+-	if (timer_irq_works()) {
+-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+-		goto out;
+-	}
+-	disable_8259A_irq(0);
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+-	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+-
+-	apic_printk(APIC_QUIET, KERN_INFO
+-		    "...trying to set up timer as ExtINT IRQ...\n");
+-
+-	init_8259A(0);
+-	make_8259A_irq(0);
+-	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+-
+-	unlock_ExtINT_logic();
+-
+-	if (timer_irq_works()) {
+-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+-		goto out;
+-	}
+-	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+-	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+-		"report.  Then try booting with the 'noapic' option.\n");
+-out:
+-	local_irq_restore(flags);
+-}
+-#else
+-int timer_uses_ioapic_pin_0 = 0;
+-#define check_timer() ((void)0)
+-#endif
+-
+-/*
+- * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
+- * to devices.  However there may be an I/O APIC pin available for
+- * this interrupt regardless.  The pin may be left unconnected, but
+- * typically it will be reused as an ExtINT cascade interrupt for
+- * the master 8259A.  In the MPS case such a pin will normally be
+- * reported as an ExtINT interrupt in the MP table.  With ACPI
+- * there is no provision for ExtINT interrupts, and in the absence
+- * of an override it would be treated as an ordinary ISA I/O APIC
+- * interrupt, that is edge-triggered and unmasked by default.  We
+- * used to do this, but it caused problems on some systems because
+- * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
+- * the same ExtINT cascade interrupt to drive the local APIC of the
+- * bootstrap processor.  Therefore we refrain from routing IRQ2 to
+- * the I/O APIC in all cases now.  No actual device should request
+- * it anyway.  --macro
+- */
+-#define PIC_IRQS	(1 << PIC_CASCADE_IR)
+-
+-void __init setup_IO_APIC(void)
+-{
+-#ifndef CONFIG_XEN
+-	int i;
+-
+-	/* Reserve all the system vectors. */
+-	for (i = first_system_vector; i < NR_VECTORS; i++)
+-		set_bit(i, used_vectors);
+-#endif
+-
+-	enable_IO_APIC();
+-
+-	io_apic_irqs = ~PIC_IRQS;
+-
+-	printk("ENABLING IO-APIC IRQs\n");
+-
+-#ifndef CONFIG_XEN
+-	/*
+-	 * Set up IO-APIC IRQ routing.
+-	 */
+-	if (!acpi_ioapic)
+-		setup_ioapic_ids_from_mpc();
+-	sync_Arb_IDs();
+-#endif
+-	setup_IO_APIC_irqs();
+-	init_IO_APIC_traps();
+-	check_timer();
+-	if (!acpi_ioapic)
+-		print_IO_APIC();
+-}
+-
+-/*
+- *	Called after all the initialization is done. If we didnt find any
+- *	APIC bugs then we can allow the modify fast path
+- */
+-
+-static int __init io_apic_bug_finalize(void)
+-{
+-	if (sis_apic_bug == -1)
+-		sis_apic_bug = 0;
+-	if (is_initial_xendomain()) {
+-		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
+-		op.u.platform_quirk.quirk_id = sis_apic_bug ?
+-			QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
+-		VOID(HYPERVISOR_platform_op(&op));
+-	}
+-	return 0;
+-}
+-
+-late_initcall(io_apic_bug_finalize);
+-
+-#ifndef CONFIG_XEN
+-
+-struct sysfs_ioapic_data {
+-	struct sys_device dev;
+-	struct IO_APIC_route_entry entry[0];
+-};
+-static struct sysfs_ioapic_data *mp_ioapic_data[MAX_IO_APICS];
+-
+-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+-{
+-	struct IO_APIC_route_entry *entry;
+-	struct sysfs_ioapic_data *data;
+-	int i;
+-
+-	data = container_of(dev, struct sysfs_ioapic_data, dev);
+-	entry = data->entry;
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+-		entry[i] = ioapic_read_entry(dev->id, i);
+-
+-	return 0;
+-}
+-
+-static int ioapic_resume(struct sys_device *dev)
+-{
+-	struct IO_APIC_route_entry *entry;
+-	struct sysfs_ioapic_data *data;
+-	unsigned long flags;
+-	union IO_APIC_reg_00 reg_00;
+-	int i;
+-
+-	data = container_of(dev, struct sysfs_ioapic_data, dev);
+-	entry = data->entry;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_00.raw = io_apic_read(dev->id, 0);
+-	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
+-		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
+-		io_apic_write(dev->id, 0, reg_00.raw);
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+-		ioapic_write_entry(dev->id, i, entry[i]);
+-
+-	return 0;
+-}
+-
+-static struct sysdev_class ioapic_sysdev_class = {
+-	.name = "ioapic",
+-	.suspend = ioapic_suspend,
+-	.resume = ioapic_resume,
+-};
+-
+-static int __init ioapic_init_sysfs(void)
+-{
+-	struct sys_device *dev;
+-	int i, size, error = 0;
+-
+-	error = sysdev_class_register(&ioapic_sysdev_class);
+-	if (error)
+-		return error;
+-
+-	for (i = 0; i < nr_ioapics; i++) {
+-		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+-			* sizeof(struct IO_APIC_route_entry);
+-		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+-		if (!mp_ioapic_data[i]) {
+-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+-			continue;
+-		}
+-		dev = &mp_ioapic_data[i]->dev;
+-		dev->id = i;
+-		dev->cls = &ioapic_sysdev_class;
+-		error = sysdev_register(dev);
+-		if (error) {
+-			kfree(mp_ioapic_data[i]);
+-			mp_ioapic_data[i] = NULL;
+-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+-			continue;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-device_initcall(ioapic_init_sysfs);
+-
+-/*
+- * Dynamic irq allocate and deallocation
+- */
+-int create_irq(void)
+-{
+-	/* Allocate an unused irq */
+-	int irq, new, vector = 0;
+-	unsigned long flags;
+-
+-	irq = -ENOSPC;
+-	spin_lock_irqsave(&vector_lock, flags);
+-	for (new = (NR_IRQS - 1); new >= 0; new--) {
+-		if (platform_legacy_irq(new))
+-			continue;
+-		if (irq_vector[new] != 0)
+-			continue;
+-		vector = __assign_irq_vector(new);
+-		if (likely(vector > 0))
+-			irq = new;
+-		break;
+-	}
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-
+-	if (irq >= 0) {
+-		set_intr_gate(vector, interrupt[irq]);
+-		dynamic_irq_init(irq);
+-	}
+-	return irq;
+-}
+-
+-void destroy_irq(unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	dynamic_irq_cleanup(irq);
+-
+-	spin_lock_irqsave(&vector_lock, flags);
+-	clear_bit(irq_vector[irq], used_vectors);
+-	irq_vector[irq] = 0;
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-}
+-
+-#endif /* CONFIG_XEN */
+-
+-/*
+- * MSI message composition
+- */
+-#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+-{
+-	int vector;
+-	unsigned dest;
+-
+-	vector = assign_irq_vector(irq);
+-	if (vector >= 0) {
+-		dest = cpu_mask_to_apicid(TARGET_CPUS);
+-
+-		msg->address_hi = MSI_ADDR_BASE_HI;
+-		msg->address_lo =
+-			MSI_ADDR_BASE_LO |
+-			((INT_DEST_MODE == 0) ?
+-MSI_ADDR_DEST_MODE_PHYSICAL:
+-				MSI_ADDR_DEST_MODE_LOGICAL) |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				MSI_ADDR_REDIRECTION_CPU:
+-				MSI_ADDR_REDIRECTION_LOWPRI) |
+-			MSI_ADDR_DEST_ID(dest);
+-
+-		msg->data =
+-			MSI_DATA_TRIGGER_EDGE |
+-			MSI_DATA_LEVEL_ASSERT |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-MSI_DATA_DELIVERY_FIXED:
+-				MSI_DATA_DELIVERY_LOWPRI) |
+-			MSI_DATA_VECTOR(vector);
+-	}
+-	return vector;
+-}
+-
+-#ifdef CONFIG_SMP
+-static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	struct msi_msg msg;
+-	unsigned int dest;
+-	cpumask_t tmp;
+-	int vector;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	vector = assign_irq_vector(irq);
+-	if (vector < 0)
+-		return;
+-
+-	dest = cpu_mask_to_apicid(mask);
+-
+-	read_msi_msg(irq, &msg);
+-
+-	msg.data &= ~MSI_DATA_VECTOR_MASK;
+-	msg.data |= MSI_DATA_VECTOR(vector);
+-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+-
+-	write_msi_msg(irq, &msg);
+-	irq_desc[irq].affinity = mask;
+-}
+-#endif /* CONFIG_SMP */
+-
+-/*
+- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+- * which implement the MSI or MSI-X Capability Structure.
+- */
+-static struct irq_chip msi_chip = {
+-	.name		= "PCI-MSI",
+-	.unmask		= unmask_msi_irq,
+-	.mask		= mask_msi_irq,
+-	.ack		= ack_ioapic_irq,
+-#ifdef CONFIG_SMP
+-	.set_affinity	= set_msi_irq_affinity,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-
+-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+-{
+-	struct msi_msg msg;
+-	int irq, ret;
+-	irq = create_irq();
+-	if (irq < 0)
+-		return irq;
+-
+-	ret = msi_compose_msg(dev, irq, &msg);
+-	if (ret < 0) {
+-		destroy_irq(irq);
+-		return ret;
+-	}
+-
+-	set_irq_msi(irq, desc);
+-	write_msi_msg(irq, &msg);
+-
+-	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
+-				      "edge");
+-
+-	return 0;
+-}
+-
+-void arch_teardown_msi_irq(unsigned int irq)
+-{
+-	destroy_irq(irq);
+-}
+-
+-#endif /* CONFIG_PCI_MSI */
+-
+-/*
+- * Hypertransport interrupt support
+- */
+-#ifdef CONFIG_HT_IRQ
+-
+-#ifdef CONFIG_SMP
+-
+-static void target_ht_irq(unsigned int irq, unsigned int dest)
+-{
+-	struct ht_irq_msg msg;
+-	fetch_ht_irq_msg(irq, &msg);
+-
+-	msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK);
+-	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+-
+-	msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest);
+-	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
+-
+-	write_ht_irq_msg(irq, &msg);
+-}
+-
+-static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	unsigned int dest;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	cpus_and(mask, tmp, CPU_MASK_ALL);
+-
+-	dest = cpu_mask_to_apicid(mask);
+-
+-	target_ht_irq(irq, dest);
+-	irq_desc[irq].affinity = mask;
+-}
+-#endif
+-
+-static struct irq_chip ht_irq_chip = {
+-	.name		= "PCI-HT",
+-	.mask		= mask_ht_irq,
+-	.unmask		= unmask_ht_irq,
+-	.ack		= ack_ioapic_irq,
+-#ifdef CONFIG_SMP
+-	.set_affinity	= set_ht_irq_affinity,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-
+-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
+-{
+-	int vector;
+-
+-	vector = assign_irq_vector(irq);
+-	if (vector >= 0) {
+-		struct ht_irq_msg msg;
+-		unsigned dest;
+-		cpumask_t tmp;
+-
+-		cpus_clear(tmp);
+-		cpu_set(vector >> 8, tmp);
+-		dest = cpu_mask_to_apicid(tmp);
+-
+-		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+-
+-		msg.address_lo =
+-			HT_IRQ_LOW_BASE |
+-			HT_IRQ_LOW_DEST_ID(dest) |
+-			HT_IRQ_LOW_VECTOR(vector) |
+-			((INT_DEST_MODE == 0) ?
+-				HT_IRQ_LOW_DM_PHYSICAL :
+-				HT_IRQ_LOW_DM_LOGICAL) |
+-			HT_IRQ_LOW_RQEOI_EDGE |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				HT_IRQ_LOW_MT_FIXED :
+-				HT_IRQ_LOW_MT_ARBITRATED) |
+-			HT_IRQ_LOW_IRQ_MASKED;
+-
+-		write_ht_irq_msg(irq, &msg);
+-
+-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+-					      handle_edge_irq, "edge");
+-	}
+-	return vector;
+-}
+-#endif /* CONFIG_HT_IRQ */
+-
+-/* --------------------------------------------------------------------------
+-			ACPI-based IOAPIC Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-int __init io_apic_get_unique_id(int ioapic, int apic_id)
+-{
+-#ifndef CONFIG_XEN
+-	union IO_APIC_reg_00 reg_00;
+-	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
+-	physid_mask_t tmp;
+-	unsigned long flags;
+-	int i = 0;
+-
+-	/*
+-	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
+-	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
+-	 * supports up to 16 on one shared APIC bus.
+-	 *
+-	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+-	 *      advantage of new APIC bus architecture.
+-	 */
+-
+-	if (physids_empty(apic_id_map))
+-		apic_id_map = ioapic_phys_id_map(phys_cpu_present_map);
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_00.raw = io_apic_read(ioapic, 0);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	if (apic_id >= get_physical_broadcast()) {
+-		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+-			"%d\n", ioapic, apic_id, reg_00.bits.ID);
+-		apic_id = reg_00.bits.ID;
+-	}
+-
+-	/*
+-	 * Every APIC in a system must have a unique ID or we get lots of nice
+-	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+-	 */
+-	if (check_apicid_used(apic_id_map, apic_id)) {
+-
+-		for (i = 0; i < get_physical_broadcast(); i++) {
+-			if (!check_apicid_used(apic_id_map, i))
+-				break;
+-		}
+-
+-		if (i == get_physical_broadcast())
+-			panic("Max apic_id exceeded!\n");
+-
+-		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+-			"trying %d\n", ioapic, apic_id, i);
+-
+-		apic_id = i;
+-	}
+-
+-	tmp = apicid_to_cpu_present(apic_id);
+-	physids_or(apic_id_map, apic_id_map, tmp);
+-
+-	if (reg_00.bits.ID != apic_id) {
+-		reg_00.bits.ID = apic_id;
+-
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		io_apic_write(ioapic, 0, reg_00.raw);
+-		reg_00.raw = io_apic_read(ioapic, 0);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-		/* Sanity check */
+-		if (reg_00.bits.ID != apic_id) {
+-			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+-			return -1;
+-		}
+-	}
+-
+-	apic_printk(APIC_VERBOSE, KERN_INFO
+-			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+-#endif /* !CONFIG_XEN */
+-
+-	return apic_id;
+-}
+-
+-
+-int __init io_apic_get_version(int ioapic)
+-{
+-	union IO_APIC_reg_01	reg_01;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_01.raw = io_apic_read(ioapic, 1);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return reg_01.bits.version;
+-}
+-
+-
+-int __init io_apic_get_redir_entries(int ioapic)
+-{
+-	union IO_APIC_reg_01	reg_01;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_01.raw = io_apic_read(ioapic, 1);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return reg_01.bits.entries;
+-}
+-
+-
+-int io_apic_set_pci_routing(int ioapic, int pin, int irq, int edge_level, int active_high_low)
+-{
+-	struct IO_APIC_route_entry entry;
+-
+-	if (!IO_APIC_IRQ(irq)) {
+-		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+-			ioapic);
+-		return -EINVAL;
+-	}
+-
+-	/*
+-	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
+-	 * Note that we mask (disable) IRQs now -- these get enabled when the
+-	 * corresponding device driver registers for this IRQ.
+-	 */
+-
+-	memset(&entry, 0, sizeof(entry));
+-
+-	entry.delivery_mode = INT_DELIVERY_MODE;
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+-	entry.trigger = edge_level;
+-	entry.polarity = active_high_low;
+-	entry.mask  = 1;
+-
+-	/*
+-	 * IRQs < 16 are already in the irq_2_pin[] map
+-	 */
+-	if (irq >= 16)
+-		add_pin_to_irq(irq, ioapic, pin);
+-
+-	entry.vector = assign_irq_vector(irq);
+-
+-	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
+-		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
+-		mp_ioapics[ioapic].mp_apicid, pin, entry.vector, irq,
+-		edge_level, active_high_low);
+-
+-	ioapic_register_intr(irq, entry.vector, edge_level);
+-
+-	if (!ioapic && (irq < 16))
+-		disable_8259A_irq(irq);
+-
+-	ioapic_write_entry(ioapic, pin, entry);
+-
+-	return 0;
+-}
+-
+-int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+-{
+-	int i;
+-
+-	if (skip_ioapic_setup)
+-		return -1;
+-
+-	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == mp_INT &&
+-		    mp_irqs[i].mp_srcbusirq == bus_irq)
+-			break;
+-	if (i >= mp_irq_entries)
+-		return -1;
+-
+-	*trigger = irq_trigger(i);
+-	*polarity = irq_polarity(i);
+-	return 0;
+-}
+-
+-#endif /* CONFIG_ACPI */
+-
+-static int __init parse_disable_timer_pin_1(char *arg)
+-{
+-	disable_timer_pin_1 = 1;
+-	return 0;
+-}
+-early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
+-
+-static int __init parse_enable_timer_pin_1(char *arg)
+-{
+-	disable_timer_pin_1 = -1;
+-	return 0;
+-}
+-early_param("enable_timer_pin_1", parse_enable_timer_pin_1);
+-
+-static int __init parse_noapic(char *arg)
+-{
+-	/* disable IO-APIC */
+-	disable_ioapic_setup();
+-	return 0;
+-}
+-early_param("noapic", parse_noapic);
+-
+-#ifndef CONFIG_XEN
+-void __init ioapic_init_mappings(void)
+-{
+-	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+-	int i;
+-
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if (smp_found_config) {
+-			ioapic_phys = mp_ioapics[i].mp_apicaddr;
+-			if (!ioapic_phys) {
+-				printk(KERN_ERR
+-				       "WARNING: bogus zero IO-APIC "
+-				       "address found in MPTABLE, "
+-				       "disabling IO/APIC support!\n");
+-				smp_found_config = 0;
+-				skip_ioapic_setup = 1;
+-				goto fake_ioapic_page;
+-			}
+-		} else {
+-fake_ioapic_page:
+-			ioapic_phys = (unsigned long)
+-				      alloc_bootmem_pages(PAGE_SIZE);
+-			ioapic_phys = __pa(ioapic_phys);
+-		}
+-		set_fixmap_nocache(idx, ioapic_phys);
+-		printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
+-		       __fix_to_virt(idx), ioapic_phys);
+-		idx++;
+-	}
+-}
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,2448 +0,0 @@
+-/*
+- *	Intel IO-APIC support for multi-Pentium hosts.
+- *
+- *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
+- *
+- *	Many thanks to Stig Venaas for trying out countless experimental
+- *	patches and reporting/debugging problems patiently!
+- *
+- *	(c) 1999, Multiple IO-APIC support, developed by
+- *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+- *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+- *	further tested and cleaned up by Zach Brown <zab@redhat.com>
+- *	and Ingo Molnar <mingo@redhat.com>
+- *
+- *	Fixes
+- *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+- *					thanks to Eric Gilmore
+- *					and Rolf G. Tews
+- *					for testing these extensively
+- *	Paul Diefenbaugh	:	Added full ACPI support
+- */
+-
+-#include <linux/mm.h>
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/sched.h>
+-#include <linux/pci.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/acpi.h>
+-#include <linux/sysdev.h>
+-#include <linux/msi.h>
+-#include <linux/htirq.h>
+-#include <linux/dmar.h>
+-#include <linux/jiffies.h>
+-#ifdef CONFIG_ACPI
+-#include <acpi/acpi_bus.h>
+-#endif
+-#include <linux/bootmem.h>
+-
+-#include <asm/idle.h>
+-#include <asm/io.h>
+-#include <asm/smp.h>
+-#include <asm/desc.h>
+-#include <asm/proto.h>
+-#include <asm/acpi.h>
+-#include <asm/dma.h>
+-#include <asm/i8259.h>
+-#include <asm/nmi.h>
+-#include <asm/msidef.h>
+-#include <asm/hypertransport.h>
+-
+-#include <mach_ipi.h>
+-#include <mach_apic.h>
+-
+-struct irq_cfg {
+-#ifndef CONFIG_XEN
+-	cpumask_t domain;
+-	cpumask_t old_domain;
+-#endif
+-	unsigned move_cleanup_count;
+-	u8 vector;
+-	u8 move_in_progress : 1;
+-};
+-
+-/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+-static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly;
+-
+-static int assign_irq_vector(int irq, cpumask_t mask);
+-
+-#ifndef CONFIG_XEN
+-int first_system_vector = 0xfe;
+-
+-char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
+-#endif
+-
+-#define __apicdebuginit  __init
+-
+-int sis_apic_bug; /* not actually supported, dummy for compile */
+-
+-static int no_timer_check;
+-
+-static int disable_timer_pin_1 __initdata;
+-
+-#ifdef CONFIG_XEN
+-#include <xen/interface/xen.h>
+-#include <xen/interface/physdev.h>
+-#include <xen/evtchn.h>
+-
+-/* Fake i8259 */
+-#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
+-#define disable_8259A_irq(_irq)  ((void)0)
+-#define i8259A_irq_pending(_irq) (0)
+-
+-unsigned long io_apic_irqs;
+-
+-#define clear_IO_APIC() ((void)0)
+-#else
+-int timer_through_8259 __initdata;
+-
+-/* Where if anywhere is the i8259 connect in external int mode */
+-static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+-#endif
+-
+-static DEFINE_SPINLOCK(ioapic_lock);
+-static DEFINE_SPINLOCK(vector_lock);
+-
+-/*
+- * # of IRQ routing registers
+- */
+-int nr_ioapic_registers[MAX_IO_APICS];
+-
+-/* I/O APIC entries */
+-struct mp_config_ioapic mp_ioapics[MAX_IO_APICS];
+-int nr_ioapics;
+-
+-/* MP IRQ source entries */
+-struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+-
+-/* # of MP IRQ source entries */
+-int mp_irq_entries;
+-
+-DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+-
+-/*
+- * Rough estimation of how many shared IRQs there are, can
+- * be changed anytime.
+- */
+-#define MAX_PLUS_SHARED_IRQS NR_IRQS
+-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
+-
+-/*
+- * This is performance-critical, we want to do it O(1)
+- *
+- * the indexing order of this array favors 1:1 mappings
+- * between pins and IRQs.
+- */
+-
+-static struct irq_pin_list {
+-	short apic, pin, next;
+-} irq_2_pin[PIN_MAP_SIZE];
+-
+-#ifndef CONFIG_XEN
+-struct io_apic {
+-	unsigned int index;
+-	unsigned int unused[3];
+-	unsigned int data;
+-};
+-
+-static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+-{
+-	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+-		+ (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK);
+-}
+-#endif
+-
+-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+-{
+-#ifndef CONFIG_XEN
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	writel(reg, &io_apic->index);
+-	return readl(&io_apic->data);
+-#else
+-	struct physdev_apic apic_op;
+-	int ret;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+-	apic_op.reg = reg;
+-	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+-	if (ret)
+-		return ret;
+-	return apic_op.value;
+-#endif
+-}
+-
+-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+-{
+-#ifndef CONFIG_XEN
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	writel(reg, &io_apic->index);
+-	writel(value, &io_apic->data);
+-#else
+-	struct physdev_apic apic_op;
+-
+-	apic_op.apic_physbase = mp_ioapics[apic].mp_apicaddr;
+-	apic_op.reg = reg;
+-	apic_op.value = value;
+-	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+-#endif
+-}
+-
+-#ifdef CONFIG_XEN
+-#define io_apic_modify io_apic_write
+-#else
+-/*
+- * Re-write a value: to be used for read-modify-write
+- * cycles where the read already set up the index register.
+- */
+-static inline void io_apic_modify(unsigned int apic, unsigned int value)
+-{
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	writel(value, &io_apic->data);
+-}
+-
+-static bool io_apic_level_ack_pending(unsigned int irq)
+-{
+-	struct irq_pin_list *entry;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	entry = irq_2_pin + irq;
+-	for (;;) {
+-		unsigned int reg;
+-		int pin;
+-
+-		pin = entry->pin;
+-		if (pin == -1)
+-			break;
+-		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+-		/* Is the remote IRR bit set? */
+-		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+-			spin_unlock_irqrestore(&ioapic_lock, flags);
+-			return true;
+-		}
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return false;
+-}
+-#endif
+-
+-/*
+- * Synchronize the IO-APIC and the CPU by doing
+- * a dummy read from the IO-APIC
+- */
+-static inline void io_apic_sync(unsigned int apic)
+-{
+-#ifndef CONFIG_XEN
+-	struct io_apic __iomem *io_apic = io_apic_base(apic);
+-	readl(&io_apic->data);
+-#endif
+-}
+-
+-union entry_union {
+-	struct { u32 w1, w2; };
+-	struct IO_APIC_route_entry entry;
+-};
+-
+-#ifndef CONFIG_XEN
+-static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+-{
+-	union entry_union eu;
+-	unsigned long flags;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+-	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	return eu.entry;
+-}
+-#endif
+-
+-/*
+- * When we write a new IO APIC routing entry, we need to write the high
+- * word first! If the mask bit in the low word is clear, we will enable
+- * the interrupt, and we need to make sure the entry is fully populated
+- * before that happens.
+- */
+-static void
+-__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+-{
+-	union entry_union eu;
+-	eu.entry = e;
+-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+-}
+-
+-static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+-{
+-	unsigned long flags;
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__ioapic_write_entry(apic, pin, e);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * When we mask an IO APIC routing entry, we need to write the low
+- * word first, in order to set the mask bit before we change the
+- * high bits!
+- */
+-static void ioapic_mask_entry(int apic, int pin)
+-{
+-	unsigned long flags;
+-	union entry_union eu = { .entry.mask = 1 };
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+-	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-#ifdef CONFIG_SMP
+-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
+-{
+-	int apic, pin;
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-
+-	BUG_ON(irq >= NR_IRQS);
+-	for (;;) {
+-		unsigned int reg;
+-		apic = entry->apic;
+-		pin = entry->pin;
+-		if (pin == -1)
+-			break;
+-		io_apic_write(apic, 0x11 + pin*2, dest);
+-		reg = io_apic_read(apic, 0x10 + pin*2);
+-		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+-		reg |= vector;
+-		io_apic_modify(apic, reg);
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-}
+-
+-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	unsigned long flags;
+-	unsigned int dest;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
+-
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-
+-	/*
+-	 * Only the high 8 bits are valid.
+-	 */
+-	dest = SET_APIC_LOGICAL_ID(dest);
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__target_IO_APIC_irq(irq, dest, cfg->vector);
+-	irq_desc[irq].affinity = mask;
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-#endif
+-#endif
+-
+-/*
+- * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+- * shared ISA-space IRQs, so we have to support them. We are super
+- * fast in the common case, and fast for shared ISA-space IRQs.
+- */
+-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
+-{
+-	static int first_free_entry = NR_IRQS;
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-
+-	BUG_ON(irq >= NR_IRQS);
+-	while (entry->next)
+-		entry = irq_2_pin + entry->next;
+-
+-	if (entry->pin != -1) {
+-		entry->next = first_free_entry;
+-		entry = irq_2_pin + entry->next;
+-		if (++first_free_entry >= PIN_MAP_SIZE)
+-			panic("io_apic.c: ran out of irq_2_pin entries!");
+-	}
+-	entry->apic = apic;
+-	entry->pin = pin;
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Reroute an IRQ to a different pin.
+- */
+-static void __init replace_pin_at_irq(unsigned int irq,
+-				      int oldapic, int oldpin,
+-				      int newapic, int newpin)
+-{
+-	struct irq_pin_list *entry = irq_2_pin + irq;
+-
+-	while (1) {
+-		if (entry->apic == oldapic && entry->pin == oldpin) {
+-			entry->apic = newapic;
+-			entry->pin = newpin;
+-		}
+-		if (!entry->next)
+-			break;
+-		entry = irq_2_pin + entry->next;
+-	}
+-}
+-
+-#define __DO_ACTION(R, ACTION, FINAL)					\
+-									\
+-{									\
+-	int pin;							\
+-	struct irq_pin_list *entry = irq_2_pin + irq;			\
+-									\
+-	BUG_ON(irq >= NR_IRQS);						\
+-	for (;;) {							\
+-		unsigned int reg;					\
+-		pin = entry->pin;					\
+-		if (pin == -1)						\
+-			break;						\
+-		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
+-		reg ACTION;						\
+-		io_apic_modify(entry->apic, reg);			\
+-		FINAL;							\
+-		if (!entry->next)					\
+-			break;						\
+-		entry = irq_2_pin + entry->next;			\
+-	}								\
+-}
+-
+-#define DO_ACTION(name,R,ACTION, FINAL)					\
+-									\
+-	static void name##_IO_APIC_irq (unsigned int irq)		\
+-	__DO_ACTION(R, ACTION, FINAL)
+-
+-/* mask = 1 */
+-DO_ACTION(__mask,	0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic))
+-
+-/* mask = 0 */
+-DO_ACTION(__unmask,	0, &= ~IO_APIC_REDIR_MASKED, )
+-
+-static void mask_IO_APIC_irq (unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__mask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-static void unmask_IO_APIC_irq (unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	__unmask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-}
+-
+-static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+-{
+-	struct IO_APIC_route_entry entry;
+-
+-	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+-	entry = ioapic_read_entry(apic, pin);
+-	if (entry.delivery_mode == dest_SMI)
+-		return;
+-	/*
+-	 * Disable it in the IO-APIC irq-routing table:
+-	 */
+-	ioapic_mask_entry(apic, pin);
+-}
+-
+-static void clear_IO_APIC (void)
+-{
+-	int apic, pin;
+-
+-	for (apic = 0; apic < nr_ioapics; apic++)
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+-			clear_IO_APIC_pin(apic, pin);
+-}
+-
+-#endif /* !CONFIG_XEN */
+-
+-int skip_ioapic_setup;
+-int ioapic_force;
+-
+-static int __init parse_noapic(char *str)
+-{
+-	disable_ioapic_setup();
+-	return 0;
+-}
+-early_param("noapic", parse_noapic);
+-
+-/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+-static int __init disable_timer_pin_setup(char *arg)
+-{
+-	disable_timer_pin_1 = 1;
+-	return 1;
+-}
+-__setup("disable_timer_pin_1", disable_timer_pin_setup);
+-
+-
+-/*
+- * Find the IRQ entry number of a certain pin.
+- */
+-static int find_irq_entry(int apic, int pin, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == type &&
+-		    (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid ||
+-		     mp_irqs[i].mp_dstapic == MP_APIC_ALL) &&
+-		    mp_irqs[i].mp_dstirq == pin)
+-			return i;
+-
+-	return -1;
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Find the pin to which IRQ[irq] (ISA) is connected
+- */
+-static int __init find_isa_irq_pin(int irq, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
+-
+-			return mp_irqs[i].mp_dstirq;
+-	}
+-	return -1;
+-}
+-
+-static int __init find_isa_irq_apic(int irq, int type)
+-{
+-	int i;
+-
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		if (test_bit(lbus, mp_bus_not_pci) &&
+-		    (mp_irqs[i].mp_irqtype == type) &&
+-		    (mp_irqs[i].mp_srcbusirq == irq))
+-			break;
+-	}
+-	if (i < mp_irq_entries) {
+-		int apic;
+-		for(apic = 0; apic < nr_ioapics; apic++) {
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic)
+-				return apic;
+-		}
+-	}
+-
+-	return -1;
+-}
+-#endif
+-
+-/*
+- * Find a specific PCI IRQ entry.
+- * Not an __init, possibly needed by modules
+- */
+-static int pin_2_irq(int idx, int apic, int pin);
+-
+-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
+-{
+-	int apic, i, best_guess = -1;
+-
+-	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+-		bus, slot, pin);
+-	if (test_bit(bus, mp_bus_not_pci)) {
+-		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+-		return -1;
+-	}
+-	for (i = 0; i < mp_irq_entries; i++) {
+-		int lbus = mp_irqs[i].mp_srcbus;
+-
+-		for (apic = 0; apic < nr_ioapics; apic++)
+-			if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic ||
+-			    mp_irqs[i].mp_dstapic == MP_APIC_ALL)
+-				break;
+-
+-		if (!test_bit(lbus, mp_bus_not_pci) &&
+-		    !mp_irqs[i].mp_irqtype &&
+-		    (bus == lbus) &&
+-		    (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) {
+-			int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq);
+-
+-			if (!(apic || IO_APIC_IRQ(irq)))
+-				continue;
+-
+-			if (pin == (mp_irqs[i].mp_srcbusirq & 3))
+-				return irq;
+-			/*
+-			 * Use the first all-but-pin matching entry as a
+-			 * best-guess fuzzy result for broken mptables.
+-			 */
+-			if (best_guess < 0)
+-				best_guess = irq;
+-		}
+-	}
+-	BUG_ON(best_guess >= NR_IRQS);
+-	return best_guess;
+-}
+-
+-/* ISA interrupts are always polarity zero edge triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_ISA_trigger(idx)	(0)
+-#define default_ISA_polarity(idx)	(0)
+-
+-/* PCI interrupts are always polarity one level triggered,
+- * when listed as conforming in the MP table. */
+-
+-#define default_PCI_trigger(idx)	(1)
+-#define default_PCI_polarity(idx)	(1)
+-
+-static int MPBIOS_polarity(int idx)
+-{
+-	int bus = mp_irqs[idx].mp_srcbus;
+-	int polarity;
+-
+-	/*
+-	 * Determine IRQ line polarity (high active or low active):
+-	 */
+-	switch (mp_irqs[idx].mp_irqflag & 3)
+-	{
+-		case 0: /* conforms, ie. bus-type dependent polarity */
+-			if (test_bit(bus, mp_bus_not_pci))
+-				polarity = default_ISA_polarity(idx);
+-			else
+-				polarity = default_PCI_polarity(idx);
+-			break;
+-		case 1: /* high active */
+-		{
+-			polarity = 0;
+-			break;
+-		}
+-		case 2: /* reserved */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			polarity = 1;
+-			break;
+-		}
+-		case 3: /* low active */
+-		{
+-			polarity = 1;
+-			break;
+-		}
+-		default: /* invalid */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			polarity = 1;
+-			break;
+-		}
+-	}
+-	return polarity;
+-}
+-
+-static int MPBIOS_trigger(int idx)
+-{
+-	int bus = mp_irqs[idx].mp_srcbus;
+-	int trigger;
+-
+-	/*
+-	 * Determine IRQ trigger mode (edge or level sensitive):
+-	 */
+-	switch ((mp_irqs[idx].mp_irqflag>>2) & 3)
+-	{
+-		case 0: /* conforms, ie. bus-type dependent */
+-			if (test_bit(bus, mp_bus_not_pci))
+-				trigger = default_ISA_trigger(idx);
+-			else
+-				trigger = default_PCI_trigger(idx);
+-			break;
+-		case 1: /* edge */
+-		{
+-			trigger = 0;
+-			break;
+-		}
+-		case 2: /* reserved */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			trigger = 1;
+-			break;
+-		}
+-		case 3: /* level */
+-		{
+-			trigger = 1;
+-			break;
+-		}
+-		default: /* invalid */
+-		{
+-			printk(KERN_WARNING "broken BIOS!!\n");
+-			trigger = 0;
+-			break;
+-		}
+-	}
+-	return trigger;
+-}
+-
+-static inline int irq_polarity(int idx)
+-{
+-	return MPBIOS_polarity(idx);
+-}
+-
+-static inline int irq_trigger(int idx)
+-{
+-	return MPBIOS_trigger(idx);
+-}
+-
+-static int pin_2_irq(int idx, int apic, int pin)
+-{
+-	int irq, i;
+-	int bus = mp_irqs[idx].mp_srcbus;
+-
+-	/*
+-	 * Debugging check, we are in big trouble if this message pops up!
+-	 */
+-	if (mp_irqs[idx].mp_dstirq != pin)
+-		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+-
+-	if (test_bit(bus, mp_bus_not_pci)) {
+-		irq = mp_irqs[idx].mp_srcbusirq;
+-	} else {
+-		/*
+-		 * PCI IRQs are mapped in order
+-		 */
+-		i = irq = 0;
+-		while (i < apic)
+-			irq += nr_ioapic_registers[i++];
+-		irq += pin;
+-	}
+-	BUG_ON(irq >= NR_IRQS);
+-	return irq;
+-}
+-
+-void lock_vector_lock(void)
+-{
+-	/* Used to the online set of cpus does not change
+-	 * during assign_irq_vector.
+-	 */
+-	spin_lock(&vector_lock);
+-}
+-
+-void unlock_vector_lock(void)
+-{
+-	spin_unlock(&vector_lock);
+-}
+-
+-static int __assign_irq_vector(int irq, cpumask_t mask)
+-{
+-	struct physdev_irq irq_op;
+-	struct irq_cfg *cfg;
+-  
+-	BUG_ON((unsigned)irq >= NR_IRQS);
+-
+-	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+-		return -EINVAL;
+-
+-	cfg = &irq_cfg[irq];
+-
+-	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+-		return -EBUSY;
+-
+-	if (cfg->vector)
+-		return 0;
+-
+-	irq_op.irq = irq;
+-	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+-		return -ENOSPC;
+-
+-	cfg->vector = irq_op.vector;
+-
+-	return 0;
+-}
+-
+-static int assign_irq_vector(int irq, cpumask_t mask)
+-{
+-	int err;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&vector_lock, flags);
+-	err = __assign_irq_vector(irq, mask);
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-	return err;
+-}
+-
+-#ifndef CONFIG_XEN
+-static void __clear_irq_vector(int irq)
+-{
+-	struct irq_cfg *cfg;
+-	cpumask_t mask;
+-	int cpu, vector;
+-
+-	BUG_ON((unsigned)irq >= NR_IRQS);
+-	cfg = &irq_cfg[irq];
+-	BUG_ON(!cfg->vector);
+-
+-	vector = cfg->vector;
+-	cpus_and(mask, cfg->domain, cpu_online_map);
+-	for_each_cpu_mask_nr(cpu, mask)
+-		per_cpu(vector_irq, cpu)[vector] = -1;
+-
+-	cfg->vector = 0;
+-	cpus_clear(cfg->domain);
+-}
+-
+-void __setup_vector_irq(int cpu)
+-{
+-	/* Initialize vector_irq on a new cpu */
+-	/* This function must be called with vector_lock held */
+-	int irq, vector;
+-
+-	/* Mark the inuse vectors */
+-	for (irq = 0; irq < NR_IRQS; ++irq) {
+-		if (!cpu_isset(cpu, irq_cfg[irq].domain))
+-			continue;
+-		vector = irq_cfg[irq].vector;
+-		per_cpu(vector_irq, cpu)[vector] = irq;
+-	}
+-	/* Mark the free vectors */
+-	for (vector = 0; vector < NR_VECTORS; ++vector) {
+-		irq = per_cpu(vector_irq, cpu)[vector];
+-		if (irq < 0)
+-			continue;
+-		if (!cpu_isset(cpu, irq_cfg[irq].domain))
+-			per_cpu(vector_irq, cpu)[vector] = -1;
+-	}
+-}
+-
+-static struct irq_chip ioapic_chip;
+-
+-static void ioapic_register_intr(int irq, unsigned long trigger)
+-{
+-	if (trigger) {
+-		irq_desc[irq].status |= IRQ_LEVEL;
+-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+-					      handle_fasteoi_irq, "fasteoi");
+-	} else {
+-		irq_desc[irq].status &= ~IRQ_LEVEL;
+-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+-					      handle_edge_irq, "edge");
+-	}
+-}
+-#else
+-#define ioapic_register_intr(irq, trigger) evtchn_register_pirq(irq)
+-#endif /* !CONFIG_XEN */
+-
+-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
+-			      int trigger, int polarity)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	struct IO_APIC_route_entry entry;
+-	cpumask_t mask;
+-
+-	if (!IO_APIC_IRQ(irq))
+-		return;
+-
+-	mask = TARGET_CPUS;
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-#ifndef CONFIG_XEN
+-	cpus_and(mask, cfg->domain, mask);
+-#endif
+-
+-	apic_printk(APIC_VERBOSE,KERN_DEBUG
+-		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+-		    "IRQ %d Mode:%i Active:%i)\n",
+-		    apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector,
+-		    irq, trigger, polarity);
+-
+-	/*
+-	 * add it to the IO-APIC irq-routing table:
+-	 */
+-	memset(&entry,0,sizeof(entry));
+-
+-	entry.delivery_mode = INT_DELIVERY_MODE;
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.dest = cpu_mask_to_apicid(mask);
+-	entry.mask = 0;				/* enable IRQ */
+-	entry.trigger = trigger;
+-	entry.polarity = polarity;
+-	entry.vector = cfg->vector;
+-
+-	/* Mask level triggered irqs.
+-	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+-	 */
+-	if (trigger)
+-		entry.mask = 1;
+-
+-	ioapic_register_intr(irq, trigger);
+-	if (irq < 16)
+-		disable_8259A_irq(irq);
+-
+-	ioapic_write_entry(apic, pin, entry);
+-}
+-
+-static void __init setup_IO_APIC_irqs(void)
+-{
+-	int apic, pin, idx, irq, first_notcon = 1;
+-
+-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-
+-		idx = find_irq_entry(apic,pin,mp_INT);
+-		if (idx == -1) {
+-			if (first_notcon) {
+-				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
+-				first_notcon = 0;
+-			} else
+-				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
+-			continue;
+-		}
+-		if (!first_notcon) {
+-			apic_printk(APIC_VERBOSE, " not connected.\n");
+-			first_notcon = 1;
+-		}
+-
+-		irq = pin_2_irq(idx, apic, pin);
+-		add_pin_to_irq(irq, apic, pin);
+-
+-		setup_IO_APIC_irq(apic, pin, irq,
+-				  irq_trigger(idx), irq_polarity(idx));
+-	}
+-	}
+-
+-	if (!first_notcon)
+-		apic_printk(APIC_VERBOSE, " not connected.\n");
+-}
+-
+-#ifndef CONFIG_XEN
+-/*
+- * Set up the timer pin, possibly with the 8259A-master behind.
+- */
+-static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin,
+-					int vector)
+-{
+-	struct IO_APIC_route_entry entry;
+-
+-	memset(&entry, 0, sizeof(entry));
+-
+-	/*
+-	 * We use logical delivery to get the timer IRQ
+-	 * to the first CPU.
+-	 */
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.mask = 1;					/* mask IRQ now */
+-	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
+-	entry.delivery_mode = INT_DELIVERY_MODE;
+-	entry.polarity = 0;
+-	entry.trigger = 0;
+-	entry.vector = vector;
+-
+-	/*
+-	 * The timer IRQ doesn't have to know that behind the
+-	 * scene we may have a 8259A-master in AEOI mode ...
+-	 */
+-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+-
+-	/*
+-	 * Add it to the IO-APIC irq-routing table:
+-	 */
+-	ioapic_write_entry(apic, pin, entry);
+-}
+-
+-void __apicdebuginit print_IO_APIC(void)
+-{
+-	int apic, i;
+-	union IO_APIC_reg_00 reg_00;
+-	union IO_APIC_reg_01 reg_01;
+-	union IO_APIC_reg_02 reg_02;
+-	unsigned long flags;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+-	for (i = 0; i < nr_ioapics; i++)
+-		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+-		       mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]);
+-
+-	/*
+-	 * We are a bit conservative about what we expect.  We have to
+-	 * know about every hardware change ASAP.
+-	 */
+-	printk(KERN_INFO "testing the IO APIC.......................\n");
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_00.raw = io_apic_read(apic, 0);
+-	reg_01.raw = io_apic_read(apic, 1);
+-	if (reg_01.bits.version >= 0x10)
+-		reg_02.raw = io_apic_read(apic, 2);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	printk("\n");
+-	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid);
+-	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+-	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+-
+-	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
+-	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+-
+-	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+-	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+-
+-	if (reg_01.bits.version >= 0x10) {
+-		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+-		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+-	}
+-
+-	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+-
+-	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+-			  " Stat Dmod Deli Vect:   \n");
+-
+-	for (i = 0; i <= reg_01.bits.entries; i++) {
+-		struct IO_APIC_route_entry entry;
+-
+-		entry = ioapic_read_entry(apic, i);
+-
+-		printk(KERN_DEBUG " %02x %03X ",
+-			i,
+-			entry.dest
+-		);
+-
+-		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
+-			entry.mask,
+-			entry.trigger,
+-			entry.irr,
+-			entry.polarity,
+-			entry.delivery_status,
+-			entry.dest_mode,
+-			entry.delivery_mode,
+-			entry.vector
+-		);
+-	}
+-	}
+-	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+-	for (i = 0; i < NR_IRQS; i++) {
+-		struct irq_pin_list *entry = irq_2_pin + i;
+-		if (entry->pin < 0)
+-			continue;
+-		printk(KERN_DEBUG "IRQ%d ", i);
+-		for (;;) {
+-			printk("-> %d:%d", entry->apic, entry->pin);
+-			if (!entry->next)
+-				break;
+-			entry = irq_2_pin + entry->next;
+-		}
+-		printk("\n");
+-	}
+-
+-	printk(KERN_INFO ".................................... done.\n");
+-
+-	return;
+-}
+-
+-static __apicdebuginit void print_APIC_bitfield (int base)
+-{
+-	unsigned int v;
+-	int i, j;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
+-	for (i = 0; i < 8; i++) {
+-		v = apic_read(base + i*0x10);
+-		for (j = 0; j < 32; j++) {
+-			if (v & (1<<j))
+-				printk("1");
+-			else
+-				printk("0");
+-		}
+-		printk("\n");
+-	}
+-}
+-
+-void __apicdebuginit print_local_APIC(void * dummy)
+-{
+-	unsigned int v, ver, maxlvt;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+-		smp_processor_id(), hard_smp_processor_id());
+-	v = apic_read(APIC_ID);
+-	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(read_apic_id()));
+-	v = apic_read(APIC_LVR);
+-	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+-	ver = GET_APIC_VERSION(v);
+-	maxlvt = lapic_get_maxlvt();
+-
+-	v = apic_read(APIC_TASKPRI);
+-	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+-
+-	v = apic_read(APIC_ARBPRI);
+-	printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+-		v & APIC_ARBPRI_MASK);
+-	v = apic_read(APIC_PROCPRI);
+-	printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+-
+-	v = apic_read(APIC_EOI);
+-	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
+-	v = apic_read(APIC_RRR);
+-	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+-	v = apic_read(APIC_LDR);
+-	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
+-	v = apic_read(APIC_DFR);
+-	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+-	v = apic_read(APIC_SPIV);
+-	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
+-
+-	printk(KERN_DEBUG "... APIC ISR field:\n");
+-	print_APIC_bitfield(APIC_ISR);
+-	printk(KERN_DEBUG "... APIC TMR field:\n");
+-	print_APIC_bitfield(APIC_TMR);
+-	printk(KERN_DEBUG "... APIC IRR field:\n");
+-	print_APIC_bitfield(APIC_IRR);
+-
+-	v = apic_read(APIC_ESR);
+-	printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+-
+-	v = apic_read(APIC_ICR);
+-	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
+-	v = apic_read(APIC_ICR2);
+-	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
+-
+-	v = apic_read(APIC_LVTT);
+-	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
+-
+-	if (maxlvt > 3) {                       /* PC is LVT#4. */
+-		v = apic_read(APIC_LVTPC);
+-		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
+-	}
+-	v = apic_read(APIC_LVT0);
+-	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
+-	v = apic_read(APIC_LVT1);
+-	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
+-
+-	if (maxlvt > 2) {			/* ERR is LVT#3. */
+-		v = apic_read(APIC_LVTERR);
+-		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
+-	}
+-
+-	v = apic_read(APIC_TMICT);
+-	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
+-	v = apic_read(APIC_TMCCT);
+-	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
+-	v = apic_read(APIC_TDCR);
+-	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+-	printk("\n");
+-}
+-
+-void print_all_local_APICs (void)
+-{
+-	on_each_cpu(print_local_APIC, NULL, 1);
+-}
+-
+-void __apicdebuginit print_PIC(void)
+-{
+-	unsigned int v;
+-	unsigned long flags;
+-
+-	if (apic_verbosity == APIC_QUIET)
+-		return;
+-
+-	printk(KERN_DEBUG "\nprinting PIC contents\n");
+-
+-	spin_lock_irqsave(&i8259A_lock, flags);
+-
+-	v = inb(0xa1) << 8 | inb(0x21);
+-	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
+-
+-	v = inb(0xa0) << 8 | inb(0x20);
+-	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
+-
+-	outb(0x0b,0xa0);
+-	outb(0x0b,0x20);
+-	v = inb(0xa0) << 8 | inb(0x20);
+-	outb(0x0a,0xa0);
+-	outb(0x0a,0x20);
+-
+-	spin_unlock_irqrestore(&i8259A_lock, flags);
+-
+-	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
+-
+-	v = inb(0x4d1) << 8 | inb(0x4d0);
+-	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+-}
+-#else
+-void __apicdebuginit print_IO_APIC(void) {}
+-#endif /* !CONFIG_XEN */
+-
+-void __init enable_IO_APIC(void)
+-{
+-	union IO_APIC_reg_01 reg_01;
+-#ifndef CONFIG_XEN
+-	int i8259_apic, i8259_pin;
+-#endif
+-	int i, apic;
+-	unsigned long flags;
+-
+-	for (i = 0; i < PIN_MAP_SIZE; i++) {
+-		irq_2_pin[i].pin = -1;
+-		irq_2_pin[i].next = 0;
+-	}
+-
+-	/*
+-	 * The number of IO-APIC IRQ registers (== #pins):
+-	 */
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		spin_lock_irqsave(&ioapic_lock, flags);
+-		reg_01.raw = io_apic_read(apic, 1);
+-		spin_unlock_irqrestore(&ioapic_lock, flags);
+-		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+-	}
+-#ifndef CONFIG_XEN
+-	for(apic = 0; apic < nr_ioapics; apic++) {
+-		int pin;
+-		/* See if any of the pins is in ExtINT mode */
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-			struct IO_APIC_route_entry entry;
+-			entry = ioapic_read_entry(apic, pin);
+-
+-			/* If the interrupt line is enabled and in ExtInt mode
+-			 * I have found the pin where the i8259 is connected.
+-			 */
+-			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+-				ioapic_i8259.apic = apic;
+-				ioapic_i8259.pin  = pin;
+-				goto found_i8259;
+-			}
+-		}
+-	}
+- found_i8259:
+-	/* Look to see what if the MP table has reported the ExtINT */
+-	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
+-	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+-	/* Trust the MP table if nothing is setup in the hardware */
+-	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+-		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+-		ioapic_i8259.pin  = i8259_pin;
+-		ioapic_i8259.apic = i8259_apic;
+-	}
+-	/* Complain if the MP table and the hardware disagree */
+-	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+-		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+-	{
+-		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
+-	}
+-#endif
+-
+-	/*
+-	 * Do not trust the IO-APIC being empty at bootup
+-	 */
+-	clear_IO_APIC();
+-}
+-
+-/*
+- * Not an __init, needed by the reboot code
+- */
+-void disable_IO_APIC(void)
+-{
+-	/*
+-	 * Clear the IO-APIC before rebooting:
+-	 */
+-	clear_IO_APIC();
+-
+-#ifndef CONFIG_XEN
+-	/*
+-	 * If the i8259 is routed through an IOAPIC
+-	 * Put that IOAPIC in virtual wire mode
+-	 * so legacy interrupts can be delivered.
+-	 */
+-	if (ioapic_i8259.pin != -1) {
+-		struct IO_APIC_route_entry entry;
+-
+-		memset(&entry, 0, sizeof(entry));
+-		entry.mask            = 0; /* Enabled */
+-		entry.trigger         = 0; /* Edge */
+-		entry.irr             = 0;
+-		entry.polarity        = 0; /* High */
+-		entry.delivery_status = 0;
+-		entry.dest_mode       = 0; /* Physical */
+-		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+-		entry.vector          = 0;
+-		entry.dest          = GET_APIC_ID(read_apic_id());
+-
+-		/*
+-		 * Add it to the IO-APIC irq-routing table:
+-		 */
+-		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+-	}
+-
+-	disconnect_bsp_APIC(ioapic_i8259.pin != -1);
+-#endif
+-}
+-
+-/*
+- * There is a nasty bug in some older SMP boards, their mptable lies
+- * about the timer IRQ. We do the following to work around the situation:
+- *
+- *	- timer IRQ defaults to IO-APIC IRQ
+- *	- if this function detects that timer IRQs are defunct, then we fall
+- *	  back to ISA timer IRQs
+- */
+-#ifndef CONFIG_XEN
+-static int __init timer_irq_works(void)
+-{
+-	unsigned long t1 = jiffies;
+-	unsigned long flags;
+-
+-	local_save_flags(flags);
+-	local_irq_enable();
+-	/* Let ten ticks pass... */
+-	mdelay((10 * 1000) / HZ);
+-	local_irq_restore(flags);
+-
+-	/*
+-	 * Expect a few ticks at least, to be sure some possible
+-	 * glue logic does not lock up after one or two first
+-	 * ticks in a non-ExtINT mode.  Also the local APIC
+-	 * might have cached one ExtINT interrupt.  Finally, at
+-	 * least one tick may be lost due to delays.
+-	 */
+-
+-	/* jiffies wrap? */
+-	if (time_after(jiffies, t1 + 4))
+-		return 1;
+-	return 0;
+-}
+-
+-/*
+- * In the SMP+IOAPIC case it might happen that there are an unspecified
+- * number of pending IRQ events unhandled. These cases are very rare,
+- * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
+- * better to do it this way as thus we do not have to be aware of
+- * 'pending' interrupts in the IRQ path, except at this point.
+- */
+-/*
+- * Edge triggered needs to resend any interrupt
+- * that was delayed but this is now handled in the device
+- * independent code.
+- */
+-
+-/*
+- * Starting up a edge-triggered IO-APIC interrupt is
+- * nasty - we need to make sure that we get the edge.
+- * If it is already asserted for some reason, we need
+- * return 1 to indicate that is was pending.
+- *
+- * This is not complete - we should be able to fake
+- * an edge even if it isn't on the 8259A...
+- */
+-
+-static unsigned int startup_ioapic_irq(unsigned int irq)
+-{
+-	int was_pending = 0;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	if (irq < 16) {
+-		disable_8259A_irq(irq);
+-		if (i8259A_irq_pending(irq))
+-			was_pending = 1;
+-	}
+-	__unmask_IO_APIC_irq(irq);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return was_pending;
+-}
+-
+-static int ioapic_retrigger_irq(unsigned int irq)
+-{
+-	struct irq_cfg *cfg = &irq_cfg[irq];
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&vector_lock, flags);
+-	send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-
+-	return 1;
+-}
+-
+-/*
+- * Level and edge triggered IO-APIC interrupts need different handling,
+- * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+- * handled with the level-triggered descriptor, but that one has slightly
+- * more overhead. Level-triggered interrupts cannot be handled with the
+- * edge-triggered handler, without risking IRQ storms and other ugly
+- * races.
+- */
+-
+-#ifdef CONFIG_SMP
+-asmlinkage void smp_irq_move_cleanup_interrupt(void)
+-{
+-	unsigned vector, me;
+-	ack_APIC_irq();
+-	exit_idle();
+-	irq_enter();
+-
+-	me = smp_processor_id();
+-	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+-		unsigned int irq;
+-		struct irq_desc *desc;
+-		struct irq_cfg *cfg;
+-		irq = __get_cpu_var(vector_irq)[vector];
+-		if (irq >= NR_IRQS)
+-			continue;
+-
+-		desc = irq_desc + irq;
+-		cfg = irq_cfg + irq;
+-		spin_lock(&desc->lock);
+-		if (!cfg->move_cleanup_count)
+-			goto unlock;
+-
+-		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+-			goto unlock;
+-
+-		__get_cpu_var(vector_irq)[vector] = -1;
+-		cfg->move_cleanup_count--;
+-unlock:
+-		spin_unlock(&desc->lock);
+-	}
+-
+-	irq_exit();
+-}
+-
+-static void irq_complete_move(unsigned int irq)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	unsigned vector, me;
+-
+-	if (likely(!cfg->move_in_progress))
+-		return;
+-
+-	vector = ~get_irq_regs()->orig_ax;
+-	me = smp_processor_id();
+-	if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
+-		cpumask_t cleanup_mask;
+-
+-		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
+-		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
+-		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+-		cfg->move_in_progress = 0;
+-	}
+-}
+-#else
+-static inline void irq_complete_move(unsigned int irq) {}
+-#endif
+-
+-static void ack_apic_edge(unsigned int irq)
+-{
+-	irq_complete_move(irq);
+-	move_native_irq(irq);
+-	ack_APIC_irq();
+-}
+-
+-static void ack_apic_level(unsigned int irq)
+-{
+-	int do_unmask_irq = 0;
+-
+-	irq_complete_move(irq);
+-#ifdef CONFIG_GENERIC_PENDING_IRQ
+-	/* If we are moving the irq we need to mask it */
+-	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+-		do_unmask_irq = 1;
+-		mask_IO_APIC_irq(irq);
+-	}
+-#endif
+-
+-	/*
+-	 * We must acknowledge the irq before we move it or the acknowledge will
+-	 * not propagate properly.
+-	 */
+-	ack_APIC_irq();
+-
+-	/* Now we can move and renable the irq */
+-	if (unlikely(do_unmask_irq)) {
+-		/* Only migrate the irq if the ack has been received.
+-		 *
+-		 * On rare occasions the broadcast level triggered ack gets
+-		 * delayed going to ioapics, and if we reprogram the
+-		 * vector while Remote IRR is still set the irq will never
+-		 * fire again.
+-		 *
+-		 * To prevent this scenario we read the Remote IRR bit
+-		 * of the ioapic.  This has two effects.
+-		 * - On any sane system the read of the ioapic will
+-		 *   flush writes (and acks) going to the ioapic from
+-		 *   this cpu.
+-		 * - We get to see if the ACK has actually been delivered.
+-		 *
+-		 * Based on failed experiments of reprogramming the
+-		 * ioapic entry from outside of irq context starting
+-		 * with masking the ioapic entry and then polling until
+-		 * Remote IRR was clear before reprogramming the
+-		 * ioapic I don't trust the Remote IRR bit to be
+-		 * completey accurate.
+-		 *
+-		 * However there appears to be no other way to plug
+-		 * this race, so if the Remote IRR bit is not
+-		 * accurate and is causing problems then it is a hardware bug
+-		 * and you can go talk to the chipset vendor about it.
+-		 */
+-		if (!io_apic_level_ack_pending(irq))
+-			move_masked_irq(irq);
+-		unmask_IO_APIC_irq(irq);
+-	}
+-}
+-
+-static struct irq_chip ioapic_chip __read_mostly = {
+-	.name 		= "IO-APIC",
+-	.startup 	= startup_ioapic_irq,
+-	.mask	 	= mask_IO_APIC_irq,
+-	.unmask	 	= unmask_IO_APIC_irq,
+-	.ack 		= ack_apic_edge,
+-	.eoi 		= ack_apic_level,
+-#ifdef CONFIG_SMP
+-	.set_affinity 	= set_ioapic_affinity_irq,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-#endif /* !CONFIG_XEN */
+-
+-static inline void init_IO_APIC_traps(void)
+-{
+-	int irq;
+-
+-	/*
+-	 * NOTE! The local APIC isn't very good at handling
+-	 * multiple interrupts at the same interrupt level.
+-	 * As the interrupt level is determined by taking the
+-	 * vector number and shifting that right by 4, we
+-	 * want to spread these out a bit so that they don't
+-	 * all fall in the same interrupt level.
+-	 *
+-	 * Also, we've got to be careful not to trash gate
+-	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+-	 */
+-	for (irq = 0; irq < NR_IRQS ; irq++) {
+-		if (IO_APIC_IRQ(irq) && !irq_cfg[irq].vector) {
+-			/*
+-			 * Hmm.. We don't have an entry for this,
+-			 * so default to an old-fashioned 8259
+-			 * interrupt if we can..
+-			 */
+-			if (irq < 16)
+-				make_8259A_irq(irq);
+-#ifndef CONFIG_XEN
+-			else
+-				/* Strange. Oh, well.. */
+-				irq_desc[irq].chip = &no_irq_chip;
+-#endif
+-		}
+-	}
+-}
+-
+-#ifndef CONFIG_XEN
+-static void unmask_lapic_irq(unsigned int irq)
+-{
+-	unsigned long v;
+-
+-	v = apic_read(APIC_LVT0);
+-	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+-}
+-
+-static void mask_lapic_irq(unsigned int irq)
+-{
+-	unsigned long v;
+-
+-	v = apic_read(APIC_LVT0);
+-	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+-}
+-
+-static void ack_lapic_irq (unsigned int irq)
+-{
+-	ack_APIC_irq();
+-}
+-
+-static struct irq_chip lapic_chip __read_mostly = {
+-	.name		= "local-APIC",
+-	.mask		= mask_lapic_irq,
+-	.unmask		= unmask_lapic_irq,
+-	.ack		= ack_lapic_irq,
+-};
+-
+-static void lapic_register_intr(int irq)
+-{
+-	irq_desc[irq].status &= ~IRQ_LEVEL;
+-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+-				      "edge");
+-}
+-
+-static void __init setup_nmi(void)
+-{
+-	/*
+- 	 * Dirty trick to enable the NMI watchdog ...
+-	 * We put the 8259A master into AEOI mode and
+-	 * unmask on all local APICs LVT0 as NMI.
+-	 *
+-	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+-	 * is from Maciej W. Rozycki - so we do not have to EOI from
+-	 * the NMI handler or the timer interrupt.
+-	 */ 
+-	printk(KERN_INFO "activating NMI Watchdog ...");
+-
+-	enable_NMI_through_LVT0();
+-
+-	printk(" done.\n");
+-}
+-
+-/*
+- * This looks a bit hackish but it's about the only one way of sending
+- * a few INTA cycles to 8259As and any associated glue logic.  ICR does
+- * not support the ExtINT mode, unfortunately.  We need to send these
+- * cycles as some i82489DX-based boards have glue logic that keeps the
+- * 8259A interrupt line asserted until INTA.  --macro
+- */
+-static inline void __init unlock_ExtINT_logic(void)
+-{
+-	int apic, pin, i;
+-	struct IO_APIC_route_entry entry0, entry1;
+-	unsigned char save_control, save_freq_select;
+-
+-	pin  = find_isa_irq_pin(8, mp_INT);
+-	apic = find_isa_irq_apic(8, mp_INT);
+-	if (pin == -1)
+-		return;
+-
+-	entry0 = ioapic_read_entry(apic, pin);
+-
+-	clear_IO_APIC_pin(apic, pin);
+-
+-	memset(&entry1, 0, sizeof(entry1));
+-
+-	entry1.dest_mode = 0;			/* physical delivery */
+-	entry1.mask = 0;			/* unmask IRQ now */
+-	entry1.dest = hard_smp_processor_id();
+-	entry1.delivery_mode = dest_ExtINT;
+-	entry1.polarity = entry0.polarity;
+-	entry1.trigger = 0;
+-	entry1.vector = 0;
+-
+-	ioapic_write_entry(apic, pin, entry1);
+-
+-	save_control = CMOS_READ(RTC_CONTROL);
+-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+-	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
+-		   RTC_FREQ_SELECT);
+-	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
+-
+-	i = 100;
+-	while (i-- > 0) {
+-		mdelay(10);
+-		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
+-			i -= 10;
+-	}
+-
+-	CMOS_WRITE(save_control, RTC_CONTROL);
+-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+-	clear_IO_APIC_pin(apic, pin);
+-
+-	ioapic_write_entry(apic, pin, entry0);
+-}
+-
+-/*
+- * This code may look a bit paranoid, but it's supposed to cooperate with
+- * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+- * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
+- * fanatically on his truly buggy board.
+- *
+- * FIXME: really need to revamp this for modern platforms only.
+- */
+-static inline void __init check_timer(void)
+-{
+-	struct irq_cfg *cfg = irq_cfg + 0;
+-	int apic1, pin1, apic2, pin2;
+-	unsigned long flags;
+-	int no_pin1 = 0;
+-
+-	local_irq_save(flags);
+-
+-	/*
+-	 * get/set the timer IRQ vector:
+-	 */
+-	disable_8259A_irq(0);
+-	assign_irq_vector(0, TARGET_CPUS);
+-
+-	/*
+-	 * As IRQ0 is to be enabled in the 8259A, the virtual
+-	 * wire has to be disabled in the local APIC.
+-	 */
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+-	init_8259A(1);
+-
+-	pin1  = find_isa_irq_pin(0, mp_INT);
+-	apic1 = find_isa_irq_apic(0, mp_INT);
+-	pin2  = ioapic_i8259.pin;
+-	apic2 = ioapic_i8259.apic;
+-
+-	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+-		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+-		    cfg->vector, apic1, pin1, apic2, pin2);
+-
+-	/*
+-	 * Some BIOS writers are clueless and report the ExtINTA
+-	 * I/O APIC input from the cascaded 8259A as the timer
+-	 * interrupt input.  So just in case, if only one pin
+-	 * was found above, try it both directly and through the
+-	 * 8259A.
+-	 */
+-	if (pin1 == -1) {
+-		pin1 = pin2;
+-		apic1 = apic2;
+-		no_pin1 = 1;
+-	} else if (pin2 == -1) {
+-		pin2 = pin1;
+-		apic2 = apic1;
+-	}
+-
+-	if (pin1 != -1) {
+-		/*
+-		 * Ok, does IRQ0 through the IOAPIC work?
+-		 */
+-		if (no_pin1) {
+-			add_pin_to_irq(0, apic1, pin1);
+-			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+-		}
+-		unmask_IO_APIC_irq(0);
+-		if (!no_timer_check && timer_irq_works()) {
+-			if (nmi_watchdog == NMI_IO_APIC) {
+-				setup_nmi();
+-				enable_8259A_irq(0);
+-			}
+-			if (disable_timer_pin_1 > 0)
+-				clear_IO_APIC_pin(0, pin1);
+-			goto out;
+-		}
+-		clear_IO_APIC_pin(apic1, pin1);
+-		if (!no_pin1)
+-			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+-				    "8254 timer not connected to IO-APIC\n");
+-
+-		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+-			    "(IRQ0) through the 8259A ...\n");
+-		apic_printk(APIC_QUIET, KERN_INFO
+-			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+-		/*
+-		 * legacy devices should be connected to IO APIC #0
+-		 */
+-		replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
+-		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+-		unmask_IO_APIC_irq(0);
+-		enable_8259A_irq(0);
+-		if (timer_irq_works()) {
+-			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+-			timer_through_8259 = 1;
+-			if (nmi_watchdog == NMI_IO_APIC) {
+-				disable_8259A_irq(0);
+-				setup_nmi();
+-				enable_8259A_irq(0);
+-			}
+-			goto out;
+-		}
+-		/*
+-		 * Cleanup, just in case ...
+-		 */
+-		disable_8259A_irq(0);
+-		clear_IO_APIC_pin(apic2, pin2);
+-		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+-	}
+-
+-	if (nmi_watchdog == NMI_IO_APIC) {
+-		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+-			    "through the IO-APIC - disabling NMI Watchdog!\n");
+-		nmi_watchdog = NMI_NONE;
+-	}
+-
+-	apic_printk(APIC_QUIET, KERN_INFO
+-		    "...trying to set up timer as Virtual Wire IRQ...\n");
+-
+-	lapic_register_intr(0);
+-	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+-	enable_8259A_irq(0);
+-
+-	if (timer_irq_works()) {
+-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+-		goto out;
+-	}
+-	disable_8259A_irq(0);
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+-	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+-
+-	apic_printk(APIC_QUIET, KERN_INFO
+-		    "...trying to set up timer as ExtINT IRQ...\n");
+-
+-	init_8259A(0);
+-	make_8259A_irq(0);
+-	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+-
+-	unlock_ExtINT_logic();
+-
+-	if (timer_irq_works()) {
+-		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+-		goto out;
+-	}
+-	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+-	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+-		"report.  Then try booting with the 'noapic' option.\n");
+-out:
+-	local_irq_restore(flags);
+-}
+-#else
+-#define check_timer() ((void)0)
+-int timer_uses_ioapic_pin_0 = 0;
+-#endif /* !CONFIG_XEN */
+-
+-static int __init notimercheck(char *s)
+-{
+-	no_timer_check = 1;
+-	return 1;
+-}
+-__setup("no_timer_check", notimercheck);
+-
+-/*
+- *
+- * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
+- * to devices.  However there may be an I/O APIC pin available for
+- * this interrupt regardless.  The pin may be left unconnected, but
+- * typically it will be reused as an ExtINT cascade interrupt for
+- * the master 8259A.  In the MPS case such a pin will normally be
+- * reported as an ExtINT interrupt in the MP table.  With ACPI
+- * there is no provision for ExtINT interrupts, and in the absence
+- * of an override it would be treated as an ordinary ISA I/O APIC
+- * interrupt, that is edge-triggered and unmasked by default.  We
+- * used to do this, but it caused problems on some systems because
+- * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
+- * the same ExtINT cascade interrupt to drive the local APIC of the
+- * bootstrap processor.  Therefore we refrain from routing IRQ2 to
+- * the I/O APIC in all cases now.  No actual device should request
+- * it anyway.  --macro
+- */
+-#define PIC_IRQS	(1<<2)
+-
+-void __init setup_IO_APIC(void)
+-{
+-	enable_IO_APIC();
+-
+-	io_apic_irqs = ~PIC_IRQS;
+-
+-	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+-
+-#ifndef CONFIG_XEN
+-	sync_Arb_IDs();
+-#endif /* !CONFIG_XEN */
+-	setup_IO_APIC_irqs();
+-	init_IO_APIC_traps();
+-	check_timer();
+-	if (!acpi_ioapic)
+-		print_IO_APIC();
+-}
+-
+-#ifndef CONFIG_XEN
+-
+-struct sysfs_ioapic_data {
+-	struct sys_device dev;
+-	struct IO_APIC_route_entry entry[0];
+-};
+-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+-
+-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+-{
+-	struct IO_APIC_route_entry *entry;
+-	struct sysfs_ioapic_data *data;
+-	int i;
+-
+-	data = container_of(dev, struct sysfs_ioapic_data, dev);
+-	entry = data->entry;
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+-		*entry = ioapic_read_entry(dev->id, i);
+-
+-	return 0;
+-}
+-
+-static int ioapic_resume(struct sys_device *dev)
+-{
+-	struct IO_APIC_route_entry *entry;
+-	struct sysfs_ioapic_data *data;
+-	unsigned long flags;
+-	union IO_APIC_reg_00 reg_00;
+-	int i;
+-
+-	data = container_of(dev, struct sysfs_ioapic_data, dev);
+-	entry = data->entry;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_00.raw = io_apic_read(dev->id, 0);
+-	if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) {
+-		reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid;
+-		io_apic_write(dev->id, 0, reg_00.raw);
+-	}
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+-		ioapic_write_entry(dev->id, i, entry[i]);
+-
+-	return 0;
+-}
+-
+-static struct sysdev_class ioapic_sysdev_class = {
+-	.name = "ioapic",
+-	.suspend = ioapic_suspend,
+-	.resume = ioapic_resume,
+-};
+-
+-static int __init ioapic_init_sysfs(void)
+-{
+-	struct sys_device * dev;
+-	int i, size, error;
+-
+-	error = sysdev_class_register(&ioapic_sysdev_class);
+-	if (error)
+-		return error;
+-
+-	for (i = 0; i < nr_ioapics; i++ ) {
+-		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+-			* sizeof(struct IO_APIC_route_entry);
+-		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+-		if (!mp_ioapic_data[i]) {
+-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+-			continue;
+-		}
+-		dev = &mp_ioapic_data[i]->dev;
+-		dev->id = i;
+-		dev->cls = &ioapic_sysdev_class;
+-		error = sysdev_register(dev);
+-		if (error) {
+-			kfree(mp_ioapic_data[i]);
+-			mp_ioapic_data[i] = NULL;
+-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+-			continue;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-device_initcall(ioapic_init_sysfs);
+-
+-/*
+- * Dynamic irq allocate and deallocation
+- */
+-int create_irq(void)
+-{
+-	/* Allocate an unused irq */
+-	int irq;
+-	int new;
+-	unsigned long flags;
+-
+-	irq = -ENOSPC;
+-	spin_lock_irqsave(&vector_lock, flags);
+-	for (new = (NR_IRQS - 1); new >= 0; new--) {
+-		if (platform_legacy_irq(new))
+-			continue;
+-		if (irq_cfg[new].vector != 0)
+-			continue;
+-		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
+-			irq = new;
+-		break;
+-	}
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-
+-	if (irq >= 0) {
+-		dynamic_irq_init(irq);
+-	}
+-	return irq;
+-}
+-
+-void destroy_irq(unsigned int irq)
+-{
+-	unsigned long flags;
+-
+-	dynamic_irq_cleanup(irq);
+-
+-	spin_lock_irqsave(&vector_lock, flags);
+-	__clear_irq_vector(irq);
+-	spin_unlock_irqrestore(&vector_lock, flags);
+-}
+-
+-#endif /* CONFIG_XEN */
+-
+-/*
+- * MSI message composition
+- */
+-#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+-static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	int err;
+-	unsigned dest;
+-	cpumask_t tmp;
+-
+-	tmp = TARGET_CPUS;
+-	err = assign_irq_vector(irq, tmp);
+-	if (!err) {
+-		cpus_and(tmp, cfg->domain, tmp);
+-		dest = cpu_mask_to_apicid(tmp);
+-
+-		msg->address_hi = MSI_ADDR_BASE_HI;
+-		msg->address_lo =
+-			MSI_ADDR_BASE_LO |
+-			((INT_DEST_MODE == 0) ?
+-				MSI_ADDR_DEST_MODE_PHYSICAL:
+-				MSI_ADDR_DEST_MODE_LOGICAL) |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				MSI_ADDR_REDIRECTION_CPU:
+-				MSI_ADDR_REDIRECTION_LOWPRI) |
+-			MSI_ADDR_DEST_ID(dest);
+-
+-		msg->data =
+-			MSI_DATA_TRIGGER_EDGE |
+-			MSI_DATA_LEVEL_ASSERT |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				MSI_DATA_DELIVERY_FIXED:
+-				MSI_DATA_DELIVERY_LOWPRI) |
+-			MSI_DATA_VECTOR(cfg->vector);
+-	}
+-	return err;
+-}
+-
+-#ifdef CONFIG_SMP
+-static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	struct msi_msg msg;
+-	unsigned int dest;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
+-
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-
+-	read_msi_msg(irq, &msg);
+-
+-	msg.data &= ~MSI_DATA_VECTOR_MASK;
+-	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+-
+-	write_msi_msg(irq, &msg);
+-	irq_desc[irq].affinity = mask;
+-}
+-#endif /* CONFIG_SMP */
+-
+-/*
+- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+- * which implement the MSI or MSI-X Capability Structure.
+- */
+-static struct irq_chip msi_chip = {
+-	.name		= "PCI-MSI",
+-	.unmask		= unmask_msi_irq,
+-	.mask		= mask_msi_irq,
+-	.ack		= ack_apic_edge,
+-#ifdef CONFIG_SMP
+-	.set_affinity	= set_msi_irq_affinity,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-
+-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+-{
+-	struct msi_msg msg;
+-	int irq, ret;
+-	irq = create_irq();
+-	if (irq < 0)
+-		return irq;
+-
+-	ret = msi_compose_msg(dev, irq, &msg);
+-	if (ret < 0) {
+-		destroy_irq(irq);
+-		return ret;
+-	}
+-
+-	set_irq_msi(irq, desc);
+-	write_msi_msg(irq, &msg);
+-
+-	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+-
+-	return 0;
+-}
+-
+-void arch_teardown_msi_irq(unsigned int irq)
+-{
+-	destroy_irq(irq);
+-}
+-
+-#ifdef CONFIG_DMAR
+-#ifdef CONFIG_SMP
+-static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	struct msi_msg msg;
+-	unsigned int dest;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
+-
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-
+-	dmar_msi_read(irq, &msg);
+-
+-	msg.data &= ~MSI_DATA_VECTOR_MASK;
+-	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+-	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+-	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+-
+-	dmar_msi_write(irq, &msg);
+-	irq_desc[irq].affinity = mask;
+-}
+-#endif /* CONFIG_SMP */
+-
+-struct irq_chip dmar_msi_type = {
+-	.name = "DMAR_MSI",
+-	.unmask = dmar_msi_unmask,
+-	.mask = dmar_msi_mask,
+-	.ack = ack_apic_edge,
+-#ifdef CONFIG_SMP
+-	.set_affinity = dmar_msi_set_affinity,
+-#endif
+-	.retrigger = ioapic_retrigger_irq,
+-};
+-
+-int arch_setup_dmar_msi(unsigned int irq)
+-{
+-	int ret;
+-	struct msi_msg msg;
+-
+-	ret = msi_compose_msg(NULL, irq, &msg);
+-	if (ret < 0)
+-		return ret;
+-	dmar_msi_write(irq, &msg);
+-	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+-		"edge");
+-	return 0;
+-}
+-#endif
+-
+-#endif /* CONFIG_PCI_MSI */
+-/*
+- * Hypertransport interrupt support
+- */
+-#ifdef CONFIG_HT_IRQ
+-
+-#ifdef CONFIG_SMP
+-
+-static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
+-{
+-	struct ht_irq_msg msg;
+-	fetch_ht_irq_msg(irq, &msg);
+-
+-	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
+-	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+-
+-	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
+-	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
+-
+-	write_ht_irq_msg(irq, &msg);
+-}
+-
+-static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	unsigned int dest;
+-	cpumask_t tmp;
+-
+-	cpus_and(tmp, mask, cpu_online_map);
+-	if (cpus_empty(tmp))
+-		return;
+-
+-	if (assign_irq_vector(irq, mask))
+-		return;
+-
+-	cpus_and(tmp, cfg->domain, mask);
+-	dest = cpu_mask_to_apicid(tmp);
+-
+-	target_ht_irq(irq, dest, cfg->vector);
+-	irq_desc[irq].affinity = mask;
+-}
+-#endif
+-
+-static struct irq_chip ht_irq_chip = {
+-	.name		= "PCI-HT",
+-	.mask		= mask_ht_irq,
+-	.unmask		= unmask_ht_irq,
+-	.ack		= ack_apic_edge,
+-#ifdef CONFIG_SMP
+-	.set_affinity	= set_ht_irq_affinity,
+-#endif
+-	.retrigger	= ioapic_retrigger_irq,
+-};
+-
+-int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
+-{
+-	struct irq_cfg *cfg = irq_cfg + irq;
+-	int err;
+-	cpumask_t tmp;
+-
+-	tmp = TARGET_CPUS;
+-	err = assign_irq_vector(irq, tmp);
+-	if (!err) {
+-		struct ht_irq_msg msg;
+-		unsigned dest;
+-
+-		cpus_and(tmp, cfg->domain, tmp);
+-		dest = cpu_mask_to_apicid(tmp);
+-
+-		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+-
+-		msg.address_lo =
+-			HT_IRQ_LOW_BASE |
+-			HT_IRQ_LOW_DEST_ID(dest) |
+-			HT_IRQ_LOW_VECTOR(cfg->vector) |
+-			((INT_DEST_MODE == 0) ?
+-				HT_IRQ_LOW_DM_PHYSICAL :
+-				HT_IRQ_LOW_DM_LOGICAL) |
+-			HT_IRQ_LOW_RQEOI_EDGE |
+-			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+-				HT_IRQ_LOW_MT_FIXED :
+-				HT_IRQ_LOW_MT_ARBITRATED) |
+-			HT_IRQ_LOW_IRQ_MASKED;
+-
+-		write_ht_irq_msg(irq, &msg);
+-
+-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+-					      handle_edge_irq, "edge");
+-	}
+-	return err;
+-}
+-#endif /* CONFIG_HT_IRQ */
+-
+-/* --------------------------------------------------------------------------
+-                          ACPI-based IOAPIC Configuration
+-   -------------------------------------------------------------------------- */
+-
+-#ifdef CONFIG_ACPI
+-
+-#define IO_APIC_MAX_ID		0xFE
+-
+-int __init io_apic_get_redir_entries (int ioapic)
+-{
+-	union IO_APIC_reg_01	reg_01;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	reg_01.raw = io_apic_read(ioapic, 1);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+-	return reg_01.bits.entries;
+-}
+-
+-
+-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+-{
+-	if (!IO_APIC_IRQ(irq)) {
+-		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+-			ioapic);
+-		return -EINVAL;
+-	}
+-
+-	/*
+-	 * IRQs < 16 are already in the irq_2_pin[] map
+-	 */
+-	if (irq >= 16)
+-		add_pin_to_irq(irq, ioapic, pin);
+-
+-	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
+-
+-	return 0;
+-}
+-
+-
+-int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+-{
+-	int i;
+-
+-	if (skip_ioapic_setup)
+-		return -1;
+-
+-	for (i = 0; i < mp_irq_entries; i++)
+-		if (mp_irqs[i].mp_irqtype == mp_INT &&
+-		    mp_irqs[i].mp_srcbusirq == bus_irq)
+-			break;
+-	if (i >= mp_irq_entries)
+-		return -1;
+-
+-	*trigger = irq_trigger(i);
+-	*polarity = irq_polarity(i);
+-	return 0;
+-}
+-
+-#endif /* CONFIG_ACPI */
+-
+-#ifndef CONFIG_XEN
+-/*
+- * This function currently is only a helper for the i386 smp boot process where
+- * we need to reprogram the ioredtbls to cater for the cpus which have come online
+- * so mask in all cases should simply be TARGET_CPUS
+- */
+-#ifdef CONFIG_SMP
+-void __init setup_ioapic_dest(void)
+-{
+-	int pin, ioapic, irq, irq_entry;
+-
+-	if (skip_ioapic_setup == 1)
+-		return;
+-
+-	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+-			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+-			if (irq_entry == -1)
+-				continue;
+-			irq = pin_2_irq(irq_entry, ioapic, pin);
+-
+-			/* setup_IO_APIC_irqs could fail to get vector for some device
+-			 * when you have too many devices, because at that time only boot
+-			 * cpu is online.
+-			 */
+-			if (!irq_cfg[irq].vector)
+-				setup_IO_APIC_irq(ioapic, pin, irq,
+-						  irq_trigger(irq_entry),
+-						  irq_polarity(irq_entry));
+-			else
+-				set_ioapic_affinity_irq(irq, TARGET_CPUS);
+-		}
+-
+-	}
+-}
+-#endif
+-
+-#define IOAPIC_RESOURCE_NAME_SIZE 11
+-
+-static struct resource *ioapic_resources;
+-
+-static struct resource * __init ioapic_setup_resources(void)
+-{
+-	unsigned long n;
+-	struct resource *res;
+-	char *mem;
+-	int i;
+-
+-	if (nr_ioapics <= 0)
+-		return NULL;
+-
+-	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+-	n *= nr_ioapics;
+-
+-	mem = alloc_bootmem(n);
+-	res = (void *)mem;
+-
+-	if (mem != NULL) {
+-		mem += sizeof(struct resource) * nr_ioapics;
+-
+-		for (i = 0; i < nr_ioapics; i++) {
+-			res[i].name = mem;
+-			res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+-			sprintf(mem,  "IOAPIC %u", i);
+-			mem += IOAPIC_RESOURCE_NAME_SIZE;
+-		}
+-	}
+-
+-	ioapic_resources = res;
+-
+-	return res;
+-}
+-
+-void __init ioapic_init_mappings(void)
+-{
+-	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+-	struct resource *ioapic_res;
+-	int i;
+-
+-	ioapic_res = ioapic_setup_resources();
+-	for (i = 0; i < nr_ioapics; i++) {
+-		if (smp_found_config) {
+-			ioapic_phys = mp_ioapics[i].mp_apicaddr;
+-		} else {
+-			ioapic_phys = (unsigned long)
+-				alloc_bootmem_pages(PAGE_SIZE);
+-			ioapic_phys = __pa(ioapic_phys);
+-		}
+-		set_fixmap_nocache(idx, ioapic_phys);
+-		apic_printk(APIC_VERBOSE,
+-			    "mapped IOAPIC to %016lx (%016lx)\n",
+-			    __fix_to_virt(idx), ioapic_phys);
+-		idx++;
+-
+-		if (ioapic_res != NULL) {
+-			ioapic_res->start = ioapic_phys;
+-			ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+-			ioapic_res++;
+-		}
+-	}
+-}
+-
+-static int __init ioapic_insert_resources(void)
+-{
+-	int i;
+-	struct resource *r = ioapic_resources;
+-
+-	if (!r) {
+-		printk(KERN_ERR
+-		       "IO APIC resources could be not be allocated.\n");
+-		return -1;
+-	}
+-
+-	for (i = 0; i < nr_ioapics; i++) {
+-		insert_resource(&iomem_resource, r);
+-		r++;
+-	}
+-
+-	return 0;
+-}
+-
+-/* Insert the IO APIC resources after PCI initialization has occured to handle
+- * IO APICS that are mapped in on a BAR in PCI space. */
+-late_initcall(ioapic_insert_resources);
+-#endif /* !CONFIG_XEN */
+--- head-2010-01-18.orig/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/thread_info.h>
+ #include <linux/syscalls.h>
++#include <asm/syscalls.h>
+ #include <xen/interface/physdev.h>
+ 
+ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+--- head-2010-01-18.orig/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -21,6 +21,8 @@
+ #ifdef CONFIG_X86_32
+ #ifndef CONFIG_XEN
+ #include <mach_apic.h>
++#include <mach_ipi.h>
++
+ /*
+  * the following functions deal with sending IPIs between CPUs.
+  *
+@@ -197,10 +199,8 @@ void send_IPI_mask_sequence(cpumask_t ma
+ #endif
+ }
+ 
+-/* must come after the send_IPI functions above for inlining */
+-#include <mach_ipi.h>
+-
+ #ifndef CONFIG_XEN
++/* must come after the send_IPI functions above for inlining */
+ static int convert_apicid_to_cpu(int apic_id)
+ {
+ 	int i;
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/irq-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,193 @@
++/*
++ * Common interrupt code for 32 and 64 bit
++ */
++#include <linux/cpu.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/seq_file.h>
++
++#include <asm/apic.h>
++#include <asm/io_apic.h>
++#include <asm/smp.h>
++
++atomic_t irq_err_count;
++
++/*
++ * 'what should we do if we get a hw irq event on an illegal vector'.
++ * each architecture has to answer this themselves.
++ */
++void ack_bad_irq(unsigned int irq)
++{
++	printk(KERN_ERR "unexpected IRQ trap at irq %02x\n", irq);
++
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
++	/*
++	 * Currently unexpected vectors happen only on SMP and APIC.
++	 * We _must_ ack these because every local APIC has only N
++	 * irq slots per priority level, and a 'hanging, unacked' IRQ
++	 * holds up an irq slot - in excessive cases (when multiple
++	 * unexpected vectors occur) that might lock up the APIC
++	 * completely.
++	 * But only ack when the APIC is enabled -AK
++	 */
++	if (cpu_has_apic)
++		ack_APIC_irq();
++#endif
++}
++
++#ifdef CONFIG_X86_32
++# define irq_stats(x)		(&per_cpu(irq_stat, x))
++#else
++# define irq_stats(x)		cpu_pda(x)
++#endif
++/*
++ * /proc/interrupts printing:
++ */
++static int show_other_interrupts(struct seq_file *p)
++{
++	int j;
++
++	seq_printf(p, "NMI: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
++	seq_printf(p, "  Non-maskable interrupts\n");
++#ifdef CONFIG_X86_LOCAL_APIC
++	seq_printf(p, "LOC: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
++	seq_printf(p, "  Local timer interrupts\n");
++#endif
++#ifdef CONFIG_SMP
++	seq_printf(p, "RES: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
++	seq_printf(p, "  Rescheduling interrupts\n");
++	seq_printf(p, "CAL: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
++	seq_printf(p, "  Function call interrupts\n");
++#ifndef CONFIG_XEN
++	seq_printf(p, "TLB: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
++	seq_printf(p, "  TLB shootdowns\n");
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++	seq_printf(p, "TRM: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
++	seq_printf(p, "  Thermal event interrupts\n");
++# ifdef CONFIG_X86_64
++	seq_printf(p, "THR: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
++	seq_printf(p, "  Threshold APIC interrupts\n");
++# endif
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++	seq_printf(p, "SPU: ");
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
++	seq_printf(p, "  Spurious interrupts\n");
++#endif
++	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
++#if defined(CONFIG_X86_IO_APIC)
++	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
++#endif
++	return 0;
++}
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++	unsigned long flags, any_count = 0;
++	int i = *(loff_t *) v, j;
++	struct irqaction *action;
++	struct irq_desc *desc;
++
++	if (i > nr_irqs)
++		return 0;
++
++	if (i == nr_irqs)
++		return show_other_interrupts(p);
++
++	/* print header */
++	if (i == 0) {
++		seq_printf(p, "           ");
++		for_each_online_cpu(j)
++			seq_printf(p, "CPU%-8d", j);
++		seq_putc(p, '\n');
++	}
++
++	desc = irq_to_desc(i);
++	spin_lock_irqsave(&desc->lock, flags);
++#ifndef CONFIG_SMP
++	any_count = kstat_irqs(i);
++#else
++	for_each_online_cpu(j)
++		any_count |= kstat_irqs_cpu(i, j);
++#endif
++	action = desc->action;
++	if (!action && !any_count)
++		goto out;
++
++	seq_printf(p, "%3d: ", i);
++#ifndef CONFIG_SMP
++	seq_printf(p, "%10u ", kstat_irqs(i));
++#else
++	for_each_online_cpu(j)
++		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
++#endif
++	seq_printf(p, " %8s", desc->chip->name);
++	seq_printf(p, "-%-8s", desc->name);
++
++	if (action) {
++		seq_printf(p, "  %s", action->name);
++		while ((action = action->next) != NULL)
++			seq_printf(p, ", %s", action->name);
++	}
++
++	seq_putc(p, '\n');
++out:
++	spin_unlock_irqrestore(&desc->lock, flags);
++	return 0;
++}
++
++/*
++ * /proc/stat helpers
++ */
++u64 arch_irq_stat_cpu(unsigned int cpu)
++{
++	u64 sum = irq_stats(cpu)->__nmi_count;
++
++#ifdef CONFIG_X86_LOCAL_APIC
++	sum += irq_stats(cpu)->apic_timer_irqs;
++#endif
++#ifdef CONFIG_SMP
++	sum += irq_stats(cpu)->irq_resched_count;
++	sum += irq_stats(cpu)->irq_call_count;
++#ifndef CONFIG_XEN
++	sum += irq_stats(cpu)->irq_tlb_count;
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++	sum += irq_stats(cpu)->irq_thermal_count;
++# ifdef CONFIG_X86_64
++	sum += irq_stats(cpu)->irq_threshold_count;
++#endif
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++	sum += irq_stats(cpu)->irq_spurious_count;
++#endif
++	return sum;
++}
++
++u64 arch_irq_stat(void)
++{
++	u64 sum = atomic_read(&irq_err_count);
++
++#ifdef CONFIG_X86_IO_APIC
++	sum += atomic_read(&irq_mis_count);
++#endif
++	return sum;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -25,29 +25,6 @@ EXPORT_PER_CPU_SYMBOL(irq_stat);
+ DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+ EXPORT_PER_CPU_SYMBOL(irq_regs);
+ 
+-/*
+- * 'what should we do if we get a hw irq event on an illegal vector'.
+- * each architecture has to answer this themselves.
+- */
+-void ack_bad_irq(unsigned int irq)
+-{
+-	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
+-
+-#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+-	/*
+-	 * Currently unexpected vectors happen only on SMP and APIC.
+-	 * We _must_ ack these because every local APIC has only N
+-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+-	 * holds up an irq slot - in excessive cases (when multiple
+-	 * unexpected vectors occur) that might lock up the APIC
+-	 * completely.
+-	 * But only ack when the APIC is enabled -AK
+-	 */
+-	if (cpu_has_apic)
+-		ack_APIC_irq();
+-#endif
+-}
+-
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /* Debugging check for stack overflow: is there less than 1KB free? */
+ static int check_stack_overflow(void)
+@@ -223,20 +200,22 @@ unsigned int do_IRQ(struct pt_regs *regs
+ {
+ 	struct pt_regs *old_regs;
+ 	/* high bit used in ret_from_ code */
+-	int overflow, irq = ~regs->orig_ax;
+-	struct irq_desc *desc = irq_desc + irq;
+-
+-	if (unlikely((unsigned)irq >= NR_IRQS)) {
+-		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+-					__func__, irq);
+-		BUG();
+-	}
++	int overflow;
++	unsigned irq = ~regs->orig_ax;
++	struct irq_desc *desc;
+ 
+ 	old_regs = set_irq_regs(regs);
+ 	/*irq_enter();*/
+ 
+ 	overflow = check_stack_overflow();
+ 
++	desc = irq_to_desc(irq);
++	if (unlikely(!desc)) {
++		printk(KERN_EMERG "%s: cannot handle IRQ %d cpu %d\n",
++					__func__, irq, smp_processor_id());
++		BUG();
++	}
++
+ 	if (!execute_on_irq_stack(overflow, desc, irq)) {
+ 		if (unlikely(overflow))
+ 			print_stack_overflow();
+@@ -248,170 +227,28 @@ unsigned int do_IRQ(struct pt_regs *regs
+ 	return 1;
+ }
+ 
+-/*
+- * Interrupt statistics:
+- */
+-
+-atomic_t irq_err_count;
+-
+-/*
+- * /proc/interrupts printing:
+- */
+-
+-int show_interrupts(struct seq_file *p, void *v)
+-{
+-	int i = *(loff_t *) v, j;
+-	struct irqaction * action;
+-	unsigned long flags;
+-
+-	if (i == 0) {
+-		seq_printf(p, "           ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "CPU%-8d",j);
+-		seq_putc(p, '\n');
+-	}
+-
+-	if (i < NR_IRQS) {
+-		unsigned any_count = 0;
+-
+-		spin_lock_irqsave(&irq_desc[i].lock, flags);
+-#ifndef CONFIG_SMP
+-		any_count = kstat_irqs(i);
+-#else
+-		for_each_online_cpu(j)
+-			any_count |= kstat_cpu(j).irqs[i];
+-#endif
+-		action = irq_desc[i].action;
+-		if (!action && !any_count)
+-			goto skip;
+-		seq_printf(p, "%3d: ",i);
+-#ifndef CONFIG_SMP
+-		seq_printf(p, "%10u ", kstat_irqs(i));
+-#else
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+-#endif
+-		seq_printf(p, " %8s", irq_desc[i].chip->name);
+-		seq_printf(p, "-%-8s", irq_desc[i].name);
+-
+-		if (action) {
+-			seq_printf(p, "  %s", action->name);
+-			while ((action = action->next) != NULL)
+-				seq_printf(p, ", %s", action->name);
+-		}
+-
+-		seq_putc(p, '\n');
+-skip:
+-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+-	} else if (i == NR_IRQS) {
+-		seq_printf(p, "NMI: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", nmi_count(j));
+-		seq_printf(p, "  Non-maskable interrupts\n");
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		seq_printf(p, "LOC: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).apic_timer_irqs);
+-		seq_printf(p, "  Local timer interrupts\n");
+-#endif
+-#ifdef CONFIG_SMP
+-		seq_printf(p, "RES: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).irq_resched_count);
+-		seq_printf(p, "  Rescheduling interrupts\n");
+-		seq_printf(p, "CAL: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).irq_call_count);
+-		seq_printf(p, "  function call interrupts\n");
+-#ifndef CONFIG_XEN
+-		seq_printf(p, "TLB: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).irq_tlb_count);
+-		seq_printf(p, "  TLB shootdowns\n");
+-#endif
+-#endif
+-#ifdef CONFIG_X86_MCE
+-		seq_printf(p, "TRM: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).irq_thermal_count);
+-		seq_printf(p, "  Thermal event interrupts\n");
+-#endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		seq_printf(p, "SPU: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ",
+-				per_cpu(irq_stat,j).irq_spurious_count);
+-		seq_printf(p, "  Spurious interrupts\n");
+-#endif
+-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+-#if defined(CONFIG_X86_IO_APIC)
+-		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+-#endif
+-	}
+-	return 0;
+-}
+-
+-/*
+- * /proc/stat helpers
+- */
+-u64 arch_irq_stat_cpu(unsigned int cpu)
+-{
+-	u64 sum = nmi_count(cpu);
+-
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	sum += per_cpu(irq_stat, cpu).apic_timer_irqs;
+-#endif
+-#ifdef CONFIG_SMP
+-	sum += per_cpu(irq_stat, cpu).irq_resched_count;
+-	sum += per_cpu(irq_stat, cpu).irq_call_count;
+-#ifndef CONFIG_XEN
+-	sum += per_cpu(irq_stat, cpu).irq_tlb_count;
+-#endif
+-#endif
+-#ifdef CONFIG_X86_MCE
+-	sum += per_cpu(irq_stat, cpu).irq_thermal_count;
+-#endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	sum += per_cpu(irq_stat, cpu).irq_spurious_count;
+-#endif
+-	return sum;
+-}
+-
+-u64 arch_irq_stat(void)
+-{
+-	u64 sum = atomic_read(&irq_err_count);
+-
+-#ifdef CONFIG_X86_IO_APIC
+-	sum += atomic_read(&irq_mis_count);
+-#endif
+-	return sum;
+-}
+-
+ #ifdef CONFIG_HOTPLUG_CPU
+ 
+ void fixup_irqs(cpumask_t map)
+ {
+ 	unsigned int irq;
+ 	static int warned;
++	struct irq_desc *desc;
+ 
+-	for (irq = 0; irq < NR_IRQS; irq++) {
++	for_each_irq_desc(irq, desc) {
+ 		cpumask_t mask;
++
+ 		if (irq == 2)
+ 			continue;
+ 
+-		cpus_and(mask, irq_desc[irq].affinity, map);
++		cpus_and(mask, desc->affinity, map);
+ 		if (any_online_cpu(mask) == NR_CPUS) {
+ 			/*printk("Breaking affinity for irq %i\n", irq);*/
+ 			mask = map;
+ 		}
+-		if (irq_desc[irq].chip->set_affinity)
+-			irq_desc[irq].chip->set_affinity(irq, mask);
+-		else if (irq_desc[irq].action && !(warned++))
++		if (desc->chip->set_affinity)
++			desc->chip->set_affinity(irq, mask);
++		else if (desc->action && !(warned++))
+ 			printk("Cannot set affinity for irq %i\n", irq);
+ 	}
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -18,30 +18,6 @@
+ #include <asm/idle.h>
+ #include <asm/smp.h>
+ 
+-atomic_t irq_err_count;
+-
+-/*
+- * 'what should we do if we get a hw irq event on an illegal vector'.
+- * each architecture has to answer this themselves.
+- */
+-void ack_bad_irq(unsigned int irq)
+-{
+-	printk(KERN_WARNING "unexpected IRQ trap at irq %02x\n", irq);
+-#ifdef CONFIG_X86_LOCAL_APIC
+-	/*
+-	 * Currently unexpected vectors happen only on SMP and APIC.
+-	 * We _must_ ack these because every local APIC has only N
+-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+-	 * holds up an irq slot - in excessive cases (when multiple
+-	 * unexpected vectors occur) that might lock up the APIC
+-	 * completely.
+-	 * But don't ack when the APIC is disabled. -AK
+-	 */
+-	if (!disable_apic)
+-		ack_APIC_irq();
+-#endif
+-}
+-
+ #ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /*
+  * Probabilistic stack overflow check:
+@@ -67,130 +43,6 @@ static inline void stack_overflow_check(
+ #endif
+ 
+ /*
+- * Generic, controller-independent functions:
+- */
+-
+-int show_interrupts(struct seq_file *p, void *v)
+-{
+-	int i = *(loff_t *) v, j;
+-	struct irqaction * action;
+-	unsigned long flags;
+-
+-	if (i == 0) {
+-		seq_printf(p, "           ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "CPU%-8d",j);
+-		seq_putc(p, '\n');
+-	}
+-
+-	if (i < NR_IRQS) {
+-		unsigned any_count = 0;
+-
+-		spin_lock_irqsave(&irq_desc[i].lock, flags);
+-#ifndef CONFIG_SMP
+-		any_count = kstat_irqs(i);
+-#else
+-		for_each_online_cpu(j)
+-			any_count |= kstat_cpu(j).irqs[i];
+-#endif
+-		action = irq_desc[i].action;
+-		if (!action && !any_count)
+-			goto skip;
+-		seq_printf(p, "%3d: ",i);
+-#ifndef CONFIG_SMP
+-		seq_printf(p, "%10u ", kstat_irqs(i));
+-#else
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+-#endif
+-		seq_printf(p, " %8s", irq_desc[i].chip->name);
+-		seq_printf(p, "-%-8s", irq_desc[i].name);
+-
+-		if (action) {
+-			seq_printf(p, "  %s", action->name);
+-			while ((action = action->next) != NULL)
+-				seq_printf(p, ", %s", action->name);
+-		}
+-		seq_putc(p, '\n');
+-skip:
+-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+-	} else if (i == NR_IRQS) {
+-		seq_printf(p, "NMI: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
+-		seq_printf(p, "  Non-maskable interrupts\n");
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		seq_printf(p, "LOC: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
+-		seq_printf(p, "  Local timer interrupts\n");
+-#endif
+-#ifdef CONFIG_SMP
+-		seq_printf(p, "RES: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_resched_count);
+-		seq_printf(p, "  Rescheduling interrupts\n");
+-		seq_printf(p, "CAL: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
+-		seq_printf(p, "  function call interrupts\n");
+-#ifndef CONFIG_XEN
+-		seq_printf(p, "TLB: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
+-		seq_printf(p, "  TLB shootdowns\n");
+-#endif
+-#endif
+-#ifdef CONFIG_X86_MCE
+-		seq_printf(p, "TRM: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
+-		seq_printf(p, "  Thermal event interrupts\n");
+-		seq_printf(p, "THR: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
+-		seq_printf(p, "  Threshold APIC interrupts\n");
+-#endif
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		seq_printf(p, "SPU: ");
+-		for_each_online_cpu(j)
+-			seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
+-		seq_printf(p, "  Spurious interrupts\n");
+-#endif
+-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+-	}
+-	return 0;
+-}
+-
+-/*
+- * /proc/stat helpers
+- */
+-u64 arch_irq_stat_cpu(unsigned int cpu)
+-{
+-	u64 sum = cpu_pda(cpu)->__nmi_count;
+-
+-	sum += cpu_pda(cpu)->apic_timer_irqs;
+-#ifdef CONFIG_SMP
+-	sum += cpu_pda(cpu)->irq_resched_count;
+-	sum += cpu_pda(cpu)->irq_call_count;
+-#ifndef CONFIG_XEN
+-	sum += cpu_pda(cpu)->irq_tlb_count;
+-#endif
+-#endif
+-#ifdef CONFIG_X86_MCE
+-	sum += cpu_pda(cpu)->irq_thermal_count;
+-	sum += cpu_pda(cpu)->irq_threshold_count;
+-#endif
+-	sum += cpu_pda(cpu)->irq_spurious_count;
+-	return sum;
+-}
+-
+-u64 arch_irq_stat(void)
+-{
+-	return atomic_read(&irq_err_count);
+-}
+-
+-/*
+  * do_IRQ handles all normal device IRQ's (the special
+  * SMP cross-CPU interrupts have their own specific
+  * handlers).
+@@ -198,6 +50,7 @@ u64 arch_irq_stat(void)
+ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
+ {
+ 	struct pt_regs *old_regs = set_irq_regs(regs);
++	struct irq_desc *desc;
+ 
+ 	/* high bit used in ret_from_ code  */
+ 	unsigned irq = ~regs->orig_ax;
+@@ -209,8 +62,9 @@ asmlinkage unsigned int do_IRQ(struct pt
+ 	stack_overflow_check(regs);
+ #endif
+ 
+-	if (likely(irq < NR_IRQS))
+-		generic_handle_irq(irq);
++	desc = irq_to_desc(irq);
++	if (likely(desc))
++		generic_handle_irq_desc(irq, desc);
+ 	else {
+ #ifndef CONFIG_XEN
+ 		if (!disable_apic)
+@@ -232,8 +86,9 @@ void fixup_irqs(cpumask_t map)
+ {
+ 	unsigned int irq;
+ 	static int warned;
++	struct irq_desc *desc;
+ 
+-	for (irq = 0; irq < NR_IRQS; irq++) {
++	for_each_irq_desc(irq, desc) {
+ 		cpumask_t mask;
+ 		int break_affinity = 0;
+ 		int set_affinity = 1;
+@@ -242,32 +97,32 @@ void fixup_irqs(cpumask_t map)
+ 			continue;
+ 
+ 		/* interrupt's are disabled at this point */
+-		spin_lock(&irq_desc[irq].lock);
++		spin_lock(&desc->lock);
+ 
+ 		if (!irq_has_action(irq) ||
+-		    cpus_equal(irq_desc[irq].affinity, map)) {
+-			spin_unlock(&irq_desc[irq].lock);
++		    cpus_equal(desc->affinity, map)) {
++			spin_unlock(&desc->lock);
+ 			continue;
+ 		}
+ 
+-		cpus_and(mask, irq_desc[irq].affinity, map);
++		cpus_and(mask, desc->affinity, map);
+ 		if (cpus_empty(mask)) {
+ 			break_affinity = 1;
+ 			mask = map;
+ 		}
+ 
+-		if (irq_desc[irq].chip->mask)
+-			irq_desc[irq].chip->mask(irq);
++		if (desc->chip->mask)
++			desc->chip->mask(irq);
+ 
+-		if (irq_desc[irq].chip->set_affinity)
+-			irq_desc[irq].chip->set_affinity(irq, mask);
++		if (desc->chip->set_affinity)
++			desc->chip->set_affinity(irq, mask);
+ 		else if (!(warned++))
+ 			set_affinity = 0;
+ 
+-		if (irq_desc[irq].chip->unmask)
+-			irq_desc[irq].chip->unmask(irq);
++		if (desc->chip->unmask)
++			desc->chip->unmask(irq);
+ 
+-		spin_unlock(&irq_desc[irq].lock);
++		spin_unlock(&desc->lock);
+ 
+ 		if (break_affinity && set_affinity)
+ 			/*printk("Broke affinity for irq %i\n", irq)*/;
+--- head-2010-01-18.orig/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -18,6 +18,7 @@
+ #include <asm/ldt.h>
+ #include <asm/desc.h>
+ #include <asm/mmu_context.h>
++#include <asm/syscalls.h>
+ 
+ #ifdef CONFIG_SMP
+ static void flush_ldt(void *current_mm)
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,214 +0,0 @@
+-/*
+- *	Intel CPU Microcode Update Driver for Linux
+- *
+- *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+- *		      2006	Shaohua Li <shaohua.li@intel.com>
+- *
+- *	This driver allows to upgrade microcode on Intel processors
+- *	belonging to IA-32 family - PentiumPro, Pentium II,
+- *	Pentium III, Xeon, Pentium 4, etc.
+- *
+- *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+- *	Software Developer's Manual
+- *	Order Number 253668 or free download from:
+- *
+- *	http://developer.intel.com/design/pentium4/manuals/253668.htm
+- *
+- *	For more information, go to http://www.urbanmyth.org/microcode
+- *
+- *	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.
+- */
+-
+-//#define DEBUG /* pr_debug */
+-#include <linux/capability.h>
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/sched.h>
+-#include <linux/smp_lock.h>
+-#include <linux/cpumask.h>
+-#include <linux/module.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-#include <linux/miscdevice.h>
+-#include <linux/spinlock.h>
+-#include <linux/mm.h>
+-#include <linux/fs.h>
+-#include <linux/mutex.h>
+-#include <linux/cpu.h>
+-#include <linux/firmware.h>
+-#include <linux/platform_device.h>
+-
+-#include <asm/msr.h>
+-#include <asm/uaccess.h>
+-#include <asm/processor.h>
+-
+-MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
+-MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+-MODULE_LICENSE("GPL");
+-
+-static int verbose;
+-module_param(verbose, int, 0644);
+-
+-#define MICROCODE_VERSION 	"1.14a-xen"
+-
+-#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
+-#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
+-#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
+-
+-/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
+-static DEFINE_MUTEX(microcode_mutex);
+-				
+-#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+-static int do_microcode_update (const void __user *ubuf, size_t len)
+-{
+-	int err;
+-	void *kbuf;
+-
+-	kbuf = vmalloc(len);
+-	if (!kbuf)
+-		return -ENOMEM;
+-
+-	if (copy_from_user(kbuf, ubuf, len) == 0) {
+-		struct xen_platform_op op;
+-
+-		op.cmd = XENPF_microcode_update;
+-		set_xen_guest_handle(op.u.microcode.data, kbuf);
+-		op.u.microcode.length = len;
+-		err = HYPERVISOR_platform_op(&op);
+-	} else
+-		err = -EFAULT;
+-
+-	vfree(kbuf);
+-
+-	return err;
+-}
+-
+-static int microcode_open (struct inode *unused1, struct file *unused2)
+-{
+-	cycle_kernel_lock();
+-	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+-}
+-
+-static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
+-{
+-	ssize_t ret;
+-
+-	if (len < MC_HEADER_SIZE) {
+-		printk(KERN_ERR "microcode: not enough data\n"); 
+-		return -EINVAL;
+-	}
+-
+-	mutex_lock(&microcode_mutex);
+-
+-	ret = do_microcode_update(buf, len);
+-	if (!ret)
+-		ret = (ssize_t)len;
+-
+-	mutex_unlock(&microcode_mutex);
+-
+-	return ret;
+-}
+-
+-static const struct file_operations microcode_fops = {
+-	.owner		= THIS_MODULE,
+-	.write		= microcode_write,
+-	.open		= microcode_open,
+-};
+-
+-static struct miscdevice microcode_dev = {
+-	.minor		= MICROCODE_MINOR,
+-	.name		= "microcode",
+-	.fops		= &microcode_fops,
+-};
+-
+-static int __init microcode_dev_init (void)
+-{
+-	int error;
+-
+-	error = misc_register(&microcode_dev);
+-	if (error) {
+-		printk(KERN_ERR
+-			"microcode: can't misc_register on minor=%d\n",
+-			MICROCODE_MINOR);
+-		return error;
+-	}
+-
+-	return 0;
+-}
+-
+-static void microcode_dev_exit (void)
+-{
+-	misc_deregister(&microcode_dev);
+-}
+-
+-MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+-#else
+-#define microcode_dev_init() 0
+-#define microcode_dev_exit() do { } while(0)
+-#endif
+-
+-/* fake device for request_firmware */
+-static struct platform_device *microcode_pdev;
+-
+-static int request_microcode(void)
+-{
+-	char name[30];
+-	const struct cpuinfo_x86 *c = &boot_cpu_data;
+-	const struct firmware *firmware;
+-	int error;
+-	struct xen_platform_op op;
+-
+-	sprintf(name,"intel-ucode/%02x-%02x-%02x",
+-		c->x86, c->x86_model, c->x86_mask);
+-	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+-	if (error) {
+-		pr_debug("microcode: data file %s load failed\n", name);
+-		return error;
+-	}
+-
+-	op.cmd = XENPF_microcode_update;
+-	set_xen_guest_handle(op.u.microcode.data, firmware->data);
+-	op.u.microcode.length = firmware->size;
+-	error = HYPERVISOR_platform_op(&op);
+-
+-	release_firmware(firmware);
+-
+-	if (error)
+-		pr_debug("ucode load failed\n");
+-
+-	return error;
+-}
+-
+-static int __init microcode_init (void)
+-{
+-	int error;
+-
+-	printk(KERN_INFO
+-		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
+-
+-	error = microcode_dev_init();
+-	if (error)
+-		return error;
+-	microcode_pdev = platform_device_register_simple("microcode", -1,
+-							 NULL, 0);
+-	if (IS_ERR(microcode_pdev)) {
+-		microcode_dev_exit();
+-		return PTR_ERR(microcode_pdev);
+-	}
+-
+-	request_microcode();
+-
+-	return 0;
+-}
+-
+-static void __exit microcode_exit (void)
+-{
+-	microcode_dev_exit();
+-	platform_device_unregister(microcode_pdev);
+-}
+-
+-module_init(microcode_init)
+-module_exit(microcode_exit)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/microcode_core-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,225 @@
++/*
++ *	Intel CPU Microcode Update Driver for Linux
++ *
++ *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
++ *		      2006	Shaohua Li <shaohua.li@intel.com>
++ *
++ *	This driver allows to upgrade microcode on Intel processors
++ *	belonging to IA-32 family - PentiumPro, Pentium II,
++ *	Pentium III, Xeon, Pentium 4, etc.
++ *
++ *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
++ *	Software Developer's Manual
++ *	Order Number 253668 or free download from:
++ *
++ *	http://developer.intel.com/design/pentium4/manuals/253668.htm
++ *
++ *	For more information, go to http://www.urbanmyth.org/microcode
++ *
++ *	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.
++ */
++#include <linux/capability.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/cpumask.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/miscdevice.h>
++#include <linux/spinlock.h>
++#include <linux/mm.h>
++#include <linux/fs.h>
++#include <linux/mutex.h>
++#include <linux/cpu.h>
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
++
++#include <asm/msr.h>
++#include <asm/uaccess.h>
++#include <asm/processor.h>
++#include <asm/microcode.h>
++
++MODULE_DESCRIPTION("Microcode Update Driver");
++MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
++MODULE_LICENSE("GPL");
++
++static int verbose;
++module_param(verbose, int, 0644);
++
++#define MICROCODE_VERSION 	"2.00-xen"
++
++/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
++static DEFINE_MUTEX(microcode_mutex);
++
++#ifdef CONFIG_MICROCODE_OLD_INTERFACE
++static int do_microcode_update(const void __user *ubuf, size_t len)
++{
++	int err;
++	void *kbuf;
++
++	kbuf = vmalloc(len);
++	if (!kbuf)
++		return -ENOMEM;
++
++	if (copy_from_user(kbuf, ubuf, len) == 0) {
++		struct xen_platform_op op;
++
++		op.cmd = XENPF_microcode_update;
++		set_xen_guest_handle(op.u.microcode.data, kbuf);
++		op.u.microcode.length = len;
++		err = HYPERVISOR_platform_op(&op);
++	} else
++		err = -EFAULT;
++
++	vfree(kbuf);
++
++	return err;
++}
++
++static int microcode_open(struct inode *unused1, struct file *unused2)
++{
++	cycle_kernel_lock();
++	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
++}
++
++static ssize_t microcode_write(struct file *file, const char __user *buf,
++			       size_t len, loff_t *ppos)
++{
++	ssize_t ret;
++
++	if ((len >> PAGE_SHIFT) > num_physpages) {
++		printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
++		       num_physpages);
++ 		return -EINVAL;
++ 	}
++
++	mutex_lock(&microcode_mutex);
++
++	ret = do_microcode_update(buf, len);
++	if (!ret)
++		ret = (ssize_t)len;
++
++	mutex_unlock(&microcode_mutex);
++
++	return ret;
++}
++
++static const struct file_operations microcode_fops = {
++	.owner		= THIS_MODULE,
++	.write		= microcode_write,
++	.open		= microcode_open,
++};
++
++static struct miscdevice microcode_dev = {
++	.minor		= MICROCODE_MINOR,
++	.name		= "microcode",
++	.fops		= &microcode_fops,
++};
++
++static int __init microcode_dev_init(void)
++{
++	int error;
++
++	error = misc_register(&microcode_dev);
++	if (error) {
++		printk(KERN_ERR
++			"microcode: can't misc_register on minor=%d\n",
++			MICROCODE_MINOR);
++		return error;
++	}
++
++	return 0;
++}
++
++static void microcode_dev_exit(void)
++{
++	misc_deregister(&microcode_dev);
++}
++
++MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
++#else
++#define microcode_dev_init() 0
++#define microcode_dev_exit() do { } while (0)
++#endif
++
++/* fake device for request_firmware */
++static struct platform_device *microcode_pdev;
++
++static int request_microcode(const char *name)
++{
++	const struct firmware *firmware;
++	int error;
++	struct xen_platform_op op;
++
++	error = request_firmware(&firmware, name, &microcode_pdev->dev);
++	if (error) {
++		pr_debug("microcode: data file %s load failed\n", name);
++		return error;
++	}
++
++	op.cmd = XENPF_microcode_update;
++	set_xen_guest_handle(op.u.microcode.data, firmware->data);
++	op.u.microcode.length = firmware->size;
++	error = HYPERVISOR_platform_op(&op);
++
++	release_firmware(firmware);
++
++	if (error)
++		pr_debug("ucode load failed\n");
++
++	return error;
++}
++
++static int __init microcode_init(void)
++{
++	const struct cpuinfo_x86 *c = &boot_cpu_data;
++	char buf[32];
++	const char *fw_name = buf;
++	int error;
++
++	if (c->x86_vendor == X86_VENDOR_INTEL)
++		sprintf(buf, "intel-ucode/%02x-%02x-%02x",
++			c->x86, c->x86_model, c->x86_mask);
++	else if (c->x86_vendor == X86_VENDOR_AMD)
++		fw_name = "amd-ucode/microcode_amd.bin";
++	else {
++		printk(KERN_ERR "microcode: no support for this CPU vendor\n");
++		return -ENODEV;
++	}
++
++	error = microcode_dev_init();
++	if (error)
++		return error;
++	microcode_pdev = platform_device_register_simple("microcode", -1,
++							 NULL, 0);
++	if (IS_ERR(microcode_pdev)) {
++		microcode_dev_exit();
++		return PTR_ERR(microcode_pdev);
++	}
++
++	request_microcode(fw_name);
++
++	printk(KERN_INFO
++	       "Microcode Update Driver: v" MICROCODE_VERSION
++	       " <tigran@aivazian.fsnet.co.uk>,"
++	       " Peter Oruba\n");
++
++	return 0;
++}
++
++static void __exit microcode_exit(void)
++{
++	microcode_dev_exit();
++	platform_device_unregister(microcode_pdev);
++
++	printk(KERN_INFO
++	       "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
++}
++
++module_init(microcode_init);
++module_exit(microcode_exit);
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -406,7 +406,9 @@ static int __init smp_read_mpc(struct mp
+        generic_bigsmp_probe();
+ #endif
+ 
++#ifdef CONFIG_X86_32
+ 	setup_apic_routing();
++#endif
+ 	if (!num_processors)
+ 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ 	return num_processors;
+@@ -611,6 +613,9 @@ static void __init __get_smp_config(unsi
+ 		printk(KERN_INFO "Using ACPI for processor (LAPIC) "
+ 		       "configuration information\n");
+ 
++	if (!mpf)
++		return;
++
+ 	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+ 	       mpf->mpf_specification);
+ #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -41,11 +41,12 @@ EXPORT_SYMBOL(bad_dma_address);
+ /* Dummy device used for NULL arguments (normally ISA). Better would
+    be probably a smaller DMA mask, but this is bug-to-bug compatible
+    to older i386. */
+-struct device fallback_dev = {
++struct device x86_dma_fallback_dev = {
+ 	.bus_id = "fallback device",
+ 	.coherent_dma_mask = DMA_32BIT_MASK,
+-	.dma_mask = &fallback_dev.coherent_dma_mask,
++	.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
+ };
++EXPORT_SYMBOL(x86_dma_fallback_dev);
+ 
+ int dma_set_mask(struct device *dev, u64 mask)
+ {
+@@ -82,7 +83,7 @@ void __init dma32_reserve_bootmem(void)
+ 	 * using 512M as goal
+ 	 */
+ 	align = 64ULL<<20;
+-	size = round_up(dma32_bootmem_size, align);
++	size = roundup(dma32_bootmem_size, align);
+ 	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
+ 				 512ULL<<20);
+ 	if (dma32_bootmem_ptr)
+@@ -109,6 +110,8 @@ static void __init dma32_free_bootmem(vo
+ #endif
+ 
+ static struct dma_mapping_ops swiotlb_dma_ops = {
++	.alloc_coherent = dma_generic_alloc_coherent,
++	.free_coherent = dma_generic_free_coherent,
+ 	.mapping_error = swiotlb_dma_mapping_error,
+ 	.map_single = swiotlb_map_single_phys,
+ 	.unmap_single = swiotlb_unmap_single,
+@@ -147,13 +150,77 @@ void __init pci_iommu_alloc(void)
+ }
+ 
+ #ifndef CONFIG_XEN
+-unsigned long iommu_num_pages(unsigned long addr, unsigned long len)
++unsigned long iommu_nr_pages(unsigned long addr, unsigned long len)
+ {
+ 	unsigned long size = roundup((addr & ~PAGE_MASK) + len, PAGE_SIZE);
+ 
+ 	return size >> PAGE_SHIFT;
+ }
+-EXPORT_SYMBOL(iommu_num_pages);
++EXPORT_SYMBOL(iommu_nr_pages);
++#endif
++
++void *dma_generic_alloc_coherent(struct device *dev, size_t size,
++				 dma_addr_t *dma_addr, gfp_t flag)
++{
++	unsigned long dma_mask;
++	struct page *page;
++#ifndef CONFIG_XEN
++	dma_addr_t addr;
++#else
++	void *memory;
++#endif
++	unsigned int order = get_order(size);
++
++	dma_mask = dma_alloc_coherent_mask(dev, flag);
++
++#ifndef CONFIG_XEN
++	flag |= __GFP_ZERO;
++again:
++#else
++	flag &= ~(__GFP_DMA | __GFP_DMA32);
++#endif
++	page = alloc_pages_node(dev_to_node(dev), flag, order);
++	if (!page)
++		return NULL;
++
++#ifndef CONFIG_XEN
++	addr = page_to_phys(page);
++	if (!is_buffer_dma_capable(dma_mask, addr, size)) {
++		__free_pages(page, order);
++
++		if (dma_mask < DMA_32BIT_MASK && !(flag & GFP_DMA)) {
++			flag = (flag & ~GFP_DMA32) | GFP_DMA;
++			goto again;
++		}
++
++		return NULL;
++	}
++
++	*dma_addr = addr;
++	return page_address(page);
++#else
++	memory = page_address(page);
++	if (xen_create_contiguous_region((unsigned long)memory, order,
++					 fls64(dma_mask))) {
++		__free_pages(page, order);
++		return NULL;
++	}
++
++	*dma_addr = virt_to_bus(memory);
++	return memset(memory, 0, size);
++#endif
++}
++
++#ifdef CONFIG_XEN
++void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
++			       dma_addr_t dma_addr)
++{
++	unsigned int order = get_order(size);
++	unsigned long va = (unsigned long)vaddr;
++
++	xen_destroy_contiguous_region(va, order);
++	free_pages(va, order);
++}
+ #endif
+ 
+ /*
+@@ -291,164 +358,6 @@ int dma_supported(struct device *dev, u6
+ }
+ EXPORT_SYMBOL(dma_supported);
+ 
+-/* Allocate DMA memory on node near device */
+-static struct page *
+-dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+-{
+-	int node;
+-
+-	node = dev_to_node(dev);
+-
+-	return alloc_pages_node(node, gfp, order);
+-}
+-
+-/*
+- * Allocate memory for a coherent mapping.
+- */
+-void *
+-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+-		   gfp_t gfp)
+-{
+-#ifndef CONFIG_XEN
+-	struct dma_mapping_ops *ops = get_dma_ops(dev);
+-#endif
+-	void *memory = NULL;
+-	struct page *page;
+-	unsigned long dma_mask = 0;
+-	int noretry = 0;
+-	unsigned int order = get_order(size);
+-
+-	/* ignore region specifiers */
+-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+-
+-	if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
+-		return memory;
+-
+-	if (!dev) {
+-		dev = &fallback_dev;
+-		gfp |= GFP_DMA;
+-	}
+-	dma_mask = dev->coherent_dma_mask;
+-	if (dma_mask == 0)
+-		dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK;
+-
+-	/* Device not DMA able */
+-	if (dev->dma_mask == NULL)
+-		return NULL;
+-
+-#ifdef CONFIG_XEN
+-	gfp &= ~(__GFP_DMA | __GFP_DMA32);
+-#else
+-	/* Don't invoke OOM killer or retry in lower 16MB DMA zone */
+-	if (gfp & __GFP_DMA)
+-		noretry = 1;
+-
+-#ifdef CONFIG_X86_64
+-	/* Why <=? Even when the mask is smaller than 4GB it is often
+-	   larger than 16MB and in this case we have a chance of
+-	   finding fitting memory in the next higher zone first. If
+-	   not retry with true GFP_DMA. -AK */
+-	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
+-		gfp |= GFP_DMA32;
+-#endif
+-
+- again:
+-#endif
+-	page = dma_alloc_pages(dev,
+-		noretry ? gfp | __GFP_NORETRY : gfp, order);
+-	if (page == NULL)
+-		return NULL;
+-
+-#ifndef CONFIG_XEN
+-	{
+-		int high, mmu;
+-		dma_addr_t bus = page_to_phys(page);
+-		memory = page_address(page);
+-		high = (bus + size) >= dma_mask;
+-		mmu = high;
+-		if (force_iommu && !(gfp & GFP_DMA))
+-			mmu = 1;
+-		else if (high) {
+-			free_pages((unsigned long)memory, order);
+-
+-			/* Don't use the 16MB ZONE_DMA unless absolutely
+-			   needed. It's better to use remapping first. */
+-			if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
+-				gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+-				goto again;
+-			}
+-
+-			/* Let low level make its own zone decisions */
+-			gfp &= ~(GFP_DMA32|GFP_DMA);
+-
+-			if (ops->alloc_coherent)
+-				return ops->alloc_coherent(dev, size,
+-							   dma_handle, gfp);
+-			return NULL;
+-		}
+-
+-		memset(memory, 0, size);
+-		if (!mmu) {
+-			*dma_handle = bus;
+-			return memory;
+-		}
+-	}
+-
+-	if (ops->alloc_coherent) {
+-		free_pages((unsigned long)memory, order);
+-		gfp &= ~(GFP_DMA|GFP_DMA32);
+-		return ops->alloc_coherent(dev, size, dma_handle, gfp);
+-	}
+-
+-	if (ops->map_simple) {
+-		*dma_handle = ops->map_simple(dev, virt_to_bus(memory),
+-					      size,
+-					      PCI_DMA_BIDIRECTIONAL);
+-		if (*dma_handle != bad_dma_address)
+-			return memory;
+-	}
+-#else
+-	memory = page_address(page);
+-	if (xen_create_contiguous_region((unsigned long)memory, order,
+-					 fls64(dma_mask)) == 0) {
+-		memset(memory, 0, size);
+-		*dma_handle = virt_to_bus(memory);
+-		return memory;
+-	}
+-#endif
+-
+-	if (panic_on_overflow)
+-		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",
+-		      (unsigned long)size);
+-	free_pages((unsigned long)memory, order);
+-	return NULL;
+-}
+-EXPORT_SYMBOL(dma_alloc_coherent);
+-
+-/*
+- * Unmap coherent memory.
+- * The caller must ensure that the device has finished accessing the mapping.
+- */
+-void dma_free_coherent(struct device *dev, size_t size,
+-			 void *vaddr, dma_addr_t bus)
+-{
+-#ifndef CONFIG_XEN
+-	struct dma_mapping_ops *ops = get_dma_ops(dev);
+-#endif
+-
+-	int order = get_order(size);
+-	WARN_ON(irqs_disabled());	/* for portability */
+-	if (dma_release_from_coherent(dev, order, vaddr))
+-		return;
+-#ifndef CONFIG_XEN
+-	if (ops->unmap_single)
+-		ops->unmap_single(dev, bus, size, 0);
+-#endif
+-	xen_destroy_contiguous_region((unsigned long)vaddr, order);
+-	free_pages((unsigned long)vaddr, order);
+-}
+-EXPORT_SYMBOL(dma_free_coherent);
+-
+ static int __init pci_iommu_init(void)
+ {
+ 	calgary_iommu_init();
+--- head-2010-01-18.orig/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-nommu-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -5,6 +5,7 @@
+ 
+ #include <xen/gnttab.h>
+ 
++#include <asm/iommu.h>
+ #include <asm/proto.h>
+ #include <asm/dma.h>
+ #include <asm/swiotlb.h>
+@@ -36,7 +37,7 @@ gnttab_map_sg(struct device *hwdev, stru
+ 			gnttab_dma_map_page(sg_page(sg)) + sg->offset;
+ 		sg->dma_length  = sg->length;
+ 		IOMMU_BUG_ON(address_needs_mapping(
+-			hwdev, sg->dma_address));
++			hwdev, sg->dma_address, sg->length));
+ 		IOMMU_BUG_ON(range_straddles_page_boundary(
+ 			page_to_pseudophys(sg_page(sg)) + sg->offset,
+ 			sg->length));
+@@ -67,7 +68,7 @@ gnttab_map_single(struct device *dev, ph
+ 	dma = gnttab_dma_map_page(pfn_to_page(paddr >> PAGE_SHIFT)) +
+ 	      offset_in_page(paddr);
+ 	IOMMU_BUG_ON(range_straddles_page_boundary(paddr, size));
+-	IOMMU_BUG_ON(address_needs_mapping(dev, dma));
++	IOMMU_BUG_ON(address_needs_mapping(dev, dma, size));
+ 
+ 	return dma;
+ }
+@@ -79,7 +80,9 @@ gnttab_unmap_single(struct device *dev, 
+ 	gnttab_dma_unmap_page(dma_addr);
+ }
+ 
+-static struct dma_mapping_ops nommu_dma_ops = {
++struct dma_mapping_ops nommu_dma_ops = {
++	.alloc_coherent = dma_generic_alloc_coherent,
++	.free_coherent = dma_generic_free_coherent,
+ 	.map_single = gnttab_map_single,
+ 	.unmap_single = gnttab_unmap_single,
+ 	.map_sg = gnttab_map_sg,
+--- head-2010-01-18.orig/arch/x86/kernel/process-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -180,7 +180,8 @@ static void mwait_idle(void)
+ static void poll_idle(void)
+ {
+ 	local_irq_enable();
+-	cpu_relax();
++	while (!need_resched())
++		cpu_relax();
+ }
+ 
+ #ifndef CONFIG_XEN
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include <linux/tick.h>
+ #include <linux/percpu.h>
+ #include <linux/prctl.h>
++#include <linux/dmi.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -60,6 +61,8 @@
+ #include <asm/cpu.h>
+ #include <asm/kdebug.h>
+ #include <asm/idle.h>
++#include <asm/syscalls.h>
++#include <asm/smp.h>
+ 
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+ asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+@@ -78,42 +81,12 @@ unsigned long thread_saved_pc(struct tas
+ 	return ((unsigned long *)tsk->thread.sp)[3];
+ }
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+-#ifndef CONFIG_XEN
+-#include <asm/nmi.h>
+-
+-static void cpu_exit_clear(void)
+-{
+-	int cpu = raw_smp_processor_id();
+-
+-	idle_task_exit();
+-
+-	cpu_uninit();
+-	irq_ctx_exit(cpu);
+-
+-	cpu_clear(cpu, cpu_callout_map);
+-	cpu_clear(cpu, cpu_callin_map);
+-
+-	numa_remove_cpu(cpu);
+-	c1e_remove_cpu(cpu);
+-}
+-#endif
+-
+-static inline void play_dead(void)
+-{
+-	idle_task_exit();
+-	local_irq_disable();
+-	cpu_clear(smp_processor_id(), cpu_initialized);
+-	preempt_enable_no_resched();
+-	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+-	cpu_bringup();
+-}
+-#else
++#ifndef CONFIG_SMP
+ static inline void play_dead(void)
+ {
+ 	BUG();
+ }
+-#endif /* CONFIG_HOTPLUG_CPU */
++#endif
+ 
+ /*
+  * The idle thread. There's no useful work to be
+@@ -155,12 +128,13 @@ void cpu_idle(void)
+ 	}
+ }
+ 
+-void __show_registers(struct pt_regs *regs, int all)
++void __show_regs(struct pt_regs *regs, int all)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+ 	unsigned long d0, d1, d2, d3, d6, d7;
+ 	unsigned long sp;
+ 	unsigned short ss, gs;
++	const char *board;
+ 
+ 	if (user_mode_vm(regs)) {
+ 		sp = regs->sp;
+@@ -173,11 +147,15 @@ void __show_registers(struct pt_regs *re
+ 	}
+ 
+ 	printk("\n");
+-	printk("Pid: %d, comm: %s %s (%s %.*s)\n",
++
++	board = dmi_get_system_info(DMI_PRODUCT_NAME);
++	if (!board)
++		board = "";
++	printk("Pid: %d, comm: %s %s (%s %.*s) %s\n",
+ 			task_pid_nr(current), current->comm,
+ 			print_tainted(), init_utsname()->release,
+ 			(int)strcspn(init_utsname()->version, " "),
+-			init_utsname()->version);
++			init_utsname()->version, board);
+ 
+ 	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+ 			(u16)regs->cs, regs->ip, regs->flags,
+@@ -216,7 +194,7 @@ void __show_registers(struct pt_regs *re
+ 
+ void show_regs(struct pt_regs *regs)
+ {
+-	__show_registers(regs, 1);
++	__show_regs(regs, 1);
+ 	show_trace(NULL, regs, &regs->sp, regs->bp);
+ }
+ 
+@@ -269,6 +247,14 @@ void exit_thread(void)
+ 		t->io_bitmap_ptr = NULL;
+ 		clear_thread_flag(TIF_IO_BITMAP);
+ 	}
++#ifdef CONFIG_X86_DS
++	/* Free any DS contexts that have not been properly released. */
++	if (unlikely(current->thread.ds_ctx)) {
++		/* we clear debugctl to make sure DS is not used. */
++		update_debugctlmsr(0);
++		ds_free(current->thread.ds_ctx);
++	}
++#endif /* CONFIG_X86_DS */
+ }
+ 
+ void flush_thread(void)
+@@ -434,6 +420,35 @@ int set_tsc_mode(unsigned int val)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_X86_DS
++static int update_debugctl(struct thread_struct *prev,
++			struct thread_struct *next, unsigned long debugctl)
++{
++	unsigned long ds_prev = 0;
++	unsigned long ds_next = 0;
++
++	if (prev->ds_ctx)
++		ds_prev = (unsigned long)prev->ds_ctx->ds;
++	if (next->ds_ctx)
++		ds_next = (unsigned long)next->ds_ctx->ds;
++
++	if (ds_next != ds_prev) {
++		/* we clear debugctl to make sure DS
++		 * is not in use when we change it */
++		debugctl = 0;
++		update_debugctlmsr(0);
++		wrmsr(MSR_IA32_DS_AREA, ds_next, 0);
++	}
++	return debugctl;
++}
++#else
++static int update_debugctl(struct thread_struct *prev,
++			struct thread_struct *next, unsigned long debugctl)
++{
++	return debugctl;
++}
++#endif /* CONFIG_X86_DS */
++
+ static noinline void
+ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+@@ -443,14 +458,7 @@ __switch_to_xtra(struct task_struct *pre
+ 	prev = &prev_p->thread;
+ 	next = &next_p->thread;
+ 
+-	debugctl = prev->debugctlmsr;
+-	if (next->ds_area_msr != prev->ds_area_msr) {
+-		/* we clear debugctl to make sure DS
+-		 * is not in use when we change it */
+-		debugctl = 0;
+-		update_debugctlmsr(0);
+-		wrmsr(MSR_IA32_DS_AREA, next->ds_area_msr, 0);
+-	}
++	debugctl = update_debugctl(prev, next, prev->debugctlmsr);
+ 
+ 	if (next->debugctlmsr != debugctl)
+ 		update_debugctlmsr(next->debugctlmsr);
+@@ -474,13 +482,13 @@ __switch_to_xtra(struct task_struct *pre
+ 			hard_enable_TSC();
+ 	}
+ 
+-#ifdef X86_BTS
++#ifdef CONFIG_X86_PTRACE_BTS
+ 	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+ 		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
+ 		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
+-#endif
++#endif /* CONFIG_X86_PTRACE_BTS */
+ }
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -40,11 +40,11 @@
+ #include <linux/kdebug.h>
+ #include <linux/tick.h>
+ #include <linux/prctl.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+ 
+-#include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+-#include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/mmu_context.h>
+@@ -58,6 +58,7 @@
+ #include <asm/hardirq.h>
+ #include <asm/ia32.h>
+ #include <asm/idle.h>
++#include <asm/syscalls.h>
+ 
+ #include <xen/cpu_hotplug.h>
+ 
+@@ -71,6 +72,13 @@ void idle_notifier_register(struct notif
+ {
+ 	atomic_notifier_chain_register(&idle_notifier, n);
+ }
++EXPORT_SYMBOL_GPL(idle_notifier_register);
++
++void idle_notifier_unregister(struct notifier_block *n)
++{
++	atomic_notifier_chain_unregister(&idle_notifier, n);
++}
++EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+ 
+ void enter_idle(void)
+ {
+@@ -94,25 +102,12 @@ void exit_idle(void)
+ 	__exit_idle();
+ }
+ 
+-#ifdef CONFIG_HOTPLUG_CPU
+-static inline void play_dead(void)
+-{
+-	idle_task_exit();
+-#ifndef CONFIG_XEN
+-	c1e_remove_cpu(raw_smp_processor_id());
+-#endif
+-	local_irq_disable();
+-	cpu_clear(smp_processor_id(), cpu_initialized);
+-	preempt_enable_no_resched();
+-	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+-	cpu_bringup();
+-}
+-#else
++#ifndef CONFIG_SMP
+ static inline void play_dead(void)
+ {
+ 	BUG();
+ }
+-#endif /* CONFIG_HOTPLUG_CPU */
++#endif
+ 
+ /*
+  * The idle thread. There's no useful work to be
+@@ -157,63 +152,74 @@ void cpu_idle(void)
+ }
+ 
+ /* Prints also some state that isn't saved in the pt_regs */
+-void __show_regs(struct pt_regs * regs)
++void __show_regs(struct pt_regs *regs, int all)
+ {
+-	unsigned long fs, gs, shadowgs;
++	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
+ 	unsigned long d0, d1, d2, d3, d6, d7;
+ 	unsigned int fsindex, gsindex;
+ 	unsigned int ds, cs, es;
+ 
+ 	printk("\n");
+ 	print_modules();
+-	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
++	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s\n",
+ 		current->pid, current->comm, print_tainted(),
+ 		init_utsname()->release,
+ 		(int)strcspn(init_utsname()->version, " "),
+ 		init_utsname()->version);
+-	printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
++	printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+ 	printk_address(regs->ip, 1);
+-	printk("RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->sp,
+-		regs->flags);
+-	printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
++	printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
++			regs->sp, regs->flags);
++	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ 	       regs->ax, regs->bx, regs->cx);
+-	printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
++	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ 	       regs->dx, regs->si, regs->di);
+-	printk("RBP: %016lx R08: %016lx R09: %016lx\n",
++	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+ 	       regs->bp, regs->r8, regs->r9);
+-	printk("R10: %016lx R11: %016lx R12: %016lx\n",
+-	       regs->r10, regs->r11, regs->r12); 
+-	printk("R13: %016lx R14: %016lx R15: %016lx\n",
+-	       regs->r13, regs->r14, regs->r15); 
+-
+-	asm("mov %%ds,%0" : "=r" (ds)); 
+-	asm("mov %%cs,%0" : "=r" (cs)); 
+-	asm("mov %%es,%0" : "=r" (es)); 
++	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
++	       regs->r10, regs->r11, regs->r12);
++	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
++	       regs->r13, regs->r14, regs->r15);
++
++	asm("movl %%ds,%0" : "=r" (ds));
++	asm("movl %%cs,%0" : "=r" (cs));
++	asm("movl %%es,%0" : "=r" (es));
+ 	asm("mov %%fs,%0" : "=r" (fsindex));
+ 	asm("mov %%gs,%0" : "=r" (gsindex));
+ 
+ 	rdmsrl(MSR_FS_BASE, fs);
+-	rdmsrl(MSR_GS_BASE, gs); 
+-	rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); 
++	rdmsrl(MSR_GS_BASE, gs);
++	rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
+ 
+-	printk("FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", 
+-	       fs,fsindex,gs,gsindex,shadowgs); 
+-	printk("CS:  %04x DS: %04x ES: %04x\n", cs, ds, es); 
++	if (!all)
++		return;
++
++	cr0 = read_cr0();
++	cr2 = read_cr2();
++	cr3 = read_cr3();
++	cr4 = read_cr4();
++
++	printk(KERN_INFO "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
++	       fs, fsindex, gs, gsindex, shadowgs);
++	printk(KERN_INFO "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
++			es, cr0);
++	printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
++			cr4);
+ 
+ 	get_debugreg(d0, 0);
+ 	get_debugreg(d1, 1);
+ 	get_debugreg(d2, 2);
+-	printk("DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
++	printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
+ 	get_debugreg(d3, 3);
+ 	get_debugreg(d6, 6);
+ 	get_debugreg(d7, 7);
+-	printk("DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
++	printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+ }
+ 
+ void show_regs(struct pt_regs *regs)
+ {
+-	printk("CPU %d:", smp_processor_id());
+-	__show_regs(regs);
++	printk(KERN_INFO "CPU %d:", smp_processor_id());
++	__show_regs(regs, 1);
+ 	show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
+ }
+ 
+@@ -250,6 +256,14 @@ void exit_thread(void)
+ #endif
+ 		t->io_bitmap_max = 0;
+ 	}
++#ifdef CONFIG_X86_DS
++	/* Free any DS contexts that have not been properly released. */
++	if (unlikely(t->ds_ctx)) {
++		/* we clear debugctl to make sure DS is not used. */
++		update_debugctlmsr(0);
++		ds_free(t->ds_ctx);
++	}
++#endif /* CONFIG_X86_DS */
+ }
+ 
+ void xen_load_gs_index(unsigned gs)
+@@ -330,10 +344,10 @@ void prepare_to_copy(struct task_struct 
+ 
+ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 		unsigned long unused,
+-	struct task_struct * p, struct pt_regs * regs)
++	struct task_struct *p, struct pt_regs *regs)
+ {
+ 	int err;
+-	struct pt_regs * childregs;
++	struct pt_regs *childregs;
+ 	struct task_struct *me = current;
+ 
+ 	childregs = ((struct pt_regs *)
+@@ -378,10 +392,10 @@ int copy_thread(int nr, unsigned long cl
+ 		if (test_thread_flag(TIF_IA32))
+ 			err = do_set_thread_area(p, -1,
+ 				(struct user_desc __user *)childregs->si, 0);
+-		else 			
+-#endif	 
+-			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8); 
+-		if (err) 
++		else
++#endif
++			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8);
++		if (err)
+ 			goto out;
+ 	}
+         p->thread.iopl = current->thread.iopl;
+@@ -489,13 +503,27 @@ static inline void __switch_to_xtra(stru
+ 	next = &next_p->thread;
+ 
+ 	debugctl = prev->debugctlmsr;
+-	if (next->ds_area_msr != prev->ds_area_msr) {
+-		/* we clear debugctl to make sure DS
+-		 * is not in use when we change it */
+-		debugctl = 0;
+-		update_debugctlmsr(0);
+-		wrmsrl(MSR_IA32_DS_AREA, next->ds_area_msr);
++
++#ifdef CONFIG_X86_DS
++	{
++		unsigned long ds_prev = 0, ds_next = 0;
++
++		if (prev->ds_ctx)
++			ds_prev = (unsigned long)prev->ds_ctx->ds;
++		if (next->ds_ctx)
++			ds_next = (unsigned long)next->ds_ctx->ds;
++
++		if (ds_next != ds_prev) {
++			/*
++			 * We clear debugctl to make sure DS
++			 * is not in use when we change it:
++			 */
++			debugctl = 0;
++			update_debugctlmsr(0);
++			wrmsrl(MSR_IA32_DS_AREA, ds_next);
++		}
+ 	}
++#endif /* CONFIG_X86_DS */
+ 
+ 	if (next->debugctlmsr != debugctl)
+ 		update_debugctlmsr(next->debugctlmsr);
+@@ -519,13 +547,13 @@ static inline void __switch_to_xtra(stru
+ 			hard_enable_TSC();
+ 	}
+ 
+-#ifdef X86_BTS
++#ifdef CONFIG_X86_PTRACE_BTS
+ 	if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS))
+ 		ptrace_bts_take_timestamp(prev_p, BTS_TASK_DEPARTS);
+ 
+ 	if (test_tsk_thread_flag(next_p, TIF_BTS_TRACE_TS))
+ 		ptrace_bts_take_timestamp(next_p, BTS_TASK_ARRIVES);
+-#endif
++#endif /* CONFIG_X86_PTRACE_BTS */
+ }
+ 
+ /*
+@@ -557,7 +585,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	multicall_entry_t _mcl[8], *mcl = _mcl;
+ 
+ 	/* we're going to use this soon, after a few expensive things */
+-	if (next_p->fpu_counter>5)
++	if (next_p->fpu_counter > 5)
+ 		prefetch(next->xstate);
+ 
+ 	/*
+@@ -638,12 +666,12 @@ __switch_to(struct task_struct *prev_p, 
+ 	if (unlikely(HYPERVISOR_multicall_check(_mcl, mcl - _mcl, NULL)))
+ 		BUG();
+ 
+-	/* 
++	/*
+ 	 * Switch DS and ES.
+ 	 * This won't pick up thread selector changes, but I guess that is ok.
+ 	 */
+ 	if (unlikely(next->es))
+-		loadsegment(es, next->es); 
++		loadsegment(es, next->es);
+ 
+ 	if (unlikely(next->ds))
+ 		loadsegment(ds, next->ds);
+@@ -657,7 +685,7 @@ __switch_to(struct task_struct *prev_p, 
+ 	 */
+ 	arch_leave_lazy_cpu_mode();
+ 
+-	/* 
++	/*
+ 	 * Switch FS and GS.
+ 	 *
+ 	 * Segment register != 0 always requires a reload.  Also
+@@ -676,12 +704,12 @@ __switch_to(struct task_struct *prev_p, 
+ 	if (next->gs)
+ 		WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER, next->gs));
+ 
+-	/* 
++	/*
+ 	 * Switch the PDA context.
+ 	 */
+ 	prev->usersp = read_pda(oldrsp);
+ 	write_pda(oldrsp, next->usersp);
+-	write_pda(pcurrent, next_p); 
++	write_pda(pcurrent, next_p);
+ 	write_pda(kernelstack,
+ 		  (unsigned long)task_stack_page(next_p) +
+ 		  THREAD_SIZE - PDA_STACKOFFSET);
+@@ -722,7 +750,7 @@ long sys_execve(char __user *name, char 
+ 		char __user * __user *envp, struct pt_regs *regs)
+ {
+ 	long error;
+-	char * filename;
++	char *filename;
+ 
+ 	filename = getname(name);
+ 	error = PTR_ERR(filename);
+@@ -780,56 +808,56 @@ asmlinkage long sys_vfork(struct pt_regs
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ 	unsigned long stack;
+-	u64 fp,ip;
++	u64 fp, ip;
+ 	int count = 0;
+ 
+-	if (!p || p == current || p->state==TASK_RUNNING)
+-		return 0; 
++	if (!p || p == current || p->state == TASK_RUNNING)
++		return 0;
+ 	stack = (unsigned long)task_stack_page(p);
+-	if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE)
++	if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
+ 		return 0;
+ 	fp = *(u64 *)(p->thread.sp);
+-	do { 
++	do {
+ 		if (fp < (unsigned long)stack ||
+-		    fp > (unsigned long)stack+THREAD_SIZE)
+-			return 0; 
++		    fp >= (unsigned long)stack+THREAD_SIZE)
++			return 0;
+ 		ip = *(u64 *)(fp+8);
+ 		if (!in_sched_functions(ip))
+ 			return ip;
+-		fp = *(u64 *)fp; 
+-	} while (count++ < 16); 
++		fp = *(u64 *)fp;
++	} while (count++ < 16);
+ 	return 0;
+ }
+ 
+ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
+-{ 
+-	int ret = 0; 
++{
++	int ret = 0;
+ 	int doit = task == current;
+ 	int cpu;
+ 
+-	switch (code) { 
++	switch (code) {
+ 	case ARCH_SET_GS:
+ 		if (addr >= TASK_SIZE_OF(task))
+-			return -EPERM; 
++			return -EPERM;
+ 		cpu = get_cpu();
+-		/* handle small bases via the GDT because that's faster to 
++		/* handle small bases via the GDT because that's faster to
+ 		   switch. */
+-		if (addr <= 0xffffffff) {  
+-			set_32bit_tls(task, GS_TLS, addr); 
+-			if (doit) { 
++		if (addr <= 0xffffffff) {
++			set_32bit_tls(task, GS_TLS, addr);
++			if (doit) {
+ 				load_TLS(&task->thread, cpu);
+-				load_gs_index(GS_TLS_SEL); 
++				load_gs_index(GS_TLS_SEL);
+ 			}
+-			task->thread.gsindex = GS_TLS_SEL; 
++			task->thread.gsindex = GS_TLS_SEL;
+ 			task->thread.gs = 0;
+-		} else { 
++		} else {
+ 			task->thread.gsindex = 0;
+ 			task->thread.gs = addr;
+ 			if (doit) {
+ 				load_gs_index(0);
+ 				ret = HYPERVISOR_set_segment_base(
+ 					SEGBASE_GS_USER, addr);
+-			} 
++			}
+ 		}
+ 		put_cpu();
+ 		break;
+@@ -884,8 +912,7 @@ long do_arch_prctl(struct task_struct *t
+ 				rdmsrl(MSR_KERNEL_GS_BASE, base);
+ 			else
+ 				base = task->thread.gs;
+-		}
+-		else
++		} else
+ 			base = task->thread.gs;
+ 		ret = put_user(base, (unsigned long __user *)addr);
+ 		break;
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -352,9 +352,27 @@ static void ati_force_hpet_resume(void)
+ 	printk(KERN_DEBUG "Force enabled HPET at resume\n");
+ }
+ 
++static u32 ati_ixp4x0_rev(struct pci_dev *dev)
++{
++	u32 d;
++	u8  b;
++
++	pci_read_config_byte(dev, 0xac, &b);
++	b &= ~(1<<5);
++	pci_write_config_byte(dev, 0xac, b);
++	pci_read_config_dword(dev, 0x70, &d);
++	d |= 1<<8;
++	pci_write_config_dword(dev, 0x70, d);
++	pci_read_config_dword(dev, 0x8, &d);
++	d &= 0xff;
++	dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d);
++	return d;
++}
++
+ static void ati_force_enable_hpet(struct pci_dev *dev)
+ {
+-	u32 uninitialized_var(val);
++	u32 d, val;
++	u8  b;
+ 
+ 	if (hpet_address || force_hpet_address)
+ 		return;
+@@ -364,14 +382,33 @@ static void ati_force_enable_hpet(struct
+ 		return;
+ 	}
+ 
++	d = ati_ixp4x0_rev(dev);
++	if (d  < 0x82)
++		return;
++
++	/* base address */
+ 	pci_write_config_dword(dev, 0x14, 0xfed00000);
+ 	pci_read_config_dword(dev, 0x14, &val);
++
++	/* enable interrupt */
++	outb(0x72, 0xcd6); b = inb(0xcd7);
++	b |= 0x1;
++	outb(0x72, 0xcd6); outb(b, 0xcd7);
++	outb(0x72, 0xcd6); b = inb(0xcd7);
++	if (!(b & 0x1))
++		return;
++	pci_read_config_dword(dev, 0x64, &d);
++	d |= (1<<10);
++	pci_write_config_dword(dev, 0x64, d);
++	pci_read_config_dword(dev, 0x64, &d);
++	if (!(d & (1<<10)))
++		return;
++
+ 	force_hpet_address = val;
+ 	force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
+ 	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
+ 		   force_hpet_address);
+ 	cached_dev = dev;
+-	return;
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
+ 			 ati_force_enable_hpet);
+--- head-2010-01-18.orig/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -261,6 +261,9 @@ unsigned long saved_video_mode;
+ #define RAMDISK_LOAD_FLAG		0x4000
+ 
+ static char __initdata command_line[COMMAND_LINE_SIZE];
++#ifdef CONFIG_CMDLINE_BOOL
++static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
++#endif
+ 
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ struct edd edd;
+@@ -339,7 +342,7 @@ static void __init relocate_initrd(void)
+ 		if (clen > MAX_MAP_CHUNK-slop)
+ 			clen = MAX_MAP_CHUNK-slop;
+ 		mapaddr = ramdisk_image & PAGE_MASK;
+-		p = early_ioremap(mapaddr, clen+slop);
++		p = early_memremap(mapaddr, clen+slop);
+ 		memcpy(q, p+slop, clen);
+ 		early_iounmap(p, clen+slop);
+ 		q += clen;
+@@ -430,7 +433,7 @@ static void __init parse_setup_data(void
+ 		return;
+ 	pa_data = boot_params.hdr.setup_data;
+ 	while (pa_data) {
+-		data = early_ioremap(pa_data, PAGE_SIZE);
++		data = early_memremap(pa_data, PAGE_SIZE);
+ 		switch (data->type) {
+ 		case SETUP_E820_EXT:
+ 			parse_e820_ext(data, pa_data);
+@@ -455,7 +458,7 @@ static void __init e820_reserve_setup_da
+ 		return;
+ 	pa_data = boot_params.hdr.setup_data;
+ 	while (pa_data) {
+-		data = early_ioremap(pa_data, sizeof(*data));
++		data = early_memremap(pa_data, sizeof(*data));
+ 		e820_update_range(pa_data, sizeof(*data)+data->len,
+ 			 E820_RAM, E820_RESERVED_KERN);
+ 		found = 1;
+@@ -483,7 +486,7 @@ static void __init reserve_early_setup_d
+ 		return;
+ 	pa_data = boot_params.hdr.setup_data;
+ 	while (pa_data) {
+-		data = early_ioremap(pa_data, sizeof(*data));
++		data = early_memremap(pa_data, sizeof(*data));
+ 		sprintf(buf, "setup data %x", data->type);
+ 		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+ 		pa_data = data->next;
+@@ -625,7 +628,13 @@ static void __init reserve_standard_io_r
+ 
+ }
+ 
+-#ifdef CONFIG_PROC_VMCORE
++/*
++ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
++ * is_kdump_kernel() to determine if we are booting after a panic. Hence
++ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
++ */
++
++#ifdef CONFIG_CRASH_DUMP
+ /* elfcorehdr= specifies the location of elf core header
+  * stored by the crashed kernel. This option will be passed
+  * by kexec loader to the capture kernel.
+@@ -646,6 +655,190 @@ static struct x86_quirks default_x86_qui
+ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+ 
+ /*
++ * Some BIOSes seem to corrupt the low 64k of memory during events
++ * like suspend/resume and unplugging an HDMI cable.  Reserve all
++ * remaining free memory in that area and fill it with a distinct
++ * pattern.
++ */
++#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
++#define MAX_SCAN_AREAS	8
++
++static int __read_mostly memory_corruption_check = -1;
++
++static unsigned __read_mostly corruption_check_size = 64*1024;
++static unsigned __read_mostly corruption_check_period = 60; /* seconds */
++
++static struct e820entry scan_areas[MAX_SCAN_AREAS];
++static int num_scan_areas;
++
++
++static int set_corruption_check(char *arg)
++{
++	char *end;
++
++	memory_corruption_check = simple_strtol(arg, &end, 10);
++
++	return (*end == 0) ? 0 : -EINVAL;
++}
++early_param("memory_corruption_check", set_corruption_check);
++
++static int set_corruption_check_period(char *arg)
++{
++	char *end;
++
++	corruption_check_period = simple_strtoul(arg, &end, 10);
++
++	return (*end == 0) ? 0 : -EINVAL;
++}
++early_param("memory_corruption_check_period", set_corruption_check_period);
++
++static int set_corruption_check_size(char *arg)
++{
++	char *end;
++	unsigned size;
++
++	size = memparse(arg, &end);
++
++	if (*end == '\0')
++		corruption_check_size = size;
++
++	return (size == corruption_check_size) ? 0 : -EINVAL;
++}
++early_param("memory_corruption_check_size", set_corruption_check_size);
++
++
++static void __init setup_bios_corruption_check(void)
++{
++	u64 addr = PAGE_SIZE;	/* assume first page is reserved anyway */
++
++	if (memory_corruption_check == -1) {
++		memory_corruption_check =
++#ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
++			1
++#else
++			0
++#endif
++			;
++	}
++
++	if (corruption_check_size == 0)
++		memory_corruption_check = 0;
++
++	if (!memory_corruption_check)
++		return;
++
++	corruption_check_size = round_up(corruption_check_size, PAGE_SIZE);
++
++	while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
++		u64 size;
++		addr = find_e820_area_size(addr, &size, PAGE_SIZE);
++
++		if (addr == 0)
++			break;
++
++		if ((addr + size) > corruption_check_size)
++			size = corruption_check_size - addr;
++
++		if (size == 0)
++			break;
++
++		e820_update_range(addr, size, E820_RAM, E820_RESERVED);
++		scan_areas[num_scan_areas].addr = addr;
++		scan_areas[num_scan_areas].size = size;
++		num_scan_areas++;
++
++		/* Assume we've already mapped this early memory */
++		memset(__va(addr), 0, size);
++
++		addr += size;
++	}
++
++	printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
++	       num_scan_areas);
++	update_e820();
++}
++
++static struct timer_list periodic_check_timer;
++
++void check_for_bios_corruption(void)
++{
++	int i;
++	int corruption = 0;
++
++	if (!memory_corruption_check)
++		return;
++
++	for(i = 0; i < num_scan_areas; i++) {
++		unsigned long *addr = __va(scan_areas[i].addr);
++		unsigned long size = scan_areas[i].size;
++
++		for(; size; addr++, size -= sizeof(unsigned long)) {
++			if (!*addr)
++				continue;
++			printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n",
++			       addr, __pa(addr), *addr);
++			corruption = 1;
++			*addr = 0;
++		}
++	}
++
++	WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n");
++}
++
++static void periodic_check_for_corruption(unsigned long data)
++{
++	check_for_bios_corruption();
++	mod_timer(&periodic_check_timer, round_jiffies(jiffies + corruption_check_period*HZ));
++}
++
++void start_periodic_check_for_corruption(void)
++{
++	if (!memory_corruption_check || corruption_check_period == 0)
++		return;
++
++	printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
++	       corruption_check_period);
++
++	init_timer(&periodic_check_timer);
++	periodic_check_timer.function = &periodic_check_for_corruption;
++	periodic_check_for_corruption(0);
++}
++#endif
++
++static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
++{
++	printk(KERN_NOTICE
++		"%s detected: BIOS may corrupt low RAM, working it around.\n",
++		d->ident);
++
++	e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
++	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
++
++	return 0;
++}
++
++/* List of systems that have known low memory corruption BIOS problems */
++static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
++#ifdef CONFIG_X86_RESERVE_LOW_64K
++	{
++		.callback = dmi_low_memory_corruption,
++		.ident = "AMI BIOS",
++		.matches = {
++			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
++		},
++	},
++	{
++		.callback = dmi_low_memory_corruption,
++		.ident = "Phoenix BIOS",
++		.matches = {
++			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
++		},
++	},
++#endif
++	{}
++};
++
++/*
+  * Determine if we were loaded by an EFI loader.  If so, then we have also been
+  * passed the efi memmap, systab, etc., so we should use these data structures
+  * for initialization.  Note, the efi init code path is determined by the
+@@ -691,6 +884,9 @@ void __init setup_arch(char **cmdline_p)
+ 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ #endif
+ 
++	/* VMI may relocate the fixmap; do this before touching ioremap area */
++	vmi_init();
++
+ 	early_cpu_init();
+ 	early_ioremap_init();
+ 
+@@ -785,6 +981,19 @@ void __init setup_arch(char **cmdline_p)
+ 	bss_resource.start = virt_to_phys(&__bss_start);
+ 	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+ 
++#ifdef CONFIG_CMDLINE_BOOL
++#ifdef CONFIG_CMDLINE_OVERRIDE
++	strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
++#else
++	if (builtin_cmdline[0]) {
++		/* append boot loader cmdline to builtin */
++		strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
++		strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
++		strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
++	}
++#endif
++#endif
++
+ 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
+@@ -794,13 +1003,8 @@ void __init setup_arch(char **cmdline_p)
+ 	check_efer();
+ #endif
+ 
+-#if defined(CONFIG_VMI) && defined(CONFIG_X86_32)
+-	/*
+-	 * Must be before kernel pagetables are setup
+-	 * or fixmap area is touched.
+-	 */
+-	vmi_init();
+-#endif
++	/* Must be before kernel pagetables are setup */
++	vmi_activate();
+ 
+ 	/* after early param, so could get panic from serial */
+ 	reserve_early_setup_data();
+@@ -819,10 +1023,15 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	finish_e820_parsing();
+ 
++	if (is_initial_xendomain()) {
++		dmi_scan_machine();
++
++		dmi_check_system(bad_bios_dmi_table);
++
+ #ifdef CONFIG_X86_32
+-	if (is_initial_xendomain())
+ 		probe_roms();
+ #endif
++	}
+ 
+ #ifndef CONFIG_XEN
+ 	/* after parse_early_param, so could debug it */
+@@ -868,6 +1077,10 @@ void __init setup_arch(char **cmdline_p)
+ 	num_physpages = max_pfn;
+ 	max_mapnr = max_pfn;
+ 
++#ifndef CONFIG_XEN
++ 	if (cpu_has_x2apic)
++ 		check_x2apic();
++#endif
+ 
+ 	/* How many end-of-memory variables you have, grandma! */
+ 	/* need this before calling reserve_initrd */
+@@ -879,6 +1092,10 @@ void __init setup_arch(char **cmdline_p)
+ 	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+ #endif
+ 
++#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
++	setup_bios_corruption_check();
++#endif
++
+ 	/* max_pfn_mapped is updated here */
+ 	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
+ 	max_pfn_mapped = max_low_pfn_mapped;
+@@ -907,9 +1124,6 @@ void __init setup_arch(char **cmdline_p)
+ 	vsmp_init();
+ #endif
+ 
+-	if (is_initial_xendomain())
+-		dmi_scan_machine();
+-
+ 	io_delay_init();
+ 
+ #ifdef CONFIG_ACPI
+@@ -924,6 +1138,8 @@ void __init setup_arch(char **cmdline_p)
+ 	 */
+ 	acpi_boot_table_init();
+ 
++	early_acpi_boot_init();
++
+ #ifdef CONFIG_ACPI_NUMA
+ 	/*
+ 	 * Parse SRAT to discover nodes.
+@@ -1069,6 +1285,7 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ 	prefill_possible_map();
++
+ #ifdef CONFIG_X86_64
+ 	init_cpu_to_node();
+ #endif
+@@ -1077,6 +1294,9 @@ void __init setup_arch(char **cmdline_p)
+ 	init_apic_mappings();
+ 	ioapic_init_mappings();
+ 
++	/* need to wait for io_apic is mapped */
++	nr_irqs = probe_nr_irqs();
++
+ 	kvm_guest_init();
+ 
+ 	e820_reserve_resources();
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:33:38.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:41:33.000000000 +0100
+@@ -42,6 +42,7 @@
+ 
+ #include <asm/delay.h>
+ #include <asm/time.h>
++#include <asm/timer.h>
+ 
+ #include <xen/evtchn.h>
+ #include <xen/sysctl.h>
+@@ -406,14 +407,9 @@ unsigned long profile_pc(struct pt_regs 
+ 	unsigned long pc = instruction_pointer(regs);
+ 
+ #if defined(CONFIG_SMP) || defined(__x86_64__)
+-# ifdef __i386__
+-	if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->cs)
+-# else
+-	if (!user_mode(regs)
+-# endif
+-	    && in_lock_functions(pc)) {
++	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+ # ifdef CONFIG_FRAME_POINTER
+-		return ((unsigned long *)regs->bp)[1];
++		return *(unsigned long *)(regs->bp + sizeof(long));
+ # else
+ #  ifdef __i386__
+ 		unsigned long *sp = (unsigned long *)&regs->sp;
+@@ -565,6 +561,7 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	run_local_timers();
+ 	if (rcu_pending(cpu))
+ 		rcu_check_callbacks(cpu, user_mode_vm(get_irq_regs()));
++	printk_tick();
+ 	scheduler_tick();
+ 	run_posix_cpu_timers(current);
+ 	profile_tick(CPU_PROFILING);
+@@ -794,7 +791,8 @@ static void stop_hz_timer(void)
+ 	smp_mb();
+ 
+ 	/* Leave ourselves in tick mode if rcu or softirq or timer pending. */
+-	if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
++	if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
++	    local_softirq_pending() ||
+ 	    (j = get_next_timer_interrupt(jiffies),
+ 	     time_before_eq(j, jiffies))) {
+ 		cpu_clear(cpu, nohz_cpu_mask);
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/kernel/traps-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,1022 @@
++/*
++ *  Copyright (C) 1991, 1992  Linus Torvalds
++ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
++ *
++ *  Pentium III FXSR, SSE support
++ *	Gareth Hughes <gareth@valinux.com>, May 2000
++ */
++
++/*
++ * Handle hardware traps and faults.
++ */
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/kprobes.h>
++#include <linux/uaccess.h>
++#include <linux/utsname.h>
++#include <linux/kdebug.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/ptrace.h>
++#include <linux/string.h>
++#include <linux/unwind.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/kexec.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++#include <linux/bug.h>
++#include <linux/nmi.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/io.h>
++
++#ifdef CONFIG_EISA
++#include <linux/ioport.h>
++#include <linux/eisa.h>
++#endif
++
++#ifdef CONFIG_MCA
++#include <linux/mca.h>
++#endif
++
++#if defined(CONFIG_EDAC)
++#include <linux/edac.h>
++#endif
++
++#include <asm/stacktrace.h>
++#include <asm/processor.h>
++#include <asm/debugreg.h>
++#include <asm/atomic.h>
++#include <asm/system.h>
++#include <asm/unwind.h>
++#include <asm/traps.h>
++#include <asm/desc.h>
++#include <asm/i387.h>
++
++#include <mach_traps.h>
++
++#ifdef CONFIG_X86_64
++#include <asm/pgalloc.h>
++#include <asm/proto.h>
++#include <asm/pda.h>
++#else
++#include <asm/processor-flags.h>
++#include <asm/arch_hooks.h>
++#include <asm/nmi.h>
++#include <asm/smp.h>
++#include <asm/io.h>
++#include <asm/traps.h>
++
++#include "cpu/mcheck/mce.h"
++
++#ifndef CONFIG_XEN
++DECLARE_BITMAP(used_vectors, NR_VECTORS);
++EXPORT_SYMBOL_GPL(used_vectors);
++#endif
++
++asmlinkage int system_call(void);
++
++/* Do we ignore FPU interrupts ? */
++char ignore_fpu_irq;
++
++#ifndef CONFIG_X86_NO_IDT
++/*
++ * The IDT has to be page-aligned to simplify the Pentium
++ * F0 0F bug workaround.. We have a special link segment
++ * for this.
++ */
++gate_desc idt_table[256]
++	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
++#endif
++#endif
++
++static int ignore_nmis;
++
++static inline void conditional_sti(struct pt_regs *regs)
++{
++	if (regs->flags & X86_EFLAGS_IF)
++		local_irq_enable();
++}
++
++static inline void preempt_conditional_sti(struct pt_regs *regs)
++{
++	inc_preempt_count();
++	if (regs->flags & X86_EFLAGS_IF)
++		local_irq_enable();
++}
++
++static inline void preempt_conditional_cli(struct pt_regs *regs)
++{
++	if (regs->flags & X86_EFLAGS_IF)
++		local_irq_disable();
++	dec_preempt_count();
++}
++
++#ifdef CONFIG_X86_32
++static inline void
++die_if_kernel(const char *str, struct pt_regs *regs, long err)
++{
++	if (!user_mode_vm(regs))
++		die(str, regs, err);
++}
++
++/*
++ * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
++ * invalid offset set (the LAZY one) and the faulting thread has
++ * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS,
++ * we set the offset field correctly and return 1.
++ */
++static int lazy_iobitmap_copy(void)
++{
++#ifndef CONFIG_XEN
++	struct thread_struct *thread;
++	struct tss_struct *tss;
++	int cpu;
++
++	cpu = get_cpu();
++	tss = &per_cpu(init_tss, cpu);
++	thread = &current->thread;
++
++	if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
++	    thread->io_bitmap_ptr) {
++		memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
++		       thread->io_bitmap_max);
++		/*
++		 * If the previously set map was extending to higher ports
++		 * than the current one, pad extra space with 0xff (no access).
++		 */
++		if (thread->io_bitmap_max < tss->io_bitmap_max) {
++			memset((char *) tss->io_bitmap +
++				thread->io_bitmap_max, 0xff,
++				tss->io_bitmap_max - thread->io_bitmap_max);
++		}
++		tss->io_bitmap_max = thread->io_bitmap_max;
++		tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
++		tss->io_bitmap_owner = thread;
++		put_cpu();
++
++		return 1;
++	}
++	put_cpu();
++#endif
++
++	return 0;
++}
++#endif
++
++static void __kprobes
++do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
++	long error_code, siginfo_t *info)
++{
++	struct task_struct *tsk = current;
++
++#ifdef CONFIG_X86_32
++	if (regs->flags & X86_VM_MASK) {
++		/*
++		 * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
++		 * On nmi (interrupt 2), do_trap should not be called.
++		 */
++		if (trapnr < 6)
++			goto vm86_trap;
++		goto trap_signal;
++	}
++#endif
++
++	if (!user_mode(regs))
++		goto kernel_trap;
++
++#ifdef CONFIG_X86_32
++trap_signal:
++#endif
++	/*
++	 * We want error_code and trap_no set for userspace faults and
++	 * kernelspace faults which result in die(), but not
++	 * kernelspace faults which are fixed up.  die() gives the
++	 * process no chance to handle the signal and notice the
++	 * kernel fault information, so that won't result in polluting
++	 * the information about previously queued, but not yet
++	 * delivered, faults.  See also do_general_protection below.
++	 */
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = trapnr;
++
++#ifdef CONFIG_X86_64
++	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
++	    printk_ratelimit()) {
++		printk(KERN_INFO
++		       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
++		       tsk->comm, tsk->pid, str,
++		       regs->ip, regs->sp, error_code);
++		print_vma_addr(" in ", regs->ip);
++		printk("\n");
++	}
++#endif
++
++	if (info)
++		force_sig_info(signr, info, tsk);
++	else
++		force_sig(signr, tsk);
++	return;
++
++kernel_trap:
++	if (!fixup_exception(regs)) {
++		tsk->thread.error_code = error_code;
++		tsk->thread.trap_no = trapnr;
++		die(str, regs, error_code);
++	}
++	return;
++
++#ifdef CONFIG_X86_32
++vm86_trap:
++	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
++						error_code, trapnr))
++		goto trap_signal;
++	return;
++#endif
++}
++
++#define DO_ERROR(trapnr, signr, str, name)				\
++dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
++{									\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++							== NOTIFY_STOP)	\
++		return;							\
++	conditional_sti(regs);						\
++	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
++}
++
++#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
++dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
++{									\
++	siginfo_t info;							\
++	info.si_signo = signr;						\
++	info.si_errno = 0;						\
++	info.si_code = sicode;						\
++	info.si_addr = (void __user *)siaddr;				\
++	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
++							== NOTIFY_STOP)	\
++		return;							\
++	conditional_sti(regs);						\
++	do_trap(trapnr, signr, str, regs, error_code, &info);		\
++}
++
++DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
++DO_ERROR(4, SIGSEGV, "overflow", overflow)
++DO_ERROR(5, SIGSEGV, "bounds", bounds)
++DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
++DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
++DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
++DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
++#ifdef CONFIG_X86_32
++DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
++#endif
++DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
++
++#ifdef CONFIG_X86_64
++/* Runs on IST stack */
++dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
++{
++	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
++			12, SIGBUS) == NOTIFY_STOP)
++		return;
++	preempt_conditional_sti(regs);
++	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
++	preempt_conditional_cli(regs);
++}
++
++dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
++{
++	static const char str[] = "double fault";
++	struct task_struct *tsk = current;
++
++	/* Return not checked because double check cannot be ignored */
++	notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 8;
++
++	/* This is always a kernel trap and never fixable (and thus must
++	   never return). */
++	for (;;)
++		die(str, regs, error_code);
++}
++#endif
++
++dotraplinkage void __kprobes
++do_general_protection(struct pt_regs *regs, long error_code)
++{
++	struct task_struct *tsk;
++
++	conditional_sti(regs);
++
++#ifdef CONFIG_X86_32
++	if (lazy_iobitmap_copy()) {
++		/* restart the faulting instruction */
++		return;
++	}
++
++	if (regs->flags & X86_VM_MASK)
++		goto gp_in_vm86;
++#endif
++
++	tsk = current;
++	if (!user_mode(regs))
++		goto gp_in_kernel;
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
++
++	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
++			printk_ratelimit()) {
++		printk(KERN_INFO
++			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
++			tsk->comm, task_pid_nr(tsk),
++			regs->ip, regs->sp, error_code);
++		print_vma_addr(" in ", regs->ip);
++		printk("\n");
++	}
++
++	force_sig(SIGSEGV, tsk);
++	return;
++
++#ifdef CONFIG_X86_32
++gp_in_vm86:
++	local_irq_enable();
++	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
++	return;
++#endif
++
++gp_in_kernel:
++	if (fixup_exception(regs))
++		return;
++
++	tsk->thread.error_code = error_code;
++	tsk->thread.trap_no = 13;
++	if (notify_die(DIE_GPF, "general protection fault", regs,
++				error_code, 13, SIGSEGV) == NOTIFY_STOP)
++		return;
++	die("general protection fault", regs, error_code);
++}
++
++static notrace __kprobes void
++mem_parity_error(unsigned char reason, struct pt_regs *regs)
++{
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
++	printk(KERN_EMERG
++		"You have some hardware problem, likely on the PCI bus.\n");
++
++#if defined(CONFIG_EDAC)
++	if (edac_handler_set()) {
++		edac_atomic_assert_error();
++		return;
++	}
++#endif
++
++	if (panic_on_unrecovered_nmi)
++		panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
++
++	/* Clear and disable the memory parity error line. */
++	clear_mem_error(reason);
++}
++
++static notrace __kprobes void
++io_check_error(unsigned char reason, struct pt_regs *regs)
++{
++	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
++	show_registers(regs);
++
++	/* Re-enable the IOCK line, wait for a few seconds */
++	clear_io_check_error(reason);
++}
++
++static notrace __kprobes void
++unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
++{
++	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
++			NOTIFY_STOP)
++		return;
++#ifdef CONFIG_MCA
++	/*
++	 * Might actually be able to figure out what the guilty party
++	 * is:
++	 */
++	if (MCA_bus) {
++		mca_handle_nmi();
++		return;
++	}
++#endif
++	printk(KERN_EMERG
++		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
++			reason, smp_processor_id());
++
++	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
++	if (panic_on_unrecovered_nmi)
++		panic("NMI: Not continuing");
++
++	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
++}
++
++static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
++{
++	unsigned char reason = 0;
++	int cpu;
++
++	cpu = smp_processor_id();
++
++	/* Only the BSP gets external NMIs from the system. */
++	if (!cpu)
++		reason = get_nmi_reason();
++
++	if (!(reason & 0xc0)) {
++		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
++								== NOTIFY_STOP)
++			return;
++#ifdef CONFIG_X86_LOCAL_APIC
++		/*
++		 * Ok, so this is none of the documented NMI sources,
++		 * so it must be the NMI watchdog.
++		 */
++		if (nmi_watchdog_tick(regs, reason))
++			return;
++		if (!do_nmi_callback(regs, cpu))
++			unknown_nmi_error(reason, regs);
++#else
++		unknown_nmi_error(reason, regs);
++#endif
++
++		return;
++	}
++	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
++		return;
++
++	/* AK: following checks seem to be broken on modern chipsets. FIXME */
++	if (reason & 0x80)
++		mem_parity_error(reason, regs);
++	if (reason & 0x40)
++		io_check_error(reason, regs);
++#ifdef CONFIG_X86_32
++	/*
++	 * Reassert NMI in case it became active meanwhile
++	 * as it's edge-triggered:
++	 */
++	reassert_nmi();
++#endif
++}
++
++dotraplinkage notrace __kprobes void
++do_nmi(struct pt_regs *regs, long error_code)
++{
++	nmi_enter();
++
++#ifdef CONFIG_X86_32
++	{ int cpu; cpu = smp_processor_id(); ++nmi_count(cpu); }
++#else
++	add_pda(__nmi_count, 1);
++#endif
++
++	if (!ignore_nmis)
++		default_do_nmi(regs);
++
++	nmi_exit();
++}
++
++void stop_nmi(void)
++{
++	acpi_nmi_disable();
++	ignore_nmis++;
++}
++
++void restart_nmi(void)
++{
++	ignore_nmis--;
++	acpi_nmi_enable();
++}
++
++/* May run on IST stack. */
++dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
++{
++#ifdef CONFIG_KPROBES
++	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
++			== NOTIFY_STOP)
++		return;
++#else
++	if (notify_die(DIE_TRAP, "int3", regs, error_code, 3, SIGTRAP)
++			== NOTIFY_STOP)
++		return;
++#endif
++
++	preempt_conditional_sti(regs);
++	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
++	preempt_conditional_cli(regs);
++}
++
++#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
++/* Help handler running on IST stack to switch back to user stack
++   for scheduling or signal handling. The actual stack switch is done in
++   entry.S */
++asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
++{
++	struct pt_regs *regs = eregs;
++	/* Did already sync */
++	if (eregs == (struct pt_regs *)eregs->sp)
++		;
++	/* Exception from user space */
++	else if (user_mode(eregs))
++		regs = task_pt_regs(current);
++	/* Exception from kernel and interrupts are enabled. Move to
++	   kernel process stack. */
++	else if (eregs->flags & X86_EFLAGS_IF)
++		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
++	if (eregs != regs)
++		*regs = *eregs;
++	return regs;
++}
++#endif
++
++/*
++ * Our handling of the processor debug registers is non-trivial.
++ * We do not clear them on entry and exit from the kernel. Therefore
++ * it is possible to get a watchpoint trap here from inside the kernel.
++ * However, the code in ./ptrace.c has ensured that the user can
++ * only set watchpoints on userspace addresses. Therefore the in-kernel
++ * watchpoint trap can only occur in code which is reading/writing
++ * from user space. Such code must not hold kernel locks (since it
++ * can equally take a page fault), therefore it is safe to call
++ * force_sig_info even though that claims and releases locks.
++ *
++ * Code in ./signal.c ensures that the debug control register
++ * is restored before we deliver any signal, and therefore that
++ * user code runs with the correct debug control register even though
++ * we clear it here.
++ *
++ * Being careful here means that we don't have to be as careful in a
++ * lot of more complicated places (task switching can be a bit lazy
++ * about restoring all the debug state, and ptrace doesn't have to
++ * find every occurrence of the TF bit that could be saved away even
++ * by user code)
++ *
++ * May run on IST stack.
++ */
++dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
++{
++	struct task_struct *tsk = current;
++	unsigned long condition;
++	int si_code;
++
++	get_debugreg(condition, 6);
++
++	/*
++	 * The processor cleared BTF, so don't mark that we need it set.
++	 */
++	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
++	tsk->thread.debugctlmsr = 0;
++
++	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
++						SIGTRAP) == NOTIFY_STOP)
++		return;
++
++	/* It's safe to allow irq's after DR6 has been saved */
++	preempt_conditional_sti(regs);
++
++	/* Mask out spurious debug traps due to lazy DR7 setting */
++	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
++		if (!tsk->thread.debugreg7)
++			goto clear_dr7;
++	}
++
++#ifdef CONFIG_X86_32
++	if (regs->flags & X86_VM_MASK)
++		goto debug_vm86;
++#endif
++
++	/* Save debug status register where ptrace can see it */
++	tsk->thread.debugreg6 = condition;
++
++	/*
++	 * Single-stepping through TF: make sure we ignore any events in
++	 * kernel space (but re-enable TF when returning to user mode).
++	 */
++	if (condition & DR_STEP) {
++		if (!user_mode(regs))
++			goto clear_TF_reenable;
++	}
++
++	si_code = get_si_code(condition);
++	/* Ok, finally something we can handle */
++	send_sigtrap(tsk, regs, error_code, si_code);
++
++	/*
++	 * Disable additional traps. They'll be re-enabled when
++	 * the signal is delivered.
++	 */
++clear_dr7:
++	set_debugreg(0, 7);
++	preempt_conditional_cli(regs);
++	return;
++
++#ifdef CONFIG_X86_32
++debug_vm86:
++	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
++	preempt_conditional_cli(regs);
++	return;
++#endif
++
++clear_TF_reenable:
++	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
++	regs->flags &= ~X86_EFLAGS_TF;
++	preempt_conditional_cli(regs);
++	return;
++}
++
++#ifdef CONFIG_X86_64
++static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
++{
++	if (fixup_exception(regs))
++		return 1;
++
++	notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
++	/* Illegal floating point operation in the kernel */
++	current->thread.trap_no = trapnr;
++	die(str, regs, 0);
++	return 0;
++}
++#endif
++
++/*
++ * Note that we play around with the 'TS' bit in an attempt to get
++ * the correct behaviour even in the presence of the asynchronous
++ * IRQ13 behaviour
++ */
++void math_error(void __user *ip)
++{
++	struct task_struct *task;
++	siginfo_t info;
++	unsigned short cwd, swd;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 16;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = ip;
++	/*
++	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
++	 * status.  0x3f is the exception bits in these regs, 0x200 is the
++	 * C1 reg you need in case of a stack fault, 0x040 is the stack
++	 * fault bit.  We should only be taking one exception at a time,
++	 * so if this combination doesn't produce any single exception,
++	 * then we have a bad program that isn't synchronizing its FPU usage
++	 * and it will suffer the consequences since we won't be able to
++	 * fully reproduce the context of the exception
++	 */
++	cwd = get_fpu_cwd(task);
++	swd = get_fpu_swd(task);
++	switch (swd & ~cwd & 0x3f) {
++	case 0x000: /* No unmasked exception */
++#ifdef CONFIG_X86_32
++		return;
++#endif
++	default: /* Multiple exceptions */
++		break;
++	case 0x001: /* Invalid Op */
++		/*
++		 * swd & 0x240 == 0x040: Stack Underflow
++		 * swd & 0x240 == 0x240: Stack Overflow
++		 * User must clear the SF bit (0x40) if set
++		 */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
++{
++	conditional_sti(regs);
++
++#ifdef CONFIG_X86_32
++	ignore_fpu_irq = 1;
++#else
++	if (!user_mode(regs) &&
++	    kernel_math_error(regs, "kernel x87 math error", 16))
++		return;
++#endif
++
++	math_error((void __user *)regs->ip);
++}
++
++static void simd_math_error(void __user *ip)
++{
++	struct task_struct *task;
++	siginfo_t info;
++	unsigned short mxcsr;
++
++	/*
++	 * Save the info for the exception handler and clear the error.
++	 */
++	task = current;
++	save_init_fpu(task);
++	task->thread.trap_no = 19;
++	task->thread.error_code = 0;
++	info.si_signo = SIGFPE;
++	info.si_errno = 0;
++	info.si_code = __SI_FAULT;
++	info.si_addr = ip;
++	/*
++	 * The SIMD FPU exceptions are handled a little differently, as there
++	 * is only a single status/control register.  Thus, to determine which
++	 * unmasked exception was caught we must mask the exception mask bits
++	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
++	 */
++	mxcsr = get_fpu_mxcsr(task);
++	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
++	case 0x000:
++	default:
++		break;
++	case 0x001: /* Invalid Op */
++		info.si_code = FPE_FLTINV;
++		break;
++	case 0x002: /* Denormalize */
++	case 0x010: /* Underflow */
++		info.si_code = FPE_FLTUND;
++		break;
++	case 0x004: /* Zero Divide */
++		info.si_code = FPE_FLTDIV;
++		break;
++	case 0x008: /* Overflow */
++		info.si_code = FPE_FLTOVF;
++		break;
++	case 0x020: /* Precision */
++		info.si_code = FPE_FLTRES;
++		break;
++	}
++	force_sig_info(SIGFPE, &info, task);
++}
++
++dotraplinkage void
++do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
++{
++	conditional_sti(regs);
++
++#ifdef CONFIG_X86_32
++	if (cpu_has_xmm) {
++		/* Handle SIMD FPU exceptions on PIII+ processors. */
++		ignore_fpu_irq = 1;
++		simd_math_error((void __user *)regs->ip);
++		return;
++	}
++	/*
++	 * Handle strange cache flush from user space exception
++	 * in all other cases.  This is undocumented behaviour.
++	 */
++	if (regs->flags & X86_VM_MASK) {
++		handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
++		return;
++	}
++	current->thread.trap_no = 19;
++	current->thread.error_code = error_code;
++	die_if_kernel("cache flush denied", regs, error_code);
++	force_sig(SIGSEGV, current);
++#else
++	if (!user_mode(regs) &&
++			kernel_math_error(regs, "kernel simd math error", 19))
++		return;
++	simd_math_error((void __user *)regs->ip);
++#endif
++}
++
++#ifndef CONFIG_XEN
++dotraplinkage void
++do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
++{
++	conditional_sti(regs);
++#if 0
++	/* No need to warn about this any longer. */
++	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
++#endif
++}
++
++#ifdef CONFIG_X86_32
++unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
++{
++	struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
++	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
++	unsigned long new_kesp = kesp - base;
++	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
++	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
++
++	/* Set up base for espfix segment */
++	desc &= 0x00f0ff0000000000ULL;
++	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
++		((((__u64)base) << 32) & 0xff00000000000000ULL) |
++		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
++		(lim_pages & 0xffff);
++	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
++
++	return new_kesp;
++}
++#else
++asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
++{
++}
++
++asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
++{
++}
++#endif
++#endif /* CONFIG_XEN */
++
++/*
++ * 'math_state_restore()' saves the current math information in the
++ * old math state array, and gets the new ones from the current task
++ *
++ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
++ * Don't touch unless you *really* know how it works.
++ *
++ * Must be called with kernel preemption disabled (in this case,
++ * local interrupts are disabled at the call-site in entry.S).
++ */
++asmlinkage void math_state_restore(void)
++{
++	struct thread_info *thread = current_thread_info();
++	struct task_struct *tsk = thread->task;
++
++	if (!tsk_used_math(tsk)) {
++		local_irq_enable();
++		/*
++		 * does a slab alloc which can sleep
++		 */
++		if (init_fpu(tsk)) {
++			/*
++			 * ran out of memory!
++			 */
++			do_group_exit(SIGKILL);
++			return;
++		}
++		local_irq_disable();
++	}
++
++	/* NB. 'clts' is done for us by Xen during virtual trap. */
++#ifdef CONFIG_X86_32
++	restore_fpu(tsk);
++#else
++	/*
++	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
++	 */
++	if (unlikely(restore_fpu_checking(tsk))) {
++		stts();
++		force_sig(SIGSEGV, tsk);
++		return;
++	}
++#endif
++	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
++	tsk->fpu_counter++;
++}
++EXPORT_SYMBOL_GPL(math_state_restore);
++
++#ifndef CONFIG_MATH_EMULATION
++asmlinkage void math_emulate(long arg)
++{
++	printk(KERN_EMERG
++		"math-emulation not enabled and no coprocessor found.\n");
++	printk(KERN_EMERG "killing %s.\n", current->comm);
++	force_sig(SIGFPE, current);
++	schedule();
++}
++#endif /* CONFIG_MATH_EMULATION */
++
++dotraplinkage void __kprobes
++do_device_not_available(struct pt_regs *regs, long error)
++{
++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
++	if (read_cr0() & X86_CR0_EM) {
++		conditional_sti(regs);
++		math_emulate(0);
++	} else {
++		math_state_restore(); /* interrupts still off */
++		conditional_sti(regs);
++	}
++#else
++	math_state_restore();
++#endif
++}
++
++#ifdef CONFIG_X86_32
++dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
++{
++	siginfo_t info;
++	local_irq_enable();
++
++	info.si_signo = SIGILL;
++	info.si_errno = 0;
++	info.si_code = ILL_BADSTK;
++	info.si_addr = 0;
++	if (notify_die(DIE_TRAP, "iret exception",
++			regs, error_code, 32, SIGILL) == NOTIFY_STOP)
++		return;
++	do_trap(32, SIGILL, "iret exception", regs, error_code, &info);
++}
++#endif
++
++/*
++ * 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 const trap_info_t __cpuinitconst trap_table[] = {
++#ifdef CONFIG_X86_32
++#define X 0
++#else
++#define X 4
++#endif
++	{  0, 0|X, __KERNEL_CS, (unsigned long)divide_error		},
++	{  1, 0|4, __KERNEL_CS, (unsigned long)debug			},
++	{  3, 3|4, __KERNEL_CS, (unsigned long)int3			},
++	{  4, 3|X, __KERNEL_CS, (unsigned long)overflow			},
++	{  5, 0|X, __KERNEL_CS, (unsigned long)bounds			},
++	{  6, 0|X, __KERNEL_CS, (unsigned long)invalid_op		},
++	{  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available	},
++	{  9, 0|X, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
++	{ 10, 0|X, __KERNEL_CS, (unsigned long)invalid_TSS		},
++	{ 11, 0|X, __KERNEL_CS, (unsigned long)segment_not_present	},
++	{ 12, 0|X, __KERNEL_CS, (unsigned long)stack_segment		},
++	{ 13, 0|X, __KERNEL_CS, (unsigned long)general_protection	},
++	{ 14, 0|4, __KERNEL_CS, (unsigned long)page_fault		},
++	{ 16, 0|X, __KERNEL_CS, (unsigned long)coprocessor_error	},
++	{ 17, 0|X, __KERNEL_CS, (unsigned long)alignment_check		},
++#ifdef CONFIG_X86_MCE
++	{ 18, 0|X, __KERNEL_CS, (unsigned long)machine_check		},
++#endif
++	{ 19, 0|X, __KERNEL_CS, (unsigned long)simd_coprocessor_error	},
++#ifdef CONFIG_X86_32
++	{ 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment		},
++	{ SYSCALL_VECTOR,  3, __KERNEL_CS, (unsigned long)system_call	},
++#elif defined(CONFIG_IA32_EMULATION)
++	{ IA32_SYSCALL_VECTOR, 3, __KERNEL_CS, (unsigned long)ia32_syscall },
++#endif
++	{  0, 0,	   0, 0						}
++};
++
++void __init trap_init(void)
++{
++	int ret;
++
++	ret = HYPERVISOR_set_trap_table(trap_table);
++	if (ret)
++		printk("HYPERVISOR_set_trap_table failed (%d)\n", ret);
++
++#ifdef CONFIG_X86_32
++	if (cpu_has_fxsr) {
++		printk(KERN_INFO "Enabling fast FPU save and restore... ");
++		set_in_cr4(X86_CR4_OSFXSR);
++		printk("done.\n");
++	}
++	if (cpu_has_xmm) {
++		printk(KERN_INFO
++			"Enabling unmasked SIMD FPU exception support... ");
++		set_in_cr4(X86_CR4_OSXMMEXCPT);
++		printk("done.\n");
++	}
++
++#endif
++	/*
++	 * Should be a barrier for any external CPU state:
++	 */
++	cpu_init();
++}
++
++void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
++{
++	const trap_info_t *t = trap_table;
++
++	for (t = trap_table; t->address; t++) {
++		trap_ctxt[t->vector].flags = t->flags;
++		trap_ctxt[t->vector].cs = t->cs;
++		trap_ctxt[t->vector].address = t->address;
++	}
++}
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1222 +0,0 @@
+-/*
+- *  Copyright (C) 1991, 1992  Linus Torvalds
+- *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+- *
+- *  Pentium III FXSR, SSE support
+- *	Gareth Hughes <gareth@valinux.com>, May 2000
+- */
+-
+-/*
+- * 'Traps.c' handles hardware traps and faults after we have saved some
+- * state in 'asm.s'.
+- */
+-#include <linux/interrupt.h>
+-#include <linux/kallsyms.h>
+-#include <linux/spinlock.h>
+-#include <linux/highmem.h>
+-#include <linux/kprobes.h>
+-#include <linux/uaccess.h>
+-#include <linux/utsname.h>
+-#include <linux/kdebug.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/ptrace.h>
+-#include <linux/string.h>
+-#include <linux/unwind.h>
+-#include <linux/delay.h>
+-#include <linux/errno.h>
+-#include <linux/kexec.h>
+-#include <linux/sched.h>
+-#include <linux/timer.h>
+-#include <linux/init.h>
+-#include <linux/bug.h>
+-#include <linux/nmi.h>
+-#include <linux/mm.h>
+-
+-#ifdef CONFIG_EISA
+-#include <linux/ioport.h>
+-#include <linux/eisa.h>
+-#endif
+-
+-#ifdef CONFIG_MCA
+-#include <linux/mca.h>
+-#endif
+-
+-#if defined(CONFIG_EDAC)
+-#include <linux/edac.h>
+-#endif
+-
+-#include <asm/arch_hooks.h>
+-#include <asm/stacktrace.h>
+-#include <asm/processor.h>
+-#include <asm/debugreg.h>
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <asm/unwind.h>
+-#include <asm/desc.h>
+-#include <asm/i387.h>
+-#include <asm/nmi.h>
+-#include <asm/smp.h>
+-#include <asm/io.h>
+-#include <asm/traps.h>
+-
+-#include "mach_traps.h"
+-
+-#ifndef CONFIG_XEN
+-DECLARE_BITMAP(used_vectors, NR_VECTORS);
+-EXPORT_SYMBOL_GPL(used_vectors);
+-#endif
+-
+-asmlinkage int system_call(void);
+-
+-/* Do we ignore FPU interrupts ? */
+-char ignore_fpu_irq;
+-
+-#ifndef CONFIG_X86_NO_IDT
+-/*
+- * The IDT has to be page-aligned to simplify the Pentium
+- * F0 0F bug workaround.. We have a special link segment
+- * for this.
+- */
+-gate_desc idt_table[256]
+-	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
+-#endif
+-
+-int panic_on_unrecovered_nmi;
+-int kstack_depth_to_print = 24;
+-static unsigned int code_bytes = 64;
+-static int ignore_nmis;
+-static int die_counter;
+-
+-void printk_address(unsigned long address, int reliable)
+-{
+-#ifdef CONFIG_KALLSYMS
+-	unsigned long offset = 0;
+-	unsigned long symsize;
+-	const char *symname;
+-	char *modname;
+-	char *delim = ":";
+-	char namebuf[KSYM_NAME_LEN];
+-	char reliab[4] = "";
+-
+-	symname = kallsyms_lookup(address, &symsize, &offset,
+-					&modname, namebuf);
+-	if (!symname) {
+-		printk(" [<%08lx>]\n", address);
+-		return;
+-	}
+-	if (!reliable)
+-		strcpy(reliab, "? ");
+-
+-	if (!modname)
+-		modname = delim = "";
+-	printk(" [<%08lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
+-		address, reliab, delim, modname, delim, symname, offset, symsize);
+-#else
+-	printk(" [<%08lx>]\n", address);
+-#endif
+-}
+-
+-static inline int valid_stack_ptr(struct thread_info *tinfo,
+-			void *p, unsigned int size)
+-{
+-	void *t = tinfo;
+-	return	p > t && p <= t + THREAD_SIZE - size;
+-}
+-
+-/* The form of the top of the frame on the stack */
+-struct stack_frame {
+-	struct stack_frame *next_frame;
+-	unsigned long return_address;
+-};
+-
+-static inline unsigned long
+-print_context_stack(struct thread_info *tinfo,
+-		unsigned long *stack, unsigned long bp,
+-		const struct stacktrace_ops *ops, void *data)
+-{
+-	struct stack_frame *frame = (struct stack_frame *)bp;
+-
+-	while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) {
+-		unsigned long addr;
+-
+-		addr = *stack;
+-		if (__kernel_text_address(addr)) {
+-			if ((unsigned long) stack == bp + 4) {
+-				ops->address(data, addr, 1);
+-				frame = frame->next_frame;
+-				bp = (unsigned long) frame;
+-			} else {
+-				ops->address(data, addr, bp == 0);
+-			}
+-		}
+-		stack++;
+-	}
+-	return bp;
+-}
+-
+-void dump_trace(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp,
+-		const struct stacktrace_ops *ops, void *data)
+-{
+-	if (!task)
+-		task = current;
+-
+-	if (!stack) {
+-		unsigned long dummy;
+-		stack = &dummy;
+-		if (task != current)
+-			stack = (unsigned long *)task->thread.sp;
+-	}
+-
+-#ifdef CONFIG_FRAME_POINTER
+-	if (!bp) {
+-		if (task == current) {
+-			/* Grab bp right from our regs */
+-			asm("movl %%ebp, %0" : "=r" (bp) :);
+-		} else {
+-			/* bp is the last reg pushed by switch_to */
+-			bp = *(unsigned long *) task->thread.sp;
+-		}
+-	}
+-#endif
+-
+-	for (;;) {
+-		struct thread_info *context;
+-
+-		context = (struct thread_info *)
+-			((unsigned long)stack & (~(THREAD_SIZE - 1)));
+-		bp = print_context_stack(context, stack, bp, ops, data);
+-		/*
+-		 * Should be after the line below, but somewhere
+-		 * in early boot context comes out corrupted and we
+-		 * can't reference it:
+-		 */
+-		if (ops->stack(data, "IRQ") < 0)
+-			break;
+-		stack = (unsigned long *)context->previous_esp;
+-		if (!stack)
+-			break;
+-		touch_nmi_watchdog();
+-	}
+-}
+-EXPORT_SYMBOL(dump_trace);
+-
+-static void
+-print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+-{
+-	printk(data);
+-	print_symbol(msg, symbol);
+-	printk("\n");
+-}
+-
+-static void print_trace_warning(void *data, char *msg)
+-{
+-	printk("%s%s\n", (char *)data, msg);
+-}
+-
+-static int print_trace_stack(void *data, char *name)
+-{
+-	return 0;
+-}
+-
+-/*
+- * Print one address/symbol entries per line.
+- */
+-static void print_trace_address(void *data, unsigned long addr, int reliable)
+-{
+-	printk("%s [<%08lx>] ", (char *)data, addr);
+-	if (!reliable)
+-		printk("? ");
+-	print_symbol("%s\n", addr);
+-	touch_nmi_watchdog();
+-}
+-
+-static const struct stacktrace_ops print_trace_ops = {
+-	.warning = print_trace_warning,
+-	.warning_symbol = print_trace_warning_symbol,
+-	.stack = print_trace_stack,
+-	.address = print_trace_address,
+-};
+-
+-static void
+-show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp, char *log_lvl)
+-{
+-	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+-	printk("%s =======================\n", log_lvl);
+-}
+-
+-void show_trace(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp)
+-{
+-	show_trace_log_lvl(task, regs, stack, bp, "");
+-}
+-
+-static void
+-show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		   unsigned long *sp, unsigned long bp, char *log_lvl)
+-{
+-	unsigned long *stack;
+-	int i;
+-
+-	if (sp == NULL) {
+-		if (task)
+-			sp = (unsigned long *)task->thread.sp;
+-		else
+-			sp = (unsigned long *)&sp;
+-	}
+-
+-	stack = sp;
+-	for (i = 0; i < kstack_depth_to_print; i++) {
+-		if (kstack_end(stack))
+-			break;
+-		if (i && ((i % 8) == 0))
+-			printk("\n%s       ", log_lvl);
+-		printk("%08lx ", *stack++);
+-	}
+-	printk("\n%sCall Trace:\n", log_lvl);
+-
+-	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+-}
+-
+-void show_stack(struct task_struct *task, unsigned long *sp)
+-{
+-	printk("       ");
+-	show_stack_log_lvl(task, NULL, sp, 0, "");
+-}
+-
+-/*
+- * The architecture-independent dump_stack generator
+- */
+-void dump_stack(void)
+-{
+-	unsigned long bp = 0;
+-	unsigned long stack;
+-
+-#ifdef CONFIG_FRAME_POINTER
+-	if (!bp)
+-		asm("movl %%ebp, %0" : "=r" (bp):);
+-#endif
+-
+-	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+-		current->pid, current->comm, print_tainted(),
+-		init_utsname()->release,
+-		(int)strcspn(init_utsname()->version, " "),
+-		init_utsname()->version);
+-
+-	show_trace(current, NULL, &stack, bp);
+-}
+-
+-EXPORT_SYMBOL(dump_stack);
+-
+-void show_registers(struct pt_regs *regs)
+-{
+-	int i;
+-
+-	print_modules();
+-	__show_registers(regs, 0);
+-
+-	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+-		TASK_COMM_LEN, current->comm, task_pid_nr(current),
+-		current_thread_info(), current, task_thread_info(current));
+-	/*
+-	 * When in-kernel, we also print out the stack and code at the
+-	 * time of the fault..
+-	 */
+-	if (!user_mode_vm(regs)) {
+-		unsigned int code_prologue = code_bytes * 43 / 64;
+-		unsigned int code_len = code_bytes;
+-		unsigned char c;
+-		u8 *ip;
+-
+-		printk("\n" KERN_EMERG "Stack: ");
+-		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
+-
+-		printk(KERN_EMERG "Code: ");
+-
+-		ip = (u8 *)regs->ip - code_prologue;
+-		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+-			/* try starting at EIP */
+-			ip = (u8 *)regs->ip;
+-			code_len = code_len - code_prologue + 1;
+-		}
+-		for (i = 0; i < code_len; i++, ip++) {
+-			if (ip < (u8 *)PAGE_OFFSET ||
+-					probe_kernel_address(ip, c)) {
+-				printk(" Bad EIP value.");
+-				break;
+-			}
+-			if (ip == (u8 *)regs->ip)
+-				printk("<%02x> ", c);
+-			else
+-				printk("%02x ", c);
+-		}
+-	}
+-	printk("\n");
+-}
+-
+-int is_valid_bugaddr(unsigned long ip)
+-{
+-	unsigned short ud2;
+-
+-	if (ip < PAGE_OFFSET)
+-		return 0;
+-	if (probe_kernel_address((unsigned short *)ip, ud2))
+-		return 0;
+-
+-	return ud2 == 0x0b0f;
+-}
+-
+-static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+-static int die_owner = -1;
+-static unsigned int die_nest_count;
+-
+-unsigned __kprobes long oops_begin(void)
+-{
+-	unsigned long flags;
+-
+-	oops_enter();
+-
+-	if (die_owner != raw_smp_processor_id()) {
+-		console_verbose();
+-		raw_local_irq_save(flags);
+-		__raw_spin_lock(&die_lock);
+-		die_owner = smp_processor_id();
+-		die_nest_count = 0;
+-		bust_spinlocks(1);
+-	} else {
+-		raw_local_irq_save(flags);
+-	}
+-	die_nest_count++;
+-	return flags;
+-}
+-
+-void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+-{
+-	bust_spinlocks(0);
+-	die_owner = -1;
+-	add_taint(TAINT_DIE);
+-	__raw_spin_unlock(&die_lock);
+-	raw_local_irq_restore(flags);
+-
+-	if (!regs)
+-		return;
+-
+-	if (kexec_should_crash(current))
+-		crash_kexec(regs);
+-
+-	if (in_interrupt())
+-		panic("Fatal exception in interrupt");
+-
+-	if (panic_on_oops)
+-		panic("Fatal exception");
+-
+-	oops_exit();
+-	do_exit(signr);
+-}
+-
+-int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+-{
+-	unsigned short ss;
+-	unsigned long sp;
+-
+-	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+-#ifdef CONFIG_PREEMPT
+-	printk("PREEMPT ");
+-#endif
+-#ifdef CONFIG_SMP
+-	printk("SMP ");
+-#endif
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	printk("DEBUG_PAGEALLOC");
+-#endif
+-	printk("\n");
+-	if (notify_die(DIE_OOPS, str, regs, err,
+-			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+-		return 1;
+-
+-	show_registers(regs);
+-	/* Executive summary in case the oops scrolled away */
+-	sp = (unsigned long) (&regs->sp);
+-	savesegment(ss, ss);
+-	if (user_mode(regs)) {
+-		sp = regs->sp;
+-		ss = regs->ss & 0xffff;
+-	}
+-	printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
+-	print_symbol("%s", regs->ip);
+-	printk(" SS:ESP %04x:%08lx\n", ss, sp);
+-	return 0;
+-}
+-
+-/*
+- * This is gone through when something in the kernel has done something bad
+- * and is about to be terminated:
+- */
+-void die(const char *str, struct pt_regs *regs, long err)
+-{
+-	unsigned long flags = oops_begin();
+-
+-	if (die_nest_count < 3) {
+-		report_bug(regs->ip, regs);
+-
+-		if (__die(str, regs, err))
+-			regs = NULL;
+-	} else {
+-		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
+-	}
+-
+-	oops_end(flags, regs, SIGSEGV);
+-}
+-
+-static inline void
+-die_if_kernel(const char *str, struct pt_regs *regs, long err)
+-{
+-	if (!user_mode_vm(regs))
+-		die(str, regs, err);
+-}
+-
+-static void __kprobes
+-do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs,
+-	long error_code, siginfo_t *info)
+-{
+-	struct task_struct *tsk = current;
+-
+-	if (regs->flags & X86_VM_MASK) {
+-		if (vm86)
+-			goto vm86_trap;
+-		goto trap_signal;
+-	}
+-
+-	if (!user_mode(regs))
+-		goto kernel_trap;
+-
+-trap_signal:
+-	/*
+-	 * We want error_code and trap_no set for userspace faults and
+-	 * kernelspace faults which result in die(), but not
+-	 * kernelspace faults which are fixed up.  die() gives the
+-	 * process no chance to handle the signal and notice the
+-	 * kernel fault information, so that won't result in polluting
+-	 * the information about previously queued, but not yet
+-	 * delivered, faults.  See also do_general_protection below.
+-	 */
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = trapnr;
+-
+-	if (info)
+-		force_sig_info(signr, info, tsk);
+-	else
+-		force_sig(signr, tsk);
+-	return;
+-
+-kernel_trap:
+-	if (!fixup_exception(regs)) {
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = trapnr;
+-		die(str, regs, error_code);
+-	}
+-	return;
+-
+-vm86_trap:
+-	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
+-						error_code, trapnr))
+-		goto trap_signal;
+-	return;
+-}
+-
+-#define DO_ERROR(trapnr, signr, str, name)				\
+-void do_##name(struct pt_regs *regs, long error_code)			\
+-{									\
+-	trace_hardirqs_fixup();						\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	do_trap(trapnr, signr, str, 0, regs, error_code, NULL);		\
+-}
+-
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq)	\
+-void do_##name(struct pt_regs *regs, long error_code)			\
+-{									\
+-	siginfo_t info;							\
+-	if (irq)							\
+-		local_irq_enable();					\
+-	info.si_signo = signr;						\
+-	info.si_errno = 0;						\
+-	info.si_code = sicode;						\
+-	info.si_addr = (void __user *)siaddr;				\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	do_trap(trapnr, signr, str, 0, regs, error_code, &info);	\
+-}
+-
+-#define DO_VM86_ERROR(trapnr, signr, str, name)				\
+-void do_##name(struct pt_regs *regs, long error_code)			\
+-{									\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	do_trap(trapnr, signr, str, 1, regs, error_code, NULL);		\
+-}
+-
+-#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)	\
+-void do_##name(struct pt_regs *regs, long error_code)			\
+-{									\
+-	siginfo_t info;							\
+-	info.si_signo = signr;						\
+-	info.si_errno = 0;						\
+-	info.si_code = sicode;						\
+-	info.si_addr = (void __user *)siaddr;				\
+-	trace_hardirqs_fixup();						\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	do_trap(trapnr, signr, str, 1, regs, error_code, &info);	\
+-}
+-
+-DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+-#ifndef CONFIG_KPROBES
+-DO_VM86_ERROR(3, SIGTRAP, "int3", int3)
+-#endif
+-DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow)
+-DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0)
+-DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+-DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+-DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0)
+-DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+-
+-void __kprobes
+-do_general_protection(struct pt_regs *regs, long error_code)
+-{
+-	struct task_struct *tsk;
+-	struct thread_struct *thread;
+-
+-	thread = &current->thread;
+-
+-	if (regs->flags & X86_VM_MASK)
+-		goto gp_in_vm86;
+-
+-	tsk = current;
+-	if (!user_mode(regs))
+-		goto gp_in_kernel;
+-
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 13;
+-
+-	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-			printk_ratelimit()) {
+-		printk(KERN_INFO
+-			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
+-			tsk->comm, task_pid_nr(tsk),
+-			regs->ip, regs->sp, error_code);
+-		print_vma_addr(" in ", regs->ip);
+-		printk("\n");
+-	}
+-
+-	force_sig(SIGSEGV, tsk);
+-	return;
+-
+-gp_in_vm86:
+-	local_irq_enable();
+-	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+-	return;
+-
+-gp_in_kernel:
+-	if (fixup_exception(regs))
+-		return;
+-
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 13;
+-	if (notify_die(DIE_GPF, "general protection fault", regs,
+-				error_code, 13, SIGSEGV) == NOTIFY_STOP)
+-		return;
+-	die("general protection fault", regs, error_code);
+-}
+-
+-static notrace __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs *regs)
+-{
+-	printk(KERN_EMERG
+-		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+-			reason, smp_processor_id());
+-
+-	printk(KERN_EMERG
+-		"You have some hardware problem, likely on the PCI bus.\n");
+-
+-#if defined(CONFIG_EDAC)
+-	if (edac_handler_set()) {
+-		edac_atomic_assert_error();
+-		return;
+-	}
+-#endif
+-
+-	if (panic_on_unrecovered_nmi)
+-		panic("NMI: Not continuing");
+-
+-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+-
+-	/* Clear and disable the memory parity error line. */
+-	clear_mem_error(reason);
+-}
+-
+-static notrace __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs *regs)
+-{
+-	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+-	show_registers(regs);
+-
+-	/* Re-enable the IOCK line, wait for a few seconds */
+-	clear_io_check_error(reason);
+-}
+-
+-static notrace __kprobes void
+-unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+-{
+-	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-#ifdef CONFIG_MCA
+-	/*
+-	 * Might actually be able to figure out what the guilty party
+-	 * is:
+-	 */
+-	if (MCA_bus) {
+-		mca_handle_nmi();
+-		return;
+-	}
+-#endif
+-	printk(KERN_EMERG
+-		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+-			reason, smp_processor_id());
+-
+-	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+-	if (panic_on_unrecovered_nmi)
+-		panic("NMI: Not continuing");
+-
+-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+-}
+-
+-static DEFINE_SPINLOCK(nmi_print_lock);
+-
+-void notrace __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
+-{
+-	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-
+-	spin_lock(&nmi_print_lock);
+-	/*
+-	* We are in trouble anyway, lets at least try
+-	* to get a message out:
+-	*/
+-	bust_spinlocks(1);
+-	printk(KERN_EMERG "%s", str);
+-	printk(" on CPU%d, ip %08lx, registers:\n",
+-		smp_processor_id(), regs->ip);
+-	show_registers(regs);
+-	if (do_panic)
+-		panic("Non maskable interrupt");
+-	console_silent();
+-	spin_unlock(&nmi_print_lock);
+-	bust_spinlocks(0);
+-
+-	/*
+-	 * If we are in kernel we are probably nested up pretty bad
+-	 * and might aswell get out now while we still can:
+-	 */
+-	if (!user_mode_vm(regs)) {
+-		current->thread.trap_no = 2;
+-		crash_kexec(regs);
+-	}
+-
+-	do_exit(SIGSEGV);
+-}
+-
+-static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+-{
+-	unsigned char reason = 0;
+-	int cpu;
+-
+-	cpu = smp_processor_id();
+-
+-	/* Only the BSP gets external NMIs from the system. */
+-	if (!cpu)
+-		reason = get_nmi_reason();
+-
+-	if (!(reason & 0xc0)) {
+-		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+-								== NOTIFY_STOP)
+-			return;
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		/*
+-		 * Ok, so this is none of the documented NMI sources,
+-		 * so it must be the NMI watchdog.
+-		 */
+-		if (nmi_watchdog_tick(regs, reason))
+-			return;
+-		if (!do_nmi_callback(regs, cpu))
+-			unknown_nmi_error(reason, regs);
+-#else
+-		unknown_nmi_error(reason, regs);
+-#endif
+-
+-		return;
+-	}
+-	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-
+-	/* AK: following checks seem to be broken on modern chipsets. FIXME */
+-	if (reason & 0x80)
+-		mem_parity_error(reason, regs);
+-	if (reason & 0x40)
+-		io_check_error(reason, regs);
+-	/*
+-	 * Reassert NMI in case it became active meanwhile
+-	 * as it's edge-triggered:
+-	 */
+-	reassert_nmi();
+-}
+-
+-notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code)
+-{
+-	int cpu;
+-
+-	nmi_enter();
+-
+-	cpu = smp_processor_id();
+-
+-	++nmi_count(cpu);
+-
+-	if (!ignore_nmis)
+-		default_do_nmi(regs);
+-
+-	nmi_exit();
+-}
+-
+-void stop_nmi(void)
+-{
+-	acpi_nmi_disable();
+-	ignore_nmis++;
+-}
+-
+-void restart_nmi(void)
+-{
+-	ignore_nmis--;
+-	acpi_nmi_enable();
+-}
+-
+-#ifdef CONFIG_KPROBES
+-void __kprobes do_int3(struct pt_regs *regs, long error_code)
+-{
+-	trace_hardirqs_fixup();
+-
+-	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+-			== NOTIFY_STOP)
+-		return;
+-	/*
+-	 * This is an interrupt gate, because kprobes wants interrupts
+-	 * disabled. Normal trap handlers don't.
+-	 */
+-	restore_interrupts(regs);
+-
+-	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+-}
+-#endif
+-
+-/*
+- * Our handling of the processor debug registers is non-trivial.
+- * We do not clear them on entry and exit from the kernel. Therefore
+- * it is possible to get a watchpoint trap here from inside the kernel.
+- * However, the code in ./ptrace.c has ensured that the user can
+- * only set watchpoints on userspace addresses. Therefore the in-kernel
+- * watchpoint trap can only occur in code which is reading/writing
+- * from user space. Such code must not hold kernel locks (since it
+- * can equally take a page fault), therefore it is safe to call
+- * force_sig_info even though that claims and releases locks.
+- *
+- * Code in ./signal.c ensures that the debug control register
+- * is restored before we deliver any signal, and therefore that
+- * user code runs with the correct debug control register even though
+- * we clear it here.
+- *
+- * Being careful here means that we don't have to be as careful in a
+- * lot of more complicated places (task switching can be a bit lazy
+- * about restoring all the debug state, and ptrace doesn't have to
+- * find every occurrence of the TF bit that could be saved away even
+- * by user code)
+- */
+-void __kprobes do_debug(struct pt_regs *regs, long error_code)
+-{
+-	struct task_struct *tsk = current;
+-	unsigned int condition;
+-
+-	trace_hardirqs_fixup();
+-
+-	get_debugreg(condition, 6);
+-
+-	/*
+-	 * The processor cleared BTF, so don't mark that we need it set.
+-	 */
+-	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
+-	tsk->thread.debugctlmsr = 0;
+-
+-	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+-						SIGTRAP) == NOTIFY_STOP)
+-		return;
+-	/* It's safe to allow irq's after DR6 has been saved */
+-	if (regs->flags & X86_EFLAGS_IF)
+-		local_irq_enable();
+-
+-	/* Mask out spurious debug traps due to lazy DR7 setting */
+-	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+-		if (!tsk->thread.debugreg7)
+-			goto clear_dr7;
+-	}
+-
+-	if (regs->flags & X86_VM_MASK)
+-		goto debug_vm86;
+-
+-	/* Save debug status register where ptrace can see it */
+-	tsk->thread.debugreg6 = condition;
+-
+-	/*
+-	 * Single-stepping through TF: make sure we ignore any events in
+-	 * kernel space (but re-enable TF when returning to user mode).
+-	 */
+-	if (condition & DR_STEP) {
+-		/*
+-		 * We already checked v86 mode above, so we can
+-		 * check for kernel mode by just checking the CPL
+-		 * of CS.
+-		 */
+-		if (!user_mode(regs))
+-			goto clear_TF_reenable;
+-	}
+-
+-	/* Ok, finally something we can handle */
+-	send_sigtrap(tsk, regs, error_code);
+-
+-	/*
+-	 * Disable additional traps. They'll be re-enabled when
+-	 * the signal is delivered.
+-	 */
+-clear_dr7:
+-	set_debugreg(0, 7);
+-	return;
+-
+-debug_vm86:
+-	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+-	return;
+-
+-clear_TF_reenable:
+-	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->flags &= ~X86_EFLAGS_TF;
+-	return;
+-}
+-
+-/*
+- * Note that we play around with the 'TS' bit in an attempt to get
+- * the correct behaviour even in the presence of the asynchronous
+- * IRQ13 behaviour
+- */
+-void math_error(void __user *ip)
+-{
+-	struct task_struct *task;
+-	siginfo_t info;
+-	unsigned short cwd, swd;
+-
+-	/*
+-	 * Save the info for the exception handler and clear the error.
+-	 */
+-	task = current;
+-	save_init_fpu(task);
+-	task->thread.trap_no = 16;
+-	task->thread.error_code = 0;
+-	info.si_signo = SIGFPE;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT;
+-	info.si_addr = ip;
+-	/*
+-	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+-	 * status.  0x3f is the exception bits in these regs, 0x200 is the
+-	 * C1 reg you need in case of a stack fault, 0x040 is the stack
+-	 * fault bit.  We should only be taking one exception at a time,
+-	 * so if this combination doesn't produce any single exception,
+-	 * then we have a bad program that isn't synchronizing its FPU usage
+-	 * and it will suffer the consequences since we won't be able to
+-	 * fully reproduce the context of the exception
+-	 */
+-	cwd = get_fpu_cwd(task);
+-	swd = get_fpu_swd(task);
+-	switch (swd & ~cwd & 0x3f) {
+-	case 0x000: /* No unmasked exception */
+-		return;
+-	default: /* Multiple exceptions */
+-		break;
+-	case 0x001: /* Invalid Op */
+-		/*
+-		 * swd & 0x240 == 0x040: Stack Underflow
+-		 * swd & 0x240 == 0x240: Stack Overflow
+-		 * User must clear the SF bit (0x40) if set
+-		 */
+-		info.si_code = FPE_FLTINV;
+-		break;
+-	case 0x002: /* Denormalize */
+-	case 0x010: /* Underflow */
+-		info.si_code = FPE_FLTUND;
+-		break;
+-	case 0x004: /* Zero Divide */
+-		info.si_code = FPE_FLTDIV;
+-		break;
+-	case 0x008: /* Overflow */
+-		info.si_code = FPE_FLTOVF;
+-		break;
+-	case 0x020: /* Precision */
+-		info.si_code = FPE_FLTRES;
+-		break;
+-	}
+-	force_sig_info(SIGFPE, &info, task);
+-}
+-
+-void do_coprocessor_error(struct pt_regs *regs, long error_code)
+-{
+-	ignore_fpu_irq = 1;
+-	math_error((void __user *)regs->ip);
+-}
+-
+-static void simd_math_error(void __user *ip)
+-{
+-	struct task_struct *task;
+-	siginfo_t info;
+-	unsigned short mxcsr;
+-
+-	/*
+-	 * Save the info for the exception handler and clear the error.
+-	 */
+-	task = current;
+-	save_init_fpu(task);
+-	task->thread.trap_no = 19;
+-	task->thread.error_code = 0;
+-	info.si_signo = SIGFPE;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT;
+-	info.si_addr = ip;
+-	/*
+-	 * The SIMD FPU exceptions are handled a little differently, as there
+-	 * is only a single status/control register.  Thus, to determine which
+-	 * unmasked exception was caught we must mask the exception mask bits
+-	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+-	 */
+-	mxcsr = get_fpu_mxcsr(task);
+-	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+-	case 0x000:
+-	default:
+-		break;
+-	case 0x001: /* Invalid Op */
+-		info.si_code = FPE_FLTINV;
+-		break;
+-	case 0x002: /* Denormalize */
+-	case 0x010: /* Underflow */
+-		info.si_code = FPE_FLTUND;
+-		break;
+-	case 0x004: /* Zero Divide */
+-		info.si_code = FPE_FLTDIV;
+-		break;
+-	case 0x008: /* Overflow */
+-		info.si_code = FPE_FLTOVF;
+-		break;
+-	case 0x020: /* Precision */
+-		info.si_code = FPE_FLTRES;
+-		break;
+-	}
+-	force_sig_info(SIGFPE, &info, task);
+-}
+-
+-void do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+-{
+-	if (cpu_has_xmm) {
+-		/* Handle SIMD FPU exceptions on PIII+ processors. */
+-		ignore_fpu_irq = 1;
+-		simd_math_error((void __user *)regs->ip);
+-		return;
+-	}
+-	/*
+-	 * Handle strange cache flush from user space exception
+-	 * in all other cases.  This is undocumented behaviour.
+-	 */
+-	if (regs->flags & X86_VM_MASK) {
+-		handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
+-		return;
+-	}
+-	current->thread.trap_no = 19;
+-	current->thread.error_code = error_code;
+-	die_if_kernel("cache flush denied", regs, error_code);
+-	force_sig(SIGSEGV, current);
+-}
+-
+-#ifndef CONFIG_XEN
+-void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+-{
+-#if 0
+-	/* No need to warn about this any longer. */
+-	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+-#endif
+-}
+-
+-unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp)
+-{
+-	struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id());
+-	unsigned long base = (kesp - uesp) & -THREAD_SIZE;
+-	unsigned long new_kesp = kesp - base;
+-	unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
+-	__u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
+-
+-	/* Set up base for espfix segment */
+-	desc &= 0x00f0ff0000000000ULL;
+-	desc |=	((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
+-		((((__u64)base) << 32) & 0xff00000000000000ULL) |
+-		((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
+-		(lim_pages & 0xffff);
+-	*(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
+-
+-	return new_kesp;
+-}
+-#endif
+-
+-/*
+- * 'math_state_restore()' saves the current math information in the
+- * old math state array, and gets the new ones from the current task
+- *
+- * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+- * Don't touch unless you *really* know how it works.
+- *
+- * Must be called with kernel preemption disabled (in this case,
+- * local interrupts are disabled at the call-site in entry.S).
+- */
+-asmlinkage void math_state_restore(void)
+-{
+-	struct thread_info *thread = current_thread_info();
+-	struct task_struct *tsk = thread->task;
+-
+-	if (!tsk_used_math(tsk)) {
+-		local_irq_enable();
+-		/*
+-		 * does a slab alloc which can sleep
+-		 */
+-		if (init_fpu(tsk)) {
+-			/*
+-			 * ran out of memory!
+-			 */
+-			do_group_exit(SIGKILL);
+-			return;
+-		}
+-		local_irq_disable();
+-	}
+-
+-	/* NB. 'clts' is done for us by Xen during virtual trap. */
+-	restore_fpu(tsk);
+-	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+-	tsk->fpu_counter++;
+-}
+-EXPORT_SYMBOL_GPL(math_state_restore);
+-
+-#ifndef CONFIG_MATH_EMULATION
+-
+-asmlinkage void math_emulate(long arg)
+-{
+-	printk(KERN_EMERG
+-		"math-emulation not enabled and no coprocessor found.\n");
+-	printk(KERN_EMERG "killing %s.\n", current->comm);
+-	force_sig(SIGFPE, current);
+-	schedule();
+-}
+-
+-#endif /* CONFIG_MATH_EMULATION */
+-
+-/*
+- * 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 const trap_info_t __cpuinitconst 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			},
+-	{  4, 3, __KERNEL_CS, (unsigned long)overflow			},
+-	{  5, 0, __KERNEL_CS, (unsigned long)bounds			},
+-	{  6, 0, __KERNEL_CS, (unsigned long)invalid_op			},
+-	{  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available	},
+-	{  9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+-	{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS		},
+-	{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present	},
+-	{ 12, 0, __KERNEL_CS, (unsigned long)stack_segment		},
+-	{ 13, 0, __KERNEL_CS, (unsigned long)general_protection		},
+-	{ 14, 0|4, __KERNEL_CS, (unsigned long)page_fault		},
+-	{ 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment		},
+-	{ 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error		},
+-	{ 17, 0, __KERNEL_CS, (unsigned long)alignment_check		},
+-#ifdef CONFIG_X86_MCE
+-	{ 18, 0, __KERNEL_CS, (unsigned long)machine_check		},
+-#endif
+-	{ 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error	},
+-	{ SYSCALL_VECTOR,  3, __KERNEL_CS, (unsigned long)system_call	},
+-	{  0, 0,	   0, 0						}
+-};
+-
+-void __init trap_init(void)
+-{
+-	int ret;
+-
+-	ret = HYPERVISOR_set_trap_table(trap_table);
+-	if (ret)
+-		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+-
+-	if (cpu_has_fxsr) {
+-		printk(KERN_INFO "Enabling fast FPU save and restore... ");
+-		set_in_cr4(X86_CR4_OSFXSR);
+-		printk("done.\n");
+-	}
+-	if (cpu_has_xmm) {
+-		printk(KERN_INFO
+-			"Enabling unmasked SIMD FPU exception support... ");
+-		set_in_cr4(X86_CR4_OSXMMEXCPT);
+-		printk("done.\n");
+-	}
+-
+-	init_thread_xstate();
+-	/*
+-	 * Should be a barrier for any external CPU state:
+-	 */
+-	cpu_init();
+-}
+-
+-void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+-{
+-	const trap_info_t *t = trap_table;
+-
+-	for (t = trap_table; t->address; t++) {
+-		trap_ctxt[t->vector].flags = t->flags;
+-		trap_ctxt[t->vector].cs = t->cs;
+-		trap_ctxt[t->vector].address = t->address;
+-	}
+-}
+-
+-static int __init kstack_setup(char *s)
+-{
+-	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+-
+-	return 1;
+-}
+-__setup("kstack=", kstack_setup);
+-
+-static int __init code_bytes_setup(char *s)
+-{
+-	code_bytes = simple_strtoul(s, NULL, 0);
+-	if (code_bytes > 8192)
+-		code_bytes = 8192;
+-
+-	return 1;
+-}
+-__setup("code_bytes=", code_bytes_setup);
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ /dev/null	1970-01-01 00:00:00.000000000 +0000
+@@ -1,1238 +0,0 @@
+-/*
+- *  Copyright (C) 1991, 1992  Linus Torvalds
+- *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+- *
+- *  Pentium III FXSR, SSE support
+- *	Gareth Hughes <gareth@valinux.com>, May 2000
+- */
+-
+-/*
+- * 'Traps.c' handles hardware traps and faults after we have saved some
+- * state in 'entry.S'.
+- */
+-#include <linux/moduleparam.h>
+-#include <linux/interrupt.h>
+-#include <linux/kallsyms.h>
+-#include <linux/spinlock.h>
+-#include <linux/kprobes.h>
+-#include <linux/uaccess.h>
+-#include <linux/utsname.h>
+-#include <linux/kdebug.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/ptrace.h>
+-#include <linux/string.h>
+-#include <linux/unwind.h>
+-#include <linux/delay.h>
+-#include <linux/errno.h>
+-#include <linux/kexec.h>
+-#include <linux/sched.h>
+-#include <linux/timer.h>
+-#include <linux/init.h>
+-#include <linux/bug.h>
+-#include <linux/nmi.h>
+-#include <linux/mm.h>
+-
+-#if defined(CONFIG_EDAC)
+-#include <linux/edac.h>
+-#endif
+-
+-#include <asm/stacktrace.h>
+-#include <asm/processor.h>
+-#include <asm/debugreg.h>
+-#include <asm/atomic.h>
+-#include <asm/system.h>
+-#include <asm/unwind.h>
+-#include <asm/desc.h>
+-#include <asm/i387.h>
+-#include <asm/nmi.h>
+-#include <asm/smp.h>
+-#include <asm/io.h>
+-#include <asm/pgalloc.h>
+-#include <asm/proto.h>
+-#include <asm/pda.h>
+-#include <asm/traps.h>
+-
+-#include <mach_traps.h>
+-
+-int panic_on_unrecovered_nmi;
+-int kstack_depth_to_print = 12;
+-static unsigned int code_bytes = 64;
+-static int ignore_nmis;
+-static int die_counter;
+-
+-static inline void conditional_sti(struct pt_regs *regs)
+-{
+-	if (regs->flags & X86_EFLAGS_IF)
+-		local_irq_enable();
+-}
+-
+-static inline void preempt_conditional_sti(struct pt_regs *regs)
+-{
+-	inc_preempt_count();
+-	if (regs->flags & X86_EFLAGS_IF)
+-		local_irq_enable();
+-}
+-
+-static inline void preempt_conditional_cli(struct pt_regs *regs)
+-{
+-	if (regs->flags & X86_EFLAGS_IF)
+-		local_irq_disable();
+-	/* Make sure to not schedule here because we could be running
+-	   on an exception stack. */
+-	dec_preempt_count();
+-}
+-
+-void printk_address(unsigned long address, int reliable)
+-{
+-	printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address);
+-}
+-
+-static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+-					unsigned *usedp, char **idp)
+-{
+-#ifndef CONFIG_X86_NO_TSS
+-	static char ids[][8] = {
+-		[DEBUG_STACK - 1] = "#DB",
+-		[NMI_STACK - 1] = "NMI",
+-		[DOUBLEFAULT_STACK - 1] = "#DF",
+-		[STACKFAULT_STACK - 1] = "#SS",
+-		[MCE_STACK - 1] = "#MC",
+-#if DEBUG_STKSZ > EXCEPTION_STKSZ
+-		[N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
+-#endif
+-	};
+-	unsigned k;
+-
+-	/*
+-	 * Iterate over all exception stacks, and figure out whether
+-	 * 'stack' is in one of them:
+-	 */
+-	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
+-		unsigned long end = per_cpu(orig_ist, cpu).ist[k];
+-		/*
+-		 * Is 'stack' above this exception frame's end?
+-		 * If yes then skip to the next frame.
+-		 */
+-		if (stack >= end)
+-			continue;
+-		/*
+-		 * Is 'stack' above this exception frame's start address?
+-		 * If yes then we found the right frame.
+-		 */
+-		if (stack >= end - EXCEPTION_STKSZ) {
+-			/*
+-			 * Make sure we only iterate through an exception
+-			 * stack once. If it comes up for the second time
+-			 * then there's something wrong going on - just
+-			 * break out and return NULL:
+-			 */
+-			if (*usedp & (1U << k))
+-				break;
+-			*usedp |= 1U << k;
+-			*idp = ids[k];
+-			return (unsigned long *)end;
+-		}
+-		/*
+-		 * If this is a debug stack, and if it has a larger size than
+-		 * the usual exception stacks, then 'stack' might still
+-		 * be within the lower portion of the debug stack:
+-		 */
+-#if DEBUG_STKSZ > EXCEPTION_STKSZ
+-		if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
+-			unsigned j = N_EXCEPTION_STACKS - 1;
+-
+-			/*
+-			 * Black magic. A large debug stack is composed of
+-			 * multiple exception stack entries, which we
+-			 * iterate through now. Dont look:
+-			 */
+-			do {
+-				++j;
+-				end -= EXCEPTION_STKSZ;
+-				ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
+-			} while (stack < end - EXCEPTION_STKSZ);
+-			if (*usedp & (1U << j))
+-				break;
+-			*usedp |= 1U << j;
+-			*idp = ids[j];
+-			return (unsigned long *)end;
+-		}
+-#endif
+-	}
+-#endif
+-	return NULL;
+-}
+-
+-/*
+- * x86-64 can have up to three kernel stacks:
+- * process stack
+- * interrupt stack
+- * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+- */
+-
+-static inline int valid_stack_ptr(struct thread_info *tinfo,
+-			void *p, unsigned int size, void *end)
+-{
+-	void *t = tinfo;
+-	if (end) {
+-		if (p < end && p >= (end-THREAD_SIZE))
+-			return 1;
+-		else
+-			return 0;
+-	}
+-	return p > t && p < t + THREAD_SIZE - size;
+-}
+-
+-/* The form of the top of the frame on the stack */
+-struct stack_frame {
+-	struct stack_frame *next_frame;
+-	unsigned long return_address;
+-};
+-
+-static inline unsigned long
+-print_context_stack(struct thread_info *tinfo,
+-		unsigned long *stack, unsigned long bp,
+-		const struct stacktrace_ops *ops, void *data,
+-		unsigned long *end)
+-{
+-	struct stack_frame *frame = (struct stack_frame *)bp;
+-
+-	while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
+-		unsigned long addr;
+-
+-		addr = *stack;
+-		if (__kernel_text_address(addr)) {
+-			if ((unsigned long) stack == bp + 8) {
+-				ops->address(data, addr, 1);
+-				frame = frame->next_frame;
+-				bp = (unsigned long) frame;
+-			} else {
+-				ops->address(data, addr, bp == 0);
+-			}
+-		}
+-		stack++;
+-	}
+-	return bp;
+-}
+-
+-void dump_trace(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp,
+-		const struct stacktrace_ops *ops, void *data)
+-{
+-	const unsigned cpu = get_cpu();
+-	unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
+-	unsigned used = 0;
+-	struct thread_info *tinfo;
+-
+-	if (!task)
+-		task = current;
+-
+-	if (!stack) {
+-		unsigned long dummy;
+-		stack = &dummy;
+-		if (task && task != current)
+-			stack = (unsigned long *)task->thread.sp;
+-	}
+-
+-#ifdef CONFIG_FRAME_POINTER
+-	if (!bp) {
+-		if (task == current) {
+-			/* Grab bp right from our regs */
+-			asm("movq %%rbp, %0" : "=r" (bp) :);
+-		} else {
+-			/* bp is the last reg pushed by switch_to */
+-			bp = *(unsigned long *) task->thread.sp;
+-		}
+-	}
+-#endif
+-
+-	/*
+-	 * Print function call entries in all stacks, starting at the
+-	 * current stack address. If the stacks consist of nested
+-	 * exceptions
+-	 */
+-	tinfo = task_thread_info(task);
+-	for (;;) {
+-		char *id;
+-		unsigned long *estack_end;
+-		estack_end = in_exception_stack(cpu, (unsigned long)stack,
+-						&used, &id);
+-
+-		if (estack_end) {
+-			if (ops->stack(data, id) < 0)
+-				break;
+-
+-			bp = print_context_stack(tinfo, stack, bp, ops,
+-							data, estack_end);
+-			ops->stack(data, "<EOE>");
+-			/*
+-			 * We link to the next stack via the
+-			 * second-to-last pointer (index -2 to end) in the
+-			 * exception stack:
+-			 */
+-			stack = (unsigned long *) estack_end[-2];
+-			continue;
+-		}
+-		if (irqstack_end) {
+-			unsigned long *irqstack;
+-			irqstack = irqstack_end -
+-				(IRQSTACKSIZE - 64) / sizeof(*irqstack);
+-
+-			if (stack >= irqstack && stack < irqstack_end) {
+-				if (ops->stack(data, "IRQ") < 0)
+-					break;
+-				bp = print_context_stack(tinfo, stack, bp,
+-						ops, data, irqstack_end);
+-				/*
+-				 * We link to the next stack (which would be
+-				 * the process stack normally) the last
+-				 * pointer (index -1 to end) in the IRQ stack:
+-				 */
+-				stack = (unsigned long *) (irqstack_end[-1]);
+-				irqstack_end = NULL;
+-				ops->stack(data, "EOI");
+-				continue;
+-			}
+-		}
+-		break;
+-	}
+-
+-	/*
+-	 * This handles the process stack:
+-	 */
+-	bp = print_context_stack(tinfo, stack, bp, ops, data, NULL);
+-	put_cpu();
+-}
+-EXPORT_SYMBOL(dump_trace);
+-
+-static void
+-print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+-{
+-	print_symbol(msg, symbol);
+-	printk("\n");
+-}
+-
+-static void print_trace_warning(void *data, char *msg)
+-{
+-	printk("%s\n", msg);
+-}
+-
+-static int print_trace_stack(void *data, char *name)
+-{
+-	printk(" <%s> ", name);
+-	return 0;
+-}
+-
+-static void print_trace_address(void *data, unsigned long addr, int reliable)
+-{
+-	touch_nmi_watchdog();
+-	printk_address(addr, reliable);
+-}
+-
+-static const struct stacktrace_ops print_trace_ops = {
+-	.warning = print_trace_warning,
+-	.warning_symbol = print_trace_warning_symbol,
+-	.stack = print_trace_stack,
+-	.address = print_trace_address,
+-};
+-
+-static void
+-show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp, char *log_lvl)
+-{
+-	printk("\nCall Trace:\n");
+-	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
+-	printk("\n");
+-}
+-
+-void show_trace(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *stack, unsigned long bp)
+-{
+-	show_trace_log_lvl(task, regs, stack, bp, "");
+-}
+-
+-static void
+-show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+-		unsigned long *sp, unsigned long bp, char *log_lvl)
+-{
+-	unsigned long *stack;
+-	int i;
+-	const int cpu = smp_processor_id();
+-	unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
+-	unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
+-
+-	// debugging aid: "show_stack(NULL, NULL);" prints the
+-	// back trace for this cpu.
+-
+-	if (sp == NULL) {
+-		if (task)
+-			sp = (unsigned long *)task->thread.sp;
+-		else
+-			sp = (unsigned long *)&sp;
+-	}
+-
+-	stack = sp;
+-	for (i = 0; i < kstack_depth_to_print; i++) {
+-		if (stack >= irqstack && stack <= irqstack_end) {
+-			if (stack == irqstack_end) {
+-				stack = (unsigned long *) (irqstack_end[-1]);
+-				printk(" <EOI> ");
+-			}
+-		} else {
+-		if (((long) stack & (THREAD_SIZE-1)) == 0)
+-			break;
+-		}
+-		if (i && ((i % 4) == 0))
+-			printk("\n");
+-		printk(" %016lx", *stack++);
+-		touch_nmi_watchdog();
+-	}
+-	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
+-}
+-
+-void show_stack(struct task_struct *task, unsigned long *sp)
+-{
+-	show_stack_log_lvl(task, NULL, sp, 0, "");
+-}
+-
+-/*
+- * The architecture-independent dump_stack generator
+- */
+-void dump_stack(void)
+-{
+-	unsigned long bp = 0;
+-	unsigned long stack;
+-
+-#ifdef CONFIG_FRAME_POINTER
+-	if (!bp)
+-		asm("movq %%rbp, %0" : "=r" (bp):);
+-#endif
+-
+-	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+-		current->pid, current->comm, print_tainted(),
+-		init_utsname()->release,
+-		(int)strcspn(init_utsname()->version, " "),
+-		init_utsname()->version);
+-	show_trace(NULL, NULL, &stack, bp);
+-}
+-
+-EXPORT_SYMBOL(dump_stack);
+-
+-void show_registers(struct pt_regs *regs)
+-{
+-	int i;
+-	unsigned long sp;
+-	const int cpu = smp_processor_id();
+-	struct task_struct *cur = cpu_pda(cpu)->pcurrent;
+-
+-	sp = regs->sp;
+-	printk("CPU %d ", cpu);
+-	__show_regs(regs);
+-	printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
+-		cur->comm, cur->pid, task_thread_info(cur), cur);
+-
+-	/*
+-	 * When in-kernel, we also print out the stack and code at the
+-	 * time of the fault..
+-	 */
+-	if (!user_mode(regs)) {
+-		unsigned int code_prologue = code_bytes * 43 / 64;
+-		unsigned int code_len = code_bytes;
+-		unsigned char c;
+-		u8 *ip;
+-
+-		printk("Stack: ");
+-		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
+-				regs->bp, "");
+-		printk("\n");
+-
+-		printk(KERN_EMERG "Code: ");
+-
+-		ip = (u8 *)regs->ip - code_prologue;
+-		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
+-			/* try starting at RIP */
+-			ip = (u8 *)regs->ip;
+-			code_len = code_len - code_prologue + 1;
+-		}
+-		for (i = 0; i < code_len; i++, ip++) {
+-			if (ip < (u8 *)PAGE_OFFSET ||
+-					probe_kernel_address(ip, c)) {
+-				printk(" Bad RIP value.");
+-				break;
+-			}
+-			if (ip == (u8 *)regs->ip)
+-				printk("<%02x> ", c);
+-			else
+-				printk("%02x ", c);
+-		}
+-	}
+-	printk("\n");
+-}
+-
+-int is_valid_bugaddr(unsigned long ip)
+-{
+-	unsigned short ud2;
+-
+-	if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
+-		return 0;
+-
+-	return ud2 == 0x0b0f;
+-}
+-
+-static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+-static int die_owner = -1;
+-static unsigned int die_nest_count;
+-
+-unsigned __kprobes long oops_begin(void)
+-{
+-	int cpu;
+-	unsigned long flags;
+-
+-	oops_enter();
+-
+-	/* racy, but better than risking deadlock. */
+-	raw_local_irq_save(flags);
+-	cpu = smp_processor_id();
+-	if (!__raw_spin_trylock(&die_lock)) {
+-		if (cpu == die_owner) 
+-			/* nested oops. should stop eventually */;
+-		else
+-			__raw_spin_lock(&die_lock);
+-	}
+-	die_nest_count++;
+-	die_owner = cpu;
+-	console_verbose();
+-	bust_spinlocks(1);
+-	return flags;
+-}
+-
+-void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+-{
+-	die_owner = -1;
+-	bust_spinlocks(0);
+-	die_nest_count--;
+-	if (!die_nest_count)
+-		/* Nest count reaches zero, release the lock. */
+-		__raw_spin_unlock(&die_lock);
+-	raw_local_irq_restore(flags);
+-	if (!regs) {
+-		oops_exit();
+-		return;
+-	}
+-	if (panic_on_oops)
+-		panic("Fatal exception");
+-	oops_exit();
+-	do_exit(signr);
+-}
+-
+-int __kprobes __die(const char *str, struct pt_regs *regs, long err)
+-{
+-	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff, ++die_counter);
+-#ifdef CONFIG_PREEMPT
+-	printk("PREEMPT ");
+-#endif
+-#ifdef CONFIG_SMP
+-	printk("SMP ");
+-#endif
+-#ifdef CONFIG_DEBUG_PAGEALLOC
+-	printk("DEBUG_PAGEALLOC");
+-#endif
+-	printk("\n");
+-	if (notify_die(DIE_OOPS, str, regs, err,
+-			current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+-		return 1;
+-
+-	show_registers(regs);
+-	add_taint(TAINT_DIE);
+-	/* Executive summary in case the oops scrolled away */
+-	printk(KERN_ALERT "RIP ");
+-	printk_address(regs->ip, 1);
+-	printk(" RSP <%016lx>\n", regs->sp);
+-	if (kexec_should_crash(current))
+-		crash_kexec(regs);
+-	return 0;
+-}
+-
+-void die(const char *str, struct pt_regs *regs, long err)
+-{
+-	unsigned long flags = oops_begin();
+-
+-	if (!user_mode(regs))
+-		report_bug(regs->ip, regs);
+-
+-	if (__die(str, regs, err))
+-		regs = NULL;
+-	oops_end(flags, regs, SIGSEGV);
+-}
+-
+-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_SYSCTL)
+-notrace __kprobes void
+-die_nmi(char *str, struct pt_regs *regs, int do_panic)
+-{
+-	unsigned long flags;
+-
+-	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-
+-	flags = oops_begin();
+-	/*
+-	 * We are in trouble anyway, lets at least try
+-	 * to get a message out.
+-	 */
+-	printk(KERN_EMERG "%s", str);
+-	printk(" on CPU%d, ip %08lx, registers:\n",
+-		smp_processor_id(), regs->ip);
+-	show_registers(regs);
+-	if (kexec_should_crash(current))
+-		crash_kexec(regs);
+-	if (do_panic || panic_on_oops)
+-		panic("Non maskable interrupt");
+-	oops_end(flags, NULL, SIGBUS);
+-	nmi_exit();
+-	local_irq_enable();
+-	do_exit(SIGBUS);
+-}
+-#endif
+-
+-static void __kprobes
+-do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
+-	long error_code, siginfo_t *info)
+-{
+-	struct task_struct *tsk = current;
+-
+-	if (!user_mode(regs))
+-		goto kernel_trap;
+-
+-	/*
+-	 * We want error_code and trap_no set for userspace faults and
+-	 * kernelspace faults which result in die(), but not
+-	 * kernelspace faults which are fixed up.  die() gives the
+-	 * process no chance to handle the signal and notice the
+-	 * kernel fault information, so that won't result in polluting
+-	 * the information about previously queued, but not yet
+-	 * delivered, faults.  See also do_general_protection below.
+-	 */
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = trapnr;
+-
+-	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+-	    printk_ratelimit()) {
+-		printk(KERN_INFO
+-		       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+-		       tsk->comm, tsk->pid, str,
+-		       regs->ip, regs->sp, error_code);
+-		print_vma_addr(" in ", regs->ip);
+-		printk("\n");
+-	}
+-
+-	if (info)
+-		force_sig_info(signr, info, tsk);
+-	else
+-		force_sig(signr, tsk);
+-	return;
+-
+-kernel_trap:
+-	if (!fixup_exception(regs)) {
+-		tsk->thread.error_code = error_code;
+-		tsk->thread.trap_no = trapnr;
+-		die(str, regs, error_code);
+-	}
+-	return;
+-}
+-
+-#define DO_ERROR(trapnr, signr, str, name) \
+-asmlinkage void do_##name(struct pt_regs * regs, long error_code)	\
+-{									\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	conditional_sti(regs);						\
+-	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
+-}
+-
+-#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
+-asmlinkage void do_##name(struct pt_regs * regs, long error_code)	\
+-{									\
+-	siginfo_t info;							\
+-	info.si_signo = signr;						\
+-	info.si_errno = 0;						\
+-	info.si_code = sicode;						\
+-	info.si_addr = (void __user *)siaddr;				\
+-	trace_hardirqs_fixup();						\
+-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+-							== NOTIFY_STOP)	\
+-		return;							\
+-	conditional_sti(regs);						\
+-	do_trap(trapnr, signr, str, regs, error_code, &info);		\
+-}
+-
+-DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+-DO_ERROR(4, SIGSEGV, "overflow", overflow)
+-DO_ERROR(5, SIGSEGV, "bounds", bounds)
+-DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
+-DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+-DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+-
+-/* Runs on IST stack */
+-asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+-{
+-	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
+-			12, SIGBUS) == NOTIFY_STOP)
+-		return;
+-	preempt_conditional_sti(regs);
+-	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+-	preempt_conditional_cli(regs);
+-}
+-
+-asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
+-{
+-	static const char str[] = "double fault";
+-	struct task_struct *tsk = current;
+-
+-	/* Return not checked because double check cannot be ignored */
+-	notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
+-
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 8;
+-
+-	/* This is always a kernel trap and never fixable (and thus must
+-	   never return). */
+-	for (;;)
+-		die(str, regs, error_code);
+-}
+-
+-asmlinkage void __kprobes
+-do_general_protection(struct pt_regs *regs, long error_code)
+-{
+-	struct task_struct *tsk;
+-
+-	conditional_sti(regs);
+-
+-	tsk = current;
+-	if (!user_mode(regs))
+-		goto gp_in_kernel;
+-
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 13;
+-
+-	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+-			printk_ratelimit()) {
+-		printk(KERN_INFO
+-			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
+-			tsk->comm, tsk->pid,
+-			regs->ip, regs->sp, error_code);
+-		print_vma_addr(" in ", regs->ip);
+-		printk("\n");
+-	}
+-
+-	force_sig(SIGSEGV, tsk);
+-	return;
+-
+-gp_in_kernel:
+-	if (fixup_exception(regs))
+-		return;
+-
+-	tsk->thread.error_code = error_code;
+-	tsk->thread.trap_no = 13;
+-	if (notify_die(DIE_GPF, "general protection fault", regs,
+-				error_code, 13, SIGSEGV) == NOTIFY_STOP)
+-		return;
+-	die("general protection fault", regs, error_code);
+-}
+-
+-static notrace __kprobes void
+-mem_parity_error(unsigned char reason, struct pt_regs *regs)
+-{
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+-		reason);
+-	printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
+-
+-#if defined(CONFIG_EDAC)
+-	if (edac_handler_set()) {
+-		edac_atomic_assert_error();
+-		return;
+-	}
+-#endif
+-
+-	if (panic_on_unrecovered_nmi)
+-		panic("NMI: Not continuing");
+-
+-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+-
+-	/* Clear and disable the memory parity error line. */
+-	clear_mem_error(reason);
+-}
+-
+-static notrace __kprobes void
+-io_check_error(unsigned char reason, struct pt_regs *regs)
+-{
+-	printk("NMI: IOCK error (debug interrupt?)\n");
+-	show_registers(regs);
+-
+-	/* Re-enable the IOCK line, wait for a few seconds */
+-	clear_io_check_error(reason);
+-}
+-
+-static notrace __kprobes void
+-unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+-{
+-	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-	printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+-		reason);
+-	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+-
+-	if (panic_on_unrecovered_nmi)
+-		panic("NMI: Not continuing");
+-
+-	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+-}
+-
+-/* Runs on IST stack. This code must keep interrupts off all the time.
+-   Nested NMIs are prevented by the CPU. */
+-asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+-{
+-	unsigned char reason = 0;
+-	int cpu;
+-
+-	cpu = smp_processor_id();
+-
+-	/* Only the BSP gets external NMIs from the system. */
+-	if (!cpu)
+-		reason = get_nmi_reason();
+-
+-	if (!(reason & 0xc0)) {
+-		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+-								== NOTIFY_STOP)
+-			return;
+-#ifdef CONFIG_X86_LOCAL_APIC
+-		/*
+-		 * Ok, so this is none of the documented NMI sources,
+-		 * so it must be the NMI watchdog.
+-		 */
+-		if (nmi_watchdog_tick(regs, reason))
+-			return;
+-#endif
+-		if (!do_nmi_callback(regs, cpu))
+-			unknown_nmi_error(reason, regs);
+-
+-		return;
+-	}
+-	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+-		return;
+-
+-	/* AK: following checks seem to be broken on modern chipsets. FIXME */
+-	if (reason & 0x80)
+-		mem_parity_error(reason, regs);
+-	if (reason & 0x40)
+-		io_check_error(reason, regs);
+-}
+-
+-asmlinkage notrace __kprobes void
+-do_nmi(struct pt_regs *regs, long error_code)
+-{
+-	nmi_enter();
+-
+-	add_pda(__nmi_count, 1);
+-
+-	if (!ignore_nmis)
+-		default_do_nmi(regs);
+-
+-	nmi_exit();
+-}
+-
+-void stop_nmi(void)
+-{
+-	acpi_nmi_disable();
+-	ignore_nmis++;
+-}
+-
+-void restart_nmi(void)
+-{
+-	ignore_nmis--;
+-	acpi_nmi_enable();
+-}
+-
+-/* runs on IST stack. */
+-asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
+-{
+-	trace_hardirqs_fixup();
+-
+-	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+-			== NOTIFY_STOP)
+-		return;
+-
+-	preempt_conditional_sti(regs);
+-	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+-	preempt_conditional_cli(regs);
+-}
+-
+-/* Help handler running on IST stack to switch back to user stack
+-   for scheduling or signal handling. The actual stack switch is done in
+-   entry.S */
+-asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
+-{
+-	struct pt_regs *regs = eregs;
+-	/* Did already sync */
+-	if (eregs == (struct pt_regs *)eregs->sp)
+-		;
+-	/* Exception from user space */
+-	else if (user_mode(eregs))
+-		regs = task_pt_regs(current);
+-	/* Exception from kernel and interrupts are enabled. Move to
+- 	   kernel process stack. */
+-	else if (eregs->flags & X86_EFLAGS_IF)
+-		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
+-	if (eregs != regs)
+-		*regs = *eregs;
+-	return regs;
+-}
+-
+-/* runs on IST stack. */
+-asmlinkage void __kprobes do_debug(struct pt_regs * regs,
+-				   unsigned long error_code)
+-{
+-	struct task_struct *tsk = current;
+-	unsigned long condition;
+-	siginfo_t info;
+-
+-	trace_hardirqs_fixup();
+-
+-	get_debugreg(condition, 6);
+-
+-	/*
+-	 * The processor cleared BTF, so don't mark that we need it set.
+-	 */
+-	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
+-	tsk->thread.debugctlmsr = 0;
+-
+-	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+-						SIGTRAP) == NOTIFY_STOP)
+-		return;
+-
+-	preempt_conditional_sti(regs);
+-
+-	/* Mask out spurious debug traps due to lazy DR7 setting */
+-	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+-		if (!tsk->thread.debugreg7)
+-			goto clear_dr7;
+-	}
+-
+-	tsk->thread.debugreg6 = condition;
+-
+-	/*
+-	 * Single-stepping through TF: make sure we ignore any events in
+-	 * kernel space (but re-enable TF when returning to user mode).
+-	 */
+-	if (condition & DR_STEP) {
+-		if (!user_mode(regs))
+-			goto clear_TF_reenable;
+-	}
+-
+-	/* Ok, finally something we can handle */
+-	tsk->thread.trap_no = 1;
+-	tsk->thread.error_code = error_code;
+-	info.si_signo = SIGTRAP;
+-	info.si_errno = 0;
+-	info.si_code = TRAP_BRKPT;
+-	info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
+-	force_sig_info(SIGTRAP, &info, tsk);
+-
+-clear_dr7:
+-	set_debugreg(0, 7);
+-	preempt_conditional_cli(regs);
+-	return;
+-
+-clear_TF_reenable:
+-	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+-	regs->flags &= ~X86_EFLAGS_TF;
+-	preempt_conditional_cli(regs);
+-	return;
+-}
+-
+-static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
+-{
+-	if (fixup_exception(regs))
+-		return 1;
+-
+-	notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
+-	/* Illegal floating point operation in the kernel */
+-	current->thread.trap_no = trapnr;
+-	die(str, regs, 0);
+-	return 0;
+-}
+-
+-/*
+- * Note that we play around with the 'TS' bit in an attempt to get
+- * the correct behaviour even in the presence of the asynchronous
+- * IRQ13 behaviour
+- */
+-asmlinkage void do_coprocessor_error(struct pt_regs *regs)
+-{
+-	void __user *ip = (void __user *)(regs->ip);
+-	struct task_struct *task;
+-	siginfo_t info;
+-	unsigned short cwd, swd;
+-
+-	conditional_sti(regs);
+-	if (!user_mode(regs) &&
+-	    kernel_math_error(regs, "kernel x87 math error", 16))
+-		return;
+-
+-	/*
+-	 * Save the info for the exception handler and clear the error.
+-	 */
+-	task = current;
+-	save_init_fpu(task);
+-	task->thread.trap_no = 16;
+-	task->thread.error_code = 0;
+-	info.si_signo = SIGFPE;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT;
+-	info.si_addr = ip;
+-	/*
+-	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+-	 * status.  0x3f is the exception bits in these regs, 0x200 is the
+-	 * C1 reg you need in case of a stack fault, 0x040 is the stack
+-	 * fault bit.  We should only be taking one exception at a time,
+-	 * so if this combination doesn't produce any single exception,
+-	 * then we have a bad program that isn't synchronizing its FPU usage
+-	 * and it will suffer the consequences since we won't be able to
+-	 * fully reproduce the context of the exception
+-	 */
+-	cwd = get_fpu_cwd(task);
+-	swd = get_fpu_swd(task);
+-	switch (swd & ~cwd & 0x3f) {
+-	case 0x000: /* No unmasked exception */
+-	default: /* Multiple exceptions */
+-		break;
+-	case 0x001: /* Invalid Op */
+-		/*
+-		 * swd & 0x240 == 0x040: Stack Underflow
+-		 * swd & 0x240 == 0x240: Stack Overflow
+-		 * User must clear the SF bit (0x40) if set
+-		 */
+-		info.si_code = FPE_FLTINV;
+-		break;
+-	case 0x002: /* Denormalize */
+-	case 0x010: /* Underflow */
+-		info.si_code = FPE_FLTUND;
+-		break;
+-	case 0x004: /* Zero Divide */
+-		info.si_code = FPE_FLTDIV;
+-		break;
+-	case 0x008: /* Overflow */
+-		info.si_code = FPE_FLTOVF;
+-		break;
+-	case 0x020: /* Precision */
+-		info.si_code = FPE_FLTRES;
+-		break;
+-	}
+-	force_sig_info(SIGFPE, &info, task);
+-}
+-
+-asmlinkage void bad_intr(void)
+-{
+-	printk("bad interrupt"); 
+-}
+-
+-asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
+-{
+-	void __user *ip = (void __user *)(regs->ip);
+-	struct task_struct *task;
+-	siginfo_t info;
+-	unsigned short mxcsr;
+-
+-	conditional_sti(regs);
+-	if (!user_mode(regs) &&
+-        	kernel_math_error(regs, "kernel simd math error", 19))
+-		return;
+-
+-	/*
+-	 * Save the info for the exception handler and clear the error.
+-	 */
+-	task = current;
+-	save_init_fpu(task);
+-	task->thread.trap_no = 19;
+-	task->thread.error_code = 0;
+-	info.si_signo = SIGFPE;
+-	info.si_errno = 0;
+-	info.si_code = __SI_FAULT;
+-	info.si_addr = ip;
+-	/*
+-	 * The SIMD FPU exceptions are handled a little differently, as there
+-	 * is only a single status/control register.  Thus, to determine which
+-	 * unmasked exception was caught we must mask the exception mask bits
+-	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+-	 */
+-	mxcsr = get_fpu_mxcsr(task);
+-	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+-	case 0x000:
+-	default:
+-		break;
+-	case 0x001: /* Invalid Op */
+-		info.si_code = FPE_FLTINV;
+-		break;
+-	case 0x002: /* Denormalize */
+-	case 0x010: /* Underflow */
+-		info.si_code = FPE_FLTUND;
+-		break;
+-	case 0x004: /* Zero Divide */
+-		info.si_code = FPE_FLTDIV;
+-		break;
+-	case 0x008: /* Overflow */
+-		info.si_code = FPE_FLTOVF;
+-		break;
+-	case 0x020: /* Precision */
+-		info.si_code = FPE_FLTRES;
+-		break;
+-	}
+-	force_sig_info(SIGFPE, &info, task);
+-}
+-
+-asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
+-{
+-}
+-
+-#if 0
+-asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+-{
+-}
+-#endif
+-
+-asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void)
+-{
+-}
+-
+-/*
+- * 'math_state_restore()' saves the current math information in the
+- * old math state array, and gets the new ones from the current task
+- *
+- * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+- * Don't touch unless you *really* know how it works.
+- */
+-asmlinkage void math_state_restore(void)
+-{
+-	struct task_struct *me = current;
+-
+-	if (!used_math()) {
+-		local_irq_enable();
+-		/*
+-		 * does a slab alloc which can sleep
+-		 */
+-		if (init_fpu(me)) {
+-			/*
+-			 * ran out of memory!
+-			 */
+-			do_group_exit(SIGKILL);
+-			return;
+-		}
+-		local_irq_disable();
+-	}
+-
+-        /* clts(); */ /* 'clts' is done for us by Xen during virtual trap. */
+-
+-	/*
+-	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+-	 */
+-	if (unlikely(restore_fpu_checking(&me->thread.xstate->fxsave))) {
+-		stts();
+-		force_sig(SIGSEGV, me);
+-		return;
+-	}
+-	task_thread_info(me)->status |= TS_USEDFPU;
+-	me->fpu_counter++;
+-}
+-EXPORT_SYMBOL_GPL(math_state_restore);
+-
+-
+-/*
+- * NB. All these are "interrupt gates" (i.e. events_mask is set) because we
+- * specify <dpl>|4 in the second field.
+- */
+-static const trap_info_t __cpuinitconst 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                       },
+-        {  4, 3|4, __KERNEL_CS, (unsigned long)overflow                   },
+-        {  5, 0|4, __KERNEL_CS, (unsigned long)bounds                     },
+-        {  6, 0|4, __KERNEL_CS, (unsigned long)invalid_op                 },
+-        {  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available       },
+-        {  9, 0|4, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun},
+-        { 10, 0|4, __KERNEL_CS, (unsigned long)invalid_TSS                },
+-        { 11, 0|4, __KERNEL_CS, (unsigned long)segment_not_present        },
+-        { 12, 0|4, __KERNEL_CS, (unsigned long)stack_segment              },
+-        { 13, 0|4, __KERNEL_CS, (unsigned long)general_protection         },
+-        { 14, 0|4, __KERNEL_CS, (unsigned long)page_fault                 },
+-        { 15, 0|4, __KERNEL_CS, (unsigned long)spurious_interrupt_bug     },
+-        { 16, 0|4, __KERNEL_CS, (unsigned long)coprocessor_error          },
+-        { 17, 0|4, __KERNEL_CS, (unsigned long)alignment_check            },
+-#ifdef CONFIG_X86_MCE
+-        { 18, 0|4, __KERNEL_CS, (unsigned long)machine_check              },
+-#endif
+-        { 19, 0|4, __KERNEL_CS, (unsigned long)simd_coprocessor_error     },
+-#ifdef CONFIG_IA32_EMULATION
+-	{ IA32_SYSCALL_VECTOR, 3, __KERNEL_CS, (unsigned long)ia32_syscall},
+-#endif
+-        {  0, 0,           0, 0                                              }
+-};
+-
+-void __init trap_init(void)
+-{
+-        int ret;
+-
+-        ret = HYPERVISOR_set_trap_table(trap_table);
+-        if (ret) 
+-		printk("HYPERVISOR_set_trap_table failed: error %d\n", ret);
+-	/*
+-	 * initialize the per thread extended state:
+-	 */
+-	init_thread_xstate();
+-	/*
+-	 * Should be a barrier for any external CPU state:
+-	 */
+-	cpu_init();
+-}
+-
+-void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+-{
+-	const trap_info_t *t = trap_table;
+-
+-	for (t = trap_table; t->address; t++) {
+-		trap_ctxt[t->vector].flags = t->flags;
+-		trap_ctxt[t->vector].cs = t->cs;
+-		trap_ctxt[t->vector].address = t->address;
+-	}
+-}
+-
+-static int __init oops_setup(char *s)
+-{
+-	if (!s)
+-		return -EINVAL;
+-	if (!strcmp(s, "panic"))
+-		panic_on_oops = 1;
+-	return 0;
+-}
+-early_param("oops", oops_setup);
+-
+-static int __init kstack_setup(char *s)
+-{
+-	if (!s)
+-		return -EINVAL;
+-	kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+-	return 0;
+-}
+-early_param("kstack", kstack_setup);
+-
+-static int __init code_bytes_setup(char *s)
+-{
+-	code_bytes = simple_strtoul(s, NULL, 0);
+-	if (code_bytes > 8192)
+-		code_bytes = 8192;
+-
+-	return 1;
+-}
+-__setup("code_bytes=", code_bytes_setup);
+--- head-2010-01-18.orig/arch/x86/mm/fault-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include <asm/tlbflush.h>
+ #include <asm/proto.h>
+ #include <asm-generic/sections.h>
++#include <asm/traps.h>
+ 
+ /*
+  * Page fault error code bits
+@@ -370,8 +371,6 @@ static int is_errata100(struct pt_regs *
+ 	return 0;
+ }
+ 
+-void do_invalid_op(struct pt_regs *, unsigned long);
+-
+ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
+ {
+ #ifdef CONFIG_X86_F00F_BUG
+@@ -609,11 +608,6 @@ void __kprobes do_page_fault(struct pt_r
+ 	unsigned long flags;
+ #endif
+ 
+-	/*
+-	 * We can fault from pretty much anywhere, with unknown IRQ state.
+-	 */
+-	trace_hardirqs_fixup();
+-
+ 	/* Set the "privileged fault" bit to something sane. */
+ 	if (user_mode_vm(regs))
+ 		error_code |= PF_USER;
+@@ -677,24 +671,23 @@ void __kprobes do_page_fault(struct pt_r
+ 	}
+ 
+ 
+-#ifdef CONFIG_X86_32
+-	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+-	   fault has been handled. */
+-	if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
+-		local_irq_enable();
+-
+ 	/*
+-	 * If we're in an interrupt, have no user context or are running in an
+-	 * atomic region then we must not take the fault.
++	 * It's safe to allow irq's after cr2 has been saved and the
++	 * vmalloc fault has been handled.
++	 *
++	 * User-mode registers count as a user access even for any
++	 * potential system fault or CPU buglet.
+ 	 */
+-	if (in_atomic() || !mm)
+-		goto bad_area_nosemaphore;
+-#else /* CONFIG_X86_64 */
+-	if (likely(regs->flags & X86_EFLAGS_IF))
++	if (user_mode_vm(regs)) {
++		local_irq_enable();
++		error_code |= PF_USER;
++	} else if (regs->flags & X86_EFLAGS_IF)
+ 		local_irq_enable();
+ 
++#ifdef CONFIG_X86_64
+ 	if (unlikely(error_code & PF_RSVD))
+ 		pgtable_bad(address, regs, error_code);
++#endif
+ 
+ 	/*
+ 	 * If we're in an interrupt, have no user context or are running in an
+@@ -703,15 +696,9 @@ void __kprobes do_page_fault(struct pt_r
+ 	if (unlikely(in_atomic() || !mm))
+ 		goto bad_area_nosemaphore;
+ 
+-	/*
+-	 * User-mode registers count as a user access even for any
+-	 * potential system fault or CPU buglet.
+-	 */
+-	if (user_mode_vm(regs))
+-		error_code |= PF_USER;
+ again:
+-#endif
+-	/* When running in the kernel we expect faults to occur only to
++	/*
++	 * When running in the kernel we expect faults to occur only to
+ 	 * addresses in user space.  All other faults represent errors in the
+ 	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+ 	 * erroneous fault occurring in a code path which already holds mmap_sem
+@@ -774,9 +761,6 @@ good_area:
+ 			goto bad_area;
+ 	}
+ 
+-#ifdef CONFIG_X86_32
+-survive:
+-#endif
+ 	/*
+ 	 * If for any reason at all we couldn't handle the fault,
+ 	 * make sure we exit gracefully rather than endlessly redo
+@@ -911,12 +895,11 @@ out_of_memory:
+ 	up_read(&mm->mmap_sem);
+ 	if (is_global_init(tsk)) {
+ 		yield();
+-#ifdef CONFIG_X86_32
+-		down_read(&mm->mmap_sem);
+-		goto survive;
+-#else
++		/*
++		 * Re-lookup the vma - in theory the vma tree might
++		 * have changed:
++		 */
+ 		goto again;
+-#endif
+ 	}
+ 
+ 	printk("VM: killing process %s\n", tsk->comm);
+@@ -946,14 +929,15 @@ LIST_HEAD(pgd_list);
+ 
+ void vmalloc_sync_all(void)
+ {
+-#ifdef CONFIG_X86_32
+-	unsigned long address = VMALLOC_START & PGDIR_MASK;
++	unsigned long address;
+ 
++#ifdef CONFIG_X86_32
+ 	if (SHARED_KERNEL_PMD)
+ 		return;
+ 
+-	BUILD_BUG_ON(TASK_SIZE & ~PMD_MASK);
+-	for (; address < hypervisor_virt_start; address += PMD_SIZE) {
++	for (address = VMALLOC_START & PMD_MASK;
++	     address >= TASK_SIZE && address < FIXADDR_TOP;
++	     address += PMD_SIZE) {
+ 		unsigned long flags;
+ 		struct page *page;
+ 
+@@ -966,10 +950,8 @@ void vmalloc_sync_all(void)
+ 		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+ #else /* CONFIG_X86_64 */
+-	unsigned long start = VMALLOC_START & PGDIR_MASK;
+-	unsigned long address;
+-
+-	for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
++	for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
++	     address += PGDIR_SIZE) {
+ 		const pgd_t *pgd_ref = pgd_offset_k(address);
+ 		unsigned long flags;
+ 		struct page *page;
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -137,6 +137,7 @@ void *kmap_atomic_pfn(unsigned long pfn,
+ 
+ 	return (void*) vaddr;
+ }
++EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
+ 
+ struct page *kmap_atomic_to_page(void *ptr)
+ {
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -34,6 +34,7 @@
+ #include <linux/scatterlist.h>
+ 
+ #include <asm/asm.h>
++#include <asm/bios_ebda.h>
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -51,6 +52,7 @@
+ #include <asm/swiotlb.h>
+ #include <asm/setup.h>
+ #include <asm/cacheflush.h>
++#include <asm/smp.h>
+ 
+ unsigned int __VMALLOC_RESERVE = 128 << 20;
+ 
+@@ -206,11 +208,32 @@ static void __init kernel_physical_mappi
+ 	pgd_t *pgd;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+-	unsigned pages_2m = 0, pages_4k = 0;
++	unsigned pages_2m, pages_4k;
++	int mapping_iter;
+ 
+-	if (!cpu_has_pse)
++	/*
++	 * First iteration will setup identity mapping using large/small pages
++	 * based on use_pse, with other attributes same as set by
++	 * the early code in head_32.S
++	 *
++	 * Second iteration will setup the appropriate attributes (NX, GLOBAL..)
++	 * as desired for the kernel identity mapping.
++	 *
++	 * This two pass mechanism conforms to the TLB app note which says:
++	 *
++	 *     "Software should not write to a paging-structure entry in a way
++	 *      that would change, for any linear address, both the page size
++	 *      and either the page frame or attributes."
++	 */
++	mapping_iter = 1;
++
++	if (!cpu_has_pse) {
+ 		use_pse = 0;
++		mapping_iter = 0;
++	}
+ 
++repeat:
++	pages_2m = pages_4k = 0;
+ 	pfn = start_pfn;
+ 	pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+ 	pgd = pgd_base + pgd_idx;
+@@ -250,6 +273,13 @@ static void __init kernel_physical_mappi
+ 			if (use_pse) {
+ 				unsigned int addr2;
+ 				pgprot_t prot = PAGE_KERNEL_LARGE;
++				/*
++				 * first pass will use the same initial
++				 * identity mapping attribute + _PAGE_PSE.
++				 */
++				pgprot_t init_prot =
++					__pgprot(PTE_IDENT_ATTR |
++						 _PAGE_PSE);
+ 
+ 				addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE +
+ 					PAGE_OFFSET + PAGE_SIZE-1;
+@@ -259,7 +289,10 @@ static void __init kernel_physical_mappi
+ 					prot = PAGE_KERNEL_LARGE_EXEC;
+ 
+ 				pages_2m++;
+-				set_pmd(pmd, pfn_pmd(pfn, prot));
++				if (mapping_iter == 1)
++					set_pmd(pmd, pfn_pmd(pfn, init_prot));
++				else
++					set_pmd(pmd, pfn_pmd(pfn, prot));
+ 
+ 				pfn += PTRS_PER_PTE;
+ 				continue;
+@@ -271,6 +304,11 @@ static void __init kernel_physical_mappi
+ 			for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn;
+ 			     pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) {
+ 				pgprot_t prot = PAGE_KERNEL;
++				/*
++				 * first pass will use the same initial
++				 * identity mapping attribute.
++				 */
++				pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR);
+ 
+ 				/* XEN: Only map initial RAM allocation. */
+ 				if (pfn >= xen_start_info->nr_pages || pte_present(*pte))
+@@ -279,12 +317,34 @@ static void __init kernel_physical_mappi
+ 					prot = PAGE_KERNEL_EXEC;
+ 
+ 				pages_4k++;
+-				set_pte(pte, pfn_pte(pfn, prot));
++				if (mapping_iter == 1)
++					set_pte(pte, pfn_pte(pfn, init_prot));
++				else
++					set_pte(pte, pfn_pte(pfn, prot));
+ 			}
+ 		}
+ 	}
+-	update_page_count(PG_LEVEL_2M, pages_2m);
+-	update_page_count(PG_LEVEL_4K, pages_4k);
++	if (mapping_iter <= 1) {
++		/*
++		 * update direct mapping page count only in the first
++		 * iteration.
++		 */
++		update_page_count(PG_LEVEL_2M, pages_2m);
++		update_page_count(PG_LEVEL_4K, pages_4k);
++	}
++	if (mapping_iter == 1) {
++		/*
++		 * local global flush tlb, which will flush the previous
++		 * mappings present in both small and large page TLB's.
++		 */
++		__flush_tlb_all();
++
++		/*
++		 * Second iteration will set the actual desired PTE attributes.
++		 */
++		mapping_iter = 2;
++		goto repeat;
++	}
+ }
+ 
+ /*
+@@ -306,7 +366,6 @@ int devmem_is_allowed(unsigned long page
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+ 
+@@ -329,6 +388,7 @@ static void __init kmap_init(void)
+ 	kmap_prot = PAGE_KERNEL;
+ }
+ 
++#ifdef CONFIG_HIGHMEM
+ static void __init permanent_kmaps_init(pgd_t *pgd_base)
+ {
+ 	unsigned long vaddr;
+@@ -416,7 +476,6 @@ static void __init set_highmem_pages_ini
+ #endif /* !CONFIG_NUMA */
+ 
+ #else
+-# define kmap_init()				do { } while (0)
+ # define permanent_kmaps_init(pgd_base)		do { } while (0)
+ # define set_highmem_pages_init()	do { } while (0)
+ #endif /* CONFIG_HIGHMEM */
+@@ -775,7 +834,7 @@ static unsigned long __init extend_init_
+ 	return start_pfn;
+ }
+ 
+-static void __init find_early_table_space(unsigned long end)
++static void __init find_early_table_space(unsigned long end, int use_pse)
+ {
+ 	unsigned long puds, pmds, ptes, tables;
+ 
+@@ -785,7 +844,7 @@ static void __init find_early_table_spac
+ 	pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+ 	tables += PAGE_ALIGN(pmds * sizeof(pmd_t));
+ 
+-	if (cpu_has_pse) {
++	if (use_pse) {
+ 		unsigned long extra;
+ 
+ 		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+@@ -818,12 +877,22 @@ unsigned long __init_refok init_memory_m
+ 	pgd_t *pgd_base = swapper_pg_dir;
+ 	unsigned long start_pfn, end_pfn;
+ 	unsigned long big_page_start;
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/*
++	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
++	 * This will simplify cpa(), which otherwise needs to support splitting
++	 * large pages into small in interrupt context, etc.
++	 */
++	int use_pse = 0;
++#else
++	int use_pse = cpu_has_pse;
++#endif
+ 
+ 	/*
+ 	 * Find space for the kernel direct mapping tables.
+ 	 */
+ 	if (!after_init_bootmem)
+-		find_early_table_space(end);
++		find_early_table_space(end, use_pse);
+ 
+ #ifdef CONFIG_X86_PAE
+ 	set_nx();
+@@ -869,7 +938,7 @@ unsigned long __init_refok init_memory_m
+ 	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+ 	if (start_pfn < end_pfn)
+ 		kernel_physical_mapping_init(pgd_base, start_pfn, end_pfn,
+-						cpu_has_pse);
++					     use_pse);
+ 
+ 	/* tail is not big page alignment ? */
+ 	start_pfn = end_pfn;
+@@ -954,6 +1023,8 @@ void __init mem_init(void)
+ 
+ 	pci_iommu_alloc();
+ 
++	start_periodic_check_for_corruption();
++
+ #ifdef CONFIG_FLATMEM
+ 	BUG_ON(!mem_map);
+ #endif
+@@ -1038,7 +1109,6 @@ void __init mem_init(void)
+ 	if (boot_cpu_data.wp_works_ok < 0)
+ 		test_wp_bit();
+ 
+-	cpa_init();
+ 	save_pg_dir();
+ 	zap_low_mappings();
+ 
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -34,6 +34,7 @@
+ #include <linux/nmi.h>
+ 
+ #include <asm/processor.h>
++#include <asm/bios_ebda.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -157,6 +158,62 @@ static unsigned long __meminitdata table
+ static unsigned long __meminitdata table_cur;
+ static unsigned long __meminitdata table_top;
+ 
++pteval_t __supported_pte_mask __read_mostly = ~0UL;
++EXPORT_SYMBOL_GPL(__supported_pte_mask);
++
++static int do_not_nx __cpuinitdata;
++
++/*
++ * noexec=on|off
++ * Control non-executable mappings for 64-bit processes.
++ *
++ * on	Enable (default)
++ * off	Disable
++ */
++static int __init nonx_setup(char *str)
++{
++	if (!str)
++		return -EINVAL;
++	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 0;
++}
++early_param("noexec", nonx_setup);
++
++void __cpuinit check_efer(void)
++{
++	unsigned long efer;
++
++	rdmsrl(MSR_EFER, efer);
++	if (!(efer & EFER_NX) || do_not_nx)
++		__supported_pte_mask &= ~_PAGE_NX;
++}
++
++int force_personality32;
++
++/*
++ * 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 32-bit processes (default)
++ * off	PROT_READ implies PROT_EXEC
++ */
++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);
++
+ /*
+  * NOTE: This function is marked __ref because it calls __init function
+  * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
+@@ -214,14 +271,6 @@ set_pte_vaddr_pud(pud_t *pud_page, unsig
+ 	}
+ 
+ 	pte = pte_offset_kernel(pmd, vaddr);
+-	if (!pte_none(*pte) && __pte_val(new_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);
+ 
+ 	/*
+@@ -306,7 +355,7 @@ void __init init_extra_mapping_uc(unsign
+ void __init cleanup_highmap(void)
+ {
+ 	unsigned long vaddr = __START_KERNEL_map;
+-	unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1;
++	unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
+ 	pmd_t *pmd = level2_kernel_pgt;
+ 	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
+ 
+@@ -336,7 +385,7 @@ static __ref void *alloc_low_page(unsign
+ 	if (pfn >= table_top)
+ 		panic("alloc_low_page: ran out of memory");
+ 
+-	adr = early_ioremap(pfn_to_mfn(pfn) * PAGE_SIZE, PAGE_SIZE);
++	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
+ 	memset(adr, 0, PAGE_SIZE);
+ 	*phys  = pfn * PAGE_SIZE;
+ 	return adr;
+@@ -382,7 +431,8 @@ static inline int __meminit make_readonl
+ }
+ 
+ static unsigned long __meminit
+-phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end)
++phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
++	      pgprot_t prot)
+ {
+ 	unsigned pages = 0;
+ 	unsigned long last_map_addr = end;
+@@ -391,49 +441,58 @@ phys_pte_init(pte_t *pte_page, unsigned 
+ 	pte_t *pte = pte_page + pte_index(addr);
+ 
+ 	for(i = pte_index(addr); i < PTRS_PER_PTE; i++, addr += PAGE_SIZE, pte++) {
+-		unsigned long pteval = addr | __PAGE_KERNEL;
++		unsigned long pteval = addr | pgprot_val(prot);
+ 
+ 		if (addr >= end ||
+ 		    (!after_bootmem &&
+ 		     (addr >> PAGE_SHIFT) >= xen_start_info->nr_pages))
+ 			break;
+ 
+-		if (__pte_val(*pte))
++		/*
++		 * We will re-use the existing mapping.
++		 * Xen for example has some special requirements, like mapping
++		 * pagetable pages as RO. So assume someone who pre-setup
++		 * these mappings are more intelligent.
++		 */
++		if (__pte_val(*pte)) {
++			pages++;
+ 			continue;
++		}
+ 
+ 		if (make_readonly(addr))
+ 			pteval &= ~_PAGE_RW;
+ 		if (0)
+ 			printk("   pte=%p addr=%lx pte=%016lx\n",
+ 			       pte, addr, pteval);
++		pages++;
+ 		if (!after_bootmem)
+ 			*pte = __pte(pteval & __supported_pte_mask);
+ 		else
+ 			set_pte(pte, __pte(pteval & __supported_pte_mask));
+ 		last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE;
+-		pages++;
+ 	}
++
+ 	update_page_count(PG_LEVEL_4K, pages);
+ 
+ 	return last_map_addr;
+ }
+ 
+ static unsigned long __meminit
+-phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end)
++phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end,
++		pgprot_t prot)
+ {
+ 	pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
+ 
+ 	BUG_ON(!max_pfn_mapped);
+-	return phys_pte_init(pte, address, end);
++	return phys_pte_init(pte, address, end, prot);
+ }
+ 
+ static unsigned long __meminit
+ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
+-			 unsigned long page_size_mask)
++	      unsigned long page_size_mask, pgprot_t prot)
+ {
+ 	unsigned long pages = 0;
+ 	unsigned long last_map_addr = end;
+-	unsigned long start = address;
+ 
+ 	int i = pmd_index(address);
+ 
+@@ -441,6 +500,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ 		unsigned long pte_phys;
+ 		pmd_t *pmd = pmd_page + pmd_index(address);
+ 		pte_t *pte;
++		pgprot_t new_prot = prot;
+ 
+ 		if (address >= end)
+ 			break;
+@@ -449,27 +509,42 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ 			if (!pmd_large(*pmd)) {
+ 				spin_lock(&init_mm.page_table_lock);
+ 				last_map_addr = phys_pte_update(pmd, address,
+-								end);
++								end, prot);
+ 				spin_unlock(&init_mm.page_table_lock);
++				continue;
+ 			}
+-			/* Count entries we're using from level2_ident_pgt */
+-			if (start == 0)
++			/*
++			 * If we are ok with PG_LEVEL_2M mapping, then we will
++			 * use the existing mapping,
++			 *
++			 * Otherwise, we will split the large page mapping but
++			 * use the same existing protection bits except for
++			 * large page, so that we don't violate Intel's TLB
++			 * Application note (317080) which says, while changing
++			 * the page sizes, new and old translations should
++			 * not differ with respect to page frame and
++			 * attributes.
++			 */
++			if (page_size_mask & (1 << PG_LEVEL_2M)) {
+ 				pages++;
+-			continue;
++				continue;
++			}
++			new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd));
+ 		}
+ 
+ 		if (page_size_mask & (1<<PG_LEVEL_2M)) {
+ 			pages++;
+ 			spin_lock(&init_mm.page_table_lock);
+ 			set_pte((pte_t *)pmd,
+-				pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
++				pfn_pte(address >> PAGE_SHIFT,
++					__pgprot(pgprot_val(prot) | _PAGE_PSE)));
+ 			spin_unlock(&init_mm.page_table_lock);
+ 			last_map_addr = (address & PMD_MASK) + PMD_SIZE;
+ 			continue;
+ 		}
+ 
+ 		pte = alloc_low_page(&pte_phys);
+-		last_map_addr = phys_pte_init(pte, address, end);
++		last_map_addr = phys_pte_init(pte, address, end, new_prot);
+ 		unmap_low_page(pte);
+ 
+ 		if (!after_bootmem) {
+@@ -490,13 +565,13 @@ phys_pmd_init(pmd_t *pmd_page, unsigned 
+ 
+ static unsigned long __meminit
+ phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
+-			 unsigned long page_size_mask)
++		unsigned long page_size_mask, pgprot_t prot)
+ {
+ 	pmd_t *pmd = pmd_offset(pud, 0);
+ 	unsigned long last_map_addr;
+ 
+ 	BUG_ON(!max_pfn_mapped);
+-	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask);
++	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot);
+ 	__flush_tlb_all();
+ 	return last_map_addr;
+ }
+@@ -513,15 +588,34 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 		unsigned long pmd_phys;
+ 		pud_t *pud = pud_page + pud_index(addr);
+ 		pmd_t *pmd;
++		pgprot_t prot = PAGE_KERNEL;
+ 
+ 		if (addr >= end)
+ 			break;
+ 
+ 		if (__pud_val(*pud)) {
+-			if (!pud_large(*pud))
++			if (!pud_large(*pud)) {
+ 				last_map_addr = phys_pmd_update(pud, addr, end,
+-							 page_size_mask);
+-			continue;
++							 page_size_mask, prot);
++				continue;
++			}
++			/*
++			 * If we are ok with PG_LEVEL_1G mapping, then we will
++			 * use the existing mapping.
++			 *
++			 * Otherwise, we will split the gbpage mapping but use
++			 * the same existing protection  bits except for large
++			 * page, so that we don't violate Intel's TLB
++			 * Application note (317080) which says, while changing
++			 * the page sizes, new and old translations should
++			 * not differ with respect to page frame and
++			 * attributes.
++			 */
++			if (page_size_mask & (1 << PG_LEVEL_1G)) {
++				pages++;
++				continue;
++			}
++			prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud));
+ 		}
+ 
+ 		if (page_size_mask & (1<<PG_LEVEL_1G)) {
+@@ -535,7 +629,8 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 		}
+ 
+ 		pmd = alloc_low_page(&pmd_phys);
+-		last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask);
++		last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask,
++					      prot);
+ 		unmap_low_page(pmd);
+ 
+ 		if (!after_bootmem) {
+@@ -554,6 +649,7 @@ phys_pud_init(pud_t *pud_page, unsigned 
+ 		}
+ 	}
+ 	__flush_tlb_all();
++
+ 	update_page_count(PG_LEVEL_1G, pages);
+ 
+ 	return last_map_addr;
+@@ -651,7 +747,8 @@ void __init xen_init_pt(void)
+ 	}
+ }
+ 
+-static void __init find_early_table_space(unsigned long end)
++static void __init find_early_table_space(unsigned long end, int use_pse,
++					  int use_gbpages)
+ {
+ 	unsigned long puds, pmds, ptes, tables;
+ 
+@@ -676,6 +773,7 @@ static void __init find_early_table_spac
+ 		 */
+ 		table_start = table_top;
+ 	}
++	__flush_tlb_all();
+ 
+ 	table_top = table_cur + (tables >> PAGE_SHIFT);
+ 
+@@ -825,11 +923,13 @@ unsigned long __init_refok init_memory_m
+ 	unsigned long last_map_addr = 0;
+ 	unsigned long page_size_mask = 0;
+ 	unsigned long start_pfn, end_pfn;
++	unsigned long pos;
+ 
+ 	struct map_range mr[NR_RANGE_MR];
+ 	int nr_range, i;
++	int use_pse, use_gbpages;
+ 
+-	printk(KERN_INFO "init_memory_mapping\n");
++	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
+ 
+ 	/*
+ 	 * Find space for the kernel direct mapping tables.
+@@ -841,9 +941,21 @@ unsigned long __init_refok init_memory_m
+ 	if (!after_bootmem)
+ 		init_gbpages();
+ 
+-	if (direct_gbpages)
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	/*
++	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
++	 * This will simplify cpa(), which otherwise needs to support splitting
++	 * large pages into small in interrupt context, etc.
++	 */
++	use_pse = use_gbpages = 0;
++#else
++	use_pse = cpu_has_pse;
++	use_gbpages = direct_gbpages;
++#endif
++
++	if (use_gbpages)
+ 		page_size_mask |= 1 << PG_LEVEL_1G;
+-	if (cpu_has_pse)
++	if (use_pse)
+ 		page_size_mask |= 1 << PG_LEVEL_2M;
+ 
+ 	memset(mr, 0, sizeof(mr));
+@@ -851,35 +963,50 @@ unsigned long __init_refok init_memory_m
+ 
+ 	/* head if not big page alignment ?*/
+ 	start_pfn = start >> PAGE_SHIFT;
+-	end_pfn = ((start + (PMD_SIZE - 1)) >> PMD_SHIFT)
++	pos = start_pfn << PAGE_SHIFT;
++	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
+ 			<< (PMD_SHIFT - PAGE_SHIFT);
+-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
++		pos = end_pfn << PAGE_SHIFT;
++	}
+ 
+ 	/* big page (2M) range*/
+-	start_pfn = ((start + (PMD_SIZE - 1))>>PMD_SHIFT)
++	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+ 			 << (PMD_SHIFT - PAGE_SHIFT);
+-	end_pfn = ((start + (PUD_SIZE - 1))>>PUD_SHIFT)
++	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+ 			 << (PUD_SHIFT - PAGE_SHIFT);
+-	if (end_pfn > ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT)))
+-		end_pfn = ((end>>PUD_SHIFT)<<(PUD_SHIFT - PAGE_SHIFT));
+-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+-			page_size_mask & (1<<PG_LEVEL_2M));
++	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
++		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask & (1<<PG_LEVEL_2M));
++		pos = end_pfn << PAGE_SHIFT;
++	}
+ 
+ 	/* big page (1G) range */
+-	start_pfn = end_pfn;
+-	end_pfn = (end>>PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
+-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
++			 << (PUD_SHIFT - PAGE_SHIFT);
++	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+ 				page_size_mask &
+ 				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
++		pos = end_pfn << PAGE_SHIFT;
++	}
+ 
+ 	/* tail is not big page (1G) alignment */
+-	start_pfn = end_pfn;
+-	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+-	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+-			page_size_mask & (1<<PG_LEVEL_2M));
++	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
++			 << (PMD_SHIFT - PAGE_SHIFT);
++	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
++	if (start_pfn < end_pfn) {
++		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
++				page_size_mask & (1<<PG_LEVEL_2M));
++		pos = end_pfn << PAGE_SHIFT;
++	}
+ 
+ 	/* tail is not big page (2M) alignment */
+-	start_pfn = end_pfn;
++	start_pfn = pos>>PAGE_SHIFT;
+ 	end_pfn = end>>PAGE_SHIFT;
+ 	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+ 
+@@ -904,7 +1031,7 @@ unsigned long __init_refok init_memory_m
+ 			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
+ 
+ 	if (!after_bootmem)
+-		find_early_table_space(end);
++		find_early_table_space(end, use_pse, use_gbpages);
+ 
+ 	if (!start) {
+ 		unsigned long addr, va = __START_KERNEL_map;
+@@ -1015,12 +1142,12 @@ int arch_add_memory(int nid, u64 start, 
+ 	unsigned long nr_pages = size >> PAGE_SHIFT;
+ 	int ret;
+ 
+-	last_mapped_pfn = init_memory_mapping(start, start + size-1);
++	last_mapped_pfn = init_memory_mapping(start, start + size);
+ 	if (last_mapped_pfn > max_pfn_mapped)
+ 		max_pfn_mapped = last_mapped_pfn;
+ 
+ 	ret = __add_pages(zone, start_pfn, nr_pages);
+-	WARN_ON(1);
++	WARN_ON_ONCE(ret);
+ 
+ 	return ret;
+ }
+@@ -1062,8 +1189,11 @@ static struct kcore_list kcore_mem, kcor
+ void __init mem_init(void)
+ {
+ 	long codesize, reservedpages, datasize, initsize;
++	unsigned long absent_pages;
+ 	unsigned long pfn;
+ 
++	start_periodic_check_for_corruption();
++
+ 	pci_iommu_alloc();
+ 
+ 	/* clear_bss() already clear the empty_zero_page */
+@@ -1076,13 +1206,15 @@ void __init mem_init(void)
+ #else
+ 	totalram_pages = free_all_bootmem();
+ #endif
++
+ 	/* XEN: init pages outside initial allocation. */
+ 	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+ 		ClearPageReserved(pfn_to_page(pfn));
+ 		init_page_count(pfn_to_page(pfn));
+ 	}
+-	reservedpages = max_pfn - totalram_pages -
+-					absent_pages_in_range(0, max_pfn);
++
++	absent_pages = absent_pages_in_range(0, max_pfn);
++	reservedpages = max_pfn - totalram_pages - absent_pages;
+ 	after_bootmem = 1;
+ 
+ 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+@@ -1099,15 +1231,14 @@ void __init mem_init(void)
+ 				 VSYSCALL_END - VSYSCALL_START);
+ 
+ 	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+-				"%ldk reserved, %ldk data, %ldk init)\n",
++			 "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n",
+ 		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ 		max_pfn << (PAGE_SHIFT-10),
+ 		codesize >> 10,
++		absent_pages << (PAGE_SHIFT-10),
+ 		reservedpages << (PAGE_SHIFT-10),
+ 		datasize >> 10,
+ 		initsize >> 10);
+-
+-	cpa_init();
+ }
+ 
+ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/mm/iomap_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -0,0 +1,61 @@
++/*
++ * Copyright © 2008 Ingo Molnar
++ *
++ * 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 <asm/iomap.h>
++#include <linux/bitops.h>
++#include <linux/module.h>
++
++/* Map 'mfn' using fixed map 'type' and protections 'prot'
++ */
++void *
++iomap_atomic_prot_pfn(unsigned long mfn, enum km_type type, pgprot_t prot)
++{
++	enum fixed_addresses idx;
++	unsigned long vaddr;
++
++	pagefault_disable();
++
++	idx = type + KM_TYPE_NR*smp_processor_id();
++	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++	pgprot_val(prot) |= _PAGE_IOMAP;
++	set_pte_at(&init_mm, vaddr, kmap_pte-idx, pfn_pte_ma(mfn, prot));
++	/*arch_flush_lazy_mmu_mode()*/;
++
++	return (void*) vaddr;
++}
++EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
++
++void
++iounmap_atomic(void *kvaddr, enum km_type type)
++{
++	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
++	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
++
++	/*
++	 * Force other mappings to Oops if they'll try to access this pte
++	 * without first remap it.  Keeping stale mappings around is a bad idea
++	 * also, in case the page changes cacheability attributes or becomes
++	 * a protected page in a hypervisor.
++	 */
++	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
++		kpte_clear_flush(kmap_pte-idx, vaddr);
++
++	/*arch_flush_lazy_mmu_mode();*/
++	pagefault_enable();
++}
++EXPORT_SYMBOL_GPL(iounmap_atomic);
+--- head-2010-01-18.orig/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/ioremap-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -25,20 +25,51 @@
+ 
+ #ifdef CONFIG_X86_64
+ 
+-#ifndef CONFIG_XEN
++static inline int phys_addr_valid(unsigned long addr)
++{
++	return addr < (1UL << boot_cpu_data.x86_phys_bits);
++}
++
++#define phys_base 0
++
+ unsigned long __phys_addr(unsigned long x)
+ {
+-	if (x >= __START_KERNEL_map)
+-		return x - __START_KERNEL_map + phys_base;
+-	return x - PAGE_OFFSET;
++	if (x >= __START_KERNEL_map) {
++		x -= __START_KERNEL_map;
++		VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
++		x += phys_base;
++	} else {
++		VIRTUAL_BUG_ON(x < PAGE_OFFSET);
++		x -= PAGE_OFFSET;
++		VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM :
++					!phys_addr_valid(x));
++	}
++	return x;
+ }
+ EXPORT_SYMBOL(__phys_addr);
+-#endif
+ 
+-static inline int phys_addr_valid(unsigned long addr)
++bool __virt_addr_valid(unsigned long x)
+ {
+-	return addr < (1UL << boot_cpu_data.x86_phys_bits);
++	if (x >= __START_KERNEL_map) {
++		x -= __START_KERNEL_map;
++		if (x >= KERNEL_IMAGE_SIZE)
++			return false;
++		x += phys_base;
++	} else {
++		if (x < PAGE_OFFSET)
++			return false;
++		x -= PAGE_OFFSET;
++		if (system_state == SYSTEM_BOOTING ?
++				x > MAXMEM : !phys_addr_valid(x)) {
++			return false;
++		}
++	}
++
++	return pfn_valid(x >> PAGE_SHIFT);
+ }
++EXPORT_SYMBOL(__virt_addr_valid);
++
++#undef phys_base
+ 
+ #else
+ 
+@@ -47,6 +78,28 @@ static inline int phys_addr_valid(unsign
+ 	return 1;
+ }
+ 
++#ifdef CONFIG_DEBUG_VIRTUAL
++unsigned long __phys_addr(unsigned long x)
++{
++	/* VMALLOC_* aren't constants; not available at the boot time */
++	VIRTUAL_BUG_ON(x < PAGE_OFFSET);
++	VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING &&
++		is_vmalloc_addr((void *) x));
++	return x - PAGE_OFFSET;
++}
++EXPORT_SYMBOL(__phys_addr);
++#endif
++
++bool __virt_addr_valid(unsigned long x)
++{
++	if (x < PAGE_OFFSET)
++		return false;
++	if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x))
++		return false;
++	return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
++}
++EXPORT_SYMBOL(__virt_addr_valid);
++
+ #endif
+ 
+ static int direct_remap_area_pte_fn(pte_t *pte,
+@@ -103,7 +156,7 @@ static int __direct_remap_pfn_range(stru
+ 		 * Fill in the machine address: PTE ptr is done later by
+ 		 * apply_to_page_range().
+ 		 */
+-		pgprot_val(prot) |= _PAGE_IO;
++		pgprot_val(prot) |= _PAGE_IOMAP;
+ 		v->val = __pte_val(pte_mkspecial(pfn_pte_ma(mfn, prot)));
+ 
+ 		mfn++;
+@@ -240,6 +293,25 @@ int page_is_ram(unsigned long pagenr)
+ 	return 0;
+ }
+ 
++int pagerange_is_ram(unsigned long start, unsigned long end)
++{
++	int ram_page = 0, not_rampage = 0;
++	unsigned long page_nr;
++
++	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
++	     ++page_nr) {
++		if (page_is_ram(mfn_to_local_pfn(page_nr)))
++			ram_page = 1;
++		else
++			not_rampage = 1;
++
++		if (ram_page == not_rampage)
++			return -1;
++	}
++
++	return ram_page;
++}
++
+ /*
+  * Fix up the linear direct mapping of the kernel to avoid cache attribute
+  * conflicts.
+@@ -327,6 +399,12 @@ static void __iomem *__ioremap_caller(re
+ 		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
+ 
+ 	/*
++	 * Check if the request spans more than any BAR in the iomem resource
++	 * tree.
++	 */
++	WARN_ON(iomem_map_sanity_check(phys_addr, size));
++
++	/*
+ 	 * Don't allow anybody to remap normal RAM that we're using..
+ 	 */
+ 	for (mfn = PFN_DOWN(phys_addr); mfn < PFN_UP(last_addr); mfn++) {
+@@ -381,16 +459,16 @@ static void __iomem *__ioremap_caller(re
+ 	switch (prot_val) {
+ 	case _PAGE_CACHE_UC:
+ 	default:
+-		prot = PAGE_KERNEL_NOCACHE;
++		prot = PAGE_KERNEL_IO_NOCACHE;
+ 		break;
+ 	case _PAGE_CACHE_UC_MINUS:
+-		prot = PAGE_KERNEL_UC_MINUS;
++		prot = PAGE_KERNEL_IO_UC_MINUS;
+ 		break;
+ 	case _PAGE_CACHE_WC:
+-		prot = PAGE_KERNEL_WC;
++		prot = PAGE_KERNEL_IO_WC;
+ 		break;
+ 	case _PAGE_CACHE_WB:
+-		prot = PAGE_KERNEL;
++		prot = PAGE_KERNEL_IO;
+ 		break;
+ 	}
+ 
+@@ -490,7 +568,7 @@ static void __iomem *ioremap_default(res
+ 					unsigned long size)
+ {
+ 	unsigned long flags;
+-	void *ret;
++	void __iomem *ret;
+ 	int err;
+ 
+ 	/*
+@@ -502,11 +580,11 @@ static void __iomem *ioremap_default(res
+ 	if (err < 0)
+ 		return NULL;
+ 
+-	ret = (void *) __ioremap_caller(phys_addr, size, flags,
+-					__builtin_return_address(0));
++	ret = __ioremap_caller(phys_addr, size, flags,
++			       __builtin_return_address(0));
+ 
+ 	free_memtype(phys_addr, phys_addr + size);
+-	return (void __iomem *)ret;
++	return ret;
+ }
+ #endif
+ 
+@@ -602,7 +680,7 @@ void unxlate_dev_mem_ptr(unsigned long p
+ }
+ #endif
+ 
+-int __initdata early_ioremap_debug;
++static int __initdata early_ioremap_debug;
+ 
+ static int __init early_ioremap_debug_setup(char *str)
+ {
+@@ -721,12 +799,12 @@ static void __init __early_set_fixmap(en
+ }
+ 
+ static inline void __init early_set_fixmap(enum fixed_addresses idx,
+-					unsigned long phys)
++					   unsigned long phys, pgprot_t prot)
+ {
+ 	if (after_paging_init)
+-		set_fixmap(idx, phys);
++		__set_fixmap(idx, phys, prot);
+ 	else
+-		__early_set_fixmap(idx, phys, PAGE_KERNEL);
++		__early_set_fixmap(idx, phys, prot);
+ }
+ 
+ static inline void __init early_clear_fixmap(enum fixed_addresses idx)
+@@ -737,16 +815,22 @@ static inline void __init early_clear_fi
+ 		__early_set_fixmap(idx, 0, __pgprot(0));
+ }
+ 
+-
+-int __initdata early_ioremap_nested;
+-
++static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
++static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+ static int __init check_early_ioremap_leak(void)
+ {
+-	if (!early_ioremap_nested)
++	int count = 0;
++	int i;
++
++	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
++		if (prev_map[i])
++			count++;
++
++	if (!count)
+ 		return 0;
+ 	WARN(1, KERN_WARNING
+ 	       "Debug warning: early ioremap leak of %d areas detected.\n",
+-		early_ioremap_nested);
++		count);
+ 	printk(KERN_WARNING
+ 		"please boot with early_ioremap_debug and report the dmesg.\n");
+ 
+@@ -754,18 +838,33 @@ static int __init check_early_ioremap_le
+ }
+ late_initcall(check_early_ioremap_leak);
+ 
+-void __init *early_ioremap(unsigned long phys_addr, unsigned long size)
++static void __init __iomem *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
+ {
+ 	unsigned long offset, last_addr;
+-	unsigned int nrpages, nesting;
++	unsigned int nrpages;
+ 	enum fixed_addresses idx0, idx;
++	int i, slot;
+ 
+ 	WARN_ON(system_state != SYSTEM_BOOTING);
+ 
+-	nesting = early_ioremap_nested;
++	slot = -1;
++	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
++		if (!prev_map[i]) {
++			slot = i;
++			break;
++		}
++	}
++
++	if (slot < 0) {
++		printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n",
++			 phys_addr, size);
++		WARN_ON(1);
++		return NULL;
++	}
++
+ 	if (early_ioremap_debug) {
+ 		printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
+-		       phys_addr, size, nesting);
++		       phys_addr, size, slot);
+ 		dump_stack();
+ 	}
+ 
+@@ -776,17 +875,13 @@ void __init *early_ioremap(unsigned long
+ 		return NULL;
+ 	}
+ 
+-	if (nesting >= FIX_BTMAPS_NESTING) {
+-		WARN_ON(1);
+-		return NULL;
+-	}
+-	early_ioremap_nested++;
++	prev_size[slot] = size;
+ 	/*
+ 	 * Mappings have to be page-aligned
+ 	 */
+ 	offset = phys_addr & ~PAGE_MASK;
+ 	phys_addr &= PAGE_MASK;
+-	size = PAGE_ALIGN(last_addr) - phys_addr;
++	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+ 
+ 	/*
+ 	 * Mappings have to fit in the FIX_BTMAP area.
+@@ -800,10 +895,10 @@ void __init *early_ioremap(unsigned long
+ 	/*
+ 	 * Ok, go for it..
+ 	 */
+-	idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
++	idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+ 	idx = idx0;
+ 	while (nrpages > 0) {
+-		early_set_fixmap(idx, phys_addr);
++		early_set_fixmap(idx, phys_addr, prot);
+ 		phys_addr += PAGE_SIZE;
+ 		--idx;
+ 		--nrpages;
+@@ -811,24 +906,55 @@ void __init *early_ioremap(unsigned long
+ 	if (early_ioremap_debug)
+ 		printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0));
+ 
+-	return (void *) (offset + fix_to_virt(idx0));
++	prev_map[slot] = (void __iomem *)(offset + fix_to_virt(idx0));
++	return prev_map[slot];
+ }
+ 
+-void __init early_iounmap(void *addr, unsigned long size)
++/* Remap an IO device */
++void __init __iomem *early_ioremap(unsigned long phys_addr, unsigned long size)
++{
++	return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
++}
++
++/* Remap memory */
++void __init __iomem *early_memremap(unsigned long phys_addr, unsigned long size)
++{
++	return __early_ioremap(phys_to_machine(phys_addr), size, PAGE_KERNEL);
++}
++
++void __init early_iounmap(void __iomem *addr, unsigned long size)
+ {
+ 	unsigned long virt_addr;
+ 	unsigned long offset;
+ 	unsigned int nrpages;
+ 	enum fixed_addresses idx;
+-	int nesting;
++	int i, slot;
+ 
+-	nesting = --early_ioremap_nested;
+-	if (WARN_ON(nesting < 0))
++	slot = -1;
++	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
++		if (prev_map[i] == addr) {
++			slot = i;
++			break;
++		}
++	}
++
++	if (slot < 0) {
++		printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n",
++			 addr, size);
++		WARN_ON(1);
++		return;
++	}
++
++	if (prev_size[slot] != size) {
++		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
++			 addr, size, slot, prev_size[slot]);
++		WARN_ON(1);
+ 		return;
++	}
+ 
+ 	if (early_ioremap_debug) {
+ 		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
+-		       size, nesting);
++		       size, slot);
+ 		dump_stack();
+ 	}
+ 
+@@ -840,12 +966,13 @@ void __init early_iounmap(void *addr, un
+ 	offset = virt_addr & ~PAGE_MASK;
+ 	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+ 
+-	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting;
++	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+ 	while (nrpages > 0) {
+ 		early_clear_fixmap(idx);
+ 		--idx;
+ 		--nrpages;
+ 	}
++	prev_map[slot] = NULL;
+ }
+ 
+ void __this_fixmap_does_not_exist(void)
+--- head-2010-01-18.orig/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -25,15 +25,27 @@
+  * The current flushing context - we pass it instead of 5 arguments:
+  */
+ struct cpa_data {
+-	unsigned long	vaddr;
++	unsigned long	*vaddr;
+ 	pgprot_t	mask_set;
+ 	pgprot_t	mask_clr;
+ 	int		numpages;
+-	int		flushtlb;
++	int		flags;
+ 	unsigned long	pfn;
+ 	unsigned	force_split : 1;
++	int		curpage;
+ };
+ 
++/*
++ * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings)
++ * using cpa_lock. So that we don't allow any other cpu, with stale large tlb
++ * entries change the page attribute in parallel to some other cpu
++ * splitting a large page entry along with changing the attribute.
++ */
++static DEFINE_SPINLOCK(cpa_lock);
++
++#define CPA_FLUSHTLB 1
++#define CPA_ARRAY 2
++
+ #ifdef CONFIG_PROC_FS
+ static unsigned long direct_pages_count[PG_LEVEL_NUM];
+ 
+@@ -53,23 +65,22 @@ static void split_page_count(int level)
+ 	direct_pages_count[level - 1] += PTRS_PER_PTE;
+ }
+ 
+-int arch_report_meminfo(char *page)
++void arch_report_meminfo(struct seq_file *m)
+ {
+-	int n = sprintf(page, "DirectMap4k:  %8lu kB\n",
++	seq_printf(m, "DirectMap4k:    %8lu kB\n",
+ 			direct_pages_count[PG_LEVEL_4K] << 2);
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+-	n += sprintf(page + n, "DirectMap2M:  %8lu kB\n",
++	seq_printf(m, "DirectMap2M:    %8lu kB\n",
+ 			direct_pages_count[PG_LEVEL_2M] << 11);
+ #else
+-	n += sprintf(page + n, "DirectMap4M:  %8lu kB\n",
++	seq_printf(m, "DirectMap4M:    %8lu kB\n",
+ 			direct_pages_count[PG_LEVEL_2M] << 12);
+ #endif
+ #ifdef CONFIG_X86_64
+ 	if (direct_gbpages)
+-		n += sprintf(page + n, "DirectMap1G:  %8lu kB\n",
++		seq_printf(m, "DirectMap1G:    %8lu kB\n",
+ 			direct_pages_count[PG_LEVEL_1G] << 20);
+ #endif
+-	return n;
+ }
+ #else
+ static inline void split_page_count(int level) { }
+@@ -84,7 +95,7 @@ static inline unsigned long highmap_star
+ 
+ static inline unsigned long highmap_end_pfn(void)
+ {
+-	return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
++	return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
+ }
+ 
+ #endif
+@@ -190,6 +201,41 @@ static void cpa_flush_range(unsigned lon
+ 	}
+ }
+ 
++static void cpa_flush_array(unsigned long *start, int numpages, int cache)
++{
++	unsigned int i, level;
++	unsigned long *addr;
++
++	BUG_ON(irqs_disabled());
++
++	on_each_cpu(__cpa_flush_range, NULL, 1);
++
++	if (!cache)
++		return;
++
++	/* 4M threshold */
++	if (numpages >= 1024) {
++		if (boot_cpu_data.x86_model >= 4)
++			wbinvd();
++		return;
++	}
++	/*
++	 * We only need to flush on one CPU,
++	 * clflush is a MESI-coherent instruction that
++	 * will cause all other CPUs to flush the same
++	 * cachelines:
++	 */
++	for (i = 0, addr = start; i < numpages; i++, addr++) {
++		pte_t *pte = lookup_address(*addr, &level);
++
++		/*
++		 * Only flush present addresses:
++		 */
++		if (pte && (__pte_val(*pte) & _PAGE_PRESENT))
++			clflush_cache_range((void *) *addr, PAGE_SIZE);
++	}
++}
++
+ /*
+  * Certain areas of memory on x86 require very specific protection flags,
+  * for example the BIOS area or kernel text. Callers don't always get this
+@@ -414,7 +460,7 @@ try_preserve_large_page(pte_t *kpte, uns
+ 		 */
+ 		new_pte = pfn_pte_ma(__pte_mfn(old_pte), canon_pgprot(new_prot));
+ 		__set_pmd_pte(kpte, address, level, new_pte);
+-		cpa->flushtlb = 1;
++		cpa->flags |= CPA_FLUSHTLB;
+ 		do_split = 0;
+ 	}
+ 
+@@ -424,84 +470,6 @@ out_unlock:
+ 	return do_split;
+ }
+ 
+-static LIST_HEAD(page_pool);
+-static unsigned long pool_size, pool_pages, pool_low;
+-static unsigned long pool_used, pool_failed;
+-
+-static void cpa_fill_pool(struct page **ret)
+-{
+-	gfp_t gfp = GFP_KERNEL;
+-	unsigned long flags;
+-	struct page *p;
+-
+-	/*
+-	 * Avoid recursion (on debug-pagealloc) and also signal
+-	 * our priority to get to these pagetables:
+-	 */
+-	if (current->flags & PF_MEMALLOC)
+-		return;
+-	current->flags |= PF_MEMALLOC;
+-
+-	/*
+-	 * Allocate atomically from atomic contexts:
+-	 */
+-	if (in_atomic() || irqs_disabled() || debug_pagealloc)
+-		gfp =  GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+-
+-	while (pool_pages < pool_size || (ret && !*ret)) {
+-		p = alloc_pages(gfp, 0);
+-		if (!p) {
+-			pool_failed++;
+-			break;
+-		}
+-		/*
+-		 * If the call site needs a page right now, provide it:
+-		 */
+-		if (ret && !*ret) {
+-			*ret = p;
+-			continue;
+-		}
+-		spin_lock_irqsave(&pgd_lock, flags);
+-		list_add(&p->lru, &page_pool);
+-		pool_pages++;
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-	}
+-
+-	current->flags &= ~PF_MEMALLOC;
+-}
+-
+-#define SHIFT_MB		(20 - PAGE_SHIFT)
+-#define ROUND_MB_GB		((1 << 10) - 1)
+-#define SHIFT_MB_GB		10
+-#define POOL_PAGES_PER_GB	16
+-
+-void __init cpa_init(void)
+-{
+-	struct sysinfo si;
+-	unsigned long gb;
+-
+-	si_meminfo(&si);
+-	/*
+-	 * Calculate the number of pool pages:
+-	 *
+-	 * Convert totalram (nr of pages) to MiB and round to the next
+-	 * GiB. Shift MiB to Gib and multiply the result by
+-	 * POOL_PAGES_PER_GB:
+-	 */
+-	if (debug_pagealloc) {
+-		gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB;
+-		pool_size = POOL_PAGES_PER_GB * gb;
+-	} else {
+-		pool_size = 1;
+-	}
+-	pool_low = pool_size;
+-
+-	cpa_fill_pool(NULL);
+-	printk(KERN_DEBUG
+-	       "CPA: page pool initialized %lu of %lu pages preallocated\n",
+-	       pool_pages, pool_size);
+-}
+-
+ static int split_large_page(pte_t *kpte, unsigned long address)
+ {
+ 	unsigned long flags, mfn, mfninc = 1;
+@@ -510,28 +478,15 @@ static int split_large_page(pte_t *kpte,
+ 	pgprot_t ref_prot;
+ 	struct page *base;
+ 
+-	/*
+-	 * Get a page from the pool. The pool list is protected by the
+-	 * pgd_lock, which we have to take anyway for the split
+-	 * operation:
+-	 */
+-	spin_lock_irqsave(&pgd_lock, flags);
+-	if (list_empty(&page_pool)) {
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-		base = NULL;
+-		cpa_fill_pool(&base);
+-		if (!base)
+-			return -ENOMEM;
+-		spin_lock_irqsave(&pgd_lock, flags);
+-	} else {
+-		base = list_first_entry(&page_pool, struct page, lru);
+-		list_del(&base->lru);
+-		pool_pages--;
+-
+-		if (pool_pages < pool_low)
+-			pool_low = pool_pages;
+-	}
++	if (!debug_pagealloc)
++		spin_unlock(&cpa_lock);
++	base = alloc_pages(GFP_KERNEL, 0);
++	if (!debug_pagealloc)
++		spin_lock(&cpa_lock);
++	if (!base)
++		return -ENOMEM;
+ 
++	spin_lock_irqsave(&pgd_lock, flags);
+ 	/*
+ 	 * Check for races, another CPU might have split this page
+ 	 * up for us already:
+@@ -592,11 +547,8 @@ out_unlock:
+ 	 * If we dropped out via the lookup_address check under
+ 	 * pgd_lock then stick the page back into the pool:
+ 	 */
+-	if (base) {
+-		list_add(&base->lru, &page_pool);
+-		pool_pages++;
+-	} else
+-		pool_used++;
++	if (base)
++		__free_page(base);
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+ 
+ 	return 0;
+@@ -604,11 +556,16 @@ out_unlock:
+ 
+ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ {
+-	unsigned long address = cpa->vaddr;
++	unsigned long address;
+ 	int do_split, err;
+ 	unsigned int level;
+ 	pte_t *kpte, old_pte;
+ 
++	if (cpa->flags & CPA_ARRAY)
++		address = cpa->vaddr[cpa->curpage];
++	else
++		address = *cpa->vaddr;
++
+ repeat:
+ 	kpte = lookup_address(address, &level);
+ 	if (!kpte)
+@@ -620,7 +577,7 @@ repeat:
+ 			return 0;
+ 		WARN(1, KERN_WARNING "CPA: called for zero pte. "
+ 		       "vaddr = %lx cpa->vaddr = %lx\n", address,
+-		       cpa->vaddr);
++		       *cpa->vaddr);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -647,7 +604,7 @@ repeat:
+ 		 */
+ 		if (__pte_val(old_pte) != __pte_val(new_pte)) {
+ 			set_pte_atomic(kpte, new_pte);
+-			cpa->flushtlb = 1;
++			cpa->flags |= CPA_FLUSHTLB;
+ 		}
+ 		cpa->numpages = 1;
+ 		return 0;
+@@ -671,7 +628,25 @@ repeat:
+ 	 */
+ 	err = split_large_page(kpte, address);
+ 	if (!err) {
+-		cpa->flushtlb = 1;
++		/*
++	 	 * Do a global flush tlb after splitting the large page
++	 	 * and before we do the actual change page attribute in the PTE.
++	 	 *
++	 	 * With out this, we violate the TLB application note, that says
++	 	 * "The TLBs may contain both ordinary and large-page
++		 *  translations for a 4-KByte range of linear addresses. This
++		 *  may occur if software modifies the paging structures so that
++		 *  the page size used for the address range changes. If the two
++		 *  translations differ with respect to page frame or attributes
++		 *  (e.g., permissions), processor behavior is undefined and may
++		 *  be implementation-specific."
++	 	 *
++	 	 * We do this global tlb flush inside the cpa_lock, so that we
++		 * don't allow any other cpu, with stale tlb entries change the
++		 * page attribute in parallel, that also falls into the
++		 * just split large page entry.
++	 	 */
++		flush_tlb_all();
+ 		goto repeat;
+ 	}
+ 
+@@ -684,6 +659,7 @@ static int cpa_process_alias(struct cpa_
+ {
+ 	struct cpa_data alias_cpa;
+ 	int ret = 0;
++	unsigned long temp_cpa_vaddr, vaddr;
+ 
+ 	if (cpa->pfn >= max_pfn_mapped)
+ 		return 0;
+@@ -696,16 +672,24 @@ static int cpa_process_alias(struct cpa_
+ 	 * No need to redo, when the primary call touched the direct
+ 	 * mapping already:
+ 	 */
+-	if (!(within(cpa->vaddr, PAGE_OFFSET,
++	if (cpa->flags & CPA_ARRAY)
++		vaddr = cpa->vaddr[cpa->curpage];
++	else
++		vaddr = *cpa->vaddr;
++
++	if (!(within(vaddr, PAGE_OFFSET,
+ 		    PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
+ #ifdef CONFIG_X86_64
+-		|| within(cpa->vaddr, PAGE_OFFSET + (1UL<<32),
++		|| within(vaddr, PAGE_OFFSET + (1UL<<32),
+ 		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
+ #endif
+ 	)) {
+ 
+ 		alias_cpa = *cpa;
+-		alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
++		temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
++		alias_cpa.vaddr = &temp_cpa_vaddr;
++		alias_cpa.flags &= ~CPA_ARRAY;
++
+ 
+ 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+ 	}
+@@ -717,7 +701,7 @@ static int cpa_process_alias(struct cpa_
+ 	 * No need to redo, when the primary call touched the high
+ 	 * mapping already:
+ 	 */
+-	if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end))
++	if (within(vaddr, (unsigned long) _text, (unsigned long) _end))
+ 		return 0;
+ 
+ 	/*
+@@ -728,8 +712,9 @@ static int cpa_process_alias(struct cpa_
+ 		return 0;
+ 
+ 	alias_cpa = *cpa;
+-	alias_cpa.vaddr =
+-		(cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
++	temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map;
++	alias_cpa.vaddr = &temp_cpa_vaddr;
++	alias_cpa.flags &= ~CPA_ARRAY;
+ 
+ 	/*
+ 	 * The high mapping range is imprecise, so ignore the return value.
+@@ -749,8 +734,15 @@ static int __change_page_attr_set_clr(st
+ 		 * preservation check.
+ 		 */
+ 		cpa->numpages = numpages;
++		/* for array changes, we can't use large page */
++		if (cpa->flags & CPA_ARRAY)
++			cpa->numpages = 1;
+ 
++		if (!debug_pagealloc)
++			spin_lock(&cpa_lock);
+ 		ret = __change_page_attr(cpa, checkalias);
++		if (!debug_pagealloc)
++			spin_unlock(&cpa_lock);
+ 		if (ret)
+ 			return ret;
+ 
+@@ -767,7 +759,11 @@ static int __change_page_attr_set_clr(st
+ 		 */
+ 		BUG_ON(cpa->numpages > numpages);
+ 		numpages -= cpa->numpages;
+-		cpa->vaddr += cpa->numpages * PAGE_SIZE;
++		if (cpa->flags & CPA_ARRAY)
++			cpa->curpage++;
++		else
++			*cpa->vaddr += cpa->numpages * PAGE_SIZE;
++
+ 	}
+ 	return 0;
+ }
+@@ -778,9 +774,9 @@ static inline int cache_attr(pgprot_t at
+ 		(_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
+ }
+ 
+-static int change_page_attr_set_clr(unsigned long addr, int numpages,
++static int change_page_attr_set_clr(unsigned long *addr, int numpages,
+ 				    pgprot_t mask_set, pgprot_t mask_clr,
+-				    int force_split)
++				    int force_split, int array)
+ {
+ 	struct cpa_data cpa;
+ 	int ret, cache, checkalias;
+@@ -795,21 +791,40 @@ static int change_page_attr_set_clr(unsi
+ 		return 0;
+ 
+ 	/* Ensure we are PAGE_SIZE aligned */
+-	if (addr & ~PAGE_MASK) {
+-		addr &= PAGE_MASK;
+-		/*
+-		 * People should not be passing in unaligned addresses:
+-		 */
+-		WARN_ON_ONCE(1);
++	if (!array) {
++		if (*addr & ~PAGE_MASK) {
++			*addr &= PAGE_MASK;
++			/*
++			 * People should not be passing in unaligned addresses:
++			 */
++			WARN_ON_ONCE(1);
++		}
++	} else {
++		int i;
++		for (i = 0; i < numpages; i++) {
++			if (addr[i] & ~PAGE_MASK) {
++				addr[i] &= PAGE_MASK;
++				WARN_ON_ONCE(1);
++			}
++		}
+ 	}
+ 
++	/* Must avoid aliasing mappings in the highmem code */
++	kmap_flush_unused();
++
++	vm_unmap_aliases();
++
+ 	cpa.vaddr = addr;
+ 	cpa.numpages = numpages;
+ 	cpa.mask_set = mask_set;
+ 	cpa.mask_clr = mask_clr;
+-	cpa.flushtlb = 0;
++	cpa.flags = 0;
++	cpa.curpage = 0;
+ 	cpa.force_split = force_split;
+ 
++	if (array)
++		cpa.flags |= CPA_ARRAY;
++
+ 	/* No alias checking for _NX bit modifications */
+ 	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+ 
+@@ -818,7 +833,7 @@ static int change_page_attr_set_clr(unsi
+ 	/*
+ 	 * Check whether we really changed something:
+ 	 */
+-	if (!cpa.flushtlb)
++	if (!(cpa.flags & CPA_FLUSHTLB))
+ 		goto out;
+ 
+ 	/*
+@@ -833,27 +848,30 @@ static int change_page_attr_set_clr(unsi
+ 	 * error case we fall back to cpa_flush_all (which uses
+ 	 * wbindv):
+ 	 */
+-	if (!ret && cpu_has_clflush)
+-		cpa_flush_range(addr, numpages, cache);
+-	else
++	if (!ret && cpu_has_clflush) {
++		if (cpa.flags & CPA_ARRAY)
++			cpa_flush_array(addr, numpages, cache);
++		else
++			cpa_flush_range(*addr, numpages, cache);
++	} else
+ 		cpa_flush_all(cache);
+ 
+ out:
+-	cpa_fill_pool(NULL);
+-
+ 	return ret;
+ }
+ 
+-static inline int change_page_attr_set(unsigned long addr, int numpages,
+-				       pgprot_t mask)
++static inline int change_page_attr_set(unsigned long *addr, int numpages,
++				       pgprot_t mask, int array)
+ {
+-	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0);
++	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0,
++		array);
+ }
+ 
+-static inline int change_page_attr_clear(unsigned long addr, int numpages,
+-					 pgprot_t mask)
++static inline int change_page_attr_clear(unsigned long *addr, int numpages,
++					 pgprot_t mask, int array)
+ {
+-	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
++	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0,
++		array);
+ }
+ 
+ #ifdef CONFIG_XEN
+@@ -906,8 +924,8 @@ int _set_memory_uc(unsigned long addr, i
+ 	/*
+ 	 * for now UC MINUS. see comments in ioremap_nocache()
+ 	 */
+-	return change_page_attr_set(addr, numpages,
+-				    __pgprot(_PAGE_CACHE_UC_MINUS));
++	return change_page_attr_set(&addr, numpages,
++				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
+ }
+ 
+ int set_memory_uc(unsigned long addr, int numpages)
+@@ -923,10 +941,48 @@ int set_memory_uc(unsigned long addr, in
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+ 
++int set_memory_array_uc(unsigned long *addr, int addrinarray)
++{
++	unsigned long start;
++	unsigned long end;
++	int i;
++	/*
++	 * for now UC MINUS. see comments in ioremap_nocache()
++	 */
++	for (i = 0; i < addrinarray; i++) {
++		start = __pa(addr[i]);
++		for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
++			if (end != __pa(addr[i + 1]))
++				break;
++			i++;
++		}
++		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
++			goto out;
++	}
++
++	return change_page_attr_set(addr, addrinarray,
++				    __pgprot(_PAGE_CACHE_UC_MINUS), 1);
++out:
++	for (i = 0; i < addrinarray; i++) {
++		unsigned long tmp = __pa(addr[i]);
++
++		if (tmp == start)
++			break;
++		for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
++			if (end != __pa(addr[i + 1]))
++				break;
++			i++;
++		}
++		free_memtype(tmp, end);
++	}
++	return -EINVAL;
++}
++EXPORT_SYMBOL(set_memory_array_uc);
++
+ int _set_memory_wc(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_set(addr, numpages,
+-				    __pgprot(_PAGE_CACHE_WC));
++	return change_page_attr_set(&addr, numpages,
++				    __pgprot(_PAGE_CACHE_WC), 0);
+ }
+ 
+ int set_memory_wc(unsigned long addr, int numpages)
+@@ -944,8 +1000,8 @@ EXPORT_SYMBOL(set_memory_wc);
+ 
+ int _set_memory_wb(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_clear(addr, numpages,
+-				      __pgprot(_PAGE_CACHE_MASK));
++	return change_page_attr_clear(&addr, numpages,
++				      __pgprot(_PAGE_CACHE_MASK), 0);
+ }
+ 
+ int set_memory_wb(unsigned long addr, int numpages)
+@@ -956,37 +1012,59 @@ int set_memory_wb(unsigned long addr, in
+ }
+ EXPORT_SYMBOL(set_memory_wb);
+ 
++int set_memory_array_wb(unsigned long *addr, int addrinarray)
++{
++	int i;
++
++	for (i = 0; i < addrinarray; i++) {
++		unsigned long start = __pa(addr[i]);
++		unsigned long end;
++
++		for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
++			if (end != __pa(addr[i + 1]))
++				break;
++			i++;
++		}
++		free_memtype(start, end);
++	}
++	return change_page_attr_clear(addr, addrinarray,
++				      __pgprot(_PAGE_CACHE_MASK), 1);
++}
++EXPORT_SYMBOL(set_memory_array_wb);
++
+ int set_memory_x(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX));
++	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0);
+ }
+ EXPORT_SYMBOL(set_memory_x);
+ 
+ int set_memory_nx(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX));
++	return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0);
+ }
+ EXPORT_SYMBOL(set_memory_nx);
+ 
+ int set_memory_ro(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW));
++	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0);
+ }
++EXPORT_SYMBOL_GPL(set_memory_ro);
+ 
+ int set_memory_rw(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW));
++	return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0);
+ }
++EXPORT_SYMBOL_GPL(set_memory_rw);
+ 
+ int set_memory_np(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
++	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0);
+ }
+ 
+ int set_memory_4k(unsigned long addr, int numpages)
+ {
+-	return change_page_attr_set_clr(addr, numpages, __pgprot(0),
+-					__pgprot(0), 1);
++	return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
++					__pgprot(0), 1, 0);
+ }
+ 
+ int set_pages_uc(struct page *page, int numpages)
+@@ -1039,22 +1117,38 @@ int set_pages_rw(struct page *page, int 
+ 
+ static int __set_pages_p(struct page *page, int numpages)
+ {
+-	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++	unsigned long tempaddr = (unsigned long) page_address(page);
++	struct cpa_data cpa = { .vaddr = &tempaddr,
+ 				.numpages = numpages,
+ 				.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
+-				.mask_clr = __pgprot(0)};
++				.mask_clr = __pgprot(0),
++				.flags = 0};
+ 
+-	return __change_page_attr_set_clr(&cpa, 1);
++	/*
++	 * No alias checking needed for setting present flag. otherwise,
++	 * we may need to break large pages for 64-bit kernel text
++	 * mappings (this adds to complexity if we want to do this from
++	 * atomic context especially). Let's keep it simple!
++	 */
++	return __change_page_attr_set_clr(&cpa, 0);
+ }
+ 
+ static int __set_pages_np(struct page *page, int numpages)
+ {
+-	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++	unsigned long tempaddr = (unsigned long) page_address(page);
++	struct cpa_data cpa = { .vaddr = &tempaddr,
+ 				.numpages = numpages,
+ 				.mask_set = __pgprot(0),
+-				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)};
++				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
++				.flags = 0};
+ 
+-	return __change_page_attr_set_clr(&cpa, 1);
++	/*
++	 * No alias checking needed for setting not present flag. otherwise,
++	 * we may need to break large pages for 64-bit kernel text
++	 * mappings (this adds to complexity if we want to do this from
++	 * atomic context especially). Let's keep it simple!
++	 */
++	return __change_page_attr_set_clr(&cpa, 0);
+ }
+ 
+ void kernel_map_pages(struct page *page, int numpages, int enable)
+@@ -1074,11 +1168,8 @@ void kernel_map_pages(struct page *page,
+ 
+ 	/*
+ 	 * The return value is ignored as the calls cannot fail.
+-	 * Large pages are kept enabled at boot time, and are
+-	 * split up quickly with DEBUG_PAGEALLOC. If a splitup
+-	 * fails here (due to temporary memory shortage) no damage
+-	 * is done because we just keep the largepage intact up
+-	 * to the next attempt when it will likely be split up:
++	 * Large pages for identity mappings are not used at boot time
++	 * and hence no memory allocations during large page split.
+ 	 */
+ 	if (enable)
+ 		__set_pages_p(page, numpages);
+@@ -1090,53 +1181,8 @@ void kernel_map_pages(struct page *page,
+ 	 * but that can deadlock->flush only current cpu:
+ 	 */
+ 	__flush_tlb_all();
+-
+-	/*
+-	 * Try to refill the page pool here. We can do this only after
+-	 * the tlb flush.
+-	 */
+-	cpa_fill_pool(NULL);
+-}
+-
+-#ifdef CONFIG_DEBUG_FS
+-static int dpa_show(struct seq_file *m, void *v)
+-{
+-	seq_puts(m, "DEBUG_PAGEALLOC\n");
+-	seq_printf(m, "pool_size     : %lu\n", pool_size);
+-	seq_printf(m, "pool_pages    : %lu\n", pool_pages);
+-	seq_printf(m, "pool_low      : %lu\n", pool_low);
+-	seq_printf(m, "pool_used     : %lu\n", pool_used);
+-	seq_printf(m, "pool_failed   : %lu\n", pool_failed);
+-
+-	return 0;
+ }
+ 
+-static int dpa_open(struct inode *inode, struct file *filp)
+-{
+-	return single_open(filp, dpa_show, NULL);
+-}
+-
+-static const struct file_operations dpa_fops = {
+-	.open		= dpa_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= single_release,
+-};
+-
+-static int __init debug_pagealloc_proc_init(void)
+-{
+-	struct dentry *de;
+-
+-	de = debugfs_create_file("debug_pagealloc", 0600, NULL, NULL,
+-				 &dpa_fops);
+-	if (!de)
+-		return -ENOMEM;
+-
+-	return 0;
+-}
+-__initcall(debug_pagealloc_proc_init);
+-#endif
+-
+ #ifdef CONFIG_HIBERNATION
+ 
+ bool kernel_page_present(struct page *page)
+--- head-2010-01-18.orig/arch/x86/mm/pat-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pat-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -7,24 +7,24 @@
+  * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen.
+  */
+ 
+-#include <linux/mm.h>
++#include <linux/seq_file.h>
++#include <linux/bootmem.h>
++#include <linux/debugfs.h>
+ #include <linux/kernel.h>
+ #include <linux/gfp.h>
++#include <linux/mm.h>
+ #include <linux/fs.h>
+-#include <linux/bootmem.h>
+-#include <linux/debugfs.h>
+-#include <linux/seq_file.h>
+ 
+-#include <asm/msr.h>
+-#include <asm/tlbflush.h>
++#include <asm/cacheflush.h>
+ #include <asm/processor.h>
+-#include <asm/page.h>
++#include <asm/tlbflush.h>
+ #include <asm/pgtable.h>
+-#include <asm/pat.h>
+-#include <asm/e820.h>
+-#include <asm/cacheflush.h>
+ #include <asm/fcntl.h>
++#include <asm/e820.h>
+ #include <asm/mtrr.h>
++#include <asm/page.h>
++#include <asm/msr.h>
++#include <asm/pat.h>
+ #include <asm/io.h>
+ 
+ #ifdef CONFIG_X86_PAT
+@@ -46,6 +46,7 @@ early_param("nopat", nopat);
+ 
+ 
+ static int debug_enable;
++
+ static int __init pat_debug_setup(char *str)
+ {
+ 	debug_enable = 1;
+@@ -157,14 +158,14 @@ static char *cattr_name(unsigned long fl
+  */
+ 
+ struct memtype {
+-	u64 start;
+-	u64 end;
+-	unsigned long type;
+-	struct list_head nd;
++	u64			start;
++	u64			end;
++	unsigned long		type;
++	struct list_head	nd;
+ };
+ 
+ static LIST_HEAD(memtype_list);
+-static DEFINE_SPINLOCK(memtype_lock); 	/* protects memtype list */
++static DEFINE_SPINLOCK(memtype_lock);	/* protects memtype list */
+ 
+ /*
+  * Does intersection of PAT memory type and MTRR memory type and returns
+@@ -192,8 +193,8 @@ static unsigned long pat_x_mtrr_type(u64
+ 	return req_type;
+ }
+ 
+-static int chk_conflict(struct memtype *new, struct memtype *entry,
+-			unsigned long *type)
++static int
++chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type)
+ {
+ 	if (new->type != entry->type) {
+ 		if (type) {
+@@ -223,6 +224,66 @@ static struct memtype *cached_entry;
+ static u64 cached_start;
+ 
+ /*
++ * For RAM pages, mark the pages as non WB memory type using
++ * PageNonWB (PG_arch_1). We allow only one set_memory_uc() or
++ * set_memory_wc() on a RAM page at a time before marking it as WB again.
++ * This is ok, because only one driver will be owning the page and
++ * doing set_memory_*() calls.
++ *
++ * For now, we use PageNonWB to track that the RAM page is being mapped
++ * as non WB. In future, we will have to use one more flag
++ * (or some other mechanism in page_struct) to distinguish between
++ * UC and WC mapping.
++ */
++static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
++				  unsigned long *new_type)
++{
++	struct page *page;
++	u64 pfn, end_pfn;
++
++	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
++		page = pfn_to_page(pfn);
++		if (page_mapped(page) || PageNonWB(page))
++			goto out;
++
++		SetPageNonWB(page);
++	}
++	return 0;
++
++out:
++	end_pfn = pfn;
++	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
++		page = pfn_to_page(pfn);
++		ClearPageNonWB(page);
++	}
++
++	return -EINVAL;
++}
++
++static int free_ram_pages_type(u64 start, u64 end)
++{
++	struct page *page;
++	u64 pfn, end_pfn;
++
++	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
++		page = pfn_to_page(pfn);
++		if (page_mapped(page) || !PageNonWB(page))
++			goto out;
++
++		ClearPageNonWB(page);
++	}
++	return 0;
++
++out:
++	end_pfn = pfn;
++	for (pfn = (start >> PAGE_SHIFT); pfn < end_pfn; ++pfn) {
++		page = pfn_to_page(pfn);
++		SetPageNonWB(page);
++	}
++	return -EINVAL;
++}
++
++/*
+  * req_type typically has one of the:
+  * - _PAGE_CACHE_WB
+  * - _PAGE_CACHE_WC
+@@ -238,14 +299,15 @@ static u64 cached_start;
+  * it will return a negative return value.
+  */
+ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
+-			unsigned long *new_type)
++		    unsigned long *new_type)
+ {
+ 	struct memtype *new, *entry;
+ 	unsigned long actual_type;
+ 	struct list_head *where;
++	int is_range_ram;
+ 	int err = 0;
+ 
+- 	BUG_ON(start >= end); /* end is exclusive */
++	BUG_ON(start >= end); /* end is exclusive */
+ 
+ 	if (!pat_enabled) {
+ 		/* This is identical to page table setting without PAT */
+@@ -278,17 +340,24 @@ int reserve_memtype(u64 start, u64 end, 
+ 			actual_type = _PAGE_CACHE_WB;
+ 		else
+ 			actual_type = _PAGE_CACHE_UC_MINUS;
+-	} else
++	} else {
+ 		actual_type = pat_x_mtrr_type(start, end,
+ 					      req_type & _PAGE_CACHE_MASK);
++	}
++
++	is_range_ram = pagerange_is_ram(start, end);
++	if (is_range_ram == 1)
++		return reserve_ram_pages_type(start, end, req_type, new_type);
++	else if (is_range_ram < 0)
++		return -EINVAL;
+ 
+ 	new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+ 	if (!new)
+ 		return -ENOMEM;
+ 
+-	new->start = start;
+-	new->end = end;
+-	new->type = actual_type;
++	new->start	= start;
++	new->end	= end;
++	new->type	= actual_type;
+ 
+ 	if (new_type)
+ 		*new_type = actual_type;
+@@ -347,6 +416,7 @@ int reserve_memtype(u64 start, u64 end, 
+ 		       start, end, cattr_name(new->type), cattr_name(req_type));
+ 		kfree(new);
+ 		spin_unlock(&memtype_lock);
++
+ 		return err;
+ 	}
+ 
+@@ -370,6 +440,7 @@ int free_memtype(u64 start, u64 end)
+ {
+ 	struct memtype *entry;
+ 	int err = -EINVAL;
++	int is_range_ram;
+ 
+ 	if (!pat_enabled)
+ 		return 0;
+@@ -378,6 +449,12 @@ int free_memtype(u64 start, u64 end)
+ 	if (is_ISA_range(start, end - 1))
+ 		return 0;
+ 
++	is_range_ram = pagerange_is_ram(start, end);
++	if (is_range_ram == 1)
++		return free_ram_pages_type(start, end);
++	else if (is_range_ram < 0)
++		return -EINVAL;
++
+ 	spin_lock(&memtype_lock);
+ 	list_for_each_entry(entry, &memtype_list, nd) {
+ 		if (entry->start == start && entry->end == end) {
+@@ -398,6 +475,7 @@ int free_memtype(u64 start, u64 end)
+ 	}
+ 
+ 	dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
++
+ 	return err;
+ }
+ 
+@@ -415,12 +493,16 @@ static inline int range_is_allowed(unsig
+ 	return 1;
+ }
+ #else
++/* This check is needed to avoid cache aliasing when PAT is enabled */
+ static inline int range_is_allowed(unsigned long mfn, unsigned long size)
+ {
+ 	u64 from = ((u64)mfn) << PAGE_SHIFT;
+ 	u64 to = from + size;
+ 	u64 cursor = from;
+ 
++	if (!pat_enabled)
++		return 1;
++
+ 	while (cursor < to) {
+ 		if (!devmem_is_allowed(mfn)) {
+ 			printk(KERN_INFO
+@@ -504,9 +586,9 @@ int phys_mem_access_prot_allowed(struct 
+ 
+ void map_devmem(unsigned long mfn, unsigned long size, pgprot_t vma_prot)
+ {
++	unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
+ 	u64 addr = (u64)mfn << PAGE_SHIFT;
+ 	unsigned long flags;
+-	unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
+ 
+ 	reserve_memtype(addr, addr + size, want_flags, &flags);
+ 	if (flags != want_flags) {
+@@ -526,7 +608,7 @@ void unmap_devmem(unsigned long mfn, uns
+ 	free_memtype(addr, addr + size);
+ }
+ 
+-#if defined(CONFIG_DEBUG_FS)
++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
+ 
+ /* get Nth element of the linked list */
+ static struct memtype *memtype_get_idx(loff_t pos)
+@@ -549,6 +631,7 @@ static struct memtype *memtype_get_idx(l
+ 	}
+ 	spin_unlock(&memtype_lock);
+ 	kfree(print_entry);
++
+ 	return NULL;
+ }
+ 
+@@ -579,6 +662,7 @@ static int memtype_seq_show(struct seq_f
+ 	seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type),
+ 			print_entry->start, print_entry->end);
+ 	kfree(print_entry);
++
+ 	return 0;
+ }
+ 
+@@ -610,4 +694,4 @@ static int __init pat_memtype_list_init(
+ 
+ late_initcall(pat_memtype_list_init);
+ 
+-#endif /* CONFIG_DEBUG_FS */
++#endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */
+--- head-2010-01-18.orig/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -129,7 +129,7 @@ void __pud_free_tlb(struct mmu_gather *t
+ static void _pin_lock(struct mm_struct *mm, int lock) {
+ 	if (lock)
+ 		spin_lock(&mm->page_table_lock);
+-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
++#if USE_SPLIT_PTLOCKS
+ 	/* While mm->page_table_lock protects us against insertions and
+ 	 * removals of higher level page table pages, it doesn't protect
+ 	 * against updates of pte-s. Such updates, however, require the
+@@ -408,10 +408,8 @@ static inline void pgd_list_del(pgd_t *p
+ #define UNSHARED_PTRS_PER_PGD				\
+ 	(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
+ 
+-static void pgd_ctor(void *p)
++static void pgd_ctor(pgd_t *pgd)
+ {
+-	pgd_t *pgd = p;
+-
+ 	pgd_test_and_unpin(pgd);
+ 
+ 	/* If the pgd points to a shared pagetable level (either the
+@@ -440,7 +438,7 @@ static void pgd_ctor(void *p)
+ 		pgd_list_add(pgd);
+ }
+ 
+-static void pgd_dtor(void *pgd)
++static void pgd_dtor(pgd_t *pgd)
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -122,7 +122,6 @@ void __init reserve_top_address(unsigned
+ 	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+ 	       (int)-reserve);
+ 	__FIXADDR_TOP = -reserve - PAGE_SIZE;
+-	__VMALLOC_RESERVE += reserve;
+ }
+ 
+ /*
+@@ -135,7 +134,8 @@ static int __init parse_vmalloc(char *ar
+ 	if (!arg)
+ 		return -EINVAL;
+ 
+-	__VMALLOC_RESERVE = memparse(arg, &arg);
++	/* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/
++	__VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET;
+ 	return 0;
+ }
+ early_param("vmalloc", parse_vmalloc);
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:47.000000000 +0100
+@@ -499,7 +499,7 @@ static int pirq_amd756_get(struct pci_de
+ 	if (pirq <= 4)
+ 		irq = read_config_nybble(router, 0x56, pirq - 1);
+ 	dev_info(&dev->dev,
+-		 "AMD756: dev [%04x/%04x], router PIRQ %d get IRQ %d\n",
++		 "AMD756: dev [%04x:%04x], router PIRQ %d get IRQ %d\n",
+ 		 dev->vendor, dev->device, pirq, irq);
+ 	return irq;
+ }
+@@ -507,7 +507,7 @@ static int pirq_amd756_get(struct pci_de
+ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+ {
+ 	dev_info(&dev->dev,
+-		 "AMD756: dev [%04x/%04x], router PIRQ %d set IRQ %d\n",
++		 "AMD756: dev [%04x:%04x], router PIRQ %d set IRQ %d\n",
+ 		 dev->vendor, dev->device, pirq, irq);
+ 	if (pirq <= 4)
+ 		write_config_nybble(router, 0x56, pirq - 1, irq);
+@@ -596,13 +596,20 @@ static __init int intel_router_probe(str
+ 	case PCI_DEVICE_ID_INTEL_ICH10_1:
+ 	case PCI_DEVICE_ID_INTEL_ICH10_2:
+ 	case PCI_DEVICE_ID_INTEL_ICH10_3:
+-	case PCI_DEVICE_ID_INTEL_PCH_0:
+-	case PCI_DEVICE_ID_INTEL_PCH_1:
+ 		r->name = "PIIX/ICH";
+ 		r->get = pirq_piix_get;
+ 		r->set = pirq_piix_set;
+ 		return 1;
+ 	}
++
++	if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) &&
++		(device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) {
++		r->name = "PIIX/ICH";
++		r->get = pirq_piix_get;
++		r->set = pirq_piix_set;
++		return 1;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -829,7 +836,7 @@ static void __init pirq_find_router(stru
+ 	r->get = NULL;
+ 	r->set = NULL;
+ 
+-	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
++	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for [%04x:%04x]\n",
+ 	    rt->rtr_vendor, rt->rtr_device);
+ 
+ 	pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
+@@ -849,7 +856,7 @@ static void __init pirq_find_router(stru
+ 			h->probe(r, pirq_router_dev, pirq_router_dev->device))
+ 			break;
+ 	}
+-	dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x/%04x]\n",
++	dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n",
+ 		 pirq_router.name,
+ 		 pirq_router_dev->vendor, pirq_router_dev->device);
+ 
+@@ -1049,35 +1056,44 @@ static void __init pcibios_fixup_irqs(vo
+ 		if (io_apic_assign_pci_irqs) {
+ 			int irq;
+ 
+-			if (pin) {
+-				/*
+-				 * interrupt pins are numbered starting
+-				 * from 1
+-				 */
+-				pin--;
+-				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+-					PCI_SLOT(dev->devfn), pin);
+-	/*
+-	 * Busses behind bridges are typically not listed in the MP-table.
+-	 * In this case we have to look up the IRQ based on the parent bus,
+-	 * parent slot, and pin number. The SMP code detects such bridged
+-	 * busses itself so we should get into this branch reliably.
+-	 */
+-				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+-					struct pci_dev *bridge = dev->bus->self;
++			if (!pin)
++				continue;
++
++			/*
++			 * interrupt pins are numbered starting from 1
++			 */
++			pin--;
++			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
++				PCI_SLOT(dev->devfn), pin);
++			/*
++			 * Busses behind bridges are typically not listed in the
++			 * MP-table.  In this case we have to look up the IRQ
++			 * based on the parent bus, parent slot, and pin number.
++			 * The SMP code detects such bridged busses itself so we
++			 * should get into this branch reliably.
++			 */
++			if (irq < 0 && dev->bus->parent) {
++				/* go back to the bridge */
++				struct pci_dev *bridge = dev->bus->self;
++				int bus;
+ 
+-					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+-					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+-							PCI_SLOT(bridge->devfn), pin);
+-					if (irq >= 0)
+-						dev_warn(&dev->dev, "using bridge %s INT %c to get IRQ %d\n",
+-							 pci_name(bridge),
+-							 'A' + pin, irq);
+-				}
+-				if (irq >= 0) {
+-					dev_info(&dev->dev, "PCI->APIC IRQ transform: INT %c -> IRQ %d\n", 'A' + pin, irq);
+-					dev->irq = irq;
+-				}
++				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
++				bus = bridge->bus->number;
++				irq = IO_APIC_get_PCI_irq_vector(bus,
++						PCI_SLOT(bridge->devfn), pin);
++				if (irq >= 0)
++					dev_warn(&dev->dev,
++						"using bridge %s INT %c to "
++							"get IRQ %d\n",
++						 pci_name(bridge),
++						 'A' + pin, irq);
++			}
++			if (irq >= 0) {
++				dev_info(&dev->dev,
++					"PCI->APIC IRQ transform: INT %c "
++						"-> IRQ %d\n",
++					'A' + pin, irq);
++				dev->irq = irq;
+ 			}
+ 		}
+ #endif
+--- head-2010-01-18.orig/arch/x86/xen/Kconfig	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/arch/x86/xen/Kconfig	2009-11-06 10:51:47.000000000 +0100
+@@ -31,7 +31,7 @@ config XEN_SAVE_RESTORE
+ 
+ config XEN_DEBUG_FS
+ 	bool "Enable Xen debug and tuning parameters in debugfs"
+-	depends on XEN && DEBUG_FS
++	depends on PARAVIRT_XEN && DEBUG_FS
+ 	default n
+ 	help
+ 	  Enable statistics output and various tuning options in debugfs.
+--- head-2010-01-18.orig/drivers/acpi/acpica/hwsleep.c	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/drivers/acpi/acpica/hwsleep.c	2009-11-06 10:51:47.000000000 +0100
+@@ -396,8 +396,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+ 	err = acpi_notify_hypervisor_state(sleep_state,
+ 			PM1Acontrol, PM1Bcontrol);
+ 	if (err) {
+-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+-				  "Hypervisor failure [%d]\n", err));
++		printk(KERN_ERR "ACPI: Hypervisor failure [%d]\n", err);
+ 		return_ACPI_STATUS(AE_ERROR);
+ 	}
+ #endif
+--- head-2010-01-18.orig/drivers/acpi/processor_extcntl.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_extcntl.c	2009-11-06 10:51:47.000000000 +0100
+@@ -30,7 +30,6 @@
+ 
+ #include <acpi/processor.h>
+ 
+-#define ACPI_PROCESSOR_COMPONENT        0x01000000
+ #define ACPI_PROCESSOR_CLASS            "processor"
+ #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
+ ACPI_MODULE_NAME("processor_extcntl")
+--- head-2010-01-18.orig/drivers/firmware/dmi_scan.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/firmware/dmi_scan.c	2009-11-06 10:51:47.000000000 +0100
+@@ -424,6 +424,11 @@ static bool dmi_matches(const struct dmi
+ {
+ 	int i;
+ 
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return false;
++#endif
++
+ 	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+ 
+ 	for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 11:23:40.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:28:36.000000000 +0100
+@@ -305,8 +305,16 @@ static int msi_map_vector(struct pci_dev
+ 	 * dev->irq in dom0 will be 'Xen pirq' if this device belongs to
+ 	 * to another domain, and will be 'Linux irq' if it belongs to dom0.
+ 	 */
+-	return ((domid != DOMID_SELF) ?
+-		map_irq.pirq : evtchn_map_pirq(-1, map_irq.pirq));
++	if (domid == DOMID_SELF) {
++		rc = evtchn_map_pirq(-1, map_irq.pirq);
++		dev_printk(KERN_DEBUG, &dev->dev,
++			   "irq %d (%d) for MSI/MSI-X\n",
++			   rc, map_irq.pirq);
++		return rc;
++	}
++	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for dom%d MSI/MSI-X\n",
++		   map_irq.pirq, domid);
++	return map_irq.pirq;
+ }
+ 
+ static void pci_intx_for_msi(struct pci_dev *dev, int enable)
+@@ -761,3 +769,24 @@ void pci_msi_init_pci_dev(struct pci_dev
+ 	INIT_LIST_HEAD(&dev->msi_list);
+ #endif
+ }
++
++#ifdef CONFIG_ACPI
++#include <linux/acpi.h>
++#include <linux/pci-acpi.h>
++static void __devinit msi_acpi_init(void)
++{
++	if (acpi_pci_disabled)
++		return;
++	pci_osc_support_set(OSC_MSI_SUPPORT);
++	pcie_osc_support_set(OSC_MSI_SUPPORT);
++}
++#else
++static inline void msi_acpi_init(void) { }
++#endif /* CONFIG_ACPI */
++
++void __devinit msi_init(void)
++{
++	if (!pci_msi_enable)
++		return;
++	msi_acpi_init();
++}
+--- head-2010-01-18.orig/drivers/xen/Makefile	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/Makefile	2009-11-06 10:51:47.000000000 +0100
+@@ -1,4 +1,5 @@
+ obj-$(CONFIG_PARAVIRT_XEN)	+= grant-table.o features.o events.o manage.o
++xen-hotplug-$(CONFIG_PARAVIRT_XEN) := cpu_hotplug.o
+ xen-xencomm-$(CONFIG_PARAVIRT_XEN) := xencomm.o
+ xen-balloon-$(CONFIG_PARAVIRT_XEN) := balloon.o
+ 
+@@ -10,6 +11,7 @@ obj-y				+= xenbus/
+ obj-$(CONFIG_XEN)		+= char/
+ 
+ obj-$(CONFIG_XEN)		+= features.o util.o
++obj-$(CONFIG_HOTPLUG_CPU)	+= $(xen-hotplug-y)
+ obj-$(CONFIG_XEN_XENCOMM)	+= $(xen-xencomm-y)
+ obj-$(CONFIG_XEN_BALLOON)	+= $(xen-balloon-y)
+ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
+--- head-2010-01-18.orig/drivers/xen/blkback/vbd.c	2009-05-19 09:16:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/blkback/vbd.c	2009-11-06 10:51:47.000000000 +0100
+@@ -94,7 +94,8 @@ int vbd_create(blkif_t *blkif, blkif_vde
+ void vbd_free(struct vbd *vbd)
+ {
+ 	if (vbd->bdev)
+-		blkdev_put(vbd->bdev);
++		blkdev_put(vbd->bdev,
++			   vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ 	vbd->bdev = NULL;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2009-11-06 10:51:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:50:18.000000000 +0100
+@@ -484,9 +484,15 @@ static void blkif_restart_queue_callback
+ 	schedule_work(&info->work);
+ }
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ int blkif_open(struct inode *inode, struct file *filep)
+ {
+-	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
++	struct block_device *bd = inode->i_bdev;
++#else
++int blkif_open(struct block_device *bd, fmode_t mode)
++{
++#endif
++	struct blkfront_info *info = bd->bd_disk->private_data;
+ 
+ 	if(info->is_ready < 0)
+ 		return -ENODEV;
+@@ -495,9 +501,16 @@ int blkif_open(struct inode *inode, stru
+ }
+ 
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ int blkif_release(struct inode *inode, struct file *filep)
+ {
+-	struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
++	struct gendisk *disk = inode->i_bdev->bd_disk;
++#else
++int blkif_release(struct gendisk *disk, fmode_t mode)
++{
++#endif
++	struct blkfront_info *info = disk->private_data;
++
+ 	info->users--;
+ 	if (info->users == 0) {
+ 		/* Check whether we have been instructed to close.  We will
+@@ -516,9 +529,16 @@ int blkif_release(struct inode *inode, s
+ }
+ 
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ int blkif_ioctl(struct inode *inode, struct file *filep,
+ 		unsigned command, unsigned long argument)
+ {
++	struct block_device *bd = inode->i_bdev;
++#else
++int blkif_ioctl(struct block_device *bd, fmode_t mode,
++		unsigned command, unsigned long argument)
++{
++#endif
+ 	int i;
+ 
+ 	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+@@ -527,7 +547,6 @@ int blkif_ioctl(struct inode *inode, str
+ 	switch (command) {
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+ 	case HDIO_GETGEO: {
+-		struct block_device *bd = inode->i_bdev;
+ 		struct hd_geometry geo;
+ 		int ret;
+ 
+@@ -554,8 +573,7 @@ int blkif_ioctl(struct inode *inode, str
+ 		return 0;
+ 
+ 	case CDROM_GET_CAPABILITY: {
+-		struct blkfront_info *info =
+-			inode->i_bdev->bd_disk->private_data;
++		struct blkfront_info *info = bd->bd_disk->private_data;
+ 		struct gendisk *gd = info->gd;
+ 		if (gd->flags & GENHD_FL_CD)
+ 			return 0;
+--- head-2010-01-18.orig/drivers/xen/blkfront/block.h	2010-01-18 16:30:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/block.h	2010-01-18 16:49:13.000000000 +0100
+@@ -123,10 +123,17 @@ struct blkfront_info
+ 
+ extern spinlock_t blkif_io_lock;
+ 
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ extern int blkif_open(struct inode *inode, struct file *filep);
+ extern int blkif_release(struct inode *inode, struct file *filep);
+ extern int blkif_ioctl(struct inode *inode, struct file *filep,
+ 		       unsigned command, unsigned long argument);
++#else
++extern int blkif_open(struct block_device *bdev, fmode_t mode);
++extern int blkif_release(struct gendisk *disk, fmode_t mode);
++extern int blkif_ioctl(struct block_device *bdev, fmode_t mode,
++ 		       unsigned command, unsigned long argument);
++#endif
+ extern int blkif_getgeo(struct block_device *, struct hd_geometry *);
+ extern int blkif_check(dev_t dev);
+ extern int blkif_revalidate(dev_t dev);
+--- head-2010-01-18.orig/drivers/xen/blkfront/vbd.c	2010-01-18 16:30:28.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/vbd.c	2010-01-18 16:49:11.000000000 +0100
+@@ -110,7 +110,11 @@ static struct block_device_operations xl
+ 	.owner = THIS_MODULE,
+ 	.open = blkif_open,
+ 	.release = blkif_release,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+ 	.ioctl  = blkif_ioctl,
++#else
++	.locked_ioctl  = blkif_ioctl,
++#endif
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+ 	.getgeo = blkif_getgeo
+ #endif
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2009-11-06 10:51:47.000000000 +0100
+@@ -36,10 +36,10 @@ dev_to_blktap(struct blktap_device *dev)
+ }
+ 
+ static int
+-blktap_device_open(struct inode *inode, struct file *filep)
++blktap_device_open(struct block_device *bd, fmode_t mode)
+ {
+ 	struct blktap *tap;
+-	struct blktap_device *dev = inode->i_bdev->bd_disk->private_data;
++	struct blktap_device *dev = bd->bd_disk->private_data;
+ 
+ 	if (!dev)
+ 		return -ENOENT;
+@@ -55,9 +55,9 @@ blktap_device_open(struct inode *inode, 
+ }
+ 
+ static int
+-blktap_device_release(struct inode *inode, struct file *filep)
++blktap_device_release(struct gendisk *disk, fmode_t mode)
+ {
+-	struct blktap_device *dev = inode->i_bdev->bd_disk->private_data;
++	struct blktap_device *dev = disk->private_data;
+ 	struct blktap *tap = dev_to_blktap(dev);
+ 
+ 	dev->users--;
+@@ -85,18 +85,17 @@ blktap_device_getgeo(struct block_device
+ }
+ 
+ static int
+-blktap_device_ioctl(struct inode *inode, struct file *filep,
++blktap_device_ioctl(struct block_device *bd, fmode_t mode,
+ 		    unsigned command, unsigned long argument)
+ {
+ 	int i;
+ 
+-	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
+-		      command, (long)argument, inode->i_rdev);
++	DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx\n",
++		      command, (long)argument);
+ 
+ 	switch (command) {
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+ 	case HDIO_GETGEO: {
+-		struct block_device *bd = inode->i_bdev;
+ 		struct hd_geometry geo;
+ 		int ret;
+ 
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:51:47.000000000 +0100
+@@ -145,7 +145,7 @@ static void bind_evtchn_to_cpu(unsigned 
+ 	BUG_ON(!test_bit(chn, s->evtchn_mask));
+ 
+ 	if (irq != -1)
+-		irq_desc[irq].affinity = cpumask_of_cpu(cpu);
++		irq_to_desc(irq)->affinity = cpumask_of_cpu(cpu);
+ 
+ 	clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
+ 	set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
+@@ -158,7 +158,7 @@ static void init_evtchn_cpu_bindings(voi
+ 
+ 	/* By default all event channels notify CPU#0. */
+ 	for (i = 0; i < NR_IRQS; i++)
+-		irq_desc[i].affinity = cpumask_of_cpu(0);
++		irq_to_desc(i)->affinity = cpumask_of_cpu(0);
+ 
+ 	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+ 	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+@@ -725,7 +725,7 @@ static void end_dynirq(unsigned int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+-	if (VALID_EVTCHN(evtchn) && !(irq_desc[irq].status & IRQ_DISABLED))
++	if (VALID_EVTCHN(evtchn) && !(irq_to_desc(irq)->status & IRQ_DISABLED))
+ 		unmask_evtchn(evtchn);
+ }
+ 
+@@ -816,7 +816,7 @@ static unsigned int startup_pirq(unsigne
+ 	bind_pirq.pirq = evtchn_get_xen_pirq(irq);
+ 	/* NB. We are happy to share unless we are probing. */
+ 	bind_pirq.flags = test_and_clear_bit(irq - PIRQ_BASE, probing_pirq)
+-			  || (irq_desc[irq].status & IRQ_AUTODETECT)
++			  || (irq_to_desc(irq)->status & IRQ_AUTODETECT)
+ 			  ? 0 : BIND_PIRQ__WILL_SHARE;
+ 	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
+ 		if (bind_pirq.flags)
+@@ -882,7 +882,7 @@ static void end_pirq(unsigned int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
+-	if ((irq_desc[irq].status & (IRQ_DISABLED|IRQ_PENDING)) ==
++	if ((irq_to_desc(irq)->status & (IRQ_DISABLED|IRQ_PENDING)) ==
+ 	    (IRQ_DISABLED|IRQ_PENDING)) {
+ 		shutdown_pirq(irq);
+ 	} else if (VALID_EVTCHN(evtchn))
+@@ -1065,7 +1065,7 @@ static void restore_cpu_ipis(unsigned in
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+-		if (!(irq_desc[irq].status & IRQ_DISABLED))
++		if (!(irq_to_desc(irq)->status & IRQ_DISABLED))
+ 			unmask_evtchn(evtchn);
+ 	}
+ }
+@@ -1201,7 +1201,7 @@ void __init xen_init_IRQ(void)
+ 	for (i = DYNIRQ_BASE; i < (DYNIRQ_BASE + NR_DYNIRQS); i++) {
+ 		irq_bindcount[i] = 0;
+ 
+-		irq_desc[i].status |= IRQ_NOPROBE;
++		irq_to_desc(i)->status |= IRQ_NOPROBE;
+ 		set_irq_chip_and_handler_name(i, &dynirq_chip,
+ 					      handle_level_irq, "level");
+ 	}
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:51:47.000000000 +0100
+@@ -25,10 +25,6 @@
+ #include <xen/cpu_hotplug.h>
+ #include <xen/xenbus.h>
+ 
+-extern irqreturn_t smp_reschedule_interrupt(int, void *);
+-extern irqreturn_t smp_call_function_interrupt(int, void *);
+-extern irqreturn_t smp_call_function_single_interrupt(int, void *);
+-
+ extern int local_setup_timer(unsigned int cpu);
+ extern void local_teardown_timer(unsigned int cpu);
+ 
+@@ -179,7 +175,7 @@ static void __cpuexit xen_smp_intr_exit(
+ }
+ #endif
+ 
+-void __cpuinit cpu_bringup(void)
++static void __cpuinit cpu_bringup(void)
+ {
+ 	cpu_init();
+ 	identify_secondary_cpu(&current_cpu_data);
+@@ -432,6 +428,20 @@ int __cpuinit __cpu_up(unsigned int cpu)
+ 	return 0;
+ }
+ 
++void __ref play_dead(void)
++{
++	idle_task_exit();
++	local_irq_disable();
++	cpu_clear(smp_processor_id(), cpu_initialized);
++	preempt_enable_no_resched();
++	VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
++#ifdef CONFIG_HOTPLUG_CPU
++	cpu_bringup();
++#else
++	BUG();
++#endif
++}
++
+ void __init smp_cpus_done(unsigned int max_cpus)
+ {
+ }
+--- head-2010-01-18.orig/drivers/xen/core/spinlock.c	2010-01-18 16:45:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/spinlock.c	2009-11-17 15:19:07.000000000 +0100
+@@ -14,8 +14,6 @@
+ 
+ #ifdef TICKET_SHIFT
+ 
+-extern irqreturn_t smp_reschedule_interrupt(int, void *);
+-
+ static DEFINE_PER_CPU(int, spinlock_irq) = -1;
+ static char spinlock_name[NR_CPUS][15];
+ 
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:51:47.000000000 +0100
+@@ -956,7 +956,7 @@ static int network_start_xmit(struct sk_
+  		return 0; 
+  	} 
+ 
+-	frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
++	frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
+ 	if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
+ 		printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
+ 		       frags);
+--- head-2010-01-18.orig/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:25.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2008-09-15 15:22:12.000000000 +0200
+@@ -348,7 +348,7 @@ static int scsifront_queuecommand(struct
+ 		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->timeout_per_command = (sc->request->timeout / HZ);
+ 
+ 	info->shadow[rqid].req_scsi_cmnd     = (unsigned long)sc;
+ 	info->shadow[rqid].sc_data_direction = sc->sc_data_direction;
+@@ -418,7 +418,7 @@ static int scsifront_dev_reset_handler(s
+ 		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->timeout_per_command = (sc->request->timeout / HZ);
+ 	ring_req->nr_segments         = 0;
+ 
+ 	scsifront_do_request(info);	
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:51:47.000000000 +0100
+@@ -40,6 +40,11 @@
+ #define XEN_BUS_ID_SIZE			BUS_ID_SIZE
+ #endif
+ 
++#ifdef CONFIG_PARAVIRT_XEN
++#define is_running_on_xen() xen_domain()
++#define is_initial_xendomain() xen_initial_domain()
++#endif
++
+ #if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
+ extern void xenbus_backend_suspend(int (*fn)(struct device *, void *));
+ extern void xenbus_backend_resume(int (*fn)(struct device *, void *));
+--- head-2010-01-18.orig/include/xen/cpu_hotplug.h	2007-08-16 18:07:01.000000000 +0200
++++ head-2010-01-18/include/xen/cpu_hotplug.h	2009-11-06 10:51:47.000000000 +0100
+@@ -15,8 +15,6 @@ void init_xenbus_allowed_cpumask(void);
+ int smp_suspend(void);
+ void smp_resume(void);
+ 
+-void cpu_bringup(void);
+-
+ #else /* !defined(CONFIG_HOTPLUG_CPU) */
+ 
+ #define cpu_up_check(cpu)		(0)
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:51:42.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-12-14 17:24:14.000000000 +0100
+@@ -49,7 +49,6 @@ int swiotlb;
+ 
+ int swiotlb_force;
+ 
+-static char *iotlb_virt_start;
+ static unsigned long iotlb_nslabs;
+ 
+ /*
+@@ -57,16 +56,7 @@ static unsigned long iotlb_nslabs;
+  * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
+  * API.
+  */
+-static unsigned long iotlb_pfn_start, iotlb_pfn_end;
+-
+-/* Does the given dma address reside within the swiotlb aperture? */
+-static inline int in_swiotlb_aperture(dma_addr_t dev_addr)
+-{
+-	unsigned long pfn = mfn_to_local_pfn(dev_addr >> PAGE_SHIFT);
+-	return (pfn_valid(pfn)
+-		&& (pfn >= iotlb_pfn_start)
+-		&& (pfn < iotlb_pfn_end));
+-}
++static char *io_tlb_start, *io_tlb_end;
+ 
+ /*
+  * When the IOMMU overflows we return a fallback buffer. This sets the size.
+@@ -151,15 +141,15 @@ swiotlb_init_with_default_size(size_t de
+ 	/*
+ 	 * Get IO TLB memory from the low pages
+ 	 */
+-	iotlb_virt_start = alloc_bootmem_pages(bytes);
+-	if (!iotlb_virt_start)
++	io_tlb_start = alloc_bootmem_pages(bytes);
++	if (!io_tlb_start)
+ 		panic("Cannot allocate SWIOTLB buffer!\n");
+ 
+ 	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
+ 	for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
+ 		do {
+ 			rc = xen_create_contiguous_region(
+-				(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
++				(unsigned long)io_tlb_start + (i << IO_TLB_SHIFT),
+ 				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+ 				dma_bits);
+ 		} while (rc && dma_bits++ < max_dma_bits);
+@@ -170,10 +160,10 @@ swiotlb_init_with_default_size(size_t de
+ 				      "some DMA memory (e.g., dom0_mem=-128M).\n");
+ 			iotlb_nslabs = i;
+ 			i <<= IO_TLB_SHIFT;
+-			free_bootmem(__pa(iotlb_virt_start + i), bytes - i);
++			free_bootmem(__pa(io_tlb_start + i), bytes - i);
+ 			bytes = i;
+ 			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
+-				unsigned int bits = fls64(virt_to_bus(iotlb_virt_start + i - 1));
++				unsigned int bits = fls64(virt_to_bus(io_tlb_start + i - 1));
+ 
+ 				if (bits > dma_bits)
+ 					dma_bits = bits;
+@@ -181,6 +171,7 @@ swiotlb_init_with_default_size(size_t de
+ 			break;
+ 		}
+ 	}
++	io_tlb_end = io_tlb_start + bytes;
+ 
+ 	/*
+ 	 * Allocate and initialize the free list array.  This array is used
+@@ -209,15 +200,12 @@ swiotlb_init_with_default_size(size_t de
+ 	if (rc)
+ 		panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
+ 
+-	iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT;
+-	iotlb_pfn_end   = iotlb_pfn_start + (bytes >> PAGE_SHIFT);
+-
+ 	printk(KERN_INFO "Software IO TLB enabled: \n"
+ 	       " Aperture:     %lu megabytes\n"
+ 	       " Kernel range: %p - %p\n"
+ 	       " Address size: %u bits\n",
+ 	       bytes >> 20,
+-	       iotlb_virt_start, iotlb_virt_start + bytes,
++	       io_tlb_start, io_tlb_end,
+ 	       dma_bits);
+ }
+ 
+@@ -245,6 +233,18 @@ swiotlb_init(void)
+ 		printk(KERN_INFO "Software IO TLB disabled\n");
+ }
+ 
++static int is_swiotlb_buffer(dma_addr_t addr)
++{
++	unsigned long pfn = mfn_to_local_pfn(PFN_DOWN(addr));
++	char *va = pfn_valid(pfn) ? __va(pfn << PAGE_SHIFT) : NULL;
++
++#ifdef CONFIG_HIGHMEM
++	if (pfn >= highstart_pfn)
++		return 0;
++#endif
++	return va >= io_tlb_start && va < io_tlb_end;
++}
++
+ /*
+  * We use __copy_to_user_inatomic to transfer to the host buffer because the
+  * buffer may be mapped read-only (e.g, in blkback driver) but lower-level
+@@ -354,7 +354,7 @@ map_single(struct device *hwdev, struct 
+ 				io_tlb_list[i] = 0;
+ 			for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
+ 				io_tlb_list[i] = ++count;
+-			dma_addr = iotlb_virt_start + (index << IO_TLB_SHIFT);
++			dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+ 
+ 			/*
+ 			 * Update the indices to avoid searching in the next
+@@ -396,7 +396,7 @@ found:
+ 
+ static struct phys_addr dma_addr_to_phys_addr(char *dma_addr)
+ {
+-	int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
++	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+ 	struct phys_addr buffer = io_tlb_orig_addr[index];
+ 	buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1);
+ 	buffer.page += buffer.offset >> PAGE_SHIFT;
+@@ -412,7 +412,7 @@ unmap_single(struct device *hwdev, char 
+ {
+ 	unsigned long flags;
+ 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+-	int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
++	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+ 	struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
+ 
+ 	/*
+@@ -504,7 +504,7 @@ _swiotlb_map_single(struct device *hwdev
+ 	 * buffering it.
+ 	 */
+ 	if (!range_straddles_page_boundary(paddr, size) &&
+-	    !address_needs_mapping(hwdev, dev_addr))
++	    !address_needs_mapping(hwdev, dev_addr, size))
+ 		return dev_addr;
+ 
+ 	/*
+@@ -555,9 +555,11 @@ void
+ swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
+ 			   size_t size, int dir, struct dma_attrs *attrs)
+ {
++ 	char *dma_addr = bus_to_virt(dev_addr);
++
+ 	BUG_ON(dir == DMA_NONE);
+-	if (in_swiotlb_aperture(dev_addr))
+-		unmap_single(hwdev, bus_to_virt(dev_addr), size, dir);
++	if (is_swiotlb_buffer(dev_addr))
++		unmap_single(hwdev, dma_addr, size, dir);
+ 	else
+ 		gnttab_dma_unmap_page(dev_addr);
+ }
+@@ -583,36 +585,44 @@ void
+ swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 			    size_t size, int dir)
+ {
++ 	char *dma_addr = bus_to_virt(dev_addr);
++
+ 	BUG_ON(dir == DMA_NONE);
+-	if (in_swiotlb_aperture(dev_addr))
+-		sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
++	if (is_swiotlb_buffer(dev_addr))
++		sync_single(hwdev, dma_addr, size, dir);
+ }
+ 
+ void
+ swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 			       size_t size, int dir)
+ {
++ 	char *dma_addr = bus_to_virt(dev_addr);
++
+ 	BUG_ON(dir == DMA_NONE);
+-	if (in_swiotlb_aperture(dev_addr))
+-		sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
++	if (is_swiotlb_buffer(dev_addr))
++		sync_single(hwdev, dma_addr, size, dir);
+ }
+ 
+ void
+ swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
+ 				  unsigned long offset, size_t size, int dir)
+ {
++ 	char *dma_addr = bus_to_virt(dev_addr);
++
+ 	BUG_ON(dir == DMA_NONE);
+-	if (in_swiotlb_aperture(dev_addr))
+-		sync_single(hwdev, bus_to_virt(dev_addr + offset), size, dir);
++	if (is_swiotlb_buffer(dev_addr))
++		sync_single(hwdev, dma_addr + offset, size, dir);
+ }
+ 
+ void
+ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
+ 				     unsigned long offset, size_t size, int dir)
+ {
++ 	char *dma_addr = bus_to_virt(dev_addr);
++
+ 	BUG_ON(dir == DMA_NONE);
+-	if (in_swiotlb_aperture(dev_addr))
+-		sync_single(hwdev, bus_to_virt(dev_addr + offset), size, dir);
++	if (is_swiotlb_buffer(dev_addr))
++		sync_single(hwdev, dma_addr + offset, size, dir);
+ }
+ 
+ void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
+@@ -650,7 +660,7 @@ swiotlb_map_sg_attrs(struct device *hwde
+ 
+ 		if (range_straddles_page_boundary(page_to_pseudophys(sg_page(sg))
+ 						  + sg->offset, sg->length)
+-		    || address_needs_mapping(hwdev, dev_addr)) {
++		    || address_needs_mapping(hwdev, dev_addr, sg->length)) {
+ 			gnttab_dma_unmap_page(dev_addr);
+ 			buffer.page   = sg_page(sg);
+ 			buffer.offset = sg->offset;
+@@ -694,7 +704,7 @@ swiotlb_unmap_sg_attrs(struct device *hw
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+-		if (in_swiotlb_aperture(sg->dma_address))
++		if (sg->dma_address != sg_phys(sg))
+ 			unmap_single(hwdev, bus_to_virt(sg->dma_address),
+ 				     sg->dma_length, dir);
+ 		else
+@@ -727,7 +737,7 @@ swiotlb_sync_sg_for_cpu(struct device *h
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+-		if (in_swiotlb_aperture(sg->dma_address))
++		if (sg->dma_address != sg_phys(sg))
+ 			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ 	}
+@@ -743,7 +753,7 @@ swiotlb_sync_sg_for_device(struct device
+ 	BUG_ON(dir == DMA_NONE);
+ 
+ 	for_each_sg(sgl, sg, nelems, i) {
+-		if (in_swiotlb_aperture(sg->dma_address))
++		if (sg->dma_address != sg_phys(sg))
+ 			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ 	}
+--- head-2010-01-18.orig/mm/vmalloc.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/mm/vmalloc.c	2009-12-16 11:52:01.000000000 +0100
+@@ -482,6 +482,8 @@ static void vmap_debug_free_range(unsign
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+ 	vunmap_page_range(start, end);
+ 	flush_tlb_kernel_range(start, end);
++#elif defined(CONFIG_XEN) && defined(CONFIG_X86)
++	vunmap_page_range(start, end);
+ #endif
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-ipi-per-cpu-irq
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-ipi-per-cpu-irq
@@ -0,0 +1,797 @@
+From: jbeulich@novell.com
+Subject: fold IPIs onto a single IRQ each
+Patch-mainline: obsolete
+
+--- head-2010-01-18.orig/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 10:52:02.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic/ipi-xen.c	2009-11-06 11:10:20.000000000 +0100
+@@ -21,31 +21,22 @@
+ 
+ #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);
+-}
+-
+ static void __send_IPI_shortcut(unsigned int shortcut, int vector)
+ {
+ 	unsigned int cpu;
+ 
+ 	switch (shortcut) {
+ 	case APIC_DEST_SELF:
+-		__send_IPI_one(smp_processor_id(), vector);
++		notify_remote_via_ipi(vector, smp_processor_id());
+ 		break;
+ 	case APIC_DEST_ALLBUT:
+ 		for_each_online_cpu(cpu)
+ 			if (cpu != smp_processor_id())
+-				__send_IPI_one(cpu, vector);
++				notify_remote_via_ipi(vector, cpu);
+ 		break;
+ 	case APIC_DEST_ALLINC:
+ 		for_each_online_cpu(cpu)
+-			__send_IPI_one(cpu, vector);
++			notify_remote_via_ipi(vector, cpu);
+ 		break;
+ 	default:
+ 		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
+@@ -63,7 +54,7 @@ void xen_send_IPI_mask_allbutself(const 
+ 	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
+ 	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
+ 		if (cpu != smp_processor_id())
+-			__send_IPI_one(cpu, vector);
++			notify_remote_via_ipi(vector, cpu);
+ 	local_irq_restore(flags);
+ }
+ 
+@@ -75,7 +66,7 @@ void xen_send_IPI_mask(const struct cpum
+ 	local_irq_save(flags);
+ 	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
+ 	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
+-		__send_IPI_one(cpu, vector);
++		notify_remote_via_ipi(vector, cpu);
+ 	local_irq_restore(flags);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/irq-xen.c	2010-01-07 11:22:00.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq-xen.c	2010-01-07 11:22:50.000000000 +0100
+@@ -312,6 +312,7 @@ void fixup_irqs(void)
+ 
+ 		affinity = desc->affinity;
+ 		if (!irq_has_action(irq) ||
++		    (desc->status & IRQ_PER_CPU) ||
+ 		    cpumask_equal(affinity, cpu_online_mask)) {
+ 			spin_unlock(&desc->lock);
+ 			continue;
+--- head-2010-01-18.orig/drivers/xen/Kconfig	2009-12-18 12:30:46.000000000 +0100
++++ head-2010-01-18/drivers/xen/Kconfig	2009-12-18 12:30:54.000000000 +0100
+@@ -4,6 +4,7 @@
+ 
+ config XEN
+ 	bool
++	select IRQ_PER_CPU if SMP
+ 
+ if XEN
+ config XEN_INTERFACE_VERSION
+@@ -349,6 +350,9 @@ endmenu
+ config HAVE_IRQ_IGNORE_UNHANDLED
+ 	def_bool y
+ 
++config IRQ_PER_CPU
++	bool
++
+ config NO_IDLE_HZ
+ 	def_bool y
+ 
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 11:10:15.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 11:10:20.000000000 +0100
+@@ -58,6 +58,22 @@ static DEFINE_SPINLOCK(irq_mapping_updat
+ static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
+ 	[0 ...  NR_EVENT_CHANNELS-1] = -1 };
+ 
++/* IRQ <-> IPI mapping. */
++#ifndef NR_IPIS
++#define NR_IPIS 1
++#endif
++#if defined(CONFIG_SMP) && defined(CONFIG_X86)
++static int ipi_to_irq[NR_IPIS] __read_mostly = {[0 ... NR_IPIS-1] = -1};
++static DEFINE_PER_CPU(int[NR_IPIS], ipi_to_evtchn);
++#else
++#define PER_CPU_IPI_IRQ
++#endif
++#if !defined(CONFIG_SMP) || !defined(PER_CPU_IPI_IRQ)
++#define BUG_IF_IPI(irq) BUG_ON(type_from_irq(irq) == IRQT_IPI)
++#else
++#define BUG_IF_IPI(irq) ((void)(irq))
++#endif
++
+ /* Binding types. */
+ enum {
+ 	IRQT_UNBOUND,
+@@ -116,12 +132,14 @@ static inline u32 mk_irq_info(u32 type, 
+  * Accessors for packed IRQ information.
+  */
+ 
++#ifdef PER_CPU_IPI_IRQ
+ static inline unsigned int evtchn_from_irq(int irq)
+ {
+ 	const struct irq_cfg *cfg = irq_cfg(irq);
+ 
+ 	return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
+ }
++#endif
+ 
+ static inline unsigned int index_from_irq(int irq)
+ {
+@@ -138,14 +156,32 @@ static inline unsigned int type_from_irq
+ 	return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND;
+ }
+ 
++#ifndef PER_CPU_IPI_IRQ
++static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq,
++						    unsigned int cpu)
++{
++	BUG_ON(type_from_irq(irq) != IRQT_IPI);
++	return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)];
++}
++
++static inline unsigned int evtchn_from_irq(unsigned int irq)
++{
++	if (type_from_irq(irq) != IRQT_IPI) {
++		const struct irq_cfg *cfg = irq_cfg(irq);
++
++		return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0;
++	}
++	return evtchn_from_per_cpu_irq(irq, smp_processor_id());
++}
++#endif
++
+ /* IRQ <-> VIRQ mapping. */
+ DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
+ 
++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+ /* IRQ <-> IPI mapping. */
+-#ifndef NR_IPIS
+-#define NR_IPIS 1
+-#endif
+ DEFINE_PER_CPU(int[NR_IPIS], ipi_to_irq) = {[0 ... NR_IPIS-1] = -1};
++#endif
+ 
+ #ifdef CONFIG_SMP
+ 
+@@ -169,8 +205,14 @@ static void bind_evtchn_to_cpu(unsigned 
+ 
+ 	BUG_ON(!test_bit(chn, s->evtchn_mask));
+ 
+-	if (irq != -1)
+-		cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
++	if (irq != -1) {
++		struct irq_desc *desc = irq_to_desc(irq);
++
++		if (!(desc->status & IRQ_PER_CPU))
++			cpumask_copy(desc->affinity, cpumask_of(cpu));
++		else
++			cpumask_set_cpu(cpu, desc->affinity);
++	}
+ 
+ 	clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_evtchn[chn]));
+ 	set_bit(chn, per_cpu(cpu_evtchn_mask, cpu));
+@@ -338,7 +380,7 @@ asmlinkage void __irq_entry evtchn_do_up
+ 
+ static struct irq_chip dynirq_chip;
+ 
+-static int find_unbound_irq(unsigned int cpu)
++static int find_unbound_irq(unsigned int cpu, bool percpu)
+ {
+ 	static int warned;
+ 	int irq;
+@@ -348,10 +390,19 @@ static int find_unbound_irq(unsigned int
+ 		struct irq_cfg *cfg = desc->chip_data;
+ 
+ 		if (!cfg->bindcount) {
++			irq_flow_handler_t handle;
++			const char *name;
++
+ 			desc->status |= IRQ_NOPROBE;
++			if (!percpu) {
++				handle = handle_level_irq;
++				name = "level";
++			} else {
++				handle = handle_percpu_irq;
++				name = "percpu";
++			}
+ 			set_irq_chip_and_handler_name(irq, &dynirq_chip,
+-						      handle_level_irq,
+-						      "level");
++						      handle, name);
+ 			return irq;
+ 		}
+ 	}
+@@ -372,7 +423,7 @@ static int bind_caller_port_to_irq(unsig
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = evtchn_to_irq[caller_port]) == -1) {
+-		if ((irq = find_unbound_irq(smp_processor_id())) < 0)
++		if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0)
+ 			goto out;
+ 
+ 		evtchn_to_irq[caller_port] = irq;
+@@ -395,7 +446,7 @@ static int bind_local_port_to_irq(unsign
+ 
+ 	BUG_ON(evtchn_to_irq[local_port] != -1);
+ 
+-	if ((irq = find_unbound_irq(smp_processor_id())) < 0) {
++	if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0) {
+ 		struct evtchn_close close = { .port = local_port };
+ 		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
+ 			BUG();
+@@ -448,7 +499,7 @@ static int bind_virq_to_irq(unsigned int
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+-		if ((irq = find_unbound_irq(cpu)) < 0)
++		if ((irq = find_unbound_irq(cpu, false)) < 0)
+ 			goto out;
+ 
+ 		bind_virq.virq = virq;
+@@ -473,6 +524,7 @@ static int bind_virq_to_irq(unsigned int
+ 	return irq;
+ }
+ 
++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+ {
+ 	struct evtchn_bind_ipi bind_ipi;
+@@ -481,7 +533,7 @@ static int bind_ipi_to_irq(unsigned int 
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
+-		if ((irq = find_unbound_irq(cpu)) < 0)
++		if ((irq = find_unbound_irq(cpu, false)) < 0)
+ 			goto out;
+ 
+ 		bind_ipi.vcpu = cpu;
+@@ -504,6 +556,7 @@ static int bind_ipi_to_irq(unsigned int 
+ 	spin_unlock(&irq_mapping_update_lock);
+ 	return irq;
+ }
++#endif
+ 
+ static void unbind_from_irq(unsigned int irq)
+ {
+@@ -511,6 +564,7 @@ static void unbind_from_irq(unsigned int
+ 	unsigned int cpu;
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_IF_IPI(irq);
+ 	spin_lock(&irq_mapping_update_lock);
+ 
+ 	if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) {
+@@ -524,10 +578,12 @@ static void unbind_from_irq(unsigned int
+ 			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))
+ 				[index_from_irq(irq)] = -1;
+ 			break;
++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ)
+ 		case IRQT_IPI:
+ 			per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))
+ 				[index_from_irq(irq)] = -1;
+ 			break;
++#endif
+ 		default:
+ 			break;
+ 		}
+@@ -550,6 +606,46 @@ static void unbind_from_irq(unsigned int
+ 	spin_unlock(&irq_mapping_update_lock);
+ }
+ 
++#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu)
++{
++	struct evtchn_close close;
++	int evtchn = evtchn_from_per_cpu_irq(irq, cpu);
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if (VALID_EVTCHN(evtchn)) {
++		struct irq_desc *desc = irq_to_desc(irq);
++
++		mask_evtchn(evtchn);
++
++		BUG_ON(irq_cfg(irq)->bindcount <= 1);
++		irq_cfg(irq)->bindcount--;
++		cpumask_clear_cpu(cpu, desc->affinity);
++
++		close.port = evtchn;
++		if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
++			BUG();
++
++		switch (type_from_irq(irq)) {
++		case IRQT_IPI:
++			per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0;
++			break;
++		default:
++			BUG();
++			break;
++		}
++
++		/* Closed ports are implicitly re-bound to VCPU0. */
++		bind_evtchn_to_cpu(evtchn, 0);
++
++		evtchn_to_irq[evtchn] = -1;
++	}
++
++	spin_unlock(&irq_mapping_update_lock);
++}
++#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */
++
+ int bind_caller_port_to_irqhandler(
+ 	unsigned int caller_port,
+ 	irq_handler_t handler,
+@@ -644,6 +740,8 @@ int bind_virq_to_irqhandler(
+ }
+ EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler);
+ 
++#ifdef CONFIG_SMP
++#ifdef PER_CPU_IPI_IRQ
+ int bind_ipi_to_irqhandler(
+ 	unsigned int ipi,
+ 	unsigned int cpu,
+@@ -667,7 +765,71 @@ int bind_ipi_to_irqhandler(
+ 
+ 	return irq;
+ }
+-EXPORT_SYMBOL_GPL(bind_ipi_to_irqhandler);
++#else
++int __cpuinit bind_ipi_to_irqaction(
++	unsigned int ipi,
++	unsigned int cpu,
++	struct irqaction *action)
++{
++	struct evtchn_bind_ipi bind_ipi;
++	int evtchn, irq, retval = 0;
++
++	spin_lock(&irq_mapping_update_lock);
++
++	if (VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi])) {
++		spin_unlock(&irq_mapping_update_lock);
++		return -EBUSY;
++	}
++
++	if ((irq = ipi_to_irq[ipi]) == -1) {
++		if ((irq = find_unbound_irq(cpu, true)) < 0) {
++			spin_unlock(&irq_mapping_update_lock);
++			return irq;
++		}
++
++		/* Extra reference so count will never drop to zero. */
++		irq_cfg(irq)->bindcount++;
++
++		ipi_to_irq[ipi] = irq;
++		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, 0);
++		retval = 1;
++	}
++
++	bind_ipi.vcpu = cpu;
++	if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
++					&bind_ipi) != 0)
++		BUG();
++
++	evtchn = bind_ipi.port;
++	evtchn_to_irq[evtchn] = irq;
++	per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
++
++	bind_evtchn_to_cpu(evtchn, cpu);
++
++	irq_cfg(irq)->bindcount++;
++
++	spin_unlock(&irq_mapping_update_lock);
++
++	if (retval == 0) {
++		unsigned long flags;
++
++		local_irq_save(flags);
++		unmask_evtchn(evtchn);
++		local_irq_restore(flags);
++	} else {
++		action->flags |= IRQF_PERCPU | IRQF_NO_SUSPEND;
++		retval = setup_irq(irq, action);
++		if (retval) {
++			unbind_from_per_cpu_irq(irq, cpu);
++			BUG_ON(retval > 0);
++			irq = retval;
++		}
++	}
++
++	return irq;
++}
++#endif /* PER_CPU_IPI_IRQ */
++#endif /* CONFIG_SMP */
+ 
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id)
+ {
+@@ -693,6 +855,7 @@ static void rebind_irq_to_cpu(unsigned i
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_IF_IPI(irq);
+ 	if (VALID_EVTCHN(evtchn))
+ 		rebind_evtchn_to_cpu(evtchn, tcpu);
+ }
+@@ -778,6 +941,7 @@ static struct irq_chip dynirq_chip = {
+ 	.unmask   = unmask_dynirq,
+ 	.mask_ack = ack_dynirq,
+ 	.ack      = ack_dynirq,
++	.eoi      = end_dynirq,
+ 	.end      = end_dynirq,
+ #ifdef CONFIG_SMP
+ 	.set_affinity = set_affinity_irq,
+@@ -957,10 +1121,21 @@ int irq_ignore_unhandled(unsigned int ir
+ 	return !!(irq_status.flags & XENIRQSTAT_shared);
+ }
+ 
++#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ)
++void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu)
++{
++	int evtchn = evtchn_from_per_cpu_irq(ipi_to_irq[ipi], cpu);
++
++	if (VALID_EVTCHN(evtchn))
++		notify_remote_via_evtchn(evtchn);
++}
++#endif
++
+ void notify_remote_via_irq(int irq)
+ {
+ 	int evtchn = evtchn_from_irq(irq);
+ 
++	BUG_IF_IPI(irq);
+ 	if (VALID_EVTCHN(evtchn))
+ 		notify_remote_via_evtchn(evtchn);
+ }
+@@ -968,6 +1143,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq)
+ 
+ int irq_to_evtchn_port(int irq)
+ {
++	BUG_IF_IPI(irq);
+ 	return evtchn_from_irq(irq);
+ }
+ EXPORT_SYMBOL_GPL(irq_to_evtchn_port);
+@@ -1083,11 +1259,17 @@ static void restore_cpu_virqs(unsigned i
+ 
+ static void restore_cpu_ipis(unsigned int cpu)
+ {
++#ifdef CONFIG_SMP
+ 	struct evtchn_bind_ipi bind_ipi;
+ 	int ipi, irq, evtchn;
+ 
+ 	for (ipi = 0; ipi < NR_IPIS; ipi++) {
++#ifdef PER_CPU_IPI_IRQ
+ 		if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1)
++#else
++		if ((irq = ipi_to_irq[ipi]) == -1
++		    || !VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi]))
++#endif
+ 			continue;
+ 
+ 		BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_IPI, ipi, 0));
+@@ -1101,13 +1283,18 @@ static void restore_cpu_ipis(unsigned in
+ 
+ 		/* Record the new mapping. */
+ 		evtchn_to_irq[evtchn] = irq;
++#ifdef PER_CPU_IPI_IRQ
+ 		irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn);
++#else
++		per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn;
++#endif
+ 		bind_evtchn_to_cpu(evtchn, cpu);
+ 
+ 		/* Ready for use. */
+ 		if (!(irq_to_desc(irq)->status & IRQ_DISABLED))
+ 			unmask_evtchn(evtchn);
+ 	}
++#endif
+ }
+ 
+ static int evtchn_resume(struct sys_device *dev)
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 11:09:19.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 11:10:20.000000000 +0100
+@@ -40,14 +40,10 @@ cpumask_var_t vcpu_initialized_mask;
+ DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info);
+ EXPORT_PER_CPU_SYMBOL(cpu_info);
+ 
+-static DEFINE_PER_CPU(int, resched_irq);
+-static DEFINE_PER_CPU(int, callfunc_irq);
+-static DEFINE_PER_CPU(int, call1func_irq);
+-static DEFINE_PER_CPU(int, reboot_irq);
+-static char resched_name[NR_CPUS][15];
+-static char callfunc_name[NR_CPUS][15];
+-static char call1func_name[NR_CPUS][15];
+-static char reboot_name[NR_CPUS][15];
++static int __read_mostly resched_irq = -1;
++static int __read_mostly callfunc_irq = -1;
++static int __read_mostly call1func_irq = -1;
++static int __read_mostly reboot_irq = -1;
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+ #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid))
+@@ -101,58 +97,68 @@ remove_siblinginfo(unsigned int cpu)
+ 
+ static int __cpuinit xen_smp_intr_init(unsigned int cpu)
+ {
++	static struct irqaction resched_action = {
++		.handler = smp_reschedule_interrupt,
++		.flags   = IRQF_DISABLED,
++		.name    = "resched"
++	}, callfunc_action = {
++		.handler = smp_call_function_interrupt,
++		.flags   = IRQF_DISABLED,
++		.name    = "callfunc"
++	}, call1func_action = {
++		.handler = smp_call_function_single_interrupt,
++		.flags   = IRQF_DISABLED,
++		.name    = "call1func"
++	}, reboot_action = {
++		.handler = smp_reboot_interrupt,
++		.flags   = IRQF_DISABLED,
++		.name    = "reboot"
++	};
+ 	int rc;
+ 
+-	per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) =
+-		per_cpu(call1func_irq, cpu) = per_cpu(reboot_irq, cpu) = -1;
+-
+-	sprintf(resched_name[cpu], "resched%u", cpu);
+-	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
+-				    cpu,
+-				    smp_reschedule_interrupt,
+-				    IRQF_DISABLED|IRQF_NOBALANCING,
+-				    resched_name[cpu],
+-				    NULL);
++	rc = bind_ipi_to_irqaction(RESCHEDULE_VECTOR,
++				   cpu,
++				   &resched_action);
+ 	if (rc < 0)
+-		goto fail;
+-	per_cpu(resched_irq, cpu) = rc;
+-
+-	sprintf(callfunc_name[cpu], "callfunc%u", cpu);
+-	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
+-				    cpu,
+-				    smp_call_function_interrupt,
+-				    IRQF_DISABLED|IRQF_NOBALANCING,
+-				    callfunc_name[cpu],
+-				    NULL);
++		return rc;
++	if (resched_irq < 0)
++		resched_irq = rc;
++	else
++		BUG_ON(resched_irq != rc);
++
++	rc = bind_ipi_to_irqaction(CALL_FUNCTION_VECTOR,
++				   cpu,
++				   &callfunc_action);
+ 	if (rc < 0)
+-		goto fail;
+-	per_cpu(callfunc_irq, cpu) = rc;
+-
+-	sprintf(call1func_name[cpu], "call1func%u", cpu);
+-	rc = bind_ipi_to_irqhandler(CALL_FUNC_SINGLE_VECTOR,
+-				    cpu,
+-				    smp_call_function_single_interrupt,
+-				    IRQF_DISABLED|IRQF_NOBALANCING,
+-				    call1func_name[cpu],
+-				    NULL);
++		goto unbind_resched;
++	if (callfunc_irq < 0)
++		callfunc_irq = rc;
++	else
++		BUG_ON(callfunc_irq != rc);
++
++	rc = bind_ipi_to_irqaction(CALL_FUNC_SINGLE_VECTOR,
++				   cpu,
++				   &call1func_action);
+ 	if (rc < 0)
+-		goto fail;
+-	per_cpu(call1func_irq, cpu) = rc;
+-
+-	sprintf(reboot_name[cpu], "reboot%u", cpu);
+-	rc = bind_ipi_to_irqhandler(REBOOT_VECTOR,
+-				    cpu,
+-				    smp_reboot_interrupt,
+-				    IRQF_DISABLED|IRQF_NOBALANCING,
+-				    reboot_name[cpu],
+-				    NULL);
++		goto unbind_call;
++	if (call1func_irq < 0)
++		call1func_irq = rc;
++	else
++		BUG_ON(call1func_irq != rc);
++
++	rc = bind_ipi_to_irqaction(REBOOT_VECTOR,
++				   cpu,
++				   &reboot_action);
+ 	if (rc < 0)
+-		goto fail;
+-	per_cpu(reboot_irq, cpu) = rc;
++		goto unbind_call1;
++	if (reboot_irq < 0)
++		reboot_irq = rc;
++	else
++		BUG_ON(reboot_irq != rc);
+ 
+ 	rc = xen_spinlock_init(cpu);
+ 	if (rc < 0)
+-		goto fail;
++		goto unbind_reboot;
+ 
+ 	if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0))
+ 		goto fail;
+@@ -160,15 +166,15 @@ static int __cpuinit xen_smp_intr_init(u
+ 	return 0;
+ 
+  fail:
+-	if (per_cpu(resched_irq, cpu) >= 0)
+-		unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+-	if (per_cpu(callfunc_irq, cpu) >= 0)
+-		unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+-	if (per_cpu(call1func_irq, cpu) >= 0)
+-		unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+-	if (per_cpu(reboot_irq, cpu) >= 0)
+-		unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
+ 	xen_spinlock_cleanup(cpu);
++ unbind_reboot:
++	unbind_from_per_cpu_irq(reboot_irq, cpu);
++ unbind_call1:
++	unbind_from_per_cpu_irq(call1func_irq, cpu);
++ unbind_call:
++	unbind_from_per_cpu_irq(callfunc_irq, cpu);
++ unbind_resched:
++	unbind_from_per_cpu_irq(resched_irq, cpu);
+ 	return rc;
+ }
+ 
+@@ -178,10 +184,10 @@ static void __cpuinit xen_smp_intr_exit(
+ 	if (cpu != 0)
+ 		local_teardown_timer(cpu);
+ 
+-	unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
+-	unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
+-	unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL);
+-	unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL);
++	unbind_from_per_cpu_irq(resched_irq, cpu);
++	unbind_from_per_cpu_irq(callfunc_irq, cpu);
++	unbind_from_per_cpu_irq(call1func_irq, cpu);
++	unbind_from_per_cpu_irq(reboot_irq, cpu);
+ 	xen_spinlock_cleanup(cpu);
+ }
+ #endif
+--- head-2010-01-18.orig/drivers/xen/core/spinlock.c	2010-01-18 16:53:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/spinlock.c	2010-01-18 17:11:17.000000000 +0100
+@@ -14,8 +14,7 @@
+ 
+ #ifdef TICKET_SHIFT
+ 
+-static DEFINE_PER_CPU(int, spinlock_irq) = -1;
+-static char spinlock_name[NR_CPUS][15];
++static int __read_mostly spinlock_irq = -1;
+ 
+ struct spinning {
+ 	raw_spinlock_t *lock;
+@@ -32,34 +31,36 @@ static DEFINE_PER_CPU(raw_rwlock_t, spin
+ 
+ int __cpuinit xen_spinlock_init(unsigned int cpu)
+ {
++	static struct irqaction spinlock_action = {
++		.handler = smp_reschedule_interrupt,
++		.flags   = IRQF_DISABLED,
++		.name    = "spinlock"
++	};
+ 	int rc;
+ 
+-	sprintf(spinlock_name[cpu], "spinlock%u", cpu);
+-	rc = bind_ipi_to_irqhandler(SPIN_UNLOCK_VECTOR,
+-				    cpu,
+-				    smp_reschedule_interrupt,
+-				    IRQF_DISABLED|IRQF_NOBALANCING,
+-				    spinlock_name[cpu],
+-				    NULL);
++	rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR,
++				   cpu,
++				   &spinlock_action);
+  	if (rc < 0)
+  		return rc;
+ 
+-	disable_irq(rc); /* make sure it's never delivered */
+-	per_cpu(spinlock_irq, cpu) = rc;
++	if (spinlock_irq < 0) {
++		disable_irq(rc); /* make sure it's never delivered */
++		spinlock_irq = rc;
++	} else
++		BUG_ON(spinlock_irq != rc);
+ 
+ 	return 0;
+ }
+ 
+ void __cpuinit xen_spinlock_cleanup(unsigned int cpu)
+ {
+-	if (per_cpu(spinlock_irq, cpu) >= 0)
+-		unbind_from_irqhandler(per_cpu(spinlock_irq, cpu), NULL);
+-	per_cpu(spinlock_irq, cpu) = -1;
++	unbind_from_per_cpu_irq(spinlock_irq, cpu);
+ }
+ 
+ int xen_spin_wait(raw_spinlock_t *lock, unsigned int token)
+ {
+-	int rc = 0, irq = percpu_read(spinlock_irq);
++	int rc = 0, irq = spinlock_irq;
+ 	raw_rwlock_t *rm_lock;
+ 	unsigned long flags;
+ 	struct spinning spinning;
+@@ -133,7 +134,7 @@ unsigned int xen_spin_adjust(raw_spinloc
+ int xen_spin_wait_flags(raw_spinlock_t *lock, unsigned int *ptok,
+ 			unsigned int flags)
+ {
+-	int rc = 0, irq = __get_cpu_var(spinlock_irq);
++	int rc = 0, irq = spinlock_irq;
+ 	raw_rwlock_t *rm_lock;
+ 	struct spinning spinning, *nested;
+ 
+@@ -221,7 +222,7 @@ void xen_spin_kick(raw_spinlock_t *lock,
+ 		raw_local_irq_restore(flags);
+ 
+ 		if (unlikely(spinning)) {
+-			notify_remote_via_irq(per_cpu(spinlock_irq, cpu));
++			notify_remote_via_ipi(SPIN_UNLOCK_VECTOR, cpu);
+ 			return;
+ 		}
+ 	}
+--- head-2010-01-18.orig/include/xen/evtchn.h	2009-12-18 10:13:12.000000000 +0100
++++ head-2010-01-18/include/xen/evtchn.h	2009-12-18 10:13:26.000000000 +0100
+@@ -92,6 +92,8 @@ int bind_virq_to_irqhandler(
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
++#if defined(CONFIG_SMP) && !defined(MODULE)
++#ifndef CONFIG_X86
+ int bind_ipi_to_irqhandler(
+ 	unsigned int ipi,
+ 	unsigned int cpu,
+@@ -99,6 +101,13 @@ int bind_ipi_to_irqhandler(
+ 	unsigned long irqflags,
+ 	const char *devname,
+ 	void *dev_id);
++#else
++int bind_ipi_to_irqaction(
++	unsigned int ipi,
++	unsigned int cpu,
++	struct irqaction *action);
++#endif
++#endif
+ 
+ /*
+  * Common unbind function for all event sources. Takes IRQ to unbind from.
+@@ -107,6 +116,11 @@ int bind_ipi_to_irqhandler(
+  */
+ void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+ 
++#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
++/* Specialized unbind function for per-CPU IRQs. */
++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu);
++#endif
++
+ #ifndef CONFIG_XEN
+ void irq_resume(void);
+ #endif
+@@ -184,5 +198,9 @@ void xen_poll_irq(int irq);
+ void notify_remote_via_irq(int irq);
+ int irq_to_evtchn_port(int irq);
+ 
++#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
++void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu);
++#endif
++
+ #endif /* __ASM_EVTCHN_H__ */
+ #endif /* CONFIG_PARAVIRT_XEN */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.26-27
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.26-27
@@ -0,0 +1,32 @@
+From: Jiri Slaby <jslaby@suse.cz>
+Subject: Linux 2.6.32.27
+Patch-mainline: 2.6.32.27
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Automatically created from "patches.kernel.org/patch-2.6.32.26-27" by xen-port-patches.py
+
+--- sle11sp1-2010-12-14.orig/arch/x86/kernel/quirks-xen.c	2010-02-09 17:12:56.000000000 +0100
++++ sle11sp1-2010-12-14/arch/x86/kernel/quirks-xen.c	2010-12-13 13:36:09.000000000 +0100
+@@ -513,6 +513,7 @@ static void __init quirk_amd_nb_node(str
+ {
+ 	struct pci_dev *nb_ht;
+ 	unsigned int devfn;
++	u32 node;
+ 	u32 val;
+ 
+ 	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
+@@ -521,7 +522,13 @@ static void __init quirk_amd_nb_node(str
+ 		return;
+ 
+ 	pci_read_config_dword(nb_ht, 0x60, &val);
+-	set_dev_node(&dev->dev, val & 7);
++	node = val & 7;
++	/*
++	 * Some hardware may return an invalid node ID,
++	 * so check it first:
++	 */
++	if (node_online(node))
++		set_dev_node(&dev->dev, node);
+ 	pci_dev_put(nb_ht);
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-cpufreq-report
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-cpufreq-report
@@ -0,0 +1,57 @@
+From: jbeulich@novell.com
+Subject: make /proc/cpuinfo track CPU speed
+Patch-mainline: obsolete
+
+--- head-2010-01-04.orig/arch/x86/kernel/acpi/processor_extcntl_xen.c	2009-07-13 14:25:35.000000000 +0200
++++ head-2010-01-04/arch/x86/kernel/acpi/processor_extcntl_xen.c	2009-11-06 11:09:27.000000000 +0100
+@@ -204,3 +204,14 @@ void arch_acpi_processor_init_extcntl(co
+ 	*ops = &xen_extcntl_ops;
+ }
+ EXPORT_SYMBOL(arch_acpi_processor_init_extcntl);
++
++unsigned int cpufreq_quick_get(unsigned int cpu)
++{
++	xen_platform_op_t op = {
++		.cmd			= XENPF_get_cpu_freq,
++		.interface_version	= XENPF_INTERFACE_VERSION,
++		.u.get_cpu_freq.vcpu	= cpu
++	};
++
++	return HYPERVISOR_platform_op(&op) == 0 ? op.u.get_cpu_freq.freq : 0;
++}
+--- head-2010-01-04.orig/include/linux/cpufreq.h	2010-01-04 12:00:40.000000000 +0100
++++ head-2010-01-04/include/linux/cpufreq.h	2009-11-06 11:09:27.000000000 +0100
+@@ -302,7 +302,7 @@ static inline unsigned int cpufreq_get(u
+ #endif
+ 
+ /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
+-#ifdef CONFIG_CPU_FREQ
++#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
+ unsigned int cpufreq_quick_get(unsigned int cpu);
+ #else
+ static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+--- head-2010-01-04.orig/include/xen/interface/platform.h	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-04/include/xen/interface/platform.h	2010-01-04 13:31:04.000000000 +0100
+@@ -355,6 +355,14 @@ struct xenpf_mem_hotadd
+     uint32_t flags;
+ };
+ 
++#define XENPF_get_cpu_freq        ('N' << 24)
++struct xenpf_get_cpu_freq {
++    /* IN variables */
++    uint32_t vcpu;
++    /* OUT variables */
++    uint32_t freq; /* in kHz */
++};
++
+ struct xen_platform_op {
+     uint32_t cmd;
+     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
+@@ -374,6 +384,7 @@ struct xen_platform_op {
+         struct xenpf_cpu_ol            cpu_ol;
+         struct xenpf_cpu_hotadd        cpu_add;
+         struct xenpf_mem_hotadd        mem_add;
++        struct xenpf_get_cpu_freq      get_cpu_freq;
+         uint8_t                        pad[128];
+     } u;
+ };
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-driverlink-conditional
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-driverlink-conditional
@@ -0,0 +1,248 @@
+From: jbeulich@novell.com
+Subject: conditionalize driverlink additions to Solarflare driver
+Patch-mainline: obsolete
+References: FATE#303479
+
+At once converted the EFX_TRACE() invocations after vetoed RX/TX
+callbacks to ...LOG() ones, which is consistent with Solarflare's
+current code according to David Riddoch (2008-09-12).
+
+--- head-2009-11-06.orig/drivers/net/sfc/Kconfig	2009-04-21 11:02:22.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/Kconfig	2009-10-12 13:41:03.000000000 +0200
+@@ -12,8 +12,12 @@ config SFC
+ 	  To compile this driver as a module, choose M here.  The module
+ 	  will be called sfc.
+ 
++config SFC_DRIVERLINK
++	bool
++
+ config SFC_RESOURCE
+ 	depends on SFC && X86
++	select SFC_DRIVERLINK
+ 	tristate "Solarflare Solarstorm SFC4000 resource driver"
+ 	help
+ 	  This module provides the SFC resource manager driver.
+--- head-2009-11-06.orig/drivers/net/sfc/Makefile	2009-02-06 12:42:18.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/Makefile	2009-10-12 13:41:03.000000000 +0200
+@@ -1,7 +1,7 @@
+ sfc-y			+= efx.o falcon.o tx.o rx.o falcon_gmac.o \
+ 			   falcon_xmac.o selftest.o ethtool.o xfp_phy.o \
+-			   mdio_10g.o tenxpress.o boards.o sfe4001.o \
+-			   driverlink.o
++			   mdio_10g.o tenxpress.o boards.o sfe4001.o
++sfc-$(CONFIG_SFC_DRIVERLINK) += driverlink.o
+ sfc-$(CONFIG_SFC_MTD)	+= mtd.o
+ 
+ obj-$(CONFIG_SFC)	+= sfc.o
+--- head-2009-11-06.orig/drivers/net/sfc/driverlink.c	2009-07-28 10:04:25.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/driverlink.c	2009-10-12 13:41:03.000000000 +0200
+@@ -14,7 +14,6 @@
+ #include <linux/rtnetlink.h>
+ #include "net_driver.h"
+ #include "efx.h"
+-#include "driverlink_api.h"
+ #include "driverlink.h"
+ 
+ /* Protects @efx_driverlink_lock and @efx_driver_list */
+--- head-2009-11-06.orig/drivers/net/sfc/driverlink.h	2009-07-28 10:04:25.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/driverlink.h	2009-10-12 13:41:03.000000000 +0200
+@@ -15,6 +15,10 @@
+ struct efx_dl_device;
+ struct efx_nic;
+ 
++#ifdef CONFIG_SFC_DRIVERLINK
++
++#include "driverlink_api.h"
++
+ /* Efx callback devices
+  *
+  * A list of the devices that own each callback. The partner to
+@@ -40,4 +44,23 @@ extern void efx_dl_unregister_nic(struct
+ extern void efx_dl_reset_suspend(struct efx_nic *efx);
+ extern void efx_dl_reset_resume(struct efx_nic *efx, int ok);
+ 
++#define EFX_DL_LOG EFX_LOG
++
++#else /* CONFIG_SFC_DRIVERLINK */
++
++enum efx_veto { EFX_ALLOW_PACKET = 0 };
++
++static inline int efx_nop_callback(struct efx_nic *efx) { return 0; }
++#define EFX_DL_CALLBACK(port, name, ...) efx_nop_callback(port)
++
++static inline int efx_dl_register_nic(struct efx_nic *efx) { return 0; }
++static inline void efx_dl_unregister_nic(struct efx_nic *efx) {}
++
++static inline void efx_dl_reset_suspend(struct efx_nic *efx) {}
++static inline void efx_dl_reset_resume(struct efx_nic *efx, int ok) {}
++
++#define EFX_DL_LOG(efx, fmt, args...) ((void)(efx))
++
++#endif /* CONFIG_SFC_DRIVERLINK */
++
+ #endif /* EFX_DRIVERLINK_H */
+--- head-2009-11-06.orig/drivers/net/sfc/efx.c	2009-10-12 13:40:25.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/efx.c	2009-10-12 13:41:03.000000000 +0200
+@@ -1689,6 +1689,7 @@ static void efx_unregister_netdev(struct
+  * Device reset and suspend
+  *
+  **************************************************************************/
++#ifdef CONFIG_SFC_DRIVERLINK
+ /* Serialise access to the driverlink callbacks, by quiescing event processing
+  * (without flushing the descriptor queues), and acquiring the rtnl_lock */
+ void efx_suspend(struct efx_nic *efx)
+@@ -1706,6 +1707,7 @@ void efx_resume(struct efx_nic *efx)
+ 	efx_start_all(efx);
+ 	rtnl_unlock();
+ }
++#endif
+ 
+ /* Tears down the entire software state and most of the hardware state
+  * before reset.  */
+@@ -1978,9 +1980,11 @@ static int efx_init_struct(struct efx_ni
+ 	efx->mac_op = &efx_dummy_mac_operations;
+ 	efx->phy_op = &efx_dummy_phy_operations;
+ 	efx->mdio.dev = net_dev;
++#ifdef CONFIG_SFC_DRIVERLINK
+ 	INIT_LIST_HEAD(&efx->dl_node);
+ 	INIT_LIST_HEAD(&efx->dl_device_list);
+ 	efx->dl_cb = efx_default_callbacks;
++#endif
+ 	INIT_WORK(&efx->phy_work, efx_phy_work);
+ 	INIT_WORK(&efx->mac_work, efx_mac_work);
+ 	atomic_set(&efx->netif_stop_count, 1);
+--- head-2009-11-06.orig/drivers/net/sfc/falcon.c	2009-07-28 10:04:25.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/falcon.c	2009-10-12 13:41:03.000000000 +0200
+@@ -36,6 +36,7 @@
+ 
+ /**
+  * struct falcon_nic_data - Falcon NIC state
++ * @next_buffer_table: First available buffer table id
+  * @resources: Resource information for driverlink client
+  * @pci_dev2: The secondary PCI device if present
+  * @i2c_data: Operations and state for I2C bit-bashing algorithm
+@@ -43,7 +44,11 @@
+  * @int_error_expire: Time at which error count will be expired
+  */
+ struct falcon_nic_data {
++#ifndef CONFIG_SFC_DRIVERLINK
++	unsigned next_buffer_table;
++#else
+ 	struct efx_dl_falcon_resources resources;
++#endif
+ 	struct pci_dev *pci_dev2;
+ 	struct i2c_algo_bit_data i2c_data;
+ 
+@@ -336,8 +341,13 @@ static int falcon_alloc_special_buffer(s
+ 	memset(buffer->addr, 0xff, len);
+ 
+ 	/* Select new buffer ID */
++#ifndef CONFIG_SFC_DRIVERLINK
++	buffer->index = nic_data->next_buffer_table;
++	nic_data->next_buffer_table += buffer->entries;
++#else
+ 	buffer->index = nic_data->resources.buffer_table_min;
+ 	nic_data->resources.buffer_table_min += buffer->entries;
++#endif
+ 
+ 	EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x "
+ 		"(virt %p phys %llx)\n", buffer->index,
+@@ -2755,6 +2765,7 @@ static int falcon_probe_nvconfig(struct 
+  * should live. */
+ static int falcon_dimension_resources(struct efx_nic *efx)
+ {
++#ifdef CONFIG_SFC_DRIVERLINK
+ 	unsigned internal_dcs_entries;
+ 	struct falcon_nic_data *nic_data = efx->nic_data;
+ 	struct efx_dl_falcon_resources *res = &nic_data->resources;
+@@ -2799,6 +2810,7 @@ static int falcon_dimension_resources(st
+ 
+ 	if (EFX_INT_MODE_USE_MSI(efx))
+ 		res->flags |= EFX_DL_FALCON_USE_MSI;
++#endif
+ 
+ 	return 0;
+ }
+@@ -2962,7 +2974,9 @@ int falcon_probe_nic(struct efx_nic *efx
+ 	return 0;
+ 
+  fail6:
++#ifdef CONFIG_SFC_DRIVERLINK
+ 	efx->dl_info = NULL;
++#endif
+  fail5:
+ 	falcon_remove_spi_devices(efx);
+ 	falcon_free_buffer(efx, &efx->irq_status);
+@@ -3150,7 +3164,9 @@ void falcon_remove_nic(struct efx_nic *e
+ 	/* Tear down the private nic state */
+ 	kfree(efx->nic_data);
+ 	efx->nic_data = NULL;
++#ifdef CONFIG_SFC_DRIVERLINK
+ 	efx->dl_info = NULL;
++#endif
+ }
+ 
+ void falcon_update_nic_stats(struct efx_nic *efx)
+--- head-2009-11-06.orig/drivers/net/sfc/net_driver.h	2009-07-28 10:04:25.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/net_driver.h	2009-10-12 13:41:03.000000000 +0200
+@@ -29,7 +29,6 @@
+ 
+ #include "enum.h"
+ #include "bitfield.h"
+-#include "driverlink_api.h"
+ #include "driverlink.h"
+ 
+ /**************************************************************************
+@@ -854,11 +853,13 @@ struct efx_nic {
+ 	void *loopback_selftest;
+ 
+ 	const char *silicon_rev;
++#ifdef CONFIG_SFC_DRIVERLINK
+ 	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;
++#endif
+ };
+ 
+ static inline int efx_dev_registered(struct efx_nic *efx)
+--- head-2009-11-06.orig/drivers/net/sfc/rx.c	2009-11-06 10:32:03.000000000 +0100
++++ head-2009-11-06/drivers/net/sfc/rx.c	2009-11-06 10:32:24.000000000 +0100
+@@ -456,8 +456,8 @@ static void efx_rx_packet_lro(struct efx
+ 	 * an obvious interface to this, so veto packets before LRO */
+ 	veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len);
+ 	if (unlikely(veto)) {
+-		EFX_TRACE(efx, "LRO RX vetoed by driverlink %s driver\n",
+-			  efx->dl_cb_dev.rx_packet->driver->name);
++		EFX_DL_LOG(efx, "LRO 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);
+ 		return;
+@@ -579,8 +579,8 @@ void __efx_rx_packet(struct efx_channel 
+ 	/* 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);
++		EFX_DL_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;
+--- head-2009-11-06.orig/drivers/net/sfc/tx.c	2009-10-12 13:40:32.000000000 +0200
++++ head-2009-11-06/drivers/net/sfc/tx.c	2009-10-12 13:41:03.000000000 +0200
+@@ -387,9 +387,9 @@ netdev_tx_t efx_hard_start_xmit(struct s
+ 	/* See if driverlink wants to veto the packet. */
+ 	veto = EFX_DL_CALLBACK(efx, tx_packet, skb);
+ 	if (unlikely(veto)) {
+-		EFX_TRACE(efx, "TX queue %d packet vetoed by "
+-			  "driverlink %s driver\n", tx_queue->queue,
+-			  efx->dl_cb_dev.tx_packet->driver->name);
++		EFX_DL_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(skb);
+ 		return NETDEV_TX_OK;
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.21
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.21
@@ -0,0 +1,5056 @@
+From: www.kernel.org
+Subject: Linux 2.6.21
+Patch-mainline: 2.6.21
+
+Automatically created from "patches.kernel.org/patch-2.6.21" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:00:05.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-06 10:46:41.000000000 +0100
+@@ -69,13 +69,15 @@ config GENERIC_CMOS_UPDATE
+ 
+ config CLOCKSOURCE_WATCHDOG
+ 	def_bool y
++	depends on !X86_XEN
+ 
+ config GENERIC_CLOCKEVENTS
+ 	def_bool y
++	depends on !X86_XEN
+ 
+ config GENERIC_CLOCKEVENTS_BROADCAST
+ 	def_bool y
+-	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
++	depends on X86_64 || (X86_32 && X86_LOCAL_APIC && !X86_XEN)
+ 
+ config LOCKDEP_SUPPORT
+ 	def_bool y
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:46:41.000000000 +0100
+@@ -138,7 +138,7 @@ ifeq ($(CONFIG_X86_64),y)
+ 	pci-dma_64-$(CONFIG_XEN)	+= pci-dma_32.o
+ endif
+ 
+-disabled-obj-$(CONFIG_XEN) := early-quirks.o i8253.o i8259_$(BITS).o reboot.o \
+-	smpboot_$(BITS).o tsc_$(BITS).o
++disabled-obj-$(CONFIG_XEN) := early-quirks.o hpet.o i8253.o i8259_$(BITS).o reboot.o \
++	smpboot_$(BITS).o tsc_$(BITS).o tsc_sync.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += mpparse_64.o
+ %/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
+--- head-2010-01-18.orig/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -25,6 +25,8 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/sysdev.h>
+ #include <linux/cpu.h>
++#include <linux/clockchips.h>
++#include <linux/acpi_pmtmr.h>
+ #include <linux/module.h>
+ 
+ #include <asm/atomic.h>
+@@ -56,83 +58,26 @@ static cpumask_t timer_bcast_ipi;
+  */
+ 
+ /*
+- * Debug level
++ * Debug level, exported for io_apic.c
+  */
+ int apic_verbosity;
+ 
+ #ifndef CONFIG_XEN
+ static int modern_apic(void)
+ {
+-	unsigned int lvr, version;
+ 	/* AMD systems use old APIC versions, so check the CPU */
+ 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+-		boot_cpu_data.x86 >= 0xf)
++	    boot_cpu_data.x86 >= 0xf)
+ 		return 1;
+-	lvr = apic_read(APIC_LVR);
+-	version = GET_APIC_VERSION(lvr);
+-	return version >= 0x14;
++	return lapic_get_version() >= 0x14;
+ }
+ #endif /* !CONFIG_XEN */
+ 
+-/*
+- * 'what should we do if we get a hw irq event on an illegal vector'.
+- * each architecture has to answer this themselves.
+- */
+-void ack_bad_irq(unsigned int irq)
+-{
+-	printk("unexpected IRQ trap at vector %02x\n", irq);
+-	/*
+-	 * Currently unexpected vectors happen only on SMP and APIC.
+-	 * We _must_ ack these because every local APIC has only N
+-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+-	 * holds up an irq slot - in excessive cases (when multiple
+-	 * unexpected vectors occur) that might lock up the APIC
+-	 * completely.
+-	 * But only ack when the APIC is enabled -AK
+-	 */
+-	if (cpu_has_apic)
+-		ack_APIC_irq();
+-}
+-
+ int get_physical_broadcast(void)
+ {
+         return 0xff;
+ }
+ 
+-#ifndef CONFIG_XEN
+-#ifndef CONFIG_SMP
+-static void up_apic_timer_interrupt_call(void)
+-{
+-	int cpu = smp_processor_id();
+-
+-	/*
+-	 * the NMI deadlock-detector uses this.
+-	 */
+-	per_cpu(irq_stat, cpu).apic_timer_irqs++;
+-
+-	smp_local_timer_interrupt();
+-}
+-#endif
+-
+-void smp_send_timer_broadcast_ipi(void)
+-{
+-	cpumask_t mask;
+-
+-	cpus_and(mask, cpu_online_map, timer_bcast_ipi);
+-	if (!cpus_empty(mask)) {
+-#ifdef CONFIG_SMP
+-		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+-#else
+-		/*
+-		 * We can directly call the apic timer interrupt handler
+-		 * in UP case. Minus all irq related functions
+-		 */
+-		up_apic_timer_interrupt_call();
+-#endif
+-	}
+-}
+-#endif
+-
+ int setup_profiling_timer(unsigned int multiplier)
+ {
+ 	return -EINVAL;
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -612,7 +612,7 @@ void __init early_cpu_init(void)
+ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+ {
+ 	memset(regs, 0, sizeof(struct pt_regs));
+-	regs->xgs = __KERNEL_PDA;
++	regs->xfs = __KERNEL_PDA;
+ 	return regs;
+ }
+ 
+@@ -669,12 +669,12 @@ struct i386_pda boot_pda = {
+ 	.pcurrent = &init_task,
+ };
+ 
+-static inline void set_kernel_gs(void)
++static inline void set_kernel_fs(void)
+ {
+-	/* Set %gs for this CPU's PDA.  Memory clobber is to create a
++	/* Set %fs for this CPU's PDA.  Memory clobber is to create a
+ 	   barrier with respect to any PDA operations, so the compiler
+ 	   doesn't move any before here. */
+-	asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory");
++	asm volatile ("mov %0, %%fs" : : "r" (__KERNEL_PDA) : "memory");
+ }
+ 
+ /* Initialize the CPU's GDT and PDA.  The boot CPU does this for
+@@ -732,7 +732,7 @@ void __cpuinit cpu_set_gdt(int cpu)
+ 	}
+ 	BUG_ON(HYPERVISOR_set_gdt(frames, (cpu_gdt_descr->size + 1) / 8));
+ 
+-	set_kernel_gs();
++	set_kernel_fs();
+ }
+ 
+ /* Common CPU init for both boot and secondary CPUs */
+@@ -777,8 +777,8 @@ static void __cpuinit _cpu_init(int cpu,
+ 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+ #endif
+ 
+-	/* Clear %fs. */
+-	asm volatile ("mov %0, %%fs" : : "r" (0));
++	/* Clear %gs. */
++	asm volatile ("mov %0, %%gs" : : "r" (0));
+ 
+ 	/* Clear all 6 debug registers: */
+ 	set_debugreg(0, 0);
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -14,6 +14,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
+ #include <asm/e820.h>
++#include <asm/setup.h>
+ #include <xen/interface/memory.h>
+ 
+ #ifdef CONFIG_EFI
+@@ -157,21 +158,22 @@ static struct resource standard_io_resou
+ 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
+ } };
+ 
+-static int romsignature(const unsigned char *x)
++#define ROMSIGNATURE 0xaa55
++
++static int __init romsignature(const unsigned char *rom)
+ {
+ 	unsigned short sig;
+-	int ret = 0;
+-	if (probe_kernel_address((const unsigned short *)x, sig) == 0)
+-		ret = (sig == 0xaa55);
+-	return ret;
++
++	return probe_kernel_address((const unsigned short *)rom, sig) == 0 &&
++	       sig == ROMSIGNATURE;
+ }
+ 
+ static int __init romchecksum(unsigned char *rom, unsigned long length)
+ {
+-	unsigned char *p, sum = 0;
++	unsigned char sum;
+ 
+-	for (p = rom; p < rom + length; p++)
+-		sum += *p;
++	for (sum = 0; length; length--)
++		sum += *rom++;
+ 	return sum == 0;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:46:41.000000000 +0100
+@@ -30,7 +30,7 @@
+  *	18(%esp) - %eax
+  *	1C(%esp) - %ds
+  *	20(%esp) - %es
+- *	24(%esp) - %gs
++ *	24(%esp) - %fs
+  *	28(%esp) - orig_eax
+  *	2C(%esp) - %eip
+  *	30(%esp) - %cs
+@@ -102,9 +102,9 @@ NMI_MASK	= 0x80000000
+ 
+ #define SAVE_ALL \
+ 	cld; \
+-	pushl %gs; \
++	pushl %fs; \
+ 	CFI_ADJUST_CFA_OFFSET 4;\
+-	/*CFI_REL_OFFSET gs, 0;*/\
++	/*CFI_REL_OFFSET fs, 0;*/\
+ 	pushl %es; \
+ 	CFI_ADJUST_CFA_OFFSET 4;\
+ 	/*CFI_REL_OFFSET es, 0;*/\
+@@ -136,7 +136,7 @@ NMI_MASK	= 0x80000000
+ 	movl %edx, %ds; \
+ 	movl %edx, %es; \
+ 	movl $(__KERNEL_PDA), %edx; \
+-	movl %edx, %gs
++	movl %edx, %fs
+ 
+ #define RESTORE_INT_REGS \
+ 	popl %ebx;	\
+@@ -169,9 +169,9 @@ NMI_MASK	= 0x80000000
+ 2:	popl %es;	\
+ 	CFI_ADJUST_CFA_OFFSET -4;\
+ 	/*CFI_RESTORE es;*/\
+-3:	popl %gs;	\
++3:	popl %fs;	\
+ 	CFI_ADJUST_CFA_OFFSET -4;\
+-	/*CFI_RESTORE gs;*/\
++	/*CFI_RESTORE fs;*/\
+ .pushsection .fixup,"ax";	\
+ 4:	movl $0,(%esp);	\
+ 	jmp 1b;		\
+@@ -230,6 +230,7 @@ ENTRY(ret_from_fork)
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	jmp syscall_exit
+ 	CFI_ENDPROC
++END(ret_from_fork)
+ 
+ /*
+  * Return to user mode is not as complex as all this looks,
+@@ -261,6 +262,7 @@ ENTRY(resume_userspace)
+ 					# int/exception return?
+ 	jne work_pending
+ 	jmp restore_all
++END(ret_from_exception)
+ 
+ #ifdef CONFIG_PREEMPT
+ ENTRY(resume_kernel)
+@@ -275,6 +277,7 @@ need_resched:
+ 	jz restore_all
+ 	call preempt_schedule_irq
+ 	jmp need_resched
++END(resume_kernel)
+ #endif
+ 	CFI_ENDPROC
+ 
+@@ -352,16 +355,17 @@ sysenter_past_esp:
+ 	movl PT_OLDESP(%esp), %ecx
+ 	xorl %ebp,%ebp
+ 	TRACE_IRQS_ON
+-1:	mov  PT_GS(%esp), %gs
++1:	mov  PT_FS(%esp), %fs
+ 	ENABLE_INTERRUPTS_SYSEXIT
+ 	CFI_ENDPROC
+ .pushsection .fixup,"ax"
+-2:	movl $0,PT_GS(%esp)
++2:	movl $0,PT_FS(%esp)
+ 	jmp 1b
+ .section __ex_table,"a"
+ 	.align 4
+ 	.long 1b,2b
+ .popsection
++ENDPROC(sysenter_entry)
+ 
+ 	# pv sysenter call handler stub
+ ENTRY(sysenter_entry_pv)
+@@ -533,6 +537,7 @@ hypervisor_iret:
+ 	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+ #endif
+ 	CFI_ENDPROC
++ENDPROC(system_call)
+ 
+ 	# perform work that needs to be done immediately before resumption
+ 	ALIGN
+@@ -578,6 +583,7 @@ work_notifysig_v86:
+ 	xorl %edx, %edx
+ 	call do_notify_resume
+ 	jmp resume_userspace_sig
++END(work_pending)
+ 
+ 	# perform syscall exit tracing
+ 	ALIGN
+@@ -593,6 +599,7 @@ syscall_trace_entry:
+ 	cmpl $(nr_syscalls), %eax
+ 	jnae syscall_call
+ 	jmp syscall_exit
++END(syscall_trace_entry)
+ 
+ 	# perform syscall exit tracing
+ 	ALIGN
+@@ -606,6 +613,7 @@ syscall_exit_work:
+ 	movl $1, %edx
+ 	call do_syscall_trace
+ 	jmp resume_userspace
++END(syscall_exit_work)
+ 	CFI_ENDPROC
+ 
+ 	RING0_INT_FRAME			# can't unwind into user space anyway
+@@ -616,16 +624,18 @@ syscall_fault:
+ 	GET_THREAD_INFO(%ebp)
+ 	movl $-EFAULT,PT_EAX(%esp)
+ 	jmp resume_userspace
++END(syscall_fault)
+ 
+ syscall_badsys:
+ 	movl $-ENOSYS,PT_EAX(%esp)
+ 	jmp resume_userspace
++END(syscall_badsys)
+ 	CFI_ENDPROC
+ 
+ #ifndef CONFIG_XEN
+ #define FIXUP_ESPFIX_STACK \
+ 	/* since we are on a wrong stack, we cant make it a C code :( */ \
+-	movl %gs:PDA_cpu, %ebx; \
++	movl %fs:PDA_cpu, %ebx; \
+ 	PER_CPU(cpu_gdt_descr, %ebx); \
+ 	movl GDS_address(%ebx), %ebx; \
+ 	GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
+@@ -656,9 +666,9 @@ syscall_badsys:
+ ENTRY(interrupt)
+ .text
+ 
+-vector=0
+ ENTRY(irq_entries_start)
+ 	RING0_INT_FRAME
++vector=0
+ .rept NR_IRQS
+ 	ALIGN
+  .if vector
+@@ -667,11 +677,16 @@ ENTRY(irq_entries_start)
+ 1:	pushl $~(vector)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp common_interrupt
+-.data
++ .previous
+ 	.long 1b
+-.text
++ .text
+ vector=vector+1
+ .endr
++END(irq_entries_start)
++
++.previous
++END(interrupt)
++.previous
+ 
+ /*
+  * the CPU automatically disables interrupts when executing an IRQ vector,
+@@ -684,6 +699,7 @@ common_interrupt:
+ 	movl %esp,%eax
+ 	call do_IRQ
+ 	jmp ret_from_intr
++ENDPROC(common_interrupt)
+ 	CFI_ENDPROC
+ 
+ #define BUILD_INTERRUPT(name, nr)	\
+@@ -696,10 +712,16 @@ ENTRY(name)				\
+ 	movl %esp,%eax;			\
+ 	call smp_/**/name;		\
+ 	jmp ret_from_intr;		\
+-	CFI_ENDPROC
++	CFI_ENDPROC;			\
++ENDPROC(name)
+ 
+ /* The include is where all of the SMP etc. interrupts come from */
+ #include "entry_arch.h"
++
++/* This alternate entry is needed because we hijack the apic LVTT */
++#if defined(CONFIG_VMI) && defined(CONFIG_X86_LOCAL_APIC)
++BUILD_INTERRUPT(apic_vmi_timer_interrupt,LOCAL_TIMER_VECTOR)
++#endif
+ #else
+ #define UNWIND_ESPFIX_STACK
+ #endif
+@@ -710,7 +732,7 @@ KPROBE_ENTRY(page_fault)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	ALIGN
+ error_code:
+-	/* the function address is in %gs's slot on the stack */
++	/* the function address is in %fs's slot on the stack */
+ 	pushl %es
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	/*CFI_REL_OFFSET es, 0*/
+@@ -739,20 +761,20 @@ error_code:
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	CFI_REL_OFFSET ebx, 0
+ 	cld
+-	pushl %gs
++	pushl %fs
+ 	CFI_ADJUST_CFA_OFFSET 4
+-	/*CFI_REL_OFFSET gs, 0*/
++	/*CFI_REL_OFFSET fs, 0*/
+ 	movl $(__KERNEL_PDA), %ecx
+-	movl %ecx, %gs
++	movl %ecx, %fs
+ 	UNWIND_ESPFIX_STACK
+ 	popl %ecx
+ 	CFI_ADJUST_CFA_OFFSET -4
+ 	/*CFI_REGISTER es, ecx*/
+-	movl PT_GS(%esp), %edi		# get the function address
++	movl PT_FS(%esp), %edi		# get the function address
+ 	movl PT_ORIG_EAX(%esp), %edx	# get the error code
+ 	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
+-	mov  %ecx, PT_GS(%esp)
+-	/*CFI_REL_OFFSET gs, ES*/
++	mov  %ecx, PT_FS(%esp)
++	/*CFI_REL_OFFSET fs, ES*/
+ 	movl $(__USER_DS), %ecx
+ 	movl %ecx, %ds
+ 	movl %ecx, %es
+@@ -844,7 +866,7 @@ critical_fixup_table:
+ 	.byte 6				# pop  %eax
+ 	.byte 7				# pop  %ds
+ 	.byte 8				# pop  %es
+-	.byte 9,9			# pop  %gs
++	.byte 9,9			# pop  %fs
+ 	.byte 10,10,10			# add  $4,%esp
+ 	.byte 11			# iret
+ 	.byte -1,-1,-1,-1		# movb $1,1(%esi) = __DISABLE_INTERRUPTS
+@@ -909,6 +931,7 @@ ENTRY(coprocessor_error)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(coprocessor_error)
+ 
+ ENTRY(simd_coprocessor_error)
+ 	RING0_INT_FRAME
+@@ -918,6 +941,7 @@ ENTRY(simd_coprocessor_error)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(simd_coprocessor_error)
+ 
+ ENTRY(device_not_available)
+ 	RING0_INT_FRAME
+@@ -940,6 +964,7 @@ device_available_emulate:
+ 	call math_state_restore
+ 	jmp ret_from_exception
+ 	CFI_ENDPROC
++END(device_not_available)
+ 
+ #ifndef CONFIG_XEN
+ /*
+@@ -1101,10 +1126,12 @@ ENTRY(native_iret)
+ 	.align 4
+ 	.long 1b,iret_exc
+ .previous
++END(native_iret)
+ 
+ ENTRY(native_irq_enable_sysexit)
+ 	sti
+ 	sysexit
++END(native_irq_enable_sysexit)
+ #endif
+ 
+ KPROBE_ENTRY(int3)
+@@ -1127,6 +1154,7 @@ ENTRY(overflow)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(overflow)
+ 
+ ENTRY(bounds)
+ 	RING0_INT_FRAME
+@@ -1136,6 +1164,7 @@ ENTRY(bounds)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(bounds)
+ 
+ ENTRY(invalid_op)
+ 	RING0_INT_FRAME
+@@ -1145,6 +1174,7 @@ ENTRY(invalid_op)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(invalid_op)
+ 
+ ENTRY(coprocessor_segment_overrun)
+ 	RING0_INT_FRAME
+@@ -1154,6 +1184,7 @@ ENTRY(coprocessor_segment_overrun)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(coprocessor_segment_overrun)
+ 
+ ENTRY(invalid_TSS)
+ 	RING0_EC_FRAME
+@@ -1161,6 +1192,7 @@ ENTRY(invalid_TSS)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(invalid_TSS)
+ 
+ ENTRY(segment_not_present)
+ 	RING0_EC_FRAME
+@@ -1168,6 +1200,7 @@ ENTRY(segment_not_present)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(segment_not_present)
+ 
+ ENTRY(stack_segment)
+ 	RING0_EC_FRAME
+@@ -1175,6 +1208,7 @@ ENTRY(stack_segment)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(stack_segment)
+ 
+ KPROBE_ENTRY(general_protection)
+ 	RING0_EC_FRAME
+@@ -1190,6 +1224,7 @@ ENTRY(alignment_check)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(alignment_check)
+ 
+ ENTRY(divide_error)
+ 	RING0_INT_FRAME
+@@ -1199,6 +1234,7 @@ ENTRY(divide_error)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(divide_error)
+ 
+ #ifdef CONFIG_X86_MCE
+ ENTRY(machine_check)
+@@ -1209,6 +1245,7 @@ ENTRY(machine_check)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(machine_check)
+ #endif
+ 
+ #ifndef CONFIG_XEN
+@@ -1228,6 +1265,7 @@ ENTRY(fixup_4gb_segment)
+ 	CFI_ADJUST_CFA_OFFSET 4
+ 	jmp error_code
+ 	CFI_ENDPROC
++END(spurious_interrupt_bug)
+ 
+ ENTRY(kernel_thread_helper)
+ 	pushl $0		# fake return address for unwinder
+--- head-2010-01-18.orig/arch/x86/kernel/head_32-xen.S	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head_32-xen.S	2009-11-06 10:46:41.000000000 +0100
+@@ -27,6 +27,7 @@
+ #define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
+ #define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id
+ 
++.section .text.head,"ax",@progbits
+ #define VIRT_ENTRY_OFFSET 0x0
+ .org VIRT_ENTRY_OFFSET
+ ENTRY(startup_32)
+@@ -60,11 +61,11 @@ ENTRY(startup_32)
+ 
+ 	movb $1,X86_HARD_MATH
+ 
+-	xorl %eax,%eax			# Clear FS
+-	movl %eax,%fs
++	xorl %eax,%eax		# Clear GS
++	movl %eax,%gs
+ 
+ 	movl $(__KERNEL_PDA),%eax
+-	mov  %eax,%gs
++	mov  %eax,%fs
+ 
+ 	cld			# gcc2 wants the direction flag cleared at all times
+ 
+@@ -75,7 +76,7 @@ ENTRY(startup_32)
+  * Point the GDT at this CPU's PDA.  This will be
+  * cpu_gdt_table and boot_pda.
+  */
+-setup_pda:
++ENTRY(setup_pda)
+ 	/* get the PDA pointer */
+ 	movl $boot_pda, %eax
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -167,7 +167,7 @@ static inline void io_apic_write(unsigne
+  */
+ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+ {
+-	volatile struct io_apic *io_apic = io_apic_base(apic);
++	volatile struct io_apic __iomem *io_apic = io_apic_base(apic);
+ 	if (sis_apic_bug)
+ 		writel(reg, &io_apic->index);
+ 	writel(value, &io_apic->data);
+@@ -392,7 +392,7 @@ static void set_ioapic_affinity_irq(unsi
+ 			break;
+ 		entry = irq_2_pin + entry->next;
+ 	}
+-	set_native_irq_info(irq, cpumask);
++	irq_desc[irq].affinity = cpumask;
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ 
+@@ -531,8 +531,8 @@ static void do_irq_balance(void)
+ 		package_index = CPU_TO_PACKAGEINDEX(i);
+ 		for (j = 0; j < NR_IRQS; j++) {
+ 			unsigned long value_now, delta;
+-			/* Is this an active IRQ? */
+-			if (!irq_desc[j].action)
++			/* Is this an active IRQ or balancing disabled ? */
++			if (!irq_desc[j].action || irq_balancing_disabled(j))
+ 				continue;
+ 			if ( package_index == i )
+ 				IRQ_DELTA(package_index,j) = 0;
+@@ -785,7 +785,7 @@ failed:
+ 	return 0;
+ }
+ 
+-int __init irqbalance_disable(char *str)
++int __devinit irqbalance_disable(char *str)
+ {
+ 	irqbalance_disabled = 1;
+ 	return 1;
+@@ -1329,11 +1329,9 @@ static void ioapic_register_intr(int irq
+ 			trigger == IOAPIC_LEVEL)
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					 handle_fasteoi_irq, "fasteoi");
+-	else {
+-		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
++	else
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					 handle_edge_irq, "edge");
+-	}
+ 	set_intr_gate(vector, interrupt[irq]);
+ }
+ #else
+@@ -1407,7 +1405,6 @@ static void __init setup_IO_APIC_irqs(vo
+ 		}
+ 		spin_lock_irqsave(&ioapic_lock, flags);
+ 		__ioapic_write_entry(apic, pin, entry);
+-		set_native_irq_info(irq, TARGET_CPUS);
+ 		spin_unlock_irqrestore(&ioapic_lock, flags);
+ 	}
+ 	}
+@@ -1638,7 +1635,7 @@ void /*__init*/ print_local_APIC(void * 
+ 	v = apic_read(APIC_LVR);
+ 	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+ 	ver = GET_APIC_VERSION(v);
+-	maxlvt = get_maxlvt();
++	maxlvt = lapic_get_maxlvt();
+ 
+ 	v = apic_read(APIC_TASKPRI);
+ 	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+@@ -1976,7 +1973,7 @@ static void __init setup_ioapic_ids_from
+ #endif
+ 
+ #ifndef CONFIG_XEN
+-static int no_timer_check __initdata;
++int no_timer_check __initdata;
+ 
+ static int __init notimercheck(char *s)
+ {
+@@ -2369,7 +2366,7 @@ static inline void __init check_timer(vo
+ 
+ 	disable_8259A_irq(0);
+ 	set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
+-				      "fasteio");
++				      "fasteoi");
+ 	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+@@ -2662,7 +2659,7 @@ static void set_msi_irq_affinity(unsigne
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	write_msi_msg(irq, &msg);
+-	set_native_irq_info(irq, mask);
++	irq_desc[irq].affinity = mask;
+ }
+ #endif /* CONFIG_SMP */
+ 
+@@ -2681,25 +2678,32 @@ static struct irq_chip msi_chip = {
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+ 
+-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
++int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+ {
+ 	struct msi_msg msg;
+-	int ret;
++	int irq, ret;
++	irq = create_irq();
++	if (irq < 0)
++		return irq;
++
++	set_irq_msi(irq, desc);
+ 	ret = msi_compose_msg(dev, irq, &msg);
+-	if (ret < 0)
++	if (ret < 0) {
++		destroy_irq(irq);
+ 		return ret;
++	}
+ 
+ 	write_msi_msg(irq, &msg);
+ 
+ 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
+ 				      "edge");
+ 
+-	return 0;
++	return irq;
+ }
+ 
+ void arch_teardown_msi_irq(unsigned int irq)
+ {
+-	return;
++	destroy_irq(irq);
+ }
+ 
+ #endif /* CONFIG_PCI_MSI */
+@@ -2739,7 +2743,7 @@ static void set_ht_irq_affinity(unsigned
+ 	dest = cpu_mask_to_apicid(mask);
+ 
+ 	target_ht_irq(irq, dest);
+-	set_native_irq_info(irq, mask);
++	irq_desc[irq].affinity = mask;
+ }
+ #endif
+ 
+@@ -2947,7 +2951,6 @@ int io_apic_set_pci_routing (int ioapic,
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+ 	__ioapic_write_entry(ioapic, pin, entry);
+-	set_native_irq_info(irq, TARGET_CPUS);
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ 
+ 	return 0;
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -10,7 +10,6 @@
+  * io_apic.c.)
+  */
+ 
+-#include <asm/uaccess.h>
+ #include <linux/module.h>
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+@@ -19,19 +18,34 @@
+ #include <linux/cpu.h>
+ #include <linux/delay.h>
+ 
++#include <asm/apic.h>
++#include <asm/uaccess.h>
++
+ DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
+ EXPORT_PER_CPU_SYMBOL(irq_stat);
+ 
+-#ifndef CONFIG_X86_LOCAL_APIC
+ /*
+  * 'what should we do if we get a hw irq event on an illegal vector'.
+  * each architecture has to answer this themselves.
+  */
+ void ack_bad_irq(unsigned int irq)
+ {
+-	printk("unexpected IRQ trap at vector %02x\n", irq);
+-}
++	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
++
++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
++	/*
++	 * Currently unexpected vectors happen only on SMP and APIC.
++	 * We _must_ ack these because every local APIC has only N
++	 * irq slots per priority level, and a 'hanging, unacked' IRQ
++	 * holds up an irq slot - in excessive cases (when multiple
++	 * unexpected vectors occur) that might lock up the APIC
++	 * completely.
++	 * But only ack when the APIC is enabled -AK
++	 */
++	if (cpu_has_apic)
++		ack_APIC_irq();
+ #endif
++}
+ 
+ #ifdef CONFIG_4KSTACKS
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/microcode-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/microcode-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -108,7 +108,7 @@ static ssize_t microcode_write (struct f
+ 	return ret;
+ }
+ 
+-static struct file_operations microcode_fops = {
++static const struct file_operations microcode_fops = {
+ 	.owner		= THIS_MODULE,
+ 	.write		= microcode_write,
+ 	.open		= microcode_open,
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -1079,7 +1079,7 @@ int mp_register_gsi(u32 gsi, int trigger
+ 	static int		gsi_to_irq[MAX_GSI_NUM];
+ 
+ 	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_fadt.sci_int == gsi)
++	if (acpi_gbl_FADT.sci_interrupt == gsi)
+ 		return gsi;
+ 
+ 	ioapic = mp_find_ioapic(gsi);
+@@ -1136,7 +1136,7 @@ int mp_register_gsi(u32 gsi, int trigger
+ 			/*
+ 			 * Don't assign IRQ used by ACPI SCI
+ 			 */
+-			if (gsi == acpi_fadt.sci_int)
++			if (gsi == acpi_gbl_FADT.sci_interrupt)
+ 				gsi = pci_irq++;
+ 			gsi_to_irq[irq] = gsi;
+ 		} else {
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -308,7 +308,7 @@ int dma_declare_coherent_memory(struct d
+ 	return DMA_MEMORY_IO;
+ 
+  free1_out:
+-	kfree(dev->dma_mem->bitmap);
++	kfree(dev->dma_mem);
+  out:
+ 	if (mem_base)
+ 		iounmap(mem_base);
+--- head-2010-01-18.orig/arch/x86/kernel/pcspeaker.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pcspeaker.c	2009-11-06 10:46:41.000000000 +0100
+@@ -6,6 +6,11 @@ static __init int add_pcspkr(void)
+ {
+ 	struct platform_device *pd;
+ 
++#ifdef CONFIG_XEN
++	if (!is_initial_xendomain())
++		return 0;
++#endif
++
+ 	pd = platform_device_register_simple("pcspkr", -1, NULL, 0);
+ 
+ 	return IS_ERR(pd) ? PTR_ERR(pd) : 0;
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -38,6 +38,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/random.h>
+ #include <linux/personality.h>
++#include <linux/tick.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -160,6 +161,7 @@ void cpu_idle(void)
+ 
+ 	/* endless idle loop with no priority at all */
+ 	while (1) {
++		tick_nohz_stop_sched_tick();
+ 		while (!need_resched()) {
+ 			void (*idle)(void);
+ 
+@@ -175,6 +177,7 @@ void cpu_idle(void)
+ 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
+ 			idle();
+ 		}
++		tick_nohz_restart_sched_tick();
+ 		preempt_enable_no_resched();
+ 		schedule();
+ 		preempt_disable();
+@@ -247,8 +250,8 @@ void show_regs(struct pt_regs * regs)
+ 		regs->eax,regs->ebx,regs->ecx,regs->edx);
+ 	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+ 		regs->esi, regs->edi, regs->ebp);
+-	printk(" DS: %04x ES: %04x GS: %04x\n",
+-	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs);
++	printk(" DS: %04x ES: %04x FS: %04x\n",
++	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs);
+ 
+ 	cr0 = read_cr0();
+ 	cr2 = read_cr2();
+@@ -279,7 +282,7 @@ int kernel_thread(int (*fn)(void *), voi
+ 
+ 	regs.xds = __USER_DS;
+ 	regs.xes = __USER_DS;
+-	regs.xgs = __KERNEL_PDA;
++	regs.xfs = __KERNEL_PDA;
+ 	regs.orig_eax = -1;
+ 	regs.eip = (unsigned long) kernel_thread_helper;
+ 	regs.xcs = __KERNEL_CS | get_kernel_rpl();
+@@ -356,7 +359,7 @@ int copy_thread(int nr, unsigned long cl
+ 
+ 	p->thread.eip = (unsigned long) ret_from_fork;
+ 
+-	savesegment(fs,p->thread.fs);
++	savesegment(gs,p->thread.gs);
+ 
+ 	tsk = current;
+ 	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+@@ -434,8 +437,8 @@ void dump_thread(struct pt_regs * regs, 
+ 	dump->regs.eax = regs->eax;
+ 	dump->regs.ds = regs->xds;
+ 	dump->regs.es = regs->xes;
+-	savesegment(fs,dump->regs.fs);
+-	dump->regs.gs = regs->xgs;
++	dump->regs.fs = regs->xfs;
++	savesegment(gs,dump->regs.gs);
+ 	dump->regs.orig_eax = regs->orig_eax;
+ 	dump->regs.eip = regs->eip;
+ 	dump->regs.cs = regs->xcs;
+@@ -637,16 +640,6 @@ struct task_struct fastcall * __switch_t
+ 		prefetch(&next->i387.fxsave);
+ 
+ 	/*
+-	 * Restore %fs if needed.
+-	 *
+-	 * Glibc normally makes %fs be zero.
+-	 */
+-	if (unlikely(next->fs))
+-		loadsegment(fs, next->fs);
+-
+-	write_pda(pcurrent, next_p);
+-
+-	/*
+ 	 * Now maybe handle debug registers
+ 	 */
+ 	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
+@@ -654,6 +647,15 @@ struct task_struct fastcall * __switch_t
+ 
+ 	disable_tsc(prev_p, next_p);
+ 
++	/*
++	 * Leave lazy mode, flushing any hypercalls made here.
++	 * This must be done before restoring TLS segments so
++	 * the GDT and LDT are properly updated, and must be
++	 * done before math_state_restore, so the TS bit is up
++	 * to date.
++	 */
++	arch_leave_lazy_cpu_mode();
++
+ 	/* If the task has used fpu the last 5 timeslices, just do a full
+ 	 * restore of the math state immediately to avoid the trap; the
+ 	 * chances of needing FPU soon are obviously high now
+@@ -661,6 +663,14 @@ struct task_struct fastcall * __switch_t
+ 	if (next_p->fpu_counter > 5)
+ 		math_state_restore();
+ 
++	/*
++	 * Restore %gs if needed (which is common)
++	 */
++	if (prev->gs | next->gs)
++		loadsegment(gs, next->gs);
++
++	write_pda(pcurrent, next_p);
++
+ 	return prev_p;
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -33,7 +33,6 @@
+ #include <linux/initrd.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+-#include <linux/platform_device.h>
+ #include <linux/console.h>
+ #include <linux/mca.h>
+ #include <linux/root_dev.h>
+@@ -148,7 +147,7 @@ unsigned long saved_videomode;
+ #define RAMDISK_PROMPT_FLAG		0x8000
+ #define RAMDISK_LOAD_FLAG		0x4000	
+ 
+-static char command_line[COMMAND_LINE_SIZE];
++static char __initdata command_line[COMMAND_LINE_SIZE];
+ 
+ unsigned char __initdata boot_params[PARAM_SIZE];
+ 
+@@ -649,8 +648,8 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	if ((i = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
+ 		i = COMMAND_LINE_SIZE;
+-	memcpy(saved_command_line, xen_start_info->cmd_line, i);
+-	saved_command_line[i - 1] = '\0';
++	memcpy(boot_command_line, xen_start_info->cmd_line, i);
++	boot_command_line[i - 1] = '\0';
+ 	parse_early_param();
+ 
+ 	if (user_defined_memmap) {
+@@ -658,11 +657,19 @@ void __init setup_arch(char **cmdline_p)
+ 		print_memory_map("user");
+ 	}
+ 
+-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
++	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
+ 	max_low_pfn = setup_memory();
+ 
++#ifdef CONFIG_VMI
++	/*
++	 * Must be after max_low_pfn is determined, and before kernel
++	 * pagetables are setup.
++	 */
++	vmi_init();
++#endif
++
+ 	/*
+ 	 * NOTE: before this point _nobody_ is allowed to allocate
+ 	 * any memory using the bootmem allocator.  Although the
+@@ -825,7 +832,6 @@ void __init setup_arch(char **cmdline_p)
+ 		conswitchp = &dummy_con;
+ #endif
+ 	}
+-	tsc_init();
+ }
+ 
+ static int
+@@ -835,31 +841,3 @@ xen_panic_event(struct notifier_block *t
+ 	/* we're never actually going to get here... */
+ 	return NOTIFY_DONE;
+ }
+-
+-static __init int add_pcspkr(void)
+-{
+-	struct platform_device *pd;
+-	int ret;
+-
+-	if (!is_initial_xendomain())
+-		return 0;
+-
+-	pd = platform_device_alloc("pcspkr", -1);
+-	if (!pd)
+-		return -ENOMEM;
+-
+-	ret = platform_device_add(pd);
+-	if (ret)
+-		platform_device_put(pd);
+-
+-	return ret;
+-}
+-device_initcall(add_pcspkr);
+-
+-/*
+- * Local Variables:
+- * mode:c
+- * c-file-style:"k&r"
+- * c-basic-offset:8
+- * End:
+- */
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -335,8 +335,7 @@ static void flush_tlb_others(cpumask_t c
+ 	/*
+ 	 * i'm not happy about this global shared spinlock in the
+ 	 * MM hot path, but we'll see how contended it is.
+-	 * Temporarily this turns IRQs off, so that lockups are
+-	 * detected by the NMI watchdog.
++	 * AK: x86-64 has a faster method that could be ported.
+ 	 */
+ 	spin_lock(&tlbstate_lock);
+ 	
+@@ -361,7 +360,7 @@ static void flush_tlb_others(cpumask_t c
+ 
+ 	while (!cpus_empty(flush_cpumask))
+ 		/* nothing. lockup detection does not belong here */
+-		mb();
++		cpu_relax();
+ 
+ 	flush_mm = NULL;
+ 	flush_va = 0;
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -51,6 +51,7 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/posix-timers.h>
+ #include <linux/cpufreq.h>
++#include <linux/clocksource.h>
+ 
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -75,25 +76,17 @@
+ #include <xen/evtchn.h>
+ #include <xen/interface/vcpu.h>
+ 
+-#if defined (__i386__)
+-#include <asm/i8259.h>
++#ifdef CONFIG_X86_32
+ #include <asm/i8253.h>
+ DEFINE_SPINLOCK(i8253_lock);
+ EXPORT_SYMBOL(i8253_lock);
+-#endif
+-
+-#define XEN_SHIFT 22
+-
+ int pit_latch_buggy;              /* extern */
+-
+-#if defined(__x86_64__)
+-unsigned long vxtime_hz = PIT_TICK_RATE;
+-struct vxtime_data __vxtime __section_vxtime;   /* for vsyscalls */
++#else
+ volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+-struct timespec __xtime __section_xtime;
+-struct timezone __sys_tz __section_sys_tz;
+ #endif
+ 
++#define XEN_SHIFT 22
++
+ unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
+ EXPORT_SYMBOL(cpu_khz);
+ 
+@@ -113,9 +106,6 @@ static DEFINE_PER_CPU(struct shadow_time
+ static struct timespec shadow_tv;
+ static u32 shadow_tv_version;
+ 
+-static struct timeval monotonic_tv;
+-static spinlock_t monotonic_lock = SPIN_LOCK_UNLOCKED;
+-
+ /* Keep track of last time we did processing/updating of jiffies and xtime. */
+ static u64 processed_system_time;   /* System time (ns) at last processing. */
+ static DEFINE_PER_CPU(u64, processed_system_time);
+@@ -210,7 +200,7 @@ static inline u64 scale_delta(u64 delta,
+ 	return product;
+ }
+ 
+-void init_cpu_khz(void)
++static void init_cpu_khz(void)
+ {
+ 	u64 __cpu_khz = 1000000ULL << 32;
+ 	struct vcpu_time_info *info = &vcpu_info(0)->time;
+@@ -229,16 +219,6 @@ static u64 get_nsec_offset(struct shadow
+ 	return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
+ }
+ 
+-#ifdef CONFIG_X86_64
+-static unsigned long get_usec_offset(struct shadow_time_info *shadow)
+-{
+-	u64 now, delta;
+-	rdtscll(now);
+-	delta = now - shadow->tsc_timestamp;
+-	return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift);
+-}
+-#endif
+-
+ static void __update_wallclock(time_t sec, long nsec)
+ {
+ 	long wtm_nsec, xtime_nsec;
+@@ -351,142 +331,6 @@ void rtc_cmos_write(unsigned char val, u
+ }
+ EXPORT_SYMBOL(rtc_cmos_write);
+ 
+-#ifdef CONFIG_X86_64
+-
+-/*
+- * This version of gettimeofday has microsecond resolution
+- * and better than microsecond precision on fast x86 machines with TSC.
+- */
+-void do_gettimeofday(struct timeval *tv)
+-{
+-	unsigned long seq;
+-	unsigned long usec, sec;
+-	unsigned long flags;
+-	s64 nsec;
+-	unsigned int cpu;
+-	struct shadow_time_info *shadow;
+-	u32 local_time_version;
+-
+-	cpu = get_cpu();
+-	shadow = &per_cpu(shadow_time, cpu);
+-
+-	do {
+-		local_time_version = shadow->version;
+-		seq = read_seqbegin(&xtime_lock);
+-
+-		usec = get_usec_offset(shadow);
+-
+-		sec = xtime.tv_sec;
+-		usec += (xtime.tv_nsec / NSEC_PER_USEC);
+-
+-		nsec = shadow->system_timestamp - processed_system_time;
+-		__normalize_time(&sec, &nsec);
+-		usec += (long)nsec / NSEC_PER_USEC;
+-
+-		if (unlikely(!time_values_up_to_date(cpu))) {
+-			/*
+-			 * We may have blocked for a long time,
+-			 * rendering our calculations invalid
+-			 * (e.g. the time delta may have
+-			 * overflowed). Detect that and recalculate
+-			 * with fresh values.
+-			 */
+-			get_time_values_from_xen(cpu);
+-			continue;
+-		}
+-	} while (read_seqretry(&xtime_lock, seq) ||
+-		 (local_time_version != shadow->version));
+-
+-	put_cpu();
+-
+-	while (usec >= USEC_PER_SEC) {
+-		usec -= USEC_PER_SEC;
+-		sec++;
+-	}
+-
+-	spin_lock_irqsave(&monotonic_lock, flags);
+-	if ((sec > monotonic_tv.tv_sec) ||
+-	    ((sec == monotonic_tv.tv_sec) && (usec > monotonic_tv.tv_usec)))
+-	{
+-		monotonic_tv.tv_sec = sec;
+-		monotonic_tv.tv_usec = usec;
+-	} else {
+-		sec = monotonic_tv.tv_sec;
+-		usec = monotonic_tv.tv_usec;
+-	}
+-	spin_unlock_irqrestore(&monotonic_lock, flags);
+-
+-	tv->tv_sec = sec;
+-	tv->tv_usec = usec;
+-}
+-
+-EXPORT_SYMBOL(do_gettimeofday);
+-
+-int do_settimeofday(struct timespec *tv)
+-{
+-	time_t sec;
+-	s64 nsec;
+-	unsigned int cpu;
+-	struct shadow_time_info *shadow;
+-	struct xen_platform_op op;
+-
+-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+-		return -EINVAL;
+-
+-	if (!is_initial_xendomain() && !independent_wallclock)
+-		return -EPERM;
+-
+-	cpu = get_cpu();
+-	shadow = &per_cpu(shadow_time, cpu);
+-
+-	write_seqlock_irq(&xtime_lock);
+-
+-	/*
+-	 * Ensure we don't get blocked for a long time so that our time delta
+-	 * overflows. If that were to happen then our shadow time values would
+-	 * be stale, so we can retry with fresh ones.
+-	 */
+-	for (;;) {
+-		nsec = tv->tv_nsec - get_nsec_offset(shadow);
+-		if (time_values_up_to_date(cpu))
+-			break;
+-		get_time_values_from_xen(cpu);
+-	}
+-	sec = tv->tv_sec;
+-	__normalize_time(&sec, &nsec);
+-
+-	if (is_initial_xendomain() && !independent_wallclock) {
+-		op.cmd = XENPF_settime;
+-		op.u.settime.secs        = sec;
+-		op.u.settime.nsecs       = nsec;
+-		op.u.settime.system_time = shadow->system_timestamp;
+-		WARN_ON(HYPERVISOR_platform_op(&op));
+-		update_wallclock();
+-	} else if (independent_wallclock) {
+-		nsec -= shadow->system_timestamp;
+-		__normalize_time(&sec, &nsec);
+-		__update_wallclock(sec, nsec);
+-	}
+-	ntp_clear();
+-
+-	/* Reset monotonic gettimeofday() timeval. */
+-	spin_lock(&monotonic_lock);
+-	monotonic_tv.tv_sec = 0;
+-	monotonic_tv.tv_usec = 0;
+-	spin_unlock(&monotonic_lock);
+-
+-	write_sequnlock_irq(&xtime_lock);
+-
+-	put_cpu();
+-
+-	clock_was_set();
+-	return 0;
+-}
+-
+-EXPORT_SYMBOL(do_settimeofday);
+-
+-#endif
+-
+ static void sync_xen_wallclock(unsigned long dummy);
+ static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
+ static void sync_xen_wallclock(unsigned long dummy)
+@@ -535,15 +379,7 @@ static int set_rtc_mmss(unsigned long no
+ 	return retval;
+ }
+ 
+-#ifdef CONFIG_X86_64
+-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
+- *		Note: This function is required to return accurate
+- *		time even in the absence of multiple timer ticks.
+- */
+-unsigned long long monotonic_clock(void)
+-#else
+ unsigned long long sched_clock(void)
+-#endif
+ {
+ 	unsigned int cpu = get_cpu();
+ 	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+@@ -563,21 +399,18 @@ unsigned long long sched_clock(void)
+ 
+ 	return time;
+ }
+-#ifdef CONFIG_X86_64
+-EXPORT_SYMBOL(monotonic_clock);
+-
+-unsigned long long sched_clock(void)
+-{
+-	return monotonic_clock();
+-}
+-#endif
+ 
+ unsigned long profile_pc(struct pt_regs *regs)
+ {
+ 	unsigned long pc = instruction_pointer(regs);
+ 
+ #if defined(CONFIG_SMP) || defined(__x86_64__)
+-	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
++# ifdef __i386__
++	if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs)
++# else
++	if (!user_mode(regs)
++# endif
++	    && in_lock_functions(pc)) {
+ # ifdef CONFIG_FRAME_POINTER
+ #  ifdef __i386__
+ 		return ((unsigned long *)regs->ebp)[1];
+@@ -586,14 +419,11 @@ unsigned long profile_pc(struct pt_regs 
+ #  endif
+ # else
+ #  ifdef __i386__
+-		unsigned long *sp;
+-		if ((regs->xcs & 2) == 0)
+-			sp = (unsigned long *)&regs->esp;
+-		else
+-			sp = (unsigned long *)regs->esp;
++		unsigned long *sp = (unsigned long *)&regs->esp;
+ #  else
+ 		unsigned long *sp = (unsigned long *)regs->rsp;
+ #  endif
++
+ 		/* Return address is either directly at stack pointer
+ 		   or above a saved eflags. Eflags has bits 22-31 zero,
+ 		   kernel addresses don't. */
+@@ -747,19 +577,6 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	return IRQ_HANDLED;
+ }
+ 
+-#ifndef CONFIG_X86_64
+-
+-void tsc_init(void)
+-{
+-	init_cpu_khz();
+-	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
+-	       cpu_khz / 1000, cpu_khz % 1000);
+-
+-	use_tsc_delay();
+-}
+-
+-#include <linux/clocksource.h>
+-
+ void mark_tsc_unstable(void)
+ {
+ #ifndef CONFIG_XEN /* XXX Should tell the hypervisor about this fact. */
+@@ -815,21 +632,9 @@ static struct clocksource clocksource_xe
+ 	.mask			= CLOCKSOURCE_MASK(64),
+ 	.mult			= 1 << XEN_SHIFT,		/* time directly in nanoseconds */
+ 	.shift			= XEN_SHIFT,
+-	.is_continuous		= 1,
++	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+ };
+ 
+-static int __init init_xen_clocksource(void)
+-{
+-	clocksource_xen.mult = clocksource_khz2mult(cpu_khz,
+-						clocksource_xen.shift);
+-
+-	return clocksource_register(&clocksource_xen);
+-}
+-
+-module_init(init_xen_clocksource);
+-
+-#endif
+-
+ static void init_missing_ticks_accounting(unsigned int cpu)
+ {
+ 	struct vcpu_register_runstate_memory_area area;
+@@ -850,7 +655,7 @@ static void init_missing_ticks_accountin
+ }
+ 
+ /* not static: needed by APM */
+-unsigned long get_cmos_time(void)
++unsigned long read_persistent_clock(void)
+ {
+ 	unsigned long retval;
+ 	unsigned long flags;
+@@ -863,11 +668,11 @@ unsigned long get_cmos_time(void)
+ 
+ 	return retval;
+ }
+-EXPORT_SYMBOL(get_cmos_time);
+ 
+ static void sync_cmos_clock(unsigned long dummy);
+ 
+ static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
++int no_sync_cmos_clock;
+ 
+ static void sync_cmos_clock(unsigned long dummy)
+ {
+@@ -911,7 +716,8 @@ static void sync_cmos_clock(unsigned lon
+ 
+ void notify_arch_cmos_timer(void)
+ {
+-	mod_timer(&sync_cmos_timer, jiffies + 1);
++	if (!no_sync_cmos_clock)
++		mod_timer(&sync_cmos_timer, jiffies + 1);
+ 	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
+ }
+ 
+@@ -944,29 +750,11 @@ static int time_init_device(void)
+ 
+ device_initcall(time_init_device);
+ 
+-#ifdef CONFIG_HPET_TIMER
+ extern void (*late_time_init)(void);
+-/* Duplicate of time_init() below, with hpet_enable part added */
+-static void __init hpet_time_init(void)
+-{
+-	struct timespec ts;
+-	ts.tv_sec = get_cmos_time();
+-	ts.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+-
+-	do_settimeofday(&ts);
+-
+-	if ((hpet_enable() >= 0) && hpet_use_timer) {
+-		printk("Using HPET for base-timer\n");
+-	}
+-
+-	do_time_init();
+-}
+-#endif
+ 
+ /* Dynamically-mapped IRQ. */
+ DEFINE_PER_CPU(int, timer_irq);
+ 
+-extern void (*late_time_init)(void);
+ static void setup_cpu0_timer_irq(void)
+ {
+ 	per_cpu(timer_irq, 0) =
+@@ -974,7 +762,7 @@ static void setup_cpu0_timer_irq(void)
+ 			VIRQ_TIMER,
+ 			0,
+ 			timer_interrupt,
+-			IRQF_DISABLED|IRQF_TIMER,
++			IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING,
+ 			"timer0",
+ 			NULL);
+ 	BUG_ON(per_cpu(timer_irq, 0) < 0);
+@@ -986,16 +774,9 @@ static struct vcpu_set_periodic_timer xe
+ 
+ void __init time_init(void)
+ {
+-#ifdef CONFIG_HPET_TIMER
+-	if (is_hpet_capable()) {
+-		/*
+-		 * HPET initialization needs to do memory-mapped io. So, let
+-		 * us do a late initialization after mem_init().
+-		 */
+-		late_time_init = hpet_time_init;
+-		return;
+-	}
+-#endif
++	init_cpu_khz();
++	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
++	       cpu_khz / 1000, cpu_khz % 1000);
+ 
+ 	switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
+ 				   &xen_set_periodic_tick)) {
+@@ -1014,18 +795,12 @@ void __init time_init(void)
+ 	per_cpu(processed_system_time, 0) = processed_system_time;
+ 	init_missing_ticks_accounting(0);
+ 
+-	update_wallclock();
++	clocksource_register(&clocksource_xen);
+ 
+-#ifdef CONFIG_X86_64
+-	init_cpu_khz();
+-	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
+-	       cpu_khz / 1000, cpu_khz % 1000);
++	update_wallclock();
+ 
+-	vxtime.mode = VXTIME_TSC;
+-	vxtime.quot = (1000000L << 32) / vxtime_hz;
+-	vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+-	sync_core();
+-	rdtscll(vxtime.last_tsc);
++#ifndef CONFIG_X86_64
++	use_tsc_delay();
+ #endif
+ 
+ 	/* Cannot request_irq() until kmem is initialised. */
+@@ -1182,7 +957,7 @@ int __cpuinit local_setup_timer(unsigned
+ 	irq = bind_virq_to_irqhandler(VIRQ_TIMER,
+ 				      cpu,
+ 				      timer_interrupt,
+-				      IRQF_DISABLED|IRQF_TIMER,
++				      IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING,
+ 				      timer_name[cpu],
+ 				      NULL);
+ 	if (irq < 0)
+@@ -1271,7 +1046,7 @@ static ctl_table xen_table[] = {
+ };
+ static int __init xen_sysctl_init(void)
+ {
+-	(void)register_sysctl_table(xen_table, 0);
++	(void)register_sysctl_table(xen_table);
+ 	return 0;
+ }
+ __initcall(xen_sysctl_init);
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -100,6 +100,7 @@ asmlinkage void fixup_4gb_segment(void);
+ asmlinkage void machine_check(void);
+ 
+ int kstack_depth_to_print = 24;
++static unsigned int code_bytes = 64;
+ ATOMIC_NOTIFIER_HEAD(i386die_chain);
+ 
+ int register_die_notifier(struct notifier_block *nb)
+@@ -297,10 +298,11 @@ void show_registers(struct pt_regs *regs
+ 	int i;
+ 	int in_kernel = 1;
+ 	unsigned long esp;
+-	unsigned short ss;
++	unsigned short ss, gs;
+ 
+ 	esp = (unsigned long) (&regs->esp);
+ 	savesegment(ss, ss);
++	savesegment(gs, gs);
+ 	if (user_mode_vm(regs)) {
+ 		in_kernel = 0;
+ 		esp = regs->esp;
+@@ -319,8 +321,8 @@ void show_registers(struct pt_regs *regs
+ 		regs->eax, regs->ebx, regs->ecx, regs->edx);
+ 	printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+ 		regs->esi, regs->edi, regs->ebp, esp);
+-	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
+-		regs->xds & 0xffff, regs->xes & 0xffff, ss);
++	printk(KERN_EMERG "ds: %04x   es: %04x   fs: %04x  gs: %04x  ss: %04x\n",
++	       regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
+ 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+ 		TASK_COMM_LEN, current->comm, current->pid,
+ 		current_thread_info(), current, current->thread_info);
+@@ -330,7 +332,8 @@ void show_registers(struct pt_regs *regs
+ 	 */
+ 	if (in_kernel) {
+ 		u8 *eip;
+-		int code_bytes = 64;
++		unsigned int code_prologue = code_bytes * 43 / 64;
++		unsigned int code_len = code_bytes;
+ 		unsigned char c;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+@@ -338,14 +341,14 @@ void show_registers(struct pt_regs *regs
+ 
+ 		printk(KERN_EMERG "Code: ");
+ 
+-		eip = (u8 *)regs->eip - 43;
++		eip = (u8 *)regs->eip - code_prologue;
+ 		if (eip < (u8 *)PAGE_OFFSET ||
+ 			probe_kernel_address(eip, c)) {
+ 			/* try starting at EIP */
+ 			eip = (u8 *)regs->eip;
+-			code_bytes = 32;
++			code_len = code_len - code_prologue + 1;
+ 		}
+-		for (i = 0; i < code_bytes; i++, eip++) {
++		for (i = 0; i < code_len; i++, eip++) {
+ 			if (eip < (u8 *)PAGE_OFFSET ||
+ 				probe_kernel_address(eip, c)) {
+ 				printk(" Bad EIP value.");
+@@ -1134,3 +1137,13 @@ static int __init kstack_setup(char *s)
+ 	return 1;
+ }
+ __setup("kstack=", kstack_setup);
++
++static int __init code_bytes_setup(char *s)
++{
++	code_bytes = simple_strtoul(s, NULL, 0);
++	if (code_bytes > 8192)
++		code_bytes = 8192;
++
++	return 1;
++}
++__setup("code_bytes=", code_bytes_setup);
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -46,43 +46,17 @@ int unregister_page_fault_notifier(struc
+ }
+ EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
+ 
+-static inline int notify_page_fault(enum die_val val, const char *str,
+-			struct pt_regs *regs, long err, int trap, int sig)
++static inline int notify_page_fault(struct pt_regs *regs, long err)
+ {
+ 	struct die_args args = {
+ 		.regs = regs,
+-		.str = str,
++		.str = "page fault",
+ 		.err = err,
+-		.trapnr = trap,
+-		.signr = sig
++		.trapnr = 14,
++		.signr = SIGSEGV
+ 	};
+-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+-}
+-
+-/*
+- * Unlock any spinlocks which will prevent us from getting the
+- * message out 
+- */
+-void bust_spinlocks(int yes)
+-{
+-	int loglevel_save = console_loglevel;
+-
+-	if (yes) {
+-		oops_in_progress = 1;
+-		return;
+-	}
+-#ifdef CONFIG_VT
+-	unblank_screen();
+-#endif
+-	oops_in_progress = 0;
+-	/*
+-	 * OK, the message is on the console.  Now we call printk()
+-	 * without oops_in_progress set so that printk will give klogd
+-	 * a poke.  Hold onto your hats...
+-	 */
+-	console_loglevel = 15;		/* NMI oopser may have shut the console up */
+-	printk(" ");
+-	console_loglevel = loglevel_save;
++	return atomic_notifier_call_chain(&notify_page_fault_chain,
++	                                  DIE_PAGE_FAULT, &args);
+ }
+ 
+ /*
+@@ -476,8 +450,7 @@ fastcall void __kprobes do_page_fault(st
+ 		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+ 		if (spurious_fault(regs, address, error_code))
+ 			return;
+-		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+-						SIGSEGV) == NOTIFY_STOP)
++		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ 			return;
+ 		/* 
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+@@ -486,8 +459,7 @@ fastcall void __kprobes do_page_fault(st
+ 		goto bad_area_nosemaphore;
+ 	}
+ 
+-	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+-					SIGSEGV) == NOTIFY_STOP)
++	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ 		return;
+ 
+ 	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+--- head-2010-01-18.orig/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/highmem_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -33,14 +33,16 @@ static void *__kmap_atomic(struct page *
+ 
+ 	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+ 	pagefault_disable();
++
++	idx = type + KM_TYPE_NR*smp_processor_id();
++	BUG_ON(!pte_none(*(kmap_pte-idx)));
++
+ 	if (!PageHighMem(page))
+ 		return page_address(page);
+ 
+-	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+-	if (!pte_none(*(kmap_pte-idx)))
+-		BUG();
+ 	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
++	/*arch_flush_lazy_mmu_mode();*/
+ 
+ 	return (void*) vaddr;
+ }
+@@ -94,6 +96,7 @@ void *kmap_atomic_pfn(unsigned long pfn,
+ 	idx = type + KM_TYPE_NR*smp_processor_id();
+ 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ 	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
++	/*arch_flush_lazy_mmu_mode();*/
+ 
+ 	return (void*) vaddr;
+ }
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -66,6 +66,7 @@ static pmd_t * __init one_md_table_init(
+ 		
+ #ifdef CONFIG_X86_PAE
+ 	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++	paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT);
+ 	make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+ 	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+ 	pud = pud_offset(pgd, 0);
+@@ -87,6 +88,7 @@ static pte_t * __init one_page_table_ini
+ {
+ 	if (pmd_none(*pmd)) {
+ 		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++		paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+ 					  XENFEAT_writable_page_tables);
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -149,6 +149,8 @@ void __set_fixmap (enum fixed_addresses 
+ void __init reserve_top_address(unsigned long reserve)
+ {
+ 	BUG_ON(fixmaps > 0);
++	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
++	       (int)-reserve);
+ 	__FIXADDR_TOP = -reserve - PAGE_SIZE;
+ 	__VMALLOC_RESERVE += reserve;
+ }
+@@ -258,6 +260,12 @@ void pgd_ctor(void *pgd, struct kmem_cac
+ 				swapper_pg_dir + USER_PTRS_PER_PGD,
+ 				KERNEL_PGD_PTRS);
+ 		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++
++		/* must happen under lock */
++		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
++			__pa(swapper_pg_dir) >> PAGE_SHIFT,
++			USER_PTRS_PER_PGD, PTRS_PER_PGD - USER_PTRS_PER_PGD);
++
+ 		pgd_list_add(pgd);
+ 		spin_unlock_irqrestore(&pgd_lock, flags);
+ 	}
+@@ -268,6 +276,7 @@ void pgd_dtor(void *pgd, struct kmem_cac
+ {
+ 	unsigned long flags; /* can be called from interrupt context */
+ 
++	paravirt_release_pd(__pa(pgd) >> PAGE_SHIFT);
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 	pgd_list_del(pgd);
+ 	spin_unlock_irqrestore(&pgd_lock, flags);
+@@ -292,6 +301,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+ 			if (!pmd)
+ 				goto out_oom;
++			paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
+ 			set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+ 		}
+ 		return pgd;
+@@ -314,6 +324,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 		pmd[i] = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+ 		if (!pmd[i])
+ 			goto out_oom;
++		paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT);
+ 	}
+ 
+ 	spin_lock_irqsave(&pgd_lock, flags);
+@@ -354,12 +365,17 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 
+ out_oom:
+ 	if (HAVE_SHARED_KERNEL_PMD) {
+-		for (i--; i >= 0; i--)
+-			kmem_cache_free(pmd_cache,
+-					(void *)__va(pgd_val(pgd[i])-1));
++		for (i--; i >= 0; i--) {
++			pgd_t pgdent = pgd[i];
++			void* pmd = (void *)__va(pgd_val(pgdent)-1);
++			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
++			kmem_cache_free(pmd_cache, pmd);
++		}
+ 	} else {
+-		for (i--; i >= 0; i--)
++		for (i--; i >= 0; i--) {
++			paravirt_release_pd(__pa(pmd[i]) >> PAGE_SHIFT);
+ 			kmem_cache_free(pmd_cache, pmd[i]);
++		}
+ 		kfree(pmd);
+ 	}
+ 	kmem_cache_free(pgd_cache, pgd);
+@@ -383,7 +399,9 @@ void pgd_free(pgd_t *pgd)
+ 	/* 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) {
+-			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
++			pgd_t pgdent = pgd[i];
++			void* pmd = (void *)__va(pgd_val(pgdent)-1);
++			paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
+ 			kmem_cache_free(pmd_cache, pmd);
+ 		}
+ 
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:46:41.000000000 +0100
+@@ -465,7 +465,7 @@ ia32_sys_call_table:
+ 	.quad sys32_vm86_warning	/* vm86old */ 
+ 	.quad compat_sys_wait4
+ 	.quad sys_swapoff		/* 115 */
+-	.quad sys32_sysinfo
++	.quad compat_sys_sysinfo
+ 	.quad sys32_ipc
+ 	.quad sys_fsync
+ 	.quad stub32_sigreturn
+@@ -510,7 +510,7 @@ ia32_sys_call_table:
+ 	.quad sys_sched_yield
+ 	.quad sys_sched_get_priority_max
+ 	.quad sys_sched_get_priority_min  /* 160 */
+-	.quad sys_sched_rr_get_interval
++	.quad sys32_sched_rr_get_interval
+ 	.quad compat_sys_nanosleep
+ 	.quad sys_mremap
+ 	.quad sys_setresuid16
+@@ -668,4 +668,5 @@ ia32_sys_call_table:
+ 	.quad compat_sys_vmsplice
+ 	.quad compat_sys_move_pages
+ 	.quad sys_getcpu
++	.quad sys_epoll_pwait
+ ia32_syscall_end:		
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_64-xen.c	2008-04-15 09:29:41.000000000 +0200
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -59,7 +59,7 @@ unsigned long acpi_wakeup_address = 0;
+ unsigned long acpi_video_flags;
+ extern char wakeup_start, wakeup_end;
+ 
+-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
++extern unsigned long acpi_copy_wakeup_routine(unsigned long);
+ 
+ static pgd_t low_ptr;
+ 
+@@ -67,8 +67,10 @@ static void init_low_mapping(void)
+ {
+ 	pgd_t *slot0 = pgd_offset(current->mm, 0UL);
+ 	low_ptr = *slot0;
++	/* FIXME: We're playing with the current task's page tables here, which
++	 * is potentially dangerous on SMP systems.
++	 */
+ 	set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
+-	WARN_ON(num_online_cpus() != 1);
+ 	local_flush_tlb();
+ }
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:49:03.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 10:52:06.000000000 +0100
+@@ -90,6 +90,13 @@ static inline int bad_addr(unsigned long
+ 		return 1;
+ 	}
+ 
++#ifdef CONFIG_NUMA
++	/* NUMA memory to node map */
++	if (last >= nodemap_addr && addr < nodemap_addr + nodemap_size) {
++		*addrp = nodemap_addr + nodemap_size;
++		return 1;
++	}
++#endif
+ 	/* XXX ramdisk image here? */ 
+ #else
+ 	if (last < (table_end<<PAGE_SHIFT)) {
+@@ -215,6 +222,37 @@ unsigned long __init e820_end_of_ram(voi
+ }
+ 
+ /*
++ * Find the hole size in the range.
++ */
++unsigned long __init e820_hole_size(unsigned long start, unsigned long end)
++{
++	unsigned long ram = 0;
++	int i;
++
++	for (i = 0; i < e820.nr_map; i++) {
++		struct e820entry *ei = &e820.map[i];
++		unsigned long last, addr;
++
++		if (ei->type != E820_RAM ||
++		    ei->addr+ei->size <= start ||
++		    ei->addr >= end)
++			continue;
++
++		addr = round_up(ei->addr, PAGE_SIZE);
++		if (addr < start)
++			addr = start;
++
++		last = round_down(ei->addr + ei->size, PAGE_SIZE);
++		if (last >= end)
++			last = end;
++
++		if (last > addr)
++			ram += last - addr;
++	}
++	return ((end - start) - ram);
++}
++
++/*
+  * Mark e820 reserved areas as busy for the resource manager.
+  */
+ void __init e820_reserve_resources(struct e820entry *e820, int nr_map)
+@@ -751,7 +789,7 @@ static int __init parse_memmap_opt(char 
+ }
+ early_param("memmap", parse_memmap_opt);
+ 
+-void finish_e820_parsing(void)
++void __init finish_e820_parsing(void)
+ {
+ 	if (userdef) {
+ 		printk(KERN_INFO "user-defined physical RAM map:\n");
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:46:41.000000000 +0100
+@@ -629,6 +629,9 @@ END(invalidate_interrupt\num)
+ ENTRY(call_function_interrupt)
+ 	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
+ END(call_function_interrupt)
++ENTRY(irq_move_cleanup_interrupt)
++	apicinterrupt IRQ_MOVE_CLEANUP_VECTOR,smp_irq_move_cleanup_interrupt
++END(irq_move_cleanup_interrupt)
+ #endif
+ 
+ ENTRY(apic_timer_interrupt)
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -45,8 +45,6 @@ static void __init clear_bss(void)
+ #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
+@@ -62,14 +60,14 @@ static void __init copy_bootdata(char *r
+ 		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
+ 	}
+ 	command_line = (char *) ((u64)(new_data));
+-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
++	memcpy(boot_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';
++	memcpy(boot_command_line, xen_start_info->cmd_line, max_cmdline);
++	boot_command_line[max_cmdline-1] = '\0';
+ #endif
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include <acpi/acpi_bus.h>
+ #endif
+ 
++#include <asm/idle.h>
+ #include <asm/io.h>
+ #include <asm/smp.h>
+ #include <asm/desc.h>
+@@ -47,7 +48,20 @@
+ #include <asm/msidef.h>
+ #include <asm/hypertransport.h>
+ 
+-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
++struct irq_cfg {
++#ifndef CONFIG_XEN
++	cpumask_t domain;
++	cpumask_t old_domain;
++#endif
++	unsigned move_cleanup_count;
++	u8 vector;
++	u8 move_in_progress : 1;
++};
++
++/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
++struct irq_cfg irq_cfg[NR_IRQS] __read_mostly;
++
++static int assign_irq_vector(int irq, cpumask_t mask);
+ 
+ #define __apicdebuginit  __init
+ 
+@@ -89,7 +103,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
+  * Rough estimation of how many shared IRQs there are, can
+  * be changed anytime.
+  */
+-#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
++#define MAX_PLUS_SHARED_IRQS NR_IRQS
+ #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
+ 
+ /*
+@@ -262,21 +276,19 @@ static void __target_IO_APIC_irq(unsigne
+ 
+ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+ {
++	struct irq_cfg *cfg = irq_cfg + irq;
+ 	unsigned long flags;
+ 	unsigned int dest;
+ 	cpumask_t tmp;
+-	int vector;
+ 
+ 	cpus_and(tmp, mask, cpu_online_map);
+ 	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	cpus_and(mask, tmp, CPU_MASK_ALL);
++		return;
+ 
+-	vector = assign_irq_vector(irq, mask, &tmp);
+-	if (vector < 0)
++	if (assign_irq_vector(irq, mask))
+ 		return;
+ 
++	cpus_and(tmp, cfg->domain, mask);
+ 	dest = cpu_mask_to_apicid(tmp);
+ 
+ 	/*
+@@ -285,8 +297,8 @@ static void set_ioapic_affinity_irq(unsi
+ 	dest = SET_APIC_LOGICAL_ID(dest);
+ 
+ 	spin_lock_irqsave(&ioapic_lock, flags);
+-	__target_IO_APIC_irq(irq, dest, vector);
+-	set_native_irq_info(irq, mask);
++	__target_IO_APIC_irq(irq, dest, cfg->vector);
++	irq_desc[irq].affinity = mask;
+ 	spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ #endif
+@@ -332,11 +344,11 @@ static void add_pin_to_irq(unsigned int 
+ 		reg = io_apic_read(entry->apic, 0x10 + R + pin*2);	\
+ 		reg ACTION;						\
+ 		io_apic_modify(entry->apic, reg);			\
++		FINAL;							\
+ 		if (!entry->next)					\
+ 			break;						\
+ 		entry = irq_2_pin + entry->next;			\
+ 	}								\
+-	FINAL;								\
+ }
+ 
+ #define DO_ACTION(name,R,ACTION, FINAL)					\
+@@ -669,77 +681,62 @@ static int pin_2_irq(int idx, int apic, 
+ 	return irq;
+ }
+ 
+-static inline int IO_APIC_irq_trigger(int irq)
+-{
+-	int apic, idx, pin;
+-
+-	for (apic = 0; apic < nr_ioapics; apic++) {
+-		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+-			idx = find_irq_entry(apic,pin,mp_INT);
+-			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))
+-				return irq_trigger(idx);
+-		}
+-	}
+-	/*
+-	 * nonexistent IRQs are edge default
+-	 */
+-	return 0;
+-}
+-
+-/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
+-
+-static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
++static int __assign_irq_vector(int irq, cpumask_t mask)
+ {
+-	int vector;
+ 	struct physdev_irq irq_op;
++	struct irq_cfg *cfg;
+   
+-	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
++	BUG_ON((unsigned)irq >= NR_IRQS);
+ 
+ 	if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS)
+ 		return -EINVAL;
+ 
+-	cpus_and(*result, mask, cpu_online_map);
++	cfg = &irq_cfg[irq];
++
++	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
++		return -EBUSY;
+ 
+-	if (irq_vector[irq] > 0)
+-		return irq_vector[irq];
++	if (cfg->vector)
++		return 0;
+ 
+ 	irq_op.irq = irq;
+ 	if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+ 		return -ENOSPC;
+ 
+-	vector = irq_op.vector;
+-	irq_vector[irq] = vector;
++	cfg->vector = irq_op.vector;
+ 
+-	return vector;
++	return 0;
+ }
+ 
+-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
++static int assign_irq_vector(int irq, cpumask_t mask)
+ {
+-	int vector;
++	int err;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	vector = __assign_irq_vector(irq, mask, result);
++	err = __assign_irq_vector(irq, mask);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+-	return vector;
++	return err;
+ }
+ 
+ #ifndef CONFIG_XEN
+ static void __clear_irq_vector(int irq)
+ {
++	struct irq_cfg *cfg;
+ 	cpumask_t mask;
+ 	int cpu, vector;
+ 
+-	BUG_ON(!irq_vector[irq]);
++	BUG_ON((unsigned)irq >= NR_IRQS);
++	cfg = &irq_cfg[irq];
++	BUG_ON(!cfg->vector);
+ 
+-	vector = irq_vector[irq];
+-	cpus_and(mask, irq_domain[irq], cpu_online_map);
++	vector = cfg->vector;
++	cpus_and(mask, cfg->domain, cpu_online_map);
+ 	for_each_cpu_mask(cpu, mask)
+ 		per_cpu(vector_irq, cpu)[vector] = -1;
+ 
+-	irq_vector[irq] = 0;
+-	irq_domain[irq] = CPU_MASK_NONE;
++	cfg->vector = 0;
++	cfg->domain = CPU_MASK_NONE;
+ }
+ 
+ void __setup_vector_irq(int cpu)
+@@ -749,10 +746,10 @@ void __setup_vector_irq(int cpu)
+ 	int irq, vector;
+ 
+ 	/* Mark the inuse vectors */
+-	for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
+-		if (!cpu_isset(cpu, irq_domain[irq]))
++	for (irq = 0; irq < NR_IRQS; ++irq) {
++		if (!cpu_isset(cpu, irq_cfg[irq].domain))
+ 			continue;
+-		vector = irq_vector[irq];
++		vector = irq_cfg[irq].vector;
+ 		per_cpu(vector_irq, cpu)[vector] = irq;
+ 	}
+ 	/* Mark the free vectors */
+@@ -760,41 +757,49 @@ void __setup_vector_irq(int cpu)
+ 		irq = per_cpu(vector_irq, cpu)[vector];
+ 		if (irq < 0)
+ 			continue;
+-		if (!cpu_isset(cpu, irq_domain[irq]))
++		if (!cpu_isset(cpu, irq_cfg[irq].domain))
+ 			per_cpu(vector_irq, cpu)[vector] = -1;
+ 	}
+ }
+ 
+-extern void (*interrupt[NR_IRQS])(void);
+-
+ static struct irq_chip ioapic_chip;
+ 
+-#define IOAPIC_AUTO	-1
+-#define IOAPIC_EDGE	0
+-#define IOAPIC_LEVEL	1
+-
+-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
++static void ioapic_register_intr(int irq, unsigned long trigger)
+ {
+-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+-			trigger == IOAPIC_LEVEL)
++	if (trigger)
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					      handle_fasteoi_irq, "fasteoi");
+-	else {
+-		irq_desc[irq].status |= IRQ_DELAYED_DISABLE;
++	else
+ 		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+ 					      handle_edge_irq, "edge");
+-	}
+ }
+ #else
+-#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq)
++#define ioapic_register_intr(irq, trigger) evtchn_register_pirq(irq)
+ #endif /* !CONFIG_XEN */
+ 
+-static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq)
++static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
++			      int trigger, int polarity)
+ {
++	struct irq_cfg *cfg = irq_cfg + irq;
+ 	struct IO_APIC_route_entry entry;
+-	int vector;
+-	unsigned long flags;
++	cpumask_t mask;
++
++	if (!IO_APIC_IRQ(irq))
++		return;
+ 
++	mask = TARGET_CPUS;
++	if (assign_irq_vector(irq, mask))
++		return;
++
++#ifndef CONFIG_XEN
++	cpus_and(mask, cfg->domain, mask);
++#endif
++
++	apic_printk(APIC_VERBOSE,KERN_DEBUG
++		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
++		    "IRQ %d Mode:%i Active:%i)\n",
++		    apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,
++		    irq, trigger, polarity);
+ 
+ 	/*
+ 	 * add it to the IO-APIC irq-routing table:
+@@ -803,41 +808,23 @@ static void __init setup_IO_APIC_irq(int
+ 
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.dest_mode = INT_DEST_MODE;
++	entry.dest = cpu_mask_to_apicid(mask);
+ 	entry.mask = 0;				/* enable IRQ */
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+-
+-	entry.trigger = irq_trigger(idx);
+-	entry.polarity = irq_polarity(idx);
++	entry.trigger = trigger;
++	entry.polarity = polarity;
++	entry.vector = cfg->vector;
+ 
+-	if (irq_trigger(idx)) {
+-		entry.trigger = 1;
++	/* Mask level triggered irqs.
++	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
++	 */
++	if (trigger)
+ 		entry.mask = 1;
+-		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+-	}
+-
+-	if (/* !apic && */ !IO_APIC_IRQ(irq))
+-		return;
+ 
+-	if (IO_APIC_IRQ(irq)) {
+-		cpumask_t mask;
+-		vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
+-		if (vector < 0)
+-			return;
+-
+-		entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+-		entry.vector = vector;
+-
+-		ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+-		if (!apic && (irq < 16))
+-			disable_8259A_irq(irq);
+-	}
++	ioapic_register_intr(irq, trigger);
++	if (irq < 16)
++		disable_8259A_irq(irq);
+ 
+ 	ioapic_write_entry(apic, pin, entry);
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	set_native_irq_info(irq, TARGET_CPUS);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
+-
+ }
+ 
+ static void __init setup_IO_APIC_irqs(void)
+@@ -862,8 +849,8 @@ static void __init setup_IO_APIC_irqs(vo
+ 		irq = pin_2_irq(idx, apic, pin);
+ 		add_pin_to_irq(irq, apic, pin);
+ 
+-		setup_IO_APIC_irq(apic, pin, idx, irq);
+-
++		setup_IO_APIC_irq(apic, pin, irq,
++				  irq_trigger(idx), irq_polarity(idx));
+ 	}
+ 	}
+ 
+@@ -894,7 +881,7 @@ static void __init setup_ExtINT_IRQ0_pin
+ 	 */
+ 	entry.dest_mode = INT_DEST_MODE;
+ 	entry.mask = 0;					/* unmask IRQ now */
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
++	entry.dest = cpu_mask_to_apicid(TARGET_CPUS);
+ 	entry.delivery_mode = INT_DELIVERY_MODE;
+ 	entry.polarity = 0;
+ 	entry.trigger = 0;
+@@ -994,18 +981,17 @@ void __apicdebuginit print_IO_APIC(void)
+ 
+ 	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+ 
+-	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
+-			  " Stat Dest Deli Vect:   \n");
++	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
++			  " Stat Dmod Deli Vect:   \n");
+ 
+ 	for (i = 0; i <= reg_01.bits.entries; i++) {
+ 		struct IO_APIC_route_entry entry;
+ 
+ 		entry = ioapic_read_entry(apic, i);
+ 
+-		printk(KERN_DEBUG " %02x %03X %02X  ",
++		printk(KERN_DEBUG " %02x %03X ",
+ 			i,
+-			entry.dest.logical.logical_dest,
+-			entry.dest.physical.physical_dest
++			entry.dest
+ 		);
+ 
+ 		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
+@@ -1269,8 +1255,7 @@ void disable_IO_APIC(void)
+ 		entry.dest_mode       = 0; /* Physical */
+ 		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+ 		entry.vector          = 0;
+-		entry.dest.physical.physical_dest =
+-					GET_APIC_ID(apic_read(APIC_ID));
++		entry.dest          = GET_APIC_ID(apic_read(APIC_ID));
+ 
+ 		/*
+ 		 * Add it to the IO-APIC irq-routing table:
+@@ -1355,16 +1340,15 @@ static unsigned int startup_ioapic_irq(u
+ 
+ static int ioapic_retrigger_irq(unsigned int irq)
+ {
++	struct irq_cfg *cfg = &irq_cfg[irq];
+ 	cpumask_t mask;
+-	unsigned vector;
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&vector_lock, flags);
+-	vector = irq_vector[irq];
+ 	cpus_clear(mask);
+-	cpu_set(first_cpu(irq_domain[irq]), mask);
++	cpu_set(first_cpu(cfg->domain), mask);
+ 
+-	send_IPI_mask(mask, vector);
++	send_IPI_mask(mask, cfg->vector);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+ 	return 1;
+@@ -1379,8 +1363,68 @@ static int ioapic_retrigger_irq(unsigned
+  * races.
+  */
+ 
++#ifdef CONFIG_SMP
++asmlinkage void smp_irq_move_cleanup_interrupt(void)
++{
++	unsigned vector, me;
++	ack_APIC_irq();
++	exit_idle();
++	irq_enter();
++
++	me = smp_processor_id();
++	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
++		unsigned int irq;
++		struct irq_desc *desc;
++		struct irq_cfg *cfg;
++		irq = __get_cpu_var(vector_irq)[vector];
++		if (irq >= NR_IRQS)
++			continue;
++
++		desc = irq_desc + irq;
++		cfg = irq_cfg + irq;
++		spin_lock(&desc->lock);
++		if (!cfg->move_cleanup_count)
++			goto unlock;
++
++		if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
++			goto unlock;
++
++		__get_cpu_var(vector_irq)[vector] = -1;
++		cfg->move_cleanup_count--;
++unlock:
++		spin_unlock(&desc->lock);
++	}
++
++	irq_exit();
++}
++
++static void irq_complete_move(unsigned int irq)
++{
++	struct irq_cfg *cfg = irq_cfg + irq;
++	unsigned vector, me;
++
++	if (likely(!cfg->move_in_progress))
++		return;
++
++	vector = ~get_irq_regs()->orig_rax;
++	me = smp_processor_id();
++	if ((vector == cfg->vector) &&
++	    cpu_isset(smp_processor_id(), cfg->domain)) {
++		cpumask_t cleanup_mask;
++
++		cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
++		cfg->move_cleanup_count = cpus_weight(cleanup_mask);
++		send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
++		cfg->move_in_progress = 0;
++	}
++}
++#else
++static inline void irq_complete_move(unsigned int irq) {}
++#endif
++
+ static void ack_apic_edge(unsigned int irq)
+ {
++	irq_complete_move(irq);
+ 	move_native_irq(irq);
+ 	ack_APIC_irq();
+ }
+@@ -1389,6 +1433,7 @@ static void ack_apic_level(unsigned int 
+ {
+ 	int do_unmask_irq = 0;
+ 
++	irq_complete_move(irq);
+ #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
+ 	/* If we are moving the irq we need to mask it */
+ 	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+@@ -1440,7 +1485,7 @@ static inline void init_IO_APIC_traps(vo
+ 	 */
+ 	for (irq = 0; irq < NR_IRQS ; irq++) {
+ 		int tmp = irq;
+-		if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
++		if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
+ 			/*
+ 			 * Hmm.. We don't have an entry for this,
+ 			 * so default to an old-fashioned 8259
+@@ -1538,7 +1583,7 @@ static inline void unlock_ExtINT_logic(v
+ 
+ 	entry1.dest_mode = 0;			/* physical delivery */
+ 	entry1.mask = 0;			/* unmask IRQ now */
+-	entry1.dest.physical.physical_dest = hard_smp_processor_id();
++	entry1.dest = hard_smp_processor_id();
+ 	entry1.delivery_mode = dest_ExtINT;
+ 	entry1.polarity = entry0.polarity;
+ 	entry1.trigger = 0;
+@@ -1582,15 +1627,14 @@ static inline void unlock_ExtINT_logic(v
+  */
+ static inline void check_timer(void)
+ {
++	struct irq_cfg *cfg = irq_cfg + 0;
+ 	int apic1, pin1, apic2, pin2;
+-	int vector;
+-	cpumask_t mask;
+ 
+ 	/*
+ 	 * get/set the timer IRQ vector:
+ 	 */
+ 	disable_8259A_irq(0);
+-	vector = assign_irq_vector(0, TARGET_CPUS, &mask);
++	assign_irq_vector(0, TARGET_CPUS);
+ 
+ 	/*
+ 	 * Subtle, code in do_timer_interrupt() expects an AEOI
+@@ -1610,7 +1654,7 @@ static inline void check_timer(void)
+ 	apic2 = ioapic_i8259.apic;
+ 
+ 	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+-		vector, apic1, pin1, apic2, pin2);
++		cfg->vector, apic1, pin1, apic2, pin2);
+ 
+ 	if (pin1 != -1) {
+ 		/*
+@@ -1641,7 +1685,7 @@ static inline void check_timer(void)
+ 		/*
+ 		 * legacy devices should be connected to IO APIC #0
+ 		 */
+-		setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
++		setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
+ 		if (timer_irq_works()) {
+ 			apic_printk(APIC_VERBOSE," works.\n");
+ 			nmi_watchdog_default();
+@@ -1666,14 +1710,14 @@ static inline void check_timer(void)
+ 
+ 	disable_8259A_irq(0);
+ 	irq_desc[0].chip = &lapic_irq_type;
+-	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
++	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+ 	enable_8259A_irq(0);
+ 
+ 	if (timer_irq_works()) {
+ 		apic_printk(APIC_VERBOSE," works.\n");
+ 		return;
+ 	}
+-	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
++	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+ 	apic_printk(APIC_VERBOSE," failed.\n");
+ 
+ 	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+@@ -1828,19 +1872,16 @@ int create_irq(void)
+ 	/* Allocate an unused irq */
+ 	int irq;
+ 	int new;
+-	int vector = 0;
+ 	unsigned long flags;
+-	cpumask_t mask;
+ 
+ 	irq = -ENOSPC;
+ 	spin_lock_irqsave(&vector_lock, flags);
+ 	for (new = (NR_IRQS - 1); new >= 0; new--) {
+ 		if (platform_legacy_irq(new))
+ 			continue;
+-		if (irq_vector[new] != 0)
++		if (irq_cfg[new].vector != 0)
+ 			continue;
+-		vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
+-		if (likely(vector > 0))
++		if (__assign_irq_vector(new, TARGET_CPUS) == 0)
+ 			irq = new;
+ 		break;
+ 	}
+@@ -1871,12 +1912,15 @@ void destroy_irq(unsigned int irq)
+ #if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+ {
+-	int vector;
++	struct irq_cfg *cfg = irq_cfg + irq;
++	int err;
+ 	unsigned dest;
+ 	cpumask_t tmp;
+ 
+-	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
+-	if (vector >= 0) {
++	tmp = TARGET_CPUS;
++	err = assign_irq_vector(irq, tmp);
++	if (!err) {
++		cpus_and(tmp, cfg->domain, tmp);
+ 		dest = cpu_mask_to_apicid(tmp);
+ 
+ 		msg->address_hi = MSI_ADDR_BASE_HI;
+@@ -1896,40 +1940,38 @@ static int msi_compose_msg(struct pci_de
+ 			((INT_DELIVERY_MODE != dest_LowestPrio) ?
+ 				MSI_DATA_DELIVERY_FIXED:
+ 				MSI_DATA_DELIVERY_LOWPRI) |
+-			MSI_DATA_VECTOR(vector);
++			MSI_DATA_VECTOR(cfg->vector);
+ 	}
+-	return vector;
++	return err;
+ }
+ 
+ #ifdef CONFIG_SMP
+ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+ {
++	struct irq_cfg *cfg = irq_cfg + irq;
+ 	struct msi_msg msg;
+ 	unsigned int dest;
+ 	cpumask_t tmp;
+-	int vector;
+ 
+ 	cpus_and(tmp, mask, cpu_online_map);
+ 	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	cpus_and(mask, tmp, CPU_MASK_ALL);
++		return;
+ 
+-	vector = assign_irq_vector(irq, mask, &tmp);
+-	if (vector < 0)
++	if (assign_irq_vector(irq, mask))
+ 		return;
+ 
++	cpus_and(tmp, cfg->domain, mask);
+ 	dest = cpu_mask_to_apicid(tmp);
+ 
+ 	read_msi_msg(irq, &msg);
+ 
+ 	msg.data &= ~MSI_DATA_VECTOR_MASK;
+-	msg.data |= MSI_DATA_VECTOR(vector);
++	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+ 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ 
+ 	write_msi_msg(irq, &msg);
+-	set_native_irq_info(irq, mask);
++	irq_desc[irq].affinity = mask;
+ }
+ #endif /* CONFIG_SMP */
+ 
+@@ -1948,24 +1990,31 @@ static struct irq_chip msi_chip = {
+ 	.retrigger	= ioapic_retrigger_irq,
+ };
+ 
+-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
++int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+ {
+ 	struct msi_msg msg;
+-	int ret;
++	int irq, ret;
++	irq = create_irq();
++	if (irq < 0)
++		return irq;
++
++	set_irq_msi(irq, desc);
+ 	ret = msi_compose_msg(dev, irq, &msg);
+-	if (ret < 0)
++	if (ret < 0) {
++		destroy_irq(irq);
+ 		return ret;
++	}
+ 
+ 	write_msi_msg(irq, &msg);
+ 
+ 	set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+ 
+-	return 0;
++	return irq;
+ }
+ 
+ void arch_teardown_msi_irq(unsigned int irq)
+ {
+-	return;
++	destroy_irq(irq);
+ }
+ 
+ #endif /* CONFIG_PCI_MSI */
+@@ -1993,24 +2042,22 @@ static void target_ht_irq(unsigned int i
+ 
+ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
+ {
++	struct irq_cfg *cfg = irq_cfg + irq;
+ 	unsigned int dest;
+ 	cpumask_t tmp;
+-	int vector;
+ 
+ 	cpus_and(tmp, mask, cpu_online_map);
+ 	if (cpus_empty(tmp))
+-		tmp = TARGET_CPUS;
+-
+-	cpus_and(mask, tmp, CPU_MASK_ALL);
++		return;
+ 
+-	vector = assign_irq_vector(irq, mask, &tmp);
+-	if (vector < 0)
++	if (assign_irq_vector(irq, mask))
+ 		return;
+ 
++	cpus_and(tmp, cfg->domain, mask);
+ 	dest = cpu_mask_to_apicid(tmp);
+ 
+-	target_ht_irq(irq, dest, vector);
+-	set_native_irq_info(irq, mask);
++	target_ht_irq(irq, dest, cfg->vector);
++	irq_desc[irq].affinity = mask;
+ }
+ #endif
+ 
+@@ -2027,14 +2074,17 @@ static struct irq_chip ht_irq_chip = {
+ 
+ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
+ {
+-	int vector;
++	struct irq_cfg *cfg = irq_cfg + irq;
++	int err;
+ 	cpumask_t tmp;
+ 
+-	vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
+-	if (vector >= 0) {
++	tmp = TARGET_CPUS;
++	err = assign_irq_vector(irq, tmp);
++	if (!err) {
+ 		struct ht_irq_msg msg;
+ 		unsigned dest;
+ 
++		cpus_and(tmp, cfg->domain, tmp);
+ 		dest = cpu_mask_to_apicid(tmp);
+ 
+ 		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+@@ -2042,7 +2092,7 @@ int arch_setup_ht_irq(unsigned int irq, 
+ 		msg.address_lo =
+ 			HT_IRQ_LOW_BASE |
+ 			HT_IRQ_LOW_DEST_ID(dest) |
+-			HT_IRQ_LOW_VECTOR(vector) |
++			HT_IRQ_LOW_VECTOR(cfg->vector) |
+ 			((INT_DEST_MODE == 0) ?
+ 				HT_IRQ_LOW_DM_PHYSICAL :
+ 				HT_IRQ_LOW_DM_LOGICAL) |
+@@ -2057,7 +2107,7 @@ int arch_setup_ht_irq(unsigned int irq, 
+ 		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+ 					      handle_edge_irq, "edge");
+ 	}
+-	return vector;
++	return err;
+ }
+ #endif /* CONFIG_HT_IRQ */
+ 
+@@ -2082,13 +2132,8 @@ int __init io_apic_get_redir_entries (in
+ }
+ 
+ 
+-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
++int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
+ {
+-	struct IO_APIC_route_entry entry;
+-	unsigned long flags;
+-	int vector;
+-	cpumask_t mask;
+-
+ 	if (!IO_APIC_IRQ(irq)) {
+ 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+ 			ioapic);
+@@ -2101,42 +2146,7 @@ int io_apic_set_pci_routing (int ioapic,
+ 	if (irq >= 16)
+ 		add_pin_to_irq(irq, ioapic, pin);
+ 
+-
+-	vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
+-	if (vector < 0)
+-		return vector;
+-
+-	/*
+-	 * Generate a PCI IRQ routing entry and program the IOAPIC accordingly.
+-	 * Note that we mask (disable) IRQs now -- these get enabled when the
+-	 * corresponding device driver registers for this IRQ.
+-	 */
+-
+-	memset(&entry,0,sizeof(entry));
+-
+-	entry.delivery_mode = INT_DELIVERY_MODE;
+-	entry.dest_mode = INT_DEST_MODE;
+-	entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask);
+-	entry.trigger = edge_level;
+-	entry.polarity = active_high_low;
+-	entry.mask = 1;					 /* Disabled (masked) */
+-	entry.vector = vector & 0xff;
+-
+-	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+-		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
+-	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
+-	       edge_level, active_high_low);
+-
+-	ioapic_register_intr(irq, entry.vector, edge_level);
+-
+-	if (!ioapic && (irq < 16))
+-		disable_8259A_irq(irq);
+-
+-	ioapic_write_entry(ioapic, pin, entry);
+-
+-	spin_lock_irqsave(&ioapic_lock, flags);
+-	set_native_irq_info(irq, TARGET_CPUS);
+-	spin_unlock_irqrestore(&ioapic_lock, flags);
++	setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
+ 
+ 	return 0;
+ }
+@@ -2169,8 +2179,10 @@ void __init setup_ioapic_dest(void)
+ 			 * when you have too many devices, because at that time only boot
+ 			 * cpu is online.
+ 			 */
+-			if(!irq_vector[irq])
+-				setup_IO_APIC_irq(ioapic, pin, irq_entry, irq);
++			if (!irq_cfg[irq].vector)
++				setup_IO_APIC_irq(ioapic, pin, irq,
++						  irq_trigger(irq_entry),
++						  irq_polarity(irq_entry));
+ 			else
+ 				set_ioapic_affinity_irq(irq, TARGET_CPUS);
+ 		}
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -18,6 +18,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/io_apic.h>
+ #include <asm/idle.h>
++#include <asm/smp.h>
+ 
+ atomic_t irq_err_count;
+ 
+@@ -120,9 +121,15 @@ asmlinkage unsigned int do_IRQ(struct pt
+ 
+ 	if (likely(irq < NR_IRQS))
+ 		generic_handle_irq(irq);
+-	else if (printk_ratelimit())
+-		printk(KERN_EMERG "%s: %d.%d No irq handler for irq\n",
+-			__func__, smp_processor_id(), irq);
++	else {
++#ifndef CONFIG_XEN
++		if (!disable_apic)
++			ack_APIC_irq();
++#endif
++		if (printk_ratelimit())
++			printk(KERN_EMERG "%s: %d.%d No irq handler for irq\n",
++				__func__, smp_processor_id(), irq);
++	}
+ 
+ 	/*irq_exit();*/
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -60,9 +60,9 @@ unsigned long mp_lapic_addr = 0;
+ /* Processor that is doing the boot up */
+ unsigned int boot_cpu_id = -1U;
+ /* Internal processor count */
+-unsigned int num_processors __initdata = 0;
++unsigned int num_processors __cpuinitdata = 0;
+ 
+-unsigned disabled_cpus __initdata;
++unsigned disabled_cpus __cpuinitdata;
+ 
+ /* Bitmask of physically existing CPUs */
+ physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
+@@ -808,7 +808,7 @@ int mp_register_gsi(u32 gsi, int trigger
+ 		return gsi;
+ 
+ 	/* Don't set up the ACPI SCI because it's already set up */
+-	if (acpi_fadt.sci_int == gsi)
++	if (acpi_gbl_FADT.sci_interrupt == gsi)
+ 		return gsi;
+ 
+ 	ioapic = mp_find_ioapic(gsi);
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -338,14 +338,17 @@ void load_gs_index(unsigned gs)
+ void flush_thread(void)
+ {
+ 	struct task_struct *tsk = current;
+-	struct thread_info *t = current_thread_info();
+ 
+-	if (t->flags & _TIF_ABI_PENDING) {
+-		t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
+-		if (t->flags & _TIF_IA32)
++	if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
++		clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
++		if (test_tsk_thread_flag(tsk, TIF_IA32)) {
++			clear_tsk_thread_flag(tsk, TIF_IA32);
++		} else {
++			set_tsk_thread_flag(tsk, TIF_IA32);
+ 			current_thread_info()->status |= TS_COMPAT;
++		}
+ 	}
+-	t->flags &= ~_TIF_DEBUG;
++	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+ 
+ 	tsk->thread.debugreg0 = 0;
+ 	tsk->thread.debugreg1 = 0;
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -141,7 +141,7 @@ EXPORT_SYMBOL_GPL(edid_info);
+ 
+ extern int root_mountflags;
+ 
+-char command_line[COMMAND_LINE_SIZE];
++char __initdata command_line[COMMAND_LINE_SIZE];
+ 
+ struct resource standard_io_resources[] = {
+ 	{ .name = "dma1", .start = 0x00, .end = 0x1f,
+@@ -179,134 +179,6 @@ struct resource code_resource = {
+ 	.flags = IORESOURCE_RAM,
+ };
+ 
+-#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM)
+-
+-static struct resource system_rom_resource = {
+-	.name = "System ROM",
+-	.start = 0xf0000,
+-	.end = 0xfffff,
+-	.flags = IORESOURCE_ROM,
+-};
+-
+-static struct resource extension_rom_resource = {
+-	.name = "Extension ROM",
+-	.start = 0xe0000,
+-	.end = 0xeffff,
+-	.flags = IORESOURCE_ROM,
+-};
+-
+-static struct resource adapter_rom_resources[] = {
+-	{ .name = "Adapter ROM", .start = 0xc8000, .end = 0,
+-		.flags = IORESOURCE_ROM },
+-	{ .name = "Adapter ROM", .start = 0, .end = 0,
+-		.flags = IORESOURCE_ROM },
+-	{ .name = "Adapter ROM", .start = 0, .end = 0,
+-		.flags = IORESOURCE_ROM },
+-	{ .name = "Adapter ROM", .start = 0, .end = 0,
+-		.flags = IORESOURCE_ROM },
+-	{ .name = "Adapter ROM", .start = 0, .end = 0,
+-		.flags = IORESOURCE_ROM },
+-	{ .name = "Adapter ROM", .start = 0, .end = 0,
+-		.flags = IORESOURCE_ROM }
+-};
+-
+-static struct resource video_rom_resource = {
+-	.name = "Video ROM",
+-	.start = 0xc0000,
+-	.end = 0xc7fff,
+-	.flags = IORESOURCE_ROM,
+-};
+-
+-static struct resource video_ram_resource = {
+-	.name = "Video RAM area",
+-	.start = 0xa0000,
+-	.end = 0xbffff,
+-	.flags = IORESOURCE_RAM,
+-};
+-
+-#define romsignature(x) (*(unsigned short *)(x) == 0xaa55)
+-
+-static int __init romchecksum(unsigned char *rom, unsigned long length)
+-{
+-	unsigned char *p, sum = 0;
+-
+-	for (p = rom; p < rom + length; p++)
+-		sum += *p;
+-	return sum == 0;
+-}
+-
+-static void __init probe_roms(void)
+-{
+-	unsigned long start, length, upper;
+-	unsigned char *rom;
+-	int	      i;
+-
+-#ifdef CONFIG_XEN
+-	/* Nothing to do if not running in dom0. */
+-	if (!is_initial_xendomain())
+-		return;
+-#endif
+-
+-	/* video rom */
+-	upper = adapter_rom_resources[0].start;
+-	for (start = video_rom_resource.start; start < upper; start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		video_rom_resource.start = start;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
+-
+-		/* if checksum okay, trust length byte */
+-		if (length && romchecksum(rom, length))
+-			video_rom_resource.end = start + length - 1;
+-
+-		request_resource(&iomem_resource, &video_rom_resource);
+-		break;
+-			}
+-
+-	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
+-	if (start < upper)
+-		start = upper;
+-
+-	/* system rom */
+-	request_resource(&iomem_resource, &system_rom_resource);
+-	upper = system_rom_resource.start;
+-
+-	/* check for extension rom (ignore length byte!) */
+-	rom = isa_bus_to_virt(extension_rom_resource.start);
+-	if (romsignature(rom)) {
+-		length = extension_rom_resource.end - extension_rom_resource.start + 1;
+-		if (romchecksum(rom, length)) {
+-			request_resource(&iomem_resource, &extension_rom_resource);
+-			upper = extension_rom_resource.start;
+-		}
+-	}
+-
+-	/* check for adapter roms on 2k boundaries */
+-	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper;
+-	     start += 2048) {
+-		rom = isa_bus_to_virt(start);
+-		if (!romsignature(rom))
+-			continue;
+-
+-		/* 0 < length <= 0x7f * 512, historically */
+-		length = rom[2] * 512;
+-
+-		/* but accept any length that fits if checksum okay */
+-		if (!length || start + length > upper || !romchecksum(rom, length))
+-			continue;
+-
+-		adapter_rom_resources[i].start = start;
+-		adapter_rom_resources[i].end = start + length - 1;
+-		request_resource(&iomem_resource, &adapter_rom_resources[i]);
+-
+-		start = adapter_rom_resources[i++].end & ~2047UL;
+-	}
+-}
+-
+ #ifdef CONFIG_PROC_VMCORE
+ /* elfcorehdr= specifies the location of elf core header
+  * stored by the crashed kernel. This option will be passed
+@@ -404,7 +276,7 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_XEN
+ 	extern struct e820map machine_e820;
+ 
+-	printk(KERN_INFO "Command line: %s\n", saved_command_line);
++	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ 
+ 	/* Register a call for panic conditions. */
+ 	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+@@ -431,7 +303,7 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	ARCH_SETUP
+ #else
+-	printk(KERN_INFO "Command line: %s\n", saved_command_line);
++	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ 
+  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+  	screen_info = SCREEN_INFO;
+@@ -462,7 +334,7 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	early_identify_cpu(&boot_cpu_data);
+ 
+-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
++	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+ 
+ 	parse_early_param();
+@@ -532,6 +404,11 @@ void __init setup_arch(char **cmdline_p)
+ 	/* reserve ebda region */
+ 	if (ebda_addr)
+ 		reserve_bootmem_generic(ebda_addr, ebda_size);
++#ifdef CONFIG_NUMA
++	/* reserve nodemap region */
++	if (nodemap_addr)
++		reserve_bootmem_generic(nodemap_addr, nodemap_size);
++#endif
+ 
+ #ifdef CONFIG_SMP
+ 	/*
+@@ -732,10 +609,8 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+ 
+ 	/*
+-	 * Request address space for all standard RAM and ROM resources
+-	 * and also for regions reported as reserved by the e820.
++	 * We trust e820 completely. No explicit ROM probing in memory.
+ 	 */
+-	probe_roms();
+ #ifdef CONFIG_XEN
+ 	if (is_initial_xendomain())
+ 		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
+@@ -744,8 +619,6 @@ void __init setup_arch(char **cmdline_p)
+ 	e820_mark_nosave_regions();
+ #endif
+ 
+-	request_resource(&iomem_resource, &video_ram_resource);
+-
+ 	{
+ 	unsigned i;
+ 	/* request I/O space for devices used on all i[345]86 PCs */
+@@ -1324,7 +1197,8 @@ static int show_cpuinfo(struct seq_file 
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
+-		NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
++		NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
++		"3dnowext", "3dnow",
+ 
+ 		/* Transmeta-defined */
+ 		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
+@@ -1342,7 +1216,7 @@ static int show_cpuinfo(struct seq_file 
+ 		/* Intel-defined (#2) */
+ 		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+ 		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
++		NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* VIA/Cyrix/Centaur-defined */
+@@ -1352,8 +1226,10 @@ static int show_cpuinfo(struct seq_file 
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* AMD-defined (#2) */
+-		"lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
++		"altmovcr8", "abm", "sse4a",
++		"misalignsse", "3dnowprefetch",
++		"osvw", "ibs", NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 	};
+@@ -1364,6 +1240,9 @@ static int show_cpuinfo(struct seq_file 
+ 		"ttp",  /* thermal trip */
+ 		"tm",
+ 		"stc",
++		"100mhzsteps",
++		"hwpstate",
++		NULL,	/* tsc invariant mapped to constant_tsc */
+ 		NULL,
+ 		/* nothing */	/* constant_tsc - moved to flags */
+ 	};
+@@ -1480,26 +1359,3 @@ struct seq_operations cpuinfo_op = {
+ 	.stop =	c_stop,
+ 	.show =	show_cpuinfo,
+ };
+-
+-#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
+-#include <linux/platform_device.h>
+-static __init int add_pcspkr(void)
+-{
+-	struct platform_device *pd;
+-	int ret;
+-
+-	if (!is_initial_xendomain())
+-		return 0;
+-
+-	pd = platform_device_alloc("pcspkr", -1);
+-	if (!pd)
+-		return -ENOMEM;
+-
+-	ret = platform_device_add(pd);
+-	if (ret)
+-		platform_device_put(pd);
+-
+-	return ret;
+-}
+-device_initcall(add_pcspkr);
+-#endif
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -26,6 +26,7 @@
+ #include <linux/seqlock.h>
+ #include <linux/jiffies.h>
+ #include <linux/sysctl.h>
++#include <linux/clocksource.h>
+ #include <linux/getcpu.h>
+ #include <linux/cpu.h>
+ #include <linux/smp.h>
+@@ -34,6 +35,7 @@
+ #include <asm/vsyscall.h>
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
++#include <asm/unistd.h>
+ #include <asm/fixmap.h>
+ #include <asm/errno.h>
+ #include <asm/io.h>
+@@ -44,56 +46,41 @@
+ #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
+ #define __syscall_clobber "r11","rcx","memory"
+ 
+-int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
+-seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
++struct vsyscall_gtod_data_t {
++	seqlock_t lock;
++	int sysctl_enabled;
++	struct timeval wall_time_tv;
++	struct timezone sys_tz;
++	cycle_t offset_base;
++	struct clocksource clock;
++};
+ int __vgetcpu_mode __section_vgetcpu_mode;
+ 
+-#include <asm/unistd.h>
+-
+-static __always_inline void timeval_normalize(struct timeval * tv)
++struct vsyscall_gtod_data_t __vsyscall_gtod_data __section_vsyscall_gtod_data =
+ {
+-	time_t __sec;
+-
+-	__sec = tv->tv_usec / 1000000;
+-	if (__sec) {
+-		tv->tv_usec %= 1000000;
+-		tv->tv_sec += __sec;
+-	}
+-}
++	.lock = SEQLOCK_UNLOCKED,
++	.sysctl_enabled = 1,
++};
+ 
+-static __always_inline void do_vgettimeofday(struct timeval * tv)
++void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+ {
+-	long sequence, t;
+-	unsigned long sec, usec;
++	unsigned long flags;
+ 
+-	do {
+-		sequence = read_seqbegin(&__xtime_lock);
+-		
+-		sec = __xtime.tv_sec;
+-		usec = __xtime.tv_nsec / 1000;
+-
+-		if (__vxtime.mode != VXTIME_HPET) {
+-			t = get_cycles_sync();
+-			if (t < __vxtime.last_tsc)
+-				t = __vxtime.last_tsc;
+-			usec += ((t - __vxtime.last_tsc) *
+-				 __vxtime.tsc_quot) >> 32;
+-			/* See comment in x86_64 do_gettimeofday. */
+-		} else {
+-			usec += ((readl((void __iomem *)
+-				   fix_to_virt(VSYSCALL_HPET) + 0xf0) -
+-				  __vxtime.last) * __vxtime.quot) >> 32;
+-		}
+-	} while (read_seqretry(&__xtime_lock, sequence));
+-
+-	tv->tv_sec = sec + usec / 1000000;
+-	tv->tv_usec = usec % 1000000;
++	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
++	/* copy vsyscall data */
++	vsyscall_gtod_data.clock = *clock;
++	vsyscall_gtod_data.wall_time_tv.tv_sec = wall_time->tv_sec;
++	vsyscall_gtod_data.wall_time_tv.tv_usec = wall_time->tv_nsec/1000;
++	vsyscall_gtod_data.sys_tz = sys_tz;
++	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+ 
+-/* RED-PEN may want to readd seq locking, but then the variable should be write-once. */
++/* RED-PEN may want to readd seq locking, but then the variable should be
++ * write-once.
++ */
+ static __always_inline void do_get_tz(struct timezone * tz)
+ {
+-	*tz = __sys_tz;
++	*tz = __vsyscall_gtod_data.sys_tz;
+ }
+ 
+ static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
+@@ -101,7 +88,8 @@ static __always_inline int gettimeofday(
+ 	int ret;
+ 	asm volatile("vsysc2: syscall"
+ 		: "=a" (ret)
+-		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber );
++		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
++		: __syscall_clobber );
+ 	return ret;
+ }
+ 
+@@ -114,10 +102,44 @@ static __always_inline long time_syscall
+ 	return secs;
+ }
+ 
++static __always_inline void do_vgettimeofday(struct timeval * tv)
++{
++	cycle_t now, base, mask, cycle_delta;
++	unsigned long seq, mult, shift, nsec_delta;
++	cycle_t (*vread)(void);
++	do {
++		seq = read_seqbegin(&__vsyscall_gtod_data.lock);
++
++		vread = __vsyscall_gtod_data.clock.vread;
++		if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) {
++			gettimeofday(tv,NULL);
++			return;
++		}
++		now = vread();
++		base = __vsyscall_gtod_data.clock.cycle_last;
++		mask = __vsyscall_gtod_data.clock.mask;
++		mult = __vsyscall_gtod_data.clock.mult;
++		shift = __vsyscall_gtod_data.clock.shift;
++
++		*tv = __vsyscall_gtod_data.wall_time_tv;
++
++	} while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
++
++	/* calculate interval: */
++	cycle_delta = (now - base) & mask;
++	/* convert to nsecs: */
++	nsec_delta = (cycle_delta * mult) >> shift;
++
++	/* convert to usecs and add to timespec: */
++	tv->tv_usec += nsec_delta / NSEC_PER_USEC;
++	while (tv->tv_usec > USEC_PER_SEC) {
++		tv->tv_sec += 1;
++		tv->tv_usec -= USEC_PER_SEC;
++	}
++}
++
+ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+ {
+-	if (!__sysctl_vsyscall)
+-		return gettimeofday(tv,tz);
+ 	if (tv)
+ 		do_vgettimeofday(tv);
+ 	if (tz)
+@@ -129,11 +151,11 @@ int __vsyscall(0) vgettimeofday(struct t
+  * unlikely */
+ time_t __vsyscall(1) vtime(time_t *t)
+ {
+-	if (!__sysctl_vsyscall)
++	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
+ 		return time_syscall(t);
+ 	else if (t)
+-		*t = __xtime.tv_sec;		
+-	return __xtime.tv_sec;
++		*t = __vsyscall_gtod_data.wall_time_tv.tv_sec;
++	return __vsyscall_gtod_data.wall_time_tv.tv_sec;
+ }
+ 
+ /* Fast way to get current CPU and node.
+@@ -210,7 +232,7 @@ static int vsyscall_sysctl_change(ctl_ta
+ 		ret = -ENOMEM;
+ 		goto out;
+ 	}
+-	if (!sysctl_vsyscall) {
++	if (!vsyscall_gtod_data.sysctl_enabled) {
+ 		writew(SYSCALL, map1);
+ 		writew(SYSCALL, map2);
+ 	} else {
+@@ -232,16 +254,17 @@ static int vsyscall_sysctl_nostrat(ctl_t
+ 
+ static ctl_table kernel_table2[] = {
+ 	{ .ctl_name = 99, .procname = "vsyscall64",
+-	  .data = &sysctl_vsyscall, .maxlen = sizeof(int), .mode = 0644,
++	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
++	  .mode = 0644,
+ 	  .strategy = vsyscall_sysctl_nostrat,
+ 	  .proc_handler = vsyscall_sysctl_change },
+-	{ 0, }
++	{}
+ };
+ 
+ static ctl_table kernel_root_table2[] = {
+ 	{ .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
+ 	  .child = kernel_table2 },
+-	{ 0 },
++	{}
+ };
+ 
+ #endif
+@@ -304,14 +327,14 @@ static int __init vsyscall_init(void)
+ 	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
+ 	map_vsyscall();
+ #ifdef CONFIG_XEN
+-	sysctl_vsyscall = 0; /* disable vgettimeofay() */
++	vsyscall_gtod_data.sysctl_enabled = 0; /* disable vgettimeofay() */
+  	if (boot_cpu_has(X86_FEATURE_RDTSCP))
+ 		vgetcpu_mode = VGETCPU_RDTSCP;
+ 	else
+ 		vgetcpu_mode = VGETCPU_LSL;
+ #endif
+ #ifdef CONFIG_SYSCTL
+-	register_sysctl_table(kernel_root_table2, 0);
++	register_sysctl_table(kernel_root_table2);
+ #endif
+ 	on_each_cpu(cpu_vsyscall_init, NULL, 0, 1);
+ 	hotcpu_notifier(cpu_vsyscall_notifier, 0);
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -56,38 +56,17 @@ int unregister_page_fault_notifier(struc
+ }
+ EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
+ 
+-static inline int notify_page_fault(enum die_val val, const char *str,
+-			struct pt_regs *regs, long err, int trap, int sig)
++static inline int notify_page_fault(struct pt_regs *regs, long err)
+ {
+ 	struct die_args args = {
+ 		.regs = regs,
+-		.str = str,
++		.str = "page fault",
+ 		.err = err,
+-		.trapnr = trap,
+-		.signr = sig
++		.trapnr = 14,
++		.signr = SIGSEGV
+ 	};
+-	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+-}
+-
+-void bust_spinlocks(int yes)
+-{
+-	int loglevel_save = console_loglevel;
+-	if (yes) {
+-		oops_in_progress = 1;
+-	} else {
+-#ifdef CONFIG_VT
+-		unblank_screen();
+-#endif
+-		oops_in_progress = 0;
+-		/*
+-		 * OK, the message is on the console.  Now we call printk()
+-		 * without oops_in_progress set so that printk will give klogd
+-		 * a poke.  Hold onto your hats...
+-		 */
+-		console_loglevel = 15;		/* NMI oopser may have shut the console up */
+-		printk(" ");
+-		console_loglevel = loglevel_save;
+-	}
++	return atomic_notifier_call_chain(&notify_page_fault_chain,
++	                                  DIE_PAGE_FAULT, &args);
+ }
+ 
+ /* Sometimes the CPU reports invalid exceptions on prefetch.
+@@ -437,8 +416,7 @@ asmlinkage void __kprobes do_page_fault(
+ 		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+ 		if (spurious_fault(regs, address, error_code))
+ 			return;
+-		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+-						SIGSEGV) == NOTIFY_STOP)
++		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ 			return;
+ 		/*
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+@@ -447,8 +425,7 @@ asmlinkage void __kprobes do_page_fault(
+ 		goto bad_area_nosemaphore;
+ 	}
+ 
+-	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+-					SIGSEGV) == NOTIFY_STOP)
++	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
+ 		return;
+ 
+ 	if (likely(regs->eflags & X86_EFLAGS_IF))
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -1132,20 +1132,30 @@ int kern_addr_valid(unsigned long addr) 
+ extern int exception_trace, page_fault_trace;
+ 
+ static ctl_table debug_table2[] = {
+-	{ 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,
+-	  proc_dointvec },
+-	{ 0, }
++	{
++		.ctl_name	= 99,
++		.procname	= "exception-trace",
++		.data		= &exception_trace,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= proc_dointvec
++	},
++	{}
+ }; 
+ 
+ static ctl_table debug_root_table2[] = { 
+-	{ .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, 
+-	   .child = debug_table2 }, 
+-	{ 0 }, 
++	{
++		.ctl_name = CTL_DEBUG,
++		.procname = "debug",
++		.mode = 0555,
++		.child = debug_table2
++	},
++	{}
+ }; 
+ 
+ static __init int x8664_sysctl_init(void)
+ { 
+-	register_sysctl_table(debug_root_table2, 1);
++	register_sysctl_table(debug_root_table2);
+ 	return 0;
+ }
+ __initcall(x8664_sysctl_init);
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -350,8 +350,8 @@ static void flush_kernel_map(void *arg)
+ 		void *adr = page_address(pg);
+ 		if (cpu_has_clflush)
+ 			cache_flush_page(adr);
+-		__flush_tlb_one(adr);
+ 	}
++	__flush_tlb_all();
+ }
+ 
+ static inline void flush_map(struct list_head *l)
+@@ -376,6 +376,7 @@ static void revert_page(unsigned long ad
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t large_pte;
++	unsigned long pfn;
+ 
+ 	pgd = pgd_offset_k(address);
+ 	BUG_ON(pgd_none(*pgd));
+@@ -383,7 +384,8 @@ static void revert_page(unsigned long ad
+ 	BUG_ON(pud_none(*pud));
+ 	pmd = pmd_offset(pud, address);
+ 	BUG_ON(__pmd_val(*pmd) & _PAGE_PSE);
+-	large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
++	pfn = (__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT;
++	large_pte = pfn_pte(pfn, ref_prot);
+ 	large_pte = pte_mkhuge(large_pte);
+ 	set_pte((pte_t *)pmd, large_pte);
+ }      
+--- head-2010-01-18.orig/drivers/acpi/processor_extcntl.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_extcntl.c	2009-11-06 10:46:41.000000000 +0100
+@@ -32,9 +32,8 @@
+ 
+ #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")
++ACPI_MODULE_NAME("processor_extcntl")
+ 
+ static int processor_extcntl_parse_csd(struct acpi_processor *pr);
+ static int processor_extcntl_get_performance(struct acpi_processor *pr);
+@@ -56,24 +55,17 @@ static int processor_notify_smm(void)
+ 		return 0;
+ 
+ 	/* Can't write pstate_cnt to smi_cmd if either value is zero */
+-	if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) {
++	if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control) {
+ 		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));
++		acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+ 
+-	/* 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);
++	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
++				    acpi_gbl_FADT.pstate_control, 8);
+ 	if (ACPI_FAILURE(status))
+ 		return status;
+ 
+--- head-2010-01-18.orig/drivers/char/tpm/tpm_xen.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/char/tpm/tpm_xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -481,7 +481,6 @@ static struct xenbus_device_id tpmfront_
+ 
+ static struct xenbus_driver tpmfront = {
+ 	.name = "vtpm",
+-	.owner = THIS_MODULE,
+ 	.ids = tpmfront_ids,
+ 	.probe = tpmfront_probe,
+ 	.remove =  tpmfront_remove,
+@@ -491,9 +490,9 @@ static struct xenbus_driver tpmfront = {
+ 	.suspend_cancel = tpmfront_suspend_cancel,
+ };
+ 
+-static void __init init_tpm_xenbus(void)
++static int __init init_tpm_xenbus(void)
+ {
+-	xenbus_register_frontend(&tpmfront);
++	return xenbus_register_frontend(&tpmfront);
+ }
+ 
+ static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 10:54:10.000000000 +0100
+@@ -36,8 +36,6 @@ struct msi_dev_list {
+ 	struct list_head list;
+ 	spinlock_t pirq_list_lock;
+ 	struct list_head pirq_list_head;
+-	/* Used for saving/restoring MSI-X tables */
+-	void __iomem *mask_base;
+ 	/* Store default pre-assigned irq */
+ 	unsigned int default_irq;
+ };
+@@ -46,14 +44,38 @@ struct msi_pirq_entry {
+ 	struct list_head list;
+ 	int pirq;
+ 	int entry_nr;
+-#ifdef CONFIG_PM
+-	/* PM save area for MSIX address/data */
+-	u32	address_hi_save;
+-	u32	address_lo_save;
+-	u32	data_save;
+-#endif
+ };
+ 
++static void msi_set_enable(struct pci_dev *dev, int enable)
++{
++	int pos;
++	u16 control;
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++	if (pos) {
++		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
++		control &= ~PCI_MSI_FLAGS_ENABLE;
++		if (enable)
++			control |= PCI_MSI_FLAGS_ENABLE;
++		pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
++	}
++}
++
++static void msix_set_enable(struct pci_dev *dev, int enable)
++{
++	int pos;
++	u16 control;
++
++	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++	if (pos) {
++		pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
++		control &= ~PCI_MSIX_FLAGS_ENABLE;
++		if (enable)
++			control |= PCI_MSIX_FLAGS_ENABLE;
++		pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
++	}
++}
++
+ static struct msi_dev_list *get_msi_dev_pirq_list(struct pci_dev *dev)
+ {
+ 	struct msi_dev_list *msi_dev_list, *ret = NULL;
+@@ -163,8 +185,8 @@ static int msi_unmap_pirq(struct pci_dev
+ 	int rc;
+ 
+ 	unmap.domid = msi_get_dev_owner(dev);
+-	/* See comments in msi_map_pirq_to_vector, input parameter pirq
+-	 * mean irq number only if the device belongs to dom0 itself.
++	/* See comments in msi_map_vector, input parameter pirq means
++	 * irq number only if the device belongs to dom0 itself.
+ 	 */
+ 	unmap.pirq = (unmap.domid != DOMID_SELF)
+ 		? pirq : evtchn_get_xen_pirq(pirq);
+@@ -200,8 +222,7 @@ static u64 find_table_base(struct pci_de
+ /*
+  * Protected by msi_lock
+  */
+-static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
+-				  int entry_nr, u64 table_base)
++static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
+ {
+ 	struct physdev_map_pirq map_irq;
+ 	int rc;
+@@ -212,7 +233,7 @@ static int msi_map_pirq_to_vector(struct
+ 	map_irq.domid = domid;
+ 	map_irq.type = MAP_PIRQ_TYPE_MSI;
+ 	map_irq.index = -1;
+-	map_irq.pirq = pirq < 0 ? -1 : evtchn_get_xen_pirq(pirq);
++	map_irq.pirq = -1;
+ 	map_irq.bus = dev->bus->number;
+ 	map_irq.devfn = dev->devfn;
+ 	map_irq.entry_nr = entry_nr;
+@@ -223,7 +244,7 @@ static int msi_map_pirq_to_vector(struct
+ 
+ 	if (rc < 0)
+ 		return rc;
+-	/* This happens when MSI support is not enabled in Xen. */
++	/* This happens when MSI support is not enabled in older Xen. */
+ 	if (rc == 0 && map_irq.pirq < 0)
+ 		return -ENOSYS;
+ 
+@@ -235,236 +256,35 @@ static int msi_map_pirq_to_vector(struct
+ 	 * to another domain, and will be 'Linux irq' if it belongs to dom0.
+ 	 */
+ 	return ((domid != DOMID_SELF) ?
+-		map_irq.pirq : evtchn_map_pirq(pirq, 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);
++		map_irq.pirq : evtchn_map_pirq(-1, map_irq.pirq));
+ }
+ 
+ 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;
+-	}
+-
+-	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;
+-	}
+-
+-	pci_intx(dev, 0);  /* disable intx */
+-}
+-
+-#ifdef CONFIG_PM
+-int pci_save_msi_state(struct pci_dev *dev)
+-{
+-	int pos, i = 0;
+-	u16 control;
+-	struct pci_cap_saved_state *save_state;
+-	u32 *cap;
+-
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+-	if (pos <= 0 || dev->no_msi)
+-		return 0;
+-
+-	pci_read_config_word(dev, msi_control_reg(pos), &control);
+-	if (!(control & PCI_MSI_FLAGS_ENABLE))
+-		return 0;
+-
+-	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
+-		GFP_KERNEL);
+-	if (!save_state) {
+-		printk(KERN_ERR "Out of memory in pci_save_msi_state\n");
+-		return -ENOMEM;
+-	}
+-	cap = &save_state->data[0];
+-
+-	pci_read_config_dword(dev, pos, &cap[i++]);
+-	control = cap[0] >> 16;
+-	pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]);
+-	if (control & PCI_MSI_FLAGS_64BIT) {
+-		pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]);
+-		pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]);
+-	} else
+-		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
+-	if (control & PCI_MSI_FLAGS_MASKBIT)
+-		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
+-	save_state->cap_nr = PCI_CAP_ID_MSI;
+-	pci_add_saved_cap(dev, save_state);
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM
+ void pci_restore_msi_state(struct pci_dev *dev)
+ {
+-	int i = 0, pos;
+-	u16 control;
+-	struct pci_cap_saved_state *save_state;
+-	u32 *cap;
+-
+-	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+-	if (!save_state || pos <= 0)
+-		return;
+-	cap = &save_state->data[0];
+-
+-	control = cap[i++] >> 16;
+-	pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
+-	if (control & PCI_MSI_FLAGS_64BIT) {
+-		pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
+-		pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]);
+-	} else
+-		pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]);
+-	if (control & PCI_MSI_FLAGS_MASKBIT)
+-		pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
+-	pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+-	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+-	pci_remove_saved_cap(save_state);
+-	kfree(save_state);
+-}
+-
+-int pci_save_msix_state(struct pci_dev *dev)
+-{
+-	int pos;
+-	u16 control;
+-	struct pci_cap_saved_state *save_state;
+-	unsigned long flags;
+-	struct msi_dev_list *msi_dev_entry;
+-	struct msi_pirq_entry *pirq_entry;
+-	void __iomem *base;
+-
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+-	if (pos <= 0 || dev->no_msi)
+-		return 0;
+-
+-	/* save the capability */
+-	pci_read_config_word(dev, msi_control_reg(pos), &control);
+-	if (!(control & PCI_MSIX_FLAGS_ENABLE))
+-		return 0;
+-
+-	msi_dev_entry = get_msi_dev_pirq_list(dev);
+-	/* If we failed to map the MSI-X table at pci_enable_msix,
+-	 * We could not support saving them here.
+-	 */
+-	if (!(base = msi_dev_entry->mask_base))
+-		return -ENOMEM;
+-
+-	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
+-		GFP_KERNEL);
+-	if (!save_state) {
+-		printk(KERN_ERR "Out of memory in pci_save_msix_state\n");
+-		return -ENOMEM;
+-	}
+-	*((u16 *)&save_state->data[0]) = control;
+-
+-	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
+-	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
+-		int j;
+-
+-		/* save the table */
+-		j = pirq_entry->entry_nr;
+-		pirq_entry->address_lo_save =
+-			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+-			      PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+-		pirq_entry->address_hi_save =
+-			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+-			      PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+-		pirq_entry->data_save =
+-			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+-			      PCI_MSIX_ENTRY_DATA_OFFSET);
+-	}
+-	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
+-
+-	save_state->cap_nr = PCI_CAP_ID_MSIX;
+-	pci_add_saved_cap(dev, save_state);
+-	return 0;
+-}
+-
+-void pci_restore_msix_state(struct pci_dev *dev)
+-{
+-	u16 save;
+-	int pos, j;
+-	void __iomem *base;
+-	struct pci_cap_saved_state *save_state;
+-	unsigned long flags;
+-	struct msi_dev_list *msi_dev_entry;
+-	struct msi_pirq_entry *pirq_entry;
+-
+-	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
+-	if (!save_state)
+-		return;
+-
+-	save = *((u16 *)&save_state->data[0]);
+-	pci_remove_saved_cap(save_state);
+-	kfree(save_state);
++	int rc;
++	struct physdev_restore_msi restore;
+ 
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+-	if (pos <= 0)
++	if (!dev->msi_enabled && !dev->msix_enabled)
+ 		return;
+ 
+-	msi_dev_entry = get_msi_dev_pirq_list(dev);
+-	base = msi_dev_entry->mask_base;
+-
+-	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
+-	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
+-		/* route the table */
+-		j = pirq_entry->entry_nr;
+-		writel(pirq_entry->address_lo_save,
+-			base + j * PCI_MSIX_ENTRY_SIZE +
+-			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+-		writel(pirq_entry->address_hi_save,
+-			base + j * PCI_MSIX_ENTRY_SIZE +
+-			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+-		writel(pirq_entry->data_save,
+-			base + j * PCI_MSIX_ENTRY_SIZE +
+-			PCI_MSIX_ENTRY_DATA_OFFSET);
+-	}
+-	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
++	pci_intx(dev, 0);		/* disable intx */
++	if (dev->msi_enabled)
++		msi_set_enable(dev, 0);
++	if (dev->msix_enabled)
++		msix_set_enable(dev, 0);
+ 
+-	pci_write_config_word(dev, msi_control_reg(pos), save);
+-	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++	restore.bus = dev->bus->number;
++	restore.devfn = dev->devfn;
++	rc = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore);
++	WARN(rc && rc != -ENOSYS, "restore_msi -> %d\n", rc);
+ }
+-#endif
++#endif	/* CONFIG_PM */
+ 
+ /**
+  * msi_capability_init - configure device's MSI capability structure
+@@ -480,6 +300,8 @@ static int msi_capability_init(struct pc
+ 	int pos, pirq;
+ 	u16 control;
+ 
++	msi_set_enable(dev, 0);	/* Ensure msi is disabled as I set it up */
++
+ 	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ 	pci_read_config_word(dev, msi_control_reg(pos), &control);
+ 
+@@ -488,7 +310,8 @@ static int msi_capability_init(struct pc
+ 		return -EBUSY;
+ 
+ 	/* Set MSI enabled bits	 */
+-	enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++	pci_intx(dev, 0);		/* disable intx */
++	msi_set_enable(dev, 1);
+ 	dev->msi_enabled = 1;
+ 
+ 	dev->irq = pirq;
+@@ -509,25 +332,20 @@ static int msix_capability_init(struct p
+ 				struct msix_entry *entries, int nvec)
+ {
+ 	u64 table_base;
+-	u16 control;
+-	int pirq, i, j, mapped, pos, nr_entries;
++	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;
+ 
++	msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
++
+ 	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ 	table_base = find_table_base(dev, pos);
+ 	if (!table_base)
+ 		return -ENODEV;
+ 
+-	pci_read_config_word(dev, msi_control_reg(pos), &control);
+-	nr_entries = multi_msix_capable(control);
+-	if (!msi_dev_entry->mask_base)
+-		msi_dev_entry->mask_base = 
+-			ioremap_nocache(table_base, nr_entries * PCI_MSIX_ENTRY_SIZE);
+-
+ 	/* MSI-X Table Initialization */
+ 	for (i = 0; i < nvec; i++) {
+ 		mapped = 0;
+@@ -566,7 +384,8 @@ static int msix_capability_init(struct p
+ 		return avail;
+ 	}
+ 
+-	enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++	pci_intx(dev, 0);		/* disable intx */
++	msix_set_enable(dev, 1);
+ 	dev->msix_enabled = 1;
+ 
+ 	return 0;
+@@ -651,17 +470,14 @@ int pci_enable_msi(struct pci_dev* dev)
+ 	/* Check whether driver already requested for MSI-X irqs */
+ 	if (dev->msix_enabled) {
+ 		printk(KERN_INFO "PCI: %s: Can't enable MSI.  "
+-		       "Device already has MSI-X irq assigned\n",
+-			   pci_name(dev));
+-		dev->irq = temp;
++		       "Device already has MSI-X enabled\n",
++		       pci_name(dev));
+ 		return -EINVAL;
+ 	}
+ 
+ 	status = msi_capability_init(dev);
+ 	if ( !status )
+ 		msi_dev_entry->default_irq = temp;
+-	else
+-		dev->irq = temp;
+ 
+ 	return status;
+ }
+@@ -669,7 +485,6 @@ int pci_enable_msi(struct pci_dev* dev)
+ extern void pci_frontend_disable_msi(struct pci_dev* dev);
+ void pci_disable_msi(struct pci_dev* dev)
+ {
+-	int pos;
+ 	int pirq;
+ 	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
+ 
+@@ -678,13 +493,11 @@ void pci_disable_msi(struct pci_dev* dev
+ 	if (!dev)
+ 		return;
+ 
++	if (!dev->msi_enabled)
++		return;
++
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+ 	if (!is_initial_xendomain()) {
+-		if (!(dev->msi_enabled)) {
+-			printk(KERN_INFO "PCI: %s: Device did not enabled MSI.\n",
+-			       pci_name(dev));
+-			return;
+-		}
+ 		evtchn_map_pirq(dev->irq, 0);
+ 		pci_frontend_disable_msi(dev);
+ 		dev->irq = msi_dev_entry->default_irq;
+@@ -693,23 +506,15 @@ void pci_disable_msi(struct pci_dev* dev
+ 	}
+ #endif
+ 
+-	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+-	if (!pos)
+-		return;
+-
+-	if (!(dev->msi_enabled)) {
+-		printk(KERN_INFO "PCI: %s: Device did not enabled MSI.\n",
+-		       pci_name(dev));
+-		return;
+-	}
+- 
+ 	pirq = dev->irq;
+ 	/* Restore dev->irq to its default pin-assertion vector */
+ 	dev->irq = msi_dev_entry->default_irq;
+ 	msi_unmap_pirq(dev, pirq);
+ 
+ 	/* Disable MSI mode */
+-	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++	msi_set_enable(dev, 0);
++	pci_intx(dev, 1);		/* enable intx */
++	dev->msi_enabled = 0;
+ }
+ 
+ /**
+@@ -804,7 +609,6 @@ int pci_enable_msix(struct pci_dev* dev,
+ 		printk(KERN_INFO "PCI: %s: Can't enable MSI-X.  "
+ 		       "Device already has an MSI irq assigned\n",
+ 		       pci_name(dev));
+-		dev->irq = temp;
+ 		return -EINVAL;
+ 	}
+ 
+@@ -812,8 +616,6 @@ int pci_enable_msix(struct pci_dev* dev,
+ 
+ 	if ( !status )
+ 		msi_dev_entry->default_irq = temp;
+-	else
+-		dev->irq = temp;
+ 
+ 	return status;
+ }
+@@ -821,18 +623,13 @@ int pci_enable_msix(struct pci_dev* dev,
+ 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;
+-	if (!dev->msix_enabled) {
+-		printk(KERN_INFO "PCI: %s: Device did not enabled MSI-X.\n",
+-		       pci_name(dev));
++
++	if (!dev->msix_enabled)
+ 		return;
+-	}
+ 
+ #ifdef CONFIG_XEN_PCIDEV_FRONTEND
+ 	if (!is_initial_xendomain()) {
+@@ -855,18 +652,12 @@ void pci_disable_msix(struct pci_dev* de
+ 	}
+ #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);
++	msix_set_enable(dev, 0);
++	pci_intx(dev, 1);		/* enable intx */
++	dev->msix_enabled = 0;
+ }
+ 
+ /**
+@@ -898,8 +689,6 @@ void msi_remove_pci_irq_vectors(struct p
+ 			kfree(pirq_entry);
+ 		}
+ 	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
+-	iounmap(msi_dev_entry->mask_base);
+-	msi_dev_entry->mask_base = NULL;
+ 	dev->irq = msi_dev_entry->default_irq;
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/balloon/sysfs.c	2009-06-09 15:01:37.000000000 +0200
++++ head-2010-01-18/drivers/xen/balloon/sysfs.c	2009-11-06 10:46:41.000000000 +0100
+@@ -34,6 +34,7 @@
+ #include <linux/stat.h>
+ #include <linux/string.h>
+ #include <linux/sysdev.h>
++#include <linux/module.h>
+ #include "common.h"
+ 
+ #ifdef HAVE_XEN_PLATFORM_COMPAT_H
+--- head-2010-01-18.orig/drivers/xen/blkback/xenbus.c	2008-05-08 14:02:04.000000000 +0200
++++ head-2010-01-18/drivers/xen/blkback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -527,7 +527,6 @@ static const struct xenbus_device_id blk
+ 
+ static struct xenbus_driver blkback = {
+ 	.name = "vbd",
+-	.owner = THIS_MODULE,
+ 	.ids = blkback_ids,
+ 	.probe = blkback_probe,
+ 	.remove = blkback_remove,
+@@ -537,5 +536,6 @@ static struct xenbus_driver blkback = {
+ 
+ void blkif_xenbus_init(void)
+ {
+-	xenbus_register_backend(&blkback);
++	if (xenbus_register_backend(&blkback))
++		BUG();
+ }
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:17:45.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:18:07.000000000 +0100
+@@ -911,7 +911,6 @@ MODULE_ALIAS("xen:vbd");
+ 
+ static struct xenbus_driver blkfront = {
+ 	.name = "vbd",
+-	.owner = THIS_MODULE,
+ 	.ids = blkfront_ids,
+ 	.probe = blkfront_probe,
+ 	.remove = blkfront_remove,
+--- head-2010-01-18.orig/drivers/xen/blktap/xenbus.c	2008-09-15 13:40:15.000000000 +0200
++++ head-2010-01-18/drivers/xen/blktap/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -465,7 +465,6 @@ static const struct xenbus_device_id blk
+ 
+ static struct xenbus_driver blktap = {
+ 	.name = "tap",
+-	.owner = THIS_MODULE,
+ 	.ids = blktap_ids,
+ 	.probe = blktap_probe,
+ 	.remove = blktap_remove,
+@@ -475,5 +474,6 @@ static struct xenbus_driver blktap = {
+ 
+ void tap_blkif_xenbus_init(void)
+ {
+-	xenbus_register_backend(&blktap);
++	if (xenbus_register_backend(&blktap))
++		BUG();
+ }
+--- head-2010-01-18.orig/drivers/xen/core/evtchn.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/evtchn.c	2009-11-06 10:46:41.000000000 +0100
+@@ -145,7 +145,7 @@ static void bind_evtchn_to_cpu(unsigned 
+ 	BUG_ON(!test_bit(chn, s->evtchn_mask));
+ 
+ 	if (irq != -1)
+-		set_native_irq_info(irq, cpumask_of_cpu(cpu));
++		irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+ 
+ 	clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
+ 	set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
+@@ -158,7 +158,7 @@ static void init_evtchn_cpu_bindings(voi
+ 
+ 	/* By default all event channels notify CPU#0. */
+ 	for (i = 0; i < NR_IRQS; i++)
+-		set_native_irq_info(i, cpumask_of_cpu(0));
++		irq_desc[i].affinity = cpumask_of_cpu(0);
+ 
+ 	memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
+ 	memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
+@@ -736,6 +736,7 @@ static struct irq_chip dynirq_chip = {
+ 	.name     = "Dynamic",
+ 	.startup  = startup_dynirq,
+ 	.shutdown = mask_dynirq,
++	.disable  = mask_dynirq,
+ 	.mask     = mask_dynirq,
+ 	.unmask   = unmask_dynirq,
+ 	.mask_ack = ack_dynirq,
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:46:41.000000000 +0100
+@@ -116,7 +116,7 @@ static int __cpuinit xen_smp_intr_init(u
+ 	rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR,
+ 				    cpu,
+ 				    smp_reschedule_interrupt,
+-				    SA_INTERRUPT,
++				    IRQF_DISABLED|IRQF_NOBALANCING,
+ 				    resched_name[cpu],
+ 				    NULL);
+ 	if (rc < 0)
+@@ -127,7 +127,7 @@ static int __cpuinit xen_smp_intr_init(u
+ 	rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
+ 				    cpu,
+ 				    smp_call_function_interrupt,
+-				    SA_INTERRUPT,
++				    IRQF_DISABLED|IRQF_NOBALANCING,
+ 				    callfunc_name[cpu],
+ 				    NULL);
+ 	if (rc < 0)
+@@ -256,7 +256,7 @@ void __init smp_prepare_cpus(unsigned in
+ {
+ 	unsigned int cpu;
+ 	struct task_struct *idle;
+-	int apicid, acpiid;
++	int apicid;
+ 	struct vcpu_get_physid cpu_id;
+ #ifdef __x86_64__
+ 	struct desc_ptr *gdt_descr;
+@@ -265,14 +265,8 @@ void __init smp_prepare_cpus(unsigned in
+ #endif
+ 
+ 	apicid = 0;
+-	if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 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;
+ 
+@@ -328,14 +322,8 @@ void __init smp_prepare_cpus(unsigned in
+ 			XENFEAT_writable_descriptor_tables);
+ 
+ 		apicid = cpu;
+-		if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0) {
++		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 = apicid;
+ 
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenfb.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenfb.c	2009-11-06 10:46:41.000000000 +0100
+@@ -857,7 +857,6 @@ MODULE_ALIAS("xen:vfb");
+ 
+ static struct xenbus_driver xenfb_driver = {
+ 	.name = "vfb",
+-	.owner = THIS_MODULE,
+ 	.ids = xenfb_ids,
+ 	.probe = xenfb_probe,
+ 	.remove = xenfb_remove,
+--- head-2010-01-18.orig/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/fbfront/xenkbd.c	2009-11-06 10:46:41.000000000 +0100
+@@ -323,7 +323,6 @@ MODULE_ALIAS("xen:vkbd");
+ 
+ static struct xenbus_driver xenkbd_driver = {
+ 	.name = "vkbd",
+-	.owner = THIS_MODULE,
+ 	.ids = xenkbd_ids,
+ 	.probe = xenkbd_probe,
+ 	.remove = xenkbd_remove,
+--- head-2010-01-18.orig/drivers/xen/netback/interface.c	2010-01-04 11:56:34.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/interface.c	2010-01-04 12:26:37.000000000 +0100
+@@ -121,7 +121,7 @@ static void netbk_get_drvinfo(struct net
+ 			      struct ethtool_drvinfo *info)
+ {
+ 	strcpy(info->driver, "netbk");
+-	strcpy(info->bus_info, dev->class_dev.dev->bus_id);
++	strcpy(info->bus_info, dev->dev.parent->bus_id);
+ }
+ 
+ static const struct netif_stat {
+--- head-2010-01-18.orig/drivers/xen/netback/xenbus.c	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -439,7 +439,6 @@ static const struct xenbus_device_id net
+ 
+ static struct xenbus_driver netback = {
+ 	.name = "vif",
+-	.owner = THIS_MODULE,
+ 	.ids = netback_ids,
+ 	.probe = netback_probe,
+ 	.remove = netback_remove,
+@@ -450,5 +449,6 @@ static struct xenbus_driver netback = {
+ 
+ void netif_xenbus_init(void)
+ {
+-	xenbus_register_backend(&netback);
++	if (xenbus_register_backend(&netback))
++		BUG();
+ }
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:46:41.000000000 +0100
+@@ -1892,20 +1892,19 @@ static struct ethtool_ops network_ethtoo
+ };
+ 
+ #ifdef CONFIG_SYSFS
+-static ssize_t show_rxbuf_min(struct class_device *cd, char *buf)
++static ssize_t show_rxbuf_min(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct net_device *netdev = container_of(cd, struct net_device,
+-						 class_dev);
+-	struct netfront_info *info = netdev_priv(netdev);
++	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+ 
+ 	return sprintf(buf, "%u\n", info->rx_min_target);
+ }
+ 
+-static ssize_t store_rxbuf_min(struct class_device *cd,
++static ssize_t store_rxbuf_min(struct device *dev,
++			       struct device_attribute *attr,
+ 			       const char *buf, size_t len)
+ {
+-	struct net_device *netdev = container_of(cd, struct net_device,
+-						 class_dev);
++	struct net_device *netdev = to_net_dev(dev);
+ 	struct netfront_info *np = netdev_priv(netdev);
+ 	char *endp;
+ 	unsigned long target;
+@@ -1935,20 +1934,19 @@ static ssize_t store_rxbuf_min(struct cl
+ 	return len;
+ }
+ 
+-static ssize_t show_rxbuf_max(struct class_device *cd, char *buf)
++static ssize_t show_rxbuf_max(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct net_device *netdev = container_of(cd, struct net_device,
+-						 class_dev);
+-	struct netfront_info *info = netdev_priv(netdev);
++	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+ 
+ 	return sprintf(buf, "%u\n", info->rx_max_target);
+ }
+ 
+-static ssize_t store_rxbuf_max(struct class_device *cd,
++static ssize_t store_rxbuf_max(struct device *dev,
++			       struct device_attribute *attr,
+ 			       const char *buf, size_t len)
+ {
+-	struct net_device *netdev = container_of(cd, struct net_device,
+-						 class_dev);
++	struct net_device *netdev = to_net_dev(dev);
+ 	struct netfront_info *np = netdev_priv(netdev);
+ 	char *endp;
+ 	unsigned long target;
+@@ -1978,16 +1976,15 @@ static ssize_t store_rxbuf_max(struct cl
+ 	return len;
+ }
+ 
+-static ssize_t show_rxbuf_cur(struct class_device *cd, char *buf)
++static ssize_t show_rxbuf_cur(struct device *dev,
++			      struct device_attribute *attr, char *buf)
+ {
+-	struct net_device *netdev = container_of(cd, struct net_device,
+-						 class_dev);
+-	struct netfront_info *info = netdev_priv(netdev);
++	struct netfront_info *info = netdev_priv(to_net_dev(dev));
+ 
+ 	return sprintf(buf, "%u\n", info->rx_target);
+ }
+ 
+-static const struct class_device_attribute xennet_attrs[] = {
++static struct device_attribute xennet_attrs[] = {
+ 	__ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
+ 	__ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
+ 	__ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
+@@ -1999,8 +1996,8 @@ static int xennet_sysfs_addif(struct net
+ 	int error = 0;
+ 
+ 	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
+-		error = class_device_create_file(&netdev->class_dev, 
+-						 &xennet_attrs[i]);
++		error = device_create_file(&netdev->dev,
++					   &xennet_attrs[i]);
+ 		if (error)
+ 			goto fail;
+ 	}
+@@ -2008,8 +2005,7 @@ static int xennet_sysfs_addif(struct net
+ 
+  fail:
+ 	while (--i >= 0)
+-		class_device_remove_file(&netdev->class_dev,
+-					 &xennet_attrs[i]);
++		device_remove_file(&netdev->dev, &xennet_attrs[i]);
+ 	return error;
+ }
+ 
+@@ -2017,10 +2013,8 @@ static void xennet_sysfs_delif(struct ne
+ {
+ 	int i;
+ 
+-	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++) {
+-		class_device_remove_file(&netdev->class_dev,
+-					 &xennet_attrs[i]);
+-	}
++	for (i = 0; i < ARRAY_SIZE(xennet_attrs); i++)
++		device_remove_file(&netdev->dev, &xennet_attrs[i]);
+ }
+ 
+ #endif /* CONFIG_SYSFS */
+@@ -2186,7 +2180,6 @@ MODULE_ALIAS("xen:vif");
+ 
+ static struct xenbus_driver netfront_driver = {
+ 	.name = "vif",
+-	.owner = THIS_MODULE,
+ 	.ids = netfront_ids,
+ 	.probe = netfront_probe,
+ 	.remove = __devexit_p(netfront_remove),
+--- head-2010-01-18.orig/drivers/xen/pciback/xenbus.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/pciback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -683,7 +683,6 @@ static const struct xenbus_device_id xen
+ 
+ static struct xenbus_driver xenbus_pciback_driver = {
+ 	.name 			= "pciback",
+-	.owner 			= THIS_MODULE,
+ 	.ids 			= xenpci_ids,
+ 	.probe 			= pciback_xenbus_probe,
+ 	.remove 		= pciback_xenbus_remove,
+--- head-2010-01-18.orig/drivers/xen/pcifront/xenbus.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/pcifront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -449,7 +449,6 @@ MODULE_ALIAS("xen:pci");
+ 
+ static struct xenbus_driver xenbus_pcifront_driver = {
+ 	.name 			= "pcifront",
+-	.owner 			= THIS_MODULE,
+ 	.ids 			= xenpci_ids,
+ 	.probe 			= pcifront_xenbus_probe,
+ 	.remove 		= pcifront_xenbus_remove,
+--- head-2010-01-18.orig/drivers/xen/scsiback/xenbus.c	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -360,7 +360,6 @@ static struct xenbus_device_id scsiback_
+ 
+ static struct xenbus_driver scsiback = {
+ 	.name			= "vscsi",
+-	.owner			= THIS_MODULE,
+ 	.ids			= scsiback_ids,
+ 	.probe			= scsiback_probe,
+ 	.remove			= scsiback_remove,
+--- head-2010-01-18.orig/drivers/xen/scsifront/xenbus.c	2008-07-21 11:00:33.000000000 +0200
++++ head-2010-01-18/drivers/xen/scsifront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -401,7 +401,6 @@ static struct xenbus_device_id scsifront
+ 
+ static struct xenbus_driver scsifront_driver = {
+ 	.name			= "vscsi",
+-	.owner			= THIS_MODULE,
+ 	.ids			= scsifront_ids,
+ 	.probe			= scsifront_probe,
+ 	.remove			= scsifront_remove,
+--- head-2010-01-18.orig/drivers/xen/tpmback/common.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/common.h	2009-11-06 10:46:41.000000000 +0100
+@@ -54,11 +54,11 @@ typedef struct tpmif_st {
+ 
+ void tpmif_disconnect_complete(tpmif_t * tpmif);
+ tpmif_t *tpmif_find(domid_t domid, struct backend_info *bi);
+-void tpmif_interface_init(void);
++int tpmif_interface_init(void);
+ void tpmif_interface_exit(void);
+ void tpmif_schedule_work(tpmif_t * tpmif);
+ void tpmif_deschedule_work(tpmif_t * tpmif);
+-void tpmif_xenbus_init(void);
++int tpmif_xenbus_init(void);
+ void tpmif_xenbus_exit(void);
+ int tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn);
+ irqreturn_t tpmif_be_int(int irq, void *dev_id);
+--- head-2010-01-18.orig/drivers/xen/tpmback/interface.c	2010-01-04 12:25:38.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/interface.c	2010-01-04 12:26:29.000000000 +0100
+@@ -160,13 +160,14 @@ void tpmif_disconnect_complete(tpmif_t *
+ 	free_tpmif(tpmif);
+ }
+ 
+-void __init tpmif_interface_init(void)
++int __init tpmif_interface_init(void)
+ {
+ 	tpmif_cachep = kmem_cache_create("tpmif_cache", sizeof (tpmif_t),
+ 					 0, 0, NULL, NULL);
++	return tpmif_cachep ? 0 : -ENOMEM;
+ }
+ 
+-void __exit tpmif_interface_exit(void)
++void tpmif_interface_exit(void)
+ {
+ 	kmem_cache_destroy(tpmif_cachep);
+ }
+--- head-2010-01-18.orig/drivers/xen/tpmback/tpmback.c	2010-01-04 12:23:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/tpmback.c	2010-01-04 12:26:23.000000000 +0100
+@@ -928,22 +928,30 @@ static int __init tpmback_init(void)
+ 	spin_lock_init(&tpm_schedule_list_lock);
+ 	INIT_LIST_HEAD(&tpm_schedule_list);
+ 
+-	tpmif_interface_init();
+-	tpmif_xenbus_init();
++	rc = tpmif_interface_init();
++	if (!rc) {
++		rc = tpmif_xenbus_init();
++		if (rc)
++			tpmif_interface_exit();
++	}
++	if (rc) {
++		misc_deregister(&vtpms_miscdevice);
++		return rc;
++	}
+ 
+ 	printk(KERN_ALERT "Successfully initialized TPM backend driver.\n");
+ 
+ 	return 0;
+ }
+-
+ module_init(tpmback_init);
+ 
+-void __exit tpmback_exit(void)
++static void __exit tpmback_exit(void)
+ {
+ 	vtpm_release_packets(NULL, 0);
+ 	tpmif_xenbus_exit();
+ 	tpmif_interface_exit();
+ 	misc_deregister(&vtpms_miscdevice);
+ }
++module_exit(tpmback_exit)
+ 
+ MODULE_LICENSE("Dual BSD/GPL");
+--- head-2010-01-18.orig/drivers/xen/tpmback/xenbus.c	2008-03-06 08:54:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/tpmback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -270,7 +270,6 @@ static const struct xenbus_device_id tpm
+ 
+ static struct xenbus_driver tpmback = {
+ 	.name = "vtpm",
+-	.owner = THIS_MODULE,
+ 	.ids = tpmback_ids,
+ 	.probe = tpmback_probe,
+ 	.remove = tpmback_remove,
+@@ -278,9 +277,9 @@ static struct xenbus_driver tpmback = {
+ };
+ 
+ 
+-void tpmif_xenbus_init(void)
++int tpmif_xenbus_init(void)
+ {
+-	xenbus_register_backend(&tpmback);
++	return xenbus_register_backend(&tpmback);
+ }
+ 
+ void tpmif_xenbus_exit(void)
+--- head-2010-01-18.orig/drivers/xen/usbback/xenbus.c	2009-11-06 10:23:23.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbback/xenbus.c	2009-11-06 10:49:41.000000000 +0100
+@@ -320,7 +320,6 @@ static const struct xenbus_device_id usb
+ 
+ static struct xenbus_driver usbback_driver = {
+ 	.name = "vusb",
+-	.owner = THIS_MODULE,
+ 	.ids = usbback_ids,
+ 	.probe = usbback_probe,
+ 	.otherend_changed = frontend_changed,
+--- head-2010-01-18.orig/drivers/xen/usbfront/xenbus.c	2009-10-15 11:45:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/usbfront/xenbus.c	2009-11-06 10:46:41.000000000 +0100
+@@ -376,7 +376,6 @@ static const struct xenbus_device_id usb
+ 
+ static struct xenbus_driver usbfront_driver = {
+ 	.name = "vusb",
+-	.owner = THIS_MODULE,
+ 	.ids = usbfront_ids,
+ 	.probe = usbfront_probe,
+ 	.otherend_changed = backend_changed,
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 10:51:20.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 10:52:26.000000000 +0100
+@@ -375,7 +375,9 @@ static void xenbus_dev_shutdown(struct d
+ }
+ 
+ int xenbus_register_driver_common(struct xenbus_driver *drv,
+-				  struct xen_bus_type *bus)
++				  struct xen_bus_type *bus,
++				  struct module *owner,
++				  const char *mod_name)
+ {
+ 	int ret;
+ 
+@@ -385,7 +387,10 @@ int xenbus_register_driver_common(struct
+ 	drv->driver.name = drv->name;
+ 	drv->driver.bus = &bus->bus;
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+-	drv->driver.owner = drv->owner;
++	drv->driver.owner = owner;
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++	drv->driver.mod_name = mod_name;
+ #endif
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+ 	drv->driver.probe = xenbus_dev_probe;
+@@ -399,13 +404,15 @@ int xenbus_register_driver_common(struct
+ 	return ret;
+ }
+ 
+-int xenbus_register_frontend(struct xenbus_driver *drv)
++int __xenbus_register_frontend(struct xenbus_driver *drv,
++			       struct module *owner, const char *mod_name)
+ {
+ 	int ret;
+ 
+ 	drv->read_otherend_details = read_backend_details;
+ 
+-	ret = xenbus_register_driver_common(drv, &xenbus_frontend);
++	ret = xenbus_register_driver_common(drv, &xenbus_frontend,
++					    owner, mod_name);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -414,7 +421,7 @@ int xenbus_register_frontend(struct xenb
+ 
+ 	return 0;
+ }
+-EXPORT_SYMBOL_GPL(xenbus_register_frontend);
++EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
+ 
+ void xenbus_unregister_driver(struct xenbus_driver *drv)
+ {
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.h	2009-11-06 10:46:41.000000000 +0100
+@@ -69,7 +69,9 @@ extern int xenbus_match(struct device *_
+ extern int xenbus_dev_probe(struct device *_dev);
+ extern int xenbus_dev_remove(struct device *_dev);
+ extern int xenbus_register_driver_common(struct xenbus_driver *drv,
+-					 struct xen_bus_type *bus);
++					 struct xen_bus_type *bus,
++					 struct module *owner,
++					 const char *mod_name);
+ extern int xenbus_probe_node(struct xen_bus_type *bus,
+ 			     const char *type,
+ 			     const char *nodename);
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2008-01-21 11:15:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:46:41.000000000 +0100
+@@ -172,13 +172,15 @@ static int xenbus_uevent_backend(struct 
+ 	return 0;
+ }
+ 
+-int xenbus_register_backend(struct xenbus_driver *drv)
++int __xenbus_register_backend(struct xenbus_driver *drv,
++			       struct module *owner, const char *mod_name)
+ {
+ 	drv->read_otherend_details = read_frontend_details;
+ 
+-	return xenbus_register_driver_common(drv, &xenbus_backend);
++	return xenbus_register_driver_common(drv, &xenbus_backend,
++					     owner, mod_name);
+ }
+-EXPORT_SYMBOL_GPL(xenbus_register_backend);
++EXPORT_SYMBOL_GPL(__xenbus_register_backend);
+ 
+ /* backend/<typename>/<frontend-uuid>/<name> */
+ static int xenbus_probe_backend_unit(const char *dir,
+--- head-2010-01-18.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:57:42.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:08.000000000 +0100
+@@ -235,7 +235,7 @@ static int bind_virq(void)
+ 		result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
+ 						 i,
+ 						 xenoprof_ovf_interrupt,
+-						 SA_INTERRUPT,
++						 IRQF_DISABLED|IRQF_NOBALANCING,
+ 						 "xenoprof",
+ 						 NULL);
+ 
+--- head-2010-01-18.orig/arch/x86/include/asm/i8253.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/i8253.h	2009-11-06 10:46:41.000000000 +0100
+@@ -8,10 +8,14 @@
+ 
+ extern spinlock_t i8253_lock;
+ 
++#ifdef CONFIG_GENERIC_CLOCKEVENTS
++
+ extern struct clock_event_device *global_clock_event;
+ 
+ extern void setup_pit_timer(void);
+ 
++#endif
++
+ #define inb_pit		inb_p
+ #define outb_pit	outb_p
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -21,7 +21,7 @@ struct Xgt_desc_struct {
+ 
+ extern struct Xgt_desc_struct idt_descr;
+ DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
+-
++extern struct Xgt_desc_struct early_gdt_descr;
+ 
+ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-06 10:46:41.000000000 +0100
+@@ -160,6 +160,19 @@ static inline void arch_leave_lazy_mmu_m
+ #define arch_use_lazy_mmu_mode() unlikely(__get_cpu_var(xen_lazy_mmu))
+ #endif
+ 
++#if 0 /* All uses are in places potentially called asynchronously, but
++       * asynchronous code should rather not make use of lazy mode at all.
++       * Therefore, all uses of this function get commented out, proper
++       * detection of asynchronous invocations is added whereever needed,
++       * and this function is disabled to catch any new (improper) uses.
++       */
++static inline void arch_flush_lazy_mmu_mode(void)
++{
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
++}
++#endif
++
+ #else /* !CONFIG_XEN || MODULE */
+ 
+ static inline void xen_multicall_flush(bool ignore) {}
+@@ -217,7 +230,7 @@ HYPERVISOR_block(
+ 	return rc;
+ }
+ 
+-static inline void /*__noreturn*/
++static inline void __noreturn
+ HYPERVISOR_shutdown(
+ 	unsigned int reason)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -108,7 +108,7 @@ sysexit_scrit:	/**** START OF SYSEXIT CR
+ sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+ 	mov  $__KERNEL_PDA, %ecx					; \
+ 	push %esp							; \
+-	mov  %ecx, %gs							; \
++	mov  %ecx, %fs							; \
+ 	call evtchn_do_upcall						; \
+ 	add  $4,%esp							; \
+ 	jmp  ret_from_intr
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -27,13 +27,13 @@ static inline void enter_lazy_tlb(struct
+ static inline void __prepare_arch_switch(void)
+ {
+ 	/*
+-	 * Save away %fs. No need to save %gs, as it was saved on the
++	 * Save away %gs. No need to save %fs, as it was saved on the
+ 	 * stack on entry.  No need to save %es and %ds, as those are
+ 	 * always kernel segments while inside the kernel.
+ 	 */
+-	asm volatile ( "mov %%fs,%0"
+-		: "=m" (current->thread.fs));
+-	asm volatile ( "movl %0,%%fs"
++	asm volatile ( "mov %%gs,%0"
++		: "=m" (current->thread.gs));
++	asm volatile ( "movl %0,%%gs"
+ 		: : "r" (0) );
+ }
+ 
+@@ -95,7 +95,7 @@ static inline void switch_mm(struct mm_s
+ }
+ 
+ #define deactivate_mm(tsk, mm)			\
+-	asm("movl %0,%%fs": :"r" (0));
++	asm("movl %0,%%gs": :"r" (0));
+ 
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_32.h	2008-07-21 11:00:33.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -6,12 +6,23 @@
+ #include <linux/mm.h>		/* for struct page */
+ #include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+ 
+-#define pmd_populate_kernel(mm, pmd, pte) \
+-		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
++#define paravirt_alloc_pt(pfn) do { } while (0)
++#define paravirt_alloc_pd(pfn) do { } while (0)
++#define paravirt_alloc_pd(pfn) do { } while (0)
++#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
++#define paravirt_release_pt(pfn) do { } while (0)
++#define paravirt_release_pd(pfn) do { } while (0)
++
++#define pmd_populate_kernel(mm, pmd, pte)			\
++do {								\
++	paravirt_alloc_pt(__pa(pte) >> PAGE_SHIFT);		\
++	set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));		\
++} while (0)
+ 
+ #define pmd_populate(mm, pmd, pte) 					\
+ do {									\
+ 	unsigned long pfn = page_to_pfn(pte);				\
++	paravirt_alloc_pt(pfn);						\
+ 	if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) {	\
+ 		if (!PageHighMem(pte))					\
+ 			BUG_ON(HYPERVISOR_update_va_mapping(		\
+@@ -42,7 +53,11 @@ static inline void pte_free_kernel(pte_t
+ 
+ extern void pte_free(struct page *pte);
+ 
+-#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
++#define __pte_free_tlb(tlb,pte) 					\
++do {									\
++	paravirt_release_pt(page_to_pfn(pte));				\
++	tlb_remove_page((tlb),(pte));					\
++} while (0)
+ 
+ #ifdef CONFIG_X86_PAE
+ /*
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -275,6 +275,7 @@ static inline pte_t pte_mkhuge(pte_t pte
+  */
+ #define pte_update(mm, addr, ptep)		do { } while (0)
+ #define pte_update_defer(mm, addr, ptep)	do { } while (0)
++#define paravirt_map_pt_hook(slot, va, pfn)	do { } while (0)
+ 
+ /*
+  * We only update the dirty/accessed state if we set
+@@ -490,12 +491,24 @@ extern pte_t *lookup_address(unsigned lo
+ #endif
+ 
+ #if defined(CONFIG_HIGHPTE)
+-#define pte_offset_map(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \
+-	 pte_index(address))
+-#define pte_offset_map_nested(dir, address) \
+-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + \
+-	 pte_index(address))
++#define pte_offset_map(dir, address)				\
++({								\
++	pte_t *__ptep;						\
++	unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;		\
++	__ptep = (pte_t *)kmap_atomic_pte(pfn_to_page(pfn),KM_PTE0); \
++	paravirt_map_pt_hook(KM_PTE0,__ptep, pfn);		\
++	__ptep = __ptep + pte_index(address);			\
++	__ptep;							\
++})
++#define pte_offset_map_nested(dir, address)			\
++({								\
++	pte_t *__ptep;						\
++	unsigned pfn = pmd_val(*(dir)) >> PAGE_SHIFT;		\
++	__ptep = (pte_t *)kmap_atomic_pte(pfn_to_page(pfn),KM_PTE1); \
++	paravirt_map_pt_hook(KM_PTE1,__ptep, pfn);		\
++	__ptep = __ptep + pte_index(address);			\
++	__ptep;							\
++})
+ #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
+ #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
+ #else
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -431,7 +431,7 @@ struct thread_struct {
+ 	.vm86_info = NULL,						\
+ 	.sysenter_cs = __KERNEL_CS,					\
+ 	.io_bitmap_ptr = NULL,						\
+-	.gs = __KERNEL_PDA,						\
++	.fs = __KERNEL_PDA,						\
+ }
+ 
+ /*
+@@ -449,8 +449,8 @@ struct thread_struct {
+ }
+ 
+ #define start_thread(regs, new_eip, new_esp) do {		\
+-	__asm__("movl %0,%%fs": :"r" (0));			\
+-	regs->xgs = 0;						\
++	__asm__("movl %0,%%gs": :"r" (0));			\
++	regs->xfs = 0;						\
+ 	set_fs(USER_DS);					\
+ 	regs->xds = __USER_DS;					\
+ 	regs->xes = __USER_DS;					\
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:46:41.000000000 +0100
+@@ -52,6 +52,11 @@ extern void cpu_exit_clear(void);
+ extern void cpu_uninit(void);
+ #endif
+ 
++#ifndef CONFIG_PARAVIRT
++#define startup_ipi_hook(phys_apicid, start_eip, start_esp) 		\
++do { } while (0)
++#endif
++
+ /*
+  * This function is needed by all SMP systems. It must _always_ be valid
+  * from the initial startup. We map APIC_BASE very early in page_setup(),
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:46:41.000000000 +0100
+@@ -416,15 +416,6 @@ static inline int pmd_large(pmd_t pte) {
+ #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+ #define mk_pte_huge(entry) (__pte_val(entry) |= _PAGE_PRESENT | _PAGE_PSE)
+  
+-/* physical address -> PTE */
+-static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+-{ 
+-	unsigned long pteval;
+-	pteval = physpage | pgprot_val(pgprot);
+-	pteval &= __supported_pte_mask;
+-	return __pte(pteval);
+-}
+- 
+ /* Change flags of a PTE */
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ { 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:46:41.000000000 +0100
+@@ -7,6 +7,7 @@
+ #include <linux/threads.h>
+ #include <linux/cpumask.h>
+ #include <linux/bitops.h>
++#include <linux/init.h>
+ extern int disable_apic;
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -73,7 +74,7 @@ extern int __cpu_disable(void);
+ extern void __cpu_die(unsigned int cpu);
+ extern void prefill_possible_map(void);
+ extern unsigned num_processors;
+-extern unsigned disabled_cpus;
++extern unsigned __cpuinitdata disabled_cpus;
+ 
+ #define NO_PROC_ID		0xFF		/* No processor magic marker */
+ 
+--- head-2010-01-18.orig/include/xen/xenbus.h	2009-12-04 10:44:50.000000000 +0100
++++ head-2010-01-18/include/xen/xenbus.h	2009-11-06 10:46:41.000000000 +0100
+@@ -93,8 +93,7 @@ struct xenbus_device_id
+ 
+ /* A xenbus driver. */
+ struct xenbus_driver {
+-	char *name;
+-	struct module *owner;
++	const char *name;
+ 	const struct xenbus_device_id *ids;
+ 	int (*probe)(struct xenbus_device *dev,
+ 		     const struct xenbus_device_id *id);
+@@ -115,8 +114,25 @@ static inline struct xenbus_driver *to_x
+ 	return container_of(drv, struct xenbus_driver, driver);
+ }
+ 
+-int xenbus_register_frontend(struct xenbus_driver *drv);
+-int xenbus_register_backend(struct xenbus_driver *drv);
++int __must_check __xenbus_register_frontend(struct xenbus_driver *drv,
++					    struct module *owner,
++					    const char *mod_name);
++
++static inline int __must_check
++xenbus_register_frontend(struct xenbus_driver *drv)
++{
++	return __xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME);
++}
++
++int __must_check __xenbus_register_backend(struct xenbus_driver *drv,
++					   struct module *owner,
++					   const char *mod_name);
++static inline int __must_check
++xenbus_register_backend(struct xenbus_driver *drv)
++{
++	return __xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME);
++}
++
+ void xenbus_unregister_driver(struct xenbus_driver *drv);
+ 
+ struct xenbus_transaction
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-04-07 13:58:49.000000000 +0200
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:46:41.000000000 +0100
+@@ -135,8 +135,8 @@ __setup("swiotlb=", setup_io_tlb_npages)
+  * Statically reserve bounce buffer space and initialize bounce buffer data
+  * structures for the software IO TLB used to implement the PCI DMA API.
+  */
+-void
+-swiotlb_init_with_default_size (size_t default_size)
++void __init
++swiotlb_init_with_default_size(size_t default_size)
+ {
+ 	unsigned long i, bytes;
+ 	int rc;
+@@ -221,7 +221,7 @@ swiotlb_init_with_default_size (size_t d
+ 	       dma_bits);
+ }
+ 
+-void
++void __init
+ swiotlb_init(void)
+ {
+ 	long ram_end;
+@@ -457,8 +457,8 @@ swiotlb_full(struct device *dev, size_t 
+ 	 * When the mapping is small enough return a static buffer to limit
+ 	 * the damage, or panic when the transfer is too big.
+ 	 */
+-	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %lu bytes at "
+-	       "device %s\n", (unsigned long)size, dev ? dev->bus_id : "?");
++	printk(KERN_ERR "PCI-DMA: Out of SW-IOMMU space for %zu bytes at "
++	       "device %s\n", size, dev ? dev->bus_id : "?");
+ 
+ 	if (size > io_tlb_overflow && do_panic) {
+ 		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+@@ -602,7 +602,7 @@ swiotlb_map_sg(struct device *hwdev, str
+ 				sg[0].dma_length = 0;
+ 				return 0;
+ 			}
+-			sg->dma_address = (dma_addr_t)virt_to_bus(map);
++			sg->dma_address = virt_to_bus(map);
+ 		} else
+ 			sg->dma_address = dev_addr;
+ 		sg->dma_length = sg->length;
+@@ -624,8 +624,7 @@ swiotlb_unmap_sg(struct device *hwdev, s
+ 
+ 	for (i = 0; i < nelems; i++, sg++)
+ 		if (in_swiotlb_aperture(sg->dma_address))
+-			unmap_single(hwdev, 
+-				     (void *)bus_to_virt(sg->dma_address),
++			unmap_single(hwdev, bus_to_virt(sg->dma_address),
+ 				     sg->dma_length, dir);
+ 		else
+ 			gnttab_dma_unmap_page(sg->dma_address);
+@@ -648,8 +647,7 @@ swiotlb_sync_sg_for_cpu(struct device *h
+ 
+ 	for (i = 0; i < nelems; i++, sg++)
+ 		if (in_swiotlb_aperture(sg->dma_address))
+-			sync_single(hwdev,
+-				    (void *)bus_to_virt(sg->dma_address),
++			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ }
+ 
+@@ -663,8 +661,7 @@ swiotlb_sync_sg_for_device(struct device
+ 
+ 	for (i = 0; i < nelems; i++, sg++)
+ 		if (in_swiotlb_aperture(sg->dma_address))
+-			sync_single(hwdev,
+-				    (void *)bus_to_virt(sg->dma_address),
++			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
+ }
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.24
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.24
@@ -0,0 +1,8553 @@
+From: www.kernel.org
+Subject: Update to 2.6.24
+Patch-mainline: 2.6.24
+
+Automatically created from "patches.kernel.org/patch-2.6.24" by xen-port-patches.py
+
+Acked-by: jbeulich@novell.com
+
+--- head-2010-01-18.orig/arch/x86/Kconfig	2009-11-20 11:00:19.000000000 +0100
++++ head-2010-01-18/arch/x86/Kconfig	2009-11-20 11:01:19.000000000 +0100
+@@ -69,15 +69,16 @@ config GENERIC_CMOS_UPDATE
+ 
+ config CLOCKSOURCE_WATCHDOG
+ 	def_bool y
+-	depends on !X86_XEN
++	depends on !XEN
+ 
+ config GENERIC_CLOCKEVENTS
+ 	def_bool y
+-	depends on !X86_XEN
++	depends on !XEN
+ 
+ config GENERIC_CLOCKEVENTS_BROADCAST
+ 	def_bool y
+-	depends on X86_64 || (X86_32 && X86_LOCAL_APIC && !X86_XEN)
++	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
++	depends on !XEN
+ 
+ config LOCKDEP_SUPPORT
+ 	def_bool y
+@@ -227,12 +228,12 @@ config X86_TRAMPOLINE
+ 
+ config X86_NO_TSS
+ 	bool
+-	depends on X86_XEN || X86_64_XEN
++	depends on XEN
+ 	default y
+ 
+ config X86_NO_IDT
+ 	bool
+-	depends on X86_XEN || X86_64_XEN
++	depends on XEN
+ 	default y
+ 
+ config X86_32_LAZY_GS
+@@ -314,6 +315,7 @@ config X86_MPPARSE
+ 
+ config X86_XEN
+ 	bool "Xen-compatible"
++	depends on X86_32
+ 	select XEN
+ 	select X86_PAE
+ 	select X86_UP_APIC if !SMP && XEN_PRIVILEGED_GUEST
+@@ -354,6 +356,7 @@ endif
+ 
+ config X86_64_XEN
+ 	bool "Enable Xen compatible kernel"
++	depends on X86_64
+ 	select XEN
+ 	select SWIOTLB
+ 	help
+@@ -672,7 +675,7 @@ source "arch/x86/Kconfig.cpu"
+ config HPET_TIMER
+ 	def_bool X86_64
+ 	prompt "HPET Timer Support" if X86_32
+-	depends on !X86_XEN && !X86_64_XEN
++	depends on !XEN
+ 	---help---
+ 	  Use the IA-PC HPET (High Precision Event Timer) to manage
+ 	  time in preference to the PIT and RTC, if a HPET is
+@@ -1008,7 +1011,7 @@ config I8K
+ 
+ config X86_REBOOTFIXUPS
+ 	bool "Enable X86 board specific fixups for reboot"
+-	depends on X86_32 && !X86_XEN
++	depends on X86_32 && !XEN
+ 	---help---
+ 	  This enables chipset and/or board specific fixups to be done
+ 	  in order to get reboot to work correctly. This is only needed on
+@@ -1407,7 +1410,7 @@ config X86_RESERVE_LOW_64K
+ config MATH_EMULATION
+ 	bool
+ 	prompt "Math emulation" if X86_32
+-	depends on !X86_XEN
++	depends on !XEN
+ 	---help---
+ 	  Linux can emulate a math coprocessor (used for floating point
+ 	  operations) if you don't have one. 486DX and Pentium processors have
+@@ -1778,6 +1781,7 @@ endmenu
+ config ARCH_ENABLE_MEMORY_HOTPLUG
+ 	def_bool y
+ 	depends on X86_64 || (X86_32 && HIGHMEM)
++	depends on !XEN
+ 
+ config ARCH_ENABLE_MEMORY_HOTREMOVE
+ 	def_bool y
+@@ -1969,7 +1973,7 @@ choice
+ 
+ config PCI_GOBIOS
+ 	bool "BIOS"
+-	depends on !X86_XEN
++	depends on !XEN
+ 
+ config PCI_GOMMCONFIG
+ 	bool "MMConfig"
+@@ -2020,7 +2024,7 @@ config PCI_MMCONFIG
+ 
+ config XEN_PCIDEV_FRONTEND
+ 	bool "Xen PCI Frontend" if X86_64
+-	depends on PCI && ((X86_XEN && (PCI_GOXEN_FE || PCI_GOANY)) || X86_64_XEN)
++	depends on PCI && XEN && (PCI_GOXEN_FE || PCI_GOANY || X86_64)
+  	select HOTPLUG
+ 	default y
+ 	help
+@@ -2036,7 +2040,7 @@ config XEN_PCIDEV_FE_DEBUG
+ 
+ config DMAR
+ 	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
+-	depends on PCI_MSI && ACPI && EXPERIMENTAL
++	depends on PCI_MSI && ACPI && !XEN && EXPERIMENTAL
+ 	help
+ 	  DMA remapping (DMAR) devices support enables independent address
+ 	  translations for Direct Memory Access (DMA) from devices.
+--- head-2010-01-18.orig/arch/x86/Makefile	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/Makefile	2009-11-06 10:51:17.000000000 +0100
+@@ -158,8 +158,8 @@ BOOT_TARGETS = bzlilo bzdisk fdimage fdi
+ PHONY += bzImage vmlinuz $(BOOT_TARGETS)
+ 
+ ifdef CONFIG_XEN
+-CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
+-	-Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS)
++KBUILD_CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
++	-Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(KBUILD_CPPFLAGS)
+ 
+ ifdef CONFIG_X86_64
+ LDFLAGS_vmlinux := -e startup_64
+@@ -173,6 +173,8 @@ KBUILD_IMAGE := $(boot)/vmlinuz
+ 
+ vmlinuz: vmlinux
+ 	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
++	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
++	$(Q)ln -fsn ../../x86/boot/$@ $(objtree)/arch/$(UTS_MACHINE)/boot/$@
+ else
+ # Default kernel to build
+ all: bzImage
+--- head-2010-01-18.orig/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/ia32/ia32entry-xen.S	2009-11-06 10:51:17.000000000 +0100
+@@ -125,20 +125,16 @@ sysenter_do_call:	
+ 	jmp int_ret_from_sys_call
+ 
+ sysenter_tracesys:
++	xchgl	%r9d,%ebp
+ 	SAVE_REST
+ 	CLEAR_RREGS
++	movq	%r9,R9(%rsp)
+ 	movq	$-ENOSYS,RAX(%rsp)	/* really needed? */
+ 	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call	syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
+-	movl	%ebp, %ebp
+-	/* no need to do an access_ok check here because rbp has been
+-	   32bit zero extended */ 
+-1:	movl	(%rbp),%r9d
+-	.section __ex_table,"a"
+-	.quad 1b,ia32_badarg
+-	.previous
++	xchgl	%ebp,%r9d
+ 	jmp	sysenter_do_call
+ 	CFI_ENDPROC
+ ENDPROC(ia32_sysenter_target)
+@@ -200,20 +196,17 @@ cstar_do_call:	
+ 	jmp int_ret_from_sys_call
+ 	
+ cstar_tracesys:	
++	xchgl %r9d,%ebp
+ 	SAVE_REST
+ 	CLEAR_RREGS
++	movq %r9,R9(%rsp)
+ 	movq $-ENOSYS,RAX(%rsp)	/* really needed? */
+ 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+ 	call syscall_trace_enter
+ 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+ 	RESTORE_REST
++	xchgl %ebp,%r9d
+ 	movl RSP-ARGOFFSET(%rsp), %r8d
+-	/* no need to do an access_ok check here because r8 has been
+-	   32bit zero extended */ 
+-1:	movl	(%r8),%r9d
+-	.section __ex_table,"a"
+-	.quad 1b,ia32_badarg
+-	.previous
+ 	jmp cstar_do_call
+ END(ia32_cstar_target)
+ 				
+--- head-2010-01-18.orig/arch/x86/kernel/Makefile	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/Makefile	2009-11-06 10:51:17.000000000 +0100
+@@ -141,4 +141,4 @@ endif
+ disabled-obj-$(CONFIG_XEN) := early-quirks.o hpet.o i8253.o i8259_$(BITS).o reboot.o \
+ 	smpboot_$(BITS).o tsc_$(BITS).o tsc_sync.o
+ disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += mpparse_64.o
+-%/head_64.o %/head_64.s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) :=
++%/head_64.o %/head_64.s: asflags-$(CONFIG_XEN) :=
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -90,7 +90,7 @@ __setup("acpi_sleep=", acpi_sleep_setup)
+ 
+ /* Ouch, we want to delete this. We already have better version in userspace, in
+    s2ram from suspend.sf.net project */
+-static __init int reset_videomode_after_s3(struct dmi_system_id *d)
++static __init int reset_videomode_after_s3(const struct dmi_system_id *d)
+ {
+ 	acpi_realmode_flags |= 2;
+ 	return 0;
+--- head-2010-01-18.orig/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/acpi/sleep_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -123,6 +123,3 @@ static int __init acpi_sleep_setup(char 
+ __setup("acpi_sleep=", acpi_sleep_setup);
+ #endif				/* CONFIG_ACPI_PV_SLEEP */
+ 
+-void acpi_pci_link_exit(void)
+-{
+-}
+--- head-2010-01-18.orig/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/apic_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -63,22 +63,38 @@ int setup_profiling_timer(unsigned int m
+ 
+ void smp_local_timer_interrupt(void)
+ {
+-	profile_tick(CPU_PROFILING);
+ #ifndef CONFIG_XEN
+-#ifdef CONFIG_SMP
+-	update_process_times(user_mode(get_irq_regs()));
+-#endif
+-#endif
++	int cpu = smp_processor_id();
++	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
++
+ 	/*
+-	 * We take the 'long' return path, and there every subsystem
+-	 * grabs the appropriate locks (kernel lock/ irq lock).
++	 * Normally we should not be here till LAPIC has been initialized but
++	 * in some cases like kdump, its possible that there is a pending LAPIC
++	 * timer interrupt from previous kernel's context and is delivered in
++	 * new kernel the moment interrupts are enabled.
+ 	 *
+-	 * We might want to decouple profiling from the 'long path',
+-	 * and do the profiling totally in assembly.
+-	 *
+-	 * Currently this isn't too much of an issue (performance wise),
+-	 * we can take more than 100K local irqs per second on a 100 MHz P5.
++	 * Interrupts are enabled early and LAPIC is setup much later, hence
++	 * its possible that when we get here evt->event_handler is NULL.
++	 * Check for event_handler being NULL and discard the interrupt as
++	 * spurious.
++	 */
++	if (!evt->event_handler) {
++		printk(KERN_WARNING
++		       "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
++		/* Switch it off */
++		lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
++		return;
++	}
++#endif
++
++	/*
++	 * the NMI deadlock-detector uses this.
+ 	 */
++	add_pda(apic_timer_irqs, 1);
++
++#ifndef CONFIG_XEN
++	evt->event_handler(evt);
++#endif
+ }
+ 
+ /*
+@@ -94,11 +110,6 @@ void smp_apic_timer_interrupt(struct pt_
+ 	struct pt_regs *old_regs = set_irq_regs(regs);
+ 
+ 	/*
+-	 * the NMI deadlock-detector uses this.
+-	 */
+-	add_pda(apic_timer_irqs, 1);
+-
+-	/*
+ 	 * NOTE! We'd better ACK the irq immediately,
+ 	 * because timer handling can be slow.
+ 	 */
+@@ -132,6 +143,7 @@ asmlinkage void smp_spurious_interrupt(v
+ 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
+ 		ack_APIC_irq();
+ 
++	add_pda(irq_spurious_count, 1);
+ 	irq_exit();
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/common-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -214,7 +214,7 @@ static void __cpuinit get_cpu_vendor(str
+ 
+ static int __init x86_fxsr_setup(char * s)
+ {
+-	/* Tell all the other CPU's to not use it... */
++	/* Tell all the other CPUs to not use it... */
+ 	disable_x86_fxsr = 1;
+ 
+ 	/*
+--- head-2010-01-18.orig/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -52,6 +52,13 @@ struct resource code_resource = {
+ 	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+ 
++struct resource bss_resource = {
++	.name	= "Kernel bss",
++	.start	= 0,
++	.end	= 0,
++	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
+ static struct resource system_rom_resource = {
+ 	.name	= "System ROM",
+ 	.start	= 0xf0000,
+@@ -266,7 +273,9 @@ static struct e820map machine_e820;
+  * and also for regions reported as reserved by the e820.
+  */
+ static void __init
+-legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
++legacy_init_iomem_resources(struct resource *code_resource,
++			    struct resource *data_resource,
++			    struct resource *bss_resource)
+ {
+ 	int i;
+ 
+@@ -300,9 +309,11 @@ legacy_init_iomem_resources(struct resou
+ #ifndef CONFIG_XEN
+ 			request_resource(res, code_resource);
+ 			request_resource(res, data_resource);
++			request_resource(res, bss_resource);
+ #endif
+ #ifdef CONFIG_KEXEC
+-			request_resource(res, &crashk_res);
++			if (crashk_res.start != crashk_res.end)
++				request_resource(res, &crashk_res);
+ #ifdef CONFIG_XEN
+ 			xen_machine_kexec_register_resources(res);
+ #endif
+@@ -329,9 +340,11 @@ static int __init request_standard_resou
+ 
+ 	printk("Setting up standard PCI resources\n");
+ 	if (efi_enabled)
+-		efi_initialize_iomem_resources(&code_resource, &data_resource);
++		efi_initialize_iomem_resources(&code_resource,
++				&data_resource, &bss_resource);
+ 	else
+-		legacy_init_iomem_resources(&code_resource, &data_resource);
++		legacy_init_iomem_resources(&code_resource,
++				&data_resource, &bss_resource);
+ 
+ 	/* EFI systems may still have VGA */
+ 	request_resource(&iomem_resource, &video_ram_resource);
+@@ -761,7 +774,7 @@ void __init e820_register_memory(void)
+ #define e820 machine_e820
+ #endif
+ 	/*
+-	 * Search for the bigest gap in the low 32 bits of the e820
++	 * Search for the biggest gap in the low 32 bits of the e820
+ 	 * memory space.
+ 	 */
+ 	last = 0x100000000ull;
+--- head-2010-01-18.orig/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:00:18.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/e820_64-xen.c	2009-12-04 11:01:22.000000000 +0100
+@@ -24,7 +24,7 @@
+ #include <asm/page.h>
+ #include <asm/e820.h>
+ #include <asm/proto.h>
+-#include <asm/bootsetup.h>
++#include <asm/setup.h>
+ #include <asm/sections.h>
+ #include <xen/interface/memory.h>
+ 
+@@ -53,7 +53,7 @@ unsigned long end_pfn_map; 
+  */
+ static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
+ 
+-extern struct resource code_resource, data_resource;
++extern struct resource code_resource, data_resource, bss_resource;
+ 
+ /* 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)
+@@ -75,10 +75,15 @@ static inline int bad_addr(unsigned long
+ 
+ 	/* initrd */ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+-	if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 
+-	    addr < INITRD_START+INITRD_SIZE) { 
+-		*addrp = PAGE_ALIGN(INITRD_START + INITRD_SIZE);
+-		return 1;
++	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
++		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
++		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
++		unsigned long ramdisk_end   = ramdisk_image+ramdisk_size;
++
++		if (last >= ramdisk_image && addr < ramdisk_end) {
++			*addrp = PAGE_ALIGN(ramdisk_end);
++			return 1;
++		}
+ 	} 
+ #endif
+ 	/* kernel code */
+@@ -251,6 +256,7 @@ void __init e820_reserve_resources(struc
+ #ifndef CONFIG_XEN
+ 			request_resource(res, &code_resource);
+ 			request_resource(res, &data_resource);
++			request_resource(res, &bss_resource);
+ #endif
+ #ifdef CONFIG_KEXEC
+ 			if (crashk_res.start != crashk_res.end)
+@@ -661,8 +667,8 @@ void __init setup_memory_region(void)
+ 	 * Otherwise fake a memory map; one section from 0k->640k,
+ 	 * the next section from 1mb->appropriate_mem_k
+ 	 */
+-	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
++	sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries);
++	if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) < 0)
+ 		early_panic("Cannot find a valid memory map");
+ 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+ 	e820_print_map("BIOS-e820");
+@@ -847,3 +853,22 @@ __init void e820_setup_gap(struct e820en
+ 	printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+ 		pci_mem_start, gapstart, gapsize);
+ }
++
++int __init arch_get_ram_range(int slot, u64 *addr, u64 *size)
++{
++	int i;
++
++	if (slot < 0 || slot >= e820.nr_map)
++		return -1;
++	for (i = slot; i < e820.nr_map; i++) {
++		if (e820.map[i].type != E820_RAM)
++			continue;
++		break;
++	}
++	if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT))
++		return -1;
++	*addr = e820.map[i].addr;
++	*size = min_t(u64, e820.map[i].size + e820.map[i].addr,
++		max_pfn << PAGE_SHIFT) - *addr;
++	return i + 1;
++}
+--- head-2010-01-18.orig/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/early_printk-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -6,15 +6,10 @@
+ #include <asm/io.h>
+ #include <asm/processor.h>
+ #include <asm/fcntl.h>
+-
+-/* Simple VGA output */
+-
+-#ifdef __i386__
+ #include <asm/setup.h>
+-#else
+-#include <asm/bootsetup.h>
+-#endif
++
+ #ifndef CONFIG_XEN
++/* Simple VGA output */
+ #define VGABASE		(__ISA_IO_base + 0xb8000)
+ 
+ static int max_ypos = 25, max_xpos = 80;
+@@ -264,10 +259,10 @@ static int __init setup_early_printk(cha
+ 		early_console = &early_serial_console;
+ 	} else if (!strncmp(buf, "vga", 3)) {
+ #ifndef CONFIG_XEN
+-	           && SCREEN_INFO.orig_video_isVGA == 1) {
+-		max_xpos = SCREEN_INFO.orig_video_cols;
+-		max_ypos = SCREEN_INFO.orig_video_lines;
+-		current_ypos = SCREEN_INFO.orig_y;
++	           && boot_params.screen_info.orig_video_isVGA == 1) {
++		max_xpos = boot_params.screen_info.orig_video_cols;
++		max_ypos = boot_params.screen_info.orig_video_lines;
++		current_ypos = boot_params.screen_info.orig_y;
+ #endif
+ 		early_console = &early_vga_console;
+  	} else if (!strncmp(buf, "simnow", 6)) {
+--- head-2010-01-18.orig/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_32-xen.S	2009-11-06 10:51:17.000000000 +0100
+@@ -254,6 +254,7 @@ check_userspace:
+ 	jb resume_kernel		# not returning to v8086 or userspace
+ 
+ ENTRY(resume_userspace)
++	LOCKDEP_SYS_EXIT
+  	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+@@ -341,6 +342,7 @@ sysenter_past_esp:
+ 	jae syscall_badsys
+ 	call *sys_call_table(,%eax,4)
+ 	movl %eax,PT_EAX(%esp)
++	LOCKDEP_SYS_EXIT
+ 	DISABLE_INTERRUPTS(CLBR_ANY)
+ 	TRACE_IRQS_OFF
+ 	movl TI_flags(%ebp), %ecx
+@@ -406,6 +408,7 @@ syscall_call:
+ 	call *sys_call_table(,%eax,4)
+ 	movl %eax,PT_EAX(%esp)		# store the return value
+ syscall_exit:
++	LOCKDEP_SYS_EXIT
+ 	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+@@ -478,7 +481,7 @@ ldt_ss:
+ 	 * is still available to implement the setting of the high
+ 	 * 16-bits in the INTERRUPT_RETURN paravirt-op.
+ 	 */
+-	cmpl $0, paravirt_ops+PARAVIRT_enabled
++	cmpl $0, pv_info+PARAVIRT_enabled
+ 	jne restore_nocheck
+ #endif
+ 
+@@ -540,6 +543,7 @@ work_pending:
+ 	jz work_notifysig
+ work_resched:
+ 	call schedule
++	LOCKDEP_SYS_EXIT
+ 	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+ 					# setting need_resched or sigpending
+ 					# between sampling and the iret
+@@ -1268,6 +1272,6 @@ ENTRY(kernel_thread_helper)
+ ENDPROC(kernel_thread_helper)
+ 
+ .section .rodata,"a"
+-#include "syscall_table.S"
++#include "syscall_table_32.S"
+ 
+ syscall_table_size=(.-sys_call_table)
+--- head-2010-01-18.orig/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/entry_64-xen.S	2009-11-06 10:51:17.000000000 +0100
+@@ -57,7 +57,7 @@
+ #include <xen/interface/arch-x86_64.h>
+ #include <xen/interface/features.h>
+ 
+-#include "xen_entry.S"
++#include "xen_entry_64.S"
+ 	
+ 	.code64
+ 
+@@ -275,6 +275,7 @@ ret_from_sys_call:
+ 	movl $_TIF_ALLWORK_MASK,%edi
+ 	/* edi:	flagmask */
+ sysret_check:		
++	LOCKDEP_SYS_EXIT
+ 	GET_THREAD_INFO(%rcx)
+         XEN_BLOCK_EVENTS(%rsi)        
+ 	TRACE_IRQS_OFF
+@@ -365,6 +366,7 @@ int_ret_from_sys_call:
+ 	movl $_TIF_ALLWORK_MASK,%edi
+ 	/* edi:	mask to check */
+ int_with_check:
++	LOCKDEP_SYS_EXIT_IRQ
+ 	GET_THREAD_INFO(%rcx)
+ 	movl threadinfo_flags(%rcx),%edx
+ 	andl %edi,%edx
+@@ -516,11 +518,12 @@ END(stub_rt_sigreturn)
+ 
+ retint_check:
+ 	CFI_DEFAULT_STACK adj=1
++	LOCKDEP_SYS_EXIT_IRQ
+ 	movl threadinfo_flags(%rcx),%edx
+ 	andl %edi,%edx
+ 	CFI_REMEMBER_STATE
+ 	jnz  retint_careful
+-retint_restore_args:
++retint_restore_args:	/* return to kernel space */
+ 	movl EFLAGS-REST_SKIP(%rsp), %eax
+ 	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
+ 	XEN_GET_VCPU_INFO(%rsi)
+@@ -841,7 +844,7 @@ error_call_handler:
+ 	movq ORIG_RAX(%rsp),%rsi	# get error code 
+ 	movq $-1,ORIG_RAX(%rsp)
+ 	call *%rax
+-error_exit:		
++error_exit:
+ 	RESTORE_REST
+ /*	cli */
+ 	XEN_BLOCK_EVENTS(%rsi)		
+@@ -849,14 +852,11 @@ error_exit:		
+ 	GET_THREAD_INFO(%rcx)	
+ 	testb $3,CS-ARGOFFSET(%rsp)
+ 	jz retint_kernel
++	LOCKDEP_SYS_EXIT_IRQ
+ 	movl  threadinfo_flags(%rcx),%edx
+ 	movl  $_TIF_WORK_MASK,%edi	
+ 	andl  %edi,%edx
+ 	jnz   retint_careful
+-	/*
+-	 * The iret might restore flags:
+-	 */
+-	TRACE_IRQS_IRETQ
+ 	jmp   retint_restore_args
+ 
+ #if 0
+@@ -1071,7 +1071,7 @@ child_rip:
+ 	movq %rsi, %rdi
+ 	call *%rax
+ 	# exit
+-	xorl %edi, %edi
++	mov %eax, %edi
+ 	call do_exit
+ 	CFI_ENDPROC
+ ENDPROC(child_rip)
+--- head-2010-01-18.orig/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/head64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/arch/x86_64/kernel/head64.c -- prepare to run common code
++ *  prepare to run common code
+  *
+  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+  *
+@@ -21,7 +21,6 @@
+ #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>
+@@ -47,27 +46,16 @@ static void __init clear_bss(void)
+ }
+ #endif
+ 
+-#define NEW_CL_POINTER		0x228	/* Relative to real mode data */
+-#define OLD_CL_MAGIC_ADDR	0x20
+-#define OLD_CL_MAGIC            0xA33F
+-#define OLD_CL_OFFSET           0x22
+-
+ static void __init copy_bootdata(char *real_mode_data)
+ {
+ #ifndef CONFIG_XEN
+-	unsigned long new_data;
+ 	char * command_line;
+ 
+-	memcpy(x86_boot_params, real_mode_data, BOOT_PARAM_SIZE);
+-	new_data = *(u32 *) (x86_boot_params + NEW_CL_POINTER);
+-	if (!new_data) {
+-		if (OLD_CL_MAGIC != *(u16 *)(real_mode_data + OLD_CL_MAGIC_ADDR)) {
+-			return;
+-		}
+-		new_data = __pa(real_mode_data) + *(u16 *)(real_mode_data + OLD_CL_OFFSET);
++	memcpy(&boot_params, real_mode_data, sizeof boot_params);
++	if (boot_params.hdr.cmd_line_ptr) {
++		command_line = __va(boot_params.hdr.cmd_line_ptr);
++		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ 	}
+-	command_line = __va(new_data);
+-	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ #else
+ 	int max_cmdline;
+ 	
+@@ -117,7 +105,7 @@ void __init x86_64_start_kernel(char * r
+ 
+ 	for (i = 0; i < IDT_ENTRIES; i++)
+ 		set_intr_gate(i, early_idt_handler);
+-	asm volatile("lidt %0" :: "m" (idt_descr));
++	load_idt((const struct desc_ptr *)&idt_descr);
+ #endif
+ 
+ 	early_printk("Kernel alive\n");
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -427,7 +427,7 @@ static struct irq_cpu_info {
+ 
+ #define IRQ_ALLOWED(cpu, allowed_mask)	cpu_isset(cpu, allowed_mask)
+ 
+-#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
++#define CPU_TO_PACKAGEINDEX(i) (first_cpu(per_cpu(cpu_sibling_map, i)))
+ 
+ static cpumask_t balance_irq_affinity[NR_IRQS] = {
+ 	[0 ... NR_IRQS-1] = CPU_MASK_ALL
+@@ -633,7 +633,7 @@ tryanotherirq:
+ 
+ 	imbalance = move_this_load;
+ 	
+-	/* For physical_balance case, we accumlated both load
++	/* For physical_balance case, we accumulated both load
+ 	 * values in the one of the siblings cpu_irq[],
+ 	 * to use the same code for physical and logical processors
+ 	 * as much as possible. 
+@@ -647,7 +647,7 @@ tryanotherirq:
+ 	 * (A+B)/2 vs B
+ 	 */
+ 	load = CPU_IRQ(min_loaded) >> 1;
+-	for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) {
++	for_each_cpu_mask(j, per_cpu(cpu_sibling_map, min_loaded)) {
+ 		if (load > CPU_IRQ(j)) {
+ 			/* This won't change cpu_sibling_map[min_loaded] */
+ 			load = CPU_IRQ(j);
+@@ -1018,7 +1018,7 @@ static int EISA_ELCR(unsigned int irq)
+ #define default_MCA_trigger(idx)	(1)
+ #define default_MCA_polarity(idx)	(0)
+ 
+-static int __init MPBIOS_polarity(int idx)
++static int MPBIOS_polarity(int idx)
+ {
+ 	int bus = mp_irqs[idx].mpc_srcbus;
+ 	int polarity;
+@@ -1347,6 +1347,11 @@ static void __init setup_IO_APIC_irqs(vo
+ 			continue;
+ 		}
+ 
++		if (!first_notcon) {
++			apic_printk(APIC_VERBOSE, " not connected.\n");
++			first_notcon = 1;
++		}
++
+ 		entry.trigger = irq_trigger(idx);
+ 		entry.polarity = irq_polarity(idx);
+ 
+@@ -1936,13 +1941,16 @@ __setup("no_timer_check", notimercheck);
+ static int __init timer_irq_works(void)
+ {
+ 	unsigned long t1 = jiffies;
++	unsigned long flags;
+ 
+ 	if (no_timer_check)
+ 		return 1;
+ 
++	local_save_flags(flags);
+ 	local_irq_enable();
+ 	/* Let ten ticks pass... */
+ 	mdelay((10 * 1000) / HZ);
++	local_irq_restore(flags);
+ 
+ 	/*
+ 	 * Expect a few ticks at least, to be sure some possible
+@@ -2223,6 +2231,9 @@ static inline void __init check_timer(vo
+ {
+ 	int apic1, pin1, apic2, pin2;
+ 	int vector;
++	unsigned long flags;
++
++	local_irq_save(flags);
+ 
+ 	/*
+ 	 * get/set the timer IRQ vector:
+@@ -2268,7 +2279,7 @@ static inline void __init check_timer(vo
+ 			}
+ 			if (disable_timer_pin_1 > 0)
+ 				clear_IO_APIC_pin(0, pin1);
+-			return;
++			goto out;
+ 		}
+ 		clear_IO_APIC_pin(apic1, pin1);
+ 		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
+@@ -2291,7 +2302,7 @@ static inline void __init check_timer(vo
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+ 				setup_nmi();
+ 			}
+-			return;
++			goto out;
+ 		}
+ 		/*
+ 		 * Cleanup, just in case ...
+@@ -2315,7 +2326,7 @@ static inline void __init check_timer(vo
+ 
+ 	if (timer_irq_works()) {
+ 		printk(" works.\n");
+-		return;
++		goto out;
+ 	}
+ 	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+ 	printk(" failed.\n");
+@@ -2331,11 +2342,13 @@ static inline void __init check_timer(vo
+ 
+ 	if (timer_irq_works()) {
+ 		printk(" works.\n");
+-		return;
++		goto out;
+ 	}
+ 	printk(" failed :(.\n");
+ 	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+ 		"report.  Then try booting with the 'noapic' option");
++out:
++	local_irq_restore(flags);
+ }
+ #else
+ int timer_uses_ioapic_pin_0 = 0;
+@@ -2353,6 +2366,14 @@ int timer_uses_ioapic_pin_0 = 0;
+ 
+ void __init setup_IO_APIC(void)
+ {
++#ifndef CONFIG_XEN
++	int i;
++
++	/* Reserve all the system vectors. */
++	for (i = FIRST_SYSTEM_VECTOR; i < NR_VECTORS; i++)
++		set_bit(i, used_vectors);
++#endif
++
+ 	enable_IO_APIC();
+ 
+ 	if (acpi_ioapic)
+@@ -2542,7 +2563,7 @@ void destroy_irq(unsigned int irq)
+ #endif /* CONFIG_XEN */
+ 
+ /*
+- * MSI mesage composition
++ * MSI message composition
+  */
+ #if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+@@ -2899,6 +2920,25 @@ int io_apic_set_pci_routing (int ioapic,
+ 	return 0;
+ }
+ 
++int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
++{
++	int i;
++
++	if (skip_ioapic_setup)
++		return -1;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mpc_irqtype == mp_INT &&
++		    mp_irqs[i].mpc_srcbusirq == bus_irq)
++			break;
++	if (i >= mp_irq_entries)
++		return -1;
++
++	*trigger = irq_trigger(i);
++	*polarity = irq_polarity(i);
++	return 0;
++}
++
+ #endif /* CONFIG_ACPI */
+ 
+ static int __init parse_disable_timer_pin_1(char *arg)
+--- head-2010-01-18.orig/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/io_apic_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -31,6 +31,7 @@
+ #include <linux/sysdev.h>
+ #include <linux/msi.h>
+ #include <linux/htirq.h>
++#include <linux/dmar.h>
+ #ifdef CONFIG_ACPI
+ #include <acpi/acpi_bus.h>
+ #endif
+@@ -584,7 +585,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
+ #define default_PCI_trigger(idx)	(1)
+ #define default_PCI_polarity(idx)	(1)
+ 
+-static int __init MPBIOS_polarity(int idx)
++static int MPBIOS_polarity(int idx)
+ {
+ 	int bus = mp_irqs[idx].mpc_srcbus;
+ 	int polarity;
+@@ -871,6 +872,10 @@ static void __init setup_IO_APIC_irqs(vo
+ 				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+ 			continue;
+ 		}
++		if (!first_notcon) {
++			apic_printk(APIC_VERBOSE, " not connected.\n");
++			first_notcon = 1;
++		}
+ 
+ 		irq = pin_2_irq(idx, apic, pin);
+ 		add_pin_to_irq(irq, apic, pin);
+@@ -881,7 +886,7 @@ static void __init setup_IO_APIC_irqs(vo
+ 	}
+ 
+ 	if (!first_notcon)
+-		apic_printk(APIC_VERBOSE," not connected.\n");
++		apic_printk(APIC_VERBOSE, " not connected.\n");
+ }
+ 
+ #ifndef CONFIG_XEN
+@@ -1277,10 +1282,13 @@ void disable_IO_APIC(void)
+ static int __init timer_irq_works(void)
+ {
+ 	unsigned long t1 = jiffies;
++	unsigned long flags;
+ 
++	local_save_flags(flags);
+ 	local_irq_enable();
+ 	/* Let ten ticks pass... */
+ 	mdelay((10 * 1000) / HZ);
++	local_irq_restore(flags);
+ 
+ 	/*
+ 	 * Expect a few ticks at least, to be sure some possible
+@@ -1655,6 +1663,9 @@ static inline void check_timer(void)
+ {
+ 	struct irq_cfg *cfg = irq_cfg + 0;
+ 	int apic1, pin1, apic2, pin2;
++	unsigned long flags;
++
++	local_irq_save(flags);
+ 
+ 	/*
+ 	 * get/set the timer IRQ vector:
+@@ -1696,7 +1707,7 @@ static inline void check_timer(void)
+ 			}
+ 			if (disable_timer_pin_1 > 0)
+ 				clear_IO_APIC_pin(0, pin1);
+-			return;
++			goto out;
+ 		}
+ 		clear_IO_APIC_pin(apic1, pin1);
+ 		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
+@@ -1718,7 +1729,7 @@ static inline void check_timer(void)
+ 			if (nmi_watchdog == NMI_IO_APIC) {
+ 				setup_nmi();
+ 			}
+-			return;
++			goto out;
+ 		}
+ 		/*
+ 		 * Cleanup, just in case ...
+@@ -1741,7 +1752,7 @@ static inline void check_timer(void)
+ 
+ 	if (timer_irq_works()) {
+ 		apic_printk(APIC_VERBOSE," works.\n");
+-		return;
++		goto out;
+ 	}
+ 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+ 	apic_printk(APIC_VERBOSE," failed.\n");
+@@ -1756,10 +1767,12 @@ static inline void check_timer(void)
+ 
+ 	if (timer_irq_works()) {
+ 		apic_printk(APIC_VERBOSE," works.\n");
+-		return;
++		goto out;
+ 	}
+ 	apic_printk(APIC_VERBOSE," failed :(.\n");
+ 	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
++out:
++	local_irq_restore(flags);
+ }
+ #else
+ #define check_timer() ((void)0)
+@@ -1775,7 +1788,7 @@ __setup("no_timer_check", notimercheck);
+ 
+ /*
+  *
+- * IRQ's that are handled by the PIC in the MPS IOAPIC case.
++ * IRQs that are handled by the PIC in the MPS IOAPIC case.
+  * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
+  *   Linux doesn't really care, as it's not actually used
+  *   for any interrupt handling anyway.
+@@ -1858,7 +1871,7 @@ static struct sysdev_class ioapic_sysdev
+ static int __init ioapic_init_sysfs(void)
+ {
+ 	struct sys_device * dev;
+-	int i, size, error = 0;
++	int i, size, error;
+ 
+ 	error = sysdev_class_register(&ioapic_sysdev_class);
+ 	if (error)
+@@ -1867,12 +1880,11 @@ static int __init ioapic_init_sysfs(void
+ 	for (i = 0; i < nr_ioapics; i++ ) {
+ 		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+ 			* sizeof(struct IO_APIC_route_entry);
+-		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
++		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+ 		if (!mp_ioapic_data[i]) {
+ 			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+ 			continue;
+ 		}
+-		memset(mp_ioapic_data[i], 0, size);
+ 		dev = &mp_ioapic_data[i]->dev;
+ 		dev->id = i;
+ 		dev->cls = &ioapic_sysdev_class;
+@@ -1933,7 +1945,7 @@ void destroy_irq(unsigned int irq)
+ #endif /* CONFIG_XEN */
+ 
+ /*
+- * MSI mesage composition
++ * MSI message composition
+  */
+ #if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+@@ -2043,8 +2055,64 @@ void arch_teardown_msi_irq(unsigned int 
+ 	destroy_irq(irq);
+ }
+ 
+-#endif /* CONFIG_PCI_MSI */
++#ifdef CONFIG_DMAR
++#ifdef CONFIG_SMP
++static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
++{
++	struct irq_cfg *cfg = irq_cfg + irq;
++	struct msi_msg msg;
++	unsigned int dest;
++	cpumask_t tmp;
++
++	cpus_and(tmp, mask, cpu_online_map);
++	if (cpus_empty(tmp))
++		return;
++
++	if (assign_irq_vector(irq, mask))
++		return;
++
++	cpus_and(tmp, cfg->domain, mask);
++	dest = cpu_mask_to_apicid(tmp);
++
++	dmar_msi_read(irq, &msg);
++
++	msg.data &= ~MSI_DATA_VECTOR_MASK;
++	msg.data |= MSI_DATA_VECTOR(cfg->vector);
++	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
++	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
++
++	dmar_msi_write(irq, &msg);
++	irq_desc[irq].affinity = mask;
++}
++#endif /* CONFIG_SMP */
++
++struct irq_chip dmar_msi_type = {
++	.name = "DMAR_MSI",
++	.unmask = dmar_msi_unmask,
++	.mask = dmar_msi_mask,
++	.ack = ack_apic_edge,
++#ifdef CONFIG_SMP
++	.set_affinity = dmar_msi_set_affinity,
++#endif
++	.retrigger = ioapic_retrigger_irq,
++};
++
++int arch_setup_dmar_msi(unsigned int irq)
++{
++	int ret;
++	struct msi_msg msg;
++
++	ret = msi_compose_msg(NULL, irq, &msg);
++	if (ret < 0)
++		return ret;
++	dmar_msi_write(irq, &msg);
++	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
++		"edge");
++	return 0;
++}
++#endif
+ 
++#endif /* CONFIG_PCI_MSI */
+ /*
+  * Hypertransport interrupt support
+  */
+@@ -2177,8 +2245,27 @@ int io_apic_set_pci_routing (int ioapic,
+ 	return 0;
+ }
+ 
+-#endif /* CONFIG_ACPI */
+ 
++int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
++{
++	int i;
++
++	if (skip_ioapic_setup)
++		return -1;
++
++	for (i = 0; i < mp_irq_entries; i++)
++		if (mp_irqs[i].mpc_irqtype == mp_INT &&
++		    mp_irqs[i].mpc_srcbusirq == bus_irq)
++			break;
++	if (i >= mp_irq_entries)
++		return -1;
++
++	*trigger = irq_trigger(i);
++	*polarity = irq_polarity(i);
++	return 0;
++}
++
++#endif /* CONFIG_ACPI */
+ 
+ #ifndef CONFIG_XEN
+ /*
+@@ -2217,3 +2304,4 @@ void __init setup_ioapic_dest(void)
+ }
+ #endif
+ #endif /* !CONFIG_XEN */
++
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *	linux/arch/i386/kernel/ioport.c
+- *
+  * This contains the io-permission bitmap code - written by obz, with changes
+  * by Linus.
+  */
+--- head-2010-01-18.orig/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ioport_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *	linux/arch/x86_64/kernel/ioport.c
+- *
+  * This contains the io-permission bitmap code - written by obz, with changes
+  * by Linus.
+  */
+--- head-2010-01-18.orig/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *	linux/arch/i386/kernel/irq.c
+- *
+  *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+  *
+  * This file contains the lowest level x86-specific interrupt
+@@ -231,8 +229,6 @@ asmlinkage void do_softirq(void)
+ 
+ 	local_irq_restore(flags);
+ }
+-
+-EXPORT_SYMBOL(do_softirq);
+ #endif
+ 
+ /*
+@@ -259,9 +255,17 @@ int show_interrupts(struct seq_file *p, 
+ 	}
+ 
+ 	if (i < NR_IRQS) {
++		unsigned any_count = 0;
++
+ 		spin_lock_irqsave(&irq_desc[i].lock, flags);
++#ifndef CONFIG_SMP
++		any_count = kstat_irqs(i);
++#else
++		for_each_online_cpu(j)
++			any_count |= kstat_cpu(j).irqs[i];
++#endif
+ 		action = irq_desc[i].action;
+-		if (!action)
++		if (!action && !any_count)
+ 			goto skip;
+ 		seq_printf(p, "%3d: ",i);
+ #ifndef CONFIG_SMP
+@@ -272,10 +276,12 @@ int show_interrupts(struct seq_file *p, 
+ #endif
+ 		seq_printf(p, " %8s", irq_desc[i].chip->name);
+ 		seq_printf(p, "-%-8s", irq_desc[i].name);
+-		seq_printf(p, "  %s", action->name);
+ 
+-		for (action=action->next; action; action = action->next)
+-			seq_printf(p, ", %s", action->name);
++		if (action) {
++			seq_printf(p, "  %s", action->name);
++			while ((action = action->next) != NULL)
++				seq_printf(p, ", %s", action->name);
++		}
+ 
+ 		seq_putc(p, '\n');
+ skip:
+@@ -284,13 +290,46 @@ skip:
+ 		seq_printf(p, "NMI: ");
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ", nmi_count(j));
+-		seq_putc(p, '\n');
++		seq_printf(p, "  Non-maskable interrupts\n");
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 		seq_printf(p, "LOC: ");
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ",
+ 				per_cpu(irq_stat,j).apic_timer_irqs);
+-		seq_putc(p, '\n');
++		seq_printf(p, "  Local timer interrupts\n");
++#endif
++#ifdef CONFIG_SMP
++		seq_printf(p, "RES: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).irq_resched_count);
++		seq_printf(p, "  Rescheduling interrupts\n");
++		seq_printf(p, "CAL: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).irq_call_count);
++		seq_printf(p, "  function call interrupts\n");
++#ifndef CONFIG_XEN
++		seq_printf(p, "TLB: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).irq_tlb_count);
++		seq_printf(p, "  TLB shootdowns\n");
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++		seq_printf(p, "TRM: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).irq_thermal_count);
++		seq_printf(p, "  Thermal event interrupts\n");
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++		seq_printf(p, "SPU: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ",
++				per_cpu(irq_stat,j).irq_spurious_count);
++		seq_printf(p, "  Spurious interrupts\n");
+ #endif
+ 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ #if defined(CONFIG_X86_IO_APIC)
+--- head-2010-01-18.orig/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/irq_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *	linux/arch/x86_64/kernel/irq.c
+- *
+  *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+  *
+  * This file contains the lowest level x86_64-specific interrupt
+@@ -64,9 +62,17 @@ int show_interrupts(struct seq_file *p, 
+ 	}
+ 
+ 	if (i < NR_IRQS) {
++		unsigned any_count = 0;
++
+ 		spin_lock_irqsave(&irq_desc[i].lock, flags);
++#ifndef CONFIG_SMP
++		any_count = kstat_irqs(i);
++#else
++		for_each_online_cpu(j)
++			any_count |= kstat_cpu(j).irqs[i];
++#endif
+ 		action = irq_desc[i].action;
+-		if (!action) 
++		if (!action && !any_count)
+ 			goto skip;
+ 		seq_printf(p, "%3d: ",i);
+ #ifndef CONFIG_SMP
+@@ -78,9 +84,11 @@ int show_interrupts(struct seq_file *p, 
+ 		seq_printf(p, " %8s", irq_desc[i].chip->name);
+ 		seq_printf(p, "-%-8s", irq_desc[i].name);
+ 
+-		seq_printf(p, "  %s", action->name);
+-		for (action=action->next; action; action = action->next)
+-			seq_printf(p, ", %s", action->name);
++		if (action) {
++			seq_printf(p, "  %s", action->name);
++			while ((action = action->next) != NULL)
++				seq_printf(p, ", %s", action->name);
++		}
+ 		seq_putc(p, '\n');
+ skip:
+ 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+@@ -88,12 +96,44 @@ skip:
+ 		seq_printf(p, "NMI: ");
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
+-		seq_putc(p, '\n');
++		seq_printf(p, "  Non-maskable interrupts\n");
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 		seq_printf(p, "LOC: ");
+ 		for_each_online_cpu(j)
+ 			seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
+-		seq_putc(p, '\n');
++		seq_printf(p, "  Local timer interrupts\n");
++#endif
++#ifdef CONFIG_SMP
++		seq_printf(p, "RES: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_resched_count);
++		seq_printf(p, "  Rescheduling interrupts\n");
++		seq_printf(p, "CAL: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
++		seq_printf(p, "  function call interrupts\n");
++#ifndef CONFIG_XEN
++		seq_printf(p, "TLB: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
++		seq_printf(p, "  TLB shootdowns\n");
++#endif
++#endif
++#ifdef CONFIG_X86_MCE
++		seq_printf(p, "TRM: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
++		seq_printf(p, "  Thermal event interrupts\n");
++		seq_printf(p, "THR: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
++		seq_printf(p, "  Threshold APIC interrupts\n");
++#endif
++#ifdef CONFIG_X86_LOCAL_APIC
++		seq_printf(p, "SPU: ");
++		for_each_online_cpu(j)
++			seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
++		seq_printf(p, "  Spurious interrupts\n");
+ #endif
+ 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ 	}
+@@ -211,7 +251,6 @@ asmlinkage void do_softirq(void)
+ 	}
+  	local_irq_restore(flags);
+ }
+-EXPORT_SYMBOL(do_softirq);
+ 
+ #ifndef CONFIG_X86_LOCAL_APIC
+ /*
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- * linux/arch/i386/kernel/ldt.c
+- *
+  * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+  */
+@@ -106,14 +104,14 @@ int init_new_context(struct task_struct 
+ 	struct mm_struct * old_mm;
+ 	int retval = 0;
+ 
+-	init_MUTEX(&mm->context.sem);
++	mutex_init(&mm->context.lock);
+ 	mm->context.size = 0;
+ 	mm->context.has_foreign_mappings = 0;
+ 	old_mm = current->mm;
+ 	if (old_mm && old_mm->context.size > 0) {
+-		down(&old_mm->context.sem);
++		mutex_lock(&old_mm->context.lock);
+ 		retval = copy_ldt(&mm->context, &old_mm->context);
+-		up(&old_mm->context.sem);
++		mutex_unlock(&old_mm->context.lock);
+ 	}
+ 	return retval;
+ }
+@@ -149,7 +147,7 @@ static int read_ldt(void __user * ptr, u
+ 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+ 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+ 
+-	down(&mm->context.sem);
++	mutex_lock(&mm->context.lock);
+ 	size = mm->context.size*LDT_ENTRY_SIZE;
+ 	if (size > bytecount)
+ 		size = bytecount;
+@@ -157,7 +155,7 @@ static int read_ldt(void __user * ptr, u
+ 	err = 0;
+ 	if (copy_to_user(ptr, mm->context.ldt, size))
+ 		err = -EFAULT;
+-	up(&mm->context.sem);
++	mutex_unlock(&mm->context.lock);
+ 	if (err < 0)
+ 		goto error_return;
+ 	if (size != bytecount) {
+@@ -213,7 +211,7 @@ static int write_ldt(void __user * ptr, 
+ 			goto out;
+ 	}
+ 
+-	down(&mm->context.sem);
++	mutex_lock(&mm->context.lock);
+ 	if (ldt_info.entry_number >= mm->context.size) {
+ 		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
+ 		if (error < 0)
+@@ -240,7 +238,7 @@ install:
+ 				entry_1, entry_2);
+ 
+ out_unlock:
+-	up(&mm->context.sem);
++	mutex_unlock(&mm->context.lock);
+ out:
+ 	return error;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/ldt_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- * linux/arch/x86_64/kernel/ldt.c
+- *
+  * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+  * Copyright (C) 2002 Andi Kleen
+@@ -112,19 +110,14 @@ int init_new_context(struct task_struct 
+ 	int retval = 0;
+ 
+ 	memset(&mm->context, 0, sizeof(mm->context));
+-	init_MUTEX(&mm->context.sem);
++	mutex_init(&mm->context.lock);
+ 	old_mm = current->mm;
+ 	if (old_mm)
+ 		mm->context.vdso = old_mm->context.vdso;
+ 	if (old_mm && old_mm->context.size > 0) {
+-		down(&old_mm->context.sem);
++		mutex_lock(&old_mm->context.lock);
+ 		retval = copy_ldt(&mm->context, &old_mm->context);
+-		up(&old_mm->context.sem);
+-	}
+-	if (retval == 0) {
+-		spin_lock(&mm_unpinned_lock);
+-		list_add(&mm->context.unpinned, &mm_unpinned);
+-		spin_unlock(&mm_unpinned_lock);
++		mutex_unlock(&old_mm->context.lock);
+ 	}
+ 	return retval;
+ }
+@@ -148,11 +141,6 @@ void destroy_context(struct mm_struct *m
+ 			kfree(mm->context.ldt);
+ 		mm->context.size = 0;
+ 	}
+-	if (!PagePinned(virt_to_page(mm->pgd))) {
+-		spin_lock(&mm_unpinned_lock);
+-		list_del(&mm->context.unpinned);
+-		spin_unlock(&mm_unpinned_lock);
+-	}
+ }
+ 
+ static int read_ldt(void __user * ptr, unsigned long bytecount)
+@@ -166,7 +154,7 @@ static int read_ldt(void __user * ptr, u
+ 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+ 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+ 
+-	down(&mm->context.sem);
++	mutex_lock(&mm->context.lock);
+ 	size = mm->context.size*LDT_ENTRY_SIZE;
+ 	if (size > bytecount)
+ 		size = bytecount;
+@@ -174,7 +162,7 @@ static int read_ldt(void __user * ptr, u
+ 	err = 0;
+ 	if (copy_to_user(ptr, mm->context.ldt, size))
+ 		err = -EFAULT;
+-	up(&mm->context.sem);
++	mutex_unlock(&mm->context.lock);
+ 	if (err < 0)
+ 		goto error_return;
+ 	if (size != bytecount) {
+@@ -227,7 +215,7 @@ static int write_ldt(void __user * ptr, 
+ 			goto out;
+ 	}
+ 
+-	down(&mm->context.sem);
++	mutex_lock(&mm->context.lock);
+ 	if (ldt_info.entry_number >= (unsigned)mm->context.size) {
+ 		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
+ 		if (error < 0)
+@@ -256,7 +244,7 @@ install:
+ 	error = HYPERVISOR_update_descriptor(mach_lp, (unsigned long)((entry_1 | (unsigned long) entry_2 << 32)));
+ 
+ out_unlock:
+-	up(&mm->context.sem);
++	mutex_unlock(&mm->context.lock);
+ out:
+ 	return error;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1023,7 +1023,7 @@ void __init mp_config_acpi_legacy_irqs (
+ 
+ 	/* 
+ 	 * Use the default configuration for the IRQs 0-15.  Unless
+-	 * overriden by (MADT) interrupt source override entries.
++	 * overridden by (MADT) interrupt source override entries.
+ 	 */
+ 	for (i = 0; i < 16; i++) {
+ 		int idx;
+--- head-2010-01-18.orig/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/mpparse_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -57,6 +57,8 @@ unsigned long mp_lapic_addr = 0;
+ 
+ /* Processor that is doing the boot up */
+ unsigned int boot_cpu_id = -1U;
++EXPORT_SYMBOL(boot_cpu_id);
++
+ /* Internal processor count */
+ unsigned int num_processors __cpuinitdata = 0;
+ 
+@@ -87,7 +89,7 @@ static int __init mpf_checksum(unsigned 
+ }
+ 
+ #ifndef CONFIG_XEN
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
++static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+ {
+ 	int cpu;
+ 	cpumask_t tmp_map;
+@@ -124,13 +126,24 @@ static void __cpuinit MP_processor_info 
+ 		cpu = 0;
+  	}
+ 	bios_cpu_apicid[cpu] = m->mpc_apicid;
+-	x86_cpu_to_apicid[cpu] = m->mpc_apicid;
++	/*
++	 * We get called early in the the start_kernel initialization
++	 * process when the per_cpu data area is not yet setup, so we
++	 * use a static array that is removed after the per_cpu data
++	 * area is created.
++	 */
++	if (x86_cpu_to_apicid_ptr) {
++		u8 *x86_cpu_to_apicid = (u8 *)x86_cpu_to_apicid_ptr;
++		x86_cpu_to_apicid[cpu] = m->mpc_apicid;
++	} else {
++		per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
++	}
+ 
+ 	cpu_set(cpu, cpu_possible_map);
+ 	cpu_set(cpu, cpu_present_map);
+ }
+ #else
+-static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
++static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
+ {
+ 	num_processors++;
+ }
+--- head-2010-01-18.orig/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/pci-dma-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -13,14 +13,13 @@
+ #include <linux/pci.h>
+ #include <linux/module.h>
+ #include <linux/version.h>
+-#include <linux/pci.h>
+ #include <asm/io.h>
+ #include <xen/balloon.h>
+ #include <xen/gnttab.h>
+ #include <asm/swiotlb.h>
+ #include <asm/tlbflush.h>
+-#include <asm-i386/mach-xen/asm/swiotlb.h>
+-#include <asm-i386/mach-xen/asm/gnttab_dma.h>
++#include <asm/swiotlb_32.h>
++#include <asm/gnttab_dma.h>
+ #include <asm/bug.h>
+ 
+ #ifdef __x86_64__
+@@ -106,27 +105,29 @@ int range_straddles_page_boundary(paddr_
+ }
+ 
+ int
+-dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++dma_map_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+ 	   enum dma_data_direction direction)
+ {
+ 	int i, rc;
+ 
+ 	BUG_ON(!valid_dma_direction(direction));
+-	WARN_ON(nents == 0 || sg[0].length == 0);
++	WARN_ON(nents == 0 || sgl->length == 0);
+ 
+ 	if (swiotlb) {
+-		rc = swiotlb_map_sg(hwdev, sg, nents, direction);
++		rc = swiotlb_map_sg(hwdev, sgl, nents, direction);
+ 	} else {
+-		for (i = 0; i < nents; i++ ) {
+-			BUG_ON(!sg[i].page);
+-			sg[i].dma_address =
+-				gnttab_dma_map_page(sg[i].page) + sg[i].offset;
+-			sg[i].dma_length  = sg[i].length;
++		struct scatterlist *sg;
++
++		for_each_sg(sgl, sg, nents, i) {
++			BUG_ON(!sg_page(sg));
++			sg->dma_address =
++				gnttab_dma_map_page(sg_page(sg)) + sg->offset;
++			sg->dma_length  = sg->length;
+ 			IOMMU_BUG_ON(address_needs_mapping(
+-				hwdev, sg[i].dma_address));
++				hwdev, sg->dma_address));
+ 			IOMMU_BUG_ON(range_straddles_page_boundary(
+-				page_to_pseudophys(sg[i].page) + sg[i].offset,
+-				sg[i].length));
++				page_to_pseudophys(sg_page(sg)) + sg->offset,
++				sg->length));
+ 		}
+ 		rc = nents;
+ 	}
+@@ -137,17 +138,19 @@ dma_map_sg(struct device *hwdev, struct 
+ EXPORT_SYMBOL(dma_map_sg);
+ 
+ void
+-dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
++dma_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+ 	     enum dma_data_direction direction)
+ {
+ 	int i;
+ 
+ 	BUG_ON(!valid_dma_direction(direction));
+ 	if (swiotlb)
+-		swiotlb_unmap_sg(hwdev, sg, nents, direction);
++		swiotlb_unmap_sg(hwdev, sgl, nents, direction);
+ 	else {
+-		for (i = 0; i < nents; i++ )
+-			gnttab_dma_unmap_page(sg[i].dma_address);
++		struct scatterlist *sg;
++
++		for_each_sg(sgl, sg, nents, i)
++			gnttab_dma_unmap_page(sg->dma_address);
+ 	}
+ }
+ EXPORT_SYMBOL(dma_unmap_sg);
+@@ -258,7 +261,8 @@ void dma_free_coherent(struct device *de
+ {
+ 	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+ 	int order = get_order(size);
+-	
++
++	WARN_ON(irqs_disabled());	/* for portability */
+ 	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+ 		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/i386/kernel/process.c
+- *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+  *  Pentium III FXSR, SSE support
+@@ -190,6 +188,10 @@ void cpu_idle(void)
+ 	}
+ }
+ 
++static void do_nothing(void *unused)
++{
++}
++
+ void cpu_idle_wait(void)
+ {
+ 	unsigned int cpu, this_cpu = get_cpu();
+@@ -214,13 +216,20 @@ void cpu_idle_wait(void)
+ 				cpu_clear(cpu, map);
+ 		}
+ 		cpus_and(map, map, cpu_online_map);
++		/*
++		 * We waited 1 sec, if a CPU still did not call idle
++		 * it may be because it is in idle and not waking up
++		 * because it has nothing to do.
++		 * Give all the remaining CPUS a kick.
++		 */
++		smp_call_function_mask(map, do_nothing, 0, 0);
+ 	} while (!cpus_empty(map));
+ 
+ 	set_cpus_allowed(current, tmp);
+ }
+ EXPORT_SYMBOL_GPL(cpu_idle_wait);
+ 
+-void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
++void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+ {
+ }
+ 
+@@ -238,34 +247,52 @@ static int __init idle_setup(char *str)
+ }
+ early_param("idle", idle_setup);
+ 
+-void show_regs(struct pt_regs * regs)
++void __show_registers(struct pt_regs *regs, int all)
+ {
+ 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+ 	unsigned long d0, d1, d2, d3, d6, d7;
++	unsigned long esp;
++	unsigned short ss, gs;
++
++	if (user_mode_vm(regs)) {
++		esp = regs->esp;
++		ss = regs->xss & 0xffff;
++		savesegment(gs, gs);
++	} else {
++		esp = (unsigned long) (&regs->esp);
++		savesegment(ss, ss);
++		savesegment(gs, gs);
++	}
+ 
+ 	printk("\n");
+-	printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+-	printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
++	printk("Pid: %d, comm: %s %s (%s %.*s)\n",
++			task_pid_nr(current), current->comm,
++			print_tainted(), init_utsname()->release,
++			(int)strcspn(init_utsname()->version, " "),
++			init_utsname()->version);
++
++	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
++			0xffff & regs->xcs, regs->eip, regs->eflags,
++			smp_processor_id());
+ 	print_symbol("EIP is at %s\n", regs->eip);
+ 
+-	if (user_mode_vm(regs))
+-		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
+-	printk(" EFLAGS: %08lx    %s  (%s %.*s)\n",
+-	       regs->eflags, print_tainted(), init_utsname()->release,
+-	       (int)strcspn(init_utsname()->version, " "),
+-	       init_utsname()->version);
+ 	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+-		regs->eax,regs->ebx,regs->ecx,regs->edx);
+-	printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+-		regs->esi, regs->edi, regs->ebp);
+-	printk(" DS: %04x ES: %04x FS: %04x\n",
+-	       0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xfs);
++		regs->eax, regs->ebx, regs->ecx, regs->edx);
++	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
++		regs->esi, regs->edi, regs->ebp, esp);
++	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
++	       regs->xds & 0xffff, regs->xes & 0xffff,
++	       regs->xfs & 0xffff, gs, ss);
++
++	if (!all)
++		return;
+ 
+ 	cr0 = read_cr0();
+ 	cr2 = read_cr2();
+ 	cr3 = read_cr3();
+ 	cr4 = read_cr4_safe();
+-	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
++	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
++			cr0, cr2, cr3, cr4);
+ 
+ 	get_debugreg(d0, 0);
+ 	get_debugreg(d1, 1);
+@@ -273,10 +300,16 @@ void show_regs(struct pt_regs * regs)
+ 	get_debugreg(d3, 3);
+ 	printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
+ 			d0, d1, d2, d3);
++
+ 	get_debugreg(d6, 6);
+ 	get_debugreg(d7, 7);
+-	printk("DR6: %08lx DR7: %08lx\n", d6, d7);
++	printk("DR6: %08lx DR7: %08lx\n",
++			d6, d7);
++}
+ 
++void show_regs(struct pt_regs *regs)
++{
++	__show_registers(regs, 1);
+ 	show_trace(NULL, regs, &regs->esp);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/process_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/x86-64/kernel/process.c
+- *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+  *  Pentium III FXSR, SSE support
+@@ -41,6 +39,7 @@
+ #include <linux/notifier.h>
+ #include <linux/kprobes.h>
+ #include <linux/kdebug.h>
++#include <linux/tick.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -172,6 +171,9 @@ void cpu_idle (void)
+ 
+ 			if (__get_cpu_var(cpu_idle_state))
+ 				__get_cpu_var(cpu_idle_state) = 0;
++
++			tick_nohz_stop_sched_tick();
++
+ 			rmb();
+ 			idle = xen_idle; /* no alternatives */
+ 			if (cpu_is_offline(smp_processor_id()))
+@@ -190,12 +192,17 @@ void cpu_idle (void)
+ 			__exit_idle();
+ 		}
+ 
++		tick_nohz_restart_sched_tick();
+ 		preempt_enable_no_resched();
+ 		schedule();
+ 		preempt_disable();
+ 	}
+ }
+ 
++static void do_nothing(void *unused)
++{
++}
++
+ void cpu_idle_wait(void)
+ {
+ 	unsigned int cpu, this_cpu = get_cpu();
+@@ -221,6 +228,13 @@ void cpu_idle_wait(void)
+ 				cpu_clear(cpu, map);
+ 		}
+ 		cpus_and(map, map, cpu_online_map);
++		/*
++		 * We waited 1 sec, if a CPU still did not call idle
++		 * it may be because it is in idle and not waking up
++		 * because it has nothing to do.
++		 * Give all the remaining CPUS a kick.
++		 */
++		smp_call_function_mask(map, do_nothing, 0, 0);
+ 	} while (!cpus_empty(map));
+ 
+ 	set_cpus_allowed(current, tmp);
+@@ -528,7 +542,7 @@ static inline void __switch_to_xtra(stru
+  *
+  * Kprobes not supported here. Set the probe on schedule instead.
+  */
+-__kprobes struct task_struct *
++struct task_struct *
+ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ 	struct thread_struct *prev = &prev_p->thread,
+--- head-2010-01-18.orig/arch/x86/kernel/quirks-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/quirks-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -41,7 +41,353 @@ static void __devinit quirk_intel_irqbal
+ 	if (!(config & 0x2))
+ 		pci_write_config_byte(dev, 0xf4, config);
+ }
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
+-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);
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH,
++			quirk_intel_irqbalance);
++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
++
++#if defined(CONFIG_HPET_TIMER)
++#include <asm/hpet.h>
++
++unsigned long force_hpet_address;
++
++static enum {
++	NONE_FORCE_HPET_RESUME,
++	OLD_ICH_FORCE_HPET_RESUME,
++	ICH_FORCE_HPET_RESUME,
++	VT8237_FORCE_HPET_RESUME,
++	NVIDIA_FORCE_HPET_RESUME,
++} force_hpet_resume_type;
++
++static void __iomem *rcba_base;
++
++static void ich_force_hpet_resume(void)
++{
++	u32 val;
++
++	if (!force_hpet_address)
++		return;
++
++	if (rcba_base == NULL)
++		BUG();
++
++	/* read the Function Disable register, dword mode only */
++	val = readl(rcba_base + 0x3404);
++	if (!(val & 0x80)) {
++		/* HPET disabled in HPTC. Trying to enable */
++		writel(val | 0x80, rcba_base + 0x3404);
++	}
++
++	val = readl(rcba_base + 0x3404);
++	if (!(val & 0x80))
++		BUG();
++	else
++		printk(KERN_DEBUG "Force enabled HPET at resume\n");
++
++	return;
++}
++
++static void ich_force_enable_hpet(struct pci_dev *dev)
++{
++	u32 val;
++	u32 uninitialized_var(rcba);
++	int err = 0;
++
++	if (hpet_address || force_hpet_address)
++		return;
++
++	pci_read_config_dword(dev, 0xF0, &rcba);
++	rcba &= 0xFFFFC000;
++	if (rcba == 0) {
++		printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
++		return;
++	}
++
++	/* use bits 31:14, 16 kB aligned */
++	rcba_base = ioremap_nocache(rcba, 0x4000);
++	if (rcba_base == NULL) {
++		printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
++		return;
++	}
++
++	/* read the Function Disable register, dword mode only */
++	val = readl(rcba_base + 0x3404);
++
++	if (val & 0x80) {
++		/* HPET is enabled in HPTC. Just not reported by BIOS */
++		val = val & 0x3;
++		force_hpet_address = 0xFED00000 | (val << 12);
++		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++			       force_hpet_address);
++		iounmap(rcba_base);
++		return;
++	}
++
++	/* HPET disabled in HPTC. Trying to enable */
++	writel(val | 0x80, rcba_base + 0x3404);
++
++	val = readl(rcba_base + 0x3404);
++	if (!(val & 0x80)) {
++		err = 1;
++	} else {
++		val = val & 0x3;
++		force_hpet_address = 0xFED00000 | (val << 12);
++	}
++
++	if (err) {
++		force_hpet_address = 0;
++		iounmap(rcba_base);
++		printk(KERN_DEBUG "Failed to force enable HPET\n");
++	} else {
++		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
++		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++			       force_hpet_address);
++	}
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
++			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
++			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,
++			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,
++			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,
++			 ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
++			 ich_force_enable_hpet);
++
++
++static struct pci_dev *cached_dev;
++
++static void old_ich_force_hpet_resume(void)
++{
++	u32 val;
++	u32 uninitialized_var(gen_cntl);
++
++	if (!force_hpet_address || !cached_dev)
++		return;
++
++	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
++	gen_cntl &= (~(0x7 << 15));
++	gen_cntl |= (0x4 << 15);
++
++	pci_write_config_dword(cached_dev, 0xD0, gen_cntl);
++	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
++	val = gen_cntl >> 15;
++	val &= 0x7;
++	if (val == 0x4)
++		printk(KERN_DEBUG "Force enabled HPET at resume\n");
++	else
++		BUG();
++}
++
++static void old_ich_force_enable_hpet(struct pci_dev *dev)
++{
++	u32 val;
++	u32 uninitialized_var(gen_cntl);
++
++	if (hpet_address || force_hpet_address)
++		return;
++
++	pci_read_config_dword(dev, 0xD0, &gen_cntl);
++	/*
++	 * Bit 17 is HPET enable bit.
++	 * Bit 16:15 control the HPET base address.
++	 */
++	val = gen_cntl >> 15;
++	val &= 0x7;
++	if (val & 0x4) {
++		val &= 0x3;
++		force_hpet_address = 0xFED00000 | (val << 12);
++		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
++			       force_hpet_address);
++		return;
++	}
++
++	/*
++	 * HPET is disabled. Trying enabling at FED00000 and check
++	 * whether it sticks
++	 */
++	gen_cntl &= (~(0x7 << 15));
++	gen_cntl |= (0x4 << 15);
++	pci_write_config_dword(dev, 0xD0, gen_cntl);
++
++	pci_read_config_dword(dev, 0xD0, &gen_cntl);
++
++	val = gen_cntl >> 15;
++	val &= 0x7;
++	if (val & 0x4) {
++		/* HPET is enabled in HPTC. Just not reported by BIOS */
++		val &= 0x3;
++		force_hpet_address = 0xFED00000 | (val << 12);
++		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++			       force_hpet_address);
++		cached_dev = dev;
++		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
++		return;
++	}
++
++	printk(KERN_DEBUG "Failed to force enable HPET\n");
++}
++
++/*
++ * Undocumented chipset features. Make sure that the user enforced
++ * this.
++ */
++static void old_ich_force_enable_hpet_user(struct pci_dev *dev)
++{
++	if (hpet_force_user)
++		old_ich_force_enable_hpet(dev);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
++			 old_ich_force_enable_hpet_user);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
++			 old_ich_force_enable_hpet_user);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
++			 old_ich_force_enable_hpet_user);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
++			 old_ich_force_enable_hpet_user);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
++			 old_ich_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12,
++			 old_ich_force_enable_hpet);
++
++
++static void vt8237_force_hpet_resume(void)
++{
++	u32 val;
++
++	if (!force_hpet_address || !cached_dev)
++		return;
++
++	val = 0xfed00000 | 0x80;
++	pci_write_config_dword(cached_dev, 0x68, val);
++
++	pci_read_config_dword(cached_dev, 0x68, &val);
++	if (val & 0x80)
++		printk(KERN_DEBUG "Force enabled HPET at resume\n");
++	else
++		BUG();
++}
++
++static void vt8237_force_enable_hpet(struct pci_dev *dev)
++{
++	u32 uninitialized_var(val);
++
++	if (!hpet_force_user || hpet_address || force_hpet_address)
++		return;
++
++	pci_read_config_dword(dev, 0x68, &val);
++	/*
++	 * Bit 7 is HPET enable bit.
++	 * Bit 31:10 is HPET base address (contrary to what datasheet claims)
++	 */
++	if (val & 0x80) {
++		force_hpet_address = (val & ~0x3ff);
++		printk(KERN_DEBUG "HPET at base address 0x%lx\n",
++			       force_hpet_address);
++		return;
++	}
++
++	/*
++	 * HPET is disabled. Trying enabling at FED00000 and check
++	 * whether it sticks
++	 */
++	val = 0xfed00000 | 0x80;
++	pci_write_config_dword(dev, 0x68, val);
++
++	pci_read_config_dword(dev, 0x68, &val);
++	if (val & 0x80) {
++		force_hpet_address = (val & ~0x3ff);
++		printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++			       force_hpet_address);
++		cached_dev = dev;
++		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
++		return;
++	}
++
++	printk(KERN_DEBUG "Failed to force enable HPET\n");
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
++			 vt8237_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
++			 vt8237_force_enable_hpet);
++
++/*
++ * Undocumented chipset feature taken from LinuxBIOS.
++ */
++static void nvidia_force_hpet_resume(void)
++{
++	pci_write_config_dword(cached_dev, 0x44, 0xfed00001);
++	printk(KERN_DEBUG "Force enabled HPET at resume\n");
++}
++
++static void nvidia_force_enable_hpet(struct pci_dev *dev)
++{
++	u32 uninitialized_var(val);
++
++	if (!hpet_force_user || hpet_address || force_hpet_address)
++		return;
++
++	pci_write_config_dword(dev, 0x44, 0xfed00001);
++	pci_read_config_dword(dev, 0x44, &val);
++	force_hpet_address = val & 0xfffffffe;
++	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
++	printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
++		force_hpet_address);
++	cached_dev = dev;
++	return;
++}
++
++/* ISA Bridges */
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0050,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0051,
++			nvidia_force_enable_hpet);
++
++/* LPC bridges */
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0360,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0361,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0362,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0363,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0364,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0365,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0366,
++			nvidia_force_enable_hpet);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0367,
++			nvidia_force_enable_hpet);
++
++void force_hpet_resume(void)
++{
++	switch (force_hpet_resume_type) {
++	    case ICH_FORCE_HPET_RESUME:
++		return ich_force_hpet_resume();
++
++	    case OLD_ICH_FORCE_HPET_RESUME:
++		return old_ich_force_hpet_resume();
++
++	    case VT8237_FORCE_HPET_RESUME:
++		return vt8237_force_hpet_resume();
++
++	    case NVIDIA_FORCE_HPET_RESUME:
++		return nvidia_force_hpet_resume();
++
++	    default:
++		break;
++	}
++}
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -15,7 +15,6 @@
+ #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>
+@@ -27,11 +26,12 @@
+ #include <asm/percpu.h>
+ #include <asm/proto.h>
+ #include <asm/sections.h>
++#include <asm/setup.h>
+ #ifdef CONFIG_XEN
+ #include <asm/hypervisor.h>
+ #endif
+ 
+-char x86_boot_params[BOOT_PARAM_SIZE] __initdata;
++struct boot_params __initdata boot_params;
+ 
+ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+ 
+@@ -159,8 +159,8 @@ static void switch_pt(void)
+ 
+ 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));
++	load_gdt(gdt_descr);
++	load_idt(idt_descr);
+ }
+ #endif
+ 
+@@ -252,6 +252,14 @@ void __cpuinit check_efer(void)
+ 
+ unsigned long kernel_eflags;
+ 
++#ifndef CONFIG_X86_NO_TSS
++/*
++ * Copies of the original ist values from the tss are only accessed during
++ * debugging, no special alignment required.
++ */
++DEFINE_PER_CPU(struct orig_ist, orig_ist);
++#endif
++
+ /*
+  * cpu_init() initializes state that is per-CPU. Some data is already
+  * initialized (naturally) in the bootstrap process, such as the GDT
+--- head-2010-01-18.orig/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/i386/kernel/setup.c
+- *
+  *  Copyright (C) 1995  Linus Torvalds
+  *
+  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+@@ -70,6 +68,7 @@
+ #include <xen/xencons.h>
+ #include <setup_arch.h>
+ #include <bios_ebda.h>
++#include <asm/cacheflush.h>
+ 
+ #ifdef CONFIG_XEN
+ #include <xen/interface/kexec.h>
+@@ -80,13 +79,14 @@ static struct notifier_block xen_panic_b
+ 	xen_panic_event, NULL, 0 /* try to go last */
+ };
+ 
+-int disable_pse __devinitdata = 0;
++int disable_pse __cpuinitdata = 0;
+ 
+ /*
+  * Machine setup..
+  */
+ extern struct resource code_resource;
+ extern struct resource data_resource;
++extern struct resource bss_resource;
+ 
+ /* cpu data as detected by the assembly code in head.S */
+ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+@@ -98,9 +98,6 @@ unsigned long mmu_cr4_features;
+ 
+ /* for MCA, but anyone else can use it if they want */
+ unsigned int machine_id;
+-#ifdef CONFIG_MCA
+-EXPORT_SYMBOL(machine_id);
+-#endif
+ unsigned int machine_submodel_id;
+ unsigned int BIOS_revision;
+ unsigned int mca_pentium_flag;
+@@ -121,7 +118,7 @@ EXPORT_SYMBOL(apm_info);
+ struct edid_info edid_info;
+ EXPORT_SYMBOL_GPL(edid_info);
+ #ifndef CONFIG_XEN
+-#define copy_edid() (edid_info = EDID_INFO)
++#define copy_edid() (edid_info = boot_params.edid_info)
+ #endif
+ struct ist_info ist_info;
+ #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
+@@ -170,10 +167,11 @@ EXPORT_SYMBOL(edd);
+  */
+ static inline void copy_edd(void)
+ {
+-     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
+-     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
+-     edd.mbr_signature_nr = EDD_MBR_SIG_NR;
+-     edd.edd_info_nr = EDD_NR;
++     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
++	    sizeof(edd.mbr_signature));
++     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
++     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
++     edd.edd_info_nr = boot_params.eddbuf_entries;
+ }
+ #endif
+ #else
+@@ -418,6 +416,53 @@ extern unsigned long __init setup_memory
+ extern void zone_sizes_init(void);
+ #endif /* !CONFIG_NEED_MULTIPLE_NODES */
+ 
++static inline unsigned long long get_total_mem(void)
++{
++	unsigned long long total;
++
++	total = max_low_pfn - min_low_pfn;
++#ifdef CONFIG_HIGHMEM
++	total += highend_pfn - highstart_pfn;
++#endif
++
++	return total << PAGE_SHIFT;
++}
++
++#ifdef CONFIG_KEXEC
++#ifndef CONFIG_XEN
++static void __init reserve_crashkernel(void)
++{
++	unsigned long long total_mem;
++	unsigned long long crash_size, crash_base;
++	int ret;
++
++	total_mem = get_total_mem();
++
++	ret = parse_crashkernel(boot_command_line, total_mem,
++			&crash_size, &crash_base);
++	if (ret == 0 && crash_size > 0) {
++		if (crash_base > 0) {
++			printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
++					"for crashkernel (System RAM: %ldMB)\n",
++					(unsigned long)(crash_size >> 20),
++					(unsigned long)(crash_base >> 20),
++					(unsigned long)(total_mem >> 20));
++			crashk_res.start = crash_base;
++			crashk_res.end   = crash_base + crash_size - 1;
++			reserve_bootmem(crash_base, crash_size);
++		} else
++			printk(KERN_INFO "crashkernel reservation failed - "
++					"you have to specify a base address\n");
++	}
++}
++#else
++#define reserve_crashkernel xen_machine_kexec_setup_resources
++#endif
++#else
++static inline void __init reserve_crashkernel(void)
++{}
++#endif
++
+ void __init setup_bootmem_allocator(void)
+ {
+ 	unsigned long bootmap_size;
+@@ -473,30 +518,25 @@ void __init setup_bootmem_allocator(void
+ 
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	if (xen_start_info->mod_start) {
+-		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
+-			/*reserve_bootmem(INITRD_START, INITRD_SIZE);*/
+-			initrd_start = INITRD_START + PAGE_OFFSET;
+-			initrd_end = initrd_start+INITRD_SIZE;
++		unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
++		unsigned long ramdisk_size  = xen_start_info->mod_len;
++		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
++		unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
++
++		if (ramdisk_end <= end_of_lowmem) {
++			/*reserve_bootmem(ramdisk_image, ramdisk_size);*/
++			initrd_start = ramdisk_image + PAGE_OFFSET;
++			initrd_end = initrd_start+ramdisk_size;
+ 			initrd_below_start_ok = 1;
+-		}
+-		else {
++		} else {
+ 			printk(KERN_ERR "initrd extends beyond end of memory "
+-			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-			    INITRD_START + INITRD_SIZE,
+-			    max_low_pfn << PAGE_SHIFT);
++			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++			       ramdisk_end, end_of_lowmem);
+ 			initrd_start = 0;
+ 		}
+ 	}
+ #endif
+-#ifdef CONFIG_KEXEC
+-#ifdef CONFIG_XEN
+-	xen_machine_kexec_setup_resources();
+-#else
+-	if (crashk_res.start != crashk_res.end)
+-		reserve_bootmem(crashk_res.start,
+-			crashk_res.end - crashk_res.start + 1);
+-#endif
+-#endif
++	reserve_crashkernel();
+ }
+ 
+ /*
+@@ -574,7 +614,8 @@ void __init setup_arch(char **cmdline_p)
+ 	 * the system table is valid.  If not, then initialize normally.
+ 	 */
+ #ifdef CONFIG_EFI
+-	if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
++	if ((boot_params.hdr.type_of_loader == 0x50) &&
++	    boot_params.efi_info.efi_systab)
+ 		efi_enabled = 1;
+ #endif
+ 
+@@ -582,18 +623,18 @@ void __init setup_arch(char **cmdline_p)
+ 	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
+ 	*/
+ 	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
+- 	screen_info = SCREEN_INFO;
++	screen_info = boot_params.screen_info;
+ 	copy_edid();
+-	apm_info.bios = APM_BIOS_INFO;
+-	ist_info = IST_INFO;
+-	saved_videomode = VIDEO_MODE;
+-	if( SYS_DESC_TABLE.length != 0 ) {
+-		set_mca_bus(SYS_DESC_TABLE.table[3] & 0x2);
+-		machine_id = SYS_DESC_TABLE.table[0];
+-		machine_submodel_id = SYS_DESC_TABLE.table[1];
+-		BIOS_revision = SYS_DESC_TABLE.table[2];
++	apm_info.bios = boot_params.apm_bios_info;
++	ist_info = boot_params.ist_info;
++	saved_videomode = boot_params.hdr.vid_mode;
++	if( boot_params.sys_desc_table.length != 0 ) {
++		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
++		machine_id = boot_params.sys_desc_table.table[0];
++		machine_submodel_id = boot_params.sys_desc_table.table[1];
++		BIOS_revision = boot_params.sys_desc_table.table[2];
+ 	}
+-	bootloader_type = LOADER_TYPE;
++	bootloader_type = boot_params.hdr.type_of_loader;
+ 
+ 	if (is_initial_xendomain()) {
+ 		const struct dom0_vga_console_info *info =
+@@ -608,9 +649,9 @@ void __init setup_arch(char **cmdline_p)
+ 		screen_info.orig_video_isVGA = 0;
+ 
+ #ifdef CONFIG_BLK_DEV_RAM
+-	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+-	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+-	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
++	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
++	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
++	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+ #endif
+ 
+ 	ARCH_SETUP
+@@ -623,7 +664,7 @@ void __init setup_arch(char **cmdline_p)
+ 
+ 	copy_edd();
+ 
+-	if (!MOUNT_ROOT_RDONLY)
++	if (!boot_params.hdr.root_flags)
+ 		root_mountflags &= ~MS_RDONLY;
+ 	init_mm.start_code = (unsigned long) _text;
+ 	init_mm.end_code = (unsigned long) _etext;
+@@ -635,6 +676,8 @@ void __init setup_arch(char **cmdline_p)
+ 	code_resource.end = virt_to_phys(_etext)-1;
+ 	data_resource.start = virt_to_phys(_etext);
+ 	data_resource.end = virt_to_phys(_edata)-1;
++	bss_resource.start = virt_to_phys(&__bss_start);
++	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+ 
+ 	if ((i = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
+ 		i = COMMAND_LINE_SIZE;
+@@ -663,7 +706,7 @@ void __init setup_arch(char **cmdline_p)
+ 	/*
+ 	 * NOTE: before this point _nobody_ is allowed to allocate
+ 	 * any memory using the bootmem allocator.  Although the
+-	 * alloctor is now initialised only the first 8Mb of the kernel
++	 * allocator is now initialised only the first 8Mb of the kernel
+ 	 * virtual address space has been mapped.  All allocations before
+ 	 * paging_init() has completed must use the alloc_bootmem_low_pages()
+ 	 * variant (which allocates DMA'able memory) and care must be taken
+@@ -786,10 +829,8 @@ void __init setup_arch(char **cmdline_p)
+ 	acpi_boot_table_init();
+ #endif
+ 
+-#ifdef CONFIG_PCI
+-#ifdef CONFIG_X86_IO_APIC
+-	check_acpi_pci();	/* Checks more than just ACPI actually */
+-#endif
++#if defined(CONFIG_PCI) && !defined(CONFIG_XEN)
++	early_quirks();
+ #endif
+ 
+ #ifdef CONFIG_ACPI
+--- head-2010-01-18.orig/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/setup_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,10 +1,5 @@
+ /*
+- *  linux/arch/x86-64/kernel/setup.c
+- *
+  *  Copyright (C) 1995  Linus Torvalds
+- *
+- *  Nov 2001 Dave Jones <davej@suse.de>
+- *  Forked from i386 setup code.
+  */
+ 
+ /*
+@@ -57,13 +52,13 @@
+ #include <asm/dma.h>
+ #include <asm/mpspec.h>
+ #include <asm/mmu_context.h>
+-#include <asm/bootsetup.h>
+ #include <asm/proto.h>
+ #include <asm/setup.h>
+ #include <asm/mach_apic.h>
+ #include <asm/numa.h>
+ #include <asm/sections.h>
+ #include <asm/dmi.h>
++#include <asm/cacheflush.h>
+ #ifdef CONFIG_XEN
+ #include <linux/percpu.h>
+ #include <xen/interface/physdev.h>
+@@ -180,6 +175,12 @@ struct resource code_resource = {
+ 	.end = 0,
+ 	.flags = IORESOURCE_RAM,
+ };
++struct resource bss_resource = {
++	.name = "Kernel bss",
++	.start = 0,
++	.end = 0,
++	.flags = IORESOURCE_RAM,
++};
+ 
+ #ifdef CONFIG_PROC_VMCORE
+ /* elfcorehdr= specifies the location of elf core header
+@@ -232,10 +233,11 @@ EXPORT_SYMBOL(edd);
+  */
+ static inline void copy_edd(void)
+ {
+-     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));
+-     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));
+-     edd.mbr_signature_nr = EDD_MBR_SIG_NR;
+-     edd.edd_info_nr = EDD_NR;
++     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
++	    sizeof(edd.mbr_signature));
++     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
++     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
++     edd.edd_info_nr = boot_params.eddbuf_entries;
+ }
+ #endif
+ #else
+@@ -244,6 +246,41 @@ static inline void copy_edd(void)
+ }
+ #endif
+ 
++#ifdef CONFIG_KEXEC
++#ifndef CONFIG_XEN
++static void __init reserve_crashkernel(void)
++{
++	unsigned long long free_mem;
++	unsigned long long crash_size, crash_base;
++	int ret;
++
++	free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
++
++	ret = parse_crashkernel(boot_command_line, free_mem,
++			&crash_size, &crash_base);
++	if (ret == 0 && crash_size) {
++		if (crash_base > 0) {
++			printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
++					"for crashkernel (System RAM: %ldMB)\n",
++					(unsigned long)(crash_size >> 20),
++					(unsigned long)(crash_base >> 20),
++					(unsigned long)(free_mem >> 20));
++			crashk_res.start = crash_base;
++			crashk_res.end   = crash_base + crash_size - 1;
++			reserve_bootmem(crash_base, crash_size);
++		} else
++			printk(KERN_INFO "crashkernel reservation failed - "
++					"you have to specify a base address\n");
++	}
++}
++#else
++#define reserve_crashkernel xen_machine_kexec_setup_resources
++#endif
++#else
++static inline void __init reserve_crashkernel(void)
++{}
++#endif
++
+ #ifndef CONFIG_XEN
+ #define EBDA_ADDR_POINTER 0x40E
+ 
+@@ -284,7 +321,7 @@ void __init setup_arch(char **cmdline_p)
+ 	atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+ 
+  	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); 
+- 	screen_info = SCREEN_INFO;
++	screen_info = boot_params.screen_info;
+ 
+ 	if (is_initial_xendomain()) {
+ 		const struct dom0_vga_console_info *info =
+@@ -307,22 +344,22 @@ void __init setup_arch(char **cmdline_p)
+ #else
+ 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ 
+- 	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+- 	screen_info = SCREEN_INFO;
+-	edid_info = EDID_INFO;
++	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
++	screen_info = boot_params.screen_info;
++	edid_info = boot_params.edid_info;
+ #endif	/* !CONFIG_XEN */
+-	saved_video_mode = SAVED_VIDEO_MODE;
+-	bootloader_type = LOADER_TYPE;
++	saved_video_mode = boot_params.hdr.vid_mode;
++	bootloader_type = boot_params.hdr.type_of_loader;
+ 
+ #ifdef CONFIG_BLK_DEV_RAM
+-	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+-	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+-	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
++	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
++	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
++	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+ #endif
+ 	setup_memory_region();
+ 	copy_edd();
+ 
+-	if (!MOUNT_ROOT_RDONLY)
++	if (!boot_params.hdr.root_flags)
+ 		root_mountflags &= ~MS_RDONLY;
+ 	init_mm.start_code = (unsigned long) &_text;
+ 	init_mm.end_code = (unsigned long) &_etext;
+@@ -333,6 +370,8 @@ void __init setup_arch(char **cmdline_p)
+ 	code_resource.end = virt_to_phys(&_etext)-1;
+ 	data_resource.start = virt_to_phys(&_etext);
+ 	data_resource.end = virt_to_phys(&_edata)-1;
++	bss_resource.start = virt_to_phys(&__bss_start);
++	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+ 
+ 	early_identify_cpu(&boot_cpu_data);
+ 
+@@ -360,6 +399,11 @@ void __init setup_arch(char **cmdline_p)
+ 	if (is_initial_xendomain())
+ 		dmi_scan_machine();
+ 
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
++	/* setup to use the static apicid table during kernel startup */
++	x86_cpu_to_apicid_ptr = (void *)&x86_cpu_to_apicid_init;
++#endif
++
+ 	/* How many end-of-memory variables you have, grandma! */
+ 	max_low_pfn = end_pfn;
+ 	max_pfn = end_pfn;
+@@ -424,52 +468,37 @@ void __init setup_arch(char **cmdline_p)
+         */
+        acpi_reserve_bootmem();
+ #endif
+-#ifdef CONFIG_XEN
+ #ifdef CONFIG_BLK_DEV_INITRD
++#ifdef CONFIG_XEN
+ 	if (xen_start_info->mod_start) {
+-		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
+-			/*reserve_bootmem_generic(INITRD_START, INITRD_SIZE);*/
+-			initrd_start = INITRD_START + PAGE_OFFSET;
+-			initrd_end = initrd_start+INITRD_SIZE;
++		unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
++		unsigned long ramdisk_size  = xen_start_info->mod_len;
++#else
++	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
++		unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
++		unsigned long ramdisk_size  = boot_params.hdr.ramdisk_size;
++#endif
++		unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
++		unsigned long end_of_mem    = end_pfn << PAGE_SHIFT;
++
++		if (ramdisk_end <= end_of_mem) {
++#ifndef CONFIG_XEN
++			reserve_bootmem_generic(ramdisk_image, ramdisk_size);
++#endif
++			initrd_start = ramdisk_image + PAGE_OFFSET;
++			initrd_end = initrd_start+ramdisk_size;
++#ifdef CONFIG_XEN
+ 			initrd_below_start_ok = 1;
+-		} else {
+-			printk(KERN_ERR "initrd extends beyond end of memory "
+-				"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-				(unsigned long)(INITRD_START + INITRD_SIZE),
+-				(unsigned long)(end_pfn << PAGE_SHIFT));
+-			initrd_start = 0;
+-		}
+-	}
+ #endif
+-#else	/* CONFIG_XEN */
+-#ifdef CONFIG_BLK_DEV_INITRD
+-	if (LOADER_TYPE && INITRD_START) {
+-		if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
+-			reserve_bootmem_generic(INITRD_START, INITRD_SIZE);
+-			initrd_start = INITRD_START + PAGE_OFFSET;
+-			initrd_end = initrd_start+INITRD_SIZE;
+-		}
+-		else {
++		} else {
+ 			printk(KERN_ERR "initrd extends beyond end of memory "
+-			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+-			    (unsigned long)(INITRD_START + INITRD_SIZE),
+-			    (unsigned long)(end_pfn << PAGE_SHIFT));
++			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
++			       ramdisk_end, end_of_mem);
+ 			initrd_start = 0;
+ 		}
+ 	}
+ #endif
+-#endif	/* !CONFIG_XEN */
+-#ifdef CONFIG_KEXEC
+-#ifdef CONFIG_XEN
+-	xen_machine_kexec_setup_resources();
+-#else
+-	if (crashk_res.start != crashk_res.end) {
+-		reserve_bootmem_generic(crashk_res.start,
+-			crashk_res.end - crashk_res.start + 1);
+-	}
+-#endif
+-#endif
+-
++	reserve_crashkernel();
+ 	paging_init();
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	/*
+@@ -784,7 +813,7 @@ static void __init amd_detect_cmp(struct
+  		   but in the same order as the HT nodeids.
+  		   If that doesn't result in a usable node fall back to the
+  		   path for the previous case.  */
+- 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
++		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
+  		if (ht_nodeid >= 0 &&
+  		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+  			node = apicid_to_node[ht_nodeid];
+@@ -799,6 +828,39 @@ static void __init amd_detect_cmp(struct
+ #endif
+ }
+ 
++#define ENABLE_C1E_MASK		0x18000000
++#define CPUID_PROCESSOR_SIGNATURE	1
++#define CPUID_XFAM		0x0ff00000
++#define CPUID_XFAM_K8		0x00000000
++#define CPUID_XFAM_10H		0x00100000
++#define CPUID_XFAM_11H		0x00200000
++#define CPUID_XMOD		0x000f0000
++#define CPUID_XMOD_REV_F	0x00040000
++
++#ifndef CONFIG_XEN
++/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
++static __cpuinit int amd_apic_timer_broken(void)
++{
++	u32 lo, hi;
++	u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
++	switch (eax & CPUID_XFAM) {
++	case CPUID_XFAM_K8:
++		if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
++			break;
++	case CPUID_XFAM_10H:
++	case CPUID_XFAM_11H:
++		rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
++		if (lo & ENABLE_C1E_MASK)
++			return 1;
++		break;
++	default:
++		/* err on the side of caution */
++		return 1;
++	}
++	return 0;
++}
++#endif
++
+ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ {
+ 	unsigned level;
+@@ -828,7 +890,7 @@ static void __cpuinit init_amd(struct cp
+ 	level = cpuid_eax(1);
+ 	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
+ 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+-	if (c->x86 == 0x10)
++	if (c->x86 == 0x10 || c->x86 == 0x11)
+ 		set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
+ 
+ 	/* Enable workaround for FXSAVE leak */
+@@ -870,6 +932,11 @@ static void __cpuinit init_amd(struct cp
+ 	/* Family 10 doesn't support C states in MWAIT so don't use it */
+ 	if (c->x86 == 0x10 && !force_mwait)
+ 		clear_bit(X86_FEATURE_MWAIT, &c->x86_capability);
++
++#ifndef CONFIG_XEN
++	if (amd_apic_timer_broken())
++		disable_apic_timer = 1;
++#endif
+ }
+ 
+ static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+@@ -1182,6 +1249,7 @@ void __cpuinit print_cpu_info(struct cpu
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ 	struct cpuinfo_x86 *c = v;
++	int cpu = 0;
+ 
+ 	/* 
+ 	 * These flag bits must match the definitions in <asm/cpufeature.h>.
+@@ -1191,7 +1259,7 @@ static int show_cpuinfo(struct seq_file 
+ 	 * applications want to get the raw CPUID data, they should access
+ 	 * /dev/cpu/<cpu_nr>/cpuid instead.
+ 	 */
+-	static char *x86_cap_flags[] = {
++	static const char *const x86_cap_flags[] = {
+ 		/* Intel-defined */
+ 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+ 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+@@ -1222,7 +1290,7 @@ static int show_cpuinfo(struct seq_file 
+ 		/* Intel-defined (#2) */
+ 		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+ 		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt",
++		NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* VIA/Cyrix/Centaur-defined */
+@@ -1232,10 +1300,10 @@ static int show_cpuinfo(struct seq_file 
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+ 		/* AMD-defined (#2) */
+-		"lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+-		"altmovcr8", "abm", "sse4a",
+-		"misalignsse", "3dnowprefetch",
+-		"osvw", "ibs", NULL, NULL, NULL, NULL,
++		"lahf_lm", "cmp_legacy", "svm", "extapic",
++		"cr8_legacy", "abm", "sse4a", "misalignsse",
++		"3dnowprefetch", "osvw", "ibs", "sse5",
++		"skinit", "wdt", NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 
+@@ -1245,7 +1313,7 @@ static int show_cpuinfo(struct seq_file 
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ 	};
+-	static char *x86_power_flags[] = { 
++	static const char *const x86_power_flags[] = {
+ 		"ts",	/* temperature sensor */
+ 		"fid",  /* frequency id control */
+ 		"vid",  /* voltage id control */
+@@ -1260,8 +1328,7 @@ static int show_cpuinfo(struct seq_file 
+ 
+ 
+ #ifdef CONFIG_SMP
+-	if (!cpu_online(c-cpu_data))
+-		return 0;
++	cpu = c->cpu_index;
+ #endif
+ 
+ 	seq_printf(m,"processor\t: %u\n"
+@@ -1269,7 +1336,7 @@ static int show_cpuinfo(struct seq_file 
+ 		     "cpu family\t: %d\n"
+ 		     "model\t\t: %d\n"
+ 		     "model name\t: %s\n",
+-		     (unsigned)(c-cpu_data),
++		     (unsigned)cpu,
+ 		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ 		     c->x86,
+ 		     (int)c->x86_model,
+@@ -1281,7 +1348,7 @@ static int show_cpuinfo(struct seq_file 
+ 		seq_printf(m, "stepping\t: unknown\n");
+ 	
+ 	if (cpu_has(c,X86_FEATURE_TSC)) {
+-		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
++		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
+ 		if (!freq)
+ 			freq = cpu_khz;
+ 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
+@@ -1294,9 +1361,9 @@ static int show_cpuinfo(struct seq_file 
+ 	
+ #ifdef CONFIG_SMP
+ 	if (smp_num_siblings * c->x86_max_cores > 1) {
+-		int cpu = c - cpu_data;
+ 		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+-		seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
++		seq_printf(m, "siblings\t: %d\n",
++			       cpus_weight(per_cpu(cpu_core_map, cpu)));
+ 		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+ 		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+ 	}
+@@ -1351,12 +1418,16 @@ static int show_cpuinfo(struct seq_file 
+ 
+ static void *c_start(struct seq_file *m, loff_t *pos)
+ {
+-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
++	if (*pos == 0)	/* just in case, cpu 0 is not the first */
++		*pos = first_cpu(cpu_online_map);
++	if ((*pos) < NR_CPUS && cpu_online(*pos))
++		return &cpu_data(*pos);
++	return NULL;
+ }
+ 
+ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+-	++*pos;
++	*pos = next_cpu(*pos, cpu_online_map);
+ 	return c_start(m, pos);
+ }
+ 
+--- head-2010-01-18.orig/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -72,7 +72,7 @@
+  *
+  *		B stepping CPUs may hang. There are hardware work arounds
+  *	for this. We warn about it in case your board doesn't have the work
+- *	arounds. Basically thats so I can tell anyone with a B stepping
++ *	arounds. Basically that's so I can tell anyone with a B stepping
+  *	CPU and SMP problems "tough".
+  *
+  *	Specific items [From Pentium Processor Specification Update]
+@@ -241,7 +241,7 @@ void leave_mm(unsigned long cpu)
+  * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
+  * 	Stop ipi delivery for the old mm. This is not synchronized with
+  * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
+- * 	for the wrong mm, and in the worst case we perform a superflous
++ * 	for the wrong mm, and in the worst case we perform a superfluous
+  * 	tlb flush.
+  * 1a2) set cpu_tlbstate to TLBSTATE_OK
+  * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
+@@ -309,6 +309,7 @@ irqreturn_t smp_invalidate_interrupt(int
+ 	smp_mb__after_clear_bit();
+ out:
+ 	put_cpu_no_resched();
++	__get_cpu_var(irq_stat).irq_tlb_count++;
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -580,7 +581,7 @@ static void stop_this_cpu (void * dummy)
+ 	 */
+ 	cpu_clear(smp_processor_id(), cpu_online_map);
+ 	disable_all_local_evtchn();
+-	if (cpu_data[smp_processor_id()].hlt_works_ok)
++	if (cpu_data(smp_processor_id()).hlt_works_ok)
+ 		for(;;) halt();
+ 	for (;;);
+ }
+@@ -610,6 +611,7 @@ void xen_smp_send_stop(void)
+  */
+ irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+ {
++	__get_cpu_var(irq_stat).irq_resched_count++;
+ 
+ 	return IRQ_HANDLED;
+ }
+@@ -632,6 +634,7 @@ irqreturn_t smp_call_function_interrupt(
+ 	 */
+ 	irq_enter();
+ 	(*func)(info);
++	__get_cpu_var(irq_stat).irq_call_count++;
+ 	irq_exit();
+ 
+ 	if (wait) {
+--- head-2010-01-18.orig/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/smp_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -167,6 +167,7 @@ asmlinkage void smp_invalidate_interrupt
+ out:
+ 	ack_APIC_irq();
+ 	cpu_clear(cpu, f->flush_cpumask);
++	add_pda(irq_tlb_count, 1);
+ }
+ 
+ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
+@@ -326,17 +327,27 @@ void unlock_ipi_call_lock(void)
+ }
+ 
+ /*
+- * this function sends a 'generic call function' IPI to one other CPU
+- * in the system.
+- *
+- * cpu is a standard Linux logical CPU number.
++ * this function sends a 'generic call function' IPI to all other CPU
++ * of the system defined in the mask.
+  */
+-static void
+-__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
++
++static int
++__smp_call_function_mask(cpumask_t mask,
++			 void (*func)(void *), void *info,
++			 int wait)
+ {
+ 	struct call_data_struct data;
+-	int cpus = 1;
++	cpumask_t allbutself;
++	int cpus;
++
++	allbutself = cpu_online_map;
++	cpu_clear(smp_processor_id(), allbutself);
++
++	cpus_and(mask, mask, allbutself);
++	cpus = cpus_weight(mask);
++
++	if (!cpus)
++		return 0;
+ 
+ 	data.func = func;
+ 	data.info = info;
+@@ -347,19 +358,55 @@ __smp_call_function_single(int cpu, void
+ 
+ 	call_data = &data;
+ 	wmb();
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
++
++	/* Send a message to other CPUs */
++	if (cpus_equal(mask, allbutself))
++		send_IPI_allbutself(CALL_FUNCTION_VECTOR);
++	else
++		send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+ 
+ 	/* Wait for response */
+ 	while (atomic_read(&data.started) != cpus)
+ 		cpu_relax();
+ 
+ 	if (!wait)
+-		return;
++		return 0;
+ 
+ 	while (atomic_read(&data.finished) != cpus)
+ 		cpu_relax();
++
++	return 0;
++}
++/**
++ * smp_call_function_mask(): Run a function on a set of other CPUs.
++ * @mask: The set of cpus to run on.  Must not include the current cpu.
++ * @func: The function to run. This must be fast and non-blocking.
++ * @info: An arbitrary pointer to pass to the function.
++ * @wait: If true, wait (atomically) until function has completed on other CPUs.
++ *
++ * Returns 0 on success, else a negative status code.
++ *
++ * If @wait is true, then returns once @func has returned; otherwise
++ * it returns just before the target cpu calls @func.
++ *
++ * You must not call this function with disabled interrupts or from a
++ * hardware interrupt handler or from a bottom half handler.
++ */
++int smp_call_function_mask(cpumask_t mask,
++			   void (*func)(void *), void *info,
++			   int wait)
++{
++	int ret;
++
++	/* Can deadlock when called with interrupts disabled */
++	WARN_ON(irqs_disabled());
++
++	spin_lock(&call_lock);
++	ret = __smp_call_function_mask(mask, func, info, wait);
++	spin_unlock(&call_lock);
++	return ret;
+ }
++EXPORT_SYMBOL(smp_call_function_mask);
+ 
+ /*
+  * smp_call_function_single - Run a function on a specific CPU
+@@ -378,6 +425,7 @@ int smp_call_function_single (int cpu, v
+ 	int nonatomic, int wait)
+ {
+ 	/* prevent preemption and reschedule on another processor */
++	int ret;
+ 	int me = get_cpu();
+ 
+ 	/* Can deadlock when called with interrupts disabled */
+@@ -391,51 +439,14 @@ int smp_call_function_single (int cpu, v
+ 		return 0;
+ 	}
+ 
+-	spin_lock(&call_lock);
+-	__smp_call_function_single(cpu, func, info, nonatomic, wait);
+-	spin_unlock(&call_lock);
++	ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
++
+ 	put_cpu();
+-	return 0;
++	return ret;
+ }
+ EXPORT_SYMBOL(smp_call_function_single);
+ 
+ /*
+- * this function sends a 'generic call function' IPI to all other CPUs
+- * in the system.
+- */
+-static void __smp_call_function (void (*func) (void *info), void *info,
+-				int nonatomic, int wait)
+-{
+-	struct call_data_struct data;
+-	int cpus = num_online_cpus()-1;
+-
+-	if (!cpus)
+-		return;
+-
+-	data.func = func;
+-	data.info = info;
+-	atomic_set(&data.started, 0);
+-	data.wait = wait;
+-	if (wait)
+-		atomic_set(&data.finished, 0);
+-
+-	call_data = &data;
+-	wmb();
+-	/* Send a message to all other CPUs and wait for them to respond */
+-	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
+-
+-	/* Wait for response */
+-	while (atomic_read(&data.started) != cpus)
+-		cpu_relax();
+-
+-	if (!wait)
+-		return;
+-
+-	while (atomic_read(&data.finished) != cpus)
+-		cpu_relax();
+-}
+-
+-/*
+  * smp_call_function - run a function on all other CPUs.
+  * @func: The function to run. This must be fast and non-blocking.
+  * @info: An arbitrary pointer to pass to the function.
+@@ -453,10 +464,7 @@ static void __smp_call_function (void (*
+ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+ 			int wait)
+ {
+-	spin_lock(&call_lock);
+-	__smp_call_function(func,info,nonatomic,wait);
+-	spin_unlock(&call_lock);
+-	return 0;
++	return smp_call_function_mask(cpu_online_map, func, info, wait);
+ }
+ EXPORT_SYMBOL(smp_call_function);
+ 
+@@ -485,7 +493,7 @@ void smp_send_stop(void)
+ 	/* Don't deadlock on the call lock in panic */
+ 	nolock = !spin_trylock(&call_lock);
+ 	local_irq_save(flags);
+-	__smp_call_function(stop_this_cpu, NULL, 0, 0);
++	__smp_call_function_mask(cpu_online_map, stop_this_cpu, NULL, 0);
+ 	if (!nolock)
+ 		spin_unlock(&call_lock);
+ 	disable_all_local_evtchn();
+@@ -505,7 +513,9 @@ asmlinkage irqreturn_t smp_reschedule_in
+ {
+ #ifndef CONFIG_XEN
+ 	ack_APIC_irq();
+-#else
++#endif
++	add_pda(irq_resched_count, 1);
++#ifdef CONFIG_XEN
+ 	return IRQ_HANDLED;
+ #endif
+ }
+@@ -535,6 +545,7 @@ asmlinkage irqreturn_t smp_call_function
+ 	exit_idle();
+ 	irq_enter();
+ 	(*func)(info);
++	add_pda(irq_call_count, 1);
+ 	irq_exit();
+ 	if (wait) {
+ 		mb();
+--- head-2010-01-18.orig/arch/x86/kernel/time-xen.c	2009-11-23 10:31:38.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/time-xen.c	2009-11-23 10:32:02.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/i386/kernel/time.c
+- *
+  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+  *
+  * This file contains the PC-specific time handling details:
+@@ -74,6 +72,7 @@
+ #include <asm/arch_hooks.h>
+ 
+ #include <xen/evtchn.h>
++#include <xen/sysctl.h>
+ #include <xen/interface/vcpu.h>
+ 
+ #include <asm/i8253.h>
+@@ -526,6 +525,13 @@ irqreturn_t timer_interrupt(int irq, voi
+ 	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+ 	struct vcpu_runstate_info runstate;
+ 
++	/* Keep nmi watchdog up to date */
++#ifdef __i386__
++	per_cpu(irq_stat, smp_processor_id()).irq0_irqs++;
++#else
++	add_pda(irq0_irqs, 1);
++#endif
++
+ 	/*
+ 	 * Here we are in the timer irq handler. We just have irqs locally
+ 	 * disabled but we don't know if the timer_bh is running on the other
+@@ -986,7 +992,7 @@ static int time_cpufreq_notifier(struct 
+ 	struct cpufreq_freqs *freq = data;
+ 	struct xen_platform_op op;
+ 
+-	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
++	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
+ 		return 0;
+ 
+ 	if (val == CPUFREQ_PRECHANGE)
+@@ -1024,30 +1030,33 @@ core_initcall(cpufreq_time_setup);
+  */
+ static ctl_table xen_subtable[] = {
+ 	{
+-		.ctl_name	= 1,
++		.ctl_name	= CTL_XEN_INDEPENDENT_WALLCLOCK,
+ 		.procname	= "independent_wallclock",
+ 		.data		= &independent_wallclock,
+ 		.maxlen		= sizeof(independent_wallclock),
+ 		.mode		= 0644,
++		.strategy	= sysctl_data,
+ 		.proc_handler	= proc_dointvec
+ 	},
+ 	{
+-		.ctl_name	= 2,
++		.ctl_name	= CTL_XEN_PERMITTED_CLOCK_JITTER,
+ 		.procname	= "permitted_clock_jitter",
+ 		.data		= &permitted_clock_jitter,
+ 		.maxlen		= sizeof(permitted_clock_jitter),
+ 		.mode		= 0644,
++		.strategy	= sysctl_data,
+ 		.proc_handler	= proc_doulongvec_minmax
+ 	},
+-	{ 0 }
++	{ }
+ };
+ static ctl_table xen_table[] = {
+ 	{
+-		.ctl_name	= 123,
++		.ctl_name	= CTL_XEN,
+ 		.procname	= "xen",
+ 		.mode		= 0555,
+-		.child		= xen_subtable},
+-	{ 0 }
++		.child		= xen_subtable
++	},
++	{ }
+ };
+ static int __init xen_sysctl_init(void)
+ {
+--- head-2010-01-18.orig/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/i386/traps.c
+- *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *
+  *  Pentium III FXSR, SSE support
+@@ -65,6 +63,11 @@
+ 
+ int panic_on_unrecovered_nmi;
+ 
++#ifndef CONFIG_XEN
++DECLARE_BITMAP(used_vectors, NR_VECTORS);
++EXPORT_SYMBOL_GPL(used_vectors);
++#endif
++
+ asmlinkage int system_call(void);
+ 
+ /* Do we ignore FPU interrupts ? */
+@@ -120,7 +123,7 @@ struct stack_frame {
+ 
+ static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ 				unsigned long *stack, unsigned long ebp,
+-				struct stacktrace_ops *ops, void *data)
++				const struct stacktrace_ops *ops, void *data)
+ {
+ #ifdef	CONFIG_FRAME_POINTER
+ 	struct stack_frame *frame = (struct stack_frame *)ebp;
+@@ -157,7 +160,7 @@ static inline unsigned long print_contex
+ 
+ void dump_trace(struct task_struct *task, struct pt_regs *regs,
+ 	        unsigned long *stack,
+-		struct stacktrace_ops *ops, void *data)
++		const struct stacktrace_ops *ops, void *data)
+ {
+ 	unsigned long ebp = 0;
+ 
+@@ -229,7 +232,7 @@ static void print_trace_address(void *da
+ 	touch_nmi_watchdog();
+ }
+ 
+-static struct stacktrace_ops print_trace_ops = {
++static const struct stacktrace_ops print_trace_ops = {
+ 	.warning = print_trace_warning,
+ 	.warning_symbol = print_trace_warning_symbol,
+ 	.stack = print_trace_stack,
+@@ -288,6 +291,11 @@ void dump_stack(void)
+ {
+ 	unsigned long stack;
+ 
++	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
++		current->pid, current->comm, print_tainted(),
++		init_utsname()->release,
++		(int)strcspn(init_utsname()->version, " "),
++		init_utsname()->version);
+ 	show_trace(current, NULL, &stack);
+ }
+ 
+@@ -296,48 +304,24 @@ EXPORT_SYMBOL(dump_stack);
+ void show_registers(struct pt_regs *regs)
+ {
+ 	int i;
+-	int in_kernel = 1;
+-	unsigned long esp;
+-	unsigned short ss, gs;
+-
+-	esp = (unsigned long) (&regs->esp);
+-	savesegment(ss, ss);
+-	savesegment(gs, gs);
+-	if (user_mode_vm(regs)) {
+-		in_kernel = 0;
+-		esp = regs->esp;
+-		ss = regs->xss & 0xffff;
+-	}
++
+ 	print_modules();
+-	printk(KERN_EMERG "CPU:    %d\n"
+-		KERN_EMERG "EIP:    %04x:[<%08lx>]    %s VLI\n"
+-		KERN_EMERG "EFLAGS: %08lx   (%s %.*s)\n",
+-		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
+-		print_tainted(), regs->eflags, init_utsname()->release,
+-		(int)strcspn(init_utsname()->version, " "),
+-		init_utsname()->version);
+-	print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
+-	printk(KERN_EMERG "eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
+-		regs->eax, regs->ebx, regs->ecx, regs->edx);
+-	printk(KERN_EMERG "esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
+-		regs->esi, regs->edi, regs->ebp, esp);
+-	printk(KERN_EMERG "ds: %04x   es: %04x   fs: %04x  gs: %04x  ss: %04x\n",
+-	       regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss);
++	__show_registers(regs, 0);
+ 	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+-		TASK_COMM_LEN, current->comm, current->pid,
++		TASK_COMM_LEN, current->comm, task_pid_nr(current),
+ 		current_thread_info(), current, task_thread_info(current));
+ 	/*
+ 	 * When in-kernel, we also print out the stack and code at the
+ 	 * time of the fault..
+ 	 */
+-	if (in_kernel) {
++	if (!user_mode_vm(regs)) {
+ 		u8 *eip;
+ 		unsigned int code_prologue = code_bytes * 43 / 64;
+ 		unsigned int code_len = code_bytes;
+ 		unsigned char c;
+ 
+ 		printk("\n" KERN_EMERG "Stack: ");
+-		show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
++		show_stack_log_lvl(NULL, regs, &regs->esp, KERN_EMERG);
+ 
+ 		printk(KERN_EMERG "Code: ");
+ 
+@@ -382,11 +366,11 @@ int is_valid_bugaddr(unsigned long eip)
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+ 	static struct {
+-		spinlock_t lock;
++		raw_spinlock_t lock;
+ 		u32 lock_owner;
+ 		int lock_owner_depth;
+ 	} die = {
+-		.lock =			__SPIN_LOCK_UNLOCKED(die.lock),
++		.lock =			__RAW_SPIN_LOCK_UNLOCKED,
+ 		.lock_owner =		-1,
+ 		.lock_owner_depth =	0
+ 	};
+@@ -397,40 +381,33 @@ void die(const char * str, struct pt_reg
+ 
+ 	if (die.lock_owner != raw_smp_processor_id()) {
+ 		console_verbose();
+-		spin_lock_irqsave(&die.lock, flags);
++		raw_local_irq_save(flags);
++		__raw_spin_lock(&die.lock);
+ 		die.lock_owner = smp_processor_id();
+ 		die.lock_owner_depth = 0;
+ 		bust_spinlocks(1);
+-	}
+-	else
+-		local_save_flags(flags);
++	} else
++		raw_local_irq_save(flags);
+ 
+ 	if (++die.lock_owner_depth < 3) {
+-		int nl = 0;
+ 		unsigned long esp;
+ 		unsigned short ss;
+ 
+ 		report_bug(regs->eip, regs);
+ 
+-		printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
++		printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff,
++		       ++die_counter);
+ #ifdef CONFIG_PREEMPT
+-		printk(KERN_EMERG "PREEMPT ");
+-		nl = 1;
++		printk("PREEMPT ");
+ #endif
+ #ifdef CONFIG_SMP
+-		if (!nl)
+-			printk(KERN_EMERG);
+ 		printk("SMP ");
+-		nl = 1;
+ #endif
+ #ifdef CONFIG_DEBUG_PAGEALLOC
+-		if (!nl)
+-			printk(KERN_EMERG);
+ 		printk("DEBUG_PAGEALLOC");
+-		nl = 1;
+ #endif
+-		if (nl)
+-			printk("\n");
++		printk("\n");
++
+ 		if (notify_die(DIE_OOPS, str, regs, err,
+ 					current->thread.trap_no, SIGSEGV) !=
+ 				NOTIFY_STOP) {
+@@ -454,7 +431,8 @@ void die(const char * str, struct pt_reg
+ 	bust_spinlocks(0);
+ 	die.lock_owner = -1;
+ 	add_taint(TAINT_DIE);
+-	spin_unlock_irqrestore(&die.lock, flags);
++	__raw_spin_unlock(&die.lock);
++	raw_local_irq_restore(flags);
+ 
+ 	if (!regs)
+ 		return;
+@@ -571,6 +549,7 @@ fastcall void do_##name(struct pt_regs *
+ 	info.si_errno = 0; \
+ 	info.si_code = sicode; \
+ 	info.si_addr = (void __user *)siaddr; \
++	trace_hardirqs_fixup(); \
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+ 						== NOTIFY_STOP) \
+ 		return; \
+@@ -606,7 +585,7 @@ fastcall void __kprobes do_general_prote
+ 	    printk_ratelimit())
+ 		printk(KERN_INFO
+ 		    "%s[%d] general protection eip:%lx esp:%lx error:%lx\n",
+-		    current->comm, current->pid,
++		    current->comm, task_pid_nr(current),
+ 		    regs->eip, regs->esp, error_code);
+ 
+ 	force_sig(SIGSEGV, current);
+@@ -785,6 +764,8 @@ void restart_nmi(void)
+ #ifdef CONFIG_KPROBES
+ fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
+ {
++	trace_hardirqs_fixup();
++
+ 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+ 			== NOTIFY_STOP)
+ 		return;
+@@ -822,6 +803,8 @@ fastcall void __kprobes do_debug(struct 
+ 	unsigned int condition;
+ 	struct task_struct *tsk = current;
+ 
++	trace_hardirqs_fixup();
++
+ 	get_debugreg(condition, 6);
+ 
+ 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+@@ -1084,20 +1067,6 @@ asmlinkage void math_emulate(long arg)
+ 
+ #endif /* CONFIG_MATH_EMULATION */
+ 
+-#ifdef CONFIG_X86_F00F_BUG
+-void __init trap_init_f00f_bug(void)
+-{
+-	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+-
+-	/*
+-	 * Update the IDT descriptor and reload the IDT so that
+-	 * it uses the read-only mapped virtual address.
+-	 */
+-	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
+-	load_idt(&idt_descr);
+-}
+-#endif
+-
+ 
+ /*
+  * NB. All these are "trap gates" (i.e. events_mask isn't set) except
+--- head-2010-01-18.orig/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/traps_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/x86-64/traps.c
+- *
+  *  Copyright (C) 1991, 1992  Linus Torvalds
+  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+  *
+@@ -33,6 +31,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/bug.h>
+ #include <linux/kdebug.h>
++#include <linux/utsname.h>
+ 
+ #if defined(CONFIG_EDAC)
+ #include <linux/edac.h>
+@@ -205,7 +204,7 @@ static unsigned long *in_exception_stack
+ #define MSG(txt) ops->warning(data, txt)
+ 
+ /*
+- * x86-64 can have upto three kernel stacks: 
++ * x86-64 can have up to three kernel stacks:
+  * process stack
+  * interrupt stack
+  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
+@@ -219,7 +218,7 @@ static inline int valid_stack_ptr(struct
+ 
+ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
+ 		unsigned long *stack,
+-		struct stacktrace_ops *ops, void *data)
++		const struct stacktrace_ops *ops, void *data)
+ {
+ 	const unsigned cpu = get_cpu();
+ 	unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr;
+@@ -340,7 +339,7 @@ static void print_trace_address(void *da
+ 	printk_address(addr);
+ }
+ 
+-static struct stacktrace_ops print_trace_ops = {
++static const struct stacktrace_ops print_trace_ops = {
+ 	.warning = print_trace_warning,
+ 	.warning_symbol = print_trace_warning_symbol,
+ 	.stack = print_trace_stack,
+@@ -404,6 +403,12 @@ void show_stack(struct task_struct *tsk,
+ void dump_stack(void)
+ {
+ 	unsigned long dummy;
++
++	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
++		current->pid, current->comm, print_tainted(),
++		init_utsname()->release,
++		(int)strcspn(init_utsname()->version, " "),
++		init_utsname()->version);
+ 	show_trace(NULL, NULL, &dummy);
+ }
+ 
+@@ -466,7 +471,7 @@ void out_of_line_bug(void)
+ EXPORT_SYMBOL(out_of_line_bug);
+ #endif
+ 
+-static DEFINE_SPINLOCK(die_lock);
++static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+ static int die_owner = -1;
+ static unsigned int die_nest_count;
+ 
+@@ -478,13 +483,13 @@ unsigned __kprobes long oops_begin(void)
+ 	oops_enter();
+ 
+ 	/* racy, but better than risking deadlock. */
+-	local_irq_save(flags);
++	raw_local_irq_save(flags);
+ 	cpu = smp_processor_id();
+-	if (!spin_trylock(&die_lock)) { 
++	if (!__raw_spin_trylock(&die_lock)) {
+ 		if (cpu == die_owner) 
+ 			/* nested oops. should stop eventually */;
+ 		else
+-			spin_lock(&die_lock);
++			__raw_spin_lock(&die_lock);
+ 	}
+ 	die_nest_count++;
+ 	die_owner = cpu;
+@@ -498,12 +503,10 @@ void __kprobes oops_end(unsigned long fl
+ 	die_owner = -1;
+ 	bust_spinlocks(0);
+ 	die_nest_count--;
+-	if (die_nest_count)
+-		/* We still own the lock */
+-		local_irq_restore(flags);
+-	else
++	if (!die_nest_count)
+ 		/* Nest count reaches zero, release the lock. */
+-		spin_unlock_irqrestore(&die_lock, flags);
++		__raw_spin_unlock(&die_lock);
++	raw_local_irq_restore(flags);
+ 	if (panic_on_oops)
+ 		panic("Fatal exception");
+ 	oops_exit();
+@@ -636,6 +639,7 @@ asmlinkage void do_##name(struct pt_regs
+ 	info.si_errno = 0; \
+ 	info.si_code = sicode; \
+ 	info.si_addr = (void __user *)siaddr; \
++	trace_hardirqs_fixup(); \
+ 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+ 							== NOTIFY_STOP) \
+ 		return; \
+@@ -741,11 +745,8 @@ mem_parity_error(unsigned char reason, s
+ 
+ 	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+ 
+-#if 0 /* XEN */
+ 	/* Clear and disable the memory parity error line. */
+-	reason = (reason & 0xf) | 4;
+-	outb(reason, 0x61);
+-#endif /* XEN */
++	clear_mem_error(reason);
+ }
+ 
+ static __kprobes void
+@@ -754,14 +755,8 @@ io_check_error(unsigned char reason, str
+ 	printk("NMI: IOCK error (debug interrupt?)\n");
+ 	show_registers(regs);
+ 
+-#if 0 /* XEN */
+ 	/* Re-enable the IOCK line, wait for a few seconds */
+-	reason = (reason & 0xf) | 8;
+-	outb(reason, 0x61);
+-	mdelay(2000);
+-	reason &= ~8;
+-	outb(reason, 0x61);
+-#endif /* XEN */
++	clear_io_check_error(reason);
+ }
+ 
+ static __kprobes void
+@@ -821,6 +816,8 @@ asmlinkage __kprobes void default_do_nmi
+ /* runs on IST stack. */
+ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
+ {
++	trace_hardirqs_fixup();
++
+ 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
+ 		return;
+ 	}
+@@ -858,6 +855,8 @@ asmlinkage void __kprobes do_debug(struc
+ 	struct task_struct *tsk = current;
+ 	siginfo_t info;
+ 
++	trace_hardirqs_fixup();
++
+ 	get_debugreg(condition, 6);
+ 
+ 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+--- head-2010-01-18.orig/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/vsyscall_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/arch/x86_64/kernel/vsyscall.c
+- *
+  *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
+  *  Copyright 2003 Andi Kleen, SuSE Labs.
+  *
+@@ -50,12 +48,12 @@
+ 	({unsigned long v;  		\
+ 	extern char __vsyscall_0; 	\
+ 	  asm("" : "=r" (v) : "0" (x)); \
+-	  ((v - VSYSCALL_FIRST_PAGE) + __pa_symbol(&__vsyscall_0)); })
++	  ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); })
+ 
+ /*
+  * vsyscall_gtod_data contains data that is :
+  * - readonly from vsyscalls
+- * - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
++ * - written by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
+  * Try to keep this structure as small as possible to avoid cache line ping pongs
+  */
+ int __vgetcpu_mode __section_vgetcpu_mode;
+@@ -66,6 +64,16 @@ struct vsyscall_gtod_data __vsyscall_gto
+ 	.sysctl_enabled = 1,
+ };
+ 
++void update_vsyscall_tz(void)
++{
++	unsigned long flags;
++
++	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
++	/* sys_tz has changed */
++	vsyscall_gtod_data.sys_tz = sys_tz;
++	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
++}
++
+ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+ {
+ 	unsigned long flags;
+@@ -79,8 +87,6 @@ void update_vsyscall(struct timespec *wa
+ 	vsyscall_gtod_data.clock.shift = clock->shift;
+ 	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+ 	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+-	vsyscall_gtod_data.sys_tz = sys_tz;
+-	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+ 	vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;
+ 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+ }
+@@ -166,7 +172,7 @@ time_t __vsyscall(1) vtime(time_t *t)
+ 	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
+ 		return time_syscall(t);
+ 
+-	vgettimeofday(&tv, 0);
++	vgettimeofday(&tv, NULL);
+ 	result = tv.tv_sec;
+ 	if (t)
+ 		*t = result;
+@@ -260,18 +266,10 @@ out:
+ 	return ret;
+ }
+ 
+-static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
+-				void __user *oldval, size_t __user *oldlenp,
+-				void __user *newval, size_t newlen)
+-{
+-	return -ENOSYS;
+-}
+-
+ static ctl_table kernel_table2[] = {
+-	{ .ctl_name = 99, .procname = "vsyscall64",
++	{ .procname = "vsyscall64",
+ 	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
+ 	  .mode = 0644,
+-	  .strategy = vsyscall_sysctl_nostrat,
+ 	  .proc_handler = vsyscall_sysctl_change },
+ 	{}
+ };
+@@ -291,9 +289,9 @@ static void __cpuinit vsyscall_set_cpu(i
+ 	unsigned long d;
+ 	unsigned long node = 0;
+ #ifdef CONFIG_NUMA
+-	node = cpu_to_node[cpu];
++	node = cpu_to_node(cpu);
+ #endif
+-	if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP))
++	if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
+ 		write_rdtscp_aux((node << 12) | cpu);
+ 
+ 	/* Store cpu number in limit so that it can be loaded quickly
+--- head-2010-01-18.orig/arch/x86/mm/fault_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+ #include <linux/kdebug.h>
++#include <linux/kprobes.h>
+ 
+ #include <asm/system.h>
+ #include <asm/desc.h>
+@@ -32,33 +33,27 @@
+ 
+ extern void die(const char *,struct pt_regs *,long);
+ 
+-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+-
+-int register_page_fault_notifier(struct notifier_block *nb)
++#ifdef CONFIG_KPROBES
++static inline int notify_page_fault(struct pt_regs *regs)
+ {
+-	vmalloc_sync_all();
+-	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+-}
+-EXPORT_SYMBOL_GPL(register_page_fault_notifier);
++	int ret = 0;
+ 
+-int unregister_page_fault_notifier(struct notifier_block *nb)
+-{
+-	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+-}
+-EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
++	/* kprobe_running() needs smp_processor_id() */
++	if (!user_mode_vm(regs)) {
++		preempt_disable();
++		if (kprobe_running() && kprobe_fault_handler(regs, 14))
++			ret = 1;
++		preempt_enable();
++	}
+ 
+-static inline int notify_page_fault(struct pt_regs *regs, long err)
++	return ret;
++}
++#else
++static inline int notify_page_fault(struct pt_regs *regs)
+ {
+-	struct die_args args = {
+-		.regs = regs,
+-		.str = "page fault",
+-		.err = err,
+-		.trapnr = 14,
+-		.signr = SIGSEGV
+-	};
+-	return atomic_notifier_call_chain(&notify_page_fault_chain,
+-	                                  DIE_PAGE_FAULT, &args);
++	return 0;
+ }
++#endif
+ 
+ /*
+  * Return EIP plus the CS segment base.  The segment limit is also
+@@ -110,7 +105,7 @@ static inline unsigned long get_segment_
+ 	   LDT and other horrors are only used in user space. */
+ 	if (seg & (1<<2)) {
+ 		/* Must lock the LDT while reading it. */
+-		down(&current->mm->context.sem);
++		mutex_lock(&current->mm->context.lock);
+ 		desc = current->mm->context.ldt;
+ 		desc = (void *)desc + (seg & ~7);
+ 	} else {
+@@ -123,7 +118,7 @@ static inline unsigned long get_segment_
+ 	base = get_desc_base((unsigned long *)desc);
+ 
+ 	if (seg & (1<<2)) { 
+-		up(&current->mm->context.sem);
++		mutex_unlock(&current->mm->context.lock);
+ 	} else
+ 		put_cpu();
+ 
+@@ -244,7 +239,7 @@ static void dump_fault_path(unsigned lon
+ 		if (mfn_to_pfn(mfn) >= highstart_pfn)
+ 			return;
+ #endif
+-		if (p[0] & _PAGE_PRESENT) {
++		if ((p[0] & _PAGE_PRESENT) && !(p[0] & _PAGE_PSE)) {
+ 			page = mfn_to_pfn(mfn) << PAGE_SHIFT; 
+ 			p  = (unsigned long *) __va(page);
+ 			address &= 0x001fffff;
+@@ -270,7 +265,8 @@ static void dump_fault_path(unsigned lon
+ 	 * it's allocated already.
+ 	 */
+ 	if ((machine_to_phys(page) >> PAGE_SHIFT) < max_low_pfn
+-	    && (page & _PAGE_PRESENT)) {
++	    && (page & _PAGE_PRESENT)
++	    && !(page & _PAGE_PSE)) {
+ 		page = machine_to_phys(page & PAGE_MASK);
+ 		page = ((unsigned long *) __va(page))[(address >> PAGE_SHIFT)
+ 		                                      & (PTRS_PER_PTE - 1)];
+@@ -416,6 +412,11 @@ fastcall void __kprobes do_page_fault(st
+ 	int write, si_code;
+ 	int fault;
+ 
++	/*
++	 * We can fault from pretty much anywhere, with unknown IRQ state.
++	 */
++	trace_hardirqs_fixup();
++
+ 	/* get the address */
+         address = read_cr2();
+ 
+@@ -453,7 +454,7 @@ fastcall void __kprobes do_page_fault(st
+ 		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+ 		if (spurious_fault(regs, address, error_code))
+ 			return;
+-		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
++		if (notify_page_fault(regs))
+ 			return;
+ 		/* 
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+@@ -462,7 +463,7 @@ fastcall void __kprobes do_page_fault(st
+ 		goto bad_area_nosemaphore;
+ 	}
+ 
+-	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
++	if (notify_page_fault(regs))
+ 		return;
+ 
+ 	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
+@@ -481,7 +482,7 @@ fastcall void __kprobes do_page_fault(st
+ 
+ 	/* When running in the kernel we expect faults to occur only to
+ 	 * addresses in user space.  All other faults represent errors in the
+-	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
++	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+ 	 * erroneous fault occurring in a code path which already holds mmap_sem
+ 	 * we will deadlock attempting to validate the fault against the
+ 	 * address space.  Luckily the kernel only validly references user
+@@ -489,7 +490,7 @@ fastcall void __kprobes do_page_fault(st
+ 	 * exceptions table.
+ 	 *
+ 	 * As the vast majority of faults will be valid we will only perform
+-	 * the source reference check when there is a possibilty of a deadlock.
++	 * the source reference check when there is a possibility of a deadlock.
+ 	 * Attempt to lock the address space, if we cannot we then validate the
+ 	 * source.  If this is invalid we can skip the address space check,
+ 	 * thus avoiding the deadlock.
+@@ -598,8 +599,8 @@ bad_area_nosemaphore:
+ 		    printk_ratelimit()) {
+ 			printk("%s%s[%d]: segfault at %08lx eip %08lx "
+ 			    "esp %08lx error %lx\n",
+-			    tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
+-			    tsk->comm, tsk->pid, address, regs->eip,
++			    task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
++			    tsk->comm, task_pid_nr(tsk), address, regs->eip,
+ 			    regs->esp, error_code);
+ 		}
+ 		tsk->thread.cr2 = address;
+@@ -664,8 +665,7 @@ no_context:
+ 			printk(KERN_ALERT "BUG: unable to handle kernel paging"
+ 					" request");
+ 		printk(" at virtual address %08lx\n",address);
+-		printk(KERN_ALERT " printing eip:\n");
+-		printk("%08lx\n", regs->eip);
++		printk(KERN_ALERT "printing eip: %08lx\n", regs->eip);
+ 		dump_fault_path(address);
+ 	}
+ 	tsk->thread.cr2 = address;
+@@ -681,14 +681,14 @@ no_context:
+  */
+ out_of_memory:
+ 	up_read(&mm->mmap_sem);
+-	if (is_init(tsk)) {
++	if (is_global_init(tsk)) {
+ 		yield();
+ 		down_read(&mm->mmap_sem);
+ 		goto survive;
+ 	}
+ 	printk("VM: killing process %s\n", tsk->comm);
+ 	if (error_code & 4)
+-		do_exit(SIGKILL);
++		do_group_exit(SIGKILL);
+ 	goto no_context;
+ 
+ do_sigbus:
+--- head-2010-01-18.orig/arch/x86/mm/fault_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/fault_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -25,6 +25,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/uaccess.h>
+ #include <linux/kdebug.h>
++#include <linux/kprobes.h>
+ 
+ #include <asm/system.h>
+ #include <asm/pgalloc.h>
+@@ -40,34 +41,27 @@
+ #define PF_RSVD	(1<<3)
+ #define PF_INSTR	(1<<4)
+ 
+-static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+-
+-/* Hook to register for page fault notifications */
+-int register_page_fault_notifier(struct notifier_block *nb)
++#ifdef CONFIG_KPROBES
++static inline int notify_page_fault(struct pt_regs *regs)
+ {
+-	vmalloc_sync_all();
+-	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+-}
+-EXPORT_SYMBOL_GPL(register_page_fault_notifier);
++	int ret = 0;
+ 
+-int unregister_page_fault_notifier(struct notifier_block *nb)
+-{
+-	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+-}
+-EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
++	/* kprobe_running() needs smp_processor_id() */
++	if (!user_mode(regs)) {
++		preempt_disable();
++		if (kprobe_running() && kprobe_fault_handler(regs, 14))
++			ret = 1;
++		preempt_enable();
++	}
+ 
+-static inline int notify_page_fault(struct pt_regs *regs, long err)
++	return ret;
++}
++#else
++static inline int notify_page_fault(struct pt_regs *regs)
+ {
+-	struct die_args args = {
+-		.regs = regs,
+-		.str = "page fault",
+-		.err = err,
+-		.trapnr = 14,
+-		.signr = SIGSEGV
+-	};
+-	return atomic_notifier_call_chain(&notify_page_fault_chain,
+-	                                  DIE_PAGE_FAULT, &args);
++	return 0;
+ }
++#endif
+ 
+ /* Sometimes the CPU reports invalid exceptions on prefetch.
+    Check that here and ignore.
+@@ -175,7 +169,7 @@ void dump_pagetable(unsigned long addres
+ 	pmd = pmd_offset(pud, address);
+ 	if (bad_address(pmd)) goto bad;
+ 	printk("PMD %lx ", pmd_val(*pmd));
+-	if (!pmd_present(*pmd))	goto ret;	 
++	if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
+ 
+ 	pte = pte_offset_kernel(pmd, address);
+ 	if (bad_address(pte)) goto bad;
+@@ -294,7 +288,6 @@ static int vmalloc_fault(unsigned long a
+ 	return 0;
+ }
+ 
+-static int page_fault_trace;
+ int show_unhandled_signals = 1;
+ 
+ 
+@@ -371,6 +364,11 @@ asmlinkage void __kprobes do_page_fault(
+ 	if (!user_mode(regs))
+ 		error_code &= ~PF_USER; /* means kernel */
+ 
++	/*
++	 * We can fault from pretty much anywhere, with unknown IRQ state.
++	 */
++	trace_hardirqs_fixup();
++
+ 	tsk = current;
+ 	mm = tsk->mm;
+ 	prefetchw(&mm->mmap_sem);
+@@ -408,7 +406,7 @@ asmlinkage void __kprobes do_page_fault(
+ 		/* Can take a spurious fault if mapping changes R/O -> R/W. */
+ 		if (spurious_fault(regs, address, error_code))
+ 			return;
+-		if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
++		if (notify_page_fault(regs))
+ 			return;
+ 		/*
+ 		 * Don't take the mm semaphore here. If we fixup a prefetch
+@@ -417,16 +415,12 @@ asmlinkage void __kprobes do_page_fault(
+ 		goto bad_area_nosemaphore;
+ 	}
+ 
+-	if (notify_page_fault(regs, error_code) == NOTIFY_STOP)
++	if (notify_page_fault(regs))
+ 		return;
+ 
+ 	if (likely(regs->eflags & X86_EFLAGS_IF))
+ 		local_irq_enable();
+ 
+-	if (unlikely(page_fault_trace))
+-		printk("pagefault rip:%lx rsp:%lx cs:%lu ss:%lu address %lx error %lx\n",
+-		       regs->rip,regs->rsp,regs->cs,regs->ss,address,error_code); 
+-
+ 	if (unlikely(error_code & PF_RSVD))
+ 		pgtable_bad(address, regs, error_code);
+ 
+@@ -447,7 +441,7 @@ asmlinkage void __kprobes do_page_fault(
+  again:
+ 	/* When running in the kernel we expect faults to occur only to
+ 	 * addresses in user space.  All other faults represent errors in the
+-	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
++	 * kernel and should generate an OOPS.  Unfortunately, in the case of an
+ 	 * erroneous fault occurring in a code path which already holds mmap_sem
+ 	 * we will deadlock attempting to validate the fault against the
+ 	 * address space.  Luckily the kernel only validly references user
+@@ -455,7 +449,7 @@ asmlinkage void __kprobes do_page_fault(
+ 	 * exceptions table.
+ 	 *
+ 	 * As the vast majority of faults will be valid we will only perform
+-	 * the source reference check when there is a possibilty of a deadlock.
++	 * the source reference check when there is a possibility of a deadlock.
+ 	 * Attempt to lock the address space, if we cannot we then validate the
+ 	 * source.  If this is invalid we can skip the address space check,
+ 	 * thus avoiding the deadlock.
+@@ -557,7 +551,7 @@ bad_area_nosemaphore:
+ 		if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+ 		    printk_ratelimit()) {
+ 			printk(
+-		       "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
++		       "%s%s[%d]: segfault at %lx rip %lx rsp %lx error %lx\n",
+ 					tsk->pid > 1 ? KERN_INFO : KERN_EMERG,
+ 					tsk->comm, tsk->pid, address, regs->rip,
+ 					regs->rsp, error_code);
+@@ -623,7 +617,7 @@ no_context:
+  */
+ out_of_memory:
+ 	up_read(&mm->mmap_sem);
+-	if (is_init(current)) {
++	if (is_global_init(current)) {
+ 		yield();
+ 		goto again;
+ 	}
+@@ -690,10 +684,3 @@ void vmalloc_sync_all(void)
+ 	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) == 
+ 				(__START_KERNEL & PGDIR_MASK)));
+ }
+-
+-static int __init enable_pagefaulttrace(char *str)
+-{
+-	page_fault_trace = 1;
+-	return 1;
+-}
+-__setup("pagefaulttrace", enable_pagefaulttrace);
+--- head-2010-01-18.orig/arch/x86/mm/hypervisor.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/hypervisor.c	2009-11-06 10:51:17.000000000 +0100
+@@ -500,6 +500,9 @@ int xen_create_contiguous_region(
+ 	unsigned long  frame, flags;
+ 	unsigned int   i;
+ 	int            rc, success;
++#ifdef CONFIG_64BIT
++	pte_t         *ptep = NULL;
++#endif
+ 	struct xen_memory_exchange exchange = {
+ 		.in = {
+ 			.nr_extents   = 1UL << order,
+@@ -525,6 +528,27 @@ int xen_create_contiguous_region(
+ 	if (unlikely(order > MAX_CONTIG_ORDER))
+ 		return -ENOMEM;
+ 
++#ifdef CONFIG_64BIT
++	if (unlikely(vstart > PAGE_OFFSET + MAXMEM)) {
++		unsigned int level;
++
++		if (vstart < __START_KERNEL_map
++		    || vstart + (PAGE_SIZE << order) > (unsigned long)_end)
++			return -EINVAL;
++		ptep = lookup_address((unsigned long)__va(__pa(vstart)),
++				      &level);
++		if (ptep && pte_none(*ptep))
++			ptep = NULL;
++		if (vstart < __START_KERNEL && ptep)
++			return -EINVAL;
++		if (order > MAX_CONTIG_ORDER - 1)
++			return -ENOMEM;
++	}
++#else
++	if (unlikely(vstart + (PAGE_SIZE << order) > (unsigned long)high_memory))
++		return -EINVAL;
++#endif
++
+ 	set_xen_guest_handle(exchange.in.extent_start, in_frames);
+ 	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
+ 
+@@ -537,9 +561,19 @@ int xen_create_contiguous_region(
+ 		in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
+ 		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ 					__pte_ma(0), 0);
++#ifdef CONFIG_64BIT
++		if (ptep)
++			MULTI_update_va_mapping(cr_mcl + i + (1U << order),
++				(unsigned long)__va(__pa(vstart)) + (i*PAGE_SIZE),
++				__pte_ma(0), 0);
++#endif
+ 		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
+ 			INVALID_P2M_ENTRY);
+ 	}
++#ifdef CONFIG_64BIT
++	if (ptep)
++		i += i;
++#endif
+ 	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
+ 		BUG();
+ 
+@@ -573,9 +607,18 @@ int xen_create_contiguous_region(
+ 		frame = success ? (out_frame + i) : in_frames[i];
+ 		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+ 					pfn_pte_ma(frame, PAGE_KERNEL), 0);
++#ifdef CONFIG_64BIT
++		if (ptep)
++			MULTI_update_va_mapping(cr_mcl + i + (1U << order),
++				(unsigned long)__va(__pa(vstart)) + (i*PAGE_SIZE),
++				pfn_pte_ma(frame, PAGE_KERNEL_RO), 0);
++#endif
+ 		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
+ 	}
+-
++#ifdef CONFIG_64BIT
++	if (ptep)
++		i += i;
++#endif
+ 	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+ 						   ? UVMF_TLB_FLUSH|UVMF_ALL
+ 						   : UVMF_INVLPG|UVMF_ALL;
+--- head-2010-01-18.orig/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -94,7 +94,14 @@ static pte_t * __init one_page_table_ini
+ #else
+ 	if (!(__pmd_val(*pmd) & _PAGE_PRESENT)) {
+ #endif
+-		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++		pte_t *page_table = NULL;
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++		page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
++#endif
++		if (!page_table)
++			page_table =
++				(pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ 
+ 		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+ 		make_lowmem_page_readonly(page_table,
+@@ -102,7 +109,7 @@ static pte_t * __init one_page_table_ini
+ 		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+ 		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+ 	}
+-	
++
+ 	return pte_offset_kernel(pmd, 0);
+ }
+ 
+@@ -360,8 +367,13 @@ static void __init set_highmem_pages_ini
+ {
+ 	int pfn;
+ 	for (pfn = highstart_pfn; pfn < highend_pfn
+-				  && pfn < xen_start_info->nr_pages; pfn++)
+-		add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
++				  && pfn < xen_start_info->nr_pages; pfn++) {
++		/*
++		 * Holes under sparsemem might not have no mem_map[]:
++		 */
++		if (pfn_valid(pfn))
++			add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
++	}
+ 
+ 	/* XEN: init high-mem pages outside initial allocation. */
+ 	for (; pfn < highend_pfn; pfn++) {
+@@ -785,35 +797,18 @@ int arch_add_memory(int nid, u64 start, 
+ 	return __add_pages(zone, start_pfn, nr_pages);
+ }
+ 
+-int remove_memory(u64 start, u64 size)
+-{
+-	return -EINVAL;
+-}
+-EXPORT_SYMBOL_GPL(remove_memory);
+ #endif
+ 
+ struct kmem_cache *pmd_cache;
+ 
+ void __init pgtable_cache_init(void)
+ {
+-	size_t pgd_size = PTRS_PER_PGD*sizeof(pgd_t);
+-
+-	if (PTRS_PER_PMD > 1) {
++	if (PTRS_PER_PMD > 1)
+ 		pmd_cache = kmem_cache_create("pmd",
+-					PTRS_PER_PMD*sizeof(pmd_t),
+-					PTRS_PER_PMD*sizeof(pmd_t),
+-					SLAB_PANIC,
+-					pmd_ctor);
+-		if (!SHARED_KERNEL_PMD) {
+-			/* If we're in PAE mode and have a non-shared
+-			   kernel pmd, then the pgd size must be a
+-			   page size.  This is because the pgd_list
+-			   links through the page structure, so there
+-			   can only be one pgd per page for this to
+-			   work. */
+-			pgd_size = PAGE_SIZE;
+-		}
+-	}
++					      PTRS_PER_PMD*sizeof(pmd_t),
++					      PTRS_PER_PMD*sizeof(pmd_t),
++					      SLAB_PANIC,
++					      pmd_ctor);
+ }
+ 
+ /*
+--- head-2010-01-18.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/init_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -798,7 +798,7 @@ static void xen_finish_init_mapping(void
+ /* Setup the direct mapping of the physical memory at PAGE_OFFSET.
+    This runs before bootmem is initialized and gets pages directly from the 
+    physical memory. To access them they are temporarily mapped. */
+-void __meminit init_memory_mapping(unsigned long start, unsigned long end)
++void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+ { 
+ 	unsigned long next;
+ 
+@@ -932,12 +932,6 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(arch_add_memory);
+ 
+-int remove_memory(u64 start, u64 size)
+-{
+-	return -EINVAL;
+-}
+-EXPORT_SYMBOL_GPL(remove_memory);
+-
+ #if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA)
+ int memory_add_physaddr_to_nid(u64 start)
+ {
+@@ -1203,14 +1197,6 @@ int in_gate_area_no_task(unsigned long a
+ 	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
+ }
+ 
+-#ifndef CONFIG_XEN
+-void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+-{
+-	return __alloc_bootmem_core(pgdat->bdata, size,
+-			SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+-}
+-#endif
+-
+ const char *arch_vma_name(struct vm_area_struct *vma)
+ {
+ 	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+@@ -1219,3 +1205,48 @@ const char *arch_vma_name(struct vm_area
+ 		return "[vsyscall]";
+ 	return NULL;
+ }
++
++#ifdef CONFIG_SPARSEMEM_VMEMMAP
++/*
++ * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
++ */
++int __meminit vmemmap_populate(struct page *start_page,
++						unsigned long size, int node)
++{
++	unsigned long addr = (unsigned long)start_page;
++	unsigned long end = (unsigned long)(start_page + size);
++	unsigned long next;
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++
++	for (; addr < end; addr = next) {
++		next = pmd_addr_end(addr, end);
++
++		pgd = vmemmap_pgd_populate(addr, node);
++		if (!pgd)
++			return -ENOMEM;
++		pud = vmemmap_pud_populate(pgd, addr, node);
++		if (!pud)
++			return -ENOMEM;
++
++		pmd = pmd_offset(pud, addr);
++		if (pmd_none(*pmd)) {
++			pte_t entry;
++			void *p = vmemmap_alloc_block(PMD_SIZE, node);
++			if (!p)
++				return -ENOMEM;
++
++			entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
++			mk_pte_huge(entry);
++			set_pmd(pmd, __pmd(pte_val(entry)));
++
++			printk(KERN_DEBUG " [%lx-%lx] PMD ->%p on node %d\n",
++				addr, addr + PMD_SIZE - 1, p, node);
++		} else
++			vmemmap_verify((pte_t *)pmd, node, addr, next);
++	}
++
++	return 0;
++}
++#endif
+--- head-2010-01-18.orig/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pageattr_64-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -17,9 +17,6 @@
+ #include <asm/pgalloc.h>
+ #include <asm/mmu_context.h>
+ 
+-LIST_HEAD(mm_unpinned);
+-DEFINE_SPINLOCK(mm_unpinned_lock);
+-
+ static void _pin_lock(struct mm_struct *mm, int lock) {
+ 	if (lock)
+ 		spin_lock(&mm->page_table_lock);
+@@ -81,8 +78,8 @@ static void _pin_lock(struct mm_struct *
+ #define PIN_BATCH 8
+ static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+ 
+-static inline unsigned int mm_walk_set_prot(void *pt, pgprot_t flags,
+-                                            unsigned int cpu, unsigned int seq)
++static inline unsigned int pgd_walk_set_prot(void *pt, pgprot_t flags,
++					     unsigned int cpu, unsigned int seq)
+ {
+ 	struct page *page = virt_to_page(pt);
+ 	unsigned long pfn = page_to_pfn(page);
+@@ -100,9 +97,9 @@ static inline unsigned int mm_walk_set_p
+ 	return seq;
+ }
+ 
+-static void mm_walk(struct mm_struct *mm, pgprot_t flags)
++static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
+ {
+-	pgd_t       *pgd;
++	pgd_t       *pgd = pgd_base;
+ 	pud_t       *pud;
+ 	pmd_t       *pmd;
+ 	pte_t       *pte;
+@@ -110,7 +107,6 @@ static void mm_walk(struct mm_struct *mm
+ 	unsigned int cpu, seq;
+ 	multicall_entry_t *mcl;
+ 
+-	pgd = mm->pgd;
+ 	cpu = get_cpu();
+ 
+ 	/*
+@@ -125,18 +121,18 @@ static void mm_walk(struct mm_struct *mm
+ 			continue;
+ 		pud = pud_offset(pgd, 0);
+ 		if (PTRS_PER_PUD > 1) /* not folded */ 
+-			seq = mm_walk_set_prot(pud,flags,cpu,seq);
++			seq = pgd_walk_set_prot(pud,flags,cpu,seq);
+ 		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+ 			if (pud_none(*pud))
+ 				continue;
+ 			pmd = pmd_offset(pud, 0);
+ 			if (PTRS_PER_PMD > 1) /* not folded */ 
+-				seq = mm_walk_set_prot(pmd,flags,cpu,seq);
++				seq = pgd_walk_set_prot(pmd,flags,cpu,seq);
+ 			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+ 				if (pmd_none(*pmd))
+ 					continue;
+ 				pte = pte_offset_kernel(pmd,0);
+-				seq = mm_walk_set_prot(pte,flags,cpu,seq);
++				seq = pgd_walk_set_prot(pte,flags,cpu,seq);
+ 			}
+ 		}
+ 	}
+@@ -148,12 +144,12 @@ static void mm_walk(struct mm_struct *mm
+ 		seq = 0;
+ 	}
+ 	MULTI_update_va_mapping(mcl + seq,
+-	       (unsigned long)__user_pgd(mm->pgd),
+-	       pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, flags),
++	       (unsigned long)__user_pgd(pgd_base),
++	       pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags),
+ 	       0);
+ 	MULTI_update_va_mapping(mcl + seq + 1,
+-	       (unsigned long)mm->pgd,
+-	       pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, flags),
++	       (unsigned long)pgd_base,
++	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+ 	       UVMF_TLB_FLUSH);
+ 	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
+ 		BUG();
+@@ -161,21 +157,35 @@ static void mm_walk(struct mm_struct *mm
+ 	put_cpu();
+ }
+ 
++static void __pgd_pin(pgd_t *pgd)
++{
++	pgd_walk(pgd, PAGE_KERNEL_RO);
++	xen_pgd_pin(__pa(pgd)); /* kernel */
++	xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */
++	SetPagePinned(virt_to_page(pgd));
++}
++
++static void __pgd_unpin(pgd_t *pgd)
++{
++	xen_pgd_unpin(__pa(pgd));
++	xen_pgd_unpin(__pa(__user_pgd(pgd)));
++	pgd_walk(pgd, PAGE_KERNEL);
++	ClearPagePinned(virt_to_page(pgd));
++}
++
++void pgd_test_and_unpin(pgd_t *pgd)
++{
++	if (PagePinned(virt_to_page(pgd)))
++		__pgd_unpin(pgd);
++}
++
+ void mm_pin(struct mm_struct *mm)
+ {
+ 	if (xen_feature(XENFEAT_writable_page_tables))
+ 		return;
+ 
+ 	pin_lock(mm);
+-
+-	mm_walk(mm, PAGE_KERNEL_RO);
+-	xen_pgd_pin(__pa(mm->pgd)); /* kernel */
+-	xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
+-	SetPagePinned(virt_to_page(mm->pgd));
+-	spin_lock(&mm_unpinned_lock);
+-	list_del(&mm->context.unpinned);
+-	spin_unlock(&mm_unpinned_lock);
+-
++	__pgd_pin(mm->pgd);
+ 	pin_unlock(mm);
+ }
+ 
+@@ -185,34 +195,30 @@ void mm_unpin(struct mm_struct *mm)
+ 		return;
+ 
+ 	pin_lock(mm);
+-
+-	xen_pgd_unpin(__pa(mm->pgd));
+-	xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
+-	mm_walk(mm, PAGE_KERNEL);
+-	ClearPagePinned(virt_to_page(mm->pgd));
+-	spin_lock(&mm_unpinned_lock);
+-	list_add(&mm->context.unpinned, &mm_unpinned);
+-	spin_unlock(&mm_unpinned_lock);
+-
++	__pgd_unpin(mm->pgd);
+ 	pin_unlock(mm);
+ }
+ 
+ void mm_pin_all(void)
+ {
++	struct page *page;
++	unsigned long flags;
++
+ 	if (xen_feature(XENFEAT_writable_page_tables))
+ 		return;
+ 
+ 	/*
+-	 * Allow uninterrupted access to the mm_unpinned list. We don't
+-	 * actually take the mm_unpinned_lock as it is taken inside mm_pin().
++	 * Allow uninterrupted access to the pgd_list. Also protects
++	 * __pgd_pin() by disabling preemption.
+ 	 * All other CPUs must be at a safe point (e.g., in stop_machine
+ 	 * or offlined entirely).
+ 	 */
+-	preempt_disable();
+-	while (!list_empty(&mm_unpinned))	
+-		mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
+-				  context.unpinned));
+-	preempt_enable();
++	spin_lock_irqsave(&pgd_lock, flags);
++	list_for_each_entry(page, &pgd_list, lru) {
++		if (!PagePinned(page))
++			__pgd_pin((pgd_t *)page_address(page));
++	}
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+ 
+ void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+@@ -331,11 +337,11 @@ static struct page *split_large_page(uns
+ 	return base;
+ } 
+ 
+-static void cache_flush_page(void *adr)
++void clflush_cache_range(void *adr, int size)
+ {
+ 	int i;
+-	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+-		asm volatile("clflush (%0)" :: "r" (adr + i));
++	for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size)
++		clflush(adr+i);
+ }
+ 
+ static void flush_kernel_map(void *arg)
+@@ -350,7 +356,7 @@ static void flush_kernel_map(void *arg)
+ 		asm volatile("wbinvd" ::: "memory");
+ 	else list_for_each_entry(pg, l, lru) {
+ 		void *adr = page_address(pg);
+-		cache_flush_page(adr);
++		clflush_cache_range(adr, PAGE_SIZE);
+ 	}
+ 	__flush_tlb_all();
+ }
+@@ -418,6 +424,7 @@ __change_page_attr(unsigned long address
+ 			split = split_large_page(address, prot, ref_prot2);
+ 			if (!split)
+ 				return -ENOMEM;
++			pgprot_val(ref_prot2) &= ~_PAGE_NX;
+ 			set_pte(kpte, mk_pte(split, ref_prot2));
+ 			kpte_page = split;
+ 		}
+@@ -510,9 +517,14 @@ void global_flush_tlb(void)
+ 	struct page *pg, *next;
+ 	struct list_head l;
+ 
+-	down_read(&init_mm.mmap_sem);
++	/*
++	 * Write-protect the semaphore, to exclude two contexts
++	 * doing a list_replace_init() call in parallel and to
++	 * exclude new additions to the deferred_pages list:
++	 */
++	down_write(&init_mm.mmap_sem);
+ 	list_replace_init(&deferred_pages, &l);
+-	up_read(&init_mm.mmap_sem);
++	up_write(&init_mm.mmap_sem);
+ 
+ 	flush_map(&l);
+ 
+--- head-2010-01-18.orig/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/mm/pgtable_32-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -6,6 +6,7 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
++#include <linux/nmi.h>
+ #include <linux/swap.h>
+ #include <linux/smp.h>
+ #include <linux/highmem.h>
+@@ -46,6 +47,8 @@ void show_mem(void)
+ 	for_each_online_pgdat(pgdat) {
+ 		pgdat_resize_lock(pgdat, &flags);
+ 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
++			if (unlikely(i % MAX_ORDER_NR_PAGES == 0))
++				touch_nmi_watchdog();
+ 			page = pgdat_page_nr(pgdat, i);
+ 			total++;
+ 			if (PageHighMem(page))
+@@ -206,7 +209,7 @@ void pte_free(struct page *pte)
+ 	__free_page(pte);
+ }
+ 
+-void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags)
++void pmd_ctor(struct kmem_cache *cache, void *pmd)
+ {
+ 	memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+ }
+--- head-2010-01-18.orig/arch/x86/pci/irq-xen.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/pci/irq-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -173,7 +173,7 @@ void eisa_set_level_irq(unsigned int irq
+ }
+ 
+ /*
+- * Common IRQ routing practice: nybbles in config space,
++ * Common IRQ routing practice: nibbles in config space,
+  * offset by some magic constant.
+  */
+ static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
+@@ -496,6 +496,26 @@ static int pirq_amd756_set(struct pci_de
+ 	return 1;
+ }
+ 
++/*
++ * PicoPower PT86C523
++ */
++static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
++{
++	outb(0x10 + ((pirq - 1) >> 1), 0x24);
++	return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf);
++}
++
++static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
++			int irq)
++{
++	unsigned int x;
++	outb(0x10 + ((pirq - 1) >> 1), 0x24);
++	x = inb(0x26);
++	x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq));
++	outb(x, 0x26);
++	return 1;
++}
++
+ #ifdef CONFIG_PCI_BIOS
+ 
+ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+@@ -569,7 +589,7 @@ static __init int via_router_probe(struc
+ 	/* FIXME: We should move some of the quirk fixup stuff here */
+ 
+ 	/*
+-	 * work arounds for some buggy BIOSes
++	 * workarounds for some buggy BIOSes
+ 	 */
+ 	if (device == PCI_DEVICE_ID_VIA_82C586_0) {
+ 		switch(router->device) {
+@@ -725,6 +745,24 @@ static __init int amd_router_probe(struc
+ 	return 1;
+ }
+ 		
++static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
++{
++	switch (device) {
++	case PCI_DEVICE_ID_PICOPOWER_PT86C523:
++		r->name = "PicoPower PT86C523";
++		r->get = pirq_pico_get;
++		r->set = pirq_pico_set;
++		return 1;
++
++	case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP:
++		r->name = "PicoPower PT86C523 rev. BB+";
++		r->get = pirq_pico_get;
++		r->set = pirq_pico_set;
++		return 1;
++	}
++	return 0;
++}
++
+ static __initdata struct irq_router_handler pirq_routers[] = {
+ 	{ PCI_VENDOR_ID_INTEL, intel_router_probe },
+ 	{ PCI_VENDOR_ID_AL, ali_router_probe },
+@@ -736,6 +774,7 @@ static __initdata struct irq_router_hand
+ 	{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
+ 	{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
+ 	{ PCI_VENDOR_ID_AMD, amd_router_probe },
++	{ PCI_VENDOR_ID_PICOPOWER, pico_router_probe },
+ 	/* Someone with docs needs to add the ATI Radeon IGP */
+ 	{ 0, NULL }
+ };
+@@ -1014,7 +1053,7 @@ static void __init pcibios_fixup_irqs(vo
+  * Work around broken HP Pavilion Notebooks which assign USB to
+  * IRQ 9 even though it is actually wired to IRQ 11
+  */
+-static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d)
++static int __init fix_broken_hp_bios_irq9(const struct dmi_system_id *d)
+ {
+ 	if (!broken_hp_bios_irq9) {
+ 		broken_hp_bios_irq9 = 1;
+@@ -1027,7 +1066,7 @@ static int __init fix_broken_hp_bios_irq
+  * Work around broken Acer TravelMate 360 Notebooks which assign
+  * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
+  */
+-static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d)
++static int __init fix_acer_tm360_irqrouting(const struct dmi_system_id *d)
+ {
+ 	if (!acer_tm360_irqrouting) {
+ 		acer_tm360_irqrouting = 1;
+--- head-2010-01-18.orig/drivers/acpi/processor_idle.c	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/drivers/acpi/processor_idle.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1153,6 +1153,14 @@ int acpi_processor_cst_has_changed(struc
+ 	if (!pr->flags.power_setup_done)
+ 		return -ENODEV;
+ 
++	if (processor_pm_external()) {
++		pr->flags.power = 0;
++		ret = acpi_processor_get_power_info(pr);
++		processor_notify_external(pr,
++			PROCESSOR_PM_CHANGE, PM_TYPE_IDLE);
++		return ret;
++	}
++
+ 	cpuidle_pause_and_lock();
+ 	cpuidle_disable_device(&pr->power.dev);
+ 	acpi_processor_get_power_info(pr);
+--- head-2010-01-18.orig/drivers/cpuidle/Kconfig	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/drivers/cpuidle/Kconfig	2009-11-06 10:51:17.000000000 +0100
+@@ -1,6 +1,7 @@
+ 
+ config CPU_IDLE
+ 	bool "CPU idle PM support"
++	depends on !PROCESSOR_EXTERNAL_CONTROL
+ 	default ACPI
+ 	help
+ 	  CPU idle is a generic framework for supporting software-controlled
+--- head-2010-01-18.orig/drivers/pci/msi-xen.c	2009-12-04 10:56:57.000000000 +0100
++++ head-2010-01-18/drivers/pci/msi-xen.c	2009-12-04 11:01:50.000000000 +0100
+@@ -260,6 +260,12 @@ static int msi_map_vector(struct pci_dev
+ 		map_irq.pirq : evtchn_map_pirq(-1, map_irq.pirq));
+ }
+ 
++static void pci_intx_for_msi(struct pci_dev *dev, int enable)
++{
++	if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
++		pci_intx(dev, enable);
++}
++
+ #ifdef CONFIG_PM
+ void pci_restore_msi_state(struct pci_dev *dev)
+ {
+@@ -269,7 +275,7 @@ void pci_restore_msi_state(struct pci_de
+ 	if (!dev->msi_enabled && !dev->msix_enabled)
+ 		return;
+ 
+-	pci_intx(dev, 0);		/* disable intx */
++	pci_intx_for_msi(dev, 0);
+ 	if (dev->msi_enabled)
+ 		msi_set_enable(dev, 0);
+ 	if (dev->msix_enabled)
+@@ -306,7 +312,7 @@ static int msi_capability_init(struct pc
+ 		return -EBUSY;
+ 
+ 	/* Set MSI enabled bits	 */
+-	pci_intx(dev, 0);		/* disable intx */
++	pci_intx_for_msi(dev, 0);
+ 	msi_set_enable(dev, 1);
+ 	dev->msi_enabled = 1;
+ 
+@@ -380,7 +386,7 @@ static int msix_capability_init(struct p
+ 		return avail;
+ 	}
+ 
+-	pci_intx(dev, 0);		/* disable intx */
++	pci_intx_for_msi(dev, 0);
+ 	msix_set_enable(dev, 1);
+ 	dev->msix_enabled = 1;
+ 
+@@ -516,7 +522,7 @@ void pci_disable_msi(struct pci_dev* dev
+ 
+ 	/* Disable MSI mode */
+ 	msi_set_enable(dev, 0);
+-	pci_intx(dev, 1);		/* enable intx */
++	pci_intx_for_msi(dev, 1);
+ 	dev->msi_enabled = 0;
+ }
+ EXPORT_SYMBOL(pci_disable_msi);
+@@ -653,7 +659,7 @@ void pci_disable_msix(struct pci_dev* de
+ 
+ 	/* Disable MSI mode */
+ 	msix_set_enable(dev, 0);
+-	pci_intx(dev, 1);		/* enable intx */
++	pci_intx_for_msi(dev, 1);
+ 	dev->msix_enabled = 0;
+ }
+ EXPORT_SYMBOL(pci_disable_msix);
+--- head-2010-01-18.orig/drivers/oprofile/cpu_buffer.c	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/drivers/oprofile/cpu_buffer.c	2009-11-06 10:51:17.000000000 +0100
+@@ -443,6 +443,39 @@ void oprofile_add_pc(unsigned long pc, i
+ 	log_sample(cpu_buf, pc, 0, is_kernel, event);
+ }
+ 
++#ifdef CONFIG_XEN
++/*
++ * This is basically log_sample(b, ESCAPE_CODE, cpu_mode, CPU_TRACE_BEGIN),
++ * as was previously accessible through oprofile_add_pc().
++ */
++void oprofile_add_mode(int cpu_mode)
++{
++	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
++	struct task_struct *task;
++
++	if (nr_available_slots(cpu_buf) < 3) {
++		cpu_buf->sample_lost_overflow++;
++		return;
++	}
++
++	task = current;
++
++	/* notice a switch from user->kernel or vice versa */
++	if (cpu_buf->last_cpu_mode != cpu_mode) {
++		cpu_buf->last_cpu_mode = cpu_mode;
++		add_code(cpu_buf, cpu_mode);
++	}
++
++	/* notice a task switch */
++	if (cpu_buf->last_task != task) {
++		cpu_buf->last_task = task;
++		add_code(cpu_buf, (unsigned long)task);
++	}
++
++	add_code(cpu_buf, CPU_TRACE_BEGIN);
++}
++#endif
++
+ void oprofile_add_trace(unsigned long pc)
+ {
+ 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+--- head-2010-01-18.orig/drivers/xen/balloon/balloon.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/balloon/balloon.c	2009-11-06 10:51:17.000000000 +0100
+@@ -312,6 +312,8 @@ static int increase_reservation(unsigned
+ 
+ #ifndef MODULE
+ 	setup_per_zone_pages_min();
++	if (rc > 0)
++		kswapd_run(0);
+ 	if (need_zonelists_rebuild)
+ 		build_all_zonelists();
+ 	else
+--- head-2010-01-18.orig/drivers/xen/blkback/blkback.c	2010-01-04 12:31:12.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkback/blkback.c	2010-01-04 12:35:54.000000000 +0100
+@@ -272,13 +272,10 @@ static void __end_block_io_op(pending_re
+ 	}
+ }
+ 
+-static int end_block_io_op(struct bio *bio, unsigned int done, int error)
++static void end_block_io_op(struct bio *bio, int error)
+ {
+-	if (bio->bi_size != 0)
+-		return 1;
+ 	__end_block_io_op(bio->bi_private, error);
+ 	bio_put(bio);
+-	return error;
+ }
+ 
+ 
+--- head-2010-01-18.orig/drivers/xen/blkfront/blkfront.c	2010-01-18 16:18:57.000000000 +0100
++++ head-2010-01-18/drivers/xen/blkfront/blkfront.c	2010-01-18 16:19:12.000000000 +0100
+@@ -233,7 +233,7 @@ static int setup_blkring(struct xenbus_d
+ 	SHARED_RING_INIT(sring);
+ 	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
+ 
+-	memset(info->sg, 0, sizeof(info->sg));
++	sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ 
+ 	err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
+ 	if (err < 0) {
+@@ -634,9 +634,8 @@ static int blkif_queue_request(struct re
+ 
+ 	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+ 	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+-	for (i = 0; i < ring_req->nr_segments; ++i) {
+-			sg = info->sg + i;
+-			buffer_mfn = page_to_phys(sg->page) >> PAGE_SHIFT;
++	for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
++			buffer_mfn = page_to_phys(sg_page(sg)) >> PAGE_SHIFT;
+ 			fsect = sg->offset >> 9;
+ 			lsect = fsect + (sg->length >> 9) - 1;
+ 			/* install a grant reference. */
+--- head-2010-01-18.orig/drivers/xen/blktap2/control.c	2009-12-16 11:43:21.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/control.c	2009-11-06 10:51:17.000000000 +0100
+@@ -18,6 +18,7 @@ blktap_control_initialize_tap(struct blk
+ 	memset(tap, 0, sizeof(*tap));
+ 	set_bit(BLKTAP_CONTROL, &tap->dev_inuse);
+ 	init_rwsem(&tap->tap_sem);
++	sg_init_table(tap->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+ 	init_waitqueue_head(&tap->wq);
+ 	atomic_set(&tap->refcnt, 0);
+ 
+--- head-2010-01-18.orig/drivers/xen/blktap2/device.c	2010-01-04 12:30:58.000000000 +0100
++++ head-2010-01-18/drivers/xen/blktap2/device.c	2010-01-04 12:36:00.000000000 +0100
+@@ -665,8 +665,7 @@ blktap_device_process_request(struct blk
+ 	request->nr_pages = 0;
+ 	blkif_req.nr_segments = blk_rq_map_sg(req->q, req, tap->sg);
+ 	BUG_ON(blkif_req.nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+-	for (i = 0; i < blkif_req.nr_segments; ++i) {
+-			sg = tap->sg + i;
++	for_each_sg(tap->sg, sg, blkif_req.nr_segments, i) {
+ 			fsect = sg->offset >> 9;
+ 			lsect = fsect + (sg->length >> 9) - 1;
+ 			nr_sects += sg->length >> 9;
+@@ -677,13 +676,13 @@ blktap_device_process_request(struct blk
+ 				.first_sect = fsect,
+ 				.last_sect  = lsect };
+ 
+-			if (PageBlkback(sg->page)) {
++			if (PageBlkback(sg_page(sg))) {
+ 				/* foreign page -- use xen */
+ 				if (blktap_prep_foreign(tap,
+ 							request,
+ 							&blkif_req,
+ 							i,
+-							sg->page,
++							sg_page(sg),
+ 							&table))
+ 					goto out;
+ 			} else {
+@@ -691,7 +690,7 @@ blktap_device_process_request(struct blk
+ 				if (blktap_map(tap,
+ 					       request,
+ 					       i,
+-					       sg->page))
++					       sg_page(sg)))
+ 					goto out;
+ 			}
+ 
+--- head-2010-01-18.orig/drivers/xen/core/firmware.c	2007-06-22 09:08:06.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/firmware.c	2009-11-06 10:51:17.000000000 +0100
+@@ -1,4 +1,5 @@
+ #include <linux/kernel.h>
++#include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/edd.h>
+--- head-2010-01-18.orig/drivers/xen/core/machine_kexec.c	2009-07-13 14:25:35.000000000 +0200
++++ head-2010-01-18/drivers/xen/core/machine_kexec.c	2009-11-06 10:51:17.000000000 +0100
+@@ -29,6 +29,10 @@ void __init xen_machine_kexec_setup_reso
+ 	int k = 0;
+ 	int rc;
+ 
++	if (strstr(boot_command_line, "crashkernel="))
++		printk(KERN_WARNING "Ignoring crashkernel command line, "
++		       "parameter will be supplied by xen\n");
++
+ 	if (!is_initial_xendomain())
+ 		return;
+ 
+@@ -130,6 +134,13 @@ void __init xen_machine_kexec_setup_reso
+ 					  xen_max_nr_phys_cpus))
+ 		goto err;
+ 
++#ifdef CONFIG_X86
++	if (xen_create_contiguous_region((unsigned long)&vmcoreinfo_note,
++					 get_order(sizeof(vmcoreinfo_note)),
++					 BITS_PER_LONG))
++		goto err;
++#endif
++
+ 	return;
+ 
+  err:
+@@ -213,6 +224,13 @@ NORET_TYPE void machine_kexec(struct kim
+ 	panic("KEXEC_CMD_kexec hypercall should not return\n");
+ }
+ 
++#ifdef CONFIG_X86
++unsigned long paddr_vmcoreinfo_note(void)
++{
++	return virt_to_machine(&vmcoreinfo_note);
++}
++#endif
++
+ void machine_shutdown(void)
+ {
+ 	/* do nothing */
+--- head-2010-01-18.orig/drivers/xen/core/smpboot.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/core/smpboot.c	2009-11-06 10:51:17.000000000 +0100
+@@ -45,8 +45,8 @@ cpumask_t cpu_possible_map;
+ EXPORT_SYMBOL(cpu_possible_map);
+ cpumask_t cpu_initialized_map;
+ 
+-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
+-EXPORT_SYMBOL(cpu_data);
++DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info);
++EXPORT_PER_CPU_SYMBOL(cpu_info);
+ 
+ static DEFINE_PER_CPU(int, resched_irq);
+ static DEFINE_PER_CPU(int, callfunc_irq);
+@@ -55,12 +55,12 @@ static char callfunc_name[NR_CPUS][15];
+ 
+ u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+ 
+-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
++DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
++DEFINE_PER_CPU(cpumask_t, cpu_core_map);
+ 
+ #if defined(__i386__)
+-u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
+-EXPORT_SYMBOL(x86_cpu_to_apicid);
++DEFINE_PER_CPU(u8, x86_cpu_to_apicid) = BAD_APICID;
++EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+ #endif
+ 
+ void __init prefill_possible_map(void)
+@@ -85,25 +85,25 @@ void __init smp_alloc_memory(void)
+ static inline void
+ set_cpu_sibling_map(unsigned int cpu)
+ {
+-	cpu_data[cpu].phys_proc_id = cpu;
+-	cpu_data[cpu].cpu_core_id  = 0;
++	cpu_data(cpu).phys_proc_id = cpu;
++	cpu_data(cpu).cpu_core_id  = 0;
+ 
+-	cpu_sibling_map[cpu] = cpumask_of_cpu(cpu);
+-	cpu_core_map[cpu]    = cpumask_of_cpu(cpu);
++	per_cpu(cpu_sibling_map, cpu) = cpumask_of_cpu(cpu);
++	per_cpu(cpu_core_map, cpu) = cpumask_of_cpu(cpu);
+ 
+-	cpu_data[cpu].booted_cores = 1;
++	cpu_data(cpu).booted_cores = 1;
+ }
+ 
+ static void
+ remove_siblinginfo(unsigned int cpu)
+ {
+-	cpu_data[cpu].phys_proc_id = BAD_APICID;
+-	cpu_data[cpu].cpu_core_id  = BAD_APICID;
++	cpu_data(cpu).phys_proc_id = BAD_APICID;
++	cpu_data(cpu).cpu_core_id  = BAD_APICID;
+ 
+-	cpus_clear(cpu_sibling_map[cpu]);
+-	cpus_clear(cpu_core_map[cpu]);
++	cpus_clear(per_cpu(cpu_sibling_map, cpu));
++	cpus_clear(per_cpu(cpu_core_map, cpu));
+ 
+-	cpu_data[cpu].booted_cores = 0;
++	cpu_data(cpu).booted_cores = 0;
+ }
+ 
+ static int __cpuinit xen_smp_intr_init(unsigned int cpu)
+@@ -162,9 +162,9 @@ void __cpuinit cpu_bringup(void)
+ {
+ 	cpu_init();
+ #ifdef __i386__
+-	identify_secondary_cpu(cpu_data + smp_processor_id());
++	identify_secondary_cpu(&current_cpu_data);
+ #else
+-	identify_cpu(cpu_data + smp_processor_id());
++	identify_cpu(&current_cpu_data);
+ #endif
+ 	touch_softlockup_watchdog();
+ 	preempt_disable();
+@@ -265,16 +265,16 @@ void __init smp_prepare_cpus(unsigned in
+ 	if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, 0, &cpu_id) == 0)
+ 		apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
+ 	boot_cpu_data.apicid = apicid;
+-	cpu_data[0] = boot_cpu_data;
++	cpu_data(0) = boot_cpu_data;
+ 
+ 	cpu_2_logical_apicid[0] = apicid;
+-	x86_cpu_to_apicid[0] = apicid;
++	per_cpu(x86_cpu_to_apicid, 0) = apicid;
+ 
+ 	current_thread_info()->cpu = 0;
+ 
+ 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+-		cpus_clear(cpu_sibling_map[cpu]);
+-		cpus_clear(cpu_core_map[cpu]);
++		cpus_clear(per_cpu(cpu_sibling_map, cpu));
++		cpus_clear(per_cpu(cpu_core_map, cpu));
+ 	}
+ 
+ 	set_cpu_sibling_map(0);
+@@ -319,11 +319,12 @@ void __init smp_prepare_cpus(unsigned in
+ 		apicid = cpu;
+ 		if (HYPERVISOR_vcpu_op(VCPUOP_get_physid, cpu, &cpu_id) == 0)
+ 			apicid = xen_vcpu_physid_to_x86_apicid(cpu_id.phys_id);
+-		cpu_data[cpu] = boot_cpu_data;
+-		cpu_data[cpu].apicid = apicid;
++		cpu_data(cpu) = boot_cpu_data;
++		cpu_data(cpu).cpu_index = cpu;
++		cpu_data(cpu).apicid = apicid;
+ 
+ 		cpu_2_logical_apicid[cpu] = apicid;
+-		x86_cpu_to_apicid[cpu] = apicid;
++		per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+ 
+ #ifdef __x86_64__
+ 		cpu_pda(cpu)->pcurrent = idle;
+--- head-2010-01-18.orig/drivers/xen/netback/loopback.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/loopback.c	2009-11-06 10:51:17.000000000 +0100
+@@ -285,9 +285,9 @@ static void __exit clean_loopback(int i)
+ 	char dev_name[IFNAMSIZ];
+ 
+ 	sprintf(dev_name, "vif0.%d", i);
+-	dev1 = dev_get_by_name(dev_name);
++	dev1 = dev_get_by_name(&init_net, dev_name);
+ 	sprintf(dev_name, "veth%d", i);
+-	dev2 = dev_get_by_name(dev_name);
++	dev2 = dev_get_by_name(&init_net, dev_name);
+ 	if (dev1 && dev2) {
+ 		unregister_netdev(dev2);
+ 		unregister_netdev(dev1);
+--- head-2010-01-18.orig/drivers/xen/netback/netback.c	2010-01-04 12:26:56.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/netback.c	2009-11-06 10:51:17.000000000 +0100
+@@ -353,8 +353,8 @@ static void xen_network_done_notify(void
+ {
+ 	static struct net_device *eth0_dev = NULL;
+ 	if (unlikely(eth0_dev == NULL))
+-		eth0_dev = __dev_get_by_name("eth0");
+-	netif_rx_schedule(eth0_dev);
++		eth0_dev = __dev_get_by_name(&init_net, "eth0");
++	netif_rx_schedule(eth0_dev, ???);
+ }
+ /* 
+  * Add following to poll() function in NAPI driver (Tigon3 is example):
+--- head-2010-01-18.orig/drivers/xen/netback/xenbus.c	2009-11-06 10:46:41.000000000 +0100
++++ head-2010-01-18/drivers/xen/netback/xenbus.c	2009-11-06 10:51:17.000000000 +0100
+@@ -149,12 +149,10 @@ fail:
+  * and vif variables to the environment, for the benefit of the vif-* hotplug
+  * scripts.
+  */
+-static int netback_uevent(struct xenbus_device *xdev, char **envp,
+-			  int num_envp, char *buffer, int buffer_size)
++static int netback_uevent(struct xenbus_device *xdev, struct kobj_uevent_env *env)
+ {
+ 	struct backend_info *be = xdev->dev.driver_data;
+ 	netif_t *netif = be->netif;
+-	int i = 0, length = 0;
+ 	char *val;
+ 
+ 	DPRINTK("netback_uevent");
+@@ -166,15 +164,11 @@ static int netback_uevent(struct xenbus_
+ 		return err;
+ 	}
+ 	else {
+-		add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+-			       &length, "script=%s", val);
++		add_uevent_var(env, "script=%s", val);
+ 		kfree(val);
+ 	}
+ 
+-	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+-		       "vif=%s", netif->dev->name);
+-
+-	envp[i] = NULL;
++	add_uevent_var(env, "vif=%s", netif->dev->name);
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/drivers/xen/netfront/accel.c	2009-05-04 10:01:03.000000000 +0200
++++ head-2010-01-18/drivers/xen/netfront/accel.c	2009-11-06 10:51:17.000000000 +0100
+@@ -325,7 +325,7 @@ accelerator_set_vif_state_hooks(struct n
+ 	DPRINTK("%p\n",vif_state);
+ 
+ 	/* Make sure there are no data path operations going on */
+-	netif_poll_disable(vif_state->np->netdev);
++	napi_disable(&vif_state->np->napi);
+ 	netif_tx_lock_bh(vif_state->np->netdev);
+ 
+ 	accelerator = vif_state->np->accelerator;
+@@ -334,7 +334,7 @@ accelerator_set_vif_state_hooks(struct n
+ 	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+ 
+ 	netif_tx_unlock_bh(vif_state->np->netdev);
+-	netif_poll_enable(vif_state->np->netdev);
++	napi_enable(&vif_state->np->napi);
+ }
+ 
+ 
+@@ -508,7 +508,7 @@ accelerator_remove_single_hook(struct ne
+ 	unsigned long flags;
+ 
+ 	/* Make sure there are no data path operations going on */
+-	netif_poll_disable(vif_state->np->netdev);
++	napi_disable(&vif_state->np->napi);
+ 	netif_tx_lock_bh(vif_state->np->netdev);
+ 
+ 	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+@@ -524,7 +524,7 @@ accelerator_remove_single_hook(struct ne
+ 	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+ 
+ 	netif_tx_unlock_bh(vif_state->np->netdev);
+-	netif_poll_enable(vif_state->np->netdev);		       
++	napi_enable(&vif_state->np->napi);
+ }
+ 
+ 
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.c	2009-11-06 10:51:17.000000000 +0100
+@@ -626,6 +626,7 @@ static int network_open(struct net_devic
+ 	struct netfront_info *np = netdev_priv(dev);
+ 
+ 	memset(&np->stats, 0, sizeof(np->stats));
++	napi_enable(&np->napi);
+ 
+ 	spin_lock_bh(&np->rx_lock);
+ 	if (netfront_carrier_ok(np)) {
+@@ -634,7 +635,7 @@ static int network_open(struct net_devic
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(dev);
++			netif_rx_schedule(dev, &np->napi);
+ 		}
+ 	}
+ 	spin_unlock_bh(&np->rx_lock);
+@@ -706,7 +707,7 @@ static void rx_refill_timeout(unsigned l
+ 
+ 	netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-	netif_rx_schedule(dev);
++	netif_rx_schedule(dev, &np->napi);
+ }
+ 
+ static void network_alloc_rx_buffers(struct net_device *dev)
+@@ -1063,7 +1064,7 @@ static irqreturn_t netif_int(int irq, vo
+ 		if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
+ 			netfront_accelerator_call_stop_napi_irq(np, dev);
+ 
+-			netif_rx_schedule(dev);
++			netif_rx_schedule(dev, &np->napi);
+ 			dev->last_rx = jiffies;
+ 		}
+ 	}
+@@ -1316,16 +1317,17 @@ static int xennet_set_skb_gso(struct sk_
+ #endif
+ }
+ 
+-static int netif_poll(struct net_device *dev, int *pbudget)
++static int netif_poll(struct napi_struct *napi, int budget)
+ {
+-	struct netfront_info *np = netdev_priv(dev);
++	struct netfront_info *np = container_of(napi, struct netfront_info, napi);
++	struct net_device *dev = np->netdev;
+ 	struct sk_buff *skb;
+ 	struct netfront_rx_info rinfo;
+ 	struct netif_rx_response *rx = &rinfo.rx;
+ 	struct netif_extra_info *extras = rinfo.extras;
+ 	RING_IDX i, rp;
+ 	struct multicall_entry *mcl;
+-	int work_done, budget, more_to_do = 1, accel_more_to_do = 1;
++	int work_done, more_to_do = 1, accel_more_to_do = 1;
+ 	struct sk_buff_head rxq;
+ 	struct sk_buff_head errq;
+ 	struct sk_buff_head tmpq;
+@@ -1345,8 +1347,6 @@ static int netif_poll(struct net_device 
+ 	skb_queue_head_init(&errq);
+ 	skb_queue_head_init(&tmpq);
+ 
+-	if ((budget = *pbudget) > dev->quota)
+-		budget = dev->quota;
+ 	rp = np->rx.sring->rsp_prod;
+ 	rmb(); /* Ensure we see queued responses up to 'rp'. */
+ 
+@@ -1508,9 +1508,6 @@ err:	
+ 			accel_more_to_do = 0;
+ 	}
+ 
+-	*pbudget   -= work_done;
+-	dev->quota -= work_done;
+-
+ 	if (work_done < budget) {
+ 		local_irq_save(flags);
+ 
+@@ -1527,14 +1524,14 @@ err:	
+ 		}
+ 
+ 		if (!more_to_do && !accel_more_to_do)
+-			__netif_rx_complete(dev);
++			__netif_rx_complete(dev, napi);
+ 
+ 		local_irq_restore(flags);
+ 	}
+ 
+ 	spin_unlock(&np->rx_lock);
+ 	
+-	return more_to_do | accel_more_to_do;
++	return work_done;
+ }
+ 
+ static void netif_release_tx_bufs(struct netfront_info *np)
+@@ -1681,6 +1678,7 @@ static int network_close(struct net_devi
+ {
+ 	struct netfront_info *np = netdev_priv(dev);
+ 	netif_stop_queue(np->netdev);
++	napi_disable(&np->napi);
+ 	return 0;
+ }
+ 
+@@ -2088,16 +2086,14 @@ static struct net_device * __devinit cre
+ 	netdev->hard_start_xmit = network_start_xmit;
+ 	netdev->stop            = network_close;
+ 	netdev->get_stats       = network_get_stats;
+-	netdev->poll            = netif_poll;
++	netif_napi_add(netdev, &np->napi, netif_poll, 64);
+ 	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;
+ 
+ 	SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+-	SET_MODULE_OWNER(netdev);
+ 	SET_NETDEV_DEV(netdev, &dev->dev);
+ 
+ 	np->netdev = netdev;
+--- head-2010-01-18.orig/drivers/xen/netfront/netfront.h	2008-01-07 13:19:18.000000000 +0100
++++ head-2010-01-18/drivers/xen/netfront/netfront.h	2009-11-06 10:51:17.000000000 +0100
+@@ -157,6 +157,8 @@ struct netfront_info {
+ 	spinlock_t   tx_lock;
+ 	spinlock_t   rx_lock;
+ 
++	struct napi_struct	napi;
++
+ 	unsigned int irq;
+ 	unsigned int copying_receiver;
+ 	unsigned int carrier;
+--- head-2010-01-18.orig/drivers/xen/pciback/Makefile	2008-07-21 11:00:33.000000000 +0200
++++ head-2010-01-18/drivers/xen/pciback/Makefile	2009-11-06 10:51:17.000000000 +0100
+@@ -12,6 +12,4 @@ pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT
+ 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
++ccflags-$(CONFIG_XEN_PCIDEV_BE_DEBUG) += -DDEBUG
+--- head-2010-01-18.orig/drivers/xen/pcifront/Makefile	2007-06-12 13:13:45.000000000 +0200
++++ head-2010-01-18/drivers/xen/pcifront/Makefile	2009-11-06 10:51:17.000000000 +0100
+@@ -2,6 +2,4 @@ obj-y += pcifront.o
+ 
+ pcifront-y := pci_op.o xenbus.o pci.o
+ 
+-ifeq ($(CONFIG_XEN_PCIDEV_FE_DEBUG),y)
+-EXTRA_CFLAGS += -DDEBUG
+-endif
++ccflags-$(CONFIG_XEN_PCIDEV_FE_DEBUG) += -DDEBUG
+--- head-2010-01-18.orig/drivers/xen/scsiback/emulate.c	2009-03-18 10:39:32.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/emulate.c	2009-11-06 10:51:17.000000000 +0100
+@@ -109,9 +109,10 @@ static void resp_not_supported_cmd(pendi
+ }
+ 
+ 
+-static int __copy_to_sg(struct scatterlist *sg, unsigned int nr_sg,
++static int __copy_to_sg(struct scatterlist *sgl, unsigned int nr_sg,
+ 	       void *buf, unsigned int buflen)
+ {
++	struct scatterlist *sg;
+ 	void *from = buf;
+ 	void *to;
+ 	unsigned int from_rest = buflen;
+@@ -120,8 +121,8 @@ static int __copy_to_sg(struct scatterli
+ 	unsigned int i;
+ 	unsigned long pfn;
+ 
+-	for (i = 0; i < nr_sg; i++) {
+-		if (sg->page == NULL) {
++	for_each_sg (sgl, sg, nr_sg, i) {
++		if (sg_page(sg) == NULL) {
+ 			printk(KERN_WARNING "%s: inconsistent length field in "
+ 			       "scatterlist\n", __FUNCTION__);
+ 			return -ENOMEM;
+@@ -130,7 +131,7 @@ static int __copy_to_sg(struct scatterli
+ 		to_capa  = sg->length;
+ 		copy_size = min_t(unsigned int, to_capa, from_rest);
+ 
+-		pfn = page_to_pfn(sg->page);
++		pfn = page_to_pfn(sg_page(sg));
+ 		to = pfn_to_kaddr(pfn) + (sg->offset);
+ 		memcpy(to, from, copy_size);
+ 
+@@ -139,7 +140,6 @@ static int __copy_to_sg(struct scatterli
+ 			return 0;
+ 		}
+ 		
+-		sg++;
+ 		from += copy_size;
+ 	}
+ 
+@@ -148,9 +148,10 @@ static int __copy_to_sg(struct scatterli
+ 	return -ENOMEM;
+ }
+ 
+-static int __copy_from_sg(struct scatterlist *sg, unsigned int nr_sg,
++static int __copy_from_sg(struct scatterlist *sgl, unsigned int nr_sg,
+ 		 void *buf, unsigned int buflen)
+ {
++	struct scatterlist *sg;
+ 	void *from;
+ 	void *to = buf;
+ 	unsigned int from_rest;
+@@ -159,8 +160,8 @@ static int __copy_from_sg(struct scatter
+ 	unsigned int i;
+ 	unsigned long pfn;
+ 
+-	for (i = 0; i < nr_sg; i++) {
+-		if (sg->page == NULL) {
++	for_each_sg (sgl, sg, nr_sg, i) {
++		if (sg_page(sg) == NULL) {
+ 			printk(KERN_WARNING "%s: inconsistent length field in "
+ 			       "scatterlist\n", __FUNCTION__);
+ 			return -ENOMEM;
+@@ -175,13 +176,11 @@ static int __copy_from_sg(struct scatter
+ 		}
+ 		copy_size = from_rest;
+ 
+-		pfn = page_to_pfn(sg->page);
++		pfn = page_to_pfn(sg_page(sg));
+ 		from = pfn_to_kaddr(pfn) + (sg->offset);
+ 		memcpy(to, from, copy_size);
+ 
+ 		to_capa  -= copy_size;
+-		
+-		sg++;
+ 		to += copy_size;
+ 	}
+ 
+--- head-2010-01-18.orig/drivers/xen/scsiback/scsiback.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsiback/scsiback.c	2010-01-04 12:35:40.000000000 +0100
+@@ -260,6 +260,8 @@ static int scsiback_gnttab_data_map(vscs
+ 	write = (data_dir == DMA_TO_DEVICE);
+ 
+ 	if (nr_segments) {
++		struct scatterlist *sg;
++
+ 		/* free of (sgl) in fast_flush_area()*/
+ 		pending_req->sgl = kmalloc(sizeof(struct scatterlist) * nr_segments,
+ 						GFP_KERNEL);
+@@ -268,6 +270,8 @@ static int scsiback_gnttab_data_map(vscs
+ 			return -ENOMEM;
+ 		}
+ 
++		sg_init_table(pending_req->sgl, nr_segments);
++
+ 		for (i = 0; i < nr_segments; i++) {
+ 			flags = GNTMAP_host_map;
+ 			if (write)
+@@ -291,7 +295,7 @@ static int scsiback_gnttab_data_map(vscs
+             }
+         }
+ 
+-		for (i = 0; i < nr_segments; i++) {
++		for_each_sg (pending_req->sgl, sg, nr_segments, i) {
+ 			struct page *pg;
+ 
+ 			if (unlikely(map[i].status != 0)) {
+@@ -310,15 +314,14 @@ static int scsiback_gnttab_data_map(vscs
+ 			set_phys_to_machine(page_to_pfn(pg),
+ 				FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
+ 
+-			pending_req->sgl[i].page   = pg;
+-			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;
++			sg_set_page(sg, pg, ring_req->seg[i].length,
++				    ring_req->seg[i].offset);
++			data_len += sg->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)
++			if (sg->offset >= PAGE_SIZE ||
++			    sg->length > PAGE_SIZE ||
++			    sg->offset + sg->length > PAGE_SIZE)
+ 				err |= 1;
+ 
+ 		}
+@@ -347,27 +350,14 @@ static int scsiback_merge_bio(struct req
+ 
+ 	blk_queue_bounce(q, &bio);
+ 
+-	if (!rq->bio)
+-		blk_rq_bio_prep(q, rq, bio);
+-	else if (!ll_back_merge_fn(q, rq, bio))
+-		return -EINVAL;
+-	else {
+-		rq->biotail->bi_next = bio;
+-		rq->biotail          = bio;
+-	}
+-
+-	return 0;
++	return blk_rq_append_bio(q, rq, bio);
+ }
+ 
+ 
+ /* quoted scsi_lib.c/scsi_bi_endio */
+-static int scsiback_bi_endio(struct bio *bio, unsigned int bytes_done, int error)
++static void scsiback_bi_endio(struct bio *bio, int error)
+ {
+-	if (bio->bi_size)
+-		return 1;
+-
+ 	bio_put(bio);
+-	return 0;
+ }
+ 
+ 
+@@ -378,16 +368,16 @@ static int request_map_sg(struct request
+ 	struct request_queue *q = rq->q;
+ 	int nr_pages;
+ 	unsigned int nsegs = count;
+-
+ 	unsigned int data_len = 0, len, bytes, off;
++	struct scatterlist *sg;
+ 	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;
++	for_each_sg (pending_req->sgl, sg, nsegs, i) {
++		page = sg_page(sg);
++		off = sg->offset;
++		len = sg->length;
+ 		data_len += len;
+ 
+ 		nr_pages = (len + off + PAGE_SIZE - 1) >> PAGE_SHIFT;
+@@ -415,7 +405,7 @@ static int request_map_sg(struct request
+ 			if (bio->bi_vcnt >= nr_vecs) {
+ 				err = scsiback_merge_bio(rq, bio);
+ 				if (err) {
+-					bio_endio(bio, bio->bi_size, 0);
++					bio_endio(bio, 0);
+ 					goto free_bios;
+ 				}
+ 				bio = NULL;
+@@ -438,7 +428,7 @@ free_bios:
+ 		/*
+ 		 * call endio instead of bio_put incase it was bounced
+ 		 */
+-		bio_endio(bio, bio->bi_size, 0);
++		bio_endio(bio, 0);
+ 	}
+ 
+ 	return err;
+--- head-2010-01-18.orig/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/scsifront/scsifront.c	2009-11-06 10:51:17.000000000 +0100
+@@ -246,11 +246,10 @@ static int map_data_for_request(struct v
+ {
+ 	grant_ref_t gref_head;
+ 	struct page *page;
+-	int err, i, ref, ref_cnt = 0;
++	int err, ref, ref_cnt = 0;
+ 	int write = (sc->sc_data_direction == DMA_TO_DEVICE);
+-	int nr_pages, off, len, bytes;
++	unsigned int i, nr_pages, off, len, bytes;
+ 	unsigned long buffer_pfn;
+-	unsigned int data_len = 0;
+ 
+ 	if (sc->sc_data_direction == DMA_NONE)
+ 		return 0;
+@@ -263,25 +262,31 @@ static int map_data_for_request(struct v
+ 
+ 	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;
++		struct scatterlist *sg, *sgl = (struct scatterlist *)sc->request_buffer;
++		unsigned int data_len = sc->request_bufflen;
+ 
++		nr_pages = (sc->request_bufflen + sgl->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;
++		for_each_sg (sgl, sg, sc->use_sg, i) {
++			page = sg_page(sg);
++			off = sg->offset;
++			len = sg->length;
+ 
+ 			buffer_pfn = page_to_phys(page) >> PAGE_SHIFT;
+ 
+-			while (len > 0) {
++			while (len > 0 && data_len > 0) {
++				/*
++				 * sg sends a scatterlist that is larger than
++				 * the data_len it wants transferred for certain
++				 * IO sizes
++				 */
+ 				bytes = min_t(unsigned int, len, PAGE_SIZE - off);
++				bytes = min(bytes, data_len);
+ 				
+ 				ref = gnttab_claim_grant_reference(&gref_head);
+ 				BUG_ON(ref == -ENOSPC);
+@@ -296,6 +301,7 @@ static int map_data_for_request(struct v
+ 
+ 				buffer_pfn++;
+ 				len -= bytes;
++				data_len -= bytes;
+ 				off = 0;
+ 				ref_cnt++;
+ 			}
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_fwd.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_fwd.c	2009-11-06 10:51:17.000000000 +0100
+@@ -181,10 +181,11 @@ int netback_accel_fwd_add(const __u8 *ma
+ 	unsigned long flags;
+ 	cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
+ 	struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++	DECLARE_MAC_BUF(buf);
+ 
+ 	BUG_ON(fwd_priv == NULL);
+ 
+-	DPRINTK("Adding mac " MAC_FMT "\n", MAC_ARG(mac));
++	DPRINTK("Adding mac %s\n", print_mac(buf, mac));
+        
+ 	spin_lock_irqsave(&fwd_set->fwd_lock, flags);
+ 	
+@@ -199,8 +200,8 @@ int netback_accel_fwd_add(const __u8 *ma
+ 	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));
++		EPRINTK("MAC address %s already accelerated.\n",
++			print_mac(buf, mac));
+ 		return -EEXIST;
+ 	}
+ 
+@@ -235,8 +236,9 @@ void netback_accel_fwd_remove(const __u8
+ 	unsigned long flags;
+ 	cuckoo_hash_mac_key key = cuckoo_mac_to_key(mac);
+ 	struct port_fwd *fwd_set = (struct port_fwd *)fwd_priv;
++	DECLARE_MAC_BUF(buf);
+ 
+-	DPRINTK("Removing mac " MAC_FMT "\n", MAC_ARG(mac));
++	DPRINTK("Removing mac %s\n", print_mac(buf, mac));
+ 
+ 	BUG_ON(fwd_priv == NULL);
+ 
+@@ -394,14 +396,16 @@ void netback_accel_tx_packet(struct sk_b
+ 
+ 	if (is_broadcast_ether_addr(skb_mac_header(skb))
+ 	    && packet_is_arp_reply(skb)) {
++		DECLARE_MAC_BUF(buf);
++
+ 		/*
+ 		 * update our fast path forwarding to reflect this
+ 		 * gratuitous ARP
+ 		 */ 
+ 		mac = skb_mac_header(skb)+ETH_ALEN;
+ 
+-		DPRINTK("%s: found gratuitous ARP for " MAC_FMT "\n",
+-			__FUNCTION__, MAC_ARG(mac));
++		DPRINTK("%s: found gratuitous ARP for %s\n",
++			__FUNCTION__, print_mac(buf, mac));
+ 
+ 		spin_lock_irqsave(&fwd_set->fwd_lock, flags);
+ 		/*
+--- head-2010-01-18.orig/drivers/xen/sfc_netback/accel_msg.c	2008-02-20 09:32:49.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netback/accel_msg.c	2009-11-06 10:51:17.000000000 +0100
+@@ -57,11 +57,11 @@ static void netback_accel_msg_tx_localma
+ {
+ 	unsigned long lock_state;
+ 	struct net_accel_msg *msg;
++	DECLARE_MAC_BUF(buf);
+ 
+ 	BUG_ON(bend == NULL || mac == NULL);
+ 
+-	VPRINTK("Sending local mac message: " MAC_FMT "\n", 
+-		MAC_ARG((const char *)mac));  
++	VPRINTK("Sending local mac message: %s\n", print_mac(buf, mac));
+ 	
+ 	msg = net_accel_msg_start_send(bend->shared_page, &bend->to_domU,
+ 				       &lock_state);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_msg.c	2009-11-06 10:51:17.000000000 +0100
+@@ -41,11 +41,13 @@ static void vnic_start_interrupts(netfro
+ 	/* Prime our interrupt */
+ 	spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
+ 	if (!netfront_accel_vi_enable_interrupts(vnic)) {
++		struct netfront_info *np = netdev_priv(vnic->net_dev);
++
+ 		/* 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);
++		netif_rx_schedule(vnic->net_dev, &np->napi);
+ 	} else {
+ 		/*
+ 		 * Nothing yet, make sure we get interrupts through
+@@ -72,6 +74,7 @@ static void vnic_stop_interrupts(netfron
+ static void vnic_start_fastpath(netfront_accel_vnic *vnic)
+ {
+ 	struct net_device *net_dev = vnic->net_dev;
++	struct netfront_info *np = netdev_priv(net_dev);
+ 	unsigned long flags;
+ 
+ 	DPRINTK("%s\n", __FUNCTION__);
+@@ -80,9 +83,9 @@ static void vnic_start_fastpath(netfront
+ 	vnic->tx_enabled = 1;
+ 	spin_unlock_irqrestore(&vnic->tx_lock, flags);
+ 	
+-	netif_poll_disable(net_dev);
++	napi_disable(&np->napi);
+ 	vnic->poll_enabled = 1;
+-	netif_poll_enable(net_dev);
++	napi_enable(&np->napi);
+ 	
+ 	vnic_start_interrupts(vnic);
+ }
+@@ -114,11 +117,11 @@ void vnic_stop_fastpath(netfront_accel_v
+ 	spin_unlock_irqrestore(&vnic->tx_lock, flags1);
+ 	
+ 	/* Must prevent polls and hold lock to modify poll_enabled */
+-	netif_poll_disable(net_dev);
++	napi_disable(&np->napi);
+ 	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);
++	napi_enable(&np->napi);
+ }
+ 
+ 
+@@ -324,8 +327,10 @@ static int vnic_process_localmac_msg(net
+ 	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));
++		DECLARE_MAC_BUF(buf);
++
++		DPRINTK("MAC has moved, could be local: %s\n",
++			print_mac(buf, 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 */
+@@ -513,6 +518,8 @@ irqreturn_t netfront_accel_net_channel_i
+ 
+ 	spin_lock_irqsave(&vnic->irq_enabled_lock, flags);
+ 	if (vnic->irq_enabled) {
++		struct netfront_info *np = netdev_priv(net_dev);
++
+ 		netfront_accel_disable_net_interrupts(vnic);
+ 		vnic->irq_enabled = 0;
+ 		spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
+@@ -525,7 +532,7 @@ irqreturn_t netfront_accel_net_channel_i
+ 				vnic->stats.event_count_since_irq;
+ 		vnic->stats.event_count_since_irq = 0;
+ #endif
+-		netif_rx_schedule(net_dev);
++		netif_rx_schedule(net_dev, &np->napi);
+ 	}
+ 	else {
+ 		spin_unlock_irqrestore(&vnic->irq_enabled_lock, flags);
+--- head-2010-01-18.orig/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:18:26.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netfront/accel_vi.c	2010-01-18 16:19:18.000000000 +0100
+@@ -643,8 +643,10 @@ netfront_accel_vi_tx_post(netfront_accel
+ 					  (cuckoo_hash_key *)(&key), &value);
+ 
+ 	if (!try_fastpath) {
+-		VPRINTK("try fast path false for mac: " MAC_FMT "\n",
+-			MAC_ARG(skb->data));
++		DECLARE_MAC_BUF(buf);
++
++		VPRINTK("try fast path false for mac: %s\n",
++			print_mac(buf, skb->data));
+ 		
+ 		return NETFRONT_ACCEL_STATUS_CANT;
+ 	}
+@@ -770,9 +772,10 @@ static void  netfront_accel_vi_rx_comple
+ 	if (compare_ether_addr(skb->data, vnic->mac)) {
+ 		struct iphdr *ip = (struct iphdr *)(skb->data + ETH_HLEN);
+ 		u16 port;
++		DECLARE_MAC_BUF(buf);
+ 
+-		DPRINTK("%s: saw wrong MAC address " MAC_FMT "\n", 
+-			__FUNCTION__, MAC_ARG(skb->data));
++		DPRINTK("%s: saw wrong MAC address %s\n",
++			__FUNCTION__, print_mac(buf, skb->data));
+ 
+ 		if (ip->protocol == IPPROTO_TCP) {
+ 			struct tcphdr *tcp = (struct tcphdr *)
+--- head-2010-01-18.orig/drivers/xen/sfc_netutil/accel_util.h	2008-02-20 09:32:49.000000000 +0100
++++ head-2010-01-18/drivers/xen/sfc_netutil/accel_util.h	2009-11-06 10:51:17.000000000 +0100
+@@ -63,9 +63,6 @@
+ 			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
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/usbfront.h	2009-11-06 10:51:17.000000000 +0100
+@@ -82,6 +82,7 @@ struct urb_priv {
+ 	struct urb *urb;
+ 	int req_id;	/* RING_REQUEST id for submitting */
+ 	int unlink_req_id; /* RING_REQUEST id for unlinking */
++	int status;
+ 	unsigned unlinked:1; /* dequeued marker */
+ };
+ 
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-hcd.c	2009-10-15 11:45:41.000000000 +0200
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-hcd.c	2009-11-06 10:51:17.000000000 +0100
+@@ -114,7 +114,6 @@ static void xenhcd_stop(struct usb_hcd *
+  * non-error returns are promise to giveback the urb later
+  */
+ static int xenhcd_urb_enqueue(struct usb_hcd *hcd,
+-				    struct usb_host_endpoint *ep,
+ 				    struct urb *urb,
+ 				    gfp_t mem_flags)
+ {
+@@ -130,6 +129,7 @@ static int xenhcd_urb_enqueue(struct usb
+ 		ret = -ENOMEM;
+ 		goto done;
+ 	}
++	urbp->status = 1;
+ 
+ 	ret = xenhcd_submit_urb(info, urbp);
+ 	if (ret != 0)
+@@ -144,7 +144,7 @@ done:
+  * called as .urb_dequeue()
+  */
+ static int xenhcd_urb_dequeue(struct usb_hcd *hcd,
+-				    struct urb *urb)
++			      struct urb *urb, int status)
+ {
+ 	struct usbfront_info *info = hcd_to_info(hcd);
+ 	struct urb_priv *urbp;
+@@ -157,6 +157,7 @@ static int xenhcd_urb_dequeue(struct usb
+ 	if (!urbp)
+ 		goto done;
+ 
++	urbp->status = status;
+ 	ret = xenhcd_unlink_urb(info, urbp);
+ 
+ done:
+--- head-2010-01-18.orig/drivers/xen/usbfront/usbfront-q.c	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/drivers/xen/usbfront/usbfront-q.c	2009-11-06 10:51:17.000000000 +0100
+@@ -236,7 +236,8 @@ __acquires(info->lock)
+ 		COUNT(info->stats.complete);
+ 	}
+ 	spin_unlock(&info->lock);
+-	usb_hcd_giveback_urb(info_to_hcd(info), urb);
++	usb_hcd_giveback_urb(info_to_hcd(info), urb,
++			     urbp->status <= 0 ? urbp->status : urb->status);
+ 	spin_lock(&info->lock);
+ }
+ 
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe.c	2009-12-04 11:00:10.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe.c	2009-11-06 10:51:17.000000000 +0100
+@@ -175,11 +175,9 @@ static int read_backend_details(struct x
+ }
+ 
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) && (defined(CONFIG_XEN) || defined(MODULE))
+-static int xenbus_uevent_frontend(struct device *dev, char **envp,
+-				  int num_envp, char *buffer, int buffer_size)
++static int xenbus_uevent_frontend(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct xenbus_device *xdev;
+-	int length = 0, i = 0;
+ 
+ 	if (dev == NULL)
+ 		return -ENODEV;
+@@ -188,12 +186,9 @@ static int xenbus_uevent_frontend(struct
+ 		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,
+-		       "MODALIAS=xen:%s", xdev->devicetype);
++	add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype);
++	add_uevent_var(env, "XENBUS_PATH=%s", xdev->nodename);
++	add_uevent_var(env, "MODALIAS=xen:%s", xdev->devicetype);
+ 
+ 	return 0;
+ }
+--- head-2010-01-18.orig/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenbus/xenbus_probe_backend.c	2009-11-06 10:51:17.000000000 +0100
+@@ -60,8 +60,7 @@
+ #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_uevent_backend(struct device *dev, struct kobj_uevent_env *env);
+ static int xenbus_probe_backend(const char *type, const char *domid);
+ 
+ extern int read_otherend_details(struct xenbus_device *xendev,
+@@ -128,13 +127,10 @@ static struct xen_bus_type xenbus_backen
+ 	},
+ };
+ 
+-static int xenbus_uevent_backend(struct device *dev, char **envp,
+-				 int num_envp, char *buffer, int buffer_size)
++static int xenbus_uevent_backend(struct device *dev, struct kobj_uevent_env *env)
+ {
+ 	struct xenbus_device *xdev;
+ 	struct xenbus_driver *drv;
+-	int i = 0;
+-	int length = 0;
+ 
+ 	DPRINTK("");
+ 
+@@ -146,27 +142,16 @@ static int xenbus_uevent_backend(struct 
+ 		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(env, "XENBUS_TYPE=%s", xdev->devicetype);
+ 
+-	add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+-		       "XENBUS_PATH=%s", xdev->nodename);
++	add_uevent_var(env, "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;
++	add_uevent_var(env, "XENBUS_BASE_PATH=%s", xenbus_backend.root);
+ 
+ 	if (dev->driver) {
+ 		drv = to_xenbus_driver(dev->driver);
+ 		if (drv && drv->uevent)
+-			return drv->uevent(xdev, envp, num_envp, buffer,
+-					   buffer_size);
++			return drv->uevent(xdev, env);
+ 	}
+ 
+ 	return 0;
+--- head-2010-01-18.orig/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:08.000000000 +0100
++++ head-2010-01-18/drivers/xen/xenoprof/xenoprofile.c	2010-01-07 09:58:23.000000000 +0100
+@@ -29,7 +29,6 @@
+ #include <xen/driver_util.h>
+ #include <xen/interface/xen.h>
+ #include <xen/interface/xenoprof.h>
+-#include "../../../drivers/oprofile/cpu_buffer.h"
+ #include "../../../drivers/oprofile/event_buffer.h"
+ 
+ #define MAX_XENOPROF_SAMPLES 16
+@@ -142,8 +141,7 @@ static void xenoprof_add_pc(xenoprof_buf
+ 		if (xenoprof_is_escape(buf, tail) &&
+ 		    xenoprof_get_event(buf, tail) == XENOPROF_TRACE_BEGIN) {
+ 			tracing=1;
+-			oprofile_add_pc(ESCAPE_CODE, buf->event_log[tail].mode, 
+-					CPU_TRACE_BEGIN); 
++			oprofile_add_mode(buf->event_log[tail].mode);
+ 			if (!is_passive)
+ 				oprofile_samples++;
+ 			else
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/agp.h	2007-06-22 09:08:06.000000000 +0200
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/agp.h	2009-11-06 10:51:17.000000000 +0100
+@@ -1,20 +1,22 @@
+-#ifndef AGP_H
+-#define AGP_H 1
++#ifndef _ASM_X86_AGP_H
++#define _ASM_X86_AGP_H
+ 
+ #include <asm/pgtable.h>
+ #include <asm/cacheflush.h>
+ #include <asm/system.h>
+ 
+-/* 
+- * Functions to keep the agpgart mappings coherent with the MMU.
+- * The GART gives the CPU a physical alias of pages in memory. The alias region is
+- * mapped uncacheable. Make sure there are no conflicting mappings
+- * with different cachability attributes for the same page. This avoids
+- * data corruption on some CPUs.
++/*
++ * Functions to keep the agpgart mappings coherent with the MMU. The
++ * GART gives the CPU a physical alias of pages in memory. The alias
++ * region is mapped uncacheable. Make sure there are no conflicting
++ * mappings with different cachability attributes for the same
++ * page. This avoids data corruption on some CPUs.
+  */
+ 
+-/* Caller's responsibility to call global_flush_tlb() for
+- * performance reasons */
++/*
++ * Caller's responsibility to call global_flush_tlb() for performance
++ * reasons
++ */
+ #define map_page_into_agp(page) ( \
+ 	xen_create_contiguous_region((unsigned long)page_address(page), 0, 32) \
+ 	?: change_page_attr(page, 1, PAGE_KERNEL_NOCACHE))
+@@ -24,9 +26,11 @@
+ 	change_page_attr(page, 1, PAGE_KERNEL))
+ #define flush_agp_mappings() global_flush_tlb()
+ 
+-/* Could use CLFLUSH here if the cpu supports it. But then it would
+-   need to be called for each cacheline of the whole page so it may not be 
+-   worth it. Would need a page for it. */
++/*
++ * Could use CLFLUSH here if the cpu supports it. But then it would
++ * need to be called for each cacheline of the whole page so it may
++ * not be worth it. Would need a page for it.
++ */
+ #define flush_agp_cache() wbinvd()
+ 
+ /* Convert a physical address to an address suitable for the GART. */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "desc_32.h"
++#else
++# include "desc_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/desc_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -34,6 +34,18 @@ static inline void clear_LDT(void)
+ 	put_cpu();
+ }
+ 
++#ifndef CONFIG_X86_NO_TSS
++static inline unsigned long __store_tr(void)
++{
++       unsigned long tr;
++
++       asm volatile ("str %w0":"=r" (tr));
++       return tr;
++}
++
++#define store_tr(tr) (tr) = __store_tr()
++#endif
++
+ /*
+  * This is the ldt that every process will get unless we need
+  * something other than this.
+@@ -47,6 +59,18 @@ extern struct desc_ptr cpu_gdt_descr[];
+ /* the cpu gdt accessor */
+ #define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+ 
++#ifndef CONFIG_XEN
++static inline void load_gdt(const struct desc_ptr *ptr)
++{
++	asm volatile("lgdt %w0"::"m" (*ptr));
++}
++
++static inline void store_gdt(struct desc_ptr *ptr)
++{
++       asm("sgdt %w0":"=m" (*ptr));
++}
++#endif
++
+ static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)  
+ {
+ 	struct gate_struct s; 	
+@@ -87,6 +111,16 @@ static inline void set_system_gate_ist(i
+ {
+ 	_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
+ }
++
++static inline void load_idt(const struct desc_ptr *ptr)
++{
++	asm volatile("lidt %w0"::"m" (*ptr));
++}
++
++static inline void store_idt(struct desc_ptr *dtr)
++{
++       asm("sidt %w0":"=m" (*dtr));
++}
+ #endif
+ 
+ static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/dma-mapping.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "dma-mapping_32.h"
++#else
++# include "dma-mapping_64.h"
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "fixmap_32.h"
++#else
++# include "fixmap_64.h"
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,420 @@
++/******************************************************************************
++ * hypercall.h
++ *
++ * Linux-specific hypervisor handling.
++ *
++ * Copyright (c) 2002-2004, K A Fraser
++ *
++ * 64-bit updates:
++ *   Benjamin Liu <benjamin.liu@intel.com>
++ *   Jun Nakajima <jun.nakajima@intel.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; 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 __HYPERCALL_H__
++#define __HYPERCALL_H__
++
++#ifndef __HYPERVISOR_H__
++# error "please don't include this file directly"
++#endif
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++# include <linux/string.h> /* memcpy() */
++#endif
++
++#ifdef CONFIG_XEN
++#define HYPERCALL_ASM_OPERAND "%c"
++#define HYPERCALL_LOCATION(op) (hypercall_page + (op) * 32)
++#define HYPERCALL_C_OPERAND(name) "i" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
++#else
++#define HYPERCALL_ASM_OPERAND "*%"
++#define HYPERCALL_LOCATION(op) (hypercall_stubs + (op) * 32)
++#define HYPERCALL_C_OPERAND(name) "g" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
++#endif
++
++#define HYPERCALL_ARG(arg, n) \
++	register typeof((arg)+0) __arg##n asm(HYPERCALL_arg##n) = (arg)
++
++#define _hypercall0(type, name)					\
++({								\
++	type __res;						\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "1"		\
++		: "=a" (__res)					\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall1(type, name, arg)				\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(arg, 1);					\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "2"		\
++		: "=a" (__res), "+r" (__arg1)			\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall2(type, name, a1, a2)				\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(a1, 1);					\
++	HYPERCALL_ARG(a2, 2);					\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "3"		\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2)	\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall3(type, name, a1, a2, a3)			\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(a1, 1);					\
++	HYPERCALL_ARG(a2, 2);					\
++	HYPERCALL_ARG(a3, 3);					\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "4"		\
++		: "=a" (__res), "+r" (__arg1),			\
++		  "+r" (__arg2), "+r" (__arg3)			\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall4(type, name, a1, a2, a3, a4)			\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(a1, 1);					\
++	HYPERCALL_ARG(a2, 2);					\
++	HYPERCALL_ARG(a3, 3);					\
++	HYPERCALL_ARG(a4, 4);					\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "5"		\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
++		  "+r" (__arg3), "+r" (__arg4)			\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(a1, 1);					\
++	HYPERCALL_ARG(a2, 2);					\
++	HYPERCALL_ARG(a3, 3);					\
++	HYPERCALL_ARG(a4, 4);					\
++	HYPERCALL_ARG(a5, 5);					\
++	asm volatile (						\
++		"call " HYPERCALL_ASM_OPERAND "6"		\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
++		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
++		: HYPERCALL_C_OPERAND(name)			\
++		: "memory" );					\
++	__res;							\
++})
++
++#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
++({								\
++	type __res;						\
++	HYPERCALL_ARG(a1, 1);					\
++	HYPERCALL_ARG(a2, 2);					\
++	HYPERCALL_ARG(a3, 3);					\
++	HYPERCALL_ARG(a4, 4);					\
++	HYPERCALL_ARG(a5, 5);					\
++	asm volatile (						\
++		"call *%6"					\
++		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
++		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
++		: "g" (HYPERCALL_LOCATION(op))			\
++		: "memory" );					\
++	__res;							\
++})
++
++#ifdef CONFIG_X86_32
++# include "hypercall_32.h"
++#else
++# include "hypercall_64.h"
++#endif
++
++static inline int __must_check
++HYPERVISOR_set_trap_table(
++	const trap_info_t *table)
++{
++	return _hypercall1(int, set_trap_table, table);
++}
++
++static inline int __must_check
++HYPERVISOR_mmu_update(
++	mmu_update_t *req, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmu_update(req, count, success_count, domid);
++	return _hypercall4(int, mmu_update, req, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_mmuext_op(
++	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
++	domid_t domid)
++{
++	if (arch_use_lazy_mmu_mode())
++		return xen_multi_mmuext_op(op, count, success_count, domid);
++	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
++}
++
++static inline int __must_check
++HYPERVISOR_set_gdt(
++	unsigned long *frame_list, unsigned int entries)
++{
++	return _hypercall2(int, set_gdt, frame_list, entries);
++}
++
++static inline int __must_check
++HYPERVISOR_stack_switch(
++	unsigned long ss, unsigned long esp)
++{
++	return _hypercall2(int, stack_switch, ss, esp);
++}
++
++static inline int
++HYPERVISOR_fpu_taskswitch(
++	int set)
++{
++	return _hypercall1(int, fpu_taskswitch, set);
++}
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++static inline int __must_check
++HYPERVISOR_sched_op_compat(
++	int cmd, unsigned long arg)
++{
++	return _hypercall2(int, sched_op_compat, cmd, arg);
++}
++#endif
++
++static inline int __must_check
++HYPERVISOR_sched_op(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, sched_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_platform_op(
++	struct xen_platform_op *platform_op)
++{
++	platform_op->interface_version = XENPF_INTERFACE_VERSION;
++	return _hypercall1(int, platform_op, platform_op);
++}
++
++struct xen_mc;
++static inline int __must_check
++HYPERVISOR_mca(
++	struct xen_mc *mc_op)
++{
++	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
++	return _hypercall1(int, mca, mc_op);
++}
++
++static inline int __must_check
++HYPERVISOR_set_debugreg(
++	unsigned int reg, unsigned long value)
++{
++	return _hypercall2(int, set_debugreg, reg, value);
++}
++
++static inline unsigned long __must_check
++HYPERVISOR_get_debugreg(
++	unsigned int reg)
++{
++	return _hypercall1(unsigned long, get_debugreg, reg);
++}
++
++static inline int __must_check
++HYPERVISOR_memory_op(
++	unsigned int cmd, void *arg)
++{
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
++	return _hypercall2(int, memory_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_multicall(
++	multicall_entry_t *call_list, unsigned int nr_calls)
++{
++	return _hypercall2(int, multicall, call_list, nr_calls);
++}
++
++static inline int __must_check
++HYPERVISOR_event_channel_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, event_channel_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct evtchn_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, event_channel_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_xen_version(
++	int cmd, void *arg)
++{
++	return _hypercall2(int, xen_version, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_console_io(
++	int cmd, unsigned int count, char *str)
++{
++	return _hypercall3(int, console_io, cmd, count, str);
++}
++
++static inline int __must_check
++HYPERVISOR_physdev_op(
++	int cmd, void *arg)
++{
++	int rc = _hypercall2(int, physdev_op, cmd, arg);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (unlikely(rc == -ENOSYS)) {
++		struct physdev_op op;
++		op.cmd = cmd;
++		memcpy(&op.u, arg, sizeof(op.u));
++		rc = _hypercall1(int, physdev_op_compat, &op);
++		memcpy(arg, &op.u, sizeof(op.u));
++	}
++#endif
++
++	return rc;
++}
++
++static inline int __must_check
++HYPERVISOR_grant_table_op(
++	unsigned int cmd, void *uop, unsigned int count)
++{
++	if (arch_use_lazy_mmu_mode())
++		xen_multicall_flush(false);
++	return _hypercall3(int, grant_table_op, cmd, uop, count);
++}
++
++static inline int __must_check
++HYPERVISOR_vm_assist(
++	unsigned int cmd, unsigned int type)
++{
++	return _hypercall2(int, vm_assist, cmd, type);
++}
++
++static inline int __must_check
++HYPERVISOR_vcpu_op(
++	int cmd, unsigned int vcpuid, void *extra_args)
++{
++	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
++}
++
++static inline int __must_check
++HYPERVISOR_suspend(
++	unsigned long srec)
++{
++	struct sched_shutdown sched_shutdown = {
++		.reason = SHUTDOWN_suspend
++	};
++
++	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
++			     &sched_shutdown, srec);
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++	if (rc == -ENOSYS)
++		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
++				 SHUTDOWN_suspend, srec);
++#endif
++
++	return rc;
++}
++
++#if CONFIG_XEN_COMPAT <= 0x030002
++static inline int
++HYPERVISOR_nmi_op(
++	unsigned long op, void *arg)
++{
++	return _hypercall2(int, nmi_op, op, arg);
++}
++#endif
++
++#ifndef CONFIG_XEN
++static inline unsigned long __must_check
++HYPERVISOR_hvm_op(
++    int op, void *arg)
++{
++    return _hypercall2(unsigned long, hvm_op, op, arg);
++}
++#endif
++
++static inline int __must_check
++HYPERVISOR_callback_op(
++	int cmd, const void *arg)
++{
++	return _hypercall2(int, callback_op, cmd, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_xenoprof_op(
++	int op, void *arg)
++{
++	return _hypercall2(int, xenoprof_op, op, arg);
++}
++
++static inline int __must_check
++HYPERVISOR_kexec_op(
++	unsigned long op, void *args)
++{
++	return _hypercall2(int, kexec_op, op, args);
++}
++
++static inline int __must_check
++HYPERVISOR_tmem_op(
++	struct tmem_op *op)
++{
++	return _hypercall1(int, tmem_op, op);
++}
++
++#endif /* __HYPERCALL_H__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypercall_32.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -1,191 +1,10 @@
+-/******************************************************************************
+- * hypercall.h
+- * 
+- * Linux-specific hypervisor handling.
+- * 
+- * Copyright (c) 2002-2004, K A Fraser
+- * 
+- * 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 __HYPERCALL_H__
+-#define __HYPERCALL_H__
+-
+-#include <linux/string.h> /* memcpy() */
+-#include <linux/stringify.h>
+-
+-#ifndef __HYPERVISOR_H__
+-# error "please don't include this file directly"
+-#endif
+-
+-#ifdef CONFIG_XEN
+-#define HYPERCALL_STR(name)					\
+-	"call hypercall_page + ("__stringify(__HYPERVISOR_##name)" * 32)"
+-#else
+-#define HYPERCALL_STR(name)					\
+-	"mov hypercall_stubs,%%eax; "				\
+-	"add $("__stringify(__HYPERVISOR_##name)" * 32),%%eax; "\
+-	"call *%%eax"
+-#endif
+-
+-#define _hypercall0(type, name)			\
+-({						\
+-	type __res;				\
+-	asm volatile (				\
+-		HYPERCALL_STR(name)		\
+-		: "=a" (__res)			\
+-		:				\
+-		: "memory" );			\
+-	__res;					\
+-})
+-
+-#define _hypercall1(type, name, a1)				\
+-({								\
+-	type __res;						\
+-	long __ign1;						\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=b" (__ign1)			\
+-		: "1" ((long)(a1))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall2(type, name, a1, a2)				\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2;					\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)	\
+-		: "1" ((long)(a1)), "2" ((long)(a2))		\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall3(type, name, a1, a2, a3)			\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3;				\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2), 	\
+-		"=d" (__ign3)					\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		"3" ((long)(a3))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall4(type, name, a1, a2, a3, a4)			\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3, __ign4;			\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
+-		"=d" (__ign3), "=S" (__ign4)			\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		"3" ((long)(a3)), "4" ((long)(a4))		\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3, __ign4, __ign5;		\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),	\
+-		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)	\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		"3" ((long)(a3)), "4" ((long)(a4)),		\
+-		"5" ((long)(a5))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
+-({								\
+-	type __res;						\
+-	register typeof((a1)+0) __arg1 asm("ebx") = (a1);	\
+-	register typeof((a2)+0) __arg2 asm("ecx") = (a2);	\
+-	register typeof((a3)+0) __arg3 asm("edx") = (a3);	\
+-	register typeof((a4)+0) __arg4 asm("esi") = (a4);	\
+-	register typeof((a5)+0) __arg5 asm("edi") = (a5);	\
+-	asm volatile (						\
+-		"call *%6"					\
+-		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
+-		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
+-		: "0" (hypercall_page + (op) * 32)		\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-static inline int __must_check
+-HYPERVISOR_set_trap_table(
+-	const trap_info_t *table)
+-{
+-	return _hypercall1(int, set_trap_table, table);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_mmu_update(
+-	mmu_update_t *req, unsigned int count, unsigned int *success_count,
+-	domid_t domid)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		return xen_multi_mmu_update(req, count, success_count, domid);
+-	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_mmuext_op(
+-	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
+-	domid_t domid)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		return xen_multi_mmuext_op(op, count, success_count, domid);
+-	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_set_gdt(
+-	unsigned long *frame_list, unsigned int entries)
+-{
+-	return _hypercall2(int, set_gdt, frame_list, entries);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_stack_switch(
+-	unsigned long ss, unsigned long esp)
+-{
+-	return _hypercall2(int, stack_switch, ss, esp);
+-}
++#define HYPERCALL_arg1 "ebx"
++#define HYPERCALL_arg2 "ecx"
++#define HYPERCALL_arg3 "edx"
++#define HYPERCALL_arg4 "esi"
++#define HYPERCALL_arg5 "edi"
+ 
++#if CONFIG_XEN_COMPAT <= 0x030002
+ static inline int __must_check
+ HYPERVISOR_set_callbacks(
+ 	unsigned long event_selector, unsigned long event_address,
+@@ -195,80 +14,24 @@ HYPERVISOR_set_callbacks(
+ 			   event_selector, event_address,
+ 			   failsafe_selector, failsafe_address);
+ }
+-
+-static inline int
+-HYPERVISOR_fpu_taskswitch(
+-	int set)
+-{
+-	return _hypercall1(int, fpu_taskswitch, set);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_sched_op_compat(
+-	int cmd, unsigned long arg)
+-{
+-	return _hypercall2(int, sched_op_compat, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_sched_op(
+-	int cmd, void *arg)
+-{
+-	return _hypercall2(int, sched_op, cmd, arg);
+-}
++#endif
+ 
+ static inline long __must_check
+ HYPERVISOR_set_timer_op(
+ 	u64 timeout)
+ {
+-	unsigned long timeout_hi = (unsigned long)(timeout>>32);
+-	unsigned long timeout_lo = (unsigned long)timeout;
+-	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_platform_op(
+-	struct xen_platform_op *platform_op)
+-{
+-	platform_op->interface_version = XENPF_INTERFACE_VERSION;
+-	return _hypercall1(int, platform_op, platform_op);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_set_debugreg(
+-	unsigned int reg, unsigned long value)
+-{
+-	return _hypercall2(int, set_debugreg, reg, value);
+-}
+-
+-static inline unsigned long __must_check
+-HYPERVISOR_get_debugreg(
+-	unsigned int reg)
+-{
+-	return _hypercall1(unsigned long, get_debugreg, reg);
++	return _hypercall2(long, set_timer_op,
++			   (unsigned long)timeout,
++			   (unsigned long)(timeout>>32));
+ }
+ 
+ static inline int __must_check
+ HYPERVISOR_update_descriptor(
+ 	u64 ma, u64 desc)
+ {
+-	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_memory_op(
+-	unsigned int cmd, void *arg)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		xen_multicall_flush(false);
+-	return _hypercall2(int, memory_op, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_multicall(
+-	multicall_entry_t *call_list, unsigned int nr_calls)
+-{
+-	return _hypercall2(int, multicall, call_list, nr_calls);
++	return _hypercall4(int, update_descriptor,
++			   (unsigned long)ma, (unsigned long)(ma>>32),
++			   (unsigned long)desc, (unsigned long)(desc>>32));
+ }
+ 
+ static inline int __must_check
+@@ -287,67 +50,6 @@ HYPERVISOR_update_va_mapping(
+ }
+ 
+ static inline int __must_check
+-HYPERVISOR_event_channel_op(
+-	int cmd, void *arg)
+-{
+-	int rc = _hypercall2(int, event_channel_op, cmd, arg);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (unlikely(rc == -ENOSYS)) {
+-		struct evtchn_op op;
+-		op.cmd = cmd;
+-		memcpy(&op.u, arg, sizeof(op.u));
+-		rc = _hypercall1(int, event_channel_op_compat, &op);
+-		memcpy(arg, &op.u, sizeof(op.u));
+-	}
+-#endif
+-
+-	return rc;
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_xen_version(
+-	int cmd, void *arg)
+-{
+-	return _hypercall2(int, xen_version, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_console_io(
+-	int cmd, unsigned int count, char *str)
+-{
+-	return _hypercall3(int, console_io, cmd, count, str);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_physdev_op(
+-	int cmd, void *arg)
+-{
+-	int rc = _hypercall2(int, physdev_op, cmd, arg);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (unlikely(rc == -ENOSYS)) {
+-		struct physdev_op op;
+-		op.cmd = cmd;
+-		memcpy(&op.u, arg, sizeof(op.u));
+-		rc = _hypercall1(int, physdev_op_compat, &op);
+-		memcpy(arg, &op.u, sizeof(op.u));
+-	}
+-#endif
+-
+-	return rc;
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_grant_table_op(
+-	unsigned int cmd, void *uop, unsigned int count)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		xen_multicall_flush(false);
+-	return _hypercall3(int, grant_table_op, cmd, uop, count);
+-}
+-
+-static inline int __must_check
+ HYPERVISOR_update_va_mapping_otherdomain(
+ 	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+ {
+@@ -358,86 +60,3 @@ HYPERVISOR_update_va_mapping_otherdomain
+ 	return _hypercall5(int, update_va_mapping_otherdomain, va,
+ 			   new_val.pte_low, pte_hi, flags, domid);
+ }
+-
+-static inline int __must_check
+-HYPERVISOR_vm_assist(
+-	unsigned int cmd, unsigned int type)
+-{
+-	return _hypercall2(int, vm_assist, cmd, type);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_vcpu_op(
+-	int cmd, unsigned int vcpuid, void *extra_args)
+-{
+-	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_suspend(
+-	unsigned long srec)
+-{
+-	struct sched_shutdown sched_shutdown = {
+-		.reason = SHUTDOWN_suspend
+-	};
+-
+-	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
+-			     &sched_shutdown, srec);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (rc == -ENOSYS)
+-		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
+-				 SHUTDOWN_suspend, srec);
+-#endif
+-
+-	return rc;
+-}
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-static inline int
+-HYPERVISOR_nmi_op(
+-	unsigned long op, void *arg)
+-{
+-	return _hypercall2(int, nmi_op, op, arg);
+-}
+-#endif
+-
+-#ifndef CONFIG_XEN
+-static inline unsigned long __must_check
+-HYPERVISOR_hvm_op(
+-    int op, void *arg)
+-{
+-    return _hypercall2(unsigned long, hvm_op, op, arg);
+-}
+-#endif
+-
+-static inline int __must_check
+-HYPERVISOR_callback_op(
+-	int cmd, const void *arg)
+-{
+-	return _hypercall2(int, callback_op, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_xenoprof_op(
+-	int op, void *arg)
+-{
+-	return _hypercall2(int, xenoprof_op, op, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_kexec_op(
+-	unsigned long op, void *args)
+-{
+-	return _hypercall2(int, kexec_op, op, args);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_tmem_op(
+-	struct tmem_op *op)
+-{
+-	return _hypercall1(int, tmem_op, op);
+-}
+-
+-
+-#endif /* __HYPERCALL_H__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypercall_64.h	2009-11-06 10:45:48.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypercall_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -1,198 +1,10 @@
+-/******************************************************************************
+- * hypercall.h
+- * 
+- * Linux-specific hypervisor handling.
+- * 
+- * Copyright (c) 2002-2004, K A Fraser
+- * 
+- * 64-bit updates:
+- *   Benjamin Liu <benjamin.liu@intel.com>
+- *   Jun Nakajima <jun.nakajima@intel.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; 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 __HYPERCALL_H__
+-#define __HYPERCALL_H__
+-
+-#include <linux/string.h> /* memcpy() */
+-#include <linux/stringify.h>
+-#include <xen/interface/arch-x86/xen-mca.h>
+-
+-#ifndef __HYPERVISOR_H__
+-# error "please don't include this file directly"
+-#endif
+-
+-#ifdef CONFIG_XEN
+-#define HYPERCALL_STR(name)					\
+-	"call hypercall_page + ("__stringify(__HYPERVISOR_##name)" * 32)"
+-#else
+-#define HYPERCALL_STR(name)					\
+-	"mov $("__stringify(__HYPERVISOR_##name)" * 32),%%eax; "\
+-	"add hypercall_stubs(%%rip),%%rax; "			\
+-	"call *%%rax"
+-#endif
+-
+-#define _hypercall0(type, name)			\
+-({						\
+-	type __res;				\
+-	asm volatile (				\
+-		HYPERCALL_STR(name)		\
+-		: "=a" (__res)			\
+-		:				\
+-		: "memory" );			\
+-	__res;					\
+-})
+-
+-#define _hypercall1(type, name, a1)				\
+-({								\
+-	type __res;						\
+-	long __ign1;						\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=D" (__ign1)			\
+-		: "1" ((long)(a1))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall2(type, name, a1, a2)				\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2;					\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=D" (__ign1), "=S" (__ign2)	\
+-		: "1" ((long)(a1)), "2" ((long)(a2))		\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall3(type, name, a1, a2, a3)			\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3;				\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=D" (__ign1), "=S" (__ign2), 	\
+-		"=d" (__ign3)					\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		"3" ((long)(a3))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall4(type, name, a1, a2, a3, a4)			\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3;				\
+-	register long __arg4 asm("r10") = (long)(a4);		\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
+-		  "=d" (__ign3), "+r" (__arg4)			\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		  "3" ((long)(a3))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
+-({								\
+-	type __res;						\
+-	long __ign1, __ign2, __ign3;				\
+-	register long __arg4 asm("r10") = (long)(a4);		\
+-	register long __arg5 asm("r8") = (long)(a5);		\
+-	asm volatile (						\
+-		HYPERCALL_STR(name)				\
+-		: "=a" (__res), "=D" (__ign1), "=S" (__ign2),	\
+-		  "=d" (__ign3), "+r" (__arg4), "+r" (__arg5)	\
+-		: "1" ((long)(a1)), "2" ((long)(a2)),		\
+-		  "3" ((long)(a3))				\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
+-({								\
+-	type __res;						\
+-	register typeof((a1)+0) __arg1 asm("rdi") = (a1);	\
+-	register typeof((a2)+0) __arg2 asm("rsi") = (a2);	\
+-	register typeof((a3)+0) __arg3 asm("rdx") = (a3);	\
+-	register typeof((a4)+0) __arg4 asm("r10") = (a4);	\
+-	register typeof((a5)+0) __arg5 asm("r8") = (a5);	\
+-	asm volatile (						\
+-		"call *%6"					\
+-		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
+-		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
+-		: "0" (hypercall_page + (op) * 32)		\
+-		: "memory" );					\
+-	__res;							\
+-})
+-
+-static inline int __must_check
+-HYPERVISOR_set_trap_table(
+-	const trap_info_t *table)
+-{
+-	return _hypercall1(int, set_trap_table, table);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_mmu_update(
+-	mmu_update_t *req, unsigned int count, unsigned int *success_count,
+-	domid_t domid)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		return xen_multi_mmu_update(req, count, success_count, domid);
+-	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_mmuext_op(
+-	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
+-	domid_t domid)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		return xen_multi_mmuext_op(op, count, success_count, domid);
+-	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_set_gdt(
+-	unsigned long *frame_list, unsigned int entries)
+-{
+-	return _hypercall2(int, set_gdt, frame_list, entries);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_stack_switch(
+-	unsigned long ss, unsigned long esp)
+-{
+-	return _hypercall2(int, stack_switch, ss, esp);
+-}
++#define HYPERCALL_arg1 "rdi"
++#define HYPERCALL_arg2 "rsi"
++#define HYPERCALL_arg3 "rdx"
++#define HYPERCALL_arg4 "r10"
++#define HYPERCALL_arg5 "r8"
+ 
++#if CONFIG_XEN_COMPAT <= 0x030002
+ static inline int __must_check
+ HYPERVISOR_set_callbacks(
+ 	unsigned long event_address, unsigned long failsafe_address, 
+@@ -201,27 +13,7 @@ HYPERVISOR_set_callbacks(
+ 	return _hypercall3(int, set_callbacks,
+ 			   event_address, failsafe_address, syscall_address);
+ }
+-
+-static inline int
+-HYPERVISOR_fpu_taskswitch(
+-	int set)
+-{
+-	return _hypercall1(int, fpu_taskswitch, set);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_sched_op_compat(
+-	int cmd, unsigned long arg)
+-{
+-	return _hypercall2(int, sched_op_compat, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_sched_op(
+-	int cmd, void *arg)
+-{
+-	return _hypercall2(int, sched_op, cmd, arg);
+-}
++#endif
+ 
+ static inline long __must_check
+ HYPERVISOR_set_timer_op(
+@@ -231,34 +23,6 @@ HYPERVISOR_set_timer_op(
+ }
+ 
+ static inline int __must_check
+-HYPERVISOR_platform_op(
+-	struct xen_platform_op *platform_op)
+-{
+-	platform_op->interface_version = XENPF_INTERFACE_VERSION;
+-	return _hypercall1(int, platform_op, platform_op);
+-}
+-static inline int __must_check
+-HYPERVISOR_mca(
+-	struct xen_mc *mc_op)
+-{
+-	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
+-	return _hypercall1(int, mca, mc_op);
+-}
+-static inline int __must_check
+-HYPERVISOR_set_debugreg(
+-	unsigned int reg, unsigned long value)
+-{
+-	return _hypercall2(int, set_debugreg, reg, value);
+-}
+-
+-static inline unsigned long __must_check
+-HYPERVISOR_get_debugreg(
+-	unsigned int reg)
+-{
+-	return _hypercall1(unsigned long, get_debugreg, reg);
+-}
+-
+-static inline int __must_check
+ HYPERVISOR_update_descriptor(
+ 	unsigned long ma, unsigned long word)
+ {
+@@ -266,22 +30,6 @@ HYPERVISOR_update_descriptor(
+ }
+ 
+ static inline int __must_check
+-HYPERVISOR_memory_op(
+-	unsigned int cmd, void *arg)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		xen_multicall_flush(false);
+-	return _hypercall2(int, memory_op, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_multicall(
+-	multicall_entry_t *call_list, unsigned int nr_calls)
+-{
+-	return _hypercall2(int, multicall, call_list, nr_calls);
+-}
+-
+-static inline int __must_check
+ HYPERVISOR_update_va_mapping(
+ 	unsigned long va, pte_t new_val, unsigned long flags)
+ {
+@@ -291,67 +39,6 @@ HYPERVISOR_update_va_mapping(
+ }
+ 
+ static inline int __must_check
+-HYPERVISOR_event_channel_op(
+-	int cmd, void *arg)
+-{
+-	int rc = _hypercall2(int, event_channel_op, cmd, arg);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (unlikely(rc == -ENOSYS)) {
+-		struct evtchn_op op;
+-		op.cmd = cmd;
+-		memcpy(&op.u, arg, sizeof(op.u));
+-		rc = _hypercall1(int, event_channel_op_compat, &op);
+-		memcpy(arg, &op.u, sizeof(op.u));
+-	}
+-#endif
+-
+-	return rc;
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_xen_version(
+-	int cmd, void *arg)
+-{
+-	return _hypercall2(int, xen_version, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_console_io(
+-	int cmd, unsigned int count, char *str)
+-{
+-	return _hypercall3(int, console_io, cmd, count, str);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_physdev_op(
+-	int cmd, void *arg)
+-{
+-	int rc = _hypercall2(int, physdev_op, cmd, arg);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (unlikely(rc == -ENOSYS)) {
+-		struct physdev_op op;
+-		op.cmd = cmd;
+-		memcpy(&op.u, arg, sizeof(op.u));
+-		rc = _hypercall1(int, physdev_op_compat, &op);
+-		memcpy(arg, &op.u, sizeof(op.u));
+-	}
+-#endif
+-
+-	return rc;
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_grant_table_op(
+-	unsigned int cmd, void *uop, unsigned int count)
+-{
+-	if (arch_use_lazy_mmu_mode())
+-		xen_multicall_flush(false);
+-	return _hypercall3(int, grant_table_op, cmd, uop, count);
+-}
+-
+-static inline int __must_check
+ HYPERVISOR_update_va_mapping_otherdomain(
+ 	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+ {
+@@ -360,90 +47,8 @@ HYPERVISOR_update_va_mapping_otherdomain
+ }
+ 
+ static inline int __must_check
+-HYPERVISOR_vm_assist(
+-	unsigned int cmd, unsigned int type)
+-{
+-	return _hypercall2(int, vm_assist, cmd, type);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_vcpu_op(
+-	int cmd, unsigned int vcpuid, void *extra_args)
+-{
+-	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+-}
+-
+-static inline int __must_check
+ HYPERVISOR_set_segment_base(
+ 	int reg, unsigned long value)
+ {
+ 	return _hypercall2(int, set_segment_base, reg, value);
+ }
+-
+-static inline int __must_check
+-HYPERVISOR_suspend(
+-	unsigned long srec)
+-{
+-	struct sched_shutdown sched_shutdown = {
+-		.reason = SHUTDOWN_suspend
+-	};
+-
+-	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
+-			     &sched_shutdown, srec);
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-	if (rc == -ENOSYS)
+-		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
+-				 SHUTDOWN_suspend, srec);
+-#endif
+-
+-	return rc;
+-}
+-
+-#if CONFIG_XEN_COMPAT <= 0x030002
+-static inline int
+-HYPERVISOR_nmi_op(
+-	unsigned long op, void *arg)
+-{
+-	return _hypercall2(int, nmi_op, op, arg);
+-}
+-#endif
+-
+-#ifndef CONFIG_XEN
+-static inline unsigned long __must_check
+-HYPERVISOR_hvm_op(
+-    int op, void *arg)
+-{
+-    return _hypercall2(unsigned long, hvm_op, op, arg);
+-}
+-#endif
+-
+-static inline int __must_check
+-HYPERVISOR_callback_op(
+-	int cmd, const void *arg)
+-{
+-	return _hypercall2(int, callback_op, cmd, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_xenoprof_op(
+-	int op, void *arg)
+-{
+-	return _hypercall2(int, xenoprof_op, op, arg);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_kexec_op(
+-	unsigned long op, void *args)
+-{
+-	return _hypercall2(int, kexec_op, op, args);
+-}
+-
+-static inline int __must_check
+-HYPERVISOR_tmem_op(
+-	struct tmem_op *op)
+-{
+-	return _hypercall1(int, tmem_op, op);
+-}
+-
+-#endif /* __HYPERCALL_H__ */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:23:50.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/hypervisor.h	2009-11-23 10:32:11.000000000 +0100
+@@ -44,6 +44,7 @@
+ #include <xen/interface/sched.h>
+ #include <xen/interface/nmi.h>
+ #include <xen/interface/tmem.h>
++#include <xen/interface/arch-x86/xen-mca.h>
+ #include <asm/percpu.h>
+ #include <asm/ptrace.h>
+ #include <asm/page.h>
+@@ -200,7 +201,6 @@ static inline void xen_multicall_flush(b
+ extern char hypercall_page[PAGE_SIZE];
+ #else
+ extern char *hypercall_stubs;
+-#define hypercall_page hypercall_stubs
+ #define is_running_on_xen() (!!hypercall_stubs)
+ #endif
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/io.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "io_32.h"
++#else
++# include "io_64.h"
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "irqflags_32.h"
++#else
++# include "irqflags_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -150,6 +150,23 @@ static inline int raw_irqs_disabled_flag
+ 									\
+ 	raw_irqs_disabled_flags(flags);					\
+ })
++
++/*
++ * makes the traced hardirq state match with the machine state
++ *
++ * should be a rarely used function, only in places where its
++ * otherwise impossible to know the irq state, like in traps.
++ */
++static inline void trace_hardirqs_fixup_flags(unsigned long flags)
++{
++	if (raw_irqs_disabled_flags(flags))
++		trace_hardirqs_off();
++	else
++		trace_hardirqs_on();
++}
++
++#define trace_hardirqs_fixup() \
++	trace_hardirqs_fixup_flags(__raw_local_save_flags())
+ #endif /* __ASSEMBLY__ */
+ 
+ /*
+@@ -181,4 +198,17 @@ static inline int raw_irqs_disabled_flag
+ # define TRACE_IRQS_OFF
+ #endif
+ 
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++# define LOCKDEP_SYS_EXIT			\
++	pushl %eax;				\
++	pushl %ecx;				\
++	pushl %edx;				\
++	call lockdep_sys_exit;			\
++	popl %edx;				\
++	popl %ecx;				\
++	popl %eax;
++#else
++# define LOCKDEP_SYS_EXIT
++#endif
++
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/irqflags_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/irqflags_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -116,6 +116,22 @@ static inline int raw_irqs_disabled_flag
+ })
+ 
+ /*
++ * makes the traced hardirq state match with the machine state
++ *
++ * should be a rarely used function, only in places where its
++ * otherwise impossible to know the irq state, like in traps.
++ */
++static inline void trace_hardirqs_fixup_flags(unsigned long flags)
++{
++	if (raw_irqs_disabled_flags(flags))
++		trace_hardirqs_off();
++	else
++		trace_hardirqs_on();
++}
++
++#define trace_hardirqs_fixup() \
++	trace_hardirqs_fixup_flags(__raw_local_save_flags())
++/*
+  * Used in the idle loop; sti takes one instruction cycle
+  * to complete:
+  */
+@@ -143,6 +159,20 @@ static inline void halt(void)
+ #  define TRACE_IRQS_ON
+ #  define TRACE_IRQS_OFF
+ # endif
++# ifdef CONFIG_DEBUG_LOCK_ALLOC
++#  define LOCKDEP_SYS_EXIT	call lockdep_sys_exit_thunk
++#  define LOCKDEP_SYS_EXIT_IRQ	\
++	TRACE_IRQS_ON; \
++	sti; \
++	SAVE_REST; \
++	LOCKDEP_SYS_EXIT; \
++	RESTORE_REST; \
++	cli; \
++	TRACE_IRQS_OFF;
++# else
++#  define LOCKDEP_SYS_EXIT
++#  define LOCKDEP_SYS_EXIT_IRQ
++# endif
+ #endif
+ 
+ #endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/maddr.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "maddr_32.h"
++#else
++# include "maddr_64.h"
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/mmu_context.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "mmu_context_32.h"
++#else
++# include "mmu_context_64.h"
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pci.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,100 @@
++#ifndef __x86_PCI_H
++#define __x86_PCI_H
++
++#include <linux/mm.h> /* for struct page */
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <asm/scatterlist.h>
++#include <asm/io.h>
++
++
++#ifdef __KERNEL__
++
++struct pci_sysdata {
++	int		domain;		/* PCI domain */
++	int		node;		/* NUMA node */
++#ifdef CONFIG_X86_64
++	void*		iommu;		/* IOMMU private data */
++#endif
++#ifdef CONFIG_XEN_PCIDEV_FRONTEND
++	struct pcifront_device *pdev;
++#endif
++};
++
++/* scan a bus after allocating a pci_sysdata for it */
++extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
++
++static inline int pci_domain_nr(struct pci_bus *bus)
++{
++	struct pci_sysdata *sd = bus->sysdata;
++	return sd->domain;
++}
++
++static inline int pci_proc_domain(struct pci_bus *bus)
++{
++	return pci_domain_nr(bus);
++}
++
++
++/* Can be used to override the logic in pci_scan_bus for skipping
++   already-configured bus numbers - to be used for buggy BIOSes
++   or architectures with incomplete PCI setup by the loader */
++
++#ifdef CONFIG_PCI
++extern unsigned int pcibios_assign_all_busses(void);
++#else
++#define pcibios_assign_all_busses()	0
++#endif
++
++#include <asm/hypervisor.h>
++#define pcibios_scan_all_fns(a, b)	(!is_initial_xendomain())
++
++extern unsigned long pci_mem_start;
++#define PCIBIOS_MIN_IO		0x1000
++#define PCIBIOS_MIN_MEM		(pci_mem_start)
++
++#define PCIBIOS_MIN_CARDBUS_IO	0x4000
++
++void pcibios_config_init(void);
++struct pci_bus * pcibios_scan_root(int bus);
++
++void pcibios_set_master(struct pci_dev *dev);
++void pcibios_penalize_isa_irq(int irq, int active);
++struct irq_routing_table *pcibios_get_irq_routing_table(void);
++int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
++
++
++#define HAVE_PCI_MMAP
++extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
++			       enum pci_mmap_state mmap_state, int write_combine);
++
++
++#ifdef CONFIG_PCI
++static inline void pci_dma_burst_advice(struct pci_dev *pdev,
++					enum pci_dma_burst_strategy *strat,
++					unsigned long *strategy_parameter)
++{
++	*strat = PCI_DMA_BURST_INFINITY;
++	*strategy_parameter = ~0UL;
++}
++#endif
++
++
++#endif  /* __KERNEL__ */
++
++#ifdef CONFIG_X86_32
++# include "pci_32.h"
++#else
++# include "pci_64.h"
++#endif
++
++/* implement the pci_ DMA API in terms of the generic device dma_ one */
++#include <asm-generic/pci-dma-compat.h>
++
++/* generic pci stuff */
++#include <asm-generic/pci.h>
++
++
++
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "pgalloc_32.h"
++#else
++# include "pgalloc_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgalloc_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -112,6 +112,8 @@ static inline void pgd_list_del(pgd_t *p
+ 	spin_unlock(&pgd_lock);
+ }
+ 
++extern void pgd_test_and_unpin(pgd_t *);
++
+ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ 	/*
+@@ -122,6 +124,7 @@ static inline pgd_t *pgd_alloc(struct mm
+ 	if (!pgd)
+ 		return NULL;
+ 	pgd_list_add(pgd);
++	pgd_test_and_unpin(pgd);
+ 	/*
+ 	 * Copy kernel pointers in from init.
+ 	 * Could keep a freelist or slab cache of those because the kernel
+@@ -144,27 +147,7 @@ static inline pgd_t *pgd_alloc(struct mm
+ 
+ static inline void pgd_free(pgd_t *pgd)
+ {
+-	pte_t *ptep = virt_to_ptep(pgd);
+-
+-	if (!pte_write(*ptep)) {
+-		xen_pgd_unpin(__pa(pgd));
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)pgd,
+-			       pfn_pte(virt_to_phys(pgd)>>PAGE_SHIFT, PAGE_KERNEL),
+-			       0));
+-	}
+-
+-	ptep = virt_to_ptep(__user_pgd(pgd));
+-
+-	if (!pte_write(*ptep)) {
+-		xen_pgd_unpin(__pa(__user_pgd(pgd)));
+-		BUG_ON(HYPERVISOR_update_va_mapping(
+-			       (unsigned long)__user_pgd(pgd),
+-			       pfn_pte(virt_to_phys(__user_pgd(pgd))>>PAGE_SHIFT, 
+-				       PAGE_KERNEL),
+-			       0));
+-	}
+-
++	pgd_test_and_unpin(pgd);
+ 	pgd_list_del(pgd);
+ 	free_pages((unsigned long)pgd, 1);
+ }
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "pgtable_32.h"
++#else
++# include "pgtable_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -17,10 +17,7 @@
+ #include <asm/fixmap.h>
+ #include <linux/threads.h>
+ 
+-#ifndef _I386_BITOPS_H
+-#include <asm/bitops.h>
+-#endif
+-
++#include <linux/bitops.h>
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+@@ -40,7 +37,7 @@ extern spinlock_t pgd_lock;
+ extern struct page *pgd_list;
+ void check_pgt_cache(void);
+ 
+-void pmd_ctor(void *, struct kmem_cache *, unsigned long);
++void pmd_ctor(struct kmem_cache *, void *);
+ void pgtable_cache_init(void);
+ void paging_init(void);
+ 
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/pgtable_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -9,7 +9,7 @@
+  * the x86-64 page table tree.
+  */
+ #include <asm/processor.h>
+-#include <asm/bitops.h>
++#include <linux/bitops.h>
+ #include <linux/threads.h>
+ #include <linux/sched.h>
+ #include <asm/pda.h>
+@@ -139,6 +139,7 @@ static inline void pgd_clear (pgd_t * pg
+ #define MAXMEM		 _AC(0x6fffffffff, UL)
+ #define VMALLOC_START    _AC(0xffffc20000000000, UL)
+ #define VMALLOC_END      _AC(0xffffe1ffffffffff, UL)
++#define VMEMMAP_START	 _AC(0xffffe20000000000, UL)
+ #define MODULES_VADDR    _AC(0xffffffff88000000, UL)
+ #define MODULES_END      _AC(0xffffffffff000000, UL)
+ #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "processor_32.h"
++#else
++# include "processor_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -80,6 +80,7 @@ struct cpuinfo_x86 {
+ 	unsigned char booted_cores;	/* number of cores as seen by OS */
+ 	__u8 phys_proc_id; 		/* Physical processor id. */
+ 	__u8 cpu_core_id;  		/* Core id */
++	__u8 cpu_index;			/* index into per_cpu list */
+ #endif
+ } __attribute__((__aligned__(SMP_CACHE_BYTES)));
+ 
+@@ -106,14 +107,19 @@ DECLARE_PER_CPU(struct tss_struct, init_
+ #endif
+ 
+ #ifdef CONFIG_SMP
+-extern struct cpuinfo_x86 cpu_data[];
+-#define current_cpu_data cpu_data[smp_processor_id()]
++DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
++#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
++#define current_cpu_data	cpu_data(smp_processor_id())
+ #else
+-#define cpu_data (&boot_cpu_data)
+-#define current_cpu_data boot_cpu_data
++#define cpu_data(cpu)		boot_cpu_data
++#define current_cpu_data	boot_cpu_data
+ #endif
+ 
+-extern	int cpu_llc_id[NR_CPUS];
++/*
++ * the following now lives in the per cpu area:
++ * extern	int cpu_llc_id[NR_CPUS];
++ */
++DECLARE_PER_CPU(u8, cpu_llc_id);
+ extern char ignore_fpu_irq;
+ 
+ void __init cpu_detect(struct cpuinfo_x86 *c);
+@@ -560,7 +566,9 @@ static inline void xen_set_iopl_mask(uns
+  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+  * resulting in stale register contents being returned.
+  */
+-static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
++static inline void cpuid(unsigned int op,
++			 unsigned int *eax, unsigned int *ebx,
++			 unsigned int *ecx, unsigned int *edx)
+ {
+ 	*eax = op;
+ 	*ecx = 0;
+@@ -568,8 +576,9 @@ static inline void cpuid(unsigned int op
+ }
+ 
+ /* Some CPUID calls want 'count' to be placed in ecx */
+-static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+-			       int *edx)
++static inline void cpuid_count(unsigned int op, int count,
++			       unsigned int *eax, unsigned int *ebx,
++			       unsigned int *ecx, unsigned int *edx)
+ {
+ 	*eax = op;
+ 	*ecx = count;
+@@ -639,6 +648,17 @@ static inline unsigned int cpuid_edx(uns
+ #define K7_NOP7        ".byte 0x8D,0x04,0x05,0,0,0,0\n"
+ #define K7_NOP8        K7_NOP7 ASM_NOP1
+ 
++/* P6 nops */
++/* uses eax dependencies (Intel-recommended choice) */
++#define P6_NOP1	GENERIC_NOP1
++#define P6_NOP2	".byte 0x66,0x90\n"
++#define P6_NOP3	".byte 0x0f,0x1f,0x00\n"
++#define P6_NOP4	".byte 0x0f,0x1f,0x40,0\n"
++#define P6_NOP5	".byte 0x0f,0x1f,0x44,0x00,0\n"
++#define P6_NOP6	".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
++#define P6_NOP7	".byte 0x0f,0x1f,0x80,0,0,0,0\n"
++#define P6_NOP8	".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
++
+ #ifdef CONFIG_MK8
+ #define ASM_NOP1 K8_NOP1
+ #define ASM_NOP2 K8_NOP2
+@@ -657,6 +677,17 @@ static inline unsigned int cpuid_edx(uns
+ #define ASM_NOP6 K7_NOP6
+ #define ASM_NOP7 K7_NOP7
+ #define ASM_NOP8 K7_NOP8
++#elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
++      defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \
++      defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4)
++#define ASM_NOP1 P6_NOP1
++#define ASM_NOP2 P6_NOP2
++#define ASM_NOP3 P6_NOP3
++#define ASM_NOP4 P6_NOP4
++#define ASM_NOP5 P6_NOP5
++#define ASM_NOP6 P6_NOP6
++#define ASM_NOP7 P6_NOP7
++#define ASM_NOP8 P6_NOP8
+ #else
+ #define ASM_NOP1 GENERIC_NOP1
+ #define ASM_NOP2 GENERIC_NOP2
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/processor_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -74,6 +74,7 @@ struct cpuinfo_x86 {
+ 	__u8	booted_cores;	/* number of cores as seen by OS */
+ 	__u8	phys_proc_id;	/* Physical Processor id. */
+ 	__u8	cpu_core_id;	/* Core id. */
++	__u8	cpu_index;	/* index into per_cpu list */
+ #endif
+ } ____cacheline_aligned;
+ 
+@@ -88,11 +89,12 @@ struct cpuinfo_x86 {
+ #define X86_VENDOR_UNKNOWN 0xff
+ 
+ #ifdef CONFIG_SMP
+-extern struct cpuinfo_x86 cpu_data[];
+-#define current_cpu_data cpu_data[smp_processor_id()]
++DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
++#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
++#define current_cpu_data	cpu_data(smp_processor_id())
+ #else
+-#define cpu_data (&boot_cpu_data)
+-#define current_cpu_data boot_cpu_data
++#define cpu_data(cpu)		boot_cpu_data
++#define current_cpu_data	boot_cpu_data
+ #endif
+ 
+ extern char ignore_irq13;
+@@ -343,6 +345,16 @@ struct extended_sigtable {
+ };
+ 
+ 
++#if defined(CONFIG_MPSC) || defined(CONFIG_MCORE2)
++#define ASM_NOP1 P6_NOP1
++#define ASM_NOP2 P6_NOP2
++#define ASM_NOP3 P6_NOP3
++#define ASM_NOP4 P6_NOP4
++#define ASM_NOP5 P6_NOP5
++#define ASM_NOP6 P6_NOP6
++#define ASM_NOP7 P6_NOP7
++#define ASM_NOP8 P6_NOP8
++#else
+ #define ASM_NOP1 K8_NOP1
+ #define ASM_NOP2 K8_NOP2
+ #define ASM_NOP3 K8_NOP3
+@@ -351,6 +363,7 @@ struct extended_sigtable {
+ #define ASM_NOP6 K8_NOP6
+ #define ASM_NOP7 K8_NOP7
+ #define ASM_NOP8 K8_NOP8
++#endif
+ 
+ /* Opteron nops */
+ #define K8_NOP1 ".byte 0x90\n"
+@@ -362,6 +375,17 @@ struct extended_sigtable {
+ #define K8_NOP7	K8_NOP4 K8_NOP3
+ #define K8_NOP8	K8_NOP4 K8_NOP4
+ 
++/* P6 nops */
++/* uses eax dependencies (Intel-recommended choice) */
++#define P6_NOP1	".byte 0x90\n"
++#define P6_NOP2	".byte 0x66,0x90\n"
++#define P6_NOP3	".byte 0x0f,0x1f,0x00\n"
++#define P6_NOP4	".byte 0x0f,0x1f,0x40,0\n"
++#define P6_NOP5	".byte 0x0f,0x1f,0x44,0x00,0\n"
++#define P6_NOP6	".byte 0x66,0x0f,0x1f,0x44,0x00,0\n"
++#define P6_NOP7	".byte 0x0f,0x1f,0x80,0,0,0,0\n"
++#define P6_NOP8	".byte 0x0f,0x1f,0x84,0x00,0,0,0,0\n"
++
+ #define ASM_NOP_MAX 8
+ 
+ /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+@@ -377,12 +401,6 @@ static inline void sync_core(void)
+ 	asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
+ } 
+ 
+-#define ARCH_HAS_PREFETCH
+-static inline void prefetch(void *x) 
+-{ 
+-	asm volatile("prefetcht0 (%0)" :: "r" (x));
+-} 
+-
+ #define ARCH_HAS_PREFETCHW 1
+ static inline void prefetchw(void *x) 
+ { 
+@@ -398,11 +416,6 @@ static inline void prefetchw(void *x) 
+ 
+ #define cpu_relax()   rep_nop()
+ 
+-static inline void serialize_cpu(void)
+-{
+-	__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+-}
+-
+ static inline void __monitor(const void *eax, unsigned long ecx,
+ 		unsigned long edx)
+ {
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "smp_32.h"
++#else
++# include "smp_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -11,7 +11,7 @@
+ #endif
+ 
+ #if defined(CONFIG_X86_LOCAL_APIC) && !defined(__ASSEMBLY__)
+-#include <asm/bitops.h>
++#include <linux/bitops.h>
+ #include <asm/mpspec.h>
+ #include <asm/apic.h>
+ #ifdef CONFIG_X86_IO_APIC
+@@ -30,8 +30,8 @@
+ extern void smp_alloc_memory(void);
+ extern int pic_mode;
+ extern int smp_num_siblings;
+-extern cpumask_t cpu_sibling_map[];
+-extern cpumask_t cpu_core_map[];
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
+ 
+ extern void (*mtrr_hook) (void);
+ extern void zap_low_mappings (void);
+@@ -39,9 +39,11 @@ extern void lock_ipi_call_lock(void);
+ extern void unlock_ipi_call_lock(void);
+ 
+ #define MAX_APICID 256
+-extern u8 x86_cpu_to_apicid[];
++extern u8 __initdata x86_cpu_to_apicid_init[];
++extern void *x86_cpu_to_apicid_ptr;
++DECLARE_PER_CPU(u8, x86_cpu_to_apicid);
+ 
+-#define cpu_physical_id(cpu)	x86_cpu_to_apicid[cpu]
++#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+ extern void cpu_exit_clear(void);
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/smp_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -40,10 +40,19 @@ extern void lock_ipi_call_lock(void);
+ extern void unlock_ipi_call_lock(void);
+ extern int smp_num_siblings;
+ extern void smp_send_reschedule(int cpu);
++extern int smp_call_function_mask(cpumask_t mask, void (*func)(void *),
++				  void *info, int wait);
+ 
+-extern cpumask_t cpu_sibling_map[NR_CPUS];
+-extern cpumask_t cpu_core_map[NR_CPUS];
+-extern u8 cpu_llc_id[NR_CPUS];
++/*
++ * cpu_sibling_map and cpu_core_map now live
++ * in the per cpu area
++ *
++ * extern cpumask_t cpu_sibling_map[NR_CPUS];
++ * extern cpumask_t cpu_core_map[NR_CPUS];
++ */
++DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
++DECLARE_PER_CPU(cpumask_t, cpu_core_map);
++DECLARE_PER_CPU(u8, cpu_llc_id);
+ 
+ #define SMP_TRAMPOLINE_BASE 0x6000
+ 
+@@ -70,6 +79,8 @@ extern unsigned __cpuinitdata disabled_c
+ 
+ #endif /* CONFIG_SMP */
+ 
++#define safe_smp_processor_id()		smp_processor_id()
++
+ #ifdef CONFIG_X86_LOCAL_APIC
+ static inline int hard_smp_processor_id(void)
+ {
+@@ -82,8 +93,9 @@ static inline int hard_smp_processor_id(
+  * Some lowlevel functions might want to know about
+  * the real APIC ID <-> CPU # mapping.
+  */
+-extern u8 x86_cpu_to_apicid[NR_CPUS];	/* physical ID */
+-extern u8 x86_cpu_to_log_apicid[NR_CPUS];
++extern u8 __initdata x86_cpu_to_apicid_init[];
++extern void *x86_cpu_to_apicid_ptr;
++DECLARE_PER_CPU(u8, x86_cpu_to_apicid);	/* physical ID */
+ extern u8 bios_cpu_apicid[];
+ 
+ #ifdef CONFIG_X86_LOCAL_APIC
+@@ -118,8 +130,9 @@ static __inline int logical_smp_processo
+ #endif
+ 
+ #ifdef CONFIG_SMP
+-#define cpu_physical_id(cpu)		x86_cpu_to_apicid[cpu]
++#define cpu_physical_id(cpu)		per_cpu(x86_cpu_to_apicid, cpu)
+ #else
++extern unsigned int boot_cpu_id;
+ #define cpu_physical_id(cpu)		boot_cpu_id
+ #endif /* !CONFIG_SMP */
+ #endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/swiotlb.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "swiotlb_32.h"
++#else
++# include_next <asm/swiotlb.h>
++#endif
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "system_32.h"
++#else
++# include "system_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -9,6 +9,7 @@
+ #include <asm/hypervisor.h>
+ 
+ #ifdef __KERNEL__
++#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
+ 
+ struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
+ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
+@@ -138,7 +139,7 @@ static inline unsigned long xen_read_cr4
+ {
+ 	unsigned long val;
+ 	/* This could fault if %cr4 does not exist */
+-	asm("1: movl %%cr4, %0		\n"
++	asm volatile("1: movl %%cr4, %0		\n"
+ 		"2:				\n"
+ 		".section __ex_table,\"a\"	\n"
+ 		".long 1b,2b			\n"
+@@ -157,6 +158,11 @@ static inline void xen_wbinvd(void)
+ 	asm volatile("wbinvd": : :"memory");
+ }
+ 
++static inline void clflush(volatile void *__p)
++{
++	asm volatile("clflush %0" : "+m" (*(char __force *)__p));
++}
++
+ #define read_cr0()	(xen_read_cr0())
+ #define write_cr0(x)	(xen_write_cr0(x))
+ #define read_cr2()	(xen_read_cr2())
+@@ -207,6 +213,7 @@ static inline unsigned long get_limit(un
+ 
+ #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+ #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
++#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+ 
+ /**
+  * read_barrier_depends - Flush all pending reads that subsequents reads
+@@ -262,18 +269,18 @@ static inline unsigned long get_limit(un
+ 
+ #define read_barrier_depends()	do { } while(0)
+ 
++#ifdef CONFIG_SMP
++#define smp_mb()	mb()
++#ifdef CONFIG_X86_PPRO_FENCE
++# define smp_rmb()	rmb()
++#else
++# define smp_rmb()	barrier()
++#endif
+ #ifdef CONFIG_X86_OOSTORE
+-/* Actually there are no OOO store capable CPUs for now that do SSE, 
+-   but make it already an possibility. */
+-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
++# define smp_wmb() 	wmb()
+ #else
+-#define wmb()	__asm__ __volatile__ ("": : :"memory")
++# define smp_wmb()	barrier()
+ #endif
+-
+-#ifdef CONFIG_SMP
+-#define smp_mb()	mb()
+-#define smp_rmb()	rmb()
+-#define smp_wmb()	wmb()
+ #define smp_read_barrier_depends()	read_barrier_depends()
+ #define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+ #else
+@@ -300,5 +307,6 @@ extern unsigned long arch_align_stack(un
+ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+ 
+ void default_idle(void);
++void __show_registers(struct pt_regs *, int all);
+ 
+ #endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/system_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -11,8 +11,12 @@
+ 
+ #ifdef __KERNEL__
+ 
+-#define __STR(x) #x
+-#define STR(x) __STR(x)
++/* entries in ARCH_DLINFO: */
++#ifdef CONFIG_IA32_EMULATION
++# define AT_VECTOR_SIZE_ARCH 2
++#else
++# define AT_VECTOR_SIZE_ARCH 1
++#endif
+ 
+ #define __SAVE(reg,offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
+ #define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
+@@ -92,7 +96,7 @@ static inline void write_cr0(unsigned lo
+ 
+ #define read_cr3() ({ \
+ 	unsigned long __dummy; \
+-	asm("movq %%cr3,%0" : "=r" (__dummy)); \
++	asm volatile("movq %%cr3,%0" : "=r" (__dummy)); \
+ 	machine_to_phys(__dummy); \
+ })
+ 
+@@ -105,7 +109,7 @@ static inline void write_cr3(unsigned lo
+ static inline unsigned long read_cr4(void)
+ { 
+ 	unsigned long cr4;
+-	asm("movq %%cr4,%0" : "=r" (cr4));
++	asm volatile("movq %%cr4,%0" : "=r" (cr4));
+ 	return cr4;
+ }
+ 
+@@ -131,12 +135,17 @@ static inline void write_cr8(unsigned lo
+ 
+ #endif	/* __KERNEL__ */
+ 
++static inline void clflush(volatile void *__p)
++{
++	asm volatile("clflush %0" : "+m" (*(char __force *)__p));
++}
++
+ #define nop() __asm__ __volatile__ ("nop")
+ 
+ #ifdef CONFIG_SMP
+ #define smp_mb()	mb()
+-#define smp_rmb()	rmb()
+-#define smp_wmb()	wmb()
++#define smp_rmb()	barrier()
++#define smp_wmb()	barrier()
+ #define smp_read_barrier_depends()	do {} while(0)
+ #else
+ #define smp_mb()	barrier()
+@@ -153,12 +162,8 @@ static inline void write_cr8(unsigned lo
+  */
+ #define mb() 	asm volatile("mfence":::"memory")
+ #define rmb()	asm volatile("lfence":::"memory")
+-
+-#ifdef CONFIG_UNORDERED_IO
+ #define wmb()	asm volatile("sfence" ::: "memory")
+-#else
+-#define wmb()	asm volatile("" ::: "memory")
+-#endif
++
+ #define read_barrier_depends()	do {} while(0)
+ #define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+ 
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "tlbflush_32.h"
++#else
++# include "tlbflush_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_32.h	2009-11-06 10:51:17.000000000 +0100
+@@ -23,7 +23,6 @@
+  *  - flush_tlb_page(vma, vmaddr) flushes one page
+  *  - flush_tlb_range(vma, start, end) flushes a range of pages
+  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+- *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+  *
+  * ..but the i386 has somewhat limited tlb flushing capabilities,
+  * and page-granular flushes are available only on i486 and up.
+@@ -97,10 +96,4 @@ static inline void flush_tlb_kernel_rang
+ 	flush_tlb_all();
+ }
+ 
+-static inline void flush_tlb_pgtables(struct mm_struct *mm,
+-				      unsigned long start, unsigned long end)
+-{
+-	/* i386 does not keep any page table caches in TLB */
+-}
+-
+ #endif /* _I386_TLBFLUSH_H */
+--- head-2010-01-18.orig/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/tlbflush_64.h	2009-11-06 10:51:17.000000000 +0100
+@@ -28,7 +28,6 @@
+  *  - flush_tlb_page(vma, vmaddr) flushes one page
+  *  - flush_tlb_range(vma, start, end) flushes a range of pages
+  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+- *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+  *
+  * x86-64 can only flush individual pages or full VMs. For a range flush
+  * we always do the full VM. Might be worth trying if for a small
+@@ -95,12 +94,4 @@ static inline void flush_tlb_kernel_rang
+ 	flush_tlb_all();
+ }
+ 
+-static inline void flush_tlb_pgtables(struct mm_struct *mm,
+-				      unsigned long start, unsigned long end)
+-{
+-	/* x86_64 does not keep any page table caches in a software TLB.
+-	   The CPUs do in their hardware TLBs, but they are handled
+-	   by the normal TLB flushing algorithms. */
+-}
+-
+ #endif /* _X8664_TLBFLUSH_H */
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/arch/x86/include/mach-xen/asm/xor.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_X86_32
++# include "../../xor_32.h"
++#else
++# include "xor_64.h"
++#endif
+--- head-2010-01-18.orig/arch/x86/include/asm/mmu.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/mmu.h	2009-11-06 10:51:17.000000000 +0100
+@@ -11,6 +11,9 @@
+ typedef struct {
+ 	void *ldt;
+ 	int size;
++#ifdef CONFIG_XEN
++	unsigned has_foreign_mappings:1;
++#endif
+ 	struct mutex lock;
+ 	void *vdso;
+ } mm_context_t;
+--- head-2010-01-18.orig/include/linux/kexec.h	2009-12-04 10:44:41.000000000 +0100
++++ head-2010-01-18/include/linux/kexec.h	2009-11-06 10:51:17.000000000 +0100
+@@ -206,8 +206,15 @@ extern int dump_after_notifier;
+ #define VMCOREINFO_BYTES           (4096)
+ #define VMCOREINFO_NOTE_NAME       "VMCOREINFO"
+ #define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
++#if !defined(CONFIG_XEN) || !defined(CONFIG_X86)
+ #define VMCOREINFO_NOTE_SIZE       (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
+ 				    + VMCOREINFO_NOTE_NAME_BYTES)
++#else
++#define VMCOREINFO_NOTE_SIZE       ALIGN(KEXEC_NOTE_HEAD_BYTES*2 \
++					 + VMCOREINFO_BYTES \
++					 + VMCOREINFO_NOTE_NAME_BYTES, \
++					 PAGE_SIZE)
++#endif
+ 
+ /* Location of a reserved region to hold the crash kernel.
+  */
+--- head-2010-01-18.orig/include/linux/oprofile.h	2009-11-06 10:45:37.000000000 +0100
++++ head-2010-01-18/include/linux/oprofile.h	2009-11-06 10:51:17.000000000 +0100
+@@ -120,6 +120,8 @@ void oprofile_add_ext_sample(unsigned lo
+  * backtrace. */
+ void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
+ 
++void oprofile_add_mode(int cpu_mode);
++
+ /* add a backtrace entry, to be called from the ->backtrace callback */
+ void oprofile_add_trace(unsigned long eip);
+ 
+--- head-2010-01-18.orig/include/linux/sysctl.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/include/linux/sysctl.h	2009-11-06 10:51:17.000000000 +0100
+@@ -68,6 +68,7 @@ enum
+ 	CTL_BUS=8,		/* Busses */
+ 	CTL_ABI=9,		/* Binary emulation */
+ 	CTL_CPU=10,		/* CPU stuff (speed scaling, etc) */
++	CTL_XEN=123,		/* Xen info and control */
+ 	CTL_ARLAN=254,		/* arlan wireless driver */
+ 	CTL_S390DBF=5677,	/* s390 debug */
+ 	CTL_SUNRPC=7249,	/* sunrpc debug */
+--- head-2010-01-18.orig/include/xen/pcifront.h	2007-06-18 08:38:13.000000000 +0200
++++ head-2010-01-18/include/xen/pcifront.h	2009-11-06 10:51:17.000000000 +0100
+@@ -12,13 +12,11 @@
+ 
+ #ifndef __ia64__
+ 
++#include <asm/pci.h>
++
+ struct pcifront_device;
+ struct pci_bus;
+-
+-struct pcifront_sd {
+-	int domain;
+-	struct pcifront_device *pdev;
+-};
++#define pcifront_sd pci_sysdata
+ 
+ static inline struct pcifront_device *
+ pcifront_get_pdev(struct pcifront_sd *sd)
+@@ -34,18 +32,6 @@ static inline void pcifront_init_sd(stru
+ 	sd->pdev = pdev;
+ }
+ 
+-#if defined(CONFIG_PCI_DOMAINS)
+-static inline int pci_domain_nr(struct pci_bus *bus)
+-{
+-	struct pcifront_sd *sd = bus->sysdata;
+-	return sd->domain;
+-}
+-static inline int pci_proc_domain(struct pci_bus *bus)
+-{
+-	return pci_domain_nr(bus);
+-}
+-#endif /* CONFIG_PCI_DOMAINS */
+-
+ static inline void pcifront_setup_root_resources(struct pci_bus *bus,
+ 						 struct pcifront_sd *sd)
+ {
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ head-2010-01-18/include/xen/sysctl.h	2009-11-06 10:51:17.000000000 +0100
+@@ -0,0 +1,11 @@
++#ifndef _XEN_SYSCTL_H
++#define _XEN_SYSCTL_H
++
++/* CTL_XEN names: */
++enum
++{
++	CTL_XEN_INDEPENDENT_WALLCLOCK=1,
++	CTL_XEN_PERMITTED_CLOCK_JITTER=2,
++};
++
++#endif /* _XEN_SYSCTL_H */
+--- head-2010-01-18.orig/include/xen/xenbus.h	2009-11-06 10:51:07.000000000 +0100
++++ head-2010-01-18/include/xen/xenbus.h	2009-11-06 10:51:17.000000000 +0100
+@@ -107,7 +107,7 @@ struct xenbus_driver {
+ 	int (*suspend)(struct xenbus_device *dev);
+ 	int (*suspend_cancel)(struct xenbus_device *dev);
+ 	int (*resume)(struct xenbus_device *dev);
+-	int (*uevent)(struct xenbus_device *, char **, int, char *, int);
++	int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
+ 	struct device_driver driver;
+ 	int (*read_otherend_details)(struct xenbus_device *dev);
+ 	int (*is_ready)(struct xenbus_device *dev);
+--- head-2010-01-18.orig/kernel/kexec.c	2009-11-06 10:46:27.000000000 +0100
++++ head-2010-01-18/kernel/kexec.c	2009-11-06 10:51:17.000000000 +0100
+@@ -53,7 +53,11 @@ int dump_after_notifier;
+ 
+ /* vmcoreinfo stuff */
+ static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+-u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
++u32
++#if defined(CONFIG_XEN) && defined(CONFIG_X86)
++__attribute__((__section__(".bss.page_aligned"), __aligned__(PAGE_SIZE)))
++#endif
++vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+ size_t vmcoreinfo_size;
+ size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+ 
+@@ -1241,6 +1245,7 @@ static int __init crash_notes_memory_ini
+ module_init(crash_notes_memory_init)
+ 
+ 
++#ifndef CONFIG_XEN
+ /*
+  * parsing the "crashkernel" commandline
+  *
+@@ -1403,7 +1408,7 @@ int __init parse_crashkernel(char 		 *cm
+ 
+ 	return 0;
+ }
+-
++#endif
+ 
+ 
+ void crash_save_vmcoreinfo(void)
+@@ -1460,7 +1465,18 @@ static int __init crash_save_vmcoreinfo_
+ 
+ 	VMCOREINFO_SYMBOL(init_uts_ns);
+ 	VMCOREINFO_SYMBOL(node_online_map);
++#ifndef CONFIG_X86_XEN
+ 	VMCOREINFO_SYMBOL(swapper_pg_dir);
++#else
++/*
++ * Since for x86-32 Xen swapper_pg_dir is a pointer rather than an array,
++ * make the value stored consistent with native (i.e. the base address of
++ * the page directory).
++ */
++# define swapper_pg_dir *swapper_pg_dir
++	VMCOREINFO_SYMBOL(swapper_pg_dir);
++# undef swapper_pg_dir
++#endif
+ 	VMCOREINFO_SYMBOL(_stext);
+ 	VMCOREINFO_SYMBOL(vmlist);
+ 
+--- head-2010-01-18.orig/kernel/sysctl_check.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/kernel/sysctl_check.c	2009-12-16 11:50:26.000000000 +0100
+@@ -4,6 +4,7 @@
+ #include <linux/sunrpc/debug.h>
+ #include <linux/string.h>
+ #include <net/ip_vs.h>
++#include <xen/sysctl.h>
+ 
+ struct trans_ctl_table {
+ 	int			ctl_name;
+@@ -896,6 +897,14 @@ static const struct trans_ctl_table tran
+ 	{}
+ };
+ 
++#ifdef CONFIG_XEN
++static struct trans_ctl_table trans_xen_table[] = {
++	{ CTL_XEN_INDEPENDENT_WALLCLOCK,	"independent_wallclock" },
++	{ CTL_XEN_PERMITTED_CLOCK_JITTER,	"permitted_clock_jitter" },
++	{}
++};
++#endif
++
+ static const struct trans_ctl_table trans_arlan_conf_table0[] = {
+ 	{ 1,	"spreadingCode" },
+ 	{ 2,	"channelNumber" },
+@@ -1231,6 +1240,9 @@ static const struct trans_ctl_table tran
+ 	{ CTL_BUS,	"bus",		trans_bus_table },
+ 	{ CTL_ABI,	"abi" },
+ 	/* CTL_CPU not used */
++#ifdef CONFIG_XEN
++	{ CTL_XEN,	"xen",		trans_xen_table },
++#endif
+ 	{ CTL_ARLAN,	"arlan",	trans_arlan_table },
+ 	{ CTL_S390DBF,	"s390dbf",	trans_s390dbf_table },
+ 	{ CTL_SUNRPC,	"sunrpc",	trans_sunrpc_table },
+--- head-2010-01-18.orig/lib/swiotlb-xen.c	2009-11-06 10:49:47.000000000 +0100
++++ head-2010-01-18/lib/swiotlb-xen.c	2009-11-06 10:51:17.000000000 +0100
+@@ -27,7 +27,7 @@
+ #include <asm/uaccess.h>
+ #include <xen/gnttab.h>
+ #include <xen/interface/memory.h>
+-#include <asm-i386/mach-xen/asm/gnttab_dma.h>
++#include <asm/gnttab_dma.h>
+ 
+ int swiotlb;
+ EXPORT_SYMBOL(swiotlb);
+@@ -574,9 +574,10 @@ swiotlb_sync_single_for_device(struct de
+  * same here.
+  */
+ int
+-swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
++swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+ 	       int dir)
+ {
++	struct scatterlist *sg;
+ 	struct phys_addr buffer;
+ 	dma_addr_t dev_addr;
+ 	char *map;
+@@ -584,22 +585,22 @@ swiotlb_map_sg(struct device *hwdev, str
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+-	for (i = 0; i < nelems; i++, sg++) {
+-		dev_addr = gnttab_dma_map_page(sg->page) + sg->offset;
++	for_each_sg(sgl, sg, nelems, i) {
++		dev_addr = gnttab_dma_map_page(sg_page(sg)) + sg->offset;
+ 
+-		if (range_straddles_page_boundary(page_to_pseudophys(sg->page)
++		if (range_straddles_page_boundary(page_to_pseudophys(sg_page(sg))
+ 						  + sg->offset, sg->length)
+ 		    || address_needs_mapping(hwdev, dev_addr)) {
+ 			gnttab_dma_unmap_page(dev_addr);
+-			buffer.page   = sg->page;
++			buffer.page   = sg_page(sg);
+ 			buffer.offset = sg->offset;
+ 			map = map_single(hwdev, buffer, sg->length, dir);
+ 			if (!map) {
+ 				/* Don't panic here, we expect map_sg users
+ 				   to do proper error handling. */
+ 				swiotlb_full(hwdev, sg->length, dir, 0);
+-				swiotlb_unmap_sg(hwdev, sg - i, i, dir);
+-				sg[0].dma_length = 0;
++				swiotlb_unmap_sg(hwdev, sgl, i, dir);
++				sgl[0].dma_length = 0;
+ 				return 0;
+ 			}
+ 			sg->dma_address = virt_to_bus(map);
+@@ -615,19 +616,21 @@ swiotlb_map_sg(struct device *hwdev, str
+  * concerning calls here are the same as for swiotlb_unmap_single() above.
+  */
+ void
+-swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
++swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+ 		 int dir)
+ {
++	struct scatterlist *sg;
+ 	int i;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+-	for (i = 0; i < nelems; i++, sg++)
++	for_each_sg(sgl, sg, nelems, i) {
+ 		if (in_swiotlb_aperture(sg->dma_address))
+ 			unmap_single(hwdev, bus_to_virt(sg->dma_address),
+ 				     sg->dma_length, dir);
+ 		else
+ 			gnttab_dma_unmap_page(sg->dma_address);
++	}
+ }
+ 
+ /*
+@@ -638,31 +641,35 @@ swiotlb_unmap_sg(struct device *hwdev, s
+  * and usage.
+  */
+ void
+-swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
++swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sgl,
+ 			int nelems, int dir)
+ {
++	struct scatterlist *sg;
+ 	int i;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+-	for (i = 0; i < nelems; i++, sg++)
++	for_each_sg(sgl, sg, nelems, i) {
+ 		if (in_swiotlb_aperture(sg->dma_address))
+ 			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
++	}
+ }
+ 
+ void
+-swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
++swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sgl,
+ 			   int nelems, int dir)
+ {
++	struct scatterlist *sg;
+ 	int i;
+ 
+ 	BUG_ON(dir == DMA_NONE);
+ 
+-	for (i = 0; i < nelems; i++, sg++)
++	for_each_sg(sgl, sg, nelems, i) {
+ 		if (in_swiotlb_aperture(sg->dma_address))
+ 			sync_single(hwdev, bus_to_virt(sg->dma_address),
+ 				    sg->dma_length, dir);
++	}
+ }
+ 
+ #ifdef CONFIG_HIGHMEM
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-set-arch
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-set-arch
@@ -0,0 +1,38 @@
+From: Kieran Mansley <kmansley@solarflare.com>
+Subject: set efhw_arch field of device type
+References: bnc#489105
+Patch-mainline: n/a
+
+Acked-by: jbeulich@novell.com
+
+--- head-2009-04-07.orig/drivers/net/sfc/sfc_resource/ci/efhw/common.h	2009-04-07 14:39:57.000000000 +0200
++++ head-2009-04-07/drivers/net/sfc/sfc_resource/ci/efhw/common.h	2009-04-07 15:02:05.000000000 +0200
+@@ -41,6 +41,10 @@
+ 
+ #include <ci/efhw/common_sysdep.h>
+ 
++enum efhw_arch {
++	EFHW_ARCH_FALCON,
++};
++
+ typedef uint32_t efhw_buffer_addr_t;
+ #define EFHW_BUFFER_ADDR_FMT	"[ba:%"PRIx32"]"
+ 
+--- head-2009-04-07.orig/drivers/net/sfc/sfc_resource/nic.c	2009-04-07 14:39:57.000000000 +0200
++++ head-2009-04-07/drivers/net/sfc/sfc_resource/nic.c	2009-04-07 15:02:05.000000000 +0200
+@@ -47,6 +47,7 @@ int efhw_device_type_init(struct efhw_de
+ 	switch (device_id) {
+ 	case 0x0703:
+ 	case 0x6703:
++		dt->arch = EFHW_ARCH_FALCON;
+ 		dt->variant = 'A';
+ 		switch (class_revision) {
+ 		case 0:
+@@ -60,6 +61,7 @@ int efhw_device_type_init(struct efhw_de
+ 		}
+ 		break;
+ 	case 0x0710:
++		dt->arch = EFHW_ARCH_FALCON;
+ 		dt->variant = 'B';
+ 		switch (class_revision) {
+ 		case 2:
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-configurable-guest-devices
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-configurable-guest-devices
@@ -0,0 +1,74 @@
+From: jbeulich@novell.com
+Subject: allow number of guest devices to be configurable
+Patch-mainline: obsolete
+
+... and derive NR_DYNIRQS from this (rather than having a hard-coded
+value).
+Similarly, allow the number of simultaneous transmits in netback to be
+configurable.
+
+--- head-2010-01-04.orig/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-11-06 10:52:09.000000000 +0100
++++ head-2010-01-04/arch/x86/include/mach-xen/asm/irq_vectors.h	2009-12-22 13:21:47.000000000 +0100
+@@ -89,7 +89,7 @@ extern int nr_pirqs;
+ #endif
+ 
+ #define DYNIRQ_BASE			(PIRQ_BASE + nr_pirqs)
+-#define NR_DYNIRQS			256
++#define NR_DYNIRQS			(64 + CONFIG_XEN_NR_GUEST_DEVICES)
+ 
+ #define NR_IRQS				(NR_PIRQS + NR_DYNIRQS)
+ 
+--- head-2010-01-04.orig/drivers/xen/Kconfig	2009-12-18 12:30:54.000000000 +0100
++++ head-2010-01-04/drivers/xen/Kconfig	2009-12-18 12:31:00.000000000 +0100
+@@ -96,6 +96,15 @@ config XEN_NETDEV_BACKEND
+ 	  network devices to other guests via a high-performance shared-memory
+ 	  interface.
+ 
++config XEN_NETDEV_TX_SHIFT
++	int "Maximum simultaneous transmit requests (as a power of 2)"
++	depends on XEN_NETDEV_BACKEND
++	range 5 16
++	default 8
++	help
++	  The maximum number transmits the driver can hold pending, expressed
++	  as the exponent of a power of 2.
++
+ config XEN_NETDEV_PIPELINED_TRANSMITTER
+ 	bool "Pipelined transmitter (DANGEROUS)"
+ 	depends on XEN_NETDEV_BACKEND
+@@ -307,6 +316,16 @@ config XEN_SYSFS
+ 	help
+ 	  Xen hypervisor attributes will show up under /sys/hypervisor/.
+ 
++config XEN_NR_GUEST_DEVICES
++	int "Number of guest devices"
++	range 0 4032 if 64BIT
++	range 0 960
++	default 256 if XEN_BACKEND
++	default 16
++	help
++	  Specify the total number of virtual devices (i.e. both frontend
++	  and backend) that you want the kernel to be able to service.
++
+ choice
+ 	prompt "Xen version compatibility"
+ 	default XEN_COMPAT_030002_AND_LATER
+--- head-2010-01-04.orig/drivers/xen/netback/netback.c	2010-01-04 13:31:26.000000000 +0100
++++ head-2010-01-04/drivers/xen/netback/netback.c	2010-01-04 13:31:38.000000000 +0100
+@@ -71,7 +71,7 @@ static DECLARE_TASKLET(net_rx_tasklet, n
+ static struct timer_list net_timer;
+ static struct timer_list netbk_tx_pending_timer;
+ 
+-#define MAX_PENDING_REQS 256
++#define MAX_PENDING_REQS (1U << CONFIG_XEN_NETDEV_TX_SHIFT)
+ 
+ static struct sk_buff_head rx_queue;
+ 
+@@ -1265,6 +1265,7 @@ static void net_tx_action(unsigned long 
+ 	net_tx_action_dealloc();
+ 
+ 	mop = tx_map_ops;
++	BUILD_BUG_ON(MAX_SKB_FRAGS >= MAX_PENDING_REQS);
+ 	while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+ 		!list_empty(&net_schedule_list)) {
+ 		/* Get a netif from the list with work to do. */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.9-10
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.9-10
@@ -0,0 +1,175 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.10
+Patch-mainline: 2.6.32.10
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.9-10" by xen-port-patches.py
+
+--- sle11sp1-2010-09-22.orig/arch/x86/include/mach-xen/asm/pgalloc.h	2009-11-06 10:52:09.000000000 +0100
++++ sle11sp1-2010-09-22/arch/x86/include/mach-xen/asm/pgalloc.h	2010-03-22 12:47:01.000000000 +0100
+@@ -27,6 +27,11 @@ pmd_t *early_get_pmd(unsigned long va);
+ #endif
+ 
+ /*
++ * Flags to use when allocating a user page table page.
++ */
++extern gfp_t __userpte_alloc_gfp;
++
++/*
+  * Allocate and free page tables.
+  */
+ extern pgd_t *pgd_alloc(struct mm_struct *);
+--- sle11sp1-2010-09-22.orig/arch/x86/kernel/apic/io_apic-xen.c	2010-08-06 17:02:21.000000000 +0200
++++ sle11sp1-2010-09-22/arch/x86/kernel/apic/io_apic-xen.c	2010-08-06 17:02:25.000000000 +0200
+@@ -1626,6 +1626,60 @@ static void __init setup_IO_APIC_irqs(vo
+ 			" (apicid-pin) not connected\n");
+ }
+ 
++/*
++ * for the gsit that is not in first ioapic
++ * but could not use acpi_register_gsi()
++ * like some special sci in IBM x3330
++ */
++void setup_IO_APIC_irq_extra(u32 gsi)
++{
++	int apic_id = 0, pin, idx, irq;
++	int node = cpu_to_node(boot_cpu_id);
++	struct irq_desc *desc;
++	struct irq_cfg *cfg;
++
++	/*
++	 * Convert 'gsi' to 'ioapic.pin'.
++	 */
++	apic_id = mp_find_ioapic(gsi);
++	if (apic_id < 0)
++		return;
++
++	pin = mp_find_ioapic_pin(apic_id, gsi);
++	idx = find_irq_entry(apic_id, pin, mp_INT);
++	if (idx == -1)
++		return;
++
++	irq = pin_2_irq(idx, apic_id, pin);
++#ifdef CONFIG_XEN
++	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
++		return;
++#endif
++#ifdef CONFIG_SPARSE_IRQ
++	desc = irq_to_desc(irq);
++	if (desc)
++		return;
++#endif
++	desc = irq_to_desc_alloc_node(irq, node);
++	if (!desc) {
++		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
++		return;
++	}
++
++	cfg = desc->chip_data;
++	add_pin_to_irq_node(cfg, node, apic_id, pin);
++
++	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
++		pr_debug("Pin %d-%d already programmed\n",
++			 mp_ioapics[apic_id].apicid, pin);
++		return;
++	}
++	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
++
++	setup_IO_APIC_irq(apic_id, pin, irq, desc,
++			irq_trigger(idx), irq_polarity(idx));
++}
++
+ #ifndef CONFIG_XEN
+ /*
+  * Set up the timer pin, possibly with the 8259A-master behind.
+@@ -3273,12 +3327,9 @@ unsigned int create_irq_nr(unsigned int 
+ 	}
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ 
+-	if (irq > 0) {
+-		dynamic_irq_init(irq);
+-		/* restore it, in case dynamic_irq_init clear it */
+-		if (desc_new)
+-			desc_new->chip_data = cfg_new;
+-	}
++	if (irq > 0)
++		dynamic_irq_init_keep_chip_data(irq);
++
+ 	return irq;
+ }
+ 
+@@ -3301,17 +3352,12 @@ void destroy_irq(unsigned int irq)
+ {
+ 	unsigned long flags;
+ 	struct irq_cfg *cfg;
+-	struct irq_desc *desc;
+ 
+-	/* store it, in case dynamic_irq_cleanup clear it */
+-	desc = irq_to_desc(irq);
+-	cfg = desc->chip_data;
+-	dynamic_irq_cleanup(irq);
+-	/* connect back irq_cfg */
+-	desc->chip_data = cfg;
++	dynamic_irq_cleanup_keep_chip_data(irq);
+ 
+ 	free_irte(irq);
+ 	spin_lock_irqsave(&vector_lock, flags);
++	cfg = irq_to_desc(irq)->chip_data;
+ 	__clear_irq_vector(irq, cfg);
+ 	spin_unlock_irqrestore(&vector_lock, flags);
+ }
+--- sle11sp1-2010-09-22.orig/arch/x86/mm/pgtable-xen.c	2010-09-22 16:14:48.000000000 +0200
++++ sle11sp1-2010-09-22/arch/x86/mm/pgtable-xen.c	2010-09-22 16:19:06.000000000 +0200
+@@ -10,6 +10,14 @@
+ 
+ #define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+ 
++#ifdef CONFIG_HIGHPTE
++#define PGALLOC_USER_GFP __GFP_HIGHMEM
++#else
++#define PGALLOC_USER_GFP 0
++#endif
++
++gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP;
++
+ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+ {
+ 	pte_t *pte = (pte_t *)__get_free_page(PGALLOC_GFP);
+@@ -28,11 +36,7 @@ pgtable_t pte_alloc_one(struct mm_struct
+ {
+ 	struct page *pte;
+ 
+-#ifdef CONFIG_HIGHPTE
+-	pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0);
+-#else
+-	pte = alloc_pages(PGALLOC_GFP, 0);
+-#endif
++	pte = alloc_pages(__userpte_alloc_gfp, 0);
+ 	if (pte) {
+ 		pgtable_page_ctor(pte);
+ 		SetPageForeign(pte, _pte_free);
+@@ -41,6 +45,23 @@ pgtable_t pte_alloc_one(struct mm_struct
+ 	return pte;
+ }
+ 
++static int __init setup_userpte(char *arg)
++{
++	if (!arg)
++		return -EINVAL;
++
++	/*
++	 * "userpte=nohigh" disables allocation of user pagetables in
++	 * high memory.
++	 */
++	if (strcmp(arg, "nohigh") == 0)
++		__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
++	else
++		return -EINVAL;
++	return 0;
++}
++early_param("userpte", setup_userpte);
++
+ void __pte_free(pgtable_t pte)
+ {
+ 	if (!PageHighMem(pte)) {
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-fixup-arch-x86
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-fixup-arch-x86
@@ -0,0 +1,67 @@
+Subject: xen3 x86 build fixes.
+From: jbeulich@novell.com
+Patch-mainline: obsolete
+
+--- head-2010-01-18.orig/arch/x86/include/asm/topology.h	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/include/asm/topology.h	2009-10-15 11:04:35.000000000 +0200
+@@ -30,7 +30,7 @@
+ #  define ENABLE_TOPO_DEFINES
+ # endif
+ #else
+-# ifdef CONFIG_SMP
++# if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ #  define ENABLE_TOPO_DEFINES
+ # endif
+ #endif
+--- head-2010-01-18.orig/arch/x86/kdb/kdba_bt.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kdb/kdba_bt.c	2009-10-12 15:43:36.000000000 +0200
+@@ -3243,6 +3243,9 @@ bb_usage_mov(const struct bb_operand *sr
+ 	    bb_is_int_reg(dst->base_rc) &&
+ 	    full_register_dst) {
+ #ifdef	CONFIG_X86_32
++#ifndef TSS_sysenter_sp0
++#define TSS_sysenter_sp0 SYSENTER_stack_sp0
++#endif
+ 		/* mov from TSS_sysenter_sp0+offset to esp to fix up the
+ 		 * sysenter stack, it leaves esp well defined.  mov
+ 		 * TSS_ysenter_sp0+offset(%esp),%esp is followed by up to 5
+--- head-2010-01-18.orig/arch/x86/kernel/cpu/intel_cacheinfo.c	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/kernel/cpu/intel_cacheinfo.c	2010-01-18 16:16:46.000000000 +0100
+@@ -502,7 +502,7 @@ unsigned int __cpuinit init_intel_cachei
+ static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
+ #define CPUID4_INFO_IDX(x, y)	(&((per_cpu(cpuid4_info, x))[y]))
+ 
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+ {
+ 	struct _cpuid4_info	*this_leaf, *sibling_leaf;
+--- head-2010-01-18.orig/arch/x86/power/Makefile	2010-01-18 15:20:21.000000000 +0100
++++ head-2010-01-18/arch/x86/power/Makefile	2009-10-12 15:43:36.000000000 +0200
+@@ -5,3 +5,5 @@ CFLAGS_cpu.o	:= $(nostackp)
+ 
+ obj-$(CONFIG_PM_SLEEP)		+= cpu.o
+ obj-$(CONFIG_HIBERNATION)	+= hibernate_$(BITS).o hibernate_asm_$(BITS).o
++
++disabled-obj-$(CONFIG_XEN)	:= cpu.o
+--- head-2010-01-18.orig/arch/x86/power/cpu.c	2009-12-04 10:44:45.000000000 +0100
++++ head-2010-01-18/arch/x86/power/cpu.c	2009-10-12 15:43:36.000000000 +0200
+@@ -125,7 +125,6 @@ static void do_fpu_end(void)
+ 
+ static void fix_processor_context(void)
+ {
+-#ifndef CONFIG_X86_NO_TSS
+ 	int cpu = smp_processor_id();
+ 	struct tss_struct *t = &per_cpu(init_tss, cpu);
+ 
+@@ -138,10 +137,7 @@ static void fix_processor_context(void)
+ 
+ #ifdef CONFIG_X86_64
+ 	get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;
+-#endif
+-#endif
+ 
+-#ifdef CONFIG_X86_64
+ 	syscall_init();				/* This sets MSR_*STAR and related */
+ #endif
+ 	load_TR_desc();				/* This does ltr */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-fixup-common
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-fixup-common
@@ -0,0 +1,424 @@
+Subject: Fix xen build.
+From: jbeulich@novell.com
+Patch-mainline: obsolete
+
+--- sle11sp1-2010-01-20.orig/drivers/acpi/acpica/hwsleep.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/acpica/hwsleep.c	2009-11-06 10:45:37.000000000 +0100
+@@ -419,6 +419,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_stat
+  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+  *
+  ******************************************************************************/
++#ifndef CONFIG_XEN
+ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
+ {
+ 	u32 in_value;
+@@ -472,6 +473,7 @@ acpi_status asmlinkage acpi_enter_sleep_
+ }
+ 
+ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
++#endif
+ 
+ /*******************************************************************************
+  *
+--- sle11sp1-2010-01-20.orig/drivers/acpi/processor_perflib.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/acpi/processor_perflib.c	2009-12-03 15:24:07.000000000 +0100
+@@ -168,7 +168,7 @@ int acpi_processor_ppc_has_changed(struc
+ 	else
+ #ifdef CONFIG_CPU_FREQ
+ 		return cpufreq_update_policy(pr->id);
+-#elif CONFIG_PROCESSOR_EXTERNAL_CONTROL
++#elif defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
+ 		return processor_notify_external(pr,
+ 				PROCESSOR_PM_CHANGE, PM_TYPE_PERF);
+ #endif
+--- sle11sp1-2010-01-20.orig/drivers/base/cpu.c	2010-01-20 10:20:51.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/base/cpu.c	2009-12-04 10:48:00.000000000 +0100
+@@ -80,7 +80,7 @@ static inline void register_cpu_control(
+ }
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
+-#ifdef CONFIG_KEXEC
++#if defined(CONFIG_KEXEC) && !defined(CONFIG_XEN)
+ #include <linux/kexec.h>
+ 
+ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
+@@ -219,7 +219,7 @@ int __cpuinit register_cpu(struct cpu *c
+ 	if (!error)
+ 		register_cpu_under_node(num, cpu_to_node(num));
+ 
+-#ifdef CONFIG_KEXEC
++#if defined(CONFIG_KEXEC) && !defined(CONFIG_XEN)
+ 	if (!error)
+ 		error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
+ #endif
+--- sle11sp1-2010-01-20.orig/drivers/ide/ide-lib.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/ide/ide-lib.c	2009-11-06 10:45:37.000000000 +0100
+@@ -18,6 +18,16 @@ void ide_toggle_bounce(ide_drive_t *driv
+ {
+ 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
+ 
++#ifndef CONFIG_XEN
++	if (!PCI_DMA_BUS_IS_PHYS) {
++		addr = BLK_BOUNCE_ANY;
++	} else if (on && drive->media == ide_disk) {
++		struct device *dev = drive->hwif->dev;
++
++		if (dev && dev->dma_mask)
++			addr = *dev->dma_mask;
++	}
++#else
+ 	if (on && drive->media == ide_disk) {
+ 		struct device *dev = drive->hwif->dev;
+ 
+@@ -26,6 +36,7 @@ void ide_toggle_bounce(ide_drive_t *driv
+ 		else if (dev && dev->dma_mask)
+ 			addr = *dev->dma_mask;
+ 	}
++#endif
+ 
+ 	if (drive->queue)
+ 		blk_queue_bounce_limit(drive->queue, addr);
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/buffer_sync.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/buffer_sync.c	2009-11-06 10:45:37.000000000 +0100
+@@ -46,7 +46,9 @@ static cpumask_var_t marked_cpus;
+ static DEFINE_SPINLOCK(task_mortuary);
+ static void process_task_mortuary(void);
+ 
++#ifdef CONFIG_XEN
+ static int cpu_current_domain[NR_CPUS];
++#endif
+ 
+ /* Take ownership of the task struct and place it on the
+  * list for processing. Only after two full buffer syncs
+@@ -158,11 +160,13 @@ static void end_sync(void)
+ int sync_start(void)
+ {
+ 	int err;
++#ifdef CONFIG_XEN
+ 	int i;
+ 
+ 	for (i = 0; i < NR_CPUS; i++) {
+ 		cpu_current_domain[i] = COORDINATOR_DOMAIN;
+ 	}
++#endif
+ 
+ 	if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
+ 		return -ENOMEM;
+@@ -312,12 +316,14 @@ static void add_cpu_mode_switch(unsigned
+ 	}
+ }
+ 
++#ifdef CONFIG_XEN
+ static void add_domain_switch(unsigned long domain_id)
+ {
+ 	add_event_entry(ESCAPE_CODE);
+ 	add_event_entry(DOMAIN_SWITCH_CODE);
+ 	add_event_entry(domain_id);
+ }
++#endif
+ 
+ static void
+ add_user_ctx_switch(struct task_struct const *task, unsigned long cookie)
+@@ -540,10 +546,12 @@ void sync_buffer(int cpu)
+ 
+ 	add_cpu_switch(cpu);
+ 
++#ifdef CONFIG_XEN
+ 	/* We need to assign the first samples in this CPU buffer to the
+ 	   same domain that we were processing at the last sync_buffer */
+ 	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
+ 		add_domain_switch(cpu_current_domain[cpu]);
++#endif
+ 
+ 	op_cpu_buffer_reset(cpu);
+ 	available = op_cpu_buffer_entries(cpu);
+@@ -553,12 +561,14 @@ void sync_buffer(int cpu)
+ 		if (!sample)
+ 			break;
+ 
++#ifdef CONFIG_XEN
+ 		if (domain_switch) {
+ 			cpu_current_domain[cpu] = sample->eip;
+ 			add_domain_switch(sample->eip);
+ 			domain_switch = 0;
+ 			continue;
+ 		}
++#endif
+ 
+ 		if (is_code(sample->eip)) {
+ 			flags = sample->event;
+@@ -584,17 +594,21 @@ void sync_buffer(int cpu)
+ 					cookie = get_exec_dcookie(mm);
+ 				add_user_ctx_switch(new, cookie);
+ 			}
++#ifdef CONFIG_XEN
+ 			if (flags & DOMAIN_SWITCH)
+ 				domain_switch = 1;
++#endif
+ 			if (op_cpu_buffer_get_size(&entry))
+ 				add_data(&entry, mm);
+ 			continue;
+ 		}
+ 
++#ifdef CONFIG_XEN
+ 		if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) {
+ 			add_sample_entry(sample->eip, sample->event);
+ 			continue;
+ 		}
++#endif
+ 
+ 		if (state < sb_bt_start)
+ 			/* ignore sample */
+@@ -611,9 +625,11 @@ void sync_buffer(int cpu)
+ 	}
+ 	release_mm(mm);
+ 
++#ifdef CONFIG_XEN
+ 	/* We reset domain to COORDINATOR at each CPU switch */
+ 	if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN)
+ 		add_domain_switch(COORDINATOR_DOMAIN);
++#endif
+ 
+ 	mark_done(cpu);
+ 
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/cpu_buffer.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/cpu_buffer.c	2009-11-06 10:45:37.000000000 +0100
+@@ -58,7 +58,11 @@ static void wq_sync_buffer(struct work_s
+ #define DEFAULT_TIMER_EXPIRE (HZ / 10)
+ static int work_enabled;
+ 
++#ifndef CONFIG_XEN
++#define current_domain COORDINATOR_DOMAIN
++#else
+ static int32_t current_domain = COORDINATOR_DOMAIN;
++#endif
+ 
+ unsigned long oprofile_get_cpu_buffer_size(void)
+ {
+@@ -463,6 +467,7 @@ fail:
+ 	return;
+ }
+ 
++#ifdef CONFIG_XEN
+ int oprofile_add_domain_switch(int32_t domain_id)
+ {
+ 	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
+@@ -481,6 +486,7 @@ int oprofile_add_domain_switch(int32_t d
+ 
+ 	return 1;
+ }
++#endif
+ 
+ /*
+  * This serves to avoid cpu buffer overflow, and makes sure
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/oprof.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/oprof.c	2009-11-06 10:45:37.000000000 +0100
+@@ -39,6 +39,7 @@ static DEFINE_MUTEX(start_mutex);
+  */
+ static int timer = 0;
+ 
++#ifdef CONFIG_XEN
+ int oprofile_set_active(int active_domains[], unsigned int adomains)
+ {
+ 	int err;
+@@ -64,6 +65,7 @@ int oprofile_set_passive(int passive_dom
+ 	mutex_unlock(&start_mutex);
+ 	return err;
+ }
++#endif
+ 
+ int oprofile_setup(void)
+ {
+--- sle11sp1-2010-01-20.orig/drivers/oprofile/oprofile_files.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/oprofile/oprofile_files.c	2009-11-06 10:45:37.000000000 +0100
+@@ -171,6 +171,8 @@ static const struct file_operations dump
+ 	.write		= dump_write,
+ };
+ 
++#ifdef CONFIG_XEN
++
+ #define TMPBUFSIZE 512
+ 
+ static unsigned int adomains = 0;
+@@ -360,6 +362,8 @@ static const struct file_operations pass
+ 	.write		= pdomain_write,
+ };
+ 
++#endif /* CONFIG_XEN */
++
+ void oprofile_create_files(struct super_block *sb, struct dentry *root)
+ {
+ 	/* reinitialize default values */
+@@ -370,8 +374,10 @@ void oprofile_create_files(struct super_
+ 
+ 	oprofilefs_create_file(sb, root, "enable", &enable_fops);
+ 	oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
++#ifdef CONFIG_XEN
+ 	oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
+ 	oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops);
++#endif
+ 	oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
+ 	oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size);
+ 	oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed);
+--- sle11sp1-2010-01-20.orig/drivers/xen/core/smpboot.c	2009-05-19 09:16:41.000000000 +0200
++++ sle11sp1-2010-01-20/drivers/xen/core/smpboot.c	2009-11-06 10:45:37.000000000 +0100
+@@ -57,7 +57,6 @@ u8 cpu_2_logical_apicid[NR_CPUS] = { [0 
+ 
+ cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+ cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+-EXPORT_SYMBOL(cpu_core_map);
+ 
+ #if defined(__i386__)
+ u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
+--- sle11sp1-2010-01-20.orig/include/linux/mm.h	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/mm.h	2009-11-06 10:45:37.000000000 +0100
+@@ -210,6 +210,7 @@ struct vm_operations_struct {
+ 	int (*access)(struct vm_area_struct *vma, unsigned long addr,
+ 		      void *buf, int len, int write);
+ 
++#ifdef CONFIG_XEN
+ 	/* Area-specific function for clearing the PTE at @ptep. Returns the
+ 	 * original value of @ptep. */
+ 	pte_t (*zap_pte)(struct vm_area_struct *vma,
+@@ -217,6 +218,7 @@ struct vm_operations_struct {
+ 
+ 	/* called before close() to indicate no more pages should be mapped */
+ 	void (*unmap)(struct vm_area_struct *area);
++#endif
+ 
+ #ifdef CONFIG_NUMA
+ 	/*
+--- sle11sp1-2010-01-20.orig/include/linux/oprofile.h	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/oprofile.h	2009-11-06 10:45:37.000000000 +0100
+@@ -16,8 +16,9 @@
+ #include <linux/types.h>
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
+-
++#ifdef CONFIG_XEN
+ #include <xen/interface/xenoprof.h>
++#endif
+  
+ /* Each escaped entry is prefixed by ESCAPE_CODE
+  * then one of the following codes, then the
+@@ -55,11 +56,12 @@ struct oprofile_operations {
+ 	/* create any necessary configuration files in the oprofile fs.
+ 	 * Optional. */
+ 	int (*create_files)(struct super_block * sb, struct dentry * root);
++#ifdef CONFIG_XEN
+ 	/* setup active domains with Xen */
+ 	int (*set_active)(int *active_domains, unsigned int adomains);
+ 	/* setup passive domains with Xen */
+ 	int (*set_passive)(int *passive_domains, unsigned int pdomains);
+-
++#endif
+ 	/* Do any necessary interrupt setup. Optional. */
+ 	int (*setup)(void);
+ 	/* Do any necessary interrupt shutdown. Optional. */
+--- sle11sp1-2010-01-20.orig/include/linux/page-flags.h	2009-12-16 11:48:10.000000000 +0100
++++ sle11sp1-2010-01-20/include/linux/page-flags.h	2009-12-16 11:49:19.000000000 +0100
+@@ -112,7 +112,7 @@ enum pageflags {
+ #endif
+ #ifdef CONFIG_XEN
+ 	PG_foreign,		/* Page is owned by foreign allocator. */
+-	PG_netback,		/* Page is owned by netback */
++	/* PG_netback,		   Page is owned by netback */
+ 	PG_blkback,		/* Page is owned by blkback */
+ #endif
+ 	__NR_PAGEFLAGS,
+@@ -357,9 +357,11 @@ CLEARPAGEFLAG(Uptodate, uptodate)
+ #define PageForeignDestructor(_page, order)		\
+ 	((void (*)(struct page *, unsigned int))(_page)->index)(_page, order)
+ 
++#if 0
+ #define PageNetback(page)       test_bit(PG_netback, &(page)->flags)
+ #define SetPageNetback(page)    set_bit(PG_netback, &(page)->flags)
+ #define ClearPageNetback(page)  clear_bit(PG_netback, &(page)->flags)
++#endif
+ 
+ #define PageBlkback(page)       test_bit(PG_blkback, &(page)->flags)
+ #define SetPageBlkback(page)    set_bit(PG_blkback, &(page)->flags)
+--- sle11sp1-2010-01-20.orig/kernel/kexec.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/kernel/kexec.c	2009-11-06 10:45:37.000000000 +0100
+@@ -45,8 +45,10 @@
+ #include <linux/kdb.h>
+ #endif
+ 
++#ifndef CONFIG_XEN
+ /* Per cpu memory for storing cpu states in case of system crash. */
+ note_buf_t* crash_notes;
++#endif
+ int dump_after_notifier;
+ 
+ /* vmcoreinfo stuff */
+@@ -1168,6 +1170,7 @@ static void final_note(u32 *buf)
+ 	memcpy(buf, &note, sizeof(note));
+ }
+ 
++#ifndef CONFIG_XEN
+ void crash_save_cpu(struct pt_regs *regs, int cpu)
+ {
+ 	struct elf_prstatus prstatus;
+@@ -1193,6 +1196,7 @@ void crash_save_cpu(struct pt_regs *regs
+ 		      	      &prstatus, sizeof(prstatus));
+ 	final_note(buf);
+ }
++#endif
+ 
+ #ifdef CONFIG_SYSCTL
+ static ctl_table dump_after_notifier_table[] = {
+@@ -1220,6 +1224,7 @@ static ctl_table kexec_sys_table[] = {
+ 
+ static int __init crash_notes_memory_init(void)
+ {
++#ifndef CONFIG_XEN
+ 	/* Allocate memory for saving cpu registers. */
+ 	crash_notes = alloc_percpu(note_buf_t);
+ 	if (!crash_notes) {
+@@ -1227,6 +1232,7 @@ static int __init crash_notes_memory_ini
+ 		" states failed\n");
+ 		return -ENOMEM;
+ 	}
++#endif
+ #ifdef CONFIG_SYSCTL
+ 	register_sysctl_table(kexec_sys_table);
+ #endif
+--- sle11sp1-2010-01-20.orig/mm/memory.c	2009-12-04 10:44:41.000000000 +0100
++++ sle11sp1-2010-01-20/mm/memory.c	2009-12-04 10:48:12.000000000 +0100
+@@ -851,10 +851,12 @@ static unsigned long zap_pte_range(struc
+ 				     page->index > details->last_index))
+ 					continue;
+ 			}
++#ifdef CONFIG_XEN
+ 			if (unlikely(vma->vm_ops && vma->vm_ops->zap_pte))
+ 				ptent = vma->vm_ops->zap_pte(vma, addr, pte,
+ 							     tlb->fullmm);
+ 			else
++#endif
+ 				ptent = ptep_get_and_clear_full(mm, addr, pte,
+ 								tlb->fullmm);
+ 			tlb_remove_tlb_entry(tlb, pte, addr);
+--- sle11sp1-2010-01-20.orig/mm/mmap.c	2010-01-20 10:22:09.000000000 +0100
++++ sle11sp1-2010-01-20/mm/mmap.c	2010-01-20 10:22:30.000000000 +0100
+@@ -1845,8 +1845,10 @@ static void unmap_region(struct mm_struc
+ 
+ static inline void unmap_vma(struct vm_area_struct *vma)
+ {
++#ifdef CONFIG_XEN
+ 	if (unlikely(vma->vm_ops && vma->vm_ops->unmap))
+ 		vma->vm_ops->unmap(vma);
++#endif
+ }
+ 
+ /*
+@@ -2159,8 +2161,10 @@ void exit_mmap(struct mm_struct *mm)
+ 
+ 	arch_exit_mmap(mm);
+ 
++#ifdef CONFIG_XEN
+ 	for (vma = mm->mmap; vma; vma = vma->vm_next)
+ 		unmap_vma(vma);
++#endif
+ 
+ 	vma = mm->mmap;
+ 	if (!vma)	/* Can happen if dup_mmap() received an OOM */
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-patch-2.6.32.10-11
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-patch-2.6.32.10-11
@@ -0,0 +1,115 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: Linux 2.6.32.11
+Patch-mainline: 2.6.32.11
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+Automatically created from "patches.kernel.org/patch-2.6.32.10-11" by xen-port-patches.py
+
+--- sle11sp1-2010-10-26.orig/arch/x86/include/mach-xen/asm/fixmap.h	2009-11-06 10:52:22.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/include/mach-xen/asm/fixmap.h	2010-04-12 14:52:38.000000000 +0200
+@@ -82,6 +82,9 @@ enum fixed_addresses {
+ #endif
+ 	FIX_DBGP_BASE,
+ 	FIX_EARLYCON_MEM_BASE,
++#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
++	FIX_OHCI1394_BASE,
++#endif
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+ #endif
+@@ -133,9 +136,6 @@ enum fixed_addresses {
+ 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+ 			(__end_of_permanent_fixed_addresses & 255),
+ 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+-	FIX_OHCI1394_BASE,
+-#endif
+ #ifdef CONFIG_X86_32
+ 	FIX_WP_TEST,
+ #endif
+--- sle11sp1-2010-10-26.orig/arch/x86/kernel/mpparse-xen.c	2009-11-06 10:52:22.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/kernel/mpparse-xen.c	2010-04-12 14:52:38.000000000 +0200
+@@ -371,13 +371,6 @@ static int __init smp_read_mpc(struct mp
+ 		x86_init.mpparse.mpc_record(1);
+ 	}
+ 
+-#ifdef CONFIG_X86_BIGSMP
+-	generic_bigsmp_probe();
+-#endif
+-
+-	if (apic->setup_apic_routing)
+-		apic->setup_apic_routing();
+-
+ 	if (!num_processors)
+ 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+ 	return num_processors;
+--- sle11sp1-2010-10-26.orig/arch/x86/kernel/process-xen.c	2010-02-09 17:12:56.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/kernel/process-xen.c	2010-04-12 14:52:38.000000000 +0200
+@@ -423,21 +423,37 @@ static int __cpuinit mwait_usable(const 
+ }
+ 
+ /*
+- * Check for AMD CPUs, which have potentially C1E support
++ * Check for AMD CPUs, where APIC timer interrupt does not wake up CPU from C1e.
++ * For more information see
++ * - Erratum #400 for NPT family 0xf and family 0x10 CPUs
++ * - Erratum #365 for family 0x11 (not affected because C1e not in use)
+  */
+ static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
+ {
++	u64 val;
+ 	if (c->x86_vendor != X86_VENDOR_AMD)
+-		return 0;
+-
+-	if (c->x86 < 0x0F)
+-		return 0;
++		goto no_c1e_idle;
+ 
+ 	/* Family 0x0f models < rev F do not have C1E */
+-	if (c->x86 == 0x0f && c->x86_model < 0x40)
+-		return 0;
++	if (c->x86 == 0x0F && c->x86_model >= 0x40)
++		return 1;
++
++	if (c->x86 == 0x10) {
++		/*
++		 * check OSVW bit for CPUs that are not affected
++		 * by erratum #400
++		 */
++		rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
++		if (val >= 2) {
++			rdmsrl(MSR_AMD64_OSVW_STATUS, val);
++			if (!(val & BIT(1)))
++				goto no_c1e_idle;
++		}
++		return 1;
++	}
+ 
+-	return 1;
++no_c1e_idle:
++	return 0;
+ }
+ 
+ static cpumask_var_t c1e_mask;
+--- sle11sp1-2010-10-26.orig/arch/x86/kernel/process_64-xen.c	2010-03-17 14:38:41.000000000 +0100
++++ sle11sp1-2010-10-26/arch/x86/kernel/process_64-xen.c	2010-04-12 14:52:38.000000000 +0200
+@@ -621,6 +621,7 @@ void set_personality_ia32(void)
+ 
+ 	/* Make sure to be in 32bit mode */
+ 	set_thread_flag(TIF_IA32);
++	current->personality |= force_personality32;
+ 
+ 	/* Prepare the first "return" to user space */
+ 	current_thread_info()->status |= TS_COMPAT;
+--- sle11sp1-2010-10-26.orig/drivers/hwmon/coretemp-xen.c	2010-10-26 09:19:30.000000000 +0200
++++ sle11sp1-2010-10-26/drivers/hwmon/coretemp-xen.c	2010-10-26 09:19:38.000000000 +0200
+@@ -233,7 +233,7 @@ static int adjust_tjmax(struct coretemp_
+ 		if (err < 0) {
+ 			dev_warn(dev,
+ 				 "Unable to access MSR 0xEE, for Tjmax, left"
+-				 " at default");
++				 " at default\n");
+ 		} else if (eax & 0x40000000) {
+ 			tjmax = tjmax_ee;
+ 		}
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen3-x86-64-preserve-large-page-mapping-for-1st-2mb-kernel-txt-with-config_debug_rodata
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen3-x86-64-preserve-large-page-mapping-for-1st-2mb-kernel-txt-with-config_debug_rodata
@@ -0,0 +1,79 @@
+From: Suresh Siddha <suresh.b.siddha@intel.com>
+Date: Wed, 14 Oct 2009 21:46:55 +0000 (-0700)
+Subject: x86-64: preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA
+Patch-mainline: 2.6.33-rc1
+Git-commit: b9af7c0d44b8bb71e3af5e94688d076414aa8c87
+References: bnc#558249
+
+x86-64: preserve large page mapping for 1st 2MB kernel txt with CONFIG_DEBUG_RODATA
+
+In the first 2MB, kernel text is co-located with kernel static
+page tables setup by head_64.S.  CONFIG_DEBUG_RODATA chops this
+2MB large page mapping to small 4KB pages as we mark the kernel text as RO,
+leaving the static page tables as RW.
+
+With CONFIG_DEBUG_RODATA disabled, OLTP run on NHM-EP shows 1% improvement
+with 2% reduction in system time and 1% improvement in iowait idle time.
+
+To recover this, move the kernel static page tables to .data section, so that
+we don't have to break the first 2MB of kernel text to small pages with
+CONFIG_DEBUG_RODATA.
+
+Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
+LKML-Reference: <20091014220254.063193621@sbs-t61.sc.intel.com>
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+Automatically created from "patches.arch/x86-64-preserve-large-page-mapping-for-1st-2mb-kernel-txt-with-config_debug_rodata" by xen-port-patches.py
+
+--- head-2009-12-04.orig/arch/x86/kernel/head_64-xen.S	2009-11-06 10:52:22.000000000 +0100
++++ head-2009-12-04/arch/x86/kernel/head_64-xen.S	2009-12-04 14:37:14.000000000 +0100
+@@ -51,9 +51,9 @@ startup_64:
+ 
+ #define NEXT_PAGE(name) \
+ 	.balign	PAGE_SIZE; \
+-	phys_##name = . - .head.text; \
+ ENTRY(name)
+ 
++	__PAGE_ALIGNED_BSS
+ NEXT_PAGE(init_level4_pgt)
+ 	.fill	512,8,0
+         /*
+@@ -81,7 +81,9 @@ NEXT_PAGE(level2_fixmap_pgt)
+ NEXT_PAGE(level1_fixmap_pgt)
+ 	.fill	512,8,0
+ 
++	.previous
+ NEXT_PAGE(hypercall_page)
++	phys_hypercall_page = . - .head.text
+ 	CFI_STARTPROC
+ 	.rept 0x1000 / 0x20
+ 	.skip 1 /* push %rcx */
+--- head-2009-12-04.orig/arch/x86/mm/init_64-xen.c	2009-11-06 10:52:23.000000000 +0100
++++ head-2009-12-04/arch/x86/mm/init_64-xen.c	2009-12-04 12:04:25.000000000 +0100
+@@ -952,7 +952,7 @@ static int kernel_set_to_readonly;
+ 
+ void set_kernel_text_rw(void)
+ {
+-	unsigned long start = PFN_ALIGN(_stext);
++	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long end = PFN_ALIGN(__start_rodata);
+ 
+ 	if (!kernel_set_to_readonly)
+@@ -966,7 +966,7 @@ void set_kernel_text_rw(void)
+ 
+ void set_kernel_text_ro(void)
+ {
+-	unsigned long start = PFN_ALIGN(_stext);
++	unsigned long start = PFN_ALIGN(_text);
+ 	unsigned long end = PFN_ALIGN(__start_rodata);
+ 
+ 	if (!kernel_set_to_readonly)
+@@ -980,7 +980,7 @@ void set_kernel_text_ro(void)
+ 
+ void mark_rodata_ro(void)
+ {
+-	unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
++	unsigned long start = PFN_ALIGN(_text), end = PFN_ALIGN(__end_rodata);
+ 	unsigned long rodata_start =
+ 		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+ 
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/xen-privcmd-mmap-batch-clear
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/xen-privcmd-mmap-batch-clear
@@ -0,0 +1,48 @@
+From: jbeulich@novell.com
+Subject: privcmd: mmapbatch-v2 fixes
+Patch-mainline: n/a
+
+- clear error indication array when no error encountered
+- no need to copy back mfn array in comapt mode shim
+
+--- sle11sp1-2010-01-20.orig/drivers/xen/privcmd/compat_privcmd.c	2009-11-06 10:45:48.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/privcmd/compat_privcmd.c	2010-01-21 12:31:29.000000000 +0100
+@@ -102,7 +102,7 @@ int privcmd_ioctl_32(int fd, unsigned in
+ 		struct privcmd_mmapbatch_v2_32 n32;
+ #ifdef xen_pfn32_t
+ 		xen_pfn_t *__user arr;
+-		xen_pfn32_t *__user arr32;
++		const xen_pfn32_t *__user arr32;
+ 		unsigned int i;
+ #endif
+ 
+@@ -133,17 +133,6 @@ int privcmd_ioctl_32(int fd, unsigned in
+ #endif
+ 
+ 		ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, (unsigned long)p);
+-
+-#ifdef xen_pfn32_t
+-		for (i = 0; !ret && i < n32.num; ++i) {
+-			xen_pfn_t mfn;
+-
+-			if (get_user(mfn, arr + i) || put_user(mfn, arr32 + i))
+-				ret = -EFAULT;
+-			else if (mfn != (xen_pfn32_t)mfn)
+-				ret = -ERANGE;
+-		}
+-#endif
+ 	}
+ 		break;
+ 	default:
+--- sle11sp1-2010-01-20.orig/drivers/xen/privcmd/privcmd.c	2010-01-19 10:33:58.000000000 +0100
++++ sle11sp1-2010-01-20/drivers/xen/privcmd/privcmd.c	2010-01-21 12:21:44.000000000 +0100
+@@ -389,7 +389,8 @@ static long privcmd_ioctl(struct file *f
+ 					ret = -EFAULT;
+ 				i += nr; p += nr;
+ 			}
+-		}
++		} else if (clear_user(m.err, nr_pages * sizeof(*m.err)))
++			ret = -EFAULT;
+ 
+ 	mmapbatch_v2_out:
+ 		list_for_each_safe(l, l2, &pagelist)
--- linux-ec2-2.6.32.orig/debian.ec2/patches.xen/sfc-endianness
+++ linux-ec2-2.6.32/debian.ec2/patches.xen/sfc-endianness
@@ -0,0 +1,18 @@
+From: jbeulich@novell.com
+Subject: fix building with gcc 4.4
+Patch-mainline: obsolete
+
+--- head-2009-05-19.orig/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h	2008-07-17 16:18:07.000000000 +0200
++++ head-2009-05-19/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h	2009-05-19 15:44:02.000000000 +0200
+@@ -42,9 +42,9 @@
+ 
+ #include <linux/io.h>
+ 
+-#ifdef __LITTLE_ENDIAN
++#if defined(__LITTLE_ENDIAN)
+ #define EFHW_IS_LITTLE_ENDIAN
+-#elif __BIG_ENDIAN
++#elif defined(__BIG_ENDIAN)
+ #define EFHW_IS_BIG_ENDIAN
+ #else
+ #error Unknown endianness
--- linux-ec2-2.6.32.orig/debian.ec2/sub-flavours/control.stub
+++ linux-ec2-2.6.32/debian.ec2/sub-flavours/control.stub
@@ -0,0 +1,39 @@
+# Items that get replaced:
+# FLAVOUR
+# DESC
+# ARCH
+# SUPPORTED
+# TARGET
+# BOOTLOADER
+# =PROVIDES=
+# =CONFLICTS=
+#
+# Items marked with =FOO= are optional
+#
+# XXX: Leave the blank line before the first package!!
+
+Package: linux-image-PKGVER-ABINUM-FLAVOUR
+Architecture: ARCH
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, =PROVIDES=
+Depends: initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1), =CONFLICTS=
+Recommends: BOOTLOADER
+Suggests: fdutils, linux-doc-PKGVER | linux-source-PKGVER
+Description: Linux kernel image for version PKGVER on DESC
+ This package contains the Linux kernel image for version PKGVER on
+ DESC.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
--- linux-ec2-2.6.32.orig/debian.ec2/sub-flavours/README
+++ linux-ec2-2.6.32/debian.ec2/sub-flavours/README
@@ -0,0 +1,12 @@
+Sub flavours are flavours that are built based on other builds. IOW, they
+are usually a subset of something else.
+
+Requirements:
+
+debian/sub-flavours/<sub>.list	: The file list, uses glob syntax
+debian/sub-flavours/<sub>.vars	: The make vars, similar to normal flavours
+debian/rules.d/<arch>.mk	: Add <base>_sub var listing the <sub>, e.g.
+				  server_sub = virtual would mean virtual is
+				  based on the server flavour.
+
+Note, the vars must include a conflicts with the flavour it was built on.
--- linux-ec2-2.6.32.orig/debian.ec2/control.d/flavour-control.stub
+++ linux-ec2-2.6.32/debian.ec2/control.d/flavour-control.stub
@@ -0,0 +1,77 @@
+# Items that get replaced:
+# FLAVOUR
+# DESC
+# ARCH
+# SUPPORTED
+# TARGET
+# BOOTLOADER
+# =PROVIDES=
+#
+# Items marked with =FOO= are optional
+#
+# This file describes the template for packages that are created for each flavour
+# in debian/control.d/vars.*
+#
+# This file gets edited in a couple of places. See the debian/control.stub rule in
+# debian/rules. PGGVER, ABINUM, and SRCPKGNAME are all converted in the
+# process of creating debian/control.
+#
+# The flavour specific strings (ARCH, DESC, etc) are converted using values from the various
+# flavour files in debian/control.d/vars.*
+#
+# XXX: Leave the blank line before the first package!!
+
+Package: linux-image-PKGVER-ABINUM-FLAVOUR
+Architecture: ARCH
+Section: admin
+Priority: optional
+Pre-Depends: dpkg (>= 1.10.24)
+Provides: linux-image, linux-image-2.6, fuse-module, =PROVIDES=
+Depends: ${misc:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3)
+Conflicts: hotplug (<< 0.0.20040105-1)
+Recommends: BOOTLOADER
+Suggests: fdutils, SRCPKGNAME-doc-PKGVER | SRCPKGNAME-source-PKGVER
+Description: Linux kernel image for version PKGVER on DESC
+ This package contains the Linux kernel image for version PKGVER on
+ DESC.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-PKGVER-ABINUM-FLAVOUR
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-PKGVER-ABINUM, ${shlibs:Depends}
+#Provides: linux-headers, linux-headers-2.6
+Description: Linux kernel headers for version PKGVER on DESC
+ This package provides kernel header files for version PKGVER on
+ DESC.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details.
+
+Package: linux-image-PKGVER-ABINUM-FLAVOUR-dbgsym
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version PKGVER on DESC
+ This package provides a kernel debug image for version PKGVER on
+ DESC.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
--- linux-ec2-2.6.32.orig/debian.ec2/control.d/vars.ec2
+++ linux-ec2-2.6.32/debian.ec2/control.d/vars.ec2
@@ -0,0 +1,6 @@
+arch="i386 amd64"
+supported="Generic"
+target="Geared toward desktop systems."
+desc="x86/x86_64"
+bootloader=""
+provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9"
--- linux-ec2-2.6.32.orig/debian.ec2/etc/getabis
+++ linux-ec2-2.6.32/debian.ec2/etc/getabis
@@ -0,0 +1,9 @@
+repo_list=(
+	"http://archive.ubuntu.com/ubuntu/pool/main/l/linux-ec2"
+	"http://ports.ubuntu.com/ubuntu-ports/pool/main/l/linux-ec2"
+	"http://archive.ubuntu.com/ubuntu/pool/universe/l/linux-ec2"
+	"http://ports.ubuntu.com/ubuntu-ports/pool/universe/l/linux-ec2"
+)
+
+getall amd64 ec2
+getall i386 ec2
--- linux-ec2-2.6.32.orig/debian.ec2/etc/kernelconfig
+++ linux-ec2-2.6.32/debian.ec2/etc/kernelconfig
@@ -0,0 +1,2 @@
+archs="amd64 i386"
+family='ubuntu'
--- linux-ec2-2.6.32.orig/ubuntu/Makefile
+++ linux-ec2-2.6.32/ubuntu/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the Linux kernel ubuntu supplied third-party device drivers.
+#
+
+obj-$(CONFIG_AUFS_FS)		+= aufs/
+obj-$(CONFIG_BLK_DEV_COMPCACHE)	+= compcache/
+obj-$(CONFIG_DM_RAID45)		+= dm-raid4-5/
+obj-$(CONFIG_FSAM7400)		+= fsam7400/
+obj-$(CONFIG_SCSI_ISCSITARGET)	+= iscsitarget/
+obj-$(CONFIG_LIRC_DEV)          += lirc/
+obj-$(CONFIG_NDISWRAPPER)	+= ndiswrapper/
+obj-$(CONFIG_OMNIBOOK)		+= omnibook/
+obj-$(CONFIG_RTL8192SE)		+= rtl8192se/
+obj-m				+= rfkill/
+
+# This is a stupid trick to get kbuild to create ubuntu/built-in.o
+obj- += foo.o
--- linux-ec2-2.6.32.orig/ubuntu/Kconfig
+++ linux-ec2-2.6.32/ubuntu/Kconfig
@@ -0,0 +1,14 @@
+menu "Ubuntu Supplied Third-Party Device Drivers"
+
+source "ubuntu/aufs/Kconfig"
+source "ubuntu/compcache/Kconfig"
+source "ubuntu/dm-raid4-5/Kconfig"
+source "ubuntu/fsam7400/Kconfig"
+source "ubuntu/iscsitarget/Kconfig"
+source "ubuntu/lirc/Kconfig"
+source "ubuntu/ndiswrapper/Kconfig"
+source "ubuntu/omnibook/Kconfig"
+source "ubuntu/rtl8192se/Kconfig"
+source "ubuntu/rfkill/Kconfig"
+
+endmenu
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/config.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/config.c
@@ -0,0 +1,322 @@
+/*
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/proc_fs.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+
+struct proc_entries {
+	const char *name;
+	struct file_operations *fops;
+};
+
+static struct proc_entries iet_proc_entries[] =
+{
+	{"volume", &volume_seq_fops},
+	{"session", &session_seq_fops},
+};
+
+static struct proc_dir_entry *proc_iet_dir;
+
+void iet_procfs_exit(void)
+{
+	int i;
+
+	if (!proc_iet_dir)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++)
+		remove_proc_entry(iet_proc_entries[i].name, proc_iet_dir);
+
+	remove_proc_entry(proc_iet_dir->name, proc_iet_dir->parent);
+}
+
+int iet_procfs_init(void)
+{
+	int i;
+	struct proc_dir_entry *ent;
+
+	if (!(proc_iet_dir = proc_mkdir("iet", init_net.proc_net)))
+		goto err;
+
+	for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) {
+		ent = create_proc_entry(iet_proc_entries[i].name, 0, proc_iet_dir);
+		if (ent)
+			ent->proc_fops = iet_proc_entries[i].fops;
+		else
+			goto err;
+	}
+
+	return 0;
+
+err:
+	if (proc_iet_dir)
+		iet_procfs_exit();
+
+	return -ENOMEM;
+}
+
+static int get_conn_info(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct iscsi_session *session;
+	struct conn_info info;
+	struct iscsi_conn *conn;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	session = session_lookup(target, info.sid);
+	if (!session)
+		return -ENOENT;
+	conn = conn_lookup(session, info.cid);
+
+	info.cid = conn->cid;
+	info.stat_sn = conn->stat_sn;
+	info.exp_stat_sn = conn->exp_stat_sn;
+
+	if (copy_to_user((void *) ptr, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int add_conn(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct iscsi_session *session;
+	struct conn_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	if (!(session = session_lookup(target, info.sid)))
+		return -ENOENT;
+
+	return conn_add(session, &info);
+}
+
+static int del_conn(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct iscsi_session *session;
+	struct conn_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	if (!(session = session_lookup(target, info.sid)))
+		return -ENOENT;
+
+	return conn_del(session, &info);
+}
+
+static int get_session_info(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct iscsi_session *session;
+	struct session_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	session = session_lookup(target, info.sid);
+
+	if (!session)
+		return -ENOENT;
+
+	info.exp_cmd_sn = session->exp_cmd_sn;
+	info.max_cmd_sn = session->max_cmd_sn;
+
+	if (copy_to_user((void *) ptr, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int add_session(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct session_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	return session_add(target, &info);
+}
+
+static int del_session(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct session_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	return session_del(target, info.sid);
+}
+
+static int add_volume(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct volume_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	return volume_add(target, &info);
+}
+
+static int del_volume(struct iscsi_target *target, unsigned long ptr)
+{
+	int err;
+	struct volume_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	return iscsi_volume_del(target, &info);
+}
+
+static int iscsi_param_config(struct iscsi_target *target, unsigned long ptr, int set)
+{
+	int err;
+	struct iscsi_param_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		goto out;
+
+	if ((err = iscsi_param_set(target, &info, set)) < 0)
+		goto out;
+
+	if (!set)
+		err = copy_to_user((void *) ptr, &info, sizeof(info));
+
+out:
+	return err;
+}
+
+static int add_target(unsigned long ptr)
+{
+	int err;
+	struct target_info info;
+
+	if ((err = copy_from_user(&info, (void *) ptr, sizeof(info))) < 0)
+		return err;
+
+	if (!(err = target_add(&info)))
+		err = copy_to_user((void *) ptr, &info, sizeof(info));
+
+	return err;
+}
+
+static long ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct iscsi_target *target = NULL;
+	long err;
+	u32 id;
+
+	if ((err = get_user(id, (u32 *) arg)) != 0)
+		goto done;
+
+	if (cmd == DEL_TARGET) {
+		err = target_del(id);
+		goto done;
+	}
+
+	target = target_lookup_by_id(id);
+
+	if (cmd == ADD_TARGET)
+		if (target) {
+			err = -EEXIST;
+			eprintk("Target %u already exist!\n", id);
+			goto done;
+		}
+
+	switch (cmd) {
+	case ADD_TARGET:
+		assert(!target);
+		err = add_target(arg);
+		goto done;
+	}
+
+	if (!target) {
+		eprintk("can't find the target %u\n", id);
+		err = -EINVAL;
+		goto done;
+	}
+
+	if ((err = target_lock(target, 1)) < 0) {
+		eprintk("interrupted %ld %d\n", err, cmd);
+		goto done;
+	}
+
+	switch (cmd) {
+	case ADD_VOLUME:
+		err = add_volume(target, arg);
+		break;
+
+	case DEL_VOLUME:
+		err = del_volume(target, arg);
+		break;
+
+	case ADD_SESSION:
+		err = add_session(target, arg);
+		break;
+
+	case DEL_SESSION:
+		err = del_session(target, arg);
+		break;
+
+	case GET_SESSION_INFO:
+		err = get_session_info(target, arg);
+		break;
+
+	case ISCSI_PARAM_SET:
+		err = iscsi_param_config(target, arg, 1);
+		break;
+
+	case ISCSI_PARAM_GET:
+		err = iscsi_param_config(target, arg, 0);
+		break;
+
+	case ADD_CONN:
+		err = add_conn(target, arg);
+		break;
+
+	case DEL_CONN:
+		err = del_conn(target, arg);
+		break;
+
+	case GET_CONN_INFO:
+		err = get_conn_info(target, arg);
+		break;
+	default:
+		eprintk("invalid ioctl cmd %x\n", cmd);
+		err = -EINVAL;
+	}
+
+	if (target)
+		target_unlock(target);
+
+done:
+	return err;
+}
+
+static int release(struct inode *i __attribute__((unused)),
+		   struct file *f __attribute__((unused)))
+{
+	target_del_all();
+	return 0;
+}
+
+struct file_operations ctr_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= ioctl,
+	.compat_ioctl	= ioctl,
+	.release	= release
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/digest.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/digest.h
@@ -0,0 +1,20 @@
+/*
+ * iSCSI digest handling.
+ * (C) 2004 Xiranet Communications GmbH <arne.redlich@xiranet.com>
+ * This code is licensed under the GPL.
+ */
+
+#ifndef __IET_DIGEST_H__
+#define __IET_DIGEST_H__
+
+extern void digest_alg_available(unsigned int *val);
+extern int digest_init(struct iscsi_conn *conn);
+extern void digest_cleanup(struct iscsi_conn *conn);
+
+extern int digest_rx_header(struct iscsi_cmnd *cmnd);
+extern int digest_rx_data(struct iscsi_cmnd *cmnd);
+
+extern void digest_tx_header(struct iscsi_cmnd *cmnd);
+extern void digest_tx_data(struct iscsi_cmnd *cmnd);
+
+#endif /* __IET_DIGEST_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iscsi_dbg.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iscsi_dbg.h
@@ -0,0 +1,137 @@
+#ifndef ISCSI_DBG_H
+#define ISCSI_DBG_H
+
+#define D_SETUP		(1UL << 0)
+#define D_EXIT		(1UL << 1)
+#define D_GENERIC	(1UL << 2)
+#define D_READ		(1UL << 3)
+#define D_WRITE 	(1UL << 4)
+#define D_IOD		(1UL << 5)
+#define D_THREAD	(1UL << 6)
+#define D_TASK_MGT	(1UL << 7)
+#define D_IOMODE	(1UL << 8)
+#define D_UAC           (1UL << 9)
+
+#define D_DATA		(D_READ | D_WRITE)
+
+extern unsigned long debug_enable_flags;
+
+#define PFX "iscsi_trgt: "
+
+#define dprintk(debug, fmt, args...) do {			\
+	if ((debug) & debug_enable_flags) {			\
+		printk(KERN_DEBUG PFX "%s(%d) " fmt, __FUNCTION__,\
+						__LINE__, args);\
+	}							\
+} while (0)
+
+#define dprintk_ua(ua, sess, lun)					\
+	dprintk(D_UAC, "sess %llu, lun %u: %p %x %x\n",			\
+		(sess)->sid, lun, ua,					\
+		(ua) ? (ua)->asc : 0,					\
+		(ua) ? (ua)->ascq : 0)
+
+#define eprintk(fmt, args...) do {				\
+	printk(KERN_ERR PFX "%s(%d) " fmt, __FUNCTION__,	\
+						__LINE__, args);\
+} while (0)
+
+#define iprintk(X...) printk(KERN_INFO PFX X)
+
+#define assert(p) do {						\
+	if (!(p)) {						\
+		printk(KERN_CRIT PFX "BUG at %s:%d assert(%s)\n",\
+		       __FILE__, __LINE__, #p);			\
+		dump_stack();					\
+		BUG();						\
+	}							\
+} while (0)
+
+#ifdef D_IOV
+static inline void iscsi_dump_iov(struct msghdr *msg)
+{
+	int i;
+	printk(PFX "%p, %d\n", msg->msg_iov, msg->msg_iovlen);
+	for (i = 0; i < min_t(size_t, msg->msg_iovlen, ISCSI_CONN_IOV_MAX); i++)
+		printk(PFX "%d: %p,%d\n", i, msg->msg_iov[i].iov_base,
+						msg->msg_iov[i].iov_len);
+}
+#else
+#define iscsi_dump_iov(x) do {} while (0)
+#endif
+
+#ifdef D_DUMP_PDU
+static void iscsi_dump_char(int ch)
+{
+	static unsigned char text[16];
+	static int i = 0;
+
+	if (ch < 0) {
+		while ((i % 16) != 0) {
+			printk("   ");
+			text[i] = ' ';
+			i++;
+			if ((i % 16) == 0)
+				printk(" | %.16s |\n", text);
+			else if ((i % 4) == 0)
+				printk(" |");
+		}
+		i = 0;
+		return;
+	}
+
+	text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch;
+	printk(" %02x", ch);
+	i++;
+	if ((i % 16) == 0) {
+		printk(" | %.16s |\n", text);
+		i = 0;
+	} else if ((i % 4) == 0)
+		printk(" |");
+}
+
+static inline void iscsi_dump_pdu(struct iscsi_pdu *pdu)
+{
+	unsigned char *buf;
+	int i;
+
+	buf = (void *)&pdu->bhs;
+	printk(PFX "BHS: (%p,%d)\n", buf, sizeof(pdu->bhs));
+	for (i = 0; i < sizeof(pdu->bhs); i++)
+		iscsi_dump_char(*buf++);
+	iscsi_dump_char(-1);
+
+	buf = (void *)pdu->ahs;
+	printk(PFX "AHS: (%p,%d)\n", buf, pdu->ahssize);
+	for (i = 0; i < pdu->ahssize; i++)
+		iscsi_dump_char(*buf++);
+	iscsi_dump_char(-1);
+
+	printk(PFX "Data: (%d)\n", pdu->datasize);
+}
+
+#else
+#define iscsi_dump_pdu(x) do {} while (0)
+#endif
+
+#define show_param(param)\
+{\
+	dprintk(D_SETUP, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",\
+		(param)->initial_r2t,\
+		(param)->immediate_data,\
+		(param)->max_connections,\
+		(param)->max_recv_data_length,\
+		(param)->max_xmit_data_length,\
+		(param)->max_burst_length,\
+		(param)->first_burst_length,\
+		(param)->default_wait_time,\
+		(param)->default_retain_time,\
+		(param)->max_outstanding_r2t,\
+		(param)->data_pdu_inorder,\
+		(param)->data_sequence_inorder,\
+		(param)->error_recovery_level,\
+		(param)->header_digest,\
+		(param)->data_digest);\
+}
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iotype.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iotype.h
@@ -0,0 +1,29 @@
+/*
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include "iscsi.h"
+
+#ifndef __IOTYPE_H__
+#define __IOTYPE_H__
+
+struct iotype {
+	const char *name;
+	struct list_head iot_list;
+
+	int (*attach)(struct iet_volume *dev, char *args);
+	int (*make_request)(struct iet_volume *dev, struct tio *tio, int rw);
+	int (*sync)(struct iet_volume *dev, struct tio *tio);
+	void (*detach)(struct iet_volume *dev);
+	void (*show)(struct iet_volume *dev, struct seq_file *seq);
+};
+
+extern struct iotype fileio;
+extern struct iotype nullio;
+extern struct iotype blockio;
+
+extern int iotype_init(void);
+extern void iotype_exit(void);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/digest.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/digest.c
@@ -0,0 +1,279 @@
+/*
+ * iSCSI digest handling.
+ * (C) 2004 - 2006 Xiranet Communications GmbH <arne.redlich@xiranet.com>
+ * This code is licensed under the GPL.
+ */
+
+#include <linux/types.h>
+
+#include "iscsi.h"
+#include "digest.h"
+#include "iscsi_dbg.h"
+
+void digest_alg_available(unsigned int *val)
+{
+	if (*val & DIGEST_CRC32C &&
+	    !crypto_has_alg("crc32c", 0, CRYPTO_ALG_ASYNC)) {
+		printk("CRC32C digest algorithm not available in kernel\n");
+		*val |= ~DIGEST_CRC32C;
+	}
+}
+
+/**
+ * initialize support for digest calculation.
+ *
+ * digest_init -
+ * @conn: ptr to connection to make use of digests
+ *
+ * @return: 0 on success, < 0 on error
+ */
+int digest_init(struct iscsi_conn *conn)
+{
+	int err = 0;
+
+	if (!(conn->hdigest_type & DIGEST_ALL))
+		conn->hdigest_type = DIGEST_NONE;
+
+	if (!(conn->ddigest_type & DIGEST_ALL))
+		conn->ddigest_type = DIGEST_NONE;
+
+	if (conn->hdigest_type & DIGEST_CRC32C ||
+	    conn->ddigest_type & DIGEST_CRC32C) {
+		conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+						      CRYPTO_ALG_ASYNC);
+		conn->rx_hash.flags = 0;
+		if (IS_ERR(conn->rx_hash.tfm)) {
+			conn->rx_hash.tfm = NULL;
+			err = -ENOMEM;
+			goto out;
+		}
+
+		conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+						      CRYPTO_ALG_ASYNC);
+		conn->tx_hash.flags = 0;
+		if (IS_ERR(conn->tx_hash.tfm)) {
+			conn->tx_hash.tfm = NULL;
+			err = -ENOMEM;
+			goto out;
+		}
+	}
+
+out:
+	if (err)
+		digest_cleanup(conn);
+
+	return err;
+}
+
+/**
+ * free resources used for digest calculation.
+ *
+ * digest_cleanup -
+ * @conn: ptr to connection that made use of digests
+ */
+void digest_cleanup(struct iscsi_conn *conn)
+{
+	if (conn->tx_hash.tfm)
+		crypto_free_hash(conn->tx_hash.tfm);
+	if (conn->rx_hash.tfm)
+		crypto_free_hash(conn->rx_hash.tfm);
+}
+
+/**
+ * debug handling of header digest errors:
+ * simulates a digest error after n PDUs / every n-th PDU of type
+ * HDIGEST_ERR_CORRUPT_PDU_TYPE.
+ */
+static inline void __dbg_simulate_header_digest_error(struct iscsi_cmnd *cmnd)
+{
+#define HDIGEST_ERR_AFTER_N_CMNDS 1000
+#define HDIGEST_ERR_ONLY_ONCE     1
+#define HDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_CMD
+#define HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY 0
+
+	static int num_cmnds = 0;
+	static int num_errs = 0;
+
+	if (cmnd_opcode(cmnd) == HDIGEST_ERR_CORRUPT_PDU_TYPE) {
+		if (HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY) {
+			if (cmnd->pdu.datasize)
+				num_cmnds++;
+		} else
+			num_cmnds++;
+	}
+
+	if ((num_cmnds == HDIGEST_ERR_AFTER_N_CMNDS)
+	    && (!(HDIGEST_ERR_ONLY_ONCE && num_errs))) {
+		printk("*** Faking header digest error ***\n");
+		printk("\tcmnd: 0x%x, itt 0x%x, sn 0x%x\n",
+		       cmnd_opcode(cmnd),
+		       be32_to_cpu(cmnd->pdu.bhs.itt),
+		       be32_to_cpu(cmnd->pdu.bhs.sn));
+		cmnd->hdigest = ~cmnd->hdigest;
+		/* make things even worse by manipulating header fields */
+		cmnd->pdu.datasize += 8;
+		num_errs++;
+		num_cmnds = 0;
+	}
+	return;
+}
+
+/**
+ * debug handling of data digest errors:
+ * simulates a digest error after n PDUs / every n-th PDU of type
+ * DDIGEST_ERR_CORRUPT_PDU_TYPE.
+ */
+static inline void __dbg_simulate_data_digest_error(struct iscsi_cmnd *cmnd)
+{
+#define DDIGEST_ERR_AFTER_N_CMNDS 50
+#define DDIGEST_ERR_ONLY_ONCE     1
+#define DDIGEST_ERR_CORRUPT_PDU_TYPE   ISCSI_OP_SCSI_DATA_OUT
+#define DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY 0
+
+	static int num_cmnds = 0;
+	static int num_errs = 0;
+
+	if ((cmnd->pdu.datasize)
+	    && (cmnd_opcode(cmnd) == DDIGEST_ERR_CORRUPT_PDU_TYPE)) {
+		switch (cmnd_opcode(cmnd)) {
+		case ISCSI_OP_SCSI_DATA_OUT:
+			if ((DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY)
+			    && (cmnd->pdu.bhs.ttt != ISCSI_RESERVED_TAG))
+				break;
+		default:
+			num_cmnds++;
+		}
+	}
+
+	if ((num_cmnds == DDIGEST_ERR_AFTER_N_CMNDS)
+	    && (!(DDIGEST_ERR_ONLY_ONCE && num_errs))
+	    && (cmnd->pdu.datasize)
+	    && (!cmnd->conn->read_overflow)) {
+		printk("*** Faking data digest error: ***");
+		printk("\tcmnd 0x%x, itt 0x%x, sn 0x%x\n",
+		       cmnd_opcode(cmnd),
+		       be32_to_cpu(cmnd->pdu.bhs.itt),
+		       be32_to_cpu(cmnd->pdu.bhs.sn));
+		cmnd->ddigest = ~cmnd->ddigest;
+		num_errs++;
+		num_cmnds = 0;
+	}
+}
+
+static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu,
+			  u8 *crc)
+{
+	struct scatterlist sg[2];
+	unsigned int nbytes = sizeof(struct iscsi_hdr);
+
+	sg_init_table(sg, pdu->ahssize ? 2 : 1);
+
+	sg_set_buf(&sg[0], &pdu->bhs, nbytes);
+	if (pdu->ahssize) {
+		sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize);
+		nbytes += pdu->ahssize;
+	}
+
+	crypto_hash_init(hash);
+	crypto_hash_update(hash, sg, nbytes);
+	crypto_hash_final(hash, crc);
+}
+
+int digest_rx_header(struct iscsi_cmnd *cmnd)
+{
+	u32 crc;
+
+	digest_header(&cmnd->conn->rx_hash, &cmnd->pdu, (u8 *) &crc);
+	if (crc != cmnd->hdigest)
+		return -EIO;
+
+	return 0;
+}
+
+void digest_tx_header(struct iscsi_cmnd *cmnd)
+{
+	digest_header(&cmnd->conn->tx_hash, &cmnd->pdu, (u8 *) &cmnd->hdigest);
+}
+
+static void digest_data(struct hash_desc *hash, struct iscsi_cmnd *cmnd,
+			struct tio *tio, u32 offset, u8 *crc)
+{
+	struct scatterlist *sg = cmnd->conn->hash_sg;
+	u32 size, length;
+	int i, idx, count;
+	unsigned int nbytes;
+
+	size = cmnd->pdu.datasize;
+	nbytes = size = (size + 3) & ~3;
+
+	offset += tio->offset;
+	idx = offset >> PAGE_CACHE_SHIFT;
+	offset &= ~PAGE_CACHE_MASK;
+	count = get_pgcnt(size, offset);
+	assert(idx + count <= tio->pg_cnt);
+
+	assert(count <= ISCSI_CONN_IOV_MAX);
+
+	sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg));
+	crypto_hash_init(hash);
+
+	for (i = 0; size; i++) {
+		if (offset + size > PAGE_CACHE_SIZE)
+			length = PAGE_CACHE_SIZE - offset;
+		else
+			length = size;
+
+		sg_set_page(&sg[i], tio->pvec[idx + i], length, offset);
+		size -= length;
+		offset = 0;
+	}
+
+	sg_mark_end(&sg[i - 1]);
+
+	crypto_hash_update(hash, sg, nbytes);
+	crypto_hash_final(hash, crc);
+}
+
+int digest_rx_data(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio;
+	struct iscsi_cmnd *scsi_cmnd;
+	struct iscsi_data_out_hdr *req;
+	u32 offset, crc;
+
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_SCSI_REJECT:
+	case ISCSI_OP_PDU_REJECT:
+	case ISCSI_OP_DATA_REJECT:
+		return 0;
+	case ISCSI_OP_SCSI_DATA_OUT:
+		scsi_cmnd = cmnd->req;
+		req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs;
+		tio = scsi_cmnd->tio;
+		offset = be32_to_cpu(req->buffer_offset);
+		break;
+	default:
+		tio = cmnd->tio;
+		offset = 0;
+	}
+
+	digest_data(&cmnd->conn->rx_hash, cmnd, tio, offset, (u8 *) &crc);
+
+	if (!cmnd->conn->read_overflow &&
+	    (cmnd_opcode(cmnd) != ISCSI_OP_PDU_REJECT)) {
+		if (crc != cmnd->ddigest)
+			return -EIO;
+	}
+
+	return 0;
+}
+
+void digest_tx_data(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio = cmnd->tio;
+	struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
+
+	assert(tio);
+	digest_data(&cmnd->conn->tx_hash, cmnd, tio,
+		    be32_to_cpu(req->buffer_offset), (u8 *) &cmnd->ddigest);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/Makefile
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the Linux kernel device drivers.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile.
+
+EXTRA_CFLAGS += -I$(src)/include 
+
+obj-m		+= iscsi_trgt.o
+iscsi_trgt-objs	:= tio.o iscsi.o nthread.o wthread.o config.o digest.o \
+			conn.o session.o target.o volume.o iotype.o \
+			file-io.o null-io.o target_disk.o event.o param.o \
+			block-io.o ua.o
+
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/target_disk.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/target_disk.c
@@ -0,0 +1,572 @@
+/*
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ *
+ * heavily based on code from kernel/iscsi.c:
+ *   Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>,
+ *   licensed under the terms of the GNU GPL v2.0,
+ */
+
+#include <linux/ctype.h>
+#include <scsi/scsi.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+
+static int insert_disconnect_pg(u8 *ptr)
+{
+	unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, disconnect_pg, sizeof(disconnect_pg));
+	return sizeof(disconnect_pg);
+}
+
+static int insert_caching_pg(u8 *ptr, int wcache, int rcache)
+{
+	unsigned char caching_pg[] = {0x08, 0x12, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00,
+				      0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,
+				      0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, caching_pg, sizeof(caching_pg));
+	if (wcache)
+		ptr[2] |= 0x04;	/* set WCE bit if we're caching writes */
+	if (!rcache)
+		ptr[2] |= 0x01; /* Read Cache Disable */
+
+	return sizeof(caching_pg);
+}
+
+static int insert_ctrl_m_pg(u8 *ptr)
+{
+	unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+				     0x00, 0x00, 0x02, 0x4b};
+
+	memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg));
+	return sizeof(ctrl_m_pg);
+}
+
+static int insert_iec_m_pg(u8 *ptr)
+{
+	unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, iec_m_pg, sizeof(iec_m_pg));
+	return sizeof(iec_m_pg);
+}
+
+static int insert_format_m_pg(u8 *ptr, u32 sector_size)
+{
+	unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, format_m_pg, sizeof(format_m_pg));
+	ptr[12] = (sector_size >> 8) & 0xff;
+	ptr[13] = sector_size & 0xff;
+	return sizeof(format_m_pg);
+}
+
+static int insert_geo_m_pg(u8 *ptr, u64 sec)
+{
+	unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};
+	u32 ncyl;
+	u32 n;
+
+	/* assume 0xff heads, 15krpm. */
+	memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));
+	ncyl = sec >> 14; /* 256 * 64 */
+	memcpy(&n, ptr+1, sizeof(u32));
+	n = n | cpu_to_be32(ncyl);
+	memcpy(ptr+1, &n, sizeof(u32));
+	return sizeof(geo_m_pg);
+}
+
+static void build_mode_sense_response(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+	struct tio *tio = cmnd->tio;
+	u8 *data, *scb = req->scb;
+	int len = 4, err = 0;
+	u8 pcode;
+
+	/* changeable parameter mode pages are unsupported */
+	if ((scb[2] & 0xc0) >> 6 == 0x1)
+		goto set_sense;
+
+	pcode = req->scb[2] & 0x3f;
+
+	assert(!tio);
+	tio = cmnd->tio = tio_alloc(1);
+	data = page_address(tio->pvec[0]);
+	assert(data);
+	clear_page(data);
+
+	if (LUReadonly(cmnd->lun))
+		data[2] = 0x80;
+
+	if ((scb[1] & 0x8))
+		data[3] = 0;
+	else {
+		data[3] = 8;
+		len += 8;
+		*(u32 *)(data + 4) = (cmnd->lun->blk_cnt >> 32) ?
+			cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt);
+		*(u32 *)(data + 8) = cpu_to_be32(1 << cmnd->lun->blk_shift);
+	}
+
+	switch (pcode) {
+	case 0x0:
+		break;
+	case 0x2:
+		len += insert_disconnect_pg(data + len);
+		break;
+	case 0x3:
+		len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift);
+		break;
+	case 0x4:
+		len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);
+		break;
+	case 0x8:
+		len += insert_caching_pg(data + len, LUWCache(cmnd->lun),
+					 LURCache(cmnd->lun));
+		break;
+	case 0xa:
+		len += insert_ctrl_m_pg(data + len);
+		break;
+	case 0x1c:
+		len += insert_iec_m_pg(data + len);
+		break;
+	case 0x3f:
+		len += insert_disconnect_pg(data + len);
+		len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift);
+		len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);
+		len += insert_caching_pg(data + len, LUWCache(cmnd->lun),
+					 LURCache(cmnd->lun));
+		len += insert_ctrl_m_pg(data + len);
+		len += insert_iec_m_pg(data + len);
+		break;
+	default:
+		err = -1;
+	}
+
+	if (!err) {
+		data[0] = len - 1;
+		tio_set(tio, len, 0);
+		return;
+	}
+
+	tio_put(tio);
+	cmnd->tio = NULL;
+ set_sense:
+	/* Invalid Field In CDB */
+	iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0);
+}
+
+static void build_inquiry_response(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+	struct tio *tio = cmnd->tio;
+	u8 *data;
+	u8 *scb = req->scb;
+	int err = -1;
+
+	/*
+	 * - CmdDt and EVPD both set or EVPD and Page Code set: illegal
+	 * - CmdDt set: not supported
+	 */
+	if ((scb[1] & 0x3) > 0x1 || (!(scb[1] & 0x3) && scb[2]))
+		goto set_sense;
+
+	assert(!tio);
+	tio = cmnd->tio = tio_alloc(1);
+	data = page_address(tio->pvec[0]);
+	assert(data);
+	clear_page(data);
+
+	if (!(scb[1] & 0x3)) {
+		data[2] = 4;
+		data[3] = 0x52;
+		data[4] = 59;
+		data[7] = 0x02;
+		memset(data + 8, 0x20, 28);
+		memcpy(data + 8,
+		       VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8));
+		memcpy(data + 16,
+		       PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16));
+		memcpy(data + 32,
+		       PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4));
+		data[58] = 0x03;
+		data[59] = 0x20;
+		data[60] = 0x09;
+		data[61] = 0x60;
+		data[62] = 0x03;
+		data[63] = 0x00;
+		tio_set(tio, 64, 0);
+		err = 0;
+	} else if (scb[1] & 0x1) {
+		/* EVPD bit set */
+		if (scb[2] == 0x0) {
+			data[1] = 0x0;
+			data[3] = 3;
+			data[4] = 0x0;
+			data[5] = 0x80;
+			data[6] = 0x83;
+			tio_set(tio, 7, 0);
+			err = 0;
+		} else if (scb[2] == 0x80) {
+			int len = (cmnd->lun && strlen(cmnd->lun->scsi_sn)) ?
+				SCSI_SN_LEN : 4;
+
+			data[1] = 0x80;
+			data[3] = len;
+			memset(data + 4, 0x20, len);
+			tio_set(tio, len + 4, 0);
+			err = 0;
+
+			if (len == SCSI_SN_LEN) {
+				char *p, *q;
+
+				p = data + 4 + len - 1;
+				q = cmnd->lun->scsi_sn + len - 1;
+
+				for (; len > 0; len--, q--)
+					if (isascii(*q) && isprint(*q))
+						*(p--) = *q;
+			}
+		} else if (scb[2] == 0x83) {
+			u32 len = SCSI_ID_LEN * sizeof(u8);
+
+			data[1] = 0x83;
+			data[3] = len + 4;
+			data[4] = 0x1;
+			data[5] = 0x1;
+			data[7] = len;
+			if (cmnd->lun) /* We need this ? */
+				memcpy(data + 8, cmnd->lun->scsi_id, len);
+			tio_set(tio, len + 8, 0);
+			err = 0;
+		}
+	}
+
+	if (!err) {
+		tio_set(tio, min_t(u8, tio->size, scb[4]), 0);
+		if (!cmnd->lun)
+			data[0] = TYPE_NO_LUN;
+		return;
+	}
+
+	tio_put(tio);
+	cmnd->tio = NULL;
+ set_sense:
+	/* Invalid Field In CDB */
+	iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0);
+}
+
+static void build_report_luns_response(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+	struct tio *tio = cmnd->tio;
+	u32 *data, size, len;
+	struct iet_volume *lun;
+	int rest, idx = 0;
+
+	size = (u32)req->scb[6] << 24 | (u32)req->scb[7] << 16 |
+		(u32)req->scb[8] << 8 | (u32)req->scb[9];
+	if (size < 16) {
+		/* Invalid Field In CDB */
+		iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0);
+		return;
+	}
+
+	len = atomic_read(&cmnd->conn->session->target->nr_volumes) * 8;
+	size = min(size & ~(8 - 1), len + 8);
+
+	assert(!tio);
+	tio = cmnd->tio = tio_alloc(get_pgcnt(size, 0));
+	tio_set(tio, size, 0);
+
+	data = page_address(tio->pvec[idx]);
+	assert(data);
+	*data++ = cpu_to_be32(len);
+	*data++ = 0;
+	size -= 8;
+	rest = PAGE_CACHE_SIZE - 8;
+	list_for_each_entry(lun, &cmnd->conn->session->target->volumes, list) {
+		if (lun->l_state != IDEV_RUNNING)
+			continue;
+
+		*data++ = cpu_to_be32((0x3ff & lun->lun) << 16 |
+				      ((lun->lun > 0xff) ? (0x1 << 30) : 0));
+		*data++ = 0;
+		if ((size -= 8) == 0)
+			break;
+		if ((rest -= 8) == 0) {
+			idx++;
+			data = page_address(tio->pvec[idx]);
+			rest = PAGE_CACHE_SIZE;
+		}
+	}
+}
+
+static void build_read_capacity_response(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio = cmnd->tio;
+	u32 *data;
+
+	assert(!tio);
+	tio = cmnd->tio = tio_alloc(1);
+	data = page_address(tio->pvec[0]);
+	assert(data);
+	clear_page(data);
+
+	data[0] = (cmnd->lun->blk_cnt >> 32) ?
+		cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt - 1);
+	data[1] = cpu_to_be32(1U << cmnd->lun->blk_shift);
+
+	tio_set(tio, 8, 0);
+}
+
+static void build_request_sense_response(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio = cmnd->tio;
+	u8 *data;
+
+	assert(!tio);
+	tio = cmnd->tio = tio_alloc(1);
+	data = page_address(tio->pvec[0]);
+	assert(data);
+	memset(data, 0, 18);
+	data[0] = 0xf0;
+	data[1] = 0;
+	data[2] = NO_SENSE;
+	data[7] = 10;
+	tio_set(tio, 18, 0);
+}
+
+static void build_service_action_in_response(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio = cmnd->tio;
+	u32 *data;
+	u64 *data64;
+
+	assert(!tio);
+
+	/* only READ_CAPACITY_16 service action is currently supported */
+	if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) != 0x10) {
+		/* Invalid Field In CDB */
+		iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0);
+		return;
+	}
+
+	tio = cmnd->tio = tio_alloc(1);
+	data = page_address(tio->pvec[0]);
+	assert(data);
+	clear_page(data);
+	data64 = (u64*) data;
+	data64[0] = cpu_to_be64(cmnd->lun->blk_cnt - 1);
+	data[2] = cpu_to_be32(1UL << cmnd->lun->blk_shift);
+
+	tio_set(tio, 12, 0);
+}
+
+static void build_read_response(struct iscsi_cmnd *cmnd)
+{
+	struct tio *tio = cmnd->tio;
+
+	assert(tio);
+	assert(cmnd->lun);
+
+	if (tio_read(cmnd->lun, tio))
+		/* Medium Error/Unrecovered Read Error */
+		iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x11, 0x0);
+}
+
+static void build_write_response(struct iscsi_cmnd *cmnd)
+{
+	int err;
+	struct tio *tio = cmnd->tio;
+
+	assert(tio);
+	assert(cmnd->lun);
+
+	list_del_init(&cmnd->list);
+	err = tio_write(cmnd->lun, tio);
+	if (!err && !LUWCache(cmnd->lun))
+		err = tio_sync(cmnd->lun, tio);
+
+	if (err)
+		/* Medium Error/Write Fault */
+		iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0);
+}
+
+static void build_sync_cache_response(struct iscsi_cmnd *cmnd)
+{
+	assert(cmnd->lun);
+	if (tio_sync(cmnd->lun, NULL))
+		/* Medium Error/Write Fault */
+		iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0);
+}
+
+static void build_generic_response(struct iscsi_cmnd *cmnd)
+{
+	return;
+}
+
+static void build_reserve_response(struct iscsi_cmnd *cmnd)
+{
+	switch (volume_reserve(cmnd->lun, cmnd->conn->session->sid)) {
+	case -ENOENT:
+		/* Logical Unit Not Supported (?) */
+		iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x25, 0x0);
+		break;
+	case -EBUSY:
+		cmnd->status = SAM_STAT_RESERVATION_CONFLICT;
+		break;
+	default:
+		break;
+	}
+}
+
+static void build_release_response(struct iscsi_cmnd *cmnd)
+{
+	if (volume_release(cmnd->lun,
+			   cmnd->conn->session->sid, 0))
+		cmnd->status = SAM_STAT_RESERVATION_CONFLICT;
+}
+
+static void build_reservation_conflict_response(struct iscsi_cmnd *cmnd)
+{
+	cmnd->status = SAM_STAT_RESERVATION_CONFLICT;
+}
+
+static int disk_check_ua(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+	struct ua_entry *ua;
+
+	if (cmnd->lun && ua_pending(cmnd->conn->session, cmnd->lun->lun)) {
+		switch(req->scb[0]){
+		case INQUIRY:
+		case REQUEST_SENSE:
+			break;
+		case REPORT_LUNS:
+			ua = ua_get_match(cmnd->conn->session,
+					  cmnd->lun->lun,
+					  /* reported luns data has changed */
+					  0x3f, 0x0e);
+			ua_free(ua);
+			break;
+		default:
+			ua = ua_get_first(cmnd->conn->session, cmnd->lun->lun);
+			iscsi_cmnd_set_sense(cmnd, UNIT_ATTENTION, ua->asc,
+					     ua->ascq);
+			ua_free(ua);
+			send_scsi_rsp(cmnd, build_generic_response);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int disk_check_reservation(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+
+	if (is_volume_reserved(cmnd->lun,
+			       cmnd->conn->session->sid)) {
+		switch (req->scb[0]) {
+		case INQUIRY:
+		case RELEASE:
+		case REPORT_LUNS:
+		case REQUEST_SENSE:
+		case READ_CAPACITY:
+			/* allowed commands when reserved */
+			break;
+		case SERVICE_ACTION_IN:
+			if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) == 0x10)
+				break;
+			/* fall through */
+		default:
+			/* return reservation conflict for all others */
+			send_scsi_rsp(cmnd,
+				      build_reservation_conflict_response);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int disk_execute_cmnd(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+
+	req->opcode &= ISCSI_OPCODE_MASK;
+
+	if (disk_check_ua(cmnd))
+		return 0;
+
+	if (disk_check_reservation(cmnd))
+		return 0;
+
+	switch (req->scb[0]) {
+	case INQUIRY:
+		send_data_rsp(cmnd, build_inquiry_response);
+		break;
+	case REPORT_LUNS:
+		send_data_rsp(cmnd, build_report_luns_response);
+		break;
+	case READ_CAPACITY:
+		send_data_rsp(cmnd, build_read_capacity_response);
+		break;
+	case MODE_SENSE:
+		send_data_rsp(cmnd, build_mode_sense_response);
+		break;
+	case REQUEST_SENSE:
+		send_data_rsp(cmnd, build_request_sense_response);
+		break;
+	case SERVICE_ACTION_IN:
+		send_data_rsp(cmnd, build_service_action_in_response);
+		break;
+	case READ_6:
+	case READ_10:
+	case READ_16:
+		send_data_rsp(cmnd, build_read_response);
+		break;
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+	case WRITE_VERIFY:
+		send_scsi_rsp(cmnd, build_write_response);
+		break;
+	case SYNCHRONIZE_CACHE:
+		send_scsi_rsp(cmnd, build_sync_cache_response);
+		break;
+	case RESERVE:
+		send_scsi_rsp(cmnd, build_reserve_response);
+		break;
+	case RELEASE:
+		send_scsi_rsp(cmnd, build_release_response);
+		break;
+	case START_STOP:
+	case TEST_UNIT_READY:
+	case VERIFY:
+	case VERIFY_16:
+		send_scsi_rsp(cmnd, build_generic_response);
+		break;
+	default:
+		eprintk("%s\n", "we should not come here!");
+		break;
+	}
+
+	return 0;
+}
+
+struct target_type disk_ops =
+{
+	.id = 0,
+	.execute_cmnd = disk_execute_cmnd,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/block-io.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/block-io.c
@@ -0,0 +1,391 @@
+/*
+ * Target device block I/O.
+ *
+ * Based on file I/O driver from FUJITA Tomonori
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * (C) 2006 Andre Brinkmann <brinkman at hni dot upb dot de>
+ * (C) 2007 Ross Walker <rswwalker at hotmail dot com>
+ * (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com>
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/parser.h>
+#include <linux/buffer_head.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+struct blockio_data {
+	char *path;
+	struct block_device *bdev;
+};
+
+struct tio_work {
+	atomic_t error;
+	atomic_t bios_remaining;
+	struct completion tio_complete;
+};
+
+static void blockio_bio_endio(struct bio *bio, int error)
+{
+	struct tio_work *tio_work = bio->bi_private;
+
+	error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
+
+	if (error)
+		atomic_set(&tio_work->error, error);
+
+	/* If last bio signal completion */
+	if (atomic_dec_and_test(&tio_work->bios_remaining))
+		complete(&tio_work->tio_complete);
+
+	bio_put(bio);
+}
+
+/*
+ * Blockio_make_request(): The function translates an iscsi-request into
+ * a number of requests to the corresponding block device.
+ */
+static int
+blockio_make_request(struct iet_volume *volume, struct tio *tio, int rw)
+{
+	struct blockio_data *bio_data = volume->private;
+	struct request_queue *bdev_q = bdev_get_queue(bio_data->bdev);
+	struct tio_work *tio_work;
+	struct bio *tio_bio = NULL, *bio = NULL, *biotail = NULL;
+
+	u32 offset = tio->offset;
+	u32 size = tio->size;
+	u32 tio_index = 0;
+
+	int max_pages = 1;
+	int err = 0;
+
+	loff_t ppos = ((loff_t) tio->idx << PAGE_SHIFT) + offset;
+
+	/* Calculate max_pages for bio_alloc (memory saver) */
+	if (bdev_q)
+		max_pages = bio_get_nr_vecs(bio_data->bdev);
+
+	tio_work = kzalloc(sizeof (*tio_work), GFP_KERNEL);
+	if (!tio_work)
+		return -ENOMEM;
+
+	atomic_set(&tio_work->error, 0);
+	atomic_set(&tio_work->bios_remaining, 0);
+	init_completion(&tio_work->tio_complete);
+
+	/* Main processing loop, allocate and fill all bios */
+	while (tio_index < tio->pg_cnt) {
+		bio = bio_alloc(GFP_KERNEL, min(max_pages, BIO_MAX_PAGES));
+		if (!bio) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		bio->bi_sector = ppos >> volume->blk_shift;
+		bio->bi_bdev = bio_data->bdev;
+		bio->bi_end_io = blockio_bio_endio;
+		bio->bi_private = tio_work;
+
+		if (tio_bio)
+			biotail = biotail->bi_next = bio;
+		else
+			tio_bio = biotail = bio;
+
+		atomic_inc(&tio_work->bios_remaining);
+
+		/* Loop for filling bio */
+		while (tio_index < tio->pg_cnt) {
+			unsigned int bytes = PAGE_SIZE - offset;
+
+			if (bytes > size)
+				bytes = size;
+
+			if (!bio_add_page(bio, tio->pvec[tio_index], bytes, offset))
+				break;
+
+			size -= bytes;
+			ppos += bytes;
+
+			offset = 0;
+
+			tio_index++;
+		}
+	}
+
+	/* Walk the list, submitting bios 1 by 1 */
+	while (tio_bio) {
+		bio = tio_bio;
+		tio_bio = tio_bio->bi_next;
+		bio->bi_next = NULL;
+
+		submit_bio(rw, bio);
+	}
+
+	if (bdev_q && bdev_q->unplug_fn)
+		bdev_q->unplug_fn(bdev_q);
+
+	wait_for_completion(&tio_work->tio_complete);
+
+	err = atomic_read(&tio_work->error);
+
+	kfree(tio_work);
+
+	return err;
+out:
+	while (tio_bio) {
+		bio = tio_bio;
+		tio_bio = tio_bio->bi_next;
+
+		bio_put(bio);
+	}
+
+	kfree(tio_work);
+
+	return err;
+}
+
+static int
+blockio_open_path(struct iet_volume *volume, const char *path)
+{
+	struct blockio_data *bio_data = volume->private;
+	struct block_device *bdev;
+	int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
+	int err = 0;
+
+	bio_data->path = kstrdup(path, GFP_KERNEL);
+	if (!bio_data->path)
+		return -ENOMEM;
+
+	bdev = open_bdev_exclusive(path, flags, THIS_MODULE);
+	if (IS_ERR(bdev)) {
+		err = PTR_ERR(bdev);
+		eprintk("Can't open device %s, error %d\n", path, err);
+		bio_data->bdev = NULL;
+	} else {
+		bio_data->bdev = bdev;
+		fsync_bdev(bio_data->bdev);
+	}
+
+	return err;
+}
+
+static int
+set_scsiid(struct iet_volume *volume, const char *id)
+{
+	size_t len;
+
+	if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) {
+		eprintk("SCSI ID too long, %zd provided, %u max\n", len,
+			SCSI_ID_LEN - VENDOR_ID_LEN);
+		return -EINVAL;
+	}
+
+	memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len);
+
+	return 0;
+}
+
+static void
+gen_scsiid(struct iet_volume *volume, struct inode *inode)
+{
+	int i;
+	u32 *p;
+
+	strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN);
+
+	for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++)
+		if (volume->scsi_id[i])
+			return;
+
+	/* If a scsi id doesn't exist generate a 16 byte one:
+	 * Bytes   1-4: target type
+	 * Bytes   5-8: target id
+	 * Bytes  9-12: inode number
+	 * Bytes 13-16: device type
+	 */
+	p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN);
+	*(p + 0) = volume->target->trgt_param.target_type;
+	*(p + 1) = volume->target->tid;
+	*(p + 2) = volume->lun;
+	*(p + 3) = (unsigned int) inode->i_sb->s_dev;
+}
+
+static int
+set_scsisn(struct iet_volume *volume, const char *sn)
+{
+	size_t len;
+
+	if ((len = strlen(sn)) > SCSI_SN_LEN) {
+		eprintk("SCSI SN too long, %zd provided, %u max\n", len,
+			SCSI_SN_LEN);
+		return -EINVAL;
+	}
+
+	memcpy(volume->scsi_sn, sn, len);
+
+	return 0;
+}
+
+/* Create an enumeration of our accepted actions */
+enum
+{
+	Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err,
+};
+
+/* Create a match table using our action enums and their matching options */
+static match_table_t tokens = {
+	{Opt_scsiid, "ScsiId=%s"},
+	{Opt_scsisn, "ScsiSN=%s"},
+	{Opt_path, "Path=%s"},
+	{Opt_ignore, "Type=%s"},
+	{Opt_ignore, "IOMode=%s"},
+	{Opt_err, NULL},
+};
+
+static int
+parse_blockio_params(struct iet_volume *volume, char *params)
+{
+	struct blockio_data *info = volume->private;
+	int err = 0;
+	char *p, *q;
+
+	/* Loop through parameters separated by commas, look up our
+	 * parameter in match table, return enumeration and arguments
+	 * select case based on the returned enum and run the action */
+	while ((p = strsep(&params, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+		if (!*p)
+			continue;
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_scsiid:
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = set_scsiid(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_scsisn:
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = set_scsisn(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_path:
+			if (info->path) {
+				iprintk("Target %s, LUN %u: "
+					"duplicate \"Path\" param\n",
+					volume->target->name, volume->lun);
+				err = -EINVAL;
+				goto out;
+			}
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = blockio_open_path(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_ignore:
+			break;
+		default:
+			iprintk("Target %s, LUN %u: unknown param %s\n",
+				volume->target->name, volume->lun, p);
+			return -EINVAL;
+		}
+	}
+
+	if (!info->path) {
+		iprintk("Target %s, LUN %u: missing \"Path\" param\n",
+			volume->target->name, volume->lun);
+		err = -EINVAL;
+	}
+  out:
+	return err;
+}
+
+static void
+blockio_detach(struct iet_volume *volume)
+{
+	struct blockio_data *bio_data = volume->private;
+	int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE);
+
+	if (bio_data->bdev)
+		close_bdev_exclusive(bio_data->bdev, flags);
+	kfree(bio_data->path);
+
+	kfree(volume->private);
+}
+
+static int
+blockio_attach(struct iet_volume *volume, char *args)
+{
+	struct blockio_data *bio_data;
+	int err = 0;
+
+	if (volume->private) {
+		eprintk("Lun %u already attached on Target %s \n",
+			volume->lun, volume->target->name);
+		return -EBUSY;
+	}
+
+	bio_data = kzalloc(sizeof (*bio_data), GFP_KERNEL);
+	if (!bio_data)
+		return -ENOMEM;
+
+	volume->private = bio_data;
+
+	if ((err = parse_blockio_params(volume, args)) < 0) {
+		eprintk("Error attaching Lun %u to Target %s \n",
+			volume->lun, volume->target->name);
+		goto out;
+	}
+
+	/* Assign a vendor id, generate scsi id if none exists */
+	gen_scsiid(volume, bio_data->bdev->bd_inode);
+
+	/* Offer neither write nor read caching */
+	ClearLURCache(volume);
+	ClearLUWCache(volume);
+
+	volume->blk_shift = SECTOR_SIZE_BITS;
+	volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift;
+
+  out:
+	if (err < 0)
+		blockio_detach(volume);
+
+	return err;
+}
+
+static void
+blockio_show(struct iet_volume *volume, struct seq_file *seq)
+{
+	struct blockio_data *bio_data = volume->private;
+
+	/* Used to display blockio volume info in /proc/net/iet/volumes */
+	seq_printf(seq, " path:%s\n", bio_data->path);
+}
+
+struct iotype blockio = {
+	.name = "blockio",
+	.attach = blockio_attach,
+	.make_request = blockio_make_request,
+	.detach = blockio_detach,
+	.show = blockio_show,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iscsi.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iscsi.c
@@ -0,0 +1,1924 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ * Copyright (C) 2008 Arne Redlich <agr@powerkom-dd.de>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/module.h>
+#include <linux/hash.h>
+#include <net/tcp.h>
+#include <scsi/scsi.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+unsigned long debug_enable_flags;
+unsigned long worker_thread_pool_size;
+
+static struct kmem_cache *iscsi_cmnd_cache;
+static u8 dummy_data[PAGE_SIZE];
+
+static int ctr_major;
+static char ctr_name[] = "ietctl";
+extern struct file_operations ctr_fops;
+
+static u32 cmnd_write_size(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
+
+	if (hdr->flags & ISCSI_CMD_WRITE)
+		return be32_to_cpu(hdr->data_length);
+	return 0;
+}
+
+static u32 cmnd_read_size(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd);
+
+	if (hdr->flags & ISCSI_CMD_READ) {
+		struct iscsi_rlength_ahdr *ahdr =
+			(struct iscsi_rlength_ahdr *)cmnd->pdu.ahs;
+
+		if (!(hdr->flags & ISCSI_CMD_WRITE))
+			return be32_to_cpu(hdr->data_length);
+		if (ahdr && ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH)
+			return be32_to_cpu(ahdr->read_length);
+	}
+	return 0;
+}
+
+static void iscsi_device_queue_cmnd(struct iscsi_cmnd *cmnd)
+{
+	set_cmnd_waitio(cmnd);
+	wthread_queue(cmnd);
+}
+
+static void iscsi_scsi_queuecmnd(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_queue *queue = &cmnd->lun->queue;
+
+	dprintk(D_GENERIC, "%p\n", cmnd);
+
+	if ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_UNTAGGED &&
+	    (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_SIMPLE) {
+		cmnd->pdu.bhs.flags &= ~ISCSI_CMD_ATTR_MASK;
+		cmnd->pdu.bhs.flags |= ISCSI_CMD_UNTAGGED;
+	}
+
+	spin_lock(&queue->queue_lock);
+
+	set_cmnd_queued(cmnd);
+
+	switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) {
+	case ISCSI_CMD_UNTAGGED:
+	case ISCSI_CMD_SIMPLE:
+		if (!list_empty(&queue->wait_list) || queue->ordered_cmnd)
+			goto pending;
+		queue->active_cnt++;
+		break;
+
+	default:
+		BUG();
+	}
+	spin_unlock(&queue->queue_lock);
+
+	iscsi_device_queue_cmnd(cmnd);
+	return;
+ pending:
+	assert(list_empty(&cmnd->list));
+
+	list_add_tail(&cmnd->list, &queue->wait_list);
+	spin_unlock(&queue->queue_lock);
+	return;
+}
+
+static void iscsi_scsi_dequeuecmnd(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_queue *queue;
+
+	if (!cmnd->lun)
+		return;
+	queue = &cmnd->lun->queue;
+	spin_lock(&queue->queue_lock);
+	switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) {
+	case ISCSI_CMD_UNTAGGED:
+	case ISCSI_CMD_SIMPLE:
+		--queue->active_cnt;
+		break;
+	case ISCSI_CMD_ORDERED:
+	case ISCSI_CMD_HEAD_OF_QUEUE:
+	case ISCSI_CMD_ACA:
+		BUG();
+	default:
+		/* Should the iscsi_scsi_queuecmnd func reject this ? */
+		break;
+	}
+
+	while (!list_empty(&queue->wait_list)) {
+		cmnd = list_entry(queue->wait_list.next, struct iscsi_cmnd, list);
+		switch ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK)) {
+		case ISCSI_CMD_UNTAGGED:
+		case ISCSI_CMD_SIMPLE:
+			list_del_init(&cmnd->list);
+			queue->active_cnt++;
+			iscsi_device_queue_cmnd(cmnd);
+			break;
+		case ISCSI_CMD_ORDERED:
+		case ISCSI_CMD_HEAD_OF_QUEUE:
+		case ISCSI_CMD_ACA:
+			BUG();
+		}
+	}
+
+	spin_unlock(&queue->queue_lock);
+
+	return;
+}
+
+/**
+ * create a new command.
+ *
+ * iscsi_cmnd_create -
+ * @conn: ptr to connection (for i/o)
+ *
+ * @return    ptr to command or NULL
+ */
+
+struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn, int req)
+{
+	struct iscsi_cmnd *cmnd;
+
+	/* TODO: async interface is necessary ? */
+	cmnd = kmem_cache_alloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL);
+
+	memset(cmnd, 0, sizeof(*cmnd));
+	INIT_LIST_HEAD(&cmnd->list);
+	INIT_LIST_HEAD(&cmnd->pdu_list);
+	INIT_LIST_HEAD(&cmnd->conn_list);
+	INIT_LIST_HEAD(&cmnd->hash_list);
+	cmnd->conn = conn;
+	spin_lock(&conn->list_lock);
+	atomic_inc(&conn->nr_cmnds);
+	if (req)
+		list_add_tail(&cmnd->conn_list, &conn->pdu_list);
+	spin_unlock(&conn->list_lock);
+	cmnd->tio = NULL;
+
+	dprintk(D_GENERIC, "%p:%p\n", conn, cmnd);
+
+	return cmnd;
+}
+
+/**
+ * create a new command used as response.
+ *
+ * iscsi_cmnd_create_rsp_cmnd -
+ * @cmnd: ptr to request command
+ *
+ * @return    ptr to response command or NULL
+ */
+
+static struct iscsi_cmnd *iscsi_cmnd_create_rsp_cmnd(struct iscsi_cmnd *cmnd, int final)
+{
+	struct iscsi_cmnd *rsp = cmnd_alloc(cmnd->conn, 0);
+
+	if (final)
+		set_cmnd_final(rsp);
+	list_add_tail(&rsp->pdu_list, &cmnd->pdu_list);
+	rsp->req = cmnd;
+	return rsp;
+}
+
+static struct iscsi_cmnd *get_rsp_cmnd(struct iscsi_cmnd *req)
+{
+	return list_entry(req->pdu_list.prev, struct iscsi_cmnd, pdu_list);
+}
+
+static void iscsi_cmnds_init_write(struct list_head *send)
+{
+	struct iscsi_cmnd *cmnd = list_entry(send->next, struct iscsi_cmnd, list);
+	struct iscsi_conn *conn = cmnd->conn;
+	struct list_head *pos, *next;
+
+	spin_lock(&conn->list_lock);
+
+	list_for_each_safe(pos, next, send) {
+		cmnd = list_entry(pos, struct iscsi_cmnd, list);
+
+		dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));
+
+		list_del_init(&cmnd->list);
+		assert(conn == cmnd->conn);
+		list_add_tail(&cmnd->list, &conn->write_list);
+	}
+
+	spin_unlock(&conn->list_lock);
+
+	nthread_wakeup(conn->session->target);
+}
+
+static void iscsi_cmnd_init_write(struct iscsi_cmnd *cmnd)
+{
+	LIST_HEAD(head);
+
+	if (!list_empty(&cmnd->list)) {
+		eprintk("%x %x %x %x %lx %u %u %u %u %u %u %u %d %d\n",
+			cmnd_itt(cmnd), cmnd_ttt(cmnd), cmnd_opcode(cmnd),
+			cmnd_scsicode(cmnd), cmnd->flags, cmnd->r2t_sn,
+			cmnd->r2t_length, cmnd->is_unsolicited_data,
+			cmnd->target_task_tag, cmnd->outstanding_r2t,
+			cmnd->hdigest, cmnd->ddigest,
+			list_empty(&cmnd->pdu_list), list_empty(&cmnd->hash_list));
+
+		assert(list_empty(&cmnd->list));
+	}
+	list_add(&cmnd->list, &head);
+	iscsi_cmnds_init_write(&head);
+}
+
+static void do_send_data_rsp(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct iscsi_cmnd *data_cmnd;
+	struct tio *tio = cmnd->tio;
+	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+	struct iscsi_data_in_hdr *rsp;
+	u32 pdusize, expsize, scsisize, size, offset, sn;
+	LIST_HEAD(send);
+
+	dprintk(D_GENERIC, "%p\n", cmnd);
+	pdusize = conn->session->param.max_xmit_data_length;
+	expsize = cmnd_read_size(cmnd);
+	size = min(expsize, tio->size);
+	offset = 0;
+	sn = 0;
+
+	while (1) {
+		data_cmnd = iscsi_cmnd_create_rsp_cmnd(cmnd, size <= pdusize);
+		tio_get(tio);
+		data_cmnd->tio = tio;
+		rsp = (struct iscsi_data_in_hdr *)&data_cmnd->pdu.bhs;
+
+		rsp->opcode = ISCSI_OP_SCSI_DATA_IN;
+		rsp->itt = req->itt;
+		rsp->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+		rsp->buffer_offset = offset;
+		rsp->data_sn = cpu_to_be32(sn);
+
+		if (size <= pdusize) {
+			data_cmnd->pdu.datasize = size;
+			rsp->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS;
+
+			scsisize = tio->size;
+			if (scsisize < expsize) {
+				rsp->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
+				size = expsize - scsisize;
+			} else if (scsisize > expsize) {
+				rsp->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW;
+				size = scsisize - expsize;
+			} else
+				size = 0;
+			rsp->residual_count = cpu_to_be32(size);
+			list_add_tail(&data_cmnd->list, &send);
+
+			break;
+		}
+
+		data_cmnd->pdu.datasize = pdusize;
+
+		size -= pdusize;
+		offset += pdusize;
+		sn++;
+
+		list_add_tail(&data_cmnd->list, &send);
+	}
+
+	iscsi_cmnds_init_write(&send);
+}
+
+static struct iscsi_cmnd *create_scsi_rsp(struct iscsi_cmnd *req)
+{
+	struct iscsi_cmnd *rsp;
+	struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
+	struct iscsi_scsi_rsp_hdr *rsp_hdr;
+	struct iscsi_sense_data *sense;
+
+	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);
+
+	rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
+	rsp_hdr->opcode = ISCSI_OP_SCSI_RSP;
+	rsp_hdr->flags = ISCSI_FLG_FINAL;
+	rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED;
+	rsp_hdr->cmd_status = req->status;
+	rsp_hdr->itt = req_hdr->itt;
+
+	if (req->status == SAM_STAT_CHECK_CONDITION) {
+		assert(!rsp->tio);
+		rsp->tio = tio_alloc(1);
+		sense = (struct iscsi_sense_data *)
+			page_address(rsp->tio->pvec[0]);
+
+		assert(sense);
+		clear_page(sense);
+		sense->length = cpu_to_be16(IET_SENSE_BUF_SIZE);
+
+		memcpy(sense->data, req->sense_buf, IET_SENSE_BUF_SIZE);
+		rsp->pdu.datasize = sizeof(struct iscsi_sense_data) +
+			IET_SENSE_BUF_SIZE;
+
+		rsp->tio->size = (rsp->pdu.datasize + 3) & -4;
+		rsp->tio->offset = 0;
+	}
+
+	return rsp;
+}
+
+void iscsi_cmnd_set_sense(struct iscsi_cmnd *cmnd, u8 sense_key, u8 asc,
+			  u8 ascq)
+{
+	cmnd->status = SAM_STAT_CHECK_CONDITION;
+
+	cmnd->sense_buf[0] = 0xf0;
+	cmnd->sense_buf[2] = sense_key;
+	cmnd->sense_buf[7] = 6;	// Additional sense length
+	cmnd->sense_buf[12] = asc;
+	cmnd->sense_buf[13] = ascq;
+}
+
+static struct iscsi_cmnd *create_sense_rsp(struct iscsi_cmnd *req,
+					   u8 sense_key, u8 asc, u8 ascq)
+{
+	iscsi_cmnd_set_sense(req, sense_key, asc, ascq);
+	return create_scsi_rsp(req);
+}
+
+void send_scsi_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *))
+{
+	struct iscsi_cmnd *rsp;
+	struct iscsi_scsi_rsp_hdr *rsp_hdr;
+	u32 size;
+
+	func(req);
+	rsp = create_scsi_rsp(req);
+
+	switch (req->status) {
+	case SAM_STAT_GOOD:
+	case SAM_STAT_RESERVATION_CONFLICT:
+		rsp_hdr = (struct iscsi_scsi_rsp_hdr *) &rsp->pdu.bhs;
+		if ((size = cmnd_read_size(req)) != 0) {
+			rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
+			rsp_hdr->residual_count = cpu_to_be32(size);
+		}
+		break;
+	default:
+		break;
+	}
+
+	iscsi_cmnd_init_write(rsp);
+}
+
+void send_data_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *))
+{
+	struct iscsi_cmnd *rsp;
+
+	func(req);
+
+	if (req->status == SAM_STAT_GOOD)
+		do_send_data_rsp(req);
+	else {
+		rsp = create_scsi_rsp(req);
+		iscsi_cmnd_init_write(rsp);
+	}
+}
+
+/**
+ * Free a command.
+ * Also frees the additional header.
+ *
+ * iscsi_cmnd_remove -
+ * @cmnd: ptr to command
+ */
+
+static void iscsi_cmnd_remove(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn;
+
+	if (!cmnd)
+		return;
+
+	if (cmnd_timer_active(cmnd)) {
+		clear_cmnd_timer_active(cmnd);
+		del_timer_sync(&cmnd->timer);
+	}
+
+	dprintk(D_GENERIC, "%p\n", cmnd);
+	conn = cmnd->conn;
+	kfree(cmnd->pdu.ahs);
+
+	if (!list_empty(&cmnd->list)) {
+		struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+
+		eprintk("cmnd %p still on some list?, %x, %x, %x, %x, %x, %x, %x %lx\n",
+			cmnd, req->opcode, req->scb[0], req->flags, req->itt,
+			be32_to_cpu(req->data_length),
+			req->cmd_sn, be32_to_cpu(cmnd->pdu.datasize),
+			conn->state);
+
+		if (cmnd->req) {
+			struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd->req);
+			eprintk("%p %x %u\n", req, req->opcode, req->scb[0]);
+		}
+		dump_stack();
+		BUG();
+	}
+	list_del(&cmnd->list);
+	spin_lock(&conn->list_lock);
+	atomic_dec(&conn->nr_cmnds);
+	list_del(&cmnd->conn_list);
+	spin_unlock(&conn->list_lock);
+
+	if (cmnd->tio)
+		tio_put(cmnd->tio);
+
+	kmem_cache_free(iscsi_cmnd_cache, cmnd);
+}
+
+static void cmnd_skip_pdu(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct tio *tio = cmnd->tio;
+	char *addr;
+	u32 size;
+	int i;
+
+	eprintk("%x %x %x %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd),
+		cmnd_hdr(cmnd)->scb[0], cmnd->pdu.datasize);
+
+	if (!(size = cmnd->pdu.datasize))
+		return;
+
+	if (tio)
+		assert(tio->pg_cnt > 0);
+	else
+		tio = cmnd->tio = tio_alloc(1);
+
+	addr = page_address(tio->pvec[0]);
+	assert(addr);
+	size = (size + 3) & -4;
+	conn->read_size = size;
+	for (i = 0; size > PAGE_CACHE_SIZE; i++, size -= PAGE_CACHE_SIZE) {
+		assert(i < ISCSI_CONN_IOV_MAX);
+		conn->read_iov[i].iov_base = addr;
+		conn->read_iov[i].iov_len = PAGE_CACHE_SIZE;
+	}
+	conn->read_iov[i].iov_base = addr;
+	conn->read_iov[i].iov_len = size;
+	conn->read_msg.msg_iov = conn->read_iov;
+	conn->read_msg.msg_iovlen = ++i;
+}
+
+static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason)
+{
+	struct iscsi_cmnd *rsp;
+	struct iscsi_reject_hdr *rsp_hdr;
+	struct tio *tio;
+	char *addr;
+
+	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);
+	rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs;
+
+	rsp_hdr->opcode = ISCSI_OP_REJECT;
+	rsp_hdr->ffffffff = ISCSI_RESERVED_TAG;
+	rsp_hdr->reason = reason;
+
+	rsp->tio = tio = tio_alloc(1);
+	addr = page_address(tio->pvec[0]);
+	clear_page(addr);
+	memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr));
+	tio->size = rsp->pdu.datasize = sizeof(struct iscsi_hdr);
+	cmnd_skip_pdu(req);
+
+	req->pdu.bhs.opcode = ISCSI_OP_PDU_REJECT;
+}
+
+static void cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct iscsi_session *sess = conn->session;
+
+	if (set_stat_sn)
+		cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn++);
+	cmnd->pdu.bhs.exp_sn = cpu_to_be32(sess->exp_cmd_sn);
+	cmnd->pdu.bhs.max_sn = cpu_to_be32(sess->exp_cmd_sn + sess->max_queued_cmnds);
+}
+
+static void update_stat_sn(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	u32 exp_stat_sn;
+
+	cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu(cmnd->pdu.bhs.exp_sn);
+	dprintk(D_GENERIC, "%x,%x\n", cmnd_opcode(cmnd), exp_stat_sn);
+	if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 &&
+	    (int)(exp_stat_sn - conn->stat_sn) <= 0) {
+		// free pdu resources
+		cmnd->conn->exp_stat_sn = exp_stat_sn;
+	}
+}
+
+static int check_cmd_sn(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_session *session = cmnd->conn->session;
+	u32 cmd_sn;
+
+	cmnd->pdu.bhs.sn = cmd_sn = be32_to_cpu(cmnd->pdu.bhs.sn);
+	dprintk(D_GENERIC, "%d(%d)\n", cmd_sn, session->exp_cmd_sn);
+	if ((s32)(cmd_sn - session->exp_cmd_sn) >= 0)
+		return 0;
+	eprintk("sequence error (%x,%x)\n", cmd_sn, session->exp_cmd_sn);
+	return -ISCSI_REASON_PROTOCOL_ERROR;
+}
+
+static struct iscsi_cmnd *__cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt)
+{
+	struct list_head *head;
+	struct iscsi_cmnd *cmnd;
+
+	head = &session->cmnd_hash[cmnd_hashfn(itt)];
+
+	list_for_each_entry(cmnd, head, hash_list) {
+		if (cmnd->pdu.bhs.itt == itt) {
+			if ((ttt != ISCSI_RESERVED_TAG) && (ttt != cmnd->target_task_tag))
+				continue;
+			return cmnd;
+		}
+	}
+
+	return NULL;
+}
+
+static struct iscsi_cmnd *cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt)
+{
+	struct iscsi_cmnd *cmnd;
+
+	spin_lock(&session->cmnd_hash_lock);
+
+	cmnd = __cmnd_find_hash(session, itt, ttt);
+
+	spin_unlock(&session->cmnd_hash_lock);
+
+	return cmnd;
+}
+
+static int cmnd_insert_hash_ttt(struct iscsi_cmnd *cmnd, u32 ttt)
+{
+	struct iscsi_session *session = cmnd->conn->session;
+	struct iscsi_cmnd *tmp;
+	struct list_head *head;
+	int err = 0;
+	u32 itt = cmnd->pdu.bhs.itt;
+
+	head = &session->cmnd_hash[cmnd_hashfn(itt)];
+
+	spin_lock(&session->cmnd_hash_lock);
+
+	tmp = __cmnd_find_hash(session, itt, ttt);
+	if (!tmp) {
+		list_add_tail(&cmnd->hash_list, head);
+		set_cmnd_hashed(cmnd);
+	} else
+		err = -ISCSI_REASON_TASK_IN_PROGRESS;
+
+	spin_unlock(&session->cmnd_hash_lock);
+
+	return err;
+}
+
+static int cmnd_insert_hash(struct iscsi_cmnd *cmnd)
+{
+	int err;
+
+	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd->pdu.bhs.itt);
+
+	if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG)
+		return -ISCSI_REASON_PROTOCOL_ERROR;
+
+	err = cmnd_insert_hash_ttt(cmnd, ISCSI_RESERVED_TAG);
+	if (!err) {
+		update_stat_sn(cmnd);
+		err = check_cmd_sn(cmnd);
+	}
+
+	return err;
+}
+
+static void __cmnd_remove_hash(struct iscsi_cmnd *cmnd)
+{
+	list_del(&cmnd->hash_list);
+}
+
+static void cmnd_remove_hash(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_session *session = cmnd->conn->session;
+	struct iscsi_cmnd *tmp;
+
+	spin_lock(&session->cmnd_hash_lock);
+
+	tmp = __cmnd_find_hash(session, cmnd->pdu.bhs.itt,
+			       cmnd->target_task_tag);
+	if (tmp && tmp == cmnd)
+		__cmnd_remove_hash(tmp);
+	else
+		eprintk("%p:%x not found\n", cmnd, cmnd_itt(cmnd));
+
+	spin_unlock(&session->cmnd_hash_lock);
+}
+
+static void cmnd_skip_data(struct iscsi_cmnd *req)
+{
+	struct iscsi_cmnd *rsp;
+	struct iscsi_scsi_rsp_hdr *rsp_hdr;
+	u32 size;
+
+	rsp = get_rsp_cmnd(req);
+	rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs;
+	if (cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP) {
+		eprintk("unexpected response command %u\n", cmnd_opcode(rsp));
+		return;
+	}
+
+	size = cmnd_write_size(req);
+	if (size) {
+		rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
+		rsp_hdr->residual_count = cpu_to_be32(size);
+	}
+	size = cmnd_read_size(req);
+	if (size) {
+		if (cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) {
+			rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW;
+			rsp_hdr->bi_residual_count = cpu_to_be32(size);
+		} else {
+			rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW;
+			rsp_hdr->residual_count = cpu_to_be32(size);
+		}
+	}
+	req->pdu.bhs.opcode =
+		(req->pdu.bhs.opcode & ~ISCSI_OPCODE_MASK) | ISCSI_OP_SCSI_REJECT;
+
+	cmnd_skip_pdu(req);
+}
+
+static int cmnd_recv_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size)
+{
+	int idx, i;
+	char *addr;
+
+	dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size);
+	offset += tio->offset;
+
+	if (!(offset < tio->offset + tio->size) ||
+	    !(offset + size <= tio->offset + tio->size)) {
+		eprintk("%u %u %u %u", offset, size, tio->offset, tio->size);
+		return -EIO;
+	}
+	assert(offset < tio->offset + tio->size);
+	assert(offset + size <= tio->offset + tio->size);
+
+	idx = offset >> PAGE_CACHE_SHIFT;
+	offset &= ~PAGE_CACHE_MASK;
+
+	conn->read_msg.msg_iov = conn->read_iov;
+	conn->read_size = size = (size + 3) & -4;
+	conn->read_overflow = 0;
+
+	i = 0;
+	while (1) {
+		assert(tio->pvec[idx]);
+		addr = page_address(tio->pvec[idx]);
+		assert(addr);
+		conn->read_iov[i].iov_base =  addr + offset;
+		if (offset + size <= PAGE_CACHE_SIZE) {
+			conn->read_iov[i].iov_len = size;
+			conn->read_msg.msg_iovlen = ++i;
+			break;
+		}
+		conn->read_iov[i].iov_len = PAGE_CACHE_SIZE - offset;
+		size -= conn->read_iov[i].iov_len;
+		offset = 0;
+		if (++i >= ISCSI_CONN_IOV_MAX) {
+			conn->read_msg.msg_iovlen = i;
+			conn->read_overflow = size;
+			conn->read_size -= size;
+			break;
+		}
+
+		idx++;
+	}
+
+	return 0;
+}
+
+static void set_offset_and_length(struct iet_volume *lu, u8 *cmd, loff_t *off, u32 *len)
+{
+	assert(lu);
+
+	switch (cmd[0]) {
+	case READ_6:
+	case WRITE_6:
+		*off = ((cmd[1] & 0x1f) << 16) + (cmd[2] << 8) + cmd[3];
+		*len = cmd[4];
+		if (!*len)
+			*len = 256;
+		break;
+	case READ_10:
+	case WRITE_10:
+	case WRITE_VERIFY:
+		*off = (u32)cmd[2] << 24 | (u32)cmd[3] << 16 |
+			(u32)cmd[4] << 8 | (u32)cmd[5];
+		*len = (cmd[7] << 8) + cmd[8];
+		break;
+	case READ_16:
+	case WRITE_16:
+		*off = (u64)cmd[2] << 56 | (u64)cmd[3] << 48 |
+			(u64)cmd[4] << 40 | (u64)cmd[5] << 32 |
+			(u64)cmd[6] << 24 | (u64)cmd[7] << 16 |
+			(u64)cmd[8] << 8 | (u64)cmd[9];
+		*len = (u32)cmd[10] << 24 | (u32)cmd[11] << 16 |
+			(u32)cmd[12] << 8 | (u32)cmd[13];
+		break;
+	default:
+		BUG();
+	}
+
+	*off <<= lu->blk_shift;
+	*len <<= lu->blk_shift;
+}
+
+static u32 translate_lun(u16 * data)
+{
+	u8 *p = (u8 *) data;
+	u32 lun = ~0U;
+
+	switch (*p >> 6) {
+	case 0:
+		lun = p[1];
+		break;
+	case 1:
+		lun = (0x3f & p[0]) << 8 | p[1];
+		break;
+	case 2:
+	case 3:
+	default:
+		eprintk("%u %u %u %u\n", data[0], data[1], data[2], data[3]);
+		break;
+	}
+
+	return lun;
+}
+
+static void send_r2t(struct iscsi_cmnd *req)
+{
+	struct iscsi_cmnd *rsp;
+	struct iscsi_r2t_hdr *rsp_hdr;
+	u32 length, offset, burst;
+	LIST_HEAD(send);
+
+	length = req->r2t_length;
+	burst = req->conn->session->param.max_burst_length;
+	offset = be32_to_cpu(cmnd_hdr(req)->data_length) - length;
+
+	do {
+		rsp = iscsi_cmnd_create_rsp_cmnd(req, 0);
+		rsp->pdu.bhs.ttt = req->target_task_tag;
+
+		rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs;
+		rsp_hdr->opcode = ISCSI_OP_R2T;
+		rsp_hdr->flags = ISCSI_FLG_FINAL;
+		memcpy(rsp_hdr->lun, cmnd_hdr(req)->lun, 8);
+		rsp_hdr->itt = cmnd_hdr(req)->itt;
+		rsp_hdr->r2t_sn = cpu_to_be32(req->r2t_sn++);
+		rsp_hdr->buffer_offset = cpu_to_be32(offset);
+		if (length > burst) {
+			rsp_hdr->data_length = cpu_to_be32(burst);
+			length -= burst;
+			offset += burst;
+		} else {
+			rsp_hdr->data_length = cpu_to_be32(length);
+			length = 0;
+		}
+
+		dprintk(D_WRITE, "%x %u %u %u %u\n", cmnd_itt(req),
+			be32_to_cpu(rsp_hdr->data_length),
+			be32_to_cpu(rsp_hdr->buffer_offset),
+			be32_to_cpu(rsp_hdr->r2t_sn), req->outstanding_r2t);
+
+		list_add_tail(&rsp->list, &send);
+
+		if (++req->outstanding_r2t >= req->conn->session->param.max_outstanding_r2t)
+			break;
+
+	} while (length);
+
+	iscsi_cmnds_init_write(&send);
+}
+
+static void scsi_cmnd_exec(struct iscsi_cmnd *cmnd)
+{
+	if (cmnd->r2t_length) {
+		if (!cmnd->is_unsolicited_data)
+			send_r2t(cmnd);
+	} else {
+		if (cmnd->lun) {
+			iscsi_scsi_queuecmnd(cmnd);
+		} else {
+			iscsi_device_queue_cmnd(cmnd);
+		}
+	}
+}
+
+static int nop_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
+{
+	u32 size, tmp;
+	int i, err = 0;
+
+	if (cmnd_ttt(cmnd) != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		cmnd->req = cmnd_find_hash(conn->session, cmnd->pdu.bhs.itt,
+					   cmnd->pdu.bhs.ttt);
+		if (!cmnd->req) {
+			/*
+			 * We didn't request this NOP-Out (by sending a
+			 * NOP-In, see 10.18.2 of the RFC) or our fake NOP-Out
+			 * timed out.
+			 */
+			eprintk("initiator bug %x\n", cmnd_itt(cmnd));
+			err = -ISCSI_REASON_PROTOCOL_ERROR;
+			goto out;
+		}
+
+		del_timer_sync(&cmnd->req->timer);
+		clear_cmnd_timer_active(cmnd->req);
+		dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p\n",
+			cmnd->req, cmnd_ttt(cmnd->req), &cmnd->req->timer);
+	}
+
+	if (cmnd_itt(cmnd) == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		if (!(cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE))
+			eprintk("%s\n", "initiator bug!");
+		update_stat_sn(cmnd);
+		err = check_cmd_sn(cmnd);
+		if (err)
+			goto out;
+	} else if ((err = cmnd_insert_hash(cmnd)) < 0) {
+		eprintk("ignore this request %x\n", cmnd_itt(cmnd));
+		goto out;
+	}
+
+	if ((size = cmnd->pdu.datasize)) {
+		size = (size + 3) & -4;
+		conn->read_msg.msg_iov = conn->read_iov;
+		if (cmnd->pdu.bhs.itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+			struct tio *tio;
+			int pg_cnt = get_pgcnt(size, 0);
+
+			assert(pg_cnt < ISCSI_CONN_IOV_MAX);
+			cmnd->tio = tio = tio_alloc(pg_cnt);
+			tio_set(tio, size, 0);
+
+			for (i = 0; i < pg_cnt; i++) {
+				conn->read_iov[i].iov_base
+					= page_address(tio->pvec[i]);
+				tmp = min_t(u32, size, PAGE_CACHE_SIZE);
+				conn->read_iov[i].iov_len = tmp;
+				conn->read_size += tmp;
+				size -= tmp;
+			}
+		} else {
+			for (i = 0; i < ISCSI_CONN_IOV_MAX; i++) {
+				conn->read_iov[i].iov_base = dummy_data;
+				tmp = min_t(u32, size, sizeof(dummy_data));
+				conn->read_iov[i].iov_len = tmp;
+				conn->read_size += tmp;
+				size -= tmp;
+			}
+		}
+		assert(!size);
+		conn->read_overflow = size;
+		conn->read_msg.msg_iovlen = i;
+	}
+
+out:
+	return err;
+}
+
+static u32 get_next_ttt(struct iscsi_session *session)
+{
+	u32 ttt;
+
+	if (session->next_ttt == ISCSI_RESERVED_TAG)
+		session->next_ttt++;
+	ttt = session->next_ttt++;
+
+	return cpu_to_be32(ttt);
+}
+
+static void scsi_cmnd_start(struct iscsi_conn *conn, struct iscsi_cmnd *req)
+{
+	struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req);
+
+	dprintk(D_GENERIC, "scsi command: %02x\n", req_hdr->scb[0]);
+
+	req->lun = volume_get(conn->session->target, translate_lun(req_hdr->lun));
+	if (!req->lun) {
+		switch (req_hdr->scb[0]) {
+		case INQUIRY:
+		case REPORT_LUNS:
+			break;
+		default:
+			eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]);
+			create_sense_rsp(req, ILLEGAL_REQUEST, 0x25, 0x0);
+			cmnd_skip_data(req);
+			goto out;
+		}
+	} else
+		set_cmnd_lunit(req);
+
+	switch (req_hdr->scb[0]) {
+	case SERVICE_ACTION_IN:
+		if ((req_hdr->scb[1] & 0x1f) != 0x10)
+			goto error;
+	case INQUIRY:
+	case REPORT_LUNS:
+	case TEST_UNIT_READY:
+	case SYNCHRONIZE_CACHE:
+	case VERIFY:
+	case VERIFY_16:
+	case START_STOP:
+	case READ_CAPACITY:
+	case MODE_SENSE:
+	case REQUEST_SENSE:
+	case RESERVE:
+	case RELEASE:
+	{
+		if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) {
+			/* unexpected unsolicited data */
+			eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]);
+			create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc);
+			cmnd_skip_data(req);
+		}
+		break;
+	}
+	case READ_6:
+	case READ_10:
+	case READ_16:
+	{
+		loff_t offset;
+		u32 length;
+
+		if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) {
+			/* unexpected unsolicited data */
+			eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]);
+			create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc);
+			cmnd_skip_data(req);
+			break;
+		}
+
+		set_offset_and_length(req->lun, req_hdr->scb, &offset, &length);
+		req->tio = tio_alloc(get_pgcnt(length, offset));
+		tio_set(req->tio, length, offset);
+		break;
+	}
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+	case WRITE_VERIFY:
+	{
+		struct iscsi_sess_param *param = &conn->session->param;
+		loff_t offset;
+		u32 length;
+
+		req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize;
+		req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL);
+		req->target_task_tag = get_next_ttt(conn->session);
+
+		if (LUReadonly(req->lun)) {
+			create_sense_rsp(req, DATA_PROTECT, 0x27, 0x0);
+			cmnd_skip_data(req);
+			break;
+		}
+
+		if (!param->immediate_data && req->pdu.datasize)
+			eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]);
+
+		if (param->initial_r2t && !(req_hdr->flags & ISCSI_CMD_FINAL))
+			eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]);
+
+		if (req_hdr->scb[0] == WRITE_VERIFY && req_hdr->scb[1] & 0x02)
+			eprintk("Verification is ignored %x\n", cmnd_itt(req));
+
+		set_offset_and_length(req->lun, req_hdr->scb, &offset, &length);
+		if (cmnd_write_size(req) != length)
+			eprintk("%x %u %u\n", cmnd_itt(req), cmnd_write_size(req), length);
+
+		req->tio = tio_alloc(get_pgcnt(length, offset));
+		tio_set(req->tio, length, offset);
+
+		if (req->pdu.datasize) {
+			if (cmnd_recv_pdu(conn, req->tio, 0, req->pdu.datasize) < 0)
+				assert(0);
+		}
+		break;
+	}
+	error:
+	default:
+		eprintk("Unsupported %x\n", req_hdr->scb[0]);
+		create_sense_rsp(req, ILLEGAL_REQUEST, 0x20, 0x0);
+		cmnd_skip_data(req);
+		break;
+	}
+
+out:
+	return;
+}
+
+static void data_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs;
+	struct iscsi_cmnd *scsi_cmnd = NULL;
+	u32 offset = be32_to_cpu(req->buffer_offset);
+
+	update_stat_sn(cmnd);
+
+	cmnd->req = scsi_cmnd = cmnd_find_hash(conn->session, req->itt, req->ttt);
+	if (!scsi_cmnd) {
+		eprintk("unable to find scsi task %x %x\n",
+			cmnd_itt(cmnd), cmnd_ttt(cmnd));
+		goto skip_data;
+	}
+
+	if (scsi_cmnd->r2t_length < cmnd->pdu.datasize) {
+		eprintk("invalid data len %x %u %u\n",
+			cmnd_itt(scsi_cmnd), cmnd->pdu.datasize, scsi_cmnd->r2t_length);
+		goto skip_data;
+	}
+
+	if (scsi_cmnd->r2t_length + offset != cmnd_write_size(scsi_cmnd)) {
+		eprintk("%x %u %u %u\n", cmnd_itt(scsi_cmnd), scsi_cmnd->r2t_length,
+			offset,	cmnd_write_size(scsi_cmnd));
+		goto skip_data;
+	}
+
+	scsi_cmnd->r2t_length -= cmnd->pdu.datasize;
+
+	if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		/* unsolicited burst data */
+		if (scsi_cmnd->pdu.bhs.flags & ISCSI_FLG_FINAL) {
+			eprintk("unexpected data from %x %x\n",
+				cmnd_itt(cmnd), cmnd_ttt(cmnd));
+			goto skip_data;
+		}
+	}
+
+	dprintk(D_WRITE, "%u %p %p %p %u %u\n", req->ttt, cmnd, scsi_cmnd,
+		scsi_cmnd->tio, offset, cmnd->pdu.datasize);
+
+	if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, cmnd->pdu.datasize) < 0)
+		goto skip_data;
+	return;
+
+skip_data:
+	cmnd->pdu.bhs.opcode = ISCSI_OP_DATA_REJECT;
+	cmnd_skip_pdu(cmnd);
+	return;
+}
+
+static void data_out_end(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs;
+	struct iscsi_cmnd *scsi_cmnd;
+	u32 offset;
+
+	assert(cmnd);
+	scsi_cmnd = cmnd->req;
+	assert(scsi_cmnd);
+
+	if (conn->read_overflow) {
+		eprintk("%x %u\n", cmnd_itt(cmnd), conn->read_overflow);
+		assert(scsi_cmnd->tio);
+		offset = be32_to_cpu(req->buffer_offset);
+		offset += cmnd->pdu.datasize - conn->read_overflow;
+		if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, conn->read_overflow) < 0)
+			assert(0);
+		return;
+	}
+
+	if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		if (req->flags & ISCSI_FLG_FINAL) {
+			scsi_cmnd->is_unsolicited_data = 0;
+			if (!cmnd_pending(scsi_cmnd))
+				scsi_cmnd_exec(scsi_cmnd);
+		}
+	} else {
+		/* TODO : proper error handling */
+		if (!(req->flags & ISCSI_FLG_FINAL) && scsi_cmnd->r2t_length == 0)
+			eprintk("initiator error %x\n", cmnd_itt(scsi_cmnd));
+
+		if (!(req->flags & ISCSI_FLG_FINAL))
+			goto out;
+
+		scsi_cmnd->outstanding_r2t--;
+
+		if (scsi_cmnd->r2t_length == 0)
+			assert(list_empty(&scsi_cmnd->pdu_list));
+
+		scsi_cmnd_exec(scsi_cmnd);
+	}
+
+out:
+	iscsi_cmnd_remove(cmnd);
+	return;
+}
+
+static int __cmnd_abort(struct iscsi_cmnd *cmnd)
+{
+	if (cmnd_waitio(cmnd))
+		return -ISCSI_RESPONSE_UNKNOWN_TASK;
+
+	if (cmnd->conn->read_cmnd != cmnd)
+		cmnd_release(cmnd, 1);
+	else if (cmnd_rxstart(cmnd))
+		set_cmnd_tmfabort(cmnd);
+	else
+		return -ISCSI_RESPONSE_UNKNOWN_TASK;
+
+	return 0;
+}
+
+static int cmnd_abort(struct iscsi_session *session, u32 itt)
+{
+	struct iscsi_cmnd *cmnd;
+	int err =  -ISCSI_RESPONSE_UNKNOWN_TASK;
+
+	if ((cmnd = cmnd_find_hash(session, itt, ISCSI_RESERVED_TAG))) {
+		eprintk("%x %x %x %u %u %u %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd),
+			cmnd->r2t_length, cmnd_scsicode(cmnd),
+			cmnd_write_size(cmnd), cmnd->is_unsolicited_data,
+			cmnd->outstanding_r2t);
+		err = __cmnd_abort(cmnd);
+	}
+
+	return err;
+}
+
+static int target_reset(struct iscsi_cmnd *req, u32 lun, int all)
+{
+	struct iscsi_target *target = req->conn->session->target;
+	struct iscsi_session *session;
+	struct iscsi_conn *conn;
+	struct iscsi_cmnd *cmnd, *tmp;
+	struct iet_volume *volume;
+
+	list_for_each_entry(session, &target->session_list, list) {
+		list_for_each_entry(conn, &session->conn_list, list) {
+			list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) {
+				if (cmnd == req)
+					continue;
+
+				if (all)
+					__cmnd_abort(cmnd);
+				else if (translate_lun(cmnd_hdr(cmnd)->lun) == lun)
+					__cmnd_abort(cmnd);
+			}
+		}
+	}
+
+	list_for_each_entry(volume, &target->volumes, list) {
+		if (all || volume->lun == lun) {
+			/* force release */
+			volume_release(volume, 0, 1);
+			/* power-on, reset, or bus device reset occurred */
+			ua_establish_for_all_sessions(target, volume->lun,
+						      0x29, 0x0);
+		}
+	}
+
+	return 0;
+}
+
+static void task_set_abort(struct iscsi_cmnd *req)
+{
+	struct iscsi_session *session = req->conn->session;
+	struct iscsi_conn *conn;
+	struct iscsi_cmnd *cmnd, *tmp;
+
+	list_for_each_entry(conn, &session->conn_list, list) {
+		list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) {
+			if (cmnd != req)
+				__cmnd_abort(cmnd);
+		}
+	}
+}
+
+static inline char *tmf_desc(int fun)
+{
+	static char *tmf_desc[] = {
+		"Unknown Function",
+		"Abort Task",
+		"Abort Task Set",
+		"Clear ACA",
+		"Clear Task Set",
+		"Logical Unit Reset",
+		"Target Warm Reset",
+		"Target Cold Reset",
+		"Task Reassign",
+        };
+
+	if ((fun < ISCSI_FUNCTION_ABORT_TASK) ||
+				(fun > ISCSI_FUNCTION_TASK_REASSIGN))
+		fun = 0;
+
+	return tmf_desc[fun];
+}
+
+static inline char *rsp_desc(int rsp)
+{
+	static char *rsp_desc[] = {
+		"Function Complete",
+		"Unknown Task",
+		"Unknown LUN",
+		"Task Allegiant",
+		"Failover Unsupported",
+		"Function Unsupported",
+		"No Authorization",
+		"Function Rejected",
+		"Unknown Response",
+	};
+
+	if (((rsp < ISCSI_RESPONSE_FUNCTION_COMPLETE) ||
+			(rsp > ISCSI_RESPONSE_NO_AUTHORIZATION)) &&
+			(rsp != ISCSI_RESPONSE_FUNCTION_REJECTED))
+		rsp = 8;
+	else if (rsp == ISCSI_RESPONSE_FUNCTION_REJECTED)
+		rsp = 7;
+
+	return rsp_desc[rsp];
+}
+
+static void execute_task_management(struct iscsi_cmnd *req)
+{
+	struct iscsi_conn *conn = req->conn;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_target *target = session->target;
+	struct iscsi_cmnd *rsp;
+	struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;
+	struct iscsi_task_rsp_hdr *rsp_hdr;
+	u32 lun;
+	int err, function = req_hdr->function & ISCSI_FUNCTION_MASK;
+
+	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);
+	rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs;
+
+	rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;
+	rsp_hdr->flags = ISCSI_FLG_FINAL;
+	rsp_hdr->itt = req_hdr->itt;
+	rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_COMPLETE;
+
+	switch (function) {
+	case ISCSI_FUNCTION_ABORT_TASK:
+	case ISCSI_FUNCTION_ABORT_TASK_SET:
+	case ISCSI_FUNCTION_CLEAR_ACA:
+	case ISCSI_FUNCTION_CLEAR_TASK_SET:
+	case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
+		lun = translate_lun(req_hdr->lun);
+		if (!volume_lookup(target, lun)) {
+			rsp_hdr->response = ISCSI_RESPONSE_UNKNOWN_LUN;
+			goto out;
+		}
+	}
+
+	switch (function) {
+	case ISCSI_FUNCTION_ABORT_TASK:
+		if ((err = cmnd_abort(conn->session, req_hdr->rtt)) < 0)
+			rsp_hdr->response = -err;
+		break;
+	case ISCSI_FUNCTION_ABORT_TASK_SET:
+		task_set_abort(req);
+		break;
+	case ISCSI_FUNCTION_CLEAR_ACA:
+		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
+		break;
+	case ISCSI_FUNCTION_CLEAR_TASK_SET:
+		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
+		break;
+	case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:
+		target_reset(req, translate_lun(req_hdr->lun), 0);
+		break;
+	case ISCSI_FUNCTION_TARGET_WARM_RESET:
+	case ISCSI_FUNCTION_TARGET_COLD_RESET:
+		target_reset(req, 0, 1);
+		if (function == ISCSI_FUNCTION_TARGET_COLD_RESET)
+			set_cmnd_close(rsp);
+		break;
+	case ISCSI_FUNCTION_TASK_REASSIGN:
+		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;
+		break;
+	default:
+		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED;
+		break;
+	}
+out:
+	iprintk("%s (%02x) issued on tid:%d lun:%d by sid:%llu (%s)\n",
+				tmf_desc(function), function, target->tid,
+				translate_lun(req_hdr->lun), session->sid,
+				rsp_desc(rsp_hdr->response));
+
+	iscsi_cmnd_init_write(rsp);
+}
+
+static void nop_hdr_setup(struct iscsi_hdr *hdr, u8 opcode, __be32 itt,
+			  __be32 ttt)
+{
+	hdr->opcode = opcode;
+	hdr->flags = ISCSI_FLG_FINAL;
+	hdr->itt = itt;
+	hdr->ttt = ttt;
+}
+
+static void nop_out_exec(struct iscsi_cmnd *req)
+{
+	struct iscsi_cmnd *rsp;
+
+	if (cmnd_itt(req) != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);
+
+		nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN, req->pdu.bhs.itt,
+			      cpu_to_be32(ISCSI_RESERVED_TAG));
+
+		if (req->pdu.datasize)
+			assert(req->tio);
+		else
+			assert(!req->tio);
+
+		if (req->tio) {
+			tio_get(req->tio);
+			rsp->tio = req->tio;
+		}
+
+		assert(get_pgcnt(req->pdu.datasize, 0) < ISCSI_CONN_IOV_MAX);
+		rsp->pdu.datasize = req->pdu.datasize;
+		iscsi_cmnd_init_write(rsp);
+	} else {
+		if (req->req) {
+			dprintk(D_GENERIC, "releasing NOP-Out %p, ttt %x; "
+				"removing NOP-In %p, ttt %x\n", req->req,
+				cmnd_ttt(req->req), req, cmnd_ttt(req));
+			cmnd_release(req->req, 0);
+		}
+		iscsi_cmnd_remove(req);
+	}
+}
+
+static void nop_in_timeout(unsigned long data)
+{
+	struct iscsi_cmnd *req = (struct iscsi_cmnd *)data;
+
+	printk(KERN_INFO "NOP-In ping timed out - closing sid:cid %llu:%u\n",
+	       req->conn->session->sid, req->conn->cid);
+	clear_cmnd_timer_active(req);
+	conn_close(req->conn);
+}
+
+/* create a fake NOP-Out req and treat the NOP-In as our rsp to it */
+void send_nop_in(struct iscsi_conn *conn)
+{
+	struct iscsi_cmnd *req = cmnd_alloc(conn, 1);
+	struct iscsi_cmnd *rsp = iscsi_cmnd_create_rsp_cmnd(req, 0);
+
+	req->target_task_tag = get_next_ttt(conn->session);
+
+
+	nop_hdr_setup(&req->pdu.bhs, ISCSI_OP_NOP_OUT,
+		      cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag);
+	nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN,
+		      cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag);
+
+	dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p; "
+		"NOP-In: %p, ttt %x;\n", req, cmnd_ttt(req), &req->timer, rsp,
+		cmnd_ttt(rsp));
+
+	init_timer(&req->timer);
+	req->timer.data = (unsigned long)req;
+	req->timer.function = nop_in_timeout;
+
+	if (cmnd_insert_hash_ttt(req, req->target_task_tag)) {
+		eprintk("%s\n",
+			"failed to insert fake NOP-Out into hash table");
+		cmnd_release(rsp, 0);
+		cmnd_release(req, 0);
+	} else
+		iscsi_cmnd_init_write(rsp);
+}
+
+static void nop_in_tx_end(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	u32 t;
+
+	if (cmnd->pdu.bhs.ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
+		return;
+
+	/*
+	 * NOP-In ping issued by the target.
+	 * FIXME: Sanitize the NOP timeout earlier, during configuration
+	 */
+	t = conn->session->target->trgt_param.nop_timeout;
+
+	if (!t || t > conn->session->target->trgt_param.nop_interval) {
+		eprintk("Adjusting NOPTimeout of tid %u from %u to %u "
+			"(== NOPInterval)\n", conn->session->target->tid,
+			t,
+			conn->session->target->trgt_param.nop_interval);
+		t = conn->session->target->trgt_param.nop_interval;
+		conn->session->target->trgt_param.nop_timeout = t;
+	}
+
+	dprintk(D_GENERIC, "NOP-In %p, %x: timer %p\n",	cmnd, cmnd_ttt(cmnd),
+		&cmnd->req->timer);
+
+	set_cmnd_timer_active(cmnd->req);
+	mod_timer(&cmnd->req->timer, jiffies + HZ * t);
+}
+
+static void logout_exec(struct iscsi_cmnd *req)
+{
+	struct iscsi_logout_req_hdr *req_hdr;
+	struct iscsi_cmnd *rsp;
+	struct iscsi_logout_rsp_hdr *rsp_hdr;
+
+	req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs;
+	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);
+	rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs;
+	rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP;
+	rsp_hdr->flags = ISCSI_FLG_FINAL;
+	rsp_hdr->itt = req_hdr->itt;
+	set_cmnd_close(rsp);
+	iscsi_cmnd_init_write(rsp);
+}
+
+static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd)
+{
+	dprintk(D_GENERIC, "%p,%x,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn);
+
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_NOP_OUT:
+		nop_out_exec(cmnd);
+		break;
+	case ISCSI_OP_SCSI_CMD:
+		scsi_cmnd_exec(cmnd);
+		break;
+	case ISCSI_OP_SCSI_TASK_MGT_MSG:
+		execute_task_management(cmnd);
+		break;
+	case ISCSI_OP_LOGOUT_CMD:
+		logout_exec(cmnd);
+		break;
+	case ISCSI_OP_SCSI_REJECT:
+		iscsi_cmnd_init_write(get_rsp_cmnd(cmnd));
+		break;
+	case ISCSI_OP_TEXT_CMD:
+	case ISCSI_OP_SNACK_CMD:
+		break;
+	default:
+		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));
+		break;
+	}
+}
+
+static void __cmnd_send_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size)
+{
+	dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size);
+	offset += tio->offset;
+
+	assert(offset <= tio->offset + tio->size);
+	assert(offset + size <= tio->offset + tio->size);
+
+	conn->write_tcmnd = tio;
+	conn->write_offset = offset;
+	conn->write_size += size;
+}
+
+static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
+{
+	u32 size;
+	struct tio *tio;
+
+	if (!cmnd->pdu.datasize)
+		return;
+
+	size = (cmnd->pdu.datasize + 3) & -4;
+	tio = cmnd->tio;
+	assert(tio);
+	assert(tio->size == size);
+	__cmnd_send_pdu(conn, tio, 0, size);
+}
+
+static void set_cork(struct socket *sock, int on)
+{
+	int opt = on;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&opt, sizeof(opt));
+	set_fs(oldfs);
+}
+
+void cmnd_release(struct iscsi_cmnd *cmnd, int force)
+{
+	struct iscsi_cmnd *req, *rsp;
+	int is_last = 0;
+
+	if (!cmnd)
+		return;
+
+/* 	eprintk("%x %lx %d\n", cmnd_opcode(cmnd), cmnd->flags, force); */
+
+	req = cmnd->req;
+	is_last = cmnd_final(cmnd);
+
+	if (force) {
+		while (!list_empty(&cmnd->pdu_list)) {
+			rsp = list_entry(cmnd->pdu_list.next, struct iscsi_cmnd, pdu_list);
+			list_del_init(&rsp->list);
+			list_del(&rsp->pdu_list);
+			iscsi_cmnd_remove(rsp);
+		}
+		list_del_init(&cmnd->list);
+	} else
+		if (cmnd_queued(cmnd))
+			iscsi_scsi_dequeuecmnd(cmnd);
+
+	if (cmnd_hashed(cmnd))
+		cmnd_remove_hash(cmnd);
+
+	if (cmnd_lunit(cmnd)) {
+		assert(cmnd->lun);
+		volume_put(cmnd->lun);
+	}
+
+	list_del_init(&cmnd->pdu_list);
+	iscsi_cmnd_remove(cmnd);
+
+	if (is_last) {
+		assert(!force);
+		assert(req);
+		cmnd_release(req, 0);
+	}
+
+	return;
+}
+
+void cmnd_tx_start(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct iovec *iop;
+
+	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));
+	assert(cmnd);
+	iscsi_cmnd_set_length(&cmnd->pdu);
+
+	set_cork(conn->sock, 1);
+
+	conn->write_iop = iop = conn->write_iov;
+	iop->iov_base = &cmnd->pdu.bhs;
+	iop->iov_len = sizeof(cmnd->pdu.bhs);
+	iop++;
+	conn->write_size = sizeof(cmnd->pdu.bhs);
+
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_NOP_IN:
+		if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) {
+			/* NOP-In ping generated by us. Don't advance StatSN. */
+			cmnd_set_sn(cmnd, 0);
+			cmnd_set_sn(cmnd->req, 0);
+			cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn);
+			cmnd->req->pdu.bhs.sn = cpu_to_be32(conn->stat_sn);
+		} else
+			cmnd_set_sn(cmnd, 1);
+		cmnd_send_pdu(conn, cmnd);
+		break;
+	case ISCSI_OP_SCSI_RSP:
+		cmnd_set_sn(cmnd, 1);
+		cmnd_send_pdu(conn, cmnd);
+		break;
+	case ISCSI_OP_SCSI_TASK_MGT_RSP:
+		cmnd_set_sn(cmnd, 1);
+		break;
+	case ISCSI_OP_TEXT_RSP:
+		cmnd_set_sn(cmnd, 1);
+		break;
+	case ISCSI_OP_SCSI_DATA_IN:
+	{
+		struct iscsi_data_in_hdr *rsp = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;
+		u32 offset;
+
+		cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0);
+		offset = rsp->buffer_offset;
+		rsp->buffer_offset = cpu_to_be32(offset);
+		__cmnd_send_pdu(conn, cmnd->tio, offset, cmnd->pdu.datasize);
+		break;
+	}
+	case ISCSI_OP_LOGOUT_RSP:
+		cmnd_set_sn(cmnd, 1);
+		break;
+	case ISCSI_OP_R2T:
+		cmnd_set_sn(cmnd, 0);
+		cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn);
+		break;
+	case ISCSI_OP_ASYNC_MSG:
+		cmnd_set_sn(cmnd, 1);
+		break;
+	case ISCSI_OP_REJECT:
+		cmnd_set_sn(cmnd, 1);
+		cmnd_send_pdu(conn, cmnd);
+		break;
+	default:
+		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));
+		break;
+	}
+
+	iop->iov_len = 0;
+	// move this?
+	conn->write_size = (conn->write_size + 3) & -4;
+	iscsi_dump_pdu(&cmnd->pdu);
+}
+
+void cmnd_tx_end(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+
+	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_NOP_IN:
+		nop_in_tx_end(cmnd);
+		break;
+	case ISCSI_OP_SCSI_RSP:
+	case ISCSI_OP_SCSI_TASK_MGT_RSP:
+	case ISCSI_OP_TEXT_RSP:
+	case ISCSI_OP_R2T:
+	case ISCSI_OP_ASYNC_MSG:
+	case ISCSI_OP_REJECT:
+	case ISCSI_OP_SCSI_DATA_IN:
+	case ISCSI_OP_LOGOUT_RSP:
+		break;
+	default:
+		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));
+		assert(0);
+		break;
+	}
+
+	if (cmnd_close(cmnd))
+		conn_close(conn);
+
+	list_del_init(&cmnd->list);
+	set_cork(cmnd->conn->sock, 0);
+}
+
+/**
+ * Push the command for execution.
+ * This functions reorders the commands.
+ * Called from the read thread.
+ *
+ * iscsi_session_push_cmnd -
+ * @cmnd: ptr to command
+ */
+
+static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_session *session = cmnd->conn->session;
+	struct list_head *entry;
+	u32 cmd_sn;
+
+	dprintk(D_GENERIC, "%p:%x %u,%u\n",
+		cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn);
+
+	if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {
+		iscsi_cmnd_exec(cmnd);
+		return;
+	}
+
+	cmd_sn = cmnd->pdu.bhs.sn;
+	if (cmd_sn == session->exp_cmd_sn) {
+		while (1) {
+			session->exp_cmd_sn = ++cmd_sn;
+			iscsi_cmnd_exec(cmnd);
+
+			if (list_empty(&session->pending_list))
+				break;
+			cmnd = list_entry(session->pending_list.next, struct iscsi_cmnd, list);
+			if (cmnd->pdu.bhs.sn != cmd_sn)
+				break;
+/* 			eprintk("find out-of-order %x %u %u\n", */
+/* 				cmnd_itt(cmnd), cmd_sn, cmnd->pdu.bhs.sn); */
+			list_del_init(&cmnd->list);
+			clear_cmnd_pending(cmnd);
+		}
+	} else {
+/* 		eprintk("out-of-order %x %u %u\n", */
+/* 			cmnd_itt(cmnd), cmd_sn, session->exp_cmd_sn); */
+
+		set_cmnd_pending(cmnd);
+		if (before(cmd_sn, session->exp_cmd_sn)) /* close the conn */
+			eprintk("unexpected cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn);
+
+		if (after(cmd_sn, session->exp_cmd_sn + session->max_queued_cmnds))
+			eprintk("too large cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn);
+
+		list_for_each(entry, &session->pending_list) {
+			struct iscsi_cmnd *tmp = list_entry(entry, struct iscsi_cmnd, list);
+			if (before(cmd_sn, tmp->pdu.bhs.sn))
+				break;
+		}
+
+		assert(list_empty(&cmnd->list));
+
+		list_add_tail(&cmnd->list, entry);
+	}
+}
+
+static int check_segment_length(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct iscsi_sess_param *param = &conn->session->param;
+
+	if (cmnd->pdu.datasize > param->max_recv_data_length) {
+		eprintk("data too long %x %u %u\n", cmnd_itt(cmnd),
+			cmnd->pdu.datasize, param->max_recv_data_length);
+
+		if (get_pgcnt(cmnd->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX) {
+			conn_close(conn);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+void cmnd_rx_start(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	int err = 0;
+
+	iscsi_dump_pdu(&cmnd->pdu);
+
+	set_cmnd_rxstart(cmnd);
+	if (check_segment_length(cmnd) < 0)
+		return;
+
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_NOP_OUT:
+		err = nop_out_start(conn, cmnd);
+		break;
+	case ISCSI_OP_SCSI_CMD:
+		if (!(err = cmnd_insert_hash(cmnd)))
+			scsi_cmnd_start(conn, cmnd);
+		break;
+	case ISCSI_OP_SCSI_TASK_MGT_MSG:
+		err = cmnd_insert_hash(cmnd);
+		break;
+	case ISCSI_OP_SCSI_DATA_OUT:
+		data_out_start(conn, cmnd);
+		break;
+	case ISCSI_OP_LOGOUT_CMD:
+		err = cmnd_insert_hash(cmnd);
+		break;
+	case ISCSI_OP_TEXT_CMD:
+	case ISCSI_OP_SNACK_CMD:
+		err = -ISCSI_REASON_UNSUPPORTED_COMMAND;
+		break;
+	default:
+		err = -ISCSI_REASON_UNSUPPORTED_COMMAND;
+		break;
+	}
+
+	if (err < 0) {
+		eprintk("%x %x %d\n", cmnd_opcode(cmnd), cmnd_itt(cmnd), err);
+		iscsi_cmnd_reject(cmnd, -err);
+	}
+}
+
+void cmnd_rx_end(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+
+	if (cmnd_tmfabort(cmnd)) {
+		cmnd_release(cmnd, 1);
+		return;
+	}
+
+	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));
+	switch (cmnd_opcode(cmnd)) {
+	case ISCSI_OP_SCSI_REJECT:
+	case ISCSI_OP_NOP_OUT:
+	case ISCSI_OP_SCSI_CMD:
+	case ISCSI_OP_SCSI_TASK_MGT_MSG:
+	case ISCSI_OP_TEXT_CMD:
+	case ISCSI_OP_LOGOUT_CMD:
+		iscsi_session_push_cmnd(cmnd);
+		break;
+	case ISCSI_OP_SCSI_DATA_OUT:
+		data_out_end(conn, cmnd);
+		break;
+	case ISCSI_OP_SNACK_CMD:
+		break;
+	case ISCSI_OP_PDU_REJECT:
+		iscsi_cmnd_init_write(get_rsp_cmnd(cmnd));
+		break;
+	case ISCSI_OP_DATA_REJECT:
+		cmnd_release(cmnd, 0);
+		break;
+	default:
+		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));
+		BUG();
+		break;
+	}
+}
+
+static void iscsi_exit(void)
+{
+	wthread_module_exit();
+
+	unregister_chrdev(ctr_major, ctr_name);
+
+	iet_procfs_exit();
+
+	event_exit();
+
+	tio_exit();
+
+	iotype_exit();
+
+	ua_exit();
+
+	if (iscsi_cmnd_cache)
+		kmem_cache_destroy(iscsi_cmnd_cache);
+}
+
+static int iscsi_init(void)
+{
+	int err = -ENOMEM;
+
+	printk("iSCSI Enterprise Target Software - version %s\n", IET_VERSION_STRING);
+
+	if ((ctr_major = register_chrdev(0, ctr_name, &ctr_fops)) < 0) {
+		eprintk("failed to register the control device %d\n", ctr_major);
+		return ctr_major;
+	}
+
+	if ((err = iet_procfs_init()) < 0)
+		goto err;
+
+	if ((err = event_init()) < 0)
+		goto err;
+
+	iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, 0);
+	if (!iscsi_cmnd_cache)
+		goto err;
+
+	err = ua_init();
+	if (err < 0)
+		goto err;
+
+	if ((err = tio_init()) < 0)
+		goto err;
+
+	if ((err = iotype_init()) < 0)
+		goto err;
+
+	if ((err = wthread_module_init()) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	iscsi_exit();
+	return err;
+}
+
+module_param(worker_thread_pool_size, ulong, S_IRUGO);
+MODULE_PARM_DESC(worker_thread_pool_size,
+		 "Size of the worker thread pool "
+		 "(0 = dedicated threads per target (default))");
+
+module_param(debug_enable_flags, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_enable_flags,
+		 "debug bitmask, low bits (0 ... 8) used, see iscsi_dbg.h");
+
+module_init(iscsi_init);
+module_exit(iscsi_exit);
+
+MODULE_VERSION(IET_VERSION_STRING);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("iSCSI Enterprise Target");
+MODULE_AUTHOR("IET development team <iscsitarget-devel@lists.sourceforge.net>");
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/target.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/target.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include "iscsi.h"
+#include "digest.h"
+#include "iscsi_dbg.h"
+
+#define	MAX_NR_TARGETS	(1UL << 30)
+
+static LIST_HEAD(target_list);
+static DECLARE_MUTEX(target_list_sem);
+static u32 next_target_id;
+static u32 nr_targets;
+
+static struct iscsi_sess_param default_session_param = {
+	.initial_r2t = 1,
+	.immediate_data = 1,
+	.max_connections = 1,
+	.max_recv_data_length = 8192,
+	.max_xmit_data_length = 8192,
+	.max_burst_length = 262144,
+	.first_burst_length = 65536,
+	.default_wait_time = 2,
+	.default_retain_time = 20,
+	.max_outstanding_r2t = 1,
+	.data_pdu_inorder = 1,
+	.data_sequence_inorder = 1,
+	.error_recovery_level = 0,
+	.header_digest = DIGEST_NONE,
+	.data_digest = DIGEST_NONE,
+	.ofmarker = 0,
+	.ifmarker = 0,
+	.ofmarkint = 2048,
+	.ifmarkint = 2048,
+};
+
+static struct iscsi_trgt_param default_target_param = {
+	.wthreads = DEFAULT_NR_WTHREADS,
+	.target_type = 0,
+	.queued_cmnds = DEFAULT_NR_QUEUED_CMNDS,
+};
+
+inline int target_lock(struct iscsi_target *target, int interruptible)
+{
+	int err = 0;
+
+	if (interruptible)
+		err = down_interruptible(&target->target_sem);
+	else
+		down(&target->target_sem);
+
+	return err;
+}
+
+inline void target_unlock(struct iscsi_target *target)
+{
+	up(&target->target_sem);
+}
+
+static struct iscsi_target *__target_lookup_by_id(u32 id)
+{
+	struct iscsi_target *target;
+
+	list_for_each_entry(target, &target_list, t_list) {
+		if (target->tid == id)
+			return target;
+	}
+	return NULL;
+}
+
+static struct iscsi_target *__target_lookup_by_name(char *name)
+{
+	struct iscsi_target *target;
+
+	list_for_each_entry(target, &target_list, t_list) {
+		if (!strcmp(target->name, name))
+			return target;
+	}
+	return NULL;
+}
+
+struct iscsi_target *target_lookup_by_id(u32 id)
+{
+	struct iscsi_target *target;
+
+	down(&target_list_sem);
+	target = __target_lookup_by_id(id);
+	up(&target_list_sem);
+
+	return target;
+}
+
+static int target_thread_start(struct iscsi_target *target)
+{
+	int err;
+
+	if ((err = nthread_start(target)) < 0)
+		return err;
+
+	if (!worker_thread_pool) {
+		err = wthread_start(target->wthread_info,
+				    target->trgt_param.wthreads, target->tid);
+		if (err)
+			nthread_stop(target);
+	}
+
+	return err;
+}
+
+static void target_thread_stop(struct iscsi_target *target)
+{
+	if (!worker_thread_pool)
+		wthread_stop(target->wthread_info);
+
+	nthread_stop(target);
+}
+
+static int iscsi_target_create(struct target_info *info, u32 tid)
+{
+	int err = -EINVAL, len;
+	char *name = info->name;
+	struct iscsi_target *target;
+
+	dprintk(D_SETUP, "%u %s\n", tid, name);
+
+	if (!(len = strlen(name))) {
+		eprintk("The length of the target name is zero %u\n", tid);
+		return err;
+	}
+
+	if (!try_module_get(THIS_MODULE)) {
+		eprintk("Fail to get module %u\n", tid);
+		return err;
+	}
+
+	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	if (!target) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (!worker_thread_pool) {
+		target->wthread_info = kmalloc(sizeof(struct worker_thread_info), GFP_KERNEL);
+		if (!target->wthread_info) {
+			err = -ENOMEM;
+			goto out;
+		}
+	}
+
+	target->tid = info->tid = tid;
+
+	memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param));
+	memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param));
+
+	strncpy(target->name, name, sizeof(target->name) - 1);
+
+	init_MUTEX(&target->target_sem);
+	spin_lock_init(&target->session_list_lock);
+
+	INIT_LIST_HEAD(&target->session_list);
+	INIT_LIST_HEAD(&target->volumes);
+
+	atomic_set(&target->nr_volumes, 0);
+
+	nthread_init(target);
+
+	if (!worker_thread_pool)
+		wthread_init(target->wthread_info);
+	else
+		target->wthread_info = worker_thread_pool;
+
+
+	if ((err = target_thread_start(target)) < 0) {
+		target_thread_stop(target);
+		goto out;
+	}
+
+	list_add(&target->t_list, &target_list);
+
+	return 0;
+out:
+	if (!worker_thread_pool)
+		kfree(target->wthread_info);
+	kfree(target);
+	module_put(THIS_MODULE);
+
+	return err;
+}
+
+int target_add(struct target_info *info)
+{
+	int err = -EEXIST;
+	u32 tid = info->tid;
+
+	down(&target_list_sem);
+
+	if (nr_targets > MAX_NR_TARGETS) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (__target_lookup_by_name(info->name))
+		goto out;
+
+	if (tid && __target_lookup_by_id(tid))
+		goto out;
+
+	if (!tid) {
+		do {
+			if (!++next_target_id)
+				++next_target_id;
+		} while (__target_lookup_by_id(next_target_id));
+
+		tid = next_target_id;
+	}
+
+	if (!(err = iscsi_target_create(info, tid)))
+		nr_targets++;
+out:
+	up(&target_list_sem);
+
+	return err;
+}
+
+static void target_destroy(struct iscsi_target *target)
+{
+	dprintk(D_SETUP, "%u\n", target->tid);
+
+	target_thread_stop(target);
+
+	while (!list_empty(&target->volumes)) {
+		struct iet_volume *volume;
+		volume = list_entry(target->volumes.next, struct iet_volume, list);
+		volume->l_state = IDEV_DEL;
+		iscsi_volume_destroy(volume);
+	}
+
+	if (!worker_thread_pool)
+		kfree(target->wthread_info);
+	kfree(target);
+
+	module_put(THIS_MODULE);
+}
+
+/* @locking: target_list_sem must be locked */
+int __target_del(struct iscsi_target *target)
+{
+	target_lock(target, 0);
+
+	if (!list_empty(&target->session_list)) {
+		target_unlock(target);
+		return -EBUSY;
+	}
+
+	list_del(&target->t_list);
+	nr_targets--;
+
+	target_unlock(target);
+	target_destroy(target);
+	return 0;
+}
+
+int target_del(u32 id)
+{
+	struct iscsi_target *target;
+	int err = down_interruptible(&target_list_sem);
+	if (err < 0)
+		return err;
+
+	target = __target_lookup_by_id(id);
+	if (!target) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	err = __target_del(target);
+ out:
+	up(&target_list_sem);
+	return err;
+}
+
+void target_del_all(void)
+{
+	DECLARE_COMPLETION_ONSTACK(done);
+	struct iscsi_target *target, *tmp;
+
+	down(&target_list_sem);
+
+	if (!list_empty(&target_list))
+		iprintk("Removing all connections, sessions and targets\n");
+
+	list_for_each_entry_safe(target, tmp, &target_list, t_list) {
+		init_completion(&done);
+		target->done = &done;
+		session_del_all(target);
+		wait_for_completion(&done);
+		__target_del(target);
+	}
+
+	next_target_id = 0;
+
+	up(&target_list_sem);
+}
+
+static void *iet_seq_start(struct seq_file *m, loff_t *pos)
+{
+	int err;
+
+	/* are you sure this is to be interruptible? */
+	err = down_interruptible(&target_list_sem);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	return seq_list_start(&target_list, *pos);
+}
+
+static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	return seq_list_next(v, &target_list, pos);
+}
+
+static void iet_seq_stop(struct seq_file *m, void *v)
+{
+	up(&target_list_sem);
+}
+
+static int iet_seq_show(struct seq_file *m, void *p)
+{
+	iet_show_info_t *func = (iet_show_info_t *)m->private;
+	struct iscsi_target *target =
+		list_entry(p, struct iscsi_target, t_list);
+	int err;
+
+	/* relly, interruptible?  I'd think target_lock(target, 0)
+	 * would be more appropriate. --lge */
+	err = target_lock(target, 1);
+	if (err < 0)
+		return err;
+
+	seq_printf(m, "tid:%u name:%s\n", target->tid, target->name);
+
+	func(m, target);
+
+	target_unlock(target);
+
+	return 0;
+}
+
+struct seq_operations iet_seq_op = {
+	.start = iet_seq_start,
+	.next = iet_seq_next,
+	.stop = iet_seq_stop,
+	.show = iet_seq_show,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/conn.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/conn.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/file.h>
+#include <linux/ip.h>
+#include <net/tcp.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "digest.h"
+
+static void print_conn_state(char *p, size_t size, unsigned long state)
+{
+	if (test_bit(CONN_ACTIVE, &state))
+		snprintf(p, size, "%s", "active");
+	else if (test_bit(CONN_CLOSING, &state))
+		snprintf(p, size, "%s", "closing");
+	else
+		snprintf(p, size, "%s", "unknown");
+}
+
+static void print_digest_state(char *p, size_t size, unsigned long flags)
+{
+	if (DIGEST_NONE & flags)
+		snprintf(p, size, "%s", "none");
+	else if (DIGEST_CRC32C & flags)
+		snprintf(p, size, "%s", "crc32c");
+	else
+		snprintf(p, size, "%s", "unknown");
+}
+
+void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
+{
+	struct iscsi_conn *conn;
+	struct sock *sk;
+	char buf[64];
+
+	list_for_each_entry(conn, &session->conn_list, list) {
+		sk = conn->sock->sk;
+		switch (sk->sk_family) {
+		case AF_INET:
+			snprintf(buf, sizeof(buf),
+				 "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr));
+			break;
+		case AF_INET6:
+			snprintf(buf, sizeof(buf), "[%pI6]",
+				 &inet6_sk(sk)->daddr);
+			break;
+		default:
+			break;
+		}
+		seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf);
+		print_conn_state(buf, sizeof(buf), conn->state);
+		seq_printf(seq, "state:%s ", buf);
+		print_digest_state(buf, sizeof(buf), conn->hdigest_type);
+		seq_printf(seq, "hd:%s ", buf);
+		print_digest_state(buf, sizeof(buf), conn->ddigest_type);
+		seq_printf(seq, "dd:%s\n", buf);
+	}
+}
+
+struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid)
+{
+	struct iscsi_conn *conn;
+
+	list_for_each_entry(conn, &session->conn_list, list) {
+		if (conn->cid == cid)
+			return conn;
+	}
+	return NULL;
+}
+
+static void iet_state_change(struct sock *sk)
+{
+	struct iscsi_conn *conn = sk->sk_user_data;
+	struct iscsi_target *target = conn->session->target;
+
+	if (sk->sk_state != TCP_ESTABLISHED)
+		conn_close(conn);
+	else
+		nthread_wakeup(target);
+
+	target->nthread_info.old_state_change(sk);
+}
+
+static void iet_data_ready(struct sock *sk, int len)
+{
+	struct iscsi_conn *conn = sk->sk_user_data;
+	struct iscsi_target *target = conn->session->target;
+
+	nthread_wakeup(target);
+	target->nthread_info.old_data_ready(sk, len);
+}
+
+/*
+ * @locking: grabs the target's nthread_lock to protect it from races with
+ * set_conn_wspace_wait()
+ */
+static void iet_write_space(struct sock *sk)
+{
+	struct iscsi_conn *conn = sk->sk_user_data;
+	struct network_thread_info *info = &conn->session->target->nthread_info;
+
+	spin_lock_bh(&info->nthread_lock);
+
+	if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) &&
+	    test_bit(CONN_WSPACE_WAIT, &conn->state)) {
+		clear_bit(CONN_WSPACE_WAIT, &conn->state);
+		__nthread_wakeup(info);
+	}
+
+	spin_unlock_bh(&info->nthread_lock);
+
+	info->old_write_space(sk);
+}
+
+static void iet_socket_bind(struct iscsi_conn *conn)
+{
+	int opt = 1;
+	mm_segment_t oldfs;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_target *target = session->target;
+
+	dprintk(D_GENERIC, "%llu\n", (unsigned long long) session->sid);
+
+	conn->sock = SOCKET_I(conn->file->f_dentry->d_inode);
+	conn->sock->sk->sk_user_data = conn;
+
+	write_lock_bh(&conn->sock->sk->sk_callback_lock);
+	target->nthread_info.old_state_change = conn->sock->sk->sk_state_change;
+	conn->sock->sk->sk_state_change = iet_state_change;
+
+	target->nthread_info.old_data_ready = conn->sock->sk->sk_data_ready;
+	conn->sock->sk->sk_data_ready = iet_data_ready;
+
+	target->nthread_info.old_write_space = conn->sock->sk->sk_write_space;
+	conn->sock->sk->sk_write_space = iet_write_space;
+	write_unlock_bh(&conn->sock->sk->sk_callback_lock);
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt));
+	set_fs(oldfs);
+}
+
+int conn_free(struct iscsi_conn *conn)
+{
+	dprintk(D_GENERIC, "%p %#Lx %u\n", conn->session,
+		(unsigned long long) conn->session->sid, conn->cid);
+
+	assert(atomic_read(&conn->nr_cmnds) == 0);
+	assert(list_empty(&conn->pdu_list));
+	assert(list_empty(&conn->write_list));
+
+	list_del(&conn->list);
+	list_del(&conn->poll_list);
+
+	del_timer_sync(&conn->nop_timer);
+	digest_cleanup(conn);
+	kfree(conn);
+
+	return 0;
+}
+
+static int iet_conn_alloc(struct iscsi_session *session, struct conn_info *info)
+{
+	struct iscsi_conn *conn;
+
+	dprintk(D_SETUP, "%#Lx:%u\n", (unsigned long long) session->sid, info->cid);
+
+	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+	if (!conn)
+		return -ENOMEM;
+
+	conn->session = session;
+	conn->cid = info->cid;
+	conn->stat_sn = info->stat_sn;
+	conn->exp_stat_sn = info->exp_stat_sn;
+
+	conn->hdigest_type = info->header_digest;
+	conn->ddigest_type = info->data_digest;
+	if (digest_init(conn) < 0) {
+		kfree(conn);
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&conn->list_lock);
+	atomic_set(&conn->nr_cmnds, 0);
+	atomic_set(&conn->nr_busy_cmnds, 0);
+	INIT_LIST_HEAD(&conn->pdu_list);
+	INIT_LIST_HEAD(&conn->write_list);
+	INIT_LIST_HEAD(&conn->poll_list);
+	init_timer(&conn->nop_timer);
+
+	list_add(&conn->list, &session->conn_list);
+
+	set_bit(CONN_ACTIVE, &conn->state);
+
+	conn->file = fget(info->fd);
+	iet_socket_bind(conn);
+
+	list_add(&conn->poll_list, &session->target->nthread_info.active_conns);
+
+	nthread_wakeup(conn->session->target);
+
+	return 0;
+}
+
+void conn_close(struct iscsi_conn *conn)
+{
+	if (test_and_clear_bit(CONN_ACTIVE, &conn->state))
+		set_bit(CONN_CLOSING, &conn->state);
+
+	nthread_wakeup(conn->session->target);
+}
+
+int conn_add(struct iscsi_session *session, struct conn_info *info)
+{
+	struct iscsi_conn *conn;
+	int err = -EEXIST;
+
+	conn = conn_lookup(session, info->cid);
+	if (conn)
+		return err;
+
+	return iet_conn_alloc(session, info);
+}
+
+int conn_del(struct iscsi_session *session, struct conn_info *info)
+{
+	struct iscsi_conn *conn;
+	int err = -EEXIST;
+
+	conn = conn_lookup(session, info->cid);
+	if (!conn)
+		return err;
+
+	conn_close(conn);
+
+	return 0;
+}
+
+/* target_lock() supposed to be held */
+void conn_del_all(struct iscsi_session *session)
+{
+	struct iscsi_conn *conn;
+
+	list_for_each_entry(conn, &session->conn_list, list)
+		conn_close(conn);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/ua.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/ua.c
@@ -0,0 +1,164 @@
+/*
+ * IET Unit Attention support
+ *
+ * Copyright (C) 2009 Xie Gang <xiegang112@gmail.com>
+ * Copyright (C) 2009 Arne Redlich <arne.redlich@googlemail.com>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <scsi/scsi.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+
+#define ua_hashfn(lun) ((lun % UA_HASH_LEN))
+
+static struct kmem_cache *ua_cache;
+
+int ua_init(void)
+{
+	ua_cache = KMEM_CACHE(ua_entry, 0);
+	if (!ua_cache) {
+		eprintk("%s", "Failed to create ua cache\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void ua_exit(void)
+{
+	if (ua_cache)
+		kmem_cache_destroy(ua_cache);
+}
+
+/* sess->ua_hash_lock needs to be held */
+static struct ua_entry * ua_find_hash(struct iscsi_session *sess, u32 lun,
+				      u8 asc, u8 ascq, int match)
+{
+	struct ua_entry *ua;
+	struct list_head *h = &sess->ua_hash[ua_hashfn(lun)];
+
+	list_for_each_entry(ua, h, entry) {
+		if (ua->lun == lun) {
+			if (!match)
+				return ua;
+			if (ua->asc == asc && ua->ascq == ascq)
+				return ua;
+		}
+	}
+
+	return NULL;
+}
+
+int ua_pending(struct iscsi_session *sess, u32 lun)
+{
+	struct ua_entry *ua;
+
+	spin_lock(&sess->ua_hash_lock);
+	ua = ua_find_hash(sess, lun, 0, 0, 0);
+	spin_unlock(&sess->ua_hash_lock);
+
+	dprintk_ua(ua, sess, lun);
+
+	return ua ? 1 : 0;
+}
+
+/* sess->ua_hash_lock needs to be held */
+static struct ua_entry * __ua_get_hash(struct iscsi_session *sess, u32 lun,
+				       u8 asc, u8 ascq, int match)
+{
+	struct ua_entry *ua = ua_find_hash(sess, lun, asc, ascq, match);
+
+	if (ua)
+		list_del_init(&ua->entry);
+
+	return ua;
+}
+
+struct ua_entry * ua_get_first(struct iscsi_session *sess, u32 lun)
+{
+	struct ua_entry *ua;
+
+	spin_lock(&sess->ua_hash_lock);
+	ua = __ua_get_hash(sess, lun, 0, 0, 0);
+	spin_unlock(&sess->ua_hash_lock);
+
+	dprintk_ua(ua, sess, lun);
+
+	return ua;
+}
+
+struct ua_entry * ua_get_match(struct iscsi_session *sess, u32 lun,
+			       u8 asc, u8 ascq)
+{
+	struct ua_entry *ua;
+
+	spin_lock(&sess->ua_hash_lock);
+	ua = __ua_get_hash(sess, lun, asc, ascq, 1);
+	spin_unlock(&sess->ua_hash_lock);
+
+	dprintk_ua(ua, sess, lun);
+
+	return ua;
+}
+
+void ua_establish_for_session(struct iscsi_session *sess, u32 lun,
+			      u8 asc, u8 ascq)
+{
+	struct list_head *l = &sess->ua_hash[ua_hashfn(lun)];
+	struct ua_entry *ua = kmem_cache_alloc(ua_cache, GFP_KERNEL);
+
+	if (!ua) {
+		eprintk("%s", "Failed to alloc ua");
+		return;
+	}
+
+	ua->asc = asc;
+	ua->ascq = ascq;
+	ua->lun = lun;
+	ua->session = sess;
+
+	spin_lock(&sess->ua_hash_lock);
+	list_add_tail(&ua->entry, l);
+	spin_unlock(&sess->ua_hash_lock);
+
+	dprintk_ua(ua, sess, lun);
+}
+
+void ua_establish_for_other_sessions(struct iscsi_session *sess, u32 lun,
+				     u8 asc, u8 ascq)
+{
+	struct list_head *l = &sess->target->session_list;
+	struct iscsi_session *s;
+
+	spin_lock(&sess->target->session_list_lock);
+	list_for_each_entry(s, l, list)
+		if (s->sid != sess->sid)
+			ua_establish_for_session(s, lun, asc, ascq);
+	spin_unlock(&sess->target->session_list_lock);
+}
+
+void ua_establish_for_all_sessions(struct iscsi_target *target, u32 lun,
+				   u8 asc, u8 ascq)
+{
+	struct list_head *l = &target->session_list;
+	struct iscsi_session *s;
+
+	spin_lock(&target->session_list_lock);
+	list_for_each_entry(s, l, list)
+		ua_establish_for_session(s, lun, asc, ascq);
+	spin_unlock(&target->session_list_lock);
+
+}
+
+void ua_free(struct ua_entry *ua)
+{
+	if (!ua)
+		return;
+
+	dprintk_ua(ua, ua->session, ua->lun);
+	BUG_ON(!list_empty(&ua->entry));
+	kmem_cache_free(ua_cache, ua);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/Kconfig
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/Kconfig
@@ -0,0 +1,3 @@
+config SCSI_ISCSITARGET
+	tristate "iSCSI Target Driver"
+	depends on SCSI
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/wthread.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/wthread.c
@@ -0,0 +1,222 @@
+/*
+ * Worker thread.
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/kthread.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+
+struct worker_thread_info *worker_thread_pool;
+
+void wthread_queue(struct iscsi_cmnd *cmnd)
+{
+	struct worker_thread_info *info = cmnd->conn->session->target->wthread_info;
+
+	if (!list_empty(&cmnd->list)) {
+		struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);
+		eprintk("%x %p %x %x %x %x %lx %x\n",
+			cmnd_itt(cmnd), req, req->opcode, req->scb[0], cmnd->pdu.datasize,
+			be32_to_cpu(req->data_length), cmnd->flags, req->flags);
+
+		if (cmnd->lun)
+			eprintk("%u\n", cmnd->lun->lun);
+		assert(list_empty(&cmnd->list));
+	}
+
+	spin_lock(&info->wthread_lock);
+	list_add_tail(&cmnd->list, &info->work_queue);
+	spin_unlock(&info->wthread_lock);
+
+	atomic_inc(&cmnd->conn->nr_busy_cmnds);
+
+	wake_up(&info->wthread_sleep);
+}
+
+static struct iscsi_cmnd * get_ready_cmnd(struct worker_thread_info *info)
+{
+	struct iscsi_cmnd *cmnd = NULL;
+
+	spin_lock(&info->wthread_lock);
+	if (!list_empty(&info->work_queue)) {
+		cmnd = list_entry(info->work_queue.next, struct iscsi_cmnd, list);
+		list_del_init(&cmnd->list);
+
+		assert(cmnd->conn);
+	}
+	spin_unlock(&info->wthread_lock);
+
+	return cmnd;
+}
+
+static int cmnd_execute(struct iscsi_cmnd *cmnd)
+{
+	int type = cmnd->conn->session->target->trgt_param.target_type;
+
+	assert(target_type_array[type]->execute_cmnd);
+	return target_type_array[type]->execute_cmnd(cmnd);
+}
+
+static int worker_thread(void *arg)
+{
+	struct worker_thread *wt = (struct worker_thread *) arg;
+	struct worker_thread_info *info = wt->w_info;
+	struct iscsi_cmnd *cmnd;
+	struct iscsi_conn *conn;
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(&info->wthread_sleep, &wait);
+
+	__set_current_state(TASK_RUNNING);
+	do {
+		while (!list_empty(&info->work_queue) &&
+		       (cmnd = get_ready_cmnd(info))) {
+			conn = cmnd->conn;
+			cmnd_execute(cmnd);
+			assert(conn);
+			atomic_dec(&conn->nr_busy_cmnds);
+		}
+
+		__set_current_state(TASK_INTERRUPTIBLE);
+		if (list_empty(&info->work_queue))
+			schedule();
+
+		__set_current_state(TASK_RUNNING);
+	} while (!kthread_should_stop());
+
+	remove_wait_queue(&info->wthread_sleep, &wait);
+
+	return 0;
+}
+
+static int start_one_worker_thread(struct worker_thread_info *info, u32 tid)
+{
+	struct worker_thread *wt;
+	struct task_struct *task;
+
+	if (!(wt = kmalloc(sizeof(struct worker_thread), GFP_KERNEL)))
+		return -ENOMEM;
+
+	wt->w_info = info;
+	task = kthread_create(worker_thread, wt, "istiod%d", tid);
+	if (IS_ERR(task)) {
+		kfree(wt);
+		return PTR_ERR(task);
+	}
+
+	wt->w_task = task;
+	list_add(&wt->w_list, &info->wthread_list);
+	info->nr_running_wthreads++;
+
+	wake_up_process(task);
+
+	return 0;
+}
+
+static int stop_one_worker_thread(struct worker_thread *wt)
+{
+	struct worker_thread_info *info = wt->w_info;
+	int err;
+
+	assert(wt->w_task);
+	err = kthread_stop(wt->w_task);
+
+	if (err < 0 && err != -EINTR)
+		return err;
+
+	list_del(&wt->w_list);
+	kfree(wt);
+	info->nr_running_wthreads--;
+
+	return 0;
+}
+
+int wthread_init(struct worker_thread_info *info)
+{
+	spin_lock_init(&info->wthread_lock);
+
+	info->nr_running_wthreads = 0;
+
+	INIT_LIST_HEAD(&info->work_queue);
+	INIT_LIST_HEAD(&info->wthread_list);
+
+	init_waitqueue_head(&info->wthread_sleep);
+
+	return 0;
+}
+
+int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid)
+{
+	int err = 0;
+
+	while (info->nr_running_wthreads < wthreads) {
+		if ((err = start_one_worker_thread(info, tid)) < 0) {
+			eprintk("Fail to create a worker thread %d\n", err);
+			goto out;
+		}
+	}
+
+	while (info->nr_running_wthreads > wthreads) {
+		struct worker_thread *wt;
+		wt = list_entry(info->wthread_list.next, struct worker_thread, w_list);
+		if ((err = stop_one_worker_thread(wt)) < 0) {
+			eprintk("Fail to stop a worker thread %d\n", err);
+			break;
+		}
+	}
+out:
+	return err;
+}
+
+int wthread_stop(struct worker_thread_info *info)
+{
+	struct worker_thread *wt, *tmp;
+	int err = 0;
+
+	list_for_each_entry_safe(wt, tmp, &info->wthread_list, w_list) {
+		if ((err = stop_one_worker_thread(wt)) < 0) {
+			eprintk("Fail to stop a worker thread %d\n", err);
+			return err;
+		}
+	}
+
+	return err;
+}
+
+int wthread_module_init()
+{
+	int err;
+
+	if (!worker_thread_pool_size)
+		return 0;
+
+	worker_thread_pool = kmalloc(sizeof(struct worker_thread_info),
+				     GFP_KERNEL);
+	if (!worker_thread_pool)
+		return -ENOMEM;
+
+	wthread_init(worker_thread_pool);
+
+	err = wthread_start(worker_thread_pool, worker_thread_pool_size, 0);
+	if (err) {
+		kfree(worker_thread_pool);
+		worker_thread_pool = NULL;
+		return err;
+	}
+
+	iprintk("iscsi_trgt using worker thread pool; size = %ld\n",
+		worker_thread_pool_size);
+
+	return 0;
+}
+
+void wthread_module_exit()
+{
+	if (!worker_thread_pool_size)
+		return;
+
+	wthread_stop(worker_thread_pool);
+	kfree(worker_thread_pool);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/tio.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/tio.c
@@ -0,0 +1,121 @@
+/*
+ * Target I/O.
+ * (C) 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+static int tio_add_pages(struct tio *tio, int count)
+{
+	int i;
+	struct page *page;
+
+	dprintk(D_GENERIC, "%p %d (%d)\n", tio, count, tio->pg_cnt);
+
+	tio->pg_cnt = count;
+
+	count *= sizeof(struct page *);
+
+	do {
+		tio->pvec = kzalloc(count, GFP_KERNEL);
+		if (!tio->pvec)
+			yield();
+	} while (!tio->pvec);
+
+	for (i = 0; i < tio->pg_cnt; i++) {
+		do {
+			if (!(page = alloc_page(GFP_KERNEL)))
+				yield();
+		} while (!page);
+		tio->pvec[i] = page;
+	}
+	return 0;
+}
+
+static struct kmem_cache *tio_cache;
+
+struct tio *tio_alloc(int count)
+{
+	struct tio *tio;
+
+	tio = kmem_cache_alloc(tio_cache, GFP_KERNEL | __GFP_NOFAIL);
+
+	tio->pg_cnt = 0;
+	tio->idx = 0;
+	tio->offset = 0;
+	tio->size = 0;
+	tio->pvec = NULL;
+
+	atomic_set(&tio->count, 1);
+
+	if (count)
+		tio_add_pages(tio, count);
+
+	return tio;
+}
+
+static void tio_free(struct tio *tio)
+{
+	int i;
+	for (i = 0; i < tio->pg_cnt; i++) {
+		assert(tio->pvec[i]);
+		__free_page(tio->pvec[i]);
+	}
+	kfree(tio->pvec);
+	kmem_cache_free(tio_cache, tio);
+}
+
+void tio_put(struct tio *tio)
+{
+	assert(atomic_read(&tio->count));
+	if (atomic_dec_and_test(&tio->count))
+		tio_free(tio);
+}
+
+void tio_get(struct tio *tio)
+{
+	atomic_inc(&tio->count);
+}
+
+void tio_set(struct tio *tio, u32 size, loff_t offset)
+{
+	tio->idx = offset >> PAGE_CACHE_SHIFT;
+	tio->offset = offset & ~PAGE_CACHE_MASK;
+	tio->size = size;
+}
+
+int tio_read(struct iet_volume *lu, struct tio *tio)
+{
+	struct iotype *iot = lu->iotype;
+	assert(iot);
+	return iot->make_request ? iot->make_request(lu, tio, READ) : 0;
+}
+
+int tio_write(struct iet_volume *lu, struct tio *tio)
+{
+	struct iotype *iot = lu->iotype;
+	assert(iot);
+	return iot->make_request ? iot->make_request(lu, tio, WRITE) : 0;
+}
+
+int tio_sync(struct iet_volume *lu, struct tio *tio)
+{
+	struct iotype *iot = lu->iotype;
+	assert(iot);
+	return iot->sync ? iot->sync(lu, tio) : 0;
+}
+
+int tio_init(void)
+{
+	tio_cache = KMEM_CACHE(tio, 0);
+	return  tio_cache ? 0 : -ENOMEM;
+}
+
+void tio_exit(void)
+{
+	if (tio_cache)
+		kmem_cache_destroy(tio_cache);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/volume.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/volume.c
@@ -0,0 +1,264 @@
+/*
+ * Volume manager
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/types.h>
+#include <linux/parser.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun)
+{
+	struct iet_volume *volume;
+
+	list_for_each_entry(volume, &target->volumes, list) {
+		if (volume->lun == lun)
+			return volume;
+	}
+	return NULL;
+}
+
+enum {
+	Opt_type,
+	Opt_iomode,
+	Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_type, "Type=%s"},
+	{Opt_iomode, "IOMode=%s"},
+	{Opt_err, NULL},
+};
+
+static int set_iotype(struct iet_volume *volume, char *params)
+{
+	int err = 0;
+	substring_t args[MAX_OPT_ARGS];
+	char *p, *argp = NULL, *buf = (char *) get_zeroed_page(GFP_USER);
+
+	if (!buf)
+		return -ENOMEM;
+	strncpy(buf, params, PAGE_CACHE_SIZE);
+
+	while ((p = strsep(&buf, ",")) != NULL) {
+		int token;
+
+		if (!*p)
+			continue;
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_type:
+			if (!(argp = match_strdup(&args[0])))
+				err = -ENOMEM;
+			if (argp && !(volume->iotype = get_iotype(argp)))
+				err = -ENOENT;
+			kfree(argp);
+			break;
+		case Opt_iomode:
+			if (!(argp = match_strdup(&args[0])))
+				err = -ENOMEM;
+			if (argp && !strcmp(argp, "ro"))
+				SetLUReadonly(volume);
+			else if (argp && !strcmp(argp, "wb"))
+				SetLUWCache(volume);
+			kfree(argp);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!err && !volume->iotype && !(volume->iotype = get_iotype("fileio"))) {
+		eprintk("%s\n", "Cannot find fileio");
+		err = -EINVAL;
+	}
+
+	free_page((unsigned long) buf);
+
+	return err;
+}
+
+int volume_add(struct iscsi_target *target, struct volume_info *info)
+{
+	int ret;
+	struct iet_volume *volume;
+	char *args;
+
+	volume = volume_lookup(target, info->lun);
+	if (volume)
+		return -EEXIST;
+
+	if (info->lun > 0x3fff)
+		return -EINVAL;
+
+	volume = kzalloc(sizeof(*volume), GFP_KERNEL);
+	if (!volume)
+		return -ENOMEM;
+
+	volume->target = target;
+	volume->lun = info->lun;
+
+	args = kzalloc(info->args_len + 1, GFP_KERNEL);
+	if (!args) {
+		ret = -ENOMEM;
+		goto free_volume;
+	}
+
+	ret = copy_from_user(args, (void *)(unsigned long)info->args_ptr,
+			     info->args_len);
+	if (ret) {
+		ret = -EFAULT;
+		goto free_args;
+	}
+
+	ret = set_iotype(volume, args);
+	if (ret < 0)
+		goto free_args;
+
+	ret = volume->iotype->attach(volume, args);
+	if (ret < 0)
+		goto free_args;
+
+	INIT_LIST_HEAD(&volume->queue.wait_list);
+	spin_lock_init(&volume->queue.queue_lock);
+	spin_lock_init(&volume->reserve_lock);
+
+	volume->l_state = IDEV_RUNNING;
+	atomic_set(&volume->l_count, 0);
+
+	list_add_tail(&volume->list, &target->volumes);
+	atomic_inc(&target->nr_volumes);
+
+	kfree(args);
+
+	return 0;
+free_args:
+	kfree(args);
+free_volume:
+	put_iotype(volume->iotype);
+	kfree(volume);
+
+	return ret;
+}
+
+void iscsi_volume_destroy(struct iet_volume *volume)
+{
+	assert(volume->l_state == IDEV_DEL);
+	assert(!atomic_read(&volume->l_count));
+
+	volume->iotype->detach(volume);
+	put_iotype(volume->iotype);
+	list_del(&volume->list);
+	kfree(volume);
+}
+
+int iscsi_volume_del(struct iscsi_target *target, struct volume_info *info)
+{
+	struct iet_volume *volume;
+
+	eprintk("%x %x\n", target->tid, info->lun);
+	if (!(volume = volume_lookup(target, info->lun)))
+		return -ENOENT;
+
+	volume->l_state = IDEV_DEL;
+	atomic_dec(&target->nr_volumes);
+	if (!atomic_read(&volume->l_count))
+		iscsi_volume_destroy(volume);
+
+	return 0;
+}
+
+struct iet_volume *volume_get(struct iscsi_target *target, u32 lun)
+{
+	struct iet_volume *volume;
+
+	if ((volume = volume_lookup(target, lun))) {
+		if (volume->l_state == IDEV_RUNNING)
+			atomic_inc(&volume->l_count);
+		else
+			volume = NULL;
+	}
+	return volume;
+}
+
+void volume_put(struct iet_volume *volume)
+{
+	if (atomic_dec_and_test(&volume->l_count) && volume->l_state == IDEV_DEL)
+		iscsi_volume_destroy(volume);
+}
+
+int volume_reserve(struct iet_volume *volume, u64 sid)
+{
+	if (!volume)
+		return -ENOENT;
+
+	spin_lock(&volume->reserve_lock);
+	if (volume->reserve_sid && volume->reserve_sid != sid) {
+		spin_unlock(&volume->reserve_lock);
+		return -EBUSY;
+	}
+
+	volume->reserve_sid = sid;
+	spin_unlock(&volume->reserve_lock);
+
+	return 0;
+}
+
+int is_volume_reserved(struct iet_volume *volume, u64 sid)
+{
+	if (!volume || !volume->reserve_sid || volume->reserve_sid == sid)
+		return 0;
+
+	return -EBUSY;
+}
+
+int volume_release(struct iet_volume *volume, u64 sid, int force)
+{
+	if (force || volume->reserve_sid == sid)
+		volume->reserve_sid = 0;
+
+	return 0;
+}
+
+static void iet_volume_info_show(struct seq_file *seq, struct iscsi_target *target)
+{
+	struct iet_volume *volume;
+
+	list_for_each_entry(volume, &target->volumes, list) {
+		seq_printf(seq, "\tlun:%u state:%x iotype:%s",
+			   volume->lun, volume->l_state, volume->iotype->name);
+		if (LUReadonly(volume))
+			seq_printf(seq, " iomode:ro");
+		else if (LUWCache(volume))
+			seq_printf(seq, " iomode:wb");
+		else
+			seq_printf(seq, " iomode:wt");
+
+		if (volume->iotype->show)
+			volume->iotype->show(volume, seq);
+		else
+			seq_printf(seq, "\n");
+	}
+}
+
+static int iet_volume_seq_open(struct inode *inode, struct file *file)
+{
+	int res;
+	res = seq_open(file, &iet_seq_op);
+	if (!res)
+		((struct seq_file *)file->private_data)->private =
+			iet_volume_info_show;
+	return res;
+}
+
+struct file_operations volume_seq_fops = {
+	.owner		= THIS_MODULE,
+	.open		= iet_volume_seq_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/param.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/param.c
@@ -0,0 +1,205 @@
+/*
+ * (C) 2005 FUJITA Tomonori <tomof@acm.org>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "digest.h"
+
+struct target_type *target_type_array[] = {
+	&disk_ops,
+};
+
+#define	CHECK_PARAM(info, iparam, word, min, max)			\
+do {									\
+	if (!info->partial || (info->partial & 1 << key_##word))	\
+		if (iparam[key_##word] < min ||				\
+			iparam[key_##word] > max) {			\
+			eprintk("%s: %u is out of range (%u %u)\n",	\
+				#word, iparam[key_##word], min, max);	\
+			iparam[key_##word] = min;			\
+		}							\
+} while (0)
+
+#define	SET_PARAM(param, info, iparam, word)				\
+({									\
+	int changed = 0;						\
+	if (!info->partial || (info->partial & 1 << key_##word)) {	\
+		if (param->word != iparam[key_##word])			\
+			changed = 1;					\
+		param->word = iparam[key_##word];			\
+	}								\
+	changed;							\
+})
+
+#define	GET_PARAM(param, info, iparam, word)				\
+do {									\
+	iparam[key_##word] = param->word;				\
+} while (0)
+
+static void sess_param_check(struct iscsi_param_info *info)
+{
+	u32 *iparam = info->session_param;
+
+	CHECK_PARAM(info, iparam, max_connections, 1, 1);
+	CHECK_PARAM(info, iparam, max_recv_data_length, 512,
+		    (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE));
+	CHECK_PARAM(info, iparam, max_xmit_data_length, 512,
+		    (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE));
+	CHECK_PARAM(info, iparam, error_recovery_level, 0, 0);
+	CHECK_PARAM(info, iparam, data_pdu_inorder, 1, 1);
+	CHECK_PARAM(info, iparam, data_sequence_inorder, 1, 1);
+
+	digest_alg_available(&iparam[key_header_digest]);
+	digest_alg_available(&iparam[key_data_digest]);
+
+	CHECK_PARAM(info, iparam, ofmarker, 0, 0);
+	CHECK_PARAM(info, iparam, ifmarker, 0, 0);
+}
+
+static void sess_param_set(struct iscsi_sess_param *param, struct iscsi_param_info *info)
+{
+	u32 *iparam = info->session_param;
+
+	SET_PARAM(param, info, iparam, initial_r2t);
+	SET_PARAM(param, info, iparam, immediate_data);
+	SET_PARAM(param, info, iparam, max_connections);
+	SET_PARAM(param, info, iparam, max_recv_data_length);
+	SET_PARAM(param, info, iparam, max_xmit_data_length);
+	SET_PARAM(param, info, iparam, max_burst_length);
+	SET_PARAM(param, info, iparam, first_burst_length);
+	SET_PARAM(param, info, iparam, default_wait_time);
+	SET_PARAM(param, info, iparam, default_retain_time);
+	SET_PARAM(param, info, iparam, max_outstanding_r2t);
+	SET_PARAM(param, info, iparam, data_pdu_inorder);
+	SET_PARAM(param, info, iparam, data_sequence_inorder);
+	SET_PARAM(param, info, iparam, error_recovery_level);
+	SET_PARAM(param, info, iparam, header_digest);
+	SET_PARAM(param, info, iparam, data_digest);
+	SET_PARAM(param, info, iparam, ofmarker);
+	SET_PARAM(param, info, iparam, ifmarker);
+	SET_PARAM(param, info, iparam, ofmarkint);
+	SET_PARAM(param, info, iparam, ifmarkint);
+}
+
+static void sess_param_get(struct iscsi_sess_param *param, struct iscsi_param_info *info)
+{
+	u32 *iparam = info->session_param;
+
+	GET_PARAM(param, info, iparam, initial_r2t);
+	GET_PARAM(param, info, iparam, immediate_data);
+	GET_PARAM(param, info, iparam, max_connections);
+	GET_PARAM(param, info, iparam, max_recv_data_length);
+	GET_PARAM(param, info, iparam, max_xmit_data_length);
+	GET_PARAM(param, info, iparam, max_burst_length);
+	GET_PARAM(param, info, iparam, first_burst_length);
+	GET_PARAM(param, info, iparam, default_wait_time);
+	GET_PARAM(param, info, iparam, default_retain_time);
+	GET_PARAM(param, info, iparam, max_outstanding_r2t);
+	GET_PARAM(param, info, iparam, data_pdu_inorder);
+	GET_PARAM(param, info, iparam, data_sequence_inorder);
+	GET_PARAM(param, info, iparam, error_recovery_level);
+	GET_PARAM(param, info, iparam, header_digest);
+	GET_PARAM(param, info, iparam, data_digest);
+	GET_PARAM(param, info, iparam, ofmarker);
+	GET_PARAM(param, info, iparam, ifmarker);
+	GET_PARAM(param, info, iparam, ofmarkint);
+	GET_PARAM(param, info, iparam, ifmarkint);
+}
+
+static void trgt_param_check(struct iscsi_param_info *info)
+{
+	u32 *iparam = info->target_param;
+
+	CHECK_PARAM(info, iparam, wthreads, MIN_NR_WTHREADS, MAX_NR_WTHREADS);
+	CHECK_PARAM(info, iparam, target_type, 0,
+		    (unsigned int) ARRAY_SIZE(target_type_array) - 1);
+	CHECK_PARAM(info, iparam, queued_cmnds, MIN_NR_QUEUED_CMNDS,
+		    MAX_NR_QUEUED_CMNDS);
+	CHECK_PARAM(info, iparam, nop_interval, MIN_NOP_INTERVAL,
+		    MAX_NOP_INTERVAL);
+	CHECK_PARAM(info, iparam, nop_timeout, MIN_NOP_TIMEOUT,
+		    MAX_NOP_TIMEOUT);
+}
+
+static void trgt_param_set(struct iscsi_target *target, struct iscsi_param_info *info)
+{
+	struct iscsi_trgt_param *param = &target->trgt_param;
+	u32 *iparam = info->target_param;
+
+	if (!worker_thread_pool &&
+	    SET_PARAM(param, info, iparam, wthreads))
+		wthread_start(target->wthread_info,
+			      target->trgt_param.wthreads, target->tid);
+	SET_PARAM(param, info, iparam, target_type);
+	SET_PARAM(param, info, iparam, queued_cmnds);
+	SET_PARAM(param, info, iparam, nop_interval);
+	SET_PARAM(param, info, iparam, nop_timeout);
+}
+
+static void trgt_param_get(struct iscsi_trgt_param *param, struct iscsi_param_info *info)
+{
+	u32 *iparam = info->target_param;
+
+	GET_PARAM(param, info, iparam, wthreads);
+	GET_PARAM(param, info, iparam, target_type);
+	GET_PARAM(param, info, iparam, queued_cmnds);
+	GET_PARAM(param, info, iparam, nop_interval);
+	GET_PARAM(param, info, iparam, nop_timeout);
+}
+
+static int trgt_param(struct iscsi_target *target, struct iscsi_param_info *info, int set)
+{
+
+	if (set) {
+		trgt_param_check(info);
+		trgt_param_set(target, info);
+	} else
+		trgt_param_get(&target->trgt_param, info);
+
+	return 0;
+}
+
+static int sess_param(struct iscsi_target *target, struct iscsi_param_info *info, int set)
+{
+	struct iscsi_session *session = NULL;
+	struct iscsi_sess_param *param;
+	int err = -ENOENT;
+
+	if (set)
+		sess_param_check(info);
+
+	if (info->sid) {
+		if (!(session = session_lookup(target, info->sid)))
+			goto out;
+		param = &session->param;
+	} else {
+		param = &target->sess_param;
+	}
+
+	if (set) {
+		sess_param_set(param, info);
+		show_param(param);
+	} else
+		sess_param_get(param, info);
+
+	err = 0;
+out:
+	return err;
+}
+
+int iscsi_param_set(struct iscsi_target *target, struct iscsi_param_info *info, int set)
+{
+	int err;
+
+	if (info->param_type == key_session)
+		err = sess_param(target, info, set);
+	else if (info->param_type == key_target)
+		err = trgt_param(target, info, set);
+	else
+		err = -EINVAL;
+
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/file-io.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/file-io.c
@@ -0,0 +1,324 @@
+/*
+ * Target device file I/O.
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/parser.h>
+#include <linux/writeback.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+struct fileio_data {
+	char *path;
+	struct file *filp;
+};
+
+static int fileio_make_request(struct iet_volume *lu, struct tio *tio, int rw)
+{
+	struct fileio_data *p = lu->private;
+	struct file *filp;
+	mm_segment_t oldfs;
+	struct page *page;
+	u32 offset, size;
+	loff_t ppos, count;
+	char *buf;
+	int i, err = 0;
+	ssize_t ret;
+
+	assert(p);
+	filp = p->filp;
+	size = tio->size;
+	offset= tio->offset;
+
+	ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT;
+	ppos += offset;
+
+	for (i = 0; i < tio->pg_cnt; i++) {
+		page = tio->pvec[i];
+		assert(page);
+		buf = page_address(page);
+		buf += offset;
+
+		if (offset + size > PAGE_CACHE_SIZE)
+			count = PAGE_CACHE_SIZE - offset;
+		else
+			count = size;
+
+		oldfs = get_fs();
+		set_fs(get_ds());
+
+		if (rw == READ)
+			ret = do_sync_read(filp, buf, count, &ppos);
+		else
+			ret = do_sync_write(filp, buf, count, &ppos);
+
+		set_fs(oldfs);
+
+		if (ret != count) {
+			eprintk("I/O error %lld, %ld\n", count, (long) ret);
+			err = -EIO;
+		}
+
+		size -= count;
+		offset = 0;
+	}
+	assert(!size);
+
+	return err;
+}
+
+static int fileio_sync(struct iet_volume *lu, struct tio *tio)
+{
+	struct fileio_data *p = lu->private;
+	struct inode *inode = p->filp->f_dentry->d_inode;
+	struct address_space *mapping = inode->i_mapping;
+	loff_t ppos, count;
+	int res;
+
+	if (tio) {
+		ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT;
+		count = tio->size;
+	} else {
+		ppos = 0;
+		count = lu->blk_cnt << lu->blk_shift;
+	}
+
+	res = filemap_write_and_wait_range(mapping, ppos, ppos + count - 1);
+	if (res) {
+		eprintk("I/O error: syncing pages failed: %d\n", res);
+		return -EIO;
+	} else
+		return 0;
+}
+
+static int open_path(struct iet_volume *volume, const char *path)
+{
+	int err = 0;
+	struct fileio_data *info = volume->private;
+	struct file *filp;
+	mm_segment_t oldfs;
+	int flags;
+
+	info->path = kstrdup(path, GFP_KERNEL);
+	if (!info->path)
+		return -ENOMEM;
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	flags = (LUReadonly(volume) ? O_RDONLY : O_RDWR) | O_LARGEFILE;
+	filp = filp_open(path, flags, 0);
+	set_fs(oldfs);
+
+	if (IS_ERR(filp)) {
+		err = PTR_ERR(filp);
+		eprintk("Can't open %s %d\n", path, err);
+		info->filp = NULL;
+	} else
+		info->filp = filp;
+
+	return err;
+}
+
+static int set_scsiid(struct iet_volume *volume, const char *id)
+{
+	size_t len;
+
+	if ((len = strlen(id)) > SCSI_ID_LEN - VENDOR_ID_LEN) {
+		eprintk("SCSI ID too long, %zd provided, %u max\n", len,
+			SCSI_ID_LEN - VENDOR_ID_LEN);
+		return -EINVAL;
+	}
+
+	memcpy(volume->scsi_id + VENDOR_ID_LEN, id, len);
+
+	return 0;
+}
+
+static void gen_scsiid(struct iet_volume *volume, struct inode *inode)
+{
+	int i;
+	u32 *p;
+
+	strlcpy(volume->scsi_id, VENDOR_ID, VENDOR_ID_LEN);
+
+	for (i = VENDOR_ID_LEN; i < SCSI_ID_LEN; i++)
+		if (volume->scsi_id[i])
+			return;
+
+	p = (u32 *) (volume->scsi_id + VENDOR_ID_LEN);
+	*(p + 0) = volume->target->trgt_param.target_type;
+	*(p + 1) = volume->target->tid;
+	*(p + 2) = (unsigned int) inode->i_ino;
+	*(p + 3) = (unsigned int) inode->i_sb->s_dev;
+}
+
+static int set_scsisn(struct iet_volume *volume, const char *sn)
+{
+	size_t len;
+
+	if ((len = strlen(sn)) > SCSI_SN_LEN) {
+		eprintk("SCSI SN too long, %zd provided, %u max\n", len,
+			SCSI_SN_LEN);
+		return -EINVAL;
+	}
+	memcpy(volume->scsi_sn, sn, len);
+	return 0;
+}
+
+enum {
+	Opt_scsiid, Opt_scsisn, Opt_path, Opt_ignore, Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_scsiid, "ScsiId=%s"},
+	{Opt_scsisn, "ScsiSN=%s"},
+	{Opt_path, "Path=%s"},
+	{Opt_ignore, "Type=%s"},
+	{Opt_ignore, "IOMode=%s"},
+	{Opt_err, NULL},
+};
+
+static int parse_fileio_params(struct iet_volume *volume, char *params)
+{
+	struct fileio_data *info = volume->private;
+	int err = 0;
+	char *p, *q;
+
+	while ((p = strsep(&params, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+		if (!*p)
+			continue;
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_scsiid:
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = set_scsiid(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_scsisn:
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = set_scsisn(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_path:
+			if (info->path) {
+				iprintk("Target %s, LUN %u: "
+					"duplicate \"Path\" param\n",
+					volume->target->name, volume->lun);
+				err = -EINVAL;
+				goto out;
+			}
+			if (!(q = match_strdup(&args[0]))) {
+				err = -ENOMEM;
+				goto out;
+			}
+			err = open_path(volume, q);
+			kfree(q);
+			if (err < 0)
+				goto out;
+			break;
+		case Opt_ignore:
+			break;
+		default:
+			iprintk("Target %s, LUN %u: unknown param %s\n",
+				volume->target->name, volume->lun, p);
+			return -EINVAL;
+		}
+	}
+
+	if (!info->path) {
+		iprintk("Target %s, LUN %u: missing \"Path\" param\n",
+			volume->target->name, volume->lun);
+		err = -EINVAL;
+	}
+out:
+	return err;
+}
+
+static void fileio_detach(struct iet_volume *lu)
+{
+	struct fileio_data *p = lu->private;
+
+	kfree(p->path);
+	if (p->filp)
+		filp_close(p->filp, NULL);
+	kfree(p);
+	lu->private = NULL;
+}
+
+static int fileio_attach(struct iet_volume *lu, char *args)
+{
+	int err = 0;
+	struct fileio_data *p;
+	struct inode *inode;
+
+	if (lu->private) {
+		printk("already attached ? %d\n", lu->lun);
+		return -EBUSY;
+	}
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	lu->private = p;
+
+	if ((err = parse_fileio_params(lu, args)) < 0) {
+		eprintk("%d\n", err);
+		goto out;
+	}
+	inode = p->filp->f_dentry->d_inode;
+
+	gen_scsiid(lu, inode);
+
+	if (S_ISREG(inode->i_mode))
+		;
+	else if (S_ISBLK(inode->i_mode))
+		inode = inode->i_bdev->bd_inode;
+	else {
+		err = -EINVAL;
+		goto out;
+	}
+
+	lu->blk_shift = SECTOR_SIZE_BITS;
+	lu->blk_cnt = inode->i_size >> lu->blk_shift;
+
+	/* we're using the page cache */
+	SetLURCache(lu);
+out:
+	if (err < 0)
+		fileio_detach(lu);
+	return err;
+}
+
+static void fileio_show(struct iet_volume *lu, struct seq_file *seq)
+{
+	struct fileio_data *p = lu->private;
+	seq_printf(seq, " path:%s\n", p->path);
+}
+
+struct iotype fileio =
+{
+	.name = "fileio",
+	.attach = fileio_attach,
+	.make_request = fileio_make_request,
+	.sync = fileio_sync,
+	.detach = fileio_detach,
+	.show = fileio_show,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iscsi_hdr.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iscsi_hdr.h
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef __ISCSI_HDR_H__
+#define __ISCSI_HDR_H__
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#define ISCSI_VERSION			0
+
+#ifndef __packed
+#define __packed __attribute__ ((packed))
+#endif
+
+struct iscsi_hdr {
+	u8  opcode;			/* 0 */
+	u8  flags;
+	u8  spec1[2];
+#if defined(__BIG_ENDIAN_BITFIELD)
+	struct {			/* 4 */
+		unsigned ahslength : 8;
+		unsigned datalength : 24;
+	} length;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	u32 length;			/* 4 */
+#endif
+	u16 lun[4];			/* 8 */
+	u32 itt;			/* 16 */
+	u32 ttt;			/* 20 */
+	u32 sn;				/* 24 */
+	u32 exp_sn;			/* 28 */
+	u32 max_sn;			/* 32 */
+	u32 spec3[3];			/* 36 */
+} __packed;				/* 48 */
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY			0x80
+#define ISCSI_OP_IMMEDIATE		0x40
+#define ISCSI_OPCODE_MASK		0x3F
+
+/* Client to Server Message Opcode values */
+#define ISCSI_OP_NOP_OUT		0x00
+#define ISCSI_OP_SCSI_CMD		0x01
+#define ISCSI_OP_SCSI_TASK_MGT_MSG	0x02
+#define ISCSI_OP_LOGIN_CMD		0x03
+#define ISCSI_OP_TEXT_CMD		0x04
+#define ISCSI_OP_SCSI_DATA_OUT		0x05
+#define ISCSI_OP_LOGOUT_CMD		0x06
+#define ISCSI_OP_SNACK_CMD		0x10
+
+#define ISCSI_OP_VENDOR1_CMD		0x1c
+#define ISCSI_OP_VENDOR2_CMD		0x1d
+#define ISCSI_OP_VENDOR3_CMD		0x1e
+#define ISCSI_OP_VENDOR4_CMD		0x1f
+
+/* Server to Client Message Opcode values */
+#define ISCSI_OP_NOP_IN 		0x20
+#define ISCSI_OP_SCSI_RSP		0x21
+#define ISCSI_OP_SCSI_TASK_MGT_RSP	0x22
+#define ISCSI_OP_LOGIN_RSP		0x23
+#define ISCSI_OP_TEXT_RSP		0x24
+#define ISCSI_OP_SCSI_DATA_IN		0x25
+#define ISCSI_OP_LOGOUT_RSP		0x26
+#define ISCSI_OP_R2T			0x31
+#define ISCSI_OP_ASYNC_MSG		0x32
+#define ISCSI_OP_REJECT			0x3f
+
+struct iscsi_ahs_hdr {
+	u16 ahslength;
+	u8 ahstype;
+} __packed;
+
+#define ISCSI_AHSTYPE_CDB		1
+#define ISCSI_AHSTYPE_RLENGTH		2
+
+union iscsi_sid {
+	struct {
+		u8 isid[6];		/* Initiator Session ID */
+		u16 tsih;		/* Target Session ID */
+	} id;
+	u64 id64;
+} __packed;
+
+struct iscsi_scsi_cmd_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 data_length;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u8  scb[16];
+} __packed;
+
+#define ISCSI_CMD_FINAL		0x80
+#define ISCSI_CMD_READ		0x40
+#define ISCSI_CMD_WRITE		0x20
+#define ISCSI_CMD_ATTR_MASK	0x07
+#define ISCSI_CMD_UNTAGGED	0x00
+#define ISCSI_CMD_SIMPLE	0x01
+#define ISCSI_CMD_ORDERED	0x02
+#define ISCSI_CMD_HEAD_OF_QUEUE	0x03
+#define ISCSI_CMD_ACA		0x04
+
+struct iscsi_cdb_ahdr {
+	u16 ahslength;
+	u8  ahstype;
+	u8  reserved;
+	u8  cdb[0];
+} __packed;
+
+struct iscsi_rlength_ahdr {
+	u16 ahslength;
+	u8  ahstype;
+	u8  reserved;
+	u32 read_length;
+} __packed;
+
+struct iscsi_scsi_rsp_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  response;
+	u8  cmd_status;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd1[2];
+	u32 itt;
+	u32 snack;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 exp_data_sn;
+	u32 bi_residual_count;
+	u32 residual_count;
+} __packed;
+
+#define ISCSI_FLG_RESIDUAL_UNDERFLOW		0x02
+#define ISCSI_FLG_RESIDUAL_OVERFLOW		0x04
+#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW		0x08
+#define ISCSI_FLG_BIRESIDUAL_OVERFLOW		0x10
+
+#define ISCSI_RESPONSE_COMMAND_COMPLETED	0x00
+#define ISCSI_RESPONSE_TARGET_FAILURE		0x01
+
+struct iscsi_sense_data {
+	u16 length;
+	u8  data[0];
+} __packed;
+
+struct iscsi_task_mgt_hdr {
+	u8  opcode;
+	u8  function;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 rtt;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 ref_cmd_sn;
+	u32 exp_data_sn;
+	u32 rsvd2[2];
+} __packed;
+
+#define ISCSI_FUNCTION_MASK			0x7f
+
+#define ISCSI_FUNCTION_ABORT_TASK		1
+#define ISCSI_FUNCTION_ABORT_TASK_SET		2
+#define ISCSI_FUNCTION_CLEAR_ACA		3
+#define ISCSI_FUNCTION_CLEAR_TASK_SET		4
+#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET	5
+#define ISCSI_FUNCTION_TARGET_WARM_RESET	6
+#define ISCSI_FUNCTION_TARGET_COLD_RESET	7
+#define ISCSI_FUNCTION_TASK_REASSIGN		8
+
+struct iscsi_task_rsp_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  response;
+	u8  rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 rsvd3;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 rsvd4[3];
+} __packed;
+
+#define ISCSI_RESPONSE_FUNCTION_COMPLETE	0
+#define ISCSI_RESPONSE_UNKNOWN_TASK		1
+#define ISCSI_RESPONSE_UNKNOWN_LUN		2
+#define ISCSI_RESPONSE_TASK_ALLEGIANT		3
+#define ISCSI_RESPONSE_FAILOVER_UNSUPPORTED	4
+#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED	5
+#define ISCSI_RESPONSE_NO_AUTHORIZATION		6
+#define ISCSI_RESPONSE_FUNCTION_REJECTED	255
+
+struct iscsi_data_out_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 ttt;
+	u32 rsvd2;
+	u32 exp_stat_sn;
+	u32 rsvd3;
+	u32 data_sn;
+	u32 buffer_offset;
+	u32 rsvd4;
+} __packed;
+
+struct iscsi_data_in_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  rsvd1;
+	u8  cmd_status;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 ttt;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 data_sn;
+	u32 buffer_offset;
+	u32 residual_count;
+} __packed;
+
+#define ISCSI_FLG_STATUS		0x01
+
+struct iscsi_r2t_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 ttt;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 r2t_sn;
+	u32 buffer_offset;
+	u32 data_length;
+} __packed;
+
+struct iscsi_async_msg_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 ffffffff;
+	u32 rsvd2;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u8  async_event;
+	u8  async_vcode;
+	u16 param1;
+	u16 param2;
+	u16 param3;
+	u32 rsvd3;
+} __packed;
+
+#define ISCSI_ASYNC_SCSI		0
+#define ISCSI_ASYNC_LOGOUT		1
+#define ISCSI_ASYNC_DROP_CONNECTION	2
+#define ISCSI_ASYNC_DROP_SESSION	3
+#define ISCSI_ASYNC_PARAM_REQUEST	4
+#define ISCSI_ASYNC_VENDOR		255
+
+struct iscsi_text_req_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 ttt;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsvd3[4];
+} __packed;
+
+struct iscsi_text_rsp_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 ttt;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 rsvd3[3];
+} __packed;
+
+struct iscsi_login_req_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  max_version;		/* Max. version supported */
+	u8  min_version;		/* Min. version supported */
+	u8  ahslength;
+	u8  datalength[3];
+	union iscsi_sid sid;
+	u32 itt;			/* Initiator Task Tag */
+	u16 cid;			/* Connection ID */
+	u16 rsvd1;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsvd2[4];
+} __packed;
+
+struct iscsi_login_rsp_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  max_version;		/* Max. version supported */
+	u8  active_version;		/* Active version */
+	u8  ahslength;
+	u8  datalength[3];
+	union iscsi_sid sid;
+	u32 itt;			/* Initiator Task Tag */
+	u32 rsvd1;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u8  status_class;		/* see Login RSP ststus classes below */
+	u8  status_detail;		/* see Login RSP Status details below */
+	u8  rsvd2[10];
+} __packed;
+
+#define ISCSI_FLG_FINAL			0x80
+#define ISCSI_FLG_TRANSIT		0x80
+#define ISCSI_FLG_CSG_SECURITY		0x00
+#define ISCSI_FLG_CSG_LOGIN		0x04
+#define ISCSI_FLG_CSG_FULL_FEATURE	0x0c
+#define ISCSI_FLG_CSG_MASK		0x0c
+#define ISCSI_FLG_NSG_SECURITY		0x00
+#define ISCSI_FLG_NSG_LOGIN		0x01
+#define ISCSI_FLG_NSG_FULL_FEATURE	0x03
+#define ISCSI_FLG_NSG_MASK		0x03
+
+/* Login Status response classes */
+#define ISCSI_STATUS_SUCCESS		0x00
+#define ISCSI_STATUS_REDIRECT		0x01
+#define ISCSI_STATUS_INITIATOR_ERR	0x02
+#define ISCSI_STATUS_TARGET_ERR		0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_STATUS_ACCEPT		0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_STATUS_TGT_MOVED_TEMP	0x01
+#define ISCSI_STATUS_TGT_MOVED_PERM	0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_STATUS_INIT_ERR		0x00
+#define ISCSI_STATUS_AUTH_FAILED	0x01
+#define ISCSI_STATUS_TGT_FORBIDDEN	0x02
+#define ISCSI_STATUS_TGT_NOT_FOUND	0x03
+#define ISCSI_STATUS_TGT_REMOVED	0x04
+#define ISCSI_STATUS_NO_VERSION		0x05
+#define ISCSI_STATUS_TOO_MANY_CONN	0x06
+#define ISCSI_STATUS_MISSING_FIELDS	0x07
+#define ISCSI_STATUS_CONN_ADD_FAILED	0x08
+#define ISCSI_STATUS_INV_SESSION_TYPE	0x09
+#define ISCSI_STATUS_SESSION_NOT_FOUND	0x0a
+#define ISCSI_STATUS_INV_REQ_TYPE	0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_STATUS_TARGET_ERROR	0x00
+#define ISCSI_STATUS_SVC_UNAVAILABLE	0x01
+#define ISCSI_STATUS_NO_RESOURCES	0x02
+
+struct iscsi_logout_req_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u16 cid;
+	u16 rsvd3;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsvd4[4];
+} __packed;
+
+struct iscsi_logout_rsp_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  response;
+	u8  rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 rsvd3;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 rsvd4;
+	u16 time2wait;
+	u16 time2retain;
+	u32 rsvd5;
+} __packed;
+
+struct iscsi_snack_req_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 itt;
+	u32 ttt;
+	u32 rsvd3;
+	u32 exp_stat_sn;
+	u32 rsvd4[2];
+	u32 beg_run;
+	u32 run_length;
+} __packed;
+
+struct iscsi_reject_hdr {
+	u8  opcode;
+	u8  flags;
+	u8  reason;
+	u8  rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u32 rsvd2[2];
+	u32 ffffffff;
+	u32 rsvd3;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 data_sn;
+	u32 rsvd4[2];
+} __packed;
+
+#define ISCSI_REASON_NO_FULL_FEATURE_PHASE	0x01
+#define ISCSI_REASON_DATA_DIGEST_ERROR		0x02
+#define ISCSI_REASON_DATA_SNACK_REJECT		0x03
+#define ISCSI_REASON_PROTOCOL_ERROR		0x04
+#define ISCSI_REASON_UNSUPPORTED_COMMAND	0x05
+#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT	0x06
+#define ISCSI_REASON_TASK_IN_PROGRESS		0x07
+#define ISCSI_REASON_INVALID_SNACK		0x08
+#define ISCSI_REASON_NO_BOOKMARK		0x09
+#define ISCSI_REASON_BOOKMARK_REJECT		0x0a
+#define ISCSI_REASON_NEGOTIATION_RESET		0x0b
+#define ISCSI_REASON_WAITING_LOGOUT		0x0c
+
+
+struct iscsi_nop_out_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 ttt;
+	u32 cmd_sn;
+	u32 exp_stat_sn;
+	u32 rsvd2[4];
+} __packed;
+
+struct iscsi_nop_in_hdr {
+	u8  opcode;
+	u8  flags;
+	u16 rsvd1;
+	u8  ahslength;
+	u8  datalength[3];
+	u16 lun[4];
+	u32 itt;
+	u32 ttt;
+	u32 stat_sn;
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+	u32 rsvd2[3];
+} __packed;
+
+#define ISCSI_RESERVED_TAG	(0xffffffffU)
+
+#endif	/* __ISCSI_HDR_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/session.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/session.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+
+struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid)
+{
+	struct iscsi_session *session;
+
+	list_for_each_entry(session, &target->session_list, list) {
+		if (session->sid == sid)
+			return session;
+	}
+	return NULL;
+}
+
+static struct iscsi_session *
+iet_session_alloc(struct iscsi_target *target, struct session_info *info)
+{
+	int i;
+	struct iscsi_session *session;
+	struct iet_volume *vol;
+
+	dprintk(D_SETUP, "%p %u %#Lx\n", target, target->tid,
+		(unsigned long long) info->sid);
+
+	session = kzalloc(sizeof(*session), GFP_KERNEL);
+	if (!session)
+		return NULL;
+
+	session->target = target;
+	session->sid = info->sid;
+	memcpy(&session->param, &target->sess_param, sizeof(session->param));
+	session->max_queued_cmnds = target->trgt_param.queued_cmnds;
+
+	session->exp_cmd_sn = info->exp_cmd_sn;
+	session->max_cmd_sn = info->max_cmd_sn;
+
+	session->initiator = kstrdup(info->initiator_name, GFP_KERNEL);
+	if (!session->initiator) {
+		kfree(session);
+		return NULL;
+	}
+
+	INIT_LIST_HEAD(&session->conn_list);
+	INIT_LIST_HEAD(&session->pending_list);
+
+	spin_lock_init(&session->cmnd_hash_lock);
+	for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++)
+		INIT_LIST_HEAD(&session->cmnd_hash[i]);
+
+	spin_lock_init(&session->ua_hash_lock);
+	for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++)
+		INIT_LIST_HEAD(&session->ua_hash[i]);
+
+	list_for_each_entry(vol, &target->volumes, list)
+		/* power-on, reset, or bus device reset occurred */
+		ua_establish_for_session(session, vol->lun, 0x29, 0x0);
+
+	session->next_ttt = 1;
+
+	spin_lock(&target->session_list_lock);
+	list_add(&session->list, &target->session_list);
+	spin_unlock(&target->session_list_lock);
+
+	return session;
+}
+
+static int session_free(struct iscsi_session *session)
+{
+	int i;
+	struct ua_entry *ua, *tmp;
+	struct list_head *l;
+	struct iscsi_target *target = session->target;
+
+	dprintk(D_SETUP, "%#Lx\n", (unsigned long long) session->sid);
+
+	spin_lock(&target->session_list_lock);
+
+	assert(list_empty(&session->conn_list));
+
+	for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) {
+		if (!list_empty(&session->cmnd_hash[i]))
+			BUG();
+	}
+
+	for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++) {
+		l = &session->ua_hash[i];
+		list_for_each_entry_safe(ua, tmp, l, entry) {
+			list_del_init(&ua->entry);
+			ua_free(ua);
+		}
+	}
+
+	list_del(&session->list);
+
+	kfree(session->initiator);
+	kfree(session);
+
+	spin_unlock(&target->session_list_lock);
+
+	return 0;
+}
+
+int session_add(struct iscsi_target *target, struct session_info *info)
+{
+	struct iscsi_session *session;
+
+	session = session_lookup(target, info->sid);
+	if (session)
+		return -EEXIST;
+
+	session = iet_session_alloc(target, info);
+	if (!session)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int session_del(struct iscsi_target *target, u64 sid)
+{
+	struct iscsi_session *session;
+
+	session = session_lookup(target, sid);
+	if (!session)
+		return -ENOENT;
+
+	if (!list_empty(&session->conn_list)) {
+		eprintk("%llu still have connections\n", (unsigned long long) session->sid);
+		return -EBUSY;
+	}
+
+	return session_free(session);
+}
+
+void session_del_all(struct iscsi_target *target)
+{
+	DECLARE_COMPLETION_ONSTACK(done);
+	struct iscsi_session *sess;
+
+	while (!list_empty(&target->session_list)) {
+		init_completion(&done);
+		target_lock(target, 0);
+		sess = list_entry(target->session_list.next, struct
+				  iscsi_session, list);
+		sess->done = &done;
+		conn_del_all(sess);
+		target_unlock(target);
+		wait_for_completion(&done);
+		target_lock(target, 0);
+		session_free(sess);
+		target_unlock(target);
+	}
+
+	if (target->done)
+		complete(target->done);
+}
+
+static void iet_session_info_show(struct seq_file *seq, struct iscsi_target *target)
+{
+	struct iscsi_session *session;
+
+	list_for_each_entry(session, &target->session_list, list) {
+		seq_printf(seq, "\tsid:%llu initiator:%s\n",
+			   (unsigned long long) session->sid, session->initiator);
+		conn_info_show(seq, session);
+	}
+}
+
+static int iet_session_seq_open(struct inode *inode, struct file *file)
+{
+	int res;
+	res = seq_open(file, &iet_seq_op);
+	if (!res)
+		((struct seq_file *)file->private_data)->private =
+			iet_session_info_show;
+	return res;
+}
+
+struct file_operations session_seq_fops = {
+	.owner		= THIS_MODULE,
+	.open		= iet_session_seq_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/nthread.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/nthread.c
@@ -0,0 +1,788 @@
+/*
+ * Network thread.
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * (C) 2008 Arne Redlich <agr@powerkom-dd.de>
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/kthread.h>
+#include <asm/ioctls.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "digest.h"
+
+enum daemon_state_bit {
+	D_ACTIVE,
+	D_DATA_READY,
+};
+
+void __nthread_wakeup(struct network_thread_info *info)
+{
+	set_bit(D_DATA_READY, &info->flags);
+	wake_up_process(info->task);
+}
+
+void nthread_wakeup(struct iscsi_target *target)
+{
+	struct network_thread_info *info = &target->nthread_info;
+
+	spin_lock_bh(&info->nthread_lock);
+	__nthread_wakeup(info);
+	spin_unlock_bh(&info->nthread_lock);
+}
+
+static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, size_t len)
+{
+	len = (len + 3) & -4; // XXX ???
+	conn->read_iov[0].iov_base = data;
+	conn->read_iov[0].iov_len = len;
+	conn->read_msg.msg_iov = conn->read_iov;
+	conn->read_msg.msg_iovlen = 1;
+	conn->read_size = (len + 3) & -4;
+}
+
+static void iscsi_conn_read_ahs(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd)
+{
+	cmnd->pdu.ahs = kmalloc(cmnd->pdu.ahssize, __GFP_NOFAIL|GFP_KERNEL);
+	assert(cmnd->pdu.ahs);
+	iscsi_conn_init_read(conn, cmnd->pdu.ahs, cmnd->pdu.ahssize);
+}
+
+static struct iscsi_cmnd * iscsi_get_send_cmnd(struct iscsi_conn *conn)
+{
+	struct iscsi_cmnd *cmnd = NULL;
+
+	spin_lock(&conn->list_lock);
+	if (!list_empty(&conn->write_list)) {
+		cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd, list);
+		list_del_init(&cmnd->list);
+	}
+	spin_unlock(&conn->list_lock);
+
+	return cmnd;
+}
+
+static int is_data_available(struct iscsi_conn *conn)
+{
+	int avail, res;
+	mm_segment_t oldfs;
+	struct socket *sock = conn->sock;
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	res = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail);
+	set_fs(oldfs);
+	return (res >= 0) ? avail : res;
+}
+
+static void forward_iov(struct msghdr *msg, int len)
+{
+	while (msg->msg_iov->iov_len <= len) {
+		len -= msg->msg_iov->iov_len;
+		msg->msg_iov++;
+		msg->msg_iovlen--;
+	}
+
+	msg->msg_iov->iov_base = (char *) msg->msg_iov->iov_base + len;
+	msg->msg_iov->iov_len -= len;
+}
+
+static int do_recv(struct iscsi_conn *conn, int state)
+{
+	mm_segment_t oldfs;
+	struct msghdr msg;
+	struct iovec iov[ISCSI_CONN_IOV_MAX];
+	int i, len, res;
+
+	if (!test_bit(CONN_ACTIVE, &conn->state)) {
+		res = -EIO;
+		goto out;
+	}
+
+	if (is_data_available(conn) <= 0) {
+		res = -EAGAIN;
+		goto out;
+	}
+
+	msg.msg_iov = iov;
+	msg.msg_iovlen = min_t(size_t, conn->read_msg.msg_iovlen, ISCSI_CONN_IOV_MAX);
+	for (i = 0, len = 0; i < msg.msg_iovlen; i++) {
+		iov[i] = conn->read_msg.msg_iov[i];
+		len += iov[i].iov_len;
+	}
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	res = sock_recvmsg(conn->sock, &msg, len, MSG_DONTWAIT | MSG_NOSIGNAL);
+	set_fs(oldfs);
+
+	if (res <= 0) {
+		switch (res) {
+		case -EAGAIN:
+		case -ERESTARTSYS:
+			break;
+		default:
+			eprintk("%d\n", res);
+			conn_close(conn);
+			break;
+		}
+	} else {
+		conn->read_size -= res;
+		if (conn->read_size)
+			forward_iov(&conn->read_msg, res);
+		else
+			conn->read_state = state;
+	}
+
+out:
+	dprintk(D_IOD, "%d\n", res);
+
+	return res;
+}
+
+enum rx_state {
+	RX_INIT_BHS, /* Must be zero. */
+	RX_BHS,
+
+	RX_INIT_AHS,
+	RX_AHS,
+
+	RX_INIT_HDIGEST,
+	RX_HDIGEST,
+	RX_CHECK_HDIGEST,
+
+	RX_INIT_DATA,
+	RX_DATA,
+
+	RX_INIT_DDIGEST,
+	RX_DDIGEST,
+	RX_CHECK_DDIGEST,
+
+	RX_END,
+};
+
+static void rx_ddigest(struct iscsi_conn *conn, int state)
+{
+	struct iscsi_cmnd *cmnd = conn->read_cmnd;
+	int res = digest_rx_data(cmnd);
+
+	if (!res)
+		conn->read_state = state;
+	else
+		conn_close(conn);
+}
+
+static void rx_hdigest(struct iscsi_conn *conn, int state)
+{
+	struct iscsi_cmnd *cmnd = conn->read_cmnd;
+	int res = digest_rx_header(cmnd);
+
+	if (!res)
+		conn->read_state = state;
+	else
+		conn_close(conn);
+}
+
+static struct iscsi_cmnd *create_cmnd(struct iscsi_conn *conn)
+{
+	struct iscsi_cmnd *cmnd;
+
+	cmnd = cmnd_alloc(conn, 1);
+	iscsi_conn_init_read(cmnd->conn, &cmnd->pdu.bhs, sizeof(cmnd->pdu.bhs));
+	conn->read_state = RX_BHS;
+
+	return cmnd;
+}
+
+static int recv(struct iscsi_conn *conn)
+{
+	struct iscsi_cmnd *cmnd = conn->read_cmnd;
+	int hdigest, ddigest, res = 1;
+
+	if (!test_bit(CONN_ACTIVE, &conn->state))
+		return -EIO;
+
+	hdigest = conn->hdigest_type & DIGEST_NONE ? 0 : 1;
+	ddigest = conn->ddigest_type & DIGEST_NONE ? 0 : 1;
+
+	switch (conn->read_state) {
+	case RX_INIT_BHS:
+		assert(!cmnd);
+		cmnd = conn->read_cmnd = create_cmnd(conn);
+	case RX_BHS:
+		res = do_recv(conn, RX_INIT_AHS);
+		if (res <= 0 || conn->read_state != RX_INIT_AHS)
+			break;
+	case RX_INIT_AHS:
+		iscsi_cmnd_get_length(&cmnd->pdu);
+		if (cmnd->pdu.ahssize) {
+			iscsi_conn_read_ahs(conn, cmnd);
+			conn->read_state = RX_AHS;
+		} else
+			conn->read_state = hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA;
+
+		if (conn->read_state != RX_AHS)
+			break;
+	case RX_AHS:
+		res = do_recv(conn, hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA);
+		if (res <= 0 || conn->read_state != RX_INIT_HDIGEST)
+			break;
+	case RX_INIT_HDIGEST:
+		iscsi_conn_init_read(conn, &cmnd->hdigest, sizeof(u32));
+		conn->read_state = RX_HDIGEST;
+	case RX_HDIGEST:
+		res = do_recv(conn, RX_CHECK_HDIGEST);
+		if (res <= 0 || conn->read_state != RX_CHECK_HDIGEST)
+			break;
+	case RX_CHECK_HDIGEST:
+		rx_hdigest(conn, RX_INIT_DATA);
+		if (conn->read_state != RX_INIT_DATA)
+			break;
+	case RX_INIT_DATA:
+		cmnd_rx_start(cmnd);
+		conn->read_state = cmnd->pdu.datasize ? RX_DATA : RX_END;
+		if (conn->read_state != RX_DATA)
+			break;
+	case RX_DATA:
+		res = do_recv(conn, ddigest ? RX_INIT_DDIGEST : RX_END);
+		if (res <= 0 || conn->read_state != RX_INIT_DDIGEST)
+			break;
+	case RX_INIT_DDIGEST:
+		iscsi_conn_init_read(conn, &cmnd->ddigest, sizeof(u32));
+		conn->read_state = RX_DDIGEST;
+	case RX_DDIGEST:
+		res = do_recv(conn, RX_CHECK_DDIGEST);
+		if (res <= 0 || conn->read_state != RX_CHECK_DDIGEST)
+			break;
+	case RX_CHECK_DDIGEST:
+		rx_ddigest(conn, RX_END);
+		break;
+	default:
+		eprintk("%d %d %x\n", res, conn->read_state, cmnd_opcode(cmnd));
+		assert(0);
+	}
+
+	if (res <= 0)
+		return res;
+
+	if (conn->read_state != RX_END)
+		return res;
+
+	if (conn->read_size) {
+		eprintk("%d %x %d\n", res, cmnd_opcode(cmnd), conn->read_size);
+		assert(0);
+	}
+
+	cmnd_rx_end(cmnd);
+	if (conn->read_size) {
+		eprintk("%x %d\n", cmnd_opcode(cmnd), conn->read_size);
+		conn->read_state = RX_DATA;
+		return 1;
+	}
+
+	conn->read_cmnd = NULL;
+	conn->read_state = RX_INIT_BHS;
+
+	return 0;
+}
+
+/*
+ * @locking: grabs the target's nthread_lock to protect it from races with
+ * iet_write_space()
+ */
+static void set_conn_wspace_wait(struct iscsi_conn *conn)
+{
+	struct network_thread_info *info = &conn->session->target->nthread_info;
+	struct sock *sk = conn->sock->sk;
+
+	spin_lock_bh(&info->nthread_lock);
+
+	if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))
+		set_bit(CONN_WSPACE_WAIT, &conn->state);
+
+	spin_unlock_bh(&info->nthread_lock);
+}
+
+/* This is taken from the Ardis code. */
+static int write_data(struct iscsi_conn *conn)
+{
+	mm_segment_t oldfs;
+	struct file *file;
+	struct socket *sock;
+	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
+	struct tio *tio;
+	struct iovec *iop;
+	int saved_size, size, sendsize;
+	int offset, idx;
+	int flags, res;
+
+	file = conn->file;
+	saved_size = size = conn->write_size;
+	iop = conn->write_iop;
+
+	if (iop) while (1) {
+		loff_t off = 0;
+		unsigned long count;
+		struct iovec *vec;
+		int rest;
+
+		vec = iop;
+		for (count = 0; vec->iov_len; count++, vec++)
+			;
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		res = vfs_writev(file, (struct iovec __user *) iop, count, &off);
+		set_fs(oldfs);
+		dprintk(D_DATA, "%#Lx:%u: %d(%ld)\n",
+			(unsigned long long) conn->session->sid, conn->cid,
+			res, (long) iop->iov_len);
+		if (unlikely(res <= 0)) {
+			if (res == -EAGAIN || res == -EINTR) {
+				conn->write_iop = iop;
+				goto out_iov;
+			}
+			goto err;
+		}
+
+		rest = res;
+		size -= res;
+		while (iop->iov_len <= rest && rest) {
+			rest -= iop->iov_len;
+			iop++;
+		}
+		iop->iov_base += rest;
+		iop->iov_len -= rest;
+
+		if (!iop->iov_len) {
+			conn->write_iop = NULL;
+			if (size)
+				break;
+			goto out_iov;
+		}
+	}
+
+	if (!(tio = conn->write_tcmnd)) {
+		eprintk("%s\n", "warning data missing!");
+		return 0;
+	}
+	offset = conn->write_offset;
+	idx = offset >> PAGE_CACHE_SHIFT;
+	offset &= ~PAGE_CACHE_MASK;
+
+	sock = conn->sock;
+	sendpage = sock->ops->sendpage ? : sock_no_sendpage;
+	flags = MSG_DONTWAIT;
+
+	while (1) {
+		sendsize = PAGE_CACHE_SIZE - offset;
+		if (size <= sendsize) {
+			res = sendpage(sock, tio->pvec[idx], offset, size, flags);
+			dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n",
+				sock->ops->sendpage ? "sendpage" : "writepage",
+				(unsigned long long ) conn->session->sid, conn->cid,
+				res, tio->pvec[idx]->index, offset, size);
+			if (unlikely(res <= 0)) {
+				if (res == -EAGAIN || res == -EINTR) {
+					goto out;
+				}
+				goto err;
+			}
+			if (res == size) {
+				conn->write_tcmnd = NULL;
+				conn->write_size = 0;
+				return saved_size;
+			}
+			offset += res;
+			size -= res;
+			continue;
+		}
+
+		res = sendpage(sock, tio->pvec[idx], offset,sendsize, flags | MSG_MORE);
+		dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n",
+			sock->ops->sendpage ? "sendpage" : "writepage",
+			(unsigned long long ) conn->session->sid, conn->cid,
+			res, tio->pvec[idx]->index, offset, sendsize);
+		if (unlikely(res <= 0)) {
+			if (res == -EAGAIN || res == -EINTR) {
+				goto out;
+			}
+			goto err;
+		}
+		if (res == sendsize) {
+			idx++;
+			offset = 0;
+		} else
+			offset += res;
+		size -= res;
+	}
+ out:
+	conn->write_offset = (idx << PAGE_CACHE_SHIFT) + offset;
+ out_iov:
+	conn->write_size = size;
+	if (res == -EAGAIN) {
+		set_conn_wspace_wait(conn);
+		if (saved_size == size)
+			return res;
+	}
+
+	return saved_size - size;
+
+ err:
+	eprintk("error %d at %#Lx:%u\n", res,
+		(unsigned long long) conn->session->sid, conn->cid);
+	return res;
+}
+
+static void exit_tx(struct iscsi_conn *conn, int res)
+{
+	if (res > 0)
+		return;
+
+	switch (res) {
+	case -EAGAIN:
+	case -ERESTARTSYS:
+		break;
+	default:
+		eprintk("%d %d %d\n", conn->write_size, conn->write_state, res);
+		conn_close(conn);
+		break;
+	}
+}
+
+static int tx_ddigest(struct iscsi_cmnd *cmnd, int state)
+{
+	int res, rest = cmnd->conn->write_size;
+	struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
+	struct kvec iov;
+
+	iov.iov_base = (char *) (&cmnd->ddigest) + (sizeof(u32) - rest);
+	iov.iov_len = rest;
+
+	res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest);
+
+	if (res > 0) {
+		cmnd->conn->write_size -= res;
+		if (!cmnd->conn->write_size)
+			cmnd->conn->write_state = state;
+	} else
+		exit_tx(cmnd->conn, res);
+
+	return res;
+}
+
+static void init_tx_hdigest(struct iscsi_cmnd *cmnd)
+{
+	struct iscsi_conn *conn = cmnd->conn;
+	struct iovec *iop;
+
+	if (conn->hdigest_type & DIGEST_NONE)
+		return;
+
+	digest_tx_header(cmnd);
+
+	for (iop = conn->write_iop; iop->iov_len; iop++)
+		;
+	iop->iov_base = &(cmnd->hdigest);
+	iop->iov_len = sizeof(u32);
+	conn->write_size += sizeof(u32);
+	iop++;
+	iop->iov_len = 0;
+
+	return;
+}
+
+enum tx_state {
+	TX_INIT, /* Must be zero. */
+	TX_BHS_DATA,
+	TX_INIT_DDIGEST,
+	TX_DDIGEST,
+	TX_END,
+};
+
+static int do_send(struct iscsi_conn *conn, int state)
+{
+	int res;
+
+	res = write_data(conn);
+
+	if (res > 0) {
+		if (!conn->write_size)
+			conn->write_state = state;
+	} else
+		exit_tx(conn, res);
+
+	return res;
+}
+
+static int send(struct iscsi_conn *conn)
+{
+	struct iscsi_cmnd *cmnd = conn->write_cmnd;
+	int ddigest, res = 0;
+
+	ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0;
+
+	switch (conn->write_state) {
+	case TX_INIT:
+		assert(!cmnd);
+		cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn);
+		if (!cmnd)
+			return 0;
+		cmnd_tx_start(cmnd);
+		init_tx_hdigest(cmnd);
+		conn->write_state = TX_BHS_DATA;
+	case TX_BHS_DATA:
+		res = do_send(conn, ddigest && cmnd->pdu.datasize ? TX_INIT_DDIGEST : TX_END);
+		if (res <= 0 || conn->write_state != TX_INIT_DDIGEST)
+			break;
+	case TX_INIT_DDIGEST:
+		digest_tx_data(cmnd);
+		assert(!cmnd->conn->write_size);
+		cmnd->conn->write_size += sizeof(u32);
+		conn->write_state = TX_DDIGEST;
+	case TX_DDIGEST:
+		res = tx_ddigest(cmnd, TX_END);
+		break;
+	default:
+		eprintk("%d %d %x\n", res, conn->write_state, cmnd_opcode(cmnd));
+		assert(0);
+	}
+
+	if (res <= 0)
+		return res;
+
+	if (conn->write_state != TX_END)
+		return res;
+
+	if (conn->write_size) {
+		eprintk("%d %x %u\n", res, cmnd_opcode(cmnd), conn->write_size);
+		assert(!conn->write_size);
+	}
+	cmnd_tx_end(cmnd);
+	cmnd_release(cmnd, 0);
+	conn->write_cmnd = NULL;
+	conn->write_state = TX_INIT;
+
+	return 0;
+}
+
+static void conn_nop_timeout(unsigned long data)
+{
+	struct iscsi_conn *conn = (struct iscsi_conn *)data;
+
+	if (test_bit(CONN_ACTIVE, &conn->state))
+		set_bit(CONN_NEED_NOP_IN, &conn->state);
+
+	dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid,
+		conn->cid, &conn->nop_timer);
+
+	nthread_wakeup(conn->session->target);
+}
+
+static void conn_reset_nop_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_target *target = conn->session->target;
+
+	if (target->trgt_param.nop_interval)
+		mod_timer(&conn->nop_timer,
+			  jiffies + HZ * target->trgt_param.nop_interval);
+}
+
+static void conn_start_nop_timer(struct iscsi_conn *conn)
+{
+	struct iscsi_target *target = conn->session->target;
+
+	if (!target->trgt_param.nop_interval || timer_pending(&conn->nop_timer))
+		return;
+
+	conn->nop_timer.data = (unsigned long)conn;
+	conn->nop_timer.function = conn_nop_timeout;
+
+	dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid,
+		conn->cid, &conn->nop_timer);
+
+	mod_timer(&conn->nop_timer,
+		  jiffies + HZ * target->trgt_param.nop_interval);
+}
+
+static void process_io(struct iscsi_conn *conn)
+{
+	struct iscsi_target *target = conn->session->target;
+	int res, wakeup = 0;
+
+	res = recv(conn);
+
+	if (is_data_available(conn) > 0 || res > 0) {
+		conn_reset_nop_timer(conn);
+		wakeup = 1;
+	}
+
+	if (!test_bit(CONN_ACTIVE, &conn->state)) {
+		wakeup = 1;
+		goto out;
+	}
+
+	if (test_bit(CONN_WSPACE_WAIT, &conn->state))
+		goto out;
+
+	res = send(conn);
+
+	if (!list_empty(&conn->write_list) || conn->write_cmnd) {
+		conn_reset_nop_timer(conn);
+		wakeup = 1;
+	}
+
+out:
+	if (wakeup)
+		nthread_wakeup(target);
+	else if (test_and_clear_bit(CONN_NEED_NOP_IN, &conn->state)) {
+		send_nop_in(conn);
+		nthread_wakeup(target);
+	} else
+		conn_start_nop_timer(conn);
+
+	return;
+}
+
+static void close_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_target *target = conn->session->target;
+	struct iscsi_cmnd *cmnd;
+
+	if (target->trgt_param.nop_interval)
+		del_timer_sync(&conn->nop_timer);
+
+	conn->sock->ops->shutdown(conn->sock, 2);
+
+	write_lock_bh(&conn->sock->sk->sk_callback_lock);
+	conn->sock->sk->sk_state_change = target->nthread_info.old_state_change;
+	conn->sock->sk->sk_data_ready = target->nthread_info.old_data_ready;
+	conn->sock->sk->sk_write_space = target->nthread_info.old_write_space;
+	write_unlock_bh(&conn->sock->sk->sk_callback_lock);
+
+	fput(conn->file);
+	conn->file = NULL;
+	conn->sock = NULL;
+
+	while (atomic_read(&conn->nr_busy_cmnds))
+		yield();
+
+	while (!list_empty(&conn->pdu_list)) {
+		cmnd = list_entry(conn->pdu_list.next, struct iscsi_cmnd, conn_list);
+
+		list_del_init(&cmnd->list);
+		cmnd_release(cmnd, 1);
+	}
+
+	if (atomic_read(&conn->nr_cmnds)) {
+		eprintk("%u\n", atomic_read(&conn->nr_cmnds));
+		list_for_each_entry(cmnd, &conn->pdu_list, conn_list)
+			eprintk("%x %x\n", cmnd_opcode(cmnd), cmnd_itt(cmnd));
+		assert(0);
+	}
+
+	event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0);
+	conn_free(conn);
+
+	if (list_empty(&session->conn_list)) {
+		if (session->done)
+			complete(session->done);
+		else
+			session_del(target, session->sid);
+	}
+}
+
+static int istd(void *arg)
+{
+	struct iscsi_target *target = arg;
+	struct network_thread_info *info = &target->nthread_info;
+	struct iscsi_conn *conn, *tmp;
+
+	__set_current_state(TASK_RUNNING);
+	do {
+		spin_lock_bh(&info->nthread_lock);
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!test_bit(D_DATA_READY, &info->flags)) {
+			spin_unlock_bh(&info->nthread_lock);
+			schedule();
+			spin_lock_bh(&info->nthread_lock);
+		}
+		__set_current_state(TASK_RUNNING);
+		clear_bit(D_DATA_READY, &info->flags);
+		spin_unlock_bh(&info->nthread_lock);
+
+		target_lock(target, 0);
+		list_for_each_entry_safe(conn, tmp, &info->active_conns, poll_list) {
+			if (test_bit(CONN_ACTIVE, &conn->state))
+				process_io(conn);
+			else
+				close_conn(conn);
+		}
+		target_unlock(target);
+
+	} while (!kthread_should_stop());
+
+	return 0;
+}
+
+int nthread_init(struct iscsi_target *target)
+{
+	struct network_thread_info *info = &target->nthread_info;
+
+	info->flags = 0;
+	info->task = NULL;
+
+	info->old_state_change = NULL;
+	info->old_data_ready = NULL;
+	info->old_write_space = NULL;
+
+	INIT_LIST_HEAD(&info->active_conns);
+
+	spin_lock_init(&info->nthread_lock);
+
+	return 0;
+}
+
+int nthread_start(struct iscsi_target *target)
+{
+	int err = 0;
+	struct network_thread_info *info = &target->nthread_info;
+	struct task_struct *task;
+
+	if (info->task) {
+		eprintk("Target (%u) already runs\n", target->tid);
+		return -EALREADY;
+	}
+
+	task = kthread_run(istd, target, "istd%d", target->tid);
+
+	if (IS_ERR(task))
+		err = PTR_ERR(task);
+	else
+		info->task = task;
+
+	return err;
+}
+
+int nthread_stop(struct iscsi_target *target)
+{
+	int err;
+	struct network_thread_info *info = &target->nthread_info;
+
+	if (!info->task)
+		return -ESRCH;
+
+	err = kthread_stop(info->task);
+
+	if (err < 0 && err != -EINTR)
+		return err;
+
+	info->task = NULL;
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/event.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/event.c
@@ -0,0 +1,96 @@
+/*
+ * Event notification code.
+ * (C) 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ *
+ * Some functions are based on audit code.
+ */
+
+#include <net/tcp.h>
+#include "iet_u.h"
+#include "iscsi_dbg.h"
+
+static struct sock *nl;
+static u32 ietd_pid;
+
+static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+	u32 uid, pid, seq;
+	char *data;
+
+	pid  = NETLINK_CREDS(skb)->pid;
+	uid  = NETLINK_CREDS(skb)->uid;
+	seq  = nlh->nlmsg_seq;
+	data = NLMSG_DATA(nlh);
+
+	ietd_pid = pid;
+
+	return 0;
+}
+
+static void event_recv_skb(struct sk_buff *skb)
+{
+	int err;
+	struct nlmsghdr	*nlh;
+	u32 rlen;
+
+	while (skb->len >= NLMSG_SPACE(0)) {
+		nlh = (struct nlmsghdr *)skb->data;
+		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+			break;
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > skb->len)
+			rlen = skb->len;
+		if ((err = event_recv_msg(skb, nlh))) {
+			netlink_ack(skb, nlh, -err);
+		} else if (nlh->nlmsg_flags & NLM_F_ACK)
+			netlink_ack(skb, nlh, 0);
+		skb_pull(skb, rlen);
+	}
+}
+
+static int notify(void *data, int len, int gfp_mask)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	static u32 seq = 0;
+
+	if (!(skb = alloc_skb(NLMSG_SPACE(len), gfp_mask)))
+		return -ENOMEM;
+
+	nlh = __nlmsg_put(skb, ietd_pid, seq++, NLMSG_DONE, len - sizeof(*nlh), 0);
+
+	memcpy(NLMSG_DATA(nlh), data, len);
+
+	return netlink_unicast(nl, skb, ietd_pid, 0);
+}
+
+int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic)
+{
+	int err;
+	struct iet_event event;
+
+	event.tid = tid;
+	event.sid = sid;
+	event.cid = cid;
+	event.state = state;
+
+	err = notify(&event, NLMSG_SPACE(sizeof(struct iet_event)), 0);
+
+	return err;
+}
+
+int event_init(void)
+{
+	nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb,
+				   NULL, THIS_MODULE);
+	if (!nl)
+		return -ENOMEM;
+	else
+		return 0;
+}
+
+void event_exit(void)
+{
+	netlink_kernel_release(nl);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/BOM
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	svn://svn.berlios.de/iscsitarget/trunk
+Current Version:	1.4.19
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iotype.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iotype.c
@@ -0,0 +1,110 @@
+/*
+ * Manager for various I/O types.
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
+ * This code is licenced under the GPL.
+ */
+
+#include "iscsi.h"
+#include "iotype.h"
+#include "iscsi_dbg.h"
+
+static LIST_HEAD(iotypes);
+static rwlock_t iotypes_lock = RW_LOCK_UNLOCKED;
+
+static struct iotype *find_iotype(const char *name)
+{
+	struct iotype *iot = NULL;
+
+	list_for_each_entry(iot, &iotypes, iot_list) {
+		if (strcmp(iot->name, name) == 0)
+			return iot;
+	}
+	return NULL;
+}
+
+struct iotype *get_iotype(const char *name)
+{
+	struct iotype *iot;
+
+	read_lock(&iotypes_lock);
+	iot = find_iotype(name);
+	read_unlock(&iotypes_lock);
+
+	return iot;
+}
+
+void put_iotype(struct iotype *iot)
+{
+	if (!iot)
+		return;
+	return;
+}
+
+static int register_iotype(struct iotype *iot)
+{
+	int err = 0;
+	struct iotype *p;
+
+	write_lock(&iotypes_lock);
+
+	p = find_iotype(iot->name);
+	if (p)
+		err = -EBUSY;
+	else
+		list_add_tail(&iot->iot_list, &iotypes);
+
+	write_unlock(&iotypes_lock);
+
+	return err;
+}
+
+static int unregister_iotype(struct iotype *iot)
+{
+	int err = 0;
+	struct iotype *p;
+
+	write_lock(&iotypes_lock);
+
+	p = find_iotype(iot->name);
+	if (p && p == iot)
+		list_del_init(&iot->iot_list);
+	else
+		err = -EINVAL;
+
+	write_unlock(&iotypes_lock);
+
+
+	return err;
+}
+
+struct iotype *iotype_array[] = {
+	&fileio,
+	&blockio,
+	&nullio,
+};
+
+int iotype_init(void)
+{
+	int i, err;
+
+	for (i = 0; i < ARRAY_SIZE(iotype_array); i++) {
+		if (!(err = register_iotype(iotype_array[i])))
+			iprintk("Registered io type %s\n",
+						iotype_array[i]->name);
+		else {
+			eprintk("Failed to register io type %s\n",
+						iotype_array[i]->name);
+			break;
+		}
+	}
+
+	return err;
+}
+
+void iotype_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(iotype_array); i++)
+		unregister_iotype(iotype_array[i]);
+}
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/iscsi.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/iscsi.h
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
+ * Copyright (C) 2008 Arne Redlich <agr@powerkom-dd.de>
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef __ISCSI_H__
+#define __ISCSI_H__
+
+#include <linux/completion.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <net/sock.h>
+
+#include "iscsi_hdr.h"
+#include "iet_u.h"
+
+#define IET_SENSE_BUF_SIZE      18
+
+struct iscsi_sess_param {
+	int initial_r2t;
+	int immediate_data;
+	int max_connections;
+	int max_recv_data_length;
+	int max_xmit_data_length;
+	int max_burst_length;
+	int first_burst_length;
+	int default_wait_time;
+	int default_retain_time;
+	int max_outstanding_r2t;
+	int data_pdu_inorder;
+	int data_sequence_inorder;
+	int error_recovery_level;
+	int header_digest;
+	int data_digest;
+	int ofmarker;
+	int ifmarker;
+	int ofmarkint;
+	int ifmarkint;
+};
+
+struct iscsi_trgt_param {
+	int wthreads;
+	int target_type;
+	int queued_cmnds;
+	int nop_interval;
+	int nop_timeout;
+};
+
+struct tio {
+	u32 pg_cnt;
+
+	pgoff_t idx;
+	u32 offset;
+	u32 size;
+
+	struct page **pvec;
+
+	atomic_t count;
+};
+
+struct network_thread_info {
+	struct task_struct *task;
+	unsigned long flags;
+	struct list_head active_conns;
+
+	spinlock_t nthread_lock;
+
+	void (*old_state_change)(struct sock *);
+	void (*old_data_ready)(struct sock *, int);
+	void (*old_write_space)(struct sock *);
+};
+
+struct worker_thread_info;
+
+struct worker_thread {
+	struct task_struct *w_task;
+	struct list_head w_list;
+	struct worker_thread_info *w_info;
+};
+
+struct worker_thread_info {
+	spinlock_t wthread_lock;
+
+	u32 nr_running_wthreads;
+
+	struct list_head wthread_list;
+	struct list_head work_queue;
+
+	wait_queue_head_t wthread_sleep;
+};
+
+struct iscsi_cmnd;
+
+struct target_type {
+	int id;
+	int (*execute_cmnd) (struct iscsi_cmnd *);
+};
+
+enum iscsi_device_state {
+	IDEV_RUNNING,
+	IDEV_DEL,
+};
+
+struct iscsi_target {
+	struct list_head t_list;
+	u32 tid;
+
+	char name[ISCSI_NAME_LEN];
+
+	struct iscsi_sess_param sess_param;
+	struct iscsi_trgt_param trgt_param;
+
+	atomic_t nr_volumes;
+	struct list_head volumes;
+	struct list_head session_list;
+
+	/* Prevents races between add/del session and adding UAs */
+	spinlock_t session_list_lock;
+
+	struct network_thread_info nthread_info;
+	/* Points either to own list or global pool */
+	struct worker_thread_info * wthread_info;
+
+	struct semaphore target_sem;
+	struct completion *done;
+};
+
+struct iscsi_queue {
+	spinlock_t queue_lock;
+	struct iscsi_cmnd *ordered_cmnd;
+	struct list_head wait_list;
+	int active_cnt;
+};
+
+struct iet_volume {
+	u32 lun;
+
+	enum iscsi_device_state l_state;
+	atomic_t l_count;
+
+	struct iscsi_target *target;
+	struct list_head list;
+
+	struct iscsi_queue queue;
+
+	u8 scsi_id[SCSI_ID_LEN];
+	u8 scsi_sn[SCSI_SN_LEN];
+
+	u32 blk_shift;
+	u64 blk_cnt;
+
+	u64 reserve_sid;
+	spinlock_t reserve_lock;
+
+	unsigned long flags;
+
+	struct iotype *iotype;
+	void *private;
+};
+
+enum lu_flags {
+	LU_READONLY,
+	LU_WCACHE,
+	LU_RCACHE,
+};
+
+#define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags)
+#define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags)
+
+#define LUWCache(lu) test_bit(LU_WCACHE, &(lu)->flags)
+#define SetLUWCache(lu) set_bit(LU_WCACHE, &(lu)->flags)
+#define ClearLUWCache(lu) clear_bit(LU_WCACHE, &(lu)->flags)
+
+#define LURCache(lu) test_bit(LU_RCACHE, &(lu)->flags)
+#define SetLURCache(lu) set_bit(LU_RCACHE, &(lu)->flags)
+#define ClearLURCache(lu) clear_bit(LU_RCACHE, &(lu)->flags)
+
+#define IET_HASH_ORDER		8
+#define	cmnd_hashfn(itt)	hash_long((itt), IET_HASH_ORDER)
+
+#define UA_HASH_LEN 8
+
+struct iscsi_session {
+	struct list_head list;
+	struct iscsi_target *target;
+	struct completion *done;
+	char *initiator;
+	u64 sid;
+
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+
+	struct iscsi_sess_param param;
+	u32 max_queued_cmnds;
+
+	struct list_head conn_list;
+
+	struct list_head pending_list;
+
+	spinlock_t cmnd_hash_lock;
+	struct list_head cmnd_hash[1 << IET_HASH_ORDER];
+
+	spinlock_t ua_hash_lock;
+	struct list_head ua_hash[UA_HASH_LEN];
+
+	u32 next_ttt;
+};
+
+enum connection_state_bit {
+	CONN_ACTIVE,
+	CONN_CLOSING,
+	CONN_WSPACE_WAIT,
+	CONN_NEED_NOP_IN,
+};
+
+#define ISCSI_CONN_IOV_MAX	(((256 << 10) >> PAGE_SHIFT) + 1)
+
+struct iscsi_conn {
+	struct list_head list;			/* list entry in session list */
+	struct iscsi_session *session;		/* owning session */
+
+	u16 cid;
+	unsigned long state;
+
+	u32 stat_sn;
+	u32 exp_stat_sn;
+
+	int hdigest_type;
+	int ddigest_type;
+
+	struct list_head poll_list;
+
+	struct file *file;
+	struct socket *sock;
+	spinlock_t list_lock;
+	atomic_t nr_cmnds;
+	atomic_t nr_busy_cmnds;
+	struct list_head pdu_list;		/* in/outcoming pdus */
+	struct list_head write_list;		/* list of data pdus to be sent */
+	struct timer_list nop_timer;
+
+	struct iscsi_cmnd *read_cmnd;
+	struct msghdr read_msg;
+	struct iovec read_iov[ISCSI_CONN_IOV_MAX];
+	u32 read_size;
+	u32 read_overflow;
+	int read_state;
+
+	struct iscsi_cmnd *write_cmnd;
+	struct iovec write_iov[ISCSI_CONN_IOV_MAX];
+	struct iovec *write_iop;
+	struct tio *write_tcmnd;
+	u32 write_size;
+	u32 write_offset;
+	int write_state;
+
+	struct hash_desc rx_hash;
+	struct hash_desc tx_hash;
+	struct scatterlist hash_sg[ISCSI_CONN_IOV_MAX];
+};
+
+struct iscsi_pdu {
+	struct iscsi_hdr bhs;
+	void *ahs;
+	unsigned int ahssize;
+	unsigned int datasize;
+};
+
+typedef void (iet_show_info_t)(struct seq_file *seq, struct iscsi_target *target);
+
+struct iscsi_cmnd {
+	struct list_head list;
+	struct list_head conn_list;
+	unsigned long flags;
+	struct iscsi_conn *conn;
+	struct iet_volume *lun;
+
+	struct iscsi_pdu pdu;
+	struct list_head pdu_list;
+
+	struct list_head hash_list;
+
+	struct tio *tio;
+
+	u8 status;
+
+	struct timer_list timer;
+
+	u32 r2t_sn;
+	u32 r2t_length;
+	u32 is_unsolicited_data;
+	u32 target_task_tag;
+	u32 outstanding_r2t;
+
+	u32 hdigest;
+	u32 ddigest;
+
+	struct iscsi_cmnd *req;
+
+	unsigned char sense_buf[IET_SENSE_BUF_SIZE];
+};
+
+struct ua_entry {
+	struct list_head entry;
+	struct iscsi_session *session; /* only used for debugging ATM */
+	u32 lun;
+	u8 asc;
+	u8 ascq;
+};
+
+#define ISCSI_OP_SCSI_REJECT	ISCSI_OP_VENDOR1_CMD
+#define ISCSI_OP_PDU_REJECT	ISCSI_OP_VENDOR2_CMD
+#define ISCSI_OP_DATA_REJECT	ISCSI_OP_VENDOR3_CMD
+#define ISCSI_OP_SCSI_ABORT	ISCSI_OP_VENDOR4_CMD
+
+/* iscsi.c */
+extern unsigned long worker_thread_pool_size;
+extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *, int);
+extern void cmnd_rx_start(struct iscsi_cmnd *);
+extern void cmnd_rx_end(struct iscsi_cmnd *);
+extern void cmnd_tx_start(struct iscsi_cmnd *);
+extern void cmnd_tx_end(struct iscsi_cmnd *);
+extern void cmnd_release(struct iscsi_cmnd *, int);
+extern void send_data_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *));
+extern void send_scsi_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *));
+extern void iscsi_cmnd_set_sense(struct iscsi_cmnd *, u8 sense_key, u8 asc,
+				 u8 ascq);
+extern void send_nop_in(struct iscsi_conn *);
+
+/* conn.c */
+extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
+extern int conn_add(struct iscsi_session *, struct conn_info *);
+extern int conn_del(struct iscsi_session *, struct conn_info *);
+extern void conn_del_all(struct iscsi_session *);
+extern int conn_free(struct iscsi_conn *);
+extern void conn_close(struct iscsi_conn *);
+extern void conn_info_show(struct seq_file *, struct iscsi_session *);
+
+/* nthread.c */
+extern int nthread_init(struct iscsi_target *);
+extern int nthread_start(struct iscsi_target *);
+extern int nthread_stop(struct iscsi_target *);
+extern void __nthread_wakeup(struct network_thread_info *);
+extern void nthread_wakeup(struct iscsi_target *);
+
+/* wthread.c */
+extern int wthread_init(struct worker_thread_info *info);
+extern int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid);
+extern int wthread_stop(struct worker_thread_info *info);
+extern void wthread_queue(struct iscsi_cmnd *);
+extern struct target_type *target_type_array[];
+extern int wthread_module_init(void);
+extern void wthread_module_exit(void);
+extern struct worker_thread_info *worker_thread_pool;
+
+/* target.c */
+extern int target_lock(struct iscsi_target *, int);
+extern void target_unlock(struct iscsi_target *);
+struct iscsi_target *target_lookup_by_id(u32);
+extern int target_add(struct target_info *);
+extern int target_del(u32 id);
+extern void target_del_all(void);
+extern struct seq_operations iet_seq_op;
+
+/* config.c */
+extern int iet_procfs_init(void);
+extern void iet_procfs_exit(void);
+extern int iet_info_show(struct seq_file *, iet_show_info_t *);
+
+/* session.c */
+extern struct file_operations session_seq_fops;
+extern struct iscsi_session *session_lookup(struct iscsi_target *, u64);
+extern int session_add(struct iscsi_target *, struct session_info *);
+extern int session_del(struct iscsi_target *, u64);
+extern void session_del_all(struct iscsi_target *);
+
+/* volume.c */
+extern struct file_operations volume_seq_fops;
+extern int volume_add(struct iscsi_target *, struct volume_info *);
+extern int iscsi_volume_del(struct iscsi_target *, struct volume_info *);
+extern void iscsi_volume_destroy(struct iet_volume *);
+extern struct iet_volume *volume_lookup(struct iscsi_target *, u32);
+extern struct iet_volume *volume_get(struct iscsi_target *, u32);
+extern void volume_put(struct iet_volume *);
+extern int volume_reserve(struct iet_volume *volume, u64 sid);
+extern int volume_release(struct iet_volume *volume, u64 sid, int force);
+extern int is_volume_reserved(struct iet_volume *volume, u64 sid);
+
+/* tio.c */
+extern int tio_init(void);
+extern void tio_exit(void);
+extern struct tio *tio_alloc(int);
+extern void tio_get(struct tio *);
+extern void tio_put(struct tio *);
+extern void tio_set(struct tio *, u32, loff_t);
+extern int tio_read(struct iet_volume *, struct tio *);
+extern int tio_write(struct iet_volume *, struct tio *);
+extern int tio_sync(struct iet_volume *, struct tio *);
+
+/* iotype.c */
+extern struct iotype *get_iotype(const char *name);
+extern void put_iotype(struct iotype *iot);
+
+/* params.c */
+extern int iscsi_param_set(struct iscsi_target *, struct iscsi_param_info *, int);
+
+/* target_disk.c */
+extern struct target_type disk_ops;
+
+/* event.c */
+extern int event_send(u32, u64, u32, u32, int);
+extern int event_init(void);
+extern void event_exit(void);
+
+/* ua.c */
+int ua_init(void);
+void ua_exit(void);
+struct ua_entry * ua_get_first(struct iscsi_session *, u32 lun);
+struct ua_entry * ua_get_match(struct iscsi_session *, u32 lun, u8 asc,
+			       u8 ascq);
+void ua_free(struct ua_entry *);
+int ua_pending(struct iscsi_session *, u32 lun);
+void ua_establish_for_session(struct iscsi_session *, u32 lun, u8 asc,
+			     u8 ascq);
+void ua_establish_for_other_sessions(struct iscsi_session *, u32 lun, u8 asc,
+				     u8 ascq);
+void ua_establish_for_all_sessions(struct iscsi_target *, u32 lun, u8 asc,
+				   u8 ascq);
+
+#define get_pgcnt(size, offset)	((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
+static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu)
+{
+#if defined(__BIG_ENDIAN)
+	pdu->ahssize = pdu->bhs.length.ahslength * 4;
+	pdu->datasize = pdu->bhs.length.datalength;
+#elif defined(__LITTLE_ENDIAN)
+	pdu->ahssize = (pdu->bhs.length & 0xff) * 4;
+	pdu->datasize = be32_to_cpu(pdu->bhs.length & ~0xff);
+#else
+#error
+#endif
+}
+
+static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu)
+{
+#if defined(__BIG_ENDIAN)
+	pdu->bhs.length.ahslength = pdu->ahssize / 4;
+	pdu->bhs.length.datalength = pdu->datasize;
+#elif defined(__LITTLE_ENDIAN)
+	pdu->bhs.length = cpu_to_be32(pdu->datasize) | (pdu->ahssize / 4);
+#else
+#error
+#endif
+}
+
+#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs)))
+#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt)
+#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt)
+#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK)
+#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0]
+
+#define	SECTOR_SIZE_BITS	9
+
+enum cmnd_flags {
+	CMND_hashed,
+	CMND_queued,
+	CMND_final,
+	CMND_waitio,
+	CMND_close,
+	CMND_lunit,
+	CMND_pending,
+	CMND_tmfabort,
+	CMND_rxstart,
+	CMND_timer_active,
+};
+
+#define set_cmnd_hashed(cmnd)	set_bit(CMND_hashed, &(cmnd)->flags)
+#define cmnd_hashed(cmnd)	test_bit(CMND_hashed, &(cmnd)->flags)
+
+#define set_cmnd_queued(cmnd)	set_bit(CMND_queued, &(cmnd)->flags)
+#define cmnd_queued(cmnd)	test_bit(CMND_queued, &(cmnd)->flags)
+
+#define set_cmnd_final(cmnd)	set_bit(CMND_final, &(cmnd)->flags)
+#define cmnd_final(cmnd)	test_bit(CMND_final, &(cmnd)->flags)
+
+#define set_cmnd_waitio(cmnd)	set_bit(CMND_waitio, &(cmnd)->flags)
+#define cmnd_waitio(cmnd)	test_bit(CMND_waitio, &(cmnd)->flags)
+
+#define set_cmnd_close(cmnd)	set_bit(CMND_close, &(cmnd)->flags)
+#define cmnd_close(cmnd)	test_bit(CMND_close, &(cmnd)->flags)
+
+#define set_cmnd_lunit(cmnd)	set_bit(CMND_lunit, &(cmnd)->flags)
+#define cmnd_lunit(cmnd)	test_bit(CMND_lunit, &(cmnd)->flags)
+
+#define set_cmnd_pending(cmnd)	set_bit(CMND_pending, &(cmnd)->flags)
+#define clear_cmnd_pending(cmnd)	clear_bit(CMND_pending, &(cmnd)->flags)
+#define cmnd_pending(cmnd)	test_bit(CMND_pending, &(cmnd)->flags)
+
+#define set_cmnd_tmfabort(cmnd)	set_bit(CMND_tmfabort, &(cmnd)->flags)
+#define cmnd_tmfabort(cmnd)	test_bit(CMND_tmfabort, &(cmnd)->flags)
+
+#define set_cmnd_rxstart(cmnd)	set_bit(CMND_rxstart, &(cmnd)->flags)
+#define cmnd_rxstart(cmnd)	test_bit(CMND_rxstart, &(cmnd)->flags)
+
+#define set_cmnd_timer_active(cmnd)  set_bit(CMND_timer_active, &(cmnd)->flags)
+#define clear_cmnd_timer_active(cmnd) \
+	                        clear_bit(CMND_timer_active, &(cmnd)->flags)
+#define cmnd_timer_active(cmnd) test_bit(CMND_timer_active, &(cmnd)->flags)
+
+#define VENDOR_ID	"IET"
+#define PRODUCT_ID	"VIRTUAL-DISK"
+#define PRODUCT_REV	"0"
+
+#endif	/* __ISCSI_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/null-io.c
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/null-io.c
@@ -0,0 +1,114 @@
+/*
+ * Target device null I/O.
+ * (C) 2005 MING Zhang <mingz@ele.uri.edu>
+ * This code is licenced under the GPL.
+ *
+ * The nullio mode will not return any meaningful or previous written
+ * data. It is only for performance measurement purpose.
+ */
+
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/parser.h>
+#include <linux/writeback.h>
+
+#include "iscsi.h"
+#include "iscsi_dbg.h"
+#include "iotype.h"
+
+struct nullio_data {
+	u64 sectors;
+};
+
+enum {
+	Opt_sectors, Opt_ignore, Opt_err,
+};
+
+static match_table_t tokens = {
+	{Opt_sectors, "Sectors=%u"},
+	{Opt_ignore, "Type=%s"},
+	{Opt_err, NULL},
+};
+
+static int parse_nullio_params(struct iet_volume *volume, char *params)
+{
+	int err = 0;
+	char *p, *q;
+	struct nullio_data *data = volume->private;
+
+	while ((p = strsep(&params, ",")) != NULL) {
+		substring_t args[MAX_OPT_ARGS];
+		int token;
+		if (!*p)
+			continue;
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_sectors:
+			q = match_strdup(&args[0]);
+			if (!q)
+				return -ENOMEM;
+			data->sectors = simple_strtoull(q, NULL, 10);
+			kfree(q);
+			break;
+		case Opt_ignore:
+			break;
+		default:
+			eprintk("Unknown %s\n", p);
+			return -EINVAL;
+			break;
+		}
+	}
+	return err;
+}
+
+static void nullio_detach(struct iet_volume *lu)
+{
+	struct nullio_data *p = lu->private;
+
+	kfree(p);
+	lu->private = NULL;
+}
+
+static int nullio_attach(struct iet_volume *lu, char *args)
+{
+	int err = 0;
+	struct nullio_data *p;
+
+	if (lu->private) {
+		printk("already attached ? %d\n", lu->lun);
+		return -EBUSY;
+	}
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	lu->private = p;
+
+	if ((err = parse_nullio_params(lu, args)) < 0) {
+		eprintk("%d\n", err);
+		goto out;
+	}
+
+	lu->blk_shift = SECTOR_SIZE_BITS;
+	lu->blk_cnt = (p->sectors = p->sectors ? : 1 << 27); /* 64 GB */
+
+out:
+	if (err < 0)
+		nullio_detach(lu);
+	return err;
+}
+
+void nullio_show(struct iet_volume *lu, struct seq_file *seq)
+{
+	struct nullio_data *p = lu->private;
+	seq_printf(seq, " sectors:%llu\n", p->sectors);
+}
+
+struct iotype nullio =
+{
+	.name = "nullio",
+	.attach = nullio_attach,
+	.detach = nullio_detach,
+	.show = nullio_show,
+};
--- linux-ec2-2.6.32.orig/ubuntu/iscsitarget/include/iet_u.h
+++ linux-ec2-2.6.32/ubuntu/iscsitarget/include/iet_u.h
@@ -0,0 +1,149 @@
+#ifndef _IET_U_H
+#define _IET_U_H
+
+#define IET_VERSION_STRING	"1.4.19"
+
+/* The maximum length of 223 bytes in the RFC. */
+#define ISCSI_NAME_LEN	256
+#define ISCSI_ARGS_LEN	2048
+
+#define ISCSI_LISTEN_PORT	3260
+
+#define VENDOR_ID_LEN	8
+#define SCSI_ID_LEN	24
+#define SCSI_SN_LEN	16
+
+#ifndef aligned_u64
+#define aligned_u64 unsigned long long __attribute__((aligned(8)))
+#endif
+
+struct target_info {
+	u32 tid;
+	char name[ISCSI_NAME_LEN];
+};
+
+struct volume_info {
+	u32 tid;
+	u32 lun;
+	aligned_u64 args_ptr;
+	u32 args_len;
+};
+
+struct session_info {
+	u32 tid;
+
+	aligned_u64 sid;
+	char initiator_name[ISCSI_NAME_LEN];
+	u32 exp_cmd_sn;
+	u32 max_cmd_sn;
+};
+
+#define DIGEST_ALL	(DIGEST_NONE | DIGEST_CRC32C)
+#define DIGEST_NONE		(1 << 0)
+#define DIGEST_CRC32C           (1 << 1)
+
+struct conn_info {
+	u32 tid;
+	aligned_u64 sid;
+
+	u32 cid;
+	u32 stat_sn;
+	u32 exp_stat_sn;
+	int header_digest;
+	int data_digest;
+	int fd;
+};
+
+enum {
+	key_initial_r2t,
+	key_immediate_data,
+	key_max_connections,
+	key_max_recv_data_length,
+	key_max_xmit_data_length,
+	key_max_burst_length,
+	key_first_burst_length,
+	key_default_wait_time,
+	key_default_retain_time,
+	key_max_outstanding_r2t,
+	key_data_pdu_inorder,
+	key_data_sequence_inorder,
+	key_error_recovery_level,
+	key_header_digest,
+	key_data_digest,
+	key_ofmarker,
+	key_ifmarker,
+	key_ofmarkint,
+	key_ifmarkint,
+	session_key_last,
+};
+
+enum {
+	key_wthreads,
+	key_target_type,
+	key_queued_cmnds,
+	key_nop_interval,
+	key_nop_timeout,
+	target_key_last,
+};
+
+enum {
+	key_session,
+	key_target,
+};
+
+struct iscsi_param_info {
+	u32 tid;
+	aligned_u64 sid;
+
+	u32 param_type;
+	u32 partial;
+
+	u32 session_param[session_key_last];
+	u32 target_param[target_key_last];
+};
+
+enum iet_event_state {
+	E_CONN_CLOSE,
+};
+
+struct iet_event {
+	u32 tid;
+	aligned_u64 sid;
+	u32 cid;
+	u32 state;
+};
+
+#define	DEFAULT_NR_WTHREADS	8
+#define	MIN_NR_WTHREADS		1
+#define	MAX_NR_WTHREADS		128
+
+#define	DEFAULT_NR_QUEUED_CMNDS	32
+#define	MIN_NR_QUEUED_CMNDS	1
+#define	MAX_NR_QUEUED_CMNDS	256
+
+#define DEFAULT_NOP_INTERVAL 	0
+#define MIN_NOP_INTERVAL 	0
+#define MAX_NOP_INTERVAL 	90
+
+#define	DEFAULT_NOP_TIMEOUT 	0
+#define MIN_NOP_TIMEOUT 	0
+#define MAX_NOP_TIMEOUT		90
+
+#define NETLINK_IET	21
+
+#define ADD_TARGET _IOW('i', 0, struct target_info)
+#define DEL_TARGET _IOW('i', 1, struct target_info)
+#define START_TARGET _IO('i', 2)
+#define STOP_TARGET _IO('i', 3)
+#define ADD_VOLUME _IOW('i', 4, struct volume_info)
+#define DEL_VOLUME _IOW('i', 5, struct volume_info)
+#define ADD_SESSION _IOW('i', 6, struct session_info)
+#define DEL_SESSION _IOW('i', 7, struct session_info)
+#define GET_SESSION_INFO _IOWR('i', 8, struct session_info)
+#define ADD_CONN _IOW('i', 9, struct conn_info)
+#define DEL_CONN _IOW('i', 10, struct conn_info)
+#define GET_CONN_INFO _IOWR('i', 11, struct conn_info)
+#define ISCSI_PARAM_SET _IOW('i', 12, struct iscsi_param_info)
+#define ISCSI_PARAM_GET _IOWR('i', 13, struct iscsi_param_info)
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/Makefile
+++ linux-ec2-2.6.32/ubuntu/fsam7400/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_FSAM7400) += fsam7400.o
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/fsam7400.c
+++ linux-ec2-2.6.32/ubuntu/fsam7400/fsam7400.c
@@ -0,0 +1,386 @@
+/*******************************************************************************
+
+  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.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Author:
+  Marcel Naziri <fsam7400@zwobbl.de>
+
+  Based on:
+  pbe5.c by Pedro Ramalhais <pmr09313@students.fct.unl.pt>
+
+  Many thanks to:
+  Pedro Ramalhais for spending several nights with me on IRC
+
+*******************************************************************************/
+
+#ifdef CONFIG_X86
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <linux/moduleparam.h>
+#else
+#include <linux/modversions.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kmod.h>
+#include <linux/io.h>
+#include <asm/uaccess.h>
+
+#define DRV_NAME         "fsam7400"
+#define DRV_VERSION      "0.5.2"
+#define DRV_DESCRIPTION  "SW RF kill switch for Fujitsu Siemens Amilo M 7400 / Maxdata 7000DX"
+#define DRV_COPYRIGHT    "Copyright(c) 2004 zwobbl"
+#define DRV_AUTHOR       "Marcel Naziri"
+#define DRV_LICENSE      "GPL"
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_LICENSE(DRV_LICENSE);
+
+#define RADIO_NONE     0xFFFFFFFF
+#define RADIO_OFF      0x00000000
+#define RADIO_ON       0x00000010
+
+static int radio = RADIO_NONE;
+static int autooff = 1;
+static int autoload = 0;
+static int uid = 0;
+static int gid = 0;
+static int debug = 0;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+module_param(radio, int, 0444);
+module_param(autooff, int, 0444);
+module_param(autoload, int, 0444);
+module_param(uid, int, 0444);
+module_param(gid, int, 0444);
+module_param(debug, int, 0444);
+#else
+MODULE_PARM(radio, "i");
+MODULE_PARM(autooff, "i");
+MODULE_PARM(autoload, "i");
+MODULE_PARM(uid, "i");
+MODULE_PARM(gid, "i");
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_PARM_DESC(radio, "desired radio state when loading module");
+MODULE_PARM_DESC(autooff, "turns radio off when unloading module (default)");
+MODULE_PARM_DESC(autoload, "load/unloads ipw2100 driver when toggling radio");
+MODULE_PARM_DESC(uid, "user ID for proc entry");
+MODULE_PARM_DESC(gid, "group ID for proc entry");
+MODULE_PARM_DESC(debug, "enables debug output on syslog");
+
+/* some more or less useful macros */
+
+#define DEBUG if (debug)
+#define DEBUG_OUT0(a) DEBUG printk(KERN_INFO DRV_NAME ": " a)
+#define DEBUG_OUT1(a,b) DEBUG printk(KERN_INFO DRV_NAME ": " a,b)
+#define DEBUG_OUT2(a,b,c) DEBUG printk(KERN_INFO DRV_NAME ": " a,b,c)
+#define DEBUG_OUT3(a,b,c,d) DEBUG printk(KERN_INFO DRV_NAME ": " a,b,c,d)
+
+#define ONOFF(x) (x) ? "ON" : "OFF"
+#define RADIO_ONOFF(x) (x) == RADIO_ON ? "ON" : "OFF"
+#define TOUL(x) (unsigned long) (x)
+
+/*
+ * NOTE: These values were obtained from disassembling the wbutton.sys driver
+ * installed in the Fujitsu Siemens Amilo M 7400 laptop. The names were guessed,
+ * so don't rely on them.
+ */
+
+/*** hardware dependant stuff ***/
+
+#define BIOS_CODE_ADDR       0x000F0000
+#define BIOS_CODE_ALT_MASK   0xFFFFC000
+
+#define BIOS_CODE_MAPSIZE      0x010000
+#define BIOS_CODE_ALT_MAPSIZE  0x004000
+
+#define BIOS_MAGIC_COMMAND    0x9610
+#define BIOS_MAGIC_OFF        0x0035
+#define BIOS_MAGIC_ON         0x0135
+#define BIOS_MAGIC_CHECK      0x0235
+
+#define PTR_POSITION  5
+#define ALLIGNED_STEP 0x10
+
+#define BIOS_SIGN_SIZE 4
+static const char bios_sign[] = {
+   0x42, 0x21, 0x55, 0x30
+};
+
+#define WLAN_DISABLED_IN_BIOS  0x01
+#define WLAN_ENABLED_IN_BIOS   0x03
+
+static unsigned long bios_code = 0;
+
+static int fsam_bios_routine(int eax, int ebx)
+{
+   __asm__ __volatile__(
+      "call *%3 \t\n"
+      : "=a"(eax)
+      : "a"(eax), "b"(ebx), "c"(bios_code)
+      );
+   return (eax & 0xFF);
+}
+
+static int fsam_call_bios(int value)
+{
+   if (bios_code) {
+      int command = BIOS_MAGIC_COMMAND;
+      DEBUG_OUT2("bios routine gets parameter eax=%X and ebx=%X\n",
+                  command, value);
+      value = fsam_bios_routine(command, value);
+      DEBUG_OUT1("bios routine results %X\n", value);
+      return value;
+   }
+   return ~0;
+}
+
+/* pointer to mapped memory*/
+static void *mem_code = NULL;
+
+static inline void fsam_unmap_memory(void)
+{
+   bios_code = 0;
+   if (mem_code) {
+      iounmap(mem_code);
+   }
+}
+
+static inline int fsam_map_memory(void)
+{
+   const unsigned long max_offset = BIOS_CODE_MAPSIZE - BIOS_SIGN_SIZE - PTR_POSITION;
+   unsigned long offset;
+   unsigned int addr;
+   mem_code = ioremap(BIOS_CODE_ADDR, BIOS_CODE_MAPSIZE);
+   if (!mem_code)
+      goto fail;
+   DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n",
+              BIOS_CODE_ADDR, BIOS_CODE_ADDR+BIOS_CODE_MAPSIZE, mem_code);
+   for ( offset = 0; offset < max_offset; offset += ALLIGNED_STEP )
+      if (check_signature((void*)TOUL(mem_code) + offset, bios_sign, BIOS_SIGN_SIZE))
+         break;
+   if (offset >= max_offset)
+     goto fail;
+   DEBUG_OUT1("bios signature found at offset %lx\n", offset);
+   addr = readl((void*)TOUL(mem_code) + offset + PTR_POSITION);
+   if (addr < BIOS_CODE_ADDR) {
+      DEBUG_OUT0("bios routine out of memory range, "
+                 "doing some new memory mapping...\n");
+      iounmap(mem_code);
+      mem_code = NULL;
+      addr &= BIOS_CODE_ALT_MASK;
+      mem_code = ioremap(addr, BIOS_CODE_ALT_MAPSIZE);
+      if (!mem_code)
+         goto fail;
+      DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n",
+                 addr, addr+BIOS_CODE_ALT_MAPSIZE, mem_code);
+      addr &= 0x3FFF;
+   } else
+     addr &= 0xFFFF;
+
+   bios_code = addr + TOUL(mem_code);
+   DEBUG_OUT1("supposed address of bios routine is %lx\n", bios_code);
+   return 1;
+ fail:
+   fsam_unmap_memory();
+   return 0;
+}
+
+/*** ipw2100 loading ***/
+
+static inline void do_ipw2100_loading(int state) 
+{
+  int status;
+  char *mode;
+  char *envp[] = { "HOME=/",
+                   "TERM=linux",
+                   "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+  if (state == RADIO_ON) {
+    char *argv[] = { "/sbin/modprobe", "-s", "-k", "ipw2100", NULL };
+    mode = "loading";
+    status = call_usermodehelper(argv[0], argv, envp, 1);
+  } else {
+    char *argv[] = { "/sbin/rmmod", "ipw2100", NULL };
+    mode = "removing";
+    status = call_usermodehelper(argv[0], argv, envp, 1);
+  }
+  DEBUG_OUT2("%s of ipw2100 module %s\n", mode, status == 0 ? "successful" : "FAILED");
+}
+
+/*** interface stuff ***/
+
+static void rfkill_set_radio(int value)
+{
+   radio = value == RADIO_ON ? fsam_call_bios(BIOS_MAGIC_ON) :
+                               fsam_call_bios(BIOS_MAGIC_OFF);
+   if (autoload) do_ipw2100_loading(radio);
+}
+
+static inline int rfkill_get_radio(void)
+{
+   return radio;
+}
+
+static inline int rfkill_supported(void)
+{
+   return bios_code != 0;
+}
+
+static inline void rfkill_initialize(void) {
+   fsam_map_memory();
+   if (rfkill_supported()) {
+      radio = radio != RADIO_NONE
+              ? ( radio ? RADIO_ON : RADIO_OFF ) /*module parameter*/
+              : ( fsam_call_bios(BIOS_MAGIC_CHECK) == WLAN_ENABLED_IN_BIOS
+                  ? RADIO_ON : RADIO_OFF );
+   }
+}
+
+static inline void rfkill_uninitialize(void) {
+   fsam_unmap_memory();
+}
+
+/*** proc stuff ***/
+
+static inline int common_proc_set_radio(struct file *file, const char *buffer, 
+                                        unsigned long count, void *data)
+{
+   unsigned long len = 7;
+   char newstate[len];
+   len = count < len ? count : len;
+   if ( copy_from_user(newstate, buffer, len) != 0 )
+     return -EFAULT;
+   if ( (*newstate == '1' || *newstate == '0') &&
+        (count == 1 || isspace(newstate[1])) )
+     rfkill_set_radio(*newstate == '1' ? RADIO_ON : RADIO_OFF);
+   else
+   if ( !strncmp(newstate, "on", 2)  &&
+        (count == 2 || isspace(newstate[2])) )
+     rfkill_set_radio(RADIO_ON);
+   else
+   if ( !strncmp(newstate, "off", 3) &&
+        (count == 3 || isspace(newstate[3])) )
+     rfkill_set_radio(RADIO_OFF);
+   else
+   if ( !strncmp(newstate, "resume", 6) &&
+        (count == 6 || isspace(newstate[6])) )
+     rfkill_set_radio(radio);
+   return count;
+}
+
+static inline int common_proc_get_radio(char *page, char **start, off_t offset,
+                                        int count, int *eof, void *data)
+{
+   int len = snprintf(page, count, DRV_DESCRIPTION ", v" DRV_VERSION "\n"
+                                   "  auto-off is %s, auto-load is %s\n",
+                                   ONOFF(autooff), ONOFF(autoload));
+   len += snprintf(page+len, count-len, "  radio state is %s\n",
+                                        RADIO_ONOFF(rfkill_get_radio()));
+   *eof = 1;
+   return len;
+}
+
+#define PROC_DIR    "driver/wireless"
+#define PROC_RADIO  "radio"
+
+static struct proc_dir_entry *dir_base = NULL;
+
+static inline void common_proc_cleanup(void)
+{
+   if (dir_base) {
+      remove_proc_entry(PROC_RADIO, dir_base);
+      remove_proc_entry(PROC_DIR, NULL);
+      dir_base = NULL;
+   }
+}
+
+static inline int common_proc_init(void)
+{
+   struct proc_dir_entry *ent;
+   int err = 0;
+   dir_base = proc_mkdir(PROC_DIR, NULL);
+   if (dir_base == NULL) {
+      printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/" PROC_DIR "\n");
+      err = -ENOMEM;
+      goto fail;
+   }
+   ent = create_proc_entry(PROC_RADIO,
+                           S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP,
+                           dir_base);
+   if (ent) {
+      ent->uid = uid;
+      ent->gid = gid;
+      ent->read_proc = common_proc_get_radio;
+      ent->write_proc = common_proc_set_radio;
+   } else {
+      printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/"
+                      PROC_DIR "/" PROC_RADIO "\n");
+      err = -ENOMEM;
+      goto fail;
+   }
+   return 0;
+ fail:
+   common_proc_cleanup();
+   return err;
+}
+
+/*** module stuff ***/
+
+static int __init common_init(void)
+{ 
+   printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", v" DRV_VERSION "\n");
+   printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+   rfkill_initialize();
+   if (rfkill_supported()) {
+      common_proc_init();
+      if (radio != RADIO_NONE)
+         rfkill_set_radio(radio);
+   } else
+      printk(KERN_INFO DRV_NAME ": no supported wireless hardware found\n");
+   return 0;
+}
+
+static void __exit common_exit(void)
+{
+   if (rfkill_supported() && autooff)
+      rfkill_set_radio(RADIO_OFF);
+   common_proc_cleanup();
+   rfkill_uninitialize();
+   printk(KERN_INFO DRV_NAME ": module removed successfully\n");
+}
+
+module_init(common_init);
+module_exit(common_exit);
+
+#else
+#error This driver is only available for X86 architecture
+#endif
+
+/*
+         1         2         3         4         5         6         7
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/INSTALL
+++ linux-ec2-2.6.32/ubuntu/fsam7400/INSTALL
@@ -0,0 +1,110 @@
+SW RF kill switch for Fujitsu Siemens Amilo M 7400
+Copyright (C) 2006, zwobbl
+For additional information, contact Marcel Naziri <fsam7400@zwobbl.de>
+
+COMPILER REQUIREMENTS
+---------   ------     ----       ---    --       --       -          -
+
+You need to be using GCC v3.0 or higher in order to build the fsam7400 module.
+Using older versions will result in several compilation errors.
+
+
+INSTALLING THE BITS
+------------ -----   -----       ----       ---       --         -
+
+# Unpack the source tarball
+
+% tar xvzf fsam7400-0.x.y.tgz
+% cd fsam7400-0.x.y
+
+Make sure to be root when performing the following operations. Also you must 
+have a kernel source tree installed under /usr/src/linux
+
+# Build the kernel module
+
+% make 
+
+Debug output is enabled by default. This is a good idea if you use the fsam module for 
+the first time, so you get some nice information printed on kernel log. If you don't 
+need the messages anymore, you have to comment out the line CONFIG_IPW2100_DEBUG=y in 
+the Makefile.
+
+# Install the kernel module
+
+% make install
+
+Now you are ready for...
+
+
+LOADING THE DRIVER
+------------ -----   -----       ----       ---       --         -
+
+Also easy to go... :)
+
+% modprobe fsam7400
+
+If you have set "wireless device" enabled in your "Advanced" bios settings of
+your Amilo M 7400 radio should be turned on at this point. So you're done!
+Watch out your kernel log if supported hardware was found. :)
+
+
+RADIO STATE AT LOADING
+
+You can override the wireless bios setting with
+
+% modprobe fsam7400 radio=[0|1]
+
+
+PROC FILESYSTEM
+
+If your hardware is supported by the driver you will get an entry in /proc 
+called driver/wireless/radio which will give you state information by typing
+
+% cat /proc/driver/wireless/radio
+
+You can turn the radio on and off at your will with 
+
+% echo [1|on] > /proc/driver/wireless/radio
+% echo [0|off] > /proc/driver/wireless/radio
+
+The module also recognizes parameters to set the user- and/or group-ID to 
+something other than root, so you don't have to adjust it by hand. 
+Just select your favourite IDs and type
+
+% modprobe fsam7400 uid=1000 gid=500
+
+Note, that /proc/driver/wireless/radio will only be read- and writeable by 
+user & group and only readable by others.
+
+If you want to see debug output on syslog use the following parameter when 
+loading the module 
+
+% modprobe fsam7400 debug=1
+
+
+AUTOMATION FEATURES
+
+By default the driver will turn off the radio automatically short before the 
+module is unloaded. To override this behaviour load the module adding the 
+following parameter
+
+% modprobe fsam7400 autooff=0
+
+Also since 0.4.0 the driver can automatically modprobe the ipw2100 module when
+radio state changes to on and rmmods it when radio is turned off by fsam7400.
+To enable autoload support, use
+
+% modprobe fsam7400 autoload=1
+
+
+HIBERNATION SUPPORT
+
+After hibernation and boot up of the system the wireless radio might be disabled
+again. To revert to the radio state before hibernation just put the following
+in the wakeup script
+
+% echo resume > /proc/driver/wireless/radio
+
+
+
+That's all for now. Have fun with the driver!
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/Kconfig
+++ linux-ec2-2.6.32/ubuntu/fsam7400/Kconfig
@@ -0,0 +1,5 @@
+config FSAM7400
+	tristate "SW RF kill switch for Fujitsu Siemens Amilo M 7400"
+	depends on CHECK_SIGNATURE
+	default m
+	---help---
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/LICENSE
+++ linux-ec2-2.6.32/ubuntu/fsam7400/LICENSE
@@ -0,0 +1,338 @@
+"This software program is licensed subject to the GNU General Public License 
+(GPL). Version 2, June 1991, available at 
+<http://www.fsf.org/copyleft/gpl.html>"
+
+GNU General Public License 
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to 
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure 
+the software is free for all its users. This General Public License applies 
+to most of the Free Software Foundation's software and to any other program 
+whose authors commit to using it. (Some other Free Software Foundation 
+software is covered by the GNU Library General Public License instead.) You 
+can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom 
+to distribute copies of free software (and charge for this service if you 
+wish), that you receive source code or can get it if you want it, that you 
+can change the software or use pieces of it in new free programs; and that 
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to 
+deny you these rights or to ask you to surrender the rights. These 
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or 
+for a fee, you must give the recipients all the rights that you have. You 
+must make sure that they, too, receive or can get the source code. And you 
+must show them these terms so they know their rights.
+ 
+We protect your rights with two steps: (1) copyright the software, and (2) 
+offer you this license which gives you legal permission to copy, distribute 
+and/or modify the software. 
+
+Also, for each author's protection and ours, we want to make certain that 
+everyone understands that there is no warranty for this free software. If 
+the software is modified by someone else and passed on, we want its 
+recipients to know that what they have is not the original, so that any 
+problems introduced by others will not reflect on the original authors' 
+reputations. 
+
+Finally, any free program is threatened constantly by software patents. We 
+wish to avoid the danger that redistributors of a free program will 
+individually obtain patent licenses, in effect making the program 
+proprietary. To prevent this, we have made it clear that any patent must be 
+licensed for everyone's free use or not licensed at all. 
+
+The precise terms and conditions for copying, distribution and modification 
+follow. 
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+   placed by the copyright holder saying it may be distributed under the 
+   terms of this General Public License. The "Program", below, refers to any
+   such program or work, and a "work based on the Program" means either the 
+   Program or any derivative work under copyright law: that is to say, a 
+   work containing the Program or a portion of it, either verbatim or with 
+   modifications and/or translated into another language. (Hereinafter, 
+   translation is included without limitation in the term "modification".) 
+   Each licensee is addressed as "you". 
+
+   Activities other than copying, distribution and modification are not 
+   covered by this License; they are outside its scope. The act of running 
+   the Program is not restricted, and the output from the Program is covered 
+   only if its contents constitute a work based on the Program (independent 
+   of having been made by running the Program). Whether that is true depends
+   on what the Program does. 
+
+1. You may copy and distribute verbatim copies of the Program's source code 
+   as you receive it, in any medium, provided that you conspicuously and 
+   appropriately publish on each copy an appropriate copyright notice and 
+   disclaimer of warranty; keep intact all the notices that refer to this 
+   License and to the absence of any warranty; and give any other recipients 
+   of the Program a copy of this License along with the Program. 
+
+   You may charge a fee for the physical act of transferring a copy, and you 
+   may at your option offer warranty protection in exchange for a fee. 
+
+2. You may modify your copy or copies of the Program or any portion of it, 
+   thus forming a work based on the Program, and copy and distribute such 
+   modifications or work under the terms of Section 1 above, provided that 
+   you also meet all of these conditions: 
+
+   * a) You must cause the modified files to carry prominent notices stating 
+        that you changed the files and the date of any change. 
+
+   * b) You must cause any work that you distribute or publish, that in 
+        whole or in part contains or is derived from the Program or any part 
+        thereof, to be licensed as a whole at no charge to all third parties
+        under the terms of this License. 
+
+   * c) If the modified program normally reads commands interactively when 
+        run, you must cause it, when started running for such interactive 
+        use in the most ordinary way, to print or display an announcement 
+        including an appropriate copyright notice and a notice that there is
+        no warranty (or else, saying that you provide a warranty) and that 
+        users may redistribute the program under these conditions, and 
+        telling the user how to view a copy of this License. (Exception: if 
+        the Program itself is interactive but does not normally print such 
+        an announcement, your work based on the Program is not required to 
+        print an announcement.) 
+
+   These requirements apply to the modified work as a whole. If identifiable 
+   sections of that work are not derived from the Program, and can be 
+   reasonably considered independent and separate works in themselves, then 
+   this License, and its terms, do not apply to those sections when you 
+   distribute them as separate works. But when you distribute the same 
+   sections as part of a whole which is a work based on the Program, the 
+   distribution of the whole must be on the terms of this License, whose 
+   permissions for other licensees extend to the entire whole, and thus to 
+   each and every part regardless of who wrote it. 
+
+   Thus, it is not the intent of this section to claim rights or contest 
+   your rights to work written entirely by you; rather, the intent is to 
+   exercise the right to control the distribution of derivative or 
+   collective works based on the Program. 
+
+   In addition, mere aggregation of another work not based on the Program 
+   with the Program (or with a work based on the Program) on a volume of a 
+   storage or distribution medium does not bring the other work under the 
+   scope of this License. 
+
+3. You may copy and distribute the Program (or a work based on it, under 
+   Section 2) in object code or executable form under the terms of Sections 
+   1 and 2 above provided that you also do one of the following: 
+
+   * a) Accompany it with the complete corresponding machine-readable source 
+        code, which must be distributed under the terms of Sections 1 and 2 
+        above on a medium customarily used for software interchange; or, 
+
+   * b) Accompany it with a written offer, valid for at least three years, 
+        to give any third party, for a charge no more than your cost of 
+        physically performing source distribution, a complete machine-
+        readable copy of the corresponding source code, to be distributed 
+        under the terms of Sections 1 and 2 above on a medium customarily 
+        used for software interchange; or, 
+
+   * c) Accompany it with the information you received as to the offer to 
+        distribute corresponding source code. (This alternative is allowed 
+        only for noncommercial distribution and only if you received the 
+        program in object code or executable form with such an offer, in 
+        accord with Subsection b above.) 
+
+   The source code for a work means the preferred form of the work for 
+   making modifications to it. For an executable work, complete source code 
+   means all the source code for all modules it contains, plus any 
+   associated interface definition files, plus the scripts used to control 
+   compilation and installation of the executable. However, as a special 
+   exception, the source code distributed need not include anything that is 
+   normally distributed (in either source or binary form) with the major 
+   components (compiler, kernel, and so on) of the operating system on which
+   the executable runs, unless that component itself accompanies the 
+   executable. 
+
+   If distribution of executable or object code is made by offering access 
+   to copy from a designated place, then offering equivalent access to copy 
+   the source code from the same place counts as distribution of the source 
+   code, even though third parties are not compelled to copy the source 
+   along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+   expressly provided under this License. Any attempt otherwise to copy, 
+   modify, sublicense or distribute the Program is void, and will 
+   automatically terminate your rights under this License. However, parties 
+   who have received copies, or rights, from you under this License will not
+   have their licenses terminated so long as such parties remain in full 
+   compliance. 
+
+5. You are not required to accept this License, since you have not signed 
+   it. However, nothing else grants you permission to modify or distribute 
+   the Program or its derivative works. These actions are prohibited by law 
+   if you do not accept this License. Therefore, by modifying or 
+   distributing the Program (or any work based on the Program), you 
+   indicate your acceptance of this License to do so, and all its terms and
+   conditions for copying, distributing or modifying the Program or works 
+   based on it. 
+
+6. Each time you redistribute the Program (or any work based on the 
+   Program), the recipient automatically receives a license from the 
+   original licensor to copy, distribute or modify the Program subject to 
+   these terms and conditions. You may not impose any further restrictions 
+   on the recipients' exercise of the rights granted herein. You are not 
+   responsible for enforcing compliance by third parties to this License. 
+
+7. If, as a consequence of a court judgment or allegation of patent 
+   infringement or for any other reason (not limited to patent issues), 
+   conditions are imposed on you (whether by court order, agreement or 
+   otherwise) that contradict the conditions of this License, they do not 
+   excuse you from the conditions of this License. If you cannot distribute 
+   so as to satisfy simultaneously your obligations under this License and 
+   any other pertinent obligations, then as a consequence you may not 
+   distribute the Program at all. For example, if a patent license would 
+   not permit royalty-free redistribution of the Program by all those who 
+   receive copies directly or indirectly through you, then the only way you 
+   could satisfy both it and this License would be to refrain entirely from 
+   distribution of the Program. 
+
+   If any portion of this section is held invalid or unenforceable under any
+   particular circumstance, the balance of the section is intended to apply
+   and the section as a whole is intended to apply in other circumstances. 
+
+   It is not the purpose of this section to induce you to infringe any 
+   patents or other property right claims or to contest validity of any 
+   such claims; this section has the sole purpose of protecting the 
+   integrity of the free software distribution system, which is implemented 
+   by public license practices. Many people have made generous contributions
+   to the wide range of software distributed through that system in 
+   reliance on consistent application of that system; it is up to the 
+   author/donor to decide if he or she is willing to distribute software 
+   through any other system and a licensee cannot impose that choice. 
+
+   This section is intended to make thoroughly clear what is believed to be 
+   a consequence of the rest of this License. 
+
+8. If the distribution and/or use of the Program is restricted in certain 
+   countries either by patents or by copyrighted interfaces, the original 
+   copyright holder who places the Program under this License may add an 
+   explicit geographical distribution limitation excluding those countries, 
+   so that distribution is permitted only in or among countries not thus 
+   excluded. In such case, this License incorporates the limitation as if 
+   written in the body of this License. 
+
+9. The Free Software Foundation may publish revised and/or new versions of 
+   the General Public License from time to time. Such new versions will be 
+   similar in spirit to the present version, but may differ in detail to 
+   address new problems or concerns. 
+
+   Each version is given a distinguishing version number. If the Program 
+   specifies a version number of this License which applies to it and "any 
+   later version", you have the option of following the terms and 
+   conditions either of that version or of any later version published by 
+   the Free Software Foundation. If the Program does not specify a version 
+   number of this License, you may choose any version ever published by the 
+   Free Software Foundation. 
+
+10. If you wish to incorporate parts of the Program into other free programs
+    whose distribution conditions are different, write to the author to ask 
+    for permission. For software which is copyrighted by the Free Software 
+    Foundation, write to the Free Software Foundation; we sometimes make 
+    exceptions for this. Our decision will be guided by the two goals of 
+    preserving the free status of all derivatives of our free software and 
+    of promoting the sharing and reuse of software generally. 
+
+   NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
+    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
+    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
+    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
+    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
+    YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+    NECESSARY SERVICING, REPAIR OR CORRECTION. 
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
+    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
+    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
+    THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
+    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest 
+possible use to the public, the best way to achieve this is to make it free 
+software which everyone can redistribute and change under these terms. 
+
+To do so, attach the following notices to the program. It is safest to 
+attach them to the start of each source file to most effectively convey the
+exclusion of warranty; and each file should have at least the "copyright" 
+line and a pointer to where the full notice is found. 
+
+one line to give the program's name and an idea of what it does.
+Copyright (C) yyyy  name of author
+
+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.
+
+Also add information on how to contact you by electronic and paper mail. 
+
+If the program is interactive, make it output a short notice like this when 
+it starts in an interactive mode: 
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 
+with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free 
+software, and you are welcome to redistribute it under certain conditions; 
+type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate 
+parts of the General Public License. Of course, the commands you use may be 
+called something other than 'show w' and 'show c'; they could even be 
+mouse-clicks or menu items--whatever suits your program. 
+
+You should also get your employer (if you work as a programmer) or your 
+school, if any, to sign a "copyright disclaimer" for the program, if 
+necessary. Here is a sample; alter the names: 
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
+'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into 
+proprietary programs. If your program is a subroutine library, you may 
+consider it more useful to permit linking proprietary applications with the 
+library. If this is what you want to do, use the GNU Library General Public 
+License instead of this License.
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/CHANGELOG
+++ linux-ec2-2.6.32/ubuntu/fsam7400/CHANGELOG
@@ -0,0 +1,34 @@
+Nov 22 2008 Changes in 0.5.2 by legolas558
+* fixed some missing include files
+
+Sep 22 2006 Changes in 0.5.1
+* Fix: possible null pointer dereference in proc code
+* Fix: module exit code was mistakenly disabled
+
+Sep 22 2006 Changes in 0.5.0
+* fixed compilation problems with kernel 2.6.18
+* debug-output enabling via module parameter
+* hibernation support: reconstruct last radio state on resume
+* disabled autoload option by default
+
+Jul 16 2006 Changes in 0.4.1
+* new Makefile fixing problems with kernel 2.6.17
+* several bug fixes and compiler cleanups
+
+Aug 20 2004 Changes in 0.4.0
+* several bug fixes and compiler cleanups
+* UID/GID for procfs entry selectable via module parameter
+* Autoload support: fsam7400 modprobes and rmmods ipw2100 automatically
+  depending on radio state
+
+Apr 15 2004 Changes in 0.3.0
+* Fix: radio state was not displayed properly
+* some proc improvements
+* finished code for alternative routine address calculation
+* debug-output selectable at compile-time with CONFIG_IPW2100_DEBUG define
+  for smaller module size if no debug is needed ;)
+
+Apr 9 2004 Changes in 0.2.1
+* Initial release
+* Determines if wireless device is enabled by default Bios-settings
+* Auto-off functionality
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/README
+++ linux-ec2-2.6.32/ubuntu/fsam7400/README
@@ -0,0 +1,60 @@
+SW RF kill switch for Fujitsu Siemens Amilo M 7400 / Maxdata 7000DX
+and compatible hardware.
+
+Please be sure that CONFIG_CHECK_SIGNATURE=y in your kernel configuration!
+Otherwise this module will not compile.
+
+Nov 22, 2008 - Release 0.5.2
+
+This package, with minor modifications from zwobbl's 0.5.1, was created
+by legolas558.
+
+More information at:
+http://legolas558.iragan.com/fsam7400
+
+Sep 24, 2006 - Release 0.5.1
+------------ -----   -----       ----       ---       --         -
+
+* Fix: possible null pointer dereference in proc code
+
+* Fix: module exit code was mistakenly disabled
+
+
+for prior changes see CHANGELOG
+
+
+TODO
+------------ -----   -----       ----       ---       --         -
+
+* Fix bugs (if there are any ;))
+
+
+------------ -----   -----       ----       ---       --         -
+
+Have a look in INSTALL for further details to get things working!
+
+
+License
+------------ -----   -----       ----       ---       --         -
+
+  Copyright(c) 2006 zwobbl. All rights reserved.
+
+  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.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  Marcel Naziri <fsam7400@zwobbl.de>
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/BOM
+++ linux-ec2-2.6.32/ubuntu/fsam7400/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	http://www.iragan.com/linux/fsam7400/
+Current Version:	0.5.2 (2008 Nov 22)
--- linux-ec2-2.6.32.orig/ubuntu/fsam7400/FILES
+++ linux-ec2-2.6.32/ubuntu/fsam7400/FILES
@@ -0,0 +1,6 @@
+CHANGELOG	Recently changes logged
+FILES		This file
+fsam7400.c	The source code, what else... :)
+INSTALL		Installation instructions
+Makefile	Makefile to build, install, uninstall the module
+README		don't forget to read it
--- linux-ec2-2.6.32.orig/ubuntu/lirc/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/Makefile
@@ -0,0 +1,23 @@
+#include $(src)/../../.config
+
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)
+
+obj-$(CONFIG_LIRC_DEV)		+= lirc_dev/
+obj-$(CONFIG_LIRC_ATIUSB)	+= lirc_atiusb/
+obj-$(CONFIG_LIRC_BT829)	+= lirc_bt829/
+obj-$(CONFIG_LIRC_ENE0100)	+= lirc_ene0100/
+obj-$(CONFIG_LIRC_I2C)		+= lirc_i2c/
+obj-$(CONFIG_LIRC_IGORPLUGUSB)	+= lirc_igorplugusb/
+obj-$(CONFIG_LIRC_IMON)		+= lirc_imon/
+obj-$(CONFIG_LIRC_IT87)		+= lirc_it87/
+obj-$(CONFIG_LIRC_ITE8709)	+= lirc_ite8709/
+obj-$(CONFIG_LIRC_MCEUSB)	+= lirc_mceusb/
+obj-$(CONFIG_LIRC_PARALLEL)	+= lirc_parallel/
+obj-$(CONFIG_LIRC_SASEM)	+= lirc_sasem/
+obj-$(CONFIG_LIRC_SERIAL)	+= lirc_serial/
+obj-$(CONFIG_LIRC_SIR)		+= lirc_sir/
+obj-$(CONFIG_LIRC_STREAMZAP)	+= lirc_streamzap/
+obj-$(CONFIG_LIRC_TTUSBIR)	+= lirc_ttusbir/
+obj-$(CONFIG_LIRC_GPIO)		+= lirc_gpio/
+obj-$(CONFIG_LIRC_TTUSBIR)	+= lirc_ttusbir/
+obj-$(CONFIG_LIRC_WPC8769L)	+= lirc_wpc8769l/
--- linux-ec2-2.6.32.orig/ubuntu/lirc/Kconfig
+++ linux-ec2-2.6.32/ubuntu/lirc/Kconfig
@@ -0,0 +1,88 @@
+config LIRC_DEV
+	tristate "LIRC Device support"
+	default m
+
+config LIRC_ATIUSB
+	tristate "LIRC ATI RF Remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_BT829
+	tristate "LIRC BT829"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_ENE0100
+	tristate "LIRC ENE0100"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_I2C
+	tristate "LIRC I2C interface remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_IGORPLUGUSB
+	tristate "LIRC IGOR custom remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_IMON
+	tristate "LIRC Imon remote or pad"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_IT87
+	tristate "LIRC IT87"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_ITE8709
+	tristate "LIRC ITE8709"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_MCEUSB
+	tristate "LIRC Microsoft Media Center Remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_PARALLEL
+	tristate "LIRC Parallel port custom remote"
+	default n
+	depends on LIRC_DEV
+
+config LIRC_SASEM
+	tristate "LIRC Sasem"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_SERIAL
+	tristate "LIRC Serial port remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_SIR
+	tristate "LIRC Laptop port IR (SIR))"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_STREAMZAP
+	tristate "LIRC Streamzap remote"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_TTUSBIR
+	tristate "LIRC TT USB IR device"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_CONFIG_LIRC_WPC8769L
+	tristate "LIRC WPC8769L device"
+	default m
+	depends on LIRC_DEV
+
+config LIRC_GPIO
+	tristate "LIRC TV Card GPIO remote"
+	default n
+	depends on LIRC_DEV
--- linux-ec2-2.6.32.orig/ubuntu/lirc/kcompat.h
+++ linux-ec2-2.6.32/ubuntu/lirc/kcompat.h
@@ -0,0 +1,402 @@
+/*      $Id: kcompat.h,v 5.44 2009/03/22 08:45:47 lirc Exp $      */
+
+#ifndef _KCOMPAT_H
+#define _KCOMPAT_H
+
+#include <linux/version.h>
+
+#ifndef __func__
+#define __func__ __FUNCTION__
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#define LIRC_THIS_MODULE(x) x,
+#else /* >= 2.6.16 */
+#define LIRC_THIS_MODULE(x)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+#include <linux/device.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#define LIRC_HAVE_DEVFS
+#define LIRC_HAVE_DEVFS_26
+#endif
+
+#define LIRC_HAVE_SYSFS
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
+
+typedef struct class_simple lirc_class_t;
+
+static inline lirc_class_t *class_create(struct module *owner, char *name)
+{
+	return class_simple_create(owner, name);
+}
+
+static inline void class_destroy(lirc_class_t *cls)
+{
+	class_simple_destroy(cls);
+}
+
+#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \
+	class_simple_device_add(cs, dev, parent, fmt, ## args)
+
+static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt)
+{
+	class_simple_device_remove(devt);
+}
+
+#else /* >= 2.6.13 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
+
+#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \
+	class_device_create(cs, dev, parent, fmt, ## args)
+
+#else /* >= 2.6.15 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+
+#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \
+	class_device_create(cs, NULL, dev, parent, fmt, ## args)
+
+#else /* >= 2.6.26 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
+
+#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \
+	device_create(cs, parent, dev, fmt, ## args)
+
+#else /* >= 2.6.27 */
+
+#define lirc_device_create device_create
+
+#endif /* >= 2.6.27 */
+
+#endif /* >= 2.6.26 */
+
+#define LIRC_DEVFS_PREFIX
+
+#endif /* >= 2.6.15 */
+
+typedef struct class lirc_class_t;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+
+#define lirc_device_destroy class_device_destroy
+
+#else
+
+#define lirc_device_destroy device_destroy
+
+#endif
+
+#endif /* >= 2.6.13 */
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#define LIRC_HAVE_DEVFS
+#define LIRC_HAVE_DEVFS_24
+#endif
+
+#ifndef LIRC_DEVFS_PREFIX
+#define LIRC_DEVFS_PREFIX "usb/"
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+static inline void del_timer_sync(struct timer_list *timerlist)
+{
+	start_bh_atomic();
+	del_timer(timerlist);
+	end_bh_atomic();
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#ifdef daemonize
+#undef daemonize
+#endif
+#define daemonize(name) do {		\
+					\
+	lock_kernel();			\
+					\
+	exit_mm(current);		\
+	exit_files(current);		\
+	exit_fs(current);		\
+	current->session = 1;		\
+	current->pgrp = 1;		\
+	current->euid = 0;		\
+	current->tty = NULL;		\
+	sigfillset(&current->blocked);	\
+					\
+	strcpy(current->comm, name);	\
+					\
+	unlock_kernel();		\
+					\
+} while (0)
+
+/* Not sure when this was introduced, sometime during 2.5.X */
+#define MODULE_PARM_int(x) MODULE_PARM(x, "i")
+#define MODULE_PARM_bool(x) MODULE_PARM(x, "i")
+#define MODULE_PARM_long(x) MODULE_PARM(x, "l")
+#define module_param(x, y, z) MODULE_PARM_##y(x)
+#else
+#include <linux/moduleparam.h>
+#endif /* Linux < 2.6.0 */
+
+/* DevFS header */
+#if defined(LIRC_HAVE_DEVFS)
+#include <linux/devfs_fs_kernel.h>
+#endif
+
+#ifdef LIRC_HAVE_DEVFS_24
+#ifdef register_chrdev
+#undef register_chrdev
+#endif
+#define register_chrdev devfs_register_chrdev
+#ifdef unregister_chrdev
+#undef unregister_chrdev
+#endif
+#define unregister_chrdev devfs_unregister_chrdev
+#endif /* DEVFS 2.4 */
+
+#ifndef LIRC_HAVE_SYSFS
+#define class_destroy(x) do { } while (0)
+#define class_create(x, y) NULL
+#define lirc_device_destroy(x, y) do { } while (0)
+#define lirc_device_create(x, y, z, xx, yy, zz) 0
+#define IS_ERR(x) 0
+typedef struct class_simple
+{
+	int notused;
+} lirc_class_t;
+#endif /* No SYSFS */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
+#define KERNEL_2_5
+
+/*
+ * We still are using MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT in the set_use_inc
+ * function of all modules for 2.4 kernel compatibility.
+ *
+ * For 2.6 kernels reference counting is done in lirc_dev by
+ * try_module_get()/module_put() because the old approach is racy.
+ *
+ */
+#ifdef MOD_INC_USE_COUNT
+#undef MOD_INC_USE_COUNT
+#endif
+#define MOD_INC_USE_COUNT
+
+#ifdef MOD_DEC_USE_COUNT
+#undef MOD_DEC_USE_COUNT
+#endif
+#define MOD_DEC_USE_COUNT
+
+#ifdef EXPORT_NO_SYMBOLS
+#undef EXPORT_NO_SYMBOLS
+#endif
+#define EXPORT_NO_SYMBOLS
+
+#else  /* Kernel < 2.5.0 */
+
+static inline int try_module_get(struct module *module)
+{
+	return 1;
+}
+
+static inline void module_put(struct module *module)
+{
+}
+
+#endif /* Kernel >= 2.5.0 */
+
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(x)
+#endif
+
+#ifndef MODULE_PARM_DESC
+#define MODULE_PARM_DESC(x, y)
+#endif
+
+#ifndef MODULE_ALIAS_CHARDEV_MAJOR
+#define MODULE_ALIAS_CHARDEV_MAJOR(x)
+#endif
+
+#ifndef MODULE_DEVICE_TABLE
+#define MODULE_DEVICE_TABLE(x, y)
+#endif
+
+#include <linux/interrupt.h>
+#ifndef IRQ_RETVAL
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+
+#ifndef MOD_IN_USE
+#ifdef CONFIG_MODULE_UNLOAD
+#define MOD_IN_USE module_refcount(THIS_MODULE)
+#else
+#error "LIRC modules currently require"
+#error "  'Loadable module support  --->  Module unloading'"
+#error "to be enabled in the kernel"
+#endif
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#if !defined(local_irq_save)
+#define local_irq_save(flags) do { save_flags(flags); cli(); } while (0)
+#endif
+#if !defined(local_irq_restore)
+#define local_irq_restore(flags) do { restore_flags(flags); } while (0)
+#endif
+#endif
+
+#if KERNEL_VERSION(2, 4, 0) <= LINUX_VERSION_CODE
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22)
+#include <linux/pci.h>
+static inline char *pci_name(struct pci_dev *pdev)
+{
+	return pdev->slot_name;
+}
+#endif /* kernel < 2.4.22 */
+#endif /* kernel >= 2.4.0 */
+
+/*************************** I2C specific *****************************/
+#include <linux/i2c.h>
+
+#ifndef I2C_CLIENT_END
+#error "********************************************************"
+#error " Sorry, this driver needs the new I2C stack.            "
+#error " You can get it at http://www2.lm-sensors.nu/~lm78/.    "
+#error "********************************************************"
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
+
+#undef i2c_get_clientdata
+#define i2c_get_clientdata(client) ((client)->data)
+
+
+#undef i2c_set_clientdata
+#define i2c_set_clientdata(client_ptr, new_data) do { \
+	(client_ptr)->data = new_data; \
+} while (0)
+
+
+#endif
+
+/* removed in 2.6.14 */
+#ifndef I2C_ALGO_BIT
+#   define I2C_ALGO_BIT 0
+#endif
+
+/* removed in 2.6.16 */
+#ifndef I2C_DRIVERID_EXP3
+#  define I2C_DRIVERID_EXP3 0xf003
+#endif
+
+/*************************** USB specific *****************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#include <linux/usb.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
+static inline int usb_kill_urb(struct urb *urb)
+{
+	return usb_unlink_urb(urb);
+}
+#endif
+
+/* removed in 2.6.14 */
+#ifndef URB_ASYNC_UNLINK
+#define URB_ASYNC_UNLINK 0
+#endif
+#endif
+
+/*************************** bttv specific ****************************/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) /* BTTV_* -> BTTV_BOARD_* */
+#define BTTV_BOARD_UNKNOWN         BTTV_UNKNOWN
+#define BTTV_BOARD_PXELVWPLTVPAK   BTTV_PXELVWPLTVPAK
+#define BTTV_BOARD_PXELVWPLTVPRO   BTTV_PXELVWPLTVPRO
+#define BTTV_BOARD_PV_BT878P_9B    BTTV_PV_BT878P_9B
+#define BTTV_BOARD_PV_BT878P_PLUS  BTTV_PV_BT878P_PLUS
+#define BTTV_BOARD_AVERMEDIA       BTTV_AVERMEDIA
+#define BTTV_BOARD_AVPHONE98       BTTV_AVPHONE98
+#define BTTV_BOARD_AVERMEDIA98     BTTV_AVERMEDIA98
+#define BTTV_BOARD_CHRONOS_VS2     BTTV_CHRONOS_VS2
+#define BTTV_BOARD_MIRO            BTTV_MIRO
+#define BTTV_BOARD_DYNALINK        BTTV_DYNALINK
+#define BTTV_BOARD_WINVIEW_601     BTTV_WINVIEW_601
+#ifdef BTTV_KWORLD
+#define BTTV_BOARD_KWORLD          BTTV_KWORLD
+#endif
+#define BTTV_BOARD_MAGICTVIEW061   BTTV_MAGICTVIEW061
+#define BTTV_BOARD_MAGICTVIEW063   BTTV_MAGICTVIEW063
+#define BTTV_BOARD_PHOEBE_TVMAS    BTTV_PHOEBE_TVMAS
+#ifdef BTTV_BESTBUY_EASYTV2
+#define BTTV_BOARD_BESTBUY_EASYTV  BTTV_BESTBUY_EASYTV
+#define BTTV_BOARD_BESTBUY_EASYTV2 BTTV_BESTBUY_EASYTV2
+#endif
+#define BTTV_BOARD_FLYVIDEO        BTTV_FLYVIDEO
+#define BTTV_BOARD_FLYVIDEO_98     BTTV_FLYVIDEO_98
+#define BTTV_BOARD_TYPHOON_TVIEW   BTTV_TYPHOON_TVIEW
+#ifdef BTTV_FLYVIDEO_98FM
+#define BTTV_BOARD_FLYVIDEO_98FM   BTTV_FLYVIDEO_98FM
+#endif
+#define BTTV_BOARD_WINFAST2000     BTTV_WINFAST2000
+#ifdef BTTV_GVBCTV5PCI
+#define BTTV_BOARD_GVBCTV5PCI      BTTV_GVBCTV5PCI
+#endif
+#endif  /* end BTTV_* -> BTTV_BOARD_* */
+
+
+/******************************* pm.h *********************************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
+typedef u32 pm_message_t;
+#endif /* kernel < 2.6.11 */
+#endif /* kernel >= 2.6.0 */
+
+/*************************** interrupt.h ******************************/
+/* added in 2.6.18, old defines removed in 2.6.24 */
+#ifndef IRQF_DISABLED
+#define IRQF_DISABLED SA_INTERRUPT
+#endif
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+/*************************** spinlock.h *******************************/
+/* added in 2.6.11 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
+#endif
+
+/***************************** slab.h *********************************/
+/* added in 2.6.14 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
+static inline void *kzalloc(size_t size, gfp_t flags)
+{
+        void *ret = kmalloc(size, flags);
+        if (ret)
+                memset(ret, 0, size);
+        return ret;
+}
+#endif
+
+/****************************** fs.h **********************************/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+static inline unsigned iminor(struct inode *inode)
+{
+	return MINOR(inode->i_rdev);
+}
+#endif
+
+#endif /* _KCOMPAT_H */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc.h
@@ -0,0 +1,105 @@
+/*      $Id: lirc.h,v 5.19 2009/08/29 07:52:41 lirc Exp $      */
+
+#ifndef _LINUX_LIRC_H
+#define _LINUX_LIRC_H
+
+#if defined(__linux__)
+#include <linux/ioctl.h>
+#elif defined(_NetBSD_)
+#include <sys/ioctl.h> 
+#elif defined(_CYGWIN_)
+#define __USE_LINUX_IOCTL_DEFS
+#include <sys/ioctl.h>
+#endif
+
+#define PULSE_BIT  0x01000000
+#define PULSE_MASK 0x00FFFFFF
+
+typedef int lirc_t;
+
+/*** lirc compatible hardware features ***/
+
+#define LIRC_MODE2SEND(x) (x)
+#define LIRC_SEND2MODE(x) (x)
+#define LIRC_MODE2REC(x) ((x) << 16)
+#define LIRC_REC2MODE(x) ((x) >> 16)
+
+#define LIRC_MODE_RAW                  0x00000001
+#define LIRC_MODE_PULSE                0x00000002
+#define LIRC_MODE_MODE2                0x00000004
+#define LIRC_MODE_CODE                 0x00000008
+#define LIRC_MODE_LIRCCODE             0x00000010
+#define LIRC_MODE_STRING               0x00000020
+
+
+#define LIRC_CAN_SEND_RAW              LIRC_MODE2SEND(LIRC_MODE_RAW)
+#define LIRC_CAN_SEND_PULSE            LIRC_MODE2SEND(LIRC_MODE_PULSE)
+#define LIRC_CAN_SEND_MODE2            LIRC_MODE2SEND(LIRC_MODE_MODE2)
+#define LIRC_CAN_SEND_CODE             LIRC_MODE2SEND(LIRC_MODE_CODE)
+#define LIRC_CAN_SEND_LIRCCODE         LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
+#define LIRC_CAN_SEND_STRING           LIRC_MODE2SEND(LIRC_MODE_STRING)
+
+#define LIRC_CAN_SEND_MASK             0x0000003f
+
+#define LIRC_CAN_SET_SEND_CARRIER      0x00000100
+#define LIRC_CAN_SET_SEND_DUTY_CYCLE   0x00000200
+#define LIRC_CAN_SET_TRANSMITTER_MASK  0x00000400
+
+#define LIRC_CAN_REC_RAW               LIRC_MODE2REC(LIRC_MODE_RAW)
+#define LIRC_CAN_REC_PULSE             LIRC_MODE2REC(LIRC_MODE_PULSE)
+#define LIRC_CAN_REC_MODE2             LIRC_MODE2REC(LIRC_MODE_MODE2)
+#define LIRC_CAN_REC_CODE              LIRC_MODE2REC(LIRC_MODE_CODE)
+#define LIRC_CAN_REC_LIRCCODE          LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
+#define LIRC_CAN_REC_STRING            LIRC_MODE2REC(LIRC_MODE_STRING)
+
+#define LIRC_CAN_REC_MASK              LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
+
+#define LIRC_CAN_SET_REC_CARRIER       (LIRC_CAN_SET_SEND_CARRIER << 16)
+#define LIRC_CAN_SET_REC_DUTY_CYCLE    (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
+
+#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
+#define LIRC_CAN_SET_REC_CARRIER_RANGE    0x80000000
+#define LIRC_CAN_GET_REC_RESOLUTION       0x20000000
+
+#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
+#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)
+
+#define LIRC_CAN_NOTIFY_DECODE            0x01000000
+
+/*** IOCTL commands for lirc driver ***/
+
+#define LIRC_GET_FEATURES              _IOR('i', 0x00000000, unsigned long)
+
+#define LIRC_GET_SEND_MODE             _IOR('i', 0x00000001, unsigned long)
+#define LIRC_GET_REC_MODE              _IOR('i', 0x00000002, unsigned long)
+#define LIRC_GET_SEND_CARRIER          _IOR('i', 0x00000003, unsigned int)
+#define LIRC_GET_REC_CARRIER           _IOR('i', 0x00000004, unsigned int)
+#define LIRC_GET_SEND_DUTY_CYCLE       _IOR('i', 0x00000005, unsigned int)
+#define LIRC_GET_REC_DUTY_CYCLE        _IOR('i', 0x00000006, unsigned int)
+#define LIRC_GET_REC_RESOLUTION        _IOR('i', 0x00000007, unsigned int)
+
+/* code length in bits, currently only for LIRC_MODE_LIRCCODE */
+#define LIRC_GET_LENGTH                _IOR('i', 0x0000000f, unsigned long)
+
+#define LIRC_SET_SEND_MODE             _IOW('i', 0x00000011, unsigned long)
+#define LIRC_SET_REC_MODE              _IOW('i', 0x00000012, unsigned long)
+/* Note: these can reset the according pulse_width */
+#define LIRC_SET_SEND_CARRIER          _IOW('i', 0x00000013, unsigned int)
+#define LIRC_SET_REC_CARRIER           _IOW('i', 0x00000014, unsigned int)
+#define LIRC_SET_SEND_DUTY_CYCLE       _IOW('i', 0x00000015, unsigned int)
+#define LIRC_SET_REC_DUTY_CYCLE        _IOW('i', 0x00000016, unsigned int)
+#define LIRC_SET_TRANSMITTER_MASK      _IOW('i', 0x00000017, unsigned int)
+
+/*
+ * to set a range use
+ * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the
+ * lower bound first and later
+ * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound
+ */
+
+#define LIRC_SET_REC_DUTY_CYCLE_RANGE  _IOW('i', 0x0000001e, unsigned int)
+#define LIRC_SET_REC_CARRIER_RANGE     _IOW('i', 0x0000001f, unsigned int)
+
+#define LIRC_NOTIFY_DECODE             _IO('i', 0x00000020)
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_mceusb/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_mceusb/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_MCEUSB)	+= lirc_mceusb.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_mceusb/lirc_mceusb.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_mceusb/lirc_mceusb.c
@@ -0,0 +1,1289 @@
+/*
+ * LIRC driver for Windows Media Center Edition USB Infrared Transceivers
+ *
+ * (C) by Martin A. Blatter <martin_a_blatter@yahoo.com>
+ *
+ * Transmitter support and reception code cleanup.
+ * (C) by Daniel Melander <lirc@rajidae.se>
+ *
+ * Original lirc_mceusb driver for 1st-gen device:
+ * Copyright (c) 2003-2004 Dan Conti <dconti@acm.wwu.edu>
+ *
+ * Original lirc_mceusb driver deprecated in favor of this driver, which
+ * supports the 1st-gen device now too. Transmitting on the 1st-gen device
+ * only functions on port #2 at the moment.
+ *
+ * Support for 1st-gen device added June 2009,
+ * by Jarod Wilson <jarod@wilsonet.com>
+ *
+ * Initial transmission support for 1st-gen device added August 2009,
+ * by Patrick Calhoun <phineas@ou.edu>
+ *
+ * Derived from ATI USB driver by Paul Miller and the original
+ * MCE USB driver by Dan Conti ((and now including chunks of the latter
+ * relevant to the 1st-gen device initialization)
+ *
+ * This driver will only work reliably with kernel version 2.6.10
+ * or higher, probably because of differences in USB device enumeration
+ * in the kernel code. Device initialization fails most of the time
+ * with earlier kernel versions.
+ *
+ **********************************************************************
+ *
+ * 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/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
+#error "*******************************************************"
+#error "Sorry, this driver needs kernel version 2.6.5 or higher"
+#error "*******************************************************"
+#endif
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#define DRIVER_VERSION	"1.90"
+#define DRIVER_AUTHOR	"Daniel Melander <lirc@rajidae.se>, " \
+			"Martin Blatter <martin_a_blatter@yahoo.com>, " \
+			"Dan Conti <dconti@acm.wwu.edu>"
+#define DRIVER_DESC	"Windows Media Center Edition USB IR Transceiver " \
+			"driver for LIRC"
+#define DRIVER_NAME	"lirc_mceusb"
+
+#define USB_BUFLEN	32	/* USB reception buffer length */
+#define LIRCBUF_SIZE	256	/* LIRC work buffer length */
+
+/* MCE constants */
+#define MCE_CMDBUF_SIZE	384 /* MCE Command buffer length */
+#define MCE_TIME_UNIT	50 /* Approx 50us resolution */
+#define MCE_CODE_LENGTH	5 /* Normal length of packet (with header) */
+#define MCE_PACKET_SIZE	4 /* Normal length of packet (without header) */
+#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
+#define MCE_CONTROL_HEADER 0x9F /* MCE status header */
+#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
+#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
+#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */
+#define MCE_PULSE_BIT	0x80 /* Pulse bit, MSB set == PULSE else SPACE */
+#define MCE_PULSE_MASK	0x7F /* Pulse mask */
+#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */
+#define MCE_PACKET_LENGTH_MASK  0x7F /* Pulse mask */
+
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG fmt, ## args);	\
+	} while (0)
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+#define RECV_FLAG_IN_PROGRESS	3
+#define RECV_FLAG_COMPLETE	4
+
+#define MCEUSB_INBOUND		1
+#define MCEUSB_OUTBOUND		2
+
+#define VENDOR_PHILIPS		0x0471
+#define VENDOR_SMK		0x0609
+#define VENDOR_TATUNG		0x1460
+#define VENDOR_GATEWAY		0x107b
+#define VENDOR_SHUTTLE		0x1308
+#define VENDOR_SHUTTLE2		0x051c
+#define VENDOR_MITSUMI		0x03ee
+#define VENDOR_TOPSEED		0x1784
+#define VENDOR_RICAVISION	0x179d
+#define VENDOR_ITRON		0x195d
+#define VENDOR_FIC		0x1509
+#define VENDOR_LG		0x043e
+#define VENDOR_MICROSOFT	0x045e
+#define VENDOR_FORMOSA		0x147a
+#define VENDOR_FINTEK		0x1934
+#define VENDOR_PINNACLE		0x2304
+#define VENDOR_ECS		0x1019
+#define VENDOR_WISTRON		0x0fb8
+#define VENDOR_COMPRO		0x185b
+#define VENDOR_NORTHSTAR	0x04eb
+
+static struct usb_device_id mceusb_dev_table[] = {
+	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+	/* Philips Infrared Transceiver - Sahara branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
+	/* Philips Infrared Transceiver - HP branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
+	/* Philips SRM5100 */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
+	/* Philips Infrared Transceiver - Omaura */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
+	/* Philips Infrared Transceiver - Spinel plus */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
+	/* Philips eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+	/* SMK/Toshiba G83C0004D410 */
+	{ USB_DEVICE(VENDOR_SMK, 0x031d) },
+	/* SMK eHome Infrared Transceiver (Sony VAIO) */
+	{ USB_DEVICE(VENDOR_SMK, 0x0322) },
+	/* bundled with Hauppauge PVR-150 */
+	{ USB_DEVICE(VENDOR_SMK, 0x0334) },
+	/* Tatung eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
+	/* Gateway eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
+	/* Mitsumi */
+	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+	/* Topseed HP eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
+	/* Ricavision internal Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
+	/* Itron ione Libra Q-11 */
+	{ USB_DEVICE(VENDOR_ITRON, 0x7002) },
+	/* FIC eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FIC, 0x9242) },
+	/* LG eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_LG, 0x9803) },
+	/* Microsoft MCE Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
+	/* Formosa eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
+	/* Formosa aim / Trust MCE Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
+	/* Formosa Industrial Computing / Beanbag Emulation Device */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
+	/* Formosa Industrial Computing AIM IR605/A */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
+	/* Fintek eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
+	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
+	/* Pinnacle Remote Kit */
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+	/* Elitegroup Computer Systems IR */
+	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
+	/* Wistron Corp. eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_WISTRON, 0x0002) },
+	/* Compro K100 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3020) },
+	/* Compro K100 v2 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3082) },
+	/* Northstar Systems eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
+	/* Terminating entry */
+	{ }
+};
+
+static struct usb_device_id pinnacle_list[] = {
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+	{}
+};
+
+static struct usb_device_id microsoft_gen1_list[] = {
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+	{}
+};
+
+static struct usb_device_id transmitter_mask_list[] = {
+	{ USB_DEVICE(VENDOR_SMK, 0x031d) },
+	{ USB_DEVICE(VENDOR_SMK, 0x0322) },
+	{ USB_DEVICE(VENDOR_SMK, 0x0334) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+	{}
+};
+
+/* data structure for each usb transceiver */
+struct mceusb_dev {
+
+	/* usb */
+	struct usb_device *usbdev;
+	struct urb *urb_in;
+	int devnum;
+	struct usb_endpoint_descriptor *usb_ep_in;
+	struct usb_endpoint_descriptor *usb_ep_out;
+
+	/* buffers and dma */
+	unsigned char *buf_in;
+	unsigned int len_in;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
+	unsigned int overflow_len;
+
+	/* lirc */
+	struct lirc_driver *d;
+	lirc_t lircdata;
+	unsigned char is_pulse;
+	struct {
+		u32 connected:1;
+		u32 pinnacle:1;
+		u32 transmitter_mask_inverted:1;
+		u32 microsoft_gen1:1;
+		u32 reserved:28;
+	} flags;
+
+	unsigned char transmitter_mask;
+	unsigned int carrier_freq;
+
+	/* handle sending (init strings) */
+	int send_flags;
+	wait_queue_head_t wait_out;
+
+	struct mutex lock;
+};
+
+/* init strings */
+static char init1[] = {0x00, 0xff, 0xaa, 0xff, 0x0b};
+static char init2[] = {0xff, 0x18};
+
+static char pin_init1[] = { 0x9f, 0x07};
+static char pin_init2[] = { 0x9f, 0x13};
+static char pin_init3[] = { 0x9f, 0x0d};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
+static unsigned long usecs_to_jiffies(const unsigned int u)
+{
+	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+	return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+	return u * (HZ / USEC_PER_SEC);
+#else
+	return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
+#endif
+}
+#endif
+static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, int len)
+{
+	char codes[USB_BUFLEN * 3 + 1];
+	int i;
+
+	if (len <= 0)
+		return;
+
+	if (ir->flags.microsoft_gen1 && len <= 2)
+		return;
+
+	for (i = 0; i < len && i < USB_BUFLEN; i++)
+		snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF);
+
+	printk(KERN_INFO "" DRIVER_NAME "[%d]: data received %s (length=%d)\n",
+		ir->devnum, codes, len);
+}
+
+static void usb_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (ir) {
+		len = urb->actual_length;
+
+		dprintk(DRIVER_NAME
+			"[%d]: callback called (status=%d len=%d)\n",
+			ir->devnum, urb->status, len);
+
+		if (debug)
+			mceusb_dev_printdata(ir, urb->transfer_buffer, len);
+	}
+
+}
+
+/* request incoming or send outgoing usb packet - used to initialize remote */
+static void request_packet_async(struct mceusb_dev *ir,
+				 struct usb_endpoint_descriptor *ep,
+				 unsigned char *data, int size, int urb_type)
+{
+	int res;
+	struct urb *async_urb;
+	unsigned char *async_buf;
+
+	if (urb_type) {
+		async_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (unlikely(!async_urb))
+			return;
+
+		async_buf = kmalloc(size, GFP_KERNEL);
+		if (!async_buf) {
+			usb_free_urb(async_urb);
+			return;
+		}
+
+		if (urb_type == MCEUSB_OUTBOUND) {
+			/* outbound data */
+			usb_fill_int_urb(async_urb, ir->usbdev,
+				usb_sndintpipe(ir->usbdev,
+					ep->bEndpointAddress),
+				async_buf, size,
+				(usb_complete_t) usb_async_callback,
+				ir, ep->bInterval);
+			memcpy(async_buf, data, size);
+		} else {
+			/* inbound data */
+			usb_fill_int_urb(async_urb, ir->usbdev,
+				usb_rcvintpipe(ir->usbdev,
+					ep->bEndpointAddress),
+				async_buf, size,
+				(usb_complete_t) usb_async_callback,
+				ir, ep->bInterval);
+		}
+		async_urb->transfer_flags = URB_ASYNC_UNLINK;
+	} else {
+		/* standard request */
+		async_urb = ir->urb_in;
+		ir->send_flags = RECV_FLAG_IN_PROGRESS;
+	}
+
+	dprintk(DRIVER_NAME "[%d]: receive request called (size=%#x)\n",
+		ir->devnum, size);
+
+	async_urb->transfer_buffer_length = size;
+	async_urb->dev = ir->usbdev;
+
+	res = usb_submit_urb(async_urb, GFP_ATOMIC);
+	if (res) {
+		dprintk(DRIVER_NAME "[%d]: receive request FAILED! (res=%d)\n",
+			ir->devnum, res);
+		return;
+	}
+	dprintk(DRIVER_NAME "[%d]: receive request complete (res=%d)\n",
+		ir->devnum, res);
+}
+
+static int unregister_from_lirc(struct mceusb_dev *ir)
+{
+	struct lirc_driver *d = ir->d;
+	int devnum;
+	int rtn;
+
+	devnum = ir->devnum;
+	dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum);
+
+	rtn = lirc_unregister_driver(d->minor);
+	if (rtn > 0) {
+		printk(DRIVER_NAME "[%d]: error in lirc_unregister minor: %d\n"
+			"Trying again...\n", devnum, d->minor);
+		if (rtn == -EBUSY) {
+			printk(DRIVER_NAME
+				"[%d]: device is opened, will unregister"
+				" on close\n", devnum);
+			return -EAGAIN;
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
+
+		rtn = lirc_unregister_driver(d->minor);
+		if (rtn > 0)
+			printk(DRIVER_NAME "[%d]: lirc_unregister failed\n",
+			devnum);
+	}
+
+	if (rtn) {
+		printk(DRIVER_NAME "[%d]: didn't free resources\n", devnum);
+		return -EAGAIN;
+	}
+
+	printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum);
+
+	lirc_buffer_free(d->rbuf);
+	kfree(d->rbuf);
+	kfree(d);
+	kfree(ir);
+	return 0;
+}
+
+static int mceusb_ir_open(void *data)
+{
+	struct mceusb_dev *ir = data;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: %s called with no context\n",
+		       __func__);
+		return -EIO;
+	}
+	dprintk(DRIVER_NAME "[%d]: mceusb IR device opened\n", ir->devnum);
+
+	MOD_INC_USE_COUNT;
+	if (!ir->flags.connected) {
+		if (!ir->usbdev)
+			return -ENOENT;
+		ir->flags.connected = 1;
+	}
+
+	return 0;
+}
+
+static void mceusb_ir_close(void *data)
+{
+	struct mceusb_dev *ir = data;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: %s called with no context\n",
+		       __func__);
+		return;
+	}
+	dprintk(DRIVER_NAME "[%d]: mceusb IR device closed\n", ir->devnum);
+
+	if (ir->flags.connected) {
+		mutex_lock(&ir->lock);
+		ir->flags.connected = 0;
+		mutex_unlock(&ir->lock);
+	}
+	MOD_DEC_USE_COUNT;
+}
+
+static void send_packet_to_lirc(struct mceusb_dev *ir)
+{
+	if (ir->lircdata) {
+		lirc_buffer_write(ir->d->rbuf,
+				  (unsigned char *) &ir->lircdata);
+		wake_up(&ir->d->rbuf->wait_poll);
+		ir->lircdata = 0;
+	}
+}
+
+static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
+{
+	int i, j;
+	int packet_len = 0;
+	int start_index = 0;
+
+	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+	if (ir->flags.microsoft_gen1)
+		start_index = 2;
+
+	/* this should only trigger w/the 1st-gen mce receiver */
+	for (i = start_index; i < (start_index + ir->overflow_len) &&
+	     i < buf_len; i++) {
+		/* rising/falling flank */
+		if (ir->is_pulse != (ir->buf_in[i] & MCE_PULSE_BIT)) {
+			send_packet_to_lirc(ir);
+			ir->is_pulse = ir->buf_in[i] & MCE_PULSE_BIT;
+		}
+
+		/* accumulate mce pulse/space values */
+		ir->lircdata += (ir->buf_in[i] & MCE_PULSE_MASK) *
+				MCE_TIME_UNIT;
+		ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0);
+	}
+	start_index += ir->overflow_len;
+	ir->overflow_len = 0;
+
+	for (i = start_index; i < buf_len; i++) {
+		/* decode mce packets of the form (84),AA,BB,CC,DD */
+		if (ir->buf_in[i] >= 0x80 && ir->buf_in[i] <= 0x9e) {
+			/* data headers */
+			/* decode packet data */
+			packet_len = ir->buf_in[i] & MCE_PACKET_LENGTH_MASK;
+			ir->overflow_len = i + 1 + packet_len - buf_len;
+			for (j = 1; j <= packet_len && (i + j < buf_len); j++) {
+				/* rising/falling flank */
+				if (ir->is_pulse !=
+				    (ir->buf_in[i + j] & MCE_PULSE_BIT)) {
+					send_packet_to_lirc(ir);
+					ir->is_pulse =
+						ir->buf_in[i + j] &
+							MCE_PULSE_BIT;
+				}
+
+				/* accumulate mce pulse/space values */
+				ir->lircdata +=
+					(ir->buf_in[i + j] & MCE_PULSE_MASK) *
+						MCE_TIME_UNIT;
+				ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0);
+			}
+
+			i += packet_len;
+		} else if (ir->buf_in[i] == MCE_CONTROL_HEADER) {
+			/* status header (0x9F) */
+			/*
+			 * A transmission containing one or more consecutive ir
+			 * commands always ends with a GAP of 100ms followed by
+			 * the sequence 0x9F 0x01 0x01 0x9F 0x15 0x00 0x00 0x80
+			 */
+
+#if 0
+	Uncomment this if the last 100ms "infinity"-space should be transmitted
+	to lirc directly instead of at the beginning of the next transmission.
+	Changes pulse/space order.
+
+			if (++i < buf_len && ir->buf_in[i]==0x01)
+				send_packet_to_lirc(ir);
+
+#endif
+
+			/* end decode loop */
+			dprintk(DRIVER_NAME "[%d] %s: found control header\n",
+				ir->devnum, __func__);
+			ir->overflow_len = 0;
+			break;
+		} else {
+			dprintk(DRIVER_NAME "[%d] %s: stray packet?\n",
+				ir->devnum, __func__);
+			ir->overflow_len = 0;
+		}
+	}
+
+	return;
+}
+
+static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int buf_len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (!ir) {
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(urb);
+		return;
+	}
+
+	buf_len = urb->actual_length;
+
+	if (debug)
+		mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len);
+
+	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
+		ir->send_flags = SEND_FLAG_COMPLETE;
+		dprintk(DRIVER_NAME "[%d]: setup answer received %d bytes\n",
+			ir->devnum, buf_len);
+	}
+
+	switch (urb->status) {
+	/* success */
+	case 0:
+		mceusb_process_ir_data(ir, buf_len);
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(urb);
+		return;
+
+	case -EPIPE:
+	default:
+		break;
+	}
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+
+static ssize_t mceusb_transmit_ir(struct file *file, const char *buf,
+				  size_t n, loff_t *ppos)
+{
+	int i, count = 0, cmdcount = 0;
+	struct mceusb_dev *ir = NULL;
+	lirc_t wbuf[LIRCBUF_SIZE]; /* Workbuffer with values from lirc */
+	unsigned char cmdbuf[MCE_CMDBUF_SIZE]; /* MCE command buffer */
+	unsigned long signal_duration = 0; /* Singnal length in us */
+	struct timeval start_time, end_time;
+
+	do_gettimeofday(&start_time);
+
+	/* Retrieve lirc_driver data for the device */
+	ir = lirc_get_pdata(file);
+	if (!ir || !ir->usb_ep_out)
+		return -EFAULT;
+
+	if (n % sizeof(lirc_t))
+		return -EINVAL;
+	count = n / sizeof(lirc_t);
+
+	/* Check if command is within limits */
+	if (count > LIRCBUF_SIZE || count%2 == 0)
+		return -EINVAL;
+	if (copy_from_user(wbuf, buf, n))
+		return -EFAULT;
+
+	/* MCE tx init header */
+	cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
+	cmdbuf[cmdcount++] = 0x08;
+	cmdbuf[cmdcount++] = ir->transmitter_mask;
+
+	/* Generate mce packet data */
+	for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
+		signal_duration += wbuf[i];
+		wbuf[i] = wbuf[i] / MCE_TIME_UNIT;
+
+		do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
+
+			/* Insert mce packet header every 4th entry */
+			if ((cmdcount < MCE_CMDBUF_SIZE) &&
+			    (cmdcount - MCE_TX_HEADER_LENGTH) %
+			     MCE_CODE_LENGTH == 0)
+				cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
+
+			/* Insert mce packet data */
+			if (cmdcount < MCE_CMDBUF_SIZE)
+				cmdbuf[cmdcount++] =
+					(wbuf[i] < MCE_PULSE_BIT ?
+					 wbuf[i] : MCE_MAX_PULSE_LENGTH) |
+					 (i & 1 ? 0x00 : MCE_PULSE_BIT);
+			else
+				return -EINVAL;
+		} while ((wbuf[i] > MCE_MAX_PULSE_LENGTH) &&
+			 (wbuf[i] -= MCE_MAX_PULSE_LENGTH));
+	}
+
+	/* Fix packet length in last header */
+	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
+		0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
+
+	/* Check if we have room for the empty packet at the end */
+	if (cmdcount >= MCE_CMDBUF_SIZE)
+		return -EINVAL;
+
+	/* All mce commands end with an empty packet (0x80) */
+	cmdbuf[cmdcount++] = 0x80;
+
+	/* Transmit the command to the mce device */
+	request_packet_async(ir, ir->usb_ep_out, cmdbuf,
+			     cmdcount, MCEUSB_OUTBOUND);
+
+	/*
+	 * The lircd gap calculation expects the write function to
+	 * wait the time it takes for the ircommand to be sent before
+	 * it returns.
+	 */
+	do_gettimeofday(&end_time);
+	signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
+			   (end_time.tv_sec - start_time.tv_sec) * 1000000;
+
+	/* delay with the closest number of ticks */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(signal_duration));
+
+	return n;
+}
+
+static void set_transmitter_mask(struct mceusb_dev *ir, unsigned int mask)
+{
+	if (ir->flags.transmitter_mask_inverted)
+		/*
+		 * The mask begins at 0x02 and has an inverted
+		 * numbering scheme
+		 */
+		ir->transmitter_mask =
+			(mask != 0x03 ? mask ^ 0x03 : mask) << 1;
+	else
+		ir->transmitter_mask = mask;
+}
+
+
+/* Sets the send carrier frequency */
+static int set_send_carrier(struct mceusb_dev *ir, int carrier)
+{
+	int clk = 10000000;
+	int prescaler = 0, divisor = 0;
+	unsigned char cmdbuf[] = { 0x9F, 0x06, 0x01, 0x80 };
+
+	/* Carrier is changed */
+	if (ir->carrier_freq != carrier) {
+
+		if (carrier <= 0) {
+			ir->carrier_freq = carrier;
+			dprintk(DRIVER_NAME "[%d]: SET_CARRIER disabling "
+				"carrier modulation\n", ir->devnum);
+			request_packet_async(ir, ir->usb_ep_out,
+					     cmdbuf, sizeof(cmdbuf),
+					     MCEUSB_OUTBOUND);
+			return carrier;
+		}
+
+		for (prescaler = 0; prescaler < 4; ++prescaler) {
+			divisor = (clk >> (2 * prescaler)) / carrier;
+			if (divisor <= 0xFF) {
+				ir->carrier_freq = carrier;
+				cmdbuf[2] = prescaler;
+				cmdbuf[3] = divisor;
+				dprintk(DRIVER_NAME "[%d]: SET_CARRIER "
+					"requesting %d Hz\n",
+					ir->devnum, carrier);
+
+				/* Transmit new carrier to mce device */
+				request_packet_async(ir, ir->usb_ep_out,
+						     cmdbuf, sizeof(cmdbuf),
+						     MCEUSB_OUTBOUND);
+				return carrier;
+			}
+		}
+
+		return -EINVAL;
+
+	}
+
+	return carrier;
+}
+
+
+static int mceusb_lirc_ioctl(struct inode *node, struct file *filep,
+			     unsigned int cmd, unsigned long arg)
+{
+	int result;
+	unsigned int ivalue;
+	unsigned long lvalue;
+	struct mceusb_dev *ir = NULL;
+
+	/* Retrieve lirc_driver data for the device */
+	ir = lirc_get_pdata(filep);
+	if (!ir || !ir->usb_ep_out)
+		return -EFAULT;
+
+
+	switch (cmd) {
+	case LIRC_SET_TRANSMITTER_MASK:
+
+		result = get_user(ivalue, (unsigned int *) arg);
+		if (result)
+			return result;
+		switch (ivalue) {
+		case 0x01: /* Transmitter 1     => 0x04 */
+		case 0x02: /* Transmitter 2     => 0x02 */
+		case 0x03: /* Transmitter 1 & 2 => 0x06 */
+			set_transmitter_mask(ir, ivalue);
+			break;
+
+		default: /* Unsupported transmitter mask */
+			return MCE_MAX_CHANNELS;
+		}
+
+		dprintk(DRIVER_NAME ": SET_TRANSMITTERS mask=%d\n", ivalue);
+		break;
+
+	case LIRC_GET_SEND_MODE:
+
+		result = put_user(LIRC_SEND2MODE(LIRC_CAN_SEND_PULSE &
+						 LIRC_CAN_SEND_MASK),
+				  (unsigned long *) arg);
+
+		if (result)
+			return result;
+		break;
+
+	case LIRC_SET_SEND_MODE:
+
+		result = get_user(lvalue, (unsigned long *) arg);
+
+		if (result)
+			return result;
+		if (lvalue != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK))
+			return -EINVAL;
+		break;
+
+	case LIRC_SET_SEND_CARRIER:
+
+		result = get_user(ivalue, (unsigned int *) arg);
+		if (result)
+			return result;
+
+		set_send_carrier(ir, ivalue);
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static struct file_operations lirc_fops = {
+	.owner	= THIS_MODULE,
+	.write	= mceusb_transmit_ir,
+	.ioctl	= mceusb_lirc_ioctl,
+};
+
+static int mceusb_gen1_init(struct mceusb_dev *ir)
+{
+	int i, ret;
+	char junk[64], data[8];
+	int partial = 0;
+
+	/*
+	 * Clear off the first few messages. These look like calibration
+	 * or test data, I can't really tell. This also flushes in case
+	 * we have random ir data queued up.
+	 */
+	for (i = 0; i < 40; i++)
+		usb_bulk_msg(ir->usbdev,
+			usb_rcvbulkpipe(ir->usbdev,
+				ir->usb_ep_in->bEndpointAddress),
+			junk, 64, &partial, HZ * 10);
+
+	ir->is_pulse = 1;
+
+	memset(data, 0, 8);
+
+	/* Get Status */
+	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+			      USB_REQ_GET_STATUS, USB_DIR_IN,
+			      0, 0, data, 2, HZ * 3);
+
+	/*    ret = usb_get_status( ir->usbdev, 0, 0, data ); */
+	dprintk("%s - ret = %d status = 0x%x 0x%x\n", __func__,
+		ret, data[0], data[1]);
+
+	/*
+	 * This is a strange one. They issue a set address to the device
+	 * on the receive control pipe and expect a certain value pair back
+	 */
+	memset(data, 0, 8);
+
+	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+			      data, 2, HZ * 3);
+	dprintk("%s - ret = %d, devnum = %d\n",
+		__func__, ret, ir->usbdev->devnum);
+	dprintk("%s - data[0] = %d, data[1] = %d\n",
+		__func__, data[0], data[1]);
+
+	/* set feature */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+			      0xc04e, 0x0000, NULL, 0, HZ * 3);
+
+	dprintk("%s - ret = %d\n", __func__, ret);
+
+	/* strange: bRequest == 4 */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      4, USB_TYPE_VENDOR,
+			      0x0808, 0x0000, NULL, 0, HZ * 3);
+	dprintk("%s - retB = %d\n", __func__, ret);
+
+	/* strange: bRequest == 2 */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      2, USB_TYPE_VENDOR,
+			      0x0000, 0x0100, NULL, 0, HZ * 3);
+	dprintk("%s - retC = %d\n", __func__, ret);
+
+	return ret;
+
+};
+
+static int mceusb_dev_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *idesc;
+	struct usb_endpoint_descriptor *ep = NULL;
+	struct usb_endpoint_descriptor *ep_in = NULL;
+	struct usb_endpoint_descriptor *ep_out = NULL;
+	struct usb_host_config *config;
+	struct mceusb_dev *ir = NULL;
+	struct lirc_driver *driver = NULL;
+	struct lirc_buffer *rbuf = NULL;
+	int devnum, pipe, maxp;
+	int minor = 0;
+	int i;
+	char buf[63], name[128] = "";
+	int mem_failure = 0;
+	int is_pinnacle;
+	int is_microsoft_gen1;
+
+	dprintk(DRIVER_NAME ": %s called\n", __func__);
+
+	usb_reset_device(dev);
+
+	config = dev->actconfig;
+
+	idesc = intf->cur_altsetting;
+
+	is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
+
+	is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0;
+
+	/* step through the endpoints to find first bulk in and out endpoint */
+	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i].desc;
+
+		if ((ep_in == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_IN)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			dprintk(DRIVER_NAME ": acceptable inbound endpoint "
+				"found\n");
+			ep_in = ep;
+			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
+			if (is_pinnacle)
+				/*
+				 * setting seems to 1 seem to cause issues with
+				 * Pinnacle timing out on transfer.
+				 */
+				ep_in->bInterval = ep->bInterval;
+			else
+				ep_in->bInterval = 1;
+		}
+
+		if ((ep_out == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_OUT)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			dprintk(DRIVER_NAME ": acceptable outbound endpoint "
+				"found\n");
+			ep_out = ep;
+			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
+			if (is_pinnacle)
+				/*
+				 * setting seems to 1 seem to cause issues with
+				 * Pinnacle timing out on transfer.
+				 */
+				ep_out->bInterval = ep->bInterval;
+			else
+				ep_out->bInterval = 1;
+		}
+	}
+	if (ep_in == NULL || ep_out == NULL) {
+		dprintk(DRIVER_NAME ": inbound and/or "
+			"outbound endpoint not found\n");
+		return -ENODEV;
+	}
+
+	devnum = dev->devnum;
+	pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	mem_failure = 0;
+	ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
+	if (!ir) {
+		mem_failure = 1;
+		goto mem_failure_switch;
+	}
+
+	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	if (!driver) {
+		mem_failure = 2;
+		goto mem_failure_switch;
+	}
+
+	rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+	if (!rbuf) {
+		mem_failure = 3;
+		goto mem_failure_switch;
+	}
+
+	if (lirc_buffer_init(rbuf, sizeof(lirc_t), LIRCBUF_SIZE)) {
+		mem_failure = 4;
+		goto mem_failure_switch;
+	}
+
+	ir->buf_in = usb_buffer_alloc(dev, maxp, GFP_ATOMIC, &ir->dma_in);
+	if (!ir->buf_in) {
+		mem_failure = 5;
+		goto mem_failure_switch;
+	}
+
+	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ir->urb_in) {
+		mem_failure = 7;
+		goto mem_failure_switch;
+	}
+
+	strcpy(driver->name, DRIVER_NAME " ");
+	driver->minor = -1;
+	driver->features = LIRC_CAN_SEND_PULSE |
+		LIRC_CAN_SET_TRANSMITTER_MASK |
+		LIRC_CAN_REC_MODE2 |
+		LIRC_CAN_SET_SEND_CARRIER;
+	driver->data = ir;
+	driver->rbuf = rbuf;
+	driver->set_use_inc = &mceusb_ir_open;
+	driver->set_use_dec = &mceusb_ir_close;
+	driver->code_length = sizeof(lirc_t) * 8;
+	driver->fops  = &lirc_fops;
+	driver->dev   = &intf->dev;
+	driver->owner = THIS_MODULE;
+
+	mutex_init(&ir->lock);
+	init_waitqueue_head(&ir->wait_out);
+
+	minor = lirc_register_driver(driver);
+	if (minor < 0)
+		mem_failure = 9;
+
+mem_failure_switch:
+
+	switch (mem_failure) {
+	case 9:
+		usb_free_urb(ir->urb_in);
+	case 7:
+		usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in);
+	case 5:
+		lirc_buffer_free(rbuf);
+	case 4:
+		kfree(rbuf);
+	case 3:
+		kfree(driver);
+	case 2:
+		kfree(ir);
+	case 1:
+		printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
+			devnum, mem_failure);
+		return -ENOMEM;
+	}
+
+	driver->minor = minor;
+	ir->d = driver;
+	ir->devnum = devnum;
+	ir->usbdev = dev;
+	ir->len_in = maxp;
+	ir->overflow_len = 0;
+	ir->flags.connected = 0;
+	ir->flags.pinnacle = is_pinnacle;
+	ir->flags.microsoft_gen1 = is_microsoft_gen1;
+	ir->flags.transmitter_mask_inverted =
+		usb_match_id(intf, transmitter_mask_list) ? 0 : 1;
+
+	ir->lircdata = PULSE_MASK;
+	ir->is_pulse = 0;
+
+	/* ir->flags.transmitter_mask_inverted must be set */
+	set_transmitter_mask(ir, MCE_DEFAULT_TX_MASK);
+	/* Saving usb interface data for use by the transmitter routine */
+	ir->usb_ep_in = ep_in;
+	ir->usb_ep_out = ep_out;
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct,
+			  buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+	printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
+	       dev->bus->busnum, devnum);
+
+	/* inbound data */
+	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
+		maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
+	ir->urb_in->transfer_dma = ir->dma_in;
+	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* initialize device */
+	if (ir->flags.pinnacle) {
+		int usbret;
+
+		/*
+		 * I have no idea why but this reset seems to be crucial to
+		 * getting the device to do outbound IO correctly - without
+		 * this the device seems to hang, ignoring all input - although
+		 * IR signals are correctly sent from the device, no input is
+		 * interpreted by the device and the host never does the
+		 * completion routine
+		 */
+
+		usbret = usb_reset_configuration(dev);
+		printk(DRIVER_NAME "[%d]: usb reset config ret %x\n",
+		       devnum, usbret);
+
+		/*
+		 * its possible we really should wait for a return
+		 * for each of these...
+		 */
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_out, pin_init1, sizeof(pin_init1),
+				     MCEUSB_OUTBOUND);
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_out, pin_init2, sizeof(pin_init2),
+				     MCEUSB_OUTBOUND);
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_out, pin_init3, sizeof(pin_init3),
+				     MCEUSB_OUTBOUND);
+	} else if (ir->flags.microsoft_gen1) {
+		/* original ms mce device requires some additional setup */
+		mceusb_gen1_init(ir);
+	} else {
+
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_out, init1,
+				     sizeof(init1), MCEUSB_OUTBOUND);
+		request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
+		request_packet_async(ir, ep_out, init2,
+				     sizeof(init2), MCEUSB_OUTBOUND);
+	}
+
+	/*
+	 * if we don't issue the correct number of receives (MCEUSB_INBOUND)
+	 * for each outbound, then the first few ir pulses will be interpreted
+	 * by the usb_async_callback routine - we should ensure we have the
+	 * right amount OR less - as the meusb_dev_recv routine will handle
+	 * the control packets OK - they start with 0x9f - but the async
+	 * callback doesn't handle ir pulse packets
+	 */
+	request_packet_async(ir, ep_in, NULL, maxp, 0);
+
+	usb_set_intfdata(intf, ir);
+
+	return 0;
+}
+
+
+static void mceusb_dev_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!ir || !ir->d)
+		return;
+
+	ir->usbdev = NULL;
+	wake_up_all(&ir->wait_out);
+
+	mutex_lock(&ir->lock);
+	usb_kill_urb(ir->urb_in);
+	usb_free_urb(ir->urb_in);
+	usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in);
+	mutex_unlock(&ir->lock);
+
+	unregister_from_lirc(ir);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	printk(DRIVER_NAME "[%d]: suspend\n", ir->devnum);
+	usb_kill_urb(ir->urb_in);
+	return 0;
+}
+
+static int mceusb_dev_resume(struct usb_interface *intf)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	printk(DRIVER_NAME "[%d]: resume\n", ir->devnum);
+	if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
+		return -EIO;
+	return 0;
+}
+#endif
+
+static struct usb_driver mceusb_dev_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name =		DRIVER_NAME,
+	.probe =	mceusb_dev_probe,
+	.disconnect =	mceusb_dev_disconnect,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+	.suspend =	mceusb_dev_suspend,
+	.resume =	mceusb_dev_resume,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+	.reset_resume =	mceusb_dev_resume,
+#endif
+#endif
+	.id_table =	mceusb_dev_table
+};
+
+static int __init mceusb_dev_init(void)
+{
+	int i;
+
+	printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " " DRIVER_VERSION "\n");
+	printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n");
+	dprintk(DRIVER_NAME ": debug mode enabled\n");
+
+	i = usb_register(&mceusb_dev_driver);
+	if (i < 0) {
+		printk(DRIVER_NAME ": usb register failed, result = %d\n", i);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit mceusb_dev_exit(void)
+{
+	usb_deregister(&mceusb_dev_driver);
+}
+
+module_init(mceusb_dev_init);
+module_exit(mceusb_dev_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
+/* this was originally lirc_mceusb2, lirc_mceusb and lirc_mceusb2 merged now */
+MODULE_ALIAS("lirc_mceusb2");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ttusbir/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ttusbir/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_TTUSBIR)	+= lirc_ttusbir.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c
@@ -0,0 +1,410 @@
+/*
+ * lirc_ttusbir.c
+ *
+ * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver
+ *
+ * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de>
+ *
+ * This LIRC driver provides access to the TechnoTrend USB IR Receiver.
+ * The receiver delivers the IR signal as raw sampled true/false data in
+ * isochronous USB packets each of size 128 byte.
+ * Currently the driver reduces the sampling rate by factor of 8 as this
+ * is still more than enough to decode RC-5 - others should be analyzed.
+ * But the driver does not rely on RC-5 it should be able to decode every
+ * IR signal that is not too fast.
+ */
+
+/*
+ *  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/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC");
+MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)");
+MODULE_LICENSE("GPL");
+
+/* #define DEBUG */
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+#define DPRINTK(_x_, a...)
+#endif
+
+/* function declarations */
+static int probe(struct usb_interface *intf, const struct usb_device_id *id);
+static void disconnect(struct usb_interface *intf);
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void urb_complete(struct urb *urb, struct pt_regs *pt_regs);
+#else
+static void urb_complete(struct urb *urb);
+#endif
+static int set_use_inc(void *data);
+static void set_use_dec(void *data);
+
+static int num_urbs = 2;
+module_param(num_urbs, int, S_IRUGO);
+MODULE_PARM_DESC(num_urbs,
+		 "Number of URBs in queue. Try to increase to 4 in case "
+		 "of problems (default: 2; minimum: 2)");
+
+/* table of devices that work with this driver */
+static struct usb_device_id device_id_table[] = {
+	/* TechnoTrend USB IR Receiver */
+	{ USB_DEVICE(0x0B48, 0x2003) },
+	/* Terminating entry */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, device_id_table);
+
+/* USB driver definition */
+static struct usb_driver usb_driver = {
+	.name = "TTUSBIR",
+	.id_table = &(device_id_table[0]),
+	.probe = probe,
+	.disconnect = disconnect,
+};
+
+/* USB device definition */
+struct ttusbir_device {
+	struct usb_driver *usb_driver;
+	struct usb_device *udev;
+	struct usb_interface *interf;
+	struct usb_class_driver class_driver;
+	unsigned int ifnum; /* Interface number to use */
+	unsigned int alt_setting; /* alternate setting to use */
+	unsigned int endpoint; /* Endpoint to use */
+	struct urb **urb; /* num_urb URB pointers*/
+	char **buffer; /* 128 byte buffer for each URB */
+	struct lirc_buffer rbuf; /* Buffer towards LIRC */
+	struct lirc_driver driver;
+	int minor;
+	int last_pulse; /* remembers if last received byte was pulse or space */
+	int last_num; /* remembers how many last bytes appeared */
+	int opened;
+};
+
+/*** LIRC specific functions ***/
+static int set_use_inc(void *data)
+{
+	int i, retval;
+	struct ttusbir_device *ttusbir = data;
+
+	DPRINTK("Sending first URBs\n");
+	/* @TODO Do I need to check if I am already opened */
+	ttusbir->opened = 1;
+
+	for (i = 0; i < num_urbs; i++) {
+		retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL);
+		if (retval) {
+			err("%s: usb_submit_urb failed on urb %d",
+			    __func__, i);
+			return retval;
+		}
+	}
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	struct ttusbir_device *ttusbir = data;
+
+	DPRINTK("Device closed\n");
+
+	ttusbir->opened = 0;
+}
+
+/*** USB specific functions ***/
+
+/*
+ * This mapping table is used to do a very simple filtering of the
+ * input signal.
+ * For a value with at least 4 bits set it returns 0xFF otherwise
+ * 0x00.  For faster IR signals this can not be used. But for RC-5 we
+ * still have about 14 samples per pulse/space, i.e. we sample with 14
+ * times higher frequency than the signal frequency
+ */
+const unsigned char map_table[] =
+{
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void urb_complete(struct urb *urb, struct pt_regs *pt_regs)
+#else
+static void urb_complete(struct urb *urb)
+#endif
+{
+	struct ttusbir_device *ttusbir;
+	unsigned char *buf;
+	int i;
+	lirc_t l;
+
+	ttusbir = urb->context;
+
+	if (!ttusbir->opened)
+		return;
+
+	buf = (unsigned char *)urb->transfer_buffer;
+
+	for (i = 0; i < 128; i++) {
+		/* Here we do the filtering and some kind of down sampling */
+		buf[i] = ~map_table[buf[i]];
+		if (ttusbir->last_pulse == buf[i]) {
+			if (ttusbir->last_num < PULSE_MASK/63)
+				ttusbir->last_num++;
+		/*
+		 * else we are in a idle period and do not need to
+		 * increment any longer
+		 */
+		} else {
+			l = ttusbir->last_num * 62; /* about 62 = us/byte */
+			if (ttusbir->last_pulse) /* pulse or space? */
+				l |= PULSE_BIT;
+			if (!lirc_buffer_full(&ttusbir->rbuf)) {
+				lirc_buffer_write(&ttusbir->rbuf, (void *)&l);
+				wake_up_interruptible(&ttusbir->rbuf.wait_poll);
+			}
+			ttusbir->last_num = 0;
+			ttusbir->last_pulse = buf[i];
+		}
+	}
+	usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */
+}
+
+/*
+ * Called whenever the USB subsystem thinks we could be the right driver
+ * to handle this device
+ */
+static int probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int alt_set, endp;
+	int found = 0;
+	int i, j;
+	int struct_size;
+	struct usb_host_interface *host_interf;
+	struct usb_interface_descriptor *interf_desc;
+	struct usb_host_endpoint *host_endpoint;
+	struct ttusbir_device *ttusbir;
+
+	DPRINTK("Module ttusbir probe\n");
+
+	/* To reduce memory fragmentation we use only one allocation */
+	struct_size =  sizeof(struct ttusbir_device) +
+		(sizeof(struct urb *) * num_urbs) +
+		(sizeof(char *) * num_urbs) +
+		(num_urbs * 128);
+	ttusbir = kzalloc(struct_size, GFP_KERNEL);
+	if (!ttusbir)
+		return -ENOMEM;
+
+	ttusbir->urb = (struct urb **)((char *)ttusbir +
+				      sizeof(struct ttusbir_device));
+	ttusbir->buffer = (char **)((char *)ttusbir->urb +
+				   (sizeof(struct urb *) * num_urbs));
+	for (i = 0; i < num_urbs; i++)
+		ttusbir->buffer[i] = (char *)ttusbir->buffer +
+			(sizeof(char *)*num_urbs) + (i * 128);
+
+	ttusbir->usb_driver = &usb_driver;
+	ttusbir->alt_setting = -1;
+	/* @TODO check if error can be returned */
+	ttusbir->udev = usb_get_dev(interface_to_usbdev(intf));
+	ttusbir->interf = intf;
+	ttusbir->last_pulse = 0x00;
+	ttusbir->last_num = 0;
+
+	/*
+	 * Now look for interface setting we can handle
+	 * We are searching for the alt setting where end point
+	 * 0x82 has max packet size 16
+	 */
+	for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) {
+		host_interf = &intf->altsetting[alt_set];
+		interf_desc = &host_interf->desc;
+		for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) {
+			host_endpoint = &host_interf->endpoint[endp];
+			if ((host_endpoint->desc.bEndpointAddress == 0x82) &&
+			    (host_endpoint->desc.wMaxPacketSize == 0x10)) {
+				ttusbir->alt_setting = alt_set;
+				ttusbir->endpoint = endp;
+				found = 1;
+				break;
+			}
+		}
+	}
+	if (ttusbir->alt_setting != -1)
+		DPRINTK("alt setting: %d\n", ttusbir->alt_setting);
+	else {
+		err("Could not find alternate setting\n");
+		kfree(ttusbir);
+		return -EINVAL;
+	}
+
+	/* OK lets setup this interface setting */
+	usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting);
+
+	/* Store device info in interface structure */
+	usb_set_intfdata(intf, ttusbir);
+
+	/* Register as a LIRC driver */
+	if (lirc_buffer_init(&ttusbir->rbuf, sizeof(lirc_t), 256) < 0) {
+		err("Could not get memory for LIRC data buffer\n");
+		usb_set_intfdata(intf, NULL);
+		kfree(ttusbir);
+		return -ENOMEM;
+	}
+	strcpy(ttusbir->driver.name, "TTUSBIR");
+	ttusbir->driver.minor = -1;
+	ttusbir->driver.code_length = 1;
+	ttusbir->driver.sample_rate = 0;
+	ttusbir->driver.data = ttusbir;
+	ttusbir->driver.add_to_buf = NULL;
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	ttusbir->driver.get_queue = NULL;
+#endif
+	ttusbir->driver.rbuf = &ttusbir->rbuf;
+	ttusbir->driver.set_use_inc = set_use_inc;
+	ttusbir->driver.set_use_dec = set_use_dec;
+	ttusbir->driver.fops = NULL;
+	ttusbir->driver.dev = &intf->dev;
+	ttusbir->driver.owner = THIS_MODULE;
+	ttusbir->driver.features = LIRC_CAN_REC_MODE2;
+	ttusbir->minor = lirc_register_driver(&ttusbir->driver);
+	if (ttusbir->minor < 0) {
+		err("Error registering as LIRC driver\n");
+		usb_set_intfdata(intf, NULL);
+		lirc_buffer_free(&ttusbir->rbuf);
+		kfree(ttusbir);
+		return -EIO;
+	}
+
+	/* Allocate and setup the URB that we will use to talk to the device */
+	for (i = 0; i < num_urbs; i++) {
+		ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL);
+		if (!ttusbir->urb[i]) {
+			err("Could not allocate memory for the URB\n");
+			for (j = i - 1; j >= 0; j--)
+				kfree(ttusbir->urb[j]);
+			lirc_buffer_free(&ttusbir->rbuf);
+			lirc_unregister_driver(ttusbir->minor);
+			kfree(ttusbir);
+			usb_set_intfdata(intf, NULL);
+			return -ENOMEM;
+		}
+		ttusbir->urb[i]->dev = ttusbir->udev;
+		ttusbir->urb[i]->context = ttusbir;
+		ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev,
+							ttusbir->endpoint);
+		ttusbir->urb[i]->interval = 1;
+		ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP;
+		ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0];
+		ttusbir->urb[i]->complete = urb_complete;
+		ttusbir->urb[i]->number_of_packets = 8;
+		ttusbir->urb[i]->transfer_buffer_length = 128;
+		for (j = 0; j < 8; j++) {
+			ttusbir->urb[i]->iso_frame_desc[j].offset = j*16;
+			ttusbir->urb[i]->iso_frame_desc[j].length = 16;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Called when the driver is unloaded or the device is unplugged
+ */
+static void disconnect(struct usb_interface *intf)
+{
+	int i;
+	struct ttusbir_device *ttusbir;
+
+	DPRINTK("Module ttusbir disconnect\n");
+
+	ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+	lirc_unregister_driver(ttusbir->minor);
+	DPRINTK("unregistered\n");
+
+	for (i = 0; i < num_urbs; i++) {
+		usb_kill_urb(ttusbir->urb[i]);
+		usb_free_urb(ttusbir->urb[i]);
+	}
+	DPRINTK("URBs killed\n");
+	lirc_buffer_free(&ttusbir->rbuf);
+	kfree(ttusbir);
+}
+
+static int ttusbir_init_module(void)
+{
+	int result;
+
+	DPRINTK(KERN_DEBUG "Module ttusbir init\n");
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&usb_driver);
+	if (result)
+		err("usb_register failed. Error number %d", result);
+	return result;
+}
+
+static void ttusbir_exit_module(void)
+{
+	printk(KERN_DEBUG "Module ttusbir exit\n");
+	usb_deregister(&usb_driver);
+}
+
+module_init(ttusbir_init_module);
+module_exit(ttusbir_exit_module);
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_it87/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_it87/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_IT87)		+= lirc_it87.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_it87/lirc_it87.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_it87/lirc_it87.h
@@ -0,0 +1,116 @@
+/* lirc_it87.h */
+/* SECTION: Definitions */
+
+/********************************* ITE IT87xx ************************/
+
+/* based on the following documentation from ITE:
+   a) IT8712F Preliminary CIR Programming Guide V0.1
+   b) IT8705F Simple LPC I/O Preliminary Specification V0.3
+   c) IT8712F EC-LPC I/O Preliminary Specification V0.5
+*/
+
+/* IT8712/05 Ports: */
+#define IT87_ADRPORT      0x2e
+#define IT87_DATAPORT     0x2f
+#define IT87_INIT         {0x87, 0x01, 0x55, 0x55}
+
+/* alternate Ports: */
+/*
+#define IT87_ADRPORT      0x4e
+#define IT87_DATAPORT     0x4f
+#define IT87_INIT         {0x87, 0x01, 0x55, 0xaa}
+ */
+
+/* IT8712/05 Registers */
+#define IT87_CFGCTRL      0x2
+#define IT87_LDN          0x7
+#define IT87_CHIP_ID1     0x20
+#define IT87_CHIP_ID2     0x21
+#define IT87_CFG_VERSION  0x22
+#define IT87_SWSUSPEND    0x23
+
+#define IT8712_CIR_LDN    0xa
+#define IT8705_CIR_LDN    0x7
+
+/* CIR Configuration Registers: */
+#define IT87_CIR_ACT      0x30
+#define IT87_CIR_BASE_MSB 0x60
+#define IT87_CIR_BASE_LSB 0x61
+#define IT87_CIR_IRQ      0x70
+#define IT87_CIR_CONFIG   0xf0
+
+/* List of IT87_CIR registers: offset to BaseAddr */
+#define IT87_CIR_DR   0
+#define IT87_CIR_IER  1
+#define IT87_CIR_RCR  2
+#define IT87_CIR_TCR1 3
+#define IT87_CIR_TCR2 4
+#define IT87_CIR_TSR  5
+#define IT87_CIR_RSR  6
+#define IT87_CIR_BDLR 5
+#define IT87_CIR_BDHR 6
+#define IT87_CIR_IIR  7
+
+/* Bit Definition */
+/* IER: */
+#define IT87_CIR_IER_TM_EN   0x80
+#define IT87_CIR_IER_RESEVED 0x40
+#define IT87_CIR_IER_RESET   0x20
+#define IT87_CIR_IER_BR      0x10
+#define IT87_CIR_IER_IEC     0x8
+#define IT87_CIR_IER_RFOIE   0x4
+#define IT87_CIR_IER_RDAIE   0x2
+#define IT87_CIR_IER_TLDLIE  0x1
+
+/* RCR: */
+#define IT87_CIR_RCR_RDWOS  0x80
+#define IT87_CIR_RCR_HCFS   0x40
+#define IT87_CIR_RCR_RXEN   0x20
+#define IT87_CIR_RCR_RXEND  0x10
+#define IT87_CIR_RCR_RXACT  0x8
+#define IT87_CIR_RCR_RXDCR  0x7
+
+/* TCR1: */
+#define IT87_CIR_TCR1_FIFOCLR 0x80
+#define IT87_CIR_TCR1_ILE     0x40
+#define IT87_CIR_TCR1_FIFOTL  0x30
+#define IT87_CIR_TCR1_TXRLE   0x8
+#define IT87_CIR_TCR1_TXENDF  0x4
+#define IT87_CIR_TCR1_TXMPM   0x3
+
+/* TCR2: */
+#define IT87_CIR_TCR2_CFQ   0xf8
+#define IT87_CIR_TCR2_TXMPW 0x7
+
+/* TSR: */
+#define IT87_CIR_TSR_RESERVED 0xc0
+#define IT87_CIR_TSR_TXFBC    0x3f
+
+/* RSR: */
+#define IT87_CIR_RSR_RXFTO    0x80
+#define IT87_CIR_RSR_RESERVED 0x40
+#define IT87_CIR_RSR_RXFBC    0x3f
+
+/* IIR: */
+#define IT87_CIR_IIR_RESERVED 0xf8
+#define IT87_CIR_IIR_IID      0x6
+#define IT87_CIR_IIR_IIP      0x1
+
+/* TM: */
+#define IT87_CIR_TM_IL_SEL    0x80
+#define IT87_CIR_TM_RESERVED  0x40
+#define IT87_CIR_TM_TM_REG    0x3f
+
+#define IT87_CIR_FIFO_SIZE 32
+
+/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */
+#define IT87_CIR_BAUDRATE_DIVISOR 0x1
+#define IT87_CIR_DEFAULT_IOBASE 0x310
+#define IT87_CIR_DEFAULT_IRQ    0x7
+#define IT87_CIR_SPACE 0x00
+#define IT87_CIR_PULSE 0xff
+#define IT87_CIR_FREQ_MIN 27
+#define IT87_CIR_FREQ_MAX 58
+#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul)
+
+/********************************* ITE IT87xx ************************/
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_it87/TODO
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_it87/TODO
@@ -0,0 +1,5 @@
+This is my todo-list for lirc_it87:
+
+1. enabling/using shared IRQ
+2. init/drop IRQ-usage in lirc_open/lirc_close
+
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_it87/README
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_it87/README
@@ -0,0 +1,46 @@
+This is the README using the ITE IT8705 and IT8712 CIR port for LIRC.
+
+The IT8705 for example can be found on the ECS K7S5A.
+
+The driver supports receiving (MODE2) and sending (PULSE). It seems
+sending 'LIRC_CAN_SEND_PULSE' isn't optimal for this type of hardware.
+But because I don't know how to implement 'LIRC_CAN_SEND_CODE', I did
+it this way.
+
+Attention:
+Because of missing hardware, the following hasn't been tested:
+a) receiving with demodulator enabled,
+b) sending (debugging output looks good) and
+c) using IT8712
+
+Any help and/or additions etc. is welcome.
+
+lirc_it87 knows about the following module-parameters:
+MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O base address (default: 0x310)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)");
+MODULE_PARM(it87_enable_demodulator, "i");
+MODULE_PARM_DESC(it87_enable_demodulator, "Receiver demodulator
+	enable/disable (1/0), default: 0");
+
+
+Usage:
+
+a) io and irq:
+
+If the driver finds the IT8705/12-CIR port initialized, io and irq of
+the preinitialized hardware is used by the driver. If both values are
+read 0x0 from the hardware, the default or given value is used.
+Note: I experienced using irq=3. The driver initialized without any
+problems, but no irqs are recognized by the system. I had to switch
+back to default, irq 7.
+      
+b) it87_enable_demodulator:
+
+The demodulator for the receiver can be switched off (default within
+the driver). If you need the demodulator simple enable it by the
+following way: it87_enable_demodulator=1.
+
+Hans-G�nter L�tke Uphues
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_it87/lirc_it87.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_it87/lirc_it87.c
@@ -0,0 +1,1012 @@
+/*
+ * LIRC driver for ITE IT8712/IT8705/IT8720 CIR port
+ *
+ * Copyright (C) 2001 Hans-Günter Lütke Uphues <hg_lu@web.de>
+ *
+ * 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
+ *
+ * ITE IT8705, IT8712(not tested) and IT8720 CIR-port support for lirc based
+ * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula
+ *
+ * Attention: Sendmode only tested with debugging logs
+ *
+ * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> :
+ *   reimplemented read function
+ * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix,
+ *   based on work of the following member of the Outertrack Digimatrix
+ *   Forum: Art103 <r_tay@hotmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/autoconf.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <asm/system.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/fcntl.h>
+#else
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/fcntl.h>
+#endif
+
+#include <linux/timer.h>
+
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+#include "../kcompat.h"
+
+#include "lirc_it87.h"
+
+#ifdef LIRC_IT87_DIGIMATRIX
+static int digimatrix = 1;
+static int it87_freq = 36; /* kHz */
+static int irq = 9;
+#else
+static int digimatrix;
+static int it87_freq = 38; /* kHz */
+static int irq = IT87_CIR_DEFAULT_IRQ;
+#endif
+
+static unsigned long it87_bits_in_byte_out;
+static unsigned long it87_send_counter;
+static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN;
+
+#define RBUF_LEN 1024
+#define WBUF_LEN 1024
+
+#define LIRC_DRIVER_NAME "lirc_it87"
+
+/* timeout for sequences in jiffies (=5/100s) */
+/* must be longer than TIME_CONST */
+#define IT87_TIMEOUT	(HZ*5/100)
+
+/* module parameters */
+static int debug;
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+static int io = IT87_CIR_DEFAULT_IOBASE;
+/* receiver demodulator default: off */
+static int it87_enable_demodulator;
+
+static int timer_enabled;
+static DEFINE_SPINLOCK(timer_lock);
+static struct timer_list timerlist;
+/* time of last signal change detected */
+static struct timeval last_tv = {0, 0};
+/* time of last UART data ready interrupt */
+static struct timeval last_intr_tv = {0, 0};
+static int last_value;
+
+static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
+
+static DEFINE_SPINLOCK(hardware_lock);
+static DEFINE_SPINLOCK(dev_lock);
+
+static lirc_t rx_buf[RBUF_LEN];
+unsigned int rx_tail, rx_head;
+static lirc_t tx_buf[WBUF_LEN];
+
+/* SECTION: Prototypes */
+
+/* Communication with user-space */
+static int lirc_open(struct inode *inode, struct file *file);
+static int lirc_close(struct inode *inode, struct file *file);
+static unsigned int lirc_poll(struct file *file, poll_table *wait);
+static ssize_t lirc_read(struct file *file, char *buf,
+			 size_t count, loff_t *ppos);
+static ssize_t lirc_write(struct file *file, const char *buf,
+			  size_t n, loff_t *pos);
+static int lirc_ioctl(struct inode *node, struct file *filep,
+		      unsigned int cmd, unsigned long arg);
+static void add_read_queue(int flag, unsigned long val);
+static int init_chrdev(void);
+static void drop_chrdev(void);
+	/* Hardware */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static irqreturn_t it87_interrupt(int irq, void *dev_id,
+				  struct pt_regs *regs);
+#else
+static irqreturn_t it87_interrupt(int irq, void *dev_id);
+#endif
+static void send_space(unsigned long len);
+static void send_pulse(unsigned long len);
+static void init_send(void);
+static void terminate_send(unsigned long len);
+static int init_hardware(void);
+static void drop_hardware(void);
+/* Initialisation */
+static int init_port(void);
+static void drop_port(void);
+
+
+/* SECTION: Communication with user-space */
+
+static int lirc_open(struct inode *inode, struct file *file)
+{
+	spin_lock(&dev_lock);
+	if (MOD_IN_USE) {
+		spin_unlock(&dev_lock);
+		return -EBUSY;
+	}
+	MOD_INC_USE_COUNT;
+	spin_unlock(&dev_lock);
+	return 0;
+}
+
+
+static int lirc_close(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static unsigned int lirc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &lirc_read_queue, wait);
+	if (rx_head != rx_tail)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+
+static ssize_t lirc_read(struct file *file, char *buf,
+			 size_t count, loff_t *ppos)
+{
+	int n = 0;
+	int retval = 0;
+
+	while (n < count) {
+		if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) {
+			retval = -EAGAIN;
+			break;
+		}
+		retval = wait_event_interruptible(lirc_read_queue,
+						  rx_head != rx_tail);
+		if (retval)
+			break;
+
+		if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head),
+				 sizeof(lirc_t))) {
+			retval = -EFAULT;
+			break;
+		}
+		rx_head = (rx_head + 1) & (RBUF_LEN - 1);
+		n += sizeof(lirc_t);
+	}
+	if (n)
+		return n;
+	return retval;
+}
+
+
+static ssize_t lirc_write(struct file *file, const char *buf,
+			  size_t n, loff_t *pos)
+{
+	int i = 0;
+
+	if (n % sizeof(lirc_t) || (n / sizeof(lirc_t)) > WBUF_LEN)
+		return -EINVAL;
+	if (copy_from_user(tx_buf, buf, n))
+		return -EFAULT;
+	n /= sizeof(lirc_t);
+	init_send();
+	while (1) {
+		if (i >= n)
+			break;
+		if (tx_buf[i])
+			send_pulse(tx_buf[i]);
+		i++;
+		if (i >= n)
+			break;
+		if (tx_buf[i])
+			send_space(tx_buf[i]);
+		i++;
+	}
+	terminate_send(tx_buf[i - 1]);
+	return n;
+}
+
+
+static int lirc_ioctl(struct inode *node, struct file *filep,
+		      unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+	unsigned long value = 0;
+	unsigned int ivalue;
+	unsigned long hw_flags;
+
+	if (cmd == LIRC_GET_FEATURES)
+		value = LIRC_CAN_SEND_PULSE |
+			LIRC_CAN_SET_SEND_CARRIER |
+			LIRC_CAN_REC_MODE2;
+	else if (cmd == LIRC_GET_SEND_MODE)
+		value = LIRC_MODE_PULSE;
+	else if (cmd == LIRC_GET_REC_MODE)
+		value = LIRC_MODE_MODE2;
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+	case LIRC_GET_SEND_MODE:
+	case LIRC_GET_REC_MODE:
+		retval = put_user(value, (unsigned long *) arg);
+		break;
+
+	case LIRC_SET_SEND_MODE:
+	case LIRC_SET_REC_MODE:
+		retval = get_user(value, (unsigned long *) arg);
+		break;
+
+	case LIRC_SET_SEND_CARRIER:
+		retval = get_user(ivalue, (unsigned int *) arg);
+		if (retval)
+			return retval;
+		ivalue /= 1000;
+		if (ivalue > IT87_CIR_FREQ_MAX ||
+		    ivalue < IT87_CIR_FREQ_MIN)
+			return -EINVAL;
+
+		it87_freq = ivalue;
+
+		spin_lock_irqsave(&hardware_lock, hw_flags);
+		outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |
+		      (it87_freq - IT87_CIR_FREQ_MIN) << 3),
+		      io + IT87_CIR_TCR2);
+		spin_unlock_irqrestore(&hardware_lock, hw_flags);
+		dprintk("demodulation frequency: %d kHz\n", it87_freq);
+
+		break;
+
+	default:
+		retval = -EINVAL;
+	}
+
+	if (retval)
+		return retval;
+
+	if (cmd == LIRC_SET_REC_MODE) {
+		if (value != LIRC_MODE_MODE2)
+			retval = -ENOSYS;
+	} else if (cmd == LIRC_SET_SEND_MODE) {
+		if (value != LIRC_MODE_PULSE)
+			retval = -ENOSYS;
+	}
+	return retval;
+}
+
+static void add_read_queue(int flag, unsigned long val)
+{
+	unsigned int new_rx_tail;
+	lirc_t newval;
+
+	dprintk("add flag %d with val %lu\n", flag, val);
+
+	newval = val & PULSE_MASK;
+
+	/*
+	 * statistically, pulses are ~TIME_CONST/2 too long. we could
+	 * maybe make this more exact, but this is good enough
+	 */
+	if (flag) {
+		/* pulse */
+		if (newval > TIME_CONST / 2)
+			newval -= TIME_CONST / 2;
+		else /* should not ever happen */
+			newval = 1;
+		newval |= PULSE_BIT;
+	} else
+		newval += TIME_CONST / 2;
+	new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);
+	if (new_rx_tail == rx_head) {
+		dprintk("Buffer overrun.\n");
+		return;
+	}
+	rx_buf[rx_tail] = newval;
+	rx_tail = new_rx_tail;
+	wake_up_interruptible(&lirc_read_queue);
+}
+
+
+static struct file_operations lirc_fops = {
+	.owner		= THIS_MODULE,
+	.read		= lirc_read,
+	.write		= lirc_write,
+	.poll		= lirc_poll,
+	.ioctl		= lirc_ioctl,
+	.open		= lirc_open,
+	.release	= lirc_close,
+};
+
+static int set_use_inc(void *data)
+{
+       return 0;
+}
+
+static void set_use_dec(void *data)
+{
+}
+
+static struct lirc_driver driver = {
+       .name		= LIRC_DRIVER_NAME,
+       .minor		= -1,
+       .code_length	= 1,
+       .sample_rate	= 0,
+       .data		= NULL,
+       .add_to_buf	= NULL,
+#ifndef LIRC_REMOVE_DURING_EXPORT
+       .get_queue	= NULL,
+#endif
+       .set_use_inc	= set_use_inc,
+       .set_use_dec	= set_use_dec,
+       .fops		= &lirc_fops,
+       .dev		= NULL,
+       .owner		= THIS_MODULE,
+};
+
+
+static int init_chrdev(void)
+{
+	driver.minor = lirc_register_driver(&driver);
+
+	if (driver.minor < 0) {
+		printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+
+static void drop_chrdev(void)
+{
+	lirc_unregister_driver(driver.minor);
+}
+
+
+/* SECTION: Hardware */
+static long delta(struct timeval *tv1, struct timeval *tv2)
+{
+	unsigned long deltv;
+
+	deltv = tv2->tv_sec - tv1->tv_sec;
+	if (deltv > 15)
+		deltv = 0xFFFFFF;
+	else
+		deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec;
+	return deltv;
+}
+
+static void it87_timeout(unsigned long data)
+{
+	unsigned long flags;
+
+	/* avoid interference with interrupt */
+	spin_lock_irqsave(&timer_lock, flags);
+
+	if (digimatrix) {
+		/* We have timed out. Disable the RX mechanism. */
+
+		outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) |
+		     IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR);
+		if (it87_RXEN_mask)
+			outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
+			     io + IT87_CIR_RCR);
+		dprintk(" TIMEOUT\n");
+		timer_enabled = 0;
+
+		/* fifo clear */
+		outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR,
+		     io+IT87_CIR_TCR1);
+
+	} else {
+		/*
+		 * if last received signal was a pulse, but receiving stopped
+		 * within the 9 bit frame, we need to finish this pulse and
+		 * simulate a signal change to from pulse to space. Otherwise
+		 * upper layers will receive two sequences next time.
+		 */
+
+		if (last_value) {
+			unsigned long pulse_end;
+
+			/* determine 'virtual' pulse end: */
+			pulse_end = delta(&last_tv, &last_intr_tv);
+			dprintk("timeout add %d for %lu usec\n",
+				last_value, pulse_end);
+			add_read_queue(last_value, pulse_end);
+			last_value = 0;
+			last_tv = last_intr_tv;
+		}
+	}
+	spin_unlock_irqrestore(&timer_lock, flags);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static irqreturn_t it87_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#else
+static irqreturn_t it87_interrupt(int irq, void *dev_id)
+#endif
+{
+	unsigned char data;
+	struct timeval curr_tv;
+	static unsigned long deltv;
+	unsigned long deltintrtv;
+	unsigned long flags, hw_flags;
+	int iir, lsr;
+	int fifo = 0;
+	static char lastbit;
+	char bit;
+
+	/* Bit duration in microseconds */
+	const unsigned long bit_duration = 1000000ul /
+		(115200 / IT87_CIR_BAUDRATE_DIVISOR);
+
+
+	iir = inb(io + IT87_CIR_IIR);
+
+	switch (iir & IT87_CIR_IIR_IID) {
+	case 0x4:
+	case 0x6:
+		lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO |
+						IT87_CIR_RSR_RXFBC);
+		fifo = lsr & IT87_CIR_RSR_RXFBC;
+		dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr);
+
+		/* avoid interference with timer */
+		spin_lock_irqsave(&timer_lock, flags);
+		spin_lock_irqsave(&hardware_lock, hw_flags);
+		if (digimatrix) {
+			static unsigned long acc_pulse;
+			static unsigned long acc_space;
+
+			do {
+				data = inb(io + IT87_CIR_DR);
+				data = ~data;
+				fifo--;
+				if (data != 0x00) {
+					if (timer_enabled)
+						del_timer(&timerlist);
+					/*
+					 * start timer for end of
+					 * sequence detection
+					 */
+					timerlist.expires = jiffies +
+							    IT87_TIMEOUT;
+					add_timer(&timerlist);
+					timer_enabled = 1;
+				}
+				/* Loop through */
+				for (bit = 0; bit < 8; ++bit) {
+					if ((data >> bit) & 1) {
+						++acc_pulse;
+						if (lastbit == 0) {
+							add_read_queue(0,
+								acc_space *
+								 bit_duration);
+							acc_space = 0;
+						}
+					} else {
+						++acc_space;
+						if (lastbit == 1) {
+							add_read_queue(1,
+								acc_pulse *
+								 bit_duration);
+							acc_pulse = 0;
+						}
+					}
+					lastbit = (data >> bit) & 1;
+				}
+
+			} while (fifo != 0);
+		} else { /* Normal Operation */
+			do {
+				del_timer(&timerlist);
+				data = inb(io + IT87_CIR_DR);
+
+				dprintk("data=%.2x\n", data);
+				do_gettimeofday(&curr_tv);
+				deltv = delta(&last_tv, &curr_tv);
+				deltintrtv = delta(&last_intr_tv, &curr_tv);
+
+				dprintk("t %lu , d %d\n",
+					deltintrtv, (int)data);
+
+				/*
+				 * if nothing came in last 2 cycles,
+				 * it was gap
+				 */
+				if (deltintrtv > TIME_CONST * 2) {
+					if (last_value) {
+						dprintk("GAP\n");
+
+						/* simulate signal change */
+						add_read_queue(last_value,
+							       deltv -
+							       deltintrtv);
+						last_value = 0;
+						last_tv.tv_sec =
+							last_intr_tv.tv_sec;
+						last_tv.tv_usec =
+							last_intr_tv.tv_usec;
+						deltv = deltintrtv;
+					}
+				}
+				data = 1;
+				if (data ^ last_value) {
+					/*
+					 * deltintrtv > 2*TIME_CONST,
+					 * remember ? the other case is
+					 * timeout
+					 */
+					add_read_queue(last_value,
+						       deltv-TIME_CONST);
+					last_value = data;
+					last_tv = curr_tv;
+					if (last_tv.tv_usec >= TIME_CONST)
+						last_tv.tv_usec -= TIME_CONST;
+					else {
+						last_tv.tv_sec--;
+						last_tv.tv_usec += 1000000 -
+							TIME_CONST;
+					}
+				}
+				last_intr_tv = curr_tv;
+				if (data) {
+					/*
+					 * start timer for end of
+					 * sequence detection
+					 */
+					timerlist.expires =
+						jiffies + IT87_TIMEOUT;
+					add_timer(&timerlist);
+				}
+				outb((inb(io + IT87_CIR_RCR) &
+				     ~IT87_CIR_RCR_RXEN) |
+				     IT87_CIR_RCR_RXACT,
+				     io + IT87_CIR_RCR);
+				if (it87_RXEN_mask)
+					outb(inb(io + IT87_CIR_RCR) |
+					     IT87_CIR_RCR_RXEN,
+					     io + IT87_CIR_RCR);
+				fifo--;
+			} while (fifo != 0);
+		}
+		spin_unlock_irqrestore(&hardware_lock, hw_flags);
+		spin_unlock_irqrestore(&timer_lock, flags);
+
+		return IRQ_RETVAL(IRQ_HANDLED);
+
+	default:
+		/* not our irq */
+		dprintk("unknown IRQ (shouldn't happen) !!\n");
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+}
+
+
+static void send_it87(unsigned long len, unsigned long stime,
+		      unsigned char send_byte, unsigned int count_bits)
+{
+	long count = len / stime;
+	long time_left = 0;
+	static unsigned char byte_out;
+	unsigned long hw_flags;
+
+	dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte);
+
+	time_left = (long)len - (long)count * (long)stime;
+	count += ((2 * time_left) / stime);
+	while (count) {
+		long i = 0;
+		for (i = 0; i < count_bits; i++) {
+			byte_out = (byte_out << 1) | (send_byte & 1);
+			it87_bits_in_byte_out++;
+		}
+		if (it87_bits_in_byte_out == 8) {
+			dprintk("out=0x%x, tsr_txfbc: 0x%x\n",
+				byte_out,
+				inb(io + IT87_CIR_TSR) &
+				IT87_CIR_TSR_TXFBC);
+
+			while ((inb(io + IT87_CIR_TSR) &
+				IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE)
+				;
+
+			spin_lock_irqsave(&hardware_lock, hw_flags);
+			outb(byte_out, io + IT87_CIR_DR);
+			spin_unlock_irqrestore(&hardware_lock, hw_flags);
+
+			it87_bits_in_byte_out = 0;
+			it87_send_counter++;
+			byte_out = 0;
+		}
+		count--;
+	}
+}
+
+
+/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */
+
+static void send_space(unsigned long len)
+{
+	send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR);
+}
+
+static void send_pulse(unsigned long len)
+{
+	send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR);
+}
+
+
+static void init_send()
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hardware_lock, flags);
+	/* RXEN=0: receiver disable */
+	it87_RXEN_mask = 0;
+	outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN,
+	     io + IT87_CIR_RCR);
+	spin_unlock_irqrestore(&hardware_lock, flags);
+	it87_bits_in_byte_out = 0;
+	it87_send_counter = 0;
+}
+
+
+static void terminate_send(unsigned long len)
+{
+	unsigned long flags;
+	unsigned long last = 0;
+
+	last = it87_send_counter;
+	/* make sure all necessary data has been sent */
+	while (last == it87_send_counter)
+		send_space(len);
+	/* wait until all data sent */
+	while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0)
+		;
+	/* then re-enable receiver */
+	spin_lock_irqsave(&hardware_lock, flags);
+	it87_RXEN_mask = IT87_CIR_RCR_RXEN;
+	outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
+	     io + IT87_CIR_RCR);
+	spin_unlock_irqrestore(&hardware_lock, flags);
+}
+
+
+static int init_hardware(void)
+{
+	unsigned long flags;
+	unsigned char it87_rcr = 0;
+
+	spin_lock_irqsave(&hardware_lock, flags);
+	/* init cir-port */
+	/* enable r/w-access to Baudrate-Register */
+	outb(IT87_CIR_IER_BR, io + IT87_CIR_IER);
+	outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR);
+	outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR);
+	/* Baudrate Register off, define IRQs: Input only */
+	if (digimatrix) {
+		outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER);
+		/* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */
+	} else {
+		outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER);
+		/* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */
+	}
+	it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1;
+	if (it87_enable_demodulator)
+		it87_rcr |= IT87_CIR_RCR_RXEND;
+	outb(it87_rcr, io + IT87_CIR_RCR);
+	if (digimatrix) {
+		/* Set FIFO depth to 1 byte, and disable TX */
+		outb(inb(io + IT87_CIR_TCR1) |  0x00,
+		     io + IT87_CIR_TCR1);
+
+		/*
+		 * TX: it87_freq (36kHz), 'reserved' sensitivity
+		 * setting (0x00)
+		 */
+		outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00,
+		     io + IT87_CIR_TCR2);
+	} else {
+		/* TX: 38kHz, 13,3us (pulse-width) */
+		outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06,
+		     io + IT87_CIR_TCR2);
+	}
+	spin_unlock_irqrestore(&hardware_lock, flags);
+	return 0;
+}
+
+
+static void drop_hardware(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hardware_lock, flags);
+	disable_irq(irq);
+	/* receiver disable */
+	it87_RXEN_mask = 0;
+	outb(0x1, io + IT87_CIR_RCR);
+	/* turn off irqs */
+	outb(0, io + IT87_CIR_IER);
+	/* fifo clear */
+	outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1);
+	/* reset */
+	outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
+	enable_irq(irq);
+	spin_unlock_irqrestore(&hardware_lock, flags);
+}
+
+
+static unsigned char it87_read(unsigned char port)
+{
+	outb(port, IT87_ADRPORT);
+	return inb(IT87_DATAPORT);
+}
+
+
+static void it87_write(unsigned char port, unsigned char data)
+{
+	outb(port, IT87_ADRPORT);
+	outb(data, IT87_DATAPORT);
+}
+
+
+/* SECTION: Initialisation */
+
+static int init_port(void)
+{
+	unsigned long hw_flags;
+	int retval = 0;
+
+	unsigned char init_bytes[4] = IT87_INIT;
+	unsigned char it87_chipid = 0;
+	unsigned char ldn = 0;
+	unsigned int  it87_io = 0;
+	unsigned int  it87_irq = 0;
+
+	/* Enter MB PnP Mode */
+	outb(init_bytes[0], IT87_ADRPORT);
+	outb(init_bytes[1], IT87_ADRPORT);
+	outb(init_bytes[2], IT87_ADRPORT);
+	outb(init_bytes[3], IT87_ADRPORT);
+
+	/* 8712 or 8705 ? */
+	it87_chipid = it87_read(IT87_CHIP_ID1);
+	if (it87_chipid != 0x87) {
+		retval = -ENXIO;
+		return retval;
+	}
+	it87_chipid = it87_read(IT87_CHIP_ID2);
+	if ((it87_chipid != 0x12) &&
+		(it87_chipid != 0x05) &&
+		(it87_chipid != 0x20)) {
+		printk(KERN_INFO LIRC_DRIVER_NAME
+		       ": no IT8705/12/20 found, exiting..\n");
+		retval = -ENXIO;
+		return retval;
+	}
+	printk(KERN_INFO LIRC_DRIVER_NAME
+	       ": found IT87%.2x.\n",
+	       it87_chipid);
+
+	/* get I/O-Port and IRQ */
+	if (it87_chipid == 0x12)
+		ldn = IT8712_CIR_LDN;
+	else
+		ldn = IT8705_CIR_LDN;
+	it87_write(IT87_LDN, ldn);
+
+	it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 +
+		  it87_read(IT87_CIR_BASE_LSB);
+	if (it87_io == 0) {
+		if (io == 0)
+			io = IT87_CIR_DEFAULT_IOBASE;
+		printk(KERN_INFO LIRC_DRIVER_NAME
+		       ": set default io 0x%x\n",
+		       io);
+		it87_write(IT87_CIR_BASE_MSB, io / 0x100);
+		it87_write(IT87_CIR_BASE_LSB, io % 0x100);
+	} else
+		io = it87_io;
+
+	it87_irq = it87_read(IT87_CIR_IRQ);
+	if (digimatrix || it87_irq == 0) {
+		if (irq == 0)
+			irq = IT87_CIR_DEFAULT_IRQ;
+		printk(KERN_INFO LIRC_DRIVER_NAME
+		       ": set default irq 0x%x\n",
+		       irq);
+		it87_write(IT87_CIR_IRQ, irq);
+	} else
+		irq = it87_irq;
+
+	spin_lock_irqsave(&hardware_lock, hw_flags);
+	/* reset */
+	outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
+	/* fifo clear */
+	outb(IT87_CIR_TCR1_FIFOCLR |
+	     /*	     IT87_CIR_TCR1_ILE | */
+	     IT87_CIR_TCR1_TXRLE |
+	     IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1);
+	spin_unlock_irqrestore(&hardware_lock, hw_flags);
+
+	/* get I/O port access and IRQ line */
+	if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
+		printk(KERN_ERR LIRC_DRIVER_NAME
+		       ": i/o port 0x%.4x already in use.\n", io);
+		/* Leaving MB PnP Mode */
+		it87_write(IT87_CFGCTRL, 0x2);
+		return -EBUSY;
+	}
+
+	/* activate CIR-Device */
+	it87_write(IT87_CIR_ACT, 0x1);
+
+	/* Leaving MB PnP Mode */
+	it87_write(IT87_CFGCTRL, 0x2);
+
+	retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/,
+			     LIRC_DRIVER_NAME, NULL);
+	if (retval < 0) {
+		printk(KERN_ERR LIRC_DRIVER_NAME
+		       ": IRQ %d already in use.\n",
+		       irq);
+		release_region(io, 8);
+		return retval;
+	}
+
+	printk(KERN_INFO LIRC_DRIVER_NAME
+	       ": I/O port 0x%.4x, IRQ %d.\n", io, irq);
+
+	init_timer(&timerlist);
+	timerlist.function = it87_timeout;
+	timerlist.data = 0xabadcafe;
+
+	return 0;
+}
+
+
+static void drop_port(void)
+{
+#if 0
+	unsigned char init_bytes[4] = IT87_INIT;
+
+	/* Enter MB PnP Mode */
+	outb(init_bytes[0], IT87_ADRPORT);
+	outb(init_bytes[1], IT87_ADRPORT);
+	outb(init_bytes[2], IT87_ADRPORT);
+	outb(init_bytes[3], IT87_ADRPORT);
+
+	/* deactivate CIR-Device */
+	it87_write(IT87_CIR_ACT, 0x0);
+
+	/* Leaving MB PnP Mode */
+	it87_write(IT87_CFGCTRL, 0x2);
+#endif
+
+	del_timer_sync(&timerlist);
+	free_irq(irq, NULL);
+	release_region(io, 8);
+}
+
+
+static int init_lirc_it87(void)
+{
+	int retval;
+
+	init_waitqueue_head(&lirc_read_queue);
+	retval = init_port();
+	if (retval < 0)
+		return retval;
+	init_hardware();
+	printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n");
+	return 0;
+}
+
+
+static int __init lirc_it87_init(void)
+{
+	int retval;
+
+	retval = init_chrdev();
+	if (retval < 0)
+		return retval;
+	retval = init_lirc_it87();
+	if (retval) {
+		drop_chrdev();
+		return retval;
+	}
+	return 0;
+}
+
+
+static void __exit lirc_it87_exit(void)
+{
+	drop_hardware();
+	drop_chrdev();
+	drop_port();
+	printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
+}
+
+module_init(lirc_it87_init);
+module_exit(lirc_it87_exit);
+
+MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port");
+MODULE_AUTHOR("Hans-Günter Lütke Uphues");
+MODULE_LICENSE("GPL");
+
+module_param(io, int, S_IRUGO);
+MODULE_PARM_DESC(io, "I/O base address (default: 0x310)");
+
+module_param(irq, int, S_IRUGO);
+#ifdef LIRC_IT87_DIGIMATRIX
+MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)");
+#else
+MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)");
+#endif
+
+module_param(it87_enable_demodulator, bool, S_IRUGO);
+MODULE_PARM_DESC(it87_enable_demodulator,
+		 "Receiver demodulator enable/disable (1/0), default: 0");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+module_param(digimatrix, bool, S_IRUGO | S_IWUSR);
+#ifdef LIRC_IT87_DIGIMATRIX
+MODULE_PARM_DESC(digimatrix,
+	"Asus Digimatrix it87 compat. enable/disable (1/0), default: 1");
+#else
+MODULE_PARM_DESC(digimatrix,
+	"Asus Digimatrix it87 compat. enable/disable (1/0), default: 0");
+#endif
+
+
+module_param(it87_freq, int, S_IRUGO);
+#ifdef LIRC_IT87_DIGIMATRIX
+MODULE_PARM_DESC(it87_freq,
+    "Carrier demodulator frequency (kHz), (default: 36)");
+#else
+MODULE_PARM_DESC(it87_freq,
+    "Carrier demodulator frequency (kHz), (default: 38)");
+#endif
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ene0100/lirc_ene0100.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ene0100/lirc_ene0100.h
@@ -0,0 +1,170 @@
+/*
+ * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
+ *
+ * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * 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 "../kcompat.h"
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+
+/* hardware address */
+#define ENE_STATUS		0	 /* hardware status - unused */
+#define ENE_ADDR_HI 		1	 /* hi byte of register address */
+#define ENE_ADDR_LO 		2	 /* low byte of register address */
+#define ENE_IO 			3	 /* read/write window */
+#define ENE_MAX_IO		4
+
+/* 8 bytes of samples, divided in 2 halfs*/
+#define ENE_SAMPLE_BUFFER 	0xF8F0	 /* regular sample buffer */
+#define ENE_SAMPLE_SPC_MASK 	(1 << 7) /* sample is space */
+#define ENE_SAMPLE_VALUE_MASK	0x7F
+#define ENE_SAMPLE_OVERFLOW	0x7F
+#define ENE_SAMPLES_SIZE	4
+
+/* fan input sample buffer */
+#define ENE_SAMPLE_BUFFER_FAN	0xF8FB	 /* this buffer holds high byte of */
+					 /* each sample of normal buffer */
+
+#define ENE_FAN_SMPL_PULS_MSK	0x8000	 /* this bit of combined sample */
+					 /* if set, says that sample is pulse */
+#define ENE_FAN_VALUE_MASK	0x0FFF   /* mask for valid bits of the value */
+
+/* first firmware register */
+#define ENE_FW1			0xF8F8
+#define	ENE_FW1_ENABLE		(1 << 0) /* enable fw processing */
+#define ENE_FW1_TXIRQ		(1 << 1) /* TX interrupt pending */
+#define ENE_FW1_WAKE		(1 << 6) /* enable wake from S3 */
+#define ENE_FW1_IRQ		(1 << 7) /* enable interrupt */
+
+/* second firmware register */
+#define ENE_FW2			0xF8F9
+#define ENE_FW2_BUF_HIGH	(1 << 0) /* which half of the buffer to read */
+#define ENE_FW2_IRQ_CLR		(1 << 2) /* clear this on IRQ */
+#define ENE_FW2_GP40_AS_LEARN	(1 << 4) /* normal input is used as */
+					 /* learning input */
+#define ENE_FW2_FAN_AS_NRML_IN	(1 << 6) /* fan is used as normal input */
+#define ENE_FW2_LEARNING	(1 << 7) /* hardware supports learning and TX */
+
+/* fan as input settings - only if learning capable */
+#define ENE_FAN_AS_IN1		0xFE30   /* fan init reg 1 */
+#define ENE_FAN_AS_IN1_EN	0xCD
+#define ENE_FAN_AS_IN2		0xFE31   /* fan init reg 2 */
+#define ENE_FAN_AS_IN2_EN	0x03
+#define ENE_SAMPLE_PERIOD_FAN   61	 /* fan input has fixed sample period */
+
+/* IRQ registers block (for revision B) */
+#define ENEB_IRQ		0xFD09	 /* IRQ number */
+#define ENEB_IRQ_UNK1		0xFD17	 /* unknown setting = 1 */
+#define ENEB_IRQ_STATUS		0xFD80	 /* irq status */
+#define ENEB_IRQ_STATUS_IR	(1 << 5) /* IR irq */
+
+/* IRQ registers block (for revision C,D) */
+#define ENEC_IRQ		0xFE9B	 /* new irq settings register */
+#define ENEC_IRQ_MASK		0x0F	 /* irq number mask */
+#define ENEC_IRQ_UNK_EN		(1 << 4) /* always enabled */
+#define ENEC_IRQ_STATUS		(1 << 5) /* irq status and ACK */
+
+/* CIR block settings */
+#define ENE_CIR_CONF1		0xFEC0
+#define ENE_CIR_CONF1_ADC_ON	0x7	 /* reciever on gpio40 enabled */
+#define ENE_CIR_CONF1_LEARN1	(1 << 3) /* enabled on learning mode */
+#define ENE_CIR_CONF1_TX_ON	0x30	 /* enabled on transmit */
+#define ENE_CIR_CONF1_TX_CARR	(1 << 7) /* send TX carrier or not */
+
+#define ENE_CIR_CONF2		0xFEC1	 /* unknown setting = 0 */
+#define ENE_CIR_CONF2_LEARN2	(1 << 4) /* set on enable learning */
+#define ENE_CIR_CONF2_GPIO40DIS	(1 << 5) /* disable normal input via gpio40 */
+
+#define ENE_CIR_SAMPLE_PERIOD	0xFEC8	 /* sample period in us */
+#define ENE_CIR_SAMPLE_OVERFLOW	(1 << 7) /* interrupt on overflows if set */
+
+
+/* transmitter - not implemented yet */
+/* KB3926C and higher */
+/* transmission is very similiar to recieving, a byte is written to */
+/* ENE_TX_INPUT, in same manner as it is read from sample buffer */
+/* sample period is fixed*/
+
+
+/* transmitter ports */
+#define ENE_TX_PORT1		0xFC01	 /* this enables one or both */
+#define ENE_TX_PORT1_EN		(1 << 5) /* TX ports */
+#define ENE_TX_PORT2		0xFC08
+#define ENE_TX_PORT2_EN		(1 << 1)
+
+#define ENE_TX_INPUT		0xFEC9	 /* next byte to transmit */
+#define ENE_TX_SPC_MASK 	(1 << 7) /* Transmitted sample is space */
+#define ENE_TX_UNK1		0xFECB	 /* set to 0x63 */
+#define ENE_TX_SMPL_PERIOD	50	 /* transmit sample period */
+
+
+#define ENE_TX_CARRIER		0xFECE	 /* TX carrier * 2 (khz) */
+#define ENE_TX_CARRIER_UNKBIT	0x80	 /* This bit set on transmit */
+#define ENE_TX_CARRIER_LOW	0xFECF	 /* TX carrier / 2 */
+
+/* Hardware versions */
+#define ENE_HW_VERSION		0xFF00	 /* hardware revision */
+#define ENE_HW_UNK 		0xFF1D
+#define ENE_HW_UNK_CLR		(1 << 2)
+#define ENE_HW_VER_MAJOR	0xFF1E	 /* chip version */
+#define ENE_HW_VER_MINOR	0xFF1F
+#define ENE_HW_VER_OLD		0xFD00
+
+#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0))
+
+#define ENE_DRIVER_NAME 	"enecir"
+#define ENE_MAXGAP 		250000	 /* this is amount of time we wait
+					 before turning the sampler, chosen
+					 arbitry */
+
+#define space(len) 	       (-(len))	 /* add a space */
+
+/* software defines */
+#define ENE_IRQ_RX		1
+#define ENE_IRQ_TX		2
+
+#define  ENE_HW_B		1	/* 3926B */
+#define  ENE_HW_C		2	/* 3926C */
+#define  ENE_HW_D		3	/* 3926D */
+
+#define ene_printk(level, text, ...) \
+	printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
+
+struct ene_device {
+	struct pnp_dev *pnp_dev;
+	struct lirc_driver *lirc_driver;
+
+	/* hw settings */
+	unsigned long hw_io;
+	int irq;
+
+	int hw_revision;			/* hardware revision */
+	int hw_learning_and_tx_capable;		/* learning capable */
+	int hw_gpio40_learning;			/* gpio40 is learning */
+	int hw_fan_as_normal_input;	/* fan input is used as regular input */
+
+	/* device data */
+	int idle;
+	int fan_input_inuse;
+
+	int sample;
+	int in_use;
+
+	struct timeval gap_start;
+};
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ene0100/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ene0100/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_ENE0100)		+= lirc_ene0100.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ene0100/lirc_ene0100.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ene0100/lirc_ene0100.c
@@ -0,0 +1,653 @@
+/*
+ * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
+ *
+ * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com>
+ *
+ * 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/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include "lirc_ene0100.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#error "Sorry, this driver needs kernel version 2.6.16 or higher"
+#else
+
+static int sample_period = 75;
+static int enable_idle = 1;
+static int enable_learning;
+
+static void ene_set_idle(struct ene_device *dev, int idle);
+static void ene_set_inputs(struct ene_device *dev, int enable);
+
+/* read a hardware register */
+static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg)
+{
+	outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+	outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+	return inb(dev->hw_io + ENE_IO);
+}
+
+/* write a hardware register */
+static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value)
+{
+	outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+	outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+	outb(value, dev->hw_io + ENE_IO);
+}
+
+/* change specific bits in hardware register */
+static void ene_hw_write_reg_mask(struct ene_device *dev,
+				  u16 reg, u8 value, u8 mask)
+{
+	u8 regvalue;
+
+	outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+	outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+
+	regvalue = inb(dev->hw_io + ENE_IO) & ~mask;
+	regvalue |= (value & mask);
+	outb(regvalue, dev->hw_io + ENE_IO);
+}
+
+/* read irq status and ack it */
+static int ene_hw_irq_status(struct ene_device *dev, int *buffer_pointer)
+{
+	u8 irq_status;
+	u8 fw_flags1, fw_flags2;
+
+	fw_flags2 = ene_hw_read_reg(dev, ENE_FW2);
+
+	if (buffer_pointer)
+		*buffer_pointer = 4 * (fw_flags2 & ENE_FW2_BUF_HIGH);
+
+	if (dev->hw_revision < ENE_HW_C) {
+		irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS);
+
+		if (!irq_status & ENEB_IRQ_STATUS_IR)
+			return 0;
+		ene_hw_write_reg(dev, ENEB_IRQ_STATUS,
+				 irq_status & ~ENEB_IRQ_STATUS_IR);
+
+		/* rev B support only recieving */
+		return ENE_IRQ_RX;
+	}
+
+	irq_status = ene_hw_read_reg(dev, ENEC_IRQ);
+
+	if (!irq_status && ENEC_IRQ_STATUS)
+		return 0;
+
+	/* original driver does that twice - a workaround ? */
+	ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
+	ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
+
+	/* clear unknown flag in F8F9 */
+	if (fw_flags2 & ENE_FW2_IRQ_CLR)
+		ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR);
+
+	/* check if this is a TX interrupt */
+	fw_flags1 = ene_hw_read_reg(dev, ENE_FW1);
+
+	if (fw_flags1 & ENE_FW1_TXIRQ) {
+		ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
+		return ENE_IRQ_TX;
+	} else
+		return ENE_IRQ_RX;
+}
+
+static int ene_hw_detect(struct ene_device *dev)
+{
+	u8 chip_major, chip_minor;
+	u8 hw_revision, old_ver;
+	u8 tmp;
+	u8 fw_capabilities;
+
+	tmp = ene_hw_read_reg(dev, ENE_HW_UNK);
+	ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR);
+
+	chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR);
+	chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR);
+
+	ene_hw_write_reg(dev, ENE_HW_UNK, tmp);
+	hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION);
+	old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD);
+
+	if (hw_revision == 0xFF) {
+
+		ene_printk(KERN_WARNING, "device seems to be disabled\n");
+		ene_printk(KERN_WARNING,
+			"send a mail to lirc-list@lists.sourceforge.net\n");
+		ene_printk(KERN_WARNING, "please attach output of acpidump\n");
+
+		return -ENODEV;
+	}
+
+	if (chip_major == 0x33) {
+		ene_printk(KERN_WARNING, "chips 0x33xx aren't supported yet\n");
+		return -ENODEV;
+	}
+
+	if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
+		dev->hw_revision = ENE_HW_C;
+		ene_printk(KERN_WARNING,
+		       "KB3926C detected, driver support is not complete!\n");
+
+	} else if (old_ver == 0x24 && hw_revision == 0xC0) {
+		dev->hw_revision = ENE_HW_B;
+		ene_printk(KERN_NOTICE, "KB3926B detected\n");
+	} else {
+		dev->hw_revision = ENE_HW_D;
+		ene_printk(KERN_WARNING,
+			"unknown ENE chip detected, assuming KB3926D\n");
+		ene_printk(KERN_WARNING, "driver support incomplete");
+
+	}
+
+	ene_printk(KERN_DEBUG, "chip is 0x%02x%02x - 0x%02x, 0x%02x\n",
+		chip_major, chip_minor, old_ver, hw_revision);
+
+
+	/* detect features hardware supports */
+
+	if (dev->hw_revision < ENE_HW_C)
+		return 0;
+
+	fw_capabilities = ene_hw_read_reg(dev, ENE_FW2);
+
+	dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN;
+	dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING;
+
+	dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable &&
+	    fw_capabilities & ENE_FW2_FAN_AS_NRML_IN;
+
+	ene_printk(KERN_NOTICE, "hardware features:\n");
+	ene_printk(KERN_NOTICE,
+		"learning and tx %s, gpio40_learn %s, fan_in %s\n",
+	       dev->hw_learning_and_tx_capable ? "on" : "off",
+	       dev->hw_gpio40_learning ? "on" : "off",
+	       dev->hw_fan_as_normal_input ? "on" : "off");
+
+	if (!dev->hw_learning_and_tx_capable && enable_learning)
+		enable_learning = 0;
+
+	if (dev->hw_learning_and_tx_capable) {
+		ene_printk(KERN_WARNING,
+		"Device supports transmitting, but the driver doesn't\n");
+		ene_printk(KERN_WARNING,
+		"due to lack of hardware to test against.\n");
+		ene_printk(KERN_WARNING,
+		"Send a mail to: lirc-list@lists.sourceforge.net\n");
+	}
+	return 0;
+}
+
+/* hardware initialization */
+static int ene_hw_init(void *data)
+{
+	u8 reg_value;
+	struct ene_device *dev = (struct ene_device *)data;
+	dev->in_use = 1;
+
+	if (dev->hw_revision < ENE_HW_C) {
+		ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1);
+		ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
+	} else {
+		reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0;
+		reg_value |= ENEC_IRQ_UNK_EN;
+		reg_value &= ~ENEC_IRQ_STATUS;
+		reg_value |= (dev->irq & ENEC_IRQ_MASK);
+		ene_hw_write_reg(dev, ENEC_IRQ, reg_value);
+		ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63);
+	}
+
+	ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00);
+	ene_set_inputs(dev, enable_learning);
+
+	/* set sampling period */
+	ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period);
+
+	/* ack any pending irqs - just in case */
+	ene_hw_irq_status(dev, NULL);
+
+	/* enter idle mode */
+	ene_set_idle(dev, 1);
+
+	/* enable firmware bits */
+	ene_hw_write_reg_mask(dev, ENE_FW1,
+			      ENE_FW1_ENABLE | ENE_FW1_IRQ,
+			      ENE_FW1_ENABLE | ENE_FW1_IRQ);
+	/* clear stats */
+	dev->sample = 0;
+	return 0;
+}
+
+/* this enables gpio40 signal, used if connected to wide band input*/
+static void ene_enable_gpio40(struct ene_device *dev, int enable)
+{
+	ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, enable ?
+			      0 : ENE_CIR_CONF2_GPIO40DIS,
+			      ENE_CIR_CONF2_GPIO40DIS);
+}
+
+/* this enables the classic sampler */
+static void ene_enable_normal_recieve(struct ene_device *dev, int enable)
+{
+	ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_ADC_ON : 0);
+}
+
+/* this enables recieve via fan input */
+static void ene_enable_fan_recieve(struct ene_device *dev, int enable)
+{
+	if (!enable)
+		ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0);
+	else {
+		ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
+		ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
+	}
+	dev->fan_input_inuse = enable;
+}
+
+/* determine which input to use*/
+static void ene_set_inputs(struct ene_device *dev, int learning_enable)
+{
+	ene_enable_normal_recieve(dev, 1);
+
+	/* old hardware doesn't support learning mode for sure */
+	if (dev->hw_revision <= ENE_HW_B)
+		return;
+
+	/* reciever not learning capable, still set gpio40 correctly */
+	if (!dev->hw_learning_and_tx_capable) {
+		ene_enable_gpio40(dev, !dev->hw_gpio40_learning);
+		return;
+	}
+
+	/* enable learning mode */
+	if (learning_enable) {
+		ene_enable_gpio40(dev, dev->hw_gpio40_learning);
+
+		/* fan input is not used for learning */
+		if (dev->hw_fan_as_normal_input)
+			ene_enable_fan_recieve(dev, 0);
+
+	/* disable learning mode */
+	} else {
+		if (dev->hw_fan_as_normal_input) {
+			ene_enable_fan_recieve(dev, 1);
+			ene_enable_normal_recieve(dev, 0);
+		} else
+			ene_enable_gpio40(dev, !dev->hw_gpio40_learning);
+	}
+
+	/* set few additional settings for this mode */
+	ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_enable ?
+			      ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1);
+
+	ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_enable ?
+			      ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2);
+}
+
+/* deinitialization */
+static void ene_hw_deinit(void *data)
+{
+	struct ene_device *dev = (struct ene_device *)data;
+
+	/* disable samplers */
+	ene_enable_normal_recieve(dev, 0);
+
+	if (dev->hw_fan_as_normal_input)
+		ene_enable_fan_recieve(dev, 0);
+
+	/* disable hardware IRQ and firmware flag */
+	ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ);
+
+	ene_set_idle(dev, 1);
+	dev->in_use = 0;
+}
+
+/*  sends current sample to userspace */
+static void send_sample(struct ene_device *dev)
+{
+	int value = abs(dev->sample) & PULSE_MASK;
+
+	if (dev->sample > 0)
+		value |= PULSE_BIT;
+
+	if (!lirc_buffer_full(dev->lirc_driver->rbuf)) {
+		lirc_buffer_write(dev->lirc_driver->rbuf, (void *)&value);
+		wake_up(&dev->lirc_driver->rbuf->wait_poll);
+	}
+	dev->sample = 0;
+}
+
+/*  this updates current sample */
+static void update_sample(struct ene_device *dev, int sample)
+{
+	if (!dev->sample)
+		dev->sample = sample;
+	else if (same_sign(dev->sample, sample))
+		dev->sample += sample;
+	else {
+		send_sample(dev);
+		dev->sample = sample;
+	}
+}
+
+/* enable or disable idle mode */
+static void ene_set_idle(struct ene_device *dev, int idle)
+{
+	struct timeval now;
+	int disable = idle && enable_idle && (dev->hw_revision < ENE_HW_C);
+
+	ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD,
+			      disable ? 0 : ENE_CIR_SAMPLE_OVERFLOW,
+			      ENE_CIR_SAMPLE_OVERFLOW);
+	dev->idle = idle;
+
+	/* remember when we have entered the idle mode */
+	if (idle) {
+		do_gettimeofday(&dev->gap_start);
+		return;
+	}
+
+	/* send the gap between keypresses now */
+	do_gettimeofday(&now);
+
+	if (now.tv_sec - dev->gap_start.tv_sec > 16)
+		dev->sample = space(PULSE_MASK);
+	else
+		dev->sample = dev->sample +
+		    space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec))
+		    + space(now.tv_usec - dev->gap_start.tv_usec);
+
+	if (abs(dev->sample) > PULSE_MASK)
+		dev->sample = space(PULSE_MASK);
+	send_sample(dev);
+}
+
+/* interrupt handler */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t ene_hw_irq(int irq, void *data)
+#else
+static irqreturn_t ene_hw_irq(int irq, void *data, struct pt_regs *regs)
+#endif
+{
+	u16 hw_value;
+	int i, hw_sample;
+	int space;
+	int buffer_pointer;
+	int irq_status;
+
+	struct ene_device *dev = (struct ene_device *)data;
+	irq_status = ene_hw_irq_status(dev, &buffer_pointer);
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	/* TODO: only RX for now */
+	if (irq_status == ENE_IRQ_TX)
+		return IRQ_HANDLED;
+
+	for (i = 0; i < ENE_SAMPLES_SIZE; i++) {
+
+		hw_value = ene_hw_read_reg(dev,
+				ENE_SAMPLE_BUFFER + buffer_pointer + i);
+
+		if (dev->fan_input_inuse) {
+			/* read high part of the sample */
+			hw_value |= ene_hw_read_reg(dev,
+			    ENE_SAMPLE_BUFFER_FAN + buffer_pointer + i) << 8;
+
+			/* test for _space_ bit */
+			space = !(hw_value & ENE_FAN_SMPL_PULS_MSK);
+
+			/* clear space bit, and other unused bits */
+			hw_value &= ENE_FAN_VALUE_MASK;
+			hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN;
+
+		} else {
+			space = hw_value & ENE_SAMPLE_SPC_MASK;
+			hw_value &= ENE_SAMPLE_VALUE_MASK;
+			hw_sample = hw_value * sample_period;
+		}
+
+		/* no more data */
+		if (!(hw_value))
+			break;
+
+		if (space)
+			hw_sample *= -1;
+
+		/* overflow sample recieved, handle it */
+
+		if (!dev->fan_input_inuse && hw_value == ENE_SAMPLE_OVERFLOW) {
+
+			if (dev->idle)
+				continue;
+
+			if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP)
+				update_sample(dev, hw_sample);
+			else
+				ene_set_idle(dev, 1);
+
+			continue;
+		}
+
+		/* normal first sample recieved */
+		if (!dev->fan_input_inuse && dev->idle) {
+			ene_set_idle(dev, 0);
+
+			/* discard first recieved value, its random
+			   since its the time signal was off before
+			   first pulse if idle mode is enabled, HW
+			   does that for us */
+
+			if (!enable_idle)
+				continue;
+		}
+		update_sample(dev, hw_sample);
+		send_sample(dev);
+	}
+	return IRQ_HANDLED;
+}
+
+static int ene_probe(struct pnp_dev *pnp_dev,
+		     const struct pnp_device_id *dev_id)
+{
+	struct ene_device *dev;
+	struct lirc_driver *lirc_driver;
+	int error = -ENOMEM;
+
+	dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
+
+	if (!dev)
+		goto err1;
+
+	dev->pnp_dev = pnp_dev;
+	pnp_set_drvdata(pnp_dev, dev);
+
+
+	/* prepare lirc interface */
+	error = -ENOMEM;
+	lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+
+	if (!lirc_driver)
+		goto err2;
+
+	dev->lirc_driver = lirc_driver;
+
+	strcpy(lirc_driver->name, ENE_DRIVER_NAME);
+	lirc_driver->minor = -1;
+	lirc_driver->code_length = sizeof(int) * 8;
+	lirc_driver->features = LIRC_CAN_REC_MODE2;
+	lirc_driver->data = dev;
+	lirc_driver->set_use_inc = ene_hw_init;
+	lirc_driver->set_use_dec = ene_hw_deinit;
+	lirc_driver->dev = &pnp_dev->dev;
+	lirc_driver->owner = THIS_MODULE;
+
+	lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+
+	if (!lirc_driver->rbuf)
+		goto err3;
+
+	if (lirc_buffer_init(lirc_driver->rbuf, sizeof(int), sizeof(int) * 256))
+		goto err4;
+
+	error = -ENODEV;
+	if (lirc_register_driver(lirc_driver))
+		goto err5;
+
+	/* validate resources */
+	if (!pnp_port_valid(pnp_dev, 0) || pnp_port_len(pnp_dev, 0) < ENE_MAX_IO)
+		goto err6;
+
+	if (!pnp_irq_valid(pnp_dev, 0))
+		goto err6;
+
+	dev->hw_io = pnp_port_start(pnp_dev, 0);
+	dev->irq = pnp_irq(pnp_dev, 0);
+
+	/* claim the resources */
+	error = -EBUSY;
+	if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME))
+		goto err6;
+
+	if (request_irq(dev->irq, ene_hw_irq,
+			IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev))
+		goto err7;
+
+	/* detect hardware version and features */
+	error = ene_hw_detect(dev);
+	if (error)
+		goto err8;
+
+	ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n");
+	return 0;
+
+err8:
+	free_irq(dev->irq, dev);
+err7:
+	release_region(dev->hw_io, ENE_MAX_IO);
+err6:
+	lirc_unregister_driver(lirc_driver->minor);
+err5:
+	lirc_buffer_free(lirc_driver->rbuf);
+err4:
+	kfree(lirc_driver->rbuf);
+err3:
+	kfree(lirc_driver);
+err2:
+	kfree(dev);
+err1:
+	return error;
+}
+
+static void ene_remove(struct pnp_dev *pnp_dev)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	ene_hw_deinit(dev);
+	free_irq(dev->irq, dev);
+	release_region(dev->hw_io, ENE_MAX_IO);
+	lirc_unregister_driver(dev->lirc_driver->minor);
+	lirc_buffer_free(dev->lirc_driver->rbuf);
+	kfree(dev->lirc_driver);
+	kfree(dev);
+}
+
+#ifdef CONFIG_PM
+
+/* TODO: make 'wake on IR' configurable and add .shutdown */
+/* currently impossible due to lack of kernel support */
+
+static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	ene_hw_write_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, ENE_FW1_WAKE);
+	return 0;
+}
+
+static int ene_resume(struct pnp_dev *pnp_dev)
+{
+	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+	if (dev->in_use)
+		ene_hw_init(dev);
+
+	ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_WAKE);
+	return 0;
+}
+
+#endif
+
+static const struct pnp_device_id ene_ids[] = {
+	{.id = "ENE0100",},
+	{},
+};
+
+static struct pnp_driver ene_driver = {
+	.name = ENE_DRIVER_NAME,
+	.id_table = ene_ids,
+	.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
+
+	.probe = ene_probe,
+	.remove = __devexit_p(ene_remove),
+
+#ifdef CONFIG_PM
+	.suspend = ene_suspend,
+	.resume = ene_resume,
+#endif
+};
+
+static int __init ene_init(void)
+{
+	if (sample_period < 5) {
+		ene_printk(KERN_ERR, "sample period must be at\n");
+		ene_printk(KERN_ERR, "least 5 us, (at least 30 recommended)\n");
+		return -EINVAL;
+	}
+	return pnp_register_driver(&ene_driver);
+}
+
+static void ene_exit(void)
+{
+	pnp_unregister_driver(&ene_driver);
+}
+
+module_param(sample_period, int, S_IRUGO);
+MODULE_PARM_DESC(sample_period, "Hardware sample period (75 us default)");
+
+module_param(enable_idle, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_idle,
+	"Enables turning off signal sampling after long inactivity time; "
+	"if disabled might help detecting input signal (default: enabled)");
+
+module_param(enable_learning, bool, S_IRUGO);
+MODULE_PARM_DESC(enable_learning, "Use wide band (learning) reciever");
+
+MODULE_DEVICE_TABLE(pnp, ene_ids);
+MODULE_DESCRIPTION
+    ("LIRC driver for KB3926B/KB3926C/KB3926D (aka ENE0100) CIR port");
+MODULE_AUTHOR("Maxim Levitsky");
+MODULE_LICENSE("GPL");
+
+module_init(ene_init);
+module_exit(ene_exit);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_serial/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_serial/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_SERIAL)	+= lirc_serial.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_serial/lirc_serial.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_serial/lirc_serial.c
@@ -0,0 +1,1422 @@
+/*      $Id: lirc_serial.c,v 5.104 2009/03/15 09:34:00 lirc Exp $      */
+/*
+ * lirc_serial.c
+ *
+ * lirc_serial - Device driver that records pulse- and pause-lengths
+ *	       (space-lengths) between DDCD event on a serial port.
+ *
+ * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de>
+ * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
+ * Copyright (C) 1998 Ben Pfaff <blp@gnu.org>
+ * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
+ * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support)
+ *  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
+ *
+ */
+
+/*
+ * Steve's changes to improve transmission fidelity:
+ *   - for systems with the rdtsc instruction and the clock counter, a
+ *     send_pule that times the pulses directly using the counter.
+ *     This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is
+ *     not needed. Measurement shows very stable waveform, even where
+ *     PCI activity slows the access to the UART, which trips up other
+ *     versions.
+ *   - For other system, non-integer-microsecond pulse/space lengths,
+ *     done using fixed point binary. So, much more accurate carrier
+ *     frequency.
+ *   - fine tuned transmitter latency, taking advantage of fractional
+ *     microseconds in previous change
+ *   - Fixed bug in the way transmitter latency was accounted for by
+ *     tuning the pulse lengths down - the send_pulse routine ignored
+ *     this overhead as it timed the overall pulse length - so the
+ *     pulse frequency was right but overall pulse length was too
+ *     long. Fixed by accounting for latency on each pulse/space
+ *     iteration.
+ *
+ * Steve Davies <steve@daviesfam.org>  July 2001
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+#include <linux/platform_device.h>
+#endif
+
+#include <asm/system.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#include <asm/io.h>
+#else
+#include <linux/io.h>
+#endif
+#include <linux/irq.h>
+#include <linux/fcntl.h>
+
+#if defined(LIRC_SERIAL_NSLU2)
+#include <asm/hardware.h>
+/* From Intel IXP42X Developer's Manual (#252480-005): */
+/* ftp://download.intel.com/design/network/manuals/25248005.pdf */
+#define UART_IE_IXP42X_UUE   0x40 /* IXP42X UART Unit enable */
+#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */
+#ifndef NSLU2_LED_GRN_GPIO
+/* added in 2.6.22 */
+#define NSLU2_LED_GRN_GPIO NSLU2_LED_GRN
+#endif
+#endif
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#if defined(LIRC_SERIAL_SOFTCARRIER) && !defined(LIRC_SERIAL_TRANSMITTER)
+#warning "Software carrier only affects transmitting"
+#endif
+
+#if defined(rdtscl)
+
+#define USE_RDTSC
+#warning "Note: using rdtsc instruction"
+#endif
+
+#ifdef LIRC_SERIAL_ANIMAX
+#ifdef LIRC_SERIAL_TRANSMITTER
+#warning "******************************************"
+#warning " This receiver does not have a	    "
+#warning " transmitter diode			"
+#warning "******************************************"
+#endif
+#endif
+
+#define LIRC_DRIVER_VERSION "$Revision: 5.104 $"
+#define LIRC_DRIVER_NAME "lirc_serial"
+
+struct lirc_serial {
+	int signal_pin;
+	int signal_pin_change;
+	int on;
+	int off;
+	long (*send_pulse)(unsigned long length);
+	void (*send_space)(long length);
+	int features;
+};
+
+#define LIRC_HOMEBREW		0
+#define LIRC_IRDEO		1
+#define LIRC_IRDEO_REMOTE	2
+#define LIRC_ANIMAX		3
+#define LIRC_IGOR		4
+#define LIRC_NSLU2		5
+
+#ifdef LIRC_SERIAL_IRDEO
+static int type = LIRC_IRDEO;
+#elif defined(LIRC_SERIAL_IRDEO_REMOTE)
+static int type = LIRC_IRDEO_REMOTE;
+#elif defined(LIRC_SERIAL_ANIMAX)
+static int type = LIRC_ANIMAX;
+#elif defined(LIRC_SERIAL_IGOR)
+static int type = LIRC_IGOR;
+#elif defined(LIRC_SERIAL_NSLU2)
+static int type = LIRC_NSLU2;
+#else
+static int type = LIRC_HOMEBREW;
+#endif
+
+/* Set defaults for NSLU2 */
+#if defined(LIRC_SERIAL_NSLU2)
+#ifndef LIRC_IRQ
+#define LIRC_IRQ IRQ_IXP4XX_UART2
+#endif
+#ifndef LIRC_PORT
+#define LIRC_PORT (IXP4XX_UART2_BASE_VIRT + REG_OFFSET)
+#endif
+#ifndef LIRC_IOMMAP
+#define LIRC_IOMMAP IXP4XX_UART2_BASE_PHYS
+#endif
+#ifndef LIRC_IOSHIFT
+#define LIRC_IOSHIFT 2
+#endif
+#ifndef LIRC_ALLOW_MMAPPED_IO
+#define LIRC_ALLOW_MMAPPED_IO
+#endif
+#endif
+
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+#ifndef LIRC_IOMMAP
+#define LIRC_IOMMAP 0
+#endif
+#ifndef LIRC_IOSHIFT
+#define LIRC_IOSHIFT 0
+#endif
+static int iommap = LIRC_IOMMAP;
+static int ioshift = LIRC_IOSHIFT;
+#endif
+
+#ifdef LIRC_SERIAL_SOFTCARRIER
+static int softcarrier = 1;
+#else
+static int softcarrier;
+#endif
+
+static int share_irq;
+static int debug;
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+/* forward declarations */
+static long send_pulse_irdeo(unsigned long length);
+static long send_pulse_homebrew(unsigned long length);
+static void send_space_irdeo(long length);
+static void send_space_homebrew(long length);
+
+static struct lirc_serial hardware[] = {
+	[LIRC_HOMEBREW] = {
+		.signal_pin        = UART_MSR_DCD,
+		.signal_pin_change = UART_MSR_DDCD,
+		.on  = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+		.off = (UART_MCR_RTS | UART_MCR_OUT2),
+		.send_pulse = send_pulse_homebrew,
+		.send_space = send_space_homebrew,
+#ifdef LIRC_SERIAL_TRANSMITTER
+		.features    = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
+				LIRC_CAN_SET_SEND_CARRIER |
+				LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
+#else
+		.features    = LIRC_CAN_REC_MODE2
+#endif
+	},
+
+	[LIRC_IRDEO] = {
+		.signal_pin        = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = UART_MCR_OUT2,
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.send_pulse  = send_pulse_irdeo,
+		.send_space  = send_space_irdeo,
+		.features    = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
+				LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
+	},
+
+	[LIRC_IRDEO_REMOTE] = {
+		.signal_pin        = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.send_pulse  = send_pulse_irdeo,
+		.send_space  = send_space_irdeo,
+		.features    = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
+				LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
+	},
+
+	[LIRC_ANIMAX] = {
+		.signal_pin        = UART_MSR_DCD,
+		.signal_pin_change = UART_MSR_DDCD,
+		.on  = 0,
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.send_pulse = NULL,
+		.send_space = NULL,
+		.features   = LIRC_CAN_REC_MODE2
+	},
+
+	[LIRC_IGOR] = {
+		.signal_pin        = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+		.off = (UART_MCR_RTS | UART_MCR_OUT2),
+		.send_pulse = send_pulse_homebrew,
+		.send_space = send_space_homebrew,
+#ifdef LIRC_SERIAL_TRANSMITTER
+		.features    = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
+				LIRC_CAN_SET_SEND_CARRIER |
+				LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
+#else
+		.features    = LIRC_CAN_REC_MODE2
+#endif
+	},
+
+#if defined(LIRC_SERIAL_NSLU2)
+	/*
+	 * Modified Linksys Network Storage Link USB 2.0 (NSLU2):
+	 * We receive on CTS of the 2nd serial port (R142,LHS), we
+	 * transmit with a IR diode between GPIO[1] (green status LED),
+	 * and ground (Matthias Goebl <matthias.goebl@goebl.net>).
+	 * See also http://www.nslu2-linux.org for this device
+	 */
+	[LIRC_NSLU2] = {
+		.signal_pin        = UART_MSR_CTS,
+		.signal_pin_change = UART_MSR_DCTS,
+		.on  = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+		.off = (UART_MCR_RTS | UART_MCR_OUT2),
+		.send_pulse = send_pulse_homebrew,
+		.send_space = send_space_homebrew,
+#ifdef LIRC_SERIAL_TRANSMITTER
+		.features    = (LIRC_CAN_SET_SEND_DUTY_CYCLE |
+				LIRC_CAN_SET_SEND_CARRIER |
+				LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2)
+#else
+		.features    = LIRC_CAN_REC_MODE2
+#endif
+	},
+#endif
+
+};
+
+#define RS_ISR_PASS_LIMIT 256
+
+/*
+ * A long pulse code from a remote might take up to 300 bytes.  The
+ * daemon should read the bytes as soon as they are generated, so take
+ * the number of keys you think you can push before the daemon runs
+ * and multiply by 300.  The driver will warn you if you overrun this
+ * buffer.  If you have a slow computer or non-busmastering IDE disks,
+ * maybe you will need to increase this.
+ */
+
+/* This MUST be a power of two!  It has to be larger than 1 as well. */
+
+#define RBUF_LEN 256
+#define WBUF_LEN 256
+
+static int sense = -1;	/* -1 = auto, 0 = active high, 1 = active low */
+static int txsense;     /* 0 = active high, 1 = active low */
+
+#ifndef LIRC_IRQ
+#define LIRC_IRQ 4
+#endif
+#ifndef LIRC_PORT
+#define LIRC_PORT 0x3f8
+#endif
+
+static int io = LIRC_PORT;
+static int irq = LIRC_IRQ;
+
+static struct timeval lasttv = {0, 0};
+
+static struct lirc_buffer rbuf;
+
+static lirc_t wbuf[WBUF_LEN];
+
+static unsigned int freq = 38000;
+static unsigned int duty_cycle = 50;
+
+/* Initialized in init_timing_params() */
+static unsigned long period;
+static unsigned long pulse_width;
+static unsigned long space_width;
+
+#if defined(__i386__)
+/*
+ * From:
+ * Linux I/O port programming mini-HOWTO
+ * Author: Riku Saikkonen <Riku.Saikkonen@hut.fi>
+ * v, 28 December 1997
+ *
+ * [...]
+ * Actually, a port I/O instruction on most ports in the 0-0x3ff range
+ * takes almost exactly 1 microsecond, so if you're, for example, using
+ * the parallel port directly, just do additional inb()s from that port
+ * to delay.
+ * [...]
+ */
+/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from
+ * comment above plus trimming to match actual measured frequency.
+ * This will be sensitive to cpu speed, though hopefully most of the 1.5us
+ * is spent in the uart access.  Still - for reference test machine was a
+ * 1.13GHz Athlon system - Steve
+ */
+
+/*
+ * changed from 400 to 450 as this works better on slower machines;
+ * faster machines will use the rdtsc code anyway
+ */
+#define LIRC_SERIAL_TRANSMITTER_LATENCY 450
+
+#else
+
+/* does anybody have information on other platforms ? */
+/* 256 = 1<<8 */
+#define LIRC_SERIAL_TRANSMITTER_LATENCY 256
+
+#endif  /* __i386__ */
+
+static unsigned int sinp(int offset)
+{
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+	if (iommap != 0) {
+		/* the register is memory-mapped */
+		offset <<= ioshift;
+		return readb(io + offset);
+	}
+#endif
+	return inb(io + offset);
+}
+
+static void soutp(int offset, int value)
+{
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+	if (iommap != 0) {
+		/* the register is memory-mapped */
+		offset <<= ioshift;
+		writeb(value, io + offset);
+	}
+#endif
+	outb(value, io + offset);
+}
+
+static void on(void)
+{
+#if defined(LIRC_SERIAL_NSLU2)
+	/*
+	 * On NSLU2, we put the transmit diode between the output of the green
+	 * status LED and ground
+	 */
+	if (type == LIRC_NSLU2) {
+		gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_LOW);
+		return;
+	}
+#endif
+	if (txsense)
+		soutp(UART_MCR, hardware[type].off);
+	else
+		soutp(UART_MCR, hardware[type].on);
+}
+
+static void off(void)
+{
+#if defined(LIRC_SERIAL_NSLU2)
+	if (type == LIRC_NSLU2) {
+		gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_HIGH);
+		return;
+	}
+#endif
+	if (txsense)
+		soutp(UART_MCR, hardware[type].on);
+	else
+		soutp(UART_MCR, hardware[type].off);
+}
+
+#ifndef MAX_UDELAY_MS
+#define MAX_UDELAY_US 5000
+#else
+#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
+#endif
+
+static void safe_udelay(unsigned long usecs)
+{
+	while (usecs > MAX_UDELAY_US) {
+		udelay(MAX_UDELAY_US);
+		usecs -= MAX_UDELAY_US;
+	}
+	udelay(usecs);
+}
+
+#ifdef USE_RDTSC
+/*
+ * This is an overflow/precision juggle, complicated in that we can't
+ * do long long divide in the kernel
+ */
+
+/*
+ * When we use the rdtsc instruction to measure clocks, we keep the
+ * pulse and space widths as clock cycles.  As this is CPU speed
+ * dependent, the widths must be calculated in init_port and ioctl
+ * time
+ */
+
+/* So send_pulse can quickly convert microseconds to clocks */
+static unsigned long conv_us_to_clocks;
+
+static int init_timing_params(unsigned int new_duty_cycle,
+		unsigned int new_freq)
+{
+	unsigned long long loops_per_sec, work;
+
+	duty_cycle = new_duty_cycle;
+	freq = new_freq;
+
+	loops_per_sec = current_cpu_data.loops_per_jiffy;
+	loops_per_sec *= HZ;
+
+	/* How many clocks in a microsecond?, avoiding long long divide */
+	work = loops_per_sec;
+	work *= 4295;  /* 4295 = 2^32 / 1e6 */
+	conv_us_to_clocks = (work >> 32);
+
+	/*
+	 * Carrier period in clocks, approach good up to 32GHz clock,
+	 * gets carrier frequency within 8Hz
+	 */
+	period = loops_per_sec >> 3;
+	period /= (freq >> 3);
+
+	/* Derive pulse and space from the period */
+	pulse_width = period * duty_cycle / 100;
+	space_width = period - pulse_width;
+	dprintk("in init_timing_params, freq=%d, duty_cycle=%d, "
+		"clk/jiffy=%ld, pulse=%ld, space=%ld, "
+		"conv_us_to_clocks=%ld\n",
+		freq, duty_cycle, current_cpu_data.loops_per_jiffy,
+		pulse_width, space_width, conv_us_to_clocks);
+	return 0;
+}
+#else /* ! USE_RDTSC */
+static int init_timing_params(unsigned int new_duty_cycle,
+		unsigned int new_freq)
+{
+/*
+ * period, pulse/space width are kept with 8 binary places -
+ * IE multiplied by 256.
+ */
+	if (256 * 1000000L / new_freq * new_duty_cycle / 100 <=
+	    LIRC_SERIAL_TRANSMITTER_LATENCY)
+		return -EINVAL;
+	if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
+	    LIRC_SERIAL_TRANSMITTER_LATENCY)
+		return -EINVAL;
+	duty_cycle = new_duty_cycle;
+	freq = new_freq;
+	period = 256 * 1000000L / freq;
+	pulse_width = period * duty_cycle / 100;
+	space_width = period - pulse_width;
+	dprintk("in init_timing_params, freq=%d pulse=%ld, "
+		"space=%ld\n", freq, pulse_width, space_width);
+	return 0;
+}
+#endif /* USE_RDTSC */
+
+
+/* return value: space length delta */
+
+static long send_pulse_irdeo(unsigned long length)
+{
+	long rawbits, ret;
+	int i;
+	unsigned char output;
+	unsigned char chunk, shifted;
+
+	/* how many bits have to be sent ? */
+	rawbits = length * 1152 / 10000;
+	if (duty_cycle > 50)
+		chunk = 3;
+	else
+		chunk = 1;
+	for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
+		shifted = chunk << (i * 3);
+		shifted >>= 1;
+		output &= (~shifted);
+		i++;
+		if (i == 3) {
+			soutp(UART_TX, output);
+			while (!(sinp(UART_LSR) & UART_LSR_THRE))
+				;
+			output = 0x7f;
+			i = 0;
+		}
+	}
+	if (i != 0) {
+		soutp(UART_TX, output);
+		while (!(sinp(UART_LSR) & UART_LSR_TEMT))
+			;
+	}
+
+	if (i == 0)
+		ret = (-rawbits) * 10000 / 1152;
+	else
+		ret = (3 - i) * 3 *10000 / 1152 + (-rawbits) * 10000 / 1152;
+
+	return ret;
+}
+
+#ifdef USE_RDTSC
+/* Version that uses Pentium rdtsc instruction to measure clocks */
+
+/*
+ * This version does sub-microsecond timing using rdtsc instruction,
+ * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY
+ * Implicitly i586 architecture...  - Steve
+ */
+
+static long send_pulse_homebrew_softcarrier(unsigned long length)
+{
+	int flag;
+	unsigned long target, start, now;
+
+	/* Get going quick as we can */
+	rdtscl(start);
+	on();
+	/* Convert length from microseconds to clocks */
+	length *= conv_us_to_clocks;
+	/* And loop till time is up - flipping at right intervals */
+	now = start;
+	target = pulse_width;
+	flag = 1;
+	while ((now - start) < length) {
+		/* Delay till flip time */
+		do {
+			rdtscl(now);
+		} while ((now - start) < target);
+
+		/* flip */
+		if (flag) {
+			rdtscl(now);
+			off();
+			target += space_width;
+		} else {
+			rdtscl(now); on();
+			target += pulse_width;
+		}
+		flag = !flag;
+	}
+	rdtscl(now);
+	return ((now - start) - length) / conv_us_to_clocks;
+}
+#else /* ! USE_RDTSC */
+/* Version using udelay() */
+
+/*
+ * here we use fixed point arithmetic, with 8
+ * fractional bits.  that gets us within 0.1% or so of the right average
+ * frequency, albeit with some jitter in pulse length - Steve
+ */
+
+/* To match 8 fractional bits used for pulse/space length */
+
+static long send_pulse_homebrew_softcarrier(unsigned long length)
+{
+	int flag;
+	unsigned long actual, target, d;
+	length <<= 8;
+
+	actual = 0; target = 0; flag = 0;
+	while (actual < length) {
+		if (flag) {
+			off();
+			target += space_width;
+		} else {
+			on();
+			target += pulse_width;
+		}
+		d = (target - actual -
+		     LIRC_SERIAL_TRANSMITTER_LATENCY + 128) >> 8;
+		/*
+		 * Note - we've checked in ioctl that the pulse/space
+		 * widths are big enough so that d is > 0
+		 */
+		udelay(d);
+		actual += (d << 8) + LIRC_SERIAL_TRANSMITTER_LATENCY;
+		flag = !flag;
+	}
+	return (actual-length) >> 8;
+}
+#endif /* USE_RDTSC */
+
+static long send_pulse_homebrew(unsigned long length)
+{
+	if (length <= 0)
+		return 0;
+
+	if (softcarrier)
+		return send_pulse_homebrew_softcarrier(length);
+	else {
+		on();
+		safe_udelay(length);
+		return 0;
+	}
+}
+
+static void send_space_irdeo(long length)
+{
+	if (length <= 0)
+		return;
+
+	safe_udelay(length);
+}
+
+static void send_space_homebrew(long length)
+{
+	off();
+	if (length <= 0)
+		return;
+	safe_udelay(length);
+}
+
+static void rbwrite(lirc_t l)
+{
+	if (lirc_buffer_full(&rbuf)) {
+		/* no new signals will be accepted */
+		dprintk("Buffer overrun\n");
+		return;
+	}
+	lirc_buffer_write(&rbuf, (void *)&l);
+}
+
+static void frbwrite(lirc_t l)
+{
+	/* simple noise filter */
+	static lirc_t pulse = 0L, space = 0L;
+	static unsigned int ptr;
+
+	if (ptr > 0 && (l & PULSE_BIT)) {
+		pulse += l & PULSE_MASK;
+		if (pulse > 250) {
+			rbwrite(space);
+			rbwrite(pulse | PULSE_BIT);
+			ptr = 0;
+			pulse = 0;
+		}
+		return;
+	}
+	if (!(l & PULSE_BIT)) {
+		if (ptr == 0) {
+			if (l > 20000) {
+				space = l;
+				ptr++;
+				return;
+			}
+		} else {
+			if (l > 20000) {
+				space += pulse;
+				if (space > PULSE_MASK)
+					space = PULSE_MASK;
+				space += l;
+				if (space > PULSE_MASK)
+					space = PULSE_MASK;
+				pulse = 0;
+				return;
+			}
+			rbwrite(space);
+			rbwrite(pulse | PULSE_BIT);
+			ptr = 0;
+			pulse = 0;
+		}
+	}
+	rbwrite(l);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t irq_handler(int i, void *blah)
+#else
+static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
+#endif
+{
+	struct timeval tv;
+	int status, counter, dcd;
+	long deltv;
+	lirc_t data;
+	static int last_dcd = -1;
+
+	if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
+		/* not our interrupt */
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+
+	counter = 0;
+	do {
+		counter++;
+		status = sinp(UART_MSR);
+		if (counter > RS_ISR_PASS_LIMIT) {
+			printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: "
+			       "We're caught!\n");
+			break;
+		}
+		if ((status & hardware[type].signal_pin_change)
+		    && sense != -1) {
+			/* get current time */
+			do_gettimeofday(&tv);
+
+			/* New mode, written by Trent Piepho
+			   <xyzzy@u.washington.edu>. */
+
+			/*
+			 * The old format was not very portable.
+			 * We now use an int to pass pulses
+			 * and spaces to user space.
+			 *
+			 * If PULSE_BIT is set a pulse has been
+			 * received, otherwise a space has been
+			 * received.  The driver needs to know if your
+			 * receiver is active high or active low, or
+			 * the space/pulse sense could be
+			 * inverted. The bits denoted by PULSE_MASK are
+			 * the length in microseconds. Lengths greater
+			 * than or equal to 16 seconds are clamped to
+			 * PULSE_MASK.  All other bits are unused.
+			 * This is a much simpler interface for user
+			 * programs, as well as eliminating "out of
+			 * phase" errors with space/pulse
+			 * autodetection.
+			 */
+
+			/* calc time since last interrupt in microseconds */
+			dcd = (status & hardware[type].signal_pin) ? 1 : 0;
+
+			if (dcd == last_dcd) {
+				printk(KERN_WARNING LIRC_DRIVER_NAME
+				": ignoring spike: %d %d %lx %lx %lx %lx\n",
+				dcd, sense,
+				tv.tv_sec, lasttv.tv_sec,
+				tv.tv_usec, lasttv.tv_usec);
+				continue;
+			}
+
+			deltv = tv.tv_sec-lasttv.tv_sec;
+			if (tv.tv_sec < lasttv.tv_sec ||
+			    (tv.tv_sec == lasttv.tv_sec &&
+			     tv.tv_usec < lasttv.tv_usec)) {
+				printk(KERN_WARNING LIRC_DRIVER_NAME
+				       ": AIEEEE: your clock just jumped "
+				       "backwards\n");
+				printk(KERN_WARNING LIRC_DRIVER_NAME
+				       ": %d %d %lx %lx %lx %lx\n",
+				       dcd, sense,
+				       tv.tv_sec, lasttv.tv_sec,
+				       tv.tv_usec, lasttv.tv_usec);
+				data = PULSE_MASK;
+			} else if (deltv > 15) {
+				data = PULSE_MASK; /* really long time */
+				if (!(dcd^sense)) {
+					/* sanity check */
+					printk(KERN_WARNING LIRC_DRIVER_NAME
+					       ": AIEEEE: "
+					       "%d %d %lx %lx %lx %lx\n",
+					       dcd, sense,
+					       tv.tv_sec, lasttv.tv_sec,
+					       tv.tv_usec, lasttv.tv_usec);
+					/*
+					 * detecting pulse while this
+					 * MUST be a space!
+					 */
+					sense = sense ? 0 : 1;
+				}
+			} else
+				data = (lirc_t) (deltv*1000000 +
+					       tv.tv_usec -
+					       lasttv.tv_usec);
+			frbwrite(dcd^sense ? data : (data|PULSE_BIT));
+			lasttv = tv;
+			last_dcd = dcd;
+			wake_up_interruptible(&rbuf.wait_poll);
+		}
+	} while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+static void hardware_init_port(void)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* First of all, disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
+
+	/* Clear registers. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+#if defined(LIRC_SERIAL_NSLU2)
+	if (type == LIRC_NSLU2) {
+		/* Setup NSLU2 UART */
+
+		/* Enable UART */
+		soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE);
+		/* Disable Receiver data Time out interrupt */
+		soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE);
+		/* set out2 = interrupt unmask; off() doesn't set MCR
+		   on NSLU2 */
+		soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
+	}
+#endif
+
+	/* Set line for power source */
+	off();
+
+	/* Clear registers again to be sure. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+	switch (type) {
+	case LIRC_IRDEO:
+	case LIRC_IRDEO_REMOTE:
+		/* setup port to 7N1 @ 115200 Baud */
+		/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */
+
+		/* Set DLAB 1. */
+		soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+		/* Set divisor to 1 => 115200 Baud */
+		soutp(UART_DLM, 0);
+		soutp(UART_DLL, 1);
+		/* Set DLAB 0 +  7N1 */
+		soutp(UART_LCR, UART_LCR_WLEN7);
+		/* THR interrupt already disabled at this point */
+		break;
+	default:
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+static int init_port(void)
+{
+	int i, nlow, nhigh;
+
+	/* Reserve io region. */
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+	/*
+	 * Future MMAP-Developers: Attention!
+	 * For memory mapped I/O you *might* need to use ioremap() first,
+	 * for the NSLU2 it's done in boot code.
+	 */
+	if (((iommap != 0)
+	     && (request_mem_region(iommap, 8 << ioshift,
+				    LIRC_DRIVER_NAME) == NULL))
+	   || ((iommap == 0)
+	       && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) {
+#else
+	if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
+#endif
+		printk(KERN_ERR  LIRC_DRIVER_NAME
+		       ": port %04x already in use\n", io);
+		printk(KERN_WARNING LIRC_DRIVER_NAME
+		       ": use 'setserial /dev/ttySX uart none'\n");
+		printk(KERN_WARNING LIRC_DRIVER_NAME
+		       ": or compile the serial port driver as module and\n");
+		printk(KERN_WARNING LIRC_DRIVER_NAME
+		       ": make sure this module is loaded first\n");
+		return -EBUSY;
+	}
+
+	hardware_init_port();
+
+	/* Initialize pulse/space widths */
+	init_timing_params(duty_cycle, freq);
+
+	/* If pin is high, then this must be an active low receiver. */
+	if (sense == -1) {
+		/* wait 1/2 sec for the power supply */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+		msleep(500);
+#else
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ/2);
+#endif
+
+		/*
+		 * probe 9 times every 0.04s, collect "votes" for
+		 * active high/low
+		 */
+		nlow = 0;
+		nhigh = 0;
+		for (i = 0; i < 9; i++) {
+			if (sinp(UART_MSR) & hardware[type].signal_pin)
+				nlow++;
+			else
+				nhigh++;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+			msleep(40);
+#else
+			schedule_timeout(HZ/25);
+#endif
+		}
+		sense = (nlow >= nhigh ? 1 : 0);
+		printk(KERN_INFO  LIRC_DRIVER_NAME  ": auto-detected active "
+		       "%s receiver\n", sense ? "low" : "high");
+	} else
+		printk(KERN_INFO  LIRC_DRIVER_NAME  ": Manually using active "
+		       "%s receiver\n", sense ? "low" : "high");
+
+	return 0;
+}
+
+static int set_use_inc(void *data)
+{
+	int result;
+	unsigned long flags;
+
+	/* Init read buffer. */
+	if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0)
+		return -ENOMEM;
+
+	/* initialize timestamp */
+	do_gettimeofday(&lasttv);
+
+	result = request_irq(irq, irq_handler,
+			     IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0),
+			     LIRC_DRIVER_NAME, (void *)&hardware);
+
+	switch (result) {
+	case -EBUSY:
+		printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
+		lirc_buffer_free(&rbuf);
+		return -EBUSY;
+	case -EINVAL:
+		printk(KERN_ERR LIRC_DRIVER_NAME
+		       ": Bad irq number or handler\n");
+		lirc_buffer_free(&rbuf);
+		return -EINVAL;
+	default:
+		dprintk("Interrupt %d, port %04x obtained\n", irq, io);
+		break;
+	};
+
+	local_irq_save(flags);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
+
+	local_irq_restore(flags);
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* First of all, disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
+	local_irq_restore(flags);
+
+	free_irq(irq, (void *)&hardware);
+
+	dprintk("freed IRQ %d\n", irq);
+	lirc_buffer_free(&rbuf);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static ssize_t lirc_write(struct file *file, const char *buf,
+			 size_t n, loff_t *ppos)
+{
+	int i, count;
+	unsigned long flags;
+	long delta = 0;
+
+	if (!(hardware[type].features&LIRC_CAN_SEND_PULSE))
+		return -EBADF;
+
+	if (n % sizeof(lirc_t))
+		return -EINVAL;
+	count = n / sizeof(lirc_t);
+	if (count > WBUF_LEN || count % 2 == 0)
+		return -EINVAL;
+	if (copy_from_user(wbuf, buf, n))
+		return -EFAULT;
+	local_irq_save(flags);
+	if (type == LIRC_IRDEO) {
+		/* DTR, RTS down */
+		on();
+	}
+	for (i = 0; i < count; i++) {
+		if (i%2)
+			hardware[type].send_space(wbuf[i]-delta);
+		else
+			delta = hardware[type].send_pulse(wbuf[i]);
+	}
+	off();
+	local_irq_restore(flags);
+	return n;
+}
+
+static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd,
+		      unsigned long arg)
+{
+	int result;
+	unsigned long value;
+	unsigned int ivalue;
+
+	switch (cmd) {
+	case LIRC_GET_SEND_MODE:
+		if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
+			return -ENOIOCTLCMD;
+
+		result = put_user(LIRC_SEND2MODE
+				  (hardware[type].features&LIRC_CAN_SEND_MASK),
+				  (unsigned long *) arg);
+		if (result)
+			return result;
+		break;
+
+	case LIRC_SET_SEND_MODE:
+		if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
+			return -ENOIOCTLCMD;
+
+		result = get_user(value, (unsigned long *) arg);
+		if (result)
+			return result;
+		/* only LIRC_MODE_PULSE supported */
+		if (value != LIRC_MODE_PULSE)
+			return -ENOSYS;
+		break;
+
+	case LIRC_GET_LENGTH:
+		return -ENOSYS;
+		break;
+
+	case LIRC_SET_SEND_DUTY_CYCLE:
+		dprintk("SET_SEND_DUTY_CYCLE\n");
+		if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
+			return -ENOIOCTLCMD;
+
+		result = get_user(ivalue, (unsigned int *) arg);
+		if (result)
+			return result;
+		if (ivalue <= 0 || ivalue > 100)
+			return -EINVAL;
+		return init_timing_params(ivalue, freq);
+		break;
+
+	case LIRC_SET_SEND_CARRIER:
+		dprintk("SET_SEND_CARRIER\n");
+		if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER))
+			return -ENOIOCTLCMD;
+
+		result = get_user(ivalue, (unsigned int *) arg);
+		if (result)
+			return result;
+		if (ivalue > 500000 || ivalue < 20000)
+			return -EINVAL;
+		return init_timing_params(duty_cycle, ivalue);
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static struct file_operations lirc_fops = {
+	.owner	= THIS_MODULE,
+	.write	= lirc_write,
+	.ioctl	= lirc_ioctl,
+};
+
+static struct lirc_driver driver = {
+	.name		= LIRC_DRIVER_NAME,
+	.minor		= -1,
+	.code_length	= 1,
+	.sample_rate	= 0,
+	.data		= NULL,
+	.add_to_buf	= NULL,
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	.get_queue	= NULL,
+#endif
+	.rbuf		= &rbuf,
+	.set_use_inc	= set_use_inc,
+	.set_use_dec	= set_use_dec,
+	.fops		= &lirc_fops,
+	.dev		= NULL,
+	.owner		= THIS_MODULE,
+};
+
+#ifdef MODULE
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+static struct platform_device *lirc_serial_dev;
+
+static int __devinit lirc_serial_probe(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int __devexit lirc_serial_remove(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int lirc_serial_suspend(struct platform_device *dev,
+			       pm_message_t state)
+{
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* Disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
+
+	/* Clear registers. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+	return 0;
+}
+
+static int lirc_serial_resume(struct platform_device *dev)
+{
+	unsigned long flags;
+
+	hardware_init_port();
+
+	local_irq_save(flags);
+	/* Enable Interrupt */
+	do_gettimeofday(&lasttv);
+	soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
+	off();
+
+	lirc_buffer_clear(&rbuf);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static struct platform_driver lirc_serial_driver = {
+	.probe		= lirc_serial_probe,
+	.remove		= __devexit_p(lirc_serial_remove),
+	.suspend	= lirc_serial_suspend,
+	.resume		= lirc_serial_resume,
+	.driver		= {
+		.name	= "lirc_serial",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init lirc_serial_init(void)
+{
+	int result;
+
+	result = platform_driver_register(&lirc_serial_driver);
+	if (result) {
+		printk("lirc register returned %d\n", result);
+		return result;
+	}
+
+	lirc_serial_dev = platform_device_alloc("lirc_serial", 0);
+	if (!lirc_serial_dev) {
+		result = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	result = platform_device_add(lirc_serial_dev);
+	if (result)
+		goto exit_device_put;
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(lirc_serial_dev);
+exit_driver_unregister:
+	platform_driver_unregister(&lirc_serial_driver);
+	return result;
+}
+
+static void __exit lirc_serial_exit(void)
+{
+	platform_device_unregister(lirc_serial_dev);
+	platform_driver_unregister(&lirc_serial_driver);
+}
+#endif
+
+static int __init lirc_serial_init_module(void)
+{
+	int result;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	result = lirc_serial_init();
+	if (result)
+		return result;
+#endif
+	switch (type) {
+	case LIRC_HOMEBREW:
+	case LIRC_IRDEO:
+	case LIRC_IRDEO_REMOTE:
+	case LIRC_ANIMAX:
+	case LIRC_IGOR:
+#if defined(LIRC_SERIAL_NSLU2)
+	case LIRC_NSLU2:
+#endif
+		break;
+	default:
+		result = -EINVAL;
+		goto exit_serial_exit;
+	}
+	if (!softcarrier) {
+		switch (type) {
+		case LIRC_HOMEBREW:
+		case LIRC_IGOR:
+		case LIRC_NSLU2:
+			hardware[type].features &=
+				~(LIRC_CAN_SET_SEND_DUTY_CYCLE|
+				  LIRC_CAN_SET_SEND_CARRIER);
+			break;
+		}
+	}
+
+	result = init_port();
+	if (result < 0)
+		goto exit_serial_exit;
+	driver.features = hardware[type].features;
+	driver.minor = lirc_register_driver(&driver);
+	if (driver.minor < 0) {
+		printk(KERN_ERR  LIRC_DRIVER_NAME
+		       ": register_chrdev failed!\n");
+		result = -EIO;
+		goto exit_release;
+	}
+
+	printk(KERN_INFO
+	       LIRC_DRIVER_NAME " " LIRC_DRIVER_VERSION " registered\n");
+	dprintk("type = %d\n", type);
+	dprintk("IRQ = %d, port = %04x\n", irq, io);
+	dprintk("share_irq = %d\n", share_irq);
+#ifdef LIRC_SERIAL_TRANSMITTER
+	dprintk("txsense = %d\n", txsense);
+#endif
+	dprintk("softcarrier = %d\n", softcarrier);
+
+	return 0;
+exit_release:
+	release_region(io, 8);
+exit_serial_exit:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	lirc_serial_exit();
+#endif
+	return result;
+}
+
+static void __exit lirc_serial_exit_module(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	lirc_serial_exit();
+#endif
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+	if (iommap != 0)
+		release_mem_region(iommap, 8 << ioshift);
+	else
+		release_region(io, 8);
+#else
+	release_region(io, 8);
+#endif
+	lirc_unregister_driver(driver.minor);
+	dprintk("cleaned up module\n");
+}
+
+
+module_init(lirc_serial_init_module);
+module_exit(lirc_serial_exit_module);
+
+MODULE_DESCRIPTION("Infra-red receiver driver for serial ports.");
+MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, "
+	      "Christoph Bartelmus, Andrei Tanas");
+MODULE_LICENSE("GPL");
+
+module_param(type, int, S_IRUGO);
+#if defined(LIRC_SERIAL_NSLU2)
+MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo,"
+		 " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug,"
+		 " 5 = NSLU2 RX:CTS2/TX:GreenLED)");
+#else
+MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo,"
+		 " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug)");
+#endif
+
+module_param(io, int, S_IRUGO);
+MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
+
+#if defined(LIRC_ALLOW_MMAPPED_IO)
+/* some architectures (e.g. intel xscale) have memory mapped registers */
+module_param(iommap, bool, S_IRUGO);
+MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O"
+		" (0 = no memory mapped io)");
+
+/*
+ * some architectures (e.g. intel xscale) align the 8bit serial registers
+ * on 32bit word boundaries.
+ * See linux-kernel/serial/8250.c serial_in()/out()
+ */
+module_param(ioshift, int, S_IRUGO);
+MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
+#endif
+
+module_param(irq, int, S_IRUGO);
+MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
+
+module_param(share_irq, bool, S_IRUGO);
+MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
+
+module_param(sense, bool, S_IRUGO);
+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
+		 " (0 = active high, 1 = active low )");
+
+#ifdef LIRC_SERIAL_TRANSMITTER
+module_param(txsense, bool, S_IRUGO);
+MODULE_PARM_DESC(txsense, "Sense of transmitter circuit"
+		 " (0 = active high, 1 = active low )");
+#endif
+
+module_param(softcarrier, bool, S_IRUGO);
+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on)");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_i2c/lirc_i2c.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_i2c/lirc_i2c.c
@@ -0,0 +1,778 @@
+/*      $Id: lirc_i2c.c,v 1.70 2009/08/30 16:59:53 jarodwilson Exp $      */
+
+/*
+ * lirc_i2c.c
+ *
+ * i2c IR driver for the onboard IR port on many TV tuner cards, including:
+ *  -Flavors of the Hauppauge PVR-150/250/350
+ *  -Hauppauge HVR-1300
+ *  -PixelView (BT878P+W/FM)
+ *  -KNC ONE TV Station/Anubis Typhoon TView Tuner
+ *  -Asus TV-Box and Creative/VisionTek BreakOut-Box
+ *  -Leadtek Winfast PVR2000
+ *
+ * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ * modified for PixelView (BT878P+W/FM) by
+ *      Michal Kochanowicz <mkochano@pld.org.pl>
+ *      Christoph Bartelmus <lirc@bartelmus.de>
+ * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by
+ *      Ulrich Mueller <ulrich.mueller42@web.de>
+ * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by
+ *      Stefan Jahn <stefan@lkcc.org>
+ * modified for inclusion into kernel sources by
+ *      Jerome Brock <jbrock@users.sourceforge.net>
+ * modified for Leadtek Winfast PVR2000 by
+ *      Thomas Reitmayr (treitmayr@yahoo.com)
+ * modified for Hauppauge HVR-1300 by
+ *      Jan Frey (jfrey@gmx.de)
+ *
+ * parts are cut&pasted from the old lirc_haup.c driver
+ *
+ *  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
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+struct IR {
+	struct lirc_driver l;
+	struct i2c_client  c;
+	int nextkey;
+	unsigned char b[3];
+	unsigned char bits;
+	unsigned char flag;
+};
+
+#define DEVICE_NAME "lirc_i2c"
+
+/* module parameters */
+static int debug;	/* debug output */
+static int minor = -1;	/* minor number */
+
+#define dprintk(fmt, args...)						\
+	do {								\
+		if (debug)						\
+			printk(KERN_DEBUG DEVICE_NAME ": " fmt,		\
+			       ## args);				\
+	} while (0)
+
+static int reverse(int data, int bits)
+{
+	int i;
+	int c;
+
+	for (c = 0, i = 0; i < bits; i++)
+		c |= ((data & (1<<i)) ? 1 : 0) << (bits-1-i);
+
+	return c;
+}
+
+static int add_to_buf_adap(void *data, struct lirc_buffer *buf)
+{
+	struct IR *ir = data;
+	unsigned char keybuf[4];
+
+	keybuf[0] = 0x00;
+	i2c_master_send(&ir->c, keybuf, 1);
+	/* poll IR chip */
+	if (i2c_master_recv(&ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
+		dprintk("read error\n");
+		return -EIO;
+	}
+
+	dprintk("key (0x%02x%02x%02x%02x)\n",
+		keybuf[0], keybuf[1], keybuf[2], keybuf[3]);
+
+	/* key pressed ? */
+	if (keybuf[2] == 0xff)
+		return -ENODATA;
+
+	/* remove repeat bit */
+	keybuf[2] &= 0x7f;
+	keybuf[3] |= 0x80;
+
+	lirc_buffer_write(buf, keybuf);
+	return 0;
+}
+
+static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf)
+{
+	struct IR *ir = data;
+	int rc;
+	unsigned char all, mask;
+	unsigned char key;
+
+	/* compute all valid bits (key code + pressed/release flag) */
+	all = ir->bits | ir->flag;
+
+	/* save IR writable mask bits */
+	mask = i2c_smbus_read_byte(&ir->c) & ~all;
+
+	/* send bit mask */
+	rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask);
+
+	/* receive scan code */
+	rc = i2c_smbus_read_byte(&ir->c);
+
+	if (rc == -1) {
+		dprintk("%s read error\n", ir->c.name);
+		return -EIO;
+	}
+
+	/* drop duplicate polls */
+	if (ir->b[0] == (rc & all))
+		return -ENODATA;
+
+	ir->b[0] = rc & all;
+
+	dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits,
+		(rc & ir->flag) ? "released" : "pressed");
+
+	/* ignore released buttons */
+	if (rc & ir->flag)
+		return -ENODATA;
+
+	/* set valid key code */
+	key  = rc & ir->bits;
+	lirc_buffer_write(buf, &key);
+	return 0;
+}
+
+/* common for Hauppauge IR receivers */
+static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf,
+		unsigned char *keybuf, int size, int offset)
+{
+	struct IR *ir = data;
+	__u16 code;
+	unsigned char codes[2];
+	int ret;
+
+	/* poll IR chip */
+	ret = i2c_master_recv(&ir->c, keybuf, size);
+	if (ret == size) {
+		ir->b[0] = keybuf[offset];
+		ir->b[1] = keybuf[offset+1];
+		ir->b[2] = keybuf[offset+2];
+		if (ir->b[0] != 0x00 && ir->b[1] != 0x00)
+			dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]);
+	} else {
+		dprintk("read error (ret=%d)\n", ret);
+		/* keep last successful read buffer */
+	}
+
+	/* key pressed ? */
+	if ((ir->b[0] & 0x80) == 0)
+		return -ENODATA;
+
+	/* look what we have */
+	code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2);
+
+	codes[0] = (code >> 8) & 0xff;
+	codes[1] = code & 0xff;
+
+	/* return it */
+	dprintk("sending code 0x%02x%02x to lirc\n", codes[0], codes[1]);
+	lirc_buffer_write(buf, codes);
+	return 0;
+}
+
+/* specific for the Hauppauge PVR150 IR receiver */
+static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf)
+{
+	unsigned char keybuf[6];
+	/* fetch 6 bytes, first relevant is at offset 3 */
+	return add_to_buf_haup_common(data, buf, keybuf, 6, 3);
+}
+
+/* used for all Hauppauge IR receivers but the PVR150 */
+static int add_to_buf_haup(void *data, struct lirc_buffer *buf)
+{
+	unsigned char keybuf[3];
+	/* fetch 3 bytes, first relevant is at offset 0 */
+	return add_to_buf_haup_common(data, buf, keybuf, 3, 0);
+}
+
+
+static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf)
+{
+	struct IR *ir = data;
+	unsigned char key;
+	s32 flags;
+	s32 code;
+
+	/* poll IR chip */
+	flags = i2c_smbus_read_byte_data(&ir->c, 0x10);
+	if (-1 == flags) {
+		dprintk("read error\n");
+		return -ENODATA;
+	}
+	/* key pressed ? */
+	if (0 == (flags & 0x80))
+		return -ENODATA;
+
+	/* read actual key code */
+	code = i2c_smbus_read_byte_data(&ir->c, 0x00);
+	if (-1 == code) {
+		dprintk("read error\n");
+		return -ENODATA;
+	}
+
+	key = code & 0xFF;
+
+	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF);
+
+	/* return it */
+	lirc_buffer_write(buf, &key);
+	return 0;
+}
+
+static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf)
+{
+	struct IR *ir = data;
+	unsigned char key;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
+		dprintk("read error\n");
+		return -1;
+	}
+	dprintk("key %02x\n", key);
+
+	/* return it */
+	lirc_buffer_write(buf, &key);
+	return 0;
+}
+
+static int add_to_buf_pv951(void *data, struct lirc_buffer *buf)
+{
+	struct IR *ir = data;
+	unsigned char key;
+	unsigned char codes[4];
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
+		dprintk("read error\n");
+		return -ENODATA;
+	}
+	/* ignore 0xaa */
+	if (key == 0xaa)
+		return -ENODATA;
+	dprintk("key %02x\n", key);
+
+	codes[0] = 0x61;
+	codes[1] = 0xD6;
+	codes[2] = reverse(key, 8);
+	codes[3] = (~codes[2])&0xff;
+
+	lirc_buffer_write(buf, codes);
+	return 0;
+}
+
+static int add_to_buf_knc1(void *data, struct lirc_buffer *buf)
+{
+	static unsigned char last_key = 0xFF;
+	struct IR *ir = data;
+	unsigned char key;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(&ir->c, &key, 1)) {
+		dprintk("read error\n");
+		return -ENODATA;
+	}
+
+	/*
+	 * it seems that 0xFE indicates that a button is still held
+	 * down, while 0xFF indicates that no button is held
+	 * down. 0xFE sequences are sometimes interrupted by 0xFF
+	 */
+
+	dprintk("key %02x\n", key);
+
+	if (key == 0xFF)
+		return -ENODATA;
+
+	if (key == 0xFE)
+		key = last_key;
+
+	last_key = key;
+	lirc_buffer_write(buf, &key);
+
+	return 0;
+}
+
+static int set_use_inc(void *data)
+{
+	struct IR *ir = data;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+	int ret;
+#endif
+
+	dprintk("%s called\n", __func__);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+	i2c_use_client(&ir->c);
+#else
+	/* lock bttv in memory while /dev/lirc is in use  */
+	ret = i2c_use_client(&ir->c);
+	if (ret != 0)
+		return ret;
+#endif
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	struct IR *ir = data;
+
+	dprintk("%s called\n", __func__);
+
+	i2c_release_client(&ir->c);
+	MOD_DEC_USE_COUNT;
+}
+
+static struct lirc_driver lirc_template = {
+	.name		= "lirc_i2c",
+	.set_use_inc	= set_use_inc,
+	.set_use_dec	= set_use_dec,
+	.dev		= NULL,
+	.owner		= THIS_MODULE,
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+static int ir_attach(struct i2c_adapter *adap, int addr,
+		      unsigned short flags, int kind);
+static int ir_probe(struct i2c_adapter *adap);
+# else
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
+#endif
+static int ir_remove(struct i2c_client *client);
+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
+static const struct i2c_device_id ir_receiver_id[] = {
+	/* Generic entry for any IR receiver */
+	{ "ir_video", 0 },
+	/* IR device specific entries could be added here */
+	{ }
+};
+#endif
+
+static struct i2c_driver driver = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+	.name		= "i2c ir driver",
+	.flags		= I2C_DF_NOTIFY,
+#else
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "i2c ir driver",
+	},
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	.attach_adapter	= ir_probe,
+	.detach_client	= ir_remove,
+#else
+	.probe		= ir_probe,
+	.remove		= ir_remove,
+	.id_table	= ir_receiver_id,
+#endif
+	.command	= ir_command,
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+static struct i2c_client client_template = {
+	.name		= "unset",
+	.driver		= &driver
+};
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+static int ir_attach(struct i2c_adapter *adap, int addr,
+		     unsigned short flags, int kind)
+#else
+static void pcf_probe(struct i2c_client *client, struct IR *ir)
+{
+	int ret1, ret2, ret3, ret4;
+
+	ret1 = i2c_smbus_write_byte(client, 0xff);
+	ret2 = i2c_smbus_read_byte(client);
+	ret3 = i2c_smbus_write_byte(client, 0x00);
+	ret4 = i2c_smbus_read_byte(client);
+
+	/* in the Asus TV-Box: bit 1-0 */
+	if (((ret2 & 0x03) == 0x03) && ((ret4 & 0x03) == 0x00)) {
+		ir->bits = (unsigned char) ~0x07;
+		ir->flag = 0x04;
+	/* in the Creative/VisionTek BreakOut-Box: bit 7-6 */
+	} else if (((ret2 & 0xc0) == 0xc0) && ((ret4 & 0xc0) == 0x00)) {
+		ir->bits = (unsigned char) ~0xe0;
+		ir->flag = 0x20;
+	}
+
+	return;
+}
+
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
+#endif
+{
+	struct IR *ir;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	int err, retval;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+#else
+	struct i2c_adapter *adap = client->adapter;
+	unsigned short addr = client->addr;
+	int retval;
+#endif
+
+	ir = kmalloc(sizeof(struct IR), GFP_KERNEL);
+	if (!ir)
+		return -ENOMEM;
+	memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	memcpy(&ir->c, &client_template, sizeof(struct i2c_client));
+
+	ir->c.adapter = adap;
+	ir->c.addr    = addr;
+	i2c_set_clientdata(&ir->c, ir);
+#else
+	memcpy(&ir->c, client, sizeof(struct i2c_client));
+
+	i2c_set_clientdata(client, ir);
+#endif
+	ir->l.data    = ir;
+	ir->l.minor   = minor;
+	ir->l.sample_rate = 10;
+	ir->l.dev     = &ir->c.dev;
+	ir->nextkey   = -1;
+
+	switch (addr) {
+	case 0x64:
+		strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE);
+		ir->l.code_length = 8;
+		ir->l.add_to_buf = add_to_buf_pixelview;
+		break;
+	case 0x4b:
+		strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE);
+		ir->l.code_length = 32;
+		ir->l.add_to_buf = add_to_buf_pv951;
+		break;
+	case 0x71:
+#ifdef I2C_HW_B_CX2341X
+		if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) ||
+		    adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) {
+#else
+		if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
+#endif
+			/*
+			 * The PVR150 IR receiver uses the same protocol as
+			 * other Hauppauge cards, but the data flow is
+			 * different, so we need to deal with it by its own.
+			 */
+			strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE);
+		} else /* I2C_HW_B_CX2388x */
+			strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE);
+		ir->l.code_length = 13;
+		ir->l.add_to_buf = add_to_buf_haup_pvr150;
+		break;
+	case 0x6b:
+		strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE);
+		ir->l.code_length = 32;
+		ir->l.add_to_buf = add_to_buf_adap;
+		break;
+	case 0x18:
+	case 0x1a:
+#ifdef I2C_HW_B_CX2341X
+		if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) ||
+		    adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) {
+#else
+		if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
+#endif
+			strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE);
+			ir->l.code_length = 13;
+			ir->l.add_to_buf = add_to_buf_haup;
+		} else { /* I2C_HW_B_CX2388x */
+			strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE);
+			ir->l.code_length = 8;
+			ir->l.add_to_buf = add_to_buf_pvr2000;
+		}
+		break;
+	case 0x30:
+		strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE);
+		ir->l.code_length = 8;
+		ir->l.add_to_buf = add_to_buf_knc1;
+		break;
+	case 0x21:
+	case 0x23:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+		ir->bits = flags & 0xff;
+		ir->flag = (flags >> 8) & 0xff;
+#else
+		pcf_probe(client, ir);
+#endif
+		strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE);
+		ir->l.code_length = 8;
+		ir->l.add_to_buf = add_to_buf_pcf8574;
+		break;
+	default:
+		/* shouldn't happen */
+		printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr);
+		kfree(ir);
+		return -EINVAL;
+	}
+	printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n",
+	       adap->id, addr, ir->c.name);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	/* register device */
+	err = i2c_attach_client(&ir->c);
+	if (err) {
+		kfree(ir);
+		return err;
+	}
+#endif
+
+	retval = lirc_register_driver(&ir->l);
+
+	if (retval < 0) {
+		printk(KERN_ERR "lirc_i2c: failed to register driver!\n");
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+		i2c_detach_client(&ir->c);
+#endif
+		kfree(ir);
+		return retval;
+	}
+
+	ir->l.minor = retval;
+
+	return 0;
+}
+
+static int ir_remove(struct i2c_client *client)
+{
+	struct IR *ir = i2c_get_clientdata(client);
+
+	/* unregister device */
+	lirc_unregister_driver(ir->l.minor);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	i2c_detach_client(&ir->c);
+#endif
+
+	/* free memory */
+	kfree(ir);
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+static int ir_probe(struct i2c_adapter *adap)
+{
+	/*
+	 * The external IR receiver is at i2c address 0x34 (0x35 for
+	 * reads).  Future Hauppauge cards will have an internal
+	 * receiver at 0x30 (0x31 for reads).  In theory, both can be
+	 * fitted, and Hauppauge suggest an external overrides an
+	 * internal.
+	 *
+	 * That's why we probe 0x1a (~0x34) first. CB
+	 *
+	 * The i2c address for the Hauppauge PVR-150 card is 0xe2,
+	 * so we need to probe 0x71 as well.
+	 */
+
+	static const int probe[] = {
+		0x1a, /* Hauppauge IR external */
+		0x18, /* Hauppauge IR internal */
+		0x71, /* Hauppauge IR (PVR150) */
+		0x4b, /* PV951 IR */
+		0x64, /* Pixelview IR */
+		0x30, /* KNC ONE IR */
+		0x6b, /* Adaptec IR */
+		-1};
+
+#ifdef I2C_HW_B_CX2388x
+	static const int probe_cx88[] = {
+		0x18, /* Leadtek Winfast PVR2000 */
+		0x71, /* Hauppauge HVR-IR */
+		-1};
+#endif
+
+	struct i2c_client c;
+	char buf;
+	int i, rc;
+
+	memset(&c, 0, sizeof(c));
+#ifdef I2C_HW_B_CX2341X
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) ||
+	    adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) {
+#else
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) {
+#endif
+		c.adapter = adap;
+		for (i = 0; -1 != probe[i]; i++) {
+			c.addr = probe[i];
+			rc = i2c_master_recv(&c, &buf, 1);
+			dprintk("probe 0x%02x @ %s: %s\n",
+				probe[i], adap->name,
+				(1 == rc) ? "yes" : "no");
+			if (1 == rc) {
+				rc = ir_attach(adap, probe[i], 0, 0);
+				if (rc < 0)
+					goto attach_fail;
+			}
+		}
+	}
+
+#ifdef I2C_HW_B_CX2388x
+	/* Leadtek Winfast PVR2000 or Hauppauge HVR-1300 */
+	else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2388x)) {
+		c.adapter = adap;
+		for (i = 0; -1 != probe_cx88[i]; i++) {
+			c.addr = probe_cx88[i];
+			rc = i2c_master_recv(&c, &buf, 1);
+			dprintk("probe 0x%02x @ %s: %s\n",
+				c.addr, adap->name,
+				(1 == rc) ? "yes" : "no");
+			if (1 == rc) {
+				rc = ir_attach(adap, c.addr, 0, 0);
+				if (rc < 0)
+					goto attach_fail;
+			}
+		}
+	}
+#endif
+
+	/* Asus TV-Box and Creative/VisionTek BreakOut-Box (PCF8574) */
+	else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) {
+		/*
+		 * addresses to probe;
+		 * leave 0x24 and 0x25 because SAA7113H possibly uses it
+		 * 0x21 and 0x22 possibly used by SAA7108E
+		 * Asus:      0x21 is a correct address (channel 1 of PCF8574)
+		 * Creative:  0x23 is a correct address (channel 3 of PCF8574)
+		 * VisionTek: 0x23 is a correct address (channel 3 of PCF8574)
+		 */
+		static const int pcf_probe[] = { 0x20, 0x21, 0x22, 0x23,
+						 0x24, 0x25, 0x26, 0x27, -1 };
+		int ret1, ret2, ret3, ret4;
+		unsigned char bits = 0, flag = 0;
+
+		c.adapter = adap;
+		for (i = 0; -1 != pcf_probe[i]; i++) {
+			c.addr = pcf_probe[i];
+			ret1 = i2c_smbus_write_byte(&c, 0xff);
+			ret2 = i2c_smbus_read_byte(&c);
+			ret3 = i2c_smbus_write_byte(&c, 0x00);
+			ret4 = i2c_smbus_read_byte(&c);
+
+			/* ensure that the writable bitmask works correctly */
+			rc = 0;
+			if (ret1 != -1 && ret2 != -1 &&
+			    ret3 != -1 && ret4 != -1) {
+				/* in the Asus TV-Box: bit 1-0 */
+				if (((ret2 & 0x03) == 0x03) &&
+				    ((ret4 & 0x03) == 0x00)) {
+					bits = (unsigned char) ~0x07;
+					flag = 0x04;
+					rc = 1;
+				}
+			/* in the Creative/VisionTek BreakOut-Box: bit 7-6 */
+				if (((ret2 & 0xc0) == 0xc0) &&
+				    ((ret4 & 0xc0) == 0x00)) {
+					bits = (unsigned char) ~0xe0;
+					flag = 0x20;
+					rc = 1;
+				}
+			}
+			dprintk("probe 0x%02x @ %s: %s\n",
+				c.addr, adap->name, rc ? "yes" : "no");
+			if (rc) {
+				rc = ir_attach(adap, pcf_probe[i],
+					       bits | (flag << 8), 0);
+				if (rc < 0)
+					goto attach_fail;
+			}
+		}
+	}
+
+	return 0;
+
+attach_fail:
+	printk(KERN_ERR "lirc_i2c: %s: ir_attach failed!\n", __func__);
+	return rc;
+
+}
+#endif
+
+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	/* nothing */
+	return 0;
+}
+
+#ifdef MODULE
+
+static int __init lirc_i2c_init(void)
+{
+	request_module("bttv");
+	request_module("rivatv");
+	request_module("ivtv");
+	request_module("cx8800");
+	i2c_add_driver(&driver);
+	return 0;
+}
+
+static void __exit lirc_i2c_exit(void)
+{
+	i2c_del_driver(&driver);
+}
+
+MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and "
+		   "Pixelview cards (i2c stack)");
+MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, "
+	      "Ulrich Mueller, Stefan Jahn, Jerome Brock");
+MODULE_LICENSE("GPL");
+
+module_param(minor, int, S_IRUGO);
+MODULE_PARM_DESC(minor, "Preferred minor device number");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+module_init(lirc_i2c_init);
+module_exit(lirc_i2c_exit);
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_i2c/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_i2c/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_I2C)		+= lirc_i2c.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_sir/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_sir/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_SIR)		+= lirc_sir.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_sir/lirc_sir.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_sir/lirc_sir.c
@@ -0,0 +1,1347 @@
+/*
+ * LIRC SIR driver, (C) 2000 Milan Pikula <www@fornax.sk>
+ *
+ * lirc_sir - Device driver for use with SIR (serial infra red)
+ * mode of IrDA on many notebooks.
+ *
+ *  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
+ *
+ *
+ * 2000/09/16 Frank Przybylski <mail@frankprzybylski.de> :
+ *  added timeout and relaxed pulse detection, removed gap bug
+ *
+ * 2000/12/15 Christoph Bartelmus <lirc@bartelmus.de> :
+ *   added support for Tekram Irmate 210 (sending does not work yet,
+ *   kind of disappointing that nobody was able to implement that
+ *   before),
+ *   major clean-up
+ *
+ * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> :
+ *   added support for StrongARM SA1100 embedded microprocessor
+ *   parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King
+ */
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
+#endif
+#include <linux/module.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/time.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <asm/system.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#include <asm/io.h>
+#else
+#include <linux/io.h>
+#endif
+#include <asm/irq.h>
+#include <linux/fcntl.h>
+#ifdef LIRC_ON_SA1100
+#include <asm/hardware.h>
+#ifdef CONFIG_SA1100_COLLIE
+#include <asm/arch/tc35143.h>
+#include <asm/ucb1200.h>
+#endif
+#endif
+
+#include <linux/timer.h>
+
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+#include "../kcompat.h"
+
+/* SECTION: Definitions */
+
+/*** Tekram dongle ***/
+#ifdef LIRC_SIR_TEKRAM
+/* stolen from kernel source */
+/* definitions for Tekram dongle */
+#define TEKRAM_115200 0x00
+#define TEKRAM_57600  0x01
+#define TEKRAM_38400  0x02
+#define TEKRAM_19200  0x03
+#define TEKRAM_9600   0x04
+#define TEKRAM_2400   0x08
+
+#define TEKRAM_PW 0x10 /* Pulse select bit */
+
+/* 10bit * 1s/115200bit in milliseconds = 87ms*/
+#define TIME_CONST (10000000ul/115200ul)
+
+#endif
+
+#ifdef LIRC_SIR_ACTISYS_ACT200L
+static void init_act200(void);
+#elif defined(LIRC_SIR_ACTISYS_ACT220L)
+static void init_act220(void);
+#endif
+
+/*** SA1100 ***/
+#ifdef LIRC_ON_SA1100
+struct sa1100_ser2_registers {
+	/* HSSP control register */
+	unsigned char hscr0;
+	/* UART registers */
+	unsigned char utcr0;
+	unsigned char utcr1;
+	unsigned char utcr2;
+	unsigned char utcr3;
+	unsigned char utcr4;
+	unsigned char utdr;
+	unsigned char utsr0;
+	unsigned char utsr1;
+} sr;
+
+static int irq = IRQ_Ser2ICP;
+
+#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0
+
+/* pulse/space ratio of 50/50 */
+static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
+/* 1000000/freq-pulse_width */
+static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY);
+static unsigned int freq = 38000;      /* modulation frequency */
+static unsigned int duty_cycle = 50;   /* duty cycle of 50% */
+
+#endif
+
+#define RBUF_LEN 1024
+#define WBUF_LEN 1024
+
+#define LIRC_DRIVER_NAME "lirc_sir"
+
+#define PULSE '['
+
+#ifndef LIRC_SIR_TEKRAM
+/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/
+#define TIME_CONST (9000000ul/115200ul)
+#endif
+
+
+/* timeout for sequences in jiffies (=5/100s), must be longer than TIME_CONST */
+#define SIR_TIMEOUT	(HZ*5/100)
+
+#ifndef LIRC_ON_SA1100
+#ifndef LIRC_IRQ
+#define LIRC_IRQ 4
+#endif
+#ifndef LIRC_PORT
+/* for external dongles, default to com1 */
+#if defined(LIRC_SIR_ACTISYS_ACT200L) || \
+    defined(LIRC_SIR_ACTISYS_ACT220L) || \
+    defined(LIRC_SIR_TEKRAM)
+#define LIRC_PORT 0x3f8
+#else
+/* onboard sir ports are typically com3 */
+#define LIRC_PORT 0x3e8
+#endif
+#endif
+
+static int io = LIRC_PORT;
+static int irq = LIRC_IRQ;
+static int threshold = 3;
+#endif
+
+static DEFINE_SPINLOCK(timer_lock);
+static struct timer_list timerlist;
+/* time of last signal change detected */
+static struct timeval last_tv = {0, 0};
+/* time of last UART data ready interrupt */
+static struct timeval last_intr_tv = {0, 0};
+static int last_value;
+
+static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
+
+static DEFINE_SPINLOCK(hardware_lock);
+static DEFINE_SPINLOCK(dev_lock);
+
+static lirc_t rx_buf[RBUF_LEN];
+static unsigned int rx_tail, rx_head;
+static lirc_t tx_buf[WBUF_LEN];
+
+static int debug;
+#define dprintk(fmt, args...)						\
+	do {								\
+		if (debug)						\
+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "		\
+				fmt, ## args);				\
+	} while (0)
+
+/* SECTION: Prototypes */
+
+/* Communication with user-space */
+static int lirc_open(struct inode *inode, struct file *file);
+static int lirc_close(struct inode *inode, struct file *file);
+static unsigned int lirc_poll(struct file *file, poll_table *wait);
+static ssize_t lirc_read(struct file *file, char *buf, size_t count,
+		loff_t *ppos);
+static ssize_t lirc_write(struct file *file, const char *buf, size_t n,
+		loff_t *pos);
+static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd,
+		unsigned long arg);
+static void add_read_queue(int flag, unsigned long val);
+#ifdef MODULE
+static int init_chrdev(void);
+static void drop_chrdev(void);
+#endif
+/* Hardware */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static irqreturn_t sir_interrupt(int irq, void *dev_id,
+				 struct pt_regs *regs);
+#else
+static irqreturn_t sir_interrupt(int irq, void *dev_id);
+#endif
+static void send_space(unsigned long len);
+static void send_pulse(unsigned long len);
+static int init_hardware(void);
+static void drop_hardware(void);
+/* Initialisation */
+static int init_port(void);
+static void drop_port(void);
+
+#ifdef LIRC_ON_SA1100
+static void on(void)
+{
+	PPSR |= PPC_TXD2;
+}
+
+static void off(void)
+{
+	PPSR &= ~PPC_TXD2;
+}
+#else
+static unsigned int sinp(int offset)
+{
+	return inb(io + offset);
+}
+
+static void soutp(int offset, int value)
+{
+	outb(value, io + offset);
+}
+#endif
+
+#ifndef MAX_UDELAY_MS
+#define MAX_UDELAY_US 5000
+#else
+#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
+#endif
+
+static void safe_udelay(unsigned long usecs)
+{
+	while (usecs > MAX_UDELAY_US) {
+		udelay(MAX_UDELAY_US);
+		usecs -= MAX_UDELAY_US;
+	}
+	udelay(usecs);
+}
+
+/* SECTION: Communication with user-space */
+
+static int lirc_open(struct inode *inode, struct file *file)
+{
+	spin_lock(&dev_lock);
+	if (MOD_IN_USE) {
+		spin_unlock(&dev_lock);
+		return -EBUSY;
+	}
+	MOD_INC_USE_COUNT;
+	spin_unlock(&dev_lock);
+	return 0;
+}
+
+static int lirc_close(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static unsigned int lirc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &lirc_read_queue, wait);
+	if (rx_head != rx_tail)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static ssize_t lirc_read(struct file *file, char *buf, size_t count,
+		loff_t *ppos)
+{
+	int n = 0;
+	int retval = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count % sizeof(lirc_t))
+		return -EINVAL;
+
+	add_wait_queue(&lirc_read_queue, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (n < count) {
+		if (rx_head != rx_tail) {
+			if (copy_to_user((void *) buf + n,
+					(void *) (rx_buf + rx_head),
+					sizeof(lirc_t))) {
+				retval = -EFAULT;
+				break;
+			}
+			rx_head = (rx_head + 1) & (RBUF_LEN - 1);
+			n += sizeof(lirc_t);
+		} else {
+			if (file->f_flags & O_NONBLOCK) {
+				retval = -EAGAIN;
+				break;
+			}
+			if (signal_pending(current)) {
+				retval = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+			set_current_state(TASK_INTERRUPTIBLE);
+		}
+	}
+	remove_wait_queue(&lirc_read_queue, &wait);
+	set_current_state(TASK_RUNNING);
+	return n ? n : retval;
+}
+static ssize_t lirc_write(struct file *file, const char *buf, size_t n,
+				loff_t *pos)
+{
+	unsigned long flags;
+	int i;
+
+	if (n % sizeof(lirc_t) || (n / sizeof(lirc_t)) > WBUF_LEN)
+		return -EINVAL;
+	if (copy_from_user(tx_buf, buf, n))
+		return -EFAULT;
+	i = 0;
+	n /= sizeof(lirc_t);
+#ifdef LIRC_ON_SA1100
+	/* disable receiver */
+	Ser2UTCR3 = 0;
+#endif
+	local_irq_save(flags);
+	while (1) {
+		if (i >= n)
+			break;
+		if (tx_buf[i])
+			send_pulse(tx_buf[i]);
+		i++;
+		if (i >= n)
+			break;
+		if (tx_buf[i])
+			send_space(tx_buf[i]);
+		i++;
+	}
+	local_irq_restore(flags);
+#ifdef LIRC_ON_SA1100
+	off();
+	udelay(1000); /* wait 1ms for IR diode to recover */
+	Ser2UTCR3 = 0;
+	/* clear status register to prevent unwanted interrupts */
+	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
+	/* enable receiver */
+	Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE;
+#endif
+	return n;
+}
+
+static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd,
+		unsigned long arg)
+{
+	int retval = 0;
+	unsigned long value = 0;
+#ifdef LIRC_ON_SA1100
+	unsigned int ivalue;
+
+	if (cmd == LIRC_GET_FEATURES)
+		value = LIRC_CAN_SEND_PULSE |
+			LIRC_CAN_SET_SEND_DUTY_CYCLE |
+			LIRC_CAN_SET_SEND_CARRIER |
+			LIRC_CAN_REC_MODE2;
+	else if (cmd == LIRC_GET_SEND_MODE)
+		value = LIRC_MODE_PULSE;
+	else if (cmd == LIRC_GET_REC_MODE)
+		value = LIRC_MODE_MODE2;
+#else
+	if (cmd == LIRC_GET_FEATURES)
+		value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
+	else if (cmd == LIRC_GET_SEND_MODE)
+		value = LIRC_MODE_PULSE;
+	else if (cmd == LIRC_GET_REC_MODE)
+		value = LIRC_MODE_MODE2;
+#endif
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+	case LIRC_GET_SEND_MODE:
+	case LIRC_GET_REC_MODE:
+		retval = put_user(value, (unsigned long *) arg);
+		break;
+
+	case LIRC_SET_SEND_MODE:
+	case LIRC_SET_REC_MODE:
+		retval = get_user(value, (unsigned long *) arg);
+		break;
+#ifdef LIRC_ON_SA1100
+	case LIRC_SET_SEND_DUTY_CYCLE:
+		retval = get_user(ivalue, (unsigned int *) arg);
+		if (retval)
+			return reetval;
+		if (ivalue <= 0 || ivalue > 100)
+			return -EINVAL;
+		/* (ivalue/100)*(1000000/freq) */
+		duty_cycle = ivalue;
+		pulse_width = (unsigned long) duty_cycle*10000/freq;
+		space_width = (unsigned long) 1000000L/freq-pulse_width;
+		if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
+			pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
+		if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
+			space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
+		break;
+	case LIRC_SET_SEND_CARRIER:
+		retval = get_user(ivalue, (unsigned int *) arg);
+		if (retval)
+			return retval;
+		if (ivalue > 500000 || ivalue < 20000)
+			return -EINVAL;
+		freq = ivalue;
+		pulse_width = (unsigned long) duty_cycle*10000/freq;
+		space_width = (unsigned long) 1000000L/freq-pulse_width;
+		if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
+			pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
+		if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
+			space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
+		break;
+#endif
+	default:
+		retval = -ENOIOCTLCMD;
+
+	}
+
+	if (retval)
+		return retval;
+	if (cmd == LIRC_SET_REC_MODE) {
+		if (value != LIRC_MODE_MODE2)
+			retval = -ENOSYS;
+	} else if (cmd == LIRC_SET_SEND_MODE) {
+		if (value != LIRC_MODE_PULSE)
+			retval = -ENOSYS;
+	}
+
+	return retval;
+}
+
+static void add_read_queue(int flag, unsigned long val)
+{
+	unsigned int new_rx_tail;
+	lirc_t newval;
+
+	dprintk("add flag %d with val %lu\n", flag, val);
+
+	newval = val & PULSE_MASK;
+
+	/*
+	 * statistically, pulses are ~TIME_CONST/2 too long. we could
+	 * maybe make this more exact, but this is good enough
+	 */
+	if (flag) {
+		/* pulse */
+		if (newval > TIME_CONST/2)
+			newval -= TIME_CONST/2;
+		else /* should not ever happen */
+			newval = 1;
+		newval |= PULSE_BIT;
+	} else {
+		newval += TIME_CONST/2;
+	}
+	new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);
+	if (new_rx_tail == rx_head) {
+		dprintk("Buffer overrun.\n");
+		return;
+	}
+	rx_buf[rx_tail] = newval;
+	rx_tail = new_rx_tail;
+	wake_up_interruptible(&lirc_read_queue);
+}
+
+static struct file_operations lirc_fops = {
+	.owner		= THIS_MODULE,
+	.read		= lirc_read,
+	.write		= lirc_write,
+	.poll		= lirc_poll,
+	.ioctl		= lirc_ioctl,
+	.open		= lirc_open,
+	.release	= lirc_close,
+};
+
+static int set_use_inc(void *data)
+{
+       return 0;
+}
+
+static void set_use_dec(void *data)
+{
+}
+
+static struct lirc_driver driver = {
+       .name		= LIRC_DRIVER_NAME,
+       .minor		= -1,
+       .code_length	= 1,
+       .sample_rate	= 0,
+       .data		= NULL,
+       .add_to_buf	= NULL,
+#ifndef LIRC_REMOVE_DURING_EXPORT
+       .get_queue	= NULL,
+#endif
+       .set_use_inc	= set_use_inc,
+       .set_use_dec	= set_use_dec,
+       .fops		= &lirc_fops,
+       .dev		= NULL,
+       .owner		= THIS_MODULE,
+};
+
+
+#ifdef MODULE
+static int init_chrdev(void)
+{
+	driver.minor = lirc_register_driver(&driver);
+	if (driver.minor < 0) {
+		printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static void drop_chrdev(void)
+{
+	lirc_unregister_driver(driver.minor);
+}
+#endif
+
+/* SECTION: Hardware */
+static long delta(struct timeval *tv1, struct timeval *tv2)
+{
+	unsigned long deltv;
+
+	deltv = tv2->tv_sec - tv1->tv_sec;
+	if (deltv > 15)
+		deltv = 0xFFFFFF;
+	else
+		deltv = deltv*1000000 +
+			tv2->tv_usec -
+			tv1->tv_usec;
+	return deltv;
+}
+
+static void sir_timeout(unsigned long data)
+{
+	/*
+	 * if last received signal was a pulse, but receiving stopped
+	 * within the 9 bit frame, we need to finish this pulse and
+	 * simulate a signal change to from pulse to space. Otherwise
+	 * upper layers will receive two sequences next time.
+	 */
+
+	unsigned long flags;
+	unsigned long pulse_end;
+
+	/* avoid interference with interrupt */
+	spin_lock_irqsave(&timer_lock, flags);
+	if (last_value) {
+#ifndef LIRC_ON_SA1100
+		/* clear unread bits in UART and restart */
+		outb(UART_FCR_CLEAR_RCVR, io + UART_FCR);
+#endif
+		/* determine 'virtual' pulse end: */
+		pulse_end = delta(&last_tv, &last_intr_tv);
+		dprintk("timeout add %d for %lu usec\n", last_value, pulse_end);
+		add_read_queue(last_value, pulse_end);
+		last_value = 0;
+		last_tv = last_intr_tv;
+	}
+	spin_unlock_irqrestore(&timer_lock, flags);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static irqreturn_t sir_interrupt(int irq, void *dev_id,
+				 struct pt_regs *regs)
+#else
+static irqreturn_t sir_interrupt(int irq, void *dev_id)
+#endif
+{
+	unsigned char data;
+	struct timeval curr_tv;
+	static unsigned long deltv;
+#ifdef LIRC_ON_SA1100
+	int status;
+	static int n;
+
+	status = Ser2UTSR0;
+	/*
+	 * Deal with any receive errors first.  The bytes in error may be
+	 * the only bytes in the receive FIFO, so we do this first.
+	 */
+	while (status & UTSR0_EIF) {
+		int bstat;
+
+		if (debug) {
+			dprintk("EIF\n");
+			bstat = Ser2UTSR1;
+
+			if (bstat & UTSR1_FRE)
+				dprintk("frame error\n");
+			if (bstat & UTSR1_ROR)
+				dprintk("receive fifo overrun\n");
+			if (bstat & UTSR1_PRE)
+				dprintk("parity error\n");
+		}
+
+		bstat = Ser2UTDR;
+		n++;
+		status = Ser2UTSR0;
+	}
+
+	if (status & (UTSR0_RFS | UTSR0_RID)) {
+		do_gettimeofday(&curr_tv);
+		deltv = delta(&last_tv, &curr_tv);
+		do {
+			data = Ser2UTDR;
+			dprintk("%d data: %u\n", n, (unsigned int) data);
+			n++;
+		} while (status & UTSR0_RID && /* do not empty fifo in order to
+						* get UTSR0_RID in any case */
+		      Ser2UTSR1 & UTSR1_RNE); /* data ready */
+
+		if (status&UTSR0_RID) {
+			add_read_queue(0 , deltv - n * TIME_CONST); /*space*/
+			add_read_queue(1, n * TIME_CONST); /*pulse*/
+			n = 0;
+			last_tv = curr_tv;
+		}
+	}
+
+	if (status & UTSR0_TFS)
+		printk(KERN_ERR "transmit fifo not full, shouldn't happen\n");
+
+	/* We must clear certain bits. */
+	status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
+	if (status)
+		Ser2UTSR0 = status;
+#else
+	unsigned long deltintrtv;
+	unsigned long flags;
+	int iir, lsr;
+
+	while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {
+		switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */
+		case UART_IIR_MSI:
+			(void) inb(io + UART_MSR);
+			break;
+		case UART_IIR_RLSI:
+			(void) inb(io + UART_LSR);
+			break;
+		case UART_IIR_THRI:
+#if 0
+			if (lsr & UART_LSR_THRE) /* FIFO is empty */
+				outb(data, io + UART_TX)
+#endif
+			break;
+		case UART_IIR_RDI:
+			/* avoid interference with timer */
+			spin_lock_irqsave(&timer_lock, flags);
+			do {
+				del_timer(&timerlist);
+				data = inb(io + UART_RX);
+				do_gettimeofday(&curr_tv);
+				deltv = delta(&last_tv, &curr_tv);
+				deltintrtv = delta(&last_intr_tv, &curr_tv);
+				dprintk("t %lu, d %d\n", deltintrtv, (int)data);
+				/*
+				 * if nothing came in last X cycles,
+				 * it was gap
+				 */
+				if (deltintrtv > TIME_CONST * threshold) {
+					if (last_value) {
+						dprintk("GAP\n");
+						/* simulate signal change */
+						add_read_queue(last_value,
+							       deltv -
+							       deltintrtv);
+						last_value = 0;
+						last_tv.tv_sec =
+							last_intr_tv.tv_sec;
+						last_tv.tv_usec =
+							last_intr_tv.tv_usec;
+						deltv = deltintrtv;
+					}
+				}
+				data = 1;
+				if (data ^ last_value) {
+					/*
+					 * deltintrtv > 2*TIME_CONST, remember?
+					 * the other case is timeout
+					 */
+					add_read_queue(last_value,
+						       deltv-TIME_CONST);
+					last_value = data;
+					last_tv = curr_tv;
+					if (last_tv.tv_usec >= TIME_CONST) {
+						last_tv.tv_usec -= TIME_CONST;
+					} else {
+						last_tv.tv_sec--;
+						last_tv.tv_usec += 1000000 -
+							TIME_CONST;
+					}
+				}
+				last_intr_tv = curr_tv;
+				if (data) {
+					/*
+					 * start timer for end of
+					 * sequence detection
+					 */
+					timerlist.expires = jiffies +
+								SIR_TIMEOUT;
+					add_timer(&timerlist);
+				}
+
+				lsr = inb(io + UART_LSR);
+			} while (lsr & UART_LSR_DR); /* data ready */
+			spin_unlock_irqrestore(&timer_lock, flags);
+			break;
+		default:
+			break;
+		}
+	}
+#endif
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+#ifdef LIRC_ON_SA1100
+static void send_pulse(unsigned long length)
+{
+	unsigned long k, delay;
+	int flag;
+
+	if (length == 0)
+		return;
+	/*
+	 * this won't give us the carrier frequency we really want
+	 * due to integer arithmetic, but we can accept this inaccuracy
+	 */
+
+	for (k = flag = 0; k < length; k += delay, flag = !flag) {
+		if (flag) {
+			off();
+			delay = space_width;
+		} else {
+			on();
+			delay = pulse_width;
+		}
+		safe_udelay(delay);
+	}
+	off();
+}
+
+static void send_space(unsigned long length)
+{
+	if (length == 0)
+		return;
+	off();
+	safe_udelay(length);
+}
+#else
+static void send_space(unsigned long len)
+{
+	safe_udelay(len);
+}
+
+static void send_pulse(unsigned long len)
+{
+	long bytes_out = len / TIME_CONST;
+	long time_left;
+
+	time_left = (long)len - (long)bytes_out * (long)TIME_CONST;
+	if (bytes_out == 0) {
+		bytes_out++;
+		time_left = 0;
+	}
+	while (bytes_out--) {
+		outb(PULSE, io + UART_TX);
+		/* FIXME treba seriozne cakanie z drivers/char/serial.c */
+		while (!(inb(io + UART_LSR) & UART_LSR_THRE))
+			;
+	}
+#if 0
+	if (time_left > 0)
+		safe_udelay(time_left);
+#endif
+}
+#endif
+
+#ifdef CONFIG_SA1100_COLLIE
+static int sa1100_irda_set_power_collie(int state)
+{
+	if (state) {
+		/*
+		 *  0 - off
+		 *  1 - short range, lowest power
+		 *  2 - medium range, medium power
+		 *  3 - maximum range, high power
+		 */
+		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,
+					 TC35143_IODIR_OUTPUT);
+		ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW);
+		udelay(100);
+	} else {
+		/* OFF */
+		ucb1200_set_io_direction(TC35143_GPIO_IR_ON,
+					 TC35143_IODIR_OUTPUT);
+		ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH);
+	}
+	return 0;
+}
+#endif
+
+static int init_hardware(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hardware_lock, flags);
+	/* reset UART */
+#ifdef LIRC_ON_SA1100
+#ifdef CONFIG_SA1100_BITSY
+	if (machine_is_bitsy()) {
+		printk(KERN_INFO "Power on IR module\n");
+		set_bitsy_egpio(EGPIO_BITSY_IR_ON);
+	}
+#endif
+#ifdef CONFIG_SA1100_COLLIE
+	sa1100_irda_set_power_collie(3);	/* power on */
+#endif
+	sr.hscr0 = Ser2HSCR0;
+
+	sr.utcr0 = Ser2UTCR0;
+	sr.utcr1 = Ser2UTCR1;
+	sr.utcr2 = Ser2UTCR2;
+	sr.utcr3 = Ser2UTCR3;
+	sr.utcr4 = Ser2UTCR4;
+
+	sr.utdr = Ser2UTDR;
+	sr.utsr0 = Ser2UTSR0;
+	sr.utsr1 = Ser2UTSR1;
+
+	/* configure GPIO */
+	/* output */
+	PPDR |= PPC_TXD2;
+	PSDR |= PPC_TXD2;
+	/* set output to 0 */
+	off();
+
+	/* Enable HP-SIR modulation, and ensure that the port is disabled. */
+	Ser2UTCR3 = 0;
+	Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP);
+
+	/* clear status register to prevent unwanted interrupts */
+	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
+
+	/* 7N1 */
+	Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData;
+	/* 115200 */
+	Ser2UTCR1 = 0;
+	Ser2UTCR2 = 1;
+	/* use HPSIR, 1.6 usec pulses */
+	Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us;
+
+	/* enable receiver, receive fifo interrupt */
+	Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE;
+
+	/* clear status register to prevent unwanted interrupts */
+	Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB);
+
+#elif defined(LIRC_SIR_TEKRAM)
+	/* disable FIFO */
+	soutp(UART_FCR,
+	      UART_FCR_CLEAR_RCVR|
+	      UART_FCR_CLEAR_XMIT|
+	      UART_FCR_TRIGGER_1);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* First of all, disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
+
+	/* Set DLAB 1. */
+	soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+
+	/* Set divisor to 12 => 9600 Baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 12);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* power supply */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	safe_udelay(50*1000);
+
+	/* -DTR low -> reset PIC */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
+	udelay(1*1000);
+
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	udelay(100);
+
+
+	/* -RTS low -> send control byte */
+	soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
+	udelay(7);
+	soutp(UART_TX, TEKRAM_115200|TEKRAM_PW);
+
+	/* one byte takes ~1042 usec to transmit at 9600,8N1 */
+	udelay(1500);
+
+	/* back to normal operation */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	udelay(50);
+
+	udelay(1500);
+
+	/* read previous control byte */
+	printk(KERN_INFO LIRC_DRIVER_NAME
+	       ": 0x%02x\n", sinp(UART_RX));
+
+	/* Set DLAB 1. */
+	soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+
+	/* Set divisor to 1 => 115200 Baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 1);
+
+	/* Set DLAB 0, 8 Bit */
+	soutp(UART_LCR, UART_LCR_WLEN8);
+	/* enable interrupts */
+	soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);
+#else
+	outb(0, io + UART_MCR);
+	outb(0, io + UART_IER);
+	/* init UART */
+	/* set DLAB, speed = 115200 */
+	outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR);
+	outb(1, io + UART_DLL); outb(0, io + UART_DLM);
+	/* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */
+	outb(UART_LCR_WLEN7, io + UART_LCR);
+	/* FIFO operation */
+	outb(UART_FCR_ENABLE_FIFO, io + UART_FCR);
+	/* interrupts */
+	/* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */
+	outb(UART_IER_RDI, io + UART_IER);
+	/* turn on UART */
+	outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR);
+#ifdef LIRC_SIR_ACTISYS_ACT200L
+	init_act200();
+#elif defined(LIRC_SIR_ACTISYS_ACT220L)
+	init_act220();
+#endif
+#endif
+	spin_unlock_irqrestore(&hardware_lock, flags);
+	return 0;
+}
+
+static void drop_hardware(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hardware_lock, flags);
+
+#ifdef LIRC_ON_SA1100
+	Ser2UTCR3 = 0;
+
+	Ser2UTCR0 = sr.utcr0;
+	Ser2UTCR1 = sr.utcr1;
+	Ser2UTCR2 = sr.utcr2;
+	Ser2UTCR4 = sr.utcr4;
+	Ser2UTCR3 = sr.utcr3;
+
+	Ser2HSCR0 = sr.hscr0;
+#ifdef CONFIG_SA1100_BITSY
+	if (machine_is_bitsy())
+		clr_bitsy_egpio(EGPIO_BITSY_IR_ON);
+#endif
+#ifdef CONFIG_SA1100_COLLIE
+	sa1100_irda_set_power_collie(0);	/* power off */
+#endif
+#else
+	/* turn off interrupts */
+	outb(0, io + UART_IER);
+#endif
+	spin_unlock_irqrestore(&hardware_lock, flags);
+}
+
+/* SECTION: Initialisation */
+
+static int init_port(void)
+{
+	int retval;
+
+	/* get I/O port access and IRQ line */
+#ifndef LIRC_ON_SA1100
+	if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
+		printk(KERN_ERR LIRC_DRIVER_NAME
+		       ": i/o port 0x%.4x already in use.\n", io);
+		return -EBUSY;
+	}
+#endif
+	retval = request_irq(irq, sir_interrupt, IRQF_DISABLED,
+			     LIRC_DRIVER_NAME, NULL);
+	if (retval < 0) {
+#               ifndef LIRC_ON_SA1100
+		release_region(io, 8);
+#               endif
+		printk(KERN_ERR LIRC_DRIVER_NAME
+			": IRQ %d already in use.\n",
+			irq);
+		return retval;
+	}
+#ifndef LIRC_ON_SA1100
+	printk(KERN_INFO LIRC_DRIVER_NAME
+		": I/O port 0x%.4x, IRQ %d.\n",
+		io, irq);
+#endif
+
+	init_timer(&timerlist);
+	timerlist.function = sir_timeout;
+	timerlist.data = 0xabadcafe;
+
+	return 0;
+}
+
+static void drop_port(void)
+{
+	free_irq(irq, NULL);
+	del_timer_sync(&timerlist);
+#ifndef LIRC_ON_SA1100
+	release_region(io, 8);
+#endif
+}
+
+#ifdef LIRC_SIR_ACTISYS_ACT200L
+/* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */
+/* some code borrowed from Linux IRDA driver */
+
+/* Register 0: Control register #1 */
+#define ACT200L_REG0    0x00
+#define ACT200L_TXEN    0x01 /* Enable transmitter */
+#define ACT200L_RXEN    0x02 /* Enable receiver */
+#define ACT200L_ECHO    0x08 /* Echo control chars */
+
+/* Register 1: Control register #2 */
+#define ACT200L_REG1    0x10
+#define ACT200L_LODB    0x01 /* Load new baud rate count value */
+#define ACT200L_WIDE    0x04 /* Expand the maximum allowable pulse */
+
+/* Register 3: Transmit mode register #2 */
+#define ACT200L_REG3    0x30
+#define ACT200L_B0      0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P)  */
+#define ACT200L_B1      0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P)  */
+#define ACT200L_CHSY    0x04 /* StartBit Synced 0=bittime, 1=startbit */
+
+/* Register 4: Output Power register */
+#define ACT200L_REG4    0x40
+#define ACT200L_OP0     0x01 /* Enable LED1C output */
+#define ACT200L_OP1     0x02 /* Enable LED2C output */
+#define ACT200L_BLKR    0x04
+
+/* Register 5: Receive Mode register */
+#define ACT200L_REG5    0x50
+#define ACT200L_RWIDL   0x01 /* fixed 1.6us pulse mode */
+    /*.. other various IRDA bit modes, and TV remote modes..*/
+
+/* Register 6: Receive Sensitivity register #1 */
+#define ACT200L_REG6    0x60
+#define ACT200L_RS0     0x01 /* receive threshold bit 0 */
+#define ACT200L_RS1     0x02 /* receive threshold bit 1 */
+
+/* Register 7: Receive Sensitivity register #2 */
+#define ACT200L_REG7    0x70
+#define ACT200L_ENPOS   0x04 /* Ignore the falling edge */
+
+/* Register 8,9: Baud Rate Divider register #1,#2 */
+#define ACT200L_REG8    0x80
+#define ACT200L_REG9    0x90
+
+#define ACT200L_2400    0x5f
+#define ACT200L_9600    0x17
+#define ACT200L_19200   0x0b
+#define ACT200L_38400   0x05
+#define ACT200L_57600   0x03
+#define ACT200L_115200  0x01
+
+/* Register 13: Control register #3 */
+#define ACT200L_REG13   0xd0
+#define ACT200L_SHDW    0x01 /* Enable access to shadow registers */
+
+/* Register 15: Status register */
+#define ACT200L_REG15   0xf0
+
+/* Register 21: Control register #4 */
+#define ACT200L_REG21   0x50
+#define ACT200L_EXCK    0x02 /* Disable clock output driver */
+#define ACT200L_OSCL    0x04 /* oscillator in low power, medium accuracy mode */
+
+static void init_act200(void)
+{
+	int i;
+	__u8 control[] = {
+		ACT200L_REG15,
+		ACT200L_REG13 | ACT200L_SHDW,
+		ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
+		ACT200L_REG13,
+		ACT200L_REG7  | ACT200L_ENPOS,
+		ACT200L_REG6  | ACT200L_RS0  | ACT200L_RS1,
+		ACT200L_REG5  | ACT200L_RWIDL,
+		ACT200L_REG4  | ACT200L_OP0  | ACT200L_OP1 | ACT200L_BLKR,
+		ACT200L_REG3  | ACT200L_B0,
+		ACT200L_REG0  | ACT200L_TXEN | ACT200L_RXEN,
+		ACT200L_REG8 |  (ACT200L_115200       & 0x0f),
+		ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f),
+		ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE
+	};
+
+	/* Set DLAB 1. */
+	soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
+
+	/* Set divisor to 12 => 9600 Baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 12);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, UART_LCR_WLEN8);
+	/* Set divisor to 12 => 9600 Baud */
+
+	/* power supply */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	for (i = 0; i < 50; i++)
+		safe_udelay(1000);
+
+		/* Reset the dongle : set RTS low for 25 ms */
+	soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
+	for (i = 0; i < 25; i++)
+		udelay(1000);
+
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	udelay(100);
+
+	/* Clear DTR and set RTS to enter command mode */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
+	udelay(7);
+
+	/* send out the control register settings for 115K 7N1 SIR operation */
+	for (i = 0; i < sizeof(control); i++) {
+		soutp(UART_TX, control[i]);
+		/* one byte takes ~1042 usec to transmit at 9600,8N1 */
+		udelay(1500);
+	}
+
+	/* back to normal operation */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	udelay(50);
+
+	udelay(1500);
+	soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+
+	/* Set DLAB 1. */
+	soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7);
+
+	/* Set divisor to 1 => 115200 Baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 1);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* Set DLAB 0, 7 Bit */
+	soutp(UART_LCR, UART_LCR_WLEN7);
+
+	/* enable interrupts */
+	soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);
+}
+#endif
+
+#ifdef LIRC_SIR_ACTISYS_ACT220L
+/*
+ * Derived from linux IrDA driver (net/irda/actisys.c)
+ * Drop me a mail for any kind of comment: maxx@spaceboyz.net
+ */
+
+void init_act220(void)
+{
+	int i;
+
+	/* DLAB 1 */
+	soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7);
+
+	/* 9600 baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 12);
+
+	/* DLAB 0 */
+	soutp(UART_LCR, UART_LCR_WLEN7);
+
+	/* reset the dongle, set DTR low for 10us */
+	soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2);
+	udelay(10);
+
+	/* back to normal (still 9600) */
+	soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2);
+
+	/*
+	 * send RTS pulses until we reach 115200
+	 * i hope this is really the same for act220l/act220l+
+	 */
+	for (i = 0; i < 3; i++) {
+		udelay(10);
+		/* set RTS low for 10 us */
+		soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2);
+		udelay(10);
+		/* set RTS high for 10 us */
+		soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2);
+	}
+
+	/* back to normal operation */
+	udelay(1500); /* better safe than sorry ;) */
+
+	/* Set DLAB 1. */
+	soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7);
+
+	/* Set divisor to 1 => 115200 Baud */
+	soutp(UART_DLM, 0);
+	soutp(UART_DLL, 1);
+
+	/* Set DLAB 0, 7 Bit */
+	/* The dongle doesn't seem to have any problems with operation at 7N1 */
+	soutp(UART_LCR, UART_LCR_WLEN7);
+
+	/* enable interrupts */
+	soutp(UART_IER, UART_IER_RDI);
+}
+#endif
+
+static int init_lirc_sir(void)
+{
+	int retval;
+
+	init_waitqueue_head(&lirc_read_queue);
+	retval = init_port();
+	if (retval < 0)
+		return retval;
+	init_hardware();
+	printk(KERN_INFO LIRC_DRIVER_NAME
+		": Installed.\n");
+	return 0;
+}
+
+#ifdef MODULE
+
+static int __init lirc_sir_init(void)
+{
+	int retval;
+
+	retval = init_chrdev();
+	if (retval < 0)
+		return retval;
+	retval = init_lirc_sir();
+	if (retval) {
+		drop_chrdev();
+		return retval;
+	}
+	return 0;
+}
+
+static void __exit lirc_sir_exit(void)
+{
+	drop_hardware();
+	drop_chrdev();
+	drop_port();
+	printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
+}
+
+module_init(lirc_sir_init);
+module_exit(lirc_sir_exit);
+
+#ifdef LIRC_SIR_TEKRAM
+MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210");
+MODULE_AUTHOR("Christoph Bartelmus");
+#elif defined(LIRC_ON_SA1100)
+MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor");
+MODULE_AUTHOR("Christoph Bartelmus");
+#elif defined(LIRC_SIR_ACTISYS_ACT200L)
+MODULE_DESCRIPTION("LIRC driver for Actisys Act200L");
+MODULE_AUTHOR("Karl Bongers");
+#elif defined(LIRC_SIR_ACTISYS_ACT220L)
+MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)");
+MODULE_AUTHOR("Jan Roemisch");
+#else
+MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports");
+MODULE_AUTHOR("Milan Pikula");
+#endif
+MODULE_LICENSE("GPL");
+
+#ifdef LIRC_ON_SA1100
+module_param(irq, int, S_IRUGO);
+MODULE_PARM_DESC(irq, "Interrupt (16)");
+#else
+module_param(io, int, S_IRUGO);
+MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
+
+module_param(irq, int, S_IRUGO);
+MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
+
+module_param(threshold, int, S_IRUGO);
+MODULE_PARM_DESC(threshold, "space detection threshold (3)");
+#endif
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_dev/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_dev/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_DEV)		+= lirc_dev.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_dev/lirc_dev.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_dev/lirc_dev.h
@@ -0,0 +1,342 @@
+/*
+ * LIRC base driver
+ *
+ * (L) by Artur Lipowski <alipowski@interia.pl>
+ *        This code is licensed under GNU GPL
+ *
+ * $Id: lirc_dev.h,v 1.37 2009/03/15 09:34:00 lirc Exp $
+ *
+ */
+
+#ifndef _LINUX_LIRC_DEV_H
+#define _LINUX_LIRC_DEV_H
+
+#ifndef LIRC_REMOVE_DURING_EXPORT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
+/* when was it really introduced? */
+#define LIRC_HAVE_KFIFO
+#endif
+#endif
+#define MAX_IRCTL_DEVICES 4
+#define BUFLEN            16
+
+#define mod(n, div) ((n) % (div))
+
+#include <linux/slab.h>
+#include <linux/fs.h>
+#ifdef LIRC_HAVE_KFIFO
+#include <linux/kfifo.h>
+#endif
+
+struct lirc_buffer {
+	wait_queue_head_t wait_poll;
+	spinlock_t lock;
+	unsigned int chunk_size;
+	unsigned int size; /* in chunks */
+	/* Using chunks instead of bytes pretends to simplify boundary checking
+	 * And should allow for some performance fine tunning later */
+#ifdef LIRC_HAVE_KFIFO
+	struct kfifo *fifo;
+#else
+	unsigned int fill; /* in chunks */
+	int head, tail;    /* in chunks */
+	unsigned char *data;
+#endif
+};
+#ifndef LIRC_HAVE_KFIFO
+static inline void lirc_buffer_lock(struct lirc_buffer *buf,
+				    unsigned long *flags)
+{
+	spin_lock_irqsave(&buf->lock, *flags);
+}
+static inline void lirc_buffer_unlock(struct lirc_buffer *buf,
+				      unsigned long *flags)
+{
+	spin_unlock_irqrestore(&buf->lock, *flags);
+}
+static inline void _lirc_buffer_clear(struct lirc_buffer *buf)
+{
+	buf->head = 0;
+	buf->tail = 0;
+	buf->fill = 0;
+}
+#endif
+static inline void lirc_buffer_clear(struct lirc_buffer *buf)
+{
+#ifdef LIRC_HAVE_KFIFO
+	if (buf->fifo)
+		kfifo_reset(buf->fifo);
+#else
+	unsigned long flags;
+	lirc_buffer_lock(buf, &flags);
+	_lirc_buffer_clear(buf);
+	lirc_buffer_unlock(buf, &flags);
+#endif
+}
+static inline int lirc_buffer_init(struct lirc_buffer *buf,
+				    unsigned int chunk_size,
+				    unsigned int size)
+{
+	init_waitqueue_head(&buf->wait_poll);
+	spin_lock_init(&buf->lock);
+#ifndef LIRC_HAVE_KFIFO
+	_lirc_buffer_clear(buf);
+#endif
+	buf->chunk_size = chunk_size;
+	buf->size = size;
+#ifdef LIRC_HAVE_KFIFO
+	buf->fifo = kfifo_alloc(size*chunk_size, GFP_KERNEL, &buf->lock);
+	if (!buf->fifo)
+		return -ENOMEM;
+#else
+	buf->data = kmalloc(size*chunk_size, GFP_KERNEL);
+	if (buf->data == NULL)
+		return -ENOMEM;
+	memset(buf->data, 0, size*chunk_size);
+#endif
+	return 0;
+}
+static inline void lirc_buffer_free(struct lirc_buffer *buf)
+{
+#ifdef LIRC_HAVE_KFIFO
+	if (buf->fifo)
+		kfifo_free(buf->fifo);
+#else
+	kfree(buf->data);
+	buf->data = NULL;
+	buf->head = 0;
+	buf->tail = 0;
+	buf->fill = 0;
+	buf->chunk_size = 0;
+	buf->size = 0;
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline int  _lirc_buffer_full(struct lirc_buffer *buf)
+{
+	return (buf->fill >= buf->size);
+}
+#endif
+static inline int  lirc_buffer_full(struct lirc_buffer *buf)
+{
+#ifdef LIRC_HAVE_KFIFO
+	return kfifo_len(buf->fifo) == buf->size * buf->chunk_size;
+#else
+	unsigned long flags;
+	int ret;
+	lirc_buffer_lock(buf, &flags);
+	ret = _lirc_buffer_full(buf);
+	lirc_buffer_unlock(buf, &flags);
+	return ret;
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline int  _lirc_buffer_empty(struct lirc_buffer *buf)
+{
+	return !(buf->fill);
+}
+#endif
+static inline int  lirc_buffer_empty(struct lirc_buffer *buf)
+{
+#ifdef LIRC_HAVE_KFIFO
+	return !kfifo_len(buf->fifo);
+#else
+	unsigned long flags;
+	int ret;
+	lirc_buffer_lock(buf, &flags);
+	ret = _lirc_buffer_empty(buf);
+	lirc_buffer_unlock(buf, &flags);
+	return ret;
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline int  _lirc_buffer_available(struct lirc_buffer *buf)
+{
+	return (buf->size - buf->fill);
+}
+#endif
+static inline int  lirc_buffer_available(struct lirc_buffer *buf)
+{
+#ifdef LIRC_HAVE_KFIFO
+	return buf->size - (kfifo_len(buf->fifo) / buf->chunk_size);
+#else
+	unsigned long flags;
+	int ret;
+	lirc_buffer_lock(buf, &flags);
+	ret = _lirc_buffer_available(buf);
+	lirc_buffer_unlock(buf, &flags);
+	return ret;
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline void _lirc_buffer_read_1(struct lirc_buffer *buf,
+				       unsigned char *dest)
+{
+	memcpy(dest, &buf->data[buf->head*buf->chunk_size], buf->chunk_size);
+	buf->head = mod(buf->head+1, buf->size);
+	buf->fill -= 1;
+}
+#endif
+static inline void lirc_buffer_read(struct lirc_buffer *buf,
+				    unsigned char *dest)
+{
+#ifdef LIRC_HAVE_KFIFO
+	if (kfifo_len(buf->fifo) >= buf->chunk_size)
+		kfifo_get(buf->fifo, dest, buf->chunk_size);
+#else
+	unsigned long flags;
+	lirc_buffer_lock(buf, &flags);
+	_lirc_buffer_read_1(buf, dest);
+	lirc_buffer_unlock(buf, &flags);
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline void _lirc_buffer_write_1(struct lirc_buffer *buf,
+				      unsigned char *orig)
+{
+	memcpy(&buf->data[buf->tail*buf->chunk_size], orig, buf->chunk_size);
+	buf->tail = mod(buf->tail+1, buf->size);
+	buf->fill++;
+}
+#endif
+static inline void lirc_buffer_write(struct lirc_buffer *buf,
+				     unsigned char *orig)
+{
+#ifdef LIRC_HAVE_KFIFO
+	kfifo_put(buf->fifo, orig, buf->chunk_size);
+#else
+	unsigned long flags;
+	lirc_buffer_lock(buf, &flags);
+	_lirc_buffer_write_1(buf, orig);
+	lirc_buffer_unlock(buf, &flags);
+#endif
+}
+#ifndef LIRC_HAVE_KFIFO
+static inline void _lirc_buffer_write_n(struct lirc_buffer *buf,
+					unsigned char *orig, int count)
+{
+	int space1;
+	if (buf->head > buf->tail)
+		space1 = buf->head - buf->tail;
+	else
+		space1 = buf->size - buf->tail;
+
+	if (count > space1) {
+		memcpy(&buf->data[buf->tail * buf->chunk_size], orig,
+		       space1 * buf->chunk_size);
+		memcpy(&buf->data[0], orig + (space1 * buf->chunk_size),
+		       (count - space1) * buf->chunk_size);
+	} else {
+		memcpy(&buf->data[buf->tail * buf->chunk_size], orig,
+		       count * buf->chunk_size);
+	}
+	buf->tail = mod(buf->tail + count, buf->size);
+	buf->fill += count;
+}
+#endif
+static inline void lirc_buffer_write_n(struct lirc_buffer *buf,
+				       unsigned char *orig, int count)
+{
+#ifdef LIRC_HAVE_KFIFO
+	kfifo_put(buf->fifo, orig, count * buf->chunk_size);
+#else
+	unsigned long flags;
+	lirc_buffer_lock(buf, &flags);
+	_lirc_buffer_write_n(buf, orig, count);
+	lirc_buffer_unlock(buf, &flags);
+#endif
+}
+
+struct lirc_driver {
+	char name[40];
+	int minor;
+	unsigned long code_length;
+	unsigned int buffer_size; /* in chunks holding one code each */
+	int sample_rate;
+	unsigned long features;
+	void *data;
+	int (*add_to_buf) (void *data, struct lirc_buffer *buf);
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	wait_queue_head_t* (*get_queue) (void *data);
+#endif
+	struct lirc_buffer *rbuf;
+	int (*set_use_inc) (void *data);
+	void (*set_use_dec) (void *data);
+	struct file_operations *fops;
+	struct device *dev;
+	struct module *owner;
+};
+/* name:
+ * this string will be used for logs
+ *
+ * minor:
+ * indicates minor device (/dev/lirc) number for registered driver
+ * if caller fills it with negative value, then the first free minor
+ * number will be used (if available)
+ *
+ * code_length:
+ * length of the remote control key code expressed in bits
+ *
+ * sample_rate:
+ * sample_rate equal to 0 means that no polling will be performed and
+ * add_to_buf will be triggered by external events (through task queue
+ * returned by get_queue)
+ *
+ * data:
+ * it may point to any driver data and this pointer will be passed to
+ * all callback functions
+ *
+ * add_to_buf:
+ * add_to_buf will be called after specified period of the time or
+ * triggered by the external event, this behavior depends on value of
+ * the sample_rate this function will be called in user context. This
+ * routine should return 0 if data was added to the buffer and
+ * -ENODATA if none was available. This should add some number of bits
+ * evenly divisible by code_length to the buffer
+ *
+ * get_queue:
+ * this callback should return a pointer to the task queue which will
+ * be used for external event waiting
+ *
+ * rbuf:
+ * if not NULL, it will be used as a read buffer, you will have to
+ * write to the buffer by other means, like irq's (see also
+ * lirc_serial.c).
+ *
+ * set_use_inc:
+ * set_use_inc will be called after device is opened
+ *
+ * set_use_dec:
+ * set_use_dec will be called after device is closed
+ *
+ * fops:
+ * file_operations for drivers which don't fit the current driver model.
+ *
+ * Some ioctl's can be directly handled by lirc_dev if the driver's
+ * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also
+ * lirc_serial.c).
+ *
+ * owner:
+ * the module owning this struct
+ *
+ */
+
+
+/* following functions can be called ONLY from user context
+ *
+ * returns negative value on error or minor number
+ * of the registered device if success
+ * contents of the structure pointed by d is copied
+ */
+extern int lirc_register_driver(struct lirc_driver *d);
+
+/* returns negative value on error or 0 if success
+*/
+extern int lirc_unregister_driver(int minor);
+
+/* Returns the private data stored in the lirc_driver
+ * associated with the given device file pointer.
+ */
+void *lirc_get_pdata(struct file *file);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_dev/lirc_dev.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_dev/lirc_dev.c
@@ -0,0 +1,1025 @@
+/*
+ * LIRC base driver
+ *
+ * (L) by Artur Lipowski <alipowski@interia.pl>
+ *
+ *  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
+ *
+ * $Id: lirc_dev.c,v 1.96 2009/08/31 16:57:55 lirc Exp $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
+#endif
+
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#else
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#include <linux/wrapper.h>
+#endif
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+#include <linux/kthread.h>
+#endif
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
+#include "../kcompat.h"
+
+/* SysFS header */
+#if defined(LIRC_HAVE_SYSFS)
+#include <linux/device.h>
+#endif
+
+#include "../lirc.h"
+#include "lirc_dev.h"
+
+static int debug;
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG fmt, ## args);	\
+	} while (0)
+
+#define IRCTL_DEV_NAME    "BaseRemoteCtl"
+#define NOPLUG            -1
+#define LOGHEAD           "lirc_dev (%s[%d]): "
+
+struct irctl {
+	struct lirc_driver d;
+	int attached;
+	int open;
+
+	struct mutex buffer_lock;
+	struct lirc_buffer *buf;
+	unsigned int chunk_size;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	int tpid;
+	struct completion *t_notify;
+	struct completion *t_notify2;
+	int shutdown;
+#else
+	struct task_struct *task;
+#endif
+	long jiffies_to_wait;
+
+#ifdef LIRC_HAVE_DEVFS_24
+	devfs_handle_t devfs_handle;
+#endif
+};
+
+static DEFINE_MUTEX(lirc_dev_lock);
+
+static struct irctl *irctls[MAX_IRCTL_DEVICES];
+static struct file_operations fops;
+
+/* Only used for sysfs but defined to void otherwise */
+static lirc_class_t *lirc_class;
+
+/*  helper function
+ *  initializes the irctl structure
+ */
+static void init_irctl(struct irctl *ir)
+{
+	mutex_init(&ir->buffer_lock);
+	ir->d.minor = NOPLUG;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	ir->tpid = -1;
+#endif
+}
+
+static void cleanup(struct irctl *ir)
+{
+	dprintk(LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
+
+	if (ir->buf != ir->d.rbuf) {
+		lirc_buffer_free(ir->buf);
+		kfree(ir->buf);
+	}
+	ir->buf = NULL;
+}
+
+/*  helper function
+ *  reads key codes from driver and puts them into buffer
+ *  returns 0 on success
+ */
+static int add_to_buf(struct irctl *ir)
+{
+	if (ir->d.add_to_buf) {
+		int res = -ENODATA;
+		int got_data = 0;
+
+		/*
+		 * service the device as long as it is returning
+		 * data and we have space
+		 */
+		while ((res = ir->d.add_to_buf(ir->d.data, ir->buf)) == 0) {
+			got_data++;
+		}
+
+		if (res == -ENODEV)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+			ir->shutdown = 1;
+#else
+			kthread_stop(ir->task);
+#endif
+
+		return got_data ? 0 : res;
+	}
+
+	return 0;
+}
+
+/* main function of the polling thread */
+static int lirc_thread(void *irctl)
+{
+	struct irctl *ir = irctl;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	/*
+	 * This thread doesn't need any user-level access, so get rid
+	 * of all our resources
+	 */
+	daemonize("lirc_dev");
+
+	if (ir->t_notify != NULL)
+		complete(ir->t_notify);
+	
+#endif
+	dprintk(LOGHEAD "poll thread started\n", ir->d.name, ir->d.minor);
+
+	do {
+		if (ir->open) {
+			if (ir->jiffies_to_wait) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(ir->jiffies_to_wait);
+#ifndef LIRC_REMOVE_DURING_EXPORT
+			} else {
+				interruptible_sleep_on(
+					ir->d.get_queue(ir->d.data));
+#endif
+			}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+			if (ir->shutdown)
+#else
+			if (kthread_should_stop())
+#endif
+				break;
+			if (!add_to_buf(ir))
+				wake_up_interruptible(&ir->buf->wait_poll);
+		} else {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule();
+		}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	} while (!ir->shutdown);
+
+	if (ir->t_notify2 != NULL)
+		wait_for_completion(ir->t_notify2);
+
+	ir->tpid = -1;
+	if (ir->t_notify != NULL)
+		complete(ir->t_notify);
+#else
+	} while (!kthread_should_stop());
+#endif
+
+	dprintk(LOGHEAD "poll thread ended\n", ir->d.name, ir->d.minor);
+
+	return 0;
+}
+
+int lirc_register_driver(struct lirc_driver *d)
+{
+	struct irctl *ir;
+	int minor;
+	int bytes_in_key;
+	unsigned int buffer_size;
+	int err;
+#ifdef LIRC_HAVE_DEVFS_24
+	char name[16];
+#endif
+	DECLARE_COMPLETION(tn);
+
+	if (!d) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "driver pointer must be not NULL!\n");
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (MAX_IRCTL_DEVICES <= d->minor) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "\"minor\" must be between 0 and %d (%d)!\n",
+		       MAX_IRCTL_DEVICES-1, d->minor);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "code length in bits for minor (%d) "
+		       "must be less than %d!\n",
+		       d->minor, BUFLEN * 8);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	printk(KERN_INFO "lirc_dev: lirc_register_driver: sample_rate: %d\n",
+		d->sample_rate);
+	if (d->sample_rate) {
+		if (2 > d->sample_rate || HZ < d->sample_rate) {
+			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+			       "sample_rate must be between 2 and %d!\n", HZ);
+			err = -EBADRQC;
+			goto out;
+		}
+		if (!d->add_to_buf) {
+			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+			       "add_to_buf cannot be NULL when "
+			       "sample_rate is set\n");
+			err = -EBADRQC;
+			goto out;
+		}
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	} else if (!(d->fops && d->fops->read) && !d->get_queue && !d->rbuf) {
+#else
+	} else if (!(d->fops && d->fops->read) && !d->rbuf) {
+#endif
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+#ifndef LIRC_REMOVE_DURING_EXPORT
+		       "fops->read, get_queue and rbuf "
+#else
+		       "fops->read and rbuf "
+#endif
+		       "cannot all be NULL!\n");
+		err = -EBADRQC;
+		goto out;
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	} else if (!d->get_queue && !d->rbuf) {
+#else
+	} else if (!d->rbuf) {
+#endif
+		if (!(d->fops && d->fops->read && d->fops->poll &&
+		      d->fops->ioctl)) {
+			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+			       "neither read, poll nor ioctl can be NULL!\n");
+			err = -EBADRQC;
+			goto out;
+		}
+	}
+
+	mutex_lock(&lirc_dev_lock);
+
+	minor = d->minor;
+
+	if (minor < 0) {
+		/* find first free slot for driver */
+		for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
+			if (!irctls[minor])
+				break;
+		if (MAX_IRCTL_DEVICES == minor) {
+			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+			       "no free slots for drivers!\n");
+			err = -ENOMEM;
+			goto out_lock;
+		}
+	} else if (irctls[minor]) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "minor (%d) just registered!\n", minor);
+		err = -EBUSY;
+		goto out_lock;
+	}
+
+	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
+	if (!ir) {
+		err = -ENOMEM;
+		goto out_lock;
+	}
+	init_irctl(ir);
+	irctls[minor] = ir;
+
+	if (d->sample_rate) {
+		ir->jiffies_to_wait = HZ / d->sample_rate;
+	} else {
+		/* it means - wait for external event in task queue */
+		ir->jiffies_to_wait = 0;
+	}
+
+	/* some safety check 8-) */
+	d->name[sizeof(d->name)-1] = '\0';
+
+	bytes_in_key = d->code_length/8 + (d->code_length%8 ? 1 : 0);
+	buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
+
+	if (d->rbuf) {
+		ir->buf = d->rbuf;
+	} else {
+		ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+		if (!ir->buf) {
+			err = -ENOMEM;
+			goto out_lock;
+		}
+		err = lirc_buffer_init(ir->buf, bytes_in_key, buffer_size);
+		if (err) {
+			kfree(ir->buf);
+			goto out_lock;
+		}
+	}
+	ir->chunk_size = ir->buf->chunk_size;
+
+	if (d->features == 0)
+		d->features = (d->code_length > 8) ?
+			LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_CODE;
+
+	ir->d = *d;
+	ir->d.minor = minor;
+
+#if defined(LIRC_HAVE_DEVFS_24)
+	sprintf(name, DEV_LIRC "/%d", ir->d.minor);
+	ir->devfs_handle = devfs_register(NULL, name, DEVFS_FL_DEFAULT,
+					  IRCTL_DEV_MAJOR, ir->d.minor,
+					  S_IFCHR | S_IRUSR | S_IWUSR,
+					  &fops, NULL);
+#elif defined(LIRC_HAVE_DEVFS_26)
+	devfs_mk_cdev(MKDEV(IRCTL_DEV_MAJOR, ir->d.minor),
+			S_IFCHR|S_IRUSR|S_IWUSR,
+			DEV_LIRC "/%u", ir->d.minor);
+#endif
+	(void) lirc_device_create(lirc_class, ir->d.dev,
+				  MKDEV(IRCTL_DEV_MAJOR, ir->d.minor), NULL,
+				  "lirc%u", ir->d.minor);
+
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	if (d->sample_rate || d->get_queue) {
+#else
+	if (d->sample_rate) {
+#endif
+		/* try to fire up polling thread */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+		ir->t_notify = &tn;
+		ir->tpid = kernel_thread(lirc_thread, (void *)ir, 0);
+		if (ir->tpid < 0) {
+#else
+		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
+		if (IS_ERR(ir->task)) {
+#endif
+			printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+			       "cannot run poll thread for minor = %d\n",
+			       d->minor);
+			err = -ECHILD;
+			goto out_sysfs;
+		}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+		wait_for_completion(&tn);
+		ir->t_notify = NULL;
+#endif
+	}
+	ir->attached = 1;
+	mutex_unlock(&lirc_dev_lock);
+
+/*
+ * Recent kernels should handle this autmatically by increasing/decreasing
+ * use count when a dependant module is loaded/unloaded.
+ */
+#ifndef KERNEL_2_5
+	MOD_INC_USE_COUNT;
+#endif
+	dprintk("lirc_dev: driver %s registered at minor number = %d\n",
+		ir->d.name, ir->d.minor);
+	d->minor = minor;
+	return minor;
+
+out_sysfs:
+	lirc_device_destroy(lirc_class,
+			    MKDEV(IRCTL_DEV_MAJOR, ir->d.minor));
+#ifdef LIRC_HAVE_DEVFS_24
+	devfs_unregister(ir->devfs_handle);
+#endif
+#ifdef LIRC_HAVE_DEVFS_26
+	devfs_remove(DEV_LIRC "/%i", ir->d.minor);
+#endif
+out_lock:
+	mutex_unlock(&lirc_dev_lock);
+out:
+	return err;
+}
+EXPORT_SYMBOL(lirc_register_driver);
+
+int lirc_unregister_driver(int minor)
+{
+	struct irctl *ir;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	DECLARE_COMPLETION(tn);
+	DECLARE_COMPLETION(tn2);
+#endif
+
+	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
+		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
+		       "\"minor\" must be between 0 and %d!\n",
+		       MAX_IRCTL_DEVICES-1);
+		return -EBADRQC;
+	}
+
+	ir = irctls[minor];
+
+	mutex_lock(&lirc_dev_lock);
+
+	if (ir->d.minor != minor) {
+		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
+		       "minor (%d) device not registered!", minor);
+		mutex_unlock(&lirc_dev_lock);
+		return -ENOENT;
+	}
+
+	/* end up polling thread */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	if (ir->tpid >= 0) {
+		ir->t_notify = &tn;
+		ir->t_notify2 = &tn2;
+		ir->shutdown = 1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+		{
+			struct task_struct *p;
+
+			p = find_task_by_pid(ir->tpid);
+			wake_up_process(p);
+		}
+#else
+		/* 2.2.x does not export wake_up_process() */
+		wake_up_interruptible(ir->d.get_queue(ir->d.data));
+#endif
+		complete(&tn2);
+		wait_for_completion(&tn);
+		ir->t_notify = NULL;
+		ir->t_notify2 = NULL;
+	}
+#else /* kernel >= 2.6.23 */
+	if (ir->task)
+		kthread_stop(ir->task);
+#endif
+
+	dprintk("lirc_dev: driver %s unregistered from minor number = %d\n",
+		ir->d.name, ir->d.minor);
+
+	ir->attached = 0;
+	if (ir->open) {
+		dprintk(LOGHEAD "releasing opened driver\n",
+			ir->d.name, ir->d.minor);
+		wake_up_interruptible(&ir->buf->wait_poll);
+		mutex_lock(&ir->buffer_lock);
+		ir->d.set_use_dec(ir->d.data);
+		module_put(ir->d.owner);
+		mutex_unlock(&ir->buffer_lock);
+	} else {
+		cleanup(ir);
+		irctls[minor] = NULL;
+		kfree(ir);
+	}
+
+#ifdef LIRC_HAVE_DEVFS_24
+	devfs_unregister(ir->devfs_handle);
+#endif
+#ifdef LIRC_HAVE_DEVFS_26
+	devfs_remove(DEV_LIRC "/%u", ir->d.minor);
+#endif
+	lirc_device_destroy(lirc_class,
+			    MKDEV(IRCTL_DEV_MAJOR, ir->d.minor));
+
+	mutex_unlock(&lirc_dev_lock);
+
+/*
+ * Recent kernels should handle this autmatically by increasing/decreasing
+ * use count when a dependant module is loaded/unloaded.
+ */
+#ifndef KERNEL_2_5
+	MOD_DEC_USE_COUNT;
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(lirc_unregister_driver);
+
+static int irctl_open(struct inode *inode, struct file *file)
+{
+	struct irctl *ir;
+	int retval;
+
+	if (iminor(inode) >= MAX_IRCTL_DEVICES || !irctls[iminor(inode)]) {
+		dprintk("lirc_dev [%d]: open result = -ENODEV\n",
+			iminor(inode));
+		return -ENODEV;
+	}
+
+	ir = irctls[iminor(inode)];
+
+	dprintk(LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+
+	/* if the driver has an open function use it instead */
+	if (ir->d.fops && ir->d.fops->open)
+		return ir->d.fops->open(inode, file);
+
+	if (mutex_lock_interruptible(&lirc_dev_lock))
+		return -ERESTARTSYS;
+
+	if (ir->d.minor == NOPLUG) {
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (ir->open) {
+		retval = -EBUSY;
+		goto error;
+	}
+
+	if (try_module_get(ir->d.owner)) {
+		++ir->open;
+		retval = ir->d.set_use_inc(ir->d.data);
+
+		if (retval) {
+			module_put(ir->d.owner);
+			--ir->open;
+		} else {
+			lirc_buffer_clear(ir->buf);
+		}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+		if (ir->tpid >= 0) {
+			struct task_struct *p;
+
+			p = find_task_by_pid(ir->tpid);
+			wake_up_process(p);
+		}
+#else
+		if (ir->task)
+			wake_up_process(ir->task);
+#endif
+	}
+ error:
+	if (ir)
+		dprintk(LOGHEAD "open result = %d\n", ir->d.name, ir->d.minor,
+			retval);
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return retval;
+}
+
+static int irctl_close(struct inode *inode, struct file *file)
+{
+	struct irctl *ir = irctls[iminor(inode)];
+
+	dprintk(LOGHEAD "close called\n", ir->d.name, ir->d.minor);
+
+	/* if the driver has a close function use it instead */
+	if (ir->d.fops && ir->d.fops->release)
+		return ir->d.fops->release(inode, file);
+
+	if (mutex_lock_interruptible(&lirc_dev_lock))
+		return -ERESTARTSYS;
+
+	--ir->open;
+	if (ir->attached) {
+		ir->d.set_use_dec(ir->d.data);
+		module_put(ir->d.owner);
+	} else {
+		cleanup(ir);
+		irctls[ir->d.minor] = NULL;
+		kfree(ir);
+	}
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return 0;
+}
+
+static unsigned int irctl_poll(struct file *file, poll_table *wait)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned int ret;
+
+	dprintk(LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
+
+	/* if the driver has a poll function use it instead */
+	if (ir->d.fops && ir->d.fops->poll)
+		return ir->d.fops->poll(file, wait);
+
+	mutex_lock(&ir->buffer_lock);
+	if (!ir->attached) {
+		mutex_unlock(&ir->buffer_lock);
+		return POLLERR;
+	}
+
+	poll_wait(file, &ir->buf->wait_poll, wait);
+
+	dprintk(LOGHEAD "poll result = %s\n",
+		ir->d.name, ir->d.minor,
+		lirc_buffer_empty(ir->buf) ? "0" : "POLLIN|POLLRDNORM");
+
+	ret = lirc_buffer_empty(ir->buf) ? 0 : (POLLIN|POLLRDNORM);
+
+	mutex_unlock(&ir->buffer_lock);
+	return ret;
+}
+
+/*
+ *
+ */
+static int irctl_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	unsigned long mode;
+	int result;
+	struct irctl *ir = irctls[iminor(inode)];
+
+	dprintk(LOGHEAD "ioctl called (0x%x)\n",
+		ir->d.name, ir->d.minor, cmd);
+
+	/* if the driver has a ioctl function use it instead */
+	if (ir->d.fops && ir->d.fops->ioctl) {
+		result = ir->d.fops->ioctl(inode, file, cmd, arg);
+		if (result != -ENOIOCTLCMD)
+			return result;
+	}
+
+	if (ir->d.minor == NOPLUG || !ir->attached) {
+		dprintk(LOGHEAD "ioctl result = -ENODEV\n",
+			ir->d.name, ir->d.minor);
+		return -ENODEV;
+	}
+
+	/* The driver can't handle cmd */
+	result = 0;
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+		result = put_user(ir->d.features, (unsigned long *)arg);
+		break;
+	case LIRC_GET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK))
+			return -ENOSYS;
+
+		result = put_user(LIRC_REC2MODE
+				  (ir->d.features & LIRC_CAN_REC_MASK),
+				  (unsigned long *)arg);
+		break;
+	case LIRC_SET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK))
+			return -ENOSYS;
+
+		result = get_user(mode, (unsigned long *)arg);
+		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
+			result = -EINVAL;
+		/*
+		 * FIXME: We should actually set the mode somehow but
+		 * for now, lirc_serial doesn't support mode changing either
+		 */
+		break;
+	case LIRC_GET_LENGTH:
+		result = put_user(ir->d.code_length, (unsigned long *) arg);
+		break;
+	default:
+		result = -EINVAL;
+	}
+
+	dprintk(LOGHEAD "ioctl result = %d\n",
+		ir->d.name, ir->d.minor, result);
+
+	return result;
+}
+
+#ifdef CONFIG_COMPAT
+#define LIRC_GET_FEATURES_COMPAT32     _IOR('i', 0x00000000, __u32)
+
+#define LIRC_GET_SEND_MODE_COMPAT32    _IOR('i', 0x00000001, __u32)
+#define LIRC_GET_REC_MODE_COMPAT32     _IOR('i', 0x00000002, __u32)
+
+#define LIRC_GET_LENGTH_COMPAT32       _IOR('i', 0x0000000f, __u32)
+
+#define LIRC_SET_SEND_MODE_COMPAT32    _IOW('i', 0x00000011, __u32)
+#define LIRC_SET_REC_MODE_COMPAT32     _IOW('i', 0x00000012, __u32)
+
+static long irctl_compat_ioctl(struct file *file,
+			       unsigned int cmd32,
+			       unsigned long arg)
+{
+	mm_segment_t old_fs;
+	int ret;
+	unsigned long val;
+	unsigned int cmd;
+
+	switch (cmd32) {
+	case LIRC_GET_FEATURES_COMPAT32:
+	case LIRC_GET_SEND_MODE_COMPAT32:
+	case LIRC_GET_REC_MODE_COMPAT32:
+	case LIRC_GET_LENGTH_COMPAT32:
+	case LIRC_SET_SEND_MODE_COMPAT32:
+	case LIRC_SET_REC_MODE_COMPAT32:
+		/*
+		 * These commands expect (unsigned long *) arg
+		 * but the 32-bit app supplied (__u32 *).
+		 * Conversion is required.
+		 */
+		if (get_user(val, (__u32 *)compat_ptr(arg)))
+			return -EFAULT;
+		lock_kernel();
+		/*
+		 * tell irctl_ioctl that it's safe to use the pointer
+		 * to val which is in kernel address space and not in
+		 * user address space
+		 */
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		cmd = _IOC(_IOC_DIR(cmd32), _IOC_TYPE(cmd32), _IOC_NR(cmd32),
+			   (_IOC_TYPECHECK(unsigned long)));
+		ret = irctl_ioctl(file->f_dentry->d_inode, file,
+				  cmd, (unsigned long)(&val));
+
+		set_fs(old_fs);
+		unlock_kernel();
+		switch (cmd) {
+		case LIRC_GET_FEATURES:
+		case LIRC_GET_SEND_MODE:
+		case LIRC_GET_REC_MODE:
+		case LIRC_GET_LENGTH:
+			if (!ret && put_user(val, (__u32 *)compat_ptr(arg)))
+				return -EFAULT;
+			break;
+		}
+		return ret;
+
+	case LIRC_GET_SEND_CARRIER:
+	case LIRC_GET_REC_CARRIER:
+	case LIRC_GET_SEND_DUTY_CYCLE:
+	case LIRC_GET_REC_DUTY_CYCLE:
+	case LIRC_GET_REC_RESOLUTION:
+	case LIRC_SET_SEND_CARRIER:
+	case LIRC_SET_REC_CARRIER:
+	case LIRC_SET_SEND_DUTY_CYCLE:
+	case LIRC_SET_REC_DUTY_CYCLE:
+	case LIRC_SET_TRANSMITTER_MASK:
+	case LIRC_SET_REC_DUTY_CYCLE_RANGE:
+	case LIRC_SET_REC_CARRIER_RANGE:
+		/*
+		 * These commands expect (unsigned int *)arg
+		 * so no problems here. Just handle the locking.
+		 */
+		lock_kernel();
+		cmd = cmd32;
+		ret = irctl_ioctl(file->f_dentry->d_inode,
+				  file, cmd, arg);
+		unlock_kernel();
+		return ret;
+	default:
+		/* unknown */
+		printk(KERN_ERR "lirc_dev: %s(%s:%d): Unknown cmd %08x\n",
+		       __func__, current->comm, current->pid, cmd32);
+		return -ENOIOCTLCMD;
+	}
+}
+#endif
+
+static ssize_t irctl_read(struct file *file,
+			  char *buffer,
+			  size_t length,
+			  loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned char buf[ir->chunk_size];
+	int ret = 0, written = 0;
+	int unlock = 1;
+	DECLARE_WAITQUEUE(wait, current);
+
+	dprintk(LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+
+	/* if the driver has a specific read function use it instead */
+	if (ir->d.fops && ir->d.fops->read)
+		return ir->d.fops->read(file, buffer, length, ppos);
+
+	if (mutex_lock_interruptible(&ir->buffer_lock))
+		return -ERESTARTSYS;
+	if (!ir->attached) {
+		mutex_unlock(&ir->buffer_lock);
+		return -ENODEV;
+	}
+
+	if (length % ir->buf->chunk_size) {
+		dprintk(LOGHEAD "read result = -EINVAL\n",
+			ir->d.name, ir->d.minor);
+		mutex_unlock(&ir->buffer_lock);
+		return -EINVAL;
+	}
+
+	/*
+	 * we add ourselves to the task queue before buffer check
+	 * to avoid losing scan code (in case when queue is awaken somewhere
+	 * between while condition checking and scheduling)
+	 */
+	add_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	/*
+	 * while we didn't provide 'length' bytes, device is opened in blocking
+	 * mode and 'copy_to_user' is happy, wait for data.
+	 */
+	while (written < length && ret == 0) {
+		if (lirc_buffer_empty(ir->buf)) {
+			/* According to the read(2) man page, 'written' can be
+			 * returned as less than 'length', instead of blocking
+			 * again, returning -EWOULDBLOCK, or returning
+			 * -ERESTARTSYS */
+			if (written)
+				break;
+			if (file->f_flags & O_NONBLOCK) {
+				ret = -EWOULDBLOCK;
+				break;
+			}
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			mutex_unlock(&ir->buffer_lock);
+			schedule();
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (mutex_lock_interruptible(&ir->buffer_lock)) {
+				unlock = 0;
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			if (!ir->attached) {
+				ret = -ENODEV;
+				break;
+			}
+		} else {
+			lirc_buffer_read(ir->buf, buf);
+			ret = copy_to_user((void *)buffer+written, buf,
+					   ir->buf->chunk_size);
+			written += ir->buf->chunk_size;
+		}
+	}
+
+	remove_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_RUNNING);
+	if(unlock) mutex_unlock(&ir->buffer_lock);
+
+	dprintk(LOGHEAD "read result = %s (%d)\n",
+		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+
+	return ret ? ret : written;
+}
+
+
+void *lirc_get_pdata(struct file *file)
+{
+	void *data = NULL;
+
+	if (file && file->f_dentry && file->f_dentry->d_inode &&
+	    file->f_dentry->d_inode->i_rdev) {
+		struct irctl *ir;
+		ir = irctls[iminor(file->f_dentry->d_inode)];
+		data = ir->d.data;
+	}
+
+	return data;
+}
+EXPORT_SYMBOL(lirc_get_pdata);
+
+
+static ssize_t irctl_write(struct file *file, const char *buffer,
+			   size_t length, loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+	dprintk(LOGHEAD "write called\n", ir->d.name, ir->d.minor);
+
+	/* if the driver has a specific read function use it instead */
+	if (ir->d.fops && ir->d.fops->write)
+		return ir->d.fops->write(file, buffer, length, ppos);
+
+	if (!ir->attached)
+		return -ENODEV;
+
+	return -EINVAL;
+}
+
+
+static struct file_operations fops = {
+	.owner		= THIS_MODULE,
+	.read		= irctl_read,
+	.write		= irctl_write,
+	.poll		= irctl_poll,
+	.ioctl		= irctl_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= irctl_compat_ioctl,
+#endif
+	.open		= irctl_open,
+	.release	= irctl_close
+};
+
+/* For now don't try to use it as a static version !  */
+#ifdef MODULE
+
+static int __init lirc_dev_init(void)
+{
+	if (register_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME, &fops)) {
+		printk(KERN_ERR "lirc_dev: register_chrdev failed\n");
+		goto out;
+	}
+
+	lirc_class = class_create(THIS_MODULE, "lirc");
+	if (IS_ERR(lirc_class)) {
+		printk(KERN_ERR "lirc_dev: class_create failed\n");
+		goto out_unregister;
+	}
+
+	printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
+	       "major %d \n", IRCTL_DEV_MAJOR);
+
+	return 0;
+
+out_unregister:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	if (unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME))
+		printk(KERN_ERR "lirc_dev: unregister_chrdev failed!\n");
+#else
+	/* unregister_chrdev returns void now */
+	unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME);
+#endif
+out:
+	return -1;
+}
+
+static void __exit lirc_dev_exit(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+	int ret;
+
+	ret = unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME);
+	class_destroy(lirc_class);
+
+	if (ret)
+		printk(KERN_ERR "lirc_dev: error in "
+		       "module_unregister_chrdev: %d\n", ret);
+	else
+		dprintk("lirc_dev: module successfully unloaded\n");
+#else
+	/* unregister_chrdev returns void now */
+	unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME);
+	class_destroy(lirc_class);
+	dprintk("lirc_dev: module unloaded\n");
+#endif
+}
+
+module_init(lirc_dev_init);
+module_exit(lirc_dev_exit);
+
+MODULE_DESCRIPTION("LIRC base driver module");
+MODULE_AUTHOR("Artur Lipowski");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(IRCTL_DEV_MAJOR);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_parallel/lirc_parallel.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_parallel/lirc_parallel.c
@@ -0,0 +1,764 @@
+/*      $Id: lirc_parallel.c,v 5.53 2009/03/08 19:22:28 lirc Exp $      */
+/*
+ * lirc_parallel.c
+ *
+ * lirc_parallel - device driver for infra-red signal receiving and
+ *                 transmitting unit built by the author
+ *
+ * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
+ *
+ *  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
+ *
+ */
+
+/*** Includes ***/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
+#endif
+
+#include <linux/autoconf.h>
+#ifdef CONFIG_SMP
+#error "--- Sorry, this driver is not SMP safe. ---"
+#endif
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/autoconf.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/io.h>
+#include <asm/signal.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#else
+#include <linux/io.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#include <asm/div64.h>
+#endif
+
+#include <linux/poll.h>
+#include <linux/parport.h>
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#include "lirc_parallel.h"
+
+#define LIRC_DRIVER_NAME "lirc_parallel"
+
+#ifndef LIRC_IRQ
+#define LIRC_IRQ 7
+#endif
+#ifndef LIRC_PORT
+#define LIRC_PORT 0x378
+#endif
+#ifndef LIRC_TIMER
+#define LIRC_TIMER 65536
+#endif
+
+/*** Global Variables ***/
+
+static int debug;
+static int check_pselecd;
+
+unsigned int irq = LIRC_IRQ;
+unsigned int io = LIRC_PORT;
+#ifdef LIRC_TIMER
+unsigned int timer;
+unsigned int default_timer = LIRC_TIMER;
+#endif
+
+#define WBUF_SIZE (256)
+#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
+
+static lirc_t wbuf[WBUF_SIZE];
+static lirc_t rbuf[RBUF_SIZE];
+
+DECLARE_WAIT_QUEUE_HEAD(lirc_wait);
+
+unsigned int rptr;
+unsigned int wptr;
+unsigned int lost_irqs;
+int is_open;
+
+struct parport *pport;
+struct pardevice *ppdevice;
+int is_claimed;
+
+unsigned int tx_mask = 1;
+
+/*** Internal Functions ***/
+
+static unsigned int in(int offset)
+{
+	switch (offset) {
+	case LIRC_LP_BASE:
+		return parport_read_data(pport);
+	case LIRC_LP_STATUS:
+		return parport_read_status(pport);
+	case LIRC_LP_CONTROL:
+		return parport_read_control(pport);
+	}
+	return 0; /* make compiler happy */
+}
+
+static void out(int offset, int value)
+{
+	switch (offset) {
+	case LIRC_LP_BASE:
+		parport_write_data(pport, value);
+		break;
+	case LIRC_LP_CONTROL:
+		parport_write_control(pport, value);
+		break;
+	case LIRC_LP_STATUS:
+		printk(KERN_INFO "%s: attempt to write to status register\n",
+		       LIRC_DRIVER_NAME);
+		break;
+	}
+}
+
+static unsigned int lirc_get_timer(void)
+{
+	return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT;
+}
+
+static unsigned int lirc_get_signal(void)
+{
+	return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT;
+}
+
+static void lirc_on(void)
+{
+	out(LIRC_PORT_DATA, tx_mask);
+}
+
+static void lirc_off(void)
+{
+	out(LIRC_PORT_DATA, 0);
+}
+
+static unsigned int init_lirc_timer(void)
+{
+	struct timeval tv, now;
+	unsigned int level, newlevel, timeelapsed, newtimer;
+	int count = 0;
+
+	do_gettimeofday(&tv);
+	tv.tv_sec++;                     /* wait max. 1 sec. */
+	level = lirc_get_timer();
+	do {
+		newlevel = lirc_get_timer();
+		if (level == 0 && newlevel != 0)
+			count++;
+		level = newlevel;
+		do_gettimeofday(&now);
+	} while (count < 1000 && (now.tv_sec < tv.tv_sec
+			     || (now.tv_sec == tv.tv_sec
+				 && now.tv_usec < tv.tv_usec)));
+
+	timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
+		     + (now.tv_usec - tv.tv_usec));
+	if (count >= 1000 && timeelapsed > 0) {
+		if (default_timer == 0) {
+			/* autodetect timer */
+			newtimer = (1000000*count)/timeelapsed;
+			printk(KERN_INFO "%s: %u Hz timer detected\n",
+			       LIRC_DRIVER_NAME, newtimer);
+			return newtimer;
+		}  else {
+			newtimer = (1000000*count)/timeelapsed;
+			if (abs(newtimer - default_timer) > default_timer/10) {
+				/* bad timer */
+				printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
+				       LIRC_DRIVER_NAME, newtimer);
+				printk(KERN_NOTICE "%s: using default timer: "
+				       "%u Hz\n",
+				       LIRC_DRIVER_NAME, default_timer);
+				return default_timer;
+			} else {
+				printk(KERN_INFO "%s: %u Hz timer detected\n",
+				       LIRC_DRIVER_NAME, newtimer);
+				return newtimer; /* use detected value */
+			}
+		}
+	} else {
+		printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
+		return 0;
+	}
+}
+
+static int lirc_claim(void)
+{
+	if (parport_claim(ppdevice) != 0) {
+		printk(KERN_WARNING "%s: could not claim port\n",
+		       LIRC_DRIVER_NAME);
+		printk(KERN_WARNING "%s: waiting for port becoming available"
+		       "\n", LIRC_DRIVER_NAME);
+		if (parport_claim_or_block(ppdevice) < 0) {
+			printk(KERN_NOTICE "%s: could not claim port, giving"
+			       " up\n", LIRC_DRIVER_NAME);
+			return 0;
+		}
+	}
+	out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
+	is_claimed = 1;
+	return 1;
+}
+
+/*** interrupt handler ***/
+
+static void rbuf_write(lirc_t signal)
+{
+	unsigned int nwptr;
+
+	nwptr = (wptr + 1) & (RBUF_SIZE - 1);
+	if (nwptr == rptr) {
+		/* no new signals will be accepted */
+		lost_irqs++;
+		printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME);
+		return;
+	}
+	rbuf[wptr] = signal;
+	wptr = nwptr;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void irq_handler(int i, void *blah, struct pt_regs *regs)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static void irq_handler(int i, void *blah)
+#else
+static void irq_handler(void *blah)
+#endif
+{
+	struct timeval tv;
+	static struct timeval lasttv;
+	static int init;
+	long signal;
+	lirc_t data;
+	unsigned int level, newlevel;
+	unsigned int timeout;
+
+	if (!MOD_IN_USE)
+		return;
+
+	if (!is_claimed)
+		return;
+
+#if 0
+	/* disable interrupt */
+	disable_irq(irq);
+	out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN));
+#endif
+	if (check_pselecd && (in(1) & LP_PSELECD))
+		return;
+
+#ifdef LIRC_TIMER
+	if (init) {
+		do_gettimeofday(&tv);
+
+		signal = tv.tv_sec - lasttv.tv_sec;
+		if (signal > 15)
+			/* really long time */
+			data = PULSE_MASK;
+		else
+			data = (lirc_t) (signal*1000000 +
+					 tv.tv_usec - lasttv.tv_usec +
+					 LIRC_SFH506_DELAY);
+
+		rbuf_write(data); /* space */
+	} else {
+		if (timer == 0) {
+			/*
+			 * wake up; we'll lose this signal, but it will be
+			 * garbage if the device is turned on anyway
+			 */
+			timer = init_lirc_timer();
+			/* enable_irq(irq); */
+			return;
+		}
+		init = 1;
+	}
+
+	timeout = timer/10;	/* timeout after 1/10 sec. */
+	signal = 1;
+	level = lirc_get_timer();
+	do {
+		newlevel = lirc_get_timer();
+		if (level == 0 && newlevel != 0)
+			signal++;
+		level = newlevel;
+
+		/* giving up */
+		if (signal > timeout
+		    || (check_pselecd && (in(1) & LP_PSELECD))) {
+			signal = 0;
+			printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME);
+			break;
+		}
+	} while (lirc_get_signal());
+
+	if (signal != 0) {
+		/* adjust value to usecs */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+		unsigned long long helper;
+
+		helper = ((unsigned long long) signal)*1000000;
+		do_div(helper, timer);
+		signal = (long) helper;
+#else
+		signal = (long) ((((double) signal)*1000000)/timer);
+#endif
+
+		if (signal > LIRC_SFH506_DELAY)
+			data = signal - LIRC_SFH506_DELAY;
+		else
+			data = 1;
+		rbuf_write(PULSE_BIT|data); /* pulse */
+	}
+	do_gettimeofday(&lasttv);
+#else
+	/* add your code here */
+#endif
+
+	wake_up_interruptible(&lirc_wait);
+
+	/* enable interrupt */
+	/*
+	  enable_irq(irq);
+	  out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN);
+	*/
+}
+
+/*** file operations ***/
+
+static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig)
+{
+	return -ESPIPE;
+}
+
+static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos)
+{
+	int result = 0;
+	int count = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (n % sizeof(lirc_t))
+		return -EINVAL;
+
+	add_wait_queue(&lirc_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (count < n) {
+		if (rptr != wptr) {
+			if (copy_to_user(buf+count, (char *) &rbuf[rptr],
+					 sizeof(lirc_t))) {
+				result = -EFAULT;
+				break;
+			}
+			rptr = (rptr + 1) & (RBUF_SIZE - 1);
+			count += sizeof(lirc_t);
+		} else {
+			if (filep->f_flags & O_NONBLOCK) {
+				result = -EAGAIN;
+				break;
+			}
+			if (signal_pending(current)) {
+				result = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+			set_current_state(TASK_INTERRUPTIBLE);
+		}
+	}
+	remove_wait_queue(&lirc_wait, &wait);
+	set_current_state(TASK_RUNNING);
+	return count ? count : result;
+}
+
+static ssize_t lirc_write(struct file *filep, const char *buf, size_t n,
+			  loff_t *ppos)
+{
+	int count;
+	unsigned int i;
+	unsigned int level, newlevel;
+	unsigned long flags;
+	lirc_t counttimer;
+
+	if (!is_claimed)
+		return -EBUSY;
+
+	if (n % sizeof(lirc_t))
+		return -EINVAL;
+
+	count = n / sizeof(lirc_t);
+
+	if (count > WBUF_SIZE || count % 2 == 0)
+		return -EINVAL;
+
+	if (copy_from_user(wbuf, buf, n))
+		return -EFAULT;
+
+#ifdef LIRC_TIMER
+	if (timer == 0) {
+		/* try again if device is ready */
+		timer = init_lirc_timer();
+		if (timer == 0)
+			return -EIO;
+	}
+
+	/* adjust values from usecs */
+	for (i = 0; i < count; i++) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+		unsigned long long helper;
+
+		helper = ((unsigned long long) wbuf[i])*timer;
+		do_div(helper, 1000000);
+		wbuf[i] = (lirc_t) helper;
+#else
+		wbuf[i] = (lirc_t) (((double) wbuf[i])*timer/1000000);
+#endif
+	}
+
+	local_irq_save(flags);
+	i = 0;
+	while (i < count) {
+		level = lirc_get_timer();
+		counttimer = 0;
+		lirc_on();
+		do {
+			newlevel = lirc_get_timer();
+			if (level == 0 && newlevel != 0)
+				counttimer++;
+			level = newlevel;
+			if (check_pselecd && (in(1) & LP_PSELECD)) {
+				lirc_off();
+				local_irq_restore(flags);
+				return -EIO;
+			}
+		} while (counttimer < wbuf[i]);
+		i++;
+
+		lirc_off();
+		if (i == count)
+			break;
+		counttimer = 0;
+		do {
+			newlevel = lirc_get_timer();
+			if (level == 0 && newlevel != 0)
+				counttimer++;
+			level = newlevel;
+			if (check_pselecd && (in(1) & LP_PSELECD)) {
+				local_irq_restore(flags);
+				return -EIO;
+			}
+		} while (counttimer < wbuf[i]);
+		i++;
+	}
+	local_irq_restore(flags);
+#else
+	/* place code that handles write without external timer here */
+#endif
+	return n;
+}
+
+static unsigned int lirc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &lirc_wait, wait);
+	if (rptr != wptr)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd,
+		      unsigned long arg)
+{
+	int result;
+	unsigned long features = LIRC_CAN_SET_TRANSMITTER_MASK |
+				 LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2;
+	unsigned long mode;
+	unsigned int ivalue;
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+		result = put_user(features, (unsigned long *) arg);
+		if (result)
+			return result;
+		break;
+	case LIRC_GET_SEND_MODE:
+		result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg);
+		if (result)
+			return result;
+		break;
+	case LIRC_GET_REC_MODE:
+		result = put_user(LIRC_MODE_MODE2, (unsigned long *) arg);
+		if (result)
+			return result;
+		break;
+	case LIRC_SET_SEND_MODE:
+		result = get_user(mode, (unsigned long *) arg);
+		if (result)
+			return result;
+		if (mode != LIRC_MODE_PULSE)
+			return -EINVAL;
+		break;
+	case LIRC_SET_REC_MODE:
+		result = get_user(mode, (unsigned long *) arg);
+		if (result)
+			return result;
+		if (mode != LIRC_MODE_MODE2)
+			return -ENOSYS;
+		break;
+	case LIRC_SET_TRANSMITTER_MASK:
+		result = get_user(ivalue, (unsigned int *) arg);
+		if (result)
+			return result;
+		if ((ivalue & LIRC_PARALLEL_TRANSMITTER_MASK) != ivalue)
+			return LIRC_PARALLEL_MAX_TRANSMITTERS;
+		tx_mask = ivalue;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int lirc_open(struct inode *node, struct file *filep)
+{
+	if (MOD_IN_USE || !lirc_claim())
+		return -EBUSY;
+
+	parport_enable_irq(pport);
+
+	/* init read ptr */
+	rptr = 0;
+	wptr = 0;
+	lost_irqs = 0;
+
+	MOD_INC_USE_COUNT;
+	is_open = 1;
+	return 0;
+}
+
+static int lirc_close(struct inode *node, struct file *filep)
+{
+	if (is_claimed) {
+		is_claimed = 0;
+		parport_release(ppdevice);
+	}
+	is_open = 0;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static struct file_operations lirc_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= lirc_lseek,
+	.read		= lirc_read,
+	.write		= lirc_write,
+	.poll		= lirc_poll,
+	.ioctl		= lirc_ioctl,
+	.open		= lirc_open,
+	.release	= lirc_close
+};
+
+static int set_use_inc(void *data)
+{
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+}
+
+static struct lirc_driver driver = {
+       .name		= LIRC_DRIVER_NAME,
+       .minor		= -1,
+       .code_length	= 1,
+       .sample_rate	= 0,
+       .data		= NULL,
+       .add_to_buf	= NULL,
+#ifndef LIRC_REMOVE_DURING_EXPORT
+       .get_queue	= NULL,
+#endif
+       .set_use_inc	= set_use_inc,
+       .set_use_dec	= set_use_dec,
+       .fops		= &lirc_fops,
+       .dev		= NULL,
+       .owner		= THIS_MODULE,
+};
+
+#ifdef MODULE
+static int pf(void *handle);
+static void kf(void *handle);
+
+static struct timer_list poll_timer;
+static void poll_state(unsigned long ignored);
+
+static void poll_state(unsigned long ignored)
+{
+	printk(KERN_NOTICE "%s: time\n",
+	       LIRC_DRIVER_NAME);
+	del_timer(&poll_timer);
+	if (is_claimed)
+		return;
+	kf(NULL);
+	if (!is_claimed) {
+		printk(KERN_NOTICE "%s: could not claim port, giving up\n",
+		       LIRC_DRIVER_NAME);
+		init_timer(&poll_timer);
+		poll_timer.expires = jiffies + HZ;
+		poll_timer.data = (unsigned long)current;
+		poll_timer.function = poll_state;
+		add_timer(&poll_timer);
+	}
+}
+
+static int pf(void *handle)
+{
+	parport_disable_irq(pport);
+	is_claimed = 0;
+	return 0;
+}
+
+static void kf(void *handle)
+{
+	if (!is_open)
+		return;
+	if (!lirc_claim())
+		return;
+	parport_enable_irq(pport);
+	lirc_off();
+	/* this is a bit annoying when you actually print...*/
+	/*
+	printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME);
+	*/
+}
+
+/*** module initialization and cleanup ***/
+
+static int __init lirc_parallel_init(void)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3)
+	pport = parport_find_base(io);
+#else
+	pport = parport_enumerate();
+	while (pport != NULL) {
+		if (pport->base == io)
+			break;
+		pport = pport->next;
+	}
+#endif
+	if (pport == NULL) {
+		printk(KERN_NOTICE "%s: no port at %x found\n",
+		       LIRC_DRIVER_NAME, io);
+		return -ENXIO;
+	}
+	ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
+					   pf, kf, irq_handler, 0, NULL);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3)
+	parport_put_port(pport);
+#endif
+	if (ppdevice == NULL) {
+		printk(KERN_NOTICE "%s: parport_register_device() failed\n",
+		       LIRC_DRIVER_NAME);
+		return -ENXIO;
+	}
+	if (parport_claim(ppdevice) != 0)
+		goto skip_init;
+	is_claimed = 1;
+	out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP);
+
+#ifdef LIRC_TIMER
+	if (debug)
+		out(LIRC_PORT_DATA, tx_mask);
+
+	timer = init_lirc_timer();
+
+#if 0	/* continue even if device is offline */
+	if (timer == 0) {
+		is_claimed = 0;
+		parport_release(pport);
+		parport_unregister_device(ppdevice);
+		return -EIO;
+	}
+
+#endif
+	if (debug)
+		out(LIRC_PORT_DATA, 0);
+#endif
+
+	is_claimed = 0;
+	parport_release(ppdevice);
+ skip_init:
+	driver.minor = lirc_register_driver(&driver);
+	if (driver.minor < 0) {
+		printk(KERN_NOTICE "%s: register_chrdev() failed\n",
+		       LIRC_DRIVER_NAME);
+		parport_unregister_device(ppdevice);
+		return -EIO;
+	}
+	printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
+	       LIRC_DRIVER_NAME, io, irq);
+	return 0;
+}
+
+static void __exit lirc_parallel_exit(void)
+{
+	parport_unregister_device(ppdevice);
+	lirc_unregister_driver(driver.minor);
+}
+
+module_init(lirc_parallel_init);
+module_exit(lirc_parallel_exit);
+
+MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");
+MODULE_AUTHOR("Christoph Bartelmus");
+MODULE_LICENSE("GPL");
+
+module_param(io, int, S_IRUGO);
+MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");
+
+module_param(irq, int, S_IRUGO);
+MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");
+
+module_param(tx_mask, int, S_IRUGO);
+MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+module_param(check_pselecd, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Check for printer (default: 0)");
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_parallel/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_parallel/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_PARALLEL)	+= lirc_parallel.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_parallel/lirc_parallel.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_parallel/lirc_parallel.h
@@ -0,0 +1,26 @@
+/*      $Id: lirc_parallel.h,v 5.2 2007/01/25 04:32:05 lirc Exp $      */
+
+#ifndef _LIRC_PARALLEL_H
+#define _LIRC_PARALLEL_H
+
+#include <linux/lp.h>
+
+#define LIRC_PORT_LEN 3
+
+#define LIRC_LP_BASE    0
+#define LIRC_LP_STATUS  1
+#define LIRC_LP_CONTROL 2
+
+#define LIRC_PORT_DATA           LIRC_LP_BASE    /* base */
+#define LIRC_PORT_TIMER        LIRC_LP_STATUS    /* status port */
+#define LIRC_PORT_TIMER_BIT          LP_PBUSY    /* busy signal */
+#define LIRC_PORT_SIGNAL       LIRC_LP_STATUS    /* status port */
+#define LIRC_PORT_SIGNAL_BIT          LP_PACK    /* ack signal */
+#define LIRC_PORT_IRQ         LIRC_LP_CONTROL    /* control port */
+
+#define LIRC_SFH506_DELAY 0             /* delay t_phl in usecs */
+
+#define LIRC_PARALLEL_MAX_TRANSMITTERS 8
+#define LIRC_PARALLEL_TRANSMITTER_MASK ((1<<LIRC_PARALLEL_MAX_TRANSMITTERS) - 1)
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_gpio/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_gpio/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_GPIO)		+= lirc_gpio.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_gpio/lirc_gpio.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_gpio/lirc_gpio.c
@@ -0,0 +1,613 @@
+/*
+ * Remote control driver for the TV-card
+ * key codes are obtained from GPIO port
+ *
+ * (L) by Artur Lipowski <alipowski@interia.pl>
+ *     patch for the AverMedia by Santiago Garcia Mantinan <manty@i.am>
+ *			    and Christoph Bartelmus <lirc@bartelmus.de>
+ *     patch for the BestBuy by Miguel Angel Alvarez <maacruz@navegalia.com>
+ *     patch for the Winfast TV2000 by Juan Toledo
+ *     <toledo@users.sourceforge.net>
+ *     patch for the I-O Data GV-BCTV5/PCI by Jens C. Rasmussen
+ *     <jens.rasmussen@ieee.org>
+ *
+ *  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
+ *
+ * $Id: lirc_gpio.c,v 1.57 2009/02/14 19:35:52 lirc Exp $
+ *
+ */
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 4)
+#error "*******************************************************"
+#error "Sorry, this driver needs kernel version 2.2.4 or higher"
+#error "*******************************************************"
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#include <linux/wrapper.h>
+#endif
+#include <linux/errno.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#include "../drivers/char/bttv.h"
+#include "../drivers/char/bttvp.h"
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
+#include "../drivers/media/video/bttv.h"
+#include "../drivers/media/video/bttvp.h"
+#else
+#include "../drivers/media/video/bt8xx/bttv.h"
+#include "../drivers/media/video/bt8xx/bttvp.h"
+#endif
+
+#if BTTV_VERSION_CODE < KERNEL_VERSION(0, 7, 45)
+#error "*******************************************************"
+#error " Sorry, this driver needs bttv version 0.7.45 or       "
+#error " higher. If you are using the bttv package, copy it to "
+#error " the kernel					    "
+#error "*******************************************************"
+#endif
+
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+/* insmod parameters */
+static int debug;
+static int card;
+static int minor = -1;
+static int bttv_id = BTTV_BOARD_UNKNOWN;
+static unsigned long gpio_mask;
+static unsigned long gpio_enable;
+static unsigned long gpio_lock_mask;
+static unsigned long gpio_xor_mask;
+static int soft_gap;
+static int sample_rate = 10;
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG fmt, ## args);	\
+	} while (0)
+
+struct rcv_info {
+	int bttv_id;
+	int card_id;
+	unsigned long gpio_mask;
+	unsigned long gpio_enable;
+	unsigned long gpio_lock_mask;
+	unsigned long gpio_xor_mask;
+	int soft_gap;
+	int sample_rate;
+	unsigned char code_length;
+};
+
+static struct rcv_info rcv_infos[] = {
+	{BTTV_BOARD_UNKNOWN,
+		0, 0, 0, 0, 0, 0, 1, 0},
+	{BTTV_BOARD_PXELVWPLTVPAK,
+		0, 0x00003e00, 0, 0x0010000, 0, 0, 15, 32},
+	{BTTV_BOARD_PXELVWPLTVPRO,
+		0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32},
+	{BTTV_BOARD_PV_BT878P_9B,
+		0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32},
+	{BTTV_BOARD_PV_BT878P_PLUS,
+		0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32},
+#ifdef BTTV_BOARD_PV_M4900
+	{BTTV_BOARD_PV_M4900,
+		0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32},
+#endif
+	{BTTV_BOARD_AVERMEDIA,
+		0, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32},
+
+	/* mapped to Capture98 */
+	{BTTV_BOARD_AVPHONE98,
+		0x00011461, 0x003b8000, 0x00004000,
+		0x0800000, 0x00800000, 0, 10, 0},
+	{BTTV_BOARD_AVERMEDIA98,
+		0x00021461, 0x003b8000, 0x00004000,
+		0x0800000, 0x00800000, 0, 10, 0},
+
+	/* mapped to Phone98 */
+	{BTTV_BOARD_AVPHONE98,
+		0x00031461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32},
+	/* is this one correct? */
+	{BTTV_BOARD_AVERMEDIA98,
+		0x00041461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32},
+	/* work-around for VDOMATE */
+	{BTTV_BOARD_AVERMEDIA98,
+		0x03001461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32},
+	/* reported by Danijel Korzinek, AVerTV GOw/FM */
+	{BTTV_BOARD_AVERMEDIA98,
+		0x00000000, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32},
+
+	{BTTV_BOARD_CHRONOS_VS2,
+		0, 0x000000f8,	0, 0x0000100, 0, 0, 20, 0},
+	/* CPH031 and CPH033 cards (?) */
+	/* MIRO was just a work-around */
+	{BTTV_BOARD_MIRO,
+		0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32},
+	{BTTV_BOARD_DYNALINK,
+		0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32},
+#ifdef BTTV_BOARD_ASKEY_CPH03X
+	{BTTV_BOARD_ASKEY_CPH03X,
+		0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32},
+#endif
+	{BTTV_BOARD_WINVIEW_601,
+		0, 0x00001f00, 0, 0x0004000, 0, 0, 0, 32},
+#ifdef BTTV_BOARD_KWORLD
+	{BTTV_BOARD_KWORLD,
+		0, 0x00007f00, 0, 0x0004000, 0, 0, 12, 32},
+#endif
+	/* just a guess */
+	{BTTV_BOARD_MAGICTVIEW061,
+		0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32},
+	{BTTV_BOARD_MAGICTVIEW063,
+		0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32},
+	{BTTV_BOARD_PHOEBE_TVMAS,
+		0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32},
+#ifdef BTTV_BOARD_BESTBUY_EASYTV2
+	{BTTV_BOARD_BESTBUY_EASYTV,
+		0, 0x00007F00, 0, 0x0004000, 0, 0, 10, 8},
+	{BTTV_BOARD_BESTBUY_EASYTV2,
+		0, 0x00007F00, 0, 0x0008000, 0, 0, 10, 8},
+#endif
+	/* lock_mask probably also 0x100, or maybe it is 0x0 for all others? */
+	{BTTV_BOARD_FLYVIDEO,
+		0, 0x000000f8, 0, 0, 0, 0, 0, 42},
+	{BTTV_BOARD_FLYVIDEO_98,
+		0, 0x000000f8,	0, 0x0000100, 0, 0, 0, 42},
+	{BTTV_BOARD_TYPHOON_TVIEW,
+		0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42},
+#ifdef BTTV_BOARD_FLYVIDEO_98FM
+	/* smorar@alfonzo.smuts.uct.ac.za */
+	{BTTV_BOARD_FLYVIDEO_98FM,
+		0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42},
+#endif
+	/* The Leadtek WinFast TV 2000 XP card (id 0x6606107d) uses an
+	 * extra gpio bit compared to the original TV 2000 card (id
+	 * 0x217d6606); as the bttv-0.7.100 driver does not
+	 * distinguish between the two cards, we enable the extra bit
+	 * based on the card id: */
+	{BTTV_BOARD_WINFAST2000,
+		0x6606107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32},
+	{BTTV_BOARD_WINFAST2000,
+		0x6609107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32},
+	{BTTV_BOARD_WINFAST2000,
+		0xff06107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32},
+	/* default: */
+	{BTTV_BOARD_WINFAST2000,
+		0, 0x000000f8,	0, 0x0000100, 0, 0, 0, 32},
+#ifdef BTTV_BOARD_GVBCTV5PCI
+	{BTTV_BOARD_GVBCTV5PCI,
+		0, 0x00f0b000, 0, 0, 0, 0, 20, 8},
+#endif
+};
+
+static unsigned char code_length;
+static unsigned char code_bytes = 1;
+
+#define MAX_BYTES 8
+
+#define LOGHEAD "lirc_gpio (%d): "
+
+/* how many bits GPIO value can be shifted right before processing
+ * it is computed from the value of gpio_mask_parameter
+ */
+static unsigned char gpio_pre_shift;
+
+static int reverse(int data, int bits)
+{
+	int i;
+	int c;
+
+	for (c = 0, i = 0; i < bits; i++)
+		c |= (((data & (1<<i)) ? 1:0)) << (bits-1-i);
+
+	return c;
+}
+
+static int build_key(unsigned long gpio_val, unsigned char codes[MAX_BYTES])
+{
+	unsigned long mask = gpio_mask;
+	unsigned char shift = 0;
+
+	dprintk(LOGHEAD "gpio_val is %lx\n", card, (unsigned long) gpio_val);
+
+	gpio_val ^= gpio_xor_mask;
+
+	if (gpio_lock_mask && (gpio_val & gpio_lock_mask))
+		return -EBUSY;
+
+	switch (bttv_id) {
+	case BTTV_BOARD_AVERMEDIA98:
+		if (bttv_write_gpio(card, gpio_enable, gpio_enable)) {
+			dprintk(LOGHEAD "cannot write to GPIO\n", card);
+			return -EIO;
+		}
+		if (bttv_read_gpio(card, &gpio_val)) {
+			dprintk(LOGHEAD "cannot read GPIO\n", card);
+			return -EIO;
+		}
+		if (bttv_write_gpio(card, gpio_enable, 0)) {
+			dprintk(LOGHEAD "cannot write to GPIO\n", card);
+			return -EIO;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* extract bits from "raw" GPIO value using gpio_mask */
+	codes[0] = 0;
+	gpio_val >>= gpio_pre_shift;
+	while (mask) {
+		if (mask & 1u)
+			codes[0] |= (gpio_val & 1u) << shift++;
+		mask >>= 1;
+		gpio_val >>= 1;
+	}
+
+	dprintk(LOGHEAD "code is %lx\n", card, (unsigned long) codes[0]);
+	switch (bttv_id) {
+	case BTTV_BOARD_AVERMEDIA:
+		codes[2] = (codes[0]<<2)&0xff;
+		codes[3] = (~codes[2])&0xff;
+		codes[0] = 0x02;
+		codes[1] = 0xFD;
+		break;
+	case BTTV_BOARD_AVPHONE98:
+		codes[2] = ((codes[0]&(~0x1))<<2)&0xff;
+		codes[3] = (~codes[2])&0xff;
+		if (codes[0]&0x1) {
+			codes[0] = 0xc0;
+			codes[1] = 0x3f;
+		} else {
+			codes[0] = 0x40;
+			codes[1] = 0xbf;
+		}
+		break;
+	case BTTV_BOARD_AVERMEDIA98:
+		break;
+	case BTTV_BOARD_FLYVIDEO:
+	case BTTV_BOARD_FLYVIDEO_98:
+	case BTTV_BOARD_TYPHOON_TVIEW:
+#ifdef BTTV_BOARD_FLYVIDEO_98FM
+	case BTTV_BOARD_FLYVIDEO_98FM:
+#endif
+		codes[4] = codes[0]<<3;
+		codes[5] = ((~codes[4])&0xff);
+
+		codes[0] = 0x00;
+		codes[1] = 0x1A;
+		codes[2] = 0x1F;
+		codes[3] = 0x2F;
+		break;
+	case BTTV_BOARD_MAGICTVIEW061:
+	case BTTV_BOARD_MAGICTVIEW063:
+	case BTTV_BOARD_PHOEBE_TVMAS:
+		codes[0] = (codes[0]&0x01)
+			| ((codes[0]&0x02)<<1)
+			| ((codes[0]&0x04)<<2)
+			| ((codes[0]&0x08)>>2)
+			| ((codes[0]&0x10)>>1);
+		/* FALLTHROUGH */
+	case BTTV_BOARD_MIRO:
+	case BTTV_BOARD_DYNALINK:
+#ifdef BTTV_BOARD_ASKEY_CPH03X
+	case BTTV_BOARD_ASKEY_CPH03X:
+#endif
+	case BTTV_BOARD_PXELVWPLTVPAK:
+	case BTTV_BOARD_PXELVWPLTVPRO:
+	case BTTV_BOARD_PV_BT878P_9B:
+	case BTTV_BOARD_PV_BT878P_PLUS:
+#ifdef BTTV_BOARD_PV_M4900
+	case BTTV_BOARD_PV_M4900:
+#endif
+#ifdef BTTV_BOARD_KWORLD
+	case BTTV_BOARD_KWORLD:
+#endif
+		codes[2] = reverse(codes[0], 8);
+		codes[3] = (~codes[2])&0xff;
+		codes[0] = 0x61;
+		codes[1] = 0xD6;
+		break;
+#if 0
+		/* derived from e-tech config file */
+		/* 26 + 16 bits */
+		/* won't apply it until it's confirmed with a fly98 */
+	case BTTV_BOARD_FLYVIDEO_98:
+	case BTTV_BOARD_FLYVIDEO_98FM:
+		codes[4] = codes[0]<<3;
+		codes[5] = (~codes[4])&0xff;
+
+		codes[0] = 0x00;
+		codes[1] = 0x1A;
+		codes[2] = 0x1F;
+		codes[3] = 0x2F;
+		break;
+#endif
+	case BTTV_BOARD_WINFAST2000:
+		/* shift extra bit */
+		codes[0] = (codes[0]&0x1f) | ((codes[0]&0x20) << 1);
+	case BTTV_BOARD_WINVIEW_601:
+		codes[2] = reverse(codes[0], 8);
+		codes[3] = (~codes[2])&0xff;
+		codes[0] = 0xC0;
+		codes[1] = 0x3F;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* add_to_buf - copy a code to the buffer */
+static int add_to_buf(void *data, struct lirc_buffer *buf)
+{
+	static unsigned long next_time;
+	static unsigned char prev_codes[MAX_BYTES];
+	unsigned long code = 0;
+	unsigned char cur_codes[MAX_BYTES];
+
+	if (bttv_read_gpio(card, &code)) {
+		dprintk(LOGHEAD "cannot read GPIO\n", card);
+		return -EIO;
+	}
+
+	if (build_key(code, cur_codes))
+		return -EFAULT;
+
+	if (soft_gap) {
+		if (!memcmp(prev_codes, cur_codes, code_bytes) &&
+			jiffies < next_time)
+			return -EAGAIN;
+
+		next_time = jiffies + soft_gap;
+	}
+	memcpy(prev_codes, cur_codes, code_bytes);
+
+	lirc_buffer_write(buf, cur_codes);
+
+	return 0;
+}
+
+static int set_use_inc(void *data)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+static wait_queue_head_t *get_queue(void *data)
+{
+	return bttv_get_gpio_queue(card);
+}
+
+static struct lirc_driver driver = {
+	.name		= "lirc_gpio  ",
+	.add_to_buf	= add_to_buf,
+	.get_queue	= get_queue,
+	.set_use_inc	= set_use_inc,
+	.set_use_dec	= set_use_dec,
+	.dev		= NULL,
+	.owner		= THIS_MODULE,
+};
+
+/*
+ *
+ */
+static int gpio_remote_init(void)
+{
+	int ret;
+	unsigned int mask;
+
+	/* "normalize" gpio_mask
+	 * this means shift it right until first bit is set
+	 */
+	while (!(gpio_mask & 1u)) {
+		gpio_pre_shift++;
+		gpio_mask >>= 1;
+	}
+
+	if (code_length)
+		driver.code_length = code_length;
+	else {
+		/* calculate scan code length in bits if needed */
+		driver.code_length = 1;
+		mask = gpio_mask >> 1;
+		while (mask) {
+			if (mask & 1u)
+				driver.code_length++;
+			mask >>= 1;
+		}
+	}
+
+	code_bytes = (driver.code_length/8) + (driver.code_length % 8 ? 1 : 0);
+	if (MAX_BYTES < code_bytes) {
+		printk(LOGHEAD "scan code too long (%d bytes)\n",
+			minor, code_bytes);
+		return -EBADRQC;
+	}
+
+	if (gpio_enable) {
+		if (bttv_gpio_enable(card, gpio_enable, gpio_enable)) {
+			printk(LOGHEAD "gpio_enable failure\n", minor);
+			return -EIO;
+		}
+	}
+
+
+	/* translate ms to jiffies */
+	soft_gap = (soft_gap*HZ) / 1000;
+
+	driver.minor = minor;
+	driver.sample_rate = sample_rate;
+
+	ret = lirc_register_driver(&driver);
+
+	if (0 > ret) {
+		printk(LOGHEAD "device registration failed with %d\n",
+			minor, ret);
+		return ret;
+	}
+
+	minor = ret;
+	printk(LOGHEAD "driver registered\n", minor);
+
+	return 0;
+}
+
+#ifdef MODULE
+/*
+ *
+ */
+int init_module(void)
+{
+	int type, cardid, card_type;
+
+	if (MAX_IRCTL_DEVICES < minor) {
+		printk(KERN_INFO "lirc_gpio: parameter minor (%d) "
+		       "must be less than %d!\n",
+		       minor, MAX_IRCTL_DEVICES - 1);
+		return -EBADRQC;
+	}
+
+	/* if gpio_mask not zero then use module parameters
+	 * instead of autodetecting TV card
+	 */
+	if (gpio_mask) {
+		if (sample_rate != 0 &&
+		    (2 > sample_rate || HZ < sample_rate)) {
+			printk(LOGHEAD "parameter sample_rate "
+			       "must be between 2 and %d!\n", minor, HZ);
+			return -EBADRQC;
+		}
+
+		if (sample_rate != 0 && soft_gap &&
+		    ((2000/sample_rate) > soft_gap || 1000 < soft_gap)) {
+			printk(LOGHEAD "parameter soft_gap "
+			       "must be between %d and 1000!\n",
+			       minor, 2000/sample_rate);
+			return -EBADRQC;
+		}
+	} else {
+		if (bttv_get_cardinfo(card, &type, &cardid) == -1) {
+			printk(LOGHEAD "could not get card type\n", minor);
+			return -EBADRQC;
+		}
+		printk(LOGHEAD "card type 0x%x, id 0x%x\n", minor,
+		       type, cardid);
+
+		if (type == BTTV_BOARD_UNKNOWN) {
+			printk(LOGHEAD "cannot detect TV card nr %d!\n",
+			       minor, card);
+			return -EBADRQC;
+		}
+		for (card_type = 1;
+		     card_type < sizeof(rcv_infos)/sizeof(struct rcv_info);
+		     card_type++) {
+			if (rcv_infos[card_type].bttv_id == type &&
+			    (rcv_infos[card_type].card_id == 0 ||
+			     rcv_infos[card_type].card_id == cardid)) {
+				bttv_id = rcv_infos[card_type].bttv_id;
+				gpio_mask = rcv_infos[card_type].gpio_mask;
+				gpio_enable = rcv_infos[card_type].gpio_enable;
+				gpio_lock_mask =
+					rcv_infos[card_type].gpio_lock_mask;
+				gpio_xor_mask =
+					rcv_infos[card_type].gpio_xor_mask;
+				soft_gap = rcv_infos[card_type].soft_gap;
+				sample_rate = rcv_infos[card_type].sample_rate;
+				code_length = rcv_infos[card_type].code_length;
+				break;
+			}
+		}
+		if (type == BTTV_BOARD_AVPHONE98 && cardid == 0x00011461)
+			bttv_id = BTTV_BOARD_AVERMEDIA98;
+
+		if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00041461)
+			bttv_id = BTTV_BOARD_AVPHONE98;
+
+		if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x03001461)
+			bttv_id = BTTV_BOARD_AVPHONE98;
+
+		if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00000000)
+			bttv_id = BTTV_BOARD_AVPHONE98;
+
+		if (card_type == sizeof(rcv_infos)/sizeof(struct rcv_info)) {
+			printk(LOGHEAD "TV card type 0x%x not supported!\n",
+			       minor, type);
+			return -EBADRQC;
+		}
+	}
+
+	return gpio_remote_init();
+}
+
+/*
+ *
+ */
+void cleanup_module(void)
+{
+	lirc_unregister_driver(minor);
+
+	dprintk(LOGHEAD "module successfully unloaded\n", minor);
+}
+
+/* Dont try to use it as a static version !  */
+MODULE_DESCRIPTION("Driver module for remote control (data "
+		   "from bt848 GPIO port)");
+MODULE_AUTHOR("Artur Lipowski");
+MODULE_LICENSE("GPL");
+
+module_param(minor, int, S_IRUGO);
+MODULE_PARM_DESC(minor, "Preferred minor device number");
+
+module_param(card, int, S_IRUGO);
+MODULE_PARM_DESC(card, "TV card number to attach to");
+
+module_param(gpio_mask, long, S_IRUGO);
+MODULE_PARM_DESC(gpio_mask, "gpio_mask");
+
+module_param(gpio_lock_mask, long, S_IRUGO);
+MODULE_PARM_DESC(gpio_lock_mask, "gpio_lock_mask");
+
+module_param(gpio_xor_mask, long, S_IRUGO);
+MODULE_PARM_DESC(gpio_xor_mask, "gpio_xor_mask");
+
+module_param(soft_gap, int, S_IRUGO);
+MODULE_PARM_DESC(soft_gap, "Time between keypresses (in ms)");
+
+module_param(sample_rate, int, S_IRUGO);
+MODULE_PARM_DESC(sample_rate, "Sample rate (between 2 and HZ)");
+
+module_param(bttv_id, int, S_IRUGO);
+MODULE_PARM_DESC(bttv_id, "BTTV card type");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_imon/lirc_imon.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_imon/lirc_imon.c
@@ -0,0 +1,2370 @@
+/*
+ *   lirc_imon.c:  LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
+ *		   including the iMON PAD model
+ *
+ *   $Id: lirc_imon.c,v 1.111 2009/09/11 04:56:18 jarodwilson Exp $
+ *
+ *   Copyright(C) 2004  Venky Raju(dev@venky.ws)
+ *
+ *   lirc_imon 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.
+ */
+#include <linux/version.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+#error "*** Sorry, this driver requires a 2.6 kernel"
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#include <linux/usb.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+#include <linux/usb/input.h>
+#else
+#include <linux/input.h>
+#endif
+#include <linux/time.h>
+#include <linux/timer.h>
+
+#include "../kcompat.h"
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+
+
+#define MOD_AUTHOR	"Venky Raju <dev@venky.ws>"
+#define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
+#define MOD_NAME	"lirc_imon"
+#define MOD_VERSION	"0.6"
+
+#define DISPLAY_MINOR_BASE	144
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
+#define DEVFS_MODE	(S_IFCHR | S_IRUSR | S_IWUSR | \
+			 S_IRGRP | S_IWGRP | S_IROTH)
+#endif
+#define DEVICE_NAME	LIRC_DEVFS_PREFIX "lcd%d"
+
+#define BUF_CHUNK_SIZE	4
+#define BUF_SIZE	128
+
+#define BIT_DURATION	250	/* each bit received is 250us */
+
+#define IMON_CLOCK_ENABLE_PACKETS	2
+
+#define dprintk(fmt, args...)						\
+	do {								\
+		if (debug)						\
+			printk(KERN_INFO MOD_NAME ": " fmt, ## args);	\
+	} while (0)
+
+/*** P R O T O T Y P E S ***/
+
+/* USB Callback prototypes */
+static int imon_probe(struct usb_interface *interface,
+		      const struct usb_device_id *id);
+static void imon_disconnect(struct usb_interface *interface);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_rx_callback_intf0(struct urb *urb, struct pt_regs *regs);
+static void usb_rx_callback_intf1(struct urb *urb, struct pt_regs *regs);
+static void usb_tx_callback(struct urb *urb, struct pt_regs *regs);
+#else
+static void usb_rx_callback_intf0(struct urb *urb);
+static void usb_rx_callback_intf1(struct urb *urb);
+static void usb_tx_callback(struct urb *urb);
+#endif
+
+/* suspend/resume support */
+static int imon_resume(struct usb_interface *intf);
+static int imon_suspend(struct usb_interface *intf, pm_message_t message);
+
+/* Display file_operations function prototypes */
+static int display_open(struct inode *inode, struct file *file);
+static int display_close(struct inode *inode, struct file *file);
+
+/* VFD write operation */
+static ssize_t vfd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos);
+
+/* LCD file_operations override function prototypes */
+static ssize_t lcd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos);
+
+/* LIRC driver function prototypes */
+static int ir_open(void *data);
+static void ir_close(void *data);
+
+/* Driver init/exit prototypes */
+static int __init imon_init(void);
+static void __exit imon_exit(void);
+
+/*** G L O B A L S ***/
+
+struct imon_context {
+	struct usb_device *usbdev_intf0;
+	/* Newer devices have two interfaces */
+	struct usb_device *usbdev_intf1;
+	int display_supported;		/* not all controllers do */
+	int display_isopen;		/* display port has been opened */
+	int ir_isopen;			/* IR port open	*/
+	int ir_isassociating;		/* IR port open for association */
+	int dev_present_intf0;		/* USB device presence, interface 0 */
+	int dev_present_intf1;		/* USB device presence, interface 1 */
+	struct mutex lock;		/* to lock this object */
+	wait_queue_head_t remove_ok;	/* For unexpected USB disconnects */
+
+	int vfd_proto_6p;		/* some VFD require a 6th packet */
+	int ir_onboard_decode;		/* IR signals decoded onboard */
+
+	struct lirc_driver *driver;
+	struct usb_endpoint_descriptor *rx_endpoint_intf0;
+	struct usb_endpoint_descriptor *rx_endpoint_intf1;
+	struct usb_endpoint_descriptor *tx_endpoint;
+	struct urb *rx_urb_intf0;
+	struct urb *rx_urb_intf1;
+	struct urb *tx_urb;
+	int tx_control;
+	unsigned char usb_rx_buf[8];
+	unsigned char usb_tx_buf[8];
+
+	struct rx_data {
+		int count;		/* length of 0 or 1 sequence */
+		int prev_bit;		/* logic level of sequence */
+		int initial_space;	/* initial space flag */
+	} rx;
+
+	struct tx_t {
+		unsigned char data_buf[35];	/* user data buffer */
+		struct completion finished;	/* wait for write to finish */
+		atomic_t busy;			/* write in progress */
+		int status;			/* status of tx completion */
+	} tx;
+
+	int ffdc_dev;			/* is this the overused ffdc ID? */
+	int ir_protocol;		/* iMON or MCE (RC6) IR protocol? */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	struct input_dev *mouse;	/* input device for iMON PAD remote */
+	struct input_dev *touch;	/* input device for touchscreen */
+#endif
+	int display_type;		/* store the display type */
+	int pad_mouse;			/* toggle kbd(0)/mouse(1) mode */
+	int touch_x;			/* x coordinate on touchscreen */
+	int touch_y;			/* y coordinate on touchscreen */
+	char name_mouse[128];
+	char phys_mouse[64];
+	char name_touch[128];
+	char phys_touch[64];
+	struct timer_list timer;
+};
+
+#define TOUCH_TIMEOUT	(HZ/30)
+
+/* display file operations. Nb: lcd_write will be subbed in as needed later */
+static struct file_operations display_fops = {
+	.owner		= THIS_MODULE,
+	.open		= &display_open,
+	.write		= &vfd_write,
+	.release	= &display_close
+};
+
+enum {
+	IMON_DISPLAY_TYPE_AUTO = 0,
+	IMON_DISPLAY_TYPE_VFD  = 1,
+	IMON_DISPLAY_TYPE_LCD  = 2,
+	IMON_DISPLAY_TYPE_VGA  = 3,
+	IMON_DISPLAY_TYPE_NONE = 4,
+};
+
+enum {
+	IMON_IR_PROTOCOL_IMON       = 0,
+	IMON_IR_PROTOCOL_MCE        = 1,
+	IMON_IR_PROTOCOL_IMON_NOPAD = 2,
+};
+/*
+ * USB Device ID for iMON USB Control Boards
+ *
+ * The Windows drivers contain 6 different inf files, more or less one for
+ * each new device until the 0x0034-0x0046 devices, which all use the same
+ * driver. Some of the devices in the 34-46 range haven't been definitively
+ * identified yet. Early devices have either a TriGem Computer, Inc. or a
+ * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later
+ * devices use the SoundGraph vendor ID (0x15c2).
+ */
+static struct usb_device_id imon_usb_id_table[] = {
+	/* TriGem iMON (IR only) -- TG_iMON.inf */
+	{ USB_DEVICE(0x0aa8, 0x8001) },
+
+	/* SoundGraph iMON (IR only) -- sg_imon.inf */
+	{ USB_DEVICE(0x04e8, 0xff30) },
+
+	/* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */
+	{ USB_DEVICE(0x0aa8, 0xffda) },
+
+	/* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */
+	{ USB_DEVICE(0x15c2, 0xffda) },
+
+	/*
+	 * Several devices with this same device ID, all use iMON_PAD.inf
+	 * SoundGraph iMON PAD (IR & VFD)
+	 * SoundGraph iMON PAD (IR & LCD)
+	 * SoundGraph iMON Knob (IR only)
+	 */
+	/* SoundGraph iMON PAD (IR & VFD/LCD), iMON Knob */
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+
+	/*
+	 * Newer devices, all driven by the latest iMON Windows driver, full
+	 * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2'
+	 * Need user input to fill in details on unknown devices.
+	 */
+	/* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	/* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	/* SoundGraph iMON OEM VFD (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0037) },
+	/* SoundGraph iMON OEM LCD (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0039) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003a) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003b) },
+	/* SoundGraph iMON OEM Inside (IR only) */
+	{ USB_DEVICE(0x15c2, 0x003c) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003d) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003e) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x003f) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0040) },
+	/* SoundGraph iMON MINI (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0041) },
+	/* Antec Veris Multimedia Station EZ External (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0042) },
+	/* Antec Veris Multimedia Station Basic Internal (IR only) */
+	{ USB_DEVICE(0x15c2, 0x0043) },
+	/* Antec Veris Multimedia Station Elite (IR & VFD) */
+	{ USB_DEVICE(0x15c2, 0x0044) },
+	/* Antec Veris Multimedia Station Premiere (IR & LCD) */
+	{ USB_DEVICE(0x15c2, 0x0045) },
+	/* device specifics unknown */
+	{ USB_DEVICE(0x15c2, 0x0046) },
+	{}
+};
+
+/* Some iMON VFD models requires a 6th packet for VFD writes */
+static struct usb_device_id vfd_proto_6p_list[] = {
+	{ USB_DEVICE(0x15c2, 0xffda) },
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0044) },
+	{}
+};
+
+/* newer iMON models use control endpoints */
+static struct usb_device_id ctl_ep_device_list[] = {
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0037) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{ USB_DEVICE(0x15c2, 0x0039) },
+	{ USB_DEVICE(0x15c2, 0x003a) },
+	{ USB_DEVICE(0x15c2, 0x003b) },
+	{ USB_DEVICE(0x15c2, 0x003c) },
+	{ USB_DEVICE(0x15c2, 0x003d) },
+	{ USB_DEVICE(0x15c2, 0x003e) },
+	{ USB_DEVICE(0x15c2, 0x003f) },
+	{ USB_DEVICE(0x15c2, 0x0040) },
+	{ USB_DEVICE(0x15c2, 0x0041) },
+	{ USB_DEVICE(0x15c2, 0x0042) },
+	{ USB_DEVICE(0x15c2, 0x0043) },
+	{ USB_DEVICE(0x15c2, 0x0044) },
+	{ USB_DEVICE(0x15c2, 0x0045) },
+	{ USB_DEVICE(0x15c2, 0x0046) },
+	{}
+};
+
+/* iMON LCD models use a different write op */
+static struct usb_device_id lcd_device_list[] = {
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{ USB_DEVICE(0x15c2, 0x0045) },
+	{}
+};
+
+/* iMON devices with front panel buttons or touchscreen need a larger buffer */
+static struct usb_device_id large_buffer_list[] = {
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{ USB_DEVICE(0x15c2, 0x0045) },
+};
+
+/* Newer iMON models decode the signal onboard */
+static struct usb_device_id ir_onboard_decode_list[] = {
+	{ USB_DEVICE(0x15c2, 0xffdc) },
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	{ USB_DEVICE(0x15c2, 0x0036) },
+	{ USB_DEVICE(0x15c2, 0x0037) },
+	{ USB_DEVICE(0x15c2, 0x0038) },
+	{ USB_DEVICE(0x15c2, 0x0039) },
+	{ USB_DEVICE(0x15c2, 0x003a) },
+	{ USB_DEVICE(0x15c2, 0x003b) },
+	{ USB_DEVICE(0x15c2, 0x003c) },
+	{ USB_DEVICE(0x15c2, 0x003d) },
+	{ USB_DEVICE(0x15c2, 0x003e) },
+	{ USB_DEVICE(0x15c2, 0x003f) },
+	{ USB_DEVICE(0x15c2, 0x0040) },
+	{ USB_DEVICE(0x15c2, 0x0041) },
+	{ USB_DEVICE(0x15c2, 0x0042) },
+	{ USB_DEVICE(0x15c2, 0x0043) },
+	{ USB_DEVICE(0x15c2, 0x0044) },
+	{ USB_DEVICE(0x15c2, 0x0045) },
+	{ USB_DEVICE(0x15c2, 0x0046) },
+	{}
+};
+
+/* Some iMON devices have no lcd/vfd, don't set one up */
+static struct usb_device_id ir_only_list[] = {
+	{ USB_DEVICE(0x0aa8, 0x8001) },
+	{ USB_DEVICE(0x04e8, 0xff30) },
+	/* the first imon lcd and the knob share this device id. :\ */
+	/*{ USB_DEVICE(0x15c2, 0xffdc) },*/
+	{ USB_DEVICE(0x15c2, 0x003c) },
+	{ USB_DEVICE(0x15c2, 0x0041) },
+	{ USB_DEVICE(0x15c2, 0x0042) },
+	{ USB_DEVICE(0x15c2, 0x0043) },
+	{}
+};
+
+/* iMON devices with VGA touchscreens */
+static struct usb_device_id imon_touchscreen_list[] = {
+	{ USB_DEVICE(0x15c2, 0x0034) },
+	{ USB_DEVICE(0x15c2, 0x0035) },
+	{}
+};
+
+/* USB Device data */
+static struct usb_driver imon_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name		= MOD_NAME,
+	.probe		= imon_probe,
+	.disconnect	= imon_disconnect,
+	.suspend	= imon_suspend,
+	.resume		= imon_resume,
+	.id_table	= imon_usb_id_table,
+};
+
+static struct usb_class_driver imon_class = {
+	.name		= DEVICE_NAME,
+	.fops		= &display_fops,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
+	.mode		= DEVFS_MODE,
+#endif
+	.minor_base	= DISPLAY_MINOR_BASE,
+};
+
+/* to prevent races between open() and disconnect(), probing, etc */
+static DEFINE_MUTEX(driver_lock);
+
+static int debug;
+
+/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
+static int display_type;
+
+/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */
+static int ir_protocol;
+
+/*
+ * In certain use cases, mouse mode isn't really helpful, and could actually
+ * cause confusion, so allow disabling it when the IR device is open.
+ */
+static int nomouse;
+
+/* threshold at which a pad push registers as an arrow key in kbd mode */
+static int pad_thresh;
+
+
+/***  M O D U L E   C O D E ***/
+
+MODULE_AUTHOR(MOD_AUTHOR);
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_VERSION(MOD_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, imon_usb_id_table);
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
+module_param(display_type, int, S_IRUGO);
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
+		 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
+module_param(ir_protocol, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=native iMON, "
+		 "1=Windows Media Center Ed. (RC-6), 2=iMON w/o PAD stabilize "
+		 "(default: native iMON)");
+module_param(nomouse, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
+		 "open. 0=don't disable, 1=disable. (default: don't disable)");
+module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
+		 "arrow key in kbd mode (default: 28)");
+
+static void free_imon_context(struct imon_context *context)
+{
+	usb_free_urb(context->tx_urb);
+	usb_free_urb(context->rx_urb_intf0);
+	usb_free_urb(context->rx_urb_intf1);
+	lirc_buffer_free(context->driver->rbuf);
+	kfree(context->driver->rbuf);
+	kfree(context->driver);
+	kfree(context);
+
+	dprintk("%s: iMON context freed\n", __func__);
+}
+
+static void deregister_from_lirc(struct imon_context *context)
+{
+	int retval;
+	int minor = context->driver->minor;
+
+	retval = lirc_unregister_driver(minor);
+	if (retval)
+		err("%s: unable to deregister from lirc(%d)",
+			__func__, retval);
+	else
+		printk(KERN_INFO MOD_NAME ": Deregistered iMON driver "
+		       "(minor:%d)\n", minor);
+
+}
+
+/**
+ * Called when the Display device (e.g. /dev/lcd0)
+ * is opened by the application.
+ */
+static int display_open(struct inode *inode, struct file *file)
+{
+	struct usb_interface *interface;
+	struct imon_context *context = NULL;
+	int subminor;
+	int retval = 0;
+
+	/* prevent races with disconnect */
+	mutex_lock(&driver_lock);
+
+	subminor = iminor(inode);
+	interface = usb_find_interface(&imon_driver, subminor);
+	if (!interface) {
+		err("%s: could not find interface for minor %d",
+		    __func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+	context = usb_get_intfdata(interface);
+
+	if (!context) {
+		err("%s: no context found for minor %d",
+					__func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->display_supported) {
+		err("%s: display not supported by device", __func__);
+		retval = -ENODEV;
+	} else if (context->display_isopen) {
+		err("%s: display port is already open", __func__);
+		retval = -EBUSY;
+	} else {
+		MOD_INC_USE_COUNT;
+		context->display_isopen = 1;
+		file->private_data = context;
+		printk(KERN_INFO "display port opened\n");
+	}
+
+	mutex_unlock(&context->lock);
+
+exit:
+	mutex_unlock(&driver_lock);
+	return retval;
+}
+
+/**
+ * Called when the display device (e.g. /dev/lcd0)
+ * is closed by the application.
+ */
+static int display_close(struct inode *inode, struct file *file)
+{
+	struct imon_context *context = NULL;
+	int retval = 0;
+
+	context = (struct imon_context *)file->private_data;
+
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->display_supported) {
+		err("%s: display not supported by device", __func__);
+		retval = -ENODEV;
+	} else if (!context->display_isopen) {
+		err("%s: display is not open", __func__);
+		retval = -EIO;
+	} else {
+		context->display_isopen = 0;
+		MOD_DEC_USE_COUNT;
+		printk(KERN_INFO "display port closed\n");
+		if (!context->dev_present_intf0 && !context->ir_isopen) {
+			/*
+			 * Device disconnected before close and IR port is not
+			 * open. If IR port is open, context will be deleted by
+			 * ir_close.
+			 */
+			mutex_unlock(&context->lock);
+			free_imon_context(context);
+			return retval;
+		}
+	}
+
+	mutex_unlock(&context->lock);
+	return retval;
+}
+
+/**
+ * Sends a packet to the device
+ */
+static int send_packet(struct imon_context *context)
+{
+	unsigned int pipe;
+	int interval = 0;
+	int retval = 0;
+	struct usb_ctrlrequest *control_req = NULL;
+
+	/* Check if we need to use control or interrupt urb */
+	if (!context->tx_control) {
+		pipe = usb_sndintpipe(context->usbdev_intf0,
+				      context->tx_endpoint->bEndpointAddress);
+		interval = context->tx_endpoint->bInterval;
+
+		usb_fill_int_urb(context->tx_urb, context->usbdev_intf0, pipe,
+				 context->usb_tx_buf,
+				 sizeof(context->usb_tx_buf),
+				 usb_tx_callback, context, interval);
+
+		context->tx_urb->actual_length = 0;
+	} else {
+		/* fill request into kmalloc'ed space: */
+		control_req = kmalloc(sizeof(struct usb_ctrlrequest),
+				      GFP_KERNEL);
+		if (control_req == NULL)
+			return -ENOMEM;
+
+		/* setup packet is '21 09 0200 0001 0008' */
+		control_req->bRequestType = 0x21;
+		control_req->bRequest = 0x09;
+		control_req->wValue = cpu_to_le16(0x0200);
+		control_req->wIndex = cpu_to_le16(0x0001);
+		control_req->wLength = cpu_to_le16(0x0008);
+
+		/* control pipe is endpoint 0x00 */
+		pipe = usb_sndctrlpipe(context->usbdev_intf0, 0);
+
+		/* build the control urb */
+		usb_fill_control_urb(context->tx_urb, context->usbdev_intf0, pipe,
+				     (unsigned char *)control_req,
+				     context->usb_tx_buf,
+				     sizeof(context->usb_tx_buf),
+				     usb_tx_callback, context);
+		context->tx_urb->actual_length = 0;
+	}
+
+	init_completion(&context->tx.finished);
+	atomic_set(&(context->tx.busy), 1);
+
+	retval = usb_submit_urb(context->tx_urb, GFP_KERNEL);
+	if (retval) {
+		atomic_set(&(context->tx.busy), 0);
+		err("%s: error submitting urb(%d)", __func__, retval);
+	} else {
+		/* Wait for transmission to complete (or abort) */
+		mutex_unlock(&context->lock);
+		retval = wait_for_completion_interruptible(
+				&context->tx.finished);
+		if (retval)
+			err("%s: task interrupted", __func__);
+		mutex_lock(&context->lock);
+
+		retval = context->tx.status;
+		if (retval)
+			err("%s: packet tx failed (%d)", __func__, retval);
+	}
+
+	kfree(control_req);
+
+	return retval;
+}
+
+/**
+ * Sends an associate packet to the iMON 2.4G.
+ *
+ * This might not be such a good idea, since it has an id collision with
+ * some versions of the "IR & VFD" combo. The only way to determine if it
+ * is an RF version is to look at the product description string. (Which
+ * we currently do not fetch).
+ */
+static int send_associate_24g(struct imon_context *context)
+{
+	int retval;
+	const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x20 };
+
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	if (!context->dev_present_intf0) {
+		err("%s: no iMON device present", __func__);
+		return -ENODEV;
+	}
+
+	memcpy(context->usb_tx_buf, packet, sizeof(packet));
+	retval = send_packet(context);
+
+	return retval;
+}
+
+/**
+ * Sends packets to setup and show clock on iMON display
+ *
+ * Arguments: year - last 2 digits of year, month - 1..12,
+ * day - 1..31, dow - day of the week (0-Sun...6-Sat),
+ * hour - 0..23, minute - 0..59, second - 0..59
+ */
+static int send_set_imon_clock(struct imon_context *context,
+			       unsigned int year, unsigned int month,
+			       unsigned int day, unsigned int dow,
+			       unsigned int hour, unsigned int minute,
+			       unsigned int second)
+{
+	unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8];
+	int retval = 0;
+	int i;
+
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	switch(context->display_type) {
+	case IMON_DISPLAY_TYPE_LCD:
+		clock_enable_pkt[0][0] = 0x80;
+		clock_enable_pkt[0][1] = year;
+		clock_enable_pkt[0][2] = month-1;
+		clock_enable_pkt[0][3] = day;
+		clock_enable_pkt[0][4] = hour;
+		clock_enable_pkt[0][5] = minute;
+		clock_enable_pkt[0][6] = second;
+
+		clock_enable_pkt[1][0] = 0x80;
+		clock_enable_pkt[1][1] = 0;
+		clock_enable_pkt[1][2] = 0;
+		clock_enable_pkt[1][3] = 0;
+		clock_enable_pkt[1][4] = 0;
+		clock_enable_pkt[1][5] = 0;
+		clock_enable_pkt[1][6] = 0;
+
+		if (context->ffdc_dev) {
+			clock_enable_pkt[0][7] = 0x50;
+			clock_enable_pkt[1][7] = 0x51;
+		} else {
+			clock_enable_pkt[0][7] = 0x88;
+			clock_enable_pkt[1][7] = 0x8a;
+		}
+
+		break;
+
+	case IMON_DISPLAY_TYPE_VFD:
+		clock_enable_pkt[0][0] = year;
+		clock_enable_pkt[0][1] = month-1;
+		clock_enable_pkt[0][2] = day;
+		clock_enable_pkt[0][3] = dow;
+		clock_enable_pkt[0][4] = hour;
+		clock_enable_pkt[0][5] = minute;
+		clock_enable_pkt[0][6] = second;
+		clock_enable_pkt[0][7] = 0x40;
+
+		clock_enable_pkt[1][0] = 0;
+		clock_enable_pkt[1][1] = 0;
+		clock_enable_pkt[1][2] = 1;
+		clock_enable_pkt[1][3] = 0;
+		clock_enable_pkt[1][4] = 0;
+		clock_enable_pkt[1][5] = 0;
+		clock_enable_pkt[1][6] = 0;
+		clock_enable_pkt[1][7] = 0x42;
+
+		break;
+
+	default:
+		return -ENODEV;
+	}
+
+
+	for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) {
+		memcpy(context->usb_tx_buf, clock_enable_pkt[i], 8);
+		retval = send_packet(context);
+		if (retval) {
+			err("%s: send_packet failed for packet %d",
+			    __func__, i);
+			break;
+		}
+	}
+
+	return retval;
+
+}
+
+/**
+ * These are the sysfs functions to handle the association on the iMON 2.4G LT.
+ */
+static ssize_t show_associate_remote(struct device *d,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct imon_context *context = dev_get_drvdata(d);
+
+	if (!context)
+		return -ENODEV;
+
+	mutex_lock(&context->lock);
+	if (context->ir_isassociating) {
+		strcpy(buf, "associating\n");
+	} else if (context->ir_isopen) {
+		strcpy(buf, "open\n");
+	} else {
+		strcpy(buf, "closed\n");
+	}
+	printk(KERN_INFO "Visit http://www.lirc.org/html/imon-24g.html for "
+	       "instructions on how to associate your iMON 2.4G DT/LT "
+	       "remote\n");
+	mutex_unlock(&context->lock);
+	return strlen(buf);
+}
+
+static ssize_t store_associate_remote(struct device *d,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct imon_context *context;
+
+	context = dev_get_drvdata(d);
+
+	if (!context)
+		return -ENODEV;
+
+	mutex_lock(&context->lock);
+	if (!context->ir_isopen) {
+		mutex_unlock(&context->lock);
+		return -EINVAL;
+	}
+
+	if (context->ir_isopen) {
+		context->ir_isassociating = 1;
+		send_associate_24g(context);
+	}
+	mutex_unlock(&context->lock);
+
+	return count;
+}
+
+/**
+ * sysfs functions to control internal imon clock
+ */
+static ssize_t show_imon_clock(struct device *d,
+			       struct device_attribute *attr, char *buf)
+{
+	struct imon_context *context = dev_get_drvdata(d);
+	size_t len;
+
+	if (!context)
+		return -ENODEV;
+
+	mutex_lock(&context->lock);
+
+	if (!context->display_supported) {
+		len = snprintf(buf, PAGE_SIZE, "Not supported.");
+	} else {
+		len = snprintf(buf, PAGE_SIZE,
+			"To set the clock on your iMON display:\n"
+			"# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n"
+			"%s", context->display_isopen ?
+			"\nNOTE: imon device must be closed\n" : "");
+	}
+
+	mutex_unlock(&context->lock);
+
+	return len;
+}
+
+static ssize_t store_imon_clock(struct device *d,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct imon_context *context = dev_get_drvdata(d);
+	ssize_t retval;
+	unsigned int year, month, day, dow, hour, minute, second;
+
+	if (!context)
+		return -ENODEV;
+
+	mutex_lock(&context->lock);
+
+	if (!context->display_supported) {
+		retval = -ENODEV;
+		goto exit;
+	} else if (context->display_isopen) {
+		retval = -EBUSY;
+		goto exit;
+	}
+
+	if (sscanf(buf, "%u %u %u %u %u %u %u",	&year, &month, &day, &dow,
+		   &hour, &minute, &second) != 7) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if ((month < 1 || month > 12) ||
+	    (day < 1 || day > 31) || (dow > 6) ||
+	    (hour > 23) || (minute > 59) || (second > 59)) {
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	retval = send_set_imon_clock(context, year, month, day, dow,
+				     hour, minute, second);
+	if (retval)
+		goto exit;
+
+	retval = count;
+exit:
+	mutex_unlock(&context->lock);
+
+	return retval;
+}
+
+
+static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock,
+		   store_imon_clock);
+
+static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote,
+		   store_associate_remote);
+
+static struct attribute *imon_display_sysfs_entries[] = {
+	&dev_attr_imon_clock.attr,
+	NULL
+};
+
+static struct attribute_group imon_display_attribute_group = {
+	.attrs = imon_display_sysfs_entries
+};
+
+static struct attribute *imon_rf_sysfs_entries[] = {
+	&dev_attr_associate_remote.attr,
+	NULL
+};
+
+static struct attribute_group imon_rf_attribute_group = {
+	.attrs = imon_rf_sysfs_entries
+};
+
+/**
+ * Writes data to the VFD.  The iMON VFD is 2x16 characters
+ * and requires data in 5 consecutive USB interrupt packets,
+ * each packet but the last carrying 7 bytes.
+ *
+ * I don't know if the VFD board supports features such as
+ * scrolling, clearing rows, blanking, etc. so at
+ * the caller must provide a full screen of data.  If fewer
+ * than 32 bytes are provided spaces will be appended to
+ * generate a full screen.
+ */
+static ssize_t vfd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos)
+{
+	int i;
+	int offset;
+	int seq;
+	int retval = 0;
+	struct imon_context *context;
+	const unsigned char vfd_packet6[] = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+
+	context = (struct imon_context *)file->private_data;
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->dev_present_intf0) {
+		err("%s: no iMON device present", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (n_bytes <= 0 || n_bytes > 32) {
+		err("%s: invalid payload size", __func__);
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(context->tx.data_buf, buf, n_bytes)) {
+		retval = -EFAULT;
+		goto exit;
+	}
+
+	/* Pad with spaces */
+	for (i = n_bytes; i < 32; ++i)
+		context->tx.data_buf[i] = ' ';
+
+	for (i = 32; i < 35; ++i)
+		context->tx.data_buf[i] = 0xFF;
+
+	offset = 0;
+	seq = 0;
+
+	do {
+		memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7);
+		context->usb_tx_buf[7] = (unsigned char) seq;
+
+		retval = send_packet(context);
+		if (retval) {
+			err("%s: send packet failed for packet #%d",
+					__func__, seq/2);
+			goto exit;
+		} else {
+			seq += 2;
+			offset += 7;
+		}
+
+	} while (offset < 35);
+
+	if (context->vfd_proto_6p) {
+		/* Send packet #6 */
+		memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6));
+		context->usb_tx_buf[7] = (unsigned char) seq;
+		retval = send_packet(context);
+		if (retval)
+			err("%s: send packet failed for packet #%d",
+					__func__, seq/2);
+	}
+
+exit:
+	mutex_unlock(&context->lock);
+
+	return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Writes data to the LCD.  The iMON OEM LCD screen excepts 8-byte
+ * packets. We accept data as 16 hexadecimal digits, followed by a
+ * newline (to make it easy to drive the device from a command-line
+ * -- even though the actual binary data is a bit complicated).
+ *
+ * The device itself is not a "traditional" text-mode display. It's
+ * actually a 16x96 pixel bitmap display. That means if you want to
+ * display text, you've got to have your own "font" and translate the
+ * text into bitmaps for display. This is really flexible (you can
+ * display whatever diacritics you need, and so on), but it's also
+ * a lot more complicated than most LCDs...
+ */
+static ssize_t lcd_write(struct file *file, const char *buf,
+			 size_t n_bytes, loff_t *pos)
+{
+	int retval = 0;
+	struct imon_context *context;
+
+	context = (struct imon_context *)file->private_data;
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->display_supported) {
+		err("%s: no iMON display present", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (n_bytes != 8) {
+		err("%s: invalid payload size: %d (expecting 8)",
+		    __func__, (int) n_bytes);
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	if (copy_from_user(context->usb_tx_buf, buf, 8)) {
+		retval = -EFAULT;
+		goto exit;
+	}
+
+	retval = send_packet(context);
+	if (retval) {
+		err("%s: send packet failed!", __func__);
+		goto exit;
+	} else {
+		dprintk("%s: write %d bytes to LCD\n", __func__, (int) n_bytes);
+	}
+exit:
+	mutex_unlock(&context->lock);
+	return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Callback function for USB core API: transmit data
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_tx_callback(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_tx_callback(struct urb *urb)
+#endif
+{
+	struct imon_context *context;
+
+	if (!urb)
+		return;
+	context = (struct imon_context *)urb->context;
+	if (!context)
+		return;
+
+	context->tx.status = urb->status;
+
+	/* notify waiters that write has finished */
+	atomic_set(&context->tx.busy, 0);
+	complete(&context->tx.finished);
+
+	return;
+}
+
+/**
+ * iMON IR receivers support two different signal sets -- those used by
+ * the iMON remotes, and those used by the Windows MCE remotes (which is
+ * really just RC-6), but only one or the other at a time, as the signals
+ * are decoded onboard the receiver.
+ */
+static void imon_set_ir_protocol(struct imon_context *context)
+{
+	int retval;
+	unsigned char ir_proto_packet[] =
+		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
+
+	switch (ir_protocol) {
+	case IMON_IR_PROTOCOL_MCE:
+		/* MCE proto not supported on devices without tx control */
+		if (!context->tx_control) {
+			printk(KERN_INFO "%s: MCE IR protocol not supported on "
+			       "this device, using iMON protocol\n", __func__);
+			context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+			return;
+		}
+		dprintk("Configuring IR receiver for MCE protocol\n");
+		ir_proto_packet[0] = 0x01;
+		context->ir_protocol = IMON_IR_PROTOCOL_MCE;
+		break;
+	case IMON_IR_PROTOCOL_IMON:
+		dprintk("Configuring IR receiver for iMON protocol\n");
+		/* ir_proto_packet[0] = 0x00; // already the default */
+		context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+		break;
+	case IMON_IR_PROTOCOL_IMON_NOPAD:
+		dprintk("Configuring IR receiver for iMON protocol without "
+			"PAD stabilize function enabled\n");
+		/* ir_proto_packet[0] = 0x00; // already the default */
+		context->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD;
+		break;
+	default:
+		printk(KERN_INFO "%s: unknown IR protocol specified, will "
+		       "just default to iMON protocol\n", __func__);
+		context->ir_protocol = IMON_IR_PROTOCOL_IMON;
+		break;
+	}
+	memcpy(context->usb_tx_buf, &ir_proto_packet,
+	       sizeof(ir_proto_packet));
+	retval = send_packet(context);
+	if (retval)
+		printk(KERN_INFO "%s: failed to set remote type\n", __func__);
+}
+
+
+/**
+ * Called by lirc_dev when the application opens /dev/lirc
+ */
+static int ir_open(void *data)
+{
+	int retval = 0;
+	struct imon_context *context;
+
+	/* prevent races with disconnect */
+	mutex_lock(&driver_lock);
+
+	context = (struct imon_context *)data;
+
+	/* initial IR protocol decode variables */
+	context->rx.count = 0;
+	context->rx.initial_space = 1;
+	context->rx.prev_bit = 0;
+
+	/* set new IR protocol if it has changed since init or last open */
+	if (ir_protocol != context->ir_protocol)
+		imon_set_ir_protocol(context);
+
+	context->ir_isopen = 1;
+	printk(KERN_INFO MOD_NAME ": IR port opened\n");
+
+	mutex_unlock(&driver_lock);
+	return retval;
+}
+
+/**
+ * Called by lirc_dev when the application closes /dev/lirc
+ */
+static void ir_close(void *data)
+{
+	struct imon_context *context;
+
+	context = (struct imon_context *)data;
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return;
+	}
+
+	mutex_lock(&context->lock);
+
+	context->ir_isopen = 0;
+	context->ir_isassociating = 0;
+	MOD_DEC_USE_COUNT;
+	printk(KERN_INFO MOD_NAME ": IR port closed\n");
+
+	if (!context->dev_present_intf0) {
+		/*
+		 * Device disconnected while IR port was still open. Driver
+		 * was not deregistered at disconnect time, so do it now.
+		 */
+		deregister_from_lirc(context);
+
+		if (!context->display_isopen) {
+			mutex_unlock(&context->lock);
+			free_imon_context(context);
+			return;
+		}
+		/*
+		 * If display port is open, context will be deleted by
+		 * display_close
+		 */
+	}
+
+	mutex_unlock(&context->lock);
+	return;
+}
+
+/**
+ * Convert bit count to time duration (in us) and submit
+ * the value to lirc_dev.
+ */
+static void submit_data(struct imon_context *context)
+{
+	unsigned char buf[4];
+	int value = context->rx.count;
+	int i;
+
+	dprintk("submitting data to LIRC\n");
+
+	value *= BIT_DURATION;
+	value &= PULSE_MASK;
+	if (context->rx.prev_bit)
+		value |= PULSE_BIT;
+
+	for (i = 0; i < 4; ++i)
+		buf[i] = value>>(i*8);
+
+	lirc_buffer_write(context->driver->rbuf, buf);
+	wake_up(&context->driver->rbuf->wait_poll);
+	return;
+}
+
+static inline int tv2int(const struct timeval *a, const struct timeval *b)
+{
+	int usecs = 0;
+	int sec   = 0;
+
+	if (b->tv_usec > a->tv_usec) {
+		usecs = 1000000;
+		sec--;
+	}
+
+	usecs += a->tv_usec - b->tv_usec;
+
+	sec += a->tv_sec - b->tv_sec;
+	sec *= 1000;
+	usecs /= 1000;
+	sec += usecs;
+
+	if (sec < 0)
+		sec = 1000;
+
+	return sec;
+}
+
+/**
+ * The directional pad behaves a bit differently, depending on whether this is
+ * one of the older ffdc devices or a newer device. Newer devices appear to
+ * have a higher resolution matrix for more precise mouse movement, but it
+ * makes things overly sensitive in keyboard mode, so we do some interesting
+ * contortions to make it less touchy. Older devices run through the same
+ * routine with shorter timeout and a smaller threshold.
+ */
+static int stabilize(int a, int b, u16 timeout, u16 threshold)
+{
+	struct timeval ct;
+	static struct timeval prev_time = {0, 0};
+	static struct timeval hit_time  = {0, 0};
+	static int x, y, prev_result, hits;
+	int result = 0;
+	int msec, msec_hit;
+
+	do_gettimeofday(&ct);
+	msec = tv2int(&ct, &prev_time);
+	msec_hit = tv2int(&ct, &hit_time);
+
+	if (msec > 100) {
+		x = 0;
+		y = 0;
+		hits = 0;
+	}
+
+	x += a;
+	y += b;
+
+	prev_time = ct;
+
+	if (abs(x) > threshold || abs(y) > threshold) {
+		if (abs(y) > abs(x))
+			result = (y > 0) ? 0x7F : 0x80;
+		else
+			result = (x > 0) ? 0x7F00 : 0x8000;
+
+		x = 0;
+		y = 0;
+
+		if (result == prev_result) {
+			hits++;
+
+			if (hits > 3) {
+				switch (result) {
+				case 0x7F:
+					y = 17 * threshold / 30;
+					break;
+				case 0x80:
+					y -= 17 * threshold / 30;
+					break;
+				case 0x7F00:
+					x = 17 * threshold / 30;
+					break;
+				case 0x8000:
+					x -= 17 * threshold / 30;
+					break;
+				}
+			}
+
+			if (hits == 2 && msec_hit < timeout) {
+				result = 0;
+				hits = 1;
+			}
+		} else {
+			prev_result = result;
+			hits = 1;
+			hit_time = ct;
+		}
+	}
+
+	return result;
+}
+
+/**
+ * Process the incoming packet
+ */
+static void imon_incoming_packet(struct imon_context *context,
+				 struct urb *urb, int intf)
+{
+	int len = urb->actual_length;
+	unsigned char *buf = urb->transfer_buffer;
+	char rel_x = 0x00, rel_y = 0x00;
+	int octet, bit;
+	unsigned char mask;
+	int i, chunk_num;
+	int ts_input = 0;
+	int dir = 0;
+	u16 timeout, threshold;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	int mouse_input;
+	int right_shift = 1;
+	struct input_dev *mouse = NULL;
+	struct input_dev *touch = NULL;
+	const unsigned char toggle_button1[] = { 0x29, 0x91, 0x15, 0xb7 };
+	const unsigned char toggle_button2[] = { 0x29, 0x91, 0x35, 0xb7 };
+	const unsigned char ch_up[]   = { 0x28, 0x93, 0x95, 0xb7 };
+	const unsigned char ch_down[] = { 0x28, 0x87, 0x95, 0xb7 };
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	mouse = context->mouse;
+	if (context->display_type == IMON_DISPLAY_TYPE_VGA)
+		touch = context->touch;
+
+	/* keyboard/mouse mode toggle button */
+	if (memcmp(buf, toggle_button1, 4) == 0 ||
+	    memcmp(buf, toggle_button2, 4) == 0) {
+		if (!nomouse) {
+			context->pad_mouse = ~(context->pad_mouse) & 0x1;
+			dprintk("toggling to %s mode\n",
+				context->pad_mouse ? "mouse" : "keyboard");
+		} else {
+			context->pad_mouse = 0;
+			dprintk("mouse mode was disabled by modparam\n");
+		}
+		return;
+	}
+
+	/* send touchscreen events through input subsystem if touchpad data */
+	if (context->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
+	    buf[7] == 0x86) {
+		if (touch == NULL) {
+			printk(KERN_WARNING "%s: touchscreen input device is "
+			       "NULL!\n", __func__);
+			return;
+		}
+		mod_timer(&context->timer, jiffies + TOUCH_TIMEOUT);
+		context->touch_x = (buf[0] << 4) | (buf[1] >> 4);
+		context->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf));
+		input_report_abs(touch, ABS_X, context->touch_x);
+		input_report_abs(touch, ABS_Y, context->touch_y);
+		input_report_key(touch, BTN_TOUCH, 0x01);
+		input_sync(touch);
+		ts_input = 1;
+
+	/* send mouse events through input subsystem in mouse mode */
+	} else if (context->pad_mouse || !context->ir_isopen) {
+		/* newer iMON device PAD or mouse button */
+		if (!context->ffdc_dev && (buf[0] & 0x01) && len == 5) {
+			mouse_input = 1;
+			rel_x = buf[2];
+			rel_y = buf[3];
+			right_shift = 1;
+		/* 0xffdc iMON PAD or mouse button input */
+		} else if (context->ffdc_dev && (buf[0] & 0x40) &&
+			   !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) {
+			mouse_input = 1;
+			rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
+				(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+			if (buf[0] & 0x02)
+				rel_x |= ~0x0f;
+			rel_x = rel_x + rel_x / 2;
+			rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
+				(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+			if (buf[0] & 0x01)
+				rel_y |= ~0x0f;
+			rel_y = rel_y + rel_y / 2;
+			right_shift = 2;
+		/* some ffdc devices decode mouse buttons differently... */
+		} else if (context->ffdc_dev && (buf[0] == 0x68)) {
+			mouse_input = 1;
+			right_shift = 2;
+		/* ch+/- buttons, which we use for an emulated scroll wheel */
+		} else if (!memcmp(buf, ch_up, 4)) {
+			mouse_input = 1;
+			dir = 1;
+		} else if (!memcmp(buf, ch_down, 4)) {
+			mouse_input = 1;
+			dir = -1;
+		} else
+			mouse_input = 0;
+
+		if (mouse_input) {
+			if (mouse == NULL) {
+				printk(KERN_WARNING "%s: mouse input device "
+				       "is NULL!\n", __func__);
+				return;
+			}
+			dprintk("sending mouse data via input subsystem\n");
+
+			if (dir) {
+				input_report_rel(mouse, REL_WHEEL, dir);
+			} else if (rel_x || rel_y) {
+				input_report_rel(mouse, REL_X, rel_x);
+				input_report_rel(mouse, REL_Y, rel_y);
+			} else {
+				input_report_key(mouse, BTN_LEFT, buf[1] & 0x1);
+				input_report_key(mouse, BTN_RIGHT,
+						 buf[1] >> right_shift & 0x1);
+			}
+			input_sync(mouse);
+			return;
+		}
+	}
+#endif
+
+	/*
+	 * at this point, mouse and touchscreen input has been handled, so
+	 * anything else goes to lirc -- bail out if no listening IR client
+	 */
+	if (!context->ir_isopen)
+		return;
+
+	/*
+	 * we need to add some special handling for
+	 * the imon's IR mouse events
+	 */
+	if ((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) {
+		/* first, pad to 8 bytes so it conforms with everything else */
+		buf[5] = buf[6] = buf[7] = 0;
+		len = 8;
+		timeout = 500;	/* in msecs */
+		/* (2*threshold) x (2*threshold) square */
+		threshold = pad_thresh ? pad_thresh : 28;
+		rel_x = buf[2];
+		rel_y = buf[3];
+
+		/*
+		 * the imon directional pad functions more like a touchpad.
+		 * Bytes 3 & 4 contain a position coordinate (x,y), with each
+		 * component ranging from -14 to 14. Since this doesn't
+		 * cooperate well with the way lirc works (it would appear to
+		 * lirc as more than 100 different buttons) we need to map it
+		 * to 4 discrete values. Also, when you get too close to
+		 * diagonals, it has a tendancy to jump back and forth, so lets
+		 * try to ignore when they get too close
+		 */
+		if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
+			if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) {
+				dir = stabilize((int)rel_x, (int)rel_y,
+						timeout, threshold);
+				if (!dir)
+					return;
+				buf[2] = dir & 0xFF;
+				buf[3] = (dir >> 8) & 0xFF;
+			}
+		} else {
+			if (abs(rel_y) > abs(rel_x)) {
+				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+				buf[3] = 0;
+			} else {
+				buf[2] = 0;
+				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+			}
+		}
+
+	} else if ((len == 8) && (buf[0] & 0x40) &&
+		   !(buf[1] & 0x01 || buf[1] >> 2 & 0x01)) {
+		/*
+		 * Handle on-board decoded pad events for e.g. older
+		 * VFD/iMON-Pad (15c2:ffdc). The remote generates various codes
+		 * from 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button
+		 * generates 0x688301b7 and the right one 0x688481b7. All other
+		 * keys generate 0x2nnnnnnn. Length has been padded to 8
+		 * already, position coordinate is encoded in buf[1] and buf[2]
+		 * with reversed endianess. Extract direction from buffer,
+		 * rotate endianess, adjust sign and feed the values into
+		 * stabilize(). The resulting codes will be 0x01008000,
+		 * 0x01007F00, ..., so one can use the normal imon-pad config
+		 * from the remotes dir.
+		 */
+		timeout = 10;	/* in msecs */
+		/* (2*threshold) x (2*threshold) square */
+		threshold = pad_thresh ? pad_thresh : 15;
+
+		/* buf[1] is x */
+		rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 |
+			(buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6;
+		if(buf[0] & 0x02)
+			rel_x |= ~0x10+1;
+		/* buf[2] is y */
+		rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 |
+			(buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6;
+		if(buf[0] & 0x01)
+			rel_y |= ~0x10+1;
+
+		buf[0] = 0x01;
+		buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0;
+
+		if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) {
+			dir = stabilize((int)rel_x, (int)rel_y,
+					timeout, threshold);
+			if (!dir)
+				return;
+			buf[2] = dir & 0xFF;
+			buf[3] = (dir >> 8) & 0xFF;
+		} else {
+			if (abs(rel_y) > abs(rel_x)) {
+				buf[2] = (rel_y > 0) ? 0x7F : 0x80;
+				buf[3] = 0;
+			} else {
+				buf[2] = 0;
+				buf[3] = (rel_x > 0) ? 0x7F : 0x80;
+			}
+		}
+
+	} else if (ts_input) {
+		/*
+		 * this is touchscreen input, which we need to down-sample
+		 * to a 64 button matrix at the moment...
+		 */
+		buf[0] = buf[0] >> 5;
+		buf[1] = 0x00;
+		buf[2] = buf[2] >> 5;
+		buf[3] = 0x00;
+		buf[4] = 0x00;
+		buf[5] = 0x00;
+		buf[6] = 0x14;
+		buf[7] = 0xff;
+	}
+
+	if (len != 8) {
+		printk(KERN_WARNING "imon %s: invalid incoming packet "
+		       "size (len = %d, intf%d)\n", __func__, len, intf);
+		return;
+	}
+
+	/* iMON 2.4G associate frame */
+	if (buf[0] == 0x00 &&
+	    buf[2] == 0xFF &&				/* REFID */
+	    buf[3] == 0xFF &&
+	    buf[4] == 0xFF &&
+	    buf[5] == 0xFF &&				/* iMON 2.4G */
+	   ((buf[6] == 0x4E && buf[7] == 0xDF) ||	/* LT */
+	    (buf[6] == 0x5E && buf[7] == 0xDF))) {	/* DT */
+		printk(KERN_WARNING "%s: remote associated refid=%02X\n",
+		       __func__, buf[1]);
+		context->ir_isassociating = 0;
+	}
+
+	chunk_num = buf[7];
+
+	if (chunk_num == 0xFF && !ts_input)
+		return;		/* filler frame, no data here */
+
+	if (buf[0] == 0xFF &&
+	    buf[1] == 0xFF &&
+	    buf[2] == 0xFF &&
+	    buf[3] == 0xFF &&
+	    buf[4] == 0xFF &&
+	    buf[5] == 0xFF &&				/* iMON 2.4G */
+	    ((buf[6] == 0x4E && buf[7] == 0xAF) ||	/* LT */
+	     (buf[6] == 0x5E && buf[7] == 0xAF)))	/* DT */
+		return;		/* filler frame, no data here */
+
+	if (debug) {
+		if (context->ir_onboard_decode)
+			printk("intf%d decoded packet: ", intf);
+		else
+			printk("raw packet: ");
+		for (i = 0; i < len; ++i)
+			printk("%02x ", buf[i]);
+		printk("\n");
+	}
+
+	if (context->ir_onboard_decode) {
+		/* The signals have been decoded onboard the iMON controller */
+		lirc_buffer_write(context->driver->rbuf, buf);
+		wake_up(&context->driver->rbuf->wait_poll);
+		return;
+	}
+
+	/*
+	 * Translate received data to pulse and space lengths.
+	 * Received data is active low, i.e. pulses are 0 and
+	 * spaces are 1.
+	 *
+	 * My original algorithm was essentially similar to
+	 * Changwoo Ryu's with the exception that he switched
+	 * the incoming bits to active high and also fed an
+	 * initial space to LIRC at the start of a new sequence
+	 * if the previous bit was a pulse.
+	 *
+	 * I've decided to adopt his algorithm.
+	 */
+
+	if (chunk_num == 1 && context->rx.initial_space) {
+		/* LIRC requires a leading space */
+		context->rx.prev_bit = 0;
+		context->rx.count = 4;
+		submit_data(context);
+		context->rx.count = 0;
+	}
+
+	for (octet = 0; octet < 5; ++octet) {
+		mask = 0x80;
+		for (bit = 0; bit < 8; ++bit) {
+			int curr_bit = !(buf[octet] & mask);
+			if (curr_bit != context->rx.prev_bit) {
+				if (context->rx.count) {
+					submit_data(context);
+					context->rx.count = 0;
+				}
+				context->rx.prev_bit = curr_bit;
+			}
+			++context->rx.count;
+			mask >>= 1;
+		}
+	}
+
+	if (chunk_num == 10) {
+		if (context->rx.count) {
+			submit_data(context);
+			context->rx.count = 0;
+		}
+		context->rx.initial_space = context->rx.prev_bit;
+	}
+}
+
+/**
+ * report touchscreen input
+ */
+static void imon_touch_display_timeout(unsigned long data)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	struct imon_context *context = (struct imon_context *)data;
+	struct input_dev *touch;
+
+	if (!context->display_type == IMON_DISPLAY_TYPE_VGA)
+		return;
+
+	touch = context->touch;
+	input_report_abs(touch, ABS_X, context->touch_x);
+	input_report_abs(touch, ABS_Y, context->touch_y);
+	input_report_key(touch, BTN_TOUCH, 0x00);
+	input_sync(touch);
+#endif
+
+	return;
+}
+
+/**
+ * Callback function for USB core API: receive data
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_rx_callback_intf0(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_rx_callback_intf0(struct urb *urb)
+#endif
+{
+	struct imon_context *context;
+	unsigned char *buf;
+	int len;
+	int intfnum = 0;
+
+	if (!urb)
+		return;
+
+	context = (struct imon_context *)urb->context;
+	if (!context)
+		return;
+
+	buf = urb->transfer_buffer;
+	len = urb->actual_length;
+
+	switch (urb->status) {
+	case -ENOENT:		/* usbcore unlink successful! */
+		return;
+
+	case 0:
+		imon_incoming_packet(context, urb, intfnum);
+		break;
+
+	default:
+		printk(KERN_WARNING "imon %s: status(%d): ignored\n",
+		       __func__, urb->status);
+		break;
+	}
+
+	usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
+
+	return;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_rx_callback_intf1(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_rx_callback_intf1(struct urb *urb)
+#endif
+{
+	struct imon_context *context;
+	unsigned char *buf;
+	int len;
+	int intfnum = 1;
+
+	if (!urb)
+		return;
+
+	context = (struct imon_context *)urb->context;
+	if (!context)
+		return;
+
+	buf = urb->transfer_buffer;
+	len = urb->actual_length;
+
+	switch (urb->status) {
+	case -ENOENT:		/* usbcore unlink successful! */
+		return;
+
+	case 0:
+		imon_incoming_packet(context, urb, intfnum);
+		break;
+
+	default:
+		printk(KERN_WARNING "imon %s: status(%d): ignored\n",
+		       __func__, urb->status);
+		break;
+	}
+
+	usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
+
+	return;
+}
+
+/**
+ * Callback function for USB core API: Probe
+ */
+static int imon_probe(struct usb_interface *interface,
+		      const struct usb_device_id *id)
+{
+	struct usb_device *usbdev = NULL;
+	struct usb_host_interface *iface_desc = NULL;
+	struct usb_endpoint_descriptor *rx_endpoint = NULL;
+	struct usb_endpoint_descriptor *tx_endpoint = NULL;
+	struct urb *rx_urb = NULL;
+	struct urb *tx_urb = NULL;
+	struct lirc_driver *driver = NULL;
+	struct lirc_buffer *rbuf = NULL;
+	struct usb_interface *first_if;
+	int ifnum;
+	int lirc_minor = 0;
+	int num_endpts;
+	int retval = 0;
+	int display_ep_found = 0;
+	int ir_ep_found = 0;
+	int alloc_status = 0;
+	int vfd_proto_6p = 0;
+	int ir_onboard_decode = 0;
+	int buf_chunk_size = BUF_CHUNK_SIZE;
+	int code_length;
+	int tx_control = 0;
+	struct imon_context *context = NULL;
+	struct imon_context *first_if_context = NULL;
+	int i, sysfs_err;
+	int configured_display_type = IMON_DISPLAY_TYPE_VFD;
+	u16 vendor, product;
+	const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+					    0x00, 0x00, 0x00, 0x88 };
+
+	/*
+	 * Try to auto-detect the type of display if the user hasn't set
+	 * it by hand via the display_type modparam. Default is VFD.
+	 */
+	if (display_type == IMON_DISPLAY_TYPE_AUTO) {
+		if (usb_match_id(interface, lcd_device_list))
+			configured_display_type = IMON_DISPLAY_TYPE_LCD;
+		else if (usb_match_id(interface, imon_touchscreen_list))
+			configured_display_type = IMON_DISPLAY_TYPE_VGA;
+		else if (usb_match_id(interface, ir_only_list))
+			configured_display_type = IMON_DISPLAY_TYPE_NONE;
+		else
+			configured_display_type = IMON_DISPLAY_TYPE_VFD;
+	} else {
+		configured_display_type = display_type;
+		dprintk("%s: overriding display type to %d via modparam\n",
+			__func__, display_type);
+	}
+
+	/*
+	 * If it's the LCD, as opposed to the VFD, we just need to replace
+	 * the "write" file op.
+	 */
+	if (configured_display_type == IMON_DISPLAY_TYPE_LCD)
+		display_fops.write = &lcd_write;
+
+	/*
+	 * To get front panel buttons working properly for newer LCD devices,
+	 * we really do need a larger buffer.
+	 */
+	if (usb_match_id(interface, large_buffer_list))
+		buf_chunk_size = 2 * BUF_CHUNK_SIZE;
+
+	code_length = buf_chunk_size * 8;
+
+	usbdev     = usb_get_dev(interface_to_usbdev(interface));
+	iface_desc = interface->cur_altsetting;
+	num_endpts = iface_desc->desc.bNumEndpoints;
+	ifnum      = iface_desc->desc.bInterfaceNumber;
+	vendor     = le16_to_cpu(usbdev->descriptor.idVendor);
+	product    = le16_to_cpu(usbdev->descriptor.idProduct);
+
+	dprintk("%s: found iMON device (%04x:%04x, intf%d)\n",
+		__func__, vendor, product, ifnum);
+
+	/* prevent races probing devices w/multiple interfaces */
+	mutex_lock(&driver_lock);
+
+	first_if = usb_ifnum_to_if(usbdev, 0);
+	first_if_context = (struct imon_context *)usb_get_intfdata(first_if);
+
+	/*
+	 * Scan the endpoint list and set:
+	 *	first input endpoint = IR endpoint
+	 *	first output endpoint = display endpoint
+	 */
+	for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) {
+		struct usb_endpoint_descriptor *ep;
+		int ep_dir;
+		int ep_type;
+		ep = &iface_desc->endpoint[i].desc;
+		ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+		ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+		if (!ir_ep_found &&
+			ep_dir == USB_DIR_IN &&
+			ep_type == USB_ENDPOINT_XFER_INT) {
+
+			rx_endpoint = ep;
+			ir_ep_found = 1;
+			dprintk("%s: found IR endpoint\n", __func__);
+
+		} else if (!display_ep_found &&
+			   ep_dir == USB_DIR_OUT &&
+			   ep_type == USB_ENDPOINT_XFER_INT) {
+			tx_endpoint = ep;
+			display_ep_found = 1;
+			dprintk("%s: found display endpoint\n", __func__);
+		}
+	}
+
+	/*
+	 * If we didn't find a display endpoint, this is probably one of the
+	 * newer iMON devices that use control urb instead of interrupt
+	 */
+	if (!display_ep_found) {
+		if (usb_match_id(interface, ctl_ep_device_list)) {
+			tx_control = 1;
+			display_ep_found = 1;
+			dprintk("%s: device uses control endpoint, not "
+				"interface OUT endpoint\n", __func__);
+		}
+	}
+
+	/*
+	 * Some iMON receivers have no display. Unfortunately, it seems
+	 * that SoundGraph recycles device IDs between devices both with
+	 * and without... :\
+	 */
+	if (configured_display_type == IMON_DISPLAY_TYPE_NONE) {
+		display_ep_found = 0;
+		dprintk("%s: device has no display\n", __func__);
+	}
+
+	/*
+	 * iMON Touch devices have a VGA touchscreen, but no "display", as
+	 * that refers to e.g. /dev/lcd0 (a character device LCD or VFD).
+	 */
+	if (configured_display_type == IMON_DISPLAY_TYPE_VGA) {
+		display_ep_found = 0;
+		dprintk("%s: iMON Touch device found\n", __func__);
+	}
+
+	/* Input endpoint is mandatory */
+	if (!ir_ep_found) {
+		err("%s: no valid input (IR) endpoint found.", __func__);
+		retval = -ENODEV;
+		goto exit;
+	} else {
+		/* Determine if the IR signals are decoded onboard */
+		if (usb_match_id(interface, ir_onboard_decode_list))
+			ir_onboard_decode = 1;
+
+		dprintk("%s: ir_onboard_decode: %d\n",
+			__func__, ir_onboard_decode);
+	}
+
+	/* Determine if display requires 6 packets */
+	if (display_ep_found) {
+		if (usb_match_id(interface, vfd_proto_6p_list))
+			vfd_proto_6p = 1;
+
+		dprintk("%s: vfd_proto_6p: %d\n",
+			__func__, vfd_proto_6p);
+	}
+
+	if (ifnum == 0) {
+		context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
+		if (!context) {
+			err("%s: kzalloc failed for context", __func__);
+			alloc_status = 1;
+			goto alloc_status_switch;
+		}
+		driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+		if (!driver) {
+			err("%s: kzalloc failed for lirc_driver", __func__);
+			alloc_status = 2;
+			goto alloc_status_switch;
+		}
+		rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+		if (!rbuf) {
+			err("%s: kmalloc failed for lirc_buffer", __func__);
+			alloc_status = 3;
+			goto alloc_status_switch;
+		}
+		if (lirc_buffer_init(rbuf, buf_chunk_size, BUF_SIZE)) {
+			err("%s: lirc_buffer_init failed", __func__);
+			alloc_status = 4;
+			goto alloc_status_switch;
+		}
+		rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!rx_urb) {
+			err("%s: usb_alloc_urb failed for IR urb", __func__);
+			alloc_status = 5;
+			goto alloc_status_switch;
+		}
+		tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!tx_urb) {
+			err("%s: usb_alloc_urb failed for display urb",
+			    __func__);
+			alloc_status = 6;
+			goto alloc_status_switch;
+		}
+
+		mutex_init(&context->lock);
+		context->vfd_proto_6p = vfd_proto_6p;
+		context->ir_onboard_decode = ir_onboard_decode;
+
+		strcpy(driver->name, MOD_NAME);
+		driver->minor = -1;
+		driver->code_length = ir_onboard_decode ?
+			code_length : sizeof(int) * 8;
+		driver->sample_rate = 0;
+		driver->features = (ir_onboard_decode) ?
+			LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2;
+		driver->data = context;
+		driver->rbuf = rbuf;
+		driver->set_use_inc = ir_open;
+		driver->set_use_dec = ir_close;
+#ifdef LIRC_HAVE_SYSFS
+		driver->dev = &interface->dev;
+#endif
+		driver->owner = THIS_MODULE;
+
+		mutex_lock(&context->lock);
+
+		context->driver = driver;
+		/* start out in keyboard mode */
+		context->pad_mouse = 0;
+
+		init_timer(&context->timer);
+		context->timer.data = (unsigned long)context;
+		context->timer.function = imon_touch_display_timeout;
+
+		lirc_minor = lirc_register_driver(driver);
+		if (lirc_minor < 0) {
+			err("%s: lirc_register_driver failed", __func__);
+			alloc_status = 7;
+			goto alloc_status_switch;
+		} else
+			printk(KERN_INFO MOD_NAME ": Registered iMON driver "
+			       "(lirc minor: %d)\n", lirc_minor);
+
+		/* Needed while unregistering! */
+		driver->minor = lirc_minor;
+
+	} else {
+	/* this is the secondary interface on the device */
+		if (first_if_context->driver) {
+			rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (!rx_urb) {
+				err("%s: usb_alloc_urb failed for IR urb",
+				    __func__);
+				alloc_status = 5;
+				goto alloc_status_switch;
+			}
+
+			context = first_if_context;
+		}
+		mutex_lock(&context->lock);
+	}
+
+	if (ifnum == 0) {
+		context->usbdev_intf0 = usbdev;
+		context->dev_present_intf0 = 1;
+		context->rx_endpoint_intf0 = rx_endpoint;
+		context->rx_urb_intf0 = rx_urb;
+
+		/*
+		 * tx is used to send characters to lcd/vfd, associate RF
+		 * remotes, set IR protocol, and maybe more...
+		 */
+		context->tx_endpoint = tx_endpoint;
+		context->tx_urb = tx_urb;
+		context->tx_control = tx_control;
+
+		if (display_ep_found)
+			context->display_supported = 1;
+
+		if (product == 0xffdc)
+			context->ffdc_dev = 1;
+
+		context->display_type = configured_display_type;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+		context->mouse = input_allocate_device();
+
+		snprintf(context->name_mouse, sizeof(context->name_mouse),
+			 "iMON PAD IR Mouse (%04x:%04x)",
+			 vendor, product);
+		context->mouse->name = context->name_mouse;
+
+		usb_make_path(usbdev, context->phys_mouse, sizeof(context->phys_mouse));
+		strlcat(context->phys_mouse, "/input0", sizeof(context->phys_mouse));
+		context->mouse->phys = context->phys_mouse;
+
+		context->mouse->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+		context->mouse->keybit[BIT_WORD(BTN_MOUSE)] =
+			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) |
+			BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) |
+			BIT_MASK(BTN_EXTRA);
+		context->mouse->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) |
+			BIT_MASK(REL_WHEEL);
+
+		input_set_drvdata(context->mouse, context);
+
+		usb_to_input_id(usbdev, &context->mouse->id);
+		context->mouse->dev.parent = &interface->dev;
+		retval = input_register_device(context->mouse);
+		if (retval)
+			printk(KERN_INFO "%s: pad mouse input device setup failed\n",
+			       __func__);
+#endif
+
+		usb_fill_int_urb(context->rx_urb_intf0, context->usbdev_intf0,
+			usb_rcvintpipe(context->usbdev_intf0,
+					context->rx_endpoint_intf0->bEndpointAddress),
+			context->usb_rx_buf, sizeof(context->usb_rx_buf),
+			usb_rx_callback_intf0, context,
+			context->rx_endpoint_intf0->bInterval);
+
+		retval = usb_submit_urb(context->rx_urb_intf0, GFP_KERNEL);
+
+		if (retval) {
+			err("%s: usb_submit_urb failed for intf0 (%d)",
+			    __func__, retval);
+			mutex_unlock(&context->lock);
+			goto exit;
+		}
+
+	} else {
+		context->usbdev_intf1 = usbdev;
+		context->dev_present_intf1 = 1;
+		context->rx_endpoint_intf1 = rx_endpoint;
+		context->rx_urb_intf1 = rx_urb;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+		if (context->display_type == IMON_DISPLAY_TYPE_VGA) {
+			context->touch = input_allocate_device();
+
+			snprintf(context->name_touch, sizeof(context->name_touch),
+				 "iMON USB Touchscreen (%04x:%04x)",
+				 vendor, product);
+			context->touch->name = context->name_touch;
+
+			usb_make_path(usbdev, context->phys_touch,
+				      sizeof(context->phys_touch));
+			strlcat(context->phys_touch, "/input1",
+				sizeof(context->phys_touch));
+			context->touch->phys = context->phys_touch;
+
+			context->touch->evbit[0] =
+				BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+			context->touch->keybit[BIT_WORD(BTN_TOUCH)] =
+				BIT_MASK(BTN_TOUCH);
+			input_set_abs_params(context->touch, ABS_X,
+					     0x00, 0xfff, 0, 0);
+			input_set_abs_params(context->touch, ABS_Y,
+					     0x00, 0xfff, 0, 0);
+
+			input_set_drvdata(context->touch, context);
+
+			usb_to_input_id(usbdev, &context->touch->id);
+			context->touch->dev.parent = &interface->dev;
+			retval = input_register_device(context->touch);
+			if (retval)
+				printk(KERN_INFO "%s: touchscreen input device setup failed\n",
+				       __func__);
+		} else
+			context->touch = NULL;
+#endif
+
+		usb_fill_int_urb(context->rx_urb_intf1, context->usbdev_intf1,
+			usb_rcvintpipe(context->usbdev_intf1,
+				context->rx_endpoint_intf1->bEndpointAddress),
+			context->usb_rx_buf, sizeof(context->usb_rx_buf),
+			usb_rx_callback_intf1, context,
+			context->rx_endpoint_intf1->bInterval);
+
+		retval = usb_submit_urb(context->rx_urb_intf1, GFP_KERNEL);
+
+		if (retval) {
+			err("%s: usb_submit_urb failed for intf1 (%d)",
+			    __func__, retval);
+			mutex_unlock(&context->lock);
+			goto exit;
+		}
+	}
+
+	usb_set_intfdata(interface, context);
+
+	/* RF products *also* use 0xffdc... sigh... */
+	if (context->ffdc_dev) {
+		sysfs_err = sysfs_create_group(&interface->dev.kobj,
+					       &imon_rf_attribute_group);
+		if (sysfs_err)
+			err("%s: Could not create RF sysfs entries(%d)",
+			    __func__, sysfs_err);
+	}
+
+	if (context->display_supported && ifnum == 0) {
+		dprintk("%s: Registering iMON display with sysfs\n", __func__);
+
+		/* set up sysfs entry for built-in clock */
+		sysfs_err = sysfs_create_group(&interface->dev.kobj,
+					       &imon_display_attribute_group);
+		if (sysfs_err)
+			err("%s: Could not create display sysfs entries(%d)",
+			    __func__, sysfs_err);
+
+		if (usb_register_dev(interface, &imon_class)) {
+			/* Not a fatal error, so ignore */
+			printk(KERN_INFO "%s: could not get a minor number for "
+			       "display\n", __func__);
+		}
+
+		/* Enable front-panel buttons and/or knobs */
+		memcpy(context->usb_tx_buf, &fp_packet, sizeof(fp_packet));
+		retval = send_packet(context);
+		/* Not fatal, but warn about it */
+		if (retval)
+			printk(KERN_INFO "%s: failed to enable front-panel "
+			       "buttons and/or knobs\n", __func__);
+	}
+
+	/* set IR protocol/remote type */
+	imon_set_ir_protocol(context);
+
+	printk(KERN_INFO MOD_NAME ": iMON device (%04x:%04x, intf%d) on "
+	       "usb<%d:%d> initialized\n", vendor, product, ifnum,
+	       usbdev->bus->busnum, usbdev->devnum);
+
+alloc_status_switch:
+	mutex_unlock(&context->lock);
+
+	switch (alloc_status) {
+	case 7:
+		usb_free_urb(tx_urb);
+	case 6:
+		usb_free_urb(rx_urb);
+	case 5:
+		if (rbuf)
+			lirc_buffer_free(rbuf);
+	case 4:
+		kfree(rbuf);
+	case 3:
+		kfree(driver);
+	case 2:
+		kfree(context);
+		context = NULL;
+	case 1:
+		retval = -ENOMEM;
+		break;
+	case 0:
+		retval = 0;
+	}
+
+exit:
+	mutex_unlock(&driver_lock);
+
+	return retval;
+}
+
+/**
+ * Callback function for USB core API: disconnect
+ */
+static void imon_disconnect(struct usb_interface *interface)
+{
+	struct imon_context *context;
+	int ifnum;
+
+	/* prevent races with ir_open()/display_open() */
+	mutex_lock(&driver_lock);
+
+	context = usb_get_intfdata(interface);
+	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
+
+	mutex_lock(&context->lock);
+
+	/*
+	 * sysfs_remove_group is safe to call even if sysfs_create_group
+	 * hasn't been called
+	 */
+	sysfs_remove_group(&interface->dev.kobj,
+			   &imon_display_attribute_group);
+	sysfs_remove_group(&interface->dev.kobj,
+			   &imon_rf_attribute_group);
+
+	usb_set_intfdata(interface, NULL);
+
+	/* Abort ongoing write */
+	if (atomic_read(&context->tx.busy)) {
+		usb_kill_urb(context->tx_urb);
+		complete_all(&context->tx.finished);
+	}
+
+	if (ifnum == 0) {
+		context->dev_present_intf0 = 0;
+		usb_kill_urb(context->rx_urb_intf0);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+		input_unregister_device(context->mouse);
+#endif
+		if (context->display_supported)
+			usb_deregister_dev(interface, &imon_class);
+	} else {
+		context->dev_present_intf1 = 0;
+		usb_kill_urb(context->rx_urb_intf1);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+		if (context->display_type == IMON_DISPLAY_TYPE_VGA)
+			input_unregister_device(context->touch);
+#endif
+	}
+
+	if (!context->ir_isopen && !context->dev_present_intf0 &&
+	    !context->dev_present_intf1) {
+		del_timer_sync(&context->timer);
+		deregister_from_lirc(context);
+		mutex_unlock(&context->lock);
+		if (!context->display_isopen)
+			free_imon_context(context);
+	} else
+		mutex_unlock(&context->lock);
+
+	mutex_unlock(&driver_lock);
+
+	printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n",
+	       __func__, ifnum);
+}
+
+static int imon_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct imon_context *context = usb_get_intfdata(intf);
+	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	if (ifnum == 0)
+		usb_kill_urb(context->rx_urb_intf0);
+	else
+		usb_kill_urb(context->rx_urb_intf1);
+
+	return 0;
+}
+
+static int imon_resume(struct usb_interface *intf)
+{
+	int rc = 0;
+	struct imon_context *context = usb_get_intfdata(intf);
+	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+	if (ifnum == 0) {
+		usb_fill_int_urb(context->rx_urb_intf0, context->usbdev_intf0,
+			usb_rcvintpipe(context->usbdev_intf0,
+					context->rx_endpoint_intf0->bEndpointAddress),
+			context->usb_rx_buf, sizeof(context->usb_rx_buf),
+			usb_rx_callback_intf0, context,
+			context->rx_endpoint_intf0->bInterval);
+
+		rc = usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC);
+
+	} else {
+		usb_fill_int_urb(context->rx_urb_intf1, context->usbdev_intf1,
+			usb_rcvintpipe(context->usbdev_intf1,
+				context->rx_endpoint_intf1->bEndpointAddress),
+			context->usb_rx_buf, sizeof(context->usb_rx_buf),
+			usb_rx_callback_intf1, context,
+			context->rx_endpoint_intf1->bInterval);
+
+		rc = usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC);
+	}
+
+	return rc;
+}
+
+static int __init imon_init(void)
+{
+	int rc;
+
+	printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n");
+
+	rc = usb_register(&imon_driver);
+	if (rc) {
+		err("%s: usb register failed(%d)", __func__, rc);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit imon_exit(void)
+{
+	usb_deregister(&imon_driver);
+	printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n");
+}
+
+module_init(imon_init);
+module_exit(imon_exit);
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_imon/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_imon/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_IMON)		+= lirc_imon.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_sasem/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_sasem/Makefile
@@ -0,0 +1,2 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+obj-$(CONFIG_LIRC_SASEM)	+= lirc_sasem.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_sasem/lirc_sasem.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_sasem/lirc_sasem.c
@@ -0,0 +1,1108 @@
+/*      $Id: lirc_sasem.c,v 1.40 2009/02/28 10:27:10 lirc Exp $      */
+/*
+ * lirc_sasem.c - USB remote support for LIRC
+ * Version 0.5
+ *
+ * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de>
+ *			 Tim Davies <tim@opensystems.net.au>
+ *
+ * This driver was derived from:
+ *   Venky Raju <dev@venky.ws>
+ *      "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD"
+ *   Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004
+ *      "lirc_atiusb - USB remote support for LIRC"
+ *   Culver Consulting Services <henry@culcon.com>'s 2003
+ *      "Sasem OnAir VFD/IR USB driver"
+ *
+ *
+ * NOTE - The LCDproc iMon driver should work with this module.  More info at
+ *	http://www.frogstorm.info/sasem
+ */
+
+/*
+ *  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/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22)
+#error "*** Sorry, this driver requires kernel version 2.4.22 or higher"
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#include <linux/usb.h>
+
+#include "../kcompat.h"
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+
+
+#define MOD_AUTHOR	"Oliver Stabel <oliver.stabel@gmx.de>, " \
+			"Tim Davies <tim@opensystems.net.au>"
+#define MOD_DESC	"USB Driver for Sasem Remote Controller V1.1"
+#define MOD_NAME	"lirc_sasem"
+#define MOD_VERSION	"0.5"
+
+#define VFD_MINOR_BASE	144	/* Same as LCD */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
+#define DEVFS_MODE S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
+#endif
+#define DEVFS_NAME	LIRC_DEVFS_PREFIX "lcd%d"
+
+#define BUF_CHUNK_SIZE	8
+#define BUF_SIZE	128
+
+#define IOCTL_LCD_CONTRAST 1
+
+/*** P R O T O T Y P E S ***/
+
+/* USB Callback prototypes */
+#ifdef KERNEL_2_5
+static int sasem_probe(struct usb_interface *interface,
+			const struct usb_device_id *id);
+static void sasem_disconnect(struct usb_interface *interface);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_rx_callback(struct urb *urb, struct pt_regs *regs);
+static void usb_tx_callback(struct urb *urb, struct pt_regs *regs);
+#else
+static void usb_rx_callback(struct urb *urb);
+static void usb_tx_callback(struct urb *urb);
+#endif
+#else
+static void *sasem_probe(struct usb_device *dev, unsigned int intf,
+				const struct usb_device_id *id);
+static void sasem_disconnect(struct usb_device *dev, void *data);
+static void usb_rx_callback(struct urb *urb);
+static void usb_tx_callback(struct urb *urb);
+#endif
+
+/* VFD file_operations function prototypes */
+static int vfd_open(struct inode *inode, struct file *file);
+static int vfd_ioctl(struct inode *inode, struct file *file,
+				unsigned cmd, unsigned long arg);
+static int vfd_close(struct inode *inode, struct file *file);
+static ssize_t vfd_write(struct file *file, const char *buf,
+				size_t n_bytes, loff_t *pos);
+
+/* LIRC driver function prototypes */
+static int ir_open(void *data);
+static void ir_close(void *data);
+
+/* Driver init/exit prototypes */
+static int __init sasem_init(void);
+static void __exit sasem_exit(void);
+
+/*** G L O B A L S ***/
+
+struct sasem_context {
+
+	struct usb_device *dev;
+	int vfd_isopen;			/* VFD port has been opened       */
+	unsigned int vfd_contrast;	/* VFD contrast		   */
+#if !defined(KERNEL_2_5)
+	int subminor;			/* index into minor_table	 */
+	devfs_handle_t devfs;
+#endif
+	int ir_isopen;			/* IR port has been opened	*/
+	int dev_present;		/* USB device presence	    */
+	struct mutex lock;		/* to lock this object	    */
+	wait_queue_head_t remove_ok;	/* For unexpected USB disconnects */
+
+	struct lirc_driver *driver;
+	struct usb_endpoint_descriptor *rx_endpoint;
+	struct usb_endpoint_descriptor *tx_endpoint;
+	struct urb *rx_urb;
+	struct urb *tx_urb;
+	unsigned char usb_rx_buf[8];
+	unsigned char usb_tx_buf[8];
+
+	struct tx_t {
+		unsigned char data_buf[32];  /* user data buffer	  */
+		struct completion finished;  /* wait for write to finish  */
+		atomic_t busy;		     /* write in progress	 */
+		int status;		     /* status of tx completion   */
+	} tx;
+
+	/* for dealing with repeat codes (wish there was a toggle bit!) */
+	struct timeval presstime;
+	char lastcode[8];
+	int codesaved;
+};
+
+/* VFD file operations */
+static struct file_operations vfd_fops = {
+
+	.owner		= THIS_MODULE,
+	.open		= &vfd_open,
+	.write		= &vfd_write,
+	.ioctl		= &vfd_ioctl,
+	.release	= &vfd_close
+};
+
+/* USB Device ID for Sasem USB Control Board */
+static struct usb_device_id sasem_usb_id_table [] = {
+	/* Sasem USB Control Board */
+	{ USB_DEVICE(0x11ba, 0x0101) },
+	/* Terminating entry */
+	{}
+};
+
+/* USB Device data */
+static struct usb_driver sasem_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name		= MOD_NAME,
+	.probe		= sasem_probe,
+	.disconnect	= sasem_disconnect,
+	.id_table	= sasem_usb_id_table,
+#if !defined(KERNEL_2_5)
+	.fops		= &vfd_fops,
+	.minor		= VFD_MINOR_BASE,
+#endif
+};
+
+#ifdef KERNEL_2_5
+static struct usb_class_driver sasem_class = {
+	.name		= DEVFS_NAME,
+	.fops		= &vfd_fops,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
+	.mode		= DEVFS_MODE,
+#endif
+	.minor_base	= VFD_MINOR_BASE,
+};
+#endif
+
+/* to prevent races between open() and disconnect() */
+static DEFINE_MUTEX(disconnect_lock);
+
+static int debug;
+
+#if !defined(KERNEL_2_5)
+
+#define MAX_DEVICES	4	/* In case there's more than one Sasem device */
+static struct sasem_context *minor_table [MAX_DEVICES];
+
+/* the global usb devfs handle */
+extern devfs_handle_t usb_devfs_handle;
+
+#endif
+
+/*** M O D U L E   C O D E ***/
+
+MODULE_AUTHOR(MOD_AUTHOR);
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_LICENSE("GPL");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
+
+static void delete_context(struct sasem_context *context)
+{
+	usb_free_urb(context->tx_urb);  /* VFD */
+	usb_free_urb(context->rx_urb);  /* IR */
+	lirc_buffer_free(context->driver->rbuf);
+	kfree(context->driver->rbuf);
+	kfree(context->driver);
+	kfree(context);
+
+	if (debug)
+		printk(KERN_INFO "%s: context deleted\n", __func__);
+}
+
+static void deregister_from_lirc(struct sasem_context *context)
+{
+	int retval;
+	int minor = context->driver->minor;
+
+	retval = lirc_unregister_driver(minor);
+	if (retval)
+		err("%s: unable to deregister from lirc (%d)",
+			__func__, retval);
+	else
+		printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n",
+		       minor);
+
+}
+
+/**
+ * Called when the VFD device (e.g. /dev/usb/lcd)
+ * is opened by the application.
+ */
+static int vfd_open(struct inode *inode, struct file *file)
+{
+#ifdef KERNEL_2_5
+	struct usb_interface *interface;
+#endif
+	struct sasem_context *context = NULL;
+	int subminor;
+	int retval = 0;
+
+	/* prevent races with disconnect */
+	mutex_lock(&disconnect_lock);
+
+#ifdef KERNEL_2_5
+	subminor = iminor(inode);
+	interface = usb_find_interface(&sasem_driver, subminor);
+	if (!interface) {
+		err("%s: could not find interface for minor %d",
+		    __func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+	context = usb_get_intfdata(interface);
+#else
+	subminor = MINOR(inode->i_rdev) - VFD_MINOR_BASE;
+	if (subminor < 0 || subminor >= MAX_DEVICES) {
+		err("%s: no record of minor %d", __func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+	context = minor_table [subminor];
+#endif
+
+	if (!context) {
+		err("%s: no context found for minor %d",
+					__func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (context->vfd_isopen) {
+		err("%s: VFD port is already open", __func__);
+		retval = -EBUSY;
+	} else {
+		MOD_INC_USE_COUNT;
+		context->vfd_isopen = 1;
+		file->private_data = context;
+		printk(KERN_INFO "VFD port opened\n");
+	}
+
+	mutex_unlock(&context->lock);
+
+exit:
+	mutex_unlock(&disconnect_lock);
+	return retval;
+}
+
+/**
+ * Called when the VFD device (e.g. /dev/usb/lcd)
+ * is closed by the application.
+ */
+static int vfd_ioctl(struct inode *inode, struct file *file,
+		     unsigned cmd, unsigned long arg)
+{
+	struct sasem_context *context = NULL;
+
+	context = (struct sasem_context *) file->private_data;
+
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	switch (cmd) {
+	case IOCTL_LCD_CONTRAST:
+		if (arg > 1000)
+			arg = 1000;
+		context->vfd_contrast = (unsigned int)arg;
+		break;
+	default:
+		printk(KERN_INFO "Unknown IOCTL command\n");
+		mutex_unlock(&context->lock);
+		return -ENOIOCTLCMD;  /* not supported */
+	}
+
+	mutex_unlock(&context->lock);
+	return 0;
+}
+
+/**
+ * Called when the VFD device (e.g. /dev/usb/lcd)
+ * is closed by the application.
+ */
+static int vfd_close(struct inode *inode, struct file *file)
+{
+	struct sasem_context *context = NULL;
+	int retval = 0;
+
+	context = (struct sasem_context *) file->private_data;
+
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->vfd_isopen) {
+		err("%s: VFD is not open", __func__);
+		retval = -EIO;
+	} else {
+		context->vfd_isopen = 0;
+		MOD_DEC_USE_COUNT;
+		printk(KERN_INFO "VFD port closed\n");
+		if (!context->dev_present && !context->ir_isopen) {
+
+			/* Device disconnected before close and IR port is
+			 * not open. If IR port is open, context will be
+			 * deleted by ir_close. */
+			mutex_unlock(&context->lock);
+			delete_context(context);
+			return retval;
+		}
+	}
+
+	mutex_unlock(&context->lock);
+	return retval;
+}
+
+/**
+ * Sends a packet to the VFD.
+ */
+static int send_packet(struct sasem_context *context)
+{
+	unsigned int pipe;
+	int interval = 0;
+	int retval = 0;
+
+	pipe = usb_sndintpipe(context->dev,
+			context->tx_endpoint->bEndpointAddress);
+#ifdef KERNEL_2_5
+	interval = context->tx_endpoint->bInterval;
+#endif	/* Use 0 for 2.4 kernels */
+
+	usb_fill_int_urb(context->tx_urb, context->dev, pipe,
+		context->usb_tx_buf, sizeof(context->usb_tx_buf),
+		usb_tx_callback, context, interval);
+
+	context->tx_urb->actual_length = 0;
+
+	init_completion(&context->tx.finished);
+	atomic_set(&(context->tx.busy), 1);
+
+#ifdef KERNEL_2_5
+	retval =  usb_submit_urb(context->tx_urb, GFP_KERNEL);
+#else
+	retval =  usb_submit_urb(context->tx_urb);
+#endif
+	if (retval) {
+		atomic_set(&(context->tx.busy), 0);
+		err("%s: error submitting urb (%d)", __func__, retval);
+	} else {
+		/* Wait for transmission to complete (or abort) */
+		mutex_unlock(&context->lock);
+		wait_for_completion(&context->tx.finished);
+		mutex_lock(&context->lock);
+
+		retval = context->tx.status;
+		if (retval)
+			err("%s: packet tx failed (%d)", __func__, retval);
+	}
+
+	return retval;
+}
+
+/**
+ * Writes data to the VFD.  The Sasem VFD is 2x16 characters
+ * and requires data in 9 consecutive USB interrupt packets,
+ * each packet carrying 8 bytes.
+ */
+static ssize_t vfd_write(struct file *file, const char *buf,
+				size_t n_bytes, loff_t *pos)
+{
+	int i;
+	int retval = 0;
+	struct sasem_context *context;
+
+	context = (struct sasem_context *) file->private_data;
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&context->lock);
+
+	if (!context->dev_present) {
+		err("%s: no Sasem device present", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (n_bytes <= 0 || n_bytes > 32) {
+		err("%s: invalid payload size", __func__);
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	retval = copy_from_user(context->tx.data_buf, buf, n_bytes);
+	if (retval < 0)
+		goto exit;
+
+	/* Pad with spaces */
+	for (i = n_bytes; i < 32; ++i)
+		context->tx.data_buf[i] = ' ';
+
+	/* Nine 8 byte packets to be sent */
+	/* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0"
+	 *       will clear the VFD */
+	for (i = 0; i < 9; i++) {
+		switch (i) {
+		case 0:
+			memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8);
+			context->usb_tx_buf[1] = (context->vfd_contrast) ?
+				(0x2B - (context->vfd_contrast - 1) / 250)
+				: 0x2B;
+			break;
+		case 1:
+			memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8);
+			break;
+		case 2:
+			memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8);
+			break;
+		case 3:
+			memcpy(context->usb_tx_buf, context->tx.data_buf, 8);
+			break;
+		case 4:
+			memcpy(context->usb_tx_buf,
+			       context->tx.data_buf + 8, 8);
+			break;
+		case 5:
+			memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8);
+			break;
+		case 6:
+			memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8);
+			break;
+		case 7:
+			memcpy(context->usb_tx_buf,
+			       context->tx.data_buf + 16, 8);
+			break;
+		case 8:
+			memcpy(context->usb_tx_buf,
+			       context->tx.data_buf + 24, 8);
+			break;
+		}
+		retval = send_packet(context);
+		if (retval) {
+
+			err("%s: send packet failed for packet #%d",
+					__func__, i);
+			goto exit;
+		}
+	}
+exit:
+
+	mutex_unlock(&context->lock);
+
+	return (!retval) ? n_bytes : retval;
+}
+
+/**
+ * Callback function for USB core API: transmit data
+ */
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_tx_callback(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_tx_callback(struct urb *urb)
+#endif
+{
+	struct sasem_context *context;
+
+	if (!urb)
+		return;
+	context = (struct sasem_context *) urb->context;
+	if (!context)
+		return;
+
+	context->tx.status = urb->status;
+
+	/* notify waiters that write has finished */
+	atomic_set(&context->tx.busy, 0);
+	complete(&context->tx.finished);
+
+	return;
+}
+
+/**
+ * Called by lirc_dev when the application opens /dev/lirc
+ */
+static int ir_open(void *data)
+{
+	int retval = 0;
+	struct sasem_context *context;
+
+	/* prevent races with disconnect */
+	mutex_lock(&disconnect_lock);
+
+	context = (struct sasem_context *) data;
+
+	mutex_lock(&context->lock);
+
+	if (context->ir_isopen) {
+		err("%s: IR port is already open", __func__);
+		retval = -EBUSY;
+		goto exit;
+	}
+
+	usb_fill_int_urb(context->rx_urb, context->dev,
+		usb_rcvintpipe(context->dev,
+				context->rx_endpoint->bEndpointAddress),
+		context->usb_rx_buf, sizeof(context->usb_rx_buf),
+		usb_rx_callback, context, context->rx_endpoint->bInterval);
+
+#ifdef KERNEL_2_5
+	retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
+#else
+	retval = usb_submit_urb(context->rx_urb);
+#endif
+
+	if (retval)
+		err("%s: usb_submit_urb failed for ir_open (%d)",
+		    __func__, retval);
+	else {
+		MOD_INC_USE_COUNT;
+		context->ir_isopen = 1;
+		printk(KERN_INFO "IR port opened\n");
+	}
+
+exit:
+	mutex_unlock(&context->lock);
+
+	mutex_unlock(&disconnect_lock);
+	return 0;
+}
+
+/**
+ * Called by lirc_dev when the application closes /dev/lirc
+ */
+static void ir_close(void *data)
+{
+	struct sasem_context *context;
+
+	context = (struct sasem_context *)data;
+	if (!context) {
+		err("%s: no context for device", __func__);
+		return;
+	}
+
+	mutex_lock(&context->lock);
+
+	usb_kill_urb(context->rx_urb);
+	context->ir_isopen = 0;
+	MOD_DEC_USE_COUNT;
+	printk(KERN_INFO "IR port closed\n");
+
+	if (!context->dev_present) {
+
+		/*
+		 * Device disconnected while IR port was
+		 * still open. Driver was not deregistered
+		 * at disconnect time, so do it now.
+		 */
+		deregister_from_lirc(context);
+
+		if (!context->vfd_isopen) {
+
+			mutex_unlock(&context->lock);
+			delete_context(context);
+			return;
+		}
+		/* If VFD port is open, context will be deleted by vfd_close */
+	}
+
+	mutex_unlock(&context->lock);
+	return;
+}
+
+/**
+ * Process the incoming packet
+ */
+static void incoming_packet(struct sasem_context *context,
+				   struct urb *urb)
+{
+	int len = urb->actual_length;
+	unsigned char *buf = urb->transfer_buffer;
+	long ms;
+	struct timeval tv;
+
+	if (len != 8) {
+		printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n",
+		     __func__, len);
+		return;
+	}
+
+#ifdef DEBUG
+	int i;
+	for (i = 0; i < 8; ++i)
+		printk(KERN_INFO "%02x ", buf [i]);
+	printk(KERN_INFO "\n");
+#endif
+
+	/*
+	 * Lirc could deal with the repeat code, but we really need to block it
+	 * if it arrives too late.  Otherwise we could repeat the wrong code.
+	 */
+
+	/* get the time since the last button press */
+	do_gettimeofday(&tv);
+	ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 +
+	     (tv.tv_usec - context->presstime.tv_usec) / 1000;
+
+	if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) {
+		/*
+		 * the repeat code is being sent, so we copy
+		 * the old code to LIRC
+		 */
+
+		/*
+		 * NOTE: Only if the last code was less than 250ms ago
+		 * - no one should be able to push another (undetected) button
+		 *   in that time and then get a false repeat of the previous
+		 *   press but it is long enough for a genuine repeat
+		 */
+		if ((ms < 250) && (context->codesaved != 0)) {
+			memcpy(buf, &context->lastcode, 8);
+			context->presstime.tv_sec = tv.tv_sec;
+			context->presstime.tv_usec = tv.tv_usec;
+		}
+	} else {
+		/* save the current valid code for repeats */
+		memcpy(&context->lastcode, buf, 8);
+		/*
+		 * set flag to signal a valid code was save;
+		 * just for safety reasons
+		 */
+		context->codesaved = 1;
+		context->presstime.tv_sec = tv.tv_sec;
+		context->presstime.tv_usec = tv.tv_usec;
+	}
+
+	lirc_buffer_write(context->driver->rbuf, buf);
+	wake_up(&context->driver->rbuf->wait_poll);
+}
+
+/**
+ * Callback function for USB core API: receive data
+ */
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_rx_callback(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_rx_callback(struct urb *urb)
+#endif
+{
+	struct sasem_context *context;
+
+	if (!urb)
+		return;
+	context = (struct sasem_context *) urb->context;
+	if (!context)
+		return;
+
+	switch (urb->status) {
+
+	case -ENOENT: 		/* usbcore unlink successful! */
+		return;
+
+	case 0:
+		if (context->ir_isopen)
+			incoming_packet(context, urb);
+		break;
+
+	default:
+		printk(KERN_WARNING "%s: status (%d): ignored\n",
+		       __func__, urb->status);
+		break;
+	}
+
+#ifdef KERNEL_2_5
+	usb_submit_urb(context->rx_urb, GFP_ATOMIC);
+#endif
+	return;
+}
+
+
+
+/**
+ * Callback function for USB core API: Probe
+ */
+#ifdef KERNEL_2_5
+static int sasem_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+#else
+static void *sasem_probe(struct usb_device *dev, unsigned int intf,
+			const struct usb_device_id *id)
+#endif
+{
+#ifdef KERNEL_2_5
+	struct usb_device *dev = NULL;
+	struct usb_host_interface *iface_desc = NULL;
+#else
+	struct usb_interface *interface = NULL;
+	struct usb_interface_descriptor *iface_desc = NULL;
+	char name [10];
+	int subminor = 0;
+#endif
+	struct usb_endpoint_descriptor *rx_endpoint = NULL;
+	struct usb_endpoint_descriptor *tx_endpoint = NULL;
+	struct urb *rx_urb = NULL;
+	struct urb *tx_urb = NULL;
+	struct lirc_driver *driver = NULL;
+	struct lirc_buffer *rbuf = NULL;
+	int lirc_minor = 0;
+	int num_endpoints;
+	int retval = 0;
+	int vfd_ep_found;
+	int ir_ep_found;
+	int alloc_status;
+	struct sasem_context *context = NULL;
+	int i;
+
+	printk(KERN_INFO "%s: found Sasem device\n", __func__);
+
+#if !defined(KERNEL_2_5)
+	for (subminor = 0; subminor < MAX_DEVICES; ++subminor) {
+		if (minor_table [subminor] == NULL)
+			break;
+	}
+	if (subminor == MAX_DEVICES) {
+		err("%s: allowed number of devices already present",
+		    __func__);
+		retval = -ENOMEM;
+		goto exit;
+	}
+#endif
+
+#ifdef KERNEL_2_5
+	dev = usb_get_dev(interface_to_usbdev(interface));
+	iface_desc = interface->cur_altsetting;
+	num_endpoints = iface_desc->desc.bNumEndpoints;
+#else
+	interface = &dev->actconfig->interface [intf];
+	iface_desc = &interface->altsetting [interface->act_altsetting];
+	num_endpoints = iface_desc->bNumEndpoints;
+#endif
+
+	/*
+	 * Scan the endpoint list and set:
+	 *	first input endpoint = IR endpoint
+	 *	first output endpoint = VFD endpoint
+	 */
+
+	ir_ep_found = 0;
+	vfd_ep_found = 0;
+
+	for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) {
+
+		struct usb_endpoint_descriptor *ep;
+		int ep_dir;
+		int ep_type;
+#ifdef KERNEL_2_5
+		ep = &iface_desc->endpoint [i].desc;
+#else
+		ep = &iface_desc->endpoint [i];
+#endif
+		ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+		ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+		if (!ir_ep_found &&
+			ep_dir == USB_DIR_IN &&
+			ep_type == USB_ENDPOINT_XFER_INT) {
+
+			rx_endpoint = ep;
+			ir_ep_found = 1;
+			if (debug)
+				printk(KERN_INFO "%s: found IR endpoint\n",
+				       __func__);
+
+		} else if (!vfd_ep_found &&
+			ep_dir == USB_DIR_OUT &&
+			ep_type == USB_ENDPOINT_XFER_INT) {
+
+			tx_endpoint = ep;
+			vfd_ep_found = 1;
+			if (debug)
+				printk(KERN_INFO "%s: found VFD endpoint\n",
+				       __func__);
+		}
+	}
+
+	/* Input endpoint is mandatory */
+	if (!ir_ep_found) {
+
+		err("%s: no valid input (IR) endpoint found.", __func__);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	if (!vfd_ep_found)
+		printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n",
+		       __func__);
+
+
+	/* Allocate memory */
+	alloc_status = 0;
+
+	context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL);
+	if (!context) {
+		err("%s: kzalloc failed for context", __func__);
+		alloc_status = 1;
+		goto alloc_status_switch;
+	}
+	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	if (!driver) {
+		err("%s: kzalloc failed for lirc_driver", __func__);
+		alloc_status = 2;
+		goto alloc_status_switch;
+	}
+	rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+	if (!rbuf) {
+		err("%s: kmalloc failed for lirc_buffer", __func__);
+		alloc_status = 3;
+		goto alloc_status_switch;
+	}
+	if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) {
+		err("%s: lirc_buffer_init failed", __func__);
+		alloc_status = 4;
+		goto alloc_status_switch;
+	}
+#ifdef KERNEL_2_5
+	rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+#else
+	rx_urb = usb_alloc_urb(0);
+#endif
+	if (!rx_urb) {
+		err("%s: usb_alloc_urb failed for IR urb", __func__);
+		alloc_status = 5;
+		goto alloc_status_switch;
+	}
+	if (vfd_ep_found) {
+#ifdef KERNEL_2_5
+		tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+#else
+		tx_urb = usb_alloc_urb(0);
+#endif
+		if (!tx_urb) {
+			err("%s: usb_alloc_urb failed for VFD urb", __func__);
+			alloc_status = 6;
+			goto alloc_status_switch;
+		}
+	}
+
+	mutex_init(&context->lock);
+
+	strcpy(driver->name, MOD_NAME);
+	driver->minor = -1;
+	driver->code_length = 64;
+	driver->sample_rate = 0;
+	driver->features = LIRC_CAN_REC_LIRCCODE;
+	driver->data = context;
+	driver->rbuf = rbuf;
+	driver->set_use_inc = ir_open;
+	driver->set_use_dec = ir_close;
+#ifdef LIRC_HAVE_SYSFS
+	driver->dev   = &interface->dev;
+#endif
+	driver->owner = THIS_MODULE;
+
+	mutex_lock(&context->lock);
+
+	lirc_minor = lirc_register_driver(driver);
+	if (lirc_minor < 0) {
+		err("%s: lirc_register_driver failed", __func__);
+		alloc_status = 7;
+		mutex_unlock(&context->lock);
+	} else
+		printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n",
+			__func__, lirc_minor);
+
+alloc_status_switch:
+
+	switch (alloc_status) {
+
+	case 7:
+		if (vfd_ep_found)
+			usb_free_urb(tx_urb);
+	case 6:
+		usb_free_urb(rx_urb);
+	case 5:
+		lirc_buffer_free(rbuf);
+	case 4:
+		kfree(rbuf);
+	case 3:
+		kfree(driver);
+	case 2:
+		kfree(context);
+		context = NULL;
+	case 1:
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	/* Needed while unregistering! */
+	driver->minor = lirc_minor;
+
+	context->dev = dev;
+	context->dev_present = 1;
+	context->rx_endpoint = rx_endpoint;
+	context->rx_urb = rx_urb;
+	if (vfd_ep_found) {
+		context->tx_endpoint = tx_endpoint;
+		context->tx_urb = tx_urb;
+		context->vfd_contrast = 1000;   /* range 0 - 1000 */
+	}
+	context->driver = driver;
+
+#ifdef KERNEL_2_5
+	usb_set_intfdata(interface, context);
+#else
+	minor_table [subminor] = context;
+	context->subminor = subminor;
+#endif
+
+	if (vfd_ep_found) {
+
+#ifdef KERNEL_2_5
+		if (debug)
+			printk(KERN_INFO "Registering VFD with sysfs\n");
+		if (usb_register_dev(interface, &sasem_class))
+			/* Not a fatal error, so ignore */
+			printk(KERN_INFO "%s: could not get a minor number "
+			       "for VFD\n", __func__);
+#else
+		if (debug)
+			printk(KERN_INFO "Registering VFD with devfs\n");
+		sprintf(name, DEVFS_NAME, subminor);
+		context->devfs = devfs_register(usb_devfs_handle, name,
+				 DEVFS_FL_DEFAULT,
+				 USB_MAJOR, VFD_MINOR_BASE + subminor,
+				 DEVFS_MODE, &vfd_fops, NULL);
+		if (!context->devfs)
+			/* not a fatal error so ignore */
+			printk(KERN_INFO "%s: devfs register failed for VFD\n",
+					__func__);
+#endif
+	}
+
+	printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n",
+			__func__, dev->bus->busnum, dev->devnum);
+
+	mutex_unlock(&context->lock);
+exit:
+#ifdef KERNEL_2_5
+	return retval;
+#else
+	return (!retval) ? context : NULL;
+#endif
+}
+
+/**
+ * Callback function for USB core API: disonnect
+ */
+#ifdef KERNEL_2_5
+static void sasem_disconnect(struct usb_interface *interface)
+#else
+static void sasem_disconnect(struct usb_device *dev, void *data)
+#endif
+{
+	struct sasem_context *context;
+
+	/* prevent races with ir_open()/vfd_open() */
+	mutex_lock(&disconnect_lock);
+
+#ifdef KERNEL_2_5
+	context = usb_get_intfdata(interface);
+#else
+	context = (struct sasem_context *)data;
+#endif
+	mutex_lock(&context->lock);
+
+	printk(KERN_INFO "%s: Sasem device disconnected\n", __func__);
+
+#ifdef KERNEL_2_5
+	usb_set_intfdata(interface, NULL);
+#else
+	minor_table [context->subminor] = NULL;
+#endif
+	context->dev_present = 0;
+
+	/* Stop reception */
+	usb_kill_urb(context->rx_urb);
+
+	/* Abort ongoing write */
+	if (atomic_read(&context->tx.busy)) {
+
+		usb_kill_urb(context->tx_urb);
+		wait_for_completion(&context->tx.finished);
+	}
+
+	/* De-register from lirc_dev if IR port is not open */
+	if (!context->ir_isopen)
+		deregister_from_lirc(context);
+
+#ifdef KERNEL_2_5
+	usb_deregister_dev(interface, &sasem_class);
+#else
+	if (context->devfs)
+		devfs_unregister(context->devfs);
+#endif
+
+	mutex_unlock(&context->lock);
+
+	if (!context->ir_isopen && !context->vfd_isopen)
+		delete_context(context);
+
+	mutex_unlock(&disconnect_lock);
+}
+
+static int __init sasem_init(void)
+{
+	int rc;
+
+	printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n");
+	printk(KERN_INFO MOD_AUTHOR "\n");
+
+	rc = usb_register(&sasem_driver);
+	if (rc < 0) {
+		err("%s: usb register failed (%d)", __func__, rc);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit sasem_exit(void)
+{
+	usb_deregister(&sasem_driver);
+	printk(KERN_INFO "module removed. Goodbye!\n");
+}
+
+
+module_init(sasem_init);
+module_exit(sasem_exit);
+
+#if !defined(KERNEL_2_5)
+EXPORT_NO_SYMBOLS;
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.c
@@ -0,0 +1,1179 @@
+/*      $Id: lirc_wpc8769l.c,v 1.8 2009/03/15 09:34:01 lirc Exp $      */
+
+/****************************************************************************
+ ** lirc_wpc8769l.c ****************************************************
+ ****************************************************************************
+ *
+ * lirc_wpc8769l - Device driver for the integrated CIR receiver found in
+ *                 Acer Aspire 6530G (and probably other models), based on
+ *                 the Winbond 8769L embedded controller.
+ *                 (Written using the lirc_serial driver as a guide).
+ *
+ * Copyright (C) 2008, 2009 Juan J. Garcia de Soria <skandalfo@gmail.com>
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/poll.h>
+
+#include <linux/bitops.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
+#include <asm/io.h>
+#else
+#include <linux/io.h>
+#endif
+#include <linux/irq.h>
+
+#include <linux/acpi.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+#include <linux/platform_device.h>
+#endif
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#include "lirc_wpc8769l.h"
+
+/* Name of the lirc device. */
+#define LIRC_DRIVER_NAME "lirc_wpc8769l"
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+#define wprintk(fmt, args...)					\
+	do {							\
+			printk(KERN_WARN LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+#define eprintk(fmt, args...)					\
+	do {							\
+			printk(KERN_ERR LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+#define iprintk(fmt, args...)					\
+	do {							\
+			printk(KERN_INFO LIRC_DRIVER_NAME ": "	\
+			       fmt, ## args);			\
+	} while (0)
+
+/* Number of driver->lirc-dev buffer elements. */
+#define RBUF_LEN 256
+
+/* Number of 0xff bytes received in a row. */
+static unsigned int wpc8769l_ff_bytes_in_a_row;
+
+/* Hardware resource parameters. */
+static unsigned int baseport1;
+static unsigned int baseport2;
+static unsigned int irq;
+
+/* Debugging flag. */
+static int debug;
+
+/* If true, we skip ACPI autodetection and use the parameter-supplied I/O and
+ * IRQ. */
+static int skip_probe;
+
+/* Whether the device is open or not. */
+static int lirc_wpc8769l_is_open;
+
+/* Code disabled since it didn't seem to work with the test hardware. */
+/*#define LIRC_WPC8769L_WAKEUP*/
+#ifdef LIRC_WPC8769L_WAKEUP
+/* These parameters are taken from the driver for MS Windows Vista.
+ * The specific values used for your hardware may be found at this registry
+ * key:
+ *
+ * HKEY_LOCAL_MACHINE/CurrentControlSet/Services/Winbond CIR/PowerKey
+ */
+static int protocol_select = 2;
+static int max_info_bits = 24;
+static unsigned int rc_wakeup_code = 0x7ffffbf3;
+static unsigned int rc_wakeup_mask = 0xff000fff;
+#endif
+
+/* Resource allocation pointers. */
+static struct resource *wpc8769l_portblock1_resource;
+static struct resource *wpc8769l_portblock2_resource;
+
+/* Hardware related spinlock. */
+static DEFINE_SPINLOCK(wpc8769l_hw_spinlock);
+
+/* The buffer for ISR to bottom half data transfer. */
+static struct lirc_buffer rbuf;
+
+/* Bit-to-MODE2 coalescing helper variables. */
+static int last_was_pulse;
+static lirc_t last_counter;
+
+/* Microseconds after a timeout-triggered pulse. */
+static s64 lastus;
+
+/* Microseconds when the timer was started. */
+static s64 timerstartus;
+
+/* Put another pulse/space to the queue, checking for overruns. */
+static void put_item(lirc_t data)
+{
+	if (lirc_buffer_full(&rbuf)) {
+		if (printk_ratelimit())
+			eprintk("RX buffer overrun.\n");
+		return;
+	}
+	lirc_buffer_write(&rbuf, (void *) &data);
+}
+
+/* Put any accumulated pulse/space to userspace. */
+static void put_span(void)
+{
+	lirc_t data;
+	if (last_counter) {
+		/* Take the usecs length. */
+		data = last_counter;
+
+		/* Mark pulse or space. */
+		if (last_was_pulse)
+			data |= PULSE_BIT;
+
+		/* Put the span to the buffer. */
+		put_item(data);
+
+		/* Reset counter, in order to avoid emitting duplicate data. */
+		last_counter = 0;
+	}
+}
+
+/* Aggregate pulse time. */
+static void put_pulse_bit(lirc_t n)
+{
+	if (last_was_pulse) {
+		last_counter += n;
+		if (last_counter > PULSE_MASK)
+			last_counter = PULSE_MASK;
+	} else {
+		put_span();
+		last_was_pulse = 1;
+		last_counter = n;
+		if (last_counter > PULSE_MASK)
+			last_counter = PULSE_MASK;
+	}
+}
+
+/* Aggregate space time. */
+static void put_space_bit(lirc_t n)
+{
+	if (!last_was_pulse) {
+		last_counter += n;
+		if (last_counter > PULSE_MASK)
+			last_counter = PULSE_MASK;
+	} else {
+		put_span();
+		last_was_pulse = 0;
+		last_counter = n;
+		if (last_counter > PULSE_MASK)
+			last_counter = PULSE_MASK;
+	}
+}
+
+/* Timeout function for last pulse part. */
+static void wpc8769l_last_timeout(unsigned long l)
+{
+	struct timeval currenttv;
+
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	/* Mark the time at which we inserted the timeout span. */
+	do_gettimeofday(&currenttv);
+	lastus = ((s64) currenttv.tv_sec) * 1000000ll + currenttv.tv_usec;
+
+	/* Emit the timeout as a space. */
+	put_space_bit(lastus - timerstartus);
+
+	/* Signal the bottom half wait queue
+	 * that there's data available. */
+	wake_up_interruptible(&rbuf.wait_poll);
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+}
+
+/* Timer for end-of-code pulse timeout. */
+static struct timer_list last_span_timer =
+	TIMER_INITIALIZER(wpc8769l_last_timeout, 0, 0);
+
+/* Interrupt handler, doing the bit sample to mode2 conversion.
+ * Perhaps this work should be taken outside of the ISR... */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t irq_handler(int irqno, void *blah)
+#else
+static irqreturn_t irq_handler(int irqno, void *blah, struct pt_regs *regs)
+#endif
+{
+	unsigned int data;
+	int handled = 0;
+	int count, more;
+	struct timeval currenttv;
+	s64 currentus, span;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+	unsigned char data_buf[WPC8769L_BYTE_BUFFER_SIZE];
+	unsigned char *data_ptr;
+	unsigned long *ldata;
+	unsigned int next_one, next_zero, size;
+#else
+	unsigned int mask;
+#endif
+
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	/* Check whether there's any data available. */
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	data = inb(baseport1 + WPC8769L_DATA_STATUS_REG);
+
+	if (data & WPC8769L_DATA_READY_MASK) {
+		/* Get current timestamp. */
+		do_gettimeofday(&currenttv);
+		currentus = ((s64) currenttv.tv_sec) * 1000000ll +
+			currenttv.tv_usec;
+
+		/* If we had a timeout before we might need to fill
+		 * in additional space time. */
+		if (lastus) {
+			/* Calculate the difference, compensating
+			 * the time for the data successfully
+			 * received (estimated to be
+			 * WPC8769L_BYTES_PER_BURST bytes). */
+			span = currentus - lastus
+					- WPC8769L_BYTES_PER_BURST
+					* WPC8769L_USECS_PER_BYTE;
+
+			/* Only insert positive spans. */
+			if (span > 0) {
+				/* Emit the extended gap as a space. */
+				put_space_bit(span);
+			}
+
+			/* Mark that we had the last timeout into account. */
+			lastus = 0;
+		}
+
+		count = 0;
+		more = 1;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+		data_ptr = data_buf;
+#endif
+		do {
+			/* Read the next byte of data. */
+			outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+			data = inb(baseport1 + WPC8769L_DATA_REG);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+			*data_ptr++ = data;
+#else
+			for (mask = 0x01 ; mask < 0x100; mask <<= 1) {
+				if (data & mask)
+					put_space_bit(WPC8769L_USECS_PER_BIT);
+				else
+					put_pulse_bit(WPC8769L_USECS_PER_BIT);
+			}
+#endif
+
+			/* Check for 0xff in a row. */
+			if (data == 0xff)
+				wpc8769l_ff_bytes_in_a_row++;
+			else
+				wpc8769l_ff_bytes_in_a_row = 0;
+
+			outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+			data = inb(baseport1 + WPC8769L_DATA_ACK_REG);
+			if (data & WPC8769L_DATA_ACK_REG) {
+				outb(WPC8769L_BANK_E0,
+					baseport1 + WPC8769L_SELECT_REG);
+				data = inb(baseport1 +
+					WPC8769L_REMAINING_RX_DATA_REG);
+				if (!data)
+					more = 0;
+			} else
+				more = 0;
+
+			count++;
+		} while (more && count < WPC8769L_BYTES_PER_BURST);
+
+		if (wpc8769l_ff_bytes_in_a_row
+			>= WPC8769L_FF_BYTES_BEFORE_RESET) {
+
+			/* Put in another 0xff byte. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+			*data_ptr++ = 0xff;
+			count++;
+#else
+			put_space_bit(8 * WPC8769L_USECS_PER_BIT);
+#endif
+
+			/* Reset the hardware in the case of too many
+			 * 0xff bytes in a row. */
+			outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+			outb(WPC8769L_TIMEOUT_RESET_MASK,
+				baseport1 + WPC8769L_TIMEOUT_RESET_REG);
+		}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
+		/* Emit the data. */
+		size = count << 3;
+
+		ldata = (unsigned long *) data_buf;
+		next_one = generic_find_next_le_bit(ldata, size, 0);
+
+		if (next_one > 0)
+			put_pulse_bit(next_one
+				* WPC8769L_USECS_PER_BIT);
+
+		while (next_one < size) {
+			next_zero = generic_find_next_zero_le_bit(ldata,
+				size, next_one + 1);
+
+			put_space_bit(
+				(next_zero - next_one)
+				* WPC8769L_USECS_PER_BIT);
+
+			if (next_zero < size) {
+				next_one = generic_find_next_le_bit(ldata,
+					size, next_zero + 1);
+
+				put_pulse_bit(
+					(next_one - next_zero)
+					* WPC8769L_USECS_PER_BIT);
+			} else {
+				next_one = size;
+			}
+		}
+#endif
+
+		/* Mark the IRQ as handled. */
+		handled = 1;
+
+		/* Signal the bottom half wait queue
+		 * that there's data available. */
+		wake_up_interruptible(&rbuf.wait_poll);
+
+		/* Set up timeout handling. */
+		mod_timer(&last_span_timer,
+			jiffies + WPC8769L_LAST_TIMEOUT_JIFFIES);
+
+		/* Set up last timer us mark. */
+		timerstartus = currentus;
+	}
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+	return IRQ_RETVAL(handled);
+}
+
+/* Prepare the hardware on module load. */
+static void wpc8769l_prepare_hardware(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	/* I don't know why this needs reading. */
+	outb(WPC8769L_BANK_E4, baseport1 + WPC8769L_SELECT_REG);
+	inb(baseport1 + WPC8769L_READ_ON_STARTUP_REG);
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+}
+
+
+/* Wake up device from power down and check whether it was the
+ * device that woke us up.
+ */
+static int wpc8769l_power_up_and_check_if_we_woke_us_up(void)
+{
+	unsigned int data;
+	int res;
+
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	if (baseport2) {
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		res = inb(baseport2 + WPC8769L_WAKEUP_STATUS_REG)
+			& WPC8769L_WAKEUP_WOKE_UP_MASK;
+
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		outb(WPC8769L_WAKEUP_WOKE_UP_MASK,
+			baseport2 + WPC8769L_WAKEUP_STATUS_REG);
+
+		outb(WPC8769L_WAKEUP_ACK_MASK,
+			baseport2 + WPC8769L_WAKEUP_ACK_REG);
+	} else {
+		outb(WPC8769L_BANK_F0, baseport1 + WPC8769L_SELECT_REG);
+		res = (inb(baseport1 + WPC8769L_WAKEUP_STATUS_LEG_REG)
+			& WPC8769L_WAKEUP_STATUS_LEG_MASK) ? 1 : 0;
+	}
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+
+	return res;
+}
+
+/* Disable interrupts from device. */
+static void wpc8769l_disable_interrupts(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_INTERRUPT_REG)
+		& ~WPC8769L_INTERRUPT_1_MASK,
+		baseport1 + WPC8769L_INTERRUPT_REG);
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_INTERRUPT_REG)
+		& ~WPC8769L_INTERRUPT_1_MASK,
+		baseport1 + WPC8769L_INTERRUPT_REG);
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+}
+
+#ifdef LIRC_WPC8769L_WAKEUP
+/* Expand value nibble for configuration of wake up parameters.
+ * This seems to manchester-encode a nibble into a byte. */
+static unsigned int wpc8769l_expand_value_nibble(unsigned int nibble)
+{
+	int i;
+	unsigned int tmp, tmp2, res;
+
+	res = 0;
+
+	for (i = 0; i < 4; i += 2) {
+		tmp = (nibble >> i) & 0x3;
+		switch (tmp) {
+		case 3:
+			tmp2 = 5;
+			break;
+		case 2:
+			tmp2 = 6;
+			break;
+		case 1:
+			tmp2 = 9;
+			break;
+		case 0:
+			tmp2 = 0x0a;
+			break;
+		default:
+			return 0;
+			break;
+		}
+		res |= ((tmp2 << i) << i);
+	}
+
+	return res;
+}
+
+/* Expand mask nibble for configuration of wake up parameters. */
+static unsigned int wpc8769l_expand_mask_nibble(unsigned int nibble)
+{
+	int i;
+	unsigned int tmp, tmp2, res;
+
+	res = 0;
+
+	for (i = 0; i < 4; i += 2) {
+		tmp = (nibble >> i) & 0x3;
+		switch (tmp) {
+		case 0:
+			tmp2 = 0;
+			break;
+		case 1:
+			tmp2 = 3;
+			break;
+		case 2:
+			tmp2 = 0x0c;
+			break;
+		case 3:
+			tmp2 = 0x0f;
+			break;
+		default:
+			return 0;
+			break;
+		}
+		res |= ((tmp2 << i) << i);
+	}
+
+	return res;
+}
+
+/* Configure wake up triggers for the hardware that supports it.
+ * THE CALLER MUST HAVE ACQUIRED wpc8769l_hw_spinlock BEFORE CALLING.
+ */
+static void wpc8769l_configure_wakeup_triggers(void)
+{
+	unsigned int x;
+	unsigned int data, data2;
+
+	int i, j;
+
+	x = inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG)
+		& WPC8769L_WAKEUP_ENABLE_MASK;
+	outb(inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG)
+		& ~WPC8769L_WAKEUP_ENABLE_MASK,
+		baseport2 + WPC8769L_WAKEUP_ENABLE_REG);
+
+	data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+	data &= ~WPC8769L_CLOCK_OFF_MASK;
+	data |= WPC8769L_CLOCK_ON_MASK;
+	outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+	outb(WPC8769L_WAKEUP_CONFIGURING_MASK,
+		baseport2 + WPC8769L_WAKEUP_STATUS_REG);
+	outb(WPC8769L_WAKEUP_ACK_MASK,
+		baseport2 + WPC8769L_WAKEUP_ACK_REG);
+
+	data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+	data &= ~WPC8769L_CLOCK_OFF_MASK;
+	data |= WPC8769L_CLOCK_ON_MASK;
+	outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+	data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+	data &= ~WPC8769L_CLOCK_OFF_MASK;
+	data |= WPC8769L_CLOCK_ON_MASK;
+	outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+	data = inb(baseport2 + WPC8769L_WAKEUP_CONFIG_REG);
+	data &= WPC8769L_WAKEUP_CONFIG_PRE_MASK;
+	data |= (max_info_bits + WPC8769L_MAX_INFO_BITS_BIAS)
+		<< WPC8769L_MAX_INFO_BITS_SHIFT;
+	outb(data, baseport2 + WPC8769L_WAKEUP_CONFIG_REG);
+
+	i = j = 0;
+
+	/* Program values. */
+	while (j < WPC8769L_WAKEUP_DATA_BITS) {
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		outb(i + WPC8769L_WAKEUP_DATA_BASE,
+			baseport2 + WPC8769L_WAKEUP_DATA_PTR_REG);
+
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		data = (rc_wakeup_code >> j) & 0x0f;
+		data = wpc8769l_expand_value_nibble(data);
+		outb(data, baseport2 + WPC8769L_WAKEUP_DATA_REG);
+
+		i++;
+		j += 4;
+	}
+
+	/* Program masks. */
+	while (j < WPC8769L_WAKEUP_DATA_BITS) {
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		outb(i + WPC8769L_WAKEUP_MASK_BASE,
+			baseport2 + WPC8769L_WAKEUP_DATA_PTR_REG);
+
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		data = (rc_wakeup_mask >> j) & 0x0f;
+		data = wpc8769l_expand_mask_nibble(data);
+		outb(data, baseport2 + WPC8769L_WAKEUP_DATA_REG);
+
+		i++;
+		j += 4;
+	}
+
+	data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+	data &= ~WPC8769L_CLOCK_OFF_MASK;
+	data |= WPC8769L_CLOCK_ON_MASK;
+	outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+	data2 = inb(baseport2 + WPC8769L_WAKEUP_CONFIG2_REG);
+	data2 &= WPC8769L_WAKEUP_CONFIG2_AND_MASK;
+	data2 |= WPC8769L_WAKEUP_CONFIG2_OR_MASK;
+
+	data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+	data &= ~WPC8769L_CLOCK_OFF_MASK;
+	data |= WPC8769L_CLOCK_ON_MASK;
+	outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+	outb(data2, baseport2 + WPC8769L_WAKEUP_CONFIG2_REG);
+
+	if (x != WPC8769L_WAKEUP_ENABLE_MASK)
+		outb(inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG)
+		| WPC8769L_WAKEUP_ENABLE_MASK,
+		baseport2 + WPC8769L_WAKEUP_ENABLE_REG);
+}
+#endif
+
+/* Enable interrupts from device. */
+static void wpc8769l_enable_interrupts(void)
+{
+	unsigned int data, data2, data_save;
+
+	unsigned int a, b;
+
+	unsigned long flags;
+	spin_lock_irqsave(&wpc8769l_hw_spinlock, flags);
+
+	outb(WPC8769L_BANK_F0, baseport1 + WPC8769L_SELECT_REG);
+	data_save = inb(baseport1 + WPC8769L_WAKEUP_STATUS_LEG_REG);
+
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(0, baseport1 + WPC8769L_HARDWARE_ENABLE1_REG);
+
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_HARDWARE_ENABLE1_REG)
+		| WPC8769L_HARDWARE_ENABLE1_MASK,
+		baseport1 + WPC8769L_HARDWARE_ENABLE1_REG);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(0, baseport1 + WPC8769L_CONFIG_REG);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	data = inb(baseport1 + WPC8769L_CONFIG_REG);
+	data &= ~WPC8769L_CONFIG_OFF_MASK;
+	data |= WPC8769L_CONFIG_ON_MASK;
+	outb(data, baseport1 + WPC8769L_CONFIG_REG);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_DATA_STATUS_MASK_1, baseport1 + WPC8769L_DATA_STATUS_REG);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_DATA_STATUS_MASK_2, baseport1 + WPC8769L_DATA_STATUS_REG);
+
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_CONFIG2_REG)
+		& ~WPC8769L_CONFIG2_OFF_MASK,
+		baseport1 + WPC8769L_CONFIG2_REG);
+
+	outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_CONFIG3_REG)
+		| WPC8769L_CONFIG3_ON_MASK,
+		baseport1 + WPC8769L_CONFIG3_REG);
+
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+	data = inb(baseport1 + WPC8769L_CONFIG4_REG);
+	data &= WPC8769L_CONFIG4_AND_MASK;
+	data |= WPC8769L_CONFIG4_ON_MASK;
+
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+	outb(data, baseport1 + WPC8769L_CONFIG4_REG);
+
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_CONFIG5_REG)
+		| WPC8769L_CONFIG5_ON_MASK,
+		baseport1 + WPC8769L_CONFIG5_REG);
+
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_CONFIG6_MASK, baseport1 + WPC8769L_CONFIG6_REG);
+
+	outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG);
+	outb(0, baseport1 + WPC8769L_CONFIG7_REG);
+
+	if (baseport2) {
+		/*
+		 * This has to do with wake-up support, which is
+		 * disabled when the second I/O range doesn't
+		 * exist.
+		 */
+		/* -- internal subroutine -- */
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		data2 = inb(baseport2 + WPC8769L_WAKEUP_CONFIG3_REG);
+		a = (data2 >> WPC8769L_WAKEUP_CONFIG3_A_SHIFT)
+			& WPC8769L_WAKEUP_CONFIG3_A_MASK;
+		b = (data2 >> WPC8769L_WAKEUP_CONFIG3_B_SHIFT)
+			& WPC8769L_WAKEUP_CONFIG3_B_MASK;
+
+		data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG);
+		data &= ~WPC8769L_CLOCK_OFF_MASK;
+		data |= WPC8769L_CLOCK_ON_MASK;
+		outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG);
+
+		data2 &= ~WPC8769L_WAKEUP_CONFIG3_OFF_MASK;
+		data2 |= WPC8769L_WAKEUP_CONFIG3_ON_MASK;
+		outb(data2, baseport2 + WPC8769L_WAKEUP_CONFIG3_REG);
+		/* -- end internal subroutine -- */
+
+#ifdef LIRC_WPC8769L_WAKEUP
+		/* Call for setting wake up filters */
+		wpc8769l_configure_wakeup_triggers();
+#endif
+	} else {
+		/* No second port range. Take these defaults. */
+		a = (data_save & WPC8769L_WAKEUP_STATUS_LEG_MASK_A)
+			? 0 : 1;
+		b = (data_save & WPC8769L_WAKEUP_STATUS_LEG_MASK_B)
+			? 1 : 0;
+	}
+
+	outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG);
+
+	data = inb(baseport1 + WPC8769L_CONFIG3_REG);
+	data = (a == 1)
+		? (data & ~WPC8769L_CONFIG3_MASK_1)
+		: (data | WPC8769L_CONFIG3_MASK_1);
+	outb(data, baseport1 + WPC8769L_CONFIG3_REG);
+
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG);
+
+	data = inb(baseport1 + WPC8769L_CONFIG2_REG);
+	data = (b == 0)
+		? (data & ~WPC8769L_CONFIG2_MASK_1)
+		: (data | WPC8769L_CONFIG2_MASK_1);
+	outb(data, baseport1 + WPC8769L_CONFIG2_REG);
+
+	outb(0, baseport1 + WPC8769L_CONFIG8_REG);
+
+	outb(0, baseport1 + WPC8769L_CONFIG9_REG);
+
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG);
+	outb(inb(baseport1 + WPC8769L_INTERRUPT_REG)
+		| WPC8769L_INTERRUPT_1_MASK,
+		baseport1 + WPC8769L_INTERRUPT_REG);
+
+	spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags);
+}
+
+/* Called when the device is opened. */
+static int set_use_inc(void *data)
+{
+	int result;
+
+	/* Reset pulse values. */
+	last_was_pulse = 0;
+	last_counter = 0;
+
+	/* Reset last timeout value. */
+	lastus = 0;
+
+	/* Init the read buffer. */
+	if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0)
+		return -ENOMEM;
+
+	/* Acquire the IRQ. */
+	result = request_irq(irq, irq_handler,
+			   IRQF_DISABLED | IRQF_SHARED,
+			   LIRC_DRIVER_NAME, THIS_MODULE);
+
+	switch (result) {
+	case -EBUSY:
+		eprintk("IRQ %d busy\n", irq);
+		lirc_buffer_free(&rbuf);
+		return -EBUSY;
+	case -EINVAL:
+		eprintk("Bad irq number or handler\n");
+		lirc_buffer_free(&rbuf);
+		return -EINVAL;
+	default:
+		dprintk("IRQ %d obtained.\n", irq);
+		break;
+	};
+
+	/* Mark the device as open. */
+	lirc_wpc8769l_is_open = 1;
+
+	/* Enable hardware interrupts. */
+	wpc8769l_enable_interrupts();
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+/* Called when the device is released. */
+static void set_use_dec(void *data)
+{
+	/* Mark the device as closed. */
+	lirc_wpc8769l_is_open = 0;
+
+	/* Cancel the timeout if pending. */
+	del_timer_sync(&last_span_timer);
+
+	/* Disable the hardware interrupts. */
+	wpc8769l_disable_interrupts();
+
+	/* Free the IRQ. */
+	free_irq(irq, THIS_MODULE);
+	dprintk("Freed IRQ %d\n", irq);
+
+	/* Free the RX buffer. */
+	lirc_buffer_free(&rbuf);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static struct lirc_driver driver = {
+	.name		= LIRC_DRIVER_NAME,
+	.minor		= -1,
+	.code_length	= 1,
+	.sample_rate	= 0,
+	.data		= NULL,
+	.add_to_buf	= NULL,
+	.get_queue	= NULL,
+	.rbuf		= &rbuf,
+	.set_use_inc	= set_use_inc,
+	.set_use_dec	= set_use_dec,
+	.fops		= NULL,
+	.dev		= NULL,
+	.owner		= THIS_MODULE,
+};
+
+static acpi_status wec_parse_resources(struct acpi_resource *resource,
+	void *context)
+{
+	if (resource->type == ACPI_RESOURCE_TYPE_IO) {
+		/* Read the two I/O ranges. */
+		if (!baseport1)
+			baseport1 = resource->data.io.minimum;
+		else if (!baseport2)
+			baseport2 = resource->data.io.minimum;
+	} else if (resource->type == ACPI_RESOURCE_TYPE_IRQ) {
+		/* Read the rx IRQ number. */
+		if (!irq)
+			irq = resource->data.irq.interrupts[0];
+	}
+	return AE_OK;
+}
+
+static acpi_status wec_parse_device(acpi_handle handle, u32 level,
+	void *context, void **return_value)
+{
+	acpi_status status;
+	iprintk("Found %s device via ACPI.\n", WPC8769L_ACPI_HID);
+
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+		wec_parse_resources, NULL);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	return AE_OK;
+}
+
+/* Find the device I/O ranges and IRQ number by searching for the
+ * CIR ACPI entry. */
+static int wpc8769l_acpi_detect(void)
+{
+	acpi_status status;
+	status = acpi_get_devices(WPC8769L_ACPI_HID, wec_parse_device, NULL,
+		NULL);
+	if (ACPI_FAILURE(status))
+		return -ENOENT;
+	else
+		return 0;
+}
+
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+static struct platform_device *lirc_wpc8769l_platform_dev;
+
+static int __devinit lirc_wpc8769l_probe(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int __devexit lirc_wpc8769l_remove(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int lirc_wpc8769l_suspend(struct platform_device *dev,
+			       pm_message_t state)
+{
+	if (lirc_wpc8769l_is_open)
+		/* Disable all interrupts. */
+		wpc8769l_disable_interrupts();
+	return 0;
+}
+
+static int lirc_wpc8769l_resume(struct platform_device *dev)
+{
+	if (lirc_wpc8769l_is_open) {
+		/* Check if we caused resuming; we still do nothing about it. */
+		wpc8769l_power_up_and_check_if_we_woke_us_up();
+
+		/* Enable interrupts again. */
+		wpc8769l_enable_interrupts();
+	}
+	return 0;
+}
+
+static struct platform_driver lirc_wpc8769l_platform_driver = {
+	.probe		= lirc_wpc8769l_probe,
+	.remove		= __devexit_p(lirc_wpc8769l_remove),
+	.suspend	= lirc_wpc8769l_suspend,
+	.resume		= lirc_wpc8769l_resume,
+	.driver		= {
+		.name	= LIRC_DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init lirc_wpc8769l_platform_init(void)
+{
+	int result;
+
+	result = platform_driver_register(&lirc_wpc8769l_platform_driver);
+	if (result) {
+		eprintk("Platform driver register returned %d.\n", result);
+		return result;
+	}
+
+	lirc_wpc8769l_platform_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
+	if (!lirc_wpc8769l_platform_dev) {
+		result = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	result = platform_device_add(lirc_wpc8769l_platform_dev);
+	if (result)
+		goto exit_device_put;
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(lirc_wpc8769l_platform_dev);
+
+exit_driver_unregister:
+	platform_driver_unregister(&lirc_wpc8769l_platform_driver);
+	return result;
+}
+
+static void __exit lirc_wpc8769l_platform_exit(void)
+{
+	platform_device_unregister(lirc_wpc8769l_platform_dev);
+	platform_driver_unregister(&lirc_wpc8769l_platform_driver);
+}
+#endif
+
+static int __init lirc_wpc8769l_module_init(void)
+{
+	int rc;
+
+	/* If needed, read the resource information for the ACPI device
+	 * description. */
+	if (!skip_probe) {
+		rc = wpc8769l_acpi_detect();
+		if (rc) {
+			eprintk("Error when looking for %s ACPI device.\n",
+				WPC8769L_ACPI_HID);
+			return rc;
+		}
+	}
+
+	/* Check that we got some resource info to work with. */
+	if (!baseport1 || !irq) {
+		rc = -ENODEV;
+		eprintk("Not all required resources found for %s device.\n",
+			LIRC_DRIVER_NAME);
+		return rc;
+	}
+
+	dprintk("%s device found to use 0x%04x, 0x%04x I/O bases, IRQ #%d.\n",
+		LIRC_DRIVER_NAME, baseport1, baseport2, irq);
+
+	/* Request the two I/O regions. */
+	wpc8769l_portblock1_resource = request_region(baseport1,
+		WPC8769L_IO_REGION_1_SIZE, LIRC_DRIVER_NAME);
+	if (!wpc8769l_portblock1_resource) {
+		rc = -EBUSY;
+		eprintk("Could not allocate I/O range at 0x%04x", baseport1);
+		return rc;
+	}
+	if (baseport2) {
+		wpc8769l_portblock2_resource = request_region(baseport2,
+			WPC8769L_IO_REGION_2_SIZE, LIRC_DRIVER_NAME);
+		if (!wpc8769l_portblock2_resource) {
+			rc = -EBUSY;
+			printk(KERN_ERR "Could not allocate I/O range "
+			       "at 0x%04x",
+				baseport2);
+			goto exit_release_region_1;
+		}
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	/* Register the platform driver and device. */
+	rc = lirc_wpc8769l_platform_init();
+	if (rc)
+		goto exit_release_region_2;
+#endif
+
+	/* Prepare the hardware. */
+	wpc8769l_prepare_hardware();
+
+	/* Do load-time checks. */
+	wpc8769l_power_up_and_check_if_we_woke_us_up();
+
+	/* Configure the driver hooks. */
+	driver.features = LIRC_CAN_REC_MODE2;
+	driver.minor = lirc_register_driver(&driver);
+	if (driver.minor < 0) {
+		eprintk("lirc_register_driver failed!\n");
+		rc = -EIO;
+		goto exit_platform_exit;
+	}
+
+	iprintk("Driver loaded.\n");
+
+	return 0; /* Everything OK. */
+
+exit_platform_exit:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	lirc_wpc8769l_platform_exit();
+
+exit_release_region_2:
+#endif
+	if (baseport2)
+		release_region(baseport2, WPC8769L_IO_REGION_2_SIZE);
+
+exit_release_region_1:
+	release_region(baseport1, WPC8769L_IO_REGION_1_SIZE);
+
+	return rc;
+}
+
+module_init(lirc_wpc8769l_module_init);
+
+static void __exit lirc_wpc8769l_module_exit(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
+	/* Unregister the platform driver and device. */
+	lirc_wpc8769l_platform_exit();
+#endif
+
+	/* Unregister the LIRC driver. */
+	lirc_unregister_driver(driver.minor);
+
+	/* Release the second range. */
+	if (baseport2)
+		release_region(baseport2, WPC8769L_IO_REGION_2_SIZE);
+
+	/* Release the first range. */
+	release_region(baseport1, WPC8769L_IO_REGION_1_SIZE);
+
+	iprintk("Driver unloaded.\n");
+}
+
+module_exit(lirc_wpc8769l_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Juan J. Garcia de Soria");
+MODULE_DESCRIPTION("Driver for the integrated Winbond WPC8769L-based IR\
+ receiver found in Acer laptops.");
+MODULE_VERSION("0.0");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+
+module_param(baseport1, uint, S_IRUGO);
+MODULE_PARM_DESC(baseport1,
+	"First I/O range base address (default: ACPI autodetect).");
+
+module_param(baseport2, uint, S_IRUGO);
+MODULE_PARM_DESC(baseport2,
+	"Second I/O range base address (default: ACPI autodetect).");
+
+module_param(irq, uint, S_IRUGO);
+MODULE_PARM_DESC(irq, "IRQ number (default: ACPI autodetect).");
+
+module_param(skip_probe, bool, S_IRUGO);
+MODULE_PARM_DESC(skip_probe,
+	"Skip ACPI-based device detection \
+(default: false for ACPI autodetect).");
+
+#ifdef LIRC_WPC8769L_WAKEUP
+module_param(protocol_select, int, S_IRUGO);
+MODULE_PARM_DESC(protocol_select,
+	"Define the protocol for wake up functions (default: 2).");
+
+module_param(max_info_bits, int, S_IRUGO);
+MODULE_PARM_DESC(max_info_bits,
+	"Define the maximum info bits for wake up functions (default: 24).");
+
+module_param(rc_wakeup_code, uint, S_IRUGO);
+MODULE_PARM_DESC(rc_wakeup_code,
+	"Define the RC code value for wake up functions\
+ (default: 0x7ffffbf3).");
+
+module_param(rc_wakeup_mask, uint, S_IRUGO);
+MODULE_PARM_DESC(rc_wakeup_mask,
+	"Define the RC code mask for wake up functions (default: 0xff000fff).");
+#endif
+
+EXPORT_NO_SYMBOLS;
+
+#endif /* MODULE */
+
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_wpc8769l/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_wpc8769l/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_WPC8769l)	+= lirc_wpc8769l.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.h
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.h
@@ -0,0 +1,186 @@
+/*      $Id: lirc_wpc8769l.h,v 1.5 2009/06/15 15:11:39 jarodwilson Exp $      */
+
+/****************************************************************************
+ ** lirc_wpc8769l.h ****************************************************
+ ****************************************************************************
+ *
+ * lirc_wpc8769l - Device driver for the integrated CIR receiver found in
+ *                 Acer Aspire 6530G (and probably other models), based on
+ *                 the Winbond 8769L embedded controller.
+ *                 (Written using the lirc_serial driver as a guide).
+ *
+ * Copyright (C) 2008, 2009 Juan J. Garcia de Soria <skandalfo@gmail.com>
+ *  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/types.h>
+
+/* Name of the ACPI resource used to autodetect the receiver. */
+#define WPC8769L_ACPI_HID "WEC1020"
+
+/* Number of microseconds for a whole byte of samples. */
+/* This is assuming 20 kHz bit sampling frequency.     */
+#define WPC8769L_USECS_PER_BYTE 400
+
+/* Number of microseconds for a bit sample. */
+#define WPC8769L_USECS_PER_BIT (WPC8769L_USECS_PER_BYTE >> 3)
+
+/* Number of bytes in each data burst. */
+#define WPC8769L_BYTES_PER_BURST 14
+
+/* Number of 0xff bytes before reset. */
+#define WPC8769L_FF_BYTES_BEFORE_RESET 250
+
+/* Microseconds timeout for last part of code. */
+#define WPC8769L_LAST_TIMEOUT_JIFFIES (HZ / 20)
+
+/* Microseconds timeout for last part of code. */
+#define WPC8769L_LAST_TIMEOUT_JIFFIES (HZ / 20)
+
+/* Size of I/O region 1. */
+#define WPC8769L_IO_REGION_1_SIZE 0x08
+
+/* Size of I/O region 2. */
+#define WPC8769L_IO_REGION_2_SIZE 0x20
+
+/* Size of a byte array for a complete burst, rounded
+ * up to an integral number of unsigned longs. */
+#define WPC8769L_BYTE_BUFFER_SIZE \
+	(((WPC8769L_BYTES_PER_BURST + 1 + BITS_PER_LONG / 8 - 1) \
+	/ (BITS_PER_LONG / 8)) * (BITS_PER_LONG / 8))
+
+
+
+/* WPC8769L register set definitions. Note that these are all wild guesses.*/
+
+/* Registers for I/O range 1. */
+#define WPC8769L_SELECT_REG			0x03
+
+/*------------*/
+#define WPC8769L_BANK_00			0x00
+
+#define WPC8769L_DATA_REG			0x00
+
+#define WPC8769L_INTERRUPT_REG			0x01
+#define WPC8769L_INTERRUPT_1_MASK		0x01
+#define WPC8769L_INTERRUPT_2_MASK		0x01
+
+#define WPC8769L_DATA_STATUS_REG		0x02
+#define WPC8769L_DATA_READY_MASK		0x01
+#define WPC8769L_DATA_STATUS_MASK_1		0x02
+#define WPC8769L_DATA_STATUS_MASK_2		0xd0
+
+#define WPC8769L_CONFIG_REG			0x04
+#define WPC8769L_CONFIG_OFF_MASK		0xe0
+#define WPC8769L_CONFIG_ON_MASK			0xc0
+
+#define WPC8769L_DATA_ACK_REG			0x05
+#define WPC8769L_DATA_ACK_MASK			0x01
+
+#define WPC8769L_TIMEOUT_RESET_REG		0x07
+#define WPC8769L_TIMEOUT_RESET_MASK		0x20
+
+/*------------*/
+#define WPC8769L_BANK_E0			0xe0
+
+#define WPC8769L_CONFIG6_REG			0x00
+#define WPC8769L_CONFIG6_MASK			0x4b
+
+#define WPC8769L_CONFIG7_REG			0x01
+
+#define WPC8769L_HARDWARE_ENABLE1_REG		0x02
+#define WPC8769L_HARDWARE_ENABLE1_MASK		0x01
+
+#define WPC8769L_CONFIG5_REG			0x04
+#define WPC8769L_CONFIG5_ON_MASK		0x30
+
+#define WPC8769L_REMAINING_RX_DATA_REG		0x07
+
+/*------------*/
+#define WPC8769L_BANK_E4			0xe4
+
+#define WPC8769L_READ_ON_STARTUP_REG		0x00
+
+/*------------*/
+#define WPC8769L_BANK_EC			0xec
+
+#define WPC8769L_CONFIG3_REG			0x04
+#define WPC8769L_CONFIG3_ON_MASK		0x01
+#define WPC8769L_CONFIG3_MASK_1			0x10
+
+/*------------*/
+#define WPC8769L_BANK_F0			0xf0
+
+#define WPC8769L_WAKEUP_STATUS_LEG_REG		0x02
+#define WPC8769L_WAKEUP_STATUS_LEG_MASK		0x04
+#define WPC8769L_WAKEUP_STATUS_LEG_MASK_A	0x02
+#define WPC8769L_WAKEUP_STATUS_LEG_MASK_B	0x08
+
+/*------------*/
+#define WPC8769L_BANK_F4			0xf4
+
+#define WPC8769L_CONFIG9_REG			0x01
+
+#define WPC8769L_CONFIG4_REG			0x02
+#define WPC8769L_CONFIG4_AND_MASK		0x0f
+#define WPC8769L_CONFIG4_ON_MASK		0x50
+
+#define WPC8769L_CONFIG8_REG			0x04
+
+#define WPC8769L_CONFIG2_REG			0x07
+#define WPC8769L_CONFIG2_OFF_MASK		0x20
+#define WPC8769L_CONFIG2_MASK_1			0x10
+
+
+/* Registers for I/O range 2. */
+#define WPC8769L_WAKEUP_ACK_REG			0x00
+#define WPC8769L_WAKEUP_ACK_MASK		0x10
+
+#define WPC8769L_WAKEUP_ENABLE_REG		0x02
+#define WPC8769L_WAKEUP_ENABLE_MASK		0x10
+
+#define WPC8769L_BANK2_CLOCK_REG		0x04
+#define WPC8769L_CLOCK_OFF_MASK			0x02
+#define WPC8769L_CLOCK_ON_MASK			0x01
+
+#define WPC8769L_WAKEUP_CONFIG_REG		0x1a
+#define WPC8769L_WAKEUP_CONFIG_PRE_MASK		0x80
+#define WPC8769L_MAX_INFO_BITS_BIAS		0x0e
+#define WPC8769L_MAX_INFO_BITS_SHIFT		0x01
+
+#define WPC8769L_WAKEUP_CONFIG3_REG		0x13
+#define WPC8769L_WAKEUP_CONFIG3_OFF_MASK	0x10
+#define WPC8769L_WAKEUP_CONFIG3_ON_MASK		0x21
+#define WPC8769L_WAKEUP_CONFIG3_A_SHIFT		0x01
+#define WPC8769L_WAKEUP_CONFIG3_A_MASK		0x03
+#define WPC8769L_WAKEUP_CONFIG3_B_SHIFT		0x03
+#define WPC8769L_WAKEUP_CONFIG3_B_MASK		0x01
+
+#define WPC8769L_WAKEUP_STATUS_REG		0x14
+#define WPC8769L_WAKEUP_WOKE_UP_MASK		0x01
+#define WPC8769L_WAKEUP_CONFIGURING_MASK	0x17
+
+#define WPC8769L_WAKEUP_CONFIG2_REG		0x15
+#define WPC8769L_WAKEUP_CONFIG2_AND_MASK	0xf9
+#define WPC8769L_WAKEUP_CONFIG2_OR_MASK		0x01
+
+#define WPC8769L_WAKEUP_DATA_PTR_REG		0x18
+#define WPC8769L_WAKEUP_DATA_BITS		0x20
+#define WPC8769L_WAKEUP_DATA_BASE		0x10
+#define WPC8769L_WAKEUP_MASK_BASE		0x20
+
+#define WPC8769L_WAKEUP_DATA_REG		0x19
+
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ite8709/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ite8709/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_ITE8709)	+= lirc_ite8709.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_ite8709/lirc_ite8709.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_ite8709/lirc_ite8709.c
@@ -0,0 +1,552 @@
+/*
+ * LIRC driver for ITE8709 CIR port
+ *
+ * Copyright (C) 2008 Grégory Lardière <spmf2004-lirc@yahoo.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
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pnp.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#include <asm/io.h>
+#else
+#include <linux/io.h>
+#endif
+
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+#include "../kcompat.h"
+
+#define LIRC_DRIVER_NAME "lirc_ite8709"
+
+#define BUF_CHUNK_SIZE	sizeof(lirc_t)
+#define BUF_SIZE	(128*BUF_CHUNK_SIZE)
+
+/*
+ * The ITE8709 device seems to be the combination of IT8512 superIO chip and
+ * a specific firmware running on the IT8512's embedded micro-controller.
+ * In addition of the embedded micro-controller, the IT8512 chip contains a
+ * CIR module and several other modules. A few modules are directly accessible
+ * by the host CPU, but most of them are only accessible by the
+ * micro-controller. The CIR module is only accessible by the micro-controller.
+ * The battery-backed SRAM module is accessible by the host CPU and the
+ * micro-controller. So one of the MC's firmware role is to act as a bridge
+ * between the host CPU and the CIR module. The firmware implements a kind of
+ * communication protocol using the SRAM module as a shared memory. The IT8512
+ * specification is publicly available on ITE's web site, but the communication
+ * protocol is not, so it was reverse-engineered.
+ */
+
+/* ITE8709 Registers addresses and values (reverse-engineered) */
+#define ITE8709_MODE		0x1a
+#define ITE8709_REG_ADR		0x1b
+#define ITE8709_REG_VAL		0x1c
+#define ITE8709_IIR		0x1e  /* Interrupt identification register */
+#define ITE8709_RFSR		0x1f  /* Receiver FIFO status register */
+#define ITE8709_FIFO_START	0x20
+
+#define ITE8709_MODE_READY	0X00
+#define ITE8709_MODE_WRITE	0X01
+#define ITE8709_MODE_READ	0X02
+#define ITE8709_IIR_RDAI	0x02  /* Receiver data available interrupt */
+#define ITE8709_IIR_RFOI	0x04  /* Receiver FIFO overrun interrupt */
+#define ITE8709_RFSR_MASK	0x3f  /* FIFO byte count mask */
+
+/*
+ * IT8512 CIR-module registers addresses and values
+ * (from IT8512 E/F specification v0.4.1)
+ */
+#define IT8512_REG_MSTCR	0x01  /* Master control register */
+#define IT8512_REG_IER		0x02  /* Interrupt enable register */
+#define IT8512_REG_CFR		0x04  /* Carrier frequency register */
+#define IT8512_REG_RCR		0x05  /* Receive control register */
+#define IT8512_REG_BDLR		0x08  /* Baud rate divisor low byte register */
+#define IT8512_REG_BDHR		0x09  /* Baud rate divisor high byte register */
+
+#define IT8512_MSTCR_RESET	0x01  /* Reset registers to default value */
+#define IT8512_MSTCR_FIFOCLR	0x02  /* Clear FIFO */
+#define IT8512_MSTCR_FIFOTL_7	0x04  /* FIFO threshold level : 7 */
+#define IT8512_MSTCR_FIFOTL_25	0x0c  /* FIFO threshold level : 25 */
+#define IT8512_IER_RDAIE	0x02  /* Enable data interrupt request */
+#define IT8512_IER_RFOIE	0x04  /* Enable FIFO overrun interrupt req */
+#define IT8512_IER_IEC		0x80  /* Enable interrupt request */
+#define IT8512_CFR_CF_36KHZ	0x09  /* Carrier freq : low speed, 36kHz */
+#define IT8512_RCR_RXDCR_1	0x01  /* Demodulation carrier range : 1 */
+#define IT8512_RCR_RXACT	0x08  /* Receiver active */
+#define IT8512_RCR_RXEN		0x80  /* Receiver enable */
+#define IT8512_BDR_6		6     /* Baud rate divisor : 6 */
+
+/* Actual values used by this driver */
+#define CFG_FIFOTL	IT8512_MSTCR_FIFOTL_25
+#define CFG_CR_FREQ	IT8512_CFR_CF_36KHZ
+#define CFG_DCR		IT8512_RCR_RXDCR_1
+#define CFG_BDR		IT8512_BDR_6
+#define CFG_TIMEOUT	100000 /* Rearm interrupt when a space is > 100 ms */
+
+static int debug;
+
+struct ite8709_device {
+	int use_count;
+	int io;
+	int irq;
+	spinlock_t hardware_lock;
+	unsigned long long acc_pulse;
+	unsigned long long acc_space;
+	char lastbit;
+	struct timeval last_tv;
+	struct lirc_driver driver;
+	struct lirc_buffer buffer;
+	struct tasklet_struct tasklet;
+	char force_rearm;
+	char rearmed;
+	char device_busy;
+};
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
+				fmt, ## args);			\
+	} while (0)
+
+
+static unsigned char ite8709_read(struct ite8709_device *dev,
+					unsigned char port)
+{
+	outb(port, dev->io);
+	return inb(dev->io+1);
+}
+
+static void ite8709_write(struct ite8709_device *dev, unsigned char port,
+				unsigned char data)
+{
+	outb(port, dev->io);
+	outb(data, dev->io+1);
+}
+
+static void ite8709_wait_device(struct ite8709_device *dev)
+{
+	int i = 0;
+	/*
+	 * loop until device tells it's ready to continue
+	 * iterations count is usually ~750 but can sometimes achieve 13000
+	 */
+	for (i = 0; i < 15000; i++) {
+		udelay(2);
+		if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY)
+			break;
+	}
+}
+
+static void ite8709_write_register(struct ite8709_device *dev,
+				unsigned char reg_adr, unsigned char reg_value)
+{
+	ite8709_wait_device(dev);
+
+	ite8709_write(dev, ITE8709_REG_VAL, reg_value);
+	ite8709_write(dev, ITE8709_REG_ADR, reg_adr);
+	ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE);
+}
+
+static void ite8709_init_hardware(struct ite8709_device *dev)
+{
+	spin_lock_irq(&dev->hardware_lock);
+	dev->device_busy = 1;
+	spin_unlock_irq(&dev->hardware_lock);
+
+	ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff);
+	ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff);
+	ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ);
+	ite8709_write_register(dev, IT8512_REG_IER,
+			IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE);
+	ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR);
+	ite8709_write_register(dev, IT8512_REG_MSTCR,
+					CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
+	ite8709_write_register(dev, IT8512_REG_RCR,
+				IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
+
+	spin_lock_irq(&dev->hardware_lock);
+	dev->device_busy = 0;
+	spin_unlock_irq(&dev->hardware_lock);
+
+	tasklet_enable(&dev->tasklet);
+}
+
+static void ite8709_drop_hardware(struct ite8709_device *dev)
+{
+	tasklet_disable(&dev->tasklet);
+
+	spin_lock_irq(&dev->hardware_lock);
+	dev->device_busy = 1;
+	spin_unlock_irq(&dev->hardware_lock);
+
+	ite8709_write_register(dev, IT8512_REG_RCR, 0);
+	ite8709_write_register(dev, IT8512_REG_MSTCR,
+				IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR);
+
+	spin_lock_irq(&dev->hardware_lock);
+	dev->device_busy = 0;
+	spin_unlock_irq(&dev->hardware_lock);
+}
+
+static int ite8709_set_use_inc(void *data)
+{
+	struct ite8709_device *dev;
+	MOD_INC_USE_COUNT;
+	dev = data;
+	if (dev->use_count == 0)
+		ite8709_init_hardware(dev);
+	dev->use_count++;
+	return 0;
+}
+
+static void ite8709_set_use_dec(void *data)
+{
+	struct ite8709_device *dev;
+	MOD_DEC_USE_COUNT;
+	dev = data;
+	dev->use_count--;
+	if (dev->use_count == 0)
+		ite8709_drop_hardware(dev);
+}
+
+static void ite8709_add_read_queue(struct ite8709_device *dev, int flag,
+					unsigned long long val)
+{
+	lirc_t value;
+
+	dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space");
+
+	value = (val > PULSE_MASK) ? PULSE_MASK : val;
+	if (flag)
+		value |= PULSE_BIT;
+
+	if (!lirc_buffer_full(&dev->buffer)) {
+		lirc_buffer_write(&dev->buffer, (void *) &value);
+		wake_up(&dev->buffer.wait_poll);
+	}
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static irqreturn_t ite8709_interrupt(int irq, void *dev_id,
+					struct pt_regs *regs)
+#else
+static irqreturn_t ite8709_interrupt(int irq, void *dev_id)
+#endif
+{
+	unsigned char data;
+	int iir, rfsr, i;
+	int fifo = 0;
+	char bit;
+	struct timeval curr_tv;
+
+	/* Bit duration in microseconds */
+	const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR);
+
+	struct ite8709_device *dev;
+	dev = dev_id;
+
+	/*
+	 * If device is busy, we simply discard data because we are in one of
+	 * these two cases : shutting down or rearming the device, so this
+	 * doesn't really matter and this avoids waiting too long in IRQ ctx
+	 */
+	spin_lock(&dev->hardware_lock);
+	if (dev->device_busy) {
+		spin_unlock(&dev->hardware_lock);
+		return IRQ_RETVAL(IRQ_HANDLED);
+	}
+
+	iir = ite8709_read(dev, ITE8709_IIR);
+
+	switch (iir) {
+	case ITE8709_IIR_RFOI:
+		dprintk("fifo overrun, scheduling forced rearm just in case\n");
+		dev->force_rearm = 1;
+		tasklet_schedule(&dev->tasklet);
+		spin_unlock(&dev->hardware_lock);
+		return IRQ_RETVAL(IRQ_HANDLED);
+
+	case ITE8709_IIR_RDAI:
+		rfsr = ite8709_read(dev, ITE8709_RFSR);
+		fifo = rfsr & ITE8709_RFSR_MASK;
+		if (fifo > 32)
+			fifo = 32;
+		dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo);
+
+		if (dev->rearmed) {
+			do_gettimeofday(&curr_tv);
+			dev->acc_space += 1000000ull
+				* (curr_tv.tv_sec - dev->last_tv.tv_sec)
+				+ (curr_tv.tv_usec - dev->last_tv.tv_usec);
+			dev->rearmed = 0;
+		}
+		for (i = 0; i < fifo; i++) {
+			data = ite8709_read(dev, i+ITE8709_FIFO_START);
+			data = ~data;
+			/* Loop through */
+			for (bit = 0; bit < 8; ++bit) {
+				if ((data >> bit) & 1) {
+					dev->acc_pulse += bit_duration;
+					if (dev->lastbit == 0) {
+						ite8709_add_read_queue(dev, 0,
+							dev->acc_space);
+						dev->acc_space = 0;
+					}
+				} else {
+					dev->acc_space += bit_duration;
+					if (dev->lastbit == 1) {
+						ite8709_add_read_queue(dev, 1,
+							dev->acc_pulse);
+						dev->acc_pulse = 0;
+					}
+				}
+				dev->lastbit = (data >> bit) & 1;
+			}
+		}
+		ite8709_write(dev, ITE8709_RFSR, 0);
+
+		if (dev->acc_space > CFG_TIMEOUT) {
+			dprintk("scheduling rearm IRQ\n");
+			do_gettimeofday(&dev->last_tv);
+			dev->force_rearm = 0;
+			tasklet_schedule(&dev->tasklet);
+		}
+
+		spin_unlock(&dev->hardware_lock);
+		return IRQ_RETVAL(IRQ_HANDLED);
+
+	default:
+		/* not our irq */
+		dprintk("unknown IRQ (shouldn't happen) !!\n");
+		spin_unlock(&dev->hardware_lock);
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+}
+
+static void ite8709_rearm_irq(unsigned long data)
+{
+	struct ite8709_device *dev;
+	unsigned long flags;
+	dev = (struct ite8709_device *) data;
+
+	spin_lock_irqsave(&dev->hardware_lock, flags);
+	dev->device_busy = 1;
+	spin_unlock_irqrestore(&dev->hardware_lock, flags);
+
+	if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) {
+		dprintk("rearming IRQ\n");
+		ite8709_write_register(dev, IT8512_REG_RCR,
+						IT8512_RCR_RXACT | CFG_DCR);
+		ite8709_write_register(dev, IT8512_REG_MSTCR,
+					CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
+		ite8709_write_register(dev, IT8512_REG_RCR,
+				IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
+		if (!dev->force_rearm)
+			dev->rearmed = 1;
+		dev->force_rearm = 0;
+	}
+
+	spin_lock_irqsave(&dev->hardware_lock, flags);
+	dev->device_busy = 0;
+	spin_unlock_irqrestore(&dev->hardware_lock, flags);
+}
+
+static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno,
+				char *msg)
+{
+	if (msg != NULL)
+		printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg);
+
+	switch (stage) {
+	case 6:
+		if (dev->use_count > 0)
+			ite8709_drop_hardware(dev);
+	case 5:
+		free_irq(dev->irq, dev);
+	case 4:
+		release_region(dev->io, 2);
+	case 3:
+		lirc_unregister_driver(dev->driver.minor);
+	case 2:
+		lirc_buffer_free(dev->driver.rbuf);
+	case 1:
+		kfree(dev);
+	case 0:
+		;
+	}
+
+	return errno;
+}
+
+static int __devinit ite8709_pnp_probe(struct pnp_dev *dev,
+					const struct pnp_device_id *dev_id)
+{
+	struct lirc_driver *driver;
+	struct ite8709_device *ite8709_dev;
+	int ret;
+
+	/* Check resources validity */
+	if (!pnp_irq_valid(dev, 0))
+		return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ");
+	if (!pnp_port_valid(dev, 2))
+		return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port");
+
+	/* Allocate memory for device struct */
+	ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL);
+	if (ite8709_dev == NULL)
+		return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed");
+	pnp_set_drvdata(dev, ite8709_dev);
+
+	/* Initialize device struct */
+	ite8709_dev->use_count = 0;
+	ite8709_dev->irq = pnp_irq(dev, 0);
+	ite8709_dev->io = pnp_port_start(dev, 2);
+	ite8709_dev->hardware_lock = __SPIN_LOCK_UNLOCKED(
+					ite8709_dev->hardware_lock);
+	ite8709_dev->acc_pulse = 0;
+	ite8709_dev->acc_space = 0;
+	ite8709_dev->lastbit = 0;
+	do_gettimeofday(&ite8709_dev->last_tv);
+	tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq,
+							(long) ite8709_dev);
+	ite8709_dev->force_rearm = 0;
+	ite8709_dev->rearmed = 0;
+	ite8709_dev->device_busy = 0;
+
+	/* Initialize driver struct */
+	driver = &ite8709_dev->driver;
+	strcpy(driver->name, LIRC_DRIVER_NAME);
+	driver->minor = -1;
+	driver->code_length = sizeof(lirc_t) * 8;
+	driver->sample_rate = 0;
+	driver->features = LIRC_CAN_REC_MODE2;
+	driver->data = ite8709_dev;
+	driver->add_to_buf = NULL;
+#ifndef LIRC_REMOVE_DURING_EXPORT
+	driver->get_queue = NULL;
+#endif
+	driver->rbuf = &ite8709_dev->buffer;
+	driver->set_use_inc = ite8709_set_use_inc;
+	driver->set_use_dec = ite8709_set_use_dec;
+	driver->fops = NULL;
+	driver->dev = &dev->dev;
+	driver->owner = THIS_MODULE;
+
+	/* Initialize LIRC buffer */
+	if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE))
+		return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
+				       "lirc_buffer_init() failed");
+
+	/* Register LIRC driver */
+	ret = lirc_register_driver(driver);
+	if (ret < 0)
+		return ite8709_cleanup(ite8709_dev, 2, ret,
+					"lirc_register_driver() failed");
+
+	/* Reserve I/O port access */
+	if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME))
+		return ite8709_cleanup(ite8709_dev, 3, -EBUSY,
+						"i/o port already in use");
+
+	/* Reserve IRQ line */
+	ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0,
+					LIRC_DRIVER_NAME, ite8709_dev);
+	if (ret < 0)
+		return ite8709_cleanup(ite8709_dev, 4, ret,
+						"IRQ already in use");
+
+	/* Initialize hardware */
+	ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */
+
+	printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n",
+					ite8709_dev->irq, ite8709_dev->io);
+
+	return 0;
+}
+
+static void __devexit ite8709_pnp_remove(struct pnp_dev *dev)
+{
+	struct ite8709_device *ite8709_dev;
+	ite8709_dev = pnp_get_drvdata(dev);
+
+	ite8709_cleanup(ite8709_dev, 6, 0, NULL);
+
+	printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n");
+}
+
+#ifdef CONFIG_PM
+static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+	struct ite8709_device *ite8709_dev;
+	ite8709_dev = pnp_get_drvdata(dev);
+
+	if (ite8709_dev->use_count > 0)
+		ite8709_drop_hardware(ite8709_dev);
+
+	return 0;
+}
+
+static int ite8709_pnp_resume(struct pnp_dev *dev)
+{
+	struct ite8709_device *ite8709_dev;
+	ite8709_dev = pnp_get_drvdata(dev);
+
+	if (ite8709_dev->use_count > 0)
+		ite8709_init_hardware(ite8709_dev);
+
+	return 0;
+}
+#else
+#define ite8709_pnp_suspend NULL
+#define ite8709_pnp_resume NULL
+#endif
+
+static const struct pnp_device_id pnp_dev_table[] = {
+	{"ITE8709", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+static struct pnp_driver ite8709_pnp_driver = {
+	.name           = LIRC_DRIVER_NAME,
+	.probe          = ite8709_pnp_probe,
+	.remove         = __devexit_p(ite8709_pnp_remove),
+	.suspend        = ite8709_pnp_suspend,
+	.resume         = ite8709_pnp_resume,
+	.id_table       = pnp_dev_table,
+};
+
+int init_module(void)
+{
+	return pnp_register_driver(&ite8709_pnp_driver);
+}
+
+void cleanup_module(void)
+{
+	pnp_unregister_driver(&ite8709_pnp_driver);
+}
+
+MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port");
+MODULE_AUTHOR("Grégory Lardière");
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c
@@ -0,0 +1,637 @@
+/*
+ * lirc_igorplugusb - USB remote support for LIRC
+ *
+ * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware.
+ * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm
+ *
+ * The device can only record bursts of up to 36 pulses/spaces.
+ * Works fine with RC5. Longer commands lead to device buffer overrun.
+ * (Maybe a better firmware or a microcontroller with more ram can help?)
+ *
+ * Version 0.1  [beta status]
+ *
+ * Copyright (C) 2004 Jan M. Hochstein
+ *	<hochstein@algo.informatik.tu-darmstadt.de>
+ *
+ * This driver was derived from:
+ *   Paul Miller <pmiller9@users.sourceforge.net>
+ *      "lirc_atiusb" module
+ *   Vladimir Dergachev <volodya@minspring.com>'s 2002
+ *      "USB ATI Remote support" (input device)
+ *   Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
+ *      "USB StreamZap remote driver" (LIRC)
+ *   Artur Lipowski <alipowski@kki.net.pl>'s 2002
+ *      "lirc_dev" and "lirc_gpio" LIRC modules
+ */
+
+/*
+ * 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/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#error "*******************************************************"
+#error "Sorry, this driver needs kernel version 2.4.0 or higher"
+#error "*******************************************************"
+#endif
+
+#include <linux/autoconf.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <linux/smp_lock.h>
+#include <linux/time.h>
+
+#include "../kcompat.h"
+#include "../lirc.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#if !defined(KERNEL_2_5)
+#define USB_CTRL_GET_TIMEOUT    5
+#endif
+
+/* module identification */
+#define DRIVER_VERSION		"0.2"
+#define DRIVER_AUTHOR		\
+	"Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>"
+#define DRIVER_DESC		"USB remote driver for LIRC"
+#define DRIVER_NAME		"lirc_igorplugusb"
+
+/* debugging support */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG DRIVER_NAME fmt, ## args);	\
+	} while (0)
+
+/* One mode2 pulse/space has 4 bytes. */
+#define CODE_LENGTH	     sizeof(lirc_t)
+
+/* Igor's firmware cannot record bursts longer than 36. */
+#define DEVICE_BUFLEN	   36
+
+/*
+ * Header at the beginning of the device's buffer:
+ *	unsigned char data_length
+ *	unsigned char data_start    (!=0 means ring-buffer overrun)
+ *	unsigned char counter       (incremented by each burst)
+ */
+#define DEVICE_HEADERLEN	3
+
+/* This is for the gap */
+#define ADDITIONAL_LIRC_BYTES   2
+
+/* times to poll per second */
+#define SAMPLE_RATE	     100
+static int sample_rate = SAMPLE_RATE;
+
+
+/**** Igor's USB Request Codes */
+
+#define SET_INFRABUFFER_EMPTY   1
+/**
+ * Params: none
+ * Answer: empty
+ */
+
+#define GET_INFRACODE	   2
+/**
+ * Params:
+ *   wValue: offset to begin reading infra buffer
+ *
+ * Answer: infra data
+ */
+
+#define SET_DATAPORT_DIRECTION  3
+/**
+ * Params:
+ *   wValue: (byte) 1 bit for each data port pin (0=in, 1=out)
+ *
+ * Answer: empty
+ */
+
+#define GET_DATAPORT_DIRECTION  4
+/**
+ * Params: none
+ *
+ * Answer: (byte) 1 bit for each data port pin (0=in, 1=out)
+ */
+
+#define SET_OUT_DATAPORT	5
+/**
+ * Params:
+ *   wValue: byte to write to output data port
+ *
+ * Answer: empty
+ */
+
+#define GET_OUT_DATAPORT	6
+/**
+ * Params: none
+ *
+ * Answer: least significant 3 bits read from output data port
+ */
+
+#define GET_IN_DATAPORT	 7
+/**
+ * Params: none
+ *
+ * Answer: least significant 3 bits read from input data port
+ */
+
+#define READ_EEPROM	     8
+/**
+ * Params:
+ *   wValue: offset to begin reading EEPROM
+ *
+ * Answer: EEPROM bytes
+ */
+
+#define WRITE_EEPROM	    9
+/**
+ * Params:
+ *   wValue: offset to EEPROM byte
+ *   wIndex: byte to write
+ *
+ * Answer: empty
+ */
+
+#define SEND_RS232	      10
+/**
+ * Params:
+ *   wValue: byte to send
+ *
+ * Answer: empty
+ */
+
+#define RECV_RS232	      11
+/**
+ * Params: none
+ *
+ * Answer: byte received
+ */
+
+#define SET_RS232_BAUD	  12
+/**
+ * Params:
+ *   wValue: byte to write to UART bit rate register (UBRR)
+ *
+ * Answer: empty
+ */
+
+#define GET_RS232_BAUD	  13
+/**
+ * Params: none
+ *
+ * Answer: byte read from UART bit rate register (UBRR)
+ */
+
+
+/* data structure for each usb remote */
+struct igorplug {
+
+	/* usb */
+	struct usb_device *usbdev;
+	struct urb *urb_in;
+	int devnum;
+
+	unsigned char *buf_in;
+	unsigned int len_in;
+	int in_space;
+	struct timeval last_time;
+
+#if defined(KERNEL_2_5)
+	dma_addr_t dma_in;
+#endif
+
+	/* lirc */
+	struct lirc_driver *d;
+
+	/* handle sending (init strings) */
+	int send_flags;
+};
+
+static int set_use_inc(void *data)
+{
+	struct igorplug *ir = data;
+
+	if (!ir) {
+		printk(KERN_ERR DRIVER_NAME
+		       "[?]: set_use_inc called with no context\n");
+		return -EIO;
+	}
+	dprintk("[%d]: set use inc\n", ir->devnum);
+
+	MOD_INC_USE_COUNT;
+
+	if (!ir->usbdev)
+		return -ENODEV;
+
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	struct igorplug *ir = data;
+
+	if (!ir) {
+		printk(KERN_ERR DRIVER_NAME
+		       "[?]: set_use_dec called with no context\n");
+		return;
+	}
+	dprintk("[%d]: set use dec\n", ir->devnum);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf,
+			   int i, int max)
+{
+	/* MODE2: pulse/space (PULSE_BIT) in 1us units */
+	while (i < max) {
+		/* 1 Igor-tick = 85.333333 us */
+		lirc_t code = (unsigned int)ir->buf_in[i] * 85 +
+			(unsigned int)ir->buf_in[i] / 3;
+		ir->last_time.tv_usec += code;
+		if (ir->in_space)
+			code |= PULSE_BIT;
+		lirc_buffer_write_n(buf, (unsigned char *)&code, 1);
+		/* 1 chunk = CODE_LENGTH bytes */
+		ir->in_space ^= 1;
+		++i;
+	}
+}
+
+/**
+ * Called in user context.
+ * return 0 if data was added to the buffer and
+ * -ENODATA if none was available. This should add some number of bits
+ * evenly divisible by code_length to the buffer
+ */
+static int usb_remote_poll(void *data, struct lirc_buffer *buf)
+{
+	int ret;
+	struct igorplug *ir = (struct igorplug *)data;
+
+	if (!ir->usbdev)  /* Has the device been removed? */
+		return -ENODEV;
+
+	memset(ir->buf_in, 0, ir->len_in);
+
+	ret = usb_control_msg(
+	      ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+	      GET_INFRACODE, USB_TYPE_VENDOR|USB_DIR_IN,
+	      0/* offset */, /*unused*/0,
+	      ir->buf_in, ir->len_in,
+	      /*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
+	if (ret > 0) {
+		lirc_t code, timediff;
+		struct timeval now;
+
+		/* ACK packet has 1 byte --> ignore */
+		if (ret < DEVICE_HEADERLEN)
+			return -ENODATA;
+
+		dprintk(": Got %d bytes. Header: %02x %02x %02x\n",
+			ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]);
+
+		do_gettimeofday(&now);
+		timediff = now.tv_sec - ir->last_time.tv_sec;
+		if (timediff + 1 > PULSE_MASK / 1000000)
+			timediff = PULSE_MASK;
+		else {
+			timediff *= 1000000;
+			timediff += now.tv_usec - ir->last_time.tv_usec;
+		}
+		ir->last_time.tv_sec = now.tv_sec;
+		ir->last_time.tv_usec = now.tv_usec;
+
+		/* create leading gap  */
+		code = timediff;
+		lirc_buffer_write(buf, (unsigned char *)&code);
+		ir->in_space = 1;   /* next comes a pulse */
+
+		if (ir->buf_in[2] == 0)
+			send_fragment(ir, buf, DEVICE_HEADERLEN, ret);
+		else {
+			printk(KERN_WARNING DRIVER_NAME
+			       "[%d]: Device buffer overrun.\n", ir->devnum);
+			/* HHHNNNNNNNNNNNOOOOOOOO H = header
+			      <---[2]--->         N = newer
+			   <---------ret--------> O = older */
+			ir->buf_in[2] %= ret - DEVICE_HEADERLEN; /* sanitize */
+			/* keep even-ness to not desync pulse/pause */
+			send_fragment(ir, buf, DEVICE_HEADERLEN +
+				      ir->buf_in[2] - (ir->buf_in[2] & 1),
+				      ret);
+			send_fragment(ir, buf, DEVICE_HEADERLEN,
+				      DEVICE_HEADERLEN + ir->buf_in[2]);
+		}
+
+		ret = usb_control_msg(
+		      ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+		      SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
+		      /*unused*/0, /*unused*/0,
+		      /*dummy*/ir->buf_in, /*dummy*/ir->len_in,
+		      /*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
+		if (ret < 0)
+			printk(KERN_WARNING DRIVER_NAME
+			       "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
+			       ir->devnum, ret);
+		return 0;
+	} else
+		printk(KERN_WARNING DRIVER_NAME
+		       "[%d]: GET_INFRACODE: error %d\n",
+			ir->devnum, ret);
+
+	return -ENODATA;
+}
+
+
+
+#if defined(KERNEL_2_5)
+static int usb_remote_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct usb_device *dev = NULL;
+	struct usb_host_interface *idesc = NULL;
+	struct usb_host_endpoint *ep_ctl2;
+#else
+static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum,
+				const struct usb_device_id *id)
+{
+	struct usb_interface *intf;
+	struct usb_interface_descriptor *idesc;
+	struct usb_endpoint_descriptor *ep_ctl2;
+#endif
+	struct igorplug *ir = NULL;
+	struct lirc_driver *driver = NULL;
+	int devnum, pipe, maxp;
+	int minor = 0;
+	char buf[63], name[128] = "";
+	int mem_failure = 0;
+	int ret;
+
+	dprintk(": usb probe called.\n");
+
+#if defined(KERNEL_2_5)
+	dev = interface_to_usbdev(intf);
+
+#  if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
+	idesc = &intf->altsetting[intf->act_altsetting];  /* in 2.6.4 */
+#  else
+	idesc = intf->cur_altsetting;  /* in 2.6.6 */
+#  endif
+
+	if (idesc->desc.bNumEndpoints != 1)
+		return -ENODEV;
+	ep_ctl2 = idesc->endpoint;
+	if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+	    != USB_DIR_IN)
+	    || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+	    != USB_ENDPOINT_XFER_CONTROL)
+		return -ENODEV;
+	pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress);
+#else
+	intf = &dev->actconfig->interface[ifnum];
+	idesc = &intf->altsetting[intf->act_altsetting];
+	if (idesc->bNumEndpoints != 1)
+		return NULL;
+	ep_ctl2 = idesc->endpoint;
+	if (((ep_ctl2->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+	    != USB_DIR_IN)
+	    || (ep_ctl2->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+	    != USB_ENDPOINT_XFER_CONTROL)
+		return NULL;
+	pipe = usb_rcvctrlpipe(dev, ep_ctl2->bEndpointAddress);
+#endif
+	devnum = dev->devnum;
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	dprintk(DRIVER_NAME "[%d]: bytes_in_key=%d maxp=%d\n",
+		devnum, CODE_LENGTH, maxp);
+
+
+	mem_failure = 0;
+	ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL);
+	if (!ir) {
+		mem_failure = 1;
+		goto mem_failure_switch;
+	}
+
+	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	if (!driver) {
+		mem_failure = 2;
+		goto mem_failure_switch;
+	}
+
+#if defined(KERNEL_2_5)
+	ir->buf_in = usb_buffer_alloc(dev,
+			      DEVICE_BUFLEN+DEVICE_HEADERLEN,
+			      GFP_ATOMIC, &ir->dma_in);
+#else
+	ir->buf_in = kmalloc(DEVICE_BUFLEN+DEVICE_HEADERLEN,
+			     GFP_KERNEL);
+#endif
+	if (!ir->buf_in) {
+		mem_failure = 3;
+		goto mem_failure_switch;
+	}
+
+	strcpy(driver->name, DRIVER_NAME " ");
+	driver->minor = -1;
+	driver->code_length = CODE_LENGTH * 8; /* in bits */
+	driver->features = LIRC_CAN_REC_MODE2;
+	driver->data = ir;
+	driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES;
+	driver->set_use_inc = &set_use_inc;
+	driver->set_use_dec = &set_use_dec;
+	driver->sample_rate = sample_rate;    /* per second */
+	driver->add_to_buf = &usb_remote_poll;
+#ifdef LIRC_HAVE_SYSFS
+	driver->dev = &intf->dev;
+#endif
+	driver->owner = THIS_MODULE;
+
+	minor = lirc_register_driver(driver);
+	if (minor < 0)
+		mem_failure = 9;
+
+mem_failure_switch:
+
+	switch (mem_failure) {
+	case 9:
+#if defined(KERNEL_2_5)
+		usb_buffer_free(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN,
+			ir->buf_in, ir->dma_in);
+#else
+		kfree(ir->buf_in);
+#endif
+	case 3:
+		kfree(driver);
+	case 2:
+		kfree(ir);
+	case 1:
+		printk(KERN_ERR DRIVER_NAME "[%d]: out of memory (code=%d)\n",
+			devnum, mem_failure);
+#if defined(KERNEL_2_5)
+		return -ENOMEM;
+#else
+		return NULL;
+#endif
+	}
+
+	driver->minor = minor;
+	ir->d = driver;
+	ir->devnum = devnum;
+	ir->usbdev = dev;
+	ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN;
+	ir->in_space = 1; /* First mode2 event is a space. */
+	do_gettimeofday(&ir->last_time);
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+	printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
+	       dev->bus->busnum, devnum);
+
+	/* clear device buffer */
+	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+		SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
+		/*unused*/0, /*unused*/0,
+		/*dummy*/ir->buf_in, /*dummy*/ir->len_in,
+		/*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
+	if (ret < 0)
+		printk(KERN_WARNING DRIVER_NAME
+		       "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
+			devnum, ret);
+
+#if defined(KERNEL_2_5)
+	usb_set_intfdata(intf, ir);
+	return 0;
+#else
+	return ir;
+#endif
+}
+
+
+#if defined(KERNEL_2_5)
+static void usb_remote_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct igorplug *ir = usb_get_intfdata(intf);
+#else
+static void usb_remote_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct igorplug *ir = ptr;
+#endif
+
+	if (!ir || !ir->d)
+		return;
+
+	printk(KERN_INFO DRIVER_NAME
+	       "[%d]: usb remote disconnected\n", ir->devnum);
+
+	lirc_unregister_driver(ir->d->minor);
+
+	lirc_buffer_free(ir->d->rbuf);
+	kfree(ir->d->rbuf);
+	kfree(ir->d);
+
+
+#if defined(KERNEL_2_5)
+	usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in);
+#else
+	kfree(ir->buf_in);
+#endif
+
+	kfree(ir);
+}
+
+static struct usb_device_id usb_remote_id_table [] = {
+	/* Igor Plug USB (Atmel's Manufact. ID) */
+	{ USB_DEVICE(0x03eb, 0x0002) },
+	/* Fit PC2 Infrared Adapter */
+	{ USB_DEVICE(0x03eb, 0x21fe) },
+
+	/* Terminating entry */
+	{ }
+};
+
+static struct usb_driver usb_remote_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name =		DRIVER_NAME,
+	.probe =	usb_remote_probe,
+	.disconnect =	usb_remote_disconnect,
+	.id_table =	usb_remote_id_table
+};
+
+static int __init usb_remote_init(void)
+{
+	int i;
+
+	printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n");
+	printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n");
+	dprintk(": debug mode enabled\n");
+
+	i = usb_register(&usb_remote_driver);
+	if (i < 0) {
+		printk(KERN_ERR DRIVER_NAME
+		       ": usb register failed, result = %d\n", i);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit usb_remote_exit(void)
+{
+	usb_deregister(&usb_remote_driver);
+}
+
+module_init(usb_remote_init);
+module_exit(usb_remote_exit);
+
+#if defined(KERNEL_2_5)
+#include <linux/vermagic.h>
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+#endif
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, usb_remote_id_table);
+
+module_param(sample_rate, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)");
+
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_igorplugusb/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_igorplugusb/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_IGORPLUGUSB)	+= lirc_igorplugusb.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_atiusb/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_atiusb/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_ATIUSB)	+= lirc_atiusb.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c
@@ -0,0 +1,1452 @@
+/*
+ * lirc_atiusb - USB remote support for LIRC
+ * (currently only supports X10 USB remotes)
+ * (supports ATI Remote Wonder and ATI Remote Wonder II, too)
+ *
+ * Copyright (C) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net>
+ *
+ * This driver was derived from:
+ *   Vladimir Dergachev <volodya@minspring.com>'s 2002
+ *      "USB ATI Remote support" (input device)
+ *   Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
+ *      "USB StreamZap remote driver" (LIRC)
+ *   Artur Lipowski <alipowski@kki.net.pl>'s 2002
+ *      "lirc_dev" and "lirc_gpio" LIRC modules
+ *   Michael Wojciechowski
+ *      initial xbox support
+ *   Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006
+ *      reworked the patch for lirc submission
+ *
+ * $Id: lirc_atiusb.c,v 1.85 2009/03/11 00:21:46 jarodwilson Exp $
+ */
+
+/*
+ * 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/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#error "*******************************************************"
+#error "Sorry, this driver needs kernel version 2.4.0 or higher"
+#error "*******************************************************"
+#endif
+
+#include <linux/autoconf.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#define DRIVER_VERSION		"$Revision: 1.85 $"
+#define DRIVER_AUTHOR		"Paul Miller <pmiller9@users.sourceforge.net>"
+#define DRIVER_DESC		"USB remote driver for LIRC"
+#define DRIVER_NAME		"lirc_atiusb"
+
+#define CODE_LENGTH		(code_length[ir->remote_type])
+#define CODE_MIN_LENGTH		(code_min_length[ir->remote_type])
+#define DECODE_LENGTH		(decode_length[ir->remote_type])
+
+#define RW2_MODENAV_KEYCODE	0x3F
+#define RW2_NULL_MODE		0xFF
+/* Fake (virtual) keycode indicating compass mouse usage */
+#define RW2_MOUSE_KEYCODE	0xFF
+#define RW2_PRESSRELEASE_KEYCODE	0xFE
+
+#define RW2_PRESS_CODE		1
+#define RW2_HOLD_CODE		2
+#define RW2_RELEASE_CODE	0
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG fmt, ## args);	\
+	} while (0)
+
+/* ATI, ATI2, XBOX */
+static const int code_length[] = {5, 3, 6};
+static const int code_min_length[] = {3, 3, 6};
+static const int decode_length[] = {5, 3, 1};
+/*
+ * USB_BUFF_LEN must be the maximum value of the code_length array.
+ * It is used for static arrays.
+ */
+#define USB_BUFF_LEN 6
+
+static int mask = 0xFFFF;	/* channel acceptance bit mask */
+static int unique;		/* enable channel-specific codes */
+static int repeat = 10;		/* repeat time in 1/100 sec */
+static int emit_updown;		/* send separate press/release codes (rw2) */
+static int emit_modekeys;	/* send keycodes for aux1-4, pc, mouse (rw2) */
+static unsigned long repeat_jiffies; /* repeat timeout */
+static int mdeadzone;		/* mouse sensitivity >= 0 */
+static int mgradient = 375;	/* 1000*gradient from cardinal direction */
+
+/* get hi and low bytes of a 16-bits int */
+#define HI(a)			((unsigned char)((a) >> 8))
+#define LO(a)			((unsigned char)((a) & 0xff))
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+#define FREE_ALL		0xFF
+
+/* endpoints */
+#define EP_KEYS			0
+#define EP_MOUSE		1
+#define EP_MOUSE_ADDR		0x81
+#define EP_KEYS_ADDR		0x82
+
+#define VENDOR_ATI1		0x0bc7
+#define VENDOR_ATI2		0x0471
+#define VENDOR_MS1		0x040b
+#define VENDOR_MS2		0x045e
+#define VENDOR_MS3		0xFFFF
+
+static struct usb_device_id usb_remote_table[] = {
+	/* X10 USB Firecracker Interface */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0002) },
+
+	/* X10 VGA Video Sender */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0003) },
+
+	/* ATI Wireless Remote Receiver */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0004) },
+
+	/* NVIDIA Wireless Remote Receiver */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0005) },
+
+	/* ATI Wireless Remote Receiver */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0006) },
+
+	/* X10 USB Wireless Transceivers */
+	{ USB_DEVICE(VENDOR_ATI1, 0x0007) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x0008) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x0009) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000A) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000B) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000C) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000D) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000E) },
+	{ USB_DEVICE(VENDOR_ATI1, 0x000F) },
+
+	/* ATI Remote Wonder 2: Input Device */
+	{ USB_DEVICE(VENDOR_ATI2, 0x0602) },
+
+	/* ATI Remote Wonder 2: Controller (???) */
+	{ USB_DEVICE(VENDOR_ATI2, 0x0603) },
+
+	/* Gamester Xbox DVD Movie Playback Kit IR */
+	{ USB_DEVICE(VENDOR_MS1, 0x6521) },
+
+	/* Microsoft Xbox DVD Movie Playback Kit IR */
+	{ USB_DEVICE(VENDOR_MS2, 0x0284) },
+
+	/*
+	 * Some Chinese manufacturer -- conflicts with the joystick from the
+	 * same manufacturer
+	 */
+	{ USB_DEVICE(VENDOR_MS3, 0xFFFF) },
+
+	/* Terminating entry */
+	{ }
+};
+
+
+/* init strings */
+#define USB_OUTLEN		7
+
+static char init1[] = {0x01, 0x00, 0x20, 0x14};
+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20};
+
+struct in_endpt {
+	/* inner link in list of endpoints for the remote specified by ir */
+	struct list_head iep_list_link;
+	struct atirf_dev *ir;
+	struct urb *urb;
+	struct usb_endpoint_descriptor *ep;
+	int type;
+
+	/* buffers and dma */
+	unsigned char *buf;
+	unsigned int len;
+#ifdef KERNEL_2_5
+	dma_addr_t dma;
+#endif
+
+	/* handle repeats */
+	unsigned char old[USB_BUFF_LEN];
+	unsigned long old_jiffies;
+};
+
+struct out_endpt {
+	struct atirf_dev *ir;
+	struct urb *urb;
+	struct usb_endpoint_descriptor *ep;
+
+	/* buffers and dma */
+	unsigned char *buf;
+#ifdef KERNEL_2_5
+	dma_addr_t dma;
+#endif
+
+	/* handle sending (init strings) */
+	int send_flags;
+	wait_queue_head_t wait;
+};
+
+
+/* data structure for each usb remote */
+struct atirf_dev {
+	/* inner link in list of all remotes managed by this module */
+	struct list_head remote_list_link;
+	/* Number of usb interfaces associated with this device */
+	int dev_refcount;
+
+	/* usb */
+	struct usb_device *usbdev;
+	/* Head link to list of all inbound endpoints in this remote */
+	struct list_head iep_listhead;
+	struct out_endpt *out_init;
+	int devnum;
+
+	/* remote type based on usb_device_id tables */
+	enum {
+		ATI1_COMPATIBLE,
+		ATI2_COMPATIBLE,
+		XBOX_COMPATIBLE
+	} remote_type;
+
+	/* rw2 current mode (mirrors the state of the remote) */
+	int mode;
+
+	/* lirc */
+	struct lirc_driver *d;
+	int connected;
+
+	/* locking */
+	struct mutex lock;
+};
+
+/* list of all registered devices via the remote_list_link in atirf_dev */
+static struct list_head remote_list;
+
+/*
+ * Convenience macros to retrieve a pointer to the surrounding struct from
+ * the given list_head reference within, pointed at by link.
+ */
+#define get_iep_from_link(link) \
+		list_entry((link), struct in_endpt, iep_list_link);
+#define get_irctl_from_link(link) \
+		list_entry((link), struct atirf_dev, remote_list_link);
+
+/* send packet - used to initialize remote */
+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data)
+{
+	struct atirf_dev *ir = oep->ir;
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = HZ; /* 1 second */
+	unsigned char buf[USB_OUTLEN];
+
+	dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd);
+
+	mutex_lock(&ir->lock);
+	oep->urb->transfer_buffer_length = LO(cmd) + 1;
+	oep->urb->dev = oep->ir->usbdev;
+	oep->send_flags = SEND_FLAG_IN_PROGRESS;
+
+	memcpy(buf+1, data, LO(cmd));
+	buf[0] = HI(cmd);
+	memcpy(oep->buf, buf, LO(cmd)+1);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&oep->wait, &wait);
+
+#ifdef KERNEL_2_5
+	if (usb_submit_urb(oep->urb, GFP_ATOMIC)) {
+#else
+	if (usb_submit_urb(oep->urb)) {
+#endif
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&oep->wait, &wait);
+		mutex_unlock(&ir->lock);
+		return;
+	}
+	mutex_unlock(&ir->lock);
+
+	while (timeout && (oep->urb->status == -EINPROGRESS)
+	       && !(oep->send_flags & SEND_FLAG_COMPLETE)) {
+		timeout = schedule_timeout(timeout);
+		rmb();
+	}
+
+	dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd);
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&oep->wait, &wait);
+#ifdef KERNEL_2_5
+	oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+	usb_unlink_urb(oep->urb);
+}
+
+static int unregister_from_lirc(struct atirf_dev *ir)
+{
+	struct lirc_driver *d = ir->d;
+	int devnum;
+
+	devnum = ir->devnum;
+	dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum);
+
+	lirc_unregister_driver(d->minor);
+
+	printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum);
+	return 0;
+}
+
+
+static int set_use_inc(void *data)
+{
+	struct atirf_dev *ir = data;
+	struct list_head *pos, *n;
+	struct in_endpt *iep;
+	int rtn;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
+		return -EIO;
+	}
+	dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
+
+	MOD_INC_USE_COUNT;
+
+	mutex_lock(&ir->lock);
+	if (!ir->connected) {
+		if (!ir->usbdev) {
+			mutex_unlock(&ir->lock);
+			dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum);
+			return -ENOENT;
+		}
+
+		/* Iterate through the inbound endpoints */
+		list_for_each_safe(pos, n, &ir->iep_listhead) {
+			/* extract the current in_endpt */
+			iep = get_iep_from_link(pos);
+			iep->urb->dev = ir->usbdev;
+			dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n",
+				ir->devnum, iep->ep->bEndpointAddress, iep);
+#ifdef KERNEL_2_5
+			rtn = usb_submit_urb(iep->urb, GFP_ATOMIC);
+#else
+			rtn = usb_submit_urb(iep->urb);
+#endif
+			if (rtn) {
+				printk(DRIVER_NAME "[%d]: open result = %d "
+				       "error submitting urb\n",
+				       ir->devnum, rtn);
+				mutex_unlock(&ir->lock);
+				MOD_DEC_USE_COUNT;
+				return -EIO;
+			}
+		}
+		ir->connected = 1;
+	}
+	mutex_unlock(&ir->lock);
+
+	return 0;
+}
+
+static void set_use_dec(void *data)
+{
+	struct atirf_dev *ir = data;
+	struct list_head *pos, *n;
+	struct in_endpt *iep;
+
+	if (!ir) {
+		printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
+		return;
+	}
+	dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
+
+	mutex_lock(&ir->lock);
+	if (ir->connected) {
+		/* Free inbound usb urbs */
+		list_for_each_safe(pos, n, &ir->iep_listhead) {
+			iep = get_iep_from_link(pos);
+			dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n",
+				ir->devnum, iep->ep->bEndpointAddress, iep);
+			usb_kill_urb(iep->urb);
+		}
+		ir->connected = 0;
+	}
+	mutex_unlock(&ir->lock);
+	MOD_DEC_USE_COUNT;
+}
+
+static void print_data(struct in_endpt *iep, char *buf, int len)
+{
+	const int clen = code_length[iep->ir->remote_type];
+	char codes[clen * 3 + 1];
+	int i;
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len && i < clen; i++)
+		snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF);
+	printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n",
+		iep->ir->devnum, codes, iep->ep->bEndpointAddress, len);
+}
+
+static int code_check_ati1(struct in_endpt *iep, int len)
+{
+	struct atirf_dev *ir = iep->ir;
+	int i, chan;
+
+	/* ATI RW1: some remotes emit both 4 and 5 byte length codes. */
+	/* ATI RW2: emit 3 byte codes */
+	if (len < CODE_MIN_LENGTH || len > CODE_LENGTH)
+		return -1;
+
+	/* *** channel not tested with 4/5-byte Dutch remotes *** */
+	chan = ((iep->buf[len-1]>>4) & 0x0F);
+
+	/* strip channel code */
+	if (!unique) {
+		iep->buf[len-1] &= 0x0F;
+		iep->buf[len-3] -= (chan<<4);
+	}
+
+	if (!((1U<<chan) & mask)) {
+		dprintk(DRIVER_NAME "[%d]: ignore channel %d\n",
+			ir->devnum, chan+1);
+		return -1;
+	}
+	dprintk(DRIVER_NAME "[%d]: accept channel %d\n", ir->devnum, chan+1);
+
+	if (ir->remote_type == ATI1_COMPATIBLE) {
+		for (i = len; i < CODE_LENGTH; i++)
+			iep->buf[i] = 0;
+		/* check for repeats */
+		if (memcmp(iep->old, iep->buf, len) == 0) {
+			if (iep->old_jiffies + repeat_jiffies > jiffies)
+				return -1;
+		} else
+			memcpy(iep->old, iep->buf, CODE_LENGTH);
+		iep->old_jiffies = jiffies;
+	}
+
+	return 0;
+}
+
+/*
+ * Since the ATI Remote Wonder II has quite a different structure from the
+ * prior version, this function was separated out to clarify the sanitization
+ * process.
+ *
+ * Here is a summary of the main differences:
+ *
+ * a. The rw2 has no sense of a transmission channel.  But, it does have an
+ *    auxiliary mode state, which is set by the mode buttons Aux1 through
+ *    Aux4 and "PC".  These map respectively to 0-4 in the first byte of the
+ *    recv buffer.  Any subsequent button press sends this mode number as its
+ *    "channel code."  Annoyingly enough, the mode setting buttons all send
+ *    the same key code (0x3f), and can only be distinguished via their mode
+ *    byte.
+ *
+ *    Because of this, old-style "unique"-parameter-enabled channel squashing
+ *    kills the functionality of the aux1-aux4 and PC buttons.  However, to
+ *    not do so would cause each remote key to send a different code depending
+ *    on the active aux.  Further complicating matters, using the mouse norb
+ *    also sends an identical code as would pushing the active aux button.  To
+ *    handle this we need a separate parameter, like rw2modes, with the
+ *    following values and meanings:
+ *
+ *	0: Don't squash any channel info
+ *	1: Only squash channel data for non-mode setting keys
+ *	2: Ignore aux keypresses, but don't squash channel
+ *	3: Ignore aux keypresses and squash channel data
+ *
+ *    Option 1 may seem useless since the mouse sends the same code, but one
+ *    need only ignore in userspace any press of a mode-setting code that only
+ *    reaffirms the current mode.  The 3rd party lirccd should be able to
+ *    handle this easily enough, but lircd doesn't keep the state necessary
+ *    for this.  TODO We could work around this in the driver by emitting a
+ *    single 02 (press) code for a mode key only if that mode is not currently
+ *    active.
+ *
+ *    Option 2 would be useful for those wanting super configurability,
+ *    offering the ability to program 5 times the number actions based on the
+ *    current mode.
+ *
+ * b. The rw2 has its own built in repeat handling; the keys endpoint
+ *    encodes this in the second byte as 1 for press, 2 for hold, and 0 for
+ *    release.  This is generally much more responsive than lirc's built-in
+ *    timeout handling.
+ *
+ *    The problem is that the remote can send the release-receive pair
+ *    (0,1) while one is still holding down the same button if the
+ *    transmission is momentarily interrupted.  (It seems that the receiver
+ *    manages this count instead of the remote.)  By default, this information
+ *    is squashed to 2.
+ *
+ *    In order to expose the built-in repeat code, set the emit_updown
+ *    parameter as described below.
+ *
+ * c. The mouse norb is much more sensitive than on the rw1.  It emulates
+ *    a joystick-like controller with the second byte representing the x-axis
+ *    and the third, the y-axis.  Treated as signed integers, these axes range
+ *    approximately as follows:
+ *
+ *	x: (left) -46 ... 46 (right) (0xd2..0x2e)
+ *	y: (up)   -46 ... 46 (down)  (0xd2..0x2e)
+ *
+ *    NB these values do not correspond to the pressure with which the mouse
+ *    norb is pushed in a given direction, but rather seems to indicate the
+ *    duration for which a given direction is held.
+ *
+ *    These are normalized to 8 cardinal directions for easy configuration via
+ *    lircd.conf.  The normalization can be fined tuned with the mdeadzone and
+ *    mgradient parameters as described below.
+ *
+ * d. The interrupt rate of the mouse vs. the normal keys is different.
+ *
+ *	mouse: ~27Hz (37ms between interrupts)
+ *	keys:  ~10Hz (100ms between interrupts)
+ *
+ *    This means that the normal gap mechanism for lircd won't work as
+ *    expected; is emit_updown>0 if you can get away with it.
+ */
+static int code_check_ati2(struct in_endpt *iep, int len)
+{
+	struct atirf_dev *ir = iep->ir;
+	int mode, i;
+	char *buf = iep->buf;
+
+	if (len != CODE_LENGTH) {
+		dprintk(DRIVER_NAME
+			"[%d]: Huh?  Abnormal length (%d) buffer received.\n",
+			ir->devnum, len);
+		return -1;
+	}
+	for (i = len; i < CODE_LENGTH; i++)
+		iep->buf[i] = 0;
+
+	mode = buf[0];
+
+	/* Squash the mode indicator if unique wasn't set non-zero */
+	if (!unique)
+		buf[0] = 0;
+
+	if (iep->ep->bEndpointAddress == EP_KEYS_ADDR) {
+		/* ignore mouse nav indicator key and mode-set (aux) keys */
+		if (buf[2] == RW2_MODENAV_KEYCODE) {
+			if (emit_modekeys >= 2) /* emit raw */
+				buf[0] = mode;
+			else if (emit_modekeys == 1) {
+				/* translate */
+				buf[0] = mode;
+				if (ir->mode != mode) {
+					buf[1] = 0x03;
+					ir->mode = mode;
+					return 0;
+				}
+			} else {
+				dprintk(DRIVER_NAME
+					"[%d]: ignore dummy code 0x%x "
+					"(ep=0x%x)\n", ir->devnum,
+					buf[2], iep->ep->bEndpointAddress);
+				return -1;
+			}
+		}
+
+		if (buf[1] != 2) {
+			/* handle press/release codes */
+			if (emit_updown == 0) /* ignore */
+				return -1;
+			else if (emit_updown == 1) /* normalize keycode */
+				 buf[2] = RW2_PRESSRELEASE_KEYCODE;
+			/* else emit raw */
+		}
+
+	} else {
+		int x = (signed char)buf[1];
+		int y = (signed char)buf[2];
+		int code = 0x00;
+		int dir_ew, dir_ns;
+
+		buf[2] = RW2_MOUSE_KEYCODE;
+
+		/* sensitivity threshold (use L2norm^2) */
+		if (mdeadzone > (x*x+y*y)) {
+			buf[1] = 0x00;
+			return 0;
+		}
+
+/* Nybble encoding: xy, 2 is -1 (S or W); 1 (N or E) */
+#define MOUSE_N		0x01
+#define MOUSE_NE	0x11
+#define MOUSE_E		0x10
+#define MOUSE_SE	0x12
+#define MOUSE_S		0x02
+#define MOUSE_SW	0x22
+#define MOUSE_W		0x20
+#define MOUSE_NW	0x21
+
+		/* cardinal leanings: positive x -> E, positive y -> S */
+		dir_ew = (x > 0) ? MOUSE_E : MOUSE_W;
+		dir_ns = (y > 0) ? MOUSE_S : MOUSE_N;
+
+		/* convert coordinates(angle) into compass direction */
+		if (x == 0)
+			code = dir_ns;
+		else if (y == 0)
+			code = dir_ew;
+		else {
+			if (abs(1000*y/x) > mgradient)
+				code = dir_ns;
+			if (abs(1000*x/y) > mgradient)
+				code |= dir_ew;
+		}
+
+		buf[1] = code;
+		dprintk(DRIVER_NAME "[%d]: mouse compass=0x%x %s%s (%d,%d)\n",
+			ir->devnum, code,
+			(code & MOUSE_S ? "S" : (code & MOUSE_N ? "N" : "")),
+			(code & MOUSE_E ? "E" : (code & MOUSE_W ? "W" : "")),
+			x, y);
+	}
+
+	return 0;
+}
+
+static int code_check_xbox(struct in_endpt *iep, int len)
+{
+	struct atirf_dev *ir = iep->ir;
+	const int clen = CODE_LENGTH;
+
+	if (len != clen) {
+		dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox "
+			"ir.. ?\n", len, clen);
+		return -1;
+	}
+
+	/* check for repeats */
+	if (memcmp(iep->old, iep->buf, len) == 0) {
+		if (iep->old_jiffies + repeat_jiffies > jiffies)
+			return -1;
+	} else {
+		/*
+		 * the third byte of xbox ir packet seems to contain key info
+		 * the last two bytes are.. some kind of clock?
+		 */
+		iep->buf[0] = iep->buf[2];
+		memset(iep->buf + 1, 0, len - 1);
+		memcpy(iep->old, iep->buf, len);
+	}
+	iep->old_jiffies = jiffies;
+
+	return 0;
+}
+
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_remote_recv(struct urb *urb)
+#endif
+{
+	struct in_endpt *iep;
+	int len, result = -1;
+
+	if (!urb)
+		return;
+	iep = urb->context;
+	if (!iep) {
+#ifdef KERNEL_2_5
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+		usb_unlink_urb(urb);
+		return;
+	}
+	if (!iep->ir->usbdev)
+		return;
+
+	len = urb->actual_length;
+	if (debug)
+		print_data(iep, urb->transfer_buffer, len);
+
+	switch (urb->status) {
+
+	case 0:
+		switch (iep->ir->remote_type) {
+		case XBOX_COMPATIBLE:
+			result = code_check_xbox(iep, len);
+			break;
+		case ATI2_COMPATIBLE:
+			result = code_check_ati2(iep, len);
+			break;
+		case ATI1_COMPATIBLE:
+		default:
+			result = code_check_ati1(iep, len);
+		}
+		if (result < 0)
+			break;
+		lirc_buffer_write(iep->ir->d->rbuf, iep->buf);
+		wake_up(&iep->ir->d->rbuf->wait_poll);
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+#ifdef KERNEL_2_5
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+		usb_unlink_urb(urb);
+		return;
+
+	case -EPIPE:
+	default:
+		break;
+	}
+
+#ifdef KERNEL_2_5
+	usb_submit_urb(urb, GFP_ATOMIC);
+#endif
+}
+
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_remote_send(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_remote_send(struct urb *urb)
+#endif
+{
+	struct out_endpt *oep;
+
+	if (!urb)
+		return;
+	oep = urb->context;
+	if (!oep) {
+#ifdef KERNEL_2_5
+		urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+		usb_unlink_urb(urb);
+		return;
+	}
+	if (!oep->ir->usbdev)
+		return;
+
+	dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum);
+
+	if (urb->status)
+		return;
+
+	oep->send_flags |= SEND_FLAG_COMPLETE;
+	wmb();
+	if (waitqueue_active(&oep->wait))
+		wake_up(&oep->wait);
+}
+
+
+/*
+ * Initialization and removal
+ */
+
+/*
+ * Free iep according to mem_failure which specifies a checkpoint into the
+ * initialization sequence for rollback recovery.
+ */
+static void free_in_endpt(struct in_endpt *iep, int mem_failure)
+{
+	struct atirf_dev *ir;
+	dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure);
+	if (!iep)
+		return;
+
+	ir = iep->ir;
+	if (!ir) {
+		dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n");
+		return;
+	}
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 5:
+		list_del(&iep->iep_list_link);
+		dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x "
+			"from list\n", ir->devnum, iep->ep->bEndpointAddress);
+	case 4:
+		if (iep->urb) {
+#ifdef KERNEL_2_5
+			iep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+			usb_unlink_urb(iep->urb);
+			usb_free_urb(iep->urb);
+			iep->urb = 0;
+		} else
+			dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n",
+				ir->devnum);
+	case 3:
+#ifdef KERNEL_2_5
+		usb_buffer_free(iep->ir->usbdev, iep->len, iep->buf, iep->dma);
+#else
+		kfree(iep->buf);
+#endif
+		iep->buf = 0;
+	case 2:
+		kfree(iep);
+	}
+	mutex_unlock(&ir->lock);
+}
+
+/*
+ * Construct a new inbound endpoint for this remote, and add it to the list of
+ * in_epts in ir.
+ */
+static struct in_endpt *new_in_endpt(struct atirf_dev *ir,
+				     struct usb_endpoint_descriptor *ep)
+{
+	struct usb_device *dev = ir->usbdev;
+	struct in_endpt *iep;
+	int pipe, maxp, len, addr;
+	int mem_failure;
+
+	addr = ep->bEndpointAddress;
+	pipe = usb_rcvintpipe(dev, addr);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+/*	len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp;
+ *	len -= (len % CODE_LENGTH); */
+	len = CODE_LENGTH;
+
+	dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found "
+		"(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len);
+
+	mem_failure = 0;
+	iep = kzalloc(sizeof(*iep), GFP_KERNEL);
+	if (!iep) {
+		mem_failure = 1;
+		goto new_in_endpt_failure_check;
+	}
+	iep->ir = ir;
+	iep->ep = ep;
+	iep->len = len;
+
+#ifdef KERNEL_2_5
+	iep->buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &iep->dma);
+#else
+	iep->buf = kmalloc(len, GFP_KERNEL);
+#endif
+	if (!iep->buf) {
+		mem_failure = 2;
+		goto new_in_endpt_failure_check;
+	}
+
+#ifdef KERNEL_2_5
+	iep->urb = usb_alloc_urb(0, GFP_KERNEL);
+#else
+	iep->urb = usb_alloc_urb(0);
+#endif
+	if (!iep->urb)
+		mem_failure = 3;
+
+new_in_endpt_failure_check:
+
+	if (mem_failure) {
+		free_in_endpt(iep, mem_failure);
+		printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
+		       ir->devnum, addr, mem_failure);
+		return NULL;
+	}
+	list_add_tail(&iep->iep_list_link, &ir->iep_listhead);
+	dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n",
+		ir->devnum, iep->ep->bEndpointAddress);
+	return iep;
+}
+
+static void free_out_endpt(struct out_endpt *oep, int mem_failure)
+{
+	struct atirf_dev *ir;
+	dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure);
+	if (!oep)
+		return;
+
+	wake_up_all(&oep->wait);
+
+	ir = oep->ir;
+	if (!ir) {
+		dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n");
+		return;
+	}
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 4:
+		if (oep->urb) {
+#ifdef KERNEL_2_5
+			oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
+#endif
+			usb_unlink_urb(oep->urb);
+			usb_free_urb(oep->urb);
+			oep->urb = 0;
+		} else {
+			dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n",
+				ir->devnum);
+		}
+	case 3:
+#ifdef KERNEL_2_5
+		usb_buffer_free(oep->ir->usbdev, USB_OUTLEN,
+				oep->buf, oep->dma);
+#else
+		kfree(oep->buf);
+#endif
+		oep->buf = 0;
+	case 2:
+		kfree(oep);
+	}
+	mutex_unlock(&ir->lock);
+}
+
+static struct out_endpt *new_out_endpt(struct atirf_dev *ir,
+				       struct usb_endpoint_descriptor *ep)
+{
+#ifdef KERNEL_2_5
+	struct usb_device *dev = ir->usbdev;
+#endif
+	struct out_endpt *oep;
+	int mem_failure;
+
+	dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n",
+		ir->devnum, ep->bEndpointAddress);
+
+	mem_failure = 0;
+	oep = kzalloc(sizeof(*oep), GFP_KERNEL);
+	if (!oep)
+		mem_failure = 1;
+	else {
+		oep->ir = ir;
+		oep->ep = ep;
+		init_waitqueue_head(&oep->wait);
+
+#ifdef KERNEL_2_5
+		oep->buf = usb_buffer_alloc(dev, USB_OUTLEN,
+					    GFP_ATOMIC, &oep->dma);
+#else
+		oep->buf = kmalloc(USB_OUTLEN, GFP_KERNEL);
+#endif
+		if (!oep->buf)
+			mem_failure = 2;
+		else {
+#ifdef KERNEL_2_5
+			oep->urb = usb_alloc_urb(0, GFP_KERNEL);
+#else
+			oep->urb = usb_alloc_urb(0);
+#endif
+			if (!oep->urb)
+				mem_failure = 3;
+		}
+	}
+	if (mem_failure) {
+		free_out_endpt(oep, mem_failure);
+		printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
+		       ir->devnum, ep->bEndpointAddress, mem_failure);
+		return NULL;
+	}
+	return oep;
+}
+
+static void free_irctl(struct atirf_dev *ir, int mem_failure)
+{
+	struct list_head *pos, *n;
+	struct in_endpt *in;
+	dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure);
+
+	if (!ir)
+		return;
+
+	list_for_each_safe(pos, n, &ir->iep_listhead) {
+		in = get_iep_from_link(pos);
+		free_in_endpt(in, FREE_ALL);
+	}
+	if (ir->out_init) {
+		free_out_endpt(ir->out_init, FREE_ALL);
+		ir->out_init = NULL;
+	}
+
+	mutex_lock(&ir->lock);
+	switch (mem_failure) {
+	case FREE_ALL:
+	case 6:
+		if (!--ir->dev_refcount) {
+			list_del(&ir->remote_list_link);
+			dprintk(DRIVER_NAME "[%d]: free_irctl: removing "
+				"remote from list\n", ir->devnum);
+		} else {
+			dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d,"
+				"aborting free_irctl\n",
+				ir->devnum, ir->dev_refcount);
+			mutex_unlock(&ir->lock);
+			return;
+		}
+	case 5:
+	case 4:
+	case 3:
+		if (ir->d) {
+			switch (mem_failure) {
+			case 5:
+				lirc_buffer_free(ir->d->rbuf);
+			case 4:
+				kfree(ir->d->rbuf);
+			case 3:
+				kfree(ir->d);
+			}
+		} else
+			printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n",
+			       ir->devnum);
+	case 2:
+		mutex_unlock(&ir->lock);
+		kfree(ir);
+		return;
+	}
+	mutex_unlock(&ir->lock);
+}
+
+static struct atirf_dev *new_irctl(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct atirf_dev *ir;
+	struct lirc_driver *driver;
+	int type, devnum, dclen;
+	int mem_failure;
+
+	devnum = dev->devnum;
+
+	switch (cpu_to_le16(dev->descriptor.idVendor)) {
+	case VENDOR_ATI1:
+		type = ATI1_COMPATIBLE;
+		break;
+	case VENDOR_ATI2:
+		type = ATI2_COMPATIBLE;
+		break;
+	case VENDOR_MS1:
+	case VENDOR_MS2:
+	case VENDOR_MS3:
+		type = XBOX_COMPATIBLE;
+		break;
+	default:
+		dprintk(DRIVER_NAME "[%d]: unknown type\n", devnum);
+		return NULL;
+	}
+	dprintk(DRIVER_NAME "[%d]: remote type = %d\n", devnum, type);
+
+	mem_failure = 0;
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	if (!ir) {
+		mem_failure = 1;
+		goto new_irctl_failure_check;
+	}
+
+	/*
+	 * at this stage we cannot use the macro [DE]CODE_LENGTH: ir
+	 * is not yet setup
+	 */
+	dclen = decode_length[type];
+	/*
+	 * add this infrared remote struct to remote_list, keeping track
+	 * of the number of drivers registered.
+	 */
+	dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum);
+	list_add_tail(&ir->remote_list_link, &remote_list);
+	ir->dev_refcount = 1;
+
+	driver = kzalloc(sizeof(*driver), GFP_KERNEL);
+	if (!driver) {
+		mem_failure = 2;
+		goto new_irctl_failure_check;
+	}
+
+	ir->d = driver;
+	driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL);
+	if (!driver->rbuf) {
+		mem_failure = 3;
+		goto new_irctl_failure_check;
+	}
+
+	if (lirc_buffer_init(driver->rbuf, dclen, 1)) {
+		mem_failure = 4;
+		goto new_irctl_failure_check;
+	}
+
+	strcpy(driver->name, DRIVER_NAME " ");
+	driver->minor = -1;
+	driver->code_length = dclen * 8;
+	driver->features = LIRC_CAN_REC_LIRCCODE;
+	driver->data = ir;
+	driver->set_use_inc = &set_use_inc;
+	driver->set_use_dec = &set_use_dec;
+#ifdef LIRC_HAVE_SYSFS
+	driver->dev = &intf->dev;
+#endif
+	driver->owner = THIS_MODULE;
+	ir->usbdev = dev;
+	ir->remote_type = type;
+	ir->devnum = devnum;
+	ir->mode = RW2_NULL_MODE;
+
+	mutex_init(&ir->lock);
+	INIT_LIST_HEAD(&ir->iep_listhead);
+
+new_irctl_failure_check:
+
+	if (mem_failure) {
+		free_irctl(ir, mem_failure);
+		printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
+		       devnum, mem_failure);
+		return NULL;
+	}
+	return ir;
+}
+
+
+/*
+ * Scan the global list of remotes to see if the device listed is one of them.
+ * If it is, the corresponding atirf_dev is returned, with its dev_refcount
+ * incremented.  Otherwise, returns null.
+ */
+static struct atirf_dev *get_prior_reg_ir(struct usb_device *dev)
+{
+	struct list_head *pos;
+	struct atirf_dev *ir = NULL;
+
+	dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum);
+	list_for_each(pos, &remote_list) {
+		ir = get_irctl_from_link(pos);
+		if (ir->usbdev != dev) {
+			dprintk(DRIVER_NAME "[%d]: device %d isn't it...",
+				dev->devnum, ir->devnum);
+		    ir = NULL;
+		} else {
+			dprintk(DRIVER_NAME "[%d]: prior instance found.\n",
+				dev->devnum);
+			ir->dev_refcount++;
+			break;
+		}
+	}
+	return ir;
+}
+
+/*
+ * If the USB interface has an out endpoint for control (eg, the first Remote
+ * Wonder) send the appropriate initialization packets.
+ */
+static void send_outbound_init(struct atirf_dev *ir)
+{
+	if (ir->out_init) {
+		struct out_endpt *oep = ir->out_init;
+		dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing "
+			"outbound ep\n", ir->devnum);
+		usb_fill_int_urb(oep->urb, ir->usbdev,
+			usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress),
+			oep->buf, USB_OUTLEN, usb_remote_send,
+			oep, oep->ep->bInterval);
+#ifdef KERNEL_2_5
+		oep->urb->transfer_dma = oep->dma;
+		oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+#endif
+
+		send_packet(oep, 0x8004, init1);
+		send_packet(oep, 0x8007, init2);
+	}
+}
+
+/* Log driver and usb info */
+static void log_usb_dev_info(struct usb_device *dev)
+{
+	char buf[63], name[128] = "";
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+	printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name,
+	       dev->bus->busnum, dev->devnum);
+}
+
+
+#ifdef KERNEL_2_5
+static int usb_remote_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *idesc;
+#else
+static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum,
+				const struct usb_device_id *id)
+{
+	struct usb_interface *intf = &dev->actconfig->interface[ifnum];
+	struct usb_interface_descriptor *idesc;
+#endif
+	struct usb_endpoint_descriptor *ep;
+	struct in_endpt *iep;
+	struct atirf_dev *ir;
+	int i, type;
+
+	dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n",
+		dev->devnum, dev, intf, id);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
+	idesc = &intf->altsetting[intf->act_altsetting];
+#else
+	idesc = intf->cur_altsetting;
+#endif
+
+	/* Check if a usb remote has already been registered for this device */
+	ir = get_prior_reg_ir(dev);
+
+	if (!ir) {
+		ir = new_irctl(intf);
+		if (!ir)
+#ifdef KERNEL_2_5
+			return -ENOMEM;
+#else
+			return NULL;
+#endif
+	}
+	type = ir->remote_type;
+
+	/*
+	 * step through the endpoints to find first in and first out endpoint
+	 * of type interrupt transfer
+	 */
+#ifdef KERNEL_2_5
+	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i].desc;
+#else
+	for (i = 0; i < idesc->bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i];
+#endif
+		dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n",
+			dev->devnum, i);
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+		     USB_DIR_IN) &&
+		     ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		      USB_ENDPOINT_XFER_INT)) {
+
+			iep = new_in_endpt(ir, ep);
+			if (iep)
+			{
+				usb_fill_int_urb(iep->urb, dev,
+					usb_rcvintpipe(dev,
+						iep->ep->bEndpointAddress),
+					iep->buf, iep->len, usb_remote_recv,
+					iep, iep->ep->bInterval);
+#ifdef KERNEL_2_5
+				iep->urb->transfer_dma = iep->dma;
+				iep->urb->transfer_flags |=
+					URB_NO_TRANSFER_DMA_MAP;
+#endif
+			}
+		}
+
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
+		     USB_DIR_OUT) &&
+		     ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		      USB_ENDPOINT_XFER_INT) &&
+		      (ir->out_init == NULL))
+			ir->out_init = new_out_endpt(ir, ep);
+	}
+	if (list_empty(&ir->iep_listhead)) {
+		printk(DRIVER_NAME "[%d]: inbound endpoint not found\n",
+		       ir->devnum);
+		free_irctl(ir, FREE_ALL);
+#ifdef KERNEL_2_5
+		return -ENODEV;
+#else
+		return NULL;
+#endif
+	}
+	if (ir->dev_refcount == 1) {
+		ir->d->minor = lirc_register_driver(ir->d);
+		if (ir->d->minor < 0) {
+			free_irctl(ir, FREE_ALL);
+#ifdef KERNEL_2_5
+			return -ENODEV;
+#else
+			return NULL;
+#endif
+		}
+
+		/* Note new driver registration in kernel logs */
+		log_usb_dev_info(dev);
+
+		/* outbound data (initialization) */
+		send_outbound_init(ir);
+	}
+
+#ifdef KERNEL_2_5
+	usb_set_intfdata(intf, ir);
+	return 0;
+#else
+	return ir;
+#endif
+}
+
+#ifdef KERNEL_2_5
+static void usb_remote_disconnect(struct usb_interface *intf)
+{
+	/* struct usb_device *dev = interface_to_usbdev(intf); */
+	struct atirf_dev *ir = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+#else
+static void usb_remote_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct atirf_dev *ir = ptr;
+#endif
+
+	dprintk(DRIVER_NAME ": disconnecting remote %d:\n",
+		(ir ? ir->devnum : -1));
+	if (!ir || !ir->d)
+		return;
+
+	if (ir->usbdev) {
+		/* Only unregister once */
+		ir->usbdev = NULL;
+		unregister_from_lirc(ir);
+	}
+
+	/* This also removes the current remote from remote_list */
+	free_irctl(ir, FREE_ALL);
+}
+
+static struct usb_driver usb_remote_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name		= DRIVER_NAME,
+	.probe		= usb_remote_probe,
+	.disconnect	= usb_remote_disconnect,
+	.id_table	= usb_remote_table
+};
+
+static int __init usb_remote_init(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&remote_list);
+
+	printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " "
+	       DRIVER_VERSION "\n");
+	printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n");
+	dprintk(DRIVER_NAME ": debug mode enabled: "
+		"$Id: lirc_atiusb.c,v 1.85 2009/03/11 00:21:46 jarodwilson Exp $\n");
+
+	repeat_jiffies = repeat*HZ/100;
+
+	i = usb_register(&usb_remote_driver);
+	if (i) {
+		printk(DRIVER_NAME ": usb register failed, result = %d\n", i);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit usb_remote_exit(void)
+{
+	usb_deregister(&usb_remote_driver);
+}
+
+module_init(usb_remote_init);
+module_exit(usb_remote_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, usb_remote_table);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)");
+
+module_param(mask, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)");
+
+module_param(unique, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)");
+
+module_param(repeat, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)");
+
+module_param(mdeadzone, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mdeadzone, "rw2 mouse sensitivity threshold (default: 0)");
+
+/*
+ * Enabling this will cause the built-in Remote Wonder II repeat coding to
+ * not be squashed.  The second byte of the keys output will then be:
+ *
+ *	1 initial press (button down)
+ *	2 holding (button remains pressed)
+ *	0 release (button up)
+ *
+ * By default, the driver emits 2 for both 1 and 2, and emits nothing for 0.
+ * This is good for people having trouble getting their rw2 to send a good
+ * consistent signal to the receiver.
+ *
+ * However, if you have no troubles with the driver outputting up-down pairs
+ * at random points while you're still holding a button, then you can enable
+ * this parameter to get finer grain repeat control out of your remote:
+ *
+ *	1 Emit a single (per-channel) virtual code for all up/down events
+ *	2 Emit the actual rw2 output
+ *
+ * 1 is easier to write lircd configs for; 2 allows full control.
+ */
+module_param(emit_updown, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(emit_updown, "emit press/release codes (rw2): 0:don't "
+		 "(default), 1:emit 2 codes only, 2:code for each button");
+
+module_param(emit_modekeys, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(emit_modekeys, "emit keycodes for aux1-aux4, pc, and mouse "
+		 "(rw2): 0:don't (default), 1:emit translated codes: one for "
+		 "mode switch, one for same mode, 2:raw codes");
+
+module_param(mgradient, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mgradient, "rw2 mouse: 1000*gradient from E to NE (default: "
+		 "500 => .5 => ~27 degrees)");
+
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_streamzap/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_streamzap/Makefile
@@ -0,0 +1,2 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+obj-$(CONFIG_LIRC_STREAMZAP)	+= lirc_streamzap.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c
@@ -0,0 +1,889 @@
+/*      $Id: lirc_streamzap.c,v 1.48 2009/03/15 09:34:00 lirc Exp $      */
+/*
+ * Streamzap Remote Control driver
+ *
+ * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
+ *
+ * This driver was based on the work of Greg Wickham and Adrian
+ * Dewhurst. It was substantially rewritten to support correct signal
+ * gaps and now maintains a delay buffer, which is used to present
+ * consistent timing behaviour to user space applications. Without the
+ * delay buffer an ugly hack would be required in lircd, which can
+ * cause sluggish signal decoding in certain situations.
+ *
+ * This driver is based on the USB skeleton driver packaged with the
+ * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *  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/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#error "*******************************************************"
+#error "Sorry, this driver needs kernel version 2.4.0 or higher"
+#error "*******************************************************"
+#endif
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#include <asm/uaccess.h>
+#else
+#include <linux/uaccess.h>
+#endif
+#include <linux/usb.h>
+
+#include "../lirc.h"
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+#define DRIVER_VERSION	"$Revision: 1.48 $"
+#define DRIVER_NAME	"lirc_streamzap"
+#define DRIVER_DESC	"Streamzap Remote Control driver"
+
+static int debug;
+
+#define USB_STREAMZAP_VENDOR_ID		0x0e9c
+#define USB_STREAMZAP_PRODUCT_ID	0x0000
+
+/* Use our own dbg macro */
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG DRIVER_NAME "[%d]: "	\
+			       fmt "\n", ## args);		\
+	} while (0)
+
+/* table of devices that work with this driver */
+static struct usb_device_id streamzap_table[] = {
+	/* Streamzap Remote Control */
+	{ USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
+	/* Terminating entry */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, streamzap_table);
+
+#define STREAMZAP_PULSE_MASK 0xf0
+#define STREAMZAP_SPACE_MASK 0x0f
+#define STREAMZAP_RESOLUTION 256
+
+/* number of samples buffered */
+#define STREAMZAP_BUFFER_SIZE 128
+
+enum StreamzapDecoderState {
+	PulseSpace,
+	FullPulse,
+	FullSpace,
+	IgnorePulse
+};
+
+/* Structure to hold all of our device specific stuff
+ *
+ * some remarks regarding locking:
+ * theoretically this struct can be accessed from three threads:
+ *
+ * - from lirc_dev through set_use_inc/set_use_dec
+ *
+ * - from the USB layer throuh probe/disconnect/irq
+ *
+ *   Careful placement of lirc_register_driver/lirc_unregister_driver
+ *   calls will prevent conflicts. lirc_dev makes sure that
+ *   set_use_inc/set_use_dec are not being executed and will not be
+ *   called after lirc_unregister_driver returns.
+ *
+ * - by the timer callback
+ *
+ *   The timer is only running when the device is connected and the
+ *   LIRC device is open. Making sure the timer is deleted by
+ *   set_use_dec will make conflicts impossible.
+ */
+struct usb_streamzap {
+
+	/* usb */
+	/* save off the usb device pointer */
+	struct usb_device	*udev;
+	/* the interface for this device */
+	struct usb_interface	*interface;
+
+	/* buffer & dma */
+	unsigned char		*buf_in;
+	dma_addr_t		dma_in;
+	unsigned int		buf_in_len;
+
+	struct usb_endpoint_descriptor *endpoint;
+
+	/* IRQ */
+	struct urb		*urb_in;
+
+	/* lirc */
+	struct lirc_driver	driver;
+	struct lirc_buffer	delay_buf;
+	struct lirc_buffer	lirc_buf;
+
+	/* timer used to support delay buffering */
+	struct timer_list	delay_timer;
+	int			timer_running;
+	spinlock_t		timer_lock;
+
+	/* tracks whether we are currently receiving some signal */
+	int			idle;
+	/* sum of signal lengths received since signal start */
+	unsigned long		sum;
+	/* start time of signal; necessary for gap tracking */
+	struct timeval		signal_last;
+	struct timeval		signal_start;
+	enum StreamzapDecoderState decoder_state;
+	struct timer_list	flush_timer;
+	int			flush;
+	int			in_use;
+};
+
+
+/* local function prototypes */
+#ifdef KERNEL_2_5
+static int streamzap_probe(struct usb_interface *interface,
+			   const struct usb_device_id *id);
+static void streamzap_disconnect(struct usb_interface *interface);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs);
+#else
+static void usb_streamzap_irq(struct urb *urb);
+#endif
+#else
+static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum,
+			     const struct usb_device_id *id);
+static void streamzap_disconnect(struct usb_device *dev, void *ptr);
+static void usb_streamzap_irq(struct urb *urb);
+#endif
+static int streamzap_use_inc(void *data);
+static void streamzap_use_dec(void *data);
+static int streamzap_ioctl(struct inode *node, struct file *filep,
+			   unsigned int cmd, unsigned long arg);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
+static int streamzap_resume(struct usb_interface *intf);
+#endif
+
+/* usb specific object needed to register this driver with the usb subsystem */
+
+static struct usb_driver streamzap_driver = {
+	LIRC_THIS_MODULE(.owner = THIS_MODULE)
+	.name =		DRIVER_NAME,
+	.probe =	streamzap_probe,
+	.disconnect =	streamzap_disconnect,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+	.suspend =	streamzap_suspend,
+	.resume =	streamzap_resume,
+#endif
+	.id_table =	streamzap_table,
+};
+
+static void stop_timer(struct usb_streamzap *sz)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sz->timer_lock, flags);
+	if (sz->timer_running) {
+		sz->timer_running = 0;
+		spin_unlock_irqrestore(&sz->timer_lock, flags);
+		del_timer_sync(&sz->delay_timer);
+	} else {
+		spin_unlock_irqrestore(&sz->timer_lock, flags);
+	}
+}
+
+static void flush_timeout(unsigned long arg)
+{
+	struct usb_streamzap *sz = (struct usb_streamzap *) arg;
+
+	/* finally start accepting data */
+	sz->flush = 0;
+}
+static void delay_timeout(unsigned long arg)
+{
+	unsigned long flags;
+	/* deliver data every 10 ms */
+	static unsigned long timer_inc =
+		(10000/(1000000/HZ)) == 0 ? 1 : (10000/(1000000/HZ));
+	struct usb_streamzap *sz = (struct usb_streamzap *) arg;
+	lirc_t data;
+
+	spin_lock_irqsave(&sz->timer_lock, flags);
+
+	if (!lirc_buffer_empty(&sz->delay_buf) &&
+	    !lirc_buffer_full(&sz->lirc_buf)) {
+		lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data);
+		lirc_buffer_write(&sz->lirc_buf, (unsigned char *) &data);
+	}
+	if (!lirc_buffer_empty(&sz->delay_buf)) {
+		while (lirc_buffer_available(&sz->delay_buf) <
+		      STREAMZAP_BUFFER_SIZE/2 &&
+		      !lirc_buffer_full(&sz->lirc_buf)) {
+			lirc_buffer_read(&sz->delay_buf,
+					 (unsigned char *) &data);
+			lirc_buffer_write(&sz->lirc_buf,
+					  (unsigned char *) &data);
+		}
+		if (sz->timer_running) {
+			sz->delay_timer.expires = jiffies + timer_inc;
+			add_timer(&sz->delay_timer);
+		}
+	} else {
+		sz->timer_running = 0;
+	}
+
+	if (!lirc_buffer_empty(&sz->lirc_buf))
+		wake_up(&sz->lirc_buf.wait_poll);
+
+	spin_unlock_irqrestore(&sz->timer_lock, flags);
+}
+
+static void flush_delay_buffer(struct usb_streamzap *sz)
+{
+	lirc_t data;
+	int empty = 1;
+
+	while (!lirc_buffer_empty(&sz->delay_buf)) {
+		empty = 0;
+		lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data);
+		if (!lirc_buffer_full(&sz->lirc_buf)) {
+			lirc_buffer_write(&sz->lirc_buf,
+					    (unsigned char *) &data);
+		} else {
+			dprintk("buffer overflow", sz->driver.minor);
+		}
+	}
+	if (!empty)
+		wake_up(&sz->lirc_buf.wait_poll);
+}
+
+static void push(struct usb_streamzap *sz, unsigned char *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sz->timer_lock, flags);
+	if (lirc_buffer_full(&sz->delay_buf)) {
+		lirc_t data;
+
+		lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data);
+		if (!lirc_buffer_full(&sz->lirc_buf)) {
+			lirc_buffer_write(&sz->lirc_buf,
+					  (unsigned char *) &data);
+		} else {
+			dprintk("buffer overflow", sz->driver.minor);
+		}
+	}
+
+	lirc_buffer_write(&sz->delay_buf, data);
+
+	if (!sz->timer_running) {
+		sz->delay_timer.expires = jiffies + HZ/10;
+		add_timer(&sz->delay_timer);
+		sz->timer_running = 1;
+	}
+
+	spin_unlock_irqrestore(&sz->timer_lock, flags);
+}
+
+static void push_full_pulse(struct usb_streamzap *sz,
+				   unsigned char value)
+{
+	lirc_t pulse;
+
+	if (sz->idle) {
+		long deltv;
+		lirc_t tmp;
+
+		sz->signal_last = sz->signal_start;
+		do_gettimeofday(&sz->signal_start);
+
+		deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec;
+		if (deltv > 15) {
+			tmp = PULSE_MASK; /* really long time */
+		} else {
+			tmp = (lirc_t) (deltv*1000000+
+					sz->signal_start.tv_usec -
+					sz->signal_last.tv_usec);
+			tmp -= sz->sum;
+		}
+		dprintk("ls %u", sz->driver.minor, tmp);
+		push(sz, (char *)&tmp);
+
+		sz->idle = 0;
+		sz->sum = 0;
+	}
+
+	pulse = ((lirc_t) value)*STREAMZAP_RESOLUTION;
+	pulse += STREAMZAP_RESOLUTION/2;
+	sz->sum += pulse;
+	pulse |= PULSE_BIT;
+
+	dprintk("p %u", sz->driver.minor, pulse&PULSE_MASK);
+	push(sz, (char *)&pulse);
+}
+
+static void push_half_pulse(struct usb_streamzap *sz,
+				   unsigned char value)
+{
+	push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK)>>4);
+}
+
+static void push_full_space(struct usb_streamzap *sz,
+				   unsigned char value)
+{
+	lirc_t space;
+
+	space = ((lirc_t) value)*STREAMZAP_RESOLUTION;
+	space += STREAMZAP_RESOLUTION/2;
+	sz->sum += space;
+	dprintk("s %u", sz->driver.minor, space);
+	push(sz, (char *)&space);
+}
+
+static void push_half_space(struct usb_streamzap *sz,
+				   unsigned char value)
+{
+	push_full_space(sz, value & STREAMZAP_SPACE_MASK);
+}
+
+/**
+ * usb_streamzap_irq - IRQ handler
+ *
+ * This procedure is invoked on reception of data from
+ * the usb remote.
+ */
+#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs)
+#else
+static void usb_streamzap_irq(struct urb *urb)
+#endif
+{
+	struct usb_streamzap *sz;
+	int		len;
+	unsigned int	i = 0;
+
+	if (!urb)
+		return;
+
+	sz = urb->context;
+	len = urb->actual_length;
+
+	switch (urb->status) {
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/*
+		 * this urb is terminated, clean up.
+		 * sz might already be invalid at this point
+		 */
+		dprintk("urb status: %d", -1, urb->status);
+		return;
+	default:
+		break;
+	}
+
+	dprintk("received %d", sz->driver.minor, urb->actual_length);
+	if (!sz->flush) {
+		for (i = 0; i < urb->actual_length; i++) {
+			dprintk("%d: %x", sz->driver.minor,
+				i, (unsigned char) sz->buf_in[i]);
+			switch (sz->decoder_state) {
+			case PulseSpace:
+				if ((sz->buf_in[i]&STREAMZAP_PULSE_MASK) ==
+				    STREAMZAP_PULSE_MASK) {
+					sz->decoder_state = FullPulse;
+					continue;
+				} else if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK)
+					   == STREAMZAP_SPACE_MASK) {
+					push_half_pulse(sz, sz->buf_in[i]);
+					sz->decoder_state = FullSpace;
+					continue;
+				} else {
+					push_half_pulse(sz, sz->buf_in[i]);
+					push_half_space(sz, sz->buf_in[i]);
+				}
+				break;
+			case FullPulse:
+				push_full_pulse(sz, sz->buf_in[i]);
+				sz->decoder_state = IgnorePulse;
+				break;
+			case FullSpace:
+				if (sz->buf_in[i] == 0xff) {
+					sz->idle = 1;
+					stop_timer(sz);
+					flush_delay_buffer(sz);
+				} else
+					push_full_space(sz, sz->buf_in[i]);
+				sz->decoder_state = PulseSpace;
+				break;
+			case IgnorePulse:
+				if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
+				    STREAMZAP_SPACE_MASK) {
+					sz->decoder_state = FullSpace;
+					continue;
+				}
+				push_half_space(sz, sz->buf_in[i]);
+				sz->decoder_state = PulseSpace;
+				break;
+			}
+		}
+	}
+
+#ifdef KERNEL_2_5
+	usb_submit_urb(urb, GFP_ATOMIC);
+#endif
+
+	return;
+}
+
+static struct file_operations streamzap_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= streamzap_ioctl,
+};
+
+
+/**
+ *	streamzap_probe
+ *
+ *	Called by usb-core to associated with a candidate device
+ *	On any failure the return value is the ERROR
+ *	On success return 0
+ */
+#ifdef KERNEL_2_5
+static int streamzap_probe(struct usb_interface *interface,
+			   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *iface_host;
+#else
+static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct usb_interface *interface = &udev->actconfig->interface[ifnum];
+	struct usb_interface_descriptor *iface_host;
+#endif
+	int retval = -ENOMEM;
+	struct usb_streamzap *sz = NULL;
+	char buf[63], name[128] = "";
+
+	/* Allocate space for device driver specific data */
+	sz = kzalloc(sizeof(struct usb_streamzap), GFP_KERNEL);
+	if (sz == NULL)
+		goto error;
+
+	sz->udev = udev;
+	sz->interface = interface;
+
+	/* Check to ensure endpoint information matches requirements */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
+	iface_host = &interface->altsetting[interface->act_altsetting];
+#else
+	iface_host = interface->cur_altsetting;
+#endif
+
+#ifdef KERNEL_2_5
+	if (iface_host->desc.bNumEndpoints != 1) {
+#else
+	if (iface_host->bNumEndpoints != 1) {
+#endif
+#ifdef KERNEL_2_5
+		err("%s: Unexpected desc.bNumEndpoints (%d)", __func__,
+		    iface_host->desc.bNumEndpoints);
+#else
+		err("%s: Unexpected desc.bNumEndpoints (%d)", __func__,
+		    iface_host->bNumEndpoints);
+#endif
+		retval = -ENODEV;
+		goto error;
+	}
+
+#ifdef KERNEL_2_5
+	sz->endpoint = &(iface_host->endpoint[0].desc);
+#else
+	sz->endpoint = &(iface_host->endpoint[0]);
+#endif
+	if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+	    != USB_DIR_IN) {
+		err("%s: endpoint doesn't match input device 02%02x",
+		    __func__, sz->endpoint->bEndpointAddress);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+	    != USB_ENDPOINT_XFER_INT) {
+		err("%s: endpoint attributes don't match xfer 02%02x",
+		    __func__, sz->endpoint->bmAttributes);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (sz->endpoint->wMaxPacketSize == 0) {
+		err("%s: endpoint message size==0? ", __func__);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	/* Allocate the USB buffer and IRQ URB */
+
+	sz->buf_in_len = sz->endpoint->wMaxPacketSize;
+#ifdef KERNEL_2_5
+	sz->buf_in = usb_buffer_alloc(sz->udev, sz->buf_in_len,
+				      GFP_ATOMIC, &sz->dma_in);
+#else
+	sz->buf_in = kmalloc(sz->buf_in_len, GFP_KERNEL);
+#endif
+	if (sz->buf_in == NULL)
+		goto error;
+
+#ifdef KERNEL_2_5
+	sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+#else
+
+	sz->urb_in = usb_alloc_urb(0);
+#endif
+	if (sz->urb_in == NULL)
+		goto error;
+
+	/* Connect this device to the LIRC sub-system */
+
+	if (lirc_buffer_init(&sz->lirc_buf, sizeof(lirc_t),
+			     STREAMZAP_BUFFER_SIZE))
+		goto error;
+
+	if (lirc_buffer_init(&sz->delay_buf, sizeof(lirc_t),
+			     STREAMZAP_BUFFER_SIZE)) {
+		lirc_buffer_free(&sz->lirc_buf);
+		goto error;
+	}
+
+	strcpy(sz->driver.name, DRIVER_NAME);
+	sz->driver.minor = -1;
+	sz->driver.sample_rate = 0;
+	sz->driver.code_length = sizeof(lirc_t) * 8;
+	sz->driver.features = LIRC_CAN_REC_MODE2 | LIRC_CAN_GET_REC_RESOLUTION;
+	sz->driver.data = sz;
+	sz->driver.rbuf = &sz->lirc_buf;
+	sz->driver.set_use_inc = &streamzap_use_inc;
+	sz->driver.set_use_dec = &streamzap_use_dec;
+	sz->driver.fops = &streamzap_fops;
+#ifdef LIRC_HAVE_SYSFS
+	sz->driver.dev = &interface->dev;
+#endif
+	sz->driver.owner = THIS_MODULE;
+
+	sz->idle = 1;
+	sz->decoder_state = PulseSpace;
+	init_timer(&sz->delay_timer);
+	sz->delay_timer.function = delay_timeout;
+	sz->delay_timer.data = (unsigned long) sz;
+	sz->timer_running = 0;
+	spin_lock_init(&sz->timer_lock);
+
+	init_timer(&sz->flush_timer);
+	sz->flush_timer.function = flush_timeout;
+	sz->flush_timer.data = (unsigned long) sz;
+	/* Complete final initialisations */
+
+	usb_fill_int_urb(sz->urb_in, udev,
+		usb_rcvintpipe(udev, sz->endpoint->bEndpointAddress),
+		sz->buf_in, sz->buf_in_len, usb_streamzap_irq, sz,
+		sz->endpoint->bInterval);
+#ifdef KERNEL_2_5
+	sz->urb_in->transfer_dma = sz->dma_in;
+	sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+#endif
+
+	if (udev->descriptor.iManufacturer
+	    && usb_string(udev, udev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+
+	if (udev->descriptor.iProduct
+	    && usb_string(udev,  udev->descriptor.iProduct,
+			  buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+
+	printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n",
+	       sz->driver.minor, name,
+	       udev->bus->busnum, sz->udev->devnum);
+
+#ifdef KERNEL_2_5
+	usb_set_intfdata(interface, sz);
+#endif
+
+	if (lirc_register_driver(&sz->driver) < 0) {
+		lirc_buffer_free(&sz->delay_buf);
+		lirc_buffer_free(&sz->lirc_buf);
+		goto error;
+	}
+
+#ifdef KERNEL_2_5
+	return 0;
+#else
+	return sz;
+#endif
+
+error:
+
+	/*
+	 * Premise is that a 'goto error' can be invoked from inside the
+	 * probe function and all necessary cleanup actions will be taken
+	 * including freeing any necessary memory blocks
+	 */
+
+	if (retval == -ENOMEM)
+		err("Out of memory");
+
+	if (sz) {
+		usb_free_urb(sz->urb_in);
+#ifdef KERNEL_2_5
+		usb_buffer_free(udev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+#else
+		if (sz->buf_in) {
+			kfree(sz->buf_in);
+		}
+#endif
+		kfree(sz);
+	}
+
+#ifdef KERNEL_2_5
+	return retval;
+#else
+	return NULL;
+#endif
+}
+
+static int streamzap_use_inc(void *data)
+{
+	struct usb_streamzap *sz = data;
+
+	if (!sz) {
+		dprintk("%s called with no context", -1, __func__);
+		return -EINVAL;
+	}
+	dprintk("set use inc", sz->driver.minor);
+	MOD_INC_USE_COUNT;
+
+	lirc_buffer_clear(&sz->lirc_buf);
+	lirc_buffer_clear(&sz->delay_buf);
+
+	sz->flush_timer.expires = jiffies + HZ;
+	sz->flush = 1;
+	add_timer(&sz->flush_timer);
+
+	sz->urb_in->dev = sz->udev;
+#ifdef KERNEL_2_5
+	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
+#else
+	if (usb_submit_urb(sz->urb_in)) {
+#endif
+		dprintk("open result = -EIO error submitting urb",
+			sz->driver.minor);
+		MOD_DEC_USE_COUNT;
+		return -EIO;
+	}
+	sz->in_use++;
+
+	return 0;
+}
+
+static void streamzap_use_dec(void *data)
+{
+	struct usb_streamzap *sz = data;
+
+	if (!sz) {
+		dprintk("%s called with no context", -1, __func__);
+		return;
+	}
+	dprintk("set use dec", sz->driver.minor);
+
+	if (sz->flush) {
+		sz->flush = 0;
+		del_timer_sync(&sz->flush_timer);
+	}
+
+	usb_kill_urb(sz->urb_in);
+
+	stop_timer(sz);
+
+	MOD_DEC_USE_COUNT;
+	sz->in_use--;
+}
+
+static int streamzap_ioctl(struct inode *node, struct file *filep,
+			   unsigned int cmd, unsigned long arg)
+{
+	int result;
+
+	switch (cmd) {
+	case LIRC_GET_REC_RESOLUTION:
+		result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg);
+		if (result)
+			return result;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+/**
+ * streamzap_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ *
+ * This routine guarantees that the driver will not submit any more urbs
+ * by clearing dev->udev.  It is also supposed to terminate any currently
+ * active urbs.  Unfortunately, usb_bulk_msg(), used in streamzap_read(),
+ * does not provide any way to do this.
+ */
+#ifdef KERNEL_2_5
+static void streamzap_disconnect(struct usb_interface *interface)
+#else
+static void streamzap_disconnect(struct usb_device *dev, void *ptr)
+#endif
+{
+	struct usb_streamzap *sz;
+	int errnum;
+	int minor;
+
+#ifdef KERNEL_2_5
+	sz = usb_get_intfdata(interface);
+#else
+	sz = ptr;
+#endif
+
+	/* unregister from the LIRC sub-system */
+
+	errnum = lirc_unregister_driver(sz->driver.minor);
+	if (errnum != 0)
+		dprintk("error in lirc_unregister: (returned %d)",
+			sz->driver.minor, errnum);
+
+	lirc_buffer_free(&sz->delay_buf);
+	lirc_buffer_free(&sz->lirc_buf);
+
+	/* unregister from the USB sub-system */
+
+	usb_free_urb(sz->urb_in);
+
+#ifdef KERNEL_2_5
+	usb_buffer_free(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+#else
+	kfree(sz->buf_in);
+#endif
+
+	minor = sz->driver.minor;
+	kfree(sz);
+
+	printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_streamzap *sz = usb_get_intfdata(intf);
+
+	printk(KERN_INFO DRIVER_NAME "[%d]: suspend\n", sz->driver.minor);
+	if (sz->in_use) {
+		if (sz->flush) {
+			sz->flush = 0;
+			del_timer_sync(&sz->flush_timer);
+		}
+
+		stop_timer(sz);
+
+		usb_kill_urb(sz->urb_in);
+	}
+	return 0;
+}
+
+static int streamzap_resume(struct usb_interface *intf)
+{
+	struct usb_streamzap *sz = usb_get_intfdata(intf);
+
+	lirc_buffer_clear(&sz->lirc_buf);
+	lirc_buffer_clear(&sz->delay_buf);
+
+	if (sz->in_use) {
+		sz->flush_timer.expires = jiffies + HZ;
+		sz->flush = 1;
+		add_timer(&sz->flush_timer);
+
+		sz->urb_in->dev = sz->udev;
+#ifdef KERNEL_2_5
+		if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
+#else
+		if (usb_submit_urb(sz->urb_in)) {
+#endif
+			dprintk("open result = -EIO error submitting urb",
+				sz->driver.minor);
+			MOD_DEC_USE_COUNT;
+			return -EIO;
+		}
+	}
+	return 0;
+}
+#endif
+
+#ifdef MODULE
+/**
+ *	usb_streamzap_init
+ */
+static int __init usb_streamzap_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&streamzap_driver);
+
+	if (result) {
+		err("usb_register failed. Error number %d",
+		    result);
+		return result;
+	}
+
+	printk(KERN_INFO DRIVER_NAME " " DRIVER_VERSION " registered\n");
+	return 0;
+}
+
+/**
+ *	usb_streamzap_exit
+ */
+static void __exit usb_streamzap_exit(void)
+{
+	usb_deregister(&streamzap_driver);
+}
+
+
+module_init(usb_streamzap_init);
+module_exit(usb_streamzap_exit);
+
+MODULE_AUTHOR("Christoph Bartelmus, Greg Wickham, Adrian Dewhurst");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_bt829/Makefile
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_bt829/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/..
+
+obj-$(CONFIG_LIRC_ATIUSB)	+= lirc_bt829.o
--- linux-ec2-2.6.32.orig/ubuntu/lirc/lirc_bt829/lirc_bt829.c
+++ linux-ec2-2.6.32/ubuntu/lirc/lirc_bt829/lirc_bt829.c
@@ -0,0 +1,399 @@
+/*
+ * Remote control driver for the TV-card based on bt829
+ *
+ *  by Leonid Froenchenko <lfroen@galileo.co.il>
+ *
+ *  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/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#error "This driver needs kernel version 2.4.0 or higher"
+#endif
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/threads.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "../kcompat.h"
+#include "../lirc_dev/lirc_dev.h"
+
+static int poll_main(void);
+static int atir_init_start(void);
+
+static void write_index(unsigned char index, unsigned int value);
+static unsigned int read_index(unsigned char index);
+
+static void do_i2c_start(void);
+static void do_i2c_stop(void);
+
+static void seems_wr_byte(unsigned char al);
+static unsigned char seems_rd_byte(void);
+
+static unsigned int read_index(unsigned char al);
+static void write_index(unsigned char ah, unsigned int edx);
+
+static void cycle_delay(int cycle);
+
+static void do_set_bits(unsigned char bl);
+static unsigned char do_get_bits(void);
+
+#define DATA_PCI_OFF 0x7FFC00
+#define WAIT_CYCLE   20
+
+#define DRIVER_NAME "lirc_bt829"
+
+static int debug;
+#define dprintk(fmt, args...)					\
+	do {							\
+		if (debug)					\
+			printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args); \
+	} while (0)
+
+static int atir_minor;
+static unsigned long pci_addr_phys;
+static unsigned char *pci_addr_lin;
+
+static struct lirc_driver atir_driver;
+
+static struct pci_dev *do_pci_probe(void)
+{
+	struct pci_dev *my_dev;
+#ifndef KERNEL_2_5
+	/* unnecessary with recent kernels */
+	if (!pci_present())
+		printk(KERN_ERR DRIVER_NAME ": no pci in this kernel\n");
+#endif
+	my_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+				PCI_DEVICE_ID_ATI_264VT, NULL);
+	if (my_dev) {
+		printk(KERN_ERR DRIVER_NAME ": Using device: %s\n",
+		       pci_name(my_dev));
+		pci_addr_phys = 0;
+		if (my_dev->resource[0].flags & IORESOURCE_MEM) {
+			pci_addr_phys = my_dev->resource[0].start;
+			printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n",
+			       (unsigned int)pci_addr_phys);
+		}
+		if (pci_addr_phys == 0) {
+			printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n");
+			return NULL;
+		}
+	} else {
+		printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n");
+		return NULL;
+	}
+	return my_dev;
+}
+
+static int atir_add_to_buf(void *data, struct lirc_buffer *buf)
+{
+	unsigned char key;
+	int status;
+	status = poll_main();
+	key = (status >> 8) & 0xFF;
+	if (status & 0xFF) {
+		dprintk("reading key %02X\n", key);
+		lirc_buffer_write(buf, &key);
+		return 0;
+	}
+	return -ENODATA;
+}
+
+static int atir_set_use_inc(void *data)
+{
+	MOD_INC_USE_COUNT;
+	dprintk("driver is opened\n");
+	return 0;
+}
+
+static void atir_set_use_dec(void *data)
+{
+	MOD_DEC_USE_COUNT;
+	dprintk("driver is closed\n");
+}
+
+int init_module(void)
+{
+	struct pci_dev *pdev;
+
+	pdev = do_pci_probe();
+	if (pdev == NULL)
+		return 1;
+
+	if (!atir_init_start())
+		return 1;
+
+	strcpy(atir_driver.name, "ATIR");
+	atir_driver.minor       = -1;
+	atir_driver.code_length = 8;
+	atir_driver.sample_rate = 10;
+	atir_driver.data        = 0;
+	atir_driver.add_to_buf  = atir_add_to_buf;
+	atir_driver.set_use_inc = atir_set_use_inc;
+	atir_driver.set_use_dec = atir_set_use_dec;
+#ifdef LIRC_HAVE_SYSFS
+	atir_driver.dev         = &pdev->dev;
+#endif
+	atir_driver.owner       = THIS_MODULE;
+
+	atir_minor = lirc_register_driver(&atir_driver);
+	if (atir_minor < 0) {
+		printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n");
+		return atir_minor;
+	}
+	dprintk("driver is registered on minor %d\n", atir_minor);
+
+	return 0;
+}
+
+
+void cleanup_module(void)
+{
+	lirc_unregister_driver(atir_minor);
+}
+
+
+static int atir_init_start(void)
+{
+	pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
+	if (pci_addr_lin == 0) {
+		printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n");
+		return 0;
+	}
+	return 1;
+}
+
+static void cycle_delay(int cycle)
+{
+	udelay(WAIT_CYCLE*cycle);
+}
+
+
+static int poll_main()
+{
+	unsigned char status_high, status_low;
+
+	do_i2c_start();
+
+	seems_wr_byte(0xAA);
+	seems_wr_byte(0x01);
+
+	do_i2c_start();
+
+	seems_wr_byte(0xAB);
+
+	status_low = seems_rd_byte();
+	status_high = seems_rd_byte();
+
+	do_i2c_stop();
+
+	return (status_high << 8) | status_low;
+}
+
+static void do_i2c_start(void)
+{
+	do_set_bits(3);
+	cycle_delay(4);
+
+	do_set_bits(1);
+	cycle_delay(7);
+
+	do_set_bits(0);
+	cycle_delay(2);
+}
+
+static void do_i2c_stop(void)
+{
+	unsigned char bits;
+	bits =  do_get_bits() & 0xFD;
+	do_set_bits(bits);
+	cycle_delay(1);
+
+	bits |= 1;
+	do_set_bits(bits);
+	cycle_delay(2);
+
+	bits |= 2;
+	do_set_bits(bits);
+	bits = 3;
+	do_set_bits(bits);
+	cycle_delay(2);
+}
+
+static void seems_wr_byte(unsigned char value)
+{
+	int i;
+	unsigned char reg;
+
+	reg = do_get_bits();
+	for (i = 0; i < 8; i++) {
+		if (value & 0x80)
+			reg |= 0x02;
+		else
+			reg &= 0xFD;
+
+		do_set_bits(reg);
+		cycle_delay(1);
+
+		reg |= 1;
+		do_set_bits(reg);
+		cycle_delay(1);
+
+		reg &= 0xFE;
+		do_set_bits(reg);
+		cycle_delay(1);
+		value <<= 1;
+	}
+	cycle_delay(2);
+
+	reg |= 2;
+	do_set_bits(reg);
+
+	reg |= 1;
+	do_set_bits(reg);
+
+	cycle_delay(1);
+	do_get_bits();
+
+	reg &= 0xFE;
+	do_set_bits(reg);
+	cycle_delay(3);
+}
+
+static unsigned char seems_rd_byte(void)
+{
+	int i;
+	int rd_byte;
+	unsigned char bits_2, bits_1;
+
+	bits_1 = do_get_bits() | 2;
+	do_set_bits(bits_1);
+
+	rd_byte = 0;
+	for (i = 0; i < 8; i++) {
+		bits_1 &= 0xFE;
+		do_set_bits(bits_1);
+		cycle_delay(2);
+
+		bits_1 |= 1;
+		do_set_bits(bits_1);
+		cycle_delay(1);
+
+		bits_2 = do_get_bits();
+		if (bits_2 & 2)
+			rd_byte |= 1;
+
+		rd_byte <<= 1;
+	}
+
+	bits_1 = 0;
+	if (bits_2 == 0)
+		bits_1 |= 2;
+
+	do_set_bits(bits_1);
+	cycle_delay(2);
+
+	bits_1 |= 1;
+	do_set_bits(bits_1);
+	cycle_delay(3);
+
+	bits_1 &= 0xFE;
+	do_set_bits(bits_1);
+	cycle_delay(2);
+
+	rd_byte >>= 1;
+	rd_byte &= 0xFF;
+	return rd_byte;
+}
+
+static void do_set_bits(unsigned char new_bits)
+{
+	int reg_val;
+	reg_val = read_index(0x34);
+	if (new_bits & 2) {
+		reg_val &= 0xFFFFFFDF;
+		reg_val |= 1;
+	} else {
+		reg_val &= 0xFFFFFFFE;
+		reg_val |= 0x20;
+	}
+	reg_val |= 0x10;
+	write_index(0x34, reg_val);
+
+	reg_val = read_index(0x31);
+	if (new_bits & 1)
+		reg_val |= 0x1000000;
+	else
+		reg_val &= 0xFEFFFFFF;
+
+	reg_val |= 0x8000000;
+	write_index(0x31, reg_val);
+}
+
+static unsigned char do_get_bits(void)
+{
+	unsigned char bits;
+	int reg_val;
+
+	reg_val = read_index(0x34);
+	reg_val |= 0x10;
+	reg_val &= 0xFFFFFFDF;
+	write_index(0x34, reg_val);
+
+	reg_val = read_index(0x34);
+	bits = 0;
+	if (reg_val & 8)
+		bits |= 2;
+	else
+		bits &= 0xFD;
+
+	reg_val = read_index(0x31);
+	if (reg_val & 0x1000000)
+		bits |= 1;
+	else
+		bits &= 0xFE;
+
+	return bits;
+}
+
+static unsigned int read_index(unsigned char index)
+{
+	unsigned char *addr;
+	unsigned int value;
+	/*  addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */
+	addr = pci_addr_lin + ((index & 0xFF) << 2);
+	value = readl(addr);
+	return value;
+}
+
+static void write_index(unsigned char index, unsigned int reg_val)
+{
+	unsigned char *addr;
+	addr = pci_addr_lin + ((index & 0xFF) << 2);
+	writel(reg_val, addr);
+}
+
+MODULE_AUTHOR("Froenchenko Leonid");
+MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards");
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+EXPORT_NO_SYMBOLS;
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/longlong.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/longlong.h
@@ -0,0 +1,1333 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+   Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* You have to define the following before including this file:
+
+   UWtype -- An unsigned type, default type for operations (typically a "word")
+   UHWtype -- An unsigned type, at least half the size of UWtype.
+   UDWtype -- An unsigned type, at least twice as large a UWtype
+   W_TYPE_SIZE -- size in bits of UWtype
+
+   UQItype -- Unsigned 8 bit type.
+   SItype, USItype -- Signed and unsigned 32 bit types.
+   DItype, UDItype -- Signed and unsigned 64 bit types.
+
+   On a 32 bit machine UWtype should typically be USItype;
+   on a 64 bit machine, UWtype should typically be UDItype.
+*/
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#ifndef W_TYPE_SIZE
+#define W_TYPE_SIZE	32
+#define UWtype		USItype
+#define UHWtype		USItype
+#define UDWtype		UDItype
+#endif
+
+/* Define auxiliary asm macros.
+
+   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+   UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+   word product in HIGH_PROD and LOW_PROD.
+
+   2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+   UDWtype product.  This is just a variant of umul_ppmm.
+
+   3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator) divides a UDWtype, composed by the UWtype integers
+   HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+   in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
+   than DENOMINATOR for correct operation.  If, in addition, the most
+   significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+   UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+   4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator).  Like udiv_qrnnd but the numbers are signed.  The quotient
+   is rounded towards 0.
+
+   5) count_leading_zeros(count, x) counts the number of zero-bits from the
+   msb to the first nonzero bit in the UWtype X.  This is the number of
+   steps X needs to be shifted left to set the msb.  Undefined for X == 0,
+   unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+   6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+   from the least significant end.
+
+   7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+   high_addend_2, low_addend_2) adds two UWtype integers, composed by
+   HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+   respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+   (i.e. carry out) is not stored anywhere, and is lost.
+
+   8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+   high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+   composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+   LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+   and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
+   and is lost.
+
+   If any of these macros are left undefined for a particular CPU,
+   C macros are used.  */
+
+/* The CPUs come in alphabetical order below.
+
+   Please add support for more CPUs here, or improve the current support
+   for the CPUs below!
+   (E.g. WE32100, IBM360.)  */
+
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+   understood by gcc1.  Use cpp to avoid major code duplication.  */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+#if defined (__alpha) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    UDItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("umulh %r1,%2,%0"						\
+	     : "=r" ((UDItype) ph)					\
+	     : "%rJ" (__m0),						\
+	       "rI" (__m1));						\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define UMUL_TIME 46
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { UDItype __r;							\
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));				\
+    (r) = __r;								\
+  } while (0)
+extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
+#define UDIV_TIME 220
+#endif /* LONGLONG_STANDALONE */
+#ifdef __alpha_cix__
+#define count_leading_zeros(COUNT,X) \
+  __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
+#define count_trailing_zeros(COUNT,X) \
+  __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
+#define COUNT_LEADING_ZEROS_0 64
+#else
+extern const UQItype __clz_tab[];
+#define count_leading_zeros(COUNT,X) \
+  do {									\
+    UDItype __xr = (X), __t, __a;					\
+    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));		\
+    __a = __clz_tab[__t ^ 0xff] - 1;					\
+    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));	\
+    (COUNT) = 64 - (__clz_tab[__t] + __a*8);				\
+  } while (0)
+#define count_trailing_zeros(COUNT,X) \
+  do {									\
+    UDItype __xr = (X), __t, __a;					\
+    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));		\
+    __t = ~__t & -~__t;							\
+    __a = ((__t & 0xCC) != 0) * 2;					\
+    __a += ((__t & 0xF0) != 0) * 4;					\
+    __a += ((__t & 0xAA) != 0);						\
+    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));	\
+    __a <<= 3;								\
+    __t &= -__t;							\
+    __a += ((__t & 0xCC) != 0) * 2;					\
+    __a += ((__t & 0xF0) != 0) * 4;					\
+    __a += ((__t & 0xAA) != 0);						\
+    (COUNT) = __a;							\
+  } while (0)
+#endif /* __alpha_cix__ */
+#endif /* __alpha */
+
+#if defined (__arc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add.f	%1, %4, %5\n\tadc	%0, %2, %3"		\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%r" ((USItype) (ah)),					\
+	     "rIJ" ((USItype) (bh)),					\
+	     "%r" ((USItype) (al)),					\
+	     "rIJ" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub.f	%1, %4, %5\n\tsbc	%0, %2, %3"		\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "r" ((USItype) (ah)),					\
+	     "rIJ" ((USItype) (bh)),					\
+	     "r" ((USItype) (al)),					\
+	     "rIJ" ((USItype) (bl)))
+/* Call libgcc routine.  */
+#define umul_ppmm(w1, w0, u, v) \
+do {									\
+  DWunion __w;								\
+  __w.ll = __umulsidi3 (u, v);						\
+  w1 = __w.s.high;							\
+  w0 = __w.s.low;							\
+} while (0)
+#define __umulsidi3 __umulsidi3
+UDItype __umulsidi3 (USItype, USItype);
+#endif
+
+#if defined (__arm__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("adds	%1, %4, %5\n\tadc	%0, %2, %3"		\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%r" ((USItype) (ah)),					\
+	     "rI" ((USItype) (bh)),					\
+	     "%r" ((USItype) (al)),					\
+	     "rI" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subs	%1, %4, %5\n\tsbc	%0, %2, %3"		\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "r" ((USItype) (ah)),					\
+	     "rI" ((USItype) (bh)),					\
+	     "r" ((USItype) (al)),					\
+	     "rI" ((USItype) (bl)))
+#define umul_ppmm(xh, xl, a, b) \
+{register USItype __t0, __t1, __t2;					\
+  __asm__ ("%@ Inlined umul_ppmm\n"					\
+	   "	mov	%2, %5, lsr #16\n"				\
+	   "	mov	%0, %6, lsr #16\n"				\
+	   "	bic	%3, %5, %2, lsl #16\n"				\
+	   "	bic	%4, %6, %0, lsl #16\n"				\
+	   "	mul	%1, %3, %4\n"					\
+	   "	mul	%4, %2, %4\n"					\
+	   "	mul	%3, %0, %3\n"					\
+	   "	mul	%0, %2, %0\n"					\
+	   "	adds	%3, %4, %3\n"					\
+	   "	addcs	%0, %0, #65536\n"				\
+	   "	adds	%1, %1, %3, lsl #16\n"				\
+	   "	adc	%0, %0, %3, lsr #16"				\
+	   : "=&r" ((USItype) (xh)),					\
+	     "=r" ((USItype) (xl)),					\
+	     "=&r" (__t0), "=&r" (__t1), "=r" (__t2)			\
+	   : "r" ((USItype) (a)),					\
+	     "r" ((USItype) (b)));}
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0"				\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%rM" ((USItype) (ah)),					\
+	     "rM" ((USItype) (bh)),					\
+	     "%rM" ((USItype) (al)),					\
+	     "rM" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0"				\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "rM" ((USItype) (ah)),					\
+	     "rM" ((USItype) (bh)),					\
+	     "rM" ((USItype) (al)),					\
+	     "rM" ((USItype) (bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(w1, w0, u, v) \
+  do {									\
+    union								\
+      {									\
+	UDItype __f;							\
+	struct {USItype __w1, __w0;} __w1w0;				\
+      } __t;								\
+    __asm__ ("xmpyu %1,%2,%0"						\
+	     : "=x" (__t.__f)						\
+	     : "x" ((USItype) (u)),					\
+	       "x" ((USItype) (v)));					\
+    (w1) = __t.__w1w0.__w1;						\
+    (w0) = __t.__w1w0.__w0;						\
+     } while (0)
+#define UMUL_TIME 8
+#else
+#define UMUL_TIME 30
+#endif
+#define UDIV_TIME 40
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __tmp;							\
+    __asm__ (								\
+       "ldi		1,%0\n"						\
+"	extru,=		%1,15,16,%%r0		; Bits 31..16 zero?\n"	\
+"	extru,tr	%1,15,16,%1		; No.  Shift down, skip add.\n"\
+"	ldo		16(%0),%0		; Yes.  Perform add.\n"	\
+"	extru,=		%1,23,8,%%r0		; Bits 15..8 zero?\n"	\
+"	extru,tr	%1,23,8,%1		; No.  Shift down, skip add.\n"\
+"	ldo		8(%0),%0		; Yes.  Perform add.\n"	\
+"	extru,=		%1,27,4,%%r0		; Bits 7..4 zero?\n"	\
+"	extru,tr	%1,27,4,%1		; No.  Shift down, skip add.\n"\
+"	ldo		4(%0),%0		; Yes.  Perform add.\n"	\
+"	extru,=		%1,29,2,%%r0		; Bits 3..2 zero?\n"	\
+"	extru,tr	%1,29,2,%1		; No.  Shift down, skip add.\n"\
+"	ldo		2(%0),%0		; Yes.  Perform add.\n"	\
+"	extru		%1,30,1,%1		; Extract bit 1.\n"	\
+"	sub		%0,%1,%0		; Subtract it.\n"	\
+	: "=r" (count), "=r" (__tmp) : "1" (x));			\
+  } while (0)
+#endif
+
+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mr %0,%3"							\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (__m0),						\
+	       "r" (__m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define smul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("mr %0,%3"							\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (m0),						\
+	       "r" (m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __xx.__i.__h = n1; __xx.__i.__l = n0;				\
+    __asm__ ("dr %0,%2"							\
+	     : "=r" (__xx.__ll)						\
+	     : "0" (__xx.__ll), "r" (d));				\
+    (q) = __xx.__i.__l; (r) = __xx.__i.__h;				\
+  } while (0)
+#endif
+
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl %5,%1\n\tadcl %3,%0"					\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%0" ((USItype) (ah)),					\
+	     "g" ((USItype) (bh)),					\
+	     "%1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl %5,%1\n\tsbbl %3,%0"					\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "0" ((USItype) (ah)),					\
+	     "g" ((USItype) (bh)),					\
+	     "1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mull %3"							\
+	   : "=a" ((USItype) (w0)),					\
+	     "=d" ((USItype) (w1))					\
+	   : "%0" ((USItype) (u)),					\
+	     "rm" ((USItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, dv) \
+  __asm__ ("divl %4"							\
+	   : "=a" ((USItype) (q)),					\
+	     "=d" ((USItype) (r))					\
+	   : "0" ((USItype) (n0)),					\
+	     "1" ((USItype) (n1)),					\
+	     "rm" ((USItype) (dv)))
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __cbtmp;							\
+    __asm__ ("bsrl %1,%0"						\
+	     : "=r" (__cbtmp) : "rm" ((USItype) (x)));			\
+    (count) = __cbtmp ^ 31;						\
+  } while (0)
+#define count_trailing_zeros(count, x) \
+  __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
+#define UMUL_TIME 40
+#define UDIV_TIME 40
+#endif /* 80x86 */
+
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("emul	%2,%1,%0"					\
+	   : "=d" (__xx.__ll)						\
+	   : "%dI" ((USItype) (u)),					\
+	     "dI" ((USItype) (v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;							\
+    __asm__ ("emul	%2,%1,%0"					\
+	     : "=d" (__w)						\
+	     : "%dI" ((USItype) (u)),					\
+	       "dI" ((USItype) (v)));					\
+    __w; })
+#endif /* __i960__ */
+
+#if defined (__M32R__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  /* The cmp clears the condition bit.  */ \
+  __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0"			\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%0" ((USItype) (ah)),					\
+	     "r" ((USItype) (bh)),					\
+	     "%1" ((USItype) (al)),					\
+	     "r" ((USItype) (bl))					\
+	   : "cbit")
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  /* The cmp clears the condition bit.  */ \
+  __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0"			\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "0" ((USItype) (ah)),					\
+	     "r" ((USItype) (bh)),					\
+	     "1" ((USItype) (al)),					\
+	     "r" ((USItype) (bl))					\
+	   : "cbit")
+#endif /* __M32R__ */
+
+#if defined (__mc68000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0"				\
+	   : "=d" ((USItype) (sh)),					\
+	     "=&d" ((USItype) (sl))					\
+	   : "%0" ((USItype) (ah)),					\
+	     "d" ((USItype) (bh)),					\
+	     "%1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0"				\
+	   : "=d" ((USItype) (sh)),					\
+	     "=&d" ((USItype) (sl))					\
+	   : "0" ((USItype) (ah)),					\
+	     "d" ((USItype) (bh)),					\
+	     "1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+
+/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r.  */
+#if defined (__mc68020__) || defined(mc68020) \
+	|| defined(__mc68030__) || defined(mc68030) \
+	|| defined(__mc68040__) || defined(mc68040) \
+	|| defined(__mcpu32__) || defined(mcpu32)
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mulu%.l %3,%1:%0"						\
+	   : "=d" ((USItype) (w0)),					\
+	     "=d" ((USItype) (w1))					\
+	   : "%0" ((USItype) (u)),					\
+	     "dmi" ((USItype) (v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divu%.l %4,%1:%0"						\
+	   : "=d" ((USItype) (q)),					\
+	     "=d" ((USItype) (r))					\
+	   : "0" ((USItype) (n0)),					\
+	     "1" ((USItype) (n1)),					\
+	     "dmi" ((USItype) (d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divs%.l %4,%1:%0"						\
+	   : "=d" ((USItype) (q)),					\
+	     "=d" ((USItype) (r))					\
+	   : "0" ((USItype) (n0)),					\
+	     "1" ((USItype) (n1)),					\
+	     "dmi" ((USItype) (d)))
+
+#else /* not mc68020 */
+#if !defined(__mcf5200__)
+/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX.  */
+#define umul_ppmm(xh, xl, a, b) \
+  __asm__ ("| Inlined umul_ppmm\n"					\
+	   "	move%.l	%2,%/d0\n"					\
+	   "	move%.l	%3,%/d1\n"					\
+	   "	move%.l	%/d0,%/d2\n"					\
+	   "	swap	%/d0\n"						\
+	   "	move%.l	%/d1,%/d3\n"					\
+	   "	swap	%/d1\n"						\
+	   "	move%.w	%/d2,%/d4\n"					\
+	   "	mulu	%/d3,%/d4\n"					\
+	   "	mulu	%/d1,%/d2\n"					\
+	   "	mulu	%/d0,%/d3\n"					\
+	   "	mulu	%/d0,%/d1\n"					\
+	   "	move%.l	%/d4,%/d0\n"					\
+	   "	eor%.w	%/d0,%/d0\n"					\
+	   "	swap	%/d0\n"						\
+	   "	add%.l	%/d0,%/d2\n"					\
+	   "	add%.l	%/d3,%/d2\n"					\
+	   "	jcc	1f\n"						\
+	   "	add%.l	%#65536,%/d1\n"					\
+	   "1:	swap	%/d2\n"						\
+	   "	moveq	%#0,%/d0\n"					\
+	   "	move%.w	%/d2,%/d0\n"					\
+	   "	move%.w	%/d4,%/d2\n"					\
+	   "	move%.l	%/d2,%1\n"					\
+	   "	add%.l	%/d1,%/d0\n"					\
+	   "	move%.l	%/d0,%0"					\
+	   : "=g" ((USItype) (xh)),					\
+	     "=g" ((USItype) (xl))					\
+	   : "g" ((USItype) (a)),					\
+	     "g" ((USItype) (b))					\
+	   : "d0", "d1", "d2", "d3", "d4")
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#endif /* not mcf5200 */
+#endif /* not mc68020 */
+
+/* The '020, '030, '040 and '060 have bitfield insns.  */
+#if defined (__mc68020__) || defined(mc68020) \
+	|| defined(__mc68030__) || defined(mc68030) \
+	|| defined(__mc68040__) || defined(mc68040) \
+	|| defined(__mc68060__) || defined(mc68060)
+#define count_leading_zeros(count, x) \
+  __asm__ ("bfffo %1{%b2:%b2},%0"					\
+	   : "=d" ((USItype) (count))					\
+	   : "od" ((USItype) (x)), "n" (0))
+#endif
+#endif /* mc68000 */
+
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3"			\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%rJ" ((USItype) (ah)),					\
+	     "rJ" ((USItype) (bh)),					\
+	     "%rJ" ((USItype) (al)),					\
+	     "rJ" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3"			\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "rJ" ((USItype) (ah)),					\
+	     "rJ" ((USItype) (bh)),					\
+	     "rJ" ((USItype) (al)),					\
+	     "rJ" ((USItype) (bl)))
+#define count_leading_zeros(count, x) \
+  do {									\
+    USItype __cbtmp;							\
+    __asm__ ("ff1 %0,%1"						\
+	     : "=r" (__cbtmp)						\
+	     : "r" ((USItype) (x)));					\
+    (count) = __cbtmp ^ 31;						\
+  } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
+#if defined (__mc88110__)
+#define umul_ppmm(wh, wl, u, v) \
+  do {									\
+    union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+    __asm__ ("mulu.d	%0,%1,%2"					\
+	     : "=r" (__xx.__ll)						\
+	     : "r" ((USItype) (u)),					\
+	       "r" ((USItype) (v)));					\
+    (wh) = __xx.__i.__h;						\
+    (wl) = __xx.__i.__l;						\
+  } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __h, __l;} __i;				\
+	  } __xx;							\
+  USItype __q;								\
+  __xx.__i.__h = (n1); __xx.__i.__l = (n0);				\
+  __asm__ ("divu.d %0,%1,%2"						\
+	   : "=r" (__q)							\
+	   : "r" (__xx.__ll),						\
+	     "r" ((USItype) (d)));					\
+  (r) = (n0) - __q * (d); (q) = __q; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __mc88110__ */
+#endif /* __m88000__ */
+
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("multu %2,%3"						\
+	   : "=l" ((USItype) (w0)),					\
+	     "=h" ((USItype) (w1))					\
+	   : "d" ((USItype) (u)),					\
+	     "d" ((USItype) (v)))
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __asm__ ("meid %2,%0"							\
+	   : "=g" (__xx.__ll)						\
+	   : "%0" ((USItype) (u)),					\
+	     "g" ((USItype) (v)));					\
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;							\
+    __asm__ ("meid %2,%0"						\
+	     : "=g" (__w)						\
+	     : "%0" ((USItype) (u)),					\
+	       "g" ((USItype) (v)));					\
+    __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;						\
+	   struct {USItype __l, __h;} __i;				\
+	  } __xx;							\
+  __xx.__i.__h = (n1); __xx.__i.__l = (n0);				\
+  __asm__ ("deid %2,%0"							\
+	   : "=g" (__xx.__ll)						\
+	   : "0" (__xx.__ll),						\
+	     "g" ((USItype) (d)));					\
+  (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+  do {									\
+    __asm__ ("ffsd     %2,%0"						\
+            : "=r" ((USItype) (count))					\
+            : "0" ((USItype) 0),					\
+              "r" ((USItype) (x)));					\
+  } while (0)
+#endif /* __ns32000__ */
+
+/* FIXME: We should test _IBMR2 here when we add assembly support for the
+   system vendor compilers.
+   FIXME: What's needed for gcc PowerPC VxWorks?  __vxworks__ is not good
+   enough, since that hits ARM and m68k too.  */
+#if (defined (_ARCH_PPC)	/* AIX */				\
+     || defined (_ARCH_PWR)	/* AIX */				\
+     || defined (_ARCH_COM)	/* AIX */				\
+     || defined (__powerpc__)	/* gcc */				\
+     || defined (__POWERPC__)	/* BEOS */				\
+     || defined (__ppc__)	/* Darwin */				\
+     || defined (PPC)		/* GNU/Linux, SysV */			\
+     ) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (bh) && (bh) == 0)				\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"		\
+	     : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0)		\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"		\
+	     : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+    else								\
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"		\
+	     : "=r" (sh), "=&r" (sl)					\
+	     : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl));		\
+  } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (ah) && (ah) == 0)				\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"	\
+	       : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"	\
+	       : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == 0)			\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"		\
+	       : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"		\
+	       : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+    else								\
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"	\
+	       : "=r" (sh), "=&r" (sl)					\
+	       : "r" (ah), "r" (bh), "rI" (al), "r" (bl));		\
+  } while (0)
+#define count_leading_zeros(count, x) \
+  __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 32
+#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
+  || defined (__ppc__) || defined (PPC) || defined (__vxworks__)
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));	\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    SItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));	\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#elif defined (_ARCH_PWR)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+  __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+  __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
+#define UDIV_TIME 100
+#endif
+#endif /* 32-bit POWER architecture variants.  */
+
+/* We should test _IBMR2 here when we add assembly support for the system
+   vendor compilers.  */
+#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (bh) && (bh) == 0)				\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"		\
+	     : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0)		\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"		\
+	     : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+    else								\
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"		\
+	     : "=r" (sh), "=&r" (sl)					\
+	     : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl));		\
+  } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {									\
+    if (__builtin_constant_p (ah) && (ah) == 0)				\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"	\
+	       : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"	\
+	       : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == 0)			\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"		\
+	       : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+    else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"		\
+	       : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+    else								\
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"	\
+	       : "=r" (sh), "=&r" (sl)					\
+	       : "r" (ah), "r" (bh), "rI" (al), "r" (bl));		\
+  } while (0)
+#define count_leading_zeros(count, x) \
+  __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 64
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    UDItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));	\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    DItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));	\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+#define SMUL_TIME 14  /* ??? */
+#define UDIV_TIME 120 /* ??? */
+#endif /* 64-bit PowerPC.  */
+
+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("a %1,%5\n\tae %0,%3"					\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%0" ((USItype) (ah)),					\
+	     "r" ((USItype) (bh)),					\
+	     "%1" ((USItype) (al)),					\
+	     "r" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("s %1,%5\n\tse %0,%3"					\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "0" ((USItype) (ah)),					\
+	     "r" ((USItype) (bh)),					\
+	     "1" ((USItype) (al)),					\
+	     "r" ((USItype) (bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ (								\
+       "s	r2,r2\n"						\
+"	mts	r10,%2\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	m	r2,%3\n"						\
+"	cas	%0,r2,r0\n"						\
+"	mfs	r10,%1"							\
+	     : "=r" ((USItype) (ph)),					\
+	       "=r" ((USItype) (pl))					\
+	     : "%r" (__m0),						\
+		"r" (__m1)						\
+	     : "r2");							\
+    (ph) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+  do {									\
+    if ((x) >= 0x10000)							\
+      __asm__ ("clz	%0,%1"						\
+	       : "=r" ((USItype) (count))				\
+	       : "r" ((USItype) (x) >> 16));				\
+    else								\
+      {									\
+	__asm__ ("clz	%0,%1"						\
+		 : "=r" ((USItype) (count))				\
+		 : "r" ((USItype) (x)));					\
+	(count) += 16;							\
+      }									\
+  } while (0)
+#endif
+
+#if defined (__sh2__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ (								\
+       "dmulu.l	%2,%3\n\tsts	macl,%1\n\tsts	mach,%0"		\
+	   : "=r" ((USItype)(w1)),					\
+	     "=r" ((USItype)(w0))					\
+	   : "r" ((USItype)(u)),					\
+	     "r" ((USItype)(v))						\
+	   : "macl", "mach")
+#define UMUL_TIME 5
+#endif
+
+#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
+#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
+#define count_leading_zeros(count, x) \
+  do									\
+    {									\
+      UDItype x_ = (USItype)(x);					\
+      SItype c_;							\
+									\
+      __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_));			\
+      (count) = c_ - 31;						\
+    }									\
+  while (0)
+#define COUNT_LEADING_ZEROS_0 32
+#endif
+
+#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
+    && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0"				\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "%rJ" ((USItype) (ah)),					\
+	     "rI" ((USItype) (bh)),					\
+	     "%rJ" ((USItype) (al)),					\
+	     "rI" ((USItype) (bl))					\
+	   __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0"				\
+	   : "=r" ((USItype) (sh)),					\
+	     "=&r" ((USItype) (sl))					\
+	   : "rJ" ((USItype) (ah)),					\
+	     "rI" ((USItype) (bh)),					\
+	     "rJ" ((USItype) (al)),					\
+	     "rI" ((USItype) (bl))					\
+	   __CLOBBER_CC)
+#if defined (__sparc_v8__)
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"					\
+	   : "=r" ((USItype) (w1)),					\
+	     "=r" ((USItype) (w0))					\
+	   : "r" ((USItype) (u)),					\
+	     "r" ((USItype) (v)))
+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
+  __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
+	   : "=&r" ((USItype) (__q)),					\
+	     "=&r" ((USItype) (__r))					\
+	   : "r" ((USItype) (__n1)),					\
+	     "r" ((USItype) (__n0)),					\
+	     "r" ((USItype) (__d)))
+#else
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide.  It also has two additional
+   instructions scan (ffs from high bit) and divscc.  */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"					\
+	   : "=r" ((USItype) (w1)),					\
+	     "=r" ((USItype) (w0))					\
+	   : "r" ((USItype) (u)),					\
+	     "r" ((USItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("! Inlined udiv_qrnnd\n"					\
+"	wr	%%g0,%2,%%y	! Not a delayed write for sparclite\n"	\
+"	tst	%%g0\n"							\
+"	divscc	%3,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%%g1\n"						\
+"	divscc	%%g1,%4,%0\n"						\
+"	rd	%%y,%1\n"						\
+"	bl,a 1f\n"							\
+"	add	%1,%4,%1\n"						\
+"1:	! End of inline udiv_qrnnd"					\
+	   : "=r" ((USItype) (q)),					\
+	     "=r" ((USItype) (r))					\
+	   : "r" ((USItype) (n1)),					\
+	     "r" ((USItype) (n0)),					\
+	     "rI" ((USItype) (d))					\
+	   : "g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+  do {                                                                  \
+  __asm__ ("scan %1,1,%0"                                               \
+           : "=r" ((USItype) (count))                                   \
+           : "r" ((USItype) (x)));					\
+  } while (0)
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+   implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
+   undefined.  */
+#else
+/* SPARC without integer multiplication and divide instructions.
+   (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("! Inlined umul_ppmm\n"					\
+"	wr	%%g0,%2,%%y	! SPARC has 0-3 delay insn after a wr\n"\
+"	sra	%3,31,%%o5	! Don't move this insn\n"		\
+"	and	%2,%%o5,%%o5	! Don't move this insn\n"		\
+"	andcc	%%g0,0,%%g1	! Don't move this insn\n"		\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,%3,%%g1\n"						\
+"	mulscc	%%g1,0,%%g1\n"						\
+"	add	%%g1,%%o5,%0\n"						\
+"	rd	%%y,%1"							\
+	   : "=r" ((USItype) (w1)),					\
+	     "=r" ((USItype) (w0))					\
+	   : "%rI" ((USItype) (u)),					\
+	     "r" ((USItype) (v))						\
+	   : "g1", "o5" __AND_CLOBBER_CC)
+#define UMUL_TIME 39		/* 39 instructions */
+/* It's quite necessary to add this much assembler for the sparc.
+   The default udiv_qrnnd (in C) is more than 10 times slower!  */
+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
+  __asm__ ("! Inlined udiv_qrnnd\n"					\
+"	mov	32,%%g1\n"						\
+"	subcc	%1,%2,%%g0\n"						\
+"1:	bcs	5f\n"							\
+"	 addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb\n"	\
+"	sub	%1,%2,%1	! this kills msb of n\n"		\
+"	addx	%1,%1,%1	! so this can't give carry\n"		\
+"	subcc	%%g1,1,%%g1\n"						\
+"2:	bne	1b\n"							\
+"	 subcc	%1,%2,%%g0\n"						\
+"	bcs	3f\n"							\
+"	 addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb\n"	\
+"	b	3f\n"							\
+"	 sub	%1,%2,%1	! this kills msb of n\n"		\
+"4:	sub	%1,%2,%1\n"						\
+"5:	addxcc	%1,%1,%1\n"						\
+"	bcc	2b\n"							\
+"	 subcc	%%g1,1,%%g1\n"						\
+"! Got carry from n.  Subtract next step to cancel this carry.\n"	\
+"	bne	4b\n"							\
+"	 addcc	%0,%0,%0	! shift n1n0 and a 0-bit in lsb\n"	\
+"	sub	%1,%2,%1\n"						\
+"3:	xnor	%0,0,%0\n"						\
+"	! End of inline udiv_qrnnd"					\
+	   : "=&r" ((USItype) (__q)),					\
+	     "=&r" ((USItype) (__r))					\
+	   : "r" ((USItype) (__d)),					\
+	     "1" ((USItype) (__n1)),					\
+	     "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC)
+#define UDIV_TIME (3+7*32)	/* 7 instructions/iteration. 32 iterations.  */
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+#endif /* sparc32 */
+
+#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \
+    && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl)				\
+  __asm__ ("addcc %r4,%5,%1\n\t"					\
+   	   "add %r2,%3,%0\n\t"						\
+   	   "bcs,a,pn %%xcc, 1f\n\t"					\
+   	   "add %0, 1, %0\n"						\
+	   "1:"								\
+	   : "=r" ((UDItype)(sh)),				      	\
+	     "=&r" ((UDItype)(sl))				      	\
+	   : "%rJ" ((UDItype)(ah)),				     	\
+	     "rI" ((UDItype)(bh)),				      	\
+	     "%rJ" ((UDItype)(al)),				     	\
+	     "rI" ((UDItype)(bl))				       	\
+	   __CLOBBER_CC)
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) 				\
+  __asm__ ("subcc %r4,%5,%1\n\t"					\
+   	   "sub %r2,%3,%0\n\t"						\
+   	   "bcs,a,pn %%xcc, 1f\n\t"					\
+   	   "sub %0, 1, %0\n\t"						\
+	   "1:"								\
+	   : "=r" ((UDItype)(sh)),				      	\
+	     "=&r" ((UDItype)(sl))				      	\
+	   : "rJ" ((UDItype)(ah)),				     	\
+	     "rI" ((UDItype)(bh)),				      	\
+	     "rJ" ((UDItype)(al)),				     	\
+	     "rI" ((UDItype)(bl))				       	\
+	   __CLOBBER_CC)
+
+#define umul_ppmm(wh, wl, u, v)						\
+  do {									\
+	  UDItype tmp1, tmp2, tmp3, tmp4;				\
+	  __asm__ __volatile__ (					\
+		   "srl %7,0,%3\n\t"					\
+		   "mulx %3,%6,%1\n\t"					\
+		   "srlx %6,32,%2\n\t"					\
+		   "mulx %2,%3,%4\n\t"					\
+		   "sllx %4,32,%5\n\t"					\
+		   "srl %6,0,%3\n\t"					\
+		   "sub %1,%5,%5\n\t"					\
+		   "srlx %5,32,%5\n\t"					\
+		   "addcc %4,%5,%4\n\t"					\
+		   "srlx %7,32,%5\n\t"					\
+		   "mulx %3,%5,%3\n\t"					\
+		   "mulx %2,%5,%5\n\t"					\
+		   "sethi %%hi(0x80000000),%2\n\t"			\
+		   "addcc %4,%3,%4\n\t"					\
+		   "srlx %4,32,%4\n\t"					\
+		   "add %2,%2,%2\n\t"					\
+		   "movcc %%xcc,%%g0,%2\n\t"				\
+		   "addcc %5,%4,%5\n\t"					\
+		   "sllx %3,32,%3\n\t"					\
+		   "add %1,%3,%1\n\t"					\
+		   "add %5,%2,%0"					\
+	   : "=r" ((UDItype)(wh)),					\
+	     "=&r" ((UDItype)(wl)),					\
+	     "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4)	\
+	   : "r" ((UDItype)(u)),					\
+	     "r" ((UDItype)(v))						\
+	   __CLOBBER_CC);						\
+  } while (0)
+#define UMUL_TIME 96
+#define UDIV_TIME 230
+#endif /* sparc64 */
+
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl2 %5,%1\n\tadwc %3,%0"					\
+	   : "=g" ((USItype) (sh)),					\
+	     "=&g" ((USItype) (sl))					\
+	   : "%0" ((USItype) (ah)),					\
+	     "g" ((USItype) (bh)),					\
+	     "%1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl2 %5,%1\n\tsbwc %3,%0"					\
+	   : "=g" ((USItype) (sh)),					\
+	     "=&g" ((USItype) (sl))					\
+	   : "0" ((USItype) (ah)),					\
+	     "g" ((USItype) (bh)),					\
+	     "1" ((USItype) (al)),					\
+	     "g" ((USItype) (bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {								\
+	UDItype __ll;							\
+	struct {USItype __l, __h;} __i;					\
+      } __xx;								\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("emul %1,%2,$0,%0"						\
+	     : "=r" (__xx.__ll)						\
+	     : "g" (__m0),						\
+	       "g" (__m1));						\
+    (xh) = __xx.__i.__h;						\
+    (xl) = __xx.__i.__l;						\
+    (xh) += ((((SItype) __m0 >> 31) & __m1)				\
+	     + (((SItype) __m1 >> 31) & __m0));				\
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {									\
+    union {DItype __ll;							\
+	   struct {SItype __l, __h;} __i;				\
+	  } __xx;							\
+    __xx.__i.__h = n1; __xx.__i.__l = n0;				\
+    __asm__ ("ediv %3,%2,%0,%1"						\
+	     : "=g" (q), "=g" (r)					\
+	     : "g" (__xx.__ll), "g" (d));				\
+  } while (0)
+#endif /* __vax__ */
+
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add	%H1,%H5\n\tadc	%H0,%H3"				\
+	   : "=r" ((unsigned int)(sh)),					\
+	     "=&r" ((unsigned int)(sl))					\
+	   : "%0" ((unsigned int)(ah)),					\
+	     "r" ((unsigned int)(bh)),					\
+	     "%1" ((unsigned int)(al)),					\
+	     "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub	%H1,%H5\n\tsbc	%H0,%H3"				\
+	   : "=r" ((unsigned int)(sh)),					\
+	     "=&r" ((unsigned int)(sl))					\
+	   : "0" ((unsigned int)(ah)),					\
+	     "r" ((unsigned int)(bh)),					\
+	     "1" ((unsigned int)(al)),					\
+	     "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {									\
+    union {long int __ll;						\
+	   struct {unsigned int __h, __l;} __i;				\
+	  } __xx;							\
+    unsigned int __m0 = (m0), __m1 = (m1);				\
+    __asm__ ("mult	%S0,%H3"					\
+	     : "=r" (__xx.__i.__h),					\
+	       "=r" (__xx.__i.__l)					\
+	     : "%1" (__m0),						\
+	       "rQR" (__m1));						\
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;				\
+    (xh) += ((((signed int) __m0 >> 15) & __m1)				\
+	     + (((signed int) __m1 >> 15) & __m0));			\
+  } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+
+/* If this machine has no inline assembler, use C macros.  */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {									\
+    UWtype __x;								\
+    __x = (al) + (bl);							\
+    (sh) = (ah) + (bh) + (__x < (al));					\
+    (sl) = __x;								\
+  } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {									\
+    UWtype __x;								\
+    __x = (al) - (bl);							\
+    (sh) = (ah) - (bh) - (__x > (al));					\
+    (sl) = __x;								\
+  } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)						\
+  do {									\
+    UWtype __x0, __x1, __x2, __x3;					\
+    UHWtype __ul, __vl, __uh, __vh;					\
+									\
+    __ul = __ll_lowpart (u);						\
+    __uh = __ll_highpart (u);						\
+    __vl = __ll_lowpart (v);						\
+    __vh = __ll_highpart (v);						\
+									\
+    __x0 = (UWtype) __ul * __vl;					\
+    __x1 = (UWtype) __ul * __vh;					\
+    __x2 = (UWtype) __uh * __vl;					\
+    __x3 = (UWtype) __uh * __vh;					\
+									\
+    __x1 += __ll_highpart (__x0);/* this can't give carry */		\
+    __x1 += __x2;		/* but this indeed can */		\
+    if (__x1 < __x2)		/* did we get it? */			\
+      __x3 += __ll_B;		/* yes, add it in the proper pos.  */	\
+									\
+    (w1) = __x3 + __ll_highpart (__x1);					\
+    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
+  } while (0)
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+  ({DWunion __w;							\
+    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
+    __w.ll; })
+#endif
+
+/* Define this unconditionally, so it can be used for debugging.  */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+  do {									\
+    UWtype __d1, __d0, __q1, __q0;					\
+    UWtype __r1, __r0, __m;						\
+    __d1 = __ll_highpart (d);						\
+    __d0 = __ll_lowpart (d);						\
+									\
+    __r1 = (n1) % __d1;							\
+    __q1 = (n1) / __d1;							\
+    __m = (UWtype) __q1 * __d0;						\
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
+    if (__r1 < __m)							\
+      {									\
+	__q1--, __r1 += (d);						\
+	if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+	  if (__r1 < __m)						\
+	    __q1--, __r1 += (d);					\
+      }									\
+    __r1 -= __m;							\
+									\
+    __r0 = __r1 % __d1;							\
+    __q0 = __r1 / __d1;							\
+    __m = (UWtype) __q0 * __d0;						\
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
+    if (__r0 < __m)							\
+      {									\
+	__q0--, __r0 += (d);						\
+	if (__r0 >= (d))						\
+	  if (__r0 < __m)						\
+	    __q0--, __r0 += (d);					\
+      }									\
+    __r0 -= __m;							\
+									\
+    (q) = (UWtype) __q1 * __ll_B | __q0;				\
+    (r) = __r0;								\
+  } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+   __udiv_w_sdiv (defined in libgcc or elsewhere).  */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  do {									\
+    USItype __r;							\
+    (q) = __udiv_w_sdiv (&__r, nh, nl, d);				\
+    (r) = __r;								\
+  } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c.  */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#if !defined (count_leading_zeros)
+extern const UQItype __clz_tab[];
+#define count_leading_zeros(count, x) \
+  do {									\
+    UWtype __xr = (x);							\
+    UWtype __a;								\
+									\
+    if (W_TYPE_SIZE <= 32)						\
+      {									\
+	__a = __xr < ((UWtype)1<<2*__BITS4)				\
+	  ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4)			\
+	  : (__xr < ((UWtype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
+      }									\
+    else								\
+      {									\
+	for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8)			\
+	  if (((__xr >> __a) & 0xff) != 0)				\
+	    break;							\
+      }									\
+									\
+    (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);		\
+  } while (0)
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
+   defined in asm, but if it is not, the C version above is good enough.  */
+#define count_trailing_zeros(count, x) \
+  do {									\
+    UWtype __ctz_x = (x);						\
+    UWtype __ctz_c;							\
+    count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x);			\
+    (count) = W_TYPE_SIZE - 1 - __ctz_c;				\
+  } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/iw_ndis.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/iw_ndis.c
@@ -0,0 +1,1973 @@
+ /*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_arp.h>
+#include <linux/usb.h>
+#include <linux/random.h>
+
+#include <net/iw_handler.h>
+#include <linux/rtnetlink.h>
+#include <asm/uaccess.h>
+
+#include "iw_ndis.h"
+#include "wrapndis.h"
+
+static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+			   2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+
+static const char *network_names[] = {"IEEE 802.11FH", "IEEE 802.11b",
+				      "IEEE 802.11a", "IEEE 802.11g", "Auto"};
+
+int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len)
+{
+	NDIS_STATUS res;
+	struct ndis_essid req;
+
+	if (ssid_len > NDIS_ESSID_MAX_SIZE)
+		return -EINVAL;
+
+	memset(&req, 0, sizeof(req));
+	req.length = ssid_len;
+	if (ssid_len)
+		memcpy(&req.essid, ssid, ssid_len);
+
+	res = mp_set(wnd, OID_802_11_SSID, &req, sizeof(req));
+	if (res) {
+		WARNING("setting essid failed (%08X)", res);
+		EXIT2(return -EINVAL);
+	}
+	memcpy(&wnd->essid, &req, sizeof(req));
+	EXIT2(return 0);
+}
+
+static int set_assoc_params(struct ndis_device *wnd)
+{
+	TRACE2("wpa_version=0x%x auth_alg=0x%x key_mgmt=0x%x "
+	       "cipher_pairwise=0x%x cipher_group=0x%x",
+	       wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg,
+	       wnd->iw_auth_key_mgmt, wnd->iw_auth_cipher_pairwise,
+	       wnd->iw_auth_cipher_group);
+	set_auth_mode(wnd);
+	set_priv_filter(wnd);
+	set_encr_mode(wnd);
+	return 0;
+}
+
+static int iw_set_essid(struct net_device *dev, struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	char ssid[NDIS_ESSID_MAX_SIZE];
+	int length;
+
+	ENTER2("");
+	memset(ssid, 0, sizeof(ssid));
+	/* there is no way to turn off essid other than to set to
+	 * random bytes; instead, we use off to mean any */
+	if (wrqu->essid.flags) {
+		/* wireless-tools prior to version 20 add extra 1, and
+		 * later than 20 don't! Deal with that mess */
+		length = wrqu->essid.length - 1;
+		if (length > 0)
+			length--;
+		while (length < wrqu->essid.length && extra[length])
+			length++;
+		TRACE2("%d", length);
+		if (length <= 0 || length > NDIS_ESSID_MAX_SIZE)
+			EXIT2(return -EINVAL);
+	} else
+		length = 0;
+
+	set_assoc_params(wnd);
+
+	memcpy(ssid, extra, length);
+	if (set_essid(wnd, ssid, length))
+		EXIT2(return -EINVAL);
+
+	EXIT2(return 0);
+}
+
+static int iw_get_essid(struct net_device *dev, struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	struct ndis_essid req;
+
+	ENTER2("");
+	memset(&req, 0, sizeof(req));
+	res = mp_query(wnd, OID_802_11_SSID, &req, sizeof(req));
+	if (res) {
+		WARNING("getting essid failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	}
+	memcpy(extra, req.essid, req.length);
+	if (req.length > 0)
+		wrqu->essid.flags  = 1;
+	else
+		wrqu->essid.flags = 0;
+	wrqu->essid.length = req.length;
+	EXIT2(return 0);
+}
+
+int set_infra_mode(struct ndis_device *wnd,
+		   enum ndis_infrastructure_mode mode)
+{
+	NDIS_STATUS res;
+	unsigned int i;
+
+	ENTER2("%d", mode);
+	res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE,
+			   &wnd->infrastructure_mode);
+	if (res != NDIS_STATUS_SUCCESS) {
+		WARNING("getting operating mode to failed (%08X)", res);
+		EXIT2(return -EINVAL);
+	}
+	if (wnd->infrastructure_mode == mode)
+		EXIT2(return 0);
+	res = mp_set_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, mode);
+	if (res) {
+		WARNING("setting operating mode to %d failed (%08X)",
+			mode, res);
+		EXIT2(return -EINVAL);
+	}
+	/* NDIS drivers clear keys when infrastructure mode is
+	 * changed. But Linux tools assume otherwise. So set the
+	 * keys */
+	if (wnd->iw_auth_key_mgmt == 0 ||
+	    wnd->iw_auth_key_mgmt == IW_AUTH_KEY_MGMT_802_1X) {
+		for (i = 0; i < MAX_ENCR_KEYS; i++) {
+			if (wnd->encr_info.keys[i].length > 0)
+				add_wep_key(wnd, wnd->encr_info.keys[i].key,
+					    wnd->encr_info.keys[i].length, i);
+		}
+	}
+	wnd->infrastructure_mode = mode;
+	EXIT2(return 0);
+}
+
+static int iw_set_infra_mode(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	enum ndis_infrastructure_mode ndis_mode;
+
+	ENTER2("%d", wrqu->mode);
+	switch (wrqu->mode) {
+	case IW_MODE_ADHOC:
+		ndis_mode = Ndis802_11IBSS;
+		break;
+	case IW_MODE_INFRA:
+		ndis_mode = Ndis802_11Infrastructure;
+		break;
+	case IW_MODE_AUTO:
+		ndis_mode = Ndis802_11AutoUnknown;
+		break;
+	default:
+		EXIT2(return -EINVAL);
+	}
+
+	if (set_infra_mode(wnd, ndis_mode))
+		EXIT2(return -EINVAL);
+
+	EXIT2(return 0);
+}
+
+static int iw_get_infra_mode(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	int ndis_mode, iw_mode;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &ndis_mode);
+	if (res) {
+		WARNING("getting operating mode failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	}
+
+	switch(ndis_mode) {
+	case Ndis802_11IBSS:
+		iw_mode = IW_MODE_ADHOC;
+		break;
+	case Ndis802_11Infrastructure:
+		iw_mode = IW_MODE_INFRA;
+		break;
+	case Ndis802_11AutoUnknown:
+		iw_mode = IW_MODE_AUTO;
+		break;
+	default:
+		ERROR("invalid operating mode (%u)", ndis_mode);
+		EXIT2(return -EINVAL);
+	}
+	wrqu->mode = iw_mode;
+	EXIT2(return 0);
+}
+
+static const char *network_type_to_name(int net_type)
+{
+	if (net_type >= 0 &&
+	    net_type < (sizeof(network_names)/sizeof(network_names[0])))
+		return network_names[net_type];
+	else
+		return network_names[sizeof(network_names) /
+				     sizeof(network_names[0]) - 1];
+}
+
+static int iw_get_network_type(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	unsigned int network_type;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE,
+			   &network_type);
+	if (res) {
+		WARNING("getting network type failed: %08X", res);
+		network_type = -1;
+	}
+	strncpy(wrqu->name, network_type_to_name(network_type),
+	        sizeof(wrqu->name) - 1);
+	wrqu->name[sizeof(wrqu->name)-1] = 0;
+	return 0;
+}
+
+static int iw_get_freq(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	struct ndis_configuration req;
+
+	ENTER2("");
+	memset(&req, 0, sizeof(req));
+	res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
+	if (res) {
+		WARNING("getting configuration failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	}
+
+	memset(&(wrqu->freq), 0, sizeof(struct iw_freq));
+
+	/* see comment in wireless.h above the "struct iw_freq"
+	   definition for an explanation of this if
+	   NOTE: 1000000 is due to the kHz
+	*/
+	if (req.ds_config > 1000000) {
+		wrqu->freq.m = req.ds_config / 10;
+		wrqu->freq.e = 1;
+	}
+	else
+		wrqu->freq.m = req.ds_config;
+
+	/* convert from kHz to Hz */
+	wrqu->freq.e += 3;
+
+	return 0;
+}
+
+static int iw_set_freq(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	struct ndis_configuration req;
+
+	ENTER2("");
+	/* this OID is valid only when not associated */
+	if (netif_carrier_ok(wnd->net_dev))
+		EXIT2(return 0);
+	memset(&req, 0, sizeof(req));
+	res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
+	if (res) {
+		WARNING("getting configuration failed (%08X)", res);
+		EXIT2(return 0);
+	}
+
+	if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) {
+		if (wrqu->freq.m >= 1 &&
+		    wrqu->freq.m <= (sizeof(freq_chan) / sizeof(freq_chan[0])))
+			req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000;
+		else
+			return -EINVAL;
+	} else {
+		int i;
+		req.ds_config = wrqu->freq.m;
+		for (i = wrqu->freq.e; i > 0; i--)
+			req.ds_config *= 10;
+		req.ds_config /= 1000;
+	}
+	res = mp_set(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req));
+	if (res)
+		WARNING("setting configuration failed (%08X)", res);
+	return 0;
+}
+
+static int iw_get_tx_power(struct net_device *dev, struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_tx_power_level ndis_power;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
+		       &ndis_power, sizeof(ndis_power));
+	if (res)
+		return -EOPNOTSUPP;
+	wrqu->txpower.flags = IW_TXPOW_MWATT;
+	wrqu->txpower.disabled = 0;
+	wrqu->txpower.fixed = 0;
+	wrqu->txpower.value = ndis_power;
+	return 0;
+}
+
+static int iw_set_tx_power(struct net_device *dev, struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_tx_power_level ndis_power;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	if (wrqu->txpower.disabled)
+		ndis_power = 0;
+	else {
+		if (wrqu->txpower.flags == IW_TXPOW_MWATT)
+			ndis_power = wrqu->txpower.value;
+		else { // wrqu->txpower.flags == IW_TXPOW_DBM
+			if (wrqu->txpower.value > 20)
+				ndis_power = 128;
+			else if (wrqu->txpower.value < -43)
+				ndis_power = 127;
+			else {
+				signed char tmp;
+				tmp = wrqu->txpower.value;
+				tmp = -12 - tmp;
+				tmp <<= 2;
+				ndis_power = (unsigned char)tmp;
+			}
+		}
+	}
+	TRACE2("%d", ndis_power);
+	res = mp_set(wnd, OID_802_11_TX_POWER_LEVEL,
+		     &ndis_power, sizeof(ndis_power));
+	if (res)
+		EXIT2(return -EOPNOTSUPP);
+	if (ndis_power == 0)
+		res = disassociate(wnd, 0);
+	EXIT2(return 0);
+}
+
+static int iw_get_bitrate(struct net_device *dev, struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ULONG ndis_rate;
+	int res;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_GEN_LINK_SPEED, &ndis_rate, sizeof(ndis_rate));
+	if (res) {
+		WARNING("getting bitrate failed (%08X)", res);
+		ndis_rate = 0;
+	}
+
+	wrqu->bitrate.value = ndis_rate * 100;
+	return 0;
+}
+
+static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	int i, n;
+	NDIS_STATUS res;
+	ndis_rates_ex rates;
+
+	ENTER2("");
+	if (wrqu->bitrate.fixed == 0)
+		EXIT2(return 0);
+
+	res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates,
+			    sizeof(rates), &n, NULL);
+	if (res) {
+		WARNING("getting bit rate failed (%08X)", res);
+		EXIT2(return 0);
+	}
+	for (i = 0; i < n; i++) {
+		if (rates[i] & 0x80)
+			continue;
+		if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) {
+			TRACE2("setting rate %d to 0",
+			       (rates[i] & 0x7f) * 500000);
+			rates[i] = 0;
+		}
+	}
+
+	res = mp_set(wnd, OID_802_11_DESIRED_RATES, &rates, n);
+	if (res) {
+		WARNING("setting bit rate failed (%08X)", res);
+		EXIT2(return 0);
+	}
+
+	return 0;
+}
+
+static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	/* Do nothing. Used for ioctls that are not implemented. */
+	return 0;
+}
+
+static int iw_get_rts_threshold(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_rts_threshold threshold;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_802_11_RTS_THRESHOLD,
+		       &threshold, sizeof(threshold));
+	if (res)
+		return -EOPNOTSUPP;
+
+	wrqu->rts.value = threshold;
+	return 0;
+}
+
+static int iw_set_rts_threshold(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_rts_threshold threshold;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	threshold = wrqu->rts.value;
+	res = mp_set(wnd, OID_802_11_RTS_THRESHOLD,
+		     &threshold, sizeof(threshold));
+	if (res == NDIS_STATUS_INVALID_DATA)
+		return -EINVAL;
+	if (res)
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+
+static int iw_get_frag_threshold(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_fragmentation_threshold frag_threshold;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
+		       &frag_threshold, sizeof(frag_threshold));
+	if (res)
+		return -ENOTSUPP;
+
+	wrqu->frag.value = frag_threshold;
+	return 0;
+}
+
+static int iw_set_frag_threshold(struct net_device *dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	ndis_rts_threshold threshold;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	threshold = wrqu->frag.value;
+	res = mp_set(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
+		     &threshold, sizeof(threshold));
+	if (res == NDIS_STATUS_INVALID_DATA)
+		return -EINVAL;
+	if (res)
+		return -EOPNOTSUPP;
+	return 0;
+}
+
+int get_ap_address(struct ndis_device *wnd, mac_address ap_addr)
+{
+	NDIS_STATUS res;
+
+	res = mp_query(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN);
+	TRACE2(MACSTRSEP, MAC2STR(ap_addr));
+	if (res) {
+		TRACE2("res: %08X", res);
+		memset(ap_addr, 0x0, ETH_ALEN);
+		EXIT2(return -EOPNOTSUPP);
+	}
+	EXIT2(return 0);
+}
+
+static int iw_get_ap_address(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	mac_address ap_addr;
+
+	ENTER2("");
+	get_ap_address(wnd, ap_addr);
+	memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN);
+	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+	EXIT2(return 0);
+}
+
+static int iw_set_ap_address(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	mac_address ap_addr;
+
+	ENTER2("");
+	memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN);
+	TRACE2(MACSTRSEP, MAC2STR(ap_addr));
+	res = mp_set(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN);
+	/* user apps may set ap's mac address, which is not required;
+	 * they may fail to work if this function fails, so return
+	 * success */
+	if (res)
+		WARNING("setting AP mac address failed (%08X)", res);
+
+	EXIT2(return 0);
+}
+
+int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version,
+		     int auth_80211_alg)
+{
+	NDIS_STATUS res;
+	ULONG auth_mode;
+
+	ENTER2("%d, %d", wpa_version, auth_80211_alg);
+	if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
+		if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X)
+			auth_mode = Ndis802_11AuthModeWPA2;
+		else
+			auth_mode = Ndis802_11AuthModeWPA2PSK;
+	} else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
+		if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X)
+			auth_mode = Ndis802_11AuthModeWPA;
+		else if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_PSK)
+			auth_mode = Ndis802_11AuthModeWPAPSK;
+		else
+			auth_mode = Ndis802_11AuthModeWPANone;
+	} else if (auth_80211_alg & IW_AUTH_ALG_SHARED_KEY) {
+		if (auth_80211_alg & IW_AUTH_ALG_OPEN_SYSTEM)
+			auth_mode = Ndis802_11AuthModeAutoSwitch;
+		else
+			auth_mode = Ndis802_11AuthModeShared;
+	} else
+		auth_mode = Ndis802_11AuthModeOpen;
+
+	res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode);
+	if (res) {
+		WARNING("setting auth mode to %u failed (%08X)",
+			auth_mode, res);
+		if (res == NDIS_STATUS_INVALID_DATA)
+			EXIT2(return -EINVAL);
+		return -EOPNOTSUPP;
+	}
+	wnd->iw_auth_wpa_version = wpa_version;
+	wnd->iw_auth_80211_alg = auth_80211_alg;
+	EXIT2(return 0);
+}
+
+int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode)
+{
+	NDIS_STATUS res;
+
+	ENTER2("%d", auth_mode);
+	res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode);
+	if (res) {
+		WARNING("setting auth mode to %u failed (%08X)",
+			auth_mode, res);
+		if (res == NDIS_STATUS_INVALID_DATA)
+			EXIT2(return -EINVAL);
+		return -EOPNOTSUPP;
+	}
+	switch (auth_mode) {
+	case Ndis802_11AuthModeWPA:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA;
+		wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
+		break;
+	case Ndis802_11AuthModeWPAPSK:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA;
+		wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
+	case Ndis802_11AuthModeWPANone:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
+		wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
+		break;
+	case Ndis802_11AuthModeWPA2:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2;
+		wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X;
+		break;
+	case Ndis802_11AuthModeWPA2PSK:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2;
+		wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK;
+		break;
+	case Ndis802_11AuthModeOpen:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
+		wnd->iw_auth_80211_alg = IW_AUTH_ALG_OPEN_SYSTEM;
+		break;
+	case Ndis802_11AuthModeShared:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
+		wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY;
+		break;
+	case Ndis802_11AuthModeAutoSwitch:
+		wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED;
+		wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY;
+		wnd->iw_auth_80211_alg |= IW_AUTH_ALG_OPEN_SYSTEM;
+		break;
+	default:
+		WARNING("invalid authentication algorithm: %d", auth_mode);
+		break;
+	}
+	EXIT2(return 0);
+}
+
+int set_auth_mode(struct ndis_device *wnd)
+{
+	return set_iw_auth_mode(wnd, wnd->iw_auth_wpa_version,
+				wnd->iw_auth_80211_alg);
+}
+
+int get_ndis_auth_mode(struct ndis_device *wnd)
+{
+	ULONG mode;
+	NDIS_STATUS res;
+
+	res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &mode);
+	if (res) {
+		WARNING("getting authentication mode failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	}
+	TRACE2("%d", mode);
+	return mode;
+}
+
+int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise,
+		     int cipher_groupwise)
+{
+	NDIS_STATUS res;
+	ULONG ndis_mode;
+
+	ENTER2("%d, %d", cipher_pairwise, cipher_groupwise);
+	if (cipher_pairwise & IW_AUTH_CIPHER_CCMP)
+		ndis_mode = Ndis802_11Encryption3Enabled;
+	else if (cipher_pairwise & IW_AUTH_CIPHER_TKIP)
+		ndis_mode = Ndis802_11Encryption2Enabled;
+	else if (cipher_pairwise &
+		 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
+		ndis_mode = Ndis802_11Encryption1Enabled;
+	else if (cipher_groupwise & IW_AUTH_CIPHER_CCMP)
+		ndis_mode = Ndis802_11Encryption3Enabled;
+	else if (cipher_groupwise & IW_AUTH_CIPHER_TKIP)
+		ndis_mode = Ndis802_11Encryption2Enabled;
+	else
+		ndis_mode = Ndis802_11EncryptionDisabled;
+
+	res = mp_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, ndis_mode);
+	if (res) {
+		WARNING("setting encryption mode to %u failed (%08X)",
+			ndis_mode, res);
+		if (res == NDIS_STATUS_INVALID_DATA)
+			EXIT2(return -EINVAL);
+		return -EOPNOTSUPP;
+	}
+	wnd->iw_auth_cipher_pairwise = cipher_pairwise;
+	wnd->iw_auth_cipher_group = cipher_groupwise;
+	EXIT2(return 0);
+}
+
+int set_encr_mode(struct ndis_device *wnd)
+{
+	return set_iw_encr_mode(wnd, wnd->iw_auth_cipher_pairwise,
+				wnd->iw_auth_cipher_group);
+}
+
+int get_ndis_encr_mode(struct ndis_device *wnd)
+{
+	ULONG mode;
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &mode);
+	if (res) {
+		WARNING("getting encryption status failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	} else
+		EXIT2(return mode);
+}
+
+static int iw_get_encr(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	int index, mode;
+	struct encr_info *encr_info = &wnd->encr_info;
+
+	ENTER2("wnd = %p", wnd);
+	wrqu->data.length = 0;
+	extra[0] = 0;
+
+	index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
+	TRACE2("index = %u", index);
+	if (index > 0)
+		index--;
+	else
+		index = encr_info->tx_key_index;
+
+	if (index < 0 || index >= MAX_ENCR_KEYS) {
+		WARNING("encryption index out of range (%u)", index);
+		EXIT2(return -EINVAL);
+	}
+
+	if (index != encr_info->tx_key_index) {
+		if (encr_info->keys[index].length > 0) {
+			wrqu->data.flags |= IW_ENCODE_ENABLED;
+			wrqu->data.length = encr_info->keys[index].length;
+			memcpy(extra, encr_info->keys[index].key,
+			       encr_info->keys[index].length);
+		}
+		else
+			wrqu->data.flags |= IW_ENCODE_DISABLED;
+
+		EXIT2(return 0);
+	}
+
+	/* transmit key */
+	mode = get_ndis_encr_mode(wnd);
+	if (mode < 0)
+		EXIT2(return -EOPNOTSUPP);
+
+	if (mode == Ndis802_11EncryptionDisabled ||
+	    mode == Ndis802_11EncryptionNotSupported)
+		wrqu->data.flags |= IW_ENCODE_DISABLED;
+	else {
+		if (mode == Ndis802_11Encryption1KeyAbsent ||
+		    mode == Ndis802_11Encryption2KeyAbsent ||
+		    mode == Ndis802_11Encryption3KeyAbsent)
+			wrqu->data.flags |= IW_ENCODE_NOKEY;
+		else {
+			wrqu->data.flags |= IW_ENCODE_ENABLED;
+			wrqu->encoding.flags |= index+1;
+			wrqu->data.length = encr_info->keys[index].length;
+			memcpy(extra, encr_info->keys[index].key,
+			       encr_info->keys[index].length);
+		}
+	}
+	mode = get_ndis_auth_mode(wnd);
+	if (mode < 0)
+		EXIT2(return -EOPNOTSUPP);
+
+	if (mode == Ndis802_11AuthModeOpen)
+		wrqu->data.flags |= IW_ENCODE_OPEN;
+	else if (mode == Ndis802_11AuthModeAutoSwitch)
+		wrqu->data.flags |= IW_ENCODE_RESTRICTED;
+	else // Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA etc.
+		wrqu->data.flags |= IW_ENCODE_RESTRICTED;
+
+	EXIT2(return 0);
+}
+
+/* index must be 0 - N, as per NDIS  */
+int add_wep_key(struct ndis_device *wnd, char *key, int key_len,
+		int index)
+{
+	struct ndis_encr_key ndis_key;
+	NDIS_STATUS res;
+
+	ENTER2("key index: %d, length: %d", index, key_len);
+	if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) {
+		WARNING("invalid key length (%d)", key_len);
+		EXIT2(return -EINVAL);
+	}
+	if (index < 0 || index >= MAX_ENCR_KEYS) {
+		WARNING("invalid key index (%d)", index);
+		EXIT2(return -EINVAL);
+	}
+	ndis_key.struct_size = sizeof(ndis_key);
+	ndis_key.length = key_len;
+	memcpy(&ndis_key.key, key, key_len);
+	ndis_key.index = index;
+
+	if (index == wnd->encr_info.tx_key_index) {
+		ndis_key.index |= (1 << 31);
+		res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
+				       IW_AUTH_CIPHER_NONE);
+		if (res)
+			WARNING("encryption couldn't be enabled (%08X)", res);
+	}
+	TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key));
+	res = mp_set(wnd, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key));
+	if (res) {
+		WARNING("adding encryption key %d failed (%08X)",
+			index+1, res);
+		EXIT2(return -EINVAL);
+	}
+
+	/* Atheros driver messes up ndis_key during ADD_WEP, so
+	 * don't rely on that; instead use info in key and key_len */
+	wnd->encr_info.keys[index].length = key_len;
+	memcpy(&wnd->encr_info.keys[index].key, key, key_len);
+
+	EXIT2(return 0);
+}
+
+/* remove_key is for both wep and wpa */
+static int remove_key(struct ndis_device *wnd, int index,
+		      mac_address bssid)
+{
+	NDIS_STATUS res;
+	if (wnd->encr_info.keys[index].length == 0)
+		EXIT2(return 0);
+	wnd->encr_info.keys[index].length = 0;
+	memset(&wnd->encr_info.keys[index].key, 0,
+	       sizeof(wnd->encr_info.keys[index].length));
+	if (wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_TKIP ||
+	    wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_CCMP ||
+	    wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_TKIP ||
+	    wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_CCMP) {
+		struct ndis_remove_key remove_key;
+		remove_key.struct_size = sizeof(remove_key);
+		remove_key.index = index;
+		if (bssid) {
+			/* pairwise key */
+			if (memcmp(bssid, "\xff\xff\xff\xff\xff\xff",
+				   ETH_ALEN) != 0)
+				remove_key.index |= (1 << 30);
+			memcpy(remove_key.bssid, bssid,
+			       sizeof(remove_key.bssid));
+		} else
+			memset(remove_key.bssid, 0xff,
+			       sizeof(remove_key.bssid));
+		if (mp_set(wnd, OID_802_11_REMOVE_KEY,
+			   &remove_key, sizeof(remove_key)))
+			EXIT2(return -EINVAL);
+	} else {
+		ndis_key_index keyindex = index;
+		res = mp_set_int(wnd, OID_802_11_REMOVE_WEP, keyindex);
+		if (res) {
+			WARNING("removing encryption key %d failed (%08X)",
+				keyindex, res);
+			EXIT2(return -EINVAL);
+		}
+	}
+	/* if it is transmit key, disable encryption */
+	if (index == wnd->encr_info.tx_key_index) {
+		res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE,
+				       IW_AUTH_CIPHER_NONE);
+		if (res)
+			WARNING("changing encr status failed (%08X)", res);
+	}
+	TRACE2("key %d removed", index);
+	EXIT2(return 0);
+}
+
+static int iw_set_wep(struct net_device *dev, struct iw_request_info *info,
+		      union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	unsigned int index, key_len;
+	struct encr_info *encr_info = &wnd->encr_info;
+	unsigned char *key;
+
+	ENTER2("");
+	index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
+	TRACE2("index = %u", index);
+
+	/* iwconfig gives index as 1 - N */
+	if (index > 0)
+		index--;
+	else
+		index = encr_info->tx_key_index;
+
+	if (index < 0 || index >= MAX_ENCR_KEYS) {
+		WARNING("encryption index out of range (%u)", index);
+		EXIT2(return -EINVAL);
+	}
+
+	/* remove key if disabled */
+	if (wrqu->data.flags & IW_ENCODE_DISABLED) {
+		if (remove_key(wnd, index, NULL))
+			EXIT2(return -EINVAL);
+		else
+			EXIT2(return 0);
+	}
+
+	/* global encryption state (for all keys) */
+	if (wrqu->data.flags & IW_ENCODE_OPEN)
+		res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen);
+	else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED)
+		res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeShared);
+	if (res) {
+		WARNING("setting authentication mode failed (%08X)", res);
+		EXIT2(return -EINVAL);
+	}
+
+	TRACE2("key length: %d", wrqu->data.length);
+
+	if (wrqu->data.length > 0) {
+		key_len = wrqu->data.length;
+		key = extra;
+	} else { // must be set as tx key
+		if (encr_info->keys[index].length == 0) {
+			WARNING("key %d is not set", index+1);
+			EXIT2(return -EINVAL);
+		}
+		key_len = encr_info->keys[index].length;
+		key = encr_info->keys[index].key;
+		encr_info->tx_key_index = index;
+	}
+
+	if (add_wep_key(wnd, key, key_len, index))
+		EXIT2(return -EINVAL);
+
+	if (index == encr_info->tx_key_index) {
+		/* if transmit key is at index other than 0, some
+		 * drivers, at least Atheros and TI, want another
+		 * (global) non-transmit key to be set; don't know why */
+		if (index != 0) {
+			int i;
+			for (i = 0; i < MAX_ENCR_KEYS; i++)
+				if (i != index &&
+				    encr_info->keys[i].length != 0)
+					break;
+			if (i == MAX_ENCR_KEYS) {
+				if (index == 0)
+					i = index + 1;
+				else
+					i = index - 1;
+				if (add_wep_key(wnd, key, key_len, i))
+					WARNING("couldn't add broadcast key"
+						" at %d", i);
+			}
+		}
+		/* ndis drivers want essid to be set after setting encr */
+		set_essid(wnd, wnd->essid.essid, wnd->essid.length);
+	}
+	EXIT2(return 0);
+}
+
+static int iw_set_nick(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	if (wrqu->data.length >= IW_ESSID_MAX_SIZE || wrqu->data.length <= 0)
+		return -EINVAL;
+	memcpy(wnd->nick, extra, wrqu->data.length);
+	wnd->nick[wrqu->data.length] = 0;
+	return 0;
+}
+
+static int iw_get_nick(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	wrqu->data.length = strlen(wnd->nick);
+	memcpy(extra, wnd->nick, wrqu->data.length);
+	return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) && !defined(IW_REQUEST_FLAG_COMPAT)
+#define	iwe_stream_add_event(a, b, c, d, e)	iwe_stream_add_event(b, c, d, e)
+#define	iwe_stream_add_point(a, b, c, d, e)	iwe_stream_add_point(b, c, d, e)
+#define	iwe_stream_add_value(a, b, c, d, e, f)	\
+	iwe_stream_add_value(b, c, d, e, f)
+#define	iwe_stream_lcp_len(a)			IW_EV_LCP_LEN
+#endif
+
+static char *ndis_translate_scan(struct net_device *dev,
+				 struct iw_request_info *info, char *event,
+				 char *end_buf, void *item)
+{
+	struct iw_event iwe;
+	char *current_val;
+	int i, nrates;
+	unsigned char buf[MAX_WPA_IE_LEN * 2 + 30];
+	struct ndis_wlan_bssid *bssid;
+	struct ndis_wlan_bssid_ex *bssid_ex;
+
+	ENTER2("%p, %p", event, item);
+	bssid = item;
+	bssid_ex = item;
+	/* add mac address */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWAP;
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	iwe.len = IW_EV_ADDR_LEN;
+	memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
+	event = iwe_stream_add_event(info, event, end_buf, &iwe,
+				     IW_EV_ADDR_LEN);
+
+	/* add essid */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWESSID;
+	iwe.u.data.length = bssid->ssid.length;
+	if (iwe.u.data.length > IW_ESSID_MAX_SIZE)
+		iwe.u.data.length = IW_ESSID_MAX_SIZE;
+	iwe.u.data.flags = 1;
+	iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+	event = iwe_stream_add_point(info, event, end_buf, &iwe,
+				     bssid->ssid.essid);
+
+	/* add protocol name */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWNAME;
+	strncpy(iwe.u.name, network_type_to_name(bssid->net_type), IFNAMSIZ);
+	event = iwe_stream_add_event(info, event, end_buf, &iwe,
+				     IW_EV_CHAR_LEN);
+
+	/* add mode */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWMODE;
+	if (bssid->mode == Ndis802_11IBSS)
+		iwe.u.mode = IW_MODE_ADHOC;
+	else if (bssid->mode == Ndis802_11Infrastructure)
+		iwe.u.mode = IW_MODE_INFRA;
+	else // if (bssid->mode == Ndis802_11AutoUnknown)
+		iwe.u.mode = IW_MODE_AUTO;
+	event = iwe_stream_add_event(info, event, end_buf, &iwe,
+				     IW_EV_UINT_LEN);
+
+	/* add freq */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWFREQ;
+	iwe.u.freq.m = bssid->config.ds_config;
+	if (bssid->config.ds_config > 1000000) {
+		iwe.u.freq.m = bssid->config.ds_config / 10;
+		iwe.u.freq.e = 1;
+	}
+	else
+		iwe.u.freq.m = bssid->config.ds_config;
+	/* convert from kHz to Hz */
+	iwe.u.freq.e += 3;
+	iwe.len = IW_EV_FREQ_LEN;
+	event = iwe_stream_add_event(info, event, end_buf, &iwe,
+				     IW_EV_FREQ_LEN);
+
+	/* add qual */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = IWEVQUAL;
+	i = 100 * (bssid->rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
+	if (i < 0)
+		i = 0;
+	else if (i > 100)
+		i = 100;
+	iwe.u.qual.level = bssid->rssi;
+	iwe.u.qual.noise = WL_NOISE;
+	iwe.u.qual.qual  = i;
+	iwe.len = IW_EV_QUAL_LEN;
+	event = iwe_stream_add_event(info, event, end_buf, &iwe,
+				     IW_EV_QUAL_LEN);
+
+	/* add key info */
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = SIOCGIWENCODE;
+	if (bssid->privacy == Ndis802_11PrivFilterAcceptAll)
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	else
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	iwe.u.data.length = 0;
+	iwe.len = IW_EV_POINT_LEN;
+	event = iwe_stream_add_point(info, event, end_buf, &iwe,
+				     bssid->ssid.essid);
+
+	/* add rate */
+	memset(&iwe, 0, sizeof(iwe));
+	current_val = event + iwe_stream_lcp_len(info);
+	iwe.cmd = SIOCGIWRATE;
+	if (bssid->length > sizeof(*bssid))
+		nrates = NDIS_MAX_RATES_EX;
+	else
+		nrates = NDIS_MAX_RATES;
+	for (i = 0 ; i < nrates ; i++) {
+		if (bssid->rates[i] & 0x7f) {
+			iwe.u.bitrate.value = ((bssid->rates[i] & 0x7f) *
+					       500000);
+			current_val = iwe_stream_add_value(info, event,
+							   current_val,
+							   end_buf, &iwe,
+							   IW_EV_PARAM_LEN);
+		}
+	}
+
+	if ((current_val - event) > iwe_stream_lcp_len(info))
+		event = current_val;
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = IWEVCUSTOM;
+	sprintf(buf, "bcn_int=%d", bssid->config.beacon_period);
+	iwe.u.data.length = strlen(buf);
+	event = iwe_stream_add_point(info, event, end_buf, &iwe, buf);
+
+	memset(&iwe, 0, sizeof(iwe));
+	iwe.cmd = IWEVCUSTOM;
+	sprintf(buf, "atim=%u", bssid->config.atim_window);
+	iwe.u.data.length = strlen(buf);
+	event = iwe_stream_add_point(info, event, end_buf, &iwe, buf);
+
+	TRACE2("%d, %u", bssid->length, (unsigned int)sizeof(*bssid));
+	if (bssid->length > sizeof(*bssid)) {
+		unsigned char *iep = (unsigned char *)bssid_ex->ies +
+			sizeof(struct ndis_fixed_ies);
+		no_warn_unused unsigned char *end = iep + bssid_ex->ie_length;
+
+		while (iep + 1 < end && iep + 2 + iep[1] <= end) {
+			unsigned char ielen = 2 + iep[1];
+
+			if (ielen > SSID_MAX_WPA_IE_LEN) {
+				iep += ielen;
+				continue;
+			}
+			if ((iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 &&
+			     memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) ||
+			    iep[0] == RSN_INFO_ELEM) {
+				memset(&iwe, 0, sizeof(iwe));
+				iwe.cmd = IWEVGENIE;
+				iwe.u.data.length = ielen;
+				event = iwe_stream_add_point(info, event,
+							     end_buf, &iwe,
+							     iep);
+			}
+			iep += ielen;
+		}
+	}
+	TRACE2("event = %p, current_val = %p", event, current_val);
+	EXIT2(return event);
+}
+
+int set_scan(struct ndis_device *wnd)
+{
+	NDIS_STATUS res;
+
+	ENTER2("");
+	res = mp_set(wnd, OID_802_11_BSSID_LIST_SCAN, NULL, 0);
+	if (res) {
+		WARNING("scanning failed (%08X)", res);
+		EXIT2(return -EOPNOTSUPP);
+	}
+	wnd->scan_timestamp = jiffies;
+	EXIT2(return 0);
+}
+
+static int iw_set_scan(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	return set_scan(wnd);
+}
+
+static int iw_get_scan(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	unsigned int i, list_len, needed;
+	NDIS_STATUS res;
+	struct ndis_bssid_list *bssid_list = NULL;
+	char *event = extra;
+	struct ndis_wlan_bssid *cur_item ;
+
+	ENTER2("");
+	if (time_before(jiffies, wnd->scan_timestamp + 3 * HZ))
+		return -EAGAIN;
+	/* try with space for a few scan items */
+	list_len = sizeof(ULONG) + sizeof(struct ndis_wlan_bssid_ex) * 8;
+	bssid_list = kmalloc(list_len, GFP_KERNEL);
+	if (!bssid_list) {
+		ERROR("couldn't allocate memory");
+		return -ENOMEM;
+	}
+	/* some drivers don't set bssid_list->num_items to 0 if
+	   OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */
+	memset(bssid_list, 0, list_len);
+
+	needed = 0;
+	res = mp_query_info(wnd, OID_802_11_BSSID_LIST,
+			    bssid_list, list_len, NULL, &needed);
+	if (res == NDIS_STATUS_INVALID_LENGTH ||
+	    res == NDIS_STATUS_BUFFER_TOO_SHORT) {
+		/* now try with required space */
+		kfree(bssid_list);
+		list_len = needed;
+		bssid_list = kmalloc(list_len, GFP_KERNEL);
+		if (!bssid_list) {
+			ERROR("couldn't allocate memory");
+			return -ENOMEM;
+		}
+		memset(bssid_list, 0, list_len);
+
+		res = mp_query(wnd, OID_802_11_BSSID_LIST,
+			       bssid_list, list_len);
+	}
+	if (res) {
+		WARNING("getting BSSID list failed (%08X)", res);
+		kfree(bssid_list);
+		EXIT2(return -EOPNOTSUPP);
+	}
+	TRACE2("%d", bssid_list->num_items);
+	cur_item = &bssid_list->bssid[0];
+	for (i = 0; i < bssid_list->num_items; i++) {
+		event = ndis_translate_scan(dev, info, event,
+					    extra + IW_SCAN_MAX_DATA, cur_item);
+		cur_item = (struct ndis_wlan_bssid *)((char *)cur_item +
+						      cur_item->length);
+	}
+	wrqu->data.length = event - extra;
+	wrqu->data.flags = 0;
+	kfree(bssid_list);
+	EXIT2(return 0);
+}
+
+static int iw_set_power_mode(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	ULONG power_mode;
+
+	if (wrqu->power.disabled == 1)
+		power_mode = NDIS_POWER_OFF;
+	else if (wrqu->power.flags & IW_POWER_MIN)
+		power_mode = NDIS_POWER_MIN;
+	else // if (wrqu->power.flags & IW_POWER_MAX)
+		power_mode = NDIS_POWER_MAX;
+
+	TRACE2("%d", power_mode);
+	res = mp_set(wnd, OID_802_11_POWER_MODE,
+		     &power_mode, sizeof(power_mode));
+	if (res)
+		WARNING("setting power mode failed (%08X)", res);
+	return 0;
+}
+
+static int iw_get_power_mode(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	ULONG power_mode;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_802_11_POWER_MODE,
+		       &power_mode, sizeof(power_mode));
+	if (res)
+		return -ENOTSUPP;
+
+	if (power_mode == NDIS_POWER_OFF)
+		wrqu->power.disabled = 1;
+	else {
+		if (wrqu->power.flags != 0)
+			return 0;
+		wrqu->power.flags |= IW_POWER_ALL_R;
+		wrqu->power.flags |= IW_POWER_TIMEOUT;
+		wrqu->power.value = 0;
+		wrqu->power.disabled = 0;
+
+		if (power_mode == NDIS_POWER_MIN)
+			wrqu->power.flags |= IW_POWER_MIN;
+		else // if (power_mode == NDIS_POWER_MAX)
+			wrqu->power.flags |= IW_POWER_MAX;
+	}
+	return 0;
+}
+
+static int iw_get_sensitivity(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	ndis_rssi rssi_trigger;
+
+	ENTER2("");
+	res = mp_query(wnd, OID_802_11_RSSI_TRIGGER,
+		       &rssi_trigger, sizeof(rssi_trigger));
+	if (res)
+		return -EOPNOTSUPP;
+	wrqu->param.value = rssi_trigger;
+	wrqu->param.disabled = (rssi_trigger == 0);
+	wrqu->param.fixed = 1;
+	return 0;
+}
+
+static int iw_set_sensitivity(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	ndis_rssi rssi_trigger;
+
+	ENTER2("");
+	if (wrqu->param.disabled)
+		rssi_trigger = 0;
+	else
+		rssi_trigger = wrqu->param.value;
+	res = mp_set(wnd, OID_802_11_RSSI_TRIGGER,
+		     &rssi_trigger, sizeof(rssi_trigger));
+	if (res == NDIS_STATUS_INVALID_DATA)
+		return -EINVAL;
+	if (res)
+		return -EOPNOTSUPP;
+	return 0;
+}
+
+static int iw_get_ndis_stats(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct iw_statistics *stats = &wnd->iw_stats;
+	memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual));
+	return 0;
+}
+
+static int iw_get_range(struct net_device *dev, struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+	struct iw_point *data = &wrqu->data;
+	struct ndis_device *wnd = netdev_priv(dev);
+	unsigned int i, n;
+	NDIS_STATUS res;
+	ndis_rates_ex rates;
+	ndis_tx_power_level tx_power;
+
+	ENTER2("");
+	data->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+
+	range->txpower_capa = IW_TXPOW_MWATT;
+	range->num_txpower = 0;
+
+	res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
+		       &tx_power, sizeof(tx_power));
+	if (!res) {
+		range->num_txpower = 1;
+		range->txpower[0] = tx_power;
+	}
+
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 18;
+
+	range->retry_capa = IW_RETRY_LIMIT;
+	range->retry_flags = IW_RETRY_LIMIT;
+	range->min_retry = 0;
+	range->max_retry = 255;
+
+	range->num_channels = 1;
+
+	range->max_qual.qual = 100;
+	range->max_qual.level = 154;
+	range->max_qual.noise = 154;
+	range->sensitivity = 3;
+
+	range->max_encoding_tokens = 4;
+	range->num_encoding_sizes = 2;
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+
+	range->num_bitrates = 0;
+	memset(&rates, 0, sizeof(rates));
+	res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES,
+			    &rates, sizeof(rates), &n, NULL);
+	if (res)
+		WARNING("getting bit rates failed: %08X", res);
+	else {
+		for (i = 0; i < n && range->num_bitrates < IW_MAX_BITRATES; i++)
+			if (rates[i] & 0x80)
+				continue;
+			else if (rates[i] & 0x7f) {
+				range->bitrate[range->num_bitrates] =
+					(rates[i] & 0x7f) * 500000;
+				range->num_bitrates++;
+			}
+	}
+
+	range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0]));
+
+	for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
+		    i < IW_MAX_FREQUENCIES; i++) {
+		range->freq[i].i = i + 1;
+		range->freq[i].m = freq_chan[i] * 100000;
+		range->freq[i].e = 1;
+	}
+	range->num_frequency = i;
+
+	range->min_rts = 0;
+	range->max_rts = 2347;
+	range->min_frag = 256;
+	range->max_frag = 2346;
+
+	/* Event capability (kernel + driver) */
+	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+				IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
+	range->event_capa[1] = IW_EVENT_CAPA_K_1;
+	range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) |
+				IW_EVENT_CAPA_MASK(IWEVCUSTOM) |
+				IW_EVENT_CAPA_MASK(IWEVREGISTERED) |
+				IW_EVENT_CAPA_MASK(IWEVEXPIRED));
+
+	range->enc_capa = 0;
+
+	if (test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr))
+		range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP;
+	if (test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr))
+		range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP;
+
+	if (test_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth) ||
+	    test_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth))
+		range->enc_capa |= IW_ENC_CAPA_WPA;
+	if (test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ||
+	    test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth))
+		range->enc_capa |= IW_ENC_CAPA_WPA2;
+
+	return 0;
+}
+
+void set_default_iw_params(struct ndis_device *wnd)
+{
+	wnd->iw_auth_key_mgmt = 0;
+	wnd->iw_auth_wpa_version = 0;
+	set_infra_mode(wnd, Ndis802_11Infrastructure);
+	set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen);
+	set_priv_filter(wnd);
+	set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
+}
+
+static int deauthenticate(struct ndis_device *wnd)
+{
+	int ret;
+
+	ENTER2("");
+	ret = disassociate(wnd, 1);
+	set_default_iw_params(wnd);
+	EXIT2(return ret);
+}
+
+NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid)
+{
+	NDIS_STATUS res;
+	u8 buf[NDIS_ESSID_MAX_SIZE];
+	int i;
+
+	TRACE2("");
+	res = mp_set(wnd, OID_802_11_DISASSOCIATE, NULL, 0);
+	/* disassociate causes radio to be turned off; if reset_ssid
+	 * is given, set ssid to random to enable radio */
+	if (reset_ssid) {
+		get_random_bytes(buf, sizeof(buf));
+		for (i = 0; i < sizeof(buf); i++)
+			buf[i] = 'a' + (buf[i] % 26);
+		set_essid(wnd, buf, sizeof(buf));
+	}
+	return res;
+}
+
+static ULONG ndis_priv_mode(struct ndis_device *wnd)
+{
+	if (wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
+	    wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA)
+		return Ndis802_11PrivFilter8021xWEP;
+	else
+		return Ndis802_11PrivFilterAcceptAll;
+}
+
+int set_priv_filter(struct ndis_device *wnd)
+{
+	NDIS_STATUS res;
+	ULONG flags;
+
+	flags = ndis_priv_mode(wnd);
+	ENTER2("filter: %d", flags);
+	res = mp_set_int(wnd, OID_802_11_PRIVACY_FILTER, flags);
+	if (res)
+		TRACE2("setting privacy filter to %d failed (%08X)",
+		       flags, res);
+	EXIT2(return 0);
+}
+
+static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+
+	ENTER2("");
+	switch (mlme->cmd) {
+	case IW_MLME_DEAUTH:
+		return deauthenticate(wnd);
+	case IW_MLME_DISASSOC:
+		TRACE2("cmd=%d reason_code=%d", mlme->cmd, mlme->reason_code);
+		return disassociate(wnd, 1);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int iw_set_genie(struct net_device *dev,
+			struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	/*
+	 * NDIS drivers do not allow IEs to be configured; this is
+	 * done by the driver based on other configuration. Return 0
+	 * to avoid causing issues with user space programs that
+	 * expect this function to succeed.
+	 */
+	return 0;
+}
+
+static int iw_set_auth(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	TRACE2("index=%d value=%d", wrqu->param.flags & IW_AUTH_INDEX,
+	       wrqu->param.value);
+	switch (wrqu->param.flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+		wnd->iw_auth_wpa_version = wrqu->param.value;
+		break;
+	case IW_AUTH_CIPHER_PAIRWISE:
+		wnd->iw_auth_cipher_pairwise = wrqu->param.value;
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		wnd->iw_auth_cipher_group = wrqu->param.value;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		wnd->iw_auth_key_mgmt = wrqu->param.value;
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		wnd->iw_auth_80211_alg = wrqu->param.value;
+		break;
+	case IW_AUTH_WPA_ENABLED:
+		if (wrqu->param.value)
+			deauthenticate(wnd);
+		break;
+	case IW_AUTH_TKIP_COUNTERMEASURES:
+	case IW_AUTH_DROP_UNENCRYPTED:
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+	case IW_AUTH_PRIVACY_INVOKED:
+		TRACE2("%d not implemented: %d",
+		       wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value);
+		break;
+	default:
+		WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static int iw_get_auth(struct net_device *dev,
+		       struct iw_request_info *info,
+		       union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	ENTER2("index=%d", wrqu->param.flags & IW_AUTH_INDEX);
+	switch (wrqu->param.flags & IW_AUTH_INDEX) {
+	case IW_AUTH_WPA_VERSION:
+		wrqu->param.value = wnd->iw_auth_wpa_version;
+		break;
+	case IW_AUTH_CIPHER_PAIRWISE:
+		wrqu->param.value = wnd->iw_auth_cipher_pairwise;
+		break;
+	case IW_AUTH_CIPHER_GROUP:
+		wrqu->param.value = wnd->iw_auth_cipher_group;
+		break;
+	case IW_AUTH_KEY_MGMT:
+		wrqu->param.value = wnd->iw_auth_key_mgmt;
+		break;
+	case IW_AUTH_80211_AUTH_ALG:
+		wrqu->param.value = wnd->iw_auth_80211_alg;
+		break;
+	default:
+		WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static int iw_set_encodeext(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct ndis_add_key ndis_key;
+	int i, keyidx;
+	NDIS_STATUS res;
+	u8 *addr;
+
+	keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
+	ENTER2("%d", keyidx);
+	if (keyidx)
+		keyidx--;
+	else
+		keyidx = wnd->encr_info.tx_key_index;
+
+	if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS)
+		return -EINVAL;
+
+	if (ext->alg == WPA_ALG_WEP) {
+		if (!test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr))
+			EXIT2(return -1);
+		if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+			wnd->encr_info.tx_key_index = keyidx;
+		if (add_wep_key(wnd, ext->key, ext->key_len, keyidx))
+			EXIT2(return -1);
+		else
+			EXIT2(return 0);
+	}
+	if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
+	    ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
+		EXIT2(return remove_key(wnd, keyidx, ndis_key.bssid));
+
+	if (ext->key_len > sizeof(ndis_key.key)) {
+		TRACE2("incorrect key length (%u)", ext->key_len);
+		EXIT2(return -1);
+	}
+
+	memset(&ndis_key, 0, sizeof(ndis_key));
+
+	ndis_key.struct_size =
+		sizeof(ndis_key) - sizeof(ndis_key.key) + ext->key_len;
+	ndis_key.length = ext->key_len;
+	ndis_key.index = keyidx;
+
+	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
+		for (i = 0; i < 6 ; i++)
+			ndis_key.rsc |= (((u64)ext->rx_seq[i]) << (i * 8));
+		TRACE2("0x%Lx", ndis_key.rsc);
+		ndis_key.index |= 1 << 29;
+	}
+
+	addr = ext->addr.sa_data;
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+		/* group key */
+		if (wnd->infrastructure_mode == Ndis802_11IBSS)
+			memset(ndis_key.bssid, 0xff, ETH_ALEN);
+		else
+			get_ap_address(wnd, ndis_key.bssid);
+	} else {
+		/* pairwise key */
+		ndis_key.index |= (1 << 30);
+		memcpy(ndis_key.bssid, addr, ETH_ALEN);
+	}
+	TRACE2(MACSTRSEP, MAC2STR(ndis_key.bssid));
+
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		ndis_key.index |= (1 << 31);
+
+	if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
+		/* wpa_supplicant gives us the Michael MIC RX/TX keys in
+		 * different order than NDIS spec, so swap the order here. */
+		memcpy(ndis_key.key, ext->key, 16);
+		memcpy(ndis_key.key + 16, ext->key + 24, 8);
+		memcpy(ndis_key.key + 24, ext->key + 16, 8);
+	} else
+		memcpy(ndis_key.key, ext->key, ext->key_len);
+
+	res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size);
+	if (res) {
+		TRACE2("adding key failed (%08X), %u",
+		       res, ndis_key.struct_size);
+		EXIT2(return -1);
+	}
+	wnd->encr_info.keys[keyidx].length = ext->key_len;
+	memcpy(&wnd->encr_info.keys[keyidx].key, ndis_key.key, ext->key_len);
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+		wnd->encr_info.tx_key_index = keyidx;
+	TRACE2("key %d added", keyidx);
+
+	EXIT2(return 0);
+}
+
+static int iw_get_encodeext(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	/* struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; */
+	/* TODO */
+	ENTER2("");
+	return 0;
+}
+
+static int iw_set_pmksa(struct net_device *dev, struct iw_request_info *info,
+			union iwreq_data *wrqu, char *extra)
+{
+	struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
+	struct ndis_pmkid pmkid;
+	NDIS_STATUS res;
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	/* TODO: must keep local list of PMKIDs since NDIS drivers
+	 * expect that all PMKID entries are included whenever a new
+	 * one is added. */
+
+	ENTER2("%d", pmksa->cmd);
+	if ((pmksa->cmd == IW_PMKSA_ADD || pmksa->cmd == IW_PMKSA_REMOVE) &&
+	    (!(wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2)))
+		EXIT2(return -EOPNOTSUPP);
+
+	memset(&pmkid, 0, sizeof(pmkid));
+	if (pmksa->cmd == IW_PMKSA_ADD) {
+		pmkid.bssid_info_count = 1;
+		memcpy(pmkid.bssid_info[0].bssid, pmksa->bssid.sa_data,
+		       ETH_ALEN);
+		memcpy(pmkid.bssid_info[0].pmkid, pmksa->pmkid, IW_PMKID_LEN);
+	}
+	pmkid.length = sizeof(pmkid);
+
+	res = mp_set(wnd, OID_802_11_PMKID, &pmkid, pmkid.length);
+	if (res == NDIS_STATUS_FAILURE)
+		EXIT2(return -EOPNOTSUPP);
+	TRACE2("OID_802_11_PMKID -> %d", res);
+	if (res)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define WEXT(id) [id - SIOCIWFIRST]
+
+static const iw_handler	ndis_handler[] = {
+	WEXT(SIOCGIWNAME)	 = iw_get_network_type,
+	WEXT(SIOCSIWESSID)	 = iw_set_essid,
+	WEXT(SIOCGIWESSID)	 = iw_get_essid,
+	WEXT(SIOCSIWMODE)	 = iw_set_infra_mode,
+	WEXT(SIOCGIWMODE)	 = iw_get_infra_mode,
+	WEXT(SIOCGIWFREQ)	 = iw_get_freq,
+	WEXT(SIOCSIWFREQ)	 = iw_set_freq,
+	WEXT(SIOCGIWTXPOW)	 = iw_get_tx_power,
+	WEXT(SIOCSIWTXPOW)	 = iw_set_tx_power,
+	WEXT(SIOCGIWRATE)	 = iw_get_bitrate,
+	WEXT(SIOCSIWRATE)	 = iw_set_bitrate,
+	WEXT(SIOCGIWRTS)	 = iw_get_rts_threshold,
+	WEXT(SIOCSIWRTS)	 = iw_set_rts_threshold,
+	WEXT(SIOCGIWFRAG)	 = iw_get_frag_threshold,
+	WEXT(SIOCSIWFRAG)	 = iw_set_frag_threshold,
+	WEXT(SIOCGIWAP)		 = iw_get_ap_address,
+	WEXT(SIOCSIWAP)		 = iw_set_ap_address,
+	WEXT(SIOCSIWENCODE)	 = iw_set_wep,
+	WEXT(SIOCGIWENCODE)	 = iw_get_encr,
+	WEXT(SIOCSIWSCAN)	 = iw_set_scan,
+	WEXT(SIOCGIWSCAN)	 = iw_get_scan,
+	WEXT(SIOCGIWPOWER)	 = iw_get_power_mode,
+	WEXT(SIOCSIWPOWER)	 = iw_set_power_mode,
+	WEXT(SIOCGIWRANGE)	 = iw_get_range,
+	WEXT(SIOCGIWSTATS)	 = iw_get_ndis_stats,
+	WEXT(SIOCGIWSENS)	 = iw_get_sensitivity,
+	WEXT(SIOCSIWSENS)	 = iw_set_sensitivity,
+	WEXT(SIOCGIWNICKN)	 = iw_get_nick,
+	WEXT(SIOCSIWNICKN)	 = iw_set_nick,
+	WEXT(SIOCSIWCOMMIT)	 = iw_set_dummy,
+	WEXT(SIOCSIWMLME)	 = iw_set_mlme,
+	WEXT(SIOCSIWGENIE)	 = iw_set_genie,
+	WEXT(SIOCSIWAUTH)	 = iw_set_auth,
+	WEXT(SIOCGIWAUTH)	 = iw_get_auth,
+	WEXT(SIOCSIWENCODEEXT)	 = iw_set_encodeext,
+	WEXT(SIOCGIWENCODEEXT)	 = iw_get_encodeext,
+	WEXT(SIOCSIWPMKSA)	 = iw_set_pmksa,
+};
+
+/* private ioctl's */
+
+static int priv_reset(struct net_device *dev, struct iw_request_info *info,
+		      union iwreq_data *wrqu, char *extra)
+{
+	int res;
+	ENTER2("");
+	res = mp_reset(netdev_priv(dev));
+	if (res) {
+		WARNING("reset failed: %08X", res);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static int priv_deauthenticate(struct net_device *dev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	int res;
+	ENTER2("");
+	res = deauthenticate(netdev_priv(dev));
+	return res;
+}
+
+static int priv_power_profile(struct net_device *dev,
+			      struct iw_request_info *info,
+			      union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct miniport *mp;
+	ULONG profile_inf;
+
+	ENTER2("");
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	if (!mp->pnp_event_notify)
+		EXIT2(return -EOPNOTSUPP);
+
+	/* 1 for AC and 0 for Battery */
+	if (wrqu->param.value)
+		profile_inf = NdisPowerProfileAcOnLine;
+	else
+		profile_inf = NdisPowerProfileBattery;
+
+	LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
+		 NdisDevicePnPEventPowerProfileChanged,
+		 &profile_inf, sizeof(profile_inf));
+	EXIT2(return 0);
+}
+
+static int priv_network_type(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	enum network_type network_type;
+	NDIS_STATUS res;
+	char type;
+
+	ENTER2("");
+	type = wrqu->param.value;
+	if (type == 'f')
+		network_type = Ndis802_11FH;
+	else if (type == 'b')
+		network_type = Ndis802_11DS;
+	else if (type == 'a')
+		network_type = Ndis802_11OFDM5;
+	else if (type == 'g' || type == 'n')
+		network_type = Ndis802_11OFDM24;
+	else
+		network_type = Ndis802_11Automode;
+
+	res = mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, network_type);
+	if (res) {
+		WARNING("setting network type to %d failed (%08X)",
+			network_type, res);
+		EXIT2(return -EINVAL);
+	}
+
+	EXIT2(return 0);
+}
+
+static int priv_media_stream_mode(struct net_device *dev,
+				  struct iw_request_info *info,
+				  union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	NDIS_STATUS res;
+	int mode;
+
+	ENTER2("");
+	if (wrqu->param.value > 0)
+		mode = Ndis802_11MediaStreamOn;
+	else
+		mode = Ndis802_11MediaStreamOff;
+	res = mp_set_int(wnd, OID_802_11_MEDIA_STREAM_MODE, mode);
+	if (res) {
+		WARNING("oid failed (%08X)", res);
+		EXIT2(return -EINVAL);
+	}
+	EXIT2(return 0);
+}
+
+static int priv_reload_defaults(struct net_device *dev,
+				struct iw_request_info *info,
+				union iwreq_data *wrqu, char *extra)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	int res;
+	ENTER2("");
+	res = mp_set_int(wnd, OID_802_11_RELOAD_DEFAULTS,
+			 Ndis802_11ReloadWEPKeys);
+	if (res) {
+		WARNING("reloading defaults failed: %08X", res);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static const struct iw_priv_args priv_args[] = {
+	{PRIV_RESET, 0, 0, "ndis_reset"},
+	{PRIV_POWER_PROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "power_profile"},
+	{PRIV_DEAUTHENTICATE, 0, 0, "deauthenticate"},
+	{PRIV_NETWORK_TYPE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "network_type"},
+	{PRIV_MEDIA_STREAM_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "media_stream"},
+
+	{PRIV_RELOAD_DEFAULTS, 0, 0, "reload_defaults"},
+};
+
+#define WEPRIV(id) [id - SIOCIWFIRSTPRIV]
+
+static const iw_handler priv_handler[] = {
+	WEPRIV(PRIV_RESET)		 = priv_reset,
+	WEPRIV(PRIV_POWER_PROFILE)	 = priv_power_profile,
+	WEPRIV(PRIV_DEAUTHENTICATE)	 = priv_deauthenticate,
+	WEPRIV(PRIV_NETWORK_TYPE)	 = priv_network_type,
+	WEPRIV(PRIV_MEDIA_STREAM_MODE)	 = priv_media_stream_mode,
+	WEPRIV(PRIV_RELOAD_DEFAULTS)	 = priv_reload_defaults,
+};
+
+const struct iw_handler_def ndis_handler_def = {
+	.num_standard	= sizeof(ndis_handler) / sizeof(ndis_handler[0]),
+	.num_private	= sizeof(priv_handler) / sizeof(priv_handler[0]),
+	.num_private_args = sizeof(priv_args) / sizeof(priv_args[0]),
+
+	.standard	= (iw_handler *)ndis_handler,
+	.private	= (iw_handler *)priv_handler,
+	.private_args	= (struct iw_priv_args *)priv_args,
+	.get_wireless_stats = get_iw_stats,
+};
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/win2lin_stubs.S
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/win2lin_stubs.S
@@ -0,0 +1,288 @@
+/*
+ *  Copyright (C) 2005 Karl Vogel, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include <linux/linkage.h>
+
+#ifdef CONFIG_X86_64
+
+/*
+# Windows <---> Linux register usage conversion when calling functions
+# V = Volatile
+# NV = Non Volatile (needs to be saved)
+#
+#         Win                     Lin
+# ---------------------------------------
+# Rax    Return           V       Return          V
+# Rbx                     NV                      NV
+# Rcx     Arg1            V       Arg4            V
+# Rdx     Arg2            V       Arg3            V
+# Rsi                     NV      Arg2            V
+# Rdi                     NV      Arg1            V
+# Rsp                     NV                      NV
+# Rbp                     NV                      NV
+# R8      Arg3            V       Arg5            V
+# R9      Arg4            V       Arg6            V
+# R10                     V                       V
+# R11                     V                       V
+# R12                     NV                      NV
+# R13                     NV                      NV
+# R14                     NV                      NV
+# R15                     NV                      NV
+#
+# In addition, Linux uses %rax to indicate number of SSE registers used
+# when variadic functions are called. Since there is no way to obtain this
+# from Windows, for now, we just assume this is 0 (hence %rax is cleared).
+#
+# Windows pushes arguments 5 and higher onto stack in case of integer
+# variables and 4 and higher in case of floating point variabes (passed
+# in SSE registers).
+
+In a windows function, the stackframe/registers look like this:
+
+# 0x0048 ....
+# 0x0040 arg8
+# 0x0038 arg7
+# 0x0030 arg6
+# 0x0028 arg5
+# 0x0020 shadow/spill space for arg4
+# 0x0018 shadow/spill space for arg3
+# 0x0010 shadow/spill space for arg2
+# 0x0008 shadow/spill space for arg1
+# 0x0000 ret
+
+# register spill space is same irrespective of number of arguments - even
+# if Windows function takes less than 4 arguments, 32 bytes above return
+# address is reserved for the function
+
+In Linux it should look like:
+
+# 0x0018 ....
+# 0x0010 arg8
+# 0x0008 arg7
+# 0x0000 ret
+
+*/
+
+#
+# setup for Windows to Linux function call
+#
+
+	.text
+
+.macro win2lin_prolog
+	push	%rsi
+	push	%rdi
+.endm
+
+.macro win2lin_epilog
+	pop	%rdi
+	pop	%rsi
+.endm
+
+# when Windows function calls Linux function, the function address is in %r10
+
+.macro call_lin_func
+	xor	%rax, %rax	# rax indicates number of SSE regs
+	call	*%r10
+.endm
+
+# before prolog, 0(%rsp) is return address, 8(%rsp) would be arg1
+# (but it is in register) and so on, so n'th arg would be at n*8(%rsp)
+# for n > 4. But in prolog, we push 2 registers that are non-volaile in
+# Windows, but volatile in Linux. So after prolog, args are at (n+2)*8(%rsp)
+
+#define win2lin_win_arg(n) (n+2)*8(%rsp)
+
+#define win2lin_arg1 mov %rcx, %rdi
+#define win2lin_arg2 mov %rdx, %rsi
+#define win2lin_arg3 mov %r8, %rdx
+#define win2lin_arg4 mov %r9, %rcx
+#define win2lin_arg5 mov win2lin_win_arg(5), %r8
+#define win2lin_arg6 mov win2lin_win_arg(6), %r9
+
+	.type	win2lin0, @function
+win2lin0:
+	win2lin_prolog
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin0, .-win2lin0
+
+	.type	win2lin1, @function
+win2lin1:
+	win2lin_prolog
+	win2lin_arg1
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin1, .-win2lin1
+
+	.type	win2lin2, @function
+win2lin2:
+	win2lin_prolog
+	win2lin_arg1
+	win2lin_arg2
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin2, .-win2lin2
+
+	.type	win2lin3, @function
+win2lin3:
+	win2lin_prolog
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin3, .-win2lin3
+
+	.type	win2lin4, @function
+win2lin4:
+	win2lin_prolog
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin4, .-win2lin4
+
+	.type	win2lin5, @function
+win2lin5:
+	win2lin_prolog
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	win2lin_arg5
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin5, .-win2lin5
+
+	.type	win2lin6, @function
+win2lin6:
+	win2lin_prolog
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	win2lin_arg5
+	win2lin_arg6
+	call_lin_func
+	win2lin_epilog
+	ret
+	.size	win2lin6, .-win2lin6
+
+# Allocate stack frame for Linux arguments before calling function.
+# First 6 args are passed through registers, so we need space for 7 and above.
+# The arguments should have been copied onto stack already.
+
+.macro call_lin_func_args n
+	sub $(\n-6)*8, %rsp
+	call_lin_func
+	add $(\n-6)*8, %rsp
+	.endm
+
+# m is index of Linux arg required, n is total number of args to function
+# After stack frame is allocated, Linux arg 7 should be at 0(%rsp),
+# arg 8 should be at 1*8(%rsp) and so on. So Linux arg m should be at (m-7)*8
+# Stack frame starts at -(n-6)*8(%rsp), so before stack frame is allocated
+# Linux arg m should be at (6-n+m-7)*8(%rsp)
+
+#define win2lin_lin_arg(m,n) (m-1-n)*8(%rsp)
+
+	.type	win2lin7, @function
+win2lin7:
+	win2lin_prolog
+
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	win2lin_arg5
+	win2lin_arg6
+
+	# copy windows argument 7 onto stack for Linux function
+	mov	win2lin_win_arg(7), %r11
+	mov	%r11, win2lin_lin_arg(7,7)
+
+	call_lin_func_args(7)
+	win2lin_epilog
+	ret
+	.size	win2lin7, .-win2lin7
+
+	.type	win2lin8, @function
+win2lin8:
+	win2lin_prolog
+
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	win2lin_arg5
+	win2lin_arg6
+
+	# copy windows arguments 7 and 8 onto stack for Linux function
+	mov	win2lin_win_arg(7), %r11
+	mov	%r11, win2lin_lin_arg(7,8)
+	mov	win2lin_win_arg(8), %r11
+	mov	%r11, win2lin_lin_arg(8,8)
+
+	call_lin_func_args(8)
+	win2lin_epilog
+	ret
+	.size	win2lin8, .-win2lin8
+
+	.type	win2lin9, @function
+win2lin9:
+win2lin10:
+win2lin11:
+win2lin12:
+	win2lin_prolog
+
+	# since we destroy rsi and rdi here, first copy windows
+	# arguments 7 through 12 onto stack for Linux function
+	mov	%rcx, %r11		# save rcx
+	lea	win2lin_win_arg(7), %rsi	# source (windows arg 7 and up)
+	lea	win2lin_lin_arg(7,12), %rdi	# = destination
+	mov	$6, %rcx			# 6 arguments
+	rep
+	movsq
+	mov	%r11, %rcx		# restore rcx
+
+	win2lin_arg1
+	win2lin_arg2
+	win2lin_arg3
+	win2lin_arg4
+	win2lin_arg5
+	win2lin_arg6
+
+	call_lin_func_args(12)
+	win2lin_epilog
+	ret
+	.size	win2lin9, .-win2lin9
+
+#define win2lin(name, argc)			\
+ENTRY(win2lin_ ## name ## _ ## argc)		\
+	lea	name(%rip), %r10 ; 		\
+	jmp	win2lin ## argc
+
+#include "win2lin_stubs.h"
+
+#endif // CONFIG_X86_64
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapper.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapper.c
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ndis.h"
+#include "iw_ndis.h"
+#include "loader.h"
+#include "pnp.h"
+#include "wrapper.h"
+
+char *if_name = "wlan%d";
+int proc_uid, proc_gid;
+int hangcheck_interval;
+static char *utils_version = UTILS_VERSION;
+
+#if defined(DEBUG) && (DEBUG > 0)
+int debug = DEBUG;
+#else
+int debug = 0;
+#endif
+
+WRAP_MODULE_PARM_STRING(if_name, 0400);
+MODULE_PARM_DESC(if_name, "Network interface name or template "
+		 "(default: wlan%d)");
+WRAP_MODULE_PARM_INT(proc_uid, 0600);
+MODULE_PARM_DESC(proc_uid, "The uid of the files created in /proc "
+		 "(default: 0).");
+WRAP_MODULE_PARM_INT(proc_gid, 0600);
+MODULE_PARM_DESC(proc_gid, "The gid of the files created in /proc "
+		 "(default: 0).");
+WRAP_MODULE_PARM_INT(debug, 0600);
+MODULE_PARM_DESC(debug, "debug level");
+
+/* 0 - default value provided by NDIS driver,
+ * positive value - force hangcheck interval to that many seconds
+ * negative value - disable hangcheck
+ */
+WRAP_MODULE_PARM_INT(hangcheck_interval, 0600);
+MODULE_PARM_DESC(hangcheck_interval, "The interval, in seconds, for checking"
+		 " if driver is hung. (default: 0)");
+
+WRAP_MODULE_PARM_STRING(utils_version, 0400);
+MODULE_PARM_DESC(utils_version, "Compatible version of utils "
+		 "(read only: " UTILS_VERSION ")");
+
+MODULE_AUTHOR("ndiswrapper team <ndiswrapper-general@lists.sourceforge.net>");
+#ifdef MODULE_DESCRIPTION
+MODULE_DESCRIPTION("NDIS wrapper driver");
+#endif
+#ifdef MODULE_VERSION
+MODULE_VERSION(DRIVER_VERSION);
+#endif
+MODULE_LICENSE("GPL");
+
+static void module_cleanup(void)
+{
+	loader_exit();
+#ifdef ENABLE_USB
+	usb_exit();
+#endif
+
+	wrap_procfs_remove();
+	wrapndis_exit();
+	ndis_exit();
+	rtl_exit();
+	crt_exit();
+	ntoskernel_exit();
+	wrapmem_exit();
+}
+
+static int __init wrapper_init(void)
+{
+	printk(KERN_INFO "%s version %s loaded (smp=%s, preempt=%s)\n",
+	       DRIVER_NAME, DRIVER_VERSION,
+#ifdef CONFIG_SMP
+	       "yes"
+#else
+	       "no"
+#endif
+		,
+#ifdef CONFIG_PREEMPT_RT
+		"rt"
+#elif defined(CONFIG_PREEMPT)
+		"yes"
+#else
+		"no"
+#endif
+		);
+
+	if (wrapmem_init() || ntoskernel_init() || crt_init() ||
+	    rtl_init() || ndis_init() || wrapndis_init() ||
+#ifdef ENABLE_USB
+	    usb_init() ||
+#endif
+	    wrap_procfs_init() || loader_init()) {
+		module_cleanup();
+		ERROR("%s: initialization failed", DRIVER_NAME);
+		return -EINVAL;
+	}
+	EXIT1(return 0);
+}
+
+static void __exit wrapper_exit(void)
+{
+	ENTER1("");
+	module_cleanup();
+}
+
+module_init(wrapper_init);
+module_exit(wrapper_exit);
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/Makefile
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/Makefile
@@ -0,0 +1,38 @@
+ndiswrapper-objs := crt.o hal.o iw_ndis.o loader.o ndis.o ntoskernel.o ntoskernel_io.o \
+	pe_linker.o pnp.o proc.o rtl.o wrapmem.o wrapndis.o wrapper.o usb.o
+
+EXPORTS = crt_exports.h hal_exports.h ndis_exports.h ntoskernel_exports.h \
+	ntoskernel_io_exports.h rtl_exports.h usb_exports.h
+
+STUB_SRCS = crt.c hal.c ndis.c ntoskernel.c ntoskernel_io.c \
+	pnp.c rtl.c wrapndis.c usb.c
+
+
+EXTRA_CFLAGS += -DENABLE_USB -I$(obj)
+EXTRA_AFLAGS += -I$(obj)
+
+# generate exports symbol table from C files
+quiet_cmd_mkexport = MKEXPORT $@
+cmd_mkexport = $(SHELL) $(srctree)/$(src)/mkexport.sh $< $@
+
+%_exports.h: %.c $(srctree)/$(src)/mkexport.sh FORCE
+	$(call if_changed,mkexport)
+
+$(addprefix $(obj)/,$(EXPORTS:_exports.h=.o)): %.o: %_exports.h
+extra-y += $(EXPORTS)
+
+ifeq ($(CONFIG_X86_64),y)
+quiet_cmd_mkstubs = MKSTUBS $@
+cmd_mkstubs = $(SHELL) $(srctree)/$(src)/mkstubs.sh $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) >$@
+
+$(obj)/win2lin_stubs.h: $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) FORCE
+	$(call if_changed,mkstubs)
+
+$(obj)/win2lin_stubs.o: $(obj)/win2lin_stubs.h
+extra-y += win2lin_stubs.h
+ndiswrapper-objs += win2lin_stubs.o
+else
+ndiswrapper-objs += divdi3.o
+endif
+
+obj-$(CONFIG_NDISWRAPPER) := ndiswrapper.o
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapndis.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapndis.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _WRAPNDIS_H_
+#define _WRAPNDIS_H_
+
+#include "ndis.h"
+#include "pnp.h"
+
+int wrapndis_init(void);
+void wrapndis_exit(void);
+
+NDIS_STATUS mp_reset(struct ndis_device *wnd);
+
+NDIS_STATUS mp_request(enum ndis_request_type request,
+		       struct ndis_device *wnd, ndis_oid oid,
+		       void *buf, ULONG buflen, ULONG *written, ULONG *needed);
+
+static inline NDIS_STATUS mp_query_info(struct ndis_device *wnd,
+					ndis_oid oid, void *buf, ULONG buflen,
+					ULONG *written, ULONG *needed)
+{
+	return mp_request(NdisRequestQueryInformation, wnd, oid,
+			  buf, buflen, written, needed);
+}
+
+static inline NDIS_STATUS mp_set_info(struct ndis_device *wnd,
+				      ndis_oid oid, void *buf, ULONG buflen,
+				      ULONG *written, ULONG *needed)
+{
+	return mp_request(NdisRequestSetInformation, wnd, oid,
+			  buf, buflen, written, needed);
+}
+
+static inline NDIS_STATUS mp_query(struct ndis_device *wnd, ndis_oid oid,
+				   void *buf, ULONG buflen)
+{
+	return mp_request(NdisRequestQueryInformation, wnd, oid,
+			  buf, buflen, NULL, NULL);
+}
+
+static inline NDIS_STATUS mp_query_int(struct ndis_device *wnd,
+				       ndis_oid oid, ULONG *data)
+{
+	return mp_request(NdisRequestQueryInformation, wnd, oid,
+			  data, sizeof(ULONG), NULL, NULL);
+}
+
+static inline NDIS_STATUS mp_set(struct ndis_device *wnd, ndis_oid oid,
+				 void *buf, ULONG buflen)
+{
+	return mp_request(NdisRequestSetInformation, wnd, oid,
+			  buf, buflen, NULL, NULL);
+}
+
+static inline NDIS_STATUS mp_set_int(struct ndis_device *wnd,
+				     ndis_oid oid, ULONG data)
+{
+	return mp_request(NdisRequestSetInformation, wnd, oid,
+			  &data, sizeof(ULONG), NULL, NULL);
+}
+
+void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet,
+		    NDIS_STATUS status);
+int init_ndis_driver(struct driver_object *drv_obj);
+NDIS_STATUS ndis_reinit(struct ndis_device *wnd);
+void set_media_state(struct ndis_device *wnd, enum ndis_media_state state);
+
+void hangcheck_add(struct ndis_device *wnd);
+void hangcheck_del(struct ndis_device *wnd);
+
+driver_dispatch_t winNdisDispatchPnp;
+driver_dispatch_t winNdisDispatchPower;
+driver_dispatch_t winNdisDispatchDeviceControl;
+
+struct iw_statistics *get_iw_stats(struct net_device *dev);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/pe_linker.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/pe_linker.c
@@ -0,0 +1,609 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifdef TEST_LOADER
+
+#include "usr_linker.h"
+
+#else
+
+#include <linux/types.h>
+#include <asm/errno.h>
+
+//#define DEBUGLINKER 2
+
+#include "ntoskernel.h"
+
+#endif
+
+struct pe_exports {
+	char *dll;
+	char *name;
+	generic_func addr;
+};
+
+static struct pe_exports pe_exports[40];
+static int num_pe_exports;
+
+#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva)
+#define CHECK_SZ(a,b) { if (sizeof(a) != b) {				\
+			ERROR("%s is bad, got %zd, expected %d",	\
+			      #a , sizeof(a), (b)); return -EINVAL; } }
+
+#if defined(DEBUGLINKER) && DEBUGLINKER > 0
+#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n",	\
+				   DRIVER_NAME, __func__,		\
+				   __LINE__ , ## __VA_ARGS__);
+static const char *image_directory_name[] = {
+	"EXPORT",
+	"IMPORT",
+	"RESOURCE",
+	"EXCEPTION",
+	"SECURITY",
+	"BASERELOC",
+	"DEBUG",
+	"COPYRIGHT",
+	"GLOBALPTR",
+	"TLS",
+	"LOAD_CONFIG",
+	"BOUND_IMPORT",
+	"IAT",
+	"DELAY_IMPORT",
+	"COM_DESCRIPTOR" };
+#else
+#define DBGLINKER(fmt, ...) do { } while (0)
+#endif
+
+#ifndef TEST_LOADER
+extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[],
+	ndis_exports[], crt_exports[], hal_exports[], rtl_exports[];
+#ifdef ENABLE_USB
+extern struct wrap_export usb_exports[];
+#endif
+
+static char *get_export(char *name)
+{
+	int i;
+
+	for (i = 0 ; ntoskernel_exports[i].name != NULL; i++)
+		if (strcmp(ntoskernel_exports[i].name, name) == 0)
+			return (char *)ntoskernel_exports[i].func;
+
+	for (i = 0 ; ntoskernel_io_exports[i].name != NULL; i++)
+		if (strcmp(ntoskernel_io_exports[i].name, name) == 0)
+			return (char *)ntoskernel_io_exports[i].func;
+
+	for (i = 0 ; ndis_exports[i].name != NULL; i++)
+		if (strcmp(ndis_exports[i].name, name) == 0)
+			return (char *)ndis_exports[i].func;
+
+	for (i = 0 ; crt_exports[i].name != NULL; i++)
+		if (strcmp(crt_exports[i].name, name) == 0)
+			return (char *)crt_exports[i].func;
+
+	for (i = 0 ; hal_exports[i].name != NULL; i++)
+		if (strcmp(hal_exports[i].name, name) == 0)
+			return (char *)hal_exports[i].func;
+
+	for (i = 0 ; rtl_exports[i].name != NULL; i++)
+		if (strcmp(rtl_exports[i].name, name) == 0)
+			return (char *)rtl_exports[i].func;
+
+#ifdef ENABLE_USB
+	for (i = 0 ; usb_exports[i].name != NULL; i++)
+		if (strcmp(usb_exports[i].name, name) == 0)
+			return (char *)usb_exports[i].func;
+#endif
+
+	for (i = 0; i < num_pe_exports; i++)
+		if (strcmp(pe_exports[i].name, name) == 0)
+			return (char *)pe_exports[i].addr;
+
+	return NULL;
+}
+#endif // TEST_LOADER
+
+static void *get_dll_init(char *name)
+{
+	int i;
+	for (i = 0; i < num_pe_exports; i++)
+		if ((strcmp(pe_exports[i].dll, name) == 0) &&
+		    (strcmp(pe_exports[i].name, "DllInitialize") == 0))
+			return (void *)pe_exports[i].addr;
+	return NULL;
+}
+
+/*
+ * Find and validate the coff header
+ *
+ */
+static int check_nt_hdr(IMAGE_NT_HEADERS *nt_hdr)
+{
+	int i;
+	WORD attr;
+	PIMAGE_OPTIONAL_HEADER opt_hdr;
+
+	/* Validate the "PE\0\0" signature */
+	if (nt_hdr->Signature != IMAGE_NT_SIGNATURE) {
+		ERROR("is this driver file? bad signature %08x",
+		      nt_hdr->Signature);
+		return -EINVAL;
+	}
+
+	opt_hdr = &nt_hdr->OptionalHeader;
+	/* Make sure Image is PE32 or PE32+ */
+#ifdef CONFIG_X86_64
+	if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+		ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
+		      "bad magic: %04X", opt_hdr->Magic);
+		return -EINVAL;
+	}
+#else
+	if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+		ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
+		      "bad magic: %04X", opt_hdr->Magic);
+		return -EINVAL;
+	}
+#endif
+
+	/* Validate the image for the current architecture. */
+#ifdef CONFIG_X86_64
+	if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
+		ERROR("kernel is 64-bit, but Windows driver is not 64-bit;"
+		      " (PE signature is %04X)", nt_hdr->FileHeader.Machine);
+		return -EINVAL;
+	}
+#else
+	if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
+		ERROR("kernel is 32-bit, but Windows driver is not 32-bit;"
+		      " (PE signature is %04X)", nt_hdr->FileHeader.Machine);
+		return -EINVAL;
+	}
+#endif
+
+	/* Must have attributes */
+#ifdef CONFIG_X86_64
+	attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE;
+#else
+	attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE;
+#endif
+	if ((nt_hdr->FileHeader.Characteristics & attr) != attr)
+		return -EINVAL;
+
+	/* Must be relocatable */
+	attr = IMAGE_FILE_RELOCS_STRIPPED;
+	if ((nt_hdr->FileHeader.Characteristics & attr))
+		return -EINVAL;
+
+	/* Make sure we have at least one section */
+	if (nt_hdr->FileHeader.NumberOfSections == 0)
+		return -EINVAL;
+
+	if (opt_hdr->SectionAlignment < opt_hdr->FileAlignment) {
+		ERROR("alignment mismatch: secion: 0x%x, file: 0x%x",
+		      opt_hdr->SectionAlignment, opt_hdr->FileAlignment);
+		return -EINVAL;
+	}
+
+	DBGLINKER("number of datadictionary entries %d",
+		  opt_hdr->NumberOfRvaAndSizes);
+	for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) {
+		DBGLINKER("datadirectory %s RVA:%X Size:%d",
+			  (i<=IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)?
+			  image_directory_name[i] : "unknown",
+			  opt_hdr->DataDirectory[i].VirtualAddress,
+			  opt_hdr->DataDirectory[i].Size);
+	}
+
+	if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
+		return IMAGE_FILE_EXECUTABLE_IMAGE;
+	if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_DLL))
+		return IMAGE_FILE_DLL;
+	return -EINVAL;
+}
+
+static int import(void *image, IMAGE_IMPORT_DESCRIPTOR *dirent, char *dll)
+{
+	ULONG_PTR *lookup_tbl, *address_tbl;
+	char *symname = NULL;
+	int i;
+	int ret = 0;
+	void *adr;
+
+	lookup_tbl  = RVA2VA(image, dirent->u.OriginalFirstThunk, ULONG_PTR *);
+	address_tbl = RVA2VA(image, dirent->FirstThunk, ULONG_PTR *);
+
+	for (i = 0; lookup_tbl[i]; i++) {
+		if (IMAGE_SNAP_BY_ORDINAL(lookup_tbl[i])) {
+			ERROR("ordinal import not supported: %Lu",
+			      (uint64_t)lookup_tbl[i]);
+			return -1;
+		}
+		else {
+			symname = RVA2VA(image,
+					 ((lookup_tbl[i] &
+					   ~IMAGE_ORDINAL_FLAG) + 2), char *);
+		}
+
+		adr = get_export(symname);
+		if (adr == NULL) {
+			ERROR("unknown symbol: %s:'%s'", dll, symname);
+			ret = -1;
+		} else {
+			DBGLINKER("found symbol: %s:%s: addr: %p, rva = %Lu",
+				  dll, symname, adr, (uint64_t)address_tbl[i]);
+			address_tbl[i] = (ULONG_PTR)adr;
+		}
+	}
+	return ret;
+}
+
+static int read_exports(struct pe_image *pe)
+{
+	IMAGE_EXPORT_DIRECTORY *export_dir_table;
+	uint32_t *export_addr_table;
+	int i;
+	uint32_t *name_table;
+	PIMAGE_OPTIONAL_HEADER opt_hdr;
+	IMAGE_DATA_DIRECTORY *export_data_dir;
+
+	opt_hdr = &pe->nt_hdr->OptionalHeader;
+	export_data_dir =
+		&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+
+	if (export_data_dir->Size == 0) {
+		DBGLINKER("no exports");
+		return 0;
+	}
+
+	export_dir_table =
+		RVA2VA(pe->image, export_data_dir->VirtualAddress,
+		       IMAGE_EXPORT_DIRECTORY *);
+
+	name_table = (unsigned int *)(pe->image +
+				      export_dir_table->AddressOfNames);
+	export_addr_table = (uint32_t *)
+		(pe->image + export_dir_table->AddressOfFunctions);
+
+	for (i = 0; i < export_dir_table->NumberOfNames; i++) {
+
+		if (export_data_dir->VirtualAddress <= *export_addr_table ||
+		    *export_addr_table >= (export_data_dir->VirtualAddress +
+					   export_data_dir->Size))
+			DBGLINKER("forwarder rva");
+
+		DBGLINKER("export symbol: %s, at %p",
+			  (char *)(pe->image + *name_table),
+			  pe->image + *export_addr_table);
+
+		pe_exports[num_pe_exports].dll = pe->name;
+		pe_exports[num_pe_exports].name = pe->image + *name_table;
+		pe_exports[num_pe_exports].addr =
+			pe->image + *export_addr_table;
+
+		num_pe_exports++;
+		name_table++;
+		export_addr_table++;
+	}
+	return 0;
+}
+
+static int fixup_imports(void *image, IMAGE_NT_HEADERS *nt_hdr)
+{
+	int i;
+	char *name;
+	int ret = 0;
+	IMAGE_IMPORT_DESCRIPTOR *dirent;
+	IMAGE_DATA_DIRECTORY *import_data_dir;
+	PIMAGE_OPTIONAL_HEADER opt_hdr;
+
+	opt_hdr = &nt_hdr->OptionalHeader;
+	import_data_dir =
+		&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+	dirent = RVA2VA(image, import_data_dir->VirtualAddress,
+			IMAGE_IMPORT_DESCRIPTOR *);
+
+	for (i = 0; dirent[i].Name; i++) {
+		name = RVA2VA(image, dirent[i].Name, char*);
+
+		DBGLINKER("imports from dll: %s", name);
+		ret += import(image, &dirent[i], name);
+	}
+	return ret;
+}
+
+static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr)
+{
+	ULONG_PTR base;
+	ULONG_PTR size;
+	IMAGE_BASE_RELOCATION *fixup_block;
+	IMAGE_DATA_DIRECTORY *base_reloc_data_dir;
+	PIMAGE_OPTIONAL_HEADER opt_hdr;
+
+	opt_hdr = &nt_hdr->OptionalHeader;
+	base = opt_hdr->ImageBase;
+	base_reloc_data_dir =
+		&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+	if (base_reloc_data_dir->Size == 0)
+		return 0;
+
+	fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress,
+			     IMAGE_BASE_RELOCATION *);
+	DBGLINKER("fixup_block=%p, image=%p", fixup_block, image);
+	DBGLINKER("fixup_block info: %x %d",
+		  fixup_block->VirtualAddress, fixup_block->SizeOfBlock);
+
+	while (fixup_block->SizeOfBlock) {
+		int i;
+		WORD fixup, offset;
+
+		size = (fixup_block->SizeOfBlock -
+			sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
+		DBGLINKER("found %Lu relocations in this block",
+			  (uint64_t)size);
+
+		for (i = 0; i < size; i++) {
+			fixup = fixup_block->TypeOffset[i];
+			offset = fixup & 0xfff;
+			switch ((fixup >> 12) & 0x0f) {
+			case IMAGE_REL_BASED_ABSOLUTE:
+				break;
+
+			case IMAGE_REL_BASED_HIGHLOW: {
+				uint32_t addr;
+				uint32_t *loc =
+					RVA2VA(image,
+					       fixup_block->VirtualAddress +
+					       offset, uint32_t *);
+				addr = RVA2VA(image, (*loc - base), uint32_t);
+				DBGLINKER("relocation: *%p (Val:%X)= %X",
+					  loc, *loc, addr);
+				*loc = addr;
+			}
+				break;
+
+			case IMAGE_REL_BASED_DIR64: {
+				uint64_t addr;
+				uint64_t *loc =
+					RVA2VA(image,
+					       fixup_block->VirtualAddress +
+					       offset, uint64_t *);
+				addr = RVA2VA(image, (*loc - base), uint64_t);
+				DBGLINKER("relocation: *%p (Val:%llX)= %llx",
+					  loc, *loc, addr);
+				*loc = addr;
+			}
+				break;
+
+			default:
+				ERROR("unknown fixup: %08X",
+				      (fixup >> 12) & 0x0f);
+				return -EOPNOTSUPP;
+				break;
+			}
+		}
+		DBGLINKER("finished relocating block");
+
+		fixup_block = (IMAGE_BASE_RELOCATION *)
+			((void *)fixup_block + fixup_block->SizeOfBlock);
+	};
+	DBGLINKER("done relocating all");
+
+	return 0;
+}
+
+/* Expand the image in memroy if necessary. The image on disk does not
+ * necessarily maps the image of the driver in memory, so we have to
+ * re-write it in order to fullfill the sections alignements. The
+ * advantage to do that is that rva_to_va becomes a simple
+ * addition. */
+static int fix_pe_image(struct pe_image *pe)
+{
+	void *image;
+	IMAGE_SECTION_HEADER *sect_hdr;
+	int i, sections;
+	int image_size;
+
+	if (pe->size == pe->opt_hdr->SizeOfImage) {
+		/* Nothing to do */
+		return 0;
+	}
+
+	image_size = pe->opt_hdr->SizeOfImage;
+#ifdef CONFIG_X86_64
+#ifdef PAGE_KERNEL_EXECUTABLE
+	image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
+			  PAGE_KERNEL_EXECUTABLE);
+#elif defined PAGE_KERNEL_EXEC
+	image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
+			  PAGE_KERNEL_EXEC);
+#else
+#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
+#endif
+#else
+#ifdef cpu_has_nx
+	/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
+	 * not available to modules! */
+	if (cpu_has_nx)
+		image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,
+				  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
+	else
+		image = vmalloc(image_size);
+#else
+		image = vmalloc(image_size);
+#endif
+#endif
+	if (image == NULL) {
+		ERROR("failed to allocate enough space for new image:"
+		      " %d bytes", image_size);
+		return -ENOMEM;
+	}
+
+	/* Copy all the headers, ie everything before the first section. */
+
+	sections = pe->nt_hdr->FileHeader.NumberOfSections;
+	sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr);
+
+	DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData);
+
+	memcpy(image, pe->image, sect_hdr->PointerToRawData);
+
+	/* Copy all the sections */
+	for (i = 0; i < sections; i++) {
+		DBGLINKER("Copy section %s from %x to %x",
+			  sect_hdr->Name, sect_hdr->PointerToRawData,
+			  sect_hdr->VirtualAddress);
+		if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData >
+		    image_size) {
+			ERROR("Invalid section %s in driver", sect_hdr->Name);
+			vfree(image);
+			return -EINVAL;
+		}
+
+		memcpy(image+sect_hdr->VirtualAddress,
+		       pe->image + sect_hdr->PointerToRawData,
+		       sect_hdr->SizeOfRawData);
+		sect_hdr++;
+	}
+
+	vfree(pe->image);
+	pe->image = image;
+	pe->size = image_size;
+
+	/* Update our internal pointers */
+	pe->nt_hdr = (IMAGE_NT_HEADERS *)
+		(pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew);
+	pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
+
+	DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",
+		  pe->nt_hdr, pe->opt_hdr, pe->image);
+
+	return 0;
+}
+
+#if defined(CONFIG_X86_64)
+static void fix_user_shared_data_addr(char *driver, unsigned long length)
+{
+	unsigned long i, n, max_addr, *addr;
+
+	n = length - sizeof(unsigned long);
+	max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
+	for (i = 0; i < n; i++) {
+		addr = (unsigned long *)(driver + i);
+		if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
+			*addr -= KI_USER_SHARED_DATA;
+			*addr += (unsigned long)&kuser_shared_data;
+			kuser_shared_data.reserved1 = 1;
+		}
+	}
+}
+#endif
+
+int link_pe_images(struct pe_image *pe_image, unsigned short n)
+{
+	int i;
+	struct pe_image *pe;
+
+#ifdef DEBUG
+	/* Sanity checkings */
+	CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER);
+	CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER);
+	CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
+	CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER +
+		 IMAGE_SIZEOF_NT_OPTIONAL_HEADER);
+	CHECK_SZ(IMAGE_DOS_HEADER, 0x40);
+	CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40);
+	CHECK_SZ(IMAGE_BASE_RELOCATION, 8);
+	CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20);
+#endif
+
+	for (i = 0; i < n; i++) {
+		IMAGE_DOS_HEADER *dos_hdr;
+		pe = &pe_image[i];
+		dos_hdr = pe->image;
+
+		if (pe->size < sizeof(IMAGE_DOS_HEADER)) {
+			TRACE1("image too small: %d", pe->size);
+			return -EINVAL;
+		}
+
+		pe->nt_hdr =
+			(IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew);
+		pe->opt_hdr = &pe->nt_hdr->OptionalHeader;
+
+		pe->type = check_nt_hdr(pe->nt_hdr);
+		if (pe->type <= 0) {
+			TRACE1("type <= 0");
+			return -EINVAL;
+		}
+
+		if (fix_pe_image(pe)) {
+			TRACE1("bad PE image");
+			return -EINVAL;
+		}
+
+		if (read_exports(pe)) {
+			TRACE1("read exports failed");
+			return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < n; i++) {
+	        pe = &pe_image[i];
+
+		if (fixup_reloc(pe->image, pe->nt_hdr)) {
+			TRACE1("fixup reloc failed");
+			return -EINVAL;
+		}
+		if (fixup_imports(pe->image, pe->nt_hdr)) {
+			TRACE1("fixup imports failed");
+			return -EINVAL;
+		}
+#if defined(CONFIG_X86_64)
+		INFO("fixing KI_USER_SHARED_DATA address in the driver");
+		fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size);
+#endif
+		flush_icache_range(pe->image, pe->size);
+
+		pe->entry =
+			RVA2VA(pe->image,
+			       pe->opt_hdr->AddressOfEntryPoint, void *);
+		TRACE1("entry is at %p, rva at %08X", pe->entry,
+		       pe->opt_hdr->AddressOfEntryPoint);
+	}
+
+	for (i = 0; i < n; i++) {
+	        pe = &pe_image[i];
+
+		if (pe->type == IMAGE_FILE_DLL) {
+			struct unicode_string ustring;
+			char *buf = "0/0t0m0p00";
+			int (*dll_entry)(struct unicode_string *ustring)
+				wstdcall;
+
+			memset(&ustring, 0, sizeof(ustring));
+			ustring.buf = (wchar_t *)buf;
+			dll_entry = (void *)get_dll_init(pe->name);
+
+			TRACE1("calling dll_init at %p", dll_entry);
+			if (!dll_entry || dll_entry(&ustring))
+				ERROR("DLL initialize failed for %s",
+				      pe->name);
+		}
+		else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE)
+			ERROR("illegal image type: %d", pe->type);
+	}
+	return 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ndis.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ndis.h
@@ -0,0 +1,1314 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _NDIS_H_
+#define _NDIS_H_
+
+#include "ntoskernel.h"
+
+//#define ALLOW_POOL_OVERFLOW 1
+
+#define NDIS_DMA_24BITS 0
+#define NDIS_DMA_32BITS 1
+#define NDIS_DMA_64BITS 2
+
+#ifdef CONFIG_X86_64
+#define MAXIMUM_PROCESSORS  64
+#else
+#define MAXIMUM_PROCESSORS  32
+#endif
+
+typedef UINT NDIS_STATUS;
+typedef UCHAR NDIS_DMA_SIZE;
+typedef LONG ndis_rssi;
+typedef ULONG ndis_key_index;
+typedef ULONG ndis_tx_power_level;
+typedef ULONGULONG ndis_key_rsc;
+typedef UCHAR ndis_rates[NDIS_MAX_RATES];
+typedef UCHAR ndis_rates_ex[NDIS_MAX_RATES_EX];
+typedef UCHAR mac_address[ETH_ALEN];
+typedef ULONG ndis_fragmentation_threshold;
+typedef ULONG ndis_rts_threshold;
+typedef ULONG ndis_antenna;
+typedef ULONG ndis_oid;
+
+typedef UCHAR ndis_pmkid_vavlue[16];
+
+typedef uint64_t NDIS_PHY_ADDRESS;
+
+struct ndis_sg_element {
+	PHYSICAL_ADDRESS address;
+	ULONG length;
+	ULONG_PTR reserved;
+};
+
+struct ndis_sg_list {
+	ULONG nent;
+	ULONG_PTR reserved;
+	struct ndis_sg_element elements[];
+};
+
+/* when sending packets, ndiswrapper associates exactly one sg element
+ * in sg list */
+struct wrap_tx_sg_list {
+	ULONG nent;
+	ULONG_PTR reserved;
+	struct ndis_sg_element elements[1];
+};
+
+struct ndis_phy_addr_unit {
+	NDIS_PHY_ADDRESS phy_addr;
+	UINT length;
+};
+
+typedef struct mdl ndis_buffer;
+
+struct ndis_buffer_pool {
+	ndis_buffer *free_descr;
+//	NT_SPIN_LOCK lock;
+	spinlock_t lock;
+	UINT max_descr;
+	UINT num_allocated_descr;
+};
+
+#define NDIS_PROTOCOL_ID_DEFAULT	0x00
+#define NDIS_PROTOCOL_ID_TCP_IP		0x02
+#define NDIS_PROTOCOL_ID_IPX		0x06
+#define NDIS_PROTOCOL_ID_NBF		0x07
+#define NDIS_PROTOCOL_ID_MAX		0x0F
+#define NDIS_PROTOCOL_ID_MASK		0x0F
+
+#define fPACKET_WRAPPER_RESERVED		0x3F
+#define fPACKET_CONTAINS_MEDIA_SPECIFIC_INFO	0x40
+#define fPACKET_ALLOCATED_BY_NDIS		0x80
+
+#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *))
+
+struct transport_header_offset {
+	USHORT protocol_type;
+	USHORT header_offset;
+};
+
+struct ndis_network_address {
+	USHORT length;
+	USHORT type;
+	UCHAR address[1];
+};
+
+struct ndis_network_address_list {
+	LONG count;
+	USHORT type;
+	struct ndis_network_address address[1];
+};
+
+struct ndis_tcp_ip_checksum_packet_info {
+	union {
+		struct {
+			ULONG v4:1;
+			ULONG v6:1;
+			ULONG tcp:1;
+			ULONG udp:1;
+			ULONG ip:1;
+		} tx;
+		struct {
+			ULONG tcp_failed:1;
+			ULONG udp_failed:1;
+			ULONG ip_failed:1;
+			ULONG tcp_succeeded:1;
+			ULONG udp_succeeded:1;
+			ULONG ip_succeeded:1;
+			ULONG loopback:1;
+		} rx;
+		ULONG value;
+	};
+};
+
+enum ndis_task {
+	TcpIpChecksumNdisTask, IpSecNdisTask, TcpLargeSendNdisTask, MaxNdisTask
+};
+
+enum ndis_encapsulation {
+	UNSPECIFIED_Encapsulation, NULL_Encapsulation,
+	IEEE_802_3_Encapsulation, IEEE_802_5_Encapsulation,
+	LLC_SNAP_ROUTED_Encapsulation, LLC_SNAP_BRIDGED_Encapsulation
+};
+
+#define NDIS_TASK_OFFLOAD_VERSION 1
+
+struct ndis_encapsulation_format {
+	enum ndis_encapsulation encap;
+	struct {
+		ULONG fixed_header_size:1;
+		ULONG reserved:31;
+	} flags;
+	ULONG header_size;
+};
+
+struct ndis_task_offload_header {
+	ULONG version;
+	ULONG size;
+	ULONG reserved;
+	ULONG offset_first_task;
+	struct ndis_encapsulation_format encap_format;
+};
+
+struct ndis_task_offload {
+	ULONG version;
+	ULONG size;
+	enum ndis_task task;
+	ULONG offset_next_task;
+	ULONG task_buf_length;
+	UCHAR task_buf[1];
+};
+
+struct v4_checksum {
+	union {
+		struct {
+			ULONG ip_opts:1;
+			ULONG tcp_opts:1;
+			ULONG tcp_csum:1;
+			ULONG udp_csum:1;
+			ULONG ip_csum:1;
+		};
+		ULONG value;
+	};
+};
+
+struct v6_checksum {
+	ULONG ip_supported:1;
+	ULONG tcp_supported:1;
+	ULONG tcp_csum:1;
+	ULONG udp_csum:1;
+};
+
+struct ndis_task_tcp_ip_checksum {
+	struct v4_checksum v4_tx;
+	struct v4_checksum v4_rx;
+	struct v6_checksum v6_tx;
+	struct v6_checksum v6_rx;
+};
+
+struct ndis_task_tcp_large_send {
+	ULONG version;
+	ULONG max_size;
+	ULONG min_seg_count;
+	BOOLEAN tcp_opts;
+	BOOLEAN ip_opts;
+};
+
+struct ndis_packet;
+
+struct ndis_packet_pool {
+	struct ndis_packet *free_descr;
+//	NT_SPIN_LOCK lock;
+	spinlock_t lock;
+	UINT max_descr;
+	UINT num_allocated_descr;
+	UINT num_used_descr;
+	UINT proto_rsvd_length;
+};
+
+struct ndis_packet_stack {
+	ULONG_PTR IM_reserved[2];
+	ULONG_PTR ndis_reserved[4];
+};
+
+enum ndis_per_packet_info {
+	TcpIpChecksumPacketInfo, IpSecPacketInfo, TcpLargeSendPacketInfo,
+	ClassificationHandlePacketInfo, NdisReserved,
+	ScatterGatherListPacketInfo, Ieee8021QInfo, OriginalPacketInfo,
+	PacketCancelId, MaxPerPacketInfo
+};
+
+struct ndis_packet_extension {
+	void *info[MaxPerPacketInfo];
+};
+
+struct ndis_packet_private {
+	UINT nr_pages;
+	UINT len;
+	ndis_buffer *buffer_head;
+	ndis_buffer *buffer_tail;
+	struct ndis_packet_pool *pool;
+	UINT count;
+	ULONG flags;
+	BOOLEAN valid_counts;
+	UCHAR packet_flags;
+	USHORT oob_offset;
+};
+
+struct ndis_packet {
+	struct ndis_packet_private private;
+	/* for use by miniport */
+	union {
+		/* for connectionless mininports */
+		struct {
+			UCHAR miniport_reserved[2 * sizeof(void *)];
+			UCHAR wrapper_reserved[2 * sizeof(void *)];
+		} cl_reserved;
+		/* for deserialized miniports */
+		struct {
+			UCHAR miniport_reserved_ex[3 * sizeof(void *)];
+			UCHAR wrapper_reserved_ex[sizeof(void *)];
+		} deserailized_reserved;
+		struct {
+			UCHAR mac_reserved[4 * sizeof(void *)];
+		} mac_reserved;
+	};
+	ULONG_PTR reserved[2];
+	UCHAR protocol_reserved[1];
+};
+
+/* OOB data */
+struct ndis_packet_oob_data {
+	union {
+		ULONGLONG time_to_tx;
+		ULONGLONG time_txed;
+	};
+	ULONGLONG time_rxed;
+	UINT header_size;
+	UINT media_size;
+	void *media;
+	NDIS_STATUS status;
+
+	/* ndiswrapper specific info; extension should be right after
+	 * ndis's oob_data */
+	struct ndis_packet_extension ext;
+	union {
+		/* used for tx only */
+		struct {
+			struct sk_buff *tx_skb;
+			union {
+				struct wrap_tx_sg_list wrap_tx_sg_list;
+				struct ndis_sg_list *tx_sg_list;
+			};
+		};
+		/* used for rx only */
+		struct {
+			unsigned char header[ETH_HLEN];
+			unsigned char *look_ahead;
+			UINT look_ahead_size;
+		};
+	};
+};
+
+#define NDIS_PACKET_OOB_DATA(packet)					\
+	(struct ndis_packet_oob_data *)(((void *)(packet)) +		\
+					(packet)->private.oob_offset)
+
+enum ndis_device_pnp_event {
+	NdisDevicePnPEventQueryRemoved, NdisDevicePnPEventRemoved,
+	NdisDevicePnPEventSurpriseRemoved, NdisDevicePnPEventQueryStopped,
+	NdisDevicePnPEventStopped, NdisDevicePnPEventPowerProfileChanged,
+	NdisDevicePnPEventMaximum
+};
+
+enum ndis_request_type {
+	NdisRequestQueryInformation, NdisRequestSetInformation,
+	NdisRequestQueryStatistics, NdisRequestOpen, NdisRequestClose,
+	NdisRequestSend, NdisRequestTransferData, NdisRequestReset,
+	NdisRequestGeneric1, NdisRequestGeneric2, NdisRequestGeneric3,
+	NdisRequestGeneric4
+};
+
+struct ndis_request {
+	mac_address mac;
+	enum ndis_request_type request_type;
+	union data {
+		struct query_info {
+			UINT oid;
+			void *buf;
+			UINT buf_len;
+			UINT written;
+			UINT needed;
+		} query_info;
+		struct set_info {
+			UINT oid;
+			void *buf;
+			UINT buf_len;
+			UINT written;
+			UINT needed;
+		} set_info;
+	} data;
+};
+
+enum ndis_medium {
+	NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan,
+	NdisMediumLocalTalk, NdisMediumDix, NdisMediumArcnetRaw,
+	NdisMediumArcnet878_2, NdisMediumAtm, NdisMediumWirelessWan,
+	NdisMediumIrda, NdisMediumBpc, NdisMediumCoWan,
+	NdisMedium1394, NdisMediumMax
+};
+
+enum ndis_physical_medium {
+	NdisPhysicalMediumUnspecified, NdisPhysicalMediumWirelessLan,
+	NdisPhysicalMediumCableModem, NdisPhysicalMediumPhoneLine,
+	NdisPhysicalMediumPowerLine, NdisPhysicalMediumDSL,
+	NdisPhysicalMediumFibreChannel, NdisPhysicalMedium1394,
+	NdisPhysicalMediumWirelessWan, NdisPhysicalMediumMax
+};
+
+enum ndis_power_state {
+	NdisDeviceStateUnspecified = 0,
+	NdisDeviceStateD0, NdisDeviceStateD1, NdisDeviceStateD2,
+	NdisDeviceStateD3, NdisDeviceStateMaximum
+};
+
+enum ndis_power_profile {
+	NdisPowerProfileBattery, NdisPowerProfileAcOnLine
+};
+
+struct ndis_pm_wakeup_capabilities {
+	enum ndis_power_state min_magic_packet_wakeup;
+	enum ndis_power_state min_pattern_wakeup;
+	enum ndis_power_state min_link_change_wakeup;
+};
+
+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET			0x00000001
+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH			0x00000002
+#define NDIS_PNP_WAKE_UP_LINK_CHANGE			0x00000004
+
+enum net_pnp_event_code {
+	NetEventSetPower, NetEventQueryPower, NetEventQueryRemoveDevice,
+	NetEventCancelRemoveDevice, NetEventReconfigure, NetEventBindList,
+	NetEventBindsComplete, NetEventPnPCapabilities, NetEventMaximum
+};
+
+struct net_pnp_event {
+	enum net_pnp_event_code code;
+	void *buf;
+	ULONG buf_length;
+	ULONG_PTR ndis_reserved[4];
+	ULONG_PTR transport_reserved[4];
+	ULONG_PTR tdi_reserved[4];
+	ULONG_PTR tdi_client_reserved[4];
+};
+
+struct ndis_pnp_capabilities {
+	ULONG flags;
+	struct ndis_pm_wakeup_capabilities wakeup;
+};
+
+typedef void (*ndis_isr_handler)(BOOLEAN *recognized, BOOLEAN *queue_handler,
+				 void *handle) wstdcall;
+typedef void (*ndis_interrupt_handler)(void *ctx) wstdcall;
+
+struct miniport {
+	/* NDIS 3.0 */
+	UCHAR major_version;
+	UCHAR minor_version;
+	USHORT filler;
+	UINT reserved;
+	BOOLEAN (*hangcheck)(void *ctx) wstdcall;
+	void (*disable_interrupt)(void *ctx) wstdcall;
+	void (*enable_interrupt)(void *ctx) wstdcall;
+	void (*mp_halt)(void *ctx) wstdcall;
+	ndis_interrupt_handler handle_interrupt;
+	NDIS_STATUS (*init)(NDIS_STATUS *error_status, UINT *medium_index,
+			    enum ndis_medium medium[], UINT medium_array_size,
+			    void *handle, void *conf_handle) wstdcall;
+	ndis_isr_handler isr;
+	NDIS_STATUS (*queryinfo)(void *ctx, ndis_oid oid, void *buffer,
+			     ULONG buflen, ULONG *written,
+			     ULONG *needed) wstdcall;
+	void *reconfig;
+	NDIS_STATUS (*reset)(BOOLEAN *reset_address, void *ctx) wstdcall;
+	NDIS_STATUS (*send)(void *ctx, struct ndis_packet *packet,
+			    UINT flags) wstdcall;
+	NDIS_STATUS (*setinfo)(void *ctx, ndis_oid oid, void *buffer,
+			       ULONG buflen, ULONG *written,
+			       ULONG *needed) wstdcall;
+	NDIS_STATUS (*tx_data)(struct ndis_packet *ndis_packet,
+			       UINT *bytes_txed, void *mp_ctx, void *rx_ctx,
+			       UINT offset, UINT bytes_to_tx) wstdcall;
+	/* NDIS 4.0 extensions */
+	void (*return_packet)(void *ctx, void *packet) wstdcall;
+	void (*send_packets)(void *ctx, struct ndis_packet **packets,
+			     INT nr_of_packets) wstdcall;
+	void (*alloc_complete)(void *handle, void *virt,
+			       NDIS_PHY_ADDRESS *phys,
+			       ULONG size, void *ctx) wstdcall;
+	/* NDIS 5.0 extensions */
+	NDIS_STATUS (*co_create_vc)(void *ctx, void *vc_handle,
+				    void *vc_ctx) wstdcall;
+	NDIS_STATUS (*co_delete_vc)(void *vc_ctx) wstdcall;
+	NDIS_STATUS (*co_activate_vc)(void *vc_ctx, void *call_params) wstdcall;
+	NDIS_STATUS (*co_deactivate_vc)(void *vc_ctx) wstdcall;
+	NDIS_STATUS (*co_send_packets)(void *vc_ctx, void **packets,
+				       UINT nr_of_packets) wstdcall;
+	NDIS_STATUS (*co_request)(void *ctx, void *vc_ctx, UINT *req) wstdcall;
+	/* NDIS 5.1 extensions */
+	void (*cancel_send_packets)(void *ctx, void *id) wstdcall;
+	void (*pnp_event_notify)(void *ctx, enum ndis_device_pnp_event event,
+				 void *inf_buf, ULONG inf_buf_len) wstdcall;
+	void (*shutdown)(void *ctx) wstdcall;
+	void *reserved1;
+	void *reserved2;
+	void *reserved3;
+	void *reserved4;
+};
+
+struct ndis_spinlock {
+	NT_SPIN_LOCK klock;
+	KIRQL irql;
+};
+
+union ndis_rw_lock_refcount {
+	UCHAR cache_line[16];
+};
+
+struct ndis_rw_lock {
+	union {
+		struct {
+			NT_SPIN_LOCK klock;
+			void *context;
+		};
+		UCHAR reserved[16];
+	};
+	union {
+		union ndis_rw_lock_refcount ref_count[MAXIMUM_PROCESSORS];
+		/* ndiswrapper specific */
+		volatile int count;
+	};
+};
+
+struct lock_state {
+	USHORT state;
+	KIRQL irql;
+};
+
+struct ndis_work_item;
+typedef void (*NDIS_PROC)(struct ndis_work_item *, void *) wstdcall;
+
+struct ndis_work_item {
+	void *ctx;
+	NDIS_PROC func;
+	union {
+		UCHAR reserved[8 * sizeof(void *)];
+		/* ndiswrapper specific */
+		struct nt_list list;
+	};
+};
+
+struct alloc_shared_mem {
+	void *ctx;
+	ULONG size;
+	BOOLEAN cached;
+};
+
+struct ndis_mp_block;
+
+/* this is opaque to drivers, so we can use it as we please */
+struct ndis_mp_interrupt {
+	struct kinterrupt *kinterrupt;
+	NT_SPIN_LOCK lock;
+	union {
+		void *reserved;
+		unsigned int irq;
+	};
+	ndis_isr_handler isr;
+	ndis_interrupt_handler mp_dpc;
+	struct kdpc intr_dpc;
+	struct ndis_mp_block *nmb;
+	UCHAR dpc_count;
+	BOOLEAN enable;
+	struct nt_event dpc_completed_event;
+	BOOLEAN shared;
+	BOOLEAN req_isr;
+};
+
+struct ndis_binary_data {
+	USHORT len;
+	void *buf;
+};
+
+enum ndis_parameter_type {
+	NdisParameterInteger, NdisParameterHexInteger,
+	NdisParameterString, NdisParameterMultiString, NdisParameterBinary,
+};
+
+typedef struct unicode_string NDIS_STRING;
+
+struct ndis_configuration_parameter {
+	enum ndis_parameter_type type;
+	union {
+		ULONG integer;
+		NDIS_STRING string;
+	} data;
+};
+
+struct ndis_driver {
+	struct miniport mp;
+};
+
+/* IDs used to store extensions in driver_object's custom extension */
+#define NDIS_DRIVER_CLIENT_ID 10
+
+struct ndis_wireless_stats {
+	ULONG length;
+	LARGE_INTEGER tx_frag;
+	LARGE_INTEGER tx_multi_frag;
+	LARGE_INTEGER failed;
+	LARGE_INTEGER retry;
+	LARGE_INTEGER multi_retry;
+	LARGE_INTEGER rtss_succ;
+	LARGE_INTEGER rtss_fail;
+	LARGE_INTEGER ack_fail;
+	LARGE_INTEGER frame_dup;
+	LARGE_INTEGER rx_frag;
+	LARGE_INTEGER rx_multi_frag;
+	LARGE_INTEGER fcs_err;
+	LARGE_INTEGER tkip_local_mic_failures;
+	LARGE_INTEGER tkip_icv_errors;
+	LARGE_INTEGER tkip_counter_measures_invoked;
+	LARGE_INTEGER tkip_replays;
+	LARGE_INTEGER ccmp_format_errors;
+	LARGE_INTEGER ccmp_replays;
+	LARGE_INTEGER ccmp_decrypt_errors;
+	LARGE_INTEGER fourway_handshake_failures;
+	LARGE_INTEGER wep_undecryptable_count;
+	LARGE_INTEGER wep_icv_errorcount;
+	LARGE_INTEGER decrypt_success_count;
+	LARGE_INTEGER decrypt_failure_count;
+};
+
+enum ndis_status_type {
+	Ndis802_11StatusType_Authentication,
+	Ndis802_11StatusType_MediaStreamMode,
+	Ndis802_11StatusType_PMKID_CandidateList,
+	Ndis802_11StatusType_RadioState,
+};
+
+struct ndis_status_indication {
+	enum ndis_status_type status_type;
+};
+
+enum ndis_radio_status {
+	Ndis802_11RadioStatusOn, Ndis802_11RadioStatusHardwareOff,
+	Ndis802_11RadioStatusSoftwareOff,
+};
+
+struct ndis_radio_status_indication
+{
+	enum ndis_status_type status_type;
+	enum ndis_radio_status radio_state;
+};
+
+enum ndis_media_state {
+	NdisMediaStateConnected,
+	NdisMediaStateDisconnected,
+};
+
+enum ndis_media_stream_mode {
+	Ndis802_11MediaStreamOff, Ndis802_11MediaStreamOn
+};
+
+enum wrapper_work {
+	LINK_STATUS_OFF, LINK_STATUS_ON, SET_MULTICAST_LIST, COLLECT_IW_STATS,
+	HANGCHECK, NETIF_WAKEQ,
+};
+
+struct encr_info {
+	struct encr_key {
+		ULONG length;
+		UCHAR key[NDIS_ENCODING_TOKEN_MAX];
+	} keys[MAX_ENCR_KEYS];
+	unsigned short tx_key_index;
+};
+
+struct ndis_essid {
+	ULONG length;
+	UCHAR essid[NDIS_ESSID_MAX_SIZE];
+};
+
+enum ndis_infrastructure_mode {
+	Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown,
+	Ndis802_11InfrastructureMax
+};
+
+enum authentication_mode {
+	Ndis802_11AuthModeOpen, Ndis802_11AuthModeShared,
+	Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA,
+	Ndis802_11AuthModeWPAPSK, Ndis802_11AuthModeWPANone,
+	Ndis802_11AuthModeWPA2, Ndis802_11AuthModeWPA2PSK,
+	Ndis802_11AuthModeMax
+};
+
+enum encryption_status {
+	Ndis802_11WEPEnabled,
+	Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+	Ndis802_11WEPDisabled,
+	Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+	Ndis802_11WEPKeyAbsent,
+	Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+	Ndis802_11WEPNotSupported,
+	Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+	Ndis802_11Encryption2Enabled, Ndis802_11Encryption2KeyAbsent,
+	Ndis802_11Encryption3Enabled, Ndis802_11Encryption3KeyAbsent
+};
+
+struct ndis_auth_encr_pair {
+	enum authentication_mode auth_mode;
+	enum encryption_status encr_mode;
+};
+
+struct ndis_capability {
+	ULONG length;
+	ULONG version;
+	ULONG num_PMKIDs;
+	ULONG num_auth_encr_pair;
+	struct ndis_auth_encr_pair auth_encr_pair[1];
+};
+
+struct ndis_guid {
+	struct guid guid;
+	union {
+		ndis_oid oid;
+		NDIS_STATUS status;
+	};
+	ULONG size;
+	ULONG flags;
+};
+
+struct ndis_timer {
+	struct nt_timer nt_timer;
+	struct kdpc kdpc;
+};
+
+struct ndis_mp_timer {
+	struct nt_timer nt_timer;
+	struct kdpc kdpc;
+	DPC func;
+	void *ctx;
+	struct ndis_mp_block *nmb;
+	struct ndis_mp_timer *next;
+};
+
+typedef struct cm_partial_resource_list NDIS_RESOURCE_LIST;
+
+struct ndis_event {
+	struct nt_event nt_event;
+};
+
+struct ndis_bind_paths {
+	UINT number;
+	struct unicode_string paths[1];
+};
+
+struct ndis_reference {
+	NT_SPIN_LOCK lock;
+	USHORT ref_count;
+	BOOLEAN closing;
+};
+
+struct ndis_filterdbs {
+	union {
+		void *eth_db;
+		void *null_db;
+	};
+	void *tr_db;
+	void *fddi_db;
+	void *arc_db;
+};
+
+enum ndis_interface_type {
+	NdisInterfaceInternal, NdisInterfaceIsa, NdisInterfaceEisa,
+	NdisInterfaceMca, NdisInterfaceTurboChannel, NdisInterfacePci,
+	NdisInterfacePcMcia,
+};
+
+struct auth_encr_capa {
+	unsigned long auth;
+	unsigned long encr;
+};
+
+struct ndis_pmkid_candidate {
+	mac_address bssid;
+	DWORD flags;
+};
+
+struct ndis_pmkid_candidate_list {
+	ULONG version;
+	ULONG num_candidates;
+	struct ndis_pmkid_candidate candidates[1];
+};
+
+/*
+ * This struct contains function pointers that the drivers references
+ * directly via macros, so it's important that they are at the correct
+ * position.
+ */
+struct ndis_mp_block {
+	void *signature;
+	struct ndis_mp_block *next;
+	struct driver_object *drv_obj;
+	void *mp_ctx;
+	struct unicode_string name;
+	struct ndis_bind_paths *bindpaths;
+	void *openqueue;
+	struct ndis_reference reference;
+	void *device_ctx;
+	UCHAR padding;
+	UCHAR lock_acquired;
+	UCHAR pmode_opens;
+	UCHAR assigned_cpu;
+	NT_SPIN_LOCK lock;
+	enum ndis_request_type *mediarequest;
+	struct ndis_mp_interrupt *interrupt;
+	ULONG flags;
+	ULONG pnp_flags;
+	struct nt_list packet_list;
+	struct ndis_packet *first_pending_tx_packet;
+	struct ndis_packet *return_packet_queue;
+	ULONG request_buffer;
+	void *set_mcast_buffer;
+	struct ndis_mp_block *primary_mp;
+	void *wrapper_ctx;
+	void *bus_data_ctx;
+	ULONG pnp_capa;
+	void *resources;
+	struct ndis_timer wakeup_dpc_timer;
+	struct unicode_string basename;
+	struct unicode_string symlink_name;
+	ULONG ndis_hangcheck_interval;
+	USHORT hanghcheck_ticks;
+	USHORT hangcheck_tick;
+	NDIS_STATUS ndis_reset_status;
+	void *resetopen;
+	struct ndis_filterdbs filterdbs;
+	void *rx_packet;
+	void *send_complete;
+	void *send_resource_avail;
+	void *reset_complete;
+
+	enum ndis_medium media_type;
+	ULONG bus_number;
+	enum ndis_interface_type bus_type;
+	enum ndis_interface_type adapter_type;
+	struct device_object *fdo;
+	struct device_object *pdo;
+	struct device_object *next_device;
+	void *mapreg;
+	void *call_mgraflist;
+	void *mp_thread;
+	void *setinfobuf;
+	USHORT setinfo_buf_len;
+	USHORT max_send_pkts;
+	NDIS_STATUS fake_status;
+	void *lock_handler;
+	struct unicode_string *adapter_instance_name;
+	void *timer_queue;
+	UINT mac_options;
+	void *pending_req;
+	UINT max_long_addrs;
+	UINT max_short_addrs;
+	UINT cur_lookahead;
+	UINT max_lookahead;
+
+	ndis_interrupt_handler irq_bh;
+	void *disable_intr;
+	void *enable_intr;
+	void *send_pkts;
+	void *deferred_send;
+	void *eth_rx_indicate;
+	void *tr_rx_indicate;
+	void *fddi_rx_indicate;
+	void *eth_rx_complete;
+	void *tr_rx_complete;
+	void *fddi_rx_complete;
+
+	void *status;
+	void *status_complete;
+	void *td_complete;
+
+	void *queryinfo_complete;
+	void *setinfo_complete;
+	void *wan_tx_complete;
+	void *wan_rx;
+	void *wan_rx_complete;
+	/* ndiswrapper specific */
+	struct ndis_device *wnd;
+};
+
+struct ndis_device {
+	struct ndis_mp_block *nmb;
+	struct wrap_device *wd;
+	struct net_device *net_dev;
+	void *shutdown_ctx;
+	struct ndis_mp_interrupt *mp_interrupt;
+	struct kdpc irq_kdpc;
+	unsigned long mem_start;
+	unsigned long mem_end;
+
+	struct net_device_stats net_stats;
+	struct iw_statistics iw_stats;
+	BOOLEAN iw_stats_enabled;
+	struct ndis_wireless_stats ndis_stats;
+
+	work_struct_t tx_work;
+	struct ndis_packet *tx_ring[TX_RING_SIZE];
+	u8 tx_ring_start;
+	u8 tx_ring_end;
+	u8 is_tx_ring_full;
+	u8 tx_ok;
+	spinlock_t tx_ring_lock;
+	struct semaphore tx_ring_mutex;
+	unsigned int max_tx_packets;
+	struct semaphore ndis_req_mutex;
+	struct task_struct *ndis_req_task;
+	int ndis_req_done;
+	NDIS_STATUS ndis_req_status;
+	ULONG packet_filter;
+
+	ULONG sg_dma_size;
+	ULONG dma_map_count;
+	dma_addr_t *dma_map_addr;
+
+	int hangcheck_interval;
+	struct timer_list hangcheck_timer;
+	int iw_stats_interval;
+	struct timer_list iw_stats_timer;
+	unsigned long scan_timestamp;
+	struct encr_info encr_info;
+	char nick[IW_ESSID_MAX_SIZE + 1];
+	struct ndis_essid essid;
+	struct auth_encr_capa capa;
+	enum ndis_infrastructure_mode infrastructure_mode;
+	int max_pmkids;
+	int num_pmkids;
+	struct ndis_pmkid *pmkids;
+	mac_address mac;
+	struct proc_dir_entry *procfs_iface;
+
+	work_struct_t ndis_work;
+	unsigned long ndis_pending_work;
+	UINT attributes;
+	int iw_auth_wpa_version;
+	int iw_auth_cipher_pairwise;
+	int iw_auth_cipher_group;
+	int iw_auth_key_mgmt;
+	int iw_auth_80211_alg;
+	struct ndis_packet_pool *tx_packet_pool;
+	struct ndis_buffer_pool *tx_buffer_pool;
+	int multicast_size;
+	struct v4_checksum rx_csum;
+	struct v4_checksum tx_csum;
+	enum ndis_physical_medium physical_medium;
+	ULONG ndis_wolopts;
+	struct nt_slist wrap_timer_slist;
+	int drv_ndis_version;
+	struct ndis_pnp_capabilities pnp_capa;
+	char netdev_name[IFNAMSIZ];
+};
+
+BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) wstdcall;
+
+int ndis_init(void);
+void ndis_exit(void);
+int ndis_init_device(struct ndis_device *wnd);
+void ndis_exit_device(struct ndis_device *wnd);
+
+int wrap_procfs_add_ndis_device(struct ndis_device *wnd);
+void wrap_procfs_remove_ndis_device(struct ndis_device *wnd);
+
+void NdisAllocatePacketPoolEx(NDIS_STATUS *status,
+			      struct ndis_packet_pool **pool_handle,
+			      UINT num_descr, UINT overflowsize,
+			      UINT proto_rsvd_length) wstdcall;
+void NdisFreePacketPool(struct ndis_packet_pool *pool) wstdcall;
+void NdisAllocatePacket(NDIS_STATUS *status, struct ndis_packet **packet,
+			struct ndis_packet_pool *pool) wstdcall;
+void NdisFreePacket(struct ndis_packet *descr) wstdcall;
+void NdisAllocateBufferPool(NDIS_STATUS *status,
+			    struct ndis_buffer_pool **pool_handle,
+			    UINT num_descr) wstdcall;
+void NdisFreeBufferPool(struct ndis_buffer_pool *pool) wstdcall;
+void NdisAllocateBuffer(NDIS_STATUS *status, ndis_buffer **buffer,
+			struct ndis_buffer_pool *pool, void *virt,
+			UINT length) wstdcall;
+void NdisFreeBuffer(ndis_buffer *descr) wstdcall;
+void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
+				struct ndis_packet **packets,
+				UINT nr_packets) wstdcall;
+void NdisMSendComplete(struct ndis_mp_block *nmb, struct ndis_packet *packet,
+		       NDIS_STATUS status) wstdcall;
+void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) wstdcall;
+void NdisMIndicateStatus(struct ndis_mp_block *nmb,
+			 NDIS_STATUS status, void *buf, UINT len) wstdcall;
+void NdisMIndicateStatusComplete(struct ndis_mp_block *nmb) wstdcall;
+void NdisMQueryInformationComplete(struct ndis_mp_block *nmb,
+				   NDIS_STATUS status) wstdcall;
+void NdisMSetInformationComplete(struct ndis_mp_block *nmb,
+				 NDIS_STATUS status) wstdcall;
+void NdisMResetComplete(struct ndis_mp_block *nmb, NDIS_STATUS status,
+			BOOLEAN address_reset) wstdcall;
+ULONG NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buffer) wstdcall;
+BOOLEAN NdisWaitEvent(struct ndis_event *event, UINT timeout) wstdcall;
+void NdisSetEvent(struct ndis_event *event) wstdcall;
+void NdisMDeregisterInterrupt(struct ndis_mp_interrupt *mp_interrupt) wstdcall;
+void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
+			  char *header1, char *header, UINT header_size,
+			  void *look_ahead, UINT look_ahead_size,
+			  UINT packet_size) wstdcall;
+void EthRxComplete(struct ndis_mp_block *nmb) wstdcall;
+void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
+			       struct ndis_packet *packet, NDIS_STATUS status,
+			       UINT bytes_txed) wstdcall;
+void NdisWriteConfiguration(NDIS_STATUS *status, struct ndis_mp_block *nmb,
+			    struct unicode_string *key,
+			    struct ndis_configuration_parameter *param) wstdcall;
+void NdisReadConfiguration(NDIS_STATUS *status,
+			   struct ndis_configuration_parameter **param,
+			   struct ndis_mp_block *nmb,
+			   struct unicode_string *key,
+			   enum ndis_parameter_type type) wstdcall;
+
+/* Required OIDs */
+#define OID_GEN_SUPPORTED_LIST			0x00010101
+#define OID_GEN_HARDWARE_STATUS			0x00010102
+#define OID_GEN_MEDIA_SUPPORTED			0x00010103
+#define OID_GEN_MEDIA_IN_USE			0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD		0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE		0x00010106
+#define OID_GEN_LINK_SPEED			0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE		0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE		0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE		0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE		0x0001010B
+#define OID_GEN_VENDOR_ID			0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION		0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER		0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD		0x0001010F
+#define OID_GEN_DRIVER_VERSION			0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE		0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS		0x00010112
+#define OID_GEN_MAC_OPTIONS			0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS		0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS		0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION		0x00010116
+#define OID_GEN_SUPPORTED_GUIDS			0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES		0x00010118	/* Set only */
+#define OID_GEN_TRANSPORT_HEADER_OFFSET		0x00010119	/* Set only */
+#define OID_GEN_MACHINE_NAME			0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER		0x0001021B	/* Set only */
+#define OID_GEN_VLAN_ID				0x0001021C
+
+/* Optional OIDs. */
+#define OID_GEN_MEDIA_CAPABILITIES		0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM			0x00010202
+
+/* Required statistics OIDs. */
+#define OID_GEN_XMIT_OK				0x00020101
+#define OID_GEN_RCV_OK				0x00020102
+#define OID_GEN_XMIT_ERROR			0x00020103
+#define OID_GEN_RCV_ERROR			0x00020104
+#define OID_GEN_RCV_NO_BUFFER			0x00020105
+
+/* Optional OID statistics */
+#define OID_GEN_DIRECTED_BYTES_XMIT		0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT		0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT		0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT		0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT		0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT		0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV		0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV		0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV		0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV		0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV		0x0002020C
+#define OID_GEN_RCV_CRC_ERROR			0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH		0x0002020E
+#define OID_GEN_GET_TIME_CAPS			0x0002020F
+#define OID_GEN_GET_NETCARD_TIME		0x00020210
+#define OID_GEN_NETCARD_LOAD			0x00020211
+#define OID_GEN_DEVICE_PROFILE			0x00020212
+
+/* 802.3 (ethernet) OIDs */
+#define OID_802_3_PERMANENT_ADDRESS		0x01010101
+#define OID_802_3_CURRENT_ADDRESS		0x01010102
+#define OID_802_3_MULTICAST_LIST		0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE		0x01010104
+#define OID_802_3_MAC_OPTIONS			0x01010105
+#define NDIS_802_3_MAC_OPTION_PRIORITY		0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT		0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION		0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS		0x01020103
+#define OID_802_3_XMIT_DEFERRED			0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS		0x01020202
+#define OID_802_3_RCV_OVERRUN			0x01020203
+#define OID_802_3_XMIT_UNDERRUN			0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE	0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST		0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS		0x01020207
+
+/* PnP and power management OIDs */
+#define OID_PNP_CAPABILITIES			0xFD010100
+#define OID_PNP_SET_POWER			0xFD010101
+#define OID_PNP_QUERY_POWER			0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN		0xFD010104
+#define OID_PNP_WAKE_UP_PATTERN_LIST		0xFD010105
+#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
+
+/* PnP/PM Statistics (Optional). */
+#define OID_PNP_WAKE_UP_OK			0xFD020200
+#define OID_PNP_WAKE_UP_ERROR			0xFD020201
+
+/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */
+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET		0x00000001
+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH		0x00000002
+#define NDIS_PNP_WAKE_UP_LINK_CHANGE		0x00000004
+
+/* 802.11 OIDs */
+#define OID_802_11_BSSID			0x0D010101
+#define OID_802_11_SSID				0x0D010102
+#define OID_802_11_NETWORK_TYPES_SUPPORTED	0x0D010203
+#define OID_802_11_NETWORK_TYPE_IN_USE		0x0D010204
+#define OID_802_11_TX_POWER_LEVEL		0x0D010205
+#define OID_802_11_RSSI				0x0D010206
+#define OID_802_11_RSSI_TRIGGER			0x0D010207
+#define OID_802_11_INFRASTRUCTURE_MODE		0x0D010108
+#define OID_802_11_FRAGMENTATION_THRESHOLD	0x0D010209
+#define OID_802_11_RTS_THRESHOLD		0x0D01020A
+#define OID_802_11_NUMBER_OF_ANTENNAS		0x0D01020B
+#define OID_802_11_RX_ANTENNA_SELECTED		0x0D01020C
+#define OID_802_11_TX_ANTENNA_SELECTED		0x0D01020D
+#define OID_802_11_SUPPORTED_RATES		0x0D01020E
+#define OID_802_11_DESIRED_RATES		0x0D010210
+#define OID_802_11_CONFIGURATION		0x0D010211
+#define OID_802_11_STATISTICS			0x0D020212
+#define OID_802_11_ADD_WEP			0x0D010113
+#define OID_802_11_REMOVE_WEP			0x0D010114
+#define OID_802_11_DISASSOCIATE			0x0D010115
+#define OID_802_11_POWER_MODE			0x0D010216
+#define OID_802_11_BSSID_LIST			0x0D010217
+#define OID_802_11_AUTHENTICATION_MODE		0x0D010118
+#define OID_802_11_PRIVACY_FILTER		0x0D010119
+#define OID_802_11_BSSID_LIST_SCAN		0x0D01011A
+#define OID_802_11_WEP_STATUS			0x0D01011B
+#define OID_802_11_ENCRYPTION_STATUS		OID_802_11_WEP_STATUS
+#define OID_802_11_RELOAD_DEFAULTS		0x0D01011C
+#define OID_802_11_ADD_KEY			0x0D01011D
+#define OID_802_11_REMOVE_KEY			0x0D01011E
+#define OID_802_11_ASSOCIATION_INFORMATION	0x0D01011F
+#define OID_802_11_TEST				0x0D010120
+#define OID_802_11_MEDIA_STREAM_MODE		0x0D010121
+#define OID_802_11_CAPABILITY			0x0D010122
+#define OID_802_11_PMKID			0x0D010123
+
+#define NDIS_STATUS_SUCCESS		0
+#define NDIS_STATUS_PENDING		0x00000103
+#define NDIS_STATUS_NOT_RECOGNIZED	0x00010001
+#define NDIS_STATUS_NOT_COPIED		0x00010002
+#define NDIS_STATUS_NOT_ACCEPTED	0x00010003
+#define NDIS_STATUS_CALL_ACTIVE		0x00010007
+#define NDIS_STATUS_ONLINE		0x40010003
+#define NDIS_STATUS_RESET_START		0x40010004
+#define NDIS_STATUS_RESET_END		0x40010005
+#define NDIS_STATUS_RING_STATUS		0x40010006
+#define NDIS_STATUS_CLOSED		0x40010007
+#define NDIS_STATUS_WAN_LINE_UP		0x40010008
+#define NDIS_STATUS_WAN_LINE_DOWN	0x40010009
+#define NDIS_STATUS_WAN_FRAGMENT	0x4001000A
+#define NDIS_STATUS_MEDIA_CONNECT	0x4001000B
+#define NDIS_STATUS_MEDIA_DISCONNECT	0x4001000C
+#define NDIS_STATUS_HARDWARE_LINE_UP	0x4001000D
+#define NDIS_STATUS_HARDWARE_LINE_DOWN	0x4001000E
+#define NDIS_STATUS_INTERFACE_UP	0x4001000F
+#define NDIS_STATUS_INTERFACE_DOWN	0x40010010
+#define NDIS_STATUS_MEDIA_BUSY		0x40010011
+#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION	0x40010012
+#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION
+#define NDIS_STATUS_LINK_SPEED_CHANGE	0x40010013
+#define NDIS_STATUS_WAN_GET_STATS	0x40010014
+#define NDIS_STATUS_WAN_CO_FRAGMENT	0x40010015
+#define NDIS_STATUS_WAN_CO_LINKPARAMS	0x40010016
+#define NDIS_STATUS_NOT_RESETTABLE	0x80010001
+#define NDIS_STATUS_SOFT_ERRORS		0x80010003
+#define NDIS_STATUS_HARD_ERRORS		0x80010004
+#define NDIS_STATUS_BUFFER_OVERFLOW	0x80000005
+#define NDIS_STATUS_FAILURE		0xC0000001
+#define NDIS_STATUS_INVALID_PARAMETER 0xC000000D
+#define NDIS_STATUS_RESOURCES		0xC000009A
+#define NDIS_STATUS_CLOSING		0xC0010002
+#define NDIS_STATUS_BAD_VERSION		0xC0010004
+#define NDIS_STATUS_BAD_CHARACTERISTICS	0xC0010005
+#define NDIS_STATUS_ADAPTER_NOT_FOUND	0xC0010006
+#define NDIS_STATUS_OPEN_FAILED		0xC0010007
+#define NDIS_STATUS_DEVICE_FAILED	0xC0010008
+#define NDIS_STATUS_MULTICAST_FULL	0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS	0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND	0xC001000B
+#define NDIS_STATUS_REQUEST_ABORTED	0xC001000C
+#define NDIS_STATUS_RESET_IN_PROGRESS	0xC001000D
+#define NDIS_STATUS_CLOSING_INDICATING	0xC001000E
+#define NDIS_STATUS_BAD_VERSION		0xC0010004
+#define NDIS_STATUS_NOT_SUPPORTED	0xC00000BB
+#define NDIS_STATUS_INVALID_PACKET	0xC001000F
+#define NDIS_STATUS_OPEN_LIST_FULL	0xC0010010
+#define NDIS_STATUS_ADAPTER_NOT_READY	0xC0010011
+#define NDIS_STATUS_ADAPTER_NOT_OPEN	0xC0010012
+#define NDIS_STATUS_NOT_INDICATING	0xC0010013
+#define NDIS_STATUS_INVALID_LENGTH	0xC0010014
+#define NDIS_STATUS_INVALID_DATA	0xC0010015
+#define NDIS_STATUS_BUFFER_TOO_SHORT	0xC0010016
+#define NDIS_STATUS_INVALID_OID		0xC0010017
+#define NDIS_STATUS_ADAPTER_REMOVED	0xC0010018
+#define NDIS_STATUS_UNSUPPORTED_MEDIA	0xC0010019
+#define NDIS_STATUS_GROUP_ADDRESS_IN_USE	0xC001001A
+#define NDIS_STATUS_FILE_NOT_FOUND	0xC001001B
+#define NDIS_STATUS_ERROR_READING_FILE	0xC001001C
+#define NDIS_STATUS_ALREADY_MAPPED	0xC001001D
+#define NDIS_STATUS_RESOURCE_CONFLICT	0xC001001E
+#define NDIS_STATUS_NO_CABLE		0xC001001F
+#define NDIS_STATUS_INVALID_SAP		0xC0010020
+#define NDIS_STATUS_SAP_IN_USE		0xC0010021
+#define NDIS_STATUS_INVALID_ADDRESS	0xC0010022
+#define NDIS_STATUS_VC_NOT_ACTIVATED	0xC0010023
+#define NDIS_STATUS_DEST_OUT_OF_ORDER	0xC0010024
+#define NDIS_STATUS_VC_NOT_AVAILABLE	0xC0010025
+#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE	0xC0010026
+#define NDIS_STATUS_INCOMPATABLE_QOS	0xC0010027
+#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED	0xC0010028
+#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION	0xC0010029
+#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR	0xC0011000
+#define NDIS_STATUS_INVALID_DEVICE_REQUEST	0xC0000010
+#define NDIS_STATUS_NETWORK_UNREACHABLE         0xC000023C
+
+/* Event codes */
+
+#define EVENT_NDIS_RESOURCE_CONFLICT	0xC0001388
+#define EVENT_NDIS_OUT_OF_RESOURCE	0xC0001389
+#define EVENT_NDIS_HARDWARE_FAILURE	0xC000138A
+#define EVENT_NDIS_ADAPTER_NOT_FOUND	0xC000138B
+#define EVENT_NDIS_INTERRUPT_CONNECT	0xC000138C
+#define EVENT_NDIS_DRIVER_FAILURE	0xC000138D
+#define EVENT_NDIS_BAD_VERSION		0xC000138E
+#define EVENT_NDIS_TIMEOUT		0x8000138F
+#define EVENT_NDIS_NETWORK_ADDRESS	0xC0001390
+#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION	0xC0001391
+#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER	0xC0001392
+#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER	0xC0001393
+#define EVENT_NDIS_BAD_IO_BASE_ADDRESS	0xC0001394
+#define EVENT_NDIS_RECEIVE_SPACE_SMALL	0x40001395
+#define EVENT_NDIS_ADAPTER_DISABLED	0x80001396
+#define EVENT_NDIS_IO_PORT_CONFLICT	0x80001397
+#define EVENT_NDIS_PORT_OR_DMA_CONFLICT	0x80001398
+#define EVENT_NDIS_MEMORY_CONFLICT	0x80001399
+#define EVENT_NDIS_INTERRUPT_CONFLICT	0x8000139A
+#define EVENT_NDIS_DMA_CONFLICT		0x8000139B
+#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR	0xC000139C
+#define EVENT_NDIS_MAXRECEIVES_ERROR	0x8000139D
+#define EVENT_NDIS_MAXTRANSMITS_ERROR	0x8000139E
+#define EVENT_NDIS_MAXFRAMESIZE_ERROR	0x8000139F
+#define EVENT_NDIS_MAXINTERNALBUFS_ERROR	0x800013A0
+#define EVENT_NDIS_MAXMULTICAST_ERROR	0x800013A1
+#define EVENT_NDIS_PRODUCTID_ERROR	0x800013A2
+#define EVENT_NDIS_LOBE_FAILUE_ERROR	0x800013A3
+#define EVENT_NDIS_SIGNAL_LOSS_ERROR	0x800013A4
+#define EVENT_NDIS_REMOVE_RECEIVED_ERROR	0x800013A5
+#define EVENT_NDIS_TOKEN_RING_CORRECTION	0x400013A6
+#define EVENT_NDIS_ADAPTER_CHECK_ERROR	0xC00013A7
+#define EVENT_NDIS_RESET_FAILURE_ERROR	0x800013A8
+#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR	0x800013A9
+#define EVENT_NDIS_RESET_FAILURE_CORRECTION	0x800013AA
+
+/* packet filter bits used by NDIS_OID_PACKET_FILTER */
+#define NDIS_PACKET_TYPE_DIRECTED               0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST              0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST          0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST              0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING         0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS            0x00000020
+#define NDIS_PACKET_TYPE_SMT                    0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL              0x00000080
+#define NDIS_PACKET_TYPE_GROUP                  0x00001000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL         0x00002000
+#define NDIS_PACKET_TYPE_FUNCTIONAL             0x00004000
+#define NDIS_PACKET_TYPE_MAC_FRAME              0x00008000
+
+/* memory allocation flags */
+#define NDIS_MEMORY_CONTIGUOUS			0x00000001
+#define NDIS_MEMORY_NONCACHED			0x00000002
+
+/* Atrribute flags to NdisMSetAtrributesEx */
+#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT    0x00000001
+#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT   0x00000002
+#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004
+#define NDIS_ATTRIBUTE_BUS_MASTER               0x00000008
+#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER      0x00000010
+#define NDIS_ATTRIBUTE_DESERIALIZE              0x00000020
+#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND       0x00000040
+#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK       0x00000080
+#define NDIS_ATTRIBUTE_NOT_CO_NDIS              0x00000100
+#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS    0x00000200
+
+#define OID_TCP_TASK_OFFLOAD			0xFC010201
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA	0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED	0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND	0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK		0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX		0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION		0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY		0x00000040
+#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE	0x00000080
+#define NDIS_MAC_OPTION_RECEIVE_AT_DPC		0x00000100
+#define NDIS_MAC_OPTION_8021Q_VLAN		0x00000200
+#define NDIS_MAC_OPTION_RESERVED		0x80000000
+
+#define deserialized_driver(wnd) (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE)
+
+static inline void serialize_lock(struct ndis_device *wnd)
+{
+	nt_spin_lock(&wnd->nmb->lock);
+}
+
+static inline void serialize_unlock(struct ndis_device *wnd)
+{
+	nt_spin_unlock(&wnd->nmb->lock);
+}
+
+static inline KIRQL serialize_lock_irql(struct ndis_device *wnd)
+{
+	if (deserialized_driver(wnd))
+		return raise_irql(DISPATCH_LEVEL);
+	else
+		return nt_spin_lock_irql(&wnd->nmb->lock, DISPATCH_LEVEL);
+}
+
+static inline void serialize_unlock_irql(struct ndis_device *wnd,
+					 KIRQL irql)
+{
+	if (deserialized_driver(wnd))
+		lower_irql(irql);
+	else
+		nt_spin_unlock_irql(&wnd->nmb->lock, irql);
+}
+
+static inline void if_serialize_lock(struct ndis_device *wnd)
+{
+	if (!deserialized_driver(wnd))
+		nt_spin_lock(&wnd->nmb->lock);
+}
+
+static inline void if_serialize_unlock(struct ndis_device *wnd)
+{
+	if (!deserialized_driver(wnd))
+		nt_spin_unlock(&wnd->nmb->lock);
+}
+
+#endif /* NDIS_H */
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/mkstubs.sh
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/mkstubs.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+for file in "$@"; do
+	echo
+	echo "# automatically generated from $file"
+	sed -n \
+		-e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/\
+		   win2lin(\1, \2)/p'   \
+		-e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/\
+		   win2lin(\1, \2)/p'   \
+	   $file | sed -e 's/[ \t	]\+//' | sort -u; \
+done
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/crt.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/crt.c
@@ -0,0 +1,578 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ntoskernel.h"
+#include "crt_exports.h"
+
+#ifdef CONFIG_X86_64
+/* Windows long is 32-bit, so strip single 'l' in integer formats */
+static void strip_l_modifier(char *str)
+{
+	char *ptr = str;
+	int in_format = 0;
+	char *lptr = NULL;
+	char last = 0;
+	char *end_ptr;
+	char *wptr;
+
+	/* Replace single 'l' inside integer formats with '\0' */
+	for (ptr = str; *ptr; ptr++) {
+		if (!in_format) {
+			if (*ptr == '%')
+				in_format = 1;
+			last = *ptr;
+			continue;
+		}
+		switch (*ptr) {
+		case 'd':
+		case 'i':
+		case 'o':
+		case 'u':
+		case 'x':
+		case 'X':
+		case 'p':
+		case 'n':
+		case 'm':
+			if (lptr) {
+				*lptr = '\0';
+				lptr = NULL;
+			}
+			in_format = 0;
+			break;
+		case 'c':
+		case 'C':
+		case 's':
+		case 'S':
+		case 'f':
+		case 'e':
+		case 'E':
+		case 'g':
+		case 'G':
+		case 'a':
+		case 'A':
+			lptr = NULL;
+			in_format = 0;
+			break;
+		case '%':
+			lptr = NULL;
+			if (last == '%')
+				in_format = 0;
+			else
+				in_format = 1;	/* ignore previous junk */
+			break;
+		case 'l':
+			if (last == 'l')
+				lptr = NULL;
+			else
+				lptr = ptr;
+			break;
+		default:
+			break;
+		}
+		last = *ptr;
+	}
+
+	/* Purge zeroes from the resulting string */
+	end_ptr = ptr;
+	wptr = str;
+	for (ptr = str; ptr < end_ptr; ptr++)
+		if (*ptr != 0)
+			*(wptr++) = *ptr;
+	*wptr = 0;
+}
+
+/*
+ * va_list on x86_64 Linux is designed to allow passing arguments in registers
+ * even to variadic functions.  va_list is a structure holding pointers to the
+ * register save area, which holds the arguments passed in registers, and to
+ * the stack, which may have the arguments that did not fit the registers.
+ * va_list also holds offsets in the register save area for the next general
+ * purpose and floating point registers that the next va_arg() would fetch.
+ *
+ * Unlike Linux, the Windows va_list is just a pointer to the stack.  No
+ * arguments are passed in the registers.  That's why we construct the Linux
+ * va_list so that the register save area is never used.  For that goal, we set
+ * the offsets to the maximal allowed values, meaning that the arguments passed
+ * in the registers have been exhausted.  The values are 48 for general purpose
+ * registers (6 registers, 8 bytes each) and 304 for floating point registers
+ * (16 registers, 16 bytes each, on top of general purpose register).
+ */
+
+struct x86_64_va_list {
+	int gp_offset;
+	int fp_offset;
+	void *overflow_arg_area;
+	void *reg_save_area;
+};
+
+#define VA_LIST_DECL(_args) \
+	va_list _args##new; \
+	struct x86_64_va_list *_args##x;
+#define VA_LIST_PREP(_args) \
+do { \
+	_args##x = (struct x86_64_va_list *)&_args##new; \
+	_args##x->gp_offset = 6 * 8;		/* GP registers exhausted */ \
+	_args##x->fp_offset = 6 * 8 + 16 * 16;	/* FP registers exhausted */ \
+	_args##x->overflow_arg_area = (void *)_args; \
+	_args##x->reg_save_area = NULL; \
+} while (0)
+#define VA_LIST_CONV(_args) (_args##new)
+#define VA_LIST_FREE(_args)
+#define FMT_DECL(_fmt) \
+	char *_fmt##copy; \
+	int _fmt##len;
+#define FMT_PREP(_fmt) \
+do { \
+	_fmt##len = strlen(format) + 1; \
+	_fmt##copy = kmalloc(_fmt##len, GFP_KERNEL); \
+	if (_fmt##copy) { \
+		memcpy(_fmt##copy, format, _fmt##len); \
+		strip_l_modifier(_fmt##copy); \
+	} \
+} while (0)
+#define FMT_CONV(_fmt) (_fmt##copy ? _fmt##copy : format)
+#define FMT_FREE(_fmt) kfree(_fmt##copy)
+
+#else /* !CONFIG_X86_64 */
+
+#define VA_LIST_DECL(_args)
+#define VA_LIST_PREP(_args)
+#define VA_LIST_CONV(_args) (_args)
+#define VA_LIST_FREE(_args)
+#define FMT_DECL(_fmt)
+#define FMT_PREP(_fmt)
+#define FMT_CONV(_fmt) (format)
+#define FMT_FREE(_fmt)
+
+#endif /* !CONFIG_X86_64 */
+
+noregparm INT WIN_FUNC(_win_sprintf,12)
+	(char *buf, const char *format, ...)
+{
+	va_list args;
+	int res;
+	FMT_DECL(format)
+
+	FMT_PREP(format);
+	va_start(args, format);
+	res = vsprintf(buf, FMT_CONV(format), args);
+	va_end(args);
+	FMT_FREE(format);
+
+	TRACE2("buf: %p: %s", buf, buf);
+	return res;
+}
+
+noregparm INT WIN_FUNC(swprintf,12)
+	(wchar_t *buf, const wchar_t *format, ...)
+{
+	TODO();
+	EXIT2(return 0);
+}
+
+noregparm INT WIN_FUNC(_win_vsprintf,3)
+	(char *str, const char *format, va_list ap)
+{
+	INT i;
+	VA_LIST_DECL(ap)
+	FMT_DECL(format)
+
+	VA_LIST_PREP(ap);
+	FMT_PREP(format);
+
+	i = vsprintf(str, FMT_CONV(format), VA_LIST_CONV(ap));
+	TRACE2("str: %p: %s", str, str);
+
+	FMT_FREE(format);
+	VA_LIST_FREE(ap);
+	EXIT2(return i);
+}
+
+noregparm INT WIN_FUNC(_win_snprintf,12)
+	(char *buf, SIZE_T count, const char *format, ...)
+{
+	va_list args;
+	int res;
+	FMT_DECL(format)
+
+	FMT_PREP(format);
+	va_start(args, format);
+	res = vsnprintf(buf, count, FMT_CONV(format), args);
+	va_end(args);
+	TRACE2("buf: %p: %s", buf, buf);
+
+	FMT_FREE(format);
+	return res;
+}
+
+noregparm INT WIN_FUNC(_win__snprintf,12)
+	(char *buf, SIZE_T count, const char *format, ...)
+{
+	va_list args;
+	int res;
+	FMT_DECL(format)
+
+	FMT_PREP(format);
+	va_start(args, format);
+	res = vsnprintf(buf, count, FMT_CONV(format), args);
+	va_end(args);
+	TRACE2("buf: %p: %s", buf, buf);
+
+	FMT_FREE(format);
+	return res;
+}
+
+noregparm INT WIN_FUNC(_win_vsnprintf,4)
+	(char *str, SIZE_T size, const char *format, va_list ap)
+{
+	INT i;
+	VA_LIST_DECL(ap)
+	FMT_DECL(format)
+
+	VA_LIST_PREP(ap);
+	FMT_PREP(format);
+
+	i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
+	TRACE2("str: %p: %s", str, str);
+
+	FMT_FREE(format);
+	VA_LIST_FREE(ap);
+	EXIT2(return i);
+}
+
+noregparm INT WIN_FUNC(_win__vsnprintf,4)
+	(char *str, SIZE_T size, const char *format, va_list ap)
+{
+	INT i;
+	VA_LIST_DECL(ap)
+	FMT_DECL(format)
+
+	VA_LIST_PREP(ap);
+	FMT_PREP(format);
+
+	i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
+	TRACE2("str: %p: %s", str, str);
+
+	FMT_FREE(format);
+	VA_LIST_FREE(ap);
+	EXIT2(return i);
+}
+
+noregparm char *WIN_FUNC(_win_strncpy,3)
+	(char *dst, char *src, SIZE_T n)
+{
+	return strncpy(dst, src, n);
+}
+
+noregparm SIZE_T WIN_FUNC(_win_strlen,1)
+	(const char *s)
+{
+	return strlen(s);
+}
+
+noregparm INT WIN_FUNC(_win_strncmp,3)
+	(const char *s1, const char *s2, SIZE_T n)
+{
+	return strncmp(s1, s2, n);
+}
+
+noregparm INT WIN_FUNC(_win_strcmp,2)
+	(const char *s1, const char *s2)
+{
+	return strcmp(s1, s2);
+}
+
+noregparm INT WIN_FUNC(_win_stricmp,2)
+	(const char *s1, const char *s2)
+{
+	return stricmp(s1, s2);
+}
+
+noregparm char *WIN_FUNC(_win_strncat,3)
+	(char *dest, const char *src, SIZE_T n)
+{
+	return strncat(dest, src, n);
+}
+
+noregparm INT WIN_FUNC(_win_wcscmp,2)
+	(const wchar_t *s1, const wchar_t *s2)
+{
+	while (*s1 && *s1 == *s2) {
+		s1++;
+		s2++;
+	}
+	return *s1 - *s2;
+}
+
+noregparm INT WIN_FUNC(_win_wcsicmp,2)
+	(const wchar_t *s1, const wchar_t *s2)
+{
+	while (*s1 && tolower((char)*s1) == tolower((char)*s2)) {
+		s1++;
+		s2++;
+	}
+	return tolower((char)*s1) - tolower((char)*s2);
+}
+
+noregparm SIZE_T WIN_FUNC(_win_wcslen,1)
+	(const wchar_t *s)
+{
+	const wchar_t *t = s;
+	while (*t)
+		t++;
+	return t - s;
+}
+
+noregparm wchar_t *WIN_FUNC(_win_wcsncpy,3)
+	(wchar_t *dest, const wchar_t *src, SIZE_T n)
+{
+	const wchar_t *s;
+	wchar_t *d;
+	s = src + n;
+	d = dest;
+	while (src < s && (*d++ = *src++))
+		;
+	if (s > src)
+		memset(d, 0, (s - src) * sizeof(wchar_t));
+	return dest;
+}
+
+noregparm wchar_t *WIN_FUNC(_win_wcscpy,2)
+	(wchar_t *dest, const wchar_t *src)
+{
+	wchar_t *d = dest;
+	while ((*d++ = *src++))
+	       ;
+	return dest;
+}
+
+noregparm wchar_t *WIN_FUNC(_win_wcscat,2)
+	(wchar_t *dest, const wchar_t *src)
+{
+	wchar_t *d;
+	d = dest;
+	while (*d)
+		d++;
+	while ((*d++ = *src++))
+		;
+	return dest;
+}
+
+noregparm INT WIN_FUNC(_win_towupper,1)
+	(wchar_t c)
+{
+	return toupper(c);
+}
+
+noregparm INT WIN_FUNC(_win_towlower,1)
+	(wchar_t c)
+{
+	return tolower(c);
+}
+
+noregparm INT WIN_FUNC(_win_tolower,1)
+	(INT c)
+{
+	return tolower(c);
+}
+
+noregparm INT WIN_FUNC(_win_toupper,1)
+	(INT c)
+{
+	return toupper(c);
+}
+
+noregparm void *WIN_FUNC(_win_strcpy,2)
+	(void *to, const void *from)
+{
+	return strcpy(to, from);
+}
+
+noregparm char *WIN_FUNC(_win_strstr,2)
+	(const char *s1, const char *s2)
+{
+	return strstr(s1, s2);
+}
+
+noregparm char *WIN_FUNC(_win_strchr,2)
+	(const char *s, int c)
+{
+	return strchr(s, c);
+}
+
+noregparm char *WIN_FUNC(_win_strrchr,2)
+	(const char *s, int c)
+{
+	return strrchr(s, c);
+}
+
+noregparm void *WIN_FUNC(_win_memmove,3)
+	(void *to, void *from, SIZE_T count)
+{
+	return memmove(to, from, count);
+}
+
+noregparm void *WIN_FUNC(_win_memchr,3)
+	(const void *s, INT c, SIZE_T n)
+{
+	return memchr(s, c, n);
+}
+
+noregparm void *WIN_FUNC(_win_memcpy,3)
+	(void *to, const void *from, SIZE_T n)
+{
+	return memcpy(to, from, n);
+}
+
+noregparm void *WIN_FUNC(_win_memset,3)
+	(void *s, char c, SIZE_T count)
+{
+	return memset(s, c, count);
+}
+
+noregparm int WIN_FUNC(_win_memcmp,3)
+	(void *s1, void *s2, SIZE_T n)
+{
+	return memcmp(s1, s2, n);
+}
+
+noregparm void WIN_FUNC(_win_srand,1)
+	(UINT seed)
+{
+	net_srandom(seed);
+}
+
+noregparm int WIN_FUNC(rand,0)
+	(void)
+{
+	char buf[6];
+	int i, n;
+
+	get_random_bytes(buf, sizeof(buf));
+	for (n = i = 0; i < sizeof(buf) ; i++)
+		n += buf[i];
+	return n;
+}
+
+noregparm int WIN_FUNC(_win_atoi,1)
+	(const char *ptr)
+{
+	int i = simple_strtol(ptr, NULL, 10);
+	return i;
+}
+
+noregparm int WIN_FUNC(_win_isprint,1)
+	(int c)
+{
+	return isprint(c);
+}
+
+wstdcall s64 WIN_FUNC(_alldiv,2)
+	(s64 a, s64 b)
+{
+	return a / b;
+}
+
+wstdcall u64 WIN_FUNC(_aulldiv,2)
+	(u64 a, u64 b)
+{
+	return a / b;
+}
+
+wstdcall s64 WIN_FUNC(_allmul,2)
+	(s64 a, s64 b)
+{
+	return a * b;
+}
+
+wstdcall u64 WIN_FUNC(_aullmul,2)
+	(u64 a, u64 b)
+{
+	return a * b;
+}
+
+wstdcall s64 WIN_FUNC(_allrem,2)
+	(s64 a, s64 b)
+{
+	return a % b;
+}
+
+wstdcall u64 WIN_FUNC(_aullrem,2)
+	(u64 a, u64 b)
+{
+	return a % b;
+}
+
+__attribute__((regparm(3))) s64 WIN_FUNC(_allshl,2)
+	(s64 a, u8 b)
+{
+	return a << b;
+}
+
+__attribute__((regparm(3))) u64 WIN_FUNC(_aullshl,2)
+	(u64 a, u8 b)
+{
+	return a << b;
+}
+
+__attribute__((regparm(3))) s64 WIN_FUNC(_allshr,2)
+	(s64 a, u8 b)
+{
+	return a >> b;
+}
+
+__attribute__((regparm(3))) u64 WIN_FUNC(_aullshr,2)
+	(u64 a, u8 b)
+{
+	return a >> b;
+}
+
+int stricmp(const char *s1, const char *s2)
+{
+	while (*s1 && tolower(*s1) == tolower(*s2)) {
+		s1++;
+		s2++;
+	}
+	return *s1 - *s2;
+}
+
+void dump_bytes(const char *ctx, const u8 *from, int len)
+{
+	int i, j;
+	u8 *buf;
+
+	buf = kmalloc(len * 3 + 1, irql_gfp());
+	if (!buf) {
+		ERROR("couldn't allocate memory");
+		return;
+	}
+	for (i = j = 0; i < len; i++, j += 3) {
+		sprintf(&buf[j], "%02x ", from[i]);
+	}
+	buf[j] = 0;
+	printk(KERN_DEBUG "%s: %p: %s\n", ctx, from, buf);
+	kfree(buf);
+}
+
+int crt_init(void)
+{
+	return 0;
+}
+
+/* called when module is being removed */
+void crt_exit(void)
+{
+	EXIT4(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/pnp.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/pnp.c
@@ -0,0 +1,742 @@
+/*
+ *  Copyright (C) 2005 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "usb.h"
+#include "pnp.h"
+#include "wrapndis.h"
+#include "loader.h"
+
+/* Functions callable from the NDIS driver */
+wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo,
+					   struct irp *irp);
+wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp);
+wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp);
+
+static NTSTATUS start_pdo(struct device_object *pdo)
+{
+	int i, ret, count, resources_size;
+	struct wrap_device *wd;
+	struct pci_dev *pdev;
+	struct cm_partial_resource_descriptor *entry;
+	struct cm_partial_resource_list *partial_resource_list;
+
+	ENTER1("%p, %p", pdo, pdo->reserved);
+	wd = pdo->reserved;
+	if (ntoskernel_init_device(wd))
+		EXIT1(return STATUS_FAILURE);
+	if (wrap_is_usb_bus(wd->dev_bus)) {
+#ifdef ENABLE_USB
+		if (usb_init_device(wd)) {
+			ntoskernel_exit_device(wd);
+			EXIT1(return STATUS_FAILURE);
+		}
+#endif
+		EXIT1(return STATUS_SUCCESS);
+	}
+	if (!wrap_is_pci_bus(wd->dev_bus))
+		EXIT1(return STATUS_SUCCESS);
+	pdev = wd->pci.pdev;
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		ERROR("couldn't enable PCI device: %x", ret);
+		return STATUS_FAILURE;
+	}
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		ERROR("couldn't request PCI regions: %x", ret);
+		goto err_enable;
+	}
+	pci_set_power_state(pdev, PCI_D0);
+#ifdef CONFIG_X86_64
+	/* 64-bit broadcom driver doesn't work if DMA is allocated
+	 * from over 1GB */
+	if (wd->vendor == 0x14e4) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(30)) ||
+		    pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(30)))
+			WARNING("couldn't set DMA mask; this driver "
+				"may not work with more than 1GB RAM");
+	}
+#endif
+	/* IRQ resource entry is filled in from pdev, instead of
+	 * pci_resource macros */
+	for (i = count = 0; pci_resource_start(pdev, i); i++)
+		if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||
+		    (pci_resource_flags(pdev, i) & IORESOURCE_IO))
+			count++;
+	/* space for entry for IRQ is already in
+	 * cm_partial_resource_list */
+	resources_size = sizeof(struct cm_resource_list) +
+		sizeof(struct cm_partial_resource_descriptor) * count;
+	TRACE2("resources: %d, %d", count, resources_size);
+	wd->resource_list = kzalloc(resources_size, GFP_KERNEL);
+	if (!wd->resource_list) {
+		WARNING("couldn't allocate memory");
+		goto err_regions;
+	}
+	wd->resource_list->count = 1;
+	wd->resource_list->list[0].interface_type = PCIBus;
+	/* bus_number is not used by WDM drivers */
+	wd->resource_list->list[0].bus_number = pdev->bus->number;
+
+	partial_resource_list =
+		&wd->resource_list->list->partial_resource_list;
+	partial_resource_list->version = 1;
+	partial_resource_list->revision = 1;
+	partial_resource_list->count = count + 1;
+
+	for (i = count = 0; pci_resource_start(pdev, i); i++) {
+		entry = &partial_resource_list->partial_descriptors[count];
+		TRACE2("%d", count);
+		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
+			entry->type = CmResourceTypeMemory;
+			entry->flags = CM_RESOURCE_MEMORY_READ_WRITE;
+			entry->share = CmResourceShareDeviceExclusive;
+		} else if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+			entry->type = CmResourceTypePort;
+			entry->flags = CM_RESOURCE_PORT_IO;
+			entry->share = CmResourceShareDeviceExclusive;
+#if 0
+		} else if (pci_resource_flags(pdev, i) & IORESOURCE_DMA) {
+			/* it looks like no driver uses this resource */
+			typeof(pci_resource_flags(pdev, 0)) flags;
+			entry->type = CmResourceTypeDma;
+			flags = pci_resource_flags(pdev, i);
+			if (flags & IORESOURCE_DMA_TYPEA)
+				entry->flags |= CM_RESOURCE_DMA_TYPE_A;
+			else if (flags & IORESOURCE_DMA_TYPEB)
+				entry->flags |= CM_RESOURCE_DMA_TYPE_B;
+			else if (flags & IORESOURCE_DMA_TYPEF)
+				entry->flags |= CM_RESOURCE_DMA_TYPE_F;
+			if (flags & IORESOURCE_DMA_8BIT)
+				entry->flags |= CM_RESOURCE_DMA_8;
+			else if (flags & IORESOURCE_DMA_16BIT)
+				entry->flags |= CM_RESOURCE_DMA_16;
+			/* what about 32bit DMA? */
+			else if (flags & IORESOURCE_DMA_8AND16BIT)
+				entry->flags |= CM_RESOURCE_DMA_8_AND_16;
+			if (flags & IORESOURCE_DMA_MASTER)
+				entry->flags |= CM_RESOURCE_DMA_BUS_MASTER;
+			entry->u.dma.channel = pci_resource_start(pdev, i);
+			/* what should this be? */
+			entry->u.dma.port = 1;
+#endif
+		} else
+			continue;
+		/* TODO: Add other resource types? */
+		entry->u.generic.start =
+			(ULONG_PTR)pci_resource_start(pdev, i);
+		entry->u.generic.length = pci_resource_len(pdev, i);
+		count++;
+	}
+
+	/* put IRQ resource at the end */
+	entry = &partial_resource_list->partial_descriptors[count++];
+	entry->type = CmResourceTypeInterrupt;
+	entry->flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+	/* we assume all devices use shared IRQ */
+	entry->share = CmResourceShareShared;
+	/* as per documentation, interrupt level should be DIRQL, but
+	 * examples from DDK as well some drivers, such as AR5211,
+	 * RT8180L use interrupt level as interrupt vector also in
+	 * NdisMRegisterInterrupt */
+	entry->u.interrupt.level = pdev->irq;
+	entry->u.interrupt.vector = pdev->irq;
+	entry->u.interrupt.affinity = -1;
+
+	TRACE2("resource list count %d, irq: %d",
+	       partial_resource_list->count, pdev->irq);
+	pci_set_drvdata(pdev, wd);
+	EXIT1(return STATUS_SUCCESS);
+err_regions:
+	pci_release_regions(pdev);
+err_enable:
+	pci_disable_device(pdev);
+	wd->pci.pdev = NULL;
+	wd->pdo = NULL;
+	EXIT1(return STATUS_FAILURE);
+}
+
+static void remove_pdo(struct device_object *pdo)
+{
+	struct wrap_device *wd = pdo->reserved;
+
+	ntoskernel_exit_device(wd);
+	if (wrap_is_pci_bus(wd->dev_bus)) {
+		struct pci_dev *pdev = wd->pci.pdev;
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		wd->pci.pdev = NULL;
+		pci_set_drvdata(pdev, NULL);
+	} else if (wrap_is_usb_bus(wd->dev_bus)) {
+#ifdef ENABLE_USB
+		usb_exit_device(wd);
+#endif
+	}
+	if (wd->resource_list)
+		kfree(wd->resource_list);
+	wd->resource_list = NULL;
+	return;
+}
+
+static NTSTATUS IoSendIrpTopDev(struct device_object *dev_obj, ULONG major_fn,
+				ULONG minor_fn, struct io_stack_location *sl)
+{
+	NTSTATUS status;
+	struct nt_event event;
+	struct irp *irp;
+	struct io_stack_location *irp_sl;
+	struct device_object *top_dev = IoGetAttachedDeviceReference(dev_obj);
+
+	KeInitializeEvent(&event, NotificationEvent, FALSE);
+	irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, top_dev, NULL, 0, NULL,
+					   &event, NULL);
+	irp->io_status.status = STATUS_NOT_IMPLEMENTED;
+	irp->io_status.info = 0;
+	irp_sl = IoGetNextIrpStackLocation(irp);
+	if (sl)
+		memcpy(irp_sl, sl, sizeof(*irp_sl));
+	irp_sl->major_fn = major_fn;
+	irp_sl->minor_fn = minor_fn;
+	status = IoCallDriver(top_dev, irp);
+	if (status == STATUS_PENDING) {
+		KeWaitForSingleObject(&event, Executive, KernelMode,
+				      FALSE, NULL);
+		status = irp->io_status.status;
+	}
+	ObDereferenceObject(top_dev);
+	return status;
+}
+
+wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo,
+					   struct  irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	NTSTATUS status;
+
+	DUMP_IRP(irp);
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+#ifdef ENABLE_USB
+	status = wrap_submit_irp(pdo, irp);
+	IOTRACE("status: %08X", status);
+	if (status != STATUS_PENDING)
+		IoCompleteRequest(irp, IO_NO_INCREMENT);
+#else
+	status = irp->io_status.status = STATUS_NOT_IMPLEMENTED;
+	IoCompleteRequest(irp, IO_NO_INCREMENT);
+#endif
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(pdoDispatchDeviceControl,2)
+
+wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	struct wrap_device *wd;
+	NTSTATUS status;
+#ifdef ENABLE_USB
+	struct usbd_bus_interface_usbdi *usb_intf;
+#endif
+
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	TRACE2("%p %d:%d", pdo, irp_sl->major_fn, irp_sl->minor_fn);
+	wd = pdo->reserved;
+	switch (irp_sl->minor_fn) {
+	case IRP_MN_START_DEVICE:
+		status = start_pdo(pdo);
+		break;
+	case IRP_MN_QUERY_STOP_DEVICE:
+	case IRP_MN_STOP_DEVICE:
+	case IRP_MN_QUERY_REMOVE_DEVICE:
+		status = STATUS_SUCCESS;
+		break;
+	case IRP_MN_REMOVE_DEVICE:
+		remove_pdo(pdo);
+		status = STATUS_SUCCESS;
+		break;
+	case IRP_MN_QUERY_INTERFACE:
+#ifdef ENABLE_USB
+		if (!wrap_is_usb_bus(wd->dev_bus)) {
+			status = STATUS_NOT_IMPLEMENTED;
+			break;
+		}
+		TRACE2("type: %x, size: %d, version: %d",
+		       irp_sl->params.query_intf.type->data1,
+		       irp_sl->params.query_intf.size,
+		       irp_sl->params.query_intf.version);
+		usb_intf = (struct usbd_bus_interface_usbdi *)
+			irp_sl->params.query_intf.intf;
+		usb_intf->Context = wd;
+		usb_intf->InterfaceReference = USBD_InterfaceReference;
+		usb_intf->InterfaceDereference = USBD_InterfaceDereference;
+		usb_intf->GetUSBDIVersion = USBD_InterfaceGetUSBDIVersion;
+		usb_intf->QueryBusTime = USBD_InterfaceQueryBusTime;
+		usb_intf->SubmitIsoOutUrb = USBD_InterfaceSubmitIsoOutUrb;
+		usb_intf->QueryBusInformation =
+			USBD_InterfaceQueryBusInformation;
+		if (irp_sl->params.query_intf.version >=
+		    USB_BUSIF_USBDI_VERSION_1)
+			usb_intf->IsDeviceHighSpeed =
+				USBD_InterfaceIsDeviceHighSpeed;
+		if (irp_sl->params.query_intf.version >=
+		    USB_BUSIF_USBDI_VERSION_2)
+			usb_intf->LogEntry = USBD_InterfaceLogEntry;
+		status = STATUS_SUCCESS;
+#else
+		status = STATUS_NOT_IMPLEMENTED;
+#endif
+		break;
+	default:
+		TRACE2("fn %d not implemented", irp_sl->minor_fn);
+		status = STATUS_SUCCESS;
+		break;
+	}
+	irp->io_status.status = status;
+	TRACE2("status: %08X", status);
+	IoCompleteRequest(irp, IO_NO_INCREMENT);
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(pdoDispatchPnp,2)
+
+wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	struct wrap_device *wd;
+	union power_state power_state;
+	struct pci_dev *pdev;
+	NTSTATUS status;
+
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	wd = pdo->reserved;
+	TRACE2("pdo: %p, fn: %d:%d, wd: %p",
+	       pdo, irp_sl->major_fn, irp_sl->minor_fn, wd);
+	switch (irp_sl->minor_fn) {
+	case IRP_MN_WAIT_WAKE:
+		/* TODO: this is not complete/correct */
+		TRACE2("state: %d, completion: %p",
+			  irp_sl->params.power.state.system_state,
+			  irp_sl->completion_routine);
+		IoMarkIrpPending(irp);
+		status = STATUS_PENDING;
+		break;
+	case IRP_MN_SET_POWER:
+		power_state = irp_sl->params.power.state;
+		if (power_state.device_state == PowerDeviceD0) {
+			TRACE2("resuming %p", wd);
+			if (wrap_is_pci_bus(wd->dev_bus)) {
+				pdev = wd->pci.pdev;
+				pci_restore_state(pdev);
+				if (wd->pci.wake_state == PowerDeviceD3) {
+					pci_enable_wake(wd->pci.pdev,
+							PCI_D3hot, 0);
+					pci_enable_wake(wd->pci.pdev,
+							PCI_D3cold, 0);
+				}
+				pci_set_power_state(pdev, PCI_D0);
+			} else { // usb device
+#ifdef ENABLE_USB
+				wrap_resume_urbs(wd);
+#endif
+			}
+		} else {
+			TRACE2("suspending device %p", wd);
+			if (wrap_is_pci_bus(wd->dev_bus)) {
+				pdev = wd->pci.pdev;
+				pci_save_state(pdev);
+				TRACE2("%d", wd->pci.wake_state);
+				if (wd->pci.wake_state == PowerDeviceD3) {
+					pci_enable_wake(wd->pci.pdev,
+							PCI_D3hot, 1);
+					pci_enable_wake(wd->pci.pdev,
+							PCI_D3cold, 1);
+				}
+				pci_set_power_state(pdev, PCI_D3hot);
+			} else { // usb device
+#ifdef ENABLE_USB
+				wrap_suspend_urbs(wd);
+#endif
+			}
+		}
+		status = STATUS_SUCCESS;
+		break;
+	case IRP_MN_QUERY_POWER:
+		status = STATUS_SUCCESS;
+		break;
+	default:
+		TRACE2("fn %d not implemented", irp_sl->minor_fn);
+		status = STATUS_SUCCESS;
+		break;
+	}
+	irp->io_status.status = status;
+	IoCompleteRequest(irp, IO_NO_INCREMENT);
+	return status;
+}
+WIN_FUNC_DECL(pdoDispatchPower,2)
+
+static NTSTATUS pnp_set_device_power_state(struct wrap_device *wd,
+					   enum device_power_state state)
+{
+	NTSTATUS status;
+	struct device_object *pdo;
+	struct io_stack_location irp_sl;
+
+	pdo = wd->pdo;
+	IOTRACE("%p, %p", pdo, IoGetAttachedDevice(pdo));
+	memset(&irp_sl, 0, sizeof(irp_sl));
+	irp_sl.params.power.state.device_state = state;
+	irp_sl.params.power.type = DevicePowerState;
+	if (state > PowerDeviceD0) {
+		status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_QUERY_POWER,
+					 &irp_sl);
+		if (status != STATUS_SUCCESS) {
+			TRACE1("query of power to %d returns %08X",
+			       state, status);
+			EXIT1(return status);
+		}
+	}
+	status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_SET_POWER, &irp_sl);
+	if (status != STATUS_SUCCESS)
+		WARNING("setting power to %d failed: %08X", state, status);
+	EXIT1(return status);
+}
+
+NTSTATUS pnp_start_device(struct wrap_device *wd)
+{
+	struct device_object *fdo;
+	struct device_object *pdo;
+	struct io_stack_location irp_sl;
+	NTSTATUS status;
+
+	pdo = wd->pdo;
+	/* TODO: for now we use same resources for both translated
+	 * resources and raw resources */
+	memset(&irp_sl, 0, sizeof(irp_sl));
+	irp_sl.params.start_device.allocated_resources =
+		wd->resource_list;
+	irp_sl.params.start_device.allocated_resources_translated =
+		wd->resource_list;
+	status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_START_DEVICE, &irp_sl);
+	fdo = IoGetAttachedDevice(pdo);
+	if (status == STATUS_SUCCESS)
+		fdo->drv_obj->drv_ext->count++;
+	else
+		WARNING("Windows driver couldn't initialize the device (%08X)",
+			status);
+	EXIT1(return status);
+}
+
+NTSTATUS pnp_stop_device(struct wrap_device *wd)
+{
+	struct device_object *pdo;
+	NTSTATUS status;
+
+	pdo = wd->pdo;
+	status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE,
+				 NULL);
+	if (status != STATUS_SUCCESS)
+		WARNING("status: %08X", status);
+	/* for now we ignore query status */
+	status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_STOP_DEVICE, NULL);
+	if (status != STATUS_SUCCESS)
+		WARNING("status: %08X", status);
+	if (status != STATUS_SUCCESS)
+		WARNING("status: %08X", status);
+	EXIT2(return status);
+}
+
+NTSTATUS pnp_remove_device(struct wrap_device *wd)
+{
+	struct device_object *pdo, *fdo;
+	struct driver_object *fdo_drv_obj;
+	NTSTATUS status;
+
+	pdo = wd->pdo;
+	fdo = IoGetAttachedDevice(pdo);
+	fdo_drv_obj = fdo->drv_obj;
+	TRACE2("%p, %p, %p", pdo, fdo, fdo_drv_obj);
+	status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE,
+				 NULL);
+	if (status != STATUS_SUCCESS)
+		WARNING("status: %08X", status);
+
+	status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE, NULL);
+	if (status != STATUS_SUCCESS)
+		WARNING("status: %08X", status);
+	/* TODO: should we use count in drv_ext or driver's Object
+	 * header reference count to keep count of devices associated
+	 * with a driver? */
+	if (status == STATUS_SUCCESS)
+		fdo_drv_obj->drv_ext->count--;
+	TRACE1("count: %d", fdo_drv_obj->drv_ext->count);
+	if (fdo_drv_obj->drv_ext->count < 0)
+		WARNING("wrong count: %d", fdo_drv_obj->drv_ext->count);
+	if (fdo_drv_obj->drv_ext->count == 0) {
+		struct wrap_driver *wrap_driver;
+		TRACE1("unloading driver: %p", fdo_drv_obj);
+		wrap_driver =
+			IoGetDriverObjectExtension(fdo_drv_obj,
+					   (void *)WRAP_DRIVER_CLIENT_ID);
+		if (fdo_drv_obj->unload)
+			LIN2WIN1(fdo_drv_obj->unload, fdo_drv_obj);
+		if (wrap_driver) {
+			if (down_interruptible(&loader_mutex))
+				WARNING("couldn't obtain loader_mutex");
+			unload_wrap_driver(wrap_driver);
+			up(&loader_mutex);
+		} else
+			ERROR("couldn't get wrap_driver");
+		ObDereferenceObject(fdo_drv_obj);
+	}
+	IoDeleteDevice(pdo);
+	unload_wrap_device(wd);
+	EXIT1(return status);
+}
+
+WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
+
+static struct device_object *alloc_pdo(struct driver_object *drv_obj)
+{
+	struct device_object *pdo;
+	NTSTATUS status ;
+	int i;
+	struct ansi_string ansi_name;
+	struct unicode_string unicode_name;
+
+	RtlInitAnsiString(&ansi_name, "NDISpdo");
+	if (RtlAnsiStringToUnicodeString(&unicode_name, &ansi_name, TRUE) ==
+	    STATUS_SUCCESS) {
+		status = IoCreateDevice(drv_obj, 0, &unicode_name,
+					FILE_DEVICE_UNKNOWN,
+					FILE_AUTOGENERATED_DEVICE_NAME,
+					FALSE, &pdo);
+		RtlFreeUnicodeString(&unicode_name);
+	} else {
+		status = IoCreateDevice(drv_obj, 0, NULL,
+					FILE_DEVICE_UNKNOWN,
+					FILE_AUTOGENERATED_DEVICE_NAME,
+					FALSE, &pdo);
+	}
+	TRACE1("%p, %d, %p", drv_obj, status, pdo);
+	if (status != STATUS_SUCCESS)
+		return NULL;
+	/* dispatch routines are called as Windows functions */
+	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+		drv_obj->major_func[i] = WIN_FUNC_PTR(IoInvalidDeviceRequest,2);
+	drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
+		WIN_FUNC_PTR(pdoDispatchDeviceControl,2);
+	drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =
+		WIN_FUNC_PTR(pdoDispatchDeviceControl,2);
+	drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(pdoDispatchPower,2);
+	drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(pdoDispatchPnp,2);
+	return pdo;
+}
+
+static int wrap_pnp_start_device(struct wrap_device *wd)
+{
+	struct wrap_driver *driver;
+	struct device_object *pdo;
+	struct driver_object *pdo_drv_obj;
+
+	ENTER1("wd: %p", wd);
+
+	if (!((wrap_is_pci_bus(wd->dev_bus)) ||
+	      (wrap_is_usb_bus(wd->dev_bus)))) {
+		ERROR("bus type %d (%d) not supported",
+		      WRAP_BUS(wd->dev_bus), wd->dev_bus);
+		EXIT1(return -EINVAL);
+	}
+	driver = load_wrap_driver(wd);
+	if (!driver)
+		return -ENODEV;
+
+	wd->driver = driver;
+	wd->dev_bus = WRAP_DEVICE_BUS(driver->dev_type, WRAP_BUS(wd->dev_bus));
+	TRACE1("dev type: %d, bus type: %d, %d", WRAP_DEVICE(wd->dev_bus),
+	       WRAP_BUS(wd->dev_bus), wd->dev_bus);
+	TRACE1("%d, %d", driver->dev_type, wrap_is_usb_bus(wd->dev_bus));
+	/* first create pdo */
+	if (wrap_is_pci_bus(wd->dev_bus))
+		pdo_drv_obj = find_bus_driver("PCI");
+	else // if (wrap_is_usb_bus(wd->dev_bus))
+		pdo_drv_obj = find_bus_driver("USB");
+	if (!pdo_drv_obj)
+		return -EINVAL;
+	pdo = alloc_pdo(pdo_drv_obj);
+	if (!pdo)
+		return -ENOMEM;
+	wd->pdo = pdo;
+	pdo->reserved = wd;
+	if (WRAP_DEVICE(wd->dev_bus) == WRAP_NDIS_DEVICE) {
+		if (init_ndis_driver(driver->drv_obj)) {
+			IoDeleteDevice(pdo);
+			return -EINVAL;
+		}
+	}
+	TRACE1("%p", driver->drv_obj->drv_ext->add_device);
+	if (driver->drv_obj->drv_ext->add_device(driver->drv_obj, pdo) !=
+	    STATUS_SUCCESS) {
+		IoDeleteDevice(pdo);
+		return -ENOMEM;
+	}
+	if (pnp_start_device(wd) != STATUS_SUCCESS) {
+		/* TODO: we need proper cleanup, to deallocate memory,
+		 * for example */
+		pnp_remove_device(wd);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * This function should not be marked __devinit because PCI IDs are
+ * added dynamically.
+ */
+int wrap_pnp_start_pci_device(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
+{
+	struct load_device load_device;
+	struct wrap_device *wd;
+
+	ENTER1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device,
+	       pdev->subsystem_vendor, pdev->subsystem_device);
+
+	load_device.bus = WRAP_PCI_BUS;
+	load_device.vendor = pdev->vendor;
+	load_device.device = pdev->device;
+	load_device.subvendor = pdev->subsystem_vendor;
+	load_device.subdevice = pdev->subsystem_device;
+	wd = load_wrap_device(&load_device);
+	if (!wd)
+		EXIT1(return -ENODEV);
+	wd->pci.pdev = pdev;
+	return wrap_pnp_start_device(wd);
+}
+
+void wrap_pnp_remove_pci_device(struct pci_dev *pdev)
+{
+	struct wrap_device *wd;
+
+	wd = (struct wrap_device *)pci_get_drvdata(pdev);
+	ENTER1("%p, %p", pdev, wd);
+	if (!wd)
+		EXIT1(return);
+	pnp_remove_device(wd);
+}
+
+int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state)
+{
+	struct wrap_device *wd;
+
+	wd = (struct wrap_device *)pci_get_drvdata(pdev);
+	return pnp_set_device_power_state(wd, PowerDeviceD3);
+}
+
+int wrap_pnp_resume_pci_device(struct pci_dev *pdev)
+{
+	struct wrap_device *wd;
+
+	wd = (struct wrap_device *)pci_get_drvdata(pdev);
+	return pnp_set_device_power_state(wd, PowerDeviceD0);
+}
+
+#ifdef ENABLE_USB
+int wrap_pnp_start_usb_device(struct usb_interface *intf,
+			      const struct usb_device_id *usb_id)
+{
+	struct wrap_device *wd;
+	int ret;
+	struct usb_device *udev = interface_to_usbdev(intf);
+	ENTER1("%04x, %04x, %04x", udev->descriptor.idVendor,
+	       udev->descriptor.idProduct, udev->descriptor.bDeviceClass);
+
+	/* USB device (e.g., RNDIS) may have multiple interfaces;
+	  initialize one interface only (is there a way to know which
+	  of these interfaces is for network?) */
+
+	if ((wd = get_wrap_device(udev, WRAP_USB_BUS))) {
+		TRACE1("device already initialized: %p", wd);
+		usb_set_intfdata(intf, NULL);
+		ret = 0;
+	} else {
+		struct load_device load_device;
+
+		load_device.bus = WRAP_USB_BUS;
+		load_device.vendor = le16_to_cpu(udev->descriptor.idVendor);
+		load_device.device = le16_to_cpu(udev->descriptor.idProduct);
+		load_device.subvendor = 0;
+		load_device.subdevice = 0;
+		wd = load_wrap_device(&load_device);
+		TRACE2("%p", wd);
+		if (wd) {
+			/* some devices (e.g., TI 4150, RNDIS) need
+			 * full reset */
+			ret = usb_reset_device(udev);
+			if (ret)
+				WARNING("reset failed: %d", ret);
+			usb_set_intfdata(intf, wd);
+			wd->usb.intf = intf;
+			wd->usb.udev = udev;
+			ret = wrap_pnp_start_device(wd);
+		} else
+			ret = -ENODEV;
+	}
+
+	TRACE2("ret: %d", ret);
+	if (ret)
+		EXIT1(return ret);
+	else
+		return 0;
+}
+
+void __devexit wrap_pnp_remove_usb_device(struct usb_interface *intf)
+{
+	struct wrap_device *wd;
+
+	wd = (struct wrap_device *)usb_get_intfdata(intf);
+	TRACE1("%p, %p", intf, wd);
+	if (wd == NULL)
+		EXIT1(return);
+	usb_set_intfdata(intf, NULL);
+	wd->usb.intf = NULL;
+	pnp_remove_device(wd);
+}
+
+int wrap_pnp_suspend_usb_device(struct usb_interface *intf, pm_message_t state)
+{
+	struct wrap_device *wd;
+	struct device_object *pdo;
+
+	wd = usb_get_intfdata(intf);
+	ENTER1("%p, %p", intf, wd);
+	if (!wd)
+		EXIT1(return 0);
+	pdo = wd->pdo;
+	if (pnp_set_device_power_state(wd, PowerDeviceD3))
+		return -1;
+	return 0;
+}
+
+int wrap_pnp_resume_usb_device(struct usb_interface *intf)
+{
+	struct wrap_device *wd;
+	wd = usb_get_intfdata(intf);
+	ENTER1("%p, %p", intf, wd);
+	if (!wd)
+		EXIT1(return 0);
+	if (pnp_set_device_power_state(wd, PowerDeviceD0))
+		return -1;
+	return 0;
+}
+
+#endif // USB
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/Kconfig
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/Kconfig
@@ -0,0 +1,4 @@
+config NDISWRAPPER
+	tristate "Wrapper for Windows NDIS network drivers"
+	depends on NET
+	default m
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ntoskernel.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ntoskernel.h
@@ -0,0 +1,1157 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _NTOSKERNEL_H_
+#define _NTOSKERNEL_H_
+
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <asm/mman.h>
+#include <linux/version.h>
+#include <linux/etherdevice.h>
+#include <net/iw_handler.h>
+#include <linux/ethtool.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/highmem.h>
+#include <linux/percpu.h>
+#include <linux/kthread.h>
+#include <linux/workqueue.h>
+
+#if !defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+#error "this module is for x86 or x86_64 architectures only"
+#endif
+
+/* Interrupt backwards compatibility stuff */
+#include <linux/interrupt.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+#ifndef IRQ_HANDLED
+#define IRQ_HANDLED
+#define IRQ_NONE
+#define irqreturn_t void
+#endif
+#endif /* Linux < 2.6.29 */
+
+/* pci functions in 2.6 kernels have problems allocating dma buffers,
+ * but seem to work fine with dma functions
+ */
+#include <asm/dma-mapping.h>
+
+#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle)			\
+	dma_alloc_coherent(&pci_dev->dev,size,dma_handle,		\
+			   GFP_KERNEL | __GFP_REPEAT)
+#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle)		\
+	dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle)
+#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction)		\
+	dma_map_single(&pci_dev->dev,addr,size,direction)
+#define PCI_DMA_UNMAP_SINGLE(pci_dev,dma_handle,size,direction)		\
+	dma_unmap_single(&pci_dev->dev,dma_handle,size,direction)
+#define MAP_SG(pci_dev, sglist, nents, direction)		\
+	dma_map_sg(&pci_dev->dev, sglist, nents, direction)
+#define UNMAP_SG(pci_dev, sglist, nents, direction)		\
+	dma_unmap_sg(&pci_dev->dev, sglist, nents, direction)
+#define PCI_DMA_MAP_ERROR(dma_addr) dma_mapping_error(dma_addr)
+
+
+#if defined(CONFIG_NET_RADIO) && !defined(CONFIG_WIRELESS_EXT)
+#define CONFIG_WIRELESS_EXT
+#endif
+
+#define prepare_wait_condition(task, var, value)	\
+do {							\
+	var = value;					\
+	task = current;					\
+	barrier();					\
+} while (0)
+
+/* Wait in wait_state (e.g., TASK_INTERRUPTIBLE) for condition to
+ * become true; timeout is either jiffies (> 0) to wait or 0 to wait
+ * forever.
+ * When timeout == 0, return value is
+ *    > 0 if condition becomes true, or
+ *    < 0 if signal is pending on the thread.
+ * When timeout > 0, return value is
+ *    > 0 if condition becomes true before timeout,
+ *    < 0 if signal is pending on the thread before timeout, or
+ *    0 if timedout (condition may have become true at the same time)
+ */
+
+#define wait_condition(condition, timeout, wait_state)		\
+({								\
+	long ret = timeout ? timeout : 1;			\
+	while (1) {						\
+		if (signal_pending(current)) {			\
+			ret = -ERESTARTSYS;			\
+			break;					\
+		}						\
+		set_current_state(wait_state);			\
+		if (condition) {				\
+			__set_current_state(TASK_RUNNING);	\
+			break;					\
+		}						\
+		if (timeout) {					\
+			ret = schedule_timeout(ret);		\
+			if (!ret)				\
+				break;				\
+		} else						\
+			schedule();				\
+	}							\
+	ret;							\
+})
+
+#ifdef WRAP_WQ
+
+struct workqueue_struct;
+
+struct workqueue_thread {
+	spinlock_t lock;
+	struct task_struct *task;
+	struct completion *completion;
+	char name[16];
+	int pid;
+	/* whether any work_structs pending? <0 implies quit */
+	s8 pending;
+	/* list of work_structs pending */
+	struct list_head work_list;
+};
+
+typedef struct workqueue_struct {
+	u8 singlethread;
+	u8 qon;
+	int num_cpus;
+	struct workqueue_thread threads[0];
+} workqueue_struct_t;
+
+typedef struct {
+	struct list_head list;
+	void (*func)(void *data);
+	void *data;
+	/* whether/on which thread scheduled */
+	struct workqueue_thread *thread;
+} work_struct_t;
+
+#define initialize_work(work, pfunc, pdata)			\
+	do {							\
+		(work)->func = (pfunc);				\
+		(work)->data = (pdata);				\
+		(work)->thread = NULL;				\
+	} while (0)
+
+#undef create_singlethread_workqueue
+#define create_singlethread_workqueue(name) wrap_create_wq(name, 1, 0)
+#undef create_workqueue
+#define create_workqueue(name) wrap_create_wq(name, 0, 0)
+#undef destroy_workqueue
+#define destroy_workqueue wrap_destroy_wq
+#undef queue_work
+#define queue_work wrap_queue_work
+#undef flush_workqueue
+#define flush_workqueue wrap_flush_wq
+
+workqueue_struct_t *wrap_create_wq(const char *name, u8 singlethread, u8 freeze);
+void wrap_destroy_wq_on(workqueue_struct_t *workq, int cpu);
+void wrap_destroy_wq(workqueue_struct_t *workq);
+int wrap_queue_work_on(workqueue_struct_t *workq, work_struct_t *work,
+		       int cpu);
+int wrap_queue_work(workqueue_struct_t *workq, work_struct_t *work);
+void wrap_cancel_work(work_struct_t *work);
+void wrap_flush_wq_on(workqueue_struct_t *workq, int cpu);
+void wrap_flush_wq(workqueue_struct_t *workq);
+typedef void *worker_param_t;
+#define worker_param_data(param, type, member) param
+
+#else // WRAP_WQ
+
+typedef struct workqueue_struct workqueue_struct_t;
+typedef struct work_struct work_struct_t;
+
+#if defined(INIT_WORK_NAR) || defined(INIT_DELAYED_WORK_DEFERRABLE)
+#define initialize_work(work, func, data) INIT_WORK(work, func)
+typedef struct work_struct *worker_param_t;
+#define worker_param_data(param, type, member)	\
+	container_of(param, type, member)
+#else
+#define initialize_work(work, func, data) INIT_WORK(work, func, data)
+typedef void *worker_param_t;
+#define worker_param_data(param, type, member) param
+#endif // INIT_WORK_NAR
+
+#endif // WRAP_WQ
+
+struct nt_thread *wrap_worker_init(workqueue_struct_t *wq);
+
+#ifdef module_param
+#define WRAP_MODULE_PARM_INT(name, perm) module_param(name, int, perm)
+#define WRAP_MODULE_PARM_STRING(name, perm) module_param(name, charp, perm)
+#else
+#define WRAP_MODULE_PARM_INT(name, perm) MODULE_PARM(name, "i")
+#define WRAP_MODULE_PARM_STRING(name, perm) MODULE_PARM(name, "s")
+#endif
+
+#ifndef LOCK_PREFIX
+#ifdef LOCK
+#define LOCK_PREFIX LOCK
+#else
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX "lock ; "
+#else
+#define LOCK_PREFIX ""
+#endif
+#endif
+#endif
+
+#ifndef NETDEV_TX_OK
+#define NETDEV_TX_OK 0
+#endif
+
+#ifndef NETDEV_TX_BUSY
+#define NETDEV_TX_BUSY 1
+#endif
+
+#ifndef CHECKSUM_HW
+#define CHECKSUM_HW CHECKSUM_PARTIAL
+#endif
+
+#ifndef offset_in_page
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+#endif
+
+#ifndef PMSG_SUSPEND
+#ifdef PM_SUSPEND
+/* this is not correct - the value of PM_SUSPEND is different from
+ * PMSG_SUSPEND, but ndiswrapper doesn't care about the value when
+ * suspending */
+#define PMSG_SUSPEND PM_SUSPEND
+#define PSMG_ON PM_ON
+#else
+typedef u32 pm_message_t;
+#define PMSG_SUSPEND 2
+#define PMSG_ON 0
+#endif
+#endif
+
+#ifndef PCI_D0
+#define PCI_D0 0
+#endif
+
+#ifndef PCI_D3hot
+#define PCI_D3hot 3
+#endif
+
+#ifndef PCI_D3cold
+#define PCI_D3cold 3
+#endif
+
+#ifndef PM_EVENT_SUSPEND
+#define PM_EVENT_SUSPEND 2
+#endif
+
+#if !defined(HAVE_NETDEV_PRIV)
+#define netdev_priv(dev)  ((dev)->priv)
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+#define ISR_PT_REGS_PARAM_DECL
+#define ISR_PT_REGS_ARG
+#else
+#define ISR_PT_REGS_PARAM_DECL , struct pt_regs *regs
+#define ISR_PT_REGS_ARG , NULL
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
+#define for_each_possible_cpu(_cpu) for_each_cpu(_cpu)
+#endif
+
+#ifndef flush_icache_range
+#define flush_icache_range(start, end) do { } while (0)
+#endif
+
+#ifndef CHECKSUM_PARTIAL
+#define CHECKSUM_PARTIAL CHECKSUM_HW
+#endif
+
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+#define memcpy_skb(skb, from, length)			\
+	memcpy(skb_put(skb, length), from, length)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#ifndef DMA_BIT_MASK
+#define DMA_BIT_MASK(n)	(((n) == 64) ? ~0ULL : ((1ULL<<(n))-1))
+#endif
+#endif
+
+#ifndef __GFP_DMA32
+#define __GFP_DMA32 GFP_DMA
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
+#define wrap_kmem_cache_create(name, size, align, flags)	\
+	kmem_cache_create(name, size, align, flags, NULL, NULL)
+#else
+#define wrap_kmem_cache_create(name, size, align, flags)	\
+	kmem_cache_create(name, size, align, flags, NULL)
+#endif
+
+#include "winnt_types.h"
+#include "ndiswrapper.h"
+#include "pe_linker.h"
+#include "wrapmem.h"
+#include "lin2win.h"
+#include "loader.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+static inline void netif_tx_lock(struct net_device *dev)
+{
+	spin_lock(&dev->xmit_lock);
+}
+static inline void netif_tx_unlock(struct net_device *dev)
+{
+	spin_unlock(&dev->xmit_lock);
+}
+static inline void netif_tx_lock_bh(struct net_device *dev)
+{
+	spin_lock_bh(&dev->xmit_lock);
+}
+static inline void netif_tx_unlock_bh(struct net_device *dev)
+{
+	spin_unlock_bh(&dev->xmit_lock);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+static inline void netif_poll_enable(struct net_device *dev)
+{
+}
+static inline void netif_poll_disable(struct net_device *dev)
+{
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#define proc_net_root init_net.proc_net
+#else
+#define proc_net_root proc_net
+#endif
+
+/* TICK is 100ns */
+#define TICKSPERSEC		10000000
+#define TICKSPERMSEC		10000
+#define SECSPERDAY		86400
+#define TICKSPERJIFFY		((TICKSPERSEC + HZ - 1) / HZ)
+
+#define int_div_round(x, y) (((x) + (y - 1)) / (y))
+
+/* 1601 to 1970 is 369 years plus 89 leap days */
+#define SECS_1601_TO_1970	((369 * 365 + 89) * (u64)SECSPERDAY)
+#define TICKS_1601_TO_1970	(SECS_1601_TO_1970 * TICKSPERSEC)
+
+/* 100ns units to HZ; if sys_time is negative, relative to current
+ * clock, otherwise from year 1601 */
+#define SYSTEM_TIME_TO_HZ(sys_time)					\
+	(((sys_time) <= 0) ? \
+	 int_div_round(((u64)HZ * (-(sys_time))), TICKSPERSEC) :	\
+	 int_div_round(((s64)HZ * ((sys_time) - ticks_1601())), TICKSPERSEC))
+
+#define MSEC_TO_HZ(ms) int_div_round((ms * HZ), 1000)
+#define USEC_TO_HZ(us) int_div_round((us * HZ), 1000000)
+
+extern u64 wrap_ticks_to_boot;
+
+static inline u64 ticks_1601(void)
+{
+	return wrap_ticks_to_boot + (u64)jiffies * TICKSPERJIFFY;
+}
+
+typedef void (*generic_func)(void);
+
+struct wrap_export {
+	const char *name;
+	generic_func func;
+};
+
+#ifdef CONFIG_X86_64
+
+#define WIN_SYMBOL(name, argc)					\
+	{#name, (generic_func) win2lin_ ## name ## _ ## argc}
+#define WIN_WIN_SYMBOL(name, argc)					\
+	{#name, (generic_func) win2lin__win_ ## name ## _ ## argc}
+#define WIN_FUNC_DECL(name, argc)			\
+	extern typeof(name) win2lin_ ## name ## _ ## argc;
+#define WIN_FUNC_PTR(name, argc) win2lin_ ## name ## _ ## argc
+
+#else
+
+#define WIN_SYMBOL(name, argc) {#name, (generic_func)name}
+#define WIN_WIN_SYMBOL(name, argc) {#name, (generic_func)_win_ ## name}
+#define WIN_FUNC_DECL(name, argc)
+#define WIN_FUNC_PTR(name, argc) name
+
+#endif
+
+#define WIN_FUNC(name, argc) name
+/* map name s to f - if f is different from s */
+#define WIN_SYMBOL_MAP(s, f)
+
+#define POOL_TAG(A, B, C, D)					\
+	((ULONG)((A) + ((B) << 8) + ((C) << 16) + ((D) << 24)))
+
+struct pe_image {
+	char name[MAX_DRIVER_NAME_LEN];
+	UINT (*entry)(struct driver_object *, struct unicode_string *) wstdcall;
+	void *image;
+	int size;
+	int type;
+
+	IMAGE_NT_HEADERS *nt_hdr;
+	IMAGE_OPTIONAL_HEADER *opt_hdr;
+};
+
+struct ndis_mp_block;
+
+struct wrap_timer {
+	struct nt_slist slist;
+	struct timer_list timer;
+	struct nt_timer *nt_timer;
+	long repeat;
+#ifdef TIMER_DEBUG
+	unsigned long wrap_timer_magic;
+#endif
+};
+
+struct ntos_work_item {
+	struct nt_list list;
+	void *arg1;
+	void *arg2;
+	NTOS_WORK_FUNC func;
+};
+
+struct wrap_device_setting {
+	struct nt_list list;
+	char name[MAX_SETTING_NAME_LEN];
+	char value[MAX_SETTING_VALUE_LEN];
+	void *encoded;
+};
+
+struct wrap_bin_file {
+	char name[MAX_DRIVER_NAME_LEN];
+	size_t size;
+	void *data;
+};
+
+#define WRAP_DRIVER_CLIENT_ID 1
+
+struct wrap_driver {
+	struct nt_list list;
+	struct driver_object *drv_obj;
+	char name[MAX_DRIVER_NAME_LEN];
+	char version[MAX_SETTING_VALUE_LEN];
+	unsigned short num_pe_images;
+	struct pe_image pe_images[MAX_DRIVER_PE_IMAGES];
+	unsigned short num_bin_files;
+	struct wrap_bin_file *bin_files;
+	struct nt_list wrap_devices;
+	struct nt_list settings;
+	int dev_type;
+	struct ndis_driver *ndis_driver;
+};
+
+enum hw_status {
+	HW_INITIALIZED = 1, HW_SUSPENDED, HW_HALTED, HW_PRESENT,
+};
+
+struct wrap_device {
+	/* first part is (de)initialized once by loader */
+	struct nt_list list;
+	int dev_bus;
+	int vendor;
+	int device;
+	int subvendor;
+	int subdevice;
+	char conf_file_name[MAX_DRIVER_NAME_LEN];
+	char driver_name[MAX_DRIVER_NAME_LEN];
+	struct wrap_driver *driver;
+	struct nt_list settings;
+
+	/* rest should be (de)initialized when a device is
+	 * (un)plugged */
+	struct cm_resource_list *resource_list;
+	unsigned long hw_status;
+	struct device_object *pdo;
+	union {
+		struct {
+			struct pci_dev *pdev;
+			enum device_power_state wake_state;
+		} pci;
+		struct {
+			struct usb_device *udev;
+			struct usb_interface *intf;
+			int num_alloc_urbs;
+			struct nt_list wrap_urb_list;
+		} usb;
+	};
+	union {
+		struct ndis_device *wnd;
+	};
+};
+
+#define wrap_is_pci_bus(dev_bus)			\
+	(WRAP_BUS(dev_bus) == WRAP_PCI_BUS ||		\
+	 WRAP_BUS(dev_bus) == WRAP_PCMCIA_BUS)
+#ifdef ENABLE_USB
+/* earlier versions of ndiswrapper used 0 as USB_BUS */
+#define wrap_is_usb_bus(dev_bus)			\
+	(WRAP_BUS(dev_bus) == WRAP_USB_BUS ||		\
+	 WRAP_BUS(dev_bus) == WRAP_INTERNAL_BUS)
+#else
+#define wrap_is_usb_bus(dev_bus) 0
+#endif
+#define wrap_is_bluetooth_device(dev_bus)			\
+	(WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE1 ||	\
+	 WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE2)
+
+extern workqueue_struct_t *ntos_wq;
+#define schedule_ntos_work(work_struct) queue_work(ntos_wq, work_struct)
+#define schedule_work(work_struct) queue_work(ntos_wq, work_struct)
+
+extern workqueue_struct_t *ndis_wq;
+#define schedule_ndis_work(work_struct) queue_work(ndis_wq, work_struct)
+
+extern workqueue_struct_t *wrapndis_wq;
+#define schedule_wrapndis_work(work_struct) queue_work(wrapndis_wq, work_struct)
+
+#define atomic_unary_op(var, size, oper)				\
+do {									\
+	if (size == 1)							\
+		__asm__ __volatile__(					\
+			LOCK_PREFIX oper "b %b0\n\t" : "+m" (var));	\
+	else if (size == 2)						\
+		__asm__ __volatile__(					\
+			LOCK_PREFIX oper "w %w0\n\t" : "+m" (var));	\
+	else if (size == 4)						\
+		__asm__ __volatile__(					\
+			LOCK_PREFIX oper "l %0\n\t" : "+m" (var));	\
+	else if (size == 8)						\
+		__asm__ __volatile__(					\
+			LOCK_PREFIX oper "q %q0\n\t" : "+m" (var));	\
+	else {								\
+		extern void _invalid_op_size_(void);			\
+		_invalid_op_size_();					\
+	}								\
+} while (0)
+
+#define atomic_inc_var_size(var, size) atomic_unary_op(var, size, "inc")
+
+#define atomic_inc_var(var) atomic_inc_var_size(var, sizeof(var))
+
+#define atomic_dec_var_size(var, size) atomic_unary_op(var, size, "dec")
+
+#define atomic_dec_var(var) atomic_dec_var_size(var, sizeof(var))
+
+#define pre_atomic_add(var, i)					\
+({								\
+	typeof(var) pre;					\
+	__asm__ __volatile__(					\
+		LOCK_PREFIX "xadd %0, %1\n\t"			\
+		: "=r"(pre), "+m"(var)				\
+		: "0"(i));					\
+	pre;							\
+})
+
+#define post_atomic_add(var, i) (pre_atomic_add(var, i) + i)
+
+#ifndef in_atomic
+#define in_atomic() in_interrupt()
+#endif
+
+#ifndef preempt_enable_no_resched
+#define preempt_enable_no_resched() preempt_enable()
+#endif
+
+//#define DEBUG_IRQL 1
+
+#ifdef DEBUG_IRQL
+#define assert_irql(cond)						\
+do {									\
+	KIRQL _irql_ = current_irql();					\
+	if (!(cond)) {							\
+		WARNING("assertion '%s' failed: %d", #cond, _irql_);	\
+		DBG_BLOCK(4) {						\
+			dump_stack();					\
+		}							\
+	}								\
+} while (0)
+#else
+#define assert_irql(cond) do { } while (0)
+#endif
+
+/* When preempt is enabled, we should preempt_disable to raise IRQL to
+ * DISPATCH_LEVEL, to be consistent with the semantics. However, using
+ * a mutex instead, so that only ndiswrapper threads run one at a time
+ * on a processor when at DISPATCH_LEVEL seems to be enough. So that
+ * is what we will use until we learn otherwise. If
+ * preempt_(en|dis)able is required for some reason, comment out
+ * following #define. */
+
+#define WRAP_PREEMPT 1
+
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PREEMPT_RT)
+#ifndef WRAP_PREEMPT
+#define WRAP_PREEMPT 1
+#endif
+#endif
+
+//#undef WRAP_PREEMPT
+
+#ifdef WRAP_PREEMPT
+
+typedef struct {
+	int count;
+	struct mutex lock;
+#ifdef CONFIG_SMP
+	typeof(current->cpus_allowed) cpus_allowed;
+#endif
+	struct task_struct *task;
+} irql_info_t;
+
+DECLARE_PER_CPU(irql_info_t, irql_info);
+
+static inline KIRQL raise_irql(KIRQL newirql)
+{
+	irql_info_t *info;
+
+	assert(newirql == DISPATCH_LEVEL);
+	info = &get_cpu_var(irql_info);
+	if (info->task == current) {
+		assert(info->count > 0);
+		assert(mutex_is_locked(&info->lock));
+#if defined(CONFIG_SMP) && defined(DEBUG)
+		do {
+			cpumask_t cpumask;
+			cpumask = cpumask_of_cpu(smp_processor_id());
+			cpus_xor(cpumask, cpumask, current->cpus_allowed);
+			assert(cpus_empty(cpumask));
+		} while (0);
+#endif
+		info->count++;
+		put_cpu_var(irql_info);
+		return DISPATCH_LEVEL;
+	}
+	/* TODO: is this enough to pin down to current cpu? */
+#ifdef CONFIG_SMP
+	assert(task_cpu(current) == smp_processor_id());
+	info->cpus_allowed = current->cpus_allowed;
+	current->cpus_allowed = cpumask_of_cpu(smp_processor_id());
+#endif
+	put_cpu_var(irql_info);
+	mutex_lock(&info->lock);
+	assert(info->count == 0);
+	assert(info->task == NULL);
+	info->count = 1;
+	info->task = current;
+	return PASSIVE_LEVEL;
+}
+
+static inline void lower_irql(KIRQL oldirql)
+{
+	irql_info_t *info;
+
+	assert(oldirql <= DISPATCH_LEVEL);
+	info = &get_cpu_var(irql_info);
+	assert(info->task == current);
+	assert(mutex_is_locked(&info->lock));
+	assert(info->count > 0);
+	if (--info->count == 0) {
+		info->task = NULL;
+#ifdef CONFIG_SMP
+		current->cpus_allowed = info->cpus_allowed;
+#endif
+		mutex_unlock(&info->lock);
+	}
+	put_cpu_var(irql_info);
+}
+
+static inline KIRQL current_irql(void)
+{
+	int count;
+	if (in_irq() || irqs_disabled())
+		EXIT4(return DIRQL);
+	if (in_atomic() || in_interrupt())
+		EXIT4(return SOFT_IRQL);
+	count = get_cpu_var(irql_info).count;
+	put_cpu_var(irql_info);
+	if (count)
+		EXIT6(return DISPATCH_LEVEL);
+	else
+		EXIT6(return PASSIVE_LEVEL);
+}
+
+#else
+
+static inline KIRQL current_irql(void)
+{
+	if (in_irq() || irqs_disabled())
+		EXIT4(return DIRQL);
+	if (in_interrupt())
+		EXIT4(return SOFT_IRQL);
+	if (in_atomic())
+		EXIT6(return DISPATCH_LEVEL);
+	else
+		EXIT6(return PASSIVE_LEVEL);
+}
+
+static inline KIRQL raise_irql(KIRQL newirql)
+{
+	KIRQL ret = in_atomic() ? DISPATCH_LEVEL : PASSIVE_LEVEL;
+	assert(newirql == DISPATCH_LEVEL);
+	assert(current_irql() <= DISPATCH_LEVEL);
+	preempt_disable();
+	return ret;
+}
+
+static inline void lower_irql(KIRQL oldirql)
+{
+	assert(current_irql() == DISPATCH_LEVEL);
+	preempt_enable();
+}
+
+#endif
+
+#define irql_gfp() (in_atomic() ? GFP_ATOMIC : GFP_KERNEL)
+
+/* Windows spinlocks are of type ULONG_PTR which is not big enough to
+ * store Linux spinlocks; so we implement Windows spinlocks using
+ * ULONG_PTR space with our own functions/macros */
+
+/* Windows seems to use 0 for unlocked state of spinlock - if Linux
+ * convention of 1 for unlocked state is used, at least prism54 driver
+ * crashes */
+
+#define NT_SPIN_LOCK_UNLOCKED 0
+#define NT_SPIN_LOCK_LOCKED 1
+
+static inline void  nt_spin_lock_init(NT_SPIN_LOCK *lock)
+{
+	*lock = NT_SPIN_LOCK_UNLOCKED;
+}
+
+#ifdef CONFIG_SMP
+
+static inline void nt_spin_lock(NT_SPIN_LOCK *lock)
+{
+	__asm__ __volatile__(
+		"1:\t"
+		"  xchgl %1, %0\n\t"
+		"  testl %1, %1\n\t"
+		"  jz 3f\n"
+		"2:\t"
+		"  rep; nop\n\t"
+		"  cmpl %2, %0\n\t"
+		"  je 1b\n\t"
+		"  jmp 2b\n"
+		"3:\n\t"
+		: "+m" (*lock)
+		: "r" (NT_SPIN_LOCK_LOCKED), "i" (NT_SPIN_LOCK_UNLOCKED));
+}
+
+static inline void nt_spin_unlock(NT_SPIN_LOCK *lock)
+{
+	*lock = NT_SPIN_LOCK_UNLOCKED;
+}
+
+#else // CONFIG_SMP
+
+#define nt_spin_lock(lock) do { } while (0)
+
+#define nt_spin_unlock(lock)  do { } while (0)
+
+#endif // CONFIG_SMP
+
+/* When kernel would've disabled preempt (e.g., in interrupt
+ * handlers), we need to fake preempt so driver thinks it is running
+ * at right IRQL */
+
+/* raise IRQL to given (higher) IRQL if necessary before locking */
+static inline KIRQL nt_spin_lock_irql(NT_SPIN_LOCK *lock, KIRQL newirql)
+{
+	KIRQL oldirql = raise_irql(newirql);
+	nt_spin_lock(lock);
+	return oldirql;
+}
+
+/* lower IRQL to given (lower) IRQL if necessary after unlocking */
+static inline void nt_spin_unlock_irql(NT_SPIN_LOCK *lock, KIRQL oldirql)
+{
+	nt_spin_unlock(lock);
+	lower_irql(oldirql);
+}
+
+#define nt_spin_lock_irqsave(lock, flags)				\
+do {									\
+	local_irq_save(flags);						\
+	preempt_disable();						\
+	nt_spin_lock(lock);						\
+} while (0)
+
+#define nt_spin_unlock_irqrestore(lock, flags)				\
+do {									\
+	nt_spin_unlock(lock);						\
+	preempt_enable_no_resched();					\
+	local_irq_restore(flags);					\
+	preempt_check_resched();					\
+} while (0)
+
+static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length)
+{
+	return PAGE_ALIGN(((unsigned long)ptr & (PAGE_SIZE - 1)) + length)
+		>> PAGE_SHIFT;
+}
+
+#ifdef CONFIG_X86_64
+
+/* TODO: can these be implemented without using spinlock? */
+
+static inline struct nt_slist *PushEntrySList(nt_slist_header *head,
+					      struct nt_slist *entry,
+					      NT_SPIN_LOCK *lock)
+{
+	KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
+	entry->next = head->next;
+	head->next = entry;
+	head->depth++;
+	nt_spin_unlock_irql(lock, irql);
+	TRACE4("%p, %p, %p", head, entry, entry->next);
+	return entry->next;
+}
+
+static inline struct nt_slist *PopEntrySList(nt_slist_header *head,
+					     NT_SPIN_LOCK *lock)
+{
+	struct nt_slist *entry;
+	KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
+	entry = head->next;
+	if (entry) {
+		head->next = entry->next;
+		head->depth--;
+	}
+	nt_spin_unlock_irql(lock, irql);
+	TRACE4("%p, %p", head, entry);
+	return entry;
+}
+
+#else
+
+#define u64_low_32(x) ((u32)x)
+#define u64_high_32(x) ((u32)(x >> 32))
+
+static inline u64 cmpxchg8b(volatile u64 *ptr, u64 old, u64 new)
+{
+	u64 prev;
+
+	__asm__ __volatile__(
+		"\n"
+		LOCK_PREFIX "cmpxchg8b %0\n"
+		: "+m" (*ptr), "=A" (prev)
+		: "A" (old), "b" (u64_low_32(new)), "c" (u64_high_32(new)));
+	return prev;
+}
+
+/* slist routines below update slist atomically - no need for
+ * spinlocks */
+
+static inline struct nt_slist *PushEntrySList(nt_slist_header *head,
+					      struct nt_slist *entry,
+					      NT_SPIN_LOCK *lock)
+{
+	nt_slist_header old, new;
+	do {
+		old.align = head->align;
+		entry->next = old.next;
+		new.next = entry;
+		new.depth = old.depth + 1;
+	} while (cmpxchg8b(&head->align, old.align, new.align) != old.align);
+	TRACE4("%p, %p, %p", head, entry, old.next);
+	return old.next;
+}
+
+static inline struct nt_slist *PopEntrySList(nt_slist_header *head,
+					     NT_SPIN_LOCK *lock)
+{
+	struct nt_slist *entry;
+	nt_slist_header old, new;
+	do {
+		old.align = head->align;
+		entry = old.next;
+		if (!entry)
+			break;
+		new.next = entry->next;
+		new.depth = old.depth - 1;
+	} while (cmpxchg8b(&head->align, old.align, new.align) != old.align);
+	TRACE4("%p, %p", head, entry);
+	return entry;
+}
+
+#endif
+
+#define sleep_hz(n)					\
+do {							\
+	set_current_state(TASK_INTERRUPTIBLE);		\
+	schedule_timeout(n);				\
+} while (0)
+
+int ntoskernel_init(void);
+void ntoskernel_exit(void);
+int ntoskernel_init_device(struct wrap_device *wd);
+void ntoskernel_exit_device(struct wrap_device *wd);
+void *allocate_object(ULONG size, enum common_object_type type,
+		      struct unicode_string *name);
+void free_object(void *object);
+
+int usb_init(void);
+void usb_exit(void);
+int usb_init_device(struct wrap_device *wd);
+void usb_exit_device(struct wrap_device *wd);
+void usb_cancel_pending_urbs(void);
+
+int crt_init(void);
+void crt_exit(void);
+int rtl_init(void);
+void rtl_exit(void);
+int wrap_procfs_init(void);
+void wrap_procfs_remove(void);
+
+int link_pe_images(struct pe_image *pe_image, unsigned short n);
+
+int stricmp(const char *s1, const char *s2);
+void dump_bytes(const char *name, const u8 *from, int len);
+struct mdl *allocate_init_mdl(void *virt, ULONG length);
+void free_mdl(struct mdl *mdl);
+struct driver_object *find_bus_driver(const char *name);
+void free_custom_extensions(struct driver_extension *drv_obj_ext);
+struct nt_thread *get_current_nt_thread(void);
+u64 ticks_1601(void);
+int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2);
+void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,
+		     struct ndis_mp_block *nmb);
+BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz,
+		       unsigned long repeat_hz, struct kdpc *kdpc);
+
+LONG InterlockedDecrement(LONG volatile *val) wfastcall;
+LONG InterlockedIncrement(LONG volatile *val) wfastcall;
+struct nt_list *ExInterlockedInsertHeadList
+	(struct nt_list *head, struct nt_list *entry,
+	 NT_SPIN_LOCK *lock) wfastcall;
+struct nt_list *ExInterlockedInsertTailList
+	(struct nt_list *head, struct nt_list *entry,
+	 NT_SPIN_LOCK *lock) wfastcall;
+struct nt_list *ExInterlockedRemoveHeadList
+	(struct nt_list *head, NT_SPIN_LOCK *lock) wfastcall;
+NTSTATUS IofCallDriver(struct device_object *dev_obj, struct irp *irp) wfastcall;
+KIRQL KfRaiseIrql(KIRQL newirql) wfastcall;
+void KfLowerIrql(KIRQL oldirql) wfastcall;
+KIRQL KfAcquireSpinLock(NT_SPIN_LOCK *lock) wfastcall;
+void KfReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wfastcall;
+void IofCompleteRequest(struct irp *irp, CHAR prio_boost) wfastcall;
+void KefReleaseSpinLockFromDpcLevel(NT_SPIN_LOCK *lock) wfastcall;
+
+LONG ObfReferenceObject(void *object) wfastcall;
+void ObfDereferenceObject(void *object) wfastcall;
+
+#define ObReferenceObject(object) ObfReferenceObject(object)
+#define ObDereferenceObject(object) ObfDereferenceObject(object)
+
+void WRITE_PORT_UCHAR(ULONG_PTR port, UCHAR value) wstdcall;
+UCHAR READ_PORT_UCHAR(ULONG_PTR port) wstdcall;
+
+#undef ExAllocatePoolWithTag
+void *ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size,
+			    ULONG tag) wstdcall;
+#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1
+#define ExAllocatePoolWithTag(pool_type, size, tag)			\
+	wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__)
+#endif
+
+void ExFreePool(void *p) wstdcall;
+ULONG MmSizeOfMdl(void *base, ULONG length) wstdcall;
+void __iomem *MmMapIoSpace(PHYSICAL_ADDRESS phys_addr, SIZE_T size,
+		   enum memory_caching_type cache) wstdcall;
+void MmUnmapIoSpace(void __iomem *addr, SIZE_T size) wstdcall;
+void MmProbeAndLockPages(struct mdl *mdl, KPROCESSOR_MODE access_mode,
+			 enum lock_operation operation) wstdcall;
+void MmUnlockPages(struct mdl *mdl) wstdcall;
+void KeInitializeEvent(struct nt_event *nt_event,
+		       enum event_type type, BOOLEAN state) wstdcall;
+LONG KeSetEvent(struct nt_event *nt_event, KPRIORITY incr,
+		BOOLEAN wait) wstdcall;
+LONG KeResetEvent(struct nt_event *nt_event) wstdcall;
+void KeClearEvent(struct nt_event *nt_event) wstdcall;
+void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall;
+BOOLEAN queue_kdpc(struct kdpc *kdpc);
+BOOLEAN dequeue_kdpc(struct kdpc *kdpc);
+
+void KeFlushQueuedDpcs(void) wstdcall;
+NTSTATUS IoConnectInterrupt(struct kinterrupt **kinterrupt,
+			    PKSERVICE_ROUTINE service_routine,
+			    void *service_context, NT_SPIN_LOCK *lock,
+			    ULONG vector, KIRQL irql, KIRQL synch_irql,
+			    enum kinterrupt_mode interrupt_mode,
+			    BOOLEAN shareable, KAFFINITY processor_enable_mask,
+			    BOOLEAN floating_save) wstdcall;
+void IoDisconnectInterrupt(struct kinterrupt *interrupt) wstdcall;
+BOOLEAN KeSynchronizeExecution(struct kinterrupt *interrupt,
+			       PKSYNCHRONIZE_ROUTINE synch_routine,
+			       void *ctx) wstdcall;
+
+NTSTATUS KeWaitForSingleObject(void *object, KWAIT_REASON reason,
+			       KPROCESSOR_MODE waitmode, BOOLEAN alertable,
+			       LARGE_INTEGER *timeout) wstdcall;
+struct mdl *IoAllocateMdl(void *virt, ULONG length, BOOLEAN second_buf,
+			  BOOLEAN charge_quota, struct irp *irp) wstdcall;
+void MmBuildMdlForNonPagedPool(struct mdl *mdl) wstdcall;
+void IoFreeMdl(struct mdl *mdl) wstdcall;
+NTSTATUS IoCreateDevice(struct driver_object *driver, ULONG dev_ext_length,
+			struct unicode_string *dev_name, DEVICE_TYPE dev_type,
+			ULONG dev_chars, BOOLEAN exclusive,
+			struct device_object **dev_obj) wstdcall;
+NTSTATUS IoCreateSymbolicLink(struct unicode_string *link,
+			      struct unicode_string *dev_name) wstdcall;
+void IoDeleteDevice(struct device_object *dev) wstdcall;
+void IoDetachDevice(struct device_object *topdev) wstdcall;
+struct device_object *IoGetAttachedDevice(struct device_object *dev) wstdcall;
+struct device_object *IoGetAttachedDeviceReference
+	(struct device_object *dev) wstdcall;
+NTSTATUS IoAllocateDriverObjectExtension
+	(struct driver_object *drv_obj, void *client_id, ULONG extlen,
+	 void **ext) wstdcall;
+void *IoGetDriverObjectExtension(struct driver_object *drv,
+				 void *client_id) wstdcall;
+struct device_object *IoAttachDeviceToDeviceStack
+	(struct device_object *src, struct device_object *dst) wstdcall;
+void KeInitializeEvent(struct nt_event *nt_event, enum event_type type,
+		       BOOLEAN state) wstdcall;
+struct irp *IoAllocateIrp(char stack_count, BOOLEAN charge_quota) wstdcall;
+void IoFreeIrp(struct irp *irp) wstdcall;
+BOOLEAN IoCancelIrp(struct irp *irp) wstdcall;
+struct irp *IoBuildSynchronousFsdRequest
+	(ULONG major_func, struct device_object *dev_obj, void *buf,
+	 ULONG length, LARGE_INTEGER *offset, struct nt_event *event,
+	 struct io_status_block *status) wstdcall;
+struct irp *IoBuildAsynchronousFsdRequest
+	(ULONG major_func, struct device_object *dev_obj, void *buf,
+	 ULONG length, LARGE_INTEGER *offset,
+	 struct io_status_block *status) wstdcall;
+NTSTATUS PoCallDriver(struct device_object *dev_obj, struct irp *irp) wstdcall;
+
+NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) wstdcall;
+WIN_FUNC_DECL(IoPassIrpDown,2);
+NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
+			  struct irp *irp) wstdcall;
+NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
+			   struct irp *irp) wstdcall;
+NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
+				struct irp *irp) wstdcall;
+
+KIRQL KeGetCurrentIrql(void) wstdcall;
+void KeInitializeSpinLock(NT_SPIN_LOCK *lock) wstdcall;
+void KeAcquireSpinLock(NT_SPIN_LOCK *lock, KIRQL *irql) wstdcall;
+void KeReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wstdcall;
+KIRQL KeAcquireSpinLockRaiseToDpc(NT_SPIN_LOCK *lock) wstdcall;
+
+void IoAcquireCancelSpinLock(KIRQL *irql) wstdcall;
+void IoReleaseCancelSpinLock(KIRQL irql) wstdcall;
+
+void RtlCopyMemory(void *dst, const void *src, SIZE_T length) wstdcall;
+NTSTATUS RtlUnicodeStringToAnsiString
+	(struct ansi_string *dst, const struct unicode_string *src,
+	 BOOLEAN dup) wstdcall;
+NTSTATUS RtlAnsiStringToUnicodeString
+	(struct unicode_string *dst, const struct ansi_string *src,
+	 BOOLEAN dup) wstdcall;
+void RtlInitAnsiString(struct ansi_string *dst, const char *src) wstdcall;
+void RtlInitString(struct ansi_string *dst, const char *src) wstdcall;
+void RtlInitUnicodeString(struct unicode_string *dest,
+			  const wchar_t *src) wstdcall;
+void RtlFreeUnicodeString(struct unicode_string *string) wstdcall;
+void RtlFreeAnsiString(struct ansi_string *string) wstdcall;
+LONG RtlCompareUnicodeString(const struct unicode_string *s1,
+			     const struct unicode_string *s2,
+			     BOOLEAN case_insensitive) wstdcall;
+void RtlCopyUnicodeString(struct unicode_string *dst,
+			  struct unicode_string *src) wstdcall;
+NTSTATUS RtlUpcaseUnicodeString(struct unicode_string *dst,
+				struct unicode_string *src,
+				BOOLEAN alloc) wstdcall;
+void KeInitializeTimer(struct nt_timer *nt_timer) wstdcall;
+void KeInitializeTimerEx(struct nt_timer *nt_timer,
+			 enum timer_type type) wstdcall;
+BOOLEAN KeSetTimerEx(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
+		     LONG period_ms, struct kdpc *kdpc) wstdcall;
+BOOLEAN KeSetTimer(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
+		   struct kdpc *kdpc) wstdcall;
+BOOLEAN KeCancelTimer(struct nt_timer *nt_timer) wstdcall;
+void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall;
+struct nt_thread *KeGetCurrentThread(void) wstdcall;
+NTSTATUS ObReferenceObjectByHandle(void *handle, ACCESS_MASK desired_access,
+				   void *obj_type, KPROCESSOR_MODE access_mode,
+				   void **object, void *handle_info) wstdcall;
+
+void adjust_user_shared_data_addr(char *driver, unsigned long length);
+
+extern spinlock_t ntoskernel_lock;
+extern spinlock_t irp_cancel_lock;
+extern struct nt_list object_list;
+#ifdef CONFIG_X86_64
+extern struct kuser_shared_data kuser_shared_data;
+#endif
+
+#define IoCompleteRequest(irp, prio) IofCompleteRequest(irp, prio)
+#define IoCallDriver(dev, irp) IofCallDriver(dev, irp)
+
+#if defined(IO_DEBUG)
+#define DUMP_IRP(_irp)							\
+do {									\
+	struct io_stack_location *_irp_sl;				\
+	_irp_sl = IoGetCurrentIrpStackLocation(_irp);			\
+	IOTRACE("irp: %p, stack size: %d, cl: %d, sl: %p, dev_obj: %p, " \
+		"mj_fn: %d, minor_fn: %d, nt_urb: %p, event: %p",	\
+		_irp, _irp->stack_count, (_irp)->current_location,	\
+		_irp_sl, _irp_sl->dev_obj, _irp_sl->major_fn,		\
+		_irp_sl->minor_fn, IRP_URB(_irp),			\
+		(_irp)->user_event);					\
+} while (0)
+#else
+#define DUMP_IRP(_irp) do { } while (0)
+#endif
+
+#endif // _NTOSKERNEL_H_
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/rtl.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/rtl.c
@@ -0,0 +1,716 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ntoskernel.h"
+#include "rtl_exports.h"
+
+wstdcall SIZE_T WIN_FUNC(RtlCompareMemory,3)
+	(const void *a, const void *b, SIZE_T len)
+{
+	size_t i;
+	char *x, *y;
+
+	x = (char *)a;
+	y = (char *)b;
+	/* MSDN says this should return number of bytes that compare as
+	 * equal. This can be interpretted as either all bytes that are
+	 * equal in 'len' bytes or that only until the bytes compare as
+	 * not equal. Initially we had it the former way, but Realtek driver
+	 * doesn't like it that way - it takes many attempts to associate
+	 * with WPA. ReactOS returns the number of bytes that are equal
+	 * upto when they compare as not equal.
+	 * According to lords at #reactos, that is the way it should be
+	 * and that msdn is wrong about it!
+	 */
+	for (i = 0; i < len && x[i] == y[i]; i++)
+		;
+	return i;
+}
+
+wstdcall void WIN_FUNC(RtlCopyMemory,3)
+	(void *dst, const void *src, SIZE_T length)
+{
+	memcpy(dst, src, length);
+}
+
+wstdcall void WIN_FUNC(RtlZeroMemory,2)
+	(void *dst, SIZE_T length)
+{
+	memset(dst, 0, length);
+}
+
+wstdcall void WIN_FUNC(RtlSecureZeroMemory,2)
+	(void *dst, SIZE_T length)
+{
+	memset(dst, 0, length);
+}
+
+wstdcall void WIN_FUNC(RtlFillMemory,3)
+	(void *dest, SIZE_T length, UCHAR fill)
+{
+	memset(dest, fill, length);
+}
+
+wstdcall void WIN_FUNC(RtlMoveMemory,3)
+	(void *dest, const void *src, SIZE_T length)
+{
+	memmove(dest, src, length);
+}
+
+wstdcall LONG WIN_FUNC(RtlCompareString,3)
+	(const struct ansi_string *s1, const struct ansi_string *s2,
+	 BOOLEAN case_insensitive)
+{
+	unsigned int len;
+	LONG ret = 0;
+	const char *p1, *p2;
+
+	ENTER2("");
+	len = min(s1->length, s2->length);
+	p1 = s1->buf;
+	p2 = s2->buf;
+	if (case_insensitive)
+		while (!ret && len--)
+			ret = toupper(*p1++) - toupper(*p2++);
+	else
+		while (!ret && len--)
+			ret = *p1++ - *p2++;
+	if (!ret)
+		ret = s1->length - s2->length;
+	EXIT2(return ret);
+}
+
+wstdcall LONG WIN_FUNC(RtlCompareUnicodeString,3)
+	(const struct unicode_string *s1, const struct unicode_string *s2,
+	 BOOLEAN case_insensitive)
+{
+	unsigned int len;
+	LONG ret = 0;
+	const wchar_t *p1, *p2;
+
+	ENTER2("");
+
+	len = min(s1->length, s2->length) / sizeof(wchar_t);
+	p1 = s1->buf;
+	p2 = s2->buf;
+	if (case_insensitive)
+		while (!ret && len--)
+			ret = toupper((u8)*p1++) - toupper((u8)*p2++);
+	else
+		while (!ret && len--)
+			ret = (u8)*p1++ - (u8)*p2++;
+	if (!ret)
+		ret = s1->length - s2->length;
+	TRACE2("len: %d, ret: %d", len, ret);
+	EXIT2(return ret);
+}
+
+wstdcall BOOLEAN WIN_FUNC(RtlEqualString,3)
+	(const struct ansi_string *s1, const struct ansi_string *s2,
+	 BOOLEAN case_insensitive)
+{
+	ENTER1("");
+	if (s1->length != s2->length)
+		return FALSE;
+	return !RtlCompareString(s1, s2, case_insensitive);
+}
+
+wstdcall BOOLEAN WIN_FUNC(RtlEqualUnicodeString,3)
+	(const struct unicode_string *s1, const struct unicode_string *s2,
+	 BOOLEAN case_insensitive)
+{
+	if (s1->length != s2->length)
+		return FALSE;
+	return !RtlCompareUnicodeString(s1, s2, case_insensitive);
+}
+
+wstdcall void WIN_FUNC(RtlCopyUnicodeString,2)
+	(struct unicode_string *dst, struct unicode_string *src)
+{
+	ENTER1("%p, %p", dst, src);
+	if (src && src->buf && dst->buf) {
+		dst->length = min(src->length, dst->max_length);
+		memcpy(dst->buf, src->buf, dst->length);
+		if (dst->length < dst->max_length)
+			dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
+	} else
+		dst->length = 0;
+	EXIT1(return);
+}
+
+wstdcall void WIN_FUNC(RtlCopyString,2)
+	(struct ansi_string *dst, struct ansi_string *src)
+{
+	ENTER1("%p, %p", dst, src);
+	if (src && src->buf && dst->buf) {
+		dst->length = min(src->length, dst->max_length);
+		memcpy(dst->buf, src->buf, dst->length);
+		if (dst->length < dst->max_length)
+			dst->buf[dst->length] = 0;
+	} else
+		dst->length = 0;
+	EXIT1(return);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeToString,2)
+	(struct unicode_string *dst, wchar_t *src)
+{
+	if (src) {
+		int len;
+		for (len = 0; src[len]; len++)
+			;
+		if (dst->length + (len * sizeof(dst->buf[0])) > dst->max_length)
+			return STATUS_BUFFER_TOO_SMALL;
+		memcpy(&dst->buf[dst->length], src, len * sizeof(dst->buf[0]));
+		dst->length += len * sizeof(dst->buf[0]);
+		if (dst->max_length > dst->length)
+			dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
+	}
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeStringToString,2)
+	(struct unicode_string *dst, struct unicode_string *src)
+{
+	if (dst->max_length < src->length + dst->length)
+		return STATUS_BUFFER_TOO_SMALL;
+	if (src->length) {
+		memcpy(&dst->buf[dst->length], src->buf, src->length);
+		dst->length += src->length;
+		if (dst->max_length > dst->length)
+			dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
+	}
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall ULONG WIN_FUNC(RtlxAnsiStringToUnicodeSize,1)
+	(const struct ansi_string *string)
+{
+	int i;
+
+	for (i = 0; i < string->max_length && string->buf[i]; i++)
+		;
+	return i * sizeof(wchar_t);
+}
+
+wstdcall ULONG WIN_FUNC(RtlxUnicodeStringToAnsiSize,1)
+	(const struct unicode_string *string)
+{
+	int i;
+
+	for (i = 0; i < string->max_length && string->buf[i]; i++)
+		;
+	return i;
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlAnsiStringToUnicodeString,3)
+	(struct unicode_string *dst, const struct ansi_string *src,
+	 BOOLEAN alloc)
+{
+	int i, n;
+
+	n = RtlxAnsiStringToUnicodeSize(src);
+	TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
+	       src->max_length, src->buf);
+	if (alloc == TRUE) {
+#if 0
+		if (n == 0) {
+			dst->length = dst->max_length = 0;
+			dst->buf = NULL;
+			EXIT2(return STATUS_SUCCESS);
+		}
+#endif
+		dst->max_length = n + sizeof(dst->buf[0]);
+		dst->buf = ExAllocatePoolWithTag(NonPagedPool,
+						 dst->max_length, 0);
+		if (!dst->buf) {
+			dst->max_length = dst->length = 0;
+			EXIT2(return STATUS_NO_MEMORY);
+		}
+	} else if (dst->max_length < n)
+		EXIT2(return STATUS_BUFFER_TOO_SMALL);
+
+	dst->length = n;
+	n /= sizeof(dst->buf[0]);
+	for (i = 0; i < n; i++)
+		dst->buf[i] = src->buf[i];
+	if (i * sizeof(dst->buf[0]) < dst->max_length)
+		dst->buf[i] = 0;
+	TRACE2("dst: length: %d, max_length: %d, string: %p",
+	       dst->length, dst->max_length, src->buf);
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToAnsiString,3)
+	(struct ansi_string *dst, const struct unicode_string *src,
+	 BOOLEAN alloc)
+{
+	int i, n;
+
+	n = RtlxUnicodeStringToAnsiSize(src);
+	TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
+	       src->max_length, src->buf);
+	if (alloc == TRUE) {
+#if 0
+		if (n == 0) {
+			dst->length = dst->max_length = 0;
+			dst->buf = NULL;
+			EXIT2(return STATUS_SUCCESS);
+		}
+#endif
+		dst->max_length = n + sizeof(dst->buf[0]);
+		dst->buf = ExAllocatePoolWithTag(NonPagedPool,
+						 dst->max_length, 0);
+		if (!dst->buf) {
+			dst->max_length = dst->length = 0;
+			EXIT1(return STATUS_NO_MEMORY);
+		}
+	} else if (dst->max_length < n)
+		EXIT2(return STATUS_BUFFER_TOO_SMALL);
+
+	dst->length = n;
+	for (i = 0; i < n; i++)
+		dst->buf[i] = src->buf[i];
+	if (i < dst->max_length)
+		dst->buf[i] = 0;
+	TRACE2("string: %p, len: %d(%d)", dst->buf, dst->length,
+	       dst->max_length);
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToInteger,3)
+	(struct unicode_string *ustring, ULONG base, ULONG *value)
+{
+	int i, sign = 1;
+	ULONG res;
+	typeof(ustring->buf) string;
+
+	if (ustring->length == 0) {
+		*value = 0;
+		return STATUS_SUCCESS;
+	}
+
+	string = ustring->buf;
+	i = 0;
+	while (i < (ustring->length / sizeof(*string)) && string[i] == ' ')
+		i++;
+	if (string[i] == '+')
+		i++;
+	else if (string[i] == '-') {
+		i++;
+		sign = -1;
+	}
+	if (base == 0) {
+		base = 10;
+		if (i <= ((ustring->length / sizeof(*string)) - 2) &&
+		    string[i] == '0') {
+			i++;
+			if (string[i] == 'b') {
+				base = 2;
+				i++;
+			} else if (string[i] == 'o') {
+				base = 8;
+				i++;
+			} else if (string[i] == 'x') {
+				base = 16;
+				i++;
+			}
+		}
+	}
+	if (!(base == 2 || base == 8 || base == 10 || base == 16))
+		EXIT2(return STATUS_INVALID_PARAMETER);
+
+	for (res = 0; i < (ustring->length / sizeof(*string)); i++) {
+		int v;
+		if (isdigit((char)string[i]))
+			v = string[i] - '0';
+		else if (isxdigit((char)string[i]))
+			v = tolower((char)string[i]) - 'a' + 10;
+		else
+			v = base;
+		if (v >= base)
+			EXIT2(return STATUS_INVALID_PARAMETER);
+		res = res * base + v;
+	}
+	*value = sign * res;
+	EXIT3(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlCharToInteger,3)
+	(const char *string, ULONG base, ULONG *value)
+{
+	int sign = 1;
+	ULONG res;
+
+	if (!string || !value)
+		EXIT2(return STATUS_INVALID_PARAMETER);
+	while (*string == ' ')
+		string++;
+	if (*string == '+')
+		string++;
+	else if (*string == '-') {
+		string++;
+		sign = -1;
+	}
+	if (base == 0) {
+		base = 10;
+		if (*string == '0') {
+			string++;
+			if (*string == 'b') {
+				base = 2;
+				string++;
+			} else if (*string == 'o') {
+				base = 8;
+				string++;
+			} else if (*string == 'x') {
+				base = 16;
+				string++;
+			}
+		}
+	}
+	if (!(base == 2 || base == 8 || base == 10 || base == 16))
+		EXIT2(return STATUS_INVALID_PARAMETER);
+
+	for (res = 0; *string; string++) {
+		int v;
+		if (isdigit(*string))
+			v = *string - '0';
+		else if (isxdigit(*string))
+			v = tolower(*string) - 'a' + 10;
+		else
+			v = base;
+		if (v >= base)
+			EXIT2(return STATUS_INVALID_PARAMETER);
+		res = res * base + v;
+	}
+	*value = sign * res;
+	EXIT3(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlIntegerToUnicodeString,3)
+	(ULONG value, ULONG base, struct unicode_string *ustring)
+{
+	typeof(ustring->buf) buf = ustring->buf;
+	int i;
+
+	if (base == 0)
+		base = 10;
+	if (!(base == 2 || base == 8 || base == 10 || base == 16))
+		return STATUS_INVALID_PARAMETER;
+	for (i = 0; value && i < ustring->max_length / sizeof(*buf); i++) {
+		int r;
+		r = value % base;
+		value /= base;
+		if (r < 10)
+			buf[i] = r + '0';
+		else
+			buf[i] = r + 'a' - 10;
+	}
+	if (value)
+		return STATUS_BUFFER_OVERFLOW;
+	ustring->length = i * sizeof(*buf);
+	return STATUS_SUCCESS;
+}
+
+wstdcall LARGE_INTEGER WIN_FUNC(RtlConvertUlongToLargeInteger,1)
+	(ULONG ul)
+{
+	LARGE_INTEGER li = ul;
+	return li;
+}
+
+wfastcall USHORT WIN_FUNC(RtlUshortByteSwap,1)
+	(USHORT src)
+{
+	return __swab16(src);
+}
+
+wfastcall ULONG WIN_FUNC(RtlUlongByteSwap,1)
+	(ULONG src)
+{
+	/* ULONG is 32 bits for both 32-bit and 64-bit architectures */
+	return __swab32(src);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlUpcaseUnicodeString,3)
+	(struct unicode_string *dst, struct unicode_string *src, BOOLEAN alloc)
+{
+	USHORT i, n;
+
+	if (alloc) {
+		dst->buf = ExAllocatePoolWithTag(NonPagedPool, src->length, 0);
+		if (dst->buf)
+			dst->max_length = src->length;
+		else
+			EXIT2(return STATUS_NO_MEMORY);
+	} else {
+		if (dst->max_length < src->length)
+			EXIT2(return STATUS_BUFFER_OVERFLOW);
+	}
+
+	n = src->length / sizeof(src->buf[0]);
+	for (i = 0; i < n; i++)
+		dst->buf[i] = toupper(src->buf[i]);
+
+	dst->length = src->length;
+	EXIT3(return STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(RtlInitUnicodeString,2)
+	(struct unicode_string *dst, const wchar_t *src)
+{
+	ENTER2("%p", dst);
+	if (dst == NULL)
+		EXIT1(return);
+	if (src == NULL) {
+		dst->max_length = dst->length = 0;
+		dst->buf = NULL;
+	} else {
+		int i;
+		for (i = 0; (char)src[i]; i++)
+			;
+		dst->buf = (typeof(dst->buf))src;
+		dst->length = i * sizeof(dst->buf[0]);
+		dst->max_length = (i + 1) * sizeof(dst->buf[0]);
+	}
+	EXIT1(return);
+}
+
+wstdcall void WIN_FUNC(RtlInitAnsiString,2)
+	(struct ansi_string *dst, const char *src)
+{
+	ENTER2("%p", dst);
+	if (dst == NULL)
+		EXIT2(return);
+	if (src == NULL) {
+		dst->max_length = dst->length = 0;
+		dst->buf = NULL;
+	} else {
+		int i;
+		for (i = 0; src[i]; i++)
+			;
+		dst->buf = (typeof(dst->buf))src;
+		dst->length = i;
+		dst->max_length = i + 1;
+	}
+	TRACE2("%p", dst->buf);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(RtlInitString,2)
+	(struct ansi_string *dst, const char *src)
+{
+	ENTER2("%p", dst);
+	RtlInitAnsiString(dst, src);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(RtlFreeUnicodeString,1)
+	(struct unicode_string *string)
+{
+	ENTER2("%p", string);
+	if (string == NULL)
+		return;
+	if (string->buf)
+		ExFreePool(string->buf);
+	string->length = string->max_length = 0;
+	string->buf = NULL;
+	return;
+}
+
+wstdcall void WIN_FUNC(RtlFreeAnsiString,1)
+	(struct ansi_string *string)
+{
+	ENTER2("%p", string);
+	if (string == NULL)
+		return;
+	if (string->buf)
+		ExFreePool(string->buf);
+	string->length = string->max_length = 0;
+	string->buf = NULL;
+	return;
+}
+
+/* guid string is of the form: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
+wstdcall NTSTATUS WIN_FUNC(RtlGUIDFromString,2)
+	(struct unicode_string *guid_string, struct guid *guid)
+{
+	struct ansi_string ansi;
+	NTSTATUS ret;
+	int i, j, k, l, m;
+
+	ret = RtlUnicodeStringToAnsiString(&ansi, guid_string, TRUE);
+	if (ret != STATUS_SUCCESS)
+		return ret;
+	if (ansi.length != 37 || ansi.buf[0] != '{' ||
+	    ansi.buf[36] != '}' || ansi.buf[9] != '-' ||
+	    ansi.buf[14] != '-' || ansi.buf[19] != '-' ||
+	    ansi.buf[24] != '-') {
+		RtlFreeAnsiString(&ansi);
+		EXIT2(return STATUS_INVALID_PARAMETER);
+	}
+	memcpy(&guid->data4, &ansi.buf[29], sizeof(guid->data3));
+	/* set end of data3 for scanf */
+	ansi.buf[29] = 0;
+	if (sscanf(&ansi.buf[1], "%x", &i) == 1 &&
+	    sscanf(&ansi.buf[10], "%x", &j) == 1 &&
+	    sscanf(&ansi.buf[15], "%x", &k) == 1 &&
+	    sscanf(&ansi.buf[20], "%x", &l) == 1 &&
+	    sscanf(&ansi.buf[25], "%x", &m) == 1) {
+		guid->data1 = (i << 16) | (j < 8) | k;
+		guid->data2 = l;
+		guid->data3 = m;
+		ret = STATUS_SUCCESS;
+	} else
+		ret = STATUS_INVALID_PARAMETER;
+	RtlFreeAnsiString(&ansi);
+	return ret;
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlQueryRegistryValues,5)
+	(ULONG relative, wchar_t *path, struct rtl_query_registry_table *tbl,
+	 void *context, void *env)
+{
+	struct ansi_string ansi;
+	struct unicode_string unicode;
+	NTSTATUS status, ret;
+	static int i = 0;
+
+	ENTER3("%x, %p", relative, tbl);
+//	TODO();
+
+	RtlInitUnicodeString(&unicode, path);
+	if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE2("%s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	ret = STATUS_SUCCESS;
+	for (; tbl->name; tbl++) {
+		RtlInitUnicodeString(&unicode, tbl->name);
+		if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
+		    STATUS_SUCCESS) {
+			TRACE2("name: %s", ansi.buf);
+			RtlFreeAnsiString(&ansi);
+		}
+		TRACE2("flags: %08X", tbl->flags);
+		if (tbl->flags == RTL_QUERY_REGISTRY_DIRECT) {
+			TRACE2("type: %08X", tbl->def_type);
+			if (tbl->def_type == REG_DWORD) {
+				/* Atheros USB driver needs this, but
+				 * don't know where and how to get its
+				 * value */
+				if (tbl->def_data) {
+					TRACE2("def_data: %x",
+					       *(int *)tbl->def_data);
+					*(DWORD *)tbl->context = 0x5f292a + i++;
+//						*(DWORD *)tbl->def_data;
+				} else
+					*(DWORD *)tbl->context = 0x2345dbe;
+			}
+		} else {
+			void *data;
+			ULONG type, length;
+
+			if (!tbl->query_func) {
+				ERROR("oops: no query_func");
+				ret = STATUS_INVALID_PARAMETER;
+				break;
+			}
+			if (tbl->flags & RTL_QUERY_REGISTRY_NOVALUE) {
+				data = NULL;
+				type = REG_NONE;
+				length = 0;
+			} else {
+				data = tbl->def_data;
+				type = tbl->def_type;
+				length = tbl->def_length;;
+			}
+			TRACE2("calling query_func: %p", tbl->query_func);
+			status = LIN2WIN6(tbl->query_func, tbl->name, type,
+					  data, length, context, env);
+			TRACE2("status: %08X", status);
+			if (status) {
+				if (status == STATUS_BUFFER_TOO_SMALL)
+					ret = STATUS_BUFFER_TOO_SMALL;
+				else
+					EXIT2(return STATUS_INVALID_PARAMETER);
+			}
+		}
+	}
+	EXIT3(return ret);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlWriteRegistryValue,6)
+	(ULONG relative, wchar_t *path, wchar_t *name, ULONG type,
+	 void *data, ULONG length)
+{
+	struct ansi_string ansi;
+	struct unicode_string unicode;
+
+	ENTER3("%d", relative);
+	TODO();
+
+	RtlInitUnicodeString(&unicode, path);
+	if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE2("%s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	RtlInitUnicodeString(&unicode, name);
+	if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE2("%s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	EXIT5(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(RtlDeleteRegistryValue,3)
+	(ULONG relative, wchar_t *path, wchar_t *name)
+{
+	return STATUS_SUCCESS;
+}
+
+wstdcall void WIN_FUNC(RtlAssert,4)
+	(char *failed_assertion, char *file_name, ULONG line_num, char *message)
+{
+	ERROR("assertion '%s' failed at %s line %d%s",
+	      failed_assertion, file_name, line_num, message ? message : "");
+	return;
+}
+
+wstdcall void WIN_FUNC(RtlUnwind,0)
+	(void)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(RtlRaiseException,1)
+	(void *exception_record)
+{
+	TODO();
+}
+
+int rtl_init(void)
+{
+	return 0;
+}
+
+/* called when module is being removed */
+void rtl_exit(void)
+{
+	EXIT4(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ndiswrapper.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ndiswrapper.h
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _NDISWRAPPER_H_
+#define _NDISWRAPPER_H_
+
+#define DRIVER_VERSION "1.55"
+#define UTILS_VERSION "1.9"
+
+#define DRIVER_NAME "ndiswrapper"
+#define DRIVER_CONFIG_DIR "/etc/ndiswrapper"
+
+#define SSID_MAX_WPA_IE_LEN 40
+#define NDIS_ESSID_MAX_SIZE 32
+#define NDIS_ENCODING_TOKEN_MAX 32
+#define MAX_ENCR_KEYS 4
+#define TX_RING_SIZE 16
+#define NDIS_MAX_RATES 8
+#define NDIS_MAX_RATES_EX 16
+#define WLAN_EID_GENERIC 221
+#define MAX_WPA_IE_LEN 64
+#define MAX_STR_LEN 512
+
+#define WRAP_PCI_BUS 5
+#define WRAP_PCMCIA_BUS 8
+/* some USB devices, e.g., DWL-G120 have BusType as 0 */
+#define WRAP_INTERNAL_BUS 0
+/* documentation at msdn says 15 is PNP bus, but inf files from all
+ * vendors say 15 is USB; which is correct? */
+#define WRAP_USB_BUS 15
+
+/* NDIS device must be 0, for compatability with old versions of
+ * ndiswrapper where device type for NDIS drivers is 0 */
+#define WRAP_NDIS_DEVICE 0
+#define WRAP_USB_DEVICE 1
+#define WRAP_BLUETOOTH_DEVICE1 2
+#define WRAP_BLUETOOTH_DEVICE2 3
+
+#define WRAP_DEVICE_BUS(dev, bus) ((dev) << 8 | (bus))
+#define WRAP_BUS(dev_bus) ((dev_bus) & 0x000FF)
+#define WRAP_DEVICE(dev_bus) ((dev_bus) >> 8)
+
+#define MAX_DRIVER_NAME_LEN 32
+#define MAX_VERSION_STRING_LEN 64
+#define MAX_SETTING_NAME_LEN 128
+#define MAX_SETTING_VALUE_LEN 256
+
+#define MAX_DRIVER_PE_IMAGES 4
+#define MAX_DRIVER_BIN_FILES 5
+#define MAX_DEVICE_SETTINGS 512
+
+#define MAX_ALLOCATED_URBS 15
+
+#define DEV_ANY_ID -1
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTRSEP "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MACSTR "%02x%02x%02x%02x%02x%02x"
+#define MACINTADR(a) (int*)&((a)[0]), (int*)&((a)[1]), (int*)&((a)[2]), \
+		(int*)&((a)[3]), (int*)&((a)[4]), (int*)&((a)[5])
+
+#ifdef __KERNEL__
+/* DEBUG macros */
+
+#define MSG(level, fmt, ...)				\
+	printk(level "ndiswrapper (%s:%d): " fmt "\n",	\
+	       __func__, __LINE__ , ## __VA_ARGS__)
+
+#define WARNING(fmt, ...) MSG(KERN_WARNING, fmt, ## __VA_ARGS__)
+#define ERROR(fmt, ...) MSG(KERN_ERR, fmt , ## __VA_ARGS__)
+#define INFO(fmt, ...) MSG(KERN_INFO, fmt , ## __VA_ARGS__)
+#define TODO() WARNING("not fully implemented (yet)")
+
+#define TRACE(fmt, ...) do { } while (0)
+#define TRACE1(fmt, ...) do { } while (0)
+#define TRACE2(fmt, ...) do { } while (0)
+#define TRACE3(fmt, ...) do { }  while (0)
+#define TRACE4(fmt, ...) do { } while (0)
+#define TRACE5(fmt, ...) do { } while (0)
+#define TRACE6(fmt, ...) do { } while (0)
+
+/* for a block of code */
+#define DBG_BLOCK(level) while (0)
+
+extern int debug;
+
+#if defined DEBUG
+#undef TRACE
+#define TRACE(level, fmt, ...)				       \
+do {								       \
+	if (debug >= level)					       \
+		printk(KERN_INFO "%s (%s:%d): " fmt "\n", DRIVER_NAME, \
+		       __func__, __LINE__ , ## __VA_ARGS__);       \
+} while (0)
+#undef DBG_BLOCK
+#define DBG_BLOCK(level) if (debug >= level)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 1
+#undef TRACE1
+#define TRACE1(fmt, ...) TRACE(1, fmt , ## __VA_ARGS__)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 2
+#undef TRACE2
+#define TRACE2(fmt, ...) TRACE(2, fmt , ## __VA_ARGS__)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 3
+#undef TRACE3
+#define TRACE3(fmt, ...) TRACE(3, fmt , ## __VA_ARGS__)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 4
+#undef TRACE4
+#define TRACE4(fmt, ...) TRACE(4, fmt , ## __VA_ARGS__)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 5
+#undef TRACE5
+#define TRACE5(fmt, ...) TRACE(5, fmt , ## __VA_ARGS__)
+#endif
+
+#if defined(DEBUG) && DEBUG >= 6
+#undef TRACE6
+#define TRACE6(fmt, ...) TRACE(6, fmt , ## __VA_ARGS__)
+#endif
+
+#define ENTER1(fmt, ...) TRACE1("Enter " fmt , ## __VA_ARGS__)
+#define ENTER2(fmt, ...) TRACE2("Enter " fmt , ## __VA_ARGS__)
+#define ENTER3(fmt, ...) TRACE3("Enter " fmt , ## __VA_ARGS__)
+#define ENTER4(fmt, ...) TRACE4("Enter " fmt , ## __VA_ARGS__)
+#define ENTER5(fmt, ...) TRACE5("Enter " fmt , ## __VA_ARGS__)
+#define ENTER6(fmt, ...) TRACE6("Enter " fmt , ## __VA_ARGS__)
+
+#define EXIT1(stmt) do { TRACE1("Exit"); stmt; } while(0)
+#define EXIT2(stmt) do { TRACE2("Exit"); stmt; } while(0)
+#define EXIT3(stmt) do { TRACE3("Exit"); stmt; } while(0)
+#define EXIT4(stmt) do { TRACE4("Exit"); stmt; } while(0)
+#define EXIT5(stmt) do { TRACE5("Exit"); stmt; } while(0)
+#define EXIT6(stmt) do { TRACE6("Exit"); stmt; } while(0)
+
+#if defined(USB_DEBUG)
+#define USBTRACE TRACE1
+#define USBENTER ENTER1
+#define USBEXIT EXIT1
+#else
+#define USBTRACE(fmt, ...)
+#define USBENTER(fmt, ...)
+#define USBEXIT(stmt) stmt
+#endif
+
+#if defined(EVENT_DEBUG)
+#define EVENTTRACE TRACE1
+#define EVENTENTER ENTER1
+#define EVENTEXIT EXIT1
+#else
+#define EVENTTRACE(fmt, ...)
+#define EVENTENTER(fmt, ...)
+#define EVENTEXIT(stmt) stmt
+#endif
+
+#if defined(TIMER_DEBUG)
+#define TIMERTRACE TRACE1
+#define TIMERENTER ENTER1
+#define TIMEREXIT EXIT1
+#else
+#define TIMERTRACE(fmt, ...)
+#define TIMERENTER(fmt, ...)
+#define TIMEREXIT(stmt) stmt
+#endif
+
+#if defined(IO_DEBUG)
+#define IOTRACE TRACE1
+#define IOENTER ENTER1
+#define IOEXIT EXIT1
+#else
+#define IOTRACE(fmt, ...)
+#define IOENTER(fmt, ...)
+#define IOEXIT(stmt) stmt
+#endif
+
+#if defined(WORK_DEBUG)
+#define WORKTRACE TRACE1
+#define WORKENTER ENTER1
+#define WORKEXIT EXIT1
+#else
+#define WORKTRACE(fmt, ...)
+#define WORKENTER(fmt, ...)
+#define WORKEXIT(stmt) stmt
+#endif
+
+#ifdef DEBUG
+#define assert(expr)							\
+do {									\
+	if (!(expr)) {							\
+		ERROR("assertion '%s' failed", #expr);			\
+		dump_stack();						\
+	}								\
+} while (0)
+#else
+#define assert(expr) do { } while (0)
+#endif
+
+#endif // __KERNEL__
+
+#endif // NDISWRAPPER_H
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/lin2win.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/lin2win.h
@@ -0,0 +1,202 @@
+/*
+ *  Copyright (C) 2006 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifdef CONFIG_X86_64
+
+/* Windows functions must have 32 bytes of shadow space for arguments
+ * above return address, irrespective of number of args. So argc >= 4
+ */
+
+#define alloc_win_stack_frame(argc)		\
+	"sub $(" #argc "+1)*8, %%rsp\n\t"
+#define free_win_stack_frame(argc)		\
+	"add $(" #argc "+1)*8, %%rsp\n\t"
+
+/* m is index of Windows arg required; Windows arg 1 should be at
+ * 0(%rsp), arg 2 at 8(%rsp) and so on after the frame is allocated.
+*/
+
+#define lin2win_win_arg(m) "(" #m "-1)*8(%%rsp)"
+
+/* args for Windows function must be in clobber / output list */
+
+#define outputs()							\
+	"=a" (_ret), "=c" (_dummy), "=d" (_dummy),			\
+		"=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
+
+#define clobbers() "cc"
+
+#define LIN2WIN0(func)							\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8");					\
+	register u64 r9 __asm__("r9");					\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(4)				\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(4)					\
+		: outputs()						\
+		: [fptr] "r" (func)					\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN1(func, arg1)						\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8");					\
+	register u64 r9 __asm__("r9");					\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(4)				\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(4)					\
+		: outputs()						\
+		: "c" (arg1), [fptr] "r" (func)				\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN2(func, arg1, arg2)					\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8");					\
+	register u64 r9 __asm__("r9");					\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(4)				\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(4)					\
+		: outputs()						\
+		: "c" (arg1), "d" (arg2), [fptr] "r" (func)		\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN3(func, arg1, arg2, arg3)				\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8") = (u64)arg3;			\
+	register u64 r9 __asm__("r9");					\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(4)				\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(4)					\
+		: outputs()						\
+		: "c" (arg1), "d" (arg2), "r" (r8),			\
+		  [fptr] "r" (func)					\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN4(func, arg1, arg2, arg3, arg4)				\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8") = (u64)arg3;			\
+	register u64 r9 __asm__("r9") = (u64)arg4;			\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(4)				\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(4)					\
+		: outputs()						\
+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),		\
+		  [fptr] "r" (func)					\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5)			\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8") = (u64)arg3;			\
+	register u64 r9 __asm__("r9") = (u64)arg4;			\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(5)				\
+		"movq %[rarg5], " lin2win_win_arg(5) "\n\t"		\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(5)					\
+		: outputs()						\
+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),		\
+		  [rarg5] "ri" ((u64)arg5),				\
+		  [fptr] "r" (func)					\
+		: clobbers());						\
+	_ret;								\
+})
+
+#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6)		\
+({									\
+	u64 _ret, _dummy;						\
+	register u64 r8 __asm__("r8") = (u64)arg3;			\
+	register u64 r9 __asm__("r9") = (u64)arg4;			\
+	register u64 r10 __asm__("r10");				\
+	register u64 r11 __asm__("r11");				\
+	__asm__ __volatile__(						\
+		alloc_win_stack_frame(6)				\
+		"movq %[rarg5], " lin2win_win_arg(5) "\n\t"		\
+		"movq %[rarg6], " lin2win_win_arg(6) "\n\t"		\
+		"callq *%[fptr]\n\t"					\
+		free_win_stack_frame(6)					\
+		: outputs()						\
+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),		\
+		  [rarg5] "ri" ((u64)arg5), [rarg6] "ri" ((u64)arg6),	\
+		  [fptr] "r" (func)					\
+		: clobbers());						\
+	_ret;								\
+})
+
+#else // CONFIG_X86_64
+
+#define LIN2WIN1(func, arg1)						\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1);							\
+})
+#define LIN2WIN2(func, arg1, arg2)					\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1, arg2);						\
+})
+#define LIN2WIN3(func, arg1, arg2, arg3)				\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1, arg2, arg3);						\
+})
+#define LIN2WIN4(func, arg1, arg2, arg3, arg4)				\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1, arg2, arg3, arg4);					\
+})
+#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5)			\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1, arg2, arg3, arg4, arg5);				\
+})
+#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6)		\
+({									\
+	TRACE6("calling %p", func);					\
+	func(arg1, arg2, arg3, arg4, arg5, arg6);			\
+})
+
+#endif // CONFIG_X86_64
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/winnt_types.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/winnt_types.h
@@ -0,0 +1,1702 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _WINNT_TYPES_H_
+#define _WINNT_TYPES_H_
+
+#define TRUE				1
+#define FALSE				0
+
+#define PASSIVE_LEVEL			0
+#define APC_LEVEL			1
+#define DISPATCH_LEVEL			2
+#define DEVICE_LEVEL_BASE		4
+
+/* soft interrupts / bottom-half's are disabled at SOFT_IRQL */
+#define SOFT_IRQL			(DEVICE_LEVEL_BASE + 1)
+#define DIRQL				(DEVICE_LEVEL_BASE + 2)
+
+#define STATUS_WAIT_0			0
+#define STATUS_SUCCESS                  0
+#define STATUS_ALERTED                  0x00000101
+#define STATUS_TIMEOUT                  0x00000102
+#define STATUS_PENDING                  0x00000103
+#define STATUS_FAILURE                  0xC0000001
+#define STATUS_NOT_IMPLEMENTED		0xC0000002
+#define STATUS_INVALID_PARAMETER        0xC000000D
+#define STATUS_INVALID_DEVICE_REQUEST	0xC0000010
+#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
+#define STATUS_ACCESS_DENIED            0xC0000022
+#define STATUS_BUFFER_TOO_SMALL         0xC0000023
+#define STATUS_OBJECT_NAME_INVALID      0xC0000023
+#define STATUS_MUTANT_NOT_OWNED		0xC0000046
+#define STATUS_RESOURCES                0xC000009A
+#define STATUS_DELETE_PENDING		0xC0000056
+#define STATUS_INSUFFICIENT_RESOURCES	0xC000009A
+#define STATUS_NOT_SUPPORTED            0xC00000BB
+#define STATUS_INVALID_PARAMETER_2      0xC00000F0
+#define STATUS_NO_MEMORY		0xC0000017
+#define STATUS_CANCELLED                0xC0000120
+#define STATUS_DEVICE_REMOVED		0xC00002B6
+#define STATUS_DEVICE_NOT_CONNECTED	0xC000009D
+
+#define STATUS_BUFFER_OVERFLOW		0x80000005
+
+#define SL_PENDING_RETURNED		0x01
+#define SL_INVOKE_ON_CANCEL		0x20
+#define SL_INVOKE_ON_SUCCESS		0x40
+#define SL_INVOKE_ON_ERROR		0x80
+
+#define IRP_MJ_CREATE			0x00
+#define IRP_MJ_CREATE_NAMED_PIPE	0x01
+#define IRP_MJ_CLOSE			0x02
+#define IRP_MJ_READ			0x03
+#define IRP_MJ_WRITE			0x04
+
+#define IRP_MJ_DEVICE_CONTROL		0x0E
+#define IRP_MJ_INTERNAL_DEVICE_CONTROL	0x0F
+#define IRP_MJ_POWER			0x16
+#define IRP_MJ_SYSTEM_CONTROL		0x0E
+#define IRP_MJ_PNP			0x1b
+#define IRP_MJ_MAXIMUM_FUNCTION		0x1b
+
+#define IRP_MN_WAIT_WAKE		0x00
+#define IRP_MN_POWER_SEQUENCE		0x01
+#define IRP_MN_SET_POWER		0x02
+#define IRP_MN_QUERY_POWER		0x03
+
+#define IRP_MN_REGINFO			0x08
+#define IRP_MN_REGINFO_EX		0x0b
+
+#define IRP_MN_START_DEVICE		0x00
+#define IRP_MN_QUERY_REMOVE_DEVICE	0x01
+#define IRP_MN_REMOVE_DEVICE		0x02
+#define IRP_MN_CANCEL_REMOVE_DEVICE	0x03
+#define IRP_MN_STOP_DEVICE		0x04
+#define IRP_MN_QUERY_STOP_DEVICE	0x05
+#define IRP_MN_CANCEL_STOP_DEVICE	0x06
+#define IRP_MN_QUERY_DEVICE_RELATIONS	0x07
+#define IRP_MN_QUERY_INTERFACE		0x08
+
+#define IRP_BUFFERED_IO			0x00000010
+#define IRP_DEALLOCATE_BUFFER		0x00000020
+#define IRP_INPUT_OPERATION		0x00000040
+
+#define IRP_DEFFER_IO_COMPLETION	0x00000800
+
+#define THREAD_WAIT_OBJECTS		3
+#define MAX_WAIT_OBJECTS		64
+
+#define LOW_PRIORITY			0
+#define LOW_REALTIME_PRIORITY		16
+#define HIGH_PRIORITY			31
+#define MAXIMUM_PRIORITY		32
+
+#define PROCESSOR_FEATURE_MAX		64
+
+#define IO_NO_INCREMENT			0
+
+#define WMIREG_ACTION_REGISTER		1
+#define WMIREG_ACTION_DEREGISTER	2
+#define WMIREG_ACTION_REREGISTER	3
+#define WMIREG_ACTION_UPDATE_GUIDS	4
+
+#define WMIREGISTER			0
+#define WMIUPDATE			1
+
+#ifdef CONFIG_X86_64
+#define wstdcall
+#define wfastcall
+#define noregparm
+
+#define KI_USER_SHARED_DATA 0xfffff78000000000UL
+
+#else
+
+#define noregparm __attribute__((regparm(0)))
+#define wstdcall __attribute__((__stdcall__, regparm(0)))
+#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ > 3) || __GNUC__ > 3)
+#undef fastcall
+#define wfastcall __attribute__((fastcall))
+#else
+#error "gcc 3.4 or newer should be used for compiling this module"
+#endif
+
+#define KI_USER_SHARED_DATA 0xffdf0000
+
+#endif
+
+#define packed __attribute__((packed))
+#define no_warn_unused __attribute__((unused))
+
+typedef u8	BOOLEAN;
+typedef u8	BYTE;
+typedef u8	*LPBYTE;
+typedef s8	CHAR;
+typedef u8	UCHAR;
+typedef s16	SHORT;
+typedef u16	USHORT;
+typedef u16	WORD;
+typedef s32	INT;
+typedef u32	UINT;
+typedef u32	DWORD;
+typedef s32	LONG;
+typedef u32	ULONG;
+typedef s64	LONGLONG;
+typedef u64	ULONGLONG;
+typedef u64	ULONGULONG;
+typedef u64	ULONG64;
+
+typedef CHAR CCHAR;
+typedef USHORT wchar_t;
+typedef SHORT CSHORT;
+typedef LONGLONG LARGE_INTEGER;
+
+typedef LONG NTSTATUS;
+
+typedef LONG KPRIORITY;
+typedef LARGE_INTEGER PHYSICAL_ADDRESS;
+typedef UCHAR KIRQL;
+typedef CHAR KPROCESSOR_MODE;
+
+/* ULONG_PTR is 32 bits on 32-bit platforms and 64 bits on 64-bit
+ * platform, which is same as 'unsigned long' in Linux */
+typedef unsigned long ULONG_PTR;
+
+typedef ULONG_PTR SIZE_T;
+typedef ULONG_PTR KAFFINITY;
+typedef ULONG ACCESS_MASK;
+
+typedef ULONG_PTR PFN_NUMBER;
+typedef ULONG SECURITY_INFORMATION;
+
+/* non-negative numbers indicate success */
+#define NT_SUCCESS(status)  ((NTSTATUS)(status) >= 0)
+
+struct ansi_string {
+	USHORT length;
+	USHORT max_length;
+	char *buf;
+};
+
+struct unicode_string {
+	USHORT length;
+	USHORT max_length;
+	wchar_t *buf;
+};
+
+struct nt_slist {
+	struct nt_slist *next;
+};
+
+#ifdef CONFIG_X86_64
+/* it is not clear how nt_slist_head is used to store pointer to
+ * slists and depth; here we assume 'align' field is used to store
+ * depth and 'region' field is used to store slist pointers */
+struct nt_slist_head {
+	union {
+		USHORT depth;
+		ULONGLONG align;
+	};
+	union {
+		ULONGLONG region;
+		struct nt_slist *next;
+	};
+} __attribute__((aligned(16)));
+typedef struct nt_slist_head nt_slist_header;
+#else
+union nt_slist_head {
+	ULONGLONG align;
+	struct {
+		struct nt_slist *next;
+		USHORT depth;
+		USHORT sequence;
+	};
+};
+typedef union nt_slist_head nt_slist_header;
+#endif
+
+struct nt_list {
+	struct nt_list *next;
+	struct nt_list *prev;
+};
+
+typedef ULONG_PTR NT_SPIN_LOCK;
+
+enum kdpc_importance {LowImportance, MediumImportance, HighImportance};
+
+struct kdpc;
+typedef void (*DPC)(struct kdpc *kdpc, void *ctx, void *arg1,
+		    void *arg2) wstdcall;
+struct kdpc {
+	SHORT type;
+	UCHAR nr_cpu;
+	UCHAR importance;
+	struct nt_list list;
+	DPC func;
+	void *ctx;
+	void *arg1;
+	void *arg2;
+	union {
+		NT_SPIN_LOCK *lock;
+		/* 'lock' is not used; 'queued' represents whether
+		 * kdpc is queued or not */
+		int queued;
+	};
+};
+
+enum pool_type {
+	NonPagedPool, PagedPool, NonPagedPoolMustSucceed, DontUseThisType,
+	NonPagedPoolCacheAligned, PagedPoolCacheAligned,
+	NonPagedPoolCacheAlignedMustS, MaxPoolType,
+	NonPagedPoolSession = 32,
+	PagedPoolSession = NonPagedPoolSession + 1,
+	NonPagedPoolMustSucceedSession = PagedPoolSession + 1,
+	DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1,
+	NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1,
+	PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1,
+	NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1
+};
+
+enum memory_caching_type_orig {
+	MmFrameBufferCached = 2
+};
+
+enum memory_caching_type {
+	MmNonCached = FALSE, MmCached = TRUE,
+	MmWriteCombined = MmFrameBufferCached, MmHardwareCoherentCached,
+	MmNonCachedUnordered, MmUSWCCached, MmMaximumCacheType
+};
+
+enum lock_operation {
+	IoReadAccess, IoWriteAccess, IoModifyAccess
+};
+
+enum mode {
+	KernelMode, UserMode, MaximumMode
+};
+
+struct mdl {
+	struct mdl *next;
+	CSHORT size;
+	CSHORT flags;
+	/* NdisFreeBuffer doesn't pass pool, so we store pool in
+	 * unused field 'process' */
+	union {
+		void *process;
+		void *pool;
+	};
+	void *mappedsystemva;
+	void *startva;
+	ULONG bytecount;
+	ULONG byteoffset;
+};
+
+#define MDL_MAPPED_TO_SYSTEM_VA		0x0001
+#define MDL_PAGES_LOCKED		0x0002
+#define MDL_SOURCE_IS_NONPAGED_POOL	0x0004
+#define MDL_ALLOCATED_FIXED_SIZE	0x0008
+#define MDL_PARTIAL			0x0010
+#define MDL_PARTIAL_HAS_BEEN_MAPPED	0x0020
+#define MDL_IO_PAGE_READ		0x0040
+#define MDL_WRITE_OPERATION		0x0080
+#define MDL_PARENT_MAPPED_SYSTEM_VA	0x0100
+#define MDL_FREE_EXTRA_PTES		0x0200
+#define MDL_IO_SPACE			0x0800
+#define MDL_NETWORK_HEADER		0x1000
+#define MDL_MAPPING_CAN_FAIL		0x2000
+#define MDL_ALLOCATED_MUST_SUCCEED	0x4000
+
+#define MDL_POOL_ALLOCATED		0x0400
+#define MDL_CACHE_ALLOCATED		0x8000
+
+#define PAGE_START(ptr) ((void *)((ULONG_PTR)(ptr) & ~(PAGE_SIZE - 1)))
+#define BYTE_OFFSET(ptr) ((ULONG)((ULONG_PTR)(ptr) & (PAGE_SIZE - 1)))
+
+#define MmGetMdlByteCount(mdl) ((mdl)->bytecount)
+#define MmGetMdlVirtualAddress(mdl) ((mdl)->startva + (mdl)->byteoffset)
+#define MmGetMdlByteOffset(mdl) ((mdl)->byteoffset)
+#define MmGetSystemAddressForMdl(mdl) ((mdl)->mappedsystemva)
+#define MmGetSystemAddressForMdlSafe(mdl, priority) ((mdl)->mappedsystemva)
+#define MmGetMdlPfnArray(mdl) ((PFN_NUMBER *)(mdl + 1))
+#define MmInitializeMdl(mdl, baseva, length)				\
+do {									\
+	(mdl)->next = NULL;						\
+	(mdl)->size = MmSizeOfMdl(baseva, length);			\
+	(mdl)->flags = 0;						\
+	(mdl)->startva = PAGE_START(baseva);				\
+	(mdl)->byteoffset = BYTE_OFFSET(baseva);			\
+	(mdl)->bytecount = length;					\
+	(mdl)->mappedsystemva = baseva;					\
+	TRACE4("%p %p %p %d %d", (mdl), baseva, (mdl)->startva,	\
+		  (mdl)->byteoffset, length);				\
+} while (0)
+
+struct kdevice_queue_entry {
+	struct nt_list list;
+	ULONG sort_key;
+	BOOLEAN inserted;
+};
+
+struct kdevice_queue {
+	USHORT type;
+	USHORT size;
+	struct nt_list list;
+	NT_SPIN_LOCK lock;
+	BOOLEAN busy;
+};
+
+struct wait_context_block {
+	struct kdevice_queue_entry wait_queue_entry;
+	void *device_routine;
+	void *device_context;
+	ULONG num_regs;
+	void *device_object;
+	void *current_irp;
+	void *buffer_chaining_dpc;
+};
+
+struct wait_block {
+	struct nt_list list;
+	struct task_struct *thread;
+	void *object;
+	int *wait_done;
+	USHORT wait_key;
+	USHORT wait_type;
+};
+
+struct dispatcher_header {
+	UCHAR type;
+	UCHAR absolute;
+	UCHAR size;
+	UCHAR inserted;
+	LONG signal_state;
+	struct nt_list wait_blocks;
+};
+
+enum event_type {
+	NotificationEvent,
+	SynchronizationEvent,
+};
+
+enum timer_type {
+	NotificationTimer = NotificationEvent,
+	SynchronizationTimer = SynchronizationEvent,
+};
+
+enum dh_type {
+	NotificationObject = NotificationEvent,
+	SynchronizationObject = SynchronizationEvent,
+	MutexObject,
+	SemaphoreObject,
+	ThreadObject,
+};
+
+enum wait_type {
+	WaitAll, WaitAny
+};
+
+/* objects that use dispatcher_header have it as the first field, so
+ * whenever we need to initialize dispatcher_header, we can convert
+ * that object into a nt_event and access dispatcher_header */
+struct nt_event {
+	struct dispatcher_header dh;
+};
+
+struct wrap_timer;
+
+#define WRAP_TIMER_MAGIC 47697249
+
+struct nt_timer {
+	struct dispatcher_header dh;
+	/* We can't fit Linux timer in this structure. Instead of
+	 * padding the nt_timer structure, we replace due_time field
+	 * with *wrap_timer and allocate memory for it when nt_timer is
+	 * initialized */
+	union {
+		ULONGLONG due_time;
+		struct wrap_timer *wrap_timer;
+	};
+	struct nt_list nt_timer_list;
+	struct kdpc *kdpc;
+	union {
+		LONG period;
+		LONG wrap_timer_magic;
+	};
+};
+
+struct nt_mutex {
+	struct dispatcher_header dh;
+	struct nt_list list;
+	struct task_struct *owner_thread;
+	BOOLEAN abandoned;
+	BOOLEAN apc_disable;
+};
+
+struct nt_semaphore {
+	struct dispatcher_header dh;
+	LONG limit;
+};
+
+struct nt_thread {
+	struct dispatcher_header dh;
+	/* the rest in Windows is a long structure; since this
+	 * structure is opaque to drivers, we just define what we
+	 * need */
+	int pid;
+	NTSTATUS status;
+	struct task_struct *task;
+	struct nt_list irps;
+	NT_SPIN_LOCK lock;
+	KPRIORITY prio;
+};
+
+#define set_object_type(dh, type)	((dh)->type = (type))
+#define is_notify_object(dh)		((dh)->type == NotificationObject)
+#define is_synch_object(dh)		((dh)->type == SynchronizationObject)
+#define is_mutex_object(dh)		((dh)->type == MutexObject)
+#define is_semaphore_object(dh)		((dh)->type == SemaphoreObject)
+#define is_nt_thread_object(dh)		((dh)->type == ThreadObject)
+
+#define IO_TYPE_ADAPTER				1
+#define IO_TYPE_CONTROLLER			2
+#define IO_TYPE_DEVICE				3
+#define IO_TYPE_DRIVER				4
+#define IO_TYPE_FILE				5
+#define IO_TYPE_IRP				6
+#define IO_TYPE_DEVICE_OBJECT_EXTENSION		13
+
+struct irp;
+struct dev_obj_ext;
+struct driver_object;
+
+struct device_object {
+	CSHORT type;
+	USHORT size;
+	LONG ref_count;
+	struct driver_object *drv_obj;
+	struct device_object *next;
+	struct device_object *attached;
+	struct irp *current_irp;
+	void *io_timer;
+	ULONG flags;
+	ULONG characteristics;
+	void *vpb;
+	void *dev_ext;
+	CCHAR stack_count;
+	union {
+		struct nt_list queue_list;
+		struct wait_context_block wcb;
+	} queue;
+	ULONG align_req;
+	struct kdevice_queue dev_queue;
+	struct kdpc dpc;
+	ULONG active_threads;
+	void *security_desc;
+	struct nt_event lock;
+	USHORT sector_size;
+	USHORT spare1;
+	struct dev_obj_ext *dev_obj_ext;
+	void *reserved;
+};
+
+struct dev_obj_ext {
+	CSHORT type;
+	CSHORT size;
+	struct device_object *dev_obj;
+	struct device_object *attached_to;
+};
+
+struct io_status_block {
+	union {
+		NTSTATUS status;
+		void *pointer;
+	};
+	ULONG_PTR info;
+};
+
+#ifdef CONFIG_X86_64
+struct io_status_block32 {
+	NTSTATUS status;
+	ULONG info;
+};
+#endif
+
+#define DEVICE_TYPE ULONG
+
+struct driver_extension;
+
+typedef NTSTATUS driver_dispatch_t(struct device_object *dev_obj,
+				   struct irp *irp) wstdcall;
+
+struct driver_object {
+	CSHORT type;
+	CSHORT size;
+	struct device_object *dev_obj;
+	ULONG flags;
+	void *start;
+	ULONG driver_size;
+	void *section;
+	struct driver_extension *drv_ext;
+	struct unicode_string name;
+	struct unicode_string *hardware_database;
+	void *fast_io_dispatch;
+	void *init;
+	void *start_io;
+	void (*unload)(struct driver_object *driver) wstdcall;
+	driver_dispatch_t *major_func[IRP_MJ_MAXIMUM_FUNCTION + 1];
+};
+
+struct driver_extension {
+	struct driver_object *drv_obj;
+	NTSTATUS (*add_device)(struct driver_object *drv_obj,
+			       struct device_object *dev_obj) wstdcall;
+	ULONG count;
+	struct unicode_string service_key_name;
+	struct nt_list custom_ext;
+};
+
+struct custom_ext {
+	struct nt_list list;
+	void *client_id;
+};
+
+struct wrap_bin_file;
+
+struct file_object {
+	CSHORT type;
+	CSHORT size;
+	struct device_object *dev_obj;
+	void *volume_parameter_block;
+	void *fs_context;
+	void *fs_context2;
+	void *section_object_pointer;
+	void *private_cache_map;
+	NTSTATUS final_status;
+	union {
+		struct file_object *related_file_object;
+		struct wrap_bin_file *wrap_bin_file;
+	};
+	BOOLEAN lock_operation;
+	BOOLEAN delete_pending;
+	BOOLEAN read_access;
+	BOOLEAN write_access;
+	BOOLEAN delete_access;
+	BOOLEAN shared_read;
+	BOOLEAN shared_write;
+	BOOLEAN shared_delete;
+	ULONG flags;
+	struct unicode_string _name_;
+	LARGE_INTEGER current_byte_offset;
+	ULONG waiters;
+	ULONG busy;
+	void *last_lock;
+	struct nt_event lock;
+	struct nt_event event;
+	void *completion_context;
+};
+
+#ifdef CONFIG_X86_64
+#define POINTER_ALIGN __attribute__((aligned(8)))
+#else
+#define POINTER_ALIGN
+#endif
+
+#define CACHE_ALIGN __attribute__((aligned(128)))
+
+enum system_power_state {
+	PowerSystemUnspecified = 0,
+	PowerSystemWorking, PowerSystemSleeping1, PowerSystemSleeping2,
+	PowerSystemSleeping3, PowerSystemHibernate, PowerSystemShutdown,
+	PowerSystemMaximum,
+};
+
+enum device_power_state {
+	PowerDeviceUnspecified = 0,
+	PowerDeviceD0, PowerDeviceD1, PowerDeviceD2, PowerDeviceD3,
+	PowerDeviceMaximum,
+};
+
+union power_state {
+	enum system_power_state system_state;
+	enum device_power_state device_state;
+};
+
+enum power_state_type {
+	SystemPowerState = 0, DevicePowerState,
+};
+
+enum power_action {
+	PowerActionNone = 0,
+	PowerActionReserved, PowerActionSleep, PowerActionHibernate,
+	PowerActionShutdown, PowerActionShutdownReset, PowerActionShutdownOff,
+	PowerActionWarmEject,
+};
+
+struct guid {
+	ULONG data1;
+	USHORT data2;
+	USHORT data3;
+	UCHAR data4[8];
+};
+
+struct nt_interface {
+	USHORT size;
+	USHORT version;
+	void *context;
+	void (*reference)(void *context) wstdcall;
+	void (*dereference)(void *context) wstdcall;
+};
+
+enum interface_type {
+	InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel,
+	TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus,
+	MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus,
+	PNPBus, MaximumInterfaceType,
+};
+
+#define CmResourceTypeNull		0
+#define CmResourceTypePort		1
+#define CmResourceTypeInterrupt		2
+#define CmResourceTypeMemory		3
+#define CmResourceTypeDma		4
+#define CmResourceTypeDeviceSpecific	5
+#define CmResourceTypeBusNumber		6
+#define CmResourceTypeMaximum		7
+
+#define CmResourceTypeNonArbitrated	128
+#define CmResourceTypeConfigData	128
+#define CmResourceTypeDevicePrivate	129
+#define CmResourceTypePcCardConfig	130
+#define CmResourceTypeMfCardConfig	131
+
+enum cm_share_disposition {
+	CmResourceShareUndetermined = 0, CmResourceShareDeviceExclusive,
+	CmResourceShareDriverExclusive, CmResourceShareShared
+};
+
+#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE	0
+#define CM_RESOURCE_INTERRUPT_LATCHED		1
+#define CM_RESOURCE_MEMORY_READ_WRITE		0x0000
+#define CM_RESOURCE_MEMORY_READ_ONLY		0x0001
+#define CM_RESOURCE_MEMORY_WRITE_ONLY		0x0002
+#define CM_RESOURCE_MEMORY_PREFETCHABLE		0x0004
+
+#define CM_RESOURCE_MEMORY_COMBINEDWRITE	0x0008
+#define CM_RESOURCE_MEMORY_24			0x0010
+#define CM_RESOURCE_MEMORY_CACHEABLE		0x0020
+
+#define CM_RESOURCE_PORT_MEMORY			0x0000
+#define CM_RESOURCE_PORT_IO			0x0001
+#define CM_RESOURCE_PORT_10_BIT_DECODE		0x0004
+#define CM_RESOURCE_PORT_12_BIT_DECODE		0x0008
+#define CM_RESOURCE_PORT_16_BIT_DECODE		0x0010
+#define CM_RESOURCE_PORT_POSITIVE_DECODE	0x0020
+#define CM_RESOURCE_PORT_PASSIVE_DECODE		0x0040
+#define CM_RESOURCE_PORT_WINDOW_DECODE		0x0080
+
+#define CM_RESOURCE_DMA_8			0x0000
+#define CM_RESOURCE_DMA_16			0x0001
+#define CM_RESOURCE_DMA_32			0x0002
+#define CM_RESOURCE_DMA_8_AND_16		0x0004
+#define CM_RESOURCE_DMA_BUS_MASTER		0x0008
+#define CM_RESOURCE_DMA_TYPE_A			0x0010
+#define CM_RESOURCE_DMA_TYPE_B			0x0020
+#define CM_RESOURCE_DMA_TYPE_F			0x0040
+
+#define MAX_RESOURCES 20
+
+#pragma pack(push,4)
+struct cm_partial_resource_descriptor {
+	UCHAR type;
+	UCHAR share;
+	USHORT flags;
+	union {
+		struct {
+			PHYSICAL_ADDRESS start;
+			ULONG length;
+		} generic;
+		struct {
+			PHYSICAL_ADDRESS start;
+			ULONG length;
+		} port;
+		struct {
+			ULONG level;
+			ULONG vector;
+			KAFFINITY affinity;
+		} interrupt;
+		struct {
+			PHYSICAL_ADDRESS start;
+			ULONG length;
+		} memory;
+		struct {
+			ULONG channel;
+			ULONG port;
+			ULONG reserved1;
+		} dma;
+		struct {
+			ULONG data[3];
+		} device_private;
+		struct {
+			ULONG start;
+			ULONG length;
+			ULONG reserved;
+		} bus_number;
+		struct {
+			ULONG data_size;
+			ULONG reserved1;
+			ULONG reserved2;
+		} device_specific_data;
+	} u;
+};
+#pragma pack(pop)
+
+struct cm_partial_resource_list {
+	USHORT version;
+	USHORT revision;
+	ULONG count;
+	struct cm_partial_resource_descriptor partial_descriptors[1];
+};
+
+struct cm_full_resource_descriptor {
+	enum interface_type interface_type;
+	ULONG bus_number;
+	struct cm_partial_resource_list partial_resource_list;
+};
+
+struct cm_resource_list {
+	ULONG count;
+	struct cm_full_resource_descriptor list[1];
+};
+
+enum file_info_class {
+	FileDirectoryInformation = 1,
+	FileBasicInformation = 4,
+	FileStandardInformation = 5,
+	FileNameInformation = 9,
+	FilePositionInformation = 14,
+	FileAlignmentInformation = 17,
+	FileNetworkOpenInformation = 34,
+	FileAttributeTagInformation = 35,
+	FileMaximumInformation = 41,
+};
+
+enum fs_info_class {
+	FileFsVolumeInformation = 1,
+	/* ... */
+	FileFsMaximumInformation = 9,
+};
+
+enum device_relation_type {
+	BusRelations, EjectionRelations, PowerRelations, RemovalRelations,
+	TargetDeviceRelation, SingleBusRelations,
+};
+
+enum bus_query_id_type {
+	BusQueryDeviceID = 0, BusQueryHardwareIDs = 1,
+	BusQueryCompatibleIDs = 2, BusQueryInstanceID = 3,
+	BusQueryDeviceSerialNumber = 4,
+};
+
+enum device_text_type {
+	DeviceTextDescription = 0, DeviceTextLocationInformation = 1,
+};
+
+enum device_usage_notification_type {
+	DeviceUsageTypeUndefined, DeviceUsageTypePaging,
+	DeviceUsageTypeHibernation, DevbiceUsageTypeDumpFile,
+};
+
+#define METHOD_BUFFERED		0
+#define METHOD_IN_DIRECT	1
+#define METHOD_OUT_DIRECT	2
+#define METHOD_NEITHER		3
+
+#define CTL_CODE(dev_type, func, method, access)			\
+	(((dev_type) << 16) | ((access) << 14) | ((func) << 2) | (method))
+
+#define IO_METHOD_FROM_CTL_CODE(code) (code & 0x3)
+
+#ifndef CONFIG_X86_64
+#pragma pack(push,4)
+#endif
+struct io_stack_location {
+	UCHAR major_fn;
+	UCHAR minor_fn;
+	UCHAR flags;
+	UCHAR control;
+	union {
+		struct {
+			void *security_context;
+			ULONG options;
+			USHORT POINTER_ALIGN file_attributes;
+			USHORT share_access;
+			ULONG POINTER_ALIGN ea_length;
+		} create;
+		struct {
+			ULONG length;
+			ULONG POINTER_ALIGN key;
+			LARGE_INTEGER byte_offset;
+		} read;
+		struct {
+			ULONG length;
+			ULONG POINTER_ALIGN key;
+			LARGE_INTEGER byte_offset;
+		} write;
+		struct {
+			ULONG length;
+			enum file_info_class POINTER_ALIGN file_info_class;
+		} query_file;
+		struct {
+			ULONG length;
+			enum file_info_class POINTER_ALIGN file_info_class;
+			struct file_object *file_object;
+			union {
+				struct {
+					BOOLEAN replace_if_exists;
+					BOOLEAN advance_only;
+				};
+				ULONG cluster_count;
+				void *delete_handle;
+			};
+		} set_file;
+		struct {
+			ULONG length;
+			enum fs_info_class POINTER_ALIGN fs_info_class;
+		} query_volume;
+		struct {
+			ULONG output_buf_len;
+			ULONG POINTER_ALIGN input_buf_len;
+			ULONG POINTER_ALIGN code;
+			void *type3_input_buf;
+		} dev_ioctl;
+		struct {
+			SECURITY_INFORMATION security_info;
+			ULONG POINTER_ALIGN length;
+		} query_security;
+		struct {
+			SECURITY_INFORMATION security_info;
+			void *security_descriptor;
+		} set_security;
+		struct {
+			void *vpb;
+			struct device_object *device_object;
+		} mount_volume;
+		struct {
+			void *vpb;
+			struct device_object *device_object;
+		} verify_volume;
+		struct {
+			void *srb;
+		} scsi;
+		struct {
+			enum device_relation_type type;
+		} query_device_relations;
+		struct {
+			const struct guid *type;
+			USHORT size;
+			USHORT version;
+			struct nt_interface *intf;
+			void *intf_data;
+		} query_intf;
+		struct {
+			void *capabilities;
+		} device_capabilities;
+		struct {
+			void *io_resource_requirement_list;
+		} filter_resource_requirements;
+		struct {
+			ULONG which_space;
+			void *buffer;
+			ULONG offset;
+			ULONG POINTER_ALIGN length;
+		} read_write_config;
+		struct {
+			BOOLEAN lock;
+		} set_lock;
+		struct {
+			enum bus_query_id_type id_type;
+		} query_id;
+		struct {
+			enum device_text_type device_text_type;
+			ULONG POINTER_ALIGN locale_id;
+		} query_device_text;
+		struct {
+			BOOLEAN in_path;
+			BOOLEAN reserved[3];
+			enum device_usage_notification_type POINTER_ALIGN type;
+		} usage_notification;
+		struct {
+			enum system_power_state power_state;
+		} wait_wake;
+		struct {
+			void *power_sequence;
+		} power_sequence;
+		struct {
+			ULONG sys_context;
+			enum power_state_type POINTER_ALIGN type;
+			union power_state POINTER_ALIGN state;
+			enum power_action POINTER_ALIGN shutdown_type;
+		} power;
+		struct {
+			struct cm_resource_list *allocated_resources;
+			struct cm_resource_list *allocated_resources_translated;
+		} start_device;
+		struct {
+			ULONG_PTR provider_id;
+			void *data_path;
+			ULONG buf_len;
+			void *buf;
+		} wmi;
+		struct {
+			void *arg1;
+			void *arg2;
+			void *arg3;
+			void *arg4;
+		} others;
+	} params;
+	struct device_object *dev_obj;
+	struct file_object *file_obj;
+	NTSTATUS (*completion_routine)(struct device_object *,
+				       struct irp *, void *) wstdcall;
+	void *context;
+};
+#ifndef CONFIG_X86_64
+#pragma pack(pop)
+#endif
+
+struct kapc {
+	CSHORT type;
+	CSHORT size;
+	ULONG spare0;
+	struct nt_thread *thread;
+	struct nt_list list;
+	void *kernele_routine;
+	void *rundown_routine;
+	void *normal_routine;
+	void *normal_context;
+	void *sys_arg1;
+	void *sys_arg2;
+	CCHAR apc_state_index;
+	KPROCESSOR_MODE apc_mode;
+	BOOLEAN inserted;
+};
+
+#define IRP_NOCACHE			0x00000001
+#define IRP_SYNCHRONOUS_API		0x00000004
+#define IRP_ASSOCIATED_IRP		0x00000008
+
+enum urb_state {
+	URB_INVALID = 1, URB_ALLOCATED, URB_SUBMITTED,
+	URB_COMPLETED, URB_FREE, URB_SUSPEND, URB_INT_UNLINKED };
+
+struct wrap_urb {
+	struct nt_list list;
+	enum urb_state state;
+	struct nt_list complete_list;
+	unsigned int flags;
+	struct urb *urb;
+	struct irp *irp;
+#ifdef USB_DEBUG
+	unsigned int id;
+#endif
+};
+
+struct irp {
+	SHORT type;
+	USHORT size;
+	struct mdl *mdl;
+	ULONG flags;
+	union {
+		struct irp *master_irp;
+		LONG irp_count;
+		void *system_buffer;
+	} associated_irp;
+	struct nt_list thread_list;
+	struct io_status_block io_status;
+	KPROCESSOR_MODE requestor_mode;
+	BOOLEAN pending_returned;
+	CHAR stack_count;
+	CHAR current_location;
+	BOOLEAN cancel;
+	KIRQL cancel_irql;
+	CCHAR apc_env;
+	UCHAR alloc_flags;
+	struct io_status_block *user_status;
+	struct nt_event *user_event;
+	union {
+		struct {
+			void *user_apc_routine;
+			void *user_apc_context;
+		} async_params;
+		LARGE_INTEGER alloc_size;
+	} overlay;
+	void (*cancel_routine)(struct device_object *, struct irp *) wstdcall;
+	void *user_buf;
+	union {
+		struct {
+			union {
+				struct kdevice_queue_entry dev_q_entry;
+				struct {
+					void *driver_context[4];
+				};
+			};
+			void *thread;
+			char *aux_buf;
+			struct {
+				struct nt_list list;
+				union {
+					struct io_stack_location *csl;
+					ULONG packet_type;
+				};
+			};
+			struct file_object *file_object;
+		} overlay;
+		union {
+			struct kapc apc;
+			/* space for apc is used for ndiswrapper
+			 * specific fields */
+			struct {
+				struct wrap_urb *wrap_urb;
+				struct wrap_device *wrap_device;
+			};
+		};
+		void *completion_key;
+	} tail;
+};
+
+#define IoSizeOfIrp(stack_count)					\
+	((USHORT)(sizeof(struct irp) +					\
+		  ((stack_count) * sizeof(struct io_stack_location))))
+#define IoGetCurrentIrpStackLocation(irp)	\
+	(irp)->tail.overlay.csl
+#define IoGetNextIrpStackLocation(irp)		\
+	(IoGetCurrentIrpStackLocation(irp) - 1)
+#define IoGetPreviousIrpStackLocation(irp)	\
+	(IoGetCurrentIrpStackLocation(irp) + 1)
+
+#define IoSetNextIrpStackLocation(irp)				\
+do {								\
+	KIRQL _irql_;						\
+	IoAcquireCancelSpinLock(&_irql_);			\
+	(irp)->current_location--;				\
+	IoGetCurrentIrpStackLocation(irp)--;			\
+	IoReleaseCancelSpinLock(_irql_);			\
+} while (0)
+
+#define IoSkipCurrentIrpStackLocation(irp) 			\
+do {								\
+	KIRQL _irql_;						\
+	IoAcquireCancelSpinLock(&_irql_);			\
+	(irp)->current_location++;				\
+	IoGetCurrentIrpStackLocation(irp)++;			\
+	IoReleaseCancelSpinLock(_irql_);			\
+} while (0)
+
+static inline void
+IoCopyCurrentIrpStackLocationToNext(struct irp *irp)
+{
+	struct io_stack_location *next;
+	next = IoGetNextIrpStackLocation(irp);
+	memcpy(next, IoGetCurrentIrpStackLocation(irp),
+	       offsetof(struct io_stack_location, completion_routine));
+	next->control = 0;
+}
+
+static inline void
+IoSetCompletionRoutine(struct irp *irp, void *routine, void *context,
+		       BOOLEAN success, BOOLEAN error, BOOLEAN cancel)
+{
+	struct io_stack_location *irp_sl = IoGetNextIrpStackLocation(irp);
+	irp_sl->completion_routine = routine;
+	irp_sl->context = context;
+	irp_sl->control = 0;
+	if (success)
+		irp_sl->control |= SL_INVOKE_ON_SUCCESS;
+	if (error)
+		irp_sl->control |= SL_INVOKE_ON_ERROR;
+	if (cancel)
+		irp_sl->control |= SL_INVOKE_ON_CANCEL;
+}
+
+#define IoMarkIrpPending(irp)						\
+	(IoGetCurrentIrpStackLocation((irp))->control |= SL_PENDING_RETURNED)
+#define IoUnmarkIrpPending(irp)						\
+	(IoGetCurrentIrpStackLocation((irp))->control &= ~SL_PENDING_RETURNED)
+
+#define IRP_SL(irp, n) (((struct io_stack_location *)((irp) + 1)) + (n))
+#define IRP_DRIVER_CONTEXT(irp) (irp)->tail.overlay.driver_context
+#define IoIrpThread(irp) ((irp)->tail.overlay.thread)
+
+#define IRP_URB(irp)							\
+	(union nt_urb *)(IoGetCurrentIrpStackLocation(irp)->params.others.arg1)
+
+#define IRP_WRAP_DEVICE(irp) (irp)->tail.wrap_device
+#define IRP_WRAP_URB(irp) (irp)->tail.wrap_urb
+
+struct wmi_guid_reg_info {
+	struct guid *guid;
+	ULONG instance_count;
+	ULONG flags;
+};
+
+struct wmilib_context {
+	ULONG guid_count;
+	struct wmi_guid_reg_info *guid_list;
+	void *query_wmi_reg_info;
+	void *query_wmi_data_block;
+	void *set_wmi_data_block;
+	void *set_wmi_data_item;
+	void *execute_wmi_method;
+	void *wmi_function_control;
+};
+
+enum key_value_information_class {
+	KeyValueBasicInformation, KeyValueFullInformation,
+	KeyValuePartialInformation, KeyValueFullInformationAlign64,
+	KeyValuePartialInformationAlign64
+};
+
+struct file_name_info {
+	ULONG length;
+	wchar_t *name;
+};
+
+struct file_std_info {
+	LARGE_INTEGER alloc_size;
+	LARGE_INTEGER eof;
+	ULONG num_links;
+	BOOLEAN delete_pending;
+	BOOLEAN dir;
+};
+
+enum nt_obj_type {
+	NT_OBJ_EVENT = 10, NT_OBJ_MUTEX, NT_OBJ_THREAD, NT_OBJ_TIMER,
+	NT_OBJ_SEMAPHORE,
+};
+
+enum common_object_type {
+	OBJECT_TYPE_NONE, OBJECT_TYPE_DEVICE, OBJECT_TYPE_DRIVER,
+	OBJECT_TYPE_NT_THREAD, OBJECT_TYPE_FILE, OBJECT_TYPE_CALLBACK,
+};
+
+struct common_object_header {
+	struct nt_list list;
+	enum common_object_type type;
+	UINT size;
+	UINT ref_count;
+	BOOLEAN close_in_process;
+	BOOLEAN permanent;
+	struct unicode_string name;
+};
+
+#define OBJECT_TO_HEADER(object)					\
+	(struct common_object_header *)((void *)(object) -		\
+					sizeof(struct common_object_header))
+#define OBJECT_SIZE(size)				\
+	((size) + sizeof(struct common_object_header))
+#define HEADER_TO_OBJECT(hdr)					\
+	((void *)(hdr) + sizeof(struct common_object_header))
+#define HANDLE_TO_OBJECT(handle) HEADER_TO_OBJECT(handle)
+#define HANDLE_TO_HEADER(handle) (handle)
+
+enum work_queue_type {
+	CriticalWorkQueue, DelayedWorkQueue, HyperCriticalWorkQueue,
+	MaximumWorkQueue
+};
+
+typedef void (*NTOS_WORK_FUNC)(void *arg1, void *arg2) wstdcall;
+
+struct io_workitem {
+	enum work_queue_type type;
+	struct device_object *dev_obj;
+	NTOS_WORK_FUNC worker_routine;
+	void *context;
+};
+
+struct io_workitem_entry {
+	struct nt_list list;
+	struct io_workitem *io_workitem;
+};
+
+enum mm_page_priority {
+	LowPagePriority, NormalPagePriority = 16, HighPagePriority = 32
+};
+
+enum kinterrupt_mode {
+	LevelSensitive, Latched
+};
+
+enum ntos_wait_reason {
+	Executive, FreePage, PageIn, PoolAllocation, DelayExecution,
+	Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn,
+	WrPoolAllocation, WrDelayExecution, WrSuspended, WrUserRequest,
+	WrEventPair, WrQueue, WrLpcReceive, WrLpcReply, WrVirtualMemory,
+	WrPageOut, WrRendezvous, Spare2, Spare3, Spare4, Spare5, Spare6,
+	WrKernel, MaximumWaitReason
+};
+
+typedef enum ntos_wait_reason KWAIT_REASON;
+
+typedef void *LOOKASIDE_ALLOC_FUNC(enum pool_type pool_type,
+				   SIZE_T size, ULONG tag) wstdcall;
+typedef void LOOKASIDE_FREE_FUNC(void *) wstdcall;
+
+struct npaged_lookaside_list {
+	nt_slist_header head;
+	USHORT depth;
+	USHORT maxdepth;
+	ULONG totalallocs;
+	union {
+		ULONG allocmisses;
+		ULONG allochits;
+	} u1;
+	ULONG totalfrees;
+	union {
+		ULONG freemisses;
+		ULONG freehits;
+	} u2;
+	enum pool_type pool_type;
+	ULONG tag;
+	ULONG size;
+	LOOKASIDE_ALLOC_FUNC *alloc_func;
+	LOOKASIDE_FREE_FUNC *free_func;
+	struct nt_list list;
+	ULONG lasttotallocs;
+	union {
+		ULONG lastallocmisses;
+		ULONG lastallochits;
+	} u3;
+	ULONG pad[2];
+#ifndef CONFIG_X86_64
+	NT_SPIN_LOCK obsolete;
+#endif
+}
+#ifdef CONFIG_X86_64
+CACHE_ALIGN
+#endif
+;
+
+enum device_registry_property {
+	DevicePropertyDeviceDescription, DevicePropertyHardwareID,
+	DevicePropertyCompatibleIDs, DevicePropertyBootConfiguration,
+	DevicePropertyBootConfigurationTranslated,
+	DevicePropertyClassName, DevicePropertyClassGuid,
+	DevicePropertyDriverKeyName, DevicePropertyManufacturer,
+	DevicePropertyFriendlyName, DevicePropertyLocationInformation,
+	DevicePropertyPhysicalDeviceObjectName, DevicePropertyBusTypeGuid,
+	DevicePropertyLegacyBusType, DevicePropertyBusNumber,
+	DevicePropertyEnumeratorName, DevicePropertyAddress,
+	DevicePropertyUINumber, DevicePropertyInstallState,
+	DevicePropertyRemovalPolicy
+};
+
+enum trace_information_class {
+	TraceIdClass, TraceHandleClass, TraceEnableFlagsClass,
+	TraceEnableLevelClass, GlobalLoggerHandleClass, EventLoggerHandleClass,
+	AllLoggerHandlesClass, TraceHandleByNameClass
+};
+
+struct kinterrupt;
+typedef BOOLEAN (*PKSERVICE_ROUTINE)(struct kinterrupt *interrupt,
+				     void *context) wstdcall;
+typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(void *context) wstdcall;
+
+struct kinterrupt {
+	ULONG vector;
+	KAFFINITY cpu_mask;
+	NT_SPIN_LOCK lock;
+	NT_SPIN_LOCK *actual_lock;
+	BOOLEAN shared;
+	BOOLEAN save_fp;
+	union {
+		CHAR processor_number;
+#ifdef CONFIG_DEBUG_SHIRQ
+		CHAR enabled;
+#endif
+	} u;
+	PKSERVICE_ROUTINE isr;
+	void *isr_ctx;
+	struct nt_list list;
+	KIRQL irql;
+	KIRQL synch_irql;
+	enum kinterrupt_mode mode;
+};
+
+struct time_fields {
+	CSHORT year;
+	CSHORT month;
+	CSHORT day;
+	CSHORT hour;
+	CSHORT minute;
+	CSHORT second;
+	CSHORT milliseconds;
+	CSHORT weekday;
+};
+
+struct object_attributes {
+	ULONG length;
+	void *root_dir;
+	struct unicode_string *name;
+	ULONG attributes;
+	void *security_descr;
+	void *security_qos;
+};
+
+typedef void (*PCALLBACK_FUNCTION)(void *context, void *arg1,
+				   void *arg2) wstdcall;
+
+struct callback_object;
+struct callback_func {
+	PCALLBACK_FUNCTION func;
+	void *context;
+	struct nt_list list;
+	struct callback_object *object;
+};
+
+struct callback_object {
+	NT_SPIN_LOCK lock;
+	struct nt_list list;
+	struct nt_list callback_funcs;
+	BOOLEAN allow_multiple_callbacks;
+	struct object_attributes *attributes;
+};
+
+enum section_inherit {
+	ViewShare = 1, ViewUnmap = 2
+};
+
+struct ksystem_time {
+	ULONG low_part;
+	LONG high1_time;
+	LONG high2_time;
+};
+
+enum nt_product_type {
+	nt_product_win_nt = 1, nt_product_lan_man_nt, nt_product_server
+};
+
+enum alt_arch_type {
+	arch_type_standard, arch_type_nex98x86, end_alternatives
+};
+
+struct kuser_shared_data {
+	ULONG tick_count;
+	ULONG tick_count_multiplier;
+	volatile struct ksystem_time interrupt_time;
+	volatile struct ksystem_time system_time;
+	volatile struct ksystem_time time_zone_bias;
+	USHORT image_number_low;
+	USHORT image_number_high;
+	wchar_t nt_system_root[260];
+	ULONG max_stack_trace_depth;
+	ULONG crypto_exponent;
+	ULONG time_zone_id;
+	ULONG large_page_min;
+	ULONG reserved2[7];
+	enum nt_product_type nt_product_type;
+	BOOLEAN product_type_is_valid;
+	ULONG nt_major_version;
+	ULONG nt_minor_version;
+	BOOLEAN processor_features[PROCESSOR_FEATURE_MAX];
+	ULONG reserved1;
+	ULONG reserved3;
+	volatile LONG time_slip;
+	enum alt_arch_type alt_arch_type;
+	LARGE_INTEGER system_expiration_date;
+	ULONG suite_mask;
+	BOOLEAN kdbg_enabled;
+	volatile ULONG active_console;
+	volatile ULONG dismount_count;
+	ULONG com_plus_package;
+	ULONG last_system_rite_event_tick_count;
+	ULONG num_phys_pages;
+	BOOLEAN safe_boot_mode;
+	ULONG trace_log;
+	ULONGLONG fill0;
+	ULONGLONG sys_call[4];
+	union {
+		volatile struct ksystem_time tick_count;
+		volatile ULONG64 tick_count_quad;
+	} tick;
+};
+
+#define REG_NONE			(0)
+#define REG_SZ				(1)
+#define REG_EXPAND_SZ			(2)
+#define REG_BINARY			(3)
+#define REG_DWORD			(4)
+
+#define RTL_REGISTRY_ABSOLUTE		0
+#define RTL_REGISTRY_SERVICES		1
+#define RTL_REGISTRY_CONTROL		2
+#define RTL_REGISTRY_WINDOWS_NT		3
+#define RTL_REGISTRY_DEVICEMAP		4
+#define RTL_REGISTRY_USER		5
+#define RTL_REGISTRY_MAXIMUM		6
+#define RTL_REGISTRY_HANDLE		0x40000000
+#define RTL_REGISTRY_OPTIONAL		0x80000000
+
+#define RTL_QUERY_REGISTRY_SUBKEY	0x00000001
+#define RTL_QUERY_REGISTRY_TOPKEY	0x00000002
+#define RTL_QUERY_REGISTRY_REQUIRED	0x00000004
+#define RTL_QUERY_REGISTRY_NOVALUE	0x00000008
+#define RTL_QUERY_REGISTRY_NOEXPAND	0x00000010
+#define RTL_QUERY_REGISTRY_DIRECT	0x00000020
+#define RTL_QUERY_REGISTRY_DELETE	0x00000040
+
+typedef NTSTATUS (*PRTL_QUERY_REGISTRY_ROUTINE)(wchar_t *name, ULONG type,
+						void *data, ULONG length,
+						void *context,
+						void *entry) wstdcall;
+
+struct rtl_query_registry_table {
+	PRTL_QUERY_REGISTRY_ROUTINE query_func;
+	ULONG flags;
+	wchar_t *name;
+	void *context;
+	ULONG def_type;
+	void *def_data;
+	ULONG def_length;
+};
+
+struct io_remove_lock {
+	BOOLEAN removed;
+	BOOLEAN reserved[3];
+	LONG io_count;
+	struct nt_event remove_event;
+};
+
+struct io_error_log_packet {
+	UCHAR major_fn_code;
+	UCHAR retry_count;
+	USHORT dump_data_size;
+	USHORT nr_of_strings;
+	USHORT string_offset;
+	USHORT event_category;
+	NTSTATUS error_code;
+	ULONG unique_error_value;
+	NTSTATUS final_status;
+	ULONG sequence_number;
+	ULONG io_control_code;
+	LARGE_INTEGER device_offset;
+	ULONG dump_data[1];
+};
+
+/* some of the functions below are slightly different from DDK's
+ * implementation; e.g., Insert functions return appropriate
+ * pointer */
+
+/* instead of using Linux's lists, we implement list manipulation
+ * functions because nt_list is used by drivers and we don't want to
+ * worry about Linux's list being different from nt_list (right now
+ * they are same, but in future they could be different) */
+
+static inline void InitializeListHead(struct nt_list *head)
+{
+	head->next = head->prev = head;
+}
+
+static inline BOOLEAN IsListEmpty(struct nt_list *head)
+{
+	if (head == head->next)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static inline void RemoveEntryList(struct nt_list *entry)
+{
+	entry->prev->next = entry->next;
+	entry->next->prev = entry->prev;
+}
+
+static inline struct nt_list *RemoveHeadList(struct nt_list *head)
+{
+	struct nt_list *entry;
+
+	entry = head->next;
+	if (entry == head)
+		return NULL;
+	else {
+		RemoveEntryList(entry);
+		return entry;
+	}
+}
+
+static inline struct nt_list *RemoveTailList(struct nt_list *head)
+{
+	struct nt_list *entry;
+
+	entry = head->prev;
+	if (entry == head)
+		return NULL;
+	else {
+		RemoveEntryList(entry);
+		return entry;
+	}
+}
+
+static inline void InsertListEntry(struct nt_list *entry, struct nt_list *prev,
+				   struct nt_list *next)
+{
+	next->prev = entry;
+	entry->next = next;
+	entry->prev = prev;
+	prev->next = entry;
+}
+
+static inline struct nt_list *InsertHeadList(struct nt_list *head,
+					     struct nt_list *entry)
+{
+	struct nt_list *ret;
+
+	if (IsListEmpty(head))
+		ret = NULL;
+	else
+		ret = head->next;
+
+	InsertListEntry(entry, head, head->next);
+	return ret;
+}
+
+static inline struct nt_list *InsertTailList(struct nt_list *head,
+					     struct nt_list *entry)
+{
+	struct nt_list *ret;
+
+	if (IsListEmpty(head))
+		ret = NULL;
+	else
+		ret = head->prev;
+
+	InsertListEntry(entry, head->prev, head);
+	return ret;
+}
+
+#define nt_list_for_each(pos, head)					\
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define nt_list_for_each_entry(pos, head, member)			\
+	for (pos = container_of((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head);					\
+	     pos = container_of(pos->member.next, typeof(*pos), member))
+
+#define nt_list_for_each_safe(pos, n, head)		       \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+	     pos = n, n = pos->next)
+
+/* device object flags */
+#define DO_VERIFY_VOLUME		0x00000002
+#define DO_BUFFERED_IO			0x00000004
+#define DO_EXCLUSIVE			0x00000008
+#define DO_DIRECT_IO			0x00000010
+#define DO_MAP_IO_BUFFER		0x00000020
+#define DO_DEVICE_HAS_NAME		0x00000040
+#define DO_DEVICE_INITIALIZING		0x00000080
+#define DO_SYSTEM_BOOT_PARTITION	0x00000100
+#define DO_LONG_TERM_REQUESTS		0x00000200
+#define DO_NEVER_LAST_DEVICE		0x00000400
+#define DO_SHUTDOWN_REGISTERED		0x00000800
+#define DO_BUS_ENUMERATED_DEVICE	0x00001000
+#define DO_POWER_PAGABLE		0x00002000
+#define DO_POWER_INRUSH			0x00004000
+#define DO_LOW_PRIORITY_FILESYSTEM	0x00010000
+
+/* Various supported device types (used with IoCreateDevice()) */
+
+#define FILE_DEVICE_BEEP		0x00000001
+#define FILE_DEVICE_CD_ROM		0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM	0x00000003
+#define FILE_DEVICE_CONTROLLER		0x00000004
+#define FILE_DEVICE_DATALINK		0x00000005
+#define FILE_DEVICE_DFS			0x00000006
+#define FILE_DEVICE_DISK		0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM	0x00000008
+#define FILE_DEVICE_FILE_SYSTEM		0x00000009
+#define FILE_DEVICE_INPORT_PORT		0x0000000A
+#define FILE_DEVICE_KEYBOARD		0x0000000B
+#define FILE_DEVICE_MAILSLOT		0x0000000C
+#define FILE_DEVICE_MIDI_IN		0x0000000D
+#define FILE_DEVICE_MIDI_OUT		0x0000000E
+#define FILE_DEVICE_MOUSE		0x0000000F
+#define FILE_DEVICE_MULTI_UNC_PROVIDER	0x00000010
+#define FILE_DEVICE_NAMED_PIPE		0x00000011
+#define FILE_DEVICE_NETWORK		0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER	0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM	0x00000014
+#define FILE_DEVICE_NULL		0x00000015
+#define FILE_DEVICE_PARALLEL_PORT	0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD	0x00000017
+#define FILE_DEVICE_PRINTER		0x00000018
+#define FILE_DEVICE_SCANNER		0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT	0x0000001A
+#define FILE_DEVICE_SERIAL_PORT		0x0000001B
+#define FILE_DEVICE_SCREEN		0x0000001C
+#define FILE_DEVICE_SOUND		0x0000001D
+#define FILE_DEVICE_STREAMS		0x0000001E
+#define FILE_DEVICE_TAPE		0x0000001F
+#define FILE_DEVICE_TAPE_FILE_SYSTEM	0x00000020
+#define FILE_DEVICE_TRANSPORT		0x00000021
+#define FILE_DEVICE_UNKNOWN		0x00000022
+#define FILE_DEVICE_VIDEO		0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK	0x00000024
+#define FILE_DEVICE_WAVE_IN		0x00000025
+#define FILE_DEVICE_WAVE_OUT		0x00000026
+#define FILE_DEVICE_8042_PORT		0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR	0x00000028
+#define FILE_DEVICE_BATTERY		0x00000029
+#define FILE_DEVICE_BUS_EXTENDER	0x0000002A
+#define FILE_DEVICE_MODEM		0x0000002B
+#define FILE_DEVICE_VDM			0x0000002C
+#define FILE_DEVICE_MASS_STORAGE	0x0000002D
+#define FILE_DEVICE_SMB			0x0000002E
+#define FILE_DEVICE_KS			0x0000002F
+#define FILE_DEVICE_CHANGER		0x00000030
+#define FILE_DEVICE_SMARTCARD		0x00000031
+#define FILE_DEVICE_ACPI		0x00000032
+#define FILE_DEVICE_DVD			0x00000033
+#define FILE_DEVICE_FULLSCREEN_VIDEO	0x00000034
+#define FILE_DEVICE_DFS_FILE_SYSTEM	0x00000035
+#define FILE_DEVICE_DFS_VOLUME		0x00000036
+#define FILE_DEVICE_SERENUM		0x00000037
+#define FILE_DEVICE_TERMSRV		0x00000038
+#define FILE_DEVICE_KSEC		0x00000039
+#define FILE_DEVICE_FIPS		0x0000003A
+
+/* Device characteristics */
+
+#define FILE_REMOVABLE_MEDIA		0x00000001
+#define FILE_READ_ONLY_DEVICE		0x00000002
+#define FILE_FLOPPY_DISKETTE		0x00000004
+#define FILE_WRITE_ONCE_MEDIA		0x00000008
+#define FILE_REMOTE_DEVICE		0x00000010
+#define FILE_DEVICE_IS_MOUNTED		0x00000020
+#define FILE_VIRTUAL_VOLUME		0x00000040
+#define FILE_AUTOGENERATED_DEVICE_NAME	0x00000080
+#define FILE_DEVICE_SECURE_OPEN		0x00000100
+
+#define FILE_READ_DATA			0x0001
+#define FILE_WRITE_DATA			0x0002
+
+#define FILE_SUPERSEDED			0x00000000
+#define FILE_OPENED			0x00000001
+#define FILE_CREATED			0x00000002
+#define FILE_OVERWRITTEN		0x00000003
+#define FILE_EXISTS			0x00000004
+#define FILE_DOES_NOT_EXIST		0x00000005
+
+
+#endif /* WINNT_TYPES_H */
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/pnp.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/pnp.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (C) 2005 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _PNP_H_
+#define _PNP_H_
+
+#include "ntoskernel.h"
+#include "ndis.h"
+#include "wrapndis.h"
+
+NTSTATUS pnp_start_device(struct wrap_device *wd);
+NTSTATUS pnp_stop_device(struct wrap_device *wd);
+NTSTATUS pnp_remove_device(struct wrap_device *wd);
+
+int wrap_pnp_start_pci_device(struct pci_dev *pdev,
+			      const struct pci_device_id *ent);
+void __devexit wrap_pnp_remove_pci_device(struct pci_dev *pdev);
+int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state);
+int wrap_pnp_resume_pci_device(struct pci_dev *pdev);
+
+#ifdef ENABLE_USB
+int wrap_pnp_start_usb_device(struct usb_interface *intf,
+			      const struct usb_device_id *usb_id);
+void wrap_pnp_remove_usb_device(struct usb_interface *intf);
+int wrap_pnp_suspend_usb_device(struct usb_interface *intf,
+				pm_message_t state);
+int wrap_pnp_resume_usb_device(struct usb_interface *intf);
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/usb.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/usb.c
@@ -0,0 +1,1457 @@
+/*
+ *  Copyright (C) 2004 Jan Kiszka
+ *  Copyright (C) 2005 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ndis.h"
+#include "usb.h"
+#include "usb_exports.h"
+
+#ifdef USB_DEBUG
+static unsigned int urb_id = 0;
+
+#define DUMP_WRAP_URB(wrap_urb, dir)					\
+	USBTRACE("urb %p (%d) %s: buf: %p, len: %d, pipe: 0x%x, %d",	\
+		 (wrap_urb)->urb, (wrap_urb)->id,			\
+		 (dir == USB_DIR_OUT) ? "going down" : "coming back",	\
+		 (wrap_urb)->urb->transfer_buffer,			\
+		 (wrap_urb)->urb->transfer_buffer_length,		\
+		 (wrap_urb)->urb->pipe, (wrap_urb)->urb->status)
+
+#define DUMP_URB_BUFFER(urb, dir)					\
+	while (debug >= 2) {						\
+		int i;							\
+		char msg[20], *t;					\
+		if (!urb->transfer_buffer)				\
+			break;						\
+		if (!((usb_pipein(urb->pipe) && dir == USB_DIR_IN) ||	\
+		      (usb_pipeout(urb->pipe) && dir == USB_DIR_OUT)))	\
+			break;						\
+		t = msg;						\
+		t += sprintf(t, "%d: ", (urb)->actual_length);		\
+		for (i = 0; i < urb->actual_length &&			\
+			     t < &msg[sizeof(msg) - 4]; i++)		\
+			t += sprintf(t, "%02X ",			\
+				     ((char *)urb->transfer_buffer)[i]); \
+		*t = 0;							\
+		USBTRACE("%s", msg);					\
+		break;							\
+	}
+
+#else
+
+#define DUMP_WRAP_URB(wrap_urb, dir) (void)0
+#define DUMP_URB_BUFFER(urb, dir) (void)0
+
+#endif
+
+#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting
+
+#ifndef USB_CTRL_SET_TIMEOUT
+#define USB_CTRL_SET_TIMEOUT 5000
+#endif
+
+#ifndef USB_CTRL_GET_TIMEOUT
+#define USB_CTRL_GET_TIMEOUT 5000
+#endif
+
+#ifndef URB_NO_TRANSFER_DMA_MAP
+#define URB_NO_TRANSFER_DMA_MAP 0
+#endif
+
+/* wrap_urb->flags */
+/* transfer_buffer for urb is allocated; free it in wrap_free_urb */
+#define WRAP_URB_COPY_BUFFER 0x01
+
+static int inline wrap_cancel_urb(struct wrap_urb *wrap_urb)
+{
+	int ret;
+	USBTRACE("%p, %p, %d", wrap_urb, wrap_urb->urb, wrap_urb->state);
+	if (wrap_urb->state != URB_SUBMITTED)
+		USBEXIT(return -1);
+	ret = usb_unlink_urb(wrap_urb->urb);
+	USBTRACE("ret: %d", ret);
+	if (ret == -EINPROGRESS)
+		return 0;
+	else {
+		WARNING("unlink failed: %d", ret);
+		return ret;
+	}
+}
+
+#define URB_STATUS(wrap_urb) (wrap_urb->urb->status)
+
+static struct nt_list wrap_urb_complete_list;
+static spinlock_t wrap_urb_complete_list_lock;
+
+static work_struct_t wrap_urb_complete_work;
+static void wrap_urb_complete_worker(worker_param_t dummy);
+
+static void kill_all_urbs(struct wrap_device *wd, int complete)
+{
+	struct nt_list *ent;
+	struct wrap_urb *wrap_urb;
+	KIRQL irql;
+
+	USBTRACE("%d", wd->usb.num_alloc_urbs);
+	while (1) {
+		IoAcquireCancelSpinLock(&irql);
+		ent = RemoveHeadList(&wd->usb.wrap_urb_list);
+		IoReleaseCancelSpinLock(irql);
+		if (!ent)
+			break;
+		wrap_urb = container_of(ent, struct wrap_urb, list);
+		if (wrap_urb->state == URB_SUBMITTED) {
+			WARNING("Windows driver %s didn't free urb: %p",
+				wd->driver->name, wrap_urb->urb);
+			if (!complete)
+				wrap_urb->urb->complete = NULL;
+			usb_kill_urb(wrap_urb->urb);
+		}
+		USBTRACE("%p, %p", wrap_urb, wrap_urb->urb);
+		usb_free_urb(wrap_urb->urb);
+		kfree(wrap_urb);
+	}
+	wd->usb.num_alloc_urbs = 0;
+}
+
+/* for a given Linux urb status code, return corresponding NT urb status */
+static USBD_STATUS wrap_urb_status(int urb_status)
+{
+	switch (urb_status) {
+	case 0:
+		return USBD_STATUS_SUCCESS;
+	case -EPROTO:
+		return USBD_STATUS_TIMEOUT;
+	case -EILSEQ:
+		return USBD_STATUS_CRC;
+	case -EPIPE:
+		return USBD_STATUS_INVALID_PIPE_HANDLE;
+	case -ECOMM:
+		return USBD_STATUS_DATA_OVERRUN;
+	case -ENOSR:
+		return USBD_STATUS_DATA_UNDERRUN;
+	case -EOVERFLOW:
+		return USBD_STATUS_BABBLE_DETECTED;
+	case -EREMOTEIO:
+		return USBD_STATUS_ERROR_SHORT_TRANSFER;;
+	case -ENODEV:
+	case -ESHUTDOWN:
+	case -ENOENT:
+		return USBD_STATUS_DEVICE_GONE;
+	case -ENOMEM:
+		return USBD_STATUS_NO_MEMORY;
+	case -EINVAL:
+		return USBD_STATUS_REQUEST_FAILED;
+	default:
+		return USBD_STATUS_NOT_SUPPORTED;
+	}
+}
+
+/* for a given USBD_STATUS, return its corresponding NTSTATUS (for irp) */
+static NTSTATUS nt_urb_irp_status(USBD_STATUS nt_urb_status)
+{
+	switch (nt_urb_status) {
+	case USBD_STATUS_SUCCESS:
+		return STATUS_SUCCESS;
+	case USBD_STATUS_DEVICE_GONE:
+		return STATUS_DEVICE_REMOVED;
+	case USBD_STATUS_PENDING:
+		return STATUS_PENDING;
+	case USBD_STATUS_NOT_SUPPORTED:
+		return STATUS_NOT_IMPLEMENTED;
+	case USBD_STATUS_NO_MEMORY:
+		return STATUS_NO_MEMORY;
+	case USBD_STATUS_REQUEST_FAILED:
+		return STATUS_NOT_SUPPORTED;
+	default:
+		return STATUS_FAILURE;
+	}
+}
+
+static void wrap_free_urb(struct urb *urb)
+{
+	struct irp *irp;
+	struct wrap_urb *wrap_urb;
+
+	USBTRACE("freeing urb: %p", urb);
+	wrap_urb = urb->context;
+	irp = wrap_urb->irp;
+	if (wrap_urb->flags & WRAP_URB_COPY_BUFFER) {
+		USBTRACE("freeing DMA buffer for URB: %p %p",
+			 urb, urb->transfer_buffer);
+		usb_buffer_free(IRP_WRAP_DEVICE(irp)->usb.udev,
+				urb->transfer_buffer_length,
+				urb->transfer_buffer, urb->transfer_dma);
+	}
+	if (urb->setup_packet)
+		kfree(urb->setup_packet);
+	if (IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs > MAX_ALLOCATED_URBS) {
+		IoAcquireCancelSpinLock(&irp->cancel_irql);
+		RemoveEntryList(&wrap_urb->list);
+		IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs--;
+		IoReleaseCancelSpinLock(irp->cancel_irql);
+		usb_free_urb(urb);
+		kfree(wrap_urb);
+	} else {
+		wrap_urb->state = URB_FREE;
+		wrap_urb->flags = 0;
+		wrap_urb->irp = NULL;
+	}
+	return;
+}
+
+void wrap_suspend_urbs(struct wrap_device *wd)
+{
+	/* TODO: do we need to cancel urbs? */
+	USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs);
+}
+
+void wrap_resume_urbs(struct wrap_device *wd)
+{
+	/* TODO: do we need to resubmit urbs? */
+	USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs);
+}
+
+wstdcall void wrap_cancel_irp(struct device_object *dev_obj, struct irp *irp)
+{
+	struct urb *urb;
+
+	/* NB: this function is called holding Cancel spinlock */
+	USBENTER("irp: %p", irp);
+	urb = IRP_WRAP_URB(irp)->urb;
+	USBTRACE("canceling urb %p", urb);
+	if (wrap_cancel_urb(IRP_WRAP_URB(irp))) {
+		irp->cancel = FALSE;
+		ERROR("urb %p can't be canceld: %d", urb,
+		      IRP_WRAP_URB(irp)->state);
+	} else
+		USBTRACE("urb %p canceled", urb);
+	IoReleaseCancelSpinLock(irp->cancel_irql);
+	return;
+}
+WIN_FUNC_DECL(wrap_cancel_irp,2)
+
+static struct urb *wrap_alloc_urb(struct irp *irp, unsigned int pipe,
+				  void *buf, unsigned int buf_len)
+{
+	struct urb *urb;
+	gfp_t alloc_flags;
+	struct wrap_urb *wrap_urb;
+	struct wrap_device *wd;
+
+	USBENTER("irp: %p", irp);
+	wd = IRP_WRAP_DEVICE(irp);
+	alloc_flags = irql_gfp();
+	IoAcquireCancelSpinLock(&irp->cancel_irql);
+	urb = NULL;
+	nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) {
+		if (cmpxchg(&wrap_urb->state, URB_FREE,
+			    URB_ALLOCATED) == URB_FREE) {
+			urb = wrap_urb->urb;
+			usb_init_urb(urb);
+			break;
+		}
+	}
+	if (!urb) {
+		IoReleaseCancelSpinLock(irp->cancel_irql);
+		wrap_urb = kzalloc(sizeof(*wrap_urb), alloc_flags);
+		if (!wrap_urb) {
+			WARNING("couldn't allocate memory");
+			return NULL;
+		}
+		urb = usb_alloc_urb(0, alloc_flags);
+		if (!urb) {
+			WARNING("couldn't allocate urb");
+			kfree(wrap_urb);
+			return NULL;
+		}
+		IoAcquireCancelSpinLock(&irp->cancel_irql);
+		wrap_urb->urb = urb;
+		wrap_urb->state = URB_ALLOCATED;
+		InsertTailList(&wd->usb.wrap_urb_list, &wrap_urb->list);
+		wd->usb.num_alloc_urbs++;
+	}
+
+#ifdef URB_ASYNC_UNLINK
+	urb->transfer_flags |= URB_ASYNC_UNLINK;
+#elif defined(USB_ASYNC_UNLINK)
+	urb->transfer_flags |= USB_ASYNC_UNLINK;
+#endif
+	urb->context = wrap_urb;
+	wrap_urb->irp = irp;
+	IRP_WRAP_URB(irp) = wrap_urb;
+	/* called as Windows function */
+	irp->cancel_routine = WIN_FUNC_PTR(wrap_cancel_irp,2);
+	IoReleaseCancelSpinLock(irp->cancel_irql);
+	USBTRACE("urb: %p", urb);
+
+	urb->transfer_buffer_length = buf_len;
+	if (buf_len && buf && (!virt_addr_valid(buf)
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_HIGHMEM4G)
+			       || PageHighMem(virt_to_page(buf))
+#endif
+		    )) {
+		urb->transfer_buffer =
+			usb_buffer_alloc(wd->usb.udev, buf_len, alloc_flags,
+					 &urb->transfer_dma);
+		if (!urb->transfer_buffer) {
+			WARNING("couldn't allocate dma buf");
+			IoAcquireCancelSpinLock(&irp->cancel_irql);
+			wrap_urb->state = URB_FREE;
+			wrap_urb->irp = NULL;
+			IRP_WRAP_URB(irp) = NULL;
+			IoReleaseCancelSpinLock(irp->cancel_irql);
+			return NULL;
+		}
+		if (urb->transfer_dma)
+			urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		wrap_urb->flags |= WRAP_URB_COPY_BUFFER;
+		if (usb_pipeout(pipe))
+			memcpy(urb->transfer_buffer, buf, buf_len);
+		USBTRACE("DMA buf for urb %p: %p", urb, urb->transfer_buffer);
+	} else
+		urb->transfer_buffer = buf;
+	return urb;
+}
+
+static USBD_STATUS wrap_submit_urb(struct irp *irp)
+{
+	int ret;
+	struct urb *urb;
+	union nt_urb *nt_urb;
+
+	urb = IRP_WRAP_URB(irp)->urb;
+	nt_urb = IRP_URB(irp);
+#ifdef USB_DEBUG
+	if (IRP_WRAP_URB(irp)->state != URB_ALLOCATED) {
+		ERROR("urb %p is in wrong state: %d",
+		      urb, IRP_WRAP_URB(irp)->state);
+		NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED;
+		return NT_URB_STATUS(nt_urb);
+	}
+	IRP_WRAP_URB(irp)->id = pre_atomic_add(urb_id, 1);
+#endif
+	DUMP_WRAP_URB(IRP_WRAP_URB(irp), USB_DIR_OUT);
+	irp->io_status.status = STATUS_PENDING;
+	irp->io_status.info = 0;
+	NT_URB_STATUS(nt_urb) = USBD_STATUS_PENDING;
+	IoMarkIrpPending(irp);
+	DUMP_URB_BUFFER(urb, USB_DIR_OUT);
+	USBTRACE("%p", urb);
+	IRP_WRAP_URB(irp)->state = URB_SUBMITTED;
+	ret = usb_submit_urb(urb, irql_gfp());
+	if (ret) {
+		USBTRACE("ret: %d", ret);
+		wrap_free_urb(urb);
+		/* we assume that IRP was not in pending state before */
+		IoUnmarkIrpPending(irp);
+		NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
+		USBEXIT(return NT_URB_STATUS(nt_urb));
+	} else
+		USBEXIT(return USBD_STATUS_PENDING);
+}
+
+static void wrap_urb_complete(struct urb *urb ISR_PT_REGS_PARAM_DECL)
+{
+	struct irp *irp;
+	struct wrap_urb *wrap_urb;
+
+	wrap_urb = urb->context;
+	USBTRACE("%p (%p) completed", wrap_urb, urb);
+	irp = wrap_urb->irp;
+	DUMP_WRAP_URB(wrap_urb, USB_DIR_IN);
+	irp->cancel_routine = NULL;
+#ifdef USB_DEBUG
+	if (wrap_urb->state != URB_SUBMITTED) {
+		WARNING("urb %p in wrong state: %d (%d)", urb, wrap_urb->state,
+			urb->status);
+		return;
+	}
+#endif
+	wrap_urb->state = URB_COMPLETED;
+	spin_lock(&wrap_urb_complete_list_lock);
+	InsertTailList(&wrap_urb_complete_list, &wrap_urb->complete_list);
+	spin_unlock(&wrap_urb_complete_list_lock);
+	schedule_ntos_work(&wrap_urb_complete_work);
+}
+
+/* one worker for all devices */
+static void wrap_urb_complete_worker(worker_param_t dummy)
+{
+	struct irp *irp;
+	struct urb *urb;
+	struct usbd_bulk_or_intr_transfer *bulk_int_tx;
+	struct usbd_vendor_or_class_request *vc_req;
+	union nt_urb *nt_urb;
+	struct wrap_urb *wrap_urb;
+	struct nt_list *ent;
+	unsigned long flags;
+
+	USBENTER("");
+	while (1) {
+		spin_lock_irqsave(&wrap_urb_complete_list_lock, flags);
+		ent = RemoveHeadList(&wrap_urb_complete_list);
+		spin_unlock_irqrestore(&wrap_urb_complete_list_lock, flags);
+		if (!ent)
+			break;
+		wrap_urb = container_of(ent, struct wrap_urb, complete_list);
+		urb = wrap_urb->urb;
+#ifdef USB_DEBUG
+		if (wrap_urb->state != URB_COMPLETED &&
+		    wrap_urb->state != URB_INT_UNLINKED)
+			WARNING("urb %p in wrong state: %d",
+				urb, wrap_urb->state);
+#endif
+		irp = wrap_urb->irp;
+		DUMP_IRP(irp);
+		nt_urb = IRP_URB(irp);
+		USBTRACE("urb: %p, nt_urb: %p, status: %d",
+			 urb, nt_urb, urb->status);
+		switch (urb->status) {
+		case 0:
+			/* succesfully transferred */
+			irp->io_status.info = urb->actual_length;
+			if (nt_urb->header.function ==
+			    URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
+				bulk_int_tx = &nt_urb->bulk_int_transfer;
+				bulk_int_tx->transfer_buffer_length =
+					urb->actual_length;
+				DUMP_URB_BUFFER(urb, USB_DIR_IN);
+				if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&
+				    usb_pipein(urb->pipe))
+					memcpy(bulk_int_tx->transfer_buffer,
+					       urb->transfer_buffer,
+					       urb->actual_length);
+			} else { // vendor or class request
+				vc_req = &nt_urb->vendor_class_request;
+				vc_req->transfer_buffer_length =
+					urb->actual_length;
+				DUMP_URB_BUFFER(urb, USB_DIR_IN);
+				if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&
+				    usb_pipein(urb->pipe))
+					memcpy(vc_req->transfer_buffer,
+					       urb->transfer_buffer,
+					       urb->actual_length);
+			}
+			NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
+			irp->io_status.status = STATUS_SUCCESS;
+			break;
+		case -ENOENT:
+		case -ECONNRESET:
+			/* urb canceled */
+			irp->io_status.info = 0;
+			TRACE2("urb %p canceled", urb);
+			NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
+			irp->io_status.status = STATUS_CANCELLED;
+			break;
+		default:
+			TRACE2("irp: %p, urb: %p, status: %d/%d",
+				 irp, urb, urb->status, wrap_urb->state);
+			irp->io_status.info = 0;
+			NT_URB_STATUS(nt_urb) = wrap_urb_status(urb->status);
+			irp->io_status.status =
+				nt_urb_irp_status(NT_URB_STATUS(nt_urb));
+			break;
+		}
+		wrap_free_urb(urb);
+		IoCompleteRequest(irp, IO_NO_INCREMENT);
+	}
+	USBEXIT(return);
+}
+
+static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp)
+{
+	usbd_pipe_handle pipe_handle;
+	struct urb *urb;
+	unsigned int pipe;
+	struct usbd_bulk_or_intr_transfer *bulk_int_tx;
+	USBD_STATUS status;
+	struct usb_device *udev;
+	union nt_urb *nt_urb;
+
+	nt_urb = IRP_URB(irp);
+	udev = IRP_WRAP_DEVICE(irp)->usb.udev;
+	bulk_int_tx = &nt_urb->bulk_int_transfer;
+	pipe_handle = bulk_int_tx->pipe_handle;
+	USBTRACE("flags: 0x%x, length: %u, buffer: %p, handle: %p",
+		 bulk_int_tx->transfer_flags,
+		 bulk_int_tx->transfer_buffer_length,
+		 bulk_int_tx->transfer_buffer, pipe_handle);
+
+	if (USBD_IS_BULK_PIPE(pipe_handle)) {
+		if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)
+			pipe = usb_rcvbulkpipe(udev,
+					       pipe_handle->bEndpointAddress);
+		else
+			pipe = usb_sndbulkpipe(udev,
+					       pipe_handle->bEndpointAddress);
+	} else {
+		if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)
+			pipe = usb_rcvintpipe(udev,
+					      pipe_handle->bEndpointAddress);
+		else
+			pipe = usb_sndintpipe(udev,
+					      pipe_handle->bEndpointAddress);
+	}
+
+	DUMP_IRP(irp);
+	urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer,
+			     bulk_int_tx->transfer_buffer_length);
+	if (!urb) {
+		ERROR("couldn't allocate urb");
+		return USBD_STATUS_NO_MEMORY;
+	}
+	if (usb_pipein(pipe) &&
+	    (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
+		USBTRACE("short not ok");
+		urb->transfer_flags |= URB_SHORT_NOT_OK;
+	}
+	if (usb_pipebulk(pipe)) {
+		usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer,
+				  bulk_int_tx->transfer_buffer_length,
+				  wrap_urb_complete, urb->context);
+		USBTRACE("submitting bulk urb %p on pipe 0x%x (ep 0x%x)",
+			 urb, urb->pipe, pipe_handle->bEndpointAddress);
+	} else {
+		usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer,
+				 bulk_int_tx->transfer_buffer_length,
+				 wrap_urb_complete, urb->context,
+				 pipe_handle->bInterval);
+		USBTRACE("submitting interrupt urb %p on pipe 0x%x (ep 0x%x), "
+			 "intvl: %d", urb, urb->pipe,
+			 pipe_handle->bEndpointAddress, pipe_handle->bInterval);
+	}
+	status = wrap_submit_urb(irp);
+	USBTRACE("status: %08X", status);
+	USBEXIT(return status);
+}
+
+static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp)
+{
+	u8 req_type;
+	unsigned int pipe;
+	struct usbd_vendor_or_class_request *vc_req;
+	struct usb_device *udev;
+	union nt_urb *nt_urb;
+	USBD_STATUS status;
+	struct urb *urb;
+	struct usb_ctrlrequest *dr;
+
+	nt_urb = IRP_URB(irp);
+	udev = IRP_WRAP_DEVICE(irp)->usb.udev;
+	vc_req = &nt_urb->vendor_class_request;
+	USBTRACE("bits: %x, req: %x, val: %08x, index: %08x, flags: %x,"
+		 "buf: %p, len: %d", vc_req->reserved_bits, vc_req->request,
+		 vc_req->value, vc_req->index, vc_req->transfer_flags,
+		 vc_req->transfer_buffer, vc_req->transfer_buffer_length);
+
+	USBTRACE("%x", nt_urb->header.function);
+	switch (nt_urb->header.function) {
+	case URB_FUNCTION_VENDOR_DEVICE:
+		req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+		break;
+	case URB_FUNCTION_VENDOR_INTERFACE:
+		req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
+		break;
+	case URB_FUNCTION_VENDOR_ENDPOINT:
+		req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+		break;
+	case URB_FUNCTION_VENDOR_OTHER:
+		req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;
+		break;
+	case URB_FUNCTION_CLASS_DEVICE:
+		req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE;
+		break;
+	case URB_FUNCTION_CLASS_INTERFACE:
+		req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		break;
+	case URB_FUNCTION_CLASS_ENDPOINT:
+		req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT;
+		break;
+	case URB_FUNCTION_CLASS_OTHER:
+		req_type = USB_TYPE_CLASS | USB_RECIP_OTHER;
+		break;
+	default:
+		ERROR("unknown request type: %x", nt_urb->header.function);
+		req_type = 0;
+		break;
+	}
+
+	req_type |= vc_req->reserved_bits;
+	USBTRACE("req type: %08x", req_type);
+
+	if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) {
+		pipe = usb_rcvctrlpipe(udev, 0);
+		req_type |= USB_DIR_IN;
+		USBTRACE("pipe: %x, dir in", pipe);
+	} else {
+		pipe = usb_sndctrlpipe(udev, 0);
+		req_type |= USB_DIR_OUT;
+		USBTRACE("pipe: %x, dir out", pipe);
+	}
+	urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer,
+			     vc_req->transfer_buffer_length);
+	if (!urb) {
+		ERROR("couldn't allocate urb");
+		return USBD_STATUS_NO_MEMORY;
+	}
+
+	if (usb_pipein(pipe) &&
+	    (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) {
+		USBTRACE("short not ok");
+		urb->transfer_flags |= URB_SHORT_NOT_OK;
+	}
+
+	dr = kzalloc(sizeof(*dr), GFP_ATOMIC);
+	if (!dr) {
+		ERROR("couldn't allocate memory");
+		wrap_free_urb(urb);
+		return USBD_STATUS_NO_MEMORY;
+	}
+	dr->bRequestType = req_type;
+	dr->bRequest = vc_req->request;
+	dr->wValue = cpu_to_le16(vc_req->value);
+	dr->wIndex = cpu_to_le16((u16)vc_req->index);
+	dr->wLength = cpu_to_le16((u16)urb->transfer_buffer_length);
+
+	usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr,
+			     urb->transfer_buffer, urb->transfer_buffer_length,
+			     wrap_urb_complete, urb->context);
+	status = wrap_submit_urb(irp);
+	USBTRACE("status: %08X", status);
+	USBEXIT(return status);
+}
+
+static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp)
+{
+	int ret;
+	union nt_urb *nt_urb;
+	usbd_pipe_handle pipe_handle;
+	unsigned int pipe1, pipe2;
+
+	nt_urb = IRP_URB(irp);
+	pipe_handle = nt_urb->pipe_req.pipe_handle;
+	/* TODO: not clear if both directions should be cleared? */
+	if (USBD_IS_BULK_PIPE(pipe_handle)) {
+		pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress);
+		pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress);
+	} else if (USBD_IS_INT_PIPE(pipe_handle)) {
+		pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress);
+		pipe2 = pipe1;
+	} else {
+		WARNING("invalid pipe %d", pipe_handle->bEndpointAddress);
+		return USBD_STATUS_INVALID_PIPE_HANDLE;
+	}
+	USBTRACE("ep: %d, pipe: 0x%x", pipe_handle->bEndpointAddress, pipe1);
+	ret = usb_clear_halt(udev, pipe1);
+	if (ret)
+		USBTRACE("resetting pipe %d failed: %d", pipe1, ret);
+	if (pipe2 != pipe1) {
+		ret = usb_clear_halt(udev, pipe2);
+		if (ret)
+			USBTRACE("resetting pipe %d failed: %d", pipe2, ret);
+	}
+//	return wrap_urb_status(ret);
+	return USBD_STATUS_SUCCESS;
+}
+
+static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp)
+{
+	union nt_urb *nt_urb;
+	usbd_pipe_handle pipe_handle;
+	struct wrap_urb *wrap_urb;
+	struct wrap_device *wd;
+	KIRQL irql;
+
+	wd = IRP_WRAP_DEVICE(irp);
+	nt_urb = IRP_URB(irp);
+	pipe_handle = nt_urb->pipe_req.pipe_handle;
+	USBENTER("%p, %x", irp, pipe_handle->bEndpointAddress);
+	IoAcquireCancelSpinLock(&irql);
+	nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) {
+		USBTRACE("%p, %p, %d, %x, %x", wrap_urb, wrap_urb->urb,
+			 wrap_urb->state, wrap_urb->urb->pipe,
+			 usb_pipeendpoint(wrap_urb->urb->pipe));
+		/* for WG111T driver, urbs for endpoint 0 should also
+		 * be canceled */
+		if ((usb_pipeendpoint(wrap_urb->urb->pipe) ==
+		     pipe_handle->bEndpointAddress) ||
+		    (usb_pipeendpoint(wrap_urb->urb->pipe) == 0)) {
+			if (wrap_cancel_urb(wrap_urb) == 0)
+				USBTRACE("canceled wrap_urb: %p", wrap_urb);
+		}
+	}
+	IoReleaseCancelSpinLock(irql);
+	NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELED;
+	USBEXIT(return USBD_STATUS_SUCCESS);
+}
+
+static USBD_STATUS wrap_set_clear_feature(struct usb_device *udev,
+					  struct irp *irp)
+{
+	union nt_urb *nt_urb;
+	struct urb_control_feature_request *feat_req;
+	int ret = 0;
+	__u8 request, type;
+	__u16 feature;
+
+	nt_urb = IRP_URB(irp);
+	feat_req = &nt_urb->feat_req;
+	feature = feat_req->feature_selector;
+	switch (nt_urb->header.function) {
+	case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
+		request = USB_REQ_SET_FEATURE;
+		type = USB_DT_DEVICE;
+		break;
+	case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
+		request = USB_REQ_SET_FEATURE;
+		type =  USB_DT_INTERFACE;
+		break;
+	case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
+		request = USB_REQ_SET_FEATURE;
+		type =  USB_DT_ENDPOINT;
+		break;
+	case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
+		request = USB_REQ_CLEAR_FEATURE;
+		type =  USB_DT_DEVICE;
+		break;
+	case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
+		request = USB_REQ_CLEAR_FEATURE;
+		type =  USB_DT_INTERFACE;
+		break;
+	case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
+		request = USB_REQ_CLEAR_FEATURE;
+		type =  USB_DT_ENDPOINT;
+		break;
+	default:
+		WARNING("invalid function: %x", nt_urb->header.function);
+		NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
+		return NT_URB_STATUS(nt_urb);
+	}
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, type,
+			      feature, feat_req->index, NULL, 0, 1000);
+	NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
+	USBEXIT(return NT_URB_STATUS(nt_urb));
+}
+
+static USBD_STATUS wrap_get_status_request(struct usb_device *udev,
+					   struct irp *irp)
+{
+	union nt_urb *nt_urb;
+	struct urb_control_get_status_request *status_req;
+	int ret = 0;
+	__u8 type;
+
+	nt_urb = IRP_URB(irp);
+	status_req = &nt_urb->status_req;
+	switch (nt_urb->header.function) {
+	case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+		type = USB_RECIP_DEVICE;
+		break;
+	case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
+		type = USB_RECIP_INTERFACE;
+		break;
+	case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
+		type = USB_RECIP_ENDPOINT;
+		break;
+	default:
+		WARNING("invalid function: %x", nt_urb->header.function);
+		NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
+		return NT_URB_STATUS(nt_urb);
+	}
+	assert(status_req->transfer_buffer_length == sizeof(u16));
+	ret = usb_get_status(udev, type, status_req->index,
+			     status_req->transfer_buffer);
+	if (ret >= 0) {
+		assert(ret <= status_req->transfer_buffer_length);
+		status_req->transfer_buffer_length = ret;
+		NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;
+	} else
+		NT_URB_STATUS(nt_urb) = wrap_urb_status(ret);
+	USBEXIT(return NT_URB_STATUS(nt_urb));
+}
+
+static void set_intf_pipe_info(struct wrap_device *wd,
+			       struct usb_interface *usb_intf,
+			       struct usbd_interface_information *intf)
+{
+	int i;
+	struct usb_endpoint_descriptor *ep;
+	struct usbd_pipe_information *pipe;
+
+	for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints; i++) {
+		ep = &(CUR_ALT_SETTING(usb_intf)->endpoint[i]).desc;
+		if (i >= intf->bNumEndpoints) {
+			ERROR("intf %p has only %d endpoints, "
+			      "ignoring endpoints above %d",
+			      intf, intf->bNumEndpoints, i);
+			break;
+		}
+		pipe = &intf->pipes[i];
+
+		if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET)
+			USBTRACE("pkt_sz: %d: %d", pipe->wMaxPacketSize,
+				 pipe->max_tx_size);
+		USBTRACE("driver wants max_tx_size to %d",
+			 pipe->max_tx_size);
+
+		pipe->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
+		pipe->bEndpointAddress = ep->bEndpointAddress;
+		pipe->type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+		if (pipe->type == UsbdPipeTypeInterrupt) {
+			/* Windows and Linux differ in how the
+			 * bInterval is interpretted */
+			/* for low speed:
+			   interval (Windows) -> frames per ms (Linux)
+			   0 to 15    -> 8
+			   16 to 35   -> 16
+			   36 to 255  -> 32
+
+			   for full speed: interval -> frames per ms
+			   1          -> 1
+			   2 to 3     -> 2
+			   4 to 7     -> 4
+			   8 to 15    -> 8
+			   16 to 31   -> 16
+			   32 to 255  -> 32
+
+			   for high speed: interval -> microframes
+			   1          -> 1
+			   2          -> 2
+			   3          -> 4
+			   4          -> 8
+			   5          -> 16
+			   6          -> 32
+			   7 to 255   -> 32
+			*/
+			if (wd->usb.udev->speed == USB_SPEED_LOW)
+				pipe->bInterval = ep->bInterval + 5;
+			else if (wd->usb.udev->speed == USB_SPEED_FULL)
+				pipe->bInterval = ep->bInterval;
+			else {
+				int j, k;
+				for (j = k = 1; j < ep->bInterval; k++)
+					j *= 2;
+				pipe->bInterval = k;
+			}
+		}
+		pipe->handle = ep;
+		USBTRACE("%d: ep 0x%x, type %d, pkt_sz %d, intv %d (%d),"
+			 "type: %d, handle %p", i, ep->bEndpointAddress,
+			 ep->bmAttributes, pipe->wMaxPacketSize, ep->bInterval,
+			 pipe->bInterval, pipe->type, pipe->handle);
+	}
+}
+
+static USBD_STATUS wrap_select_configuration(struct wrap_device *wd,
+					     union nt_urb *nt_urb,
+					     struct irp *irp)
+{
+	int i, ret;
+	struct usbd_select_configuration *sel_conf;
+	struct usb_device *udev;
+	struct usbd_interface_information *intf;
+	struct usb_config_descriptor *config;
+	struct usb_interface *usb_intf;
+
+	udev = wd->usb.udev;
+	sel_conf = &nt_urb->select_conf;
+	config = sel_conf->config;
+	USBTRACE("%p", config);
+	if (config == NULL) {
+		kill_all_urbs(wd, 1);
+		ret = usb_reset_configuration(udev);
+		return wrap_urb_status(ret);
+	}
+
+	USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x",
+		 config->bConfigurationValue, config->bDescriptorType,
+		 config->wTotalLength, config->bNumInterfaces,
+		 config->bmAttributes);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			      USB_REQ_SET_CONFIGURATION, 0,
+			      config->bConfigurationValue, 0,
+			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0) {
+		ERROR("ret: %d", ret);
+		return wrap_urb_status(ret);
+	}
+	sel_conf->handle = udev->actconfig;
+	intf = &sel_conf->intf;
+	for (i = 0; i < config->bNumInterfaces && intf->bLength > 0;
+	     i++, intf = (((void *)intf) + intf->bLength)) {
+
+		USBTRACE("intf: %d, alt setting: %d",
+			 intf->bInterfaceNumber, intf->bAlternateSetting);
+		ret = usb_set_interface(udev, intf->bInterfaceNumber,
+					intf->bAlternateSetting);
+		if (ret < 0) {
+			ERROR("failed with %d", ret);
+			return wrap_urb_status(ret);
+		}
+		usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);
+		if (!usb_intf) {
+			ERROR("couldn't obtain ifnum");
+			return USBD_STATUS_REQUEST_FAILED;
+		}
+		USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints);
+		set_intf_pipe_info(wd, usb_intf, intf);
+	}
+	return USBD_STATUS_SUCCESS;
+}
+
+static USBD_STATUS wrap_select_interface(struct wrap_device *wd,
+					 union nt_urb *nt_urb,
+					 struct irp *irp)
+{
+	int ret;
+	struct usbd_select_interface *sel_intf;
+	struct usb_device *udev;
+	struct usbd_interface_information *intf;
+	struct usb_interface *usb_intf;
+
+	udev = wd->usb.udev;
+	sel_intf = &nt_urb->select_intf;
+	intf = &sel_intf->intf;
+
+	ret = usb_set_interface(udev, intf->bInterfaceNumber,
+				intf->bAlternateSetting);
+	if (ret < 0) {
+		ERROR("failed with %d", ret);
+		return wrap_urb_status(ret);
+	}
+	usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);
+	if (!usb_intf) {
+		ERROR("couldn't get interface information");
+		return USBD_STATUS_REQUEST_FAILED;
+	}
+	USBTRACE("intf: %p, num ep: %d", usb_intf, intf->bNumEndpoints);
+	set_intf_pipe_info(wd, usb_intf, intf);
+	return USBD_STATUS_SUCCESS;
+}
+
+static int wrap_usb_get_string(struct usb_device *udev, unsigned short langid,
+			       unsigned char index, void *buf, int size)
+{
+	int i, ret;
+	/* if langid is 0, return array of langauges supported in
+	 * buf */
+	for (i = 0; i < 3; i++) {
+		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				      USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+				      (USB_DT_STRING << 8) + index, langid,
+				      buf, size, USB_CTRL_GET_TIMEOUT);
+		if (ret > 0 || ret == -EPIPE)
+			break;
+	}
+	return ret;
+}
+
+static USBD_STATUS wrap_get_descriptor(struct wrap_device *wd,
+				       union nt_urb *nt_urb, struct irp *irp)
+{
+	struct usbd_control_descriptor_request *control_desc;
+	int ret = 0;
+	struct usb_device *udev;
+
+	udev = wd->usb.udev;
+	control_desc = &nt_urb->control_desc;
+	USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p,"
+		 "transfer_buffer_length = %d", control_desc->desc_type,
+		 control_desc->index, control_desc->transfer_buffer,
+		 control_desc->transfer_buffer_length);
+
+	if (control_desc->desc_type == USB_DT_STRING) {
+		USBTRACE("langid: %x", control_desc->language_id);
+		ret = wrap_usb_get_string(udev, control_desc->language_id,
+					  control_desc->index,
+					  control_desc->transfer_buffer,
+					  control_desc->transfer_buffer_length);
+	} else {
+		ret = usb_get_descriptor(udev, control_desc->desc_type,
+					 control_desc->index,
+					 control_desc->transfer_buffer,
+					 control_desc->transfer_buffer_length);
+	}
+	if (ret < 0) {
+		USBTRACE("request %d failed: %d", control_desc->desc_type, ret);
+		control_desc->transfer_buffer_length = 0;
+		return wrap_urb_status(ret);
+	} else {
+		USBTRACE("ret: %08x", ret);
+		control_desc->transfer_buffer_length = ret;
+		irp->io_status.info = ret;
+		return USBD_STATUS_SUCCESS;
+	}
+}
+
+static USBD_STATUS wrap_process_nt_urb(struct irp *irp)
+{
+	union nt_urb *nt_urb;
+	struct usb_device *udev;
+	USBD_STATUS status;
+	struct wrap_device *wd;
+
+	wd = IRP_WRAP_DEVICE(irp);
+	udev = wd->usb.udev;
+	nt_urb = IRP_URB(irp);
+	USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x",
+		 nt_urb, irp, nt_urb->header.length, nt_urb->header.function);
+
+	DUMP_IRP(irp);
+	switch (nt_urb->header.function) {
+		/* bulk/int and vendor/class urbs are submitted to
+		 * Linux USB core; if the call is sucessful, urb's
+		 * completion worker will return IRP later */
+	case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+		USBTRACE("submitting bulk/int irp: %p", irp);
+		status = wrap_bulk_or_intr_trans(irp);
+		break;
+
+	case URB_FUNCTION_VENDOR_DEVICE:
+	case URB_FUNCTION_VENDOR_INTERFACE:
+	case URB_FUNCTION_VENDOR_ENDPOINT:
+	case URB_FUNCTION_VENDOR_OTHER:
+	case URB_FUNCTION_CLASS_DEVICE:
+	case URB_FUNCTION_CLASS_INTERFACE:
+	case URB_FUNCTION_CLASS_ENDPOINT:
+	case URB_FUNCTION_CLASS_OTHER:
+		USBTRACE("submitting vendor/class irp: %p", irp);
+		status = wrap_vendor_or_class_req(irp);
+		break;
+
+		/* rest are synchronous */
+	case URB_FUNCTION_SELECT_CONFIGURATION:
+		status = wrap_select_configuration(wd, nt_urb, irp);
+		NT_URB_STATUS(nt_urb) = status;
+		break;
+
+	case URB_FUNCTION_SELECT_INTERFACE:
+		status = wrap_select_interface(wd, nt_urb, irp);
+		NT_URB_STATUS(nt_urb) = status;
+		break;
+
+	case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+		status = wrap_get_descriptor(wd, nt_urb, irp);
+		NT_URB_STATUS(nt_urb) = status;
+		break;
+
+	case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
+		status = wrap_reset_pipe(udev, irp);
+		NT_URB_STATUS(nt_urb) = status;
+		break;
+
+	case URB_FUNCTION_ABORT_PIPE:
+		status = wrap_abort_pipe(udev, irp);
+		break;
+
+	case URB_FUNCTION_SET_FEATURE_TO_DEVICE:
+	case URB_FUNCTION_SET_FEATURE_TO_INTERFACE:
+	case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT:
+	case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE:
+	case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE:
+	case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT:
+		status = wrap_set_clear_feature(udev, irp);
+		break;
+
+	case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+	case URB_FUNCTION_GET_STATUS_FROM_INTERFACE:
+	case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT:
+		status = wrap_get_status_request(udev, irp);
+		break;
+
+	default:
+		ERROR("function %x not implemented", nt_urb->header.function);
+		status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED;
+		break;
+	}
+	USBTRACE("status: %08X", status);
+	return status;
+}
+
+static USBD_STATUS wrap_reset_port(struct irp *irp)
+{
+	no_warn_unused int ret, lock = 0;
+	struct wrap_device *wd;
+
+	wd = IRP_WRAP_DEVICE(irp);
+	USBENTER("%p, %p", wd, wd->usb.udev);
+	lock = usb_lock_device_for_reset(wd->usb.udev, wd->usb.intf);
+	if (lock < 0) {
+		WARNING("locking failed: %d", lock);
+//		return wrap_urb_status(lock);
+		return USBD_STATUS_SUCCESS;
+	}
+	ret = usb_reset_device(wd->usb.udev);
+	if (ret < 0)
+		USBTRACE("reset failed: %d", ret);
+	/* TODO: should reconfigure? */
+	if (lock)
+		usb_unlock_device(wd->usb.udev);
+//	return wrap_urb_status(ret);
+	return USBD_STATUS_SUCCESS;
+}
+
+static USBD_STATUS wrap_get_port_status(struct irp *irp)
+{
+	struct wrap_device *wd;
+	ULONG *status;
+	enum usb_device_state state;
+
+	wd = IRP_WRAP_DEVICE(irp);
+	USBENTER("%p, %p", wd, wd->usb.udev);
+	status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1;
+	state = wd->usb.udev->state;
+	if (state != USB_STATE_NOTATTACHED &&
+	    state != USB_STATE_SUSPENDED) {
+		*status |= USBD_PORT_CONNECTED;
+		if (state == USB_STATE_CONFIGURED)
+			*status |= USBD_PORT_ENABLED;
+	}
+	USBTRACE("state: %d, *status: %08X", state, *status);
+	return USBD_STATUS_SUCCESS;
+}
+
+NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	struct wrap_device *wd;
+	USBD_STATUS status;
+	struct usbd_idle_callback *idle_callback;
+
+	USBENTER("%p, %p", pdo, irp);
+	wd = pdo->reserved;
+	if (wd->usb.intf == NULL) {
+		USBTRACE("%p", irp);
+		irp->io_status.status = STATUS_DEVICE_REMOVED;
+		irp->io_status.info = 0;
+		USBEXIT(return STATUS_DEVICE_REMOVED);
+	}
+	IRP_WRAP_DEVICE(irp) = wd;
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	switch (irp_sl->params.dev_ioctl.code) {
+	case IOCTL_INTERNAL_USB_SUBMIT_URB:
+		status = wrap_process_nt_urb(irp);
+		break;
+	case IOCTL_INTERNAL_USB_RESET_PORT:
+		status = wrap_reset_port(irp);
+		break;
+	case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
+		status = wrap_get_port_status(irp);
+		break;
+	case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
+		idle_callback = irp_sl->params.dev_ioctl.type3_input_buf;
+		USBTRACE("suspend function: %p", idle_callback->callback);
+		status = USBD_STATUS_NOT_SUPPORTED;
+		break;
+	default:
+		ERROR("ioctl %08X NOT IMPLEMENTED",
+		      irp_sl->params.dev_ioctl.code);
+		status = USBD_STATUS_NOT_SUPPORTED;
+		break;
+	}
+
+	USBTRACE("status: %08X", status);
+	if (status == USBD_STATUS_PENDING) {
+		/* don't touch this IRP - it may have been already
+		 * completed/returned */
+		return STATUS_PENDING;
+	} else {
+		irp->io_status.status = nt_urb_irp_status(status);
+		if (status != USBD_STATUS_SUCCESS)
+			irp->io_status.info = 0;
+		USBEXIT(return irp->io_status.status);
+	}
+}
+
+/* TODO: The example on msdn in reference section suggests that second
+ * argument should be an array of usbd_interface_information, but
+ * description and examples elsewhere suggest that it should be
+ * usbd_interface_list_entry structre. Which is correct? */
+
+wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequestEx,2)
+	(struct usb_config_descriptor *config,
+	 struct usbd_interface_list_entry *intf_list)
+{
+	int size, i, n;
+	struct usbd_interface_information *intf;
+	struct usbd_pipe_information *pipe;
+	struct usb_interface_descriptor *intf_desc;
+	struct usbd_select_configuration *select_conf;
+
+	USBENTER("config = %p, intf_list = %p", config, intf_list);
+
+	/* calculate size required; select_conf already has space for
+	 * one intf structure */
+	size = sizeof(*select_conf) - sizeof(*intf);
+	for (n = 0; n < config->bNumInterfaces; n++) {
+		i = intf_list[n].intf_desc->bNumEndpoints;
+		/* intf already has space for one pipe */
+		size += sizeof(*intf) + (i - 1) * sizeof(*pipe);
+	}
+	/* don't use kmalloc - driver frees it with ExFreePool */
+	select_conf = ExAllocatePoolWithTag(NonPagedPool, size,
+					    POOL_TAG('L', 'U', 'S', 'B'));
+	if (!select_conf) {
+		WARNING("couldn't allocate memory");
+		return NULL;
+	}
+	memset(select_conf, 0, size);
+	intf = &select_conf->intf;
+	select_conf->handle = config;
+	for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc; n++) {
+		/* initialize 'intf' fields in intf_list so they point
+		 * to appropriate entry; these may be read/written by
+		 * driver after this function returns */
+		intf_list[n].intf = intf;
+		intf_desc = intf_list[n].intf_desc;
+
+		i = intf_desc->bNumEndpoints;
+		intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe);
+
+		intf->bInterfaceNumber = intf_desc->bInterfaceNumber;
+		intf->bAlternateSetting = intf_desc->bAlternateSetting;
+		intf->bInterfaceClass = intf_desc->bInterfaceClass;
+		intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass;
+		intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol;
+		intf->bNumEndpoints = intf_desc->bNumEndpoints;
+
+		pipe = &intf->pipes[0];
+		for (i = 0; i < intf->bNumEndpoints; i++) {
+			memset(&pipe[i], 0, sizeof(*pipe));
+			pipe[i].max_tx_size =
+				USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
+		}
+		intf->handle = intf_desc;
+		intf = (((void *)intf) + intf->bLength);
+	}
+	select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION;
+	select_conf->header.length = size;
+	select_conf->config = config;
+	USBEXIT(return (union nt_urb *)select_conf);
+}
+
+WIN_SYMBOL_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx)
+
+wstdcall struct usb_interface_descriptor *
+WIN_FUNC(USBD_ParseConfigurationDescriptorEx,7)
+	(struct usb_config_descriptor *config, void *start,
+	 LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass,
+	 LONG bInterfaceSubClass, LONG bInterfaceProtocol)
+{
+	void *pos;
+	struct usb_interface_descriptor *intf;
+
+	USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d,"
+		 " class = %d, subclass = %d, proto = %d", config, start,
+		 bInterfaceNumber, bAlternateSetting, bInterfaceClass,
+		 bInterfaceSubClass, bInterfaceProtocol);
+
+	for (pos = start;
+	     pos < ((void *)config + le16_to_cpu(config->wTotalLength));
+	     pos += intf->bLength) {
+
+		intf = pos;
+
+		if ((intf->bDescriptorType == USB_DT_INTERFACE) &&
+		    ((bInterfaceNumber == -1) ||
+		     (intf->bInterfaceNumber == bInterfaceNumber)) &&
+		    ((bAlternateSetting == -1) ||
+		     (intf->bAlternateSetting == bAlternateSetting)) &&
+		    ((bInterfaceClass == -1) ||
+		     (intf->bInterfaceClass == bInterfaceClass)) &&
+		    ((bInterfaceSubClass == -1) ||
+		     (intf->bInterfaceSubClass == bInterfaceSubClass)) &&
+		    ((bInterfaceProtocol == -1) ||
+		     (intf->bInterfaceProtocol == bInterfaceProtocol))) {
+			USBTRACE("selected interface = %p", intf);
+			USBEXIT(return intf);
+		}
+	}
+	USBEXIT(return NULL);
+}
+
+WIN_SYMBOL_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx)
+
+wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequest,2)
+	(struct usb_config_descriptor *config, USHORT *size)
+{
+	union nt_urb *nt_urb;
+	struct usbd_interface_list_entry intf_list[2];
+	struct usb_interface_descriptor *intf_desc;
+
+	USBENTER("config = %p, urb_size = %p", config, size);
+
+	intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1,
+							-1, -1, -1);
+	intf_list[0].intf_desc = intf_desc;
+	intf_list[0].intf = NULL;
+	intf_list[1].intf_desc = NULL;
+	intf_list[1].intf = NULL;
+	nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list);
+	if (!nt_urb)
+		return NULL;
+
+	*size = nt_urb->select_conf.header.length;
+	USBEXIT(return nt_urb);
+}
+
+wstdcall struct usb_interface_descriptor *
+WIN_FUNC(USBD_ParseConfigurationDescriptor,3)
+	(struct usb_config_descriptor *config, UCHAR bInterfaceNumber,
+	 UCHAR bAlternateSetting)
+{
+	return USBD_ParseConfigurationDescriptorEx(config, config,
+						   bInterfaceNumber,
+						   bAlternateSetting,
+						   -1, -1, -1);
+}
+
+wstdcall usb_common_descriptor_t *WIN_FUNC(USBD_ParseDescriptors,4)
+	(void *buf, ULONG length, void *start, LONG type)
+{
+	usb_common_descriptor_t *descr = start;
+
+	while ((void *)descr < buf + length) {
+		if (descr->bDescriptorType == type)
+			return descr;
+		if (descr->bLength == 0)
+			break;
+		descr = (void *)descr + descr->bLength;
+	}
+	USBEXIT(return NULL);
+}
+
+WIN_SYMBOL_MAP("_USBD_ParseDescriptors@16", USBD_ParseDescriptors)
+
+wstdcall void WIN_FUNC(USBD_GetUSBDIVersion,1)
+	(struct usbd_version_info *version_info)
+{
+	/* this function is obsolete in Windows XP */
+	if (version_info) {
+		version_info->usbdi_version = USBDI_VERSION_XP;
+		/* TODO: how do we get this correctly? */
+		version_info->supported_usb_version = 0x110;
+	}
+	USBEXIT(return);
+}
+
+wstdcall void
+USBD_InterfaceGetUSBDIVersion(void *context,
+			      struct usbd_version_info *version_info,
+			      ULONG *hcd_capa)
+{
+	struct wrap_device *wd = context;
+
+	if (version_info) {
+		version_info->usbdi_version = USBDI_VERSION_XP;
+		if (wd->usb.udev->speed == USB_SPEED_HIGH)
+			version_info->supported_usb_version = 0x200;
+		else
+			version_info->supported_usb_version = 0x110;
+	}
+	*hcd_capa = USB_HCD_CAPS_SUPPORTS_RT_THREADS;
+	USBEXIT(return);
+}
+
+wstdcall BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context)
+{
+	struct wrap_device *wd = context;
+
+	USBTRACE("wd: %p", wd);
+	if (wd->usb.udev->speed == USB_SPEED_HIGH)
+		USBEXIT(return TRUE);
+	else
+		USBEXIT(return FALSE);
+}
+
+wstdcall void USBD_InterfaceReference(void *context)
+{
+	USBTRACE("%p", context);
+	TODO();
+}
+
+wstdcall void USBD_InterfaceDereference(void *context)
+{
+	USBTRACE("%p", context);
+	TODO();
+}
+
+wstdcall NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame)
+{
+	struct wrap_device *wd = context;
+
+	*frame = usb_get_current_frame_number(wd->usb.udev);
+	USBEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context,
+					       union nt_urb *nt_urb)
+{
+	/* TODO: implement this */
+	TODO();
+	USBEXIT(return STATUS_NOT_IMPLEMENTED);
+}
+
+wstdcall NTSTATUS
+USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf,
+				  ULONG *buf_length, ULONG *buf_actual_length)
+{
+	struct wrap_device *wd = context;
+	struct usb_bus_information_level *bus_info;
+	struct usb_bus *bus;
+
+	bus = wd->usb.udev->bus;
+	bus_info = buf;
+	TODO();
+	USBEXIT(return STATUS_NOT_IMPLEMENTED);
+}
+
+wstdcall NTSTATUS
+USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag,
+		       ULONG p1, ULONG p2)
+{
+	ERROR("%p, %x, %x, %x, %x", context, driver_tag, enum_tag, p1, p2);
+	USBEXIT(return STATUS_SUCCESS);
+}
+
+int usb_init(void)
+{
+	InitializeListHead(&wrap_urb_complete_list);
+	spin_lock_init(&wrap_urb_complete_list_lock);
+	initialize_work(&wrap_urb_complete_work, wrap_urb_complete_worker, NULL);
+#ifdef USB_DEBUG
+	urb_id = 0;
+#endif
+	return 0;
+}
+
+void usb_exit(void)
+{
+	USBEXIT(return);
+}
+
+int usb_init_device(struct wrap_device *wd)
+{
+	InitializeListHead(&wd->usb.wrap_urb_list);
+	wd->usb.num_alloc_urbs = 0;
+	USBEXIT(return 0);
+}
+
+void usb_exit_device(struct wrap_device *wd)
+{
+	kill_all_urbs(wd, 0);
+	USBEXIT(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/pe_linker.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/pe_linker.h
@@ -0,0 +1,993 @@
+/*
+ * This file is an excerpt of winnt.h from WINE, which bears the
+ * following copyright:
+ *
+ * Win32 definitions for Windows NT
+ *
+ * Copyright 1996 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+/*
+ * File formats definitions
+ */
+typedef struct _IMAGE_DOS_HEADER {
+    WORD  e_magic;      /* 00: MZ Header signature */
+    WORD  e_cblp;       /* 02: Bytes on last page of file */
+    WORD  e_cp;         /* 04: Pages in file */
+    WORD  e_crlc;       /* 06: Relocations */
+    WORD  e_cparhdr;    /* 08: Size of header in paragraphs */
+    WORD  e_minalloc;   /* 0a: Minimum extra paragraphs needed */
+    WORD  e_maxalloc;   /* 0c: Maximum extra paragraphs needed */
+    WORD  e_ss;         /* 0e: Initial (relative) SS value */
+    WORD  e_sp;         /* 10: Initial SP value */
+    WORD  e_csum;       /* 12: Checksum */
+    WORD  e_ip;         /* 14: Initial IP value */
+    WORD  e_cs;         /* 16: Initial (relative) CS value */
+    WORD  e_lfarlc;     /* 18: File address of relocation table */
+    WORD  e_ovno;       /* 1a: Overlay number */
+    WORD  e_res[4];     /* 1c: Reserved words */
+    WORD  e_oemid;      /* 24: OEM identifier (for e_oeminfo) */
+    WORD  e_oeminfo;    /* 26: OEM information; e_oemid specific */
+    WORD  e_res2[10];   /* 28: Reserved words */
+    DWORD e_lfanew;     /* 3c: Offset to extended header */
+} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
+
+#define IMAGE_DOS_SIGNATURE    0x5A4D     /* MZ   */
+#define IMAGE_OS2_SIGNATURE    0x454E     /* NE   */
+#define IMAGE_OS2_SIGNATURE_LE 0x454C     /* LE   */
+#define IMAGE_OS2_SIGNATURE_LX 0x584C     /* LX */
+#define IMAGE_VXD_SIGNATURE    0x454C     /* LE   */
+#define IMAGE_NT_SIGNATURE     0x00004550 /* PE00 */
+
+/*
+ * This is the Windows executable (NE) header.
+ * the name IMAGE_OS2_HEADER is misleading, but in the SDK this way.
+ */
+typedef struct
+{
+    WORD  ne_magic;             /* 00 NE signature 'NE' */
+    BYTE  ne_ver;               /* 02 Linker version number */
+    BYTE  ne_rev;               /* 03 Linker revision number */
+    WORD  ne_enttab;            /* 04 Offset to entry table relative to NE */
+    WORD  ne_cbenttab;          /* 06 Length of entry table in bytes */
+    LONG  ne_crc;               /* 08 Checksum */
+    WORD  ne_flags;             /* 0c Flags about segments in this file */
+    WORD  ne_autodata;          /* 0e Automatic data segment number */
+    WORD  ne_heap;              /* 10 Initial size of local heap */
+    WORD  ne_stack;             /* 12 Initial size of stack */
+    DWORD ne_csip;              /* 14 Initial CS:IP */
+    DWORD ne_sssp;              /* 18 Initial SS:SP */
+    WORD  ne_cseg;              /* 1c # of entries in segment table */
+    WORD  ne_cmod;              /* 1e # of entries in module reference tab. */
+    WORD  ne_cbnrestab;         /* 20 Length of nonresident-name table */
+    WORD  ne_segtab;            /* 22 Offset to segment table */
+    WORD  ne_rsrctab;           /* 24 Offset to resource table */
+    WORD  ne_restab;            /* 26 Offset to resident-name table */
+    WORD  ne_modtab;            /* 28 Offset to module reference table */
+    WORD  ne_imptab;            /* 2a Offset to imported name table */
+    DWORD ne_nrestab;           /* 2c Offset to nonresident-name table */
+    WORD  ne_cmovent;           /* 30 # of movable entry points */
+    WORD  ne_align;             /* 32 Logical sector alignment shift count */
+    WORD  ne_cres;              /* 34 # of resource segments */
+    BYTE  ne_exetyp;            /* 36 Flags indicating target OS */
+    BYTE  ne_flagsothers;       /* 37 Additional information flags */
+    WORD  ne_pretthunks;        /* 38 Offset to return thunks */
+    WORD  ne_psegrefbytes;      /* 3a Offset to segment ref. bytes */
+    WORD  ne_swaparea;          /* 3c Reserved by Microsoft */
+    WORD  ne_expver;            /* 3e Expected Windows version number */
+} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER;
+
+typedef struct _IMAGE_VXD_HEADER {
+  WORD  e32_magic;
+  BYTE  e32_border;
+  BYTE  e32_worder;
+  DWORD e32_level;
+  WORD  e32_cpu;
+  WORD  e32_os;
+  DWORD e32_ver;
+  DWORD e32_mflags;
+  DWORD e32_mpages;
+  DWORD e32_startobj;
+  DWORD e32_eip;
+  DWORD e32_stackobj;
+  DWORD e32_esp;
+  DWORD e32_pagesize;
+  DWORD e32_lastpagesize;
+  DWORD e32_fixupsize;
+  DWORD e32_fixupsum;
+  DWORD e32_ldrsize;
+  DWORD e32_ldrsum;
+  DWORD e32_objtab;
+  DWORD e32_objcnt;
+  DWORD e32_objmap;
+  DWORD e32_itermap;
+  DWORD e32_rsrctab;
+  DWORD e32_rsrccnt;
+  DWORD e32_restab;
+  DWORD e32_enttab;
+  DWORD e32_dirtab;
+  DWORD e32_dircnt;
+  DWORD e32_fpagetab;
+  DWORD e32_frectab;
+  DWORD e32_impmod;
+  DWORD e32_impmodcnt;
+  DWORD e32_impproc;
+  DWORD e32_pagesum;
+  DWORD e32_datapage;
+  DWORD e32_preload;
+  DWORD e32_nrestab;
+  DWORD e32_cbnrestab;
+  DWORD e32_nressum;
+  DWORD e32_autodata;
+  DWORD e32_debuginfo;
+  DWORD e32_debuglen;
+  DWORD e32_instpreload;
+  DWORD e32_instdemand;
+  DWORD e32_heapsize;
+  BYTE  e32_res3[12];
+  DWORD e32_winresoff;
+  DWORD e32_winreslen;
+  WORD  e32_devid;
+  WORD  e32_ddkver;
+} IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER;
+
+/* These defines describe the meanings of the bits in the
+   Characteristics field */
+
+#define IMAGE_FILE_RELOCS_STRIPPED	0x0001 /* No relocation info */
+#define IMAGE_FILE_EXECUTABLE_IMAGE	0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED   0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008
+#define IMAGE_FILE_AGGRESIVE_WS_TRIM	0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE	0x0020
+#define IMAGE_FILE_16BIT_MACHINE	0x0040
+#define IMAGE_FILE_BYTES_REVERSED_LO	0x0080
+#define IMAGE_FILE_32BIT_MACHINE	0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED	0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	0x0400
+#define IMAGE_FILE_NET_RUN_FROM_SWAP	0x0800
+#define IMAGE_FILE_SYSTEM		0x1000
+#define IMAGE_FILE_DLL			0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY	0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI	0x8000
+
+/* These are the settings of the Machine field. */
+#define	IMAGE_FILE_MACHINE_UNKNOWN	0
+#define	IMAGE_FILE_MACHINE_I860		0x014d
+#define	IMAGE_FILE_MACHINE_I386		0x014c
+#define	IMAGE_FILE_MACHINE_R3000	0x0162
+#define	IMAGE_FILE_MACHINE_R4000	0x0166
+#define	IMAGE_FILE_MACHINE_R10000	0x0168
+#define	IMAGE_FILE_MACHINE_WCEMIPSV2	0x0169
+#define	IMAGE_FILE_MACHINE_ALPHA	0x0184
+#define	IMAGE_FILE_MACHINE_SH3		0x01a2
+#define	IMAGE_FILE_MACHINE_SH3DSP	0x01a3
+#define	IMAGE_FILE_MACHINE_SH3E		0x01a4
+#define	IMAGE_FILE_MACHINE_SH4		0x01a6
+#define	IMAGE_FILE_MACHINE_SH5		0x01a8
+#define	IMAGE_FILE_MACHINE_ARM		0x01c0
+#define	IMAGE_FILE_MACHINE_THUMB	0x01c2
+#define	IMAGE_FILE_MACHINE_AM33		0x01d3
+#define	IMAGE_FILE_MACHINE_POWERPC	0x01f0
+#define	IMAGE_FILE_MACHINE_POWERPCFP	0x01f1
+#define	IMAGE_FILE_MACHINE_IA64		0x0200
+#define	IMAGE_FILE_MACHINE_MIPS16	0x0266
+#define	IMAGE_FILE_MACHINE_ALPHA64	0x0284
+#define	IMAGE_FILE_MACHINE_MIPSFPU	0x0366
+#define	IMAGE_FILE_MACHINE_MIPSFPU16	0x0466
+#define	IMAGE_FILE_MACHINE_AXP64	IMAGE_FILE_MACHINE_ALPHA64
+#define	IMAGE_FILE_MACHINE_TRICORE	0x0520
+#define	IMAGE_FILE_MACHINE_CEF		0x0cef
+#define	IMAGE_FILE_MACHINE_EBC		0x0ebc
+#define	IMAGE_FILE_MACHINE_AMD64	0x8664
+#define	IMAGE_FILE_MACHINE_M32R		0x9041
+#define	IMAGE_FILE_MACHINE_CEE		0xc0ee
+
+#define	IMAGE_SIZEOF_FILE_HEADER		20
+#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER	56
+#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER	28
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 	224
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 	240
+#define IMAGE_SIZEOF_SHORT_NAME 		8
+#define IMAGE_SIZEOF_SECTION_HEADER 		40
+#define IMAGE_SIZEOF_SYMBOL 			18
+#define IMAGE_SIZEOF_AUX_SYMBOL 		18
+#define IMAGE_SIZEOF_RELOCATION 		10
+#define IMAGE_SIZEOF_BASE_RELOCATION 		8
+#define IMAGE_SIZEOF_LINENUMBER 		6
+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 	60
+
+/* Possible Magic values */
+#define IMAGE_NT_OPTIONAL_HDR32_MAGIC        0x010b
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC        0x020b
+#define IMAGE_ROM_OPTIONAL_HDR_MAGIC       0x0107
+
+#ifdef CONFIG_X86_64
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER64
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC
+#else
+#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER32
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC
+#endif
+
+/* These are indexes into the DataDirectory array */
+#define IMAGE_FILE_EXPORT_DIRECTORY		0
+#define IMAGE_FILE_IMPORT_DIRECTORY		1
+#define IMAGE_FILE_RESOURCE_DIRECTORY		2
+#define IMAGE_FILE_EXCEPTION_DIRECTORY		3
+#define IMAGE_FILE_SECURITY_DIRECTORY		4
+#define IMAGE_FILE_BASE_RELOCATION_TABLE	5
+#define IMAGE_FILE_DEBUG_DIRECTORY		6
+#define IMAGE_FILE_DESCRIPTION_STRING		7
+#define IMAGE_FILE_MACHINE_VALUE		8  /* Mips */
+#define IMAGE_FILE_THREAD_LOCAL_STORAGE		9
+#define IMAGE_FILE_CALLBACK_DIRECTORY		10
+
+/* Directory Entries, indices into the DataDirectory array */
+
+#define	IMAGE_DIRECTORY_ENTRY_EXPORT		0
+#define	IMAGE_DIRECTORY_ENTRY_IMPORT		1
+#define	IMAGE_DIRECTORY_ENTRY_RESOURCE		2
+#define	IMAGE_DIRECTORY_ENTRY_EXCEPTION		3
+#define	IMAGE_DIRECTORY_ENTRY_SECURITY		4
+#define	IMAGE_DIRECTORY_ENTRY_BASERELOC		5
+#define	IMAGE_DIRECTORY_ENTRY_DEBUG		6
+#define	IMAGE_DIRECTORY_ENTRY_COPYRIGHT		7
+#define	IMAGE_DIRECTORY_ENTRY_GLOBALPTR		8  /* (MIPS GP) */
+#define	IMAGE_DIRECTORY_ENTRY_TLS		9
+#define	IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG	10
+#define	IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT	11
+#define	IMAGE_DIRECTORY_ENTRY_IAT		12  /* Import Address Table */
+#define	IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT	13
+#define	IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR	14
+
+/* Subsystem Values */
+
+#define	IMAGE_SUBSYSTEM_UNKNOWN			0
+#define	IMAGE_SUBSYSTEM_NATIVE			1
+#define	IMAGE_SUBSYSTEM_WINDOWS_GUI		2  /* Windows GUI subsystem */
+#define	IMAGE_SUBSYSTEM_WINDOWS_CUI		3  /* Windows character subsystem */
+#define	IMAGE_SUBSYSTEM_OS2_CUI			5
+#define	IMAGE_SUBSYSTEM_POSIX_CUI		7
+#define	IMAGE_SUBSYSTEM_NATIVE_WINDOWS		8  /* native Win9x driver */
+#define	IMAGE_SUBSYSTEM_WINDOWS_CE_GUI		9  /* Windows CE subsystem */
+#define	IMAGE_SUBSYSTEM_EFI_APPLICATION		10
+#define	IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER	11
+#define	IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER	12
+#define	IMAGE_SUBSYSTEM_EFI_ROM			13
+#define	IMAGE_SUBSYSTEM_XBOX			14
+
+typedef struct _IMAGE_FILE_HEADER {
+  WORD  Machine;
+  WORD  NumberOfSections;
+  DWORD TimeDateStamp;
+  DWORD PointerToSymbolTable;
+  DWORD NumberOfSymbols;
+  WORD  SizeOfOptionalHeader;
+  WORD  Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+  DWORD VirtualAddress;
+  DWORD Size;
+} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+typedef struct _IMAGE_OPTIONAL_HEADER32 {
+
+  /* Standard fields */
+
+  WORD  Magic;
+  BYTE  MajorLinkerVersion;
+  BYTE  MinorLinkerVersion;
+  DWORD SizeOfCode;
+  DWORD SizeOfInitializedData;
+  DWORD SizeOfUninitializedData;
+  DWORD AddressOfEntryPoint;
+  DWORD BaseOfCode;
+  DWORD BaseOfData;
+
+  /* NT additional fields */
+  DWORD ImageBase;
+  DWORD SectionAlignment;
+  DWORD FileAlignment;
+  WORD  MajorOperatingSystemVersion;
+  WORD  MinorOperatingSystemVersion;
+  WORD  MajorImageVersion;
+  WORD  MinorImageVersion;
+  WORD  MajorSubsystemVersion;
+  WORD  MinorSubsystemVersion;
+  DWORD Win32VersionValue;
+  DWORD SizeOfImage;
+  DWORD SizeOfHeaders;
+  DWORD CheckSum;
+  WORD  Subsystem;
+  WORD  DllCharacteristics;
+  DWORD SizeOfStackReserve;
+  DWORD SizeOfStackCommit;
+  DWORD SizeOfHeapReserve;
+  DWORD SizeOfHeapCommit;
+  DWORD LoaderFlags;
+  DWORD NumberOfRvaAndSizes;
+  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
+
+typedef struct _IMAGE_OPTIONAL_HEADER64 {
+
+  /* Standard fields */
+
+  WORD  Magic;
+  BYTE  MajorLinkerVersion;
+  BYTE  MinorLinkerVersion;
+  DWORD SizeOfCode;
+  DWORD SizeOfInitializedData;
+  DWORD SizeOfUninitializedData;
+  DWORD AddressOfEntryPoint;
+  DWORD BaseOfCode;
+
+  /* NT additional fields */
+  ULONGLONG ImageBase;
+  DWORD SectionAlignment;
+  DWORD FileAlignment;
+  WORD  MajorOperatingSystemVersion;
+  WORD  MinorOperatingSystemVersion;
+  WORD  MajorImageVersion;
+  WORD  MinorImageVersion;
+  WORD  MajorSubsystemVersion;
+  WORD  MinorSubsystemVersion;
+  DWORD Win32VersionValue;
+  DWORD SizeOfImage;
+  DWORD SizeOfHeaders;
+  DWORD CheckSum;
+  WORD  Subsystem;
+  WORD  DllCharacteristics;
+  ULONGLONG SizeOfStackReserve;
+  ULONGLONG SizeOfStackCommit;
+  ULONGLONG SizeOfHeapReserve;
+  ULONGLONG SizeOfHeapCommit;
+  DWORD LoaderFlags;
+  DWORD NumberOfRvaAndSizes;
+  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
+
+#ifdef CONFIG_X86_64
+typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
+typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
+#else
+typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
+typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
+#endif
+
+typedef struct _IMAGE_NT_HEADERS32 {
+  DWORD Signature; /* "PE"\0\0 */	/* 0x00 */
+  IMAGE_FILE_HEADER FileHeader;		/* 0x04 */
+  IMAGE_OPTIONAL_HEADER32 OptionalHeader;	/* 0x18 */
+} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
+
+typedef struct _IMAGE_NT_HEADERS64 {
+  DWORD Signature; /* "PE"\0\0 */	/* 0x00 */
+  IMAGE_FILE_HEADER FileHeader;		/* 0x04 */
+  IMAGE_OPTIONAL_HEADER64 OptionalHeader;	/* 0x18 */
+} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
+
+#ifdef CONFIG_X86_64
+typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
+typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
+#else
+typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
+typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
+#endif
+
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct _IMAGE_SECTION_HEADER {
+  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
+  union {
+    DWORD PhysicalAddress;
+    DWORD VirtualSize;
+  } Misc;
+  DWORD VirtualAddress;
+  DWORD SizeOfRawData;
+  DWORD PointerToRawData;
+  DWORD PointerToRelocations;
+  DWORD PointerToLinenumbers;
+  WORD  NumberOfRelocations;
+  WORD  NumberOfLinenumbers;
+  DWORD Characteristics;
+} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
+
+#define	IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define IMAGE_FIRST_SECTION(ntheader) \
+((PIMAGE_SECTION_HEADER)((LPBYTE)&((PIMAGE_NT_HEADERS)(ntheader))->OptionalHeader + \
+((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader))
+
+/* These defines are for the Characteristics bitfield. */
+/* #define IMAGE_SCN_TYPE_REG			0x00000000 - Reserved */
+/* #define IMAGE_SCN_TYPE_DSECT			0x00000001 - Reserved */
+/* #define IMAGE_SCN_TYPE_NOLOAD		0x00000002 - Reserved */
+/* #define IMAGE_SCN_TYPE_GROUP			0x00000004 - Reserved */
+#define IMAGE_SCN_TYPE_NO_PAD			0x00000008 /* Reserved */
+/* #define IMAGE_SCN_TYPE_COPY			0x00000010 - Reserved */
+
+#define IMAGE_SCN_CNT_CODE			0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA		0x00000040
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA	0x00000080
+
+#define	IMAGE_SCN_LNK_OTHER			0x00000100
+#define	IMAGE_SCN_LNK_INFO			0x00000200
+/* #define IMAGE_SCN_TYPE_OVER		0x00000400 - Reserved */
+#define	IMAGE_SCN_LNK_REMOVE			0x00000800
+#define	IMAGE_SCN_LNK_COMDAT			0x00001000
+
+/* 						0x00002000 - Reserved */
+/* #define IMAGE_SCN_MEM_PROTECTED 		0x00004000 - Obsolete */
+#define	IMAGE_SCN_MEM_FARDATA			0x00008000
+
+/* #define IMAGE_SCN_MEM_SYSHEAP		0x00010000 - Obsolete */
+#define	IMAGE_SCN_MEM_PURGEABLE			0x00020000
+#define	IMAGE_SCN_MEM_16BIT			0x00020000
+#define	IMAGE_SCN_MEM_LOCKED			0x00040000
+#define	IMAGE_SCN_MEM_PRELOAD			0x00080000
+
+#define	IMAGE_SCN_ALIGN_1BYTES			0x00100000
+#define	IMAGE_SCN_ALIGN_2BYTES			0x00200000
+#define	IMAGE_SCN_ALIGN_4BYTES			0x00300000
+#define	IMAGE_SCN_ALIGN_8BYTES			0x00400000
+#define	IMAGE_SCN_ALIGN_16BYTES			0x00500000  /* Default */
+#define	IMAGE_SCN_ALIGN_32BYTES			0x00600000
+#define	IMAGE_SCN_ALIGN_64BYTES			0x00700000
+#define	IMAGE_SCN_ALIGN_128BYTES		0x00800000
+#define	IMAGE_SCN_ALIGN_256BYTES		0x00900000
+#define	IMAGE_SCN_ALIGN_512BYTES		0x00A00000
+#define	IMAGE_SCN_ALIGN_1024BYTES		0x00B00000
+#define	IMAGE_SCN_ALIGN_2048BYTES		0x00C00000
+#define	IMAGE_SCN_ALIGN_4096BYTES		0x00D00000
+#define	IMAGE_SCN_ALIGN_8192BYTES		0x00E00000
+/* 						0x00F00000 - Unused */
+#define	IMAGE_SCN_ALIGN_MASK			0x00F00000
+
+#define IMAGE_SCN_LNK_NRELOC_OVFL		0x01000000
+
+
+#define IMAGE_SCN_MEM_DISCARDABLE		0x02000000
+#define IMAGE_SCN_MEM_NOT_CACHED		0x04000000
+#define IMAGE_SCN_MEM_NOT_PAGED			0x08000000
+#define IMAGE_SCN_MEM_SHARED			0x10000000
+#define IMAGE_SCN_MEM_EXECUTE			0x20000000
+#define IMAGE_SCN_MEM_READ			0x40000000
+#define IMAGE_SCN_MEM_WRITE			0x80000000
+
+typedef struct _IMAGE_SYMBOL {
+    union {
+        BYTE    ShortName[8];
+        struct {
+            DWORD   Short;
+            DWORD   Long;
+        } Name;
+        DWORD   LongName[2];
+    } N;
+    DWORD   Value;
+    SHORT   SectionNumber;
+    WORD    Type;
+    BYTE    StorageClass;
+    BYTE    NumberOfAuxSymbols;
+} IMAGE_SYMBOL;
+typedef IMAGE_SYMBOL *PIMAGE_SYMBOL;
+
+#define IMAGE_SIZEOF_SYMBOL 18
+
+typedef struct _IMAGE_LINENUMBER {
+    union {
+        DWORD   SymbolTableIndex;
+        DWORD   VirtualAddress;
+    } Type;
+    WORD    Linenumber;
+} IMAGE_LINENUMBER;
+typedef IMAGE_LINENUMBER *PIMAGE_LINENUMBER;
+
+#define IMAGE_SIZEOF_LINENUMBER  6
+
+typedef union _IMAGE_AUX_SYMBOL {
+    struct {
+        DWORD    TagIndex;
+        union {
+            struct {
+                WORD    Linenumber;
+                WORD    Size;
+            } LnSz;
+           DWORD    TotalSize;
+        } Misc;
+        union {
+            struct {
+                DWORD    PointerToLinenumber;
+                DWORD    PointerToNextFunction;
+            } Function;
+            struct {
+                WORD     Dimension[4];
+            } Array;
+        } FcnAry;
+        WORD    TvIndex;
+    } Sym;
+    struct {
+        BYTE    Name[IMAGE_SIZEOF_SYMBOL];
+    } File;
+    struct {
+        DWORD   Length;
+        WORD    NumberOfRelocations;
+        WORD    NumberOfLinenumbers;
+        DWORD   CheckSum;
+        SHORT   Number;
+        BYTE    Selection;
+    } Section;
+} IMAGE_AUX_SYMBOL;
+typedef IMAGE_AUX_SYMBOL *PIMAGE_AUX_SYMBOL;
+
+#define IMAGE_SIZEOF_AUX_SYMBOL 18
+
+#define IMAGE_SYM_UNDEFINED           (SHORT)0
+#define IMAGE_SYM_ABSOLUTE            (SHORT)-1
+#define IMAGE_SYM_DEBUG               (SHORT)-2
+
+#define IMAGE_SYM_TYPE_NULL                 0x0000
+#define IMAGE_SYM_TYPE_VOID                 0x0001
+#define IMAGE_SYM_TYPE_CHAR                 0x0002
+#define IMAGE_SYM_TYPE_SHORT                0x0003
+#define IMAGE_SYM_TYPE_INT                  0x0004
+#define IMAGE_SYM_TYPE_LONG                 0x0005
+#define IMAGE_SYM_TYPE_FLOAT                0x0006
+#define IMAGE_SYM_TYPE_DOUBLE               0x0007
+#define IMAGE_SYM_TYPE_STRUCT               0x0008
+#define IMAGE_SYM_TYPE_UNION                0x0009
+#define IMAGE_SYM_TYPE_ENUM                 0x000A
+#define IMAGE_SYM_TYPE_MOE                  0x000B
+#define IMAGE_SYM_TYPE_BYTE                 0x000C
+#define IMAGE_SYM_TYPE_WORD                 0x000D
+#define IMAGE_SYM_TYPE_UINT                 0x000E
+#define IMAGE_SYM_TYPE_DWORD                0x000F
+#define IMAGE_SYM_TYPE_PCODE                0x8000
+
+#define IMAGE_SYM_DTYPE_NULL                0
+#define IMAGE_SYM_DTYPE_POINTER             1
+#define IMAGE_SYM_DTYPE_FUNCTION            2
+#define IMAGE_SYM_DTYPE_ARRAY               3
+
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION     (BYTE )-1
+#define IMAGE_SYM_CLASS_NULL                0x0000
+#define IMAGE_SYM_CLASS_AUTOMATIC           0x0001
+#define IMAGE_SYM_CLASS_EXTERNAL            0x0002
+#define IMAGE_SYM_CLASS_STATIC              0x0003
+#define IMAGE_SYM_CLASS_REGISTER            0x0004
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF        0x0005
+#define IMAGE_SYM_CLASS_LABEL               0x0006
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL     0x0007
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT    0x0008
+#define IMAGE_SYM_CLASS_ARGUMENT            0x0009
+#define IMAGE_SYM_CLASS_STRUCT_TAG          0x000A
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION     0x000B
+#define IMAGE_SYM_CLASS_UNION_TAG           0x000C
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION     0x000D
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC    0x000E
+#define IMAGE_SYM_CLASS_ENUM_TAG            0x000F
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM      0x0010
+#define IMAGE_SYM_CLASS_REGISTER_PARAM      0x0011
+#define IMAGE_SYM_CLASS_BIT_FIELD           0x0012
+
+#define IMAGE_SYM_CLASS_FAR_EXTERNAL        0x0044
+#define IMAGE_SYM_CLASS_BLOCK               0x0064
+#define IMAGE_SYM_CLASS_FUNCTION            0x0065
+#define IMAGE_SYM_CLASS_END_OF_STRUCT       0x0066
+#define IMAGE_SYM_CLASS_FILE                0x0067
+#define IMAGE_SYM_CLASS_SECTION             0x0068
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL       0x0069
+
+#define N_BTMASK                            0x000F
+#define N_TMASK                             0x0030
+#define N_TMASK1                            0x00C0
+#define N_TMASK2                            0x00F0
+#define N_BTSHFT                            4
+#define N_TSHIFT                            2
+
+#define BTYPE(x) ((x) & N_BTMASK)
+
+#ifndef ISPTR
+#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT))
+#endif
+
+#ifndef ISFCN
+#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))
+#endif
+
+#ifndef ISARY
+#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT))
+#endif
+
+#ifndef ISTAG
+#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || (x)==IMAGE_SYM_CLASS_UNION_TAG || (x)==IMAGE_SYM_CLASS_ENUM_TAG)
+#endif
+
+#ifndef INCREF
+#define INCREF(x) ((((x)&~N_BTMASK)<<N_TSHIFT)|(IMAGE_SYM_DTYPE_POINTER<<N_BTSHFT)|((x)&N_BTMASK))
+#endif
+#ifndef DECREF
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+#endif
+
+#define IMAGE_COMDAT_SELECT_NODUPLICATES    1
+#define IMAGE_COMDAT_SELECT_ANY             2
+#define IMAGE_COMDAT_SELECT_SAME_SIZE       3
+#define IMAGE_COMDAT_SELECT_EXACT_MATCH     4
+#define IMAGE_COMDAT_SELECT_ASSOCIATIVE     5
+#define IMAGE_COMDAT_SELECT_LARGEST         6
+#define IMAGE_COMDAT_SELECT_NEWEST          7
+
+#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY  1
+#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY    2
+#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS      3
+
+/* Export module directory */
+
+typedef struct _IMAGE_EXPORT_DIRECTORY {
+	DWORD	Characteristics;
+	DWORD	TimeDateStamp;
+	WORD	MajorVersion;
+	WORD	MinorVersion;
+	DWORD	Name;
+	DWORD	Base;
+	DWORD	NumberOfFunctions;
+	DWORD	NumberOfNames;
+	DWORD	AddressOfFunctions;
+	DWORD	AddressOfNames;
+	DWORD	AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
+
+/* Import name entry */
+typedef struct _IMAGE_IMPORT_BY_NAME {
+	WORD	Hint;
+	BYTE	Name[1];
+} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;
+
+/* Import thunk */
+typedef struct _IMAGE_THUNK_DATA32 {
+	union {
+		DWORD    ForwarderString;
+		DWORD    Function;
+		DWORD    Ordinal;
+		DWORD	AddressOfData;
+	} u1;
+} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
+
+typedef struct _IMAGE_THUNK_DATA64 {
+	union {
+		ULONGLONG    ForwarderString;
+		ULONGLONG    Function;
+		ULONGLONG    Ordinal;
+		ULONGLONG    AddressOfData;
+	} u1;
+} IMAGE_THUNK_DATA64,*PIMAGE_THUNK_DATA64;
+
+#ifdef CONFIG_X86_64
+typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA;
+typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA;
+#else
+typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA;
+typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA;
+#endif
+
+/* Import module directory */
+
+typedef struct packed _IMAGE_IMPORT_DESCRIPTOR {
+	union {
+		DWORD	Characteristics; /* 0 for terminating null
+					  * import descriptor */
+		DWORD   OriginalFirstThunk; /* RVA to original unbound
+					     * IAT */
+	} u;
+	DWORD	TimeDateStamp;	/* 0 if not bound,
+				 * -1 if bound, and real date\time stamp
+				 *    in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
+				 * (new BIND)
+				 * otherwise date/time stamp of DLL bound to
+				 * (Old BIND)
+				 */
+	DWORD	ForwarderChain;	/* -1 if no forwarders */
+	DWORD	Name;
+	/* RVA to IAT (if bound this IAT has actual addresses) */
+	DWORD   FirstThunk;
+} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
+
+#define	IMAGE_ORDINAL_FLAG32		0x80000000
+#define	IMAGE_ORDINAL_FLAG64		0x8000000000000000UL
+#define	IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0)
+#define	IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0)
+#define	IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+#ifdef CONFIG_X86_64
+#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64
+#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL64
+#else
+#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG32
+#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL32
+#endif
+
+typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR
+{
+    DWORD   TimeDateStamp;
+    WORD    OffsetModuleName;
+    WORD    NumberOfModuleForwarderRefs;
+/* Array of zero or more IMAGE_BOUND_FORWARDER_REF follows */
+} IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;
+
+typedef struct _IMAGE_BOUND_FORWARDER_REF
+{
+    DWORD   TimeDateStamp;
+    WORD    OffsetModuleName;
+    WORD    Reserved;
+} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;
+
+typedef struct _IMAGE_BASE_RELOCATION
+{
+	DWORD	VirtualAddress;
+	DWORD	SizeOfBlock;
+	WORD	TypeOffset[0];
+} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION;
+
+typedef struct _IMAGE_RELOCATION
+{
+    union {
+        DWORD   VirtualAddress;
+        DWORD   RelocCount;
+    } DUMMYUNIONNAME;
+    DWORD   SymbolTableIndex;
+    WORD    Type;
+} IMAGE_RELOCATION, *PIMAGE_RELOCATION;
+
+#define IMAGE_SIZEOF_RELOCATION 10
+
+/* generic relocation types */
+#define IMAGE_REL_BASED_ABSOLUTE 		0
+#define IMAGE_REL_BASED_HIGH			1
+#define IMAGE_REL_BASED_LOW			2
+#define IMAGE_REL_BASED_HIGHLOW			3
+#define IMAGE_REL_BASED_HIGHADJ			4
+#define IMAGE_REL_BASED_MIPS_JMPADDR		5
+#define IMAGE_REL_BASED_SECTION			6
+#define	IMAGE_REL_BASED_REL			7
+#define IMAGE_REL_BASED_MIPS_JMPADDR16		9
+#define IMAGE_REL_BASED_IA64_IMM64		9 /* yes, 9 too */
+#define IMAGE_REL_BASED_DIR64			10
+#define IMAGE_REL_BASED_HIGH3ADJ		11
+
+/* I386 relocation types */
+#define	IMAGE_REL_I386_ABSOLUTE			0
+#define	IMAGE_REL_I386_DIR16			1
+#define	IMAGE_REL_I386_REL16			2
+#define	IMAGE_REL_I386_DIR32			6
+#define	IMAGE_REL_I386_DIR32NB			7
+#define	IMAGE_REL_I386_SEG12			9
+#define	IMAGE_REL_I386_SECTION			10
+#define	IMAGE_REL_I386_SECREL			11
+#define	IMAGE_REL_I386_REL32			20
+
+/* MIPS relocation types */
+#define IMAGE_REL_MIPS_ABSOLUTE		0x0000
+#define IMAGE_REL_MIPS_REFHALF		0x0001
+#define IMAGE_REL_MIPS_REFWORD		0x0002
+#define IMAGE_REL_MIPS_JMPADDR		0x0003
+#define IMAGE_REL_MIPS_REFHI		0x0004
+#define IMAGE_REL_MIPS_REFLO		0x0005
+#define IMAGE_REL_MIPS_GPREL		0x0006
+#define IMAGE_REL_MIPS_LITERAL		0x0007
+#define IMAGE_REL_MIPS_SECTION		0x000A
+#define IMAGE_REL_MIPS_SECREL		0x000B
+#define IMAGE_REL_MIPS_SECRELLO		0x000C
+#define IMAGE_REL_MIPS_SECRELHI		0x000D
+#define	IMAGE_REL_MIPS_JMPADDR16	0x0010
+#define IMAGE_REL_MIPS_REFWORDNB	0x0022
+#define IMAGE_REL_MIPS_PAIR		0x0025
+
+/* ALPHA relocation types */
+#define IMAGE_REL_ALPHA_ABSOLUTE	0x0000
+#define IMAGE_REL_ALPHA_REFLONG		0x0001
+#define IMAGE_REL_ALPHA_REFQUAD		0x0002
+#define IMAGE_REL_ALPHA_GPREL		0x0003
+#define IMAGE_REL_ALPHA_LITERAL		0x0004
+#define IMAGE_REL_ALPHA_LITUSE		0x0005
+#define IMAGE_REL_ALPHA_GPDISP		0x0006
+#define IMAGE_REL_ALPHA_BRADDR		0x0007
+#define IMAGE_REL_ALPHA_HINT		0x0008
+#define IMAGE_REL_ALPHA_INLINE_REFLONG	0x0009
+#define IMAGE_REL_ALPHA_REFHI		0x000A
+#define IMAGE_REL_ALPHA_REFLO		0x000B
+#define IMAGE_REL_ALPHA_PAIR		0x000C
+#define IMAGE_REL_ALPHA_MATCH		0x000D
+#define IMAGE_REL_ALPHA_SECTION		0x000E
+#define IMAGE_REL_ALPHA_SECREL		0x000F
+#define IMAGE_REL_ALPHA_REFLONGNB	0x0010
+#define IMAGE_REL_ALPHA_SECRELLO	0x0011
+#define IMAGE_REL_ALPHA_SECRELHI	0x0012
+#define IMAGE_REL_ALPHA_REFQ3		0x0013
+#define IMAGE_REL_ALPHA_REFQ2		0x0014
+#define IMAGE_REL_ALPHA_REFQ1		0x0015
+#define IMAGE_REL_ALPHA_GPRELLO		0x0016
+#define IMAGE_REL_ALPHA_GPRELHI		0x0017
+
+/* PowerPC relocation types */
+#define IMAGE_REL_PPC_ABSOLUTE          0x0000
+#define IMAGE_REL_PPC_ADDR64            0x0001
+#define IMAGE_REL_PPC_ADDR            0x0002
+#define IMAGE_REL_PPC_ADDR24            0x0003
+#define IMAGE_REL_PPC_ADDR16            0x0004
+#define IMAGE_REL_PPC_ADDR14            0x0005
+#define IMAGE_REL_PPC_REL24             0x0006
+#define IMAGE_REL_PPC_REL14             0x0007
+#define IMAGE_REL_PPC_TOCREL16          0x0008
+#define IMAGE_REL_PPC_TOCREL14          0x0009
+#define IMAGE_REL_PPC_ADDR32NB          0x000A
+#define IMAGE_REL_PPC_SECREL            0x000B
+#define IMAGE_REL_PPC_SECTION           0x000C
+#define IMAGE_REL_PPC_IFGLUE            0x000D
+#define IMAGE_REL_PPC_IMGLUE            0x000E
+#define IMAGE_REL_PPC_SECREL16          0x000F
+#define IMAGE_REL_PPC_REFHI             0x0010
+#define IMAGE_REL_PPC_REFLO             0x0011
+#define IMAGE_REL_PPC_PAIR              0x0012
+#define IMAGE_REL_PPC_SECRELLO          0x0013
+#define IMAGE_REL_PPC_SECRELHI          0x0014
+#define IMAGE_REL_PPC_GPREL		0x0015
+#define IMAGE_REL_PPC_TYPEMASK          0x00FF
+/* modifier bits */
+#define IMAGE_REL_PPC_NEG               0x0100
+#define IMAGE_REL_PPC_BRTAKEN           0x0200
+#define IMAGE_REL_PPC_BRNTAKEN          0x0400
+#define IMAGE_REL_PPC_TOCDEFN           0x0800
+
+/* SH3 ? relocation type */
+#define IMAGE_REL_SH3_ABSOLUTE          0x0000
+#define IMAGE_REL_SH3_DIRECT16          0x0001
+#define IMAGE_REL_SH3_DIRECT          0x0002
+#define IMAGE_REL_SH3_DIRECT8           0x0003
+#define IMAGE_REL_SH3_DIRECT8_WORD      0x0004
+#define IMAGE_REL_SH3_DIRECT8_LONG      0x0005
+#define IMAGE_REL_SH3_DIRECT4           0x0006
+#define IMAGE_REL_SH3_DIRECT4_WORD      0x0007
+#define IMAGE_REL_SH3_DIRECT4_LONG      0x0008
+#define IMAGE_REL_SH3_PCREL8_WORD       0x0009
+#define IMAGE_REL_SH3_PCREL8_LONG       0x000A
+#define IMAGE_REL_SH3_PCREL12_WORD      0x000B
+#define IMAGE_REL_SH3_STARTOF_SECTION   0x000C
+#define IMAGE_REL_SH3_SIZEOF_SECTION    0x000D
+#define IMAGE_REL_SH3_SECTION           0x000E
+#define IMAGE_REL_SH3_SECREL            0x000F
+#define IMAGE_REL_SH3_DIRECT32_NB       0x0010
+
+/* ARM (Archimedes?) relocation types */
+#define IMAGE_REL_ARM_ABSOLUTE		0x0000
+#define IMAGE_REL_ARM_ADDR		0x0001
+#define IMAGE_REL_ARM_ADDR32NB		0x0002
+#define IMAGE_REL_ARM_BRANCH24		0x0003
+#define IMAGE_REL_ARM_BRANCH11		0x0004
+#define IMAGE_REL_ARM_SECTION		0x000E
+#define IMAGE_REL_ARM_SECREL		0x000F
+
+/* IA64 relocation types */
+#define IMAGE_REL_IA64_ABSOLUTE		0x0000
+#define IMAGE_REL_IA64_IMM14		0x0001
+#define IMAGE_REL_IA64_IMM22		0x0002
+#define IMAGE_REL_IA64_IMM64		0x0003
+#define IMAGE_REL_IA64_DIR		0x0004
+#define IMAGE_REL_IA64_DIR64		0x0005
+#define IMAGE_REL_IA64_PCREL21B		0x0006
+#define IMAGE_REL_IA64_PCREL21M		0x0007
+#define IMAGE_REL_IA64_PCREL21F		0x0008
+#define IMAGE_REL_IA64_GPREL22		0x0009
+#define IMAGE_REL_IA64_LTOFF22		0x000A
+#define IMAGE_REL_IA64_SECTION		0x000B
+#define IMAGE_REL_IA64_SECREL22		0x000C
+#define IMAGE_REL_IA64_SECREL64I	0x000D
+#define IMAGE_REL_IA64_SECREL		0x000E
+#define IMAGE_REL_IA64_LTOFF64		0x000F
+#define IMAGE_REL_IA64_DIR32NB		0x0010
+#define IMAGE_REL_IA64_RESERVED_11	0x0011
+#define IMAGE_REL_IA64_RESERVED_12	0x0012
+#define IMAGE_REL_IA64_RESERVED_13	0x0013
+#define IMAGE_REL_IA64_RESERVED_14	0x0014
+#define IMAGE_REL_IA64_RESERVED_15	0x0015
+#define IMAGE_REL_IA64_RESERVED_16	0x0016
+#define IMAGE_REL_IA64_ADDEND		0x001F
+
+/* archive format */
+
+#define IMAGE_ARCHIVE_START_SIZE             8
+#define IMAGE_ARCHIVE_START                  "!<arch>\n"
+#define IMAGE_ARCHIVE_END                    "`\n"
+#define IMAGE_ARCHIVE_PAD                    "\n"
+#define IMAGE_ARCHIVE_LINKER_MEMBER          "/               "
+#define IMAGE_ARCHIVE_LONGNAMES_MEMBER       "//              "
+
+typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER
+{
+    BYTE     Name[16];
+    BYTE     Date[12];
+    BYTE     UserID[6];
+    BYTE     GroupID[6];
+    BYTE     Mode[8];
+    BYTE     Size[10];
+    BYTE     EndHeader[2];
+} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+/*
+ * Resource directory stuff
+ */
+typedef struct _IMAGE_RESOURCE_DIRECTORY {
+	DWORD	Characteristics;
+	DWORD	TimeDateStamp;
+	WORD	MajorVersion;
+	WORD	MinorVersion;
+	WORD	NumberOfNamedEntries;
+	WORD	NumberOfIdEntries;
+	/*  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */
+} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
+
+#define	IMAGE_RESOURCE_NAME_IS_STRING		0x80000000
+#define	IMAGE_RESOURCE_DATA_IS_DIRECTORY	0x80000000
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
+	union {
+		struct {
+#ifdef BITFIELDS_BIGENDIAN
+			unsigned NameIsString:1;
+			unsigned NameOffset:31;
+#else
+			unsigned NameOffset:31;
+			unsigned NameIsString:1;
+#endif
+		} DUMMYSTRUCTNAME1;
+		DWORD   Name;
+                struct {
+#ifdef WORDS_BIGENDIAN
+			WORD    __pad;
+			WORD    Id;
+#else
+			WORD    Id;
+			WORD    __pad;
+#endif
+		} DUMMYSTRUCTNAME2;
+	} DUMMYUNIONNAME1;
+	union {
+		DWORD   OffsetToData;
+		struct {
+#ifdef BITFIELDS_BIGENDIAN
+			unsigned DataIsDirectory:1;
+			unsigned OffsetToDirectory:31;
+#else
+			unsigned OffsetToDirectory:31;
+			unsigned DataIsDirectory:1;
+#endif
+		} DUMMYSTRUCTNAME3;
+	} DUMMYUNIONNAME2;
+} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
+	WORD	Length;
+	CHAR	NameString[ 1 ];
+} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING;
+
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapper.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapper.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef WRAPPER_H
+#define WRAPPER_H
+
+extern char *if_name;
+extern int proc_uid;
+extern int proc_gid;
+extern int hangcheck_interval;
+
+#endif /* WRAPPER_H */
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/loader.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/loader.c
@@ -0,0 +1,877 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ndis.h"
+#include "loader.h"
+#include "wrapndis.h"
+#include "pnp.h"
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+/*
+  Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318}
+  Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318}
+  PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318}
+  USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
+*/
+
+/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */
+static struct guid class_guids[] = {
+	/* Network */
+	{0x4d36e972, 0xe325, 0x11ce, },
+	/* USB WDM */
+	{0x36fc9e60, 0xc465, 0x11cf, },
+	/* Bluetooth */
+	{0xe0cbf06c, 0xcd8b, 0x4647, },
+	/* ivtcorporatino.com's bluetooth device claims this is
+	 * bluetooth guid */
+	{0xf12d3cf8, 0xb11d, 0x457e, },
+};
+
+struct semaphore loader_mutex;
+static struct completion loader_complete;
+
+static struct nt_list wrap_devices;
+static struct nt_list wrap_drivers;
+
+static int wrap_device_type(int data1)
+{
+	int i;
+	for (i = 0; i < sizeof(class_guids) / sizeof(class_guids[0]); i++)
+		if (data1 == class_guids[i].data1)
+			return i;
+	ERROR("unknown device: 0x%x\n", data1);
+	return -1;
+}
+
+/* load driver for given device, if not already loaded */
+struct wrap_driver *load_wrap_driver(struct wrap_device *wd)
+{
+	int ret;
+	struct nt_list *cur;
+	struct wrap_driver *wrap_driver;
+
+	ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,
+	       wd->subvendor, wd->subdevice);
+	if (down_interruptible(&loader_mutex)) {
+		WARNING("couldn't obtain loader_mutex");
+		EXIT1(return NULL);
+	}
+	wrap_driver = NULL;
+	nt_list_for_each(cur, &wrap_drivers) {
+		wrap_driver = container_of(cur, struct wrap_driver, list);
+		if (!stricmp(wrap_driver->name, wd->driver_name)) {
+			TRACE1("driver %s already loaded", wrap_driver->name);
+			break;
+		} else
+			wrap_driver = NULL;
+	}
+	up(&loader_mutex);
+
+	if (!wrap_driver) {
+		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
+#if defined(DEBUG) && DEBUG >= 1
+				"1",
+#else
+				"0",
+#endif
+				UTILS_VERSION, wd->driver_name,
+				wd->conf_file_name, NULL};
+		char *env[] = {NULL};
+
+		TRACE1("loading driver %s", wd->driver_name);
+		if (down_interruptible(&loader_mutex)) {
+			WARNING("couldn't obtain loader_mutex");
+			EXIT1(return NULL);
+		}
+		INIT_COMPLETION(loader_complete);
+		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
+		if (ret) {
+			up(&loader_mutex);
+			ERROR("couldn't load driver %s; check system log "
+			      "for messages from 'loadndisdriver'",
+			      wd->driver_name);
+			EXIT1(return NULL);
+		}
+		wait_for_completion(&loader_complete);
+		TRACE1("%s", wd->driver_name);
+		wrap_driver = NULL;
+		nt_list_for_each(cur, &wrap_drivers) {
+			wrap_driver = container_of(cur, struct wrap_driver,
+						   list);
+			if (!stricmp(wrap_driver->name, wd->driver_name)) {
+				wd->driver = wrap_driver;
+				break;
+			} else
+				wrap_driver = NULL;
+		}
+		up(&loader_mutex);
+		if (wrap_driver)
+			TRACE1("driver %s is loaded", wrap_driver->name);
+		else
+			ERROR("couldn't load driver '%s'", wd->driver_name);
+	}
+	EXIT1(return wrap_driver);
+}
+
+/* load the driver files from userspace. */
+static int load_sys_files(struct wrap_driver *driver,
+			  struct load_driver *load_driver)
+{
+	int i, err;
+
+	TRACE1("num_pe_images = %d", load_driver->num_sys_files);
+	TRACE1("loading driver: %s", load_driver->name);
+	strncpy(driver->name, load_driver->name, sizeof(driver->name));
+	driver->name[sizeof(driver->name)-1] = 0;
+	TRACE1("driver: %s", driver->name);
+	err = 0;
+	driver->num_pe_images = 0;
+	for (i = 0; i < load_driver->num_sys_files; i++) {
+		struct pe_image *pe_image;
+		pe_image = &driver->pe_images[driver->num_pe_images];
+
+		strncpy(pe_image->name, load_driver->sys_files[i].name,
+			sizeof(pe_image->name));
+		pe_image->name[sizeof(pe_image->name)-1] = 0;
+		TRACE1("image size: %lu bytes",
+		       (unsigned long)load_driver->sys_files[i].size);
+
+#ifdef CONFIG_X86_64
+#ifdef PAGE_KERNEL_EXECUTABLE
+		pe_image->image =
+			__vmalloc(load_driver->sys_files[i].size,
+				  GFP_KERNEL | __GFP_HIGHMEM,
+				  PAGE_KERNEL_EXECUTABLE);
+#elif defined PAGE_KERNEL_EXEC
+		pe_image->image =
+			__vmalloc(load_driver->sys_files[i].size,
+				  GFP_KERNEL | __GFP_HIGHMEM,
+				  PAGE_KERNEL_EXEC);
+#else
+#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
+#endif
+#else
+		/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
+		 * not available to modules! */
+#ifdef cpu_has_nx
+		if (cpu_has_nx)
+			pe_image->image =
+				__vmalloc(load_driver->sys_files[i].size,
+					  GFP_KERNEL | __GFP_HIGHMEM,
+					  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
+		else
+			pe_image->image =
+				vmalloc(load_driver->sys_files[i].size);
+#else
+			pe_image->image =
+				vmalloc(load_driver->sys_files[i].size);
+#endif
+#endif
+		if (!pe_image->image) {
+			ERROR("couldn't allocate memory");
+			err = -ENOMEM;
+			break;
+		}
+		TRACE1("image is at %p", pe_image->image);
+
+		if (copy_from_user(pe_image->image,
+				   load_driver->sys_files[i].data,
+				   load_driver->sys_files[i].size)) {
+			ERROR("couldn't load file %s",
+			      load_driver->sys_files[i].name);
+			err = -EFAULT;
+			break;
+		}
+		pe_image->size = load_driver->sys_files[i].size;
+		driver->num_pe_images++;
+	}
+
+	if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
+		ERROR("couldn't prepare driver '%s'", load_driver->name);
+		err = -EINVAL;
+	}
+
+	if (driver->num_pe_images < load_driver->num_sys_files || err) {
+		for (i = 0; i < driver->num_pe_images; i++)
+			if (driver->pe_images[i].image)
+				vfree(driver->pe_images[i].image);
+		driver->num_pe_images = 0;
+		EXIT1(return err);
+	} else
+		EXIT1(return 0);
+}
+
+struct wrap_bin_file *get_bin_file(char *bin_file_name)
+{
+	int i = 0;
+	struct wrap_driver *driver, *cur;
+
+	ENTER1("%s", bin_file_name);
+	if (down_interruptible(&loader_mutex)) {
+		WARNING("couldn't obtain loader_mutex");
+		EXIT1(return NULL);
+	}
+	driver = NULL;
+	nt_list_for_each_entry(cur, &wrap_drivers, list) {
+		for (i = 0; i < cur->num_bin_files; i++)
+			if (!stricmp(cur->bin_files[i].name, bin_file_name)) {
+				driver = cur;
+				break;
+			}
+		if (driver)
+			break;
+	}
+	up(&loader_mutex);
+	if (!driver) {
+		TRACE1("coudln't find bin file '%s'", bin_file_name);
+		return NULL;
+	}
+
+	if (!driver->bin_files[i].data) {
+		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
+#if defined(DEBUG) && DEBUG >= 1
+				"1",
+#else
+				"0",
+#endif
+				UTILS_VERSION, driver->name,
+				driver->bin_files[i].name, NULL};
+		char *env[] = {NULL};
+		int ret;
+
+		TRACE1("loading bin file %s/%s", driver->name,
+		       driver->bin_files[i].name);
+		if (down_interruptible(&loader_mutex)) {
+			WARNING("couldn't obtain loader_mutex");
+			EXIT1(return NULL);
+		}
+		INIT_COMPLETION(loader_complete);
+		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
+		if (ret) {
+			up(&loader_mutex);
+			ERROR("couldn't load file %s/%s; check system log "
+			      "for messages from 'loadndisdriver' (%d)",
+			      driver->name, driver->bin_files[i].name, ret);
+			EXIT1(return NULL);
+		}
+		wait_for_completion(&loader_complete);
+		up(&loader_mutex);
+		if (!driver->bin_files[i].data) {
+			WARNING("couldn't load binary file %s",
+				driver->bin_files[i].name);
+			EXIT1(return NULL);
+		}
+	}
+	EXIT2(return &(driver->bin_files[i]));
+}
+
+/* called with loader_mutex down */
+static int add_bin_file(struct load_driver_file *driver_file)
+{
+	struct wrap_driver *driver, *cur;
+	struct wrap_bin_file *bin_file;
+	int i = 0;
+
+	driver = NULL;
+	nt_list_for_each_entry(cur, &wrap_drivers, list) {
+		for (i = 0; i < cur->num_bin_files; i++)
+			if (!stricmp(cur->bin_files[i].name,
+				     driver_file->name)) {
+				driver = cur;
+				break;
+			}
+		if (driver)
+			break;
+	}
+	if (!driver) {
+		ERROR("couldn't find %s", driver_file->name);
+		return -EINVAL;
+	}
+	bin_file = &driver->bin_files[i];
+	strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));
+	bin_file->name[sizeof(bin_file->name)-1] = 0;
+	bin_file->data = vmalloc(driver_file->size);
+	if (!bin_file->data) {
+		ERROR("couldn't allocate memory");
+		return -ENOMEM;
+	}
+	bin_file->size = driver_file->size;
+	if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {
+		ERROR("couldn't copy data");
+		free_bin_file(bin_file);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+void free_bin_file(struct wrap_bin_file *bin_file)
+{
+	TRACE2("unloading %s", bin_file->name);
+	if (bin_file->data)
+		vfree(bin_file->data);
+	bin_file->data = NULL;
+	bin_file->size = 0;
+	EXIT2(return);
+}
+
+/* load firmware files from userspace */
+static int load_bin_files_info(struct wrap_driver *driver,
+			       struct load_driver *load_driver)
+{
+	struct wrap_bin_file *bin_files;
+	int i;
+
+	ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files);
+	driver->num_bin_files = 0;
+	driver->bin_files = NULL;
+	if (load_driver->num_bin_files == 0)
+		EXIT1(return 0);
+	bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
+			    GFP_KERNEL);
+	if (!bin_files) {
+		ERROR("couldn't allocate memory");
+		EXIT1(return -ENOMEM);
+	}
+
+	for (i = 0; i < load_driver->num_bin_files; i++) {
+		strncpy(bin_files[i].name, load_driver->bin_files[i].name,
+			sizeof(bin_files[i].name));
+		bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;
+		TRACE2("loaded bin file %s", bin_files[i].name);
+	}
+	driver->num_bin_files = load_driver->num_bin_files;
+	driver->bin_files = bin_files;
+	EXIT1(return 0);
+}
+
+/* load settnigs for a device. called with loader_mutex down */
+static int load_settings(struct wrap_driver *wrap_driver,
+			 struct load_driver *load_driver)
+{
+	int i, num_settings;
+
+	ENTER1("%p, %p", wrap_driver, load_driver);
+
+	num_settings = 0;
+	for (i = 0; i < load_driver->num_settings; i++) {
+		struct load_device_setting *load_setting =
+			&load_driver->settings[i];
+		struct wrap_device_setting *setting;
+		ULONG data1;
+
+		setting = kzalloc(sizeof(*setting), GFP_KERNEL);
+		if (!setting) {
+			ERROR("couldn't allocate memory");
+			break;
+		}
+		strncpy(setting->name, load_setting->name,
+			sizeof(setting->name));
+		setting->name[sizeof(setting->name)-1] = 0;
+		strncpy(setting->value, load_setting->value,
+		       sizeof(setting->value));
+		setting->value[sizeof(setting->value)-1] = 0;
+		TRACE2("%p: %s=%s", setting, setting->name, setting->value);
+
+		if (strcmp(setting->name, "driver_version") == 0) {
+			strncpy(wrap_driver->version, setting->value,
+				sizeof(wrap_driver->version));
+			wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;
+		} else if (strcmp(setting->name, "class_guid") == 0 &&
+			   sscanf(setting->value, "%x", &data1) == 1) {
+			wrap_driver->dev_type = wrap_device_type(data1);
+			if (wrap_driver->dev_type < 0) {
+				WARNING("unknown guid: %x", data1);
+				wrap_driver->dev_type = 0;
+			}
+		}
+		InsertTailList(&wrap_driver->settings, &setting->list);
+		num_settings++;
+	}
+	/* it is not a fatal error if some settings couldn't be loaded */
+	if (num_settings > 0)
+		EXIT1(return 0);
+	else
+		EXIT1(return -EINVAL);
+}
+
+void unload_wrap_device(struct wrap_device *wd)
+{
+	struct nt_list *cur;
+	ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
+	       wd->vendor, wd->device, wd->subvendor, wd->subdevice,
+	       wd->driver_name);
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	while ((cur = RemoveHeadList(&wd->settings))) {
+		struct wrap_device_setting *setting;
+		setting = container_of(cur, struct wrap_device_setting, list);
+		kfree(setting);
+	}
+	RemoveEntryList(&wd->list);
+	up(&loader_mutex);
+	kfree(wd);
+	EXIT1(return);
+}
+
+/* should be called with loader_mutex down */
+void unload_wrap_driver(struct wrap_driver *driver)
+{
+	int i;
+	struct driver_object *drv_obj;
+	struct nt_list *cur, *next;
+
+	ENTER1("unloading driver: %s (%p)", driver->name, driver);
+	TRACE1("freeing %d images", driver->num_pe_images);
+	drv_obj = driver->drv_obj;
+	for (i = 0; i < driver->num_pe_images; i++)
+		if (driver->pe_images[i].image) {
+			TRACE1("freeing image at %p",
+			       driver->pe_images[i].image);
+			vfree(driver->pe_images[i].image);
+		}
+
+	TRACE1("freeing %d bin files", driver->num_bin_files);
+	for (i = 0; i < driver->num_bin_files; i++) {
+		TRACE1("freeing image at %p", driver->bin_files[i].data);
+		if (driver->bin_files[i].data)
+			vfree(driver->bin_files[i].data);
+	}
+	if (driver->bin_files)
+		kfree(driver->bin_files);
+	RtlFreeUnicodeString(&drv_obj->name);
+	RemoveEntryList(&driver->list);
+	nt_list_for_each_safe(cur, next, &driver->settings) {
+		struct wrap_device_setting *setting;
+		struct ndis_configuration_parameter *param;
+
+		setting = container_of(cur, struct wrap_device_setting, list);
+		TRACE2("%p", setting);
+		param = setting->encoded;
+		if (param) {
+			TRACE2("%p", param);
+			if (param->type == NdisParameterString)
+				RtlFreeUnicodeString(&param->data.string);
+			ExFreePool(param);
+		}
+		kfree(setting);
+	}
+	/* this frees driver */
+	free_custom_extensions(drv_obj->drv_ext);
+	kfree(drv_obj->drv_ext);
+	TRACE1("drv_obj: %p", drv_obj);
+
+	EXIT1(return);
+}
+
+/* call the entry point of the driver */
+static int start_wrap_driver(struct wrap_driver *driver)
+{
+	int i;
+	NTSTATUS ret, res;
+	struct driver_object *drv_obj;
+	typeof(driver->pe_images[0].entry) entry;
+
+	ENTER1("%s", driver->name);
+	drv_obj = driver->drv_obj;
+	for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
+		/* dlls are already started by loader */
+		if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
+			entry = driver->pe_images[i].entry;
+			drv_obj->start = driver->pe_images[i].entry;
+			drv_obj->driver_size = driver->pe_images[i].size;
+			TRACE1("entry: %p, %p, drv_obj: %p",
+			       entry, *entry, drv_obj);
+			res = LIN2WIN2(entry, drv_obj, &drv_obj->name);
+			ret |= res;
+			TRACE1("entry returns %08X", res);
+			break;
+		}
+	if (ret) {
+		ERROR("driver initialization failed: %08X", ret);
+		RtlFreeUnicodeString(&drv_obj->name);
+		/* this frees ndis_driver */
+		free_custom_extensions(drv_obj->drv_ext);
+		kfree(drv_obj->drv_ext);
+		TRACE1("drv_obj: %p", drv_obj);
+		ObDereferenceObject(drv_obj);
+		EXIT1(return -EINVAL);
+	}
+	EXIT1(return 0);
+}
+
+/*
+ * add driver to list of loaded driver but make sure this driver is
+ * not loaded before. called with loader_mutex down
+ */
+static int add_wrap_driver(struct wrap_driver *driver)
+{
+	struct wrap_driver *tmp;
+
+	ENTER1("name: %s", driver->name);
+	nt_list_for_each_entry(tmp, &wrap_drivers, list) {
+		if (stricmp(tmp->name, driver->name) == 0) {
+			ERROR("cannot add duplicate driver");
+			EXIT1(return -EBUSY);
+		}
+	}
+	InsertHeadList(&wrap_drivers, &driver->list);
+	EXIT1(return 0);
+}
+
+/* load a driver from userspace and initialize it. called with
+ * loader_mutex down */
+static int load_user_space_driver(struct load_driver *load_driver)
+{
+	struct driver_object *drv_obj;
+	struct ansi_string ansi_reg;
+	struct wrap_driver *wrap_driver = NULL;
+
+	ENTER1("%p", load_driver);
+	drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
+	if (!drv_obj) {
+		ERROR("couldn't allocate memory");
+		EXIT1(return -ENOMEM);
+	}
+	TRACE1("drv_obj: %p", drv_obj);
+	drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
+	if (!drv_obj->drv_ext) {
+		ERROR("couldn't allocate memory");
+		ObDereferenceObject(drv_obj);
+		EXIT1(return -ENOMEM);
+	}
+	InitializeListHead(&drv_obj->drv_ext->custom_ext);
+	if (IoAllocateDriverObjectExtension(drv_obj,
+					    (void *)WRAP_DRIVER_CLIENT_ID,
+					    sizeof(*wrap_driver),
+					    (void **)&wrap_driver) !=
+	    STATUS_SUCCESS)
+		EXIT1(return -ENOMEM);
+	TRACE1("driver: %p", wrap_driver);
+	memset(wrap_driver, 0, sizeof(*wrap_driver));
+	InitializeListHead(&wrap_driver->list);
+	InitializeListHead(&wrap_driver->settings);
+	InitializeListHead(&wrap_driver->wrap_devices);
+	wrap_driver->drv_obj = drv_obj;
+	RtlInitAnsiString(&ansi_reg, "/tmp");
+	if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=
+	    STATUS_SUCCESS) {
+		ERROR("couldn't initialize registry path");
+		free_custom_extensions(drv_obj->drv_ext);
+		kfree(drv_obj->drv_ext);
+		TRACE1("drv_obj: %p", drv_obj);
+		ObDereferenceObject(drv_obj);
+		EXIT1(return -EINVAL);
+	}
+	strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));
+	wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;
+	if (load_sys_files(wrap_driver, load_driver) ||
+	    load_bin_files_info(wrap_driver, load_driver) ||
+	    load_settings(wrap_driver, load_driver) ||
+	    start_wrap_driver(wrap_driver) ||
+	    add_wrap_driver(wrap_driver)) {
+		unload_wrap_driver(wrap_driver);
+		EXIT1(return -EINVAL);
+	} else {
+		printk(KERN_INFO "%s: driver %s (%s) loaded\n",
+		       DRIVER_NAME, wrap_driver->name, wrap_driver->version);
+		add_taint(TAINT_PROPRIETARY_MODULE);
+		EXIT1(return 0);
+	}
+}
+
+static struct pci_device_id wrap_pci_id_table[] = {
+	{PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID},
+};
+
+static struct pci_driver wrap_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= wrap_pci_id_table,
+	.probe		= wrap_pnp_start_pci_device,
+	.remove		= __devexit_p(wrap_pnp_remove_pci_device),
+	.suspend	= wrap_pnp_suspend_pci_device,
+	.resume		= wrap_pnp_resume_pci_device,
+};
+
+#ifdef ENABLE_USB
+static struct usb_device_id wrap_usb_id_table[] = {
+	{
+		.driver_info = 1
+	},
+};
+
+static struct usb_driver wrap_usb_driver = {
+	.name = DRIVER_NAME,
+	.id_table = wrap_usb_id_table,
+	.probe = wrap_pnp_start_usb_device,
+	.disconnect = __devexit_p(wrap_pnp_remove_usb_device),
+	.suspend = wrap_pnp_suspend_usb_device,
+	.resume = wrap_pnp_resume_usb_device,
+};
+#endif
+
+/* register drivers for pci and usb */
+static void register_devices(void)
+{
+	int res;
+
+	res = pci_register_driver(&wrap_pci_driver);
+	if (res < 0) {
+		ERROR("couldn't register pci driver: %d", res);
+		wrap_pci_driver.name = NULL;
+	}
+
+#ifdef ENABLE_USB
+	res = usb_register(&wrap_usb_driver);
+	if (res < 0) {
+		ERROR("couldn't register usb driver: %d", res);
+		wrap_usb_driver.name = NULL;
+	}
+#endif
+	EXIT1(return);
+}
+
+static void unregister_devices(void)
+{
+	struct nt_list *cur, *next;
+
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	nt_list_for_each_safe(cur, next, &wrap_devices) {
+		struct wrap_device *wd;
+		wd = container_of(cur, struct wrap_device, list);
+		set_bit(HW_PRESENT, &wd->hw_status);
+	}
+	up(&loader_mutex);
+
+	if (wrap_pci_driver.name)
+		pci_unregister_driver(&wrap_pci_driver);
+#ifdef ENABLE_USB
+	if (wrap_usb_driver.name)
+		usb_deregister(&wrap_usb_driver);
+#endif
+}
+
+struct wrap_device *load_wrap_device(struct load_device *load_device)
+{
+	int ret;
+	struct nt_list *cur;
+	struct wrap_device *wd = NULL;
+	char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
+
+	ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,
+	       load_device->device, load_device->subvendor,
+	       load_device->subdevice);
+	if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&
+	    sprintf(device, "%04x", load_device->device) == 4 &&
+	    sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&
+	    sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&
+	    sprintf(bus, "%04x", load_device->bus) == 4) {
+		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,
+#if defined(DEBUG) && DEBUG >= 1
+				"1",
+#else
+				"0",
+#endif
+				UTILS_VERSION, vendor, device,
+				subvendor, subdevice, bus, NULL};
+		char *env[] = {NULL};
+		TRACE2("%s, %s, %s, %s, %s", vendor, device,
+		       subvendor, subdevice, bus);
+		if (down_interruptible(&loader_mutex)) {
+			WARNING("couldn't obtain loader_mutex");
+			EXIT1(return NULL);
+		}
+		INIT_COMPLETION(loader_complete);
+		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
+		if (ret) {
+			up(&loader_mutex);
+			TRACE1("couldn't load device %04x:%04x; check system "
+			       "log for messages from 'loadndisdriver'",
+			       load_device->vendor, load_device->device);
+			EXIT1(return NULL);
+		}
+		wait_for_completion(&loader_complete);
+		wd = NULL;
+		nt_list_for_each(cur, &wrap_devices) {
+			wd = container_of(cur, struct wrap_device, list);
+			TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,
+			       wd->device, wd->subvendor, wd->subdevice);
+			if (wd->vendor == load_device->vendor &&
+			    wd->device == load_device->device)
+				break;
+			else
+				wd = NULL;
+		}
+		up(&loader_mutex);
+	} else
+		wd = NULL;
+	EXIT1(return wd);
+}
+
+struct wrap_device *get_wrap_device(void *dev, int bus)
+{
+	struct nt_list *cur;
+	struct wrap_device *wd;
+
+	if (down_interruptible(&loader_mutex)) {
+		WARNING("couldn't obtain loader_mutex");
+		return NULL;
+	}
+	wd = NULL;
+	nt_list_for_each(cur, &wrap_devices) {
+		wd = container_of(cur, struct wrap_device, list);
+		if (bus == WRAP_PCI_BUS &&
+		    wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)
+			break;
+		else if (bus == WRAP_USB_BUS &&
+			 wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
+			break;
+		else
+			wd = NULL;
+	}
+	up(&loader_mutex);
+	return wd;
+}
+
+/* called with loader_mutex is down */
+static int wrapper_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct load_driver *load_driver;
+	struct load_device load_device;
+	struct load_driver_file load_bin_file;
+	int ret;
+	void __user *addr = (void __user *)arg;
+
+	ENTER1("cmd: %u", cmd);
+
+	ret = 0;
+	switch (cmd) {
+	case WRAP_IOCTL_LOAD_DEVICE:
+		if (copy_from_user(&load_device, addr, sizeof(load_device))) {
+			ret = -EFAULT;
+			break;
+		}
+		TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,
+		       load_device.device, load_device.subvendor,
+		       load_device.subdevice);
+		if (load_device.vendor) {
+			struct wrap_device *wd;
+			wd = kzalloc(sizeof(*wd), GFP_KERNEL);
+			if (!wd) {
+				ret = -ENOMEM;
+				break;
+			}
+			InitializeListHead(&wd->settings);
+			wd->dev_bus = WRAP_BUS(load_device.bus);
+			wd->vendor = load_device.vendor;
+			wd->device = load_device.device;
+			wd->subvendor = load_device.subvendor;
+			wd->subdevice = load_device.subdevice;
+			strncpy(wd->conf_file_name, load_device.conf_file_name,
+				sizeof(wd->conf_file_name));
+			wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;
+			strncpy(wd->driver_name, load_device.driver_name,
+			       sizeof(wd->driver_name));
+			wd->driver_name[sizeof(wd->driver_name)-1] = 0;
+			InsertHeadList(&wrap_devices, &wd->list);
+			ret = 0;
+		} else
+			ret = -EINVAL;
+		break;
+	case WRAP_IOCTL_LOAD_DRIVER:
+		TRACE1("loading driver at %p", addr);
+		load_driver = vmalloc(sizeof(*load_driver));
+		if (!load_driver) {
+			ret = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
+			ret = -EFAULT;
+		else
+			ret = load_user_space_driver(load_driver);
+		vfree(load_driver);
+		break;
+	case WRAP_IOCTL_LOAD_BIN_FILE:
+		if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
+			ret = -EFAULT;
+		else
+			ret = add_bin_file(&load_bin_file);
+		break;
+	default:
+		ERROR("unknown ioctl %u", cmd);
+		ret = -EINVAL;
+		break;
+	}
+	complete(&loader_complete);
+	EXIT1(return ret);
+}
+
+static int wrapper_ioctl_release(struct inode *inode, struct file *file)
+{
+	ENTER1("");
+	return 0;
+}
+
+static struct file_operations wrapper_fops = {
+	.owner          = THIS_MODULE,
+	.ioctl		= wrapper_ioctl,
+	.release	= wrapper_ioctl_release,
+};
+
+static struct miscdevice wrapper_misc = {
+	.name   = DRIVER_NAME,
+	.minor	= MISC_DYNAMIC_MINOR,
+	.fops   = &wrapper_fops
+};
+
+int loader_init(void)
+{
+	int err;
+
+	InitializeListHead(&wrap_drivers);
+	InitializeListHead(&wrap_devices);
+	init_MUTEX(&loader_mutex);
+	init_completion(&loader_complete);
+	if ((err = misc_register(&wrapper_misc)) < 0 ) {
+		ERROR("couldn't register module (%d)", err);
+		unregister_devices();
+		EXIT1(return err);
+	}
+	register_devices();
+	EXIT1(return 0);
+}
+
+void loader_exit(void)
+{
+	struct nt_list *cur, *next;
+
+	ENTER1("");
+	misc_deregister(&wrapper_misc);
+	unregister_devices();
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	nt_list_for_each_safe(cur, next, &wrap_drivers) {
+		struct wrap_driver *driver;
+		driver = container_of(cur, struct wrap_driver, list);
+		unload_wrap_driver(driver);
+	}
+	up(&loader_mutex);
+	EXIT1(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ntoskernel.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ntoskernel.c
@@ -0,0 +1,2683 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ntoskernel.h"
+#include "ndis.h"
+#include "usb.h"
+#include "pnp.h"
+#include "loader.h"
+#include "ntoskernel_exports.h"
+
+/* MDLs describe a range of virtual address with an array of physical
+ * pages right after the header. For different ranges of virtual
+ * addresses, the number of entries of physical pages may be different
+ * (depending on number of entries required). If we want to allocate
+ * MDLs from a pool, the size has to be constant. So we assume that
+ * maximum range used by a driver is MDL_CACHE_PAGES; if a driver
+ * requests an MDL for a bigger region, we allocate it with kmalloc;
+ * otherwise, we allocate from the pool */
+
+#define MDL_CACHE_PAGES 3
+#define MDL_CACHE_SIZE (sizeof(struct mdl) + \
+			(sizeof(PFN_NUMBER) * MDL_CACHE_PAGES))
+struct wrap_mdl {
+	struct nt_list list;
+	struct mdl mdl[0];
+};
+
+/* everything here is for all drivers/devices - not per driver/device */
+static spinlock_t dispatcher_lock;
+spinlock_t ntoskernel_lock;
+static void *mdl_cache;
+static struct nt_list wrap_mdl_list;
+
+static work_struct_t kdpc_work;
+static void kdpc_worker(worker_param_t dummy);
+
+static struct nt_list kdpc_list;
+static spinlock_t kdpc_list_lock;
+
+static struct nt_list callback_objects;
+
+struct nt_list object_list;
+
+struct bus_driver {
+	struct nt_list list;
+	char name[MAX_DRIVER_NAME_LEN];
+	struct driver_object drv_obj;
+};
+
+static struct nt_list bus_driver_list;
+
+static work_struct_t ntos_work;
+static struct nt_list ntos_work_list;
+static spinlock_t ntos_work_lock;
+static void ntos_work_worker(worker_param_t dummy);
+static struct nt_thread *ntos_worker_thread;
+spinlock_t irp_cancel_lock;
+static NT_SPIN_LOCK nt_list_lock;
+static struct nt_slist wrap_timer_slist;
+
+/* compute ticks (100ns) since 1601 until when system booted into
+ * wrap_ticks_to_boot */
+u64 wrap_ticks_to_boot;
+
+#if defined(CONFIG_X86_64)
+static struct timer_list shared_data_timer;
+struct kuser_shared_data kuser_shared_data;
+static void update_user_shared_data_proc(unsigned long data);
+#endif
+
+WIN_SYMBOL_MAP("KeTickCount", &jiffies)
+
+WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE)
+
+workqueue_struct_t *ntos_wq;
+
+#ifdef WRAP_PREEMPT
+DEFINE_PER_CPU(irql_info_t, irql_info);
+#endif
+
+#if defined(CONFIG_X86_64)
+static void update_user_shared_data_proc(unsigned long data)
+{
+	/* timer is supposed to be scheduled every 10ms, but bigger
+	 * intervals seem to work (tried upto 50ms) */
+	*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();
+	*((ULONG64 *)&kuser_shared_data.interrupt_time) =
+		jiffies * TICKSPERSEC / HZ;
+	*((ULONG64 *)&kuser_shared_data.tick) = jiffies;
+
+	mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30));
+}
+#endif
+
+void *allocate_object(ULONG size, enum common_object_type type,
+		      struct unicode_string *name)
+{
+	struct common_object_header *hdr;
+	void *body;
+
+	/* we pad header as prefix to body */
+	hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0);
+	if (!hdr) {
+		WARNING("couldn't allocate memory");
+		return NULL;
+	}
+	memset(hdr, 0, OBJECT_SIZE(size));
+	if (name) {
+		hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool,
+						      name->max_length, 0);
+		if (!hdr->name.buf) {
+			ExFreePool(hdr);
+			return NULL;
+		}
+		memcpy(hdr->name.buf, name->buf, name->max_length);
+		hdr->name.length = name->length;
+		hdr->name.max_length = name->max_length;
+	}
+	hdr->type = type;
+	hdr->ref_count = 1;
+	spin_lock_bh(&ntoskernel_lock);
+	/* threads are looked up often (in KeWaitForXXX), so optimize
+	 * for fast lookups of threads */
+	if (type == OBJECT_TYPE_NT_THREAD)
+		InsertHeadList(&object_list, &hdr->list);
+	else
+		InsertTailList(&object_list, &hdr->list);
+	spin_unlock_bh(&ntoskernel_lock);
+	body = HEADER_TO_OBJECT(hdr);
+	TRACE3("allocated hdr: %p, body: %p", hdr, body);
+	return body;
+}
+
+void free_object(void *object)
+{
+	struct common_object_header *hdr;
+
+	hdr = OBJECT_TO_HEADER(object);
+	spin_lock_bh(&ntoskernel_lock);
+	RemoveEntryList(&hdr->list);
+	spin_unlock_bh(&ntoskernel_lock);
+	TRACE3("freed hdr: %p, body: %p", hdr, object);
+	if (hdr->name.buf)
+		ExFreePool(hdr->name.buf);
+	ExFreePool(hdr);
+}
+
+static int add_bus_driver(const char *name)
+{
+	struct bus_driver *bus_driver;
+
+	bus_driver = kzalloc(sizeof(*bus_driver), GFP_KERNEL);
+	if (!bus_driver) {
+		ERROR("couldn't allocate memory");
+		return -ENOMEM;
+	}
+	strncpy(bus_driver->name, name, sizeof(bus_driver->name));
+	bus_driver->name[sizeof(bus_driver->name)-1] = 0;
+	spin_lock_bh(&ntoskernel_lock);
+	InsertTailList(&bus_driver_list, &bus_driver->list);
+	spin_unlock_bh(&ntoskernel_lock);
+	TRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj);
+	return STATUS_SUCCESS;
+}
+
+struct driver_object *find_bus_driver(const char *name)
+{
+	struct bus_driver *bus_driver;
+	struct driver_object *drv_obj;
+
+	spin_lock_bh(&ntoskernel_lock);
+	drv_obj = NULL;
+	nt_list_for_each_entry(bus_driver, &bus_driver_list, list) {
+		if (strcmp(bus_driver->name, name) == 0) {
+			drv_obj = &bus_driver->drv_obj;
+			break;
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	return drv_obj;
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3)
+	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
+{
+	struct nt_list *first;
+	unsigned long flags;
+
+	ENTER5("head = %p, entry = %p", head, entry);
+	nt_spin_lock_irqsave(lock, flags);
+	first = InsertHeadList(head, entry);
+	nt_spin_unlock_irqrestore(lock, flags);
+	TRACE5("head = %p, old = %p", head, first);
+	return first;
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3)
+	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
+{
+	ENTER5("%p", head);
+	return ExfInterlockedInsertHeadList(head, entry, lock);
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3)
+	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
+{
+	struct nt_list *last;
+	unsigned long flags;
+
+	ENTER5("head = %p, entry = %p", head, entry);
+	nt_spin_lock_irqsave(lock, flags);
+	last = InsertTailList(head, entry);
+	nt_spin_unlock_irqrestore(lock, flags);
+	TRACE5("head = %p, old = %p", head, last);
+	return last;
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3)
+	(struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock)
+{
+	ENTER5("%p", head);
+	return ExfInterlockedInsertTailList(head, entry, lock);
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2)
+	(struct nt_list *head, NT_SPIN_LOCK *lock)
+{
+	struct nt_list *ret;
+	unsigned long flags;
+
+	ENTER5("head = %p", head);
+	nt_spin_lock_irqsave(lock, flags);
+	ret = RemoveHeadList(head);
+	nt_spin_unlock_irqrestore(lock, flags);
+	TRACE5("head = %p, ret = %p", head, ret);
+	return ret;
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2)
+	(struct nt_list *head, NT_SPIN_LOCK *lock)
+{
+	ENTER5("%p", head);
+	return ExfInterlockedRemoveHeadList(head, lock);
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2)
+	(struct nt_list *head, NT_SPIN_LOCK *lock)
+{
+	struct nt_list *ret;
+	unsigned long flags;
+
+	ENTER5("head = %p", head);
+	nt_spin_lock_irqsave(lock, flags);
+	ret = RemoveTailList(head);
+	nt_spin_unlock_irqrestore(lock, flags);
+	TRACE5("head = %p, ret = %p", head, ret);
+	return ret;
+}
+
+wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2)
+	(struct nt_list *head, NT_SPIN_LOCK *lock)
+{
+	ENTER5("%p", head);
+	return ExfInterlockedRemoveTailList(head, lock);
+}
+
+wfastcall void WIN_FUNC(InitializeSListHead,1)
+	(nt_slist_header *head)
+{
+	memset(head, 0, sizeof(*head));
+}
+
+wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPushEntrySList,3)
+	(nt_slist_header *head, struct nt_slist *entry, NT_SPIN_LOCK *lock)
+{
+	struct nt_slist *ret;
+
+	ret = PushEntrySList(head, entry, lock);
+	return ret;
+}
+
+wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPushEntrySList,2)
+	(nt_slist_header *head, struct nt_slist *entry)
+{
+	struct nt_slist *ret;
+
+	ret = PushEntrySList(head, entry, &nt_list_lock);
+	return ret;
+}
+
+wfastcall struct nt_slist *WIN_FUNC(InterlockedPushEntrySList,2)
+	(nt_slist_header *head, struct nt_slist *entry)
+{
+	struct nt_slist *ret;
+
+	ret = PushEntrySList(head, entry, &nt_list_lock);
+	return ret;
+}
+
+wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPopEntrySList,2)
+	(nt_slist_header *head, NT_SPIN_LOCK *lock)
+{
+	struct nt_slist *ret;
+
+	ret = PopEntrySList(head, lock);
+	return ret;
+}
+
+wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPopEntrySList,1)
+	(nt_slist_header *head)
+{
+	struct nt_slist *ret;
+
+	ret = PopEntrySList(head, &nt_list_lock);
+	return ret;
+}
+
+wfastcall struct nt_slist *WIN_FUNC(InterlockedPopEntrySList,1)
+	(nt_slist_header *head)
+{
+	struct nt_slist *ret;
+
+	ret = PopEntrySList(head, &nt_list_lock);
+	return ret;
+}
+
+wstdcall USHORT WIN_FUNC(ExQueryDepthSList,1)
+	(nt_slist_header *head)
+{
+	USHORT depth;
+	ENTER5("%p", head);
+	depth = head->depth;
+	TRACE5("%d, %p", depth, head->next);
+	return depth;
+}
+
+wfastcall LONG WIN_FUNC(InterlockedIncrement,1)
+	(LONG volatile *val)
+{
+	return post_atomic_add(*val, 1);
+}
+
+wfastcall LONG WIN_FUNC(InterlockedDecrement,1)
+	(LONG volatile *val)
+{
+	return post_atomic_add(*val, -1);
+}
+
+wfastcall LONG WIN_FUNC(InterlockedExchange,2)
+	(LONG volatile *target, LONG val)
+{
+	return xchg(target, val);
+}
+
+wfastcall LONG WIN_FUNC(InterlockedCompareExchange,3)
+	(LONG volatile *dest, LONG new, LONG old)
+{
+	return cmpxchg(dest, old, new);
+}
+
+wfastcall void WIN_FUNC(ExInterlockedAddLargeStatistic,2)
+	(LARGE_INTEGER volatile *plint, ULONG n)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+#ifdef CONFIG_X86_64
+	__asm__ __volatile__(
+		"\n"
+		LOCK_PREFIX "add %1, %0\n\t"
+		: "+m" (*plint)
+		: "r" (n));
+#else
+	__asm__ __volatile__(
+		"1:\t"
+		"   movl %1, %%ebx\n\t"
+		"   movl %%edx, %%ecx\n\t"
+		"   addl %%eax, %%ebx\n\t"
+		"   adcl $0, %%ecx\n\t"
+		    LOCK_PREFIX "cmpxchg8b %0\n\t"
+		"   jnz 1b\n\t"
+		: "+m" (*plint)
+		: "m" (n), "A" (*plint)
+		: "ebx", "ecx");
+#endif
+	local_irq_restore(flags);
+}
+
+static void initialize_object(struct dispatcher_header *dh, enum dh_type type,
+			      int state)
+{
+	memset(dh, 0, sizeof(*dh));
+	set_object_type(dh, type);
+	dh->signal_state = state;
+	InitializeListHead(&dh->wait_blocks);
+}
+
+static void timer_proc(unsigned long data)
+{
+	struct wrap_timer *wrap_timer = (struct wrap_timer *)data;
+	struct nt_timer *nt_timer;
+	struct kdpc *kdpc;
+
+	nt_timer = wrap_timer->nt_timer;
+	TIMERENTER("%p(%p), %lu", wrap_timer, nt_timer, jiffies);
+#ifdef TIMER_DEBUG
+	BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
+	BUG_ON(nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
+#endif
+	KeSetEvent((struct nt_event *)nt_timer, 0, FALSE);
+	if (wrap_timer->repeat)
+		mod_timer(&wrap_timer->timer, jiffies + wrap_timer->repeat);
+	kdpc = nt_timer->kdpc;
+	if (kdpc)
+		queue_kdpc(kdpc);
+	TIMEREXIT(return);
+}
+
+void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type,
+		     struct ndis_mp_block *nmb)
+{
+	struct wrap_timer *wrap_timer;
+
+	/* TODO: if a timer is initialized more than once, we allocate
+	 * memory for wrap_timer more than once for the same nt_timer,
+	 * wasting memory. We can check if nt_timer->wrap_timer_magic is
+	 * set and not allocate, but it is not guaranteed always to be
+	 * safe */
+	TIMERENTER("%p", nt_timer);
+	/* we allocate memory for wrap_timer behind driver's back and
+	 * there is no NDIS/DDK function where this memory can be
+	 * freed, so we use slack_kmalloc so it gets freed when driver
+	 * is unloaded */
+	if (nmb)
+		wrap_timer = kmalloc(sizeof(*wrap_timer), irql_gfp());
+	else
+		wrap_timer = slack_kmalloc(sizeof(*wrap_timer));
+	if (!wrap_timer) {
+		ERROR("couldn't allocate memory for timer");
+		return;
+	}
+
+	memset(wrap_timer, 0, sizeof(*wrap_timer));
+	init_timer(&wrap_timer->timer);
+	wrap_timer->timer.data = (unsigned long)wrap_timer;
+	wrap_timer->timer.function = timer_proc;
+	wrap_timer->nt_timer = nt_timer;
+#ifdef TIMER_DEBUG
+	wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
+#endif
+	nt_timer->wrap_timer = wrap_timer;
+	nt_timer->kdpc = NULL;
+	initialize_object(&nt_timer->dh, type, 0);
+	nt_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
+	TIMERTRACE("timer %p (%p)", wrap_timer, nt_timer);
+	spin_lock_bh(&ntoskernel_lock);
+	if (nmb) {
+		wrap_timer->slist.next = nmb->wnd->wrap_timer_slist.next;
+		nmb->wnd->wrap_timer_slist.next = &wrap_timer->slist;
+	} else {
+		wrap_timer->slist.next = wrap_timer_slist.next;
+		wrap_timer_slist.next = &wrap_timer->slist;
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	TIMEREXIT(return);
+}
+
+wstdcall void WIN_FUNC(KeInitializeTimerEx,2)
+	(struct nt_timer *nt_timer, enum timer_type type)
+{
+	TIMERENTER("%p", nt_timer);
+	wrap_init_timer(nt_timer, type, NULL);
+}
+
+wstdcall void WIN_FUNC(KeInitializeTimer,1)
+	(struct nt_timer *nt_timer)
+{
+	TIMERENTER("%p", nt_timer);
+	wrap_init_timer(nt_timer, NotificationTimer, NULL);
+}
+
+/* expires and repeat are in HZ */
+BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz,
+		       unsigned long repeat_hz, struct kdpc *kdpc)
+{
+	struct wrap_timer *wrap_timer;
+
+	TIMERENTER("%p, %lu, %lu, %p, %lu",
+		   nt_timer, expires_hz, repeat_hz, kdpc, jiffies);
+
+	wrap_timer = nt_timer->wrap_timer;
+	TIMERTRACE("%p", wrap_timer);
+#ifdef TIMER_DEBUG
+	if (wrap_timer->nt_timer != nt_timer)
+		WARNING("bad timers: %p, %p, %p", wrap_timer, nt_timer,
+			wrap_timer->nt_timer);
+	if (nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) {
+		WARNING("buggy Windows timer didn't initialize timer %p",
+			nt_timer);
+		return FALSE;
+	}
+	if (wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) {
+		WARNING("timer %p is not initialized (%lx)?",
+			wrap_timer, wrap_timer->wrap_timer_magic);
+		wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC;
+	}
+#endif
+	KeClearEvent((struct nt_event *)nt_timer);
+	nt_timer->kdpc = kdpc;
+	wrap_timer->repeat = repeat_hz;
+	if (mod_timer(&wrap_timer->timer, jiffies + expires_hz))
+		TIMEREXIT(return TRUE);
+	else
+		TIMEREXIT(return FALSE);
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeSetTimerEx,4)
+	(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
+	 LONG period_ms, struct kdpc *kdpc)
+{
+	unsigned long expires_hz, repeat_hz;
+
+	TIMERENTER("%p, %Ld, %d", nt_timer, duetime_ticks, period_ms);
+	expires_hz = SYSTEM_TIME_TO_HZ(duetime_ticks);
+	repeat_hz = MSEC_TO_HZ(period_ms);
+	return wrap_set_timer(nt_timer, expires_hz, repeat_hz, kdpc);
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeSetTimer,3)
+	(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks,
+	 struct kdpc *kdpc)
+{
+	TIMERENTER("%p, %Ld, %p", nt_timer, duetime_ticks, kdpc);
+	return KeSetTimerEx(nt_timer, duetime_ticks, 0, kdpc);
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeCancelTimer,1)
+	(struct nt_timer *nt_timer)
+{
+	struct wrap_timer *wrap_timer;
+	int ret;
+
+	TIMERENTER("%p", nt_timer);
+	wrap_timer = nt_timer->wrap_timer;
+	if (!wrap_timer) {
+		ERROR("invalid wrap_timer");
+		return TRUE;
+	}
+#ifdef TIMER_DEBUG
+	BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC);
+#endif
+	/* disable timer before deleting so if it is periodic timer, it
+	 * won't be re-armed after deleting */
+	wrap_timer->repeat = 0;
+	ret = del_timer_sync(&wrap_timer->timer);
+	/* the documentation for KeCancelTimer suggests the DPC is
+	 * deqeued, but actually DPC is left to run */
+	if (ret)
+		TIMEREXIT(return TRUE);
+	else
+		TIMEREXIT(return FALSE);
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeReadStateTimer,1)
+	(struct nt_timer *nt_timer)
+{
+	if (nt_timer->dh.signal_state)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+wstdcall void WIN_FUNC(KeInitializeDpc,3)
+	(struct kdpc *kdpc, void *func, void *ctx)
+{
+	ENTER3("%p, %p, %p", kdpc, func, ctx);
+	memset(kdpc, 0, sizeof(*kdpc));
+	kdpc->func = func;
+	kdpc->ctx  = ctx;
+	InitializeListHead(&kdpc->list);
+}
+
+static void kdpc_worker(worker_param_t dummy)
+{
+	struct nt_list *entry;
+	struct kdpc *kdpc;
+	unsigned long flags;
+	KIRQL irql;
+
+	WORKENTER("");
+	irql = raise_irql(DISPATCH_LEVEL);
+	while (1) {
+		spin_lock_irqsave(&kdpc_list_lock, flags);
+		entry = RemoveHeadList(&kdpc_list);
+		if (entry) {
+			kdpc = container_of(entry, struct kdpc, list);
+			assert(kdpc->queued);
+			kdpc->queued = 0;
+		} else
+			kdpc = NULL;
+		spin_unlock_irqrestore(&kdpc_list_lock, flags);
+		if (!kdpc)
+			break;
+		WORKTRACE("%p, %p, %p, %p, %p", kdpc, kdpc->func, kdpc->ctx,
+			  kdpc->arg1, kdpc->arg2);
+		assert_irql(_irql_ == DISPATCH_LEVEL);
+		LIN2WIN4(kdpc->func, kdpc, kdpc->ctx, kdpc->arg1, kdpc->arg2);
+		assert_irql(_irql_ == DISPATCH_LEVEL);
+	}
+	lower_irql(irql);
+	WORKEXIT(return);
+}
+
+wstdcall void WIN_FUNC(KeFlushQueuedDpcs,0)
+	(void)
+{
+	kdpc_worker(NULL);
+}
+
+BOOLEAN queue_kdpc(struct kdpc *kdpc)
+{
+	BOOLEAN ret;
+	unsigned long flags;
+
+	WORKENTER("%p", kdpc);
+	spin_lock_irqsave(&kdpc_list_lock, flags);
+	if (kdpc->queued)
+		ret = FALSE;
+	else {
+		if (unlikely(kdpc->importance == HighImportance))
+			InsertHeadList(&kdpc_list, &kdpc->list);
+		else
+			InsertTailList(&kdpc_list, &kdpc->list);
+		kdpc->queued = 1;
+		ret = TRUE;
+	}
+	spin_unlock_irqrestore(&kdpc_list_lock, flags);
+	if (ret == TRUE)
+		schedule_ntos_work(&kdpc_work);
+	WORKTRACE("%d", ret);
+	return ret;
+}
+
+BOOLEAN dequeue_kdpc(struct kdpc *kdpc)
+{
+	BOOLEAN ret;
+	unsigned long flags;
+
+	WORKENTER("%p", kdpc);
+	spin_lock_irqsave(&kdpc_list_lock, flags);
+	if (kdpc->queued) {
+		RemoveEntryList(&kdpc->list);
+		kdpc->queued = 0;
+		ret = TRUE;
+	} else
+		ret = FALSE;
+	spin_unlock_irqrestore(&kdpc_list_lock, flags);
+	WORKTRACE("%d", ret);
+	return ret;
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeInsertQueueDpc,3)
+	(struct kdpc *kdpc, void *arg1, void *arg2)
+{
+	WORKENTER("%p, %p, %p", kdpc, arg1, arg2);
+	kdpc->arg1 = arg1;
+	kdpc->arg2 = arg2;
+	return queue_kdpc(kdpc);
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeRemoveQueueDpc,1)
+	(struct kdpc *kdpc)
+{
+	return dequeue_kdpc(kdpc);
+}
+
+wstdcall void WIN_FUNC(KeSetImportanceDpc,2)
+	(struct kdpc *kdpc, enum kdpc_importance importance)
+{
+	kdpc->importance = importance;
+}
+
+static void ntos_work_worker(worker_param_t dummy)
+{
+	struct ntos_work_item *ntos_work_item;
+	struct nt_list *cur;
+
+	while (1) {
+		spin_lock_bh(&ntos_work_lock);
+		cur = RemoveHeadList(&ntos_work_list);
+		spin_unlock_bh(&ntos_work_lock);
+		if (!cur)
+			break;
+		ntos_work_item = container_of(cur, struct ntos_work_item, list);
+		WORKTRACE("%p: executing %p, %p, %p", current,
+			  ntos_work_item->func, ntos_work_item->arg1,
+			  ntos_work_item->arg2);
+		LIN2WIN2(ntos_work_item->func, ntos_work_item->arg1,
+			 ntos_work_item->arg2);
+		kfree(ntos_work_item);
+	}
+	WORKEXIT(return);
+}
+
+int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2)
+{
+	struct ntos_work_item *ntos_work_item;
+
+	WORKENTER("adding work: %p, %p, %p", func, arg1, arg2);
+	ntos_work_item = kmalloc(sizeof(*ntos_work_item), irql_gfp());
+	if (!ntos_work_item) {
+		ERROR("couldn't allocate memory");
+		return -ENOMEM;
+	}
+	ntos_work_item->func = func;
+	ntos_work_item->arg1 = arg1;
+	ntos_work_item->arg2 = arg2;
+	spin_lock_bh(&ntos_work_lock);
+	InsertTailList(&ntos_work_list, &ntos_work_item->list);
+	spin_unlock_bh(&ntos_work_lock);
+	schedule_ntos_work(&ntos_work);
+	WORKEXIT(return 0);
+}
+
+wstdcall void WIN_FUNC(KeInitializeSpinLock,1)
+	(NT_SPIN_LOCK *lock)
+{
+	ENTER6("%p", lock);
+	nt_spin_lock_init(lock);
+}
+
+wstdcall void WIN_FUNC(KeAcquireSpinLock,2)
+	(NT_SPIN_LOCK *lock, KIRQL *irql)
+{
+	ENTER6("%p", lock);
+	*irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL);
+}
+
+wstdcall void WIN_FUNC(KeReleaseSpinLock,2)
+	(NT_SPIN_LOCK *lock, KIRQL oldirql)
+{
+	ENTER6("%p", lock);
+	nt_spin_unlock_irql(lock, oldirql);
+}
+
+wstdcall void WIN_FUNC(KeAcquireSpinLockAtDpcLevel,1)
+	(NT_SPIN_LOCK *lock)
+{
+	ENTER6("%p", lock);
+	nt_spin_lock(lock);
+}
+
+wstdcall void WIN_FUNC(KeReleaseSpinLockFromDpcLevel,1)
+	(NT_SPIN_LOCK *lock)
+{
+	ENTER6("%p", lock);
+	nt_spin_unlock(lock);
+}
+
+wstdcall void WIN_FUNC(KeRaiseIrql,2)
+	(KIRQL newirql, KIRQL *oldirql)
+{
+	ENTER6("%d", newirql);
+	*oldirql = raise_irql(newirql);
+}
+
+wstdcall KIRQL WIN_FUNC(KeRaiseIrqlToDpcLevel,0)
+	(void)
+{
+	return raise_irql(DISPATCH_LEVEL);
+}
+
+wstdcall void WIN_FUNC(KeLowerIrql,1)
+	(KIRQL irql)
+{
+	ENTER6("%d", irql);
+	lower_irql(irql);
+}
+
+wstdcall KIRQL WIN_FUNC(KeAcquireSpinLockRaiseToDpc,1)
+	(NT_SPIN_LOCK *lock)
+{
+	ENTER6("%p", lock);
+	return nt_spin_lock_irql(lock, DISPATCH_LEVEL);
+}
+
+#undef ExAllocatePoolWithTag
+
+wstdcall void *WIN_FUNC(ExAllocatePoolWithTag,3)
+	(enum pool_type pool_type, SIZE_T size, ULONG tag)
+{
+	void *addr;
+
+	ENTER4("pool_type: %d, size: %lu, tag: 0x%x", pool_type, size, tag);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	if (size < PAGE_SIZE)
+		addr = kmalloc(size, irql_gfp());
+	else {
+		if (irql_gfp() & GFP_ATOMIC) {
+			addr = __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM,
+					 PAGE_KERNEL);
+			TRACE1("%p, %lu", addr, size);
+		} else {
+			addr = vmalloc(size);
+			TRACE1("%p, %lu", addr, size);
+		}
+	}
+	DBG_BLOCK(1) {
+		if (addr)
+			TRACE4("addr: %p, %lu", addr, size);
+		else
+			TRACE1("failed: %lu", size);
+	}
+	return addr;
+}
+WIN_FUNC_DECL(ExAllocatePoolWithTag,3)
+
+wstdcall void WIN_FUNC(ExFreePoolWithTag,2)
+	(void *addr, ULONG tag)
+{
+	TRACE4("%p", addr);
+	if ((unsigned long)addr < VMALLOC_START ||
+	    (unsigned long)addr >= VMALLOC_END)
+		kfree(addr);
+	else
+		vfree(addr);
+
+	EXIT4(return);
+}
+
+wstdcall void WIN_FUNC(ExFreePool,1)
+	(void *addr)
+{
+	ExFreePoolWithTag(addr, 0);
+}
+WIN_FUNC_DECL(ExFreePool,1)
+
+wstdcall void WIN_FUNC(ExInitializeNPagedLookasideList,7)
+	(struct npaged_lookaside_list *lookaside,
+	 LOOKASIDE_ALLOC_FUNC *alloc_func, LOOKASIDE_FREE_FUNC *free_func,
+	 ULONG flags, SIZE_T size, ULONG tag, USHORT depth)
+{
+	ENTER3("lookaside: %p, size: %lu, flags: %u, head: %p, "
+	       "alloc: %p, free: %p", lookaside, size, flags,
+	       lookaside, alloc_func, free_func);
+
+	memset(lookaside, 0, sizeof(*lookaside));
+
+	lookaside->size = size;
+	lookaside->tag = tag;
+	lookaside->depth = 4;
+	lookaside->maxdepth = 256;
+	lookaside->pool_type = NonPagedPool;
+
+	if (alloc_func)
+		lookaside->alloc_func = alloc_func;
+	else
+		lookaside->alloc_func = WIN_FUNC_PTR(ExAllocatePoolWithTag,3);
+	if (free_func)
+		lookaside->free_func = free_func;
+	else
+		lookaside->free_func = WIN_FUNC_PTR(ExFreePool,1);
+
+#ifndef CONFIG_X86_64
+	nt_spin_lock_init(&lookaside->obsolete);
+#endif
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(ExDeleteNPagedLookasideList,1)
+	(struct npaged_lookaside_list *lookaside)
+{
+	struct nt_slist *entry;
+
+	ENTER3("lookaside = %p", lookaside);
+	while ((entry = ExpInterlockedPopEntrySList(&lookaside->head)))
+		LIN2WIN1(lookaside->free_func, entry);
+	EXIT3(return);
+}
+
+#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1
+#define ExAllocatePoolWithTag(pool_type, size, tag)			\
+	wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__)
+#endif
+
+wstdcall NTSTATUS WIN_FUNC(ExCreateCallback,4)
+	(struct callback_object **object, struct object_attributes *attributes,
+	 BOOLEAN create, BOOLEAN allow_multiple_callbacks)
+{
+	struct callback_object *obj;
+
+	ENTER2("");
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(obj, &callback_objects, callback_funcs) {
+		if (obj->attributes == attributes) {
+			spin_unlock_bh(&ntoskernel_lock);
+			*object = obj;
+			return STATUS_SUCCESS;
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	obj = allocate_object(sizeof(struct callback_object),
+			      OBJECT_TYPE_CALLBACK, NULL);
+	if (!obj)
+		EXIT2(return STATUS_INSUFFICIENT_RESOURCES);
+	InitializeListHead(&obj->callback_funcs);
+	nt_spin_lock_init(&obj->lock);
+	obj->allow_multiple_callbacks = allow_multiple_callbacks;
+	obj->attributes = attributes;
+	*object = obj;
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall void *WIN_FUNC(ExRegisterCallback,3)
+	(struct callback_object *object, PCALLBACK_FUNCTION func, void *context)
+{
+	struct callback_func *callback;
+	KIRQL irql;
+
+	ENTER2("");
+	irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
+	if (object->allow_multiple_callbacks == FALSE &&
+	    !IsListEmpty(&object->callback_funcs)) {
+		nt_spin_unlock_irql(&object->lock, irql);
+		EXIT2(return NULL);
+	}
+	nt_spin_unlock_irql(&object->lock, irql);
+	callback = kmalloc(sizeof(*callback), GFP_KERNEL);
+	if (!callback) {
+		ERROR("couldn't allocate memory");
+		return NULL;
+	}
+	callback->func = func;
+	callback->context = context;
+	callback->object = object;
+	irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
+	InsertTailList(&object->callback_funcs, &callback->list);
+	nt_spin_unlock_irql(&object->lock, irql);
+	EXIT2(return callback);
+}
+
+wstdcall void WIN_FUNC(ExUnregisterCallback,1)
+	(struct callback_func *callback)
+{
+	struct callback_object *object;
+	KIRQL irql;
+
+	ENTER3("%p", callback);
+	if (!callback)
+		return;
+	object = callback->object;
+	irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
+	RemoveEntryList(&callback->list);
+	nt_spin_unlock_irql(&object->lock, irql);
+	kfree(callback);
+	return;
+}
+
+wstdcall void WIN_FUNC(ExNotifyCallback,3)
+	(struct callback_object *object, void *arg1, void *arg2)
+{
+	struct callback_func *callback;
+	KIRQL irql;
+
+	ENTER3("%p", object);
+	irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL);
+	nt_list_for_each_entry(callback, &object->callback_funcs, list) {
+		LIN2WIN3(callback->func, callback->context, arg1, arg2);
+	}
+	nt_spin_unlock_irql(&object->lock, irql);
+	return;
+}
+
+/* check and set signaled state; should be called with dispatcher_lock held */
+/* @grab indicates if the event should be grabbed or checked
+ * - note that a semaphore may stay in signaled state for multiple
+ * 'grabs' if the count is > 1 */
+static int grab_object(struct dispatcher_header *dh,
+		       struct task_struct *thread, int grab)
+{
+	EVENTTRACE("%p, %p, %d, %d", dh, thread, grab, dh->signal_state);
+	if (unlikely(is_mutex_object(dh))) {
+		struct nt_mutex *nt_mutex;
+		nt_mutex = container_of(dh, struct nt_mutex, dh);
+		EVENTTRACE("%p, %p, %d, %p, %d", nt_mutex,
+			   nt_mutex->owner_thread, dh->signal_state,
+			   thread, grab);
+		/* either no thread owns the mutex or this thread owns
+		 * it */
+		assert(dh->signal_state == 1 && nt_mutex->owner_thread == NULL);
+		assert(dh->signal_state < 1 && nt_mutex->owner_thread != NULL);
+		if ((dh->signal_state == 1 && nt_mutex->owner_thread == NULL) ||
+		    nt_mutex->owner_thread == thread) {
+			if (grab) {
+				dh->signal_state--;
+				nt_mutex->owner_thread = thread;
+			}
+			EVENTEXIT(return 1);
+		}
+	} else if (dh->signal_state > 0) {
+		/* to grab, decrement signal_state for synchronization
+		 * or semaphore objects */
+		if (grab && (is_synch_object(dh) || is_semaphore_object(dh)))
+			dh->signal_state--;
+		EVENTEXIT(return 1);
+	}
+	EVENTEXIT(return 0);
+}
+
+/* this function should be called holding dispatcher_lock */
+static void object_signalled(struct dispatcher_header *dh)
+{
+	struct nt_list *cur, *next;
+	struct wait_block *wb;
+
+	EVENTENTER("%p", dh);
+	nt_list_for_each_safe(cur, next, &dh->wait_blocks) {
+		wb = container_of(cur, struct wait_block, list);
+		assert(wb->thread != NULL);
+		assert(wb->object == NULL);
+		if (!grab_object(dh, wb->thread, 1))
+			continue;
+		EVENTTRACE("%p (%p): waking %p", dh, wb, wb->thread);
+		RemoveEntryList(cur);
+		wb->object = dh;
+		*(wb->wait_done) = 1;
+		wake_up_process(wb->thread);
+	}
+	EVENTEXIT(return);
+}
+
+wstdcall NTSTATUS WIN_FUNC(KeWaitForMultipleObjects,8)
+	(ULONG count, void *object[], enum wait_type wait_type,
+	 KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode,
+	 BOOLEAN alertable, LARGE_INTEGER *timeout,
+	 struct wait_block *wait_block_array)
+{
+	int i, res = 0, wait_count, wait_done;
+	typeof(jiffies) wait_hz = 0;
+	struct wait_block *wb, wb_array[THREAD_WAIT_OBJECTS];
+	struct dispatcher_header *dh;
+
+	EVENTENTER("%p, %d, %u, %p", current, count, wait_type, timeout);
+
+	if (count > MAX_WAIT_OBJECTS ||
+	    (count > THREAD_WAIT_OBJECTS && wait_block_array == NULL))
+		EVENTEXIT(return STATUS_INVALID_PARAMETER);
+
+	if (wait_block_array == NULL)
+		wb = wb_array;
+	else
+		wb = wait_block_array;
+
+	/* If *timeout == 0: In the case of WaitAny, if an object can
+	 * be grabbed (object is in signaled state), grab and
+	 * return. In the case of WaitAll, we have to first make sure
+	 * all objects can be grabbed. If any/some of them can't be
+	 * grabbed, either we return STATUS_TIMEOUT or wait for them,
+	 * depending on how to satisfy wait. If all of them can be
+	 * grabbed, we will grab them in the next loop below */
+
+	spin_lock_bh(&dispatcher_lock);
+	for (i = wait_count = 0; i < count; i++) {
+		dh = object[i];
+		EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state);
+		/* wait_type == 1 for WaitAny, 0 for WaitAll */
+		if (grab_object(dh, current, wait_type)) {
+			if (wait_type == WaitAny) {
+				spin_unlock_bh(&dispatcher_lock);
+				EVENTEXIT(return STATUS_WAIT_0 + i);
+			}
+		} else {
+			EVENTTRACE("%p: wait for %p", current, dh);
+			wait_count++;
+		}
+	}
+
+	if (timeout && *timeout == 0 && wait_count) {
+		spin_unlock_bh(&dispatcher_lock);
+		EVENTEXIT(return STATUS_TIMEOUT);
+	}
+
+	/* get the list of objects the thread needs to wait on and add
+	 * the thread on the wait list for each such object */
+	/* if *timeout == 0, this step will grab all the objects */
+	wait_done = 0;
+	for (i = 0; i < count; i++) {
+		dh = object[i];
+		EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state);
+		wb[i].object = NULL;
+		if (grab_object(dh, current, 1)) {
+			EVENTTRACE("%p: no wait for %p (%d)",
+				   current, dh, dh->signal_state);
+			/* mark that we are not waiting on this object */
+			wb[i].thread = NULL;
+		} else {
+			wb[i].wait_done = &wait_done;
+			wb[i].thread = current;
+			EVENTTRACE("%p: wait for %p", current, dh);
+			InsertTailList(&dh->wait_blocks, &wb[i].list);
+		}
+	}
+	spin_unlock_bh(&dispatcher_lock);
+	if (wait_count == 0)
+		EVENTEXIT(return STATUS_SUCCESS);
+
+	assert(timeout == NULL || *timeout != 0);
+	if (timeout == NULL)
+		wait_hz = 0;
+	else
+		wait_hz = SYSTEM_TIME_TO_HZ(*timeout);
+
+	DBG_BLOCK(2) {
+		KIRQL irql = current_irql();
+		if (irql >= DISPATCH_LEVEL) {
+			TRACE2("wait in atomic context: %lu, %d, %ld",
+			       wait_hz, in_atomic(), in_interrupt());
+		}
+	}
+	assert_irql(_irql_ < DISPATCH_LEVEL);
+	EVENTTRACE("%p: sleep for %ld on %p", current, wait_hz, &wait_done);
+	/* we don't honor 'alertable' - according to decription for
+	 * this, even if waiting in non-alertable state, thread may be
+	 * alerted in some circumstances */
+	while (wait_count) {
+		res = wait_condition(wait_done, wait_hz, TASK_INTERRUPTIBLE);
+		spin_lock_bh(&dispatcher_lock);
+		EVENTTRACE("%p woke up: %d, %d", current, res, wait_done);
+		/* the event may have been set by the time
+		 * wrap_wait_event returned and spinlock obtained, so
+		 * don't rely on value of 'res' - check event status */
+		if (!wait_done) {
+			assert(res <= 0);
+			/* timed out or interrupted; remove from wait list */
+			for (i = 0; i < count; i++) {
+				if (!wb[i].thread)
+					continue;
+				EVENTTRACE("%p: timedout, dequeue %p (%p)",
+					   current, object[i], wb[i].object);
+				assert(wb[i].object == NULL);
+				RemoveEntryList(&wb[i].list);
+			}
+			spin_unlock_bh(&dispatcher_lock);
+			if (res < 0)
+				EVENTEXIT(return STATUS_ALERTED);
+			else
+				EVENTEXIT(return STATUS_TIMEOUT);
+		}
+		assert(res > 0);
+		/* woken because object(s) signalled */
+		for (i = 0; wait_count && i < count; i++) {
+			if (!wb[i].thread || !wb[i].object)
+				continue;
+			DBG_BLOCK(1) {
+				if (wb[i].object != object[i]) {
+					EVENTTRACE("oops %p != %p",
+						   wb[i].object, object[i]);
+					continue;
+				}
+			}
+			wait_count--;
+			if (wait_type == WaitAny) {
+				int j;
+				/* done; remove from rest of wait list */
+				for (j = i + 1; j < count; j++) {
+					if (wb[j].thread && !wb[j].object)
+						RemoveEntryList(&wb[j].list);
+				}
+				spin_unlock_bh(&dispatcher_lock);
+				EVENTEXIT(return STATUS_WAIT_0 + i);
+			}
+		}
+		wait_done = 0;
+		spin_unlock_bh(&dispatcher_lock);
+		if (wait_count == 0)
+			EVENTEXIT(return STATUS_SUCCESS);
+
+		/* this thread is still waiting for more objects, so
+		 * let it wait for remaining time and those objects */
+		if (timeout)
+			wait_hz = res;
+		else
+			wait_hz = 0;
+	}
+	/* should never reach here, but compiler wants return value */
+	ERROR("%p: wait_hz: %ld", current, wait_hz);
+	EVENTEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(KeWaitForSingleObject,5)
+	(void *object, KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode,
+	 BOOLEAN alertable, LARGE_INTEGER *timeout)
+{
+	return KeWaitForMultipleObjects(1, &object, WaitAny, wait_reason,
+					wait_mode, alertable, timeout, NULL);
+}
+
+wstdcall void WIN_FUNC(KeInitializeEvent,3)
+	(struct nt_event *nt_event, enum event_type type, BOOLEAN state)
+{
+	EVENTENTER("event = %p, type = %d, state = %d", nt_event, type, state);
+	initialize_object(&nt_event->dh, type, state);
+	EVENTEXIT(return);
+}
+
+wstdcall LONG WIN_FUNC(KeSetEvent,3)
+	(struct nt_event *nt_event, KPRIORITY incr, BOOLEAN wait)
+{
+	LONG old_state;
+
+	EVENTENTER("%p, %d", nt_event, nt_event->dh.type);
+	if (wait == TRUE)
+		WARNING("wait = %d, not yet implemented", wait);
+	spin_lock_bh(&dispatcher_lock);
+	old_state = nt_event->dh.signal_state;
+	nt_event->dh.signal_state = 1;
+	if (old_state == 0)
+		object_signalled(&nt_event->dh);
+	spin_unlock_bh(&dispatcher_lock);
+	EVENTEXIT(return old_state);
+}
+
+wstdcall void WIN_FUNC(KeClearEvent,1)
+	(struct nt_event *nt_event)
+{
+	EVENTENTER("%p", nt_event);
+	nt_event->dh.signal_state = 0;
+	EVENTEXIT(return);
+}
+
+wstdcall LONG WIN_FUNC(KeResetEvent,1)
+	(struct nt_event *nt_event)
+{
+	LONG old_state;
+
+	EVENTENTER("%p", nt_event);
+	old_state = xchg(&nt_event->dh.signal_state, 0);
+	EVENTEXIT(return old_state);
+}
+
+wstdcall LONG WIN_FUNC(KeReadStateEvent,1)
+	(struct nt_event *nt_event)
+{
+	LONG state;
+
+	state = nt_event->dh.signal_state;
+	EVENTTRACE("%d", state);
+	return state;
+}
+
+wstdcall void WIN_FUNC(KeInitializeMutex,2)
+	(struct nt_mutex *mutex, ULONG level)
+{
+	EVENTENTER("%p", mutex);
+	initialize_object(&mutex->dh, MutexObject, 1);
+	mutex->dh.size = sizeof(*mutex);
+	InitializeListHead(&mutex->list);
+	mutex->abandoned = FALSE;
+	mutex->apc_disable = 1;
+	mutex->owner_thread = NULL;
+	EVENTEXIT(return);
+}
+
+wstdcall LONG WIN_FUNC(KeReleaseMutex,2)
+	(struct nt_mutex *mutex, BOOLEAN wait)
+{
+	LONG ret;
+	struct task_struct *thread;
+
+	EVENTENTER("%p, %d, %p", mutex, wait, current);
+	if (wait == TRUE)
+		WARNING("wait: %d", wait);
+	thread = current;
+	spin_lock_bh(&dispatcher_lock);
+	EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread,
+		   mutex->dh.signal_state);
+	if ((mutex->owner_thread == thread) && (mutex->dh.signal_state <= 0)) {
+		ret = mutex->dh.signal_state++;
+		if (ret == 0) {
+			mutex->owner_thread = NULL;
+			object_signalled(&mutex->dh);
+		}
+	} else {
+		ret = STATUS_MUTANT_NOT_OWNED;
+		WARNING("invalid mutex: %p, %p, %p", mutex, mutex->owner_thread,
+			thread);
+	}
+	EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread,
+		   mutex->dh.signal_state);
+	spin_unlock_bh(&dispatcher_lock);
+	EVENTEXIT(return ret);
+}
+
+wstdcall void WIN_FUNC(KeInitializeSemaphore,3)
+	(struct nt_semaphore *semaphore, LONG count, LONG limit)
+{
+	EVENTENTER("%p: %d", semaphore, count);
+	/* if limit > 1, we need to satisfy as many waits (until count
+	 * becomes 0); so we keep decrementing count everytime a wait
+	 * is satisified */
+	initialize_object(&semaphore->dh, SemaphoreObject, count);
+	semaphore->dh.size = sizeof(*semaphore);
+	semaphore->limit = limit;
+	EVENTEXIT(return);
+}
+
+wstdcall LONG WIN_FUNC(KeReleaseSemaphore,4)
+	(struct nt_semaphore *semaphore, KPRIORITY incr, LONG adjustment,
+	 BOOLEAN wait)
+{
+	LONG ret;
+
+	EVENTENTER("%p", semaphore);
+	spin_lock_bh(&dispatcher_lock);
+	ret = semaphore->dh.signal_state;
+	assert(ret >= 0);
+	if (semaphore->dh.signal_state + adjustment <= semaphore->limit)
+		semaphore->dh.signal_state += adjustment;
+	else {
+		WARNING("releasing %d over limit %d", adjustment,
+			semaphore->limit);
+		semaphore->dh.signal_state = semaphore->limit;
+	}
+	if (semaphore->dh.signal_state > 0)
+		object_signalled(&semaphore->dh);
+	spin_unlock_bh(&dispatcher_lock);
+	EVENTEXIT(return ret);
+}
+
+wstdcall NTSTATUS WIN_FUNC(KeDelayExecutionThread,3)
+	(KPROCESSOR_MODE wait_mode, BOOLEAN alertable, LARGE_INTEGER *interval)
+{
+	int res;
+	long timeout;
+
+	if (wait_mode != 0)
+		ERROR("invalid wait_mode %d", wait_mode);
+
+	timeout = SYSTEM_TIME_TO_HZ(*interval);
+	EVENTTRACE("%p, %Ld, %ld", current, *interval, timeout);
+	if (timeout <= 0)
+		EVENTEXIT(return STATUS_SUCCESS);
+
+	if (alertable)
+		set_current_state(TASK_INTERRUPTIBLE);
+	else
+		set_current_state(TASK_UNINTERRUPTIBLE);
+
+	res = schedule_timeout(timeout);
+	EVENTTRACE("%p, %d", current, res);
+	if (res == 0)
+		EVENTEXIT(return STATUS_SUCCESS);
+	else
+		EVENTEXIT(return STATUS_ALERTED);
+}
+
+wstdcall ULONGLONG WIN_FUNC(KeQueryInterruptTime,0)
+	(void)
+{
+	EXIT5(return jiffies * TICKSPERJIFFY);
+}
+
+wstdcall ULONG WIN_FUNC(KeQueryTimeIncrement,0)
+	(void)
+{
+	EXIT5(return TICKSPERSEC / HZ);
+}
+
+wstdcall void WIN_FUNC(KeQuerySystemTime,1)
+	(LARGE_INTEGER *time)
+{
+	*time = ticks_1601();
+	TRACE5("%Lu, %lu", *time, jiffies);
+}
+
+wstdcall void WIN_FUNC(KeQueryTickCount,1)
+	(LARGE_INTEGER *count)
+{
+	*count = jiffies;
+}
+
+wstdcall LARGE_INTEGER WIN_FUNC(KeQueryPerformanceCounter,1)
+	(LARGE_INTEGER *counter)
+{
+	if (counter)
+		*counter = HZ;
+	return jiffies;
+}
+
+wstdcall KAFFINITY WIN_FUNC(KeQueryActiveProcessors,0)
+	(void)
+{
+	int i, n;
+	KAFFINITY bits = 0;
+#ifdef num_online_cpus
+	n = num_online_cpus();
+#else
+	n = NR_CPUS;
+#endif
+	for (i = 0; i < n; i++)
+		bits = (bits << 1) | 1;
+	return bits;
+}
+
+struct nt_thread *get_current_nt_thread(void)
+{
+	struct task_struct *task = current;
+	struct nt_thread *thread;
+	struct common_object_header *header;
+
+	TRACE6("task: %p", task);
+	thread = NULL;
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(header, &object_list, list) {
+		TRACE6("%p, %d", header, header->type);
+		if (header->type != OBJECT_TYPE_NT_THREAD)
+			break;
+		thread = HEADER_TO_OBJECT(header);
+		TRACE6("%p, %p", thread, thread->task);
+		if (thread->task == task)
+			break;
+		else
+			thread = NULL;
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	if (thread == NULL)
+		TRACE4("couldn't find thread for task %p, %d", task, task->pid);
+	TRACE6("%p", thread);
+	return thread;
+}
+
+static struct task_struct *get_nt_thread_task(struct nt_thread *thread)
+{
+	struct task_struct *task;
+	struct common_object_header *header;
+
+	TRACE6("%p", thread);
+	task = NULL;
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(header, &object_list, list) {
+		TRACE6("%p, %d", header, header->type);
+		if (header->type != OBJECT_TYPE_NT_THREAD)
+			break;
+		if (thread == HEADER_TO_OBJECT(header)) {
+			task = thread->task;
+			break;
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	if (task == NULL)
+		TRACE2("%p: couldn't find task for %p", current, thread);
+	return task;
+}
+
+static struct nt_thread *create_nt_thread(struct task_struct *task)
+{
+	struct nt_thread *thread;
+	thread = allocate_object(sizeof(*thread), OBJECT_TYPE_NT_THREAD, NULL);
+	if (!thread) {
+		ERROR("couldn't allocate thread object");
+		EXIT2(return NULL);
+	}
+	thread->task = task;
+	if (task)
+		thread->pid = task->pid;
+	else
+		thread->pid = 0;
+	nt_spin_lock_init(&thread->lock);
+	InitializeListHead(&thread->irps);
+	initialize_object(&thread->dh, ThreadObject, 0);
+	thread->dh.size = sizeof(*thread);
+	thread->prio = LOW_PRIORITY;
+	return thread;
+}
+
+wstdcall struct nt_thread *WIN_FUNC(KeGetCurrentThread,0)
+	(void)
+{
+	struct nt_thread *thread = get_current_nt_thread();
+	TRACE2("%p, %p", thread, current);
+	return thread;
+}
+
+wstdcall KPRIORITY WIN_FUNC(KeQueryPriorityThread,1)
+	(struct nt_thread *thread)
+{
+	KPRIORITY prio;
+	struct task_struct *task;
+
+	TRACE2("%p", thread);
+#ifdef CONFIG_X86_64
+	/* sis163u driver for amd64 passes 0x1f from thread created by
+	 * PsCreateSystemThread - no idea what is 0x1f */
+	if (thread == (void *)0x1f)
+		thread = get_current_nt_thread();
+#endif
+	if (!thread) {
+		TRACE2("invalid thread");
+		EXIT2(return LOW_REALTIME_PRIORITY);
+	}
+	task = get_nt_thread_task(thread);
+	if (!task) {
+		TRACE2("couldn't find task for thread: %p", thread);
+		EXIT2(return LOW_REALTIME_PRIORITY);
+	}
+
+	prio = thread->prio;
+
+	TRACE2("%d", prio);
+	return prio;
+}
+
+wstdcall KPRIORITY WIN_FUNC(KeSetPriorityThread,2)
+	(struct nt_thread *thread, KPRIORITY prio)
+{
+	KPRIORITY old_prio;
+	struct task_struct *task;
+
+	TRACE2("thread: %p, priority = %u", thread, prio);
+#ifdef CONFIG_X86_64
+	if (thread == (void *)0x1f)
+		thread = get_current_nt_thread();
+#endif
+	if (!thread) {
+		TRACE2("invalid thread");
+		EXIT2(return LOW_REALTIME_PRIORITY);
+	}
+	task = get_nt_thread_task(thread);
+	if (!task) {
+		TRACE2("couldn't find task for thread: %p", thread);
+		EXIT2(return LOW_REALTIME_PRIORITY);
+	}
+
+	old_prio = thread->prio;
+	thread->prio = prio;
+
+	TRACE2("%d, %d", old_prio, thread->prio);
+	return old_prio;
+}
+
+struct thread_trampoline {
+	void (*func)(void *) wstdcall;
+	void *ctx;
+	struct nt_thread *thread;
+	struct completion started;
+};
+
+static int ntdriver_thread(void *data)
+{
+	struct thread_trampoline *thread_tramp = data;
+	/* yes, a tramp! */
+	typeof(thread_tramp->func) func = thread_tramp->func;
+	typeof(thread_tramp->ctx) ctx = thread_tramp->ctx;
+
+	thread_tramp->thread->task = current;
+	thread_tramp->thread->pid = current->pid;
+	TRACE2("thread: %p, task: %p (%d)", thread_tramp->thread,
+	       current, current->pid);
+	complete(&thread_tramp->started);
+
+#ifdef PF_NOFREEZE
+	current->flags |= PF_NOFREEZE;
+#endif
+	strncpy(current->comm, "ntdriver", sizeof(current->comm));
+	current->comm[sizeof(current->comm)-1] = 0;
+	LIN2WIN1(func, ctx);
+	ERROR("task: %p", current);
+	return 0;
+}
+
+wstdcall NTSTATUS WIN_FUNC(PsCreateSystemThread,7)
+	(void **handle, ULONG access, void *obj_attr, void *process,
+	 void *client_id, void (*func)(void *) wstdcall, void *ctx)
+{
+	struct thread_trampoline thread_tramp;
+
+	ENTER2("handle = %p, access = %u, obj_attr = %p, process = %p, "
+	       "client_id = %p, func = %p, context = %p", handle, access,
+	       obj_attr, process, client_id, func, ctx);
+
+	thread_tramp.thread = create_nt_thread(NULL);
+	if (!thread_tramp.thread) {
+		ERROR("couldn't allocate thread object");
+		EXIT2(return STATUS_RESOURCES);
+	}
+	TRACE2("thread: %p", thread_tramp.thread);
+	thread_tramp.func = func;
+	thread_tramp.ctx = ctx;
+	init_completion(&thread_tramp.started);
+
+	thread_tramp.thread->task = kthread_run(ntdriver_thread,
+						&thread_tramp, "ntdriver");
+	if (IS_ERR(thread_tramp.thread->task)) {
+		free_object(thread_tramp.thread);
+		EXIT2(return STATUS_FAILURE);
+	}
+	TRACE2("created task: %p", thread_tramp.thread->task);
+
+	wait_for_completion(&thread_tramp.started);
+	*handle = OBJECT_TO_HEADER(thread_tramp.thread);
+	TRACE2("created thread: %p, %p", thread_tramp.thread, *handle);
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(PsTerminateSystemThread,1)
+	(NTSTATUS status)
+{
+	struct nt_thread *thread;
+
+	TRACE2("%p, %08X", current, status);
+	thread = get_current_nt_thread();
+	TRACE2("%p", thread);
+	if (thread) {
+		KeSetEvent((struct nt_event *)&thread->dh, 0, FALSE);
+		while (1) {
+			struct nt_list *ent;
+			struct irp *irp;
+			KIRQL irql;
+			irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
+			ent = RemoveHeadList(&thread->irps);
+			nt_spin_unlock_irql(&thread->lock, irql);
+			if (!ent)
+				break;
+			irp = container_of(ent, struct irp, thread_list);
+			IOTRACE("%p", irp);
+			IoCancelIrp(irp);
+		}
+		/* the driver may later query this status with
+		 * ZwQueryInformationThread */
+		thread->status = status;
+	} else
+		ERROR("couldn't find thread for task: %p", current);
+
+	complete_and_exit(NULL, status);
+	ERROR("oops: %p, %d", thread->task, thread->pid);
+	return STATUS_FAILURE;
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeRemoveEntryDeviceQueue,2)
+	(struct kdevice_queue *dev_queue, struct kdevice_queue_entry *entry)
+{
+	struct kdevice_queue_entry *e;
+	KIRQL irql;
+
+	irql = nt_spin_lock_irql(&dev_queue->lock, DISPATCH_LEVEL);
+	nt_list_for_each_entry(e, &dev_queue->list, list) {
+		if (e == entry) {
+			RemoveEntryList(&e->list);
+			nt_spin_unlock_irql(&dev_queue->lock, irql);
+			return TRUE;
+		}
+	}
+	nt_spin_unlock_irql(&dev_queue->lock, irql);
+	return FALSE;
+}
+
+wstdcall BOOLEAN WIN_FUNC(KeSynchronizeExecution,3)
+	(struct kinterrupt *interrupt, PKSYNCHRONIZE_ROUTINE synch_routine,
+	 void *ctx)
+{
+	BOOLEAN ret;
+	unsigned long flags;
+
+	nt_spin_lock_irqsave(interrupt->actual_lock, flags);
+	ret = LIN2WIN1(synch_routine, ctx);
+	nt_spin_unlock_irqrestore(interrupt->actual_lock, flags);
+	TRACE6("%d", ret);
+	return ret;
+}
+
+wstdcall void *WIN_FUNC(MmAllocateContiguousMemorySpecifyCache,5)
+	(SIZE_T size, PHYSICAL_ADDRESS lowest, PHYSICAL_ADDRESS highest,
+	 PHYSICAL_ADDRESS boundary, enum memory_caching_type cache_type)
+{
+	void *addr;
+	gfp_t flags;
+
+	ENTER2("%lu, 0x%lx, 0x%lx, 0x%lx, %d", size, (long)lowest,
+	       (long)highest, (long)boundary, cache_type);
+	flags = irql_gfp();
+	addr = wrap_get_free_pages(flags, size);
+	TRACE2("%p, %lu, 0x%x", addr, size, flags);
+	if (addr && ((virt_to_phys(addr) + size) <= highest))
+		EXIT2(return addr);
+#ifdef CONFIG_X86_64
+	/* GFP_DMA is really only 16MB even on x86-64, but there is no
+	 * other zone available */
+	if (highest <= DMA_BIT_MASK(31))
+		flags |= __GFP_DMA;
+	else if (highest <= DMA_BIT_MASK(32))
+		flags |= __GFP_DMA32;
+#else
+	if (highest <= DMA_BIT_MASK(24))
+		flags |= __GFP_DMA;
+	else if (highest > DMA_BIT_MASK(30))
+		flags |= __GFP_HIGHMEM;
+#endif
+	addr = wrap_get_free_pages(flags, size);
+	TRACE2("%p, %lu, 0x%x", addr, size, flags);
+	return addr;
+}
+
+wstdcall void WIN_FUNC(MmFreeContiguousMemorySpecifyCache,3)
+	(void *base, SIZE_T size, enum memory_caching_type cache_type)
+{
+	TRACE2("%p, %lu", base, size);
+	free_pages((unsigned long)base, get_order(size));
+}
+
+wstdcall PHYSICAL_ADDRESS WIN_FUNC(MmGetPhysicalAddress,1)
+	(void *base)
+{
+	unsigned long phy = virt_to_phys(base);
+	TRACE2("%p, %p", base, (void *)phy);
+	return phy;
+}
+
+/* Atheros card with pciid 168C:0014 calls this function with 0xf0000
+ * and 0xf6ef0 address, and then check for things that seem to be
+ * related to ACPI: "_SM_" and "_DMI_". This may be the hack they do
+ * to check if this card is installed in IBM thinkpads; we can
+ * probably get this device to work if we create a buffer with the
+ * strings as required by the driver and return virtual address for
+ * that address instead */
+wstdcall void __iomem *WIN_FUNC(MmMapIoSpace,3)
+	(PHYSICAL_ADDRESS phys_addr, SIZE_T size,
+	 enum memory_caching_type cache)
+{
+	void __iomem *virt;
+	ENTER1("cache type: %d", cache);
+	if (cache == MmCached)
+		virt = ioremap(phys_addr, size);
+	else
+		virt = ioremap_nocache(phys_addr, size);
+	TRACE1("%Lx, %lu, %p", phys_addr, size, virt);
+	return virt;
+}
+
+wstdcall void WIN_FUNC(MmUnmapIoSpace,2)
+	(void __iomem *addr, SIZE_T size)
+{
+	ENTER1("%p, %lu", addr, size);
+	iounmap(addr);
+	return;
+}
+
+wstdcall ULONG WIN_FUNC(MmSizeOfMdl,2)
+	(void *base, ULONG length)
+{
+	return sizeof(struct mdl) +
+	       (sizeof(PFN_NUMBER) * SPAN_PAGES(base, length));
+}
+
+struct mdl *allocate_init_mdl(void *virt, ULONG length)
+{
+	struct wrap_mdl *wrap_mdl;
+	struct mdl *mdl;
+	int mdl_size = MmSizeOfMdl(virt, length);
+
+	if (mdl_size <= MDL_CACHE_SIZE) {
+		wrap_mdl = kmem_cache_alloc(mdl_cache, irql_gfp());
+		if (!wrap_mdl)
+			return NULL;
+		spin_lock_bh(&dispatcher_lock);
+		InsertHeadList(&wrap_mdl_list, &wrap_mdl->list);
+		spin_unlock_bh(&dispatcher_lock);
+		mdl = wrap_mdl->mdl;
+		TRACE3("allocated mdl from cache: %p(%p), %p(%d)",
+		       wrap_mdl, mdl, virt, length);
+		memset(mdl, 0, MDL_CACHE_SIZE);
+		MmInitializeMdl(mdl, virt, length);
+		/* mark the MDL as allocated from cache pool so when
+		 * it is freed, we free it back to the pool */
+		mdl->flags = MDL_ALLOCATED_FIXED_SIZE | MDL_CACHE_ALLOCATED;
+	} else {
+		wrap_mdl =
+			kmalloc(sizeof(*wrap_mdl) + mdl_size, irql_gfp());
+		if (!wrap_mdl)
+			return NULL;
+		mdl = wrap_mdl->mdl;
+		TRACE3("allocated mdl from memory: %p(%p), %p(%d)",
+		       wrap_mdl, mdl, virt, length);
+		spin_lock_bh(&dispatcher_lock);
+		InsertHeadList(&wrap_mdl_list, &wrap_mdl->list);
+		spin_unlock_bh(&dispatcher_lock);
+		memset(mdl, 0, mdl_size);
+		MmInitializeMdl(mdl, virt, length);
+		mdl->flags = MDL_ALLOCATED_FIXED_SIZE;
+	}
+	return mdl;
+}
+
+void free_mdl(struct mdl *mdl)
+{
+	/* A driver may allocate Mdl with NdisAllocateBuffer and free
+	 * with IoFreeMdl (e.g., 64-bit Broadcom). Since we need to
+	 * treat buffers allocated with Ndis calls differently, we
+	 * must call NdisFreeBuffer if it is allocated with Ndis
+	 * function. We set 'pool' field in Ndis functions. */
+	if (!mdl)
+		return;
+	if (mdl->pool)
+		NdisFreeBuffer(mdl);
+	else {
+		struct wrap_mdl *wrap_mdl = (struct wrap_mdl *)
+			((char *)mdl - offsetof(struct wrap_mdl, mdl));
+		spin_lock_bh(&dispatcher_lock);
+		RemoveEntryList(&wrap_mdl->list);
+		spin_unlock_bh(&dispatcher_lock);
+
+		if (mdl->flags & MDL_CACHE_ALLOCATED) {
+			TRACE3("freeing mdl cache: %p, %p, %p",
+			       wrap_mdl, mdl, mdl->mappedsystemva);
+			kmem_cache_free(mdl_cache, wrap_mdl);
+		} else {
+			TRACE3("freeing mdl: %p, %p, %p",
+			       wrap_mdl, mdl, mdl->mappedsystemva);
+			kfree(wrap_mdl);
+		}
+	}
+	return;
+}
+
+wstdcall void WIN_FUNC(IoBuildPartialMdl,4)
+	(struct mdl *source, struct mdl *target, void *virt, ULONG length)
+{
+	MmInitializeMdl(target, virt, length);
+	target->flags |= MDL_PARTIAL;
+}
+
+wstdcall void WIN_FUNC(MmBuildMdlForNonPagedPool,1)
+	(struct mdl *mdl)
+{
+	PFN_NUMBER *mdl_pages;
+	int i, n;
+
+	ENTER4("%p", mdl);
+	/* already mapped */
+//	mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl);
+	mdl->flags |= MDL_SOURCE_IS_NONPAGED_POOL;
+	TRACE4("%p, %p, %p, %d, %d", mdl, mdl->mappedsystemva, mdl->startva,
+	       mdl->byteoffset, mdl->bytecount);
+	n = SPAN_PAGES(MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl));
+	if (n > MDL_CACHE_PAGES)
+		WARNING("%p, %d, %d", MmGetSystemAddressForMdl(mdl),
+			MmGetMdlByteCount(mdl), n);
+	mdl_pages = MmGetMdlPfnArray(mdl);
+	for (i = 0; i < n; i++)
+		mdl_pages[i] = (ULONG_PTR)mdl->startva + (i * PAGE_SIZE);
+	EXIT4(return);
+}
+
+wstdcall void *WIN_FUNC(MmMapLockedPages,2)
+	(struct mdl *mdl, KPROCESSOR_MODE access_mode)
+{
+	/* already mapped */
+//	mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl);
+	mdl->flags |= MDL_MAPPED_TO_SYSTEM_VA;
+	/* what is the need for MDL_PARTIAL_HAS_BEEN_MAPPED? */
+	if (mdl->flags & MDL_PARTIAL)
+		mdl->flags |= MDL_PARTIAL_HAS_BEEN_MAPPED;
+	return mdl->mappedsystemva;
+}
+
+wstdcall void *WIN_FUNC(MmMapLockedPagesSpecifyCache,6)
+	(struct mdl *mdl, KPROCESSOR_MODE access_mode,
+	 enum memory_caching_type cache_type, void *base_address,
+	 ULONG bug_check, enum mm_page_priority priority)
+{
+	return MmMapLockedPages(mdl, access_mode);
+}
+
+wstdcall void WIN_FUNC(MmUnmapLockedPages,2)
+	(void *base, struct mdl *mdl)
+{
+	mdl->flags &= ~MDL_MAPPED_TO_SYSTEM_VA;
+	return;
+}
+
+wstdcall void WIN_FUNC(MmProbeAndLockPages,3)
+	(struct mdl *mdl, KPROCESSOR_MODE access_mode,
+	 enum lock_operation operation)
+{
+	/* already locked */
+	mdl->flags |= MDL_PAGES_LOCKED;
+	return;
+}
+
+wstdcall void WIN_FUNC(MmUnlockPages,1)
+	(struct mdl *mdl)
+{
+	mdl->flags &= ~MDL_PAGES_LOCKED;
+	return;
+}
+
+wstdcall BOOLEAN WIN_FUNC(MmIsAddressValid,1)
+	(void *virt_addr)
+{
+	if (virt_addr_valid(virt_addr))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+wstdcall void *WIN_FUNC(MmLockPagableDataSection,1)
+	(void *address)
+{
+	return address;
+}
+
+wstdcall void WIN_FUNC(MmUnlockPagableImageSection,1)
+	(void *handle)
+{
+	return;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ObReferenceObjectByHandle,6)
+	(void *handle, ACCESS_MASK desired_access, void *obj_type,
+	 KPROCESSOR_MODE access_mode, void **object, void *handle_info)
+{
+	struct common_object_header *hdr;
+
+	TRACE2("%p", handle);
+	hdr = HANDLE_TO_HEADER(handle);
+	atomic_inc_var(hdr->ref_count);
+	*object = HEADER_TO_OBJECT(hdr);
+	TRACE2("%p, %p, %d, %p", hdr, object, hdr->ref_count, *object);
+	return STATUS_SUCCESS;
+}
+
+/* DDK doesn't say if return value should be before incrementing or
+ * after incrementing reference count, but according to #reactos
+ * devels, it should be return value after incrementing */
+wfastcall LONG WIN_FUNC(ObfReferenceObject,1)
+	(void *object)
+{
+	struct common_object_header *hdr;
+	LONG ret;
+
+	hdr = OBJECT_TO_HEADER(object);
+	ret = post_atomic_add(hdr->ref_count, 1);
+	TRACE2("%p, %d, %p", hdr, hdr->ref_count, object);
+	return ret;
+}
+
+static int dereference_object(void *object)
+{
+	struct common_object_header *hdr;
+	int ref_count;
+
+	ENTER2("object: %p", object);
+	hdr = OBJECT_TO_HEADER(object);
+	TRACE2("hdr: %p", hdr);
+	ref_count = post_atomic_add(hdr->ref_count, -1);
+	TRACE2("object: %p, %d", object, ref_count);
+	if (ref_count < 0)
+		ERROR("invalid object: %p (%d)", object, ref_count);
+	if (ref_count <= 0) {
+		free_object(object);
+		return 1;
+	} else
+		return 0;
+}
+
+wfastcall void WIN_FUNC(ObfDereferenceObject,1)
+	(void *object)
+{
+	TRACE2("%p", object);
+	dereference_object(object);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwCreateFile,11)
+	(void **handle, ACCESS_MASK access_mask,
+	 struct object_attributes *obj_attr, struct io_status_block *iosb,
+	 LARGE_INTEGER *size, ULONG file_attr, ULONG share_access,
+	 ULONG create_disposition, ULONG create_options, void *ea_buffer,
+	 ULONG ea_length)
+{
+	struct common_object_header *coh;
+	struct file_object *fo;
+	struct ansi_string ansi;
+	struct wrap_bin_file *bin_file;
+	char *file_basename;
+	NTSTATUS status;
+
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(coh, &object_list, list) {
+		if (coh->type != OBJECT_TYPE_FILE)
+			continue;
+		/* TODO: check if file is opened in shared mode */
+		if (!RtlCompareUnicodeString(&coh->name, obj_attr->name, TRUE)) {
+			fo = HEADER_TO_OBJECT(coh);
+			bin_file = fo->wrap_bin_file;
+			*handle = coh;
+			spin_unlock_bh(&ntoskernel_lock);
+			ObReferenceObject(fo);
+			iosb->status = FILE_OPENED;
+			iosb->info = bin_file->size;
+			EXIT2(return STATUS_SUCCESS);
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+
+	if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) !=
+	    STATUS_SUCCESS)
+		EXIT2(return STATUS_INSUFFICIENT_RESOURCES);
+
+	file_basename = strrchr(ansi.buf, '\\');
+	if (file_basename)
+		file_basename++;
+	else
+		file_basename = ansi.buf;
+	TRACE2("file: '%s', '%s'", ansi.buf, file_basename);
+
+	fo = allocate_object(sizeof(struct file_object), OBJECT_TYPE_FILE,
+			     obj_attr->name);
+	if (!fo) {
+		RtlFreeAnsiString(&ansi);
+		iosb->status = STATUS_INSUFFICIENT_RESOURCES;
+		iosb->info = 0;
+		EXIT2(return STATUS_FAILURE);
+	}
+	coh = OBJECT_TO_HEADER(fo);
+	bin_file = get_bin_file(file_basename);
+	if (bin_file) {
+		TRACE2("%s, %s", bin_file->name, file_basename);
+		fo->flags = FILE_OPENED;
+	} else if (access_mask & FILE_WRITE_DATA) {
+		bin_file = kzalloc(sizeof(*bin_file), GFP_KERNEL);
+		if (bin_file) {
+			strncpy(bin_file->name, file_basename,
+				sizeof(bin_file->name));
+			bin_file->name[sizeof(bin_file->name)-1] = 0;
+			bin_file->data = vmalloc(*size);
+			if (bin_file->data) {
+				memset(bin_file->data, 0, *size);
+				bin_file->size = *size;
+				fo->flags = FILE_CREATED;
+			} else {
+				kfree(bin_file);
+				bin_file = NULL;
+			}
+		}
+	} else
+		bin_file = NULL;
+
+	RtlFreeAnsiString(&ansi);
+	if (!bin_file) {
+		iosb->status = FILE_DOES_NOT_EXIST;
+		iosb->info = 0;
+		free_object(fo);
+		EXIT2(return STATUS_FAILURE);
+	}
+
+	fo->wrap_bin_file = bin_file;
+	fo->current_byte_offset = 0;
+	if (access_mask & FILE_READ_DATA)
+		fo->read_access = TRUE;
+	if (access_mask & FILE_WRITE_DATA)
+		fo->write_access = TRUE;
+	iosb->status = FILE_OPENED;
+	iosb->info = bin_file->size;
+	*handle = coh;
+	TRACE2("handle: %p", *handle);
+	status = STATUS_SUCCESS;
+	EXIT2(return status);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwOpenFile,6)
+	(void **handle, ACCESS_MASK access_mask,
+	 struct object_attributes *obj_attr, struct io_status_block *iosb,
+	 ULONG share_access, ULONG open_options)
+{
+	LARGE_INTEGER size;
+	return ZwCreateFile(handle, access_mask, obj_attr, iosb, &size, 0,
+			    share_access, 0, open_options, NULL, 0);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwReadFile,9)
+	(void *handle, struct nt_event *event, void *apc_routine,
+	 void *apc_context, struct io_status_block *iosb, void *buffer,
+	 ULONG length, LARGE_INTEGER *byte_offset, ULONG *key)
+{
+	struct file_object *fo;
+	struct common_object_header *coh;
+	ULONG count;
+	size_t offset;
+	struct wrap_bin_file *file;
+
+	TRACE2("%p", handle);
+	coh = handle;
+	if (coh->type != OBJECT_TYPE_FILE) {
+		ERROR("handle %p is invalid: %d", handle, coh->type);
+		EXIT2(return STATUS_FAILURE);
+	}
+	fo = HANDLE_TO_OBJECT(coh);
+	file = fo->wrap_bin_file;
+	TRACE2("file: %s (%zu)", file->name, file->size);
+	spin_lock_bh(&ntoskernel_lock);
+	if (byte_offset)
+		offset = *byte_offset;
+	else
+		offset = fo->current_byte_offset;
+	count = min((size_t)length, file->size - offset);
+	TRACE2("count: %u, offset: %zu, length: %u", count, offset, length);
+	memcpy(buffer, ((void *)file->data) + offset, count);
+	fo->current_byte_offset = offset + count;
+	spin_unlock_bh(&ntoskernel_lock);
+	iosb->status = STATUS_SUCCESS;
+	iosb->info = count;
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,9)
+	(void *handle, struct nt_event *event, void *apc_routine,
+	 void *apc_context, struct io_status_block *iosb, void *buffer,
+	 ULONG length, LARGE_INTEGER *byte_offset, ULONG *key)
+{
+	struct file_object *fo;
+	struct common_object_header *coh;
+	struct wrap_bin_file *file;
+	unsigned long offset;
+
+	TRACE2("%p", handle);
+	coh = handle;
+	if (coh->type != OBJECT_TYPE_FILE) {
+		ERROR("handle %p is invalid: %d", handle, coh->type);
+		EXIT2(return STATUS_FAILURE);
+	}
+	fo = HANDLE_TO_OBJECT(coh);
+	file = fo->wrap_bin_file;
+	TRACE2("file: %zu, %u", file->size, length);
+	spin_lock_bh(&ntoskernel_lock);
+	if (byte_offset)
+		offset = *byte_offset;
+	else
+		offset = fo->current_byte_offset;
+	if (length + offset > file->size) {
+		WARNING("%lu, %u", length + offset, (unsigned int)file->size);
+		/* TODO: implement writing past end of current size */
+		iosb->status = STATUS_FAILURE;
+		iosb->info = 0;
+	} else {
+		memcpy(file->data + offset, buffer, length);
+		iosb->status = STATUS_SUCCESS;
+		iosb->info = length;
+		fo->current_byte_offset = offset + length;
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	EXIT2(return iosb->status);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwClose,1)
+	(void *handle)
+{
+	struct common_object_header *coh;
+
+	TRACE2("%p", handle);
+	if (handle == NULL) {
+		TRACE1("");
+		EXIT2(return STATUS_SUCCESS);
+	}
+	coh = handle;
+	if (coh->type == OBJECT_TYPE_FILE) {
+		struct file_object *fo;
+		struct wrap_bin_file *bin_file;
+		typeof(fo->flags) flags;
+
+		fo = HANDLE_TO_OBJECT(handle);
+		flags = fo->flags;
+		bin_file = fo->wrap_bin_file;
+		if (dereference_object(fo)) {
+			if (flags == FILE_CREATED) {
+				vfree(bin_file->data);
+				kfree(bin_file);
+			} else
+				free_bin_file(bin_file);
+		}
+	} else if (coh->type == OBJECT_TYPE_NT_THREAD) {
+		struct nt_thread *thread = HANDLE_TO_OBJECT(handle);
+		TRACE2("thread: %p (%p)", thread, handle);
+		ObDereferenceObject(thread);
+	} else {
+		/* TODO: can we just dereference object here? */
+		WARNING("closing handle 0x%x not implemented", coh->type);
+	}
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwQueryInformationFile,5)
+	(void *handle, struct io_status_block *iosb, void *info,
+	 ULONG length, enum file_info_class class)
+{
+	struct file_object *fo;
+	struct file_name_info *fni;
+	struct file_std_info *fsi;
+	struct wrap_bin_file *file;
+	struct common_object_header *coh;
+
+	ENTER2("%p", handle);
+	coh = handle;
+	if (coh->type != OBJECT_TYPE_FILE) {
+		ERROR("handle %p is invalid: %d", coh, coh->type);
+		EXIT2(return STATUS_FAILURE);
+	}
+	fo = HANDLE_TO_OBJECT(handle);
+	TRACE2("fo: %p, %d", fo, class);
+	switch (class) {
+	case FileNameInformation:
+		fni = info;
+		fni->length = min(length, (typeof(length))coh->name.length);
+		memcpy(fni->name, coh->name.buf, fni->length);
+		iosb->status = STATUS_SUCCESS;
+		iosb->info = fni->length;
+		break;
+	case FileStandardInformation:
+		fsi = info;
+		file = fo->wrap_bin_file;
+		fsi->alloc_size = file->size;
+		fsi->eof = file->size;
+		fsi->num_links = 1;
+		fsi->delete_pending = FALSE;
+		fsi->dir = FALSE;
+		iosb->status = STATUS_SUCCESS;
+		iosb->info = 0;
+		break;
+	default:
+		WARNING("type %d not implemented yet", class);
+		iosb->status = STATUS_FAILURE;
+		iosb->info = 0;
+		break;
+	}
+	EXIT2(return iosb->status);
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwOpenSection,3)
+	(void **handle, ACCESS_MASK access, struct object_attributes *obj_attrs)
+{
+	INFO("%p, 0x%x, %d", obj_attrs, obj_attrs->attributes, access);
+	TODO();
+	*handle = obj_attrs;
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwMapViewOfSection,10)
+	(void *secn_handle, void *process_handle, void **base_address,
+	 ULONG zero_bits, LARGE_INTEGER *secn_offset, SIZE_T *view_size,
+	 enum section_inherit inherit, ULONG alloc_type, ULONG protect)
+{
+	INFO("%p, %p, %p", secn_handle, process_handle, base_address);
+	TODO();
+	*base_address = (void *)0xdeadbeef;
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwUnmapViewOfSection,2)
+	(void *process_handle, void *base_address)
+{
+	INFO("%p, %p", process_handle, base_address);
+	TODO();
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwCreateKey,7)
+	(void **handle, ACCESS_MASK desired_access,
+	 struct object_attributes *attr, ULONG title_index,
+	 struct unicode_string *class, ULONG create_options,
+	 ULONG *disposition)
+{
+	struct ansi_string ansi;
+	if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE1("key: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	*handle = NULL;
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwOpenKey,3)
+	(void **handle, ACCESS_MASK desired_access,
+	 struct object_attributes *attr)
+{
+	struct ansi_string ansi;
+	if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE1("key: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	*handle = NULL;
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwSetValueKey,6)
+	(void *handle, struct unicode_string *name, ULONG title_index,
+	 ULONG type, void *data, ULONG data_size)
+{
+	struct ansi_string ansi;
+	if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) ==
+	    STATUS_SUCCESS) {
+		TRACE1("key: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwQueryValueKey,6)
+	(void *handle, struct unicode_string *name,
+	 enum key_value_information_class class, void *info,
+	 ULONG length, ULONG *res_length)
+{
+	struct ansi_string ansi;
+	if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) {
+		TRACE1("key: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	TODO();
+	return STATUS_INVALID_PARAMETER;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwDeleteKey,1)
+	(void *handle)
+{
+	ENTER2("%p", handle);
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(ZwPowerInformation,4)
+	(INT info_level, void *in_buf, ULONG in_buf_len, void *out_buf,
+	 ULONG out_buf_len)
+{
+	INFO("%d, %u, %u", info_level, in_buf_len, out_buf_len);
+	TODO();
+	return STATUS_ACCESS_DENIED;
+}
+
+wstdcall NTSTATUS WIN_FUNC(WmiSystemControl,4)
+	(struct wmilib_context *info, struct device_object *dev_obj,
+	 struct irp *irp, void *irp_disposition)
+{
+	TODO();
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(WmiCompleteRequest,5)
+	(struct device_object *dev_obj, struct irp *irp, NTSTATUS status,
+	 ULONG buffer_used, CCHAR priority_boost)
+{
+	TODO();
+	return STATUS_SUCCESS;
+}
+
+noregparm NTSTATUS WIN_FUNC(WmiTraceMessage,12)
+	(void *tracehandle, ULONG message_flags,
+	 void *message_guid, USHORT message_no, ...)
+{
+	TODO();
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(WmiQueryTraceInformation,4)
+	(enum trace_information_class trace_info_class, void *trace_info,
+	 ULONG *req_length, void *buf)
+{
+	TODO();
+	EXIT2(return STATUS_SUCCESS);
+}
+
+/* this function can't be wstdcall as it takes variable number of args */
+noregparm ULONG WIN_FUNC(DbgPrint,12)
+	(char *format, ...)
+{
+#ifdef DEBUG
+	va_list args;
+	static char buf[100];
+
+	va_start(args, format);
+	vsnprintf(buf, sizeof(buf), format, args);
+	printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __func__, buf);
+	va_end(args);
+#endif
+	return STATUS_SUCCESS;
+}
+
+wstdcall void WIN_FUNC(KeBugCheck,1)
+	(ULONG code)
+{
+	TODO();
+	return;
+}
+
+wstdcall void WIN_FUNC(KeBugCheckEx,5)
+	(ULONG code, ULONG_PTR param1, ULONG_PTR param2,
+	 ULONG_PTR param3, ULONG_PTR param4)
+{
+	TODO();
+	return;
+}
+
+wstdcall void WIN_FUNC(ExSystemTimeToLocalTime,2)
+	(LARGE_INTEGER *system_time, LARGE_INTEGER *local_time)
+{
+	*local_time = *system_time;
+}
+
+wstdcall ULONG WIN_FUNC(ExSetTimerResolution,2)
+	(ULONG time, BOOLEAN set)
+{
+	/* why a driver should change system wide timer resolution is
+	 * beyond me */
+	return time;
+}
+
+wstdcall void WIN_FUNC(DbgBreakPoint,0)
+	(void)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(_except_handler3,0)
+	(void)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(__C_specific_handler,0)
+	(void)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(_purecall,0)
+	(void)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(__chkstk,0)
+	(void)
+{
+	TODO();
+}
+
+struct worker_init_struct {
+	work_struct_t work;
+	struct completion completion;
+	struct nt_thread *nt_thread;
+};
+
+static void wrap_worker_init_func(worker_param_t param)
+{
+	struct worker_init_struct *worker_init_struct;
+
+	worker_init_struct =
+		worker_param_data(param, struct worker_init_struct, work);
+	TRACE1("%p", worker_init_struct);
+	worker_init_struct->nt_thread = create_nt_thread(current);
+	if (!worker_init_struct->nt_thread)
+		WARNING("couldn't create worker thread");
+	complete(&worker_init_struct->completion);
+}
+
+struct nt_thread *wrap_worker_init(workqueue_struct_t *wq)
+{
+	struct worker_init_struct worker_init_struct;
+
+	TRACE1("%p", &worker_init_struct);
+	init_completion(&worker_init_struct.completion);
+	initialize_work(&worker_init_struct.work, wrap_worker_init_func,
+			&worker_init_struct);
+	worker_init_struct.nt_thread = NULL;
+	if (wq)
+		queue_work(wq, &worker_init_struct.work);
+	else
+		schedule_work(&worker_init_struct.work);
+	wait_for_completion(&worker_init_struct.completion);
+	TRACE1("%p", worker_init_struct.nt_thread);
+	return worker_init_struct.nt_thread;
+}
+
+int ntoskernel_init(void)
+{
+	struct timeval now;
+
+	spin_lock_init(&dispatcher_lock);
+	spin_lock_init(&ntoskernel_lock);
+	spin_lock_init(&ntos_work_lock);
+	spin_lock_init(&kdpc_list_lock);
+	spin_lock_init(&irp_cancel_lock);
+	InitializeListHead(&wrap_mdl_list);
+	InitializeListHead(&kdpc_list);
+	InitializeListHead(&callback_objects);
+	InitializeListHead(&bus_driver_list);
+	InitializeListHead(&object_list);
+	InitializeListHead(&ntos_work_list);
+
+	nt_spin_lock_init(&nt_list_lock);
+
+	initialize_work(&kdpc_work, kdpc_worker, NULL);
+	initialize_work(&ntos_work, ntos_work_worker, NULL);
+	wrap_timer_slist.next = NULL;
+
+	do_gettimeofday(&now);
+	wrap_ticks_to_boot = TICKS_1601_TO_1970;
+	wrap_ticks_to_boot += (u64)now.tv_sec * TICKSPERSEC;
+	wrap_ticks_to_boot += now.tv_usec * 10;
+	wrap_ticks_to_boot -= jiffies * TICKSPERJIFFY;
+	TRACE2("%Lu", wrap_ticks_to_boot);
+
+#ifdef WRAP_PREEMPT
+	do {
+		int cpu;
+		for_each_possible_cpu(cpu) {
+			irql_info_t *info;
+			info = &per_cpu(irql_info, cpu);
+			mutex_init(&(info->lock));
+			info->task = NULL;
+			info->count = 0;
+		}
+	} while (0);
+#endif
+
+	ntos_wq = create_singlethread_workqueue("ntos_wq");
+	if (!ntos_wq) {
+		WARNING("couldn't create ntos_wq thread");
+		return -ENOMEM;
+	}
+	ntos_worker_thread = wrap_worker_init(ntos_wq);
+	TRACE1("%p", ntos_worker_thread);
+
+	if (add_bus_driver("PCI")
+#ifdef ENABLE_USB
+	    || add_bus_driver("USB")
+#endif
+		) {
+		ntoskernel_exit();
+		return -ENOMEM;
+	}
+	mdl_cache =
+		wrap_kmem_cache_create("wrap_mdl",
+				       sizeof(struct wrap_mdl) + MDL_CACHE_SIZE,
+				       0, 0);
+	TRACE2("%p", mdl_cache);
+	if (!mdl_cache) {
+		ERROR("couldn't allocate MDL cache");
+		ntoskernel_exit();
+		return -ENOMEM;
+	}
+
+#if defined(CONFIG_X86_64)
+	memset(&kuser_shared_data, 0, sizeof(kuser_shared_data));
+	*((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601();
+	init_timer(&shared_data_timer);
+	shared_data_timer.function = update_user_shared_data_proc;
+	shared_data_timer.data = (unsigned long)0;
+#endif
+	return 0;
+}
+
+int ntoskernel_init_device(struct wrap_device *wd)
+{
+#if defined(CONFIG_X86_64)
+	if (kuser_shared_data.reserved1)
+		mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30));
+#endif
+	return 0;
+}
+
+void ntoskernel_exit_device(struct wrap_device *wd)
+{
+	ENTER2("");
+
+	KeFlushQueuedDpcs();
+	EXIT2(return);
+}
+
+void ntoskernel_exit(void)
+{
+	struct nt_list *cur;
+
+	ENTER2("");
+
+	/* free kernel (Ke) timers */
+	TRACE2("freeing timers");
+	while (1) {
+		struct wrap_timer *wrap_timer;
+		struct nt_slist *slist;
+
+		spin_lock_bh(&ntoskernel_lock);
+		if ((slist = wrap_timer_slist.next))
+			wrap_timer_slist.next = slist->next;
+		spin_unlock_bh(&ntoskernel_lock);
+		TIMERTRACE("%p", slist);
+		if (!slist)
+			break;
+		wrap_timer = container_of(slist, struct wrap_timer, slist);
+		if (del_timer_sync(&wrap_timer->timer))
+			WARNING("Buggy Windows driver left timer %p running",
+				wrap_timer->nt_timer);
+		memset(wrap_timer, 0, sizeof(*wrap_timer));
+		slack_kfree(wrap_timer);
+	}
+
+	TRACE2("freeing MDLs");
+	if (mdl_cache) {
+		spin_lock_bh(&ntoskernel_lock);
+		if (!IsListEmpty(&wrap_mdl_list))
+			ERROR("Windows driver didn't free all MDLs; "
+			      "freeing them now");
+		while ((cur = RemoveHeadList(&wrap_mdl_list))) {
+			struct wrap_mdl *wrap_mdl;
+			wrap_mdl = container_of(cur, struct wrap_mdl, list);
+			if (wrap_mdl->mdl->flags & MDL_CACHE_ALLOCATED)
+				kmem_cache_free(mdl_cache, wrap_mdl);
+			else
+				kfree(wrap_mdl);
+		}
+		spin_unlock_bh(&ntoskernel_lock);
+		kmem_cache_destroy(mdl_cache);
+		mdl_cache = NULL;
+	}
+
+	TRACE2("freeing callbacks");
+	spin_lock_bh(&ntoskernel_lock);
+	while ((cur = RemoveHeadList(&callback_objects))) {
+		struct callback_object *object;
+		struct nt_list *ent;
+		object = container_of(cur, struct callback_object, list);
+		while ((ent = RemoveHeadList(&object->callback_funcs))) {
+			struct callback_func *f;
+			f = container_of(ent, struct callback_func, list);
+			kfree(f);
+		}
+		kfree(object);
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+
+	spin_lock_bh(&ntoskernel_lock);
+	while ((cur = RemoveHeadList(&bus_driver_list))) {
+		struct bus_driver *bus_driver;
+		bus_driver = container_of(cur, struct bus_driver, list);
+		/* TODO: make sure all all drivers are shutdown/removed */
+		kfree(bus_driver);
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+
+#if defined(CONFIG_X86_64)
+	del_timer_sync(&shared_data_timer);
+#endif
+	if (ntos_wq)
+		destroy_workqueue(ntos_wq);
+	TRACE1("%p", ntos_worker_thread);
+	if (ntos_worker_thread)
+		ObDereferenceObject(ntos_worker_thread);
+	ENTER2("freeing objects");
+	spin_lock_bh(&ntoskernel_lock);
+	while ((cur = RemoveHeadList(&object_list))) {
+		struct common_object_header *hdr;
+		hdr = container_of(cur, struct common_object_header, list);
+		if (hdr->type == OBJECT_TYPE_NT_THREAD)
+			TRACE1("object %p(%d) was not freed, freeing it now",
+			       HEADER_TO_OBJECT(hdr), hdr->type);
+		else
+			WARNING("object %p(%d) was not freed, freeing it now",
+				HEADER_TO_OBJECT(hdr), hdr->type);
+		ExFreePool(hdr);
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+
+	EXIT2(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapmem.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapmem.h
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (C) 2006 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _WRAPMEM_H_
+
+/* set ALLOC_DEBUG to 1 to get information about memory used by both
+ * ndiswrapper and Windows driver by reading
+ * /proc/net/ndiswrapper/debug; this will also show memory leaks
+ * (memory allocated but not freed) when ndiswrapper module is
+ * unloaded.
+
+ * ALLOC_DEBUG=2: details about individual allocations leaking is printed
+ * ALLOC_DEBUG=3: tags in ExAllocatePoolWithTag leaking printed
+*/
+
+//#ifndef ALLOC_DEBUG
+//#define ALLOC_DEBUG 1
+//#endif
+
+enum alloc_type { ALLOC_TYPE_KMALLOC_ATOMIC, ALLOC_TYPE_KMALLOC_NON_ATOMIC,
+		  ALLOC_TYPE_VMALLOC_ATOMIC, ALLOC_TYPE_VMALLOC_NON_ATOMIC,
+		  ALLOC_TYPE_SLACK, ALLOC_TYPE_PAGES, ALLOC_TYPE_MAX };
+
+int wrapmem_init(void);
+void wrapmem_exit(void);
+void *slack_kmalloc(size_t size);
+void slack_kfree(void *ptr);
+void wrapmem_info(void);
+
+#ifdef ALLOC_DEBUG
+void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line);
+void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line);
+void wrap_kfree(void *ptr);
+void *wrap_vmalloc(unsigned long size, const char *file, int line);
+void *wrap__vmalloc(unsigned long size, gfp_t flags, pgprot_t prot,
+		    const char *file, int line);
+void wrap_vfree(void *ptr);
+void *wrap_alloc_pages(gfp_t flags, unsigned int size,
+		       const char *file, int line);
+void wrap_free_pages(unsigned long ptr, int order);
+int alloc_size(enum alloc_type type);
+
+#ifndef _WRAPMEM_C_
+#undef kmalloc
+#undef kzalloc
+#undef kfree
+#undef vmalloc
+#undef __vmalloc
+#undef vfree
+#define kmalloc(size, flags)				\
+	wrap_kmalloc(size, flags, __FILE__, __LINE__)
+#define kzalloc(size, flags)				\
+	wrap_kzalloc(size, flags, __FILE__, __LINE__)
+#define vmalloc(size)				\
+	wrap_vmalloc(size, __FILE__, __LINE__)
+#define __vmalloc(size, flags, prot)				\
+	wrap__vmalloc(size, flags, prot, __FILE__, __LINE__)
+#define kfree(ptr) wrap_kfree(ptr)
+#define vfree(ptr) wrap_vfree(ptr)
+
+#define wrap_get_free_pages(flags, size)			\
+	wrap_alloc_pages(flags, size, __FILE__, __LINE__)
+#undef free_pages
+#define free_pages(ptr, order) wrap_free_pages(ptr, order)
+
+#if ALLOC_DEBUG > 1
+void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size,
+				 ULONG tag, const char *file, int line);
+#define ExAllocatePoolWithTag(pool_type, size, tag)			\
+	wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__)
+#endif
+
+#endif // _WRAPMEM_C_
+
+#else
+
+#define wrap_get_free_pages(flags, size)			\
+	(void *)__get_free_pages(flags, get_order(size))
+
+#endif // ALLOC_DEBUG
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/loader.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/loader.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _LOADER_H_
+#define _LOADER_H_
+
+#include "ndiswrapper.h"
+
+#ifndef __KERNEL__
+#define __user
+#endif
+
+struct load_driver_file {
+	char driver_name[MAX_DRIVER_NAME_LEN];
+	char name[MAX_DRIVER_NAME_LEN];
+	size_t size;
+	void __user *data;
+};
+
+struct load_device_setting {
+	char name[MAX_SETTING_NAME_LEN];
+	char value[MAX_SETTING_VALUE_LEN];
+};
+
+struct load_device {
+	int bus;
+	int vendor;
+	int device;
+	int subvendor;
+	int subdevice;
+	char conf_file_name[MAX_DRIVER_NAME_LEN];
+	char driver_name[MAX_DRIVER_NAME_LEN];
+};
+
+struct load_devices {
+	int count;
+	struct load_device *devices;
+};
+
+struct load_driver {
+	char name[MAX_DRIVER_NAME_LEN];
+	char conf_file_name[MAX_DRIVER_NAME_LEN];
+	unsigned int num_sys_files;
+	struct load_driver_file sys_files[MAX_DRIVER_PE_IMAGES];
+	unsigned int num_settings;
+	struct load_device_setting settings[MAX_DEVICE_SETTINGS];
+	unsigned int num_bin_files;
+	struct load_driver_file bin_files[MAX_DRIVER_BIN_FILES];
+};
+
+#define WRAP_IOCTL_LOAD_DEVICE _IOW(('N' + 'd' + 'i' + 'S'), 0,	\
+				    struct load_device *)
+#define WRAP_IOCTL_LOAD_DRIVER _IOW(('N' + 'd' + 'i' + 'S'), 1,	\
+				    struct load_driver *)
+#define WRAP_IOCTL_LOAD_BIN_FILE _IOW(('N' + 'd' + 'i' + 'S'), 2,	\
+				      struct load_driver_file *)
+
+#define WRAP_CMD_LOAD_DEVICE "load_device"
+#define WRAP_CMD_LOAD_DRIVER "load_driver"
+#define WRAP_CMD_LOAD_BIN_FILE "load_bin_file"
+
+int loader_init(void);
+void loader_exit(void);
+
+#ifdef __KERNEL__
+struct wrap_device *load_wrap_device(struct load_device *load_device);
+struct wrap_driver *load_wrap_driver(struct wrap_device *device);
+struct wrap_bin_file *get_bin_file(char *bin_file_name);
+void free_bin_file(struct wrap_bin_file *bin_file);
+void unload_wrap_driver(struct wrap_driver *driver);
+void unload_wrap_device(struct wrap_device *wd);
+struct wrap_device *get_wrap_device(void *dev, int bus_type);
+
+extern struct semaphore loader_mutex;
+#endif
+
+#endif /* LOADER_H */
+
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/iw_ndis.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/iw_ndis.h
@@ -0,0 +1,208 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _IW_NDIS_H_
+#define _IW_NDIS_H_
+
+#include "ndis.h"
+
+#define	WL_NOISE	-96	/* typical noise level in dBm */
+#define	WL_SIGMAX	-32	/* typical maximum signal level in dBm */
+
+struct ndis_encr_key {
+	ULONG struct_size;
+	ULONG index;
+	ULONG length;
+	UCHAR key[NDIS_ENCODING_TOKEN_MAX];
+};
+
+struct ndis_add_key {
+	ULONG struct_size;
+	ndis_key_index index;
+	ULONG length;
+	mac_address bssid;
+	UCHAR pad[6];
+	ndis_key_rsc rsc;
+	UCHAR key[NDIS_ENCODING_TOKEN_MAX];
+};
+
+struct ndis_remove_key {
+	ULONG struct_size;
+	ndis_key_index index;
+	mac_address bssid;
+};
+
+struct ndis_fixed_ies {
+	UCHAR time_stamp[8];
+	USHORT beacon_interval;
+	USHORT capa;
+};
+
+struct ndis_variable_ies {
+	ULONG elem_id;
+	UCHAR length;
+	UCHAR data[1];
+};
+
+enum ndis_reload_defaults { Ndis802_11ReloadWEPKeys };
+
+struct ndis_assoc_info {
+	ULONG length;
+	USHORT req_ies;
+	struct req_ie {
+		USHORT capa;
+		USHORT listen_interval;
+		mac_address cur_ap_address;
+	} req_ie;
+	ULONG req_ie_length;
+	ULONG offset_req_ies;
+	USHORT resp_ies;
+	struct resp_ie {
+		USHORT capa;
+		USHORT status_code;
+		USHORT assoc_id;
+	} resp_ie;
+	ULONG resp_ie_length;
+	ULONG offset_resp_ies;
+};
+
+struct ndis_configuration_fh {
+	ULONG length;
+	ULONG hop_pattern;
+	ULONG hop_set;
+	ULONG dwell_time;
+};
+
+struct ndis_configuration {
+	ULONG length;
+	ULONG beacon_period;
+	ULONG atim_window;
+	ULONG ds_config;
+	struct ndis_configuration_fh fh_config;
+};
+
+struct ndis_wlan_bssid {
+	ULONG length;
+	mac_address mac;
+	UCHAR reserved[2];
+	struct ndis_essid ssid;
+	ULONG privacy;
+	ndis_rssi rssi;
+	UINT net_type;
+	struct ndis_configuration config;
+	UINT mode;
+	ndis_rates rates;
+};
+
+struct ndis_wlan_bssid_ex {
+	ULONG length;
+	mac_address mac;
+	UCHAR reserved[2];
+	struct ndis_essid ssid;
+	ULONG privacy;
+	ndis_rssi rssi;
+	UINT net_type;
+	struct ndis_configuration config;
+	UINT mode;
+	ndis_rates_ex rates_ex;
+	ULONG ie_length;
+	UCHAR ies[1];
+};
+
+/* we use bssid_list as bssid_list_ex also */
+struct ndis_bssid_list {
+	ULONG num_items;
+	struct ndis_wlan_bssid bssid[1];
+};
+
+enum ndis_priv_filter {
+	Ndis802_11PrivFilterAcceptAll, Ndis802_11PrivFilter8021xWEP
+};
+
+enum network_type {
+	Ndis802_11FH, Ndis802_11DS, Ndis802_11OFDM5, Ndis802_11OFDM24,
+	/* MSDN site uses Ndis802_11Automode, which is not mentioned
+	 * in DDK, so add one and assign it to
+	 * Ndis802_11NetworkTypeMax */
+	Ndis802_11Automode, Ndis802_11NetworkTypeMax = Ndis802_11Automode
+};
+
+struct network_type_list {
+	ULONG num;
+	enum network_type types[1];
+};
+
+enum ndis_power {
+	NDIS_POWER_OFF = 0, NDIS_POWER_MAX, NDIS_POWER_MIN,
+};
+
+struct ndis_auth_req {
+	ULONG length;
+	mac_address bssid;
+	ULONG flags;
+};
+
+struct ndis_bssid_info {
+	mac_address bssid;
+	ndis_pmkid_vavlue pmkid;
+};
+
+struct ndis_pmkid {
+	ULONG length;
+	ULONG bssid_info_count;
+	struct ndis_bssid_info bssid_info[1];
+};
+
+int add_wep_key(struct ndis_device *wnd, char *key, int key_len,
+		int index);
+int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len);
+int set_infra_mode(struct ndis_device *wnd,
+		   enum ndis_infrastructure_mode mode);
+int get_ap_address(struct ndis_device *wnd, mac_address mac);
+int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode);
+int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version,
+		     int auth_80211_alg);
+int set_auth_mode(struct ndis_device *wnd);
+int set_ndis_encr_mode(struct ndis_device *wnd, int cipher_pairwise,
+		       int cipher_groupwise);
+int get_ndis_encr_mode(struct ndis_device *wnd);
+int set_encr_mode(struct ndis_device *wnd);
+int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise,
+		     int cipher_groupwise);
+int get_ndis_auth_mode(struct ndis_device *wnd);
+int set_priv_filter(struct ndis_device *wnd);
+int set_scan(struct ndis_device *wnd);
+NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid);
+void set_default_iw_params(struct ndis_device *wnd);
+extern const struct iw_handler_def ndis_handler_def;
+
+#define PRIV_RESET	 		SIOCIWFIRSTPRIV+16
+#define PRIV_POWER_PROFILE	 	SIOCIWFIRSTPRIV+17
+#define PRIV_NETWORK_TYPE	 	SIOCIWFIRSTPRIV+18
+#define PRIV_DEAUTHENTICATE 		SIOCIWFIRSTPRIV+19
+#define PRIV_MEDIA_STREAM_MODE 		SIOCIWFIRSTPRIV+20
+#define PRIV_RELOAD_DEFAULTS		SIOCIWFIRSTPRIV+23
+
+#define RSN_INFO_ELEM		0x30
+
+/* these have to match what is in wpa_supplicant */
+
+typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
+typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
+	       CIPHER_WEP104 } wpa_cipher;
+typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
+	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
+
+#endif // IW_NDIS_H
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/hal.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/hal.c
@@ -0,0 +1,157 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ntoskernel.h"
+#include "hal_exports.h"
+
+wstdcall void WIN_FUNC(WRITE_PORT_ULONG,2)
+	(ULONG_PTR port, ULONG value)
+{
+	outl(value, port);
+}
+
+wstdcall ULONG WIN_FUNC(READ_PORT_ULONG,1)
+	(ULONG_PTR port)
+{
+	return inl(port);
+}
+
+wstdcall void WIN_FUNC(WRITE_PORT_USHORT,2)
+	(ULONG_PTR port, USHORT value)
+{
+	outw(value, port);
+}
+
+wstdcall USHORT WIN_FUNC(READ_PORT_USHORT,1)
+	(ULONG_PTR port)
+{
+	return inw(port);
+}
+
+wstdcall void WIN_FUNC(WRITE_PORT_UCHAR,2)
+	(ULONG_PTR port, UCHAR value)
+{
+	outb(value, port);
+}
+
+wstdcall UCHAR WIN_FUNC(READ_PORT_UCHAR,1)
+	(ULONG_PTR port)
+{
+	return inb(port);
+}
+
+wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_USHORT,3)
+	(ULONG_PTR port, USHORT *buf, ULONG count)
+{
+	outsw(port, buf, count);
+}
+
+wstdcall void WIN_FUNC(READ_PORT_BUFFER_USHORT,3)
+	(ULONG_PTR port, USHORT *buf, ULONG count)
+{
+	insw(port, buf, count);
+}
+
+wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_ULONG,3)
+	(ULONG_PTR port, ULONG *buf, ULONG count)
+{
+	outsl(port, buf, count);
+}
+
+wstdcall void WIN_FUNC(READ_PORT_BUFFER_ULONG,3)
+	(ULONG_PTR port, ULONG *buf, ULONG count)
+{
+	insl(port, buf, count);
+}
+
+wstdcall USHORT WIN_FUNC(READ_REGISTER_USHORT,1)
+	(void __iomem *reg)
+{
+	return readw(reg);
+}
+
+wstdcall void WIN_FUNC(WRITE_REGISTER_ULONG,2)
+	(void __iomem *reg, UINT val)
+{
+	writel(val, reg);
+}
+
+wstdcall void WIN_FUNC(WRITE_REGISTER_USHORT,2)
+	(void __iomem *reg, USHORT val)
+{
+	writew(val, reg);
+}
+
+wstdcall void WIN_FUNC(WRITE_REGISTER_UCHAR,2)
+	(void __iomem *reg, UCHAR val)
+{
+	writeb(val, reg);
+}
+
+wstdcall void WIN_FUNC(KeStallExecutionProcessor,1)
+	(ULONG usecs)
+{
+	udelay(usecs);
+}
+
+wstdcall KIRQL WIN_FUNC(KeGetCurrentIrql,0)
+	(void)
+{
+	return current_irql();
+}
+
+wfastcall KIRQL WIN_FUNC(KfRaiseIrql,1)
+	(KIRQL newirql)
+{
+	return raise_irql(newirql);
+}
+
+wfastcall void WIN_FUNC(KfLowerIrql,1)
+	(KIRQL oldirql)
+{
+	lower_irql(oldirql);
+}
+
+wfastcall KIRQL WIN_FUNC(KfAcquireSpinLock,1)
+	(NT_SPIN_LOCK *lock)
+{
+	return nt_spin_lock_irql(lock, DISPATCH_LEVEL);
+}
+
+wfastcall void WIN_FUNC(KfReleaseSpinLock,2)
+	(NT_SPIN_LOCK *lock, KIRQL oldirql)
+{
+	nt_spin_unlock_irql(lock, oldirql);
+}
+
+wfastcall void WIN_FUNC(KefAcquireSpinLockAtDpcLevel,1)
+	(NT_SPIN_LOCK *lock)
+{
+#ifdef DEBUG_IRQL
+	if (current_irql() != DISPATCH_LEVEL)
+		ERROR("irql != DISPATCH_LEVEL");
+#endif
+	nt_spin_lock(lock);
+}
+
+wfastcall void WIN_FUNC(KefReleaseSpinLockFromDpcLevel,1)
+	(NT_SPIN_LOCK *lock)
+{
+#ifdef DEBUG_IRQL
+	if (current_irql() != DISPATCH_LEVEL)
+		ERROR("irql != DISPATCH_LEVEL");
+#endif
+	nt_spin_unlock(lock);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapndis.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapndis.c
@@ -0,0 +1,2133 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ndis.h"
+#include "iw_ndis.h"
+#include "pnp.h"
+#include "loader.h"
+#include "wrapndis.h"
+#include <linux/inetdevice.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/in.h>
+#include "wrapper.h"
+
+/* Functions callable from the NDIS driver */
+wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo,
+					    struct irp *irp);
+wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp);
+wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp);
+
+workqueue_struct_t *wrapndis_wq;
+static struct nt_thread *wrapndis_worker_thread;
+
+static int set_packet_filter(struct ndis_device *wnd,
+			     ULONG packet_filter);
+static void add_iw_stats_timer(struct ndis_device *wnd);
+static void del_iw_stats_timer(struct ndis_device *wnd);
+static NDIS_STATUS ndis_start_device(struct ndis_device *wnd);
+static int ndis_remove_device(struct ndis_device *wnd);
+static void set_multicast_list(struct ndis_device *wnd);
+static int ndis_net_dev_open(struct net_device *net_dev);
+static int ndis_net_dev_close(struct net_device *net_dev);
+
+/* MiniportReset */
+NDIS_STATUS mp_reset(struct ndis_device *wnd)
+{
+	NDIS_STATUS res;
+	struct miniport *mp;
+	BOOLEAN reset_address;
+	KIRQL irql;
+
+	ENTER2("wnd: %p", wnd);
+	if (down_interruptible(&wnd->tx_ring_mutex))
+		EXIT3(return NDIS_STATUS_FAILURE);
+	if (down_interruptible(&wnd->ndis_req_mutex)) {
+		up(&wnd->tx_ring_mutex);
+		EXIT3(return NDIS_STATUS_FAILURE);
+	}
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0);
+	WARNING("%s is being reset", wnd->net_dev->name);
+	irql = serialize_lock_irql(wnd);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	res = LIN2WIN2(mp->reset, &reset_address, wnd->nmb->mp_ctx);
+	serialize_unlock_irql(wnd, irql);
+
+	TRACE2("%08X, %08X", res, reset_address);
+	if (res == NDIS_STATUS_PENDING) {
+		/* wait for NdisMResetComplete */
+		if (wait_condition((wnd->ndis_req_done > 0), 0,
+				   TASK_INTERRUPTIBLE) < 0)
+			res = NDIS_STATUS_FAILURE;
+		else {
+			res = wnd->ndis_req_status;
+			reset_address = wnd->ndis_req_done - 1;
+		}
+		TRACE2("%08X, %08X", res, reset_address);
+	}
+	up(&wnd->ndis_req_mutex);
+	if (res == NDIS_STATUS_SUCCESS && reset_address) {
+		set_packet_filter(wnd, wnd->packet_filter);
+		set_multicast_list(wnd);
+	}
+	up(&wnd->tx_ring_mutex);
+	EXIT3(return res);
+}
+
+/* MiniportRequest(Query/Set)Information */
+NDIS_STATUS mp_request(enum ndis_request_type request,
+		       struct ndis_device *wnd, ndis_oid oid,
+		       void *buf, ULONG buflen, ULONG *written, ULONG *needed)
+{
+	NDIS_STATUS res;
+	ULONG w, n;
+	struct miniport *mp;
+	KIRQL irql;
+
+	if (down_interruptible(&wnd->ndis_req_mutex))
+		EXIT3(return NDIS_STATUS_FAILURE);
+	if (!written)
+		written = &w;
+	if (!needed)
+		needed = &n;
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0);
+	irql = serialize_lock_irql(wnd);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	switch (request) {
+	case NdisRequestQueryInformation:
+		TRACE2("%p, %08X, %p", mp->queryinfo, oid, wnd->nmb->mp_ctx);
+		res = LIN2WIN6(mp->queryinfo, wnd->nmb->mp_ctx, oid, buf,
+			       buflen, written, needed);
+		break;
+	case NdisRequestSetInformation:
+		TRACE2("%p, %08X, %p", mp->setinfo, oid, wnd->nmb->mp_ctx);
+		res = LIN2WIN6(mp->setinfo, wnd->nmb->mp_ctx, oid, buf,
+			       buflen, written, needed);
+		break;
+	default:
+		WARNING("invalid request %d, %08X", request, oid);
+		res = NDIS_STATUS_NOT_SUPPORTED;
+		break;
+	}
+	serialize_unlock_irql(wnd, irql);
+	TRACE2("%08X, %08X", res, oid);
+	if (res == NDIS_STATUS_PENDING) {
+		/* wait for NdisMQueryInformationComplete */
+		if (wait_condition((wnd->ndis_req_done > 0), 0,
+				   TASK_INTERRUPTIBLE) < 0)
+			res = NDIS_STATUS_FAILURE;
+		else
+			res = wnd->ndis_req_status;
+		TRACE2("%08X, %08X", res, oid);
+	}
+	up(&wnd->ndis_req_mutex);
+	DBG_BLOCK(2) {
+		if (res || needed)
+			TRACE2("%08X, %d, %d, %d", res, buflen, *written,
+			       *needed);
+	}
+	EXIT3(return res);
+}
+
+/* MiniportPnPEventNotify */
+static NDIS_STATUS mp_pnp_event(struct ndis_device *wnd,
+				enum ndis_device_pnp_event event,
+				ULONG power_profile)
+{
+	struct miniport *mp;
+
+	ENTER1("%p, %d", wnd, event);
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	if (!mp->pnp_event_notify) {
+		TRACE1("Windows driver %s doesn't support "
+		       "MiniportPnpEventNotify", wnd->wd->driver->name);
+		return NDIS_STATUS_FAILURE;
+	}
+	/* RNDIS driver doesn't like to be notified if device is
+	 * already halted */
+	if (!test_bit(HW_INITIALIZED, &wnd->wd->hw_status))
+		EXIT1(return NDIS_STATUS_SUCCESS);
+	switch (event) {
+	case NdisDevicePnPEventSurpriseRemoved:
+		TRACE1("%u, %p",
+		       (wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK),
+		       mp->pnp_event_notify);
+		if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) &&
+		    !test_bit(HW_PRESENT, &wnd->wd->hw_status) &&
+		    mp->pnp_event_notify) {
+			TRACE1("calling surprise_removed");
+			LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
+				 NdisDevicePnPEventSurpriseRemoved, NULL, 0);
+		} else
+			TRACE1("Windows driver %s doesn't support "
+			       "MiniportPnpEventNotify for safe unplugging",
+			       wnd->wd->driver->name);
+		return NDIS_STATUS_SUCCESS;
+	case NdisDevicePnPEventPowerProfileChanged:
+		if (power_profile)
+			power_profile = NdisPowerProfileAcOnLine;
+		LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx,
+			 NdisDevicePnPEventPowerProfileChanged,
+			 &power_profile, (ULONG)sizeof(power_profile));
+		return NDIS_STATUS_SUCCESS;
+	default:
+		WARNING("event %d not yet implemented", event);
+		return NDIS_STATUS_SUCCESS;
+	}
+}
+
+/* MiniportInitialize */
+static NDIS_STATUS mp_init(struct ndis_device *wnd)
+{
+	NDIS_STATUS error_status, status;
+	UINT medium_index;
+	enum ndis_medium medium_array[] = {NdisMedium802_3};
+	struct miniport *mp;
+
+	ENTER1("irql: %d", current_irql());
+	if (test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) {
+		WARNING("device %p already initialized!", wnd);
+		return NDIS_STATUS_FAILURE;
+	}
+
+	if (!wnd->wd->driver->ndis_driver ||
+	    !wnd->wd->driver->ndis_driver->mp.init) {
+		WARNING("assuming WDM (non-NDIS) driver");
+		EXIT1(return NDIS_STATUS_NOT_RECOGNIZED);
+	}
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	status = LIN2WIN6(mp->init, &error_status, &medium_index, medium_array,
+			  sizeof(medium_array) / sizeof(medium_array[0]),
+			  wnd->nmb, wnd->nmb);
+	TRACE1("init returns: %08X, irql: %d", status, current_irql());
+	if (status != NDIS_STATUS_SUCCESS) {
+		WARNING("couldn't initialize device: %08X", status);
+		EXIT1(return NDIS_STATUS_FAILURE);
+	}
+
+	/* Wait a little to let card power up otherwise ifup might
+	 * fail after boot */
+	sleep_hz(HZ / 5);
+	status = mp_pnp_event(wnd, NdisDevicePnPEventPowerProfileChanged,
+			      NdisPowerProfileAcOnLine);
+	if (status != NDIS_STATUS_SUCCESS)
+		TRACE1("setting power failed: %08X", status);
+	set_bit(HW_INITIALIZED, &wnd->wd->hw_status);
+	/* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is
+	 * misleading/confusing */
+	status = mp_query(wnd, OID_PNP_CAPABILITIES,
+			  &wnd->pnp_capa, sizeof(wnd->pnp_capa));
+	if (status == NDIS_STATUS_SUCCESS) {
+		TRACE1("%d, %d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup,
+		       wnd->pnp_capa.wakeup.min_pattern_wakeup);
+		wnd->attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
+		status = mp_query_int(wnd, OID_PNP_ENABLE_WAKE_UP,
+				      &wnd->ndis_wolopts);
+		TRACE1("%08X, %x", status, wnd->ndis_wolopts);
+	} else if (status == NDIS_STATUS_NOT_SUPPORTED)
+		wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
+	TRACE1("%d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup);
+	/* although some NDIS drivers support suspend, Linux kernel
+	 * has issues with suspending USB devices */
+	if (wrap_is_usb_bus(wnd->wd->dev_bus)) {
+		wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
+		wnd->ndis_wolopts = 0;
+	}
+	mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
+	EXIT1(return NDIS_STATUS_SUCCESS);
+}
+
+/* MiniportHalt */
+static void mp_halt(struct ndis_device *wnd)
+{
+	struct miniport *mp;
+
+	ENTER1("%p", wnd);
+	if (!test_and_clear_bit(HW_INITIALIZED, &wnd->wd->hw_status)) {
+		WARNING("device %p is not initialized - not halting", wnd);
+		return;
+	}
+	hangcheck_del(wnd);
+	del_iw_stats_timer(wnd);
+	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan &&
+	    wrap_is_pci_bus(wnd->wd->dev_bus)) {
+		up(&wnd->ndis_req_mutex);
+		disassociate(wnd, 0);
+		if (down_interruptible(&wnd->ndis_req_mutex))
+			WARNING("couldn't obtain ndis_req_mutex");
+	}
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	TRACE1("halt: %p", mp->mp_halt);
+	LIN2WIN1(mp->mp_halt, wnd->nmb->mp_ctx);
+	/* if a driver doesn't call NdisMDeregisterInterrupt during
+	 * halt, deregister it now */
+	if (wnd->mp_interrupt)
+		NdisMDeregisterInterrupt(wnd->mp_interrupt);
+	/* cancel any timers left by bugyy windows driver; also free
+	 * the memory for timers */
+	while (1) {
+		struct nt_slist *slist;
+		struct wrap_timer *wrap_timer;
+
+		spin_lock_bh(&ntoskernel_lock);
+		if ((slist = wnd->wrap_timer_slist.next))
+			wnd->wrap_timer_slist.next = slist->next;
+		spin_unlock_bh(&ntoskernel_lock);
+		TIMERTRACE("%p", slist);
+		if (!slist)
+			break;
+		wrap_timer = container_of(slist, struct wrap_timer, slist);
+		wrap_timer->repeat = 0;
+		/* ktimer that this wrap_timer is associated to can't
+		 * be touched, as it may have been freed by the driver
+		 * already */
+		if (del_timer_sync(&wrap_timer->timer))
+			WARNING("Buggy Windows driver left timer %p "
+				"running", wrap_timer->nt_timer);
+		memset(wrap_timer, 0, sizeof(*wrap_timer));
+		kfree(wrap_timer);
+	}
+	EXIT1(return);
+}
+
+static NDIS_STATUS mp_set_power_state(struct ndis_device *wnd,
+				      enum ndis_power_state state)
+{
+	NDIS_STATUS status;
+
+	TRACE1("%d", state);
+	if (state == NdisDeviceStateD0) {
+		status = NDIS_STATUS_SUCCESS;
+		up(&wnd->ndis_req_mutex);
+		if (test_and_clear_bit(HW_HALTED, &wnd->wd->hw_status)) {
+			status = mp_init(wnd);
+			if (status == NDIS_STATUS_SUCCESS) {
+				set_packet_filter(wnd, wnd->packet_filter);
+				set_multicast_list(wnd);
+			}
+		} else if (test_and_clear_bit(HW_SUSPENDED,
+					      &wnd->wd->hw_status)) {
+			status = mp_set_int(wnd, OID_PNP_SET_POWER, state);
+			if (status != NDIS_STATUS_SUCCESS)
+				WARNING("%s: setting power to state %d failed? "
+					"%08X", wnd->net_dev->name, state,
+					status);
+		} else
+			return NDIS_STATUS_FAILURE;
+
+		if (wrap_is_pci_bus(wnd->wd->dev_bus)) {
+			pci_enable_wake(wnd->wd->pci.pdev, PCI_D3hot, 0);
+			pci_enable_wake(wnd->wd->pci.pdev, PCI_D3cold, 0);
+		}
+		if (status == NDIS_STATUS_SUCCESS) {
+			up(&wnd->tx_ring_mutex);
+			netif_device_attach(wnd->net_dev);
+			hangcheck_add(wnd);
+			add_iw_stats_timer(wnd);
+		} else
+			WARNING("%s: couldn't set power to state %d; device not"
+				" resumed", wnd->net_dev->name, state);
+		EXIT1(return status);
+	} else {
+		if (down_interruptible(&wnd->tx_ring_mutex))
+			EXIT1(return NDIS_STATUS_FAILURE);
+		netif_device_detach(wnd->net_dev);
+		hangcheck_del(wnd);
+		del_iw_stats_timer(wnd);
+		status = NDIS_STATUS_NOT_SUPPORTED;
+		if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) {
+			status = mp_set_int(wnd, OID_PNP_ENABLE_WAKE_UP,
+					    wnd->ndis_wolopts);
+			TRACE2("0x%x, 0x%x", status, wnd->ndis_wolopts);
+			if (status == NDIS_STATUS_SUCCESS) {
+				if (wnd->ndis_wolopts)
+					wnd->wd->pci.wake_state =
+						PowerDeviceD3;
+				else
+					wnd->wd->pci.wake_state =
+						PowerDeviceUnspecified;
+			} else
+				WARNING("couldn't set wake-on-lan options: "
+					"0x%x, %08X", wnd->ndis_wolopts, status);
+			status = mp_set_int(wnd, OID_PNP_SET_POWER, state);
+			if (status == NDIS_STATUS_SUCCESS)
+				set_bit(HW_SUSPENDED, &wnd->wd->hw_status);
+			else
+				WARNING("suspend failed: %08X", status);
+		}
+		if (status != NDIS_STATUS_SUCCESS) {
+			WARNING("%s does not support power management; "
+				"halting the device", wnd->net_dev->name);
+			mp_halt(wnd);
+			set_bit(HW_HALTED, &wnd->wd->hw_status);
+			status = STATUS_SUCCESS;
+		}
+		if (down_interruptible(&wnd->ndis_req_mutex))
+			WARNING("couldn't lock ndis_req_mutex");
+		EXIT1(return status);
+	}
+}
+
+static int ndis_set_mac_address(struct net_device *dev, void *p)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct sockaddr *addr = p;
+	struct ndis_configuration_parameter param;
+	struct unicode_string key;
+	struct ansi_string ansi;
+	NDIS_STATUS res;
+	unsigned char mac_string[2 * ETH_ALEN + 1];
+	mac_address mac;
+
+	memcpy(mac, addr->sa_data, sizeof(mac));
+	memset(mac_string, 0, sizeof(mac_string));
+	res = snprintf(mac_string, sizeof(mac_string), MACSTR, MAC2STR(mac));
+	if (res != (sizeof(mac_string) - 1))
+		EXIT1(return -EINVAL);
+	TRACE1("new mac: %s", mac_string);
+
+	RtlInitAnsiString(&ansi, mac_string);
+	if (RtlAnsiStringToUnicodeString(&param.data.string, &ansi,
+					 TRUE) != STATUS_SUCCESS)
+		EXIT1(return -EINVAL);
+
+	param.type = NdisParameterString;
+	RtlInitAnsiString(&ansi, "NetworkAddress");
+	if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) {
+		RtlFreeUnicodeString(&param.data.string);
+		EXIT1(return -EINVAL);
+	}
+	NdisWriteConfiguration(&res, wnd->nmb, &key, &param);
+	RtlFreeUnicodeString(&key);
+	RtlFreeUnicodeString(&param.data.string);
+
+	if (res != NDIS_STATUS_SUCCESS)
+		EXIT1(return -EFAULT);
+	if (ndis_reinit(wnd) == NDIS_STATUS_SUCCESS) {
+		res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS,
+			       mac, sizeof(mac));
+		if (res == NDIS_STATUS_SUCCESS) {
+			TRACE1("mac:" MACSTRSEP, MAC2STR(mac));
+			memcpy(dev->dev_addr, mac, sizeof(mac));
+		} else
+			ERROR("couldn't get mac address: %08X", res);
+	}
+	EXIT1(return 0);
+}
+
+static int setup_tx_sg_list(struct ndis_device *wnd, struct sk_buff *skb,
+			    struct ndis_packet_oob_data *oob_data)
+{
+	struct ndis_sg_element *sg_element;
+	struct ndis_sg_list *sg_list;
+	int i;
+
+	ENTER3("%p, %d", skb, skb_shinfo(skb)->nr_frags);
+	if (skb_shinfo(skb)->nr_frags <= 1) {
+		sg_element = &oob_data->wrap_tx_sg_list.elements[0];
+		sg_element->address =
+			PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,
+					   skb->len, PCI_DMA_TODEVICE);
+		sg_element->length = skb->len;
+		oob_data->wrap_tx_sg_list.nent = 1;
+		oob_data->ext.info[ScatterGatherListPacketInfo] =
+			&oob_data->wrap_tx_sg_list;
+		TRACE3("%Lx, %u", sg_element->address, sg_element->length);
+		return 0;
+	}
+	sg_list = kmalloc(sizeof(*sg_list) +
+			  (skb_shinfo(skb)->nr_frags + 1) * sizeof(*sg_element),
+			  GFP_ATOMIC);
+	if (!sg_list)
+		return -ENOMEM;
+	sg_list->nent = skb_shinfo(skb)->nr_frags + 1;
+	TRACE3("%p, %d", sg_list, sg_list->nent);
+	sg_element = sg_list->elements;
+	sg_element->length = skb_headlen(skb);
+	sg_element->address =
+		PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,
+				   skb_headlen(skb), PCI_DMA_TODEVICE);
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		sg_element++;
+		sg_element->length = frag->size;
+		sg_element->address =
+			pci_map_page(wnd->wd->pci.pdev, frag->page,
+				     frag->page_offset, frag->size,
+				     PCI_DMA_TODEVICE);
+		TRACE3("%Lx, %u", sg_element->address, sg_element->length);
+	}
+	oob_data->ext.info[ScatterGatherListPacketInfo] = sg_list;
+	return 0;
+}
+
+static void free_tx_sg_list(struct ndis_device *wnd,
+			    struct ndis_packet_oob_data *oob_data)
+{
+	int i;
+	struct ndis_sg_element *sg_element;
+	struct ndis_sg_list *sg_list =
+		oob_data->ext.info[ScatterGatherListPacketInfo];
+	sg_element = sg_list->elements;
+	TRACE3("%p, %d", sg_list, sg_list->nent);
+	PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, sg_element->address,
+			     sg_element->length, PCI_DMA_TODEVICE);
+	if (sg_list->nent == 1)
+		EXIT3(return);
+	for (i = 1; i < sg_list->nent; i++, sg_element++) {
+		TRACE3("%Lx, %u", sg_element->address, sg_element->length);
+		pci_unmap_page(wnd->wd->pci.pdev, sg_element->address,
+			       sg_element->length, PCI_DMA_TODEVICE);
+	}
+	TRACE3("%p", sg_list);
+	kfree(sg_list);
+}
+
+static struct ndis_packet *alloc_tx_packet(struct ndis_device *wnd,
+					   struct sk_buff *skb)
+{
+	struct ndis_packet *packet;
+	ndis_buffer *buffer;
+	struct ndis_packet_oob_data *oob_data;
+	NDIS_STATUS status;
+
+	NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool);
+	if (status != NDIS_STATUS_SUCCESS)
+		return NULL;
+	NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool,
+			   skb->data, skb->len);
+	if (status != NDIS_STATUS_SUCCESS) {
+		NdisFreePacket(packet);
+		return NULL;
+	}
+	packet->private.buffer_head = buffer;
+	packet->private.buffer_tail = buffer;
+
+	oob_data = NDIS_PACKET_OOB_DATA(packet);
+	oob_data->tx_skb = skb;
+	if (wnd->sg_dma_size) {
+		if (setup_tx_sg_list(wnd, skb, oob_data)) {
+			NdisFreeBuffer(buffer);
+			NdisFreePacket(packet);
+			return NULL;
+		}
+	}
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		struct ndis_tcp_ip_checksum_packet_info csum;
+		int protocol;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
+		protocol = ntohs(skb->protocol);
+#else
+		protocol = skb->nh.iph->protocol;
+#endif
+		csum.value = 0;
+		csum.tx.v4 = 1;
+		if (protocol == IPPROTO_TCP)
+			csum.tx.tcp = 1;
+		else if (protocol == IPPROTO_UDP)
+			csum.tx.udp = 1;
+//		csum->tx.ip = 1;
+		packet->private.flags |= NDIS_PROTOCOL_ID_TCP_IP;
+		oob_data->ext.info[TcpIpChecksumPacketInfo] =
+			(void *)(ULONG_PTR)csum.value;
+	}
+	DBG_BLOCK(4) {
+		dump_bytes(__func__, skb->data, skb->len);
+	}
+	TRACE4("%p, %p, %p", packet, buffer, skb);
+	return packet;
+}
+
+void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet,
+		    NDIS_STATUS status)
+{
+	ndis_buffer *buffer;
+	struct ndis_packet_oob_data *oob_data;
+	struct sk_buff *skb;
+	struct ndis_packet_pool *pool;
+
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	assert(packet->private.packet_flags);
+	oob_data = NDIS_PACKET_OOB_DATA(packet);
+	skb = oob_data->tx_skb;
+	buffer = packet->private.buffer_head;
+	TRACE4("%p, %p, %p, %08X", packet, buffer, skb, status);
+	if (status == NDIS_STATUS_SUCCESS) {
+		pre_atomic_add(wnd->net_stats.tx_bytes, packet->private.len);
+		atomic_inc_var(wnd->net_stats.tx_packets);
+	} else {
+		TRACE1("packet dropped: %08X", status);
+		atomic_inc_var(wnd->net_stats.tx_dropped);
+	}
+	if (wnd->sg_dma_size)
+		free_tx_sg_list(wnd, oob_data);
+	NdisFreeBuffer(buffer);
+	dev_kfree_skb_any(skb);
+	pool = packet->private.pool;
+	NdisFreePacket(packet);
+	if (netif_queue_stopped(wnd->net_dev) &&
+	    ((pool->max_descr - pool->num_used_descr) >=
+	     (wnd->max_tx_packets / 4))) {
+		set_bit(NETIF_WAKEQ, &wnd->ndis_pending_work);
+		schedule_wrapndis_work(&wnd->ndis_work);
+	}
+	EXIT4(return);
+}
+
+/* MiniportSend and MiniportSendPackets */
+/* this function is called holding tx_ring_mutex. start and n are such
+ * that start + n < TX_RING_SIZE; i.e., packets don't wrap around
+ * ring */
+static u8 mp_tx_packets(struct ndis_device *wnd, u8 start, u8 n)
+{
+	NDIS_STATUS res;
+	struct miniport *mp;
+	struct ndis_packet *packet;
+	u8 sent;
+	KIRQL irql;
+
+	ENTER3("%d, %d", start, n);
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	if (mp->send_packets) {
+		if (deserialized_driver(wnd)) {
+			LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx,
+				 &wnd->tx_ring[start], n);
+			sent = n;
+		} else {
+			irql = serialize_lock_irql(wnd);
+			LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx,
+				 &wnd->tx_ring[start], n);
+			serialize_unlock_irql(wnd, irql);
+			for (sent = 0; sent < n && wnd->tx_ok; sent++) {
+				struct ndis_packet_oob_data *oob_data;
+				packet = wnd->tx_ring[start + sent];
+				oob_data = NDIS_PACKET_OOB_DATA(packet);
+				switch ((res =
+					 xchg(&oob_data->status,
+					      NDIS_STATUS_NOT_RECOGNIZED))) {
+				case NDIS_STATUS_SUCCESS:
+					free_tx_packet(wnd, packet,
+						       NDIS_STATUS_SUCCESS);
+					break;
+				case NDIS_STATUS_PENDING:
+					break;
+				case NDIS_STATUS_RESOURCES:
+					wnd->tx_ok = 0;
+					/* resubmit this packet and
+					 * the rest when resources
+					 * become available */
+					sent--;
+					break;
+				case NDIS_STATUS_FAILURE:
+					free_tx_packet(wnd, packet,
+						       NDIS_STATUS_FAILURE);
+					break;
+				default:
+					ERROR("%p: invalid status: %08X",
+					      packet, res);
+					free_tx_packet(wnd, packet,
+						       oob_data->status);
+					break;
+				}
+				TRACE3("%p, %d", packet, res);
+			}
+		}
+		TRACE3("sent: %d(%d)", sent, n);
+	} else {
+		for (sent = 0; sent < n && wnd->tx_ok; sent++) {
+			struct ndis_packet_oob_data *oob_data;
+			packet = wnd->tx_ring[start + sent];
+			oob_data = NDIS_PACKET_OOB_DATA(packet);
+			oob_data->status = NDIS_STATUS_NOT_RECOGNIZED;
+			irql = serialize_lock_irql(wnd);
+			res = LIN2WIN3(mp->send, wnd->nmb->mp_ctx,
+				       packet, packet->private.flags);
+			serialize_unlock_irql(wnd, irql);
+			switch (res) {
+			case NDIS_STATUS_SUCCESS:
+				free_tx_packet(wnd, packet, res);
+				break;
+			case NDIS_STATUS_PENDING:
+				break;
+			case NDIS_STATUS_RESOURCES:
+				wnd->tx_ok = 0;
+				/* resend this packet when resources
+				 * become available */
+				sent--;
+				break;
+			case NDIS_STATUS_FAILURE:
+				free_tx_packet(wnd, packet, res);
+				break;
+			default:
+				ERROR("packet %p: invalid status: %08X",
+				      packet, res);
+				break;
+			}
+		}
+	}
+	EXIT3(return sent);
+}
+
+static void tx_worker(worker_param_t param)
+{
+	struct ndis_device *wnd;
+	s8 n;
+
+	wnd = worker_param_data(param, struct ndis_device, tx_work);
+	ENTER3("tx_ok %d", wnd->tx_ok);
+	while (wnd->tx_ok) {
+		if (down_interruptible(&wnd->tx_ring_mutex))
+			break;
+		spin_lock_bh(&wnd->tx_ring_lock);
+		n = wnd->tx_ring_end - wnd->tx_ring_start;
+		TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);
+		/* end == start if either ring is empty or full; in
+		 * the latter case is_tx_ring_full is set */
+		if (n == 0) {
+			if (wnd->is_tx_ring_full)
+				n = TX_RING_SIZE - wnd->tx_ring_start;
+			else {
+				spin_unlock_bh(&wnd->tx_ring_lock);
+				up(&wnd->tx_ring_mutex);
+				break;
+			}
+		} else if (n < 0)
+			n = TX_RING_SIZE - wnd->tx_ring_start;
+		spin_unlock_bh(&wnd->tx_ring_lock);
+		if (unlikely(n > wnd->max_tx_packets))
+			n = wnd->max_tx_packets;
+		n = mp_tx_packets(wnd, wnd->tx_ring_start, n);
+		if (n) {
+			wnd->net_dev->trans_start = jiffies;
+			wnd->tx_ring_start =
+				(wnd->tx_ring_start + n) % TX_RING_SIZE;
+			wnd->is_tx_ring_full = 0;
+		}
+		up(&wnd->tx_ring_mutex);
+		TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n);
+	}
+	EXIT3(return);
+}
+
+static int tx_skbuff(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	struct ndis_packet *packet;
+
+	packet = alloc_tx_packet(wnd, skb);
+	if (!packet) {
+		TRACE2("couldn't allocate packet");
+		netif_tx_lock(dev);
+		netif_stop_queue(dev);
+		netif_tx_unlock(dev);
+		return NETDEV_TX_BUSY;
+	}
+	spin_lock(&wnd->tx_ring_lock);
+	wnd->tx_ring[wnd->tx_ring_end++] = packet;
+	if (wnd->tx_ring_end == TX_RING_SIZE)
+		wnd->tx_ring_end = 0;
+	if (wnd->tx_ring_end == wnd->tx_ring_start) {
+		netif_tx_lock(dev);
+		wnd->is_tx_ring_full = 1;
+		netif_stop_queue(dev);
+		netif_tx_unlock(dev);
+	}
+	spin_unlock(&wnd->tx_ring_lock);
+	TRACE4("ring: %d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
+	schedule_wrapndis_work(&wnd->tx_work);
+	return NETDEV_TX_OK;
+}
+
+static int set_packet_filter(struct ndis_device *wnd, ULONG packet_filter)
+{
+	NDIS_STATUS res;
+
+	while (1) {
+		res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,
+				 packet_filter);
+		if (res == NDIS_STATUS_SUCCESS)
+			break;
+		TRACE2("couldn't set filter 0x%08x", packet_filter);
+		/* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */
+		if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+			packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
+			continue;
+		}
+		if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) {
+			packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL;
+			continue;
+		}
+		if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) {
+			packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
+			continue;
+		}
+		if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) {
+			packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
+			packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+			continue;
+		}
+		if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
+			packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
+			continue;
+		}
+		break;
+	}
+
+	wnd->packet_filter = packet_filter;
+	res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter);
+	if (packet_filter != wnd->packet_filter) {
+		WARNING("filter not set: 0x%08x, 0x%08x",
+			packet_filter, wnd->packet_filter);
+		wnd->packet_filter = packet_filter;
+	}
+	if (wnd->packet_filter)
+		EXIT3(return 0);
+	else
+		EXIT3(return -1);
+}
+
+void set_media_state(struct ndis_device *wnd, enum ndis_media_state state)
+{
+	ENTER2("state: 0x%x", state);
+	if (state == NdisMediaStateConnected) {
+		netif_carrier_on(wnd->net_dev);
+		wnd->tx_ok = 1;
+		if (netif_queue_stopped(wnd->net_dev))
+			netif_wake_queue(wnd->net_dev);
+		if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
+			set_bit(LINK_STATUS_ON, &wnd->ndis_pending_work);
+			schedule_wrapndis_work(&wnd->ndis_work);
+		}
+	} else if (state == NdisMediaStateDisconnected) {
+		netif_carrier_off(wnd->net_dev);
+		netif_stop_queue(wnd->net_dev);
+		wnd->tx_ok = 0;
+		if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
+			memset(&wnd->essid, 0, sizeof(wnd->essid));
+			set_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work);
+			schedule_wrapndis_work(&wnd->ndis_work);
+		}
+	} else {
+		WARNING("invalid media state: 0x%x", state);
+	}
+}
+
+static int ndis_net_dev_open(struct net_device *net_dev)
+{
+	ENTER1("%p", netdev_priv(net_dev));
+	netif_start_queue(net_dev);
+	netif_poll_enable(net_dev);
+	EXIT1(return 0);
+}
+
+static int ndis_net_dev_close(struct net_device *net_dev)
+{
+	ENTER1("%p", netdev_priv(net_dev));
+	netif_poll_disable(net_dev);
+	netif_tx_disable(net_dev);
+	EXIT1(return 0);
+}
+
+static int ndis_change_mtu(struct net_device *net_dev, int mtu)
+{
+	struct ndis_device *wnd = netdev_priv(net_dev);
+	int max;
+
+	if (mtu < ETH_ZLEN)
+		return -EINVAL;
+	if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &max) !=
+	    NDIS_STATUS_SUCCESS)
+		return -EOPNOTSUPP;
+	TRACE1("%d", max);
+	max -= ETH_HLEN;
+	if (max <= ETH_ZLEN)
+		return -EINVAL;
+	if (mtu + ETH_HLEN > max)
+		return -EINVAL;
+	net_dev->mtu = mtu;
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ndis_poll_controller(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	disable_irq(dev->irq);
+	ndis_isr(wnd->mp_interrupt->kinterrupt, wnd->mp_interrupt);
+	enable_irq(dev->irq);
+}
+#endif
+
+/* called from BH context */
+static struct net_device_stats *ndis_get_stats(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	return &wnd->net_stats;
+}
+
+/* called from BH context */
+static void ndis_set_multicast_list(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	set_bit(SET_MULTICAST_LIST, &wnd->ndis_pending_work);
+	schedule_wrapndis_work(&wnd->ndis_work);
+}
+
+/* called from BH context */
+struct iw_statistics *get_iw_stats(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	return &wnd->iw_stats;
+}
+
+static void update_iw_stats(struct ndis_device *wnd)
+{
+	struct iw_statistics *iw_stats = &wnd->iw_stats;
+	struct ndis_wireless_stats ndis_stats;
+	NDIS_STATUS res;
+	ndis_rssi rssi;
+	int qual;
+
+	ENTER2("%p", wnd);
+	if (wnd->iw_stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) {
+		memset(iw_stats, 0, sizeof(*iw_stats));
+		EXIT2(return);
+	}
+	res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi));
+	if (res == NDIS_STATUS_SUCCESS)
+		iw_stats->qual.level = rssi;
+
+	qual = 100 * (rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
+	if (qual < 0)
+		qual = 0;
+	else if (qual > 100)
+		qual = 100;
+
+	iw_stats->qual.noise = WL_NOISE;
+	iw_stats->qual.qual  = qual;
+
+	res = mp_query(wnd, OID_802_11_STATISTICS,
+		       &ndis_stats, sizeof(ndis_stats));
+	if (res != NDIS_STATUS_SUCCESS)
+		EXIT2(return);
+	iw_stats->discard.retries = (unsigned long)ndis_stats.retry +
+		(unsigned long)ndis_stats.multi_retry;
+	iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err +
+		(unsigned long)ndis_stats.rtss_fail +
+		(unsigned long)ndis_stats.ack_fail +
+		(unsigned long)ndis_stats.frame_dup;
+
+	EXIT2(return);
+}
+
+static void set_multicast_list(struct ndis_device *wnd)
+{
+	struct net_device *net_dev;
+	ULONG packet_filter;
+	NDIS_STATUS res;
+
+	net_dev = wnd->net_dev;
+	packet_filter = wnd->packet_filter;
+
+	TRACE2("0x%08x", packet_filter);
+	if (net_dev->flags & IFF_PROMISC) {
+		packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS |
+			NDIS_PACKET_TYPE_ALL_LOCAL;
+	} else if (net_dev->flags & IFF_ALLMULTI ||
+		   net_dev->mc_count > wnd->multicast_size) {
+		packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+		TRACE2("0x%08x", packet_filter);
+	} else if (net_dev->mc_count > 0) {
+		int i, size;
+		char *buf;
+		struct dev_mc_list *mclist;
+		size = min(wnd->multicast_size, net_dev->mc_count);
+		TRACE2("%d, %d", wnd->multicast_size, net_dev->mc_count);
+		buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);
+		if (!buf) {
+			WARNING("couldn't allocate memory");
+			EXIT2(return);
+		}
+		mclist = net_dev->mc_list;
+		for (i = 0; i < size && mclist; mclist = mclist->next) {
+			if (mclist->dmi_addrlen != ETH_ALEN)
+				continue;
+			memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);
+			TRACE2(MACSTRSEP, MAC2STR(mclist->dmi_addr));
+			i++;
+		}
+		res = mp_set(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN);
+		if (res == NDIS_STATUS_SUCCESS && i > 0)
+			packet_filter |= NDIS_PACKET_TYPE_MULTICAST;
+		else
+			packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+		kfree(buf);
+	}
+	TRACE2("0x%08x", packet_filter);
+	res = set_packet_filter(wnd, packet_filter);
+	if (res)
+		TRACE1("couldn't set packet filter (%08X)", res);
+	EXIT2(return);
+}
+
+static void link_status_off(struct ndis_device *wnd)
+{
+#ifdef CONFIG_WIRELESS_EXT
+	union iwreq_data wrqu;
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+	EXIT2(return);
+}
+
+static void link_status_on(struct ndis_device *wnd)
+{
+#ifdef CONFIG_WIRELESS_EXT
+	struct ndis_assoc_info *ndis_assoc_info;
+	union iwreq_data wrqu;
+	NDIS_STATUS res;
+	const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32;
+#endif
+
+	ENTER2("");
+#ifdef CONFIG_WIRELESS_EXT
+	memset(&wrqu, 0, sizeof(wrqu));
+	ndis_assoc_info = kzalloc(assoc_size, GFP_KERNEL);
+	if (!ndis_assoc_info) {
+		ERROR("couldn't allocate memory");
+		goto send_assoc_event;
+	}
+	res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION,
+		       ndis_assoc_info, assoc_size);
+	if (res) {
+		TRACE2("query assoc_info failed (%08X)", res);
+		kfree(ndis_assoc_info);
+		goto send_assoc_event;
+	}
+	TRACE2("%u, 0x%x, %u, 0x%x, %u", ndis_assoc_info->length,
+	       ndis_assoc_info->req_ies, ndis_assoc_info->req_ie_length,
+	       ndis_assoc_info->resp_ies, ndis_assoc_info->resp_ie_length);
+	if (ndis_assoc_info->req_ie_length > 0) {
+		wrqu.data.length = ndis_assoc_info->req_ie_length;
+		wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu,
+				    ((char *)ndis_assoc_info) +
+				    ndis_assoc_info->offset_req_ies);
+	}
+	if (ndis_assoc_info->resp_ie_length > 0) {
+		wrqu.data.length = ndis_assoc_info->resp_ie_length;
+		wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu,
+				    ((char *)ndis_assoc_info) +
+				    ndis_assoc_info->offset_resp_ies);
+	}
+	kfree(ndis_assoc_info);
+
+send_assoc_event:
+	get_ap_address(wnd, wrqu.ap_addr.sa_data);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data));
+	wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+	EXIT2(return);
+}
+
+static void iw_stats_timer_proc(unsigned long data)
+{
+	struct ndis_device *wnd = (struct ndis_device *)data;
+
+	ENTER2("%d", wnd->iw_stats_interval);
+	if (wnd->iw_stats_interval > 0) {
+		set_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work);
+		schedule_wrapndis_work(&wnd->ndis_work);
+	}
+	mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);
+}
+
+static void add_iw_stats_timer(struct ndis_device *wnd)
+{
+	if (wnd->physical_medium != NdisPhysicalMediumWirelessLan)
+		return;
+	if (wnd->iw_stats_interval < 0)
+		wnd->iw_stats_interval *= -1;
+	wnd->iw_stats_timer.data = (unsigned long)wnd;
+	wnd->iw_stats_timer.function = iw_stats_timer_proc;
+	mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval);
+}
+
+static void del_iw_stats_timer(struct ndis_device *wnd)
+{
+	ENTER2("%d", wnd->iw_stats_interval);
+	wnd->iw_stats_interval *= -1;
+	del_timer_sync(&wnd->iw_stats_timer);
+	EXIT2(return);
+}
+
+static void hangcheck_proc(unsigned long data)
+{
+	struct ndis_device *wnd = (struct ndis_device *)data;
+
+	ENTER3("%d", wnd->hangcheck_interval);
+	if (wnd->hangcheck_interval > 0) {
+		set_bit(HANGCHECK, &wnd->ndis_pending_work);
+		schedule_wrapndis_work(&wnd->ndis_work);
+	}
+	mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval);
+	EXIT3(return);
+}
+
+void hangcheck_add(struct ndis_device *wnd)
+{
+	if (!wnd->wd->driver->ndis_driver->mp.hangcheck ||
+	    hangcheck_interval < 0)
+		EXIT2(return);
+
+	if (hangcheck_interval > 0)
+		wnd->hangcheck_interval = hangcheck_interval * HZ;
+	if (wnd->hangcheck_interval < 0)
+		wnd->hangcheck_interval *= -1;
+	wnd->hangcheck_timer.data = (unsigned long)wnd;
+	wnd->hangcheck_timer.function = hangcheck_proc;
+	mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval);
+	EXIT2(return);
+}
+
+void hangcheck_del(struct ndis_device *wnd)
+{
+	ENTER2("%d", wnd->hangcheck_interval);
+	if (wnd->hangcheck_interval > 0)
+		wnd->hangcheck_interval *= -1;
+	del_timer_sync(&wnd->hangcheck_timer);
+	EXIT2(return);
+}
+
+/* worker procedure to take care of setting/checking various states */
+static void ndis_worker(worker_param_t param)
+{
+	struct ndis_device *wnd;
+
+	wnd = worker_param_data(param, struct ndis_device, ndis_work);
+	WORKTRACE("0x%lx", wnd->ndis_pending_work);
+
+	if (test_and_clear_bit(NETIF_WAKEQ, &wnd->ndis_pending_work)) {
+		netif_tx_lock_bh(wnd->net_dev);
+		netif_wake_queue(wnd->net_dev);
+		netif_tx_unlock_bh(wnd->net_dev);
+	}
+
+	if (test_and_clear_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work))
+		link_status_off(wnd);
+
+	if (test_and_clear_bit(LINK_STATUS_ON, &wnd->ndis_pending_work))
+		link_status_on(wnd);
+
+	if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work))
+		update_iw_stats(wnd);
+
+	if (test_and_clear_bit(SET_MULTICAST_LIST,
+			       &wnd->ndis_pending_work))
+		set_multicast_list(wnd);
+
+	if (test_and_clear_bit(HANGCHECK, &wnd->ndis_pending_work)) {
+		struct miniport *mp;
+		BOOLEAN reset;
+		KIRQL irql;
+
+		mp = &wnd->wd->driver->ndis_driver->mp;
+		irql = serialize_lock_irql(wnd);
+		reset = LIN2WIN1(mp->hangcheck, wnd->nmb->mp_ctx);
+		serialize_unlock_irql(wnd, irql);
+		if (reset) {
+			TRACE2("%s needs reset", wnd->net_dev->name);
+			mp_reset(wnd);
+		}
+	}
+	WORKEXIT(return);
+}
+
+NDIS_STATUS ndis_reinit(struct ndis_device *wnd)
+{
+	NDIS_STATUS status;
+
+	wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND;
+	status = mp_set_power_state(wnd, NdisDeviceStateD3);
+	if (status != NDIS_STATUS_SUCCESS) {
+		ERROR("halting device %s failed: %08X", wnd->net_dev->name,
+		      status);
+		return status;
+	}
+	status = mp_set_power_state(wnd, NdisDeviceStateD0);
+	if (status != NDIS_STATUS_SUCCESS)
+		ERROR("starting device %s failed: %08X", wnd->net_dev->name,
+		      status);
+	return status;
+}
+
+static void get_encryption_capa(struct ndis_device *wnd, char *buf,
+				const int buf_len)
+{
+	int i, mode;
+	NDIS_STATUS res;
+	struct ndis_assoc_info ndis_assoc_info;
+	struct ndis_add_key ndis_key;
+	struct ndis_capability *c;
+
+	ENTER1("%p", wnd);
+	/* set network type to g, b, or a, in that order */
+	res = mp_query(wnd, OID_802_11_NETWORK_TYPES_SUPPORTED, buf, buf_len);
+	if (res == NDIS_STATUS_SUCCESS) {
+		struct network_type_list *net_types;
+		unsigned long types = 0;
+		net_types = (typeof(net_types))buf;
+		for (i = 0; i < net_types->num; i++) {
+			TRACE2("%d", net_types->types[i]);
+			set_bit(net_types->types[i], &types);
+		}
+		if (types & Ndis802_11OFDM24)
+			mode = Ndis802_11OFDM24;
+		else if (types & Ndis802_11DS)
+			mode = Ndis802_11DS;
+		else if (types & Ndis802_11OFDM5)
+			mode = Ndis802_11OFDM5;
+		else
+			mode = Ndis802_11DS;
+		mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode);
+	}
+	/* check if WEP is supported */
+	if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
+			     IW_AUTH_CIPHER_NONE) == 0 &&
+	    get_ndis_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent)
+		set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr);
+
+	/* check if WPA is supported */
+	if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 &&
+	    get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPA)
+		set_bit(Ndis802_11AuthModeWPA, &wnd->capa.encr);
+	else
+		EXIT1(return);
+
+	if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 &&
+	    get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK)
+		set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.encr);
+
+	/* check for highest encryption */
+	mode = 0;
+	if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_CCMP,
+			     IW_AUTH_CIPHER_NONE) == 0 &&
+	    (i = get_ndis_encr_mode(wnd)) > 0 &&
+	    (i == Ndis802_11Encryption3KeyAbsent ||
+	     i == Ndis802_11Encryption3Enabled))
+		mode = Ndis802_11Encryption3Enabled;
+	else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_TKIP,
+				  IW_AUTH_CIPHER_NONE) == 0 &&
+		 (i = get_ndis_encr_mode(wnd)) > 0 &&
+		 (i == Ndis802_11Encryption2KeyAbsent ||
+		  i == Ndis802_11Encryption2Enabled))
+		mode = Ndis802_11Encryption2Enabled;
+	else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104,
+				  IW_AUTH_CIPHER_NONE) == 0 &&
+		 (i = get_ndis_encr_mode(wnd)) > 0 &&
+		 (i == Ndis802_11Encryption1KeyAbsent ||
+		  i == Ndis802_11Encryption1Enabled))
+		mode = Ndis802_11Encryption1Enabled;
+
+	TRACE1("mode: %d", mode);
+	if (mode == 0)
+		EXIT1(return);
+	set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr);
+	if (mode == Ndis802_11Encryption1Enabled)
+		EXIT1(return);
+
+	ndis_key.length = 32;
+	ndis_key.index = 0xC0000001;
+	ndis_key.struct_size = sizeof(ndis_key);
+	res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size);
+	TRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key));
+	if (res && res != NDIS_STATUS_INVALID_DATA)
+		EXIT1(return);
+	res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION,
+		       &ndis_assoc_info, sizeof(ndis_assoc_info));
+	TRACE1("%08X", res);
+	if (res == NDIS_STATUS_NOT_SUPPORTED)
+		EXIT1(return);
+
+	set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr);
+	if (mode == Ndis802_11Encryption3Enabled)
+		set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr);
+	/* not all drivers support OID_802_11_CAPABILITY, so we don't
+	 * know for sure if driver support WPA or WPAPSK; assume
+	 * WPAPSK */
+	set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth);
+	wnd->max_pmkids = 1;
+
+	memset(buf, 0, buf_len);
+	c = (struct ndis_capability *)buf;
+	res = mp_query(wnd, OID_802_11_CAPABILITY, buf, buf_len);
+	if (!(res == NDIS_STATUS_SUCCESS && c->version == 2))
+		EXIT1(return);
+	wnd->max_pmkids = c->num_PMKIDs;
+
+	for (i = 0; i < c->num_auth_encr_pair; i++) {
+		struct ndis_auth_encr_pair *ae;
+
+		ae = &c->auth_encr_pair[i];
+		if ((char *)(ae + 1) > buf + buf_len)
+			break;
+		switch (ae->auth_mode) {
+		case Ndis802_11AuthModeOpen:
+		case Ndis802_11AuthModeShared:
+		case Ndis802_11AuthModeWPA:
+		case Ndis802_11AuthModeWPAPSK:
+		case Ndis802_11AuthModeWPANone:
+		case Ndis802_11AuthModeWPA2:
+		case Ndis802_11AuthModeWPA2PSK:
+			set_bit(ae->auth_mode, &wnd->capa.auth);
+			break;
+		default:
+			WARNING("unknown auth_mode: %d", ae->auth_mode);
+			break;
+		}
+		switch (ae->encr_mode) {
+		case Ndis802_11EncryptionDisabled:
+		case Ndis802_11Encryption1Enabled:
+		case Ndis802_11Encryption2Enabled:
+		case Ndis802_11Encryption3Enabled:
+			set_bit(ae->encr_mode, &wnd->capa.encr);
+			break;
+		default:
+			WARNING("unknown encr_mode: %d", ae->encr_mode);
+			break;
+		}
+	}
+	EXIT1(return);
+}
+
+wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo,
+					    struct irp *irp)
+{
+	struct ndis_device *wnd;
+
+	TRACE3("fdo: %p", fdo);
+	/* for now, we don't have anything intresting here, so pass it
+	 * down to bus driver */
+	wnd = fdo->reserved;
+	return IoPassIrpDown(wnd->nmb->pdo, irp);
+}
+WIN_FUNC_DECL(NdisDispatchDeviceControl,2)
+
+wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	struct ndis_device *wnd;
+	enum ndis_power_state state;
+	NTSTATUS status;
+	NDIS_STATUS ndis_status;
+
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	wnd = fdo->reserved;
+	IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn,
+		irp_sl->minor_fn, wnd);
+	if ((irp_sl->params.power.type == SystemPowerState &&
+	     irp_sl->params.power.state.system_state > PowerSystemWorking) ||
+	    (irp_sl->params.power.type == DevicePowerState &&
+	     irp_sl->params.power.state.device_state > PowerDeviceD0))
+		state = NdisDeviceStateD3;
+	else
+		state = NdisDeviceStateD0;
+	switch (irp_sl->minor_fn) {
+	case IRP_MN_SET_POWER:
+		if (state == NdisDeviceStateD0) {
+			status = IoSyncForwardIrp(wnd->nmb->pdo, irp);
+			if (status != STATUS_SUCCESS)
+				break;
+			ndis_status = mp_set_power_state(wnd, state);
+			if (ndis_status != NDIS_STATUS_SUCCESS)
+				WARNING("couldn't set power to %d: %08X",
+					state, ndis_status);
+			TRACE2("%s: device resumed", wnd->net_dev->name);
+			irp->io_status.status = status = STATUS_SUCCESS;
+			IoCompleteRequest(irp, IO_NO_INCREMENT);
+			break;
+		} else {
+			ndis_status = mp_set_power_state(wnd, state);
+			/* TODO: handle error case */
+			if (ndis_status != NDIS_STATUS_SUCCESS)
+				WARNING("setting power to %d failed: %08X",
+					state, ndis_status);
+			status = IoAsyncForwardIrp(wnd->nmb->pdo, irp);
+		}
+		break;
+	case IRP_MN_QUERY_POWER:
+		if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) {
+			ndis_status = mp_query(wnd, OID_PNP_QUERY_POWER,
+					       &state, sizeof(state));
+			TRACE2("%d, %08X", state, ndis_status);
+			/* this OID must always succeed */
+			if (ndis_status != NDIS_STATUS_SUCCESS)
+				TRACE1("query power returns %08X", ndis_status);
+			irp->io_status.status = STATUS_SUCCESS;
+		} else
+			irp->io_status.status = STATUS_SUCCESS;
+		status = IoPassIrpDown(wnd->nmb->pdo, irp);
+		break;
+	case IRP_MN_WAIT_WAKE:
+	case IRP_MN_POWER_SEQUENCE:
+		/* TODO: implement WAIT_WAKE */
+		status = IoPassIrpDown(wnd->nmb->pdo, irp);
+		break;
+	default:
+		status = IoPassIrpDown(wnd->nmb->pdo, irp);
+		break;
+	}
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(NdisDispatchPower,2)
+
+wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	struct ndis_device *wnd;
+	struct device_object *pdo;
+	NTSTATUS status;
+
+	IOTRACE("fdo: %p, irp: %p", fdo, irp);
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	wnd = fdo->reserved;
+	pdo = wnd->nmb->pdo;
+	switch (irp_sl->minor_fn) {
+	case IRP_MN_START_DEVICE:
+		status = IoSyncForwardIrp(pdo, irp);
+		if (status != STATUS_SUCCESS)
+			break;
+		if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS)
+			status = STATUS_SUCCESS;
+		else
+			status = STATUS_FAILURE;
+		irp->io_status.status = status;
+		IoCompleteRequest(irp, IO_NO_INCREMENT);
+		break;
+	case IRP_MN_QUERY_STOP_DEVICE:
+		/* TODO: implement in NDIS */
+		status = IoPassIrpDown(wnd->nmb->pdo, irp);
+		break;
+	case IRP_MN_STOP_DEVICE:
+		mp_halt(wnd);
+		irp->io_status.status = STATUS_SUCCESS;
+		status = IoAsyncForwardIrp(pdo, irp);
+		break;
+	case IRP_MN_REMOVE_DEVICE:
+		TRACE1("%s", wnd->net_dev->name);
+		mp_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved, 0);
+		if (ndis_remove_device(wnd)) {
+			status = STATUS_FAILURE;
+			break;
+		}
+		/* wnd is already freed */
+		status = IoAsyncForwardIrp(pdo, irp);
+		IoDetachDevice(fdo);
+		IoDeleteDevice(fdo);
+		break;
+	default:
+		status = IoAsyncForwardIrp(pdo, irp);
+		break;
+	}
+	IOTRACE("status: %08X", status);
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(NdisDispatchPnp,2)
+
+static void set_task_offload(struct ndis_device *wnd, void *buf,
+			     const int buf_size)
+{
+	struct ndis_task_offload_header *task_offload_header;
+	struct ndis_task_offload *task_offload;
+	struct ndis_task_tcp_ip_checksum *csum = NULL;
+	struct ndis_task_tcp_large_send *tso = NULL;
+	NDIS_STATUS status;
+
+	memset(buf, 0, buf_size);
+	task_offload_header = buf;
+	task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION;
+	task_offload_header->size = sizeof(*task_offload_header);
+	task_offload_header->encap_format.flags.fixed_header_size = 1;
+	task_offload_header->encap_format.header_size = sizeof(struct ethhdr);
+	task_offload_header->encap_format.encap = IEEE_802_3_Encapsulation;
+	status = mp_query(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size);
+	TRACE1("%08X", status);
+	if (status != NDIS_STATUS_SUCCESS)
+		EXIT1(return);
+	if (task_offload_header->offset_first_task == 0)
+		EXIT1(return);
+	task_offload = ((void *)task_offload_header +
+			task_offload_header->offset_first_task);
+	while (1) {
+		TRACE1("%d, %d", task_offload->version, task_offload->task);
+		switch(task_offload->task) {
+		case TcpIpChecksumNdisTask:
+			csum = (void *)task_offload->task_buf;
+			break;
+		case TcpLargeSendNdisTask:
+			tso = (void *)task_offload->task_buf;
+			break;
+		default:
+			TRACE1("%d", task_offload->task);
+			break;
+		}
+		if (task_offload->offset_next_task == 0)
+			break;
+		task_offload = (void *)task_offload +
+			task_offload->offset_next_task;
+	}
+	if (tso)
+		TRACE1("%u, %u, %d, %d", tso->max_size, tso->min_seg_count,
+		       tso->tcp_opts, tso->ip_opts);
+	if (!csum)
+		EXIT1(return);
+	TRACE1("%08x, %08x", csum->v4_tx.value, csum->v4_rx.value);
+	task_offload_header->encap_format.flags.fixed_header_size = 1;
+	task_offload_header->encap_format.header_size = sizeof(struct ethhdr);
+	task_offload_header->offset_first_task = sizeof(*task_offload_header);
+	task_offload = ((void *)task_offload_header +
+			task_offload_header->offset_first_task);
+	task_offload->offset_next_task = 0;
+	task_offload->size = sizeof(*task_offload);
+	task_offload->task = TcpIpChecksumNdisTask;
+	memcpy(task_offload->task_buf, csum, sizeof(*csum));
+	task_offload->task_buf_length = sizeof(*csum);
+	status = mp_set(wnd, OID_TCP_TASK_OFFLOAD, task_offload_header,
+			sizeof(*task_offload_header) +
+			sizeof(*task_offload) + sizeof(*csum));
+	TRACE1("%08X", status);
+	if (status != NDIS_STATUS_SUCCESS)
+		EXIT2(return);
+	wnd->tx_csum = csum->v4_tx;
+	if (csum->v4_tx.tcp_csum && csum->v4_tx.udp_csum) {
+		if (csum->v4_tx.ip_csum) {
+			wnd->net_dev->features |= NETIF_F_HW_CSUM;
+			TRACE1("hw checksum enabled");
+		} else {
+			wnd->net_dev->features |= NETIF_F_IP_CSUM;
+			TRACE1("IP checksum enabled");
+		}
+		if (wnd->sg_dma_size)
+			wnd->net_dev->features |= NETIF_F_SG;
+	}
+	wnd->rx_csum = csum->v4_rx;
+	EXIT1(return);
+}
+
+static void get_supported_oids(struct ndis_device *wnd)
+{
+	NDIS_STATUS res;
+	int i, n, needed;
+	ndis_oid *oids;
+
+	res = mp_query_info(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0, NULL,
+			    &needed);
+	if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT ||
+	      res == NDIS_STATUS_INVALID_LENGTH))
+		EXIT1(return);
+	oids = kmalloc(needed, GFP_KERNEL);
+	if (!oids) {
+		TRACE1("couldn't allocate memory");
+		EXIT1(return);
+	}
+	res = mp_query(wnd, OID_GEN_SUPPORTED_LIST, oids, needed);
+	if (res) {
+		TRACE1("failed: %08X", res);
+		kfree(oids);
+		EXIT1(return);
+	}
+	for (i = 0, n = needed / sizeof(*oids); i < n; i++) {
+		TRACE1("oid: %08X", oids[i]);
+		/* if a wireless device didn't say so for
+		 * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */
+		if (wnd->physical_medium != NdisPhysicalMediumWirelessLan &&
+		    oids[i] == OID_802_11_SSID)
+			wnd->physical_medium = NdisPhysicalMediumWirelessLan;
+	}
+	kfree(oids);
+	EXIT1(return);
+}
+
+static void ndis_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 2);
+	strcat(info->driver, "+");
+	strncat(info->driver, wnd->wd->driver->name,
+		sizeof(info->driver) - strlen(DRIVER_NAME) - 1);
+	strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 2);
+	strcat(info->version, "+");
+	strncat(info->version, wnd->wd->driver->version,
+		sizeof(info->version) - strlen(DRIVER_VERSION) - 1);
+	if (wrap_is_pci_bus(wnd->wd->dev_bus))
+		strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev),
+			sizeof(info->bus_info) - 1);
+#ifdef ENABLE_USB
+	else
+		usb_make_path(wnd->wd->usb.udev, info->bus_info,
+			      sizeof(info->bus_info) - 1);
+#endif
+	return;
+}
+
+static u32 ndis_get_link(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	return netif_carrier_ok(wnd->net_dev);
+}
+
+static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	wol->supported = 0;
+	wol->wolopts = 0;
+	if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND))
+		EXIT2(return);
+	if (!wrap_is_pci_bus(wnd->wd->dev_bus))
+		EXIT2(return);
+	/* we always suspend to D3 */
+	if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3)
+		return;
+	wol->supported |= WAKE_MAGIC;
+	if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
+		wol->wolopts |= WAKE_MAGIC;
+	return;
+}
+
+static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND))
+		return -EOPNOTSUPP;
+	if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3)
+		EXIT2(return -EOPNOTSUPP);
+	TRACE2("0x%x", wol->wolopts);
+	if (wol->wolopts & WAKE_MAGIC) {
+		wnd->ndis_wolopts |= NDIS_PNP_WAKE_UP_MAGIC_PACKET;
+		if (wol->wolopts != WAKE_MAGIC)
+			WARNING("ignored wake-on-lan options: 0x%x",
+				wol->wolopts & ~WAKE_MAGIC);
+	} else if (!wol->wolopts)
+		wnd->ndis_wolopts = 0;
+	else
+		return -EOPNOTSUPP;
+	TRACE2("0x%x", wnd->ndis_wolopts);
+	return 0;
+}
+
+static u32 ndis_get_tx_csum(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	if (wnd->tx_csum.tcp_csum && wnd->tx_csum.udp_csum)
+		return 1;
+	else
+		return 0;
+}
+
+static u32 ndis_get_rx_csum(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	if (wnd->rx_csum.value)
+		return 1;
+	else
+		return 0;
+}
+
+static int ndis_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	if (data && (wnd->tx_csum.value == 0))
+		return -EOPNOTSUPP;
+
+	if (wnd->tx_csum.ip_csum)
+		ethtool_op_set_tx_hw_csum(dev, data);
+	else
+		ethtool_op_set_tx_csum(dev, data);
+	return 0;
+}
+
+static int ndis_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+
+	if (data && (wnd->tx_csum.value == 0))
+		return -EOPNOTSUPP;
+
+	/* TODO: enable/disable rx csum through NDIS */
+	return 0;
+}
+
+static u32 ndis_get_sg(struct net_device *dev)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	if (wnd->sg_dma_size)
+		return ethtool_op_get_sg(dev);
+	else
+		return 0;
+}
+
+static int ndis_set_sg(struct net_device *dev, u32 data)
+{
+	struct ndis_device *wnd = netdev_priv(dev);
+	if (wnd->sg_dma_size)
+		return ethtool_op_set_sg(dev, data);
+	else
+		return -EOPNOTSUPP;
+}
+
+static struct ethtool_ops ndis_ethtool_ops = {
+	.get_drvinfo	= ndis_get_drvinfo,
+	.get_link	= ndis_get_link,
+	.get_wol	= ndis_get_wol,
+	.set_wol	= ndis_set_wol,
+	.get_tx_csum	= ndis_get_tx_csum,
+	.get_rx_csum	= ndis_get_rx_csum,
+	.set_tx_csum	= ndis_set_tx_csum,
+	.set_rx_csum	= ndis_set_rx_csum,
+	.get_sg		= ndis_get_sg,
+	.set_sg		= ndis_set_sg,
+};
+
+static int notifier_event(struct notifier_block *notifier, unsigned long event,
+			  void *ptr)
+{
+	struct net_device *net_dev = ptr;
+
+	ENTER2("0x%lx", event);
+	if (net_dev->ethtool_ops == &ndis_ethtool_ops
+	    && event == NETDEV_CHANGENAME) {
+		struct ndis_device *wnd = netdev_priv(net_dev);
+		/* called with rtnl lock held, so no need to lock */
+		wrap_procfs_remove_ndis_device(wnd);
+		printk(KERN_INFO "%s: changing interface name from '%s' to "
+		       "'%s'\n", DRIVER_NAME, wnd->netdev_name, net_dev->name);
+		memcpy(wnd->netdev_name, net_dev->name,
+		       sizeof(wnd->netdev_name));
+		wrap_procfs_add_ndis_device(wnd);
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block netdev_notifier = {
+	.notifier_call = notifier_event,
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+static const struct net_device_ops ndis_netdev_ops = {
+	.ndo_open = ndis_net_dev_open,
+	.ndo_stop = ndis_net_dev_close,
+	.ndo_start_xmit = tx_skbuff,
+	.ndo_change_mtu = ndis_change_mtu,
+	.ndo_set_multicast_list = ndis_set_multicast_list,
+	.ndo_set_mac_address = ndis_set_mac_address,
+	.ndo_get_stats = ndis_get_stats,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller = ndis_poll_controller,
+#endif
+};
+#endif
+
+static NDIS_STATUS ndis_start_device(struct ndis_device *wnd)
+{
+	struct wrap_device *wd;
+	struct net_device *net_dev;
+	NDIS_STATUS status;
+	char *buf;
+	const int buf_len = 256;
+	mac_address mac;
+	struct transport_header_offset *tx_header_offset;
+	int n;
+
+	ENTER2("%d", in_atomic());
+	status = mp_init(wnd);
+	if (status == NDIS_STATUS_NOT_RECOGNIZED)
+		EXIT1(return NDIS_STATUS_SUCCESS);
+	if (status != NDIS_STATUS_SUCCESS)
+		EXIT1(return status);
+	wd = wnd->wd;
+	net_dev = wnd->net_dev;
+
+	get_supported_oids(wnd);
+	memset(mac, 0, sizeof(mac));
+	status = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac));
+	if (memcmp(mac, "\x00\x00\x00\x00\x00\x00", sizeof(mac)) == 0) {
+		status = mp_query(wnd, OID_802_3_PERMANENT_ADDRESS, mac,
+				  sizeof(mac));
+		if (status != NDIS_STATUS_SUCCESS) {
+			ERROR("couldn't get mac address: %08X", status);
+			goto err_start;
+		}
+	}
+	TRACE1("mac:" MACSTRSEP, MAC2STR(mac));
+	memcpy(net_dev->dev_addr, mac, ETH_ALEN);
+
+	strncpy(net_dev->name, if_name, IFNAMSIZ - 1);
+	net_dev->name[IFNAMSIZ - 1] = 0;
+
+	wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED |
+		NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
+	net_dev->netdev_ops = &ndis_netdev_ops;
+#else
+	net_dev->open = ndis_net_dev_open;
+	net_dev->hard_start_xmit = tx_skbuff;
+	net_dev->stop = ndis_net_dev_close;
+	net_dev->get_stats = ndis_get_stats;
+	net_dev->change_mtu = ndis_change_mtu;
+	net_dev->set_multicast_list = ndis_set_multicast_list;
+	net_dev->set_mac_address = ndis_set_mac_address;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	net_dev->poll_controller = ndis_poll_controller;
+#endif
+#endif
+	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
+		net_dev->wireless_handlers = &ndis_handler_def;
+	}
+	net_dev->ethtool_ops = &ndis_ethtool_ops;
+	if (wnd->mp_interrupt)
+		net_dev->irq = wnd->mp_interrupt->irq;
+	net_dev->mem_start = wnd->mem_start;
+	net_dev->mem_end = wnd->mem_end;
+	status = mp_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE,
+			      &wnd->multicast_size);
+	if (status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0)
+		wnd->multicast_size = 0;
+	if (wnd->multicast_size > 0)
+		net_dev->flags |= IFF_MULTICAST;
+	else
+		net_dev->flags &= ~IFF_MULTICAST;
+
+	buf = kmalloc(buf_len, GFP_KERNEL);
+	if (!buf) {
+		WARNING("couldn't allocate memory");
+		goto err_start;
+	}
+
+	set_task_offload(wnd, buf, buf_len);
+#ifdef NETIF_F_LLTX
+	net_dev->features |= NETIF_F_LLTX;
+#endif
+
+	if (register_netdev(net_dev)) {
+		ERROR("cannot register net device %s", net_dev->name);
+		goto err_register;
+	}
+	memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name));
+	memset(buf, 0, buf_len);
+	status = mp_query(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_len);
+	if (status != NDIS_STATUS_SUCCESS) {
+		WARNING("couldn't get vendor information: 0x%x", status);
+		buf[0] = 0;
+	}
+	wnd->drv_ndis_version = n = 0;
+	mp_query_int(wnd, OID_GEN_DRIVER_VERSION, &wnd->drv_ndis_version);
+	mp_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n);
+
+	printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS "
+	       "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', "
+	       "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr),
+	       deserialized_driver(wnd) ? "" : "serialized ",
+	       wnd->wd->driver->name, n, wnd->drv_ndis_version, buf,
+	       wnd->wd->conf_file_name);
+
+	if (deserialized_driver(wnd)) {
+		/* deserialized drivers don't have a limit, but we
+		 * keep max at TX_RING_SIZE */
+		wnd->max_tx_packets = TX_RING_SIZE;
+	} else {
+		status = mp_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS,
+				      &wnd->max_tx_packets);
+		if (status != NDIS_STATUS_SUCCESS)
+			wnd->max_tx_packets = 1;
+		if (wnd->max_tx_packets > TX_RING_SIZE)
+			wnd->max_tx_packets = TX_RING_SIZE;
+	}
+	TRACE2("maximum send packets: %d", wnd->max_tx_packets);
+	NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool,
+				 wnd->max_tx_packets, 0,
+				 PROTOCOL_RESERVED_SIZE_IN_PACKET);
+	if (status != NDIS_STATUS_SUCCESS) {
+		ERROR("couldn't allocate packet pool");
+		goto packet_pool_err;
+	}
+	NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool,
+			       wnd->max_tx_packets + 4);
+	if (status != NDIS_STATUS_SUCCESS) {
+		ERROR("couldn't allocate buffer pool");
+		goto buffer_pool_err;
+	}
+	TRACE1("pool: %p", wnd->tx_buffer_pool);
+
+	if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) ==
+	    NDIS_STATUS_SUCCESS && n > ETH_HLEN)
+		ndis_change_mtu(wnd->net_dev, n - ETH_HLEN);
+
+	if (mp_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) == NDIS_STATUS_SUCCESS)
+		TRACE2("mac options supported: 0x%x", n);
+
+	tx_header_offset = (typeof(tx_header_offset))buf;
+	tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP;
+	tx_header_offset->header_offset = sizeof(ETH_HLEN);
+	status = mp_set(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET,
+			tx_header_offset, sizeof(*tx_header_offset));
+	TRACE2("%08X", status);
+
+	status = mp_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM,
+			      &wnd->physical_medium);
+	if (status != NDIS_STATUS_SUCCESS)
+		wnd->physical_medium = NdisPhysicalMediumUnspecified;
+
+	if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
+		mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
+		get_encryption_capa(wnd, buf, buf_len);
+		TRACE1("capbilities = %ld", wnd->capa.encr);
+		printk(KERN_INFO "%s: encryption modes supported: "
+		       "%s%s%s%s%s%s%s\n", net_dev->name,
+		       test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
+		       "WEP" : "none",
+
+		       test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
+		       "; TKIP with WPA" : "",
+		       test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
+		       ", WPA2" : "",
+		       test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
+		       ", WPA2PSK" : "",
+
+		       test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
+		       "; AES/CCMP with WPA" : "",
+		       test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
+		       ", WPA2" : "",
+		       test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
+		       ", WPA2PSK" : "");
+
+		set_default_iw_params(wnd);
+	}
+	status = mp_query_int(wnd, OID_GEN_MEDIA_CONNECT_STATUS, (int *)buf);
+	if (status == NDIS_STATUS_SUCCESS)
+		set_media_state(wnd, *((int *)buf));
+	kfree(buf);
+	wrap_procfs_add_ndis_device(wnd);
+	hangcheck_add(wnd);
+	add_iw_stats_timer(wnd);
+	EXIT1(return NDIS_STATUS_SUCCESS);
+
+buffer_pool_err:
+	wnd->tx_buffer_pool = NULL;
+	if (wnd->tx_packet_pool) {
+		NdisFreePacketPool(wnd->tx_packet_pool);
+		wnd->tx_packet_pool = NULL;
+	}
+packet_pool_err:
+err_register:
+	kfree(buf);
+err_start:
+	ndis_remove_device(wnd);
+	EXIT1(return NDIS_STATUS_FAILURE);
+}
+
+static int ndis_remove_device(struct ndis_device *wnd)
+{
+	s8 tx_pending;
+
+	/* prevent setting essid during disassociation */
+	memset(&wnd->essid, 0, sizeof(wnd->essid));
+	wnd->tx_ok = 0;
+	if (wnd->max_tx_packets)
+		unregister_netdev(wnd->net_dev);
+	netif_carrier_off(wnd->net_dev);
+	/* if device is suspended, but resume failed, tx_ring_mutex
+	 * may already be locked */
+	if (down_trylock(&wnd->tx_ring_mutex))
+		WARNING("couldn't obtain tx_ring_mutex");
+	spin_lock_bh(&wnd->tx_ring_lock);
+	tx_pending = wnd->tx_ring_end - wnd->tx_ring_start;
+	if (tx_pending < 0)
+		tx_pending += TX_RING_SIZE;
+	else if (tx_pending == 0 && wnd->is_tx_ring_full)
+		tx_pending = TX_RING_SIZE - 1;
+	wnd->is_tx_ring_full = 0;
+	/* throw away pending packets */
+	while (tx_pending-- > 0) {
+		struct ndis_packet *packet;
+
+		packet = wnd->tx_ring[wnd->tx_ring_start];
+		free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING);
+		wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE;
+	}
+	spin_unlock_bh(&wnd->tx_ring_lock);
+	up(&wnd->tx_ring_mutex);
+	wrap_procfs_remove_ndis_device(wnd);
+	mp_halt(wnd);
+	ndis_exit_device(wnd);
+
+	if (wnd->tx_packet_pool) {
+		NdisFreePacketPool(wnd->tx_packet_pool);
+		wnd->tx_packet_pool = NULL;
+	}
+	if (wnd->tx_buffer_pool) {
+		NdisFreeBufferPool(wnd->tx_buffer_pool);
+		wnd->tx_buffer_pool = NULL;
+	}
+	if (wnd->pmkids)
+		kfree(wnd->pmkids);
+	printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME,
+	       wnd->net_dev->name);
+	kfree(wnd->nmb);
+	free_netdev(wnd->net_dev);
+	EXIT2(return 0);
+}
+
+static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj,
+				       struct device_object *pdo)
+{
+	struct device_object *fdo;
+	struct ndis_mp_block *nmb;
+	NTSTATUS status;
+	struct ndis_device *wnd;
+	struct net_device *net_dev;
+	struct wrap_device *wd;
+	unsigned long i;
+
+	ENTER2("%p, %p", drv_obj, pdo);
+	if (strlen(if_name) >= IFNAMSIZ) {
+		ERROR("interface name '%s' is too long", if_name);
+		return STATUS_INVALID_PARAMETER;
+	}
+	net_dev = alloc_etherdev(sizeof(*wnd));
+	if (!net_dev) {
+		ERROR("couldn't allocate device");
+		return STATUS_RESOURCES;
+	}
+	wd = pdo->reserved;
+	if (wrap_is_pci_bus(wd->dev_bus))
+		SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev);
+	if (wrap_is_usb_bus(wd->dev_bus))
+		SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev);
+	status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, 0,
+				FALSE, &fdo);
+	if (status != STATUS_SUCCESS) {
+		free_netdev(net_dev);
+		EXIT2(return status);
+	}
+	wnd = netdev_priv(net_dev);
+	TRACE1("wnd: %p", wnd);
+
+	nmb = kmalloc(sizeof(*nmb), GFP_KERNEL);
+	if (!nmb) {
+		WARNING("couldn't allocate memory");
+		IoDeleteDevice(fdo);
+		free_netdev(net_dev);
+		return STATUS_RESOURCES;
+	}
+#if defined(DEBUG) && DEBUG >= 6
+	/* poison nmb so if a driver accesses uninitialized pointers, we
+	 * know what it is */
+	for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++)
+		((unsigned long *)nmb)[i] = i + 0x8a3fc1;
+#endif
+
+	wnd->nmb = nmb;
+	nmb->wnd = wnd;
+	nmb->pdo = pdo;
+	wd->wnd = wnd;
+	wnd->wd = wd;
+	wnd->net_dev = net_dev;
+	fdo->reserved = wnd;
+	nmb->fdo = fdo;
+	if (ndis_init_device(wnd)) {
+		IoDeleteDevice(fdo);
+		kfree(nmb);
+		free_netdev(net_dev);
+		EXIT1(return STATUS_RESOURCES);
+	}
+	nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo);
+	spin_lock_init(&wnd->tx_ring_lock);
+	init_MUTEX(&wnd->tx_ring_mutex);
+	init_MUTEX(&wnd->ndis_req_mutex);
+	wnd->ndis_req_done = 0;
+	initialize_work(&wnd->tx_work, tx_worker, wnd);
+	wnd->tx_ring_start = 0;
+	wnd->tx_ring_end = 0;
+	wnd->is_tx_ring_full = 0;
+	wnd->capa.encr = 0;
+	wnd->capa.auth = 0;
+	wnd->attributes = 0;
+	wnd->dma_map_count = 0;
+	wnd->dma_map_addr = NULL;
+	wnd->nick[0] = 0;
+	init_timer(&wnd->hangcheck_timer);
+	wnd->scan_timestamp = 0;
+	init_timer(&wnd->iw_stats_timer);
+	wnd->iw_stats_interval = 10 * HZ;
+	wnd->ndis_pending_work = 0;
+	memset(&wnd->essid, 0, sizeof(wnd->essid));
+	memset(&wnd->encr_info, 0, sizeof(wnd->encr_info));
+	wnd->infrastructure_mode = Ndis802_11Infrastructure;
+	initialize_work(&wnd->ndis_work, ndis_worker, wnd);
+	wnd->iw_stats_enabled = TRUE;
+
+	TRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p",
+	       nmb, pdo, fdo, fdo->attached, nmb->next_device);
+
+	/* dispatch routines are called as Windows functions */
+	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+		drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2);
+
+	drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2);
+	drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2);
+	drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
+		WIN_FUNC_PTR(NdisDispatchDeviceControl,2);
+//	drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =
+//		WIN_FUNC_PTR(NdisDispatchDeviceControl,2);
+	EXIT2(return STATUS_SUCCESS);
+}
+
+int init_ndis_driver(struct driver_object *drv_obj)
+{
+	ENTER1("%p", drv_obj);
+	drv_obj->drv_ext->add_device = NdisAddDevice;
+	return 0;
+}
+
+int wrapndis_init(void)
+{
+	wrapndis_wq = create_singlethread_workqueue("wrapndis_wq");
+	if (!wrapndis_wq)
+		EXIT1(return -ENOMEM);
+	wrapndis_worker_thread = wrap_worker_init(wrapndis_wq);
+	TRACE1("%p", wrapndis_worker_thread);
+	register_netdevice_notifier(&netdev_notifier);
+	return 0;
+}
+
+void wrapndis_exit(void)
+{
+	unregister_netdevice_notifier(&netdev_notifier);
+	if (wrapndis_wq)
+		destroy_workqueue(wrapndis_wq);
+	TRACE1("%p", wrapndis_worker_thread);
+	if (wrapndis_worker_thread)
+		ObDereferenceObject(wrapndis_worker_thread);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/divdi3.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/divdi3.c
@@ -0,0 +1,329 @@
+/* 64-bit multiplication and division
+   Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#if BITS_PER_LONG != 32
+#error This is for 32-bit targets only
+#endif
+
+typedef unsigned int UQItype	__attribute__ ((mode (QI)));
+typedef          int SItype	__attribute__ ((mode (SI)));
+typedef unsigned int USItype	__attribute__ ((mode (SI)));
+typedef          int DItype	__attribute__ ((mode (DI)));
+typedef unsigned int UDItype	__attribute__ ((mode (DI)));
+#define Wtype SItype
+#define HWtype SItype
+#define DWtype DItype
+#define UWtype USItype
+#define UHWtype USItype
+#define UDWtype UDItype
+#define W_TYPE_SIZE 32
+
+#include "longlong.h"
+
+#if defined(__BIG_ENDIAN)
+struct DWstruct { Wtype high, low;};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct { Wtype low, high;};
+#else
+#error Unhandled endianity
+#endif
+typedef union { struct DWstruct s; DWtype ll; } DWunion;
+
+/* Prototypes of exported functions.  */
+extern DWtype __divdi3 (DWtype u, DWtype v);
+extern DWtype __moddi3 (DWtype u, DWtype v);
+extern UDWtype __udivdi3 (UDWtype u, UDWtype v);
+extern UDWtype __umoddi3 (UDWtype u, UDWtype v);
+
+static UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
+{
+  DWunion ww;
+  DWunion nn, dd;
+  DWunion rr;
+  UWtype d0, d1, n0, n1, n2;
+  UWtype q0, q1;
+  UWtype b, bm;
+
+  nn.ll = n;
+  dd.ll = d;
+
+  d0 = dd.s.low;
+  d1 = dd.s.high;
+  n0 = nn.s.low;
+  n1 = nn.s.high;
+
+#if !UDIV_NEEDS_NORMALIZATION
+  if (d1 == 0)
+    {
+      if (d0 > n1)
+	{
+	  /* 0q = nn / 0D */
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+	  q1 = 0;
+
+	  /* Remainder in n0.  */
+	}
+      else
+	{
+	  /* qq = NN / 0d */
+
+	  if (d0 == 0)
+	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
+
+	  udiv_qrnnd (q1, n1, 0, n1, d0);
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+
+	  /* Remainder in n0.  */
+	}
+
+      if (rp != 0)
+	{
+	  rr.s.low = n0;
+	  rr.s.high = 0;
+	  *rp = rr.ll;
+	}
+    }
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+  if (d1 == 0)
+    {
+      if (d0 > n1)
+	{
+	  /* 0q = nn / 0D */
+
+	  count_leading_zeros (bm, d0);
+
+	  if (bm != 0)
+	    {
+	      /* Normalize, i.e. make the most significant bit of the
+		 denominator set.  */
+
+	      d0 = d0 << bm;
+	      n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
+	      n0 = n0 << bm;
+	    }
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+	  q1 = 0;
+
+	  /* Remainder in n0 >> bm.  */
+	}
+      else
+	{
+	  /* qq = NN / 0d */
+
+	  if (d0 == 0)
+	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
+
+	  count_leading_zeros (bm, d0);
+
+	  if (bm == 0)
+	    {
+	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 leading quotient digit q1 = 1).
+
+		 This special case is necessary, not an optimization.
+		 (Shifts counts of W_TYPE_SIZE are undefined.)  */
+
+	      n1 -= d0;
+	      q1 = 1;
+	    }
+	  else
+	    {
+	      /* Normalize.  */
+
+	      b = W_TYPE_SIZE - bm;
+
+	      d0 = d0 << bm;
+	      n2 = n1 >> b;
+	      n1 = (n1 << bm) | (n0 >> b);
+	      n0 = n0 << bm;
+
+	      udiv_qrnnd (q1, n1, n2, n1, d0);
+	    }
+
+	  /* n1 != d0...  */
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+
+	  /* Remainder in n0 >> bm.  */
+	}
+
+      if (rp != 0)
+	{
+	  rr.s.low = n0 >> bm;
+	  rr.s.high = 0;
+	  *rp = rr.ll;
+	}
+    }
+#endif /* UDIV_NEEDS_NORMALIZATION */
+
+  else
+    {
+      if (d1 > n1)
+	{
+	  /* 00 = nn / DD */
+
+	  q0 = 0;
+	  q1 = 0;
+
+	  /* Remainder in n1n0.  */
+	  if (rp != 0)
+	    {
+	      rr.s.low = n0;
+	      rr.s.high = n1;
+	      *rp = rr.ll;
+	    }
+	}
+      else
+	{
+	  /* 0q = NN / dd */
+
+	  count_leading_zeros (bm, d1);
+	  if (bm == 0)
+	    {
+	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 quotient digit q0 = 0 or 1).
+
+		 This special case is necessary, not an optimization.  */
+
+	      /* The condition on the next line takes advantage of that
+		 n1 >= d1 (true due to program flow).  */
+	      if (n1 > d1 || n0 >= d0)
+		{
+		  q0 = 1;
+		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
+		}
+	      else
+		q0 = 0;
+
+	      q1 = 0;
+
+	      if (rp != 0)
+		{
+		  rr.s.low = n0;
+		  rr.s.high = n1;
+		  *rp = rr.ll;
+		}
+	    }
+	  else
+	    {
+	      UWtype m1, m0;
+	      /* Normalize.  */
+
+	      b = W_TYPE_SIZE - bm;
+
+	      d1 = (d1 << bm) | (d0 >> b);
+	      d0 = d0 << bm;
+	      n2 = n1 >> b;
+	      n1 = (n1 << bm) | (n0 >> b);
+	      n0 = n0 << bm;
+
+	      udiv_qrnnd (q0, n1, n2, n1, d1);
+	      umul_ppmm (m1, m0, q0, d0);
+
+	      if (m1 > n1 || (m1 == n1 && m0 > n0))
+		{
+		  q0--;
+		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
+		}
+
+	      q1 = 0;
+
+	      /* Remainder in (n1n0 - m1m0) >> bm.  */
+	      if (rp != 0)
+		{
+		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
+		  rr.s.low = (n1 << b) | (n0 >> bm);
+		  rr.s.high = n1 >> bm;
+		  *rp = rr.ll;
+		}
+	    }
+	}
+    }
+
+  ww.s.low = q0;
+  ww.s.high = q1;
+  return ww.ll;
+}
+
+DWtype
+__divdi3 (DWtype u, DWtype v)
+{
+  Wtype c = 0;
+  DWtype w;
+
+  if (u < 0)
+    {
+      c = ~c;
+      u = -u;
+    }
+  if (v < 0)
+    {
+      c = ~c;
+      v = -v;
+    }
+  w = __udivmoddi4 (u, v, NULL);
+  if (c)
+    w = -w;
+  return w;
+}
+
+DWtype
+__moddi3 (DWtype u, DWtype v)
+{
+  Wtype c = 0;
+  DWtype w;
+
+  if (u < 0)
+    {
+      c = ~c;
+      u = -u;
+    }
+  if (v < 0)
+    v = -v;
+  __udivmoddi4 (u, v, &w);
+  if (c)
+    w = -w;
+  return w;
+}
+
+UDWtype
+__udivdi3 (UDWtype u, UDWtype v)
+{
+  return __udivmoddi4 (u, v, NULL);
+}
+
+UDWtype
+__umoddi3 (UDWtype u, UDWtype v)
+{
+  UDWtype w;
+
+  __udivmoddi4 (u, v, &w);
+  return w;
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/usb.h
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/usb.h
@@ -0,0 +1,376 @@
+/*
+ *  Copyright (C) 2004 Jan Kiszka
+ *  Copyright (C) 2005 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include "ntoskernel.h"
+
+#define IOCTL_INTERNAL_USB_SUBMIT_URB			0x00220003
+#define IOCTL_INTERNAL_USB_RESET_PORT			0x00220007
+#define IOCTL_INTERNAL_USB_GET_PORT_STATUS		0x00220013
+#define IOCTL_INTERNAL_USB_CYCLE_PORT			0x0022001F
+#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION	0x00220027
+
+#define URB_FUNCTION_SELECT_CONFIGURATION            0x0000
+#define URB_FUNCTION_SELECT_INTERFACE                0x0001
+#define URB_FUNCTION_ABORT_PIPE                      0x0002
+#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL       0x0003
+#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL    0x0004
+#define URB_FUNCTION_GET_FRAME_LENGTH                0x0005
+#define URB_FUNCTION_SET_FRAME_LENGTH                0x0006
+#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER        0x0007
+#define URB_FUNCTION_CONTROL_TRANSFER                0x0008
+#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER      0x0009
+#define URB_FUNCTION_ISOCH_TRANSFER                  0x000A
+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE      0x000B
+#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE        0x000C
+#define URB_FUNCTION_SET_FEATURE_TO_DEVICE           0x000D
+#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE        0x000E
+#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT         0x000F
+#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE         0x0010
+#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE      0x0011
+#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT       0x0012
+#define URB_FUNCTION_GET_STATUS_FROM_DEVICE          0x0013
+#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE       0x0014
+#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT        0x0015
+#define URB_FUNCTION_RESERVED_0X0016                 0x0016
+#define URB_FUNCTION_VENDOR_DEVICE                   0x0017
+#define URB_FUNCTION_VENDOR_INTERFACE                0x0018
+#define URB_FUNCTION_VENDOR_ENDPOINT                 0x0019
+#define URB_FUNCTION_CLASS_DEVICE                    0x001A
+#define URB_FUNCTION_CLASS_INTERFACE                 0x001B
+#define URB_FUNCTION_CLASS_ENDPOINT                  0x001C
+#define URB_FUNCTION_RESERVE_0X001D                  0x001D
+#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E
+#define URB_FUNCTION_CLASS_OTHER                     0x001F
+#define URB_FUNCTION_VENDOR_OTHER                    0x0020
+#define URB_FUNCTION_GET_STATUS_FROM_OTHER           0x0021
+#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER          0x0022
+#define URB_FUNCTION_SET_FEATURE_TO_OTHER            0x0023
+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT    0x0024
+#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT      0x0025
+#define URB_FUNCTION_GET_CONFIGURATION               0x0026
+#define URB_FUNCTION_GET_INTERFACE                   0x0027
+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE   0x0028
+#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE     0x0029
+#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR       0x002A
+#define URB_FUNCTION_RESERVE_0X002B                  0x002B
+#define URB_FUNCTION_RESERVE_0X002C                  0x002C
+#define URB_FUNCTION_RESERVE_0X002D                  0x002D
+#define URB_FUNCTION_RESERVE_0X002E                  0x002E
+#define URB_FUNCTION_RESERVE_0X002F                  0x002F
+// USB 2.0 calls start at 0x0030
+#define URB_FUNCTION_SYNC_RESET_PIPE                 0x0030
+#define URB_FUNCTION_SYNC_CLEAR_STALL                0x0031
+#define URB_FUNCTION_CONTROL_TRANSFER_EX             0x0032
+
+#define USBD_PF_CHANGE_MAX_PACKET		0x00000001
+
+#define USBD_TRANSFER_DIRECTION_OUT		0
+#define USBD_TRANSFER_DIRECTION_IN		1
+
+#define USBD_SHORT_TRANSFER_OK			0x00000002
+#define USBD_START_ISO_TRANSFER_ASAP		0x00000004
+#define USBD_DEFAULT_PIPE_TRANSFER		0x00000008
+
+#define USBD_TRANSFER_DIRECTION(flags)		\
+	((flags) & USBD_TRANSFER_DIRECTION_IN)
+
+enum pipe_type {UsbdPipeTypeControl = USB_ENDPOINT_XFER_CONTROL,
+		UsbdPipeTypeIsochronous = USB_ENDPOINT_XFER_ISOC,
+		UsbdPipeTypeBulk = USB_ENDPOINT_XFER_BULK,
+		UsbdPipeTypeInterrupt = USB_ENDPOINT_XFER_INT};
+
+#define USBD_IS_BULK_PIPE(pipe_handle)					\
+	(((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)	\
+	 == USB_ENDPOINT_XFER_BULK)
+
+#define USBD_IS_INT_PIPE(pipe_handle)					\
+	(((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)	\
+	 == USB_ENDPOINT_XFER_INT)
+
+#define USBD_PORT_ENABLED			0x00000001
+#define USBD_PORT_CONNECTED			0x00000002
+
+typedef LONG USBD_STATUS;
+
+#define USBD_STATUS_SUCCESS			0x0
+#define USBD_STATUS_PENDING			0x40000000
+#define USBD_STATUS_CANCELED			0x00010000
+
+#define USBD_STATUS_CRC				0xC0000001
+#define USBD_STATUS_BTSTUFF			0xC0000002
+#define USBD_STATUS_DATA_TOGGLE_MISMATCH	0xC0000003
+#define USBD_STATUS_STALL_PID			0xC0000004
+#define USBD_STATUS_DEV_NOT_RESPONDING		0xC0000005
+#define USBD_STATUS_PID_CHECK_FAILURE		0xC0000006
+#define USBD_STATUS_UNEXPECTED_PID	     	0xC0000007
+#define USBD_STATUS_DATA_OVERRUN		0xC0000008
+#define USBD_STATUS_DATA_UNDERRUN		0xC0000009
+#define USBD_STATUS_RESERVED1			0xC000000A
+#define USBD_STATUS_RESERVED2			0xC000000B
+#define USBD_STATUS_BUFFER_OVERRUN		0xC000000C
+#define USBD_STATUS_BUFFER_UNDERRUN		0xC000000D
+#define USBD_STATUS_NOT_ACCESSED		0xC000000F
+#define USBD_STATUS_FIFO			0xC0000010
+#define USBD_STATUS_XACT_ERROR			0xC0000011
+#define USBD_STATUS_BABBLE_DETECTED		0xC0000012
+#define USBD_STATUS_DATA_BUFFER_ERROR		0xC0000013
+
+#define USBD_STATUS_NOT_SUPPORTED		0xC0000E00
+#define USBD_STATUS_BUFFER_TOO_SMALL		0xC0003000
+#define USBD_STATUS_TIMEOUT			0xC0006000
+#define USBD_STATUS_DEVICE_GONE			0xC0007000
+
+#define USBD_STATUS_NO_MEMORY			0x80000100
+#define USBD_STATUS_INVALID_URB_FUNCTION	0x80000200
+#define USBD_STATUS_INVALID_PARAMETER		0x80000300
+#define USBD_STATUS_REQUEST_FAILED		0x80000500
+#define USBD_STATUS_INVALID_PIPE_HANDLE		0x80000600
+#define USBD_STATUS_ERROR_SHORT_TRANSFER	0x80000900
+
+#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE	PAGE_SIZE
+
+struct urb_hcd_area {
+	void *reserved8[8];
+};
+
+typedef struct usb_endpoint_descriptor *usbd_pipe_handle;
+typedef struct usb_descriptor_header usb_common_descriptor_t;
+
+struct usbd_pipe_information {
+	USHORT wMaxPacketSize;
+	UCHAR bEndpointAddress;
+	UCHAR bInterval;
+	enum pipe_type type;
+	usbd_pipe_handle handle;
+	ULONG max_tx_size;
+	ULONG flags;
+};
+
+struct usbd_interface_information {
+	USHORT bLength;
+	UCHAR bInterfaceNumber;
+	UCHAR bAlternateSetting;
+	UCHAR bInterfaceClass;
+	UCHAR bInterfaceSubClass;
+	UCHAR bInterfaceProtocol;
+	UCHAR reserved;
+	void *handle;
+	ULONG bNumEndpoints;
+	struct usbd_pipe_information pipes[1];
+};
+
+struct usbd_interface_list_entry {
+	struct usb_interface_descriptor *intf_desc;
+	struct usbd_interface_information *intf;
+};
+
+struct nt_urb_header {
+	USHORT length;
+	USHORT function;
+	USBD_STATUS status;
+	void *usbd_dev_handle;
+	ULONG usbd_flags;
+};
+
+struct usbd_select_interface {
+	struct nt_urb_header header;
+	void *handle;
+	struct usbd_interface_information intf;
+};
+
+struct usbd_select_configuration {
+	struct nt_urb_header header;
+	struct usb_config_descriptor *config;
+	void *handle;
+	struct usbd_interface_information intf;
+};
+
+struct usbd_control_descriptor_request {
+	struct nt_urb_header header;
+	void *reserved;
+	ULONG reserved0;
+	ULONG transfer_buffer_length;
+	void *transfer_buffer;
+	struct mdl *mdl;
+	union nt_urb *urb_link;
+	struct urb_hcd_area hca;
+	USHORT reserved1;
+	UCHAR index;
+	UCHAR desc_type;
+	USHORT language_id;
+	USHORT reserved2;
+};
+
+struct usbd_bulk_or_intr_transfer {
+	struct nt_urb_header header;
+	usbd_pipe_handle pipe_handle;
+	ULONG transfer_flags;
+	ULONG transfer_buffer_length;
+	void *transfer_buffer;
+	struct mdl *mdl;
+	union nt_urb *urb_link;
+	struct urb_hcd_area hca;
+};
+
+struct usbd_pipe_request {
+	struct nt_urb_header header;
+	usbd_pipe_handle pipe_handle;
+};
+
+struct usbd_vendor_or_class_request {
+	struct nt_urb_header header;
+	void *reserved;
+	ULONG transfer_flags;
+	ULONG transfer_buffer_length;
+	void *transfer_buffer;
+	struct mdl *mdl;
+	union nt_urb *link;
+	struct urb_hcd_area hca;
+	UCHAR reserved_bits;
+	UCHAR request;
+	USHORT value;
+	USHORT index;
+	USHORT reserved1;
+};
+
+struct urb_control_feature_request {
+	struct nt_urb_header header;
+	void *reserved;
+	ULONG reserved2;
+	ULONG reserved3;
+	void *reserved4;
+	struct mdl *reserved5;
+	union nt_urb *link;
+	struct urb_hcd_area hca;
+	USHORT reserved0;
+	USHORT feature_selector;
+	USHORT index;
+	USHORT reserved1;
+};
+
+struct urb_control_get_status_request {
+	struct nt_urb_header header;
+	void *reserved;
+	ULONG reserved0;
+	ULONG transfer_buffer_length;
+	void *transfer_buffer;
+	struct mdl *mdl;
+	union nt_urb *link;
+	struct urb_hcd_area hca;
+	UCHAR reserved1[4];
+	USHORT index;
+	USHORT reserved2;
+};
+
+struct usbd_iso_packet_desc {
+	ULONG offset;
+	ULONG length;
+	USBD_STATUS status;
+};
+
+struct usbd_isochronous_transfer {
+	struct nt_urb_header header;
+	usbd_pipe_handle pipe_handle;
+	ULONG transfer_flags;
+	ULONG transfer_buffer_length;
+	void *transfer_buffer;
+	struct mdl *mdl;
+	union nt_urb *urb_link;
+	struct urb_hcd_area hca;
+	ULONG start_frame;
+	ULONG number_of_packets;
+	ULONG error_count;
+	struct usbd_iso_packet_desc iso_packet[1];
+};
+
+union nt_urb {
+	struct nt_urb_header header;
+	struct usbd_select_interface select_intf;
+	struct usbd_select_configuration select_conf;
+	struct usbd_bulk_or_intr_transfer bulk_int_transfer;
+	struct usbd_control_descriptor_request control_desc;
+	struct usbd_vendor_or_class_request vendor_class_request;
+	struct usbd_isochronous_transfer isochronous;
+	struct usbd_pipe_request pipe_req;
+	struct urb_control_feature_request feat_req;
+	struct urb_control_get_status_request status_req;
+};
+
+struct usbd_bus_interface_usbdi {
+	USHORT Size;
+	USHORT Version;
+	void *Context;
+	void *InterfaceReference;
+	void *InterfaceDereference;
+	void *GetUSBDIVersion;
+	void *QueryBusTime;
+	void *SubmitIsoOutUrb;
+	void *QueryBusInformation;
+	/* version 1 and above have following field */
+	void *IsDeviceHighSpeed;
+	/* version 2 (and above) have following field */
+	void *LogEntry;
+};
+
+struct usbd_bus_information_level {
+	ULONG TotalBandwidth;
+	ULONG ConsumedBandwidth;
+	/* level 1 and above have following fields */
+	ULONG ControllerNameLength;
+	wchar_t ControllerName[1];
+};
+
+#define USBDI_VERSION_XP			0x00000500 // Windows XP
+#define USB_HCD_CAPS_SUPPORTS_RT_THREADS	0x00000001
+#define USB_BUSIF_USBDI_VERSION_0		0x0000
+#define USB_BUSIF_USBDI_VERSION_1		0x0001
+#define USB_BUSIF_USBDI_VERSION_2		0x0002
+
+struct usbd_version_info {
+	ULONG usbdi_version;
+	ULONG supported_usb_version;
+};
+
+struct usbd_idle_callback {
+	void *callback;
+	void *context;
+};
+
+#define NT_URB_STATUS(nt_urb) ((nt_urb)->header.status)
+
+NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp);
+void wrap_suspend_urbs(struct wrap_device *wd);
+void wrap_resume_urbs(struct wrap_device *wd);
+
+void USBD_InterfaceGetUSBDIVersion(void *context,
+				   struct usbd_version_info *version_info,
+				   ULONG *hcd_capa) wstdcall;
+BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context) wstdcall;
+void USBD_InterfaceReference(void *context) wstdcall;
+void USBD_InterfaceDereference(void *context) wstdcall;
+NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame) wstdcall;
+NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context,
+				       union nt_urb *nt_urb) wstdcall;
+NTSTATUS USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf,
+					   ULONG *buf_length,
+					   ULONG *buf_actual_length) wstdcall;
+NTSTATUS USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag,
+				ULONG p1, ULONG p2) wstdcall;
+
+#endif /* USB_H */
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/proc.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/proc.c
@@ -0,0 +1,565 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+#include "ndis.h"
+#include "iw_ndis.h"
+#include "wrapndis.h"
+#include "pnp.h"
+#include "wrapper.h"
+
+#define MAX_PROC_STR_LEN 32
+
+static struct proc_dir_entry *wrap_procfs_entry;
+
+static int procfs_read_ndis_stats(char *page, char **start, off_t off,
+				  int count, int *eof, void *data)
+{
+	char *p = page;
+	struct ndis_device *wnd = (struct ndis_device *)data;
+	struct ndis_wireless_stats stats;
+	NDIS_STATUS res;
+	ndis_rssi rssi;
+
+	if (off != 0) {
+		*eof = 1;
+		return 0;
+	}
+
+	res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi));
+	if (!res)
+		p += sprintf(p, "signal_level=%d dBm\n", (s32)rssi);
+
+	res = mp_query(wnd, OID_802_11_STATISTICS, &stats, sizeof(stats));
+	if (!res) {
+
+		p += sprintf(p, "tx_frames=%Lu\n", stats.tx_frag);
+		p += sprintf(p, "tx_multicast_frames=%Lu\n",
+			     stats.tx_multi_frag);
+		p += sprintf(p, "tx_failed=%Lu\n", stats.failed);
+		p += sprintf(p, "tx_retry=%Lu\n", stats.retry);
+		p += sprintf(p, "tx_multi_rerty=%Lu\n", stats.multi_retry);
+		p += sprintf(p, "tx_rtss_success=%Lu\n", stats.rtss_succ);
+		p += sprintf(p, "tx_rtss_fail=%Lu\n", stats.rtss_fail);
+		p += sprintf(p, "ack_fail=%Lu\n", stats.ack_fail);
+		p += sprintf(p, "frame_duplicates=%Lu\n", stats.frame_dup);
+		p += sprintf(p, "rx_frames=%Lu\n", stats.rx_frag);
+		p += sprintf(p, "rx_multicast_frames=%Lu\n",
+			     stats.rx_multi_frag);
+		p += sprintf(p, "fcs_errors=%Lu\n", stats.fcs_err);
+	}
+
+	if (p - page > count) {
+		ERROR("wrote %lu bytes (limit is %u)\n",
+		      (unsigned long)(p - page), count);
+		*eof = 1;
+	}
+
+	return p - page;
+}
+
+static int procfs_read_ndis_encr(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
+{
+	char *p = page;
+	struct ndis_device *wnd = (struct ndis_device *)data;
+	int i, encr_status, auth_mode, infra_mode;
+	NDIS_STATUS res;
+	struct ndis_essid essid;
+	mac_address ap_address;
+
+	if (off != 0) {
+		*eof = 1;
+		return 0;
+	}
+
+	res = mp_query(wnd, OID_802_11_BSSID,
+		       &ap_address, sizeof(ap_address));
+	if (res)
+		memset(ap_address, 0, ETH_ALEN);
+	p += sprintf(p, "ap_address=%2.2X", ap_address[0]);
+	for (i = 1 ; i < ETH_ALEN ; i++)
+		p += sprintf(p, ":%2.2X", ap_address[i]);
+	p += sprintf(p, "\n");
+
+	res = mp_query(wnd, OID_802_11_SSID, &essid, sizeof(essid));
+	if (!res)
+		p += sprintf(p, "essid=%.*s\n", essid.length, essid.essid);
+
+	res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &encr_status);
+	if (!res) {
+		typeof(&wnd->encr_info.keys[0]) tx_key;
+		p += sprintf(p, "tx_key=%u\n", wnd->encr_info.tx_key_index);
+		p += sprintf(p, "key=");
+		tx_key = &wnd->encr_info.keys[wnd->encr_info.tx_key_index];
+		if (tx_key->length > 0)
+			for (i = 0; i < tx_key->length; i++)
+				p += sprintf(p, "%2.2X", tx_key->key[i]);
+		else
+			p += sprintf(p, "off");
+		p += sprintf(p, "\n");
+		p += sprintf(p, "encr_mode=%d\n", encr_status);
+	}
+	res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &auth_mode);
+	if (!res)
+		p += sprintf(p, "auth_mode=%d\n", auth_mode);
+	res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &infra_mode);
+	p += sprintf(p, "mode=%s\n", (infra_mode == Ndis802_11IBSS) ?
+		     "adhoc" : (infra_mode == Ndis802_11Infrastructure) ?
+		     "managed" : "auto");
+	if (p - page > count) {
+		WARNING("wrote %lu bytes (limit is %u)",
+			(unsigned long)(p - page), count);
+		*eof = 1;
+	}
+
+	return p - page;
+}
+
+static int procfs_read_ndis_hw(char *page, char **start, off_t off,
+			       int count, int *eof, void *data)
+{
+	char *p = page;
+	struct ndis_device *wnd = (struct ndis_device *)data;
+	struct ndis_configuration config;
+	unsigned int power_mode;
+	NDIS_STATUS res;
+	ndis_tx_power_level tx_power;
+	ULONG bit_rate;
+	ndis_rts_threshold rts_threshold;
+	ndis_fragmentation_threshold frag_threshold;
+	ndis_antenna antenna;
+	ULONG packet_filter;
+	int n;
+	mac_address mac;
+	char *hw_status[] = {"ready", "initializing", "resetting", "closing",
+			     "not ready"};
+
+	if (off != 0) {
+		*eof = 1;
+		return 0;
+	}
+
+	res = mp_query_int(wnd, OID_GEN_HARDWARE_STATUS, &n);
+	if (res == NDIS_STATUS_SUCCESS &&
+	    n >= 0 && n < sizeof(hw_status) / sizeof(hw_status[0]))
+		p += sprintf(p, "status=%s\n", hw_status[n]);
+
+	res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac));
+	if (!res)
+		p += sprintf(p, "mac: " MACSTRSEP "\n", MAC2STR(mac));
+	res = mp_query(wnd, OID_802_11_CONFIGURATION, &config, sizeof(config));
+	if (!res) {
+		p += sprintf(p, "beacon_period=%u msec\n",
+			     config.beacon_period);
+		p += sprintf(p, "atim_window=%u msec\n", config.atim_window);
+		p += sprintf(p, "frequency=%u kHZ\n", config.ds_config);
+		p += sprintf(p, "hop_pattern=%u\n",
+			     config.fh_config.hop_pattern);
+		p += sprintf(p, "hop_set=%u\n",
+			     config.fh_config.hop_set);
+		p += sprintf(p, "dwell_time=%u msec\n",
+			     config.fh_config.dwell_time);
+	}
+
+	res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL,
+		       &tx_power, sizeof(tx_power));
+	if (!res)
+		p += sprintf(p, "tx_power=%u mW\n", tx_power);
+
+	res = mp_query(wnd, OID_GEN_LINK_SPEED, &bit_rate, sizeof(bit_rate));
+	if (!res)
+		p += sprintf(p, "bit_rate=%u kBps\n", (u32)bit_rate / 10);
+
+	res = mp_query(wnd, OID_802_11_RTS_THRESHOLD,
+		       &rts_threshold, sizeof(rts_threshold));
+	if (!res)
+		p += sprintf(p, "rts_threshold=%u bytes\n", rts_threshold);
+
+	res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD,
+		       &frag_threshold, sizeof(frag_threshold));
+	if (!res)
+		p += sprintf(p, "frag_threshold=%u bytes\n", frag_threshold);
+
+	res = mp_query_int(wnd, OID_802_11_POWER_MODE, &power_mode);
+	if (!res)
+		p += sprintf(p, "power_mode=%s\n",
+			     (power_mode == NDIS_POWER_OFF) ? "always_on" :
+			     (power_mode == NDIS_POWER_MAX) ?
+			     "max_savings" : "min_savings");
+
+	res = mp_query(wnd, OID_802_11_NUMBER_OF_ANTENNAS,
+		       &antenna, sizeof(antenna));
+	if (!res)
+		p += sprintf(p, "num_antennas=%u\n", antenna);
+
+	res = mp_query(wnd, OID_802_11_TX_ANTENNA_SELECTED,
+		       &antenna, sizeof(antenna));
+	if (!res)
+		p += sprintf(p, "tx_antenna=%u\n", antenna);
+
+	res = mp_query(wnd, OID_802_11_RX_ANTENNA_SELECTED,
+		       &antenna, sizeof(antenna));
+	if (!res)
+		p += sprintf(p, "rx_antenna=%u\n", antenna);
+
+	p += sprintf(p, "encryption_modes=%s%s%s%s%s%s%s\n",
+		     test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
+		     "WEP" : "none",
+
+		     test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
+		     "; TKIP with WPA" : "",
+		     test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
+		     ", WPA2" : "",
+		     test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
+		     ", WPA2PSK" : "",
+
+		     test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
+		     "; AES/CCMP with WPA" : "",
+		     test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
+		     ", WPA2" : "",
+		     test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
+		     ", WPA2PSK" : "");
+
+	res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter);
+	if (!res) {
+		if (packet_filter != wnd->packet_filter)
+			WARNING("wrong packet_filter? 0x%08x, 0x%08x\n",
+				packet_filter, wnd->packet_filter);
+		p += sprintf(p, "packet_filter: 0x%08x\n", packet_filter);
+	}
+	if (p - page > count) {
+		WARNING("wrote %lu bytes (limit is %u)",
+			(unsigned long)(p - page), count);
+		*eof = 1;
+	}
+
+	return p - page;
+}
+
+static int procfs_read_ndis_settings(char *page, char **start, off_t off,
+				     int count, int *eof, void *data)
+{
+	char *p = page;
+	struct ndis_device *wnd = (struct ndis_device *)data;
+	struct wrap_device_setting *setting;
+
+	if (off != 0) {
+		*eof = 1;
+		return 0;
+	}
+
+	p += sprintf(p, "hangcheck_interval=%d\n",
+		     hangcheck_interval == 0 ?
+		     (int)(wnd->hangcheck_interval / HZ) : -1);
+
+	list_for_each_entry(setting, &wnd->wd->settings, list) {
+		p += sprintf(p, "%s=%s\n", setting->name, setting->value);
+	}
+
+	list_for_each_entry(setting, &wnd->wd->driver->settings, list) {
+		p += sprintf(p, "%s=%s\n", setting->name, setting->value);
+	}
+
+	return p - page;
+}
+
+static int procfs_write_ndis_settings(struct file *file, const char __user *buf,
+				      unsigned long count, void *data)
+{
+	struct ndis_device *wnd = (struct ndis_device *)data;
+	char setting[MAX_PROC_STR_LEN], *p;
+	unsigned int i;
+	NDIS_STATUS res;
+
+	if (count > MAX_PROC_STR_LEN)
+		return -EINVAL;
+
+	memset(setting, 0, sizeof(setting));
+	if (copy_from_user(setting, buf, count))
+		return -EFAULT;
+
+	if ((p = strchr(setting, '\n')))
+		*p = 0;
+
+	if ((p = strchr(setting, '=')))
+		*p = 0;
+
+	if (!strcmp(setting, "hangcheck_interval")) {
+		if (!p)
+			return -EINVAL;
+		p++;
+		i = simple_strtol(p, NULL, 10);
+		hangcheck_del(wnd);
+		if (i > 0) {
+			wnd->hangcheck_interval = i * HZ;
+			hangcheck_add(wnd);
+		}
+	} else if (!strcmp(setting, "suspend")) {
+		if (!p)
+			return -EINVAL;
+		p++;
+		i = simple_strtol(p, NULL, 10);
+		if (i <= 0 || i > 3)
+			return -EINVAL;
+		if (wrap_is_pci_bus(wnd->wd->dev_bus))
+			i = wrap_pnp_suspend_pci_device(wnd->wd->pci.pdev,
+							PMSG_SUSPEND);
+		else
+#ifdef ENABLE_USB
+			i = wrap_pnp_suspend_usb_device(wnd->wd->usb.intf,
+							PMSG_SUSPEND);
+#else
+		i = -1;
+#endif
+		if (i)
+			return -EINVAL;
+	} else if (!strcmp(setting, "resume")) {
+		if (wrap_is_pci_bus(wnd->wd->dev_bus))
+			i = wrap_pnp_resume_pci_device(wnd->wd->pci.pdev);
+		else
+#ifdef ENABLE_USB
+			i = wrap_pnp_resume_usb_device(wnd->wd->usb.intf);
+#else
+		i = -1;
+#endif
+		if (i)
+			return -EINVAL;
+	} else if (!strcmp(setting, "stats_enabled")) {
+		if (!p)
+			return -EINVAL;
+		p++;
+		i = simple_strtol(p, NULL, 10);
+		if (i > 0)
+			wnd->iw_stats_enabled = TRUE;
+		else
+			wnd->iw_stats_enabled = FALSE;
+	} else if (!strcmp(setting, "packet_filter")) {
+		if (!p)
+			return -EINVAL;
+		p++;
+		i = simple_strtol(p, NULL, 10);
+		res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, i);
+		if (res)
+			WARNING("setting packet_filter failed: %08X", res);
+	} else if (!strcmp(setting, "reinit")) {
+		if (ndis_reinit(wnd) != NDIS_STATUS_SUCCESS)
+			return -EFAULT;
+	} else {
+		struct ndis_configuration_parameter param;
+		struct unicode_string key;
+		struct ansi_string ansi;
+
+		if (!p)
+			return -EINVAL;
+		p++;
+		RtlInitAnsiString(&ansi, p);
+		if (RtlAnsiStringToUnicodeString(&param.data.string, &ansi,
+						 TRUE) != STATUS_SUCCESS)
+			EXIT1(return -EFAULT);
+		param.type = NdisParameterString;
+		RtlInitAnsiString(&ansi, setting);
+		if (RtlAnsiStringToUnicodeString(&key, &ansi,
+						 TRUE) != STATUS_SUCCESS) {
+			RtlFreeUnicodeString(&param.data.string);
+			EXIT1(return -EINVAL);
+		}
+		NdisWriteConfiguration(&res, wnd->nmb, &key, &param);
+		RtlFreeUnicodeString(&key);
+		RtlFreeUnicodeString(&param.data.string);
+		if (res != NDIS_STATUS_SUCCESS)
+			return -EFAULT;
+	}
+	return count;
+}
+
+int wrap_procfs_add_ndis_device(struct ndis_device *wnd)
+{
+	struct proc_dir_entry *procfs_entry;
+
+	if (wrap_procfs_entry == NULL)
+		return -ENOMEM;
+
+	if (wnd->procfs_iface) {
+		ERROR("%s already registered?", wnd->netdev_name);
+		return -EINVAL;
+	}
+	wnd->procfs_iface = proc_mkdir(wnd->netdev_name, wrap_procfs_entry);
+	if (wnd->procfs_iface == NULL) {
+		ERROR("couldn't create proc directory");
+		return -ENOMEM;
+	}
+	wnd->procfs_iface->uid = proc_uid;
+	wnd->procfs_iface->gid = proc_gid;
+
+	procfs_entry = create_proc_entry("hw", S_IFREG | S_IRUSR | S_IRGRP,
+					 wnd->procfs_iface);
+	if (procfs_entry == NULL) {
+		ERROR("couldn't create proc entry for 'hw'");
+		goto err_hw;
+	} else {
+		procfs_entry->uid = proc_uid;
+		procfs_entry->gid = proc_gid;
+		procfs_entry->data = wnd;
+		procfs_entry->read_proc = procfs_read_ndis_hw;
+	}
+
+	procfs_entry = create_proc_entry("stats", S_IFREG | S_IRUSR | S_IRGRP,
+					 wnd->procfs_iface);
+	if (procfs_entry == NULL) {
+		ERROR("couldn't create proc entry for 'stats'");
+		goto err_stats;
+	} else {
+		procfs_entry->uid = proc_uid;
+		procfs_entry->gid = proc_gid;
+		procfs_entry->data = wnd;
+		procfs_entry->read_proc = procfs_read_ndis_stats;
+	}
+
+	procfs_entry = create_proc_entry("encr", S_IFREG | S_IRUSR | S_IRGRP,
+					 wnd->procfs_iface);
+	if (procfs_entry == NULL) {
+		ERROR("couldn't create proc entry for 'encr'");
+		goto err_encr;
+	} else {
+		procfs_entry->uid = proc_uid;
+		procfs_entry->gid = proc_gid;
+		procfs_entry->data = wnd;
+		procfs_entry->read_proc = procfs_read_ndis_encr;
+	}
+
+	procfs_entry = create_proc_entry("settings", S_IFREG |
+					 S_IRUSR | S_IRGRP |
+					 S_IWUSR | S_IWGRP, wnd->procfs_iface);
+	if (procfs_entry == NULL) {
+		ERROR("couldn't create proc entry for 'settings'");
+		goto err_settings;
+	} else {
+		procfs_entry->uid = proc_uid;
+		procfs_entry->gid = proc_gid;
+		procfs_entry->data = wnd;
+		procfs_entry->read_proc = procfs_read_ndis_settings;
+		procfs_entry->write_proc = procfs_write_ndis_settings;
+	}
+	return 0;
+
+err_settings:
+	remove_proc_entry("encr", wnd->procfs_iface);
+err_encr:
+	remove_proc_entry("stats", wnd->procfs_iface);
+err_stats:
+	remove_proc_entry("hw", wnd->procfs_iface);
+err_hw:
+	remove_proc_entry(wnd->netdev_name, wrap_procfs_entry);
+	wnd->procfs_iface = NULL;
+	return -ENOMEM;
+}
+
+void wrap_procfs_remove_ndis_device(struct ndis_device *wnd)
+{
+	struct proc_dir_entry *procfs_iface = xchg(&wnd->procfs_iface, NULL);
+
+	if (procfs_iface == NULL)
+		return;
+	remove_proc_entry("hw", procfs_iface);
+	remove_proc_entry("stats", procfs_iface);
+	remove_proc_entry("encr", procfs_iface);
+	remove_proc_entry("settings", procfs_iface);
+	if (wrap_procfs_entry)
+		remove_proc_entry(wnd->netdev_name, wrap_procfs_entry);
+}
+
+static int procfs_read_debug(char *page, char **start, off_t off,
+			     int count, int *eof, void *data)
+{
+	char *p = page;
+	enum alloc_type type;
+
+	if (off != 0) {
+		*eof = 1;
+		return 0;
+	}
+	p += sprintf(p, "%d\n", debug);
+	type = 0;
+#ifdef ALLOC_DEBUG
+	for (type = 0; type < ALLOC_TYPE_MAX; type++)
+		p += sprintf(p, "total size of allocations in %d: %d\n",
+			     type, alloc_size(type));
+#endif
+	return p - page;
+}
+
+static int procfs_write_debug(struct file *file, const char __user *buf,
+			      unsigned long count, void *data)
+{
+	int i;
+	char setting[MAX_PROC_STR_LEN], *p;
+
+	if (count > MAX_PROC_STR_LEN)
+		return -EINVAL;
+
+	memset(setting, 0, sizeof(setting));
+	if (copy_from_user(setting, buf, count))
+		return -EFAULT;
+
+	if ((p = strchr(setting, '\n')))
+		*p = 0;
+
+	if ((p = strchr(setting, '=')))
+		*p = 0;
+
+	i = simple_strtol(setting, NULL, 10);
+	if (i >= 0 && i < 10)
+		debug = i;
+	else
+		return -EINVAL;
+	return count;
+}
+
+int wrap_procfs_init(void)
+{
+	struct proc_dir_entry *procfs_entry;
+
+	wrap_procfs_entry = proc_mkdir(DRIVER_NAME, proc_net_root);
+	if (wrap_procfs_entry == NULL) {
+		ERROR("couldn't create procfs directory");
+		return -ENOMEM;
+	}
+	wrap_procfs_entry->uid = proc_uid;
+	wrap_procfs_entry->gid = proc_gid;
+
+	procfs_entry = create_proc_entry("debug", S_IFREG | S_IRUSR | S_IRGRP,
+					 wrap_procfs_entry);
+	if (procfs_entry == NULL) {
+		ERROR("couldn't create proc entry for 'debug'");
+		return -ENOMEM;
+	} else {
+		procfs_entry->uid = proc_uid;
+		procfs_entry->gid = proc_gid;
+		procfs_entry->read_proc  = procfs_read_debug;
+		procfs_entry->write_proc = procfs_write_debug;
+	}
+	return 0;
+}
+
+void wrap_procfs_remove(void)
+{
+	if (wrap_procfs_entry == NULL)
+		return;
+	remove_proc_entry("debug", wrap_procfs_entry);
+	remove_proc_entry(DRIVER_NAME, proc_net_root);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ndis.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ndis.c
@@ -0,0 +1,2974 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ndis.h"
+#include "iw_ndis.h"
+#include "wrapndis.h"
+#include "pnp.h"
+#include "loader.h"
+#include <linux/kernel_stat.h>
+#include <asm/dma.h>
+#include "ndis_exports.h"
+
+#define MAX_ALLOCATED_NDIS_PACKETS TX_RING_SIZE
+#define MAX_ALLOCATED_NDIS_BUFFERS TX_RING_SIZE
+
+static void ndis_worker(worker_param_t dummy);
+static work_struct_t ndis_work;
+static struct nt_list ndis_work_list;
+static spinlock_t ndis_work_list_lock;
+
+workqueue_struct_t *ndis_wq;
+static struct nt_thread *ndis_worker_thread;
+
+static void *ndis_get_routine_address(char *name);
+
+wstdcall void WIN_FUNC(NdisInitializeWrapper,4)
+	(void **driver_handle, struct driver_object *driver,
+	 struct unicode_string *reg_path, void *unused)
+{
+	ENTER1("handle: %p, driver: %p", driver_handle, driver);
+	*driver_handle = driver;
+	EXIT1(return);
+}
+
+wstdcall void WIN_FUNC(NdisTerminateWrapper,2)
+	(struct device_object *dev_obj, void *system_specific)
+{
+	EXIT1(return);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3)
+	(struct driver_object *drv_obj, struct miniport *mp, UINT length)
+{
+	int min_length;
+	struct wrap_driver *wrap_driver;
+	struct ndis_driver *ndis_driver;
+
+	min_length = ((char *)&mp->co_create_vc) - ((char *)mp);
+
+	ENTER1("%p %p %d", drv_obj, mp, length);
+
+	if (mp->major_version < 4) {
+		ERROR("Driver is using ndis version %d which is too old.",
+		      mp->major_version);
+		EXIT1(return NDIS_STATUS_BAD_VERSION);
+	}
+
+	if (length < min_length) {
+		ERROR("Characteristics length %d is too small", length);
+		EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS);
+	}
+
+	TRACE1("%d.%d, %d, %u", mp->major_version, mp->minor_version, length,
+	       (u32)sizeof(struct miniport));
+	wrap_driver = IoGetDriverObjectExtension(drv_obj,
+						 (void *)WRAP_DRIVER_CLIENT_ID);
+	if (!wrap_driver) {
+		ERROR("couldn't get wrap_driver");
+		EXIT1(return NDIS_STATUS_RESOURCES);
+	}
+	if (IoAllocateDriverObjectExtension(
+		    drv_obj, (void *)NDIS_DRIVER_CLIENT_ID,
+		    sizeof(*ndis_driver), (void **)&ndis_driver) !=
+	    STATUS_SUCCESS)
+		EXIT1(return NDIS_STATUS_RESOURCES);
+	wrap_driver->ndis_driver = ndis_driver;
+	TRACE1("driver: %p", ndis_driver);
+	memcpy(&ndis_driver->mp, mp, min_t(int, sizeof(*mp), length));
+
+	DBG_BLOCK(2) {
+		int i;
+		void **func;
+		char *mp_funcs[] = {
+			"queryinfo", "reconfig", "reset", "send", "setinfo",
+			"tx_data", "return_packet", "send_packets",
+			"alloc_complete", "co_create_vc", "co_delete_vc",
+			"co_activate_vc", "co_deactivate_vc",
+			"co_send_packets", "co_request", "cancel_send_packets",
+			"pnp_event_notify", "shutdown",
+		};
+		func = (void **)&ndis_driver->mp.queryinfo;
+		for (i = 0; i < (sizeof(mp_funcs) / sizeof(mp_funcs[0])); i++)
+			TRACE2("function '%s' is at %p", mp_funcs[i], func[i]);
+	}
+	EXIT1(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6)
+	(struct driver_object *drv_obj, struct unicode_string *dev_name,
+	 struct unicode_string *link, void **funcs,
+	 struct device_object **dev_obj, void **dev_obj_handle)
+{
+	NTSTATUS status;
+	struct device_object *tmp;
+	int i;
+
+	ENTER1("%p, %p, %p", drv_obj, dev_name, link);
+	status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0,
+				FALSE, &tmp);
+
+	if (status != STATUS_SUCCESS)
+		EXIT1(return NDIS_STATUS_RESOURCES);
+	if (link)
+		status = IoCreateSymbolicLink(link, dev_name);
+	if (status != STATUS_SUCCESS) {
+		IoDeleteDevice(tmp);
+		EXIT1(return NDIS_STATUS_RESOURCES);
+	}
+
+	*dev_obj = tmp;
+	*dev_obj_handle = *dev_obj;
+	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+		if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) {
+			drv_obj->major_func[i] = funcs[i];
+			TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]);
+		}
+	EXIT1(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1)
+	(struct device_object *dev_obj)
+{
+	ENTER2("%p", dev_obj);
+	IoDeleteDevice(dev_obj);
+	return NDIS_STATUS_SUCCESS;
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3)
+	(void **dest, UINT length, ULONG tag)
+{
+	void *addr;
+
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	addr = ExAllocatePoolWithTag(NonPagedPool, length, tag);
+	TRACE4("%p", addr);
+	if (addr) {
+		*dest = addr;
+		EXIT4(return NDIS_STATUS_SUCCESS);
+	} else
+		EXIT4(return NDIS_STATUS_FAILURE);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4)
+	(void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address)
+{
+	return NdisAllocateMemoryWithTag(dest, length, 0);
+}
+
+/* length_tag is either length or tag, depending on if
+ * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate
+ * memory */
+wstdcall void WIN_FUNC(NdisFreeMemory,3)
+	(void *addr, UINT length_tag, UINT flags)
+{
+	TRACE4("%p", addr);
+	ExFreePool(addr);
+}
+
+noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12)
+	(struct driver_object *drv_obj, ULONG error, ULONG count, ...)
+{
+	va_list args;
+	int i;
+	ULONG code;
+
+	va_start(args, count);
+	ERROR("log: %08X, count: %d, return_address: %p",
+	      error, count, __builtin_return_address(0));
+	for (i = 0; i < count; i++) {
+		code = va_arg(args, ULONG);
+		ERROR("code: 0x%x", code);
+	}
+	va_end(args);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisOpenConfiguration,3)
+	(NDIS_STATUS *status, struct ndis_mp_block **conf_handle,
+	 struct ndis_mp_block *handle)
+{
+	ENTER2("%p", conf_handle);
+	*conf_handle = handle;
+	*status = NDIS_STATUS_SUCCESS;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3)
+	(NDIS_STATUS *status, void **confhandle,
+	 struct unicode_string *section)
+{
+	ENTER2("%p", confhandle);
+	*status = NDIS_STATUS_SUCCESS;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4)
+	(NDIS_STATUS *status, void *handle,
+	 struct unicode_string *key, void **subkeyhandle)
+{
+	struct ansi_string ansi;
+	ENTER2("");
+	if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) {
+		TRACE2("%s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	*subkeyhandle = handle;
+	*status = NDIS_STATUS_SUCCESS;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5)
+	(NDIS_STATUS *status, void *handle, ULONG index,
+	 struct unicode_string *key, void **subkeyhandle)
+{
+	ENTER2("%u", index);
+//	*subkeyhandle = handle;
+	*status = NDIS_STATUS_FAILURE;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisCloseConfiguration,1)
+	(void *handle)
+{
+	/* instead of freeing all configuration parameters as we are
+	 * supposed to do here, we free them when the device is
+	 * removed */
+	ENTER2("%p", handle);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisOpenFile,5)
+	(NDIS_STATUS *status, struct wrap_bin_file **file,
+	 UINT *filelength, struct unicode_string *filename,
+	 NDIS_PHY_ADDRESS highest_address)
+{
+	struct ansi_string ansi;
+	struct wrap_bin_file *bin_file;
+
+	ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file);
+	if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) !=
+	    STATUS_SUCCESS) {
+		*status = NDIS_STATUS_RESOURCES;
+		EXIT2(return);
+	}
+	TRACE2("%s", ansi.buf);
+	bin_file = get_bin_file(ansi.buf);
+	if (bin_file) {
+		*file = bin_file;
+		*filelength = bin_file->size;
+		*status = NDIS_STATUS_SUCCESS;
+	} else
+		*status = NDIS_STATUS_FILE_NOT_FOUND;
+
+	RtlFreeAnsiString(&ansi);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisMapFile,3)
+	(NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file)
+{
+	ENTER2("%p", file);
+
+	if (!file) {
+		*status = NDIS_STATUS_ALREADY_MAPPED;
+		EXIT2(return);
+	}
+
+	*status = NDIS_STATUS_SUCCESS;
+	*mappedbuffer = file->data;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisUnmapFile,1)
+	(struct wrap_bin_file *file)
+{
+	ENTER2("%p", file);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisCloseFile,1)
+	(struct wrap_bin_file *file)
+{
+	ENTER2("%p", file);
+	free_bin_file(file);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisGetSystemUpTime,1)
+	(ULONG *ms)
+{
+	*ms = 1000 * jiffies / HZ;
+	EXIT5(return);
+}
+
+wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1)
+	(ndis_buffer *buffer)
+{
+	ULONG n, length;
+
+	if (buffer == NULL)
+		EXIT2(return 0);
+	if (MmGetMdlByteCount(buffer) == 0)
+		EXIT2(return 1);
+
+	length = MmGetMdlByteCount(buffer);
+	n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length);
+	TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva,
+	       length, n);
+	EXIT3(return n);
+}
+
+wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2)
+	(ndis_buffer *buffer, UINT *arraysize)
+{
+	ENTER3("%p", buffer);
+	*arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer);
+	EXIT3(return);
+}
+
+static struct ndis_configuration_parameter *
+ndis_encode_setting(struct wrap_device_setting *setting,
+		    enum ndis_parameter_type type)
+{
+	struct ansi_string ansi;
+	struct ndis_configuration_parameter *param;
+
+	param = setting->encoded;
+	if (param) {
+		if (param->type == type)
+			EXIT2(return param);
+		if (param->type == NdisParameterString)
+			RtlFreeUnicodeString(&param->data.string);
+		setting->encoded = NULL;
+	} else
+		param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0);
+	if (!param) {
+		ERROR("couldn't allocate memory");
+		return NULL;
+	}
+	switch(type) {
+	case NdisParameterInteger:
+		param->data.integer = simple_strtol(setting->value, NULL, 0);
+		TRACE2("0x%x", (ULONG)param->data.integer);
+		break;
+	case NdisParameterHexInteger:
+		param->data.integer = simple_strtol(setting->value, NULL, 16);
+		TRACE2("0x%x", (ULONG)param->data.integer);
+		break;
+	case NdisParameterString:
+		RtlInitAnsiString(&ansi, setting->value);
+		TRACE2("'%s'", ansi.buf);
+		if (RtlAnsiStringToUnicodeString(&param->data.string,
+						 &ansi, TRUE)) {
+			ExFreePool(param);
+			EXIT2(return NULL);
+		}
+		break;
+	case NdisParameterBinary:
+		param->data.integer = simple_strtol(setting->value, NULL, 2);
+		TRACE2("0x%x", (ULONG)param->data.integer);
+		break;
+	default:
+		ERROR("unknown type: %d", type);
+		ExFreePool(param);
+		return NULL;
+	}
+	param->type = type;
+	setting->encoded = param;
+	EXIT2(return param);
+}
+
+static int ndis_decode_setting(struct wrap_device_setting *setting,
+			       struct ndis_configuration_parameter *param)
+{
+	struct ansi_string ansi;
+	struct ndis_configuration_parameter *prev;
+
+	ENTER2("%p, %p", setting, param);
+	prev = setting->encoded;
+	if (prev && prev->type == NdisParameterString) {
+		RtlFreeUnicodeString(&prev->data.string);
+		setting->encoded = NULL;
+	}
+	switch(param->type) {
+	case NdisParameterInteger:
+		snprintf(setting->value, sizeof(u32), "%u",
+			 param->data.integer);
+		setting->value[sizeof(ULONG)] = 0;
+		break;
+	case NdisParameterHexInteger:
+		snprintf(setting->value, sizeof(u32), "%x",
+			 param->data.integer);
+		setting->value[sizeof(ULONG)] = 0;
+		break;
+	case NdisParameterString:
+		ansi.buf = setting->value;
+		ansi.max_length = MAX_SETTING_VALUE_LEN;
+		if ((RtlUnicodeStringToAnsiString(&ansi, &param->data.string,
+						  FALSE) != STATUS_SUCCESS)
+		    || ansi.length >= MAX_SETTING_VALUE_LEN) {
+			EXIT1(return -1);
+		}
+		if (ansi.length == ansi.max_length)
+			ansi.length--;
+		setting->value[ansi.length] = 0;
+		break;
+	case NdisParameterBinary:
+		snprintf(setting->value, sizeof(u32), "%u",
+			 param->data.integer);
+		setting->value[sizeof(ULONG)] = 0;
+		break;
+	default:
+		TRACE2("unknown setting type: %d", param->type);
+		return -1;
+	}
+	TRACE2("setting changed %s='%s', %d", setting->name, setting->value,
+	       ansi.length);
+	return 0;
+}
+
+static int read_setting(struct nt_list *setting_list, char *keyname, int length,
+			struct ndis_configuration_parameter **param,
+			enum ndis_parameter_type type)
+{
+	struct wrap_device_setting *setting;
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	nt_list_for_each_entry(setting, setting_list, list) {
+		if (strnicmp(keyname, setting->name, length) == 0) {
+			TRACE2("setting %s='%s'", keyname, setting->value);
+			up(&loader_mutex);
+			*param = ndis_encode_setting(setting, type);
+			if (*param)
+				EXIT2(return 0);
+			else
+				EXIT2(return -1);
+		}
+	}
+	up(&loader_mutex);
+	EXIT2(return -1);
+}
+
+wstdcall void WIN_FUNC(NdisReadConfiguration,5)
+	(NDIS_STATUS *status, struct ndis_configuration_parameter **param,
+	 struct ndis_mp_block *nmb, struct unicode_string *key,
+	 enum ndis_parameter_type type)
+{
+	struct ansi_string ansi;
+	int ret;
+
+	ENTER2("nmb: %p", nmb);
+	ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE);
+	if (ret != STATUS_SUCCESS || ansi.buf == NULL) {
+		*param = NULL;
+		*status = NDIS_STATUS_FAILURE;
+		RtlFreeAnsiString(&ansi);
+		EXIT2(return);
+	}
+	TRACE2("%d, %s", type, ansi.buf);
+
+	if (read_setting(&nmb->wnd->wd->settings, ansi.buf,
+			 ansi.length, param, type) == 0 ||
+	    read_setting(&nmb->wnd->wd->driver->settings, ansi.buf,
+			 ansi.length, param, type) == 0)
+		*status = NDIS_STATUS_SUCCESS;
+	else {
+		TRACE2("setting %s not found (type:%d)", ansi.buf, type);
+		*status = NDIS_STATUS_FAILURE;
+	}
+	RtlFreeAnsiString(&ansi);
+	EXIT2(return);
+
+}
+
+wstdcall void WIN_FUNC(NdisWriteConfiguration,4)
+	(NDIS_STATUS *status, struct ndis_mp_block *nmb,
+	 struct unicode_string *key, struct ndis_configuration_parameter *param)
+{
+	struct ansi_string ansi;
+	char *keyname;
+	struct wrap_device_setting *setting;
+
+	ENTER2("nmb: %p", nmb);
+	if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE)) {
+		*status = NDIS_STATUS_FAILURE;
+		EXIT2(return);
+	}
+	keyname = ansi.buf;
+	TRACE2("%s", keyname);
+
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) {
+		if (strnicmp(keyname, setting->name, ansi.length) == 0) {
+			up(&loader_mutex);
+			if (ndis_decode_setting(setting, param))
+				*status = NDIS_STATUS_FAILURE;
+			else
+				*status = NDIS_STATUS_SUCCESS;
+			RtlFreeAnsiString(&ansi);
+			EXIT2(return);
+		}
+	}
+	up(&loader_mutex);
+	setting = kzalloc(sizeof(*setting), GFP_KERNEL);
+	if (setting) {
+		if (ansi.length == ansi.max_length)
+			ansi.length--;
+		memcpy(setting->name, keyname, ansi.length);
+		setting->name[ansi.length] = 0;
+		if (ndis_decode_setting(setting, param))
+			*status = NDIS_STATUS_FAILURE;
+		else {
+			*status = NDIS_STATUS_SUCCESS;
+			if (down_interruptible(&loader_mutex))
+				WARNING("couldn't obtain loader_mutex");
+			InsertTailList(&nmb->wnd->wd->settings, &setting->list);
+			up(&loader_mutex);
+		}
+	} else
+		*status = NDIS_STATUS_RESOURCES;
+
+	RtlFreeAnsiString(&ansi);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisReadNetworkAddress,4)
+	(NDIS_STATUS *status, void **addr, UINT *len,
+	 struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct ndis_configuration_parameter *param;
+	struct unicode_string key;
+	struct ansi_string ansi;
+	typeof(wnd->mac) mac;
+	int i, ret;
+
+	ENTER2("%p", nmb);
+	RtlInitAnsiString(&ansi, "NetworkAddress");
+	*status = NDIS_STATUS_FAILURE;
+	if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS)
+		EXIT1(return);
+
+	NdisReadConfiguration(&ret, &param, nmb, &key, NdisParameterString);
+	RtlFreeUnicodeString(&key);
+	if (ret != NDIS_STATUS_SUCCESS)
+		EXIT1(return);
+	ret = RtlUnicodeStringToAnsiString(&ansi, &param->data.string, TRUE);
+	if (ret != STATUS_SUCCESS)
+		EXIT1(return);
+
+	i = 0;
+	if (ansi.length >= 2 * sizeof(mac)) {
+		for (i = 0; i < sizeof(mac); i++) {
+			char c[3];
+			int x;
+			c[0] = ansi.buf[i*2];
+			c[1] = ansi.buf[i*2+1];
+			c[2] = 0;
+			ret = sscanf(c, "%x", &x);
+			if (ret != 1)
+				break;
+			mac[i] = x;
+		}
+	}
+	TRACE2("%s, %d, " MACSTR, ansi.buf, i, MAC2STR(mac));
+	RtlFreeAnsiString(&ansi);
+	if (i == sizeof(mac)) {
+		memcpy(wnd->mac, mac, sizeof(wnd->mac));
+		*len = sizeof(mac);
+		*addr = wnd->mac;
+		*status = NDIS_STATUS_SUCCESS;
+	}
+	EXIT1(return);
+}
+
+wstdcall void WIN_FUNC(NdisInitializeString,2)
+	(struct unicode_string *dest, UCHAR *src)
+{
+	struct ansi_string ansi;
+
+	ENTER2("");
+	if (src == NULL) {
+		dest->length = dest->max_length = 0;
+		dest->buf = NULL;
+	} else {
+		RtlInitAnsiString(&ansi, src);
+		/* the string is freed with NdisFreeMemory */
+		RtlAnsiStringToUnicodeString(dest, &ansi, TRUE);
+	}
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisInitAnsiString,2)
+	(struct ansi_string *dst, CHAR *src)
+{
+	RtlInitAnsiString(dst, src);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisInitUnicodeString,2)
+	(struct unicode_string *dest, const wchar_t *src)
+{
+	RtlInitUnicodeString(dest, src);
+	return;
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisAnsiStringToUnicodeString,2)
+	(struct unicode_string *dst, struct ansi_string *src)
+{
+	ENTER2("");
+	if (dst == NULL || src == NULL)
+		EXIT2(return NDIS_STATUS_FAILURE);
+	if (RtlAnsiStringToUnicodeString(dst, src, FALSE) == STATUS_SUCCESS)
+		return NDIS_STATUS_SUCCESS;
+	else
+		return NDIS_STATUS_FAILURE;
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisUnicodeStringToAnsiString,2)
+	(struct ansi_string *dst, struct unicode_string *src)
+{
+	ENTER2("");
+	if (dst == NULL || src == NULL)
+		EXIT2(return NDIS_STATUS_FAILURE);
+	if (RtlUnicodeStringToAnsiString(dst, src, FALSE) == STATUS_SUCCESS)
+		return NDIS_STATUS_SUCCESS;
+	else
+		return NDIS_STATUS_FAILURE;
+}
+
+wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2)
+	(struct unicode_string *dst, struct unicode_string *src)
+{
+	EXIT2(return RtlUpcaseUnicodeString(dst, src, FALSE));
+}
+
+wstdcall void WIN_FUNC(NdisMSetAttributesEx,5)
+	(struct ndis_mp_block *nmb, void *mp_ctx,
+	 UINT hangcheck_interval, UINT attributes, ULONG adaptertype)
+{
+	struct ndis_device *wnd;
+
+	ENTER1("%p, %p, %d, %08x, %d", nmb, mp_ctx, hangcheck_interval,
+	       attributes, adaptertype);
+	wnd = nmb->wnd;
+	nmb->mp_ctx = mp_ctx;
+	wnd->attributes = attributes;
+
+	if ((attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
+	    wrap_is_pci_bus(wnd->wd->dev_bus))
+		pci_set_master(wnd->wd->pci.pdev);
+
+	if (hangcheck_interval > 0)
+		wnd->hangcheck_interval = 2 * hangcheck_interval * HZ;
+	else
+		wnd->hangcheck_interval = 2 * HZ;
+
+	EXIT1(return);
+}
+
+wstdcall ULONG WIN_FUNC(NdisReadPciSlotInformation,5)
+	(struct ndis_mp_block *nmb, ULONG slot,
+	 ULONG offset, char *buf, ULONG len)
+{
+	struct wrap_device *wd = nmb->wnd->wd;
+	ULONG i;
+	for (i = 0; i < len; i++)
+		if (pci_read_config_byte(wd->pci.pdev, offset + i, &buf[i]) !=
+		    PCIBIOS_SUCCESSFUL)
+			break;
+	DBG_BLOCK(2) {
+		if (i != len)
+			WARNING("%u, %u", i, len);
+	}
+	return i;
+}
+
+wstdcall ULONG WIN_FUNC(NdisImmediateReadPciSlotInformation,5)
+	(struct ndis_mp_block *nmb, ULONG slot,
+	 ULONG offset, char *buf, ULONG len)
+{
+	return NdisReadPciSlotInformation(nmb, slot, offset, buf, len);
+}
+
+wstdcall ULONG WIN_FUNC(NdisWritePciSlotInformation,5)
+	(struct ndis_mp_block *nmb, ULONG slot,
+	 ULONG offset, char *buf, ULONG len)
+{
+	struct wrap_device *wd = nmb->wnd->wd;
+	ULONG i;
+	for (i = 0; i < len; i++)
+		if (pci_write_config_byte(wd->pci.pdev, offset + i, buf[i]) !=
+		    PCIBIOS_SUCCESSFUL)
+			break;
+	DBG_BLOCK(2) {
+		if (i != len)
+			WARNING("%u, %u", i, len);
+	}
+	return i;
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4)
+	(void **virt, struct ndis_mp_block *nmb, UINT start, UINT len)
+{
+	ENTER3("%08x %08x", start, len);
+	*virt = (void *)(ULONG_PTR)start;
+	return NDIS_STATUS_SUCCESS;
+}
+
+wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4)
+	(struct ndis_mp_block *nmb, UINT start, UINT len, void* virt)
+{
+	ENTER1("%08x %08x", start, len);
+}
+
+wstdcall void WIN_FUNC(NdisReadPortUchar,3)
+	(struct ndis_mp_block *nmb, ULONG port, char *data)
+{
+	*data = inb(port);
+}
+
+wstdcall void WIN_FUNC(NdisImmediateReadPortUchar,3)
+	(struct ndis_mp_block *nmb, ULONG port, char *data)
+{
+	*data = inb(port);
+}
+
+wstdcall void WIN_FUNC(NdisWritePortUchar,3)
+	(struct ndis_mp_block *nmb, ULONG port, char data)
+{
+	outb(data, port);
+}
+
+wstdcall void WIN_FUNC(NdisImmediateWritePortUchar,3)
+	(struct ndis_mp_block *nmb, ULONG port, char data)
+{
+	outb(data, port);
+}
+
+wstdcall void WIN_FUNC(NdisMQueryAdapterResources,4)
+	(NDIS_STATUS *status, struct ndis_mp_block *nmb,
+	 NDIS_RESOURCE_LIST *resource_list, UINT *size)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	NDIS_RESOURCE_LIST *list;
+	UINT resource_length;
+
+	list = &wnd->wd->resource_list->list->partial_resource_list;
+	resource_length = sizeof(struct cm_partial_resource_list) +
+		sizeof(struct cm_partial_resource_descriptor) *
+		(list->count - 1);
+	TRACE2("%p, %p,%d (%d), %p %d %d", wnd, resource_list, *size,
+	       resource_length, &list->partial_descriptors[list->count-1],
+	       list->partial_descriptors[list->count-1].u.interrupt.level,
+	       list->partial_descriptors[list->count-1].u.interrupt.vector);
+	if (*size < sizeof(*list)) {
+		*size = resource_length;
+		*status = NDIS_STATUS_BUFFER_TOO_SHORT;
+	} else {
+		ULONG count;
+		if (*size >= resource_length) {
+			*size = resource_length;
+			count = list->count;
+		} else {
+			UINT n = sizeof(*list);
+			count = 1;
+			while (count++ < list->count && n < *size)
+				n += sizeof(list->partial_descriptors);
+			*size = n;
+		}
+		memcpy(resource_list, list, *size);
+		resource_list->count = count;
+		*status = NDIS_STATUS_SUCCESS;
+	}
+	EXIT2(return);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMPciAssignResources,3)
+	(struct ndis_mp_block *nmb, ULONG slot_number,
+	 NDIS_RESOURCE_LIST **resources)
+{
+	struct ndis_device *wnd = nmb->wnd;
+
+	ENTER2("%p, %p", wnd, wnd->wd->resource_list);
+	*resources = &wnd->wd->resource_list->list->partial_resource_list;
+	EXIT2(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMMapIoSpace,4)
+	(void __iomem **virt, struct ndis_mp_block *nmb,
+	 NDIS_PHY_ADDRESS phy_addr, UINT len)
+{
+	struct ndis_device *wnd = nmb->wnd;
+
+	ENTER2("%Lx, %d", phy_addr, len);
+	*virt = MmMapIoSpace(phy_addr, len, MmCached);
+	if (*virt == NULL) {
+		ERROR("ioremap failed");
+		EXIT2(return NDIS_STATUS_FAILURE);
+	}
+	wnd->mem_start = phy_addr;
+	wnd->mem_end = phy_addr + len;
+	TRACE2("%p", *virt);
+	EXIT2(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisMUnmapIoSpace,3)
+	(struct ndis_mp_block *nmb, void __iomem *virt, UINT len)
+{
+	ENTER2("%p, %d", virt, len);
+	MmUnmapIoSpace(virt, len);
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisAllocateSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	TRACE4("lock %p, %p", lock, &lock->klock);
+	KeInitializeSpinLock(&lock->klock);
+	lock->irql = PASSIVE_LEVEL;
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisFreeSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	TRACE4("lock %p, %p", lock, &lock->klock);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisAcquireSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	ENTER6("lock %p, %p", lock, &lock->klock);
+//	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	lock->irql = nt_spin_lock_irql(&lock->klock, DISPATCH_LEVEL);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisReleaseSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	ENTER6("lock %p, %p", lock, &lock->klock);
+//	assert_irql(_irql_ == DISPATCH_LEVEL);
+	nt_spin_unlock_irql(&lock->klock, lock->irql);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisDprAcquireSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	ENTER6("lock %p", &lock->klock);
+//	assert_irql(_irql_ == DISPATCH_LEVEL);
+	nt_spin_lock(&lock->klock);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisDprReleaseSpinLock,1)
+	(struct ndis_spinlock *lock)
+{
+	ENTER6("lock %p", &lock->klock);
+//	assert_irql(_irql_ == DISPATCH_LEVEL);
+	nt_spin_unlock(&lock->klock);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisInitializeReadWriteLock,1)
+	(struct ndis_rw_lock *rw_lock)
+{
+	ENTER3("%p", rw_lock);
+	memset(rw_lock, 0, sizeof(*rw_lock));
+	KeInitializeSpinLock(&rw_lock->klock);
+	return;
+}
+
+/* read/write locks are implemented in a rather simplisitic way - we
+ * should probably use Linux's rw_lock implementation */
+
+wstdcall void WIN_FUNC(NdisAcquireReadWriteLock,3)
+	(struct ndis_rw_lock *rw_lock, BOOLEAN write,
+	 struct lock_state *lock_state)
+{
+	if (write) {
+		while (1) {
+			if (cmpxchg(&rw_lock->count, 0, -1) == 0)
+				return;
+			while (rw_lock->count)
+				cpu_relax();
+		}
+		return;
+	}
+	while (1) {
+		typeof(rw_lock->count) count;
+		while ((count = rw_lock->count) < 0)
+			cpu_relax();
+		if (cmpxchg(&rw_lock->count, count, count + 1) == count)
+			return;
+	}
+}
+
+wstdcall void WIN_FUNC(NdisReleaseReadWriteLock,2)
+	(struct ndis_rw_lock *rw_lock, struct lock_state *lock_state)
+{
+	if (rw_lock->count > 0)
+		pre_atomic_add(rw_lock->count, -1);
+	else if (rw_lock->count == -1)
+		rw_lock->count = 0;
+	else
+		WARNING("invalid state: %d", rw_lock->count);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateMapRegisters,5)
+	(struct ndis_mp_block *nmb, UINT dmachan,
+	 NDIS_DMA_SIZE dmasize, ULONG basemap, ULONG max_buf_size)
+{
+	struct ndis_device *wnd = nmb->wnd;
+
+	ENTER2("%p, %d %d %d %d", wnd, dmachan, dmasize, basemap, max_buf_size);
+	if (wnd->dma_map_count > 0) {
+		WARNING("%s: map registers already allocated: %u",
+			wnd->net_dev->name, wnd->dma_map_count);
+		EXIT2(return NDIS_STATUS_RESOURCES);
+	}
+	if (dmasize == NDIS_DMA_24BITS) {
+		if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(24)) ||
+		    pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
+						DMA_BIT_MASK(24)))
+			WARNING("setting dma mask failed");
+	} else if (dmasize == NDIS_DMA_32BITS) {
+		/* consistent dma is in low 32-bits by default */
+		if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)))
+			WARNING("setting dma mask failed");
+#ifdef CONFIG_X86_64
+	} else if (dmasize == NDIS_DMA_64BITS) {
+		if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(64)) ||
+		    pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
+						DMA_BIT_MASK(64)))
+			WARNING("setting dma mask failed");
+		else
+			wnd->net_dev->features |= NETIF_F_HIGHDMA;
+#endif
+	}
+	/* since memory for buffer is allocated with kmalloc, buffer
+	 * is physically contiguous, so entire map will fit in one
+	 * register */
+	if (basemap > 64) {
+		WARNING("Windows driver %s requesting too many (%u) "
+			"map registers", wnd->wd->driver->name, basemap);
+		/* As per NDIS, NDIS_STATUS_RESOURCES should be
+		 * returned, but with that Atheros PCI driver fails -
+		 * for now tolerate it */
+//		EXIT2(return NDIS_STATUS_RESOURCES);
+	}
+
+	wnd->dma_map_addr = kmalloc(basemap * sizeof(*(wnd->dma_map_addr)),
+				    GFP_KERNEL);
+	if (!wnd->dma_map_addr)
+		EXIT2(return NDIS_STATUS_RESOURCES);
+	memset(wnd->dma_map_addr, 0, basemap * sizeof(*(wnd->dma_map_addr)));
+	wnd->dma_map_count = basemap;
+	TRACE2("%u", wnd->dma_map_count);
+	EXIT2(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisMFreeMapRegisters,1)
+	(struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	int i;
+
+	ENTER2("wnd: %p", wnd);
+	if (wnd->dma_map_addr) {
+		for (i = 0; i < wnd->dma_map_count; i++) {
+			if (wnd->dma_map_addr[i])
+				WARNING("%s: dma addr %p not freed by "
+					"Windows driver", wnd->net_dev->name,
+					(void *)wnd->dma_map_addr[i]);
+		}
+		kfree(wnd->dma_map_addr);
+		wnd->dma_map_addr = NULL;
+	} else
+		WARNING("map registers already freed?");
+	wnd->dma_map_count = 0;
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisMStartBufferPhysicalMapping,6)
+	(struct ndis_mp_block *nmb, ndis_buffer *buf,
+	 ULONG index, BOOLEAN write_to_dev,
+	 struct ndis_phy_addr_unit *phy_addr_array, UINT *array_size)
+{
+	struct ndis_device *wnd = nmb->wnd;
+
+	ENTER3("%p, %p, %u, %u", wnd, buf, index, wnd->dma_map_count);
+	if (unlikely(wnd->sg_dma_size || !write_to_dev ||
+		     index >= wnd->dma_map_count)) {
+		WARNING("invalid request: %d, %d, %d, %d", wnd->sg_dma_size,
+			write_to_dev, index, wnd->dma_map_count);
+		phy_addr_array[0].phy_addr = 0;
+		phy_addr_array[0].length = 0;
+		*array_size = 0;
+		return;
+	}
+	if (wnd->dma_map_addr[index]) {
+		TRACE2("buffer %p at %d is already mapped: %lx", buf, index,
+		       (unsigned long)wnd->dma_map_addr[index]);
+//		*array_size = 1;
+		return;
+	}
+	TRACE3("%p, %p, %u", buf, MmGetSystemAddressForMdl(buf),
+	       MmGetMdlByteCount(buf));
+	DBG_BLOCK(4) {
+		dump_bytes(__func__, MmGetSystemAddressForMdl(buf),
+			   MmGetMdlByteCount(buf));
+	}
+	wnd->dma_map_addr[index] =
+		PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev,
+				   MmGetSystemAddressForMdl(buf),
+				   MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
+	phy_addr_array[0].phy_addr = wnd->dma_map_addr[index];
+	phy_addr_array[0].length = MmGetMdlByteCount(buf);
+	TRACE4("%Lx, %d, %d", phy_addr_array[0].phy_addr,
+	       phy_addr_array[0].length, index);
+	*array_size = 1;
+}
+
+wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3)
+	(struct ndis_mp_block *nmb, ndis_buffer *buf, ULONG index)
+{
+	struct ndis_device *wnd = nmb->wnd;
+
+	ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count);
+
+	if (unlikely(wnd->sg_dma_size))
+		WARNING("buffer %p may have been unmapped already", buf);
+	if (index >= wnd->dma_map_count) {
+		ERROR("invalid map register (%u >= %u)",
+		      index, wnd->dma_map_count);
+		return;
+	}
+	TRACE4("%lx", (unsigned long)wnd->dma_map_addr[index]);
+	if (wnd->dma_map_addr[index]) {
+		PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index],
+				     MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
+		wnd->dma_map_addr[index] = 0;
+	} else
+		WARNING("map registers at %u not used", index);
+}
+
+wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5)
+	(struct ndis_mp_block *nmb, ULONG size,
+	 BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys)
+{
+	dma_addr_t dma_addr;
+	struct wrap_device *wd = nmb->wnd->wd;
+
+	ENTER3("size: %u, cached: %d", size, cached);
+	*virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr);
+	if (*virt)
+		*phys = dma_addr;
+	else
+		WARNING("couldn't allocate %d bytes of %scached DMA memory",
+			size, cached ? "" : "un-");
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5)
+	(struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached,
+	 void *virt, NDIS_PHY_ADDRESS addr)
+{
+	struct wrap_device *wd = nmb->wnd->wd;
+	ENTER3("%p, %Lx, %u", virt, addr, size);
+	PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr);
+	EXIT3(return);
+}
+
+wstdcall void alloc_shared_memory_async(void *arg1, void *arg2)
+{
+	struct ndis_device *wnd;
+	struct alloc_shared_mem *alloc_shared_mem;
+	struct miniport *mp;
+	void *virt;
+	NDIS_PHY_ADDRESS phys;
+	KIRQL irql;
+
+	wnd = arg1;
+	alloc_shared_mem = arg2;
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size,
+				  alloc_shared_mem->cached, &virt, &phys);
+	irql = serialize_lock_irql(wnd);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	LIN2WIN5(mp->alloc_complete, wnd->nmb, virt,
+		 &phys, alloc_shared_mem->size, alloc_shared_mem->ctx);
+	serialize_unlock_irql(wnd, irql);
+	kfree(alloc_shared_mem);
+}
+WIN_FUNC_DECL(alloc_shared_memory_async,2)
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4)
+	(struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, void *ctx)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct alloc_shared_mem *alloc_shared_mem;
+
+	ENTER3("wnd: %p", wnd);
+	alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), irql_gfp());
+	if (!alloc_shared_mem) {
+		WARNING("couldn't allocate memory");
+		return NDIS_STATUS_FAILURE;
+	}
+
+	alloc_shared_mem->size = size;
+	alloc_shared_mem->cached = cached;
+	alloc_shared_mem->ctx = ctx;
+	if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2),
+				    wnd, alloc_shared_mem))
+		EXIT3(return NDIS_STATUS_FAILURE);
+	EXIT3(return NDIS_STATUS_PENDING);
+}
+
+/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of
+ * allocating and freeing with kernel functions, we chain them into
+ * ndis_buffer_pool. When an MDL is freed, it is added to the list of
+ * free MDLs. When allocated, we first check if there is one in free
+ * list and if so just return it; otherwise, we allocate a new one and
+ * return that. This reduces memory fragmentation. Windows DDK says
+ * that the driver itself shouldn't check what is returned in
+ * pool_handle, presumably because buffer pools are not used in
+ * XP. However, as long as driver follows rest of the semantics - that
+ * it should indicate maximum number of MDLs used with num_descr and
+ * pass the same pool_handle in other buffer functions, this should
+ * work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle,
+ * so we use 'process' field of MDL to store pool_handle. */
+
+wstdcall void WIN_FUNC(NdisAllocateBufferPool,3)
+	(NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle,
+	 UINT num_descr)
+{
+	struct ndis_buffer_pool *pool;
+
+	ENTER1("buffers: %d", num_descr);
+	pool = kmalloc(sizeof(*pool), irql_gfp());
+	if (!pool) {
+		*status = NDIS_STATUS_RESOURCES;
+		EXIT3(return);
+	}
+	spin_lock_init(&pool->lock);
+	pool->max_descr = num_descr;
+	pool->num_allocated_descr = 0;
+	pool->free_descr = NULL;
+	*pool_handle = pool;
+	*status = NDIS_STATUS_SUCCESS;
+	TRACE1("pool: %p, num_descr: %d", pool, num_descr);
+	EXIT1(return);
+}
+
+wstdcall void WIN_FUNC(NdisAllocateBuffer,5)
+	(NDIS_STATUS *status, ndis_buffer **buffer,
+	 struct ndis_buffer_pool *pool, void *virt, UINT length)
+{
+	ndis_buffer *descr;
+
+	ENTER4("pool: %p (%d)", pool, pool->num_allocated_descr);
+	/* NDIS drivers should call this at DISPATCH_LEVEL, but
+	 * alloc_tx_packet calls at SOFT_IRQL */
+	assert_irql(_irql_ <= SOFT_LEVEL);
+	if (!pool) {
+		*status = NDIS_STATUS_FAILURE;
+		*buffer = NULL;
+		EXIT4(return);
+	}
+	spin_lock_bh(&pool->lock);
+	if ((descr = pool->free_descr))
+		pool->free_descr = descr->next;
+	spin_unlock_bh(&pool->lock);
+	if (descr) {
+		typeof(descr->flags) flags;
+		flags = descr->flags;
+		memset(descr, 0, sizeof(*descr));
+		MmInitializeMdl(descr, virt, length);
+		if (flags & MDL_CACHE_ALLOCATED)
+			descr->flags |= MDL_CACHE_ALLOCATED;
+	} else {
+		if (pool->num_allocated_descr > pool->max_descr) {
+			TRACE2("pool %p is full: %d(%d)", pool,
+			       pool->num_allocated_descr, pool->max_descr);
+#ifndef ALLOW_POOL_OVERFLOW
+			*status = NDIS_STATUS_FAILURE;
+			*buffer = NULL;
+			return;
+#endif
+		}
+		descr = allocate_init_mdl(virt, length);
+		if (!descr) {
+			WARNING("couldn't allocate buffer");
+			*status = NDIS_STATUS_FAILURE;
+			*buffer = NULL;
+			EXIT4(return);
+		}
+		TRACE4("buffer %p for %p, %d", descr, virt, length);
+		atomic_inc_var(pool->num_allocated_descr);
+	}
+	/* TODO: make sure this mdl can map given buffer */
+	MmBuildMdlForNonPagedPool(descr);
+//	descr->flags |= MDL_ALLOCATED_FIXED_SIZE |
+//		MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED;
+	descr->pool = pool;
+	*buffer = descr;
+	*status = NDIS_STATUS_SUCCESS;
+	TRACE4("buffer: %p", descr);
+	EXIT4(return);
+}
+
+wstdcall void WIN_FUNC(NdisFreeBuffer,1)
+	(ndis_buffer *buffer)
+{
+	struct ndis_buffer_pool *pool;
+
+	ENTER4("%p", buffer);
+	if (!buffer || !buffer->pool) {
+		ERROR("invalid buffer");
+		EXIT4(return);
+	}
+	pool = buffer->pool;
+	if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) {
+		/* NB NB NB: set mdl's 'pool' field to NULL before
+		 * calling free_mdl; otherwise free_mdl calls
+		 * NdisFreeBuffer back */
+		atomic_dec_var(pool->num_allocated_descr);
+		buffer->pool = NULL;
+		free_mdl(buffer);
+	} else {
+		spin_lock_bh(&pool->lock);
+		buffer->next = pool->free_descr;
+		pool->free_descr = buffer;
+		spin_unlock_bh(&pool->lock);
+	}
+	EXIT4(return);
+}
+
+wstdcall void WIN_FUNC(NdisFreeBufferPool,1)
+	(struct ndis_buffer_pool *pool)
+{
+	ndis_buffer *cur, *next;
+
+	TRACE3("pool: %p", pool);
+	if (!pool) {
+		WARNING("invalid pool");
+		EXIT3(return);
+	}
+	spin_lock_bh(&pool->lock);
+	cur = pool->free_descr;
+	while (cur) {
+		next = cur->next;
+		cur->pool = NULL;
+		free_mdl(cur);
+		cur = next;
+	}
+	spin_unlock_bh(&pool->lock);
+	kfree(pool);
+	pool = NULL;
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisAdjustBufferLength,2)
+	(ndis_buffer *buffer, UINT length)
+{
+	ENTER4("%p, %d", buffer, length);
+	buffer->bytecount = length;
+}
+
+wstdcall void WIN_FUNC(NdisQueryBuffer,3)
+	(ndis_buffer *buffer, void **virt, UINT *length)
+{
+	ENTER4("buffer: %p", buffer);
+	if (virt)
+		*virt = MmGetSystemAddressForMdl(buffer);
+	*length = MmGetMdlByteCount(buffer);
+	TRACE4("%p, %u", virt? *virt : NULL, *length);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisQueryBufferSafe,4)
+	(ndis_buffer *buffer, void **virt, UINT *length,
+	 enum mm_page_priority priority)
+{
+	ENTER4("%p, %p, %p, %d", buffer, virt, length, priority);
+	if (virt)
+		*virt = MmGetSystemAddressForMdlSafe(buffer, priority);
+	*length = MmGetMdlByteCount(buffer);
+	TRACE4("%p, %u", virt? *virt : NULL, *length);
+}
+
+wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1)
+	(ndis_buffer *buffer)
+{
+	ENTER3("%p", buffer);
+	return MmGetSystemAddressForMdl(buffer);
+}
+
+wstdcall ULONG WIN_FUNC(NdisBufferLength,1)
+	(ndis_buffer *buffer)
+{
+	ENTER3("%p", buffer);
+	return MmGetMdlByteCount(buffer);
+}
+
+wstdcall void WIN_FUNC(NdisQueryBufferOffset,3)
+	(ndis_buffer *buffer, UINT *offset, UINT *length)
+{
+	ENTER3("%p", buffer);
+	*offset = MmGetMdlByteOffset(buffer);
+	*length = MmGetMdlByteCount(buffer);
+	TRACE3("%d, %d", *offset, *length);
+}
+
+wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2)
+	(struct ndis_packet *packet, ndis_buffer **buffer)
+{
+	ndis_buffer *b, *btail;
+
+	ENTER3("%p", packet);
+	b = packet->private.buffer_head;
+	if (!b) {
+		/* no buffer in packet */
+		*buffer = NULL;
+		EXIT3(return);
+	}
+	btail = packet->private.buffer_tail;
+	*buffer = btail;
+	if (b == btail) {
+		/* one buffer in packet */
+		packet->private.buffer_head = NULL;
+		packet->private.buffer_tail = NULL;
+	} else {
+		while (b->next != btail)
+			b = b->next;
+		packet->private.buffer_tail = b;
+		b->next = NULL;
+	}
+	packet->private.valid_counts = FALSE;
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2)
+	(struct ndis_packet *packet, ndis_buffer **buffer)
+{
+	ENTER3("%p", packet);
+	if (packet->private.buffer_head == NULL) {
+		/* no buffer in packet */
+		*buffer = NULL;
+		EXIT3(return);
+	}
+
+	*buffer = packet->private.buffer_head;
+	if (packet->private.buffer_head == packet->private.buffer_tail) {
+		/* one buffer in packet */
+		packet->private.buffer_head = NULL;
+		packet->private.buffer_tail = NULL;
+	} else
+		packet->private.buffer_head = (*buffer)->next;
+
+	packet->private.valid_counts = FALSE;
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6)
+	(struct ndis_packet *packet, ndis_buffer **first_buffer,
+	 void **first_buffer_va, UINT *first_buffer_length,
+	 UINT *total_buffer_length, enum mm_page_priority priority)
+{
+	ndis_buffer *b = packet->private.buffer_head;
+
+	ENTER3("%p(%p)", packet, b);
+	*first_buffer = b;
+	if (b) {
+		*first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority);
+		*first_buffer_length = *total_buffer_length =
+			MmGetMdlByteCount(b);
+		for (b = b->next; b; b = b->next)
+			*total_buffer_length += MmGetMdlByteCount(b);
+	} else {
+		*first_buffer_va = NULL;
+		*first_buffer_length = 0;
+		*total_buffer_length = 0;
+	}
+	TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length,
+	       *total_buffer_length);
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6)
+	(struct ndis_packet *packet, ndis_buffer **first_buffer,
+	 void **first_buffer_va, UINT *first_buffer_length,
+	 UINT *total_buffer_length, enum mm_page_priority priority)
+{
+	NdisGetFirstBufferFromPacketSafe(packet, first_buffer,
+					 first_buffer_va, first_buffer_length,
+					 total_buffer_length,
+					 NormalPagePriority);
+}
+
+wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5)
+	(NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
+	 UINT num_descr, UINT overflowsize, UINT proto_rsvd_length)
+{
+	struct ndis_packet_pool *pool;
+
+	ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length);
+	pool = kzalloc(sizeof(*pool), irql_gfp());
+	if (!pool) {
+		*status = NDIS_STATUS_RESOURCES;
+		EXIT3(return);
+	}
+	spin_lock_init(&pool->lock);
+	pool->max_descr = num_descr;
+	pool->num_allocated_descr = 0;
+	pool->num_used_descr = 0;
+	pool->free_descr = NULL;
+	pool->proto_rsvd_length = proto_rsvd_length;
+	*pool_handle = pool;
+	*status = NDIS_STATUS_SUCCESS;
+	TRACE3("pool: %p", pool);
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisAllocatePacketPool,4)
+	(NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
+	 UINT num_descr, UINT proto_rsvd_length)
+{
+	NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0,
+				 proto_rsvd_length);
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisFreePacketPool,1)
+	(struct ndis_packet_pool *pool)
+{
+	struct ndis_packet *packet, *next;
+
+	ENTER3("pool: %p", pool);
+	if (!pool) {
+		WARNING("invalid pool");
+		EXIT3(return);
+	}
+	spin_lock_bh(&pool->lock);
+	packet = pool->free_descr;
+	while (packet) {
+		next = (struct ndis_packet *)packet->reserved[0];
+		kfree(packet);
+		packet = next;
+	}
+	pool->num_allocated_descr = 0;
+	pool->num_used_descr = 0;
+	pool->free_descr = NULL;
+	spin_unlock_bh(&pool->lock);
+	kfree(pool);
+	EXIT3(return);
+}
+
+wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1)
+	(struct ndis_packet_pool *pool)
+{
+	EXIT4(return pool->num_used_descr);
+}
+
+wstdcall void WIN_FUNC(NdisAllocatePacket,3)
+	(NDIS_STATUS *status, struct ndis_packet **ndis_packet,
+	 struct ndis_packet_pool *pool)
+{
+	struct ndis_packet *packet;
+	int packet_length;
+
+	ENTER4("pool: %p", pool);
+	if (!pool) {
+		*status = NDIS_STATUS_RESOURCES;
+		*ndis_packet = NULL;
+		EXIT4(return);
+	}
+	assert_irql(_irql_ <= SOFT_LEVEL);
+	if (pool->num_used_descr > pool->max_descr) {
+		TRACE3("pool %p is full: %d(%d)", pool,
+		       pool->num_used_descr, pool->max_descr);
+#ifndef ALLOW_POOL_OVERFLOW
+		*status = NDIS_STATUS_RESOURCES;
+		*ndis_packet = NULL;
+		return;
+#endif
+	}
+	/* packet has space for 1 byte in protocol_reserved field */
+	packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length +
+		sizeof(struct ndis_packet_oob_data);
+	spin_lock_bh(&pool->lock);
+	if ((packet = pool->free_descr))
+		pool->free_descr = (void *)packet->reserved[0];
+	spin_unlock_bh(&pool->lock);
+	if (!packet) {
+		packet = kmalloc(packet_length, irql_gfp());
+		if (!packet) {
+			WARNING("couldn't allocate packet");
+			*status = NDIS_STATUS_RESOURCES;
+			*ndis_packet = NULL;
+			return;
+		}
+		atomic_inc_var(pool->num_allocated_descr);
+	}
+	TRACE4("%p, %p", pool, packet);
+	atomic_inc_var(pool->num_used_descr);
+	memset(packet, 0, packet_length);
+	packet->private.oob_offset =
+		packet_length - sizeof(struct ndis_packet_oob_data);
+	packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS;
+	packet->private.pool = pool;
+	*ndis_packet = packet;
+	*status = NDIS_STATUS_SUCCESS;
+	EXIT4(return);
+}
+
+wstdcall void WIN_FUNC(NdisDprAllocatePacket,3)
+	(NDIS_STATUS *status, struct ndis_packet **packet,
+	 struct ndis_packet_pool *pool)
+{
+	NdisAllocatePacket(status, packet, pool);
+}
+
+wstdcall void WIN_FUNC(NdisFreePacket,1)
+	(struct ndis_packet *packet)
+{
+	struct ndis_packet_pool *pool;
+
+	ENTER4("%p, %p", packet, packet->private.pool);
+	pool = packet->private.pool;
+	if (!pool) {
+		ERROR("invalid pool %p", packet);
+		EXIT4(return);
+	}
+	assert((int)pool->num_used_descr > 0);
+	atomic_dec_var(pool->num_used_descr);
+	if (packet->reserved[1]) {
+		TRACE3("%p, %p", packet, (void *)packet->reserved[1]);
+		kfree((void *)packet->reserved[1]);
+		packet->reserved[1] = 0;
+	}
+	if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) {
+		TRACE3("%p", pool);
+		atomic_dec_var(pool->num_allocated_descr);
+		kfree(packet);
+	} else {
+		TRACE4("%p, %p, %p", pool, packet, pool->free_descr);
+		spin_lock_bh(&pool->lock);
+		packet->reserved[0] =
+			(typeof(packet->reserved[0]))pool->free_descr;
+		pool->free_descr = packet;
+		spin_unlock_bh(&pool->lock);
+	}
+	EXIT4(return);
+}
+
+wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2)
+	(struct ndis_packet *packet, BOOLEAN *stacks_remain)
+{
+	struct ndis_packet_stack *stack;
+
+	if (!packet->reserved[1]) {
+		stack = kzalloc(2 * sizeof(*stack), irql_gfp());
+		TRACE3("%p, %p", packet, stack);
+		packet->reserved[1] = (typeof(packet->reserved[1]))stack;
+	} else {
+		stack = (void *)packet->reserved[1];;
+		if (xchg(&stack->ndis_reserved[0], 1)) {
+			stack++;
+			if (xchg(&stack->ndis_reserved[0], 1))
+				stack = NULL;
+		}
+		TRACE3("%p", stack);
+	}
+	if (stack)
+		*stacks_remain = TRUE;
+	else
+		*stacks_remain = FALSE;
+
+	EXIT3(return stack);
+}
+
+wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7)
+	(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
+	 struct ndis_packet *src, UINT src_offset, UINT *num_copied,
+	 enum mm_page_priority priority)
+{
+	UINT dst_n, src_n, n, left;
+	ndis_buffer *dst_buf;
+	ndis_buffer *src_buf;
+
+	ENTER4("");
+	if (!dst || !src) {
+		*num_copied = 0;
+		EXIT4(return);
+	}
+
+	dst_buf = dst->private.buffer_head;
+	src_buf = src->private.buffer_head;
+
+	if (!dst_buf || !src_buf) {
+		*num_copied = 0;
+		EXIT4(return);
+	}
+	dst_n = MmGetMdlByteCount(dst_buf) - dst_offset;
+	src_n = MmGetMdlByteCount(src_buf) - src_offset;
+
+	n = min(src_n, dst_n);
+	n = min(n, num_to_copy);
+	memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
+	       MmGetSystemAddressForMdl(src_buf) + src_offset, n);
+
+	left = num_to_copy - n;
+	while (left > 0) {
+		src_offset += n;
+		dst_offset += n;
+		dst_n -= n;
+		src_n -= n;
+		if (dst_n == 0) {
+			dst_buf = dst_buf->next;
+			if (!dst_buf)
+				break;
+			dst_n = MmGetMdlByteCount(dst_buf);
+			dst_offset = 0;
+		}
+		if (src_n == 0) {
+			src_buf = src_buf->next;
+			if (!src_buf)
+				break;
+			src_n = MmGetMdlByteCount(src_buf);
+			src_offset = 0;
+		}
+
+		n = min(src_n, dst_n);
+		n = min(n, left);
+		memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
+		       MmGetSystemAddressForMdl(src_buf) + src_offset, n);
+		left -= n;
+	}
+	*num_copied = num_to_copy - left;
+	EXIT4(return);
+}
+
+wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6)
+	(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
+	 struct ndis_packet *src, UINT src_offset, UINT *num_copied)
+{
+	NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy,
+				       src, src_offset, num_copied,
+				       NormalPagePriority);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2)
+	(struct ndis_packet *dst, struct ndis_packet *src)
+{
+	struct ndis_packet_oob_data *dst_oob, *src_oob;
+	dst_oob = NDIS_PACKET_OOB_DATA(dst);
+	src_oob = NDIS_PACKET_OOB_DATA(src);
+	memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext));
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisSend,3)
+	(NDIS_STATUS *status, struct ndis_mp_block *nmb,
+	 struct ndis_packet *packet)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct miniport *mp;
+	KIRQL irql;
+
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	if (mp->send_packets) {
+		irql = serialize_lock_irql(wnd);
+		assert_irql(_irql_ == DISPATCH_LEVEL);
+		LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1);
+		serialize_unlock_irql(wnd, irql);
+		if (deserialized_driver(wnd))
+			*status = NDIS_STATUS_PENDING;
+		else {
+			struct ndis_packet_oob_data *oob_data;
+			oob_data = NDIS_PACKET_OOB_DATA(packet);
+			*status = oob_data->status;
+			switch (*status) {
+			case NDIS_STATUS_SUCCESS:
+				free_tx_packet(wnd, packet, *status);
+				break;
+			case NDIS_STATUS_PENDING:
+				break;
+			case NDIS_STATUS_RESOURCES:
+				wnd->tx_ok = 0;
+				break;
+			case NDIS_STATUS_FAILURE:
+			default:
+				free_tx_packet(wnd, packet, *status);
+				break;
+			}
+		}
+	} else {
+		irql = serialize_lock_irql(wnd);
+		assert_irql(_irql_ == DISPATCH_LEVEL);
+		*status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0);
+		serialize_unlock_irql(wnd, irql);
+		switch (*status) {
+		case NDIS_STATUS_SUCCESS:
+			free_tx_packet(wnd, packet, *status);
+			break;
+		case NDIS_STATUS_PENDING:
+			break;
+		case NDIS_STATUS_RESOURCES:
+			wnd->tx_ok = 0;
+			break;
+		case NDIS_STATUS_FAILURE:
+		default:
+			free_tx_packet(wnd, packet, *status);
+			break;
+		}
+	}
+	EXIT3(return);
+}
+
+/* called for serialized drivers only */
+wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2)
+{
+	struct ndis_mp_timer *timer;
+	struct ndis_mp_block *nmb;
+
+	timer = ctx;
+	TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	nmb = timer->nmb;
+	serialize_lock(nmb->wnd);
+	LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL);
+	serialize_unlock(nmb->wnd);
+	TIMEREXIT(return);
+}
+WIN_FUNC_DECL(mp_timer_dpc,4)
+
+wstdcall void WIN_FUNC(NdisMInitializeTimer,4)
+	(struct ndis_mp_timer *timer, struct ndis_mp_block *nmb,
+	 DPC func, void *ctx)
+{
+	TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb);
+	assert_irql(_irql_ == PASSIVE_LEVEL);
+	timer->func = func;
+	timer->ctx = ctx;
+	timer->nmb = nmb;
+	if (deserialized_driver(nmb->wnd))
+		KeInitializeDpc(&timer->kdpc, func, ctx);
+	else
+		KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4),
+				timer);
+	wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb);
+	TIMEREXIT(return);
+}
+
+wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2)
+	(struct ndis_mp_timer *timer, UINT period_ms)
+{
+	unsigned long expires = MSEC_TO_HZ(period_ms);
+
+	TIMERENTER("%p, %u, %ld", timer, period_ms, expires);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc);
+	TIMEREXIT(return);
+}
+
+wstdcall void WIN_FUNC(NdisMCancelTimer,2)
+	(struct ndis_mp_timer *timer, BOOLEAN *canceled)
+{
+	TIMERENTER("%p", timer);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	*canceled = KeCancelTimer(&timer->nt_timer);
+	TIMERTRACE("%d", *canceled);
+	return;
+}
+
+wstdcall void WIN_FUNC(NdisInitializeTimer,3)
+	(struct ndis_timer *timer, void *func, void *ctx)
+{
+	TIMERENTER("%p, %p, %p", timer, func, ctx);
+	assert_irql(_irql_ == PASSIVE_LEVEL);
+	KeInitializeDpc(&timer->kdpc, func, ctx);
+	wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL);
+	TIMEREXIT(return);
+}
+
+/* NdisMSetTimer is a macro that calls NdisSetTimer with
+ * ndis_mp_timer typecast to ndis_timer */
+
+wstdcall void WIN_FUNC(NdisSetTimer,2)
+	(struct ndis_timer *timer, UINT duetime_ms)
+{
+	unsigned long expires = MSEC_TO_HZ(duetime_ms);
+
+	TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer,
+		   duetime_ms, expires);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc);
+	TIMEREXIT(return);
+}
+
+wstdcall void WIN_FUNC(NdisCancelTimer,2)
+	(struct ndis_timer *timer, BOOLEAN *canceled)
+{
+	TIMERENTER("%p", timer);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	*canceled = KeCancelTimer(&timer->nt_timer);
+	TIMEREXIT(return);
+}
+
+wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3)
+	(struct ndis_mp_block *nmb, void *ctx, void *func)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	ENTER1("%p", func);
+	wnd->wd->driver->ndis_driver->mp.shutdown = func;
+	wnd->shutdown_ctx = ctx;
+}
+
+wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1)
+	(struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
+	wnd->shutdown_ctx = NULL;
+}
+
+/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt
+ * to be called in irq handler, but mrv800c (deserialized) driver
+ * wants. NDIS is confusing about when to call MiniportEnableInterrupt
+ * For now, handle these cases with two separate irq handlers based on
+ * observation of these two drivers. However, it is likely not
+ * correct. */
+wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx,
+				       void *arg1, void *arg2)
+{
+	struct ndis_device *wnd = ctx;
+	ndis_interrupt_handler irq_handler = arg1;
+	struct miniport *mp = arg2;
+
+	TRACE6("%p", irq_handler);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	LIN2WIN1(irq_handler, wnd->nmb->mp_ctx);
+	if (mp->enable_interrupt)
+		LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx);
+	EXIT6(return);
+}
+WIN_FUNC_DECL(deserialized_irq_handler,4)
+
+wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx,
+				     void *arg1, void *arg2)
+{
+	struct ndis_device *wnd = ctx;
+	ndis_interrupt_handler irq_handler = arg1;
+
+	TRACE6("%p, %p, %p", wnd, irq_handler, arg2);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	serialize_lock(wnd);
+	LIN2WIN1(irq_handler, arg2);
+	serialize_unlock(wnd);
+	EXIT6(return);
+}
+WIN_FUNC_DECL(serialized_irq_handler,4)
+
+wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx)
+{
+	struct ndis_mp_interrupt *mp_interrupt = ctx;
+	struct ndis_device *wnd = mp_interrupt->nmb->wnd;
+	BOOLEAN recognized = TRUE, queue_handler = TRUE;
+
+	TRACE6("%p", wnd);
+	/* kernel may call ISR when registering interrupt, in
+	 * the same context if DEBUG_SHIRQ is enabled */
+	assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL);
+	if (mp_interrupt->shared)
+		LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler,
+			 wnd->nmb->mp_ctx);
+	else {
+		struct miniport *mp;
+		mp = &wnd->wd->driver->ndis_driver->mp;
+		LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx);
+		/* it is not shared interrupt, so handler must be called */
+		recognized = queue_handler = TRUE;
+	}
+	if (recognized) {
+		if (queue_handler) {
+			TRACE5("%p", &wnd->irq_kdpc);
+			queue_kdpc(&wnd->irq_kdpc);
+		}
+		EXIT6(return TRUE);
+	}
+	EXIT6(return FALSE);
+}
+WIN_FUNC_DECL(ndis_isr,2)
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7)
+	(struct ndis_mp_interrupt *mp_interrupt,
+	 struct ndis_mp_block *nmb, UINT vector, UINT level,
+	 BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct miniport *mp;
+
+	ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d",
+	       mp_interrupt, vector, level, req_isr, shared, mode);
+
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	nt_spin_lock_init(&mp_interrupt->lock);
+	mp_interrupt->irq = vector;
+	mp_interrupt->isr = mp->isr;
+	mp_interrupt->mp_dpc = mp->handle_interrupt;
+	mp_interrupt->nmb = nmb;
+	mp_interrupt->req_isr = req_isr;
+	if (shared && !req_isr)
+		WARNING("shared but dynamic interrupt!");
+	mp_interrupt->shared = shared;
+	wnd->mp_interrupt = mp_interrupt;
+	if (mp->enable_interrupt)
+		mp_interrupt->enable = TRUE;
+	else
+		mp_interrupt->enable = FALSE;
+
+	if (deserialized_driver(wnd)) {
+		KeInitializeDpc(&wnd->irq_kdpc,
+				WIN_FUNC_PTR(deserialized_irq_handler,4),
+				nmb->wnd);
+		wnd->irq_kdpc.arg1 = mp->handle_interrupt;
+		wnd->irq_kdpc.arg2 = mp;
+		TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
+		       nmb->wnd, nmb->mp_ctx);
+	} else {
+		KeInitializeDpc(&wnd->irq_kdpc,
+				WIN_FUNC_PTR(serialized_irq_handler,4),
+				nmb->wnd);
+		wnd->irq_kdpc.arg1 = mp->handle_interrupt;
+		wnd->irq_kdpc.arg2 = nmb->mp_ctx;
+		TRACE2("%p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
+		       nmb->wnd);
+	}
+
+	if (IoConnectInterrupt(&mp_interrupt->kinterrupt,
+			       WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL,
+			       vector, DIRQL, DIRQL, mode, shared, 0, FALSE) !=
+	    STATUS_SUCCESS) {
+		printk(KERN_WARNING "%s: request for IRQ %d failed\n",
+		       DRIVER_NAME, vector);
+		return NDIS_STATUS_RESOURCES;
+	}
+	printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector);
+	EXIT1(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1)
+	(struct ndis_mp_interrupt *mp_interrupt)
+{
+	struct ndis_mp_block *nmb;
+
+	ENTER1("%p", mp_interrupt);
+	nmb = xchg(&mp_interrupt->nmb, NULL);
+	TRACE1("%p", nmb);
+	if (!nmb) {
+		WARNING("interrupt already freed?");
+		return;
+	}
+	nmb->wnd->mp_interrupt = NULL;
+	if (dequeue_kdpc(&nmb->wnd->irq_kdpc))
+		TRACE2("interrupt kdpc was pending");
+	flush_workqueue(wrapndis_wq);
+	IoDisconnectInterrupt(mp_interrupt->kinterrupt);
+	EXIT1(return);
+}
+
+wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3)
+	(struct ndis_mp_interrupt *mp_interrupt,
+	 PKSYNCHRONIZE_ROUTINE sync_func, void *ctx)
+{
+	return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx);
+}
+
+/* called via function pointer; but 64-bit RNDIS driver calls directly */
+wstdcall void WIN_FUNC(NdisMIndicateStatus,4)
+	(struct ndis_mp_block *nmb, NDIS_STATUS status, void *buf, UINT len)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct ndis_status_indication *si;
+
+	ENTER2("status=0x%x len=%d", status, len);
+	switch (status) {
+	case NDIS_STATUS_MEDIA_CONNECT:
+		set_media_state(wnd, NdisMediaStateConnected);
+		break;
+	case NDIS_STATUS_MEDIA_DISCONNECT:
+		set_media_state(wnd, NdisMediaStateDisconnected);
+		break;
+	case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION:
+		if (!buf)
+			break;
+		si = buf;
+		TRACE2("status_type=%d", si->status_type);
+		switch (si->status_type) {
+		case Ndis802_11StatusType_MediaStreamMode:
+			break;
+#ifdef CONFIG_WIRELESS_EXT
+		case Ndis802_11StatusType_Authentication:
+			buf = (char *)buf + sizeof(*si);
+			len -= sizeof(*si);
+			while (len > 0) {
+				int pairwise_error = 0, group_error = 0;
+				struct ndis_auth_req *auth_req =
+					(struct ndis_auth_req *)buf;
+				TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid));
+				if (auth_req->flags & 0x01)
+					TRACE2("reauth request");
+				if (auth_req->flags & 0x02)
+					TRACE2("key update request");
+				if (auth_req->flags & 0x06) {
+					pairwise_error = 1;
+					TRACE2("pairwise_error");
+				}
+				if (auth_req->flags & 0x0E) {
+					group_error = 1;
+					TRACE2("group_error");
+				}
+				if (pairwise_error || group_error) {
+					union iwreq_data wrqu;
+					struct iw_michaelmicfailure micfailure;
+
+					memset(&micfailure, 0, sizeof(micfailure));
+					if (pairwise_error)
+						micfailure.flags |=
+							IW_MICFAILURE_PAIRWISE;
+					if (group_error)
+						micfailure.flags |=
+							IW_MICFAILURE_GROUP;
+					memcpy(micfailure.src_addr.sa_data,
+					       auth_req->bssid, ETH_ALEN);
+					memset(&wrqu, 0, sizeof(wrqu));
+					wrqu.data.length = sizeof(micfailure);
+					wireless_send_event(wnd->net_dev,
+							    IWEVMICHAELMICFAILURE,
+							    &wrqu, (u8 *)&micfailure);
+				}
+				len -= auth_req->length;
+				buf = (char *)buf + auth_req->length;
+			}
+			break;
+		case Ndis802_11StatusType_PMKID_CandidateList:
+		{
+			u8 *end;
+			unsigned long i;
+			struct ndis_pmkid_candidate_list *cand;
+
+			cand = buf + sizeof(struct ndis_status_indication);
+			if (len < sizeof(struct ndis_status_indication) +
+			    sizeof(struct ndis_pmkid_candidate_list) ||
+				cand->version != 1) {
+				WARNING("unrecognized PMKID ignored");
+				EXIT1(return);
+			}
+
+			end = (u8 *)buf + len;
+			TRACE2("PMKID ver %d num_cand %d",
+			       cand->version, cand->num_candidates);
+			for (i = 0; i < cand->num_candidates; i++) {
+				struct iw_pmkid_cand pcand;
+				union iwreq_data wrqu;
+				struct ndis_pmkid_candidate *c =
+					&cand->candidates[i];
+				if ((u8 *)(c + 1) > end) {
+					TRACE2("truncated PMKID");
+					break;
+				}
+				TRACE2("%ld: " MACSTRSEP " 0x%x",
+				       i, MAC2STR(c->bssid), c->flags);
+				memset(&pcand, 0, sizeof(pcand));
+				if (c->flags & 0x01)
+					pcand.flags |= IW_PMKID_CAND_PREAUTH;
+				pcand.index = i;
+				memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN);
+
+				memset(&wrqu, 0, sizeof(wrqu));
+				wrqu.data.length = sizeof(pcand);
+				wireless_send_event(wnd->net_dev, IWEVPMKIDCAND,
+						    &wrqu, (u8 *)&pcand);
+			}
+			break;
+		}
+		case Ndis802_11StatusType_RadioState:
+		{
+			struct ndis_radio_status_indication *radio_status = buf;
+			if (radio_status->radio_state ==
+			    Ndis802_11RadioStatusOn)
+				INFO("radio is turned on");
+			else if (radio_status->radio_state ==
+				 Ndis802_11RadioStatusHardwareOff)
+				INFO("radio is turned off by hardware");
+			else if (radio_status->radio_state ==
+				 Ndis802_11RadioStatusSoftwareOff)
+				INFO("radio is turned off by software");
+			break;
+		}
+#endif
+		default:
+			/* is this RSSI indication? */
+			TRACE2("unknown indication: %x", si->status_type);
+			break;
+		}
+		break;
+	default:
+		TRACE2("unknown status: %08X", status);
+		break;
+	}
+
+	EXIT2(return);
+}
+
+/* called via function pointer; but 64-bit RNDIS driver calls directly */
+wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1)
+	(struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	ENTER2("%p", wnd);
+	if (wnd->tx_ok)
+		schedule_wrapndis_work(&wnd->tx_work);
+}
+
+/* called via function pointer */
+wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb,
+				struct ndis_packet *packet, NDIS_STATUS status)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	ENTER4("%p, %08X", packet, status);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	if (deserialized_driver(wnd))
+		free_tx_packet(wnd, packet, status);
+	else {
+		struct ndis_packet_oob_data *oob_data;
+		NDIS_STATUS pkt_status;
+		TRACE3("%p, %08x", packet, status);
+		oob_data = NDIS_PACKET_OOB_DATA(packet);
+		switch ((pkt_status = xchg(&oob_data->status, status))) {
+		case NDIS_STATUS_NOT_RECOGNIZED:
+			free_tx_packet(wnd, packet, status);
+			break;
+		case NDIS_STATUS_PENDING:
+		case 0:
+			break;
+		default:
+			WARNING("%p: invalid status: %08X", packet, pkt_status);
+			break;
+		}
+		/* In case a serialized driver has earlier requested a
+		 * pause by returning NDIS_STATUS_RESOURCES during
+		 * MiniportSend(Packets), wakeup tx worker now.
+		 */
+		if (xchg(&wnd->tx_ok, 1) == 0) {
+			TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
+			schedule_wrapndis_work(&wnd->tx_work);
+		}
+	}
+	EXIT3(return);
+}
+
+/* called via function pointer */
+wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
+	wnd->tx_ok = 1;
+	schedule_wrapndis_work(&wnd->tx_work);
+	EXIT3(return);
+}
+
+wstdcall void return_packet(void *arg1, void *arg2)
+{
+	struct ndis_device *wnd;
+	struct ndis_packet *packet;
+	struct miniport *mp;
+	KIRQL irql;
+
+	wnd = arg1;
+	packet = arg2;
+	ENTER4("%p, %p", wnd, packet);
+	mp = &wnd->wd->driver->ndis_driver->mp;
+	irql = serialize_lock_irql(wnd);
+	assert_irql(_irql_ == DISPATCH_LEVEL);
+	LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet);
+	serialize_unlock_irql(wnd, irql);
+	EXIT4(return);
+}
+WIN_FUNC_DECL(return_packet,2)
+
+/* called via function pointer */
+wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
+					 struct ndis_packet **packets,
+					 UINT nr_packets)
+{
+	struct ndis_device *wnd;
+	ndis_buffer *buffer;
+	struct ndis_packet *packet;
+	struct sk_buff *skb;
+	ULONG i, length, total_length;
+	struct ndis_packet_oob_data *oob_data;
+	void *virt;
+	struct ndis_tcp_ip_checksum_packet_info csum;
+
+	ENTER3("%p, %d", nmb, nr_packets);
+	assert_irql(_irql_ <= DISPATCH_LEVEL);
+	wnd = nmb->wnd;
+	for (i = 0; i < nr_packets; i++) {
+		packet = packets[i];
+		if (!packet) {
+			WARNING("empty packet ignored");
+			continue;
+		}
+		wnd->net_dev->last_rx = jiffies;
+		/* get total number of bytes in packet */
+		NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,
+						 &length, &total_length,
+						 NormalPagePriority);
+		TRACE3("%d, %d", length, total_length);
+		oob_data = NDIS_PACKET_OOB_DATA(packet);
+		TRACE3("0x%x, 0x%x, %Lu", packet->private.flags,
+		       packet->private.packet_flags, oob_data->time_rxed);
+		skb = dev_alloc_skb(total_length);
+		if (skb) {
+			while (buffer) {
+				memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
+					   MmGetMdlByteCount(buffer));
+				buffer = buffer->next;
+			}
+			skb->dev = wnd->net_dev;
+			skb->protocol = eth_type_trans(skb, wnd->net_dev);
+			pre_atomic_add(wnd->net_stats.rx_bytes, total_length);
+			atomic_inc_var(wnd->net_stats.rx_packets);
+			csum.value = (typeof(csum.value))(ULONG_PTR)
+				oob_data->ext.info[TcpIpChecksumPacketInfo];
+			TRACE3("0x%05x", csum.value);
+			if (wnd->rx_csum.value &&
+			    (csum.rx.tcp_succeeded || csum.rx.udp_succeeded ||
+			     csum.rx.ip_succeeded))
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				skb->ip_summed = CHECKSUM_NONE;
+
+			if (in_interrupt())
+				netif_rx(skb);
+			else
+				netif_rx_ni(skb);
+		} else {
+			WARNING("couldn't allocate skb; packet dropped");
+			atomic_inc_var(wnd->net_stats.rx_dropped);
+		}
+
+		/* serialized drivers check the status upon return
+		 * from this function */
+		if (!deserialized_driver(wnd)) {
+			oob_data->status = NDIS_STATUS_SUCCESS;
+			continue;
+		}
+
+		/* if a deserialized driver sets
+		 * NDIS_STATUS_RESOURCES, then it reclaims the packet
+		 * upon return from this function */
+		if (oob_data->status == NDIS_STATUS_RESOURCES)
+			continue;
+
+		assert(oob_data->status == NDIS_STATUS_SUCCESS);
+		/* deserialized driver doesn't check the status upon
+		 * return from this function; we need to call
+		 * MiniportReturnPacket later for this packet. Calling
+		 * MiniportReturnPacket from here is not correct - the
+		 * driver doesn't expect it (at least Centrino driver
+		 * crashes) */
+		schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2),
+					wnd, packet);
+	}
+	EXIT3(return);
+}
+
+/* called via function pointer (by NdisMEthIndicateReceive macro); the
+ * first argument is nmb->eth_db */
+wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
+				   char *header1, char *header, UINT header_size,
+				   void *look_ahead, UINT look_ahead_size,
+				   UINT packet_size)
+{
+	struct sk_buff *skb = NULL;
+	struct ndis_device *wnd;
+	unsigned int skb_size = 0;
+	KIRQL irql;
+	struct ndis_packet_oob_data *oob_data;
+
+	ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, "
+	       "size = %d, packet = %d", nmb, rx_ctx, header, header_size,
+	       look_ahead, look_ahead_size, packet_size);
+
+	wnd = nmb->wnd;
+	TRACE3("wnd = %p", wnd);
+	if (!wnd) {
+		ERROR("nmb is NULL");
+		EXIT3(return);
+	}
+	wnd->net_dev->last_rx = jiffies;
+
+	if (look_ahead_size < packet_size) {
+		struct ndis_packet *packet;
+		struct miniport *mp;
+		unsigned int bytes_txed;
+		NDIS_STATUS res;
+
+		NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool);
+		if (res != NDIS_STATUS_SUCCESS) {
+			atomic_inc_var(wnd->net_stats.rx_dropped);
+			EXIT3(return);
+		}
+		oob_data = NDIS_PACKET_OOB_DATA(packet);
+		mp = &wnd->wd->driver->ndis_driver->mp;
+		irql = serialize_lock_irql(wnd);
+		assert_irql(_irql_ == DISPATCH_LEVEL);
+		res = LIN2WIN6(mp->tx_data, packet, &bytes_txed, nmb,
+			       rx_ctx, look_ahead_size, packet_size);
+		serialize_unlock_irql(wnd, irql);
+		TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed);
+		if (res == NDIS_STATUS_SUCCESS) {
+			ndis_buffer *buffer;
+			struct ndis_tcp_ip_checksum_packet_info csum;
+			skb = dev_alloc_skb(header_size + look_ahead_size +
+					    bytes_txed);
+			if (!skb) {
+				ERROR("couldn't allocate skb; packet dropped");
+				atomic_inc_var(wnd->net_stats.rx_dropped);
+				NdisFreePacket(packet);
+				return;
+			}
+			memcpy_skb(skb, header, header_size);
+			memcpy_skb(skb, look_ahead, look_ahead_size);
+			buffer = packet->private.buffer_head;
+			while (buffer) {
+				memcpy_skb(skb,
+					   MmGetSystemAddressForMdl(buffer),
+					   MmGetMdlByteCount(buffer));
+				buffer = buffer->next;
+			}
+			skb_size = header_size + look_ahead_size + bytes_txed;
+			csum.value = (typeof(csum.value))(ULONG_PTR)
+				oob_data->ext.info[TcpIpChecksumPacketInfo];
+			TRACE3("0x%05x", csum.value);
+			if (wnd->rx_csum.value &&
+			    (csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				skb->ip_summed = CHECKSUM_NONE;
+			NdisFreePacket(packet);
+		} else if (res == NDIS_STATUS_PENDING) {
+			/* driver will call td_complete */
+			oob_data->look_ahead = kmalloc(look_ahead_size,
+						       GFP_ATOMIC);
+			if (!oob_data->look_ahead) {
+				NdisFreePacket(packet);
+				ERROR("packet dropped");
+				atomic_inc_var(wnd->net_stats.rx_dropped);
+				EXIT3(return);
+			}
+			assert(sizeof(oob_data->header) == header_size);
+			memcpy(oob_data->header, header,
+			       sizeof(oob_data->header));
+			memcpy(oob_data->look_ahead, look_ahead,
+			       look_ahead_size);
+			oob_data->look_ahead_size = look_ahead_size;
+			EXIT3(return);
+		} else {
+			WARNING("packet dropped: %08X", res);
+			atomic_inc_var(wnd->net_stats.rx_dropped);
+			NdisFreePacket(packet);
+			EXIT3(return);
+		}
+	} else {
+		skb_size = header_size + packet_size;
+		skb = dev_alloc_skb(skb_size);
+		if (skb) {
+			memcpy_skb(skb, header, header_size);
+			memcpy_skb(skb, look_ahead, packet_size);
+		}
+	}
+
+	if (skb) {
+		skb->dev = wnd->net_dev;
+		skb->protocol = eth_type_trans(skb, wnd->net_dev);
+		pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
+		atomic_inc_var(wnd->net_stats.rx_packets);
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+	}
+
+	EXIT3(return);
+}
+
+/* called via function pointer */
+wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
+					struct ndis_packet *packet,
+					NDIS_STATUS status, UINT bytes_txed)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct sk_buff *skb;
+	unsigned int skb_size;
+	struct ndis_packet_oob_data *oob_data;
+	ndis_buffer *buffer;
+	struct ndis_tcp_ip_checksum_packet_info csum;
+
+	ENTER3("wnd = %p, packet = %p, bytes_txed = %d",
+	       wnd, packet, bytes_txed);
+	if (!packet) {
+		WARNING("illegal packet");
+		EXIT3(return);
+	}
+	wnd->net_dev->last_rx = jiffies;
+	oob_data = NDIS_PACKET_OOB_DATA(packet);
+	skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +
+		bytes_txed;
+	skb = dev_alloc_skb(skb_size);
+	if (!skb) {
+		kfree(oob_data->look_ahead);
+		NdisFreePacket(packet);
+		ERROR("couldn't allocate skb; packet dropped");
+		atomic_inc_var(wnd->net_stats.rx_dropped);
+		EXIT3(return);
+	}
+	memcpy_skb(skb, oob_data->header, sizeof(oob_data->header));
+	memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size);
+	buffer = packet->private.buffer_head;
+	while (buffer) {
+		memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
+			   MmGetMdlByteCount(buffer));
+		buffer = buffer->next;
+	}
+	kfree(oob_data->look_ahead);
+	NdisFreePacket(packet);
+	skb->dev = wnd->net_dev;
+	skb->protocol = eth_type_trans(skb, wnd->net_dev);
+	pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
+	atomic_inc_var(wnd->net_stats.rx_packets);
+
+	csum.value = (typeof(csum.value))(ULONG_PTR)
+		oob_data->ext.info[TcpIpChecksumPacketInfo];
+	TRACE3("0x%05x", csum.value);
+	if (wnd->rx_csum.value &&
+	    (csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	else
+		skb->ip_summed = CHECKSUM_NONE;
+
+	if (in_interrupt())
+		netif_rx(skb);
+	else
+		netif_rx_ni(skb);
+}
+
+/* called via function pointer */
+wstdcall void EthRxComplete(struct ndis_mp_block *nmb)
+{
+	TRACE3("");
+}
+
+/* called via function pointer */
+wstdcall void NdisMQueryInformationComplete(struct ndis_mp_block *nmb,
+					    NDIS_STATUS status)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	typeof(wnd->ndis_req_task) task;
+
+	ENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status);
+	wnd->ndis_req_status = status;
+	wnd->ndis_req_done = 1;
+	if ((task = xchg(&wnd->ndis_req_task, NULL)))
+		wake_up_process(task);
+	else
+		WARNING("invalid task");
+	EXIT2(return);
+}
+
+/* called via function pointer */
+wstdcall void NdisMSetInformationComplete(struct ndis_mp_block *nmb,
+					  NDIS_STATUS status)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	typeof(wnd->ndis_req_task) task;
+
+	ENTER2("status = %08X", status);
+	wnd->ndis_req_status = status;
+	wnd->ndis_req_done = 1;
+	if ((task = xchg(&wnd->ndis_req_task, NULL)))
+		wake_up_process(task);
+	else
+		WARNING("invalid task");
+	EXIT2(return);
+}
+
+/* called via function pointer */
+wstdcall void NdisMResetComplete(struct ndis_mp_block *nmb,
+				 NDIS_STATUS status, BOOLEAN address_reset)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	typeof(wnd->ndis_req_task) task;
+
+	ENTER2("status: %08X, %u", status, address_reset);
+	wnd->ndis_req_status = status;
+	wnd->ndis_req_done = address_reset + 1;
+	if ((task = xchg(&wnd->ndis_req_task, NULL)))
+		wake_up_process(task);
+	else
+		WARNING("invalid task");
+	EXIT2(return);
+}
+
+wstdcall void WIN_FUNC(NdisMSleep,1)
+	(ULONG us)
+{
+	unsigned long delay;
+
+	ENTER4("%p: us: %u", current, us);
+	delay = USEC_TO_HZ(us);
+	sleep_hz(delay);
+	TRACE4("%p: done", current);
+}
+
+wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1)
+	(LARGE_INTEGER *time)
+{
+	*time = ticks_1601();
+	TRACE5("%Lu, %lu", *time, jiffies);
+}
+
+wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1)
+	(LONG *val)
+{
+	return InterlockedDecrement(val);
+}
+
+wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1)
+	(LONG *val)
+{
+	return InterlockedIncrement(val);
+}
+
+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3)
+	(struct nt_list *head, struct nt_list *entry,
+	 struct ndis_spinlock *lock)
+{
+	return ExInterlockedInsertHeadList(head, entry, &lock->klock);
+}
+
+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3)
+	(struct nt_list *head, struct nt_list *entry,
+	 struct ndis_spinlock *lock)
+{
+	return ExInterlockedInsertTailList(head, entry, &lock->klock);
+}
+
+wstdcall struct nt_list *WIN_FUNC(NdisInterlockedRemoveHeadList,2)
+	(struct nt_list *head, struct ndis_spinlock *lock)
+{
+	return ExInterlockedRemoveHeadList(head, &lock->klock);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMInitializeScatterGatherDma,3)
+	(struct ndis_mp_block *nmb, BOOLEAN dma_size, ULONG max_phy_map)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	ENTER2("dma_size=%d, maxtransfer=%u", dma_size, max_phy_map);
+#ifdef CONFIG_X86_64
+	if (dma_size != NDIS_DMA_64BITS) {
+		TRACE1("DMA size is not 64-bits");
+		if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)) ||
+		    pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
+						DMA_BIT_MASK(32)))
+			WARNING("setting dma mask failed");
+	}
+#endif
+	if ((wnd->attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
+	    wrap_is_pci_bus(wnd->wd->dev_bus)) {
+		wnd->sg_dma_size = max_phy_map;
+		return NDIS_STATUS_SUCCESS;
+	} else
+		EXIT1(return NDIS_STATUS_NOT_SUPPORTED);
+}
+
+wstdcall ULONG WIN_FUNC(NdisMGetDmaAlignment,1)
+	(struct ndis_mp_block *nmb)
+{
+	ENTER3("");
+	return dma_get_cache_alignment();
+}
+
+wstdcall CHAR WIN_FUNC(NdisSystemProcessorCount,0)
+	(void)
+{
+	return (CHAR)NR_CPUS;
+}
+
+wstdcall void WIN_FUNC(NdisGetCurrentProcessorCounts,3)
+	(ULONG *idle, ULONG *kernel_user, ULONG *index)
+{
+	int cpu = smp_processor_id();
+	*idle = kstat_cpu(cpu).cpustat.idle;
+	*kernel_user = kstat_cpu(cpu).cpustat.system +
+		kstat_cpu(cpu).cpustat.user;
+	*index = cpu;
+}
+
+wstdcall void WIN_FUNC(NdisInitializeEvent,1)
+	(struct ndis_event *ndis_event)
+{
+	EVENTENTER("%p", ndis_event);
+	KeInitializeEvent(&ndis_event->nt_event, NotificationEvent, 0);
+}
+
+wstdcall BOOLEAN WIN_FUNC(NdisWaitEvent,2)
+	(struct ndis_event *ndis_event, UINT ms)
+{
+	LARGE_INTEGER ticks;
+	NTSTATUS res;
+
+	EVENTENTER("%p %u", ndis_event, ms);
+	ticks = -((LARGE_INTEGER)ms * TICKSPERMSEC);
+	res = KeWaitForSingleObject(&ndis_event->nt_event, 0, 0, TRUE,
+				    ms == 0 ? NULL : &ticks);
+	if (res == STATUS_SUCCESS)
+		EXIT3(return TRUE);
+	else
+		EXIT3(return FALSE);
+}
+
+wstdcall void WIN_FUNC(NdisSetEvent,1)
+	(struct ndis_event *ndis_event)
+{
+	EVENTENTER("%p", ndis_event);
+	KeSetEvent(&ndis_event->nt_event, 0, 0);
+}
+
+wstdcall void WIN_FUNC(NdisResetEvent,1)
+	(struct ndis_event *ndis_event)
+{
+	EVENTENTER("%p", ndis_event);
+	KeResetEvent(&ndis_event->nt_event);
+}
+
+static void ndis_worker(worker_param_t dummy)
+{
+	struct nt_list *ent;
+	struct ndis_work_item *ndis_work_item;
+
+	WORKENTER("");
+	while (1) {
+		spin_lock_bh(&ndis_work_list_lock);
+		ent = RemoveHeadList(&ndis_work_list);
+		spin_unlock_bh(&ndis_work_list_lock);
+		if (!ent)
+			break;
+		ndis_work_item = container_of(ent, struct ndis_work_item, list);
+		WORKTRACE("%p: %p, %p", ndis_work_item,
+			  ndis_work_item->func, ndis_work_item->ctx);
+		LIN2WIN2(ndis_work_item->func, ndis_work_item,
+			 ndis_work_item->ctx);
+		WORKTRACE("%p done", ndis_work_item);
+	}
+	WORKEXIT(return);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisScheduleWorkItem,1)
+	(struct ndis_work_item *ndis_work_item)
+{
+	ENTER3("%p", ndis_work_item);
+	spin_lock_bh(&ndis_work_list_lock);
+	InsertTailList(&ndis_work_list, &ndis_work_item->list);
+	spin_unlock_bh(&ndis_work_list_lock);
+	WORKTRACE("scheduling %p", ndis_work_item);
+	schedule_ndis_work(&ndis_work);
+	EXIT3(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisMGetDeviceProperty,6)
+	(struct ndis_mp_block *nmb, void **phy_dev, void **func_dev,
+	 void **next_dev, void **alloc_res, void**trans_res)
+{
+	ENTER2("nmb: %p, phy_dev = %p, func_dev = %p, next_dev = %p, "
+	       "alloc_res = %p, trans_res = %p", nmb, phy_dev, func_dev,
+	       next_dev, alloc_res, trans_res);
+	if (phy_dev)
+		*phy_dev = nmb->pdo;
+	if (func_dev)
+		*func_dev = nmb->fdo;
+	if (next_dev)
+		*next_dev = nmb->next_device;
+}
+
+wstdcall void WIN_FUNC(NdisMRegisterUnloadHandler,2)
+	(struct driver_object *drv_obj, void *unload)
+{
+	if (drv_obj)
+		drv_obj->unload = unload;
+	return;
+}
+
+wstdcall UINT WIN_FUNC(NdisGetVersion,0)
+	(void)
+{
+	return 0x00050001;
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMQueryAdapterInstanceName,2)
+	(struct unicode_string *name, struct ndis_mp_block *nmb)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	struct ansi_string ansi;
+
+	if (wrap_is_pci_bus(wnd->wd->dev_bus))
+		RtlInitAnsiString(&ansi, "PCI Ethernet Adapter");
+	else
+		RtlInitAnsiString(&ansi, "USB Ethernet Adapter");
+
+	if (RtlAnsiStringToUnicodeString(name, &ansi, TRUE))
+		EXIT2(return NDIS_STATUS_RESOURCES);
+	else
+		EXIT2(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisWriteEventLogEntry,7)
+	(void *handle, NDIS_STATUS code, ULONG value, USHORT n,
+	 void *strings, ULONG datasize, void *data)
+{
+	TRACE1("0x%x, 0x%x, %u, %u", code, value, n, datasize);
+	return NDIS_STATUS_SUCCESS;
+}
+
+wstdcall void *WIN_FUNC(NdisGetRoutineAddress,1)
+	(struct unicode_string *unicode_string)
+{
+	struct ansi_string ansi_string;
+	void *address;
+
+	if (RtlUnicodeStringToAnsiString(&ansi_string, unicode_string, TRUE) !=
+	    STATUS_SUCCESS)
+		EXIT1(return NULL);
+	INFO("%s", ansi_string.buf);
+	address = ndis_get_routine_address(ansi_string.buf);
+	RtlFreeAnsiString(&ansi_string);
+	return address;
+}
+
+wstdcall ULONG WIN_FUNC(NdisReadPcmciaAttributeMemory,4)
+	(struct ndis_mp_block *nmb, ULONG offset, void *buffer,
+	 ULONG length)
+{
+	TODO();
+	return 0;
+}
+
+wstdcall ULONG WIN_FUNC(NdisWritePcmciaAttributeMemory,4)
+	(struct ndis_mp_block *nmb, ULONG offset, void *buffer,
+	 ULONG length)
+{
+	TODO();
+	return 0;
+}
+
+wstdcall void WIN_FUNC(NdisMCoIndicateReceivePacket,3)
+	(struct ndis_mp_block *nmb, struct ndis_packet **packets,
+	 UINT nr_packets)
+{
+	ENTER3("nmb = %p", nmb);
+	NdisMIndicateReceivePacket(nmb, packets, nr_packets);
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisMCoSendComplete,3)
+	(NDIS_STATUS status, struct ndis_mp_block *nmb,
+	 struct ndis_packet *packet)
+{
+	ENTER3("%08x", status);
+	NdisMSendComplete(nmb, packet, status);
+	EXIT3(return);
+}
+
+wstdcall void WIN_FUNC(NdisMCoRequestComplete,3)
+	(NDIS_STATUS status, struct ndis_mp_block *nmb,
+	 struct ndis_request *ndis_request)
+{
+	struct ndis_device *wnd = nmb->wnd;
+	typeof(wnd->ndis_req_task) task;
+
+	ENTER3("%08X", status);
+	wnd->ndis_req_status = status;
+	wnd->ndis_req_done = 1;
+	if ((task = xchg(&wnd->ndis_req_task, NULL)))
+		wake_up_process(task);
+	else
+		WARNING("invalid task");
+	EXIT3(return);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisIMNotifiyPnPEvent,2)
+	(struct ndis_mp_block *nmb, struct net_pnp_event *event)
+{
+	ENTER2("%p, %d", nmb, event->code);
+	/* NdisWrapper never calls protocol's pnp event notifier, so
+	 * nothing to do here */
+	EXIT2(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisCompletePnPEvent,2)
+	(NDIS_STATUS status, void *handle, struct net_pnp_event *event)
+{
+	ENTER2("%d, %p, %d", status, handle, event->code);
+	/* NdisWrapper never calls protocol's pnp event notifier, so
+	 * nothing to do here */
+	EXIT2(return);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMSetMiniportSecondary,2)
+	(struct ndis_mp_block *nmb2, struct ndis_mp_block *nmb1)
+{
+	ENTER3("%p, %p", nmb1, nmb2);
+	TODO();
+	EXIT3(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall NDIS_STATUS WIN_FUNC(NdisMPromoteMiniport,1)
+	(struct ndis_mp_block *nmb)
+{
+	ENTER3("%p", nmb);
+	TODO();
+	EXIT3(return NDIS_STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(NdisMCoActivateVcComplete,3)
+	(NDIS_STATUS status, void *handle, void *params)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(NdisMCoDeactivateVcComplete,2)
+	(NDIS_STATUS status, void *handle)
+{
+	TODO();
+}
+
+wstdcall void WIN_FUNC(NdisMRemoveMiniport,1)
+	(void *handle)
+{
+	TODO();
+}
+
+static void *ndis_get_routine_address(char *name)
+{
+	int i;
+	ENTER2("%p", name);
+	for (i = 0; i < sizeof(ndis_exports) / sizeof(ndis_exports[0]); i++) {
+		if (strcmp(name, ndis_exports[i].name) == 0) {
+			TRACE2("%p", ndis_exports[i].func);
+			return ndis_exports[i].func;
+		}
+	}
+	EXIT2(return NULL);
+}
+
+/* ndis_init_device is called for each device */
+int ndis_init_device(struct ndis_device *wnd)
+{
+	struct ndis_mp_block *nmb = wnd->nmb;
+
+	KeInitializeSpinLock(&nmb->lock);
+	wnd->mp_interrupt = NULL;
+	wnd->wrap_timer_slist.next = NULL;
+	if (wnd->wd->driver->ndis_driver)
+		wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
+
+	nmb->filterdbs.eth_db = nmb;
+	nmb->filterdbs.tr_db = nmb;
+	nmb->filterdbs.fddi_db = nmb;
+	nmb->filterdbs.arc_db = nmb;
+
+	nmb->rx_packet = WIN_FUNC_PTR(NdisMIndicateReceivePacket,3);
+	nmb->send_complete = WIN_FUNC_PTR(NdisMSendComplete,3);
+	nmb->send_resource_avail = WIN_FUNC_PTR(NdisMSendResourcesAvailable,1);
+	nmb->status = WIN_FUNC_PTR(NdisMIndicateStatus,4);
+	nmb->status_complete = WIN_FUNC_PTR(NdisMIndicateStatusComplete,1);
+	nmb->queryinfo_complete = WIN_FUNC_PTR(NdisMQueryInformationComplete,2);
+	nmb->setinfo_complete = WIN_FUNC_PTR(NdisMSetInformationComplete,2);
+	nmb->reset_complete = WIN_FUNC_PTR(NdisMResetComplete,3);
+	nmb->eth_rx_indicate = WIN_FUNC_PTR(EthRxIndicateHandler,8);
+	nmb->eth_rx_complete = WIN_FUNC_PTR(EthRxComplete,1);
+	nmb->td_complete = WIN_FUNC_PTR(NdisMTransferDataComplete,4);
+	return 0;
+}
+
+/* ndis_exit_device is called for each device */
+void ndis_exit_device(struct ndis_device *wnd)
+{
+	struct wrap_device_setting *setting;
+	ENTER2("%p", wnd);
+	if (down_interruptible(&loader_mutex))
+		WARNING("couldn't obtain loader_mutex");
+	nt_list_for_each_entry(setting, &wnd->wd->settings, list) {
+		struct ndis_configuration_parameter *param;
+		param = setting->encoded;
+		if (param) {
+			if (param->type == NdisParameterString)
+				RtlFreeUnicodeString(&param->data.string);
+			ExFreePool(param);
+			setting->encoded = NULL;
+		}
+	}
+	up(&loader_mutex);
+}
+
+/* ndis_init is called once when module is loaded */
+int ndis_init(void)
+{
+	InitializeListHead(&ndis_work_list);
+	spin_lock_init(&ndis_work_list_lock);
+	initialize_work(&ndis_work, ndis_worker, NULL);
+
+	ndis_wq = create_singlethread_workqueue("ndis_wq");
+	if (!ndis_wq) {
+		WARNING("couldn't create worker thread");
+		EXIT1(return -ENOMEM);
+	}
+
+	ndis_worker_thread = wrap_worker_init(ndis_wq);
+	TRACE1("%p", ndis_worker_thread);
+	return 0;
+}
+
+/* ndis_exit is called once when module is removed */
+void ndis_exit(void)
+{
+	ENTER1("");
+	if (ndis_wq)
+		destroy_workqueue(ndis_wq);
+	TRACE1("%p", ndis_worker_thread);
+	if (ndis_worker_thread)
+		ObDereferenceObject(ndis_worker_thread);
+	EXIT1(return);
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/wrapmem.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/wrapmem.c
@@ -0,0 +1,360 @@
+/*
+ *  Copyright (C) 2006 Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#define _WRAPMEM_C_
+
+#include "ntoskernel.h"
+
+struct slack_alloc_info {
+	struct nt_list list;
+	size_t size;
+};
+
+static struct nt_list allocs;
+static struct nt_list slack_allocs;
+static spinlock_t alloc_lock;
+
+struct vmem_block {
+	struct nt_list list;
+	int size;
+};
+
+static struct nt_list vmem_list;
+
+#if defined(ALLOC_DEBUG)
+struct alloc_info {
+	enum alloc_type type;
+	size_t size;
+#if ALLOC_DEBUG > 1
+	struct nt_list list;
+	const char *file;
+	int line;
+	ULONG tag;
+#endif
+};
+
+static atomic_t alloc_sizes[ALLOC_TYPE_MAX];
+#endif
+
+void wrapmem_info(void)
+{
+#ifdef ALLOC_DEBUG
+	enum alloc_type type;
+	for (type = 0; type < ALLOC_TYPE_MAX; type++)
+		INFO("total size of allocations in %d: %d",
+		       type, atomic_read(&alloc_sizes[type]));
+#endif
+}
+
+/* allocate memory and add it to list of allocated pointers; if a
+ * driver doesn't free this memory for any reason (buggy driver or we
+ * allocate space behind driver's back since we need more space than
+ * corresponding Windows structure provides etc.), this gets freed
+ * automatically when module is unloaded
+ */
+void *slack_kmalloc(size_t size)
+{
+	struct slack_alloc_info *info;
+	gfp_t flags;
+
+	ENTER4("size = %lu", (unsigned long)size);
+
+	if (irql_gfp() & GFP_ATOMIC)
+		flags = GFP_ATOMIC;
+	else
+		flags = GFP_KERNEL;
+	info = kmalloc(size + sizeof(*info), flags);
+	if (!info)
+		return NULL;
+	info->size = size;
+	spin_lock_bh(&alloc_lock);
+	InsertTailList(&slack_allocs, &info->list);
+	spin_unlock_bh(&alloc_lock);
+#ifdef ALLOC_DEBUG
+	atomic_add(size, &alloc_sizes[ALLOC_TYPE_SLACK]);
+#endif
+	TRACE4("%p, %p", info, info + 1);
+	EXIT4(return info + 1);
+}
+
+/* free pointer and remove from list of allocated pointers */
+void slack_kfree(void *ptr)
+{
+	struct slack_alloc_info *info;
+
+	ENTER4("%p", ptr);
+	info = ptr - sizeof(*info);
+	spin_lock_bh(&alloc_lock);
+	RemoveEntryList(&info->list);
+	spin_unlock_bh(&alloc_lock);
+#ifdef ALLOC_DEBUG
+	atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
+#endif
+	kfree(info);
+	EXIT4(return);
+}
+
+#if defined(ALLOC_DEBUG)
+void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line)
+{
+	struct alloc_info *info;
+
+	info = kmalloc(size + sizeof(*info), flags);
+	if (!info)
+		return NULL;
+	if (flags & GFP_ATOMIC)
+		info->type = ALLOC_TYPE_KMALLOC_ATOMIC;
+	else
+		info->type = ALLOC_TYPE_KMALLOC_NON_ATOMIC;
+	info->size = size;
+	atomic_add(size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	info->file = file;
+	info->line = line;
+	info->tag = 0;
+	spin_lock_bh(&alloc_lock);
+	InsertTailList(&allocs, &info->list);
+	spin_unlock_bh(&alloc_lock);
+#endif
+	TRACE4("%p", info + 1);
+	return info + 1;
+}
+
+void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line)
+{
+	void *ptr = wrap_kmalloc(size, flags, file, line);
+	if (ptr)
+		memset(ptr, 0, size);
+	return ptr;
+}
+
+void wrap_kfree(void *ptr)
+{
+	struct alloc_info *info;
+
+	TRACE4("%p", ptr);
+	if (!ptr)
+		return;
+	info = ptr - sizeof(*info);
+	atomic_sub(info->size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	spin_lock_bh(&alloc_lock);
+	RemoveEntryList(&info->list);
+	spin_unlock_bh(&alloc_lock);
+	if (!(info->type == ALLOC_TYPE_KMALLOC_ATOMIC ||
+	      info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC))
+		WARNING("invliad type: %d", info->type);
+#endif
+	kfree(info);
+}
+
+void *wrap_vmalloc(unsigned long size, const char *file, int line)
+{
+	struct alloc_info *info;
+
+	info = vmalloc(size + sizeof(*info));
+	if (!info)
+		return NULL;
+	info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC;
+	info->size = size;
+	atomic_add(size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	info->file = file;
+	info->line = line;
+	info->tag = 0;
+	spin_lock_bh(&alloc_lock);
+	InsertTailList(&allocs, &info->list);
+	spin_unlock_bh(&alloc_lock);
+#endif
+	return info + 1;
+}
+
+void *wrap__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+		    const char *file, int line)
+{
+	struct alloc_info *info;
+
+	info = __vmalloc(size + sizeof(*info), gfp_mask, prot);
+	if (!info)
+		return NULL;
+	if (gfp_mask & GFP_ATOMIC)
+		info->type = ALLOC_TYPE_VMALLOC_ATOMIC;
+	else
+		info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC;
+	info->size = size;
+	atomic_add(size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	info->file = file;
+	info->line = line;
+	info->tag = 0;
+	spin_lock_bh(&alloc_lock);
+	InsertTailList(&allocs, &info->list);
+	spin_unlock_bh(&alloc_lock);
+#endif
+	return info + 1;
+}
+
+void wrap_vfree(void *ptr)
+{
+	struct alloc_info *info;
+
+	info = ptr - sizeof(*info);
+	atomic_sub(info->size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	spin_lock_bh(&alloc_lock);
+	RemoveEntryList(&info->list);
+	spin_unlock_bh(&alloc_lock);
+	if (!(info->type == ALLOC_TYPE_VMALLOC_ATOMIC ||
+	      info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC))
+		WARNING("invliad type: %d", info->type);
+#endif
+	vfree(info);
+}
+
+void *wrap_alloc_pages(gfp_t flags, unsigned int size,
+		       const char *file, int line)
+{
+	struct alloc_info *info;
+
+	size += sizeof(*info);
+	info = (struct alloc_info *)__get_free_pages(flags, get_order(size));
+	if (!info)
+		return NULL;
+	info->type = ALLOC_TYPE_PAGES;
+	info->size = size;
+	atomic_add(size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	info->file = file;
+	info->line = line;
+	info->tag = 0;
+	spin_lock_bh(&alloc_lock);
+	InsertTailList(&allocs, &info->list);
+	spin_unlock_bh(&alloc_lock);
+#endif
+	return info + 1;
+}
+
+void wrap_free_pages(unsigned long ptr, int order)
+{
+	struct alloc_info *info;
+
+	info = (void *)ptr - sizeof(*info);
+	atomic_sub(info->size, &alloc_sizes[info->type]);
+#if ALLOC_DEBUG > 1
+	spin_lock_bh(&alloc_lock);
+	RemoveEntryList(&info->list);
+	spin_unlock_bh(&alloc_lock);
+	if (info->type != ALLOC_TYPE_PAGES)
+		WARNING("invliad type: %d", info->type);
+#endif
+	free_pages((unsigned long)info, get_order(info->size));
+}
+
+#if ALLOC_DEBUG > 1
+#undef ExAllocatePoolWithTag
+void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size,
+				 ULONG tag, const char *file, int line)
+{
+	void *addr;
+	struct alloc_info *info;
+
+	ENTER4("pool_type: %d, size: %lu, tag: %u", pool_type, size, tag);
+	addr = ExAllocatePoolWithTag(pool_type, size, tag);
+	if (!addr)
+		return NULL;
+	info = addr - sizeof(*info);
+	info->file = file;
+	info->line = line;
+	info->tag = tag;
+	EXIT4(return addr);
+}
+#endif
+
+int alloc_size(enum alloc_type type)
+{
+	if (type >= 0 && type < ALLOC_TYPE_MAX)
+		return atomic_read(&alloc_sizes[type]);
+	else
+		return -EINVAL;
+}
+
+#endif // ALLOC_DEBUG
+
+int wrapmem_init(void)
+{
+	InitializeListHead(&allocs);
+	InitializeListHead(&slack_allocs);
+	InitializeListHead(&vmem_list);
+	spin_lock_init(&alloc_lock);
+	return 0;
+}
+
+void wrapmem_exit(void)
+{
+	enum alloc_type type;
+	struct nt_list *ent;
+
+	/* free all pointers on the slack list */
+	while (1) {
+		struct slack_alloc_info *info;
+		spin_lock_bh(&alloc_lock);
+		ent = RemoveHeadList(&slack_allocs);
+		spin_unlock_bh(&alloc_lock);
+		if (!ent)
+			break;
+		info = container_of(ent, struct slack_alloc_info, list);
+#ifdef ALLOC_DEBUG
+		atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
+#endif
+		kfree(info);
+	}
+	type = 0;
+#ifdef ALLOC_DEBUG
+	for (type = 0; type < ALLOC_TYPE_MAX; type++) {
+		int n = atomic_read(&alloc_sizes[type]);
+		if (n)
+			WARNING("%d bytes of memory in %d leaking", n, type);
+	}
+
+#if ALLOC_DEBUG > 1
+	while (1) {
+		struct alloc_info *info;
+
+		spin_lock_bh(&alloc_lock);
+		ent = RemoveHeadList(&allocs);
+		spin_unlock_bh(&alloc_lock);
+		if (!ent)
+			break;
+		info = container_of(ent, struct alloc_info, list);
+		atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]);
+		WARNING("%p in %d of size %zu allocated at %s(%d) "
+			"with tag 0x%08X leaking; freeing it now",
+			info + 1, info->type, info->size, info->file,
+			info->line, info->tag);
+		if (info->type == ALLOC_TYPE_KMALLOC_ATOMIC ||
+		    info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC)
+			kfree(info);
+		else if (info->type == ALLOC_TYPE_VMALLOC_ATOMIC ||
+			 info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC)
+			vfree(info);
+		else if (info->type == ALLOC_TYPE_PAGES)
+			free_pages((unsigned long)info, get_order(info->size));
+		else
+			WARNING("invalid type: %d; not freed", info->type);
+	}
+#endif
+#endif
+	return;
+}
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/BOM
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	http://sourceforge.net/project/showfiles.php?group_id=93482
+Current Version:	1.55
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/mkexport.sh
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/mkexport.sh
@@ -0,0 +1,42 @@
+#! /bin/sh
+
+# Generate exports symbol table from C files
+
+input="$1"
+output="$2"
+exports=$(basename "$output" .h)
+exec >"$output"
+
+echo "/* automatically generated from src */";
+
+sed -n -e '/^\(wstdcall\|wfastcall\|noregparm\|__attribute__\)/{
+:more
+N
+s/\([^{]\)$/\1/
+t more
+s/\n{$/;/
+p
+}' $input
+
+echo "#ifdef CONFIG_X86_64";
+
+sed -n \
+	-e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
+'WIN_FUNC_DECL(\1, \2)/p' \
+	-e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
+'WIN_FUNC_DECL(\1, \2)/p' $input | sort -u
+
+echo "#endif"
+echo "extern struct wrap_export $exports[];"
+echo "struct wrap_export $exports[] = {"
+
+sed -n \
+	-e 's/.*WIN_FUNC(_win_\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
+'	WIN_WIN_SYMBOL(\1, \2),/p' \
+	-e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\
+'	WIN_SYMBOL(\1, \2),/p' \
+	-e 's/.*WIN_SYMBOL_MAP(\("[^"]\+"\)[ ,\n]\+\([^)]\+\)).*/'\
+'	{\1, (generic_func)\2},/p' $input | sort -u
+
+echo "	{NULL, NULL}"
+echo "};"
--- linux-ec2-2.6.32.orig/ubuntu/ndiswrapper/ntoskernel_io.c
+++ linux-ec2-2.6.32/ubuntu/ndiswrapper/ntoskernel_io.c
@@ -0,0 +1,1106 @@
+/*
+ *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
+ *
+ *  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.
+ *
+ */
+
+#include "ntoskernel.h"
+#include "ndis.h"
+#include "wrapndis.h"
+#include "usb.h"
+#include "loader.h"
+#include "ntoskernel_io_exports.h"
+
+wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1)
+	(KIRQL *irql) __acquires(irql)
+{
+	spin_lock_bh(&irp_cancel_lock);
+	*irql = 0;
+}
+
+wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1)
+	(KIRQL irql) __releases(irql)
+{
+	spin_unlock_bh(&irp_cancel_lock);
+}
+
+wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2)
+	(UCHAR major, UCHAR minor)
+{
+	IOENTER("%d, %x", major, minor);
+	if (major == 1 &&
+	    (minor == 0x30 || // Windows 2003
+	     minor == 0x20 || // Windows XP
+	     minor == 0x10)) // Windows 2000
+		IOEXIT(return TRUE);
+	IOEXIT(return FALSE);
+}
+
+wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1)
+	(struct irp *irp)
+{
+#ifdef CONFIG_X86_64
+	return FALSE;
+#else
+	return TRUE;
+#endif
+}
+
+wstdcall void WIN_FUNC(IoInitializeIrp,3)
+	(struct irp *irp, USHORT size, CCHAR stack_count)
+{
+	IOENTER("irp: %p, %d, %d", irp, size, stack_count);
+
+	memset(irp, 0, size);
+	irp->size = size;
+	irp->stack_count = stack_count;
+	irp->current_location = stack_count;
+	IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count);
+	IOEXIT(return);
+}
+
+wstdcall void WIN_FUNC(IoReuseIrp,2)
+	(struct irp *irp, NTSTATUS status)
+{
+	IOENTER("%p, %d", irp, status);
+	if (irp) {
+		UCHAR alloc_flags;
+
+		alloc_flags = irp->alloc_flags;
+		IoInitializeIrp(irp, irp->size, irp->stack_count);
+		irp->alloc_flags = alloc_flags;
+		irp->io_status.status = status;
+	}
+	IOEXIT(return);
+}
+
+wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2)
+	(char stack_count, BOOLEAN charge_quota)
+{
+	struct irp *irp;
+	int irp_size;
+
+	IOENTER("count: %d", stack_count);
+	stack_count++;
+	irp_size = IoSizeOfIrp(stack_count);
+	irp = kmalloc(irp_size, irql_gfp());
+	if (irp)
+		IoInitializeIrp(irp, irp_size, stack_count);
+	IOTRACE("irp %p", irp);
+	IOEXIT(return irp);
+}
+
+wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1)
+	(struct irp *irp)
+{
+	typeof(irp->cancel_routine) cancel_routine;
+
+	/* NB: this function may be called at DISPATCH_LEVEL */
+	IOTRACE("irp: %p", irp);
+	if (!irp)
+		return FALSE;
+	DUMP_IRP(irp);
+	IoAcquireCancelSpinLock(&irp->cancel_irql);
+	cancel_routine = xchg(&irp->cancel_routine, NULL);
+	IOTRACE("%p", cancel_routine);
+	irp->cancel = TRUE;
+	if (cancel_routine) {
+		struct io_stack_location *irp_sl;
+		irp_sl = IoGetCurrentIrpStackLocation(irp);
+		IOTRACE("%p, %p", irp_sl, irp_sl->dev_obj);
+		/* cancel_routine will release the spin lock */
+		__release(irp->cancel_irql);
+		LIN2WIN2(cancel_routine, irp_sl->dev_obj, irp);
+		/* in usb's cancel, irp->cancel is set to indicate
+		 * status of cancel */
+		IOEXIT(return xchg(&irp->cancel, TRUE));
+	} else {
+		IOTRACE("irp %p already canceled", irp);
+		IoReleaseCancelSpinLock(irp->cancel_irql);
+		IOEXIT(return FALSE);
+	}
+}
+
+wstdcall void IoQueueThreadIrp(struct irp *irp)
+{
+	struct nt_thread *thread;
+	KIRQL irql;
+
+	thread = get_current_nt_thread();
+	if (thread) {
+		IOTRACE("thread: %p, task: %p", thread, thread->task);
+		irp->flags |= IRP_SYNCHRONOUS_API;
+		irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
+		InsertTailList(&thread->irps, &irp->thread_list);
+		IoIrpThread(irp) = thread;
+		nt_spin_unlock_irql(&thread->lock, irql);
+	} else
+		IoIrpThread(irp) = NULL;
+}
+
+wstdcall void IoDequeueThreadIrp(struct irp *irp)
+{
+	struct nt_thread *thread;
+	KIRQL irql;
+
+	thread = IoIrpThread(irp);
+	if (thread) {
+		irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL);
+		RemoveEntryList(&irp->thread_list);
+		nt_spin_unlock_irql(&thread->lock, irql);
+	}
+}
+
+wstdcall void WIN_FUNC(IoFreeIrp,1)
+	(struct irp *irp)
+{
+	IOENTER("irp = %p", irp);
+	if (irp->flags & IRP_SYNCHRONOUS_API)
+		IoDequeueThreadIrp(irp);
+	kfree(irp);
+
+	IOEXIT(return);
+}
+
+wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6)
+	(ULONG major_fn, struct device_object *dev_obj, void *buffer,
+	 ULONG length, LARGE_INTEGER *offset,
+	 struct io_status_block *user_status)
+{
+	struct irp *irp;
+	struct io_stack_location *irp_sl;
+
+	IOENTER("%p", dev_obj);
+	if (!dev_obj)
+		IOEXIT(return NULL);
+	irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
+	if (irp == NULL) {
+		WARNING("couldn't allocate irp");
+		IOEXIT(return NULL);
+	}
+
+	irp_sl = IoGetNextIrpStackLocation(irp);
+	irp_sl->major_fn = major_fn;
+	IOTRACE("major_fn: %d", major_fn);
+	irp_sl->minor_fn = 0;
+	irp_sl->flags = 0;
+	irp_sl->control = 0;
+	irp_sl->dev_obj = dev_obj;
+	irp_sl->file_obj = NULL;
+	irp_sl->completion_routine = NULL;
+
+	if (dev_obj->flags & DO_DIRECT_IO) {
+		irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp);
+		if (irp->mdl == NULL) {
+			IoFreeIrp(irp);
+			return NULL;
+		}
+		MmProbeAndLockPages(irp->mdl, KernelMode,
+				    major_fn == IRP_MJ_WRITE ?
+				    IoReadAccess : IoWriteAccess);
+		IOTRACE("mdl: %p", irp->mdl);
+	} else if (dev_obj->flags & DO_BUFFERED_IO) {
+		irp->associated_irp.system_buffer = buffer;
+		irp->flags = IRP_BUFFERED_IO;
+		irp->mdl = NULL;
+		IOTRACE("buffer: %p", buffer);
+	}
+	if (major_fn == IRP_MJ_READ) {
+		irp_sl->params.read.length = length;
+		irp_sl->params.read.byte_offset = *offset;
+	} else if (major_fn == IRP_MJ_WRITE) {
+		irp_sl->params.write.length = length;
+		irp_sl->params.write.byte_offset = *offset;
+	}
+	irp->user_status = user_status;
+	IOTRACE("irp: %p", irp);
+	return irp;
+}
+
+wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7)
+	(ULONG major_fn, struct device_object *dev_obj, void *buf,
+	 ULONG length, LARGE_INTEGER *offset, struct nt_event *event,
+	 struct io_status_block *user_status)
+{
+	struct irp *irp;
+
+	irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length,
+					    offset, user_status);
+	if (irp == NULL)
+		return NULL;
+	irp->user_event = event;
+	IoQueueThreadIrp(irp);
+	return irp;
+}
+
+wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9)
+	(ULONG ioctl, struct device_object *dev_obj,
+	 void *input_buf, ULONG input_buf_len, void *output_buf,
+	 ULONG output_buf_len, BOOLEAN internal_ioctl,
+	 struct nt_event *event, struct io_status_block *io_status)
+{
+	struct irp *irp;
+	struct io_stack_location *irp_sl;
+	ULONG buf_len;
+
+	IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl);
+	if (!dev_obj)
+		IOEXIT(return NULL);
+	irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
+	if (irp == NULL) {
+		WARNING("couldn't allocate irp");
+		return NULL;
+	}
+	irp_sl = IoGetNextIrpStackLocation(irp);
+	irp_sl->params.dev_ioctl.code = ioctl;
+	irp_sl->params.dev_ioctl.input_buf_len = input_buf_len;
+	irp_sl->params.dev_ioctl.output_buf_len = output_buf_len;
+	irp_sl->major_fn = (internal_ioctl) ?
+		IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
+	IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl));
+
+	switch (IO_METHOD_FROM_CTL_CODE(ioctl)) {
+	case METHOD_BUFFERED:
+		buf_len = max(input_buf_len, output_buf_len);
+		if (buf_len) {
+			irp->associated_irp.system_buffer =
+				ExAllocatePoolWithTag(NonPagedPool, buf_len, 0);
+			if (!irp->associated_irp.system_buffer) {
+				IoFreeIrp(irp);
+				IOEXIT(return NULL);
+			}
+			irp->associated_irp.system_buffer = input_buf;
+			if (input_buf)
+				memcpy(irp->associated_irp.system_buffer,
+				       input_buf, input_buf_len);
+			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
+			if (output_buf)
+				irp->flags = IRP_INPUT_OPERATION;
+			irp->user_buf = output_buf;
+		} else
+			irp->user_buf = NULL;
+		break;
+	case METHOD_IN_DIRECT:
+	case METHOD_OUT_DIRECT:
+		if (input_buf) {
+			irp->associated_irp.system_buffer =
+				ExAllocatePoolWithTag(NonPagedPool,
+						      input_buf_len, 0);
+			if (!irp->associated_irp.system_buffer) {
+				IoFreeIrp(irp);
+				IOEXIT(return NULL);
+			}
+			memcpy(irp->associated_irp.system_buffer,
+			       input_buf, input_buf_len);
+			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
+		}
+		/* TODO: we are supposed to setup MDL, but USB layer
+		 * doesn't use MDLs. Moreover, USB layer mirrors
+		 * non-DMAable buffers, so no need to allocate
+		 * DMAable buffer here */
+		if (output_buf) {
+			irp->associated_irp.system_buffer =
+				ExAllocatePoolWithTag(NonPagedPool,
+						      output_buf_len, 0);
+			if (!irp->associated_irp.system_buffer) {
+				IoFreeIrp(irp);
+				IOEXIT(return NULL);
+			}
+			irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
+		}
+		break;
+	case METHOD_NEITHER:
+		irp->user_buf = output_buf;
+		irp_sl->params.dev_ioctl.type3_input_buf = input_buf;
+		break;
+	}
+
+	irp->user_status = io_status;
+	irp->user_event = event;
+	IoQueueThreadIrp(irp);
+
+	IOTRACE("irp: %p", irp);
+	IOEXIT(return irp);
+}
+
+wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2)
+	(struct device_object *dev_obj, struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	NTSTATUS status;
+	driver_dispatch_t *major_func;
+	struct driver_object *drv_obj;
+
+	if (irp->current_location <= 0) {
+		ERROR("invalid irp: %p, %d", irp, irp->current_location);
+		return STATUS_INVALID_PARAMETER;
+	}
+	IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj,
+		irp->current_location, irp->stack_count,
+		IoGetCurrentIrpStackLocation(irp));
+	IoSetNextIrpStackLocation(irp);
+	DUMP_IRP(irp);
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	drv_obj = dev_obj->drv_obj;
+	irp_sl->dev_obj = dev_obj;
+	major_func = drv_obj->major_func[irp_sl->major_fn];
+	IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj);
+	if (major_func)
+		status = LIN2WIN2(major_func, dev_obj, irp);
+	else {
+		ERROR("major_function %d is not implemented",
+		      irp_sl->major_fn);
+		status = STATUS_NOT_SUPPORTED;
+	}
+	IOEXIT(return status);
+}
+
+wfastcall void WIN_FUNC(IofCompleteRequest,2)
+	(struct irp *irp, CHAR prio_boost)
+{
+	struct io_stack_location *irp_sl;
+
+#ifdef IO_DEBUG
+	DUMP_IRP(irp);
+	if (irp->io_status.status == STATUS_PENDING) {
+		ERROR("invalid irp: %p, STATUS_PENDING", irp);
+		return;
+	}
+	if (irp->current_location < 0 ||
+	    irp->current_location >= irp->stack_count) {
+		ERROR("invalid irp: %p, %d", irp, irp->current_location);
+		return;
+	}
+#endif
+	for (irp_sl = IoGetCurrentIrpStackLocation(irp);
+	     irp->current_location < irp->stack_count; irp_sl++) {
+		struct device_object *dev_obj;
+		NTSTATUS status;
+
+		DUMP_IRP(irp);
+		if (irp_sl->control & SL_PENDING_RETURNED)
+			irp->pending_returned = TRUE;
+
+		/* current_location and dev_obj must be same as when
+		 * driver called IoSetCompletionRoutine, which sets
+		 * completion routine at next (lower) location, which
+		 * is what we are going to call below; so we set
+		 * current_location and dev_obj for the previous
+		 * (higher) location */
+		IoSkipCurrentIrpStackLocation(irp);
+		if (irp->current_location < irp->stack_count)
+			dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj;
+		else
+			dev_obj = NULL;
+
+		IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count,
+			dev_obj);
+		if (irp_sl->completion_routine &&
+		    ((irp->io_status.status == STATUS_SUCCESS &&
+		      irp_sl->control & SL_INVOKE_ON_SUCCESS) ||
+		     (irp->io_status.status != STATUS_SUCCESS &&
+		      irp_sl->control & SL_INVOKE_ON_ERROR) ||
+		     (irp->cancel == TRUE &&
+		      irp_sl->control & SL_INVOKE_ON_CANCEL))) {
+			IOTRACE("calling completion_routine at: %p, %p",
+				irp_sl->completion_routine, irp_sl->context);
+			status = LIN2WIN3(irp_sl->completion_routine,
+					  dev_obj, irp, irp_sl->context);
+			IOTRACE("status: %08X", status);
+			if (status == STATUS_MORE_PROCESSING_REQUIRED)
+				IOEXIT(return);
+		} else {
+			/* propagate pending status to next irp_sl */
+			if (irp->pending_returned &&
+			    irp->current_location < irp->stack_count)
+				IoMarkIrpPending(irp);
+		}
+	}
+
+	if (irp->user_status) {
+		irp->user_status->status = irp->io_status.status;
+		irp->user_status->info = irp->io_status.info;
+	}
+
+	if (irp->user_event) {
+		IOTRACE("setting event %p", irp->user_event);
+		KeSetEvent(irp->user_event, prio_boost, FALSE);
+	}
+
+	if (irp->associated_irp.system_buffer &&
+	    (irp->flags & IRP_DEALLOCATE_BUFFER))
+		ExFreePool(irp->associated_irp.system_buffer);
+	else {
+		struct mdl *mdl;
+		while ((mdl = irp->mdl)) {
+			irp->mdl = mdl->next;
+			MmUnlockPages(mdl);
+			IoFreeMdl(mdl);
+		}
+	}
+	IOTRACE("freeing irp %p", irp);
+	IoFreeIrp(irp);
+	IOEXIT(return);
+}
+
+wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp)
+{
+	IoSkipCurrentIrpStackLocation(irp);
+	IOEXIT(return IoCallDriver(dev_obj, irp));
+}
+
+wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj,
+				    struct irp *irp, void *context)
+{
+	if (irp->pending_returned == TRUE)
+		KeSetEvent(context, IO_NO_INCREMENT, FALSE);
+	IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED);
+}
+WIN_FUNC_DECL(IoIrpSyncComplete,3)
+
+wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj,
+				   struct irp *irp)
+{
+	struct nt_event event;
+	NTSTATUS status;
+
+	IoCopyCurrentIrpStackLocationToNext(irp);
+	KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+	/* completion function is called as Windows function */
+	IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event,
+			       TRUE, TRUE, TRUE);
+	status = IoCallDriver(dev_obj, irp);
+	IOTRACE("%08X", status);
+	if (status == STATUS_PENDING) {
+		KeWaitForSingleObject(&event, Executive, KernelMode, FALSE,
+				      NULL);
+		status = irp->io_status.status;
+	}
+	IOTRACE("%08X", status);
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(IoSyncForwardIrp,2)
+
+wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj,
+				    struct irp *irp)
+{
+	NTSTATUS status;
+
+	IoCopyCurrentIrpStackLocationToNext(irp);
+	status = IoCallDriver(dev_obj, irp);
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(IoAsyncForwardIrp,2)
+
+wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj,
+					 struct irp *irp)
+{
+	struct io_stack_location *irp_sl;
+	NTSTATUS status;
+
+	irp_sl = IoGetCurrentIrpStackLocation(irp);
+	WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn);
+	irp->io_status.status = STATUS_SUCCESS;
+	irp->io_status.info = 0;
+	status = irp->io_status.status;
+	IoCompleteRequest(irp, IO_NO_INCREMENT);
+	IOEXIT(return status);
+}
+WIN_FUNC_DECL(IoInvalidDeviceRequest,2)
+
+static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL)
+{
+	struct kinterrupt *interrupt = data;
+	BOOLEAN ret;
+
+#ifdef CONFIG_DEBUG_SHIRQ
+	if (!interrupt->u.enabled)
+		EXIT1(return IRQ_NONE);
+#endif
+	TRACE6("%p", interrupt);
+	nt_spin_lock(interrupt->actual_lock);
+	ret = LIN2WIN2(interrupt->isr, interrupt, interrupt->isr_ctx);
+	nt_spin_unlock(interrupt->actual_lock);
+	if (ret == TRUE)
+		EXIT6(return IRQ_HANDLED);
+	else
+		EXIT6(return IRQ_NONE);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11)
+	(struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE isr, void *isr_ctx,
+	 NT_SPIN_LOCK *lock, ULONG vector, KIRQL irql, KIRQL synch_irql,
+	 enum kinterrupt_mode mode, BOOLEAN shared, KAFFINITY cpu_mask,
+	 BOOLEAN save_fp)
+{
+	struct kinterrupt *interrupt;
+	IOENTER("");
+	interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL);
+	if (!interrupt)
+		IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
+	interrupt->vector = vector;
+	interrupt->cpu_mask = cpu_mask;
+	nt_spin_lock_init(&interrupt->lock);
+	if (lock)
+		interrupt->actual_lock = lock;
+	else
+		interrupt->actual_lock = &interrupt->lock;
+	interrupt->shared = shared;
+	interrupt->save_fp = save_fp;
+	interrupt->isr = isr;
+	interrupt->isr_ctx = isr_ctx;
+	InitializeListHead(&interrupt->list);
+	interrupt->irql = irql;
+	interrupt->synch_irql = synch_irql;
+	interrupt->mode = mode;
+	if (request_irq(vector, io_irq_isr, shared ? IRQF_SHARED : 0,
+			"ndiswrapper", interrupt)) {
+		WARNING("request for irq %d failed", vector);
+		kfree(interrupt);
+		IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
+	}
+	*kinterrupt = interrupt;
+#ifdef CONFIG_DEBUG_SHIRQ
+	interrupt->u.enabled = 1;
+#endif
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(IoDisconnectInterrupt,1)
+	(struct kinterrupt *interrupt)
+{
+#ifdef CONFIG_DEBUG_SHIRQ
+	interrupt->u.enabled = 0;
+#endif
+	free_irq(interrupt->vector, interrupt);
+	kfree(interrupt);
+}
+
+wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5)
+	(void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota,
+	 struct irp *irp)
+{
+	struct mdl *mdl;
+	mdl = allocate_init_mdl(virt, length);
+	if (!mdl)
+		return NULL;
+	if (irp) {
+		if (second_buf == TRUE) {
+			struct mdl *last;
+
+			last = irp->mdl;
+			while (last->next)
+				last = last->next;
+			last->next = mdl;
+		} else
+			irp->mdl = mdl;
+	}
+	IOTRACE("%p", mdl);
+	return mdl;
+}
+
+wstdcall void WIN_FUNC(IoFreeMdl,1)
+	(struct mdl *mdl)
+{
+	IOTRACE("%p", mdl);
+	free_mdl(mdl);
+}
+
+wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1)
+	(struct device_object *dev_obj)
+{
+	struct io_workitem *io_workitem;
+
+	IOENTER("%p", dev_obj);
+	io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp());
+	if (!io_workitem)
+		IOEXIT(return NULL);
+	io_workitem->dev_obj = dev_obj;
+	IOEXIT(return io_workitem);
+}
+
+wstdcall void WIN_FUNC(IoFreeWorkItem,1)
+	(struct io_workitem *io_workitem)
+{
+	kfree(io_workitem);
+	IOEXIT(return);
+}
+
+wstdcall void WIN_FUNC(IoQueueWorkItem,4)
+	(struct io_workitem *io_workitem, void *func,
+	 enum work_queue_type queue_type, void *context)
+{
+	IOENTER("%p, %p", io_workitem, io_workitem->dev_obj);
+	io_workitem->worker_routine = func;
+	io_workitem->context = context;
+	schedule_ntos_work_item(func, io_workitem->dev_obj, context);
+	IOEXIT(return);
+}
+
+wstdcall void WIN_FUNC(ExQueueWorkItem,2)
+	(struct io_workitem *io_workitem, enum work_queue_type queue_type)
+{
+	IOENTER("%p", io_workitem);
+	schedule_ntos_work_item(io_workitem->worker_routine,
+				io_workitem->dev_obj, io_workitem->context);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4)
+	(struct driver_object *drv_obj, void *client_id, ULONG extlen,
+	 void **ext)
+{
+	struct custom_ext *ce;
+
+	IOENTER("%p, %p", drv_obj, client_id);
+	ce = kmalloc(sizeof(*ce) + extlen, irql_gfp());
+	if (ce == NULL)
+		return STATUS_INSUFFICIENT_RESOURCES;
+
+	IOTRACE("custom_ext: %p", ce);
+	ce->client_id = client_id;
+	spin_lock_bh(&ntoskernel_lock);
+	InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list);
+	spin_unlock_bh(&ntoskernel_lock);
+
+	*ext = (void *)ce + sizeof(*ce);
+	IOTRACE("ext: %p", *ext);
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2)
+	(struct driver_object *drv_obj, void *client_id)
+{
+	struct custom_ext *ce;
+	void *ret;
+
+	IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id);
+	ret = NULL;
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) {
+		if (ce->client_id == client_id) {
+			ret = (void *)ce + sizeof(*ce);
+			break;
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	IOTRACE("ret: %p", ret);
+	return ret;
+}
+
+void free_custom_extensions(struct driver_extension *drv_ext)
+{
+	struct nt_list *ent;
+
+	IOENTER("%p", drv_ext);
+	spin_lock_bh(&ntoskernel_lock);
+	while ((ent = RemoveHeadList(&drv_ext->custom_ext)))
+		kfree(ent);
+	spin_unlock_bh(&ntoskernel_lock);
+	IOEXIT(return);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7)
+	(struct driver_object *drv_obj, ULONG dev_ext_length,
+	 struct unicode_string *dev_name, DEVICE_TYPE dev_type,
+	 ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev)
+{
+	struct device_object *dev;
+	struct dev_obj_ext *dev_obj_ext;
+	int size;
+
+	IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name);
+
+	size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext);
+	dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name);
+	if (!dev)
+		IOEXIT(return STATUS_INSUFFICIENT_RESOURCES);
+	if (dev_ext_length)
+		dev->dev_ext = dev + 1;
+	else
+		dev->dev_ext = NULL;
+
+	dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length;
+	dev_obj_ext->dev_obj = dev;
+	dev_obj_ext->size = 0;
+	dev_obj_ext->type = IO_TYPE_DEVICE;
+	dev->dev_obj_ext = dev_obj_ext;
+
+	dev->type = dev_type;
+	dev->flags = 0;
+	dev->size = sizeof(*dev) + dev_ext_length;
+	dev->ref_count = 1;
+	dev->attached = NULL;
+	dev->stack_count = 1;
+
+	dev->drv_obj = drv_obj;
+	dev->next = drv_obj->dev_obj;
+	drv_obj->dev_obj = dev;
+
+	dev->align_req = 1;
+	dev->characteristics = dev_chars;
+	dev->io_timer = NULL;
+	KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE);
+	dev->vpb = NULL;
+
+	IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext);
+	*newdev = dev;
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2)
+	(struct unicode_string *link, struct unicode_string *dev_name)
+{
+	struct ansi_string ansi;
+
+	IOENTER("%p, %p", dev_name, link);
+	if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) ==
+			 STATUS_SUCCESS)) {
+		IOTRACE("dev_name: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
+		     STATUS_SUCCESS)) {
+		IOTRACE("link: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+//	TODO();
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2)
+	(struct unicode_string *link, struct unicode_string *dev_name)
+{
+	IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name));
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1)
+	(struct unicode_string *link)
+{
+	struct ansi_string ansi;
+
+	IOENTER("%p", link);
+	if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) ==
+		     STATUS_SUCCESS)) {
+		IOTRACE("dev_name: %s", ansi.buf);
+		RtlFreeAnsiString(&ansi);
+	}
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(IoDeleteDevice,1)
+	(struct device_object *dev)
+{
+	IOENTER("%p", dev);
+	if (dev == NULL)
+		IOEXIT(return);
+	IOTRACE("drv_obj: %p", dev->drv_obj);
+	if (dev->drv_obj) {
+		struct device_object *prev;
+
+		prev = dev->drv_obj->dev_obj;
+		IOTRACE("dev_obj: %p", prev);
+		if (prev == dev)
+			dev->drv_obj->dev_obj = dev->next;
+		else if (prev) {
+			while (prev->next != dev)
+				prev = prev->next;
+			prev->next = dev->next;
+		}
+	}
+	ObDereferenceObject(dev);
+	IOEXIT(return);
+}
+
+wstdcall void WIN_FUNC(IoDetachDevice,1)
+	(struct device_object *tgt)
+{
+	struct device_object *tail;
+
+	IOENTER("%p", tgt);
+	if (!tgt)
+		IOEXIT(return);
+	tail = tgt->attached;
+	if (!tail)
+		IOEXIT(return);
+	IOTRACE("tail: %p", tail);
+
+	spin_lock_bh(&ntoskernel_lock);
+	tgt->attached = tail->attached;
+	IOTRACE("attached:%p", tgt->attached);
+	for ( ; tail; tail = tail->attached) {
+		IOTRACE("tail:%p", tail);
+		tail->stack_count--;
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	IOEXIT(return);
+}
+
+wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1)
+	(struct device_object *dev)
+{
+	IOENTER("%p", dev);
+	if (!dev)
+		IOEXIT(return NULL);
+	spin_lock_bh(&ntoskernel_lock);
+	while (dev->attached)
+		dev = dev->attached;
+	spin_unlock_bh(&ntoskernel_lock);
+	IOEXIT(return dev);
+}
+
+wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1)
+	(struct device_object *dev)
+{
+	IOENTER("%p", dev);
+	if (!dev)
+		IOEXIT(return NULL);
+	dev = IoGetAttachedDevice(dev);
+	ObReferenceObject(dev);
+	IOEXIT(return dev);
+}
+
+wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2)
+	(struct device_object *src, struct device_object *tgt)
+{
+	struct device_object *attached;
+	struct dev_obj_ext *src_dev_ext;
+
+	IOENTER("%p, %p", src, tgt);
+	attached = IoGetAttachedDevice(tgt);
+	IOTRACE("%p", attached);
+	src_dev_ext = src->dev_obj_ext;
+	spin_lock_bh(&ntoskernel_lock);
+	if (attached)
+		attached->attached = src;
+	src->attached = NULL;
+	src->stack_count = attached->stack_count + 1;
+	src_dev_ext->attached_to = attached;
+	spin_unlock_bh(&ntoskernel_lock);
+	IOTRACE("stack_count: %d -> %d", attached->stack_count,
+		src->stack_count);
+	IOEXIT(return attached);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5)
+	(struct device_object *pdo, enum device_registry_property dev_property,
+	 ULONG buffer_len, void *buffer, ULONG *result_len)
+{
+	struct ansi_string ansi;
+	struct unicode_string unicode;
+	struct wrap_device *wd;
+	ULONG need;
+
+	IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, "
+		"buffer = %p, result_len = %p", pdo, dev_property,
+		buffer_len, buffer, result_len);
+
+	wd = pdo->reserved;
+	switch (dev_property) {
+	case DevicePropertyDeviceDescription:
+	case DevicePropertyFriendlyName:
+	case DevicePropertyDriverKeyName:
+		if (wrap_is_pci_bus(wd->dev_bus))
+			RtlInitAnsiString(&ansi, "PCI");
+		else // if (wrap_is_usb_bus(wd->dev_bus))
+			RtlInitAnsiString(&ansi, "USB");
+		need = sizeof(wchar_t) * (ansi.max_length + 1);
+		if (buffer_len < need) {
+			*result_len = need;
+			IOEXIT(return STATUS_BUFFER_TOO_SMALL);
+		}
+		unicode.max_length = buffer_len;
+		unicode.buf = buffer;
+		if (RtlAnsiStringToUnicodeString(&unicode, &ansi,
+						 FALSE) != STATUS_SUCCESS) {
+			*result_len = unicode.length;
+			IOEXIT(return STATUS_BUFFER_TOO_SMALL);
+		}
+		IOEXIT(return STATUS_SUCCESS);
+	default:
+		WARNING("%d not implemented", dev_property);
+		IOEXIT(return STATUS_INVALID_PARAMETER_2);
+	}
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4)
+	(struct unicode_string *name, ACCESS_MASK desired_access,
+	 void *file_obj, struct device_object *dev_obj)
+{
+	struct common_object_header *coh;
+
+	dev_obj = NULL;
+	/* TODO: access is not checked and file_obj is set to NULL */
+	file_obj = NULL;
+	spin_lock_bh(&ntoskernel_lock);
+	nt_list_for_each_entry(coh, &object_list, list) {
+		TRACE5("header: %p, type: %d", coh, coh->type);
+		if (coh->type != OBJECT_TYPE_DEVICE)
+			continue;
+		if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) {
+			dev_obj = HEADER_TO_OBJECT(coh);
+			TRACE5("dev_obj: %p", dev_obj);
+			break;
+		}
+	}
+	spin_unlock_bh(&ntoskernel_lock);
+	if (dev_obj)
+		IOEXIT(return STATUS_SUCCESS);
+	else
+		IOEXIT(return STATUS_OBJECT_NAME_INVALID);
+}
+
+/* NOTE: Make sure to compile with -freg-struct-return, so gcc will
+ * return union in register, like Windows */
+wstdcall union power_state WIN_FUNC(PoSetPowerState,3)
+	(struct device_object *dev_obj, enum power_state_type type,
+	 union power_state state)
+{
+	IOEXIT(return state);
+}
+
+wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2)
+	(struct device_object *dev_obj, struct irp *irp)
+{
+	return IoCallDriver(dev_obj, irp);
+}
+
+wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6)
+	(struct device_object *dev_obj, UCHAR minor_fn,
+	 union power_state power_state, void *completion_func,
+	 void *context, struct irp **pirp)
+{
+	struct irp *irp;
+	struct io_stack_location *irp_sl;
+
+	TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj);
+	irp = IoAllocateIrp(dev_obj->stack_count, FALSE);
+	if (!irp)
+		return STATUS_INSUFFICIENT_RESOURCES;
+	irp_sl = IoGetNextIrpStackLocation(irp);
+	irp_sl->major_fn = IRP_MJ_POWER;
+	irp_sl->minor_fn = minor_fn;
+	if (minor_fn == IRP_MN_WAIT_WAKE)
+		irp_sl->params.power.type = SystemPowerState;
+	else
+		irp_sl->params.power.type = DevicePowerState;
+	irp_sl->params.power.state = power_state;
+	irp_sl->completion_routine = completion_func;
+	irp->io_status.status = STATUS_NOT_SUPPORTED;
+	*pirp = irp;
+	return PoCallDriver(dev_obj, irp);
+}
+
+wstdcall void WIN_FUNC(PoStartNextPowerIrp,1)
+	(struct irp *irp)
+{
+	IOENTER("irp = %p", irp);
+	IOEXIT(return);
+}
+
+wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5)
+	(struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min,
+	 ULONG high_mark, ULONG lock_size)
+{
+	TODO();
+}
+
+wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2)
+	(void *io_object, UCHAR entry_size)
+{
+	/* not implemented fully */
+	void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size,
+			    irql_gfp());
+	TRACE2("%p", ret);
+	if (ret)
+		return ret + sizeof(struct io_error_log_packet);
+	else
+		return NULL;
+}
+
+wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1)
+	(void *entry)
+{
+	/* TODO: log error with codes and message */
+	ERROR("");
+}
+
+wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1)
+	(void *entry)
+{
+	TRACE2("%p", entry);
+	kfree(entry - sizeof(struct io_error_log_packet));
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5)
+	(struct io_remove_lock lock, void *tag, char *file, ULONG line,
+	 ULONG lock_size)
+{
+	TODO();
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3)
+	(struct io_remove_lock lock, void *tag, ULONG lock_size)
+{
+	TODO();
+	IOEXIT(return STATUS_SUCCESS);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4)
+	(struct device_object *pdo, struct guid *guid_class,
+	 struct unicode_string *reference, struct unicode_string *link)
+{
+	struct ansi_string ansi;
+
+	/* TODO: check if pdo is valid */
+	RtlInitAnsiString(&ansi, "ndis");
+	ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link,
+	       guid_class->data1, guid_class->data2, guid_class->data3);
+	return RtlAnsiStringToUnicodeString(link, &ansi, TRUE);
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2)
+	(struct unicode_string *link, BOOLEAN enable)
+{
+	ENTER1("link: %p, enable: %d", link, enable);
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4)
+	(struct device_object *dev_obj, ULONG type, ACCESS_MASK mask,
+	 void **handle)
+{
+	ENTER1("dev_obj: %p", dev_obj);
+	*handle = dev_obj;
+	return STATUS_SUCCESS;
+}
+
+wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2)
+	(struct device_object *dev_obj, ULONG action)
+{
+	ENTER2("%p, %d", dev_obj, action);
+	EXIT2(return STATUS_SUCCESS);
+}
+
+wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2)
+	(struct device_object *dev_obj, enum device_relation_type type)
+{
+	INFO("%p, %d", dev_obj, type);
+	TODO();
+}
+
+wstdcall void WIN_FUNC(IoInvalidateDeviceState,1)
+	(struct device_object *pdo)
+{
+	INFO("%p", pdo);
+	TODO();
+}
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/pio.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/pio.c
@@ -0,0 +1,173 @@
+/*
+ * pio.c -- low level functions I/O ports
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+/*
+ * IO port backend. Only support single or dual ports operations
+ * private data structure: it's the linked list of requested ports
+ * 
+ * Race condition issue: omnibook_pio_init/exit functions are only called from
+ * omnibook_backend_match and omnibook_remove from init.c, this should happen
+ * only at module init/exit time so there is no need for a lock.
+ */
+
+struct pio_priv_data_t {
+	unsigned long addr;
+	struct kref refcount;
+	struct list_head list;
+};
+
+static struct pio_priv_data_t pio_priv_data = {
+	.addr = 0,
+	.list = LIST_HEAD_INIT(pio_priv_data.list),
+};
+
+/*
+ * Match an entry in the linked list helper function: see if we have and entry
+ * whose addr field match maddr
+ */
+static struct pio_priv_data_t *omnibook_match_port(struct pio_priv_data_t *data,
+						      unsigned long maddr)
+{
+	struct pio_priv_data_t *cursor;
+
+	list_for_each_entry(cursor, &data->list, list) {
+		if (cursor->addr == maddr) {
+			return cursor;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * See if we have to request raddr
+ */
+static int omnibook_claim_port(struct pio_priv_data_t *data, unsigned long raddr)
+{
+	struct pio_priv_data_t *match, *new;
+
+	match = omnibook_match_port(data, raddr);
+	if (match) {
+		/* Already requested by us: increment kref and quit */
+		kref_get(&match->refcount);
+		return 0;
+	}
+
+	/* there was no match: request the region and add to list */
+	if (!request_region(raddr, 1, OMNIBOOK_MODULE_NAME)) {
+		printk(O_ERR "Request I/O port error\n");
+		return -ENODEV;
+	}
+
+	new = kmalloc(sizeof(struct pio_priv_data_t), GFP_KERNEL);
+	if (!new) {
+		release_region(raddr, 1);
+		return -ENOMEM;
+	}
+
+	kref_init(&new->refcount);
+	new->addr = raddr;
+	list_add(&new->list, &data->list);
+
+	return 0;
+}
+
+/*
+ * Register read_addr and write_addr
+ */
+static int omnibook_pio_init(const struct omnibook_operation *io_op)
+{
+	int retval = 0;
+
+	if (io_op->read_addr
+	    && (retval = omnibook_claim_port(io_op->backend->data, io_op->read_addr)))
+		goto out;
+
+	if (io_op->write_addr && (io_op->write_addr != io_op->read_addr))
+		retval = omnibook_claim_port(io_op->backend->data, io_op->write_addr);
+
+      out:
+	return retval;
+}
+
+/*
+ * REALLY release a port
+ */
+static void omnibook_free_port(struct kref *ref)
+{
+	struct pio_priv_data_t *data;
+
+	data = container_of(ref, struct pio_priv_data_t, refcount);
+	release_region(data->addr, 1);
+	list_del(&data->list);
+	kfree(data);
+}
+
+/*
+ * Unregister read_addr and write_addr
+ */
+static void omnibook_pio_exit(const struct omnibook_operation *io_op)
+{
+	struct pio_priv_data_t *match;
+
+	match = omnibook_match_port(io_op->backend->data, io_op->read_addr);
+	if (match)
+		kref_put(&match->refcount, omnibook_free_port);
+
+	match = omnibook_match_port(io_op->backend->data, io_op->write_addr);
+	if (match)
+		kref_put(&match->refcount, omnibook_free_port);
+
+}
+
+static int omnibook_io_read(const struct omnibook_operation *io_op, u8 * value)
+{
+	*value = inb(io_op->read_addr);
+	if (io_op->read_mask)
+		*value &= io_op->read_mask;
+	return 0;
+}
+
+static int omnibook_io_write(const struct omnibook_operation *io_op, u8 value)
+{
+	outb(io_op->write_addr, value);
+	return 0;
+}
+
+/*
+ * Backend interface declarations
+ */
+struct omnibook_backend pio_backend = {
+	.name = "pio",
+	.data = &pio_priv_data,
+	.init = omnibook_pio_init,
+	.exit = omnibook_pio_exit,
+	.byte_read = omnibook_io_read,
+	.byte_write = omnibook_io_write,
+};
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/polling.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/polling.c
@@ -0,0 +1,259 @@
+/*
+ * polling.c -- scancode emulation for volume buttons
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+
+/*
+ * XE3GC type key_polling polling:
+ *
+ * Polling interval for keys (100 ms)
+ */
+
+#define OMNIBOOK_POLL	msecs_to_jiffies(100)
+
+/*
+ * workqueue manipulations are mutex protected and thus kept in sync with key_polling_enabled
+ */
+static struct workqueue_struct *omnibook_wq;  
+static int key_polling_enabled;
+static DEFINE_MUTEX(poll_mutex);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_key_poller(struct work_struct *work);
+DECLARE_DELAYED_WORK(omnibook_poll_work, *omnibook_key_poller);
+#else
+static void omnibook_key_poller(void *data);
+DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, NULL);
+#endif
+
+static struct omnibook_feature key_polling_driver;
+static struct input_dev *poll_input_dev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+	static void omnibook_key_poller(struct work_struct *work)
+#else
+	static void omnibook_key_poller(void *data)
+#endif
+{
+	u8 q0a;
+	int retval;
+
+	mutex_lock(&key_polling_driver.io_op->backend->mutex);
+	__backend_byte_read(key_polling_driver.io_op, &q0a);
+	__backend_byte_write(key_polling_driver.io_op, 0);
+	mutex_unlock(&key_polling_driver.io_op->backend->mutex);
+
+#ifdef CONFIG_OMNIBOOK_DEBUG
+	if (unlikely(q0a & XE3GC_SLPB_MASK))
+		dprintk("Sleep button pressed.\n");
+	if (unlikely(q0a & XE3GC_F5_MASK))
+		dprintk("Fn-F5 - LCD/CRT switch pressed.\n");
+	if (unlikely(q0a & XE3GC_CNTR_MASK))
+		dprintk("Fn+F3/Fn+F4 - Contrast up or down pressed.\n");
+	if (unlikely(q0a & XE3GC_BRGT_MASK))
+		dprintk("Fn+F1/Fn+F2 - Brightness up or down pressed.\n");
+#endif
+
+	/*
+	 * Volume button scancode emulaton
+	 * It emulates a key press and a release without repeat as other OneTouch buttons do.
+	 */
+
+	if (unlikely(q0a & XE3GC_VOLD_MASK)) {
+		dprintk("Fn-down arrow or Volume down pressed.\n");
+		omnibook_report_key(poll_input_dev, KEY_VOLUMEDOWN);
+	}
+	if (unlikely(q0a & XE3GC_VOLU_MASK)) {
+		dprintk("Fn-up arrow or Volume up pressed.\n");
+		omnibook_report_key(poll_input_dev, KEY_VOLUMEUP);
+	}
+	if (unlikely(q0a & XE3GC_MUTE_MASK)) {
+		dprintk("Fn+F7 - Volume mute pressed.\n");
+		omnibook_report_key(poll_input_dev, KEY_MUTE);
+	}
+
+	retval = queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
+	if(unlikely(!retval)) /* here non-zero on success */
+		printk(O_ERR "Key_poller failed to rearm.\n");
+}
+
+static int omnibook_key_polling_enable(void)
+{
+	int retval = 0;
+
+	if(mutex_lock_interruptible(&poll_mutex))
+		return -ERESTARTSYS;
+
+	if(key_polling_enabled)
+		goto out;
+
+	retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
+	if(retval)
+		printk(O_ERR "Key_poller enabling failed.\n");
+	else {	
+		dprintk("Scancode emulation for volume buttons enabled.\n");
+		key_polling_enabled = 1;
+	}
+
+	out:
+	mutex_unlock(&poll_mutex);
+	return retval;
+}
+	
+static int omnibook_key_polling_disable(void)
+{
+	if(mutex_lock_interruptible(&poll_mutex))
+		return -ERESTARTSYS;
+
+	if(!key_polling_enabled)
+		goto out;
+
+	cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work);
+	dprintk("Scancode emulation for volume buttons disabled.\n");
+	key_polling_enabled = 0;
+
+	out:
+	mutex_unlock(&poll_mutex);
+	return 0;
+}
+
+
+static int omnibook_key_polling_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	
+	if(mutex_lock_interruptible(&poll_mutex))
+		return -ERESTARTSYS;
+
+	len += sprintf(buffer + len, "Volume buttons polling is %s.\n",
+		(key_polling_enabled) ? "enabled" : "disabled");
+#ifdef CONFIG_OMNIBOOK_DEBUG
+	if(key_polling_enabled)	
+		len += sprintf(buffer + len, "Will poll in %i msec.\n",
+		jiffies_to_msecs(omnibook_poll_work.timer.expires - jiffies));
+#endif
+	mutex_unlock(&poll_mutex);
+	return len;
+}
+
+static int omnibook_key_polling_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+	switch (*buffer) {
+	case '0':
+		retval = omnibook_key_polling_disable();
+		break;
+	case '1':
+		retval = omnibook_key_polling_enable();
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+
+/*
+ * Stop polling upon suspend an restore it upon resume
+ */
+static int omnibook_key_polling_resume(struct omnibook_operation *io_op)
+{
+	int retval = 0;
+
+	mutex_lock(&poll_mutex);
+	if(key_polling_enabled)
+		retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL);
+	mutex_unlock(&poll_mutex);
+	return retval;	
+}
+
+static int omnibook_key_polling_suspend(struct omnibook_operation *io_op)
+{
+	mutex_lock(&poll_mutex);
+	if(key_polling_enabled)
+		cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work);
+	mutex_unlock(&poll_mutex);
+	return 0;
+}
+
+static int __init omnibook_key_polling_init(struct omnibook_operation *io_op)
+{
+	int retval = 0;	
+	
+	poll_input_dev = input_allocate_device();
+	if (!poll_input_dev) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	poll_input_dev->name = "Omnibook legacy laptop scancode generator";
+	poll_input_dev->phys = "omnibook/input0";
+	poll_input_dev->id.bustype = BUS_HOST;
+	
+	/* this device has three keys */
+	set_bit(EV_KEY, poll_input_dev->evbit);
+	set_bit(KEY_VOLUMEDOWN, poll_input_dev->keybit);
+	set_bit(KEY_VOLUMEUP, poll_input_dev->keybit);
+	set_bit(KEY_MUTE, poll_input_dev->keybit);
+
+	retval = input_register_device(poll_input_dev);
+	if (retval) {
+		input_free_device(poll_input_dev);
+		goto out;
+	}
+
+	omnibook_wq = create_singlethread_workqueue("omnibook");
+	if(!omnibook_wq)
+		retval = -ENOMEM;
+	else
+		retval = omnibook_key_polling_enable();
+
+out:
+	return retval;
+}
+
+static void __exit omnibook_key_polling_cleanup(struct omnibook_operation *io_op)
+{
+	omnibook_key_polling_disable();	
+	destroy_workqueue(omnibook_wq);
+	input_unregister_device(poll_input_dev);
+}
+
+static struct omnibook_tbl key_polling_table[] __initdata = {
+	{XE3GC, SIMPLE_BYTE(EC, XE3GC_Q0A, 0)},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature key_polling_driver = {
+	.name = "key_polling",
+	.enabled = 0, /* dangerous */
+	.read = omnibook_key_polling_read,
+	.write = omnibook_key_polling_write,
+	.init = omnibook_key_polling_init,
+	.exit = omnibook_key_polling_cleanup,
+	.suspend = omnibook_key_polling_suspend,
+	.resume = omnibook_key_polling_resume,
+	.ectypes = XE3GC,
+	.tbl = key_polling_table,
+};
+
+module_param_named(key_polling, key_polling_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(key_polling, "Use 0 to disable, 1 to enable key polling");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/muteled.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/muteled.c
@@ -0,0 +1,109 @@
+/*
+ * mutled.c -- MUTE LED control
+ * 
+ * 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, 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.
+ *
+ * Written by Thomas Perl <thp@perli.net>, 2006
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_muteled_set(struct omnibook_operation *io_op, int status)
+{
+	int retval = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	if((retval = __omnibook_toggle(io_op, !!status))) {
+		printk(O_ERR "Failed muteled %s command.\n", status ? "on" : "off");
+		goto out;
+	}
+
+	io_op->backend->muteled_state = !!status;
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Hardware query is unsupported, reading is unreliable.
+ */
+static int omnibook_muteled_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+	len +=
+	    sprintf(buffer + len, "Last mute LED action was an %s command.\n",
+		    io_op->backend->touchpad_state ? "on" : "off");
+
+	mutex_unlock(&io_op->backend->mutex);
+	return len;
+}
+
+static int omnibook_muteled_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int cmd;
+
+	if (*buffer == '0' || *buffer == '1') {
+		cmd = *buffer - '0';
+		if (!omnibook_muteled_set(io_op, cmd)) {
+			dprintk("Switching mute LED to %s state.\n", cmd ? "on" : "off");
+		}
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * May re-enable muteled upon resume
+ */
+static int omnibook_muteled_resume(struct omnibook_operation *io_op)
+{	
+	int retval;
+	mutex_lock(&io_op->backend->mutex);
+	retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Switch muteled off upon exit
+ */
+static void __exit omnibook_muteled_cleanup(struct omnibook_operation *io_op)
+{
+	omnibook_muteled_set(io_op, 0);
+}
+
+static struct omnibook_tbl muteled_table[] __initdata = {
+	{XE4500, COMMAND(KBC, OMNIBOOK_KBC_CMD_MUTELED_ON, OMNIBOOK_KBC_CMD_MUTELED_OFF)},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature muteled_driver = {
+	.name = "muteled",
+	.enabled = 1,
+	.read = omnibook_muteled_read,
+	.write = omnibook_muteled_write,
+	.exit = omnibook_muteled_cleanup,
+	.resume = omnibook_muteled_resume,
+	.ectypes = XE4500,
+	.tbl = muteled_table,
+};
+
+module_param_named(muteled, muteled_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(muteled, "Use 0 to disable, 1 to enable 'Audo Mute' LED control");
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/bluetooth.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/bluetooth.c
@@ -0,0 +1,104 @@
+/*
+ * wireless.c Bluetooth feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_bt_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int retval;
+	unsigned int state;
+
+	if ((retval = backend_aerial_get(io_op, &state)))
+		return retval;
+
+	len +=
+	    sprintf(buffer + len, "Bluetooth adapter is %s",
+		    (state & BT_EX) ? "present" : "absent");
+	if (state & BT_EX)
+		len += sprintf(buffer + len, " and %s", (state & BT_STA) ? "enabled" : "disabled");
+	len += sprintf(buffer + len, ".\n");
+	return len;
+
+}
+
+static int omnibook_bt_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	unsigned int state;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;	
+
+	if ((retval = __backend_aerial_get(io_op, &state)))
+		goto out;
+
+	if (*buffer == '0')
+		state &= ~BT_STA;
+	else if (*buffer == '1')
+		state |= BT_STA;
+	else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	retval = __backend_aerial_set(io_op, state);
+
+	out:		
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static struct omnibook_feature bt_driver;
+
+static int __init omnibook_bt_init(struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	unsigned int state;
+
+/*
+ *  Refuse enabling/disabling a non-existent device
+ */
+
+	if ((retval = backend_aerial_get(io_op, &state)))
+		return retval;
+
+	if (!(state & BT_EX))
+		bt_driver.write = NULL;
+
+	return retval;
+}
+
+static struct omnibook_tbl wireless_table[] __initdata = {
+	{TSM70 | TSA105 | TSX205, {ACPI,}},	/* stubs to select backend */
+	{TSM40, {SMI,}},			/* stubs to select backend */
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature bt_driver = {
+	.name = "bluetooth",
+	.enabled = 1,
+	.read = omnibook_bt_read,
+	.write = omnibook_bt_write,
+	.init = omnibook_bt_init,
+	.ectypes = TSM70 | TSM40 | TSA105 | TSX205,
+	.tbl = wireless_table,
+};
+
+module_param_named(bluetooth, bt_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(bluetooth, "Use 0 to disable, 1 to enable bluetooth adapter control");
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/touchpad.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/touchpad.c
@@ -0,0 +1,126 @@
+/*
+ * touchpad.c -- enable/disable touchpad
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_touchpad_set(struct omnibook_operation *io_op, int status)
+{
+	int retval = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	if ((retval = __omnibook_toggle(io_op, !!status))) {
+		printk(O_ERR "Failed touchpad %sable command.\n", status ? "en" : "dis");
+		goto out;
+	}
+
+	io_op->backend->touchpad_state = !!status;
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Power management handlers: redisable touchpad on resume (if necessary)
+ */
+static int omnibook_touchpad_resume(struct omnibook_operation *io_op)
+{
+	int retval;
+	mutex_lock(&io_op->backend->mutex);
+	retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Hardware query is unsupported, so reading is unreliable.
+ */
+static int omnibook_touchpad_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	len +=
+	    sprintf(buffer + len, "Last touchpad action was an %s command.\n",
+		    io_op->backend->touchpad_state ? "enable" : "disable");
+
+	mutex_unlock(&io_op->backend->mutex);
+	return len;
+}
+
+static int omnibook_touchpad_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int cmd;
+
+	if (*buffer == '0' || *buffer == '1') {
+		cmd = *buffer - '0';
+		if (!omnibook_touchpad_set(io_op, cmd)) {
+			dprintk("%sabling touchpad.\n", cmd ? "En" : "Dis");
+		}
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static int __init omnibook_touchpad_init(struct omnibook_operation *io_op)
+{
+	mutex_lock(&io_op->backend->mutex);
+	/* Touchpad is assumed to be enabled by default */
+	io_op->backend->touchpad_state = 1;
+	mutex_unlock(&io_op->backend->mutex);
+	return 0;
+}
+
+/*
+ * Reenable touchpad upon exit
+ */
+static void __exit omnibook_touchpad_cleanup(struct omnibook_operation *io_op)
+{
+	omnibook_touchpad_set(io_op, 1);
+	printk(O_INFO "Enabling touchpad.\n");
+}
+
+static struct omnibook_tbl touchpad_table[] __initdata = {
+	{XE3GF | XE3GC | TSP10,
+	 COMMAND(KBC, OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE, OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)},
+	{TSM70, {CDI, 0, TSM70_FN_INDEX, 0, TSM70_TOUCHPAD_ON, TSM70_TOUCHPAD_OFF}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature touchpad_driver = {
+	.name = "touchpad",
+	.enabled = 1,
+	.read = omnibook_touchpad_read,
+	.write = omnibook_touchpad_write,
+	.init = omnibook_touchpad_init,
+	.exit = omnibook_touchpad_cleanup,
+	.resume = omnibook_touchpad_resume,
+	.ectypes = XE3GF | XE3GC | TSP10 | TSM70,
+	.tbl = touchpad_table,
+};
+
+module_param_named(touchpad, touchpad_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(touchpad, "Use 0 to disable, 1 to enable touchpad handling");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/sections.lds
+++ linux-ec2-2.6.32/ubuntu/omnibook/sections.lds
@@ -0,0 +1,11 @@
+SECTIONS
+{
+  .data :
+    {
+      . = ALIGN(32);
+      _start_features_driver = .;
+      *(.features)
+      _end_features_driver = .;
+      *(.data)
+    } 
+}
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/laptop.h
+++ linux-ec2-2.6.32/ubuntu/omnibook/laptop.h
@@ -0,0 +1,1077 @@
+/*
+ * laptop.h -- Various structures about supported hardware
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+
+#define HP_SIGNATURE	"Hewlett-Packard"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+static int __init dmi_matched(struct dmi_system_id *dmi);
+#else
+static int __init dmi_matched(const struct dmi_system_id *dmi);
+#endif
+
+static struct  dmi_system_id omnibook_ids[] __initdata = {
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XE3 GF",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GF"),
+		},
+		.driver_data = (void *) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XT1000",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XT1000"),
+		},
+		.driver_data = (void *) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XE2 DC",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE2 DC"),
+		},
+		.driver_data = (void *) XE2
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XE3 GC",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GC"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XE3 GD / Pavilion N5430",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GD"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XE3 GE / Pavilion N5415",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GE"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 500 FA",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
+		},
+		.driver_data = (void*) OB500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 510 FB",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 510 FB"),
+		},
+		.driver_data = (void*) OB510
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 4150",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 4150"),
+		},
+		.driver_data = (void*) OB4150
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 900 B",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 900 B"),
+		},
+		.driver_data = (void*) OB4150
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 6000 EA",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6000 EA"),
+		},
+		.driver_data = (void*) OB6000
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 6100 EB",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6100 EB"),
+		},
+		.driver_data = (void*) OB6100
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook xe4000/xe4100",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4000"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook xe4400",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4400"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook xe4500",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4500"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook 6200 EG / vt6200 / xt 6200",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6200 EG"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	/* There are no model specific strings of some HP OmniBook XT1500 */
+	{
+		.callback = dmi_matched,
+		.ident = "HP OmniBook XT1500",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ze4000 / ze4125",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook ze4000"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	/* There are no model specific strings of some HP Pavilion xt155 and some HP Pavilion ze4100 
+	 * There are no model specific strings of some HP nx9000 */
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion xt155 / ze4100 / nx9000",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook PC"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ZU1000 FA / ZU1000 FA / ZU1175",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion ZU1000 FA"),
+		},
+		.driver_data = (void*) OB500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion Notebook XE3 GC / N5290",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook XE3 GC"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion Notebook GD / N5441",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GD"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion Notebook GE / XH545",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion Notebook ZT1000 / ZT1141",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	/* There are no model specific strings of some HP Pavilion ZT1175 and ZT1195 notebooks */
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ZT1175 / ZT1195",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ze4200 series",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4200"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ze4300 series",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4300"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ze4500 series",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4500"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Pavilion ze8500 series",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze8500"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	/* Compaq nx9000 */
+	{
+		.callback = dmi_matched,
+		.ident = "HP Compaq nx9000",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9000"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Compaq nx9005",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9005"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP Compaq nx9010",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9010"),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1000"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1005",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1005"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1110",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1110"),
+		},
+		.driver_data = (void*) XE3GF
+	},	
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1115",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1115"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1130",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1130"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1700-100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1700-100"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1700-200",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1700-200"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1700-300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1700-300"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1700-400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1700-400"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1700-500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1700-500"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1900"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1905",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1905"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1950",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1950"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1955",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S1955"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 2430",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S2430"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 2435",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S2435"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 3000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S3000"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 3005",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S3005"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1000"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1005",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1005"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1110",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1110"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1115",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1115"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1115",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Toshiba 1115"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1900",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1900"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1905",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1905"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1950",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1950"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 1955",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1955"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 2430",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2430"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 2435",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2435"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 3000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3000"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite 3005",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3005"),
+		},
+		.driver_data = (void*) XE3GF,
+	},
+	{
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A70",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A70"),
+                },
+                .driver_data = (void*) TSM70
+        },
+	{
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A75",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A75"),
+                },
+                .driver_data = (void*) TSM70
+        },
+	{
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A80",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A80"),
+                },
+                .driver_data = (void*) TSM70
+        },
+        {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite A105",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A105"),
+                },
+                .driver_data = (void*) TSA105
+        },
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite A100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"),
+		},
+		.driver_data = (void*) TSA105
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite P100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"),
+		},
+		.driver_data = (void*) TSA105
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite P10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+		},
+		.driver_data = (void*) TSP10
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite P15",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P15"),
+		},
+		.driver_data = (void*) TSP10
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite P20",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P20"),
+		},
+		.driver_data = (void*) TSP10
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite P25",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P25"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M30X",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M30X"),
+		},
+		.driver_data = (void*) TSM30X
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M35X",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M35X"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M50",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M50"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M60",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M60"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M70",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M70"),
+		},
+		.driver_data = (void*) TSM70
+	},
+        {
+                .callback = dmi_matched,
+                .ident = "Toshiba Satellite M100",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE M100"),
+                },
+                .driver_data = (void*) TSM70
+        },
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M100"),
+		},
+		.driver_data = (void*) TSM70
+	},
+		{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M115",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M115"),
+		},
+		.driver_data = (void*) TSA105
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M40X",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40X"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M40",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40"),
+		},
+		.driver_data = (void*) TSM40
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite M45",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M45"),
+		},
+		.driver_data = (void*) TSM40
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Satellite X205-S9800",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite X205"),
+		},
+		.driver_data = (void*) TSX205
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Tecra S1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA S1"),
+		},
+		.driver_data = (void*) TSM40
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Tecra S1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S1"),
+		},
+		.driver_data = (void*) TSM40
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Tecra S2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S2"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Tecra A4",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Tecra A4"),
+		},
+		.driver_data = (void*) TSM40
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Toshiba Tecra A6",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A6"),
+		},
+		.driver_data = (void*) TSM70
+	},
+	{
+                .callback = dmi_matched,
+                .ident = "Toshiba Equium A110",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                        DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
+                },
+                .driver_data = (void*) TSM30X /* FIXME: provisional */
+        },
+	{
+		.callback = dmi_matched,
+		.ident = "Compal ACL00",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+			DMI_MATCH(DMI_BOARD_NAME, "ACL00"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Compal ACL10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+			DMI_MATCH(DMI_BOARD_NAME, "ACL10"),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Fujitsu-Siemens Amilo D series",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D-Series"),
+		},
+		.driver_data = (void*) AMILOD
+	},
+/* HP Technology code Matching:
+ * Technology code appears in the first two chracters of BIOS version string
+ * ended by a dot, but it prefixed a space character on some models and BIOS
+ * versions.
+ * New HP/Compaq models use more characters (eg. KF_KH.).
+ */
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code CI",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "CI."),
+		},
+		.driver_data = (void*) OB4150
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code CL",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "CL."),
+		},
+		.driver_data = (void*) OB4150
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code DC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "DC."),
+		},
+		.driver_data = (void*) XE2
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code EA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "EA."),
+		},
+		.driver_data = (void*) OB6000
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code EB",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "EB."),
+		},
+		.driver_data = (void*) OB6100
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code EG",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "EG."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code FA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "FA."),
+		},
+		.driver_data = (void*) OB500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code FB",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "FB."),
+		},
+		.driver_data = (void*) OB510
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code GC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "GC."),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code GD",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "GD."),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code GE",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "GE."),
+		},
+		.driver_data = (void*) XE3GC
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code GF",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "GF."),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code IB",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "IB."),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code IC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "IC."),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code ID",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "ID."),
+		},
+		.driver_data = (void*) XE3GF
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KA."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KB",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KB."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KC."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KD",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KD."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KE",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KE."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KE_KG",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KE_KG."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "HP model with technology code KF_KH",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE),
+			DMI_MATCH(DMI_BIOS_VERSION, "KF_KH."),
+		},
+		.driver_data = (void*) XE4500
+	},
+	{ NULL, }
+};
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/lcd.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/lcd.c
@@ -0,0 +1,207 @@
+/*
+ * lcd.c -- LCD brightness and on/off
+ * 
+ * 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, 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.
+ *
+ * Written by Maciek Górniak <mago@acn.waw.pl>, 2002
+ * Modified by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include <linux/err.h>
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+#include <linux/backlight.h>
+#endif
+
+#include "hardware.h"
+
+unsigned int omnibook_max_brightness;
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+static struct backlight_device *omnibook_backlight_device;
+
+static int omnibook_get_backlight(struct backlight_device *bd);
+static int omnibook_set_backlight(struct backlight_device *bd);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+static struct backlight_ops omnibookbl_ops = {
+#else /* 2.6.21 */
+static struct backlight_properties omnibookbl_data = {
+	.owner = THIS_MODULE,
+#endif /* 2.6.21 */
+	.get_brightness = omnibook_get_backlight,
+	.update_status = omnibook_set_backlight,
+};
+
+static int omnibook_get_backlight(struct backlight_device *bd)
+{
+	int retval = 0;
+	struct omnibook_operation *io_op;
+	u8 brgt;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+	io_op = bl_get_data(bd);
+#else /* 2.6.23 */	
+	io_op = class_get_devdata(&bd->class_dev);
+#endif /* 2.6.23 */
+	retval = backend_byte_read(io_op, &brgt);
+	if (!retval)
+		retval = brgt;
+
+	return retval;
+}
+
+static int omnibook_set_backlight(struct backlight_device *bd)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+	u8 intensity = bd->props.brightness;
+#else /* 2.6.21 */
+	u8 intensity = bd->props->brightness;
+#endif /* 2.6.21 */	
+	struct omnibook_operation *io_op;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+	io_op = bl_get_data(bd);
+#else /* 2.6.23 */	
+	io_op = class_get_devdata(&bd->class_dev);
+#endif /* 2.6.23 */
+	return backend_byte_write(io_op, intensity);
+}
+#endif /* CONFIG_OMNIBOOK_BACKLIGHT */
+
+static int omnibook_brightness_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	u8 brgt;
+
+	backend_byte_read(io_op, &brgt);
+
+	len +=
+	    sprintf(buffer + len, "LCD brightness: %2d (max value: %d)\n", brgt,
+		    omnibook_max_brightness);
+
+	return len;
+}
+
+static int omnibook_brightness_write(char *buffer, struct omnibook_operation *io_op)
+{
+	unsigned int brgt = 0;
+	char *endp;
+
+	if (strncmp(buffer, "off", 3) == 0)
+		omnibook_lcd_blank(1);
+	else if (strncmp(buffer, "on", 2) == 0)
+		omnibook_lcd_blank(0);
+	else {
+		brgt = simple_strtoul(buffer, &endp, 10);
+		if ((endp == buffer) || (brgt > omnibook_max_brightness))
+			return -EINVAL;
+		else {
+			backend_byte_write(io_op, brgt);
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+			omnibook_backlight_device->props.brightness = brgt;
+#else /* 2.6.21 */
+			omnibookbl_data.brightness = brgt;
+#endif
+#endif	
+		}
+	}
+	return 0;
+}
+
+static int __init omnibook_brightness_init(struct omnibook_operation *io_op)
+{
+	/*
+	 * FIXME: What is exactly the max value for each model ?
+	 * I know that it's 7 for the TSM30X, TSM70, TSM40 and TSA105
+	 * and previous versions of this driver (wrongly) assumed it was 10 for
+	 * all models.
+	 * 
+	 * XE3GF
+	 * TSM30X
+	 * TSM70
+	 * TSM40
+	 * TSA105
+	 * TSX205
+	 */
+	if (omnibook_ectype & (XE3GF | TSM70 | TSM30X | TSM40 | TSA105 | TSX205))
+		omnibook_max_brightness = 7;
+	else {
+		omnibook_max_brightness = 10;
+		printk(O_WARN "Assuming that LCD brightness is between 0 and %i,\n",
+		       omnibook_max_brightness);
+		printk(O_WARN
+		       "please contact http://sourceforge.net/projects/omnibook to confirm.\n");
+	}
+
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+	
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+	omnibook_backlight_device =
+	    backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_ops);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	omnibook_backlight_device =
+	    backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_data);
+#else /*  < 2.6.20 */
+	omnibook_backlight_device =
+	    backlight_device_register(OMNIBOOK_MODULE_NAME, (void *)io_op, &omnibookbl_data);
+#endif
+	if (IS_ERR(omnibook_backlight_device)) {
+		printk(O_ERR "Unable to register as backlight device.\n");
+		return -ENODEV;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+	omnibook_backlight_device->props.max_brightness = omnibook_max_brightness;
+	backend_byte_read(io_op, (u8*) &omnibook_backlight_device->props.brightness);
+#else /* < 2.6.21 */
+	omnibookbl_data.max_brightness = omnibook_max_brightness;
+	backend_byte_read(io_op, (u8*) &omnibookbl_data.brightness);
+#endif
+ 
+#endif /* CONFIG_OMNIBOOK_BACKLIGHT */
+	return 0;
+}
+static void __exit omnibook_brightness_cleanup(struct omnibook_operation *io_op)
+{
+#ifdef CONFIG_OMNIBOOK_BACKLIGHT
+	backlight_device_unregister(omnibook_backlight_device);
+#endif
+}
+
+static struct omnibook_tbl lcd_table[] __initdata = {
+	{TSM70 | TSX205, {CDI, TSM70_LCD_READ, TSM70_LCD_WRITE, 0, 0, 0}},
+	{TSM40, {SMI, SMI_GET_LCD_BRIGHTNESS, SMI_SET_LCD_BRIGHTNESS, 0, 0, 0}},
+	{XE3GF | TSP10 | TSM70 | TSM30X, SIMPLE_BYTE(EC, XE3GF_BRTS, XE3GF_BRTS_MASK)},
+	{XE3GC, SIMPLE_BYTE(EC, XE3GC_BTVL, XE3GC_BTVL_MASK)},
+	{AMILOD, SIMPLE_BYTE(EC, AMILOD_CBRG, XE3GC_BTVL_MASK)},
+	{TSA105, SIMPLE_BYTE(EC, A105_BNDT, A105_BNDT_MASK)},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature lcd_driver = {
+	.name = "lcd",
+	.enabled = 1,
+	.read = omnibook_brightness_read,
+	.write = omnibook_brightness_write,
+	.init = omnibook_brightness_init,
+	.exit = omnibook_brightness_cleanup,
+	.ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X | TSM40 | TSA105 | TSX205,
+	.tbl = lcd_table,
+};
+
+module_param_named(lcd, lcd_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(lcd, "Use 0 to disable, 1 to enable to LCD brightness support");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/wireless.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/wireless.c
@@ -0,0 +1,108 @@
+/*
+ * wireless.c Wifi feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_wifi_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int retval;
+	unsigned int state;
+
+	if ((retval = backend_aerial_get(io_op, &state)))
+		return retval;
+
+	len +=
+	    sprintf(buffer + len, "Wifi adapter is %s", (state & WIFI_EX) ? "present" : "absent");
+	if (state & WIFI_EX)
+		len +=
+		    sprintf(buffer + len, " and %s", (state & WIFI_STA) ? "enabled" : "disabled");
+	len += sprintf(buffer + len, ".\n");
+	len +=
+	    sprintf(buffer + len, "Wifi Kill switch is %s.\n", (state & KILLSWITCH) ? "on" : "off");
+
+	return len;
+
+}
+
+static int omnibook_wifi_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	unsigned int state;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;	
+
+	if ((retval = __backend_aerial_get(io_op, &state)))
+		goto out;
+
+	if (*buffer == '0')
+		state &= ~WIFI_STA;
+	else if (*buffer == '1')
+		state |= WIFI_STA;
+	else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	if ((retval = __backend_aerial_set(io_op, state)))
+		return retval;
+
+	out:		
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static struct omnibook_feature wifi_driver;
+
+static int __init omnibook_wifi_init(struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	unsigned int state;
+
+/*
+ *  Refuse enabling/disabling a non-existent device
+ */
+
+	if ((retval = backend_aerial_get(io_op, &state)))
+		return retval;
+
+	if (!(state & WIFI_EX))
+		wifi_driver.write = NULL;
+
+	return retval;
+}
+
+static struct omnibook_tbl wireless_table[] __initdata = {
+	{TSM70 | TSX205, {ACPI,}},	/* stubs to select backend */
+	{TSM40, {SMI,}},		/* stubs to select backend */
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature wifi_driver = {
+	.name = "wifi",
+	.enabled = 1,
+	.read = omnibook_wifi_read,
+	.write = omnibook_wifi_write,
+	.init = omnibook_wifi_init,
+	.ectypes = TSM70 | TSM40 | TSX205,
+	.tbl = wireless_table,
+};
+
+module_param_named(wifi, wifi_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(wifi, "Use 0 to disable, 1 to enable Wifi adapter control");
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/fan.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/fan.c
@@ -0,0 +1,183 @@
+/*
+ * fan.c -- fan status/control
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/delay.h>
+#include <asm/io.h>
+#include "hardware.h"
+
+static const struct omnibook_operation ctmp_io_op = { EC, XE3GF_CTMP, 0, 0, 0, 0 };
+static const struct omnibook_operation fot_io_op = { EC, XE3GF_FOT, XE3GF_FOT, 0, 0, 0 };
+
+static int omnibook_get_fan(struct omnibook_operation *io_op)
+{
+	u8 fan;
+	int retval;
+
+	if ((retval = backend_byte_read(io_op, &fan)))
+		return retval;
+
+	/*
+	 * For most models the reading is a bool
+	 * It as to be inverted on all but OB6000|OB6100|OB4150|AMILOD
+	 * TSP10|XE3GF|TSX205 return an integer
+	 */
+
+	if (omnibook_ectype & (TSP10 | XE3GF | TSX205))
+		retval = fan;
+	else if (omnibook_ectype & (OB6000 | OB6100 | OB4150 | AMILOD))
+		retval = !!fan;
+	else
+		retval = !fan;
+
+	return retval;
+}
+
+static int omnibook_fan_on(struct omnibook_operation *io_op)
+{
+	return omnibook_apply_write_mask(io_op, 1);
+}
+
+static int omnibook_fan_off(struct omnibook_operation *io_op)
+{
+	int i, retval = 0;
+
+	if (!(omnibook_ectype & (XE3GF | TSP10 | TSX205))) {
+		retval = omnibook_apply_write_mask(io_op, 0);
+		return retval;
+	} else {
+	/*
+ 	 * Special handling for XE3GF & TSP10
+	 */
+		u8 fot, temp, fan;
+
+		if(mutex_lock_interruptible(&io_op->backend->mutex))
+			return -ERESTARTSYS;	
+
+		retval = __backend_byte_read(io_op, &fan);
+
+		/* error or fan is already off */
+		if (retval || !fan)
+			goto out;
+
+		/* now we set FOT to current temp, then reset to initial value */
+		if ((retval = __backend_byte_read(&fot_io_op, &fot)))
+			goto out;
+		if ((retval = __backend_byte_read(&ctmp_io_op, &temp)))
+			goto out;
+
+		/* Wait for no longer than 250ms (this is arbitrary). */
+		for (i = 0; i < 250; i++) {
+			__backend_byte_write(&fot_io_op, temp);
+			mdelay(1);
+			__backend_byte_read(io_op, &fan);
+			if (!fan) /* Fan is off */
+				break;
+		}
+		__backend_byte_write(&fot_io_op, fot);
+
+		if(i == 250 ) {
+			printk(O_ERR "Attempt to switch off the fan failed.\n");
+			retval = -EIO;
+		}
+
+		out:		
+		mutex_unlock(&io_op->backend->mutex);
+	}
+		
+
+	return retval;
+}
+
+static int omnibook_fan_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int fan;
+	int len = 0;
+	char *str;
+
+	fan = omnibook_get_fan(io_op);
+	if (fan < 0)
+		return fan;
+	str = (fan) ? "on" : "off";
+
+	if (fan > 1)
+		len += sprintf(buffer + len, "Fan is %s (level %d)\n", str, fan);
+	else
+		len += sprintf(buffer + len, "Fan is %s\n", str);
+
+	return len;
+}
+
+static int omnibook_fan_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+
+	switch (*buffer) {
+	case '0':
+		retval = omnibook_fan_off(io_op);
+		break;
+	case '1':
+		retval = omnibook_fan_on(io_op);
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static struct omnibook_feature fan_driver;
+
+static int __init omnibook_fan_init(struct omnibook_operation *io_op)
+{
+	/*
+	 * OB4150
+	 * XE2
+	 * AMILOD
+	 * They only support fan reading 
+	 */
+	if (omnibook_ectype & (OB4150 | XE2 | AMILOD))
+		fan_driver.write = NULL;
+	return 0;
+}
+
+static struct omnibook_tbl fan_table[] __initdata = {
+	{XE3GF | TSP10 | TSM70 | TSX205, {EC, XE3GF_FSRD, XE3GF_FSRD, 0, XE3GF_FAN_ON_MASK, 0}},
+	{OB500,
+	 {PIO, OB500_GPO1, OB500_GPO1, OB500_FAN_OFF_MASK, -OB500_FAN_ON_MASK, OB500_FAN_OFF_MASK}},
+	{OB510,
+	 {PIO, OB510_GPIO, OB510_GPIO, OB510_FAN_OFF_MASK, -OB510_FAN_ON_MASK, OB510_FAN_OFF_MASK}},
+	{OB6000 | OB6100,
+	 {EC, OB6000_STA1, OB6000_STA1, OB6000_FAN_MASK, OB6000_FAN_MASK, -OB6000_FAN_MASK}},
+	{OB4150 | AMILOD, {EC, OB4150_STA1, 0, OB4150_FAN_MASK, 0, 0}},
+	{XE2, {PIO, OB500_GPO1, 0, XE2_FAN_MASK, 0, 0}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature fan_driver = {
+	.name = "fan",
+	.enabled = 1,
+	.read = omnibook_fan_read,
+	.write = omnibook_fan_write,
+	.init = omnibook_fan_init,
+	.ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | XE2 | AMILOD | TSP10 | TSX205,
+	.tbl = fan_table,
+};
+
+module_param_named(fan, fan_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(fan, "Use 0 to disable, 1 to enable fan status monitor and control");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/Makefile
+++ linux-ec2-2.6.32/ubuntu/omnibook/Makefile
@@ -0,0 +1,171 @@
+#
+# Makefile -- makefile for the HP OmniBook support module
+#
+# 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, 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.
+#
+# Written by Soós Péter <sp@osb.hu>, 2002-2004
+# Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
+#
+
+#Module informations
+
+MODULE_NAME = omnibook
+MODULE_VERSION = 2.20090707
+MODULE_BRANCH = trunk
+
+# Out-of-tree configuration
+ifndef CONFIG_OMNIBOOK
+OMNIBOOK_STANDALONE=y
+CONFIG_OMNIBOOK=m
+
+#Uncomment and set to force debug behavior
+#NOTE:	Default (commented) behavior is to enable debug in trunk or branch svn 
+#	snapshot and to disable it for release
+#OMNIBOOK_WANT_DEBUG=n
+
+#comment to disable backlight device support
+OMNIBOOK_WANT_BACKLIGHT=y
+
+#Uncomment to force legacy (pre-ACPI system) features support
+#OMNIBOOK_WANT_LEGACY=y
+
+endif
+
+ifeq ($(KERNELRELEASE),)
+# Support for direct Makefile invocation
+
+DESTDIR	= 
+MODDIR	= $(DESTDIR)/lib/modules
+KVERS	= $(shell uname -r)
+KVER	= $(KVERS)
+VMODDIR = $(MODDIR)/$(KVER)
+INSTDIR	= extra
+#KSRC	= /usr/src/linux
+KSRC	= $(VMODDIR)/build
+KMODDIR	= $(KSRC)/drivers/misc/omnibook
+KDOCDIR	= $(KSRC)/Documentation/omnibook
+PWD	= $(shell pwd)
+TODAY	= $(shell date +%Y%m%d)
+DEPMOD	= /sbin/depmod -aq
+RMMOD	= /sbin/modprobe -r
+INSMOD	= /sbin/modprobe
+INSTALL	= install -m 644
+MKDIR	= mkdir -p
+RM	= rm -f
+FIND	= find
+
+all:		 $(MODULE_NAME).ko
+
+clean:
+		make -C $(KSRC) M=$(PWD) clean
+		$(RM) -r *~ "#*#" .swp
+		$(RM) -r debian/omnibook-source *-stamp
+		$(RM) -r Module.symvers Modules.symvers
+
+install:	all
+		# Removing module from locations used by previous versions
+		$(RM) $(VMODDIR)/kernel/drivers/char/$(MODULE_NAME).ko
+		$(RM) $(VMODDIR)/kernel/drivers/misc/$(MODULE_NAME).ko
+		make INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=$(INSTDIR) -C $(KSRC) M=$(PWD) modules_install
+
+unload:
+		$(RMMOD) $(MODULE_NAME) || :
+
+load:		install unload
+		$(DEPMOD)
+		$(INSMOD) $(MODULE_NAME)
+
+uninstall:	unload
+		$(FIND) $(VMODDIR) -name "$(MODULE_NAME).ko" -exec $(RM) {} \;
+		$(DEPMOD)
+
+$(MODULE_NAME).ko:
+		$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
+
+kinstall:
+		$(RM) -r $(KMODDIR)
+		$(MKDIR) $(KMODDIR)
+		$(INSTALL) *.h *.c sections.lds $(KMODDIR)
+		$(MKDIR) $(KDOCDIR)
+		$(INSTALL) doc/README $(KDOCDIR)
+		
+kpatch:		kinstall
+		(cd $(KSRC); patch -p1 < $(PWD)/misc/omnibook-integration.patch)
+
+version:	
+		sed -i "s|^\(MODULE_VERSION = \).*|\1 2.$(TODAY)|" Makefile
+		sed -i "s|^\(MODULE_BRANCH = \).*|\1 release|" Makefile
+		sed -i "s|^\(2\.\)X\{8\}|\1$(TODAY)|" doc/ChangeLog
+		
+
+release:	clean version
+		mkdir -p ../$(MODULE_NAME)-2.$(TODAY)
+		cp -a *.h *.c *.lds Makefile doc misc ../$(MODULE_NAME)-2.$(TODAY)
+		rm -f ../$(MODULE_NAME)-2.$(TODAY).tar ../$(MODULE_NAME)-2.$(TODAY).tar.gz
+		(cd ..; tar cvf $(MODULE_NAME)-2.$(TODAY).tar $(MODULE_NAME)-2.$(TODAY); gzip -9 $(MODULE_NAME)-2.$(TODAY).tar)
+
+else
+# Support for kernel build system invocation
+
+ifneq ($(MODULE_BRANCH), release)
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)-$(MODULE_BRANCH)"'
+else
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)"'
+endif
+
+ifeq ($(OMNIBOOK_STANDALONE),y)
+
+ifeq ($(OMNIBOOK_WANT_BACKLIGHT),y)
+ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+# we support backlight interface only after 2.6.16
+ifeq ($(shell if [ $(SUBLEVEL) -gt 16 ] ; then echo -n 'y'; fi),y)
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_BACKLIGHT
+else
+$(warning "Backlight support in only supported for kernel version newer than 2.6.16")
+$(warning "Disabling backlight sysfs interface")
+endif
+endif
+endif
+
+ifeq ($(OMNIBOOK_WANT_LEGACY),y)
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY
+endif
+
+ifndef CONFIG_ACPI_EC
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY
+endif
+
+ifneq ($(MODULE_BRANCH), release)
+ifneq ($(OMNIBOOK_WANT_DEBUG),n)	
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0
+endif
+else
+ifeq ($(OMNIBOOK_WANT_DEBUG),y)	
+EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0
+endif
+
+endif
+
+endif
+
+EXTRA_CFLAGS += -DOMNIBOOK_MODULE_NAME='"$(MODULE_NAME)"'
+#EXTRA_LDFLAGS +=  $(src)/sections.lds
+EXTRA_LDFLAGS += $(PWD)/ubuntu/omnibook/sections.lds
+
+obj-$(CONFIG_OMNIBOOK) += $(MODULE_NAME).o
+omnibook-objs := init.o lib.o ec.o kbc.o pio.o compal.o acpi.o nbsmi.o \
+          ac.o battery.o blank.o bluetooth.o cooling.o display.o dock.o \
+	  dump.o fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o \
+	  polling.o temperature.o touchpad.o wireless.o throttling.o 
+
+endif # End of kernel build system part
+
+# End of file
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/temperature.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/temperature.c
@@ -0,0 +1,55 @@
+/*
+ * temperature.c -- CPU temprature monitoring
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_temperature_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int retval;
+	u8 temp;
+
+	if ((retval = backend_byte_read(io_op, &temp)))
+		return retval;
+
+	len += sprintf(buffer + len, "CPU temperature:            %2d C\n", temp);
+
+	return len;
+}
+
+static struct omnibook_tbl temp_table[] __initdata = {
+	{XE3GF | TSP10 | TSM70 | TSM30X | TSX205, SIMPLE_BYTE(EC, XE3GF_CTMP, 0)},
+	{XE3GC | AMILOD, SIMPLE_BYTE(EC, XE3GC_CTMP, 0)},
+	{OB500 | OB510 | OB6000 | OB6100 | XE4500 | XE2, SIMPLE_BYTE(EC, OB500_CTMP, 0)},
+	{OB4150, SIMPLE_BYTE(EC, OB4150_TMP, 0)},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature temperature_driver = {
+	.name = "temperature",
+	.enabled = 1,
+	.read = omnibook_temperature_read,
+	.ectypes =
+	    XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | XE2 | AMILOD | TSP10
+	    | TSM70 | TSM30X | TSX205,
+	.tbl = temp_table,
+};
+
+module_param_named(temperature, temperature_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(temperature, "Use 0 to disable, 1 to enable thermal status and policy support");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/omnibook.h
+++ linux-ec2-2.6.32/ubuntu/omnibook/omnibook.h
@@ -0,0 +1,145 @@
+/*
+ * omnibook.h -- High level data structures and functions of omnibook
+ *               support code
+ *
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/version.h>
+
+/*
+ * EC types
+ */
+
+extern enum omnibook_ectype_t {
+	NONE   = 0,	  /* 0  Default/unknown EC type */ 
+	XE3GF  = (1<<0),  /* 1  HP OmniBook XE3 GF, most old Toshiba Satellites */
+	XE3GC  = (1<<1),  /* 2  HP OmniBook XE3 GC, GD, GE and compatible */
+	OB500  = (1<<2),  /* 3  HP OmniBook 500 and compatible */
+	OB510  = (1<<3),  /* 4  HP OmniBook 510 */
+	OB6000 = (1<<4),  /* 5  HP OmniBook 6000 */
+	OB6100 = (1<<5),  /* 6  HP OmniBook 6100 */
+	XE4500 = (1<<6),  /* 7  HP OmniBook xe4500 and compatible */
+	OB4150 = (1<<7),  /* 8  HP OmniBook 4150 */
+	XE2    = (1<<8),  /* 9  HP OmniBook XE2 */
+	AMILOD = (1<<9),  /* 10 Fujitsu Amilo D */
+	TSP10  = (1<<10), /* 11 Toshiba Satellite P10, P15, P20 and compatible */
+	TSM70  = (1<<11), /* 12 Toshiba Satellite M40X, M70 and compatible */
+	TSM40  = (1<<12), /* 13 Toshiba Satellite M40, M45 and Tecra S1 */
+	TSA105 = (1<<13), /* 14 Toshiba Satellite A105 and compatible (Real support is MISSING) */
+	TSM30X = (1<<14), /* 15 Toshiba Stallite M30X and compatible */
+	TSX205 = (1<<15)  /* 16 Toshiba Stallite X205 and compatible */
+} omnibook_ectype;
+
+#define ALL_ECTYPES XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM70|TSM40|TSA105|TSM30X|TSX205
+
+/*
+ * This represent a feature provided by this module
+ */
+
+struct omnibook_operation;
+
+struct omnibook_feature {
+	char *name;						/* Name */
+	int enabled;						/* Set from module parameter */
+	int (*read) (char *,struct omnibook_operation *);	/* Procfile read function */
+	int (*write) (char *,struct omnibook_operation *);	/* Procfile write function */
+	int (*init) (struct omnibook_operation *);		/* Specific Initialization function */
+	void (*exit) (struct omnibook_operation *);		/* Specific Cleanup function */
+	int (*suspend) (struct omnibook_operation *);		/* PM Suspend function */
+	int (*resume) (struct omnibook_operation *);		/* PM Resume function */
+	int ectypes;						/* Type(s) of EC we support for this feature (bitmask) */
+	struct omnibook_tbl *tbl;
+	struct omnibook_operation *io_op;
+	struct list_head list;
+};
+
+/*
+ * State of a Wifi/Bluetooth adapter
+ */
+enum {
+	WIFI_EX = (1<<0),	/* 1 1=present 0=absent */
+	WIFI_STA = (1<<1),	/* 2 1=enabled 0=disabled */
+	KILLSWITCH = (1<<2),	/* 4 1=radio on 0=radio off */
+	BT_EX = (1<<3),		/* 8 1=present 0=absent */
+	BT_STA = (1<<4),	/* 16 1=enabled 0=disabled */
+};
+
+/*
+ * Hotkeys state backend neutral masks
+ */
+enum {
+	HKEY_ONETOUCH = (1<<0),		/* 1   Ontetouch button scancode generation */
+	HKEY_MULTIMEDIA = (1<<1),	/* 2   "Multimedia hotkeys" scancode generation */	
+	HKEY_FN = (1<<2),		/* 4   Fn + foo hotkeys scancode generation */
+	HKEY_STICK = (1<<3),		/* 8   Stick key (Fn locked/unlocked on keypress)  */
+	HKEY_TWICE_LOCK = (1<<4),	/* 16  Press Fn twice to lock */
+	HKEY_DOCK = (1<<5),		/* 32  (Un)Dock events scancode generation */
+	HKEY_FNF5 = (1<<6),		/* 64  Fn + F5 (toggle display) is enabled */
+};
+
+#define HKEY_LAST_SHIFT 6
+
+/*
+ * Display state backend neutral masks
+ * _ON masks = port is powered up and running
+ * _DET masks = a plugged display have been detected 
+ */
+
+enum {	
+	DISPLAY_LCD_ON = (1<<0),	/* 1 Internal LCD panel */
+	DISPLAY_CRT_ON = (1<<1),	/* 2 External VGA port */
+	DISPLAY_TVO_ON = (1<<2),	/* 4 External TV-OUT port */
+	DISPLAY_DVI_ON = (1<<3),	/* 8 External DVI port */
+	DISPLAY_LCD_DET = (1<<4),	/* 16 Internal LCD panel */
+	DISPLAY_CRT_DET = (1<<5),	/* 32 External VGA port */
+	DISPLAY_TVO_DET = (1<<6),	/* 64 External TV-OUT port */
+	DISPLAY_DVI_DET = (1<<7),	/* 128 External DVI port */
+};
+
+extern unsigned int omnibook_max_brightness;
+int set_omnibook_param(const char *val, struct kernel_param *kp);
+int omnibook_lcd_blank(int blank);
+struct omnibook_feature *omnibook_find_feature(char *name);
+void omnibook_report_key(struct input_dev *dev, unsigned int keycode);
+
+/* 
+ * __attribute_used__ is not defined anymore in 2.6.24
+ * but __used appeared only in 2.6.22
+ */
+#ifndef __used
+#define __used	__attribute_used__
+#endif
+
+#define __declared_feature __attribute__ (( __section__(".features"),  __aligned__(__alignof__ (struct omnibook_feature)))) __used
+
+/*
+ * yet another printk wrapper
+ */
+#define O_INFO	KERN_INFO OMNIBOOK_MODULE_NAME ": "
+#define O_WARN	KERN_WARNING OMNIBOOK_MODULE_NAME ": "
+#define O_ERR	KERN_ERR OMNIBOOK_MODULE_NAME ": "
+
+#ifdef CONFIG_OMNIBOOK_DEBUG
+#define dprintk(fmt, args...) printk(KERN_INFO "%s: " fmt, OMNIBOOK_MODULE_NAME, ## args)
+#define dprintk_simple(fmt, args...) printk(fmt, ## args)
+#else
+#define dprintk(fmt, args...)	do { } while(0)
+#define dprintk_simple(fmt, args...) do { } while(0)
+#endif
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/kbc.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/kbc.c
@@ -0,0 +1,152 @@
+/*
+ * kbc.c -- low level functions to access Keyboard Controller
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+extern int omnibook_key_polling_enable(void);
+extern int omnibook_key_polling_disable(void);
+
+/*
+ * Registers of the keyboard controller
+ */
+
+#define OMNIBOOK_KBC_DATA		0x60
+#define OMNIBOOK_KBC_SC			0x64
+
+/*
+ * Keyboard controller status register bits
+ */
+
+#define OMNIBOOK_KBC_STAT_OBF		0x01	/* Output buffer full */
+#define OMNIBOOK_KBC_STAT_IBF		0x02	/* Input buffer full */
+
+
+/*
+ * Interrupt control
+ */
+
+static DEFINE_SPINLOCK(omnibook_kbc_lock);
+
+/*
+ * Wait for keyboard buffer
+ */
+
+static int omnibook_kbc_wait(u8 event)
+{
+	int timeout = OMNIBOOK_TIMEOUT;
+
+	switch (event) {
+	case OMNIBOOK_KBC_STAT_OBF:
+		while (!(inb(OMNIBOOK_KBC_SC) & event) && timeout--)
+			mdelay(1);
+		break;
+	case OMNIBOOK_KBC_STAT_IBF:
+		while ((inb(OMNIBOOK_KBC_SC) & event) && timeout--)
+			mdelay(1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (timeout > 0)
+		return 0;
+	return -ETIME;
+}
+
+/*
+ * Write to the keyboard command register
+ */
+
+static int omnibook_kbc_write_command(u8 cmd)
+{
+	int retval;
+
+	spin_lock_irq(&omnibook_kbc_lock);
+	retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb(cmd, OMNIBOOK_KBC_SC);
+	retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+      end:
+	spin_unlock_irq(&omnibook_kbc_lock);
+	return retval;
+}
+
+/*
+ * Write to the keyboard data register
+ */
+
+static int omnibook_kbc_write_data(u8 data)
+{
+	int retval;
+
+	spin_lock_irq(&omnibook_kbc_lock);
+	retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb(data, OMNIBOOK_KBC_DATA);
+	retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
+      end:
+	spin_unlock_irq(&omnibook_kbc_lock);
+	return retval;
+}
+
+/*
+ * Send a command to keyboard controller
+ */
+
+static int omnibook_kbc_command(const struct omnibook_operation *io_op, u8 data)
+{
+	int retval;
+
+	if ((retval = omnibook_kbc_write_command(OMNIBOOK_KBC_CONTROL_CMD)))
+		return retval;
+
+	retval = omnibook_kbc_write_data(data);
+	return retval;
+}
+
+/*
+ * Onetouch button hotkey handler
+ */
+static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval;
+
+	retval = __omnibook_toggle(io_op, !!(state & HKEY_ONETOUCH));
+	return retval;
+}
+
+/*
+ * Backend interface declarations
+ */
+struct omnibook_backend kbc_backend = {
+	.name = "i8042",
+	.hotkeys_write_cap = HKEY_ONETOUCH,
+	.byte_write = omnibook_kbc_command,
+	.hotkeys_set = omnibook_kbc_hotkeys,
+};
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/acpi.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/acpi.c
@@ -0,0 +1,1158 @@
+/*
+ * acpi.c -- ACPI methods low-level access code for TSM70 class laptops
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+#ifdef CONFIG_ACPI
+
+#include <acpi/acpi_drivers.h>
+#include <linux/workqueue.h>
+
+/* copied from drivers/input/serio/i8042-io.h */
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+
+/*
+ * ACPI backend masks and strings
+ */
+
+#define GET_WIRELESS_METHOD "ANTR"
+#define SET_WIRELESS_METHOD "ANTW"
+#define WLEX_MASK	0x4
+#define WLAT_MASK	0x1
+#define BTEX_MASK	0x8
+#define BTAT_MASK	0x2
+#define KLSW_MASK	0x10
+
+#define GET_DISPLAY_METHOD "DOSS"
+#define SET_DISPLAY_METHOD "DOSW"
+/* Display reading masks CADL = detected, CSTE = enabled */
+#define	LCD_CADL	0x10
+#define	CRT_CADL	0x20
+#define	TVO_CADL	0x40
+#define	DVI_CADL	0x80
+#define	LCD_CSTE	0x1
+#define	CRT_CSTE	0x2
+#define	TVO_CSTE	0x4
+#define DVI_CSTE	0x8
+
+/* TSX205 Video-Out methods and return values */
+#define TSX205_SET_DISPLAY_METHOD "STBL"
+#define TSX205_SLI_DISPLAY_METHOD "SL01.VGA1.STBL"
+/* NOTE: Method DSSW seems to be some sort of auto-detect method */
+#define TSX205_AUTO_DISPLAY_METHOD "DSSW"
+#define TSX205_DSPY_DE	0x1F	/* DE - Detected and Enabled */
+#define TSX205_DSPY_DN	0x1D	/* DN - Detected and Not enabled */
+#define TSX205_DSPY_NE	0x0F	/* NE - Not detected and Enabled */
+#define TSX205_DSPY_NN	0x0D	/* NN - Not detected and Not enabled */
+
+#define GET_THROTTLE_METHOD "THRO"
+#define	SET_THROTTLE_METHOD "CLCK"
+
+static char ec_dev_list[][20] = {
+	"\\_SB.PCI0.LPCB.EC0",
+	"\\_SB.PCI0.LPC0.EC0",
+};
+
+/* TSX205 HCI and display handles */
+static char tsx205_dev_list[][20] = {
+	"\\_SB.VALZ",
+	"\\_SB.PCI0.PEGP.VGA"
+};
+
+/* TSX205 GET video-out methods */
+static char tsx205_video_list[][20] = {
+	"LCD._DCS",
+	"CRT._DCS",
+	"TV._DCS",
+	"DVI._DCS",
+	"SL01.VGA1.LCD._DCS",
+	"SL01.VGA1.CRT._DCS",
+	"SL01.VGA1.TV._DCS",
+	"SL01.VGA1.DVI._DCS",
+};
+
+#define TOSHIBA_ACPI_BT_CLASS "bluetooth"
+#define TOSHIBA_ACPI_DEVICE_NAME "bluetooth adapter"
+
+#define TOSH_BT_ACTIVATE_USB	"AUSB"
+#define TOSH_BT_DISABLE_USB	"DUSB"
+#define TOSH_BT_POWER_ON	"BTPO"
+#define TOSH_BT_POWER_OFF	"BTPF"
+#define TOSH_BT_STATUS		"BTST"
+#define	TOSH_BT_KSST_MASK	0x1
+#define	TOSH_BT_USB_MASK	0x40
+#define	TOSH_BT_POWER_MASK	0x80
+
+/*
+ * ACPI driver for Toshiba Bluetooth device
+ */
+static int omnibook_acpi_bt_add(struct acpi_device *device);
+static int omnibook_acpi_bt_remove(struct acpi_device *device, int type);
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+static const struct acpi_device_id omnibook_bt_ids[] = {
+	{"TOS6205", 0},
+	{"", 0},
+};
+
+static struct acpi_driver omnibook_bt_driver = {
+	.name	= OMNIBOOK_MODULE_NAME,
+	.class	= TOSHIBA_ACPI_BT_CLASS,
+	.ids	= omnibook_bt_ids,
+	.ops	= {
+			.add	=  omnibook_acpi_bt_add,
+			.remove	=  omnibook_acpi_bt_remove,
+		  },
+};
+#else /* 2.6.23 */
+static struct acpi_driver omnibook_bt_driver = {
+	.name	= OMNIBOOK_MODULE_NAME,
+	.class	= TOSHIBA_ACPI_BT_CLASS,
+	.ids	= "TOS6205",
+	.ops	= {
+			.add	=  omnibook_acpi_bt_add,
+			.remove	=  omnibook_acpi_bt_remove,
+		  },
+};
+#endif /* 2.6.23 */
+
+
+/*
+ * ACPI backend private data structure
+ */
+struct acpi_backend_data {
+	acpi_handle ec_handle;  /* Handle on ACPI EC device */
+	acpi_handle bt_handle;  /* Handle on ACPI BT device */
+	acpi_handle hci_handle; /* Handle on ACPI HCI device */
+	acpi_handle dis_handle; /* Handle on ACPI Display device */
+	unsigned has_antr_antw:1; /* Are there ANTR/ANTW methods in the EC device ? */
+	unsigned has_doss_dosw:1; /* Are there DOSS/DOSW methods in the EC device ? */
+	unsigned has_sli:1; /* Does the laptop has SLI enabled ? */
+	struct input_dev *acpi_input_dev;
+	struct work_struct fnkey_work;
+};
+
+/*
+ * Hotkeys workflow:
+ * 1. Fn+Foo pressed
+ * 2. Scancode 0x6e generated by kbd controller
+ * 3. Scancode 0x6e caught by omnibook input handler
+ * 4. INFO method has keycode of last actually pressed Fn key
+ * 5. acpi_scan_table used to associate a detected keycode with a generated one
+ * 6. Generated keycode issued using the omnibook input device
+ */
+
+/*
+ * The input handler should only bind with the standard AT keyboard.
+ * XXX: Scancode 0x6e won't be detected if the keyboard has already been
+ * grabbed (the Xorg event input driver do that)
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+static int hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 const struct input_device_id *id)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static struct input_handle *hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 const struct input_device_id *id)
+#else
+static struct input_handle *hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 struct input_device_id *id)
+#endif
+{
+	struct input_handle *handle;
+	int error;
+
+	/* the 0x0001 vendor magic number is found in atkbd.c */
+	if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001))
+		goto out_nobind;
+
+	if(!strstr(dev->phys, I8042_KBD_PHYS_DESC))
+		goto out_nobind;
+
+	dprintk("hook_connect for device %s.\n", dev->name);
+
+	if(dev->grab)
+		printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n",
+			dev->grab->name);
+
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+		return -ENOMEM;
+#else
+		return NULL;
+#endif
+
+	handle->dev = dev;
+	handle->handler = handler;
+	handle->name = "omnibook_scancode_hook";
+	handle->private = handler->private;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	error = input_register_handle(handle);
+	if (error) {
+		dprintk("register_handle failed\n");
+		goto out_nobind_free;
+	} 
+	error = input_open_device(handle);
+	if (error) {
+		dprintk("register_handle failed\n");
+		input_unregister_handle(handle);
+		goto out_nobind_free;
+	} 
+	
+#else
+	status=input_open_device(handle);
+	if (error==0) dprintk("Input device opened\n");
+	else { 
+		dprintk("opening input device failed\n");
+		goto out_nobind_free;
+	}
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	return 0;
+out_nobind_free:
+	kfree(handle);
+out_nobind:
+	return -ENODEV;
+#else
+	return handle;
+out_nobind_free:
+	kfree(handle);
+out_nobind:
+	return NULL;
+#endif	
+}
+
+static void hook_disconnect(struct input_handle *handle)
+{
+	dprintk("hook_disconnect.\n");
+	input_close_device(handle);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	input_unregister_handle(handle);
+#endif
+	kfree(handle);
+}
+
+/*
+ * Hook for scancode 0x6e. Actual handling is done in a workqueue.
+ */
+static void hook_event(struct input_handle *handle, unsigned int event_type,
+		      unsigned int event_code, int value)
+{
+	if (event_type == EV_MSC && event_code == MSC_SCAN && value == ACPI_FN_SCAN)
+		schedule_work(&((struct acpi_backend_data *)handle->private)->fnkey_work);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static const struct input_device_id hook_ids[] = {
+#else
+static struct input_device_id hook_ids[] = {
+#endif
+	{
+                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+                .evbit = { BIT(EV_KEY) },
+        },
+	{ },    /* Terminating entry */
+};
+
+static struct input_handler hook_handler = {
+	.event		= hook_event,
+	.connect	= hook_connect,
+	.disconnect	= hook_disconnect,
+	.name		= OMNIBOOK_MODULE_NAME,
+	.id_table	= hook_ids,
+};
+
+/*
+ * Detected scancode to keycode table
+ */
+static const struct {
+	unsigned int scancode;
+	unsigned int keycode;
+} acpi_scan_table[] = {
+	{ HCI_FN_RELEASED,    KEY_FN},
+	{ HCI_MUTE,           KEY_MUTE},
+	{ HCI_BREAK,          KEY_COFFEE},
+	{ HCI_1,              KEY_ZOOMOUT},
+	{ HCI_2,              KEY_ZOOMIN},
+	{ HCI_SPACE,          KEY_ZOOMRESET},
+	{ HCI_BSM,            KEY_BATTERY},
+	{ HCI_SUSPEND,        KEY_SLEEP},
+	{ HCI_HIBERNATE,      KEY_SUSPEND},
+	{ HCI_VIDEOOUT,       KEY_SWITCHVIDEOMODE},
+	{ HCI_BRIGHTNESSDOWN, KEY_BRIGHTNESSDOWN},
+	{ HCI_BRIGHTNESSUP,   KEY_BRIGHTNESSUP},
+	{ HCI_WLAN,           KEY_WLAN},
+	{ HCI_TOUCHPAD,       KEY_PROG1},
+	{ HCI_FN_PRESSED,     KEY_FN},
+	{ 0, 0},
+};
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work);
+#else
+static void omnibook_handle_fnkey(void* data);
+#endif
+
+/*
+ * Register the input handler and the input device in the input subsystem
+ */
+static int register_input_subsystem(struct acpi_backend_data *priv_data)
+{
+	int i, retval = 0;
+	struct input_dev *acpi_input_dev;
+
+	acpi_input_dev = input_allocate_device();
+	if (!acpi_input_dev) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	acpi_input_dev->name = "Omnibook ACPI scancode generator";
+	acpi_input_dev->phys = "omnibook/input0";
+	acpi_input_dev->id.bustype = BUS_HOST;
+	
+	set_bit(EV_KEY, acpi_input_dev->evbit);
+	
+	for(i=0 ; i < ARRAY_SIZE(acpi_scan_table); i++)
+		set_bit(acpi_scan_table[i].keycode, acpi_input_dev->keybit);
+
+	retval = input_register_device(acpi_input_dev);
+	if (retval) {
+		input_free_device(acpi_input_dev);
+		goto out;
+	}
+
+	priv_data->acpi_input_dev = acpi_input_dev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+	INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey);
+#else
+	INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data);
+#endif
+
+
+	hook_handler.private = priv_data;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+	retval = input_register_handler(&hook_handler);	
+#else
+	input_register_handler(&hook_handler);
+#endif
+
+	out:	
+	return retval;
+}
+
+/*
+ * Execute an ACPI method which return either an integer or nothing
+ * and that require 0 or 1 numerical argument
+ * (acpi_evaluate_object wrapper)
+ */
+static int omnibook_acpi_execute(acpi_handle dev_handle, char *method, const int *param, int *result)
+{
+
+	struct acpi_object_list args_list;
+	struct acpi_buffer buff;
+	union acpi_object arg, out_objs[1];
+	
+	if (param) {
+		args_list.count = 1;
+		args_list.pointer = &arg;
+		arg.type = ACPI_TYPE_INTEGER;
+		arg.integer.value = *param;
+	} else
+		args_list.count = 0;
+
+	buff.length = sizeof(out_objs);
+	buff.pointer = out_objs;
+
+	if (acpi_evaluate_object(dev_handle, method, &args_list, &buff) != AE_OK) {
+		printk(O_ERR "ACPI method execution failed\n");
+		return -EIO;
+	}
+
+	if (!result)		/* We don't care what the method returned here */
+		return 0;
+
+	if (out_objs[0].type != ACPI_TYPE_INTEGER) {
+		printk(O_ERR "ACPI method result is not a number\n");
+		return -EINVAL;
+	}
+
+	*result = out_objs[0].integer.value;
+	return 0;
+}
+
+/*
+ * Probe for expected ACPI devices
+ */
+static int omnibook_acpi_init(const struct omnibook_operation *io_op)
+{
+	int retval = 0;	
+	acpi_handle dev_handle, method_handle, hci_handle, dis_handle;
+	int i;
+	int has_sli = 0;
+	struct acpi_backend_data *priv_data;
+	
+	if (unlikely(acpi_disabled)) {
+		printk(O_ERR "ACPI is disabled: feature unavailable.\n");
+		return -ENODEV;
+	}
+
+	if (!io_op->backend->data) {
+		dprintk("Try to init ACPI backend\n");
+		mutex_init(&io_op->backend->mutex);
+		mutex_lock(&io_op->backend->mutex);
+		kref_init(&io_op->backend->kref);
+		priv_data = kzalloc(sizeof(struct acpi_backend_data), GFP_KERNEL);
+		if (!priv_data) {
+			retval = -ENOMEM;
+			goto error0;
+		}
+
+		/* Locate ACPI EC device, acpi_get_handle set dev_handle to NULL if not found */
+		for (i = 0; i < ARRAY_SIZE(ec_dev_list); i++) {
+			if (acpi_get_handle(NULL, ec_dev_list[i], &dev_handle) == AE_OK) {
+				dprintk("ACPI EC device found\n");
+				priv_data->ec_handle = dev_handle;
+				break;
+			}
+		}
+		
+		if (!dev_handle) {
+			printk(O_ERR "Can't get handle on ACPI EC device.\n");
+			retval = -ENODEV;
+			goto error1;
+		}
+
+		/* Probe for HCI and Display devices only on TSX205 models */
+		if (omnibook_ectype & TSX205) {
+			if (acpi_get_handle(NULL, tsx205_dev_list[0], &hci_handle) == AE_OK) {
+				dprintk("Toshiba X205 HCI device found\n");
+				priv_data->hci_handle = hci_handle;
+			}
+
+			if (!hci_handle) {
+				printk(O_ERR "Couldn't get HCI handle.\n");
+				retval = -ENODEV;
+				goto error1;
+			}
+
+			if (acpi_get_handle(NULL, tsx205_dev_list[1], &dis_handle) == AE_OK)
+				priv_data->dis_handle = dis_handle;
+
+			if (!dis_handle) {
+				printk(O_ERR "Couldn't get X205 Display handle.\n");
+				retval = -ENODEV;
+				goto error1;
+			}
+
+			/* Does the laptop has SLI enabled? */
+			omnibook_acpi_execute(dis_handle, (char *)TSX205_SLIVDO_METHOD, NULL, &has_sli);
+			if (has_sli)
+				dprintk("Toshiba X205 Display device found (SLI).\n");
+			else
+				dprintk("Toshiba X205 Display device found.\n");
+
+			priv_data->has_sli = has_sli;
+		}
+
+		if ((acpi_get_handle( dev_handle, GET_WIRELESS_METHOD, &method_handle) == AE_OK) &&
+		    (acpi_get_handle( dev_handle, SET_WIRELESS_METHOD, &method_handle) == AE_OK))
+			priv_data->has_antr_antw = 1;
+
+		if (omnibook_ectype & TSX205) {
+			if ((acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) ==  AE_OK) &&
+			    (acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) ==  AE_OK))
+				priv_data->has_doss_dosw = 1;
+		} else {
+			if ((acpi_get_handle( dev_handle, GET_DISPLAY_METHOD, &method_handle) == AE_OK) &&
+			    (acpi_get_handle( dev_handle, SET_DISPLAY_METHOD, &method_handle) == AE_OK))
+				priv_data->has_doss_dosw = 1;
+		}
+
+		retval = register_input_subsystem(priv_data);
+		if(retval)
+			goto error1;
+
+		io_op->backend->data = (void *) priv_data;
+		
+		mutex_unlock(&io_op->backend->mutex);
+		
+		/* attempt to register Toshiba bluetooth ACPI driver */
+		acpi_bus_register_driver(&omnibook_bt_driver);
+
+		dprintk("ACPI backend init OK\n");
+		
+		return 0;
+
+	} else {
+		dprintk("ACPI backend has already been initialized\n");
+		kref_get(&io_op->backend->kref);
+		return 0;
+	}
+		
+	error1:
+	kfree(priv_data);
+	io_op->backend->data = NULL;
+	error0:
+	mutex_unlock(&io_op->backend->mutex);
+	mutex_destroy(&io_op->backend->mutex);
+	return retval;
+}
+
+static void omnibook_acpi_free(struct kref *ref)
+{
+	struct omnibook_backend *backend;
+	struct acpi_backend_data *priv_data;
+
+	backend = container_of(ref, struct omnibook_backend, kref);
+	priv_data = backend->data;
+
+	dprintk("ACPI backend not used anymore: disposing\n");
+
+	
+	dprintk("ptr addr: %p driver name: %s\n",&omnibook_bt_driver, omnibook_bt_driver.name);
+	acpi_bus_unregister_driver(&omnibook_bt_driver);
+
+	flush_scheduled_work();
+	input_unregister_handler(&hook_handler);
+	input_unregister_device(priv_data->acpi_input_dev);
+	
+	mutex_lock(&backend->mutex);
+	kfree(backend->data);
+	backend->data = NULL;
+	mutex_unlock(&backend->mutex);
+	mutex_destroy(&backend->mutex);
+}
+
+static void omnibook_acpi_exit(const struct omnibook_operation *io_op)
+{
+	dprintk("Trying to dispose ACPI backend\n");
+	kref_put(&io_op->backend->kref, omnibook_acpi_free);
+}
+
+/* forward declaration */
+struct omnibook_backend acpi_backend;
+
+/* Function taken from toshiba_acpi */
+static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+{
+	struct acpi_backend_data *priv_data = acpi_backend.data;
+	struct acpi_object_list params;
+	union acpi_object in_objs[HCI_WORDS];
+	struct acpi_buffer results;
+	union acpi_object out_objs[HCI_WORDS + 1];
+	acpi_status status;
+	int i;
+
+	params.count = HCI_WORDS;
+	params.pointer = in_objs;
+	for (i = 0; i < HCI_WORDS; ++i) {
+		in_objs[i].type = ACPI_TYPE_INTEGER;
+		in_objs[i].integer.value = in[i];
+	}
+
+	results.length = sizeof(out_objs);
+	results.pointer = out_objs;
+
+	status = acpi_evaluate_object(priv_data->hci_handle, (char *)HCI_METHOD, &params,
+				      &results);
+	if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
+		for (i = 0; i < out_objs->package.count; ++i) {
+			out[i] = out_objs->package.elements[i].integer.value;
+		}
+	}
+
+	return status;
+}
+
+/*
+ * Set Bluetooth device state using the Toshiba BT device
+ */
+static int set_bt_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+	int retval = 0;
+
+	if (state) {
+		retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_ACTIVATE_USB, NULL, NULL);
+		if (retval)
+			goto out;
+		retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_ON, NULL, NULL);
+		if (retval)
+			goto out;
+	} else {
+		retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_DISABLE_USB, NULL, NULL);
+		if (retval)
+			goto out;
+		retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_OFF, NULL, NULL);
+		if (retval)
+			goto out;
+	}
+	out:
+	return retval;
+}
+
+static int omnibook_acpi_bt_add(struct acpi_device *device)
+{
+	int retval;
+	struct acpi_backend_data *priv_data = acpi_backend.data;
+	
+	dprintk("Enabling Toshiba Bluetooth ACPI device.\n");
+	strcpy(acpi_device_name(device), TOSHIBA_ACPI_DEVICE_NAME);
+	strcpy(acpi_device_class(device), TOSHIBA_ACPI_BT_CLASS);
+
+	/* Save handle in backend private data structure. ugly. */
+
+	mutex_lock(&acpi_backend.mutex);
+	priv_data->bt_handle = device->handle;
+	retval = set_bt_status(priv_data, 1);
+	mutex_unlock(&acpi_backend.mutex);
+
+	return retval;
+}
+
+static int omnibook_acpi_bt_remove(struct acpi_device *device, int type)
+{
+	int retval;
+	struct acpi_backend_data *priv_data = acpi_backend.data;
+
+	mutex_lock(&acpi_backend.mutex);
+	dprintk("Disabling Toshiba Bluetooth ACPI device.\n");
+	retval = set_bt_status(priv_data, 0);
+	priv_data->bt_handle = NULL;
+	mutex_unlock(&acpi_backend.mutex);
+	
+	return retval;
+}
+
+/*
+ * Get Bluetooth status using the BTST method
+ */
+static int get_bt_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+	int retval = 0;
+	int raw_state;
+
+	if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state)))
+		return retval;
+
+	dprintk("BTST raw_state: %x\n", raw_state);
+
+	*state = BT_EX;
+	*state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0;
+
+	return retval;
+}
+
+/*
+ * Get the Bluetooth + Wireless status using the ANTR method
+ * FIXME: what if ANTR and BTST disagree ? we thrust ANTR for now
+ */
+static int get_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+	int retval = 0;
+	int raw_state;
+
+	if ((retval = omnibook_acpi_execute(priv_data->ec_handle, GET_WIRELESS_METHOD, NULL, &raw_state)))
+		return retval;
+
+	dprintk("get_wireless raw_state: %x\n", raw_state);
+
+	*state = (raw_state & WLEX_MASK) ? WIFI_EX : 0;
+	*state |= (raw_state & WLAT_MASK) ? WIFI_STA : 0;
+	*state |= (raw_state & KLSW_MASK) ? KILLSWITCH : 0;
+	*state |= (raw_state & BTEX_MASK) ? BT_EX : 0;
+	*state |= (raw_state & BTAT_MASK) ? BT_STA : 0;
+
+	return retval;
+}
+
+static int get_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state)
+{
+	int retval = 0;
+	int raw_state;
+	u32 in[HCI_WORDS] = { HCI_GET, HCI_RF_CONTROL, 0, HCI_WIRELESS_CHECK, 0, 0 };
+	u32 out[HCI_WORDS];
+
+	hci_raw(in, out);
+
+	/* Now let's check the killswitch */
+	if ((retval = omnibook_acpi_execute(priv_data->ec_handle, TSX205_KILLSW_METHOD, NULL, &raw_state)))
+		return retval;
+
+	dprintk("get_wireless raw_state: %x\n", out[2]);
+
+	*state = ((out[2] & 0xff)) ? WIFI_EX : 0;
+	*state |= (raw_state) ? WIFI_STA : 0;
+	*state |= (!raw_state) ? KILLSWITCH : 0;
+
+	/* And finally BT */
+	if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state)))
+		return retval;
+	
+	*state |= BT_EX;
+	*state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0;
+
+	return retval;
+}
+
+static int omnibook_acpi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval;
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+
+	/* use BTST (BT device) if we don't have ANTR/ANTW (EC device) */
+	if (omnibook_ectype & TSX205)
+		retval = get_tsx205_wireless_status(priv_data, state);
+	else if (priv_data->has_antr_antw)
+		retval = get_wireless_status(priv_data, state);
+	else if(priv_data->bt_handle)
+		retval = get_bt_status(priv_data, state);
+	else
+		retval = -ENODEV;
+
+	return retval;
+}
+
+/*
+ * Set the Bluetooth + Wireless status using the ANTW method
+ */
+static int set_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+	int retval;
+	int raw_state;
+
+	raw_state = !!(state & WIFI_STA);	/* bit 0 */
+	raw_state |= !!(state & BT_STA) << 0x1;	/* bit 1 */
+
+	dprintk("set_wireless raw_state: %x\n", raw_state);
+
+	retval = omnibook_acpi_execute(priv_data->ec_handle, SET_WIRELESS_METHOD, &raw_state, NULL);
+
+	return retval;
+}
+
+static int set_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state)
+{
+	int retval;
+	int raw_state = !!(state & WIFI_STA);
+
+	dprintk("set_wireless raw_state: %x\n", raw_state);
+
+	u32 in[HCI_WORDS] = { HCI_SET, HCI_RF_CONTROL, raw_state, HCI_WIRELESS_POWER, 0, 0 };
+	u32 out[HCI_WORDS];
+	hci_raw(in, out);
+
+	raw_state |= !!(state & BT_STA) << 0x1;	/* bit 1 */
+
+	/* BT status */
+	retval = set_bt_status(priv_data->bt_handle, state);
+
+	return retval;
+}
+
+static int omnibook_acpi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval = -ENODEV;
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+
+	/* First try the TSX205 methods */
+	if(omnibook_ectype & TSX205)
+		retval = set_tsx205_wireless_status(priv_data, state);
+
+	/* Then try the ANTR/ANTW methods */
+	if(priv_data->has_antr_antw)
+		retval = set_wireless_status(priv_data, state);
+	
+	/* Then try the bluetooth ACPI device if present */
+	if(priv_data->bt_handle)
+		retval = set_bt_status(priv_data, (state & BT_STA));
+
+	return retval;
+}
+
+static int tsx205_get_display(const struct acpi_backend_data *priv_data, unsigned int *state, unsigned int device)
+{
+	int retval = 0;
+	int raw_state = 0;
+
+	retval = omnibook_acpi_execute(priv_data->dis_handle, tsx205_video_list[device], NULL, &raw_state);
+	if (retval < 0) {
+		dprintk(O_ERR "Failed to get video device (%d) state.\n", device);
+		return retval;
+	}
+
+	/* Ugly, but better than nothing... */
+	switch (device) {
+	case 0:
+	case 4:	/* LCD device */
+		dprintk("get_display LCD (%d) raw_state: %x\n", device, raw_state);
+		if (raw_state == TSX205_DSPY_DE) {
+			*state |= DISPLAY_LCD_DET;
+			*state |= DISPLAY_LCD_ON;
+		} else
+		if (raw_state == TSX205_DSPY_DN)
+			*state |= DISPLAY_LCD_DET;
+		else if (raw_state == TSX205_DSPY_NE)
+			*state |= DISPLAY_LCD_ON;
+		break;
+	case 1:
+	case 5:	/* CRT device */
+		dprintk("get_display CRT (%d) raw_state: %x\n", device, raw_state);
+		if (raw_state == TSX205_DSPY_DE) {
+			*state |= DISPLAY_CRT_DET;
+			*state |= DISPLAY_CRT_ON;
+		} else
+		if (raw_state == TSX205_DSPY_DN)
+			*state |= DISPLAY_CRT_DET;
+		else if (raw_state == TSX205_DSPY_NE)
+			*state |= DISPLAY_CRT_ON;
+		break;
+	case 2:
+	case 6:	/* TV-OUT device */
+		dprintk("get_display TV-OUT (%d) raw_state: %x\n", device, raw_state);
+		if (raw_state == TSX205_DSPY_DE) {
+			*state |= DISPLAY_TVO_DET;
+			*state |= DISPLAY_TVO_ON;
+		} else
+		if (raw_state == TSX205_DSPY_DN)
+			*state |= DISPLAY_TVO_DET;
+		else if (raw_state == TSX205_DSPY_NE)
+			*state |= DISPLAY_TVO_ON;
+		break;
+	case 3:
+	case 7:	/* DVI device */
+		dprintk("get_display DVI (%d) raw_state: %x\n", device, raw_state);
+		if (raw_state == TSX205_DSPY_DE) {
+			*state |= DISPLAY_DVI_DET;
+			*state |= DISPLAY_DVI_ON;
+		} else
+		if (raw_state == TSX205_DSPY_DN)
+			*state |= DISPLAY_DVI_DET;
+		else if (raw_state == TSX205_DSPY_NE)
+			*state |= DISPLAY_DVI_ON;
+		break;
+	}
+
+	return retval;
+}
+
+static int omnibook_acpi_get_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval = 0;
+	int raw_state = 0;
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+	
+	if(!priv_data->has_doss_dosw)
+		return -ENODEV;
+
+	if (omnibook_ectype & TSX205) {
+		int i;
+
+		/* Loop 'tru the different Video-Out devices */
+		if (priv_data->has_sli)
+			for (i = 4; i < ARRAY_SIZE(tsx205_video_list); i++)
+				retval = tsx205_get_display(priv_data, state, i);
+		else
+			for (i = 0; i < 4; i++)
+				retval = tsx205_get_display(priv_data, state, i);
+
+		if (retval < 0)
+			return -EIO;
+	
+		goto vidout;
+	}
+
+	retval = omnibook_acpi_execute(priv_data->ec_handle, GET_DISPLAY_METHOD, NULL, &raw_state);
+	if (retval < 0)
+		return retval;
+
+	dprintk("get_display raw_state: %x\n", raw_state);
+
+	/* Backend specific to backend-neutral conversion */
+	*state = (raw_state & LCD_CSTE) ? DISPLAY_LCD_ON : 0;
+	*state |= (raw_state & CRT_CSTE) ? DISPLAY_CRT_ON : 0;
+	*state |= (raw_state & TVO_CSTE) ? DISPLAY_TVO_ON : 0;
+	*state |= (raw_state & DVI_CSTE) ? DISPLAY_DVI_ON : 0;
+
+	*state |= (raw_state & LCD_CADL) ? DISPLAY_LCD_DET : 0;
+	*state |= (raw_state & CRT_CADL) ? DISPLAY_CRT_DET : 0;
+	*state |= (raw_state & TVO_CADL) ? DISPLAY_TVO_DET : 0;
+	*state |= (raw_state & DVI_CADL) ? DISPLAY_DVI_DET : 0;
+
+vidout:
+	return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON
+	    | DISPLAY_LCD_DET | DISPLAY_CRT_DET | DISPLAY_TVO_DET | DISPLAY_DVI_DET;
+}
+
+static const unsigned int acpi_display_mode_list[] = {
+	DISPLAY_LCD_ON,
+	DISPLAY_CRT_ON,
+	DISPLAY_LCD_ON | DISPLAY_CRT_ON,
+	DISPLAY_TVO_ON,
+	DISPLAY_LCD_ON | DISPLAY_TVO_ON,
+	DISPLAY_CRT_ON | DISPLAY_TVO_ON,
+	DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON,
+	DISPLAY_DVI_ON,
+	DISPLAY_LCD_ON | DISPLAY_DVI_ON,
+};
+
+static int omnibook_acpi_set_display(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval = 0;
+	int i; 
+	int matched = -1;
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+
+	if(!priv_data->has_doss_dosw)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(acpi_display_mode_list); i++) {
+		if (acpi_display_mode_list[i] == state) {
+			matched = i + 1;	/* raw state is array row number + 1 */
+			break;
+		}
+	}
+	if (matched == -1) {
+		printk("Display mode %x is unsupported.\n", state);
+		return -EINVAL;
+	}
+
+	dprintk("set_display raw_state: %x\n", matched);
+
+	if (omnibook_ectype & TSX205) {
+		if (priv_data->has_sli)
+			retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SLI_DISPLAY_METHOD, &matched, NULL);
+		else
+			retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SET_DISPLAY_METHOD, &matched, NULL);
+	} else
+		retval = omnibook_acpi_execute(priv_data->ec_handle, SET_DISPLAY_METHOD, &matched, NULL);
+	if (retval < 0)
+		return retval;
+
+	return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON;
+}
+
+static int omnibook_acpi_get_throttle(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval;
+	int thtl_en = 0, thtl_dty = 0;
+	int param;
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+	
+	param = 0;
+	/* Read THEN aka THTL_EN in ICH6M datasheets */
+	retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, &param, &thtl_en); 
+	if ( thtl_en == 0 ) {
+		*state = 0;
+		return retval;
+	}
+	param = 1;
+	/* Read DUTY aka THTL_DTY in ICH6M datasheets */
+	retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, &param, &thtl_dty);
+	WARN_ON(thtl_dty > 7); /* We shouldn't encounter more than 7 throttling level */
+	*state = 8 - thtl_dty; /* THTL_DTY and ACPI T-state are reverse mapped */
+	return retval;
+}
+
+static int omnibook_acpi_set_throttle(const struct omnibook_operation *io_op, unsigned int state)
+{
+	struct acpi_backend_data *priv_data = io_op->backend->data;
+	/* THTL_DTY and ACPI T-state are reverse mapped */
+	/* throttling.c already clamped state between 0 and 7 */
+	if (state) 
+		state = 8 - state;
+
+	return omnibook_acpi_execute(priv_data->ec_handle, SET_THROTTLE_METHOD, &state, NULL);
+}
+
+/*
+ * Fn+foo hotkeys handling
+ */
+static int omnibook_hci_get_hotkeys(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	u32 in[HCI_WORDS] = { HCI_GET, HCI_HOTKEY_EVENT, 0, 0, 0, 0 };
+	u32 out[HCI_WORDS];
+	acpi_status status = hci_raw(in, out);
+
+	if (status != AE_OK)
+		return HCI_FAILURE;
+
+	dprintk("get_hotkeys raw_state: %x\n", out[2]);
+
+	*state = (out[2] & ACPI_FN_MASK) ? HKEY_FN : 0;
+
+	return 0;
+}
+
+static int omnibook_hci_set_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
+	u32 out[HCI_WORDS];
+	in[0] = HCI_SET;
+	in[1] = HCI_HOTKEY_EVENT;
+	in[2] = (state & HKEY_FN) ? 1 : 0;
+	acpi_status status = hci_raw(in, out);
+
+	dprintk("set_hotkeys (Fn interface) raw_state: %x\n", in[2]);
+
+	return (status == AE_OK) ? out[0] : HCI_FAILURE;
+}
+
+static int omnibook_acpi_get_events(unsigned int *state)
+{
+	acpi_status status;
+	struct acpi_backend_data *priv_data = acpi_backend.data;
+  
+	/* We need to call the NTFY method first so it can activate the TECF variable */
+	status = omnibook_acpi_execute(priv_data->ec_handle, TSX205_NOTIFY_METHOD, NULL, NULL);
+	if (status != AE_OK) {
+		dprintk(O_ERR "Failed to activate NTFY method.\n");
+		return -EIO;
+	}
+
+	/* Now we can poll the INFO method to get last pressed hotkey */
+	status = omnibook_acpi_execute(priv_data->hci_handle, TSX205_EVENTS_METHOD, NULL, state);
+	if (status != AE_OK) {
+		dprintk(O_ERR "Failed to get Hotkey event.\n");
+		return -EIO;
+	}
+
+	/* We only care about a key press, so just report the Fn key Press/Release */
+	if ( ((*state & ~0x80) == 0x100) || ((*state & ~0x80) == 0x17f) )
+		*state &= ~0x80;
+
+	return status;
+}
+
+/*
+ * Adjust the lcd backlight level by delta.
+ * Used for Fn+F6/F7 keypress
+ */
+static int adjust_brighness(int delta)
+{
+	struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd");
+	struct omnibook_operation *io_op;
+	int retval = 0;
+	u8 brgt;
+
+	if(!lcd_feature)
+		return -ENODEV;
+
+	io_op = lcd_feature->io_op;
+
+	mutex_lock(&io_op->backend->mutex);
+
+	if(( retval = __backend_byte_read(io_op, &brgt)))
+		goto out;	
+
+	dprintk("Fn-F6/F7 pressed: adjusting brightness.\n");
+
+	if (((int) brgt + delta) < 0)
+		brgt = 0;
+	else if ((brgt + delta) > omnibook_max_brightness)
+		brgt = omnibook_max_brightness;
+	else
+		brgt += delta;
+
+	retval = __backend_byte_write(io_op, brgt);
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Workqueue handler for Fn hotkeys
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work)
+#else
+static void omnibook_handle_fnkey(void* data)
+#endif
+{
+	int i;
+	u32 gen_scan;
+	struct input_dev *input_dev;
+	acpi_status status;
+
+	status = omnibook_acpi_get_events(&gen_scan);
+	if (status != AE_OK)
+		return;
+
+	dprintk("detected scancode 0x%x.\n", gen_scan);
+	switch(gen_scan) {
+	case HCI_BRIGHTNESSDOWN:
+		adjust_brighness(-1);
+		break;
+	case HCI_BRIGHTNESSUP:
+		adjust_brighness(+1);
+		break;
+	}
+
+	for (i = 0 ; i < ARRAY_SIZE(acpi_scan_table); i++) {
+		if (gen_scan == acpi_scan_table[i].scancode) {
+			dprintk("generating keycode %i.\n", acpi_scan_table[i].keycode);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+			input_dev = container_of(work, struct acpi_backend_data, fnkey_work)->acpi_input_dev;
+#else
+			input_dev = ((struct acpi_backend_data *) data)->acpi_input_dev;
+#endif
+			omnibook_report_key(input_dev, acpi_scan_table[i].keycode);
+			break;
+		}
+	}
+}
+
+struct omnibook_backend acpi_backend = {
+	.name = "acpi",
+	.hotkeys_read_cap = HKEY_FN,
+	.hotkeys_write_cap = HKEY_FN,
+	.init = omnibook_acpi_init,
+	.exit = omnibook_acpi_exit,
+	.aerial_get = omnibook_acpi_get_wireless,
+	.aerial_set = omnibook_acpi_set_wireless,
+	.display_get = omnibook_acpi_get_display,
+	.display_set = omnibook_acpi_set_display,
+	.throttle_get = omnibook_acpi_get_throttle,
+	.throttle_set = omnibook_acpi_set_throttle,
+	.hotkeys_get = omnibook_hci_get_hotkeys,
+	.hotkeys_set = omnibook_hci_set_hotkeys,
+};
+
+#else				/* CONFIG_ACPI */
+
+/* dummy backend for non-ACPI systems */
+static int _fail_probe(const struct omnibook_operation *io_op)
+{
+	return -ENODEV;
+}
+
+struct omnibook_backend acpi_backend = {
+	.name = "acpi",
+	.init = _fail_probe,
+};
+
+#endif				/* CONFIG_ACPI */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/ec.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/ec.c
@@ -0,0 +1,188 @@
+/*
+ * ec.c -- low level functions to access Embedded Controller,
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+/*
+ * Interrupt control
+ */
+
+static DEFINE_SPINLOCK(omnibook_ec_lock);
+
+/*
+ * Registers of the embedded controller
+ */
+
+#define OMNIBOOK_EC_DATA		0x62
+#define OMNIBOOK_EC_SC			0x66
+
+/*
+ * Embedded controller status register bits
+ */
+
+#define OMNIBOOK_EC_STAT_OBF		0x01	/* Output buffer full */
+#define OMNIBOOK_EC_STAT_IBF		0x02	/* Input buffer full */
+
+
+/*
+ * Embedded controller commands
+ */
+
+#define OMNIBOOK_EC_CMD_READ		0x80
+#define OMNIBOOK_EC_CMD_WRITE		0x81
+
+/*
+ * Wait for embedded controller buffer
+ */
+
+static int omnibook_ec_wait(u8 event)
+{
+	int timeout = OMNIBOOK_TIMEOUT;
+
+	switch (event) {
+	case OMNIBOOK_EC_STAT_OBF:
+		while (!(inb(OMNIBOOK_EC_SC) & event) && timeout--)
+			mdelay(1);
+		break;
+	case OMNIBOOK_EC_STAT_IBF:
+		while ((inb(OMNIBOOK_EC_SC) & event) && timeout--)
+			mdelay(1);
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (timeout > 0)
+		return 0;
+	return -ETIME;
+}
+
+/*
+ * Read from the embedded controller
+ * Decide at run-time if we can use the much cleaner ACPI EC driver instead of
+ * this implementation, this is the case if ACPI has been compiled and is not
+ * disabled.
+ */
+
+static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 * data)
+{
+	int retval;
+
+#ifdef CONFIG_ACPI_EC
+	if (likely(!acpi_disabled)) {
+		retval = ec_read((u8) io_op->read_addr, data);
+		if (io_op->read_mask)
+			*data &= io_op->read_mask;
+//		dprintk("ACPI EC read at %lx success %i.\n", io_op->read_addr, retval);
+		return retval;
+	}
+#endif
+	spin_lock_irq(&omnibook_ec_lock);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb(OMNIBOOK_EC_CMD_READ, OMNIBOOK_EC_SC);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF);
+	if (retval)
+		goto end;
+	*data = inb(OMNIBOOK_EC_DATA);
+	if (io_op->read_mask)
+		*data &= io_op->read_mask;
+      end:
+	spin_unlock_irq(&omnibook_ec_lock);
+//	dprintk("Custom EC read at %lx success %i.\n", io_op->read_addr, retval);
+	return retval;
+}
+
+/*
+ * Write to the embedded controller:
+ * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner 
+ * ACPI EC driver instead of this legacy implementation. 
+ * This is the case if ACPI has been compiled and is not
+ * disabled.
+ * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation
+ */
+
+static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data)
+{
+	int retval;
+
+#ifdef CONFIG_ACPI_EC
+	if (likely(!acpi_disabled)) {
+		retval = ec_write((u8) io_op->write_addr, data);
+//		dprintk("ACPI EC write at %lx success %i.\n", io_op->write_addr, retval);
+		return retval;
+	}
+#endif
+
+	spin_lock_irq(&omnibook_ec_lock);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb(OMNIBOOK_EC_CMD_WRITE, OMNIBOOK_EC_SC);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA);
+	retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
+	if (retval)
+		goto end;
+	outb(data, OMNIBOOK_EC_DATA);
+      end:
+	spin_unlock_irq(&omnibook_ec_lock);
+//	dprintk("Custom EC write at %lx success %i.\n", io_op->write_addr, retval);
+	return retval;
+}
+
+static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval;
+	u8 raw_state;
+
+	retval = __backend_byte_read(io_op, &raw_state);
+	if (retval < 0)
+		return retval;
+
+	*state = !!(raw_state) & DISPLAY_CRT_DET;
+
+	return DISPLAY_CRT_DET;
+}
+
+/*
+ * Backend interface declarations
+ */
+
+struct omnibook_backend ec_backend = {
+	.name = "ec",
+	.byte_read = omnibook_ec_read,
+	.byte_write = omnibook_ec_write,
+	.display_get = omnibook_ec_display,
+};
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/lib.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/lib.c
@@ -0,0 +1,81 @@
+/*
+ * lib.c -- Generic helpers functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include "hardware.h"
+#include "compat.h"
+#include <linux/input.h>
+
+/*
+ * Generic funtion for applying a mask on a value
+ * Hack: degenerate to omnibook_toggle if there is no read method 
+ * of if the read address is 0, this is used in blank.c 
+ */
+int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle)
+{
+	int retval = 0;
+	int mask;
+	u8 data;
+
+	if(!(io_op->backend->byte_read  && io_op->read_addr))
+		return __omnibook_toggle(io_op,toggle);
+
+	if ((retval = __backend_byte_read(io_op, &data)))
+		return retval;
+
+	if (toggle == 1)
+		mask = io_op->on_mask;
+	else if (toggle == 0)
+		mask = io_op->off_mask;
+	else
+		return -EINVAL;
+
+	if (mask > 0)
+		data |= (u8) mask;
+	else if (mask < 0)
+		data &= ~((u8) (-mask));
+	else
+		return -EINVAL;
+
+	retval = __backend_byte_write(io_op, data);
+
+	return retval;
+}
+
+/*
+ * Helper for toggle like operations
+ */
+int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle)
+{
+	int retval;
+	u8 data;
+
+	data = toggle ? io_op->on_mask : io_op->off_mask;
+	retval = __backend_byte_write(io_op, data);
+	return retval;
+}
+
+void omnibook_report_key( struct input_dev *dev, unsigned int keycode)
+{
+	input_report_key(dev, keycode, 1);
+	input_sync(dev);
+	input_report_key(dev, keycode, 0);
+	input_sync(dev);
+}
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/Kconfig
+++ linux-ec2-2.6.32/ubuntu/omnibook/Kconfig
@@ -0,0 +1,5 @@
+config OMNIBOOK
+	tristate "Kernel module for HP and Toshiba laptops"
+	depends on X86
+	default m
+	---help---
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/dump.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/dump.c
@@ -0,0 +1,107 @@
+/*
+ *  dump.c - Raw dump of EC register, stolen from ibm_acpi.c
+ *
+ *
+ *  Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static u8 ecdump_regs[256];
+
+static int ecdump_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int i, j;
+	u8 v;
+
+	len +=
+	    sprintf(buffer + len,
+		    "EC      " " +00 +01 +02 +03 +04 +05 +06 +07"
+		    " +08 +09 +0a +0b +0c +0d +0e +0f\n");
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+			return -ERESTARTSYS;
+
+	for (i = 0; i < 255; i += 16) {
+		len += sprintf(buffer + len, "EC 0x%02x:", i);
+		for (j = 0; j < 16; j++) {
+			io_op->read_addr = i +j;
+			if (__backend_byte_read(io_op, &v))
+				break;
+			if (v != ecdump_regs[i + j])
+				len += sprintf(buffer + len, " *%02x", v);
+			else
+				len += sprintf(buffer + len, "  %02x", v);
+			ecdump_regs[i + j] = v;
+		}
+		len += sprintf(buffer + len, "\n");
+		if (j != 16)
+			break;
+	}
+
+	mutex_unlock(&io_op->backend->mutex);
+
+	/* These are way too dangerous to advertise openly... */
+#if 0
+	len +=
+	    sprintf(buffer + len,
+		    "commands:\t0x<offset> 0x<value>" " (<offset> is 00-ff, <value> is 00-ff)\n");
+	len +=
+	    sprintf(buffer + len,
+		    "commands:\t0x<offset> <value>  " " (<offset> is 00-ff, <value> is 0-255)\n");
+#endif
+	return len;
+}
+
+static int ecdump_write(char *buffer, struct omnibook_operation *io_op)
+{
+
+	int i, v;
+
+	if (sscanf(buffer, "0x%x 0x%x", &i, &v) == 2) {
+		/* i and v set */
+	} else if (sscanf(buffer, "0x%x %u", &i, &v) == 2) {
+		/* i and v set */
+	} else
+		return -EINVAL;
+	if (i >= 0 && i < 256 && v >= 0 && v < 256) {
+		io_op->write_addr = i;
+		return backend_byte_write(io_op, v);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct omnibook_tbl dump_table[] __initdata = {
+	{ALL_ECTYPES, {EC,}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature dump_driver = {
+	.name = "dump",
+	.enabled = 0,
+	.read = ecdump_read,
+	.write = ecdump_write,
+	.tbl = dump_table,
+};
+
+module_param_named(dump, dump_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dump, "Use 0 to disable, 1 to enable embedded controller register dump support");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/cooling.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/cooling.c
@@ -0,0 +1,97 @@
+/*
+ * colling.c -- cooling methods feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2007
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_cooling_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	len += sprintf(buffer + len, "Cooling method : %s\n", 
+			io_op->backend->cooling_state ? "Performance"  : "Powersave" );
+
+	mutex_unlock(&io_op->backend->mutex);
+	return len;
+}
+
+static int omnibook_cooling_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+
+	if (*buffer == '0') {
+		retval = __backend_byte_write(io_op, 
+				TSM70_COOLING_OFFSET + TSM70_COOLING_POWERSAVE);
+	} else if (*buffer == '1') {
+		retval = __backend_byte_write(io_op,
+				TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+	} else {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	/* *buffer is either '0' or '1' here */
+	if (!retval)
+		io_op->backend->cooling_state = *buffer - '0' ;
+
+	mutex_unlock(&io_op->backend->mutex);
+
+	out:
+	return retval;
+}
+
+static int __init omnibook_cooling_init(struct omnibook_operation *io_op)
+{
+	mutex_lock(&io_op->backend->mutex);
+	/* XXX: Assumed default cooling method: performance */
+	io_op->backend->cooling_state = TSM70_COOLING_PERF;
+	mutex_unlock(&io_op->backend->mutex);
+	return 0;
+}
+
+static void __exit omnibook_cooling_exit(struct omnibook_operation *io_op)
+{
+	/* Set back cooling method to performance */	
+	backend_byte_write(io_op, TSM70_COOLING_OFFSET + TSM70_COOLING_PERF);
+}
+
+static struct omnibook_tbl cooling_table[] __initdata = {
+	{TSM70 | TSX205, {CDI, 0, TSM70_FN_INDEX, 0, 0, 0 }},
+	{0,}
+};
+
+struct omnibook_feature __declared_feature cooling_driver = {
+	.name = "cooling",
+	.enabled = 1,
+	.read = omnibook_cooling_read,
+	.write = omnibook_cooling_write,
+	.init = omnibook_cooling_init,
+	.exit = omnibook_cooling_exit,
+	.ectypes = TSM70 | TSX205,
+	.tbl = cooling_table,
+};
+
+module_param_named(cooling, cooling_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(cooling, "Use 0 to disable, 1 to enable CPU cooling method control");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/compal.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/compal.c
@@ -0,0 +1,526 @@
+/*
+ * compal.c -- EC PIO Command/Data/Index mode low-level access code
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kref.h>
+
+#include <asm/io.h>
+#include "hardware.h"
+
+/*
+ * ATI's IXP PCI-LPC bridge
+ */
+#define PCI_DEVICE_ID_ATI_SB400 0x4377
+
+/* 
+ * PCI Config space regiser
+ * Laptop with Intel ICH Chipset
+ * See ICH6M and ICH7M spec
+ */
+#define INTEL_LPC_GEN1_DEC	0x84
+#define INTEL_LPC_GEN4_DEC	0x90
+#define INTEL_IOPORT_BASE 	0xff2c
+
+/* 
+ * PCI Config space regiser
+ * Laptop with ATI Chipset
+ * FIXME Untested, name unknown
+ */
+#define ATI_LPC_REG		0x4a
+#define ATI_IOPORT_BASE 	0xfd60
+
+/* 
+ *This interface uses 2 ports for command and 1 port for data
+ *These are relative to the ioport_base address
+ */
+
+#define PIO_PORT_COMMAND1	0x1
+#define PIO_PORT_COMMAND2	0x2
+#define PIO_PORT_DATA		0x3
+
+/*
+ * Private data of this backend
+ */
+static struct pci_dev *lpc_bridge;	/* Southbridge chip ISA bridge/LPC interface PCI device */
+static u32 ioport_base;		/* PIO base adress */
+static union {
+	u16 word;
+	u32 dword;
+} pci_reg_state;		/* Saved state of register in PCI config spave */
+
+/*
+ * Possible list of supported southbridges
+ * Here mostly to implement a more or less clean PCI probing
+ * Works only because of previous DMI probing.
+ * Shared with nbsmi backend
+ */
+const struct pci_device_id lpc_bridge_table[] = {
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+        {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB400, PCI_ANY_ID, PCI_ANY_ID, 0, 0,},
+	{0,},			/* End of list */
+};
+
+/*
+ * Low-level Read function:
+ * Write a 2-bytes wide command to the COMMAND ports
+ * Read the result in the DATA port
+ */
+static unsigned char lowlevel_read(u16 command)
+{
+	unsigned char data;
+	outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1);
+	outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2);
+	data = inb(ioport_base + PIO_PORT_DATA);
+	return data;
+}
+
+/*
+ * Low-level Write function:
+ * Write a 2-bytes wide command to the COMMAND ports
+ * Write the result in the DATA port
+ */
+static void lowlevel_write(u16 command, u8 data)
+{
+	outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1);
+	outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2);
+	outb(data, ioport_base + PIO_PORT_DATA);
+}
+
+/*
+ * Probe for a state of the PIO Command/Data/Index interface
+ * Give some time for the controler to settle in the desired state
+ * mode significance:
+ * 0: Waiting for command
+ * 1,2,3: I am confused FIXME
+ */
+static int check_cdimode_flag(unsigned int mode)
+{
+	int i;
+	int retval;
+
+	/*dprintk("Index mode:");*/
+	for (i = 1; i <= 250; i++) {
+		retval = lowlevel_read(0xfbfc);
+		/*dprintk_simple(" [%i]", retval);*/
+		if (retval == mode) {
+			/*dprintk_simple(".\n");
+			dprintk("Index Mode Ok (%i) after %i iter\n", mode, i);*/
+			return 0;
+		}
+		udelay(100);
+	}
+	printk(O_ERR "check_cdimode_flag timeout.\n");
+	return -ETIME;
+}
+
+/*
+ * Check for conventional default (0xf432) state in Commad ports
+ */
+static int check_default_state(void)
+{
+	int i;
+
+	for (i = 1; i <= 250; i++) {
+		if ((inb(ioport_base + PIO_PORT_COMMAND1) == 0xf4)
+		    && (inb(ioport_base + PIO_PORT_COMMAND2) == 0x32))
+			return 0;
+		udelay(100);
+	}
+	printk(O_ERR "check_default_state timeout.\n");
+	return -ETIME;
+}
+
+/*
+ * Enable EC Command/Data/Index PIO Access and then check EC state.
+ * Enabling is done in PCI config space of the LPC bridge.
+ *
+ * Just after Enabling, the EC should be in a precisly defined state:
+ * - PIO should be in a conventional default state (0xf432 in the Command ports)
+ * - Command/Data/Index interface waiting for command
+ * The EC is expected to be in that state prior to any attempt to use the interface.
+ *
+ */
+static int enable_cdimode(void)
+{
+	union {
+		u16 word;
+		u32 dword;
+	} value;
+
+	switch (lpc_bridge->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		switch (lpc_bridge->device) {
+		case PCI_DEVICE_ID_INTEL_ICH7_0:	/* ICH7 */
+		case PCI_DEVICE_ID_INTEL_ICH7_1:
+		case PCI_DEVICE_ID_INTEL_ICH7_30:
+		case PCI_DEVICE_ID_INTEL_ICH7_31:
+		case PCI_DEVICE_ID_INTEL_ICH8_4:	/* ICH8 */
+			pci_read_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, &(value.dword));
+			pci_reg_state.dword = value.dword;
+			value.dword = 0x3CFF21;
+			pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, value.dword);
+			break;
+		default:	/* All other Intel chipset */
+			pci_read_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, &(value.word));
+			pci_reg_state.word = value.word;
+			value.word = (INTEL_IOPORT_BASE & 0xfff1) | 0x1;
+			pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, value.word);
+		}
+		break;
+	case PCI_VENDOR_ID_ATI:
+		pci_read_config_dword(lpc_bridge, ATI_LPC_REG, &(value.dword));
+		pci_reg_state.dword = value.dword;
+		value.dword = ((pci_reg_state.dword & 0x7f) | 0x80) << 0x10;
+		pci_write_config_dword(lpc_bridge, ATI_LPC_REG, value.dword);
+		break;
+	default:
+		BUG();
+	}
+	dprintk("Saved state of PCI register: [%x].\n", pci_reg_state.dword);
+
+	if (check_default_state() || check_cdimode_flag(0)) {
+		printk(O_ERR "EC state check failure, please report.\n");
+		return -EIO;
+	}
+
+	return 0;
+
+}
+
+/*
+ * Send a write command and associated data code to be written
+ * Known commands an associated code significance:
+ * 0xfbfd: Select Index with 'code' ordinal
+ * 0xfbfe: Set to 'code' a previously selected Index
+ * 0xfbfc: Set CDI mode flag
+ */
+static int send_ec_cmd(unsigned int command, u8 code)
+{
+	lowlevel_write(0xfbfc, 0x2);
+	lowlevel_write(command, code);
+	lowlevel_write(0xfbfc, 0x1);
+	if (check_cdimode_flag(2))
+		return -ETIME;
+	return 0;
+}
+
+/*
+ * Send a read command
+ * Known commands an associated code significance:
+ * 0xfbfe: Read a previously selected Index
+ * 0xfbfc: Set CDI mode flag
+ */
+static int read_ec_cmd(unsigned int command, u8 * value)
+{
+	*value = lowlevel_read(command);
+	lowlevel_write(0xfbfc, 0x1);
+	if (check_cdimode_flag(2))
+		return -ETIME;
+	return 0;
+}
+
+/*
+ * Disable EC Command/Data/Index PIO Access 
+ * Step 1: clear_cdimode
+ * Send Disable command
+ * Revert PIO interface to conventional default state (0xf432 in the Command ports)
+ * Step 2: clear_cdimode_pci
+ * Disable the interface in the PCI config space of the Southbridge
+ * These steps are separated due to constrains in error path treatement
+ */
+static void clear_cdimode(void)
+{
+	lowlevel_write(0xfbfc, 0x0);
+	outb(0xf4, ioport_base + PIO_PORT_COMMAND1);
+	outb(0x32, ioport_base + PIO_PORT_COMMAND2);
+}
+
+static void clear_cdimode_pci(void)
+{
+	switch (lpc_bridge->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		switch (lpc_bridge->device) {
+		case PCI_DEVICE_ID_INTEL_ICH7_0:	/* ICH7 */
+		case PCI_DEVICE_ID_INTEL_ICH7_1:
+		case PCI_DEVICE_ID_INTEL_ICH7_30:
+		case PCI_DEVICE_ID_INTEL_ICH7_31:
+		case PCI_DEVICE_ID_INTEL_ICH8_4:	/* ICH8 */
+			pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, pci_reg_state.dword);
+			break;
+		default:	/* All other Intel chipset */
+			pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, pci_reg_state.word);
+		}
+		break;
+	case PCI_VENDOR_ID_ATI:
+		pci_write_config_dword(lpc_bridge, ATI_LPC_REG, pci_reg_state.dword);
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Try to init the backend
+ * This function can be called blindly as it use a kref
+ * to check if the init sequence was already done.
+ */
+static int omnibook_cdimode_init(const struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	int i;
+
+	/* ectypes other than TSM70 have no business with this backend */
+	if (!(omnibook_ectype & (TSM70 | TSX205)))
+		return -ENODEV;
+
+	if (io_op->backend->already_failed) {
+		dprintk("CDI backend init already failed, skipping.\n");
+		return -ENODEV;
+	}
+
+	if (!lpc_bridge) {
+		/* Fist use of the backend */
+		dprintk("Try to init cdimode\n");
+		mutex_init(&io_op->backend->mutex);
+		mutex_lock(&io_op->backend->mutex);
+		kref_init(&io_op->backend->kref);
+
+		/* PCI probing: find the LPC Super I/O bridge PCI device */
+		for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i)
+			lpc_bridge =
+			    pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device,
+					   NULL);
+
+		if (!lpc_bridge) {
+			printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n");
+			retval = -ENODEV;
+			goto error1;
+		}
+
+		if ((retval = pci_enable_device(lpc_bridge))) {
+			printk(O_ERR "Unable to enable PCI device.\n");
+			goto error2;
+		}
+
+		switch (lpc_bridge->vendor) {
+		case PCI_VENDOR_ID_INTEL:
+			ioport_base = INTEL_IOPORT_BASE;
+			break;
+		case PCI_VENDOR_ID_ATI:
+			ioport_base = ATI_IOPORT_BASE;
+			break;
+		default:
+			BUG();
+		}
+
+		if (!request_region(ioport_base, 4, OMNIBOOK_MODULE_NAME)) {
+			printk(O_ERR "Request I/O region error\n");
+			retval = -ENODEV;
+			goto error2;
+		}
+
+		/*
+		 * Make an enable-check disable cycle for testing purpose
+		 */
+
+		retval = enable_cdimode();
+		if (retval)
+			goto error3;
+
+		clear_cdimode();
+		clear_cdimode_pci();
+
+		dprintk("Cdimode init ok\n");
+		mutex_unlock(&io_op->backend->mutex);
+		return 0;
+	} else {
+		dprintk("Cdimode has already been initialized\n");
+		kref_get(&io_op->backend->kref);
+		return 0;
+	}
+
+      error3:
+	clear_cdimode_pci();
+	release_region(ioport_base, 4);
+      error2:
+	pci_dev_put(lpc_bridge);
+	lpc_bridge = NULL;
+      error1:
+	io_op->backend->already_failed = 1;
+	mutex_unlock(&io_op->backend->mutex);
+	mutex_destroy(&io_op->backend->mutex);
+	return retval;
+}
+
+static void cdimode_free(struct kref *ref)
+{
+	struct omnibook_backend *backend;
+	
+	dprintk("Cdimode not used anymore: disposing\n");
+
+	backend = container_of(ref, struct omnibook_backend, kref);
+
+	mutex_lock(&backend->mutex);
+	pci_dev_put(lpc_bridge);
+	release_region(ioport_base, 4);
+	lpc_bridge = NULL;
+	mutex_unlock(&backend->mutex);
+	mutex_destroy(&backend->mutex);
+}
+
+static void omnibook_cdimode_exit(const struct omnibook_operation *io_op)
+{
+	/* ectypes other than TSM70 have no business with this backend */
+	BUG_ON(!(omnibook_ectype & (TSM70 | TSX205)));
+	dprintk("Trying to dispose cdimode\n");
+	kref_put(&io_op->backend->kref, cdimode_free);
+}
+
+/* 
+ * Read EC index and write result to value 
+ * 'EC index' here is unrelated to an index in the EC registers
+ */
+static int omnibook_cdimode_read(const struct omnibook_operation *io_op, u8 * value)
+{
+	int retval = 0;
+
+	if (!lpc_bridge)
+		return -ENODEV;
+
+	retval = enable_cdimode();
+	if (retval)
+		goto out;
+	retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->read_addr);
+	if (retval)
+		goto error;
+	retval = read_ec_cmd(0xfbfe, value);
+
+	if (io_op->read_mask)
+		*value &= io_op->read_mask;
+
+      error:
+	clear_cdimode();
+      out:
+	clear_cdimode_pci();
+	return retval;
+}
+
+/* 
+ * Write value 
+ * 'EC index' here is unrelated to an index in the EC registers
+ */
+static int omnibook_cdimode_write(const struct omnibook_operation *io_op, u8 value)
+{
+	int retval = 0;
+
+	if (!lpc_bridge)
+		return -ENODEV;
+
+	retval = enable_cdimode();
+	if (retval)
+		goto out;
+	retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->write_addr);
+	if (retval)
+		goto error;
+	retval = send_ec_cmd(0xfbfe, value);
+      error:
+	clear_cdimode();
+      out:
+	clear_cdimode_pci();
+	return retval;
+
+}
+
+/*
+ * Fn+foo and multimedia hotkeys handling
+ */
+static int omnibook_cdimode_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval;
+
+	struct omnibook_operation hotkeys_op = 
+		{ CDI, 0, TSM70_FN_INDEX, 0, TSM70_FN_ENABLE, TSM70_FN_DISABLE};
+
+	/* Fn+foo handling */
+	retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_FN));
+	if (retval < 0)
+		return retval;
+
+	/* Multimedia keys handling */
+	hotkeys_op.write_addr = TSM70_HOTKEYS_INDEX;
+	hotkeys_op.on_mask = TSM70_HOTKEYS_ENABLE;
+	hotkeys_op.off_mask = TSM70_HOTKEYS_DISABLE;
+	retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_MULTIMEDIA));
+
+	return retval;
+}
+
+/* Scan index space, this hard locks my machine */
+#if 0
+static int compal_scan(char *buffer)
+{
+	int len = 0;
+	int i, j;
+	u8 v;
+
+	for (i = 0; i < 255; i += 16) {
+		for (j = 0; j < 16; j++) {
+			omnibook_compal_read(i + j, &v);
+			len += sprintf(buffer + len, "Read index %02x: %02x\n", i + j, v);
+			mdelay(500);
+		}
+		if (j != 16)
+			break;
+	}
+
+	return len;
+}
+#endif
+
+struct omnibook_backend compal_backend = {
+	.name = "compal",
+	.hotkeys_write_cap = HKEY_MULTIMEDIA | HKEY_FN,
+	.init = omnibook_cdimode_init,
+	.exit = omnibook_cdimode_exit,
+	.byte_read = omnibook_cdimode_read,
+	.byte_write = omnibook_cdimode_write,
+	.hotkeys_set = omnibook_cdimode_hotkeys,
+};
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/nbsmi.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/nbsmi.c
@@ -0,0 +1,968 @@
+/*
+ * nbsmi.c -- Toshiba SMI low-level acces code
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ * Sources of inspirations for this code were:
+ * -Toshiba via provided hardware specification
+ * -Thorsten Zachmann with the 's1bl' project
+ * -Frederico Munoz with the 'tecra_acpi' project
+ * Thanks to them
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+#include <linux/preempt.h>
+#include <linux/pci.h>
+#include <linux/kref.h>
+#include <asm/io.h>
+#include <asm/mc146818rtc.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+/* copied from drivers/input/serio/i8042-io.h */
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+
+/*
+ * ATI's IXP PCI-LPC bridge
+ */
+#define INTEL_PMBASE	0x40
+#define INTEL_GPE0_EN	0x2c
+
+#define BUFFER_SIZE	0x20
+#define INTEL_OFFSET	0x60
+#define	INTEL_SMI_PORT	0xb2	/* APM_CNT port in INTEL ICH specs */
+
+/*
+ * Toshiba Specs state 0xef here but:
+ * -this would overflow (ef + 19 > ff)
+ * -code from Toshiba use e0, which make much more sense
+ */
+
+#define ATI_OFFSET	0xe0
+#define	ATI_SMI_PORT	0xb0
+
+#define	EC_INDEX_PORT	0x300
+#define EC_DATA_PORT	0x301
+
+/* Masks decode for GetAeral */
+#define WLEX_MASK 	0x4
+#define WLAT_MASK	0x8
+#define BTEX_MASK	0x1
+#define BTAT_MASK	0x2
+
+/*
+ * Private data of this backend
+ */
+struct nbsmi_backend_data {
+	struct pci_dev *lpc_bridge;	/* Southbridge chip ISA bridge/LPC interface PCI device */
+	u8 start_offset;		/* Start offset in CMOS memory */
+	struct input_dev *nbsmi_input_dev;
+	struct work_struct fnkey_work;
+};
+
+/*
+ * Possible list of supported southbridges
+ * Here mostly to implement a more or less clean PCI probing
+ * Works only because of previous DMI probing.
+ * It's in compal.c
+ */
+extern const struct pci_device_id lpc_bridge_table[];
+
+/*
+ * Since we are going to trigger an SMI, all registers (I assume this does not
+ * include esp and maybe ebp) and eflags may be mangled in the
+ * process. 
+ * We also disable preemtion and IRQs upon SMI call.
+ */
+static inline u32 ati_do_smi_call(u16 function)
+{
+	unsigned long flags;
+	u32 retval = 0;
+
+	local_irq_save(flags);
+	preempt_disable();
+	
+/*
+ * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT
+ * thus the clobber list.
+ *
+ * Equivalent pseudocode:
+ *
+ * eax = function; [non null]
+ * outw(eax, ATI_SMI_PORT); <- This Trigger an SMI
+ * if( eax == 0 ) [success if eax has been cleared]
+ * 	goto out;
+ * if( inb(ATI_SMI_PORT + 1) == 0) [if not in eax, success maybe be stored here]
+ *	goto out;
+ * retval = -EIO; [too bad]
+ * out:
+ */
+	__asm__ __volatile__("outw  %%ax, %2;	\
+			      orw %%ax, %%ax;	\
+			      jz 1f;		\
+			      inw %3, %%ax;	\
+			      orw %%ax, %%ax;	\
+			      jz 1f;		\
+			      movl %4, %0;	\
+			      1:;"
+			     : "=m" (retval)
+			     : "a"(function), "N"(ATI_SMI_PORT), "N"(ATI_SMI_PORT+1), "i"(-EIO)
+			     : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc");
+
+	local_irq_restore(flags);
+	preempt_enable_no_resched();
+	return retval;
+}
+
+static inline u32 intel_do_smi_call(u16 function, struct pci_dev *lpc_bridge)
+{
+	u32 state;
+	unsigned long flags;
+	u32 retval = 0;
+	u32 sci_en = 0;
+
+	local_irq_save(flags);
+	preempt_disable();
+
+/* 
+ * We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space )
+ * And we access offset 2c (GPE0_EN), save the state, disable all SCI
+ * and restore the state after the SMI call
+ */			
+	pci_read_config_dword(lpc_bridge, INTEL_PMBASE, &sci_en);
+	sci_en = sci_en & 0xff80; /* Keep bits 15:7 */
+	sci_en += INTEL_GPE0_EN;  /* GPEO_EN offset */
+	state = inl(sci_en);
+	outl(0, sci_en);
+
+/*
+ * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT
+ * thus the clobber list.
+ *
+ * Equivalent pseudocode:
+ *
+ * eax = function; [non null]
+ * outw(eax, INTEL_SMI_PORT); <- This Trigger an SMI
+ * if( eax == 0 ) [success if eax has been cleared]
+ * 	goto out; 
+ * retval = -EIO; [too bad]
+ * out:
+ */
+	__asm__ __volatile__("outw %%ax, %2;	\
+			      orw %%ax, %%ax;	\
+			      jz 1f;		\
+			      movl %3, %0;	\
+			      1:;"
+			     : "=m" (retval)
+			     : "a"(function), "N"(INTEL_SMI_PORT), "i"(-EIO)
+			     : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc");
+
+	outl(state, sci_en);
+	local_irq_restore(flags);
+	preempt_enable_no_resched();
+	return retval;
+}
+
+static int nbsmi_smi_command(u16 function, 
+			     const u8 * inputbuffer,
+			     u8 * outputbuffer,
+			     const struct nbsmi_backend_data *priv_data)
+{
+	int count;
+	u32 retval = 0;
+	
+
+	for (count = 0; count < BUFFER_SIZE; count++) {
+		outb(count + priv_data->start_offset, RTC_PORT(2));
+		outb(*(inputbuffer + count), RTC_PORT(3));
+	}
+
+/* 
+ * We have to write 0xe4XX to smi_port
+ * where XX is the SMI function code
+ */
+	function = (function & 0xff) << 8;
+	function |= 0xe4;
+
+	switch (priv_data->lpc_bridge->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		retval = intel_do_smi_call(function, priv_data->lpc_bridge);
+		break;
+	case PCI_VENDOR_ID_ATI:
+		retval = ati_do_smi_call(function);
+		break;
+	default:
+		BUG();
+	}
+
+	if (retval)
+		printk(O_ERR "smi_command failed with error %u.\n", retval);
+
+	for (count = 0; count < BUFFER_SIZE; count++) {
+		outb(count + priv_data->start_offset, RTC_PORT(2));
+		*(outputbuffer + count) = inb(RTC_PORT(3));
+	}
+
+	return retval;
+}
+
+static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 * data)
+{
+	int retval;
+	u8 *inputbuffer;
+	u8 *outputbuffer;
+	struct nbsmi_backend_data *priv_data = io_op->backend->data;
+
+	if (!priv_data)
+		return -ENODEV;
+
+	inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
+	if (!inputbuffer) {
+		retval = -ENOMEM;
+		goto error1;
+	}
+
+	outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
+	if (!outputbuffer) {
+		retval = -ENOMEM;
+		goto error2;
+	}
+
+	retval = nbsmi_smi_command((u16) io_op->read_addr, inputbuffer, outputbuffer, priv_data);
+	if (retval)
+		goto out;
+
+	*data = outputbuffer[0];
+
+	if (io_op->read_mask)
+		*data &= io_op->read_mask;
+
+      out:
+	kfree(outputbuffer);
+      error2:
+	kfree(inputbuffer);
+      error1:
+	return retval;
+}
+
+static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 data)
+{
+	int retval;
+	u8 *inputbuffer;
+	u8 *outputbuffer;
+	struct nbsmi_backend_data *priv_data = io_op->backend->data;
+
+	if (!priv_data)
+		return -ENODEV;
+
+	inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
+	if (!inputbuffer) {
+		retval = -ENOMEM;
+		goto error1;
+	}
+
+	outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL);
+	if (!outputbuffer) {
+		retval = -ENOMEM;
+		goto error2;
+	}
+
+	inputbuffer[0] = data;
+
+	retval = nbsmi_smi_command((u16) io_op->write_addr, inputbuffer, outputbuffer, priv_data);
+
+	kfree(outputbuffer);
+      error2:
+	kfree(inputbuffer);
+      error1:
+	return retval;
+}
+
+/*
+ * Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers)
+ */
+static inline void nbsmi_ec_read_command(u8 index, u8 * data)
+{
+	outb(index, EC_INDEX_PORT);
+	*data = inb(EC_DATA_PORT);
+}
+
+#if 0
+static inline void nbsmi_ec_write_command(u8 index, u8 data)
+{
+	outb(index, EC_INDEX_PORT);
+	outb(data, EC_DATA_PORT);
+}
+#endif
+
+
+/*
+ * Hotkeys workflow:
+ * 1. Fn+Foo pressed
+ * 2. Scancode 0x6d generated by kbd controller
+ * 3. Scancode 0x6d caught by omnibook input handler
+ * 4. SMI Call issued -> Got keycode of last actually pressed Fn key
+ * 5. nbsmi_scan_table used to associate a detected keycode with a generated one
+ * 6. Generated keycode issued using the omnibook input device
+ */
+
+/*
+ * The input handler should only bind with the standard AT keyboard.
+ * XXX: Scancode 0x6d won't be detected if the keyboard has already been
+ * grabbed (the Xorg event input driver do that)
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+static int hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 const struct input_device_id *id)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static struct input_handle *hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 const struct input_device_id *id)
+#else
+static struct input_handle *hook_connect(struct input_handler *handler,
+					 struct input_dev *dev,
+					 struct input_device_id *id)
+#endif
+{
+	struct input_handle *handle;
+	int error;
+
+	/* the 0x0001 vendor magic number is found in atkbd.c */
+	if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001))
+		goto out_nobind;
+
+	if(!strstr(dev->phys, I8042_KBD_PHYS_DESC))
+		goto out_nobind;
+
+	dprintk("hook_connect for device %s.\n", dev->name);
+
+	if(dev->grab)
+		printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n",
+			dev->grab->name);
+
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+		return -ENOMEM;
+#else
+		return NULL;
+#endif
+
+	handle->dev = dev;
+	handle->handler = handler;
+	handle->name = "omnibook_scancode_hook";
+	handle->private = handler->private;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	error = input_register_handle(handle);
+	if (error) {
+		dprintk("register_handle failed\n");
+		goto out_nobind_free;
+	} 
+	error = input_open_device(handle);
+	if (error) {
+		dprintk("register_handle failed\n");
+		input_unregister_handle(handle);
+		goto out_nobind_free;
+	} 
+	
+#else
+	error = input_open_device(handle);
+	if (error==0) dprintk("Input device opened\n");
+	else { 
+		dprintk("opening input device failed\n");
+		goto out_nobind_free;
+	}
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	return 0;
+out_nobind_free:
+	kfree(handle);
+out_nobind:
+	return -ENODEV;
+#else
+	return handle;
+out_nobind_free:
+	kfree(handle);
+out_nobind:
+	return NULL;
+#endif	
+}
+
+static void hook_disconnect(struct input_handle *handle)
+{
+	dprintk("hook_disconnect.\n");
+	input_close_device(handle);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21))
+	input_unregister_handle(handle);
+#endif
+	kfree(handle);
+}
+
+/*
+ * Hook for scancode 0x6d. Actual handling is done in a workqueue as 
+ * the nbsmi backend might sleep.
+ */
+
+static void hook_event(struct input_handle *handle, unsigned int event_type,
+		      unsigned int event_code, int value)
+{
+	if (event_type == EV_MSC && event_code == MSC_SCAN && value == SMI_FN_SCAN)
+		schedule_work(&((struct nbsmi_backend_data *)handle->private)->fnkey_work);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+static const struct input_device_id hook_ids[] = {
+#else
+static struct input_device_id hook_ids[] = {
+#endif
+	{
+                .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+                .evbit = { BIT(EV_KEY) },
+        },
+	{ },    /* Terminating entry */
+};
+
+static struct input_handler hook_handler = {
+	.event		= hook_event,
+	.connect	= hook_connect,
+	.disconnect	= hook_disconnect,
+	.name		= OMNIBOOK_MODULE_NAME,
+	.id_table	= hook_ids,
+};
+
+/*
+ * Define some KEY_ that may be missing in input.h for some kernel versions
+ */
+#ifndef KEY_WLAN
+#define KEY_WLAN 238
+#endif 
+
+/*
+ * Detected scancode to keycode table
+ */
+static const struct {
+	unsigned int scancode;
+	unsigned int keycode;
+} nbsmi_scan_table[] = {
+	{ KEY_ESC, KEY_MUTE},
+	{ KEY_F1, KEY_FN_F1},
+	{ KEY_F2, KEY_PROG1},
+	{ KEY_F3, KEY_SLEEP},
+	{ KEY_F4, KEY_SUSPEND},
+	{ KEY_F5, KEY_SWITCHVIDEOMODE},
+	{ KEY_F6, KEY_BRIGHTNESSDOWN},
+	{ KEY_F7, KEY_BRIGHTNESSUP},
+	{ KEY_F8, KEY_WLAN},
+	{ KEY_F9, KEY_FN_F9},
+	{ KEY_SPACE, KEY_ZOOM},
+	{ 0,0},
+};
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work);
+#else
+static void omnibook_handle_fnkey(void* data);
+#endif
+
+/*
+ * Register the input handler and the input device in the input subsystem
+ */
+static int register_input_subsystem(struct nbsmi_backend_data *priv_data)
+{
+	int i, retval = 0;
+	struct input_dev *nbsmi_input_dev;
+
+	nbsmi_input_dev = input_allocate_device();
+	if (!nbsmi_input_dev) {
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	nbsmi_input_dev->name = "Omnibook NbSMI scancode generator";
+	nbsmi_input_dev->phys = "omnibook/input0";
+	nbsmi_input_dev->id.bustype = BUS_HOST;
+	
+	set_bit(EV_KEY, nbsmi_input_dev->evbit);
+	
+	for(i=0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++)
+		set_bit(nbsmi_scan_table[i].keycode, nbsmi_input_dev->keybit);
+
+	retval = input_register_device(nbsmi_input_dev);
+	if(retval) {
+		input_free_device(nbsmi_input_dev);
+		goto out;
+	}
+
+	priv_data->nbsmi_input_dev = nbsmi_input_dev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+	INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey);
+#else
+	INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data);
+#endif
+
+
+	hook_handler.private = priv_data;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+	retval = input_register_handler(&hook_handler);	
+#else
+	input_register_handler(&hook_handler);
+#endif
+
+	out:	
+	return retval;
+}
+
+/*
+ * Try to init the backend
+ * This function can be called blindly as it use a kref
+ * to check if the init sequence was already done.
+ */
+static int omnibook_nbsmi_init(const struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	int i;
+	u8 ec_data;
+	u32 smi_port = 0;
+	struct nbsmi_backend_data *priv_data;
+
+	/* ectypes other than TSM40 have no business with this backend */
+	if (!(omnibook_ectype & TSM40))
+		return -ENODEV;
+
+	if (io_op->backend->already_failed) {
+		dprintk("NbSmi backend init already failed, skipping.\n");
+		return -ENODEV;
+	}
+
+	if (!io_op->backend->data) {
+		/* Fist use of the backend */
+		dprintk("Try to init NbSmi\n");
+		mutex_init(&io_op->backend->mutex);
+		mutex_lock(&io_op->backend->mutex);
+		kref_init(&io_op->backend->kref);
+
+		priv_data = kzalloc(sizeof(struct nbsmi_backend_data), GFP_KERNEL);
+		if (!priv_data) {
+			retval = -ENOMEM;
+			goto error0;
+		}
+
+		/* PCI probing: find the LPC Super I/O bridge PCI device */
+		for (i = 0; !priv_data->lpc_bridge && lpc_bridge_table[i].vendor; ++i)
+			priv_data->lpc_bridge =
+			    pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device,
+					   NULL);
+
+		if (!priv_data->lpc_bridge) {
+			printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n");
+			retval = -ENODEV;
+			goto error1;
+		}
+
+		if ((retval = pci_enable_device(priv_data->lpc_bridge))) {
+			printk(O_ERR "Unable to enable PCI device.\n");
+			goto error2;
+		}
+
+		switch (priv_data->lpc_bridge->vendor) {
+		case PCI_VENDOR_ID_INTEL:
+			priv_data->start_offset = INTEL_OFFSET;
+			smi_port = INTEL_SMI_PORT;
+			break;
+		case PCI_VENDOR_ID_ATI:
+			priv_data->start_offset = ATI_OFFSET;
+			smi_port = ATI_SMI_PORT;
+			break;
+		default:
+			BUG();
+		}
+
+		if (!request_region(smi_port, 2, OMNIBOOK_MODULE_NAME)) {
+			printk(O_ERR "Request SMI I/O region error\n");
+			retval = -ENODEV;
+			goto error2;
+		}
+
+		if (!request_region(EC_INDEX_PORT, 2, OMNIBOOK_MODULE_NAME)) {
+			printk(O_ERR "Request EC I/O region error\n");
+			retval = -ENODEV;
+			goto error3;
+		}
+
+		/*
+		 * Try some heuristic tests to avoid enabling this interface on unsuported laptops:
+		 * See what a port 300h read index 8f gives. Guess there is nothing if read 0xff
+		 */
+
+		nbsmi_ec_read_command(SMI_FN_PRESSED, &ec_data);
+		dprintk("NbSmi test probe read: %x\n", ec_data);
+		if (ec_data == 0xff) {
+			printk(O_ERR "Probing at SMSC Mailbox registers failed, disabling NbSmi\n");
+			retval = -ENODEV;
+			goto error4;
+		}
+
+		retval = register_input_subsystem(priv_data);
+		if(retval)
+			goto error4;
+
+		io_op->backend->data = priv_data;
+
+		dprintk("NbSmi init ok\n");
+		mutex_unlock(&io_op->backend->mutex);
+		return 0;
+	} else {
+		dprintk("NbSmi has already been initialized\n");
+		kref_get(&io_op->backend->kref);
+		return 0;
+	}
+      error4:
+	release_region(EC_INDEX_PORT, 2);
+      error3:
+	release_region(smi_port, 2);
+      error2:
+	pci_dev_put(priv_data->lpc_bridge);
+      error1:
+	kfree(priv_data);
+	io_op->backend->data = NULL;
+      error0:
+	io_op->backend->already_failed = 1;
+	mutex_unlock(&io_op->backend->mutex);
+	mutex_destroy(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Free all allocated stuff and unregister from the input subsystem
+ */
+static void nbsmi_free(struct kref *ref)
+{
+	u32 smi_port = 0;
+	struct omnibook_backend *backend;
+	struct nbsmi_backend_data *priv_data;
+
+	dprintk("NbSmi not used anymore: disposing\n");
+
+	backend = container_of(ref, struct omnibook_backend, kref);
+	priv_data = backend->data;
+
+	flush_scheduled_work();
+	input_unregister_handler(&hook_handler);
+	input_unregister_device(priv_data->nbsmi_input_dev);
+
+	mutex_lock(&backend->mutex);
+
+	switch (priv_data->lpc_bridge->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		smi_port = INTEL_SMI_PORT;
+		break;
+	case PCI_VENDOR_ID_ATI:
+		smi_port = ATI_SMI_PORT;
+		break;
+	default:
+		BUG();
+	}
+
+	pci_dev_put(priv_data->lpc_bridge);
+	release_region(smi_port, 2);
+	release_region(EC_INDEX_PORT, 2);
+	kfree(priv_data);
+	backend->data = NULL;
+	mutex_unlock(&backend->mutex);
+	mutex_destroy(&backend->mutex);
+}
+
+static void omnibook_nbsmi_exit(const struct omnibook_operation *io_op)
+{
+	/* ectypes other than TSM40 have no business with this backend */
+	BUG_ON(!(omnibook_ectype & TSM40));
+	dprintk("Trying to dispose NbSmi\n");
+	kref_put(&io_op->backend->kref, nbsmi_free);
+}
+
+/*
+ * Adjust the lcd backlight level by delta.
+ * Used for Fn+F6/F7 keypress
+ */
+static int adjust_brighness(int delta)
+{
+	struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd");
+	struct omnibook_operation *io_op;
+	int retval = 0;
+	u8 brgt;
+
+	if(!lcd_feature)
+		return -ENODEV;
+
+	io_op = lcd_feature->io_op;
+
+	mutex_lock(&io_op->backend->mutex);
+
+	if(( retval = __backend_byte_read(io_op, &brgt)))
+		goto out;	
+
+	dprintk("FnF6/F7 pressed: adjusting britghtnes.\n");
+
+	if (((int) brgt + delta) < 0)
+		brgt = 0;
+	else if ((brgt + delta) > omnibook_max_brightness)
+		brgt = omnibook_max_brightness;
+	else
+		brgt += delta;
+
+	retval = __backend_byte_write(io_op, brgt);
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static const struct omnibook_operation last_scan_op = SIMPLE_BYTE(SMI,SMI_GET_FN_LAST_SCAN,0);
+
+/*
+ * Workqueue handler for Fn hotkeys
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+static void omnibook_handle_fnkey(struct work_struct *work)
+#else
+static void omnibook_handle_fnkey(void* data)
+#endif
+{
+	int i;
+	u8 gen_scan;
+	struct input_dev *input_dev;
+
+	if(backend_byte_read(&last_scan_op, &gen_scan))
+		return;
+
+	dprintk("detected scancode %x.\n", gen_scan);
+	switch(gen_scan) {
+	case KEY_F6:
+		adjust_brighness(-1);
+		break;
+	case KEY_F7:
+		adjust_brighness(+1);
+		break;
+	}
+
+	for(i = 0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) {
+		if( gen_scan == nbsmi_scan_table[i].scancode) {
+			dprintk("generating keycode %i.\n", nbsmi_scan_table[i].keycode);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19))
+			input_dev = container_of(work, struct nbsmi_backend_data, fnkey_work)->nbsmi_input_dev;
+#else
+			input_dev = ((struct nbsmi_backend_data *) data)->nbsmi_input_dev;
+#endif
+			omnibook_report_key(input_dev, nbsmi_scan_table[i].keycode);
+			break;
+		}
+	}
+}
+
+static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval = 0;
+	struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_GET_KILL_SWITCH, 0);
+	u8 data;
+
+	if ((retval = nbsmi_smi_read_command(&aerial_op, &data)))
+		goto out;
+
+	dprintk("get_wireless (kill switch) raw_state: %x\n", data);
+
+	*state = data ? KILLSWITCH : 0;
+
+	aerial_op.read_addr = SMI_GET_AERIAL;
+
+	if ((retval = nbsmi_smi_read_command(&aerial_op, &data)))
+		goto out;
+
+	dprintk("get_wireless (aerial) raw_state: %x\n", data);
+
+	*state |= (data & WLEX_MASK) ? WIFI_EX : 0;
+	*state |= (data & WLAT_MASK) ? WIFI_STA : 0;
+	*state |= (data & BTEX_MASK) ? BT_EX : 0;
+	*state |= (data & BTAT_MASK) ? BT_STA : 0;
+
+      out:
+	return retval;
+}
+
+static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval = 0;
+	u8 data;
+	struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_SET_AERIAL, 0);
+
+	data = !!(state & BT_STA);
+	data |= !!(state & WIFI_STA) << 0x1;
+
+	dprintk("set_wireless raw_state: %x\n", data);
+
+	retval = nbsmi_smi_write_command(&aerial_op, data);
+
+	return retval;
+}
+
+static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval;
+	u8 data = 0;
+	struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_GET_FN_INTERFACE, 0);
+
+	retval = nbsmi_smi_read_command(&hotkeys_op, &data);
+	if (retval < 0)
+		return retval;
+
+	dprintk("get_hotkeys raw_state: %x\n", data);
+
+	*state = (data & SMI_FN_KEYS_MASK) ? HKEY_FN : 0;
+	*state |= (data & SMI_STICK_KEYS_MASK) ? HKEY_STICK : 0;
+	*state |= (data & SMI_FN_TWICE_LOCK_MASK) ? HKEY_TWICE_LOCK : 0;
+	*state |= (data & SMI_FN_DOCK_MASK) ? HKEY_DOCK : 0;
+
+	return 0;
+}
+
+
+static int omnibook_nbmsi_hotkeys_set(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int i, retval;
+	u8 data, rdata;
+	struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_SET_FN_F5_INTERFACE, 0);	
+	u8* data_array;
+
+	data = !!(state & HKEY_FNF5);
+
+	dprintk("set_hotkeys (Fn F5) raw_state: %x\n", data);
+
+	retval = nbsmi_smi_write_command(&hotkeys_op, data);
+	if (retval < 0)
+		return retval;
+
+	hotkeys_op.write_addr = SMI_SET_FN_INTERFACE;
+	hotkeys_op.read_addr =	SMI_GET_FN_INTERFACE;
+
+	data = (state & HKEY_FN) ? SMI_FN_KEYS_MASK : 0;
+	data |= (state & HKEY_STICK) ? SMI_STICK_KEYS_MASK : 0;
+	data |= (state & HKEY_TWICE_LOCK) ? SMI_FN_TWICE_LOCK_MASK : 0;
+	data |= (state & HKEY_DOCK) ? SMI_FN_DOCK_MASK : 0;
+
+	dprintk("set_hotkeys (Fn interface) raw_state: %x\n", data);
+
+	/*
+	 * Hardware seems to be quite stubborn and multiple retries may be
+	 * required. The criteria here is simple: retry until probed state match
+	 * the requested one (with timeout).
+	 */
+
+	data_array = kcalloc(250, sizeof(u8), GFP_KERNEL);
+	if(!data_array)
+		return -ENODEV;
+
+	for (i = 0; i < 250; i++) {
+		retval = nbsmi_smi_write_command(&hotkeys_op, data);
+		if (retval)
+			goto out;
+		mdelay(1);
+		retval = nbsmi_smi_read_command(&hotkeys_op, &rdata);
+		if(retval)
+			goto out;
+		data_array[i] = rdata;
+		if(rdata == data) {
+			dprintk("check loop ok after %i iters\n.",i);
+			retval = 0;
+			goto out;
+		}
+	}
+	dprintk("error or check loop timeout !!\n");
+	dprintk("forensics datas: ");
+	for (i = 0; i < 250; i++)
+		dprintk_simple("%x ", data_array[i]);
+	dprintk_simple("\n");
+out:
+	kfree(data_array);
+	return retval;
+}
+
+static const unsigned int nbsmi_display_mode_list[] = {
+	DISPLAY_LCD_ON,
+	DISPLAY_LCD_ON | DISPLAY_CRT_ON,
+	DISPLAY_CRT_ON,
+	DISPLAY_LCD_ON | DISPLAY_TVO_ON,
+	DISPLAY_TVO_ON,
+};
+
+static int omnibook_nbmsi_display_get(const struct omnibook_operation *io_op, unsigned int *state)
+{
+	int retval = 0;
+	u8 data;
+
+	retval = nbsmi_smi_read_command(io_op, &data);
+	if (retval < 0)
+		return retval;
+
+	if (data > (ARRAY_SIZE(nbsmi_display_mode_list) - 1))
+		return -EIO;
+
+	*state = nbsmi_display_mode_list[data];
+
+	return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON;
+}
+
+static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval;
+	int i;
+	u8 matched = 255;
+
+	for (i = 0; i < ARRAY_SIZE(nbsmi_display_mode_list); i++) {
+		if (nbsmi_display_mode_list[i] == state) {
+			matched = i;
+			break;
+		}
+	}
+
+	if(matched == 255) {
+		printk(O_ERR "Display mode %x is unsupported.\n", state);
+		return -EINVAL;
+	}
+
+	retval = nbsmi_smi_write_command(io_op, matched);
+	if (retval < 0)
+		return retval;
+
+	return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON;
+}
+
+struct omnibook_backend nbsmi_backend = {
+	.name = "nbsmi",
+	.hotkeys_read_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK,
+	.hotkeys_write_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK | HKEY_FNF5,
+	.init = omnibook_nbsmi_init,
+	.exit = omnibook_nbsmi_exit,
+	.byte_read = nbsmi_smi_read_command,
+	.byte_write = nbsmi_smi_write_command,
+	.aerial_get = omnibook_nbsmi_get_wireless,
+	.aerial_set = omnibook_nbsmi_set_wireless,
+	.hotkeys_get = omnibook_nbmsi_hotkeys_get,
+	.hotkeys_set = omnibook_nbmsi_hotkeys_set,
+	.display_get = omnibook_nbmsi_display_get,
+	.display_set = omnibook_nbmsi_display_set,
+};
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/fan_policy.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/fan_policy.c
@@ -0,0 +1,188 @@
+/*
+ * fan_policy.c -- fan policy support
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/ctype.h>
+#include "hardware.h"
+
+/*
+ * Default temperature limits.
+ * Danger! You may overheat your CPU!
+ * Do not change these values unless you exactly know what you do.
+ */
+
+#define OMNIBOOK_FAN_LEVELS			8
+#define OMNIBOOK_FAN_MIN			25	/* Minimal value of fan off temperature */
+#define OMNIBOOK_FOT_MAX			75	/* Maximal value of fan off temperature */
+#define OMNIBOOK_FAN_MAX			95	/* Maximal value of fan on temperature */
+#define OMNIBOOK_FOT_DEFAULT			60	/* Default value of fan off temperature */
+#define OMNIBOOK_FAN1_DEFAULT			75	/* Default value of fan on temperature */
+#define OMNIBOOK_FAN2_DEFAULT			85	/* Default value of fan level 2 temperature */
+#define OMNIBOOK_FAN3_DEFAULT			90	/* Default value of fan level 3 temperature */
+#define OMNIBOOK_FAN4_DEFAULT			95	/* Default value of fan level 4 temperature */
+#define OMNIBOOK_FAN5_DEFAULT			95	/* Default value of fan level 5 temperature */
+#define OMNIBOOK_FAN6_DEFAULT			95	/* Default value of fan level 6 temperature */
+#define OMNIBOOK_FAN7_DEFAULT			95	/* Default value of fan level 7 temperature */
+
+static const u8 fan_defaults[] = {
+		OMNIBOOK_FOT_DEFAULT,
+		OMNIBOOK_FAN1_DEFAULT,
+		OMNIBOOK_FAN2_DEFAULT,
+		OMNIBOOK_FAN3_DEFAULT,
+		OMNIBOOK_FAN4_DEFAULT,
+		OMNIBOOK_FAN5_DEFAULT,
+		OMNIBOOK_FAN6_DEFAULT,
+		OMNIBOOK_FAN7_DEFAULT,
+};
+
+static int omnibook_get_fan_policy(struct omnibook_operation *io_op, u8 *fan_policy)
+{
+	int retval ;
+	int i;
+
+	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+		io_op->read_addr = XE3GF_FOT + i;
+		if ((retval = __backend_byte_read(io_op, &fan_policy[i])))
+			return retval;
+	}
+
+	return 0;
+}
+
+static int omnibook_set_fan_policy(struct omnibook_operation *io_op, const u8 *fan_policy)
+{
+	int retval;
+	int i;
+
+	if (fan_policy[0] > OMNIBOOK_FOT_MAX)
+		return -EINVAL;
+
+	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+		if ((fan_policy[i] > fan_policy[i + 1])
+		    || (fan_policy[i] < OMNIBOOK_FAN_MIN)
+		    || (fan_policy[i] > OMNIBOOK_FAN_MAX))
+			return -EINVAL;
+	}
+	for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) {
+		io_op->write_addr = XE3GF_FOT + i;
+		if ((retval = __backend_byte_write(io_op, fan_policy[i])))
+			return retval;
+	}
+
+	return 0;
+}
+
+static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+	int len = 0;
+	u8 i;
+	u8 fan_policy[OMNIBOOK_FAN_LEVELS];
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	retval = omnibook_get_fan_policy(io_op, &fan_policy[0]);
+
+	mutex_unlock(&io_op->backend->mutex);
+
+	if(retval)
+		return retval;
+
+	len += sprintf(buffer + len, "Fan off temperature:        %2d C\n", fan_policy[0]);
+	len += sprintf(buffer + len, "Fan on temperature:         %2d C\n", fan_policy[1]);
+	for (i = 2; i < OMNIBOOK_FAN_LEVELS; i++) {
+		len +=
+		    sprintf(buffer + len, "Fan level %1d temperature:    %2d C\n", i,
+			    fan_policy[i]);
+	}
+	len += sprintf(buffer + len, "Minimal temperature to set: %2d C\n", OMNIBOOK_FAN_MIN);
+	len += sprintf(buffer + len, "Maximal temperature to set: %2d C\n", OMNIBOOK_FAN_MAX);
+
+	return len;
+}
+
+static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int n = 0;
+	char *b;
+	char *endp;
+	int retval;
+	int temp;
+	u8 fan_policy[OMNIBOOK_FAN_LEVELS];
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	if ((retval = omnibook_get_fan_policy(io_op, &fan_policy[0])))
+		goto out;
+
+	/* 
+	 * Could also be done much simpler using sscanf(,"%u %u ... 
+	 * but this would hardcode OMNIBOOK_FAN_LEVELS.
+	 * The parsed format is "%u " repeated OMNIBOOK_FAN_LEVELS+1 times
+	 */
+
+	b = buffer;
+	do {
+		dprintk("n=[%i] b=[%s]\n", n, b);
+		if (n > OMNIBOOK_FAN_LEVELS) {
+			retval = -EINVAL;
+			goto out;
+		}
+		if (!isspace(*b)) {
+			temp = simple_strtoul(b, &endp, 10);
+			if (endp != b) {	/* there was a match */
+				fan_policy[n++] = temp;
+				b = endp;
+			} else {
+				retval = -EINVAL;
+				goto out;
+			}
+		} else
+			b++;
+	} while ((*b != '\0') && (*b != '\n'));
+
+	/* A zero value set the defaults */
+	if ((fan_policy[0] == 0) && (n == 1))
+		retval = omnibook_set_fan_policy(io_op, &fan_defaults[0]);
+	else
+		retval = omnibook_set_fan_policy(io_op, &fan_policy[0]);
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static struct omnibook_tbl fan_policy_table[] __initdata = {
+	{XE3GF, {EC,}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature fan_policy_driver = {
+	.name = "fan_policy",
+	.enabled = 1,
+	.read = omnibook_fan_policy_read,
+	.write = omnibook_fan_policy_write,
+	.ectypes = XE3GF,
+	.tbl = fan_policy_table,
+};
+
+module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/throttling.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/throttling.c
@@ -0,0 +1,83 @@
+/*
+ * throttling.c --CPU throttling control feature
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2007
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+/*
+ * Throttling level/rate mapping found in ICH6M datasheets
+ * the output is set to mimic the one of /proc/acpi/cpu/CPU0/throttling
+ * XXX: We always assume that there are 8 T-States and one processor.
+ */
+static const int trate[8] = { 0, 12, 25, 37, 50, 62, 75, 87 };
+
+static int omnibook_throttle_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int tstate = 0;
+	int retval, i;
+
+	retval = backend_throttle_get(io_op, &tstate);
+	if (retval < 0)
+		return retval;
+
+	len += sprintf(buffer + len, "state count:             8\n");
+        len += sprintf(buffer + len, "active state:            T%d\n", tstate);
+	for (i = 0; i < 8; i += 1)
+	{
+		len += sprintf(buffer + len, "   %cT%d:                  %02d%%\n",
+			(i == tstate ? '*' : ' '),
+			i,
+			trate[i]);
+	}
+
+	return len;
+}
+
+static int omnibook_throttle_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	int data;
+	char *endp;
+
+	data = simple_strtoul(buffer, &endp, 10);
+	if ((endp == buffer) || (data > 7)) /* There are 8 throttling levels */
+		return -EINVAL;
+	else
+		retval = backend_throttle_set(io_op, data);
+	
+	return retval;
+}
+
+
+static struct omnibook_tbl throttle_table[] __initdata = {
+	{TSM70 | TSX205, {ACPI,}},
+	{0,}
+};
+
+struct omnibook_feature __declared_feature throttle_driver = {
+	.name = "throttling",
+	.enabled = 1,
+	.read = omnibook_throttle_read,
+	.write = omnibook_throttle_write,
+	.ectypes = TSM70 | TSX205,
+	.tbl = throttle_table,
+};
+
+module_param_named(throttle, throttle_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(throttle, "Use 0 to disable, 1 to enable CPU throttling control");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/blank.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/blank.c
@@ -0,0 +1,138 @@
+/*
+ * blank.c -- blanking lcd console
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <asm/io.h>
+#include "hardware.h"
+
+static struct omnibook_feature blank_driver;
+
+/* 
+ * console_blank_hook pointer manipulation is lock protected
+ */
+extern int (*console_blank_hook) (int);
+static DEFINE_SPINLOCK(blank_spinlock);
+
+
+int omnibook_lcd_blank(int blank)
+{
+	struct omnibook_feature *blank_feature = omnibook_find_feature("blank");
+
+	if(!blank_feature)
+		return -ENODEV;
+
+	return omnibook_apply_write_mask(blank_feature->io_op, blank);
+}
+
+static int console_blank_register_hook(void)
+{
+	spin_lock(&blank_spinlock);
+	if (console_blank_hook != omnibook_lcd_blank) {
+		if (console_blank_hook == NULL) {
+			console_blank_hook = omnibook_lcd_blank;
+			printk(O_INFO "LCD backlight turn off at console blanking is enabled.\n");
+		} else 
+			printk(O_INFO "There is a console blanking solution already registered.\n");
+	}
+	spin_unlock(&blank_spinlock);
+	return 0;
+}
+
+static int console_blank_unregister_hook(void)
+{
+	int retval;
+	spin_lock(&blank_spinlock);
+	if (console_blank_hook == omnibook_lcd_blank) {
+		console_blank_hook = NULL;
+		printk(O_INFO "LCD backlight turn off at console blanking is disabled.\n");
+	} else if (console_blank_hook) {
+		printk(O_WARN "You can not disable another console blanking solution.\n");
+		retval = -EBUSY;
+	} else {
+		printk(O_INFO "Console blanking already disabled.\n");
+	}
+	spin_unlock(&blank_spinlock);
+	return retval;
+}
+
+static int omnibook_console_blank_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	spin_lock(&blank_spinlock);
+
+	len +=
+	    sprintf(buffer + len, "LCD console blanking hook is %s\n",
+		    (console_blank_hook == omnibook_lcd_blank) ? "enabled" : "disabled");
+
+	spin_unlock(&blank_spinlock);
+
+	return len;
+}
+
+static int omnibook_console_blank_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+
+	switch (*buffer) {
+	case '0':
+		retval = console_blank_unregister_hook();
+		break;
+	case '1':
+		retval = console_blank_register_hook();
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static int __init omnibook_console_blank_init(struct omnibook_operation *io_op)
+{	
+	return console_blank_register_hook();
+}
+
+static void __exit omnibook_console_blank_cleanup(struct omnibook_operation *io_op)
+{
+	console_blank_unregister_hook();
+}
+
+static struct omnibook_tbl blank_table[] __initdata = {
+	{TSM70 | TSX205, {CDI, 0, TSM100_BLANK_INDEX, 0, TSM100_LCD_OFF, TSM100_LCD_ON}},
+	{XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X,
+	 COMMAND(KBC, OMNIBOOK_KBC_CMD_LCD_OFF, OMNIBOOK_KBC_CMD_LCD_ON)},
+	{OB500 | OB6000 | XE2, {PIO, OB500_GPO1, OB500_GPO1, 0, -OB500_BKLT_MASK, OB500_BKLT_MASK}},
+	{OB510 | OB6100, {PIO, OB510_GPO2, OB510_GPO2, 0, -OB510_BKLT_MASK, OB510_BKLT_MASK}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature blank_driver = {
+	.name = "blank",
+	.enabled = 1,
+	.read = omnibook_console_blank_read,
+	.write = omnibook_console_blank_write,
+	.init = omnibook_console_blank_init,
+	.exit = omnibook_console_blank_cleanup,
+	.ectypes =
+	    XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X | TSX205,
+	.tbl = blank_table,
+};
+
+module_param_named(blank, blank_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(blank, "Use 0 to disable, 1 to enable lcd console blanking");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/compat.h
+++ linux-ec2-2.6.32/ubuntu/omnibook/compat.h
@@ -0,0 +1,71 @@
+/*
+ * compat.h -- Older kernel (=> 2.6.11) support 
+ * 
+ * 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, 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.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include <linux/version.h>
+
+/*
+ * For compatibility with kernel older than 2.6.16
+ * Mutex to Semaphore fallback
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+#include <asm/semaphore.h>
+#define DEFINE_MUTEX(lock)		DECLARE_MUTEX(lock)
+#define	mutex_init(lock)		init_MUTEX(lock)
+#define mutex_lock(lock)		down(lock)
+#define mutex_lock_interruptible(lock)	down_interruptible(lock)
+#define mutex_unlock(lock)		up(lock)
+#define mutex_destroy(lock)		do { } while(0)
+#else
+#include <linux/mutex.h>
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.14
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
+static void inline *kzalloc(size_t size, int flags)
+{
+	void *ret = kmalloc(size, flags);
+	if (ret)
+		memset(ret, 0, size);
+	return ret;
+}
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.11
+ */
+
+#ifndef DEFINE_SPINLOCK
+#define DEFINE_SPINLOCK(s)              spinlock_t s = SPIN_LOCK_UNLOCKED
+#endif
+
+/*
+ * Those kernel don't have ICH7 southbridge pcids
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+#define PCI_DEVICE_ID_INTEL_ICH7_0      0x27b8
+#define PCI_DEVICE_ID_INTEL_ICH7_1      0x27b9
+#define PCI_DEVICE_ID_INTEL_ICH7_30	0x27b0
+#define PCI_DEVICE_ID_INTEL_ICH7_31     0x27bd
+#endif
+
+
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/hotkeys.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/hotkeys.c
@@ -0,0 +1,193 @@
+/*
+ * hotkeys.c -- code to handling Hotkey/E-Key/EasyAccess buttons
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+/* Predefined convinient on/off states */
+#define HKEY_ON  HKEY_ONETOUCH|HKEY_MULTIMEDIA|HKEY_FN|HKEY_DOCK|HKEY_FNF5
+#define HKEY_OFF 0
+
+/*
+ * Set hotkeys status and update recorded saved state
+ */
+static int hotkeys_set_save(struct omnibook_operation *io_op, unsigned int state)
+{
+	int retval;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	retval = __backend_hotkeys_set(io_op, state);
+	if (retval < 0)
+		goto out;
+
+	/* Update saved state */
+	io_op->backend->hotkeys_state = state & io_op->backend->hotkeys_write_cap;
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Read hotkeys status, fallback to reading saved state if real probing is not
+ * supported.
+ */
+static int hotkeys_get_save(struct omnibook_operation *io_op, unsigned int *state)
+{
+	unsigned int read_state = 0;
+	int retval = 0;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+
+	if (io_op->backend->hotkeys_get)
+		retval = __backend_hotkeys_get(io_op, &read_state);
+	if (retval < 0)
+		goto out;
+
+	/* Return previously set state for the fields that are write only */
+	*state = (read_state & io_op->backend->hotkeys_read_cap) + 
+		 (io_op->backend->hotkeys_state & ~io_op->backend->hotkeys_read_cap);
+
+	out:
+	mutex_unlock(&io_op->backend->mutex);
+	return 0;
+}
+
+/*
+ * Power management handlers
+ */
+
+/*
+ * Restore previously saved state
+ */
+static int omnibook_hotkeys_resume(struct omnibook_operation *io_op)
+{
+	int retval;
+	mutex_lock(&io_op->backend->mutex);
+	retval = __backend_hotkeys_set(io_op, io_op->backend->hotkeys_state);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Disable hotkeys upon suspend (FIXME is the disabling required ?)
+ */
+static int omnibook_hotkeys_suspend(struct omnibook_operation *io_op)
+{
+	int retval = 0;
+	retval = backend_hotkeys_set(io_op, HKEY_OFF);
+	return retval;
+}
+
+static const char pretty_name[][27] = {
+	"Onetouch buttons are",
+	"Multimedia hotkeys are",
+	"Fn hotkeys are",
+	"Stick key is",
+	"Press Fn twice to lock is",
+	"Dock events are",
+	"Fn + F5 hotkey is",
+};
+
+static int omnibook_hotkeys_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int retval;
+	unsigned int read_state = 0; /* buggy gcc 4.1 warning fix */
+	unsigned int shift, mask;
+
+	retval = hotkeys_get_save(io_op, &read_state);
+
+	if (retval < 0)
+		return retval;
+
+	for (shift = 0; shift <= HKEY_LAST_SHIFT ; shift++) {
+		mask = 1 << shift;
+		/* we assume write capability or read capability imply support */
+		if ((io_op->backend->hotkeys_read_cap | io_op->backend->hotkeys_write_cap) & mask)
+			len +=
+			    sprintf(buffer + len, "%s %s.\n", pretty_name[shift],
+				    (read_state & mask) ? "enabled" : "disabled");
+	}
+
+	return len;
+}
+
+static int omnibook_hotkeys_write(char *buffer, struct omnibook_operation *io_op)
+{
+	unsigned int state;
+	char *endp;
+
+	if (strncmp(buffer, "off", 3) == 0)
+		hotkeys_set_save(io_op, HKEY_OFF);
+	else if (strncmp(buffer, "on", 2) == 0)
+		hotkeys_set_save(io_op, HKEY_ON);
+	else {
+		state = simple_strtoul(buffer, &endp, 16);
+		if (endp == buffer)
+			return -EINVAL;
+		else
+			hotkeys_set_save(io_op, state);
+	}
+	return 0;
+}
+
+static int __init omnibook_hotkeys_init(struct omnibook_operation *io_op)
+{
+	int retval;
+
+	printk(O_INFO "Enabling all hotkeys.\n");
+	retval = hotkeys_set_save(io_op, HKEY_ON);
+	return retval < 0 ? retval : 0;
+}
+
+static void __exit omnibook_hotkeys_cleanup(struct omnibook_operation *io_op)
+{
+	printk(O_INFO "Disabling all hotkeys.\n");
+	hotkeys_set_save(io_op, HKEY_OFF);
+}
+
+static struct omnibook_tbl hotkeys_table[] __initdata = {
+	{XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM30X, 
+	COMMAND(KBC,OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE,OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE)},
+	{TSM70, {CDI,}},
+	{TSM40, {SMI,}},
+	{TSX205, {ACPI,}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature hotkeys_driver = {
+	.name = "hotkeys",
+	.enabled = 1,
+	.read = omnibook_hotkeys_read,
+	.write = omnibook_hotkeys_write,
+	.init = omnibook_hotkeys_init,
+	.exit = omnibook_hotkeys_cleanup,
+	.suspend = omnibook_hotkeys_suspend,
+	.resume = omnibook_hotkeys_resume,
+	.ectypes =
+	    XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM70 | TSM30X |
+	    TSM40 | TSX205,
+	.tbl = hotkeys_table,
+};
+
+module_param_named(hotkeys, hotkeys_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(hotkeys, "Use 0 to disable, 1 to enable hotkeys handling");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/battery.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/battery.c
@@ -0,0 +1,557 @@
+/*
+ * battery.c -- battery related functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+struct omnibook_battery_info {
+	u8 type;		/* 1 - Li-Ion, 2 NiMH */
+	u16 sn;			/* Serial number */
+	u16 dv;			/* Design Voltage */
+	u16 dc;			/* Design Capacity */
+};
+
+struct omnibook_battery_state {
+	u16 pv;			/* Present Voltage */
+	u16 rc;			/* Remaining Capacity */
+	u16 lc;			/* Last Full Capacity */
+	u8 gauge;		/* Gauge in % */
+	u8 status;		/* 0 - unknown, 1 - charged, 2 - discharging, 3 - charging, 4 - critical) */
+};
+
+enum {
+	OMNIBOOK_BATTSTAT_UNKNOWN,
+	OMNIBOOK_BATTSTAT_CHARGED,
+	OMNIBOOK_BATTSTAT_DISCHARGING,
+	OMNIBOOK_BATTSTAT_CHARGING,
+	OMNIBOOK_BATTSTAT_CRITICAL
+};
+
+#define BAT_OFFSET 0x10
+
+static int __backend_u16_read(struct omnibook_operation *io_op, u16 *data)
+{
+	int retval;
+	u8 byte;
+
+	retval = __backend_byte_read(io_op, &byte);
+	if (retval)
+		return retval;
+	*data = byte;
+	io_op->read_addr += 1;
+	retval = __backend_byte_read(io_op, &byte);
+	*data += (byte << 8);
+	return retval;
+}
+
+static int omnibook_battery_present(struct omnibook_operation *io_op, int num)
+{
+	int retval;
+	u8 bat;
+	int i;
+
+	/*
+	 * XE3GF
+	 * TSP10
+	 * TSM30X
+	 * TSM70
+	 */
+	if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+		io_op->read_addr = XE3GF_BAL;
+		io_op->read_mask = XE3GF_BAL0_MASK;
+		for (i = 0; i < num; i++)
+			io_op->read_mask = io_op->read_mask << 1;
+		retval = __backend_byte_read(io_op, &bat);
+	/*
+	 * XE3GC
+	 * AMILOD
+	 */
+	} else if (omnibook_ectype & (XE3GC | AMILOD)) {
+		io_op->read_addr = XE3GC_BAT;
+		io_op->read_mask = XE3GC_BAT0_MASK;
+		for (i = 0; i < num; i++)
+			io_op->read_mask = io_op->read_mask << 1;
+		retval = __backend_byte_read(io_op, &bat);
+	} else
+		retval = -ENODEV;
+
+	/* restore default read_mask */
+	io_op->read_mask = 0;
+
+	return !!bat;
+}
+
+/*
+ * Get static battery information
+ * All info have to be reread every time because battery sould be cahnged
+ * when laptop is on AC power 
+ * return values:
+ *  < 0 - ERROR
+ *    0 - OK
+ *    1 - Battery is not present
+ *    2 - Not supported
+ */
+static int omnibook_get_battery_info(struct omnibook_operation *io_op,
+				     int num,
+				     struct omnibook_battery_info *battinfo)
+{
+	int retval;
+	/*
+	 * XE3GF
+	 * TSP10
+	 * TSM70
+         * TSM30X
+	 */
+	if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = XE3GF_BTY0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+				return retval;
+			io_op->read_addr = XE3GF_BSN0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).sn)))
+				return retval;
+			io_op->read_addr = XE3GF_BDV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+				return retval;
+			io_op->read_addr = XE3GF_BDC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+				return retval;
+
+			(*battinfo).type = ((*battinfo).type & XE3GF_BTY_MASK) ? 1 : 0;
+		} else
+			return 1;
+	/*
+	 * XE3GC
+	 */
+	} else if (omnibook_ectype & (XE3GC)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = XE3GC_BDV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+				return retval;
+			io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+				return retval;
+			io_op->read_addr = XE3GC_BTY0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+				return retval;
+
+			(*battinfo).type = ((*battinfo).type & XE3GC_BTY_MASK) ? 1 : 0;
+			(*battinfo).sn = 0;	/* Unknown */
+		} else
+			return 1;
+		/*
+		 * AMILOD
+		 */
+	} else if (omnibook_ectype & (AMILOD)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = AMILOD_BDV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dv)))
+				return retval;
+			io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battinfo).dc)))
+				return retval;
+			io_op->read_addr = AMILOD_BTY0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &(*battinfo).type)))
+				return retval;
+
+			(*battinfo).type = ((*battinfo).type & AMILOD_BTY_MASK) ? 1 : 0;
+			(*battinfo).sn = 0;	/* Unknown */
+		} else
+			return 1;
+		/*
+		 * FIXME
+		 * OB500
+		 * OB510
+		 */
+	} else if (omnibook_ectype & (OB500 | OB510)) {
+		switch (num) {
+		case 0:
+		case 1:
+		case 2:
+			break;
+		default:
+			return -EINVAL;
+		}
+		/*
+		 * OB6000
+		 * OB6100
+		 * XE4500
+		 */
+	} else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) {
+		switch (num) {
+		case 0:
+		case 1:
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else
+		return 2;
+
+	return 0;
+}
+
+/*
+ * Get battery status
+ * return values:
+ *  < 0 - ERROR
+ *    0 - OK
+ *    1 - Battery is not present
+ *    2 - Not supported
+ */
+static int omnibook_get_battery_status(struct omnibook_operation *io_op, 
+				       int num,
+				       struct omnibook_battery_state *battstat)
+{
+	int retval;
+	u8 status;
+	u16 dc;
+	int gauge;
+
+	/*
+	 * XE3GF
+	 * TSP10
+	 * TSM70
+	 */
+	if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = XE3GF_BST0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = XE3GF_BRC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = XE3GF_BPV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			io_op->read_addr = XE3GF_BFC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).lc)))
+				return retval;
+			io_op->read_addr = XE3GF_GAU0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &(*battstat).gauge)))
+				return retval;
+
+			if (status & XE3GF_BST_MASK_CRT)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+			else if (status & XE3GF_BST_MASK_CHR)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+			else if (status & XE3GF_BST_MASK_DSC)
+				(*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+			else if (status & (XE3GF_BST_MASK_CHR | XE3GF_BST_MASK_DSC))
+				(*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+			else {
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+			}
+		} else
+			return 1;
+	/*
+	 * XE3GC
+	 */
+	} else if (omnibook_ectype & (XE3GC)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = XE3GC_BST0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = XE3GC_BRC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = XE3GC_BPV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &dc)))
+				return retval;
+
+			if (status & XE3GC_BST_MASK_CRT)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+			else if (status & XE3GC_BST_MASK_CHR)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+			else if (status & XE3GC_BST_MASK_DSC)
+				(*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+			else if (status & (XE3GC_BST_MASK_CHR | XE3GC_BST_MASK_DSC))
+				(*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+			else {
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+			}
+			gauge = ((*battstat).rc * 100) / dc;
+			(*battstat).gauge = gauge;
+			(*battstat).lc = 0;	/* Unknown */
+		} else
+			return 1;
+	/*
+	 * AMILOD
+	 */
+	} else if (omnibook_ectype & (AMILOD)) {
+		retval = omnibook_battery_present(io_op, num);
+		if (retval < 0)
+			return retval;
+		if (retval) {
+			io_op->read_addr = AMILOD_BST0 + (BAT_OFFSET * num);
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = AMILOD_BRC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = AMILOD_BPV0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num);
+			if ((retval = __backend_u16_read(io_op, &dc)))
+				return retval;
+
+			if (status & AMILOD_BST_MASK_CRT)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+			else if (status & AMILOD_BST_MASK_CHR)
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+			else if (status & AMILOD_BST_MASK_DSC)
+				(*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+			else if (status & (AMILOD_BST_MASK_CHR | AMILOD_BST_MASK_DSC))
+				(*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+			else {
+				(*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+			}
+			gauge = ((*battstat).rc * 100) / dc;
+			(*battstat).gauge = gauge;
+			(*battstat).lc = 0;	/* Unknown */
+		} else
+			return 1;
+		/*
+		 * OB500
+		 * OB510
+		 */
+	} else if (omnibook_ectype & (OB500 | OB510)) {
+		switch (num) {
+		case 0:
+			io_op->read_addr = OB500_BT1S;
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = OB500_BT1C;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = OB500_BT1V;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			break;
+		case 1:
+			io_op->read_addr = OB500_BT2S;
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = OB500_BT2C;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = OB500_BT2V;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			break;
+		case 2:
+			io_op->read_addr = OB500_BT3S;
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = OB500_BT3C;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = OB500_BT3V;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (status & OB500_BST_MASK_CRT)
+			(*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+		else if (status & OB500_BST_MASK_CHR)
+			(*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+		else if (status & OB500_BST_MASK_DSC)
+			(*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+		else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC))
+			(*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+		else {
+			(*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+		}
+		/*
+		 * OB6000
+		 * OB6100
+		 * XE4500
+		 */
+	} else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) {
+		switch (num) {
+		case 0:
+			io_op->read_addr = OB500_BT1S;
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = OB500_BT1C;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = OB500_BT1V;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			break;
+		case 1:
+			io_op->read_addr = OB500_BT3S;
+			if ((retval = __backend_byte_read(io_op, &status)))
+				return retval;
+			io_op->read_addr = OB500_BT3C;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).rc)))
+				return retval;
+			io_op->read_addr = OB500_BT3V;
+			if ((retval = __backend_u16_read(io_op, &(*battstat).pv)))
+				return retval;
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (status & OB500_BST_MASK_CRT)
+			(*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL;
+		else if (status & OB500_BST_MASK_CHR)
+			(*battstat).status = OMNIBOOK_BATTSTAT_CHARGING;
+		else if (status & OB500_BST_MASK_DSC)
+			(*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING;
+		else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC))
+			(*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN;
+		else {
+			(*battstat).status = OMNIBOOK_BATTSTAT_CHARGED;
+		}
+	} else {
+		return 2;
+	}
+	return 0;
+}
+
+static int omnibook_battery_read(char *buffer, struct omnibook_operation *io_op)
+{
+	char *statustr;
+	char *typestr;
+	int max = 0;
+	int num = 0;
+	int len = 0;
+	int retval;
+	int i;
+	struct omnibook_battery_info battinfo;
+	struct omnibook_battery_state battstat;
+	/*
+	 * XE3GF
+	 * XE3GC
+	 * 0B6000
+	 * 0B6100
+	 * XE4500
+	 * AMILOD
+	 * TSP10
+	 */
+	if (omnibook_ectype & (XE3GF | XE3GC | OB6000 | OB6100 | XE4500 | AMILOD | TSP10))
+		max = 2;
+	/*
+	 * OB500
+	 * 0B510
+	 */
+	else if (omnibook_ectype & (OB500 | OB510))
+		max = 3;
+	/*
+	 * TSM30X
+	 * TSM70
+	 */
+	else if (omnibook_ectype & (TSM70 | TSM30X))
+		max = 1;
+
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+			return -ERESTARTSYS;
+
+	for (i = 0; i < max; i++) {
+		retval = omnibook_get_battery_info(io_op, i, &battinfo);
+		if (retval == 0) {
+			num++;
+			omnibook_get_battery_status(io_op, i, &battstat);
+			typestr = (battinfo.type) ? "Li-Ion" : "NiMH";
+			switch (battstat.status) {
+			case OMNIBOOK_BATTSTAT_CHARGED:
+				statustr = "charged";
+				break;
+			case OMNIBOOK_BATTSTAT_DISCHARGING:
+				statustr = "discharging";
+				break;
+			case OMNIBOOK_BATTSTAT_CHARGING:
+				statustr = "charging";
+				break;
+			case OMNIBOOK_BATTSTAT_CRITICAL:
+				statustr = "critical";
+				break;
+			default:
+				statustr = "unknown";
+			}
+
+			len += sprintf(buffer + len, "Battery:            %11d\n", i);
+			len += sprintf(buffer + len, "Type:               %11s\n", typestr);
+			if (battinfo.sn)
+				len +=
+				    sprintf(buffer + len, "Serial Number:      %11d\n",
+					    battinfo.sn);
+			len += sprintf(buffer + len, "Present Voltage:    %11d mV\n", battstat.pv);
+			len += sprintf(buffer + len, "Design Voltage:     %11d mV\n", battinfo.dv);
+			len += sprintf(buffer + len, "Remaining Capacity: %11d mAh\n", battstat.rc);
+			if (battstat.lc)
+				len +=
+				    sprintf(buffer + len, "Last Full Capacity: %11d mAh\n",
+					    battstat.lc);
+			len += sprintf(buffer + len, "Design Capacity:    %11d mAh\n", battinfo.dc);
+			len +=
+			    sprintf(buffer + len, "Gauge:              %11d %%\n", battstat.gauge);
+			len += sprintf(buffer + len, "Status:             %11s\n", statustr);
+			len += sprintf(buffer + len, "\n");
+		}
+	}
+	if (num == 0)
+		len += sprintf(buffer + len, "No battery present\n");
+
+	mutex_unlock(&io_op->backend->mutex);
+
+	return len;
+}
+
+static struct omnibook_tbl battery_table[] __initdata = {
+	{XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X, {EC,}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature battery_driver = {
+	.name = "battery",
+#ifdef CONFIG_OMNIBOOK_LEGACY
+	.enabled = 1,
+#else
+	.enabled = 0,
+#endif
+	.read = omnibook_battery_read,
+	.ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X,	/* FIXME: OB500|OB6000|OB6100|XE4500 */
+	.tbl = battery_table,
+};
+
+module_param_named(battery, battery_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(battery, "Use 0 to disable, 1 to enable battery status monitoring");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/init.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/init.c
@@ -0,0 +1,535 @@
+/*
+ * init.c -- module initialization code
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/proc_fs.h>
+#include <linux/dmi.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+
+#include "hardware.h"
+#include "laptop.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/platform_device.h>
+#else
+#include <linux/device.h>
+#endif
+
+/*
+ * For compatibility with kernel older than 2.6.11
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+typedef u32 pm_message_t;
+#endif
+
+static int __init omnibook_probe(struct platform_device *dev);
+static int __exit omnibook_remove(struct platform_device *dev);
+static int omnibook_suspend(struct platform_device *dev, pm_message_t state);
+static int omnibook_resume(struct platform_device *dev);
+
+/*
+ * For compatibility with kernel older than 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#define to_platform_device(x) container_of((x), struct platform_device, dev)
+
+static int __init compat_omnibook_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return omnibook_probe(pdev);
+}
+
+static int __exit compat_omnibook_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return omnibook_remove(pdev);
+}
+
+static int compat_omnibook_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return omnibook_suspend(pdev, state);
+}
+
+static int compat_omnibook_resume(struct device *dev, u32 level)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return omnibook_resume(pdev);
+}
+
+#endif
+
+static struct proc_dir_entry *omnibook_proc_root = NULL;
+
+enum omnibook_ectype_t omnibook_ectype = NONE;
+
+static const char *laptop_model __initdata;
+
+static int omnibook_userset = 0;
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+static struct platform_device *omnibook_device;
+
+static struct platform_driver omnibook_driver = {
+	.probe = omnibook_probe,
+	.remove = omnibook_remove,
+#ifdef CONFIG_PM
+	.suspend = omnibook_suspend,
+	.resume = omnibook_resume,
+#endif
+	.driver = {
+		   .name = OMNIBOOK_MODULE_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+
+#else				/* 2.6.15 */
+
+static struct device_driver omnibook_driver = {
+	.name = OMNIBOOK_MODULE_NAME,
+	.bus = &platform_bus_type,
+	.probe = compat_omnibook_probe,
+	.remove = compat_omnibook_remove,
+#ifdef CONFIG_PM
+	.suspend = compat_omnibook_suspend,
+	.resume = compat_omnibook_resume,
+#endif
+};
+
+static struct platform_device omnibook_device = {
+	.name = OMNIBOOK_MODULE_NAME,
+};
+
+#endif				/* 2.6.15 */
+
+/* Linked list of all enabled features */
+static struct omnibook_feature *omnibook_available_feature;
+
+/* Delimiters of the .features section wich holds all the omnibook_feature structs */
+extern struct omnibook_feature _start_features_driver[];
+extern struct omnibook_feature _end_features_driver[];
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+static int __init dmi_matched(struct dmi_system_id *dmi)
+#else
+static int __init dmi_matched(const struct dmi_system_id *dmi)
+#endif
+{
+	omnibook_ectype = (enum omnibook_ectype_t)dmi->driver_data;
+	if (dmi->ident)
+		laptop_model = (char *)dmi->ident;
+	else
+		laptop_model = dmi_get_system_info(DMI_PRODUCT_VERSION);
+	return 1;		/* return non zero means we stop the parsing selecting this entry */
+}
+
+/* 
+ * Callback function for procfs file reading: the name of the file read was stored in *data 
+ */
+static int procfile_read_dispatch(char *page, char **start, off_t off, int count, int *eof,
+				  void *data)
+{
+	struct omnibook_feature *feature = (struct omnibook_feature *)data;
+	int len = 0;
+
+	if (!feature || !feature->read)
+		return -EINVAL;
+
+	if(off)
+		goto out;
+
+	len = feature->read(page, feature->io_op);
+	if (len < 0)
+		return len;
+
+	out:
+	*eof = 1;
+	return len;
+}
+
+/* 
+ * Callback function for procfs file writing: the name of the file written was stored in *data 
+ */
+static int procfile_write_dispatch(struct file *file, const char __user * userbuf,
+				   unsigned long count, void *data)
+{
+	struct omnibook_feature *feature = (struct omnibook_feature *)data;
+	char *kernbuf;
+	int retval;
+
+	if (!feature || !feature->write)
+		return -EINVAL;
+
+	kernbuf = kmalloc(count + 1, GFP_KERNEL);
+	if (!kernbuf)
+		return -ENOMEM;
+
+	if (copy_from_user(kernbuf, userbuf, count)) {
+		kfree(kernbuf);
+		return -EFAULT;
+	}
+
+	/* Make sure the string is \0 terminated */
+	kernbuf[count] = '\0';
+
+	retval = feature->write(kernbuf, feature->io_op);
+	if (retval == 0)
+		retval = count;
+
+	kfree(kernbuf);
+
+	return retval;
+}
+
+/*
+ * Match an ectype and return pointer to corresponding omnibook_operation.
+ * Also make corresponding backend initialisation if necessary, and skip
+ * to the next entry if it fails.
+ */
+static struct omnibook_operation *omnibook_backend_match(struct omnibook_tbl *tbl)
+{
+	int i;
+	struct omnibook_operation *matched = NULL;
+
+	for (i = 0; tbl[i].ectypes; i++) {
+		if (omnibook_ectype & tbl[i].ectypes) {
+			if (tbl[i].io_op.backend->init && tbl[i].io_op.backend->init(&tbl[i].io_op)) {
+				dprintk("Backend %s init failed, skipping entry.\n",
+					tbl[i].io_op.backend->name);
+				continue;
+			}
+			matched = &tbl[i].io_op;
+			dprintk("Returning table entry nr %i.\n", i);
+			break;
+		}
+	}
+	return matched;
+}
+
+/* 
+ * Initialise a feature and add it to the linked list of active features
+ */
+static int __init omnibook_init(struct omnibook_feature *feature)
+{
+	int retval = 0;
+	mode_t pmode;
+	struct proc_dir_entry *proc_entry;
+	struct omnibook_operation *op;
+
+	if (!feature)
+		return -EINVAL;
+
+/*
+ * Select appropriate backend for feature operations
+ * We copy the io_op field so the tbl can be initdata
+ */
+	if (feature->tbl) {
+		dprintk("Begin table match of %s feature.\n", feature->name);
+		op = omnibook_backend_match(feature->tbl);
+		if (!op) {
+			dprintk("Match failed: disabling %s.\n", feature->name);
+			return -ENODEV;
+		}
+		feature->io_op = kmalloc(sizeof(struct omnibook_operation), GFP_KERNEL);
+		if (!feature->io_op)
+			return -ENOMEM;
+		memcpy(feature->io_op, op, sizeof(struct omnibook_operation));
+	} else
+		dprintk("%s feature has no backend table, io_op not initialized.\n", feature->name);
+
+/*
+ * Specific feature init code
+ */
+	if (feature->init && (retval = feature->init(feature->io_op))) {
+		printk(O_ERR "Init function of %s failed with error %i.\n", feature->name, retval);
+		goto err;
+	}
+/*
+ * procfs file setup
+ */
+	if (feature->name && feature->read) {
+		pmode = S_IFREG | S_IRUGO;
+		if (feature->write) {
+			pmode |= S_IWUSR;
+			if (omnibook_userset)
+				pmode |= S_IWUGO;
+		}
+
+		proc_entry = create_proc_entry(feature->name, pmode, omnibook_proc_root);
+
+		if (!proc_entry) {
+			printk(O_ERR "Unable to create proc entry %s\n", feature->name);
+			if (feature->exit)
+				feature->exit(feature->io_op);
+			retval = -ENOENT;
+			goto err;
+		}
+		proc_entry->data = feature;
+		proc_entry->read_proc = &procfile_read_dispatch;
+		if (feature->write)
+			proc_entry->write_proc = &procfile_write_dispatch;
+		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
+			proc_entry->owner = THIS_MODULE;
+		#endif
+	}
+	list_add_tail(&feature->list, &omnibook_available_feature->list);
+	return 0;
+      err:
+	if (feature->io_op && feature->io_op->backend->exit)
+		feature->io_op->backend->exit(feature->io_op);
+	kfree(feature->io_op);
+	return retval;
+}
+
+/* 
+ * Callback function for driver registering :
+ * Initialize the linked list of enabled features and call omnibook_init to populate it
+ */
+static int __init omnibook_probe(struct platform_device *dev)
+{
+	int i;
+	struct omnibook_feature *feature;
+
+	/* temporary hack */
+	mutex_init(&kbc_backend.mutex);
+	mutex_init(&pio_backend.mutex);
+	mutex_init(&ec_backend.mutex);
+
+	omnibook_available_feature = kzalloc(sizeof(struct omnibook_feature), GFP_KERNEL);
+	if (!omnibook_available_feature)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&omnibook_available_feature->list);
+
+	for (i = 0; i < _end_features_driver - _start_features_driver; i++) {
+
+		feature = &_start_features_driver[i];
+
+		if (!feature->enabled)
+			continue;
+
+		if ((omnibook_ectype & feature->ectypes) || (!feature->ectypes))
+			omnibook_init(feature);
+	}
+
+	printk(O_INFO "Enabled features:");
+	list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+		if (feature->name)
+			printk(" %s", feature->name);
+	}
+	printk(".\n");
+
+	return 0;
+}
+
+/* 
+ * Callback function for driver removal
+ */
+static int __exit omnibook_remove(struct platform_device *dev)
+{
+	struct omnibook_feature *feature, *temp;
+
+	list_for_each_entry_safe(feature, temp, &omnibook_available_feature->list, list) {
+		list_del(&feature->list);
+		/* Feature specific cleanup */
+		if (feature->exit)
+			feature->exit(feature->io_op);
+		/* Generic backend cleanup */
+		if (feature->io_op && feature->io_op->backend->exit)
+			feature->io_op->backend->exit(feature->io_op);
+		if (feature->name)
+			remove_proc_entry(feature->name, omnibook_proc_root);
+		kfree(feature->io_op);
+	}
+	kfree(omnibook_available_feature);
+
+	return 0;
+}
+
+/* 
+ * Callback function for system suspend 
+ */
+static int omnibook_suspend(struct platform_device *dev, pm_message_t state)
+{
+	int retval;
+	struct omnibook_feature *feature;
+
+	list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+		if (feature->suspend) {
+			retval = feature->suspend(feature->io_op);
+			if (retval)
+				printk(O_ERR "Unable to suspend the %s feature (error %i).\n", feature->name, retval);
+		}
+	}
+	return 0;
+}
+
+/* 
+ * Callback function for system resume
+ */
+static int omnibook_resume(struct platform_device *dev)
+{
+	int retval;
+	struct omnibook_feature *feature;
+
+	list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+		if (feature->resume) {
+			retval = feature->resume(feature->io_op);
+			if (retval)
+				printk(O_ERR "Unable to resume the %s feature (error %i).\n", feature->name, retval);
+		}
+	}
+	return 0;
+}
+
+/* 
+ * Find a given available feature by its name
+ */
+struct omnibook_feature *omnibook_find_feature(char *name)
+{
+	struct omnibook_feature *feature;
+
+	list_for_each_entry(feature, &omnibook_available_feature->list, list) {
+		if (!strcmp(feature->name, name))
+			return feature;
+	}
+	return NULL;
+}
+
+/*
+ * Maintain compatibility with the old ectype numbers:
+ * ex: The user set/get ectype=12 for TSM70=2^(12-1)
+ */
+static int __init set_ectype_param(const char *val, struct kernel_param *kp)
+{
+	char *endp;
+	int value;
+
+	if (!val)
+		return -EINVAL;
+
+	value = simple_strtol(val, &endp, 10);
+	if (endp == val)	/* No match */
+		return -EINVAL;
+	omnibook_ectype = 1 << (value - 1);
+	return 0;
+}
+
+static int get_ectype_param(char *buffer, struct kernel_param *kp)
+{
+	return sprintf(buffer, "%i", ffs(omnibook_ectype));
+}
+
+static int __init omnibook_module_init(void)
+{
+	int retval;
+
+	printk(O_INFO "Driver version %s.\n", OMNIBOOK_MODULE_VERSION);
+
+	if (omnibook_ectype != NONE)
+		printk(O_WARN "Forced load with EC type %i.\n", ffs(omnibook_ectype));
+	else if (dmi_check_system(omnibook_ids))
+		printk(O_INFO "%s detected.\n", laptop_model);
+	else
+		printk(O_INFO "Unknown model.\n");
+
+	omnibook_proc_root = proc_mkdir(OMNIBOOK_MODULE_NAME, NULL);
+	if (!omnibook_proc_root) {
+		printk(O_ERR "Unable to create /proc/%s.\n", OMNIBOOK_MODULE_NAME);
+		return -ENOENT;
+	}
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+	retval = platform_driver_register(&omnibook_driver);
+	if (retval < 0)
+		return retval;
+
+	omnibook_device = platform_device_alloc(OMNIBOOK_MODULE_NAME, -1);
+	if (!omnibook_device) {
+		platform_driver_unregister(&omnibook_driver);
+		return -ENOMEM;
+	}
+
+	retval = platform_device_add(omnibook_device);
+	if (retval) {
+		platform_device_put(omnibook_device);
+		platform_driver_unregister(&omnibook_driver);
+		return retval;
+	}
+#else				/* 2.6.15 */
+
+	retval = driver_register(&omnibook_driver);
+	if (retval < 0)
+		return retval;
+
+	retval = platform_device_register(&omnibook_device);
+
+	if (retval) {
+		driver_unregister(&omnibook_driver);
+		return retval;
+	}
+#endif
+	return 0;
+}
+
+static void __exit omnibook_module_cleanup(void)
+{
+
+/*
+ * The platform_driver interface was added in linux 2.6.15
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+	platform_device_unregister(omnibook_device);
+	platform_driver_unregister(&omnibook_driver);
+#else
+	platform_device_unregister(&omnibook_device);
+	driver_unregister(&omnibook_driver);
+#endif
+
+	if (omnibook_proc_root)
+		remove_proc_entry("omnibook", NULL);
+	printk(O_INFO "Module is unloaded.\n");
+}
+
+module_init(omnibook_module_init);
+module_exit(omnibook_module_cleanup);
+
+MODULE_AUTHOR("Soós Péter, Mathieu Bérard");
+MODULE_VERSION(OMNIBOOK_MODULE_VERSION);
+MODULE_DESCRIPTION
+    ("Kernel interface for HP OmniBook, HP Pavilion, Toshiba Satellite and Compal ACL00 laptops");
+MODULE_LICENSE("GPL");
+module_param_call(ectype, set_ectype_param, get_ectype_param, NULL, S_IRUGO);
+module_param_named(userset, omnibook_userset, int, S_IRUGO);
+MODULE_PARM_DESC(ectype, "Type of embedded controller firmware");
+MODULE_PARM_DESC(userset, "Use 0 to disable, 1 to enable users to set parameters");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/BOM
+++ linux-ec2-2.6.32/ubuntu/omnibook/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	http://sourceforge.net/projects/omke/
+Current Version:	2.20070211
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/ac.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/ac.c
@@ -0,0 +1,60 @@
+/*
+ * ac.c -- AC adapter related functions
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_ac_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	u8 ac;
+	int retval;
+
+	retval = backend_byte_read(io_op, &ac);
+	if (retval < 0)
+		return retval;
+
+	len += sprintf(buffer + len, "AC %s\n", (!!ac) ? "on-line" : "off-line");
+
+	return len;
+}
+
+static struct omnibook_tbl ac_table[] __initdata = {
+	{XE3GF | TSP10 | TSM30X | TSM70, SIMPLE_BYTE(EC, XE3GF_ADP, XE3GF_ADP_MASK)},
+	{XE3GC | AMILOD, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_ADP_MASK)},
+	{OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA2, OB500_ADP_MASK)},
+	{OB4150, SIMPLE_BYTE(EC, OB4150_ADP, OB4150_ADP_MASK)},
+	{XE2, SIMPLE_BYTE(EC, XE2_STA1, XE2_ADP_MASK)},
+	{0,}
+};
+
+struct omnibook_feature __declared_feature ac_driver = {
+	.name = "ac",
+#ifdef CONFIG_OMNIBOOK_LEGACY
+	.enabled = 1,
+#else
+	.enabled = 0,
+#endif
+	.read = omnibook_ac_read,
+	.ectypes = XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X,
+	.tbl = ac_table,
+};
+
+module_param_named(ac, ac_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(ac, "Use 0 to disable, 1 to enable AC adapter status monitoring");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/dock.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/dock.c
@@ -0,0 +1,84 @@
+/*
+ * dock.c -- docking station/port replicator support
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static int omnibook_dock_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	u8 dock;
+	int retval;
+
+	if ((retval = backend_byte_read(io_op, &dock)))
+		return retval;
+
+	len += sprintf(buffer + len, "Laptop is %s\n", (dock) ? "docked" : "undocked");
+
+	return len;
+}
+
+static int omnibook_dock_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+
+	switch (*buffer) {
+	case '0':
+		retval = backend_byte_write(io_op, 0);
+		break;
+	case '1':
+		retval = backend_byte_write(io_op, 1);
+		break;
+	default:
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+static struct omnibook_feature dock_driver;
+
+static int __init omnibook_dock_init(struct omnibook_operation *io_op)
+{
+	/* writing is only supported on ectype 13 */
+	if(!(omnibook_ectype & TSM40))
+		dock_driver.write = NULL;
+	
+	return 0;
+}
+
+static struct omnibook_tbl dock_table[] __initdata = {
+	{XE3GF, SIMPLE_BYTE(EC, XE3GF_CSPR, XE3GF_CSPR_MASK)},
+	{OB500 | OB510 | OB6000 | OB6100, SIMPLE_BYTE(EC, OB500_STA1, OB500_DCKS_MASK)},
+	{OB4150, SIMPLE_BYTE(EC, OB4150_DCID, 0)},
+	{TSM40, {SMI, SMI_GET_DOCK, SMI_SET_DOCK, 0, 0, 0}},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature dock_driver = {
+	.name = "dock",
+	.enabled = 0,
+	.init = omnibook_dock_init,
+	.read = omnibook_dock_read,
+	.write = omnibook_dock_write,
+	.ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | TSM40,
+	.tbl = dock_table,
+};
+
+module_param_named(dock, dock_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dock, "Use 0 to disable, 1 to enable docking station support");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/info.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/info.c
@@ -0,0 +1,68 @@
+/*
+ * info.c -- trivial informational features
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+
+#include <linux/dmi.h>
+#include <linux/version.h>
+
+static int omnibook_version_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	len += sprintf(buffer + len, "%s\n", OMNIBOOK_MODULE_VERSION);
+
+	return len;
+}
+
+static int omnibook_dmi_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+
+	len += sprintf(buffer + len, "BIOS Vendor:   %s\n", dmi_get_system_info(DMI_BIOS_VENDOR));
+	len += sprintf(buffer + len, "BIOS Version:  %s\n", dmi_get_system_info(DMI_BIOS_VERSION));
+	len += sprintf(buffer + len, "BIOS Release:  %s\n", dmi_get_system_info(DMI_BIOS_DATE));
+	len += sprintf(buffer + len, "System Vendor: %s\n", dmi_get_system_info(DMI_SYS_VENDOR));
+	len += sprintf(buffer + len, "Product Name:  %s\n", dmi_get_system_info(DMI_PRODUCT_NAME));
+	len +=
+	    sprintf(buffer + len, "Version:       %s\n", dmi_get_system_info(DMI_PRODUCT_VERSION));
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+	len +=
+	    sprintf(buffer + len, "Serial Number: %s\n", dmi_get_system_info(DMI_PRODUCT_SERIAL));
+#endif
+	len += sprintf(buffer + len, "Board Vendor:  %s\n", dmi_get_system_info(DMI_BOARD_VENDOR));
+	len += sprintf(buffer + len, "Board Name:    %s\n", dmi_get_system_info(DMI_BOARD_VERSION));
+
+	return len;
+}
+
+static struct omnibook_feature __declared_feature version_driver = {
+	.name = "version",
+	.enabled = 1,
+	.read = omnibook_version_read,
+};
+
+static struct omnibook_feature __declared_feature dmi_driver = {
+	.name = "dmi",
+	.enabled = 1,
+	.read = omnibook_dmi_read,
+};
+
+module_param_named(dmi, dmi_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(dmi, "Use 0 to disable, 1 to enable DMI informations display support");
+
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/hardware.h
+++ linux-ec2-2.6.32/ubuntu/omnibook/hardware.h
@@ -0,0 +1,582 @@
+/*
+ * hardware.h -- low level definitions to access Embedded Controller and co.
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006-2007
+ */
+
+#include <linux/acpi.h>
+#include "compat.h"
+
+/*
+ * Quite ugly:
+ * on_mask and off_maks are also used to store the i8042 data for kbc backend.
+ * an union seemed overkilled
+ */
+
+struct omnibook_backend;
+
+struct omnibook_operation {
+		struct omnibook_backend *backend;
+		unsigned long read_addr; /* address for data reading */
+		unsigned long write_addr; /* address for data writing */
+		u8 read_mask; /* read mask */
+		int on_mask; /* mask to set (pos value) or unset (neg value) to put feature in on state */
+		int off_mask; /* mask to set (pos value) or unset (neg value) to put feature in off state */
+};
+
+#define COMMAND(backend,data_on,data_off) { backend, 0, 0, 0, data_on, data_off }
+#define SIMPLE_BYTE(backend,addr,mask) { backend, addr, addr, mask, 0, 0 }
+
+struct omnibook_tbl {
+	enum omnibook_ectype_t ectypes;
+	struct omnibook_operation io_op;
+};
+
+/*
+ * Backend interface definition
+ */
+
+struct omnibook_backend {
+	const char *name;	/* backend name */
+	struct mutex mutex;	/* serializes all access to backend functions */
+	const unsigned int hotkeys_read_cap; /* hotkey probing mask */
+	const unsigned int hotkeys_write_cap; /* hotkey setting mask */
+
+	/* Public data fields, access with mutex held */
+	unsigned int hotkeys_state;	/* saved hotkeys state */
+	unsigned int touchpad_state;	/* saved touchpad state */
+	unsigned int muteled_state;	/* saved muteled state */
+	unsigned int cooling_state;	/* saved cooling method state */
+
+	/* Public function pointers */
+	int (*init) (const struct omnibook_operation *); 
+	void (*exit) (const struct omnibook_operation *);
+	int (*byte_read) (const struct omnibook_operation *, u8 *); 
+	int (*byte_write) (const struct omnibook_operation *, u8);
+	int (*aerial_get) (const struct omnibook_operation *, unsigned int *);
+	int (*aerial_set) (const struct omnibook_operation *, unsigned int);
+	int (*hotkeys_get) (const struct omnibook_operation *, unsigned int *);
+	int (*hotkeys_set) (const struct omnibook_operation *, unsigned int);
+	int (*display_get) (const struct omnibook_operation *, unsigned int *);
+	int (*display_set) (const struct omnibook_operation *, unsigned int);
+	int (*throttle_get) (const struct omnibook_operation *, unsigned int *);
+	int (*throttle_set) (const struct omnibook_operation *, unsigned int);
+
+	/* Private fields, never to be accessed outside backend code */
+	struct kref kref;	/* Reference counter of this backend */
+	void *data;		/* private data pointer */
+	int already_failed;	/* Backend init already failed at least once */
+};
+
+extern struct omnibook_backend kbc_backend;
+extern struct omnibook_backend pio_backend;
+extern struct omnibook_backend ec_backend;
+extern struct omnibook_backend acpi_backend;
+extern struct omnibook_backend nbsmi_backend;
+extern struct omnibook_backend compal_backend;
+
+#define KBC   &kbc_backend
+#define PIO   &pio_backend
+#define EC    &ec_backend
+#define ACPI  &acpi_backend
+#define SMI   &nbsmi_backend
+#define CDI   &compal_backend
+
+int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle);
+int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle);
+
+/*
+ * Lock helper functions. Defines locking and __prefixed non locking variants.
+ */
+
+#define helper_func(func) \
+static inline int backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \
+{ \
+	int retval; \
+	if(mutex_lock_interruptible(&io_op->backend->mutex)) \
+		return -ERESTARTSYS; \
+	retval = io_op->backend->func##_get(io_op, data); \
+	mutex_unlock(&io_op->backend->mutex); \
+	return retval; \
+} \
+static inline int backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \
+{ \
+	int retval; \
+	if(mutex_lock_interruptible(&io_op->backend->mutex)) \
+		return -ERESTARTSYS; \
+	retval = io_op->backend->func##_set(io_op, data); \
+	mutex_unlock(&io_op->backend->mutex); \
+	return retval; \
+}\
+static inline int __backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \
+{ \
+	int retval; \
+	WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \
+	retval = io_op->backend->func##_get(io_op, data); \
+	return retval; \
+} \
+static inline int __backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \
+{ \
+	int retval; \
+	WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \
+	retval = io_op->backend->func##_set(io_op, data); \
+	return retval; \
+}
+
+helper_func(aerial)
+helper_func(hotkeys)
+helper_func(display)
+helper_func(throttle)
+
+static inline int backend_byte_read(const struct omnibook_operation *io_op, u8 *data)
+{
+	int retval;
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+	retval = io_op->backend->byte_read(io_op, data);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static inline int backend_byte_write(const struct omnibook_operation *io_op, u8 data)
+{
+	int retval;
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+	retval = io_op->backend->byte_write(io_op, data);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static inline int __backend_byte_read(const struct omnibook_operation *io_op, u8 *data)
+{
+	int retval;
+	WARN_ON(!mutex_is_locked(&io_op->backend->mutex));
+	retval = io_op->backend->byte_read(io_op, data);
+	return retval;
+}
+
+static inline int __backend_byte_write(const struct omnibook_operation *io_op, u8 data)
+{
+	int retval;
+	WARN_ON(!mutex_is_locked(&io_op->backend->mutex));
+	retval = io_op->backend->byte_write(io_op, data);
+	return retval;
+}
+
+static inline int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle)
+{
+	int retval;
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+	retval = __omnibook_apply_write_mask(io_op, toggle);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+static inline int omnibook_toggle(const struct omnibook_operation *io_op, int toggle)
+{
+	int retval;
+	if(mutex_lock_interruptible(&io_op->backend->mutex))
+		return -ERESTARTSYS;
+	retval = __omnibook_toggle(io_op, toggle);
+	mutex_unlock(&io_op->backend->mutex);
+	return retval;
+}
+
+/*
+ * Timeout in ms for sending to controller
+ */
+
+#define OMNIBOOK_TIMEOUT                250
+
+
+/*
+ *	Embedded controller adresses
+ */
+
+#define XE3GF_CHGM	0x90	/* , 16 bit */
+#define XE3GF_CHGS	0x92	/* , 16 bit */
+#define XE3GF_CHGC	0x94	/* Current charge of board, 16 bit */
+#define XE3GF_CHGV	0x96	/* Current voltage, 16 bit */
+#define XE3GF_CHGA	0x98	/* Current intensity, 16 bit */
+#define XE3GF_BAL	0x9A	/* Battery present status */
+#define XE3GF_STA1	0x9C	/* Various status bits */
+#define XE3GF_CSPR	0xA1	/* Port replicator status, 1 bit */
+#define XE3GF_ADP	0xA3	/* AC acapter status, 1 bit */
+#define XE3GF_FOT	0xA5	/* Fan off temperature, 8 bit */
+#define XE3GF_FSD1	0xA6	/* Fan on temperature, 8 bit */
+#define XE3GF_FSD2	0xA7	/* Fan level 2 temperature, 8 bit */
+#define XE3GF_FSD3	0xA8	/* Fan level 3 temperature, 8 bit */
+#define XE3GF_FSD4	0xA9	/* Fan level 4 temperature, 8 bit */
+#define XE3GF_FSD5	0xAA	/* Fan level 5 temperature, 8 bit */
+#define XE3GF_FSD6	0xAB	/* Fan level 6 temperature, 8 bit */
+#define XE3GF_FSD7	0xAC	/* Fan level 7 temperature, 8 bit */
+#define XE3GF_FSRD	0xAD	/* Fan status, 8 bit */
+#define XE3GF_CTMP	0xB0	/* CPU tempetature, 8 bit */
+#define XE3GF_BRTS	0xB9	/* LCD brightness, 4 bit */
+#define XE3GF_BTY0	0xC0	/* Battery 0 type, 1 bit */
+#define XE3GF_BST0	0xC1	/* Battery 0 status, 3 bit */
+#define XE3GF_BRC0	0xC2	/* Battery 0 remaining capacity, 16 bit */
+#define XE3GF_BSN0	0xC4	/* Battery 0 serial number 16 bit */
+#define XE3GF_BPV0	0xC6	/* Battery 0 present voltage, 16 bit */
+#define XE3GF_BDV0	0xC8	/* Battery 0 design voltage 16 bit */
+#define XE3GF_BDC0	0xCA	/* Battery 0 design capacity 16 bit */
+#define XE3GF_BFC0	0xCC	/* Battery 0 last full capacity 16 bit */
+#define XE3GF_GAU0	0xCE	/* Battery 0 gauge, 8 bit */
+#define XE3GF_BTY1	0xD0	/* Battery 1 type, 1 bit */
+#define XE3GF_BST1	0xD1	/* Battery 1 status, 3 bit */
+#define XE3GF_BRC1	0xD2	/* Battery 1 remaining capacity, 16 bit */
+#define XE3GF_BSN1	0xD4	/* Battery 1 serial number, 16 bit */
+#define XE3GF_BPV1	0xD6	/* Battery 1 present voltage, 16 bit */
+#define XE3GF_BDV1	0xD8	/* Battery 1 design voltage 16 bit */
+#define XE3GF_BDC1	0xDA	/* Battery 1 design capacity 16 bit */
+#define XE3GF_BFC1	0xDC	/* Battery 1 last full capacity 16 bit */
+#define XE3GF_GAU1	0xDE	/* Battery 1 gauge, 8 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define XE3GF_SHDD_MASK		0x40	/* External display status */
+#define XE3GF_CSPR_MASK		0x01	/* Port replicator status */
+#define XE3GF_ADP_MASK		0x20	/* AC acapter status */
+#define XE3GF_BAL0_MASK		0x01	/* Battery 0 present */
+#define XE3GF_BAL1_MASK		0x02	/* Battery 1 present */
+#define XE3GF_BMF_MASK		0x70	/* Model code */
+#define XE3GF_BTY_MASK		0x80	/* Type: Ni-MH or Li-Ion */
+#define XE3GF_BST_MASK_DSC	0x01	/* Discarging */
+#define XE3GF_BST_MASK_CHR	0x02	/* Charging */
+#define XE3GF_BST_MASK_CRT	0x04	/* Critical */
+#define XE3GF_FSRD_MASK_S1	0x01	/* Fan level 1 */
+#define XE3GF_FSRD_MASK_S2	0x02	/* Fan level 2 */
+#define XE3GF_FSRD_MASK_S3	0x04	/* Fan level 3 */
+#define XE3GF_FSRD_MASK_S4	0x08	/* Fan level 4 */
+#define XE3GF_FSRD_MASK_S5	0x10	/* Fan level 5 */
+#define XE3GF_FSRD_MASK_S6	0x20	/* Fan level 6 */
+#define XE3GF_FSRD_MASK_S7	0x40	/* Fan level 7 */
+#define XE3GF_BRTS_MASK		0x0F	/* LCD brightness */
+#define XE3GF_FAN_ON_MASK	0x02	/* Fan on */
+
+/*
+ * OmniBook XE3 GC values
+ */
+
+#define XE3GC_CTMP	0x28	/* CPU tempetature, 8 bit */
+#define XE3GC_STA1	0x30	/* Various status bits */
+#define XE3GC_Q0A	0x31	/* Various status bits */
+#define XE3GC_CCUR	0x38	/* Current charge of board, 16 bit ? */
+#define XE3GC_CVOL	0x3A	/* Current voltage, 16 bit ? */
+#define XE3GC_CARM	0x3C	/* Current intensity, 16 bit ? */
+#define XE3GC_BAT	0x3E	/* Battery present status */
+#define XE3GC_BST0	0x40	/* Battery 0 status, 3 bit */
+#define XE3GC_BPR0	0x41	/* Battery 0 present rate, 16 bit ? */
+#define XE3GC_BRC0	0x43	/* Battery 0 remaining capacity, 16 bit */
+#define XE3GC_BPV0	0x45	/* Battery 0 present voltage, 16 bit */
+#define XE3GC_BDV0	0x47	/* Battery 0 design voltage 16 bit */
+#define XE3GC_BDC0	0x49	/* Battery 0 design capacity 16 bit */
+#define XE3GC_BTY0	0x4A	/* Battery 0 type, 1 bit ? */
+#define XE3GC_BTP0	0x4B	/* Battery 0 ?, 1 bit */
+#define XE3GC_BSN0	0x4C	/* Battery 0 serial number, 8 bit ? */
+#define XE3GC_BMF0	0x4D	/* Battery 0 ?,8 bit */
+#define XE3GC_BST1	0x50	/* Battery 1 status, 3 bit */
+#define XE3GC_BPR1	0x51	/* Battery 1 present rate, 16 bit ? */
+#define XE3GC_BRC1	0x53	/* Battery 1 remaining capacity, 16 bit */
+#define XE3GC_BPV1	0x55	/* Battery 1 present voltage, 16 bit */
+#define XE3GC_BDV1	0x57	/* Battery 1 design voltage 16 bit */
+#define XE3GC_BDC1	0x59	/* Battery 1 design capacity 16 bit */
+#define XE3GC_BTY1	0x5A	/* Battery 1 type, 1 bit ? */
+#define XE3GC_BTP1	0x5B	/* Battery 1 ?, 1 bit */
+#define XE3GC_BSN1	0x5C	/* Battery 1 serial number, 8 bit ? */
+#define XE3GC_BMF1	0x5D	/* Battery 1 ?,8 bit */
+#define XE3GC_STA2	0x61	/* Various status bits */
+#define XE3GC_BTVL	0x6A	/* LCD brightness, 4 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define XE3GC_ADP_MASK		0x40	/* AC acapter status */
+#define XE3GC_BAT0_MASK		0x01	/* Battery 0 present */
+#define XE3GC_BAT1_MASK		0x02	/* Battery 1 present */
+#define XE3GC_BTY_MASK		0x01	/* Type: Ni-MH or Li-Ion */
+#define XE3GC_BST_MASK_DSC	0x01	/* Discarging */
+#define XE3GC_BST_MASK_CHR	0x02	/* Charging */
+#define XE3GC_BST_MASK_CRT	0x04	/* Critical */
+#define XE3GC_CRTI_MASK		0x04	/* External display status */
+#define XE3GC_SLPB_MASK		0x01	/* Sleep button pressed */
+#define XE3GC_F5_MASK		0x02	/* Fn-F5 - LCD/CRT switch pressed */
+#define XE3GC_VOLD_MASK		0x04	/* Fn-down arrow or Volume down pressed */
+#define XE3GC_VOLU_MASK		0x08	/* Fn-up arrow or Volume up pressed */
+#define XE3GC_MUTE_MASK		0x10	/* Fn+F7 - Volume mute pressed */
+#define XE3GC_CNTR_MASK		0x20	/* Fn+F3/Fn+F4 - Contrast up or down pressed */
+#define XE3GC_BRGT_MASK		0x40	/* Fn+F1/Fn+F2 - Brightness up or down pressed */
+#define XE3GC_BTVL_MASK		0x0F	/* LCD brightness */
+
+/*
+ * Toshiba Satellite A105 values and mask
+ */
+
+#define A105_BNDT				0xA3	/* LCD brightness */
+#define A105_BNDT_MASK				0x0F
+
+/*
+ * Fujitsu Amilo D values
+ */
+
+#define AMILOD_TMP	0x28	/* CPU tempetature, 8 bit */
+#define AMILOD_STA1	0x30	/* Various status bits */
+#define AMILOD_BAT	0x3E	/* Battery present status */
+#define AMILOD_BDC0	0x40	/* Battery 0 design capacity 16 bit */
+#define AMILOD_BDV0	0x42	/* Battery 0 design voltage 16 bit */
+#define AMILOD_BTY0	0x44	/* Battery 0 type, 1 bit ? */
+#define AMILOD_BST0	0x45	/* Battery 0 status, 3 bit */
+#define AMILOD_BPR0	0x46	/* Battery 0 present rate, 16 bit ? */
+#define AMILOD_BRC0	0x48	/* Battery 0 remaining capacity, 16 bit */
+#define AMILOD_BPV0	0x4A	/* Battery 0 present voltage, 16 bit */
+#define AMILOD_BTP0	0x4C	/* Battery 0 ?, 1 bit */
+#define AMILOD_BDC1	0x50	/* Battery 1 design capacity 16 bit */
+#define AMILOD_BDV1	0x52	/* Battery 1 design voltage 16 bit */
+#define AMILOD_BTY1	0x54	/* Battery 1 type, 1 bit ? */
+#define AMILOD_BST1	0x55	/* Battery 1 status, 3 bit */
+#define AMILOD_BPR1	0x56	/* Battery 1 present rate, 16 bit ? */
+#define AMILOD_BRC1	0x58	/* Battery 1 remaining capacity, 16 bit */
+#define AMILOD_BPV1	0x5A	/* Battery 1 present voltage, 16 bit */
+#define AMILOD_BTP1	0x5C	/* Battery 1 ?, 1 bit */
+#define AMILOD_CBRG	0x6F	/* LCD brightness, 4 bit */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define AMILOD_ADP_MASK		0x40	/* AC acapter status */
+#define AMILOD_BAT0_MASK	0x01	/* Battery 0 present */
+#define AMILOD_BAT1_MASK	0x02	/* Battery 1 present */
+#define AMILOD_BTY_MASK		0x01	/* Type: Ni-MH or Li-Ion */
+#define AMILOD_BST_MASK_DSC	0x01	/* Discarging */
+#define AMILOD_BST_MASK_CHR	0x02	/* Charging */
+#define AMILOD_BST_MASK_CRT	0x04	/* Critical */
+#define AMILOD_CBRG_MASK	0x0F	/* LCD brightness */
+
+/*
+ * OmniBook 500, 510, 6000, 6100, XE2 values
+ */
+
+#define OB500_STA1	0x44	/* Various status bits */
+#define OB500_STA2	0x50	/* Various status bits */
+#define OB500_CTMP	0x55	/* CPU tempetature, 8 bit */
+#define OB500_BT1I	0x58	/* Battery 1 ? 16 bit */
+#define OB500_BT1C	0x5A	/* Battery 1 remaining capacity 16 bit ? */
+#define OB500_BT1V	0x5C	/* Battery 1 present voltage 16 bit ? */
+#define OB500_BT1S	0x5E	/* Battery 1 status 3 bit ? */
+#define OB500_BT2I	0x6A	/* Battery 2 ? 16 bit */
+#define OB500_BT2C	0x6C	/* Battery 2 remaining capacity 16 bit ? */
+#define OB500_BT2V	0x6E	/* Battery 2 present voltage 16 bit ? */
+#define OB500_BT2S	0x70	/* Battery 2 status 3 bit ? */
+#define OB500_BT3I	0x5F	/* Battery 3 ? 16 bit */
+#define OB500_BT3C	0x61	/* Battery 3 remaining capacity 16 bit ? */
+#define OB500_BT3V	0x63	/* Battery 3 present voltage 16 bit ? */
+#define OB500_BT3S	0x65	/* Battery 3 status 3 bit ? */
+
+#define OB6000_STA1	0x77	/* Various status bits */
+
+#define XE2_STA1	0x50	/* Various status bits */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define OB500_LIDS_MASK		0x01	/* LID status */
+#define OB500_CRTS_MASK		0x20	/* External display status */
+#define OB500_SLPS_MASK		0x40	/* Sleep button status */
+#define OB500_DCKS_MASK		0x80	/* Docking status */
+#define OB500_ADP_MASK		0x02	/* AC acapter status */
+#define OB500_BST_MASK_DSC	0x01	/* Discarging */
+#define OB500_BST_MASK_CHR	0x02	/* Charging */
+#define OB500_BST_MASK_CRT	0x04	/* Critical */
+
+#define OB6000_FAN_MASK		0x10	/* Fan status */
+
+#define XE2_ADP_MASK		0x02	/* AC acapter status */
+
+/*
+ * OmniBook 4150
+ */
+
+#define OB4150_TMP		0x28	/* CPU tempetature, 8 bit */
+#define OB4150_STA1		0x2E	/* Various status bits */
+#define OB4150_STA2		0x2F	/* Various status bits */
+#define OB4150_ADP		0x30	/* AC acapter status, 1 bit */
+#define OB4150_DCID		0x2C	/* Port replicator */
+
+/*
+ * Bitmasks for sub byte values
+ */
+
+#define OB4150_FAN_MASK		0x01	/* Fan status */
+#define OB4150_ADP_MASK		0x40	/* AC acapter status */
+#define OB4150_CRST_MASK	0x20	/* External display status */
+
+/*
+ *	Keyboard controller command for some laptop functions
+ */
+
+#define OMNIBOOK_KBC_CONTROL_CMD		0x59
+
+/*
+ *	Keyboard controller command parameters for functions available via kbc
+ */
+
+#define OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE	0x90	/* Enables OneTouch buttons */
+#define OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE	0x91	/* Disables OneTouch buttons */
+#define OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE	0xAA	/* Enables touchpad */
+#define OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE	0xA9	/* Disables touchpad */
+#define OMNIBOOK_KBC_CMD_LCD_ON			0xE1	/* Turns LCD display on */
+#define OMNIBOOK_KBC_CMD_LCD_OFF		0xE2	/* Turns LCD display off */
+#define OMNIBOOK_KBC_CMD_MUTELED_ON     	0x94	/* Turns (xe4500) Mute LED on */
+#define OMNIBOOK_KBC_CMD_MUTELED_OFF    	0x95	/* Turns (xe4500) Mute LED off */
+#define OMNIBOOK_KBC_CMD_AC_POWER_ENABLE	0xC2	/* Enable AC power */
+#define OMNIBOOK_KBC_CMD_AC_POWER_DISABLE	0xC1	/* Disable AC power */
+
+/*
+ * Other I/O ports
+ */
+
+#define ACL00_AC_STAT		0x11B9	/* AC adapter status on ACL00 */
+#define ACL00_AC_MASK		0x04	/* Bitmask for AC adapter status on ACL00 */
+#define TOSH3K_AC_STAT		0x102D	/* AC adapter status on Toshiba 3000 */
+#define TOSH3K_AC_MASK		0x08	/* Bitmask for AC adapter status on Toshiba 3000 */
+#define XE3GF_AC_STAT		0x11B9	/* AC adapter status on XE3 GF */
+#define XE3GF_AC_MASK		0x04	/* Bitmask for AC adapter status on XE3 GF */
+#define XE3GF_LID_STAT		0x11AD	/* LID switch status on XE3 GF */
+#define XE3GF_LID_MASK		0x20	/* Bitmask for LID switch status on XE3 GF */
+#define XE3GC_SMIC		0xFE00
+
+#define OB500_GPO1		0x8034	/* Fan control */
+#define OB510_GPO2		0x11B9	/* LCD backlight */
+#define OB510_GPIO		0x118F	/* Fan control */
+
+#define OB500_FAN_ON_MASK	0x0A	/* Turn fan on with zero bits */
+#define OB500_FAN_OFF_MASK	0x08	/* Fan status/off */
+#define OB500_BKLT_MASK		0x40	/* LCD backlight */
+#define OB510_FAN_ON_MASK	0x18	/* Turn fan on with zero bits */
+#define OB510_FAN_OFF_MASK	0x10	/* Turn fan on */
+#define OB510_BKLT_MASK		0x01	/* LCD backlight */
+
+#define XE2_FAN_MASK		0x02	/* Turn fan on with zero bit */
+
+/*
+ * Memory adresses
+ */
+
+#define XE3GC_BCMD		0xFFFFEBC
+
+/*
+ * Toshiba Satellite A105 values and mask
+ */
+
+#define A105_BNDT		0xA3	/* LCD brightness */
+#define A105_BNDT_MASK		0x0F
+
+/*
+ * Index and values for Command/Data/Index interface
+ * Notice similitudes with commands code for kbc
+ */
+
+#define TSM70_FN_INDEX		0x45
+#define TSM70_FN_ENABLE		0x75
+#define TSM70_FN_DISABLE	0x74
+#define TSM70_HOTKEYS_INDEX	0x59
+#define TSM70_HOTKEYS_ENABLE	0x90
+#define TSM70_HOTKEYS_DISABLE	0x91
+#define TSM70_LCD_READ		0x5C
+#define TSM70_LCD_WRITE		0x5D
+#define TSM70_TOUCHPAD_ON 	0x80
+#define TSM70_TOUCHPAD_OFF	0x81
+#define TSM100_BLANK_INDEX	0x59
+#define	TSM100_LCD_ON		0xe1
+#define	TSM100_LCD_OFF		0xe2
+#define TSM70_COOLING_OFFSET	0xb0
+#define TSM70_COOLING_POWERSAVE	0x0
+#define TSM70_COOLING_PERF	0x2
+
+/* Toshiba SMI funtions and constants*/
+#define SMI_FN_PRESSED		0x8f
+#define SMI_SET_LCD_BRIGHTNESS	0xa2
+#define SMI_GET_LCD_BRIGHTNESS	0xa3
+#define SMI_GET_KILL_SWITCH	0xa4
+#define SMI_SET_AERIAL		0xa5
+#define SMI_GET_AERIAL		0xa6
+#define SMI_SET_DISPLAY_STATE	0xa7
+#define SMI_GET_DISPLAY_STATE	0xa8
+#define SMI_SET_FN_INTERFACE	0xa9
+#define SMI_GET_FN_INTERFACE	0xaa
+#define SMI_GET_FN_LAST_SCAN	0xab
+#define SMI_SET_DOCK		0xac	/* Undocumented */
+#define SMI_GET_DOCK		0xad	/* Undocumented */
+#define SMI_SET_FN_F5_INTERFACE	0xc2
+
+#define SMI_FN_KEYS_MASK	0x01
+#define SMI_STICK_KEYS_MASK	0x02
+#define SMI_FN_TWICE_LOCK_MASK	0x04
+#define SMI_FN_DOCK_MASK	0x08
+
+#define SMI_FN_SCAN		0x6d	/* Fn key scancode */
+#define	SMI_DOCK_SCAN		0x6e	/* Dock scancode */
+
+/* Toshiba HCI method and constants */
+#define HCI_METHOD		"SPFC"
+#define HCI_WORDS		6
+
+#define HCI_GET			0xfe00
+#define HCI_SET			0xff00
+
+#define HCI_HOTKEY_EVENT	0x001e
+#define HCI_RF_CONTROL		0x0056
+
+#define HCI_ENABLE		0x0001
+#define HCI_DISABLE		0x0000
+
+#define HCI_WIRELESS_CHECK	0x0001
+#define HCI_WIRELESS_POWER	0x0200
+
+#define HCI_SUCCESS		0x0000
+#define HCI_FAILURE		0x1000
+#define HCI_NOT_SUPPORTED	0x8000
+
+/* Toshiba Satellite X205 methods */
+#define TSX205_EVENTS_METHOD	"INFO"
+#define TSX205_NOTIFY_METHOD	"NTFY"
+#define TSX205_KILLSW_METHOD	"KLSW"
+#define TSX205_SLIVDO_METHOD	"CSLI"
+
+#define ACPI_FN_MASK		0x01
+#define ACPI_FN_SCAN		0x6e	/* Fn key scancode */
+
+/* HCI key definitions */
+#define HCI_FN_RELEASED		0x100
+#define HCI_MUTE		0x101
+#define HCI_1			0x102
+#define HCI_2			0x103
+#define HCI_SPACE		0x139
+#define HCI_BREAK		0x13b
+#define HCI_BSM			0x13c
+#define HCI_SUSPEND		0x13d
+#define HCI_HIBERNATE		0x13e
+#define HCI_VIDEOOUT		0x13f
+#define HCI_BRIGHTNESSDOWN	0x140
+#define HCI_BRIGHTNESSUP	0x141
+#define HCI_WLAN		0x142
+#define HCI_TOUCHPAD		0x143
+#define HCI_FN_PRESSED		0x17f
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/display.c
+++ linux-ec2-2.6.32/ubuntu/omnibook/display.c
@@ -0,0 +1,114 @@
+/*
+ * display.c -- External display (LCD,VGA,TV-OUT) feature
+ * 
+ * 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, 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.
+ *
+ * Written by Soós Péter <sp@osb.hu>, 2002-2004
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ */
+
+#include "omnibook.h"
+#include "hardware.h"
+
+static const char display_name[][16] = {
+	"Internal LCD",
+	"External VGA",
+	"External TV-OUT",
+	"External DVI",
+};
+
+static int omnibook_display_read(char *buffer, struct omnibook_operation *io_op)
+{
+	int len = 0;
+	int retval;
+	unsigned int sta, en_mask, det_mask;
+
+	retval = backend_display_get(io_op, &sta);
+	if (retval < 0)
+		return retval;
+
+	for (en_mask = DISPLAY_LCD_ON; en_mask <= DISPLAY_DVI_ON; en_mask = en_mask << 1) {
+		det_mask = en_mask << 4;	/* see display masks in omnibook.h */
+		if (!(retval & en_mask) && !(retval & det_mask))
+			continue;	/* not supported */
+		len += sprintf(buffer + len, "%s:", display_name[ffs(en_mask) - 1]);
+		if (retval & det_mask)
+			len +=
+			    sprintf(buffer + len, " display %s",
+				    (sta & det_mask) ? "present" : "absent");
+		if (retval & en_mask)
+			len +=
+			    sprintf(buffer + len, " port %s",
+				    (sta & en_mask) ? "enabled" : "disabled");
+		len += sprintf(buffer + len, "\n");
+	}
+
+	return len;
+}
+
+static int omnibook_display_write(char *buffer, struct omnibook_operation *io_op)
+{
+	int retval;
+	unsigned int state;
+	char *endp;
+
+	state = simple_strtoul(buffer, &endp, 16);
+	if (endp == buffer)
+		return -EINVAL;
+	else
+		retval = backend_display_set(io_op, state);
+
+	return retval;
+}
+
+static struct omnibook_feature display_driver;
+
+static int __init omnibook_display_init(struct omnibook_operation *io_op)
+{
+	int retval;
+	unsigned int state;
+	
+	/* Disable file writing if unsuported by backend */
+	if (!io_op->backend->display_set)
+		display_driver.write = NULL;
+		
+	retval = backend_display_get(io_op, &state);
+	if (retval < 0)
+		return retval;
+	else
+		return 0;
+}
+
+static struct omnibook_tbl display_table[] __initdata = {
+	{TSM70 | TSX205, {ACPI,}},
+	{TSM40, {SMI, SMI_GET_DISPLAY_STATE, SMI_SET_DISPLAY_STATE, 0, 0, 0}},
+	{XE3GF | TSP10 | TSM70 | TSM30X | TSM40, SIMPLE_BYTE(EC, XE3GF_STA1, XE3GF_SHDD_MASK)},
+	{XE3GC, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_CRTI_MASK)},
+	{OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA1, OB500_CRTS_MASK)},
+	{OB4150, SIMPLE_BYTE(EC, OB4150_STA2, OB4150_CRST_MASK)},
+	{0,}
+};
+
+static struct omnibook_feature __declared_feature display_driver = {
+	.name = "display",
+	.enabled = 1,
+	.init = omnibook_display_init,
+	.read = omnibook_display_read,
+	.write = omnibook_display_write,
+	.ectypes =
+	    XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | TSP10 | TSM70 | TSM30X |
+	    TSM40 | TSX205,
+	.tbl = display_table,
+};
+
+module_param_named(display, display_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(display, "Use 0 to disable, 1 to enable display status handling");
+/* End of file */
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/changelog
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/changelog
@@ -0,0 +1,170 @@
+omnibook (2:2.20070211+svn20090714b-1) unstable; urgency=low
+
+  * New SVN snapshot:
+    + fix build issue induced by previous patches
+    + fix build with kernel >= 2.6.30
+
+ -- Julien Valroff <julien@kirya.net>  Tue, 14 Jul 2009 18:17:49 +0200
+
+omnibook (2:2.20070211+svn20090714-1) unstable; urgency=low
+
+  * New SVN snapshot:
+    + Applied patches from Azael Avalos <coproscefalo@gmail.com>
+    to add support to Satellite X205 and other laptops based on
+    ICH8
+  * New Standards version 3.8.2
+  * Bumped DH compat to 7
+  * Updated copyright information
+  * Now use dh_prep instead of dh_clean -k
+
+ -- Julien Valroff <julien@kirya.net>  Tue, 14 Jul 2009 10:03:00 +0200
+
+omnibook (2:2.20070211+svn20090227-1) unstable; urgency=low
+
+  * New SVN snapshot
+    + Applied patch from Danny Kukawka <dkukawka@suse.de> to
+    fix compiler warning about use uninitialized variable
+    + Applied patch from Danny Kukawka <dkukawka@suse.de> to
+    fix build the driver on older kernel versions
+
+  * New Standards version 3.8.0 - no further changes needed
+  * Updated copryight information
+
+ -- Julien Valroff <julien@kirya.net>  Fri, 27 Feb 2009 19:57:35 +0100
+
+omnibook (2:2.20070211+svn20071217-1) unstable; urgency=low
+
+  * New SVN snapshot (r271)
+  * Added amd64 as a compatible architecture for the module
+  * New Standards version 3.7.3 - no further changes needed
+
+ -- Julien Valroff <julien@kirya.net>  Mon, 17 Dec 2007 18:00:29 +0100
+
+omnibook (2:2.20070211+svn20071006-1) unstable; urgency=low
+
+  * New SVN snapshot (r264):
+    + Update for acpi and backlight API changes in linux 2.6.23
+  * First upload to Debian (Closes: #445602):
+    + Improved debian/copyright
+    + Bumped debhelper compat to version 5
+    + Added myself as maintainer
+    + Updated README.Debian
+  * debian/control:
+    + Moved Homepage to own field (from pseudo-field in long description)
+    + Added Vcs-* fields
+
+ -- Julien Valroff <julien@kirya.net>  Thu, 29 Nov 2007 18:30:27 +0100
+
+omnibook (2:2.20070211+svn20070905-1) unstable; urgency=low
+
+  * Added dependency on dpatch
+  * [debian/rules]:
+    - Fixed lintian warning in the clean target
+
+ -- Julien Valroff <julien@kirya.net>  Wed, 05 Sep 2007 20:25:13 +0200
+
+omnibook (2:2.20070211+svn20070526-1) unstable; urgency=low
+
+  * New SVN snapshot (r259):
+    + Fixed compilation issue with kernel 2.6.21
+    + DMI signature added:
+        Toshiba Satellite P25 (ectype 11)
+        Toshiba Satellite M60 (ectype 12)
+  * Added patch to disable debug for SVN snasphot
+
+ -- Julien Valroff <julien@kirya.net>  Sat, 26 May 2007 15:19:57 +0200
+
+omnibook (2:2.20070211-1) unstable; urgency=low
+
+  * New upstream release:
+    + For ectype 12 (Satellite M40X, M70, M100, ...):
+      - improved bluetooth control
+      - cooling method control
+      - CPU throttling ( ACPI T-States)
+    + Full hotkeys support for Tecra S1
+    + Bluetooth control for Ectype 14 (Satellite A100, A105, M115, ...)
+  * Updated homepage in long description
+
+ -- Julien Valroff <julien@kirya.net>  Mon, 12 Feb 2007 18:50:05 +0100
+
+omnibook (2:2.20060921+svn20061202-1) unstable; urgency=low
+
+  * New SVN snapshot (r228)
+
+ -- Julien Valroff <julien@kirya.net>  Sat,  2 Dec 2006 10:17:07 +0100
+
+omnibook (2:2.20060921+svn20061112-1) unstable; urgency=low
+
+  * SVN snapshot:
+    + Disabled Acer support
+    + Fixed and improved bluetooth handling for TSM30X class laptop
+    + DMI signature added:
+      HP Pavilion ze4500 (ectype 7)
+      Toshiba Satellite 1130 (ectype 1)
+      Toshiba Satellite A75 (ectype 12)
+      Toshiba Tecra A4 (ectype 13)
+    + Implemented Volume down,up and Mute buttons polling for ectype 2
+    + Implemented ectype 13 Fn hotkeys handling.
+  * changed compression of the sources in /usr/src/ to bzip2
+
+ -- Julien Valroff <julien@kirya.net>  Sat, 11 Nov 2006 14:08:47 +0100
+
+omnibook (2:2.20060921-1) unstable; urgency=low
+
+  * New upstream release:
+    + Expand display and hotkeys features
+    + Added support for more laptops
+    + Code cleanups
+    + Minor bug fixes
+
+ -- Julien Valroff <julien@kirya.net>  Mon, 25 Sep 2006 08:14:59 +0200
+
+omnibook (2:2.20060817-1) unstable; urgency=low
+
+  * New upstream release
+  * [01_makfefile.dpatch] Removed - fixed upstream
+  * Changed defaut STEM value to linux (follows kernel-package)
+  * Uses dh_installmodules for maintainance scripts
+
+ -- Julien Valroff <julien@kirya.net>  Mon, 11 Sep 2006 18:00:50 +0200
+
+omnibook (2:2.20060809-2) unstable; urgency=low
+
+  * Include copyright and Debian changelog in omnibook-module
+  * Fix Makefile issue in a more elegant way
+
+ -- Julien Valroff <julien@kirya.net>  Thu, 10 Aug 2006 10:16:47 +0200
+
+omnibook (2:2.20060809-1) unstable; urgency=low
+
+  * New upstream release:
+    + Addeed autodetection of the Toshiba Satellite M40X laptop
+
+ -- Julien Valroff <julien@kirya.net>  Thu, 10 Aug 2006 09:40:45 +0200
+
+omnibook (2:2.20060806-1) unstable; urgency=low
+
+  * New upstream branch - Mathieu Bérard launched new project
+  * Added myself as co-maintainer
+  * Bumped upstream version and use epoch to ensure upgrades
+  * [debian/rules]:
+    + Clean-ups
+    + Recommends linux-image or kernel-image
+  * [debian/control] Improved long description
+  * [debian/post*.modules.in] Fixed bashisms
+  * Added patch to fix install target in Makefile
+
+ -- Julien Valroff <julien@kirya.net>  Thu, 10 Aug 2006 01:35:38 +0200
+
+omnibook (20060126-1) unstable; urgency=low
+
+  * Minor build inconveniences corrected.
+
+ -- Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>  Sun, 18 Jun 2006 12:28:55 -0700
+
+omnibook (20060126-0) unstable; urgency=low
+
+  * Locally built.
+
+ -- Péter Soós <sp@osb.hu>  Wed, 25 Jan 2006 21:06:28 +0100
+
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/rules
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/rules
@@ -0,0 +1,135 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode. 
+#export DH_VERBOSE=1
+
+include /usr/share/dpatch/dpatch.make
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+
+# Name of the source package
+psource	:= omnibook-source
+
+# The short upstream name, used for the module source directory
+sname	:= omnibook
+
+# prefix of the target package name
+PACKAGE=omnibook-module
+
+### end  KERNEL SETUP
+
+configure: configure-stamp
+configure-stamp:
+	dh_testdir
+	touch configure-stamp
+
+
+build-arch: configure-stamp  build-arch-stamp
+build-arch-stamp:
+	dh_testdir
+	touch build-arch-stamp
+
+build-indep: patch configure-stamp build-indep-stamp
+build-indep-stamp:
+	dh_testdir
+
+	touch build-indep-stamp
+
+build: patch build-arch build-indep
+
+clean: unpatch
+	dh_testdir
+	rm -f build-arch-stamp build-indep-stamp configure-stamp
+
+	dh_clean
+
+install: DH_OPTIONS=
+install: patch build
+	dh_testdir
+	dh_testroot
+	dh_prep
+	dh_installdirs
+
+	# Create the directories to install the source into
+	dh_installdirs -p$(psource)  usr/src/modules/$(sname)/debian
+	cp debian/compat debian/rules debian/changelog \
+		debian/control debian/copyright debian/*.modules.in \
+		debian/$(psource)/usr/src/modules/$(sname)/debian
+	cp Makefile *.c *.h *.lds debian/$(psource)/usr/src/modules/$(sname)
+
+	cd debian/$(psource)/usr/src && tar c modules | bzip2 -9 > $(sname).tar.bz2 && rm -rf modules
+	dh_install
+
+# Build architecture-independent files here.
+# Pass -i to all debhelper commands in this target to reduce clutter.
+binary-indep: build install
+	dh_testdir -i
+	dh_testroot -i
+	dh_installchangelogs -i doc/ChangeLog
+	dh_installdocs -i
+	dh_installexamples -i
+	dh_installman -i
+	dh_link -i
+	dh_compress -i
+	dh_fixperms -i
+	dh_installdeb -i
+	dh_installdeb -i
+	dh_shlibdeps -i
+	dh_gencontrol -i
+	dh_md5sums -i
+	dh_builddeb -i
+ 
+# Build architecture-dependent files here.
+binary-arch: build install
+
+# modifieable for experiments or debugging m-a
+MA_DIR ?= /usr/share/modass
+# load generic variable handling
+-include $(MA_DIR)/include/generic.make
+# load default rules, including kdist, kdist_image, ...
+-include $(MA_DIR)/include/common-rules.make
+
+ifndef KPKG_STEM
+STEM:=linux
+else
+STEM:=${KPKG_STEM}
+endif
+
+kdist_clean: prep-deb-files
+	[ ! -f Makefile ] || $(MAKE) KSRC=$(KSRC) clean
+	dh_clean
+
+kdist_config: prep-deb-files
+	sed -i -e 's/_STEM_/$(STEM)/g' debian/control
+
+binary-modules: kdist_config prep-deb-files
+	dh_testroot
+	dh_prep
+	dh_installdirs lib/modules/$(KVERS)/extra
+
+	# Build the module
+	$(MAKE) KSRC=$(KSRC) KVERS=$(KVERS)
+
+	# Install the module
+	$(MAKE) install KSRC=$(KSRC) DESTDIR=$(CURDIR)/debian/$(PKGNAME) INSTDIR=extra DEPMOD="/bin/true"
+
+	dh_installdocs
+	dh_compress
+	dh_installmodules
+	dh_installchangelogs
+	dh_fixperms
+	dh_installdeb
+	dh_gencontrol -- -v$(VERSION)
+	dh_md5sums
+	dh_builddeb --destdir=$(DEB_DESTDIR)
+	dh_prep
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure binary-modules kdist kdist_config kdist_image kdist_clean
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/control
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/control
@@ -0,0 +1,21 @@
+Source: omnibook
+Section: misc
+Priority: optional
+Maintainer: Julien Valroff <julien@kirya.net>
+Build-Depends: debhelper (>> 7.0.0), dpatch, bzip2
+Standards-Version: 3.8.2
+Homepage: http://omnibook.sf.net
+Vcs-Svn: https://omnibook.svn.sourceforge.net/svnroot/omnibook/omnibook/trunk
+Vcs-Browser: http://omnibook.svn.sourceforge.net/viewvc/omnibook/
+
+Package: omnibook-source
+Architecture: all
+Depends: debhelper (>= 4.0.0), make, module-assistant, kernel-package, bzip2, dpatch
+Description: Source for the omnibook driver
+ This package contains the loadable kernel modules for the HP OmniBooks,
+ Pavilions, Toshiba Satellites and some other laptops manufactured by
+ Compal Electronics, Inc as ODM.
+ .
+ This module is only compatible with Linux kernels >= 2.6.9
+ .
+ Kernel source is required to compile this module.
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/control.modules.in
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/control.modules.in
@@ -0,0 +1,23 @@
+Source: omnibook
+Section: misc
+Priority: optional
+Maintainer: Julien Valroff <julien@kirya.net>
+Build-Depends: debhelper (>> 7.0.0)
+Standards-Version: 3.8.2
+
+Package: omnibook-module-_KVERS_
+Architecture: i386 amd64
+Recommends: _STEM_-image-_KVERS_
+Provides: omnibook-module
+Description: omnibook module for Linux (kernel _KVERS_)
+ This package contains the loadable kernel modules for the HP OmniBooks,
+ Pavilions, Toshiba Satellites and some other laptops manufactured by
+ Compal Electronics, Inc as ODM.
+ .
+ This package contains the compiled kernel modules for _KVERS_
+ .
+ If you have compiled your own kernel, you will most likely need to build
+ your own omnibook-module.  The omnibook-source package has been
+ provided for use with the Debian kernel-package utility to produce a version
+ of omnibook-module for your kernel.
+
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/compat
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/compat
@@ -0,0 +1 @@
+7
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/docs
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/docs
@@ -0,0 +1,4 @@
+doc/BUGS
+doc/CREDITS
+doc/README
+misc/hotkeys
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/copyright
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/copyright
@@ -0,0 +1,32 @@
+This package was debianized by Peter Soos <sp@osb.hu> on
+Wed, 25 Jan 2006 21:06:28 +0100.
+Debian package was improved by Julien Valroff <julien@kirya.net>
+
+It was downloaded from http://sourceforge.net/projects/omnibook
+
+Copyright Holder: 2006-2007 Mathieu Bérard <math_b@users.sourceforge.net>
+
+dump.c:
+   Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
+
+License:
+
+   This package 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 package 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.
+
+The Debian packaging is
+  Copyright (C) 2006 Peter Soos <sp@osb.hu>
+  Copyright (C) 2006-2009 Julien Valroff <julien@kirya.net>
+It is licensed under the GPL, version 2.
+
+You should have received a copy of the GNU General Public License with
+the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL-2;
+if not, write to the  Free Software Foundation, Inc., 51 Franklin St,
+Fifth Floor, Boston, MA 02110-1301, USA.
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/debian/README.Debian
+++ linux-ec2-2.6.32/ubuntu/omnibook/debian/README.Debian
@@ -0,0 +1,30 @@
+omnibook for Debian
+-------------------
+
+Please see docs/README for a description of the omnibook kernel module.
+
+The Debian omnibook source package provides omnibook-source, package
+which provides the source for the kernel module.
+
+The omnibook-source package can be used in several ways,
+
+ - Using the make-kpkg(1) command provided by the kernel-package Debian
+   package. This will produce a corresponding omnibook-modules package for
+   the Debian kernel-image package that you are using.
+   See the "modules_image" section of the make-kpkg(1) man page.
+ 
+ - Using module-assistant. Simply issue the following command (as root):
+   $ module-assistant auto-install omnibook
+   Please see the module-assistant documentation for futher details.
+
+ - Changing to the /usr/src/modules/omnibook/ directory and building as
+   the README file instructs using "make; make install". This will build
+   and install a module specific to the system you are building on and is
+   not under control of the packaging system.
+
+If your are not using module-assisatant, you have to unpack 
+/usr/src/omnibook-source.tar.bz2 to /usr/src.
+
+ -- Peter Soos <sp@osb.hu>, Wed, 25 Jan 2006 21:06:28 +0100
+ -- Julien Valroff <julien@kirya.net>  Sun, 07 Oct 2007 10:38:07 +0200
+
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/doc/COPYING
+++ linux-ec2-2.6.32/ubuntu/omnibook/doc/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/doc/ChangeLog
+++ linux-ec2-2.6.32/ubuntu/omnibook/doc/ChangeLog
@@ -0,0 +1,521 @@
+Changelog file for omnibook package:
+------------------------------------
+
+2.XXXXXXXX Mathieu Bérard <math_b@users.sourceforge.net>
+* DMI signature added:
+	Toshiba Satellite P25 (ectype 11)
+	Toshiba Satellite M60 (ectype 12)
+* Applied patch from Danny Kukawka <dkukawka@suse.de> to
+  fix compiler warning about use uninitialized variable
+* Applied patch from Danny Kukawka <dkukawka@suse.de> to
+  fix build the driver on older kernel versions
+* Applied patches from Azael Avalos <coproscefalo@gmail.com>
+  to add support to Satellite X205 and other laptops based on
+  ICH8
+* Fix build with kernel >= 2.6.30
+
+2.20070211 Mathieu Bérard <math_b@users.sourceforge.net>
+* Disable Acer support, acerhk module should provided better
+  support with a far more complete autodetection database
+  (see http://www2.informatik.hu-berlin.de/~tauber/acerhk/)
+* Fix and improve bluetooth handling for TSM30X class laptops
+  bluetooth now also works for TSA105
+* Implement Volume down,up and Mute buttons polling for ectype 2
+   It was the last missing part from the "omke" module which never
+   got ported to linux 2.6
+* Implement ectype 13 Fn hotkeys handling.
+* DMI signature added:
+	HP Pavilion ze4500 (ectype 7)
+	Toshiba Satellite 1130 (ectype 1)
+	Toshiba Satellite A75 (ectype 12)
+	Toshiba Tecra A4 (ectype 13)
+	Toshiba Satellite A80 (ectype 12)
+	Toshiba Satellite P100 (ectype 14)
+* Split TSM30X (ectype 12) : this ectype was reimplemented and if the
+  new implementation works with Toshiba M40X, M70, M100... it does not
+  (and will never, due to hardware) with Toshiba M30X, the only way
+  to fix this is to split TSM30X (ectype 12) in :
+  -TSM70 (ectype 12) => new implementation (compal.c & acpi.c backends)
+  -TSM30X (ectype 15) => old implementation (legacy backends)
+  This is done by renaming TSM30X to TSM40 and restore old TSM30X
+  The state of the Toshiba M35X is unknown and is assigned to TSM70, one
+  should send a bug report if that fail.
+  Fix bugs 1617818 and 1605278
+* New features for TSM70 class laptops:
+  -Cooling method control (can tune fan behaviour to 'Save power' or
+   to 'Maximize performance') provided in /proc/omnibook/cooling 
+  -CPU Throttling status&control (also known as ACPI T-States) should
+   be supported out of the box via /proc/acpi/processor/CPU0/throttling
+   but at least Toshiba Satellite M70 as a deficient ACPI FADT table
+   which prevent than, thus a custom access to ACPI Throttling is 
+   provided in /proc/omnibook/throttling
+
+2.20060921 Mathieu Bérard <math_b@users.sourceforge.net>
+* The minimal required kernel version is now 2.6.9 (kref API)
+* Convert semaphore to mutex with fallback for pre 2.6.16 kernel
+* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY:
+  pre-ACPI features now depends on it.
+  Default enabling of ac and battery features also
+  depends on it. It is _disabled_ by default.
+* Introduce ACPI methods execution backend: TSM70 needs it
+  for Display and Wifi/Bluetooth features
+* Expand display and hotkeys features
+* Introduce experimental NbSmi backend for TSM40. It is
+  based on technical documentation provided by Toshiba.
+  Thanks Toshiba !
+* Kill unused omnibook_mem_read/write function for mmio
+  access
+* Cleanup in blank.c fan.c temperature.c
+* Unbreak Pio backend: use request/release_region
+* Introduce bluetooth and wifi frontend features : they allow
+  adapter state querry and control (existence probing, wifi
+  kill switch probing and adapter enabling/disabling).
+  Supported by TSM30X and TSM40
+* Introduce omnibook_backend struct as a uniform way of 
+  communication between backend and frontend, this
+  kill omnibook_io_{read/write} and friends.
+* Modify ombibook_feature struct to incorporate pointers
+  to an omnibook_table table and to a omnibook_operation
+  struct which is picked-up from the ectype matching
+  omnibook_table entry upon feature initialization
+* Add muteled resume handler
+* Add touchpad handling for TSM30X
+* Add proper display handling for TSM30X
+* Change all features struct name from foo_feature to
+  foo_driver to kept modpost section mismatch detection
+  silent. Put tbl, init and exit entries to their relevant
+  sections.
+* Many bugfix and dock support for TSM40 by Holger Nelson.
+* Add DMI Signature for Toshiba Satellite 1700-Series, with ectype 10.
+  LCD does not work.
+* Add DMI Signature for Toshiba Equium A110, added with
+  ectype 1, until implementation of a better backend
+* Add DMI Signature for Toshiba _Satellite_ M100, Satellite A70 
+  and Tecra S2. added with ectype 12
+* Add DMI Signature for Toshiba Tecra S1, added with
+  ectype 13
+
+2.200608017 Mathieu Bérard <math_b@users.sourceforge.net>
+* Fix bug un omnibook_io_match
+* Fix DMI handling behaviour: we stop on the FIRST matched
+  DMI entry. This is restoring pre-20060806 behaviour.
+  Invert M40 vs. M40X entry position.
+
+2.20060816 Mathieu Bérard <math_b@users.sourceforge.net>
+* Merge from the new-backend branch: Add new backend code 
+  (in compal.c) used with TSM30X class laptops:
+  Used for lcd access
+  Used for hotkeys support: now most Fn+key generate a scancode,
+  as well as the wifi kill switch.
+  Warning: tested only on TSM40X an TSM70 laptops.
+* Create omnibook_io_operation struct and omnibook_io_{read/write}
+  funtions to simplify implementation of some simple features.
+  Used with ac display dock and led features.
+* Rename onetouch feature to "hotkeys" which is a vendor neutral name.
+* The minimal required kernel version is now 2.6.9 (kref API)
+* Convert semaphore to mutex with fallback for pre 2.6.16 kernel
+* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY:
+  pre-ACPI features now depends on it.
+  Default enabling of ac and battery features also
+  depends on it. It is _disabled_ by default.
+* Introduce ACPI methods execution backend: TSM70 needs it
+  for Display and Wifi/Bluetooth features
+* Expand display and hotkeys features
+* Introduce experimental NbSmi backend for TSM40. It is
+  based on technical documentation provided by Toshiba.
+  Thanks Toshiba !
+* Kill unused omnibook_mem_read/write function for mmio
+  access
+* Cleanup in blank.c fan.c temperature.c
+* Unbreak Pio backend: use request/release_region
+* Introduce bluetooth and wifi frontend features : they allow
+  adapter state querry and control (existence probing, wifi 
+  kill switch probing and adapter enabling/disabling).
+  Supported by TSM30X and TSM40
+* Introduce omnibook_backend struct as a uniform way of 
+  communication between backend and frontend, this
+  kill omnibook_io_{read/write} and friends.
+* Modify ombibook_feature struct to incorporate pointers
+  to an omnibook_table table and to a omnibook_operation
+  struct which is picked-up from the ectype matching
+  omnibook_table entry upon feature initialization
+* Add muteled resume handler
+* Add touchpad handling for TSM30X
+* Add proper display handling for TSM30X
+* Change all features struct name from foo_feature to
+  foo_driver to kept modpost section mismatch detection
+  silent. Put tbl, init and exit entries to their relevant
+  sections.
+
+2.20060809 Mathieu Bérard <math_b@users.sourceforge.net>
+* Add dmi info for Toshiba Satellite M40X (Thanks Julien Valroff) 
+* Fix two brown paper bag bugs in Debian/Ubuntu support 
+
+2.20060806 Mathieu Bérard <math_b@users.sourceforge.net>
+* Make the module linux 2.6 only
+  Kernel versions from 2.6.8 to a least 2.6.17 are supported
+  Code for compatibility with kernels older than 2.6.17 is 
+  mostly implemented in compat.h
+* Integrate with Driver Model:
+  register as a platform device and optional
+  registration as a backlight device (2.6.17+ required here)
+* Get rid of deprecated pm_legacy functions
+* Use kernel-provided DMI information:
+  Use kernel-provided dmi_check_system for system identification
+  omnibook_tc_t and omnibook_models_t are merged and converted into a
+  dmi_system_id struct and moved from init.c to laptop.h
+* MODULE_PARAM -> 2.6-style module_parm_*
+* Move some code from "feature".c files back to init.c
+  Interface is provided by the new omnibook_feature struct
+  Enabled features are now in placed in a linked list
+  This eliminate util.c
+  Rationale: Reduce code duplication and create a standard template for features
+* Move dmi and version display into their own file: info.c
+* Remove all (as unneeded) EXPORT_SYMBOL
+* Misc fixes in Makefile
+  Also make more use of Kbuild
+* Use sscanf and simple_stro{u}l for strings parsing instead of custom code
+* Run lindent for better conformance with kernel coding style
+* Add very limited support for some Toshiba M40 (more info needed)
+* Use bitmasks for EC types matching, this change is transparent for the user
+  (e.g. one can still use ectype=num module parameter)
+  Rationale: Reduce the size of the omnibook_feature struct
+* Polish Debian support: Use module-assistant and fix all Lintian warning
+  Fix building against non-running kernel (Thanks to Daniel Gimpelevich)
+* Update documentation and omnibook-integration.patch
+* Fix spinlock usage: they can be used unconditionally as they are automatically
+  optimized out at build-time on UP. This should improve PREEMPT safety
+* Spinlock protect omnibook_mem_* and use ioread8 and iowrite8
+* Fix: Custom EC access function are also used if ACPI is compiled but disabled
+* Cleanup: remove lots of unneeded #ifdef
+* Add a new feature for testers: dump
+  Dump was stolen from the ibm_acpi driver
+  It is disabled by default
+* Bump version to 2.YYYYMMDD
+
+2006-05-15 Thomas Perl <thp@perli.net>
+* Added support for xe4500's "audio mute" led
+
+2006-01-26 Soós Péter <sp@osb.hu>
+* Added support for kernels >= 2.6.15 (pm_legacy.h)
+* Added Toshiba Satellite M30X
+* Added support for Toshiba Satellite M70
+* Added support for HP Pavilion ze4300 series
+* Fixed module unloading on 2.6 series kernels (thanks to
+  math_b@users.sourceforge.net)
+* Changed version number to +%Y%m%d format
+* Added Debian support
+
+2005-02-17 Soós Péter <sp@osb.hu> 
+* Fixed Makefile
+* Updated Toshiba 1115 information
+
+2004-12-15 Scott Barnes <reeve@users.sourceforge.net>
+* Added Toshiba Satellite M35X
+
+2004-09-16 Soós Péter <sp@osb.hu>
+* Added INSTALL-2.6 file
+* Little spelling fixes in documentation
+* Little bugfixes
+* Added Compal ACL10
+
+2004-07-01 Soós Péter <sp@osb.hu>
+* Added new technology codes
+* Added some new HP nx9000 detection string
+* Added Toshiba Satellite P20
+
+2004-06-07 Chris Green <cmg@dok.org>
+* Added Toshiba Satellite P15
+
+2004-06-01 Soós Péter <sp@osb.hu>
+* Added Toshiba Satellite 1955
+* Added Toshiba Satellite 2435
+* Added Toshiba Satellite P10 (new ectype)
+* Acer Aspire 1350
+
+2004-01-23 Soós Péter <sp@osb.hu>
+* Added HP Pavilion ze8500 (HP nx9010)
+* fixed PM handler for OneTouch keys and touchpad
+
+2004-01-20 Soós Péter <sp@osb.hu>
+* Only fan status supported on HP OmniBook 4150, XE2 and
+  Fujitsu-Siemens Amilo D, fan control is unsupported
+* #include fixes in ec.c
+
+2004-01-16 Soós Péter <sp@osb.hu>
+* Added fan support for Fujitsu-Siemens Amilo D series laptops
+
+2004-01-14 Soós Péter <sp@osb.hu>
+* Fixed Makefile for kernels 2.6
+* Added Fujitsu-Siemens Amilo D series laptops (new ectype)
+
+2003-12-08 Soós Péter <sp@osb.hu>
+
+* Fixed tecnology code detection
+* Added HP/Compaq nx9005
+* Fixed Makefile for kernel 2.4
+
+2003-11-12 Soós Péter <sp@osb.hu>
+
+* Fixed KERNEL_WARNING in init.c
+
+2003-11-10 Soós Péter <sp@osb.hu>
+
+* Fixed timeout bugs in ec.c
+* Fixed touchpad dependency code for kernel 2.6
+* Added Compaq nx9000
+
+2003-11-10 Mark Chappell <mark@nslm.fsnet.co.uk>
+
+* Added kernel 2.6 support to Makefile
+
+2003-10-23 Soós Péter <sp@osb.hu>
+
+* Totally removed key polling code for kernels >= 2.5.0 but 2.5/2.6 kernels
+  is unsuported yet
+* proc_battery is static
+* Added HP OmniBook 900 B support
+* Added HP OmniBook XE2 support (added new ectype value for it)
+* Added Compaq nx9010
+* Reversed ChangeLog
+* Some documentation changes
+
+2003-08-28 Soós Péter <sp@osb.hu>
+
+* Added Toshiba Satellite 2430
+* Documentation enhancements
+
+2003-04-03 Soós Péter <sp@osb.hu>
+
+* Really fixed __init bug in user parameter code
+* Fixed omnibook_dmi_ident (it was static)
+
+2003-03-31 Soós Péter <sp@osb.hu>
+
+* Fixed HP technology code detection
+* Key polling is disabled by default on XE3GC style machines
+* Fixed PM code in polling.c
+* Added util.c
+* Fixed __init bug in user parameter code
+* Cleaned up ec.h
+* Added Toshiba Satellite 1950 detection
+* Documentation enhancements
+
+2003-03-13 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion ZU1155 and ZU1175 detection
+
+2003-03-11 Soós Péter <sp@osb.hu>
+
+* Fixed bogus version information
+
+2003-03-06 Ducrot Bruno <ducrot@poupinou.org>
+
+* Fan off hack for XE3GF style machines
+
+2003-03-04 Ducrot Bruno <ducrot@poupinou.org>
+
+* Fixed spinlock problem
+
+2003-02-28 Soós Péter <sp@osb.hu>
+
+* Added /proc/omnibook/version
+* Added OMNIBOOK_ prefix to MODULE_NAME and MODULE_VERSION definitions
+* Fixed bugs in lcd.c (thanks to Bernhard Kaindl <bernhard.kaindl@gmx.de>)
+* Some code tuning and cosmetic changes
+* Fixed OmniBook 4150 support
+
+2003-02-26 Soós Péter <sp@osb.hu>
+
+* Fixed kernel Oops in technology code identification
+* Some minor changes in logging
+
+2003-02-25 Soós Péter <sp@osb.hu>
+
+* Try to identify HP laptops by technology code if machine is unsupported
+* Fixed dmi identification code
+
+2003-02-14 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion ze4100 support
+* Added HP Pavilion ze4200 support
+* Fixed HP Pavilion xt155 detection
+* Added Acer Aspire 1400 series laptop support
+* Fixed APM status detection bug
+* Cleaned up dmi identification code
+* Removed "Asset Tag:" field from dmi string structure
+
+2003-01-27 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion N5430 support
+* EC functions are work even if boot parameter acpi=off is given
+* Improved error handling in externally callable functions
+* Fixed kernel integration patch
+* Removed unreliable undocking feature for OB500
+* Fixed HP Pavilion N5415 support
+* Added new format hotkeys sample files
+
+2003-01-09 Ducrot Bruno <ducrot@poupinou.org>
+
+* Added to use ACPI_EC if available
+
+2003-01-09 Soós Péter <sp@osb.hu>
+
+* Fixed reverse console blanking bug on OB5xx and OB6xxx
+* Disabled unreliable undocking feature on OB500
+
+2003-01-08 Ducrot Bruno <ducrot@poupinou.org>
+
+* Added Toshiba Satellite 3000, 3005, 1000, 1005, 1110, 1115, 1900, 1905
+  support
+
+2003-01-08 Soós Péter <sp@osb.hu>
+
+* The ectype values changed again! See the README!
+* Fixed new ectypes detection bug
+* Added OmniBook xe4400 support
+* Added LCD display turn off at console blanking on OB5xx and OB6xxx
+* Documentation fixes
+
+2003-01-07 Soós Péter <sp@osb.hu>
+
+* Fixed bit level negation bug in fan.c
+* Added turn fan on for Toshiba 3000
+* Corrected OmniBook 4150 support code
+
+2003-01-06 Soós Péter <sp@osb.hu>
+
+* Changed ectype values! See the README!
+* Fixed some bugs in obtest utility
+* Fixed second battery status bug in battery.c
+* Added textual descriptions to some functions in /proc/omnibook
+* Fix APM emulation to work when APM support is present but APM power
+  status reporting flagged broken
+* Added docking station support
+* Added fan support
+* Added module parameter: user
+* Added OmniBook xe155, xe4100 and ze4125 support
+* Fan policy moved to /proc/omnibook/fan_policy
+* Reorganized scancode emulation code for XE3 GC
+* Polling of volume buttons on XE3CG style models can be enabled/disabled
+  via /proc/omnibook/key_polling
+* Finished abstraction layer
+* Some minor changes in Rick's model detection code
+* New kernel integration code
+
+2002-12-22 Rick Richardson <rickr@mn.rr.com>
+
+* Added on and off as valid input to /proc/omnibook/lcd, to turn
+  the LCD backlight on and off.
+
+2002-12-15 Rick Richardson <rickr@mn.rr.com>
+
+* Reimplemented model detection so you only have to modify one file
+  to add a new model. features.h is now deprecated.
+* Added the Toshiba Satellite 1115/S103 to the supported models
+* Fixed bug in apmemu.c which caused /proc/apm to report the battery
+  status as critical when the battery was charging.
+
+2002-10-16 Soós Péter <sp@osb.hu>
+
+* Added HP Pavilion N5415 support
+* Corrected HP Pavilion N5441 support
+* Fix values of OB500 type machines in ec.h
+* LCD brightness support added for XE3GC and XE3GF style machines
+* Added HP OmniBook 510 FB support
+* AC adapter status monitoring is working on all machines
+* External display status monitoring is working on all machines
+* CPU temperature monitoring is working on all machines
+* __init functions gone to init.h
+* Added an abstraction layer between the low level, hardware dependent
+  functions and the applications (not yet finished). See omnibook.h for
+  details.
+
+2002-09-20 Soós Péter <sp@osb.hu>
+
+* Using save_flags()/cli() instead spinlocks in ec.c because of laptops do
+  not have more than one CPU (yet ;)). This improves performance and
+  eliminates packet loss in ppp stack
+* The previous version of XE3 GC scancode emulation was buggy: it worked only
+  when ACPI enabled. Current version is working ACPI independent way
+
+2002-09-05 Soós Péter <sp@osb.hu>
+
+* Added secondary battery support (untested, please report!)
+* Added ectype module parameter to specify the type of embedded
+  controller firmware
+* Added some OmniBook XE3 GC support code
+* Added some OmniBook 500 style embedded controller firmware support code
+  (OmniBook 5xx, 6xxx and some Pavilions)
+* Reorganized features matrix (again): the features depends on the embedded
+  controller firmware, not the model
+* Added external display status monitoring on some machine
+* Added scancode emulation on OmniBook XE3 GC
+
+2002-08-14 Soós Péter <sp@osb.hu>
+
+* Added HP OmniBook 6000 EA support (OneTouch only)
+* Added HP OmniBook 6100 EB support (OneTouch only)
+* Fixed Toshiba Satellite 3000-100 detection
+* Fixed timeout and locking bugs in ec.c
+* Added HP Pavilion Notebook ZT1141
+* Reorganized the feature matrix and parameter detection code to make easy
+  to add new features differents machine by machine
+
+2002-08-11 Soós Péter <sp@osb.hu>
+
+* Fixed removing of procfs entries
+* Fixed APM detection
+* Added kernel source integration
+* Fixed __initdata bugs
+* Handling difference between untesed and unsupported features
+
+2002-08-09 Soós Péter <sp@osb.hu>
+
+* Added Compal ACL00 laptop support
+* Updated documentation
+* Added touchpad support
+* Some bugfixes
+* /proc/apm emulation added
+
+2002-08-06 Soós Péter <sp@osb.hu>
+
+* Corrected full charged battery info
+* Added OneTouch handling via procfs
+* Added console blank handling via procfs
+* Added temperature policy handling via procfs
+* Corrected the bug in DMI code to report the serial number
+* Added module parameter support
+* Added HP Pavilion Notebook N5490, ZT1195 (and probably other Pavilions)
+
+2002-07-17 Soós Péter <sp@osb.hu>
+
+* Improved error handling
+* Some text corrections
+* Added Toshiba Satellite 3000-100 support
+* Some code tuning
+* Added omnibook prefix for variables and functions to prevent conflicts
+  with another code
+* Added /proc filesystem support
+* Added battery status monitoring
+* Added CPU temperature monitoring
+
+2002-06-03 Soós Péter <sp@osb.hu>
+
+* Some code tuning
+
+2002-05-07 Soós Péter <sp@osb.hu>
+
+* Added missing #include <linux/sched.h> to main.c
+* Some text corrections
+* Added HP OmniBook 500 FA support (OneTouch only)
+
+2002-05-06 Soós Péter <sp@osb.hu>
+
+* LCD display turn off at console blanking added
+* Code cleanup
+
+2002-05-02 Soós Péter <sp@osb.hu>
+
+* The first release of omnibook module
+* OneTouch button support
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/doc/BUGS
+++ linux-ec2-2.6.32/ubuntu/omnibook/doc/BUGS
@@ -0,0 +1,17 @@
+Bugs and problems in omnibook module code
+=========================================
+
+* Volume Control buttons on machine (not on docking station) do not generate
+  scancodes on OB500 style models. It is unhandled yet.
+* Setting the LCD brightness on HP OmniBook XE3 GF via /proc/omnibook/lcd
+  is working if you press one of the brightness control keys once after
+  writing the value into /proc/omnibook/lcd.
+* I'm not a native English speaker so text corrections are welcome.
+* obtest can BADLY confuse the in-kernel ACPI code due to its racy 
+  implementation.
+* Reenabling wifi adapter after previous disabling is broken on 
+  Toshiba Satellite M100 (ipw3945)
+* Real support of ectype 14 is still missing 
+* See http://sourceforge.net/tracker/?atid=868542&group_id=174260&func=browse
+  for sf.net bug tracking system.
+
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/doc/CREDITS
+++ linux-ec2-2.6.32/ubuntu/omnibook/doc/CREDITS
@@ -0,0 +1,39 @@
+The module was originally written by
+
+* Soós Péter <sp@osb.hu>
+
+Special thanks to the following persons and/or organisations (without
+particular order):
+
+* Al Stone <ahs3@fc.hp.com> and Linux Systems Operation at HP for lending
+  an HP OmniBook 500 for the project purposes.
+* Pavel Mihaylov <bin@bash.info> for his omke project discovering a lot of
+  OmniBook features, providing some code for XE3 GC machines and testing.
+* Ducrot Bruno <ducrot@poupinou.org> sharing lots of information about
+  embedded controller and related code, added lots of Toshiba support,
+  writing tosh3k code, sending patches etc.
+
+Thanks to the following people (without particular order):
+
+* Al Stone <ahs3@fc.hp.com> for sharing some programming information.
+* Guido Guenther <agx@sigxcpu.org> for initial OneTouch enabling code.
+* Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> for initial
+  OneTouch power management code.
+* Maciek Gorniak <mago@acn.waw.pl> for initial HP Pavilion N5415 detecting
+  code and initial lcd brighness code.
+* Rick Richardson <rickr@mn.rr.com> for some bugfixes and useful patches.
+* Bob McElrath <mcelrath@draal.physics.wisc.edu> for initial Compal ACL00
+  code.
+* Luisimi Moya <luismimoya@eresmas.net> for Acer Aspire 1400 support.
+* Bernhard Kaindl <bernhard.kaindl@gmx.de> for bugfixes and patches
+* Gabriele Vivinetto <gabriele.mailing@rvmgroup.it> for documentation
+  enhancements and testing.
+* Mark Chappell <nslm@nslm.fsnet.co.uk> for building on kernel 2.6.
+* Massimo Dal Zotto <dz@debian.org> for his i8k code.
+* Jonathan A. Buzzard <jonathan@buzzard.org.uk> for his toshiba code.
+* Some others on OmniBook mailing list at
+  http://zurich.ai.mit.edu/mailman/listinfo/omnibook
+  for providing information and testing.
+
+Last but not least thanks to Linus Torvald and more for creating and
+maintaining the Linux kernel.
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/doc/README
+++ linux-ec2-2.6.32/ubuntu/omnibook/doc/README
@@ -0,0 +1,42 @@
+===============================================================
+Kernel Support for HP OmniBooks, Pavilions and Compal laptops
+===============================================================
+
+This package is intended to provide Linux kernel support for many laptops such as:
+- HP OmniBook and Pavilion
+- Toshiba Satellite and Tecra which are not supported by the toshiba_acpi module
+- Compal ACL00
+- Many laptops manufactured by Compal Electronics, Inc as ODM
+
+Supported features depends on the exact laptop model but may include:
+- Enabling hotkey buttons
+- Console (LCD display) blanking
+- Battery status monitoring.
+- Fan and fan policy support
+- Touchpad control
+- AC Adapter status monitoring
+- External display monitors status monitoring and control
+- LCD brightness (backlight) monitoring and control
+- Docking station/port replicator status
+- CPU temperature monitoring
+- Mute LED monitoring and control
+- Wifi and Bluetooth adapters monitoring and control
+- Cooling method control
+- CPU Throttling control
+
+Useful links:
+
+Full documentation (HOWTO, Installation instructions, Supported laptops list... ):
+http://omnibook.sourceforge.net/doku.php?id=start
+
+Sourceforge project page:
+http://sourceforge.net/projects/omnibook
+
+Other links not related to the project:
+
+For HP Omnibook specific issues ou can see the OmniBook mailing list:
+http://zurich.ai.mit.edu/mailman/listinfo/omnibook
+
+or the Toshiba linux mailing list:
+http://linux.toshiba-dme.co.jp/linux/
+
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/README.mmkeys
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/README.mmkeys
@@ -0,0 +1,9 @@
+This patch maps some extra Fn+key combinations to keycodes for multimedia
+keyboards and only works for the nbsmi-backend. It might be useful if you
+want to control some mediaplayer while working with other applications.
+
+Following combinations are mapped:
+Fn+Y => Previous song
+Fn+X => Play/pause
+Fn+V => Stop CD
+Fn+B => Next song
\ No newline at end of file
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/dmi_strings.txt
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/dmi_strings.txt
@@ -0,0 +1,857 @@
+HP OmniBook XT1000 -------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IB.M1.05
+BIOS Release:  02/28/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XT1000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: HP OmniBook XT1000
+
+---------------------------------------------
+HP OmniBook XT1500 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IC.M1.05
+BIOS Release:  08/13/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: HP OmniBook
+
+---------------------------------------------
+HP OmniBook XT1500 -------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  ID.M1.04
+BIOS Release:  08/14/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GF
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook Zinfandel 4.5
+
+---------------------------------------------
+HP OmniBook XE3 GC --------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GC.M1.63
+BIOS Release:  01/01/1992
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GC
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-733
+
+---------------------------------------------
+HP OmniBook XE3 GF --------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GF.M1.07
+BIOS Release:  03/05/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GF
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-101
+
+---------------------------------------------
+HP OmniBook 500 FA --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  FA.M2.62
+BIOS Release:  11/30/1999
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 500 FA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 500 FA
+
+---------------------------------------------
+HP OmniBook 510 FB --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  FB.M1.20
+BIOS Release:  04/12/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 510 FB
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 510FB
+
+---------------------------------------------
+Toshiba Satellite 3000-100 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.20
+BIOS Release:  10/12/01
+System Vendor: TOSHIBA
+Product Name:  S3000-100
+Version:       PS300E-03EKL-FR
+Board Vendor:  Null
+Board Name:    888M1
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1115-s103------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/11/2002
+System Vendor: TOSHIBA
+Product Name:  Satellite 1115
+Version:       PS111U-001FUV
+Board Vendor:  TOSHIBA
+Board Name:    BTK20
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1110 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/11/2002
+System Vendor: TOSHIBA
+Product Name:  S1110
+Version:       PS111E-003DN-GR
+Board Vendor:  TOSHIBA
+Board Name:    BTK20
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1130 ----------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V1.70A
+BIOS Release: 09/02/2003
+System Vendor: TOSHIBA
+Product Name: Satellite 1130
+Version: PS113E-05ZYF-GR
+Board Vendor: TOSHIBA
+Board Name: BTW30
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite 1900-704 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.50
+BIOS Release:  11/25/2002
+System Vendor: TOSHIBA
+Product Name:  Satellite 1950
+Version:       PS195E-008QY-DU
+Board Vendor:  TOSHIBA
+Board Name:    ATR60
+
+---------------------------------------------
+Toshiba Satellite 1955-s805 -----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.00
+BIOS Release:  01/17/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite 1955
+Version:       PS197U-000LEV
+Board Vendor:  TOSHIBA
+Board Name:    BTR80
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite A70 -----------------------
+
+BIOS Vendor: TOSHIBA 
+BIOS Version: V1.50 
+BIOS Release: 11/16/2004 
+System Vendor: TOSHIBA 
+Product Name: Satellite A70 
+Version: PSA70C-KL100E 
+Serial Number: X4451615K 
+Board Vendor: TOSHIBA 
+Board Name: EDW10 
+Board Version: Null 
+
+---------------------------------------------
+Toshiba Satellite A80 -----------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.50
+BIOS Release: 01/11/2006
+System Vendor: TOSHIBA
+Product Name: Satellite A80
+Version: PSA80E-03T00JSP
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Satellite A105 ----------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  1.30
+BIOS Release:  02/09/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite A105
+Version:       PSAA8U-02000U
+Board Vendor:  Intel Corporation
+Board Name:    Not Applicable
+
+---------------------------------------------
+Toshiba Satellite P10 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/12/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite P10
+Version:       PSP10E-34FJR
+Board Vendor:  TOSHIBA
+Board Name:    DAL00
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite P15 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.20
+BIOS Release:  09/12/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite P15
+Version:       PSP10U-0DUJPV
+Board Vendor:  TOSHIBA
+Board Name:    DAL00
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite P25 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.10
+BIOS Release:  12/27/2004
+System Vendor: TOSHIBA
+Product Name:  Satellite P25
+Version:       PSP20U-19PS8R
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite P100 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V3.30  
+BIOS Release:  12/22/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite P100
+Version:       PSPA3E-02E013G3                   
+Board Vendor:  TOSHIBA
+Board Name:    Not Applicable                 
+
+---------------------------------------------
+Toshiba Satellite M40 -----------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  1.10
+BIOS Release:  08/24/05
+System Vendor: TOSHIBA
+Product Name:  Satellite M40
+Version:       PSM44E-00U00EFR
+Board Vendor:  ATI
+Board Name:    SB400
+Board Version: Rev0.4b
+
+---------------------------------------------
+Toshiba Satellite M45 (S355) ----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  Version 2.00
+BIOS Release:  02/07/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M45
+Version:       PSM40U-073001
+Board Vendor:  TOSHIBA
+Board Name:    Version A0
+
+---------------------------------------------
+Toshiba Satellite M40X (-131)----------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.60
+BIOS Release:  06/09/2005
+System Vendor: TOSHIBA
+Product Name:  Satellite M40X
+Version:       PSM4XE-01400GFR
+Board Vendor:  TOSHIBA
+Board Name:    EAL30
+Board Version: Null
+
+---------------------------------------------
+Toshiba Satellite M50------------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.10
+BIOS Release: 05/08/2006
+System Vendor: TOSHIBA
+Product Name: Satellite M50
+Version: PSM51E-01C011IT
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Satellite M60 -----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.60
+BIOS Release:  03/16/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M60
+Version:       PSM60E-0CD01FIT
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite M70 -----------------------
+
+BIOS Vendor:	TOSHIBA
+BIOS Version:	V1.10
+BIOS Release:	09/15/2005
+System Vendor:	TOSHIBA
+Product Name:	Satellite M70
+Version:	PSM71E-01100KFR
+Board Vendor:	TOSHIBA
+Board Name:	HTW00
+Board Version:	Null
+
+---------------------------------------------
+Toshiba Satellite A75 -----------------------
+
+IOS Vendor:    TOSHIBA
+BIOS Version:  V1.50
+BIOS Release:  11/16/2004
+System Vendor: TOSHIBA
+Product Name:  Satellite A75
+Version:       PSA70U-004004B
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Satellite M100 ----------------------
+
+BIOS Vendor:    TOSHIBA
+BIOS Version:   V1.90
+BIOS Release:   07/20/2006
+System Vendor:  TOSHIBA
+Product Name:   SATELLITE M100
+Version:        PSMA0E-030019TE
+Board Vendor:   TOSHIBA
+Board Name:     HAQAA
+Board Version:  Null
+
+---------------------------------------------
+Toshiba Satellite M100 ----------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.00
+BIOS Release:  03/30/2006
+System Vendor: TOSHIBA
+Product Name:  Satellite M100
+Version:       PSMA2U-00T00G
+Board Vendor:  TOSHIBA
+Board Name:    HAWAA
+Board Version: None
+
+---------------------------------------------
+Toshiba Satellite M115 ----------------------
+
+Bios vender: Phoenix Tech. LTD
+Bios version: 1.00
+Bios release: 08/31/2006
+System Vendor: Toshiba
+Product Name: Satellite M115
+Version: PSMBOU-015007
+Board vendor Intel
+Board name: N/a
+
+---------------------------------------------
+Toshiba Equium A110 -------------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.30
+BIOS Release:  07/20/2006
+System Vendor: TOSHIBA
+Product Name:  EQUIUM A110
+Version:       PSAB2E-002006AV
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Toshiba Tecra A4 ----------------------------
+
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  Version 1.70
+BIOS Release:  10/14/2005
+System Vendor: TOSHIBA
+Product Name:  Tecra A4
+Version:       PTA40E-0UN00FSP
+Board Vendor:  TOSHIBA
+Board Name:    Version A0
+
+---------------------------------------------
+Toshiba Tecra A6 ----------------------------
+
+BIOS Vendor: TOSHIBA
+BIOS Version: V2.70
+BIOS Release: 04/26/2007
+System Vendor: TOSHIBA
+Product Name: TECRA A6
+Version: PTA60U-0FK00D
+Board Vendor: TOSHIBA
+Board Name: Null
+
+---------------------------------------------
+Toshiba Tecra S2 ----------------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V2.50
+BIOS Release:  01/11/2006
+System Vendor: TOSHIBA
+Product Name:  Tecra S2
+Version:       PTS20E-1FE04Q8M
+Board Vendor:  TOSHIBA
+Board Name:    Null
+
+---------------------------------------------
+Compal ACL00 --------------------------------
+
+BIOS Vendor:   COMPAL
+BIOS Version:  V2.10C
+BIOS Release:  03/25/02
+System Vendor: COMPAL
+Product Name:  *
+Version:       *
+Board Vendor:  Null
+Board Name:    ACL00
+Board Version: Null
+
+---------------------------------------------
+Compal ACL10 --------------------------------
+
+BIOS Vendor:   COMPAL
+BIOS Version:  V1.10
+BIOS Release:  04/12/2001
+System Vendor: *
+Product Name:  *
+Version:       *
+Board Vendor:  COMPAL
+Board Name:    ACL10
+Board Version: Null
+
+---------------------------------------------
+HP Pavilion ZT1195 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IC.M1.00
+BIOS Release:  03/20/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: HP Pavilion Notebook
+
+---------------------------------------------
+HP Pavilion ZT1141 --------------------------
+
+BIOS Vendor:   Insyde Software
+BIOS Version:  IB.M1.05
+BIOS Release:  02/28/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook ZT1000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: HP Pavilion Notebook ZT1000
+
+---------------------------------------------
+HP OmniBook 6100 EB -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EB.M2.20
+BIOS Release:  02/27/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6100 EB
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6100EB
+
+---------------------------------------------
+HP OmniBook 6000 EA -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EA.M1.81
+BIOS Release:  02/22/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6000 EA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6000EA
+
+---------------------------------------------
+HP OmniBook xe4500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KB.M1.30
+BIOS Release:  08/05/20022
+System Vendor: Hewlett-Packard.
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook xe4500
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: xe4500
+
+---------------------------------------------
+HP Pavilion N5441 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GD.M1.08
+BIOS Release:  09/27/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook Model GD
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5430 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GD.M1.08
+BIOS Release:  09/27/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GD
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5415 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GE.M1.04
+BIOS Release:  07/30/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook XE3 GE
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+HP Pavilion N5290 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GC.M1.63
+BIOS Release:  01/01/1992
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook XE3 GC
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-733
+
+---------------------------------------------
+HP OmniBook vt6200 -------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  EG.M2.10
+BIOS Release:  09/19/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6200 EG
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6200EG
+
+---------------------------------------------
+HP OmniBook 4150 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  CI.M2.250
+BIOS Release:  06/10/99
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 4150
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook TS32T2
+
+---------------------------------------------
+HP OmniBook xt6200 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  EG.M2.10
+BIOS Release:  09/19/02
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 6200 EG
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 6200EG
+
+---------------------------------------------
+HP Pavilion ze4125 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd
+BIOS Version:  KA.M1.20
+BIOS Release:  09/13/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC
+Version:       HP NoteBook ze4000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC
+Board Version: HP NoteBook ze4000
+
+---------------------------------------------
+HP OmniBook xt155 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.40
+BIOS Release:  10/11/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC
+Version:       HP Notebook PC
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC
+Board Version: HP Notebook PC
+
+---------------------------------------------
+HP OmniBook xe4100 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KC.M1.10
+BIOS Release:  07/11/2002
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook xe4000
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: 4000KC
+
+---------------------------------------------
+HP Omnibook xe4400 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KD.M1.60
+BIOS Release:  09/19/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP Omnibook xe4400
+Board Vendor:  Hewlett-Packard
+Board Name:    HP OmniBook PC
+Board Version: xe4400
+
+---------------------------------------------
+HP Pavilion ze4100 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.40
+BIOS Release:  10/11/20022
+System Vendor: Hewlett-Packard
+Product Name:  HP NoteBook PC         
+Version:       HP Notebook PC
+Board Vendor:  Hewlett-Packard
+Board Name:    HP NoteBook PC         
+Board Version: HP Notebook PC
+
+---------------------------------------------
+Acer Aspire 1350 ----------------------------
+BIOS Vendor:   Acer   
+BIOS Version:  3A24
+BIOS Release:  12/01/2003
+System Vendor: Acer,Inc.
+Product Name:  Aspire 1350
+Version:       3A24
+Board Vendor:  Acer,Inc.
+Board Name:    Aspire 1350
+Board Version: Rev.A
+
+---------------------------------------------
+Acer Aspire 1406 LC -------------------------
+
+BIOS Vendor:   Acer
+BIOS Version:  V2.30
+BIOS Release:  10/04/02
+System Vendor: Acer
+Product Name:  Aspire 1400 series
+Version:       *
+Board Vendor:  Null
+Board Name:    BR20
+Board Version: Null
+
+---------------------------------------------
+HP Pavilion ze4200 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE.M1.53
+BIOS Release:  12/10/20022
+System Vendor: Hewlett-Packard
+Product Name:  Pavilion ze4200
+Version:       KE.M1.53
+Board Vendor:  Hewlett-Packard
+Board Name:    002A
+Board Version: NS570 Version PQ1A74
+
+---------------------------------------------
+HP Pavilion ze4500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KAM1.57  
+BIOS Release:  02/19/2004
+System Vendor: Hewlett-Packard          
+Product Name:  Pavilion ze4500 (DP793E) 
+Version:       KAM1.57  
+Board Vendor:  Hewlett-Packard          
+Board Name:    PQ1A83
+
+---------------------------------------------
+HP Pavilion ZU1175 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  FA.M2.60
+BIOS Release:  11/30/1999
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion ZU1000 FA
+Board Vendor:  Hewlett-Packard
+Board Name:    HP Pavilion Notebook PC
+Board Version: 1000FA
+
+---------------------------------------------
+HP Pavilion XH545 ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  GE.M1.03
+BIOS Release:  11/08/2001
+System Vendor: Hewlett-Packard
+Product Name:  HP Pavilion Notebook PC
+Version:       HP Pavilion Notebook Model GE
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook N32N-736
+
+---------------------------------------------
+Toshiba Satellite 2430-402 ------------------
+
+BIOS Vendor:   TOSHIBA
+BIOS Version:  V1.30
+BIOS Release:  01/16/2003
+System Vendor: TOSHIBA
+Product Name:  Satellite 2430
+Version:       PS243E-06P4S-4V
+Board Vendor:  TOSHIBA
+Board Name:    BTS88
+Board Version: Null
+
+---------------------------------------------
+HP OmniBook 900 B ---------------------------
+
+BIOS Vendor:   Phoenix Technologies LTD
+BIOS Version:  CL.M3.13
+BIOS Release:  11/11/99
+System Vendor: Hewlett-Packard
+Product Name:  HP OmniBook PC
+Version:       HP OmniBook 900 B
+Board Vendor:  Hewlett-Packard
+Board Name:    N/A
+Board Version: OmniBook TS32U2
+
+---------------------------------------------
+HP Compaq nx9000 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE_KG.M1.06
+BIOS Release:  05/16/2003
+System Vendor: Hewlett-Packard        
+Product Name:  HP nx9000 (DG223T)       
+Version:       KG.M1.06
+Board Vendor:  Hewlett-Packard        
+Board Name:    002A                   
+Board Version: NS570 Version PQ1A78   
+
+---------------------------------------------
+HP Compaq nx9000 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KE_KG.M1.15
+BIOS Release:  12/19/2003
+System Vendor: Hewlett-Packard
+Product Name:  HP Notebook PC
+Version:       HP Notebook PC
+Board Vendor:  <NULL>
+Board Name:    <NULL>
+Board Version: <NULL>
+
+---------------------------------------------
+HP Compaq nx9005 ----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KAM1.46
+BIOS Release:  07/21/200392
+System Vendor: Hewlett-Packard
+Product Name:  HP nx9005 (DJ163A)
+Version:       KAM1.46
+Board Vendor:  Hewlett-Packard
+Board Name:    0024
+Board Version: PQ1A78
+
+----------------------------------------------
+HP Compaq nx9010 -----------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KF_KH.F.08
+BIOS Release:  06/06/2003
+System Vendor: Hewlett-Packard
+Product Name:  HP nx9010 (DJ123A)
+Version:       KH.F.08
+Board Vendor:  Hewlett-Packard
+Board Name:    0850
+Board Version: NS570 Version PQ1B56
+
+----------------------------------------------
+HP Pavilion ze8500 --------------------------
+
+BIOS Vendor:   Phoenix Technologies Ltd.
+BIOS Version:  KF_KH.F.18
+BIOS Release:  11/13/2003
+System Vendor: Hewlett-Packard
+Product Name:  Pavilion ze8500 (DJ317A)
+Version:       KH.F.18
+Board Vendor:  Hewlett-Packard
+Board Name:    0850
+Board Version: NS570 Version PQ1B60
+
+---------------------------------------------
+Fujitsu-Siemens Amilo D ---------------------
+
+BIOS Vendor:   Phoenix
+BIOS Version:  V1.20
+BIOS Release:  11/14/2001
+System Vendor: FUJITSU SIEMENS
+Product Name:  Amilo D-Series
+Version:       DESKTOP CPU ONLY
+Board Vendor:  CY23
+Board Name:    8606-686B
+Board Version: None
+
+---------------------------------------------
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/ob5xx.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/ob5xx.def
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP OmniBook 5xx">
+
+	<!--
+		Multimedia keys are disabled by default on HP OmniBook
+		laptops. For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<Shell		keycode="244"/>
+		<Help		keycode="243"/>
+
+		<!-- Keys below available on the docking station only -->
+
+		<PrevTrack	keycode="144"/>
+		<Play		keycode="162"/>
+		<Stop		keycode="164"/>
+		<NextTrack	keycode="153"/>
+
+		<VolUp		keycode="176" adj="1"/>
+		<VolDown	keycode="174" adj="1"/>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/xe3gf.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/xe3gf.def
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP OmniBook XE3 GF">
+
+	<!--
+		Multimedia keys are disabled by default on HP OmniBook
+		laptops. For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<PrevTrack	keycode="144"/>
+		<Play		keycode="162"/>
+		<Stop		keycode="164"/>
+		<NextTrack	keycode="153"/>
+
+		<VolUp		keycode="176" adj="1"/>
+		<VolDown	keycode="174" adj="1"/>
+
+		<Email		keycode="236"/>
+		<WebBrowser	keycode="178"/>
+		<Shell		keycode="244"/>
+		<Help		keycode="243"/>
+
+		<userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/xt155.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/xt155.def
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP OmniBook xt155">
+
+	<!--
+		Multimedia keys are disabled by default on HP OmniBook
+		laptops. For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<Email		keycode="236"/>
+		<WebBrowser	keycode="178"/>
+		<Shell		keycode="243"/>
+		<ScreenSaver	keycode="241"/>
+		<Help		keycode="240"/>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/nx9xxx.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/nx9xxx.def
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP/Compaq nx9xxx laptops">
+
+	<!--
+		Multimedia keys are disabled by default on HP laptops.
+		For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<Email		keycode="236"/>
+		<WebBrowser	keycode="178"/>
+		<Shell		keycode="243"/>
+		<ScreenSaver	keycode="241"/>
+		<Help		keycode="240"/>
+
+		<VolUp		keycode="176" adj="1"/>
+		<VolDown	keycode="174" adj="1"/>
+
+		<userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/xe4xxx.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/xe4xxx.def
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP OmniBook xe4xxx and ze4xxx">
+
+	<!--
+		Multimedia keys are disabled by default on HP OmniBook
+		laptops. For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<Email		keycode="236"/>
+		<WebBrowser	keycode="178"/>
+		<Shell		keycode="243"/>
+		<ScreenSaver	keycode="241"/>
+		<Help		keycode="240"/>
+
+		<VolUp		keycode="176" adj="1"/>
+		<VolDown	keycode="174" adj="1"/>
+
+		<userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/README.hotkeys
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/README.hotkeys
@@ -0,0 +1,22 @@
+HotKeys is a program to use the special keys on internet/multimedia
+keyboards.
+
+The HotKeys daemon listens for the "special" hotkeys that you won't
+normally use on your Internet/Multimedia keyboards. The buttons
+perform their intended behaviors, such as volume up and down, mute the
+speaker, or launch applications.  It has On-screen display (OSD) to
+show the volume, program that's being started, etc.  It features an
+XML-based keycode configuration file format, which makes it possible
+to define the hotkeys to launch any programs you want.
+
+You may reach it at http://ypwong.org/hotkeys/
+
+Files in this directory provide examles for hotkeys definition files
+for certain laptop models supported by omnibook module:
+
+ob5xx.def:	HP OmniBook 5xx
+xe3gc.def:	HP OmniBook XE3 GC, GD, GE and HP Pavilion N5xxx
+xe3gf.def:	HP OmniBook XE3 GF
+xe4xxx.def:	HP OmniBook xe4xxx and ze4xxx
+xt155.def:	HP OmniBook xt155
+nx9xxx.def:	HP/Compaq nx9xxx
--- linux-ec2-2.6.32.orig/ubuntu/omnibook/misc/hotkeys/xe3gc.def
+++ linux-ec2-2.6.32/ubuntu/omnibook/misc/hotkeys/xe3gc.def
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<definition>
+	<config model="HP OmniBook XE3 GC, GD, GE and HP Pavilion N5xxx">
+
+	<!--
+		Multimedia keys are disabled by default on HP OmniBook
+		laptops. For enabling them see the project at URL
+		http://sourceforge.net/projects/omke
+	-->
+
+		<PrevTrack	keycode="144"/>
+		<Play		keycode="162"/>
+		<Stop		keycode="164"/>
+		<NextTrack	keycode="153"/>
+
+		<VolUp		keycode="176" adj="1"/>
+		<VolDown	keycode="174" adj="1"/>
+
+		<WebBrowser	keycode="243"/>
+		<Email		keycode="244"/>
+		<Shell		keycode="242"/>
+		<Help		keycode="241"/>
+
+		<userdef keycode="160" command="aumix -vM">Sound muted</userdef>
+
+	</config>
+
+	<contributor>
+		<name>Soos, Peter</name>
+		<email>sp@osb.hu</email>
+	</contributor>
+</definition>
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-raid4-5.c
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-raid4-5.c
@@ -0,0 +1,4547 @@
+/*[A[A
+ * Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen <heinzm@redhat.com>
+ *
+ * This file is released under the GPL.
+ *
+ *
+ * Linux 2.6 Device Mapper RAID4 and RAID5 target.
+ *
+ * Supports:
+ *	o RAID4 with dedicated and selectable parity device
+ *	o RAID5 with rotating parity (left+right, symmetric+asymmetric)
+ *	o recovery of out of sync device for initial
+ *	  RAID set creation or after dead drive replacement
+ *	o run time optimization of xor algorithm used to calculate parity
+ *
+ *
+ * Thanks to MD for:
+ *    o the raid address calculation algorithm
+ *    o the base of the biovec <-> page list copier.
+ *
+ *
+ * Uses region hash to keep track of how many writes are in flight to
+ * regions in order to use dirty log to keep state of regions to recover:
+ *
+ *    o clean regions (those which are synchronized
+ * 	and don't have write io in flight)
+ *    o dirty regions (those with write io in flight)
+ *
+ *
+ * On startup, any dirty regions are migrated to the
+ * 'nosync' state and are subject to recovery by the daemon.
+ *
+ * See raid_ctr() for table definition.
+ *
+ * FIXME: recovery bandwidth
+ */ 
+
+static const char *version = "v0.2594b";
+
+#include "dm.h"
+#include "dm-memcache.h"
+#include "dm-message.h"
+#include "dm-raid45.h"
+
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/raid/xor.h>
+
+#include <linux/bio.h>
+#include <linux/dm-io.h>
+#include <linux/dm-dirty-log.h>
+#include "dm-region-hash.h"
+
+
+/*
+ * Configurable parameters
+ */
+
+/* Minimum/maximum and default # of selectable stripes. */
+#define	STRIPES_MIN		8
+#define	STRIPES_MAX		16384
+#define	STRIPES_DEFAULT		80
+
+/* Maximum and default chunk size in sectors if not set in constructor. */
+#define	CHUNK_SIZE_MIN		8
+#define	CHUNK_SIZE_MAX		16384
+#define	CHUNK_SIZE_DEFAULT	64
+
+/* Default io size in sectors if not set in constructor. */
+#define	IO_SIZE_MIN		CHUNK_SIZE_MIN
+#define	IO_SIZE_DEFAULT		IO_SIZE_MIN
+
+/* Recover io size default in sectors. */
+#define	RECOVER_IO_SIZE_MIN		64
+#define	RECOVER_IO_SIZE_DEFAULT		256
+
+/* Default, minimum and maximum percentage of recover io bandwidth. */
+#define	BANDWIDTH_DEFAULT	10
+#define	BANDWIDTH_MIN		1
+#define	BANDWIDTH_MAX		100
+
+/* # of parallel recovered regions */
+#define RECOVERY_STRIPES_MIN	1
+#define RECOVERY_STRIPES_MAX	64
+#define RECOVERY_STRIPES_DEFAULT	RECOVERY_STRIPES_MIN
+/*
+ * END Configurable parameters
+ */
+
+#define	TARGET	"dm-raid45"
+#define	DAEMON	"kraid45d"
+#define	DM_MSG_PREFIX	TARGET
+
+#define	SECTORS_PER_PAGE	(PAGE_SIZE >> SECTOR_SHIFT)
+
+/* Amount/size for __xor(). */
+#define	XOR_SIZE	PAGE_SIZE
+
+/* Check value in range. */
+#define	range_ok(i, min, max)	(i >= min && i <= max)
+
+/* Check argument is power of 2. */
+#define POWER_OF_2(a) (!(a & (a - 1)))
+
+/* Structure access macros. */
+/* Derive raid_set from stripe_cache pointer. */
+#define	RS(x)	container_of(x, struct raid_set, sc)
+
+/* Page reference. */
+#define PAGE(stripe, p)  ((stripe)->obj[p].pl->page)
+
+/* Stripe chunk reference. */
+#define CHUNK(stripe, p) ((stripe)->chunk + p)
+
+/* Bio list reference. */
+#define	BL(stripe, p, rw)	(stripe->chunk[p].bl + rw)
+#define	BL_CHUNK(chunk, rw)	(chunk->bl + rw)
+
+/* Page list reference. */
+#define	PL(stripe, p)		(stripe->obj[p].pl)
+/* END: structure access macros. */
+
+/* Factor out to dm-bio-list.h */
+static inline void bio_list_push(struct bio_list *bl, struct bio *bio)
+{
+	bio->bi_next = bl->head;
+	bl->head = bio;
+
+	if (!bl->tail)
+		bl->tail = bio;
+}
+
+/* Factor out to dm.h */
+#define TI_ERR_RET(str, ret) \
+	do { ti->error = str; return ret; } while (0);
+#define TI_ERR(str)     TI_ERR_RET(str, -EINVAL)
+
+/* Macro to define access IO flags access inline functions. */
+#define	BITOPS(name, what, var, flag) \
+static inline int TestClear ## name ## what(struct var *v) \
+{ return test_and_clear_bit(flag, &v->io.flags); } \
+static inline int TestSet ## name ## what(struct var *v) \
+{ return test_and_set_bit(flag, &v->io.flags); } \
+static inline void Clear ## name ## what(struct var *v) \
+{ clear_bit(flag, &v->io.flags); } \
+static inline void Set ## name ## what(struct var *v) \
+{ set_bit(flag, &v->io.flags); } \
+static inline int name ## what(struct var *v) \
+{ return test_bit(flag, &v->io.flags); }
+
+/*-----------------------------------------------------------------
+ * Stripe cache
+ *
+ * Cache for all reads and writes to raid sets (operational or degraded)
+ *
+ * We need to run all data to and from a RAID set through this cache,
+ * because parity chunks need to get calculated from data chunks
+ * or, in the degraded/resynchronization case, missing chunks need
+ * to be reconstructed using the other chunks of the stripe.
+ *---------------------------------------------------------------*/
+/* A chunk within a stripe (holds bios hanging off). */
+/* IO status flags for chunks of a stripe. */
+enum chunk_flags {
+	CHUNK_DIRTY,		/* Pages of chunk dirty; need writing. */
+	CHUNK_ERROR,		/* IO error on any chunk page. */
+	CHUNK_IO,		/* Allow/prohibit IO on chunk pages. */
+	CHUNK_LOCKED,		/* Chunk pages locked during IO. */
+	CHUNK_MUST_IO,		/* Chunk must io. */
+	CHUNK_UNLOCK,		/* Enforce chunk unlock. */
+	CHUNK_UPTODATE,		/* Chunk pages are uptodate. */
+};
+
+#if READ != 0 || WRITE != 1
+#error dm-raid45: READ/WRITE != 0/1 used as index!!!
+#endif
+
+enum bl_type {
+	WRITE_QUEUED = WRITE + 1,
+	WRITE_MERGED,
+	NR_BL_TYPES,	/* Must be last one! */
+};
+struct stripe_chunk {
+	atomic_t cnt;		/* Reference count. */
+	struct stripe *stripe;	/* Backpointer to stripe for endio(). */
+	/* Bio lists for reads, writes, and writes merged. */
+	struct bio_list bl[NR_BL_TYPES];
+	struct {
+		unsigned long flags; /* IO status flags. */
+	} io;
+};
+
+/* Define chunk bit operations. */
+BITOPS(Chunk, Dirty,	 stripe_chunk, CHUNK_DIRTY)
+BITOPS(Chunk, Error,	 stripe_chunk, CHUNK_ERROR)
+BITOPS(Chunk, Io,	 stripe_chunk, CHUNK_IO)
+BITOPS(Chunk, Locked,	 stripe_chunk, CHUNK_LOCKED)
+BITOPS(Chunk, MustIo,	 stripe_chunk, CHUNK_MUST_IO)
+BITOPS(Chunk, Unlock,	 stripe_chunk, CHUNK_UNLOCK)
+BITOPS(Chunk, Uptodate,	 stripe_chunk, CHUNK_UPTODATE)
+
+/*
+ * Stripe linked list indexes. Keep order, because the stripe
+ * and the stripe cache rely on the first 3!
+ */
+enum list_types {
+	LIST_FLUSH,	/* Stripes to flush for io. */
+	LIST_ENDIO,	/* Stripes to endio. */
+	LIST_LRU,	/* Least recently used stripes. */
+	SC_NR_LISTS,	/* # of lists in stripe cache. */
+	LIST_HASH = SC_NR_LISTS,	/* Hashed stripes. */
+	LIST_RECOVER = LIST_HASH, /* For recovery type stripes only. */
+	STRIPE_NR_LISTS,/* To size array in struct stripe. */
+};
+
+/* Adressing region recovery. */
+struct recover_addr {
+	struct dm_region *reg;	/* Actual region to recover. */
+	sector_t pos;	/* Position within region to recover. */
+	sector_t end;	/* End of region to recover. */
+};
+
+/* A stripe: the io object to handle all reads and writes to a RAID set. */
+struct stripe {
+	atomic_t cnt;			/* Reference count. */
+	struct stripe_cache *sc;	/* Backpointer to stripe cache. */
+
+	/*
+	 * 4 linked lists:
+	 *   o io list to flush io
+	 *   o endio list
+	 *   o LRU list to put stripes w/o reference count on
+	 *   o stripe cache hash
+	 */
+	struct list_head lists[STRIPE_NR_LISTS];
+
+	sector_t key;	 /* Hash key. */
+	region_t region; /* Region stripe is mapped to. */
+
+	struct {
+		unsigned long flags;	/* Stripe state flags (see below). */
+
+		/*
+		 * Pending ios in flight:
+		 *
+		 * used to control move of stripe to endio list
+		 */
+		atomic_t pending;
+
+		/* Sectors to read and write for multi page stripe sets. */
+		unsigned size;
+	} io;
+
+	/* Address region recovery. */
+	struct recover_addr *recover;
+
+	/* Lock on stripe (Future: for clustering). */
+	void *lock;
+
+	struct {
+		unsigned short parity;	/* Parity chunk index. */
+		short recover;		/* Recovery chunk index. */
+	} idx;
+
+	/*
+	 * This stripe's memory cache object (dm-mem-cache);
+	 * i.e. the io chunk pages.
+	 */
+	struct dm_mem_cache_object *obj;
+
+	/* Array of stripe sets (dynamically allocated). */
+	struct stripe_chunk chunk[0];
+};
+
+/* States stripes can be in (flags field). */
+enum stripe_states {
+	STRIPE_ERROR,		/* io error on stripe. */
+	STRIPE_MERGED,		/* Writes got merged to be written. */
+	STRIPE_RBW,		/* Read-before-write stripe. */
+	STRIPE_RECONSTRUCT,	/* Reconstruct of a missing chunk required. */
+	STRIPE_RECONSTRUCTED,	/* Reconstructed of a missing chunk. */
+	STRIPE_RECOVER,		/* Stripe used for RAID set recovery. */
+};
+
+/* Define stripe bit operations. */
+BITOPS(Stripe, Error,	      stripe, STRIPE_ERROR)
+BITOPS(Stripe, Merged,        stripe, STRIPE_MERGED)
+BITOPS(Stripe, RBW,	      stripe, STRIPE_RBW)
+BITOPS(Stripe, Reconstruct,   stripe, STRIPE_RECONSTRUCT)
+BITOPS(Stripe, Reconstructed, stripe, STRIPE_RECONSTRUCTED)
+BITOPS(Stripe, Recover,	      stripe, STRIPE_RECOVER)
+
+/* A stripe hash. */
+struct stripe_hash {
+	struct list_head *hash;
+	unsigned buckets;
+	unsigned mask;
+	unsigned prime;
+	unsigned shift;
+};
+
+enum sc_lock_types {
+	LOCK_ENDIO,	/* Protect endio list. */
+	LOCK_LRU,	/* Protect LRU list. */
+	NR_LOCKS,       /* To size array in struct stripe_cache. */
+};
+
+/* A stripe cache. */
+struct stripe_cache {
+	/* Stripe hash. */
+	struct stripe_hash hash;
+
+	spinlock_t locks[NR_LOCKS];	/* Locks to protect lists. */
+
+	/* Stripes with io to flush, stripes to endio and LRU lists. */
+	struct list_head lists[SC_NR_LISTS];
+
+	/* Slab cache to allocate stripes from. */
+	struct {
+		struct kmem_cache *cache;	/* Cache itself. */
+		char name[32];	/* Unique name. */
+	} kc;
+
+	struct dm_io_client *dm_io_client; /* dm-io client resource context. */
+
+	/* dm-mem-cache client resource context. */
+	struct dm_mem_cache_client *mem_cache_client;
+
+	int stripes_parm;	    /* # stripes parameter from constructor. */
+	atomic_t stripes;	    /* actual # of stripes in cache. */
+	atomic_t stripes_to_set;    /* # of stripes to resize cache to. */
+	atomic_t stripes_last;	    /* last # of stripes in cache. */
+	atomic_t active_stripes;    /* actual # of active stripes in cache. */
+
+	/* REMOVEME: */
+	atomic_t active_stripes_max; /* actual # of active stripes in cache. */
+};
+
+/* Flag specs for raid_dev */ ;
+enum raid_dev_flags {
+	DEV_FAILED,	/* Device failed. */
+	DEV_IO_QUEUED,	/* Io got queued to device. */
+};
+
+/* The raid device in a set. */
+struct raid_dev {
+	struct dm_dev *dev;
+	sector_t start;		/* Offset to map to. */
+	struct {	/* Using struct to be able to BITOPS(). */
+		unsigned long flags;	/* raid_dev_flags. */
+	} io;
+};
+
+BITOPS(Dev, Failed,   raid_dev, DEV_FAILED)
+BITOPS(Dev, IoQueued, raid_dev, DEV_IO_QUEUED)
+
+/* Flags spec for raid_set. */
+enum raid_set_flags {
+	RS_CHECK_OVERWRITE,	/* Check for chunk overwrites. */
+	RS_DEAD,		/* RAID set inoperational. */
+	RS_DEGRADED,		/* Io errors on RAID device. */
+	RS_DEVEL_STATS,		/* REMOVEME: display status information. */
+	RS_RECOVER,		/* Do recovery. */
+	RS_RECOVERY_BANDWIDTH,	/* Allow recovery bandwidth (delayed bios). */
+	RS_SC_BUSY,		/* Stripe cache busy -> send an event. */
+	RS_SUSPEND,		/* Suspend RAID set. */
+};
+
+/* REMOVEME: devel stats counters. */
+enum stats_types {
+	S_BIOS_READ,
+	S_BIOS_ADDED_READ,
+	S_BIOS_ENDIO_READ,
+	S_BIOS_WRITE,
+	S_BIOS_ADDED_WRITE,
+	S_BIOS_ENDIO_WRITE,
+	S_CAN_MERGE,
+	S_CANT_MERGE,
+	S_CONGESTED,
+	S_DM_IO_READ,
+	S_DM_IO_WRITE,
+	S_BANDWIDTH,
+	S_BARRIER,
+	S_BIO_COPY_PL_NEXT,
+	S_DEGRADED,
+	S_DELAYED_BIOS,
+	S_FLUSHS,
+	S_HITS_1ST,
+	S_IOS_POST,
+	S_INSCACHE,
+	S_MAX_LOOKUP,
+	S_CHUNK_LOCKED,
+	S_NO_BANDWIDTH,
+	S_NOT_CONGESTED,
+	S_NO_RW,
+	S_NOSYNC,
+	S_OVERWRITE,
+	S_PROHIBITCHUNKIO,
+	S_RECONSTRUCT_EI,
+	S_RECONSTRUCT_DEV,
+	S_RECONSTRUCT_SET,
+	S_RECONSTRUCTED,
+	S_REQUEUE,
+	S_STRIPE_ERROR,
+	S_SUM_DELAYED_BIOS,
+	S_XORS,
+	S_NR_STATS,	/* # of stats counters. Must be last! */
+};
+
+/* Status type -> string mappings. */
+struct stats_map {
+	const enum stats_types type;
+	const char *str;
+};
+
+static struct stats_map stats_map[] = {
+	{ S_BIOS_READ, "r=" },
+	{ S_BIOS_ADDED_READ, "/" },
+	{ S_BIOS_ENDIO_READ, "/" },
+	{ S_BIOS_WRITE, " w=" },
+	{ S_BIOS_ADDED_WRITE, "/" },
+	{ S_BIOS_ENDIO_WRITE, "/" },
+	{ S_DM_IO_READ, " rc=" },
+	{ S_DM_IO_WRITE, " wc=" },
+	{ S_BANDWIDTH, "\nbw=" },
+	{ S_NO_BANDWIDTH, " no_bw=" },
+	{ S_BARRIER, "\nbarrier=" },
+	{ S_BIO_COPY_PL_NEXT, "\nbio_cp_next=" },
+	{ S_CAN_MERGE, "\nmerge=" },
+	{ S_CANT_MERGE, "/no_merge=" },
+	{ S_CHUNK_LOCKED, "\nchunk_locked=" },
+	{ S_CONGESTED, "\ncgst=" },
+	{ S_NOT_CONGESTED, "/not_cgst=" },
+	{ S_DEGRADED, "\ndegraded=" },
+	{ S_DELAYED_BIOS, "\ndel_bios=" },
+	{ S_SUM_DELAYED_BIOS, "/sum_del_bios=" },
+	{ S_FLUSHS, "\nflushs=" },
+	{ S_HITS_1ST, "\nhits_1st=" },
+	{ S_IOS_POST, " ios_post=" },
+	{ S_INSCACHE, " inscache=" },
+	{ S_MAX_LOOKUP, " maxlookup=" },
+	{ S_NO_RW, "\nno_rw=" },
+	{ S_NOSYNC, " nosync=" },
+	{ S_OVERWRITE, " ovr=" },
+	{ S_PROHIBITCHUNKIO, " prhbt_io=" },
+	{ S_RECONSTRUCT_EI, "\nrec_ei=" },
+	{ S_RECONSTRUCT_DEV, " rec_dev=" },
+	{ S_RECONSTRUCT_SET, " rec_set=" },
+	{ S_RECONSTRUCTED, " rec=" },
+	{ S_REQUEUE, " requeue=" },
+	{ S_STRIPE_ERROR, " stripe_err=" },
+	{ S_XORS, " xors=" },
+};
+
+/*
+ * A RAID set.
+ */
+#define	dm_rh_client	dm_region_hash
+enum count_type { IO_WORK = 0, IO_RECOVER, IO_NR_COUNT };
+typedef void (*xor_function_t)(unsigned count, unsigned long **data);
+struct raid_set {
+	struct dm_target *ti;	/* Target pointer. */
+
+	struct {
+		unsigned long flags;	/* State flags. */
+		struct mutex in_lock;	/* Protects central input list below. */
+		struct bio_list in;	/* Pending ios (central input list). */
+		struct bio_list work;	/* ios work set. */
+		wait_queue_head_t suspendq;	/* suspend synchronization. */
+		atomic_t in_process;	/* counter of queued bios (suspendq). */
+		atomic_t in_process_max;/* counter of queued bios max. */
+
+		/* io work. */
+		struct workqueue_struct *wq;
+		struct delayed_work dws_do_raid;	/* For main worker. */
+		struct work_struct ws_do_table_event;	/* For event worker. */
+	} io;
+
+	/* Stripe locking abstraction. */
+	struct dm_raid45_locking_type *locking;
+
+	struct stripe_cache sc;	/* Stripe cache for this set. */
+
+	/* Xor optimization. */
+	struct {
+		struct xor_func *f;
+		unsigned chunks;
+		unsigned speed;
+	} xor;
+
+	/* Recovery parameters. */
+	struct recover {
+		struct dm_dirty_log *dl;	/* Dirty log. */
+		struct dm_rh_client *rh;	/* Region hash. */
+
+		struct dm_io_client *dm_io_client; /* recovery dm-io client. */
+		/* dm-mem-cache client resource context for recovery stripes. */
+		struct dm_mem_cache_client *mem_cache_client;
+
+		struct list_head stripes;	/* List of recovery stripes. */
+
+		region_t nr_regions;
+		region_t nr_regions_to_recover;
+		region_t nr_regions_recovered;
+		unsigned long start_jiffies;
+		unsigned long end_jiffies;
+
+		unsigned bandwidth;	 /* Recovery bandwidth [%]. */
+		unsigned bandwidth_work; /* Recovery bandwidth [factor]. */
+		unsigned bandwidth_parm; /*  " constructor parm. */
+		unsigned io_size;        /* recovery io size <= region size. */
+		unsigned io_size_parm;   /* recovery io size ctr parameter. */
+		unsigned recovery;	 /* Recovery allowed/prohibited. */
+		unsigned recovery_stripes; /* # of parallel recovery stripes. */
+
+		/* recovery io throttling. */
+		atomic_t io_count[IO_NR_COUNT];	/* counter recover/regular io.*/
+		unsigned long last_jiffies;
+	} recover;
+
+	/* RAID set parameters. */
+	struct {
+		struct raid_type *raid_type;	/* RAID type (eg, RAID4). */
+		unsigned raid_parms;	/* # variable raid parameters. */
+
+		unsigned chunk_size;	/* Sectors per chunk. */
+		unsigned chunk_size_parm;
+		unsigned chunk_shift;	/* rsector chunk size shift. */
+
+		unsigned io_size;	/* Sectors per io. */
+		unsigned io_size_parm;
+		unsigned io_mask;	/* Mask for bio_copy_page_list(). */
+		unsigned io_inv_mask;	/* Mask for raid_address(). */
+
+		sector_t sectors_per_dev;	/* Sectors per device. */
+
+		atomic_t failed_devs;		/* Amount of devices failed. */
+
+		/* Index of device to initialize. */
+		int dev_to_init;
+		int dev_to_init_parm;
+
+		/* Raid devices dynamically allocated. */
+		unsigned raid_devs;	/* # of RAID devices below. */
+		unsigned data_devs;	/* # of RAID data devices. */
+
+		int ei;		/* index of failed RAID device. */
+
+		/* Index of dedicated parity device (i.e. RAID4). */
+		int pi;
+		int pi_parm;	/* constructor parm for status output. */
+	} set;
+
+	/* REMOVEME: devel stats counters. */
+	atomic_t stats[S_NR_STATS];
+
+	/* Dynamically allocated temporary pointers for xor(). */
+	unsigned long **data;
+
+	/* Dynamically allocated RAID devices. Alignment? */
+	struct raid_dev dev[0];
+};
+
+/* Define RAID set bit operations. */
+BITOPS(RS, Bandwidth, raid_set, RS_RECOVERY_BANDWIDTH)
+BITOPS(RS, CheckOverwrite, raid_set, RS_CHECK_OVERWRITE)
+BITOPS(RS, Dead, raid_set, RS_DEAD)
+BITOPS(RS, Degraded, raid_set, RS_DEGRADED)
+BITOPS(RS, DevelStats, raid_set, RS_DEVEL_STATS)
+BITOPS(RS, Recover, raid_set, RS_RECOVER)
+BITOPS(RS, ScBusy, raid_set, RS_SC_BUSY)
+BITOPS(RS, Suspend, raid_set, RS_SUSPEND)
+#undef BITOPS
+
+/*-----------------------------------------------------------------
+ * Raid-4/5 set structures.
+ *---------------------------------------------------------------*/
+/* RAID level definitions. */
+enum raid_level {
+	raid4,
+	raid5,
+};
+
+/* Symmetric/Asymmetric, Left/Right parity rotating algorithms. */
+enum raid_algorithm {
+	none,
+	left_asym,
+	right_asym,
+	left_sym,
+	right_sym,
+};
+
+struct raid_type {
+	const char *name;		/* RAID algorithm. */
+	const char *descr;		/* Descriptor text for logging. */
+	const unsigned parity_devs;	/* # of parity devices. */
+	const unsigned minimal_devs;	/* minimal # of devices in set. */
+	const enum raid_level level;		/* RAID level. */
+	const enum raid_algorithm algorithm;	/* RAID algorithm. */
+};
+
+/* Supported raid types and properties. */
+static struct raid_type raid_types[] = {
+	{"raid4",    "RAID4 (dedicated parity disk)", 1, 3, raid4, none},
+	{"raid5_la", "RAID5 (left asymmetric)",       1, 3, raid5, left_asym},
+	{"raid5_ra", "RAID5 (right asymmetric)",      1, 3, raid5, right_asym},
+	{"raid5_ls", "RAID5 (left symmetric)",        1, 3, raid5, left_sym},
+	{"raid5_rs", "RAID5 (right symmetric)",       1, 3, raid5, right_sym},
+};
+
+/* Address as calculated by raid_address(). */
+struct raid_address {
+	sector_t key;		/* Hash key (address of stripe % chunk_size). */
+	unsigned di, pi;	/* Data and parity disks index. */
+};
+
+/* REMOVEME: reset statistics counters. */
+static void stats_reset(struct raid_set *rs)
+{
+	unsigned s = S_NR_STATS;
+
+	while (s--)
+		atomic_set(rs->stats + s, 0);
+}
+
+/*----------------------------------------------------------------
+ * RAID set management routines.
+ *--------------------------------------------------------------*/
+/*
+ * Begin small helper functions.
+ */
+/* No need to be called from region hash indirectly at dm_rh_dec(). */
+static void wake_dummy(void *context) {}
+
+/* Return # of io reference. */
+static int io_ref(struct raid_set *rs)
+{
+	return atomic_read(&rs->io.in_process);
+}
+
+/* Get an io reference. */
+static void io_get(struct raid_set *rs)
+{
+	int p = atomic_inc_return(&rs->io.in_process);
+
+	if (p > atomic_read(&rs->io.in_process_max))
+		atomic_set(&rs->io.in_process_max, p); /* REMOVEME: max. */
+}
+
+/* Put the io reference and conditionally wake io waiters. */
+static void io_put(struct raid_set *rs)
+{
+	/* Intel: rebuild data corrupter? */
+	if (atomic_dec_and_test(&rs->io.in_process))
+		wake_up(&rs->io.suspendq);
+	else
+		BUG_ON(io_ref(rs) < 0);
+}
+
+/* Wait until all io has been processed. */
+static void wait_ios(struct raid_set *rs)
+{
+	wait_event(rs->io.suspendq, !io_ref(rs));
+}
+
+/* Queue (optionally delayed) io work. */
+static void wake_do_raid_delayed(struct raid_set *rs, unsigned long delay)
+{
+	queue_delayed_work(rs->io.wq, &rs->io.dws_do_raid, delay);
+}
+
+/* Queue io work immediately (called from region hash too). */
+static void wake_do_raid(void *context)
+{
+	struct raid_set *rs = context;
+
+	queue_work(rs->io.wq, &rs->io.dws_do_raid.work);
+}
+
+/* Calculate device sector offset. */
+static sector_t _sector(struct raid_set *rs, struct bio *bio)
+{
+	sector_t sector = bio->bi_sector;
+
+	sector_div(sector, rs->set.data_devs);
+	return sector;
+}
+
+/* Return # of active stripes in stripe cache. */
+static int sc_active(struct stripe_cache *sc)
+{
+	return atomic_read(&sc->active_stripes);
+}
+
+/* Stripe cache busy indicator. */
+static int sc_busy(struct raid_set *rs)
+{
+	return sc_active(&rs->sc) >
+	       atomic_read(&rs->sc.stripes) - (STRIPES_MIN / 2);
+}
+
+/* Set chunks states. */
+enum chunk_dirty_type { CLEAN, DIRTY, ERROR };
+static void chunk_set(struct stripe_chunk *chunk, enum chunk_dirty_type type)
+{
+	switch (type) {
+	case CLEAN:
+		ClearChunkDirty(chunk);
+		break;
+	case DIRTY:
+		SetChunkDirty(chunk);
+		break;
+	case ERROR:
+		SetChunkError(chunk);
+		SetStripeError(chunk->stripe);
+		return;
+	default:
+		BUG();
+	}
+
+	SetChunkUptodate(chunk);
+	SetChunkIo(chunk);
+	ClearChunkError(chunk);
+}
+
+/* Return region state for a sector. */
+static int region_state(struct raid_set *rs, sector_t sector, 
+			enum dm_rh_region_states state)
+{
+	struct dm_rh_client *rh = rs->recover.rh;
+	region_t region = dm_rh_sector_to_region(rh, sector);
+
+	return !!(dm_rh_get_state(rh, region, 1) & state);
+}
+
+/*
+ * Return true in case a chunk should be read/written
+ *
+ * Conditions to read/write:
+ *	o chunk not uptodate
+ *	o chunk dirty
+ *
+ * Conditios to avoid io:
+ *	o io already ongoing on chunk
+ *	o io explitely prohibited
+ */
+static int chunk_io(struct stripe_chunk *chunk)
+{
+	/* 2nd run optimization (flag set below on first run). */
+	if (TestClearChunkMustIo(chunk))
+		return 1;
+
+	/* Avoid io if prohibited or a locked chunk. */
+	if (!ChunkIo(chunk) || ChunkLocked(chunk))
+		return 0;
+
+	if (!ChunkUptodate(chunk) || ChunkDirty(chunk)) {
+		SetChunkMustIo(chunk); /* 2nd run optimization. */
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Call a function on each chunk needing io unless device failed. */
+static unsigned for_each_io_dev(struct stripe *stripe,
+			        void (*f_io)(struct stripe *stripe, unsigned p))
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned p, r = 0;
+
+	for (p = 0; p < rs->set.raid_devs; p++) {
+		if (chunk_io(CHUNK(stripe, p)) && !DevFailed(rs->dev + p)) {
+			f_io(stripe, p);
+			r++;
+		}
+	}
+
+	return r;
+}
+
+/*
+ * Index of device to calculate parity on.
+ *
+ * Either the parity device index *or* the selected
+ * device to init after a spare replacement.
+ */
+static int dev_for_parity(struct stripe *stripe, int *sync)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	int r = region_state(rs, stripe->key, DM_RH_NOSYNC | DM_RH_RECOVERING);
+
+	*sync = !r;
+
+	/* Reconstruct a particular device ?. */
+	if (r && rs->set.dev_to_init > -1)
+		return rs->set.dev_to_init;
+	else if (rs->set.raid_type->level == raid4)
+		return rs->set.pi;
+	else if (!StripeRecover(stripe))
+		return stripe->idx.parity;
+	else
+		return -1;
+}
+
+/* RAID set congested function. */
+static int rs_congested(void *congested_data, int bdi_bits)
+{
+	int r;
+	unsigned p;
+	struct raid_set *rs = congested_data;
+
+	if (sc_busy(rs) || RSSuspend(rs))
+		r = 1;
+	else for (r = 0, p = rs->set.raid_devs; !r && p--; ) {
+		/* If any of our component devices are overloaded. */
+		struct request_queue *q = bdev_get_queue(rs->dev[p].dev->bdev);
+
+		r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+	}
+
+	/* REMOVEME: statistics. */
+	atomic_inc(rs->stats + (r ? S_CONGESTED : S_NOT_CONGESTED));
+	return r;
+}
+
+/* RAID device degrade check. */
+static void rs_check_degrade_dev(struct raid_set *rs,
+				       struct stripe *stripe, unsigned p)
+{
+	if (TestSetDevFailed(rs->dev + p))
+		return;
+
+	/* Through an event in case of member device errors. */
+	if (atomic_inc_return(&rs->set.failed_devs) >
+	    rs->set.raid_type->parity_devs &&
+	    !TestSetRSDead(rs)) {
+		/* Display RAID set dead message once. */
+		unsigned p;
+		char buf[BDEVNAME_SIZE];
+
+		DMERR("FATAL: too many devices failed -> RAID set broken");
+		for (p = 0; p < rs->set.raid_devs; p++) {
+			if (DevFailed(rs->dev + p))
+				DMERR("device /dev/%s failed",
+				      bdevname(rs->dev[p].dev->bdev, buf));
+		}
+	}
+
+	/* Only log the first member error. */
+	if (!TestSetRSDegraded(rs)) {
+		char buf[BDEVNAME_SIZE];
+
+		/* Store index for recovery. */
+		rs->set.ei = p;
+		DMERR("CRITICAL: %sio error on device /dev/%s "
+		      "in region=%llu; DEGRADING RAID set\n",
+		      stripe ? "" : "FAKED ",
+		      bdevname(rs->dev[p].dev->bdev, buf),
+		      (unsigned long long) (stripe ? stripe->key : 0));
+		DMERR("further device error messages suppressed");
+	}
+
+	schedule_work(&rs->io.ws_do_table_event);
+}
+
+/* RAID set degrade check. */
+static void rs_check_degrade(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned p = rs->set.raid_devs;
+
+	while (p--) {
+		if (ChunkError(CHUNK(stripe, p)))
+			rs_check_degrade_dev(rs, stripe, p);
+	}
+}
+
+/* Lookup a RAID device by name or by major:minor number. */
+static int raid_dev_lookup(struct raid_set *rs, struct raid_dev *dev_lookup)
+{
+	unsigned p;
+	struct raid_dev *dev;
+
+	/*
+	 * Must be an incremental loop, because the device array
+	 * can have empty slots still on calls from raid_ctr()
+	 */
+	for (dev = rs->dev, p = 0;
+	     dev->dev && p < rs->set.raid_devs;
+	     dev++, p++) {
+		if (dev_lookup->dev->bdev->bd_dev == dev->dev->bdev->bd_dev)
+			return p;
+	}
+
+	return -ENODEV;
+}
+/*
+ * End small helper functions.
+ */
+
+/*
+ * Stripe hash functions
+ */
+/* Initialize/destroy stripe hash. */
+static int hash_init(struct stripe_hash *hash, unsigned stripes)
+{
+	unsigned buckets = 2, max_buckets = stripes >> 1;
+	static unsigned hash_primes[] = {
+		/* Table of primes for hash_fn/table size optimization. */
+		1, 2, 3, 7, 13, 27, 53, 97, 193, 389, 769,
+		1543, 3079, 6151, 12289, 24593, 49157, 98317,
+	};
+
+	/* Calculate number of buckets (2^^n <= stripes / 2). */
+	while (buckets < max_buckets)
+		buckets <<= 1;
+
+	/* Allocate stripe hash buckets. */
+	hash->hash = vmalloc(buckets * sizeof(*hash->hash));
+	if (!hash->hash)
+		return -ENOMEM;
+
+	hash->buckets = buckets;
+	hash->mask = buckets - 1;
+	hash->shift = ffs(buckets);
+	if (hash->shift > ARRAY_SIZE(hash_primes))
+		hash->shift = ARRAY_SIZE(hash_primes) - 1;
+
+	BUG_ON(hash->shift < 2);
+	hash->prime = hash_primes[hash->shift];
+
+	/* Initialize buckets. */
+	while (buckets--)
+		INIT_LIST_HEAD(hash->hash + buckets);
+	return 0;
+}
+
+static void hash_exit(struct stripe_hash *hash)
+{
+	if (hash->hash) {
+		vfree(hash->hash);
+		hash->hash = NULL;
+	}
+}
+
+static unsigned hash_fn(struct stripe_hash *hash, sector_t key)
+{
+	return (unsigned) (((key * hash->prime) >> hash->shift) & hash->mask);
+}
+
+static struct list_head *hash_bucket(struct stripe_hash *hash, sector_t key)
+{
+	return hash->hash + hash_fn(hash, key);
+}
+
+/* Insert an entry into a hash. */
+static void stripe_insert(struct stripe_hash *hash, struct stripe *stripe)
+{
+	list_add(stripe->lists + LIST_HASH, hash_bucket(hash, stripe->key));
+}
+
+/* Lookup an entry in the stripe hash. */
+static struct stripe *stripe_lookup(struct stripe_cache *sc, sector_t key)
+{
+	unsigned look = 0;
+	struct stripe *stripe;
+	struct list_head *bucket = hash_bucket(&sc->hash, key);
+
+	list_for_each_entry(stripe, bucket, lists[LIST_HASH]) {
+		look++;
+
+		if (stripe->key == key) {
+			/* REMOVEME: statisics. */
+			if (look > atomic_read(RS(sc)->stats + S_MAX_LOOKUP))
+				atomic_set(RS(sc)->stats + S_MAX_LOOKUP, look);
+			return stripe;
+		}
+	}
+
+	return NULL;
+}
+
+/* Resize the stripe cache hash on size changes. */
+static int sc_hash_resize(struct stripe_cache *sc)
+{
+	/* Resize indicated ? */
+	if (atomic_read(&sc->stripes) != atomic_read(&sc->stripes_last)) {
+		int r;
+		struct stripe_hash hash;
+
+		r = hash_init(&hash, atomic_read(&sc->stripes));
+		if (r)
+			return r;
+
+		if (sc->hash.hash) {
+			unsigned b = sc->hash.buckets;
+			struct list_head *pos, *tmp;
+
+			/* Walk old buckets and insert into new. */
+			while (b--) {
+				list_for_each_safe(pos, tmp, sc->hash.hash + b)
+				    stripe_insert(&hash,
+						  list_entry(pos, struct stripe,
+							     lists[LIST_HASH]));
+			}
+
+		}
+
+		hash_exit(&sc->hash);
+		memcpy(&sc->hash, &hash, sizeof(sc->hash));
+		atomic_set(&sc->stripes_last, atomic_read(&sc->stripes));
+	}
+
+	return 0;
+}
+/* End hash stripe hash function. */
+
+/* List add, delete, push and pop functions. */
+/* Add stripe to flush list. */
+#define	DEL_LIST(lh) \
+	if (!list_empty(lh)) \
+		list_del_init(lh);
+
+/* Delete stripe from hash. */
+static void stripe_hash_del(struct stripe *stripe)
+{
+	DEL_LIST(stripe->lists + LIST_HASH);
+}
+
+/* Return stripe reference count. */
+static inline int stripe_ref(struct stripe *stripe)
+{
+	return atomic_read(&stripe->cnt);
+}
+
+static void stripe_flush_add(struct stripe *stripe)
+{
+	struct stripe_cache *sc = stripe->sc;
+	struct list_head *lh = stripe->lists + LIST_FLUSH;
+
+	if (!StripeReconstruct(stripe) && list_empty(lh))
+		list_add_tail(lh, sc->lists + LIST_FLUSH);
+}
+
+/*
+ * Add stripe to LRU (inactive) list.
+ *
+ * Need lock, because of concurrent access from message interface.
+ */
+static void stripe_lru_add(struct stripe *stripe)
+{
+	if (!StripeRecover(stripe)) {
+		unsigned long flags;
+		struct list_head *lh = stripe->lists + LIST_LRU;
+		spinlock_t *lock = stripe->sc->locks + LOCK_LRU;
+
+		spin_lock_irqsave(lock, flags);
+		if (list_empty(lh))
+			list_add_tail(lh, stripe->sc->lists + LIST_LRU);
+		spin_unlock_irqrestore(lock, flags);
+	}
+}
+
+#define POP_LIST(list) \
+	do { \
+		if (list_empty(sc->lists + (list))) \
+			stripe = NULL; \
+		else { \
+			stripe = list_first_entry(sc->lists + (list), \
+						  struct stripe, \
+						  lists[(list)]); \
+			list_del_init(stripe->lists + (list)); \
+		} \
+	} while (0);
+
+/* Pop an available stripe off the LRU list. */
+static struct stripe *stripe_lru_pop(struct stripe_cache *sc)
+{
+	struct stripe *stripe;
+	spinlock_t *lock = sc->locks + LOCK_LRU;
+
+	spin_lock_irq(lock);
+	POP_LIST(LIST_LRU);
+	spin_unlock_irq(lock);
+
+	return stripe;
+}
+
+/* Pop an available stripe off the io list. */
+static struct stripe *stripe_io_pop(struct stripe_cache *sc)
+{
+	struct stripe *stripe;
+
+	POP_LIST(LIST_FLUSH);
+	return stripe;
+}
+
+/* Push a stripe safely onto the endio list to be handled by do_endios(). */
+static void stripe_endio_push(struct stripe *stripe)
+{
+	unsigned long flags;
+	struct stripe_cache *sc = stripe->sc;
+	struct list_head *stripe_list = stripe->lists + LIST_ENDIO,
+			 *sc_list = sc->lists + LIST_ENDIO;
+	spinlock_t *lock = sc->locks + LOCK_ENDIO;
+
+	/* This runs in parallel with do_endios(). */
+	spin_lock_irqsave(lock, flags);
+	if (list_empty(stripe_list))
+		list_add_tail(stripe_list, sc_list);
+	spin_unlock_irqrestore(lock, flags);
+
+	wake_do_raid(RS(sc)); /* Wake myself. */
+}
+
+/* Pop a stripe off safely off the endio list. */
+static struct stripe *stripe_endio_pop(struct stripe_cache *sc)
+{
+	struct stripe *stripe;
+	spinlock_t *lock = sc->locks + LOCK_ENDIO;
+
+	/* This runs in parallel with endio(). */
+	spin_lock_irq(lock);
+	POP_LIST(LIST_ENDIO)
+	spin_unlock_irq(lock);
+	return stripe;
+}
+#undef POP_LIST
+
+/*
+ * Stripe cache locking functions
+ */
+/* Dummy lock function for single host RAID4+5. */
+static void *no_lock(sector_t key, enum dm_lock_type type)
+{
+	return &no_lock;
+}
+
+/* Dummy unlock function for single host RAID4+5. */
+static void no_unlock(void *lock_handle)
+{
+}
+
+/* No locking (for single host RAID 4+5). */
+static struct dm_raid45_locking_type locking_none = {
+	.lock = no_lock,
+	.unlock = no_unlock,
+};
+
+/* Lock a stripe (for clustering). */
+static int
+stripe_lock(struct stripe *stripe, int rw, sector_t key)
+{
+	stripe->lock = RS(stripe->sc)->locking->lock(key, rw == READ ? DM_RAID45_SHARED : DM_RAID45_EX);
+	return stripe->lock ? 0 : -EPERM;
+}
+
+/* Unlock a stripe (for clustering). */
+static void stripe_unlock(struct stripe *stripe)
+{
+	RS(stripe->sc)->locking->unlock(stripe->lock);
+	stripe->lock = NULL;
+}
+
+/* Test io pending on stripe. */
+static int stripe_io_ref(struct stripe *stripe)
+{
+	return atomic_read(&stripe->io.pending);
+}
+
+static void stripe_io_get(struct stripe *stripe)
+{
+	if (atomic_inc_return(&stripe->io.pending) == 1)
+		/* REMOVEME: statistics */
+		atomic_inc(&stripe->sc->active_stripes);
+	else
+		BUG_ON(stripe_io_ref(stripe) < 0);
+}
+
+static void stripe_io_put(struct stripe *stripe)
+{
+	if (atomic_dec_and_test(&stripe->io.pending)) {
+		if (unlikely(StripeRecover(stripe)))
+			/* Don't put recovery stripe on endio list. */
+			wake_do_raid(RS(stripe->sc));
+		else
+			/* Add regular stripe to endio list and wake daemon. */
+			stripe_endio_push(stripe);
+
+		/* REMOVEME: statistics */
+		atomic_dec(&stripe->sc->active_stripes);
+	} else
+		BUG_ON(stripe_io_ref(stripe) < 0);
+}
+
+/* Take stripe reference out. */
+static int stripe_get(struct stripe *stripe)
+{
+	int r;
+	struct list_head *lh = stripe->lists + LIST_LRU;
+	spinlock_t *lock = stripe->sc->locks + LOCK_LRU;
+
+	/* Delete stripe from LRU (inactive) list if on. */
+	spin_lock_irq(lock);
+	DEL_LIST(lh);
+	spin_unlock_irq(lock);
+
+	BUG_ON(stripe_ref(stripe) < 0);
+
+	/* Lock stripe on first reference */
+	r = (atomic_inc_return(&stripe->cnt) == 1) ?
+	    stripe_lock(stripe, WRITE, stripe->key) : 0;
+
+	return r;
+}
+#undef DEL_LIST
+
+/* Return references on a chunk. */
+static int chunk_ref(struct stripe_chunk *chunk)
+{
+	return atomic_read(&chunk->cnt);
+}
+
+/* Take out reference on a chunk. */
+static int chunk_get(struct stripe_chunk *chunk)
+{
+	return atomic_inc_return(&chunk->cnt);
+}
+
+/* Drop reference on a chunk. */
+static void chunk_put(struct stripe_chunk *chunk)
+{
+	BUG_ON(atomic_dec_return(&chunk->cnt) < 0);
+}
+
+/*
+ * Drop reference on a stripe.
+ *
+ * Move it to list of LRU stripes if zero.
+ */
+static void stripe_put(struct stripe *stripe)
+{
+	if (atomic_dec_and_test(&stripe->cnt)) {
+		BUG_ON(stripe_io_ref(stripe));
+		stripe_unlock(stripe);
+	} else
+		BUG_ON(stripe_ref(stripe) < 0);
+}
+
+/* Helper needed by for_each_io_dev(). */
+static void stripe_get_references(struct stripe *stripe, unsigned p)
+{
+
+	/*
+	 * Another one to reference the stripe in
+	 * order to protect vs. LRU list moves.
+	 */
+	io_get(RS(stripe->sc));	/* Global io references. */
+	stripe_get(stripe);
+	stripe_io_get(stripe);	/* One for each chunk io. */
+}
+
+/* Helper for endio() to put all take references. */
+static void stripe_put_references(struct stripe *stripe)
+{
+	stripe_io_put(stripe);	/* One for each chunk io. */
+	stripe_put(stripe);
+	io_put(RS(stripe->sc));
+}
+
+/*
+ * Stripe cache functions.
+ */
+/*
+ * Invalidate all chunks (i.e. their pages)  of a stripe.
+ *
+ * I only keep state for the whole chunk.
+ */
+static inline void stripe_chunk_invalidate(struct stripe_chunk *chunk)
+{
+	chunk->io.flags = 0;
+}
+
+static void
+stripe_chunks_invalidate(struct stripe *stripe)
+{
+	unsigned p = RS(stripe->sc)->set.raid_devs;
+
+	while (p--)
+		stripe_chunk_invalidate(CHUNK(stripe, p));
+}
+
+/* Prepare stripe for (re)use. */
+static void stripe_invalidate(struct stripe *stripe)
+{
+	stripe->io.flags = 0;
+	stripe->idx.parity = stripe->idx.recover = -1;
+	stripe_chunks_invalidate(stripe);
+}
+
+/*
+ * Allow io on all chunks of a stripe.
+ * If not set, IO will not occur; i.e. it's prohibited.
+ *
+ * Actual IO submission for allowed chunks depends
+ * on their !uptodate or dirty state.
+ */
+static void stripe_allow_io(struct stripe *stripe)
+{
+	unsigned p = RS(stripe->sc)->set.raid_devs;
+
+	while (p--)
+		SetChunkIo(CHUNK(stripe, p));
+}
+
+/* Initialize a stripe. */
+static void stripe_init(struct stripe_cache *sc, struct stripe *stripe)
+{
+	unsigned i, p = RS(sc)->set.raid_devs;
+
+	/* Work all io chunks. */
+	while (p--) {
+		struct stripe_chunk *chunk = CHUNK(stripe, p);
+
+		atomic_set(&chunk->cnt, 0);
+		chunk->stripe = stripe;
+		i = ARRAY_SIZE(chunk->bl);
+		while (i--)
+			bio_list_init(chunk->bl + i);
+	}
+
+	stripe->sc = sc;
+
+
+	i = ARRAY_SIZE(stripe->lists);
+	while (i--)
+		INIT_LIST_HEAD(stripe->lists + i);
+
+	stripe->io.size = RS(sc)->set.io_size;
+	atomic_set(&stripe->cnt, 0);
+	atomic_set(&stripe->io.pending, 0);
+	stripe_invalidate(stripe);
+}
+
+/* Number of pages per chunk. */
+static inline unsigned chunk_pages(unsigned sectors)
+{
+	return dm_div_up(sectors, SECTORS_PER_PAGE);
+}
+
+/* Number of pages per stripe. */
+static inline unsigned stripe_pages(struct raid_set *rs, unsigned io_size)
+{
+	return chunk_pages(io_size) * rs->set.raid_devs;
+}
+
+/* Initialize part of page_list (recovery). */
+static void stripe_zero_pl_part(struct stripe *stripe, int p,
+				unsigned start, unsigned count)
+{
+	unsigned o = start / SECTORS_PER_PAGE, pages = chunk_pages(count);
+	/* Get offset into the page_list. */
+	struct page_list *pl = pl_elem(PL(stripe, p), o);
+
+	BUG_ON(!pl);
+	while (pl && pages--) {
+		BUG_ON(!pl->page);
+		memset(page_address(pl->page), 0, PAGE_SIZE);
+		pl = pl->next;
+	}
+}
+
+/* Initialize parity chunk of stripe. */
+static void stripe_zero_chunk(struct stripe *stripe, int p)
+{
+	if (p > -1)
+		stripe_zero_pl_part(stripe, p, 0, stripe->io.size);
+}
+
+/* Return dynamic stripe structure size. */
+static size_t stripe_size(struct raid_set *rs)
+{
+	return sizeof(struct stripe) +
+		      rs->set.raid_devs * sizeof(struct stripe_chunk);
+}
+
+/* Allocate a stripe and its memory object. */
+/* XXX adjust to cope with stripe cache and recovery stripe caches. */
+enum grow { SC_GROW, SC_KEEP };
+static struct stripe *stripe_alloc(struct stripe_cache *sc,
+				   struct dm_mem_cache_client *mc,
+				   enum grow grow)
+{
+	int r;
+	struct stripe *stripe;
+
+	stripe = kmem_cache_zalloc(sc->kc.cache, GFP_KERNEL);
+	if (stripe) {
+		/* Grow the dm-mem-cache by one object. */
+		if (grow == SC_GROW) {
+			r = dm_mem_cache_grow(mc, 1);
+			if (r)
+				goto err_free;
+		}
+
+		stripe->obj = dm_mem_cache_alloc(mc);
+		if (!stripe->obj)
+			goto err_shrink;
+
+		stripe_init(sc, stripe);
+	}
+
+	return stripe;
+
+err_shrink:
+	if (grow == SC_GROW)
+		dm_mem_cache_shrink(mc, 1);
+err_free:
+	kmem_cache_free(sc->kc.cache, stripe);
+	return NULL;
+}
+
+/*
+ * Free a stripes memory object, shrink the
+ * memory cache and free the stripe itself.
+ */
+static void stripe_free(struct stripe *stripe, struct dm_mem_cache_client *mc)
+{
+	dm_mem_cache_free(mc, stripe->obj);
+	dm_mem_cache_shrink(mc, 1);
+	kmem_cache_free(stripe->sc->kc.cache, stripe);
+}
+
+/* Free the recovery stripe. */
+static void stripe_recover_free(struct raid_set *rs)
+{
+	struct recover *rec = &rs->recover;
+	struct dm_mem_cache_client *mc;
+
+	mc = rec->mem_cache_client;
+	rec->mem_cache_client = NULL;
+	if (mc) {
+		struct stripe *stripe;
+
+		while (!list_empty(&rec->stripes)) {
+			stripe = list_first_entry(&rec->stripes, struct stripe,
+						  lists[LIST_RECOVER]);
+			list_del(stripe->lists + LIST_RECOVER);
+			kfree(stripe->recover);
+			stripe_free(stripe, mc);
+		}
+	
+		dm_mem_cache_client_destroy(mc);
+		dm_io_client_destroy(rec->dm_io_client);
+		rec->dm_io_client = NULL;
+	}
+}
+
+/* Grow stripe cache. */
+static int sc_grow(struct stripe_cache *sc, unsigned stripes, enum grow grow)
+{
+	int r = 0;
+
+	/* Try to allocate this many (additional) stripes. */
+	while (stripes--) {
+		struct stripe *stripe =
+			stripe_alloc(sc, sc->mem_cache_client, grow);
+
+		if (likely(stripe)) {
+			stripe_lru_add(stripe);
+			atomic_inc(&sc->stripes);
+		} else {
+			r = -ENOMEM;
+			break;
+		}
+	}
+
+	return r ? r : sc_hash_resize(sc);
+}
+
+/* Shrink stripe cache. */
+static int sc_shrink(struct stripe_cache *sc, unsigned stripes)
+{
+	int r = 0;
+
+	/* Try to get unused stripe from LRU list. */
+	while (stripes--) {
+		struct stripe *stripe;
+
+		stripe = stripe_lru_pop(sc);
+		if (stripe) {
+			/* An LRU stripe may never have ios pending! */
+			BUG_ON(stripe_io_ref(stripe));
+			BUG_ON(stripe_ref(stripe));
+			atomic_dec(&sc->stripes);
+			/* Remove from hash if on before deletion. */
+			stripe_hash_del(stripe);
+			stripe_free(stripe, sc->mem_cache_client);
+		} else {
+			r = -ENOENT;
+			break;
+		}
+	}
+
+	/* Check if stats are still sane. */
+	if (atomic_read(&sc->active_stripes_max) >
+	    atomic_read(&sc->stripes))
+		atomic_set(&sc->active_stripes_max, 0);
+
+	if (r)
+		return r;
+
+	return atomic_read(&sc->stripes) ? sc_hash_resize(sc) : 0;
+}
+
+/* Create stripe cache and recovery. */
+static int sc_init(struct raid_set *rs, unsigned stripes)
+{
+	unsigned i, r, rstripes;
+	struct stripe_cache *sc = &rs->sc;
+	struct stripe *stripe;
+	struct recover *rec = &rs->recover;
+	struct mapped_device *md;
+	struct gendisk *disk;
+
+	/* Initialize lists and locks. */
+	i = ARRAY_SIZE(sc->lists);
+	while (i--)
+		INIT_LIST_HEAD(sc->lists + i);
+
+	INIT_LIST_HEAD(&rec->stripes);
+
+	/* Initialize endio and LRU list locks. */
+	i = NR_LOCKS;
+	while (i--)
+		spin_lock_init(sc->locks + i);
+
+	/* Initialize atomic variables. */
+	atomic_set(&sc->stripes, 0);
+	atomic_set(&sc->stripes_to_set, 0);
+	atomic_set(&sc->active_stripes, 0);
+	atomic_set(&sc->active_stripes_max, 0);	/* REMOVEME: statistics. */
+
+	/*
+	 * We need a runtime unique # to suffix the kmem cache name
+	 * because we'll have one for each active RAID set.
+	 */
+	md = dm_table_get_md(rs->ti->table);
+	disk = dm_disk(md);
+	sprintf(sc->kc.name, "%s-%d", TARGET, disk->first_minor);
+	dm_put(md);
+	sc->kc.cache = kmem_cache_create(sc->kc.name, stripe_size(rs),
+					 0, 0, NULL);
+	if (!sc->kc.cache)
+		return -ENOMEM;
+
+	/* Create memory cache client context for RAID stripe cache. */
+	sc->mem_cache_client =
+		dm_mem_cache_client_create(stripes, rs->set.raid_devs,
+					   chunk_pages(rs->set.io_size));
+	if (IS_ERR(sc->mem_cache_client))
+		return PTR_ERR(sc->mem_cache_client);
+
+	/* Create memory cache client context for RAID recovery stripe(s). */
+	rstripes = rec->recovery_stripes;
+	rec->mem_cache_client =
+		dm_mem_cache_client_create(rstripes, rs->set.raid_devs,
+					   chunk_pages(rec->io_size));
+	if (IS_ERR(rec->mem_cache_client))
+		return PTR_ERR(rec->mem_cache_client);
+
+	/* Create dm-io client context for IO stripes. */
+	sc->dm_io_client =
+		dm_io_client_create((stripes > 32 ? 32 : stripes) *
+				    rs->set.raid_devs *
+				    chunk_pages(rs->set.io_size));
+	if (IS_ERR(sc->dm_io_client))
+		return PTR_ERR(sc->dm_io_client);
+
+	/* FIXME: intermingeled with stripe cache initialization. */
+	/* Create dm-io client context for recovery stripes. */
+	rec->dm_io_client =
+		dm_io_client_create(rstripes * rs->set.raid_devs *
+				    chunk_pages(rec->io_size));
+	if (IS_ERR(rec->dm_io_client))
+		return PTR_ERR(rec->dm_io_client);
+
+	/* Allocate stripes for set recovery. */
+	while (rstripes--) {
+		stripe = stripe_alloc(sc, rec->mem_cache_client, SC_KEEP);
+		if (!stripe)
+			return -ENOMEM;
+
+		stripe->recover = kzalloc(sizeof(*stripe->recover), GFP_KERNEL);
+		if (!stripe->recover) {
+			stripe_free(stripe, rec->mem_cache_client);
+			return -ENOMEM;
+		}
+
+		SetStripeRecover(stripe);
+		stripe->io.size = rec->io_size;
+		list_add_tail(stripe->lists + LIST_RECOVER, &rec->stripes);
+		/* Don't add recovery stripes to LRU list! */
+	}
+
+	/*
+	 * Allocate the stripe objetcs from the
+	 * cache and add them to the LRU list.
+	 */
+	r = sc_grow(sc, stripes, SC_KEEP);
+	if (!r)
+		atomic_set(&sc->stripes_last, stripes);
+
+	return r;
+}
+
+/* Destroy the stripe cache. */
+static void sc_exit(struct stripe_cache *sc)
+{
+	struct raid_set *rs = RS(sc);
+
+	if (sc->kc.cache) {
+		stripe_recover_free(rs);
+		BUG_ON(sc_shrink(sc, atomic_read(&sc->stripes)));
+		kmem_cache_destroy(sc->kc.cache);
+		sc->kc.cache = NULL;
+
+		if (sc->mem_cache_client && !IS_ERR(sc->mem_cache_client))
+			dm_mem_cache_client_destroy(sc->mem_cache_client);
+
+		if (sc->dm_io_client && !IS_ERR(sc->dm_io_client))
+			dm_io_client_destroy(sc->dm_io_client);
+
+		hash_exit(&sc->hash);
+	}
+}
+
+/*
+ * Calculate RAID address
+ *
+ * Delivers tuple with the index of the data disk holding the chunk
+ * in the set, the parity disks index and the start of the stripe
+ * within the address space of the set (used as the stripe cache hash key).
+ */
+/* thx MD. */
+static struct raid_address *raid_address(struct raid_set *rs, sector_t sector,
+					 struct raid_address *addr)
+{
+	sector_t stripe, tmp;
+
+	/*
+	 * chunk_number = sector / chunk_size
+	 * stripe_number = chunk_number / data_devs
+	 * di = stripe % data_devs;
+	 */
+	stripe = sector >> rs->set.chunk_shift;
+	addr->di = sector_div(stripe, rs->set.data_devs);
+
+	switch (rs->set.raid_type->level) {
+	case raid4:
+		addr->pi = rs->set.pi;
+		goto check_shift_di;
+	case raid5:
+		tmp = stripe;
+		addr->pi = sector_div(tmp, rs->set.raid_devs);
+
+		switch (rs->set.raid_type->algorithm) {
+		case left_asym:		/* Left asymmetric. */
+			addr->pi = rs->set.data_devs - addr->pi;
+		case right_asym:	/* Right asymmetric. */
+check_shift_di:
+			if (addr->di >= addr->pi)
+				addr->di++;
+			break;
+		case left_sym:		/* Left symmetric. */
+			addr->pi = rs->set.data_devs - addr->pi;
+		case right_sym:		/* Right symmetric. */
+			addr->di = (addr->pi + addr->di + 1) %
+				   rs->set.raid_devs;
+			break;
+		case none: /* Ain't happen: RAID4 algorithm placeholder. */
+			BUG();
+		}
+	}
+
+	/*
+	 * Start offset of the stripes chunk on any single device of the RAID
+	 * set, adjusted in case io size differs from chunk size.
+	 */
+	addr->key = (stripe << rs->set.chunk_shift) +
+		    (sector & rs->set.io_inv_mask);
+	return addr;
+}
+
+/*
+ * Copy data across between stripe pages and bio vectors.
+ *
+ * Pay attention to data alignment in stripe and bio pages.
+ */
+static void bio_copy_page_list(int rw, struct stripe *stripe,
+			       struct page_list *pl, struct bio *bio)
+{
+	unsigned i, page_offset;
+	void *page_addr;
+	struct raid_set *rs = RS(stripe->sc);
+	struct bio_vec *bv;
+
+	/* Get start page in page list for this sector. */
+	i = (bio->bi_sector & rs->set.io_mask) / SECTORS_PER_PAGE;
+	pl = pl_elem(pl, i);
+	BUG_ON(!pl);
+	BUG_ON(!pl->page);
+
+	page_addr = page_address(pl->page);
+	page_offset = to_bytes(bio->bi_sector & (SECTORS_PER_PAGE - 1));
+
+	/* Walk all segments and copy data across between bio_vecs and pages. */
+	bio_for_each_segment(bv, bio, i) {
+		int len = bv->bv_len, size;
+		unsigned bio_offset = 0;
+		void *bio_addr = __bio_kmap_atomic(bio, i, KM_USER0);
+redo:
+		size = (page_offset + len > PAGE_SIZE) ?
+		       PAGE_SIZE - page_offset : len;
+
+		if (rw == READ)
+			memcpy(bio_addr + bio_offset,
+			       page_addr + page_offset, size);
+		else
+			memcpy(page_addr + page_offset,
+			       bio_addr + bio_offset, size);
+
+		page_offset += size;
+		if (page_offset == PAGE_SIZE) {
+			/*
+			 * We reached the end of the chunk page ->
+			 * need to refer to the next one to copy more data.
+			 */
+			len -= size;
+			if (len) {
+				/* Get next page. */
+				pl = pl->next;
+				BUG_ON(!pl);
+				BUG_ON(!pl->page);
+				page_addr = page_address(pl->page);
+				page_offset = 0;
+				bio_offset += size;
+				/* REMOVEME: statistics. */
+				atomic_inc(rs->stats + S_BIO_COPY_PL_NEXT);
+				goto redo;
+			}
+		}
+
+		__bio_kunmap_atomic(bio_addr, KM_USER0);
+	}
+}
+
+/*
+ * Xor optimization macros.
+ */
+/* Xor data pointer declaration and initialization macros. */
+#define DECLARE_2	unsigned long *d0 = data[0], *d1 = data[1]
+#define DECLARE_3	DECLARE_2, *d2 = data[2]
+#define DECLARE_4	DECLARE_3, *d3 = data[3]
+#define DECLARE_5	DECLARE_4, *d4 = data[4]
+#define DECLARE_6	DECLARE_5, *d5 = data[5]
+#define DECLARE_7	DECLARE_6, *d6 = data[6]
+#define DECLARE_8	DECLARE_7, *d7 = data[7]
+
+/* Xor unrole macros. */
+#define D2(n)	d0[n] = d0[n] ^ d1[n]
+#define D3(n)	D2(n) ^ d2[n]
+#define D4(n)	D3(n) ^ d3[n]
+#define D5(n)	D4(n) ^ d4[n]
+#define D6(n)	D5(n) ^ d5[n]
+#define D7(n)	D6(n) ^ d6[n]
+#define D8(n)	D7(n) ^ d7[n]
+
+#define	X_2(macro, offset)	macro(offset); macro(offset + 1);
+#define	X_4(macro, offset)	X_2(macro, offset); X_2(macro, offset + 2);
+#define	X_8(macro, offset)	X_4(macro, offset); X_4(macro, offset + 4);
+#define	X_16(macro, offset)	X_8(macro, offset); X_8(macro, offset + 8);
+#define	X_32(macro, offset)	X_16(macro, offset); X_16(macro, offset + 16);
+#define	X_64(macro, offset)	X_32(macro, offset); X_32(macro, offset + 32);
+
+/* Define a _xor_#chunks_#xors_per_run() function. */
+#define	_XOR(chunks, xors_per_run) \
+static void _xor ## chunks ## _ ## xors_per_run(unsigned long **data) \
+{ \
+	unsigned end = XOR_SIZE / sizeof(data[0]), i; \
+	DECLARE_ ## chunks; \
+\
+	for (i = 0; i < end; i += xors_per_run) { \
+		X_ ## xors_per_run(D ## chunks, i); \
+	} \
+}
+
+/* Define xor functions for 2 - 8 chunks and xors per run. */
+#define	MAKE_XOR_PER_RUN(xors_per_run) \
+	_XOR(2, xors_per_run); _XOR(3, xors_per_run); \
+	_XOR(4, xors_per_run); _XOR(5, xors_per_run); \
+	_XOR(6, xors_per_run); _XOR(7, xors_per_run); \
+	_XOR(8, xors_per_run);
+
+MAKE_XOR_PER_RUN(8)	/* Define _xor_*_8() functions. */
+MAKE_XOR_PER_RUN(16)	/* Define _xor_*_16() functions. */
+MAKE_XOR_PER_RUN(32)	/* Define _xor_*_32() functions. */
+MAKE_XOR_PER_RUN(64)	/* Define _xor_*_64() functions. */
+
+#define MAKE_XOR(xors_per_run) \
+struct { \
+	void (*f)(unsigned long **); \
+} static xor_funcs ## xors_per_run[] = { \
+	{ NULL }, /* NULL pointers to optimize indexing in xor(). */ \
+	{ NULL }, \
+	{ _xor2_ ## xors_per_run }, \
+	{ _xor3_ ## xors_per_run }, \
+	{ _xor4_ ## xors_per_run }, \
+	{ _xor5_ ## xors_per_run }, \
+	{ _xor6_ ## xors_per_run }, \
+	{ _xor7_ ## xors_per_run }, \
+	{ _xor8_ ## xors_per_run }, \
+}; \
+\
+static void xor_ ## xors_per_run(unsigned n, unsigned long **data) \
+{ \
+	/* Call respective function for amount of chunks. */ \
+	xor_funcs ## xors_per_run[n].f(data); \
+}
+
+/* Define xor_8() - xor_64 functions. */
+MAKE_XOR(8)
+MAKE_XOR(16)
+MAKE_XOR(32)
+MAKE_XOR(64)
+
+/* Maximum number of chunks, which can be xor'ed in one go. */
+#define	XOR_CHUNKS_MAX	(ARRAY_SIZE(xor_funcs8) - 1)
+
+static void xor_blocks_wrapper(unsigned n, unsigned long **data)
+{
+	BUG_ON(n < 2 || n > MAX_XOR_BLOCKS + 1);
+	xor_blocks(n - 1, XOR_SIZE, (void *) data[0], (void **) data + 1);
+}
+
+struct xor_func {
+	xor_function_t f;
+	const char *name;
+} static xor_funcs[] = {
+	{ xor_8,   "xor_8"  },
+	{ xor_16,  "xor_16" },
+	{ xor_32,  "xor_32" },
+	{ xor_64,  "xor_64" },
+	{ xor_blocks_wrapper, "xor_blocks" },
+};
+
+/*
+ * Check, if chunk has to be xored in/out:
+ *
+ * o if writes are queued
+ * o if writes are merged
+ * o if stripe is to be reconstructed
+ * o if recovery stripe
+ */
+static inline int chunk_must_xor(struct stripe_chunk *chunk)
+{
+	if (ChunkUptodate(chunk)) {
+		BUG_ON(!bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED)) &&
+		       !bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED)));
+
+		if (!bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED)) ||
+		    !bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED)))
+			return 1;
+
+		if (StripeReconstruct(chunk->stripe) ||
+		    StripeRecover(chunk->stripe))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate crc.
+ *
+ * This indexes into the chunks of a stripe and their pages.
+ *
+ * All chunks will be xored into the indexed (@pi)
+ * chunk in maximum groups of xor.chunks.
+ *
+ */
+static void xor(struct stripe *stripe, unsigned pi, unsigned sector)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned max_chunks = rs->xor.chunks, n = 1,
+		 o = sector / SECTORS_PER_PAGE, /* Offset into the page_list. */
+		 p = rs->set.raid_devs;
+	unsigned long **d = rs->data;
+	xor_function_t xor_f = rs->xor.f->f;
+
+	BUG_ON(sector > stripe->io.size);
+
+	/* Address of parity page to xor into. */
+	d[0] = page_address(pl_elem(PL(stripe, pi), o)->page);
+
+	while (p--) {
+		/* Preset pointers to data pages. */
+		if (p != pi && chunk_must_xor(CHUNK(stripe, p)))
+			d[n++] = page_address(pl_elem(PL(stripe, p), o)->page);
+
+		/* If max chunks -> xor. */
+		if (n == max_chunks) {
+			xor_f(n, d);
+			n = 1;
+		}
+	}
+
+	/* If chunks -> xor. */
+	if (n > 1)
+		xor_f(n, d);
+}
+
+/* Common xor loop through all stripe page lists. */
+static void common_xor(struct stripe *stripe, sector_t count,
+		       unsigned off, unsigned pi)
+{
+	unsigned sector;
+
+	BUG_ON(!count);
+	for (sector = off; sector < count; sector += SECTORS_PER_PAGE)
+		xor(stripe, pi, sector);
+
+	/* Set parity page uptodate and clean. */
+	chunk_set(CHUNK(stripe, pi), CLEAN);
+	atomic_inc(RS(stripe->sc)->stats + S_XORS); /* REMOVEME: statistics. */
+}
+
+/*
+ * Calculate parity sectors on intact stripes.
+ *
+ * Need to calculate raid address for recover stripe, because its
+ * chunk sizes differs and is typically larger than io chunk size.
+ */
+static void parity_xor(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned chunk_size = rs->set.chunk_size, io_size = stripe->io.size,
+		 xor_size = chunk_size > io_size ? io_size : chunk_size;
+	sector_t off;
+
+	/* This can be the recover stripe with a larger io size. */
+	for (off = 0; off < io_size; off += xor_size) {
+		/*
+		 * Recover stripe is likely bigger than regular io
+		 * ones and has no precalculated parity disk index ->
+		 * need to calculate RAID address.
+		 */
+		if (unlikely(StripeRecover(stripe))) {
+			struct raid_address addr;
+
+			raid_address(rs,
+				     (stripe->key + off) * rs->set.data_devs,
+				     &addr);
+			stripe->idx.parity = addr.pi;
+			stripe_zero_pl_part(stripe, addr.pi, off, xor_size);
+		}
+
+		common_xor(stripe, xor_size, off, stripe->idx.parity);
+		chunk_set(CHUNK(stripe, stripe->idx.parity), DIRTY);
+	}
+}
+
+/* Reconstruct missing chunk. */
+static void stripe_reconstruct(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	int p = rs->set.raid_devs, pr = stripe->idx.recover;
+
+	BUG_ON(pr < 0);
+
+	/* Check if all but the chunk to be reconstructed are uptodate. */
+	while (p--)
+		BUG_ON(p != pr && !ChunkUptodate(CHUNK(stripe, p)));
+
+	/* REMOVEME: statistics. */
+	atomic_inc(rs->stats + (RSDegraded(rs) ? S_RECONSTRUCT_EI :
+						 S_RECONSTRUCT_DEV));
+	/* Zero chunk to be reconstructed. */
+	stripe_zero_chunk(stripe, pr);
+	common_xor(stripe, stripe->io.size, 0, pr);
+	stripe->idx.recover = -1;
+}
+
+/*
+ * Recovery io throttling
+ */
+/* Conditionally reset io counters. */
+static int recover_io_reset(struct raid_set *rs)
+{
+	unsigned long j = jiffies;
+
+	/* Pay attention to jiffies overflows. */
+	if (j > rs->recover.last_jiffies + HZ / 20 ||
+	    j < rs->recover.last_jiffies) {
+		atomic_set(rs->recover.io_count + IO_WORK, 0);
+		atomic_set(rs->recover.io_count + IO_RECOVER, 0);
+		rs->recover.last_jiffies = j;
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Count ios. */
+static void recover_io_count(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+
+	recover_io_reset(rs);
+	atomic_inc(rs->recover.io_count +
+		   (StripeRecover(stripe) ? IO_RECOVER : IO_WORK));
+}
+
+/* Try getting a stripe either from the hash or from the LRU list. */
+static struct stripe *stripe_find(struct raid_set *rs,
+				  struct raid_address *addr)
+{
+	int r;
+	struct stripe_cache *sc = &rs->sc;
+	struct stripe *stripe;
+
+	/* Try stripe from hash. */
+	stripe = stripe_lookup(sc, addr->key);
+	if (stripe) {
+		r = stripe_get(stripe);
+		if (r)
+			goto get_lock_failed;
+
+		atomic_inc(rs->stats + S_HITS_1ST); /* REMOVEME: statistics. */
+	} else {
+		/* Not in hash -> try to get an LRU stripe. */
+		stripe = stripe_lru_pop(sc);
+		if (stripe) {
+			/*
+			 * An LRU stripe may not be referenced
+			 * and may never have ios pending!
+			 */
+			BUG_ON(stripe_ref(stripe));
+			BUG_ON(stripe_io_ref(stripe));
+
+			/* Remove from hash if on before reuse. */
+			stripe_hash_del(stripe);
+
+			/* Invalidate before reinserting with changed key. */
+			stripe_invalidate(stripe);
+
+			stripe->key = addr->key;
+			stripe->region = dm_rh_sector_to_region(rs->recover.rh,
+								addr->key);
+			stripe->idx.parity = addr->pi;
+			r = stripe_get(stripe);
+			if (r)
+				goto get_lock_failed;
+
+			/* Insert stripe into the stripe hash. */
+			stripe_insert(&sc->hash, stripe);
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_INSCACHE);
+		}
+	}
+
+	return stripe;
+
+get_lock_failed:
+	stripe_put(stripe);
+	return NULL;
+}
+
+/*
+ * Process end io
+ *
+ * I need to do it here because I can't in interrupt
+ */
+/* End io all bios on a bio list. */
+static void bio_list_endio(struct stripe *stripe, struct bio_list *bl,
+			   int p, int error)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	struct bio *bio;
+	struct page_list *pl = PL(stripe, p);
+	struct stripe_chunk *chunk = CHUNK(stripe, p);
+
+	/* Update region counters. */
+	while ((bio = bio_list_pop(bl))) {
+		if (bio_data_dir(bio) == WRITE)
+			/* Drop io pending count for any writes. */
+			dm_rh_dec(rs->recover.rh, stripe->region);
+		else if (!error)
+			/* Copy data accross. */
+			bio_copy_page_list(READ, stripe, pl, bio);
+
+		bio_endio(bio, error);
+
+		/* REMOVEME: statistics. */
+		atomic_inc(rs->stats + (bio_data_dir(bio) == READ ?
+			   S_BIOS_ENDIO_READ : S_BIOS_ENDIO_WRITE));
+
+		chunk_put(chunk);
+		stripe_put(stripe);
+		io_put(rs);	/* Wake any suspend waiters on last bio. */
+	}
+}
+
+/*
+ * End io all reads/writes on a stripe copying
+ * read data accross from stripe to bios and
+ * decrementing region counters for writes.
+ *
+ * Processing of ios depeding on state:
+ * o no chunk error -> endio ok
+ * o degraded:
+ *   - chunk error and read -> ignore to be requeued
+ *   - chunk error and write -> endio ok
+ * o dead (more than parity_devs failed) and chunk_error-> endio failed
+ */
+static void stripe_endio(int rw, struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned p = rs->set.raid_devs;
+	int write = (rw != READ);
+
+	while (p--) {
+		struct stripe_chunk *chunk = CHUNK(stripe, p);
+		struct bio_list *bl;
+
+		BUG_ON(ChunkLocked(chunk));
+
+		bl = BL_CHUNK(chunk, rw);
+		if (bio_list_empty(bl))
+			continue;
+
+		if (unlikely(ChunkError(chunk) || !ChunkUptodate(chunk))) {
+			/* RAID set dead. */
+			if (unlikely(RSDead(rs)))
+				bio_list_endio(stripe, bl, p, -EIO);
+			/* RAID set degraded. */
+			else if (write)
+				bio_list_endio(stripe, bl, p, 0);
+		} else {
+			BUG_ON(!RSDegraded(rs) && ChunkDirty(chunk));
+			bio_list_endio(stripe, bl, p, 0);
+		}
+	}
+}
+
+/* Fail all ios hanging off all bio lists of a stripe. */
+static void stripe_fail_io(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned p = rs->set.raid_devs;
+
+	while (p--) {
+		struct stripe_chunk *chunk = CHUNK(stripe, p);
+		int i = ARRAY_SIZE(chunk->bl);
+
+		/* Fail all bios on all bio lists of the stripe. */
+		while (i--) {
+			struct bio_list *bl = chunk->bl + i;
+
+			if (!bio_list_empty(bl))
+				bio_list_endio(stripe, bl, p, -EIO);
+		}
+	}
+
+	/* Put stripe on LRU list. */
+	BUG_ON(stripe_io_ref(stripe));
+	BUG_ON(stripe_ref(stripe));
+}
+
+/* Unlock all required chunks. */
+static void stripe_chunks_unlock(struct stripe *stripe)
+{
+	unsigned p = RS(stripe->sc)->set.raid_devs;
+	struct stripe_chunk *chunk;
+
+	while (p--) {
+		chunk = CHUNK(stripe, p);
+
+		if (TestClearChunkUnlock(chunk))
+			ClearChunkLocked(chunk);
+	}
+}
+
+/*
+ * Queue reads and writes to a stripe by hanging
+ * their bios off the stripesets read/write lists.
+ */
+static int stripe_queue_bio(struct raid_set *rs, struct bio *bio,
+			    struct bio_list *reject)
+{
+	struct raid_address addr;
+	struct stripe *stripe;
+
+	stripe = stripe_find(rs, raid_address(rs, bio->bi_sector, &addr));
+	if (stripe) {
+		int r = 0, rw = bio_data_dir(bio);
+
+		/* Distinguish reads and writes. */
+		bio_list_add(BL(stripe, addr.di, rw), bio);
+	
+		if (rw == READ)
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_BIOS_ADDED_READ);
+		else {
+			/* Inrement pending write count on region. */
+			dm_rh_inc(rs->recover.rh, stripe->region);
+			r = 1;
+
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_BIOS_ADDED_WRITE);
+		}
+
+		/*
+		 * Put on io (flush) list in case of
+		 * initial bio queued to chunk.
+		 */
+		if (chunk_get(CHUNK(stripe, addr.di)) == 1)
+			stripe_flush_add(stripe);
+
+		return r;
+	}
+
+	/* Got no stripe from cache or failed to lock it -> reject bio. */
+	bio_list_add(reject, bio);
+	atomic_inc(rs->stats + S_IOS_POST); /* REMOVEME: statistics. */
+	return 0;
+}
+
+/*
+ * Handle all stripes by handing them to the daemon, because we can't
+ * map their chunk pages to copy the data in interrupt context.
+ *
+ * We don't want to handle them here either, while interrupts are disabled.
+ */
+
+/* Read/write endio function for dm-io (interrupt context). */
+static void endio(unsigned long error, void *context)
+{
+	struct stripe_chunk *chunk = context;
+
+	if (unlikely(error)) {
+		chunk_set(chunk, ERROR);
+		/* REMOVEME: statistics. */
+		atomic_inc(RS(chunk->stripe->sc)->stats + S_STRIPE_ERROR);
+	} else
+		chunk_set(chunk, CLEAN);
+
+	/*
+	 * For recovery stripes, I need to reset locked locked
+	 * here, because those aren't processed in do_endios().
+	 */
+	if (unlikely(StripeRecover(chunk->stripe)))
+		ClearChunkLocked(chunk);
+	else
+		SetChunkUnlock(chunk);
+
+	/* Indirectly puts stripe on cache's endio list via stripe_io_put(). */
+	stripe_put_references(chunk->stripe);
+}
+
+/* Read/Write a chunk asynchronously. */
+static void stripe_chunk_rw(struct stripe *stripe, unsigned p)
+{
+	struct stripe_cache *sc = stripe->sc;
+	struct raid_set *rs = RS(sc);
+	struct dm_mem_cache_object *obj = stripe->obj + p;
+	struct page_list *pl = obj->pl;
+	struct stripe_chunk *chunk = CHUNK(stripe, p);
+	struct raid_dev *dev = rs->dev + p;
+	struct dm_io_region io = {
+		.bdev = dev->dev->bdev,
+		.sector = stripe->key,
+		.count = stripe->io.size,
+	};
+	struct dm_io_request control = {
+		.bi_rw = ChunkDirty(chunk) ? WRITE : READ,
+		.mem = {
+			.type = DM_IO_PAGE_LIST,
+			.ptr.pl = pl,
+			.offset = 0,
+		},
+		.notify = {
+			.fn = endio,
+			.context = chunk,
+		},
+		.client = StripeRecover(stripe) ? rs->recover.dm_io_client :
+						  sc->dm_io_client,
+	};
+
+	BUG_ON(ChunkLocked(chunk));
+	BUG_ON(!ChunkUptodate(chunk) && ChunkDirty(chunk));
+	BUG_ON(ChunkUptodate(chunk) && !ChunkDirty(chunk));
+
+	/*
+	 * Don't rw past end of device, which can happen, because
+	 * typically sectors_per_dev isn't divisible by io_size.
+	 */
+	if (unlikely(io.sector + io.count > rs->set.sectors_per_dev))
+		io.count = rs->set.sectors_per_dev - io.sector;
+
+	BUG_ON(!io.count);
+	io.sector += dev->start;	/* Add <offset>. */
+	if (RSRecover(rs))
+		recover_io_count(stripe);	/* Recovery io accounting. */
+
+	/* REMOVEME: statistics. */
+	atomic_inc(rs->stats + (ChunkDirty(chunk) ? S_DM_IO_WRITE :
+						    S_DM_IO_READ));
+	SetChunkLocked(chunk);
+	SetDevIoQueued(dev);
+	BUG_ON(dm_io(&control, 1, &io, NULL));
+}
+
+/*
+ * Write dirty or read not uptodate page lists of a stripe.
+ */
+static int stripe_chunks_rw(struct stripe *stripe)
+{
+	int r;
+	struct raid_set *rs = RS(stripe->sc);
+
+	/*
+	 * Increment the pending count on the stripe
+	 * first, so that we don't race in endio().
+	 *
+	 * An inc (IO) is needed for any chunk unless !ChunkIo(chunk):
+	 *
+	 * o not uptodate
+	 * o dirtied by writes merged
+	 * o dirtied by parity calculations
+	 */
+	r = for_each_io_dev(stripe, stripe_get_references);
+	if (r) {
+		/* Io needed: chunks are either not uptodate or dirty. */
+		int max;	/* REMOVEME: */
+		struct stripe_cache *sc = &rs->sc;
+
+		/* Submit actual io. */
+		for_each_io_dev(stripe, stripe_chunk_rw);
+
+		/* REMOVEME: statistics */
+		max = sc_active(sc);
+		if (atomic_read(&sc->active_stripes_max) < max)
+			atomic_set(&sc->active_stripes_max, max);
+
+		atomic_inc(rs->stats + S_FLUSHS);
+		/* END REMOVEME: statistics */
+	}
+
+	return r;
+}
+
+/* Merge in all writes hence dirtying respective chunks. */
+static void stripe_merge_writes(struct stripe *stripe)
+{
+	unsigned p = RS(stripe->sc)->set.raid_devs;
+
+	while (p--) {
+		struct stripe_chunk *chunk = CHUNK(stripe, p);
+		struct bio_list *write = BL_CHUNK(chunk, WRITE_QUEUED);
+	
+		if (!bio_list_empty(write)) {
+			struct bio *bio;
+			struct page_list *pl = stripe->obj[p].pl;
+
+			/*
+			 * We can play with the lists without holding a lock,
+			 * because it is just us accessing them anyway.
+			 */
+			bio_list_for_each(bio, write)
+				bio_copy_page_list(WRITE, stripe, pl, bio);
+
+			bio_list_merge(BL_CHUNK(chunk, WRITE_MERGED), write);
+			bio_list_init(write);
+			chunk_set(chunk, DIRTY);
+		}
+	}
+}
+
+/* Queue all writes to get merged. */
+static int stripe_queue_writes(struct stripe *stripe)
+{
+	int r = 0;
+	unsigned p = RS(stripe->sc)->set.raid_devs;
+
+	while (p--) {
+		struct stripe_chunk *chunk = CHUNK(stripe, p);
+		struct bio_list *write = BL_CHUNK(chunk, WRITE);
+
+		if (!bio_list_empty(write)) {
+			bio_list_merge(BL_CHUNK(chunk, WRITE_QUEUED), write);
+			bio_list_init(write);
+SetChunkIo(chunk);
+			r = 1;
+		}
+	}
+
+	return r;
+}
+
+
+/* Check, if a chunk gets completely overwritten. */
+static int stripe_check_chunk_overwrite(struct stripe *stripe, unsigned p)
+{
+	unsigned sectors = 0;
+	struct bio *bio;
+	struct bio_list *bl = BL(stripe, p, WRITE_QUEUED);
+
+	bio_list_for_each(bio, bl)
+		sectors += bio_sectors(bio);
+
+	BUG_ON(sectors > RS(stripe->sc)->set.io_size);
+	return sectors == RS(stripe->sc)->set.io_size;
+}
+
+/*
+ * Avoid io on broken/reconstructed drive in order to
+ * reconstruct date on endio.
+ *
+ * (*1*) We set StripeReconstruct() in here, so that _do_endios()
+ *	 will trigger a reconstruct call before resetting it.
+ */
+static int stripe_chunk_set_io_flags(struct stripe *stripe, int pr)
+{
+	struct stripe_chunk *chunk = CHUNK(stripe, pr);
+
+	/*
+	 * Allow io on all chunks but the indexed one,
+	 * because we're either degraded or prohibit it
+	 * on the one for later reconstruction.
+	 */
+	/* Includes ClearChunkIo(), ClearChunkUptodate(). */
+	stripe_chunk_invalidate(chunk);
+	stripe->idx.recover = pr;
+	SetStripeReconstruct(stripe);
+
+	/* REMOVEME: statistics. */
+	atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO);
+	return -EPERM;
+}
+
+/* Chunk locked/uptodate and device failed tests. */
+static struct stripe_chunk *
+stripe_chunk_check(struct stripe *stripe, unsigned p, unsigned *chunks_uptodate)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	struct stripe_chunk *chunk = CHUNK(stripe, p);
+
+	/* Can't access active chunks. */
+	if (ChunkLocked(chunk)) {
+		/* REMOVEME: statistics. */
+		atomic_inc(rs->stats + S_CHUNK_LOCKED);
+		return NULL;
+	}
+
+	/* Can't access broken devive. */
+	if (ChunkError(chunk) || DevFailed(rs->dev + p))
+		return NULL;
+
+	/* Can access uptodate chunks. */
+	if (ChunkUptodate(chunk)) {
+		(*chunks_uptodate)++;
+		return NULL;
+	}
+
+	return chunk;
+}
+
+/*
+ * Degraded/reconstruction mode.
+ *
+ * Check stripe state to figure which chunks don't need IO.
+ *
+ * Returns 0 for fully operational, -EPERM for degraded/resynchronizing.
+ */
+static int stripe_check_reconstruct(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+
+	if (RSDead(rs)) {
+		ClearStripeReconstruct(stripe);
+		ClearStripeReconstructed(stripe);
+		stripe_allow_io(stripe);
+		return 0;
+	}
+
+	/* Avoid further reconstruction setting, when already set. */
+	if (StripeReconstruct(stripe)) {
+		/* REMOVEME: statistics. */
+		atomic_inc(rs->stats + S_RECONSTRUCT_SET);
+		return -EBUSY;
+	}
+
+	/* Initially allow io on all chunks. */
+	stripe_allow_io(stripe);
+
+	/* Return if stripe is already reconstructed. */
+	if (StripeReconstructed(stripe)) {
+		atomic_inc(rs->stats + S_RECONSTRUCTED);
+		return 0;
+	}
+
+	/*
+	 * Degraded/reconstruction mode (device failed) ->
+	 * avoid io on the failed device.
+	 */
+	if (unlikely(RSDegraded(rs))) {
+		/* REMOVEME: statistics. */
+		atomic_inc(rs->stats + S_DEGRADED);
+		/* Allow IO on all devices but the dead one. */
+		BUG_ON(rs->set.ei < 0);
+		return stripe_chunk_set_io_flags(stripe, rs->set.ei);
+	} else {
+		int sync, pi = dev_for_parity(stripe, &sync);
+
+		/*
+		 * Reconstruction mode (ie. a particular (replaced) device or
+		 * some (rotating) parity chunk is being resynchronized) ->
+		 *   o make sure all needed chunks are read in
+		 *   o writes are allowed to go through
+		 */
+		if (!sync) {
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_NOSYNC);
+			/* Allow IO on all devs but the one to reconstruct. */
+			return stripe_chunk_set_io_flags(stripe, pi);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Check, if stripe is ready to merge writes.
+ * I.e. if all chunks present to allow to merge bios.
+ *
+ * We prohibit io on:
+ *
+ * o chunks without bios
+ * o chunks which get completely written over
+ */
+static int stripe_merge_possible(struct stripe *stripe, int nosync)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned chunks_overwrite = 0, chunks_prohibited = 0,
+		 chunks_uptodate = 0, p = rs->set.raid_devs;
+
+	/* Walk all chunks. */
+	while (p--) {
+		struct stripe_chunk *chunk;
+
+		/* Prohibit io on broken devices. */
+		if (DevFailed(rs->dev + p)) {
+			chunk = CHUNK(stripe, p);
+			goto prohibit_io;
+		}
+
+		/* We can't optimize any further if no chunk. */
+		chunk = stripe_chunk_check(stripe, p, &chunks_uptodate);
+		if (!chunk || nosync)
+			continue;
+
+		/*
+		 * We have a chunk, which is not uptodate.
+		 *
+		 * If this is not parity and we don't have
+		 * reads queued, we can optimize further.
+		 */
+		if (p != stripe->idx.parity &&
+		    bio_list_empty(BL_CHUNK(chunk, READ)) &&
+		    bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED))) {
+			if (bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED)))
+				goto prohibit_io;
+			else if (RSCheckOverwrite(rs) &&
+				 stripe_check_chunk_overwrite(stripe, p))
+				/* Completely overwritten chunk. */
+				chunks_overwrite++;
+		}
+
+		/* Allow io for chunks with bios and overwritten ones. */
+		SetChunkIo(chunk);
+		continue;
+
+prohibit_io:
+		/* No io for broken devices or for chunks w/o bios. */
+		ClearChunkIo(chunk);
+		chunks_prohibited++;
+		/* REMOVEME: statistics. */
+		atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO);
+	}
+
+	/* All data chunks will get written over. */
+	if (chunks_overwrite == rs->set.data_devs)
+		atomic_inc(rs->stats + S_OVERWRITE); /* REMOVEME: statistics.*/
+	else if (chunks_uptodate + chunks_prohibited < rs->set.raid_devs) {
+		/* We don't have enough chunks to merge. */
+		atomic_inc(rs->stats + S_CANT_MERGE); /* REMOVEME: statistics.*/
+		return -EPERM;
+	}
+
+	/*
+	 * If we have all chunks up to date or overwrite them, we
+	 * just zero the parity chunk and let stripe_rw() recreate it.
+	 */
+	if (chunks_uptodate == rs->set.raid_devs ||
+	    chunks_overwrite == rs->set.data_devs) {
+		stripe_zero_chunk(stripe, stripe->idx.parity);
+		BUG_ON(StripeReconstruct(stripe));
+		SetStripeReconstruct(stripe);	/* Enforce xor in caller. */
+	} else {
+		/*
+		 * With less chunks, we xor parity out.
+		 *
+		 * (*4*) We rely on !StripeReconstruct() in chunk_must_xor(),
+		 *	 so that only chunks with queued or merged writes 
+		 *	 are being xored.
+		 */
+		parity_xor(stripe);
+	}
+
+	/*
+	 * We do have enough chunks to merge.
+	 * All chunks are uptodate or get written over.
+	 */
+	atomic_inc(rs->stats + S_CAN_MERGE); /* REMOVEME: statistics. */
+	return 0;
+}
+
+/*
+ * Avoid reading chunks in case we're fully operational.
+ *
+ * We prohibit io on any chunks without bios but the parity chunk.
+ */
+static void stripe_avoid_reads(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	unsigned dummy = 0, p = rs->set.raid_devs;
+
+	/* Walk all chunks. */
+	while (p--) {
+		struct stripe_chunk *chunk =
+			stripe_chunk_check(stripe, p, &dummy);
+
+		if (!chunk)
+			continue;
+
+		/* If parity or any bios pending -> allow io. */
+		if (chunk_ref(chunk) || p == stripe->idx.parity)
+			SetChunkIo(chunk);
+		else {
+			ClearChunkIo(chunk);
+			/* REMOVEME: statistics. */
+			atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO);
+		}
+	}
+}
+
+/*
+ * Read/write a stripe.
+ *
+ * All stripe read/write activity goes through this function
+ * unless recovery, which has to call stripe_chunk_rw() directly.
+ *
+ * Make sure we don't try already merged stripes in order
+ * to avoid data corruption.
+ *
+ * Check the state of the RAID set and if degraded (or
+ * resynchronizing for reads), read in all other chunks but
+ * the one on the dead/resynchronizing device in order to be
+ * able to reconstruct the missing one in _do_endios().
+ *
+ * Can be called on active stripes in order
+ * to dispatch new io on inactive chunks.
+ *
+ * States to cover:
+ *   o stripe to read and/or write
+ *   o stripe with error to reconstruct
+ */
+static void stripe_rw(struct stripe *stripe)
+{
+	int nosync, r;
+	struct raid_set *rs = RS(stripe->sc);
+
+	/*
+ 	 * Check, if a chunk needs to be reconstructed
+ 	 * because of a degraded set or a region out of sync.
+ 	 */
+	nosync = stripe_check_reconstruct(stripe);
+	switch (nosync) {
+	case -EBUSY:
+		return; /* Wait for stripe reconstruction to finish. */
+	case -EPERM:
+		goto io;
+	}
+
+	/*
+	 * If we don't have merged writes pending, we can schedule
+	 * queued writes to be merged next without corrupting data.
+	 */
+	if (!StripeMerged(stripe)) {
+		r = stripe_queue_writes(stripe);
+		if (r)
+			/* Writes got queued -> flag RBW. */
+			SetStripeRBW(stripe);
+	}
+
+	/*
+	 * Merge all writes hanging off uptodate/overwritten
+	 * chunks of the stripe.
+	 */
+	if (StripeRBW(stripe)) {
+		r = stripe_merge_possible(stripe, nosync);
+		if (!r) { /* Merge possible. */
+			struct stripe_chunk *chunk;
+
+			/*
+			 * I rely on valid parity in order
+			 * to xor a fraction of chunks out
+			 * of parity and back in.
+			 */
+			stripe_merge_writes(stripe);	/* Merge writes in. */
+			parity_xor(stripe);		/* Update parity. */
+			ClearStripeReconstruct(stripe);	/* Reset xor enforce. */
+			SetStripeMerged(stripe);	/* Writes merged. */
+			ClearStripeRBW(stripe);		/* Disable RBW. */
+
+			/*
+			 * REMOVEME: sanity check on parity chunk
+			 * 	     states after writes got merged.
+			 */
+			chunk = CHUNK(stripe, stripe->idx.parity);
+			BUG_ON(ChunkLocked(chunk));
+			BUG_ON(!ChunkUptodate(chunk));
+			BUG_ON(!ChunkDirty(chunk));
+			BUG_ON(!ChunkIo(chunk));
+		}
+	} else if (!nosync && !StripeMerged(stripe))
+		/* Read avoidance if not degraded/resynchronizing/merged. */
+		stripe_avoid_reads(stripe);
+
+io:
+	/* Now submit any reads/writes for non-uptodate or dirty chunks. */
+	r = stripe_chunks_rw(stripe);
+	if (!r) {
+		/*
+		 * No io submitted because of chunk io
+		 * prohibited or locked chunks/failed devices
+		 * -> push to end io list for processing.
+		 */
+		stripe_endio_push(stripe);
+		atomic_inc(rs->stats + S_NO_RW); /* REMOVEME: statistics. */
+	}
+}
+
+/*
+ * Recovery functions
+ */
+/* Read a stripe off a raid set for recovery. */
+static int stripe_recover_read(struct stripe *stripe, int pi)
+{
+	BUG_ON(stripe_io_ref(stripe));
+
+	/* Invalidate all chunks so that they get read in. */
+	stripe_chunks_invalidate(stripe);
+	stripe_allow_io(stripe); /* Allow io on all recovery chunks. */
+
+	/*
+	 * If we are reconstructing a perticular device, we can avoid
+ 	 * reading the respective chunk in, because we're going to
+	 * reconstruct it anyway.
+	 *
+	 * We can't do that for resynchronization of rotating parity,
+	 * because the recovery stripe chunk size is typically larger
+	 * than the sets chunk size.
+	 */
+	if (pi > -1)
+		ClearChunkIo(CHUNK(stripe, pi));
+
+	return stripe_chunks_rw(stripe);
+}
+
+/* Write a stripe to a raid set for recovery. */
+static int stripe_recover_write(struct stripe *stripe, int pi)
+{
+	BUG_ON(stripe_io_ref(stripe));
+
+	/*
+	 * If this is a reconstruct of a particular device, then
+	 * reconstruct the respective chunk, else create parity chunk.
+	 */
+	if (pi > -1) {
+		stripe_zero_chunk(stripe, pi);
+		common_xor(stripe, stripe->io.size, 0, pi);
+		chunk_set(CHUNK(stripe, pi), DIRTY);
+	} else
+		parity_xor(stripe);
+
+	return stripe_chunks_rw(stripe);
+}
+
+/* Read/write a recovery stripe. */
+static int stripe_recover_rw(struct stripe *stripe)
+{
+	int r = 0, sync = 0;
+
+	/* Read/write flip-flop. */
+	if (TestClearStripeRBW(stripe)) {
+		SetStripeMerged(stripe);
+		stripe->key = stripe->recover->pos;
+		r = stripe_recover_read(stripe, dev_for_parity(stripe, &sync));
+		BUG_ON(!r);
+	} else if (TestClearStripeMerged(stripe)) {
+		r = stripe_recover_write(stripe, dev_for_parity(stripe, &sync));
+		BUG_ON(!r);
+	}
+
+	BUG_ON(sync);
+	return r;
+}
+
+/* Recover bandwidth available ?. */
+static int recover_bandwidth(struct raid_set *rs)
+{
+	int r, work;
+
+	/* On reset or when bios delayed -> allow recovery. */
+	r = recover_io_reset(rs);
+	if (r || RSBandwidth(rs))
+		goto out;
+
+	work = atomic_read(rs->recover.io_count + IO_WORK);
+	if (work) {
+		/* Pay attention to larger recover stripe size. */
+		int recover = atomic_read(rs->recover.io_count + IO_RECOVER) *
+					  rs->recover.io_size / rs->set.io_size;
+
+		/*
+		 * Don't use more than given bandwidth
+		 * of the work io for recovery.
+		 */
+		if (recover > work / rs->recover.bandwidth_work) {
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_NO_BANDWIDTH);
+			return 0;
+		}
+	}
+
+out:
+	atomic_inc(rs->stats + S_BANDWIDTH);	/* REMOVEME: statistics. */
+	return 1;
+}
+
+/* Try to get a region to recover. */
+static int stripe_recover_get_region(struct stripe *stripe)
+{
+	struct raid_set *rs = RS(stripe->sc);
+	struct recover *rec = &rs->recover;
+	struct recover_addr *addr = stripe->recover;
+	struct dm_dirty_log *dl = rec->dl;
+	struct dm_rh_client *rh = rec->rh;
+
+	BUG_ON(!dl);
+	BUG_ON(!rh);
+
+	/* Return, that we have region first to finish it during suspension. */
+	if (addr->reg)
+		return 1;
+
+	if (RSSuspend(rs))
+		return -EPERM;
+
+	if (dl->type->get_sync_count(dl) >= rec->nr_regions)
+		return -ENOENT;
+
+	/* If we don't have enough bandwidth, we don't proceed recovering. */
+	if (!recover_bandwidth(rs))
+		return -EAGAIN;
+
+	/* Start quiescing a region. */
+	dm_rh_recovery_prepare(rh);
+	addr->reg = dm_rh_recovery_start(rh);
+	if (!addr->reg)
+		return -EAGAIN;
+
+	addr->pos = dm_rh_region_to_sector(rh, dm_rh_get_region_key(addr->reg));
+	addr->end = addr->pos + dm_rh_get_region_size(rh);
+
+	/*
+	 * Take one global io reference out for the
+	 * whole region, which is going to be released
+	 * when the region is completely done with.
+	 */
+	io_get(rs);
+	return 0;
+}
+
+/* Update region hash state. */
+enum recover_type { REC_FAILURE = 0, REC_SUCCESS = 1 };
+static void recover_rh_update(struct stripe *stripe, enum recover_type success)
+{
+	struct recover_addr *addr = stripe->recover;
+	struct raid_set *rs = RS(stripe->sc);
+	struct recover *rec = &rs->recover;
+
+	if (!addr->reg) {
+		DMERR("%s- Called w/o region", __func__);
+		return;
+	}
+
+	dm_rh_recovery_end(addr->reg, success);
+	if (success)
+		rec->nr_regions_recovered++;
+
+	addr->reg = NULL;
+
+	/*
+	 * Completely done with this region ->
+	 * release the 1st io reference.
+	 */
+	io_put(rs);
+}
+
+/* Set start of recovery state. */
+static void set_start_recovery(struct raid_set *rs)
+{
+	/* Initialize recovery. */
+	rs->recover.start_jiffies = jiffies;
+	rs->recover.end_jiffies = 0;
+}
+
+/* Set end of recovery state. */
+static void set_end_recovery(struct raid_set *rs)
+{
+	ClearRSRecover(rs);
+	rs->set.dev_to_init = -1;
+
+	/* Check for jiffies overrun. */
+	rs->recover.end_jiffies = jiffies;
+	if (rs->recover.end_jiffies < rs->recover.start_jiffies)
+		rs->recover.end_jiffies = ~0;
+}
+
+/* Handle recovery on one recovery stripe. */
+static int _do_recovery(struct stripe *stripe)
+{
+	int r;
+	struct raid_set *rs = RS(stripe->sc);
+	struct recover_addr *addr = stripe->recover;
+
+	/* If recovery is active -> return. */
+	if (stripe_io_ref(stripe))
+		return 1;
+
+	/* IO error is fatal for recovery -> stop it. */
+	if (unlikely(StripeError(stripe)))
+		goto err;
+
+	/* Recovery end required. */
+	if (!RSRecover(rs))
+		goto err;
+
+	/* Get a region to recover. */
+	r = stripe_recover_get_region(stripe);
+	switch (r) {
+	case 0:	/* Got a new region: flag initial read before write. */
+		SetStripeRBW(stripe);
+	case 1:	/* Have a region in the works. */
+		break;
+	case -EAGAIN:
+		/* No bandwidth/quiesced region yet, try later. */
+		if (!io_ref(rs))
+			wake_do_raid_delayed(rs, HZ / 4);
+	case -EPERM:
+		/* Suspend. */
+		return 1;
+	case -ENOENT:	/* No more regions to recover. */
+		schedule_work(&rs->io.ws_do_table_event);
+		return 0;
+	default:
+		BUG();
+	}
+
+	/* Read/write a recover stripe. */
+	r = stripe_recover_rw(stripe);
+	if (r)
+		/* IO initiated. */
+		return 1;
+
+	/* Read and write finished-> update recovery position within region. */
+	addr->pos += stripe->io.size;
+
+	/* If we're at end of region, update region hash. */
+	if (addr->pos >= addr->end ||
+	    addr->pos >= rs->set.sectors_per_dev)
+		recover_rh_update(stripe, REC_SUCCESS);
+	else
+		/* Prepare to read next region segment. */
+		SetStripeRBW(stripe);
+
+	/* Schedule myself for another round... */
+	wake_do_raid(rs);
+	return 1;
+
+err:
+	/* FIXME: rather try recovering other regions on error? */
+	rs_check_degrade(stripe);
+	recover_rh_update(stripe, REC_FAILURE);
+
+	/* Check state of partially recovered array. */
+	if (RSDegraded(rs) && !RSDead(rs) &&
+	    rs->set.dev_to_init != -1 &&
+	    rs->set.ei != rs->set.dev_to_init)
+		/* Broken drive != drive to recover -> FATAL. */
+		SetRSDead(rs);
+
+	if (StripeError(stripe)) {
+		char buf[BDEVNAME_SIZE];
+
+		DMERR("stopping recovery due to "
+		      "ERROR on /dev/%s, stripe at offset %llu",
+		      bdevname(rs->dev[rs->set.ei].dev->bdev, buf),
+		      (unsigned long long) stripe->key);
+
+	}
+
+	/* Make sure, that all quiesced regions get released. */
+	while (addr->reg) {
+		dm_rh_recovery_end(addr->reg, -EIO);
+		addr->reg = dm_rh_recovery_start(rs->recover.rh);
+	}
+
+	return 0;
+}
+
+/* Called by main io daemon to recover regions. */
+static void do_recovery(struct raid_set *rs)
+{
+	if (RSRecover(rs)) {
+		int r = 0;
+		struct stripe *stripe;
+
+		list_for_each_entry(stripe, &rs->recover.stripes,
+				    lists[LIST_RECOVER])
+			r += _do_recovery(stripe);
+
+		if (!r) {
+			set_end_recovery(rs);
+			stripe_recover_free(rs);
+		}
+	}
+}
+
+/*
+ * END recovery functions
+ */
+
+/* End io process all stripes handed in by endio() callback. */
+static void _do_endios(struct raid_set *rs, struct stripe *stripe,
+		       struct list_head *flush_list)
+{
+	/* First unlock all required chunks. */
+	stripe_chunks_unlock(stripe);
+
+	/*
+	 * If an io error on a stripe occured, degrade the RAID set
+	 * and try to endio as many bios as possible. If any bios can't
+	 * be endio processed, requeue the stripe (stripe_ref() != 0).
+	 */
+	if (TestClearStripeError(stripe)) {
+		/*
+		 * FIXME: if read, rewrite the failed chunk after reconstruction
+		 *        in order to trigger disk bad sector relocation.
+		 */
+		rs_check_degrade(stripe); /* Resets ChunkError(). */
+		ClearStripeReconstruct(stripe);
+		ClearStripeReconstructed(stripe);
+	}
+
+	/* Got to reconstruct a missing chunk. */
+	if (StripeReconstruct(stripe)) {
+		/*
+		 * (*2*) We use StripeReconstruct() to allow for
+		 *	 all chunks to be xored into the reconstructed
+		 *	 one (see chunk_must_xor()).
+		 */
+		stripe_reconstruct(stripe);
+
+		/*
+		 * (*3*) Now we reset StripeReconstruct() and flag
+		 * 	 StripeReconstructed() to show to stripe_rw(),
+		 * 	 that we have reconstructed a missing chunk.
+		 */
+		ClearStripeReconstruct(stripe);
+		SetStripeReconstructed(stripe);
+
+		/* FIXME: reschedule to be written in case of read. */
+		// if (!StripeRBW(stripe)) {
+		// 	chunk_set(CHUNK(stripe, pr), DIRTY);
+		// 	stripe_chunks_rw(stripe);
+		// }
+	}
+
+	/*
+	 * Now that we eventually got a complete stripe, we
+	 * can process the rest of the end ios on reads.
+	 */
+	stripe_endio(READ, stripe);
+
+	/* End io all merged writes. */
+	if (TestClearStripeMerged(stripe))
+		stripe_endio(WRITE_MERGED, stripe);
+
+	/* If RAID set is dead -> fail any ios to dead drives. */
+	if (RSDead(rs)) {
+		DMERR_LIMIT("RAID set dead: failing ios to dead devices");
+		stripe_fail_io(stripe);
+	}
+
+	/*
+	 * We have stripe references still,
+	 * beacuse of read befeore writes or IO errors ->
+	 * got to put on flush list for processing.
+	 */
+	if (stripe_ref(stripe)) {
+		BUG_ON(!list_empty(stripe->lists + LIST_LRU));
+		list_add_tail(stripe->lists + LIST_FLUSH, flush_list);
+		atomic_inc(rs->stats + S_REQUEUE); /* REMOVEME: statistics. */
+	} else
+		stripe_lru_add(stripe);
+}
+
+/* Pop any endio stripes off of the endio list and belabour them. */
+static void do_endios(struct raid_set *rs)
+{
+	struct stripe_cache *sc = &rs->sc;
+	struct stripe *stripe;
+	/* IO flush list for sorted requeued stripes. */
+	struct list_head flush_list;
+
+	INIT_LIST_HEAD(&flush_list);
+
+	while ((stripe = stripe_endio_pop(sc))) {
+		/* Avoid endio on stripes with newly io'ed chunks. */
+		if (!stripe_io_ref(stripe))
+			_do_endios(rs, stripe, &flush_list);
+	}
+
+	/*
+	 * Insert any requeued stripes in the proper
+	 * order at the beginning of the io (flush) list.
+	 */
+	list_splice(&flush_list, sc->lists + LIST_FLUSH);
+}
+
+/* Flush any stripes on the io list. */
+static void do_flush(struct raid_set *rs)
+{
+	struct stripe *stripe;
+
+	while ((stripe = stripe_io_pop(&rs->sc)))
+		stripe_rw(stripe); /* Read/write stripe. */
+}
+
+/* Stripe cache resizing. */
+static void do_sc_resize(struct raid_set *rs)
+{
+	unsigned set = atomic_read(&rs->sc.stripes_to_set);
+
+	if (set) {
+		unsigned cur = atomic_read(&rs->sc.stripes);
+		int r = (set > cur) ? sc_grow(&rs->sc, set - cur, SC_GROW) :
+				      sc_shrink(&rs->sc, cur - set);
+
+		/* Flag end of resizeing if ok. */
+		if (!r)
+			atomic_set(&rs->sc.stripes_to_set, 0);
+	}
+}
+
+/*
+ * Process all ios
+ *
+ * We do different things with the io depending
+ * on the state of the region that it is in:
+ *
+ * o reads: hang off stripe cache or postpone if full
+ *
+ * o writes:
+ *
+ *  CLEAN/DIRTY/NOSYNC:	increment pending and hang io off stripe's stripe set.
+ *			In case stripe cache is full or busy, postpone the io.
+ *
+ *  RECOVERING:		delay the io until recovery of the region completes.
+ *
+ */
+static void do_ios(struct raid_set *rs, struct bio_list *ios)
+{
+	int r;
+	unsigned flush = 0, delay = 0;
+	sector_t sector;
+	struct dm_rh_client *rh = rs->recover.rh;
+	struct bio *bio;
+	struct bio_list reject;
+
+	bio_list_init(&reject);
+
+	/*
+	 * Classify each io:
+	 *    o delay writes to recovering regions (let reads go through)
+	 *    o queue io to all other regions
+	 */
+	while ((bio = bio_list_pop(ios))) {
+		/*
+		 * In case we get a barrier bio, push it back onto
+		 * the input queue unless all work queues are empty
+		 * and the stripe cache is inactive.
+		 */
+		if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
+			/* REMOVEME: statistics. */
+			atomic_inc(rs->stats + S_BARRIER);
+			if (delay ||
+			    !list_empty(rs->sc.lists + LIST_FLUSH) ||
+			    !bio_list_empty(&reject) ||
+			    sc_active(&rs->sc)) {
+				bio_list_push(ios, bio);
+				break;
+			}
+		}
+
+		/* Check for recovering regions. */
+		sector = _sector(rs, bio);
+		r = region_state(rs, sector, DM_RH_RECOVERING);
+		if (unlikely(r && bio_data_dir(bio) == WRITE)) {
+			delay++;
+			/* Wait writing to recovering regions. */
+			dm_rh_delay_by_region(rh, bio,
+					      dm_rh_sector_to_region(rh,
+								     sector));
+			/* REMOVEME: statistics.*/
+			atomic_inc(rs->stats + S_DELAYED_BIOS);
+			atomic_inc(rs->stats + S_SUM_DELAYED_BIOS);
+
+			/* Force bandwidth tests in recovery. */
+			SetRSBandwidth(rs);
+		} else {
+			/*
+			 * Process ios to non-recovering regions by queueing
+			 * them to stripes (does dm_rh_inc()) for writes).
+			 */
+			flush += stripe_queue_bio(rs, bio, &reject);
+		}
+	}
+
+	if (flush) {
+		/* FIXME: better error handling. */
+		r = dm_rh_flush(rh); /* Writes got queued -> flush dirty log. */
+		if (r)
+			DMERR_LIMIT("dirty log flush");
+	}
+
+	/* Merge any rejected bios back to the head of the input list. */
+	bio_list_merge_head(ios, &reject);
+}
+
+/* Unplug: let any queued io role on the sets devices. */
+static void do_unplug(struct raid_set *rs)
+{
+	struct raid_dev *dev = rs->dev + rs->set.raid_devs;
+
+	while (dev-- > rs->dev) {
+		/* Only call any device unplug function, if io got queued. */
+		if (TestClearDevIoQueued(dev))
+			blk_unplug(bdev_get_queue(dev->dev->bdev));
+	}
+}
+
+/* Send an event in case we're getting too busy. */
+static void do_busy_event(struct raid_set *rs)
+{
+	if (sc_busy(rs)) {
+		if (!TestSetRSScBusy(rs))
+			schedule_work(&rs->io.ws_do_table_event);
+	}
+
+	ClearRSScBusy(rs);
+}
+
+/* Throw an event. */
+static void do_table_event(struct work_struct *ws)
+{
+	struct raid_set *rs = container_of(ws, struct raid_set,
+					   io.ws_do_table_event);
+	dm_table_event(rs->ti->table);
+}
+
+
+/*-----------------------------------------------------------------
+ * RAID daemon
+ *---------------------------------------------------------------*/
+/*
+ * o belabour all end ios
+ * o update the region hash states
+ * o optionally shrink the stripe cache
+ * o optionally do recovery
+ * o unplug any component raid devices with queued bios
+ * o grab the input queue
+ * o work an all requeued or new ios and perform stripe cache flushs
+ * o unplug any component raid devices with queued bios
+ * o check, if the stripe cache gets too busy and throw an event if so
+ */
+static void do_raid(struct work_struct *ws)
+{
+	struct raid_set *rs = container_of(ws, struct raid_set,
+					   io.dws_do_raid.work);
+	struct bio_list *ios = &rs->io.work, *ios_in = &rs->io.in;
+
+	/*
+	 * We always need to end io, so that ios can get errored in
+	 * case the set failed and the region counters get decremented
+	 * before we update region hash states and go any further.
+	 */
+	do_endios(rs);
+	dm_rh_update_states(rs->recover.rh, 1);
+
+	/*
+	 * Now that we've end io'd, which may have put stripes on the LRU list
+	 * to allow for shrinking, we resize the stripe cache if requested.
+	 */
+	do_sc_resize(rs);
+
+	/* Try to recover regions. */
+	do_recovery(rs);
+	do_unplug(rs);		/* Unplug the sets device queues. */
+
+	/* Quickly grab all new ios queued and add them to the work list. */
+	mutex_lock(&rs->io.in_lock);
+	bio_list_merge(ios, ios_in);
+	bio_list_init(ios_in);
+	mutex_unlock(&rs->io.in_lock);
+
+	if (!bio_list_empty(ios))
+		do_ios(rs, ios); /* Got ios to work into the cache. */
+
+	do_flush(rs);		/* Flush any stripes on io list. */
+	do_unplug(rs);		/* Unplug the sets device queues. */
+	do_busy_event(rs);	/* Check if we got too busy. */
+}
+
+/*
+ * Callback for region hash to dispatch
+ * delayed bios queued to recovered regions
+ * (gets called via dm_rh_update_states()).
+ */
+static void dispatch_delayed_bios(void *context, struct bio_list *bl)
+{
+	struct raid_set *rs = context;
+	struct bio *bio;
+
+	/* REMOVEME: statistics; decrement pending delayed bios counter. */
+	bio_list_for_each(bio, bl)
+		atomic_dec(rs->stats + S_DELAYED_BIOS);
+
+	/* Merge region hash private list to work list. */
+	bio_list_merge_head(&rs->io.work, bl);
+	bio_list_init(bl);
+	ClearRSBandwidth(rs);
+}
+
+/*************************************************************
+ * Constructor helpers
+ *************************************************************/
+/* Calculate MB/sec. */
+static unsigned mbpers(struct raid_set *rs, unsigned speed)
+{
+	return to_bytes(speed * rs->set.data_devs *
+			rs->recover.io_size * HZ >> 10) >> 10;
+}
+
+/*
+ * Discover fastest xor algorithm and # of chunks combination.
+ */
+/* Calculate speed for algorithm and # of chunks. */
+static unsigned xor_speed(struct stripe *stripe)
+{
+	unsigned r = 0;
+	unsigned long j;
+
+	/* Wait for next tick. */
+	for (j = jiffies; j == jiffies; )
+		;
+
+	/* Do xors for a full tick. */
+	for (j = jiffies; j == jiffies; ) {
+		mb();
+		common_xor(stripe, stripe->io.size, 0, 0);
+		mb();
+		r++;
+	}
+
+	return r;
+}
+
+/* Optimize xor algorithm for this RAID set. */
+static unsigned xor_optimize(struct raid_set *rs)
+{
+	unsigned chunks_max = 2, p = rs->set.raid_devs, speed_max = 0;
+	struct xor_func *f = ARRAY_END(xor_funcs), *f_max = NULL;
+	struct stripe *stripe;
+
+	BUG_ON(list_empty(&rs->recover.stripes));
+	stripe = list_first_entry(&rs->recover.stripes, struct stripe,
+				  lists[LIST_RECOVER]);
+
+	/* Must set uptodate so that xor() will belabour chunks. */
+	while (p--)
+		SetChunkUptodate(CHUNK(stripe, p));
+
+	/* Try all xor functions. */
+	while (f-- > xor_funcs) {
+		unsigned speed;
+
+		/* Set actual xor function for common_xor(). */
+		rs->xor.f = f;
+		rs->xor.chunks = (f->f == xor_blocks_wrapper ?
+				  (MAX_XOR_BLOCKS + 1) : XOR_CHUNKS_MAX) + 1;
+
+		while (rs->xor.chunks-- > 2) {
+			speed = xor_speed(stripe);
+			if (speed > speed_max) {
+				speed_max = speed;
+				chunks_max = rs->xor.chunks;
+				f_max = f;
+			}
+		}
+	}
+
+	/* Memorize optimum parameters. */
+	rs->xor.f = f_max;
+	rs->xor.chunks = chunks_max;
+	return speed_max;
+}
+
+/*
+ * Allocate a RAID context (a RAID set)
+ */
+/* Structure for variable RAID parameters. */
+struct variable_parms {
+	int bandwidth;
+	int bandwidth_parm;
+	int chunk_size;
+	int chunk_size_parm;
+	int io_size;
+	int io_size_parm;
+	int stripes;
+	int stripes_parm;
+	int recover_io_size;
+	int recover_io_size_parm;
+	int raid_parms;
+	int recovery;
+	int recovery_stripes;
+	int recovery_stripes_parm;
+};
+
+static struct raid_set *
+context_alloc(struct raid_type *raid_type, struct variable_parms *p,
+	      unsigned raid_devs, sector_t sectors_per_dev,
+	      struct dm_target *ti, unsigned dl_parms, char **argv)
+{
+	int r;
+	size_t len;
+	sector_t region_size, ti_len;
+	struct raid_set *rs = NULL;
+	struct dm_dirty_log *dl;
+	struct recover *rec;
+
+	/*
+	 * Create the dirty log
+	 *
+	 * We need to change length for the dirty log constructor,
+	 * because we want an amount of regions for all stripes derived
+	 * from the single device size, so that we can keep region
+	 * size = 2^^n independant of the number of devices
+	 */
+	ti_len = ti->len;
+	ti->len = sectors_per_dev;
+	dl = dm_dirty_log_create(argv[0], ti, dl_parms, argv + 2);
+	ti->len = ti_len;
+	if (!dl)
+		goto bad_dirty_log;
+
+	/* Chunk size *must* be smaller than region size. */
+	region_size = dl->type->get_region_size(dl);
+	if (p->chunk_size > region_size)
+		goto bad_chunk_size;
+
+	/* Recover io size *must* be smaller than region size as well. */
+	if (p->recover_io_size > region_size)
+		goto bad_recover_io_size;
+
+	/* Size and allocate the RAID set structure. */
+	len = sizeof(*rs->data) + sizeof(*rs->dev);
+	if (dm_array_too_big(sizeof(*rs), len, raid_devs))
+		goto bad_array;
+
+	len = sizeof(*rs) + raid_devs * len;
+	rs = kzalloc(len, GFP_KERNEL);
+	if (!rs)
+		goto bad_alloc;
+
+	rec = &rs->recover;
+	atomic_set(&rs->io.in_process, 0);
+	atomic_set(&rs->io.in_process_max, 0);
+	rec->io_size = p->recover_io_size;
+
+	/* Pointer to data array. */
+	rs->data = (unsigned long **)
+		   ((void *) rs->dev + raid_devs * sizeof(*rs->dev));
+	rec->dl = dl;
+	rs->set.raid_devs = raid_devs;
+	rs->set.data_devs = raid_devs - raid_type->parity_devs;
+	rs->set.raid_type = raid_type;
+
+	rs->set.raid_parms = p->raid_parms;
+	rs->set.chunk_size_parm = p->chunk_size_parm;
+	rs->set.io_size_parm = p->io_size_parm;
+	rs->sc.stripes_parm = p->stripes_parm;
+	rec->io_size_parm = p->recover_io_size_parm;
+	rec->bandwidth_parm = p->bandwidth_parm;
+	rec->recovery = p->recovery;
+	rec->recovery_stripes = p->recovery_stripes;
+
+	/*
+	 * Set chunk and io size and respective shifts
+	 * (used to avoid divisions)
+	 */
+	rs->set.chunk_size = p->chunk_size;
+	rs->set.chunk_shift = ffs(p->chunk_size) - 1;
+
+	rs->set.io_size = p->io_size;
+	rs->set.io_mask = p->io_size - 1;
+	/* Mask to adjust address key in case io_size != chunk_size. */
+	rs->set.io_inv_mask = (p->chunk_size - 1) & ~rs->set.io_mask;
+
+	rs->set.sectors_per_dev = sectors_per_dev;
+
+	rs->set.ei = -1;	/* Indicate no failed device. */
+	atomic_set(&rs->set.failed_devs, 0);
+
+	rs->ti = ti;
+
+	atomic_set(rec->io_count + IO_WORK, 0);
+	atomic_set(rec->io_count + IO_RECOVER, 0);
+
+	/* Initialize io lock and queues. */
+	mutex_init(&rs->io.in_lock);
+	bio_list_init(&rs->io.in);
+	bio_list_init(&rs->io.work);
+
+	init_waitqueue_head(&rs->io.suspendq);	/* Suspend waiters (dm-io). */
+
+	rec->nr_regions = dm_sector_div_up(sectors_per_dev, region_size);
+	rec->rh = dm_region_hash_create(rs, dispatch_delayed_bios,
+			wake_dummy, wake_do_raid, 0, p->recovery_stripes,
+			dl, region_size, rec->nr_regions);
+	if (IS_ERR(rec->rh))
+		goto bad_rh;
+
+	/* Initialize stripe cache. */
+	r = sc_init(rs, p->stripes);
+	if (r)
+		goto bad_sc;
+
+	/* REMOVEME: statistics. */
+	stats_reset(rs);
+	ClearRSDevelStats(rs);	/* Disnable development status. */
+	return rs;
+
+bad_dirty_log:
+	TI_ERR_RET("Error creating dirty log", ERR_PTR(-ENOMEM));
+
+bad_chunk_size:
+	dm_dirty_log_destroy(dl);
+	TI_ERR_RET("Chunk size larger than region size", ERR_PTR(-EINVAL));
+
+bad_recover_io_size:
+	dm_dirty_log_destroy(dl);
+	TI_ERR_RET("Recover stripe io size larger than region size",
+			ERR_PTR(-EINVAL));
+
+bad_array:
+	dm_dirty_log_destroy(dl);
+	TI_ERR_RET("Arry too big", ERR_PTR(-EINVAL));
+
+bad_alloc:
+	dm_dirty_log_destroy(dl);
+	TI_ERR_RET("Cannot allocate raid context", ERR_PTR(-ENOMEM));
+
+bad_rh:
+	dm_dirty_log_destroy(dl);
+	ti->error = DM_MSG_PREFIX "Error creating dirty region hash";
+	goto free_rs;
+
+bad_sc:
+	dm_region_hash_destroy(rec->rh); /* Destroys dirty log too. */
+	sc_exit(&rs->sc);
+	ti->error = DM_MSG_PREFIX "Error creating stripe cache";
+free_rs:
+	kfree(rs);
+	return ERR_PTR(-ENOMEM);
+}
+
+/* Free a RAID context (a RAID set). */
+static void context_free(struct raid_set *rs, unsigned p)
+{
+	while (p--)
+		dm_put_device(rs->ti, rs->dev[p].dev);
+
+	sc_exit(&rs->sc);
+	dm_region_hash_destroy(rs->recover.rh); /* Destroys dirty log too. */
+	kfree(rs);
+}
+
+/* Create work queue and initialize delayed work. */
+static int rs_workqueue_init(struct raid_set *rs)
+{
+	struct dm_target *ti = rs->ti;
+
+	rs->io.wq = create_singlethread_workqueue(DAEMON);
+	if (!rs->io.wq)
+		TI_ERR_RET("failed to create " DAEMON, -ENOMEM);
+
+	INIT_DELAYED_WORK(&rs->io.dws_do_raid, do_raid);
+	INIT_WORK(&rs->io.ws_do_table_event, do_table_event);
+	return 0;
+}
+
+/* Return pointer to raid_type structure for raid name. */
+static struct raid_type *get_raid_type(char *name)
+{
+	struct raid_type *r = ARRAY_END(raid_types);
+
+	while (r-- > raid_types) {
+		if (!strcmp(r->name, name))
+			return r;
+	}
+
+	return NULL;
+}
+
+/* FIXME: factor out to dm core. */
+static int multiple(sector_t a, sector_t b, sector_t *n)
+{
+	sector_t r = a;
+
+	sector_div(r, b);
+	*n = r;
+	return a == r * b;
+}
+
+/* Log RAID set information to kernel log. */
+static void rs_log(struct raid_set *rs, unsigned speed)
+{
+	unsigned p;
+	char buf[BDEVNAME_SIZE];
+
+	for (p = 0; p < rs->set.raid_devs; p++)
+		DMINFO("/dev/%s is raid disk %u%s",
+				bdevname(rs->dev[p].dev->bdev, buf), p,
+				(p == rs->set.pi) ? " (parity)" : "");
+
+	DMINFO("%d/%d/%d sectors chunk/io/recovery size, %u stripes\n"
+	       "algorithm \"%s\", %u chunks with %uMB/s\n"
+	       "%s set with net %u/%u devices",
+	       rs->set.chunk_size, rs->set.io_size, rs->recover.io_size,
+	       atomic_read(&rs->sc.stripes),
+	       rs->xor.f->name, rs->xor.chunks, mbpers(rs, speed),
+	       rs->set.raid_type->descr, rs->set.data_devs, rs->set.raid_devs);
+}
+
+/* Get all devices and offsets. */
+static int dev_parms(struct raid_set *rs, char **argv, int *p)
+{
+	struct dm_target *ti = rs->ti;
+
+	for (*p = 0; *p < rs->set.raid_devs; (*p)++, argv += 2) {
+		int r;
+		unsigned long long tmp;
+		struct raid_dev *dev = rs->dev + *p;
+
+		/* Get offset and device. */
+		if (sscanf(argv[1], "%llu", &tmp) != 1 ||
+		    tmp > rs->set.sectors_per_dev)
+			TI_ERR("Invalid RAID device offset parameter");
+
+		dev->start = tmp;
+		r = dm_get_device(ti, *argv, dev->start,
+				  rs->set.sectors_per_dev,
+				  dm_table_get_mode(ti->table), &dev->dev);
+		if (r)
+			TI_ERR_RET("RAID device lookup failure", r);
+
+		r = raid_dev_lookup(rs, dev);
+		if (r != -ENODEV && r < *p) {
+			(*p)++;	/* Ensure dm_put_device() on actual device. */
+			TI_ERR_RET("Duplicate RAID device", -ENXIO);
+		}
+	}
+
+	return 0;
+}
+
+/* Set recovery bandwidth. */
+static void
+recover_set_bandwidth(struct raid_set *rs, unsigned bandwidth)
+{
+	rs->recover.bandwidth = bandwidth;
+	rs->recover.bandwidth_work = 100 / bandwidth;
+}
+
+/* Handle variable number of RAID parameters. */
+static int get_raid_variable_parms(struct dm_target *ti, char **argv, 
+				   struct variable_parms *vp)
+{
+	int p, value;
+	struct {
+		int action; /* -1: skip, 0: no pwer2 check, 1: power2 check */
+		char *errmsg;
+		int min, max;
+		int *var, *var2, *var3;
+	} argctr[] = {
+		{ 1,
+		  "Invalid chunk size; must be -1 or 2^^n and <= 16384",
+ 		  IO_SIZE_MIN, CHUNK_SIZE_MAX,
+		  &vp->chunk_size_parm, &vp->chunk_size, &vp->io_size },
+		{ 0,
+		  "Invalid number of stripes: must be -1 or >= 8 and <= 16384",
+		  STRIPES_MIN, STRIPES_MAX,
+		  &vp->stripes_parm, &vp->stripes, NULL },
+		{ 1,
+		  "Invalid io size; must -1 or >= 8, 2^^n and less equal "
+		  "min(BIO_MAX_SECTORS/2, chunk size)",
+		  IO_SIZE_MIN, 0, /* Needs to be updated in loop below. */
+		  &vp->io_size_parm, &vp->io_size, NULL },
+		{ 1,
+		  "Invalid recovery io size; must be -1 or "
+		  "2^^n and less equal BIO_MAX_SECTORS/2",
+		  RECOVER_IO_SIZE_MIN, BIO_MAX_SECTORS / 2,
+		  &vp->recover_io_size_parm, &vp->recover_io_size, NULL },
+		{ 0,
+		  "Invalid recovery bandwidth percentage; "
+		  "must be -1 or > 0 and <= 100",
+		  BANDWIDTH_MIN, BANDWIDTH_MAX,
+		  &vp->bandwidth_parm, &vp->bandwidth, NULL },
+		/* Handle sync argument seperately in loop. */
+		{ -1,
+		  "Invalid recovery switch; must be \"sync\" or \"nosync\"" },
+		{ 0,
+		  "Invalid number of recovery stripes;"
+		  "must be -1, > 0 and <= 16384",
+		  RECOVERY_STRIPES_MIN, RECOVERY_STRIPES_MAX,
+		  &vp->recovery_stripes_parm, &vp->recovery_stripes, NULL },
+	}, *varp;
+
+	/* Fetch # of variable raid parameters. */
+	if (sscanf(*(argv++), "%d", &vp->raid_parms) != 1 ||
+	    !range_ok(vp->raid_parms, 0, 7))
+		TI_ERR("Bad variable raid parameters number");
+
+	/* Preset variable RAID parameters. */
+	vp->chunk_size = CHUNK_SIZE_DEFAULT;
+	vp->io_size = IO_SIZE_DEFAULT;
+	vp->stripes = STRIPES_DEFAULT;
+	vp->recover_io_size = RECOVER_IO_SIZE_DEFAULT;
+	vp->bandwidth = BANDWIDTH_DEFAULT;
+	vp->recovery = 1;
+	vp->recovery_stripes = RECOVERY_STRIPES_DEFAULT;
+
+	/* Walk the array of argument constraints for all given ones. */
+	for (p = 0, varp = argctr; p < vp->raid_parms; p++, varp++) {
+	     	BUG_ON(varp >= ARRAY_END(argctr));
+
+		/* Special case for "[no]sync" string argument. */
+		if (varp->action < 0) {
+			if (!strcmp(*argv, "sync"))
+				;
+			else if (!strcmp(*argv, "nosync"))
+				vp->recovery = 0;
+			else
+				TI_ERR(varp->errmsg);
+
+			argv++;
+			continue;
+		}
+
+		/*
+		 * Special case for io_size depending
+		 * on previously set chunk size.
+		 */
+		if (p == 2)
+			varp->max = min(BIO_MAX_SECTORS / 2, vp->chunk_size);
+
+		if (sscanf(*(argv++), "%d", &value) != 1 ||
+		    (value != -1 &&
+		     ((varp->action && !POWER_OF_2(value)) ||
+		      !range_ok(value, varp->min, varp->max))))
+			TI_ERR(varp->errmsg);
+
+		*varp->var = value;
+		if (value != -1) {
+			if (varp->var2)
+				*varp->var2 = value;
+			if (varp->var3)
+				*varp->var3 = value;
+		}
+	}
+
+	return 0;
+}
+
+/* Parse optional locking parameters. */
+static int get_raid_locking_parms(struct dm_target *ti, char **argv,
+				  int *locking_parms,
+				  struct dm_raid45_locking_type **locking_type)
+{
+	if (!strnicmp(argv[0], "locking", strlen(argv[0]))) {
+		char *lckstr = argv[1];
+		size_t lcksz = strlen(lckstr);
+
+		if (!strnicmp(lckstr, "none", lcksz)) {
+			*locking_type = &locking_none;
+			*locking_parms = 2;
+		} else if (!strnicmp(lckstr, "cluster", lcksz)) {
+			DMERR("locking type \"%s\" not yet implemented",
+			      lckstr);
+			return -EINVAL;
+		} else {
+			DMERR("unknown locking type \"%s\"", lckstr);
+			return -EINVAL;
+		}
+	}
+
+	*locking_parms = 0;
+	*locking_type = &locking_none;
+	return 0;
+}
+
+/* Set backing device read ahead properties of RAID set. */
+static void rs_set_read_ahead(struct raid_set *rs,
+			      unsigned sectors, unsigned stripes)
+{
+	unsigned ra_pages = dm_div_up(sectors, SECTORS_PER_PAGE);
+	struct mapped_device *md = dm_table_get_md(rs->ti->table);
+	struct backing_dev_info *bdi = &dm_disk(md)->queue->backing_dev_info;
+
+	/* Set read-ahead for the RAID set and the component devices. */
+	if (ra_pages) {
+		unsigned p = rs->set.raid_devs;
+
+		bdi->ra_pages = stripes * ra_pages * rs->set.data_devs;
+
+		while (p--) {
+			struct request_queue *q =
+				bdev_get_queue(rs->dev[p].dev->bdev);
+
+			q->backing_dev_info.ra_pages = ra_pages;
+		}
+	}
+
+	dm_put(md);
+}
+
+/* Set congested function. */
+static void rs_set_congested_fn(struct raid_set *rs)
+{
+	struct mapped_device *md = dm_table_get_md(rs->ti->table);
+	struct backing_dev_info *bdi = &dm_disk(md)->queue->backing_dev_info;
+
+	/* Set congested function and data. */
+	bdi->congested_fn = rs_congested;
+	bdi->congested_data = rs;
+	dm_put(md);
+}
+
+/*
+ * Construct a RAID4/5 mapping:
+ *
+ * log_type #log_params <log_params> \
+ * raid_type [#parity_dev] #raid_variable_params <raid_params> \
+ * [locking "none"/"cluster"]
+ * #raid_devs #dev_to_initialize [<dev_path> <offset>]{3,}
+ *
+ * log_type = "core"/"disk",
+ * #log_params = 1-3 (1-2 for core dirty log type, 3 for disk dirty log only)
+ * log_params = [dirty_log_path] region_size [[no]sync])
+ *
+ * raid_type = "raid4", "raid5_la", "raid5_ra", "raid5_ls", "raid5_rs"
+ *
+ * #parity_dev = N if raid_type = "raid4"
+ * o N = -1: pick default = last device
+ * o N >= 0 and < #raid_devs: parity device index
+ *
+ * #raid_variable_params = 0-7; raid_params (-1 = default):
+ *   [chunk_size [#stripes [io_size [recover_io_size \
+ *    [%recovery_bandwidth [recovery_switch [#recovery_stripes]]]]]]]
+ *   o chunk_size (unit to calculate drive addresses; must be 2^^n, > 8
+ *     and <= CHUNK_SIZE_MAX)
+ *   o #stripes is number of stripes allocated to stripe cache
+ *     (must be > 1 and < STRIPES_MAX)
+ *   o io_size (io unit size per device in sectors; must be 2^^n and > 8)
+ *   o recover_io_size (io unit size per device for recovery in sectors;
+ must be 2^^n, > SECTORS_PER_PAGE and <= region_size)
+ *   o %recovery_bandwith is the maximum amount spend for recovery during
+ *     application io (1-100%)
+ *   o recovery switch = [sync|nosync]
+ *   o #recovery_stripes is the number of recovery stripes used for
+ *     parallel recovery of the RAID set
+ * If raid_variable_params = 0, defaults will be used.
+ * Any raid_variable_param can be set to -1 to apply a default
+ *
+ * #raid_devs = N (N >= 3)
+ *
+ * #dev_to_initialize = N
+ * -1: initialize parity on all devices
+ * >= 0 and < #raid_devs: initialize raid_path; used to force reconstruction
+ * of a failed devices content after replacement
+ *
+ * <dev_path> = device_path (eg, /dev/sdd1)
+ * <offset>   = begin at offset on <dev_path>
+ *
+ */
+#define	MIN_PARMS	13
+static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int dev_to_init, dl_parms, i, locking_parms,
+	    parity_parm, pi = -1, r, raid_devs;
+	unsigned speed;
+	sector_t tmp, sectors_per_dev;
+	struct dm_raid45_locking_type *locking;
+	struct raid_set *rs;
+	struct raid_type *raid_type;
+	struct variable_parms parms;
+
+	/* Ensure minimum number of parameters. */
+	if (argc < MIN_PARMS)
+		TI_ERR("Not enough parameters");
+
+	/* Fetch # of dirty log parameters. */
+	if (sscanf(argv[1], "%d", &dl_parms) != 1 ||
+	    !range_ok(dl_parms, 1, 4711)) /* ;-) */
+		TI_ERR("Bad dirty log parameters number");
+
+	/* Check raid_type. */
+	raid_type = get_raid_type(argv[dl_parms + 2]);
+	if (!raid_type)
+		TI_ERR("Bad raid type");
+
+	/* In case of RAID4, parity drive is selectable. */
+	parity_parm = !!(raid_type->level == raid4);
+
+	/* Handle variable number of RAID parameters. */
+	r = get_raid_variable_parms(ti, argv + dl_parms + parity_parm + 3,
+				    &parms);
+	if (r)
+		return r;
+
+	/* Handle any locking parameters. */
+	r = get_raid_locking_parms(ti,
+				   argv + dl_parms + parity_parm +
+				   parms.raid_parms + 4,
+				   &locking_parms, &locking);
+	if (r)
+		return r;
+
+	/* # of raid devices. */
+	i = dl_parms + parity_parm + parms.raid_parms + locking_parms + 4;
+	if (sscanf(argv[i], "%d", &raid_devs) != 1 ||
+	    raid_devs < raid_type->minimal_devs)
+		TI_ERR("Invalid number of raid devices");
+
+	/* In case of RAID4, check parity drive index is in limits. */
+	if (raid_type->level == raid4) {
+		/* Fetch index of parity device. */
+		if (sscanf(argv[dl_parms + 3], "%d", &pi) != 1 ||
+		    (pi != -1 && !range_ok(pi, 0, raid_devs - 1)))
+			TI_ERR("Invalid RAID4 parity device index");
+	}
+
+	/*
+	 * Index of device to initialize starts at 0
+	 *
+	 * o -1 -> don't initialize a selected device;
+	 *         initialize parity conforming to algorithm
+	 * o 0..raid_devs-1 -> initialize respective device
+	 *   (used for reconstruction of a replaced device)
+	 */
+	if (sscanf(argv[dl_parms + parity_parm + parms.raid_parms +
+		   locking_parms + 5], "%d", &dev_to_init) != 1 ||
+	    !range_ok(dev_to_init, -1, raid_devs - 1))
+		TI_ERR("Invalid number for raid device to initialize");
+
+	/* Check # of raid device arguments. */
+	if (argc - dl_parms - parity_parm - parms.raid_parms - 6 !=
+	    2 * raid_devs)
+		TI_ERR("Wrong number of raid device/offset arguments");
+
+	/*
+	 * Check that the table length is devisable
+	 * w/o rest by (raid_devs - parity_devs)
+	 */
+	if (!multiple(ti->len, raid_devs - raid_type->parity_devs,
+		      &sectors_per_dev))
+		TI_ERR("Target length not divisible by number of data devices");
+
+	/*
+	 * Check that the device size is
+	 * devisable w/o rest by chunk size
+	 */
+	if (!multiple(sectors_per_dev, parms.chunk_size, &tmp))
+		TI_ERR("Device length not divisible by chunk_size");
+
+	/****************************************************************
+	 * Now that we checked the constructor arguments ->
+	 * let's allocate the RAID set
+	 ****************************************************************/
+	rs = context_alloc(raid_type, &parms, raid_devs, sectors_per_dev,
+			   ti, dl_parms, argv);
+	if (IS_ERR(rs))
+		return PTR_ERR(rs);
+
+
+	rs->set.dev_to_init = rs->set.dev_to_init_parm = dev_to_init;
+	rs->set.pi = rs->set.pi_parm = pi;
+
+	/* Set RAID4 parity drive index. */
+	if (raid_type->level == raid4)
+		rs->set.pi = (pi == -1) ? rs->set.data_devs : pi;
+
+	recover_set_bandwidth(rs, parms.bandwidth);
+
+	/* Use locking type to lock stripe access. */
+	rs->locking = locking;
+
+	/* Get the device/offset tupels. */
+	argv += dl_parms + 6 + parity_parm + parms.raid_parms;
+	r = dev_parms(rs, argv, &i);
+	if (r)
+		goto err;
+
+	/* Set backing device information (eg. read ahead). */
+	rs_set_read_ahead(rs, 2 * rs->set.chunk_size, 4 /* stripes */);
+	rs_set_congested_fn(rs); /* Set congested function. */
+	SetRSCheckOverwrite(rs); /* Allow chunk overwrite checks. */
+	speed = xor_optimize(rs); /* Select best xor algorithm. */
+
+	/* Set for recovery of any nosync regions. */
+	if (parms.recovery)
+		SetRSRecover(rs);
+	else {
+		/*
+		 * Need to free recovery stripe(s) here in case
+		 * of nosync, because xor_optimize uses one.
+		 */
+		set_start_recovery(rs);
+		set_end_recovery(rs);
+		stripe_recover_free(rs);
+	}
+
+	/*
+	 * Make sure that dm core only hands maximum io size
+	 * length down and pays attention to io boundaries.
+	 */
+	ti->split_io = rs->set.io_size;
+	ti->private = rs;
+
+	/* Initialize work queue to handle this RAID set's io. */
+	r = rs_workqueue_init(rs);
+	if (r)
+		goto err;
+
+	rs_log(rs, speed); /* Log information about RAID set. */
+	return 0;
+
+err:
+	context_free(rs, i);
+	return r;
+}
+
+/*
+ * Destruct a raid mapping
+ */
+static void raid_dtr(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+
+	destroy_workqueue(rs->io.wq);
+	context_free(rs, rs->set.raid_devs);
+}
+
+/* Raid mapping function. */
+static int raid_map(struct dm_target *ti, struct bio *bio,
+		    union map_info *map_context)
+{
+	/* I don't want to waste stripe cache capacity. */
+	if (bio_rw(bio) == READA)
+		return -EIO;
+	else {
+		struct raid_set *rs = ti->private;
+
+		/*
+		 * Get io reference to be waiting for to drop
+		 * to zero on device suspension/destruction.
+		 */
+		io_get(rs);
+		bio->bi_sector -= ti->begin;	/* Remap sector. */
+
+		/* Queue io to RAID set. */
+		mutex_lock(&rs->io.in_lock);
+		bio_list_add(&rs->io.in, bio);
+		mutex_unlock(&rs->io.in_lock);
+
+		/* Wake daemon to process input list. */
+		wake_do_raid(rs);
+
+		/* REMOVEME: statistics. */
+		atomic_inc(rs->stats + (bio_data_dir(bio) == READ ?
+				        S_BIOS_READ : S_BIOS_WRITE));
+		return DM_MAPIO_SUBMITTED;	/* Handle later. */
+	}
+}
+
+/* Device suspend. */
+static void raid_presuspend(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+	struct dm_dirty_log *dl = rs->recover.dl;
+
+	SetRSSuspend(rs);
+
+	if (RSRecover(rs))
+		dm_rh_stop_recovery(rs->recover.rh);
+
+	cancel_delayed_work(&rs->io.dws_do_raid);
+	flush_workqueue(rs->io.wq);
+	wait_ios(rs);	/* Wait for completion of all ios being processed. */
+
+	if (dl->type->presuspend && dl->type->presuspend(dl))
+		/* FIXME: need better error handling. */
+		DMWARN("log presuspend failed");
+}
+
+static void raid_postsuspend(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+	struct dm_dirty_log *dl = rs->recover.dl;
+
+	if (dl->type->postsuspend && dl->type->postsuspend(dl))
+		/* FIXME: need better error handling. */
+		DMWARN("log postsuspend failed");
+
+}
+
+/* Device resume. */
+static void raid_resume(struct dm_target *ti)
+{
+	struct raid_set *rs = ti->private;
+	struct recover *rec = &rs->recover;
+	struct dm_dirty_log *dl = rec->dl;
+
+	if (dl->type->resume && dl->type->resume(dl))
+		/* Resume dirty log. */
+		/* FIXME: need better error handling. */
+		DMWARN("log resume failed");
+
+	rec->nr_regions_to_recover =
+		rec->nr_regions - dl->type->get_sync_count(dl);
+
+	/* Restart any unfinished recovery. */
+	if (RSRecover(rs)) {
+		set_start_recovery(rs);
+		dm_rh_start_recovery(rec->rh);
+	}
+
+	ClearRSSuspend(rs);
+	wake_do_raid(rs);
+}
+
+/* Return stripe cache size. */
+static unsigned sc_size(struct raid_set *rs)
+{
+	return to_sector(atomic_read(&rs->sc.stripes) *
+			 (sizeof(struct stripe) +
+			  (sizeof(struct stripe_chunk) +
+			   (sizeof(struct page_list) +
+			    to_bytes(rs->set.io_size) *
+			    rs->set.raid_devs)) +
+			  (rs->recover.end_jiffies ?
+			   0 : rs->recover.recovery_stripes *
+			   to_bytes(rs->set.raid_devs * rs->recover.io_size))));
+}
+
+/* REMOVEME: status output for development. */
+static void raid_devel_stats(struct dm_target *ti, char *result,
+			     unsigned *size, unsigned maxlen)
+{
+	unsigned sz = *size;
+	unsigned long j;
+	char buf[BDEVNAME_SIZE], *p;
+	struct stats_map *sm;
+	struct raid_set *rs = ti->private;
+	struct recover *rec = &rs->recover;
+	struct timespec ts;
+
+	DMEMIT("%s %s %u\n", version, rs->xor.f->name, rs->xor.chunks);
+	DMEMIT("act_ios=%d ", io_ref(rs));
+	DMEMIT("act_ios_max=%d\n", atomic_read(&rs->io.in_process_max));
+	DMEMIT("act_stripes=%d ", sc_active(&rs->sc));
+	DMEMIT("act_stripes_max=%d\n",
+	       atomic_read(&rs->sc.active_stripes_max));
+
+	for (sm = stats_map; sm < ARRAY_END(stats_map); sm++)
+		DMEMIT("%s%d", sm->str, atomic_read(rs->stats + sm->type));
+
+	DMEMIT(" checkovr=%s\n", RSCheckOverwrite(rs) ? "on" : "off");
+	DMEMIT("sc=%u/%u/%u/%u/%u/%u/%u\n", rs->set.chunk_size,
+	       atomic_read(&rs->sc.stripes), rs->set.io_size,
+	       rec->recovery_stripes, rec->io_size, rs->sc.hash.buckets,
+	       sc_size(rs));
+
+	j = (rec->end_jiffies ? rec->end_jiffies : jiffies) -
+	    rec->start_jiffies;
+	jiffies_to_timespec(j, &ts);
+	sprintf(buf, "%ld.%ld", ts.tv_sec, ts.tv_nsec);
+	p = strchr(buf, '.');
+	p[3] = 0;
+
+	DMEMIT("rg=%llu/%llu/%llu/%u %s\n",
+	       (unsigned long long) rec->nr_regions_recovered,
+	       (unsigned long long) rec->nr_regions_to_recover,
+	       (unsigned long long) rec->nr_regions, rec->bandwidth, buf);
+
+	*size = sz;
+}
+
+static int raid_status(struct dm_target *ti, status_type_t type,
+		       char *result, unsigned maxlen)
+{
+	unsigned p, sz = 0;
+	char buf[BDEVNAME_SIZE];
+	struct raid_set *rs = ti->private;
+	int raid_parms[] = {
+		rs->set.chunk_size_parm,
+		rs->sc.stripes_parm,
+		rs->set.io_size_parm,
+		rs->recover.io_size_parm,
+		rs->recover.bandwidth_parm,
+		-2,
+		rs->recover.recovery_stripes,
+	};
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		/* REMOVEME: statistics. */
+		if (RSDevelStats(rs))
+			raid_devel_stats(ti, result, &sz, maxlen);
+
+		DMEMIT("%u ", rs->set.raid_devs);
+
+		for (p = 0; p < rs->set.raid_devs; p++)
+			DMEMIT("%s ",
+			       format_dev_t(buf, rs->dev[p].dev->bdev->bd_dev));
+
+		DMEMIT("1 ");
+		for (p = 0; p < rs->set.raid_devs; p++) {
+			DMEMIT("%c", !DevFailed(rs->dev + p) ? 'A' : 'D');
+
+			if (p == rs->set.pi)
+				DMEMIT("p");
+
+			if (rs->set.dev_to_init == p)
+				DMEMIT("i");
+		}
+
+		break;
+	case STATUSTYPE_TABLE:
+		sz = rs->recover.dl->type->status(rs->recover.dl, type,
+						  result, maxlen);
+		DMEMIT("%s %u ", rs->set.raid_type->name,
+		       rs->set.raid_parms);
+
+		for (p = 0; p < rs->set.raid_parms; p++) {
+			if (raid_parms[p] > -2)
+				DMEMIT("%d ", raid_parms[p]);
+			else
+				DMEMIT("%s ", rs->recover.recovery ?
+					      "sync" : "nosync");
+		}
+
+		DMEMIT("%u %d ", rs->set.raid_devs, rs->set.dev_to_init);
+
+		for (p = 0; p < rs->set.raid_devs; p++)
+			DMEMIT("%s %llu ",
+			       format_dev_t(buf, rs->dev[p].dev->bdev->bd_dev),
+			       (unsigned long long) rs->dev[p].start);
+	}
+
+	return 0;
+}
+
+/*
+ * Message interface
+ */
+enum raid_msg_actions {
+	act_bw,			/* Recovery bandwidth switch. */
+	act_dev,		/* Device failure switch. */
+	act_overwrite,		/* Stripe overwrite check. */
+	act_stats,		/* Development statistics switch. */
+	act_sc,			/* Stripe cache switch. */
+
+	act_on,			/* Set entity on. */
+	act_off,		/* Set entity off. */
+	act_reset,		/* Reset entity. */
+
+	act_set = act_on,	/* Set # absolute. */
+	act_grow = act_off,	/* Grow # by an amount. */
+	act_shrink = act_reset,	/* Shrink # by an amount. */
+};
+
+/* Turn a delta into an absolute value. */
+static int _absolute(unsigned long action, int act, int r)
+{
+	/* Make delta absolute. */
+	if (test_bit(act_set, &action))
+		;
+	else if (test_bit(act_grow, &action))
+		r += act;
+	else if (test_bit(act_shrink, &action))
+		r = act - r;
+	else
+		r = -EINVAL;
+
+	return r;
+}
+
+ /* Change recovery io bandwidth. */
+static int bandwidth_change(struct dm_msg *msg, void *context)
+{
+	struct raid_set *rs = context;
+	int act = rs->recover.bandwidth;
+	int bandwidth = DM_MSG_INT_ARG(msg);
+
+	if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) {
+		/* Make delta bandwidth absolute. */
+		bandwidth = _absolute(msg->action, act, bandwidth);
+
+		/* Check range. */
+		if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) {
+			recover_set_bandwidth(rs, bandwidth);
+			return 0;
+		}
+	}
+
+	set_bit(dm_msg_ret_arg, &msg->ret);
+	set_bit(dm_msg_ret_inval, &msg->ret);
+	return -EINVAL;
+}
+
+/* Set/reset development feature flags. */
+static int devel_flags(struct dm_msg *msg, void *context)
+{
+	struct raid_set *rs = context;
+
+	if (test_bit(act_on, &msg->action))
+		return test_and_set_bit(msg->spec->parm,
+					&rs->io.flags) ? -EPERM : 0;
+	else if (test_bit(act_off, &msg->action))
+		return test_and_clear_bit(msg->spec->parm,
+					  &rs->io.flags) ? 0 : -EPERM;
+	else if (test_bit(act_reset, &msg->action)) {
+		if (test_bit(act_stats, &msg->action)) {
+			stats_reset(rs);
+			goto on;
+		} else if (test_bit(act_overwrite, &msg->action)) {
+on:
+			set_bit(msg->spec->parm, &rs->io.flags);
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/* Resize the stripe cache. */
+static int sc_resize(struct dm_msg *msg, void *context)
+{
+	int act, stripes;
+	struct raid_set *rs = context;
+
+	/* Deny permission in case the daemon is still resizing!. */
+	if (atomic_read(&rs->sc.stripes_to_set))
+		return -EPERM;
+
+	stripes = DM_MSG_INT_ARG(msg);
+	if (stripes > 0) {
+		act = atomic_read(&rs->sc.stripes);
+
+		/* Make delta stripes absolute. */
+		stripes = _absolute(msg->action, act, stripes);
+
+		/*
+		 * Check range and that the # of stripes changes.
+		 * We leave the resizing to the wroker.
+		 */
+		if (range_ok(stripes, STRIPES_MIN, STRIPES_MAX) &&
+		    stripes != atomic_read(&rs->sc.stripes)) {
+			atomic_set(&rs->sc.stripes_to_set, stripes);
+			wake_do_raid(rs);
+			return 0;
+		}
+	}
+
+	set_bit(dm_msg_ret_arg, &msg->ret);
+	set_bit(dm_msg_ret_inval, &msg->ret);
+	return -EINVAL;
+}
+
+/* Parse the RAID message action. */
+/*
+ * 'ba[ndwidth] {se[t],g[row],sh[rink]} #'	# e.g 'ba se 50'
+ * "o[verwrite]  {on,of[f],r[eset]}'		# e.g. 'o of'
+ * 'sta[tistics] {on,of[f],r[eset]}'		# e.g. 'stat of'
+ * 'str[ipecache] {se[t],g[row],sh[rink]} #'	# e.g. 'stripe set 1024'
+ *
+ */
+static int raid_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	/* Variables to store the parsed parameters im. */
+	static int i[2];
+	static unsigned long *i_arg[] = {
+		(unsigned long *) i + 0,
+		(unsigned long *) i + 1,
+	};
+
+	/* Declare all message option strings. */
+	static char *str_sgs[] = { "set", "grow", "shrink" };
+	static char *str_oor[] = { "on", "off", "reset" };
+
+	/* Declare all actions. */
+	static unsigned long act_sgs[] = { act_set, act_grow, act_shrink };
+	static unsigned long act_oor[] = { act_on, act_off, act_reset };
+
+	/* Bandwidth option. */
+	static struct dm_message_option bw_opt = { 3, str_sgs, act_sgs };
+	static struct dm_message_argument bw_args = {
+		1, i_arg, { dm_msg_int_t }
+	};
+
+	static struct dm_message_argument null_args = {
+		0, NULL, { dm_msg_int_t }
+	};
+
+	/* Overwrite and statistics option. */
+	static struct dm_message_option ovr_stats_opt = { 3, str_oor, act_oor };
+
+	/* Sripecache option. */
+	static struct dm_message_option stripe_opt = { 3, str_sgs, act_sgs };
+
+	/* Declare messages. */
+	static struct dm_msg_spec specs[] = {
+		{ "bandwidth", act_bw, &bw_opt, &bw_args,
+		  0, bandwidth_change },
+		{ "overwrite", act_overwrite, &ovr_stats_opt, &null_args,
+		  RS_CHECK_OVERWRITE, devel_flags },
+		{ "statistics", act_stats, &ovr_stats_opt, &null_args,
+		  RS_DEVEL_STATS, devel_flags },
+		{ "stripecache", act_sc, &stripe_opt, &bw_args,
+		  0, sc_resize },
+	};
+
+	/* The message for the parser. */
+	struct dm_msg msg = {
+		.num_specs = ARRAY_SIZE(specs),
+		.specs = specs,
+	};
+
+	return dm_message_parse(TARGET, &msg, ti->private, argc, argv);
+}
+/*
+ * END message interface
+ */
+
+static struct target_type raid_target = {
+	.name = "raid45",
+	.version = {1, 0, 0},
+	.module = THIS_MODULE,
+	.ctr = raid_ctr,
+	.dtr = raid_dtr,
+	.map = raid_map,
+	.presuspend = raid_presuspend,
+	.postsuspend = raid_postsuspend,
+	.resume = raid_resume,
+	.status = raid_status,
+	.message = raid_message,
+};
+
+static void init_exit(const char *bad_msg, const char *good_msg, int r)
+{
+	if (r)
+		DMERR("Failed to %sregister target [%d]", bad_msg, r);
+	else
+		DMINFO("%s %s", good_msg, version);
+}
+
+static int __init dm_raid_init(void)
+{
+	int r = dm_register_target(&raid_target);
+
+	init_exit("", "initialized", r);
+	return r;
+}
+
+static void __exit dm_raid_exit(void)
+{
+	dm_unregister_target(&raid_target);
+	init_exit("un", "exit", 0);
+}
+
+/* Module hooks. */
+module_init(dm_raid_init);
+module_exit(dm_raid_exit);
+
+MODULE_DESCRIPTION(DM_NAME " raid4/5 target");
+MODULE_AUTHOR("Heinz Mauelshagen <hjm@redhat.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("dm-raid4");
+MODULE_ALIAS("dm-raid5");
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-memcache.h
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-memcache.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen <Mauelshagen@RedHat.com>
+ *
+ * Device-mapper memory object handling:
+ *
+ * o allocate/free total_pages in a per client page pool.
+ *
+ * o allocate/free memory objects with chunks (1..n) of
+ *   pages_per_chunk pages hanging off.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _DM_MEM_CACHE_H
+#define _DM_MEM_CACHE_H
+
+#define	DM_MEM_CACHE_H_VERSION	"0.1"
+
+#include "dm.h"
+#include <linux/dm-io.h>
+
+static inline struct page_list *pl_elem(struct page_list *pl, unsigned p)
+{
+	while (pl && p--)
+		pl = pl->next;
+
+	return pl;
+}
+
+struct dm_mem_cache_object {
+	struct page_list *pl; /* Dynamically allocated array */
+	void *private;	      /* Caller context reference */
+};
+
+struct dm_mem_cache_client;
+
+/*
+ * Create/destroy dm memory cache client resources.
+ *
+ * On creation, a number of @objects with @chunks of
+ * @pages_per_chunk pages will be allocated.
+ */
+struct dm_mem_cache_client *
+dm_mem_cache_client_create(unsigned objects, unsigned chunks,
+			   unsigned pages_per_chunk);
+void dm_mem_cache_client_destroy(struct dm_mem_cache_client *client);
+
+/*
+ * Grow/shrink a dm memory cache client resources
+ * by @objetcs amount of objects.
+ */
+int dm_mem_cache_grow(struct dm_mem_cache_client *client, unsigned objects);
+int dm_mem_cache_shrink(struct dm_mem_cache_client *client, unsigned objects);
+
+/*
+ * Allocate/free a memory object
+ *
+ * On allocation one object with an amount of chunks and
+ * an amount of pages per chunk will be returned on success.
+ */
+struct dm_mem_cache_object *
+dm_mem_cache_alloc(struct dm_mem_cache_client *client);
+void dm_mem_cache_free(struct dm_mem_cache_client *client,
+		       struct dm_mem_cache_object *object);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-memcache.c
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-memcache.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen <heinzm@redhat.com>
+ *
+ * Device-mapper memory object handling:
+ *
+ * o allocate/free total_pages in a per client page pool.
+ *
+ * o allocate/free memory objects with chunks (1..n) of
+ *   pages_per_chunk pages hanging off.
+ *
+ * This file is released under the GPL.
+ */
+
+#define	DM_MEM_CACHE_VERSION	"0.2"
+
+#include "dm.h"
+#include "dm-memcache.h"
+#include <linux/dm-io.h>
+
+struct dm_mem_cache_client {
+	spinlock_t lock;
+	mempool_t *objs_pool;
+	struct page_list *free_list;
+	unsigned objects;
+	unsigned chunks;
+	unsigned pages_per_chunk;
+	unsigned free_pages;
+	unsigned total_pages;
+};
+
+/*
+ * Free pages and page_list elements of client.
+ */
+static void free_cache_pages(struct page_list *list)
+{
+	while (list) {
+		struct page_list *pl = list;
+
+		list = pl->next;
+		BUG_ON(!pl->page);
+		__free_page(pl->page);
+		kfree(pl);
+	}
+}
+
+/*
+ * Alloc number of pages and page_list elements as required by client.
+ */
+static struct page_list *alloc_cache_pages(unsigned pages)
+{
+	struct page_list *pl, *ret = NULL;
+	struct page *page;
+
+	while (pages--) {
+		page = alloc_page(GFP_NOIO);
+		if (!page)
+			goto err;
+
+		pl = kmalloc(sizeof(*pl), GFP_NOIO);
+		if (!pl) {
+			__free_page(page);
+			goto err;
+		}
+
+		pl->page = page;
+		pl->next = ret;
+		ret = pl;
+	}
+
+	return ret;
+
+err:
+	free_cache_pages(ret);
+	return NULL;
+}
+
+/*
+ * Allocate page_list elements from the pool to chunks of the memory object.
+ */
+static void alloc_chunks(struct dm_mem_cache_client *cl,
+			 struct dm_mem_cache_object *obj)
+{
+	unsigned chunks = cl->chunks;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	local_irq_disable();
+	while (chunks--) {
+		unsigned p = cl->pages_per_chunk;
+
+		obj[chunks].pl = NULL;
+
+		while (p--) {
+			struct page_list *pl;
+
+			/* Take next element from free list */
+			spin_lock(&cl->lock);
+			pl = cl->free_list;
+			BUG_ON(!pl);
+			cl->free_list = pl->next;
+			spin_unlock(&cl->lock);
+
+			pl->next = obj[chunks].pl;
+			obj[chunks].pl = pl;
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Free page_list elements putting them back onto free list
+ */
+static void free_chunks(struct dm_mem_cache_client *cl,
+			struct dm_mem_cache_object *obj)
+{
+	unsigned chunks = cl->chunks;
+	unsigned long flags;
+	struct page_list *next, *pl;
+
+	local_irq_save(flags);
+	local_irq_disable();
+	while (chunks--) {
+		for (pl = obj[chunks].pl; pl; pl = next) {
+			next = pl->next;
+
+			spin_lock(&cl->lock);
+			pl->next = cl->free_list;
+			cl->free_list = pl;
+			cl->free_pages++;
+			spin_unlock(&cl->lock);
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Create/destroy dm memory cache client resources.
+ */
+struct dm_mem_cache_client *
+dm_mem_cache_client_create(unsigned objects, unsigned chunks,
+			   unsigned pages_per_chunk)
+{
+	unsigned total_pages = objects * chunks * pages_per_chunk;
+	struct dm_mem_cache_client *client;
+
+	BUG_ON(!total_pages);
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return ERR_PTR(-ENOMEM);
+
+	client->objs_pool = mempool_create_kmalloc_pool(objects,
+				chunks * sizeof(struct dm_mem_cache_object));
+	if (!client->objs_pool)
+		goto err;
+
+	client->free_list = alloc_cache_pages(total_pages);
+	if (!client->free_list)
+		goto err1;
+
+	spin_lock_init(&client->lock);
+	client->objects = objects;
+	client->chunks = chunks;
+	client->pages_per_chunk = pages_per_chunk;
+	client->free_pages = client->total_pages = total_pages;
+	return client;
+
+err1:
+	mempool_destroy(client->objs_pool);
+err:
+	kfree(client);
+	return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL(dm_mem_cache_client_create);
+
+void dm_mem_cache_client_destroy(struct dm_mem_cache_client *cl)
+{
+	BUG_ON(cl->free_pages != cl->total_pages);
+	free_cache_pages(cl->free_list);
+	mempool_destroy(cl->objs_pool);
+	kfree(cl);
+}
+EXPORT_SYMBOL(dm_mem_cache_client_destroy);
+
+/*
+ * Grow a clients cache by an amount of pages.
+ *
+ * Don't call from interrupt context!
+ */
+int dm_mem_cache_grow(struct dm_mem_cache_client *cl, unsigned objects)
+{
+	unsigned pages = objects * cl->chunks * cl->pages_per_chunk;
+	struct page_list *pl, *last;
+
+	BUG_ON(!pages);
+	pl = alloc_cache_pages(pages);
+	if (!pl)
+		return -ENOMEM;
+
+	last = pl;
+	while (last->next)
+		last = last->next;
+
+	spin_lock_irq(&cl->lock);
+	last->next = cl->free_list;
+	cl->free_list = pl;
+	cl->free_pages += pages;
+	cl->total_pages += pages;
+	cl->objects++;
+	spin_unlock_irq(&cl->lock);
+
+	mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO);
+	return 0;
+}
+EXPORT_SYMBOL(dm_mem_cache_grow);
+
+/* Shrink a clients cache by an amount of pages */
+int dm_mem_cache_shrink(struct dm_mem_cache_client *cl, unsigned objects)
+{
+	int r;
+	unsigned pages = objects * cl->chunks * cl->pages_per_chunk, p = pages;
+	unsigned long flags;
+	struct page_list *last = NULL, *pl, *pos;
+
+	BUG_ON(!pages);
+
+	spin_lock_irqsave(&cl->lock, flags);
+	pl = pos = cl->free_list;
+	while (p-- && pos->next) {
+		last = pos;
+		pos = pos->next;
+	}
+
+	if (++p)
+		r = -ENOMEM;
+	else {
+		r = 0;
+		cl->free_list = pos;
+		cl->free_pages -= pages;
+		cl->total_pages -= pages;
+		cl->objects--;
+		last->next = NULL;
+	}
+	spin_unlock_irqrestore(&cl->lock, flags);
+
+	if (!r) {
+		free_cache_pages(pl);
+		mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO);
+	}
+
+	return r;
+}
+EXPORT_SYMBOL(dm_mem_cache_shrink);
+
+/*
+ * Allocate/free a memory object
+ *
+ * Can be called from interrupt context
+ */
+struct dm_mem_cache_object *dm_mem_cache_alloc(struct dm_mem_cache_client *cl)
+{
+	int r = 0;
+	unsigned pages = cl->chunks * cl->pages_per_chunk;
+	unsigned long flags;
+	struct dm_mem_cache_object *obj;
+
+	obj = mempool_alloc(cl->objs_pool, GFP_NOIO);
+	if (!obj)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock_irqsave(&cl->lock, flags);
+	if (pages > cl->free_pages)
+		r = -ENOMEM;
+	else
+		cl->free_pages -= pages;
+	spin_unlock_irqrestore(&cl->lock, flags);
+
+	if (r) {
+		mempool_free(obj, cl->objs_pool);
+		return ERR_PTR(r);
+	}
+
+	alloc_chunks(cl, obj);
+	return obj;
+}
+EXPORT_SYMBOL(dm_mem_cache_alloc);
+
+void dm_mem_cache_free(struct dm_mem_cache_client *cl,
+		       struct dm_mem_cache_object *obj)
+{
+	free_chunks(cl, obj);
+	mempool_free(obj, cl->objs_pool);
+}
+EXPORT_SYMBOL(dm_mem_cache_free);
+
+MODULE_DESCRIPTION(DM_NAME " dm memory cache");
+MODULE_AUTHOR("Heinz Mauelshagen <hjm@redhat.com>");
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/Makefile
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/Makefile
@@ -0,0 +1,4 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/md
+
+obj-$(CONFIG_DM_RAID45) := dm-raid45.o
+dm-raid45-objs := dm-raid4-5.o dm-memcache.o dm-region-hash.o dm-message.o
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-message.c
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-message.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007,2008 Red Hat Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen <heinzm@redhat.com>
+ *
+ * General device-mapper message interface argument parser.
+ *
+ * This file is released under the GPL.
+ *
+ * device-mapper message parser.
+ *
+ */
+
+#include "dm.h"
+#include "dm-message.h"
+#include <linux/kernel.h>
+
+#define DM_MSG_PREFIX	"dm_message"
+
+/* Basename of a path. */
+static inline char *
+basename(char *s)
+{
+	char *p = strrchr(s, '/');
+
+	return p ? p + 1 : s;
+}
+
+/* Get an argument depending on type. */
+static void
+message_arguments(struct dm_msg *msg, int argc, char **argv)
+{
+
+	if (argc) {
+		int i;
+		struct dm_message_argument *args = msg->spec->args;
+
+		for (i = 0; i < args->num_args; i++) {
+			int r;
+			unsigned long **ptr = args->ptr;
+			enum dm_message_argument_type type = args->types[i];
+
+			switch (type) {
+			case dm_msg_base_t:
+				((char **) ptr)[i] = basename(argv[i]);
+				break;
+
+			case dm_msg_str_t:
+				((char **) ptr)[i] = argv[i];
+				break;
+
+			case dm_msg_int_t:
+				r = sscanf(argv[i], "%d", ((int **) ptr)[i]);
+				goto check;
+
+			case dm_msg_uint_t:
+				r = sscanf(argv[i], "%u",
+					   ((unsigned **) ptr)[i]);
+				goto check;
+
+			case dm_msg_uint64_t:
+				r = sscanf(argv[i], "%llu",
+					   ((unsigned long long **) ptr)[i]);
+
+check:
+				if (r != 1) {
+					set_bit(dm_msg_ret_undef, &msg->ret);
+					set_bit(dm_msg_ret_arg, &msg->ret);
+				}
+			}
+		}
+	}
+}
+
+/* Parse message options. */
+static void
+message_options_parse(struct dm_msg *msg, int argc, char **argv)
+{
+	int hit = 0;
+	unsigned long *action;
+	size_t l1 = strlen(*argv), l_hit = 0;
+	struct dm_message_option *o = msg->spec->options;
+	char **option, **option_end = o->options + o->num_options;
+
+	for (option = o->options, action = o->actions;
+	     option < option_end; option++, action++) {
+		size_t l2 = strlen(*option);
+
+		if (!strnicmp(*argv, *option, min(l1, l2))) {
+			hit++;
+			l_hit = l2;
+			set_bit(*action, &msg->action);
+		}
+	}
+
+	/* Assume error. */
+	msg->ret = 0;
+	set_bit(dm_msg_ret_option, &msg->ret);
+	if (!hit || l1 > l_hit)
+		set_bit(dm_msg_ret_undef, &msg->ret);	/* Undefined option. */
+	else if (hit > 1)
+		set_bit(dm_msg_ret_ambiguous, &msg->ret); /* Ambiguous option.*/
+	else {
+		clear_bit(dm_msg_ret_option, &msg->ret); /* Option OK. */
+		message_arguments(msg, --argc, ++argv);
+	}
+}
+
+static inline void
+print_ret(const char *caller, unsigned long ret)
+{
+	struct {
+		unsigned long err;
+		const char *err_str;
+	} static err_msg[] = {
+		{ dm_msg_ret_ambiguous, "message ambiguous" },
+		{ dm_msg_ret_inval, "message invalid" },
+		{ dm_msg_ret_undef, "message undefined" },
+		{ dm_msg_ret_arg, "message argument" },
+		{ dm_msg_ret_argcount, "message argument count" },
+		{ dm_msg_ret_option, "option" },
+	}, *e = ARRAY_END(err_msg);
+
+	while (e-- > err_msg) {
+		if (test_bit(e->err, &ret))
+			DMERR("%s %s", caller, e->err_str);
+	}
+}
+
+/* Parse a message action. */
+int
+dm_message_parse(const char *caller, struct dm_msg *msg, void *context,
+		 int argc, char **argv)
+{
+	int hit = 0;
+	size_t l1, l_hit = 0;
+	struct dm_msg_spec *s, *s_hit = NULL,
+			   *s_end = msg->specs + msg->num_specs;
+
+	if (argc < 2)
+		return -EINVAL;
+
+	l1 = strlen(*argv);
+	for (s = msg->specs; s < s_end; s++) {
+		size_t l2 = strlen(s->cmd);
+
+		if (!strnicmp(*argv, s->cmd, min(l1, l2))) {
+			hit++;
+			l_hit = l2;
+			s_hit = s;
+		}
+	}
+
+	msg->ret = 0;
+	if (!hit || l1 > l_hit)	/* No hit or message string too long. */
+		set_bit(dm_msg_ret_undef, &msg->ret);
+	else if (hit > 1)	/* Ambiguous message. */
+		set_bit(dm_msg_ret_ambiguous, &msg->ret);
+	else if (argc - 2 != s_hit->args->num_args) {
+		set_bit(dm_msg_ret_undef, &msg->ret);
+		set_bit(dm_msg_ret_argcount, &msg->ret);
+	}
+
+	if (msg->ret)
+		goto bad;
+
+	msg->action = 0;
+	msg->spec = s_hit;
+	set_bit(s_hit->action, &msg->action);
+	message_options_parse(msg, --argc, ++argv);
+
+	if (!msg->ret)
+		return msg->spec->f(msg, context);
+
+bad:
+	print_ret(caller, msg->ret);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(dm_message_parse);
+
+MODULE_DESCRIPTION(DM_NAME " device-mapper target message parser");
+MODULE_AUTHOR("Heinz Mauelshagen <hjm@redhat.com>");
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-raid45.h
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-raid45.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen (Mauelshagen@RedHat.com)
+ *
+ * Locking definitions for the device-mapper RAID45 target.
+ *
+ * This file is released under the GPL.
+ *
+ */
+
+#ifndef _DM_RAID45_H
+#define _DM_RAID45_H
+
+/* Factor out to dm.h! */
+#define	STR_LEN(ptr, str)	(ptr), (str), strlen((ptr))
+
+enum dm_lock_type { DM_RAID45_EX, DM_RAID45_SHARED };
+
+struct dm_raid45_locking_type {
+	/* Request a lock on a stripe. */
+	void* (*lock)(sector_t key, enum dm_lock_type type);
+
+	/* Release a lock on a stripe. */
+	void (*unlock)(void *lock_handle);
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-region-hash.h
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-region-hash.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * Device-Mapper dirty region hash interface.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_REGION_HASH_H
+#define DM_REGION_HASH_H
+
+#include <linux/dm-dirty-log.h>
+
+/*-----------------------------------------------------------------
+ * Region hash
+ *----------------------------------------------------------------*/
+struct dm_region_hash;
+struct dm_region;
+
+/*
+ * States a region can have.
+ */
+enum dm_rh_region_states {
+	DM_RH_CLEAN	 = 0x01,	/* No writes in flight. */
+	DM_RH_DIRTY	 = 0x02,	/* Writes in flight. */
+	DM_RH_NOSYNC	 = 0x04,	/* Out of sync. */
+	DM_RH_RECOVERING = 0x08,	/* Under resynchronization. */
+};
+
+/*
+ * Region hash create/destroy.
+ */
+struct bio_list;
+struct dm_region_hash *dm_region_hash_create(
+		void *context, void (*dispatch_bios)(void *context,
+						     struct bio_list *bios),
+		void (*wakeup_workers)(void *context),
+		void (*wakeup_all_recovery_waiters)(void *context),
+		sector_t target_begin, unsigned max_recovery,
+		struct dm_dirty_log *log, uint32_t region_size,
+		region_t nr_regions);
+void dm_region_hash_destroy(struct dm_region_hash *rh);
+
+struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh);
+
+/*
+ * Conversion functions.
+ */
+region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio);
+sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region);
+region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector);
+void *dm_rh_region_context(struct dm_region *reg);
+
+/*
+ * Get region size and key (ie. number of the region).
+ */
+sector_t dm_rh_get_region_size(struct dm_region_hash *rh);
+region_t dm_rh_get_region_key(struct dm_region *reg);
+
+/*
+ * Get/set/update region state (and dirty log).
+ *
+ */
+int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block);
+void dm_rh_set_state(struct dm_region_hash *rh, region_t region,
+		     enum dm_rh_region_states state, int may_block);
+
+/* Non-zero errors_handled leaves the state of the region NOSYNC */
+void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled);
+
+/* Flush the region hash and dirty log. */
+int dm_rh_flush(struct dm_region_hash *rh);
+
+/* Inc/dec pending count on regions. */
+void dm_rh_inc(struct dm_region_hash *rh, region_t region);
+void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios);
+void dm_rh_dec(struct dm_region_hash *rh, region_t region);
+
+/* Delay bios on regions. */
+void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio);
+void dm_rh_delay_by_region(struct dm_region_hash *rh, struct bio *bio,
+			   region_t region);
+
+void dm_rh_mark_nosync(struct dm_region_hash *rh,
+		       struct bio *bio, unsigned done, int error);
+
+/*
+ * Region recovery control.
+ */
+
+/* Prepare some regions for recovery by starting to quiesce them. */
+void dm_rh_recovery_prepare(struct dm_region_hash *rh);
+
+/* Try fetching a quiesced region for recovery. */
+struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh);
+
+/* Report recovery end on a region. */
+void dm_rh_recovery_end(struct dm_region *reg, int error);
+
+/* Returns number of regions with recovery work outstanding. */
+int dm_rh_recovery_in_flight(struct dm_region_hash *rh);
+
+/* Start/stop recovery. */
+void dm_rh_start_recovery(struct dm_region_hash *rh);
+void dm_rh_stop_recovery(struct dm_region_hash *rh);
+
+#endif /* DM_REGION_HASH_H */
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/Kconfig
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/Kconfig
@@ -0,0 +1,6 @@
+config DM_RAID45
+	tristate "RAID 4/5 target (EXPERIMENTAL)"
+	depends on BLK_DEV_DM && XOR_BLOCKS && EXPERIMENTAL
+	default m
+	---help---
+	A target that supports RAID4 and RAID5 mappings.
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-region-hash.c
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-region-hash.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/dm-dirty-log.h>
+#include "dm-region-hash.h"
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include "dm.h"
+
+#define	DM_MSG_PREFIX	"region hash"
+
+/*-----------------------------------------------------------------
+ * Region hash
+ *
+ * The mirror splits itself up into discrete regions.  Each
+ * region can be in one of three states: clean, dirty,
+ * nosync.  There is no need to put clean regions in the hash.
+ *
+ * In addition to being present in the hash table a region _may_
+ * be present on one of three lists.
+ *
+ *   clean_regions: Regions on this list have no io pending to
+ *   them, they are in sync, we are no longer interested in them,
+ *   they are dull.  dm_rh_update_states() will remove them from the
+ *   hash table.
+ *
+ *   quiesced_regions: These regions have been spun down, ready
+ *   for recovery.  rh_recovery_start() will remove regions from
+ *   this list and hand them to kmirrord, which will schedule the
+ *   recovery io with kcopyd.
+ *
+ *   recovered_regions: Regions that kcopyd has successfully
+ *   recovered.  dm_rh_update_states() will now schedule any delayed
+ *   io, up the recovery_count, and remove the region from the
+ *   hash.
+ *
+ * There are 2 locks:
+ *   A rw spin lock 'hash_lock' protects just the hash table,
+ *   this is never held in write mode from interrupt context,
+ *   which I believe means that we only have to disable irqs when
+ *   doing a write lock.
+ *
+ *   An ordinary spin lock 'region_lock' that protects the three
+ *   lists in the region_hash, with the 'state', 'list' and
+ *   'delayed_bios' fields of the regions.  This is used from irq
+ *   context, so all other uses will have to suspend local irqs.
+ *---------------------------------------------------------------*/
+struct dm_region_hash {
+	uint32_t region_size;
+	unsigned region_shift;
+
+	/* holds persistent region state */
+	struct dm_dirty_log *log;
+
+	/* hash table */
+	rwlock_t hash_lock;
+	mempool_t *region_pool;
+	unsigned mask;
+	unsigned nr_buckets;
+	unsigned prime;
+	unsigned shift;
+	struct list_head *buckets;
+
+	unsigned max_recovery; /* Max # of regions to recover in parallel */
+
+	spinlock_t region_lock;
+	atomic_t recovery_in_flight;
+	struct semaphore recovery_count;
+	struct list_head clean_regions;
+	struct list_head quiesced_regions;
+	struct list_head recovered_regions;
+	struct list_head failed_recovered_regions;
+
+	void *context;
+	sector_t target_begin;
+
+	/* Callback function to schedule bios writes */
+	void (*dispatch_bios)(void *context, struct bio_list *bios);
+
+	/* Callback function to wakeup callers worker thread. */
+	void (*wakeup_workers)(void *context);
+
+	/* Callback function to wakeup callers recovery waiters. */
+	void (*wakeup_all_recovery_waiters)(void *context);
+};
+
+struct dm_region {
+	struct dm_region_hash *rh;	/* FIXME: can we get rid of this ? */
+	region_t key;
+	int state;
+
+	struct list_head hash_list;
+	struct list_head list;
+
+	atomic_t pending;
+	struct bio_list delayed_bios;
+};
+
+/*
+ * Conversion fns
+ */
+region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector)
+{
+	return sector >> rh->region_shift;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_sector_to_region);
+
+sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region)
+{
+	return region << rh->region_shift;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_region_to_sector);
+
+region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio)
+{
+	return dm_rh_sector_to_region(rh, bio->bi_sector - rh->target_begin);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_bio_to_region);
+
+void *dm_rh_region_context(struct dm_region *reg)
+{
+	return reg->rh->context;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_region_context);
+
+region_t dm_rh_get_region_key(struct dm_region *reg)
+{
+	return reg->key;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_get_region_key);
+
+sector_t dm_rh_get_region_size(struct dm_region_hash *rh)
+{
+	return rh->region_size;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_get_region_size);
+
+/*
+ * FIXME: shall we pass in a structure instead of all these args to
+ * dm_region_hash_create()????
+ */
+#define RH_HASH_MULT 2654435387U
+#define RH_HASH_SHIFT 12
+
+#define MIN_REGIONS 64
+struct dm_region_hash *dm_region_hash_create(
+		void *context, void (*dispatch_bios)(void *context,
+						     struct bio_list *bios),
+		void (*wakeup_workers)(void *context),
+		void (*wakeup_all_recovery_waiters)(void *context),
+		sector_t target_begin, unsigned max_recovery,
+		struct dm_dirty_log *log, uint32_t region_size,
+		region_t nr_regions)
+{
+	struct dm_region_hash *rh;
+	unsigned nr_buckets, max_buckets;
+	size_t i;
+
+	/*
+	 * Calculate a suitable number of buckets for our hash
+	 * table.
+	 */
+	max_buckets = nr_regions >> 6;
+	for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1)
+		;
+	nr_buckets >>= 1;
+
+	rh = kmalloc(sizeof(*rh), GFP_KERNEL);
+	if (!rh) {
+		DMERR("unable to allocate region hash memory");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	rh->context = context;
+	rh->dispatch_bios = dispatch_bios;
+	rh->wakeup_workers = wakeup_workers;
+	rh->wakeup_all_recovery_waiters = wakeup_all_recovery_waiters;
+	rh->target_begin = target_begin;
+	rh->max_recovery = max_recovery;
+	rh->log = log;
+	rh->region_size = region_size;
+	rh->region_shift = ffs(region_size) - 1;
+	rwlock_init(&rh->hash_lock);
+	rh->mask = nr_buckets - 1;
+	rh->nr_buckets = nr_buckets;
+
+	rh->shift = RH_HASH_SHIFT;
+	rh->prime = RH_HASH_MULT;
+
+	rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
+	if (!rh->buckets) {
+		DMERR("unable to allocate region hash bucket memory");
+		kfree(rh);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < nr_buckets; i++)
+		INIT_LIST_HEAD(rh->buckets + i);
+
+	spin_lock_init(&rh->region_lock);
+	sema_init(&rh->recovery_count, 0);
+	atomic_set(&rh->recovery_in_flight, 0);
+	INIT_LIST_HEAD(&rh->clean_regions);
+	INIT_LIST_HEAD(&rh->quiesced_regions);
+	INIT_LIST_HEAD(&rh->recovered_regions);
+	INIT_LIST_HEAD(&rh->failed_recovered_regions);
+
+	rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
+						      sizeof(struct dm_region));
+	if (!rh->region_pool) {
+		vfree(rh->buckets);
+		kfree(rh);
+		rh = ERR_PTR(-ENOMEM);
+	}
+
+	return rh;
+}
+// EXPORT_SYMBOL_GPL(dm_region_hash_create);
+
+void dm_region_hash_destroy(struct dm_region_hash *rh)
+{
+	unsigned h;
+	struct dm_region *reg, *nreg;
+
+	BUG_ON(!list_empty(&rh->quiesced_regions));
+	for (h = 0; h < rh->nr_buckets; h++) {
+		list_for_each_entry_safe(reg, nreg, rh->buckets + h,
+					 hash_list) {
+			BUG_ON(atomic_read(&reg->pending));
+			mempool_free(reg, rh->region_pool);
+		}
+	}
+
+	if (rh->log)
+		dm_dirty_log_destroy(rh->log);
+
+	if (rh->region_pool)
+		mempool_destroy(rh->region_pool);
+
+	vfree(rh->buckets);
+	kfree(rh);
+}
+// EXPORT_SYMBOL_GPL(dm_region_hash_destroy);
+
+struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh)
+{
+	return rh->log;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_dirty_log);
+
+static unsigned rh_hash(struct dm_region_hash *rh, region_t region)
+{
+	return (unsigned) ((region * rh->prime) >> rh->shift) & rh->mask;
+}
+
+static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region)
+{
+	struct dm_region *reg;
+	struct list_head *bucket = rh->buckets + rh_hash(rh, region);
+
+	list_for_each_entry(reg, bucket, hash_list)
+		if (reg->key == region)
+			return reg;
+
+	return NULL;
+}
+
+static void __rh_insert(struct dm_region_hash *rh, struct dm_region *reg)
+{
+	list_add(&reg->hash_list, rh->buckets + rh_hash(rh, reg->key));
+}
+
+static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region)
+{
+	struct dm_region *reg, *nreg;
+
+	nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
+	if (unlikely(!nreg))
+		nreg = kmalloc(sizeof(*nreg), GFP_NOIO | __GFP_NOFAIL);
+
+	nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
+		      DM_RH_CLEAN : DM_RH_NOSYNC;
+	nreg->rh = rh;
+	nreg->key = region;
+	INIT_LIST_HEAD(&nreg->list);
+	atomic_set(&nreg->pending, 0);
+	bio_list_init(&nreg->delayed_bios);
+
+	write_lock_irq(&rh->hash_lock);
+	reg = __rh_lookup(rh, region);
+	if (reg)
+		/* We lost the race. */
+		mempool_free(nreg, rh->region_pool);
+	else {
+		__rh_insert(rh, nreg);
+		if (nreg->state == DM_RH_CLEAN) {
+			spin_lock(&rh->region_lock);
+			list_add(&nreg->list, &rh->clean_regions);
+			spin_unlock(&rh->region_lock);
+		}
+
+		reg = nreg;
+	}
+	write_unlock_irq(&rh->hash_lock);
+
+	return reg;
+}
+
+static struct dm_region *__rh_find(struct dm_region_hash *rh, region_t region)
+{
+	struct dm_region *reg;
+
+	reg = __rh_lookup(rh, region);
+	if (!reg) {
+		read_unlock(&rh->hash_lock);
+		reg = __rh_alloc(rh, region);
+		read_lock(&rh->hash_lock);
+	}
+
+	return reg;
+}
+
+int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block)
+{
+	int r;
+	struct dm_region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_lookup(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	if (reg)
+		return reg->state;
+
+	/*
+	 * The region wasn't in the hash, so we fall back to the
+	 * dirty log.
+	 */
+	r = rh->log->type->in_sync(rh->log, region, may_block);
+
+	/*
+	 * Any error from the dirty log (eg. -EWOULDBLOCK) gets
+	 * taken as a DM_RH_NOSYNC
+	 */
+	return r == 1 ? DM_RH_CLEAN : DM_RH_NOSYNC;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_get_state);
+
+static void complete_resync_work(struct dm_region *reg, int success)
+{
+	struct dm_region_hash *rh = reg->rh;
+
+	rh->log->type->set_region_sync(rh->log, reg->key, success);
+
+	/*
+	 * Dispatch the bios before we call 'wake_up_all'.
+	 * This is important because if we are suspending,
+	 * we want to know that recovery is complete and
+	 * the work queue is flushed.  If we wake_up_all
+	 * before we dispatch_bios (queue bios and call wake()),
+	 * then we risk suspending before the work queue
+	 * has been properly flushed.
+	 */
+	rh->dispatch_bios(rh->context, &reg->delayed_bios);
+	if (atomic_dec_and_test(&rh->recovery_in_flight))
+		rh->wakeup_all_recovery_waiters(rh->context);
+	up(&rh->recovery_count);
+}
+
+/* dm_rh_mark_nosync
+ * @ms
+ * @bio
+ * @done
+ * @error
+ *
+ * The bio was written on some mirror(s) but failed on other mirror(s).
+ * We can successfully endio the bio but should avoid the region being
+ * marked clean by setting the state DM_RH_NOSYNC.
+ *
+ * This function is _not_ safe in interrupt context!
+ */
+void dm_rh_mark_nosync(struct dm_region_hash *rh,
+		       struct bio *bio, unsigned done, int error)
+{
+	unsigned long flags;
+	struct dm_dirty_log *log = rh->log;
+	struct dm_region *reg;
+	region_t region = dm_rh_bio_to_region(rh, bio);
+	int recovering = 0;
+
+	/* We must inform the log that the sync count has changed. */
+	log->type->set_region_sync(log, region, 0);
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	/* region hash entry should exist because write was in-flight */
+	BUG_ON(!reg);
+	BUG_ON(!list_empty(&reg->list));
+
+	spin_lock_irqsave(&rh->region_lock, flags);
+	/*
+	 * Possible cases:
+	 *   1) DM_RH_DIRTY
+	 *   2) DM_RH_NOSYNC: was dirty, other preceeding writes failed
+	 *   3) DM_RH_RECOVERING: flushing pending writes
+	 * Either case, the region should have not been connected to list.
+	 */
+	recovering = (reg->state == DM_RH_RECOVERING);
+	reg->state = DM_RH_NOSYNC;
+	BUG_ON(!list_empty(&reg->list));
+	spin_unlock_irqrestore(&rh->region_lock, flags);
+
+	bio_endio(bio, error);
+	if (recovering)
+		complete_resync_work(reg, 0);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_mark_nosync);
+
+void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled)
+{
+	struct dm_region *reg, *next;
+
+	LIST_HEAD(clean);
+	LIST_HEAD(recovered);
+	LIST_HEAD(failed_recovered);
+
+	/*
+	 * Quickly grab the lists.
+	 */
+	write_lock_irq(&rh->hash_lock);
+	spin_lock(&rh->region_lock);
+	if (!list_empty(&rh->clean_regions)) {
+		list_splice_init(&rh->clean_regions, &clean);
+
+		list_for_each_entry(reg, &clean, list)
+			list_del(&reg->hash_list);
+	}
+
+	if (!list_empty(&rh->recovered_regions)) {
+		list_splice_init(&rh->recovered_regions, &recovered);
+
+		list_for_each_entry(reg, &recovered, list)
+			list_del(&reg->hash_list);
+	}
+
+	if (!list_empty(&rh->failed_recovered_regions)) {
+		list_splice_init(&rh->failed_recovered_regions,
+				 &failed_recovered);
+
+		list_for_each_entry(reg, &failed_recovered, list)
+			list_del(&reg->hash_list);
+	}
+
+	spin_unlock(&rh->region_lock);
+	write_unlock_irq(&rh->hash_lock);
+
+	/*
+	 * All the regions on the recovered and clean lists have
+	 * now been pulled out of the system, so no need to do
+	 * any more locking.
+	 */
+	list_for_each_entry_safe(reg, next, &recovered, list) {
+		rh->log->type->clear_region(rh->log, reg->key);
+		complete_resync_work(reg, 1);
+		mempool_free(reg, rh->region_pool);
+	}
+
+	list_for_each_entry_safe(reg, next, &failed_recovered, list) {
+		complete_resync_work(reg, errors_handled ? 0 : 1);
+		mempool_free(reg, rh->region_pool);
+	}
+
+	list_for_each_entry_safe(reg, next, &clean, list) {
+		rh->log->type->clear_region(rh->log, reg->key);
+		mempool_free(reg, rh->region_pool);
+	}
+
+	rh->log->type->flush(rh->log);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_update_states);
+
+void dm_rh_inc(struct dm_region_hash *rh, region_t region)
+{
+	struct dm_region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+
+	spin_lock_irq(&rh->region_lock);
+	atomic_inc(&reg->pending);
+
+	if (reg->state == DM_RH_CLEAN) {
+		reg->state = DM_RH_DIRTY;
+		list_del_init(&reg->list);	/* take off the clean list */
+		spin_unlock_irq(&rh->region_lock);
+
+		rh->log->type->mark_region(rh->log, reg->key);
+	} else
+		spin_unlock_irq(&rh->region_lock);
+
+
+	read_unlock(&rh->hash_lock);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_inc);
+
+void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
+{
+	struct bio *bio;
+
+	for (bio = bios->head; bio; bio = bio->bi_next)
+		dm_rh_inc(rh, dm_rh_bio_to_region(rh, bio));
+}
+// EXPORT_SYMBOL_GPL(dm_rh_inc_pending);
+
+void dm_rh_dec(struct dm_region_hash *rh, region_t region)
+{
+	unsigned long flags;
+	struct dm_region *reg;
+	int should_wake = 0;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_lookup(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	spin_lock_irqsave(&rh->region_lock, flags);
+	if (atomic_dec_and_test(&reg->pending)) {
+		/*
+		 * There is no pending I/O for this region.
+		 * We can move the region to corresponding list for next action.
+		 * At this point, the region is not yet connected to any list.
+		 *
+		 * If the state is DM_RH_NOSYNC, the region should be kept off
+		 * from clean list.
+		 * The hash entry for DM_RH_NOSYNC will remain in memory
+		 * until the region is recovered or the map is reloaded.
+		 */
+
+		/* do nothing for DM_RH_NOSYNC */
+		if (reg->state == DM_RH_RECOVERING) {
+			list_add_tail(&reg->list, &rh->quiesced_regions);
+		} else if (reg->state == DM_RH_DIRTY) {
+			reg->state = DM_RH_CLEAN;
+			list_add(&reg->list, &rh->clean_regions);
+		}
+		should_wake = 1;
+	}
+	spin_unlock_irqrestore(&rh->region_lock, flags);
+
+	if (should_wake)
+		rh->wakeup_workers(rh->context);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_dec);
+
+/*
+ * Starts quiescing a region in preparation for recovery.
+ */
+static int __rh_recovery_prepare(struct dm_region_hash *rh)
+{
+	int r;
+	region_t region;
+	struct dm_region *reg;
+
+	/*
+	 * Ask the dirty log what's next.
+	 */
+	r = rh->log->type->get_resync_work(rh->log, &region);
+	if (r <= 0)
+		return r;
+
+	/*
+	 * Get this region, and start it quiescing by setting the
+	 * recovering flag.
+	 */
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+	read_unlock(&rh->hash_lock);
+
+	spin_lock_irq(&rh->region_lock);
+	reg->state = DM_RH_RECOVERING;
+
+	/* Already quiesced ? */
+	if (atomic_read(&reg->pending))
+		list_del_init(&reg->list);
+	else
+		list_move(&reg->list, &rh->quiesced_regions);
+
+	spin_unlock_irq(&rh->region_lock);
+
+	return 1;
+}
+
+void dm_rh_recovery_prepare(struct dm_region_hash *rh)
+{
+	/* Extra reference to avoid race with dm_rh_stop_recovery */
+	atomic_inc(&rh->recovery_in_flight);
+
+	while (!down_trylock(&rh->recovery_count)) {
+		atomic_inc(&rh->recovery_in_flight);
+		if (__rh_recovery_prepare(rh) <= 0) {
+			atomic_dec(&rh->recovery_in_flight);
+			up(&rh->recovery_count);
+			break;
+		}
+	}
+
+	/* Drop the extra reference */
+	if (atomic_dec_and_test(&rh->recovery_in_flight))
+		rh->wakeup_all_recovery_waiters(rh->context);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_recovery_prepare);
+
+/*
+ * Returns any quiesced regions.
+ */
+struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh)
+{
+	struct dm_region *reg = NULL;
+
+	spin_lock_irq(&rh->region_lock);
+	if (!list_empty(&rh->quiesced_regions)) {
+		reg = list_entry(rh->quiesced_regions.next,
+				 struct dm_region, list);
+		list_del_init(&reg->list);  /* remove from the quiesced list */
+	}
+	spin_unlock_irq(&rh->region_lock);
+
+	return reg;
+}
+// EXPORT_SYMBOL_GPL(dm_rh_recovery_start);
+
+void dm_rh_recovery_end(struct dm_region *reg, int success)
+{
+	struct dm_region_hash *rh = reg->rh;
+
+	spin_lock_irq(&rh->region_lock);
+	if (success)
+		list_add(&reg->list, &reg->rh->recovered_regions);
+	else {
+		reg->state = DM_RH_NOSYNC;
+		list_add(&reg->list, &reg->rh->failed_recovered_regions);
+	}
+	spin_unlock_irq(&rh->region_lock);
+
+	rh->wakeup_workers(rh->context);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_recovery_end);
+
+/* Return recovery in flight count. */
+int dm_rh_recovery_in_flight(struct dm_region_hash *rh)
+{
+	return atomic_read(&rh->recovery_in_flight);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_recovery_in_flight);
+
+int dm_rh_flush(struct dm_region_hash *rh)
+{
+	return rh->log->type->flush(rh->log);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_flush);
+
+void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio)
+{
+	struct dm_region *reg;
+
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, dm_rh_bio_to_region(rh, bio));
+	bio_list_add(&reg->delayed_bios, bio);
+	read_unlock(&rh->hash_lock);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_delay);
+
+void dm_rh_delay_by_region(struct dm_region_hash *rh,
+			   struct bio *bio, region_t region)
+{
+	struct dm_region *reg;
+
+	/* FIXME: locking. */
+	read_lock(&rh->hash_lock);
+	reg = __rh_find(rh, region);
+	bio_list_add(&reg->delayed_bios, bio);
+	read_unlock(&rh->hash_lock);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_delay_by_region);
+
+void dm_rh_stop_recovery(struct dm_region_hash *rh)
+{
+	int i;
+
+	/* wait for any recovering regions */
+	for (i = 0; i < rh->max_recovery; i++)
+		down(&rh->recovery_count);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_stop_recovery);
+
+void dm_rh_start_recovery(struct dm_region_hash *rh)
+{
+	int i;
+
+	for (i = 0; i < rh->max_recovery; i++)
+		up(&rh->recovery_count);
+
+	rh->wakeup_workers(rh->context);
+}
+// EXPORT_SYMBOL_GPL(dm_rh_start_recovery);
+
+MODULE_DESCRIPTION(DM_NAME " region hash");
+MODULE_AUTHOR("Joe Thornber/Heinz Mauelshagen <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-message.h
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-message.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007,2008 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen <Mauelshagen@RedHat.de>
+ *
+ * General device-mapper message interface argument parser.
+ *
+ * This file is released under the GPL.
+ *
+ */
+
+#ifndef DM_MESSAGE_H
+#define DM_MESSAGE_H
+
+/* Factor out to dm.h. */
+/* Reference to array end. */
+#define ARRAY_END(a)    ((a) + ARRAY_SIZE(a))
+
+/* Message return bits. */
+enum dm_message_return {
+	dm_msg_ret_ambiguous,		/* Action ambiguous. */
+	dm_msg_ret_inval,		/* Action invalid. */
+	dm_msg_ret_undef,		/* Action undefined. */
+
+	dm_msg_ret_option,		/* Option error. */
+	dm_msg_ret_arg,			/* Argument error. */
+	dm_msg_ret_argcount,		/* Argument count error. */
+};
+
+/* Message argument type conversions. */
+enum dm_message_argument_type {
+	dm_msg_base_t,		/* Basename string. */
+	dm_msg_str_t,		/* String. */
+	dm_msg_int_t,		/* Signed int. */
+	dm_msg_uint_t,		/* Unsigned int. */
+	dm_msg_uint64_t,	/* Unsigned int 64. */
+};
+
+/* A message option. */
+struct dm_message_option {
+	unsigned num_options;
+	char **options;
+	unsigned long *actions;
+};
+
+/* Message arguments and types. */
+struct dm_message_argument {
+	unsigned num_args;
+	unsigned long **ptr;
+	enum dm_message_argument_type types[];
+};
+
+/* Client message. */
+struct dm_msg {
+	unsigned long action;		/* Identified action. */
+	unsigned long ret;		/* Return bits. */
+	unsigned num_specs;		/* # of sepcifications listed. */
+	struct dm_msg_spec *specs;	/* Specification list. */
+	struct dm_msg_spec *spec;	/* Specification selected. */
+};
+
+/* Secification of the message. */
+struct dm_msg_spec {
+	const char *cmd;	/* Name of the command (i.e. 'bandwidth'). */
+	unsigned long action;
+	struct dm_message_option *options;
+	struct dm_message_argument *args;
+	unsigned long parm;	/* Parameter to pass through to callback. */
+	/* Function to process for action. */
+	int (*f) (struct dm_msg *msg, void *context);
+};
+
+/* Parameter access macros. */
+#define	DM_MSG_PARM(msg) ((msg)->spec->parm)
+
+#define	DM_MSG_STR_ARGS(msg, idx) ((char *) *(msg)->spec->args->ptr[idx])
+#define	DM_MSG_INT_ARGS(msg, idx) ((int) *(msg)->spec->args->ptr[idx])
+#define	DM_MSG_UINT_ARGS(msg, idx) ((unsigned) DM_MSG_INT_ARG(msg, idx))
+#define	DM_MSG_UINT64_ARGS(msg, idx) ((uint64_t)  *(msg)->spec->args->ptr[idx])
+
+#define	DM_MSG_STR_ARG(msg)	DM_MSG_STR_ARGS(msg, 0)
+#define	DM_MSG_INT_ARG(msg)	DM_MSG_INT_ARGS(msg, 0)
+#define	DM_MSG_UINT_ARG(msg)	DM_MSG_UINT_ARGS(msg, 0)
+#define	DM_MSG_UINT64_ARG(msg)	DM_MSG_UINT64_ARGS(msg, 0)
+
+
+/* Parse a message and its options and optionally call a function back. */
+int dm_message_parse(const char *caller, struct dm_msg *msg, void *context,
+		     int argc, char **argv);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/BOM
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/BOM
@@ -0,0 +1,3 @@
+Downloaded from:	http://people.redhat.com/~heinzm/sw/dm/dm-raid45/
+Current Version:	2009.04.24 (2.6.30-rc3)
+Comments:		All of the patches to dmraid1/dm-log, etc are upstream.
--- linux-ec2-2.6.32.orig/ubuntu/dm-raid4-5/dm-raid4-5.h
+++ linux-ec2-2.6.32/ubuntu/dm-raid4-5/dm-raid4-5.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006  Red Hat GmbH
+ *
+ * Module Author: Heinz Mauelshagen (Mauelshagen@RedHat.com)
+ *
+ * This file is released under the GPL.
+ *
+ */
+
+#ifndef _DM_RAID45_H
+#define _DM_RAID45_H
+
+/* Factor out to dm.h! */
+#define	STR_LEN(ptr, str) ptr, str, strlen(ptr)
+
+enum lock_type { RAID45_EX, RAID45_SHARED };
+
+struct dmraid45_locking_type {
+        /* Request a lock on a stripe. */
+        void* (*lock)(sector_t key, enum lock_type type);
+
+        /* Release a lock on a stripe. */
+        void (*unlock)(void *lock_handle);
+
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/aufs/opts.c
+++ linux-ec2-2.6.32/ubuntu/aufs/opts.c
@@ -0,0 +1,1549 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * mount options/flags
+ */
+
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/types.h> /* a distribution requires */
+#include <linux/parser.h>
+#include "aufs.h"
+
+/* ---------------------------------------------------------------------- */
+
+enum {
+	Opt_br,
+	Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
+	Opt_idel, Opt_imod, Opt_ireorder,
+	Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
+	Opt_rdblk_def, Opt_rdhash_def,
+	Opt_xino, Opt_zxino, Opt_noxino,
+	Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
+	Opt_trunc_xino_path, Opt_itrunc_xino,
+	Opt_trunc_xib, Opt_notrunc_xib,
+	Opt_shwh, Opt_noshwh,
+	Opt_plink, Opt_noplink, Opt_list_plink,
+	Opt_udba,
+	/* Opt_lock, Opt_unlock, */
+	Opt_cmd, Opt_cmd_args,
+	Opt_diropq_a, Opt_diropq_w,
+	Opt_warn_perm, Opt_nowarn_perm,
+	Opt_wbr_copyup, Opt_wbr_create,
+	Opt_refrof, Opt_norefrof,
+	Opt_verbose, Opt_noverbose,
+	Opt_sum, Opt_nosum, Opt_wsum,
+	Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
+};
+
+static match_table_t options = {
+	{Opt_br, "br=%s"},
+	{Opt_br, "br:%s"},
+
+	{Opt_add, "add=%d:%s"},
+	{Opt_add, "add:%d:%s"},
+	{Opt_add, "ins=%d:%s"},
+	{Opt_add, "ins:%d:%s"},
+	{Opt_append, "append=%s"},
+	{Opt_append, "append:%s"},
+	{Opt_prepend, "prepend=%s"},
+	{Opt_prepend, "prepend:%s"},
+
+	{Opt_del, "del=%s"},
+	{Opt_del, "del:%s"},
+	/* {Opt_idel, "idel:%d"}, */
+	{Opt_mod, "mod=%s"},
+	{Opt_mod, "mod:%s"},
+	/* {Opt_imod, "imod:%d:%s"}, */
+
+	{Opt_dirwh, "dirwh=%d"},
+
+	{Opt_xino, "xino=%s"},
+	{Opt_noxino, "noxino"},
+	{Opt_trunc_xino, "trunc_xino"},
+	{Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
+	{Opt_notrunc_xino, "notrunc_xino"},
+	{Opt_trunc_xino_path, "trunc_xino=%s"},
+	{Opt_itrunc_xino, "itrunc_xino=%d"},
+	/* {Opt_zxino, "zxino=%s"}, */
+	{Opt_trunc_xib, "trunc_xib"},
+	{Opt_notrunc_xib, "notrunc_xib"},
+
+	{Opt_plink, "plink"},
+	{Opt_noplink, "noplink"},
+#ifdef CONFIG_AUFS_DEBUG
+	{Opt_list_plink, "list_plink"},
+#endif
+
+	{Opt_udba, "udba=%s"},
+
+	{Opt_diropq_a, "diropq=always"},
+	{Opt_diropq_a, "diropq=a"},
+	{Opt_diropq_w, "diropq=whiteouted"},
+	{Opt_diropq_w, "diropq=w"},
+
+	{Opt_warn_perm, "warn_perm"},
+	{Opt_nowarn_perm, "nowarn_perm"},
+
+	/* keep them temporary */
+	{Opt_ignore_silent, "coo=%s"},
+	{Opt_ignore_silent, "nodlgt"},
+	{Opt_ignore_silent, "nodirperm1"},
+	{Opt_ignore_silent, "clean_plink"},
+
+#ifdef CONFIG_AUFS_SHWH
+	{Opt_shwh, "shwh"},
+#endif
+	{Opt_noshwh, "noshwh"},
+
+	{Opt_rendir, "rendir=%d"},
+
+	{Opt_refrof, "refrof"},
+	{Opt_norefrof, "norefrof"},
+
+	{Opt_verbose, "verbose"},
+	{Opt_verbose, "v"},
+	{Opt_noverbose, "noverbose"},
+	{Opt_noverbose, "quiet"},
+	{Opt_noverbose, "q"},
+	{Opt_noverbose, "silent"},
+
+	{Opt_sum, "sum"},
+	{Opt_nosum, "nosum"},
+	{Opt_wsum, "wsum"},
+
+	{Opt_rdcache, "rdcache=%d"},
+	{Opt_rdblk, "rdblk=%d"},
+	{Opt_rdblk_def, "rdblk=def"},
+	{Opt_rdhash, "rdhash=%d"},
+	{Opt_rdhash_def, "rdhash=def"},
+
+	{Opt_wbr_create, "create=%s"},
+	{Opt_wbr_create, "create_policy=%s"},
+	{Opt_wbr_copyup, "cpup=%s"},
+	{Opt_wbr_copyup, "copyup=%s"},
+	{Opt_wbr_copyup, "copyup_policy=%s"},
+
+	/* internal use for the scripts */
+	{Opt_ignore_silent, "si=%s"},
+
+	{Opt_br, "dirs=%s"},
+	{Opt_ignore, "debug=%d"},
+	{Opt_ignore, "delete=whiteout"},
+	{Opt_ignore, "delete=all"},
+	{Opt_ignore, "imap=%s"},
+
+	/* temporary workaround, due to old mount(8)? */
+	{Opt_ignore_silent, "relatime"},
+
+	{Opt_err, NULL}
+};
+
+/* ---------------------------------------------------------------------- */
+
+static const char *au_parser_pattern(int val, struct match_token *token)
+{
+	while (token->pattern) {
+		if (token->token == val)
+			return token->pattern;
+		token++;
+	}
+	BUG();
+	return "??";
+}
+
+/* ---------------------------------------------------------------------- */
+
+static match_table_t brperms = {
+	{AuBrPerm_RO, AUFS_BRPERM_RO},
+	{AuBrPerm_RR, AUFS_BRPERM_RR},
+	{AuBrPerm_RW, AUFS_BRPERM_RW},
+
+	{AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
+	{AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
+	{AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
+
+	{AuBrPerm_ROWH, "nfsro"},
+	{AuBrPerm_RO, NULL}
+};
+
+static int noinline_for_stack br_perm_val(char *perm)
+{
+	int val;
+	substring_t args[MAX_OPT_ARGS];
+
+	val = match_token(perm, brperms, args);
+	return val;
+}
+
+const char *au_optstr_br_perm(int brperm)
+{
+	return au_parser_pattern(brperm, (void *)brperms);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static match_table_t udbalevel = {
+	{AuOpt_UDBA_REVAL, "reval"},
+	{AuOpt_UDBA_NONE, "none"},
+#ifdef CONFIG_AUFS_HINOTIFY
+	{AuOpt_UDBA_HINOTIFY, "inotify"},
+#endif
+	{-1, NULL}
+};
+
+static int noinline_for_stack udba_val(char *str)
+{
+	substring_t args[MAX_OPT_ARGS];
+
+	return match_token(str, udbalevel, args);
+}
+
+const char *au_optstr_udba(int udba)
+{
+	return au_parser_pattern(udba, (void *)udbalevel);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static match_table_t au_wbr_create_policy = {
+	{AuWbrCreate_TDP, "tdp"},
+	{AuWbrCreate_TDP, "top-down-parent"},
+	{AuWbrCreate_RR, "rr"},
+	{AuWbrCreate_RR, "round-robin"},
+	{AuWbrCreate_MFS, "mfs"},
+	{AuWbrCreate_MFS, "most-free-space"},
+	{AuWbrCreate_MFSV, "mfs:%d"},
+	{AuWbrCreate_MFSV, "most-free-space:%d"},
+
+	{AuWbrCreate_MFSRR, "mfsrr:%d"},
+	{AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
+	{AuWbrCreate_PMFS, "pmfs"},
+	{AuWbrCreate_PMFSV, "pmfs:%d"},
+
+	{-1, NULL}
+};
+
+/*
+ * cf. linux/lib/parser.c and cmdline.c
+ * gave up calling memparse() since it uses simple_strtoull() instead of
+ * strict_...().
+ */
+static int noinline_for_stack
+au_match_ull(substring_t *s, unsigned long long *result)
+{
+	int err;
+	unsigned int len;
+	char a[32];
+
+	err = -ERANGE;
+	len = s->to - s->from;
+	if (len + 1 <= sizeof(a)) {
+		memcpy(a, s->from, len);
+		a[len] = '\0';
+		err = strict_strtoull(a, 0, result);
+	}
+	return err;
+}
+
+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
+			    struct au_opt_wbr_create *create)
+{
+	int err;
+	unsigned long long ull;
+
+	err = 0;
+	if (!au_match_ull(arg, &ull))
+		create->mfsrr_watermark = ull;
+	else {
+		pr_err("bad integer in %s\n", str);
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static int au_wbr_mfs_sec(substring_t *arg, char *str,
+			  struct au_opt_wbr_create *create)
+{
+	int n, err;
+
+	err = 0;
+	if (!match_int(arg, &n) && 0 <= n)
+		create->mfs_second = n;
+	else {
+		pr_err("bad integer in %s\n", str);
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static int noinline_for_stack
+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
+{
+	int err, e;
+	substring_t args[MAX_OPT_ARGS];
+
+	err = match_token(str, au_wbr_create_policy, args);
+	create->wbr_create = err;
+	switch (err) {
+	case AuWbrCreate_MFSRRV:
+		e = au_wbr_mfs_wmark(&args[0], str, create);
+		if (!e)
+			e = au_wbr_mfs_sec(&args[1], str, create);
+		if (unlikely(e))
+			err = e;
+		break;
+	case AuWbrCreate_MFSRR:
+		e = au_wbr_mfs_wmark(&args[0], str, create);
+		if (unlikely(e)) {
+			err = e;
+			break;
+		}
+		/*FALLTHROUGH*/
+	case AuWbrCreate_MFS:
+	case AuWbrCreate_PMFS:
+		create->mfs_second = AUFS_MFS_SECOND_DEF;
+		break;
+	case AuWbrCreate_MFSV:
+	case AuWbrCreate_PMFSV:
+		e = au_wbr_mfs_sec(&args[0], str, create);
+		if (unlikely(e))
+			err = e;
+		break;
+	}
+
+	return err;
+}
+
+const char *au_optstr_wbr_create(int wbr_create)
+{
+	return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
+}
+
+static match_table_t au_wbr_copyup_policy = {
+	{AuWbrCopyup_TDP, "tdp"},
+	{AuWbrCopyup_TDP, "top-down-parent"},
+	{AuWbrCopyup_BUP, "bup"},
+	{AuWbrCopyup_BUP, "bottom-up-parent"},
+	{AuWbrCopyup_BU, "bu"},
+	{AuWbrCopyup_BU, "bottom-up"},
+	{-1, NULL}
+};
+
+static int noinline_for_stack au_wbr_copyup_val(char *str)
+{
+	substring_t args[MAX_OPT_ARGS];
+
+	return match_token(str, au_wbr_copyup_policy, args);
+}
+
+const char *au_optstr_wbr_copyup(int wbr_copyup)
+{
+	return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+
+static void dump_opts(struct au_opts *opts)
+{
+#ifdef CONFIG_AUFS_DEBUG
+	/* reduce stack space */
+	union {
+		struct au_opt_add *add;
+		struct au_opt_del *del;
+		struct au_opt_mod *mod;
+		struct au_opt_xino *xino;
+		struct au_opt_xino_itrunc *xino_itrunc;
+		struct au_opt_wbr_create *create;
+	} u;
+	struct au_opt *opt;
+
+	opt = opts->opt;
+	while (opt->type != Opt_tail) {
+		switch (opt->type) {
+		case Opt_add:
+			u.add = &opt->add;
+			AuDbg("add {b%d, %s, 0x%x, %p}\n",
+				  u.add->bindex, u.add->pathname, u.add->perm,
+				  u.add->path.dentry);
+			break;
+		case Opt_del:
+		case Opt_idel:
+			u.del = &opt->del;
+			AuDbg("del {%s, %p}\n",
+			      u.del->pathname, u.del->h_path.dentry);
+			break;
+		case Opt_mod:
+		case Opt_imod:
+			u.mod = &opt->mod;
+			AuDbg("mod {%s, 0x%x, %p}\n",
+				  u.mod->path, u.mod->perm, u.mod->h_root);
+			break;
+		case Opt_append:
+			u.add = &opt->add;
+			AuDbg("append {b%d, %s, 0x%x, %p}\n",
+				  u.add->bindex, u.add->pathname, u.add->perm,
+				  u.add->path.dentry);
+			break;
+		case Opt_prepend:
+			u.add = &opt->add;
+			AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
+				  u.add->bindex, u.add->pathname, u.add->perm,
+				  u.add->path.dentry);
+			break;
+		case Opt_dirwh:
+			AuDbg("dirwh %d\n", opt->dirwh);
+			break;
+		case Opt_rdcache:
+			AuDbg("rdcache %d\n", opt->rdcache);
+			break;
+		case Opt_rdblk:
+			AuDbg("rdblk %u\n", opt->rdblk);
+			break;
+		case Opt_rdblk_def:
+			AuDbg("rdblk_def\n");
+			break;
+		case Opt_rdhash:
+			AuDbg("rdhash %u\n", opt->rdhash);
+			break;
+		case Opt_rdhash_def:
+			AuDbg("rdhash_def\n");
+			break;
+		case Opt_xino:
+			u.xino = &opt->xino;
+			AuDbg("xino {%s %.*s}\n",
+				  u.xino->path,
+				  AuDLNPair(u.xino->file->f_dentry));
+			break;
+		case Opt_trunc_xino:
+			AuLabel(trunc_xino);
+			break;
+		case Opt_notrunc_xino:
+			AuLabel(notrunc_xino);
+			break;
+		case Opt_trunc_xino_path:
+		case Opt_itrunc_xino:
+			u.xino_itrunc = &opt->xino_itrunc;
+			AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
+			break;
+
+		case Opt_noxino:
+			AuLabel(noxino);
+			break;
+		case Opt_trunc_xib:
+			AuLabel(trunc_xib);
+			break;
+		case Opt_notrunc_xib:
+			AuLabel(notrunc_xib);
+			break;
+		case Opt_shwh:
+			AuLabel(shwh);
+			break;
+		case Opt_noshwh:
+			AuLabel(noshwh);
+			break;
+		case Opt_plink:
+			AuLabel(plink);
+			break;
+		case Opt_noplink:
+			AuLabel(noplink);
+			break;
+		case Opt_list_plink:
+			AuLabel(list_plink);
+			break;
+		case Opt_udba:
+			AuDbg("udba %d, %s\n",
+				  opt->udba, au_optstr_udba(opt->udba));
+			break;
+		case Opt_diropq_a:
+			AuLabel(diropq_a);
+			break;
+		case Opt_diropq_w:
+			AuLabel(diropq_w);
+			break;
+		case Opt_warn_perm:
+			AuLabel(warn_perm);
+			break;
+		case Opt_nowarn_perm:
+			AuLabel(nowarn_perm);
+			break;
+		case Opt_refrof:
+			AuLabel(refrof);
+			break;
+		case Opt_norefrof:
+			AuLabel(norefrof);
+			break;
+		case Opt_verbose:
+			AuLabel(verbose);
+			break;
+		case Opt_noverbose:
+			AuLabel(noverbose);
+			break;
+		case Opt_sum:
+			AuLabel(sum);
+			break;
+		case Opt_nosum:
+			AuLabel(nosum);
+			break;
+		case Opt_wsum:
+			AuLabel(wsum);
+			break;
+		case Opt_wbr_create:
+			u.create = &opt->wbr_create;
+			AuDbg("create %d, %s\n", u.create->wbr_create,
+				  au_optstr_wbr_create(u.create->wbr_create));
+			switch (u.create->wbr_create) {
+			case AuWbrCreate_MFSV:
+			case AuWbrCreate_PMFSV:
+				AuDbg("%d sec\n", u.create->mfs_second);
+				break;
+			case AuWbrCreate_MFSRR:
+				AuDbg("%llu watermark\n",
+					  u.create->mfsrr_watermark);
+				break;
+			case AuWbrCreate_MFSRRV:
+				AuDbg("%llu watermark, %d sec\n",
+					  u.create->mfsrr_watermark,
+					  u.create->mfs_second);
+				break;
+			}
+			break;
+		case Opt_wbr_copyup:
+			AuDbg("copyup %d, %s\n", opt->wbr_copyup,
+				  au_optstr_wbr_copyup(opt->wbr_copyup));
+			break;
+		default:
+			BUG();
+		}
+		opt++;
+	}
+#endif
+}
+
+void au_opts_free(struct au_opts *opts)
+{
+	struct au_opt *opt;
+
+	opt = opts->opt;
+	while (opt->type != Opt_tail) {
+		switch (opt->type) {
+		case Opt_add:
+		case Opt_append:
+		case Opt_prepend:
+			path_put(&opt->add.path);
+			break;
+		case Opt_del:
+		case Opt_idel:
+			path_put(&opt->del.h_path);
+			break;
+		case Opt_mod:
+		case Opt_imod:
+			dput(opt->mod.h_root);
+			break;
+		case Opt_xino:
+			fput(opt->xino.file);
+			break;
+		}
+		opt++;
+	}
+}
+
+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
+		   aufs_bindex_t bindex)
+{
+	int err;
+	struct au_opt_add *add = &opt->add;
+	char *p;
+
+	add->bindex = bindex;
+	add->perm = AuBrPerm_Last;
+	add->pathname = opt_str;
+	p = strchr(opt_str, '=');
+	if (p) {
+		*p++ = 0;
+		if (*p)
+			add->perm = br_perm_val(p);
+	}
+
+	err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
+	if (!err) {
+		if (!p) {
+			add->perm = AuBrPerm_RO;
+			if (au_test_fs_rr(add->path.dentry->d_sb))
+				add->perm = AuBrPerm_RR;
+			else if (!bindex && !(sb_flags & MS_RDONLY))
+				add->perm = AuBrPerm_RW;
+		}
+		opt->type = Opt_add;
+		goto out;
+	}
+	pr_err("lookup failed %s (%d)\n", add->pathname, err);
+	err = -EINVAL;
+
+ out:
+	return err;
+}
+
+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
+{
+	int err;
+
+	del->pathname = args[0].from;
+	AuDbg("del path %s\n", del->pathname);
+
+	err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
+	if (unlikely(err))
+		pr_err("lookup failed %s (%d)\n", del->pathname, err);
+
+	return err;
+}
+
+#if 0 /* reserved for future use */
+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
+			      struct au_opt_del *del, substring_t args[])
+{
+	int err;
+	struct dentry *root;
+
+	err = -EINVAL;
+	root = sb->s_root;
+	aufs_read_lock(root, AuLock_FLUSH);
+	if (bindex < 0 || au_sbend(sb) < bindex) {
+		pr_err("out of bounds, %d\n", bindex);
+		goto out;
+	}
+
+	err = 0;
+	del->h_path.dentry = dget(au_h_dptr(root, bindex));
+	del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
+
+ out:
+	aufs_read_unlock(root, !AuLock_IR);
+	return err;
+}
+#endif
+
+static int noinline_for_stack
+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
+{
+	int err;
+	struct path path;
+	char *p;
+
+	err = -EINVAL;
+	mod->path = args[0].from;
+	p = strchr(mod->path, '=');
+	if (unlikely(!p)) {
+		pr_err("no permssion %s\n", args[0].from);
+		goto out;
+	}
+
+	*p++ = 0;
+	err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
+	if (unlikely(err)) {
+		pr_err("lookup failed %s (%d)\n", mod->path, err);
+		goto out;
+	}
+
+	mod->perm = br_perm_val(p);
+	AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
+	mod->h_root = dget(path.dentry);
+	path_put(&path);
+
+ out:
+	return err;
+}
+
+#if 0 /* reserved for future use */
+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
+			      struct au_opt_mod *mod, substring_t args[])
+{
+	int err;
+	struct dentry *root;
+
+	err = -EINVAL;
+	root = sb->s_root;
+	aufs_read_lock(root, AuLock_FLUSH);
+	if (bindex < 0 || au_sbend(sb) < bindex) {
+		pr_err("out of bounds, %d\n", bindex);
+		goto out;
+	}
+
+	err = 0;
+	mod->perm = br_perm_val(args[1].from);
+	AuDbg("mod path %s, perm 0x%x, %s\n",
+	      mod->path, mod->perm, args[1].from);
+	mod->h_root = dget(au_h_dptr(root, bindex));
+
+ out:
+	aufs_read_unlock(root, !AuLock_IR);
+	return err;
+}
+#endif
+
+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
+			      substring_t args[])
+{
+	int err;
+	struct file *file;
+
+	file = au_xino_create(sb, args[0].from, /*silent*/0);
+	err = PTR_ERR(file);
+	if (IS_ERR(file))
+		goto out;
+
+	err = -EINVAL;
+	if (unlikely(file->f_dentry->d_sb == sb)) {
+		fput(file);
+		pr_err("%s must be outside\n", args[0].from);
+		goto out;
+	}
+
+	err = 0;
+	xino->file = file;
+	xino->path = args[0].from;
+
+ out:
+	return err;
+}
+
+static int noinline_for_stack
+au_opts_parse_xino_itrunc_path(struct super_block *sb,
+			       struct au_opt_xino_itrunc *xino_itrunc,
+			       substring_t args[])
+{
+	int err;
+	aufs_bindex_t bend, bindex;
+	struct path path;
+	struct dentry *root;
+
+	err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
+	if (unlikely(err)) {
+		pr_err("lookup failed %s (%d)\n", args[0].from, err);
+		goto out;
+	}
+
+	xino_itrunc->bindex = -1;
+	root = sb->s_root;
+	aufs_read_lock(root, AuLock_FLUSH);
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex <= bend; bindex++) {
+		if (au_h_dptr(root, bindex) == path.dentry) {
+			xino_itrunc->bindex = bindex;
+			break;
+		}
+	}
+	aufs_read_unlock(root, !AuLock_IR);
+	path_put(&path);
+
+	if (unlikely(xino_itrunc->bindex < 0)) {
+		pr_err("no such branch %s\n", args[0].from);
+		err = -EINVAL;
+	}
+
+ out:
+	return err;
+}
+
+/* called without aufs lock */
+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
+{
+	int err, n, token;
+	aufs_bindex_t bindex;
+	unsigned char skipped;
+	struct dentry *root;
+	struct au_opt *opt, *opt_tail;
+	char *opt_str;
+	/* reduce the stack space */
+	union {
+		struct au_opt_xino_itrunc *xino_itrunc;
+		struct au_opt_wbr_create *create;
+	} u;
+	struct {
+		substring_t args[MAX_OPT_ARGS];
+	} *a;
+
+	err = -ENOMEM;
+	a = kmalloc(sizeof(*a), GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	root = sb->s_root;
+	err = 0;
+	bindex = 0;
+	opt = opts->opt;
+	opt_tail = opt + opts->max_opt - 1;
+	opt->type = Opt_tail;
+	while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
+		err = -EINVAL;
+		skipped = 0;
+		token = match_token(opt_str, options, a->args);
+		switch (token) {
+		case Opt_br:
+			err = 0;
+			while (!err && (opt_str = strsep(&a->args[0].from, ":"))
+			       && *opt_str) {
+				err = opt_add(opt, opt_str, opts->sb_flags,
+					      bindex++);
+				if (unlikely(!err && ++opt > opt_tail)) {
+					err = -E2BIG;
+					break;
+				}
+				opt->type = Opt_tail;
+				skipped = 1;
+			}
+			break;
+		case Opt_add:
+			if (unlikely(match_int(&a->args[0], &n))) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			bindex = n;
+			err = opt_add(opt, a->args[1].from, opts->sb_flags,
+				      bindex);
+			if (!err)
+				opt->type = token;
+			break;
+		case Opt_append:
+			err = opt_add(opt, a->args[0].from, opts->sb_flags,
+				      /*dummy bindex*/1);
+			if (!err)
+				opt->type = token;
+			break;
+		case Opt_prepend:
+			err = opt_add(opt, a->args[0].from, opts->sb_flags,
+				      /*bindex*/0);
+			if (!err)
+				opt->type = token;
+			break;
+		case Opt_del:
+			err = au_opts_parse_del(&opt->del, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+#if 0 /* reserved for future use */
+		case Opt_idel:
+			del->pathname = "(indexed)";
+			if (unlikely(match_int(&args[0], &n))) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			err = au_opts_parse_idel(sb, n, &opt->del, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+#endif
+		case Opt_mod:
+			err = au_opts_parse_mod(&opt->mod, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+#ifdef IMOD /* reserved for future use */
+		case Opt_imod:
+			u.mod->path = "(indexed)";
+			if (unlikely(match_int(&a->args[0], &n))) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+#endif
+		case Opt_xino:
+			err = au_opts_parse_xino(sb, &opt->xino, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+
+		case Opt_trunc_xino_path:
+			err = au_opts_parse_xino_itrunc_path
+				(sb, &opt->xino_itrunc, a->args);
+			if (!err)
+				opt->type = token;
+			break;
+
+		case Opt_itrunc_xino:
+			u.xino_itrunc = &opt->xino_itrunc;
+			if (unlikely(match_int(&a->args[0], &n))) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			u.xino_itrunc->bindex = n;
+			aufs_read_lock(root, AuLock_FLUSH);
+			if (n < 0 || au_sbend(sb) < n) {
+				pr_err("out of bounds, %d\n", n);
+				aufs_read_unlock(root, !AuLock_IR);
+				break;
+			}
+			aufs_read_unlock(root, !AuLock_IR);
+			err = 0;
+			opt->type = token;
+			break;
+
+		case Opt_dirwh:
+			if (unlikely(match_int(&a->args[0], &opt->dirwh)))
+				break;
+			err = 0;
+			opt->type = token;
+			break;
+
+		case Opt_rdcache:
+			if (unlikely(match_int(&a->args[0], &opt->rdcache)))
+				break;
+			err = 0;
+			opt->type = token;
+			break;
+		case Opt_rdblk:
+			if (unlikely(match_int(&a->args[0], &n)
+				     || n < 0
+				     || n > KMALLOC_MAX_SIZE)) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			if (unlikely(n && n < NAME_MAX)) {
+				pr_err("rdblk must be larger than %d\n",
+				       NAME_MAX);
+				break;
+			}
+			opt->rdblk = n;
+			err = 0;
+			opt->type = token;
+			break;
+		case Opt_rdhash:
+			if (unlikely(match_int(&a->args[0], &n)
+				     || n < 0
+				     || n * sizeof(struct hlist_head)
+				     > KMALLOC_MAX_SIZE)) {
+				pr_err("bad integer in %s\n", opt_str);
+				break;
+			}
+			opt->rdhash = n;
+			err = 0;
+			opt->type = token;
+			break;
+
+		case Opt_trunc_xino:
+		case Opt_notrunc_xino:
+		case Opt_noxino:
+		case Opt_trunc_xib:
+		case Opt_notrunc_xib:
+		case Opt_shwh:
+		case Opt_noshwh:
+		case Opt_plink:
+		case Opt_noplink:
+		case Opt_list_plink:
+		case Opt_diropq_a:
+		case Opt_diropq_w:
+		case Opt_warn_perm:
+		case Opt_nowarn_perm:
+		case Opt_refrof:
+		case Opt_norefrof:
+		case Opt_verbose:
+		case Opt_noverbose:
+		case Opt_sum:
+		case Opt_nosum:
+		case Opt_wsum:
+		case Opt_rdblk_def:
+		case Opt_rdhash_def:
+			err = 0;
+			opt->type = token;
+			break;
+
+		case Opt_udba:
+			opt->udba = udba_val(a->args[0].from);
+			if (opt->udba >= 0) {
+				err = 0;
+				opt->type = token;
+			} else
+				pr_err("wrong value, %s\n", opt_str);
+			break;
+
+		case Opt_wbr_create:
+			u.create = &opt->wbr_create;
+			u.create->wbr_create
+				= au_wbr_create_val(a->args[0].from, u.create);
+			if (u.create->wbr_create >= 0) {
+				err = 0;
+				opt->type = token;
+			} else
+				pr_err("wrong value, %s\n", opt_str);
+			break;
+		case Opt_wbr_copyup:
+			opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
+			if (opt->wbr_copyup >= 0) {
+				err = 0;
+				opt->type = token;
+			} else
+				pr_err("wrong value, %s\n", opt_str);
+			break;
+
+		case Opt_ignore:
+			pr_warning("ignored %s\n", opt_str);
+			/*FALLTHROUGH*/
+		case Opt_ignore_silent:
+			skipped = 1;
+			err = 0;
+			break;
+		case Opt_err:
+			pr_err("unknown option %s\n", opt_str);
+			break;
+		}
+
+		if (!err && !skipped) {
+			if (unlikely(++opt > opt_tail)) {
+				err = -E2BIG;
+				opt--;
+				opt->type = Opt_tail;
+				break;
+			}
+			opt->type = Opt_tail;
+		}
+	}
+
+	kfree(a);
+	dump_opts(opts);
+	if (unlikely(err))
+		au_opts_free(opts);
+
+ out:
+	return err;
+}
+
+static int au_opt_wbr_create(struct super_block *sb,
+			     struct au_opt_wbr_create *create)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	err = 1; /* handled */
+	sbinfo = au_sbi(sb);
+	if (sbinfo->si_wbr_create_ops->fin) {
+		err = sbinfo->si_wbr_create_ops->fin(sb);
+		if (!err)
+			err = 1;
+	}
+
+	sbinfo->si_wbr_create = create->wbr_create;
+	sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
+	switch (create->wbr_create) {
+	case AuWbrCreate_MFSRRV:
+	case AuWbrCreate_MFSRR:
+		sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
+		/*FALLTHROUGH*/
+	case AuWbrCreate_MFS:
+	case AuWbrCreate_MFSV:
+	case AuWbrCreate_PMFS:
+	case AuWbrCreate_PMFSV:
+		sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
+		break;
+	}
+
+	if (sbinfo->si_wbr_create_ops->init)
+		sbinfo->si_wbr_create_ops->init(sb); /* ignore */
+
+	return err;
+}
+
+/*
+ * returns,
+ * plus: processed without an error
+ * zero: unprocessed
+ */
+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
+			 struct au_opts *opts)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	err = 1; /* handled */
+	sbinfo = au_sbi(sb);
+	switch (opt->type) {
+	case Opt_udba:
+		sbinfo->si_mntflags &= ~AuOptMask_UDBA;
+		sbinfo->si_mntflags |= opt->udba;
+		opts->given_udba |= opt->udba;
+		break;
+
+	case Opt_plink:
+		au_opt_set(sbinfo->si_mntflags, PLINK);
+		break;
+	case Opt_noplink:
+		if (au_opt_test(sbinfo->si_mntflags, PLINK))
+			au_plink_put(sb);
+		au_opt_clr(sbinfo->si_mntflags, PLINK);
+		break;
+	case Opt_list_plink:
+		if (au_opt_test(sbinfo->si_mntflags, PLINK))
+			au_plink_list(sb);
+		break;
+
+	case Opt_diropq_a:
+		au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
+		break;
+	case Opt_diropq_w:
+		au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
+		break;
+
+	case Opt_warn_perm:
+		au_opt_set(sbinfo->si_mntflags, WARN_PERM);
+		break;
+	case Opt_nowarn_perm:
+		au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
+		break;
+
+	case Opt_refrof:
+		au_opt_set(sbinfo->si_mntflags, REFROF);
+		break;
+	case Opt_norefrof:
+		au_opt_clr(sbinfo->si_mntflags, REFROF);
+		break;
+
+	case Opt_verbose:
+		au_opt_set(sbinfo->si_mntflags, VERBOSE);
+		break;
+	case Opt_noverbose:
+		au_opt_clr(sbinfo->si_mntflags, VERBOSE);
+		break;
+
+	case Opt_sum:
+		au_opt_set(sbinfo->si_mntflags, SUM);
+		break;
+	case Opt_wsum:
+		au_opt_clr(sbinfo->si_mntflags, SUM);
+		au_opt_set(sbinfo->si_mntflags, SUM_W);
+	case Opt_nosum:
+		au_opt_clr(sbinfo->si_mntflags, SUM);
+		au_opt_clr(sbinfo->si_mntflags, SUM_W);
+		break;
+
+	case Opt_wbr_create:
+		err = au_opt_wbr_create(sb, &opt->wbr_create);
+		break;
+	case Opt_wbr_copyup:
+		sbinfo->si_wbr_copyup = opt->wbr_copyup;
+		sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
+		break;
+
+	case Opt_dirwh:
+		sbinfo->si_dirwh = opt->dirwh;
+		break;
+
+	case Opt_rdcache:
+		sbinfo->si_rdcache = opt->rdcache * HZ;
+		break;
+	case Opt_rdblk:
+		sbinfo->si_rdblk = opt->rdblk;
+		break;
+	case Opt_rdblk_def:
+		sbinfo->si_rdblk = AUFS_RDBLK_DEF;
+		break;
+	case Opt_rdhash:
+		sbinfo->si_rdhash = opt->rdhash;
+		break;
+	case Opt_rdhash_def:
+		sbinfo->si_rdhash = AUFS_RDHASH_DEF;
+		break;
+
+	case Opt_shwh:
+		au_opt_set(sbinfo->si_mntflags, SHWH);
+		break;
+	case Opt_noshwh:
+		au_opt_clr(sbinfo->si_mntflags, SHWH);
+		break;
+
+	case Opt_trunc_xino:
+		au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
+		break;
+	case Opt_notrunc_xino:
+		au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
+		break;
+
+	case Opt_trunc_xino_path:
+	case Opt_itrunc_xino:
+		err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
+		if (!err)
+			err = 1;
+		break;
+
+	case Opt_trunc_xib:
+		au_fset_opts(opts->flags, TRUNC_XIB);
+		break;
+	case Opt_notrunc_xib:
+		au_fclr_opts(opts->flags, TRUNC_XIB);
+		break;
+
+	default:
+		err = 0;
+		break;
+	}
+
+	return err;
+}
+
+/*
+ * returns tri-state.
+ * plus: processed without an error
+ * zero: unprocessed
+ * minus: error
+ */
+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
+		     struct au_opts *opts)
+{
+	int err, do_refresh;
+
+	err = 0;
+	switch (opt->type) {
+	case Opt_append:
+		opt->add.bindex = au_sbend(sb) + 1;
+		if (opt->add.bindex < 0)
+			opt->add.bindex = 0;
+		goto add;
+	case Opt_prepend:
+		opt->add.bindex = 0;
+	add:
+	case Opt_add:
+		err = au_br_add(sb, &opt->add,
+				au_ftest_opts(opts->flags, REMOUNT));
+		if (!err) {
+			err = 1;
+			au_fset_opts(opts->flags, REFRESH_DIR);
+			if (au_br_whable(opt->add.perm))
+				au_fset_opts(opts->flags, REFRESH_NONDIR);
+		}
+		break;
+
+	case Opt_del:
+	case Opt_idel:
+		err = au_br_del(sb, &opt->del,
+				au_ftest_opts(opts->flags, REMOUNT));
+		if (!err) {
+			err = 1;
+			au_fset_opts(opts->flags, TRUNC_XIB);
+			au_fset_opts(opts->flags, REFRESH_DIR);
+			au_fset_opts(opts->flags, REFRESH_NONDIR);
+		}
+		break;
+
+	case Opt_mod:
+	case Opt_imod:
+		err = au_br_mod(sb, &opt->mod,
+				au_ftest_opts(opts->flags, REMOUNT),
+				&do_refresh);
+		if (!err) {
+			err = 1;
+			if (do_refresh) {
+				au_fset_opts(opts->flags, REFRESH_DIR);
+				au_fset_opts(opts->flags, REFRESH_NONDIR);
+			}
+		}
+		break;
+	}
+
+	return err;
+}
+
+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
+		       struct au_opt_xino **opt_xino,
+		       struct au_opts *opts)
+{
+	int err;
+	aufs_bindex_t bend, bindex;
+	struct dentry *root, *parent, *h_root;
+
+	err = 0;
+	switch (opt->type) {
+	case Opt_xino:
+		err = au_xino_set(sb, &opt->xino,
+				  !!au_ftest_opts(opts->flags, REMOUNT));
+		if (unlikely(err))
+			break;
+
+		*opt_xino = &opt->xino;
+		au_xino_brid_set(sb, -1);
+
+		/* safe d_parent access */
+		parent = opt->xino.file->f_dentry->d_parent;
+		root = sb->s_root;
+		bend = au_sbend(sb);
+		for (bindex = 0; bindex <= bend; bindex++) {
+			h_root = au_h_dptr(root, bindex);
+			if (h_root == parent) {
+				au_xino_brid_set(sb, au_sbr_id(sb, bindex));
+				break;
+			}
+		}
+		break;
+
+	case Opt_noxino:
+		au_xino_clr(sb);
+		au_xino_brid_set(sb, -1);
+		*opt_xino = (void *)-1;
+		break;
+	}
+
+	return err;
+}
+
+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
+		   unsigned int pending)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	unsigned char do_plink, skip, do_free;
+	struct au_branch *br;
+	struct au_wbr *wbr;
+	struct dentry *root;
+	struct inode *dir, *h_dir;
+	struct au_sbinfo *sbinfo;
+	struct au_hinode *hdir;
+
+	SiMustAnyLock(sb);
+
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
+
+	if (!(sb_flags & MS_RDONLY)) {
+		if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
+			pr_warning("first branch should be rw\n");
+		if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
+			pr_warning("shwh should be used with ro\n");
+	}
+
+	if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
+	    && !au_opt_test(sbinfo->si_mntflags, XINO))
+		pr_warning("udba=inotify requires xino\n");
+
+	err = 0;
+	root = sb->s_root;
+	dir = sb->s_root->d_inode;
+	do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
+	bend = au_sbend(sb);
+	for (bindex = 0; !err && bindex <= bend; bindex++) {
+		skip = 0;
+		h_dir = au_h_iptr(dir, bindex);
+		br = au_sbr(sb, bindex);
+		do_free = 0;
+
+		wbr = br->br_wbr;
+		if (wbr)
+			wbr_wh_read_lock(wbr);
+
+		switch (br->br_perm) {
+		case AuBrPerm_RO:
+		case AuBrPerm_ROWH:
+		case AuBrPerm_RR:
+		case AuBrPerm_RRWH:
+			do_free = !!wbr;
+			skip = (!wbr
+				|| (!wbr->wbr_whbase
+				    && !wbr->wbr_plink
+				    && !wbr->wbr_orph));
+			break;
+
+		case AuBrPerm_RWNoLinkWH:
+			/* skip = (!br->br_whbase && !br->br_orph); */
+			skip = (!wbr || !wbr->wbr_whbase);
+			if (skip && wbr) {
+				if (do_plink)
+					skip = !!wbr->wbr_plink;
+				else
+					skip = !wbr->wbr_plink;
+			}
+			break;
+
+		case AuBrPerm_RW:
+			/* skip = (br->br_whbase && br->br_ohph); */
+			skip = (wbr && wbr->wbr_whbase);
+			if (skip) {
+				if (do_plink)
+					skip = !!wbr->wbr_plink;
+				else
+					skip = !wbr->wbr_plink;
+			}
+			break;
+
+		default:
+			BUG();
+		}
+		if (wbr)
+			wbr_wh_read_unlock(wbr);
+
+		if (skip)
+			continue;
+
+		hdir = au_hi(dir, bindex);
+		au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
+		if (wbr)
+			wbr_wh_write_lock(wbr);
+		err = au_wh_init(au_h_dptr(root, bindex), br, sb);
+		if (wbr)
+			wbr_wh_write_unlock(wbr);
+		au_hin_imtx_unlock(hdir);
+
+		if (!err && do_free) {
+			kfree(wbr);
+			br->br_wbr = NULL;
+		}
+	}
+
+	return err;
+}
+
+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
+{
+	int err;
+	unsigned int tmp;
+	aufs_bindex_t bend;
+	struct au_opt *opt;
+	struct au_opt_xino *opt_xino, xino;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	err = 0;
+	opt_xino = NULL;
+	opt = opts->opt;
+	while (err >= 0 && opt->type != Opt_tail)
+		err = au_opt_simple(sb, opt++, opts);
+	if (err > 0)
+		err = 0;
+	else if (unlikely(err < 0))
+		goto out;
+
+	/* disable xino and udba temporary */
+	sbinfo = au_sbi(sb);
+	tmp = sbinfo->si_mntflags;
+	au_opt_clr(sbinfo->si_mntflags, XINO);
+	au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
+
+	opt = opts->opt;
+	while (err >= 0 && opt->type != Opt_tail)
+		err = au_opt_br(sb, opt++, opts);
+	if (err > 0)
+		err = 0;
+	else if (unlikely(err < 0))
+		goto out;
+
+	bend = au_sbend(sb);
+	if (unlikely(bend < 0)) {
+		err = -EINVAL;
+		pr_err("no branches\n");
+		goto out;
+	}
+
+	if (au_opt_test(tmp, XINO))
+		au_opt_set(sbinfo->si_mntflags, XINO);
+	opt = opts->opt;
+	while (!err && opt->type != Opt_tail)
+		err = au_opt_xino(sb, opt++, &opt_xino, opts);
+	if (unlikely(err))
+		goto out;
+
+	err = au_opts_verify(sb, sb->s_flags, tmp);
+	if (unlikely(err))
+		goto out;
+
+	/* restore xino */
+	if (au_opt_test(tmp, XINO) && !opt_xino) {
+		xino.file = au_xino_def(sb);
+		err = PTR_ERR(xino.file);
+		if (IS_ERR(xino.file))
+			goto out;
+
+		err = au_xino_set(sb, &xino, /*remount*/0);
+		fput(xino.file);
+		if (unlikely(err))
+			goto out;
+	}
+
+	/* restore udba */
+	sbinfo->si_mntflags &= ~AuOptMask_UDBA;
+	sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
+	if (au_opt_test(tmp, UDBA_HINOTIFY)) {
+		struct inode *dir = sb->s_root->d_inode;
+		au_reset_hinotify(dir,
+				  au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
+	}
+
+ out:
+	return err;
+}
+
+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
+{
+	int err, rerr;
+	struct inode *dir;
+	struct au_opt_xino *opt_xino;
+	struct au_opt *opt;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	dir = sb->s_root->d_inode;
+	sbinfo = au_sbi(sb);
+	err = 0;
+	opt_xino = NULL;
+	opt = opts->opt;
+	while (err >= 0 && opt->type != Opt_tail) {
+		err = au_opt_simple(sb, opt, opts);
+		if (!err)
+			err = au_opt_br(sb, opt, opts);
+		if (!err)
+			err = au_opt_xino(sb, opt, &opt_xino, opts);
+		opt++;
+	}
+	if (err > 0)
+		err = 0;
+	AuTraceErr(err);
+	/* go on even err */
+
+	rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
+	if (unlikely(rerr && !err))
+		err = rerr;
+
+	if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
+		rerr = au_xib_trunc(sb);
+		if (unlikely(rerr && !err))
+			err = rerr;
+	}
+
+	/* will be handled by the caller */
+	if (!au_ftest_opts(opts->flags, REFRESH_DIR)
+	    && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
+		au_fset_opts(opts->flags, REFRESH_DIR);
+
+	AuDbg("status 0x%x\n", opts->flags);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+unsigned int au_opt_udba(struct super_block *sb)
+{
+	return au_mntflags(sb) & AuOptMask_UDBA;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/conf.mk
+++ linux-ec2-2.6.32/ubuntu/aufs/conf.mk
@@ -0,0 +1,31 @@
+
+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
+
+define AuConf
+ifdef ${1}
+AuConfStr += ${1}=${${1}}
+endif
+endef
+
+$(foreach i, BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
+	HINOTIFY \
+	EXPORT INO_T_64 \
+	RDU \
+	SHWH \
+	BR_RAMFS \
+	BR_FUSE POLL \
+	BDEV_LOOP \
+	DEBUG MAGIC_SYSRQ, \
+	$(eval $(call AuConf,CONFIG_AUFS_${i})))
+
+AuConfName = ${obj}/conf.str
+${AuConfName}.tmp: FORCE
+	@echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
+${AuConfName}: ${AuConfName}.tmp
+	@diff -q $< $@ > /dev/null 2>&1 || { \
+	echo '  GEN    ' $@; \
+	cp -p $< $@; \
+	}
+FORCE:
+clean-files += ${AuConfName} ${AuConfName}.tmp
+${obj}/sysfs.o: ${AuConfName}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/vfsub.h
+++ linux-ec2-2.6.32/ubuntu/aufs/vfsub.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sub-routines for VFS
+ */
+
+#ifndef __AUFS_VFSUB_H__
+#define __AUFS_VFSUB_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/fs_stack.h>
+
+/* ---------------------------------------------------------------------- */
+
+/* lock subclass for lower inode */
+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
+/* reduce? gave up. */
+enum {
+	AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
+	AuLsc_I_PARENT,		/* lower inode, parent first */
+	AuLsc_I_PARENT2,	/* copyup dirs */
+	AuLsc_I_PARENT3,	/* copyup wh */
+	AuLsc_I_CHILD,
+	AuLsc_I_CHILD2,
+	AuLsc_I_End
+};
+
+/* to debug easier, do not make them inlined functions */
+#define MtxMustLock(mtx)	AuDebugOn(!mutex_is_locked(mtx))
+#define IMustLock(i)		MtxMustLock(&(i)->i_mutex)
+
+/* ---------------------------------------------------------------------- */
+
+static inline void vfsub_copy_inode_size(struct inode *inode,
+					 struct inode *h_inode)
+{
+	spin_lock(&inode->i_lock);
+	fsstack_copy_inode_size(inode, h_inode);
+	spin_unlock(&inode->i_lock);
+}
+
+int vfsub_update_h_iattr(struct path *h_path, int *did);
+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
+struct file *vfsub_dentry_open(struct path *path, int flags,
+			       const struct cred *cred);
+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
+				    int len);
+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
+
+/* ---------------------------------------------------------------------- */
+
+struct au_hinode;
+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
+				 struct dentry *d2, struct au_hinode *hdir2);
+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
+			 struct dentry *d2, struct au_hinode *hdir2);
+
+int vfsub_create(struct inode *dir, struct path *path, int mode);
+int vfsub_symlink(struct inode *dir, struct path *path,
+		  const char *symname);
+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
+	       struct path *path);
+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
+		 struct inode *hdir, struct path *path);
+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
+int vfsub_rmdir(struct inode *dir, struct path *path);
+
+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
+int vfsub_notify_change(struct path *path, struct iattr *ia);
+int vfsub_unlink(struct inode *dir, struct path *path, int force);
+
+/* ---------------------------------------------------------------------- */
+
+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
+		     loff_t *ppos);
+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
+			loff_t *ppos);
+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
+		      loff_t *ppos);
+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
+		      loff_t *ppos);
+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
+
+long vfsub_splice_to(struct file *in, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t len,
+		     unsigned int flags);
+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
+		       loff_t *ppos, size_t len, unsigned int flags);
+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
+		struct file *h_file);
+
+static inline void vfsub_file_accessed(struct file *h_file)
+{
+	file_accessed(h_file);
+	vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
+}
+
+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
+				     struct dentry *h_dentry)
+{
+	struct path h_path = {
+		.dentry	= h_dentry,
+		.mnt	= h_mnt
+	};
+	touch_atime(h_mnt, h_dentry);
+	vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
+}
+
+/* ---------------------------------------------------------------------- */
+
+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
+{
+	loff_t err;
+
+	/* lockdep_off(); */
+	err = vfs_llseek(file, offset, origin);
+	/* lockdep_on(); */
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* dirty workaround for strict type of fmode_t */
+union vfsub_fmu {
+	fmode_t fm;
+	unsigned int ui;
+};
+
+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
+{
+	union vfsub_fmu u = {
+		.fm = fm
+	};
+
+	BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
+
+	return u.ui;
+}
+
+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
+{
+	union vfsub_fmu u = {
+		.ui = ui
+	};
+
+	return u.fm;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_VFSUB_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/super.c
+++ linux-ec2-2.6.32/ubuntu/aufs/super.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * mount and super_block operations
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/statfs.h>
+#include "aufs.h"
+
+/*
+ * super_operations
+ */
+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
+{
+	struct au_icntnr *c;
+
+	c = au_cache_alloc_icntnr();
+	if (c) {
+		inode_init_once(&c->vfs_inode);
+		c->vfs_inode.i_version = 1; /* sigen(sb); */
+		c->iinfo.ii_hinode = NULL;
+		return &c->vfs_inode;
+	}
+	return NULL;
+}
+
+static void aufs_destroy_inode(struct inode *inode)
+{
+	au_iinfo_fin(inode);
+	au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
+}
+
+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
+{
+	struct inode *inode;
+	int err;
+
+	inode = iget_locked(sb, ino);
+	if (unlikely(!inode)) {
+		inode = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+	if (!(inode->i_state & I_NEW))
+		goto out;
+
+	err = au_xigen_new(inode);
+	if (!err)
+		err = au_iinfo_init(inode);
+	if (!err)
+		inode->i_version++;
+	else {
+		iget_failed(inode);
+		inode = ERR_PTR(err);
+	}
+
+ out:
+	/* never return NULL */
+	AuDebugOn(!inode);
+	AuTraceErrPtr(inode);
+	return inode;
+}
+
+/* lock free root dinfo */
+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	struct path path;
+	struct au_hdentry *hd;
+	struct au_branch *br;
+
+	err = 0;
+	bend = au_sbend(sb);
+	hd = au_di(sb->s_root)->di_hdentry;
+	for (bindex = 0; !err && bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		path.mnt = br->br_mnt;
+		path.dentry = hd[bindex].hd_dentry;
+		err = au_seq_path(seq, &path);
+		if (err > 0)
+			err = seq_printf(seq, "=%s",
+					 au_optstr_br_perm(br->br_perm));
+		if (!err && bindex != bend)
+			err = seq_putc(seq, ':');
+	}
+
+	return err;
+}
+
+static void au_show_wbr_create(struct seq_file *m, int v,
+			       struct au_sbinfo *sbinfo)
+{
+	const char *pat;
+
+	AuRwMustAnyLock(&sbinfo->si_rwsem);
+
+	seq_printf(m, ",create=");
+	pat = au_optstr_wbr_create(v);
+	switch (v) {
+	case AuWbrCreate_TDP:
+	case AuWbrCreate_RR:
+	case AuWbrCreate_MFS:
+	case AuWbrCreate_PMFS:
+		seq_printf(m, pat);
+		break;
+	case AuWbrCreate_MFSV:
+		seq_printf(m, /*pat*/"mfs:%lu",
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	case AuWbrCreate_PMFSV:
+		seq_printf(m, /*pat*/"pmfs:%lu",
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	case AuWbrCreate_MFSRR:
+		seq_printf(m, /*pat*/"mfsrr:%llu",
+			   sbinfo->si_wbr_mfs.mfsrr_watermark);
+		break;
+	case AuWbrCreate_MFSRRV:
+		seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
+			   sbinfo->si_wbr_mfs.mfsrr_watermark,
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	}
+}
+
+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
+{
+#ifdef CONFIG_SYSFS
+	return 0;
+#else
+	int err;
+	const int len = sizeof(AUFS_XINO_FNAME) - 1;
+	aufs_bindex_t bindex, brid;
+	struct super_block *sb;
+	struct qstr *name;
+	struct file *f;
+	struct dentry *d, *h_root;
+
+	AuRwMustAnyLock(&sbinfo->si_rwsem);
+
+	err = 0;
+	sb = mnt->mnt_sb;
+	f = au_sbi(sb)->si_xib;
+	if (!f)
+		goto out;
+
+	/* stop printing the default xino path on the first writable branch */
+	h_root = NULL;
+	brid = au_xino_brid(sb);
+	if (brid >= 0) {
+		bindex = au_br_index(sb, brid);
+		h_root = au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
+	}
+	d = f->f_dentry;
+	name = &d->d_name;
+	/* safe ->d_parent because the file is unlinked */
+	if (d->d_parent == h_root
+	    && name->len == len
+	    && !memcmp(name->name, AUFS_XINO_FNAME, len))
+		goto out;
+
+	seq_puts(seq, ",xino=");
+	err = au_xino_path(seq, f);
+
+ out:
+	return err;
+#endif
+}
+
+/* seq_file will re-call me in case of too long string */
+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	int err, n;
+	unsigned int mnt_flags, v;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+
+#define AuBool(name, str) do { \
+	v = au_opt_test(mnt_flags, name); \
+	if (v != au_opt_test(AuOpt_Def, name)) \
+		seq_printf(m, ",%s" #str, v ? "" : "no"); \
+} while (0)
+
+#define AuStr(name, str) do { \
+	v = mnt_flags & AuOptMask_##name; \
+	if (v != (AuOpt_Def & AuOptMask_##name)) \
+		seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
+} while (0)
+
+#define AuUInt(name, str, val) do { \
+	if (val != AUFS_##name##_DEF) \
+		seq_printf(m, "," #str "=%u", val); \
+} while (0)
+
+	/* lock free root dinfo */
+	sb = mnt->mnt_sb;
+	si_noflush_read_lock(sb);
+	sbinfo = au_sbi(sb);
+	seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
+
+	mnt_flags = au_mntflags(sb);
+	if (au_opt_test(mnt_flags, XINO)) {
+		err = au_show_xino(m, mnt);
+		if (unlikely(err))
+			goto out;
+	} else
+		seq_puts(m, ",noxino");
+
+	AuBool(TRUNC_XINO, trunc_xino);
+	AuStr(UDBA, udba);
+	AuBool(SHWH, shwh);
+	AuBool(PLINK, plink);
+	/* AuBool(DIRPERM1, dirperm1); */
+	/* AuBool(REFROF, refrof); */
+
+	v = sbinfo->si_wbr_create;
+	if (v != AuWbrCreate_Def)
+		au_show_wbr_create(m, v, sbinfo);
+
+	v = sbinfo->si_wbr_copyup;
+	if (v != AuWbrCopyup_Def)
+		seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
+
+	v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
+	if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
+		seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
+
+	AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
+
+	n = sbinfo->si_rdcache / HZ;
+	AuUInt(RDCACHE, rdcache, n);
+
+	AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
+	AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
+
+	AuBool(SUM, sum);
+	/* AuBool(SUM_W, wsum); */
+	AuBool(WARN_PERM, warn_perm);
+	AuBool(VERBOSE, verbose);
+
+ out:
+	/* be sure to print "br:" last */
+	if (!sysaufs_brs) {
+		seq_puts(m, ",br:");
+		au_show_brs(m, sb);
+	}
+	si_read_unlock(sb);
+	return 0;
+
+#undef Deleted
+#undef AuBool
+#undef AuStr
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* sum mode which returns the summation for statfs(2) */
+
+static u64 au_add_till_max(u64 a, u64 b)
+{
+	u64 old;
+
+	old = a;
+	a += b;
+	if (old < a)
+		return a;
+	return ULLONG_MAX;
+}
+
+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
+{
+	int err;
+	u64 blocks, bfree, bavail, files, ffree;
+	aufs_bindex_t bend, bindex, i;
+	unsigned char shared;
+	struct vfsmount *h_mnt;
+	struct super_block *h_sb;
+
+	blocks = 0;
+	bfree = 0;
+	bavail = 0;
+	files = 0;
+	ffree = 0;
+
+	err = 0;
+	bend = au_sbend(sb);
+	for (bindex = bend; bindex >= 0; bindex--) {
+		h_mnt = au_sbr_mnt(sb, bindex);
+		h_sb = h_mnt->mnt_sb;
+		shared = 0;
+		for (i = bindex + 1; !shared && i <= bend; i++)
+			shared = (au_sbr_sb(sb, i) == h_sb);
+		if (shared)
+			continue;
+
+		/* sb->s_root for NFS is unreliable */
+		err = vfs_statfs(h_mnt->mnt_root, buf);
+		if (unlikely(err))
+			goto out;
+
+		blocks = au_add_till_max(blocks, buf->f_blocks);
+		bfree = au_add_till_max(bfree, buf->f_bfree);
+		bavail = au_add_till_max(bavail, buf->f_bavail);
+		files = au_add_till_max(files, buf->f_files);
+		ffree = au_add_till_max(ffree, buf->f_ffree);
+	}
+
+	buf->f_blocks = blocks;
+	buf->f_bfree = bfree;
+	buf->f_bavail = bavail;
+	buf->f_files = files;
+	buf->f_ffree = ffree;
+
+ out:
+	return err;
+}
+
+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	int err;
+	struct super_block *sb;
+
+	/* lock free root dinfo */
+	sb = dentry->d_sb;
+	si_noflush_read_lock(sb);
+	if (!au_opt_test(au_mntflags(sb), SUM))
+		/* sb->s_root for NFS is unreliable */
+		err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
+	else
+		err = au_statfs_sum(sb, buf);
+	si_read_unlock(sb);
+
+	if (!err) {
+		buf->f_type = AUFS_SUPER_MAGIC;
+		buf->f_namelen = AUFS_MAX_NAMELEN;
+		memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
+	}
+	/* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* try flushing the lower fs at aufs remount/unmount time */
+
+static void au_fsync_br(struct super_block *sb)
+{
+	aufs_bindex_t bend, bindex;
+	int brperm;
+	struct au_branch *br;
+	struct super_block *h_sb;
+
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex < bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		brperm = br->br_perm;
+		if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
+			continue;
+		h_sb = br->br_mnt->mnt_sb;
+		if (bdev_read_only(h_sb->s_bdev))
+			continue;
+
+		/* lockdep_off(); */
+		down_write(&h_sb->s_umount);
+		shrink_dcache_sb(h_sb);
+		sync_filesystem(h_sb);
+		up_write(&h_sb->s_umount);
+		/* lockdep_on(); */
+	}
+}
+
+/*
+ * this IS NOT for super_operations.
+ * I guess it will be reverted someday.
+ */
+static void aufs_umount_begin(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	sbinfo = au_sbi(sb);
+	if (!sbinfo)
+		return;
+
+	si_write_lock(sb);
+	au_fsync_br(sb);
+	if (au_opt_test(au_mntflags(sb), PLINK))
+		au_plink_put(sb);
+	if (sbinfo->si_wbr_create_ops->fin)
+		sbinfo->si_wbr_create_ops->fin(sb);
+	si_write_unlock(sb);
+}
+
+/* final actions when unmounting a file system */
+static void aufs_put_super(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	sbinfo = au_sbi(sb);
+	if (!sbinfo)
+		return;
+
+	aufs_umount_begin(sb);
+	dbgaufs_si_fin(sbinfo);
+	kobject_put(&sbinfo->si_kobj);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * refresh dentry and inode at remount time.
+ */
+static int do_refresh(struct dentry *dentry, mode_t type,
+		      unsigned int dir_flags)
+{
+	int err;
+	struct dentry *parent;
+
+	di_write_lock_child(dentry);
+	parent = dget_parent(dentry);
+	di_read_lock_parent(parent, AuLock_IR);
+
+	/* returns the number of positive dentries */
+	err = au_refresh_hdentry(dentry, type);
+	if (err >= 0) {
+		struct inode *inode = dentry->d_inode;
+		err = au_refresh_hinode(inode, dentry);
+		if (!err && type == S_IFDIR)
+			au_reset_hinotify(inode, dir_flags);
+	}
+	if (unlikely(err))
+		pr_err("unrecoverable error %d, %.*s\n",
+		       err, AuDLNPair(dentry));
+
+	di_read_unlock(parent, AuLock_IR);
+	dput(parent);
+	di_write_unlock(dentry);
+
+	return err;
+}
+
+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
+{
+	return S_ISDIR(dentry->d_inode->i_mode);
+}
+
+/* gave up consolidating with refresh_nondir() */
+static int refresh_dir(struct dentry *root, unsigned int sigen)
+{
+	int err, i, j, ndentry, e;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+	struct inode *inode;
+	const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
+
+	err = 0;
+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
+		if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
+			ii_write_lock_child(inode);
+			e = au_refresh_hinode_self(inode, /*do_attr*/1);
+			ii_write_unlock(inode);
+			if (unlikely(e)) {
+				AuDbg("e %d, i%lu\n", e, inode->i_ino);
+				if (!err)
+					err = e;
+				/* go on even if err */
+			}
+		}
+
+	e = au_dpages_init(&dpages, GFP_NOFS);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out;
+	}
+	e = au_dcsub_pages(&dpages, root, test_dir, NULL);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out_dpages;
+	}
+
+	for (i = 0; !e && i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		ndentry = dpage->ndentry;
+		for (j = 0; !e && j < ndentry; j++) {
+			struct dentry *d;
+
+			d = dentries[j];
+			au_dbg_verify_dir_parent(d, sigen);
+			if (au_digen(d) != sigen) {
+				e = do_refresh(d, S_IFDIR, flags);
+				if (unlikely(e && !err))
+					err = e;
+				/* break on err */
+			}
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	return err;
+}
+
+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
+{
+	return !S_ISDIR(dentry->d_inode->i_mode);
+}
+
+static int refresh_nondir(struct dentry *root, unsigned int sigen,
+			  int do_dentry)
+{
+	int err, i, j, ndentry, e;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+	struct inode *inode;
+
+	err = 0;
+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
+		if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
+			ii_write_lock_child(inode);
+			e = au_refresh_hinode_self(inode, /*do_attr*/1);
+			ii_write_unlock(inode);
+			if (unlikely(e)) {
+				AuDbg("e %d, i%lu\n", e, inode->i_ino);
+				if (!err)
+					err = e;
+				/* go on even if err */
+			}
+		}
+
+	if (!do_dentry)
+		goto out;
+
+	e = au_dpages_init(&dpages, GFP_NOFS);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out;
+	}
+	e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out_dpages;
+	}
+
+	for (i = 0; i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		ndentry = dpage->ndentry;
+		for (j = 0; j < ndentry; j++) {
+			struct dentry *d;
+
+			d = dentries[j];
+			au_dbg_verify_nondir_parent(d, sigen);
+			inode = d->d_inode;
+			if (inode && au_digen(d) != sigen) {
+				e = do_refresh(d, inode->i_mode & S_IFMT,
+					       /*dir_flags*/0);
+				if (unlikely(e && !err))
+					err = e;
+				/* go on even err */
+			}
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	return err;
+}
+
+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
+{
+	int err;
+	unsigned int sigen;
+	struct au_sbinfo *sbinfo;
+	struct dentry *root;
+	struct inode *inode;
+
+	au_sigen_inc(sb);
+	sigen = au_sigen(sb);
+	sbinfo = au_sbi(sb);
+	au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
+
+	root = sb->s_root;
+	DiMustNoWaiters(root);
+	inode = root->d_inode;
+	IiMustNoWaiters(inode);
+	au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
+	di_write_unlock(root);
+
+	err = refresh_dir(root, sigen);
+	if (unlikely(err)) {
+		au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
+		pr_warning("Refreshing directories failed, ignored (%d)\n",
+			   err);
+	}
+
+	if (au_ftest_opts(flags, REFRESH_NONDIR)) {
+		err = refresh_nondir(root, sigen, !err);
+		if (unlikely(err))
+			pr_warning("Refreshing non-directories failed, ignored"
+				   "(%d)\n", err);
+	}
+
+	/* aufs_write_lock() calls ..._child() */
+	di_write_lock_child(root);
+	au_cpup_attr_all(root->d_inode, /*force*/1);
+}
+
+/* stop extra interpretation of errno in mount(8), and strange error messages */
+static int cvt_err(int err)
+{
+	AuTraceErr(err);
+
+	switch (err) {
+	case -ENOENT:
+	case -ENOTDIR:
+	case -EEXIST:
+	case -EIO:
+		err = -EINVAL;
+	}
+	return err;
+}
+
+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+	int err;
+	struct au_opts opts;
+	struct dentry *root;
+	struct inode *inode;
+	struct au_sbinfo *sbinfo;
+
+	err = 0;
+	root = sb->s_root;
+	if (!data || !*data) {
+		aufs_write_lock(root);
+		err = au_opts_verify(sb, *flags, /*pending*/0);
+		if (!err)
+			au_fsync_br(sb);
+		aufs_write_unlock(root);
+		goto out;
+	}
+
+	err = -ENOMEM;
+	memset(&opts, 0, sizeof(opts));
+	opts.opt = (void *)__get_free_page(GFP_NOFS);
+	if (unlikely(!opts.opt))
+		goto out;
+	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
+	opts.flags = AuOpts_REMOUNT;
+	opts.sb_flags = *flags;
+
+	/* parse it before aufs lock */
+	err = au_opts_parse(sb, data, &opts);
+	if (unlikely(err))
+		goto out_opts;
+
+	sbinfo = au_sbi(sb);
+	inode = root->d_inode;
+	mutex_lock(&inode->i_mutex);
+	aufs_write_lock(root);
+	au_fsync_br(sb);
+
+	/* au_opts_remount() may return an error */
+	err = au_opts_remount(sb, &opts);
+	au_opts_free(&opts);
+
+	if (au_ftest_opts(opts.flags, REFRESH_DIR)
+	    || au_ftest_opts(opts.flags, REFRESH_NONDIR))
+		au_remount_refresh(sb, opts.flags);
+
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+
+ out_opts:
+	free_page((unsigned long)opts.opt);
+ out:
+	err = cvt_err(err);
+	AuTraceErr(err);
+	return err;
+}
+
+static const struct super_operations aufs_sop = {
+	.alloc_inode	= aufs_alloc_inode,
+	.destroy_inode	= aufs_destroy_inode,
+	.drop_inode	= generic_delete_inode,
+	.show_options	= aufs_show_options,
+	.statfs		= aufs_statfs,
+	.put_super	= aufs_put_super,
+	.remount_fs	= aufs_remount_fs
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int alloc_root(struct super_block *sb)
+{
+	int err;
+	struct inode *inode;
+	struct dentry *root;
+
+	err = -ENOMEM;
+	inode = au_iget_locked(sb, AUFS_ROOT_INO);
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		goto out;
+
+	inode->i_op = &aufs_dir_iop;
+	inode->i_fop = &aufs_dir_fop;
+	inode->i_mode = S_IFDIR;
+	inode->i_nlink = 2;
+	unlock_new_inode(inode);
+
+	root = d_alloc_root(inode);
+	if (unlikely(!root))
+		goto out_iput;
+	err = PTR_ERR(root);
+	if (IS_ERR(root))
+		goto out_iput;
+
+	err = au_alloc_dinfo(root);
+	if (!err) {
+		sb->s_root = root;
+		return 0; /* success */
+	}
+	dput(root);
+	goto out; /* do not iput */
+
+ out_iput:
+	iget_failed(inode);
+	iput(inode);
+ out:
+	return err;
+
+}
+
+static int aufs_fill_super(struct super_block *sb, void *raw_data,
+			   int silent __maybe_unused)
+{
+	int err;
+	struct au_opts opts;
+	struct dentry *root;
+	struct inode *inode;
+	char *arg = raw_data;
+
+	if (unlikely(!arg || !*arg)) {
+		err = -EINVAL;
+		pr_err("no arg\n");
+		goto out;
+	}
+
+	err = -ENOMEM;
+	memset(&opts, 0, sizeof(opts));
+	opts.opt = (void *)__get_free_page(GFP_NOFS);
+	if (unlikely(!opts.opt))
+		goto out;
+	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
+	opts.sb_flags = sb->s_flags;
+
+	err = au_si_alloc(sb);
+	if (unlikely(err))
+		goto out_opts;
+
+	/* all timestamps always follow the ones on the branch */
+	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
+	sb->s_op = &aufs_sop;
+	sb->s_magic = AUFS_SUPER_MAGIC;
+	sb->s_maxbytes = 0;
+	au_export_init(sb);
+
+	err = alloc_root(sb);
+	if (unlikely(err)) {
+		si_write_unlock(sb);
+		goto out_info;
+	}
+	root = sb->s_root;
+	inode = root->d_inode;
+
+	/*
+	 * actually we can parse options regardless aufs lock here.
+	 * but at remount time, parsing must be done before aufs lock.
+	 * so we follow the same rule.
+	 */
+	ii_write_lock_parent(inode);
+	aufs_write_unlock(root);
+	err = au_opts_parse(sb, arg, &opts);
+	if (unlikely(err))
+		goto out_root;
+
+	/* lock vfs_inode first, then aufs. */
+	mutex_lock(&inode->i_mutex);
+	inode->i_op = &aufs_dir_iop;
+	inode->i_fop = &aufs_dir_fop;
+	aufs_write_lock(root);
+	err = au_opts_mount(sb, &opts);
+	au_opts_free(&opts);
+	if (unlikely(err))
+		goto out_unlock;
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+	goto out_opts; /* success */
+
+ out_unlock:
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+ out_root:
+	dput(root);
+	sb->s_root = NULL;
+ out_info:
+	kobject_put(&au_sbi(sb)->si_kobj);
+	sb->s_fs_info = NULL;
+ out_opts:
+	free_page((unsigned long)opts.opt);
+ out:
+	AuTraceErr(err);
+	err = cvt_err(err);
+	AuTraceErr(err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
+		       const char *dev_name __maybe_unused, void *raw_data,
+		       struct vfsmount *mnt)
+{
+	int err;
+	struct super_block *sb;
+
+	/* all timestamps always follow the ones on the branch */
+	/* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
+	err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
+	if (!err) {
+		sb = mnt->mnt_sb;
+		si_write_lock(sb);
+		sysaufs_brs_add(sb, 0);
+		si_write_unlock(sb);
+	}
+	return err;
+}
+
+struct file_system_type aufs_fs_type = {
+	.name		= AUFS_FSTYPE,
+	.fs_flags	=
+		FS_RENAME_DOES_D_MOVE	/* a race between rename and others */
+		| FS_REVAL_DOT,		/* for NFS branch and udba */
+	.get_sb		= aufs_get_sb,
+	.kill_sb	= generic_shutdown_super,
+	/* no need to __module_get() and module_put(). */
+	.owner		= THIS_MODULE,
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/poll.c
+++ linux-ec2-2.6.32/ubuntu/aufs/poll.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * poll operation
+ * There is only one filesystem which implements ->poll operation, currently.
+ */
+
+#include "aufs.h"
+
+unsigned int aufs_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask;
+	int err;
+	struct file *h_file;
+	struct dentry *dentry;
+	struct super_block *sb;
+
+	/* We should pretend an error happened. */
+	mask = POLLERR /* | POLLIN | POLLOUT */;
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
+	if (unlikely(err))
+		goto out;
+
+	/* it is not an error if h_file has no operation */
+	mask = DEFAULT_POLLMASK;
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (h_file->f_op && h_file->f_op->poll)
+		mask = h_file->f_op->poll(h_file, wait);
+
+	di_read_unlock(dentry, AuLock_IR);
+	fi_read_unlock(file);
+
+ out:
+	si_read_unlock(sb);
+	AuTraceErr((int)mask);
+	return mask;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dbgaufs.h
+++ linux-ec2-2.6.32/ubuntu/aufs/dbgaufs.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * debugfs interface
+ */
+
+#ifndef __DBGAUFS_H__
+#define __DBGAUFS_H__
+
+#ifdef __KERNEL__
+
+#include <linux/init.h>
+#include <linux/aufs_type.h>
+
+struct super_block;
+struct au_sbinfo;
+
+#ifdef CONFIG_DEBUG_FS
+/* dbgaufs.c */
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
+void dbgaufs_fin(void);
+int __init dbgaufs_init(void);
+
+#else
+
+static inline
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+	/* empty */
+}
+
+static inline
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+	/* empty */
+}
+
+static inline
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
+{
+	/* empty */
+}
+
+static inline
+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
+{
+	return 0;
+}
+
+#define dbgaufs_fin()	do {} while (0)
+
+static inline
+int __init dbgaufs_init(void)
+{
+	return 0;
+}
+#endif /* CONFIG_DEBUG_FS */
+
+#endif /* __KERNEL__ */
+#endif /* __DBGAUFS_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dentry.c
+++ linux-ec2-2.6.32/ubuntu/aufs/dentry.c
@@ -0,0 +1,880 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * lookup and dentry operations
+ */
+
+#include <linux/namei.h>
+#include "aufs.h"
+
+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
+{
+	if (nd) {
+		*h_nd = *nd;
+
+		/*
+		 * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
+		 * due to whiteout and branch permission.
+		 */
+		h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
+				 | LOOKUP_FOLLOW);
+		/* unnecessary? */
+		h_nd->intent.open.file = NULL;
+	} else
+		memset(h_nd, 0, sizeof(*h_nd));
+}
+
+struct au_lkup_one_args {
+	struct dentry **errp;
+	struct qstr *name;
+	struct dentry *h_parent;
+	struct au_branch *br;
+	struct nameidata *nd;
+};
+
+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
+			   struct au_branch *br, struct nameidata *nd)
+{
+	struct dentry *h_dentry;
+	int err;
+	struct nameidata h_nd;
+
+	if (au_test_fs_null_nd(h_parent->d_sb))
+		return vfsub_lookup_one_len(name->name, h_parent, name->len);
+
+	au_h_nd(&h_nd, nd);
+	h_nd.path.dentry = h_parent;
+	h_nd.path.mnt = br->br_mnt;
+
+	err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
+	h_dentry = ERR_PTR(err);
+	if (!err) {
+		path_get(&h_nd.path);
+		h_dentry = vfsub_lookup_hash(&h_nd);
+		path_put(&h_nd.path);
+	}
+
+	AuTraceErrPtr(h_dentry);
+	return h_dentry;
+}
+
+static void au_call_lkup_one(void *args)
+{
+	struct au_lkup_one_args *a = args;
+	*a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
+}
+
+#define AuLkup_ALLOW_NEG	1
+#define au_ftest_lkup(flags, name)	((flags) & AuLkup_##name)
+#define au_fset_lkup(flags, name)	{ (flags) |= AuLkup_##name; }
+#define au_fclr_lkup(flags, name)	{ (flags) &= ~AuLkup_##name; }
+
+struct au_do_lookup_args {
+	unsigned int		flags;
+	mode_t			type;
+	struct nameidata	*nd;
+};
+
+/*
+ * returns positive/negative dentry, NULL or an error.
+ * NULL means whiteout-ed or not-found.
+ */
+static struct dentry*
+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
+	     aufs_bindex_t bindex, struct qstr *wh_name,
+	     struct au_do_lookup_args *args)
+{
+	struct dentry *h_dentry;
+	struct inode *h_inode, *inode;
+	struct qstr *name;
+	struct au_branch *br;
+	int wh_found, opq;
+	unsigned char wh_able;
+	const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
+
+	name = &dentry->d_name;
+	wh_found = 0;
+	br = au_sbr(dentry->d_sb, bindex);
+	wh_able = !!au_br_whable(br->br_perm);
+	if (wh_able)
+		wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
+	h_dentry = ERR_PTR(wh_found);
+	if (!wh_found)
+		goto real_lookup;
+	if (unlikely(wh_found < 0))
+		goto out;
+
+	/* We found a whiteout */
+	/* au_set_dbend(dentry, bindex); */
+	au_set_dbwh(dentry, bindex);
+	if (!allow_neg)
+		return NULL; /* success */
+
+ real_lookup:
+	h_dentry = au_lkup_one(name, h_parent, br, args->nd);
+	if (IS_ERR(h_dentry))
+		goto out;
+
+	h_inode = h_dentry->d_inode;
+	if (!h_inode) {
+		if (!allow_neg)
+			goto out_neg;
+	} else if (wh_found
+		   || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
+		goto out_neg;
+
+	if (au_dbend(dentry) <= bindex)
+		au_set_dbend(dentry, bindex);
+	if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
+		au_set_dbstart(dentry, bindex);
+	au_set_h_dptr(dentry, bindex, h_dentry);
+
+	inode = dentry->d_inode;
+	if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
+	    || (inode && !S_ISDIR(inode->i_mode)))
+		goto out; /* success */
+
+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+	opq = au_diropq_test(h_dentry, br);
+	mutex_unlock(&h_inode->i_mutex);
+	if (opq > 0)
+		au_set_dbdiropq(dentry, bindex);
+	else if (unlikely(opq < 0)) {
+		au_set_h_dptr(dentry, bindex, NULL);
+		h_dentry = ERR_PTR(opq);
+	}
+	goto out;
+
+ out_neg:
+	dput(h_dentry);
+	h_dentry = NULL;
+ out:
+	return h_dentry;
+}
+
+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
+{
+	if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
+		     && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
+		return -EPERM;
+	return 0;
+}
+
+/*
+ * returns the number of lower positive dentries,
+ * otherwise an error.
+ * can be called at unlinking with @type is zero.
+ */
+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
+		   struct nameidata *nd)
+{
+	int npositive, err;
+	aufs_bindex_t bindex, btail, bdiropq;
+	unsigned char isdir;
+	struct qstr whname;
+	struct au_do_lookup_args args = {
+		.flags	= 0,
+		.type	= type,
+		.nd	= nd
+	};
+	const struct qstr *name = &dentry->d_name;
+	struct dentry *parent;
+	struct inode *inode;
+
+	parent = dget_parent(dentry);
+	err = au_test_shwh(dentry->d_sb, name);
+	if (unlikely(err))
+		goto out;
+
+	err = au_wh_name_alloc(&whname, name);
+	if (unlikely(err))
+		goto out;
+
+	inode = dentry->d_inode;
+	isdir = !!(inode && S_ISDIR(inode->i_mode));
+	if (!type)
+		au_fset_lkup(args.flags, ALLOW_NEG);
+
+	npositive = 0;
+	btail = au_dbtaildir(parent);
+	for (bindex = bstart; bindex <= btail; bindex++) {
+		struct dentry *h_parent, *h_dentry;
+		struct inode *h_inode, *h_dir;
+
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (h_dentry) {
+			if (h_dentry->d_inode)
+				npositive++;
+			if (type != S_IFDIR)
+				break;
+			continue;
+		}
+		h_parent = au_h_dptr(parent, bindex);
+		if (!h_parent)
+			continue;
+		h_dir = h_parent->d_inode;
+		if (!h_dir || !S_ISDIR(h_dir->i_mode))
+			continue;
+
+		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
+		h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
+					&args);
+		mutex_unlock(&h_dir->i_mutex);
+		err = PTR_ERR(h_dentry);
+		if (IS_ERR(h_dentry))
+			goto out_wh;
+		au_fclr_lkup(args.flags, ALLOW_NEG);
+
+		if (au_dbwh(dentry) >= 0)
+			break;
+		if (!h_dentry)
+			continue;
+		h_inode = h_dentry->d_inode;
+		if (!h_inode)
+			continue;
+		npositive++;
+		if (!args.type)
+			args.type = h_inode->i_mode & S_IFMT;
+		if (args.type != S_IFDIR)
+			break;
+		else if (isdir) {
+			/* the type of lower may be different */
+			bdiropq = au_dbdiropq(dentry);
+			if (bdiropq >= 0 && bdiropq <= bindex)
+				break;
+		}
+	}
+
+	if (npositive) {
+		AuLabel(positive);
+		au_update_dbstart(dentry);
+	}
+	err = npositive;
+	if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
+		     && au_dbstart(dentry) < 0))
+		/* both of real entry and whiteout found */
+		err = -EIO;
+
+ out_wh:
+	kfree(whname.name);
+ out:
+	dput(parent);
+	return err;
+}
+
+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
+			       struct au_branch *br)
+{
+	struct dentry *dentry;
+	int wkq_err;
+
+	if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
+		dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
+	else {
+		struct au_lkup_one_args args = {
+			.errp		= &dentry,
+			.name		= name,
+			.h_parent	= parent,
+			.br		= br,
+			.nd		= NULL
+		};
+
+		wkq_err = au_wkq_wait(au_call_lkup_one, &args);
+		if (unlikely(wkq_err))
+			dentry = ERR_PTR(wkq_err);
+	}
+
+	return dentry;
+}
+
+/*
+ * lookup @dentry on @bindex which should be negative.
+ */
+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	int err;
+	struct dentry *parent, *h_parent, *h_dentry;
+	struct qstr *name;
+
+	name = &dentry->d_name;
+	parent = dget_parent(dentry);
+	h_parent = au_h_dptr(parent, bindex);
+	h_dentry = au_sio_lkup_one(name, h_parent,
+				   au_sbr(dentry->d_sb, bindex));
+	err = PTR_ERR(h_dentry);
+	if (IS_ERR(h_dentry))
+		goto out;
+	if (unlikely(h_dentry->d_inode)) {
+		err = -EIO;
+		AuIOErr("b%d %.*s should be negative.\n",
+			bindex, AuDLNPair(h_dentry));
+		dput(h_dentry);
+		goto out;
+	}
+
+	if (bindex < au_dbstart(dentry))
+		au_set_dbstart(dentry, bindex);
+	if (au_dbend(dentry) < bindex)
+		au_set_dbend(dentry, bindex);
+	au_set_h_dptr(dentry, bindex, h_dentry);
+	err = 0;
+
+ out:
+	dput(parent);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* subset of struct inode */
+struct au_iattr {
+	unsigned long		i_ino;
+	/* unsigned int		i_nlink; */
+	uid_t			i_uid;
+	gid_t			i_gid;
+	u64			i_version;
+/*
+	loff_t			i_size;
+	blkcnt_t		i_blocks;
+*/
+	umode_t			i_mode;
+};
+
+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
+{
+	ia->i_ino = h_inode->i_ino;
+	/* ia->i_nlink = h_inode->i_nlink; */
+	ia->i_uid = h_inode->i_uid;
+	ia->i_gid = h_inode->i_gid;
+	ia->i_version = h_inode->i_version;
+/*
+	ia->i_size = h_inode->i_size;
+	ia->i_blocks = h_inode->i_blocks;
+*/
+	ia->i_mode = (h_inode->i_mode & S_IFMT);
+}
+
+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
+{
+	return ia->i_ino != h_inode->i_ino
+		/* || ia->i_nlink != h_inode->i_nlink */
+		|| ia->i_uid != h_inode->i_uid
+		|| ia->i_gid != h_inode->i_gid
+		|| ia->i_version != h_inode->i_version
+/*
+		|| ia->i_size != h_inode->i_size
+		|| ia->i_blocks != h_inode->i_blocks
+*/
+		|| ia->i_mode != (h_inode->i_mode & S_IFMT);
+}
+
+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
+			      struct au_branch *br)
+{
+	int err;
+	struct au_iattr ia;
+	struct inode *h_inode;
+	struct dentry *h_d;
+	struct super_block *h_sb;
+
+	err = 0;
+	memset(&ia, -1, sizeof(ia));
+	h_sb = h_dentry->d_sb;
+	h_inode = h_dentry->d_inode;
+	if (h_inode)
+		au_iattr_save(&ia, h_inode);
+	else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
+		/* nfs d_revalidate may return 0 for negative dentry */
+		/* fuse d_revalidate always return 0 for negative dentry */
+		goto out;
+
+	/* main purpose is namei.c:cached_lookup() and d_revalidate */
+	h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
+	err = PTR_ERR(h_d);
+	if (IS_ERR(h_d))
+		goto out;
+
+	err = 0;
+	if (unlikely(h_d != h_dentry
+		     || h_d->d_inode != h_inode
+		     || (h_inode && au_iattr_test(&ia, h_inode))))
+		err = au_busy_or_stale();
+	dput(h_d);
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
+		struct dentry *h_parent, struct au_branch *br)
+{
+	int err;
+
+	err = 0;
+	if (udba == AuOpt_UDBA_REVAL) {
+		IMustLock(h_dir);
+		err = (h_dentry->d_parent->d_inode != h_dir);
+	} else if (udba == AuOpt_UDBA_HINOTIFY)
+		err = au_h_verify_dentry(h_dentry, h_parent, br);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
+				  struct dentry *parent)
+{
+	struct dentry *h_d, *h_dp;
+	struct au_hdentry tmp, *q;
+	struct super_block *sb;
+	aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
+
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	bend = dinfo->di_bend;
+	bwh = dinfo->di_bwh;
+	bdiropq = dinfo->di_bdiropq;
+	for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
+		h_d = p->hd_dentry;
+		if (!h_d)
+			continue;
+
+		h_dp = dget_parent(h_d);
+		if (h_dp == au_h_dptr(parent, bindex)) {
+			dput(h_dp);
+			continue;
+		}
+
+		new_bindex = au_find_dbindex(parent, h_dp);
+		dput(h_dp);
+		if (dinfo->di_bwh == bindex)
+			bwh = new_bindex;
+		if (dinfo->di_bdiropq == bindex)
+			bdiropq = new_bindex;
+		if (new_bindex < 0) {
+			au_hdput(p);
+			p->hd_dentry = NULL;
+			continue;
+		}
+
+		/* swap two lower dentries, and loop again */
+		q = dinfo->di_hdentry + new_bindex;
+		tmp = *q;
+		*q = *p;
+		*p = tmp;
+		if (tmp.hd_dentry) {
+			bindex--;
+			p--;
+		}
+	}
+
+	sb = parent->d_sb;
+	dinfo->di_bwh = -1;
+	if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
+		dinfo->di_bwh = bwh;
+
+	dinfo->di_bdiropq = -1;
+	if (bdiropq >= 0
+	    && bdiropq <= au_sbend(sb)
+	    && au_sbr_whable(sb, bdiropq))
+		dinfo->di_bdiropq = bdiropq;
+
+	bend = au_dbend(parent);
+	p = dinfo->di_hdentry;
+	for (bindex = 0; bindex <= bend; bindex++, p++)
+		if (p->hd_dentry) {
+			dinfo->di_bstart = bindex;
+			break;
+		}
+
+	p = dinfo->di_hdentry + bend;
+	for (bindex = bend; bindex >= 0; bindex--, p--)
+		if (p->hd_dentry) {
+			dinfo->di_bend = bindex;
+			break;
+		}
+}
+
+/*
+ * returns the number of found lower positive dentries,
+ * otherwise an error.
+ */
+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
+{
+	int npositive, err;
+	unsigned int sigen;
+	aufs_bindex_t bstart;
+	struct au_dinfo *dinfo;
+	struct super_block *sb;
+	struct dentry *parent;
+
+	DiMustWriteLock(dentry);
+
+	sb = dentry->d_sb;
+	AuDebugOn(IS_ROOT(dentry));
+	sigen = au_sigen(sb);
+	parent = dget_parent(dentry);
+	AuDebugOn(au_digen(parent) != sigen
+		  || au_iigen(parent->d_inode) != sigen);
+
+	dinfo = au_di(dentry);
+	err = au_di_realloc(dinfo, au_sbend(sb) + 1);
+	npositive = err;
+	if (unlikely(err))
+		goto out;
+	au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
+			      parent);
+
+	npositive = 0;
+	bstart = au_dbstart(parent);
+	if (type != S_IFDIR && dinfo->di_bstart == bstart)
+		goto out_dgen; /* success */
+
+	npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
+	if (npositive < 0)
+		goto out;
+	if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
+		d_drop(dentry);
+
+ out_dgen:
+	au_update_digen(dentry);
+ out:
+	dput(parent);
+	AuTraceErr(npositive);
+	return npositive;
+}
+
+static noinline_for_stack
+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
+		    struct dentry *dentry, aufs_bindex_t bindex)
+{
+	int err, valid;
+	int (*reval)(struct dentry *, struct nameidata *);
+
+	err = 0;
+	reval = NULL;
+	if (h_dentry->d_op)
+		reval = h_dentry->d_op->d_revalidate;
+	if (!reval)
+		goto out;
+
+	AuDbg("b%d\n", bindex);
+	if (au_test_fs_null_nd(h_dentry->d_sb))
+		/* it may return tri-state */
+		valid = reval(h_dentry, NULL);
+	else {
+		struct nameidata h_nd;
+		int locked;
+		struct dentry *parent;
+
+		au_h_nd(&h_nd, nd);
+		parent = nd->path.dentry;
+		locked = (nd && nd->path.dentry != dentry);
+		if (locked)
+			di_read_lock_parent(parent, AuLock_IR);
+		BUG_ON(bindex > au_dbend(parent));
+		h_nd.path.dentry = au_h_dptr(parent, bindex);
+		BUG_ON(!h_nd.path.dentry);
+		h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
+		path_get(&h_nd.path);
+		valid = reval(h_dentry, &h_nd);
+		path_put(&h_nd.path);
+		if (locked)
+			di_read_unlock(parent, AuLock_IR);
+	}
+
+	if (unlikely(valid < 0))
+		err = valid;
+	else if (!valid)
+		err = -EINVAL;
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+/* todo: remove this */
+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
+			  struct nameidata *nd, int do_udba)
+{
+	int err;
+	umode_t mode, h_mode;
+	aufs_bindex_t bindex, btail, bstart, ibs, ibe;
+	unsigned char plus, unhashed, is_root, h_plus;
+	struct inode *first, *h_inode, *h_cached_inode;
+	struct dentry *h_dentry;
+	struct qstr *name, *h_name;
+
+	err = 0;
+	plus = 0;
+	mode = 0;
+	first = NULL;
+	ibs = -1;
+	ibe = -1;
+	unhashed = !!d_unhashed(dentry);
+	is_root = !!IS_ROOT(dentry);
+	name = &dentry->d_name;
+
+	/*
+	 * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
+	 * But inotify doesn't fire some necessary events,
+	 *	IN_ATTRIB for atime/nlink/pageio
+	 *	IN_DELETE for NFS dentry
+	 * Let's do REVAL test too.
+	 */
+	if (do_udba && inode) {
+		mode = (inode->i_mode & S_IFMT);
+		plus = (inode->i_nlink > 0);
+		first = au_h_iptr(inode, au_ibstart(inode));
+		ibs = au_ibstart(inode);
+		ibe = au_ibend(inode);
+	}
+
+	bstart = au_dbstart(dentry);
+	btail = bstart;
+	if (inode && S_ISDIR(inode->i_mode))
+		btail = au_dbtaildir(dentry);
+	for (bindex = bstart; bindex <= btail; bindex++) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (!h_dentry)
+			continue;
+
+		AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
+		h_name = &h_dentry->d_name;
+		if (unlikely(do_udba
+			     && !is_root
+			     && (unhashed != !!d_unhashed(h_dentry)
+				 || name->len != h_name->len
+				 || memcmp(name->name, h_name->name, name->len))
+			    )) {
+			AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
+				  unhashed, d_unhashed(h_dentry),
+				  AuDLNPair(dentry), AuDLNPair(h_dentry));
+			goto err;
+		}
+
+		err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
+		if (unlikely(err))
+			/* do not goto err, to keep the errno */
+			break;
+
+		/* todo: plink too? */
+		if (!do_udba)
+			continue;
+
+		/* UDBA tests */
+		h_inode = h_dentry->d_inode;
+		if (unlikely(!!inode != !!h_inode))
+			goto err;
+
+		h_plus = plus;
+		h_mode = mode;
+		h_cached_inode = h_inode;
+		if (h_inode) {
+			h_mode = (h_inode->i_mode & S_IFMT);
+			h_plus = (h_inode->i_nlink > 0);
+		}
+		if (inode && ibs <= bindex && bindex <= ibe)
+			h_cached_inode = au_h_iptr(inode, bindex);
+
+		if (unlikely(plus != h_plus
+			     || mode != h_mode
+			     || h_cached_inode != h_inode))
+			goto err;
+		continue;
+
+	err:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
+{
+	int err;
+	struct dentry *parent;
+	struct inode *inode;
+
+	inode = dentry->d_inode;
+	if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
+		return 0;
+
+	parent = dget_parent(dentry);
+	di_read_lock_parent(parent, AuLock_IR);
+	AuDebugOn(au_digen(parent) != sigen
+		  || au_iigen(parent->d_inode) != sigen);
+	au_dbg_verify_gen(parent, sigen);
+
+	/* returns a number of positive dentries */
+	err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
+	if (err >= 0)
+		err = au_refresh_hinode(inode, dentry);
+
+	di_read_unlock(parent, AuLock_IR);
+	dput(parent);
+	return err;
+}
+
+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
+{
+	int err;
+	struct dentry *d, *parent;
+	struct inode *inode;
+
+	if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
+		return simple_reval_dpath(dentry, sigen);
+
+	/* slow loop, keep it simple and stupid */
+	/* cf: au_cpup_dirs() */
+	err = 0;
+	parent = NULL;
+	while (au_digen(dentry) != sigen
+	       || au_iigen(dentry->d_inode) != sigen) {
+		d = dentry;
+		while (1) {
+			dput(parent);
+			parent = dget_parent(d);
+			if (au_digen(parent) == sigen
+			    && au_iigen(parent->d_inode) == sigen)
+				break;
+			d = parent;
+		}
+
+		inode = d->d_inode;
+		if (d != dentry)
+			di_write_lock_child(d);
+
+		/* someone might update our dentry while we were sleeping */
+		if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
+			di_read_lock_parent(parent, AuLock_IR);
+			/* returns a number of positive dentries */
+			err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
+			if (err >= 0)
+				err = au_refresh_hinode(inode, d);
+			di_read_unlock(parent, AuLock_IR);
+		}
+
+		if (d != dentry)
+			di_write_unlock(d);
+		dput(parent);
+		if (unlikely(err))
+			break;
+	}
+
+	return err;
+}
+
+/*
+ * if valid returns 1, otherwise 0.
+ */
+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	int valid, err;
+	unsigned int sigen;
+	unsigned char do_udba;
+	struct super_block *sb;
+	struct inode *inode;
+
+	err = -EINVAL;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
+	sigen = au_sigen(sb);
+	if (au_digen(dentry) != sigen) {
+		AuDebugOn(IS_ROOT(dentry));
+		if (inode)
+			err = au_reval_dpath(dentry, sigen);
+		if (unlikely(err))
+			goto out_dgrade;
+		AuDebugOn(au_digen(dentry) != sigen);
+	}
+	if (inode && au_iigen(inode) != sigen) {
+		AuDebugOn(IS_ROOT(dentry));
+		err = au_refresh_hinode(inode, dentry);
+		if (unlikely(err))
+			goto out_dgrade;
+		AuDebugOn(au_iigen(inode) != sigen);
+	}
+	di_downgrade_lock(dentry, AuLock_IR);
+
+	AuDebugOn(au_digen(dentry) != sigen);
+	AuDebugOn(inode && au_iigen(inode) != sigen);
+	err = -EINVAL;
+	do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
+	if (do_udba && inode) {
+		aufs_bindex_t bstart = au_ibstart(inode);
+
+		if (bstart >= 0
+		    && au_test_higen(inode, au_h_iptr(inode, bstart)))
+			goto out;
+	}
+
+	err = h_d_revalidate(dentry, inode, nd, do_udba);
+	if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
+		/* both of real entry and whiteout found */
+		err = -EIO;
+	goto out;
+
+ out_dgrade:
+	di_downgrade_lock(dentry, AuLock_IR);
+ out:
+	aufs_read_unlock(dentry, AuLock_IR);
+	AuTraceErr(err);
+	valid = !err;
+	if (!valid)
+		AuDbg("%.*s invalid\n", AuDLNPair(dentry));
+	return valid;
+}
+
+static void aufs_d_release(struct dentry *dentry)
+{
+	struct au_dinfo *dinfo;
+	aufs_bindex_t bend, bindex;
+
+	dinfo = dentry->d_fsdata;
+	if (!dinfo)
+		return;
+
+	/* dentry may not be revalidated */
+	bindex = dinfo->di_bstart;
+	if (bindex >= 0) {
+		struct au_hdentry *p;
+
+		bend = dinfo->di_bend;
+		p = dinfo->di_hdentry + bindex;
+		while (bindex++ <= bend) {
+			if (p->hd_dentry)
+				au_hdput(p);
+			p++;
+		}
+	}
+	kfree(dinfo->di_hdentry);
+	AuRwDestroy(&dinfo->di_rwsem);
+	au_cache_free_dinfo(dinfo);
+	au_hin_di_reinit(dentry);
+}
+
+struct dentry_operations aufs_dop = {
+	.d_revalidate	= aufs_d_revalidate,
+	.d_release	= aufs_d_release
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/whout.c
+++ linux-ec2-2.6.32/ubuntu/aufs/whout.c
@@ -0,0 +1,1055 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * whiteout for logical deletion and opaque directory
+ */
+
+#include <linux/fs.h>
+#include "aufs.h"
+
+#define WH_MASK			S_IRUGO
+
+/*
+ * If a directory contains this file, then it is opaque.  We start with the
+ * .wh. flag so that it is blocked by lookup.
+ */
+static struct qstr diropq_name = {
+	.name = AUFS_WH_DIROPQ,
+	.len = sizeof(AUFS_WH_DIROPQ) - 1
+};
+
+/*
+ * generate whiteout name, which is NOT terminated by NULL.
+ * @name: original d_name.name
+ * @len: original d_name.len
+ * @wh: whiteout qstr
+ * returns zero when succeeds, otherwise error.
+ * succeeded value as wh->name should be freed by kfree().
+ */
+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
+{
+	char *p;
+
+	if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
+		return -ENAMETOOLONG;
+
+	wh->len = name->len + AUFS_WH_PFX_LEN;
+	p = kmalloc(wh->len, GFP_NOFS);
+	wh->name = p;
+	if (p) {
+		memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
+		memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
+		/* smp_mb(); */
+		return 0;
+	}
+	return -ENOMEM;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * test if the @wh_name exists under @h_parent.
+ * @try_sio specifies the necessary of super-io.
+ */
+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
+	       struct au_branch *br, int try_sio)
+{
+	int err;
+	struct dentry *wh_dentry;
+	struct inode *h_dir;
+
+	h_dir = h_parent->d_inode;
+	if (!try_sio)
+		wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
+	else
+		wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out;
+
+	err = 0;
+	if (!wh_dentry->d_inode)
+		goto out_wh; /* success */
+
+	err = 1;
+	if (S_ISREG(wh_dentry->d_inode->i_mode))
+		goto out_wh; /* success */
+
+	err = -EIO;
+	AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
+		AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
+
+ out_wh:
+	dput(wh_dentry);
+ out:
+	return err;
+}
+
+/*
+ * test if the @h_dentry sets opaque or not.
+ */
+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
+{
+	int err;
+	struct inode *h_dir;
+
+	h_dir = h_dentry->d_inode;
+	err = au_wh_test(h_dentry, &diropq_name, br,
+			 au_test_h_perm_sio(h_dir, MAY_EXEC));
+	return err;
+}
+
+/*
+ * returns a negative dentry whose name is unique and temporary.
+ */
+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
+			     struct qstr *prefix)
+{
+	struct dentry *dentry;
+	int i;
+	char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1],
+		*name, *p;
+	static unsigned short cnt;
+	struct qstr qs;
+
+	BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
+
+	name = defname;
+	qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
+	if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
+		dentry = ERR_PTR(-ENAMETOOLONG);
+		if (unlikely(qs.len > NAME_MAX))
+			goto out;
+		dentry = ERR_PTR(-ENOMEM);
+		name = kmalloc(qs.len + 1, GFP_NOFS);
+		if (unlikely(!name))
+			goto out;
+	}
+
+	/* doubly whiteout-ed */
+	memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
+	p = name + AUFS_WH_PFX_LEN * 2;
+	memcpy(p, prefix->name, prefix->len);
+	p += prefix->len;
+	*p++ = '.';
+	AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
+
+	qs.name = name;
+	for (i = 0; i < 3; i++) {
+		sprintf(p, "%.*d", AUFS_WH_TMP_LEN, cnt++);
+		dentry = au_sio_lkup_one(&qs, h_parent, br);
+		if (IS_ERR(dentry) || !dentry->d_inode)
+			goto out_name;
+		dput(dentry);
+	}
+	/* pr_warning("could not get random name\n"); */
+	dentry = ERR_PTR(-EEXIST);
+	AuDbg("%.*s\n", AuLNPair(&qs));
+	BUG();
+
+ out_name:
+	if (name != defname)
+		kfree(name);
+ out:
+	AuTraceErrPtr(dentry);
+	return dentry;
+}
+
+/*
+ * rename the @h_dentry on @br to the whiteouted temporary name.
+ */
+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
+{
+	int err;
+	struct path h_path = {
+		.mnt = br->br_mnt
+	};
+	struct inode *h_dir;
+	struct dentry *h_parent;
+
+	h_parent = h_dentry->d_parent; /* dir inode is locked */
+	h_dir = h_parent->d_inode;
+	IMustLock(h_dir);
+
+	h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
+	err = PTR_ERR(h_path.dentry);
+	if (IS_ERR(h_path.dentry))
+		goto out;
+
+	/* under the same dir, no need to lock_rename() */
+	err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
+	AuTraceErr(err);
+	dput(h_path.dentry);
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * functions for removing a whiteout
+ */
+
+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
+{
+	int force;
+
+	/*
+	 * forces superio when the dir has a sticky bit.
+	 * this may be a violation of unix fs semantics.
+	 */
+	force = (h_dir->i_mode & S_ISVTX)
+		&& h_path->dentry->d_inode->i_uid != current_fsuid();
+	return vfsub_unlink(h_dir, h_path, force);
+}
+
+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
+			struct dentry *dentry)
+{
+	int err;
+
+	err = do_unlink_wh(h_dir, h_path);
+	if (!err && dentry)
+		au_set_dbwh(dentry, -1);
+
+	return err;
+}
+
+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
+			  struct au_branch *br)
+{
+	int err;
+	struct path h_path = {
+		.mnt = br->br_mnt
+	};
+
+	err = 0;
+	h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
+	if (IS_ERR(h_path.dentry))
+		err = PTR_ERR(h_path.dentry);
+	else {
+		if (h_path.dentry->d_inode
+		    && S_ISREG(h_path.dentry->d_inode->i_mode))
+			err = do_unlink_wh(h_parent->d_inode, &h_path);
+		dput(h_path.dentry);
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * initialize/clean whiteout for a branch
+ */
+
+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
+			const int isdir)
+{
+	int err;
+
+	if (!whpath->dentry->d_inode)
+		return;
+
+	err = mnt_want_write(whpath->mnt);
+	if (!err) {
+		if (isdir)
+			err = vfsub_rmdir(h_dir, whpath);
+		else
+			err = vfsub_unlink(h_dir, whpath, /*force*/0);
+		mnt_drop_write(whpath->mnt);
+	}
+	if (unlikely(err))
+		pr_warning("failed removing %.*s (%d), ignored.\n",
+			   AuDLNPair(whpath->dentry), err);
+}
+
+static int test_linkable(struct dentry *h_root)
+{
+	struct inode *h_dir = h_root->d_inode;
+
+	if (h_dir->i_op->link)
+		return 0;
+
+	pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
+	       AuDLNPair(h_root), au_sbtype(h_root->d_sb));
+	return -ENOSYS;
+}
+
+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
+static int au_whdir(struct inode *h_dir, struct path *path)
+{
+	int err;
+
+	err = -EEXIST;
+	if (!path->dentry->d_inode) {
+		int mode = S_IRWXU;
+
+		if (au_test_nfs(path->dentry->d_sb))
+			mode |= S_IXUGO;
+		err = mnt_want_write(path->mnt);
+		if (!err) {
+			err = vfsub_mkdir(h_dir, path, mode);
+			mnt_drop_write(path->mnt);
+		}
+	} else if (S_ISDIR(path->dentry->d_inode->i_mode))
+		err = 0;
+	else
+		pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
+
+	return err;
+}
+
+struct au_wh_base {
+	const struct qstr *name;
+	struct dentry *dentry;
+};
+
+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
+			  struct path *h_path)
+{
+	h_path->dentry = base[AuBrWh_BASE].dentry;
+	au_wh_clean(h_dir, h_path, /*isdir*/0);
+	h_path->dentry = base[AuBrWh_PLINK].dentry;
+	au_wh_clean(h_dir, h_path, /*isdir*/1);
+	h_path->dentry = base[AuBrWh_ORPH].dentry;
+	au_wh_clean(h_dir, h_path, /*isdir*/1);
+}
+
+/*
+ * returns tri-state,
+ * minus: error, caller should print the mesage
+ * zero: succuess
+ * plus: error, caller should NOT print the mesage
+ */
+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
+				int do_plink, struct au_wh_base base[],
+				struct path *h_path)
+{
+	int err;
+	struct inode *h_dir;
+
+	h_dir = h_root->d_inode;
+	h_path->dentry = base[AuBrWh_BASE].dentry;
+	au_wh_clean(h_dir, h_path, /*isdir*/0);
+	h_path->dentry = base[AuBrWh_PLINK].dentry;
+	if (do_plink) {
+		err = test_linkable(h_root);
+		if (unlikely(err)) {
+			err = 1;
+			goto out;
+		}
+
+		err = au_whdir(h_dir, h_path);
+		if (unlikely(err))
+			goto out;
+		wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
+	} else
+		au_wh_clean(h_dir, h_path, /*isdir*/1);
+	h_path->dentry = base[AuBrWh_ORPH].dentry;
+	err = au_whdir(h_dir, h_path);
+	if (unlikely(err))
+		goto out;
+	wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
+
+ out:
+	return err;
+}
+
+/*
+ * for the moment, aufs supports the branch filesystem which does not support
+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
+ * copyup failed. finally, such filesystem will not be used as the writable
+ * branch.
+ *
+ * returns tri-state, see above.
+ */
+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
+			 int do_plink, struct au_wh_base base[],
+			 struct path *h_path)
+{
+	int err;
+	struct inode *h_dir;
+
+	WbrWhMustWriteLock(wbr);
+
+	err = test_linkable(h_root);
+	if (unlikely(err)) {
+		err = 1;
+		goto out;
+	}
+
+	/*
+	 * todo: should this create be done in /sbin/mount.aufs helper?
+	 */
+	err = -EEXIST;
+	h_dir = h_root->d_inode;
+	if (!base[AuBrWh_BASE].dentry->d_inode) {
+		err = mnt_want_write(h_path->mnt);
+		if (!err) {
+			h_path->dentry = base[AuBrWh_BASE].dentry;
+			err = vfsub_create(h_dir, h_path, WH_MASK);
+			mnt_drop_write(h_path->mnt);
+		}
+	} else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
+		err = 0;
+	else
+		pr_err("unknown %.*s/%.*s exists\n",
+		       AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
+	if (unlikely(err))
+		goto out;
+
+	h_path->dentry = base[AuBrWh_PLINK].dentry;
+	if (do_plink) {
+		err = au_whdir(h_dir, h_path);
+		if (unlikely(err))
+			goto out;
+		wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
+	} else
+		au_wh_clean(h_dir, h_path, /*isdir*/1);
+	wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
+
+	h_path->dentry = base[AuBrWh_ORPH].dentry;
+	err = au_whdir(h_dir, h_path);
+	if (unlikely(err))
+		goto out;
+	wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
+
+ out:
+	return err;
+}
+
+/*
+ * initialize the whiteout base file/dir for @br.
+ */
+int au_wh_init(struct dentry *h_root, struct au_branch *br,
+	       struct super_block *sb)
+{
+	int err, i;
+	const unsigned char do_plink
+		= !!au_opt_test(au_mntflags(sb), PLINK);
+	struct path path = {
+		.mnt = br->br_mnt
+	};
+	struct inode *h_dir;
+	struct au_wbr *wbr = br->br_wbr;
+	static const struct qstr base_name[] = {
+		[AuBrWh_BASE] = {
+			.name	= AUFS_BASE_NAME,
+			.len	= sizeof(AUFS_BASE_NAME) - 1
+		},
+		[AuBrWh_PLINK] = {
+			.name	= AUFS_PLINKDIR_NAME,
+			.len	= sizeof(AUFS_PLINKDIR_NAME) - 1
+		},
+		[AuBrWh_ORPH] = {
+			.name	= AUFS_ORPHDIR_NAME,
+			.len	= sizeof(AUFS_ORPHDIR_NAME) - 1
+		}
+	};
+	struct au_wh_base base[] = {
+		[AuBrWh_BASE] = {
+			.name	= base_name + AuBrWh_BASE,
+			.dentry	= NULL
+		},
+		[AuBrWh_PLINK] = {
+			.name	= base_name + AuBrWh_PLINK,
+			.dentry	= NULL
+		},
+		[AuBrWh_ORPH] = {
+			.name	= base_name + AuBrWh_ORPH,
+			.dentry	= NULL
+		}
+	};
+
+	if (wbr)
+		WbrWhMustWriteLock(wbr);
+
+	h_dir = h_root->d_inode;
+	for (i = 0; i < AuBrWh_Last; i++) {
+		/* doubly whiteouted */
+		struct dentry *d;
+
+		d = au_wh_lkup(h_root, (void *)base[i].name, br);
+		err = PTR_ERR(d);
+		if (IS_ERR(d))
+			goto out;
+
+		base[i].dentry = d;
+		AuDebugOn(wbr
+			  && wbr->wbr_wh[i]
+			  && wbr->wbr_wh[i] != base[i].dentry);
+	}
+
+	if (wbr)
+		for (i = 0; i < AuBrWh_Last; i++) {
+			dput(wbr->wbr_wh[i]);
+			wbr->wbr_wh[i] = NULL;
+		}
+
+	err = 0;
+
+	switch (br->br_perm) {
+	case AuBrPerm_RO:
+	case AuBrPerm_ROWH:
+	case AuBrPerm_RR:
+	case AuBrPerm_RRWH:
+		au_wh_init_ro(h_dir, base, &path);
+		break;
+
+	case AuBrPerm_RWNoLinkWH:
+		err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
+		if (err > 0)
+			goto out;
+		else if (err)
+			goto out_err;
+		break;
+
+	case AuBrPerm_RW:
+		err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
+		if (err > 0)
+			goto out;
+		else if (err)
+			goto out_err;
+		break;
+
+	default:
+		BUG();
+	}
+	goto out; /* success */
+
+ out_err:
+	pr_err("an error(%d) on the writable branch %.*s(%s)\n",
+	       err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
+ out:
+	for (i = 0; i < AuBrWh_Last; i++)
+		dput(base[i].dentry);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * whiteouts are all hard-linked usually.
+ * when its link count reaches a ceiling, we create a new whiteout base
+ * asynchronously.
+ */
+
+struct reinit_br_wh {
+	struct super_block *sb;
+	struct au_branch *br;
+};
+
+static void reinit_br_wh(void *arg)
+{
+	int err;
+	aufs_bindex_t bindex;
+	struct path h_path;
+	struct reinit_br_wh *a = arg;
+	struct au_wbr *wbr;
+	struct inode *dir;
+	struct dentry *h_root;
+	struct au_hinode *hdir;
+
+	err = 0;
+	wbr = a->br->br_wbr;
+	/* big aufs lock */
+	si_noflush_write_lock(a->sb);
+	if (!au_br_writable(a->br->br_perm))
+		goto out;
+	bindex = au_br_index(a->sb, a->br->br_id);
+	if (unlikely(bindex < 0))
+		goto out;
+
+	di_read_lock_parent(a->sb->s_root, AuLock_IR);
+	dir = a->sb->s_root->d_inode;
+	hdir = au_hi(dir, bindex);
+	h_root = au_h_dptr(a->sb->s_root, bindex);
+
+	au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
+	wbr_wh_write_lock(wbr);
+	err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
+			  h_root, a->br);
+	if (!err) {
+		err = mnt_want_write(a->br->br_mnt);
+		if (!err) {
+			h_path.dentry = wbr->wbr_whbase;
+			h_path.mnt = a->br->br_mnt;
+			err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
+			mnt_drop_write(a->br->br_mnt);
+		}
+	} else {
+		pr_warning("%.*s is moved, ignored\n",
+			   AuDLNPair(wbr->wbr_whbase));
+		err = 0;
+	}
+	dput(wbr->wbr_whbase);
+	wbr->wbr_whbase = NULL;
+	if (!err)
+		err = au_wh_init(h_root, a->br, a->sb);
+	wbr_wh_write_unlock(wbr);
+	au_hin_imtx_unlock(hdir);
+	di_read_unlock(a->sb->s_root, AuLock_IR);
+
+ out:
+	if (wbr)
+		atomic_dec(&wbr->wbr_wh_running);
+	atomic_dec(&a->br->br_count);
+	au_nwt_done(&au_sbi(a->sb)->si_nowait);
+	si_write_unlock(a->sb);
+	kfree(arg);
+	if (unlikely(err))
+		AuIOErr("err %d\n", err);
+}
+
+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
+{
+	int do_dec, wkq_err;
+	struct reinit_br_wh *arg;
+
+	do_dec = 1;
+	if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
+		goto out;
+
+	/* ignore ENOMEM */
+	arg = kmalloc(sizeof(*arg), GFP_NOFS);
+	if (arg) {
+		/*
+		 * dec(wh_running), kfree(arg) and dec(br_count)
+		 * in reinit function
+		 */
+		arg->sb = sb;
+		arg->br = br;
+		atomic_inc(&br->br_count);
+		wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
+		if (unlikely(wkq_err)) {
+			atomic_dec(&br->br_wbr->wbr_wh_running);
+			atomic_dec(&br->br_count);
+			kfree(arg);
+		}
+		do_dec = 0;
+	}
+
+ out:
+	if (do_dec)
+		atomic_dec(&br->br_wbr->wbr_wh_running);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * create the whiteout @wh.
+ */
+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
+			     struct dentry *wh)
+{
+	int err;
+	struct path h_path = {
+		.dentry = wh
+	};
+	struct au_branch *br;
+	struct au_wbr *wbr;
+	struct dentry *h_parent;
+	struct inode *h_dir;
+
+	h_parent = wh->d_parent; /* dir inode is locked */
+	h_dir = h_parent->d_inode;
+	IMustLock(h_dir);
+
+	br = au_sbr(sb, bindex);
+	h_path.mnt = br->br_mnt;
+	wbr = br->br_wbr;
+	wbr_wh_read_lock(wbr);
+	if (wbr->wbr_whbase) {
+		err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
+		if (!err || err != -EMLINK)
+			goto out;
+
+		/* link count full. re-initialize br_whbase. */
+		kick_reinit_br_wh(sb, br);
+	}
+
+	/* return this error in this context */
+	err = vfsub_create(h_dir, &h_path, WH_MASK);
+
+ out:
+	wbr_wh_read_unlock(wbr);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * create or remove the diropq.
+ */
+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
+				unsigned int flags)
+{
+	struct dentry *opq_dentry, *h_dentry;
+	struct super_block *sb;
+	struct au_branch *br;
+	int err;
+
+	sb = dentry->d_sb;
+	br = au_sbr(sb, bindex);
+	h_dentry = au_h_dptr(dentry, bindex);
+	opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
+	if (IS_ERR(opq_dentry))
+		goto out;
+
+	if (au_ftest_diropq(flags, CREATE)) {
+		err = link_or_create_wh(sb, bindex, opq_dentry);
+		if (!err) {
+			au_set_dbdiropq(dentry, bindex);
+			goto out; /* success */
+		}
+	} else {
+		struct path tmp = {
+			.dentry = opq_dentry,
+			.mnt	= br->br_mnt
+		};
+		err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
+		if (!err)
+			au_set_dbdiropq(dentry, -1);
+	}
+	dput(opq_dentry);
+	opq_dentry = ERR_PTR(err);
+
+ out:
+	return opq_dentry;
+}
+
+struct do_diropq_args {
+	struct dentry **errp;
+	struct dentry *dentry;
+	aufs_bindex_t bindex;
+	unsigned int flags;
+};
+
+static void call_do_diropq(void *args)
+{
+	struct do_diropq_args *a = args;
+	*a->errp = do_diropq(a->dentry, a->bindex, a->flags);
+}
+
+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
+			     unsigned int flags)
+{
+	struct dentry *diropq, *h_dentry;
+
+	h_dentry = au_h_dptr(dentry, bindex);
+	if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
+		diropq = do_diropq(dentry, bindex, flags);
+	else {
+		int wkq_err;
+		struct do_diropq_args args = {
+			.errp		= &diropq,
+			.dentry		= dentry,
+			.bindex		= bindex,
+			.flags		= flags
+		};
+
+		wkq_err = au_wkq_wait(call_do_diropq, &args);
+		if (unlikely(wkq_err))
+			diropq = ERR_PTR(wkq_err);
+	}
+
+	return diropq;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * lookup whiteout dentry.
+ * @h_parent: lower parent dentry which must exist and be locked
+ * @base_name: name of dentry which will be whiteouted
+ * returns dentry for whiteout.
+ */
+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
+			  struct au_branch *br)
+{
+	int err;
+	struct qstr wh_name;
+	struct dentry *wh_dentry;
+
+	err = au_wh_name_alloc(&wh_name, base_name);
+	wh_dentry = ERR_PTR(err);
+	if (!err) {
+		wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
+		kfree(wh_name.name);
+	}
+	return wh_dentry;
+}
+
+/*
+ * link/create a whiteout for @dentry on @bindex.
+ */
+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
+			    struct dentry *h_parent)
+{
+	struct dentry *wh_dentry;
+	struct super_block *sb;
+	int err;
+
+	sb = dentry->d_sb;
+	wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
+	if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
+		err = link_or_create_wh(sb, bindex, wh_dentry);
+		if (!err)
+			au_set_dbwh(dentry, bindex);
+		else {
+			dput(wh_dentry);
+			wh_dentry = ERR_PTR(err);
+		}
+	}
+
+	return wh_dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* Delete all whiteouts in this directory on branch bindex. */
+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
+			   aufs_bindex_t bindex, struct au_branch *br)
+{
+	int err;
+	unsigned long ul, n;
+	struct qstr wh_name;
+	char *p;
+	struct hlist_head *head;
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos;
+	struct au_vdir_destr *str;
+
+	err = -ENOMEM;
+	p = __getname();
+	wh_name.name = p;
+	if (unlikely(!wh_name.name))
+		goto out;
+
+	err = 0;
+	memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
+	p += AUFS_WH_PFX_LEN;
+	n = whlist->nh_num;
+	head = whlist->nh_head;
+	for (ul = 0; !err && ul < n; ul++, head++) {
+		hlist_for_each_entry(tpos, pos, head, wh_hash) {
+			if (tpos->wh_bindex != bindex)
+				continue;
+
+			str = &tpos->wh_str;
+			if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
+				memcpy(p, str->name, str->len);
+				wh_name.len = AUFS_WH_PFX_LEN + str->len;
+				err = unlink_wh_name(h_dentry, &wh_name, br);
+				if (!err)
+					continue;
+				break;
+			}
+			AuIOErr("whiteout name too long %.*s\n",
+				str->len, str->name);
+			err = -EIO;
+			break;
+		}
+	}
+	__putname(wh_name.name);
+
+ out:
+	return err;
+}
+
+struct del_wh_children_args {
+	int *errp;
+	struct dentry *h_dentry;
+	struct au_nhash *whlist;
+	aufs_bindex_t bindex;
+	struct au_branch *br;
+};
+
+static void call_del_wh_children(void *args)
+{
+	struct del_wh_children_args *a = args;
+	*a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
+{
+	struct au_whtmp_rmdir *whtmp;
+	int err;
+	unsigned int rdhash;
+
+	SiMustAnyLock(sb);
+
+	whtmp = kmalloc(sizeof(*whtmp), gfp);
+	if (unlikely(!whtmp)) {
+		whtmp = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	whtmp->dir = NULL;
+	whtmp->wh_dentry = NULL;
+	/* no estimation for dir size */
+	rdhash = au_sbi(sb)->si_rdhash;
+	if (!rdhash)
+		rdhash = AUFS_RDHASH_DEF;
+	err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
+	if (unlikely(err)) {
+		kfree(whtmp);
+		whtmp = ERR_PTR(err);
+	}
+
+ out:
+	return whtmp;
+}
+
+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
+{
+	dput(whtmp->wh_dentry);
+	iput(whtmp->dir);
+	au_nhash_wh_free(&whtmp->whlist);
+	kfree(whtmp);
+}
+
+/*
+ * rmdir the whiteouted temporary named dir @h_dentry.
+ * @whlist: whiteouted children.
+ */
+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
+		   struct dentry *wh_dentry, struct au_nhash *whlist)
+{
+	int err;
+	struct path h_tmp;
+	struct inode *wh_inode, *h_dir;
+	struct au_branch *br;
+
+	h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
+	IMustLock(h_dir);
+
+	br = au_sbr(dir->i_sb, bindex);
+	wh_inode = wh_dentry->d_inode;
+	mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
+
+	/*
+	 * someone else might change some whiteouts while we were sleeping.
+	 * it means this whlist may have an obsoleted entry.
+	 */
+	if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
+		err = del_wh_children(wh_dentry, whlist, bindex, br);
+	else {
+		int wkq_err;
+		struct del_wh_children_args args = {
+			.errp		= &err,
+			.h_dentry	= wh_dentry,
+			.whlist		= whlist,
+			.bindex		= bindex,
+			.br		= br
+		};
+
+		wkq_err = au_wkq_wait(call_del_wh_children, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+	mutex_unlock(&wh_inode->i_mutex);
+
+	if (!err) {
+		h_tmp.dentry = wh_dentry;
+		h_tmp.mnt = br->br_mnt;
+		err = vfsub_rmdir(h_dir, &h_tmp);
+		/* d_drop(h_dentry); */
+	}
+
+	if (!err) {
+		if (au_ibstart(dir) == bindex) {
+			au_cpup_attr_timesizes(dir);
+			drop_nlink(dir);
+		}
+		return 0; /* success */
+	}
+
+	pr_warning("failed removing %.*s(%d), ignored\n",
+		   AuDLNPair(wh_dentry), err);
+	return err;
+}
+
+static void call_rmdir_whtmp(void *args)
+{
+	int err;
+	struct au_whtmp_rmdir *a = args;
+	struct super_block *sb;
+	struct dentry *h_parent;
+	struct inode *h_dir;
+	struct au_branch *br;
+	struct au_hinode *hdir;
+
+	/* rmdir by nfsd may cause deadlock with this i_mutex */
+	/* mutex_lock(&a->dir->i_mutex); */
+	sb = a->dir->i_sb;
+	si_noflush_read_lock(sb);
+	err = au_test_ro(sb, a->bindex, NULL);
+	if (unlikely(err))
+		goto out;
+
+	err = -EIO;
+	br = au_sbr(sb, a->bindex);
+	ii_write_lock_parent(a->dir);
+	h_parent = dget_parent(a->wh_dentry);
+	h_dir = h_parent->d_inode;
+	hdir = au_hi(a->dir, a->bindex);
+	au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
+	err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
+	if (!err) {
+		err = mnt_want_write(br->br_mnt);
+		if (!err) {
+			err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
+					     &a->whlist);
+			mnt_drop_write(br->br_mnt);
+		}
+	}
+	au_hin_imtx_unlock(hdir);
+	dput(h_parent);
+	ii_write_unlock(a->dir);
+
+ out:
+	/* mutex_unlock(&a->dir->i_mutex); */
+	au_nwt_done(&au_sbi(sb)->si_nowait);
+	si_read_unlock(sb);
+	au_whtmp_rmdir_free(a);
+	if (unlikely(err))
+		AuIOErr("err %d\n", err);
+}
+
+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
+			 struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
+{
+	int wkq_err;
+
+	IMustLock(dir);
+
+	/* all post-process will be done in do_rmdir_whtmp(). */
+	args->dir = au_igrab(dir);
+	args->bindex = bindex;
+	args->wh_dentry = dget(wh_dentry);
+	wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
+	if (unlikely(wkq_err)) {
+		pr_warning("rmdir error %.*s (%d), ignored\n",
+			   AuDLNPair(wh_dentry), wkq_err);
+		au_whtmp_rmdir_free(args);
+	}
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/sysaufs.c
+++ linux-ec2-2.6.32/ubuntu/aufs/sysaufs.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sysfs interface and lifetime management
+ * they are necessary regardless sysfs is disabled.
+ */
+
+#include <linux/fs.h>
+#include <linux/random.h>
+#include <linux/sysfs.h>
+#include "aufs.h"
+
+unsigned long sysaufs_si_mask;
+struct kset *sysaufs_ket;
+
+#define AuSiAttr(_name) { \
+	.attr   = { .name = __stringify(_name), .mode = 0444 },	\
+	.show   = sysaufs_si_##_name,				\
+}
+
+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
+struct attribute *sysaufs_si_attrs[] = {
+	&sysaufs_si_attr_xi_path.attr,
+	NULL,
+};
+
+static struct sysfs_ops au_sbi_ops = {
+	.show   = sysaufs_si_show
+};
+
+static struct kobj_type au_sbi_ktype = {
+	.release	= au_si_free,
+	.sysfs_ops	= &au_sbi_ops,
+	.default_attrs	= sysaufs_si_attrs
+};
+
+/* ---------------------------------------------------------------------- */
+
+int sysaufs_si_init(struct au_sbinfo *sbinfo)
+{
+	int err;
+
+	sbinfo->si_kobj.kset = sysaufs_ket;
+	/* cf. sysaufs_name() */
+	err = kobject_init_and_add
+		(&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
+		 SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
+
+	dbgaufs_si_null(sbinfo);
+	if (!err) {
+		err = dbgaufs_si_init(sbinfo);
+		if (unlikely(err))
+			kobject_put(&sbinfo->si_kobj);
+	}
+	return err;
+}
+
+void sysaufs_fin(void)
+{
+	dbgaufs_fin();
+	sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
+	kset_unregister(sysaufs_ket);
+}
+
+int __init sysaufs_init(void)
+{
+	int err;
+
+	do {
+		get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
+	} while (!sysaufs_si_mask);
+
+	sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
+	err = PTR_ERR(sysaufs_ket);
+	if (IS_ERR(sysaufs_ket))
+		goto out;
+	err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
+	if (unlikely(err)) {
+		kset_unregister(sysaufs_ket);
+		goto out;
+	}
+
+	err = dbgaufs_init();
+	if (unlikely(err))
+		sysaufs_fin();
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/loop.h
+++ linux-ec2-2.6.32/ubuntu/aufs/loop.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * support for loopback mount as a branch
+ */
+
+#ifndef __AUFS_LOOP_H__
+#define __AUFS_LOOP_H__
+
+#ifdef __KERNEL__
+
+struct dentry;
+struct super_block;
+
+#ifdef CONFIG_AUFS_BDEV_LOOP
+/* loop.c */
+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
+			     struct dentry *h_d2);
+int au_test_loopback_kthread(void);
+#else
+static inline
+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
+			     struct dentry *h_d2)
+{
+	return 0;
+}
+
+static inline int au_test_loopback_kthread(void)
+{
+	return 0;
+}
+#endif /* BLK_DEV_LOOP */
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_LOOP_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dir.c
+++ linux-ec2-2.6.32/ubuntu/aufs/dir.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * directory operations
+ */
+
+#include <linux/file.h>
+#include <linux/fs_stack.h>
+#include "aufs.h"
+
+void au_add_nlink(struct inode *dir, struct inode *h_dir)
+{
+	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
+
+	dir->i_nlink += h_dir->i_nlink - 2;
+	if (h_dir->i_nlink < 2)
+		dir->i_nlink += 2;
+}
+
+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
+{
+	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
+
+	dir->i_nlink -= h_dir->i_nlink - 2;
+	if (h_dir->i_nlink < 2)
+		dir->i_nlink -= 2;
+}
+
+loff_t au_dir_size(struct file *file, struct dentry *dentry)
+{
+	loff_t sz;
+	aufs_bindex_t bindex, bend;
+	struct file *h_file;
+	struct dentry *h_dentry;
+
+	sz = 0;
+	if (file) {
+		AuDebugOn(!file->f_dentry);
+		AuDebugOn(!file->f_dentry->d_inode);
+		AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
+
+		bend = au_fbend(file);
+		for (bindex = au_fbstart(file);
+		     bindex <= bend && sz < KMALLOC_MAX_SIZE;
+		     bindex++) {
+			h_file = au_h_fptr(file, bindex);
+			if (h_file
+			    && h_file->f_dentry
+			    && h_file->f_dentry->d_inode)
+				sz += i_size_read(h_file->f_dentry->d_inode);
+		}
+	} else {
+		AuDebugOn(!dentry);
+		AuDebugOn(!dentry->d_inode);
+		AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
+
+		bend = au_dbtaildir(dentry);
+		for (bindex = au_dbstart(dentry);
+		     bindex <= bend && sz < KMALLOC_MAX_SIZE;
+		     bindex++) {
+			h_dentry = au_h_dptr(dentry, bindex);
+			if (h_dentry && h_dentry->d_inode)
+				sz += i_size_read(h_dentry->d_inode);
+		}
+	}
+	if (sz < KMALLOC_MAX_SIZE)
+		sz = roundup_pow_of_two(sz);
+	if (sz > KMALLOC_MAX_SIZE)
+		sz = KMALLOC_MAX_SIZE;
+	else if (sz < NAME_MAX) {
+		BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
+		sz = AUFS_RDBLK_DEF;
+	}
+	return sz;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int reopen_dir(struct file *file)
+{
+	int err;
+	unsigned int flags;
+	aufs_bindex_t bindex, btail, bstart;
+	struct dentry *dentry, *h_dentry;
+	struct file *h_file;
+
+	/* open all lower dirs */
+	dentry = file->f_dentry;
+	bstart = au_dbstart(dentry);
+	for (bindex = au_fbstart(file); bindex < bstart; bindex++)
+		au_set_h_fptr(file, bindex, NULL);
+	au_set_fbstart(file, bstart);
+
+	btail = au_dbtaildir(dentry);
+	for (bindex = au_fbend(file); btail < bindex; bindex--)
+		au_set_h_fptr(file, bindex, NULL);
+	au_set_fbend(file, btail);
+
+	spin_lock(&file->f_lock);
+	flags = file->f_flags;
+	spin_unlock(&file->f_lock);
+	for (bindex = bstart; bindex <= btail; bindex++) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (!h_dentry)
+			continue;
+		h_file = au_h_fptr(file, bindex);
+		if (h_file)
+			continue;
+
+		h_file = au_h_open(dentry, bindex, flags, file);
+		err = PTR_ERR(h_file);
+		if (IS_ERR(h_file))
+			goto out; /* close all? */
+		au_set_h_fptr(file, bindex, h_file);
+	}
+	au_update_figen(file);
+	/* todo: necessary? */
+	/* file->f_ra = h_file->f_ra; */
+	err = 0;
+
+ out:
+	return err;
+}
+
+static int do_open_dir(struct file *file, int flags)
+{
+	int err;
+	aufs_bindex_t bindex, btail;
+	struct dentry *dentry, *h_dentry;
+	struct file *h_file;
+
+	FiMustWriteLock(file);
+
+	err = 0;
+	dentry = file->f_dentry;
+	au_set_fvdir_cache(file, NULL);
+	au_fi(file)->fi_maintain_plink = 0;
+	file->f_version = dentry->d_inode->i_version;
+	bindex = au_dbstart(dentry);
+	au_set_fbstart(file, bindex);
+	btail = au_dbtaildir(dentry);
+	au_set_fbend(file, btail);
+	for (; !err && bindex <= btail; bindex++) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (!h_dentry)
+			continue;
+
+		h_file = au_h_open(dentry, bindex, flags, file);
+		if (IS_ERR(h_file)) {
+			err = PTR_ERR(h_file);
+			break;
+		}
+		au_set_h_fptr(file, bindex, h_file);
+	}
+	au_update_figen(file);
+	/* todo: necessary? */
+	/* file->f_ra = h_file->f_ra; */
+	if (!err)
+		return 0; /* success */
+
+	/* close all */
+	for (bindex = au_fbstart(file); bindex <= btail; bindex++)
+		au_set_h_fptr(file, bindex, NULL);
+	au_set_fbstart(file, -1);
+	au_set_fbend(file, -1);
+	return err;
+}
+
+static int aufs_open_dir(struct inode *inode __maybe_unused,
+			 struct file *file)
+{
+	return au_do_open(file, do_open_dir);
+}
+
+static int aufs_release_dir(struct inode *inode __maybe_unused,
+			    struct file *file)
+{
+	struct au_vdir *vdir_cache;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+
+	sb = file->f_dentry->d_sb;
+	si_noflush_read_lock(sb);
+	fi_write_lock(file);
+	vdir_cache = au_fvdir_cache(file);
+	if (vdir_cache)
+		au_vdir_free(vdir_cache);
+	if (au_fi(file)->fi_maintain_plink) {
+		sbinfo = au_sbi(sb);
+		/* clear the flag without write-lock */
+		sbinfo->au_si_status &= ~AuSi_MAINTAIN_PLINK;
+		smp_mb();
+		wake_up_all(&sbinfo->si_plink_wq);
+	}
+	fi_write_unlock(file);
+	au_finfo_fin(file);
+	si_read_unlock(sb);
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
+{
+	int err;
+	aufs_bindex_t bend, bindex;
+	struct inode *inode;
+	struct super_block *sb;
+
+	err = 0;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	IMustLock(inode);
+	bend = au_dbend(dentry);
+	for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
+		struct path h_path;
+		struct inode *h_inode;
+
+		if (au_test_ro(sb, bindex, inode))
+			continue;
+		h_path.dentry = au_h_dptr(dentry, bindex);
+		if (!h_path.dentry)
+			continue;
+		h_inode = h_path.dentry->d_inode;
+		if (!h_inode)
+			continue;
+
+		/* no mnt_want_write() */
+		/* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
+		/* todo: inotiry fired? */
+		h_path.mnt = au_sbr_mnt(sb, bindex);
+		mutex_lock(&h_inode->i_mutex);
+		err = filemap_fdatawrite(h_inode->i_mapping);
+		AuDebugOn(!h_inode->i_fop);
+		if (!err && h_inode->i_fop->fsync)
+			err = h_inode->i_fop->fsync(NULL, h_path.dentry,
+						    datasync);
+		if (!err)
+			err = filemap_fdatawrite(h_inode->i_mapping);
+		if (!err)
+			vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
+		mutex_unlock(&h_inode->i_mutex);
+	}
+
+	return err;
+}
+
+static int au_do_fsync_dir(struct file *file, int datasync)
+{
+	int err;
+	aufs_bindex_t bend, bindex;
+	struct file *h_file;
+	struct super_block *sb;
+	struct inode *inode;
+	struct mutex *h_mtx;
+
+	err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	sb = file->f_dentry->d_sb;
+	inode = file->f_dentry->d_inode;
+	bend = au_fbend(file);
+	for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
+		h_file = au_h_fptr(file, bindex);
+		if (!h_file || au_test_ro(sb, bindex, inode))
+			continue;
+
+		err = vfs_fsync(h_file, h_file->f_dentry, datasync);
+		if (!err) {
+			h_mtx = &h_file->f_dentry->d_inode->i_mutex;
+			mutex_lock(h_mtx);
+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
+			/*ignore*/
+			mutex_unlock(h_mtx);
+		}
+	}
+
+ out:
+	return err;
+}
+
+/*
+ * @file may be NULL
+ */
+static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
+			  int datasync)
+{
+	int err;
+	struct super_block *sb;
+
+	IMustLock(dentry->d_inode);
+
+	err = 0;
+	sb = dentry->d_sb;
+	si_noflush_read_lock(sb);
+	if (file)
+		err = au_do_fsync_dir(file, datasync);
+	else {
+		di_write_lock_child(dentry);
+		err = au_do_fsync_dir_no_file(dentry, datasync);
+	}
+	au_cpup_attr_timesizes(dentry->d_inode);
+	di_write_unlock(dentry);
+	if (file)
+		fi_write_unlock(file);
+
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	int err;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
+	IMustLock(inode);
+
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+	err = au_vdir_init(file);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+
+	if (!au_test_nfsd(current)) {
+		err = au_vdir_fill_de(file, dirent, filldir);
+		fsstack_copy_attr_atime(inode,
+					au_h_iptr(inode, au_ibstart(inode)));
+	} else {
+		/*
+		 * nfsd filldir may call lookup_one_len(), vfs_getattr(),
+		 * encode_fh() and others.
+		 */
+		struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
+
+		di_read_unlock(dentry, AuLock_IR);
+		si_read_unlock(sb);
+		/* lockdep_off(); */
+		err = au_vdir_fill_de(file, dirent, filldir);
+		/* lockdep_on(); */
+		fsstack_copy_attr_atime(inode, h_inode);
+		fi_write_unlock(file);
+
+		AuTraceErr(err);
+		return err;
+	}
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define AuTestEmpty_WHONLY	1
+#define AuTestEmpty_CALLED	(1 << 1)
+#define AuTestEmpty_SHWH	(1 << 2)
+#define au_ftest_testempty(flags, name)	((flags) & AuTestEmpty_##name)
+#define au_fset_testempty(flags, name)	{ (flags) |= AuTestEmpty_##name; }
+#define au_fclr_testempty(flags, name)	{ (flags) &= ~AuTestEmpty_##name; }
+
+#ifndef CONFIG_AUFS_SHWH
+#undef AuTestEmpty_SHWH
+#define AuTestEmpty_SHWH	0
+#endif
+
+struct test_empty_arg {
+	struct au_nhash *whlist;
+	unsigned int flags;
+	int err;
+	aufs_bindex_t bindex;
+};
+
+static int test_empty_cb(void *__arg, const char *__name, int namelen,
+			 loff_t offset __maybe_unused, u64 ino,
+			 unsigned int d_type)
+{
+	struct test_empty_arg *arg = __arg;
+	char *name = (void *)__name;
+
+	arg->err = 0;
+	au_fset_testempty(arg->flags, CALLED);
+	/* smp_mb(); */
+	if (name[0] == '.'
+	    && (namelen == 1 || (name[1] == '.' && namelen == 2)))
+		goto out; /* success */
+
+	if (namelen <= AUFS_WH_PFX_LEN
+	    || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
+		if (au_ftest_testempty(arg->flags, WHONLY)
+		    && !au_nhash_test_known_wh(arg->whlist, name, namelen))
+			arg->err = -ENOTEMPTY;
+		goto out;
+	}
+
+	name += AUFS_WH_PFX_LEN;
+	namelen -= AUFS_WH_PFX_LEN;
+	if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
+		arg->err = au_nhash_append_wh
+			(arg->whlist, name, namelen, ino, d_type, arg->bindex,
+			 au_ftest_testempty(arg->flags, SHWH));
+
+ out:
+	/* smp_mb(); */
+	AuTraceErr(arg->err);
+	return arg->err;
+}
+
+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
+{
+	int err;
+	struct file *h_file;
+
+	h_file = au_h_open(dentry, arg->bindex,
+			   O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
+			   /*file*/NULL);
+	err = PTR_ERR(h_file);
+	if (IS_ERR(h_file))
+		goto out;
+
+	err = 0;
+	if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
+	    && !h_file->f_dentry->d_inode->i_nlink)
+		goto out_put;
+
+	do {
+		arg->err = 0;
+		au_fclr_testempty(arg->flags, CALLED);
+		/* smp_mb(); */
+		err = vfsub_readdir(h_file, test_empty_cb, arg);
+		if (err >= 0)
+			err = arg->err;
+	} while (!err && au_ftest_testempty(arg->flags, CALLED));
+
+ out_put:
+	fput(h_file);
+	au_sbr_put(dentry->d_sb, arg->bindex);
+ out:
+	return err;
+}
+
+struct do_test_empty_args {
+	int *errp;
+	struct dentry *dentry;
+	struct test_empty_arg *arg;
+};
+
+static void call_do_test_empty(void *args)
+{
+	struct do_test_empty_args *a = args;
+	*a->errp = do_test_empty(a->dentry, a->arg);
+}
+
+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
+{
+	int err, wkq_err;
+	struct dentry *h_dentry;
+	struct inode *h_inode;
+
+	h_dentry = au_h_dptr(dentry, arg->bindex);
+	h_inode = h_dentry->d_inode;
+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+	err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
+	mutex_unlock(&h_inode->i_mutex);
+	if (!err)
+		err = do_test_empty(dentry, arg);
+	else {
+		struct do_test_empty_args args = {
+			.errp	= &err,
+			.dentry	= dentry,
+			.arg	= arg
+		};
+		unsigned int flags = arg->flags;
+
+		wkq_err = au_wkq_wait(call_do_test_empty, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+		arg->flags = flags;
+	}
+
+	return err;
+}
+
+int au_test_empty_lower(struct dentry *dentry)
+{
+	int err;
+	unsigned int rdhash;
+	aufs_bindex_t bindex, bstart, btail;
+	struct au_nhash whlist;
+	struct test_empty_arg arg;
+
+	SiMustAnyLock(dentry->d_sb);
+
+	rdhash = au_sbi(dentry->d_sb)->si_rdhash;
+	if (!rdhash)
+		rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
+	err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
+	if (unlikely(err))
+		goto out;
+
+	arg.flags = 0;
+	arg.whlist = &whlist;
+	bstart = au_dbstart(dentry);
+	if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
+		au_fset_testempty(arg.flags, SHWH);
+	arg.bindex = bstart;
+	err = do_test_empty(dentry, &arg);
+	if (unlikely(err))
+		goto out_whlist;
+
+	au_fset_testempty(arg.flags, WHONLY);
+	btail = au_dbtaildir(dentry);
+	for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
+		struct dentry *h_dentry;
+
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (h_dentry && h_dentry->d_inode) {
+			arg.bindex = bindex;
+			err = do_test_empty(dentry, &arg);
+		}
+	}
+
+ out_whlist:
+	au_nhash_wh_free(&whlist);
+ out:
+	return err;
+}
+
+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
+{
+	int err;
+	struct test_empty_arg arg;
+	aufs_bindex_t bindex, btail;
+
+	err = 0;
+	arg.whlist = whlist;
+	arg.flags = AuTestEmpty_WHONLY;
+	if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
+		au_fset_testempty(arg.flags, SHWH);
+	btail = au_dbtaildir(dentry);
+	for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
+		struct dentry *h_dentry;
+
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (h_dentry && h_dentry->d_inode) {
+			arg.bindex = bindex;
+			err = sio_test_empty(dentry, &arg);
+		}
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+const struct file_operations aufs_dir_fop = {
+	.read		= generic_read_dir,
+	.readdir	= aufs_readdir,
+	.unlocked_ioctl	= aufs_ioctl_dir,
+	.open		= aufs_open_dir,
+	.release	= aufs_release_dir,
+	.flush		= aufs_flush,
+	.fsync		= aufs_fsync_dir
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dcsub.h
+++ linux-ec2-2.6.32/ubuntu/aufs/dcsub.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sub-routines for dentry cache
+ */
+
+#ifndef __AUFS_DCSUB_H__
+#define __AUFS_DCSUB_H__
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+struct dentry;
+
+struct au_dpage {
+	int ndentry;
+	struct dentry **dentries;
+};
+
+struct au_dcsub_pages {
+	int ndpage;
+	struct au_dpage *dpages;
+};
+
+/* ---------------------------------------------------------------------- */
+
+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
+void au_dpages_free(struct au_dcsub_pages *dpages);
+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
+		   au_dpages_test test, void *arg);
+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
+		       int do_include, au_dpages_test test, void *arg);
+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DCSUB_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/inode.h
+++ linux-ec2-2.6.32/ubuntu/aufs/inode.h
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode operations
+ */
+
+#ifndef __AUFS_INODE_H__
+#define __AUFS_INODE_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/inotify.h>
+#include <linux/aufs_type.h>
+#include "rwsem.h"
+
+struct vfsmount;
+
+struct au_hinotify {
+#ifdef CONFIG_AUFS_HINOTIFY
+	struct inotify_watch	hin_watch;
+	struct inode		*hin_aufs_inode;	/* no get/put */
+#endif
+};
+
+struct au_hinode {
+	struct inode		*hi_inode;
+	aufs_bindex_t		hi_id;
+#ifdef CONFIG_AUFS_HINOTIFY
+	struct au_hinotify	*hi_notify;
+#endif
+
+	/* reference to the copied-up whiteout with get/put */
+	struct dentry		*hi_whdentry;
+};
+
+struct au_vdir;
+struct au_iinfo {
+	atomic_t		ii_generation;
+	struct super_block	*ii_hsb1;	/* no get/put */
+
+	struct au_rwsem		ii_rwsem;
+	aufs_bindex_t		ii_bstart, ii_bend;
+	__u32			ii_higen;
+	struct au_hinode	*ii_hinode;
+	struct au_vdir		*ii_vdir;
+};
+
+struct au_icntnr {
+	struct au_iinfo iinfo;
+	struct inode vfs_inode;
+};
+
+/* au_pin flags */
+#define AuPin_DI_LOCKED		1
+#define AuPin_MNT_WRITE		(1 << 1)
+#define au_ftest_pin(flags, name)	((flags) & AuPin_##name)
+#define au_fset_pin(flags, name)	{ (flags) |= AuPin_##name; }
+#define au_fclr_pin(flags, name)	{ (flags) &= ~AuPin_##name; }
+
+struct au_pin {
+	/* input */
+	struct dentry *dentry;
+	unsigned int udba;
+	unsigned char lsc_di, lsc_hi, flags;
+	aufs_bindex_t bindex;
+
+	/* output */
+	struct dentry *parent;
+	struct au_hinode *hdir;
+	struct vfsmount *h_mnt;
+};
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct au_iinfo *au_ii(struct inode *inode)
+{
+	struct au_iinfo *iinfo;
+
+	iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
+	if (iinfo->ii_hinode)
+		return iinfo;
+	return NULL; /* debugging bad_inode case */
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* inode.c */
+struct inode *au_igrab(struct inode *inode);
+int au_refresh_hinode_self(struct inode *inode, int do_attr);
+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+	   unsigned int d_type, ino_t *ino);
+struct inode *au_new_inode(struct dentry *dentry, int must_new);
+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
+	       struct inode *inode);
+int au_test_h_perm(struct inode *h_inode, int mask);
+int au_test_h_perm_sio(struct inode *h_inode, int mask);
+
+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
+			    ino_t h_ino, unsigned int d_type, ino_t *ino)
+{
+#ifdef CONFIG_AUFS_SHWH
+	return au_ino(sb, bindex, h_ino, d_type, ino);
+#else
+	return 0;
+#endif
+}
+
+/* i_op.c */
+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
+
+/* au_wr_dir flags */
+#define AuWrDir_ADD_ENTRY	1
+#define AuWrDir_ISDIR		(1 << 1)
+#define au_ftest_wrdir(flags, name)	((flags) & AuWrDir_##name)
+#define au_fset_wrdir(flags, name)	{ (flags) |= AuWrDir_##name; }
+#define au_fclr_wrdir(flags, name)	{ (flags) &= ~AuWrDir_##name; }
+
+struct au_wr_dir_args {
+	aufs_bindex_t force_btgt;
+	unsigned char flags;
+};
+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
+	      struct au_wr_dir_args *args);
+
+struct dentry *au_pinned_h_parent(struct au_pin *pin);
+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
+		 aufs_bindex_t bindex, int lsc_di, int lsc_hi,
+		 unsigned int udba, unsigned char flags);
+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
+	   unsigned int udba, unsigned char flags) __must_check;
+int au_do_pin(struct au_pin *pin) __must_check;
+void au_unpin(struct au_pin *pin);
+
+/* i_op_add.c */
+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
+	       struct dentry *h_parent, int isdir);
+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd);
+int aufs_link(struct dentry *src_dentry, struct inode *dir,
+	      struct dentry *dentry);
+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+
+/* i_op_del.c */
+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
+	       struct dentry *h_parent, int isdir);
+int aufs_unlink(struct inode *dir, struct dentry *dentry);
+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
+
+/* i_op_ren.c */
+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
+		struct inode *dir, struct dentry *dentry);
+
+/* iinfo.c */
+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
+void au_hiput(struct au_hinode *hinode);
+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
+		  struct dentry *h_wh);
+unsigned int au_hi_flags(struct inode *inode, int isdir);
+
+/* hinode flags */
+#define AuHi_XINO	1
+#define AuHi_HINOTIFY	(1 << 1)
+#define au_ftest_hi(flags, name)	((flags) & AuHi_##name)
+#define au_fset_hi(flags, name)		{ (flags) |= AuHi_##name; }
+#define au_fclr_hi(flags, name)		{ (flags) &= ~AuHi_##name; }
+
+#ifndef CONFIG_AUFS_HINOTIFY
+#undef AuHi_HINOTIFY
+#define AuHi_HINOTIFY	0
+#endif
+
+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
+		   struct inode *h_inode, unsigned int flags);
+
+void au_update_iigen(struct inode *inode);
+void au_update_brange(struct inode *inode, int do_put_zero);
+
+int au_iinfo_init(struct inode *inode);
+void au_iinfo_fin(struct inode *inode);
+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
+
+/* plink.c */
+void au_plink_block_maintain(struct super_block *sb);
+#ifdef CONFIG_AUFS_DEBUG
+void au_plink_list(struct super_block *sb);
+#else
+static inline void au_plink_list(struct super_block *sb)
+{
+	/* nothing */
+}
+#endif
+int au_plink_test(struct inode *inode);
+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
+		     struct dentry *h_dentry);
+void au_plink_put(struct super_block *sb);
+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
+long au_plink_ioctl(struct file *file, unsigned int cmd);
+
+/* ---------------------------------------------------------------------- */
+
+/* lock subclass for iinfo */
+enum {
+	AuLsc_II_CHILD,		/* child first */
+	AuLsc_II_CHILD2,	/* rename(2), link(2), and cpup at hinotify */
+	AuLsc_II_CHILD3,	/* copyup dirs */
+	AuLsc_II_PARENT,	/* see AuLsc_I_PARENT in vfsub.h */
+	AuLsc_II_PARENT2,
+	AuLsc_II_PARENT3,	/* copyup dirs */
+	AuLsc_II_NEW_CHILD
+};
+
+/*
+ * ii_read_lock_child, ii_write_lock_child,
+ * ii_read_lock_child2, ii_write_lock_child2,
+ * ii_read_lock_child3, ii_write_lock_child3,
+ * ii_read_lock_parent, ii_write_lock_parent,
+ * ii_read_lock_parent2, ii_write_lock_parent2,
+ * ii_read_lock_parent3, ii_write_lock_parent3,
+ * ii_read_lock_new_child, ii_write_lock_new_child,
+ */
+#define AuReadLockFunc(name, lsc) \
+static inline void ii_read_lock_##name(struct inode *i) \
+{ \
+	au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
+}
+
+#define AuWriteLockFunc(name, lsc) \
+static inline void ii_write_lock_##name(struct inode *i) \
+{ \
+	au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
+}
+
+#define AuRWLockFuncs(name, lsc) \
+	AuReadLockFunc(name, lsc) \
+	AuWriteLockFunc(name, lsc)
+
+AuRWLockFuncs(child, CHILD);
+AuRWLockFuncs(child2, CHILD2);
+AuRWLockFuncs(child3, CHILD3);
+AuRWLockFuncs(parent, PARENT);
+AuRWLockFuncs(parent2, PARENT2);
+AuRWLockFuncs(parent3, PARENT3);
+AuRWLockFuncs(new_child, NEW_CHILD);
+
+#undef AuReadLockFunc
+#undef AuWriteLockFunc
+#undef AuRWLockFuncs
+
+/*
+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
+ */
+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
+
+#define IiMustNoWaiters(i)	AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
+#define IiMustAnyLock(i)	AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
+#define IiMustWriteLock(i)	AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
+
+/* ---------------------------------------------------------------------- */
+
+static inline unsigned int au_iigen(struct inode *inode)
+{
+	return atomic_read(&au_ii(inode)->ii_generation);
+}
+
+/* tiny test for inode number */
+/* tmpfs generation is too rough */
+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
+{
+	struct au_iinfo *iinfo;
+
+	iinfo = au_ii(inode);
+	AuRwMustAnyLock(&iinfo->ii_rwsem);
+	return !(iinfo->ii_hsb1 == h_inode->i_sb
+		 && iinfo->ii_higen == h_inode->i_generation);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
+					aufs_bindex_t bindex)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
+}
+
+static inline aufs_bindex_t au_ibstart(struct inode *inode)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_bstart;
+}
+
+static inline aufs_bindex_t au_ibend(struct inode *inode)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_bend;
+}
+
+static inline struct au_vdir *au_ivdir(struct inode *inode)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_vdir;
+}
+
+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
+}
+
+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
+{
+	IiMustWriteLock(inode);
+	au_ii(inode)->ii_bend = bindex;
+}
+
+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
+{
+	IiMustWriteLock(inode);
+	au_ii(inode)->ii_vdir = vdir;
+}
+
+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
+{
+	IiMustAnyLock(inode);
+	return au_ii(inode)->ii_hinode + bindex;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
+{
+	if (pin)
+		return pin->parent;
+	return NULL;
+}
+
+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
+{
+	if (pin && pin->hdir)
+		return pin->hdir->hi_inode;
+	return NULL;
+}
+
+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
+{
+	if (pin)
+		return pin->hdir;
+	return NULL;
+}
+
+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
+{
+	if (pin)
+		pin->dentry = dentry;
+}
+
+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
+					   unsigned char lflag)
+{
+	if (pin) {
+		/* dirty macros require brackets */
+		if (lflag) {
+			au_fset_pin(pin->flags, DI_LOCKED);
+		} else {
+			au_fclr_pin(pin->flags, DI_LOCKED);
+		}
+	}
+}
+
+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
+{
+	if (pin) {
+		dput(pin->parent);
+		pin->parent = dget(parent);
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_HINOTIFY
+/* hinotify.c */
+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
+		 struct inode *h_inode);
+void au_hin_free(struct au_hinode *hinode);
+void au_hin_ctl(struct au_hinode *hinode, int do_set);
+void au_reset_hinotify(struct inode *inode, unsigned int flags);
+
+int __init au_hinotify_init(void);
+void au_hinotify_fin(void);
+
+static inline
+void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
+{
+	hinode->hi_notify = val;
+}
+
+static inline void au_iigen_dec(struct inode *inode)
+{
+	atomic_dec_return(&au_ii(inode)->ii_generation);
+}
+
+#else
+static inline
+int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
+		 struct inode *inode __maybe_unused,
+		 struct inode *h_inode __maybe_unused)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
+{
+	/* nothing */
+}
+
+static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
+			      int do_set __maybe_unused)
+{
+	/* nothing */
+}
+
+static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
+				     unsigned int flags __maybe_unused)
+{
+	/* nothing */
+}
+
+static inline int au_hinotify_init(void)
+{
+	return 0;
+}
+
+#define au_hinotify_fin()	do {} while (0)
+
+static inline
+void au_hin_init(struct au_hinode *hinode __maybe_unused,
+		 struct au_hinotify *val __maybe_unused)
+{
+	/* empty */
+}
+#endif /* CONFIG_AUFS_HINOTIFY */
+
+static inline void au_hin_suspend(struct au_hinode *hdir)
+{
+	au_hin_ctl(hdir, /*do_set*/0);
+}
+
+static inline void au_hin_resume(struct au_hinode *hdir)
+{
+	au_hin_ctl(hdir, /*do_set*/1);
+}
+
+static inline void au_hin_imtx_lock(struct au_hinode *hdir)
+{
+	mutex_lock(&hdir->hi_inode->i_mutex);
+	au_hin_suspend(hdir);
+}
+
+static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
+					   unsigned int sc __maybe_unused)
+{
+	mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
+	au_hin_suspend(hdir);
+}
+
+static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
+{
+	au_hin_resume(hdir);
+	mutex_unlock(&hdir->hi_inode->i_mutex);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_INODE_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/Makefile
+++ linux-ec2-2.6.32/ubuntu/aufs/Makefile
@@ -0,0 +1,33 @@
+
+include ${src}/magic.mk
+ifeq (${CONFIG_AUFS_FS},m)
+include ${src}/conf.mk
+endif
+-include ${src}/priv_def.mk
+
+# cf. include/linux/kernel.h
+# enable pr_debug
+ccflags-y += -DDEBUG
+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
+	__func__, __LINE__, current->comm, current->pid'
+
+obj-$(CONFIG_AUFS_FS) += aufs.o
+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
+	wkq.o vfsub.o dcsub.o \
+	cpup.o whout.o plink.o wbr_policy.o \
+	dinfo.o dentry.o \
+	finfo.o file.o f_op.o \
+	dir.o vdir.o \
+	iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
+	ioctl.o
+
+# all are boolean
+aufs-$(CONFIG_SYSFS) += sysfs.o
+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
+aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
+aufs-$(CONFIG_AUFS_EXPORT) += export.o
+aufs-$(CONFIG_AUFS_POLL) += poll.o
+aufs-$(CONFIG_AUFS_RDU) += rdu.o
+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dentry.h
+++ linux-ec2-2.6.32/ubuntu/aufs/dentry.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * lookup and dentry operations
+ */
+
+#ifndef __AUFS_DENTRY_H__
+#define __AUFS_DENTRY_H__
+
+#ifdef __KERNEL__
+
+#include <linux/dcache.h>
+#include <linux/aufs_type.h>
+#include "rwsem.h"
+
+/* make a single member structure for future use */
+/* todo: remove this structure */
+struct au_hdentry {
+	struct dentry		*hd_dentry;
+};
+
+struct au_dinfo {
+	atomic_t		di_generation;
+
+	struct au_rwsem		di_rwsem;
+	aufs_bindex_t		di_bstart, di_bend, di_bwh, di_bdiropq;
+	struct au_hdentry	*di_hdentry;
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* dentry.c */
+extern struct dentry_operations aufs_dop;
+struct au_branch;
+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
+			   struct au_branch *br, struct nameidata *nd);
+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
+			       struct au_branch *br);
+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
+		struct dentry *h_parent, struct au_branch *br);
+
+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
+		   struct nameidata *nd);
+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
+
+/* dinfo.c */
+int au_alloc_dinfo(struct dentry *dentry);
+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
+
+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
+void di_read_unlock(struct dentry *d, int flags);
+void di_downgrade_lock(struct dentry *d, int flags);
+void di_write_lock(struct dentry *d, unsigned int lsc);
+void di_write_unlock(struct dentry *d);
+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
+
+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
+aufs_bindex_t au_dbtail(struct dentry *dentry);
+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
+
+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
+		   struct dentry *h_dentry);
+void au_update_digen(struct dentry *dentry);
+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
+void au_update_dbstart(struct dentry *dentry);
+void au_update_dbend(struct dentry *dentry);
+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct au_dinfo *au_di(struct dentry *dentry)
+{
+	return dentry->d_fsdata;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* lock subclass for dinfo */
+enum {
+	AuLsc_DI_CHILD,		/* child first */
+	AuLsc_DI_CHILD2,	/* rename(2), link(2), and cpup at hinotify */
+	AuLsc_DI_CHILD3,	/* copyup dirs */
+	AuLsc_DI_PARENT,
+	AuLsc_DI_PARENT2,
+	AuLsc_DI_PARENT3
+};
+
+/*
+ * di_read_lock_child, di_write_lock_child,
+ * di_read_lock_child2, di_write_lock_child2,
+ * di_read_lock_child3, di_write_lock_child3,
+ * di_read_lock_parent, di_write_lock_parent,
+ * di_read_lock_parent2, di_write_lock_parent2,
+ * di_read_lock_parent3, di_write_lock_parent3,
+ */
+#define AuReadLockFunc(name, lsc) \
+static inline void di_read_lock_##name(struct dentry *d, int flags) \
+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
+
+#define AuWriteLockFunc(name, lsc) \
+static inline void di_write_lock_##name(struct dentry *d) \
+{ di_write_lock(d, AuLsc_DI_##lsc); }
+
+#define AuRWLockFuncs(name, lsc) \
+	AuReadLockFunc(name, lsc) \
+	AuWriteLockFunc(name, lsc)
+
+AuRWLockFuncs(child, CHILD);
+AuRWLockFuncs(child2, CHILD2);
+AuRWLockFuncs(child3, CHILD3);
+AuRWLockFuncs(parent, PARENT);
+AuRWLockFuncs(parent2, PARENT2);
+AuRWLockFuncs(parent3, PARENT3);
+
+#undef AuReadLockFunc
+#undef AuWriteLockFunc
+#undef AuRWLockFuncs
+
+#define DiMustNoWaiters(d)	AuRwMustNoWaiters(&au_di(d)->di_rwsem)
+#define DiMustAnyLock(d)	AuRwMustAnyLock(&au_di(d)->di_rwsem)
+#define DiMustWriteLock(d)	AuRwMustWriteLock(&au_di(d)->di_rwsem)
+
+/* ---------------------------------------------------------------------- */
+
+/* todo: memory barrier? */
+static inline unsigned int au_digen(struct dentry *d)
+{
+	return atomic_read(&au_di(d)->di_generation);
+}
+
+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
+{
+	hdentry->hd_dentry = NULL;
+}
+
+static inline void au_hdput(struct au_hdentry *hd)
+{
+	dput(hd->hd_dentry);
+}
+
+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
+{
+	DiMustAnyLock(dentry);
+	return au_di(dentry)->di_bstart;
+}
+
+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
+{
+	DiMustAnyLock(dentry);
+	return au_di(dentry)->di_bend;
+}
+
+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
+{
+	DiMustAnyLock(dentry);
+	return au_di(dentry)->di_bwh;
+}
+
+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
+{
+	DiMustAnyLock(dentry);
+	return au_di(dentry)->di_bdiropq;
+}
+
+/* todo: hard/soft set? */
+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	DiMustWriteLock(dentry);
+	au_di(dentry)->di_bstart = bindex;
+}
+
+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	DiMustWriteLock(dentry);
+	au_di(dentry)->di_bend = bindex;
+}
+
+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	DiMustWriteLock(dentry);
+	/* dbwh can be outside of bstart - bend range */
+	au_di(dentry)->di_bwh = bindex;
+}
+
+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	DiMustWriteLock(dentry);
+	au_di(dentry)->di_bdiropq = bindex;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_HINOTIFY
+static inline void au_digen_dec(struct dentry *d)
+{
+	atomic_dec_return(&au_di(d)->di_generation);
+}
+
+static inline void au_hin_di_reinit(struct dentry *dentry)
+{
+	dentry->d_fsdata = NULL;
+}
+#else
+static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
+{
+	/* empty */
+}
+#endif /* CONFIG_AUFS_HINOTIFY */
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DENTRY_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/cpup.c
+++ linux-ec2-2.6.32/ubuntu/aufs/cpup.c
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * copy-up functions, see wbr_policy.c for copy-down
+ */
+
+#include <linux/file.h>
+#include <linux/fs_stack.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include "aufs.h"
+
+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
+{
+	const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
+		| S_NOATIME | S_NOCMTIME;
+
+	dst->i_flags |= src->i_flags & ~mask;
+	if (au_test_fs_notime(dst->i_sb))
+		dst->i_flags |= S_NOATIME | S_NOCMTIME;
+}
+
+void au_cpup_attr_timesizes(struct inode *inode)
+{
+	struct inode *h_inode;
+
+	h_inode = au_h_iptr(inode, au_ibstart(inode));
+	fsstack_copy_attr_times(inode, h_inode);
+	vfsub_copy_inode_size(inode, h_inode);
+}
+
+void au_cpup_attr_nlink(struct inode *inode, int force)
+{
+	struct inode *h_inode;
+	struct super_block *sb;
+	aufs_bindex_t bindex, bend;
+
+	sb = inode->i_sb;
+	bindex = au_ibstart(inode);
+	h_inode = au_h_iptr(inode, bindex);
+	if (!force
+	    && !S_ISDIR(h_inode->i_mode)
+	    && au_opt_test(au_mntflags(sb), PLINK)
+	    && au_plink_test(inode))
+		return;
+
+	inode->i_nlink = h_inode->i_nlink;
+
+	/*
+	 * fewer nlink makes find(1) noisy, but larger nlink doesn't.
+	 * it may includes whplink directory.
+	 */
+	if (S_ISDIR(h_inode->i_mode)) {
+		bend = au_ibend(inode);
+		for (bindex++; bindex <= bend; bindex++) {
+			h_inode = au_h_iptr(inode, bindex);
+			if (h_inode)
+				au_add_nlink(inode, h_inode);
+		}
+	}
+}
+
+void au_cpup_attr_changeable(struct inode *inode)
+{
+	struct inode *h_inode;
+
+	h_inode = au_h_iptr(inode, au_ibstart(inode));
+	inode->i_mode = h_inode->i_mode;
+	inode->i_uid = h_inode->i_uid;
+	inode->i_gid = h_inode->i_gid;
+	au_cpup_attr_timesizes(inode);
+	au_cpup_attr_flags(inode, h_inode);
+}
+
+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
+{
+	struct au_iinfo *iinfo = au_ii(inode);
+
+	IiMustWriteLock(inode);
+
+	iinfo->ii_higen = h_inode->i_generation;
+	iinfo->ii_hsb1 = h_inode->i_sb;
+}
+
+void au_cpup_attr_all(struct inode *inode, int force)
+{
+	struct inode *h_inode;
+
+	h_inode = au_h_iptr(inode, au_ibstart(inode));
+	au_cpup_attr_changeable(inode);
+	if (inode->i_nlink > 0)
+		au_cpup_attr_nlink(inode, force);
+	inode->i_rdev = h_inode->i_rdev;
+	inode->i_blkbits = h_inode->i_blkbits;
+	au_cpup_igen(inode, h_inode);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
+
+/* keep the timestamps of the parent dir when cpup */
+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
+		    struct path *h_path)
+{
+	struct inode *h_inode;
+
+	dt->dt_dentry = dentry;
+	dt->dt_h_path = *h_path;
+	h_inode = h_path->dentry->d_inode;
+	dt->dt_atime = h_inode->i_atime;
+	dt->dt_mtime = h_inode->i_mtime;
+	/* smp_mb(); */
+}
+
+void au_dtime_revert(struct au_dtime *dt)
+{
+	struct iattr attr;
+	int err;
+
+	attr.ia_atime = dt->dt_atime;
+	attr.ia_mtime = dt->dt_mtime;
+	attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
+		| ATTR_ATIME | ATTR_ATIME_SET;
+
+	err = vfsub_notify_change(&dt->dt_h_path, &attr);
+	if (unlikely(err))
+		pr_warning("restoring timestamps failed(%d). ignored\n", err);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static noinline_for_stack
+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
+{
+	int err, sbits;
+	struct iattr ia;
+	struct path h_path;
+	struct inode *h_isrc, *h_idst;
+
+	h_path.dentry = au_h_dptr(dst, bindex);
+	h_idst = h_path.dentry->d_inode;
+	h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
+	h_isrc = h_src->d_inode;
+	ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
+		| ATTR_ATIME | ATTR_MTIME
+		| ATTR_ATIME_SET | ATTR_MTIME_SET;
+	ia.ia_uid = h_isrc->i_uid;
+	ia.ia_gid = h_isrc->i_gid;
+	ia.ia_atime = h_isrc->i_atime;
+	ia.ia_mtime = h_isrc->i_mtime;
+	if (h_idst->i_mode != h_isrc->i_mode
+	    && !S_ISLNK(h_idst->i_mode)) {
+		ia.ia_valid |= ATTR_MODE;
+		ia.ia_mode = h_isrc->i_mode;
+	}
+	sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
+	au_cpup_attr_flags(h_idst, h_isrc);
+	err = vfsub_notify_change(&h_path, &ia);
+
+	/* is this nfs only? */
+	if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
+		ia.ia_valid = ATTR_FORCE | ATTR_MODE;
+		ia.ia_mode = h_isrc->i_mode;
+		err = vfsub_notify_change(&h_path, &ia);
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
+			   char *buf, unsigned long blksize)
+{
+	int err;
+	size_t sz, rbytes, wbytes;
+	unsigned char all_zero;
+	char *p, *zp;
+	struct mutex *h_mtx;
+	/* reduce stack usage */
+	struct iattr *ia;
+
+	zp = page_address(ZERO_PAGE(0));
+	if (unlikely(!zp))
+		return -ENOMEM; /* possible? */
+
+	err = 0;
+	all_zero = 0;
+	while (len) {
+		AuDbg("len %lld\n", len);
+		sz = blksize;
+		if (len < blksize)
+			sz = len;
+
+		rbytes = 0;
+		/* todo: signal_pending? */
+		while (!rbytes || err == -EAGAIN || err == -EINTR) {
+			rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
+			err = rbytes;
+		}
+		if (unlikely(err < 0))
+			break;
+
+		all_zero = 0;
+		if (len >= rbytes && rbytes == blksize)
+			all_zero = !memcmp(buf, zp, rbytes);
+		if (!all_zero) {
+			wbytes = rbytes;
+			p = buf;
+			while (wbytes) {
+				size_t b;
+
+				b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
+				err = b;
+				/* todo: signal_pending? */
+				if (unlikely(err == -EAGAIN || err == -EINTR))
+					continue;
+				if (unlikely(err < 0))
+					break;
+				wbytes -= b;
+				p += b;
+			}
+		} else {
+			loff_t res;
+
+			AuLabel(hole);
+			res = vfsub_llseek(dst, rbytes, SEEK_CUR);
+			err = res;
+			if (unlikely(res < 0))
+				break;
+		}
+		len -= rbytes;
+		err = 0;
+	}
+
+	/* the last block may be a hole */
+	if (!err && all_zero) {
+		AuLabel(last hole);
+
+		err = 1;
+		if (au_test_nfs(dst->f_dentry->d_sb)) {
+			/* nfs requires this step to make last hole */
+			/* is this only nfs? */
+			do {
+				/* todo: signal_pending? */
+				err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
+			} while (err == -EAGAIN || err == -EINTR);
+			if (err == 1)
+				dst->f_pos--;
+		}
+
+		if (err == 1) {
+			ia = (void *)buf;
+			ia->ia_size = dst->f_pos;
+			ia->ia_valid = ATTR_SIZE | ATTR_FILE;
+			ia->ia_file = dst;
+			h_mtx = &dst->f_dentry->d_inode->i_mutex;
+			mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
+			err = vfsub_notify_change(&dst->f_path, ia);
+			mutex_unlock(h_mtx);
+		}
+	}
+
+	return err;
+}
+
+int au_copy_file(struct file *dst, struct file *src, loff_t len)
+{
+	int err;
+	unsigned long blksize;
+	unsigned char do_kfree;
+	char *buf;
+
+	err = -ENOMEM;
+	blksize = dst->f_dentry->d_sb->s_blocksize;
+	if (!blksize || PAGE_SIZE < blksize)
+		blksize = PAGE_SIZE;
+	AuDbg("blksize %lu\n", blksize);
+	do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
+	if (do_kfree)
+		buf = kmalloc(blksize, GFP_NOFS);
+	else
+		buf = (void *)__get_free_page(GFP_NOFS);
+	if (unlikely(!buf))
+		goto out;
+
+	if (len > (1 << 22))
+		AuDbg("copying a large file %lld\n", (long long)len);
+
+	src->f_pos = 0;
+	dst->f_pos = 0;
+	err = au_do_copy_file(dst, src, len, buf, blksize);
+	if (do_kfree)
+		kfree(buf);
+	else
+		free_page((unsigned long)buf);
+
+ out:
+	return err;
+}
+
+/*
+ * to support a sparse file which is opened with O_APPEND,
+ * we need to close the file.
+ */
+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
+			aufs_bindex_t bsrc, loff_t len)
+{
+	int err, i;
+	enum { SRC, DST };
+	struct {
+		aufs_bindex_t bindex;
+		unsigned int flags;
+		struct dentry *dentry;
+		struct file *file;
+		void *label, *label_file;
+	} *f, file[] = {
+		{
+			.bindex = bsrc,
+			.flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
+			.file = NULL,
+			.label = &&out,
+			.label_file = &&out_src
+		},
+		{
+			.bindex = bdst,
+			.flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
+			.file = NULL,
+			.label = &&out_src,
+			.label_file = &&out_dst
+		}
+	};
+	struct super_block *sb;
+
+	/* bsrc branch can be ro/rw. */
+	sb = dentry->d_sb;
+	f = file;
+	for (i = 0; i < 2; i++, f++) {
+		f->dentry = au_h_dptr(dentry, f->bindex);
+		f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
+		err = PTR_ERR(f->file);
+		if (IS_ERR(f->file))
+			goto *f->label;
+		err = -EINVAL;
+		if (unlikely(!f->file->f_op))
+			goto *f->label_file;
+	}
+
+	/* try stopping to update while we copyup */
+	IMustLock(file[SRC].dentry->d_inode);
+	err = au_copy_file(file[DST].file, file[SRC].file, len);
+
+ out_dst:
+	fput(file[DST].file);
+	au_sbr_put(sb, file[DST].bindex);
+ out_src:
+	fput(file[SRC].file);
+	au_sbr_put(sb, file[SRC].bindex);
+ out:
+	return err;
+}
+
+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
+			      aufs_bindex_t bsrc, loff_t len,
+			      struct inode *h_dir, struct path *h_path)
+{
+	int err, rerr;
+	loff_t l;
+
+	err = 0;
+	l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
+	if (len == -1 || l < len)
+		len = l;
+	if (len)
+		err = au_cp_regular(dentry, bdst, bsrc, len);
+	if (!err)
+		goto out; /* success */
+
+	rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
+	if (rerr) {
+		AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
+			AuDLNPair(h_path->dentry), err, rerr);
+		err = -EIO;
+	}
+
+ out:
+	return err;
+}
+
+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
+			      struct inode *h_dir)
+{
+	int err, symlen;
+	mm_segment_t old_fs;
+	char *sym;
+
+	err = -ENOSYS;
+	if (unlikely(!h_src->d_inode->i_op->readlink))
+		goto out;
+
+	err = -ENOMEM;
+	sym = __getname();
+	if (unlikely(!sym))
+		goto out;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
+						PATH_MAX);
+	err = symlen;
+	set_fs(old_fs);
+
+	if (symlen > 0) {
+		sym[symlen] = 0;
+		err = vfsub_symlink(h_dir, h_path, sym);
+	}
+	__putname(sym);
+
+ out:
+	return err;
+}
+
+/* return with the lower dst inode is locked */
+static noinline_for_stack
+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
+	       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
+	       struct dentry *dst_parent)
+{
+	int err;
+	umode_t mode;
+	unsigned int mnt_flags;
+	unsigned char isdir;
+	const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
+	struct au_dtime dt;
+	struct path h_path;
+	struct dentry *h_src, *h_dst, *h_parent;
+	struct inode *h_inode, *h_dir;
+	struct super_block *sb;
+
+	/* bsrc branch can be ro/rw. */
+	h_src = au_h_dptr(dentry, bsrc);
+	h_inode = h_src->d_inode;
+	AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
+
+	/* try stopping to be referenced while we are creating */
+	h_dst = au_h_dptr(dentry, bdst);
+	h_parent = h_dst->d_parent; /* dir inode is locked */
+	h_dir = h_parent->d_inode;
+	IMustLock(h_dir);
+	AuDebugOn(h_parent != h_dst->d_parent);
+
+	sb = dentry->d_sb;
+	h_path.mnt = au_sbr_mnt(sb, bdst);
+	if (do_dt) {
+		h_path.dentry = h_parent;
+		au_dtime_store(&dt, dst_parent, &h_path);
+	}
+	h_path.dentry = h_dst;
+
+	isdir = 0;
+	mode = h_inode->i_mode;
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+		/* try stopping to update while we are referencing */
+		IMustLock(h_inode);
+		err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
+		if (!err)
+			err = au_do_cpup_regular
+				(dentry, bdst, bsrc, len,
+				 au_h_iptr(dst_parent->d_inode, bdst), &h_path);
+		break;
+	case S_IFDIR:
+		isdir = 1;
+		err = vfsub_mkdir(h_dir, &h_path, mode);
+		if (!err) {
+			/*
+			 * strange behaviour from the users view,
+			 * particularry setattr case
+			 */
+			if (au_ibstart(dst_parent->d_inode) == bdst)
+				au_cpup_attr_nlink(dst_parent->d_inode,
+						   /*force*/1);
+			au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
+		}
+		break;
+	case S_IFLNK:
+		err = au_do_cpup_symlink(&h_path, h_src, h_dir);
+		break;
+	case S_IFCHR:
+	case S_IFBLK:
+		AuDebugOn(!capable(CAP_MKNOD));
+		/*FALLTHROUGH*/
+	case S_IFIFO:
+	case S_IFSOCK:
+		err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
+		break;
+	default:
+		AuIOErr("Unknown inode type 0%o\n", mode);
+		err = -EIO;
+	}
+
+	mnt_flags = au_mntflags(sb);
+	if (!au_opt_test(mnt_flags, UDBA_NONE)
+	    && !isdir
+	    && au_opt_test(mnt_flags, XINO)
+	    && h_inode->i_nlink == 1
+	    /* todo: unnecessary? */
+	    /* && dentry->d_inode->i_nlink == 1 */
+	    && bdst < bsrc
+	    && !au_ftest_cpup(flags, KEEPLINO))
+		au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
+		/* ignore this error */
+
+	if (do_dt)
+		au_dtime_revert(&dt);
+	return err;
+}
+
+/*
+ * copyup the @dentry from @bsrc to @bdst.
+ * the caller must set the both of lower dentries.
+ * @len is for truncating when it is -1 copyup the entire file.
+ * in link/rename cases, @dst_parent may be different from the real one.
+ */
+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
+			  aufs_bindex_t bsrc, loff_t len, unsigned int flags,
+			  struct dentry *dst_parent)
+{
+	int err, rerr;
+	aufs_bindex_t old_ibstart;
+	unsigned char isdir, plink;
+	struct au_dtime dt;
+	struct path h_path;
+	struct dentry *h_src, *h_dst, *h_parent;
+	struct inode *dst_inode, *h_dir, *inode;
+	struct super_block *sb;
+
+	AuDebugOn(bsrc <= bdst);
+
+	sb = dentry->d_sb;
+	h_path.mnt = au_sbr_mnt(sb, bdst);
+	h_dst = au_h_dptr(dentry, bdst);
+	h_parent = h_dst->d_parent; /* dir inode is locked */
+	h_dir = h_parent->d_inode;
+	IMustLock(h_dir);
+
+	h_src = au_h_dptr(dentry, bsrc);
+	inode = dentry->d_inode;
+
+	if (!dst_parent)
+		dst_parent = dget_parent(dentry);
+	else
+		dget(dst_parent);
+
+	plink = !!au_opt_test(au_mntflags(sb), PLINK);
+	dst_inode = au_h_iptr(inode, bdst);
+	if (dst_inode) {
+		if (unlikely(!plink)) {
+			err = -EIO;
+			AuIOErr("i%lu exists on a upper branch "
+				"but plink is disabled\n", inode->i_ino);
+			goto out;
+		}
+
+		if (dst_inode->i_nlink) {
+			const int do_dt = au_ftest_cpup(flags, DTIME);
+
+			h_src = au_plink_lkup(inode, bdst);
+			err = PTR_ERR(h_src);
+			if (IS_ERR(h_src))
+				goto out;
+			if (unlikely(!h_src->d_inode)) {
+				err = -EIO;
+				AuIOErr("i%lu exists on a upper branch "
+					"but plink is broken\n", inode->i_ino);
+				dput(h_src);
+				goto out;
+			}
+
+			if (do_dt) {
+				h_path.dentry = h_parent;
+				au_dtime_store(&dt, dst_parent, &h_path);
+			}
+			h_path.dentry = h_dst;
+			err = vfsub_link(h_src, h_dir, &h_path);
+			if (do_dt)
+				au_dtime_revert(&dt);
+			dput(h_src);
+			goto out;
+		} else
+			/* todo: cpup_wh_file? */
+			/* udba work */
+			au_update_brange(inode, 1);
+	}
+
+	old_ibstart = au_ibstart(inode);
+	err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
+	if (unlikely(err))
+		goto out;
+	dst_inode = h_dst->d_inode;
+	mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
+
+	err = cpup_iattr(dentry, bdst, h_src);
+	isdir = S_ISDIR(dst_inode->i_mode);
+	if (!err) {
+		if (bdst < old_ibstart)
+			au_set_ibstart(inode, bdst);
+		au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
+			      au_hi_flags(inode, isdir));
+		mutex_unlock(&dst_inode->i_mutex);
+		if (!isdir
+		    && h_src->d_inode->i_nlink > 1
+		    && plink)
+			au_plink_append(inode, bdst, h_dst);
+		goto out; /* success */
+	}
+
+	/* revert */
+	h_path.dentry = h_parent;
+	mutex_unlock(&dst_inode->i_mutex);
+	au_dtime_store(&dt, dst_parent, &h_path);
+	h_path.dentry = h_dst;
+	if (!isdir)
+		rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
+	else
+		rerr = vfsub_rmdir(h_dir, &h_path);
+	au_dtime_revert(&dt);
+	if (rerr) {
+		AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
+		err = -EIO;
+	}
+
+ out:
+	dput(dst_parent);
+	return err;
+}
+
+struct au_cpup_single_args {
+	int *errp;
+	struct dentry *dentry;
+	aufs_bindex_t bdst, bsrc;
+	loff_t len;
+	unsigned int flags;
+	struct dentry *dst_parent;
+};
+
+static void au_call_cpup_single(void *args)
+{
+	struct au_cpup_single_args *a = args;
+	*a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
+				  a->flags, a->dst_parent);
+}
+
+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
+		       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
+		       struct dentry *dst_parent)
+{
+	int err, wkq_err;
+	umode_t mode;
+	struct dentry *h_dentry;
+
+	h_dentry = au_h_dptr(dentry, bsrc);
+	mode = h_dentry->d_inode->i_mode & S_IFMT;
+	if ((mode != S_IFCHR && mode != S_IFBLK)
+	    || capable(CAP_MKNOD))
+		err = au_cpup_single(dentry, bdst, bsrc, len, flags,
+				     dst_parent);
+	else {
+		struct au_cpup_single_args args = {
+			.errp		= &err,
+			.dentry		= dentry,
+			.bdst		= bdst,
+			.bsrc		= bsrc,
+			.len		= len,
+			.flags		= flags,
+			.dst_parent	= dst_parent
+		};
+		wkq_err = au_wkq_wait(au_call_cpup_single, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	return err;
+}
+
+/*
+ * copyup the @dentry from the first active lower branch to @bdst,
+ * using au_cpup_single().
+ */
+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+			  unsigned int flags)
+{
+	int err;
+	aufs_bindex_t bsrc, bend;
+
+	bend = au_dbend(dentry);
+	for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
+		if (au_h_dptr(dentry, bsrc))
+			break;
+
+	err = au_lkup_neg(dentry, bdst);
+	if (!err) {
+		err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
+		if (!err)
+			return 0; /* success */
+
+		/* revert */
+		au_set_h_dptr(dentry, bdst, NULL);
+		au_set_dbstart(dentry, bsrc);
+	}
+
+	return err;
+}
+
+struct au_cpup_simple_args {
+	int *errp;
+	struct dentry *dentry;
+	aufs_bindex_t bdst;
+	loff_t len;
+	unsigned int flags;
+};
+
+static void au_call_cpup_simple(void *args)
+{
+	struct au_cpup_simple_args *a = args;
+	*a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
+}
+
+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+		       unsigned int flags)
+{
+	int err, wkq_err;
+	unsigned char do_sio;
+	struct dentry *parent;
+	struct inode *h_dir;
+
+	parent = dget_parent(dentry);
+	h_dir = au_h_iptr(parent->d_inode, bdst);
+	do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
+	if (!do_sio) {
+		/*
+		 * testing CAP_MKNOD is for generic fs,
+		 * but CAP_FSETID is for xfs only, currently.
+		 */
+		umode_t mode = dentry->d_inode->i_mode;
+		do_sio = (((mode & (S_IFCHR | S_IFBLK))
+			   && !capable(CAP_MKNOD))
+			  || ((mode & (S_ISUID | S_ISGID))
+			      && !capable(CAP_FSETID)));
+	}
+	if (!do_sio)
+		err = au_cpup_simple(dentry, bdst, len, flags);
+	else {
+		struct au_cpup_simple_args args = {
+			.errp		= &err,
+			.dentry		= dentry,
+			.bdst		= bdst,
+			.len		= len,
+			.flags		= flags
+		};
+		wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	dput(parent);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * copyup the deleted file for writing.
+ */
+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
+			 struct dentry *wh_dentry, struct file *file,
+			 loff_t len)
+{
+	int err;
+	aufs_bindex_t bstart;
+	struct au_dinfo *dinfo;
+	struct dentry *h_d_dst, *h_d_start;
+
+	dinfo = au_di(dentry);
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	bstart = dinfo->di_bstart;
+	h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
+	dinfo->di_bstart = bdst;
+	dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
+	h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
+	if (file)
+		dinfo->di_hdentry[0 + bstart].hd_dentry
+			= au_h_fptr(file, au_fbstart(file))->f_dentry;
+	err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
+			     /*h_parent*/NULL);
+	if (!err && file) {
+		err = au_reopen_nondir(file);
+		dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
+	}
+	dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
+	dinfo->di_bstart = bstart;
+
+	return err;
+}
+
+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+		      struct file *file)
+{
+	int err;
+	struct au_dtime dt;
+	struct dentry *parent, *h_parent, *wh_dentry;
+	struct au_branch *br;
+	struct path h_path;
+
+	br = au_sbr(dentry->d_sb, bdst);
+	parent = dget_parent(dentry);
+	h_parent = au_h_dptr(parent, bdst);
+	wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out;
+
+	h_path.dentry = h_parent;
+	h_path.mnt = br->br_mnt;
+	au_dtime_store(&dt, parent, &h_path);
+	err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
+	if (unlikely(err))
+		goto out_wh;
+
+	dget(wh_dentry);
+	h_path.dentry = wh_dentry;
+	err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
+	if (unlikely(err)) {
+		AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
+			AuDLNPair(wh_dentry), err);
+		err = -EIO;
+	}
+	au_dtime_revert(&dt);
+	au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
+
+ out_wh:
+	dput(wh_dentry);
+ out:
+	dput(parent);
+	return err;
+}
+
+struct au_cpup_wh_args {
+	int *errp;
+	struct dentry *dentry;
+	aufs_bindex_t bdst;
+	loff_t len;
+	struct file *file;
+};
+
+static void au_call_cpup_wh(void *args)
+{
+	struct au_cpup_wh_args *a = args;
+	*a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
+}
+
+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+		   struct file *file)
+{
+	int err, wkq_err;
+	struct dentry *parent, *h_orph, *h_parent, *h_dentry;
+	struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
+	struct au_wbr *wbr;
+
+	parent = dget_parent(dentry);
+	dir = parent->d_inode;
+	h_orph = NULL;
+	h_parent = NULL;
+	h_dir = au_igrab(au_h_iptr(dir, bdst));
+	h_tmpdir = h_dir;
+	if (!h_dir->i_nlink) {
+		wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
+		h_orph = wbr->wbr_orph;
+
+		h_parent = dget(au_h_dptr(parent, bdst));
+		au_set_h_dptr(parent, bdst, NULL);
+		au_set_h_dptr(parent, bdst, dget(h_orph));
+		h_tmpdir = h_orph->d_inode;
+		au_set_h_iptr(dir, bdst, NULL, 0);
+		au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
+
+		/* this temporary unlock is safe */
+		if (file)
+			h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
+		else
+			h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
+		h_inode = h_dentry->d_inode;
+		IMustLock(h_inode);
+		mutex_unlock(&h_inode->i_mutex);
+		mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
+		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+	}
+
+	if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
+		err = au_cpup_wh(dentry, bdst, len, file);
+	else {
+		struct au_cpup_wh_args args = {
+			.errp	= &err,
+			.dentry	= dentry,
+			.bdst	= bdst,
+			.len	= len,
+			.file	= file
+		};
+		wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	if (h_orph) {
+		mutex_unlock(&h_tmpdir->i_mutex);
+		au_set_h_iptr(dir, bdst, NULL, 0);
+		au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
+		au_set_h_dptr(parent, bdst, NULL);
+		au_set_h_dptr(parent, bdst, h_parent);
+	}
+	iput(h_dir);
+	dput(parent);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * generic routine for both of copy-up and copy-down.
+ */
+/* cf. revalidate function in file.c */
+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
+	       int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
+			 struct dentry *h_parent, void *arg),
+	       void *arg)
+{
+	int err;
+	struct au_pin pin;
+	struct dentry *d, *parent, *h_parent, *real_parent;
+
+	err = 0;
+	parent = dget_parent(dentry);
+	if (IS_ROOT(parent))
+		goto out;
+
+	au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
+		    au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
+
+	/* do not use au_dpage */
+	real_parent = parent;
+	while (1) {
+		dput(parent);
+		parent = dget_parent(dentry);
+		h_parent = au_h_dptr(parent, bdst);
+		if (h_parent)
+			goto out; /* success */
+
+		/* find top dir which is necessary to cpup */
+		do {
+			d = parent;
+			dput(parent);
+			parent = dget_parent(d);
+			di_read_lock_parent3(parent, !AuLock_IR);
+			h_parent = au_h_dptr(parent, bdst);
+			di_read_unlock(parent, !AuLock_IR);
+		} while (!h_parent);
+
+		if (d != real_parent)
+			di_write_lock_child3(d);
+
+		/* somebody else might create while we were sleeping */
+		if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
+			if (au_h_dptr(d, bdst))
+				au_update_dbstart(d);
+
+			au_pin_set_dentry(&pin, d);
+			err = au_do_pin(&pin);
+			if (!err) {
+				err = cp(d, bdst, h_parent, arg);
+				au_unpin(&pin);
+			}
+		}
+
+		if (d != real_parent)
+			di_write_unlock(d);
+		if (unlikely(err))
+			break;
+	}
+
+ out:
+	dput(parent);
+	return err;
+}
+
+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
+		       struct dentry *h_parent __maybe_unused ,
+		       void *arg __maybe_unused)
+{
+	return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
+}
+
+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
+{
+	return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
+}
+
+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
+{
+	int err;
+	struct dentry *parent;
+	struct inode *dir;
+
+	parent = dget_parent(dentry);
+	dir = parent->d_inode;
+	err = 0;
+	if (au_h_iptr(dir, bdst))
+		goto out;
+
+	di_read_unlock(parent, AuLock_IR);
+	di_write_lock_parent(parent);
+	/* someone else might change our inode while we were sleeping */
+	if (!au_h_iptr(dir, bdst))
+		err = au_cpup_dirs(dentry, bdst);
+	di_downgrade_lock(parent, AuLock_IR);
+
+ out:
+	dput(parent);
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/export.c
+++ linux-ec2-2.6.32/ubuntu/aufs/export.c
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * export via nfs
+ */
+
+#include <linux/exportfs.h>
+#include <linux/file.h>
+#include <linux/mnt_namespace.h>
+#include <linux/namei.h>
+#include <linux/nsproxy.h>
+#include <linux/random.h>
+#include "aufs.h"
+
+union conv {
+#ifdef CONFIG_AUFS_INO_T_64
+	__u32 a[2];
+#else
+	__u32 a[1];
+#endif
+	ino_t ino;
+};
+
+static ino_t decode_ino(__u32 *a)
+{
+	union conv u;
+
+	BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
+	u.a[0] = a[0];
+#ifdef CONFIG_AUFS_INO_T_64
+	u.a[1] = a[1];
+#endif
+	return u.ino;
+}
+
+static void encode_ino(__u32 *a, ino_t ino)
+{
+	union conv u;
+
+	u.ino = ino;
+	a[0] = u.a[0];
+#ifdef CONFIG_AUFS_INO_T_64
+	a[1] = u.a[1];
+#endif
+}
+
+/* NFS file handle */
+enum {
+	Fh_br_id,
+	Fh_sigen,
+#ifdef CONFIG_AUFS_INO_T_64
+	/* support 64bit inode number */
+	Fh_ino1,
+	Fh_ino2,
+	Fh_dir_ino1,
+	Fh_dir_ino2,
+#else
+	Fh_ino1,
+	Fh_dir_ino1,
+#endif
+	Fh_igen,
+	Fh_h_type,
+	Fh_tail,
+
+	Fh_ino = Fh_ino1,
+	Fh_dir_ino = Fh_dir_ino1
+};
+
+static int au_test_anon(struct dentry *dentry)
+{
+	return !!(dentry->d_flags & DCACHE_DISCONNECTED);
+}
+
+/* ---------------------------------------------------------------------- */
+/* inode generation external table */
+
+int au_xigen_inc(struct inode *inode)
+{
+	int err;
+	loff_t pos;
+	ssize_t sz;
+	__u32 igen;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+
+	err = 0;
+	sb = inode->i_sb;
+	sbinfo = au_sbi(sb);
+	/*
+	 * temporary workaround for escaping from SiMustAnyLock() in
+	 * au_mntflags(), since this function is called from au_iinfo_fin().
+	 */
+	if (unlikely(!au_opt_test(sbinfo->si_mntflags, XINO)))
+		goto out;
+
+	pos = inode->i_ino;
+	pos *= sizeof(igen);
+	igen = inode->i_generation + 1;
+	sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
+			 sizeof(igen), &pos);
+	if (sz == sizeof(igen))
+		goto out; /* success */
+
+	err = sz;
+	if (unlikely(sz >= 0)) {
+		err = -EIO;
+		AuIOErr("xigen error (%zd)\n", sz);
+	}
+
+ out:
+	return err;
+}
+
+int au_xigen_new(struct inode *inode)
+{
+	int err;
+	loff_t pos;
+	ssize_t sz;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+	struct file *file;
+
+	err = 0;
+	/* todo: dirty, at mount time */
+	if (inode->i_ino == AUFS_ROOT_INO)
+		goto out;
+	sb = inode->i_sb;
+	SiMustAnyLock(sb);
+	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
+		goto out;
+
+	err = -EFBIG;
+	pos = inode->i_ino;
+	if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
+		AuIOErr1("too large i%lld\n", pos);
+		goto out;
+	}
+	pos *= sizeof(inode->i_generation);
+
+	err = 0;
+	sbinfo = au_sbi(sb);
+	file = sbinfo->si_xigen;
+	BUG_ON(!file);
+
+	if (i_size_read(file->f_dentry->d_inode)
+	    < pos + sizeof(inode->i_generation)) {
+		inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
+		sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
+				 sizeof(inode->i_generation), &pos);
+	} else
+		sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
+				sizeof(inode->i_generation), &pos);
+	if (sz == sizeof(inode->i_generation))
+		goto out; /* success */
+
+	err = sz;
+	if (unlikely(sz >= 0)) {
+		err = -EIO;
+		AuIOErr("xigen error (%zd)\n", sz);
+	}
+
+ out:
+	return err;
+}
+
+int au_xigen_set(struct super_block *sb, struct file *base)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+	struct file *file;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	file = au_xino_create2(base, sbinfo->si_xigen);
+	err = PTR_ERR(file);
+	if (IS_ERR(file))
+		goto out;
+	err = 0;
+	if (sbinfo->si_xigen)
+		fput(sbinfo->si_xigen);
+	sbinfo->si_xigen = file;
+
+ out:
+	return err;
+}
+
+void au_xigen_clr(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	if (sbinfo->si_xigen) {
+		fput(sbinfo->si_xigen);
+		sbinfo->si_xigen = NULL;
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
+				    ino_t dir_ino)
+{
+	struct dentry *dentry, *d;
+	struct inode *inode;
+	unsigned int sigen;
+
+	dentry = NULL;
+	inode = ilookup(sb, ino);
+	if (!inode)
+		goto out;
+
+	dentry = ERR_PTR(-ESTALE);
+	sigen = au_sigen(sb);
+	if (unlikely(is_bad_inode(inode)
+		     || IS_DEADDIR(inode)
+		     || sigen != au_iigen(inode)))
+		goto out_iput;
+
+	dentry = NULL;
+	if (!dir_ino || S_ISDIR(inode->i_mode))
+		dentry = d_find_alias(inode);
+	else {
+		spin_lock(&dcache_lock);
+		list_for_each_entry(d, &inode->i_dentry, d_alias)
+			if (!au_test_anon(d)
+			    && d->d_parent->d_inode->i_ino == dir_ino) {
+				dentry = dget_locked(d);
+				break;
+			}
+		spin_unlock(&dcache_lock);
+	}
+	if (unlikely(dentry && sigen != au_digen(dentry))) {
+		dput(dentry);
+		dentry = ERR_PTR(-ESTALE);
+	}
+
+ out_iput:
+	iput(inode);
+ out:
+	return dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* todo: dirty? */
+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
+static struct vfsmount *au_mnt_get(struct super_block *sb)
+{
+	struct mnt_namespace *ns;
+	struct vfsmount *pos, *mnt;
+
+	spin_lock(&vfsmount_lock);
+	/* no get/put ?? */
+	AuDebugOn(!current->nsproxy);
+	ns = current->nsproxy->mnt_ns;
+	AuDebugOn(!ns);
+	mnt = NULL;
+	/* the order (reverse) will not be a problem */
+	list_for_each_entry(pos, &ns->list, mnt_list)
+		if (pos->mnt_sb == sb) {
+			mnt = mntget(pos);
+			break;
+		}
+	spin_unlock(&vfsmount_lock);
+	AuDebugOn(!mnt);
+
+	return mnt;
+}
+
+struct au_nfsd_si_lock {
+	const unsigned int sigen;
+	const aufs_bindex_t br_id;
+	unsigned char force_lock;
+};
+
+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
+				       struct au_nfsd_si_lock *nsi_lock)
+{
+	aufs_bindex_t bindex;
+
+	si_read_lock(sb, AuLock_FLUSH);
+
+	/* branch id may be wrapped around */
+	bindex = au_br_index(sb, nsi_lock->br_id);
+	if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
+		goto out; /* success */
+
+	if (!nsi_lock->force_lock)
+		si_read_unlock(sb);
+	bindex = -1;
+
+ out:
+	return bindex;
+}
+
+struct find_name_by_ino {
+	int called, found;
+	ino_t ino;
+	char *name;
+	int namelen;
+};
+
+static int
+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
+		 u64 ino, unsigned int d_type)
+{
+	struct find_name_by_ino *a = arg;
+
+	a->called++;
+	if (a->ino != ino)
+		return 0;
+
+	memcpy(a->name, name, namelen);
+	a->namelen = namelen;
+	a->found = 1;
+	return 1;
+}
+
+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
+				     struct au_nfsd_si_lock *nsi_lock)
+{
+	struct dentry *dentry, *parent;
+	struct file *file;
+	struct inode *dir;
+	struct find_name_by_ino arg;
+	int err;
+
+	parent = path->dentry;
+	if (nsi_lock)
+		si_read_unlock(parent->d_sb);
+	path_get(path);
+	file = vfsub_dentry_open(path, au_dir_roflags, current_cred());
+	dentry = (void *)file;
+	if (IS_ERR(file))
+		goto out;
+
+	dentry = ERR_PTR(-ENOMEM);
+	arg.name = __getname();
+	if (unlikely(!arg.name))
+		goto out_file;
+	arg.ino = ino;
+	arg.found = 0;
+	do {
+		arg.called = 0;
+		/* smp_mb(); */
+		err = vfsub_readdir(file, find_name_by_ino, &arg);
+	} while (!err && !arg.found && arg.called);
+	dentry = ERR_PTR(err);
+	if (unlikely(err))
+		goto out_name;
+	dentry = ERR_PTR(-ENOENT);
+	if (!arg.found)
+		goto out_name;
+
+	/* do not call au_lkup_one() */
+	dir = parent->d_inode;
+	mutex_lock(&dir->i_mutex);
+	dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
+	mutex_unlock(&dir->i_mutex);
+	AuTraceErrPtr(dentry);
+	if (IS_ERR(dentry))
+		goto out_name;
+	AuDebugOn(au_test_anon(dentry));
+	if (unlikely(!dentry->d_inode)) {
+		dput(dentry);
+		dentry = ERR_PTR(-ENOENT);
+	}
+
+ out_name:
+	__putname(arg.name);
+ out_file:
+	fput(file);
+ out:
+	if (unlikely(nsi_lock
+		     && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
+		if (!IS_ERR(dentry)) {
+			dput(dentry);
+			dentry = ERR_PTR(-ESTALE);
+		}
+	AuTraceErrPtr(dentry);
+	return dentry;
+}
+
+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
+					ino_t dir_ino,
+					struct au_nfsd_si_lock *nsi_lock)
+{
+	struct dentry *dentry;
+	struct path path;
+
+	if (dir_ino != AUFS_ROOT_INO) {
+		path.dentry = decode_by_ino(sb, dir_ino, 0);
+		dentry = path.dentry;
+		if (!path.dentry || IS_ERR(path.dentry))
+			goto out;
+		AuDebugOn(au_test_anon(path.dentry));
+	} else
+		path.dentry = dget(sb->s_root);
+
+	path.mnt = au_mnt_get(sb);
+	dentry = au_lkup_by_ino(&path, ino, nsi_lock);
+	path_put(&path);
+
+ out:
+	AuTraceErrPtr(dentry);
+	return dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int h_acceptable(void *expv, struct dentry *dentry)
+{
+	return 1;
+}
+
+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
+			   char *buf, int len, struct super_block *sb)
+{
+	char *p;
+	int n;
+	struct path path;
+
+	p = d_path(h_rootpath, buf, len);
+	if (IS_ERR(p))
+		goto out;
+	n = strlen(p);
+
+	path.mnt = h_rootpath->mnt;
+	path.dentry = h_parent;
+	p = d_path(&path, buf, len);
+	if (IS_ERR(p))
+		goto out;
+	if (n != 1)
+		p += n;
+
+	path.mnt = au_mnt_get(sb);
+	path.dentry = sb->s_root;
+	p = d_path(&path, buf, len - strlen(p));
+	mntput(path.mnt);
+	if (IS_ERR(p))
+		goto out;
+	if (n != 1)
+		p[strlen(p)] = '/';
+
+ out:
+	AuTraceErrPtr(p);
+	return p;
+}
+
+static
+struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
+			      ino_t ino, __u32 *fh, int fh_len,
+			      struct au_nfsd_si_lock *nsi_lock)
+{
+	struct dentry *dentry, *h_parent, *root;
+	struct super_block *h_sb;
+	char *pathname, *p;
+	struct vfsmount *h_mnt;
+	struct au_branch *br;
+	int err;
+	struct path path;
+
+	br = au_sbr(sb, bindex);
+	/* au_br_get(br); */
+	h_mnt = br->br_mnt;
+	h_sb = h_mnt->mnt_sb;
+	/* todo: call lower fh_to_dentry()? fh_to_parent()? */
+	h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
+				      fh_len - Fh_tail, fh[Fh_h_type],
+				      h_acceptable, /*context*/NULL);
+	dentry = h_parent;
+	if (unlikely(!h_parent || IS_ERR(h_parent))) {
+		AuWarn1("%s decode_fh failed, %ld\n",
+			au_sbtype(h_sb), PTR_ERR(h_parent));
+		goto out;
+	}
+	dentry = NULL;
+	if (unlikely(au_test_anon(h_parent))) {
+		AuWarn1("%s decode_fh returned a disconnected dentry\n",
+			au_sbtype(h_sb));
+		goto out_h_parent;
+	}
+
+	dentry = ERR_PTR(-ENOMEM);
+	pathname = (void *)__get_free_page(GFP_NOFS);
+	if (unlikely(!pathname))
+		goto out_h_parent;
+
+	root = sb->s_root;
+	path.mnt = h_mnt;
+	di_read_lock_parent(root, !AuLock_IR);
+	path.dentry = au_h_dptr(root, bindex);
+	di_read_unlock(root, !AuLock_IR);
+	p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
+	dentry = (void *)p;
+	if (IS_ERR(p))
+		goto out_pathname;
+
+	si_read_unlock(sb);
+	err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+	dentry = ERR_PTR(err);
+	if (unlikely(err))
+		goto out_relock;
+
+	dentry = ERR_PTR(-ENOENT);
+	AuDebugOn(au_test_anon(path.dentry));
+	if (unlikely(!path.dentry->d_inode))
+		goto out_path;
+
+	if (ino != path.dentry->d_inode->i_ino)
+		dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
+	else
+		dentry = dget(path.dentry);
+
+ out_path:
+	path_put(&path);
+ out_relock:
+	if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
+		if (!IS_ERR(dentry)) {
+			dput(dentry);
+			dentry = ERR_PTR(-ESTALE);
+		}
+ out_pathname:
+	free_page((unsigned long)pathname);
+ out_h_parent:
+	dput(h_parent);
+ out:
+	/* au_br_put(br); */
+	AuTraceErrPtr(dentry);
+	return dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct dentry *
+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
+		  int fh_type)
+{
+	struct dentry *dentry;
+	__u32 *fh = fid->raw;
+	ino_t ino, dir_ino;
+	aufs_bindex_t bindex;
+	struct au_nfsd_si_lock nsi_lock = {
+		.sigen		= fh[Fh_sigen],
+		.br_id		= fh[Fh_br_id],
+		.force_lock	= 0
+	};
+
+	AuDebugOn(fh_len < Fh_tail);
+
+	dentry = ERR_PTR(-ESTALE);
+	/* branch id may be wrapped around */
+	bindex = si_nfsd_read_lock(sb, &nsi_lock);
+	if (unlikely(bindex < 0))
+		goto out;
+	nsi_lock.force_lock = 1;
+
+	/* is this inode still cached? */
+	ino = decode_ino(fh + Fh_ino);
+	AuDebugOn(ino == AUFS_ROOT_INO);
+	dir_ino = decode_ino(fh + Fh_dir_ino);
+	dentry = decode_by_ino(sb, ino, dir_ino);
+	if (IS_ERR(dentry))
+		goto out_unlock;
+	if (dentry)
+		goto accept;
+
+	/* is the parent dir cached? */
+	dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
+	if (IS_ERR(dentry))
+		goto out_unlock;
+	if (dentry)
+		goto accept;
+
+	/* lookup path */
+	dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
+	if (IS_ERR(dentry))
+		goto out_unlock;
+	if (unlikely(!dentry))
+		/* todo?: make it ESTALE */
+		goto out_unlock;
+
+ accept:
+	if (dentry->d_inode->i_generation == fh[Fh_igen])
+		goto out_unlock; /* success */
+
+	dput(dentry);
+	dentry = ERR_PTR(-ESTALE);
+ out_unlock:
+	si_read_unlock(sb);
+ out:
+	AuTraceErrPtr(dentry);
+	return dentry;
+}
+
+#if 0 /* reserved for future use */
+/* support subtreecheck option */
+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
+					int fh_len, int fh_type)
+{
+	struct dentry *parent;
+	__u32 *fh = fid->raw;
+	ino_t dir_ino;
+
+	dir_ino = decode_ino(fh + Fh_dir_ino);
+	parent = decode_by_ino(sb, dir_ino, 0);
+	if (IS_ERR(parent))
+		goto out;
+	if (!parent)
+		parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
+					dir_ino, fh, fh_len);
+
+ out:
+	AuTraceErrPtr(parent);
+	return parent;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+			  int connectable)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	struct super_block *sb, *h_sb;
+	struct inode *inode;
+	struct dentry *parent, *h_parent;
+	struct au_branch *br;
+
+	AuDebugOn(au_test_anon(dentry));
+
+	parent = NULL;
+	err = -ENOSPC;
+	if (unlikely(*max_len <= Fh_tail)) {
+		AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
+		goto out;
+	}
+
+	err = FILEID_ROOT;
+	if (IS_ROOT(dentry)) {
+		AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
+		goto out;
+	}
+
+	err = -EIO;
+	h_parent = NULL;
+	sb = dentry->d_sb;
+	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
+	parent = dget_parent(dentry);
+	di_read_lock_parent(parent, !AuLock_IR);
+	inode = dentry->d_inode;
+	AuDebugOn(!inode);
+#ifdef CONFIG_AUFS_DEBUG
+	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
+		AuWarn1("NFS-exporting requires xino\n");
+#endif
+
+	bend = au_dbtaildir(parent);
+	for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
+		h_parent = au_h_dptr(parent, bindex);
+		if (h_parent) {
+			dget(h_parent);
+			break;
+		}
+	}
+	if (unlikely(!h_parent))
+		goto out_unlock;
+
+	err = -EPERM;
+	br = au_sbr(sb, bindex);
+	h_sb = br->br_mnt->mnt_sb;
+	if (unlikely(!h_sb->s_export_op)) {
+		AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
+		goto out_dput;
+	}
+
+	fh[Fh_br_id] = br->br_id;
+	fh[Fh_sigen] = au_sigen(sb);
+	encode_ino(fh + Fh_ino, inode->i_ino);
+	encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
+	fh[Fh_igen] = inode->i_generation;
+
+	*max_len -= Fh_tail;
+	fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
+					   max_len,
+					   /*connectable or subtreecheck*/0);
+	err = fh[Fh_h_type];
+	*max_len += Fh_tail;
+	/* todo: macros? */
+	if (err != 255)
+		err = 99;
+	else
+		AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
+
+ out_dput:
+	dput(h_parent);
+ out_unlock:
+	di_read_unlock(parent, !AuLock_IR);
+	dput(parent);
+	aufs_read_unlock(dentry, AuLock_IR);
+ out:
+	if (unlikely(err < 0))
+		err = 255;
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct export_operations aufs_export_op = {
+	.fh_to_dentry	= aufs_fh_to_dentry,
+	/* .fh_to_parent	= aufs_fh_to_parent, */
+	.encode_fh	= aufs_encode_fh
+};
+
+void au_export_init(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+	__u32 u;
+
+	sb->s_export_op = &aufs_export_op;
+	sbinfo = au_sbi(sb);
+	sbinfo->si_xigen = NULL;
+	get_random_bytes(&u, sizeof(u));
+	BUILD_BUG_ON(sizeof(u) != sizeof(int));
+	atomic_set(&sbinfo->si_xigen_next, u);
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/magic.mk
+++ linux-ec2-2.6.32/ubuntu/aufs/magic.mk
@@ -0,0 +1,48 @@
+
+# defined in ${srctree}/fs/fuse/inode.c
+# tristate
+ifdef CONFIG_FUSE_FS
+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
+endif
+
+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
+# tristate
+ifdef CONFIG_OCFS2_FS
+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
+endif
+
+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
+# tristate
+ifdef CONFIG_OCFS2_FS_O2CB
+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
+endif
+
+# defined in ${srctree}/fs/cifs/cifsfs.c
+# tristate
+ifdef CONFIG_CIFS_FS
+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
+endif
+
+# defined in ${srctree}/fs/xfs/xfs_sb.h
+# tristate
+ifdef CONFIG_XFS_FS
+ccflags-y += -DXFS_SB_MAGIC=0x58465342
+endif
+
+# defined in ${srctree}/fs/configfs/mount.c
+# tristate
+ifdef CONFIG_CONFIGFS_FS
+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
+endif
+
+# defined in ${srctree}/fs/9p/v9fs.h
+# tristate
+ifdef CONFIG_9P_FS
+ccflags-y += -DV9FS_MAGIC=0x01021997
+endif
+
+# defined in ${srctree}/fs/ubifs/ubifs.h
+# tristate
+ifdef CONFIG_UBIFS_FS
+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
+endif
--- linux-ec2-2.6.32.orig/ubuntu/aufs/super.h
+++ linux-ec2-2.6.32/ubuntu/aufs/super.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * super_block operations
+ */
+
+#ifndef __AUFS_SUPER_H__
+#define __AUFS_SUPER_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/aufs_type.h>
+#include "rwsem.h"
+#include "spl.h"
+#include "wkq.h"
+
+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
+			       loff_t *);
+
+/* policies to select one among multiple writable branches */
+struct au_wbr_copyup_operations {
+	int (*copyup)(struct dentry *dentry);
+};
+
+struct au_wbr_create_operations {
+	int (*create)(struct dentry *dentry, int isdir);
+	int (*init)(struct super_block *sb);
+	int (*fin)(struct super_block *sb);
+};
+
+struct au_wbr_mfs {
+	struct mutex	mfs_lock; /* protect this structure */
+	unsigned long	mfs_jiffy;
+	unsigned long	mfs_expire;
+	aufs_bindex_t	mfs_bindex;
+
+	unsigned long long	mfsrr_bytes;
+	unsigned long long	mfsrr_watermark;
+};
+
+struct au_branch;
+struct au_sbinfo {
+	/* nowait tasks in the system-wide workqueue */
+	struct au_nowait_tasks	si_nowait;
+
+	struct au_rwsem		si_rwsem;
+
+	/* branch management */
+	unsigned int		si_generation;
+
+	/* see above flags */
+	unsigned char		au_si_status;
+
+	aufs_bindex_t		si_bend;
+	aufs_bindex_t		si_last_br_id;
+	struct au_branch	**si_branch;
+
+	/* policy to select a writable branch */
+	unsigned char		si_wbr_copyup;
+	unsigned char		si_wbr_create;
+	struct au_wbr_copyup_operations *si_wbr_copyup_ops;
+	struct au_wbr_create_operations *si_wbr_create_ops;
+
+	/* round robin */
+	atomic_t		si_wbr_rr_next;
+
+	/* most free space */
+	struct au_wbr_mfs	si_wbr_mfs;
+
+	/* mount flags */
+	/* include/asm-ia64/siginfo.h defines a macro named si_flags */
+	unsigned int		si_mntflags;
+
+	/* external inode number (bitmap and translation table) */
+	au_readf_t		si_xread;
+	au_writef_t		si_xwrite;
+	struct file		*si_xib;
+	struct mutex		si_xib_mtx; /* protect xib members */
+	unsigned long		*si_xib_buf;
+	unsigned long		si_xib_last_pindex;
+	int			si_xib_next_bit;
+	aufs_bindex_t		si_xino_brid;
+	/* reserved for future use */
+	/* unsigned long long	si_xib_limit; */	/* Max xib file size */
+
+#ifdef CONFIG_AUFS_EXPORT
+	/* i_generation */
+	struct file		*si_xigen;
+	atomic_t		si_xigen_next;
+#endif
+
+	/* vdir parameters */
+	unsigned long		si_rdcache;	/* max cache time in HZ */
+	unsigned int		si_rdblk;	/* deblk size */
+	unsigned int		si_rdhash;	/* hash size */
+
+	/*
+	 * If the number of whiteouts are larger than si_dirwh, leave all of
+	 * them after au_whtmp_ren to reduce the cost of rmdir(2).
+	 * future fsck.aufs or kernel thread will remove them later.
+	 * Otherwise, remove all whiteouts and the dir in rmdir(2).
+	 */
+	unsigned int		si_dirwh;
+
+	/*
+	 * rename(2) a directory with all children.
+	 */
+	/* reserved for future use */
+	/* int			si_rendir; */
+
+	/* pseudo_link list */
+	struct au_splhead	si_plink;
+	wait_queue_head_t	si_plink_wq;
+
+	/*
+	 * sysfs and lifetime management.
+	 * this is not a small structure and it may be a waste of memory in case
+	 * of sysfs is disabled, particulary when many aufs-es are mounted.
+	 * but using sysfs is majority.
+	 */
+	struct kobject		si_kobj;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry		 *si_dbgaufs, *si_dbgaufs_xib;
+#ifdef CONFIG_AUFS_EXPORT
+	struct dentry		 *si_dbgaufs_xigen;
+#endif
+#endif
+
+	/* dirty, necessary for unmounting, sysfs and sysrq */
+	struct super_block	*si_sb;
+};
+
+/* sbinfo status flags */
+/*
+ * set true when refresh_dirs() failed at remount time.
+ * then try refreshing dirs at access time again.
+ * if it is false, refreshing dirs at access time is unnecesary
+ */
+#define AuSi_FAILED_REFRESH_DIRS	1
+#define AuSi_MAINTAIN_PLINK		(1 << 1)	/* ioctl */
+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
+					   unsigned int flag)
+{
+	AuRwMustAnyLock(&sbi->si_rwsem);
+	return sbi->au_si_status & flag;
+}
+#define au_ftest_si(sbinfo, name)	au_do_ftest_si(sbinfo, AuSi_##name)
+#define au_fset_si(sbinfo, name) do { \
+	AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
+	(sbinfo)->au_si_status |= AuSi_##name; \
+} while (0)
+#define au_fclr_si(sbinfo, name) do { \
+	AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
+	(sbinfo)->au_si_status &= ~AuSi_##name; \
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+
+/* policy to select one among writable branches */
+#define AuWbrCopyup(sbinfo, ...) \
+	((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
+#define AuWbrCreate(sbinfo, ...) \
+	((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
+
+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
+#define AuLock_DW		1		/* write-lock dentry */
+#define AuLock_IR		(1 << 1)	/* read-lock inode */
+#define AuLock_IW		(1 << 2)	/* write-lock inode */
+#define AuLock_FLUSH		(1 << 3)	/* wait for 'nowait' tasks */
+#define AuLock_DIR		(1 << 4)	/* target is a dir */
+#define au_ftest_lock(flags, name)	((flags) & AuLock_##name)
+#define au_fset_lock(flags, name)	{ (flags) |= AuLock_##name; }
+#define au_fclr_lock(flags, name)	{ (flags) &= ~AuLock_##name; }
+
+/* ---------------------------------------------------------------------- */
+
+/* super.c */
+extern struct file_system_type aufs_fs_type;
+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
+
+/* sbinfo.c */
+void au_si_free(struct kobject *kobj);
+int au_si_alloc(struct super_block *sb);
+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
+
+unsigned int au_sigen_inc(struct super_block *sb);
+aufs_bindex_t au_new_br_id(struct super_block *sb);
+
+void aufs_read_lock(struct dentry *dentry, int flags);
+void aufs_read_unlock(struct dentry *dentry, int flags);
+void aufs_write_lock(struct dentry *dentry);
+void aufs_write_unlock(struct dentry *dentry);
+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
+
+/* wbr_policy.c */
+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
+extern struct au_wbr_create_operations au_wbr_create_ops[];
+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_EXPORT
+void au_export_init(struct super_block *sb);
+
+static inline int au_test_nfsd(struct task_struct *tsk)
+{
+	return !tsk->mm && !strcmp(tsk->comm, "nfsd");
+}
+
+int au_xigen_inc(struct inode *inode);
+int au_xigen_new(struct inode *inode);
+int au_xigen_set(struct super_block *sb, struct file *base);
+void au_xigen_clr(struct super_block *sb);
+
+static inline int au_busy_or_stale(void)
+{
+	if (!au_test_nfsd(current))
+		return -EBUSY;
+	return -ESTALE;
+}
+#else
+static inline void au_export_init(struct super_block *sb)
+{
+	/* nothing */
+}
+
+static inline int au_test_nfsd(struct task_struct *tsk)
+{
+	return 0;
+}
+
+static inline int au_xigen_inc(struct inode *inode)
+{
+	return 0;
+}
+
+static inline int au_xigen_new(struct inode *inode)
+{
+	return 0;
+}
+
+static inline int au_xigen_set(struct super_block *sb, struct file *base)
+{
+	return 0;
+}
+
+static inline void au_xigen_clr(struct super_block *sb)
+{
+	/* empty */
+}
+
+static inline int au_busy_or_stale(void)
+{
+	return -EBUSY;
+}
+#endif /* CONFIG_AUFS_EXPORT */
+
+/* ---------------------------------------------------------------------- */
+
+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
+{
+	/*
+	 * This function is a dynamic '__init' fucntion actually,
+	 * so the tiny check for si_rwsem is unnecessary.
+	 */
+	/* AuRwMustWriteLock(&sbinfo->si_rwsem); */
+#ifdef CONFIG_DEBUG_FS
+	sbinfo->si_dbgaufs = NULL;
+	sbinfo->si_dbgaufs_xib = NULL;
+#ifdef CONFIG_AUFS_EXPORT
+	sbinfo->si_dbgaufs_xigen = NULL;
+#endif
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* lock superblock. mainly for entry point functions */
+/*
+ * si_noflush_read_lock, si_noflush_write_lock,
+ * si_read_unlock, si_write_unlock, si_downgrade_lock
+ */
+AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
+		       &au_sbi(sb)->si_rwsem);
+AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
+
+#define SiMustNoWaiters(sb)	AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
+#define SiMustAnyLock(sb)	AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
+#define SiMustWriteLock(sb)	AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
+
+static inline void si_read_lock(struct super_block *sb, int flags)
+{
+	if (au_ftest_lock(flags, FLUSH))
+		au_nwt_flush(&au_sbi(sb)->si_nowait);
+	si_noflush_read_lock(sb);
+}
+
+static inline void si_write_lock(struct super_block *sb)
+{
+	au_nwt_flush(&au_sbi(sb)->si_nowait);
+	si_noflush_write_lock(sb);
+}
+
+static inline int si_read_trylock(struct super_block *sb, int flags)
+{
+	if (au_ftest_lock(flags, FLUSH))
+		au_nwt_flush(&au_sbi(sb)->si_nowait);
+	return si_noflush_read_trylock(sb);
+}
+
+static inline int si_write_trylock(struct super_block *sb, int flags)
+{
+	if (au_ftest_lock(flags, FLUSH))
+		au_nwt_flush(&au_sbi(sb)->si_nowait);
+	return si_noflush_write_trylock(sb);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static inline aufs_bindex_t au_sbend(struct super_block *sb)
+{
+	SiMustAnyLock(sb);
+	return au_sbi(sb)->si_bend;
+}
+
+static inline unsigned int au_mntflags(struct super_block *sb)
+{
+	SiMustAnyLock(sb);
+	return au_sbi(sb)->si_mntflags;
+}
+
+static inline unsigned int au_sigen(struct super_block *sb)
+{
+	SiMustAnyLock(sb);
+	return au_sbi(sb)->si_generation;
+}
+
+static inline struct au_branch *au_sbr(struct super_block *sb,
+				       aufs_bindex_t bindex)
+{
+	SiMustAnyLock(sb);
+	return au_sbi(sb)->si_branch[0 + bindex];
+}
+
+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
+{
+	SiMustWriteLock(sb);
+	au_sbi(sb)->si_xino_brid = brid;
+}
+
+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
+{
+	SiMustAnyLock(sb);
+	return au_sbi(sb)->si_xino_brid;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_SUPER_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dinfo.c
+++ linux-ec2-2.6.32/ubuntu/aufs/dinfo.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * dentry private data
+ */
+
+#include "aufs.h"
+
+int au_alloc_dinfo(struct dentry *dentry)
+{
+	struct au_dinfo *dinfo;
+	struct super_block *sb;
+	int nbr;
+
+	dinfo = au_cache_alloc_dinfo();
+	if (unlikely(!dinfo))
+		goto out;
+
+	sb = dentry->d_sb;
+	nbr = au_sbend(sb) + 1;
+	if (nbr <= 0)
+		nbr = 1;
+	dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
+	if (unlikely(!dinfo->di_hdentry))
+		goto out_dinfo;
+
+	atomic_set(&dinfo->di_generation, au_sigen(sb));
+	/* smp_mb(); */ /* atomic_set */
+	au_rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
+	dinfo->di_bstart = -1;
+	dinfo->di_bend = -1;
+	dinfo->di_bwh = -1;
+	dinfo->di_bdiropq = -1;
+
+	dentry->d_fsdata = dinfo;
+	dentry->d_op = &aufs_dop;
+	return 0; /* success */
+
+ out_dinfo:
+	au_cache_free_dinfo(dinfo);
+ out:
+	return -ENOMEM;
+}
+
+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
+{
+	int err, sz;
+	struct au_hdentry *hdp;
+
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	err = -ENOMEM;
+	sz = sizeof(*hdp) * (dinfo->di_bend + 1);
+	if (!sz)
+		sz = sizeof(*hdp);
+	hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
+	if (hdp) {
+		dinfo->di_hdentry = hdp;
+		err = 0;
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
+{
+	switch (lsc) {
+	case AuLsc_DI_CHILD:
+		ii_write_lock_child(inode);
+		break;
+	case AuLsc_DI_CHILD2:
+		ii_write_lock_child2(inode);
+		break;
+	case AuLsc_DI_CHILD3:
+		ii_write_lock_child3(inode);
+		break;
+	case AuLsc_DI_PARENT:
+		ii_write_lock_parent(inode);
+		break;
+	case AuLsc_DI_PARENT2:
+		ii_write_lock_parent2(inode);
+		break;
+	case AuLsc_DI_PARENT3:
+		ii_write_lock_parent3(inode);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
+{
+	switch (lsc) {
+	case AuLsc_DI_CHILD:
+		ii_read_lock_child(inode);
+		break;
+	case AuLsc_DI_CHILD2:
+		ii_read_lock_child2(inode);
+		break;
+	case AuLsc_DI_CHILD3:
+		ii_read_lock_child3(inode);
+		break;
+	case AuLsc_DI_PARENT:
+		ii_read_lock_parent(inode);
+		break;
+	case AuLsc_DI_PARENT2:
+		ii_read_lock_parent2(inode);
+		break;
+	case AuLsc_DI_PARENT3:
+		ii_read_lock_parent3(inode);
+		break;
+	default:
+		BUG();
+	}
+}
+
+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
+{
+	au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
+	if (d->d_inode) {
+		if (au_ftest_lock(flags, IW))
+			do_ii_write_lock(d->d_inode, lsc);
+		else if (au_ftest_lock(flags, IR))
+			do_ii_read_lock(d->d_inode, lsc);
+	}
+}
+
+void di_read_unlock(struct dentry *d, int flags)
+{
+	if (d->d_inode) {
+		if (au_ftest_lock(flags, IW))
+			ii_write_unlock(d->d_inode);
+		else if (au_ftest_lock(flags, IR))
+			ii_read_unlock(d->d_inode);
+	}
+	au_rw_read_unlock(&au_di(d)->di_rwsem);
+}
+
+void di_downgrade_lock(struct dentry *d, int flags)
+{
+	if (d->d_inode && au_ftest_lock(flags, IR))
+		ii_downgrade_lock(d->d_inode);
+	au_rw_dgrade_lock(&au_di(d)->di_rwsem);
+}
+
+void di_write_lock(struct dentry *d, unsigned int lsc)
+{
+	au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
+	if (d->d_inode)
+		do_ii_write_lock(d->d_inode, lsc);
+}
+
+void di_write_unlock(struct dentry *d)
+{
+	if (d->d_inode)
+		ii_write_unlock(d->d_inode);
+	au_rw_write_unlock(&au_di(d)->di_rwsem);
+}
+
+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
+{
+	AuDebugOn(d1 == d2
+		  || d1->d_inode == d2->d_inode
+		  || d1->d_sb != d2->d_sb);
+
+	if (isdir && au_test_subdir(d1, d2)) {
+		di_write_lock_child(d1);
+		di_write_lock_child2(d2);
+	} else {
+		/* there should be no races */
+		di_write_lock_child(d2);
+		di_write_lock_child2(d1);
+	}
+}
+
+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
+{
+	AuDebugOn(d1 == d2
+		  || d1->d_inode == d2->d_inode
+		  || d1->d_sb != d2->d_sb);
+
+	if (isdir && au_test_subdir(d1, d2)) {
+		di_write_lock_parent(d1);
+		di_write_lock_parent2(d2);
+	} else {
+		/* there should be no races */
+		di_write_lock_parent(d2);
+		di_write_lock_parent2(d1);
+	}
+}
+
+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
+{
+	di_write_unlock(d1);
+	if (d1->d_inode == d2->d_inode)
+		au_rw_write_unlock(&au_di(d2)->di_rwsem);
+	else
+		di_write_unlock(d2);
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	struct dentry *d;
+
+	DiMustAnyLock(dentry);
+
+	if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
+		return NULL;
+	AuDebugOn(bindex < 0);
+	d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
+	AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
+	return d;
+}
+
+aufs_bindex_t au_dbtail(struct dentry *dentry)
+{
+	aufs_bindex_t bend, bwh;
+
+	bend = au_dbend(dentry);
+	if (0 <= bend) {
+		bwh = au_dbwh(dentry);
+		if (!bwh)
+			return bwh;
+		if (0 < bwh && bwh < bend)
+			return bwh - 1;
+	}
+	return bend;
+}
+
+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
+{
+	aufs_bindex_t bend, bopq;
+
+	bend = au_dbtail(dentry);
+	if (0 <= bend) {
+		bopq = au_dbdiropq(dentry);
+		if (0 <= bopq && bopq < bend)
+			bend = bopq;
+	}
+	return bend;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
+		   struct dentry *h_dentry)
+{
+	struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
+
+	DiMustWriteLock(dentry);
+
+	if (hd->hd_dentry)
+		au_hdput(hd);
+	hd->hd_dentry = h_dentry;
+}
+
+void au_update_digen(struct dentry *dentry)
+{
+	atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
+	/* smp_mb(); */ /* atomic_set */
+}
+
+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
+{
+	struct au_dinfo *dinfo;
+	struct dentry *h_d;
+
+	DiMustWriteLock(dentry);
+
+	dinfo = au_di(dentry);
+	if (!dinfo || dinfo->di_bstart < 0)
+		return;
+
+	if (do_put_zero) {
+		aufs_bindex_t bindex, bend;
+
+		bend = dinfo->di_bend;
+		for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
+			h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
+			if (h_d && !h_d->d_inode)
+				au_set_h_dptr(dentry, bindex, NULL);
+		}
+	}
+
+	dinfo->di_bstart = -1;
+	while (++dinfo->di_bstart <= dinfo->di_bend)
+		if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
+			break;
+	if (dinfo->di_bstart > dinfo->di_bend) {
+		dinfo->di_bstart = -1;
+		dinfo->di_bend = -1;
+		return;
+	}
+
+	dinfo->di_bend++;
+	while (0 <= --dinfo->di_bend)
+		if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
+			break;
+	AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
+}
+
+void au_update_dbstart(struct dentry *dentry)
+{
+	aufs_bindex_t bindex, bend;
+	struct dentry *h_dentry;
+
+	bend = au_dbend(dentry);
+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (!h_dentry)
+			continue;
+		if (h_dentry->d_inode) {
+			au_set_dbstart(dentry, bindex);
+			return;
+		}
+		au_set_h_dptr(dentry, bindex, NULL);
+	}
+}
+
+void au_update_dbend(struct dentry *dentry)
+{
+	aufs_bindex_t bindex, bstart;
+	struct dentry *h_dentry;
+
+	bstart = au_dbstart(dentry);
+	for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (!h_dentry)
+			continue;
+		if (h_dentry->d_inode) {
+			au_set_dbend(dentry, bindex);
+			return;
+		}
+		au_set_h_dptr(dentry, bindex, NULL);
+	}
+}
+
+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
+{
+	aufs_bindex_t bindex, bend;
+
+	bend = au_dbend(dentry);
+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
+		if (au_h_dptr(dentry, bindex) == h_dentry)
+			return bindex;
+	return -1;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/branch.c
+++ linux-ec2-2.6.32/ubuntu/aufs/branch.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * branch management
+ */
+
+#include <linux/file.h>
+#include <linux/statfs.h>
+#include "aufs.h"
+
+/*
+ * free a single branch
+ */
+static void au_br_do_free(struct au_branch *br)
+{
+	int i;
+	struct au_wbr *wbr;
+
+	if (br->br_xino.xi_file)
+		fput(br->br_xino.xi_file);
+	mutex_destroy(&br->br_xino.xi_nondir_mtx);
+
+	AuDebugOn(atomic_read(&br->br_count));
+
+	wbr = br->br_wbr;
+	if (wbr) {
+		for (i = 0; i < AuBrWh_Last; i++)
+			dput(wbr->wbr_wh[i]);
+		AuDebugOn(atomic_read(&wbr->wbr_wh_running));
+		AuRwDestroy(&wbr->wbr_wh_rwsem);
+	}
+
+	/* some filesystems acquire extra lock */
+	/* lockdep_off(); */
+	mntput(br->br_mnt);
+	/* lockdep_on(); */
+
+	kfree(wbr);
+	kfree(br);
+}
+
+/*
+ * frees all branches
+ */
+void au_br_free(struct au_sbinfo *sbinfo)
+{
+	aufs_bindex_t bmax;
+	struct au_branch **br;
+
+	AuRwMustWriteLock(&sbinfo->si_rwsem);
+
+	bmax = sbinfo->si_bend + 1;
+	br = sbinfo->si_branch;
+	while (bmax--)
+		au_br_do_free(*br++);
+}
+
+/*
+ * find the index of a branch which is specified by @br_id.
+ */
+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
+{
+	aufs_bindex_t bindex, bend;
+
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex <= bend; bindex++)
+		if (au_sbr_id(sb, bindex) == br_id)
+			return bindex;
+	return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * add a branch
+ */
+
+static int test_overlap(struct super_block *sb, struct dentry *h_d1,
+			struct dentry *h_d2)
+{
+	if (unlikely(h_d1 == h_d2))
+		return 1;
+	return !!au_test_subdir(h_d1, h_d2)
+		|| !!au_test_subdir(h_d2, h_d1)
+		|| au_test_loopback_overlap(sb, h_d1, h_d2)
+		|| au_test_loopback_overlap(sb, h_d2, h_d1);
+}
+
+/*
+ * returns a newly allocated branch. @new_nbranch is a number of branches
+ * after adding a branch.
+ */
+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
+				     int perm)
+{
+	struct au_branch *add_branch;
+	struct dentry *root;
+
+	root = sb->s_root;
+	add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
+	if (unlikely(!add_branch))
+		goto out;
+
+	add_branch->br_wbr = NULL;
+	if (au_br_writable(perm)) {
+		/* may be freed separately at changing the branch permission */
+		add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
+					     GFP_NOFS);
+		if (unlikely(!add_branch->br_wbr))
+			goto out_br;
+	}
+
+	if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
+		     || au_di_realloc(au_di(root), new_nbranch)
+		     || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
+		goto out_wbr;
+	return add_branch; /* success */
+
+ out_wbr:
+	kfree(add_branch->br_wbr);
+ out_br:
+	kfree(add_branch);
+ out:
+	return ERR_PTR(-ENOMEM);
+}
+
+/*
+ * test if the branch permission is legal or not.
+ */
+static int test_br(struct inode *inode, int brperm, char *path)
+{
+	int err;
+
+	err = 0;
+	if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
+		pr_err("write permission for readonly mount or inode, %s\n",
+		       path);
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+/*
+ * returns:
+ * 0: success, the caller will add it
+ * plus: success, it is already unified, the caller should ignore it
+ * minus: error
+ */
+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
+{
+	int err;
+	aufs_bindex_t bend, bindex;
+	struct dentry *root;
+	struct inode *inode, *h_inode;
+
+	root = sb->s_root;
+	bend = au_sbend(sb);
+	if (unlikely(bend >= 0
+		     && au_find_dbindex(root, add->path.dentry) >= 0)) {
+		err = 1;
+		if (!remount) {
+			err = -EINVAL;
+			pr_err("%s duplicated\n", add->pathname);
+		}
+		goto out;
+	}
+
+	err = -ENOSPC; /* -E2BIG; */
+	if (unlikely(AUFS_BRANCH_MAX <= add->bindex
+		     || AUFS_BRANCH_MAX - 1 <= bend)) {
+		pr_err("number of branches exceeded %s\n", add->pathname);
+		goto out;
+	}
+
+	err = -EDOM;
+	if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
+		pr_err("bad index %d\n", add->bindex);
+		goto out;
+	}
+
+	inode = add->path.dentry->d_inode;
+	err = -ENOENT;
+	if (unlikely(!inode->i_nlink)) {
+		pr_err("no existence %s\n", add->pathname);
+		goto out;
+	}
+
+	err = -EINVAL;
+	if (unlikely(inode->i_sb == sb)) {
+		pr_err("%s must be outside\n", add->pathname);
+		goto out;
+	}
+
+	if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
+		pr_err("unsupported filesystem, %s (%s)\n",
+		       add->pathname, au_sbtype(inode->i_sb));
+		goto out;
+	}
+
+	err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
+	if (unlikely(err))
+		goto out;
+
+	if (bend < 0)
+		return 0; /* success */
+
+	err = -EINVAL;
+	for (bindex = 0; bindex <= bend; bindex++)
+		if (unlikely(test_overlap(sb, add->path.dentry,
+					  au_h_dptr(root, bindex)))) {
+			pr_err("%s is overlapped\n", add->pathname);
+			goto out;
+		}
+
+	err = 0;
+	if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
+		h_inode = au_h_dptr(root, 0)->d_inode;
+		if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
+		    || h_inode->i_uid != inode->i_uid
+		    || h_inode->i_gid != inode->i_gid)
+			pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
+				   add->pathname,
+				   inode->i_uid, inode->i_gid,
+				   (inode->i_mode & S_IALLUGO),
+				   h_inode->i_uid, h_inode->i_gid,
+				   (h_inode->i_mode & S_IALLUGO));
+	}
+
+ out:
+	return err;
+}
+
+/*
+ * initialize or clean the whiteouts for an adding branch
+ */
+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
+			 int new_perm, struct dentry *h_root)
+{
+	int err, old_perm;
+	aufs_bindex_t bindex;
+	struct mutex *h_mtx;
+	struct au_wbr *wbr;
+	struct au_hinode *hdir;
+
+	wbr = br->br_wbr;
+	old_perm = br->br_perm;
+	br->br_perm = new_perm;
+	hdir = NULL;
+	h_mtx = NULL;
+	bindex = au_br_index(sb, br->br_id);
+	if (0 <= bindex) {
+		hdir = au_hi(sb->s_root->d_inode, bindex);
+		au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
+	} else {
+		h_mtx = &h_root->d_inode->i_mutex;
+		mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
+	}
+	if (!wbr)
+		err = au_wh_init(h_root, br, sb);
+	else {
+		wbr_wh_write_lock(wbr);
+		err = au_wh_init(h_root, br, sb);
+		wbr_wh_write_unlock(wbr);
+	}
+	if (hdir)
+		au_hin_imtx_unlock(hdir);
+	else
+		mutex_unlock(h_mtx);
+	br->br_perm = old_perm;
+
+	if (!err && wbr && !au_br_writable(new_perm)) {
+		kfree(wbr);
+		br->br_wbr = NULL;
+	}
+
+	return err;
+}
+
+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
+		       int perm, struct path *path)
+{
+	int err;
+	struct kstatfs kst;
+	struct au_wbr *wbr;
+	struct dentry *h_dentry;
+
+	wbr = br->br_wbr;
+	au_rw_init(&wbr->wbr_wh_rwsem);
+	memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
+	atomic_set(&wbr->wbr_wh_running, 0);
+	wbr->wbr_bytes = 0;
+
+	/*
+	 * a limit for rmdir/rename a dir
+	 * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
+	 */
+	h_dentry = path->dentry;
+	err = vfs_statfs(h_dentry, &kst);
+	if (unlikely(err))
+		goto out;
+	err = -EINVAL;
+	if (kst.f_namelen >= NAME_MAX)
+		err = au_br_init_wh(sb, br, perm, h_dentry);
+	else
+		pr_err("%.*s(%s), unsupported namelen %ld\n",
+		       AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
+		       kst.f_namelen);
+
+ out:
+	return err;
+}
+
+/* intialize a new branch */
+static int au_br_init(struct au_branch *br, struct super_block *sb,
+		      struct au_opt_add *add)
+{
+	int err;
+
+	err = 0;
+	memset(&br->br_xino, 0, sizeof(br->br_xino));
+	mutex_init(&br->br_xino.xi_nondir_mtx);
+	br->br_perm = add->perm;
+	br->br_mnt = add->path.mnt; /* set first, mntget() later */
+	atomic_set(&br->br_count, 0);
+	br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
+	atomic_set(&br->br_xino_running, 0);
+	br->br_id = au_new_br_id(sb);
+
+	if (au_br_writable(add->perm)) {
+		err = au_wbr_init(br, sb, add->perm, &add->path);
+		if (unlikely(err))
+			goto out;
+	}
+
+	if (au_opt_test(au_mntflags(sb), XINO)) {
+		err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
+				 au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
+		if (unlikely(err)) {
+			AuDebugOn(br->br_xino.xi_file);
+			goto out;
+		}
+	}
+
+	sysaufs_br_init(br);
+	mntget(add->path.mnt);
+
+ out:
+	return err;
+}
+
+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
+			     struct au_branch *br, aufs_bindex_t bend,
+			     aufs_bindex_t amount)
+{
+	struct au_branch **brp;
+
+	AuRwMustWriteLock(&sbinfo->si_rwsem);
+
+	brp = sbinfo->si_branch + bindex;
+	memmove(brp + 1, brp, sizeof(*brp) * amount);
+	*brp = br;
+	sbinfo->si_bend++;
+	if (unlikely(bend < 0))
+		sbinfo->si_bend = 0;
+}
+
+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
+			     aufs_bindex_t bend, aufs_bindex_t amount)
+{
+	struct au_hdentry *hdp;
+
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	hdp = dinfo->di_hdentry + bindex;
+	memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
+	au_h_dentry_init(hdp);
+	dinfo->di_bend++;
+	if (unlikely(bend < 0))
+		dinfo->di_bstart = 0;
+}
+
+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
+			     aufs_bindex_t bend, aufs_bindex_t amount)
+{
+	struct au_hinode *hip;
+
+	AuRwMustWriteLock(&iinfo->ii_rwsem);
+
+	hip = iinfo->ii_hinode + bindex;
+	memmove(hip + 1, hip, sizeof(*hip) * amount);
+	hip->hi_inode = NULL;
+	au_hin_init(hip, NULL);
+	iinfo->ii_bend++;
+	if (unlikely(bend < 0))
+		iinfo->ii_bstart = 0;
+}
+
+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
+			 struct au_branch *br, aufs_bindex_t bindex)
+{
+	struct dentry *root;
+	struct inode *root_inode;
+	aufs_bindex_t bend, amount;
+
+	root = sb->s_root;
+	root_inode = root->d_inode;
+	au_plink_block_maintain(sb);
+	bend = au_sbend(sb);
+	amount = bend + 1 - bindex;
+	au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
+	au_br_do_add_hdp(au_di(root), bindex, bend, amount);
+	au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
+	au_set_h_dptr(root, bindex, dget(h_dentry));
+	au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
+		      /*flags*/0);
+}
+
+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
+{
+	int err;
+	aufs_bindex_t bend, add_bindex;
+	struct dentry *root, *h_dentry;
+	struct inode *root_inode;
+	struct au_branch *add_branch;
+
+	root = sb->s_root;
+	root_inode = root->d_inode;
+	IMustLock(root_inode);
+	err = test_add(sb, add, remount);
+	if (unlikely(err < 0))
+		goto out;
+	if (err) {
+		err = 0;
+		goto out; /* success */
+	}
+
+	bend = au_sbend(sb);
+	add_branch = au_br_alloc(sb, bend + 2, add->perm);
+	err = PTR_ERR(add_branch);
+	if (IS_ERR(add_branch))
+		goto out;
+
+	err = au_br_init(add_branch, sb, add);
+	if (unlikely(err)) {
+		au_br_do_free(add_branch);
+		goto out;
+	}
+
+	add_bindex = add->bindex;
+	h_dentry = add->path.dentry;
+	if (!remount)
+		au_br_do_add(sb, h_dentry, add_branch, add_bindex);
+	else {
+		sysaufs_brs_del(sb, add_bindex);
+		au_br_do_add(sb, h_dentry, add_branch, add_bindex);
+		sysaufs_brs_add(sb, add_bindex);
+	}
+
+	if (!add_bindex) {
+		au_cpup_attr_all(root_inode, /*force*/1);
+		sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
+	} else
+		au_add_nlink(root_inode, h_dentry->d_inode);
+
+	/*
+	 * this test/set prevents aufs from handling unnecesary inotify events
+	 * of xino files, in a case of re-adding a writable branch which was
+	 * once detached from aufs.
+	 */
+	if (au_xino_brid(sb) < 0
+	    && au_br_writable(add_branch->br_perm)
+	    && !au_test_fs_bad_xino(h_dentry->d_sb)
+	    && add_branch->br_xino.xi_file
+	    && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
+		au_xino_brid_set(sb, add_branch->br_id);
+
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * delete a branch
+ */
+
+/* to show the line number, do not make it inlined function */
+#define AuVerbose(do_info, fmt, ...) do { \
+	if (do_info) \
+		pr_info(fmt, ##__VA_ARGS__); \
+} while (0)
+
+/*
+ * test if the branch is deletable or not.
+ */
+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
+			    unsigned int sigen)
+{
+	int err, i, j, ndentry;
+	aufs_bindex_t bstart, bend;
+	unsigned char verbose;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry *d;
+	struct inode *inode;
+
+	err = au_dpages_init(&dpages, GFP_NOFS);
+	if (unlikely(err))
+		goto out;
+	err = au_dcsub_pages(&dpages, root, NULL, NULL);
+	if (unlikely(err))
+		goto out_dpages;
+
+	verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
+	for (i = 0; !err && i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		ndentry = dpage->ndentry;
+		for (j = 0; !err && j < ndentry; j++) {
+			d = dpage->dentries[j];
+			AuDebugOn(!atomic_read(&d->d_count));
+			inode = d->d_inode;
+			if (au_digen(d) == sigen && au_iigen(inode) == sigen)
+				di_read_lock_child(d, AuLock_IR);
+			else {
+				di_write_lock_child(d);
+				err = au_reval_dpath(d, sigen);
+				if (!err)
+					di_downgrade_lock(d, AuLock_IR);
+				else {
+					di_write_unlock(d);
+					break;
+				}
+			}
+
+			bstart = au_dbstart(d);
+			bend = au_dbend(d);
+			if (bstart <= bindex
+			    && bindex <= bend
+			    && au_h_dptr(d, bindex)
+			    && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
+				err = -EBUSY;
+				AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
+			}
+			di_read_unlock(d, AuLock_IR);
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	return err;
+}
+
+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
+			   unsigned int sigen)
+{
+	int err;
+	struct inode *i;
+	aufs_bindex_t bstart, bend;
+	unsigned char verbose;
+
+	err = 0;
+	verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
+	list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
+		AuDebugOn(!atomic_read(&i->i_count));
+		if (!list_empty(&i->i_dentry))
+			continue;
+
+		if (au_iigen(i) == sigen)
+			ii_read_lock_child(i);
+		else {
+			ii_write_lock_child(i);
+			err = au_refresh_hinode_self(i, /*do_attr*/1);
+			if (!err)
+				ii_downgrade_lock(i);
+			else {
+				ii_write_unlock(i);
+				break;
+			}
+		}
+
+		bstart = au_ibstart(i);
+		bend = au_ibend(i);
+		if (bstart <= bindex
+		    && bindex <= bend
+		    && au_h_iptr(i, bindex)
+		    && (!S_ISDIR(i->i_mode) || bstart == bend)) {
+			err = -EBUSY;
+			AuVerbose(verbose, "busy i%lu\n", i->i_ino);
+			ii_read_unlock(i);
+			break;
+		}
+		ii_read_unlock(i);
+	}
+
+	return err;
+}
+
+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
+{
+	int err;
+	unsigned int sigen;
+
+	sigen = au_sigen(root->d_sb);
+	DiMustNoWaiters(root);
+	IiMustNoWaiters(root->d_inode);
+	di_write_unlock(root);
+	err = test_dentry_busy(root, bindex, sigen);
+	if (!err)
+		err = test_inode_busy(root->d_sb, bindex, sigen);
+	di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
+
+	return err;
+}
+
+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
+			     const aufs_bindex_t bindex,
+			     const aufs_bindex_t bend)
+{
+	struct au_branch **brp, **p;
+
+	AuRwMustWriteLock(&sbinfo->si_rwsem);
+
+	brp = sbinfo->si_branch + bindex;
+	if (bindex < bend)
+		memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
+	sbinfo->si_branch[0 + bend] = NULL;
+	sbinfo->si_bend--;
+
+	p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
+	if (p)
+		sbinfo->si_branch = p;
+}
+
+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
+			     const aufs_bindex_t bend)
+{
+	struct au_hdentry *hdp, *p;
+
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	hdp = dinfo->di_hdentry + bindex;
+	if (bindex < bend)
+		memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
+	dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
+	dinfo->di_bend--;
+
+	p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
+	if (p)
+		dinfo->di_hdentry = p;
+}
+
+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
+			     const aufs_bindex_t bend)
+{
+	struct au_hinode *hip, *p;
+
+	AuRwMustWriteLock(&iinfo->ii_rwsem);
+
+	hip = iinfo->ii_hinode + bindex;
+	if (bindex < bend)
+		memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
+	iinfo->ii_hinode[0 + bend].hi_inode = NULL;
+	au_hin_init(iinfo->ii_hinode + bend, NULL);
+	iinfo->ii_bend--;
+
+	p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
+	if (p)
+		iinfo->ii_hinode = p;
+}
+
+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
+			 struct au_branch *br)
+{
+	aufs_bindex_t bend;
+	struct au_sbinfo *sbinfo;
+	struct dentry *root;
+	struct inode *inode;
+
+	SiMustWriteLock(sb);
+
+	root = sb->s_root;
+	inode = root->d_inode;
+	au_plink_block_maintain(sb);
+	sbinfo = au_sbi(sb);
+	bend = sbinfo->si_bend;
+
+	dput(au_h_dptr(root, bindex));
+	au_hiput(au_hi(inode, bindex));
+	au_br_do_free(br);
+
+	au_br_do_del_brp(sbinfo, bindex, bend);
+	au_br_do_del_hdp(au_di(root), bindex, bend);
+	au_br_do_del_hip(au_ii(inode), bindex, bend);
+}
+
+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
+{
+	int err, rerr, i;
+	unsigned int mnt_flags;
+	aufs_bindex_t bindex, bend, br_id;
+	unsigned char do_wh, verbose;
+	struct au_branch *br;
+	struct au_wbr *wbr;
+
+	err = 0;
+	bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
+	if (bindex < 0) {
+		if (remount)
+			goto out; /* success */
+		err = -ENOENT;
+		pr_err("%s no such branch\n", del->pathname);
+		goto out;
+	}
+	AuDbg("bindex b%d\n", bindex);
+
+	err = -EBUSY;
+	mnt_flags = au_mntflags(sb);
+	verbose = !!au_opt_test(mnt_flags, VERBOSE);
+	bend = au_sbend(sb);
+	if (unlikely(!bend)) {
+		AuVerbose(verbose, "no more branches left\n");
+		goto out;
+	}
+	br = au_sbr(sb, bindex);
+	i = atomic_read(&br->br_count);
+	if (unlikely(i)) {
+		AuVerbose(verbose, "%d file(s) opened\n", i);
+		goto out;
+	}
+
+	wbr = br->br_wbr;
+	do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
+	if (do_wh) {
+		/* instead of WbrWhMustWriteLock(wbr) */
+		SiMustWriteLock(sb);
+		for (i = 0; i < AuBrWh_Last; i++) {
+			dput(wbr->wbr_wh[i]);
+			wbr->wbr_wh[i] = NULL;
+		}
+	}
+
+	err = test_children_busy(sb->s_root, bindex);
+	if (unlikely(err)) {
+		if (do_wh)
+			goto out_wh;
+		goto out;
+	}
+
+	err = 0;
+	br_id = br->br_id;
+	if (!remount)
+		au_br_do_del(sb, bindex, br);
+	else {
+		sysaufs_brs_del(sb, bindex);
+		au_br_do_del(sb, bindex, br);
+		sysaufs_brs_add(sb, bindex);
+	}
+
+	if (!bindex) {
+		au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
+		sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
+	} else
+		au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
+	if (au_opt_test(mnt_flags, PLINK))
+		au_plink_half_refresh(sb, br_id);
+
+	if (au_xino_brid(sb) == br->br_id)
+		au_xino_brid_set(sb, -1);
+	goto out; /* success */
+
+ out_wh:
+	/* revert */
+	rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
+	if (rerr)
+		pr_warning("failed re-creating base whiteout, %s. (%d)\n",
+			   del->pathname, rerr);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * change a branch permission
+ */
+
+static void au_warn_ima(void)
+{
+#ifdef CONFIG_IMA
+	/* since it doesn't support mark_files_ro() */
+	pr_warning("RW -> RO makes IMA to produce wrong message");
+#endif
+}
+
+static int do_need_sigen_inc(int a, int b)
+{
+	return au_br_whable(a) && !au_br_whable(b);
+}
+
+static int need_sigen_inc(int old, int new)
+{
+	return do_need_sigen_inc(old, new)
+		|| do_need_sigen_inc(new, old);
+}
+
+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
+{
+	int err;
+	unsigned long n, ul, bytes, files;
+	aufs_bindex_t bstart;
+	struct file *file, *hf, **a;
+	const int step_bytes = 1024, /* memory allocation unit */
+		step_files = step_bytes / sizeof(*a);
+
+	err = -ENOMEM;
+	n = 0;
+	bytes = step_bytes;
+	files = step_files;
+	a = kmalloc(bytes, GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	/* no need file_list_lock() since sbinfo is locked? defered? */
+	list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
+		if (special_file(file->f_dentry->d_inode->i_mode))
+			continue;
+
+		AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
+		fi_read_lock(file);
+		if (unlikely(au_test_mmapped(file))) {
+			err = -EBUSY;
+			FiMustNoWaiters(file);
+			fi_read_unlock(file);
+			goto out_free;
+		}
+
+		bstart = au_fbstart(file);
+		if (!S_ISREG(file->f_dentry->d_inode->i_mode)
+		    || !(file->f_mode & FMODE_WRITE)
+		    || bstart != bindex) {
+			FiMustNoWaiters(file);
+			fi_read_unlock(file);
+			continue;
+		}
+
+		hf = au_h_fptr(file, bstart);
+		FiMustNoWaiters(file);
+		fi_read_unlock(file);
+
+		if (n < files)
+			a[n++] = hf;
+		else {
+			void *p;
+
+			err = -ENOMEM;
+			bytes += step_bytes;
+			files += step_files;
+			p = krealloc(a, bytes, GFP_NOFS);
+			if (p) {
+				a = p;
+				a[n++] = hf;
+			} else
+				goto out_free;
+		}
+	}
+
+	err = 0;
+	if (n)
+		au_warn_ima();
+	for (ul = 0; ul < n; ul++) {
+		/* todo: already flushed? */
+		/* cf. fs/super.c:mark_files_ro() */
+		hf = a[ul];
+		hf->f_mode &= ~FMODE_WRITE;
+		if (!file_check_writeable(hf)) {
+			file_release_write(hf);
+			mnt_drop_write(hf->f_vfsmnt);
+		}
+	}
+
+ out_free:
+	kfree(a);
+ out:
+	return err;
+}
+
+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
+	      int *do_update)
+{
+	int err, rerr;
+	aufs_bindex_t bindex;
+	struct path path;
+	struct dentry *root;
+	struct au_branch *br;
+
+	root = sb->s_root;
+	au_plink_block_maintain(sb);
+	bindex = au_find_dbindex(root, mod->h_root);
+	if (bindex < 0) {
+		if (remount)
+			return 0; /* success */
+		err = -ENOENT;
+		pr_err("%s no such branch\n", mod->path);
+		goto out;
+	}
+	AuDbg("bindex b%d\n", bindex);
+
+	err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
+	if (unlikely(err))
+		goto out;
+
+	br = au_sbr(sb, bindex);
+	if (br->br_perm == mod->perm)
+		return 0; /* success */
+
+	if (au_br_writable(br->br_perm)) {
+		/* remove whiteout base */
+		err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
+		if (unlikely(err))
+			goto out;
+
+		if (!au_br_writable(mod->perm)) {
+			/* rw --> ro, file might be mmapped */
+			DiMustNoWaiters(root);
+			IiMustNoWaiters(root->d_inode);
+			di_write_unlock(root);
+			err = au_br_mod_files_ro(sb, bindex);
+			/* aufs_write_lock() calls ..._child() */
+			di_write_lock_child(root);
+
+			if (unlikely(err)) {
+				rerr = -ENOMEM;
+				br->br_wbr = kmalloc(sizeof(*br->br_wbr),
+						     GFP_NOFS);
+				if (br->br_wbr) {
+					path.mnt = br->br_mnt;
+					path.dentry = mod->h_root;
+					rerr = au_wbr_init(br, sb, br->br_perm,
+							   &path);
+				}
+				if (unlikely(rerr)) {
+					AuIOErr("nested error %d (%d)\n",
+						rerr, err);
+					br->br_perm = mod->perm;
+				}
+			}
+		}
+	} else if (au_br_writable(mod->perm)) {
+		/* ro --> rw */
+		err = -ENOMEM;
+		br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
+		if (br->br_wbr) {
+			path.mnt = br->br_mnt;
+			path.dentry = mod->h_root;
+			err = au_wbr_init(br, sb, mod->perm, &path);
+			if (unlikely(err)) {
+				kfree(br->br_wbr);
+				br->br_wbr = NULL;
+			}
+		}
+	}
+
+	if (!err) {
+		*do_update |= need_sigen_inc(br->br_perm, mod->perm);
+		br->br_perm = mod->perm;
+	}
+
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/sysfs.c
+++ linux-ec2-2.6.32/ubuntu/aufs/sysfs.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sysfs interface
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/sysfs.h>
+#include "aufs.h"
+
+#ifdef CONFIG_AUFS_FS_MODULE
+/* this entry violates the "one line per file" policy of sysfs */
+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
+			   char *buf)
+{
+	ssize_t err;
+	static char *conf =
+/* this file is generated at compiling */
+#include "conf.str"
+		;
+
+	err = snprintf(buf, PAGE_SIZE, conf);
+	if (unlikely(err >= PAGE_SIZE))
+		err = -EFBIG;
+	return err;
+}
+
+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
+#endif
+
+static struct attribute *au_attr[] = {
+#ifdef CONFIG_AUFS_FS_MODULE
+	&au_config_attr.attr,
+#endif
+	NULL,	/* need to NULL terminate the list of attributes */
+};
+
+static struct attribute_group sysaufs_attr_group_body = {
+	.attrs = au_attr
+};
+
+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
+
+/* ---------------------------------------------------------------------- */
+
+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
+{
+	int err;
+
+	SiMustAnyLock(sb);
+
+	err = 0;
+	if (au_opt_test(au_mntflags(sb), XINO)) {
+		err = au_xino_path(seq, au_sbi(sb)->si_xib);
+		seq_putc(seq, '\n');
+	}
+	return err;
+}
+
+/*
+ * the lifetime of branch is independent from the entry under sysfs.
+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
+ * unlinked.
+ */
+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
+			 aufs_bindex_t bindex)
+{
+	struct path path;
+	struct dentry *root;
+	struct au_branch *br;
+
+	AuDbg("b%d\n", bindex);
+
+	root = sb->s_root;
+	di_read_lock_parent(root, !AuLock_IR);
+	br = au_sbr(sb, bindex);
+	path.mnt = br->br_mnt;
+	path.dentry = au_h_dptr(root, bindex);
+	au_seq_path(seq, &path);
+	di_read_unlock(root, !AuLock_IR);
+	seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct seq_file *au_seq(char *p, ssize_t len)
+{
+	struct seq_file *seq;
+
+	seq = kzalloc(sizeof(*seq), GFP_NOFS);
+	if (seq) {
+		/* mutex_init(&seq.lock); */
+		seq->buf = p;
+		seq->size = len;
+		return seq; /* success */
+	}
+
+	seq = ERR_PTR(-ENOMEM);
+	return seq;
+}
+
+#define SysaufsBr_PREFIX "br"
+
+/* todo: file size may exceed PAGE_SIZE */
+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
+			char *buf)
+{
+	ssize_t err;
+	long l;
+	aufs_bindex_t bend;
+	struct au_sbinfo *sbinfo;
+	struct super_block *sb;
+	struct seq_file *seq;
+	char *name;
+	struct attribute **cattr;
+
+	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
+	sb = sbinfo->si_sb;
+
+	/*
+	 * prevent a race condition between sysfs and aufs.
+	 * for instance, sysfs_file_read() calls sysfs_get_active_two() which
+	 * prohibits maintaining the sysfs entries.
+	 * hew we acquire read lock after sysfs_get_active_two().
+	 * on the other hand, the remount process may maintain the sysfs/aufs
+	 * entries after acquiring write lock.
+	 * it can cause a deadlock.
+	 * simply we gave up processing read here.
+	 */
+	err = -EBUSY;
+	if (unlikely(!si_noflush_read_trylock(sb)))
+		goto out;
+
+	seq = au_seq(buf, PAGE_SIZE);
+	err = PTR_ERR(seq);
+	if (IS_ERR(seq))
+		goto out_unlock;
+
+	name = (void *)attr->name;
+	cattr = sysaufs_si_attrs;
+	while (*cattr) {
+		if (!strcmp(name, (*cattr)->name)) {
+			err = container_of(*cattr, struct sysaufs_si_attr, attr)
+				->show(seq, sb);
+			goto out_seq;
+		}
+		cattr++;
+	}
+
+	bend = au_sbend(sb);
+	if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
+		name += sizeof(SysaufsBr_PREFIX) - 1;
+		err = strict_strtol(name, 10, &l);
+		if (!err) {
+			if (l <= bend)
+				err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
+			else
+				err = -ENOENT;
+		}
+		goto out_seq;
+	}
+	BUG();
+
+ out_seq:
+	if (!err) {
+		err = seq->count;
+		/* sysfs limit */
+		if (unlikely(err == PAGE_SIZE))
+			err = -EFBIG;
+	}
+	kfree(seq);
+ out_unlock:
+	si_read_unlock(sb);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void sysaufs_br_init(struct au_branch *br)
+{
+	br->br_attr.name = br->br_name;
+	br->br_attr.mode = S_IRUGO;
+	br->br_attr.owner = THIS_MODULE;
+}
+
+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+	struct au_branch *br;
+	struct kobject *kobj;
+	aufs_bindex_t bend;
+
+	dbgaufs_brs_del(sb, bindex);
+
+	if (!sysaufs_brs)
+		return;
+
+	kobj = &au_sbi(sb)->si_kobj;
+	bend = au_sbend(sb);
+	for (; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		sysfs_remove_file(kobj, &br->br_attr);
+	}
+}
+
+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+	int err;
+	aufs_bindex_t bend;
+	struct kobject *kobj;
+	struct au_branch *br;
+
+	dbgaufs_brs_add(sb, bindex);
+
+	if (!sysaufs_brs)
+		return;
+
+	kobj = &au_sbi(sb)->si_kobj;
+	bend = au_sbend(sb);
+	for (; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
+			 "%d", bindex);
+		err = sysfs_create_file(kobj, &br->br_attr);
+		if (unlikely(err))
+			pr_warning("failed %s under sysfs(%d)\n",
+				   br->br_name, err);
+	}
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/wkq.c
+++ linux-ec2-2.6.32/ubuntu/aufs/wkq.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * workqueue for asynchronous/super-io operations
+ * todo: try new dredential scheme
+ */
+
+#include <linux/module.h>
+#include "aufs.h"
+
+/* internal workqueue named AUFS_WKQ_NAME */
+static struct au_wkq {
+	struct workqueue_struct	*q;
+
+	/* balancing */
+	atomic_t		busy;
+} *au_wkq;
+
+struct au_wkinfo {
+	struct work_struct wk;
+	struct super_block *sb;
+
+	unsigned int flags; /* see wkq.h */
+
+	au_wkq_func_t func;
+	void *args;
+
+	atomic_t *busyp;
+	struct completion *comp;
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
+{
+	wkinfo->busyp = &wkq->busy;
+	if (au_ftest_wkq(wkinfo->flags, WAIT))
+		return !queue_work(wkq->q, &wkinfo->wk);
+	else
+		return !schedule_work(&wkinfo->wk);
+}
+
+static void do_wkq(struct au_wkinfo *wkinfo)
+{
+	unsigned int idle, n;
+	int i, idle_idx;
+
+	while (1) {
+		if (au_ftest_wkq(wkinfo->flags, WAIT)) {
+			idle_idx = 0;
+			idle = UINT_MAX;
+			for (i = 0; i < aufs_nwkq; i++) {
+				n = atomic_inc_return(&au_wkq[i].busy);
+				if (n == 1 && !enqueue(au_wkq + i, wkinfo))
+					return; /* success */
+
+				if (n < idle) {
+					idle_idx = i;
+					idle = n;
+				}
+				atomic_dec(&au_wkq[i].busy);
+			}
+		} else
+			idle_idx = aufs_nwkq;
+
+		atomic_inc(&au_wkq[idle_idx].busy);
+		if (!enqueue(au_wkq + idle_idx, wkinfo))
+			return; /* success */
+
+		/* impossible? */
+		AuWarn1("failed to queue_work()\n");
+		yield();
+	}
+}
+
+static void wkq_func(struct work_struct *wk)
+{
+	struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
+
+	wkinfo->func(wkinfo->args);
+	atomic_dec_return(wkinfo->busyp);
+	if (au_ftest_wkq(wkinfo->flags, WAIT))
+		complete(wkinfo->comp);
+	else {
+		kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
+		module_put(THIS_MODULE);
+		kfree(wkinfo);
+	}
+}
+
+/*
+ * Since struct completion is large, try allocating it dynamically.
+ */
+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
+#define AuWkqCompDeclare(name)	struct completion *comp = NULL
+
+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
+{
+	*comp = kmalloc(sizeof(**comp), GFP_NOFS);
+	if (*comp) {
+		init_completion(*comp);
+		wkinfo->comp = *comp;
+		return 0;
+	}
+	return -ENOMEM;
+}
+
+static void au_wkq_comp_free(struct completion *comp)
+{
+	kfree(comp);
+}
+
+#else
+
+/* no braces */
+#define AuWkqCompDeclare(name) \
+	DECLARE_COMPLETION_ONSTACK(_ ## name); \
+	struct completion *comp = &_ ## name
+
+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
+{
+	wkinfo->comp = *comp;
+	return 0;
+}
+
+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
+{
+	/* empty */
+}
+#endif /* 4KSTACKS */
+
+static void au_wkq_run(struct au_wkinfo *wkinfo)
+{
+	au_dbg_verify_kthread();
+	INIT_WORK(&wkinfo->wk, wkq_func);
+	do_wkq(wkinfo);
+}
+
+int au_wkq_wait(au_wkq_func_t func, void *args)
+{
+	int err;
+	AuWkqCompDeclare(comp);
+	struct au_wkinfo wkinfo = {
+		.flags	= AuWkq_WAIT,
+		.func	= func,
+		.args	= args
+	};
+
+	err = au_wkq_comp_alloc(&wkinfo, &comp);
+	if (!err) {
+		au_wkq_run(&wkinfo);
+		/* no timeout, no interrupt */
+		wait_for_completion(wkinfo.comp);
+		au_wkq_comp_free(comp);
+	}
+
+	return err;
+
+}
+
+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
+{
+	int err;
+	struct au_wkinfo *wkinfo;
+
+	atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
+
+	/*
+	 * wkq_func() must free this wkinfo.
+	 * it highly depends upon the implementation of workqueue.
+	 */
+	err = 0;
+	wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
+	if (wkinfo) {
+		wkinfo->sb = sb;
+		wkinfo->flags = !AuWkq_WAIT;
+		wkinfo->func = func;
+		wkinfo->args = args;
+		wkinfo->comp = NULL;
+		kobject_get(&au_sbi(sb)->si_kobj);
+		__module_get(THIS_MODULE);
+
+		au_wkq_run(wkinfo);
+	} else {
+		err = -ENOMEM;
+		atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_nwt_init(struct au_nowait_tasks *nwt)
+{
+	atomic_set(&nwt->nw_len, 0);
+	/* smp_mb();*/ /* atomic_set */
+	init_waitqueue_head(&nwt->nw_wq);
+}
+
+void au_wkq_fin(void)
+{
+	int i;
+
+	for (i = 0; i < aufs_nwkq; i++)
+		if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
+			destroy_workqueue(au_wkq[i].q);
+	kfree(au_wkq);
+}
+
+int __init au_wkq_init(void)
+{
+	int err, i;
+	struct au_wkq *nowaitq;
+
+	/* '+1' is for accounting of nowait queue */
+	err = -ENOMEM;
+	au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
+	if (unlikely(!au_wkq))
+		goto out;
+
+	err = 0;
+	for (i = 0; i < aufs_nwkq; i++) {
+		au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
+		if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
+			atomic_set(&au_wkq[i].busy, 0);
+			continue;
+		}
+
+		err = PTR_ERR(au_wkq[i].q);
+		au_wkq_fin();
+		goto out;
+	}
+
+	/* nowait accounting */
+	nowaitq = au_wkq + aufs_nwkq;
+	atomic_set(&nowaitq->busy, 0);
+	nowaitq->q = NULL;
+	/* smp_mb(); */ /* atomic_set */
+
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/wkq.h
+++ linux-ec2-2.6.32/ubuntu/aufs/wkq.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * workqueue for asynchronous/super-io operations
+ * todo: try new credentials management scheme
+ */
+
+#ifndef __AUFS_WKQ_H__
+#define __AUFS_WKQ_H__
+
+#ifdef __KERNEL__
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/aufs_type.h>
+
+struct super_block;
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
+ */
+struct au_nowait_tasks {
+	atomic_t		nw_len;
+	wait_queue_head_t	nw_wq;
+};
+
+/* ---------------------------------------------------------------------- */
+
+typedef void (*au_wkq_func_t)(void *args);
+
+/* wkq flags */
+#define AuWkq_WAIT	1
+#define au_ftest_wkq(flags, name)	((flags) & AuWkq_##name)
+#define au_fset_wkq(flags, name)	{ (flags) |= AuWkq_##name; }
+#define au_fclr_wkq(flags, name)	{ (flags) &= ~AuWkq_##name; }
+
+/* wkq.c */
+int au_wkq_wait(au_wkq_func_t func, void *args);
+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
+void au_nwt_init(struct au_nowait_tasks *nwt);
+int __init au_wkq_init(void);
+void au_wkq_fin(void);
+
+/* ---------------------------------------------------------------------- */
+
+static inline int au_test_wkq(struct task_struct *tsk)
+{
+	return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
+}
+
+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
+{
+	if (!atomic_dec_return(&nwt->nw_len))
+		wake_up_all(&nwt->nw_wq);
+}
+
+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
+{
+	wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
+	return 0;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_WKQ_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dbgaufs.c
+++ linux-ec2-2.6.32/ubuntu/aufs/dbgaufs.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * debugfs interface
+ */
+
+#include <linux/debugfs.h>
+#include "aufs.h"
+
+#ifndef CONFIG_SYSFS
+#error DEBUG_FS depends upon SYSFS
+#endif
+
+static struct dentry *dbgaufs;
+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
+
+/* 20 is max digits length of ulong 64 */
+struct dbgaufs_arg {
+	int n;
+	char a[20 * 4];
+};
+
+/*
+ * common function for all XINO files
+ */
+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
+			      struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
+{
+	int err;
+	struct kstat st;
+	struct dbgaufs_arg *p;
+
+	err = -ENOMEM;
+	p = kmalloc(sizeof(*p), GFP_NOFS);
+	if (unlikely(!p))
+		goto out;
+
+	err = 0;
+	p->n = 0;
+	file->private_data = p;
+	if (!xf)
+		goto out;
+
+	err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
+	if (!err) {
+		if (do_fcnt)
+			p->n = snprintf
+				(p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
+				 (long)file_count(xf), st.blocks, st.blksize,
+				 (long long)st.size);
+		else
+			p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
+					st.blocks, st.blksize,
+					(long long)st.size);
+		AuDebugOn(p->n >= sizeof(p->a));
+	} else {
+		p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
+		err = 0;
+	}
+
+ out:
+	return err;
+
+}
+
+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
+			       size_t count, loff_t *ppos)
+{
+	struct dbgaufs_arg *p;
+
+	p = file->private_data;
+	return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+	struct super_block *sb;
+
+	sbinfo = inode->i_private;
+	sb = sbinfo->si_sb;
+	si_noflush_read_lock(sb);
+	err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
+	si_read_unlock(sb);
+	return err;
+}
+
+static const struct file_operations dbgaufs_xib_fop = {
+	.open		= dbgaufs_xib_open,
+	.release	= dbgaufs_xi_release,
+	.read		= dbgaufs_xi_read
+};
+
+/* ---------------------------------------------------------------------- */
+
+#define DbgaufsXi_PREFIX "xi"
+
+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
+{
+	int err;
+	long l;
+	struct au_sbinfo *sbinfo;
+	struct super_block *sb;
+	struct file *xf;
+	struct qstr *name;
+
+	err = -ENOENT;
+	xf = NULL;
+	name = &file->f_dentry->d_name;
+	if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
+		     || memcmp(name->name, DbgaufsXi_PREFIX,
+			       sizeof(DbgaufsXi_PREFIX) - 1)))
+		goto out;
+	err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
+	if (unlikely(err))
+		goto out;
+
+	sbinfo = inode->i_private;
+	sb = sbinfo->si_sb;
+	si_noflush_read_lock(sb);
+	if (l <= au_sbend(sb)) {
+		xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
+		err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
+	} else
+		err = -ENOENT;
+	si_read_unlock(sb);
+
+ out:
+	return err;
+}
+
+static const struct file_operations dbgaufs_xino_fop = {
+	.open		= dbgaufs_xino_open,
+	.release	= dbgaufs_xi_release,
+	.read		= dbgaufs_xi_read
+};
+
+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+	aufs_bindex_t bend;
+	struct au_branch *br;
+	struct au_xino_file *xi;
+
+	if (!au_sbi(sb)->si_dbgaufs)
+		return;
+
+	bend = au_sbend(sb);
+	for (; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		xi = &br->br_xino;
+		if (xi->xi_dbgaufs) {
+			debugfs_remove(xi->xi_dbgaufs);
+			xi->xi_dbgaufs = NULL;
+		}
+	}
+}
+
+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+	struct au_sbinfo *sbinfo;
+	struct dentry *parent;
+	struct au_branch *br;
+	struct au_xino_file *xi;
+	aufs_bindex_t bend;
+	char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
+
+	sbinfo = au_sbi(sb);
+	parent = sbinfo->si_dbgaufs;
+	if (!parent)
+		return;
+
+	bend = au_sbend(sb);
+	for (; bindex <= bend; bindex++) {
+		snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
+		br = au_sbr(sb, bindex);
+		xi = &br->br_xino;
+		AuDebugOn(xi->xi_dbgaufs);
+		xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
+						     sbinfo, &dbgaufs_xino_fop);
+		/* ignore an error */
+		if (unlikely(!xi->xi_dbgaufs))
+			AuWarn1("failed %s under debugfs\n", name);
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_EXPORT
+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+	struct super_block *sb;
+
+	sbinfo = inode->i_private;
+	sb = sbinfo->si_sb;
+	si_noflush_read_lock(sb);
+	err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
+	si_read_unlock(sb);
+	return err;
+}
+
+static const struct file_operations dbgaufs_xigen_fop = {
+	.open		= dbgaufs_xigen_open,
+	.release	= dbgaufs_xi_release,
+	.read		= dbgaufs_xi_read
+};
+
+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
+{
+	int err;
+
+	/*
+	 * This function is a dynamic '__init' fucntion actually,
+	 * so the tiny check for si_rwsem is unnecessary.
+	 */
+	/* AuRwMustWriteLock(&sbinfo->si_rwsem); */
+
+	err = -EIO;
+	sbinfo->si_dbgaufs_xigen = debugfs_create_file
+		("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
+		 &dbgaufs_xigen_fop);
+	if (sbinfo->si_dbgaufs_xigen)
+		err = 0;
+
+	return err;
+}
+#else
+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
+{
+	return 0;
+}
+#endif /* CONFIG_AUFS_EXPORT */
+
+/* ---------------------------------------------------------------------- */
+
+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
+{
+	/*
+	 * This function is a dynamic '__init' fucntion actually,
+	 * so the tiny check for si_rwsem is unnecessary.
+	 */
+	/* AuRwMustWriteLock(&sbinfo->si_rwsem); */
+
+	debugfs_remove_recursive(sbinfo->si_dbgaufs);
+	sbinfo->si_dbgaufs = NULL;
+	kobject_put(&sbinfo->si_kobj);
+}
+
+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
+{
+	int err;
+	char name[SysaufsSiNameLen];
+
+	/*
+	 * This function is a dynamic '__init' fucntion actually,
+	 * so the tiny check for si_rwsem is unnecessary.
+	 */
+	/* AuRwMustWriteLock(&sbinfo->si_rwsem); */
+
+	err = -ENOENT;
+	if (!dbgaufs) {
+		AuErr1("/debug/aufs is uninitialized\n");
+		goto out;
+	}
+
+	err = -EIO;
+	sysaufs_name(sbinfo, name);
+	sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
+	if (unlikely(!sbinfo->si_dbgaufs))
+		goto out;
+	kobject_get(&sbinfo->si_kobj);
+
+	sbinfo->si_dbgaufs_xib = debugfs_create_file
+		("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
+		 &dbgaufs_xib_fop);
+	if (unlikely(!sbinfo->si_dbgaufs_xib))
+		goto out_dir;
+
+	err = dbgaufs_xigen_init(sbinfo);
+	if (!err)
+		goto out; /* success */
+
+ out_dir:
+	dbgaufs_si_fin(sbinfo);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void dbgaufs_fin(void)
+{
+	debugfs_remove(dbgaufs);
+}
+
+int __init dbgaufs_init(void)
+{
+	int err;
+
+	err = -EIO;
+	dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
+	if (dbgaufs)
+		err = 0;
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/hinotify.c
+++ linux-ec2-2.6.32/ubuntu/aufs/hinotify.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inotify for the lower directories
+ */
+
+#include "aufs.h"
+
+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
+static struct inotify_handle *au_hin_handle;
+
+AuCacheFuncs(hinotify, HINOTIFY);
+
+int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
+		 struct inode *h_inode)
+{
+	int err;
+	struct au_hinotify *hin;
+	s32 wd;
+
+	err = -ENOMEM;
+	hin = au_cache_alloc_hinotify();
+	if (hin) {
+		AuDebugOn(hinode->hi_notify);
+		hinode->hi_notify = hin;
+		hin->hin_aufs_inode = inode;
+
+		inotify_init_watch(&hin->hin_watch);
+		wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
+				       AuHinMask);
+		if (wd >= 0)
+			return 0; /* success */
+
+		err = wd;
+		put_inotify_watch(&hin->hin_watch);
+		au_cache_free_hinotify(hin);
+		hinode->hi_notify = NULL;
+	}
+
+	return err;
+}
+
+void au_hin_free(struct au_hinode *hinode)
+{
+	int err;
+	struct au_hinotify *hin;
+
+	hin = hinode->hi_notify;
+	if (hin) {
+		err = 0;
+		if (atomic_read(&hin->hin_watch.count))
+			err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
+		if (unlikely(err))
+			/* it means the watch is already removed */
+			pr_warning("failed inotify_rm_watch() %d\n", err);
+		au_cache_free_hinotify(hin);
+		hinode->hi_notify = NULL;
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_hin_ctl(struct au_hinode *hinode, int do_set)
+{
+	struct inode *h_inode;
+	struct inotify_watch *watch;
+
+	if (!hinode->hi_notify)
+		return;
+
+	h_inode = hinode->hi_inode;
+	IMustLock(h_inode);
+
+	/* todo: try inotify_find_update_watch()? */
+	watch = &hinode->hi_notify->hin_watch;
+	mutex_lock(&h_inode->inotify_mutex);
+	/* mutex_lock(&watch->ih->mutex); */
+	if (do_set) {
+		AuDebugOn(watch->mask & AuHinMask);
+		watch->mask |= AuHinMask;
+	} else {
+		AuDebugOn(!(watch->mask & AuHinMask));
+		watch->mask &= ~AuHinMask;
+	}
+	/* mutex_unlock(&watch->ih->mutex); */
+	mutex_unlock(&h_inode->inotify_mutex);
+}
+
+void au_reset_hinotify(struct inode *inode, unsigned int flags)
+{
+	aufs_bindex_t bindex, bend;
+	struct inode *hi;
+	struct dentry *iwhdentry;
+
+	bend = au_ibend(inode);
+	for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
+		hi = au_h_iptr(inode, bindex);
+		if (!hi)
+			continue;
+
+		/* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
+		iwhdentry = au_hi_wh(inode, bindex);
+		if (iwhdentry)
+			dget(iwhdentry);
+		au_igrab(hi);
+		au_set_h_iptr(inode, bindex, NULL, 0);
+		au_set_h_iptr(inode, bindex, au_igrab(hi),
+			      flags & ~AuHi_XINO);
+		iput(hi);
+		dput(iwhdentry);
+		/* mutex_unlock(&hi->i_mutex); */
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int hin_xino(struct inode *inode, struct inode *h_inode)
+{
+	int err;
+	aufs_bindex_t bindex, bend, bfound, bstart;
+	struct inode *h_i;
+
+	err = 0;
+	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
+		pr_warning("branch root dir was changed\n");
+		goto out;
+	}
+
+	bfound = -1;
+	bend = au_ibend(inode);
+	bstart = au_ibstart(inode);
+#if 0 /* reserved for future use */
+	if (bindex == bend) {
+		/* keep this ino in rename case */
+		goto out;
+	}
+#endif
+	for (bindex = bstart; bindex <= bend; bindex++) {
+		if (au_h_iptr(inode, bindex) == h_inode) {
+			bfound = bindex;
+			break;
+		}
+	}
+	if (bfound < 0)
+		goto out;
+
+	for (bindex = bstart; bindex <= bend; bindex++) {
+		h_i = au_h_iptr(inode, bindex);
+		if (!h_i)
+			continue;
+
+		err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
+		/* ignore this error */
+		/* bad action? */
+	}
+
+	/* children inode number will be broken */
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int hin_gen_tree(struct dentry *dentry)
+{
+	int err, i, j, ndentry;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+
+	err = au_dpages_init(&dpages, GFP_NOFS);
+	if (unlikely(err))
+		goto out;
+	err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
+	if (unlikely(err))
+		goto out_dpages;
+
+	for (i = 0; i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		ndentry = dpage->ndentry;
+		for (j = 0; j < ndentry; j++) {
+			struct dentry *d;
+
+			d = dentries[j];
+			if (IS_ROOT(d))
+				continue;
+
+			d_drop(d);
+			au_digen_dec(d);
+			if (d->d_inode)
+				/* todo: reset children xino?
+				   cached children only? */
+				au_iigen_dec(d->d_inode);
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+
+	/* discard children */
+	dentry_unhash(dentry);
+	dput(dentry);
+ out:
+	return err;
+}
+
+/*
+ * return 0 if processed.
+ */
+static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
+			    const unsigned int isdir)
+{
+	int err;
+	struct dentry *d;
+	struct qstr *dname;
+
+	err = 1;
+	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
+		pr_warning("branch root dir was changed\n");
+		err = 0;
+		goto out;
+	}
+
+	if (!isdir) {
+		AuDebugOn(!name);
+		au_iigen_dec(inode);
+		spin_lock(&dcache_lock);
+		list_for_each_entry(d, &inode->i_dentry, d_alias) {
+			dname = &d->d_name;
+			if (dname->len != nlen
+			    && memcmp(dname->name, name, nlen))
+				continue;
+			err = 0;
+			spin_lock(&d->d_lock);
+			__d_drop(d);
+			au_digen_dec(d);
+			spin_unlock(&d->d_lock);
+			break;
+		}
+		spin_unlock(&dcache_lock);
+	} else {
+		au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
+		d = d_find_alias(inode);
+		if (!d) {
+			au_iigen_dec(inode);
+			goto out;
+		}
+
+		dname = &d->d_name;
+		if (dname->len == nlen && !memcmp(dname->name, name, nlen))
+			err = hin_gen_tree(d);
+		dput(d);
+	}
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
+{
+	int err;
+	struct inode *inode;
+
+	inode = dentry->d_inode;
+	if (IS_ROOT(dentry)
+	    /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
+		) {
+		pr_warning("branch root dir was changed\n");
+		return 0;
+	}
+
+	err = 0;
+	if (!isdir) {
+		d_drop(dentry);
+		au_digen_dec(dentry);
+		if (inode)
+			au_iigen_dec(inode);
+	} else {
+		au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
+		if (inode)
+			err = hin_gen_tree(dentry);
+	}
+
+	AuTraceErr(err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* hinotify job flags */
+#define AuHinJob_XINO0		1
+#define AuHinJob_GEN		(1 << 1)
+#define AuHinJob_DIRENT		(1 << 2)
+#define AuHinJob_ISDIR		(1 << 3)
+#define AuHinJob_TRYXINO0	(1 << 4)
+#define AuHinJob_MNTPNT		(1 << 5)
+#define au_ftest_hinjob(flags, name)	((flags) & AuHinJob_##name)
+#define au_fset_hinjob(flags, name)	{ (flags) |= AuHinJob_##name; }
+#define au_fclr_hinjob(flags, name)	{ (flags) &= ~AuHinJob_##name; }
+
+struct hin_job_args {
+	unsigned int flags;
+	struct inode *inode, *h_inode, *dir, *h_dir;
+	struct dentry *dentry;
+	char *h_name;
+	int h_nlen;
+};
+
+static int hin_job(struct hin_job_args *a)
+{
+	const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
+
+	/* reset xino */
+	if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
+		hin_xino(a->inode, a->h_inode); /* ignore this error */
+
+	if (au_ftest_hinjob(a->flags, TRYXINO0)
+	    && a->inode
+	    && a->h_inode) {
+		mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
+		if (!a->h_inode->i_nlink)
+			hin_xino(a->inode, a->h_inode); /* ignore this error */
+		mutex_unlock(&a->h_inode->i_mutex);
+	}
+
+	/* make the generation obsolete */
+	if (au_ftest_hinjob(a->flags, GEN)) {
+		int err = -1;
+		if (a->inode)
+			err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
+					       isdir);
+		if (err && a->dentry)
+			hin_gen_by_name(a->dentry, isdir);
+		/* ignore this error */
+	}
+
+	/* make dir entries obsolete */
+	if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
+		struct au_vdir *vdir;
+
+		vdir = au_ivdir(a->inode);
+		if (vdir)
+			vdir->vd_jiffy = 0;
+		/* IMustLock(a->inode); */
+		/* a->inode->i_version++; */
+	}
+
+	/* can do nothing but warn */
+	if (au_ftest_hinjob(a->flags, MNTPNT)
+	    && a->dentry
+	    && d_mountpoint(a->dentry))
+		pr_warning("mount-point %.*s is removed or renamed\n",
+			   AuDLNPair(a->dentry));
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static char *in_name(u32 mask)
+{
+#ifdef CONFIG_AUFS_DEBUG
+#define test_ret(flag)	if (mask & flag) \
+				return #flag;
+	test_ret(IN_ACCESS);
+	test_ret(IN_MODIFY);
+	test_ret(IN_ATTRIB);
+	test_ret(IN_CLOSE_WRITE);
+	test_ret(IN_CLOSE_NOWRITE);
+	test_ret(IN_OPEN);
+	test_ret(IN_MOVED_FROM);
+	test_ret(IN_MOVED_TO);
+	test_ret(IN_CREATE);
+	test_ret(IN_DELETE);
+	test_ret(IN_DELETE_SELF);
+	test_ret(IN_MOVE_SELF);
+	test_ret(IN_UNMOUNT);
+	test_ret(IN_Q_OVERFLOW);
+	test_ret(IN_IGNORED);
+	return "";
+#undef test_ret
+#else
+	return "??";
+#endif
+}
+
+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
+					   struct inode *dir)
+{
+	struct dentry *dentry, *d, *parent;
+	struct qstr *dname;
+
+	parent = d_find_alias(dir);
+	if (!parent)
+		return NULL;
+
+	dentry = NULL;
+	spin_lock(&dcache_lock);
+	list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
+		/* AuDbg("%.*s\n", AuDLNPair(d)); */
+		dname = &d->d_name;
+		if (dname->len != nlen || memcmp(dname->name, name, nlen))
+			continue;
+		if (!atomic_read(&d->d_count) || !d->d_fsdata) {
+			spin_lock(&d->d_lock);
+			__d_drop(d);
+			spin_unlock(&d->d_lock);
+			continue;
+		}
+
+		dentry = dget(d);
+		break;
+	}
+	spin_unlock(&dcache_lock);
+	dput(parent);
+
+	if (dentry)
+		di_write_lock_child(dentry);
+
+	return dentry;
+}
+
+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
+					 aufs_bindex_t bindex, ino_t h_ino)
+{
+	struct inode *inode;
+	ino_t ino;
+	int err;
+
+	inode = NULL;
+	err = au_xino_read(sb, bindex, h_ino, &ino);
+	if (!err && ino)
+		inode = ilookup(sb, ino);
+	if (!inode)
+		goto out;
+
+	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
+		pr_warning("wrong root branch\n");
+		iput(inode);
+		inode = NULL;
+		goto out;
+	}
+
+	ii_write_lock_child(inode);
+
+ out:
+	return inode;
+}
+
+enum { CHILD, PARENT };
+struct postproc_args {
+	struct inode *h_dir, *dir, *h_child_inode;
+	u32 mask;
+	unsigned int flags[2];
+	unsigned int h_child_nlen;
+	char h_child_name[];
+};
+
+static void postproc(void *_args)
+{
+	struct postproc_args *a = _args;
+	struct super_block *sb;
+	aufs_bindex_t bindex, bend, bfound;
+	unsigned char xino, try_iput;
+	int err;
+	struct inode *inode;
+	ino_t h_ino;
+	struct hin_job_args args;
+	struct dentry *dentry;
+	struct au_sbinfo *sbinfo;
+
+	AuDebugOn(!_args);
+	AuDebugOn(!a->h_dir);
+	AuDebugOn(!a->dir);
+	AuDebugOn(!a->mask);
+	AuDbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
+	      a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
+	      a->h_child_inode ? a->h_child_inode->i_ino : 0);
+
+	inode = NULL;
+	dentry = NULL;
+	/*
+	 * do not lock a->dir->i_mutex here
+	 * because of d_revalidate() may cause a deadlock.
+	 */
+	sb = a->dir->i_sb;
+	AuDebugOn(!sb);
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!sbinfo);
+	/* big aufs lock */
+	si_noflush_write_lock(sb);
+
+	ii_read_lock_parent(a->dir);
+	bfound = -1;
+	bend = au_ibend(a->dir);
+	for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
+		if (au_h_iptr(a->dir, bindex) == a->h_dir) {
+			bfound = bindex;
+			break;
+		}
+	ii_read_unlock(a->dir);
+	if (unlikely(bfound < 0))
+		goto out;
+
+	xino = !!au_opt_test(au_mntflags(sb), XINO);
+	h_ino = 0;
+	if (a->h_child_inode)
+		h_ino = a->h_child_inode->i_ino;
+
+	if (a->h_child_nlen
+	    && (au_ftest_hinjob(a->flags[CHILD], GEN)
+		|| au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
+		dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
+					      a->dir);
+	try_iput = 0;
+	if (dentry)
+		inode = dentry->d_inode;
+	if (xino && !inode && h_ino
+	    && (au_ftest_hinjob(a->flags[CHILD], XINO0)
+		|| au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
+		|| au_ftest_hinjob(a->flags[CHILD], GEN))) {
+		inode = lookup_wlock_by_ino(sb, bfound, h_ino);
+		try_iput = 1;
+	    }
+
+	args.flags = a->flags[CHILD];
+	args.dentry = dentry;
+	args.inode = inode;
+	args.h_inode = a->h_child_inode;
+	args.dir = a->dir;
+	args.h_dir = a->h_dir;
+	args.h_name = a->h_child_name;
+	args.h_nlen = a->h_child_nlen;
+	err = hin_job(&args);
+	if (dentry) {
+		if (dentry->d_fsdata)
+			di_write_unlock(dentry);
+		dput(dentry);
+	}
+	if (inode && try_iput) {
+		ii_write_unlock(inode);
+		iput(inode);
+	}
+
+	ii_write_lock_parent(a->dir);
+	args.flags = a->flags[PARENT];
+	args.dentry = NULL;
+	args.inode = a->dir;
+	args.h_inode = a->h_dir;
+	args.dir = NULL;
+	args.h_dir = NULL;
+	args.h_name = NULL;
+	args.h_nlen = 0;
+	err = hin_job(&args);
+	ii_write_unlock(a->dir);
+
+ out:
+	au_nwt_done(&sbinfo->si_nowait);
+	si_write_unlock(sb);
+
+	iput(a->h_child_inode);
+	iput(a->h_dir);
+	iput(a->dir);
+	kfree(a);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
+			 u32 mask, u32 cookie __maybe_unused,
+			 const char *h_child_name, struct inode *h_child_inode)
+{
+	struct au_hinotify *hinotify;
+	struct postproc_args *args;
+	int len, wkq_err;
+	unsigned char isdir, isroot, wh;
+	char *p;
+	struct inode *dir;
+	unsigned int flags[2];
+
+	/* if IN_UNMOUNT happens, there must be another bug */
+	AuDebugOn(mask & IN_UNMOUNT);
+	if (mask & (IN_IGNORED | IN_UNMOUNT)) {
+		put_inotify_watch(watch);
+		return;
+	}
+#ifdef AuDbgHinotify
+	au_debug(1);
+	if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
+		AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
+		      " hi%lu\n",
+		      watch->inode->i_ino, wd, mask, in_name(mask), cookie,
+		      h_child_name ? h_child_name : "",
+		      h_child_inode ? h_child_inode->i_ino : 0);
+		WARN_ON(1);
+	}
+	au_debug(0);
+#endif
+
+	hinotify = container_of(watch, struct au_hinotify, hin_watch);
+	AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
+	dir = igrab(hinotify->hin_aufs_inode);
+	if (!dir)
+		return;
+
+	isroot = (dir->i_ino == AUFS_ROOT_INO);
+	len = 0;
+	wh = 0;
+	if (h_child_name) {
+		len = strlen(h_child_name);
+		if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
+			h_child_name += AUFS_WH_PFX_LEN;
+			len -= AUFS_WH_PFX_LEN;
+			wh = 1;
+		}
+	}
+
+	isdir = 0;
+	if (h_child_inode)
+		isdir = !!S_ISDIR(h_child_inode->i_mode);
+	flags[PARENT] = AuHinJob_ISDIR;
+	flags[CHILD] = 0;
+	if (isdir)
+		flags[CHILD] = AuHinJob_ISDIR;
+	switch (mask & IN_ALL_EVENTS) {
+	case IN_MOVED_FROM:
+	case IN_MOVED_TO:
+		AuDebugOn(!h_child_name || !h_child_inode);
+		au_fset_hinjob(flags[CHILD], GEN);
+		au_fset_hinjob(flags[CHILD], XINO0);
+		au_fset_hinjob(flags[CHILD], MNTPNT);
+		au_fset_hinjob(flags[PARENT], DIRENT);
+		break;
+
+	case IN_CREATE:
+		AuDebugOn(!h_child_name || !h_child_inode);
+		au_fset_hinjob(flags[PARENT], DIRENT);
+		au_fset_hinjob(flags[CHILD], GEN);
+		break;
+
+	case IN_DELETE:
+		/*
+		 * aufs never be able to get this child inode.
+		 * revalidation should be in d_revalidate()
+		 * by checking i_nlink, i_generation or d_unhashed().
+		 */
+		AuDebugOn(!h_child_name);
+		au_fset_hinjob(flags[PARENT], DIRENT);
+		au_fset_hinjob(flags[CHILD], GEN);
+		au_fset_hinjob(flags[CHILD], TRYXINO0);
+		au_fset_hinjob(flags[CHILD], MNTPNT);
+		break;
+
+	default:
+		AuDebugOn(1);
+	}
+
+	if (wh)
+		h_child_inode = NULL;
+
+	/* iput() and kfree() will be called in postproc() */
+	/*
+	 * inotify_mutex is already acquired and kmalloc/prune_icache may lock
+	 * iprune_mutex. strange.
+	 */
+	/* lockdep_off(); */
+	args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
+	/* lockdep_on(); */
+	if (unlikely(!args)) {
+		AuErr1("no memory\n");
+		iput(dir);
+		return;
+	}
+	args->flags[PARENT] = flags[PARENT];
+	args->flags[CHILD] = flags[CHILD];
+	args->mask = mask;
+	args->dir = dir;
+	args->h_dir = igrab(watch->inode);
+	if (h_child_inode)
+		h_child_inode = igrab(h_child_inode); /* can be NULL */
+	args->h_child_inode = h_child_inode;
+	args->h_child_nlen = len;
+	if (len) {
+		p = (void *)args;
+		p += sizeof(*args);
+		memcpy(p, h_child_name, len + 1);
+	}
+
+	/* lockdep_off(); */
+	wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
+	/* lockdep_on(); */
+	if (unlikely(wkq_err))
+		pr_err("wkq %d\n", wkq_err);
+}
+
+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
+{
+	return;
+}
+
+static struct inotify_operations aufs_inotify_ops = {
+	.handle_event	= aufs_inotify,
+	.destroy_watch	= aufs_inotify_destroy
+};
+
+/* ---------------------------------------------------------------------- */
+
+static void au_hin_destroy_cache(void)
+{
+	kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
+	au_cachep[AuCache_HINOTIFY] = NULL;
+}
+
+int __init au_hinotify_init(void)
+{
+	int err;
+
+	err = -ENOMEM;
+	au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
+	if (au_cachep[AuCache_HINOTIFY]) {
+		err = 0;
+		au_hin_handle = inotify_init(&aufs_inotify_ops);
+		if (IS_ERR(au_hin_handle)) {
+			err = PTR_ERR(au_hin_handle);
+			au_hin_destroy_cache();
+		}
+	}
+	AuTraceErr(err);
+	return err;
+}
+
+void au_hinotify_fin(void)
+{
+	inotify_destroy(au_hin_handle);
+	if (au_cachep[AuCache_HINOTIFY])
+		au_hin_destroy_cache();
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/wbr_policy.c
+++ linux-ec2-2.6.32/ubuntu/aufs/wbr_policy.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * policies for selecting one among multiple writable branches
+ */
+
+#include <linux/statfs.h>
+#include "aufs.h"
+
+/* subset of cpup_attr() */
+static noinline_for_stack
+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
+{
+	int err, sbits;
+	struct iattr ia;
+	struct inode *h_isrc;
+
+	h_isrc = h_src->d_inode;
+	ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
+	ia.ia_mode = h_isrc->i_mode;
+	ia.ia_uid = h_isrc->i_uid;
+	ia.ia_gid = h_isrc->i_gid;
+	sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
+	au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
+	err = vfsub_sio_notify_change(h_path, &ia);
+
+	/* is this nfs only? */
+	if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
+		ia.ia_valid = ATTR_FORCE | ATTR_MODE;
+		ia.ia_mode = h_isrc->i_mode;
+		err = vfsub_sio_notify_change(h_path, &ia);
+	}
+
+	return err;
+}
+
+#define AuCpdown_PARENT_OPQ	1
+#define AuCpdown_WHED		(1 << 1)
+#define AuCpdown_MADE_DIR	(1 << 2)
+#define AuCpdown_DIROPQ		(1 << 3)
+#define au_ftest_cpdown(flags, name)	((flags) & AuCpdown_##name)
+#define au_fset_cpdown(flags, name)	{ (flags) |= AuCpdown_##name; }
+#define au_fclr_cpdown(flags, name)	{ (flags) &= ~AuCpdown_##name; }
+
+struct au_cpdown_dir_args {
+	struct dentry *parent;
+	unsigned int flags;
+};
+
+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
+			     struct au_cpdown_dir_args *a)
+{
+	int err;
+	struct dentry *opq_dentry;
+
+	opq_dentry = au_diropq_create(dentry, bdst);
+	err = PTR_ERR(opq_dentry);
+	if (IS_ERR(opq_dentry))
+		goto out;
+	dput(opq_dentry);
+	au_fset_cpdown(a->flags, DIROPQ);
+
+ out:
+	return err;
+}
+
+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
+			    struct inode *dir, aufs_bindex_t bdst)
+{
+	int err;
+	struct path h_path;
+	struct au_branch *br;
+
+	br = au_sbr(dentry->d_sb, bdst);
+	h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
+	err = PTR_ERR(h_path.dentry);
+	if (IS_ERR(h_path.dentry))
+		goto out;
+
+	err = 0;
+	if (h_path.dentry->d_inode) {
+		h_path.mnt = br->br_mnt;
+		err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
+					  dentry);
+	}
+	dput(h_path.dentry);
+
+ out:
+	return err;
+}
+
+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
+			 struct dentry *h_parent, void *arg)
+{
+	int err, rerr;
+	aufs_bindex_t bend, bopq, bstart;
+	unsigned char parent_opq;
+	struct path h_path;
+	struct dentry *parent;
+	struct inode *h_dir, *h_inode, *inode, *dir;
+	struct au_cpdown_dir_args *args = arg;
+
+	bstart = au_dbstart(dentry);
+	/* dentry is di-locked */
+	parent = dget_parent(dentry);
+	dir = parent->d_inode;
+	h_dir = h_parent->d_inode;
+	AuDebugOn(h_dir != au_h_iptr(dir, bdst));
+	IMustLock(h_dir);
+
+	err = au_lkup_neg(dentry, bdst);
+	if (unlikely(err < 0))
+		goto out;
+	h_path.dentry = au_h_dptr(dentry, bdst);
+	h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
+	err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
+			      S_IRWXU | S_IRUGO | S_IXUGO);
+	if (unlikely(err))
+		goto out_put;
+	au_fset_cpdown(args->flags, MADE_DIR);
+
+	bend = au_dbend(dentry);
+	bopq = au_dbdiropq(dentry);
+	au_fclr_cpdown(args->flags, WHED);
+	au_fclr_cpdown(args->flags, DIROPQ);
+	if (au_dbwh(dentry) == bdst)
+		au_fset_cpdown(args->flags, WHED);
+	if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
+		au_fset_cpdown(args->flags, PARENT_OPQ);
+	parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
+		      && args->parent == dentry);
+	h_inode = h_path.dentry->d_inode;
+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+	if (au_ftest_cpdown(args->flags, WHED)) {
+		err = au_cpdown_dir_opq(dentry, bdst, args);
+		if (unlikely(err)) {
+			mutex_unlock(&h_inode->i_mutex);
+			goto out_dir;
+		}
+	}
+
+	err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
+	mutex_unlock(&h_inode->i_mutex);
+	if (unlikely(err))
+		goto out_opq;
+
+	if (au_ftest_cpdown(args->flags, WHED)) {
+		err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
+		if (unlikely(err))
+			goto out_opq;
+	}
+
+	inode = dentry->d_inode;
+	if (au_ibend(inode) < bdst)
+		au_set_ibend(inode, bdst);
+	au_set_h_iptr(inode, bdst, au_igrab(h_inode),
+		      au_hi_flags(inode, /*isdir*/1));
+	goto out; /* success */
+
+	/* revert */
+ out_opq:
+	if (au_ftest_cpdown(args->flags, DIROPQ)) {
+		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+		rerr = au_diropq_remove(dentry, bdst);
+		mutex_unlock(&h_inode->i_mutex);
+		if (unlikely(rerr)) {
+			AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
+				AuDLNPair(dentry), bdst, rerr);
+			err = -EIO;
+			goto out;
+		}
+	}
+ out_dir:
+	if (au_ftest_cpdown(args->flags, MADE_DIR)) {
+		rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
+		if (unlikely(rerr)) {
+			AuIOErr("failed removing %.*s b%d (%d)\n",
+				AuDLNPair(dentry), bdst, rerr);
+			err = -EIO;
+		}
+	}
+ out_put:
+	au_set_h_dptr(dentry, bdst, NULL);
+	if (au_dbend(dentry) == bdst)
+		au_update_dbend(dentry);
+ out:
+	dput(parent);
+	return err;
+}
+
+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
+{
+	int err;
+	struct au_cpdown_dir_args args = {
+		.parent	= dget_parent(dentry),
+		.flags	= 0
+	};
+
+	err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
+	dput(args.parent);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* policies for create */
+
+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
+{
+	for (; bindex >= 0; bindex--)
+		if (!au_br_rdonly(au_sbr(sb, bindex)))
+			return bindex;
+	return -EROFS;
+}
+
+/* top down parent */
+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
+{
+	int err;
+	aufs_bindex_t bstart, bindex;
+	struct super_block *sb;
+	struct dentry *parent, *h_parent;
+
+	sb = dentry->d_sb;
+	bstart = au_dbstart(dentry);
+	err = bstart;
+	if (!au_br_rdonly(au_sbr(sb, bstart)))
+		goto out;
+
+	err = -EROFS;
+	parent = dget_parent(dentry);
+	for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
+		h_parent = au_h_dptr(parent, bindex);
+		if (!h_parent || !h_parent->d_inode)
+			continue;
+
+		if (!au_br_rdonly(au_sbr(sb, bindex))) {
+			err = bindex;
+			break;
+		}
+	}
+	dput(parent);
+
+	/* bottom up here */
+	if (unlikely(err < 0))
+		err = au_wbr_bu(sb, bstart - 1);
+
+ out:
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* an exception for the policy other than tdp */
+static int au_wbr_create_exp(struct dentry *dentry)
+{
+	int err;
+	aufs_bindex_t bwh, bdiropq;
+	struct dentry *parent;
+
+	err = -1;
+	bwh = au_dbwh(dentry);
+	parent = dget_parent(dentry);
+	bdiropq = au_dbdiropq(parent);
+	if (bwh >= 0) {
+		if (bdiropq >= 0)
+			err = min(bdiropq, bwh);
+		else
+			err = bwh;
+		AuDbg("%d\n", err);
+	} else if (bdiropq >= 0) {
+		err = bdiropq;
+		AuDbg("%d\n", err);
+	}
+	dput(parent);
+
+	if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
+		err = -1;
+
+	AuDbg("%d\n", err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* round robin */
+static int au_wbr_create_init_rr(struct super_block *sb)
+{
+	int err;
+
+	err = au_wbr_bu(sb, au_sbend(sb));
+	atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
+	/* smp_mb(); */
+
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
+{
+	int err, nbr;
+	unsigned int u;
+	aufs_bindex_t bindex, bend;
+	struct super_block *sb;
+	atomic_t *next;
+
+	err = au_wbr_create_exp(dentry);
+	if (err >= 0)
+		goto out;
+
+	sb = dentry->d_sb;
+	next = &au_sbi(sb)->si_wbr_rr_next;
+	bend = au_sbend(sb);
+	nbr = bend + 1;
+	for (bindex = 0; bindex <= bend; bindex++) {
+		if (!isdir) {
+			err = atomic_dec_return(next) + 1;
+			/* modulo for 0 is meaningless */
+			if (unlikely(!err))
+				err = atomic_dec_return(next) + 1;
+		} else
+			err = atomic_read(next);
+		AuDbg("%d\n", err);
+		u = err;
+		err = u % nbr;
+		AuDbg("%d\n", err);
+		if (!au_br_rdonly(au_sbr(sb, err)))
+			break;
+		err = -EROFS;
+	}
+
+ out:
+	AuDbg("%d\n", err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* most free space */
+static void au_mfs(struct dentry *dentry)
+{
+	struct super_block *sb;
+	struct au_branch *br;
+	struct au_wbr_mfs *mfs;
+	aufs_bindex_t bindex, bend;
+	int err;
+	unsigned long long b, bavail;
+	/* reduce the stack usage */
+	struct kstatfs *st;
+
+	st = kmalloc(sizeof(*st), GFP_NOFS);
+	if (unlikely(!st)) {
+		AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
+		return;
+	}
+
+	bavail = 0;
+	sb = dentry->d_sb;
+	mfs = &au_sbi(sb)->si_wbr_mfs;
+	MtxMustLock(&mfs->mfs_lock);
+	mfs->mfs_bindex = -EROFS;
+	mfs->mfsrr_bytes = 0;
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		if (au_br_rdonly(br))
+			continue;
+
+		/* sb->s_root for NFS is unreliable */
+		err = vfs_statfs(br->br_mnt->mnt_root, st);
+		if (unlikely(err)) {
+			AuWarn1("failed statfs, b%d, %d\n", bindex, err);
+			continue;
+		}
+
+		/* when the available size is equal, select the lower one */
+		BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
+			     || sizeof(b) < sizeof(st->f_bsize));
+		b = st->f_bavail * st->f_bsize;
+		br->br_wbr->wbr_bytes = b;
+		if (b >= bavail) {
+			bavail = b;
+			mfs->mfs_bindex = bindex;
+			mfs->mfs_jiffy = jiffies;
+		}
+	}
+
+	mfs->mfsrr_bytes = bavail;
+	AuDbg("b%d\n", mfs->mfs_bindex);
+	kfree(st);
+}
+
+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
+{
+	int err;
+	struct super_block *sb;
+	struct au_wbr_mfs *mfs;
+
+	err = au_wbr_create_exp(dentry);
+	if (err >= 0)
+		goto out;
+
+	sb = dentry->d_sb;
+	mfs = &au_sbi(sb)->si_wbr_mfs;
+	mutex_lock(&mfs->mfs_lock);
+	if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
+	    || mfs->mfs_bindex < 0
+	    || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
+		au_mfs(dentry);
+	mutex_unlock(&mfs->mfs_lock);
+	err = mfs->mfs_bindex;
+
+ out:
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+static int au_wbr_create_init_mfs(struct super_block *sb)
+{
+	struct au_wbr_mfs *mfs;
+
+	mfs = &au_sbi(sb)->si_wbr_mfs;
+	mutex_init(&mfs->mfs_lock);
+	mfs->mfs_jiffy = 0;
+	mfs->mfs_bindex = -EROFS;
+
+	return 0;
+}
+
+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
+{
+	mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* most free space and then round robin */
+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
+{
+	int err;
+	struct au_wbr_mfs *mfs;
+
+	err = au_wbr_create_mfs(dentry, isdir);
+	if (err >= 0) {
+		mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
+		mutex_lock(&mfs->mfs_lock);
+		if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
+			err = au_wbr_create_rr(dentry, isdir);
+		mutex_unlock(&mfs->mfs_lock);
+	}
+
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+static int au_wbr_create_init_mfsrr(struct super_block *sb)
+{
+	int err;
+
+	au_wbr_create_init_mfs(sb); /* ignore */
+	err = au_wbr_create_init_rr(sb);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* top down parent and most free space */
+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
+{
+	int err, e2;
+	unsigned long long b;
+	aufs_bindex_t bindex, bstart, bend;
+	struct super_block *sb;
+	struct dentry *parent, *h_parent;
+	struct au_branch *br;
+
+	err = au_wbr_create_tdp(dentry, isdir);
+	if (unlikely(err < 0))
+		goto out;
+	parent = dget_parent(dentry);
+	bstart = au_dbstart(parent);
+	bend = au_dbtaildir(parent);
+	if (bstart == bend)
+		goto out_parent; /* success */
+
+	e2 = au_wbr_create_mfs(dentry, isdir);
+	if (e2 < 0)
+		goto out_parent; /* success */
+
+	/* when the available size is equal, select upper one */
+	sb = dentry->d_sb;
+	br = au_sbr(sb, err);
+	b = br->br_wbr->wbr_bytes;
+	AuDbg("b%d, %llu\n", err, b);
+
+	for (bindex = bstart; bindex <= bend; bindex++) {
+		h_parent = au_h_dptr(parent, bindex);
+		if (!h_parent || !h_parent->d_inode)
+			continue;
+
+		br = au_sbr(sb, bindex);
+		if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
+			b = br->br_wbr->wbr_bytes;
+			err = bindex;
+			AuDbg("b%d, %llu\n", err, b);
+		}
+	}
+
+ out_parent:
+	dput(parent);
+ out:
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* policies for copyup */
+
+/* top down parent */
+static int au_wbr_copyup_tdp(struct dentry *dentry)
+{
+	return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
+}
+
+/* bottom up parent */
+static int au_wbr_copyup_bup(struct dentry *dentry)
+{
+	int err;
+	aufs_bindex_t bindex, bstart;
+	struct dentry *parent, *h_parent;
+	struct super_block *sb;
+
+	err = -EROFS;
+	sb = dentry->d_sb;
+	parent = dget_parent(dentry);
+	bstart = au_dbstart(parent);
+	for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
+		h_parent = au_h_dptr(parent, bindex);
+		if (!h_parent || !h_parent->d_inode)
+			continue;
+
+		if (!au_br_rdonly(au_sbr(sb, bindex))) {
+			err = bindex;
+			break;
+		}
+	}
+	dput(parent);
+
+	/* bottom up here */
+	if (unlikely(err < 0))
+		err = au_wbr_bu(sb, bstart - 1);
+
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+/* bottom up */
+static int au_wbr_copyup_bu(struct dentry *dentry)
+{
+	int err;
+
+	err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
+
+	AuDbg("b%d\n", err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
+	[AuWbrCopyup_TDP] = {
+		.copyup	= au_wbr_copyup_tdp
+	},
+	[AuWbrCopyup_BUP] = {
+		.copyup	= au_wbr_copyup_bup
+	},
+	[AuWbrCopyup_BU] = {
+		.copyup	= au_wbr_copyup_bu
+	}
+};
+
+struct au_wbr_create_operations au_wbr_create_ops[] = {
+	[AuWbrCreate_TDP] = {
+		.create	= au_wbr_create_tdp
+	},
+	[AuWbrCreate_RR] = {
+		.create	= au_wbr_create_rr,
+		.init	= au_wbr_create_init_rr
+	},
+	[AuWbrCreate_MFS] = {
+		.create	= au_wbr_create_mfs,
+		.init	= au_wbr_create_init_mfs,
+		.fin	= au_wbr_create_fin_mfs
+	},
+	[AuWbrCreate_MFSV] = {
+		.create	= au_wbr_create_mfs,
+		.init	= au_wbr_create_init_mfs,
+		.fin	= au_wbr_create_fin_mfs
+	},
+	[AuWbrCreate_MFSRR] = {
+		.create	= au_wbr_create_mfsrr,
+		.init	= au_wbr_create_init_mfsrr,
+		.fin	= au_wbr_create_fin_mfs
+	},
+	[AuWbrCreate_MFSRRV] = {
+		.create	= au_wbr_create_mfsrr,
+		.init	= au_wbr_create_init_mfsrr,
+		.fin	= au_wbr_create_fin_mfs
+	},
+	[AuWbrCreate_PMFS] = {
+		.create	= au_wbr_create_pmfs,
+		.init	= au_wbr_create_init_mfs,
+		.fin	= au_wbr_create_fin_mfs
+	},
+	[AuWbrCreate_PMFSV] = {
+		.create	= au_wbr_create_pmfs,
+		.init	= au_wbr_create_init_mfs,
+		.fin	= au_wbr_create_fin_mfs
+	}
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/debug.c
+++ linux-ec2-2.6.32/ubuntu/aufs/debug.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * debug print functions
+ */
+
+#include <linux/module.h>
+#include <linux/vt_kern.h>
+#include "aufs.h"
+
+int aufs_debug;
+MODULE_PARM_DESC(debug, "debug print");
+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+char *au_plevel = KERN_DEBUG;
+#define dpri(fmt, ...) do { \
+	if (au_debug_test()) \
+		printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+
+void au_dpri_whlist(struct au_nhash *whlist)
+{
+	unsigned long ul, n;
+	struct hlist_head *head;
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos;
+
+	n = whlist->nh_num;
+	head = whlist->nh_head;
+	for (ul = 0; ul < n; ul++) {
+		hlist_for_each_entry(tpos, pos, head, wh_hash)
+			dpri("b%d, %.*s, %d\n",
+			     tpos->wh_bindex,
+			     tpos->wh_str.len, tpos->wh_str.name,
+			     tpos->wh_str.len);
+		head++;
+	}
+}
+
+void au_dpri_vdir(struct au_vdir *vdir)
+{
+	unsigned long ul;
+	union au_vdir_deblk_p p;
+	unsigned char *o;
+
+	if (!vdir || IS_ERR(vdir)) {
+		dpri("err %ld\n", PTR_ERR(vdir));
+		return;
+	}
+
+	dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
+	     vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
+	     vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
+	for (ul = 0; ul < vdir->vd_nblk; ul++) {
+		p.deblk = vdir->vd_deblk[ul];
+		o = p.deblk;
+		dpri("[%lu]: %p\n", ul, o);
+	}
+}
+
+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
+			struct dentry *wh)
+{
+	char *n = NULL;
+	int l = 0;
+
+	if (!inode || IS_ERR(inode)) {
+		dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
+		return -1;
+	}
+
+	/* the type of i_blocks depends upon CONFIG_LSF */
+	BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
+		     && sizeof(inode->i_blocks) != sizeof(u64));
+	if (wh) {
+		n = (void *)wh->d_name.name;
+		l = wh->d_name.len;
+	}
+
+	dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
+	     " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
+	     bindex,
+	     inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
+	     atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
+	     i_size_read(inode), (unsigned long long)inode->i_blocks,
+	     (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
+	     inode->i_mapping ? inode->i_mapping->nrpages : 0,
+	     inode->i_state, inode->i_flags, inode->i_generation,
+	     l ? ", wh " : "", l, n);
+	return 0;
+}
+
+void au_dpri_inode(struct inode *inode)
+{
+	struct au_iinfo *iinfo;
+	aufs_bindex_t bindex;
+	int err;
+
+	err = do_pri_inode(-1, inode, NULL);
+	if (err || !au_test_aufs(inode->i_sb))
+		return;
+
+	iinfo = au_ii(inode);
+	if (!iinfo)
+		return;
+	dpri("i-1: bstart %d, bend %d, gen %d\n",
+	     iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
+	if (iinfo->ii_bstart < 0)
+		return;
+	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
+		do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
+			     iinfo->ii_hinode[0 + bindex].hi_whdentry);
+}
+
+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
+{
+	struct dentry *wh = NULL;
+
+	if (!dentry || IS_ERR(dentry)) {
+		dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
+		return -1;
+	}
+	/* do not call dget_parent() here */
+	dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
+	     bindex,
+	     AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
+	     dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
+	     atomic_read(&dentry->d_count), dentry->d_flags);
+	if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
+		struct au_iinfo *iinfo = au_ii(dentry->d_inode);
+		if (iinfo)
+			wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
+	}
+	do_pri_inode(bindex, dentry->d_inode, wh);
+	return 0;
+}
+
+void au_dpri_dentry(struct dentry *dentry)
+{
+	struct au_dinfo *dinfo;
+	aufs_bindex_t bindex;
+	int err;
+
+	err = do_pri_dentry(-1, dentry);
+	if (err || !au_test_aufs(dentry->d_sb))
+		return;
+
+	dinfo = au_di(dentry);
+	if (!dinfo)
+		return;
+	dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
+	     dinfo->di_bstart, dinfo->di_bend,
+	     dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
+	if (dinfo->di_bstart < 0)
+		return;
+	for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
+		do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
+}
+
+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
+{
+	char a[32];
+
+	if (!file || IS_ERR(file)) {
+		dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
+		return -1;
+	}
+	a[0] = 0;
+	if (bindex < 0
+	    && file->f_dentry
+	    && au_test_aufs(file->f_dentry->d_sb)
+	    && au_fi(file))
+		snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
+	dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
+	     bindex, file->f_mode, file->f_flags, (long)file_count(file),
+	     file->f_pos, a);
+	if (file->f_dentry)
+		do_pri_dentry(bindex, file->f_dentry);
+	return 0;
+}
+
+void au_dpri_file(struct file *file)
+{
+	struct au_finfo *finfo;
+	aufs_bindex_t bindex;
+	int err;
+
+	err = do_pri_file(-1, file);
+	if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
+		return;
+
+	finfo = au_fi(file);
+	if (!finfo)
+		return;
+	if (finfo->fi_bstart < 0)
+		return;
+	for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
+		struct au_hfile *hf;
+
+		hf = finfo->fi_hfile + bindex;
+		do_pri_file(bindex, hf ? hf->hf_file : NULL);
+	}
+}
+
+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
+{
+	struct vfsmount *mnt;
+	struct super_block *sb;
+
+	if (!br || IS_ERR(br))
+		goto out;
+	mnt = br->br_mnt;
+	if (!mnt || IS_ERR(mnt))
+		goto out;
+	sb = mnt->mnt_sb;
+	if (!sb || IS_ERR(sb))
+		goto out;
+
+	dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
+	     "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
+	     "xino %d\n",
+	     bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
+	     au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
+	     sb->s_flags, sb->s_count - S_BIAS,
+	     atomic_read(&sb->s_active), !!br->br_xino.xi_file);
+	return 0;
+
+ out:
+	dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
+	return -1;
+}
+
+void au_dpri_sb(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+	aufs_bindex_t bindex;
+	int err;
+	/* to reuduce stack size */
+	struct {
+		struct vfsmount mnt;
+		struct au_branch fake;
+	} *a;
+
+	/* this function can be called from magic sysrq */
+	a = kzalloc(sizeof(*a), GFP_ATOMIC);
+	if (unlikely(!a)) {
+		dpri("no memory\n");
+		return;
+	}
+
+	a->mnt.mnt_sb = sb;
+	a->fake.br_perm = 0;
+	a->fake.br_mnt = &a->mnt;
+	a->fake.br_xino.xi_file = NULL;
+	atomic_set(&a->fake.br_count, 0);
+	smp_mb(); /* atomic_set */
+	err = do_pri_br(-1, &a->fake);
+	kfree(a);
+	dpri("dev 0x%x\n", sb->s_dev);
+	if (err || !au_test_aufs(sb))
+		return;
+
+	sbinfo = au_sbi(sb);
+	if (!sbinfo)
+		return;
+	dpri("nw %d, gen %u, kobj %d\n",
+	     atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
+	     atomic_read(&sbinfo->si_kobj.kref.refcount));
+	for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
+		do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_dbg_sleep_jiffy(int jiffy)
+{
+	while (jiffy)
+		jiffy = schedule_timeout_uninterruptible(jiffy);
+}
+
+void au_dbg_iattr(struct iattr *ia)
+{
+#define AuBit(name)	if (ia->ia_valid & ATTR_ ## name) \
+				dpri(#name "\n")
+	AuBit(MODE);
+	AuBit(UID);
+	AuBit(GID);
+	AuBit(SIZE);
+	AuBit(ATIME);
+	AuBit(MTIME);
+	AuBit(CTIME);
+	AuBit(ATIME_SET);
+	AuBit(MTIME_SET);
+	AuBit(FORCE);
+	AuBit(ATTR_FLAG);
+	AuBit(KILL_SUID);
+	AuBit(KILL_SGID);
+	AuBit(FILE);
+	AuBit(KILL_PRIV);
+	AuBit(OPEN);
+	AuBit(TIMES_SET);
+#undef	AuBit
+	dpri("ia_file %p\n", ia->ia_file);
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
+{
+	struct dentry *parent;
+
+	parent = dget_parent(dentry);
+	AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
+		  || IS_ROOT(dentry)
+		  || au_digen(parent) != sigen);
+	dput(parent);
+}
+
+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
+{
+	struct dentry *parent;
+
+	parent = dget_parent(dentry);
+	AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
+		  || au_digen(parent) != sigen);
+	dput(parent);
+}
+
+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
+{
+	int err, i, j;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+
+	err = au_dpages_init(&dpages, GFP_NOFS);
+	AuDebugOn(err);
+	err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
+	AuDebugOn(err);
+	for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		for (j = dpage->ndentry - 1; !err && j >= 0; j--)
+			AuDebugOn(au_digen(dentries[j]) != sigen);
+	}
+	au_dpages_free(&dpages);
+}
+
+void au_dbg_verify_hf(struct au_finfo *finfo)
+{
+	struct au_hfile *hf;
+	aufs_bindex_t bend, bindex;
+
+	if (finfo->fi_bstart >= 0) {
+		bend = finfo->fi_bend;
+		for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
+			hf = finfo->fi_hfile + bindex;
+			AuDebugOn(hf->hf_file || hf->hf_br);
+		}
+	}
+}
+
+void au_dbg_verify_kthread(void)
+{
+	if (au_test_wkq(current)) {
+		au_dbg_blocked();
+		BUG();
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
+{
+#ifdef AuForceNoPlink
+	au_opt_clr(sbinfo->si_mntflags, PLINK);
+#endif
+#ifdef AuForceNoXino
+	au_opt_clr(sbinfo->si_mntflags, XINO);
+#endif
+#ifdef AuForceNoRefrof
+	au_opt_clr(sbinfo->si_mntflags, REFROF);
+#endif
+#ifdef AuForceHinotify
+	au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
+#endif
+#ifdef AuForceRd0
+	sbinfo->si_rdblk = 0;
+	sbinfo->si_rdhash = 0;
+#endif
+}
+
+int __init au_debug_init(void)
+{
+	aufs_bindex_t bindex;
+	struct au_vdir_destr destr;
+
+	bindex = -1;
+	AuDebugOn(bindex >= 0);
+
+	destr.len = -1;
+	AuDebugOn(destr.len < NAME_MAX);
+
+#ifdef CONFIG_4KSTACKS
+	pr_warning("CONFIG_4KSTACKS is defined.\n");
+#endif
+
+#ifdef AuForceNoBrs
+	sysaufs_brs = 0;
+#endif
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/Kconfig
+++ linux-ec2-2.6.32/ubuntu/aufs/Kconfig
@@ -0,0 +1,140 @@
+config AUFS_FS
+	tristate "Aufs (Advanced multi layered unification filesystem) support"
+	depends on EXPERIMENTAL
+	help
+	Aufs is a stackable unification filesystem such as Unionfs,
+	which unifies several directories and provides a merged single
+	directory.
+	In the early days, aufs was entirely re-designed and
+	re-implemented Unionfs Version 1.x series. Introducing many
+	original ideas, approaches and improvements, it becomes totally
+	different from Unionfs while keeping the basic features.
+
+if AUFS_FS
+choice
+	prompt "Maximum number of branches"
+	default AUFS_BRANCH_MAX_127
+	help
+	Specifies the maximum number of branches (or member directories)
+	in a single aufs. The larger value consumes more system
+	resources and has a minor impact to performance.
+config AUFS_BRANCH_MAX_127
+	bool "127"
+	help
+	Specifies the maximum number of branches (or member directories)
+	in a single aufs. The larger value consumes more system
+	resources and has a minor impact to performance.
+config AUFS_BRANCH_MAX_511
+	bool "511"
+	help
+	Specifies the maximum number of branches (or member directories)
+	in a single aufs. The larger value consumes more system
+	resources and has a minor impact to performance.
+config AUFS_BRANCH_MAX_1023
+	bool "1023"
+	help
+	Specifies the maximum number of branches (or member directories)
+	in a single aufs. The larger value consumes more system
+	resources and has a minor impact to performance.
+config AUFS_BRANCH_MAX_32767
+	bool "32767"
+	help
+	Specifies the maximum number of branches (or member directories)
+	in a single aufs. The larger value consumes more system
+	resources and has a minor impact to performance.
+endchoice
+
+config AUFS_HINOTIFY
+	bool "Use inotify to detect actions on a branch"
+	depends on INOTIFY
+	help
+	If you want to modify files on branches directly, eg. bypassing aufs,
+	and want aufs to detect the changes of them fully, then enable this
+	option and use 'udba=inotify' mount option.
+	It will have a negative impact to the performance.
+	See detail in aufs.5.
+
+config AUFS_EXPORT
+	bool "NFS-exportable aufs"
+	depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
+	help
+	If you want to export your mounted aufs via NFS, then enable this
+	option. There are several requirements for this configuration.
+	See detail in aufs.5.
+
+config AUFS_INO_T_64
+	bool
+	depends on AUFS_EXPORT
+	depends on 64BIT && !(ALPHA || S390)
+	default y
+	help
+	Automatic configuration for internal use.
+	/* typedef unsigned long/int __kernel_ino_t */
+	/* alpha and s390x are int */
+
+config AUFS_RDU
+	bool "Readdir in userspace"
+	help
+	If you have millions of files under a single aufs directory, and
+	meet the out of memory, then enable this option and set
+	environment variables for your readdir(3).
+	See detail in aufs.5.
+
+config AUFS_SHWH
+	bool "Show whiteouts"
+	help
+	If you want to make the whiteouts in aufs visible, then enable
+	this option and specify 'shwh' mount option. Although it may
+	sounds like philosophy or something, but in technically it
+	simply shows the name of whiteout with keeping its behaviour.
+
+config AUFS_BR_RAMFS
+	bool "Ramfs (initramfs/rootfs) as an aufs branch"
+	help
+	If you want to use ramfs as an aufs branch fs, then enable this
+	option. Generally tmpfs is recommended.
+	Aufs prohibited them to be a branch fs by default, because
+	initramfs becomes unusable after switch_root or something
+	generally. If you sets initramfs as an aufs branch and boot your
+	system by switch_root, you will meet a problem easily since the
+	files in initramfs may be inaccessible.
+	Unless you are going to use ramfs as an aufs branch fs without
+	switch_root or something, leave it N.
+
+config AUFS_BR_FUSE
+	bool "Fuse fs as an aufs branch"
+	depends on FUSE_FS
+	select AUFS_POLL
+	help
+	If you want to use fuse-based userspace filesystem as an aufs
+	branch fs, then enable this option.
+	It implements the internal poll(2) operation which is
+	implemented by fuse only (curretnly).
+
+config AUFS_POLL
+	bool
+	help
+	Automatic configuration for internal use.
+
+config AUFS_BDEV_LOOP
+	bool
+	depends on BLK_DEV_LOOP
+	default y
+	help
+	Automatic configuration for internal use.
+	Convert =[ym] into =y.
+
+config AUFS_DEBUG
+	bool "Debug aufs"
+	help
+	Enable this to compile aufs internal debug code.
+	It will have a negative impact to the performance.
+
+config AUFS_MAGIC_SYSRQ
+	bool
+	depends on AUFS_DEBUG && MAGIC_SYSRQ
+	default y
+	help
+	Automatic configuration for internal use.
+	When aufs supports Magic SysRq, enabled automatically.
+endif
--- linux-ec2-2.6.32.orig/ubuntu/aufs/debug.h
+++ linux-ec2-2.6.32/ubuntu/aufs/debug.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * debug print functions
+ */
+
+#ifndef __AUFS_DEBUG_H__
+#define __AUFS_DEBUG_H__
+
+#ifdef __KERNEL__
+
+#include <asm/system.h>
+#include <linux/bug.h>
+/* #include <linux/err.h> */
+#include <linux/init.h>
+/* #include <linux/kernel.h> */
+#include <linux/delay.h>
+/* #include <linux/kd.h> */
+/* #include <linux/vt_kern.h> */
+#include <linux/sysrq.h>
+#include <linux/aufs_type.h>
+
+#include <asm/system.h>
+
+#ifdef CONFIG_AUFS_DEBUG
+#define AuDebugOn(a)		BUG_ON(a)
+
+/* module parameter */
+extern int aufs_debug;
+static inline void au_debug(int n)
+{
+	aufs_debug = n;
+	smp_mb();
+}
+
+static inline int au_debug_test(void)
+{
+	return aufs_debug;
+}
+#else
+#define AuDebugOn(a)		do {} while (0)
+#define au_debug()		do {} while (0)
+static inline int au_debug_test(void)
+{
+	return 0;
+}
+#endif /* CONFIG_AUFS_DEBUG */
+
+/* ---------------------------------------------------------------------- */
+
+/* debug print */
+
+#define AuDbg(fmt, ...) do { \
+	if (au_debug_test()) \
+		pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
+} while (0)
+#define AuLabel(l) 		AuDbg(#l "\n")
+#define AuIOErr(fmt, ...)	pr_err("I/O Error, " fmt, ##__VA_ARGS__)
+#define AuWarn1(fmt, ...) do { \
+	static unsigned char _c; \
+	if (!_c++) \
+		pr_warning(fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define AuErr1(fmt, ...) do { \
+	static unsigned char _c; \
+	if (!_c++) \
+		pr_err(fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define AuIOErr1(fmt, ...) do { \
+	static unsigned char _c; \
+	if (!_c++) \
+		AuIOErr(fmt, ##__VA_ARGS__); \
+} while (0)
+
+#define AuUnsupportMsg	"This operation is not supported." \
+			" Please report this application to aufs-users ML."
+#define AuUnsupport(fmt, ...) do { \
+	pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
+	dump_stack(); \
+} while (0)
+
+#define AuTraceErr(e) do { \
+	if (unlikely((e) < 0)) \
+		AuDbg("err %d\n", (int)(e)); \
+} while (0)
+
+#define AuTraceErrPtr(p) do { \
+	if (IS_ERR(p)) \
+		AuDbg("err %ld\n", PTR_ERR(p)); \
+} while (0)
+
+/* dirty macros for debug print, use with "%.*s" and caution */
+#define AuLNPair(qstr)		(qstr)->len, (qstr)->name
+#define AuDLNPair(d)		AuLNPair(&(d)->d_name)
+
+/* ---------------------------------------------------------------------- */
+
+struct au_sbinfo;
+struct au_finfo;
+struct dentry;
+#ifdef CONFIG_AUFS_DEBUG
+extern char *au_plevel;
+struct au_nhash;
+void au_dpri_whlist(struct au_nhash *whlist);
+struct au_vdir;
+void au_dpri_vdir(struct au_vdir *vdir);
+struct inode;
+void au_dpri_inode(struct inode *inode);
+void au_dpri_dentry(struct dentry *dentry);
+struct file;
+void au_dpri_file(struct file *filp);
+struct super_block;
+void au_dpri_sb(struct super_block *sb);
+
+void au_dbg_sleep_jiffy(int jiffy);
+struct iattr;
+void au_dbg_iattr(struct iattr *ia);
+
+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
+void au_dbg_verify_hf(struct au_finfo *finfo);
+void au_dbg_verify_kthread(void);
+
+int __init au_debug_init(void);
+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
+#define AuDbgWhlist(w) do { \
+	AuDbg(#w "\n"); \
+	au_dpri_whlist(w); \
+} while (0)
+
+#define AuDbgVdir(v) do { \
+	AuDbg(#v "\n"); \
+	au_dpri_vdir(v); \
+} while (0)
+
+#define AuDbgInode(i) do { \
+	AuDbg(#i "\n"); \
+	au_dpri_inode(i); \
+} while (0)
+
+#define AuDbgDentry(d) do { \
+	AuDbg(#d "\n"); \
+	au_dpri_dentry(d); \
+} while (0)
+
+#define AuDbgFile(f) do { \
+	AuDbg(#f "\n"); \
+	au_dpri_file(f); \
+} while (0)
+
+#define AuDbgSb(sb) do { \
+	AuDbg(#sb "\n"); \
+	au_dpri_sb(sb); \
+} while (0)
+
+#define AuDbgSleep(sec) do { \
+	AuDbg("sleep %d sec\n", sec); \
+	ssleep(sec); \
+} while (0)
+
+#define AuDbgSleepJiffy(jiffy) do { \
+	AuDbg("sleep %d jiffies\n", jiffy); \
+	au_dbg_sleep_jiffy(jiffy); \
+} while (0)
+
+#define AuDbgIAttr(ia) do { \
+	AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
+	au_dbg_iattr(ia); \
+} while (0)
+#else
+static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
+					    unsigned int sigen)
+{
+	/* empty */
+}
+static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
+					       unsigned int sigen)
+{
+	/* empty */
+}
+static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
+{
+	/* empty */
+}
+static inline void au_dbg_verify_hf(struct au_finfo *finfo)
+{
+	/* empty */
+}
+static inline void au_dbg_verify_kthread(void)
+{
+	/* empty */
+}
+
+static inline int au_debug_init(void)
+{
+	return 0;
+}
+static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
+{
+	/* empty */
+}
+#define AuDbgWhlist(w)		do {} while (0)
+#define AuDbgVdir(v)		do {} while (0)
+#define AuDbgInode(i)		do {} while (0)
+#define AuDbgDentry(d)		do {} while (0)
+#define AuDbgFile(f)		do {} while (0)
+#define AuDbgSb(sb)		do {} while (0)
+#define AuDbgSleep(sec)		do {} while (0)
+#define AuDbgSleepJiffy(jiffy)	do {} while (0)
+#define AuDbgIAttr(ia)		do {} while (0)
+#endif /* CONFIG_AUFS_DEBUG */
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
+int __init au_sysrq_init(void);
+void au_sysrq_fin(void);
+
+#ifdef CONFIG_HW_CONSOLE
+#define au_dbg_blocked() do { \
+	WARN_ON(1); \
+	handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
+} while (0)
+#else
+#define au_dbg_blocked()	do {} while (0)
+#endif
+
+#else
+static inline int au_sysrq_init(void)
+{
+	return 0;
+}
+#define au_sysrq_fin()		do {} while (0)
+#define au_dbg_blocked()	do {} while (0)
+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DEBUG_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/cpup.h
+++ linux-ec2-2.6.32/ubuntu/aufs/cpup.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * copy-up/down functions
+ */
+
+#ifndef __AUFS_CPUP_H__
+#define __AUFS_CPUP_H__
+
+#ifdef __KERNEL__
+
+#include <linux/path.h>
+#include <linux/time.h>
+#include <linux/aufs_type.h>
+
+struct inode;
+struct file;
+
+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
+void au_cpup_attr_timesizes(struct inode *inode);
+void au_cpup_attr_nlink(struct inode *inode, int force);
+void au_cpup_attr_changeable(struct inode *inode);
+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
+void au_cpup_attr_all(struct inode *inode, int force);
+
+/* ---------------------------------------------------------------------- */
+
+/* cpup flags */
+#define AuCpup_DTIME	1		/* do dtime_store/revert */
+#define AuCpup_KEEPLINO	(1 << 1)	/* do not clear the lower xino,
+					   for link(2) */
+#define au_ftest_cpup(flags, name)	((flags) & AuCpup_##name)
+#define au_fset_cpup(flags, name)	{ (flags) |= AuCpup_##name; }
+#define au_fclr_cpup(flags, name)	{ (flags) &= ~AuCpup_##name; }
+
+int au_copy_file(struct file *dst, struct file *src, loff_t len);
+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
+		       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
+		       struct dentry *dst_parent);
+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+		       unsigned int flags);
+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
+		   struct file *file);
+
+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
+	       int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
+			 struct dentry *h_parent, void *arg),
+	       void *arg);
+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
+
+/* ---------------------------------------------------------------------- */
+
+/* keep timestamps when copyup */
+struct au_dtime {
+	struct dentry *dt_dentry;
+	struct path dt_h_path;
+	struct timespec dt_atime, dt_mtime;
+};
+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
+		    struct path *h_path);
+void au_dtime_revert(struct au_dtime *dt);
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_CPUP_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dir.h
+++ linux-ec2-2.6.32/ubuntu/aufs/dir.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * directory operations
+ */
+
+#ifndef __AUFS_DIR_H__
+#define __AUFS_DIR_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/aufs_type.h>
+
+/* ---------------------------------------------------------------------- */
+
+/* need to be faster and smaller */
+
+struct au_nhash {
+	unsigned int		nh_num;
+	struct hlist_head	*nh_head;
+};
+
+struct au_vdir_destr {
+	unsigned char	len;
+	unsigned char	name[0];
+} __packed;
+
+struct au_vdir_dehstr {
+	struct hlist_node	hash;
+	struct au_vdir_destr	*str;
+};
+
+struct au_vdir_de {
+	ino_t			de_ino;
+	unsigned char		de_type;
+	/* caution: packed */
+	struct au_vdir_destr	de_str;
+} __packed;
+
+struct au_vdir_wh {
+	struct hlist_node	wh_hash;
+#ifdef CONFIG_AUFS_SHWH
+	ino_t			wh_ino;
+	aufs_bindex_t		wh_bindex;
+	unsigned char		wh_type;
+#else
+	aufs_bindex_t		wh_bindex;
+#endif
+	/* caution: packed */
+	struct au_vdir_destr	wh_str;
+} __packed;
+
+union au_vdir_deblk_p {
+	unsigned char		*deblk;
+	struct au_vdir_de	*de;
+};
+
+struct au_vdir {
+	unsigned char	**vd_deblk;
+	unsigned long	vd_nblk;
+	struct {
+		unsigned long		ul;
+		union au_vdir_deblk_p	p;
+	} vd_last;
+
+	unsigned long	vd_version;
+	unsigned int	vd_deblk_sz;
+	unsigned long	vd_jiffy;
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* dir.c */
+extern const struct file_operations aufs_dir_fop;
+void au_add_nlink(struct inode *dir, struct inode *h_dir);
+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
+loff_t au_dir_size(struct file *file, struct dentry *dentry);
+int au_test_empty_lower(struct dentry *dentry);
+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
+
+/* vdir.c */
+unsigned int au_rdhash_est(loff_t sz);
+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
+void au_nhash_wh_free(struct au_nhash *whlist);
+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
+			    int limit);
+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
+		       unsigned int d_type, aufs_bindex_t bindex,
+		       unsigned char shwh);
+void au_vdir_free(struct au_vdir *vdir);
+int au_vdir_init(struct file *file);
+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
+
+/* ioctl.c */
+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
+
+#ifdef CONFIG_AUFS_RDU
+/* rdu.c */
+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_DIR_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/dcsub.c
+++ linux-ec2-2.6.32/ubuntu/aufs/dcsub.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sub-routines for dentry cache
+ */
+
+#include "aufs.h"
+
+static void au_dpage_free(struct au_dpage *dpage)
+{
+	int i;
+	struct dentry **p;
+
+	p = dpage->dentries;
+	for (i = 0; i < dpage->ndentry; i++)
+		dput(*p++);
+	free_page((unsigned long)dpage->dentries);
+}
+
+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
+{
+	int err;
+	void *p;
+
+	err = -ENOMEM;
+	dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
+	if (unlikely(!dpages->dpages))
+		goto out;
+
+	p = (void *)__get_free_page(gfp);
+	if (unlikely(!p))
+		goto out_dpages;
+
+	dpages->dpages[0].ndentry = 0;
+	dpages->dpages[0].dentries = p;
+	dpages->ndpage = 1;
+	return 0; /* success */
+
+ out_dpages:
+	kfree(dpages->dpages);
+ out:
+	return err;
+}
+
+void au_dpages_free(struct au_dcsub_pages *dpages)
+{
+	int i;
+	struct au_dpage *p;
+
+	p = dpages->dpages;
+	for (i = 0; i < dpages->ndpage; i++)
+		au_dpage_free(p++);
+	kfree(dpages->dpages);
+}
+
+static int au_dpages_append(struct au_dcsub_pages *dpages,
+			    struct dentry *dentry, gfp_t gfp)
+{
+	int err, sz;
+	struct au_dpage *dpage;
+	void *p;
+
+	dpage = dpages->dpages + dpages->ndpage - 1;
+	sz = PAGE_SIZE / sizeof(dentry);
+	if (unlikely(dpage->ndentry >= sz)) {
+		AuLabel(new dpage);
+		err = -ENOMEM;
+		sz = dpages->ndpage * sizeof(*dpages->dpages);
+		p = au_kzrealloc(dpages->dpages, sz,
+				 sz + sizeof(*dpages->dpages), gfp);
+		if (unlikely(!p))
+			goto out;
+
+		dpages->dpages = p;
+		dpage = dpages->dpages + dpages->ndpage;
+		p = (void *)__get_free_page(gfp);
+		if (unlikely(!p))
+			goto out;
+
+		dpage->ndentry = 0;
+		dpage->dentries = p;
+		dpages->ndpage++;
+	}
+
+	dpage->dentries[dpage->ndentry++] = dget(dentry);
+	return 0; /* success */
+
+ out:
+	return err;
+}
+
+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
+		   au_dpages_test test, void *arg)
+{
+	int err;
+	struct dentry *this_parent = root;
+	struct list_head *next;
+	struct super_block *sb = root->d_sb;
+
+	err = 0;
+	spin_lock(&dcache_lock);
+ repeat:
+	next = this_parent->d_subdirs.next;
+ resume:
+	if (this_parent->d_sb == sb
+	    && !IS_ROOT(this_parent)
+	    && atomic_read(&this_parent->d_count)
+	    && this_parent->d_inode
+	    && (!test || test(this_parent, arg))) {
+		err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
+		if (unlikely(err))
+			goto out;
+	}
+
+	while (next != &this_parent->d_subdirs) {
+		struct list_head *tmp = next;
+		struct dentry *dentry = list_entry(tmp, struct dentry,
+						   d_u.d_child);
+		next = tmp->next;
+		if (/*d_unhashed(dentry) || */!dentry->d_inode)
+			continue;
+		if (!list_empty(&dentry->d_subdirs)) {
+			this_parent = dentry;
+			goto repeat;
+		}
+		if (dentry->d_sb == sb
+		    && atomic_read(&dentry->d_count)
+		    && (!test || test(dentry, arg))) {
+			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
+			if (unlikely(err))
+				goto out;
+		}
+	}
+
+	if (this_parent != root) {
+		next = this_parent->d_u.d_child.next;
+		this_parent = this_parent->d_parent; /* dcache_lock is locked */
+		goto resume;
+	}
+ out:
+	spin_unlock(&dcache_lock);
+	return err;
+}
+
+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
+		       int do_include, au_dpages_test test, void *arg)
+{
+	int err;
+
+	err = 0;
+	spin_lock(&dcache_lock);
+	if (do_include && (!test || test(dentry, arg))) {
+		err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
+		if (unlikely(err))
+			goto out;
+	}
+	while (!IS_ROOT(dentry)) {
+		dentry = dentry->d_parent; /* dcache_lock is locked */
+		if (!test || test(dentry, arg)) {
+			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
+			if (unlikely(err))
+				break;
+		}
+	}
+
+ out:
+	spin_unlock(&dcache_lock);
+
+	return err;
+}
+
+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
+{
+	struct dentry *trap, **dentries;
+	int err, i, j;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+
+	trap = ERR_PTR(-ENOMEM);
+	err = au_dpages_init(&dpages, GFP_NOFS);
+	if (unlikely(err))
+		goto out;
+	err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
+	if (unlikely(err))
+		goto out_dpages;
+
+	trap = d1;
+	for (i = 0; !err && i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		for (j = 0; !err && j < dpage->ndentry; j++) {
+			struct dentry *d;
+
+			d = dentries[j];
+			err = (d == d2);
+			if (!err)
+				trap = d;
+		}
+	}
+	if (!err)
+		trap = NULL;
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	return trap;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/sysaufs.h
+++ linux-ec2-2.6.32/ubuntu/aufs/sysaufs.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sysfs interface and mount lifetime management
+ */
+
+#ifndef __SYSAUFS_H__
+#define __SYSAUFS_H__
+
+#ifdef __KERNEL__
+
+#include <linux/sysfs.h>
+#include <linux/aufs_type.h>
+#include "module.h"
+
+struct super_block;
+struct au_sbinfo;
+
+struct sysaufs_si_attr {
+	struct attribute attr;
+	int (*show)(struct seq_file *seq, struct super_block *sb);
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* sysaufs.c */
+extern unsigned long sysaufs_si_mask;
+extern struct kset *sysaufs_ket;
+extern struct attribute *sysaufs_si_attrs[];
+int sysaufs_si_init(struct au_sbinfo *sbinfo);
+int __init sysaufs_init(void);
+void sysaufs_fin(void);
+
+/* ---------------------------------------------------------------------- */
+
+/* some people doesn't like to show a pointer in kernel */
+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
+{
+	return sysaufs_si_mask ^ (unsigned long)sbinfo;
+}
+
+#define SysaufsSiNamePrefix	"si_"
+#define SysaufsSiNameLen	(sizeof(SysaufsSiNamePrefix) + 16)
+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
+{
+	snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
+		 sysaufs_si_id(sbinfo));
+}
+
+struct au_branch;
+#ifdef CONFIG_SYSFS
+/* sysfs.c */
+extern struct attribute_group *sysaufs_attr_group;
+
+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
+			 char *buf);
+
+void sysaufs_br_init(struct au_branch *br);
+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
+
+#define sysaufs_brs_init()	do {} while (0)
+
+#else
+#define sysaufs_attr_group	NULL
+
+static inline
+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
+{
+	return 0;
+}
+
+static inline
+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
+			 char *buf)
+{
+	return 0;
+}
+
+static inline void sysaufs_br_init(struct au_branch *br)
+{
+	/* empty */
+}
+
+static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
+{
+	/* nothing */
+}
+
+static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
+{
+	/* nothing */
+}
+
+static inline void sysaufs_brs_init(void)
+{
+	sysaufs_brs = 0;
+}
+
+#endif /* CONFIG_SYSFS */
+
+#endif /* __KERNEL__ */
+#endif /* __SYSAUFS_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/i_op.c
+++ linux-ec2-2.6.32/ubuntu/aufs/i_op.c
@@ -0,0 +1,886 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode operations (except add/del/rename)
+ */
+
+#include <linux/device_cgroup.h>
+#include <linux/fs_stack.h>
+#include <linux/mm.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+#include <linux/uaccess.h>
+#include "aufs.h"
+
+static int h_permission(struct inode *h_inode, int mask,
+			struct vfsmount *h_mnt, int brperm)
+{
+	int err;
+	const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
+
+	err = -EACCES;
+	if ((write_mask && IS_IMMUTABLE(h_inode))
+	    || ((mask & MAY_EXEC)
+		&& S_ISREG(h_inode->i_mode)
+		&& ((h_mnt->mnt_flags & MNT_NOEXEC)
+		    || !(h_inode->i_mode & S_IXUGO))))
+		goto out;
+
+	/*
+	 * - skip the lower fs test in the case of write to ro branch.
+	 * - nfs dir permission write check is optimized, but a policy for
+	 *   link/rename requires a real check.
+	 */
+	if ((write_mask && !au_br_writable(brperm))
+	    || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
+		&& write_mask && !(mask & MAY_READ))
+	    || !h_inode->i_op->permission) {
+		/* AuLabel(generic_permission); */
+		err = generic_permission(h_inode, mask, NULL);
+	} else {
+		/* AuLabel(h_inode->permission); */
+		err = h_inode->i_op->permission(h_inode, mask);
+		AuTraceErr(err);
+	}
+
+	if (!err)
+		err = devcgroup_inode_permission(h_inode, mask);
+	if (!err)
+		err = security_inode_permission
+			(h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
+					  | MAY_APPEND));
+
+#if 0
+	if (!err) {
+		/* todo: do we need to call ima_path_check()? */
+		struct path h_path = {
+			.dentry	=
+			.mnt	= h_mnt
+		};
+		err = ima_path_check(&h_path,
+				     mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
+				     IMA_COUNT_LEAVE);
+	}
+#endif
+
+ out:
+	return err;
+}
+
+static int aufs_permission(struct inode *inode, int mask)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	const unsigned char isdir = !!S_ISDIR(inode->i_mode);
+	const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
+	struct inode *h_inode;
+	struct super_block *sb;
+	struct au_branch *br;
+
+	sb = inode->i_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	ii_read_lock_child(inode);
+
+	if (!isdir || write_mask) {
+		err = au_busy_or_stale();
+		h_inode = au_h_iptr(inode, au_ibstart(inode));
+		if (unlikely(!h_inode
+			     || (h_inode->i_mode & S_IFMT)
+			     != (inode->i_mode & S_IFMT)))
+			goto out;
+
+		err = 0;
+		bindex = au_ibstart(inode);
+		br = au_sbr(sb, bindex);
+		err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
+		if (write_mask && !err) {
+			/* test whether the upper writable branch exists */
+			err = -EROFS;
+			for (; bindex >= 0; bindex--)
+				if (!au_br_rdonly(au_sbr(sb, bindex))) {
+					err = 0;
+					break;
+				}
+		}
+		goto out;
+	}
+
+	/* non-write to dir */
+	err = 0;
+	bend = au_ibend(inode);
+	for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
+		h_inode = au_h_iptr(inode, bindex);
+		if (h_inode) {
+			err = au_busy_or_stale();
+			if (unlikely(!S_ISDIR(h_inode->i_mode)))
+				break;
+
+			br = au_sbr(sb, bindex);
+			err = h_permission(h_inode, mask, br->br_mnt,
+					   br->br_perm);
+		}
+	}
+
+ out:
+	ii_read_unlock(inode);
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
+				  struct nameidata *nd)
+{
+	struct dentry *ret, *parent;
+	struct inode *inode, *h_inode;
+	struct mutex *mtx;
+	struct super_block *sb;
+	int err, npositive;
+	aufs_bindex_t bstart;
+
+	IMustLock(dir);
+
+	sb = dir->i_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	ret = ERR_PTR(-ENAMETOOLONG);
+	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
+		goto out;
+	err = au_alloc_dinfo(dentry);
+	ret = ERR_PTR(err);
+	if (unlikely(err))
+		goto out;
+
+	parent = dentry->d_parent; /* dir inode is locked */
+	di_read_lock_parent(parent, AuLock_IR);
+	npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
+	di_read_unlock(parent, AuLock_IR);
+	err = npositive;
+	ret = ERR_PTR(err);
+	if (unlikely(err < 0))
+		goto out_unlock;
+
+	inode = NULL;
+	if (npositive) {
+		bstart = au_dbstart(dentry);
+		h_inode = au_h_dptr(dentry, bstart)->d_inode;
+		if (!S_ISDIR(h_inode->i_mode)) {
+			/*
+			 * stop 'race'-ing between hardlinks under different
+			 * parents.
+			 */
+			mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
+			mutex_lock(mtx);
+			inode = au_new_inode(dentry, /*must_new*/0);
+			mutex_unlock(mtx);
+		} else
+			inode = au_new_inode(dentry, /*must_new*/0);
+		ret = (void *)inode;
+	}
+	if (IS_ERR(inode))
+		goto out_unlock;
+
+	ret = d_splice_alias(inode, dentry);
+	if (unlikely(IS_ERR(ret) && inode))
+		ii_write_unlock(inode);
+
+ out_unlock:
+	di_write_unlock(dentry);
+ out:
+	si_read_unlock(sb);
+	return ret;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
+			  const unsigned char add_entry, aufs_bindex_t bcpup,
+			  aufs_bindex_t bstart)
+{
+	int err;
+	struct dentry *h_parent;
+	struct inode *h_dir;
+
+	if (add_entry) {
+		au_update_dbstart(dentry);
+		IMustLock(parent->d_inode);
+	} else
+		di_write_lock_parent(parent);
+
+	err = 0;
+	if (!au_h_dptr(parent, bcpup)) {
+		if (bstart < bcpup)
+			err = au_cpdown_dirs(dentry, bcpup);
+		else
+			err = au_cpup_dirs(dentry, bcpup);
+	}
+	if (!err && add_entry) {
+		h_parent = au_h_dptr(parent, bcpup);
+		h_dir = h_parent->d_inode;
+		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
+		err = au_lkup_neg(dentry, bcpup);
+		/* todo: no unlock here */
+		mutex_unlock(&h_dir->i_mutex);
+		if (bstart < bcpup && au_dbstart(dentry) < 0) {
+			au_set_dbstart(dentry, 0);
+			au_update_dbrange(dentry, /*do_put_zero*/0);
+		}
+	}
+
+	if (!add_entry)
+		di_write_unlock(parent);
+	if (!err)
+		err = bcpup; /* success */
+
+	return err;
+}
+
+/*
+ * decide the branch and the parent dir where we will create a new entry.
+ * returns new bindex or an error.
+ * copyup the parent dir if needed.
+ */
+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
+	      struct au_wr_dir_args *args)
+{
+	int err;
+	aufs_bindex_t bcpup, bstart, src_bstart;
+	const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
+							 ADD_ENTRY);
+	struct super_block *sb;
+	struct dentry *parent;
+	struct au_sbinfo *sbinfo;
+
+	sb = dentry->d_sb;
+	sbinfo = au_sbi(sb);
+	parent = dget_parent(dentry);
+	bstart = au_dbstart(dentry);
+	bcpup = bstart;
+	if (args->force_btgt < 0) {
+		if (src_dentry) {
+			src_bstart = au_dbstart(src_dentry);
+			if (src_bstart < bstart)
+				bcpup = src_bstart;
+		} else if (add_entry) {
+			err = AuWbrCreate(sbinfo, dentry,
+					  au_ftest_wrdir(args->flags, ISDIR));
+			bcpup = err;
+		}
+
+		if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
+			if (add_entry)
+				err = AuWbrCopyup(sbinfo, dentry);
+			else {
+				if (!IS_ROOT(dentry)) {
+					di_read_lock_parent(parent, !AuLock_IR);
+					err = AuWbrCopyup(sbinfo, dentry);
+					di_read_unlock(parent, !AuLock_IR);
+				} else
+					err = AuWbrCopyup(sbinfo, dentry);
+			}
+			bcpup = err;
+			if (unlikely(err < 0))
+				goto out;
+		}
+	} else {
+		bcpup = args->force_btgt;
+		AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
+	}
+	AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
+	if (bstart < bcpup)
+		au_update_dbrange(dentry, /*do_put_zero*/1);
+
+	err = bcpup;
+	if (bcpup == bstart)
+		goto out; /* success */
+
+	/* copyup the new parent into the branch we process */
+	err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
+
+ out:
+	dput(parent);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct dentry *au_pinned_h_parent(struct au_pin *pin)
+{
+	if (pin && pin->parent)
+		return au_h_dptr(pin->parent, pin->bindex);
+	return NULL;
+}
+
+void au_unpin(struct au_pin *p)
+{
+	if (au_ftest_pin(p->flags, MNT_WRITE))
+		mnt_drop_write(p->h_mnt);
+	if (!p->hdir)
+		return;
+
+	au_hin_imtx_unlock(p->hdir);
+	if (!au_ftest_pin(p->flags, DI_LOCKED))
+		di_read_unlock(p->parent, AuLock_IR);
+	iput(p->hdir->hi_inode);
+	dput(p->parent);
+	p->parent = NULL;
+	p->hdir = NULL;
+	p->h_mnt = NULL;
+}
+
+int au_do_pin(struct au_pin *p)
+{
+	int err;
+	struct super_block *sb;
+	struct dentry *h_dentry, *h_parent;
+	struct au_branch *br;
+	struct inode *h_dir;
+
+	err = 0;
+	sb = p->dentry->d_sb;
+	br = au_sbr(sb, p->bindex);
+	if (IS_ROOT(p->dentry)) {
+		if (au_ftest_pin(p->flags, MNT_WRITE)) {
+			p->h_mnt = br->br_mnt;
+			err = mnt_want_write(p->h_mnt);
+			if (unlikely(err)) {
+				au_fclr_pin(p->flags, MNT_WRITE);
+				goto out_err;
+			}
+		}
+		goto out;
+	}
+
+	h_dentry = NULL;
+	if (p->bindex <= au_dbend(p->dentry))
+		h_dentry = au_h_dptr(p->dentry, p->bindex);
+
+	p->parent = dget_parent(p->dentry);
+	if (!au_ftest_pin(p->flags, DI_LOCKED))
+		di_read_lock(p->parent, AuLock_IR, p->lsc_di);
+
+	h_dir = NULL;
+	h_parent = au_h_dptr(p->parent, p->bindex);
+	p->hdir = au_hi(p->parent->d_inode, p->bindex);
+	if (p->hdir)
+		h_dir = p->hdir->hi_inode;
+
+	/* udba case */
+	if (unlikely(!p->hdir || !h_dir)) {
+		if (!au_ftest_pin(p->flags, DI_LOCKED))
+			di_read_unlock(p->parent, AuLock_IR);
+		dput(p->parent);
+		p->parent = NULL;
+		goto out_err;
+	}
+
+	au_igrab(h_dir);
+	au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
+
+	if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
+		err = -EBUSY;
+		goto out_unpin;
+	}
+	if (h_dentry) {
+		err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
+		if (unlikely(err)) {
+			au_fclr_pin(p->flags, MNT_WRITE);
+			goto out_unpin;
+		}
+	}
+
+	if (au_ftest_pin(p->flags, MNT_WRITE)) {
+		p->h_mnt = br->br_mnt;
+		err = mnt_want_write(p->h_mnt);
+		if (unlikely(err)) {
+			au_fclr_pin(p->flags, MNT_WRITE);
+			goto out_unpin;
+		}
+	}
+	goto out; /* success */
+
+ out_unpin:
+	au_unpin(p);
+ out_err:
+	pr_err("err %d\n", err);
+	err = au_busy_or_stale();
+ out:
+	return err;
+}
+
+void au_pin_init(struct au_pin *p, struct dentry *dentry,
+		 aufs_bindex_t bindex, int lsc_di, int lsc_hi,
+		 unsigned int udba, unsigned char flags)
+{
+	p->dentry = dentry;
+	p->udba = udba;
+	p->lsc_di = lsc_di;
+	p->lsc_hi = lsc_hi;
+	p->flags = flags;
+	p->bindex = bindex;
+
+	p->parent = NULL;
+	p->hdir = NULL;
+	p->h_mnt = NULL;
+}
+
+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
+	   unsigned int udba, unsigned char flags)
+{
+	au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
+		    udba, flags);
+	return au_do_pin(pin);
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define AuIcpup_DID_CPUP	1
+#define au_ftest_icpup(flags, name)	((flags) & AuIcpup_##name)
+#define au_fset_icpup(flags, name)	{ (flags) |= AuIcpup_##name; }
+#define au_fclr_icpup(flags, name)	{ (flags) &= ~AuIcpup_##name; }
+
+struct au_icpup_args {
+	unsigned char flags;
+	unsigned char pin_flags;
+	aufs_bindex_t btgt;
+	struct au_pin pin;
+	struct path h_path;
+	struct inode *h_inode;
+};
+
+static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
+			     struct au_icpup_args *a)
+{
+	int err;
+	unsigned int udba;
+	loff_t sz;
+	aufs_bindex_t bstart;
+	struct dentry *hi_wh, *parent;
+	struct inode *inode;
+	struct au_wr_dir_args wr_dir_args = {
+		.force_btgt	= -1,
+		.flags		= 0
+	};
+
+	di_write_lock_child(dentry);
+	bstart = au_dbstart(dentry);
+	inode = dentry->d_inode;
+	if (S_ISDIR(inode->i_mode))
+		au_fset_wrdir(wr_dir_args.flags, ISDIR);
+	/* plink or hi_wh() case */
+	if (bstart != au_ibstart(inode))
+		wr_dir_args.force_btgt = au_ibstart(inode);
+	err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
+	if (unlikely(err < 0))
+		goto out_dentry;
+	a->btgt = err;
+	if (err != bstart)
+		au_fset_icpup(a->flags, DID_CPUP);
+
+	err = 0;
+	a->pin_flags = AuPin_MNT_WRITE;
+	parent = NULL;
+	if (!IS_ROOT(dentry)) {
+		au_fset_pin(a->pin_flags, DI_LOCKED);
+		parent = dget_parent(dentry);
+		di_write_lock_parent(parent);
+	}
+
+	udba = au_opt_udba(dentry->d_sb);
+	if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
+		udba = AuOpt_UDBA_NONE;
+	err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
+	if (unlikely(err)) {
+		if (parent) {
+			di_write_unlock(parent);
+			dput(parent);
+		}
+		goto out_dentry;
+	}
+	a->h_path.dentry = au_h_dptr(dentry, bstart);
+	a->h_inode = a->h_path.dentry->d_inode;
+	mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
+	sz = -1;
+	if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
+		sz = ia->ia_size;
+
+	hi_wh = NULL;
+	if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
+		hi_wh = au_hi_wh(inode, a->btgt);
+		if (!hi_wh) {
+			err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
+			if (unlikely(err))
+				goto out_unlock;
+			hi_wh = au_hi_wh(inode, a->btgt);
+			/* todo: revalidate hi_wh? */
+		}
+	}
+
+	if (parent) {
+		au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
+		di_downgrade_lock(parent, AuLock_IR);
+		dput(parent);
+	}
+	if (!au_ftest_icpup(a->flags, DID_CPUP))
+		goto out; /* success */
+
+	if (!d_unhashed(dentry)) {
+		err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
+		if (!err)
+			a->h_path.dentry = au_h_dptr(dentry, a->btgt);
+	} else if (!hi_wh)
+		a->h_path.dentry = au_h_dptr(dentry, a->btgt);
+	else
+		a->h_path.dentry = hi_wh; /* do not dget here */
+
+ out_unlock:
+	mutex_unlock(&a->h_inode->i_mutex);
+	a->h_inode = a->h_path.dentry->d_inode;
+	if (!err) {
+		mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
+		goto out; /* success */
+	}
+
+	au_unpin(&a->pin);
+
+ out_dentry:
+	di_write_unlock(dentry);
+ out:
+	return err;
+}
+
+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
+{
+	int err;
+	struct inode *inode;
+	struct super_block *sb;
+	struct file *file;
+	struct au_icpup_args *a;
+
+	err = -ENOMEM;
+	a = kzalloc(sizeof(*a), GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	inode = dentry->d_inode;
+	IMustLock(inode);
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+
+	file = NULL;
+	if (ia->ia_valid & ATTR_FILE) {
+		/* currently ftruncate(2) only */
+		file = ia->ia_file;
+		fi_write_lock(file);
+		ia->ia_file = au_h_fptr(file, au_fbstart(file));
+	}
+
+	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+		ia->ia_valid &= ~ATTR_MODE;
+
+	err = au_lock_and_icpup(dentry, ia, a);
+	if (unlikely(err < 0))
+		goto out_si;
+	if (au_ftest_icpup(a->flags, DID_CPUP)) {
+		ia->ia_file = NULL;
+		ia->ia_valid &= ~ATTR_FILE;
+	}
+
+	a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
+	if (ia->ia_valid & ATTR_SIZE) {
+		struct file *f;
+
+		if (ia->ia_size < i_size_read(inode)) {
+			/* unmap only */
+			err = vmtruncate(inode, ia->ia_size);
+			if (unlikely(err))
+				goto out_unlock;
+		}
+
+		f = NULL;
+		if (ia->ia_valid & ATTR_FILE)
+			f = ia->ia_file;
+		mutex_unlock(&a->h_inode->i_mutex);
+		err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
+		mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
+	} else
+		err = vfsub_notify_change(&a->h_path, ia);
+	if (!err)
+		au_cpup_attr_changeable(inode);
+
+ out_unlock:
+	mutex_unlock(&a->h_inode->i_mutex);
+	au_unpin(&a->pin);
+	di_write_unlock(dentry);
+ out_si:
+	if (file) {
+		fi_write_unlock(file);
+		ia->ia_file = file;
+		ia->ia_valid |= ATTR_FILE;
+	}
+	si_read_unlock(sb);
+	kfree(a);
+ out:
+	return err;
+}
+
+static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
+{
+	int err;
+	struct inode *inode;
+	struct dentry *parent;
+
+	err = 0;
+	inode = dentry->d_inode;
+	di_write_lock_child(dentry);
+	if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
+		parent = dget_parent(dentry);
+		di_read_lock_parent(parent, AuLock_IR);
+		/* returns a number of positive dentries */
+		err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
+		if (err >= 0)
+			err = au_refresh_hinode(inode, dentry);
+		di_read_unlock(parent, AuLock_IR);
+		dput(parent);
+	}
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		di_read_unlock(dentry, AuLock_IR);
+
+	AuTraceErr(err);
+	return err;
+}
+
+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
+			     unsigned int nlink)
+{
+	inode->i_mode = st->mode;
+	inode->i_uid = st->uid;
+	inode->i_gid = st->gid;
+	inode->i_atime = st->atime;
+	inode->i_mtime = st->mtime;
+	inode->i_ctime = st->ctime;
+
+	au_cpup_attr_nlink(inode, /*force*/0);
+	if (S_ISDIR(inode->i_mode)) {
+		inode->i_nlink -= nlink;
+		inode->i_nlink += st->nlink;
+	}
+
+	spin_lock(&inode->i_lock);
+	inode->i_blocks = st->blocks;
+	i_size_write(inode, st->size);
+	spin_unlock(&inode->i_lock);
+}
+
+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
+			struct dentry *dentry, struct kstat *st)
+{
+	int err;
+	unsigned int mnt_flags;
+	aufs_bindex_t bindex;
+	unsigned char udba_none, positive;
+	struct super_block *sb, *h_sb;
+	struct inode *inode;
+	struct vfsmount *h_mnt;
+	struct dentry *h_dentry;
+
+	err = 0;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	si_read_lock(sb, AuLock_FLUSH);
+	mnt_flags = au_mntflags(sb);
+	udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
+
+	/* support fstat(2) */
+	if (!d_unhashed(dentry) && !udba_none) {
+		unsigned int sigen = au_sigen(sb);
+		if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
+			di_read_lock_child(dentry, AuLock_IR);
+		else {
+			AuDebugOn(IS_ROOT(dentry));
+			err = au_getattr_lock_reval(dentry, sigen);
+			if (unlikely(err))
+				goto out;
+		}
+	} else
+		di_read_lock_child(dentry, AuLock_IR);
+
+	bindex = au_ibstart(inode);
+	h_mnt = au_sbr_mnt(sb, bindex);
+	h_sb = h_mnt->mnt_sb;
+	if (!au_test_fs_bad_iattr(h_sb) && udba_none)
+		goto out_fill; /* success */
+
+	h_dentry = NULL;
+	if (au_dbstart(dentry) == bindex)
+		h_dentry = dget(au_h_dptr(dentry, bindex));
+	else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
+		h_dentry = au_plink_lkup(inode, bindex);
+		if (IS_ERR(h_dentry))
+			goto out_fill; /* pretending success */
+	}
+	/* illegally overlapped or something */
+	if (unlikely(!h_dentry))
+		goto out_fill; /* pretending success */
+
+	positive = !!h_dentry->d_inode;
+	if (positive)
+		err = vfs_getattr(h_mnt, h_dentry, st);
+	dput(h_dentry);
+	if (!err) {
+		if (positive)
+			au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
+		goto out_fill; /* success */
+	}
+	goto out_unlock;
+
+ out_fill:
+	generic_fillattr(inode, st);
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
+		      int bufsiz)
+{
+	int err;
+	struct super_block *sb;
+	struct dentry *h_dentry;
+
+	err = -EINVAL;
+	h_dentry = au_h_dptr(dentry, bindex);
+	if (unlikely(/* !h_dentry
+		     || !h_dentry->d_inode
+		     || !h_dentry->d_inode->i_op
+		     || */ !h_dentry->d_inode->i_op->readlink))
+		goto out;
+
+	err = security_inode_readlink(h_dentry);
+	if (unlikely(err))
+		goto out;
+
+	sb = dentry->d_sb;
+	if (!au_test_ro(sb, bindex, dentry->d_inode)) {
+		vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
+		fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
+	}
+	err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
+
+ out:
+	return err;
+}
+
+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+{
+	int err;
+
+	aufs_read_lock(dentry, AuLock_IR);
+	err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
+	aufs_read_unlock(dentry, AuLock_IR);
+
+	return err;
+}
+
+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	int err;
+	char *buf;
+	mm_segment_t old_fs;
+
+	err = -ENOMEM;
+	buf = __getname();
+	if (unlikely(!buf))
+		goto out;
+
+	aufs_read_lock(dentry, AuLock_IR);
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
+			 PATH_MAX);
+	set_fs(old_fs);
+	aufs_read_unlock(dentry, AuLock_IR);
+
+	if (err >= 0) {
+		buf[err] = 0;
+		/* will be freed by put_link */
+		nd_set_link(nd, buf);
+		return NULL; /* success */
+	}
+	__putname(buf);
+
+ out:
+	path_put(&nd->path);
+	AuTraceErr(err);
+	return ERR_PTR(err);
+}
+
+static void aufs_put_link(struct dentry *dentry __maybe_unused,
+			  struct nameidata *nd, void *cookie __maybe_unused)
+{
+	__putname(nd_get_link(nd));
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void aufs_truncate_range(struct inode *inode __maybe_unused,
+				loff_t start __maybe_unused,
+				loff_t end __maybe_unused)
+{
+	AuUnsupport();
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct inode_operations aufs_symlink_iop = {
+	.permission	= aufs_permission,
+	.setattr	= aufs_setattr,
+	.getattr	= aufs_getattr,
+	.readlink	= aufs_readlink,
+	.follow_link	= aufs_follow_link,
+	.put_link	= aufs_put_link
+};
+
+struct inode_operations aufs_dir_iop = {
+	.create		= aufs_create,
+	.lookup		= aufs_lookup,
+	.link		= aufs_link,
+	.unlink		= aufs_unlink,
+	.symlink	= aufs_symlink,
+	.mkdir		= aufs_mkdir,
+	.rmdir		= aufs_rmdir,
+	.mknod		= aufs_mknod,
+	.rename		= aufs_rename,
+
+	.permission	= aufs_permission,
+	.setattr	= aufs_setattr,
+	.getattr	= aufs_getattr
+};
+
+struct inode_operations aufs_iop = {
+	.permission	= aufs_permission,
+	.setattr	= aufs_setattr,
+	.getattr	= aufs_getattr,
+	.truncate_range	= aufs_truncate_range
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/xino.c
+++ linux-ec2-2.6.32/ubuntu/aufs/xino.c
@@ -0,0 +1,1204 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * external inode number translation table and bitmap
+ */
+
+#include <linux/file.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include "aufs.h"
+
+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
+		   loff_t *pos)
+{
+	ssize_t err;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	do {
+		/* todo: signal_pending? */
+		err = func(file, (char __user *)buf, size, pos);
+	} while (err == -EAGAIN || err == -EINTR);
+	set_fs(oldfs);
+
+#if 0 /* reserved for future use */
+	if (err > 0)
+		fsnotify_access(file->f_dentry);
+#endif
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
+			      size_t size, loff_t *pos)
+{
+	ssize_t err;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	/* lockdep_off(); */
+	do {
+		/* todo: signal_pending? */
+		err = func(file, (const char __user *)buf, size, pos);
+	} while (err == -EAGAIN || err == -EINTR);
+	/* lockdep_on(); */
+	set_fs(oldfs);
+
+#if 0 /* reserved for future use */
+	if (err > 0)
+		fsnotify_modify(file->f_dentry);
+#endif
+
+	return err;
+}
+
+struct do_xino_fwrite_args {
+	ssize_t *errp;
+	au_writef_t func;
+	struct file *file;
+	void *buf;
+	size_t size;
+	loff_t *pos;
+};
+
+static void call_do_xino_fwrite(void *args)
+{
+	struct do_xino_fwrite_args *a = args;
+	*a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
+}
+
+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
+		    loff_t *pos)
+{
+	ssize_t err;
+
+	/* todo: signal block and no wkq? */
+	/* todo: new credential scheme */
+	/*
+	 * it breaks RLIMIT_FSIZE and normal user's limit,
+	 * users should care about quota and real 'filesystem full.'
+	 */
+	if (!au_test_wkq(current)) {
+		int wkq_err;
+		struct do_xino_fwrite_args args = {
+			.errp	= &err,
+			.func	= func,
+			.file	= file,
+			.buf	= buf,
+			.size	= size,
+			.pos	= pos
+		};
+
+		wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	} else
+		err = do_xino_fwrite(func, file, buf, size, pos);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * create a new xinofile at the same place/path as @base_file.
+ */
+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
+{
+	struct file *file;
+	struct dentry *base, *dentry, *parent;
+	struct inode *dir;
+	struct qstr *name;
+	int err;
+	struct path path;
+
+	base = base_file->f_dentry;
+	parent = base->d_parent; /* dir inode is locked */
+	dir = parent->d_inode;
+	IMustLock(dir);
+
+	file = ERR_PTR(-EINVAL);
+	name = &base->d_name;
+	dentry = vfsub_lookup_one_len(name->name, parent, name->len);
+	if (IS_ERR(dentry)) {
+		file = (void *)dentry;
+		pr_err("%.*s lookup err %ld\n",
+		       AuLNPair(name), PTR_ERR(dentry));
+		goto out;
+	}
+
+	/* no need to mnt_want_write() since we call dentry_open() later */
+	err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
+	if (unlikely(err)) {
+		file = ERR_PTR(err);
+		pr_err("%.*s create err %d\n", AuLNPair(name), err);
+		goto out_dput;
+	}
+
+	path.dentry = dentry;
+	path.mnt = base_file->f_vfsmnt;
+	path_get(&path);
+	file = vfsub_dentry_open(&path, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
+				 current_cred());
+	if (IS_ERR(file)) {
+		pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
+		goto out_dput;
+	}
+
+	err = vfsub_unlink(dir, &file->f_path, /*force*/0);
+	if (unlikely(err)) {
+		pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
+		goto out_fput;
+	}
+
+	if (copy_src) {
+		/* no one can touch copy_src xino */
+		err = au_copy_file(file, copy_src,
+				   i_size_read(copy_src->f_dentry->d_inode));
+		if (unlikely(err)) {
+			pr_err("%.*s copy err %d\n", AuLNPair(name), err);
+			goto out_fput;
+		}
+	}
+	goto out_dput; /* success */
+
+ out_fput:
+	fput(file);
+	file = ERR_PTR(err);
+ out_dput:
+	dput(dentry);
+ out:
+	return file;
+}
+
+struct au_xino_lock_dir {
+	struct au_hinode *hdir;
+	struct dentry *parent;
+	struct mutex *mtx;
+};
+
+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
+			     struct au_xino_lock_dir *ldir)
+{
+	aufs_bindex_t brid, bindex;
+
+	ldir->hdir = NULL;
+	bindex = -1;
+	brid = au_xino_brid(sb);
+	if (brid >= 0)
+		bindex = au_br_index(sb, brid);
+	if (bindex >= 0) {
+		ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
+		au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
+	} else {
+		ldir->parent = dget_parent(xino->f_dentry);
+		ldir->mtx = &ldir->parent->d_inode->i_mutex;
+		mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
+	}
+}
+
+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
+{
+	if (ldir->hdir)
+		au_hin_imtx_unlock(ldir->hdir);
+	else {
+		mutex_unlock(ldir->mtx);
+		dput(ldir->parent);
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* trucate xino files asynchronously */
+
+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
+{
+	int err;
+	aufs_bindex_t bi, bend;
+	struct au_branch *br;
+	struct file *new_xino, *file;
+	struct super_block *h_sb;
+	struct au_xino_lock_dir ldir;
+
+	err = -EINVAL;
+	bend = au_sbend(sb);
+	if (unlikely(bindex < 0 || bend < bindex))
+		goto out;
+	br = au_sbr(sb, bindex);
+	file = br->br_xino.xi_file;
+	if (!file)
+		goto out;
+
+	au_xino_lock_dir(sb, file, &ldir);
+	/* mnt_want_write() is unnecessary here */
+	new_xino = au_xino_create2(file, file);
+	au_xino_unlock_dir(&ldir);
+	err = PTR_ERR(new_xino);
+	if (IS_ERR(new_xino))
+		goto out;
+	err = 0;
+	fput(file);
+	br->br_xino.xi_file = new_xino;
+
+	h_sb = br->br_mnt->mnt_sb;
+	for (bi = 0; bi <= bend; bi++) {
+		if (unlikely(bi == bindex))
+			continue;
+		br = au_sbr(sb, bi);
+		if (br->br_mnt->mnt_sb != h_sb)
+			continue;
+
+		fput(br->br_xino.xi_file);
+		br->br_xino.xi_file = new_xino;
+		get_file(new_xino);
+	}
+
+ out:
+	return err;
+}
+
+struct xino_do_trunc_args {
+	struct super_block *sb;
+	struct au_branch *br;
+};
+
+static void xino_do_trunc(void *_args)
+{
+	struct xino_do_trunc_args *args = _args;
+	struct super_block *sb;
+	struct au_branch *br;
+	struct inode *dir;
+	int err;
+	aufs_bindex_t bindex;
+
+	err = 0;
+	sb = args->sb;
+	dir = sb->s_root->d_inode;
+	br = args->br;
+
+	si_noflush_write_lock(sb);
+	ii_read_lock_parent(dir);
+	bindex = au_br_index(sb, br->br_id);
+	err = au_xino_trunc(sb, bindex);
+	if (!err
+	    && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
+	    >= br->br_xino_upper)
+		br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
+
+	ii_read_unlock(dir);
+	if (unlikely(err))
+		pr_warning("err b%d, (%d)\n", bindex, err);
+	atomic_dec(&br->br_xino_running);
+	atomic_dec(&br->br_count);
+	au_nwt_done(&au_sbi(sb)->si_nowait);
+	si_write_unlock(sb);
+	kfree(args);
+}
+
+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
+{
+	struct xino_do_trunc_args *args;
+	int wkq_err;
+
+	if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
+	    < br->br_xino_upper)
+		return;
+
+	if (atomic_inc_return(&br->br_xino_running) > 1)
+		goto out;
+
+	/* lock and kfree() will be called in trunc_xino() */
+	args = kmalloc(sizeof(*args), GFP_NOFS);
+	if (unlikely(!args)) {
+		AuErr1("no memory\n");
+		goto out_args;
+	}
+
+	atomic_inc_return(&br->br_count);
+	args->sb = sb;
+	args->br = br;
+	wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
+	if (!wkq_err)
+		return; /* success */
+
+	pr_err("wkq %d\n", wkq_err);
+	atomic_dec_return(&br->br_count);
+
+ out_args:
+	kfree(args);
+ out:
+	atomic_dec_return(&br->br_xino_running);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_xino_do_write(au_writef_t write, struct file *file,
+			    ino_t h_ino, ino_t ino)
+{
+	loff_t pos;
+	ssize_t sz;
+
+	pos = h_ino;
+	if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
+		AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
+		return -EFBIG;
+	}
+	pos *= sizeof(ino);
+	sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
+	if (sz == sizeof(ino))
+		return 0; /* success */
+
+	AuIOErr("write failed (%zd)\n", sz);
+	return -EIO;
+}
+
+/*
+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
+ * at the position of @h_ino.
+ * even if @ino is zero, it is written to the xinofile and means no entry.
+ * if the size of the xino file on a specific filesystem exceeds the watermark,
+ * try truncating it.
+ */
+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		  ino_t ino)
+{
+	int err;
+	unsigned int mnt_flags;
+	struct au_branch *br;
+
+	BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
+		     || ((loff_t)-1) > 0);
+	SiMustAnyLock(sb);
+
+	mnt_flags = au_mntflags(sb);
+	if (!au_opt_test(mnt_flags, XINO))
+		return 0;
+
+	br = au_sbr(sb, bindex);
+	err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
+			       h_ino, ino);
+	if (!err) {
+		if (au_opt_test(mnt_flags, TRUNC_XINO)
+		    && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
+			xino_try_trunc(sb, br);
+		return 0; /* success */
+	}
+
+	AuIOErr("write failed (%d)\n", err);
+	return -EIO;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* aufs inode number bitmap */
+
+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
+static ino_t xib_calc_ino(unsigned long pindex, int bit)
+{
+	ino_t ino;
+
+	AuDebugOn(bit < 0 || page_bits <= bit);
+	ino = AUFS_FIRST_INO + pindex * page_bits + bit;
+	return ino;
+}
+
+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
+{
+	AuDebugOn(ino < AUFS_FIRST_INO);
+	ino -= AUFS_FIRST_INO;
+	*pindex = ino / page_bits;
+	*bit = ino % page_bits;
+}
+
+static int xib_pindex(struct super_block *sb, unsigned long pindex)
+{
+	int err;
+	loff_t pos;
+	ssize_t sz;
+	struct au_sbinfo *sbinfo;
+	struct file *xib;
+	unsigned long *p;
+
+	sbinfo = au_sbi(sb);
+	MtxMustLock(&sbinfo->si_xib_mtx);
+	AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
+		  || !au_opt_test(sbinfo->si_mntflags, XINO));
+
+	if (pindex == sbinfo->si_xib_last_pindex)
+		return 0;
+
+	xib = sbinfo->si_xib;
+	p = sbinfo->si_xib_buf;
+	pos = sbinfo->si_xib_last_pindex;
+	pos *= PAGE_SIZE;
+	sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
+	if (unlikely(sz != PAGE_SIZE))
+		goto out;
+
+	pos = pindex;
+	pos *= PAGE_SIZE;
+	if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
+		sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
+	else {
+		memset(p, 0, PAGE_SIZE);
+		sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
+	}
+	if (sz == PAGE_SIZE) {
+		sbinfo->si_xib_last_pindex = pindex;
+		return 0; /* success */
+	}
+
+ out:
+	AuIOErr1("write failed (%zd)\n", sz);
+	err = sz;
+	if (sz >= 0)
+		err = -EIO;
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		   ino_t ino)
+{
+	int err, bit;
+	unsigned long pindex;
+	struct au_sbinfo *sbinfo;
+
+	if (!au_opt_test(au_mntflags(sb), XINO))
+		return 0;
+
+	err = 0;
+	if (ino) {
+		sbinfo = au_sbi(sb);
+		xib_calc_bit(ino, &pindex, &bit);
+		AuDebugOn(page_bits <= bit);
+		mutex_lock(&sbinfo->si_xib_mtx);
+		err = xib_pindex(sb, pindex);
+		if (!err) {
+			clear_bit(bit, sbinfo->si_xib_buf);
+			sbinfo->si_xib_next_bit = bit;
+		}
+		mutex_unlock(&sbinfo->si_xib_mtx);
+	}
+
+	if (!err)
+		err = au_xino_write(sb, bindex, h_ino, 0);
+	return err;
+}
+
+/* get an unused inode number from bitmap */
+ino_t au_xino_new_ino(struct super_block *sb)
+{
+	ino_t ino;
+	unsigned long *p, pindex, ul, pend;
+	struct au_sbinfo *sbinfo;
+	struct file *file;
+	int free_bit, err;
+
+	if (!au_opt_test(au_mntflags(sb), XINO))
+		return iunique(sb, AUFS_FIRST_INO);
+
+	sbinfo = au_sbi(sb);
+	mutex_lock(&sbinfo->si_xib_mtx);
+	p = sbinfo->si_xib_buf;
+	free_bit = sbinfo->si_xib_next_bit;
+	if (free_bit < page_bits && !test_bit(free_bit, p))
+		goto out; /* success */
+	free_bit = find_first_zero_bit(p, page_bits);
+	if (free_bit < page_bits)
+		goto out; /* success */
+
+	pindex = sbinfo->si_xib_last_pindex;
+	for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
+		err = xib_pindex(sb, ul);
+		if (unlikely(err))
+			goto out_err;
+		free_bit = find_first_zero_bit(p, page_bits);
+		if (free_bit < page_bits)
+			goto out; /* success */
+	}
+
+	file = sbinfo->si_xib;
+	pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
+	for (ul = pindex + 1; ul <= pend; ul++) {
+		err = xib_pindex(sb, ul);
+		if (unlikely(err))
+			goto out_err;
+		free_bit = find_first_zero_bit(p, page_bits);
+		if (free_bit < page_bits)
+			goto out; /* success */
+	}
+	BUG();
+
+ out:
+	set_bit(free_bit, p);
+	sbinfo->si_xib_next_bit++;
+	pindex = sbinfo->si_xib_last_pindex;
+	mutex_unlock(&sbinfo->si_xib_mtx);
+	ino = xib_calc_ino(pindex, free_bit);
+	AuDbg("i%lu\n", (unsigned long)ino);
+	return ino;
+ out_err:
+	mutex_unlock(&sbinfo->si_xib_mtx);
+	AuDbg("i0\n");
+	return 0;
+}
+
+/*
+ * read @ino from xinofile for the specified branch{@sb, @bindex}
+ * at the position of @h_ino.
+ * if @ino does not exist and @do_new is true, get new one.
+ */
+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		 ino_t *ino)
+{
+	int err;
+	ssize_t sz;
+	loff_t pos;
+	struct file *file;
+	struct au_sbinfo *sbinfo;
+
+	*ino = 0;
+	if (!au_opt_test(au_mntflags(sb), XINO))
+		return 0; /* no xino */
+
+	err = 0;
+	sbinfo = au_sbi(sb);
+	pos = h_ino;
+	if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
+		AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
+		return -EFBIG;
+	}
+	pos *= sizeof(*ino);
+
+	file = au_sbr(sb, bindex)->br_xino.xi_file;
+	if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
+		return 0; /* no ino */
+
+	sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
+	if (sz == sizeof(*ino))
+		return 0; /* success */
+
+	err = sz;
+	if (unlikely(sz >= 0)) {
+		err = -EIO;
+		AuIOErr("xino read error (%zd)\n", sz);
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* create and set a new xino file */
+
+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
+{
+	struct file *file;
+	struct dentry *h_parent, *d;
+	struct inode *h_dir;
+	int err;
+
+	/*
+	 * at mount-time, and the xino file is the default path,
+	 * hinotify is disabled so we have no inotify events to ignore.
+	 * when a user specified the xino, we cannot get au_hdir to be ignored.
+	 */
+	file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
+			       S_IRUGO | S_IWUGO);
+	if (IS_ERR(file)) {
+		if (!silent)
+			pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
+		return file;
+	}
+
+	/* keep file count */
+	h_parent = dget_parent(file->f_dentry);
+	h_dir = h_parent->d_inode;
+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
+	/* mnt_want_write() is unnecessary here */
+	err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
+	mutex_unlock(&h_dir->i_mutex);
+	dput(h_parent);
+	if (unlikely(err)) {
+		if (!silent)
+			pr_err("unlink %s(%d)\n", fname, err);
+		goto out;
+	}
+
+	err = -EINVAL;
+	d = file->f_dentry;
+	if (unlikely(sb == d->d_sb)) {
+		if (!silent)
+			pr_err("%s must be outside\n", fname);
+		goto out;
+	}
+	if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
+		if (!silent)
+			pr_err("xino doesn't support %s(%s)\n",
+			       fname, au_sbtype(d->d_sb));
+		goto out;
+	}
+	return file; /* success */
+
+ out:
+	fput(file);
+	file = ERR_PTR(err);
+	return file;
+}
+
+/*
+ * find another branch who is on the same filesystem of the specified
+ * branch{@btgt}. search until @bend.
+ */
+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
+			aufs_bindex_t bend)
+{
+	aufs_bindex_t bindex;
+	struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
+
+	for (bindex = 0; bindex < btgt; bindex++)
+		if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
+			return bindex;
+	for (bindex++; bindex <= bend; bindex++)
+		if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
+			return bindex;
+	return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * initialize the xinofile for the specified branch @br
+ * at the place/path where @base_file indicates.
+ * test whether another branch is on the same filesystem or not,
+ * if @do_test is true.
+ */
+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
+	       struct file *base_file, int do_test)
+{
+	int err;
+	ino_t ino;
+	aufs_bindex_t bend, bindex;
+	struct au_branch *shared_br, *b;
+	struct file *file;
+	struct super_block *tgt_sb;
+
+	shared_br = NULL;
+	bend = au_sbend(sb);
+	if (do_test) {
+		tgt_sb = br->br_mnt->mnt_sb;
+		for (bindex = 0; bindex <= bend; bindex++) {
+			b = au_sbr(sb, bindex);
+			if (tgt_sb == b->br_mnt->mnt_sb) {
+				shared_br = b;
+				break;
+			}
+		}
+	}
+
+	if (!shared_br || !shared_br->br_xino.xi_file) {
+		struct au_xino_lock_dir ldir;
+
+		au_xino_lock_dir(sb, base_file, &ldir);
+		/* mnt_want_write() is unnecessary here */
+		file = au_xino_create2(base_file, NULL);
+		au_xino_unlock_dir(&ldir);
+		err = PTR_ERR(file);
+		if (IS_ERR(file))
+			goto out;
+		br->br_xino.xi_file = file;
+	} else {
+		br->br_xino.xi_file = shared_br->br_xino.xi_file;
+		get_file(br->br_xino.xi_file);
+	}
+
+	ino = AUFS_ROOT_INO;
+	err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
+			       h_ino, ino);
+	if (!err)
+		return 0; /* success */
+
+
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* trucate a xino bitmap file */
+
+/* todo: slow */
+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
+{
+	int err, bit;
+	ssize_t sz;
+	unsigned long pindex;
+	loff_t pos, pend;
+	struct au_sbinfo *sbinfo;
+	au_readf_t func;
+	ino_t *ino;
+	unsigned long *p;
+
+	err = 0;
+	sbinfo = au_sbi(sb);
+	MtxMustLock(&sbinfo->si_xib_mtx);
+	p = sbinfo->si_xib_buf;
+	func = sbinfo->si_xread;
+	pend = i_size_read(file->f_dentry->d_inode);
+	pos = 0;
+	while (pos < pend) {
+		sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
+		err = sz;
+		if (unlikely(sz <= 0))
+			goto out;
+
+		err = 0;
+		for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
+			if (unlikely(*ino < AUFS_FIRST_INO))
+				continue;
+
+			xib_calc_bit(*ino, &pindex, &bit);
+			AuDebugOn(page_bits <= bit);
+			err = xib_pindex(sb, pindex);
+			if (!err)
+				set_bit(bit, p);
+			else
+				goto out;
+		}
+	}
+
+ out:
+	return err;
+}
+
+static int xib_restore(struct super_block *sb)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	void *page;
+
+	err = -ENOMEM;
+	page = (void *)__get_free_page(GFP_NOFS);
+	if (unlikely(!page))
+		goto out;
+
+	err = 0;
+	bend = au_sbend(sb);
+	for (bindex = 0; !err && bindex <= bend; bindex++)
+		if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
+			err = do_xib_restore
+				(sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
+		else
+			AuDbg("b%d\n", bindex);
+	free_page((unsigned long)page);
+
+ out:
+	return err;
+}
+
+int au_xib_trunc(struct super_block *sb)
+{
+	int err;
+	ssize_t sz;
+	loff_t pos;
+	struct au_xino_lock_dir ldir;
+	struct au_sbinfo *sbinfo;
+	unsigned long *p;
+	struct file *file;
+
+	SiMustWriteLock(sb);
+
+	err = 0;
+	sbinfo = au_sbi(sb);
+	if (!au_opt_test(sbinfo->si_mntflags, XINO))
+		goto out;
+
+	file = sbinfo->si_xib;
+	if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
+		goto out;
+
+	au_xino_lock_dir(sb, file, &ldir);
+	/* mnt_want_write() is unnecessary here */
+	file = au_xino_create2(sbinfo->si_xib, NULL);
+	au_xino_unlock_dir(&ldir);
+	err = PTR_ERR(file);
+	if (IS_ERR(file))
+		goto out;
+	fput(sbinfo->si_xib);
+	sbinfo->si_xib = file;
+
+	p = sbinfo->si_xib_buf;
+	memset(p, 0, PAGE_SIZE);
+	pos = 0;
+	sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
+	if (unlikely(sz != PAGE_SIZE)) {
+		err = sz;
+		AuIOErr("err %d\n", err);
+		if (sz >= 0)
+			err = -EIO;
+		goto out;
+	}
+
+	mutex_lock(&sbinfo->si_xib_mtx);
+	/* mnt_want_write() is unnecessary here */
+	err = xib_restore(sb);
+	mutex_unlock(&sbinfo->si_xib_mtx);
+
+out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * xino mount option handlers
+ */
+static au_readf_t find_readf(struct file *h_file)
+{
+	const struct file_operations *fop = h_file->f_op;
+
+	if (fop) {
+		if (fop->read)
+			return fop->read;
+		if (fop->aio_read)
+			return do_sync_read;
+	}
+	return ERR_PTR(-ENOSYS);
+}
+
+static au_writef_t find_writef(struct file *h_file)
+{
+	const struct file_operations *fop = h_file->f_op;
+
+	if (fop) {
+		if (fop->write)
+			return fop->write;
+		if (fop->aio_write)
+			return do_sync_write;
+	}
+	return ERR_PTR(-ENOSYS);
+}
+
+/* xino bitmap */
+static void xino_clear_xib(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	sbinfo->si_xread = NULL;
+	sbinfo->si_xwrite = NULL;
+	if (sbinfo->si_xib)
+		fput(sbinfo->si_xib);
+	sbinfo->si_xib = NULL;
+	free_page((unsigned long)sbinfo->si_xib_buf);
+	sbinfo->si_xib_buf = NULL;
+}
+
+static int au_xino_set_xib(struct super_block *sb, struct file *base)
+{
+	int err;
+	loff_t pos;
+	struct au_sbinfo *sbinfo;
+	struct file *file;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	file = au_xino_create2(base, sbinfo->si_xib);
+	err = PTR_ERR(file);
+	if (IS_ERR(file))
+		goto out;
+	if (sbinfo->si_xib)
+		fput(sbinfo->si_xib);
+	sbinfo->si_xib = file;
+	sbinfo->si_xread = find_readf(file);
+	sbinfo->si_xwrite = find_writef(file);
+
+	err = -ENOMEM;
+	if (!sbinfo->si_xib_buf)
+		sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
+	if (unlikely(!sbinfo->si_xib_buf))
+		goto out_unset;
+
+	sbinfo->si_xib_last_pindex = 0;
+	sbinfo->si_xib_next_bit = 0;
+	if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
+		pos = 0;
+		err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
+				  PAGE_SIZE, &pos);
+		if (unlikely(err != PAGE_SIZE))
+			goto out_free;
+	}
+	err = 0;
+	goto out; /* success */
+
+ out_free:
+	free_page((unsigned long)sbinfo->si_xib_buf);
+	sbinfo->si_xib_buf = NULL;
+	if (err >= 0)
+		err = -EIO;
+ out_unset:
+	fput(sbinfo->si_xib);
+	sbinfo->si_xib = NULL;
+	sbinfo->si_xread = NULL;
+	sbinfo->si_xwrite = NULL;
+ out:
+	return err;
+}
+
+/* xino for each branch */
+static void xino_clear_br(struct super_block *sb)
+{
+	aufs_bindex_t bindex, bend;
+	struct au_branch *br;
+
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		if (!br || !br->br_xino.xi_file)
+			continue;
+
+		fput(br->br_xino.xi_file);
+		br->br_xino.xi_file = NULL;
+	}
+}
+
+static int au_xino_set_br(struct super_block *sb, struct file *base)
+{
+	int err;
+	ino_t ino;
+	aufs_bindex_t bindex, bend, bshared;
+	struct {
+		struct file *old, *new;
+	} *fpair, *p;
+	struct au_branch *br;
+	struct inode *inode;
+	au_writef_t writef;
+
+	SiMustWriteLock(sb);
+
+	err = -ENOMEM;
+	bend = au_sbend(sb);
+	fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
+	if (unlikely(!fpair))
+		goto out;
+
+	inode = sb->s_root->d_inode;
+	ino = AUFS_ROOT_INO;
+	writef = au_sbi(sb)->si_xwrite;
+	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
+		br = au_sbr(sb, bindex);
+		bshared = is_sb_shared(sb, bindex, bindex - 1);
+		if (bshared >= 0) {
+			/* shared xino */
+			*p = fpair[bshared];
+			get_file(p->new);
+		}
+
+		if (!p->new) {
+			/* new xino */
+			p->old = br->br_xino.xi_file;
+			p->new = au_xino_create2(base, br->br_xino.xi_file);
+			err = PTR_ERR(p->new);
+			if (IS_ERR(p->new)) {
+				p->new = NULL;
+				goto out_pair;
+			}
+		}
+
+		err = au_xino_do_write(writef, p->new,
+				       au_h_iptr(inode, bindex)->i_ino, ino);
+		if (unlikely(err))
+			goto out_pair;
+	}
+
+	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
+		br = au_sbr(sb, bindex);
+		if (br->br_xino.xi_file)
+			fput(br->br_xino.xi_file);
+		get_file(p->new);
+		br->br_xino.xi_file = p->new;
+	}
+
+ out_pair:
+	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
+		if (p->new)
+			fput(p->new);
+		else
+			break;
+	kfree(fpair);
+ out:
+	return err;
+}
+
+void au_xino_clr(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	au_xigen_clr(sb);
+	xino_clear_xib(sb);
+	xino_clear_br(sb);
+	sbinfo = au_sbi(sb);
+	/* lvalue, do not call au_mntflags() */
+	au_opt_clr(sbinfo->si_mntflags, XINO);
+}
+
+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
+{
+	int err, skip;
+	struct dentry *parent, *cur_parent;
+	struct qstr *dname, *cur_name;
+	struct file *cur_xino;
+	struct inode *dir;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	err = 0;
+	sbinfo = au_sbi(sb);
+	parent = dget_parent(xino->file->f_dentry);
+	if (remount) {
+		skip = 0;
+		dname = &xino->file->f_dentry->d_name;
+		cur_xino = sbinfo->si_xib;
+		if (cur_xino) {
+			cur_parent = dget_parent(cur_xino->f_dentry);
+			cur_name = &cur_xino->f_dentry->d_name;
+			skip = (cur_parent == parent
+				&& dname->len == cur_name->len
+				&& !memcmp(dname->name, cur_name->name,
+					   dname->len));
+			dput(cur_parent);
+		}
+		if (skip)
+			goto out;
+	}
+
+	au_opt_set(sbinfo->si_mntflags, XINO);
+	dir = parent->d_inode;
+	mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
+	/* mnt_want_write() is unnecessary here */
+	err = au_xino_set_xib(sb, xino->file);
+	if (!err)
+		err = au_xigen_set(sb, xino->file);
+	if (!err)
+		err = au_xino_set_br(sb, xino->file);
+	mutex_unlock(&dir->i_mutex);
+	if (!err)
+		goto out; /* success */
+
+	/* reset all */
+	AuIOErr("failed creating xino(%d).\n", err);
+
+ out:
+	dput(parent);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * create a xinofile at the default place/path.
+ */
+struct file *au_xino_def(struct super_block *sb)
+{
+	struct file *file;
+	char *page, *p;
+	struct au_branch *br;
+	struct super_block *h_sb;
+	struct path path;
+	aufs_bindex_t bend, bindex, bwr;
+
+	br = NULL;
+	bend = au_sbend(sb);
+	bwr = -1;
+	for (bindex = 0; bindex <= bend; bindex++) {
+		br = au_sbr(sb, bindex);
+		if (au_br_writable(br->br_perm)
+		    && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
+			bwr = bindex;
+			break;
+		}
+	}
+
+	if (bwr >= 0) {
+		file = ERR_PTR(-ENOMEM);
+		page = __getname();
+		if (unlikely(!page))
+			goto out;
+		path.mnt = br->br_mnt;
+		path.dentry = au_h_dptr(sb->s_root, bwr);
+		p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
+		file = (void *)p;
+		if (!IS_ERR(p)) {
+			strcat(p, "/" AUFS_XINO_FNAME);
+			AuDbg("%s\n", p);
+			file = au_xino_create(sb, p, /*silent*/0);
+			if (!IS_ERR(file))
+				au_xino_brid_set(sb, br->br_id);
+		}
+		__putname(page);
+	} else {
+		file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
+		if (IS_ERR(file))
+			goto out;
+		h_sb = file->f_dentry->d_sb;
+		if (unlikely(au_test_fs_bad_xino(h_sb))) {
+			pr_err("xino doesn't support %s(%s)\n",
+			       AUFS_XINO_DEFPATH, au_sbtype(h_sb));
+			fput(file);
+			file = ERR_PTR(-EINVAL);
+		}
+		if (!IS_ERR(file))
+			au_xino_brid_set(sb, -1);
+	}
+
+ out:
+	return file;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_xino_path(struct seq_file *seq, struct file *file)
+{
+	int err;
+
+	err = au_seq_path(seq, &file->f_path);
+	if (unlikely(err < 0))
+		goto out;
+
+	err = 0;
+#define Deleted "\\040(deleted)"
+	seq->count -= sizeof(Deleted) - 1;
+	AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
+			 sizeof(Deleted) - 1));
+#undef Deleted
+
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/i_op_del.c
+++ linux-ec2-2.6.32/ubuntu/aufs/i_op_del.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode operations (del entry)
+ */
+
+#include "aufs.h"
+
+/*
+ * decide if a new whiteout for @dentry is necessary or not.
+ * when it is necessary, prepare the parent dir for the upper branch whose
+ * branch index is @bcpup for creation. the actual creation of the whiteout will
+ * be done by caller.
+ * return value:
+ * 0: wh is unnecessary
+ * plus: wh is necessary
+ * minus: error
+ */
+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
+{
+	int need_wh, err;
+	aufs_bindex_t bstart;
+	struct super_block *sb;
+
+	sb = dentry->d_sb;
+	bstart = au_dbstart(dentry);
+	if (*bcpup < 0) {
+		*bcpup = bstart;
+		if (au_test_ro(sb, bstart, dentry->d_inode)) {
+			err = AuWbrCopyup(au_sbi(sb), dentry);
+			*bcpup = err;
+			if (unlikely(err < 0))
+				goto out;
+		}
+	} else
+		AuDebugOn(bstart < *bcpup
+			  || au_test_ro(sb, *bcpup, dentry->d_inode));
+	AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
+
+	if (*bcpup != bstart) {
+		err = au_cpup_dirs(dentry, *bcpup);
+		if (unlikely(err))
+			goto out;
+		need_wh = 1;
+	} else {
+		aufs_bindex_t old_bend, new_bend, bdiropq = -1;
+
+		old_bend = au_dbend(dentry);
+		if (isdir) {
+			bdiropq = au_dbdiropq(dentry);
+			au_set_dbdiropq(dentry, -1);
+		}
+		need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
+					 /*nd*/NULL);
+		err = need_wh;
+		if (isdir)
+			au_set_dbdiropq(dentry, bdiropq);
+		if (unlikely(err < 0))
+			goto out;
+		new_bend = au_dbend(dentry);
+		if (!need_wh && old_bend != new_bend) {
+			au_set_h_dptr(dentry, new_bend, NULL);
+			au_set_dbend(dentry, old_bend);
+		}
+	}
+	AuDbg("need_wh %d\n", need_wh);
+	err = need_wh;
+
+ out:
+	return err;
+}
+
+/*
+ * simple tests for the del-entry operations.
+ * following the checks in vfs, plus the parent-child relationship.
+ */
+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
+	       struct dentry *h_parent, int isdir)
+{
+	int err;
+	umode_t h_mode;
+	struct dentry *h_dentry, *h_latest;
+	struct inode *h_inode;
+
+	h_dentry = au_h_dptr(dentry, bindex);
+	h_inode = h_dentry->d_inode;
+	if (dentry->d_inode) {
+		err = -ENOENT;
+		if (unlikely(!h_inode || !h_inode->i_nlink))
+			goto out;
+
+		h_mode = h_inode->i_mode;
+		if (!isdir) {
+			err = -EISDIR;
+			if (unlikely(S_ISDIR(h_mode)))
+				goto out;
+		} else if (unlikely(!S_ISDIR(h_mode))) {
+			err = -ENOTDIR;
+			goto out;
+		}
+	} else {
+		/* rename(2) case */
+		err = -EIO;
+		if (unlikely(h_inode))
+			goto out;
+	}
+
+	err = -ENOENT;
+	/* expected parent dir is locked */
+	if (unlikely(h_parent != h_dentry->d_parent))
+		goto out;
+	err = 0;
+
+	/*
+	 * rmdir a dir may break the consistency on some filesystem.
+	 * let's try heavy test.
+	 */
+	err = -EACCES;
+	if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
+		goto out;
+
+	h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
+				   au_sbr(dentry->d_sb, bindex));
+	err = -EIO;
+	if (IS_ERR(h_latest))
+		goto out;
+	if (h_latest == h_dentry)
+		err = 0;
+	dput(h_latest);
+
+ out:
+	return err;
+}
+
+/*
+ * decide the branch where we operate for @dentry. the branch index will be set
+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
+ * dir for reverting.
+ * when a new whiteout is necessary, create it.
+ */
+static struct dentry*
+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
+		    struct au_dtime *dt, struct au_pin *pin)
+{
+	struct dentry *wh_dentry;
+	struct super_block *sb;
+	struct path h_path;
+	int err, need_wh;
+	unsigned int udba;
+	aufs_bindex_t bcpup;
+
+	need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
+	wh_dentry = ERR_PTR(need_wh);
+	if (unlikely(need_wh < 0))
+		goto out;
+
+	sb = dentry->d_sb;
+	udba = au_opt_udba(sb);
+	bcpup = *rbcpup;
+	err = au_pin(pin, dentry, bcpup, udba,
+		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+	wh_dentry = ERR_PTR(err);
+	if (unlikely(err))
+		goto out;
+
+	h_path.dentry = au_pinned_h_parent(pin);
+	if (udba != AuOpt_UDBA_NONE
+	    && au_dbstart(dentry) == bcpup) {
+		err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
+		wh_dentry = ERR_PTR(err);
+		if (unlikely(err))
+			goto out_unpin;
+	}
+
+	h_path.mnt = au_sbr_mnt(sb, bcpup);
+	au_dtime_store(dt, au_pinned_parent(pin), &h_path);
+	wh_dentry = NULL;
+	if (!need_wh)
+		goto out; /* success, no need to create whiteout */
+
+	wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
+	if (!IS_ERR(wh_dentry))
+		goto out; /* success */
+	/* returns with the parent is locked and wh_dentry is dget-ed */
+
+ out_unpin:
+	au_unpin(pin);
+ out:
+	return wh_dentry;
+}
+
+/*
+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
+ * in order to be revertible and save time for removing many child whiteouts
+ * under the dir.
+ * returns 1 when there are too many child whiteout and caller should remove
+ * them asynchronously. returns 0 when the number of children is enough small to
+ * remove now or the branch fs is a remote fs.
+ * otherwise return an error.
+ */
+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
+			   struct au_nhash *whlist, struct inode *dir)
+{
+	int rmdir_later, err, dirwh;
+	struct dentry *h_dentry;
+	struct super_block *sb;
+
+	sb = dentry->d_sb;
+	SiMustAnyLock(sb);
+	h_dentry = au_h_dptr(dentry, bindex);
+	err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
+	if (unlikely(err))
+		goto out;
+
+	/* stop monitoring */
+	au_hin_free(au_hi(dentry->d_inode, bindex));
+
+	if (!au_test_fs_remote(h_dentry->d_sb)) {
+		dirwh = au_sbi(sb)->si_dirwh;
+		rmdir_later = (dirwh <= 1);
+		if (!rmdir_later)
+			rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
+							      dirwh);
+		if (rmdir_later)
+			return rmdir_later;
+	}
+
+	err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
+	if (unlikely(err)) {
+		AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
+			AuDLNPair(h_dentry), bindex, err);
+		err = 0;
+	}
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+/*
+ * final procedure for deleting a entry.
+ * maintain dentry and iattr.
+ */
+static void epilog(struct inode *dir, struct dentry *dentry,
+		   aufs_bindex_t bindex)
+{
+	struct inode *inode;
+
+	inode = dentry->d_inode;
+	d_drop(dentry);
+	inode->i_ctime = dir->i_ctime;
+
+	if (atomic_read(&dentry->d_count) == 1) {
+		au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
+		au_update_dbstart(dentry);
+	}
+	if (au_ibstart(dir) == bindex)
+		au_cpup_attr_timesizes(dir);
+	dir->i_version++;
+}
+
+/*
+ * when an error happened, remove the created whiteout and revert everything.
+ */
+static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
+		     struct dentry *wh_dentry, struct dentry *dentry,
+		     struct au_dtime *dt)
+{
+	int rerr;
+	struct path h_path = {
+		.dentry	= wh_dentry,
+		.mnt	= au_sbr_mnt(dir->i_sb, bwh)
+	};
+
+	rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
+	if (!rerr) {
+		au_set_dbwh(dentry, bwh);
+		au_dtime_revert(dt);
+		return 0;
+	}
+
+	AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
+		AuDLNPair(dentry), err, rerr);
+	return -EIO;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int aufs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int err;
+	aufs_bindex_t bwh, bindex, bstart;
+	struct au_dtime dt;
+	struct au_pin pin;
+	struct path h_path;
+	struct inode *inode, *h_dir;
+	struct dentry *parent, *wh_dentry;
+
+	IMustLock(dir);
+	inode = dentry->d_inode;
+	if (unlikely(!inode))
+		return -ENOENT; /* possible? */
+	IMustLock(inode);
+
+	aufs_read_lock(dentry, AuLock_DW);
+	parent = dentry->d_parent; /* dir inode is locked */
+	di_write_lock_parent(parent);
+
+	bstart = au_dbstart(dentry);
+	bwh = au_dbwh(dentry);
+	bindex = -1;
+	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out;
+
+	h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
+	h_path.dentry = au_h_dptr(dentry, bstart);
+	dget(h_path.dentry);
+	if (bindex == bstart) {
+		h_dir = au_pinned_h_dir(&pin);
+		err = vfsub_unlink(h_dir, &h_path, /*force*/0);
+	} else {
+		/* dir inode is locked */
+		h_dir = wh_dentry->d_parent->d_inode;
+		IMustLock(h_dir);
+		err = 0;
+	}
+
+	if (!err) {
+		drop_nlink(inode);
+		epilog(dir, dentry, bindex);
+
+		/* update target timestamps */
+		if (bindex == bstart) {
+			vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
+			inode->i_ctime = h_path.dentry->d_inode->i_ctime;
+		} else
+			/* todo: this timestamp may be reverted later */
+			inode->i_ctime = h_dir->i_ctime;
+		goto out_unlock; /* success */
+	}
+
+	/* revert */
+	if (wh_dentry) {
+		int rerr;
+
+		rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
+		if (rerr)
+			err = rerr;
+	}
+
+ out_unlock:
+	au_unpin(&pin);
+	dput(wh_dentry);
+	dput(h_path.dentry);
+ out:
+	di_write_unlock(parent);
+	aufs_read_unlock(dentry, AuLock_DW);
+	return err;
+}
+
+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int err, rmdir_later;
+	aufs_bindex_t bwh, bindex, bstart;
+	struct au_dtime dt;
+	struct au_pin pin;
+	struct inode *inode;
+	struct dentry *parent, *wh_dentry, *h_dentry;
+	struct au_whtmp_rmdir *args;
+
+	IMustLock(dir);
+	inode = dentry->d_inode;
+	err = -ENOENT; /* possible? */
+	if (unlikely(!inode))
+		goto out;
+	IMustLock(inode);
+
+	aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
+	err = -ENOMEM;
+	args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
+	if (unlikely(!args))
+		goto out_unlock;
+
+	parent = dentry->d_parent; /* dir inode is locked */
+	di_write_lock_parent(parent);
+	err = au_test_empty(dentry, &args->whlist);
+	if (unlikely(err))
+		goto out_args;
+
+	bstart = au_dbstart(dentry);
+	bwh = au_dbwh(dentry);
+	bindex = -1;
+	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out_args;
+
+	h_dentry = au_h_dptr(dentry, bstart);
+	dget(h_dentry);
+	rmdir_later = 0;
+	if (bindex == bstart) {
+		err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
+		if (err > 0) {
+			rmdir_later = err;
+			err = 0;
+		}
+	} else {
+		/* stop monitoring */
+		au_hin_free(au_hi(inode, bstart));
+
+		/* dir inode is locked */
+		IMustLock(wh_dentry->d_parent->d_inode);
+		err = 0;
+	}
+
+	if (!err) {
+		clear_nlink(inode);
+		au_set_dbdiropq(dentry, -1);
+		epilog(dir, dentry, bindex);
+
+		if (rmdir_later) {
+			au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
+			args = NULL;
+		}
+
+		goto out_unpin; /* success */
+	}
+
+	/* revert */
+	AuLabel(revert);
+	if (wh_dentry) {
+		int rerr;
+
+		rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
+		if (rerr)
+			err = rerr;
+	}
+
+ out_unpin:
+	au_unpin(&pin);
+	dput(wh_dentry);
+	dput(h_dentry);
+ out_args:
+	di_write_unlock(parent);
+	if (args)
+		au_whtmp_rmdir_free(args);
+ out_unlock:
+	aufs_read_unlock(dentry, AuLock_DW);
+ out:
+	AuTraceErr(err);
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/vfsub.c
+++ linux-ec2-2.6.32/ubuntu/aufs/vfsub.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * sub-routines for VFS
+ */
+
+#include <linux/ima.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+#include <linux/splice.h>
+#include <linux/uaccess.h>
+#include "aufs.h"
+
+int vfsub_update_h_iattr(struct path *h_path, int *did)
+{
+	int err;
+	struct kstat st;
+	struct super_block *h_sb;
+
+	/* for remote fs, leave work for its getattr or d_revalidate */
+	/* for bad i_attr fs, handle them in aufs_getattr() */
+	/* still some fs may acquire i_mutex. we need to skip them */
+	err = 0;
+	if (!did)
+		did = &err;
+	h_sb = h_path->dentry->d_sb;
+	*did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
+	if (*did)
+		err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct file *vfsub_dentry_open(struct path *path, int flags,
+			       const struct cred *cred)
+{
+	struct file *file;
+
+	file = dentry_open(path->dentry, path->mnt, flags, cred);
+	if (IS_ERR(file))
+		return file;
+	/* as NFSD does, just call ima_..._get() simply after dentry_open */
+	ima_counts_get(file);
+	return file;
+}
+
+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
+{
+	struct file *file;
+
+	/* lockdep_off(); */
+	file = filp_open(path, oflags, mode);
+	/* lockdep_on(); */
+	if (IS_ERR(file))
+		goto out;
+	vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+
+ out:
+	return file;
+}
+
+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
+{
+	int err;
+
+	/* lockdep_off(); */
+	err = kern_path(name, flags, path);
+	/* lockdep_on(); */
+	if (!err && path->dentry->d_inode)
+		vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
+				    int len)
+{
+	struct path path = {
+		.mnt = NULL
+	};
+
+	/* VFS checks it too, but by WARN_ON_ONCE() */
+	IMustLock(parent->d_inode);
+
+	path.dentry = lookup_one_len(name, parent, len);
+	if (IS_ERR(path.dentry))
+		goto out;
+	if (path.dentry->d_inode)
+		vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
+
+ out:
+	AuTraceErrPtr(path.dentry);
+	return path.dentry;
+}
+
+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
+{
+	struct path path = {
+		.mnt = nd->path.mnt
+	};
+
+	IMustLock(nd->path.dentry->d_inode);
+
+	path.dentry = lookup_hash(nd);
+	if (!IS_ERR(path.dentry) && path.dentry->d_inode)
+		vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
+
+	AuTraceErrPtr(path.dentry);
+	return path.dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
+				 struct dentry *d2, struct au_hinode *hdir2)
+{
+	struct dentry *d;
+
+	lockdep_off();
+	d = lock_rename(d1, d2);
+	lockdep_on();
+	au_hin_suspend(hdir1);
+	if (hdir1 != hdir2)
+		au_hin_suspend(hdir2);
+
+	return d;
+}
+
+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
+			 struct dentry *d2, struct au_hinode *hdir2)
+{
+	au_hin_resume(hdir1);
+	if (hdir1 != hdir2)
+		au_hin_resume(hdir2);
+	lockdep_off();
+	unlock_rename(d1, d2);
+	lockdep_on();
+}
+
+/* ---------------------------------------------------------------------- */
+
+int vfsub_create(struct inode *dir, struct path *path, int mode)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_mknod(path, path->dentry, mode, 0);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	if (au_test_fs_null_nd(dir->i_sb))
+		err = vfs_create(dir, path->dentry, mode, NULL);
+	else {
+		struct nameidata h_nd;
+
+		memset(&h_nd, 0, sizeof(h_nd));
+		h_nd.flags = LOOKUP_CREATE;
+		h_nd.intent.open.flags = O_CREAT
+			| vfsub_fmode_to_uint(FMODE_READ);
+		h_nd.intent.open.create_mode = mode;
+		h_nd.path.dentry = path->dentry->d_parent;
+		h_nd.path.mnt = path->mnt;
+		path_get(&h_nd.path);
+		err = vfs_create(dir, path->dentry, mode, &h_nd);
+		path_put(&h_nd.path);
+	}
+
+	if (!err) {
+		struct path tmp = *path;
+		int did;
+
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = path->dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_symlink(path, path->dentry, symname);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	err = vfs_symlink(dir, path->dentry, symname);
+	if (!err) {
+		struct path tmp = *path;
+		int did;
+
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = path->dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_mknod(path, path->dentry, mode, dev);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	err = vfs_mknod(dir, path->dentry, mode, dev);
+	if (!err) {
+		struct path tmp = *path;
+		int did;
+
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = path->dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+static int au_test_nlink(struct inode *inode)
+{
+	const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
+
+	if (!au_test_fs_no_limit_nlink(inode->i_sb)
+	    || inode->i_nlink < link_max)
+		return 0;
+	return -EMLINK;
+}
+
+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	err = au_test_nlink(src_dentry->d_inode);
+	if (unlikely(err))
+		return err;
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_link(src_dentry, path, path->dentry);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	/* lockdep_off(); */
+	err = vfs_link(src_dentry, dir, path->dentry);
+	/* lockdep_on(); */
+	if (!err) {
+		struct path tmp = *path;
+		int did;
+
+		/* fuse has different memory inode for the same inumber */
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = path->dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+			tmp.dentry = src_dentry;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
+		 struct inode *dir, struct path *path)
+{
+	int err;
+	struct path tmp = {
+		.mnt	= path->mnt
+	};
+	struct dentry *d;
+
+	IMustLock(dir);
+	IMustLock(src_dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	tmp.dentry = src_dentry->d_parent;
+	err = security_path_rename(&tmp, src_dentry, path, path->dentry);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	/* lockdep_off(); */
+	err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
+	/* lockdep_on(); */
+	if (!err) {
+		int did;
+
+		tmp.dentry = d->d_parent;
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = src_dentry;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+			tmp.dentry = src_dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_mkdir(path, path->dentry, mode);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	err = vfs_mkdir(dir, path->dentry, mode);
+	if (!err) {
+		struct path tmp = *path;
+		int did;
+
+		vfsub_update_h_iattr(&tmp, &did);
+		if (did) {
+			tmp.dentry = path->dentry->d_parent;
+			vfsub_update_h_iattr(&tmp, /*did*/NULL);
+		}
+		/*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+int vfsub_rmdir(struct inode *dir, struct path *path)
+{
+	int err;
+	struct dentry *d;
+
+	IMustLock(dir);
+
+	d = path->dentry;
+	path->dentry = d->d_parent;
+	err = security_path_rmdir(path, path->dentry);
+	path->dentry = d;
+	if (unlikely(err))
+		goto out;
+
+	/* lockdep_off(); */
+	err = vfs_rmdir(dir, path->dentry);
+	/* lockdep_on(); */
+	if (!err) {
+		struct path tmp = {
+			.dentry	= path->dentry->d_parent,
+			.mnt	= path->mnt
+		};
+
+		vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
+	}
+
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
+		     loff_t *ppos)
+{
+	ssize_t err;
+
+	err = vfs_read(file, ubuf, count, ppos);
+	if (err >= 0)
+		vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+/* todo: kernel_read()? */
+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
+		     loff_t *ppos)
+{
+	ssize_t err;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
+	set_fs(oldfs);
+	return err;
+}
+
+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
+		      loff_t *ppos)
+{
+	ssize_t err;
+
+	/* lockdep_off(); */
+	err = vfs_write(file, ubuf, count, ppos);
+	/* lockdep_on(); */
+	if (err >= 0)
+		vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
+{
+	ssize_t err;
+	mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
+	set_fs(oldfs);
+	return err;
+}
+
+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
+{
+	int err;
+
+	/* lockdep_off(); */
+	err = vfs_readdir(file, filldir, arg);
+	/* lockdep_on(); */
+	if (err >= 0)
+		vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+long vfsub_splice_to(struct file *in, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t len,
+		     unsigned int flags)
+{
+	long err;
+
+	/* lockdep_off(); */
+	err = do_splice_to(in, ppos, pipe, len, flags);
+	/* lockdep_on(); */
+	if (err >= 0)
+		vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
+		       loff_t *ppos, size_t len, unsigned int flags)
+{
+	long err;
+
+	/* lockdep_off(); */
+	err = do_splice_from(pipe, out, ppos, len, flags);
+	/* lockdep_on(); */
+	if (err >= 0)
+		vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
+	return err;
+}
+
+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
+		struct file *h_file)
+{
+	int err;
+	struct inode *h_inode;
+
+	h_inode = h_path->dentry->d_inode;
+	if (!h_file) {
+		err = mnt_want_write(h_path->mnt);
+		if (err)
+			goto out;
+		err = inode_permission(h_inode, MAY_WRITE);
+		if (err)
+			goto out_mnt;
+		err = get_write_access(h_inode);
+		if (err)
+			goto out_mnt;
+		err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
+		if (err)
+			goto out_inode;
+	}
+
+	err = locks_verify_truncate(h_inode, h_file, length);
+	if (!err)
+		err = security_path_truncate(h_path, length, attr);
+	if (!err) {
+		/* lockdep_off(); */
+		err = do_truncate(h_path->dentry, length, attr, h_file);
+		/* lockdep_on(); */
+	}
+
+ out_inode:
+	if (!h_file)
+		put_write_access(h_inode);
+ out_mnt:
+	if (!h_file)
+		mnt_drop_write(h_path->mnt);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct au_vfsub_mkdir_args {
+	int *errp;
+	struct inode *dir;
+	struct path *path;
+	int mode;
+};
+
+static void au_call_vfsub_mkdir(void *args)
+{
+	struct au_vfsub_mkdir_args *a = args;
+	*a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
+}
+
+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
+{
+	int err, do_sio, wkq_err;
+
+	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
+	if (!do_sio)
+		err = vfsub_mkdir(dir, path, mode);
+	else {
+		struct au_vfsub_mkdir_args args = {
+			.errp	= &err,
+			.dir	= dir,
+			.path	= path,
+			.mode	= mode
+		};
+		wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	return err;
+}
+
+struct au_vfsub_rmdir_args {
+	int *errp;
+	struct inode *dir;
+	struct path *path;
+};
+
+static void au_call_vfsub_rmdir(void *args)
+{
+	struct au_vfsub_rmdir_args *a = args;
+	*a->errp = vfsub_rmdir(a->dir, a->path);
+}
+
+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
+{
+	int err, do_sio, wkq_err;
+
+	do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
+	if (!do_sio)
+		err = vfsub_rmdir(dir, path);
+	else {
+		struct au_vfsub_rmdir_args args = {
+			.errp	= &err,
+			.dir	= dir,
+			.path	= path
+		};
+		wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct notify_change_args {
+	int *errp;
+	struct path *path;
+	struct iattr *ia;
+};
+
+static void call_notify_change(void *args)
+{
+	struct notify_change_args *a = args;
+	struct inode *h_inode;
+
+	h_inode = a->path->dentry->d_inode;
+	IMustLock(h_inode);
+
+	*a->errp = -EPERM;
+	if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
+		/* lockdep_off(); */
+		*a->errp = notify_change(a->path->dentry, a->ia);
+		/* lockdep_on(); */
+		if (!*a->errp)
+			vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
+	}
+	AuTraceErr(*a->errp);
+}
+
+int vfsub_notify_change(struct path *path, struct iattr *ia)
+{
+	int err;
+	struct notify_change_args args = {
+		.errp	= &err,
+		.path	= path,
+		.ia	= ia
+	};
+
+	call_notify_change(&args);
+
+	return err;
+}
+
+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
+{
+	int err, wkq_err;
+	struct notify_change_args args = {
+		.errp	= &err,
+		.path	= path,
+		.ia	= ia
+	};
+
+	wkq_err = au_wkq_wait(call_notify_change, &args);
+	if (unlikely(wkq_err))
+		err = wkq_err;
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct unlink_args {
+	int *errp;
+	struct inode *dir;
+	struct path *path;
+};
+
+static void call_unlink(void *args)
+{
+	struct unlink_args *a = args;
+	struct dentry *d = a->path->dentry;
+	struct inode *h_inode;
+	const int stop_sillyrename = (au_test_nfs(d->d_sb)
+				      && atomic_read(&d->d_count) == 1);
+
+	IMustLock(a->dir);
+
+	a->path->dentry = d->d_parent;
+	*a->errp = security_path_unlink(a->path, d);
+	a->path->dentry = d;
+	if (unlikely(*a->errp))
+		return;
+
+	if (!stop_sillyrename)
+		dget(d);
+	h_inode = d->d_inode;
+	if (h_inode)
+		atomic_inc(&h_inode->i_count);
+
+	/* lockdep_off(); */
+	*a->errp = vfs_unlink(a->dir, d);
+	/* lockdep_on(); */
+	if (!*a->errp) {
+		struct path tmp = {
+			.dentry = d->d_parent,
+			.mnt	= a->path->mnt
+		};
+		vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
+	}
+
+	if (!stop_sillyrename)
+		dput(d);
+	if (h_inode)
+		iput(h_inode);
+
+	AuTraceErr(*a->errp);
+}
+
+/*
+ * @dir: must be locked.
+ * @dentry: target dentry.
+ */
+int vfsub_unlink(struct inode *dir, struct path *path, int force)
+{
+	int err;
+	struct unlink_args args = {
+		.errp	= &err,
+		.dir	= dir,
+		.path	= path
+	};
+
+	if (!force)
+		call_unlink(&args);
+	else {
+		int wkq_err;
+
+		wkq_err = au_wkq_wait(call_unlink, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	}
+
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/sbinfo.c
+++ linux-ec2-2.6.32/ubuntu/aufs/sbinfo.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * superblock private data
+ */
+
+#include "aufs.h"
+
+/*
+ * they are necessary regardless sysfs is disabled.
+ */
+void au_si_free(struct kobject *kobj)
+{
+	struct au_sbinfo *sbinfo;
+	struct super_block *sb;
+
+	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
+	AuDebugOn(!list_empty(&sbinfo->si_plink.head));
+
+	sb = sbinfo->si_sb;
+	si_write_lock(sb);
+	au_xino_clr(sb);
+	au_br_free(sbinfo);
+	kfree(sbinfo->si_branch);
+	mutex_destroy(&sbinfo->si_xib_mtx);
+	si_write_unlock(sb);
+	AuRwDestroy(&sbinfo->si_rwsem);
+
+	kfree(sbinfo);
+}
+
+int au_si_alloc(struct super_block *sb)
+{
+	int err;
+	struct au_sbinfo *sbinfo;
+
+	err = -ENOMEM;
+	sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
+	if (unlikely(!sbinfo))
+		goto out;
+
+	/* will be reallocated separately */
+	sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
+	if (unlikely(!sbinfo->si_branch))
+		goto out_sbinfo;
+
+	memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
+	err = sysaufs_si_init(sbinfo);
+	if (unlikely(err))
+		goto out_br;
+
+	au_nwt_init(&sbinfo->si_nowait);
+	au_rw_init_wlock(&sbinfo->si_rwsem);
+	sbinfo->si_generation = 0;
+	sbinfo->au_si_status = 0;
+	sbinfo->si_bend = -1;
+	sbinfo->si_last_br_id = 0;
+
+	sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
+	sbinfo->si_wbr_create = AuWbrCreate_Def;
+	sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
+	sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
+
+	sbinfo->si_mntflags = AuOpt_Def;
+
+	sbinfo->si_xread = NULL;
+	sbinfo->si_xwrite = NULL;
+	sbinfo->si_xib = NULL;
+	mutex_init(&sbinfo->si_xib_mtx);
+	sbinfo->si_xib_buf = NULL;
+	sbinfo->si_xino_brid = -1;
+	/* leave si_xib_last_pindex and si_xib_next_bit */
+
+	sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
+	sbinfo->si_rdblk = AUFS_RDBLK_DEF;
+	sbinfo->si_rdhash = AUFS_RDHASH_DEF;
+	sbinfo->si_dirwh = AUFS_DIRWH_DEF;
+
+	au_spl_init(&sbinfo->si_plink);
+	init_waitqueue_head(&sbinfo->si_plink_wq);
+
+	/* leave other members for sysaufs and si_mnt. */
+	sbinfo->si_sb = sb;
+	sb->s_fs_info = sbinfo;
+	au_debug_sbinfo_init(sbinfo);
+	return 0; /* success */
+
+ out_br:
+	kfree(sbinfo->si_branch);
+ out_sbinfo:
+	kfree(sbinfo);
+ out:
+	return err;
+}
+
+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
+{
+	int err, sz;
+	struct au_branch **brp;
+
+	AuRwMustWriteLock(&sbinfo->si_rwsem);
+
+	err = -ENOMEM;
+	sz = sizeof(*brp) * (sbinfo->si_bend + 1);
+	if (unlikely(!sz))
+		sz = sizeof(*brp);
+	brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
+	if (brp) {
+		sbinfo->si_branch = brp;
+		err = 0;
+	}
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+unsigned int au_sigen_inc(struct super_block *sb)
+{
+	unsigned int gen;
+
+	SiMustWriteLock(sb);
+
+	gen = ++au_sbi(sb)->si_generation;
+	au_update_digen(sb->s_root);
+	au_update_iigen(sb->s_root->d_inode);
+	sb->s_root->d_inode->i_version++;
+	return gen;
+}
+
+aufs_bindex_t au_new_br_id(struct super_block *sb)
+{
+	aufs_bindex_t br_id;
+	int i;
+	struct au_sbinfo *sbinfo;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
+		br_id = ++sbinfo->si_last_br_id;
+		if (br_id && au_br_index(sb, br_id) < 0)
+			return br_id;
+	}
+
+	return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* dentry and super_block lock. call at entry point */
+void aufs_read_lock(struct dentry *dentry, int flags)
+{
+	si_read_lock(dentry->d_sb, flags);
+	if (au_ftest_lock(flags, DW))
+		di_write_lock_child(dentry);
+	else
+		di_read_lock_child(dentry, flags);
+}
+
+void aufs_read_unlock(struct dentry *dentry, int flags)
+{
+	if (au_ftest_lock(flags, DW))
+		di_write_unlock(dentry);
+	else
+		di_read_unlock(dentry, flags);
+	si_read_unlock(dentry->d_sb);
+}
+
+void aufs_write_lock(struct dentry *dentry)
+{
+	si_write_lock(dentry->d_sb);
+	di_write_lock_child(dentry);
+}
+
+void aufs_write_unlock(struct dentry *dentry)
+{
+	di_write_unlock(dentry);
+	si_write_unlock(dentry->d_sb);
+}
+
+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
+{
+	si_read_lock(d1->d_sb, flags);
+	di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
+}
+
+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
+{
+	di_write_unlock2(d1, d2);
+	si_read_unlock(d1->d_sb);
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/inode.c
+++ linux-ec2-2.6.32/ubuntu/aufs/inode.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode functions
+ */
+
+#include "aufs.h"
+
+struct inode *au_igrab(struct inode *inode)
+{
+	if (inode) {
+		AuDebugOn(!atomic_read(&inode->i_count));
+		atomic_inc_return(&inode->i_count);
+	}
+	return inode;
+}
+
+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
+{
+	au_cpup_attr_all(inode, /*force*/0);
+	au_update_iigen(inode);
+	if (do_version)
+		inode->i_version++;
+}
+
+int au_refresh_hinode_self(struct inode *inode, int do_attr)
+{
+	int err;
+	aufs_bindex_t bindex, new_bindex;
+	unsigned char update;
+	struct inode *first;
+	struct au_hinode *p, *q, tmp;
+	struct super_block *sb;
+	struct au_iinfo *iinfo;
+
+	IiMustWriteLock(inode);
+
+	update = 0;
+	sb = inode->i_sb;
+	iinfo = au_ii(inode);
+	err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
+	if (unlikely(err))
+		goto out;
+
+	p = iinfo->ii_hinode + iinfo->ii_bstart;
+	first = p->hi_inode;
+	err = 0;
+	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
+	     bindex++, p++) {
+		if (!p->hi_inode)
+			continue;
+
+		new_bindex = au_br_index(sb, p->hi_id);
+		if (new_bindex == bindex)
+			continue;
+
+		if (new_bindex < 0) {
+			update++;
+			au_hiput(p);
+			p->hi_inode = NULL;
+			continue;
+		}
+
+		if (new_bindex < iinfo->ii_bstart)
+			iinfo->ii_bstart = new_bindex;
+		if (iinfo->ii_bend < new_bindex)
+			iinfo->ii_bend = new_bindex;
+		/* swap two lower inode, and loop again */
+		q = iinfo->ii_hinode + new_bindex;
+		tmp = *q;
+		*q = *p;
+		*p = tmp;
+		if (tmp.hi_inode) {
+			bindex--;
+			p--;
+		}
+	}
+	au_update_brange(inode, /*do_put_zero*/0);
+	if (do_attr)
+		au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
+
+ out:
+	return err;
+}
+
+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
+{
+	int err, update;
+	unsigned int flags;
+	aufs_bindex_t bindex, bend;
+	unsigned char isdir;
+	struct inode *first;
+	struct au_hinode *p;
+	struct au_iinfo *iinfo;
+
+	err = au_refresh_hinode_self(inode, /*do_attr*/0);
+	if (unlikely(err))
+		goto out;
+
+	update = 0;
+	iinfo = au_ii(inode);
+	p = iinfo->ii_hinode + iinfo->ii_bstart;
+	first = p->hi_inode;
+	isdir = S_ISDIR(inode->i_mode);
+	flags = au_hi_flags(inode, isdir);
+	bend = au_dbend(dentry);
+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
+		struct inode *h_i;
+		struct dentry *h_d;
+
+		h_d = au_h_dptr(dentry, bindex);
+		if (!h_d || !h_d->d_inode)
+			continue;
+
+		if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
+			h_i = au_h_iptr(inode, bindex);
+			if (h_i) {
+				if (h_i == h_d->d_inode)
+					continue;
+				err = -EIO;
+				break;
+			}
+		}
+		if (bindex < iinfo->ii_bstart)
+			iinfo->ii_bstart = bindex;
+		if (iinfo->ii_bend < bindex)
+			iinfo->ii_bend = bindex;
+		au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
+		update = 1;
+	}
+	au_update_brange(inode, /*do_put_zero*/0);
+
+	if (unlikely(err))
+		goto out;
+
+	au_refresh_hinode_attr(inode, update && isdir);
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int set_inode(struct inode *inode, struct dentry *dentry)
+{
+	int err;
+	unsigned int flags;
+	umode_t mode;
+	aufs_bindex_t bindex, bstart, btail;
+	unsigned char isdir;
+	struct dentry *h_dentry;
+	struct inode *h_inode;
+	struct au_iinfo *iinfo;
+
+	IiMustWriteLock(inode);
+
+	err = 0;
+	isdir = 0;
+	bstart = au_dbstart(dentry);
+	h_inode = au_h_dptr(dentry, bstart)->d_inode;
+	mode = h_inode->i_mode;
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+		btail = au_dbtail(dentry);
+		inode->i_op = &aufs_iop;
+		inode->i_fop = &aufs_file_fop;
+		inode->i_mapping->a_ops = &aufs_aop;
+		break;
+	case S_IFDIR:
+		isdir = 1;
+		btail = au_dbtaildir(dentry);
+		inode->i_op = &aufs_dir_iop;
+		inode->i_fop = &aufs_dir_fop;
+		break;
+	case S_IFLNK:
+		btail = au_dbtail(dentry);
+		inode->i_op = &aufs_symlink_iop;
+		break;
+	case S_IFBLK:
+	case S_IFCHR:
+	case S_IFIFO:
+	case S_IFSOCK:
+		btail = au_dbtail(dentry);
+		inode->i_op = &aufs_iop;
+		init_special_inode(inode, mode, h_inode->i_rdev);
+		break;
+	default:
+		AuIOErr("Unknown file type 0%o\n", mode);
+		err = -EIO;
+		goto out;
+	}
+
+	/* do not set inotify for whiteouted dirs (SHWH mode) */
+	flags = au_hi_flags(inode, isdir);
+	if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
+	    && au_ftest_hi(flags, HINOTIFY)
+	    && dentry->d_name.len > AUFS_WH_PFX_LEN
+	    && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
+		au_fclr_hi(flags, HINOTIFY);
+	iinfo = au_ii(inode);
+	iinfo->ii_bstart = bstart;
+	iinfo->ii_bend = btail;
+	for (bindex = bstart; bindex <= btail; bindex++) {
+		h_dentry = au_h_dptr(dentry, bindex);
+		if (h_dentry)
+			au_set_h_iptr(inode, bindex,
+				      au_igrab(h_dentry->d_inode), flags);
+	}
+	au_cpup_attr_all(inode, /*force*/1);
+
+ out:
+	return err;
+}
+
+/* successful returns with iinfo write_locked */
+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	struct inode *h_inode, *h_dinode;
+
+	*matched = 0;
+
+	/*
+	 * before this function, if aufs got any iinfo lock, it must be only
+	 * one, the parent dir.
+	 * it can happen by UDBA and the obsoleted inode number.
+	 */
+	err = -EIO;
+	if (unlikely(inode->i_ino == parent_ino(dentry)))
+		goto out;
+
+	err = 0;
+	ii_write_lock_new_child(inode);
+	h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
+	bend = au_ibend(inode);
+	for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
+		h_inode = au_h_iptr(inode, bindex);
+		if (h_inode && h_inode == h_dinode) {
+			*matched = 1;
+			err = 0;
+			if (au_iigen(inode) != au_digen(dentry))
+				err = au_refresh_hinode(inode, dentry);
+			break;
+		}
+	}
+
+	if (unlikely(err))
+		ii_write_unlock(inode);
+ out:
+	return err;
+}
+
+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+	   unsigned int d_type, ino_t *ino)
+{
+	int err;
+	struct mutex *mtx;
+	const int isdir = (d_type == DT_DIR);
+
+	/* prevent hardlinks from race condition */
+	mtx = NULL;
+	if (!isdir) {
+		mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
+		mutex_lock(mtx);
+	}
+	err = au_xino_read(sb, bindex, h_ino, ino);
+	if (unlikely(err))
+		goto out;
+
+	if (!*ino) {
+		err = -EIO;
+		*ino = au_xino_new_ino(sb);
+		if (unlikely(!*ino))
+			goto out;
+		err = au_xino_write(sb, bindex, h_ino, *ino);
+		if (unlikely(err))
+			goto out;
+	}
+
+ out:
+	if (!isdir)
+		mutex_unlock(mtx);
+	return err;
+}
+
+/* successful returns with iinfo write_locked */
+/* todo: return with unlocked? */
+struct inode *au_new_inode(struct dentry *dentry, int must_new)
+{
+	struct inode *inode;
+	struct dentry *h_dentry;
+	struct super_block *sb;
+	ino_t h_ino, ino;
+	int err, match;
+	aufs_bindex_t bstart;
+
+	sb = dentry->d_sb;
+	bstart = au_dbstart(dentry);
+	h_dentry = au_h_dptr(dentry, bstart);
+	h_ino = h_dentry->d_inode->i_ino;
+	err = au_xino_read(sb, bstart, h_ino, &ino);
+	inode = ERR_PTR(err);
+	if (unlikely(err))
+		goto out;
+ new_ino:
+	if (!ino) {
+		ino = au_xino_new_ino(sb);
+		if (unlikely(!ino)) {
+			inode = ERR_PTR(-EIO);
+			goto out;
+		}
+	}
+
+	AuDbg("i%lu\n", (unsigned long)ino);
+	inode = au_iget_locked(sb, ino);
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		goto out;
+
+	AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
+	if (inode->i_state & I_NEW) {
+		ii_write_lock_new_child(inode);
+		err = set_inode(inode, dentry);
+		unlock_new_inode(inode);
+		if (!err)
+			goto out; /* success */
+
+		iget_failed(inode);
+		ii_write_unlock(inode);
+		goto out_iput;
+	} else if (!must_new) {
+		err = reval_inode(inode, dentry, &match);
+		if (!err)
+			goto out; /* success */
+		else if (match)
+			goto out_iput;
+	}
+
+	if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
+		AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
+			" b%d, %s, %.*s, hi%lu, i%lu.\n",
+			bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
+			(unsigned long)h_ino, (unsigned long)ino);
+	ino = 0;
+	err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
+	if (!err) {
+		iput(inode);
+		goto new_ino;
+	}
+
+ out_iput:
+	iput(inode);
+	inode = ERR_PTR(err);
+ out:
+	return inode;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
+	       struct inode *inode)
+{
+	int err;
+
+	err = au_br_rdonly(au_sbr(sb, bindex));
+
+	/* pseudo-link after flushed may happen out of bounds */
+	if (!err
+	    && inode
+	    && au_ibstart(inode) <= bindex
+	    && bindex <= au_ibend(inode)) {
+		/*
+		 * permission check is unnecessary since vfsub routine
+		 * will be called later
+		 */
+		struct inode *hi = au_h_iptr(inode, bindex);
+		if (hi)
+			err = IS_IMMUTABLE(hi) ? -EROFS : 0;
+	}
+
+	return err;
+}
+
+int au_test_h_perm(struct inode *h_inode, int mask)
+{
+	if (!current_fsuid())
+		return 0;
+	return inode_permission(h_inode, mask);
+}
+
+int au_test_h_perm_sio(struct inode *h_inode, int mask)
+{
+	if (au_test_nfs(h_inode->i_sb)
+	    && (mask & MAY_WRITE)
+	    && S_ISDIR(h_inode->i_mode))
+		mask |= MAY_READ; /* force permission check */
+	return au_test_h_perm(h_inode, mask);
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/branch.h
+++ linux-ec2-2.6.32/ubuntu/aufs/branch.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * branch filesystems and xino for them
+ */
+
+#ifndef __AUFS_BRANCH_H__
+#define __AUFS_BRANCH_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/aufs_type.h>
+#include "rwsem.h"
+#include "super.h"
+
+/* ---------------------------------------------------------------------- */
+
+/* a xino file */
+struct au_xino_file {
+	struct file		*xi_file;
+	struct mutex		xi_nondir_mtx;
+
+	/* todo: make xino files an array to support huge inode number */
+
+#ifdef CONFIG_DEBUG_FS
+	struct dentry		 *xi_dbgaufs;
+#endif
+};
+
+/* members for writable branch only */
+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
+struct au_wbr {
+	struct au_rwsem		wbr_wh_rwsem;
+	struct dentry		*wbr_wh[AuBrWh_Last];
+	atomic_t 		wbr_wh_running;
+#define wbr_whbase		wbr_wh[AuBrWh_BASE]	/* whiteout base */
+#define wbr_plink		wbr_wh[AuBrWh_PLINK]	/* pseudo-link dir */
+#define wbr_orph		wbr_wh[AuBrWh_ORPH]	/* dir for orphans */
+
+	/* mfs mode */
+	unsigned long long	wbr_bytes;
+};
+
+/* protected by superblock rwsem */
+struct au_branch {
+	struct au_xino_file	br_xino;
+
+	aufs_bindex_t		br_id;
+
+	int			br_perm;
+	struct vfsmount		*br_mnt;
+	atomic_t		br_count;
+
+	struct au_wbr		*br_wbr;
+
+	/* xino truncation */
+	blkcnt_t		br_xino_upper;	/* watermark in blocks */
+	atomic_t		br_xino_running;
+
+#ifdef CONFIG_SYSFS
+	/* an entry under sysfs per mount-point */
+	char			br_name[8];
+	struct attribute	br_attr;
+#endif
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* branch permission and attribute */
+enum {
+	AuBrPerm_RW,		/* writable, linkable wh */
+	AuBrPerm_RO,		/* readonly, no wh */
+	AuBrPerm_RR,		/* natively readonly, no wh */
+
+	AuBrPerm_RWNoLinkWH,	/* un-linkable whiteouts */
+
+	AuBrPerm_ROWH,		/* whiteout-able */
+	AuBrPerm_RRWH,		/* whiteout-able */
+
+	AuBrPerm_Last
+};
+
+static inline int au_br_writable(int brperm)
+{
+	return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
+}
+
+static inline int au_br_whable(int brperm)
+{
+	return brperm == AuBrPerm_RW
+		|| brperm == AuBrPerm_ROWH
+		|| brperm == AuBrPerm_RRWH;
+}
+
+static inline int au_br_rdonly(struct au_branch *br)
+{
+	return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
+		|| !au_br_writable(br->br_perm))
+		? -EROFS : 0;
+}
+
+static inline int au_br_hinotifyable(int brperm __maybe_unused)
+{
+#ifdef CONFIG_AUFS_HINOTIFY
+	return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
+#else
+	return 0;
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* branch.c */
+struct au_sbinfo;
+void au_br_free(struct au_sbinfo *sinfo);
+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
+struct au_opt_add;
+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
+struct au_opt_del;
+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
+struct au_opt_mod;
+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
+	      int *do_update);
+
+/* xino.c */
+static const loff_t au_loff_max = LLONG_MAX;
+
+int au_xib_trunc(struct super_block *sb);
+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
+		   loff_t *pos);
+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
+		    loff_t *pos);
+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
+ino_t au_xino_new_ino(struct super_block *sb);
+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		   ino_t ino);
+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		  ino_t ino);
+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+		 ino_t *ino);
+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
+	       struct file *base_file, int do_test);
+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
+
+struct au_opt_xino;
+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
+void au_xino_clr(struct super_block *sb);
+struct file *au_xino_def(struct super_block *sb);
+int au_xino_path(struct seq_file *seq, struct file *file);
+
+/* ---------------------------------------------------------------------- */
+
+/* Superblock to branch */
+static inline
+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
+{
+	return au_sbr(sb, bindex)->br_id;
+}
+
+static inline
+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
+{
+	return au_sbr(sb, bindex)->br_mnt;
+}
+
+static inline
+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
+{
+	return au_sbr_mnt(sb, bindex)->mnt_sb;
+}
+
+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
+{
+	atomic_dec_return(&au_sbr(sb, bindex)->br_count);
+}
+
+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
+{
+	return au_sbr(sb, bindex)->br_perm;
+}
+
+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
+{
+	return au_br_whable(au_sbr_perm(sb, bindex));
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * wbr_wh_read_lock, wbr_wh_write_lock
+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
+ */
+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
+
+#define WbrWhMustNoWaiters(wbr)	AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
+#define WbrWhMustAnyLock(wbr)	AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
+#define WbrWhMustWriteLock(wbr)	AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_BRANCH_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/finfo.c
+++ linux-ec2-2.6.32/ubuntu/aufs/finfo.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * file private data
+ */
+
+#include <linux/file.h>
+#include "aufs.h"
+
+void au_hfput(struct au_hfile *hf, struct file *file)
+{
+	if (file->f_flags & vfsub_fmode_to_uint(FMODE_EXEC))
+		allow_write_access(hf->hf_file);
+	fput(hf->hf_file);
+	hf->hf_file = NULL;
+	atomic_dec_return(&hf->hf_br->br_count);
+	hf->hf_br = NULL;
+}
+
+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
+{
+	struct au_finfo *finfo = au_fi(file);
+	struct au_hfile *hf;
+
+	hf = finfo->fi_hfile + bindex;
+	if (hf->hf_file)
+		au_hfput(hf, file);
+	if (val) {
+		hf->hf_file = val;
+		hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
+	}
+}
+
+void au_update_figen(struct file *file)
+{
+	atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
+	/* smp_mb(); */ /* atomic_set */
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_finfo_fin(struct file *file)
+{
+	struct au_finfo *finfo;
+	aufs_bindex_t bindex, bend;
+
+	fi_write_lock(file);
+	bend = au_fbend(file);
+	bindex = au_fbstart(file);
+	if (bindex >= 0)
+		/*
+		 * calls fput() instead of filp_close(),
+		 * since no dnotify or lock for the lower file.
+		 */
+		for (; bindex <= bend; bindex++)
+			au_set_h_fptr(file, bindex, NULL);
+
+	finfo = au_fi(file);
+	au_dbg_verify_hf(finfo);
+	kfree(finfo->fi_hfile);
+	fi_write_unlock(file);
+	AuRwDestroy(&finfo->fi_rwsem);
+	au_cache_free_finfo(finfo);
+}
+
+int au_finfo_init(struct file *file)
+{
+	struct au_finfo *finfo;
+	struct dentry *dentry;
+
+	dentry = file->f_dentry;
+	finfo = au_cache_alloc_finfo();
+	if (unlikely(!finfo))
+		goto out;
+
+	finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
+				  sizeof(*finfo->fi_hfile), GFP_NOFS);
+	if (unlikely(!finfo->fi_hfile))
+		goto out_finfo;
+
+	au_rw_init_wlock(&finfo->fi_rwsem);
+	finfo->fi_bstart = -1;
+	finfo->fi_bend = -1;
+	atomic_set(&finfo->fi_generation, au_digen(dentry));
+	/* smp_mb(); */ /* atomic_set */
+
+	file->private_data = finfo;
+	return 0; /* success */
+
+ out_finfo:
+	au_cache_free_finfo(finfo);
+ out:
+	return -ENOMEM;
+}
+
+int au_fi_realloc(struct au_finfo *finfo, int nbr)
+{
+	int err, sz;
+	struct au_hfile *hfp;
+
+	err = -ENOMEM;
+	sz = sizeof(*hfp) * (finfo->fi_bend + 1);
+	if (!sz)
+		sz = sizeof(*hfp);
+	hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
+	if (hfp) {
+		finfo->fi_hfile = hfp;
+		err = 0;
+	}
+
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/i_op_ren.c
+++ linux-ec2-2.6.32/ubuntu/aufs/i_op_ren.c
@@ -0,0 +1,961 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode operation (rename entry)
+ * todo: this is crazy monster
+ */
+
+#include "aufs.h"
+
+enum { AuSRC, AuDST, AuSrcDst };
+enum { AuPARENT, AuCHILD, AuParentChild };
+
+#define AuRen_ISDIR	1
+#define AuRen_ISSAMEDIR	(1 << 1)
+#define AuRen_WHSRC	(1 << 2)
+#define AuRen_WHDST	(1 << 3)
+#define AuRen_MNT_WRITE	(1 << 4)
+#define AuRen_DT_DSTDIR	(1 << 5)
+#define AuRen_DIROPQ	(1 << 6)
+#define AuRen_CPUP	(1 << 7)
+#define au_ftest_ren(flags, name)	((flags) & AuRen_##name)
+#define au_fset_ren(flags, name)	{ (flags) |= AuRen_##name; }
+#define au_fclr_ren(flags, name)	{ (flags) &= ~AuRen_##name; }
+
+struct au_ren_args {
+	struct {
+		struct dentry *dentry, *h_dentry, *parent, *h_parent,
+			*wh_dentry;
+		struct inode *dir, *inode;
+		struct au_hinode *hdir;
+		struct au_dtime dt[AuParentChild];
+		aufs_bindex_t bstart;
+	} sd[AuSrcDst];
+
+#define src_dentry	sd[AuSRC].dentry
+#define src_dir		sd[AuSRC].dir
+#define src_inode	sd[AuSRC].inode
+#define src_h_dentry	sd[AuSRC].h_dentry
+#define src_parent	sd[AuSRC].parent
+#define src_h_parent	sd[AuSRC].h_parent
+#define src_wh_dentry	sd[AuSRC].wh_dentry
+#define src_hdir	sd[AuSRC].hdir
+#define src_h_dir	sd[AuSRC].hdir->hi_inode
+#define src_dt		sd[AuSRC].dt
+#define src_bstart	sd[AuSRC].bstart
+
+#define dst_dentry	sd[AuDST].dentry
+#define dst_dir		sd[AuDST].dir
+#define dst_inode	sd[AuDST].inode
+#define dst_h_dentry	sd[AuDST].h_dentry
+#define dst_parent	sd[AuDST].parent
+#define dst_h_parent	sd[AuDST].h_parent
+#define dst_wh_dentry	sd[AuDST].wh_dentry
+#define dst_hdir	sd[AuDST].hdir
+#define dst_h_dir	sd[AuDST].hdir->hi_inode
+#define dst_dt		sd[AuDST].dt
+#define dst_bstart	sd[AuDST].bstart
+
+	struct dentry *h_trap;
+	struct au_branch *br;
+	struct au_hinode *src_hinode;
+	struct path h_path;
+	struct au_nhash whlist;
+	aufs_bindex_t btgt;
+
+	unsigned int flags;
+
+	struct au_whtmp_rmdir *thargs;
+	struct dentry *h_dst;
+};
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * functions for reverting.
+ * when an error happened in a single rename systemcall, we should revert
+ * everything as if nothing happend.
+ * we don't need to revert the copied-up/down the parent dir since they are
+ * harmless.
+ */
+
+#define RevertFailure(fmt, ...) do { \
+	AuIOErr("revert failure: " fmt " (%d, %d)\n", \
+		##__VA_ARGS__, err, rerr); \
+	err = -EIO; \
+} while (0)
+
+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
+{
+	int rerr;
+
+	au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
+	rerr = au_diropq_remove(a->src_dentry, a->btgt);
+	au_hin_imtx_unlock(a->src_hinode);
+	if (rerr)
+		RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
+}
+
+
+static void au_ren_rev_rename(int err, struct au_ren_args *a)
+{
+	int rerr;
+
+	a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
+				       a->br, /*nd*/NULL);
+	rerr = PTR_ERR(a->h_path.dentry);
+	if (IS_ERR(a->h_path.dentry)) {
+		RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
+		return;
+	}
+
+	rerr = vfsub_rename(a->dst_h_dir,
+			    au_h_dptr(a->src_dentry, a->btgt),
+			    a->src_h_dir, &a->h_path);
+	d_drop(a->h_path.dentry);
+	dput(a->h_path.dentry);
+	/* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
+	if (rerr)
+		RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
+}
+
+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
+{
+	int rerr;
+
+	a->h_path.dentry = a->dst_h_dentry;
+	rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
+	au_set_h_dptr(a->src_dentry, a->btgt, NULL);
+	au_set_dbstart(a->src_dentry, a->src_bstart);
+	if (rerr)
+		RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
+}
+
+
+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
+{
+	int rerr;
+
+	a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
+				       a->br, /*nd*/NULL);
+	rerr = PTR_ERR(a->h_path.dentry);
+	if (IS_ERR(a->h_path.dentry)) {
+		RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
+		return;
+	}
+	if (a->h_path.dentry->d_inode) {
+		d_drop(a->h_path.dentry);
+		dput(a->h_path.dentry);
+		return;
+	}
+
+	rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
+	d_drop(a->h_path.dentry);
+	dput(a->h_path.dentry);
+	if (!rerr) {
+		au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
+		au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
+	} else
+		RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
+}
+
+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
+{
+	int rerr;
+
+	a->h_path.dentry = a->src_wh_dentry;
+	rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
+	if (rerr)
+		RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
+}
+
+static void au_ren_rev_drop(struct au_ren_args *a)
+{
+	struct dentry *d, *h_d;
+	int i;
+	aufs_bindex_t bend, bindex;
+
+	for (i = 0; i < AuSrcDst; i++) {
+		d = a->sd[i].dentry;
+		d_drop(d);
+		bend = au_dbend(d);
+		for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
+			h_d = au_h_dptr(d, bindex);
+			if (h_d)
+				d_drop(h_d);
+		}
+	}
+
+	au_update_dbstart(a->dst_dentry);
+	if (a->thargs)
+		d_drop(a->h_dst);
+}
+#undef RevertFailure
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * when we have to copyup the renaming entry, do it with the rename-target name
+ * in order to minimize the cost (the later actual rename is unnecessary).
+ * otherwise rename it on the target branch.
+ */
+static int au_ren_or_cpup(struct au_ren_args *a)
+{
+	int err;
+	struct dentry *d;
+
+	d = a->src_dentry;
+	if (au_dbstart(d) == a->btgt) {
+		a->h_path.dentry = a->dst_h_dentry;
+		if (au_ftest_ren(a->flags, DIROPQ)
+		    && au_dbdiropq(d) == a->btgt)
+			au_fclr_ren(a->flags, DIROPQ);
+		AuDebugOn(au_dbstart(d) != a->btgt);
+		err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
+				   a->dst_h_dir, &a->h_path);
+	} else {
+		struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
+
+		au_fset_ren(a->flags, CPUP);
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		au_set_dbstart(d, a->btgt);
+		au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
+		err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
+					 !AuCpup_DTIME, a->dst_parent);
+		if (unlikely(err)) {
+			au_set_h_dptr(d, a->btgt, NULL);
+			au_set_dbstart(d, a->src_bstart);
+		}
+		mutex_unlock(h_mtx);
+	}
+
+	return err;
+}
+
+/* cf. aufs_rmdir() */
+static int au_ren_del_whtmp(struct au_ren_args *a)
+{
+	int err;
+	struct inode *dir;
+
+	dir = a->dst_dir;
+	SiMustAnyLock(dir->i_sb);
+	if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
+				     au_sbi(dir->i_sb)->si_dirwh)
+	    || au_test_fs_remote(a->h_dst->d_sb)) {
+		err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
+		if (unlikely(err))
+			pr_warning("failed removing whtmp dir %.*s (%d), "
+				   "ignored.\n", AuDLNPair(a->h_dst), err);
+	} else {
+		au_nhash_wh_free(&a->thargs->whlist);
+		a->thargs->whlist = a->whlist;
+		a->whlist.nh_num = 0;
+		au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
+		dput(a->h_dst);
+		a->thargs = NULL;
+	}
+
+	return 0;
+}
+
+/* make it 'opaque' dir. */
+static int au_ren_diropq(struct au_ren_args *a)
+{
+	int err;
+	struct dentry *diropq;
+
+	err = 0;
+	a->src_hinode = au_hi(a->src_inode, a->btgt);
+	au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
+	diropq = au_diropq_create(a->src_dentry, a->btgt);
+	au_hin_imtx_unlock(a->src_hinode);
+	if (IS_ERR(diropq))
+		err = PTR_ERR(diropq);
+	dput(diropq);
+
+	return err;
+}
+
+static int do_rename(struct au_ren_args *a)
+{
+	int err;
+	struct dentry *d, *h_d;
+
+	/* prepare workqueue args for asynchronous rmdir */
+	h_d = a->dst_h_dentry;
+	if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
+		err = -ENOMEM;
+		a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
+		if (unlikely(!a->thargs))
+			goto out;
+		a->h_dst = dget(h_d);
+	}
+
+	/* create whiteout for src_dentry */
+	if (au_ftest_ren(a->flags, WHSRC)) {
+		a->src_wh_dentry
+			= au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
+		err = PTR_ERR(a->src_wh_dentry);
+		if (IS_ERR(a->src_wh_dentry))
+			goto out_thargs;
+	}
+
+	/* lookup whiteout for dentry */
+	if (au_ftest_ren(a->flags, WHDST)) {
+		h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
+				 a->br);
+		err = PTR_ERR(h_d);
+		if (IS_ERR(h_d))
+			goto out_whsrc;
+		if (!h_d->d_inode)
+			dput(h_d);
+		else
+			a->dst_wh_dentry = h_d;
+	}
+
+	/* rename dentry to tmpwh */
+	if (a->thargs) {
+		err = au_whtmp_ren(a->dst_h_dentry, a->br);
+		if (unlikely(err))
+			goto out_whdst;
+
+		d = a->dst_dentry;
+		au_set_h_dptr(d, a->btgt, NULL);
+		err = au_lkup_neg(d, a->btgt);
+		if (unlikely(err))
+			goto out_whtmp;
+		a->dst_h_dentry = au_h_dptr(d, a->btgt);
+	}
+
+	/* cpup src */
+	if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
+		struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
+
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
+					 !AuCpup_DTIME);
+		mutex_unlock(h_mtx);
+		if (unlikely(err))
+			goto out_whtmp;
+	}
+
+	/* rename by vfs_rename or cpup */
+	d = a->dst_dentry;
+	if (au_ftest_ren(a->flags, ISDIR)
+	    && (a->dst_wh_dentry
+		|| au_dbdiropq(d) == a->btgt
+		/* hide the lower to keep xino */
+		|| a->btgt < au_dbend(d)
+		|| au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
+		au_fset_ren(a->flags, DIROPQ);
+	err = au_ren_or_cpup(a);
+	if (unlikely(err))
+		/* leave the copied-up one */
+		goto out_whtmp;
+
+	/* make dir opaque */
+	if (au_ftest_ren(a->flags, DIROPQ)) {
+		err = au_ren_diropq(a);
+		if (unlikely(err))
+			goto out_rename;
+	}
+
+	/* update target timestamps */
+	AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
+	a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
+	vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
+	a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
+
+	/* remove whiteout for dentry */
+	if (a->dst_wh_dentry) {
+		a->h_path.dentry = a->dst_wh_dentry;
+		err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
+					  a->dst_dentry);
+		if (unlikely(err))
+			goto out_diropq;
+	}
+
+	/* remove whtmp */
+	if (a->thargs)
+		au_ren_del_whtmp(a); /* ignore this error */
+
+	err = 0;
+	goto out_success;
+
+ out_diropq:
+	if (au_ftest_ren(a->flags, DIROPQ))
+		au_ren_rev_diropq(err, a);
+ out_rename:
+	if (!au_ftest_ren(a->flags, CPUP))
+		au_ren_rev_rename(err, a);
+	else
+		au_ren_rev_cpup(err, a);
+ out_whtmp:
+	if (a->thargs)
+		au_ren_rev_whtmp(err, a);
+ out_whdst:
+	dput(a->dst_wh_dentry);
+	a->dst_wh_dentry = NULL;
+ out_whsrc:
+	if (a->src_wh_dentry)
+		au_ren_rev_whsrc(err, a);
+	au_ren_rev_drop(a);
+ out_success:
+	dput(a->src_wh_dentry);
+	dput(a->dst_wh_dentry);
+ out_thargs:
+	if (a->thargs) {
+		dput(a->h_dst);
+		au_whtmp_rmdir_free(a->thargs);
+		a->thargs = NULL;
+	}
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * test if @dentry dir can be rename destination or not.
+ * success means, it is a logically empty dir.
+ */
+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
+{
+	return au_test_empty(dentry, whlist);
+}
+
+/*
+ * test if @dentry dir can be rename source or not.
+ * if it can, return 0 and @children is filled.
+ * success means,
+ * - it is a logically empty dir.
+ * - or, it exists on writable branch and has no children including whiteouts
+ *       on the lower branch.
+ */
+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
+{
+	int err;
+	unsigned int rdhash;
+	aufs_bindex_t bstart;
+
+	bstart = au_dbstart(dentry);
+	if (bstart != btgt) {
+		struct au_nhash whlist;
+
+		SiMustAnyLock(dentry->d_sb);
+		rdhash = au_sbi(dentry->d_sb)->si_rdhash;
+		if (!rdhash)
+			rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
+							   dentry));
+		err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
+		if (unlikely(err))
+			goto out;
+		err = au_test_empty(dentry, &whlist);
+		au_nhash_wh_free(&whlist);
+		goto out;
+	}
+
+	if (bstart == au_dbtaildir(dentry))
+		return 0; /* success */
+
+	err = au_test_empty_lower(dentry);
+
+ out:
+	if (err == -ENOTEMPTY) {
+		AuWarn1("renaming dir who has child(ren) on multiple branches,"
+			" is not supported\n");
+		err = -EXDEV;
+	}
+	return err;
+}
+
+/* side effect: sets whlist and h_dentry */
+static int au_ren_may_dir(struct au_ren_args *a)
+{
+	int err;
+	unsigned int rdhash;
+	struct dentry *d;
+
+	d = a->dst_dentry;
+	SiMustAnyLock(d->d_sb);
+
+	err = 0;
+	if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
+		rdhash = au_sbi(d->d_sb)->si_rdhash;
+		if (!rdhash)
+			rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
+		err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
+		if (unlikely(err))
+			goto out;
+
+		au_set_dbstart(d, a->dst_bstart);
+		err = may_rename_dstdir(d, &a->whlist);
+		au_set_dbstart(d, a->btgt);
+	}
+	a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
+	if (unlikely(err))
+		goto out;
+
+	d = a->src_dentry;
+	a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
+	if (au_ftest_ren(a->flags, ISDIR)) {
+		err = may_rename_srcdir(d, a->btgt);
+		if (unlikely(err)) {
+			au_nhash_wh_free(&a->whlist);
+			a->whlist.nh_num = 0;
+		}
+	}
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * simple tests for rename.
+ * following the checks in vfs, plus the parent-child relationship.
+ */
+static int au_may_ren(struct au_ren_args *a)
+{
+	int err, isdir;
+	struct inode *h_inode;
+
+	if (a->src_bstart == a->btgt) {
+		err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
+				 au_ftest_ren(a->flags, ISDIR));
+		if (unlikely(err))
+			goto out;
+		err = -EINVAL;
+		if (unlikely(a->src_h_dentry == a->h_trap))
+			goto out;
+	}
+
+	err = 0;
+	if (a->dst_bstart != a->btgt)
+		goto out;
+
+	err = -EIO;
+	h_inode = a->dst_h_dentry->d_inode;
+	isdir = !!au_ftest_ren(a->flags, ISDIR);
+	if (!a->dst_dentry->d_inode) {
+		if (unlikely(h_inode))
+			goto out;
+		err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
+				 isdir);
+	} else {
+		if (unlikely(!h_inode || !h_inode->i_nlink))
+			goto out;
+		err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
+				 isdir);
+		if (unlikely(err))
+			goto out;
+		err = -ENOTEMPTY;
+		if (unlikely(a->dst_h_dentry == a->h_trap))
+			goto out;
+		err = 0;
+	}
+
+ out:
+	if (unlikely(err == -ENOENT || err == -EEXIST))
+		err = -EIO;
+	AuTraceErr(err);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * locking order
+ * (VFS)
+ * - src_dir and dir by lock_rename()
+ * - inode if exitsts
+ * (aufs)
+ * - lock all
+ *   + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
+ *     + si_read_lock
+ *     + di_write_lock2_child()
+ *       + di_write_lock_child()
+ *	   + ii_write_lock_child()
+ *       + di_write_lock_child2()
+ *	   + ii_write_lock_child2()
+ *     + src_parent and parent
+ *       + di_write_lock_parent()
+ *	   + ii_write_lock_parent()
+ *       + di_write_lock_parent2()
+ *	   + ii_write_lock_parent2()
+ *   + lower src_dir and dir by vfsub_lock_rename()
+ *   + verify the every relationships between child and parent. if any
+ *     of them failed, unlock all and return -EBUSY.
+ */
+static void au_ren_unlock(struct au_ren_args *a)
+{
+	struct super_block *sb;
+
+	sb = a->dst_dentry->d_sb;
+	if (au_ftest_ren(a->flags, MNT_WRITE))
+		mnt_drop_write(a->br->br_mnt);
+	vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
+			    a->dst_h_parent, a->dst_hdir);
+}
+
+static int au_ren_lock(struct au_ren_args *a)
+{
+	int err;
+	unsigned int udba;
+
+	err = 0;
+	a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
+	a->src_hdir = au_hi(a->src_dir, a->btgt);
+	a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
+	a->dst_hdir = au_hi(a->dst_dir, a->btgt);
+	a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
+				      a->dst_h_parent, a->dst_hdir);
+	udba = au_opt_udba(a->src_dentry->d_sb);
+	if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
+		     || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
+		err = au_busy_or_stale();
+	if (!err && au_dbstart(a->src_dentry) == a->btgt)
+		err = au_h_verify(a->src_h_dentry, udba,
+				  a->src_h_parent->d_inode, a->src_h_parent,
+				  a->br);
+	if (!err && au_dbstart(a->dst_dentry) == a->btgt)
+		err = au_h_verify(a->dst_h_dentry, udba,
+				  a->dst_h_parent->d_inode, a->dst_h_parent,
+				  a->br);
+	if (!err) {
+		err = mnt_want_write(a->br->br_mnt);
+		if (unlikely(err))
+			goto out_unlock;
+		au_fset_ren(a->flags, MNT_WRITE);
+		goto out; /* success */
+	}
+
+	err = au_busy_or_stale();
+
+ out_unlock:
+	au_ren_unlock(a);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void au_ren_refresh_dir(struct au_ren_args *a)
+{
+	struct inode *dir;
+
+	dir = a->dst_dir;
+	dir->i_version++;
+	if (au_ftest_ren(a->flags, ISDIR)) {
+		/* is this updating defined in POSIX? */
+		au_cpup_attr_timesizes(a->src_inode);
+		au_cpup_attr_nlink(dir, /*force*/1);
+		if (a->dst_inode) {
+			clear_nlink(a->dst_inode);
+			au_cpup_attr_timesizes(a->dst_inode);
+		}
+	}
+	if (au_ibstart(dir) == a->btgt)
+		au_cpup_attr_timesizes(dir);
+
+	if (au_ftest_ren(a->flags, ISSAMEDIR))
+		return;
+
+	dir = a->src_dir;
+	dir->i_version++;
+	if (au_ftest_ren(a->flags, ISDIR))
+		au_cpup_attr_nlink(dir, /*force*/1);
+	if (au_ibstart(dir) == a->btgt)
+		au_cpup_attr_timesizes(dir);
+}
+
+static void au_ren_refresh(struct au_ren_args *a)
+{
+	aufs_bindex_t bend, bindex;
+	struct dentry *d, *h_d;
+	struct inode *i, *h_i;
+	struct super_block *sb;
+
+	d = a->src_dentry;
+	au_set_dbwh(d, -1);
+	bend = au_dbend(d);
+	for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
+		h_d = au_h_dptr(d, bindex);
+		if (h_d)
+			au_set_h_dptr(d, bindex, NULL);
+	}
+	au_set_dbend(d, a->btgt);
+
+	sb = d->d_sb;
+	i = a->src_inode;
+	if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
+		return; /* success */
+
+	bend = au_ibend(i);
+	for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
+		h_i = au_h_iptr(i, bindex);
+		if (h_i) {
+			au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
+			/* ignore this error */
+			au_set_h_iptr(i, bindex, NULL, 0);
+		}
+	}
+	au_set_ibend(i, a->btgt);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* mainly for link(2) and rename(2) */
+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
+{
+	aufs_bindex_t bdiropq, bwh;
+	struct dentry *parent;
+	struct au_branch *br;
+
+	parent = dentry->d_parent;
+	IMustLock(parent->d_inode); /* dir is locked */
+
+	bdiropq = au_dbdiropq(parent);
+	bwh = au_dbwh(dentry);
+	br = au_sbr(dentry->d_sb, btgt);
+	if (au_br_rdonly(br)
+	    || (0 <= bdiropq && bdiropq < btgt)
+	    || (0 <= bwh && bwh < btgt))
+		btgt = -1;
+
+	AuDbg("btgt %d\n", btgt);
+	return btgt;
+}
+
+/* sets src_bstart, dst_bstart and btgt */
+static int au_ren_wbr(struct au_ren_args *a)
+{
+	int err;
+	struct au_wr_dir_args wr_dir_args = {
+		/* .force_btgt	= -1, */
+		.flags		= AuWrDir_ADD_ENTRY
+	};
+
+	a->src_bstart = au_dbstart(a->src_dentry);
+	a->dst_bstart = au_dbstart(a->dst_dentry);
+	if (au_ftest_ren(a->flags, ISDIR))
+		au_fset_wrdir(wr_dir_args.flags, ISDIR);
+	wr_dir_args.force_btgt = a->src_bstart;
+	if (a->dst_inode && a->dst_bstart < a->src_bstart)
+		wr_dir_args.force_btgt = a->dst_bstart;
+	wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
+	err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
+	a->btgt = err;
+
+	return err;
+}
+
+static void au_ren_dt(struct au_ren_args *a)
+{
+	a->h_path.dentry = a->src_h_parent;
+	au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
+	if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
+		a->h_path.dentry = a->dst_h_parent;
+		au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
+	}
+
+	au_fclr_ren(a->flags, DT_DSTDIR);
+	if (!au_ftest_ren(a->flags, ISDIR))
+		return;
+
+	a->h_path.dentry = a->src_h_dentry;
+	au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
+	if (a->dst_h_dentry->d_inode) {
+		au_fset_ren(a->flags, DT_DSTDIR);
+		a->h_path.dentry = a->dst_h_dentry;
+		au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
+	}
+}
+
+static void au_ren_rev_dt(int err, struct au_ren_args *a)
+{
+	struct dentry *h_d;
+	struct mutex *h_mtx;
+
+	au_dtime_revert(a->src_dt + AuPARENT);
+	if (!au_ftest_ren(a->flags, ISSAMEDIR))
+		au_dtime_revert(a->dst_dt + AuPARENT);
+
+	if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
+		h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
+		h_mtx = &h_d->d_inode->i_mutex;
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		au_dtime_revert(a->src_dt + AuCHILD);
+		mutex_unlock(h_mtx);
+
+		if (au_ftest_ren(a->flags, DT_DSTDIR)) {
+			h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
+			h_mtx = &h_d->d_inode->i_mutex;
+			mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+			au_dtime_revert(a->dst_dt + AuCHILD);
+			mutex_unlock(h_mtx);
+		}
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
+		struct inode *_dst_dir, struct dentry *_dst_dentry)
+{
+	int err;
+	/* reduce stack space */
+	struct au_ren_args *a;
+
+	AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
+	IMustLock(_src_dir);
+	IMustLock(_dst_dir);
+
+	err = -ENOMEM;
+	BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
+	a = kzalloc(sizeof(*a), GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	a->src_dir = _src_dir;
+	a->src_dentry = _src_dentry;
+	a->src_inode = a->src_dentry->d_inode;
+	a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
+	a->dst_dir = _dst_dir;
+	a->dst_dentry = _dst_dentry;
+	a->dst_inode = a->dst_dentry->d_inode;
+	a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
+	if (a->dst_inode) {
+		IMustLock(a->dst_inode);
+		au_igrab(a->dst_inode);
+	}
+
+	err = -ENOTDIR;
+	if (S_ISDIR(a->src_inode->i_mode)) {
+		au_fset_ren(a->flags, ISDIR);
+		if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
+			goto out_free;
+		aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
+					  AuLock_DIR | AuLock_FLUSH);
+	} else
+		aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
+					  AuLock_FLUSH);
+
+	au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
+	di_write_lock_parent(a->dst_parent);
+
+	/* which branch we process */
+	err = au_ren_wbr(a);
+	if (unlikely(err < 0))
+		goto out_unlock;
+	a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
+	a->h_path.mnt = a->br->br_mnt;
+
+	/* are they available to be renamed */
+	err = au_ren_may_dir(a);
+	if (unlikely(err))
+		goto out_children;
+
+	/* prepare the writable parent dir on the same branch */
+	if (a->dst_bstart == a->btgt) {
+		au_fset_ren(a->flags, WHDST);
+	} else {
+		err = au_cpup_dirs(a->dst_dentry, a->btgt);
+		if (unlikely(err))
+			goto out_children;
+	}
+
+	if (a->src_dir != a->dst_dir) {
+		/*
+		 * this temporary unlock is safe,
+		 * because both dir->i_mutex are locked.
+		 */
+		di_write_unlock(a->dst_parent);
+		di_write_lock_parent(a->src_parent);
+		err = au_wr_dir_need_wh(a->src_dentry,
+					au_ftest_ren(a->flags, ISDIR),
+					&a->btgt);
+		di_write_unlock(a->src_parent);
+		di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
+		au_fclr_ren(a->flags, ISSAMEDIR);
+	} else
+		err = au_wr_dir_need_wh(a->src_dentry,
+					au_ftest_ren(a->flags, ISDIR),
+					&a->btgt);
+	if (unlikely(err < 0))
+		goto out_children;
+	if (err)
+		au_fset_ren(a->flags, WHSRC);
+
+	/* lock them all */
+	err = au_ren_lock(a);
+	if (unlikely(err))
+		goto out_children;
+
+	if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
+		err = au_may_ren(a);
+	else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
+		err = -ENAMETOOLONG;
+	if (unlikely(err))
+		goto out_hdir;
+
+	/* store timestamps to be revertible */
+	au_ren_dt(a);
+
+	/* here we go */
+	err = do_rename(a);
+	if (unlikely(err))
+		goto out_dt;
+
+	/* update dir attributes */
+	au_ren_refresh_dir(a);
+
+	/* dput/iput all lower dentries */
+	au_ren_refresh(a);
+
+	goto out_hdir; /* success */
+
+ out_dt:
+	au_ren_rev_dt(err, a);
+ out_hdir:
+	au_ren_unlock(a);
+ out_children:
+	au_nhash_wh_free(&a->whlist);
+ out_unlock:
+	if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
+		au_update_dbstart(a->dst_dentry);
+		d_drop(a->dst_dentry);
+	}
+	if (!err)
+		d_move(a->src_dentry, a->dst_dentry);
+	if (au_ftest_ren(a->flags, ISSAMEDIR))
+		di_write_unlock(a->dst_parent);
+	else
+		di_write_unlock2(a->src_parent, a->dst_parent);
+	aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
+ out_free:
+	iput(a->dst_inode);
+	if (a->thargs)
+		au_whtmp_rmdir_free(a->thargs);
+	kfree(a);
+ out:
+	AuTraceErr(err);
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/opts.h
+++ linux-ec2-2.6.32/ubuntu/aufs/opts.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * mount options/flags
+ */
+
+#ifndef __AUFS_OPTS_H__
+#define __AUFS_OPTS_H__
+
+#ifdef __KERNEL__
+
+#include <linux/path.h>
+#include <linux/aufs_type.h>
+
+struct file;
+struct super_block;
+
+/* ---------------------------------------------------------------------- */
+
+/* mount flags */
+#define AuOpt_XINO		1		/* external inode number bitmap
+						   and translation table */
+#define AuOpt_TRUNC_XINO	(1 << 1)	/* truncate xino files */
+#define AuOpt_UDBA_NONE		(1 << 2)	/* users direct branch access */
+#define AuOpt_UDBA_REVAL	(1 << 3)
+#define AuOpt_UDBA_HINOTIFY	(1 << 4)
+#define AuOpt_SHWH		(1 << 5)	/* show whiteout */
+#define AuOpt_PLINK		(1 << 6)	/* pseudo-link */
+#define AuOpt_DIRPERM1		(1 << 7)	/* unimplemented */
+#define AuOpt_REFROF		(1 << 8)	/* unimplemented */
+#define AuOpt_ALWAYS_DIROPQ	(1 << 9)	/* policy to creating diropq */
+#define AuOpt_SUM		(1 << 10)	/* summation for statfs(2) */
+#define AuOpt_SUM_W		(1 << 11)	/* unimplemented */
+#define AuOpt_WARN_PERM		(1 << 12)	/* warn when add-branch */
+#define AuOpt_VERBOSE		(1 << 13)	/* busy inode when del-branch */
+
+#ifndef CONFIG_AUFS_HINOTIFY
+#undef AuOpt_UDBA_HINOTIFY
+#define AuOpt_UDBA_HINOTIFY	0
+#endif
+#ifndef CONFIG_AUFS_SHWH
+#undef AuOpt_SHWH
+#define AuOpt_SHWH		0
+#endif
+
+#define AuOpt_Def	(AuOpt_XINO \
+			 | AuOpt_UDBA_REVAL \
+			 | AuOpt_PLINK \
+			 /* | AuOpt_DIRPERM1 */ \
+			 | AuOpt_WARN_PERM)
+#define AuOptMask_UDBA	(AuOpt_UDBA_NONE \
+			 | AuOpt_UDBA_REVAL \
+			 | AuOpt_UDBA_HINOTIFY)
+
+#define au_opt_test(flags, name)	(flags & AuOpt_##name)
+#define au_opt_set(flags, name) do { \
+	BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
+	((flags) |= AuOpt_##name); \
+} while (0)
+#define au_opt_set_udba(flags, name) do { \
+	(flags) &= ~AuOptMask_UDBA; \
+	((flags) |= AuOpt_##name); \
+} while (0)
+#define au_opt_clr(flags, name)		{ ((flags) &= ~AuOpt_##name); }
+
+/* ---------------------------------------------------------------------- */
+
+/* policies to select one among multiple writable branches */
+enum {
+	AuWbrCreate_TDP,	/* top down parent */
+	AuWbrCreate_RR,		/* round robin */
+	AuWbrCreate_MFS,	/* most free space */
+	AuWbrCreate_MFSV,	/* mfs with seconds */
+	AuWbrCreate_MFSRR,	/* mfs then rr */
+	AuWbrCreate_MFSRRV,	/* mfs then rr with seconds */
+	AuWbrCreate_PMFS,	/* parent and mfs */
+	AuWbrCreate_PMFSV,	/* parent and mfs with seconds */
+
+	AuWbrCreate_Def = AuWbrCreate_TDP
+};
+
+enum {
+	AuWbrCopyup_TDP,	/* top down parent */
+	AuWbrCopyup_BUP,	/* bottom up parent */
+	AuWbrCopyup_BU,		/* bottom up */
+
+	AuWbrCopyup_Def = AuWbrCopyup_TDP
+};
+
+/* ---------------------------------------------------------------------- */
+
+struct au_opt_add {
+	aufs_bindex_t	bindex;
+	char		*pathname;
+	int		perm;
+	struct path	path;
+};
+
+struct au_opt_del {
+	char		*pathname;
+	struct path	h_path;
+};
+
+struct au_opt_mod {
+	char		*path;
+	int		perm;
+	struct dentry	*h_root;
+};
+
+struct au_opt_xino {
+	char		*path;
+	struct file	*file;
+};
+
+struct au_opt_xino_itrunc {
+	aufs_bindex_t	bindex;
+};
+
+struct au_opt_wbr_create {
+	int			wbr_create;
+	int			mfs_second;
+	unsigned long long	mfsrr_watermark;
+};
+
+struct au_opt {
+	int type;
+	union {
+		struct au_opt_xino	xino;
+		struct au_opt_xino_itrunc xino_itrunc;
+		struct au_opt_add	add;
+		struct au_opt_del	del;
+		struct au_opt_mod	mod;
+		int			dirwh;
+		int			rdcache;
+		unsigned int		rdblk;
+		unsigned int		rdhash;
+		int			udba;
+		struct au_opt_wbr_create wbr_create;
+		int			wbr_copyup;
+	};
+};
+
+/* opts flags */
+#define AuOpts_REMOUNT		1
+#define AuOpts_REFRESH_DIR	(1 << 1)
+#define AuOpts_REFRESH_NONDIR	(1 << 2)
+#define AuOpts_TRUNC_XIB	(1 << 3)
+#define au_ftest_opts(flags, name)	((flags) & AuOpts_##name)
+#define au_fset_opts(flags, name)	{ (flags) |= AuOpts_##name; }
+#define au_fclr_opts(flags, name)	{ (flags) &= ~AuOpts_##name; }
+
+struct au_opts {
+	struct au_opt	*opt;
+	int		max_opt;
+
+	unsigned int	given_udba;
+	unsigned int	flags;
+	unsigned long	sb_flags;
+};
+
+/* ---------------------------------------------------------------------- */
+
+const char *au_optstr_br_perm(int brperm);
+const char *au_optstr_udba(int udba);
+const char *au_optstr_wbr_copyup(int wbr_copyup);
+const char *au_optstr_wbr_create(int wbr_create);
+
+void au_opts_free(struct au_opts *opts);
+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
+		   unsigned int pending);
+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
+
+unsigned int au_opt_udba(struct super_block *sb);
+
+/* ---------------------------------------------------------------------- */
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_OPTS_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/ioctl.c
+++ linux-ec2-2.6.32/ubuntu/aufs/ioctl.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * ioctl
+ * plink-management and readdir in userspace.
+ * assist the pathconf(3) wrapper library.
+ */
+
+#include <linux/file.h>
+#include "aufs.h"
+
+static int au_wbr_fd(struct path *path)
+{
+	int err, fd, flags;
+	aufs_bindex_t wbi, bindex, bend;
+	struct file *h_file;
+	struct super_block *sb;
+	struct dentry *root;
+	struct au_branch *wbr;
+
+	err = get_unused_fd();
+	if (unlikely(err < 0))
+		goto out;
+	fd = err;
+
+	flags = O_RDONLY | O_DIRECTORY;
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
+	wbi = 0;
+	sb = path->dentry->d_sb;
+	root = sb->s_root;
+	aufs_read_lock(root, AuLock_IR);
+	wbr = au_sbr(sb, wbi);
+	if (!(path->mnt->mnt_flags & MNT_READONLY)
+	    && !au_br_writable(wbr->br_perm)) {
+		bend = au_sbend(sb);
+		for (bindex = 1; bindex <= bend; bindex++) {
+			wbr = au_sbr(sb, bindex);
+			if (au_br_writable(wbr->br_perm)) {
+				wbi = bindex;
+				break;
+			}
+		}
+		wbr = au_sbr(sb, wbi);
+	}
+	AuDbg("wbi %d\n", wbi);
+	h_file = au_h_open(root, wbi, flags, NULL);
+	aufs_read_unlock(root, AuLock_IR);
+	err = PTR_ERR(h_file);
+	if (IS_ERR(h_file))
+		goto out_fd;
+
+	atomic_dec(&wbr->br_count); /* cf. au_h_open() */
+	fd_install(fd, h_file);
+	err = fd;
+	goto out; /* success */
+
+ out_fd:
+	put_unused_fd(fd);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long err;
+
+	switch (cmd) {
+	case AUFS_CTL_PLINK_MAINT:
+	case AUFS_CTL_PLINK_CLEAN:
+		err = au_plink_ioctl(file, cmd);
+		break;
+
+	case AUFS_CTL_RDU:
+	case AUFS_CTL_RDU_INO:
+		err = au_rdu_ioctl(file, cmd, arg);
+		break;
+
+	case AUFS_CTL_WBR_FD:
+		err = au_wbr_fd(&file->f_path);
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+
+	AuTraceErr(err);
+	return err;
+}
+
+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long err;
+
+	switch (cmd) {
+	case AUFS_CTL_WBR_FD:
+		err = au_wbr_fd(&file->f_path);
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+
+	AuTraceErr(err);
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/f_op.c
+++ linux-ec2-2.6.32/ubuntu/aufs/f_op.c
@@ -0,0 +1,828 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * file and vm operations
+ */
+
+#include <linux/file.h>
+#include <linux/fs_stack.h>
+#include <linux/ima.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/security.h>
+#include "aufs.h"
+
+/* common function to regular file and dir */
+int aufs_flush(struct file *file, fl_owner_t id)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	struct dentry *dentry;
+	struct file *h_file;
+
+	dentry = file->f_dentry;
+	si_noflush_read_lock(dentry->d_sb);
+	fi_read_lock(file);
+	di_read_lock_child(dentry, AuLock_IW);
+
+	err = 0;
+	bend = au_fbend(file);
+	for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
+		h_file = au_h_fptr(file, bindex);
+		if (!h_file || !h_file->f_op || !h_file->f_op->flush)
+			continue;
+
+		err = h_file->f_op->flush(h_file, id);
+		if (!err)
+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
+		/*ignore*/
+	}
+	au_cpup_attr_timesizes(dentry->d_inode);
+
+	di_read_unlock(dentry, AuLock_IW);
+	fi_read_unlock(file);
+	si_read_unlock(dentry->d_sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int do_open_nondir(struct file *file, int flags)
+{
+	int err;
+	aufs_bindex_t bindex;
+	struct file *h_file;
+	struct dentry *dentry;
+	struct au_finfo *finfo;
+
+	FiMustWriteLock(file);
+
+	err = 0;
+	dentry = file->f_dentry;
+	finfo = au_fi(file);
+	finfo->fi_h_vm_ops = NULL;
+	finfo->fi_vm_ops = NULL;
+	bindex = au_dbstart(dentry);
+	/* O_TRUNC is processed already */
+	BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
+	       && (flags & O_TRUNC));
+
+	h_file = au_h_open(dentry, bindex, flags, file);
+	if (IS_ERR(h_file))
+		err = PTR_ERR(h_file);
+	else {
+		au_set_fbstart(file, bindex);
+		au_set_fbend(file, bindex);
+		au_set_h_fptr(file, bindex, h_file);
+		au_update_figen(file);
+		/* todo: necessary? */
+		/* file->f_ra = h_file->f_ra; */
+	}
+	return err;
+}
+
+static int aufs_open_nondir(struct inode *inode __maybe_unused,
+			    struct file *file)
+{
+	return au_do_open(file, do_open_nondir);
+}
+
+static int aufs_release_nondir(struct inode *inode __maybe_unused,
+			       struct file *file)
+{
+	struct super_block *sb = file->f_dentry->d_sb;
+
+	si_noflush_read_lock(sb);
+	kfree(au_fi(file)->fi_vm_ops);
+	au_finfo_fin(file);
+	si_read_unlock(sb);
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
+			 loff_t *ppos)
+{
+	ssize_t err;
+	struct dentry *dentry;
+	struct file *h_file;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
+	if (unlikely(err))
+		goto out;
+
+	h_file = au_h_fptr(file, au_fbstart(file));
+	err = vfsub_read_u(h_file, buf, count, ppos);
+	/* todo: necessary? */
+	/* file->f_ra = h_file->f_ra; */
+	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
+
+	di_read_unlock(dentry, AuLock_IR);
+	fi_read_unlock(file);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
+			  size_t count, loff_t *ppos)
+{
+	ssize_t err;
+	aufs_bindex_t bstart;
+	struct au_pin pin;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct super_block *sb;
+	struct file *h_file;
+	char __user *buf = (char __user *)ubuf;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	mutex_lock(&inode->i_mutex);
+	si_read_lock(sb, AuLock_FLUSH);
+
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	err = au_ready_to_write(file, -1, &pin);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+
+	bstart = au_fbstart(file);
+	h_file = au_h_fptr(file, bstart);
+	au_unpin(&pin);
+	err = vfsub_write_u(h_file, buf, count, ppos);
+	au_cpup_attr_timesizes(inode);
+	inode->i_mode = h_file->f_dentry->d_inode->i_mode;
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+
+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
+			     unsigned long nv, loff_t pos)
+{
+	ssize_t err;
+	struct file *file, *h_file;
+	struct dentry *dentry;
+	struct super_block *sb;
+
+	file = kio->ki_filp;
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
+	if (unlikely(err))
+		goto out;
+
+	err = -ENOSYS;
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (h_file->f_op && h_file->f_op->aio_read) {
+		err = security_file_permission(h_file, MAY_READ);
+		if (unlikely(err))
+			goto out_unlock;
+		if (!is_sync_kiocb(kio)) {
+			get_file(h_file);
+			fput(file);
+		}
+		kio->ki_filp = h_file;
+		err = h_file->f_op->aio_read(kio, iov, nv, pos);
+		/* todo: necessary? */
+		/* file->f_ra = h_file->f_ra; */
+		fsstack_copy_attr_atime(dentry->d_inode,
+					h_file->f_dentry->d_inode);
+	} else
+		/* currently there is no such fs */
+		WARN_ON_ONCE(h_file->f_op && h_file->f_op->read);
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_read_unlock(file);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
+			      unsigned long nv, loff_t pos)
+{
+	ssize_t err;
+	aufs_bindex_t bstart;
+	struct au_pin pin;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct super_block *sb;
+	struct file *file, *h_file;
+
+	file = kio->ki_filp;
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	mutex_lock(&inode->i_mutex);
+	si_read_lock(sb, AuLock_FLUSH);
+
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	err = au_ready_to_write(file, -1, &pin);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+
+	err = -ENOSYS;
+	bstart = au_fbstart(file);
+	h_file = au_h_fptr(file, bstart);
+	au_unpin(&pin);
+	if (h_file->f_op && h_file->f_op->aio_write) {
+		err = security_file_permission(h_file, MAY_WRITE);
+		if (unlikely(err))
+			goto out_unlock;
+		if (!is_sync_kiocb(kio)) {
+			get_file(h_file);
+			fput(file);
+		}
+		kio->ki_filp = h_file;
+		err = h_file->f_op->aio_write(kio, iov, nv, pos);
+		au_cpup_attr_timesizes(inode);
+		inode->i_mode = h_file->f_dentry->d_inode->i_mode;
+	} else
+		/* currently there is no such fs */
+		WARN_ON_ONCE(h_file->f_op && h_file->f_op->write);
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+
+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
+				struct pipe_inode_info *pipe, size_t len,
+				unsigned int flags)
+{
+	ssize_t err;
+	struct file *h_file;
+	struct dentry *dentry;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
+	if (unlikely(err))
+		goto out;
+
+	err = -EINVAL;
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (au_test_loopback_kthread()) {
+		file->f_mapping = h_file->f_mapping;
+		smp_mb(); /* unnecessary? */
+	}
+	err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
+	/* todo: necessasry? */
+	/* file->f_ra = h_file->f_ra; */
+	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
+
+	di_read_unlock(dentry, AuLock_IR);
+	fi_read_unlock(file);
+
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+static ssize_t
+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
+		  size_t len, unsigned int flags)
+{
+	ssize_t err;
+	struct au_pin pin;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct super_block *sb;
+	struct file *h_file;
+
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
+	mutex_lock(&inode->i_mutex);
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	err = au_ready_to_write(file, -1, &pin);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+
+	h_file = au_h_fptr(file, au_fbstart(file));
+	au_unpin(&pin);
+	err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
+	au_cpup_attr_timesizes(inode);
+	inode->i_mode = h_file->f_dentry->d_inode->i_mode;
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static struct file *au_safe_file(struct vm_area_struct *vma)
+{
+	struct file *file;
+
+	file = vma->vm_file;
+	if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
+		return file;
+	return NULL;
+}
+
+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
+{
+	vma->vm_file = file;
+	/* smp_mb(); */ /* flush vm_file */
+}
+
+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int err;
+	static DECLARE_WAIT_QUEUE_HEAD(wq);
+	struct file *file, *h_file;
+	struct au_finfo *finfo;
+
+	/* todo: non-robr mode, user vm_file as it is? */
+	wait_event(wq, (file = au_safe_file(vma)));
+
+	/* do not revalidate, no si lock */
+	finfo = au_fi(file);
+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
+
+	mutex_lock(&finfo->fi_vm_mtx);
+	vma->vm_file = h_file;
+	err = finfo->fi_h_vm_ops->fault(vma, vmf);
+	/* todo: necessary? */
+	/* file->f_ra = h_file->f_ra; */
+	au_reset_file(vma, file);
+	mutex_unlock(&finfo->fi_vm_mtx);
+#if 0 /* def CONFIG_SMP */
+	/* wake_up_nr(&wq, online_cpu - 1); */
+	wake_up_all(&wq);
+#else
+	wake_up(&wq);
+#endif
+
+	return err;
+}
+
+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int err;
+	static DECLARE_WAIT_QUEUE_HEAD(wq);
+	struct file *file, *h_file;
+	struct au_finfo *finfo;
+
+	wait_event(wq, (file = au_safe_file(vma)));
+
+	finfo = au_fi(file);
+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
+
+	mutex_lock(&finfo->fi_vm_mtx);
+	vma->vm_file = h_file;
+	err = finfo->fi_h_vm_ops->page_mkwrite(vma, vmf);
+	au_reset_file(vma, file);
+	mutex_unlock(&finfo->fi_vm_mtx);
+	wake_up(&wq);
+
+	return err;
+}
+
+static void aufs_vm_close(struct vm_area_struct *vma)
+{
+	static DECLARE_WAIT_QUEUE_HEAD(wq);
+	struct file *file, *h_file;
+	struct au_finfo *finfo;
+
+	wait_event(wq, (file = au_safe_file(vma)));
+
+	finfo = au_fi(file);
+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
+
+	mutex_lock(&finfo->fi_vm_mtx);
+	vma->vm_file = h_file;
+	finfo->fi_h_vm_ops->close(vma);
+	au_reset_file(vma, file);
+	mutex_unlock(&finfo->fi_vm_mtx);
+	wake_up(&wq);
+}
+
+static struct vm_operations_struct aufs_vm_ops = {
+	/* .close and .page_mkwrite are not set by default */
+	.fault		= aufs_fault,
+};
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned long au_prot_conv(unsigned long flags)
+{
+	unsigned long prot;
+
+	prot = 0;
+	if (flags & VM_READ)
+		prot |= PROT_READ;
+	if (flags & VM_WRITE)
+		prot |= PROT_WRITE;
+	if (flags & VM_EXEC)
+		prot |= PROT_EXEC;
+	return prot;
+}
+
+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
+					      struct vm_area_struct *vma)
+{
+	struct vm_operations_struct *vm_ops;
+	int err;
+
+	vm_ops = ERR_PTR(-ENODEV);
+	if (!h_file->f_op || !h_file->f_op->mmap)
+		goto out;
+
+	err = ima_file_mmap(h_file, au_prot_conv(vma->vm_flags));
+	vm_ops = ERR_PTR(err);
+	if (err)
+		goto out;
+
+	err = h_file->f_op->mmap(h_file, vma);
+	vm_ops = ERR_PTR(err);
+	if (unlikely(err))
+		goto out;
+
+	/* oops, it became 'const' */
+	vm_ops = (struct vm_operations_struct *)vma->vm_ops;
+	err = do_munmap(current->mm, vma->vm_start,
+			vma->vm_end - vma->vm_start);
+	if (unlikely(err)) {
+		AuIOErr("failed internal unmapping %.*s, %d\n",
+			AuDLNPair(h_file->f_dentry), err);
+		vm_ops = ERR_PTR(-EIO);
+	}
+
+ out:
+	return vm_ops;
+}
+
+static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
+{
+	int err;
+	struct vm_operations_struct *h_ops;
+
+	AuRwMustAnyLock(&finfo->fi_rwsem);
+
+	err = 0;
+	h_ops = finfo->fi_h_vm_ops;
+	AuDebugOn(!h_ops);
+	if ((!h_ops->page_mkwrite && !h_ops->close)
+	    || finfo->fi_vm_ops)
+		goto out;
+
+	err = -ENOMEM;
+	finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
+	if (unlikely(!finfo->fi_vm_ops))
+		goto out;
+
+	err = 0;
+	if (h_ops->page_mkwrite)
+		finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
+	if (h_ops->close)
+		finfo->fi_vm_ops->close = aufs_vm_close;
+
+	vma->vm_ops = finfo->fi_vm_ops;
+
+ out:
+	return err;
+}
+
+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int err;
+	unsigned char wlock, mmapped;
+	struct dentry *dentry;
+	struct super_block *sb;
+	struct file *h_file;
+	struct vm_operations_struct *vm_ops;
+
+	dentry = file->f_dentry;
+	wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	mmapped = !!au_test_mmapped(file);
+	if (wlock) {
+		struct au_pin pin;
+
+		err = au_ready_to_write(file, -1, &pin);
+		di_downgrade_lock(dentry, AuLock_IR);
+		if (unlikely(err))
+			goto out_unlock;
+		au_unpin(&pin);
+	} else
+		di_downgrade_lock(dentry, AuLock_IR);
+
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (!mmapped && au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
+		/*
+		 * by this assignment, f_mapping will differs from aufs inode
+		 * i_mapping.
+		 * if someone else mixes the use of f_dentry->d_inode and
+		 * f_mapping->host, then a problem may arise.
+		 */
+		file->f_mapping = h_file->f_mapping;
+	}
+
+	vm_ops = NULL;
+	if (!mmapped) {
+		vm_ops = au_vm_ops(h_file, vma);
+		err = PTR_ERR(vm_ops);
+		if (IS_ERR(vm_ops))
+			goto out_unlock;
+	}
+
+	/*
+	 * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
+	 * currently MAP_DENYWRITE from userspace is ignored, but elf loader
+	 * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
+	 * both of the aufs file and the lower file is deny_write_access()-ed.
+	 * finally I hope we can skip handlling MAP_DENYWRITE here.
+	 */
+	err = generic_file_mmap(file, vma);
+	if (unlikely(err))
+		goto out_unlock;
+
+	vma->vm_ops = &aufs_vm_ops;
+	if (!mmapped) {
+		struct au_finfo *finfo = au_fi(file);
+
+		finfo->fi_h_vm_ops = vm_ops;
+		mutex_init(&finfo->fi_vm_mtx);
+	}
+
+	err = au_custom_vm_ops(au_fi(file), vma);
+	if (unlikely(err))
+		goto out_unlock;
+
+	vfsub_file_accessed(h_file);
+	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
+			     int datasync)
+{
+	int err;
+	struct au_pin pin;
+	struct inode *inode;
+	struct file *h_file;
+	struct super_block *sb;
+
+	inode = dentry->d_inode;
+	IMustLock(file->f_mapping->host);
+	if (inode != file->f_mapping->host) {
+		mutex_unlock(&file->f_mapping->host->i_mutex);
+		mutex_lock(&inode->i_mutex);
+	}
+	IMustLock(inode);
+
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+
+	err = 0; /* -EBADF; */ /* posix? */
+	if (unlikely(!(file->f_mode & FMODE_WRITE)))
+		goto out;
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	err = au_ready_to_write(file, -1, &pin);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+	au_unpin(&pin);
+
+	err = -EINVAL;
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (h_file->f_op && h_file->f_op->fsync) {
+		struct dentry *h_d;
+		struct mutex *h_mtx;
+
+		/*
+		 * no filemap_fdatawrite() since aufs file has no its own
+		 * mapping, but dir.
+		 */
+		h_d = h_file->f_dentry;
+		h_mtx = &h_d->d_inode->i_mutex;
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		err = h_file->f_op->fsync(h_file, h_d, datasync);
+		if (!err)
+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
+		/*ignore*/
+		au_cpup_attr_timesizes(inode);
+		mutex_unlock(h_mtx);
+	}
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	if (inode != file->f_mapping->host) {
+		mutex_unlock(&inode->i_mutex);
+		mutex_lock(&file->f_mapping->host->i_mutex);
+	}
+	return err;
+}
+
+/* no one supports this operation, currently */
+#if 0
+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
+{
+	int err;
+	struct au_pin pin;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct file *file, *h_file;
+	struct super_block *sb;
+
+	file = kio->ki_filp;
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
+	mutex_lock(&inode->i_mutex);
+
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+
+	err = 0; /* -EBADF; */ /* posix? */
+	if (unlikely(!(file->f_mode & FMODE_WRITE)))
+		goto out;
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
+	if (unlikely(err))
+		goto out;
+
+	err = au_ready_to_write(file, -1, &pin);
+	di_downgrade_lock(dentry, AuLock_IR);
+	if (unlikely(err))
+		goto out_unlock;
+	au_unpin(&pin);
+
+	err = -ENOSYS;
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (h_file->f_op && h_file->f_op->aio_fsync) {
+		struct dentry *h_d;
+		struct mutex *h_mtx;
+
+		h_d = h_file->f_dentry;
+		h_mtx = &h_d->d_inode->i_mutex;
+		if (!is_sync_kiocb(kio)) {
+			get_file(h_file);
+			fput(file);
+		}
+		kio->ki_filp = h_file;
+		err = h_file->f_op->aio_fsync(kio, datasync);
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		if (!err)
+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
+		/*ignore*/
+		au_cpup_attr_timesizes(inode);
+		mutex_unlock(h_mtx);
+	}
+
+ out_unlock:
+	di_read_unlock(dentry, AuLock_IR);
+	fi_write_unlock(file);
+ out:
+	si_read_unlock(sb);
+	mutex_unlock(&inode->i_mutex);
+	return err;
+}
+#endif
+
+static int aufs_fasync(int fd, struct file *file, int flag)
+{
+	int err;
+	struct file *h_file;
+	struct dentry *dentry;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
+	if (unlikely(err))
+		goto out;
+
+	h_file = au_h_fptr(file, au_fbstart(file));
+	if (h_file->f_op && h_file->f_op->fasync)
+		err = h_file->f_op->fasync(fd, h_file, flag);
+
+	di_read_unlock(dentry, AuLock_IR);
+	fi_read_unlock(file);
+
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* no one supports this operation, currently */
+#if 0
+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
+			     size_t len, loff_t *pos , int more)
+{
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+const struct file_operations aufs_file_fop = {
+	/*
+	 * while generic_file_llseek/_unlocked() don't use BKL,
+	 * don't use it since it operates file->f_mapping->host.
+	 * in aufs, it may be a real file and may confuse users by UDBA.
+	 */
+	/* .llseek		= generic_file_llseek, */
+
+	.read		= aufs_read,
+	.write		= aufs_write,
+	.aio_read	= aufs_aio_read,
+	.aio_write	= aufs_aio_write,
+#ifdef CONFIG_AUFS_POLL
+	.poll		= aufs_poll,
+#endif
+	.unlocked_ioctl	= aufs_ioctl_nondir,
+	.mmap		= aufs_mmap,
+	.open		= aufs_open_nondir,
+	.flush		= aufs_flush,
+	.release	= aufs_release_nondir,
+	.fsync		= aufs_fsync_nondir,
+	/* .aio_fsync	= aufs_aio_fsync_nondir, */
+	.fasync		= aufs_fasync,
+	/* .sendpage	= aufs_sendpage, */
+	.splice_write	= aufs_splice_write,
+	.splice_read	= aufs_splice_read,
+#if 0
+	.aio_splice_write = aufs_aio_splice_write,
+	.aio_splice_read  = aufs_aio_splice_read
+#endif
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/vdir.c
+++ linux-ec2-2.6.32/ubuntu/aufs/vdir.c
@@ -0,0 +1,884 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * virtual or vertical directory
+ */
+
+#include <linux/hash.h>
+#include "aufs.h"
+
+static unsigned int calc_size(int nlen)
+{
+	return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
+}
+
+static int set_deblk_end(union au_vdir_deblk_p *p,
+			 union au_vdir_deblk_p *deblk_end)
+{
+	if (calc_size(0) <= deblk_end->deblk - p->deblk) {
+		p->de->de_str.len = 0;
+		/* smp_mb(); */
+		return 0;
+	}
+	return -1; /* error */
+}
+
+/* returns true or false */
+static int is_deblk_end(union au_vdir_deblk_p *p,
+			union au_vdir_deblk_p *deblk_end)
+{
+	if (calc_size(0) <= deblk_end->deblk - p->deblk)
+		return !p->de->de_str.len;
+	return 1;
+}
+
+static unsigned char *last_deblk(struct au_vdir *vdir)
+{
+	return vdir->vd_deblk[vdir->vd_nblk - 1];
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* estimate the apropriate size for name hash table */
+unsigned int au_rdhash_est(loff_t sz)
+{
+	unsigned int n;
+
+	n = UINT_MAX;
+	sz >>= 10;
+	if (sz < n)
+		n = sz;
+	if (sz < AUFS_RDHASH_DEF)
+		n = AUFS_RDHASH_DEF;
+	/* pr_info("n %u\n", n); */
+	return n;
+}
+
+/*
+ * the allocated memory has to be freed by
+ * au_nhash_wh_free() or au_nhash_de_free().
+ */
+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
+{
+	struct hlist_head *head;
+	unsigned int u;
+
+	head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
+	if (head) {
+		nhash->nh_num = num_hash;
+		nhash->nh_head = head;
+		for (u = 0; u < num_hash; u++)
+			INIT_HLIST_HEAD(head++);
+		return 0; /* success */
+	}
+
+	return -ENOMEM;
+}
+
+static void nhash_count(struct hlist_head *head)
+{
+#if 0
+	unsigned long n;
+	struct hlist_node *pos;
+
+	n = 0;
+	hlist_for_each(pos, head)
+		n++;
+	pr_info("%lu\n", n);
+#endif
+}
+
+static void au_nhash_wh_do_free(struct hlist_head *head)
+{
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos, *node;
+
+	hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
+		/* hlist_del(pos); */
+		kfree(tpos);
+	}
+}
+
+static void au_nhash_de_do_free(struct hlist_head *head)
+{
+	struct au_vdir_dehstr *tpos;
+	struct hlist_node *pos, *node;
+
+	hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
+		/* hlist_del(pos); */
+		au_cache_free_dehstr(tpos);
+	}
+}
+
+static void au_nhash_do_free(struct au_nhash *nhash,
+			     void (*free)(struct hlist_head *head))
+{
+	unsigned int n;
+	struct hlist_head *head;
+
+	n = nhash->nh_num;
+	if (!n)
+		return;
+
+	head = nhash->nh_head;
+	while (n-- > 0) {
+		nhash_count(head);
+		free(head++);
+	}
+	kfree(nhash->nh_head);
+}
+
+void au_nhash_wh_free(struct au_nhash *whlist)
+{
+	au_nhash_do_free(whlist, au_nhash_wh_do_free);
+}
+
+static void au_nhash_de_free(struct au_nhash *delist)
+{
+	au_nhash_do_free(delist, au_nhash_de_do_free);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
+			    int limit)
+{
+	int num;
+	unsigned int u, n;
+	struct hlist_head *head;
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos;
+
+	num = 0;
+	n = whlist->nh_num;
+	head = whlist->nh_head;
+	for (u = 0; u < n; u++, head++)
+		hlist_for_each_entry(tpos, pos, head, wh_hash)
+			if (tpos->wh_bindex == btgt && ++num > limit)
+				return 1;
+	return 0;
+}
+
+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
+				       unsigned char *name,
+				       unsigned int len)
+{
+	unsigned int v;
+	/* const unsigned int magic_bit = 12; */
+
+	AuDebugOn(!nhash->nh_num || !nhash->nh_head);
+
+	v = 0;
+	while (len--)
+		v += *name++;
+	/* v = hash_long(v, magic_bit); */
+	v %= nhash->nh_num;
+	return nhash->nh_head + v;
+}
+
+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
+			      int nlen)
+{
+	return str->len == nlen && !memcmp(str->name, name, nlen);
+}
+
+/* returns found or not */
+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
+{
+	struct hlist_head *head;
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos;
+	struct au_vdir_destr *str;
+
+	head = au_name_hash(whlist, name, nlen);
+	hlist_for_each_entry(tpos, pos, head, wh_hash) {
+		str = &tpos->wh_str;
+		AuDbg("%.*s\n", str->len, str->name);
+		if (au_nhash_test_name(str, name, nlen))
+			return 1;
+	}
+	return 0;
+}
+
+/* returns found(true) or not */
+static int test_known(struct au_nhash *delist, char *name, int nlen)
+{
+	struct hlist_head *head;
+	struct au_vdir_dehstr *tpos;
+	struct hlist_node *pos;
+	struct au_vdir_destr *str;
+
+	head = au_name_hash(delist, name, nlen);
+	hlist_for_each_entry(tpos, pos, head, hash) {
+		str = tpos->str;
+		AuDbg("%.*s\n", str->len, str->name);
+		if (au_nhash_test_name(str, name, nlen))
+			return 1;
+	}
+	return 0;
+}
+
+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
+			    unsigned char d_type)
+{
+#ifdef CONFIG_AUFS_SHWH
+	wh->wh_ino = ino;
+	wh->wh_type = d_type;
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
+		       unsigned int d_type, aufs_bindex_t bindex,
+		       unsigned char shwh)
+{
+	int err;
+	struct au_vdir_destr *str;
+	struct au_vdir_wh *wh;
+
+	AuDbg("%.*s\n", nlen, name);
+	AuDebugOn(!whlist->nh_num || !whlist->nh_head);
+
+	err = -ENOMEM;
+	wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
+	if (unlikely(!wh))
+		goto out;
+
+	err = 0;
+	wh->wh_bindex = bindex;
+	if (shwh)
+		au_shwh_init_wh(wh, ino, d_type);
+	str = &wh->wh_str;
+	str->len = nlen;
+	memcpy(str->name, name, nlen);
+	hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
+	/* smp_mb(); */
+
+ out:
+	return err;
+}
+
+static int append_deblk(struct au_vdir *vdir)
+{
+	int err;
+	unsigned long ul;
+	const unsigned int deblk_sz = vdir->vd_deblk_sz;
+	union au_vdir_deblk_p p, deblk_end;
+	unsigned char **o;
+
+	err = -ENOMEM;
+	o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
+		     GFP_NOFS);
+	if (unlikely(!o))
+		goto out;
+
+	vdir->vd_deblk = o;
+	p.deblk = kmalloc(deblk_sz, GFP_NOFS);
+	if (p.deblk) {
+		ul = vdir->vd_nblk++;
+		vdir->vd_deblk[ul] = p.deblk;
+		vdir->vd_last.ul = ul;
+		vdir->vd_last.p.deblk = p.deblk;
+		deblk_end.deblk = p.deblk + deblk_sz;
+		err = set_deblk_end(&p, &deblk_end);
+	}
+
+ out:
+	return err;
+}
+
+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
+		     unsigned int d_type, struct au_nhash *delist)
+{
+	int err;
+	unsigned int sz;
+	const unsigned int deblk_sz = vdir->vd_deblk_sz;
+	union au_vdir_deblk_p p, *room, deblk_end;
+	struct au_vdir_dehstr *dehstr;
+
+	p.deblk = last_deblk(vdir);
+	deblk_end.deblk = p.deblk + deblk_sz;
+	room = &vdir->vd_last.p;
+	AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
+		  || !is_deblk_end(room, &deblk_end));
+
+	sz = calc_size(nlen);
+	if (unlikely(sz > deblk_end.deblk - room->deblk)) {
+		err = append_deblk(vdir);
+		if (unlikely(err))
+			goto out;
+
+		p.deblk = last_deblk(vdir);
+		deblk_end.deblk = p.deblk + deblk_sz;
+		/* smp_mb(); */
+		AuDebugOn(room->deblk != p.deblk);
+	}
+
+	err = -ENOMEM;
+	dehstr = au_cache_alloc_dehstr();
+	if (unlikely(!dehstr))
+		goto out;
+
+	dehstr->str = &room->de->de_str;
+	hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
+	room->de->de_ino = ino;
+	room->de->de_type = d_type;
+	room->de->de_str.len = nlen;
+	memcpy(room->de->de_str.name, name, nlen);
+
+	err = 0;
+	room->deblk += sz;
+	if (unlikely(set_deblk_end(room, &deblk_end)))
+		err = append_deblk(vdir);
+	/* smp_mb(); */
+
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void au_vdir_free(struct au_vdir *vdir)
+{
+	unsigned char **deblk;
+
+	deblk = vdir->vd_deblk;
+	while (vdir->vd_nblk--)
+		kfree(*deblk++);
+	kfree(vdir->vd_deblk);
+	au_cache_free_vdir(vdir);
+}
+
+static struct au_vdir *alloc_vdir(struct file *file)
+{
+	struct au_vdir *vdir;
+	struct super_block *sb;
+	int err;
+
+	sb = file->f_dentry->d_sb;
+	SiMustAnyLock(sb);
+
+	err = -ENOMEM;
+	vdir = au_cache_alloc_vdir();
+	if (unlikely(!vdir))
+		goto out;
+
+	vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
+	if (unlikely(!vdir->vd_deblk))
+		goto out_free;
+
+	vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
+	if (!vdir->vd_deblk_sz) {
+		/* estimate the apropriate size for deblk */
+		vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
+		/* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
+	}
+	vdir->vd_nblk = 0;
+	vdir->vd_version = 0;
+	vdir->vd_jiffy = 0;
+	err = append_deblk(vdir);
+	if (!err)
+		return vdir; /* success */
+
+	kfree(vdir->vd_deblk);
+
+ out_free:
+	au_cache_free_vdir(vdir);
+ out:
+	vdir = ERR_PTR(err);
+	return vdir;
+}
+
+static int reinit_vdir(struct au_vdir *vdir)
+{
+	int err;
+	union au_vdir_deblk_p p, deblk_end;
+
+	while (vdir->vd_nblk > 1) {
+		kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
+		/* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
+		vdir->vd_nblk--;
+	}
+	p.deblk = vdir->vd_deblk[0];
+	deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
+	err = set_deblk_end(&p, &deblk_end);
+	/* keep vd_dblk_sz */
+	vdir->vd_last.ul = 0;
+	vdir->vd_last.p.deblk = vdir->vd_deblk[0];
+	vdir->vd_version = 0;
+	vdir->vd_jiffy = 0;
+	/* smp_mb(); */
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define AuFillVdir_CALLED	1
+#define AuFillVdir_WHABLE	(1 << 1)
+#define AuFillVdir_SHWH		(1 << 2)
+#define au_ftest_fillvdir(flags, name)	((flags) & AuFillVdir_##name)
+#define au_fset_fillvdir(flags, name)	{ (flags) |= AuFillVdir_##name; }
+#define au_fclr_fillvdir(flags, name)	{ (flags) &= ~AuFillVdir_##name; }
+
+#ifndef CONFIG_AUFS_SHWH
+#undef AuFillVdir_SHWH
+#define AuFillVdir_SHWH		0
+#endif
+
+struct fillvdir_arg {
+	struct file		*file;
+	struct au_vdir		*vdir;
+	struct au_nhash		delist;
+	struct au_nhash		whlist;
+	aufs_bindex_t		bindex;
+	unsigned int		flags;
+	int			err;
+};
+
+static int fillvdir(void *__arg, const char *__name, int nlen,
+		    loff_t offset __maybe_unused, u64 h_ino,
+		    unsigned int d_type)
+{
+	struct fillvdir_arg *arg = __arg;
+	char *name = (void *)__name;
+	struct super_block *sb;
+	ino_t ino;
+	const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
+
+	arg->err = 0;
+	sb = arg->file->f_dentry->d_sb;
+	au_fset_fillvdir(arg->flags, CALLED);
+	/* smp_mb(); */
+	if (nlen <= AUFS_WH_PFX_LEN
+	    || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
+		if (test_known(&arg->delist, name, nlen)
+		    || au_nhash_test_known_wh(&arg->whlist, name, nlen))
+			goto out; /* already exists or whiteouted */
+
+		sb = arg->file->f_dentry->d_sb;
+		arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
+		if (!arg->err) {
+			if (unlikely(nlen > AUFS_MAX_NAMELEN))
+				d_type = DT_UNKNOWN;
+			arg->err = append_de(arg->vdir, name, nlen, ino,
+					     d_type, &arg->delist);
+		}
+	} else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
+		name += AUFS_WH_PFX_LEN;
+		nlen -= AUFS_WH_PFX_LEN;
+		if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
+			goto out; /* already whiteouted */
+
+		if (shwh)
+			arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
+					     &ino);
+		if (!arg->err) {
+			if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
+				d_type = DT_UNKNOWN;
+			arg->err = au_nhash_append_wh
+				(&arg->whlist, name, nlen, ino, d_type,
+				 arg->bindex, shwh);
+		}
+	}
+
+ out:
+	if (!arg->err)
+		arg->vdir->vd_jiffy = jiffies;
+	/* smp_mb(); */
+	AuTraceErr(arg->err);
+	return arg->err;
+}
+
+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
+			  struct au_nhash *whlist, struct au_nhash *delist)
+{
+#ifdef CONFIG_AUFS_SHWH
+	int err;
+	unsigned int nh, u;
+	struct hlist_head *head;
+	struct au_vdir_wh *tpos;
+	struct hlist_node *pos, *n;
+	char *p, *o;
+	struct au_vdir_destr *destr;
+
+	AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
+
+	err = -ENOMEM;
+	o = p = __getname();
+	if (unlikely(!p))
+		goto out;
+
+	err = 0;
+	nh = whlist->nh_num;
+	memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
+	p += AUFS_WH_PFX_LEN;
+	for (u = 0; u < nh; u++) {
+		head = whlist->nh_head + u;
+		hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
+			destr = &tpos->wh_str;
+			memcpy(p, destr->name, destr->len);
+			err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
+					tpos->wh_ino, tpos->wh_type, delist);
+			if (unlikely(err))
+				break;
+		}
+	}
+
+	__putname(o);
+
+ out:
+	AuTraceErr(err);
+	return err;
+#else
+	return 0;
+#endif
+}
+
+static int au_do_read_vdir(struct fillvdir_arg *arg)
+{
+	int err;
+	unsigned int rdhash;
+	loff_t offset;
+	aufs_bindex_t bend, bindex, bstart;
+	unsigned char shwh;
+	struct file *hf, *file;
+	struct super_block *sb;
+
+	file = arg->file;
+	sb = file->f_dentry->d_sb;
+	SiMustAnyLock(sb);
+
+	rdhash = au_sbi(sb)->si_rdhash;
+	if (!rdhash)
+		rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
+	err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
+	if (unlikely(err))
+		goto out;
+	err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
+	if (unlikely(err))
+		goto out_delist;
+
+	err = 0;
+	arg->flags = 0;
+	shwh = 0;
+	if (au_opt_test(au_mntflags(sb), SHWH)) {
+		shwh = 1;
+		au_fset_fillvdir(arg->flags, SHWH);
+	}
+	bstart = au_fbstart(file);
+	bend = au_fbend(file);
+	for (bindex = bstart; !err && bindex <= bend; bindex++) {
+		hf = au_h_fptr(file, bindex);
+		if (!hf)
+			continue;
+
+		offset = vfsub_llseek(hf, 0, SEEK_SET);
+		err = offset;
+		if (unlikely(offset))
+			break;
+
+		arg->bindex = bindex;
+		au_fclr_fillvdir(arg->flags, WHABLE);
+		if (shwh
+		    || (bindex != bend
+			&& au_br_whable(au_sbr_perm(sb, bindex))))
+			au_fset_fillvdir(arg->flags, WHABLE);
+		do {
+			arg->err = 0;
+			au_fclr_fillvdir(arg->flags, CALLED);
+			/* smp_mb(); */
+			err = vfsub_readdir(hf, fillvdir, arg);
+			if (err >= 0)
+				err = arg->err;
+		} while (!err && au_ftest_fillvdir(arg->flags, CALLED));
+	}
+
+	if (!err && shwh)
+		err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
+
+	au_nhash_wh_free(&arg->whlist);
+
+ out_delist:
+	au_nhash_de_free(&arg->delist);
+ out:
+	return err;
+}
+
+static int read_vdir(struct file *file, int may_read)
+{
+	int err;
+	unsigned long expire;
+	unsigned char do_read;
+	struct fillvdir_arg arg;
+	struct inode *inode;
+	struct au_vdir *vdir, *allocated;
+
+	err = 0;
+	inode = file->f_dentry->d_inode;
+	IMustLock(inode);
+	SiMustAnyLock(inode->i_sb);
+
+	allocated = NULL;
+	do_read = 0;
+	expire = au_sbi(inode->i_sb)->si_rdcache;
+	vdir = au_ivdir(inode);
+	if (!vdir) {
+		do_read = 1;
+		vdir = alloc_vdir(file);
+		err = PTR_ERR(vdir);
+		if (IS_ERR(vdir))
+			goto out;
+		err = 0;
+		allocated = vdir;
+	} else if (may_read
+		   && (inode->i_version != vdir->vd_version
+		       || time_after(jiffies, vdir->vd_jiffy + expire))) {
+		do_read = 1;
+		err = reinit_vdir(vdir);
+		if (unlikely(err))
+			goto out;
+	}
+
+	if (!do_read)
+		return 0; /* success */
+
+	arg.file = file;
+	arg.vdir = vdir;
+	err = au_do_read_vdir(&arg);
+	if (!err) {
+		/* file->f_pos = 0; */
+		vdir->vd_version = inode->i_version;
+		vdir->vd_last.ul = 0;
+		vdir->vd_last.p.deblk = vdir->vd_deblk[0];
+		if (allocated)
+			au_set_ivdir(inode, allocated);
+	} else if (allocated)
+		au_vdir_free(allocated);
+
+ out:
+	return err;
+}
+
+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
+{
+	int err, rerr;
+	unsigned long ul, n;
+	const unsigned int deblk_sz = src->vd_deblk_sz;
+
+	AuDebugOn(tgt->vd_nblk != 1);
+
+	err = -ENOMEM;
+	if (tgt->vd_nblk < src->vd_nblk) {
+		unsigned char **p;
+
+		p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
+			     GFP_NOFS);
+		if (unlikely(!p))
+			goto out;
+		tgt->vd_deblk = p;
+	}
+
+	if (tgt->vd_deblk_sz != deblk_sz) {
+		unsigned char *p;
+
+		tgt->vd_deblk_sz = deblk_sz;
+		p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
+		if (unlikely(!p))
+			goto out;
+		tgt->vd_deblk[0] = p;
+	}
+	memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
+	tgt->vd_version = src->vd_version;
+	tgt->vd_jiffy = src->vd_jiffy;
+
+	n = src->vd_nblk;
+	for (ul = 1; ul < n; ul++) {
+		tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
+					    GFP_NOFS);
+		if (unlikely(!tgt->vd_deblk[ul]))
+			goto out;
+		tgt->vd_nblk++;
+	}
+	tgt->vd_nblk = n;
+	tgt->vd_last.ul = tgt->vd_last.ul;
+	tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
+	tgt->vd_last.p.deblk += src->vd_last.p.deblk
+		- src->vd_deblk[src->vd_last.ul];
+	/* smp_mb(); */
+	return 0; /* success */
+
+ out:
+	rerr = reinit_vdir(tgt);
+	BUG_ON(rerr);
+	return err;
+}
+
+int au_vdir_init(struct file *file)
+{
+	int err;
+	struct inode *inode;
+	struct au_vdir *vdir_cache, *allocated;
+
+	err = read_vdir(file, !file->f_pos);
+	if (unlikely(err))
+		goto out;
+
+	allocated = NULL;
+	vdir_cache = au_fvdir_cache(file);
+	if (!vdir_cache) {
+		vdir_cache = alloc_vdir(file);
+		err = PTR_ERR(vdir_cache);
+		if (IS_ERR(vdir_cache))
+			goto out;
+		allocated = vdir_cache;
+	} else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
+		err = reinit_vdir(vdir_cache);
+		if (unlikely(err))
+			goto out;
+	} else
+		return 0; /* success */
+
+	inode = file->f_dentry->d_inode;
+	err = copy_vdir(vdir_cache, au_ivdir(inode));
+	if (!err) {
+		file->f_version = inode->i_version;
+		if (allocated)
+			au_set_fvdir_cache(file, allocated);
+	} else if (allocated)
+		au_vdir_free(allocated);
+
+ out:
+	return err;
+}
+
+static loff_t calc_offset(struct au_vdir *vdir)
+{
+	loff_t offset;
+	union au_vdir_deblk_p p;
+
+	p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
+	offset = vdir->vd_last.p.deblk - p.deblk;
+	offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
+	return offset;
+}
+
+/* returns true or false */
+static int seek_vdir(struct file *file)
+{
+	int valid;
+	unsigned int deblk_sz;
+	unsigned long ul, n;
+	loff_t offset;
+	union au_vdir_deblk_p p, deblk_end;
+	struct au_vdir *vdir_cache;
+
+	valid = 1;
+	vdir_cache = au_fvdir_cache(file);
+	offset = calc_offset(vdir_cache);
+	AuDbg("offset %lld\n", offset);
+	if (file->f_pos == offset)
+		goto out;
+
+	vdir_cache->vd_last.ul = 0;
+	vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
+	if (!file->f_pos)
+		goto out;
+
+	valid = 0;
+	deblk_sz = vdir_cache->vd_deblk_sz;
+	ul = div64_u64(file->f_pos, deblk_sz);
+	AuDbg("ul %lu\n", ul);
+	if (ul >= vdir_cache->vd_nblk)
+		goto out;
+
+	n = vdir_cache->vd_nblk;
+	for (; ul < n; ul++) {
+		p.deblk = vdir_cache->vd_deblk[ul];
+		deblk_end.deblk = p.deblk + deblk_sz;
+		offset = ul;
+		offset *= deblk_sz;
+		while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
+			unsigned int l;
+
+			l = calc_size(p.de->de_str.len);
+			offset += l;
+			p.deblk += l;
+		}
+		if (!is_deblk_end(&p, &deblk_end)) {
+			valid = 1;
+			vdir_cache->vd_last.ul = ul;
+			vdir_cache->vd_last.p = p;
+			break;
+		}
+	}
+
+ out:
+	/* smp_mb(); */
+	AuTraceErr(!valid);
+	return valid;
+}
+
+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
+{
+	int err;
+	unsigned int l, deblk_sz;
+	union au_vdir_deblk_p deblk_end;
+	struct au_vdir *vdir_cache;
+	struct au_vdir_de *de;
+
+	vdir_cache = au_fvdir_cache(file);
+	if (!seek_vdir(file))
+		return 0;
+
+	deblk_sz = vdir_cache->vd_deblk_sz;
+	while (1) {
+		deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
+		deblk_end.deblk += deblk_sz;
+		while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
+			de = vdir_cache->vd_last.p.de;
+			AuDbg("%.*s, off%lld, i%lu, dt%d\n",
+			      de->de_str.len, de->de_str.name, file->f_pos,
+			      (unsigned long)de->de_ino, de->de_type);
+			err = filldir(dirent, de->de_str.name, de->de_str.len,
+				      file->f_pos, de->de_ino, de->de_type);
+			if (unlikely(err)) {
+				AuTraceErr(err);
+				/* todo: ignore the error caused by udba? */
+				/* return err; */
+				return 0;
+			}
+
+			l = calc_size(de->de_str.len);
+			vdir_cache->vd_last.p.deblk += l;
+			file->f_pos += l;
+		}
+		if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
+			vdir_cache->vd_last.ul++;
+			vdir_cache->vd_last.p.deblk
+				= vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
+			file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
+			continue;
+		}
+		break;
+	}
+
+	/* smp_mb(); */
+	return 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/sysrq.c
+++ linux-ec2-2.6.32/ubuntu/aufs/sysrq.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * magic sysrq hanlder
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+/* #include <linux/sysrq.h> */
+#include "aufs.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void sysrq_sb(struct super_block *sb)
+{
+	char *plevel;
+	struct au_sbinfo *sbinfo;
+	struct file *file;
+
+	plevel = au_plevel;
+	au_plevel = KERN_WARNING;
+	au_debug(1);
+
+	sbinfo = au_sbi(sb);
+	/* since we define pr_fmt, call printk directly */
+	printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
+	printk(KERN_WARNING AUFS_NAME ": superblock\n");
+	au_dpri_sb(sb);
+	printk(KERN_WARNING AUFS_NAME ": root dentry\n");
+	au_dpri_dentry(sb->s_root);
+	printk(KERN_WARNING AUFS_NAME ": root inode\n");
+	au_dpri_inode(sb->s_root->d_inode);
+#if 0
+	struct inode *i;
+	printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
+	list_for_each_entry(i, &sb->s_inodes, i_sb_list)
+		if (list_empty(&i->i_dentry))
+			au_dpri_inode(i);
+#endif
+	printk(KERN_WARNING AUFS_NAME ": files\n");
+	list_for_each_entry(file, &sb->s_files, f_u.fu_list)
+		if (!special_file(file->f_dentry->d_inode->i_mode))
+			au_dpri_file(file);
+
+	au_plevel = plevel;
+	au_debug(0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* module parameter */
+static char *aufs_sysrq_key = "a";
+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
+
+static void au_sysrq(int key __maybe_unused,
+		     struct tty_struct *tty __maybe_unused)
+{
+	struct kobject *kobj;
+	struct au_sbinfo *sbinfo;
+
+	/* spin_lock(&sysaufs_ket->list_lock); */
+	list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
+		sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
+		sysrq_sb(sbinfo->si_sb);
+	}
+	/* spin_unlock(&sysaufs_ket->list_lock); */
+}
+
+static struct sysrq_key_op au_sysrq_op = {
+	.handler	= au_sysrq,
+	.help_msg	= "Aufs",
+	.action_msg	= "Aufs",
+	.enable_mask	= SYSRQ_ENABLE_DUMP
+};
+
+/* ---------------------------------------------------------------------- */
+
+int __init au_sysrq_init(void)
+{
+	int err;
+	char key;
+
+	err = -1;
+	key = *aufs_sysrq_key;
+	if ('a' <= key && key <= 'z')
+		err = register_sysrq_key(key, &au_sysrq_op);
+	if (unlikely(err))
+		pr_err("err %d, sysrq=%c\n", err, key);
+	return err;
+}
+
+void au_sysrq_fin(void)
+{
+	int err;
+	err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
+	if (unlikely(err))
+		pr_err("err %d (ignored)\n", err);
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/i_op_add.c
+++ linux-ec2-2.6.32/ubuntu/aufs/i_op_add.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode operations (add entry)
+ */
+
+#include "aufs.h"
+
+/*
+ * final procedure of adding a new entry, except link(2).
+ * remove whiteout, instantiate, copyup the parent dir's times and size
+ * and update version.
+ * if it failed, re-create the removed whiteout.
+ */
+static int epilog(struct inode *dir, aufs_bindex_t bindex,
+		  struct dentry *wh_dentry, struct dentry *dentry)
+{
+	int err, rerr;
+	aufs_bindex_t bwh;
+	struct path h_path;
+	struct inode *inode, *h_dir;
+	struct dentry *wh;
+
+	bwh = -1;
+	if (wh_dentry) {
+		h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
+		IMustLock(h_dir);
+		AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
+		bwh = au_dbwh(dentry);
+		h_path.dentry = wh_dentry;
+		h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
+		err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
+					  dentry);
+		if (unlikely(err))
+			goto out;
+	}
+
+	inode = au_new_inode(dentry, /*must_new*/1);
+	if (!IS_ERR(inode)) {
+		d_instantiate(dentry, inode);
+		dir = dentry->d_parent->d_inode; /* dir inode is locked */
+		IMustLock(dir);
+		if (au_ibstart(dir) == au_dbstart(dentry))
+			au_cpup_attr_timesizes(dir);
+		dir->i_version++;
+		return 0; /* success */
+	}
+
+	err = PTR_ERR(inode);
+	if (!wh_dentry)
+		goto out;
+
+	/* revert */
+	/* dir inode is locked */
+	wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
+	rerr = PTR_ERR(wh);
+	if (IS_ERR(wh)) {
+		AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
+			AuDLNPair(dentry), err, rerr);
+		err = -EIO;
+	} else
+		dput(wh);
+
+ out:
+	return err;
+}
+
+/*
+ * simple tests for the adding inode operations.
+ * following the checks in vfs, plus the parent-child relationship.
+ */
+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
+	       struct dentry *h_parent, int isdir)
+{
+	int err;
+	umode_t h_mode;
+	struct dentry *h_dentry;
+	struct inode *h_inode;
+
+	err = -ENAMETOOLONG;
+	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
+		goto out;
+
+	h_dentry = au_h_dptr(dentry, bindex);
+	h_inode = h_dentry->d_inode;
+	if (!dentry->d_inode) {
+		err = -EEXIST;
+		if (unlikely(h_inode))
+			goto out;
+	} else {
+		/* rename(2) case */
+		err = -EIO;
+		if (unlikely(!h_inode || !h_inode->i_nlink))
+			goto out;
+
+		h_mode = h_inode->i_mode;
+		if (!isdir) {
+			err = -EISDIR;
+			if (unlikely(S_ISDIR(h_mode)))
+				goto out;
+		} else if (unlikely(!S_ISDIR(h_mode))) {
+			err = -ENOTDIR;
+			goto out;
+		}
+	}
+
+	err = -EIO;
+	/* expected parent dir is locked */
+	if (unlikely(h_parent != h_dentry->d_parent))
+		goto out;
+	err = 0;
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+/*
+ * initial procedure of adding a new entry.
+ * prepare writable branch and the parent dir, lock it,
+ * and lookup whiteout for the new entry.
+ */
+static struct dentry*
+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
+		  struct dentry *src_dentry, struct au_pin *pin,
+		  struct au_wr_dir_args *wr_dir_args)
+{
+	struct dentry *wh_dentry, *h_parent;
+	struct super_block *sb;
+	struct au_branch *br;
+	int err;
+	unsigned int udba;
+	aufs_bindex_t bcpup;
+
+	AuDbg("%.*s\n", AuDLNPair(dentry));
+
+	err = au_wr_dir(dentry, src_dentry, wr_dir_args);
+	bcpup = err;
+	wh_dentry = ERR_PTR(err);
+	if (unlikely(err < 0))
+		goto out;
+
+	sb = dentry->d_sb;
+	udba = au_opt_udba(sb);
+	err = au_pin(pin, dentry, bcpup, udba,
+		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+	wh_dentry = ERR_PTR(err);
+	if (unlikely(err))
+		goto out;
+
+	h_parent = au_pinned_h_parent(pin);
+	if (udba != AuOpt_UDBA_NONE
+	    && au_dbstart(dentry) == bcpup)
+		err = au_may_add(dentry, bcpup, h_parent,
+				 au_ftest_wrdir(wr_dir_args->flags, ISDIR));
+	else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
+		err = -ENAMETOOLONG;
+	wh_dentry = ERR_PTR(err);
+	if (unlikely(err))
+		goto out_unpin;
+
+	br = au_sbr(sb, bcpup);
+	if (dt) {
+		struct path tmp = {
+			.dentry	= h_parent,
+			.mnt	= br->br_mnt
+		};
+		au_dtime_store(dt, au_pinned_parent(pin), &tmp);
+	}
+
+	wh_dentry = NULL;
+	if (bcpup != au_dbwh(dentry))
+		goto out; /* success */
+
+	wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
+
+ out_unpin:
+	if (IS_ERR(wh_dentry))
+		au_unpin(pin);
+ out:
+	return wh_dentry;
+}
+
+/* ---------------------------------------------------------------------- */
+
+enum { Mknod, Symlink, Creat };
+struct simple_arg {
+	int type;
+	union {
+		struct {
+			int mode;
+			struct nameidata *nd;
+		} c;
+		struct {
+			const char *symname;
+		} s;
+		struct {
+			int mode;
+			dev_t dev;
+		} m;
+	} u;
+};
+
+static int add_simple(struct inode *dir, struct dentry *dentry,
+		      struct simple_arg *arg)
+{
+	int err;
+	aufs_bindex_t bstart;
+	unsigned char created;
+	struct au_dtime dt;
+	struct au_pin pin;
+	struct path h_path;
+	struct dentry *wh_dentry, *parent;
+	struct inode *h_dir;
+	struct au_wr_dir_args wr_dir_args = {
+		.force_btgt	= -1,
+		.flags		= AuWrDir_ADD_ENTRY
+	};
+
+	AuDbg("%.*s\n", AuDLNPair(dentry));
+	IMustLock(dir);
+
+	parent = dentry->d_parent; /* dir inode is locked */
+	aufs_read_lock(dentry, AuLock_DW);
+	di_write_lock_parent(parent);
+	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
+				      &wr_dir_args);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out;
+
+	bstart = au_dbstart(dentry);
+	h_path.dentry = au_h_dptr(dentry, bstart);
+	h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
+	h_dir = au_pinned_h_dir(&pin);
+	switch (arg->type) {
+	case Creat:
+		err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
+		break;
+	case Symlink:
+		err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
+		break;
+	case Mknod:
+		err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
+		break;
+	default:
+		BUG();
+	}
+	created = !err;
+	if (!err)
+		err = epilog(dir, bstart, wh_dentry, dentry);
+
+	/* revert */
+	if (unlikely(created && err && h_path.dentry->d_inode)) {
+		int rerr;
+		rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
+		if (rerr) {
+			AuIOErr("%.*s revert failure(%d, %d)\n",
+				AuDLNPair(dentry), err, rerr);
+			err = -EIO;
+		}
+		au_dtime_revert(&dt);
+		d_drop(dentry);
+	}
+
+	au_unpin(&pin);
+	dput(wh_dentry);
+
+ out:
+	if (unlikely(err)) {
+		au_update_dbstart(dentry);
+		d_drop(dentry);
+	}
+	di_write_unlock(parent);
+	aufs_read_unlock(dentry, AuLock_DW);
+	return err;
+}
+
+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+	struct simple_arg arg = {
+		.type = Mknod,
+		.u.m = {
+			.mode	= mode,
+			.dev	= dev
+		}
+	};
+	return add_simple(dir, dentry, &arg);
+}
+
+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+	struct simple_arg arg = {
+		.type = Symlink,
+		.u.s.symname = symname
+	};
+	return add_simple(dir, dentry, &arg);
+}
+
+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
+{
+	struct simple_arg arg = {
+		.type = Creat,
+		.u.c = {
+			.mode	= mode,
+			.nd	= nd
+		}
+	};
+	return add_simple(dir, dentry, &arg);
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct au_link_args {
+	aufs_bindex_t bdst, bsrc;
+	struct au_pin pin;
+	struct path h_path;
+	struct dentry *src_parent, *parent;
+};
+
+static int au_cpup_before_link(struct dentry *src_dentry,
+			       struct au_link_args *a)
+{
+	int err;
+	struct dentry *h_src_dentry;
+	struct mutex *h_mtx;
+
+	di_read_lock_parent(a->src_parent, AuLock_IR);
+	err = au_test_and_cpup_dirs(src_dentry, a->bdst);
+	if (unlikely(err))
+		goto out;
+
+	h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
+	h_mtx = &h_src_dentry->d_inode->i_mutex;
+	err = au_pin(&a->pin, src_dentry, a->bdst,
+		     au_opt_udba(src_dentry->d_sb),
+		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+	if (unlikely(err))
+		goto out;
+	mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+	err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
+				 AuCpup_DTIME /* | AuCpup_KEEPLINO */);
+	mutex_unlock(h_mtx);
+	au_unpin(&a->pin);
+
+ out:
+	di_read_unlock(a->src_parent, AuLock_IR);
+	return err;
+}
+
+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
+{
+	int err;
+	unsigned char plink;
+	struct inode *h_inode, *inode;
+	struct dentry *h_src_dentry;
+	struct super_block *sb;
+
+	plink = 0;
+	h_inode = NULL;
+	sb = src_dentry->d_sb;
+	inode = src_dentry->d_inode;
+	if (au_ibstart(inode) <= a->bdst)
+		h_inode = au_h_iptr(inode, a->bdst);
+	if (!h_inode || !h_inode->i_nlink) {
+		/* copyup src_dentry as the name of dentry. */
+		au_set_dbstart(src_dentry, a->bdst);
+		au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
+		h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
+		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+		err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
+					 AuCpup_KEEPLINO, a->parent);
+		mutex_unlock(&h_inode->i_mutex);
+		au_set_h_dptr(src_dentry, a->bdst, NULL);
+		au_set_dbstart(src_dentry, a->bsrc);
+	} else {
+		/* the inode of src_dentry already exists on a.bdst branch */
+		h_src_dentry = d_find_alias(h_inode);
+		if (!h_src_dentry && au_plink_test(inode)) {
+			plink = 1;
+			h_src_dentry = au_plink_lkup(inode, a->bdst);
+			err = PTR_ERR(h_src_dentry);
+			if (IS_ERR(h_src_dentry))
+				goto out;
+
+			if (unlikely(!h_src_dentry->d_inode)) {
+				dput(h_src_dentry);
+				h_src_dentry = NULL;
+			}
+
+		}
+		if (h_src_dentry) {
+			err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
+					 &a->h_path);
+			dput(h_src_dentry);
+		} else {
+			AuIOErr("no dentry found for hi%lu on b%d\n",
+				h_inode->i_ino, a->bdst);
+			err = -EIO;
+		}
+	}
+
+	if (!err && !plink)
+		au_plink_append(inode, a->bdst, a->h_path.dentry);
+
+out:
+	return err;
+}
+
+int aufs_link(struct dentry *src_dentry, struct inode *dir,
+	      struct dentry *dentry)
+{
+	int err, rerr;
+	struct au_dtime dt;
+	struct au_link_args *a;
+	struct dentry *wh_dentry, *h_src_dentry;
+	struct inode *inode;
+	struct super_block *sb;
+	struct au_wr_dir_args wr_dir_args = {
+		/* .force_btgt	= -1, */
+		.flags		= AuWrDir_ADD_ENTRY
+	};
+
+	IMustLock(dir);
+	inode = src_dentry->d_inode;
+	IMustLock(inode);
+
+	err = -ENOENT;
+	if (unlikely(!inode->i_nlink))
+		goto out;
+
+	err = -ENOMEM;
+	a = kzalloc(sizeof(*a), GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	a->parent = dentry->d_parent; /* dir inode is locked */
+	aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
+	a->src_parent = dget_parent(src_dentry);
+	wr_dir_args.force_btgt = au_dbstart(src_dentry);
+
+	di_write_lock_parent(a->parent);
+	wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
+	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
+				      &wr_dir_args);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out_unlock;
+
+	err = 0;
+	sb = dentry->d_sb;
+	a->bdst = au_dbstart(dentry);
+	a->h_path.dentry = au_h_dptr(dentry, a->bdst);
+	a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
+	a->bsrc = au_dbstart(src_dentry);
+	if (au_opt_test(au_mntflags(sb), PLINK)) {
+		if (a->bdst < a->bsrc
+		    /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
+			err = au_cpup_or_link(src_dentry, a);
+		else {
+			h_src_dentry = au_h_dptr(src_dentry, a->bdst);
+			err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
+					 &a->h_path);
+		}
+	} else {
+		/*
+		 * copyup src_dentry to the branch we process,
+		 * and then link(2) to it.
+		 */
+		if (a->bdst < a->bsrc
+		    /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
+			au_unpin(&a->pin);
+			di_write_unlock(a->parent);
+			err = au_cpup_before_link(src_dentry, a);
+			di_write_lock_parent(a->parent);
+			if (!err)
+				err = au_pin(&a->pin, dentry, a->bdst,
+					     au_opt_udba(sb),
+					     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+			if (unlikely(err))
+				goto out_wh;
+		}
+		if (!err) {
+			h_src_dentry = au_h_dptr(src_dentry, a->bdst);
+			err = -ENOENT;
+			if (h_src_dentry && h_src_dentry->d_inode)
+				err = vfsub_link(h_src_dentry,
+						 au_pinned_h_dir(&a->pin),
+						 &a->h_path);
+		}
+	}
+	if (unlikely(err))
+		goto out_unpin;
+
+	if (wh_dentry) {
+		a->h_path.dentry = wh_dentry;
+		err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
+					  dentry);
+		if (unlikely(err))
+			goto out_revert;
+	}
+
+	dir->i_version++;
+	if (au_ibstart(dir) == au_dbstart(dentry))
+		au_cpup_attr_timesizes(dir);
+	inc_nlink(inode);
+	inode->i_ctime = dir->i_ctime;
+	if (!d_unhashed(a->h_path.dentry))
+		d_instantiate(dentry, au_igrab(inode));
+	else
+		/* some filesystem calls d_drop() */
+		d_drop(dentry);
+	goto out_unpin; /* success */
+
+ out_revert:
+	rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
+	if (!rerr)
+		goto out_dt;
+	AuIOErr("%.*s reverting failed(%d, %d)\n",
+		AuDLNPair(dentry), err, rerr);
+	err = -EIO;
+ out_dt:
+	d_drop(dentry);
+	au_dtime_revert(&dt);
+ out_unpin:
+	au_unpin(&a->pin);
+ out_wh:
+	dput(wh_dentry);
+ out_unlock:
+	if (unlikely(err)) {
+		au_update_dbstart(dentry);
+		d_drop(dentry);
+	}
+	di_write_unlock(a->parent);
+	dput(a->src_parent);
+	aufs_read_and_write_unlock2(dentry, src_dentry);
+	kfree(a);
+ out:
+	return err;
+}
+
+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int err, rerr;
+	aufs_bindex_t bindex;
+	unsigned char diropq;
+	struct path h_path;
+	struct dentry *wh_dentry, *parent, *opq_dentry;
+	struct mutex *h_mtx;
+	struct super_block *sb;
+	struct {
+		struct au_pin pin;
+		struct au_dtime dt;
+	} *a; /* reduce the stack usage */
+	struct au_wr_dir_args wr_dir_args = {
+		.force_btgt	= -1,
+		.flags		= AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
+	};
+
+	IMustLock(dir);
+
+	err = -ENOMEM;
+	a = kmalloc(sizeof(*a), GFP_NOFS);
+	if (unlikely(!a))
+		goto out;
+
+	aufs_read_lock(dentry, AuLock_DW);
+	parent = dentry->d_parent; /* dir inode is locked */
+	di_write_lock_parent(parent);
+	wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
+				      &a->pin, &wr_dir_args);
+	err = PTR_ERR(wh_dentry);
+	if (IS_ERR(wh_dentry))
+		goto out_free;
+
+	sb = dentry->d_sb;
+	bindex = au_dbstart(dentry);
+	h_path.dentry = au_h_dptr(dentry, bindex);
+	h_path.mnt = au_sbr_mnt(sb, bindex);
+	err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
+	if (unlikely(err))
+		goto out_unlock;
+
+	/* make the dir opaque */
+	diropq = 0;
+	h_mtx = &h_path.dentry->d_inode->i_mutex;
+	if (wh_dentry
+	    || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		opq_dentry = au_diropq_create(dentry, bindex);
+		mutex_unlock(h_mtx);
+		err = PTR_ERR(opq_dentry);
+		if (IS_ERR(opq_dentry))
+			goto out_dir;
+		dput(opq_dentry);
+		diropq = 1;
+	}
+
+	err = epilog(dir, bindex, wh_dentry, dentry);
+	if (!err) {
+		inc_nlink(dir);
+		goto out_unlock; /* success */
+	}
+
+	/* revert */
+	if (diropq) {
+		AuLabel(revert opq);
+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
+		rerr = au_diropq_remove(dentry, bindex);
+		mutex_unlock(h_mtx);
+		if (rerr) {
+			AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
+				AuDLNPair(dentry), err, rerr);
+			err = -EIO;
+		}
+	}
+
+ out_dir:
+	AuLabel(revert dir);
+	rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
+	if (rerr) {
+		AuIOErr("%.*s reverting dir failed(%d, %d)\n",
+			AuDLNPair(dentry), err, rerr);
+		err = -EIO;
+	}
+	d_drop(dentry);
+	au_dtime_revert(&a->dt);
+ out_unlock:
+	au_unpin(&a->pin);
+	dput(wh_dentry);
+ out_free:
+	if (unlikely(err)) {
+		au_update_dbstart(dentry);
+		d_drop(dentry);
+	}
+	di_write_unlock(parent);
+	aufs_read_unlock(dentry, AuLock_DW);
+	kfree(a);
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/aufs.h
+++ linux-ec2-2.6.32/ubuntu/aufs/aufs.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * all header files
+ */
+
+#ifndef __AUFS_H__
+#define __AUFS_H__
+
+#ifdef __KERNEL__
+
+#include "debug.h"
+
+#include "branch.h"
+#include "cpup.h"
+#include "dcsub.h"
+#include "dbgaufs.h"
+#include "dentry.h"
+#include "dir.h"
+#include "file.h"
+#include "fstype.h"
+#include "inode.h"
+#include "loop.h"
+#include "module.h"
+#include "opts.h"
+#include "rwsem.h"
+#include "spl.h"
+#include "super.h"
+#include "sysaufs.h"
+#include "vfsub.h"
+#include "whout.h"
+#include "wkq.h"
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/fstype.h
+++ linux-ec2-2.6.32/ubuntu/aufs/fstype.h
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * judging filesystem type
+ */
+
+#ifndef __AUFS_FSTYPE_H__
+#define __AUFS_FSTYPE_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/magic.h>
+#include <linux/romfs_fs.h>
+#include <linux/aufs_type.h>
+
+static inline int au_test_aufs(struct super_block *sb)
+{
+	return sb->s_magic == AUFS_SUPER_MAGIC;
+}
+
+static inline const char *au_sbtype(struct super_block *sb)
+{
+	return sb->s_type->name;
+}
+
+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
+	return sb->s_magic == ROMFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
+	return sb->s_magic == ISOFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
+	return sb->s_magic == CRAMFS_MAGIC;
+#endif
+	return 0;
+}
+
+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
+	return sb->s_magic == NFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
+	return sb->s_magic == FUSE_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
+	return sb->s_magic == XFS_SB_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
+{
+#ifdef CONFIG_TMPFS
+	return sb->s_magic == TMPFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
+	return !strcmp(au_sbtype(sb), "ecryptfs");
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
+	return sb->s_magic == SMB_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
+	return sb->s_magic == OCFS2_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
+	return sb->s_magic == DLMFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_coda(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
+	return sb->s_magic == CODA_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
+	return sb->s_magic == V9FS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
+	return sb->s_magic == EXT4_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
+	return !strcmp(au_sbtype(sb), "sysv");
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_ramfs(struct super_block *sb)
+{
+	return sb->s_magic == RAMFS_MAGIC;
+}
+
+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
+	return sb->s_magic == UBIFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
+{
+#ifdef CONFIG_PROC_FS
+	return sb->s_magic == PROC_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
+{
+#ifdef CONFIG_SYSFS
+	return sb->s_magic == SYSFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
+	return sb->s_magic == CONFIGFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_minix(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
+	return sb->s_magic == MINIX3_SUPER_MAGIC
+		|| sb->s_magic == MINIX2_SUPER_MAGIC
+		|| sb->s_magic == MINIX2_SUPER_MAGIC2
+		|| sb->s_magic == MINIX_SUPER_MAGIC
+		|| sb->s_magic == MINIX_SUPER_MAGIC2;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
+	return sb->s_magic == CIFS_MAGIC_NUMBER;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_fat(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
+	return sb->s_magic == MSDOS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_msdos(struct super_block *sb)
+{
+	return au_test_fat(sb);
+}
+
+static inline int au_test_vfat(struct super_block *sb)
+{
+	return au_test_fat(sb);
+}
+
+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
+{
+#ifdef CONFIG_SECURITYFS
+	return sb->s_magic == SECURITYFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
+	return sb->s_magic == SQUASHFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
+	return sb->s_magic == BTRFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
+	return sb->s_magic == XENFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
+{
+#ifdef CONFIG_DEBUG_FS
+	return sb->s_magic == DEBUGFS_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
+{
+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
+	return sb->s_magic == NILFS_SUPER_MAGIC;
+#else
+	return 0;
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * they can't be an aufs branch.
+ */
+static inline int au_test_fs_unsuppoted(struct super_block *sb)
+{
+	return
+#ifndef CONFIG_AUFS_BR_RAMFS
+		au_test_ramfs(sb) ||
+#endif
+		au_test_procfs(sb)
+		|| au_test_sysfs(sb)
+		|| au_test_configfs(sb)
+		|| au_test_debugfs(sb)
+		|| au_test_securityfs(sb)
+		|| au_test_xenfs(sb)
+		|| au_test_ecryptfs(sb)
+		/* || !strcmp(au_sbtype(sb), "unionfs") */
+		|| au_test_aufs(sb); /* will be supported in next version */
+}
+
+/*
+ * If the filesystem supports NFS-export, then it has to support NULL as
+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
+ * We can apply this principle when we handle a lower filesystem.
+ */
+static inline int au_test_fs_null_nd(struct super_block *sb)
+{
+	return !!sb->s_export_op;
+}
+
+static inline int au_test_fs_remote(struct super_block *sb)
+{
+	return !au_test_tmpfs(sb)
+#ifdef CONFIG_AUFS_BR_RAMFS
+		&& !au_test_ramfs(sb)
+#endif
+		&& !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Note: these functions (below) are created after reading ->getattr() in all
+ * filesystems under linux/fs. it means we have to do so in every update...
+ */
+
+/*
+ * some filesystems require getattr to refresh the inode attributes before
+ * referencing.
+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
+ * and leave the work for d_revalidate()
+ */
+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
+{
+	return au_test_nfs(sb)
+		|| au_test_fuse(sb)
+		/* || au_test_smbfs(sb) */	/* untested */
+		/* || au_test_ocfs2(sb) */	/* untested */
+		/* || au_test_btrfs(sb) */	/* untested */
+		/* || au_test_coda(sb) */	/* untested */
+		/* || au_test_v9fs(sb) */	/* untested */
+		;
+}
+
+/*
+ * filesystems which don't maintain i_size or i_blocks.
+ */
+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
+{
+	return au_test_xfs(sb)
+		/* || au_test_ext4(sb) */	/* untested */
+		/* || au_test_ocfs2(sb) */	/* untested */
+		/* || au_test_ocfs2_dlmfs(sb) */ /* untested */
+		/* || au_test_sysv(sb) */	/* untested */
+		/* || au_test_ubifs(sb) */	/* untested */
+		/* || au_test_minix(sb) */	/* untested */
+		;
+}
+
+/*
+ * filesystems which don't store the correct value in some of their inode
+ * attributes.
+ */
+static inline int au_test_fs_bad_iattr(struct super_block *sb)
+{
+	return au_test_fs_bad_iattr_size(sb)
+		/* || au_test_cifs(sb) */	/* untested */
+		|| au_test_fat(sb)
+		|| au_test_msdos(sb)
+		|| au_test_vfat(sb);
+}
+
+/* they don't check i_nlink in link(2) */
+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
+{
+	return au_test_tmpfs(sb)
+#ifdef CONFIG_AUFS_BR_RAMFS
+		|| au_test_ramfs(sb)
+#endif
+		|| au_test_ubifs(sb);
+}
+
+/*
+ * filesystems which sets S_NOATIME and S_NOCMTIME.
+ */
+static inline int au_test_fs_notime(struct super_block *sb)
+{
+	return au_test_nfs(sb)
+		|| au_test_fuse(sb)
+		|| au_test_ubifs(sb)
+		/* || au_test_cifs(sb) */	/* untested */
+		;
+}
+
+/*
+ * filesystems which requires replacing i_mapping.
+ */
+static inline int au_test_fs_bad_mapping(struct super_block *sb)
+{
+	return au_test_fuse(sb)
+		|| au_test_ubifs(sb);
+}
+
+/* temporary support for i#1 in cramfs */
+static inline int au_test_fs_unique_ino(struct inode *inode)
+{
+	if (au_test_cramfs(inode->i_sb))
+		return inode->i_ino != 1;
+	return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * the filesystem where the xino files placed must support i/o after unlink and
+ * maintain i_size and i_blocks.
+ */
+static inline int au_test_fs_bad_xino(struct super_block *sb)
+{
+	return au_test_fs_remote(sb)
+		|| au_test_fs_bad_iattr_size(sb)
+#ifdef CONFIG_AUFS_BR_RAMFS
+		|| !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
+#else
+		|| !au_test_fs_null_nd(sb) /* to keep xino code simple */
+#endif
+		/* don't want unnecessary work for xino */
+		|| au_test_aufs(sb)
+		|| au_test_ecryptfs(sb)
+		|| au_test_nilfs(sb);
+}
+
+static inline int au_test_fs_trunc_xino(struct super_block *sb)
+{
+	return au_test_tmpfs(sb)
+		|| au_test_ramfs(sb);
+}
+
+/*
+ * test if the @sb is real-readonly.
+ */
+static inline int au_test_fs_rr(struct super_block *sb)
+{
+	return au_test_squashfs(sb)
+		|| au_test_iso9660(sb)
+		|| au_test_cramfs(sb)
+		|| au_test_romfs(sb);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_FSTYPE_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/module.c
+++ linux-ec2-2.6.32/ubuntu/aufs/module.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * module global variables and operations
+ */
+
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include "aufs.h"
+
+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
+{
+	if (new_sz <= nused)
+		return p;
+
+	p = krealloc(p, new_sz, gfp);
+	if (p)
+		memset(p + nused, 0, new_sz - nused);
+	return p;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * aufs caches
+ */
+struct kmem_cache *au_cachep[AuCache_Last];
+static int __init au_cache_init(void)
+{
+	au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
+	if (au_cachep[AuCache_DINFO])
+		au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
+	if (au_cachep[AuCache_ICNTNR])
+		au_cachep[AuCache_FINFO] = AuCache(au_finfo);
+	if (au_cachep[AuCache_FINFO])
+		au_cachep[AuCache_VDIR] = AuCache(au_vdir);
+	if (au_cachep[AuCache_VDIR])
+		au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
+	if (au_cachep[AuCache_DEHSTR])
+		return 0;
+
+	return -ENOMEM;
+}
+
+static void au_cache_fin(void)
+{
+	int i;
+	for (i = 0; i < AuCache_Last; i++)
+		if (au_cachep[i]) {
+			kmem_cache_destroy(au_cachep[i]);
+			au_cachep[i] = NULL;
+		}
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_dir_roflags;
+
+/*
+ * functions for module interface.
+ */
+MODULE_LICENSE("GPL");
+/* MODULE_LICENSE("GPL v2"); */
+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
+MODULE_DESCRIPTION(AUFS_NAME
+	" -- Advanced multi layered unification filesystem");
+MODULE_VERSION(AUFS_VERSION);
+
+/* it should be 'byte', but param_set_byte() prints it by "%c" */
+short aufs_nwkq = AUFS_NWKQ_DEF;
+MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
+module_param_named(nwkq, aufs_nwkq, short, S_IRUGO);
+
+/* this module parameter has no meaning when SYSFS is disabled */
+int sysaufs_brs = 1;
+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
+
+/* ---------------------------------------------------------------------- */
+
+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
+
+int au_seq_path(struct seq_file *seq, struct path *path)
+{
+	return seq_path(seq, path, au_esc_chars);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int __init aufs_init(void)
+{
+	int err, i;
+	char *p;
+
+	p = au_esc_chars;
+	for (i = 1; i <= ' '; i++)
+		*p++ = i;
+	*p++ = '\\';
+	*p++ = '\x7f';
+	*p = 0;
+
+	au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
+
+	sysaufs_brs_init();
+	au_debug_init();
+
+	err = -EINVAL;
+	if (unlikely(aufs_nwkq <= 0))
+		goto out;
+
+	err = sysaufs_init();
+	if (unlikely(err))
+		goto out;
+	err = au_wkq_init();
+	if (unlikely(err))
+		goto out_sysaufs;
+	err = au_hinotify_init();
+	if (unlikely(err))
+		goto out_wkq;
+	err = au_sysrq_init();
+	if (unlikely(err))
+		goto out_hin;
+	err = au_cache_init();
+	if (unlikely(err))
+		goto out_sysrq;
+	err = register_filesystem(&aufs_fs_type);
+	if (unlikely(err))
+		goto out_cache;
+	/* since we define pr_fmt, call printk directly */
+	printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
+	goto out; /* success */
+
+ out_cache:
+	au_cache_fin();
+ out_sysrq:
+	au_sysrq_fin();
+ out_hin:
+	au_hinotify_fin();
+ out_wkq:
+	au_wkq_fin();
+ out_sysaufs:
+	sysaufs_fin();
+ out:
+	return err;
+}
+
+static void __exit aufs_exit(void)
+{
+	unregister_filesystem(&aufs_fs_type);
+	au_cache_fin();
+	au_sysrq_fin();
+	au_hinotify_fin();
+	au_wkq_fin();
+	sysaufs_fin();
+}
+
+module_init(aufs_init);
+module_exit(aufs_exit);
--- linux-ec2-2.6.32.orig/ubuntu/aufs/loop.c
+++ linux-ec2-2.6.32/ubuntu/aufs/loop.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * support for loopback block device as a branch
+ */
+
+#include <linux/loop.h>
+#include "aufs.h"
+
+/*
+ * test if two lower dentries have overlapping branches.
+ */
+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
+			     struct dentry *h_d2)
+{
+	struct inode *h_inode;
+	struct loop_device *l;
+
+	h_inode = h_d1->d_inode;
+	if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
+		return 0;
+
+	l = h_inode->i_sb->s_bdev->bd_disk->private_data;
+	h_d1 = l->lo_backing_file->f_dentry;
+	/* h_d1 can be local NFS. in this case aufs cannot detect the loop */
+	if (unlikely(h_d1->d_sb == sb))
+		return 1;
+	return !!au_test_subdir(h_d1, h_d2);
+}
+
+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
+int au_test_loopback_kthread(void)
+{
+	const char c = current->comm[4];
+
+	return current->mm == NULL
+	       && '0' <= c && c <= '9'
+	       && strncmp(current->comm, "loop", 4) == 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/file.h
+++ linux-ec2-2.6.32/ubuntu/aufs/file.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * file operations
+ */
+
+#ifndef __AUFS_FILE_H__
+#define __AUFS_FILE_H__
+
+#ifdef __KERNEL__
+
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/aufs_type.h>
+#include "rwsem.h"
+
+struct au_branch;
+struct au_hfile {
+	struct file		*hf_file;
+	struct au_branch	*hf_br;
+};
+
+struct au_vdir;
+struct au_finfo {
+	atomic_t		fi_generation;
+
+	struct au_rwsem		fi_rwsem;
+	struct au_hfile		*fi_hfile;
+	aufs_bindex_t		fi_bstart, fi_bend;
+
+	union {
+		/* non-dir only */
+		struct {
+			struct vm_operations_struct	*fi_h_vm_ops;
+			struct vm_operations_struct	*fi_vm_ops;
+			struct mutex			fi_vm_mtx;
+		};
+
+		/* dir only */
+		struct {
+			struct au_vdir		*fi_vdir_cache;
+			int			fi_maintain_plink;
+		};
+	};
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* file.c */
+extern struct address_space_operations aufs_aop;
+unsigned int au_file_roflags(unsigned int flags);
+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
+		       struct file *file);
+int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
+int au_reopen_nondir(struct file *file);
+struct au_pin;
+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
+			  int wlock);
+
+/* poll.c */
+#ifdef CONFIG_AUFS_POLL
+unsigned int aufs_poll(struct file *file, poll_table *wait);
+#endif
+
+/* f_op.c */
+extern const struct file_operations aufs_file_fop;
+int aufs_flush(struct file *file, fl_owner_t id);
+
+/* finfo.c */
+void au_hfput(struct au_hfile *hf, struct file *file);
+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
+		   struct file *h_file);
+
+void au_update_figen(struct file *file);
+
+void au_finfo_fin(struct file *file);
+int au_finfo_init(struct file *file);
+int au_fi_realloc(struct au_finfo *finfo, int nbr);
+
+/* ioctl.c */
+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct au_finfo *au_fi(struct file *file)
+{
+	return file->private_data;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * fi_read_lock, fi_write_lock,
+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
+ */
+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
+
+#define FiMustNoWaiters(f)	AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
+#define FiMustAnyLock(f)	AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
+#define FiMustWriteLock(f)	AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
+
+/* ---------------------------------------------------------------------- */
+
+/* todo: hard/soft set? */
+static inline aufs_bindex_t au_fbstart(struct file *file)
+{
+	FiMustAnyLock(file);
+	return au_fi(file)->fi_bstart;
+}
+
+static inline aufs_bindex_t au_fbend(struct file *file)
+{
+	FiMustAnyLock(file);
+	return au_fi(file)->fi_bend;
+}
+
+static inline struct au_vdir *au_fvdir_cache(struct file *file)
+{
+	FiMustAnyLock(file);
+	return au_fi(file)->fi_vdir_cache;
+}
+
+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
+{
+	FiMustWriteLock(file);
+	au_fi(file)->fi_bstart = bindex;
+}
+
+static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
+{
+	FiMustWriteLock(file);
+	au_fi(file)->fi_bend = bindex;
+}
+
+static inline void au_set_fvdir_cache(struct file *file,
+				      struct au_vdir *vdir_cache)
+{
+	FiMustWriteLock(file);
+	au_fi(file)->fi_vdir_cache = vdir_cache;
+}
+
+static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
+{
+	FiMustAnyLock(file);
+	return au_fi(file)->fi_hfile[0 + bindex].hf_file;
+}
+
+/* todo: memory barrier? */
+static inline unsigned int au_figen(struct file *f)
+{
+	return atomic_read(&au_fi(f)->fi_generation);
+}
+
+static inline int au_test_mmapped(struct file *f)
+{
+	/* FiMustAnyLock(f); */
+	return !!(au_fi(f)->fi_h_vm_ops);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_FILE_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/plink.c
+++ linux-ec2-2.6.32/ubuntu/aufs/plink.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * pseudo-link
+ */
+
+#include "aufs.h"
+
+/*
+ * during a user process maintains the pseudo-links,
+ * prohibit adding a new plink and branch manipulation.
+ */
+void au_plink_block_maintain(struct super_block *sb)
+{
+	struct au_sbinfo *sbi = au_sbi(sb);
+
+	SiMustAnyLock(sb);
+
+	/* gave up wake_up_bit() */
+	wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct pseudo_link {
+	struct list_head list;
+	struct inode *inode;
+};
+
+#ifdef CONFIG_AUFS_DEBUG
+void au_plink_list(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+	struct list_head *plink_list;
+	struct pseudo_link *plink;
+
+	SiMustAnyLock(sb);
+
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
+
+	plink_list = &sbinfo->si_plink.head;
+	spin_lock(&sbinfo->si_plink.spin);
+	list_for_each_entry(plink, plink_list, list)
+		AuDbg("%lu\n", plink->inode->i_ino);
+	spin_unlock(&sbinfo->si_plink.spin);
+}
+#endif
+
+/* is the inode pseudo-linked? */
+int au_plink_test(struct inode *inode)
+{
+	int found;
+	struct au_sbinfo *sbinfo;
+	struct list_head *plink_list;
+	struct pseudo_link *plink;
+
+	sbinfo = au_sbi(inode->i_sb);
+	AuRwMustAnyLock(&sbinfo->si_rwsem);
+	AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
+
+	found = 0;
+	plink_list = &sbinfo->si_plink.head;
+	spin_lock(&sbinfo->si_plink.spin);
+	list_for_each_entry(plink, plink_list, list)
+		if (plink->inode == inode) {
+			found = 1;
+			break;
+		}
+	spin_unlock(&sbinfo->si_plink.spin);
+	return found;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * generate a name for plink.
+ * the file will be stored under AUFS_WH_PLINKDIR.
+ */
+/* 20 is max digits length of ulong 64 */
+#define PLINK_NAME_LEN	((20 + 1) * 2)
+
+static int plink_name(char *name, int len, struct inode *inode,
+		      aufs_bindex_t bindex)
+{
+	int rlen;
+	struct inode *h_inode;
+
+	h_inode = au_h_iptr(inode, bindex);
+	rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
+	return rlen;
+}
+
+/* lookup the plink-ed @inode under the branch at @bindex */
+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
+{
+	struct dentry *h_dentry, *h_parent;
+	struct au_branch *br;
+	struct inode *h_dir;
+	char a[PLINK_NAME_LEN];
+	struct qstr tgtname = {
+		.name	= a
+	};
+
+	br = au_sbr(inode->i_sb, bindex);
+	h_parent = br->br_wbr->wbr_plink;
+	h_dir = h_parent->d_inode;
+	tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
+	/* always superio. */
+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
+	h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
+	mutex_unlock(&h_dir->i_mutex);
+	return h_dentry;
+}
+
+/* create a pseudo-link */
+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
+		      struct dentry *h_dentry, struct au_branch *br)
+{
+	int err;
+	struct path h_path = {
+		.mnt = br->br_mnt
+	};
+	struct inode *h_dir;
+
+	h_dir = h_parent->d_inode;
+ again:
+	h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
+	err = PTR_ERR(h_path.dentry);
+	if (IS_ERR(h_path.dentry))
+		goto out;
+
+	err = 0;
+	/* wh.plink dir is not monitored */
+	if (h_path.dentry->d_inode
+	    && h_path.dentry->d_inode != h_dentry->d_inode) {
+		err = vfsub_unlink(h_dir, &h_path, /*force*/0);
+		dput(h_path.dentry);
+		h_path.dentry = NULL;
+		if (!err)
+			goto again;
+	}
+	if (!err && !h_path.dentry->d_inode)
+		err = vfsub_link(h_dentry, h_dir, &h_path);
+	dput(h_path.dentry);
+
+ out:
+	return err;
+}
+
+struct do_whplink_args {
+	int *errp;
+	struct qstr *tgt;
+	struct dentry *h_parent;
+	struct dentry *h_dentry;
+	struct au_branch *br;
+};
+
+static void call_do_whplink(void *args)
+{
+	struct do_whplink_args *a = args;
+	*a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
+}
+
+static int whplink(struct dentry *h_dentry, struct inode *inode,
+		   aufs_bindex_t bindex, struct au_branch *br)
+{
+	int err, wkq_err;
+	struct au_wbr *wbr;
+	struct dentry *h_parent;
+	struct inode *h_dir;
+	char a[PLINK_NAME_LEN];
+	struct qstr tgtname = {
+		.name = a
+	};
+
+	wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
+	h_parent = wbr->wbr_plink;
+	h_dir = h_parent->d_inode;
+	tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
+	/* always superio. */
+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
+	if (!au_test_wkq(current)) {
+		struct do_whplink_args args = {
+			.errp		= &err,
+			.tgt		= &tgtname,
+			.h_parent	= h_parent,
+			.h_dentry	= h_dentry,
+			.br		= br
+		};
+		wkq_err = au_wkq_wait(call_do_whplink, &args);
+		if (unlikely(wkq_err))
+			err = wkq_err;
+	} else
+		err = do_whplink(&tgtname, h_parent, h_dentry, br);
+	mutex_unlock(&h_dir->i_mutex);
+
+	return err;
+}
+
+/* free a single plink */
+static void do_put_plink(struct pseudo_link *plink, int do_del)
+{
+	iput(plink->inode);
+	if (do_del)
+		list_del(&plink->list);
+	kfree(plink);
+}
+
+/*
+ * create a new pseudo-link for @h_dentry on @bindex.
+ * the linked inode is held in aufs @inode.
+ */
+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
+		     struct dentry *h_dentry)
+{
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+	struct list_head *plink_list;
+	struct pseudo_link *plink;
+	int found, err, cnt;
+
+	sb = inode->i_sb;
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
+
+	err = 0;
+	cnt = 0;
+	found = 0;
+	plink_list = &sbinfo->si_plink.head;
+	spin_lock(&sbinfo->si_plink.spin);
+	list_for_each_entry(plink, plink_list, list) {
+		cnt++;
+		if (plink->inode == inode) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		spin_unlock(&sbinfo->si_plink.spin);
+		return;
+	}
+
+	plink = NULL;
+	if (!found) {
+		plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
+		if (plink) {
+			plink->inode = au_igrab(inode);
+			list_add(&plink->list, plink_list);
+			cnt++;
+		} else
+			err = -ENOMEM;
+	}
+	spin_unlock(&sbinfo->si_plink.spin);
+
+	if (!err) {
+		au_plink_block_maintain(sb);
+		err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
+	}
+
+	if (unlikely(cnt > AUFS_PLINK_WARN))
+		AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
+	if (unlikely(err)) {
+		pr_warning("err %d, damaged pseudo link.\n", err);
+		if (!found && plink)
+			do_put_plink(plink, /*do_del*/1);
+	}
+}
+
+/* free all plinks */
+void au_plink_put(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+	struct list_head *plink_list;
+	struct pseudo_link *plink, *tmp;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
+
+	plink_list = &sbinfo->si_plink.head;
+	/* no spin_lock since sbinfo is write-locked */
+	list_for_each_entry_safe(plink, tmp, plink_list, list)
+		do_put_plink(plink, 0);
+	INIT_LIST_HEAD(plink_list);
+}
+
+/* free the plinks on a branch specified by @br_id */
+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
+{
+	struct au_sbinfo *sbinfo;
+	struct list_head *plink_list;
+	struct pseudo_link *plink, *tmp;
+	struct inode *inode;
+	aufs_bindex_t bstart, bend, bindex;
+	unsigned char do_put;
+
+	SiMustWriteLock(sb);
+
+	sbinfo = au_sbi(sb);
+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
+
+	plink_list = &sbinfo->si_plink.head;
+	/* no spin_lock since sbinfo is write-locked */
+	list_for_each_entry_safe(plink, tmp, plink_list, list) {
+		do_put = 0;
+		inode = au_igrab(plink->inode);
+		ii_write_lock_child(inode);
+		bstart = au_ibstart(inode);
+		bend = au_ibend(inode);
+		if (bstart >= 0) {
+			for (bindex = bstart; bindex <= bend; bindex++) {
+				if (!au_h_iptr(inode, bindex)
+				    || au_ii_br_id(inode, bindex) != br_id)
+					continue;
+				au_set_h_iptr(inode, bindex, NULL, 0);
+				do_put = 1;
+				break;
+			}
+		} else
+			do_put_plink(plink, 1);
+
+		if (do_put) {
+			for (bindex = bstart; bindex <= bend; bindex++)
+				if (au_h_iptr(inode, bindex)) {
+					do_put = 0;
+					break;
+				}
+			if (do_put)
+				do_put_plink(plink, 1);
+		}
+		ii_write_unlock(inode);
+		iput(inode);
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+long au_plink_ioctl(struct file *file, unsigned int cmd)
+{
+	long err;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+
+	err = -EACCES;
+	if (!capable(CAP_SYS_ADMIN))
+		goto out;
+
+	err = 0;
+	sb = file->f_dentry->d_sb;
+	sbinfo = au_sbi(sb);
+	switch (cmd) {
+	case AUFS_CTL_PLINK_MAINT:
+		/*
+		 * pseudo-link maintenance mode,
+		 * cleared by aufs_release_dir()
+		 */
+		si_write_lock(sb);
+		if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
+			au_fset_si(sbinfo, MAINTAIN_PLINK);
+			au_fi(file)->fi_maintain_plink = 1;
+		} else
+			err = -EBUSY;
+		si_write_unlock(sb);
+		break;
+	case AUFS_CTL_PLINK_CLEAN:
+		aufs_write_lock(sb->s_root);
+		if (au_opt_test(sbinfo->si_mntflags, PLINK))
+			au_plink_put(sb);
+		aufs_write_unlock(sb->s_root);
+		break;
+	default:
+		err = -EINVAL;
+	}
+ out:
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/whout.h
+++ linux-ec2-2.6.32/ubuntu/aufs/whout.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * whiteout for logical deletion and opaque directory
+ */
+
+#ifndef __AUFS_WHOUT_H__
+#define __AUFS_WHOUT_H__
+
+#ifdef __KERNEL__
+
+#include <linux/aufs_type.h>
+#include "dir.h"
+
+/* whout.c */
+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
+struct au_branch;
+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
+	       struct au_branch *br, int try_sio);
+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
+			     struct qstr *prefix);
+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
+			struct dentry *dentry);
+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
+	       struct super_block *sb);
+
+/* diropq flags */
+#define AuDiropq_CREATE	1
+#define au_ftest_diropq(flags, name)	((flags) & AuDiropq_##name)
+#define au_fset_diropq(flags, name)	{ (flags) |= AuDiropq_##name; }
+#define au_fclr_diropq(flags, name)	{ (flags) &= ~AuDiropq_##name; }
+
+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
+			     unsigned int flags);
+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
+			  struct au_branch *br);
+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
+			    struct dentry *h_parent);
+
+/* real rmdir for the whiteout-ed dir */
+struct au_whtmp_rmdir {
+	struct inode *dir;
+	aufs_bindex_t bindex;
+	struct dentry *wh_dentry;
+	struct au_nhash whlist;
+};
+
+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
+		   struct dentry *wh_dentry, struct au_nhash *whlist);
+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
+			 struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
+
+/* ---------------------------------------------------------------------- */
+
+static inline struct dentry *au_diropq_create(struct dentry *dentry,
+					      aufs_bindex_t bindex)
+{
+	return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
+}
+
+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
+{
+	return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_WHOUT_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/iinfo.c
+++ linux-ec2-2.6.32/ubuntu/aufs/iinfo.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * inode private data
+ */
+
+#include "aufs.h"
+
+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
+{
+	struct inode *h_inode;
+
+	IiMustAnyLock(inode);
+
+	h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
+	AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
+	return h_inode;
+}
+
+/* todo: hard/soft set? */
+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
+{
+	struct au_iinfo *iinfo = au_ii(inode);
+	struct inode *h_inode;
+
+	IiMustWriteLock(inode);
+
+	iinfo->ii_bstart = bindex;
+	h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
+	if (h_inode)
+		au_cpup_igen(inode, h_inode);
+}
+
+void au_hiput(struct au_hinode *hinode)
+{
+	au_hin_free(hinode);
+	dput(hinode->hi_whdentry);
+	iput(hinode->hi_inode);
+}
+
+unsigned int au_hi_flags(struct inode *inode, int isdir)
+{
+	unsigned int flags;
+	const unsigned int mnt_flags = au_mntflags(inode->i_sb);
+
+	flags = 0;
+	if (au_opt_test(mnt_flags, XINO))
+		au_fset_hi(flags, XINO);
+	if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
+		au_fset_hi(flags, HINOTIFY);
+	return flags;
+}
+
+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
+		   struct inode *h_inode, unsigned int flags)
+{
+	struct au_hinode *hinode;
+	struct inode *hi;
+	struct au_iinfo *iinfo = au_ii(inode);
+
+	IiMustWriteLock(inode);
+
+	hinode = iinfo->ii_hinode + bindex;
+	hi = hinode->hi_inode;
+	AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
+	AuDebugOn(h_inode && hi);
+
+	if (hi)
+		au_hiput(hinode);
+	hinode->hi_inode = h_inode;
+	if (h_inode) {
+		int err;
+		struct super_block *sb = inode->i_sb;
+		struct au_branch *br;
+
+		if (bindex == iinfo->ii_bstart)
+			au_cpup_igen(inode, h_inode);
+		br = au_sbr(sb, bindex);
+		hinode->hi_id = br->br_id;
+		if (au_ftest_hi(flags, XINO)) {
+			err = au_xino_write(sb, bindex, h_inode->i_ino,
+					    inode->i_ino);
+			if (unlikely(err))
+				AuIOErr1("failed au_xino_write() %d\n", err);
+		}
+
+		if (au_ftest_hi(flags, HINOTIFY)
+		    && au_br_hinotifyable(br->br_perm)) {
+			err = au_hin_alloc(hinode, inode, h_inode);
+			if (unlikely(err))
+				AuIOErr1("au_hin_alloc() %d\n", err);
+		}
+	}
+}
+
+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
+		  struct dentry *h_wh)
+{
+	struct au_hinode *hinode;
+
+	IiMustWriteLock(inode);
+
+	hinode = au_ii(inode)->ii_hinode + bindex;
+	AuDebugOn(hinode->hi_whdentry);
+	hinode->hi_whdentry = h_wh;
+}
+
+void au_update_iigen(struct inode *inode)
+{
+	atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
+	/* smp_mb(); */ /* atomic_set */
+}
+
+/* it may be called at remount time, too */
+void au_update_brange(struct inode *inode, int do_put_zero)
+{
+	struct au_iinfo *iinfo;
+
+	iinfo = au_ii(inode);
+	if (!iinfo || iinfo->ii_bstart < 0)
+		return;
+
+	IiMustWriteLock(inode);
+
+	if (do_put_zero) {
+		aufs_bindex_t bindex;
+
+		for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
+		     bindex++) {
+			struct inode *h_i;
+
+			h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
+			if (h_i && !h_i->i_nlink)
+				au_set_h_iptr(inode, bindex, NULL, 0);
+		}
+	}
+
+	iinfo->ii_bstart = -1;
+	while (++iinfo->ii_bstart <= iinfo->ii_bend)
+		if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
+			break;
+	if (iinfo->ii_bstart > iinfo->ii_bend) {
+		iinfo->ii_bstart = -1;
+		iinfo->ii_bend = -1;
+		return;
+	}
+
+	iinfo->ii_bend++;
+	while (0 <= --iinfo->ii_bend)
+		if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
+			break;
+	AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int au_iinfo_init(struct inode *inode)
+{
+	struct au_iinfo *iinfo;
+	struct super_block *sb;
+	int nbr, i;
+
+	sb = inode->i_sb;
+	iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
+	nbr = au_sbend(sb) + 1;
+	if (unlikely(nbr <= 0))
+		nbr = 1;
+	iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
+	if (iinfo->ii_hinode) {
+		for (i = 0; i < nbr; i++)
+			iinfo->ii_hinode[i].hi_id = -1;
+
+		atomic_set(&iinfo->ii_generation, au_sigen(sb));
+		/* smp_mb(); */ /* atomic_set */
+		au_rw_init(&iinfo->ii_rwsem);
+		iinfo->ii_bstart = -1;
+		iinfo->ii_bend = -1;
+		iinfo->ii_vdir = NULL;
+		return 0;
+	}
+	return -ENOMEM;
+}
+
+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
+{
+	int err, sz;
+	struct au_hinode *hip;
+
+	AuRwMustWriteLock(&iinfo->ii_rwsem);
+
+	err = -ENOMEM;
+	sz = sizeof(*hip) * (iinfo->ii_bend + 1);
+	if (!sz)
+		sz = sizeof(*hip);
+	hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
+	if (hip) {
+		iinfo->ii_hinode = hip;
+		err = 0;
+	}
+
+	return err;
+}
+
+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
+			   ino_t ino)
+{
+	int err;
+	aufs_bindex_t bindex;
+	unsigned char locked;
+
+	err = 0;
+	locked = !!si_noflush_read_trylock(sb);
+	bindex = au_br_index(sb, hinode->hi_id);
+	if (bindex >= 0)
+		err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
+	/* error action? */
+	if (locked)
+		si_read_unlock(sb);
+	return err;
+}
+
+void au_iinfo_fin(struct inode *inode)
+{
+	ino_t ino;
+	aufs_bindex_t bend;
+	unsigned char unlinked = !inode->i_nlink;
+	struct au_iinfo *iinfo;
+	struct au_hinode *hi;
+	struct super_block *sb;
+
+	if (unlinked) {
+		int err = au_xigen_inc(inode);
+		if (unlikely(err))
+			AuWarn1("failed resetting i_generation, %d\n", err);
+	}
+
+	iinfo = au_ii(inode);
+	/* bad_inode case */
+	if (!iinfo)
+		return;
+
+	if (iinfo->ii_vdir)
+		au_vdir_free(iinfo->ii_vdir);
+
+	if (iinfo->ii_bstart >= 0) {
+		sb = inode->i_sb;
+		ino = 0;
+		if (unlinked)
+			ino = inode->i_ino;
+		hi = iinfo->ii_hinode + iinfo->ii_bstart;
+		bend = iinfo->ii_bend;
+		while (iinfo->ii_bstart++ <= bend) {
+			if (hi->hi_inode) {
+				if (unlinked || !hi->hi_inode->i_nlink) {
+					au_iinfo_write0(sb, hi, ino);
+					/* ignore this error */
+					ino = 0;
+				}
+				au_hiput(hi);
+			}
+			hi++;
+		}
+	}
+
+	kfree(iinfo->ii_hinode);
+	AuRwDestroy(&iinfo->ii_rwsem);
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/BOM
+++ linux-ec2-2.6.32/ubuntu/aufs/BOM
@@ -0,0 +1,12 @@
+Git Tree:      http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git
+Git Branch:    aufs2 (86695db9a39ac200a441f8ff0ddd0bb24005238d)
+
+This standalone snapshot was built from the commit below in the main
+aufs2-2.6.git tree (http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-2.6.git):
+
+    commit 2a119c29c8bb5f9953d2866450e5fe13ea88520f
+    Author: J. R. Okajima <hooanon05@yahoo.co.jp>
+    Date:   Sat Dec 5 11:05:06 2009 +0900
+
+	aufs: tiny, a note about pathconf(3) wrapper
+
--- linux-ec2-2.6.32.orig/ubuntu/aufs/rdu.c
+++ linux-ec2-2.6.32/ubuntu/aufs/rdu.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * readdir in userspace.
+ */
+
+#include <linux/security.h>
+#include <linux/uaccess.h>
+#include <linux/aufs_type.h>
+#include "aufs.h"
+
+/* bits for struct aufs_rdu.flags */
+#define	AuRdu_CALLED	1
+#define	AuRdu_CONT	(1 << 1)
+#define	AuRdu_FULL	(1 << 2)
+#define au_ftest_rdu(flags, name)	((flags) & AuRdu_##name)
+#define au_fset_rdu(flags, name)	{ (flags) |= AuRdu_##name; }
+#define au_fclr_rdu(flags, name)	{ (flags) &= ~AuRdu_##name; }
+
+struct au_rdu_arg {
+	struct aufs_rdu			*rdu;
+	union au_rdu_ent_ul		ent;
+	unsigned long			end;
+
+	struct super_block		*sb;
+	int				err;
+};
+
+static int au_rdu_fill(void *__arg, const char *name, int nlen,
+		       loff_t offset, u64 h_ino, unsigned int d_type)
+{
+	int err, len;
+	struct au_rdu_arg *arg = __arg;
+	struct aufs_rdu *rdu = arg->rdu;
+	struct au_rdu_ent ent;
+
+	err = 0;
+	arg->err = 0;
+	au_fset_rdu(rdu->cookie.flags, CALLED);
+	len = au_rdu_len(nlen);
+	if (arg->ent.ul + len  < arg->end) {
+		ent.ino = h_ino;
+		ent.bindex = rdu->cookie.bindex;
+		ent.type = d_type;
+		ent.nlen = nlen;
+		if (unlikely(nlen > AUFS_MAX_NAMELEN))
+			ent.type = DT_UNKNOWN;
+
+		err = -EFAULT;
+		if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
+			goto out;
+		if (copy_to_user(arg->ent.e->name, name, nlen))
+			goto out;
+		/* the terminating NULL */
+		if (__put_user(0, arg->ent.e->name + nlen))
+			goto out;
+		err = 0;
+		/* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
+		arg->ent.ul += len;
+		rdu->rent++;
+	} else {
+		err = -EFAULT;
+		au_fset_rdu(rdu->cookie.flags, FULL);
+		rdu->full = 1;
+		rdu->tail = arg->ent;
+	}
+
+ out:
+	/* AuTraceErr(err); */
+	return err;
+}
+
+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
+{
+	int err;
+	loff_t offset;
+	struct au_rdu_cookie *cookie = &arg->rdu->cookie;
+
+	offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
+	err = offset;
+	if (unlikely(offset != cookie->h_pos))
+		goto out;
+
+	err = 0;
+	do {
+		arg->err = 0;
+		au_fclr_rdu(cookie->flags, CALLED);
+		/* smp_mb(); */
+		err = vfsub_readdir(h_file, au_rdu_fill, arg);
+		if (err >= 0)
+			err = arg->err;
+	} while (!err
+		 && au_ftest_rdu(cookie->flags, CALLED)
+		 && !au_ftest_rdu(cookie->flags, FULL));
+	cookie->h_pos = h_file->f_pos;
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
+{
+	int err;
+	aufs_bindex_t bend;
+	struct au_rdu_arg arg;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct file *h_file;
+	struct au_rdu_cookie *cookie = &rdu->cookie;
+
+	err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
+	if (unlikely(err)) {
+		err = -EFAULT;
+		AuTraceErr(err);
+		goto out;
+	}
+	rdu->rent = 0;
+	rdu->tail = rdu->ent;
+	rdu->full = 0;
+	arg.rdu = rdu;
+	arg.ent = rdu->ent;
+	arg.end = arg.ent.ul;
+	arg.end += rdu->sz;
+
+	err = -ENOTDIR;
+	if (unlikely(!file->f_op || !file->f_op->readdir))
+		goto out;
+
+	err = security_file_permission(file, MAY_READ);
+	AuTraceErr(err);
+	if (unlikely(err))
+		goto out;
+
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
+#if 1
+	mutex_lock(&inode->i_mutex);
+#else
+	err = mutex_lock_killable(&inode->i_mutex);
+	AuTraceErr(err);
+	if (unlikely(err))
+		goto out;
+#endif
+	err = -ENOENT;
+	if (unlikely(IS_DEADDIR(inode)))
+		goto out_mtx;
+
+	arg.sb = inode->i_sb;
+	si_read_lock(arg.sb, AuLock_FLUSH);
+	fi_read_lock(file);
+
+	err = -EAGAIN;
+	if (unlikely(au_ftest_rdu(cookie->flags, CONT)
+		     && cookie->generation != au_figen(file)))
+		goto out_unlock;
+
+	err = 0;
+	if (!rdu->blk) {
+		rdu->blk = au_sbi(arg.sb)->si_rdblk;
+		if (!rdu->blk)
+			rdu->blk = au_dir_size(file, /*dentry*/NULL);
+	}
+	bend = au_fbstart(file);
+	if (cookie->bindex < bend)
+		cookie->bindex = bend;
+	bend = au_fbend(file);
+	/* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
+	for (; !err && cookie->bindex <= bend;
+	     cookie->bindex++, cookie->h_pos = 0) {
+		h_file = au_h_fptr(file, cookie->bindex);
+		if (!h_file)
+			continue;
+
+		au_fclr_rdu(cookie->flags, FULL);
+		err = au_rdu_do(h_file, &arg);
+		AuTraceErr(err);
+		if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
+			break;
+	}
+	AuDbg("rent %llu\n", rdu->rent);
+
+	if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
+		rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
+		au_fset_rdu(cookie->flags, CONT);
+		cookie->generation = au_figen(file);
+	}
+
+	ii_read_lock_child(inode);
+	fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
+	ii_read_unlock(inode);
+
+ out_unlock:
+	fi_read_unlock(file);
+	si_read_unlock(arg.sb);
+ out_mtx:
+	mutex_unlock(&inode->i_mutex);
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
+{
+	int err;
+	ino_t ino;
+	unsigned long long nent;
+	union au_rdu_ent_ul *u;
+	struct au_rdu_ent ent;
+	struct super_block *sb;
+
+	err = 0;
+	nent = rdu->nent;
+	u = &rdu->ent;
+	sb = file->f_dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	while (nent-- > 0) {
+		err = !access_ok(VERIFY_WRITE, u->e, sizeof(ent));
+		if (unlikely(err)) {
+			err = -EFAULT;
+			AuTraceErr(err);
+			break;
+		}
+
+		err = copy_from_user(&ent, u->e, sizeof(ent));
+		if (unlikely(err)) {
+			err = -EFAULT;
+			AuTraceErr(err);
+			break;
+		}
+
+		/* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
+		if (!ent.wh)
+			err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
+		else
+			err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
+					&ino);
+		if (unlikely(err)) {
+			AuTraceErr(err);
+			break;
+		}
+
+		err = __put_user(ino, &u->e->ino);
+		if (unlikely(err)) {
+			err = -EFAULT;
+			AuTraceErr(err);
+			break;
+		}
+		u->ul += au_rdu_len(ent.nlen);
+	}
+	si_read_unlock(sb);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_rdu_verify(struct aufs_rdu *rdu)
+{
+	AuDbg("rdu{%llu, %p, (%u, %u) | %u | %llu, %u, %u | "
+	      "%llu, b%d, 0x%x, g%u}\n",
+	      rdu->sz, rdu->ent.e, rdu->verify[0], rdu->verify[1],
+	      rdu->blk,
+	      rdu->rent, rdu->shwh, rdu->full,
+	      rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
+	      rdu->cookie.generation);
+
+	if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)
+	    && rdu->verify[AufsCtlRduV_SZ_PTR] == sizeof(rdu))
+		return 0;
+
+	AuDbg("%u:%u, %u:%u\n",
+	      rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu),
+	      rdu->verify[AufsCtlRduV_SZ_PTR], (unsigned int)sizeof(rdu));
+	return -EINVAL;
+}
+
+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long err, e;
+	struct aufs_rdu rdu;
+	void __user *p = (void __user *)arg;
+
+	err = copy_from_user(&rdu, p, sizeof(rdu));
+	if (unlikely(err)) {
+		err = -EFAULT;
+		AuTraceErr(err);
+		goto out;
+	}
+	err = au_rdu_verify(&rdu);
+	if (unlikely(err))
+		goto out;
+
+	switch (cmd) {
+	case AUFS_CTL_RDU:
+		err = au_rdu(file, &rdu);
+		if (unlikely(err))
+			break;
+
+		e = copy_to_user(p, &rdu, sizeof(rdu));
+		if (unlikely(e)) {
+			err = -EFAULT;
+			AuTraceErr(err);
+		}
+		break;
+	case AUFS_CTL_RDU_INO:
+		err = au_rdu_ino(file, &rdu);
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+
+ out:
+	AuTraceErr(err);
+	return err;
+}
--- linux-ec2-2.6.32.orig/ubuntu/aufs/module.h
+++ linux-ec2-2.6.32/ubuntu/aufs/module.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * module initialization and module-global
+ */
+
+#ifndef __AUFS_MODULE_H__
+#define __AUFS_MODULE_H__
+
+#ifdef __KERNEL__
+
+#include <linux/slab.h>
+
+struct path;
+struct seq_file;
+
+/* module parameters */
+extern short aufs_nwkq;
+extern int sysaufs_brs;
+
+/* ---------------------------------------------------------------------- */
+
+extern int au_dir_roflags;
+
+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
+int au_seq_path(struct seq_file *seq, struct path *path);
+
+/* ---------------------------------------------------------------------- */
+
+/* kmem cache */
+enum {
+	AuCache_DINFO,
+	AuCache_ICNTNR,
+	AuCache_FINFO,
+	AuCache_VDIR,
+	AuCache_DEHSTR,
+#ifdef CONFIG_AUFS_HINOTIFY
+	AuCache_HINOTIFY,
+#endif
+	AuCache_Last
+};
+
+#define AuCache(type)	KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
+
+extern struct kmem_cache *au_cachep[];
+
+#define AuCacheFuncs(name, index) \
+static inline void *au_cache_alloc_##name(void) \
+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
+static inline void au_cache_free_##name(void *p) \
+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
+
+AuCacheFuncs(dinfo, DINFO);
+AuCacheFuncs(icntnr, ICNTNR);
+AuCacheFuncs(finfo, FINFO);
+AuCacheFuncs(vdir, VDIR);
+AuCacheFuncs(dehstr, DEHSTR);
+
+/*  ---------------------------------------------------------------------- */
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_MODULE_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/rwsem.h
+++ linux-ec2-2.6.32/ubuntu/aufs/rwsem.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * simple read-write semaphore wrappers
+ */
+
+#ifndef __AUFS_RWSEM_H__
+#define __AUFS_RWSEM_H__
+
+#ifdef __KERNEL__
+
+#include <linux/rwsem.h>
+
+struct au_rwsem {
+	struct rw_semaphore	rwsem;
+#ifdef CONFIG_AUFS_DEBUG
+	/* just for debugging, not almighty counter */
+	atomic_t		rcnt, wcnt;
+#endif
+};
+
+#ifdef CONFIG_AUFS_DEBUG
+#define AuDbgCntInit(rw) do { \
+	atomic_set(&(rw)->rcnt, 0); \
+	atomic_set(&(rw)->wcnt, 0); \
+	smp_mb(); /* atomic set */ \
+} while (0)
+
+#define AuDbgRcntInc(rw)	atomic_inc_return(&(rw)->rcnt)
+#define AuDbgRcntDec(rw)	WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
+#define AuDbgWcntInc(rw)	WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
+#define AuDbgWcntDec(rw)	WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
+#else
+#define AuDbgCntInit(rw)	do {} while (0)
+#define AuDbgRcntInc(rw)	do {} while (0)
+#define AuDbgRcntDec(rw)	do {} while (0)
+#define AuDbgWcntInc(rw)	do {} while (0)
+#define AuDbgWcntDec(rw)	do {} while (0)
+#endif /* CONFIG_AUFS_DEBUG */
+
+/* to debug easier, do not make them inlined functions */
+#define AuRwMustNoWaiters(rw)	AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
+/* rwsem_is_locked() is unusable */
+#define AuRwMustReadLock(rw)	AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
+#define AuRwMustWriteLock(rw)	AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
+#define AuRwMustAnyLock(rw)	AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
+					&& atomic_read(&(rw)->wcnt) <= 0)
+#define AuRwDestroy(rw)		AuDebugOn(atomic_read(&(rw)->rcnt) \
+					|| atomic_read(&(rw)->wcnt))
+
+static inline void au_rw_init(struct au_rwsem *rw)
+{
+	AuDbgCntInit(rw);
+	init_rwsem(&rw->rwsem);
+}
+
+static inline void au_rw_init_wlock(struct au_rwsem *rw)
+{
+	au_rw_init(rw);
+	down_write(&rw->rwsem);
+	AuDbgWcntInc(rw);
+}
+
+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
+					   unsigned int lsc)
+{
+	au_rw_init(rw);
+	down_write_nested(&rw->rwsem, lsc);
+	AuDbgWcntInc(rw);
+}
+
+static inline void au_rw_read_lock(struct au_rwsem *rw)
+{
+	down_read(&rw->rwsem);
+	AuDbgRcntInc(rw);
+}
+
+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
+{
+	down_read_nested(&rw->rwsem, lsc);
+	AuDbgRcntInc(rw);
+}
+
+static inline void au_rw_read_unlock(struct au_rwsem *rw)
+{
+	AuRwMustReadLock(rw);
+	AuDbgRcntDec(rw);
+	up_read(&rw->rwsem);
+}
+
+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
+{
+	AuRwMustWriteLock(rw);
+	AuDbgRcntInc(rw);
+	AuDbgWcntDec(rw);
+	downgrade_write(&rw->rwsem);
+}
+
+static inline void au_rw_write_lock(struct au_rwsem *rw)
+{
+	down_write(&rw->rwsem);
+	AuDbgWcntInc(rw);
+}
+
+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
+					   unsigned int lsc)
+{
+	down_write_nested(&rw->rwsem, lsc);
+	AuDbgWcntInc(rw);
+}
+
+static inline void au_rw_write_unlock(struct au_rwsem *rw)
+{
+	AuRwMustWriteLock(rw);
+	AuDbgWcntDec(rw);
+	up_write(&rw->rwsem);
+}
+
+/* why is not _nested version defined */
+static inline int au_rw_read_trylock(struct au_rwsem *rw)
+{
+	int ret = down_read_trylock(&rw->rwsem);
+	if (ret)
+		AuDbgRcntInc(rw);
+	return ret;
+}
+
+static inline int au_rw_write_trylock(struct au_rwsem *rw)
+{
+	int ret = down_write_trylock(&rw->rwsem);
+	if (ret)
+		AuDbgWcntInc(rw);
+	return ret;
+}
+
+#undef AuDbgCntInit
+#undef AuDbgRcntInc
+#undef AuDbgRcntDec
+#undef AuDbgWcntInc
+#undef AuDbgWcntDec
+
+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
+static inline void prefix##_read_lock(param) \
+{ au_rw_read_lock(rwsem); } \
+static inline void prefix##_write_lock(param) \
+{ au_rw_write_lock(rwsem); } \
+static inline int prefix##_read_trylock(param) \
+{ return au_rw_read_trylock(rwsem); } \
+static inline int prefix##_write_trylock(param) \
+{ return au_rw_write_trylock(rwsem); }
+/* why is not _nested version defined */
+/* static inline void prefix##_read_trylock_nested(param, lsc)
+{ au_rw_read_trylock_nested(rwsem, lsc)); }
+static inline void prefix##_write_trylock_nestd(param, lsc)
+{ au_rw_write_trylock_nested(rwsem, lsc); } */
+
+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
+static inline void prefix##_read_unlock(param) \
+{ au_rw_read_unlock(rwsem); } \
+static inline void prefix##_write_unlock(param) \
+{ au_rw_write_unlock(rwsem); } \
+static inline void prefix##_downgrade_lock(param) \
+{ au_rw_dgrade_lock(rwsem); }
+
+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
+	AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
+	AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_RWSEM_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/aufs/file.c
+++ linux-ec2-2.6.32/ubuntu/aufs/file.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * handling file/dir, and address_space operation
+ */
+
+#include <linux/file.h>
+#include <linux/fsnotify.h>
+#include <linux/namei.h>
+#include <linux/pagemap.h>
+#include "aufs.h"
+
+/* drop flags for writing */
+unsigned int au_file_roflags(unsigned int flags)
+{
+	flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
+	flags |= O_RDONLY | O_NOATIME;
+	return flags;
+}
+
+/* common functions to regular file and dir */
+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
+		       struct file *file)
+{
+	struct file *h_file;
+	struct dentry *h_dentry;
+	struct inode *h_inode;
+	struct super_block *sb;
+	struct au_branch *br;
+	int err, exec_flag;
+	struct path h_path;
+
+	/* a race condition can happen between open and unlink/rmdir */
+	h_file = ERR_PTR(-ENOENT);
+	h_dentry = au_h_dptr(dentry, bindex);
+	if (au_test_nfsd(current) && !h_dentry)
+		goto out;
+	h_inode = h_dentry->d_inode;
+	if (au_test_nfsd(current) && !h_inode)
+		goto out;
+	if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
+		     || !h_inode))
+		goto out;
+
+	sb = dentry->d_sb;
+	br = au_sbr(sb, bindex);
+	h_file = ERR_PTR(-EACCES);
+	exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
+	if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
+			goto out;
+
+	/* drop flags for writing */
+	if (au_test_ro(sb, bindex, dentry->d_inode))
+		flags = au_file_roflags(flags);
+	flags &= ~O_CREAT;
+	atomic_inc(&br->br_count);
+	h_path.dentry = h_dentry;
+	h_path.mnt = br->br_mnt;
+	path_get(&h_path);
+	h_file = vfsub_dentry_open(&h_path, flags, current_cred());
+	if (IS_ERR(h_file))
+		goto out_br;
+
+	if (exec_flag) {
+		err = deny_write_access(h_file);
+		if (unlikely(err)) {
+			fput(h_file);
+			h_file = ERR_PTR(err);
+			goto out_br;
+		}
+	}
+	fsnotify_open(h_dentry);
+	goto out; /* success */
+
+ out_br:
+	atomic_dec(&br->br_count);
+ out:
+	return h_file;
+}
+
+int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
+{
+	int err;
+	unsigned int flags;
+	struct dentry *dentry;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	si_read_lock(sb, AuLock_FLUSH);
+	err = au_finfo_init(file);
+	if (unlikely(err))
+		goto out;
+
+	di_read_lock_child(dentry, AuLock_IR);
+	spin_lock(&file->f_lock);
+	flags = file->f_flags;
+	spin_unlock(&file->f_lock);
+	err = open(file, flags);
+	di_read_unlock(dentry, AuLock_IR);
+
+	fi_write_unlock(file);
+	if (unlikely(err))
+		au_finfo_fin(file);
+ out:
+	si_read_unlock(sb);
+	return err;
+}
+
+int au_reopen_nondir(struct file *file)
+{
+	int err;
+	unsigned int flags;
+	aufs_bindex_t bstart, bindex, bend;
+	struct dentry *dentry;
+	struct file *h_file, *h_file_tmp;
+
+	dentry = file->f_dentry;
+	bstart = au_dbstart(dentry);
+	h_file_tmp = NULL;
+	if (au_fbstart(file) == bstart) {
+		h_file = au_h_fptr(file, bstart);
+		if (file->f_mode == h_file->f_mode)
+			return 0; /* success */
+		h_file_tmp = h_file;
+		get_file(h_file_tmp);
+		au_set_h_fptr(file, bstart, NULL);
+	}
+	AuDebugOn(au_fbstart(file) < bstart
+		  || au_fi(file)->fi_hfile[0 + bstart].hf_file);
+
+	spin_lock(&file->f_lock);
+	flags = file->f_flags & ~O_TRUNC;
+	spin_unlock(&file->f_lock);
+	h_file = au_h_open(dentry, bstart, flags, file);
+	err = PTR_ERR(h_file);
+	if (IS_ERR(h_file))
+		goto out; /* todo: close all? */
+
+	err = 0;
+	au_set_fbstart(file, bstart);
+	au_set_h_fptr(file, bstart, h_file);
+	au_update_figen(file);
+	/* todo: necessary? */
+	/* file->f_ra = h_file->f_ra; */
+
+	/* close lower files */
+	bend = au_fbend(file);
+	for (bindex = bstart + 1; bindex <= bend; bindex++)
+		au_set_h_fptr(file, bindex, NULL);
+	au_set_fbend(file, bstart);
+
+ out:
+	if (h_file_tmp)
+		fput(h_file_tmp);
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
+			struct dentry *hi_wh)
+{
+	int err;
+	aufs_bindex_t bstart;
+	struct au_dinfo *dinfo;
+	struct dentry *h_dentry;
+
+	dinfo = au_di(file->f_dentry);
+	AuRwMustWriteLock(&dinfo->di_rwsem);
+
+	bstart = dinfo->di_bstart;
+	dinfo->di_bstart = btgt;
+	h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
+	dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
+	err = au_reopen_nondir(file);
+	dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
+	dinfo->di_bstart = bstart;
+
+	return err;
+}
+
+static int au_ready_to_write_wh(struct file *file, loff_t len,
+				aufs_bindex_t bcpup)
+{
+	int err;
+	struct inode *inode;
+	struct dentry *dentry, *hi_wh;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
+	hi_wh = au_hi_wh(inode, bcpup);
+	if (!hi_wh)
+		err = au_sio_cpup_wh(dentry, bcpup, len, file);
+	else
+		/* already copied-up after unlink */
+		err = au_reopen_wh(file, bcpup, hi_wh);
+
+	sb = dentry->d_sb;
+	if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
+		au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
+
+	return err;
+}
+
+/*
+ * prepare the @file for writing.
+ */
+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
+{
+	int err;
+	aufs_bindex_t bstart, bcpup;
+	struct dentry *dentry, *parent, *h_dentry;
+	struct inode *h_inode, *inode;
+	struct super_block *sb;
+
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	bstart = au_fbstart(file);
+	inode = dentry->d_inode;
+	err = au_test_ro(sb, bstart, inode);
+	if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
+		err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
+		goto out;
+	}
+
+	/* need to cpup */
+	parent = dget_parent(dentry);
+	di_write_lock_parent(parent);
+	err = AuWbrCopyup(au_sbi(sb), dentry);
+	bcpup = err;
+	if (unlikely(err < 0))
+		goto out_dgrade;
+	err = 0;
+
+	if (!au_h_dptr(parent, bcpup)) {
+		err = au_cpup_dirs(dentry, bcpup);
+		if (unlikely(err))
+			goto out_dgrade;
+	}
+
+	err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
+		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+	if (unlikely(err))
+		goto out_dgrade;
+
+	h_dentry = au_h_fptr(file, bstart)->f_dentry;
+	h_inode = h_dentry->d_inode;
+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
+	if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
+	    /* || !h_inode->i_nlink */) {
+		err = au_ready_to_write_wh(file, len, bcpup);
+		di_downgrade_lock(parent, AuLock_IR);
+	} else {
+		di_downgrade_lock(parent, AuLock_IR);
+		if (!au_h_dptr(dentry, bcpup))
+			err = au_sio_cpup_simple(dentry, bcpup, len,
+						 AuCpup_DTIME);
+		if (!err)
+			err = au_reopen_nondir(file);
+	}
+	mutex_unlock(&h_inode->i_mutex);
+
+	if (!err) {
+		au_pin_set_parent_lflag(pin, /*lflag*/0);
+		goto out_dput; /* success */
+	}
+	au_unpin(pin);
+	goto out_unlock;
+
+ out_dgrade:
+	di_downgrade_lock(parent, AuLock_IR);
+ out_unlock:
+	di_read_unlock(parent, AuLock_IR);
+ out_dput:
+	dput(parent);
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
+{
+	int err;
+	aufs_bindex_t bstart;
+	struct au_pin pin;
+	struct au_finfo *finfo;
+	struct dentry *dentry, *parent, *hi_wh;
+	struct inode *inode;
+	struct super_block *sb;
+
+	FiMustWriteLock(file);
+
+	err = 0;
+	finfo = au_fi(file);
+	dentry = file->f_dentry;
+	sb = dentry->d_sb;
+	inode = dentry->d_inode;
+	bstart = au_ibstart(inode);
+	if (bstart == finfo->fi_bstart)
+		goto out;
+
+	parent = dget_parent(dentry);
+	if (au_test_ro(sb, bstart, inode)) {
+		di_read_lock_parent(parent, !AuLock_IR);
+		err = AuWbrCopyup(au_sbi(sb), dentry);
+		bstart = err;
+		di_read_unlock(parent, !AuLock_IR);
+		if (unlikely(err < 0))
+			goto out_parent;
+		err = 0;
+	}
+
+	di_read_lock_parent(parent, AuLock_IR);
+	hi_wh = au_hi_wh(inode, bstart);
+	if (au_opt_test(au_mntflags(sb), PLINK)
+	    && au_plink_test(inode)
+	    && !d_unhashed(dentry)) {
+		err = au_test_and_cpup_dirs(dentry, bstart);
+		if (unlikely(err))
+			goto out_unlock;
+
+		/* always superio. */
+		err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
+			     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
+		if (!err)
+			err = au_sio_cpup_simple(dentry, bstart, -1,
+						 AuCpup_DTIME);
+		au_unpin(&pin);
+	} else if (hi_wh) {
+		/* already copied-up after unlink */
+		err = au_reopen_wh(file, bstart, hi_wh);
+		*need_reopen = 0;
+	}
+
+ out_unlock:
+	di_read_unlock(parent, AuLock_IR);
+ out_parent:
+	dput(parent);
+ out:
+	return err;
+}
+
+static void au_do_refresh_file(struct file *file)
+{
+	aufs_bindex_t bindex, bend, new_bindex, brid;
+	struct au_hfile *p, tmp, *q;
+	struct au_finfo *finfo;
+	struct super_block *sb;
+
+	FiMustWriteLock(file);
+
+	sb = file->f_dentry->d_sb;
+	finfo = au_fi(file);
+	p = finfo->fi_hfile + finfo->fi_bstart;
+	brid = p->hf_br->br_id;
+	bend = finfo->fi_bend;
+	for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
+		if (!p->hf_file)
+			continue;
+
+		new_bindex = au_br_index(sb, p->hf_br->br_id);
+		if (new_bindex == bindex)
+			continue;
+		if (new_bindex < 0) {
+			au_set_h_fptr(file, bindex, NULL);
+			continue;
+		}
+
+		/* swap two lower inode, and loop again */
+		q = finfo->fi_hfile + new_bindex;
+		tmp = *q;
+		*q = *p;
+		*p = tmp;
+		if (tmp.hf_file) {
+			bindex--;
+			p--;
+		}
+	}
+
+	p = finfo->fi_hfile;
+	if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
+		bend = au_sbend(sb);
+		for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
+		     finfo->fi_bstart++, p++)
+			if (p->hf_file) {
+				if (p->hf_file->f_dentry
+				    && p->hf_file->f_dentry->d_inode)
+					break;
+				else
+					au_hfput(p, file);
+			}
+	} else {
+		bend = au_br_index(sb, brid);
+		for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
+		     finfo->fi_bstart++, p++)
+			if (p->hf_file)
+				au_hfput(p, file);
+		bend = au_sbend(sb);
+	}
+
+	p = finfo->fi_hfile + bend;
+	for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
+	     finfo->fi_bend--, p--)
+		if (p->hf_file) {
+			if (p->hf_file->f_dentry
+			    && p->hf_file->f_dentry->d_inode)
+				break;
+			else
+				au_hfput(p, file);
+		}
+	AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
+}
+
+/*
+ * after branch manipulating, refresh the file.
+ */
+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
+{
+	int err, need_reopen;
+	struct dentry *dentry;
+	aufs_bindex_t bend, bindex;
+
+	dentry = file->f_dentry;
+	err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
+	if (unlikely(err))
+		goto out;
+	au_do_refresh_file(file);
+
+	err = 0;
+	need_reopen = 1;
+	if (!au_test_mmapped(file))
+		err = au_file_refresh_by_inode(file, &need_reopen);
+	if (!err && need_reopen && !d_unhashed(dentry))
+		err = reopen(file);
+	if (!err) {
+		au_update_figen(file);
+		return 0; /* success */
+	}
+
+	/* error, close all lower files */
+	bend = au_fbend(file);
+	for (bindex = au_fbstart(file); bindex <= bend; bindex++)
+		au_set_h_fptr(file, bindex, NULL);
+
+ out:
+	return err;
+}
+
+/* common function to regular file and dir */
+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
+			  int wlock)
+{
+	int err;
+	unsigned int sigen, figen;
+	aufs_bindex_t bstart;
+	unsigned char pseudo_link;
+	struct dentry *dentry;
+
+	err = 0;
+	dentry = file->f_dentry;
+	sigen = au_sigen(dentry->d_sb);
+	fi_write_lock(file);
+	figen = au_figen(file);
+	di_write_lock_child(dentry);
+	bstart = au_dbstart(dentry);
+	pseudo_link = (bstart != au_ibstart(dentry->d_inode));
+	if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
+		if (!wlock) {
+			di_downgrade_lock(dentry, AuLock_IR);
+			fi_downgrade_lock(file);
+		}
+		goto out; /* success */
+	}
+
+	AuDbg("sigen %d, figen %d\n", sigen, figen);
+	if (sigen != au_digen(dentry)
+	    || sigen != au_iigen(dentry->d_inode)) {
+		err = au_reval_dpath(dentry, sigen);
+		if (unlikely(err < 0))
+			goto out;
+		AuDebugOn(au_digen(dentry) != sigen
+			  || au_iigen(dentry->d_inode) != sigen);
+	}
+
+	err = refresh_file(file, reopen);
+	if (!err) {
+		if (!wlock) {
+			di_downgrade_lock(dentry, AuLock_IR);
+			fi_downgrade_lock(file);
+		}
+	} else {
+		di_write_unlock(dentry);
+		fi_write_unlock(file);
+	}
+
+ out:
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* cf. aufs_nopage() */
+/* for madvise(2) */
+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
+{
+	unlock_page(page);
+	return 0;
+}
+
+/* they will never be called. */
+#ifdef CONFIG_AUFS_DEBUG
+static int aufs_write_begin(struct file *file, struct address_space *mapping,
+			    loff_t pos, unsigned len, unsigned flags,
+			    struct page **pagep, void **fsdata)
+{ AuUnsupport(); return 0; }
+static int aufs_write_end(struct file *file, struct address_space *mapping,
+			  loff_t pos, unsigned len, unsigned copied,
+			  struct page *page, void *fsdata)
+{ AuUnsupport(); return 0; }
+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
+{ AuUnsupport(); return 0; }
+static void aufs_sync_page(struct page *page)
+{ AuUnsupport(); }
+
+static int aufs_set_page_dirty(struct page *page)
+{ AuUnsupport(); return 0; }
+static void aufs_invalidatepage(struct page *page, unsigned long offset)
+{ AuUnsupport(); }
+static int aufs_releasepage(struct page *page, gfp_t gfp)
+{ AuUnsupport(); return 0; }
+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
+			      const struct iovec *iov, loff_t offset,
+			      unsigned long nr_segs)
+{ AuUnsupport(); return 0; }
+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
+			    int create, void **kmem, unsigned long *pfn)
+{ AuUnsupport(); return 0; }
+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
+			    struct page *page)
+{ AuUnsupport(); return 0; }
+static int aufs_launder_page(struct page *page)
+{ AuUnsupport(); return 0; }
+static int aufs_is_partially_uptodate(struct page *page,
+				      read_descriptor_t *desc,
+				      unsigned long from)
+{ AuUnsupport(); return 0; }
+static int aufs_error_remove_page(struct address_space *mapping,
+				  struct page *page)
+{ AuUnsupport(); return 0; }
+#endif /* CONFIG_AUFS_DEBUG */
+
+struct address_space_operations aufs_aop = {
+	.readpage		= aufs_readpage,
+#ifdef CONFIG_AUFS_DEBUG
+	.writepage		= aufs_writepage,
+	.sync_page		= aufs_sync_page,
+	/* no writepages, because of writepage */
+	.set_page_dirty		= aufs_set_page_dirty,
+	/* no readpages, because of readpage */
+	.write_begin		= aufs_write_begin,
+	.write_end		= aufs_write_end,
+	/* no bmap, no block device */
+	.invalidatepage		= aufs_invalidatepage,
+	.releasepage		= aufs_releasepage,
+	.direct_IO		= aufs_direct_IO,	/* todo */
+	.get_xip_mem		= aufs_get_xip_mem,	/* todo */
+	.migratepage		= aufs_migratepage,
+	.launder_page		= aufs_launder_page,
+	.is_partially_uptodate	= aufs_is_partially_uptodate,
+	.error_remove_page	= aufs_error_remove_page
+#endif /* CONFIG_AUFS_DEBUG */
+};
--- linux-ec2-2.6.32.orig/ubuntu/aufs/spl.h
+++ linux-ec2-2.6.32/ubuntu/aufs/spl.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * simple list protected by a spinlock
+ */
+
+#ifndef __AUFS_SPL_H__
+#define __AUFS_SPL_H__
+
+#ifdef __KERNEL__
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+struct au_splhead {
+	spinlock_t		spin;
+	struct list_head	head;
+};
+
+static inline void au_spl_init(struct au_splhead *spl)
+{
+	spin_lock_init(&spl->spin);
+	INIT_LIST_HEAD(&spl->head);
+}
+
+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
+{
+	spin_lock(&spl->spin);
+	list_add(list, &spl->head);
+	spin_unlock(&spl->spin);
+}
+
+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
+{
+	spin_lock(&spl->spin);
+	list_del(list);
+	spin_unlock(&spl->spin);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_SPL_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/compcache/xvmalloc.h
+++ linux-ec2-2.6.32/ubuntu/compcache/xvmalloc.h
@@ -0,0 +1,30 @@
+/*
+ * xvmalloc.h
+ *
+ * Copyright (C) 2008, 2009  Nitin Gupta
+ *
+ * This code is released using a dual license strategy: GPL/LGPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of GNU General Public License Version 2.0
+ * Released under the terms of GNU Lesser General Public License Version 2.1
+ */
+
+#ifndef _XVMALLOC_H_
+#define _XVMALLOC_H_
+
+#include <linux/types.h>
+
+struct xv_pool;
+
+struct xv_pool *xv_create_pool(void);
+void xv_destroy_pool(struct xv_pool *pool);
+
+int xv_malloc(struct xv_pool *pool, u32 size, u32 *pagenum, u32 *offset,
+							gfp_t flags);
+void xv_free(struct xv_pool *pool, u32 pagenum, u32 offset);
+
+u32 xv_get_object_size(void *obj);
+u64 xv_get_total_size_bytes(struct xv_pool *pool);
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/compcache/Makefile
+++ linux-ec2-2.6.32/ubuntu/compcache/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BLK_DEV_COMPCACHE) := ramzswap.o xvmalloc.o
--- linux-ec2-2.6.32.orig/ubuntu/compcache/ramzswap.h
+++ linux-ec2-2.6.32/ubuntu/compcache/ramzswap.h
@@ -0,0 +1,159 @@
+/*
+ * Compressed RAM based swap device
+ *
+ * Copyright (C) 2008, 2009  Nitin Gupta
+ *
+ * This RAM based block device acts as swap disk.
+ * Pages swapped to this device are compressed and
+ * stored in memory.
+ *
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ * Project home: http://compcache.googlecode.com
+ */
+
+#ifndef _RAMZSWAP_H_
+#define _RAMZSWAP_H_
+
+#include "xvmalloc.h"
+
+/*
+ * Stored at beginning of each compressed object.
+ *
+ * It stores back-reference to table entry which points to this
+ * object. This is required to support memory defragmentation or
+ * migrating compressed pages to backing swap disk.
+ */
+struct zobj_header {
+#if 0
+	u32 table_idx;
+#endif
+};
+
+/*-- Configurable parameters */
+
+/* Default ramzswap disk size: 25% of total RAM */
+#define DEFAULT_DISKSIZE_PERC_RAM	25
+#define DEFAULT_MEMLIMIT_PERC_RAM	15
+
+/*
+ * Max compressed page size when backing device is provided.
+ * Pages that compress to size greater than this are sent to
+ * physical swap disk.
+ */
+#define MAX_CPAGE_SIZE_BDEV	(PAGE_SIZE / 2)
+
+/*
+ * Max compressed page size when there is no backing dev.
+ * Pages that compress to size greater than this are stored
+ * uncompressed in memory.
+ */
+#define MAX_CPAGE_SIZE_NOBDEV	(PAGE_SIZE / 4 * 3)
+
+/*
+ * NOTE: MAX_CPAGE_SIZE_{BDEV,NOBDEV} sizes must be
+ * less than or equal to:
+ *   XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header)
+ * since otherwise xvMalloc would always return failure.
+ */
+
+/*-- End of configurable params */
+
+#define SECTOR_SHIFT		9
+#define SECTOR_SIZE		(1 << SECTOR_SHIFT)
+#define SECTORS_PER_PAGE_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
+#define SECTORS_PER_PAGE	(1 << SECTORS_PER_PAGE_SHIFT)
+
+/* Message prefix */
+#define C "ramzswap: "
+
+/* Debugging and Stats */
+#define NOP	do { } while (0)
+
+#if defined(CONFIG_BLK_DEV_RAMZSWAP_STATS)
+#define STATS
+#endif
+
+#if defined(STATS)
+#define stat_inc(stat)			((stat)++)
+#define stat_dec(stat)			((stat)--)
+#define stat_inc_if_less(stat, val1, val2) \
+				((stat) += ((val1) < (val2) ? 1 : 0))
+#define stat_dec_if_less(stat, val1, val2) \
+				((stat) -= ((val1) < (val2) ? 1 : 0))
+#else	/* STATS */
+#define stat_inc(x)			NOP
+#define stat_dec(x)			NOP
+#define stat_inc_if_less(x, v1, v2)	NOP
+#define stat_dec_if_less(x, v1, v2)	NOP
+#endif	/* STATS */
+
+/* Flags for ramzswap pages (table[page_no].flags) */
+enum rzs_pageflags {
+	/* Page is stored uncompressed */
+	RZS_UNCOMPRESSED,
+
+	/* Page consists entirely of zeros */
+	RZS_ZERO,
+
+	__NR_RZS_PAGEFLAGS,
+};
+
+/*-- Data structures */
+
+/* Indexed by page no. */
+struct table {
+	u32 pagenum;
+	u16 offset;
+	u8 count;	/* object ref count (not yet used) */
+	u8 flags;
+};
+
+struct ramzswap {
+	struct xv_pool *mem_pool;
+	void *compress_workmem;
+	void *compress_buffer;
+	struct table *table;
+	struct mutex lock;
+	struct gendisk *disk;
+	/*
+	 * This is limit on compressed data size (stats.compr_size)
+	 * Its applicable only when backing swap device is present.
+	 */
+	size_t memlimit;	/* bytes */
+	/*
+	 * This is limit on amount of *uncompressed* worth of data
+	 * we can hold. When backing swap device is provided, it is
+	 * set equal to device size.
+	 */
+	size_t disksize;	/* bytes */
+
+	/* backing swap device info */
+	struct block_device *backing_swap;
+	struct file *swap_file;
+	int old_block_size;
+};
+
+struct ramzswap_stats {
+	/* basic stats */
+	size_t compr_size;	/* compressed size of pages stored -
+				 * needed to enforce memlimit */
+	/* more stats */
+#if defined(STATS)
+	u64 num_reads;		/* failed + successful */
+	u64 num_writes;		/* --do-- */
+	u64 failed_reads;	/* can happen when memory is too low */
+	u64 failed_writes;	/* should NEVER! happen */
+	u64 invalid_io;		/* non-swap I/O requests */
+	u64 pages_discard;	/* no. of pages freed by discard callback */
+	u32 pages_zero;		/* no. of zero filled pages */
+	u32 pages_stored;	/* no. of pages currently stored */
+	u32 good_compress;	/* no. of pages with compression ratio<=50% */
+	u32 pages_expand;	/* no. of incompressible pages */
+	u64 bdev_num_reads;	/* no. of reads on backing dev */
+	u64 bdev_num_writes;	/* no. of writes on backing dev */
+#endif
+};
+/*-- */
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/compcache/GPL.txt
+++ linux-ec2-2.6.32/ubuntu/compcache/GPL.txt
@@ -0,0 +1,280 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
--- linux-ec2-2.6.32.orig/ubuntu/compcache/Kconfig
+++ linux-ec2-2.6.32/ubuntu/compcache/Kconfig
@@ -0,0 +1,31 @@
+menu "Compcache options"
+
+config BLK_DEV_COMPCACHE
+	tristate "Compressed RAM based swap device"
+	default m
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
+	depends on BLOCK
+	help
+	  This creates RAM based block device which acts as swap disk. Pages
+	  swapped to this disk are compressed and stored in memory itself.
+	  Project Home: http://code.google.com/p/compcache/
+
+config BLK_DEV_COMPCACHE_DEBUG
+	default n
+	depends on BLK_DEV_COMPCACHE
+	bool "Enable debugging"
+	help
+	  This causes negligible performance loss and size increase.
+	  If unsure, say Y.
+
+config BLK_DEV_COMPCACHE_STATS
+	default n
+	depends on BLK_DEV_COMPCACHE
+	bool "Enable statistics"
+	help
+	  Creates /proc/compcache to export various statistics.
+	  This adds about 4K to size with negligible performance loss.
+	  If unsure, say Y.
+ 
+endmenu
--- linux-ec2-2.6.32.orig/ubuntu/compcache/ramzswap.c
+++ linux-ec2-2.6.32/ubuntu/compcache/ramzswap.c
@@ -0,0 +1,1049 @@
+/*
+ * Compressed RAM based swap device
+ *
+ * Copyright (C) 2008, 2009  Nitin Gupta
+ *
+ * This RAM based block device acts as swap disk.
+ * Pages swapped to this device are compressed and
+ * stored in memory.
+ *
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ * Project home: http://compcache.googlecode.com
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/device.h>
+#include <linux/genhd.h>
+#include <linux/highmem.h>
+#include <linux/lzo.h>
+#include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/vmalloc.h>
+
+#include "compat.h"
+#include "ramzswap.h"
+
+/* Globals */
+static struct ramzswap rzs;
+static struct ramzswap_stats stats;
+/*
+ * Pages that compress to larger than this size are
+ * forwarded to backing swap, if present or stored
+ * uncompressed in memory otherwise.
+ */
+static unsigned int MAX_CPAGE_SIZE;
+
+/* Module params (documentation at end) */
+static unsigned long disksize_kb;
+static unsigned long memlimit_kb;
+static char *backing_swap;
+
+static int __init ramzswap_init(void);
+static struct block_device_operations ramzswap_devops = {
+	.owner = THIS_MODULE,
+};
+
+static int test_flag(u32 index, enum rzs_pageflags flag)
+{
+	return rzs.table[index].flags & BIT(flag);
+}
+
+static void set_flag(u32 index, enum rzs_pageflags flag)
+{
+	rzs.table[index].flags |= BIT(flag);
+}
+
+static void clear_flag(u32 index, enum rzs_pageflags flag)
+{
+	rzs.table[index].flags &= ~BIT(flag);
+}
+
+static int page_zero_filled(void *ptr)
+{
+	u32 pos;
+	u64 *page;
+
+	page = (u64 *)ptr;
+
+	for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
+		if (page[pos])
+			return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Given <pagenum, offset> pair, provide a dereferencable pointer.
+ */
+static void *get_ptr_atomic(u32 pagenum, u16 offset, enum km_type type)
+{
+	unsigned char *page;
+
+	page = kmap_atomic(pfn_to_page(pagenum), type);
+	return page + offset;
+}
+
+static void put_ptr_atomic(void *ptr, enum km_type type)
+{
+	kunmap_atomic(ptr, type);
+}
+
+#if defined(STATS)
+static struct proc_dir_entry *proc;
+
+static int proc_ramzswap_read(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	int len;
+	size_t succ_writes, mem_used;
+	unsigned int good_compress_perc = 0, no_compress_perc = 0;
+
+	mem_used = xv_get_total_size_bytes(rzs.mem_pool)
+			+ (stats.pages_expand << PAGE_SHIFT);
+
+	if (off > 0) {
+		*eof = 1;
+		return 0;
+	}
+
+#define K(x)	((x) >> 10)
+	/* Basic stats */
+	len = sprintf(page,
+		"DiskSize:	%8zu kB\n",
+		(size_t)(K(rzs.disksize)));
+
+	if (rzs.backing_swap) {
+		/* This must always be less than ComprDataSize */
+		len += sprintf(page + len,
+			"MemLimit:	%8zu kB\n",
+			K(rzs.memlimit));
+	}
+
+	succ_writes = stats.num_writes - stats.failed_writes;
+
+	if (succ_writes && stats.pages_stored) {
+		good_compress_perc = stats.good_compress * 100
+					/ stats.pages_stored;
+		no_compress_perc = stats.pages_expand * 100
+					/ stats.pages_stored;
+	}
+
+	/* Extended stats */
+	len += sprintf(page + len,
+		"NumReads:	%8llu\n"
+		"NumWrites:	%8llu\n"
+		"FailedReads:	%8llu\n"
+		"FailedWrites:	%8llu\n"
+		"InvalidIO:	%8llu\n"
+		"PagesDiscard:	%8llu\n"
+		"ZeroPages:	%8u\n"
+		"GoodCompress:	%8u %%\n"
+		"NoCompress:	%8u %%\n"
+		"PagesStored:	%8u\n"
+		"PagesUsed:	%8zu\n"
+		"OrigDataSize:	%8zu kB\n"
+		"ComprDataSize:	%8zu kB\n"
+		"MemUsedTotal:	%8zu kB\n",
+		stats.num_reads,
+		stats.num_writes,
+		stats.failed_reads,
+		stats.failed_writes,
+		stats.invalid_io,
+		stats.pages_discard,
+		stats.pages_zero,
+		good_compress_perc,
+		no_compress_perc,
+		stats.pages_stored,
+		mem_used >> PAGE_SHIFT,
+		(size_t)(K(stats.pages_stored << PAGE_SHIFT)),
+		(size_t)(K(stats.compr_size)),
+		(size_t)(K(mem_used)));
+
+	if (rzs.backing_swap) {
+		/* This must always be less than ComprDataSize */
+		len += sprintf(page + len,
+			"BDevNumReads:	%8llu\n"
+			"BDevNumWrites:	%8llu\n",
+			stats.bdev_num_reads,
+			stats.bdev_num_writes);
+	}
+
+	return len;
+}
+#endif	/* STATS */
+
+/*
+ * Check if value of backing_swap module param is sane.
+ * Claim this device and set ramzswap size equal to
+ * size of this block device.
+ */
+static int setup_backing_swap(void)
+{
+	int error = 0;
+	struct inode *inode;
+	struct file *swap_file;
+	struct address_space *mapping;
+	struct block_device *bdev = NULL;
+
+	if (backing_swap == NULL) {
+		pr_debug(C "backing_swap param not given\n");
+		goto out;
+	}
+
+	pr_info(C "Using backing swap device: %s\n", backing_swap);
+
+	swap_file = filp_open(backing_swap, O_RDWR | O_LARGEFILE, 0);
+	if (IS_ERR(swap_file)) {
+		pr_err(C "Error opening backing device: %s\n", backing_swap);
+		error = -EINVAL;
+		goto out;
+	}
+
+	mapping = swap_file->f_mapping;
+	inode = mapping->host;
+
+	if (S_ISBLK(inode->i_mode)) {
+		bdev = I_BDEV(inode);
+		error = bd_claim(bdev, ramzswap_init);
+		if (error < 0) {
+			bdev = NULL;
+			goto bad_param;
+		}
+		rzs.old_block_size = block_size(bdev);
+		error = set_blocksize(bdev, PAGE_SIZE);
+		if (error < 0)
+			goto bad_param;
+	} else {
+		/* TODO: support for regular file as backing swap */
+		pr_info(C "%s is not a block device.\n", backing_swap);
+		error = -EINVAL;
+		goto out;
+	}
+
+	rzs.swap_file = swap_file;
+	rzs.backing_swap = bdev;
+	rzs.disksize = i_size_read(inode);
+	BUG_ON(!rzs.disksize);
+
+	return 0;
+
+bad_param:
+	if (bdev) {
+		set_blocksize(bdev, rzs.old_block_size);
+		bd_release(bdev);
+	}
+	filp_close(swap_file, NULL);
+
+out:
+	rzs.backing_swap = NULL;
+	return error;
+}
+
+/*
+ * Check if request is within bounds and page aligned.
+ */
+static inline int valid_swap_request(struct bio *bio)
+{
+	if (unlikely(
+		(bio->bi_sector >= (rzs.disksize >> SECTOR_SHIFT)) ||
+		(bio->bi_sector & (SECTORS_PER_PAGE - 1)) ||
+		(bio->bi_vcnt != 1) ||
+		(bio->bi_size != PAGE_SIZE) ||
+		(bio->bi_io_vec[0].bv_offset != 0))) {
+
+		return 0;
+	}
+
+	/* swap request is valid */
+	return 1;
+}
+
+static void ramzswap_free_page(size_t index)
+{
+	u32 clen;
+	void *obj;
+
+	u32 pagenum = rzs.table[index].pagenum;
+	u32 offset = rzs.table[index].offset;
+
+	if (unlikely(test_flag(index, RZS_UNCOMPRESSED))) {
+		clen = PAGE_SIZE;
+		__free_page(pfn_to_page(pagenum));
+		clear_flag(index, RZS_UNCOMPRESSED);
+		stat_dec(stats.pages_expand);
+		goto out;
+	}
+
+	obj = get_ptr_atomic(pagenum, offset, KM_USER0);
+	clen = xv_get_object_size(obj) - sizeof(struct zobj_header);
+	put_ptr_atomic(obj, KM_USER0);
+
+	xv_free(rzs.mem_pool, pagenum, offset);
+	stat_dec_if_less(stats.good_compress, clen, PAGE_SIZE / 2 + 1);
+
+out:
+	stats.compr_size -= clen;
+	stat_dec(stats.pages_stored);
+
+	rzs.table[index].pagenum = 0;
+	rzs.table[index].offset = 0;
+}
+
+#ifdef SWAP_DISCARD_SUPPORTED
+static int ramzswap_prepare_discard(struct request_queue *q,
+					struct request *req)
+{
+	return 0;
+}
+
+/*
+ * Called by main I/O handler function. This helper
+ * function handles 'discard' I/O requests which means
+ * that  some swap pages are no longer required, so
+ * swap device can take needed action -- we free memory
+ * allocated for these pages.
+ */
+static int ramzswap_discard(struct bio *bio)
+{
+	size_t index, start_page, num_pages;
+
+	start_page = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+	num_pages = bio->bi_size >> (SECTOR_SHIFT + SECTORS_PER_PAGE_SHIFT);
+
+	for (index = start_page; index < start_page + num_pages; index++) {
+		if (rzs.table[index].pagenum) {
+			ramzswap_free_page(index);
+			stat_inc(stats.pages_discard);
+		}
+	}
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+}
+#endif
+
+int handle_zero_page(struct bio *bio)
+{
+	void *user_mem;
+	struct page *page = bio->bi_io_vec[0].bv_page;
+
+	user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0);
+	memset(user_mem, 0, PAGE_SIZE);
+	put_ptr_atomic(user_mem, KM_USER0);
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+}
+
+int handle_uncompressed_page(struct bio *bio)
+{
+	u32 index;
+	struct page *page;
+	unsigned char *user_mem, *cmem;
+
+	page = bio->bi_io_vec[0].bv_page;
+	index = bio->bi_sector >>SECTORS_PER_PAGE_SHIFT;
+
+	user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0);
+	cmem = get_ptr_atomic(rzs.table[index].pagenum,
+			rzs.table[index].offset, KM_USER1);
+
+	memcpy(user_mem, cmem, PAGE_SIZE);
+	put_ptr_atomic(user_mem, KM_USER0);
+	put_ptr_atomic(cmem, KM_USER1);
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+}
+
+
+/*
+ * Called when request page is not present in ramzswap.
+ * Its either in backing swap device (if present) or
+ * this is an attempt to read before any previous write
+ * to this location - this happens due to readahead when
+ * swap device is read from user-space (e.g. during swapon)
+ */
+int handle_ramzswap_fault(struct bio *bio)
+{
+	void *user_mem;
+	struct page *page = bio->bi_io_vec[0].bv_page;
+
+	/*
+	 * Always forward such requests to backing swap
+	 * device (if present)
+	 */
+	if (rzs.backing_swap) {
+		stat_dec(stats.num_reads);
+		stat_inc(stats.bdev_num_reads);
+		bio->bi_bdev = rzs.backing_swap;
+		return 1;
+	}
+
+	/*
+	 * Its unlikely event in case backing dev is
+	 * not present
+	 */
+	pr_debug(C "Read before write on swap device: "
+		"sector=%lu, size=%u, offset=%u\n",
+		(ulong)(bio->bi_sector), bio->bi_size,
+		bio->bi_io_vec[0].bv_offset);
+	user_mem = kmap(page);
+	memset(user_mem, 0, PAGE_SIZE);
+	kunmap(page);
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+}
+
+int ramzswap_read(struct bio *bio)
+{
+	int ret;
+	u32 index;
+	size_t clen;
+	struct page *page;
+	struct zobj_header *zheader;
+	unsigned char *user_mem, *cmem;
+
+	stat_inc(stats.num_reads);
+
+	page = bio->bi_io_vec[0].bv_page;
+	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+
+	if (test_flag(index, RZS_ZERO))
+		return handle_zero_page(bio);
+
+	/* Requested page is not present in compressed area */
+	if (!rzs.table[index].pagenum)
+		return handle_ramzswap_fault(bio);
+
+	/* Page is stored uncompressed since its incompressible */
+	if (unlikely(test_flag(index, RZS_UNCOMPRESSED)))
+		return handle_uncompressed_page(bio);
+
+	user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0);
+	clen = PAGE_SIZE;
+
+	cmem = get_ptr_atomic(rzs.table[index].pagenum,
+			rzs.table[index].offset, KM_USER1);
+
+	ret = lzo1x_decompress_safe(
+		cmem + sizeof(*zheader),
+		xv_get_object_size(cmem) - sizeof(*zheader),
+		user_mem, &clen);
+
+	put_ptr_atomic(user_mem, KM_USER0);
+	put_ptr_atomic(cmem, KM_USER1);
+
+	/* should NEVER happen */
+	if (unlikely(ret != LZO_E_OK)) {
+		pr_err(C "Decompression failed! err=%d, page=%u\n",
+			ret, index);
+		stat_inc(stats.failed_reads);
+		goto out;
+	}
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+
+out:
+	BIO_IO_ERROR(bio);
+	return 0;
+}
+
+int ramzswap_write(struct bio *bio)
+{
+	int ret, fwd_write_request = 0;
+	u32 offset;
+	size_t clen, index;
+	struct zobj_header *zheader;
+	struct page *page, *page_store;
+	unsigned char *user_mem, *cmem, *src;
+
+	stat_inc(stats.num_writes);
+
+	page = bio->bi_io_vec[0].bv_page;
+	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+
+	src = rzs.compress_buffer;
+
+	/*
+	 * System swaps to same sector again when the stored page
+	 * is no longer referenced by any process. So, its now safe
+	 * to free the memory that was allocated for this page.
+	 */
+	if (rzs.table[index].pagenum)
+		ramzswap_free_page(index);
+
+	/*
+	 * No memory ia allocated for zero filled pages.
+	 * Simply clear zero page flag.
+	 */
+	if (test_flag(index, RZS_ZERO)) {
+		stat_dec(stats.pages_zero);
+		clear_flag(index, RZS_ZERO);
+	}
+
+	mutex_lock(&rzs.lock);
+
+	user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0);
+	if (page_zero_filled(user_mem)) {
+		put_ptr_atomic(user_mem, KM_USER0);
+		mutex_unlock(&rzs.lock);
+		stat_inc(stats.pages_zero);
+		set_flag(index, RZS_ZERO);
+
+		set_bit(BIO_UPTODATE, &bio->bi_flags);
+		BIO_ENDIO(bio, 0);
+		return 0;
+	}
+
+	if (rzs.backing_swap &&
+		(stats.compr_size > rzs.memlimit - PAGE_SIZE)) {
+		put_ptr_atomic(user_mem, KM_USER0);
+		mutex_unlock(&rzs.lock);
+		fwd_write_request = 1;
+		goto out;
+	}
+
+	ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen,
+				rzs.compress_workmem);
+
+	put_ptr_atomic(user_mem, KM_USER0);
+
+	if (unlikely(ret != LZO_E_OK)) {
+		mutex_unlock(&rzs.lock);
+		pr_err(C "Compression failed! err=%d\n", ret);
+		stat_inc(stats.failed_writes);
+		goto out;
+	}
+
+	/*
+	 * Page is incompressible. Forward it to backing swap
+	 * if present. Otherwise, store it as-is (uncompressed)
+	 * since we do not want to return too many swap write
+	 * errors which has side effect of hanging the system.
+	 */
+	if (unlikely(clen > MAX_CPAGE_SIZE)) {
+		if (rzs.backing_swap) {
+			mutex_unlock(&rzs.lock);
+			fwd_write_request = 1;
+			goto out;
+		}
+
+		clen = PAGE_SIZE;
+		page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+		if (unlikely(!page_store)) {
+			mutex_unlock(&rzs.lock);
+			stat_inc(stats.failed_writes);
+			goto out;
+		}
+
+		offset = 0;
+		set_flag(index, RZS_UNCOMPRESSED);
+		stat_inc(stats.pages_expand);
+		rzs.table[index].pagenum = page_to_pfn(page_store);
+		src = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0);
+		goto memstore;
+	}
+
+	if (xv_malloc(rzs.mem_pool, clen + sizeof(*zheader),
+			&rzs.table[index].pagenum, &offset,
+			GFP_NOIO | __GFP_HIGHMEM)) {
+		mutex_unlock(&rzs.lock);
+		pr_info(C "Error allocating memory for compressed "
+			"page: %zu, size=%zu\n", index, clen);
+		stat_inc(stats.failed_writes);
+		if (rzs.backing_swap)
+			fwd_write_request = 1;
+		goto out;
+	}
+
+memstore:
+	rzs.table[index].offset = offset;
+
+	cmem = get_ptr_atomic(rzs.table[index].pagenum,
+			rzs.table[index].offset, KM_USER1);
+
+#if 0
+	/* Back-reference needed for memory defragmentation */
+	if (!test_flag(index, RZS_UNCOMPRESSED)) {
+		zheader = (struct zobj_header *)cmem;
+		zheader->table_idx = index;
+		cmem += sizeof(*zheader);
+	}
+#endif
+
+	memcpy(cmem, src, clen);
+
+	put_ptr_atomic(cmem, KM_USER1);
+	if (unlikely(test_flag(index, RZS_UNCOMPRESSED)))
+		put_ptr_atomic(src, KM_USER0);
+
+	/* Update stats */
+	stats.compr_size += clen;
+	stat_inc(stats.pages_stored);
+	stat_inc_if_less(stats.good_compress, clen, PAGE_SIZE / 2 + 1);
+
+	mutex_unlock(&rzs.lock);
+
+	set_bit(BIO_UPTODATE, &bio->bi_flags);
+	BIO_ENDIO(bio, 0);
+	return 0;
+
+out:
+	if (fwd_write_request) {
+		stat_inc(stats.bdev_num_writes);
+		bio->bi_bdev = rzs.backing_swap;
+		return 1;
+	}
+
+	BIO_IO_ERROR(bio);
+	return 0;
+}
+
+/*
+ * Handler function for all ramzswap I/O requests.
+ */
+static int ramzswap_make_request(struct request_queue *queue, struct bio *bio)
+{
+	int ret = 0;
+
+#ifdef SWAP_DISCARD_SUPPORTED
+	if (bio_discard(bio))
+		return ramzswap_discard(bio);
+#endif
+
+	if (!valid_swap_request(bio)) {
+		stat_inc(stats.invalid_io);
+		BIO_IO_ERROR(bio);
+		return 0;
+	}
+
+	switch (bio_data_dir(bio)) {
+	case READ:
+		ret = ramzswap_read(bio);
+		break;
+
+	case WRITE:
+		ret = ramzswap_write(bio);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Swap header (1st page of swap device) contains information
+ * to indentify it as a swap partition. Prepare such a header
+ * for ramzswap device (ramzswap0) so that swapon can identify
+ * it as swap partition. In case backing swap device is provided,
+ * copy its swap header.
+ */
+static int setup_swap_header(union swap_header *s)
+{
+	int ret = 0;
+	struct page *page;
+	struct address_space *mapping;
+	union swap_header *backing_swap_header;
+
+	/*
+	 * There is no backing swap device. Create a swap header
+	 * that is acceptable by swapon.
+	 */
+	if (rzs.backing_swap == NULL) {
+		s->info.version = 1;
+		s->info.last_page = rzs.disksize >> PAGE_SHIFT;
+		s->info.nr_badpages = 0;
+		memcpy(s->magic.magic, "SWAPSPACE2", 10);
+		return 0;
+	}
+
+	/*
+	 * We have a backing swap device. Copy its swap header
+	 * to ramzswap device header. If this header contains
+	 * invalid information (backing device not a swap
+	 * partition, etc.), swapon will fail for ramzswap
+	 * which is correct behavior - we don't want to swap
+	 * over filesystem partition!
+	 */
+
+	/* Read the backing swap header (code from sys_swapon) */
+	mapping = rzs.swap_file->f_mapping;
+	if (!mapping->a_ops->readpage) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	page = read_mapping_page(mapping, 0, rzs.swap_file);
+	if (IS_ERR(page)) {
+		ret = PTR_ERR(page);
+		goto out;
+	}
+
+	backing_swap_header = kmap(page);
+	*s = *backing_swap_header;
+	kunmap(page);
+
+out:
+	return ret;
+}
+
+static void ramzswap_set_disksize(size_t totalram_bytes)
+{
+	rzs.disksize = disksize_kb << 10;
+
+	if (!disksize_kb) {
+		pr_info(C
+		"disk size not provided. You can use disksize_kb module "
+		"param to specify size.\nUsing default: (%u%% of RAM).\n",
+		DEFAULT_DISKSIZE_PERC_RAM
+		);
+		rzs.disksize = DEFAULT_DISKSIZE_PERC_RAM *
+					(totalram_bytes / 100);
+	}
+
+	if (disksize_kb > 2 * (totalram_bytes >> 10)) {
+		pr_info(C
+		"There is little point creating a ramzswap of greater than "
+		"twice the size of memory since we expect a 2:1 compression "
+		"ratio. Note that ramzswap uses about 0.1%% of the size of "
+		"the swap device when not in use so a huge ramzswap is "
+		"wasteful.\n"
+		"\tMemory Size: %zu kB\n"
+		"\tSize you selected: %lu kB\n"
+		"Continuing anyway ...\n",
+		totalram_bytes >> 10, disksize_kb
+		);
+	}
+
+	rzs.disksize &= PAGE_MASK;
+	pr_info(C "disk size set to %zu kB\n", rzs.disksize >> 10);
+}
+
+/*
+ * memlimit cannot be greater than backing disk size.
+ */
+static void ramzswap_set_memlimit(size_t totalram_bytes)
+{
+	int memlimit_valid = 1;
+	rzs.memlimit = memlimit_kb << 10;
+
+	if (!rzs.memlimit) {
+		pr_info(C "memory limit not set. You can use "
+			"memlimit_kb module param to specify limit.");
+		memlimit_valid = 0;
+	}
+
+	if (rzs.memlimit > rzs.disksize) {
+		pr_info(C "memory limit cannot be greater than "
+			"disksize: limit=%zu, disksize=%zu",
+			rzs.memlimit, rzs.disksize);
+		memlimit_valid = 0;
+	}
+
+	if (!memlimit_valid) {
+		size_t mempart, disksize;
+		pr_info(C "\nUsing default: MIN[(%u%% of RAM), "
+			"(backing disk size)].\n",
+			DEFAULT_MEMLIMIT_PERC_RAM);
+		mempart = DEFAULT_MEMLIMIT_PERC_RAM * (totalram_bytes / 100);
+		disksize = rzs.disksize;
+		rzs.memlimit = mempart > disksize ? disksize : mempart;
+	}
+
+	if (rzs.memlimit > totalram_bytes / 2) {
+		pr_info(C
+		"Its not advisable setting limit more than half of "
+		"size of memory since we expect a 2:1 compression ratio. "
+		"Limit represents amount of *compressed* data we can keep "
+		"in memory!\n"
+		"\tMemory Size: %zu kB\n"
+		"\tLimit you selected: %lu kB\n"
+		"Continuing anyway ...\n",
+		totalram_bytes >> 10, memlimit_kb
+		);
+	}
+
+	rzs.memlimit &= PAGE_MASK;
+	BUG_ON(!rzs.memlimit);
+
+	pr_info(C "memory limit set to %zu kB\n", rzs.memlimit >> 10);
+}
+
+static int __init ramzswap_init(void)
+{
+	int ret;
+	size_t num_pages, totalram_bytes;
+	struct sysinfo i;
+	struct page *page;
+	void *swap_header;
+
+	mutex_init(&rzs.lock);
+
+	ret = setup_backing_swap();
+	if (ret)
+		goto fail;
+
+	si_meminfo(&i);
+	/* Here is a trivia: guess unit used for i.totalram !! */
+	totalram_bytes = i.totalram << PAGE_SHIFT;
+
+	if (rzs.backing_swap)
+		ramzswap_set_memlimit(totalram_bytes);
+	else
+		ramzswap_set_disksize(totalram_bytes);
+
+	rzs.compress_workmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+	if (rzs.compress_workmem == NULL) {
+		pr_err(C "Error allocating compressor working memory\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	rzs.compress_buffer = kmalloc(2 * PAGE_SIZE, GFP_KERNEL);
+	if (rzs.compress_buffer == NULL) {
+		pr_err(C "Error allocating compressor buffer space\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	num_pages = rzs.disksize >> PAGE_SHIFT;
+	rzs.table = vmalloc(num_pages * sizeof(*rzs.table));
+	if (rzs.table == NULL) {
+		pr_err(C "Error allocating ramzswap address table\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+	memset(rzs.table, 0, num_pages * sizeof(*rzs.table));
+
+	page = alloc_page(__GFP_ZERO);
+	if (page == NULL) {
+		pr_err(C "Error allocating swap header page\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+	rzs.table[0].pagenum = page_to_pfn(page);
+	set_flag(0, RZS_UNCOMPRESSED);
+
+	swap_header = kmap(page);
+	ret = setup_swap_header((union swap_header *)(swap_header));
+	kunmap(page);
+	if (ret) {
+		pr_err(C "Error setting swap header\n");
+		goto fail;
+	}
+
+	rzs.disk = alloc_disk(1);
+	if (rzs.disk == NULL) {
+		pr_err(C "Error allocating disk structure\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	rzs.disk->first_minor = 0;
+	rzs.disk->fops = &ramzswap_devops;
+	/*
+	 * It is named like this to prevent distro installers
+	 * from offering ramzswap as installation target. They
+	 * seem to ignore all devices beginning with 'ram'
+	 */
+	strcpy(rzs.disk->disk_name, "ramzswap0");
+
+	rzs.disk->major = register_blkdev(0, rzs.disk->disk_name);
+	if (rzs.disk->major < 0) {
+		pr_err(C "Cannot register block device\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	rzs.disk->queue = blk_alloc_queue(GFP_KERNEL);
+	if (rzs.disk->queue == NULL) {
+		pr_err(C "Cannot register disk queue\n");
+		ret = -EFAULT;
+		goto fail;
+	}
+
+	set_capacity(rzs.disk, rzs.disksize >> SECTOR_SHIFT);
+	blk_queue_make_request(rzs.disk->queue, ramzswap_make_request);
+
+#ifdef QUEUE_FLAG_NONROT
+	/*
+	 * Assuming backing device is "rotational" type.
+	 * TODO: check if its actually "non-rotational" (SSD).
+	 *
+	 * We have ident mapping of sectors for ramzswap and
+	 * and the backing swap device. So, this queue flag
+	 * should be according to backing dev.
+	 */
+	if (!rzs.backing_swap)
+		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs.disk->queue);
+#endif
+#ifdef SWAP_DISCARD_SUPPORTED
+	blk_queue_set_discard(rzs.disk->queue, ramzswap_prepare_discard);
+#endif
+	blk_queue_logical_block_size(rzs.disk->queue, PAGE_SIZE);
+	add_disk(rzs.disk);
+
+	rzs.mem_pool = xv_create_pool();
+	if (!rzs.mem_pool) {
+		pr_err(C "Error creating memory pool\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+#if defined(STATS)
+	proc = create_proc_entry("ramzswap", S_IRUGO, NULL);
+	if (proc)
+		proc->read_proc = &proc_ramzswap_read;
+	else {
+		ret = -ENOMEM;
+		pr_warning(C "Error creating proc entry\n");
+		goto fail;
+	}
+#endif
+
+	/*
+	 * Pages that compress to size greater than this are forwarded
+	 * to physical swap disk (if backing dev is provided)
+	 */
+	if (rzs.backing_swap)
+		MAX_CPAGE_SIZE = MAX_CPAGE_SIZE_BDEV;
+	else
+		MAX_CPAGE_SIZE = MAX_CPAGE_SIZE_NOBDEV;
+
+	pr_debug(C "Max compressed page size: %u bytes\n", MAX_CPAGE_SIZE);
+
+	pr_debug(C "Initialization done!\n");
+	return 0;
+
+fail:
+	if (rzs.disk != NULL) {
+		if (rzs.disk->major > 0)
+			unregister_blkdev(rzs.disk->major, rzs.disk->disk_name);
+		del_gendisk(rzs.disk);
+	}
+
+	if (rzs.table && rzs.table[0].pagenum)
+		__free_page(pfn_to_page(rzs.table[0].pagenum));
+	kfree(rzs.compress_workmem);
+	kfree(rzs.compress_buffer);
+	vfree(rzs.table);
+	xv_destroy_pool(rzs.mem_pool);
+#if defined(STATS)
+	if (proc)
+		remove_proc_entry("ramzswap", proc->parent);
+#endif
+	pr_err(C "Initialization failed: err=%d\n", ret);
+	return ret;
+}
+
+static void __exit ramzswap_exit(void)
+{
+	size_t index, num_pages;
+	num_pages = rzs.disksize >> PAGE_SHIFT;
+
+	unregister_blkdev(rzs.disk->major, rzs.disk->disk_name);
+	del_gendisk(rzs.disk);
+
+	/* Close backing swap device (if present) */
+	if (rzs.backing_swap) {
+		set_blocksize(rzs.backing_swap, rzs.old_block_size);
+		bd_release(rzs.backing_swap);
+		filp_close(rzs.swap_file, NULL);
+	}
+
+	__free_page(pfn_to_page(rzs.table[0].pagenum));
+	kfree(rzs.compress_workmem);
+	kfree(rzs.compress_buffer);
+
+	/* Free all pages that are still in ramzswap */
+	for (index = 1; index < num_pages; index++) {
+		u32 pagenum, offset;
+
+		pagenum = rzs.table[index].pagenum;
+		offset = rzs.table[index].offset;
+
+		if (!pagenum)
+			continue;
+
+		if (unlikely(test_flag(index, RZS_UNCOMPRESSED)))
+			__free_page(pfn_to_page(pagenum));
+		else
+			xv_free(rzs.mem_pool, pagenum, offset);
+	}
+
+	vfree(rzs.table);
+	xv_destroy_pool(rzs.mem_pool);
+
+#if defined(STATS)
+	remove_proc_entry("ramzswap", proc->parent);
+#endif
+	pr_debug(C "cleanup done!\n");
+}
+
+/*
+ * This param is applicable only when there is no backing swap device.
+ * We ignore this param in case backing dev is provided since then its
+ * always equal to size of the backing swap device.
+ *
+ * This size refers to amount of (uncompressed) data it can hold.
+ * For e.g. disksize_kb=1024 means it can hold 1024kb worth of
+ * uncompressed data even if this data compresses to just, say, 100kb.
+ *
+ * Default value is used if this param is missing or 0 (if its applicable).
+ * Default: [DEFAULT_DISKSIZE_PERC_RAM]% of RAM
+ */
+module_param(disksize_kb, ulong, 0);
+MODULE_PARM_DESC(disksize_kb, "ramzswap device size (kB)");
+
+/*
+ * This param is applicable only when backing swap device is provided.
+ * This refers to limit on amount of (compressed) data it can hold in
+ * memory. Note that total amount of memory used (MemUsedTotal) can
+ * exceed this memlimit since that includes memory wastage due to
+ * fragmentation and metadata overhead.
+ *
+ * Any additional data beyond this limit is forwarded to backing
+ * swap device. TODO: allow changing memlimit at runtime.
+ *
+ * Default value is used if this param is missing or 0 (if its applicable).
+ * Default: MIN([DEFAULT_MEMLIMIT_PERC_RAM]% of RAM, Backing Device Size)
+ */
+module_param(memlimit_kb, ulong, 0);
+MODULE_PARM_DESC(memlimit_kb, "ramzswap memory limit (kB)");
+
+/*
+ * This is block device to be used as backing store for ramzswap.
+ * When pages more than memlimit_kb as swapped to ramzswap, we store
+ * any additional pages in this device. We may also move some pages
+ * from ramzswap to this device in case system is really low on
+ * memory (TODO).
+ *
+ * This device is not directly visible to kernel as a swap device
+ * (/proc/swaps will only show /dev/ramzswap0 and not this device).
+ * Managing this backing device is the job of ramzswap module.
+ */
+module_param(backing_swap, charp, 0);
+MODULE_PARM_DESC(backing_swap, "Backing swap partition");
+
+module_init(ramzswap_init);
+module_exit(ramzswap_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
+MODULE_DESCRIPTION("Compressed RAM Based Swap Device");
--- linux-ec2-2.6.32.orig/ubuntu/compcache/README
+++ linux-ec2-2.6.32/ubuntu/compcache/README
@@ -0,0 +1,45 @@
+ramzswap: Compressed RAM based swap device
+-------------------------------------------
+
+Project home: http://compcache.googlecode.com
+
+* Introduction
+This is a RAM based block device which acts as swap disk.
+Pages swapped to this device are compressed and stored in
+memory itself. See project home for use cases, performance
+numbers and lot more.
+
+* Compiling
+ - Run 'make': this will compile all modules against your kernel.
+
+ - Following kernel modules are created:
+   - xvmalloc.ko
+   - ramzswap.ko
+
+* Using
+ - Following scipts are included
+   - use_ramzswap.sh [<disksize(KB)|<memlimit(KB)>] [<backing_swap>]
+     This loads all required modules and sets up swap device.
+     NOTE: script contains detailed documentation on parameters.
+
+   - unuse_ramzswap.sh
+     Unloads all modules and turns off ramzswap swap device.
+
+* Common Problems
+ - If you get lots of compile errors, make sure you have package for
+   kernel source installed. For e.g., on Fedora its 'kernel-devel' package.
+
+ - If (un)use_ramzswap scripts fail to work, refer to wiki:
+   http://code.google.com/p/compcache/wiki/CompilingAndUsing
+
+* Notes
+ - Statistics are exported via /proc/ramzswap
+
+Please consider using Issue Tracker:
+http://code.google.com/p/compcache/issues/list
+for reporting any bugs/feature requests.
+
+Cheers!
+Nitin Gupta
+EMail: ngupta at vflare dot org
+
--- linux-ec2-2.6.32.orig/ubuntu/compcache/LGPL-2.1.txt
+++ linux-ec2-2.6.32/ubuntu/compcache/LGPL-2.1.txt
@@ -0,0 +1,510 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard.  To achieve this, non-free programs must
+be allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at least
+    three years, to give the same user the materials specified in
+    Subsection 6a, above, for a charge no more than the cost of
+    performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James
+  Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- linux-ec2-2.6.32.orig/ubuntu/compcache/compat.h
+++ linux-ec2-2.6.32/ubuntu/compcache/compat.h
@@ -0,0 +1,34 @@
+#ifndef _CCACHE_COMPAT_H_
+#define _CCACHE_COMPAT_H_
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
+#define BIO_IO_ERROR(bio)	bio_io_error(bio, PAGE_SIZE)
+#define BIO_ENDIO(bio, error)	bio_endio(bio, PAGE_SIZE, error)
+#else
+#define BIO_IO_ERROR(bio)	bio_io_error(bio)
+#define BIO_ENDIO(bio, error)	bio_endio(bio, error)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, arg...) \
+	printk(KERN_ERR fmt, ##arg)
+#endif
+
+#ifndef pr_warning
+#define pr_warning(fmt, arg...) \
+	printk(KERN_WARNING fmt, ##arg)
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, arg...) \
+	printk(KERN_ERR fmt, ##arg)
+#endif
+
+#ifdef bio_discard
+#define SWAP_DISCARD_SUPPORTED
+#endif
+
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/compcache/Changelog
+++ linux-ec2-2.6.32/ubuntu/compcache/Changelog
@@ -0,0 +1,82 @@
+version 0.5.3	(8/4/2009)
+ - Major cleanups.
+ - Rename module: compcache.ko -> ramzswap.ko
+ - Rename params: backing_dev -> backing_swap
+ - Updated use_compcache.sh script with detailed
+   documentation on parameters.
+ - LZO de/compress modules are no longer packaged
+   with compcache. Most distros now include these.
+
+version 0.5.2	(11/3/2009)
+ - Can forward incompressible pages to physical swap disk.
+ - New module params:
+ 	- memlimit_kb
+	- disksize_kb
+	- backing_dev
+   See use_compcache.sh for documentation on these params.
+ - Modified use_compcache.sh script to handle new params.
+ - Detect zero-filled pages and don't allocate any memory
+   for them.
+
+version 0.5.1	(22/1/2009)
+ - Fix crash on x86 systems with higmem (mem > ~1G).
+   This required minor changes to atomic (un)map functions (see Issue #20).
+
+version 0.5	(16/1/2009)
+ - Fix crash in case compcache init fails.
+
+version 0.5pre4	(10/1/2009)
+ - Support discarding pages for freed swap blocks (requires 2.6.28-git14).
+   This feature will be disabled if compiled for older kernel.
+ - Mark ramzswap as "solid-state" block device (requires 2.6.26-git14).
+ - Fixed incorrect stats reporting in /proc/compcache (some
+   new stats added too).
+
+version 0.5pre3	(5/1/2009)
+ - Use kmap_atomic() in xvMalloc. This fixes issue #19
+ - Remove xvMapPage() and xvUnmapMap() from xvMalloc.
+
+version 0.5pre2 (28/10/2008)
+ - Alloc full page for uncompressible pages instead
+   of returning I/O error.
+ - Warn users when using ramzswap > (2 x RAM size)
+
+version 0.5pre1 (15/10/2008)
+ - Replaced TLSF with xvMalloc memory allocator
+   http://code.google.com/p/compcache/wiki/xvMalloc
+
+version 0.4	(13/8/2008)
+ - Enable debug and stats option for compcache and tlsf by default
+   proc nodes: /proc/{tlsfinfo,compcache}
+ - Fix crash when reading /proc/tlsfinfo
+ - Lots of cleanups: clean compile on x64
+ 
+version 0.3	(17/3/2008)
+ - Fix spurious swap read failures
+ - Better swap request filtering
+ - Swap device again renamed to /dev/ramzswap0
+   This is to prevent Ubuntu installer from presenting
+   this device as possible installation target (see Issue #5)
+ - use_compcache.sh script now waits for disk node to be created
+   instead of arbitrary sleep (see Issue #6).
+ - Modified scripts: use_compcache.sh and unuse_compcache.sh
+   to now use new device name (compcache0 -> ramzswap0).
+
+version 0.2	(3/3/2008)
+ - Fixed bug on systems with highmem
+ - Better filtering-out of non-swap requests
+ - Export statistics through proc nodes:
+   - /proc/compcache
+   - /proc/tlsfinfo
+ - Debug and Statistics support for allocator
+   and compcache can now be individually turned
+   on/off by setting DEBUG, STATS to 0/1 in
+   respective header files
+ - Swap device now renamed to /dev/compcache0
+ - Added scripts: use_compcache.sh and unuse_compcache.sh
+   See README for usage
+ - Default compcache size set to 25% of RAM
+ - Lots of code cleanups
+ - Updated README
+ - Created Changelog :)
+
--- linux-ec2-2.6.32.orig/ubuntu/compcache/BOM
+++ linux-ec2-2.6.32/ubuntu/compcache/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	http://code.google.com/p/compcache/
+Current Version:	0.5.3
--- linux-ec2-2.6.32.orig/ubuntu/compcache/xvmalloc.c
+++ linux-ec2-2.6.32/ubuntu/compcache/xvmalloc.c
@@ -0,0 +1,557 @@
+/*
+ * xvmalloc.c
+ *
+ * Copyright (C) 2008, 2009  Nitin Gupta
+ *
+ * This code is released using a dual license strategy: GPL/LGPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of GNU General Public License Version 2.0
+ * Released under the terms of GNU Lesser General Public License Version 2.1
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "xvmalloc.h"
+#include "xvmalloc_int.h"
+
+static void stat_inc(u64 *value)
+{
+	*value = *value + 1;
+}
+
+static void stat_dec(u64 *value)
+{
+	*value = *value - 1;
+}
+
+static int test_flag(struct block_header *block, enum blockflags flag)
+{
+	return block->prev & BIT(flag);
+}
+
+static void set_flag(struct block_header *block, enum blockflags flag)
+{
+	block->prev |= BIT(flag);
+}
+
+static void clear_flag(struct block_header *block, enum blockflags flag)
+{
+	block->prev &= ~BIT(flag);
+}
+
+/*
+ * Given <pagenum, offset> pair, provide a derefrencable pointer.
+ * This is called from xv_malloc/xv_free path, so it needs to be fast.
+ */
+static void *get_ptr_atomic(u32 pagenum, u16 offset, enum km_type type)
+{
+	unsigned char *base;
+
+	base = kmap_atomic(pfn_to_page(pagenum), type);
+	return base + offset;
+}
+
+static void put_ptr_atomic(void *ptr, enum km_type type)
+{
+	kunmap_atomic(ptr, type);
+}
+
+static u32 get_blockprev(struct block_header *block)
+{
+	return block->prev & PREV_MASK;
+}
+
+static void set_blockprev(struct block_header *block, u16 new_offset)
+{
+	block->prev = new_offset | (block->prev & FLAGS_MASK);
+}
+
+static struct block_header *BLOCK_NEXT(struct block_header *block)
+{
+	return (struct block_header *)((char *)block + block->size + XV_ALIGN);
+}
+
+/*
+ * Get index of free list containing blocks of maximum size
+ * which is less than or equal to given size.
+ */
+static u32 get_index_for_insert(u32 size)
+{
+	if (unlikely(size > XV_MAX_ALLOC_SIZE))
+		size = XV_MAX_ALLOC_SIZE;
+	size &= ~FL_DELTA_MASK;
+	return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT;
+}
+
+/*
+ * Get index of free list having blocks of size greater than
+ * or equal to requested size.
+ */
+static u32 get_index(u32 size)
+{
+	if (unlikely(size < XV_MIN_ALLOC_SIZE))
+		size = XV_MIN_ALLOC_SIZE;
+	size = ALIGN(size, FL_DELTA);
+	return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT;
+}
+
+/*
+ * Allocate a memory page. Called when a pool needs to grow.
+ */
+static u32 xv_alloc_page(gfp_t flags)
+{
+	struct page *page;
+
+	//page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+	page = alloc_page(flags);
+	if (unlikely(!page))
+		return 0;
+
+	return page_to_pfn(page);
+}
+
+/*
+ * Called when all objects in a page are freed.
+ */
+static void xv_free_page(u32 pagenum)
+{
+	__free_page(pfn_to_page(pagenum));
+}
+
+/**
+ * find_block - find block of at least given size
+ * @pool: memory pool to search from
+ * @size: size of block required
+ * @pagenum: page no. containing required block
+ * @offset: offset within the page where block is located.
+ *
+ * Searches two level bitmap to locate block of at least
+ * the given size. If such a block is found, it provides
+ * <pagenum, offset> to identify this block and returns index
+ * in freelist where we found this block.
+ * Otherwise, returns 0 and <pagenum, offset> params are not touched.
+ */
+static u32 find_block(struct xv_pool *pool, u32 size,
+			u32 *pagenum, u32 *offset)
+{
+	ulong flbitmap, slbitmap;
+	u32 flindex, slindex, slbitstart;
+
+	/* There are no free blocks in this pool */
+	if (!pool->flbitmap)
+		return 0;
+
+	/* Get freelist index correspoding to this size */
+	slindex = get_index(size);
+	slbitmap = pool->slbitmap[slindex / BITS_PER_LONG];
+	slbitstart = slindex % BITS_PER_LONG;
+
+	/*
+	 * If freelist is not empty at this index, we found the
+	 * block - head of this list. This is approximate best-fit match.
+	 */
+	if (test_bit(slbitstart, &slbitmap)) {
+		*pagenum = pool->freelist[slindex].pagenum;
+		*offset = pool->freelist[slindex].offset;
+		return slindex;
+	}
+
+	/*
+	 * No best-fit found. Search a bit further in bitmap for a free block.
+	 * Second level bitmap consists of series of 32-bit chunks. Search
+	 * further in the chunk where we expected a best-fit, starting from
+	 * index location found above.
+	 */
+	slbitstart++;
+	slbitmap >>= slbitstart;
+
+	/* Skip this search if we were already at end of this bitmap chunk */
+	if ((slbitstart != BITS_PER_LONG) && slbitmap) {
+		slindex += __ffs(slbitmap) + 1;
+		*pagenum = pool->freelist[slindex].pagenum;
+		*offset = pool->freelist[slindex].offset;
+		return slindex;
+	}
+
+	/* Now do a full two-level bitmap search to find next nearest fit */
+	flindex = slindex / BITS_PER_LONG;
+
+	flbitmap = (pool->flbitmap) >> (flindex + 1);
+	if (!flbitmap)
+		return 0;
+
+	flindex += __ffs(flbitmap) + 1;
+	slbitmap = pool->slbitmap[flindex];
+	slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap);
+	*pagenum = pool->freelist[slindex].pagenum;
+	*offset = pool->freelist[slindex].offset;
+
+	return slindex;
+}
+
+/*
+ * Insert block at <pagenum, offset> in freelist of given pool.
+ * freelist used depends on block size.
+ */
+static void insert_block(struct xv_pool *pool, u32 pagenum, u32 offset,
+			struct block_header *block)
+{
+	u32 flindex, slindex;
+	struct block_header *nextblock;
+
+	slindex = get_index_for_insert(block->size);
+	flindex = slindex / BITS_PER_LONG;
+
+	block->link.prev_pagenum = 0;
+	block->link.prev_offset = 0;
+	block->link.next_pagenum = pool->freelist[slindex].pagenum;
+	block->link.next_offset = pool->freelist[slindex].offset;
+	pool->freelist[slindex].pagenum = pagenum;
+	pool->freelist[slindex].offset = offset;
+
+	if (block->link.next_pagenum) {
+		nextblock = get_ptr_atomic(block->link.next_pagenum,
+					block->link.next_offset, KM_USER1);
+		nextblock->link.prev_pagenum = pagenum;
+		nextblock->link.prev_offset = offset;
+		put_ptr_atomic(nextblock, KM_USER1);
+	}
+
+	__set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]);
+	__set_bit(flindex, &pool->flbitmap);
+}
+
+/*
+ * Remove block from head of freelist. Index 'slindex' identifies the freelist.
+ */
+static void remove_block_head(struct xv_pool *pool,
+			struct block_header *block, u32 slindex)
+{
+	struct block_header *tmpblock;
+	u32 flindex = slindex / BITS_PER_LONG;
+
+	pool->freelist[slindex].pagenum = block->link.next_pagenum;
+	pool->freelist[slindex].offset = block->link.next_offset;
+	block->link.prev_pagenum = 0;
+	block->link.prev_offset = 0;
+
+	if (!pool->freelist[slindex].pagenum) {
+		__clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]);
+		if (!pool->slbitmap[flindex])
+			__clear_bit(flindex, &pool->flbitmap);
+	} else {
+		/*
+		 * DEBUG ONLY: We need not reinitialize freelist head previous
+		 * pointer to 0 - we never depend on its value. But just for
+		 * sanity, lets do it.
+		 */
+		tmpblock = get_ptr_atomic(pool->freelist[slindex].pagenum,
+				pool->freelist[slindex].offset, KM_USER1);
+		tmpblock->link.prev_pagenum = 0;
+		tmpblock->link.prev_offset = 0;
+		put_ptr_atomic(tmpblock, KM_USER1);
+	}
+}
+
+/*
+ * Remove block from freelist. Index 'slindex' identifies the freelist.
+ */
+static void remove_block(struct xv_pool *pool, u32 pagenum, u32 offset,
+			struct block_header *block, u32 slindex)
+{
+	u32 flindex;
+	struct block_header *tmpblock;
+
+	if (pool->freelist[slindex].pagenum == pagenum
+	   && pool->freelist[slindex].offset == offset) {
+		remove_block_head(pool, block, slindex);
+		return;
+	}
+
+	flindex = slindex / BITS_PER_LONG;
+
+	if (block->link.prev_pagenum) {
+		tmpblock = get_ptr_atomic(block->link.prev_pagenum,
+				block->link.prev_offset, KM_USER1);
+		tmpblock->link.next_pagenum = block->link.next_pagenum;
+		tmpblock->link.next_offset = block->link.next_offset;
+		put_ptr_atomic(tmpblock, KM_USER1);
+	}
+
+	if (block->link.next_pagenum) {
+		tmpblock = get_ptr_atomic(block->link.next_pagenum,
+				block->link.next_offset, KM_USER1);
+		tmpblock->link.prev_pagenum = block->link.prev_pagenum;
+		tmpblock->link.prev_offset = block->link.prev_offset;
+		put_ptr_atomic(tmpblock, KM_USER1);
+	}
+
+	return;
+}
+
+/*
+ * Allocate a page and add it freelist of given pool.
+ */
+static int grow_pool(struct xv_pool *pool, gfp_t flags)
+{
+	u32 pagenum;
+	struct block_header *block;
+
+	pagenum = xv_alloc_page(flags);
+	if (unlikely(!pagenum))
+		return -ENOMEM;
+
+	stat_inc(&pool->total_pages);
+
+	spin_lock(&pool->lock);
+	block = get_ptr_atomic(pagenum, 0, KM_USER0);
+
+	block->size = PAGE_SIZE - XV_ALIGN;
+	set_flag(block, BLOCK_FREE);
+	clear_flag(block, PREV_FREE);
+	set_blockprev(block, 0);
+
+	insert_block(pool, pagenum, 0, block);
+
+	put_ptr_atomic(block, KM_USER0);
+	spin_unlock(&pool->lock);
+
+	return 0;
+}
+
+/*
+ * Create a memory pool. Allocates freelist, bitmaps and other
+ * per-pool metadata.
+ */
+struct xv_pool *xv_create_pool(void)
+{
+	u32 ovhd_size;
+	struct xv_pool *pool;
+
+	ovhd_size = roundup(sizeof(*pool), PAGE_SIZE);
+	pool = kzalloc(ovhd_size, GFP_KERNEL);
+	if (!pool)
+		return NULL;
+
+	spin_lock_init(&pool->lock);
+
+	return pool;
+}
+EXPORT_SYMBOL_GPL(xv_create_pool);
+
+void xv_destroy_pool(struct xv_pool *pool)
+{
+	kfree(pool);
+}
+EXPORT_SYMBOL_GPL(xv_destroy_pool);
+
+/**
+ * xv_malloc - Allocate block of given size from pool.
+ * @pool: pool to allocate from
+ * @size: size of block to allocate
+ * @pagenum: page no. that holds the object
+ * @offset: location of object within pagenum
+ *
+ * On success, <pagenum, offset> identifies block allocated
+ * and 0 is returned. On failure, <pagenum, offset> is set to
+ * 0 and -ENOMEM is returned.
+ *
+ * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail.
+ */
+int xv_malloc(struct xv_pool *pool, u32 size, u32 *pagenum, u32 *offset,
+							gfp_t flags)
+{
+	int error;
+	u32 index, tmpsize, origsize, tmpoffset;
+	struct block_header *block, *tmpblock;
+
+	*pagenum = 0;
+	*offset = 0;
+	origsize = size;
+
+	if (unlikely(!size || size > XV_MAX_ALLOC_SIZE))
+		return -ENOMEM;
+
+	size = ALIGN(size, XV_ALIGN);
+
+	spin_lock(&pool->lock);
+
+	index = find_block(pool, size, pagenum, offset);
+
+	if (!*pagenum) {
+		spin_unlock(&pool->lock);
+		if (flags & GFP_NOWAIT)
+			return -ENOMEM;
+		error = grow_pool(pool, flags);
+		if (unlikely(error))
+			return -ENOMEM;
+
+		spin_lock(&pool->lock);
+		index = find_block(pool, size, pagenum, offset);
+	}
+
+	if (!*pagenum) {
+		spin_unlock(&pool->lock);
+		return -ENOMEM;
+	}
+
+	block = get_ptr_atomic(*pagenum, *offset, KM_USER0);
+
+	remove_block_head(pool, block, index);
+
+	/* Split the block if required */
+	tmpoffset = *offset + size + XV_ALIGN;
+	tmpsize = block->size - size;
+	tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN);
+	if (tmpsize) {
+		tmpblock->size = tmpsize - XV_ALIGN;
+		set_flag(tmpblock, BLOCK_FREE);
+		clear_flag(tmpblock, PREV_FREE);
+
+		set_blockprev(tmpblock, *offset);
+		if (tmpblock->size >= XV_MIN_ALLOC_SIZE)
+			insert_block(pool, *pagenum, tmpoffset, tmpblock);
+
+		if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) {
+			tmpblock = BLOCK_NEXT(tmpblock);
+			set_blockprev(tmpblock, tmpoffset);
+		}
+	} else {
+		/* This block is exact fit */
+		if (tmpoffset != PAGE_SIZE)
+			clear_flag(tmpblock, PREV_FREE);
+	}
+
+	block->size = origsize;
+	clear_flag(block, BLOCK_FREE);
+
+	put_ptr_atomic(block, KM_USER0);
+	spin_unlock(&pool->lock);
+
+	*offset += XV_ALIGN;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xv_malloc);
+
+/*
+ * Free block identified with <pagenum, offset>
+ */
+void xv_free(struct xv_pool *pool, u32 pagenum, u32 offset)
+{
+	void *page;
+	struct block_header *block, *tmpblock;
+
+	offset -= XV_ALIGN;
+
+	spin_lock(&pool->lock);
+
+	page = get_ptr_atomic(pagenum, 0, KM_USER0);
+	block = (struct block_header *)((char *)page + offset);
+
+	/* Catch double free bugs */
+	BUG_ON(test_flag(block, BLOCK_FREE));
+
+	block->size = ALIGN(block->size, XV_ALIGN);
+
+	tmpblock = BLOCK_NEXT(block);
+	if (offset + block->size + XV_ALIGN == PAGE_SIZE)
+		tmpblock = NULL;
+
+	/* Merge next block if its free */
+	if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) {
+		/*
+		 * Blocks smaller than XV_MIN_ALLOC_SIZE
+		 * are not inserted in any free list.
+		 */
+		if (tmpblock->size >= XV_MIN_ALLOC_SIZE) {
+			remove_block(pool, pagenum,
+				    offset + block->size + XV_ALIGN, tmpblock,
+				    get_index_for_insert(tmpblock->size));
+		}
+		block->size += tmpblock->size + XV_ALIGN;
+	}
+
+	/* Merge previous block if its free */
+	if (test_flag(block, PREV_FREE)) {
+		tmpblock = (struct block_header *)((char *)(page) +
+						get_blockprev(block));
+		offset = offset - tmpblock->size - XV_ALIGN;
+
+		if (tmpblock->size >= XV_MIN_ALLOC_SIZE)
+			remove_block(pool, pagenum, offset, tmpblock,
+				    get_index_for_insert(tmpblock->size));
+
+		tmpblock->size += block->size + XV_ALIGN;
+		block = tmpblock;
+	}
+
+	/* No used objects in this page. Free it. */
+	if (block->size == PAGE_SIZE - XV_ALIGN) {
+		put_ptr_atomic(page, KM_USER0);
+		spin_unlock(&pool->lock);
+
+		xv_free_page(pagenum);
+		stat_dec(&pool->total_pages);
+		return;
+	}
+
+	set_flag(block, BLOCK_FREE);
+	if (block->size >= XV_MIN_ALLOC_SIZE)
+		insert_block(pool, pagenum, offset, block);
+
+	if (offset + block->size + XV_ALIGN != PAGE_SIZE) {
+		tmpblock = BLOCK_NEXT(block);
+		set_flag(tmpblock, PREV_FREE);
+		set_blockprev(tmpblock, offset);
+	}
+
+	put_ptr_atomic(page, KM_USER0);
+	spin_unlock(&pool->lock);
+
+	return;
+}
+EXPORT_SYMBOL_GPL(xv_free);
+
+u32 xv_get_object_size(void *obj)
+{
+	struct block_header *blk;
+
+	blk = (struct block_header *)((char *)(obj) - XV_ALIGN);
+	return blk->size;
+}
+EXPORT_SYMBOL_GPL(xv_get_object_size);
+
+/*
+ * Returns total memory used by allocator (userdata + metadata)
+ */
+u64 xv_get_total_size_bytes(struct xv_pool *pool)
+{
+	return pool->total_pages << PAGE_SHIFT;
+}
+EXPORT_SYMBOL_GPL(xv_get_total_size_bytes);
+
+static int __init xv_malloc_init(void)
+{
+	return 0;
+}
+
+static void __exit xv_malloc_exit(void)
+{
+	return;
+}
+
+module_init(xv_malloc_init);
+module_exit(xv_malloc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
+MODULE_DESCRIPTION("xvmalloc memory allocator");
--- linux-ec2-2.6.32.orig/ubuntu/compcache/xvmalloc_int.h
+++ linux-ec2-2.6.32/ubuntu/compcache/xvmalloc_int.h
@@ -0,0 +1,86 @@
+/*
+ * xvmalloc_int.c
+ *
+ * Copyright (C) 2008, 2009  Nitin Gupta
+ *
+ * This code is released using a dual license strategy: GPL/LGPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of GNU General Public License Version 2.0
+ * Released under the terms of GNU Lesser General Public License Version 2.1
+ */
+
+#ifndef _XVMALLOC_INT_H_
+#define _XVMALLOC_INT_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/* User configurable params */
+
+/* This must be greater than sizeof(LinkFree) */
+#define XV_MIN_ALLOC_SIZE       32
+#define XV_MAX_ALLOC_SIZE       (PAGE_SIZE - XV_ALIGN)
+
+/* Must be power of two */
+#define XV_ALIGN_SHIFT	2
+#define XV_ALIGN	(1 << XV_ALIGN_SHIFT)
+#define XV_ALIGN_MASK	(XV_ALIGN - 1)
+
+/* Free lists are separated by FL_DELTA bytes */
+#define FL_DELTA_SHIFT	3
+#define FL_DELTA	(1 << FL_DELTA_SHIFT)
+#define FL_DELTA_MASK	(FL_DELTA - 1)
+#define NUM_FREE_LISTS	((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \
+				/ FL_DELTA + 1)
+
+#define MAX_FLI		DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG)
+
+/* End of user params */
+
+enum blockflags {
+	BLOCK_FREE,
+	PREV_FREE,
+	__NR_BLOCKFLAGS,
+};
+
+#define FLAGS_MASK	XV_ALIGN_MASK
+#define PREV_MASK	(~FLAGS_MASK)
+
+struct freelist_entry {
+	u32 pagenum;
+	u16 offset;
+	u16 pad;
+};
+
+struct link_free {
+	u32 prev_pagenum;
+	u32 next_pagenum;
+	u16 prev_offset;
+	u16 next_offset;
+};
+
+struct block_header {
+	union {
+		/* This common header must be ALIGN bytes */
+		u8 common[XV_ALIGN];
+		struct {
+			u16 size;
+			u16 prev;
+		};
+	};
+	struct link_free link;
+};
+
+struct xv_pool {
+	ulong flbitmap;
+	ulong slbitmap[MAX_FLI];
+	spinlock_t lock;
+
+	struct freelist_entry freelist[NUM_FREE_LISTS];
+
+	/* stats */
+	u64 total_pages;
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/include/README
+++ linux-ec2-2.6.32/ubuntu/include/README
@@ -0,0 +1,4 @@
+Only use this directory for things which need to share their headers with
+other parts of the kernel or other modules in ubuntu/
+
+Otherwise, keep them local to the module directory.
--- linux-ec2-2.6.32.orig/ubuntu/include/linux/aufs_type.h
+++ linux-ec2-2.6.32/ubuntu/include/linux/aufs_type.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2005-2009 Junjiro R. Okajima
+ *
+ * This program, aufs 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AUFS_TYPE_H__
+#define __AUFS_TYPE_H__
+
+#include <linux/ioctl.h>
+#include <linux/limits.h>
+#include <linux/types.h>
+
+#define AUFS_VERSION	"2-standalone.tree-20091207"
+
+/* todo? move this to linux-2.6.19/include/magic.h */
+#define AUFS_SUPER_MAGIC	('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef CONFIG_AUFS_BRANCH_MAX_127
+typedef __s8 aufs_bindex_t;
+#define AUFS_BRANCH_MAX 127
+#else
+typedef __s16 aufs_bindex_t;
+#ifdef CONFIG_AUFS_BRANCH_MAX_511
+#define AUFS_BRANCH_MAX 511
+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
+#define AUFS_BRANCH_MAX 1023
+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
+#define AUFS_BRANCH_MAX 32767
+#endif
+#endif
+
+#ifdef __KERNEL__
+#ifndef AUFS_BRANCH_MAX
+#error unknown CONFIG_AUFS_BRANCH_MAX value
+#endif
+#endif /* __KERNEL__ */
+
+/* ---------------------------------------------------------------------- */
+
+#define AUFS_NAME		"aufs"
+#define AUFS_FSTYPE		AUFS_NAME
+
+#define AUFS_ROOT_INO		2
+#define AUFS_FIRST_INO		11
+
+#define AUFS_WH_PFX		".wh."
+#define AUFS_WH_PFX_LEN		((int)sizeof(AUFS_WH_PFX) - 1)
+#define AUFS_WH_TMP_LEN		4
+/* a limit for rmdir/rename a dir */
+#define AUFS_MAX_NAMELEN	(NAME_MAX \
+				- AUFS_WH_PFX_LEN * 2	/* doubly whiteouted */\
+				- 1			/* dot */\
+				- AUFS_WH_TMP_LEN)	/* hex */
+#define AUFS_XINO_FNAME		"." AUFS_NAME ".xino"
+#define AUFS_XINO_DEFPATH	"/tmp/" AUFS_XINO_FNAME
+#define AUFS_XINO_TRUNC_INIT	64 /* blocks */
+#define AUFS_XINO_TRUNC_STEP	4  /* blocks */
+#define AUFS_DIRWH_DEF		3
+#define AUFS_RDCACHE_DEF	10 /* seconds */
+#define AUFS_RDBLK_DEF		512 /* bytes */
+#define AUFS_RDHASH_DEF		32
+#define AUFS_WKQ_NAME		AUFS_NAME "d"
+#define AUFS_NWKQ_DEF		4
+#define AUFS_MFS_SECOND_DEF	30 /* seconds */
+#define AUFS_PLINK_WARN		100 /* number of plinks */
+
+#define AUFS_DIROPQ_NAME	AUFS_WH_PFX ".opq" /* whiteouted doubly */
+#define AUFS_WH_DIROPQ		AUFS_WH_PFX AUFS_DIROPQ_NAME
+
+#define AUFS_BASE_NAME		AUFS_WH_PFX AUFS_NAME
+#define AUFS_PLINKDIR_NAME	AUFS_WH_PFX "plnk"
+#define AUFS_ORPHDIR_NAME	AUFS_WH_PFX "orph"
+
+/* doubly whiteouted */
+#define AUFS_WH_BASE		AUFS_WH_PFX AUFS_BASE_NAME
+#define AUFS_WH_PLINKDIR	AUFS_WH_PFX AUFS_PLINKDIR_NAME
+#define AUFS_WH_ORPHDIR		AUFS_WH_PFX AUFS_ORPHDIR_NAME
+
+/* branch permission */
+#define AUFS_BRPERM_RW		"rw"
+#define AUFS_BRPERM_RO		"ro"
+#define AUFS_BRPERM_RR		"rr"
+#define AUFS_BRPERM_WH		"wh"
+#define AUFS_BRPERM_NLWH	"nolwh"
+#define AUFS_BRPERM_ROWH	AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
+#define AUFS_BRPERM_RRWH	AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
+#define AUFS_BRPERM_RWNLWH	AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
+
+/* ---------------------------------------------------------------------- */
+
+/* ioctl */
+enum {
+	AuCtl_PLINK_MAINT,
+	AuCtl_PLINK_CLEAN,
+
+	/* readdir in userspace */
+	AuCtl_RDU,
+	AuCtl_RDU_INO,
+
+	/* pathconf wrapper */
+	AuCtl_WBR_FD
+};
+
+/* borrowed from linux/include/linux/kernel.h */
+#ifndef ALIGN
+#define ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a)-1)
+#define __ALIGN_MASK(x, mask)	(((x)+(mask))&~(mask))
+#endif
+
+/* borrowed from linux/include/linux/compiler-gcc3.h */
+#ifndef __aligned
+#define __aligned(x)			__attribute__((aligned(x)))
+#define __packed			__attribute__((packed))
+#endif
+
+struct au_rdu_cookie {
+	__u64		h_pos;
+	__s16		bindex;
+	__u8		flags;
+	__u8		pad;
+	__u32		generation;
+} __aligned(8);
+
+struct au_rdu_ent {
+	__u64		ino;
+	__s16		bindex;
+	__u8		type;
+	__u8		nlen;
+	__u8		wh;
+	char		name[0];
+} __aligned(8);
+
+static inline int au_rdu_len(int nlen)
+{
+	/* include the terminating NULL */
+	return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
+		     sizeof(__u64));
+}
+
+union au_rdu_ent_ul {
+	struct au_rdu_ent __user	*e;
+	unsigned long			ul;
+};
+
+enum {
+	AufsCtlRduV_SZ,
+	AufsCtlRduV_SZ_PTR,
+	AufsCtlRduV_End
+};
+
+struct aufs_rdu {
+	/* input */
+	union {
+		__u64		sz;	/* AuCtl_RDU */
+		__u64		nent;	/* AuCtl_RDU_INO */
+	};
+	union au_rdu_ent_ul	ent;
+	__u16			verify[AufsCtlRduV_End];
+
+	/* input/output */
+	__u32			blk;
+
+	/* output */
+	union au_rdu_ent_ul	tail;
+	/* number of entries which were added in a single call */
+	__u64			rent;
+	__u8			full;
+	__u8			shwh;
+
+	struct au_rdu_cookie	cookie;
+} __aligned(8);
+
+#define AuCtlType		'A'
+#define AUFS_CTL_PLINK_MAINT	_IO(AuCtlType, AuCtl_PLINK_MAINT)
+#define AUFS_CTL_PLINK_CLEAN	_IO(AuCtlType, AuCtl_PLINK_CLEAN)
+#define AUFS_CTL_RDU		_IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
+#define AUFS_CTL_RDU_INO	_IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
+#define AUFS_CTL_WBR_FD		_IO(AuCtlType, AuCtl_WBR_FD)
+
+#endif /* __AUFS_TYPE_H__ */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_rfkill.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_rfkill.h
@@ -0,0 +1,12 @@
+#ifndef RTL_RFKILL_H
+#define RTL_RFKILL_H
+
+#ifdef CONFIG_RTL_RFKILL 
+struct net_device;
+
+bool rtl8192_rfkill_init(struct net_device *dev);
+void rtl8192_rfkill_poll(struct net_device *dev);
+void rtl8192_rfkill_exit(struct net_device *dev);
+#endif
+
+#endif /* RTL_RFKILL_H */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_pm.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_pm.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifdef CONFIG_PM_RTL
+
+#ifndef R8192E_PM_H
+#define R8192E_PM_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+#define pm_message_t u32
+#endif
+
+int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state);
+int rtl8192E_suspend (struct pci_dev *dev, pm_message_t state);
+int rtl8192E_resume (struct pci_dev *dev);
+int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable);
+
+#endif 
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_cam.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_cam.c
@@ -0,0 +1,569 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#if defined RTL8192CE
+#include "rtl8192c/r8192C_phy.h"
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#include "rtl8192c/r8192C_Efuse.h"
+#elif defined RTL8192SE  
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#include "rtl8192s/r8192S_Efuse.h"
+#else
+#include "rtl8192e/r8192E_phy.h"
+#include "rtl8192e/r8192E_phyreg.h"
+#include "rtl8192e/r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "rtl8192e/r8192E_cmdpkt.h"
+#endif
+
+extern int hwwep;
+void CamResetAllEntry(struct net_device *dev)
+{
+	u32 ulcommand = 0;
+
+	ulcommand |= BIT31|BIT30;
+	write_nic_dword(dev, RWCAM, ulcommand); 
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+void CamDeleteOneEntry(struct net_device *dev, u8 EntryNo)
+{
+	u32 ulCommand = EntryNo * CAM_CONTENT_COUNT;
+	u32 ulContent = 0;
+
+	ulCommand = ulCommand | BIT31 | BIT16;
+
+	write_nic_dword(dev,WCAMI,ulContent);
+	write_nic_dword(dev,RWCAM,ulCommand);
+}
+
+void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh)
+{
+	u32 i;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	for( i = 0 ; i<	TOTAL_CAM_ENTRY; i++) {
+
+		if (is_mesh) {
+			if(ieee->swmeshcamtable[i].bused )
+			{
+				setKey(dev,
+						i,
+						ieee->swmeshcamtable[i].key_index,
+						ieee->swmeshcamtable[i].key_type,
+						ieee->swmeshcamtable[i].macaddr,
+						ieee->swmeshcamtable[i].useDK,
+						(u32*)(&ieee->swmeshcamtable[i].key_buf[0])					
+				      );
+			}
+		} else {
+			if(ieee->swcamtable[i].bused )
+			{
+				setKey(dev,
+						i,
+						ieee->swcamtable[i].key_index,
+						ieee->swcamtable[i].key_type,
+						ieee->swcamtable[i].macaddr,
+						ieee->swcamtable[i].useDK,
+						(u32*)(&ieee->swcamtable[i].key_buf[0]));
+			}
+		}
+	}
+}
+#endif
+
+void write_cam(struct net_device *dev, u8 addr, u32 data)
+{
+	write_nic_dword(dev, WCAMI, data);
+	write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
+}
+
+u32 read_cam(struct net_device *dev, u8 addr)
+{
+	write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
+	return read_nic_dword(dev, 0xa8);
+}
+
+void EnableHWSecurityConfig8192(struct net_device *dev)
+{
+	u8 SECR_value = 0x0;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib; 
+	SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
+#ifdef _RTL8192_EXT_PATCH_
+	if ((((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->rtllib->auth_mode != 2)) 
+			&&(ieee->iw_mode != IW_MODE_MESH))
+#else
+	if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->rtllib->auth_mode != 2))
+#endif
+	{
+		SECR_value |= SCR_RxUseDK;
+		SECR_value |= SCR_TxUseDK;
+	}
+	else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
+	{
+		SECR_value |= SCR_RxUseDK;
+		SECR_value |= SCR_TxUseDK;
+	}
+
+
+	ieee->hwsec_active = 1;
+#ifdef _RTL8192_EXT_PATCH_	
+	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep )
+	{
+		ieee->hwsec_active = 0;
+		SECR_value &= ~SCR_RxDecEnable;
+		SECR_value &= ~SCR_TxUseDK;
+		SECR_value &= ~SCR_RxUseDK;
+		SECR_value &= ~SCR_TxEncEnable;
+	}
+#else
+	if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep)
+	{
+		ieee->hwsec_active = 0;
+		SECR_value &= ~SCR_RxDecEnable;
+	}
+#endif
+
+#ifdef RTL8192CE
+	write_nic_byte(dev, REG_CR+1,0x02); 
+#endif
+	RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \
+			ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);	
+	{
+		write_nic_byte(dev, SECR,  SECR_value);
+	}
+
+}
+
+void set_swcam(struct net_device *dev, 
+		u8 EntryNo,
+		u8 KeyIndex, 
+		u16 KeyType, 
+		u8 *MacAddr, 
+		u8 DefaultKey, 
+		u32 *KeyContent, 
+		u8 is_mesh)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	printk("===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",__FUNCTION__,EntryNo,KeyIndex,KeyType,is_mesh);
+	if(is_mesh){
+#ifdef _RTL8192_EXT_PATCH_	
+		ieee->swmeshcamtable[EntryNo].bused=true;
+		ieee->swmeshcamtable[EntryNo].key_index=KeyIndex;
+		ieee->swmeshcamtable[EntryNo].key_type=KeyType;
+		memcpy(ieee->swmeshcamtable[EntryNo].macaddr,MacAddr,6);
+		ieee->swmeshcamtable[EntryNo].useDK=DefaultKey;
+		memcpy(ieee->swmeshcamtable[EntryNo].key_buf,(u8*)KeyContent,16);
+#endif	
+	}
+	else
+	{
+		ieee->swcamtable[EntryNo].bused=true;
+		ieee->swcamtable[EntryNo].key_index=KeyIndex;
+		ieee->swcamtable[EntryNo].key_type=KeyType;
+		memcpy(ieee->swcamtable[EntryNo].macaddr,MacAddr,6);
+		ieee->swcamtable[EntryNo].useDK=DefaultKey;
+		memcpy(ieee->swcamtable[EntryNo].key_buf,(u8*)KeyContent,16);
+	}
+}
+#ifdef _RTL8192_EXT_PATCH_	
+void reset_IFswcam(struct net_device *dev, u8 is_mesh)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	if(is_mesh){
+		memset(ieee->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32);
+	}
+	else{
+		memset(ieee->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+	}
+}
+#endif	
+void setKey(struct net_device *dev, 
+		u8 EntryNo,
+		u8 KeyIndex, 
+		u16 KeyType, 
+		u8 *MacAddr, 
+		u8 DefaultKey, 
+		u32 *KeyContent )
+{
+	u32 TargetCommand = 0;
+	u32 TargetContent = 0;
+	u16 usConfig = 0;
+	u8 i;
+#ifdef ENABLE_IPS
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	RT_RF_POWER_STATE	rtState;
+	rtState = priv->rtllib->eRFPowerState;
+	if(priv->rtllib->PowerSaveControl.bInactivePs){ 
+		if(rtState == eRfOff){
+			if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+			{
+				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+				return ;
+			}
+			else{
+				down(&priv->rtllib->ips_sem);
+				IPSLeave(dev);
+				up(&priv->rtllib->ips_sem);			}
+		}
+	}
+	priv->rtllib->is_set_key = true;
+#endif
+	if (EntryNo >= TOTAL_CAM_ENTRY)
+		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
+
+	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+
+	if (DefaultKey)
+		usConfig |= BIT15 | (KeyType<<2);
+	else
+		usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
+
+
+	for(i=0 ; i<CAM_CONTENT_COUNT; i++){
+		TargetCommand  = i+CAM_CONTENT_COUNT*EntryNo;
+		TargetCommand |= BIT31|BIT16;
+
+		if(i==0){
+			TargetContent = (u32)(*(MacAddr+0)) << 16|
+				(u32)(*(MacAddr+1)) << 24|
+				(u32)usConfig;
+
+			write_nic_dword(dev, WCAMI, TargetContent); 
+			write_nic_dword(dev, RWCAM, TargetCommand);
+		}
+		else if(i==1){
+			TargetContent = (u32)(*(MacAddr+2)) 	 |
+				(u32)(*(MacAddr+3)) <<  8|
+				(u32)(*(MacAddr+4)) << 16|
+				(u32)(*(MacAddr+5)) << 24;
+			write_nic_dword(dev, WCAMI, TargetContent); 
+			write_nic_dword(dev, RWCAM, TargetCommand);
+		}
+		else {	
+			if(KeyContent != NULL)
+			{
+				write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) ); 
+				write_nic_dword(dev, RWCAM, TargetCommand);
+			}
+		}
+	}
+	RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig);
+}
+#if 0
+void CamPrintDbgReg(struct net_device* dev)
+{
+	unsigned long rvalue;
+	unsigned char ucValue;
+	write_nic_dword(dev, DCAM, 0x80000000);
+	msleep(40);
+	rvalue = read_nic_dword(dev, DCAM);	
+	RT_TRACE(COMP_SEC, " TX CAM=%8lX ",rvalue);
+	if((rvalue & 0x40000000) != 0x4000000) 
+		RT_TRACE(COMP_SEC, "-->TX Key Not Found      ");
+	msleep(20);
+	write_nic_dword(dev, DCAM, 0x00000000);	
+	rvalue = read_nic_dword(dev, DCAM);	
+	RT_TRACE(COMP_SEC, "RX CAM=%8lX ",rvalue);
+	if((rvalue & 0x40000000) != 0x4000000) 
+		RT_TRACE(COMP_SEC, "-->CAM Key Not Found   ");
+	ucValue = read_nic_byte(dev, SECR);
+	RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue);
+}
+#endif
+void CAM_read_entry(struct net_device *dev, u32 iIndex)
+{
+	u32 target_command=0;
+	u32 target_content=0;
+	u8 entry_i=0;
+	u32 ulStatus;
+	s32 i=100;
+	for(entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
+	{
+		target_command= entry_i+CAM_CONTENT_COUNT*iIndex;
+		target_command= target_command | BIT31;
+
+#if 1
+		while((i--)>=0)
+		{
+			ulStatus = read_nic_dword(dev, RWCAM);
+			if(ulStatus & BIT31){
+				continue;
+			}
+			else{
+				break;
+			}
+		}
+#endif
+		write_nic_dword(dev, RWCAM, target_command);
+		RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command);
+		target_content = read_nic_dword(dev, RCAMO);
+		RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content);
+	}
+	printk("\n");
+}
+
+void CamRestoreAllEntry(	struct net_device *dev)
+{
+	u8 EntryId = 0;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8*	MacAddr = priv->rtllib->current_network.bssid;
+
+	static u8	CAM_CONST_ADDR[4][6] = {
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
+	static u8	CAM_CONST_BROAD[] = 
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+	RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
+
+
+	if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40)||
+			(priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104))
+	{
+
+		for(EntryId=0; EntryId<4; EntryId++)
+		{
+			{
+				MacAddr = CAM_CONST_ADDR[EntryId];
+				if(priv->rtllib->swcamtable[EntryId].bused )
+				{
+					setKey(dev, 
+							EntryId ,
+							EntryId,
+							priv->rtllib->pairwise_key_type,
+							MacAddr, 
+							0,
+							(u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0])					
+					      );
+				}		
+			}	
+		}	
+
+	}
+	else if(priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP)
+	{
+
+		{
+			if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+			{
+				setKey(dev, 
+						4,
+						0,
+						priv->rtllib->pairwise_key_type, 
+						(u8*)dev->dev_addr, 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[4].key_buf[0])					
+				      );
+			}	
+			else
+			{
+				setKey(dev, 
+						4,
+						0,
+						priv->rtllib->pairwise_key_type, 
+						MacAddr, 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[4].key_buf[0])					
+				      );
+			}
+
+		}
+	}
+	else if(priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP)
+	{
+
+		{
+			if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+			{
+				setKey(dev, 
+						4,
+						0,
+						priv->rtllib->pairwise_key_type,
+						(u8*)dev->dev_addr, 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[4].key_buf[0])					
+				      );
+			}
+			else
+			{
+				setKey(dev, 
+						4,
+						0,
+						priv->rtllib->pairwise_key_type,
+						MacAddr, 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[4].key_buf[0])					
+				      );
+			}			
+		}
+	}
+
+
+
+	if(priv->rtllib->group_key_type == KEY_TYPE_TKIP)
+	{
+		MacAddr = CAM_CONST_BROAD;
+		for(EntryId=1 ; EntryId<4 ; EntryId++)
+		{
+			if(priv->rtllib->swcamtable[EntryId].bused )
+			{
+				setKey(dev, 
+						EntryId, 
+						EntryId,
+						priv->rtllib->group_key_type,
+						MacAddr, 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0])					
+				      );
+			}	
+		}
+		if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+		{
+			if(priv->rtllib->swcamtable[0].bused ){
+				setKey(dev, 
+						0,
+						0,
+						priv->rtllib->group_key_type,
+						CAM_CONST_ADDR[0], 
+						0,
+						(u32*)(&priv->rtllib->swcamtable[0].key_buf[0])					
+				      );
+			}
+			else
+			{
+				RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",__FUNCTION__);
+				return;
+			}
+		}			
+	} else if(priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
+		MacAddr = CAM_CONST_BROAD;
+		for(EntryId=1; EntryId<4 ; EntryId++)
+		{
+			if(priv->rtllib->swcamtable[EntryId].bused )
+			{	
+				setKey(dev, 
+				       EntryId , 
+				       EntryId,
+				       priv->rtllib->group_key_type,
+				       MacAddr, 
+				       0,
+				       (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
+			}	
+		}
+
+		if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+			if (priv->rtllib->swcamtable[0].bused) {
+				setKey(dev, 
+					0 , 
+					0,
+					priv->rtllib->group_key_type,
+					CAM_CONST_ADDR[0], 
+					0,
+					(u32*)(&priv->rtllib->swcamtable[0].key_buf[0]));
+			} else {
+				RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n", 
+						__FUNCTION__);
+				return;
+			}
+		}
+	}
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_
+u8 rtl8192_get_free_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr)
+{
+	u32 bitmap = (ieee->HwSecCamBitMap)>>4;
+	u8 entry_idx = 0;
+	u8 i, *addr;
+
+	if ((NULL == ieee) || (NULL == sta_addr)) {
+		printk("%s: ieee or sta_addr is NULL.\n", __FUNCTION__);
+		return TOTAL_CAM_ENTRY;
+	}
+
+	/* Does STA already exist? */
+	/* CAM Index 31 is for AP */
+	for (i = 4; i < TOTAL_CAM_ENTRY-1; i++) {
+		addr = ieee->HwSecCamStaAddr[i];
+		if(memcmp(addr, sta_addr, ETH_ALEN) == 0)
+			return i;
+	}
+
+	/* Get a free CAM entry. */
+	for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY - 1; entry_idx++) {
+		if ((bitmap & BIT0) == 0) {
+			ieee->HwSecCamBitMap |= BIT0<<entry_idx;
+			memcpy(ieee->HwSecCamStaAddr[entry_idx], sta_addr, ETH_ALEN);
+			return entry_idx;
+		}
+		bitmap = bitmap >>1;
+	}
+
+	return TOTAL_CAM_ENTRY;
+}
+
+void rtl8192_del_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr)
+{
+	u32 bitmap;
+	u8 i, *addr;
+
+	if ((NULL == ieee) || (NULL == sta_addr)) {
+		printk("%s: ieee or sta_addr is NULL.\n", __FUNCTION__);
+		return;
+	}
+
+	if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\
+	     sta_addr[4]|sta_addr[5]) == 0) {
+		printk("%s: sta_addr is 00:00:00:00:00:00.\n", __FUNCTION__);
+		return;
+	}
+	
+	/* Does STA already exist? */
+	for (i = 4; i < TOTAL_CAM_ENTRY; i++) {
+		addr = ieee->HwSecCamStaAddr[i];
+		bitmap = (ieee->HwSecCamBitMap)>>i;
+		if (((bitmap & BIT0) == BIT0) && (memcmp(addr, sta_addr, ETH_ALEN) == 0)) {
+			/* Remove from HW Security CAM */	
+			CamDeleteOneEntry(ieee->dev, i);
+			memset(ieee->HwSecCamStaAddr[i], 0, ETH_ALEN);
+			ieee->HwSecCamBitMap &= ~(BIT0<<i);
+			memset(&(ieee->swmeshcamtable[i]), 0, sizeof(SW_CAM_TABLE));
+			RT_TRACE(COMP_SEC, "====>del sw entry, EntryNo:%d, MacAddr:"MAC_FMT"\n", 
+					i, MAC_ARG(sta_addr));
+		}
+	}
+	return;
+}
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_debug.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_debug.c
@@ -0,0 +1,1384 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_debug.h"
+#include "rtl_core.h"
+#ifdef RTL8192CE
+#include "rtl8192c/r8192C_phy.h"
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#include "rtl8192c/r8192C_Efuse.h"
+#elif defined RTL8192SE
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#include "rtl8192s/r8192S_Efuse.h"
+#else
+#include "rtl8192e/r8192E_phy.h" 
+#include "rtl8192e/r8192E_phyreg.h"
+#include "rtl8192e/r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "rtl8192e/r8192E_cmdpkt.h"
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+#include "../../mshclass/msh_class.h"
+#endif
+/* this is only for debugging */
+void print_buffer(u32 *buffer, int len)
+{
+	int i;
+	u8 *buf =(u8*)buffer;
+	
+	printk("ASCII BUFFER DUMP (len: %x):\n",len);
+	
+	for(i=0;i<len;i++)
+		printk("%c",buf[i]);
+		
+	printk("\nBINARY BUFFER DUMP (len: %x):\n",len);
+	
+	for(i=0;i<len;i++)
+		printk("%x",buf[i]);
+
+	printk("\n");
+}
+
+/* this is only for debug */
+void dump_eprom(struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < 0xff; i++) {
+		RT_TRACE(COMP_INIT, "EEPROM addr %x : %x", i, eprom_read(dev,i));
+	}
+}
+
+/* this is only for debug */
+void rtl8192_dump_reg(struct net_device *dev)
+{
+	int i;
+	int n;
+	int max = 0x5ff;
+
+	RT_TRACE(COMP_INIT, "Dumping NIC register map");
+
+	for (n = 0; n <= max; ) {
+		printk( "\nD: %2x> ", n);
+		for (i = 0; i < 16 && n <= max; i++, n++)
+			printk("%2x ", read_nic_byte(dev, n));
+	}
+	printk("\n");
+}
+
+#ifdef RTL8192CE
+void rtl8192ce_dump_tx_desc(tx_desc *pDesc)
+{	
+#if 0
+	RTPRINT(FTX, TX_DESC, ("DW 0 =========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("Own = %d\n", pDesc->OWN));
+	RTPRINT(FTX, TX_DESC, ("GF = %d\n", pDesc->GF));
+	RTPRINT(FTX, TX_DESC, ("LINIP = %d\n", pDesc->LINIP));
+	RTPRINT(FTX, TX_DESC, ("FS = %d\n", pDesc->FirstSeg));
+	RTPRINT(FTX, TX_DESC, ("LS = %d\n", pDesc->LastSeg));
+	RTPRINT(FTX, TX_DESC, ("Offset = %d\n", pDesc->Offset));
+	RTPRINT(FTX, TX_DESC, ("PktSize = %d\r\n", pDesc->PktSize));
+
+	RTPRINT(FTX, TX_DESC, ("DW 1 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("PKTOFFSET = %d\n", pDesc->PktOffset));
+	RTPRINT(FTX, TX_DESC, ("HTC = %d\n", pDesc->HTC));
+	RTPRINT(FTX, TX_DESC, ("SecType = %d\n", pDesc->SecType));
+	RTPRINT(FTX, TX_DESC, ("EnDescID = %d\n", pDesc->EnDescID));
+	RTPRINT(FTX, TX_DESC, ("NoACM = %d\n", pDesc->NOACM));
+	RTPRINT(FTX, TX_DESC, ("QueueSelect = %d\n", pDesc->QueueSel));
+	RTPRINT(FTX, TX_DESC, ("PIFS = %d\n", pDesc->PIFS));
+	RTPRINT(FTX, TX_DESC, ("MoreFrag = %d\n", pDesc->MoreFrag));
+	RTPRINT(FTX, TX_DESC, ("MacID = %d\r\n", pDesc->MacID));
+
+	RTPRINT(FTX, TX_DESC, ("DW 2 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("BK = %d\n", pDesc->Bk));
+	RTPRINT(FTX, TX_DESC, ("AGG_EN = %d\n", pDesc->AggEn));
+	RTPRINT(FTX, TX_DESC, ("Data Retry CNT = %d\n", pDesc->DATARC));
+	RTPRINT(FTX, TX_DESC, ("RTS Retry CNT = %d\n", pDesc->RTSRC));
+	RTPRINT(FTX, TX_DESC, ("TSFL = %d\n", pDesc->TSFL));
+	RTPRINT(FTX, TX_DESC, ("RetryLmtEn = %d\n", pDesc->RetryLmtEn));
+	RTPRINT(FTX, TX_DESC, ("DataRetryLmt = %d\r\n", pDesc->TxRetryLmt));
+
+	RTPRINT(FTX, TX_DESC, ("DW 3 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("Seq = %d\n", pDesc->Seq));
+	RTPRINT(FTX, TX_DESC, ("TailPage = %d\n", pDesc->TailPage));
+	RTPRINT(FTX, TX_DESC, ("NextHeadPage = %d\r\n", pDesc->NextHeadPage));
+
+	RTPRINT(FTX, TX_DESC, ("DW 4 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("UserRate = %d\n", pDesc->UserRate));
+	RTPRINT(FTX, TX_DESC, ("RTS STBC = %d\n", pDesc->RTSSTBC));
+	RTPRINT(FTX, TX_DESC, ("RTSSC = %d\n", pDesc->RTSSC));
+	RTPRINT(FTX, TX_DESC, ("STBC = %d\n", pDesc->STBC));
+	RTPRINT(FTX, TX_DESC, ("TXSC = %d\n", pDesc->TxSc));
+	RTPRINT(FTX, TX_DESC, ("TxBw = %d\n", pDesc->TxBW));
+	RTPRINT(FTX, TX_DESC, ("TxShort = %d\n", pDesc->TxShort));
+	RTPRINT(FTX, TX_DESC, ("RTSEn = %d\n", pDesc->RTSEn));
+	RTPRINT(FTX, TX_DESC, ("CTS2Self = %d\n", pDesc->CTS2Self));
+	RTPRINT(FTX, TX_DESC, ("RTSRateFBLmt = %d\n", pDesc->RTSRateFBLmt));
+	RTPRINT(FTX, TX_DESC, ("DisRTSFB = %d\n", pDesc->DisRTSFB));
+	RTPRINT(FTX, TX_DESC, ("RTSRate = %d\r\n", pDesc->RTSRate));
+
+	RTPRINT(FTX, TX_DESC, ("DW 5 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("TxAGC = %d\n", pDesc->TXAGCA));
+	RTPRINT(FTX, TX_DESC, ("TxAGC = %d\n", pDesc->TXAGCB));
+	RTPRINT(FTX, TX_DESC, ("DataRateFBLmt = %d\n", pDesc->TxRateFBLmt));
+	RTPRINT(FTX, TX_DESC, ("Disable Feedback = %d\n", pDesc->DisDataFB));
+	RTPRINT(FTX, TX_DESC, ("TX_Rate = %d\n", pDesc->TxRate));
+	RTPRINT(FTX, TX_DESC, ("PktID = %d\r\n", pDesc->PktID));
+
+	RTPRINT(FTX, TX_DESC, ("DW 6 ==========\r\n"));
+
+	RTPRINT(FTX, TX_DESC, ("DW 7-9 ==========\r\n"));
+	RTPRINT(FTX, TX_DESC, ("TxBufferSize = %d\r\n", pDesc->TxBufferSize));
+
+	RTPRINT(FTX, TX_DESC, ("PhyAddressLow = %08x\n", pDesc->TxBuffAddr));
+
+	RTPRINT(FTX, TX_DESC, ("NextDescAddress= %08X\n", pDesc->NextDescAddress));
+#else
+	u32* desc = (u32*)pDesc;
+	u8 i=0;
+	printk("#########################\n");	
+	for(i=0;i<=9;i++){
+		printk("#########>%x\n", desc[i]);	
+	}
+	printk("#########################\n\n");	
+#endif
+}
+#endif
+
+#ifdef RTL8192SE
+void rtl8192se_dump_tx_desc(tx_desc* pDesc)
+{	
+    printk("DW 0 =========\r\n");
+    printk("Own = %d\n", pDesc->OWN);
+    printk("GF = %d\n", pDesc->GF);
+    printk("LINIP = %d\n", pDesc->LINIP);
+    printk("FS = %d\n", pDesc->FirstSeg);
+    printk("LS = %d\n", pDesc->LastSeg);
+    printk("Offset = %d\n", pDesc->Offset);
+    printk("PktSize = %d\r\n", pDesc->PktSize);
+
+    printk("DW 1 ==========\r\n");
+    printk("HWPC = %d\n", pDesc->HWPC);
+    printk("PKTOFFSET = %d\n", pDesc->PktOffset);
+    printk("WDS = %d\n", pDesc->WDS);
+    printk("HTC = %d\n", pDesc->HTC);
+    printk("SecType = %d\n", pDesc->SecType);
+    printk("EnDescID = %d\n", pDesc->EnDescID);
+    printk("PktType = %d\n", pDesc->PktType);
+    printk("OUI = %d\n", pDesc->OUI);
+    printk("SecKeyId = %d\n", pDesc->KeyID);
+    printk("NonQos = %d\n", pDesc->NonQos);
+    printk("NoACM = %d\n", pDesc->NoACM);
+    printk("AckPolicy = %d\n", pDesc->AckPolicy);
+    printk("QueueSelect = %d\n", pDesc->QueueSel);
+    printk("PIFS = %d\n", pDesc->PIFS);
+    printk("MoreFrag = %d\n", pDesc->MoreFrag);
+    printk("MoreData = %d\n", pDesc->MoreData);
+    printk("MacID = %d\r\n", pDesc->MacID);
+
+    printk("DW 2 ==========\r\n");
+    printk("OwnMAC = %d\n", pDesc->OwnMAC);
+    printk("BK = %d\n", pDesc->BK);
+    printk("AGG_EN = %d\n", pDesc->AggEn);
+    printk("Data Retry CNT = %d\n", pDesc->DATARC);
+    printk("RTS Retry CNT = %d\n", pDesc->RTSRC);
+    printk("TSFL = %d\n", pDesc->TSFL);
+    printk("RetryLmtEn = %d\n", pDesc->RetryLmtEn);
+    printk("DataRetryLmt = %d\r\n", pDesc->DataRetryLmt);
+
+    printk("DW 3 ==========\r\n");
+    printk("Frag = %d\n", pDesc->Frag);
+    printk("Seq = %d\n", pDesc->Seq);
+    printk("TailPage = %d\n", pDesc->TailPage);
+    printk("NextHeadPage = %d\r\n", pDesc->NextHeadPage);
+
+    printk("DW 4 ==========\r\n");
+    printk("UserRate = %d\n", pDesc->UserRate);
+    printk("RTS STBC = %d\n", pDesc->RTSSTBC);
+    printk("RTSSC = %d\n", pDesc->RTSSC);
+    printk("RTSBW = %d\n", pDesc->RTSBW);
+    printk("RTSShort = %d\n", pDesc->RTSShort);
+    printk("RTSHT = %d\n", pDesc->RTSHT);
+    printk("RD = %d\n", pDesc->RD);
+    printk("STBC = %d\n", pDesc->STBC);
+    printk("TXSC = %d\n", pDesc->TXSC);
+    printk("TxBw = %d\n", pDesc->TxBw);
+    printk("TxShort = %d\n", pDesc->TxShort);
+    printk("TXHT = %d\n", pDesc->TXHT);
+    printk("RaBRSRID = %d\n", pDesc->RaBRSRID);
+    printk("RTSEn = %d\n", pDesc->RTSEn);
+    printk("CTS2Self = %d\n", pDesc->CTS2Self);
+    printk("RTSRateFBLmt = %d\n", pDesc->RTSRateFBLmt);
+    printk("DisRTSFB = %d\n", pDesc->DisRTSFB);
+    printk("RTSRate = %d\r\n", pDesc->RTSRate);
+
+    printk("DW 5 ==========\r\n");
+    printk("TxAGC = %d\n", pDesc->TxAGC);
+    printk("DataRateFBLmt = %d\n", pDesc->DataRateFBLmt);
+    printk("Disable Feedback = %d\n", pDesc->DISFB);
+    printk("TX_Rate = %d\n", pDesc->TxRate);
+    printk("PktID = %d\r\n", pDesc->PktID);
+
+    printk("DW 6 ==========\r\n");
+    printk("TCPChkSum = %d\n", pDesc->TCPChkSum);
+    printk("IPChkSum = %d\r\n", pDesc->IPChkSum);
+
+    printk("DW 7-9 ==========\r\n");
+    printk("TCPEn = %d\n", pDesc->TCPEn);
+    printk("IPHdrOffset = %d\n", pDesc->IPHdrOffset);
+    printk("TxBufferSize = %d\r\n", pDesc->TxBufferSize);
+
+    printk("PhyAddressLow = %08x\n", pDesc->TxBuffAddr);
+
+    printk("NextDescAddress= %08X\n", pDesc->NextDescAddress);
+}
+#endif
+
+#ifdef CONFIG_RTLWIFI_DEBUGFS
+/* debugfs related stuff */
+static struct dentry *rtl_debugfs_root;
+static int rtl_dbgfs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t rtl_dbgfs_register_write(struct file *file,
+		const char __user *user_buf,
+		size_t count,
+		loff_t *ppos)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)file->private_data;
+	char buf[32];
+	int buf_size;
+	u32 type, offset;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	if (sscanf(buf, "%x,%x", &type, &offset ) == 2) {
+		priv->debug->hw_type = type;
+		priv->debug->hw_offset = offset;
+	} else {
+		priv->debug->hw_type = 0;
+		priv->debug->hw_offset = 0;
+	}
+
+	return count;
+}
+
+void  rtl_hardware_grab(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int t = 0;
+	int timeout = 20; 
+	u32 mask = RF_CHANGE_BY_HW|RF_CHANGE_BY_PS|RF_CHANGE_BY_IPS;
+
+	priv->debug->hw_holding = true;
+#ifdef ENABLE_IPS
+	rtllib_ips_leave_wq(dev);
+#endif
+	do {
+		if ((priv->rtllib->RfOffReason & mask)) {
+			msleep(100);
+			t++;
+		} else {
+			return;
+		}
+	} while (t < timeout);
+
+	return;
+}
+
+static ssize_t rtl_dbgfs_register_read(struct file *file,
+		char __user *user_buf,
+		size_t count,
+		loff_t *ppos)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)file->private_data;
+	struct net_device *dev = priv->rtllib->dev;
+	ssize_t ret = 0;
+	char buf[2048];
+	int n,i;
+	u32 len = 0;
+	u32 max = 0xff;
+	u32 page_no, path;
+
+	rtl_hardware_grab(dev);
+
+	if(!priv->debug->hw_type) {
+		page_no = (priv->debug->hw_offset > 0x0f)? 0x0f: priv->debug->hw_offset;
+#ifdef RTL8192SE 
+		if(page_no >= 0x08 ) {
+			len += snprintf(buf + len, count - len,
+					"\n#################### BB page- %x##################\n ", page_no);
+			for(n=0;n<=max;)
+			{
+				len += snprintf(buf + len, count - len, "\nD:  %2x > ",n);
+				for(i=0;i<4 && n<=max;n+=4,i++)
+					len += snprintf(buf + len, count - len,
+							"%8.8x ",rtl8192_QueryBBReg(dev,(page_no << 8|n), 
+								bMaskDWord));
+			}
+
+		} else 
+#endif		
+		{
+			len += snprintf(buf + len,count - len,
+					"\n#################### MAC page- %x##################\n ", page_no);
+			for(n=0;n<=max;) {
+				len += snprintf(buf + len, count - len, "\nD:  %2x > ",n);
+				for(i=0;i<16 && n<=max;i++,n++)
+					len += snprintf(buf + len, count - len,
+							"%2.2x ",read_nic_byte(dev,((page_no<<8)|n)));
+			}
+		}
+	} else {
+		path = (priv->debug->hw_offset < RF90_PATH_MAX)? priv->debug->hw_offset:(RF90_PATH_MAX - 1);
+		len += snprintf(buf + len, count - len,
+				"\n#################### RF-PATH-%x ##################\n ", 0x0a+path);
+		for(n=0;n<=max;) {
+			len += snprintf(buf+ len, count - len, "\nD:  %2x > ",n);
+			for(i=0;i<4 && n<=max;n+=4,i++)
+				len += snprintf(buf + len, count - len,
+					"%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)path,\
+					       	n, bMaskDWord)); 
+		}   
+	}
+
+	priv->debug->hw_holding = false;
+
+	len += snprintf(buf + len, count - len, "\n");
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	return ret;
+}
+
+static const struct file_operations rtl_register_debug = {
+	.read   = rtl_dbgfs_register_read,
+	.write  = rtl_dbgfs_register_write,
+	.open   = rtl_dbgfs_open,
+	.owner  = THIS_MODULE
+};
+
+int rtl_debug_module_init(struct r8192_priv *priv, const char *name)
+{
+	rtl_fs_debug *debug;
+	int ret = 0;
+
+	if (!rtl_debugfs_root)
+		return -ENOENT;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+	debug = kzalloc(sizeof(rtl_fs_debug), GFP_KERNEL);
+#else
+	rtl_fs_debug = kmalloc(sizeof(*rtl_fs_debug), GFP_KERNEL);
+	memset(rtl_fs_debug,0,sizeof(*rtl_fs_debug));
+#endif
+	if (!debug) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	priv->debug = debug;
+
+	debug->name = name;
+	debug->dir_drv = debugfs_create_dir(name, rtl_debugfs_root);
+	if (!debug->dir_drv ) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	debug->debug_register = debugfs_create_file("debug_register", S_IRUGO,
+			 debug->dir_drv, priv, &rtl_register_debug);
+	if(!debug->debug_register) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	return 0;
+err:
+        RT_TRACE(COMP_DBG, "Can't open the debugfs directory\n");
+        rtl_debug_module_remove(priv);
+        return ret;	
+
+}		
+
+void rtl_debug_module_remove(struct r8192_priv *priv)
+{
+	if (!priv->debug)
+		return;
+	debugfs_remove(priv->debug->debug_register);
+	debugfs_remove(priv->debug->dir_drv);
+	kfree(priv->debug);
+	priv->debug = NULL;
+}
+
+int rtl_create_debugfs_root(void)
+{       
+	rtl_debugfs_root = debugfs_create_dir(DRV_NAME, NULL);
+	if (!rtl_debugfs_root)
+		return -ENOENT;
+
+	return 0;
+}
+
+void rtl_remove_debugfs_root(void)
+{
+	debugfs_remove(rtl_debugfs_root);
+	rtl_debugfs_root = NULL;
+}
+#endif
+
+/****************************************************************************
+   -----------------------------PROCFS STUFF-------------------------
+*****************************************************************************/
+/*This part is related to PROC, which will record some statistics. */
+static struct proc_dir_entry *rtl8192_proc = NULL;
+
+static int proc_get_stats_ap(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	struct rtllib_network *target;
+	
+	int len = 0;
+
+        list_for_each_entry(target, &ieee->network_list, list) {
+
+		len += snprintf(page + len, count - len,
+                "%s ", target->ssid);
+
+		if(target->wpa_ie_len>0 || target->rsn_ie_len>0){
+	                len += snprintf(page + len, count - len,
+        	        "WPA\n");
+		}
+		else{
+                        len += snprintf(page + len, count - len,
+                        "non_WPA\n");
+                }
+		 
+        }
+	
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_registers_0(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x000;
+	
+#ifdef RTL8192SE
+	/* This dump the current register page */
+	if(!IS_BB_REG_OFFSET_92S(page0)){
+		len += snprintf(page + len, count - len,
+				"\n####################page %x##################\n ", (page0>>8));
+		for(n=0;n<=max;)
+		{
+			len += snprintf(page + len, count - len,
+					"\nD:  %2x > ",n);
+			for(i=0;i<16 && n<=max;i++,n++)
+				len += snprintf(page + len, count - len,
+						"%2.2x ",read_nic_byte(dev,(page0|n)));
+		}
+	}else
+#endif
+	{
+		len += snprintf(page + len, count - len,
+				"\n####################page %x##################\n ", (page0>>8));
+		for(n=0;n<=max;)
+		{
+			len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+			for(i=0;i<16 && n<=max;n++,i++)
+				len += snprintf(page + len, count - len,
+						"%2.2x ",read_nic_byte(dev,(page0|n)));
+		}
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_1(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x100;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len,
+				"\nD:  %2x > ",n);
+		for(i=0;i<16 && n<=max;i++,n++)
+			len += snprintf(page + len, count - len,
+					"%2.2x ",read_nic_byte(dev,(page0|n)));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_2(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x200;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len,
+				"\nD:  %2x > ",n);
+		for(i=0;i<16 && n<=max;i++,n++)
+			len += snprintf(page + len, count - len,
+					"%2.2x ",read_nic_byte(dev,(page0|n)));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_3(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x300;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len,
+				"\nD:  %2x > ",n);
+		for(i=0;i<16 && n<=max;i++,n++)
+			len += snprintf(page + len, count - len,
+					"%2.2x ",read_nic_byte(dev,(page0|n)));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_4(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x400;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len,
+				"\nD:  %2x > ",n);
+		for(i=0;i<16 && n<=max;i++,n++)
+			len += snprintf(page + len, count - len,
+					"%2.2x ",read_nic_byte(dev,(page0|n)));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_5(char *page, char **start,
+                          off_t offset, int count,
+                          int *eof, void *data)
+{
+        struct net_device *dev = data;
+
+        int len = 0;
+        int i,n,page0;
+
+        int max=0xff;
+        page0 = 0x500;
+
+        /* This dump the current register page */
+        len += snprintf(page + len, count - len,
+                        "\n####################page %x##################\n ", (page0>>8));
+        for(n=0;n<=max;)
+        {
+                len += snprintf(page + len, count - len,
+                                "\nD:  %2x > ",n);
+                for(i=0;i<16 && n<=max;i++,n++)
+                        len += snprintf(page + len, count - len,
+                                        "%2.2x ",read_nic_byte(dev,(page0|n)));
+        }
+        len += snprintf(page + len, count - len,"\n");
+        *eof = 1;
+        return len;
+
+}
+static int proc_get_registers_6(char *page, char **start,
+                          off_t offset, int count,
+                          int *eof, void *data)
+{
+        struct net_device *dev = data;
+
+        int len = 0;
+        int i,n,page0;
+
+        int max=0xff;
+        page0 = 0x600;
+
+        /* This dump the current register page */
+        len += snprintf(page + len, count - len,
+                        "\n####################page %x##################\n ", (page0>>8));
+        for(n=0;n<=max;)
+        {
+                len += snprintf(page + len, count - len,
+                                "\nD:  %2x > ",n);
+                for(i=0;i<16 && n<=max;i++,n++)
+                        len += snprintf(page + len, count - len,
+                                        "%2.2x ",read_nic_byte(dev,(page0|n)));
+        }
+        len += snprintf(page + len, count - len,"\n");
+        *eof = 1;
+        return len;
+
+}
+static int proc_get_registers_7(char *page, char **start,
+                          off_t offset, int count,
+                          int *eof, void *data)
+{
+        struct net_device *dev = data;
+
+        int len = 0;
+        int i,n,page0;
+
+        int max=0xff;
+        page0 = 0x700;
+
+        /* This dump the current register page */
+        len += snprintf(page + len, count - len,
+                        "\n####################page %x##################\n ", (page0>>8));
+        for(n=0;n<=max;)
+        {
+                len += snprintf(page + len, count - len,
+                                "\nD:  %2x > ",n);
+                for(i=0;i<16 && n<=max;i++,n++)
+                        len += snprintf(page + len, count - len,
+                                        "%2.2x ",read_nic_byte(dev,(page0|n)));
+        }
+        len += snprintf(page + len, count - len,"\n");
+        *eof = 1;
+        return len;
+
+}
+static int proc_get_registers_8(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x800;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+
+}
+static int proc_get_registers_9(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0x900;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+static int proc_get_registers_a(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0xa00;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+static int proc_get_registers_b(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0xb00;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+static int proc_get_registers_c(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0xc00;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+static int proc_get_registers_d(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0xd00;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+static int proc_get_registers_e(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n,page0;
+			
+	int max=0xff;
+	page0 = 0xe00;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n####################page %x##################\n ", (page0>>8));
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_reg_rf_a(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n;
+			
+	int max=0xff;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n#################### RF-A ##################\n ");
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A,n, bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_reg_rf_b(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n;
+			
+	int max=0xff;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n#################### RF-B ##################\n ");
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_B, n, bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_reg_rf_c(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n;
+			
+	int max=0xff;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n#################### RF-C ##################\n ");
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_C, n, bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_reg_rf_d(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	int len = 0;
+	int i,n;
+			
+	int max=0xff;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+			"\n#################### RF-D ##################\n ");
+	for(n=0;n<=max;)
+	{
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",n);
+		for(i=0;i<4 && n<=max;n+=4,i++)
+			len += snprintf(page + len, count - len,
+					"%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_D, n, bMaskDWord));
+	}
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_cam_register(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	u32 target_command=0;
+	u32 target_content=0;
+	u8 entry_i=0;
+	u32 ulStatus;
+	int len = 0;
+	int i=100, j = 0;
+
+	/* This dump the current register page */
+	len += snprintf(page + len, count - len,
+				"\n#################### SECURITY CAM ##################\n ");
+	for(j=0; j<TOTAL_CAM_ENTRY; j++)
+	{
+		if((j>6) && (j<31))
+			continue;
+		len += snprintf(page + len, count - len, "\nD:  %2x > ",j);
+	 	for(entry_i=0;entry_i<CAM_CONTENT_COUNT;entry_i++)
+	 	{
+			target_command= entry_i+CAM_CONTENT_COUNT*j;
+			target_command= target_command | BIT31;
+
+			while((i--)>=0)
+			{
+				ulStatus = read_nic_dword(dev, RWCAM);
+				if(ulStatus & BIT31){
+					continue;
+				}
+				else{
+					break;
+				}
+			}
+	  		write_nic_dword(dev, RWCAM, target_command);
+	  	 	target_content = read_nic_dword(dev, RCAMO);
+			len += snprintf(page + len, count - len,"%8.8x ",target_content);
+	 	}
+	}
+
+	len += snprintf(page + len, count - len,"\n");
+	*eof = 1;
+	return len;
+}
+
+static int proc_get_stats_tx(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	
+	int len = 0;
+	
+	len += snprintf(page + len, count - len,
+		"TX VI priority ok int: %lu\n"
+		"TX VO priority ok int: %lu\n"
+		"TX BE priority ok int: %lu\n"
+		"TX BK priority ok int: %lu\n"
+		"TX MANAGE priority ok int: %lu\n"
+		"TX BEACON priority ok int: %lu\n"
+		"TX BEACON priority error int: %lu\n"
+		"TX CMDPKT priority ok int: %lu\n"
+		"TX queue stopped?: %d\n"
+		"TX fifo overflow: %lu\n"
+		"TX total data packets %lu\n"		
+		"TX total data bytes :%lu\n",
+		priv->stats.txviokint,
+		priv->stats.txvookint,
+		priv->stats.txbeokint,
+		priv->stats.txbkokint,
+		priv->stats.txmanageokint,
+		priv->stats.txbeaconokint,
+		priv->stats.txbeaconerr,
+		priv->stats.txcmdpktokint,
+		netif_queue_stopped(dev),
+		priv->stats.txoverflow,
+		priv->rtllib->stats.tx_packets,
+		priv->rtllib->stats.tx_bytes
+
+
+		);
+			
+	*eof = 1;
+	return len;
+}		
+
+
+
+static int proc_get_stats_rx(char *page, char **start,
+			  off_t offset, int count,
+			  int *eof, void *data)
+{
+	struct net_device *dev = data;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	
+	int len = 0;
+	
+	len += snprintf(page + len, count - len,
+		"RX packets: %lu\n"
+		"RX data crc err: %lu\n"
+		"RX mgmt crc err: %lu\n"
+		"RX desc err: %lu\n"
+		"RX rx overflow error: %lu\n",
+		priv->stats.rxint,
+		priv->stats.rxdatacrcerr,
+		priv->stats.rxmgmtcrcerr,
+		priv->stats.rxrdu,
+		priv->stats.rxoverflow);
+			
+	*eof = 1;
+	return len;
+}		
+
+void rtl8192_proc_module_init(void)
+{	
+	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+	rtl8192_proc=create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
+#else
+	rtl8192_proc=create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+#endif
+}
+
+
+void rtl8192_proc_module_remove(void)
+{
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+	remove_proc_entry(DRV_NAME, proc_net);
+#else
+	remove_proc_entry(DRV_NAME, init_net.proc_net);
+#endif
+}
+
+
+void rtl8192_proc_remove_one(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	printk("dev name %s\n",dev->name);
+
+	if (priv->dir_dev) {
+		remove_proc_entry("stats-tx", priv->dir_dev);
+		remove_proc_entry("stats-rx", priv->dir_dev);
+		remove_proc_entry("stats-ap", priv->dir_dev);
+		remove_proc_entry("registers-0", priv->dir_dev);
+		remove_proc_entry("registers-1", priv->dir_dev);
+		remove_proc_entry("registers-2", priv->dir_dev);
+		remove_proc_entry("registers-3", priv->dir_dev);
+		remove_proc_entry("registers-4", priv->dir_dev);
+		remove_proc_entry("registers-5", priv->dir_dev);
+		remove_proc_entry("registers-6", priv->dir_dev);
+		remove_proc_entry("registers-7", priv->dir_dev);
+		remove_proc_entry("registers-8", priv->dir_dev);
+		remove_proc_entry("registers-9", priv->dir_dev);
+		remove_proc_entry("registers-a", priv->dir_dev);
+		remove_proc_entry("registers-b", priv->dir_dev);
+		remove_proc_entry("registers-c", priv->dir_dev);
+		remove_proc_entry("registers-d", priv->dir_dev);
+		remove_proc_entry("registers-e", priv->dir_dev);
+		remove_proc_entry("RF-A", priv->dir_dev);
+		remove_proc_entry("RF-B", priv->dir_dev);
+		remove_proc_entry("RF-C", priv->dir_dev);
+		remove_proc_entry("RF-D", priv->dir_dev);
+		remove_proc_entry("SEC-CAM", priv->dir_dev);
+#ifdef _RTL8192_EXT_PATCH_
+		remove_proc_entry("ra0", rtl8192_proc);
+#else
+		remove_proc_entry("wlan0", rtl8192_proc);
+#endif
+		priv->dir_dev = NULL;
+	}
+}
+
+
+void rtl8192_proc_init_one(struct net_device *dev)
+{
+	struct proc_dir_entry *e;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	priv->dir_dev = create_proc_entry(dev->name, 
+					  S_IFDIR | S_IRUGO | S_IXUGO, 
+					  rtl8192_proc);
+	if (!priv->dir_dev) {
+		RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
+		      dev->name);
+		return;
+	}
+	e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_stats_rx, dev);
+				   
+	if (!e) {
+		RT_TRACE(COMP_ERR,"Unable to initialize "
+		      "/proc/net/rtl8192/%s/stats-rx\n",
+		      dev->name);
+	}
+	
+	
+	e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_stats_tx, dev);
+				   
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/stats-tx\n",
+		      dev->name);
+	}
+	
+	e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_stats_ap, dev);
+				   
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/stats-ap\n",
+		      dev->name);
+	}
+	
+	e = create_proc_read_entry("registers-0", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_0, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-0\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-1", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_1, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-1\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-2", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_2, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-2\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-3", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_3, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-3\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-4", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_4, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-4\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-5", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_5, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-5\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-6", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_6, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-6\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-7", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_7, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-7\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-8", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_8, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-8\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-9", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_9, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-9\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-a", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_a, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-a\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-b", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_b, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-b\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-c", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_c, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-c\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-d", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_d, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-d\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("registers-e", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_registers_e, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/registers-e\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("RF-A", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_reg_rf_a, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/RF-A\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("RF-B", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_reg_rf_b, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/RF-B\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("RF-C", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_reg_rf_c, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/RF-C\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("RF-D", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_reg_rf_d, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/RF-D\n",
+		      dev->name);
+	}
+	e = create_proc_read_entry("SEC-CAM", S_IFREG | S_IRUGO,
+				   priv->dir_dev, proc_get_cam_register, dev);
+	if (!e) {
+		RT_TRACE(COMP_ERR, "Unable to initialize "
+		      "/proc/net/rtl8192/%s/SEC-CAM\n",
+		      dev->name);
+	}
+#ifdef _RTL8192_EXT_PATCH_
+        if( priv->mshobj && priv->mshobj->ext_patch_create_proc )
+                priv->mshobj->ext_patch_create_proc(priv);
+#endif
+
+}
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_cam.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_cam.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL_CAM_H
+#define _RTL_CAM_H
+
+#include <linux/types.h>
+struct net_device;
+
+void CamResetAllEntry(struct net_device* dev);
+void EnableHWSecurityConfig8192(struct net_device *dev);
+void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent );
+void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh);
+void CamPrintDbgReg(struct net_device* dev);
+
+#ifdef _RTL8192_EXT_PATCH_
+void CamDeleteOneEntry(struct net_device *dev, u8 EntryNo);
+void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh);
+#endif
+
+u32 read_cam(struct net_device *dev, u8 addr);
+void write_cam(struct net_device *dev, u8 addr, u32 data);
+
+void CamRestoreAllEntry(struct net_device *dev);
+#ifdef _RTL8192_EXT_PATCH_
+void reset_IFswcam(struct net_device *dev, u8 is_mesh);
+void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh);
+int rtl8192_set_key_for_AP(struct rtllib_device *ieee);
+#endif
+
+void CAM_read_entry(struct net_device *dev, u32 iIndex);
+
+#ifdef _RTL8192_EXT_PATCH_
+u8 rtl8192_get_free_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr);
+void rtl8192_del_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr);
+int meshdev_set_key_for_peer(struct net_device *dev, u8 *Addr, u8 KeyIndex, u16 KeyType, u32 *KeyContent);
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_core.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_core.h
@@ -0,0 +1,1449 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef _RTL_CORE_H
+#define _RTL_CORE_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/rtnetlink.h>	
+#include <linux/wireless.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>	
+#include <linux/if_arp.h>
+#include <linux/random.h>
+#include <linux/version.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27))
+#include <asm/semaphore.h>
+#endif
+#include "rtllib/rtllib.h"
+
+#ifdef ENABLE_DOT11D
+#include "rtllib/dot11d.h"
+#endif
+
+#ifdef RTL8192SE
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_firmware.h"
+#include "rtl8192s/r8192S_hw.h"
+#elif defined RTL8190P || defined RTL8192E
+#include "rtl8192e/r8192E_firmware.h"
+#include "rtl8192e/r8192E_hw.h"
+#endif
+
+#ifdef RTL8192SE
+#include "rtl8192s/r8192S_scan.h"
+#include "rtl8192s/r8192S_dev.h"
+#include "rtl8192s/r8192S_led.h"
+#include "rtl8192s/r8192S_def.h"
+#include "rtl8192s/r8192S_mp.h"
+#elif defined RTL8190P || defined RTL8192E
+#include "rtl8192e/r8190P_def.h"
+#include "rtl8192e/r8192E_dev.h"
+#elif defined RTL8192CE
+#include "rtl8192c/r8192C_dev.h"
+#include "rtl8192c/r8192C_led.h"
+#include "rtl8192c/r8192C_def.h"
+#include "rtl8192c/r8192C_phy.h"
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_firmware.h"
+#include "rtl8192c/r8192C_hw.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#include "rtl8192c/r8192C_Efuse.h"
+#include "rtl8192c/r8192C_com.h"
+#endif
+
+#ifdef CONFIG_CFG_80211 
+#include "rtl_regd.h"
+#endif
+
+#ifdef CONFIG_RTL_RFKILL
+#include "rtl_rfkill.h"
+#endif
+
+#include "rtl_debug.h"
+#include "rtl_eeprom.h"
+#include "rtl_ps.h"
+#include "rtl_cam.h"
+
+#define DRV_COPYRIGHT  "Copyright(c) 2008 - 2010 Realsil Semiconductor Corporation"
+#define DRV_AUTHOR  "<wlanfae@realtek.com>"
+#define DRV_VERSION  "0015.0127.2010"
+
+#ifdef RTL8190P
+#define DRV_NAME "rtl819xP"
+#elif defined RTL8192E
+#define DRV_NAME "rtl819xE"
+#elif defined RTL8192SE
+#define DRV_NAME "rtl819xSE"
+#elif defined RTL8192CE
+#define DRV_NAME "rtl8192CE"
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#define RTL_PCI_DEVICE(vend, dev, cfg) \
+	.vendor = (vend), .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice =PCI_ANY_ID , \
+	.driver_data = (kernel_ulong_t)&(cfg)
+#else
+#define RTL_PCI_DEVICE(vend, dev, cfg) \
+	.vendor = (vend), .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice =PCI_ANY_ID
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	typedef void irqreturn_type; 
+#else
+	typedef irqreturn_t irqreturn_type; 
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+
+#if !defined(PCI_CAP_ID_EXP)
+#define PCI_CAP_ID_EXP			    0x10
+#endif
+#if !defined(PCI_EXP_LNKCTL)
+#define PCI_EXP_LNKCTL			    0x10
+#endif
+
+typedef int __bitwise pci_power_t; 
+#define PCI_D0		((pci_power_t __force) 0)
+#define PCI_D1		((pci_power_t __force) 1)
+#define PCI_D2		((pci_power_t __force) 2)
+#define PCI_D3hot	((pci_power_t __force) 3)
+#define PCI_D3cold	((pci_power_t __force) 4)
+#define PCI_UNKNOWN	((pci_power_t __force) 5)
+#define PCI_POWER_ERROR	((pci_power_t __force) -1)
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+	#define rtl8192_interrupt(x,y,z) rtl8192_interrupt_rsl(x,y,z)
+#else
+	#define rtl8192_interrupt(x,y,z) rtl8192_interrupt_rsl(x,y)
+#endif
+
+#define RTL_MAX_SCAN_SIZE 128 
+
+#define RTL_RATE_MAX     	30
+
+#define TOTAL_CAM_ENTRY 	32
+#define CAM_CONTENT_COUNT 	8
+
+#ifndef BIT
+#define BIT(_i)				(1<<(_i))
+#endif
+
+#define DMESG(x,a...)
+#define DMESGW(x,a...)
+#define DMESGE(x,a...)
+extern u32 rt_global_debug_component;
+#define RT_TRACE(component, x, args...) \
+do { if(rt_global_debug_component & component) \
+	printk(KERN_DEBUG DRV_NAME ":" x "\n" , \
+	       ##args);\
+}while(0);
+
+#ifdef _RTL8192_EXT_PATCH_	
+#define IS_NIC_DOWN(priv)	((!(priv)->up) && (!(priv)->mesh_up))
+#else  
+#define IS_NIC_DOWN(priv)	(!(priv)->up)
+#endif  
+
+#ifdef RTL8192CE
+#define RT_ASSERT(_Exp,Fmt)				\
+		if(!(_Exp))						\
+		{								\
+			printk("Rtl819x: ");				\
+			printk Fmt;					\
+		}
+#define		PHY_BBR				BIT0
+#define		PHY_BBW				BIT1
+#define		PHY_RFR				BIT2
+#define		PHY_RFW				BIT3
+#define		PHY_MACR				BIT4
+#define		PHY_MACW				BIT5
+#define		PHY_ALLR				BIT6
+#define		PHY_ALLW				BIT7
+#define		PHY_TXPWR				BIT8
+#define		PHY_PWRDIFF			BIT9
+/* Define different debug flag for dedicated service modules in debug flag array. */
+typedef enum tag_DBGP_Flag_Type_Definition
+{
+	FQoS				= 0,	
+	FTX					= 1,
+	FRX					= 2,	
+	FSEC				= 3,
+	FMGNT				= 4,
+	FMLME				= 5,
+	FRESOURCE			= 6,
+	FBEACON				= 7,
+	FISR				= 8,
+	FPHY				= 9,
+	FMP					= 10,
+	FEEPROM			= 11,
+	FPWR				= 12,
+	FDM					= 13,
+	FDBGCtrl			= 14,
+	FC2H				= 15,
+	FBT					= 16,
+	FINIT				= 17,
+	DBGP_TYPE_MAX
+}DBGP_FLAG_E;
+#define		INIT_EEPROM				BIT0
+#define		INIT_TxPower				BIT1
+#define		INIT_IQK					BIT2
+#define		EFUSE_READ_ALL			BIT2
+#define		EFUSE_PG					BIT1
+#define		DM_Monitor			BIT2
+#define		TX_DESC				BIT3
+#define RTPRINT(dbgtype, dbgflag, printstr)	\
+		{									\
+			if(dbgflag == TX_DESC) \
+			{								\
+				printk printstr;				\
+			}								\
+		}
+
+#define RT_PRINT_DATA(_Comp, _TitleString, _HexData, _HexDataLen)			\
+		do {\
+			if((_Comp) & rt_global_debug_component )	\
+			{									\
+				int __i;								\
+				u8*	ptr = (u8*)_HexData;				\
+				printk("Rtl819x: ");						\
+				printk(_TitleString);						\
+				for( __i=0; __i<(int)_HexDataLen; __i++ )				\
+				{								\
+					printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?"  ":" ");	\
+					if (((__i + 1) % 16) == 0)	printk("\n");			\
+				}								\
+				printk("\n");							\
+			} \
+		}while(0);			
+#endif
+                                       
+#define RTL819x_DEBUG                  
+#ifdef RTL819x_DEBUG                   
+#define assert(expr) \
+        if (!(expr)) {                                  \
+                printk( "Assertion failed! %s,%s,%s,line=%d\n", \
+                #expr,__FILE__,__FUNCTION__,__LINE__);          \
+        }
+#define RT_DEBUG_DATA(level, data, datalen)      \
+        do{ if ((rt_global_debug_component & (level)) == (level))   \
+                {       \
+                        int _i;                                  \
+                        u8* _pdata = (u8*) data;                 \
+                        printk(KERN_DEBUG DRV_NAME ": %s()\n", __FUNCTION__);   \
+                        for(_i=0; _i<(int)(datalen); _i++)                 \
+                        {                                               \
+                                printk("%2x ", _pdata[_i]);               \
+                                if ((_i+1)%16 == 0) printk("\n");        \
+                        }                               \
+                        printk("\n");                   \
+                }                                       \
+        } while (0)  
+#else
+#define assert(expr) do {} while (0)
+#define RT_DEBUG_DATA(level, data, datalen) do {} while(0)
+#endif 
+
+#ifdef _RTL8192_EXT_PATCH_
+#define IS_UNDER_11N_AES_MODE(_rtllib)  ((_rtllib->pHTInfo->bCurrentHTSupport == true) &&\
+					((_rtllib->pairwise_key_type == KEY_TYPE_CCMP) || \
+					 (_rtllib->mesh_pairwise_key_type == KEY_TYPE_CCMP)))
+#else
+#define IS_UNDER_11N_AES_MODE(_rtllib)  ((_rtllib->pHTInfo->bCurrentHTSupport == true) &&\
+					(_rtllib->pairwise_key_type == KEY_TYPE_CCMP))
+#endif
+
+#define HAL_MEMORY_MAPPED_IO_RANGE_8190PCI 	0x1000     
+#define HAL_HW_PCI_REVISION_ID_8190PCI			0x00
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192PCIE	0x4000	
+#define HAL_HW_PCI_REVISION_ID_8192PCIE		0x01
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192SE	0x4000	
+#define HAL_HW_PCI_REVISION_ID_8192SE 	0x10
+#define HAL_HW_PCI_REVISION_ID_8192CE			0x1
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192CE	0x4000	
+#define HAL_HW_PCI_REVISION_ID_8192DE			0x0
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192DE	0x4000	
+
+#define HAL_HW_PCI_8180_DEVICE_ID             		0x8180
+#define HAL_HW_PCI_8185_DEVICE_ID             		0x8185	
+#define HAL_HW_PCI_8188_DEVICE_ID             		0x8188	
+#define HAL_HW_PCI_8198_DEVICE_ID             		0x8198	
+#define HAL_HW_PCI_8190_DEVICE_ID             		0x8190	
+#define HAL_HW_PCI_8192_DEVICE_ID             		0x8192	
+#define HAL_HW_PCI_8192SE_DEVICE_ID             		0x8192	
+#define HAL_HW_PCI_8174_DEVICE_ID             		0x8174	
+#define HAL_HW_PCI_8173_DEVICE_ID             		0x8173	
+#define HAL_HW_PCI_8172_DEVICE_ID             		0x8172	
+#define HAL_HW_PCI_8171_DEVICE_ID             		0x8171	
+#define HAL_HW_PCI_0045_DEVICE_ID				0x0045	
+#define HAL_HW_PCI_0046_DEVICE_ID				0x0046	
+#define HAL_HW_PCI_0044_DEVICE_ID				0x0044	
+#define HAL_HW_PCI_0047_DEVICE_ID				0x0047	
+#define HAL_HW_PCI_700F_DEVICE_ID		   		0x700F
+#define HAL_HW_PCI_701F_DEVICE_ID		   		0x701F
+#define HAL_HW_PCI_DLINK_DEVICE_ID				0x3304
+#define HAL_HW_PCI_8192CET_DEVICE_ID             	0x8191	
+#define HAL_HW_PCI_8192CE_DEVICE_ID             		0x8178	
+#define HAL_HW_PCI_8191CE_DEVICE_ID             		0x8177	
+#define HAL_HW_PCI_8188CE_DEVICE_ID             		0x8176	
+#define HAL_HW_PCI_8192CU_DEVICE_ID             		0x8191	
+#define HAL_HW_PCI_8192DE_DEVICE_ID             		0x092D	
+#define HAL_HW_PCI_8192DU_DEVICE_ID             		0x092D	
+
+#ifdef RTL8192CE
+#define RTL819X_DEFAULT_RF_TYPE 	RF_2T2R
+#else
+#define RTL819X_DEFAULT_RF_TYPE 	RF_1T2R
+#endif
+
+#define RTLLIB_WATCH_DOG_TIME    	2000
+
+#define MAX_DEV_ADDR_SIZE		8  /* support till 64 bit bus width OS */
+#define MAX_FIRMWARE_INFORMATION_SIZE   32 
+#define MAX_802_11_HEADER_LENGTH       	(40 + MAX_FIRMWARE_INFORMATION_SIZE)
+#define ENCRYPTION_MAX_OVERHEAD		128
+#define MAX_FRAGMENT_COUNT		8
+#define MAX_TRANSMIT_BUFFER_SIZE  	(1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT) 
+
+#define scrclng				4		
+
+#define DEFAULT_FRAG_THRESHOLD 	2342U
+#define MIN_FRAG_THRESHOLD     	256U
+#define DEFAULT_BEACONINTERVAL 	0x64U
+
+#define DEFAULT_SSID 		""
+#define DEFAULT_RETRY_RTS	7
+#define DEFAULT_RETRY_DATA 	7
+#define PRISM_HDR_SIZE 		64
+
+#define	PHY_RSSI_SLID_WIN_MAX		 	100
+
+#define RTL_IOCTL_WPA_SUPPLICANT		SIOCIWFIRSTPRIV+30
+
+#define TxBBGainTableLength 		        37
+#define CCKTxBBGainTableLength 	                23
+
+#define CHANNEL_PLAN_LEN			10
+#define sCrcLng 		                4
+
+#define NIC_SEND_HANG_THRESHOLD_NORMAL		4        
+#define NIC_SEND_HANG_THRESHOLD_POWERSAVE 	8
+
+#define MAX_TX_QUEUE				9 
+
+#if defined RTL8192SE || defined RTL8192CE
+#define MAX_RX_QUEUE				2
+#else 
+#define MAX_RX_QUEUE				1
+#endif
+
+#define MAX_RX_COUNT                            64
+#define MAX_TX_QUEUE_COUNT                      9        
+
+enum RTL819x_PHY_PARAM {
+	RTL819X_PHY_MACPHY_REG		= 0,		
+	RTL819X_PHY_MACPHY_REG_PG	= 1,		
+	RTL8188C_PHY_MACREG			=2,		
+	RTL8192C_PHY_MACREG			=3,		
+	RTL819X_PHY_REG				= 4,		
+	RTL819X_PHY_REG_1T2R			= 5,		
+	RTL819X_PHY_REG_to1T1R		= 6,		
+	RTL819X_PHY_REG_to1T2R		= 7,		
+	RTL819X_PHY_REG_to2T2R		= 8,		
+	RTL819X_PHY_REG_PG			= 9,		
+	RTL819X_AGC_TAB				= 10,		
+	RTL819X_PHY_RADIO_A			=11,		
+	RTL819X_PHY_RADIO_A_1T		=12,		
+	RTL819X_PHY_RADIO_A_2T		=13,		
+	RTL819X_PHY_RADIO_B			=14,		
+	RTL819X_PHY_RADIO_B_GM		=15,		
+	RTL819X_PHY_RADIO_C			=16,		
+	RTL819X_PHY_RADIO_D			=17,		
+	RTL819X_EEPROM_MAP			=18,		
+	RTL819X_EFUSE_MAP				=19,		
+};
+
+enum RTL_DEBUG {
+	COMP_TRACE		= BIT0,	 
+	COMP_DBG		= BIT1,	 
+	COMP_INIT		= BIT2,	 
+	COMP_RECV		= BIT3,	 
+	COMP_SEND		= BIT4,	 
+	COMP_CMD		= BIT5,	 
+	COMP_POWER	        = BIT6,	 
+	COMP_EPROM	        = BIT7,	 
+	COMP_SWBW		= BIT8,	 
+	COMP_SEC		= BIT9,	 
+	COMP_LPS		= BIT10, 
+	COMP_QOS		= BIT11, 
+	COMP_RATE		= BIT12, 
+	COMP_RXDESC	        = BIT13, 
+	COMP_PHY		= BIT14, 
+	COMP_DIG		= BIT15, 
+	COMP_TXAGC		= BIT16, 
+	COMP_HALDM	        = BIT17, 
+	COMP_POWER_TRACKING	= BIT18, 
+	COMP_CH		        = BIT19, 
+	COMP_RF		        = BIT20, 
+	COMP_FIRMWARE	        = BIT21, 
+	COMP_HT		        = BIT22, 
+	COMP_RESET		= BIT23,
+	COMP_CMDPKT	        = BIT24,
+	COMP_SCAN		= BIT25,
+	COMP_PS		        = BIT26,
+	COMP_DOWN		= BIT27, 
+	COMP_INTR 		= BIT28, 
+	COMP_LED		= BIT29, 
+	COMP_MLME		= BIT30, 
+	COMP_ERR		= BIT31  
+};
+
+typedef enum{
+	NIC_UNKNOWN     = 0,
+	NIC_8192E       = 1,
+	NIC_8190P       = 2,
+	NIC_8192SE      = 4,
+	NIC_8192CE      	= 5,
+	NIC_8192CU      	= 6,
+	NIC_8192DE      	= 7,
+	NIC_8192DU      	= 8,
+	} nic_t;
+
+typedef	enum _RT_EEPROM_TYPE{
+	EEPROM_93C46,
+	EEPROM_93C56,
+	EEPROM_BOOT_EFUSE,
+}RT_EEPROM_TYPE,*PRT_EEPROM_TYPE;
+
+typedef enum _tag_TxCmd_Config_Index{
+	TXCMD_TXRA_HISTORY_CTRL	        = 0xFF900000,
+	TXCMD_RESET_TX_PKT_BUFF		= 0xFF900001,
+	TXCMD_RESET_RX_PKT_BUFF		= 0xFF900002,
+	TXCMD_SET_TX_DURATION		= 0xFF900003,
+	TXCMD_SET_RX_RSSI		= 0xFF900004,
+	TXCMD_SET_TX_PWR_TRACKING	= 0xFF900005,
+	TXCMD_XXXX_CTRL,
+}DCMD_TXCMD_OP;
+
+typedef enum _RT_RF_TYPE_819xU{
+        RF_TYPE_MIN = 0,
+        RF_8225,
+        RF_8256,
+        RF_8258,
+        RF_6052=4,		
+        RF_PSEUDO_11N = 5,
+}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU;
+
+typedef enum tag_Rf_Operatetion_State
+{    
+    RF_STEP_INIT = 0,
+    RF_STEP_NORMAL,   
+    RF_STEP_MAX
+}RF_STEP_E;
+
+typedef enum _RT_STATUS{
+	RT_STATUS_SUCCESS,
+	RT_STATUS_FAILURE,
+	RT_STATUS_PENDING,
+	RT_STATUS_RESOURCE
+}RT_STATUS,*PRT_STATUS;
+
+typedef enum _RT_CUSTOMER_ID
+{
+	RT_CID_DEFAULT          = 0,
+	RT_CID_8187_ALPHA0      = 1,
+	RT_CID_8187_SERCOMM_PS  = 2,
+	RT_CID_8187_HW_LED      = 3,
+	RT_CID_8187_NETGEAR     = 4,
+	RT_CID_WHQL             = 5,
+	RT_CID_819x_CAMEO       = 6, 
+	RT_CID_819x_RUNTOP      = 7,
+	RT_CID_819x_Senao       = 8,
+	RT_CID_TOSHIBA          = 9,	
+	RT_CID_819x_Netcore     = 10,
+	RT_CID_Nettronix        = 11,
+	RT_CID_DLINK            = 12,
+	RT_CID_PRONET           = 13,
+	RT_CID_COREGA           = 14,
+	RT_CID_819x_ALPHA       = 15,
+	RT_CID_819x_Sitecom     = 16,
+	RT_CID_CCX              = 17, 
+	RT_CID_819x_Lenovo      = 18,	
+	RT_CID_819x_QMI         = 19,
+	RT_CID_819x_Edimax_Belkin = 20,		
+	RT_CID_819x_Sercomm_Belkin = 21,			
+	RT_CID_819x_CAMEO1 = 22,
+	RT_CID_819x_MSI = 23,
+	RT_CID_819x_Acer = 24,
+	RT_CID_819x_HP	=27,
+}RT_CUSTOMER_ID, *PRT_CUSTOMER_ID;
+
+typedef enum _RT_OP_MODE{
+	RT_OP_MODE_AP,
+	RT_OP_MODE_INFRASTRUCTURE,
+	RT_OP_MODE_IBSS,
+	RT_OP_MODE_NO_LINK,
+}RT_OP_MODE, *PRT_OP_MODE;
+
+typedef enum _RESET_TYPE {
+	RESET_TYPE_NORESET = 0x00,
+	RESET_TYPE_NORMAL = 0x01,
+	RESET_TYPE_SILENT = 0x02
+} RESET_TYPE;
+
+typedef enum _IC_INFERIORITY_8192S{
+	IC_INFERIORITY_A            = 0, 
+	IC_INFERIORITY_B            = 1, 
+}IC_INFERIORITY_8192S, *PIC_INFERIORITY_8192S;
+
+typedef enum _PCI_BRIDGE_VENDOR {
+	PCI_BRIDGE_VENDOR_INTEL = 0x01,
+	PCI_BRIDGE_VENDOR_ATI = 0x02,
+	PCI_BRIDGE_VENDOR_AMD = 0x04,
+	PCI_BRIDGE_VENDOR_SIS = 0x08,
+	PCI_BRIDGE_VENDOR_UNKNOWN = 0x40,
+	PCI_BRIDGE_VENDOR_MAX = 0x80
+} PCI_BRIDGE_VENDOR;
+
+typedef struct buffer
+{
+	struct buffer *next;
+	u32 *buf;
+	dma_addr_t dma;
+	
+} buffer;
+
+typedef struct rtl_reg_debug{
+        unsigned int  cmd;
+        struct {
+                unsigned char type;
+                unsigned char addr;
+                unsigned char page;
+                unsigned char length;
+        } head;
+        unsigned char buf[0xff];
+}rtl_reg_debug;
+
+typedef struct _rt_9x_tx_rate_history {
+	u32             cck[4];
+	u32             ofdm[8];
+	u32             ht_mcs[4][16];
+}rt_tx_rahis_t, *prt_tx_rahis_t;
+
+typedef	struct _RT_SMOOTH_DATA_4RF {
+	char	elements[4][100];
+	u32	index;			
+	u32	TotalNum;		
+	u32	TotalVal[4];		
+}RT_SMOOTH_DATA_4RF, *PRT_SMOOTH_DATA_4RF;
+
+#ifdef _RTL8192_EXT_PATCH_
+typedef	struct _RT_SMOOTH_DATA {
+	u32	elements[100];	
+	u32	index;			
+	u32	TotalNum;		
+	u32	TotalVal;		
+}RT_SMOOTH_DATA, *PRT_SMOOTH_DATA;
+#endif
+typedef struct Stats
+{
+	unsigned long txrdu;
+	unsigned long rxrdu;
+	unsigned long rxok;
+	unsigned long rxframgment;
+	unsigned long rxcmdpkt[4];		
+	unsigned long rxurberr;
+	unsigned long rxstaterr;
+	unsigned long rxdatacrcerr;
+	unsigned long rxmgmtcrcerr;
+	unsigned long rxcrcerrmin;
+	unsigned long rxcrcerrmid;
+	unsigned long rxcrcerrmax;
+	unsigned long received_rate_histogram[4][32];	
+	unsigned long received_preamble_GI[2][32];		
+	unsigned long	rx_AMPDUsize_histogram[5]; 
+	unsigned long rx_AMPDUnum_histogram[5]; 
+	unsigned long numpacket_matchbssid;	
+	unsigned long numpacket_toself;		
+	unsigned long num_process_phyinfo;		
+	unsigned long numqry_phystatus;
+	unsigned long numqry_phystatusCCK;
+	unsigned long numqry_phystatusHT;
+	unsigned long received_bwtype[5];              
+	unsigned long txnperr;
+	unsigned long txnpdrop;
+	unsigned long txresumed;
+	unsigned long rxoverflow;
+	unsigned long rxint;
+	unsigned long txnpokint;
+	unsigned long ints;
+	unsigned long shints;
+	unsigned long txoverflow;
+	unsigned long txlpokint;
+	unsigned long txlpdrop;
+	unsigned long txlperr;
+	unsigned long txbeokint;
+	unsigned long txbedrop;
+	unsigned long txbeerr;
+	unsigned long txbkokint;
+	unsigned long txbkdrop;
+	unsigned long txbkerr;
+	unsigned long txviokint;
+	unsigned long txvidrop;
+	unsigned long txvierr;
+	unsigned long txvookint;
+	unsigned long txvodrop;
+	unsigned long txvoerr;
+	unsigned long txbeaconokint;
+	unsigned long txbeacondrop;
+	unsigned long txbeaconerr;
+	unsigned long txmanageokint;
+	unsigned long txmanagedrop;
+	unsigned long txmanageerr;
+	unsigned long txcmdpktokint;
+	unsigned long txdatapkt;
+	unsigned long txfeedback;
+	unsigned long txfeedbackok;
+	unsigned long txoktotal;
+	unsigned long txokbytestotal;
+	unsigned long txokinperiod;
+	unsigned long txmulticast;
+	unsigned long txbytesmulticast;
+	unsigned long txbroadcast;
+	unsigned long txbytesbroadcast;
+	unsigned long txunicast;
+	unsigned long txbytesunicast;
+	unsigned long rxbytesunicast;
+	unsigned long txfeedbackfail;
+	unsigned long txerrtotal;
+	unsigned long txerrbytestotal;
+	unsigned long txerrmulticast;
+	unsigned long txerrbroadcast;
+	unsigned long txerrunicast;
+	unsigned long txretrycount;
+	unsigned long txfeedbackretry;
+	u8			last_packet_rate;
+	unsigned long slide_signal_strength[100];
+	unsigned long slide_evm[100];
+	unsigned long	slide_rssi_total;	
+	unsigned long slide_evm_total;	
+	long signal_strength; 
+	long signal_quality;
+	long last_signal_strength_inpercent;
+	long	recv_signal_power;	
+	u8 rx_rssi_percentage[4];
+	u8 rx_evm_percentage[2];
+	long rxSNRdB[4];
+	rt_tx_rahis_t txrate;
+	u32 Slide_Beacon_pwdb[100];	
+	u32 Slide_Beacon_Total;		
+	RT_SMOOTH_DATA_4RF		cck_adc_pwdb;
+	u32	CurrentShowTxate;
+#ifdef _RTL8192_EXT_PATCH_
+	u32 RssiCalculateCnt;
+	RT_SMOOTH_DATA	ui_rssi;
+	RT_SMOOTH_DATA ui_link_quality;
+#endif
+} Stats;
+
+typedef struct 	ChnlAccessSetting {
+	u16 SIFS_Timer;
+	u16 DIFS_Timer; 
+	u16 SlotTimeTimer;
+	u16 EIFS_Timer;
+	u16 CWminIndex;
+	u16 CWmaxIndex;
+}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING;
+
+typedef enum _TWO_PORT_STATUS
+{
+	TWO_PORT_STATUS__DEFAULT_ONLY,				
+	TWO_PORT_STATUS__EXTENSION_ONLY,			
+	TWO_PORT_STATUS__EXTENSION_FOLLOW_DEFAULT,	
+	TWO_PORT_STATUS__DEFAULT_G_EXTENSION_N20,	
+	TWO_PORT_STATUS__ADHOC,						
+	TWO_PORT_STATUS__WITHOUT_ANY_ASSOCIATE		
+}TWO_PORT_STATUS;
+
+typedef struct _txbbgain_struct
+{
+	long	txbb_iq_amplifygain;
+	u32	txbbgain_value;
+} txbbgain_struct, *ptxbbgain_struct;
+
+typedef struct _ccktxbbgain_struct
+{
+	u8	ccktxbb_valuearray[8];
+} ccktxbbgain_struct,*pccktxbbgain_struct;
+
+typedef struct _init_gain
+{
+	u8				xaagccore1;
+	u8				xbagccore1;
+	u8				xcagccore1;
+	u8				xdagccore1;
+	u8				cca;
+
+} init_gain, *pinit_gain;
+
+typedef struct _tx_ring{
+	u32 * desc;
+	u8 nStuckCount;
+	struct _tx_ring * next;
+}__attribute__ ((packed)) tx_ring, * ptx_ring;
+
+struct rtl8192_tx_ring {
+    tx_desc *desc;
+    dma_addr_t dma;
+    unsigned int idx;
+    unsigned int entries;
+    struct sk_buff_head queue;
+};
+
+
+
+struct rtl819x_ops{
+	nic_t nic_type;
+	void (* get_eeprom_size)(struct net_device* dev);
+	void (* init_adapter_variable)(struct net_device* dev);
+	void (* init_before_adapter_start)(struct net_device* dev);
+	bool (* initialize_adapter)(struct net_device* dev);
+	void (*link_change)(struct net_device* dev);
+	void (* tx_fill_descriptor)(struct net_device* dev, tx_desc * tx_desc, cb_desc * cb_desc, struct sk_buff *skb);
+	void (* tx_fill_cmd_descriptor)(struct net_device* dev, tx_desc_cmd * entry, cb_desc * cb_desc, struct sk_buff *skb); 
+	bool (* rx_query_status_descriptor)(struct net_device* dev, struct rtllib_rx_stats*  stats, rx_desc *pdesc, struct sk_buff* skb);
+	bool (* rx_command_packet_handler)(struct net_device *dev, struct sk_buff* skb, rx_desc *pdesc);
+	void (* stop_adapter)(struct net_device *dev, bool reset);
+#if defined RTL8192SE || defined RTL8192CE
+	void (* update_ratr_table)(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry);
+#else
+	void (* update_ratr_table)(struct net_device* dev);
+#endif
+	void (* irq_enable)(struct net_device* dev);
+	void (* irq_disable)(struct net_device* dev);
+	void (* irq_clear)(struct net_device* dev);
+	void (* rx_enable)(struct net_device* dev);
+	void (* tx_enable)(struct net_device* dev);	
+	void (* interrupt_recognized)(struct net_device *dev, u32 *p_inta, u32 *p_intb);
+	bool (* TxCheckStuckHandler)(struct net_device* dev);
+	bool (* RxCheckStuckHandler)(struct net_device* dev);
+};
+
+typedef struct r8192_priv
+{
+	struct pci_dev *pdev;
+	struct pci_dev *bridge_pdev;
+
+	u8	RegPciASPM;
+	u8	RegHwSwRfOffD3;
+	u8	RegSupportPciASPM;
+	
+	u8      rssi_level;
+	void *scan_cmd;
+
+	u8 check_roaming_cnt;
+	struct rtl819x_ops* ops;
+	bool bfirst_init;
+	bool bfirst_after_down;
+	bool initialized_at_probe;
+	LOG_INTERRUPT_8190_T InterruptLog;
+	bool bIgnoreSilentReset;
+	u32 	SilentResetRxSoltNum;
+	u32	SilentResetRxSlotIndex;
+	u32	SilentResetRxStuckEvent[MAX_SILENT_RESET_RX_SLOT_NUM];
+	RT_CUSTOMER_ID CustomerID;
+	bool	being_init_adapter;
+	bool	sw_radio_on;
+	u8	IC_Cut;
+	int irq;
+	short irq_enabled;
+	struct rtllib_device *rtllib;
+	u8 Rf_Mode;
+	nic_t card_8192; 
+	u8 card_8192_version; 
+	short enable_gpio0;
+	enum card_type {PCI,MINIPCI,CARDBUS,USB}card_type;
+	short hw_plcp_len;
+	short plcp_preamble_mode;
+	u8 ScanDelay;	
+
+	spinlock_t fw_scan_lock;
+	spinlock_t irq_lock;
+	spinlock_t irq_th_lock;
+	spinlock_t tx_lock;
+	spinlock_t rf_ps_lock;
+	spinlock_t rw_lock;
+	spinlock_t rt_h2c_lock;
+#ifdef CONFIG_ASPM_OR_D3
+	spinlock_t D3_lock;
+#endif
+
+#ifdef CONFIG_CFG_80211
+	struct ieee80211_rate rates[IEEE80211_NUM_BANDS][RTL_RATE_MAX];
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+#endif	
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+	struct semaphore mutex;
+#else
+	struct mutex mutex;
+#endif
+	bool ps_force;
+	spinlock_t rf_lock; 
+	spinlock_t ps_lock;
+
+	u32 irq_mask[2];
+	short chan;
+	u8    hwscan_bw_40;
+	short sens;
+	short max_sens;
+	u32 rx_prevlen;
+	
+	rx_desc *rx_ring[MAX_RX_QUEUE];
+	dma_addr_t rx_ring_dma[MAX_RX_QUEUE];
+	unsigned int rx_idx[MAX_RX_QUEUE];
+	struct sk_buff *rx_buf[MAX_RX_QUEUE][MAX_RX_COUNT];
+	int rxringcount;
+	u16 rxbuffersize;
+
+	struct sk_buff *rx_skb;
+	u32 *rxring;
+	u32 *rxringtail;
+	dma_addr_t rxringdma;
+	struct buffer *rxbuffer;
+	struct buffer *rxbufferhead;
+	short rx_skb_complete;
+	struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT];
+	int txringcount;
+	int txbuffsize;
+	int txfwbuffersize;
+	struct tasklet_struct irq_rx_tasklet;
+	struct tasklet_struct irq_tx_tasklet;
+	struct tasklet_struct irq_prepare_beacon_tasklet;
+
+	struct buffer *txmapbufs;
+	struct buffer *txbkpbufs;
+	struct buffer *txbepbufs;
+	struct buffer *txvipbufs;	
+	struct buffer *txvopbufs;
+	struct buffer *txcmdbufs;
+	struct buffer *txmapbufstail;
+	struct buffer *txbkpbufstail;
+	struct buffer *txbepbufstail;
+	struct buffer *txvipbufstail;      
+	struct buffer *txvopbufstail;
+	struct buffer *txcmdbufstail;
+	ptx_ring txbeaconringtail;
+	dma_addr_t txbeaconringdma;
+	ptx_ring txbeaconring;
+	int txbeaconcount;
+	struct buffer *txbeaconbufs;
+	struct buffer *txbeaconbufstail;
+	ptx_ring txmapring;
+	ptx_ring txbkpring;
+	ptx_ring txbepring;
+	ptx_ring txvipring;
+	ptx_ring txvopring;
+	ptx_ring txcmdring;
+	ptx_ring txmapringtail;
+	ptx_ring txbkpringtail;
+	ptx_ring txbepringtail;
+	ptx_ring txvipringtail;
+	ptx_ring txvopringtail;
+	ptx_ring txcmdringtail;
+	ptx_ring txmapringhead;
+	ptx_ring txbkpringhead;
+	ptx_ring txbepringhead;
+	ptx_ring txvipringhead;
+	ptx_ring txvopringhead;
+	ptx_ring txcmdringhead;
+	dma_addr_t txmapringdma;
+	dma_addr_t txbkpringdma;
+	dma_addr_t txbepringdma;
+	dma_addr_t txvipringdma;
+	dma_addr_t txvopringdma;
+	dma_addr_t txcmdringdma;
+
+	short up;
+	short up_first_time;
+#ifdef _RTL8192_EXT_PATCH_
+	short mesh_up;
+#endif
+	short crcmon; 
+	struct semaphore wx_sem;
+	struct semaphore rf_sem; 
+	u8 rf_type; 
+	RT_RF_TYPE_819xU rf_chip;
+	char nick[IW_ESSID_MAX_SIZE + 1];
+
+	short (*rf_set_sens)(struct net_device *dev,short sens);
+	u8 (*rf_set_chan)(struct net_device *dev,u8 ch);
+	void (*rf_close)(struct net_device *dev);
+	void (*rf_init)(struct net_device *dev);
+	short promisc;	
+	/*stats*/
+	struct Stats stats;
+	struct iw_statistics wstats;
+	struct proc_dir_entry *dir_dev;
+
+	struct sk_buff_head rx_queue;
+	struct sk_buff_head skb_queue;
+	work_struct_rsl qos_activate;
+	atomic_t tx_pending[0x10];
+
+	u16	ShortRetryLimit;
+	u16	LongRetryLimit;
+	u32	TransmitConfig;
+	u8	RegCWinMin;		
+#ifdef _RTL8192_EXT_PATCH_
+	u32     NumTxUnicast; 
+	u8      keepAliveLevel; 
+#endif	
+
+	u32     LastRxDescTSFHigh;
+	u32     LastRxDescTSFLow;
+
+
+	u16	EarlyRxThreshold;
+	u32	ReceiveConfig;
+	u8	AcmControl;
+
+	u8	RFProgType;
+
+	u8 retry_data;
+	u8 retry_rts;
+	u16 rts;
+
+	struct 	ChnlAccessSetting  ChannelAccessSetting;
+
+	work_struct_rsl reset_wq;
+
+#ifdef CONFIG_RTLWIFI_DEBUGFS
+	rtl_fs_debug *debug;
+#endif /* CONFIG_IWLWIFI_DEBUGFS */
+#ifdef CONFIG_RTL_RFKILL
+	bool rfkill_off;
+#endif	
+	/**********************************************************/
+	u16	basic_rate;
+	u8	short_preamble;
+	u8 	slot_time;
+	u16 SifsTime;
+	u8 RegWirelessMode;
+	prt_firmware		pFirmware;
+	rtl819x_loopback_e	LoopbackMode;
+	firmware_source_e	firmware_source;
+	u8 firmware_version;
+	u16 rf_pathmap;
+	bool AutoloadFailFlag;
+	short epromtype;
+	u16 eeprom_vid;
+	u16 eeprom_did;
+	u16 eeprom_svid;
+	u16 eeprom_smid;
+	u8  eeprom_CustomerID;
+	u16  eeprom_ChannelPlan;
+	u8 eeprom_version;
+	u8  EfuseMap[2][HWSET_MAX_SIZE_92S];
+	u16 EfuseUsedBytes;
+	u8  EfuseUsedPercentage;
+
+#ifdef EFUSE_REPG_WORKAROUND 
+	bool efuse_RePGSec1Flag;
+	u8   efuse_RePGData[8];
+#endif
+	u8 EEPROMRegulatory;
+	u8 EEPROMPwrGroup[2][3];
+	u8 EEPROMOptional;	
+	u8 ThermalValue;
+	long EntryMinUndecoratedSmoothedPWDB;
+	long EntryMaxUndecoratedSmoothedPWDB;
+	u8 DynamicTxHighPowerLvl;  
+	u8 LastDTPLvl;
+	u32 CurrentRATR0;
+	FALSE_ALARM_STATISTICS FalseAlmCnt;
+
+	bool bInformFWDriverControlDM;
+	u8 PwrGroupHT20[2][14];
+	u8 PwrGroupHT40[2][14];
+	u16 FwCmdIOMap;
+	u32 FwCmdIOParam;
+	bool bSupportASPM; 
+	u32 RfRegChnlVal[2];
+	u8 DMFlag; 
+	u8 DM_Type; 
+	u8 ShowRateMode;
+	u8 RATRTableBitmap;
+
+#if (EEPROM_OLD_FORMAT_SUPPORT == 1)
+	u8 EEPROMTxPowerLevelCCK[14];		
+	u8 EEPROMTxPowerLevelOFDM24G[14];	
+	u8 EEPROMTxPowerLevelOFDM5G[24];	
+#else
+	u8 RfCckChnlAreaTxPwr[2][3];	
+	u8 RfOfdmChnlAreaTxPwr1T[2][3];	
+	u8 RfOfdmChnlAreaTxPwr2T[2][3];	
+#endif	
+	u8 EEPROMRfACCKChnl1TxPwLevel[3];	
+	u8 EEPROMRfAOfdmChnlTxPwLevel[3];
+	u8 EEPROMRfCCCKChnl1TxPwLevel[3];	
+	u8 EEPROMRfCOfdmChnlTxPwLevel[3];
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8 EEPROMWapiSupport;
+	u8 WapiSupport;
+#endif
+	u16 EEPROMTxPowerDiff;
+	u16 EEPROMAntPwDiff;		
+	u8 EEPROMThermalMeter;
+	u8 EEPROMPwDiff;
+	u8 EEPROMCrystalCap;
+
+	u8 EEPROMBluetoothCoexist;	
+	u8 EEPROMBluetoothType;
+	u8 EEPROMBluetoothAntNum;
+	u8 EEPROMBluetoothAntIsolation;
+	u8 EEPROMBluetoothRadioShared;
+
+	
+	u8 EEPROMSupportWoWLAN;
+	u8 EEPROMBoardType;
+	u8 EEPROM_Def_Ver;
+	u8 EEPROMHT2T_TxPwr[6];			
+	u8 EEPROMTSSI_A;
+	u8 EEPROMTSSI_B;
+	u8 EEPROMTxPowerLevelCCK_V1[3];
+	u8 EEPROMLegacyHTTxPowerDiff;	
+	bool bTXPowerDataReadFromEEPORM;
+	u16 RegChannelPlan; 
+	u16 ChannelPlan;
+	bool bChnlPlanFromHW;
+	bool RegRfOff;
+	bool isRFOff;
+	bool bInPowerSaveMode;
+	u8	bHwRfOffAction;	
+	BB_REGISTER_DEFINITION_T	PHYRegDef[4];	
+	u8					pwrGroupCnt;
+#if  defined RTL8192CE
+	u32	MCSTxPowerLevelOriginalOffset[4][16];	
+#elif defined RTL8192SE 
+	u32	MCSTxPowerLevelOriginalOffset[4][7];
+#else
+	u32	MCSTxPowerLevelOriginalOffset[6];
+#endif
+	u32	CCKTxPowerLevelOriginalOffset;
+	u8	TxPowerLevelCCK[14];			
+	u8	TxPowerLevelCCK_A[14];			
+	u8 	TxPowerLevelCCK_C[14];
+	u8	TxPowerLevelOFDM24G[14];		
+	u8	TxPowerLevelOFDM5G[14];			
+	u8	TxPowerLevelOFDM24G_A[14];	
+	u8	TxPowerLevelOFDM24G_C[14];	
+	u8	LegacyHTTxPowerDiff;			
+	u8	TxPowerDiff;
+	s8	RF_C_TxPwDiff;					
+	s8	RF_B_TxPwDiff;
+	u8 	RfTxPwrLevelCck[2][14];
+	u8	RfTxPwrLevelOfdm1T[2][14];
+	u8	RfTxPwrLevelOfdm2T[2][14];
+	u8	AntennaTxPwDiff[3];				
+	u8	TxPwrHt20Diff[2][14];				
+	u8	TxPwrLegacyHtDiff[2][14];		
+#if 0
+	u8	TxPwrbandEdgeHt40[2][2];		
+	u8	TxPwrbandEdgeHt20[2][2];		
+	u8	TxPwrbandEdgeLegacyOfdm[2][2];	
+#endif
+	u8	TxPwrSafetyFlag;				
+	u8	HT2T_TxPwr_A[14]; 				
+	u8	HT2T_TxPwr_B[14]; 				
+	u8	CurrentCckTxPwrIdx;
+	u8 	CurrentOfdm24GTxPwrIdx;
+
+	u8	CrystalCap;						
+	u8	ThermalMeter[2];	
+	u8      BluetoothCoexist;
+	IC_INFERIORITY_8192S IC_Class;
+
+	u8	CckPwEnl;
+	u16	TSSI_13dBm;
+	u32 	Pwr_Track;
+	u8	CCKPresentAttentuation_20Mdefault;
+	u8	CCKPresentAttentuation_40Mdefault;
+	char	CCKPresentAttentuation_difference;
+	char	CCKPresentAttentuation;
+	u8	bCckHighPower;
+	long	undecorated_smoothed_pwdb;
+	long	undecorated_smoothed_cck_adc_pwdb[4];
+	u8	SwChnlInProgress;
+	u8 	SwChnlStage;
+	u8	SwChnlStep;
+	u8	SetBWModeInProgress;
+	HT_CHANNEL_WIDTH		CurrentChannelBW;
+
+	u8	nCur40MhzPrimeSC;	
+	u32	RfReg0Value[4];
+	u8 	NumTotalRFPath;	
+	bool 	brfpath_rxenable[4];
+	struct timer_list watch_dog_timer;	
+
+	bool	bdynamic_txpower;  
+	bool	bDynamicTxHighPower;  
+	bool	bDynamicTxLowPower;  
+	bool	bLastDTPFlag_High;
+	bool	bLastDTPFlag_Low;
+
+	bool	bstore_last_dtpflag;
+	bool	bstart_txctrl_bydtp;   
+	rate_adaptive rate_adaptive;
+	txbbgain_struct txbbgain_table[TxBBGainTableLength];
+	u8   txpower_count;
+	bool btxpower_trackingInit;
+	u8   OFDM_index;
+	u8   CCK_index;
+	u8   Record_CCK_20Mindex;
+	u8   Record_CCK_40Mindex;
+	ccktxbbgain_struct	cck_txbbgain_table[CCKTxBBGainTableLength];
+	ccktxbbgain_struct	cck_txbbgain_ch14_table[CCKTxBBGainTableLength];
+	u8 rfa_txpowertrackingindex;
+	u8 rfa_txpowertrackingindex_real;
+	u8 rfa_txpowertracking_default;
+	u8 rfc_txpowertrackingindex;
+	u8 rfc_txpowertrackingindex_real;
+	u8 rfc_txpowertracking_default;
+	bool btxpower_tracking;
+	bool bcck_in_ch14;
+
+	init_gain initgain_backup;
+	u8   DefaultInitialGain[4];
+	bool bis_any_nonbepkts;
+	bool bcurrent_turbo_EDCA;
+
+	bool SetFwCmdInProgress; 
+	u8 CurrentFwCmdIO;
+
+	u8 	MidHighPwrTHR_L1;
+	u8 	MidHighPwrTHR_L2;
+
+
+	bool	bis_cur_rdlstate;
+	struct timer_list fsync_timer;
+	bool bfsync_processing;	
+	u32 	rate_record;
+	u32 	rateCountDiffRecord;
+	u32	ContiuneDiffCount;
+	bool bswitch_fsync;
+
+	u8	framesync;
+	u32 	framesyncC34;
+	u8   	framesyncMonitor;
+	u16 	nrxAMPDU_size;
+	u8 	nrxAMPDU_aggr_num;
+
+	u32 last_rxdesc_tsf_high;
+	u32 last_rxdesc_tsf_low;
+
+	bool bHwRadioOff;
+	bool pwrdown;
+	bool blinked_ingpio;
+	bool aspm_clkreq_enable;
+	u32 pci_bridge_vendor;
+	u8 RegHostPciASPMSetting;
+	int PciBridgeASPMRegOffset;
+	u8 PciBridgeLinkCtrlReg;
+	u8 RegDevicePciASPMSetting;
+	int ASPMRegOffset;
+	int ClkReqOffset;
+	u8 LinkCtrlReg;
+
+	bool RFChangeInProgress; 
+	bool SetRFPowerStateInProgress;
+	bool bdisable_nic;
+	RT_OP_MODE OpMode;
+	u32 reset_count;
+	bool bpbc_pressed;
+	u32 txpower_checkcnt;
+	u32 txpower_tracking_callback_cnt;
+	u8 thermal_read_val[40];
+	u8 thermal_readback_index;
+	u32 ccktxpower_adjustcnt_not_ch14;
+	u32 ccktxpower_adjustcnt_ch14;
+	u8 tx_fwinfo_force_subcarriermode;
+	u8 tx_fwinfo_force_subcarrierval;
+
+	RESET_TYPE	ResetProgress;
+	bool		bForcedSilentReset;
+	bool		bDisableNormalResetCheck;
+	u16		TxCounter;
+	u16		RxCounter;
+	int		IrpPendingCount;
+	bool		bResetInProgress;
+	bool		force_reset;
+	bool		force_lps;
+	u8		InitialGainOperateType;
+#if defined RTL8192SE || defined RTL8192CE
+	LED_STRATEGY_8190	LedStrategy;  
+	LED_8190			SwLed0;
+	LED_8190			SwLed1;
+#endif
+	delayed_work_struct_rsl update_beacon_wq;
+	delayed_work_struct_rsl watch_dog_wq;    
+	delayed_work_struct_rsl txpower_tracking_wq;
+	delayed_work_struct_rsl rfpath_check_wq;
+	delayed_work_struct_rsl gpio_change_rf_wq;
+	delayed_work_struct_rsl initialgain_operate_wq;
+	delayed_work_struct_rsl check_hw_scan_wq; 
+	delayed_work_struct_rsl hw_scan_simu_wq; 
+	delayed_work_struct_rsl start_hw_scan_wq; 	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)  
+	struct workqueue_struct *priv_wq;
+#else
+	u32 *priv_wq;
+#endif
+	struct timer_list gpio_polling_timer;
+	u8     polling_timer_on;
+	bool bDriverIsGoingToUnload;
+#ifdef _RTL8192_EXT_PATCH_
+	struct mshclass			*mshobj;
+#endif
+
+	bool chan_forced;
+	bool bSingleCarrier;
+	bool RegBoard;
+	bool bCckContTx; 
+ 	bool bOfdmContTx; 
+	bool bStartContTx; 
+	u8   RegPaModel; 
+	u8   btMpCckTxPower; 
+	u8   btMpOfdmTxPower; 
+
+	u32	MptActType; 	
+	u32	MptIoOffset; 
+	u32	MptIoValue; 
+	u32	MptRfPath;
+
+	u32	MptBandWidth;			
+	u32	MptRateIndex;			
+	u8	MptChannelToSw; 		
+	u32  MptRCR;
+
+	u8	PwrDomainProtect;	
+	u8	H2CTxCmdSeq; 
+
+#ifdef RTL8192CE
+	u8	EEPROMTSSI[2];
+	u8	EEPROMPwrLimitHT20[3];
+	u8	EEPROMPwrLimitHT40[3];
+	u8	EEPROMChnlAreaTxPwrCCK[2][3];	
+	u8	EEPROMChnlAreaTxPwrHT40_1S[2][3];	
+	u8	EEPROMChnlAreaTxPwrHT40_2SDiff[2][3];	
+	u8	TxPwrLevelCck[2][14];
+	u8	TxPwrLevelHT40_1S[2][14];		
+	u8	TxPwrLevelHT40_2S[2][14];		
+	bool	bRPDownloadFinished;
+	bool	bH2CSetInProgress;
+	u8	SetIOInProgress;
+	IO_TYPE	CurrentIOType;
+	BT_COEXIST_STR	bt_coexist;	
+	
+	u8	CurFwCmdRegSet;
+	u8	LastHMEBoxNum;
+#endif
+	bool	bDMInitialGainEnable;
+        bool    MutualAuthenticationFail;
+	bool	bDisableFrameBursting;
+	bool	bLedOpenDrain; 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+	u32	pci_state;
+#endif
+}r8192_priv;
+
+
+#ifdef _RTL8192_EXT_PATCH_
+struct meshdev_priv {
+	struct net_device_stats stats;
+	struct rtllib_device *rtllib;
+	struct r8192_priv * priv;
+};
+#endif
+
+extern const struct ethtool_ops rtl819x_ethtool_ops;
+
+#ifdef RTL8192CE
+#define Rtl819XFwImageArray				Rtl8192CEFwImgArray
+#define Rtl819XMAC_Array					Rtl8192CEMAC_2T_Array
+#define Rtl819XAGCTAB_2TArray			Rtl8192CEAGCTAB_2TArray
+#define Rtl819XAGCTAB_1TArray			Rtl8192CEAGCTAB_1TArray
+#define Rtl819XPHY_REG_2TArray			Rtl8192CEPHY_REG_2TArray			
+#define Rtl819XPHY_REG_1TArray			Rtl8192CEPHY_REG_1TArray
+#define Rtl819XRadioA_2TArray				Rtl8192CERadioA_2TArray
+#define Rtl819XRadioA_1TArray				Rtl8192CERadioA_1TArray
+#define Rtl819XRadioB_2TArray				Rtl8192CERadioB_2TArray
+#define Rtl819XRadioB_1TArray				Rtl8192CERadioB_1TArray
+#define Rtl819XMAC_Array					Rtl8192CEMAC_2T_Array
+#define Rtl819XPHY_REG_Array_PG 			Rtl8192CEPHY_REG_Array_PG
+#endif
+
+bool init_firmware(struct net_device *dev);
+void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
+short rtl8192_tx(struct net_device *dev, struct sk_buff* skb);
+
+u8 read_nic_io_byte(struct net_device *dev, int x);
+u32 read_nic_io_dword(struct net_device *dev, int x);
+u16 read_nic_io_word(struct net_device *dev, int x) ;
+void write_nic_io_byte(struct net_device *dev, int x,u8 y);
+void write_nic_io_word(struct net_device *dev, int x,u16 y);
+void write_nic_io_dword(struct net_device *dev, int x,u32 y);
+
+u8 read_nic_byte(struct net_device *dev, int x);
+u32 read_nic_dword(struct net_device *dev, int x);
+u16 read_nic_word(struct net_device *dev, int x) ;
+void write_nic_byte(struct net_device *dev, int x,u8 y);
+void write_nic_word(struct net_device *dev, int x,u16 y);
+void write_nic_dword(struct net_device *dev, int x,u32 y);
+
+void force_pci_posting(struct net_device *dev);
+
+void rtl8192_rx_enable(struct net_device *);
+void rtl8192_tx_enable(struct net_device *);
+
+void rtl8192_disassociate(struct net_device *dev);
+void rtl8185_set_rf_pins_enable(struct net_device *dev,u32 a);
+
+int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev);
+void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate);
+void rtl8192_data_hard_stop(struct net_device *dev);
+void rtl8192_data_hard_resume(struct net_device *dev);
+void rtl8192_restart(void *data);
+void rtl819x_watchdog_wqcallback(void *data);
+void rtl8192_hw_sleep_wq (void *data);
+void watch_dog_timer_callback(unsigned long data);
+void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
+void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
+int rtl8192_down(struct net_device *dev,bool shutdownrf);
+int rtl8192_up(struct net_device *dev);
+void rtl8192_commit(struct net_device *dev);
+void rtl8192_set_chan(struct net_device *dev,short ch);
+
+void check_rfctrl_gpio_timer(unsigned long data);
+
+
+extern void firmware_init_param(struct net_device *dev);
+extern bool cmpk_message_handle_tx(struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len);
+void rtl8192_hw_wakeup_wq(void *data);
+
+irqreturn_type rtl8192_interrupt(int irq, void *netdev, struct pt_regs *regs);
+
+short rtl8192_pci_initdescring(struct net_device *dev);
+
+void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
+
+int _rtl8192_up(struct net_device *dev,bool is_silent_reset);
+
+short rtl8192_is_tx_queue_empty(struct net_device *dev);
+#ifdef RTL8192SE
+void rtl8192_irq_disable(struct net_device *dev);
+void GetHwReg8192SE(struct net_device *dev,u8 variable,u8* val);
+void SetHwReg8192SE(struct net_device *dev,u8 variable,u8* val);
+void SwLedOn(struct net_device *dev , PLED_8190 pLed);
+void SwLedOff(struct net_device *dev, PLED_8190 pLed);
+void Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info  *pEntry);
+void SetBeaconRelatedRegisters8192SE(struct net_device *dev);
+
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
+void rtl8192se_check_tsf_wq(struct work_struct * work);
+void rtl8192se_update_assoc_sta_info_wq(struct work_struct * work);
+#else
+void rtl8192se_check_tsf_wq(struct net_device *dev);
+void rtl8192se_update_assoc_sta_info_wq(struct net_device *dev);
+#endif
+#endif
+
+void check_rfctrl_gpio_timer(unsigned long data);
+u8 HalSetSysClk8192SE(struct net_device *dev, u8 Data);
+void gen_RefreshLedState(struct net_device *dev);
+#ifdef _RTL8192_EXT_PATCH_
+extern int r8192_mesh_set_enc_ext(struct net_device *dev, struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr);
+#ifdef BUILT_IN_MSHCLASS
+extern int msh_init(void);
+extern void msh_exit(void);
+#endif
+#endif
+#define IS_HARDWARE_TYPE_819xP(_priv) ((((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8190P)||\
+					(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192E))
+#define IS_HARDWARE_TYPE_8192SE(_priv)	(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192SE)
+#define IS_HARDWARE_TYPE_8192CE(_priv)	(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192CE)
+#define IS_HARDWARE_TYPE_8192CU(_priv)	(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192CU)
+#define IS_HARDWARE_TYPE_8192DE(_priv)	(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192DE)
+#define IS_HARDWARE_TYPE_8192DU(_priv)	(((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192DU)
+extern void dm_InitRateAdaptiveMask(struct net_device * dev);
+
+void rtl8192_tx_timeout(struct net_device *dev);
+void rtl8192_pci_resetdescring(struct net_device *dev);
+void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode);
+void rtl8192_irq_enable(struct net_device *dev);
+void rtl8192_config_rate(struct net_device* dev, u16* rate_config);
+void rtl8192_update_cap(struct net_device* dev, u16 cap);
+void rtl8192_irq_disable(struct net_device *dev);
+
+void rtl819x_UpdateRxPktTimeStamp (struct net_device *dev, struct rtllib_rx_stats *stats);
+long rtl819x_translate_todbm(struct r8192_priv * priv, u8 signal_strength_index	);
+void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv * priv,struct rtllib_rx_stats * pprevious_stats);
+u8 rtl819x_evm_dbtopercentage(char value);
+void rtl819x_process_cck_rxpathsel(struct r8192_priv * priv,struct rtllib_rx_stats * pprevious_stats);
+u8 rtl819x_query_rxpwrpercentage(	char		antpower	);
+void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats * psrc_stats,struct rtllib_rx_stats * ptarget_stats);
+
+bool NicIFEnableNIC(struct net_device* dev);
+bool NicIFDisableNIC(struct net_device* dev);
+
+bool
+MgntActSet_RF_State(
+	struct net_device* dev,
+	RT_RF_POWER_STATE	StateToSet,
+	RT_RF_CHANGE_SOURCE ChangeSource
+	);
+#ifdef CONFIG_CFG_80211
+struct net_device *wiphy_to_net_device(struct wiphy *wiphy);
+#endif
+
+#endif
+
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_wx.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_wx.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef R819x_WX_H
+#define R819x_WX_H
+
+struct net_device;
+struct iw_handler_def;
+struct iw_statistics;
+
+extern struct iw_handler_def r8192_wx_handlers_def;
+struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
+u16 rtl8192_11n_user_show_rates(struct net_device* dev);
+
+#ifdef _RTL8192_EXT_PATCH_
+extern struct iw_handler_def meshdev_wx_handlers_def;
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/Makefile
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/Makefile
@@ -0,0 +1,786 @@
+NIC_SELECT = RTL8192SE
+
+CC = gcc
+KVER  := $(shell uname -r)
+MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
+
+ifeq ($(shell uname -r|cut -d. -f1,2), 2.6)
+###################### KERNEL 2.6 ################################
+ifeq ($(NIC_SELECT),RTL8192CE)
+sub_folder = rtl8192c
+EXTRA_CFLAGS = -DRTL8192CE
+EXTRA_CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 		\
+		-DRTL8192SU_DISABLE_CCK_RATE=0 		\
+		-DDISABLE_BB_RF=0 			\
+		-DRTL92SE_FPGA_VERIFY=0	 		\
+		-DSIMULATE_ETHERNET=0 			\
+		-DSUPERMAC_92D_ENABLE=0			\
+		-DEARLYMODE_ENABLE_FOR_92D=0 		\
+		-DRTL8192S_DISABLE_FW_DM=0 		\
+		-DMP_CCK_WORKAROUND=0			\
+		-DRTL8192SE_DISABLE_MGNT_QUEUE=0	\
+		-DRTL8190_Download_Firmware_From_Header=1 \
+		-DMUTUAL_AUTHENTICATION=1		\
+		-DFOR_QMI=0				\
+		-DENABLE_TKIP11N 			\
+		-DCONFIG_PM_RTL 			\
+		-DCONFIG_PM 				\
+		-DENABLE_IPS 				\
+		-DENABLE_LPS 				\
+		-DCONFIG_ASPM_OR_D3 			\
+		-DENABLE_GPIO_RADIO_CTL 		\
+		-DMP_DRIVER=0				\
+		-DENABLE_DOT11D 			
+		#					\
+		-D_ENABLE_SW_BEACON 			\
+		-DUSE_FW_SOURCE_IMG_FILE 		\
+		-DEFUSE_REPG_WORKAROUND			\
+		-DENABLE_AMSDU 				\
+		-DADHOC_11N 				\
+		-DFOR_ANDROID_X86			\
+		-DCONFIG_64BIT_DMA			\
+		#
+endif
+
+ifeq ($(NIC_SELECT),RTL8192SE)
+sub_folder = rtl8192s
+EXTRA_CFLAGS = -DRTL8192SE
+EXTRA_CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 		\
+		-DRTL92SE_FPGA_VERIFY=0 		\
+		-DDEMO_BOARD_SUPPORT=1 			\
+		-DRTL8192SU_DISABLE_CCK_RATE=0 		\
+		-DRTL8192S_DISABLE_FW_DM=0 		\
+		-DHAL_MAC_ENABLE=1 			\
+		-DHAL_BB_ENABLE=1 			\
+		-DHAL_RF_ENABLE=1 			\
+		-DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 \
+		-DDISABLE_BB_RF=0 			\
+		-DCONFIG_PM_RTL 			\
+		-DCONFIG_PM 				\
+		-DENABLE_GPIO_RADIO_CTL 		\
+		-DRTL8190_Download_Firmware_From_Header=1 \
+		-DENABLE_LPS 				\
+		-DCONFIG_RX_CMD				\
+		-DENABLE_IPS 				\
+		-DUSE_FW_SOURCE_IMG_FILE 		\
+		-DENABLE_DOT11D 			\
+		-DCONFIG_ASPM_OR_D3 			\
+		#					\
+		-DCONFIG_CRDA	 			\
+		-DCONFIG_CFG_80211 			\
+		-DCONFIG_RTL_RFKILL	 		\
+		-DCONFIG_FW_SETCHAN			\
+		-DRTL8192S_WAPI_SUPPORT			\
+		-D_ENABLE_SW_BEACON 			\
+		-DCONFIG_MP 				\
+		-DENABLE_AMSDU 				\
+		-DADHOC_11N				\
+		-DEFUSE_REPG_WORKAROUN			\
+		-DENABLE_TKIP11N			\
+		-DFOR_ANDROID_X86			\
+		#
+		#NOTICE:
+		#[1] CONFIG_MP is for MP test, 
+		#    you should close IPS/LPS/GPIO/ASPM 
+		#[2] In order to support CRDA, RFKILL 
+      		#    CONFIG_CFG_80211 need to be enabled at first.
+		#[3] In order to support CRDA, 
+      		#    DOT11D need to be enabled at first.
+		#[4] CRDA and RFKILL can be enabled individually. 
+                
+		
+endif
+ifeq ($(NIC_SELECT),RTL8190P)
+sub_folder = rtl8192e
+EXTRA_CFLAGS += -DRTL8190P				\
+		-DUSE_FW_SOURCE_IMG_FILE		\
+		-DEEPROM_OLD_FORMAT_SUPPORT=1		\
+		-DENABLE_DOT11D 			
+		#					\
+		-DCONFIG_PM				\
+		-DENABLE_TKIP11N			\
+		-DFOR_ANDROID_X86			\
+		#
+endif
+ifeq ($(NIC_SELECT),RTL8192E)
+sub_folder = rtl8192e
+EXTRA_CFLAGS+=-DRTL8192E				\
+		-DEEPROM_OLD_FORMAT_SUPPORT=1		\
+		-DUSE_FW_SOURCE_IMG_FILE		\
+		-DENABLE_IPS				\
+		-DENABLE_LPS				\
+		-DENABLE_GPIO_RADIO_CTL			\
+		-DCONFIG_PM_RTL 			\
+		-DCONFIG_PM 				\
+		-DENABLE_DOT11D 			
+		#					\
+		-DCONFIG_RTL8192_IO_MAP			\
+		-DCONFIG_ASPM_OR_D3 			\
+		-DENABLE_TKIP11N			\
+		-DFOR_ANDROID_X86			\
+		#
+endif
+ifeq ($(NIC_SELECT),RTL8191SE_MESH)
+sub_folder = rtl8192s
+EXTRA_CFLAGS += -DRTL8192SE 				\
+		-DEEPROM_OLD_FORMAT_SUPPORT=0 		\
+		-DRTL92SE_FPGA_VERIFY=0 		\
+		-DDEMO_BOARD_SUPPORT=1 			\
+		-DRTL8192SU_DISABLE_CCK_RATE=0 		\
+		-DRTL8192S_DISABLE_FW_DM=0 		\
+		-DHAL_MAC_ENABLE=1 			\
+		-DHAL_BB_ENABLE=1 			\
+		-DHAL_RF_ENABLE=1 			\
+		-DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 \
+		-DDISABLE_BB_RF=0 			\
+		-DRTL8190_Download_Firmware_From_Header=1 \
+		-DEFUSE_REPG_WORKAROUND 		\
+		-DCONFIG_PM 				\
+		-DCONFIG_PM_RTL 			\
+		-DENABLE_GPIO_RADIO_CTL			\
+		-DENABLE_IPS 				\
+		-DENABLE_LPS				\
+		-DCONFIG_ASPM_OR_D3 			\
+		-DCUSTOMER_ID_INTEL_CMPC 		\
+		-DMESH_8192_SPECIFIED 			\
+		-D_RTL8192_EXT_PATCH_ 			\
+		-D_MESH_DEBUG_ 				\
+		-DTREE_BASED_ROUTING_ENABLE 		\
+		-DMESH_PATHSEL_DBG_LV=0 		\
+		-DMESH_PATHSEL_DBG_SIMPLE=0 		\
+		-DMESH_PATHSEL_DBG_TEST=0		\
+		-DBUILT_IN_MSHCLASS 			\
+		-DENABLE_AMSDU				\
+		-DUSE_FW_SOURCE_IMG_FILE 		\
+		-DENABLE_DOT11D 			\
+		-DCONFIG_RX_CMD				\
+		#					\
+		-DADHOC_11N				\
+		-DCOMPATIBLE_WITH_RALINK_MESH 		\
+		-DCONFIG_CRDA	 			\
+		-DCONFIG_FW_SETCHAN			\
+		-DRTL8192S_WAPI_SUPPORT			\
+		-DMESH_AUTO_TEST			\
+		-D_ENABLE_SW_BEACON			\
+		-DEFUSE_REPG_WORKAROUND 		\
+		-DENABLE_TKIP11N			\
+		-DFOR_ANDROID_X86			\
+		-DCONFIG_MP 				\
+		#
+endif
+
+#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem.
+ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0)
+	EXTRA_CFLAGS += -DOPENSUSE_SLED=1
+else
+	EXTRA_CFLAGS += -DOPENSUSE_SLED=0
+endif
+
+# Switch AP will fail in moblin2. This flag is to solve this issue.
+ifeq ($(shell uname -r | cut -d. -f6 | cut -d- -f1), moblin2)
+	EXTRA_CFLAGS += -DFOR_MOBLIN
+endif
+
+EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless
+EXTRA_CFLAGS += -std=gnu89
+EXTRA_CFLAGS += -O2
+EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
+EXTRA_CFLAGS += -DTHOMAS_TURBO
+#flag for single module compile
+EXTRA_CFLAGS += -DBUILT_IN_RTLLIB
+#EXTRA_CFLAGS += -DCONFIG_RTLWIFI_DEBUGFS
+ifeq ($(NIC_SELECT),RTL8190P)
+r8190_pci-objs := rtl_core.o 		\
+		  rtl_eeprom.o 		\
+		  rtl_ps.o 		\
+		  rtl_wx.o 		\
+		  rtl_cam.o		\
+		  rtl_dm.o 		\
+		  rtl_pm.o 		\
+		  rtl_debug.o 		\
+		  rtl_ethtool.o		\
+		  rtl8192e/r8190P_hwimg.o	\
+		  rtl8192e/r8190P_rtl8256.o 	\
+		  rtl8192e/r8192E_dev.o		\
+		  rtl8192e/r8192E_phy.o 		\
+		  rtl8192e/r8192E_firmware.o 	\
+		  rtl8192e/r8192E_cmdpkt.o 	\
+		  ../../rtllib/rtllib_rx.o                \
+		  ../../rtllib/rtllib_softmac.o           \
+		  ../../rtllib/rtllib_tx.o                \
+		  ../../rtllib/rtllib_wx.o                \
+		  ../../rtllib/rtllib_module.o            \
+		  ../../rtllib/rtllib_softmac_wx.o        \
+		  ../../rtllib/rtl819x_HTProc.o              \
+		  ../../rtllib/rtl819x_TSProc.o              \
+		  ../../rtllib/rtl819x_BAProc.o              \
+		  ../../rtllib/dot11d.o                      \
+		  ../../rtllib/rtllib_crypt.o             \
+		  ../../rtllib/rtllib_crypt_tkip.o        \
+		  ../../rtllib/rtllib_crypt_ccmp.o        \
+		  ../../rtllib/rtllib_crypt_wep.o
+
+obj-m := r8190_pci.o
+endif
+ifeq ($(NIC_SELECT),RTL8192E)
+r8192e_pci-objs := rtl_core.o 		\
+		  rtl_eeprom.o 	\
+		  rtl_ps.o 		\
+		  rtl_wx.o   	\
+		  rtl_cam.o		\
+		  rtl_dm.o 		\
+		  rtl_pm.o 		\
+		  rtl_debug.o		\
+		  rtl_ethtool.o		\
+		  rtl8192e/r8192E_dev.o		\
+		  rtl8192e/r8192E_phy.o 		\
+		  rtl8192e/r8192E_firmware.o 	\
+		  rtl8192e/r8192E_cmdpkt.o 	\
+		  rtl8192e/r8192E_hwimg.o 	\
+		  rtl8192e/r8190P_rtl8256.o 	\
+		  rtllib/rtllib_rx.o                \
+		  rtllib/rtllib_softmac.o           \
+		  rtllib/rtllib_tx.o                \
+		  rtllib/rtllib_wx.o                \
+		  rtllib/rtllib_module.o            \
+		  rtllib/rtllib_softmac_wx.o        \
+		  rtllib/rtl819x_HTProc.o              \
+		  rtllib/rtl819x_TSProc.o              \
+		  rtllib/rtl819x_BAProc.o              \
+		  rtllib/dot11d.o                      \
+		  rtllib/rtllib_crypt.o             \
+		  rtllib/rtllib_crypt_tkip.o        \
+		  rtllib/rtllib_crypt_ccmp.o        \
+		  rtllib/rtllib_crypt_wep.o
+obj-m := r8192e_pci.o
+endif
+ifeq ($(NIC_SELECT),RTL8192SE)
+r8192se_pci-objs := rtl_core.o 		\
+		  rtl_regd.o		\
+		  rtl_rfkill.o		\
+		  rtl_eeprom.o 		\
+		  rtl_wx.o 		\
+		  rtl_cam.o		\
+		  rtl_pm.o 		\
+		  rtl_ps.o 		\
+		  rtl_dm.o 		\
+		  rtl_debug.o		\
+		  rtl_ethtool.o         \
+		  rtl8192s/r8192S_dev.o 	\
+		  rtl8192s/r8192S_Efuse.o 	\
+		  rtl8192s/r8192S_phy.o 	\
+		  rtl8192s/r8192S_firmware.o 	\
+		  rtl8192s/r8192S_rtl6052.o 	\
+		  rtl8192s/r8192S_hwimg.o 	\
+		  rtl8192s/r8192S_led.o 	\
+		  rtl8192s/r8192S_mp.o		\
+		  rtl8192s/r8192S_scan.o	\
+		  rtllib/rtllib_rx.o                \
+		  rtllib/rtllib_softmac.o           \
+		  rtllib/rtllib_tx.o                \
+		  rtllib/rtllib_wx.o                \
+		  rtllib/rtllib_module.o            \
+		  rtllib/rtllib_softmac_wx.o        \
+		  rtllib/rtl819x_HTProc.o              \
+		  rtllib/rtl819x_TSProc.o              \
+		  rtllib/rtl819x_BAProc.o              \
+		  rtllib/dot11d.o                      \
+		  rtllib/rtllib_crypt.o             \
+		  rtllib/rtllib_crypt_tkip.o        \
+		  rtllib/rtllib_crypt_ccmp.o        \
+		  rtllib/rtllib_crypt_wep.o		\
+		  rtllib/wapi.o        			\
+		  rtllib/wapi_interface.o
+#		  rtl8192e/r8190P_rtl8256.o 	
+obj-m := r8192se_pci.o
+endif
+
+ifeq ($(NIC_SELECT),RTL8192CE)
+r8192ce_pci-objs := rtl_core.o 		\
+		  rtl_eeprom.o 		\
+		  rtl_wx.o 		\
+		  rtl_cam.o		\
+		  rtl_pm.o 		\
+		  rtl_ps.o 		\
+		  rtl_debug.o		\
+		  rtl_ethtool.o         \
+		  rtl8192c/r8192C_dev.o 	\
+		  rtl8192c/r8192C_Efuse.o 	\
+		  rtl8192c/r8192C_phy.o 	\
+		  rtl8192c/r8192C_firmware.o 	\
+		  rtl8192c/r8192C_dm.o 		\
+		  rtl8192c/r8192C_rtl6052.o 	\
+		  rtl8192c/r8192C_hwimg.o 	\
+		  rtl8192c/r8192C_led.o 	\
+		  rtl8192c/r8192C_com.o 	\
+		  rtl8192c/r8192C_PhyParam.o 	\
+		  ../../rtllib/rtllib_rx.o                \
+		  ../../rtllib/rtllib_softmac.o           \
+		  ../../rtllib/rtllib_tx.o                \
+		  ../../rtllib/rtllib_wx.o                \
+		  ../../rtllib/rtllib_module.o            \
+		  ../../rtllib/rtllib_softmac_wx.o        \
+		  ../../rtllib/rtl819x_HTProc.o              \
+		  ../../rtllib/rtl819x_TSProc.o              \
+		  ../../rtllib/rtl819x_BAProc.o              \
+		  ../../rtllib/dot11d.o                      \
+		  ../../rtllib/rtllib_crypt.o             \
+		  ../../rtllib/rtllib_crypt_tkip.o        \
+		  ../../rtllib/rtllib_crypt_ccmp.o        \
+		  ../../rtllib/rtllib_crypt_wep.o
+obj-m := r8192ce_pci.o
+endif
+
+ifeq ($(NIC_SELECT),RTL8191SE_MESH)
+r8192se_pci_mesh-objs := rtl_core.o 	\
+		  rtl_regd.o		\
+		  rtl_rfkill.o		\
+		  rtl_eeprom.o 		\
+		  rtl_ps.o 		\
+		  rtl_wx.o 		\
+		  rtl_cam.o		\
+		  rtl_dm.o 		\
+		  rtl_pm.o 		\
+		  rtl_debug.o		\
+		  rtl_ethtool.o         \
+		  rtl_mesh.o		\
+		  rtl8192s/r8192S_dev.o \
+		  rtl8192s/r8192S_Efuse.o 	\
+		  rtl8192s/r8192S_phy.o 	\
+		  rtl8192s/r8192S_firmware.o 	\
+		  rtl8192s/r8192S_rtl6052.o 	\
+		  rtl8192s/r8192S_hwimg.o 	\
+		  rtl8192s/r8192S_led.o 	\
+		  rtl8192s/r8192S_mp.o		\
+		  rtl8192s/r8192S_scan.o		\
+		  ../../rtllib/rtllib_rx.o                \
+		  ../../rtllib/rtllib_softmac.o           \
+		  ../../rtllib/rtllib_tx.o                \
+		  ../../rtllib/rtllib_wx.o                \
+		  ../../rtllib/rtllib_module.o            \
+		  ../../rtllib/rtllib_softmac_wx.o        \
+		  ../../rtllib/rtl819x_HTProc.o           \
+		  ../../rtllib/rtl819x_TSProc.o           \
+		  ../../rtllib/rtl819x_BAProc.o           \
+		  ../../rtllib/dot11d.o                   \
+		  ../../rtllib/rtllib_crypt.o             \
+		  ../../rtllib/rtllib_crypt_tkip.o        \
+		  ../../rtllib/rtllib_crypt_ccmp.o        \
+		  ../../rtllib/rtllib_crypt_wep.o	  \
+		  ../../mshclass/msh_class.o 		  \
+		  ../../mshclass/mesh_8192_util.o  	  \
+		  ../../mshclass/rtl8192_mesh.o 	  \
+		  ../../mshclass/rtl8192s_sme.o 	  \
+	  	  ../../mshclass/rtl8192_proc.o 	  \
+		  ../../mshclass/8192s_pathsel.o 	  \
+		  ../../mshclass/hash_table.o 		  \
+		  ../../mshclass/rtl8192_sha1.o           \
+		  ../../mshclass/rtl8192_sha256.o         \
+		  ../../mshclass/rtl8192_aes.o            \
+		  ../../mshclass/mesh_abbr_handshk.o      \
+		  ../../mshclass/rtl8192_bn_ctx.o         \
+		  ../../mshclass/rtl8192_bn_asm.o         \
+		  ../../mshclass/rtl8192_bn_gcd.o         \
+		  ../../mshclass/rtl8192_bn_mont.o        \
+		  ../../mshclass/rtl8192_bn_recp.o        \
+		  ../../mshclass/rtl8192_bn_lib.o         \
+		  ../../mshclass/mesh_ath.o		  \
+		  ../../mshclass/pathselection.o 	  \
+		  ../../mshclass/tree_proactive.o
+#		  rtl8192e/r8190P_rtl8256.o 	
+obj-m := r8192se_pci_mesh.o
+endif
+
+
+KSRC := /lib/modules/$(KVER)/build
+INSTALL_PREFIX :=
+IMG_DIR := /lib/firmware/
+all: modules
+
+modules:
+	$(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules
+install: modules
+ifeq ($(NIC_SELECT),RTL8190P)
+	install -p -m 644 r8190_pci.ko $(MODDESTDIR)
+endif
+ifeq ($(NIC_SELECT),RTL8192E)
+	install -p -m 644 r8192e_pci.ko $(MODDESTDIR)
+endif
+ifeq ($(NIC_SELECT),RTL8192SE)
+	install -p -m 644 r8192se_pci.ko $(MODDESTDIR)
+endif
+ifeq ($(NIC_SELECT),RTL8192CE)
+	install -p -m 644 r8192ce_pci.ko $(MODDESTDIR)
+endif
+ifeq ($(NIC_SELECT),RTL8191SE_MESH)
+	cp ../../script/mesh-tools /usr/share/enhanced-easy-network/ -rf
+	cp ../../script/mesh.conf /etc/
+	cp ../../script/wpa_mesh_tkip.conf /etc/
+	cp ../../script/wpa_mesh_ccmp.conf /etc/
+	chmod 777 ../../script/do_install
+	../../script/do_install
+	install -p -m 644 r8192se_pci_mesh.ko $(MODDESTDIR)
+endif
+
+	depmod -a
+	@#copy firmware img to target fold
+	$(shell [ -d "$(IMG_DIR)/`uname -r`" ] && cp -fr $(RTL819x_FIRM_DIR)/$(NIC_SELECT) $(IMG_DIR)/`uname -r`/.)
+	$(shell [ ! -d "$(IMG_DIR)/`uname -r`" ] && cp -fr $(RTL819x_FIRM_DIR)/$(NIC_SELECT) $(IMG_DIR)/.)
+uninstall:
+ifeq ($(NIC_SELECT),RTL8190P)
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8190_pci.ko)
+endif
+ifeq ($(NIC_SELECT),RTL8192E)
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192e_pci.ko)
+endif
+ifeq ($(NIC_SELECT),RTL8192SE)
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci.ko)
+endif
+ifeq ($(NIC_SELECT),RTL8192CE)
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192ce_pci.ko)
+endif
+ifeq ($(NIC_SELECT),RTL8191SE_MESH)
+	rm -f /etc/wpa_mesh_tkip.conf
+	rm -f /etc/wpa_mesh_ccmp.conf
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci_mesh.ko)
+endif
+	depmod -a
+	@#delete the firmware img
+	@rm -fr /lib/firmware/$(NIC_SELECT)
+	@rm -fr /lib/firmware/`uname -r`/$(NIC_SELECT)
+else
+###################### KERNEL 2.4 ################################
+LD := ld
+KSRC := /lib/modules/$(KVER)/build
+CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
+CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
+CFLAGS += -I$(KSRC)/include -I.
+CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h
+#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB  
+
+ifeq ($(NIC_SELECT),RTL8190P)
+sub_folder = rtl8192e
+CFLAGS += -DRTL8190P
+CFLAGS+=-DEEPROM_OLD_FORMAT_SUPPORT=1
+#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS
+endif
+
+ifeq ($(NIC_SELECT),RTL8192E)
+sub_folder = rtl8192e
+CFLAGS += -DRTL8192E
+CFLAGS+=-DEEPROM_OLD_FORMAT_SUPPORT=1
+CFLAGS+=-DENABLE_GPIO_RADIO_CTL
+#CFLAGS += -DENABLE_IPS
+#CFLAGS += -DENABLE_IPS
+#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS
+endif
+
+ifeq ($(NIC_SELECT),RTL8192SE)
+sub_folder = rtl8192s
+CFLAGS += -DRTL8192SE
+CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 
+CFLAGS += -DRTL92SE_FPGA_VERIFY=0 
+CFLAGS += -DDEMO_BOARD_SUPPORT=1 
+CFLAGS += -DRTL8192SU_DISABLE_CCK_RATE=0 
+CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 
+CFLAGS += -DHAL_MAC_ENABLE=1 
+CFLAGS += -DHAL_BB_ENABLE=1 
+CFLAGS += -DHAL_RF_ENABLE=1 
+CFLAGS += -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 
+CFLAGS += -DDISABLE_BB_RF=0 
+CFLAGS += -DRTL8190_Download_Firmware_From_Header=1 
+#CFLAGS += -DRTL8192S_WAPI_SUPPORT=1 
+#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS
+#CFLAGS += -DCONFIG_PM_RTL 
+#CFLAGS += -DENABLE_GPIO_RADIO_CTL  
+#EXTRA_CFLAGS += -DCONFIG_PM
+#EXTRA_CFLAGS += -DENABLE_IPS
+#EXTRA_CFLAGS += -DENABLE_LPS
+#EXTRA_CFLAGS += -DCONFIG_ASPM_OR_D3
+#CFLAGS += -DENABLE_AMSDU
+#CFLAGS += -DADHOC_11N
+endif
+
+ifeq ($(NIC_SELECT),RTL8191SE_MESH)
+sub_folder = rtl8192s
+CFLAGS += -DRTL8192SE
+CFLAGS +=-DEEPROM_OLD_FORMAT_SUPPORT=1
+#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS
+CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 
+CFLAGS += -DRTL92SE_FPGA_VERIFY=0 
+CFLAGS += -DDEMO_BOARD_SUPPORT=1 
+CFLAGS += -DRTL8192SU_DISABLE_CCK_RATE=0 
+CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 
+CFLAGS += -DHAL_MAC_ENABLE=1 
+CFLAGS += -DHAL_BB_ENABLE=1 
+CFLAGS += -DHAL_RF_ENABLE=1 
+CFLAGS += -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 
+CFLAGS += -DDISABLE_BB_RF=0 
+CFLAGS += -DCONFIG_PM_RTL 
+CFLAGS += -DENABLE_GPIO_RADIO_CTL  
+CFLAGS += -DRTL8190_Download_Firmware_From_Header=1 
+CFLAGS += -DENABLE_IPS
+CFLAGS += -DENABLE_LPS
+CFLAGS += -DCONFIG_ASPM_OR_D3
+CFLAGS += -D_RTL8192_EXT_PATCH_ \
+	  -DMESH_8192_SPECIFIED \
+	  -D_MESH_DEBUG_ \
+	  -DTREE_BASED_ROUTING_ENABLE \
+	  -DMESH_PATHSEL_DBG_LV=0 \
+	  -DMESH_PATHSEL_DBG_SIMPLE=0 \
+	  -DMESH_PATHSEL_DBG_TEST=0\
+	  -DBUILT_IN_MSHCLASS \
+	  -DCUSTOMER_ID_INTEL_CMPC \
+	  -DENABLE_AMSDU
+endif
+CFLAGS += -DTHOMAS_TURBO
+CFLAGS += -DENABLE_DOT11D
+
+#flag for single module compile
+CFLAGS += -DBUILT_IN_RTLLIB
+CFLAGS += -DBUILT_IN_CRYPTO
+#CFLAGS += -DENABLE_TKIP11N
+
+SMP := $(shell $(CC) $(CFLAGS) -E -dM $(CONFIG_FILE) | \
+   grep CONFIG_SMP | awk '{print $$3}')
+ifneq ($(SMP),1)
+   SMP := 0
+endif
+ifeq ($(SMP),1)
+   CFLAGS    += -D__SMP__
+endif
+OBJS := ${patsubst %.c, %.o, ${wildcard *.c}}
+
+ifeq ($(NIC_SELECT),RTL8190P)
+all:r8190_pci.o
+r8190_pci.o: \
+	rtl_core.o      \
+	rtl_eeprom.o     \
+	rtl_ps.o        \
+	rtl_dm.o \
+	rtl_wx.o \
+	rtl_cam.o	 \
+	rtl_pm.o \
+	rtl_debug.o \
+	rtl_ethtool.o         \
+	rtl8192e/r8190P_rtl8256.o \
+	rtl8192e/r8190P_hwimg.o \
+	rtl8192e/r8192E_dev.o	\
+	rtl8192e/r8192E_cmdpkt.o\
+	rtl8192e/r8192E_firmware.o \
+	rtl8192e/r8192E_phy.o \
+	../../rtllib/rtllib_rx.o                \
+	../../rtllib/rtllib_softmac.o           \
+	../../rtllib/rtllib_tx.o                \
+	../../rtllib/rtllib_wx.o                \
+	../../rtllib/rtllib_module.o            \
+	../../rtllib/rtllib_softmac_wx.o        \
+	../../rtllib/rtl819x_HTProc.o              \
+	../../rtllib/rtl819x_TSProc.o              \
+	../../rtllib/rtl819x_BAProc.o              \
+	../../rtllib/dot11d.o                      \
+	../../rtllib/rtllib_crypt.o             \
+	../../rtllib/rtllib_crypt_tkip.o        \
+	../../rtllib/rtllib_crypt_ccmp.o        \
+	../../rtllib/rtllib_crypt_wep.o	\
+	../../rtllib/api.o			\
+	../../rtllib/compress.o		\
+	../../rtllib/digest.o		\
+	../../rtllib/cipher.o		\
+	../../rtllib/scatterwalk.o		\
+	../../rtllib/arc4.o			\
+	../../rtllib/michael_mic.o		\
+	../../rtllib/aes.o			\
+	../../rtllib/proc.o
+
+	$(LD) -r $^ -o $@
+install:r8190_pci.o
+	install -p -m 644 r8190_pci.o  $(MODDESTDIR)
+	@depmod -a
+uninstall:
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8190_pci.o)
+	@depmod -a
+endif
+
+ifeq ($(NIC_SELECT),RTL8192E)
+all:r8192e_pci.o
+r8192e_pci.o: \
+	rtl_core.o \
+	rtl_eeprom.o \
+	rtl_ps.o 		\
+	rtl_dm.o \
+	rtl_wx.o \
+	rtl_cam.o	\
+	rtl_pm.o \
+	rtl_debug.o \
+	rtl_ethtool.o         \
+	rtl8192e/r8192E_dev.o           \
+	rtl8192e/r8190P_rtl8256.o \
+	rtl8192e/r8192E_hwimg.o \
+	rtl8192e/r8192E_cmdpkt.o\
+	rtl8192e/r8192E_firmware.o \
+	rtl8192e/r8192E_phy.o \
+	../../rtllib/rtllib_rx.o                \
+	../../rtllib/rtllib_softmac.o           \
+	../../rtllib/rtllib_tx.o                \
+	../../rtllib/rtllib_wx.o                \
+	../../rtllib/rtllib_module.o            \
+	../../rtllib/rtllib_softmac_wx.o        \
+	../../rtllib/rtl819x_HTProc.o              \
+	../../rtllib/rtl819x_TSProc.o              \
+	../../rtllib/rtl819x_BAProc.o              \
+	../../rtllib/dot11d.o                      \
+	../../rtllib/rtllib_crypt.o             \
+	../../rtllib/rtllib_crypt_tkip.o        \
+	../../rtllib/rtllib_crypt_ccmp.o        \
+	../../rtllib/rtllib_crypt_wep.o	\
+	../../rtllib/api.o			\
+	../../rtllib/compress.o		\
+	../../rtllib/digest.o		\
+	../../rtllib/cipher.o		\
+	../../rtllib/scatterwalk.o		\
+	../../rtllib/arc4.o			\
+	../../rtllib/michael_mic.o		\
+	../../rtllib/aes.o			\
+	../../rtllib/proc.o
+
+	$(LD) -r $^ -o $@
+install:
+	install -p -m 644 r8192e_pci.o  $(MODDESTDIR)
+	@depmod -a
+uninstall:
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192e_pci.o)
+	@depmod -a
+endif
+
+ifeq ($(NIC_SELECT),RTL8192SE)
+all:r8192se_pci.o
+r8192se_pci.o: rtl_core.o \
+	rtl_debug.o \
+	rtl_ethtool.o \
+	rtl_eeprom.o \
+ 	rtl_ps.o        \
+	rtl_dm.o \
+	rtl_wx.o \
+	rtl_cam.o		\
+	rtl_pm.o \
+	rtl8192s/r8192S_dev.o \
+	rtl8192s/r8192S_Efuse.o \
+	rtl8192s/r8192S_firmware.o \
+	rtl8192s/r8192S_hwimg.o \
+	rtl8192s/r8192S_led.o \
+	rtl8192s/r8192S_phy.o \
+	rtl8192s/r8192S_rtl6052.o \
+	../../rtllib/rtllib_rx.o                \
+	../../rtllib/rtllib_softmac.o           \
+	../../rtllib/rtllib_tx.o                \
+	../../rtllib/rtllib_wx.o                \
+	../../rtllib/rtllib_module.o            \
+	../../rtllib/rtllib_softmac_wx.o        \
+	../../rtllib/rtl819x_HTProc.o              \
+	../../rtllib/rtl819x_TSProc.o              \
+	../../rtllib/rtl819x_BAProc.o              \
+	../../rtllib/dot11d.o                      \
+	../../rtllib/rtllib_crypt.o             \
+	../../rtllib/rtllib_crypt_tkip.o        \
+	../../rtllib/rtllib_crypt_ccmp.o        \
+	../../rtllib/rtllib_crypt_wep.o	\
+	../../rtllib/api.o			\
+	../../rtllib/compress.o		\
+	../../rtllib/digest.o		\
+	../../rtllib/cipher.o		\
+	../../rtllib/scatterwalk.o		\
+	../../rtllib/arc4.o			\
+	../../rtllib/michael_mic.o		\
+	../../rtllib/aes.o			\
+	../../rtllib/proc.o			\
+	../../rtllib/wapi.o			\
+	../../rtllib/wapi_interface.o
+#	rtl8192e/r8192E_cmdpkt.o 
+#	rtl8192e/r8190P_rtl8256.o 
+	$(LD) -r $^ -o $@
+install:r8192se_pci.o
+	install -p -m 644 r8192se_pci.o  $(MODDESTDIR)
+	@depmod -a
+uninstall:
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci.o)
+	@depmod -a
+endif
+
+ifeq ($(NIC_SELECT),RTL8191SE_MESH )
+all:r8192se_pci_mesh.o
+r8192se_pci_mesh.o: 		\
+	rtl_core.o 		\
+	rtl_eeprom.o 		\
+	rtl_ps.o 		\
+	rtl_dm.o 		\
+	rtl_wx.o 		\
+	rtl_cam.o		\
+	rtl_pm.o 		\
+	rtl_debug.o 		\
+	rtl_ethtool.o 		\
+	rtl_mesh.o		\
+	rtl8192s/r8192S_dev.o 		\
+	rtl8192s/r8192S_Efuse.o 	\
+	rtl8192s/r8192S_firmware.o 	\
+	rtl8192s/r8192S_hwimg.o 	\
+	rtl8192s/r8192S_led.o 		\
+	rtl8192s/r8192S_phy.o 		\
+	rtl8192s/r8192S_rtl6052.o 	\
+	../../rtllib/rtllib_rx.o                \
+	../../rtllib/rtllib_softmac.o           \
+	../../rtllib/rtllib_tx.o                \
+	../../rtllib/rtllib_wx.o                \
+	../../rtllib/rtllib_module.o            \
+	../../rtllib/rtllib_softmac_wx.o        \
+	../../rtllib/rtl819x_HTProc.o              \
+	../../rtllib/rtl819x_TSProc.o              \
+	../../rtllib/rtl819x_BAProc.o              \
+	../../rtllib/dot11d.o                      \
+	../../rtllib/rtllib_crypt.o             \
+	../../rtllib/rtllib_crypt_tkip.o        \
+	../../rtllib/rtllib_crypt_ccmp.o        \
+	../../rtllib/rtllib_crypt_wep.o		\
+	../../mshclass/msh_class.o 			\
+	../../mshclass/mesh_8192_util.o  		\
+	../../mshclass/rtl8192_mesh.o 			\
+	../../mshclass/rtl8192s_sme.o 			\
+	../../mshclass/rtl8192_proc.o 			\
+	../../mshclass/8192s_pathsel.o 			\
+	../../mshclass/hash_table.o 			\
+	../../mshclass/pathselection.o 			\
+	../../mshclass/tree_proactive.o			\
+        ../../mshclass/hash_table.o                   \
+        ../../mshclass/sha1.o                         \
+        ../../mshclass/sha256.o                       \
+        ../../mshclass/aes.o                          \
+        ../../mshclass/mesh_abbr_handshk.o            \
+        ../../mshclass/bn_ctx.o                       \
+        ../../mshclass/bn_asm.o                       \
+        ../../mshclass/bn_gcd.o                       \
+        ../../mshclass/bn_mont.o                      \
+        ../../mshclass/bn_recp.o                      \
+        ../../mshclass/bn_lib.o                       \
+        ../../mshclass/mesh_ath.o
+#	rtl8192e/r8190P_rtl8256.o \	
+#	rtl8192e/r8192E_cmdpkt.o 
+	$(LD) -r $^ -o $@
+install:r8192se_pci_mesh.o
+	install -p -m 644 r8192se_pci_mesh.o  $(MODDESTDIR)
+	@depmod -a
+uninstall:
+	$(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci_mesh.o)
+	@depmod -a
+endif
+endif
+
+.PHONY:clean
+clean:
+	rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~
+	rm -fr .tmp_versions
+	rm -fr Modules.symvers
+	rm -fr Module.symvers
+	rm -fr Module.markers
+	rm -fr modules.order
+	rm -fr tags
+	@make -C $(sub_folder)/ clean
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_dm.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_dm.h
@@ -0,0 +1,332 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef	__R8192UDM_H__
+#define __R8192UDM_H__
+
+
+/*--------------------------Define Parameters-------------------------------*/
+#define 		OFDM_Table_Length	19
+#define		CCK_Table_length	12
+
+#define		DM_DIG_THRESH_HIGH					40
+#define		DM_DIG_THRESH_LOW					35
+
+#define		DM_FALSEALARM_THRESH_LOW	40
+#define		DM_FALSEALARM_THRESH_HIGH	1000
+
+#define		DM_DIG_HIGH_PWR_THRESH_HIGH		75
+#define		DM_DIG_HIGH_PWR_THRESH_LOW		70
+
+#define		BW_AUTO_SWITCH_HIGH_LOW			25
+#define		BW_AUTO_SWITCH_LOW_HIGH			30
+
+#define		DM_check_fsync_time_interval				500
+
+
+#define		DM_DIG_BACKOFF				12
+#ifdef RTL8192SE
+#define		DM_DIG_MAX					0x3e
+#elif defined RTL8190P || defined RTL8192E
+#define		DM_DIG_MAX					0x36
+#endif
+#define		DM_DIG_MIN					0x1c
+#define		DM_DIG_MIN_Netcore			0x12
+
+#define		DM_DIG_BACKOFF_MAX			12
+#define		DM_DIG_BACKOFF_MIN			-4
+
+#define		RxPathSelection_SS_TH_low		30
+#define		RxPathSelection_diff_TH			18
+
+#define		RateAdaptiveTH_High			50
+#define		RateAdaptiveTH_Low_20M		30
+#define		RateAdaptiveTH_Low_40M		10
+#define		VeryLowRSSI					15
+
+#ifdef RTL8192SE
+#define		CTSToSelfTHVal				30
+#elif defined RTL8190P || defined RTL8192E
+#define		CTSToSelfTHVal					35
+#endif
+
+#define		WAIotTHVal						25
+
+#define		E_FOR_TX_POWER_TRACK               300
+#define		TX_POWER_NEAR_FIELD_THRESH_HIGH		68
+#define		TX_POWER_NEAR_FIELD_THRESH_LOW		62
+#define         TX_POWER_ATHEROAP_THRESH_HIGH           78
+#define 	TX_POWER_ATHEROAP_THRESH_LOW		72
+
+#define 		Current_Tx_Rate_Reg         0x1e0
+#define 		Initial_Tx_Rate_Reg         0x1e1 
+#define 		Tx_Retry_Count_Reg         0x1ac
+#define		RegC38_TH				 20
+
+#define		TX_POWER_NEAR_FIELD_THRESH_LVL2	74
+#define		TX_POWER_NEAR_FIELD_THRESH_LVL1	67
+
+#define		TxHighPwrLevel_Normal		0	
+#define		TxHighPwrLevel_Level1		1
+#define		TxHighPwrLevel_Level2		2
+
+#define		DM_Type_ByFW			0
+#define		DM_Type_ByDriver		1
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/ 
+typedef struct _dynamic_initial_gain_threshold_
+{
+	u8		dig_enable_flag;
+	u8		dig_algorithm;
+	u8		Dig_TwoPort_Algorithm;
+	u8		Dig_Ext_Port_Stage;
+	u8		dbg_mode;
+	u8		dig_algorithm_switch;
+	
+	long		rssi_low_thresh;
+	long		rssi_high_thresh;
+
+	u32		FALowThresh;
+	u32		FAHighThresh;
+	
+	long		rssi_high_power_lowthresh;
+	long		rssi_high_power_highthresh;
+
+	u8		dig_state;
+	u8		dig_highpwr_state;
+	u8		CurSTAConnectState;
+	u8		PreSTAConnectState;
+	u8		CurAPConnectState;
+	u8		PreAPConnectState;
+
+	u8		curpd_thstate;
+	u8		prepd_thstate;
+	u8		curcs_ratio_state;
+	u8		precs_ratio_state;
+
+	u32		pre_ig_value;
+	u32		cur_ig_value;
+
+	u8		Backoff_Enable_Flag;
+	u8		backoff_val;
+	char		BackoffVal_range_max;
+	char		BackoffVal_range_min;
+	u8		rx_gain_range_max;
+	u8		rx_gain_range_min;
+	bool		initialgain_lowerbound_state;
+
+	long		rssi_val;
+}dig_t;
+
+typedef enum tag_dynamic_init_gain_state_definition
+{
+	DM_STA_DIG_OFF = 0,	
+	DM_STA_DIG_ON,		
+	DM_STA_DIG_MAX
+}dm_dig_sta_e;
+
+
+typedef enum tag_dynamic_ratr_state_definition
+{
+	DM_RATR_STA_HIGH = 0,
+	DM_RATR_STA_MIDDLE = 1,
+	DM_RATR_STA_LOW = 2,
+	DM_RATR_STA_MAX
+}dm_ratr_sta_e;
+
+typedef enum tag_dynamic_init_gain_operation_type_definition
+{
+	DIG_TYPE_THRESH_HIGH	= 0,
+	DIG_TYPE_THRESH_LOW	= 1,
+	DIG_TYPE_THRESH_HIGHPWR_HIGH	= 2,
+	DIG_TYPE_THRESH_HIGHPWR_LOW	= 3,
+	DIG_TYPE_DBG_MODE				= 4,
+	DIG_TYPE_RSSI						= 5,
+	DIG_TYPE_ALGORITHM				= 6,
+	DIG_TYPE_BACKOFF					= 7,
+	DIG_TYPE_PWDB_FACTOR			= 8,
+	DIG_TYPE_RX_GAIN_MIN				= 9,
+	DIG_TYPE_RX_GAIN_MAX				= 10,
+	DIG_TYPE_ENABLE 		= 20,
+	DIG_TYPE_DISABLE 		= 30,
+	DIG_OP_TYPE_MAX
+}dm_dig_op_e;
+
+typedef enum tag_dig_algorithm_definition
+{
+	DIG_ALGO_BY_FALSE_ALARM = 0,	
+	DIG_ALGO_BY_RSSI	= 1,
+	DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2,
+	DIG_ALGO_BY_TOW_PORT = 3,
+	DIG_ALGO_MAX
+}dm_dig_alg_e;
+
+typedef enum tag_DIG_TWO_PORT_ALGO_Definition
+{
+	DIG_TWO_PORT_ALGO_RSSI = 0,
+	DIG_TWO_PORT_ALGO_FALSE_ALARM = 1,
+}DM_DIG_TWO_PORT_ALG_E;
+
+
+typedef enum tag_DIG_EXT_PORT_ALGO_Definition
+{
+	DIG_EXT_PORT_STAGE_0 = 0,
+	DIG_EXT_PORT_STAGE_1 = 1,
+	DIG_EXT_PORT_STAGE_2 = 2,
+	DIG_EXT_PORT_STAGE_3 = 3,
+	DIG_EXT_PORT_STAGE_MAX = 4,
+}DM_DIG_EXT_PORT_ALG_E;
+
+typedef enum tag_dig_dbgmode_definition
+{
+	DIG_DBG_OFF = 0,	
+	DIG_DBG_ON = 1,
+	DIG_DBG_MAX
+}dm_dig_dbg_e;
+
+typedef enum tag_dig_connect_definition
+{
+	DIG_STA_DISCONNECT = 0,	
+	DIG_STA_CONNECT = 1,
+	DIG_STA_BEFORE_CONNECT = 2,
+	DIG_AP_DISCONNECT = 3,
+	DIG_AP_CONNECT = 4, 
+	DIG_AP_ADD_STATION = 5,
+	DIG_CONNECT_MAX
+}dm_dig_connect_e;
+
+typedef enum tag_dig_packetdetection_threshold_definition
+{
+	DIG_PD_AT_LOW_POWER = 0,	
+	DIG_PD_AT_NORMAL_POWER = 1,
+	DIG_PD_AT_HIGH_POWER = 2,
+	DIG_PD_MAX
+}dm_dig_pd_th_e;
+
+typedef enum tag_dig_cck_cs_ratio_state_definition
+{
+	DIG_CS_RATIO_LOWER = 0,	
+	DIG_CS_RATIO_HIGHER = 1,
+	DIG_CS_MAX
+}dm_dig_cs_ratio_e;
+typedef struct _Dynamic_Rx_Path_Selection_
+{
+	u8		Enable;
+	u8		DbgMode;
+	u8		cck_method;
+	u8		cck_Rx_path;
+
+	u8		SS_TH_low;
+	u8		diff_TH;
+	u8		disabledRF;
+	u8		reserved;
+	
+	u8		rf_rssi[4];
+	u8		rf_enable_rssi_th[4];
+	long		cck_pwdb_sta[4];
+}DRxPathSel;
+
+typedef enum tag_CCK_Rx_Path_Method_Definition
+{
+	CCK_Rx_Version_1 = 0,	
+	CCK_Rx_Version_2= 1,
+	CCK_Rx_Version_MAX
+}DM_CCK_Rx_Path_Method;
+
+
+typedef enum tag_DM_DbgMode_Definition
+{
+	DM_DBG_OFF = 0,	
+	DM_DBG_ON = 1,
+	DM_DBG_MAX
+}DM_DBG_E;
+
+typedef struct tag_Tx_Config_Cmd_Format
+{
+	u32	Op;					
+	u32	Length;					
+	u32	Value;
+}DCMD_TXCMD_T, *PDCMD_TXCMD_T;
+/*------------------------------Define structure----------------------------*/ 
+
+
+/*------------------------Export global variable----------------------------*/
+extern	dig_t	dm_digtable;
+extern	u8		dm_shadow[16][256];
+extern DRxPathSel      DM_RxPathSelTable;
+
+extern	u8			test_flag;
+/*------------------------Export global variable----------------------------*/
+
+
+/*------------------------Export Marco Definition---------------------------*/
+#define DM_APInitGainChangeNotify(Event) {dm_digtable.CurAPConnectState = Event;}
+/*------------------------Export Marco Definition---------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+/*--------------------------Exported Function prototype---------------------*/
+extern  void    init_hal_dm(struct net_device *dev);
+extern  void deinit_hal_dm(struct net_device *dev);
+
+extern void hal_dm_watchdog(struct net_device *dev);
+
+
+extern  void    init_rate_adaptive(struct net_device *dev);
+extern  void    dm_txpower_trackingcallback(void *data);
+
+#ifndef RTL8192SE
+extern  void dm_cck_txpower_adjust(struct net_device *dev,bool  binch14);
+#endif
+
+extern  void    dm_restore_dynamic_mechanism_state(struct net_device *dev);
+extern  void    dm_backup_dynamic_mechanism_state(struct net_device *dev);
+extern  void    dm_change_dynamic_initgain_thresh(struct net_device *dev,
+                                                                u32             dm_type,
+                                                                u32             dm_value);
+extern  void    DM_ChangeFsyncSetting(struct net_device *dev,
+                                                                                                s32             DM_Type,
+                                                                                                s32             DM_Value);
+extern  void dm_force_tx_fw_info(struct net_device *dev,
+                                                                                u32             force_type,
+                                                                                u32             force_value);
+extern  void    dm_init_edca_turbo(struct net_device *dev);
+extern  void    dm_rf_operation_test_callback(unsigned long data);
+extern  void    dm_rf_pathcheck_workitemcallback(void *data);
+extern  void dm_fsync_timer_callback(unsigned long data);
+#if 0
+extern  bool    dm_check_lbus_status(struct net_device *dev);
+#endif
+extern  void dm_check_fsync(struct net_device *dev);
+extern  void    dm_shadow_init(struct net_device *dev);
+extern  void dm_initialize_txpower_tracking(struct net_device *dev);
+
+#if (defined RTL8192E || defined RTL8192SE)
+extern  void    dm_CheckRfCtrlGPIO(void *data);
+#endif
+
+#ifdef RTL8192SE
+extern void Power_DomainInit92SE(struct net_device *dev);
+#endif
+#endif	/*__R8192UDM_H__ */
+
+
+/* End of r8192U_dm.h */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_endianfree.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_endianfree.h
@@ -0,0 +1,156 @@
+#ifndef __INC_ENDIANFREE_H
+#define __INC_ENDIANFREE_H
+
+/*
+ *	Call endian free function when
+ *		1. Read/write packet content.
+ *		2. Before write integer to IO.
+ *		3. After read integer from IO.
+ */
+
+#define __MACHINE_LITTLE_ENDIAN 1234    /* LSB first: i386, vax */
+#define __MACHINE_BIG_ENDIAN    4321    /* MSB first: 68000, ibm, net, ppc */
+
+#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN
+
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define EF1Byte(_val)				((u8)(_val))
+#define EF2Byte(_val)				((u16)(_val))
+#define EF4Byte(_val)				((u32)(_val))
+
+#else
+#define EF1Byte(_val)				((u8)(_val))
+#define EF2Byte(_val)				(((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8))
+#define EF4Byte(_val)				(((((u32)(_val))&0x000000ff)<<24)|\
+						((((u32)(_val))&0x0000ff00)<<8)|\
+						((((u32)(_val))&0x00ff0000)>>8)|\
+						((((u32)(_val))&0xff000000)>>24))
+#endif
+
+#define ReadEF1Byte(_ptr)		EF1Byte(*((u8 *)(_ptr)))
+#define ReadEF2Byte(_ptr)		EF2Byte(*((u16 *)(_ptr)))
+#define ReadEF4Byte(_ptr)		EF4Byte(*((u32 *)(_ptr)))
+
+#define WriteEF1Byte(_ptr, _val)	(*((u8 *)(_ptr)))=EF1Byte(_val)
+#define WriteEF2Byte(_ptr, _val)	(*((u16 *)(_ptr)))=EF2Byte(_val)
+#define WriteEF4Byte(_ptr, _val)	(*((u32 *)(_ptr)))=EF4Byte(_val)									
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define H2N1BYTE(_val)	((u8)(_val))
+#define H2N2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
+			((((u16)(_val))&0xff00)>>8))
+#define H2N4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
+			((((u32)(_val))&0x0000ff00)<<8)	|\
+			((((u32)(_val))&0x00ff0000)>>8)	|\
+			((((u32)(_val))&0xff000000)>>24))
+#else
+#define H2N1BYTE(_val)			((u8)(_val))
+#define H2N2BYTE(_val)			((u16)(_val))
+#define H2N4BYTE(_val)			((u32)(_val))
+#endif
+
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define N2H1BYTE(_val)	((u8)(_val))
+#define N2H2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
+			((((u16)(_val))&0xff00)>>8))
+#define N2H4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
+			((((u32)(_val))&0x0000ff00)<<8)	|\
+			((((u32)(_val))&0x00ff0000)>>8)	|\
+			((((u32)(_val))&0xff000000)>>24))
+#else
+#define N2H1BYTE(_val)			((u8)(_val))
+#define N2H2BYTE(_val)			((u16)(_val))
+#define N2H4BYTE(_val)			((u32)(_val))
+#endif
+
+#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen)))
+#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset)) 
+
+#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart))))
+
+#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_32(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P4BYTE_TO_HOST_4BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u32 *)(__pStart)) = \
+	EF4Byte( \
+	LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	| \
+	( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \
+       );
+
+
+#define BIT_LEN_MASK_16(__BitLen) \
+	(0xFFFF >> (16 - (__BitLen)))
+
+#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \
+	(BIT_LEN_MASK_16(__BitLen) << (__BitOffset))
+
+#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
+	(EF2Byte(*((u16 *)(__pStart))))
+
+#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_16(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u16 *)(__pStart)) = \
+	EF2Byte( \
+		LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+		| \
+		( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \
+       );
+
+#define BIT_LEN_MASK_8(__BitLen) \
+	(0xFF >> (8 - (__BitLen)))
+
+#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \
+	(BIT_LEN_MASK_8(__BitLen) << (__BitOffset))
+
+#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
+	(EF1Byte(*((u8 *)(__pStart))))
+
+#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_8(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u8 *)(__pStart)) = \
+	EF1Byte( \
+		LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+		| \
+		( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \
+       );
+
+#define	N_BYTE_ALIGMENT(__Value, __Aligment) ((__Aligment == 1) ? (__Value) : (((__Value + __Aligment - 1) / __Aligment) * __Aligment))
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_eeprom.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_eeprom.c
@@ -0,0 +1,140 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "rtl_eeprom.h"
+
+void eprom_cs(struct net_device *dev, short bit)
+{
+	if(bit)
+		write_nic_byte(dev, EPROM_CMD,
+			       (1<<EPROM_CS_SHIFT) | \
+			       read_nic_byte(dev, EPROM_CMD)); 
+	else
+		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
+			       &~(1<<EPROM_CS_SHIFT)); 
+
+	udelay(EPROM_DELAY);
+}
+
+
+void eprom_ck_cycle(struct net_device *dev)
+{
+	write_nic_byte(dev, EPROM_CMD,
+		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev,EPROM_CMD)); 
+	udelay(EPROM_DELAY);
+	write_nic_byte(dev, EPROM_CMD, 
+		       read_nic_byte(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT)); 
+	udelay(EPROM_DELAY);
+}
+
+
+void eprom_w(struct net_device *dev,short bit)
+{
+	if(bit)
+		write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
+			       read_nic_byte(dev,EPROM_CMD)); 
+	else
+		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev,EPROM_CMD)\
+			       &~(1<<EPROM_W_SHIFT)); 
+
+	udelay(EPROM_DELAY);
+}
+
+
+short eprom_r(struct net_device *dev)
+{
+	short bit;
+
+	bit=(read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
+	udelay(EPROM_DELAY);
+
+	if(bit) return 1;
+	return 0;
+}
+
+
+void eprom_send_bits_string(struct net_device *dev, short b[], int len)
+{
+	int i;
+	
+	for(i=0; i<len; i++){
+		eprom_w(dev, b[i]);
+		eprom_ck_cycle(dev);
+	}
+}
+
+
+u32 eprom_read(struct net_device *dev, u32 addr)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	short read_cmd[]={1,1,0};
+	short addr_str[8];
+	int i;
+	int addr_len;
+	u32 ret;
+
+	ret=0;
+	write_nic_byte(dev, EPROM_CMD,
+		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT)); 
+	udelay(EPROM_DELAY);
+	
+	if (priv->epromtype==EEPROM_93C56){
+		addr_str[7]=addr & 1;
+		addr_str[6]=addr & (1<<1);
+		addr_str[5]=addr & (1<<2);
+		addr_str[4]=addr & (1<<3);
+		addr_str[3]=addr & (1<<4);
+		addr_str[2]=addr & (1<<5);
+		addr_str[1]=addr & (1<<6);
+		addr_str[0]=addr & (1<<7);
+		addr_len=8;
+	}else{
+		addr_str[5]=addr & 1;
+		addr_str[4]=addr & (1<<1);
+		addr_str[3]=addr & (1<<2);
+		addr_str[2]=addr & (1<<3);
+		addr_str[1]=addr & (1<<4);
+		addr_str[0]=addr & (1<<5);
+		addr_len=6;
+	}
+	eprom_cs(dev, 1);
+	eprom_ck_cycle(dev);
+	eprom_send_bits_string(dev, read_cmd, 3);
+	eprom_send_bits_string(dev, addr_str, addr_len);
+
+	eprom_w(dev, 0); 
+	
+	for(i=0;i<16;i++){	
+		eprom_ck_cycle(dev);
+		ret |= (eprom_r(dev)<<(15-i));
+	}
+	
+	eprom_cs(dev, 0);
+	eprom_ck_cycle(dev);
+
+	write_nic_byte(dev, EPROM_CMD,
+		       (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); 
+	return ret;
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_mesh.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_mesh.c
@@ -0,0 +1,371 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifdef _RTL8192_EXT_PATCH_
+
+#include <asm/uaccess.h>
+#include <linux/pci.h>
+
+#include "rtl_wx.h"
+#include "rtl_core.h"
+#include "rtl_dm.h"
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#include "rtl8192s/r8192S_Efuse.h"
+#include "../../mshclass/msh_class.h"
+
+int meshdev_up(struct net_device *meshdev,bool is_silent_reset)
+{
+	struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(mpriv->priv->rtllib->PowerSaveControl));
+        bool init_status;
+        struct net_device *dev = ieee->dev; 
+	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
+
+	mpriv->priv->up_first_time = 0;
+	mpriv->rtllib->iw_mode = IW_MODE_MESH;   
+	if(mpriv->priv->mesh_up){
+		RT_TRACE(COMP_INIT,"%s():mesh is up,return\n",__FUNCTION__);
+		return -1;
+	}
+#ifdef RTL8192SE        
+        mpriv->priv->ReceiveConfig =
+        RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/
+        RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV |
+       RCR_AICV | RCR_ACRC32    |                               
+        RCR_AB          | RCR_AM                |                               
+        RCR_APM         |                                                               
+        /*RCR_AAP               |*/                                                     
+        RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF |      
+        (mpriv->priv->EarlyRxThreshold<<RCR_FIFO_OFFSET)       ;
+
+#else
+        mpriv->priv->ReceiveConfig = RCR_ADD3  |
+                RCR_AMF | RCR_ADF |             
+                RCR_AICV |                      
+                RCR_AB | RCR_AM | RCR_APM |     
+                RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
+                ((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
+
+#endif
+
+	if(!mpriv->priv->up) {
+		RT_TRACE(COMP_INIT, "Bringing up iface");
+		mpriv->priv->bfirst_init = true;
+		init_status = mpriv->priv->ops->initialize_adapter(dev);
+		if(init_status != true) {
+			RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+			return -1;
+		}
+		RT_TRACE(COMP_INIT, "start adapter finished\n");
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+		printk("==>%s():priv->up is 0\n",__FUNCTION__);
+		mpriv->rtllib->ieee_up=1;		
+		mpriv->priv->bfirst_init = false;
+#ifdef ENABLE_GPIO_RADIO_CTL
+		if(mpriv->priv->polling_timer_on == 0){
+			check_rfctrl_gpio_timer((unsigned long)dev);
+		}
+#endif
+		if(!is_silent_reset){
+			mpriv->rtllib->current_network.channel = INIT_DEFAULT_CHAN;
+			mpriv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN;
+			if(mpriv->priv->mshobj->ext_patch_r819x_wx_set_mesh_chan) 
+				mpriv->priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,INIT_DEFAULT_CHAN);          
+			if(mpriv->priv->mshobj->ext_patch_r819x_wx_set_channel)
+			{
+				mpriv->priv->mshobj->ext_patch_r819x_wx_set_channel(mpriv->rtllib, INIT_DEFAULT_CHAN);
+			}
+			printk("%s():set chan %d\n",__FUNCTION__,INIT_DEFAULT_CHAN);
+			mpriv->rtllib->set_chan(dev, INIT_DEFAULT_CHAN);
+		}
+		dm_InitRateAdaptiveMask(dev);
+		watch_dog_timer_callback((unsigned long) dev);
+	
+	} else {
+		rtllib_stop_scan(ieee);
+		msleep(1000);
+	}
+        if(!ieee->mesh_started) {
+#ifdef RTL8192E
+            if(ieee->eRFPowerState!=eRfOn)
+                MgntActSet_RF_State(dev, eRfOn, ieee->RfOffReason);	
+#endif
+            if(mpriv->priv->mshobj && mpriv->priv->mshobj->ext_patch_rtl819x_up )
+                mpriv->priv->mshobj->ext_patch_rtl819x_up(mpriv->priv->mshobj);
+
+
+            if(!netif_queue_stopped(meshdev))
+                netif_start_queue(meshdev);
+            else
+                netif_wake_queue(meshdev);
+
+            rtllib_reset_queue(ieee);
+	}
+		
+	mpriv->priv->mesh_up = 1;
+
+	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
+	return 0;
+}
+
+int meshdev_down(struct net_device *meshdev)
+{
+	struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void*)ieee->priv;
+	struct net_device *dev = ieee->dev;
+	unsigned long flags = 0;
+	u8 RFInProgressTimeOut = 0;
+	if(priv->mesh_up == 0) {
+		RT_TRACE(COMP_ERR,"%s():ERR!!! mesh is already down\n",__FUNCTION__)
+		return -1;
+	}
+
+	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
+	
+	if (netif_running(meshdev)) {
+		netif_stop_queue(meshdev);
+	}
+
+	if(!priv->up)
+	{
+        	priv->bDriverIsGoingToUnload = true;	
+		ieee->ieee_up = 0;  
+		rtl8192_irq_disable(dev);
+		rtl8192_cancel_deferred_work(priv);
+#ifndef RTL8190P
+		cancel_delayed_work(&priv->rtllib->hw_wakeup_wq);
+#endif
+		deinit_hal_dm(dev);
+		del_timer_sync(&priv->watch_dog_timer);	
+		rtllib_softmac_stop_protocol(ieee, 1, true);
+
+		SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		while(priv->RFChangeInProgress)
+		{
+			SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+			if(RFInProgressTimeOut > 100)
+			{
+				SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+				break;
+			}
+			printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__);
+			mdelay(1);
+			RFInProgressTimeOut ++;
+			SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		}
+		priv->RFChangeInProgress = true;
+		SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		priv->ops->stop_adapter(dev, false);
+		SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		priv->RFChangeInProgress = false;
+		SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		udelay(100);
+		memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list));
+		priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN;
+#ifdef CONFIG_ASPM_OR_D3
+		RT_ENABLE_ASPM(dev);
+#endif
+		memset(&ieee->current_mesh_network, 0 , offsetof(struct rtllib_network, list));
+		priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN;
+		ieee->mesh_state = RTLLIB_NOLINK;
+	} else {
+		rtllib_softmac_stop_protocol(ieee, 1, true);
+		memset(&ieee->current_mesh_network, 0 , offsetof(struct rtllib_network, list));
+		if((ieee->current_network.channel > 0) && (ieee->current_network.channel < 15))
+			priv->rtllib->current_mesh_network.channel = ieee->current_network.channel;
+		else
+			priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN;
+				
+		ieee->mesh_state = RTLLIB_NOLINK;
+		ieee->iw_mode = IW_MODE_INFRA;
+	}
+	priv->mesh_up = 0;  
+	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
+
+	return 0;
+}
+
+static int meshdev_open(struct net_device *meshdev)
+{
+	struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void*)ieee->priv;
+	int ret;
+	
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = meshdev_up(meshdev,false);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+
+	return ret;
+}
+
+static int meshdev_close(struct net_device *meshdev)
+{
+	struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	int ret;
+	
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = meshdev_down(meshdev);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	
+	return ret;
+}
+
+extern int meshdev_wx_mesh(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra);
+static int meshdev_ioctl(struct net_device *meshdev, struct ifreq *rq, int cmd)
+{
+	struct iwreq *wrq = (struct iwreq *)rq;
+	int ret = -1;
+	if(cmd == 0x8BEE)
+	{
+		ret = meshdev_wx_mesh(meshdev, NULL, &(wrq->u), wrq->u.data.pointer);
+	}
+	return ret;
+}
+
+struct net_device_stats *meshdev_stats(struct net_device *meshdev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 
+	return &((struct meshdev_priv*)netdev_priv(meshdev))->stats;
+#else
+	return &((struct meshdev_priv*)meshdev->priv)->stats;
+#endif
+}
+
+static int meshdev_tx(struct sk_buff *skb, struct net_device *meshdev)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device * ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	memset(skb->cb,0,sizeof(skb->cb));
+	
+	return rtllib_mesh_xmit(skb, dev);	
+}
+
+static void meshdev_tx_timeout(struct net_device *meshdev)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device * ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	rtl8192_tx_timeout(dev);	
+}
+
+#ifdef HAVE_NET_DEVICE_OPS
+static const struct net_device_ops mesh_netdev_ops = {
+	.ndo_open = meshdev_open,
+	.ndo_stop = meshdev_close,
+	.ndo_get_stats = meshdev_stats,
+	.ndo_tx_timeout = meshdev_tx_timeout,
+	.ndo_do_ioctl = meshdev_ioctl,
+	.ndo_start_xmit = meshdev_tx,
+};
+#endif
+
+void meshdev_init(struct net_device* meshdev)
+{
+	struct meshdev_priv *mpriv;
+	ether_setup(meshdev);
+
+#ifdef HAVE_NET_DEVICE_OPS
+	meshdev->netdev_ops = &mesh_netdev_ops;
+#else	
+	meshdev->open = meshdev_open;
+	meshdev->stop = meshdev_close;
+	meshdev->tx_timeout = meshdev_tx_timeout;
+	meshdev->do_ioctl = meshdev_ioctl;
+	meshdev->get_stats = meshdev_stats;
+	meshdev->hard_start_xmit = meshdev_tx;
+#endif	
+	meshdev->wireless_handlers = &meshdev_wx_handlers_def;
+	meshdev->destructor = free_netdev;
+	meshdev->watchdog_timeo = HZ*3;	
+	meshdev->type = ARPHRD_ETHER; 
+	memset(meshdev->broadcast,0xFF, ETH_ALEN);
+	
+	meshdev->watchdog_timeo = 3 * HZ;
+
+	mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	memset(mpriv, 0, sizeof(struct meshdev_priv));
+
+	return;
+}
+
+int meshdev_update_ext_chnl_offset_as_client(void *data)
+{
+	struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device,
+			ext_update_extchnloffset_wq);
+	struct r8192_priv *priv = (void *)ieee->priv;
+	struct net_device *dev = ieee->dev;
+	struct mshclass *mshobj= priv->mshobj;
+	u8 updateBW = 0;
+	u8 bserverHT = 0;
+
+	updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT);
+	printk("$$$$$$%s(): Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n",
+			__FUNCTION__,ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT);
+	if (updateBW == 1) {
+		if (bserverHT == 0) {
+			printk("===>server is not HT supported,set 20M\n");
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);  
+		} else {
+			printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",
+					ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset);
+			if (ieee->pHTInfo->bCurBW40MHz)
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset);  
+			else
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset);  
+		}
+	} else {
+		printk("===>there is no same hostname server, ERR!!!\n");
+		return -1;
+	}
+	return 0;
+}
+
+int meshdev_start_mesh_protocol_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device,
+			ext_start_mesh_protocol_wq);
+
+	ieee->set_chan(ieee->dev, ieee->current_mesh_network.channel);
+	if(ieee->pHTInfo->bCurBW40MHz)
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+	else
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+
+	rtllib_start_mesh_protocol(ieee);
+
+	return 0;
+}
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_mesh.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_mesh.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifdef _RTL8192_EXT_PATCH_
+#ifndef _RTL_MESH_H
+#define _RTL_MESH_H
+
+struct net_device;
+struct net_device_stats;
+
+int meshdev_up(struct net_device *meshdev,bool is_silent_reset);
+int meshdev_down(struct net_device *meshdev);
+struct net_device_stats *meshdev_stats(struct net_device *meshdev);
+void meshdev_init(struct net_device* meshdev);
+
+int meshdev_update_ext_chnl_offset_as_client(void *data);
+int meshdev_start_mesh_protocol_wq(void *data);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_ps.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_ps.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#ifndef _RTL_PS_H
+#define _RTL_PS_H
+
+#include <linux/types.h>
+struct net_device;
+
+#define RT_CHECK_FOR_HANG_PERIOD 2
+#define INIT_DEFAULT_CHAN 	 1
+
+#if defined CONFIG_ASPM_OR_D3
+#define RT_DISABLE_ASPM(dev)            PlatformDisableASPM(dev)
+#define RT_ENABLE_ASPM(dev)             PlatformEnableASPM(dev)
+#define RT_ENTER_D3(dev, _bTempSetting) PlatformSetPMCSR(dev, 0x03, _bTempSetting)
+#define RT_LEAVE_D3(dev, _bTempSetting) PlatformSetPMCSR(dev, 0, _bTempSetting)
+bool PlatformEnable92CEBackDoor(struct net_device *dev);
+void PlatformDisableASPM(struct net_device *dev);
+void PlatformEnableASPM(struct net_device *dev);
+u32 PlatformResetPciSpace(struct net_device *dev,u8 Value);
+#endif
+
+#if defined(RTL8192E) || defined(RTL8192SE) || defined RTL8192CE
+void rtl8192_hw_wakeup(struct net_device *dev);
+void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl);
+void rtllib_ips_leave_wq(struct net_device *dev);
+void rtllib_ips_leave(struct net_device *dev);
+void IPSLeave_wq (void *data);
+#endif
+
+#ifdef ENABLE_IPS
+void IPSEnter(struct net_device *dev);
+void IPSLeave(struct net_device *dev);
+#endif
+
+#ifdef ENABLE_LPS
+void LeisurePSEnter(struct net_device *dev);
+void LeisurePSLeave(struct net_device *dev);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_core.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_core.c
@@ -0,0 +1,5975 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#undef LOOP_TEST
+#undef RX_DONT_PASS_UL
+#undef DEBUG_EPROM
+#undef DEBUG_RX_VERBOSE
+#undef DUMMY_RX
+#undef DEBUG_ZERO_RX
+#undef DEBUG_RX_SKB
+#undef DEBUG_TX_FRAG
+#undef DEBUG_RX_FRAG
+#undef DEBUG_TX_FILLDESC
+#undef DEBUG_TX
+#undef DEBUG_IRQ
+#undef DEBUG_RX
+#undef DEBUG_RXALLOC
+#undef DEBUG_REGISTERS
+#undef DEBUG_RING
+#undef DEBUG_IRQ_TASKLET
+#undef DEBUG_TX_ALLOC
+#undef DEBUG_TX_DESC
+
+#include <asm/uaccess.h>
+#include <linux/pci.h>
+#include "rtl_core.h"
+#if defined RTL8192CE
+#include "rtl8192c/r8192C_phy.h" 
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#include "rtl8192c/r8192C_Efuse.h"
+#include "rtl8192c/r8192C_dm.h"
+#elif defined RTL8192SE
+#include "rtl8192s/r8192S_phy.h" 
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#include "rtl8192s/r8192S_Efuse.h"
+#else
+#include "rtl8192e/r8192E_phy.h" 
+#include "rtl8192e/r8192E_phyreg.h"
+#include "rtl8192e/r8190P_rtl8256.h" 
+#include "rtl8192e/r8192E_cmdpkt.h"
+#endif
+
+#include "rtl_wx.h"
+#ifndef RTL8192CE
+#include "rtl_dm.h"
+#endif
+
+#ifdef CONFIG_PM_RTL
+#include "rtl_pm.h"
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+#include "../../mshclass/msh_class.h"
+#include "rtl_mesh.h"
+#endif
+
+#ifdef RTL8192S_WAPI_SUPPORT
+#include "../../rtllib/wapi.h"
+#include "../../rtllib/wapi_interface.h"
+#endif
+
+int hwwep = 1; 
+static int channels = 0x3fff;
+#ifdef _RTL8192_EXT_PATCH_
+char* ifname = "ra%d";
+#else
+char* ifname = "wlan%d";
+#endif
+
+u32 rt_global_debug_component = \
+						COMP_ERR ; 
+
+#ifdef RTL8192SE
+struct rtl819x_ops rtl8192se_ops = {
+	.nic_type = NIC_8192SE,
+	.get_eeprom_size 			= rtl8192se_get_eeprom_size,
+	.init_adapter_variable 		= rtl8192se_InitializeVariables,
+	.init_before_adapter_start 	= MacConfigBeforeFwDownload,
+	.initialize_adapter 		= rtl8192se_adapter_start,
+	.link_change 			= rtl8192se_link_change,
+	.tx_fill_descriptor 		= rtl8192se_tx_fill_desc,
+	.tx_fill_cmd_descriptor 	= rtl8192se_tx_fill_cmd_desc,
+	.rx_query_status_descriptor 	= rtl8192se_rx_query_status_desc,
+	.rx_command_packet_handler = rtl8192se_RxCommandPacketHandle,
+	.stop_adapter 				= rtl8192se_halt_adapter,
+	.update_ratr_table 			= rtl8192se_update_ratr_table,
+	.irq_enable				= rtl8192se_EnableInterrupt,
+	.irq_disable				= rtl8192se_DisableInterrupt,
+	.irq_clear					= rtl8192se_ClearInterrupt,
+	.rx_enable				= rtl8192se_enable_rx,
+	.tx_enable				= rtl8192se_enable_tx,
+	.interrupt_recognized		= rtl8192se_interrupt_recognized,
+	.TxCheckStuckHandler		= rtl8192se_HalTxCheckStuck,
+	.RxCheckStuckHandler		= rtl8192se_HalRxCheckStuck,
+};
+#elif defined RTL8192CE
+struct rtl819x_ops rtl8192ce_ops = {
+	.nic_type 					= NIC_8192CE,
+	.get_eeprom_size 			= rtl8192ce_get_eeprom_size,
+	.init_adapter_variable 		= rtl8192ce_InitializeVariables,
+	.initialize_adapter 			= rtl8192ce_adapter_start,
+	.link_change 				= rtl8192ce_link_change,
+	.tx_fill_descriptor 			= rtl8192ce_tx_fill_desc,
+	.tx_fill_cmd_descriptor 		= rtl8192ce_tx_fill_cmd_desc,
+	.rx_query_status_descriptor 	= rtl8192ce_rx_query_status_desc,
+	.rx_command_packet_handler = NULL,
+	.stop_adapter 				= rtl8192ce_halt_adapter,
+	.update_ratr_table 			= rtl8192ce_UpdateHalRATRTable,
+	.irq_enable				= rtl8192ce_EnableInterrupt,
+	.irq_disable				= rtl8192ce_DisableInterrupt,
+	.irq_clear					= rtl8192ce_ClearInterrupt,
+	.rx_enable				= rtl8192ce_enable_rx,
+	.tx_enable				= rtl8192ce_enable_tx,
+	.interrupt_recognized		= rtl8192ce_interrupt_recognized,
+	.TxCheckStuckHandler		= rtl8192ce_HalTxCheckStuck,
+	.RxCheckStuckHandler		= rtl8192ce_HalRxCheckStuck,
+};
+#else
+struct rtl819x_ops rtl819xp_ops = {
+	.nic_type 					= NIC_UNKNOWN,
+	.get_eeprom_size 			= rtl8192_get_eeprom_size,
+	.init_adapter_variable 		= rtl8192_InitializeVariables,
+	.initialize_adapter 			= rtl8192_adapter_start,
+	.link_change 				= rtl8192_link_change,
+	.tx_fill_descriptor 			= rtl8192_tx_fill_desc,
+	.tx_fill_cmd_descriptor 		= rtl8192_tx_fill_cmd_desc,
+	.rx_query_status_descriptor 	= rtl8192_rx_query_status_desc,
+	.rx_command_packet_handler = NULL,
+	.stop_adapter 				= rtl8192_halt_adapter,
+	.update_ratr_table 			= rtl8192_update_ratr_table,
+	.irq_enable				= rtl8192_EnableInterrupt,
+	.irq_disable				= rtl8192_DisableInterrupt,
+	.irq_clear					= rtl8192_ClearInterrupt,
+	.rx_enable				= rtl8192_enable_rx,
+	.tx_enable				= rtl8192_enable_tx,
+	.interrupt_recognized		= rtl8192_interrupt_recognized,
+	.TxCheckStuckHandler		= rtl8192_HalTxCheckStuck,
+	.RxCheckStuckHandler		= rtl8192_HalRxCheckStuck,
+};
+#endif
+
+static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = {
+#ifdef RTL8190P
+	/* Realtek */
+	/* Dlink */
+	{RTL_PCI_DEVICE(0x10ec, 0x8190, rtl819xp_ops)},
+	/* Corega */
+	{RTL_PCI_DEVICE(0x07aa, 0x0045, rtl819xp_ops)},
+	{RTL_PCI_DEVICE(0x07aa, 0x0046, rtl819xp_ops)},
+#elif defined(RTL8192E)
+	/* Realtek */
+	{RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
+	/* Corega */
+	{RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
+	{RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},
+#elif defined(RTL8192SE)	/*8192SE*/
+	{RTL_PCI_DEVICE(0x10ec, 0x8171, rtl8192se_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8172, rtl8192se_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8173, rtl8192se_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8174, rtl8192se_ops)},
+#elif defined(RTL8192CE)	/*8192CE*/
+	{RTL_PCI_DEVICE(0x10ec, 0x8191, rtl8192ce_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8178, rtl8192ce_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8177, rtl8192ce_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x8176, rtl8192ce_ops)},
+	{RTL_PCI_DEVICE(0x10ec, 0x092D, rtl8192ce_ops)},
+#endif
+	{}
+};
+MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
+
+static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
+			 const struct pci_device_id *id);
+static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
+
+static struct pci_driver rtl8192_pci_driver = {
+	.name		= DRV_NAME,	          /* Driver name   */
+	.id_table	= rtl8192_pci_id_tbl,	          /* PCI_ID table  */
+	.probe		= rtl8192_pci_probe,	          /* probe fn      */
+	.remove		= __devexit_p(rtl8192_pci_disconnect),	  /* remove fn     */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)
+#ifdef CONFIG_PM_RTL
+	.suspend	= rtl8192E_suspend,	          /* PM suspend fn */
+	.resume		= rtl8192E_resume,                 /* PM resume fn  */
+#else
+	.suspend	= NULL,			          /* PM suspend fn */
+	.resume      	= NULL,			          /* PM resume fn  */
+#endif
+#endif
+};
+
+/****************************************************************************
+   -----------------------------IO STUFF-------------------------
+*****************************************************************************/
+bool
+PlatformIOCheckPageLegalAndGetRegMask(
+	u32 	u4bPage,
+	u8*	pu1bPageMask
+)
+{
+	bool		bReturn = false;
+	*pu1bPageMask = 0xfe;
+
+	switch(u4bPage)
+	{
+		case 1: case 2: case 3: case 4:	
+		case 8: case 9: case 10: case 12: case 13:	
+			bReturn = true;
+			*pu1bPageMask = 0xf0;
+			break;
+			
+		default:
+			bReturn = false;
+			break;
+	}
+
+	return bReturn;
+}
+
+void write_nic_io_byte(struct net_device *dev, int x,u8 y)
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+
+	if(u4bPage == 0)
+	{
+		outb(y&0xff,dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			write_nic_io_byte(dev, (x & 0xff), y);
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	
+        
+}
+
+void write_nic_io_word(struct net_device *dev, int x,u16 y)
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+
+	if(u4bPage == 0)
+	{
+		outw(y,dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			write_nic_io_word(dev, (x & 0xff), y);
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	        
+}
+
+void write_nic_io_dword(struct net_device *dev, int x,u32 y)
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+
+	if(u4bPage == 0)
+	{
+		outl(y,dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			write_nic_io_dword(dev, (x & 0xff), y);
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	        
+}
+u8 read_nic_io_byte(struct net_device *dev, int x) 
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+	u8	Data = 0;
+
+	if(u4bPage == 0)
+	{
+		return 0xff&inb(dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			Data = read_nic_io_byte(dev, (x & 0xff));
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	
+	return Data;
+}
+
+u16 read_nic_io_word(struct net_device *dev, int x) 
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+	u16	Data = 0;
+
+	if(u4bPage == 0)
+	{
+		return inw(dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			Data = read_nic_io_word(dev, (x & 0xff));
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	        
+	return Data;
+}
+
+u32 read_nic_io_dword(struct net_device *dev, int x) 
+{
+	u32 u4bPage = (x >> 8);
+	u8 u1PageMask = 0;
+	bool	bIsLegalPage = false;
+	u32	Data = 0;
+
+	if(u4bPage == 0)
+	{
+		return inl(dev->base_addr +x);
+	}else
+	{
+		bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask);
+		if(bIsLegalPage)
+		{
+			u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+			write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); 
+			Data = read_nic_io_dword(dev, (x & 0xff));
+			write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); 
+			
+		}else
+		{
+			;
+		}
+	}
+	
+	return Data;
+}
+
+u8 read_nic_byte(struct net_device *dev, int x) 
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	return read_nic_io_byte(dev, x);
+#else
+        return 0xff&readb((u8*)dev->mem_start +x);
+#endif
+}
+
+u32 read_nic_dword(struct net_device *dev, int x) 
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	return read_nic_io_dword(dev, x);
+#else
+        return readl((u8*)dev->mem_start +x);
+#endif
+}
+
+u16 read_nic_word(struct net_device *dev, int x) 
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	return read_nic_io_word(dev, x);
+#else
+        return readw((u8*)dev->mem_start +x);
+#endif
+}
+
+void write_nic_byte(struct net_device *dev, int x,u8 y)
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	write_nic_io_byte(dev, x, y);
+#else
+        writeb(y,(u8*)dev->mem_start +x);
+#if !(defined RTL8192SE || defined RTL8192CE)	
+	udelay(20);
+#endif	
+#endif
+}
+
+void write_nic_dword(struct net_device *dev, int x,u32 y)
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	write_nic_io_dword(dev, x, y);
+#else
+        writel(y,(u8*)dev->mem_start +x);
+#if !(defined RTL8192SE || defined RTL8192CE)	
+	udelay(20);
+#endif	
+#endif
+}
+
+void write_nic_word(struct net_device *dev, int x,u16 y) 
+{
+#ifdef CONFIG_RTL8192_IO_MAP
+	write_nic_io_word(dev, x, y);
+#else
+        writew(y,(u8*)dev->mem_start +x);
+#if !(defined RTL8192SE || defined RTL8192CE)	
+	udelay(20);
+#endif	
+#endif
+}
+
+/****************************************************************************
+   -----------------------------GENERAL FUNCTION-------------------------
+*****************************************************************************/
+
+void
+MgntDisconnectIBSS(
+	struct net_device* dev
+) 
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	OpMode;
+	u8			i;
+	bool	bFilterOutNonAssociatedBSSID = false;
+
+
+	priv->rtllib->state = RTLLIB_NOLINK;
+
+	for(i=0;i<6;i++)  priv->rtllib->current_network.bssid[i]= 0x55;
+
+	priv->OpMode = RT_OP_MODE_NO_LINK;
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_BSSID, priv->rtllib->current_network.bssid);
+	OpMode = RT_OP_MODE_NO_LINK;
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
+	rtllib_stop_send_beacons(priv->rtllib);
+	
+	bFilterOutNonAssociatedBSSID = false;
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID));
+	notify_wx_assoc_event(priv->rtllib);
+
+}
+
+void
+MlmeDisassociateRequest(
+	struct net_device* dev,
+	u8* 		asSta,
+	u8		asRsn
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 i;
+	u8	OpMode;
+
+	RemovePeerTS(priv->rtllib, asSta);
+	
+	
+	if(memcpy(priv->rtllib->current_network.bssid,asSta,6) == 0)
+	{
+		priv->rtllib->state = RTLLIB_NOLINK;
+		
+		for(i=0;i<6;i++)  priv->rtllib->current_network.bssid[i] = 0x22;
+		OpMode = RT_OP_MODE_NO_LINK;
+		priv->OpMode = RT_OP_MODE_NO_LINK;
+		priv->rtllib->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, (u8 *)(&OpMode) );
+		rtllib_disassociate(priv->rtllib);
+
+		priv->rtllib->SetHwRegHandler(dev, HW_VAR_BSSID, priv->rtllib->current_network.bssid);
+		
+	}
+
+}
+
+void
+MgntDisconnectAP(
+	struct net_device* dev,
+	u8 asRsn
+) 
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool bFilterOutNonAssociatedBSSID = false;
+
+
+#ifdef TO_DO
+	if(   pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch ||
+		(pMgntInfo->bAPSuportCCKM && pMgntInfo->bCCX8021xenable) )	
+	{
+		SecClearAllKeys(dev);
+		RT_TRACE(COMP_SEC, DBG_LOUD,("======>CCKM clear key..."))
+	}
+#endif
+	bFilterOutNonAssociatedBSSID = false;
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID));
+	MlmeDisassociateRequest( dev, priv->rtllib->current_network.bssid, asRsn );
+
+	priv->rtllib->state = RTLLIB_NOLINK;
+}
+
+bool
+MgntDisconnect(
+	struct net_device* dev,
+	u8 asRsn
+) 
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+#if 1
+	if(priv->rtllib->ps != RTLLIB_PS_DISABLED)
+	{
+#ifndef RTL8190P
+                rtl8192_hw_wakeup(dev);
+#endif
+	}
+#endif
+#ifdef TO_DO
+	if(pMgntInfo->mActingAsAp)
+	{
+		RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> AP_DisassociateAllStation\n"));
+		AP_DisassociateAllStation(dev, unspec_reason);
+		return true;
+	}	
+#endif
+
+	if( priv->rtllib->state == RTLLIB_LINKED )
+	{
+		if( priv->rtllib->iw_mode == IW_MODE_ADHOC )
+		{
+			MgntDisconnectIBSS(dev);
+		}
+#ifdef _RTL8192_EXT_PATCH_
+		if((priv->rtllib->iw_mode == IW_MODE_INFRA ) || ((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0)))
+#else
+		if( priv->rtllib->iw_mode == IW_MODE_INFRA )
+#endif
+		{
+#ifdef TO_DO_LIST
+			SecClearAllKeys(Adapter); 
+#endif
+			MgntDisconnectAP(dev, asRsn);
+		}
+
+	}
+
+	return true;
+}
+bool
+MgntActSet_RF_State(
+	struct net_device* dev,
+	RT_RF_POWER_STATE	StateToSet,
+	RT_RF_CHANGE_SOURCE ChangeSource
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device * ieee = priv->rtllib;
+	bool 			bActionAllowed = false; 
+	bool 			bConnectBySSID = false;
+	RT_RF_POWER_STATE	rtState;
+	u16			RFWaitCounter = 0;
+	unsigned long flag;
+	RT_TRACE((COMP_PS | COMP_RF), "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet);
+
+
+	while(true)
+	{
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		if(priv->RFChangeInProgress)
+		{
+			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+			RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet);
+			printk("MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet);
+			#if 1	
+			while(priv->RFChangeInProgress)
+			{
+				RFWaitCounter ++;
+				RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter);
+				mdelay(1);
+
+				if(RFWaitCounter > 100)
+				{
+					RT_TRACE(COMP_ERR, "MgntActSet_RF_State(): Wait too logn to set RF\n");
+					return false;
+				}
+			}
+			#endif
+		}
+		else
+		{
+			priv->RFChangeInProgress = true;
+			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+			break;
+		}
+	}
+
+	rtState = priv->rtllib->eRFPowerState;
+
+	switch(StateToSet) 
+	{
+	case eRfOn:
+
+		priv->rtllib->RfOffReason &= (~ChangeSource);
+
+		if((ChangeSource == RF_CHANGE_BY_HW) && (priv->bHwRadioOff == true)){
+			priv->bHwRadioOff = false;
+		}
+
+		if(! priv->rtllib->RfOffReason)
+		{
+			priv->rtllib->RfOffReason = 0;
+			bActionAllowed = true;
+
+			
+			if(rtState == eRfOff && ChangeSource >=RF_CHANGE_BY_HW )
+			{
+				bConnectBySSID = true;
+			}
+		}
+		else{
+			RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->rtllib->RfOffReason, ChangeSource);
+                }
+
+		break;
+
+	case eRfOff:
+
+		if((priv->rtllib->iw_mode == IW_MODE_INFRA) || (priv->rtllib->iw_mode == IW_MODE_ADHOC))
+		{
+			if ((priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) || (ChangeSource > RF_CHANGE_BY_IPS))
+			{
+				if(ieee->state == RTLLIB_LINKED)
+					priv->blinked_ingpio = true;
+				else
+					priv->blinked_ingpio = false;	
+				MgntDisconnect(dev, disas_lv_ss);
+	
+	
+				
+			}
+		}
+		if((ChangeSource == RF_CHANGE_BY_HW) && (priv->bHwRadioOff == false)){
+			priv->bHwRadioOff = true;
+		}
+		priv->rtllib->RfOffReason |= ChangeSource;
+		bActionAllowed = true;
+		break;
+
+	case eRfSleep:
+		priv->rtllib->RfOffReason |= ChangeSource;
+		bActionAllowed = true;
+		break;
+
+	default:
+		break;
+	}
+
+	if(bActionAllowed)
+	{
+		RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->rtllib->RfOffReason);
+		PHY_SetRFPowerState(dev, StateToSet);	
+		if(StateToSet == eRfOn) 
+		{				
+
+			if(bConnectBySSID && (priv->blinked_ingpio == true))
+			{				
+				queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0);
+				priv->blinked_ingpio = false;
+
+			}
+#ifdef _RTL8192_EXT_PATCH_
+			if(priv->rtllib->iw_mode == IW_MODE_MESH){
+				queue_work_rsl(ieee->wq, &ieee->ext_start_mesh_protocol_wq);
+
+			}
+#endif		
+		}
+		else if(StateToSet == eRfOff)
+		{		
+		}		
+	}
+	else
+	{
+		RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->rtllib->RfOffReason);
+	}
+
+	spin_lock_irqsave(&priv->rf_ps_lock,flag);
+	priv->RFChangeInProgress = false;
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+	
+	RT_TRACE((COMP_PS && COMP_RF), "<===MgntActSet_RF_State()\n");
+	return bActionAllowed;
+}
+
+
+short rtl8192_get_nic_desc_num(struct net_device *dev, int prio)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+    /* For now, we reserved two free descriptor as a safety boundary 
+     * between the tail and the head 
+     */
+    if((prio == MGNT_QUEUE) &&(skb_queue_len(&ring->queue)>10))
+    	printk("-----[%d]---------ring->idx=%d queue_len=%d---------\n",
+			prio,ring->idx, skb_queue_len(&ring->queue));
+    return skb_queue_len(&ring->queue);
+}
+
+short rtl8192_check_nic_enough_desc(struct net_device *dev, int prio)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+    if (ring->entries - skb_queue_len(&ring->queue) >= 2) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+void rtl8192_tx_timeout(struct net_device *dev)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+    schedule_work(&priv->reset_wq);
+#else
+    schedule_task(&priv->reset_wq);
+#endif
+    printk("TXTIMEOUT");
+}
+
+void rtl8192_irq_enable(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+	priv->irq_enabled = 1;
+	
+	priv->ops->irq_enable(dev);
+}
+
+void rtl8192_irq_disable(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+
+	priv->ops->irq_disable(dev);
+
+	priv->irq_enabled = 0;
+}
+
+void rtl8192_irq_clear(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+
+	priv->ops->irq_clear(dev);
+}
+
+
+void rtl8192_set_chan(struct net_device *dev,short ch)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+    RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch);	
+    if (priv->chan_forced)
+		return;
+
+    priv->chan = ch;
+
+
+#ifndef LOOP_TEST	
+
+
+    if (priv->rf_set_chan)
+        priv->rf_set_chan(dev,priv->chan);
+
+#ifdef CONFIG_FW_SETCHAN
+    priv->rtllib->SetFwCmdHandler(dev, FW_CMD_CHAN_SET);	
+#endif
+
+#endif
+}
+
+void rtl8192_update_cap(struct net_device* dev, u16 cap)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_network *net = &priv->rtllib->current_network;
+
+	priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
+	
+	{
+		bool		ShortPreamble;
+			
+		if(cap & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		{ 
+			{
+				ShortPreamble = true;
+				priv->rtllib->SetHwRegHandler( dev, HW_VAR_ACK_PREAMBLE, (unsigned char *)&ShortPreamble );
+			}
+		}
+		else
+		{ 
+			{
+				ShortPreamble = false;
+				priv->rtllib->SetHwRegHandler( dev, HW_VAR_ACK_PREAMBLE, (unsigned char *)&ShortPreamble );
+			}
+		}
+	}
+
+#ifdef RTL8192CE
+	if( net->mode & IEEE_G)
+#elif defined RTL8192SE || defined RTL8192E || defined RTL8190P
+	if (net->mode & (IEEE_G|IEEE_N_24G)) 
+#endif
+	{
+		u8	slot_time_val;
+		u8	CurSlotTime = priv->slot_time;
+		
+#ifdef RTL8192CE
+		if( (cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) && (!(priv->rtllib->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)))
+#elif defined RTL8192SE || defined RTL8192E || defined RTL8190P
+		if ((cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) && (!priv->rtllib->pHTInfo->bCurrentRT2RTLongSlotTime)) 
+#endif
+		{ 
+			if(CurSlotTime != SHORT_SLOT_TIME)
+			{
+				slot_time_val = SHORT_SLOT_TIME;
+				priv->rtllib->SetHwRegHandler( dev, HW_VAR_SLOT_TIME, &slot_time_val );
+			}
+		}
+		else
+		{ 
+			if(CurSlotTime != NON_SHORT_SLOT_TIME)
+			{
+				slot_time_val = NON_SHORT_SLOT_TIME;
+				priv->rtllib->SetHwRegHandler( dev, HW_VAR_SLOT_TIME, &slot_time_val );
+			}
+		}
+	}
+}
+
+static struct rtllib_qos_parameters def_qos_parameters = {
+        {3,3,3,3},
+        {7,7,7,7},
+        {2,2,2,2},
+        {0,0,0,0},
+        {0,0,0,0} 
+};
+
+void rtl8192_update_beacon(void *data)
+{
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
+	struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, update_beacon_wq.work);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+        struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+ 	struct rtllib_device* ieee = priv->rtllib;
+	struct rtllib_network* net = &ieee->current_network;
+
+	if (ieee->pHTInfo->bCurrentHTSupport)
+		HTUpdateSelfAndPeerSetting(ieee, net);
+	ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
+	ieee->pHTInfo->RT2RT_HT_Mode = net->bssht.RT2RT_HT_Mode;
+	rtl8192_update_cap(dev, net->capability);
+}
+
+#ifdef RTL8192CE
+int WDCAPARA_ADD[] = {REG_EDCA_BE_PARAM,REG_EDCA_BK_PARAM,REG_EDCA_VI_PARAM,REG_EDCA_VO_PARAM};
+#else
+int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
+#endif
+void rtl8192_qos_activate(void *data)
+{
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
+	struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, qos_activate);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+#ifndef RTL8192CE
+        struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters;
+        u8 mode = priv->rtllib->current_network.mode;
+	u8  u1bAIFS;
+	u32 u4bAcParam;
+#endif
+        int i;
+
+        if (priv == NULL)
+                return;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+	down(&priv->mutex);
+#else
+        mutex_lock(&priv->mutex);
+#endif
+        if(priv->rtllib->state != RTLLIB_LINKED)
+		goto success;
+	RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
+	
+	for (i = 0; i <  QOS_QUEUE_NUM; i++) {
+#ifdef RTL8192CE
+		priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8*)(&i));
+#else 
+		u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; 
+		u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
+				(((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
+				(((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
+				((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
+		write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
+#endif
+	}
+
+success:
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+	up(&priv->mutex);
+#else
+        mutex_unlock(&priv->mutex);
+#endif
+}
+
+static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
+		int active_network,
+		struct rtllib_network *network)
+{
+	int ret = 0;
+	u32 size = sizeof(struct rtllib_qos_parameters);
+
+	if(priv->rtllib->state !=RTLLIB_LINKED)
+                return ret;
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (!((priv->rtllib->iw_mode == IW_MODE_INFRA ) || 
+	      ((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0))))
+#else
+	if ((priv->rtllib->iw_mode != IW_MODE_INFRA)) 
+#endif
+		return ret;
+
+	if (network->flags & NETWORK_HAS_QOS_MASK) {
+		if (active_network &&
+				(network->flags & NETWORK_HAS_QOS_PARAMETERS))
+			network->qos_data.active = network->qos_data.supported;
+
+		if ((network->qos_data.active == 1) && (active_network == 1) &&
+				(network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
+				(network->qos_data.old_param_count !=
+				 network->qos_data.param_count)) {
+			network->qos_data.old_param_count =
+				network->qos_data.param_count;
+                         priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
+			queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+			RT_TRACE (COMP_QOS, "QoS parameters change call "
+					"qos_activate\n");
+		}
+	} else {
+		memcpy(&priv->rtllib->current_network.qos_data.parameters,\
+		       &def_qos_parameters, size);
+
+		if ((network->qos_data.active == 1) && (active_network == 1)) {
+			queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+			RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
+		}
+		network->qos_data.active = 0;
+		network->qos_data.supported = 0;
+	}
+
+	return 0;
+}
+
+static int rtl8192_handle_beacon(struct net_device * dev,
+                              struct rtllib_beacon * beacon,
+                              struct rtllib_network * network)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	rtl8192_qos_handle_probe_response(priv,1,network);
+
+	queue_delayed_work_rsl(priv->priv_wq, &priv->update_beacon_wq, 0);
+	return 0;
+
+}
+
+static int rtl8192_qos_association_resp(struct r8192_priv *priv,
+                                    struct rtllib_network *network)
+{
+        int ret = 0;
+        unsigned long flags;
+        u32 size = sizeof(struct rtllib_qos_parameters);
+        int set_qos_param = 0;
+
+        if ((priv == NULL) || (network == NULL))
+                return ret;
+
+	if(priv->rtllib->state !=RTLLIB_LINKED)
+                return ret;
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (!((priv->rtllib->iw_mode == IW_MODE_INFRA ) || 
+	      ((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0))))
+#else
+	if ((priv->rtllib->iw_mode != IW_MODE_INFRA)) 
+#endif
+                return ret;
+
+        spin_lock_irqsave(&priv->rtllib->lock, flags);
+	if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
+		memcpy(&priv->rtllib->current_network.qos_data.parameters,\
+			 &network->qos_data.parameters,\
+			sizeof(struct rtllib_qos_parameters));
+		priv->rtllib->current_network.qos_data.active = 1;
+                priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
+#if 0
+		if((priv->rtllib->current_network.qos_data.param_count != \
+					network->qos_data.param_count))
+#endif
+		 {
+                        set_qos_param = 1;
+			priv->rtllib->current_network.qos_data.old_param_count = \
+				 priv->rtllib->current_network.qos_data.param_count;
+			priv->rtllib->current_network.qos_data.param_count = \
+			     	 network->qos_data.param_count;
+		}
+        } else {
+		memcpy(&priv->rtllib->current_network.qos_data.parameters,\
+		       &def_qos_parameters, size);
+		priv->rtllib->current_network.qos_data.active = 0;
+		priv->rtllib->current_network.qos_data.supported = 0;
+                set_qos_param = 1;
+        }
+
+        spin_unlock_irqrestore(&priv->rtllib->lock, flags);
+
+	RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __FUNCTION__,
+			network->flags ,priv->rtllib->current_network.qos_data.active);
+	if (set_qos_param == 1) {
+		dm_init_edca_turbo(priv->rtllib->dev);
+		queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+	}
+        return ret;
+}
+
+static int rtl8192_handle_assoc_response(struct net_device *dev,
+                                     struct rtllib_assoc_response_frame *resp,
+                                     struct rtllib_network *network)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+        rtl8192_qos_association_resp(priv, network);
+        return 0;
+}
+
+void rtl8192_prepare_beacon(struct r8192_priv *priv)
+{
+#ifdef _RTL8192_EXT_PATCH_
+	struct net_device *dev = priv->rtllib->dev;
+#endif
+	struct sk_buff *skb;
+	cb_desc *tcb_desc; 
+
+#ifdef _RTL8192_EXT_PATCH_
+	if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->mesh_state == RTLLIB_NOLINK))
+		return;
+#endif
+	skb = rtllib_get_beacon(priv->rtllib);
+	tcb_desc = (cb_desc *)(skb->cb + 8);
+#ifdef _RTL8192_EXT_PATCH_
+	memset(skb->cb, 0, sizeof(skb->cb));
+#endif
+	tcb_desc->queue_index = BEACON_QUEUE;
+	tcb_desc->data_rate = 2;
+	tcb_desc->RATRIndex = 7;
+	tcb_desc->bTxDisableRateFallBack = 1;
+	tcb_desc->bTxUseDriverAssingedRate = 1;
+#ifdef _RTL8192_EXT_PATCH_
+	tcb_desc->bTxEnableFwCalcDur = 0;
+	memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+#endif
+	skb_push(skb, priv->rtllib->tx_headroom);	
+	if(skb){
+		rtl8192_tx(priv->rtllib->dev,skb);
+	}
+}
+
+void rtl8192_stop_beacon(struct net_device *dev)
+{
+}
+
+void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
+{
+	 struct r8192_priv *priv = rtllib_priv(dev);
+	 struct rtllib_network *net;
+	 u8 i=0, basic_rate = 0;
+#ifdef _RTL8192_EXT_PATCH_	
+	if(priv->rtllib->iw_mode == IW_MODE_MESH)
+		net = & priv->rtllib->current_mesh_network;
+	else
+		net = & priv->rtllib->current_network;
+#else	
+	net = & priv->rtllib->current_network;
+#endif
+
+	 for (i = 0; i < net->rates_len; i++) {
+		 basic_rate = net->rates[i] & 0x7f;
+		 switch (basic_rate) {
+		 case MGN_1M:	
+			 *rate_config |= RRSR_1M;	
+			 break;
+		 case MGN_2M:	
+			 *rate_config |= RRSR_2M;	
+			 break;
+		 case MGN_5_5M:	
+			 *rate_config |= RRSR_5_5M;	
+			 break;
+		 case MGN_11M:	
+			 *rate_config |= RRSR_11M;	
+			 break;
+		 case MGN_6M:	
+			 *rate_config |= RRSR_6M;	
+			 break;
+		 case MGN_9M:	
+			 *rate_config |= RRSR_9M;	
+			 break;
+		 case MGN_12M:	
+			 *rate_config |= RRSR_12M;	
+			 break;
+		 case MGN_18M:	
+			 *rate_config |= RRSR_18M;	
+			 break;
+		 case MGN_24M:	
+			 *rate_config |= RRSR_24M;	
+			 break;
+		 case MGN_36M:	
+			 *rate_config |= RRSR_36M;	
+			 break;
+		 case MGN_48M:	
+			 *rate_config |= RRSR_48M;	
+			 break;
+		 case MGN_54M:	
+			 *rate_config |= RRSR_54M;	
+			 break;
+		 }
+	 }
+
+	 for (i = 0; i < net->rates_ex_len; i++) {
+		 basic_rate = net->rates_ex[i] & 0x7f;
+		 switch (basic_rate) {
+		 case MGN_1M:	
+			 *rate_config |= RRSR_1M;	
+			 break;
+		 case MGN_2M:	
+			 *rate_config |= RRSR_2M;	
+			 break;
+		 case MGN_5_5M:	
+			 *rate_config |= RRSR_5_5M;	
+			 break;
+		 case MGN_11M:	
+			 *rate_config |= RRSR_11M;	
+			 break;
+		 case MGN_6M:	
+			 *rate_config |= RRSR_6M;	
+			 break;
+		 case MGN_9M:	
+			 *rate_config |= RRSR_9M;	
+			 break;
+		 case MGN_12M:	
+			 *rate_config |= RRSR_12M;	
+			 break;
+		 case MGN_18M:	
+			 *rate_config |= RRSR_18M;	
+			 break;
+		 case MGN_24M:	
+			 *rate_config |= RRSR_24M;	
+			 break;
+		 case MGN_36M:	
+			 *rate_config |= RRSR_36M;	
+			 break;
+		 case MGN_48M:	
+			 *rate_config |= RRSR_48M;	
+			 break;
+		 case MGN_54M:	
+			 *rate_config |= RRSR_54M;	
+			 break;
+		 }
+	 }
+}
+
+void rtl8192_refresh_supportrate(struct r8192_priv* priv)
+{
+	struct rtllib_device* ieee = priv->rtllib;
+	if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G) {
+		memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
+		memcpy(ieee->Regdot11TxHTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
+		
+#ifdef RTL8192CE
+		if(priv->rf_type == RF_1T1R) {
+			ieee->Regdot11HTOperationalRateSet[1] = 0;
+		}
+#endif
+
+#ifdef RTL8192SE
+		if(priv->rf_type == RF_1T1R) {
+			ieee->Regdot11HTOperationalRateSet[1] = 0;
+		}
+		if(priv->rf_type == RF_1T1R || priv->rf_type == RF_1T2R)
+		{
+			ieee->Regdot11TxHTOperationalRateSet[1] = 0;
+		}
+
+            if(priv->rtllib->b1SSSupport == true) {
+                ieee->Regdot11HTOperationalRateSet[1] = 0;
+            }
+#endif
+	} else {
+		memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
+	}
+	return;
+}
+
+u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 ret = 0;
+
+	switch(priv->rf_chip) {
+	case RF_8225:
+	case RF_8256:
+	case RF_6052:
+	case RF_PSEUDO_11N:
+		ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G | WIRELESS_MODE_B);
+		break;
+	case RF_8258:
+		ret = (WIRELESS_MODE_A | WIRELESS_MODE_N_5G);
+		break;
+	default:
+		ret = WIRELESS_MODE_B;
+		break;
+	}
+	return ret;
+}
+
+void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
+
+#if 0
+	if(	(wireless_mode != WIRELESS_MODE_B) && 
+		(wireless_mode != WIRELESS_MODE_G) &&
+		(wireless_mode != WIRELESS_MODE_A) &&
+		(wireless_mode != WIRELESS_MODE_AUTO) &&
+		(wireless_mode != WIRELESS_MODE_N_24G) &&
+		(wireless_mode != WIRELESS_MODE_N_5G) ) 
+	{
+		wireless_mode = WIRELESS_MODE_AUTO;
+	}
+#endif
+	if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode & bSupportMode) == 0)) {
+		if (bSupportMode & WIRELESS_MODE_N_24G) {
+			wireless_mode = WIRELESS_MODE_N_24G;
+		} else if (bSupportMode & WIRELESS_MODE_N_5G) {
+			wireless_mode = WIRELESS_MODE_N_5G;
+		} else if((bSupportMode & WIRELESS_MODE_A)) {
+			wireless_mode = WIRELESS_MODE_A;
+		} else if((bSupportMode & WIRELESS_MODE_G)) {
+			wireless_mode = WIRELESS_MODE_G;
+		} else if((bSupportMode & WIRELESS_MODE_B)) {
+			wireless_mode = WIRELESS_MODE_B;
+		} else {
+			RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported (%x)!!!\n",
+				       	__FUNCTION__, bSupportMode);
+			wireless_mode = WIRELESS_MODE_B;
+		}
+	}
+
+#ifdef _RTL8192_EXT_PATCH_
+	if ((wireless_mode & WIRELESS_MODE_N_24G) == WIRELESS_MODE_N_24G)
+		wireless_mode = WIRELESS_MODE_N_24G;
+	else if((wireless_mode & WIRELESS_MODE_N_5G) == WIRELESS_MODE_N_5G)
+		wireless_mode = WIRELESS_MODE_N_5G;
+	else if ((wireless_mode & WIRELESS_MODE_A) == WIRELESS_MODE_A)
+		wireless_mode = WIRELESS_MODE_A;
+	else if ((wireless_mode & WIRELESS_MODE_G) == WIRELESS_MODE_G)
+		wireless_mode = WIRELESS_MODE_G;
+	else
+		wireless_mode = WIRELESS_MODE_B;
+#else
+	if ((wireless_mode & (WIRELESS_MODE_B | WIRELESS_MODE_G)) == (WIRELESS_MODE_G | WIRELESS_MODE_B))
+		wireless_mode = WIRELESS_MODE_G;
+#endif
+
+#ifdef RTL8192SE
+	write_nic_word(dev, SIFS_OFDM, 0x0e0e); 
+#endif
+#ifdef RTL8192CE
+	{
+		u16 SIFS_Timer = 0x0a0a;
+		
+		if(wireless_mode == WIRELESS_MODE_G)
+			SIFS_Timer = 0x0a0a;
+	 	else
+			SIFS_Timer = 0x1010;
+
+		priv->rtllib->SetHwRegHandler( dev, HW_VAR_SIFS,  (u8*)&SIFS_Timer);
+	}
+#endif
+	priv->rtllib->mode = wireless_mode;
+	
+	if ((wireless_mode == WIRELESS_MODE_N_24G) ||  (wireless_mode == WIRELESS_MODE_N_5G)){
+		priv->rtllib->pHTInfo->bEnableHT = 1;	
+                printk("%s(), wireless_mode:%x, bEnableHT = 1\n", __FUNCTION__,wireless_mode);
+        }else{
+		priv->rtllib->pHTInfo->bEnableHT = 0;
+                printk("%s(), wireless_mode:%x, bEnableHT = 0\n", __FUNCTION__,wireless_mode);
+        }
+	RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
+	rtl8192_refresh_supportrate(priv);
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_
+#define KEEP_ALIVE_INTERVAL 				20 
+#define DEFAULT_KEEP_ALIVE_LEVEL			1
+
+static void MgntLinkKeepAlive(struct r8192_priv *priv )
+{
+	if (priv->keepAliveLevel == 0)
+		return;
+
+	if((priv->rtllib->state == RTLLIB_LINKED) && (!priv->rtllib->is_roaming))
+	{
+		
+		if ( (priv->keepAliveLevel== 2) ||
+			(priv->rtllib->LinkDetectInfo.LastNumTxUnicast == priv->NumTxUnicast && 
+			priv->rtllib->LinkDetectInfo.NumRxUnicastOkInPeriod == 0)
+			)
+		{
+			priv->rtllib->LinkDetectInfo.IdleCount++;	
+
+			if(priv->rtllib->LinkDetectInfo.IdleCount >= ((KEEP_ALIVE_INTERVAL / RT_CHECK_FOR_HANG_PERIOD)-1) )
+			{
+				priv->rtllib->LinkDetectInfo.IdleCount = 0;
+				rtllib_sta_ps_send_null_frame(priv->rtllib, false);
+			}
+		}
+		else
+		{
+			priv->rtllib->LinkDetectInfo.IdleCount = 0;
+		}
+		priv->rtllib->LinkDetectInfo.LastNumTxUnicast = priv->NumTxUnicast; 
+		priv->rtllib->LinkDetectInfo.LastNumRxUnicast = priv->rtllib->LinkDetectInfo.NumRxUnicastOkInPeriod;
+	}
+}
+
+static void rtl8192_init_mesh_variable(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 i;
+
+	priv->rtllib->mesh_security_setting = 0;
+	memset(priv->rtllib->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32);
+	priv->rtllib->mesh_sec_type = 0;
+
+	priv->NumTxUnicast = 0;
+	priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
+
+	priv->FwCmdIOMap = 0;
+	priv->FwCmdIOParam = 0;
+	priv->ThermalValue = 0;
+	priv->DMFlag = 0;
+	priv->rssi_level = 0;
+	priv->rtllib->bUseRAMask = 0;
+
+	priv->rtllib->set_key_for_AP = rtl8192_set_key_for_AP;
+	memset(priv->rtllib->swmeshratrtable,0,8*(sizeof(SW_RATR_TABLE)));
+	priv->rtllib->mesh_amsdu_in_process = 0;
+	priv->rtllib->HwSecCamBitMap = 0;
+	memset(priv->rtllib->HwSecCamStaAddr,0,TOTAL_CAM_ENTRY * ETH_ALEN); 
+	priv->rtllib->LinkingPeerBitMap = 0;
+	memset(priv->rtllib->LinkingPeerAddr,0,(MAX_MP-1) * ETH_ALEN); 
+	memset(priv->rtllib->LinkingPeerSecState, 0, (MAX_MP-1));
+	memset(priv->rtllib->peer_AID_Addr,0,30 * ETH_ALEN);
+	priv->rtllib->peer_AID_bitmap = 0;
+	priv->rtllib->backup_channel = 1;
+	priv->rtllib->del_hwsec_cam_entry = rtl8192_del_hwsec_cam_entry; 
+	priv->rtllib->set_key_for_peer = meshdev_set_key_for_peer;
+	priv->rtllib->hostname_len = 0;
+	memset(priv->rtllib->hostname, 0, sizeof(priv->rtllib->hostname));
+	strcpy(priv->rtllib->hostname, "Crab"); 
+	priv->rtllib->hostname_len = strlen(priv->rtllib->hostname);
+	priv->rtllib->meshScanMode = 0;
+	priv->rtllib->currentRate = 0xffffffff;
+	priv->mshobj = alloc_mshobj(priv);
+	printk("priv is %p,mshobj is %p\n",priv,priv->mshobj);
+
+	if (priv->mshobj) {
+		priv->rtllib->ext_patch_rtllib_start_protocol = 
+			priv->mshobj->ext_patch_rtllib_start_protocol;
+		priv->rtllib->ext_patch_rtllib_stop_protocol = 
+			priv->mshobj->ext_patch_rtllib_stop_protocol;
+		priv->rtllib->ext_patch_rtllib_start_mesh = 
+			priv->mshobj->ext_patch_rtllib_start_mesh;
+		priv->rtllib->ext_patch_rtllib_probe_req_1 = 
+			priv->mshobj->ext_patch_rtllib_probe_req_1;
+		priv->rtllib->ext_patch_rtllib_probe_req_2 = 
+			priv->mshobj->ext_patch_rtllib_probe_req_2;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_auth = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_auth;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_deauth = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_deauth;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close;
+		priv->rtllib->ext_patch_rtllib_close_all_peerlink = 
+			priv->mshobj->ext_patch_rtllib_close_all_peerlink;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann;
+		priv->rtllib->ext_patch_rtllib_ext_stop_scan_wq_set_channel = 
+			priv->mshobj->ext_patch_rtllib_ext_stop_scan_wq_set_channel;
+		priv->rtllib->ext_patch_r819x_wx_set_mesh_chan = 
+			priv->mshobj->ext_patch_r819x_wx_set_mesh_chan;
+		priv->rtllib->ext_patch_r819x_wx_set_channel = 
+			priv->mshobj->ext_patch_r819x_wx_set_channel;
+		priv->rtllib->ext_patch_rtllib_process_probe_response_1 = 
+			priv->mshobj->ext_patch_rtllib_process_probe_response_1;
+		priv->rtllib->ext_patch_rtllib_rx_mgt_on_probe_req = 
+			priv->mshobj->ext_patch_rtllib_rx_mgt_on_probe_req;
+		priv->rtllib->ext_patch_rtllib_rx_mgt_update_expire = 
+			priv->mshobj->ext_patch_rtllib_rx_mgt_update_expire;
+		priv->rtllib->ext_patch_get_beacon_get_probersp = 
+			priv->mshobj->ext_patch_get_beacon_get_probersp;
+		priv->rtllib->ext_patch_rtllib_rx_on_rx = 
+			priv->mshobj->ext_patch_rtllib_rx_on_rx;		
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_hdrlen = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_get_hdrlen;
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_mac_hdrlen = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_get_mac_hdrlen;
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc = 
+			priv->mshobj->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc;
+		priv->rtllib->ext_patch_rtllib_rx_is_valid_framectl = 
+			priv->mshobj->ext_patch_rtllib_rx_is_valid_framectl;
+		priv->rtllib->ext_patch_rtllib_softmac_xmit_get_rate = 
+			priv->mshobj->ext_patch_rtllib_softmac_xmit_get_rate;
+		/* added by david for setting acl dynamically */
+		priv->rtllib->ext_patch_rtllib_acl_query = 
+			priv->mshobj->ext_patch_rtllib_acl_query;
+		priv->rtllib->ext_patch_rtllib_is_mesh = 
+			priv->mshobj->ext_patch_rtllib_is_mesh;
+		priv->rtllib->ext_patch_rtllib_create_crypt_for_peer = 
+			priv->mshobj->ext_patch_rtllib_create_crypt_for_peer;
+		priv->rtllib->ext_patch_rtllib_get_peermp_htinfo = 
+			priv->mshobj->ext_patch_rtllib_get_peermp_htinfo;
+		priv->rtllib->ext_patch_rtllib_send_ath_commit = 
+			priv->mshobj->ext_patch_rtllib_send_ath_commit;
+		priv->rtllib->ext_patch_rtllib_send_ath_confirm = 
+			priv->mshobj->ext_patch_rtllib_send_ath_confirm;
+		priv->rtllib->ext_patch_rtllib_rx_ath_commit = 
+			priv->mshobj->ext_patch_rtllib_rx_ath_commit;
+		priv->rtllib->ext_patch_rtllib_rx_ath_confirm = 
+			priv->mshobj->ext_patch_rtllib_rx_ath_confirm;
+	}
+	for (i = 0; i < MAX_QUEUE_SIZE; i++) {
+		skb_queue_head_init(&priv->rtllib->skb_meshaggQ[i]);
+	}
+}
+
+int _rtl8192_mesh_up(struct net_device *dev,bool is_silent_reset)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	bool init_status = true;
+	priv->bDriverIsGoingToUnload = false;
+	priv->bdisable_nic = false;  
+
+	if(priv->mesh_up){
+		RT_TRACE(COMP_ERR,"%s(): since mesh0 is already up, ra0 is forbidden to open.\n",__FUNCTION__);
+		return -1;
+	}
+	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
+	if(!is_silent_reset)
+		priv->rtllib->iw_mode = IW_MODE_INFRA;
+	if(priv->up){
+		RT_TRACE(COMP_ERR,"%s():%s is up,return\n",__FUNCTION__,DRV_NAME);
+		return -1;
+	}
+#ifdef RTL8192SE        
+	priv->ReceiveConfig =
+				RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/
+				RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV |
+				RCR_AICV | RCR_ACRC32    |                               
+				RCR_AB          | RCR_AM                |                               
+				RCR_APM         |                                                               
+				/*RCR_AAP               |*/                                                     
+				RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF |      
+				(priv->EarlyRxThreshold<<RCR_FIFO_OFFSET)       ;
+#endif
+
+	if(!priv->mesh_up)
+	{
+		RT_TRACE(COMP_INIT, "Bringing up iface");
+		priv->bfirst_init = true;
+		init_status = priv->ops->initialize_adapter(dev);
+		if(init_status != true)
+		{
+			RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+			return -1;
+		}
+		RT_TRACE(COMP_INIT, "start adapter finished\n");
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+		priv->rtllib->ieee_up=1;
+		priv->bfirst_init = false;
+#ifdef ENABLE_GPIO_RADIO_CTL
+		if(priv->polling_timer_on == 0){
+			check_rfctrl_gpio_timer((unsigned long)dev);
+		}
+#endif
+		priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN;
+		priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN;
+		if((priv->mshobj->ext_patch_r819x_wx_set_mesh_chan) && (!is_silent_reset))
+			priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,INIT_DEFAULT_CHAN);
+		if((priv->mshobj->ext_patch_r819x_wx_set_channel) && (!is_silent_reset))
+		{
+			priv->mshobj->ext_patch_r819x_wx_set_channel(priv->rtllib, INIT_DEFAULT_CHAN);
+		}
+		dm_InitRateAdaptiveMask(dev);
+	}	
+	else
+	{
+		rtllib_stop_scan_syncro(priv->rtllib);
+	}
+	priv->up=1; 
+	printk("%s():set chan %d\n",__FUNCTION__,INIT_DEFAULT_CHAN);
+	priv->rtllib->set_chan(dev, INIT_DEFAULT_CHAN); 
+	priv->up_first_time = 0;
+	if(!priv->rtllib->proto_started) 
+	{
+#ifdef RTL8192E
+		if(priv->rtllib->eRFPowerState!=eRfOn)
+			MgntActSet_RF_State(dev, eRfOn, priv->rtllib->RfOffReason);	
+#endif
+		if(priv->rtllib->state != RTLLIB_LINKED)
+			rtllib_softmac_start_protocol(priv->rtllib, 0);
+	}
+	if(!priv->mesh_up)
+		watch_dog_timer_callback((unsigned long) dev);
+	rtllib_reset_queue(priv->rtllib);
+	if(!netif_queue_stopped(dev))
+		netif_start_queue(dev);
+	else
+		netif_wake_queue(dev);
+	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
+
+	return 0;
+}
+
+int rtl8192_mesh_down(struct net_device *dev, bool shutdownrf)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags = 0;
+	u8 RFInProgressTimeOut = 0;
+
+	if (priv->up == 0) 
+		return -1;
+
+	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
+#ifdef ENABLE_LPS
+	if(priv->rtllib->state == RTLLIB_LINKED)
+		LeisurePSLeave(dev);
+#endif
+	priv->up=0; 
+
+	/* FIXME */
+	if (!netif_queue_stopped(dev))
+		netif_stop_queue(dev);  
+	if(!priv->mesh_up)
+	{
+		priv->bDriverIsGoingToUnload = true;	
+		priv->rtllib->ieee_up = 0;  
+		/* mesh stack has also be closed, then disalbe the hardware function at 
+		 * the same time */
+		priv->rtllib->wpa_ie_len = 0;
+		if(priv->rtllib->wpa_ie)
+			kfree(priv->rtllib->wpa_ie);
+		priv->rtllib->wpa_ie = NULL;
+#ifdef RTL8192S_WAPI_SUPPORT
+		priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false;
+		priv->rtllib->wapiInfo.wapiTxMsk.bSet = false;
+#endif		
+		CamResetAllEntry(dev);
+		memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+		rtl8192_irq_disable(dev);
+		rtl8192_cancel_deferred_work(priv);
+#ifndef RTL8190P
+		cancel_delayed_work(&priv->rtllib->hw_wakeup_wq);
+#endif
+		deinit_hal_dm(dev);
+		del_timer_sync(&priv->watch_dog_timer);	
+
+		rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
+		SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		while(priv->RFChangeInProgress)
+		{
+			SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+			if(RFInProgressTimeOut > 100)
+			{
+				SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+				break;
+			}
+			printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__);
+			mdelay(1);
+			RFInProgressTimeOut ++;
+			SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		}
+		priv->RFChangeInProgress = true;
+		SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		priv->ops->stop_adapter(dev, false);
+		SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		priv->RFChangeInProgress = false;
+		SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock);
+		udelay(100);
+		memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list));
+		priv->rtllib->wap_set = 0; 
+		priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN;
+#ifdef CONFIG_ASPM_OR_D3
+		RT_ENABLE_ASPM(dev);
+#endif
+	} else {
+		priv->rtllib->wpa_ie_len = 0;
+		if(priv->rtllib->wpa_ie)
+			kfree(priv->rtllib->wpa_ie);
+		priv->rtllib->wpa_ie = NULL;
+#ifdef RTL8192S_WAPI_SUPPORT
+		priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false;
+		priv->rtllib->wapiInfo.wapiTxMsk.bSet = false;
+#endif
+		CamResetAllEntry(dev);
+		CamRestoreEachIFEntry(dev,1);	
+		memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+
+		rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
+		memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list));
+		priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN;
+		priv->rtllib->wap_set = 0; 
+	}
+
+	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
+
+	return 0;
+}
+
+void rtl8192_dinit_mshobj(struct r8192_priv *priv) 
+{
+
+	if(priv && priv->mshobj)
+	{
+		if(priv->mshobj->ext_patch_remove_proc)
+			priv->mshobj->ext_patch_remove_proc(priv);
+		priv->rtllib->ext_patch_rtllib_start_protocol = 0;
+		priv->rtllib->ext_patch_rtllib_stop_protocol = 0;
+		priv->rtllib->ext_patch_rtllib_probe_req_1 = 0;
+		priv->rtllib->ext_patch_rtllib_probe_req_2 = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_auth =0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_deauth =0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report= 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req= 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep=0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann=0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann=0;
+		priv->rtllib->ext_patch_rtllib_ext_stop_scan_wq_set_channel = 0;
+		priv->rtllib->ext_patch_rtllib_process_probe_response_1 = 0;
+		priv->rtllib->ext_patch_rtllib_rx_mgt_on_probe_req = 0;
+		priv->rtllib->ext_patch_rtllib_rx_mgt_update_expire = 0;
+		priv->rtllib->ext_patch_rtllib_rx_on_rx = 0;
+		priv->rtllib->ext_patch_get_beacon_get_probersp = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_hdrlen = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_mac_hdrlen = 0;
+		priv->rtllib->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc = 0;
+		priv->rtllib->ext_patch_rtllib_rx_is_valid_framectl = 0;
+		priv->rtllib->ext_patch_rtllib_softmac_xmit_get_rate = 0;
+		priv->rtllib->ext_patch_rtllib_is_mesh = 0;
+		priv->rtllib->ext_patch_rtllib_create_crypt_for_peer = 0;
+		priv->rtllib->ext_patch_rtllib_get_peermp_htinfo = 0;
+		priv->rtllib->ext_patch_rtllib_send_ath_commit = 0;
+		priv->rtllib->ext_patch_rtllib_send_ath_confirm = 0;
+		priv->rtllib->ext_patch_rtllib_rx_ath_commit = 0;
+		priv->rtllib->ext_patch_rtllib_rx_ath_confirm = 0;
+                free_mshobj(&priv->mshobj);
+	}
+
+}
+#else
+int _rtl8192_sta_up(struct net_device *dev,bool is_silent_reset)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	bool init_status = true;
+	priv->bDriverIsGoingToUnload = false;
+	priv->bdisable_nic = false;  
+
+	priv->up=1;
+	priv->rtllib->ieee_up=1;	
+	
+	priv->up_first_time = 0;
+	RT_TRACE(COMP_INIT, "Bringing up iface");
+	priv->bfirst_init = true;
+	init_status = priv->ops->initialize_adapter(dev);
+	if(init_status != true)
+	{
+		RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+		priv->bfirst_init = false;
+		return -1;
+	}
+
+	RT_TRACE(COMP_INIT, "start adapter finished\n");
+	RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+	priv->bfirst_init = false;
+#if defined RTL8192SE || defined RTL8192CE
+	if(priv->rtllib->eRFPowerState!=eRfOn)
+		MgntActSet_RF_State(dev, eRfOn, priv->rtllib->RfOffReason);	
+#endif
+
+#ifdef ENABLE_GPIO_RADIO_CTL
+	if(priv->polling_timer_on == 0){
+		check_rfctrl_gpio_timer((unsigned long)dev);
+	}
+#endif
+
+	if(priv->rtllib->state != RTLLIB_LINKED)
+#ifndef CONFIG_MP
+	rtllib_softmac_start_protocol(priv->rtllib);
+#endif
+	rtllib_reset_queue(priv->rtllib);
+#ifndef CONFIG_MP
+	watch_dog_timer_callback((unsigned long) dev);
+#endif
+
+
+	if(!netif_queue_stopped(dev))
+		netif_start_queue(dev);
+	else
+		netif_wake_queue(dev);
+
+	return 0;
+}
+
+int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags = 0;
+	u8 RFInProgressTimeOut = 0;
+
+	if (priv->up == 0) return -1;
+
+#ifdef ENABLE_LPS
+	if(priv->rtllib->state == RTLLIB_LINKED)
+		LeisurePSLeave(dev);
+#endif
+
+	priv->bDriverIsGoingToUnload = true;
+	priv->up=0;
+	priv->rtllib->ieee_up = 0;
+	priv->bfirst_after_down = 1;
+	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
+	if (!netif_queue_stopped(dev))
+		netif_stop_queue(dev);
+
+	priv->rtllib->wpa_ie_len = 0;
+	if(priv->rtllib->wpa_ie)
+		kfree(priv->rtllib->wpa_ie);
+	priv->rtllib->wpa_ie = NULL;
+#ifdef RTL8192S_WAPI_SUPPORT	
+	priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false;
+	priv->rtllib->wapiInfo.wapiTxMsk.bSet = false;
+#endif	
+	CamResetAllEntry(dev);	
+	memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+	rtl8192_irq_disable(dev);
+
+	del_timer_sync(&priv->watch_dog_timer);	
+	rtl8192_cancel_deferred_work(priv);
+#ifndef RTL8190P
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	cancel_delayed_work(&priv->rtllib->hw_wakeup_wq);
+#endif
+#endif
+
+	rtllib_softmac_stop_protocol(priv->rtllib,true);
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	while(priv->RFChangeInProgress)
+	{
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+		if(RFInProgressTimeOut > 100)
+		{
+			spin_lock_irqsave(&priv->rf_ps_lock,flags);
+			break;
+		}
+		printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__);
+		mdelay(1);
+		RFInProgressTimeOut ++;
+		spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	}
+	priv->RFChangeInProgress = true;
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+	priv->ops->stop_adapter(dev, false);
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	priv->RFChangeInProgress = false;
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+	udelay(100);
+	memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list));
+#ifdef CONFIG_ASPM_OR_D3
+	RT_ENABLE_ASPM(dev);
+#endif
+	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
+
+	return 0;
+}
+
+#endif
+
+static void rtl8192_init_priv_handler(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	priv->rtllib->softmac_hard_start_xmit 	= rtl8192_hard_start_xmit;
+	priv->rtllib->set_chan 				= rtl8192_set_chan;
+	priv->rtllib->link_change 			= priv->ops->link_change;
+	priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
+	priv->rtllib->data_hard_stop 		= rtl8192_data_hard_stop;
+	priv->rtllib->data_hard_resume 		= rtl8192_data_hard_resume;
+	priv->rtllib->check_nic_enough_desc 	= rtl8192_check_nic_enough_desc;	
+	priv->rtllib->get_nic_desc_num 		= rtl8192_get_nic_desc_num;	
+#ifdef _RTL8192_EXT_PATCH_
+	priv->rtllib->set_mesh_key 			= r8192_mesh_set_enc_ext;
+#endif
+	priv->rtllib->handle_assoc_response 	= rtl8192_handle_assoc_response;
+	priv->rtllib->handle_beacon 		= rtl8192_handle_beacon;
+	priv->rtllib->SetWirelessMode 		= rtl8192_SetWirelessMode;
+	
+#ifdef ENABLE_LPS
+	priv->rtllib->LeisurePSLeave 		= LeisurePSLeave;
+#endif
+
+#ifdef RTL8192CE
+	priv->rtllib->SetBWModeHandler 		= PHY_SetBWMode8192C;
+	priv->rf_set_chan 						= PHY_SwChnl8192C;
+	
+#ifdef _ENABLE_SW_BEACON
+	priv->rtllib->start_send_beacons 	= NULL;
+	priv->rtllib->stop_send_beacons 	= NULL;
+#else
+	priv->rtllib->start_send_beacons 	= rtl8192ce_SetBeaconRelatedRegisters;
+	priv->rtllib->stop_send_beacons 	= rtl8192_stop_beacon;
+#endif
+	
+	priv->rtllib->sta_wake_up 			= rtl8192_hw_wakeup;
+	priv->rtllib->enter_sleep_state 		= rtl8192_hw_to_sleep;
+	priv->rtllib->ps_is_queue_empty 	= rtl8192_is_tx_queue_empty;
+	
+	priv->rtllib->GetNmodeSupportBySecCfg = rtl8192ce_GetNmodeSupportBySecCfg;
+	priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192ce_GetHalfNmodeSupportByAPs;
+
+	priv->rtllib->SetHwRegHandler 		= rtl8192ce_SetHwReg;
+	priv->rtllib->GetHwRegHandler 		= rtl8192ce_GetHwReg;
+	priv->rtllib->AllowAllDestAddrHandler = rtl8192ce_AllowAllDestAddr;
+	priv->rtllib->SetFwCmdHandler 		= rtl8192ce_phy_SetFwCmdIO;
+	priv->rtllib->UpdateHalRAMaskHandler 	= rtl8192ce_UpdateHalRAMask;
+	priv->rtllib->UpdateBeaconInterruptHandler = rtl8192ce_UpdateInterruptMask;
+	priv->rtllib->rtl_11n_user_show_rates = rtl8192_11n_user_show_rates;
+#ifdef ENABLE_IPS
+	priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
+	priv->rtllib->rtllib_ips_leave 	= rtllib_ips_leave;
+#endif
+
+	priv->rtllib->LedControlHandler 		= LedControl8192CE;
+	priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192C;
+#endif
+
+#ifdef RTL8192SE
+	priv->rtllib->SetBWModeHandler 		= rtl8192_SetBWMode;
+	priv->rf_set_chan 						= rtl8192_phy_SwChnl;
+	
+#ifdef _RTL8192_EXT_PATCH_
+	priv->rtllib->start_send_beacons = NULL;
+	priv->rtllib->stop_send_beacons = NULL;
+#else	
+#ifdef _ENABLE_SW_BEACON
+	priv->rtllib->start_send_beacons = NULL;
+	priv->rtllib->stop_send_beacons = NULL;
+#else
+	priv->rtllib->start_send_beacons = rtl8192se_start_beacon;
+	priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
+#endif	
+#endif	
+	priv->rtllib->sta_wake_up = rtl8192_hw_wakeup;
+	priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep;
+	priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
+
+	priv->rtllib->GetNmodeSupportBySecCfg = rtl8192se_GetNmodeSupportBySecCfg;
+	priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192se_GetHalfNmodeSupportByAPs;
+
+	priv->rtllib->SetBeaconRelatedRegistersHandler = SetBeaconRelatedRegisters8192SE;
+	priv->rtllib->Adhoc_InitRateAdaptive = Adhoc_InitRateAdaptive;
+	priv->rtllib->check_ht_cap = rtl8192se_check_ht_cap;
+	priv->rtllib->SetHwRegHandler = SetHwReg8192SE;
+	priv->rtllib->GetHwRegHandler = GetHwReg8192SE;
+	priv->rtllib->AllowAllDestAddrHandler = rtl8192se_AllowAllDestAddr; 
+	priv->rtllib->SetFwCmdHandler = rtl8192se_set_fw_cmd;
+	priv->rtllib->UpdateHalRAMaskHandler = UpdateHalRAMask8192SE;
+	priv->rtllib->UpdateBeaconInterruptHandler = NULL;
+	priv->rtllib->rtl_11n_user_show_rates = rtl8192_11n_user_show_rates;
+#ifdef ENABLE_IPS
+	priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
+	priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+#endif
+
+	priv->rtllib->LedControlHandler = LedControl8192SE;
+	priv->rtllib->rtllib_start_hw_scan = rtl8192se_hw_scan_initiate;
+	priv->rtllib->rtllib_stop_hw_scan = rtl8192se_cancel_hw_scan;
+#endif
+
+#ifdef RTL8192E
+	priv->rtllib->SetBWModeHandler 		= rtl8192_SetBWMode;
+	priv->rf_set_chan 						= rtl8192_phy_SwChnl;
+	
+#ifdef _ENABLE_SW_BEACON
+	priv->rtllib->start_send_beacons = NULL;
+	priv->rtllib->stop_send_beacons = NULL;
+#else
+	priv->rtllib->start_send_beacons = rtl8192e_start_beacon;
+	priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
+#endif
+	
+	priv->rtllib->sta_wake_up = rtl8192_hw_wakeup;
+	priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep;
+	priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
+
+	priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg;
+	priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192_GetHalfNmodeSupportByAPs;
+
+	priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg;
+	priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr; 
+	priv->rtllib->SetFwCmdHandler = NULL;
+	priv->rtllib->InitialGainHandler = InitialGain819xPci;
+#ifdef ENABLE_IPS
+	priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
+	priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+#endif
+
+	priv->rtllib->LedControlHandler = NULL;
+	priv->rtllib->UpdateBeaconInterruptHandler = NULL;
+#endif
+
+#ifdef RTL8190P
+	priv->rtllib->SetBWModeHandler 		= rtl8192_SetBWMode;
+	priv->rf_set_chan 						= rtl8192_phy_SwChnl;
+	
+#ifdef _ENABLE_SW_BEACON
+	priv->rtllib->start_send_beacons = NULL;
+	priv->rtllib->stop_send_beacons = NULL;
+#else
+	priv->rtllib->start_send_beacons = rtl8192e_start_beacon;
+	priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
+#endif
+	
+	priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg;
+	priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192_GetHalfNmodeSupportByAPs;
+
+	priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg;
+	priv->rtllib->SetFwCmdHandler = NULL;
+	priv->rtllib->InitialGainHandler = InitialGain819xPci;
+#ifdef ENABLE_IPS
+	priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
+	priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+#endif
+
+	priv->rtllib->LedControlHandler = NULL;
+	priv->rtllib->UpdateBeaconInterruptHandler = NULL;
+#endif
+
+#ifdef CONFIG_RTL_RFKILL
+	priv->rtllib->rtllib_rfkill_poll = rtl8192_rfkill_poll; 
+#else
+	priv->rtllib->rtllib_rfkill_poll = NULL;
+#endif
+}
+
+static void rtl8192_init_aspm(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+#ifdef CONFIG_ASPM_OR_D3
+	int pos;
+	u8 value;
+#endif
+
+	priv->bridge_pdev = priv->pdev->bus->self;
+	switch (priv->bridge_pdev->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		priv->pci_bridge_vendor = PCI_BRIDGE_VENDOR_INTEL;
+			break;
+	case PCI_VENDOR_ID_SI:
+		priv->pci_bridge_vendor = PCI_BRIDGE_VENDOR_SIS;
+			break;
+	default:
+		priv->pci_bridge_vendor = 0;
+		break;
+	}
+	
+#ifdef CONFIG_ASPM_OR_D3
+	if (priv->pci_bridge_vendor & (PCI_BRIDGE_VENDOR_INTEL | PCI_BRIDGE_VENDOR_SIS)) {
+		priv->aspm_clkreq_enable = true;
+		priv->RegHostPciASPMSetting = 0x02;
+		pos = pci_find_capability(priv->bridge_pdev, PCI_CAP_ID_EXP);
+		priv->PciBridgeASPMRegOffset = pos + PCI_EXP_LNKCTL;
+		pci_read_config_byte(priv->bridge_pdev, pos + PCI_EXP_LNKCTL, &value);
+		priv->PciBridgeLinkCtrlReg = value;
+
+		priv->RegDevicePciASPMSetting = 0x03;
+		pos = pci_find_capability(priv->pdev, PCI_CAP_ID_EXP);
+		priv->ASPMRegOffset = pos + PCI_EXP_LNKCTL;
+		priv->ClkReqOffset = pos + PCI_EXP_LNKCTL + 1;
+		pci_read_config_byte(priv->pdev, pos + PCI_EXP_LNKCTL, &value);
+		priv->LinkCtrlReg = value;
+	} else {
+		priv->aspm_clkreq_enable = false;
+	}
+#endif	
+}
+
+static void rtl8192_init_priv_variable(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+#if defined RTL8192SE || defined RTL8192CE || defined RTL8192E	
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+#endif
+	u8 i;
+
+	priv->rtllib->hwscan_sem_up = 1;
+	priv->rtllib->status = 0;
+	priv->H2CTxCmdSeq = 0;
+	priv->bDisableFrameBursting = 0;
+	priv->bDMInitialGainEnable = 1;	
+	priv->polling_timer_on = 0;
+	priv->up_first_time = 1;
+	priv->blinked_ingpio = false;
+	priv->bDriverIsGoingToUnload = false;
+	priv->being_init_adapter = false;
+	priv->initialized_at_probe = false;
+	priv->sw_radio_on = true;
+	priv->bdisable_nic = false;
+	priv->bfirst_init = false;
+	priv->txringcount = 64;
+	priv->rxbuffersize = 9100;
+	priv->rxringcount = MAX_RX_COUNT;
+	priv->irq_enabled=0;
+	priv->chan = 1; 
+	priv->RegWirelessMode = WIRELESS_MODE_AUTO;
+	priv->RegChannelPlan = 0xf;
+	priv->nrxAMPDU_size = 0;
+	priv->nrxAMPDU_aggr_num = 0;
+	priv->last_rxdesc_tsf_high = 0;
+	priv->last_rxdesc_tsf_low = 0;
+	priv->rtllib->mode = WIRELESS_MODE_AUTO; 
+	priv->rtllib->iw_mode = IW_MODE_INFRA;
+	priv->rtllib->bNetPromiscuousMode = false;
+	priv->rtllib->IntelPromiscuousModeInfo.bPromiscuousOn = false;
+	priv->rtllib->IntelPromiscuousModeInfo.bFilterSourceStationFrame = false;
+	priv->rtllib->ieee_up=0;
+	priv->retry_rts = DEFAULT_RETRY_RTS;
+	priv->retry_data = DEFAULT_RETRY_DATA;
+	priv->rtllib->rts = DEFAULT_RTS_THRESHOLD;
+	priv->rtllib->rate = 110; 
+	priv->rtllib->short_slot = 1;
+	priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
+	priv->bcck_in_ch14 = false;
+	priv->bfsync_processing  = false;
+	priv->CCKPresentAttentuation = 0;
+	priv->rfa_txpowertrackingindex = 0;
+	priv->rfc_txpowertrackingindex = 0;
+	priv->CckPwEnl = 6;
+	priv->ScanDelay = 50;
+	priv->ResetProgress = RESET_TYPE_NORESET;
+	priv->bForcedSilentReset = 0;
+	priv->bDisableNormalResetCheck = false;
+	priv->force_reset = false;
+	memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+
+	memset(&priv->InterruptLog,0,sizeof(LOG_INTERRUPT_8190_T));
+	priv->RxCounter = 0;
+        priv->rtllib->wx_set_enc = 0;
+	priv->bHwRadioOff = false;
+	priv->RegRfOff = 0;
+	priv->isRFOff = false;
+	priv->bInPowerSaveMode = false;
+	priv->rtllib->RfOffReason = 0;
+	priv->RFChangeInProgress = false;
+	priv->bHwRfOffAction = 0;
+	priv->SetRFPowerStateInProgress = false;
+	priv->rtllib->PowerSaveControl.bInactivePs = true;
+	priv->rtllib->PowerSaveControl.bIPSModeBackup = false;
+	priv->rtllib->PowerSaveControl.bLeisurePs = true;
+	priv->rtllib->PowerSaveControl.bFwCtrlLPS = false;
+	priv->rtllib->LPSDelayCnt = 0;
+        priv->rtllib->sta_sleep = 0;
+	priv->rtllib->eRFPowerState = eRfOn;
+
+	priv->txpower_checkcnt = 0;
+	priv->thermal_readback_index =0;
+	priv->txpower_tracking_callback_cnt = 0;
+	priv->ccktxpower_adjustcnt_ch14 = 0;
+	priv->ccktxpower_adjustcnt_not_ch14 = 0;
+
+#if defined RTL8192SE 
+	for(i = 0; i<PEER_MAX_ASSOC; i++){
+		priv->rtllib->peer_assoc_list[i]=NULL;
+		priv->rtllib->AvailableAIDTable[i] = 99; 
+	}
+	priv->RATRTableBitmap = 0;
+	priv->rtllib->amsdu_in_process = 0;
+#endif	
+	
+	rtl8192_init_aspm(dev);
+
+	priv->rtllib->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;	
+	priv->rtllib->iw_mode = IW_MODE_INFRA;
+	priv->rtllib->active_scan = 1;
+	priv->rtllib->be_scan_inprogress = false;
+	priv->rtllib->modulation = RTLLIB_CCK_MODULATION | RTLLIB_OFDM_MODULATION;
+	priv->rtllib->host_encrypt = 1;
+	priv->rtllib->host_decrypt = 1;
+
+	priv->rtllib->dot11PowerSaveMode = eActive;
+#if defined (RTL8192S_WAPI_SUPPORT)
+	priv->rtllib->wapiInfo.bWapiPSK = false;
+#endif
+	priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
+	priv->rtllib->MaxMssDensity = 0;
+	priv->rtllib->MinSpaceCfg = 0;
+	
+	priv->card_type = PCI;
+
+#if defined RTL8192SE || defined RTL8192CE || defined RTL8192E	
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+	pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
+
+	pPSC->RegMaxLPSAwakeIntvl = 5;
+#endif
+
+	priv->AcmControl = 0;	
+	priv->pFirmware = (rt_firmware*)vmalloc(sizeof(rt_firmware));
+	if (priv->pFirmware)
+	memset(priv->pFirmware, 0, sizeof(rt_firmware));
+
+        skb_queue_head_init(&priv->rx_queue);
+	skb_queue_head_init(&priv->skb_queue);
+
+	for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+		skb_queue_head_init(&priv->rtllib->skb_waitQ [i]);
+	}
+	for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+		skb_queue_head_init(&priv->rtllib->skb_aggQ [i]);
+	}
+
+}	
+
+static void rtl8192_init_priv_lock(struct r8192_priv* priv)
+{
+	spin_lock_init(&priv->fw_scan_lock);
+	spin_lock_init(&priv->tx_lock);
+	spin_lock_init(&priv->irq_lock);
+	spin_lock_init(&priv->irq_th_lock);
+	spin_lock_init(&priv->rf_ps_lock);
+	spin_lock_init(&priv->ps_lock);
+	spin_lock_init(&priv->rf_lock);
+	spin_lock_init(&priv->rt_h2c_lock);
+#ifdef CONFIG_ASPM_OR_D3
+	spin_lock_init(&priv->D3_lock);
+#endif
+	sema_init(&priv->wx_sem,1);
+	sema_init(&priv->rf_sem,1);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+	sema_init(&priv->mutex, 1);
+#else
+	mutex_init(&priv->mutex);
+#endif
+}
+
+static void rtl8192_init_priv_task(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);	
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+#ifdef PF_SYNCTHREAD
+	priv->priv_wq = create_workqueue(DRV_NAME,0);
+#else	
+	priv->priv_wq = create_workqueue(DRV_NAME);
+#endif
+#endif
+	INIT_WORK_RSL(&priv->reset_wq,  (void*)rtl8192_restart, dev);
+#ifdef ENABLE_IPS
+	INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void*)IPSLeave_wq, dev);  
+#endif
+	INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq, (void*)rtl819x_watchdog_wqcallback, dev);
+	INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq,  (void*)dm_txpower_trackingcallback, dev);
+	INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq,  (void*)dm_rf_pathcheck_workitemcallback, dev);
+	INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq, (void*)rtl8192_update_beacon, dev);
+	INIT_WORK_RSL(&priv->qos_activate, (void*)rtl8192_qos_activate, dev);
+#ifndef RTL8190P	
+	INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq,(void*) rtl8192_hw_wakeup_wq, dev);
+	INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq,(void*) rtl8192_hw_sleep_wq, dev);
+#endif
+#if defined RTL8192SE 
+	INIT_DELAYED_WORK_RSL(&priv->check_hw_scan_wq, (void*)rtl8192se_check_hw_scan, dev);
+	INIT_DELAYED_WORK_RSL(&priv->hw_scan_simu_wq, (void*)rtl8192se_hw_scan_simu, dev);
+	INIT_DELAYED_WORK_RSL(&priv->start_hw_scan_wq, (void*)rtl8192se_start_hw_scan, dev);
+	INIT_DELAYED_WORK_RSL(&priv->rtllib->check_tsf_wq,(void*)rtl8192se_check_tsf_wq, dev);
+	INIT_DELAYED_WORK_RSL(&priv->rtllib->update_assoc_sta_info_wq, 
+			(void*)rtl8192se_update_assoc_sta_info_wq, dev);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	INIT_WORK_RSL(&priv->rtllib->ext_create_crypt_for_peers_wq, (void*)msh_create_crypt_for_peers_wq, dev);
+	INIT_WORK_RSL(&priv->rtllib->ext_path_sel_ops_wq,(void*) path_sel_ops_wq, dev);
+	INIT_WORK_RSL(&priv->rtllib->ext_update_extchnloffset_wq, 
+			(void*) meshdev_update_ext_chnl_offset_as_client, dev);
+	INIT_DELAYED_WORK_RSL(&priv->rtllib->ext_wx_set_key_wq, (void*)ext_mesh_set_key_wq,priv->rtllib);
+	INIT_WORK_RSL(&priv->rtllib->ext_start_mesh_protocol_wq, 
+			(void*) meshdev_start_mesh_protocol_wq, dev);
+#endif
+	tasklet_init(&priv->irq_rx_tasklet,
+	     (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
+	     (unsigned long)priv);
+	tasklet_init(&priv->irq_tx_tasklet,
+	     (void(*)(unsigned long))rtl8192_irq_tx_tasklet,
+	     (unsigned long)priv);
+        tasklet_init(&priv->irq_prepare_beacon_tasklet,
+                (void(*)(unsigned long))rtl8192_prepare_beacon,
+                (unsigned long)priv);
+}
+
+short rtl8192_get_channel_map(struct net_device * dev)
+{
+	int i;
+
+#ifdef ENABLE_DOT11D
+	struct r8192_priv *priv = rtllib_priv(dev);
+	if ((priv->rf_chip != RF_8225) && (priv->rf_chip != RF_8256) 
+			&& (priv->rf_chip != RF_6052)) {
+		RT_TRACE(COMP_ERR, "%s: unknown rf chip, can't set channel map\n", __FUNCTION__);
+		return -1;
+	}
+		
+	if (priv->ChannelPlan > COUNTRY_CODE_MAX) {
+		printk("rtl819x_init:Error channel plan! Set to default.\n");
+		priv->ChannelPlan= COUNTRY_CODE_FCC;
+	}
+	RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
+	Dot11d_Init(priv->rtllib);
+#ifndef CONFIG_CRDA
+	Dot11d_Channelmap(priv->ChannelPlan, priv->rtllib);
+#endif	
+#else
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ch;
+	if(!channels){
+		DMESG("No channels, aborting");
+		return -1;
+	}
+
+	ch = channels;
+	priv->ChannelPlan = 0;
+	for (i = 1; i <= 14; i++) {
+		(priv->rtllib->channel_map)[i] = (u8)(ch & 0x01);
+		ch >>= 1;
+	}
+	priv->rtllib->IbssStartChnl= 10;
+	priv->rtllib->ibss_maxjoin_chal = 11;
+#endif
+	for (i = 1; i <= 11; i++) {
+		(priv->rtllib->active_channel_map)[i] = 1;
+	}
+	(priv->rtllib->active_channel_map)[12] = 2;
+	(priv->rtllib->active_channel_map)[13] = 2;
+	
+	return 0;
+}
+
+short rtl8192_init(struct net_device *dev)
+{		
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	memset(&(priv->stats),0,sizeof(struct Stats));
+#ifdef CONFIG_MP
+	rtl8192_init_mp(dev);
+#endif	
+	
+	rtl8192_init_priv_handler(dev);
+	rtl8192_init_priv_variable(dev);
+#ifdef _RTL8192_EXT_PATCH_
+	rtl8192_init_mesh_variable(dev);
+#endif
+	rtl8192_init_priv_lock(priv);
+	rtl8192_init_priv_task(dev);
+	priv->ops->get_eeprom_size(dev);
+	priv->ops->init_adapter_variable(dev);
+	rtl8192_get_channel_map(dev);
+
+#ifdef CONFIG_CFG_80211
+	/* channel map setting for the cfg80211 style */
+	{
+		struct r8192_priv* priv = rtllib_priv(dev);
+		rtllib_set_geo(priv);	
+	}
+#endif
+
+	init_hal_dm(dev);
+
+#if defined RTL8192SE || defined RTL8192CE
+	InitSwLeds(dev);
+#endif
+	setup_timer(&priv->watch_dog_timer,
+		    watch_dog_timer_callback, 
+		    (unsigned long) dev);
+
+	setup_timer(&priv->gpio_polling_timer, 
+		    check_rfctrl_gpio_timer,
+		    (unsigned long)dev);
+
+	rtl8192_irq_disable(dev);
+#if defined(IRQF_SHARED)
+        if (request_irq(dev->irq, (void*)rtl8192_interrupt_rsl, IRQF_SHARED, dev->name, dev)) 
+#else
+        if (request_irq(dev->irq, (void *)rtl8192_interrupt_rsl, SA_SHIRQ, dev->name, dev)) 
+#endif
+	{
+		printk("Error allocating IRQ %d",dev->irq);
+		return -1;
+	} else { 
+		priv->irq=dev->irq;
+		RT_TRACE(COMP_INIT, "IRQ %d\n",dev->irq);
+	}
+
+	if (rtl8192_pci_initdescring(dev) != 0) { 
+		printk("Endopoints initialization failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef RTL8192CE
+static void
+rtl8192_update_default_setting(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+#ifdef CONFIG_ASPM_OR_D3
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+#endif
+
+	priv->RegPciASPM = 3; 
+
+	priv->RegHwSwRfOffD3 = 0; 
+	
+	priv->RegSupportPciASPM = true;
+	
+	pPSC->RegRfPsLevel = 0;
+	priv->bSupportASPM = 0;
+
+
+	switch(priv->RegPciASPM)
+	{
+	case 0: 
+		break;
+		
+	case 1: 
+		pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
+		break;
+
+	case 2: 
+		pPSC->RegRfPsLevel |= (RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+		break;
+
+	case 3: 
+		pPSC->RegRfPsLevel &= ~(RT_RF_LPS_LEVEL_ASPM);
+		pPSC->RegRfPsLevel |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+		break;
+
+	case 4: 
+		pPSC->RegRfPsLevel &= ~(RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ);
+		pPSC->RegRfPsLevel |= RT_RF_PS_LEVEL_ALWAYS_ASPM;
+		break;
+	}
+
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+
+	switch(priv->RegHwSwRfOffD3)
+	{
+	case 1:
+		if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM)
+			pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+		break;
+
+	case 2:
+		if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM)
+			pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+		pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+		break;
+
+	case 3:
+		pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_PCI_D3;
+		break;
+	}
+
+
+	switch(priv->RegSupportPciASPM)
+	{
+	case 0: 
+		{
+			bool		bSupportASPM = false;
+			priv->bSupportASPM = bSupportASPM;
+		}
+		break;
+
+	case 1: 
+		{
+			bool		bSupportASPM = true;
+			priv->bSupportASPM = bSupportASPM;
+		}
+		break;
+
+	case 2: 
+		if(priv->pci_bridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
+		{
+			bool		bSupportASPM = true;
+			priv->bSupportASPM = bSupportASPM;
+		}
+		break;
+		
+	default:
+		break;
+	}
+}
+#endif
+
+#if defined CONFIG_ASPM_OR_D3
+static void
+rtl8192_initialize_adapter_common(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+#ifdef CONFIG_ASPM_OR_D3
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+#endif
+
+#ifdef RTL8192CE
+	rtl8192_update_default_setting(dev);
+#endif
+
+#ifdef CONFIG_ASPM_OR_D3
+	if(pPSC->RegRfPsLevel & RT_RF_PS_LEVEL_ALWAYS_ASPM)
+	{
+		RT_ENABLE_ASPM(dev);
+		RT_SET_PS_LEVEL(pPSC, RT_RF_PS_LEVEL_ALWAYS_ASPM);
+	}
+#endif
+}
+#endif
+
+/***************************************************************************
+    -------------------------------WATCHDOG STUFF---------------------------
+***************************************************************************/
+short rtl8192_is_tx_queue_empty(struct net_device *dev)
+{
+	int i=0;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	for (i=0; i<=MGNT_QUEUE; i++)
+	{
+		if ((i== TXCMD_QUEUE) || (i == HCCA_QUEUE) )
+			continue;
+		if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0){
+			printk("===>tx queue is not empty:%d, %d\n", i, skb_queue_len(&(&priv->tx_ring[i])->queue));
+			return 0;
+		}
+	}
+	return 1;
+}
+
+RESET_TYPE
+rtl819x_TxCheckStuck(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8			QueueID;
+	u8			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+	bool			bCheckFwTxCnt = false;
+	struct rtl8192_tx_ring  *ring = NULL;
+	struct sk_buff* skb = NULL;
+	cb_desc * tcb_desc = NULL;
+	unsigned long flags = 0;
+	
+#if 0
+	switch (priv->rtllib->dot11PowerSaveMode)
+	{
+		case eActive:		
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL;
+			break;
+		case eMaxPs:		
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+			break;
+		case eFastPs:	
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+			break;
+		default:
+			break;
+	}
+#else
+	switch (priv->rtllib->ps)
+	{
+		case RTLLIB_PS_DISABLED:		
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL;
+			break;
+		case (RTLLIB_PS_MBCAST|RTLLIB_PS_UNICAST):		
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+			break;
+		default:
+			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+			break;
+	}
+#endif
+	spin_lock_irqsave(&priv->irq_th_lock,flags);
+	for(QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++)
+	{
+
+	
+		if(QueueID == TXCMD_QUEUE)
+			continue;
+#ifdef RTL8192CE
+		if((QueueID == 8) || (QueueID == 5))
+			continue;
+#endif
+
+		ring = &priv->tx_ring[QueueID];
+
+		if(skb_queue_len(&ring->queue) == 0)
+			continue;
+		else
+		{
+			skb = (&ring->queue)->next;
+			tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+			tcb_desc->nStuckCount++;
+			bCheckFwTxCnt = true;
+#if defined RTL8192SE || defined RTL8192CE
+			if(tcb_desc->nStuckCount > ResetThreshold)
+			{
+				RT_TRACE( COMP_RESET, "TxCheckStuck(): Need silent reset because nStuckCount > ResetThreshold.\n" );
+                                spin_unlock_irqrestore(&priv->irq_th_lock,flags);				
+				return RESET_TYPE_SILENT;
+			}
+			bCheckFwTxCnt = false;
+			#endif
+		}
+	}
+	spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+	
+	if(bCheckFwTxCnt) {
+		if (priv->ops->TxCheckStuckHandler(dev))
+		{
+			RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
+			return RESET_TYPE_SILENT;
+		}
+	}
+
+	return RESET_TYPE_NORESET;
+}
+
+RESET_TYPE rtl819x_RxCheckStuck(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(priv->ops->RxCheckStuckHandler(dev))
+	{
+		RT_TRACE(COMP_RESET, "RxStuck Condition\n");
+		return RESET_TYPE_SILENT;
+	}
+	
+	return RESET_TYPE_NORESET;
+}
+
+RESET_TYPE
+rtl819x_ifcheck_resetornot(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	RESET_TYPE	TxResetType = RESET_TYPE_NORESET;
+	RESET_TYPE	RxResetType = RESET_TYPE_NORESET;
+	RT_RF_POWER_STATE 	rfState;
+	
+	rfState = priv->rtllib->eRFPowerState;
+	
+	if(rfState == eRfOn)
+		TxResetType = rtl819x_TxCheckStuck(dev);
+	
+	if( rfState == eRfOn && 
+	    (priv->rtllib->iw_mode == IW_MODE_INFRA) && 
+	    (priv->rtllib->state == RTLLIB_LINKED)) {
+
+		RxResetType = rtl819x_RxCheckStuck(dev);
+	}
+	
+	RT_TRACE(COMP_RESET,"%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType);
+	if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL){
+		printk("%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType);
+		return RESET_TYPE_NORMAL;
+	} else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){
+		printk("%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType);
+		return RESET_TYPE_SILENT;
+	} else {
+		return RESET_TYPE_NORESET;
+	}
+
+}
+
+void rtl819x_ifsilentreset(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	reset_times = 0;
+	int reset_status = 0;
+	struct rtllib_device *ieee = priv->rtllib;
+	unsigned long flag;
+#ifdef _RTL8192_EXT_PATCH_
+	bool wlansilentreset = false,meshsilentreset = false;
+	u8 backup_channel_wlan = 1,backup_channel_mesh = 1;
+	u8 updateBW = 0;
+	u8 bserverHT = 0;
+	int i=0;
+	u8 IsPortal = 0;
+#endif	
+		
+	if(priv->ResetProgress==RESET_TYPE_NORESET) {
+
+		RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
+		
+		priv->ResetProgress = RESET_TYPE_SILENT;
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		if(priv->RFChangeInProgress)
+		{
+			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+			goto END;
+		}
+		priv->RFChangeInProgress = true;
+		priv->bResetInProgress = true;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+RESET_START:	
+		down(&priv->wx_sem);	
+#ifdef ENABLE_LPS
+		if(priv->rtllib->state == RTLLIB_LINKED)
+			LeisurePSLeave(dev);
+#endif
+		if(IS_NIC_DOWN(priv))
+		{
+			RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
+			up(&priv->wx_sem);
+			return ;
+		}
+#ifdef _RTL8192_EXT_PATCH_
+		if(priv->up == 1)
+		{
+			printk("================>wlansilentreset is true\n");
+			wlansilentreset = true;
+			priv->up = 0;
+		}
+		if(priv->mesh_up == 1)
+		{
+			printk("================>meshsilentreset is true\n");
+			meshsilentreset = true;
+			priv->mesh_up = 0;
+		}
+#else
+		priv->up = 0;
+#endif
+		RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
+		mdelay(1000);
+		RT_TRACE(COMP_RESET,"%s():111111111111111111111111======>start to down the driver\n",__FUNCTION__);
+		if(!netif_queue_stopped(dev))
+			netif_stop_queue(dev);
+#if !(defined RTL8192SE || defined RTL8192CE)
+		dm_backup_dynamic_mechanism_state(dev);
+#endif
+		rtl8192_irq_disable(dev);
+		del_timer_sync(&priv->watch_dog_timer);	
+		rtl8192_cancel_deferred_work(priv);
+		deinit_hal_dm(dev);
+		rtllib_stop_scan_syncro(ieee);
+#ifdef _RTL8192_EXT_PATCH_
+		backup_channel_wlan = ieee->current_network.channel;
+		backup_channel_mesh = ieee->current_mesh_network.channel;
+		if((ieee->state == RTLLIB_LINKED) && ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_ADHOC)))
+		{
+			printk("====>down, infra or adhoc\n");
+			SEM_DOWN_IEEE_WX(&ieee->wx_sem);
+			printk("ieee->state is RTLLIB_LINKED\n");
+			rtllib_stop_send_beacons(priv->rtllib);
+			del_timer_sync(&ieee->associate_timer);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+			cancel_delayed_work(&ieee->associate_retry_wq);	
+#endif	
+			rtllib_stop_scan(ieee);
+			netif_carrier_off(dev);
+			SEM_UP_IEEE_WX(&ieee->wx_sem);
+		}
+		else if((ieee->iw_mode == IW_MODE_MESH) && (ieee->mesh_state == RTLLIB_MESH_LINKED))
+		{
+			if(priv->mshobj->ext_patch_r819x_wx_get_AsPortal)
+				priv->mshobj->ext_patch_r819x_wx_get_AsPortal(priv, &IsPortal);
+			if((!ieee->only_mesh) && (ieee->state == RTLLIB_LINKED)){
+				printk("====>down, wlan server\n");
+				SEM_DOWN_IEEE_WX(&ieee->wx_sem);
+				printk("ieee->state is RTLLIB_LINKED\n");
+				rtllib_stop_send_beacons(priv->rtllib);
+				del_timer_sync(&ieee->associate_timer);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+				cancel_delayed_work(&ieee->associate_retry_wq);	
+#endif	
+				rtllib_stop_scan(ieee);
+				netif_carrier_off(dev);
+				SEM_UP_IEEE_WX(&ieee->wx_sem);
+				if(priv->mshobj->ext_patch_rtllib_stop_protocol)
+					priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1);
+			}
+			else if((!ieee->only_mesh) && (ieee->state != RTLLIB_LINKED)){
+				printk("====>down, wlan server\n");
+				SEM_DOWN_IEEE_WX(&ieee->wx_sem);
+				printk("ieee->state is Not RTLLIB_LINKED\n");
+				rtllib_stop_send_beacons(priv->rtllib);
+				rtllib_stop_scan(ieee);
+				netif_carrier_off(dev);
+				SEM_UP_IEEE_WX(&ieee->wx_sem);
+				if(priv->mshobj->ext_patch_rtllib_stop_protocol)
+					priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1);
+			}
+			else if(ieee->only_mesh && IsPortal)
+			{
+				printk("====>down, eth0 server\n");
+				if(priv->mshobj->ext_patch_rtllib_stop_protocol)
+					priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1);
+			}
+			else if(ieee->only_mesh && !IsPortal)
+			{
+				printk("====>down, p2p or client\n");
+				if(priv->mshobj->ext_patch_rtllib_stop_protocol)
+					priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1);
+			}
+			else{
+				printk("====>down, no link\n");
+				if(priv->mshobj->ext_patch_rtllib_stop_protocol)
+					priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1);
+			}
+		}
+		else{
+			printk("====>down, no link\n");
+			printk("ieee->state is NOT LINKED\n");
+			rtllib_softmac_stop_protocol(priv->rtllib,0,true);		
+		}
+#else
+		if(ieee->state == RTLLIB_LINKED)
+		{
+			SEM_DOWN_IEEE_WX(&ieee->wx_sem);
+			printk("ieee->state is RTLLIB_LINKED\n");
+			rtllib_stop_send_beacons(priv->rtllib);
+			del_timer_sync(&ieee->associate_timer);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+			cancel_delayed_work(&ieee->associate_retry_wq);	
+#endif	
+			rtllib_stop_scan(ieee);
+			netif_carrier_off(dev);
+			SEM_UP_IEEE_WX(&ieee->wx_sem);
+		}
+		else{
+			printk("ieee->state is NOT LINKED\n");
+			rtllib_softmac_stop_protocol(priv->rtllib,true);		
+		}
+#endif
+#ifdef RTL8190P
+		priv->ops->stop_adapter(dev, true);
+#endif
+		up(&priv->wx_sem);
+		RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);	
+		RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
+#ifdef _RTL8192_EXT_PATCH_
+		if(wlansilentreset == true){
+			reset_status = _rtl8192_up(dev,true);
+		}
+		if(meshsilentreset == true)
+			reset_status = meshdev_up(ieee->meshdev,true);
+#else
+		reset_status = _rtl8192_up(dev,true);
+#endif		
+		RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
+		if(reset_status == -1)
+		{
+			if(reset_times < 3)
+			{
+				reset_times++;
+				goto RESET_START;
+			}
+			else
+			{
+				RT_TRACE(COMP_ERR," ERR!!! %s():  Reset Failed!!\n",__FUNCTION__);
+			}
+		}
+		ieee->is_silent_reset = 1;
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		priv->RFChangeInProgress = false;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+		EnableHWSecurityConfig8192(dev);
+#ifdef _RTL8192_EXT_PATCH_
+		ieee->current_network.channel = backup_channel_wlan;
+		ieee->current_mesh_network.channel = backup_channel_mesh;
+#endif
+		if(ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA)
+		{
+			ieee->set_chan(ieee->dev, ieee->current_network.channel);
+		
+			queue_work_rsl(ieee->wq, &ieee->associate_complete_wq);
+	
+		}
+		else if(ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
+		{
+			ieee->set_chan(ieee->dev, ieee->current_network.channel);
+			ieee->link_change(ieee->dev);
+	
+			notify_wx_assoc_event(ieee);
+	
+			rtllib_start_send_beacons(ieee);
+	
+			if (ieee->data_hard_resume)
+				ieee->data_hard_resume(ieee->dev);
+			netif_carrier_on(ieee->dev);
+		}
+#ifdef _RTL8192_EXT_PATCH_
+		else if (ieee->iw_mode == IW_MODE_MESH) 
+		{
+			if(!ieee->only_mesh) 
+			{	
+				printk("===>up, wlan0 server\n");
+				ieee->set_chan(ieee->dev, ieee->current_network.channel);
+			
+				queue_work_rsl(ieee->wq, &ieee->associate_complete_wq);
+				if (ieee->current_mesh_network.beacon_interval == 0)
+					ieee->current_mesh_network.beacon_interval = 100;
+				ieee->mesh_state = RTLLIB_MESH_LINKED;
+				ieee->link_change(ieee->dev);
+				if(priv->mshobj->ext_patch_rtllib_start_protocol)
+					priv->mshobj->ext_patch_rtllib_start_protocol(ieee);
+			}
+			else if(ieee->only_mesh && IsPortal)
+			{
+				printk("===>up, eth0 server\n");
+				if (ieee->current_mesh_network.beacon_interval == 0)
+					ieee->current_mesh_network.beacon_interval = 100;
+				ieee->mesh_state = RTLLIB_MESH_LINKED;
+				ieee->link_change(ieee->dev);
+				if(priv->mshobj->ext_patch_rtllib_start_protocol)
+					priv->mshobj->ext_patch_rtllib_start_protocol(ieee);
+				ieee->current_network.channel = ieee->current_mesh_network.channel; 
+				if(ieee->pHTInfo->bCurBW40MHz)
+					HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+				else
+					HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+			}
+			else if(ieee->only_mesh && !IsPortal)
+			{
+				printk("===>up, p2p or client\n");
+				if (ieee->current_mesh_network.beacon_interval == 0)
+					ieee->current_mesh_network.beacon_interval = 100;
+				ieee->mesh_state = RTLLIB_MESH_LINKED;
+				ieee->link_change(ieee->dev);
+				if(priv->mshobj->ext_patch_rtllib_start_protocol)
+					priv->mshobj->ext_patch_rtllib_start_protocol(ieee);
+				if(ieee->p2pmode){
+					printk("===>up, p2p\n");
+					ieee->current_network.channel = ieee->current_mesh_network.channel; 
+					if(ieee->pHTInfo->bCurBW40MHz)
+						HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+					else
+						HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+				}else{
+					printk("===>up, client\n");
+					updateBW = priv->mshobj->ext_patch_r819x_wx_update_beacon(ieee->dev,&bserverHT);
+					printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n",
+					ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT);
+					if (updateBW == 1) {
+						if (bserverHT == 0) {
+							printk("===>server is not HT supported,set 20M\n");
+							HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);  
+						} else {
+							printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",
+									ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset);
+							if (ieee->pHTInfo->bCurBW40MHz)
+								HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset);  
+							else
+								HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset);  
+						}
+					} else {
+						printk("===>there is no same hostname server, ERR!!!\n");
+					}
+				}
+			}
+				
+		}
+#endif
+#ifdef TO_DO_LIST
+		else if(Adapter->MgntInfo.mActingAsAp)
+		{
+			AP_StartApRequest((PVOID)Adapter);
+			Adapter->HalFunc.ResetHalRATRTableHandler(Adapter);
+		}
+#endif
+		
+#ifdef TO_DO_LIST
+		if(Adapter->MgntInfo.mActingAsAp)
+			AP_CamRestoreAllEntry(Adapter);
+		else
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+		if(wlansilentreset){
+			printk("==========>wlansilentreset\n");
+			CamRestoreEachIFEntry(dev,0);
+		}
+		if(meshsilentreset){
+			printk("==========>meshsilentreset\n");
+			CamRestoreEachIFEntry(dev,1);
+			for(i=0;i<8;i++)
+			{
+				if(ieee->swmeshratrtable[i].bused == true)
+				{
+					printk("====>restore ratr table: index=%d,value=%x\n",i,ieee->swmeshratrtable[i].ratr_value);
+					write_nic_dword(dev,ARFR0+i*4,ieee->swmeshratrtable[i].ratr_value);
+				}
+			}
+		}
+#else
+		CamRestoreAllEntry(dev);
+#endif
+#if !(defined RTL8192SE || defined RTL8192CE)
+		dm_restore_dynamic_mechanism_state(dev);
+#endif
+END:
+		priv->ResetProgress = RESET_TYPE_NORESET;
+		priv->reset_count++;
+
+		priv->bForcedSilentReset =false;
+		priv->bResetInProgress = false;
+
+#ifdef RTL8190P
+		write_nic_byte(dev, UFWP, 1);	
+#endif
+		RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
+	}
+}
+
+void rtl819x_update_rxcounts(struct r8192_priv *priv,
+			     u32 *TotalRxBcnNum,
+			     u32 *TotalRxDataNum)	
+{
+	u16 			SlotIndex;
+	u8			i;
+
+	*TotalRxBcnNum = 0;
+	*TotalRxDataNum = 0;
+
+	SlotIndex = (priv->rtllib->LinkDetectInfo.SlotIndex++)%(priv->rtllib->LinkDetectInfo.SlotNum);
+	priv->rtllib->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->rtllib->LinkDetectInfo.NumRecvBcnInPeriod;
+	priv->rtllib->LinkDetectInfo.RxDataNum[SlotIndex] = priv->rtllib->LinkDetectInfo.NumRecvDataInPeriod;
+	for (i = 0; i < priv->rtllib->LinkDetectInfo.SlotNum; i++) {	
+		*TotalRxBcnNum += priv->rtllib->LinkDetectInfo.RxBcnNum[i];
+		*TotalRxDataNum += priv->rtllib->LinkDetectInfo.RxDataNum[i];
+	}
+}
+
+
+void	rtl819x_watchdog_wqcallback(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,watch_dog_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+	struct rtllib_device* ieee = priv->rtllib;
+	RESET_TYPE	ResetType = RESET_TYPE_NORESET;
+	static u8	check_reset_cnt = 0;
+#ifdef _RTL8192_EXT_PATCH_
+	static u8	last_reset_count = 0;
+#endif
+	unsigned long flags;
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	bool bBusyTraffic = false;
+#ifdef ENABLE_LPS
+	bool bEnterPS = false;
+#endif
+	if(IS_NIC_DOWN(priv) || (priv->bHwRadioOff == true))
+		return;
+
+	if(priv->rtllib->state >= RTLLIB_LINKED)
+	{
+		if(priv->rtllib->CntAfterLink<2)
+			priv->rtllib->CntAfterLink++;
+	}
+	else
+	{
+		priv->rtllib->CntAfterLink = 0;
+	}
+	
+	hal_dm_watchdog(dev);
+
+#ifdef ENABLE_IPS
+	if(rtllib_act_scanning(priv->rtllib,false) == false){
+		if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == RTLLIB_NOLINK) &&\
+		    (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\
+		    (!ieee->proto_stoppping) && !ieee->wx_set_enc
+#ifdef CONFIG_RTLWIFI_DEBUGFS	    
+		    && (!priv->debug->hw_holding)
+#endif		    
+		 ){
+			if((ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE)&& 
+			    (!ieee->bNetPromiscuousMode))
+			{
+				RT_TRACE(COMP_PS, "====================>haha:IPSEnter()\n");
+				IPSEnter(dev);	
+			}
+		}
+	}
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	MgntLinkKeepAlive(priv);
+#endif
+	{
+		if((ieee->state == RTLLIB_LINKED) && (ieee->iw_mode == IW_MODE_INFRA) && (!ieee->bNetPromiscuousMode))
+		{
+			if(	ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
+				ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
+				bBusyTraffic = true;
+			}
+			
+#ifdef ENABLE_LPS
+			if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+				(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+			{
+				bEnterPS= false;
+			}
+			else
+			{
+				bEnterPS= true;
+			}
+
+			if (ieee->current_network.beacon_interval < 95)
+				bEnterPS= false;
+
+			if(bEnterPS)
+			{
+				LeisurePSEnter(dev);
+			}
+			else
+			{
+				LeisurePSLeave(dev);
+			}
+#endif
+		
+		}
+		else
+		{
+#ifdef ENABLE_LPS
+			RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
+			LeisurePSLeave(dev);
+#endif
+		}
+
+	       ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
+	       ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+	       ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+	       ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
+	}
+
+	{
+#if defined RTL8192SE 
+		if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+			IbssAgeFunction(ieee);
+#endif
+			
+		if(ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA)
+		{
+			u32	TotalRxBcnNum = 0;
+			u32	TotalRxDataNum = 0;	
+
+			rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
+
+			if((TotalRxBcnNum+TotalRxDataNum) == 0)
+				priv->check_roaming_cnt ++;
+			else
+				priv->check_roaming_cnt = 0;
+
+
+			if(priv->check_roaming_cnt > 0)
+			{
+				if( ieee->eRFPowerState == eRfOff)
+					RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
+
+				printk("===>%s(): AP is power off,chan:%d, connect another one\n",__FUNCTION__, priv->chan);
+
+				ieee->state = RTLLIB_ASSOCIATING;
+
+#if defined(RTL8192S_WAPI_SUPPORT)				
+				if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable))
+					WapiReturnOneStaInfo(ieee,priv->rtllib->current_network.bssid,0);
+#endif
+				RemovePeerTS(priv->rtllib,priv->rtllib->current_network.bssid);
+				ieee->is_roaming = true;
+				ieee->is_set_key = false;
+                                ieee->link_change(dev);
+			        if(ieee->LedControlHandler)
+				   ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); 
+
+				notify_wx_assoc_event(ieee); 
+
+				queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0);
+
+				priv->check_roaming_cnt = 0;
+			}
+		}
+	      ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
+              ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
+		
+	}
+
+	spin_lock_irqsave(&priv->tx_lock,flags);
+	if((check_reset_cnt++ >= 3) && (!ieee->is_roaming) && 
+			(!priv->RFChangeInProgress) && (!pPSC->bSwRfProcessing))
+	{
+    		ResetType = rtl819x_ifcheck_resetornot(dev);
+#ifdef _RTL8192_EXT_PATCH_
+		if(check_reset_cnt == 0xFF)
+#endif
+		check_reset_cnt = 3;
+	}
+	spin_unlock_irqrestore(&priv->tx_lock,flags);
+	
+	if(!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL)
+	{
+		priv->ResetProgress = RESET_TYPE_NORMAL;
+		RT_TRACE(COMP_RESET,"%s(): NOMAL RESET\n",__FUNCTION__);
+		return;
+	}
+
+#ifdef _RTL8192_EXT_PATCH_
+	if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) 
+	{
+			if((check_reset_cnt != (last_reset_count + 1)) && !priv->force_reset){
+				printk("=======================>%s: Resume firmware\n", __FUNCTION__);
+				r8192se_resume_firm(dev);	
+				last_reset_count = check_reset_cnt;
+			}else{
+				printk("=======================>%s: Silent Reset\n", __FUNCTION__);
+				rtl819x_ifsilentreset(dev);
+			}
+	}
+#else
+	if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) 
+	{
+		rtl819x_ifsilentreset(dev);
+	}
+#endif
+	priv->force_reset = false;
+	priv->bForcedSilentReset = false;
+	priv->bResetInProgress = false;
+	RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
+	
+}
+
+void watch_dog_timer_callback(unsigned long data)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *) data);
+	queue_delayed_work_rsl(priv->priv_wq,&priv->watch_dog_wq,0);
+	mod_timer(&priv->watch_dog_timer, jiffies + MSECS(RTLLIB_WATCH_DOG_TIME));
+}
+
+/****************************************************************************
+ ---------------------------- NIC TX/RX STUFF---------------------------
+*****************************************************************************/
+void rtl8192_rx_enable(struct net_device *dev)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	priv->ops->rx_enable(dev);
+}
+
+void rtl8192_tx_enable(struct net_device *dev)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	
+	priv->ops->tx_enable(dev);
+
+    rtllib_reset_queue(priv->rtllib);
+}
+
+
+static void rtl8192_free_rx_ring(struct net_device *dev)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    	int i,rx_queue_idx;
+
+	for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){
+    for (i = 0; i < priv->rxringcount; i++) {
+        		struct sk_buff *skb = priv->rx_buf[rx_queue_idx][i];
+        if (!skb)
+            continue;
+
+        pci_unmap_single(priv->pdev,
+                *((dma_addr_t *)skb->cb),
+                priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+        kfree_skb(skb);
+    }
+
+    		pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount,
+            		priv->rx_ring[rx_queue_idx], priv->rx_ring_dma[rx_queue_idx]);
+    		priv->rx_ring[rx_queue_idx] = NULL;
+	}
+}
+
+static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+    while (skb_queue_len(&ring->queue)) {
+        tx_desc *entry = &ring->desc[ring->idx];
+        struct sk_buff *skb = __skb_dequeue(&ring->queue);
+
+        pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
+                skb->len, PCI_DMA_TODEVICE);
+        kfree_skb(skb);
+        ring->idx = (ring->idx + 1) % ring->entries;
+    }
+
+    pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
+            ring->desc, ring->dma);
+    ring->desc = NULL;
+}
+
+void rtl8192_data_hard_stop(struct net_device *dev)
+{
+	#if 0
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	priv->dma_poll_mask |= (1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
+	rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
+	write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
+	rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
+	#endif
+}
+
+
+void rtl8192_data_hard_resume(struct net_device *dev)
+{
+	#if 0
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	priv->dma_poll_mask &= ~(1<<TX_DMA_STOP_LOWPRIORITY_SHIFT);
+	rtl8192_set_mode(dev,EPROM_CMD_CONFIG);
+	write_nic_byte(dev,TX_DMA_POLLING,priv->dma_poll_mask);
+	rtl8192_set_mode(dev,EPROM_CMD_NORMAL);
+	#endif
+}
+
+void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	int ret;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	u8 queue_index = tcb_desc->queue_index;
+	
+	if((priv->rtllib->eRFPowerState == eRfOff) || IS_NIC_DOWN(priv) || priv->bResetInProgress){
+		kfree_skb(skb);
+		return;	
+	}
+	
+	assert(queue_index != TXCMD_QUEUE);
+
+
+        memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+#if 0
+	tcb_desc->RATRIndex = 7;
+	tcb_desc->bTxDisableRateFallBack = 1;
+	tcb_desc->bTxUseDriverAssingedRate = 1;
+	tcb_desc->bTxEnableFwCalcDur = 1;
+#endif
+	skb_push(skb, priv->rtllib->tx_headroom);
+	ret = rtl8192_tx(dev, skb);
+	if(ret != 0) {
+		kfree_skb(skb);
+	};
+
+	if(queue_index!=MGNT_QUEUE) {
+		priv->rtllib->stats.tx_bytes+=(skb->len - priv->rtllib->tx_headroom);
+		priv->rtllib->stats.tx_packets++;
+	}
+
+
+	return;
+}
+
+int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	int ret;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	u8 queue_index = tcb_desc->queue_index;
+
+	if(queue_index != TXCMD_QUEUE){
+		if((priv->rtllib->eRFPowerState == eRfOff) ||IS_NIC_DOWN(priv) || priv->bResetInProgress){
+			kfree_skb(skb);
+			return 0;	
+		}
+	}
+
+	memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+	if(queue_index == TXCMD_QUEUE) {
+		rtl8192_tx_cmd(dev, skb);
+		ret = 0;
+		return ret;
+	} else {
+		tcb_desc->RATRIndex = 7;
+		tcb_desc->bTxDisableRateFallBack = 1;
+		tcb_desc->bTxUseDriverAssingedRate = 1;
+		tcb_desc->bTxEnableFwCalcDur = 1;
+		skb_push(skb, priv->rtllib->tx_headroom);
+		ret = rtl8192_tx(dev, skb);
+		if(ret != 0) {
+			kfree_skb(skb);
+		};
+	}
+	
+	
+	
+	return ret;
+
+}
+
+void rtl8192_tx_isr(struct net_device *dev, int prio)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+    struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+    while (skb_queue_len(&ring->queue)) {
+        tx_desc *entry = &ring->desc[ring->idx];
+        struct sk_buff *skb;
+
+        if(prio != BEACON_QUEUE) {
+            if(entry->OWN)
+                return;
+            ring->idx = (ring->idx + 1) % ring->entries;
+        }
+
+        skb = __skb_dequeue(&ring->queue);
+        pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
+                skb->len, PCI_DMA_TODEVICE);
+
+        kfree_skb(skb);
+    }
+    if(prio == MGNT_QUEUE)
+             ;
+    if(prio != BEACON_QUEUE) {
+        tasklet_schedule(&priv->irq_tx_tasklet);
+    }
+
+}
+
+void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    struct rtl8192_tx_ring *ring;
+    tx_desc_cmd* entry;
+    unsigned int idx;
+    cb_desc *tcb_desc;
+    unsigned long flags;
+
+    spin_lock_irqsave(&priv->irq_th_lock,flags);
+    ring = &priv->tx_ring[TXCMD_QUEUE];
+
+    idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
+    entry = (tx_desc_cmd*) &ring->desc[idx];
+
+    tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+    
+    priv->ops->tx_fill_cmd_descriptor(dev, entry, tcb_desc, skb);
+
+    __skb_queue_tail(&ring->queue, skb);
+    spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+
+    return;
+}
+
+short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
+{
+    	struct r8192_priv *priv = rtllib_priv(dev);
+    	struct rtl8192_tx_ring  *ring;
+    	unsigned long flags;
+    	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+    	tx_desc *pdesc = NULL;
+    	struct rtllib_hdr_1addr * header = NULL;
+    	u16 fc=0, type=0,stype=0;
+    	bool  multi_addr=false,broad_addr=false,uni_addr=false;
+    	u8*   pda_addr = NULL;
+    	int   idx;
+    	u32 fwinfo_size = 0;
+
+    	if(priv->bdisable_nic){
+        	RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index);
+			return skb->len;
+    	}
+
+    	priv->rtllib->bAwakePktSent = true;
+	
+#if defined RTL8192SE || defined RTL8192CE
+    	fwinfo_size = 0;
+#else
+   	fwinfo_size = sizeof(TX_FWINFO_8190PCI);
+#endif
+
+    	header = (struct rtllib_hdr_1addr *)(((u8*)skb->data) + fwinfo_size);
+    	fc = header->frame_ctl;
+    	type = WLAN_FC_GET_TYPE(fc);
+    	stype = WLAN_FC_GET_STYPE(fc);
+    	pda_addr = header->addr1;
+		
+    	if(is_multicast_ether_addr(pda_addr))
+        	multi_addr = true;
+    	else if(is_broadcast_ether_addr(pda_addr))
+        	broad_addr = true;
+    	else {
+#ifdef _RTL8192_EXT_PATCH_
+        	priv->NumTxUnicast++;
+#endif
+        	uni_addr = true;
+    	}
+		
+    	if(uni_addr)
+        	priv->stats.txbytesunicast += skb->len - fwinfo_size;
+    	else if(multi_addr)
+        	priv->stats.txbytesmulticast += skb->len - fwinfo_size;
+    	else 
+        	priv->stats.txbytesbroadcast += skb->len - fwinfo_size;
+
+    	spin_lock_irqsave(&priv->irq_th_lock,flags);
+    	ring = &priv->tx_ring[tcb_desc->queue_index];
+    	if (tcb_desc->queue_index != BEACON_QUEUE) {
+        	idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
+    	} else {
+        	idx = 0;
+    	}
+
+    	pdesc = &ring->desc[idx];
+	if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
+		RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d, skblen = 0x%x", \
+				tcb_desc->queue_index,ring->idx, idx,skb->len);
+		spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+		return skb->len;
+	} 
+
+	if(tcb_desc->queue_index == MGNT_QUEUE)
+	{
+	}
+
+	if(type == RTLLIB_FTYPE_DATA){
+	    	if(priv->rtllib->LedControlHandler)
+			priv->rtllib->LedControlHandler(dev, LED_CTL_TX);
+    	}
+    	priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, skb);
+    	__skb_queue_tail(&ring->queue, skb);
+    	pdesc->OWN = 1;
+    	spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+    	dev->trans_start = jiffies;
+
+#ifdef RTL8192CE 
+	if(tcb_desc->queue_index == BEACON_QUEUE){
+		write_nic_word(dev, REG_PCIE_CTRL_REG, BIT4);
+	}else{
+		write_nic_word(dev, REG_PCIE_CTRL_REG, BIT0<<(tcb_desc->queue_index));
+	}
+#else
+		write_nic_word(dev,TPPoll,0x01<<tcb_desc->queue_index);
+#endif
+	return 0;	
+}
+
+short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
+{
+    	struct r8192_priv *priv = rtllib_priv(dev);
+    	rx_desc *entry = NULL;
+    	int i, rx_queue_idx;
+
+	for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){
+    		priv->rx_ring[rx_queue_idx] = pci_alloc_consistent(priv->pdev,
+            	sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, &priv->rx_ring_dma[rx_queue_idx]);
+
+    		if (!priv->rx_ring[rx_queue_idx] || (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) {
+        		RT_TRACE(COMP_ERR,"Cannot allocate RX ring\n");
+        		return -ENOMEM;
+    		}
+
+    		memset(priv->rx_ring[rx_queue_idx], 0, sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount);
+    		priv->rx_idx[rx_queue_idx] = 0;
+
+    		for (i = 0; i < priv->rxringcount; i++) {
+        		struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize);
+        		dma_addr_t *mapping;
+        		entry = &priv->rx_ring[rx_queue_idx][i];
+        		if (!skb)
+            			return 0;
+        		skb->dev = dev;
+        		priv->rx_buf[rx_queue_idx][i] = skb;
+        		mapping = (dma_addr_t *)skb->cb;
+        		*mapping = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb),
+                	priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+
+        		entry->BufferAddress = cpu_to_le32(*mapping);
+
+        		entry->Length = priv->rxbuffersize;
+        		entry->OWN = 1;
+    		}
+
+    		entry->EOR = 1;
+	}
+    	return 0;
+}
+
+static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
+        unsigned int prio, unsigned int entries)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+    tx_desc *ring;
+    dma_addr_t dma;
+    int i;
+
+    ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+    if (!ring || (unsigned long)ring & 0xFF) {
+        RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", prio);
+        return -ENOMEM;
+    }
+
+    memset(ring, 0, sizeof(*ring)*entries);
+    priv->tx_ring[prio].desc = ring;
+    priv->tx_ring[prio].dma = dma;
+    priv->tx_ring[prio].idx = 0;
+    priv->tx_ring[prio].entries = entries;
+    skb_queue_head_init(&priv->tx_ring[prio].queue);
+
+    for (i = 0; i < entries; i++)
+        ring[i].NextDescAddress =
+            cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring));
+
+    return 0;
+}
+
+                    
+short rtl8192_pci_initdescring(struct net_device *dev)
+{
+    u32 ret;
+    int i;
+    struct r8192_priv *priv = rtllib_priv(dev);
+
+    ret = rtl8192_alloc_rx_desc_ring(dev);
+    if (ret) {
+        return ret;
+    }
+    
+
+    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
+        if ((ret = rtl8192_alloc_tx_desc_ring(dev, i, priv->txringcount)))
+            goto err_free_rings;
+    }
+
+#if 0
+    if ((ret = rtl8192_alloc_tx_desc_ring(dev, MAX_TX_QUEUE_COUNT - 1, 2)))
+        goto err_free_rings;
+#endif    
+
+    return 0;
+
+err_free_rings:
+    rtl8192_free_rx_ring(dev);
+    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+        if (priv->tx_ring[i].desc)
+            rtl8192_free_tx_ring(dev, i);
+    return 1;
+}
+
+void rtl8192_pci_resetdescring(struct net_device *dev)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    	int i,rx_queue_idx;
+    unsigned long flags = 0;
+
+	for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){	
+    		if(priv->rx_ring[rx_queue_idx]) {
+        		rx_desc *entry = NULL;
+        		for (i = 0; i < priv->rxringcount; i++) {
+            			entry = &priv->rx_ring[rx_queue_idx][i];
+            			entry->OWN = 1;
+        		}
+        		priv->rx_idx[rx_queue_idx] = 0;
+    		}
+	}
+
+    spin_lock_irqsave(&priv->irq_th_lock,flags);
+    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
+        if (priv->tx_ring[i].desc) {
+            struct rtl8192_tx_ring *ring = &priv->tx_ring[i];
+
+            while (skb_queue_len(&ring->queue)) {
+                tx_desc *entry = &ring->desc[ring->idx];
+                struct sk_buff *skb = __skb_dequeue(&ring->queue);
+
+                pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
+                        skb->len, PCI_DMA_TODEVICE);
+                kfree_skb(skb);
+                ring->idx = (ring->idx + 1) % ring->entries;
+            }
+            ring->idx = 0;
+        }
+    }
+    spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+}
+
+void rtl819x_UpdateRxPktTimeStamp (struct net_device *dev, struct rtllib_rx_stats *stats)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	if(stats->bIsAMPDU && !stats->bFirstMPDU) {
+		stats->mac_time[0] = priv->LastRxDescTSFLow;
+		stats->mac_time[1] = priv->LastRxDescTSFHigh;
+	} else {
+		priv->LastRxDescTSFLow = stats->mac_time[0];
+		priv->LastRxDescTSFHigh = stats->mac_time[1];
+	}
+}
+
+long rtl819x_translate_todbm(struct r8192_priv * priv, u8 signal_strength_index	)
+{
+	long	signal_power; 
+
+#ifdef _RTL8192_EXT_PATCH_
+	if(priv->CustomerID == RT_CID_819x_Lenovo)
+	{	
+		signal_power = (long)signal_strength_index;
+		if(signal_power >= 45)
+			signal_power -= 110;
+		else
+		{
+			signal_power = ((signal_power*6)/10);
+			signal_power -= 93;
+		}
+		return signal_power;
+	}
+#endif
+	signal_power = (long)((signal_strength_index + 1) >> 1); 
+	signal_power -= 95; 
+
+	return signal_power;
+}
+
+
+void
+rtl819x_update_rxsignalstatistics8190pci(
+	struct r8192_priv * priv,
+	struct rtllib_rx_stats * pprevious_stats
+	)
+{
+	int weighting = 0;
+
+
+	if(priv->stats.recv_signal_power == 0)
+		priv->stats.recv_signal_power = pprevious_stats->RecvSignalPower;
+
+	if(pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power)
+		weighting = 5;
+	else if(pprevious_stats->RecvSignalPower < priv->stats.recv_signal_power)
+		weighting = (-5);
+	priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pprevious_stats->RecvSignalPower + weighting) / 6;
+}
+
+void
+rtl819x_process_cck_rxpathsel(
+	struct r8192_priv * priv,
+	struct rtllib_rx_stats * pprevious_stats
+	)
+{
+#ifdef RTL8190P	
+	char				last_cck_adc_pwdb[4]={0,0,0,0};
+	u8				i;
+		if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable)
+		{
+			if(pprevious_stats->bIsCCK && 
+				(pprevious_stats->bPacketToSelf ||pprevious_stats->bPacketBeacon))
+			{
+				if(priv->stats.cck_adc_pwdb.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX)
+				{
+					priv->stats.cck_adc_pwdb.TotalNum = PHY_RSSI_SLID_WIN_MAX;
+					for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
+					{
+						last_cck_adc_pwdb[i] = priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index];
+						priv->stats.cck_adc_pwdb.TotalVal[i] -= last_cck_adc_pwdb[i];
+					}
+				}
+				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
+				{
+					priv->stats.cck_adc_pwdb.TotalVal[i] += pprevious_stats->cck_adc_pwdb[i];
+					priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index] = pprevious_stats->cck_adc_pwdb[i];
+				}
+				priv->stats.cck_adc_pwdb.index++;
+				if(priv->stats.cck_adc_pwdb.index >= PHY_RSSI_SLID_WIN_MAX)
+					priv->stats.cck_adc_pwdb.index = 0;
+
+				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
+				{
+					DM_RxPathSelTable.cck_pwdb_sta[i] = priv->stats.cck_adc_pwdb.TotalVal[i]/priv->stats.cck_adc_pwdb.TotalNum;
+				}
+
+				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
+				{
+					if(pprevious_stats->cck_adc_pwdb[i]  > (char)priv->undecorated_smoothed_cck_adc_pwdb[i])
+					{
+						priv->undecorated_smoothed_cck_adc_pwdb[i] = 
+							( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) + 
+							(pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
+						priv->undecorated_smoothed_cck_adc_pwdb[i] = priv->undecorated_smoothed_cck_adc_pwdb[i] + 1;
+					}
+					else
+					{
+						priv->undecorated_smoothed_cck_adc_pwdb[i] = 
+							( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) + 
+							(pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
+					}
+				}
+			}
+		}
+#endif
+}
+
+
+u8 rtl819x_query_rxpwrpercentage(
+	char		antpower
+	)
+{
+	if ((antpower <= -100) || (antpower >= 20))
+	{
+		return	0;
+	}
+	else if (antpower >= 0)
+	{
+		return	100;
+	}
+	else
+	{
+		return	(100+antpower);
+	}
+	
+}	/* QueryRxPwrPercentage */
+
+u8 
+rtl819x_evm_dbtopercentage(
+	char value
+	)
+{
+	char ret_val;
+	
+	ret_val = value;
+	
+	if(ret_val >= 0)
+		ret_val = 0;
+	if(ret_val <= -33)
+		ret_val = -33;
+	ret_val = 0 - ret_val;
+	ret_val*=3;
+	if(ret_val == 99)
+		ret_val = 100;
+	return(ret_val);
+}
+
+void
+rtl8192_record_rxdesc_forlateruse(
+	struct rtllib_rx_stats * psrc_stats,
+	struct rtllib_rx_stats * ptarget_stats
+)
+{
+	ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
+	ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
+}
+
+
+
+void rtl8192_rx_normal(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_hdr_1addr *rtllib_hdr = NULL;
+	bool unicast_packet = false;
+	bool bLedBlinking=true;
+	u16 fc=0, type=0;
+	u32 skb_len = 0;
+	int rx_queue_idx = RX_MPDU_QUEUE;
+	
+	struct rtllib_rx_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+		.freq = RTLLIB_24GHZ_BAND,
+	};
+	unsigned int count = priv->rxringcount;
+
+	stats.nic_type = NIC_8192E;
+
+	while (count--) {
+		rx_desc *pdesc = &priv->rx_ring[rx_queue_idx][priv->rx_idx[rx_queue_idx]];
+		struct sk_buff *skb = priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]];
+
+		if (pdesc->OWN){
+			return;
+		} else {
+
+			struct sk_buff *new_skb = NULL;
+			if (!priv->ops->rx_query_status_descriptor(dev, &stats, pdesc, skb))
+				goto done;
+
+			pci_unmap_single(priv->pdev,
+					*((dma_addr_t *)skb->cb), 
+					priv->rxbuffersize, 
+					PCI_DMA_FROMDEVICE);
+
+			skb_put(skb, pdesc->Length);
+			skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift);
+			skb_trim(skb, skb->len - 4/*sCrcLng*/);
+			rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
+			if(is_broadcast_ether_addr(rtllib_hdr->addr1)) {
+			}else if(is_multicast_ether_addr(rtllib_hdr->addr1)){
+			}else {
+				/* unicast packet */
+				unicast_packet = true;
+			}
+			fc = le16_to_cpu(rtllib_hdr->frame_ctl);
+			type = WLAN_FC_GET_TYPE(fc);
+			if(type == RTLLIB_FTYPE_MGMT)
+			{
+				bLedBlinking = false;
+			}
+			if(bLedBlinking)
+				if(priv->rtllib->LedControlHandler)
+				priv->rtllib->LedControlHandler(dev, LED_CTL_RX);
+
+			if(stats.bCRC) {
+				if(type != RTLLIB_FTYPE_MGMT)
+					priv->stats.rxdatacrcerr ++;
+				else
+					priv->stats.rxmgmtcrcerr ++;
+			}
+
+			skb_len = skb->len;
+			
+#ifdef RTL8192CE
+			if (!stats.bCRC)
+#else
+			if (1)
+#endif
+			{
+			if(!rtllib_rx(priv->rtllib, skb, &stats)){
+				dev_kfree_skb_any(skb);
+			} else {
+				priv->stats.rxok++;
+				if(unicast_packet) {
+					priv->stats.rxbytesunicast += skb_len;
+				}
+			}
+			}else{
+				dev_kfree_skb_any(skb);
+			}
+#if 1
+			new_skb = dev_alloc_skb(priv->rxbuffersize);
+			if (unlikely(!new_skb))
+			{
+				printk("==========>can't alloc skb for rx\n");
+				goto done;
+			}
+			skb=new_skb;
+                        skb->dev = dev;
+#endif
+			priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb;
+			*((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+
+		}
+done:
+		pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
+		pdesc->OWN = 1;
+		pdesc->Length = priv->rxbuffersize;
+		if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1)
+			pdesc->EOR = 1;
+		priv->rx_idx[rx_queue_idx] = (priv->rx_idx[rx_queue_idx] + 1) % priv->rxringcount;
+	}
+
+}
+
+void rtl8192_rx_cmd(struct net_device *dev)
+{
+#ifdef RTL8192SE
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	unsigned int count = priv->rxringcount;
+	int rx_queue_idx = RX_CMD_QUEUE;
+
+	struct rtllib_rx_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+		.freq = RTLLIB_24GHZ_BAND,
+	};
+	stats.nic_type = NIC_8192E;
+
+	while (count--) {
+		rx_desc *pdesc = &priv->rx_ring[rx_queue_idx][priv->rx_idx[rx_queue_idx]];
+		struct sk_buff *skb = priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]];
+
+		if (pdesc->OWN){
+			return;
+		} else {
+			struct sk_buff *new_skb = NULL;
+
+			pci_unmap_single(priv->pdev,
+					*((dma_addr_t *)skb->cb), 
+					priv->rxbuffersize, 
+					PCI_DMA_FROMDEVICE);
+
+			skb_put(skb, pdesc->Length);
+
+			if(pdesc->MACID == 0x1e){
+
+				pdesc->Length = pdesc->Length - 32;
+				pdesc->DrvInfoSize = 4; 
+				printk(">>>>%s()CMD PKT RX, beacon_len:%d payload_len:%d\n",__func__, pdesc->Length,skb->len);
+				
+				
+				priv->ops->rx_query_status_descriptor(dev, &stats, pdesc, skb);
+				skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift);
+                                if(0)
+				{
+					u8 i = 0;
+					u8 *arry = (u8*) skb->data;
+
+					printk("\n==============>\n");
+					for(i = 0; i < 32; i ++){
+						if((i % 4 == 0)&&(i != 0))
+							printk("\n");
+						printk("%2.2x ", arry[i]);
+					}
+					printk("\n<==============\n");
+				}
+			}
+
+			skb_trim(skb, skb->len - 4/*sCrcLng*/);
+
+			if(pdesc->MACID == 0x1e){
+				if(!rtllib_rx(priv->rtllib, skb, &stats)){
+					dev_kfree_skb_any(skb);
+				} 
+			}else{
+			if(priv->ops->rx_command_packet_handler != NULL)
+				priv->ops->rx_command_packet_handler(dev, skb, pdesc);
+			dev_kfree_skb_any(skb);
+			}
+
+		
+			new_skb = dev_alloc_skb(priv->rxbuffersize);
+			if (unlikely(!new_skb))
+			{
+				printk("==========>can't alloc skb for rx\n");
+				goto done;
+			}
+			skb=new_skb;
+                        skb->dev = dev;
+
+			priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb;
+			*((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+
+		}
+done:
+		pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
+		pdesc->OWN = 1;
+		pdesc->Length = priv->rxbuffersize;
+		if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1)
+			pdesc->EOR = 1;
+		priv->rx_idx[rx_queue_idx] = (priv->rx_idx[rx_queue_idx] + 1) % priv->rxringcount;
+	}
+#endif
+}
+
+
+void rtl8192_tx_resume(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	struct sk_buff *skb;
+	int queue_index;
+
+	for(queue_index = BK_QUEUE; queue_index < TXCMD_QUEUE;queue_index++) {
+		while((!skb_queue_empty(&ieee->skb_waitQ[queue_index]))&&
+				(priv->rtllib->check_nic_enough_desc(dev,queue_index) > 0)) {
+			skb = skb_dequeue(&ieee->skb_waitQ[queue_index]);
+			ieee->softmac_data_hard_start_xmit(skb,dev,0/* rate useless now*/);
+			#if 0
+			if(queue_index!=MGNT_QUEUE) {
+				ieee->stats.tx_packets++;
+				ieee->stats.tx_bytes += skb->len;
+			}
+			#endif
+		}
+#ifdef ENABLE_AMSDU
+		while((skb_queue_len(&priv->rtllib->skb_aggQ[queue_index]) > 0)&&\
+				(!(priv->rtllib->queue_stop)) && \
+				(priv->rtllib->check_nic_enough_desc(dev,queue_index) > 0)){
+
+			struct sk_buff_head pSendList;
+			u8 dst[ETH_ALEN];
+			cb_desc *tcb_desc = NULL;
+			int qos_actived = priv->rtllib->current_network.qos_data.active;
+			struct sta_info *psta = NULL;
+			u8 bIsSptAmsdu = false;
+
+#ifdef WIFI_TEST 
+			if (queue_index <= VO_QUEUE)
+				queue_index = wmm_queue_select(priv, queue_index, priv->rtllib->skb_aggQ);
+#endif
+			priv->rtllib->amsdu_in_process = true;
+
+			skb = skb_dequeue(&(priv->rtllib->skb_aggQ[queue_index]));
+			if(skb == NULL)
+			{
+				printk("In %s:Skb is NULL\n",__FUNCTION__);
+				return;
+			}
+			tcb_desc = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE);
+			if(tcb_desc->bFromAggrQ)
+			{
+				rtllib_xmit_inter(skb, dev);
+				return;
+			}
+
+			memcpy(dst, skb->data, ETH_ALEN);
+			if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+			{
+				psta = GetStaInfo(priv->rtllib, dst);
+				if(psta) {
+					if(psta->htinfo.bEnableHT)
+						bIsSptAmsdu = true;
+				}
+			}
+			else if(priv->rtllib->iw_mode == IW_MODE_INFRA)
+				bIsSptAmsdu = true;
+			else
+				bIsSptAmsdu = true;
+			bIsSptAmsdu = true;
+
+			bIsSptAmsdu = bIsSptAmsdu && priv->rtllib->pHTInfo->bCurrent_AMSDU_Support && qos_actived;
+
+			if(qos_actived &&       !is_broadcast_ether_addr(dst) &&
+					!is_multicast_ether_addr(dst) &&
+					bIsSptAmsdu)
+			{
+				skb_queue_head_init(&pSendList);
+				if(AMSDU_GetAggregatibleList(priv->rtllib, skb, &pSendList,queue_index))
+				{
+					struct sk_buff * pAggrSkb = AMSDU_Aggregation(priv->rtllib, &pSendList);
+					if(NULL != pAggrSkb)
+						rtllib_xmit_inter(pAggrSkb, dev);
+				}
+			}
+			else
+			{
+				memset(skb->cb,0,sizeof(skb->cb));
+				tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+				tcb_desc->bFromAggrQ = true;
+				rtllib_xmit_inter(skb, dev);
+			}
+		}
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+		while((!skb_queue_empty(&priv->rtllib->skb_meshaggQ[queue_index]) )&&\
+			(priv->rtllib->check_nic_enough_desc(dev,queue_index)> 0))
+		{
+			struct sk_buff_head pSendList;
+			u8 dst[ETH_ALEN];
+			cb_desc *tcb_desc = NULL;
+			u8 IsHTEnable = false;
+			int qos_actived = 1; 
+			priv->rtllib->mesh_amsdu_in_process = true;
+			skb = skb_dequeue(&(priv->rtllib->skb_meshaggQ[queue_index]));
+			if(skb == NULL)
+			{
+				priv->rtllib->mesh_amsdu_in_process = false;
+				printk("In %s:Skb is NULL\n",__FUNCTION__);
+				return;
+			}
+			tcb_desc = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE);
+			if(tcb_desc->bFromAggrQ)
+			{
+				rtllib_mesh_xmit(skb, dev);
+				continue;
+			}
+			memcpy(dst, skb->data, ETH_ALEN);
+			
+#if 0
+			ppeerMP_htinfo phtinfo = NULL;
+			bool is_mesh = false;
+			if(priv->mshobj->ext_patch_rtllib_is_mesh)
+				is_mesh = priv->mshobj->ext_patch_rtllib_is_mesh(priv->rtllib,dst);
+			if(is_mesh){
+				if(priv->rtllib->ext_patch_rtllib_get_peermp_htinfo)
+				{
+					phtinfo = priv->rtllib->ext_patch_rtllib_get_peermp_htinfo(ieee,dst);
+					if(phtinfo == NULL)
+					{
+						RT_TRACE(COMP_ERR,"%s(): No htinfo\n",__FUNCTION__);
+					}
+					else
+					{
+						if(phtinfo->bEnableHT)
+							IsHTEnable = true;
+					}	
+				}
+			}
+			else 
+			{
+				printk("===>%s():tx AMSDU data has not entry,dst: "MAC_FMT"\n",__FUNCTION__,MAC_ARG(dst));
+				IsHTEnable = true;
+			}
+#else
+			IsHTEnable = true;
+#endif
+			IsHTEnable = (IsHTEnable && ieee->pHTInfo->bCurrent_Mesh_AMSDU_Support && qos_actived);
+			if( !is_broadcast_ether_addr(dst) && 
+				!is_multicast_ether_addr(dst) &&
+				IsHTEnable) 
+			{
+				skb_queue_head_init(&pSendList);
+				if(msh_AMSDU_GetAggregatibleList(priv->rtllib, skb, &pSendList,queue_index))
+				{				
+					struct sk_buff * pAggrSkb = msh_AMSDU_Aggregation(priv->rtllib, &pSendList);
+					if(NULL != pAggrSkb)
+						rtllib_mesh_xmit(pAggrSkb, dev);
+				}else{
+					priv->rtllib->mesh_amsdu_in_process = false;
+					return;
+				}
+			}
+			else
+			{
+				memset(skb->cb,0,sizeof(skb->cb));
+				tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+				tcb_desc->bFromAggrQ = true;
+				rtllib_mesh_xmit(skb, dev);
+			}
+		}
+#endif		
+	}
+}
+
+void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
+{
+       rtl8192_tx_resume(priv->rtllib->dev);
+}
+
+void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
+{
+       	rtl8192_rx_normal(priv->rtllib->dev);
+
+	if(MAX_RX_QUEUE > 1)
+		rtl8192_rx_cmd(priv->rtllib->dev);
+	
+#ifndef RTL8192CE
+       write_nic_dword(priv->rtllib->dev, INTA_MASK,read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU); 
+#endif
+}
+
+/****************************************************************************
+ ---------------------------- NIC START/CLOSE STUFF---------------------------
+*****************************************************************************/
+void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	cancel_delayed_work(&priv->watch_dog_wq);
+	cancel_delayed_work(&priv->update_beacon_wq);
+#ifndef RTL8190P
+	cancel_delayed_work(&priv->rtllib->hw_sleep_wq);
+#endif
+#if defined RTL8192SE 
+	cancel_delayed_work(&priv->check_hw_scan_wq);
+	cancel_delayed_work(&priv->hw_scan_simu_wq);
+	cancel_delayed_work(&priv->start_hw_scan_wq);
+	cancel_delayed_work(&priv->rtllib->update_assoc_sta_info_wq);
+	cancel_delayed_work(&priv->rtllib->check_tsf_wq);
+#endif
+#endif
+
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,22)
+	cancel_work_sync(&priv->reset_wq);
+	cancel_work_sync(&priv->qos_activate);
+#elif ((LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)))
+	cancel_delayed_work(&priv->reset_wq);
+	cancel_delayed_work(&priv->qos_activate);
+#if defined RTL8192SE 
+	cancel_delayed_work(&priv->rtllib->update_assoc_sta_info_wq);
+	cancel_delayed_work(&priv->rtllib->check_tsf_wq);
+#endif
+#endif
+
+}
+
+int _rtl8192_up(struct net_device *dev,bool is_silent_reset)
+{
+#ifdef _RTL8192_EXT_PATCH_
+	if(_rtl8192_mesh_up(dev, is_silent_reset) == -1)
+		return -1;
+#else
+	if(_rtl8192_sta_up(dev, is_silent_reset) == -1)
+		return -1;
+#endif
+
+	return 0;
+}
+
+
+int rtl8192_open(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret;
+	
+	down(&priv->wx_sem);
+	ret = rtl8192_up(dev);
+	up(&priv->wx_sem);
+	return ret;
+	
+}
+
+
+int rtl8192_up(struct net_device *dev)
+{
+#ifndef _RTL8192_EXT_PATCH_
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if (priv->up == 1) return -1;
+	return _rtl8192_up(dev,false);
+#else	
+	return _rtl8192_up(dev,false);
+#endif	
+}
+
+
+int rtl8192_close(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret;
+	
+	if ((rtllib_act_scanning(priv->rtllib, false)) && 
+		!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		rtllib_stop_scan(priv->rtllib);
+	}
+
+	down(&priv->wx_sem);
+
+	ret = rtl8192_down(dev,true);
+	
+	up(&priv->wx_sem);
+	
+	return ret;
+
+}
+
+int rtl8192_down(struct net_device *dev, bool shutdownrf)
+{
+#ifdef CONFIG_MP
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+	if(rtl8192_mesh_down(dev, shutdownrf) == -1)
+		return -1;
+#else
+	if(rtl8192_sta_down(dev, shutdownrf) == -1)
+		return -1;
+#endif
+
+#ifdef CONFIG_MP
+	if (priv->bCckContTx) {
+		printk("####RTL819X MP####stop single cck continious TX\n");
+		mpt_StopCckCoNtTx(dev);
+	} 
+	if (priv->bOfdmContTx) {
+		printk("####RTL819X MP####stop single ofdm continious TX\n");
+		mpt_StopOfdmContTx(dev);
+	} 
+	if (priv->bSingleCarrier) {
+		printk("####RTL819X MP####stop single carrier mode\n");
+		MPT_ProSetSingleCarrier(dev, false);
+	}
+#endif
+	return 0;
+}
+
+void rtl8192_commit(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (IS_NIC_DOWN(priv)) 
+		return ;
+	rtllib_softmac_stop_protocol(priv->rtllib,0,true);
+	rtl8192_irq_disable(dev);
+	priv->ops->stop_adapter(dev, true);
+	priv->up = 0;
+	_rtl8192_up(dev,false);
+#else
+	if (priv->up == 0) return ;
+	rtllib_softmac_stop_protocol(priv->rtllib,true);
+	rtl8192_irq_disable(dev);
+	priv->ops->stop_adapter(dev, true);
+	_rtl8192_up(dev,false);
+#endif
+	
+}
+
+void rtl8192_restart(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, reset_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+        struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+
+	down(&priv->wx_sem);
+	
+	rtl8192_commit(dev);
+	
+	up(&priv->wx_sem);
+}
+
+static void r8192_set_multicast(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	short promisc;
+
+	
+	
+	promisc = (dev->flags & IFF_PROMISC) ? 1:0;
+	
+	if (promisc != priv->promisc) {
+		;
+	}
+	
+	priv->promisc = promisc;
+	
+}
+
+
+int r8192_set_mac_adr(struct net_device *dev, void *mac)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct sockaddr *addr = mac;
+	
+	down(&priv->wx_sem);
+	
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+		
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+	schedule_work(&priv->reset_wq);
+#else
+	schedule_task(&priv->reset_wq);
+#endif	
+	up(&priv->wx_sem);
+	
+	return 0;
+}
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+extern int wapi_ioctl_set_mode(struct net_device *dev, struct iw_request_info *a,union iwreq_data *wrqu, char *b);
+int WAPI_Ioctl(struct net_device *dev, struct iwreq *wrq, int cmd)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	static u8 QueueData[WAPI_MAX_BUFF_LEN];
+#define DATAQUEUE_EMPTY	"Queue is empty"
+	int ret = 0;
+
+	switch(cmd){
+	    	case WAPI_CMD_GET_WAPI_SUPPORT:
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_WAPI_SUPPORT!\n",__FUNCTION__);
+			if(copy_to_user((u8 *)(wrq->u.data.pointer), &ieee->WapiSupport, sizeof(u8))==0)
+				wrq->u.data.length = sizeof(u8);
+			break;
+	    	case WAPI_CMD_SET_WAPI_ENABLE:
+		{
+			u8 wapi_enable = *(u8 *)wrq->u.data.pointer;
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_WAPI_ENABLE!\n",__FUNCTION__);
+			if((ieee->WapiSupport) && (wapi_enable == 1)){
+				ieee->wapiInfo.bWapiEnable = true;
+				ieee->pairwise_key_type = KEY_TYPE_SMS4;
+				ieee->group_key_type = KEY_TYPE_SMS4;
+				ieee->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+				ieee->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+			}
+			else if (wapi_enable == 0) {
+				ieee->wapiInfo.bWapiEnable = false;
+				ieee->pairwise_key_type = KEY_TYPE_NA;
+				ieee->group_key_type = KEY_TYPE_NA;
+			}
+			break;
+	    	}
+	    	case WAPI_CMD_SET_WAPI_PSK:
+		{
+			u8 wapi_psk = *(u8 *)wrq->u.data.pointer;
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_WAPI_PSK!\n",__FUNCTION__);
+			if(ieee->wapiInfo.bWapiEnable){
+				ieee->wapiInfo.bWapiPSK = (wapi_psk > 0)?1:0; 
+				WAPI_TRACE(WAPI_API, "%s(): bWapiPSK=%d!\n",__FUNCTION__, ieee->wapiInfo.bWapiPSK);
+			}
+			break;
+	    	}
+	    	case WAPI_CMD_SET_KEY:
+		{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/
+			PRT_WAPI_T			pWapiInfo = &ieee->wapiInfo;
+			PRT_WAPI_BKID		pWapiBkid;
+			PRT_WAPI_STA_INFO	pWapiSta;
+			u8					data[43];
+			bool					bTxEnable;
+			bool					bUpdate;
+			bool					bAuthenticator;
+			u8					PeerAddr[6];
+			u8					WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+			u8					WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+			u8					WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;		
+
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_KEY!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if(wrq->u.data.length < 26){
+				ret = -1;
+				break;
+			}
+
+			copy_from_user(data, (u8 *)wrq->u.data.pointer, wrq->u.data.length);
+			bTxEnable = data[1];
+			bAuthenticator = data[2];
+			bUpdate = data[3];
+		 	memcpy(PeerAddr,data+4,6);
+				
+			if(data[0] == 0x3){
+				if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){
+					pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID,list);
+					list_del_init(&pWapiBkid->list);
+					memcpy(pWapiBkid->bkid, data+10, 16);
+					list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList);
+					WAPI_DATA(WAPI_API, "SetKey - BKID", pWapiBkid->bkid, 16);
+				}
+			} else if (data[0] == 0x04){
+				list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+					if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){
+						if(bUpdate){
+							if(bAuthenticator) {
+								memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16);
+							} else {
+								memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+								memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							}
+						}
+					}
+				}
+			}
+			else{
+				list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+					if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){
+						pWapiSta->bAuthenticatorInUpdata = false;
+						switch(data[0]){
+						case 1:              
+							if(bAuthenticator){         
+								memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16);
+								if(!bUpdate) {     
+									WAPI_TRACE(WAPI_API, "%s(): AE fisrt set usk!\n",__FUNCTION__);
+									pWapiSta->wapiUsk.bSet = true;
+									memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+									memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+									pWapiSta->wapiUsk.keyId = *(data+42);
+									pWapiSta->wapiUsk.bTxEnable = true;
+									WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUsk.dataKey, 16);
+									WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUsk.micKey, 16);
+								}
+								else               
+								{
+									WAPI_TRACE(WAPI_API, "%s(): AE update usk!\n",__FUNCTION__);
+									pWapiSta->wapiUskUpdate.bSet = true;
+									pWapiSta->bAuthenticatorInUpdata = true;
+									memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+									memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+									memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+									pWapiSta->wapiUskUpdate.keyId = *(data+42);
+									pWapiSta->wapiUskUpdate.bTxEnable = true;
+									WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiUskUpdate.keyId);
+									WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUskUpdate.dataKey, 16);
+									WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUskUpdate.micKey, 16);
+								}
+							}
+							else{
+								if(!bUpdate){
+									WAPI_TRACE(WAPI_API, "%s(): ASUE fisrt set usk!\n",__FUNCTION__);
+									if(bTxEnable){
+										pWapiSta->wapiUsk.bTxEnable = true;
+										memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+										WAPI_TRACE(WAPI_API, "%s(): Tx enable!\n",__FUNCTION__);
+									}else{
+										pWapiSta->wapiUsk.bSet = true;
+										memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+										memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+										pWapiSta->wapiUsk.keyId = *(data+42);
+										pWapiSta->wapiUsk.bTxEnable = false;
+										WAPI_TRACE(WAPI_API, "%s(): Tx disable!\n",__FUNCTION__);
+										WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUsk.dataKey, 16);
+										WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUsk.micKey, 16);
+									}
+								}else{
+									WAPI_TRACE(WAPI_API, "%s(): ASUE update usk!\n",__FUNCTION__);
+									if(bTxEnable){
+										pWapiSta->wapiUskUpdate.bTxEnable = true;
+										if(pWapiSta->wapiUskUpdate.bSet){
+											WAPI_TRACE(WAPI_API, "%s(): ASUE set usk!\n",__FUNCTION__);
+											memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16);
+											memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16);
+											pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId;
+											memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
+											memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
+											memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
+											memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
+											memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16);
+											pWapiSta->wapiUskUpdate.bTxEnable = false;
+											pWapiSta->wapiUskUpdate.bSet = false;
+										}
+										memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+									}else{
+										WAPI_TRACE(WAPI_API, "%s(): ASUE set update usk!\n",__FUNCTION__);
+										pWapiSta->wapiUskUpdate.bSet = true;
+										memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+										memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+										pWapiSta->wapiUskUpdate.keyId = *(data+42);
+										pWapiSta->wapiUskUpdate.bTxEnable = false;
+										WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiUskUpdate.keyId);
+										WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUskUpdate.dataKey, 16);
+										WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUskUpdate.micKey, 16);
+									}
+								}
+							}
+							break;
+						case 2:		
+							if(bAuthenticator){          
+								pWapiInfo->wapiTxMsk.bSet = true;
+								memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16);													
+								memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16);
+								pWapiInfo->wapiTxMsk.keyId = *(data+42);
+								pWapiInfo->wapiTxMsk.bTxEnable = true;
+								memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16);
+								if(!bUpdate){      
+									WAPI_TRACE(WAPI_API, "%s(): AE fisrt set msk!\n",__FUNCTION__);
+									if(!pWapiSta->bSetkeyOk)
+										pWapiSta->bSetkeyOk = true;
+									pWapiInfo->bFirstAuthentiateInProgress= false;
+								}else{               
+									WAPI_TRACE(WAPI_API, "%s():AE update msk!\n",__FUNCTION__);
+								}
+								WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiInfo->wapiTxMsk.keyId);
+								WAPI_DATA(WAPI_API, "SetKey - AE Msk Data Key", pWapiInfo->wapiTxMsk.dataKey, 16);
+								WAPI_DATA(WAPI_API, "SetKey - AE Msk Mic Key", pWapiInfo->wapiTxMsk.micKey, 16);
+							}
+							else{
+								if(!bUpdate){
+									WAPI_TRACE(WAPI_API, "%s(): ASUE fisrt set msk!\n",__FUNCTION__);
+									pWapiSta->wapiMsk.bSet = true;
+									memcpy(pWapiSta->wapiMsk.dataKey,data+10,16);													
+									memcpy(pWapiSta->wapiMsk.micKey,data+26,16);
+									pWapiSta->wapiMsk.keyId = *(data+42);
+									pWapiSta->wapiMsk.bTxEnable = false;
+									if(!pWapiSta->bSetkeyOk)
+										pWapiSta->bSetkeyOk = true;
+									pWapiInfo->bFirstAuthentiateInProgress= false;
+									WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Data Key", pWapiSta->wapiMsk.dataKey, 16);
+									WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Mic Key", pWapiSta->wapiMsk.micKey, 16);
+								}else{
+									WAPI_TRACE(WAPI_API, "%s(): ASUE update msk!\n",__FUNCTION__);
+									pWapiSta->wapiMskUpdate.bSet = true;
+									memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16);													
+									memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16);
+									pWapiSta->wapiMskUpdate.keyId = *(data+42);
+									pWapiSta->wapiMskUpdate.bTxEnable = false;
+									WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiMskUpdate.keyId);
+									WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Data Key", pWapiSta->wapiMskUpdate.dataKey, 16);
+									WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Mic Key", pWapiSta->wapiMskUpdate.micKey, 16);
+								}
+							}
+							break;
+						default:
+							WAPI_TRACE(WAPI_ERR, "%s(): Unknown Flag!\n",__FUNCTION__);
+							break;
+						}
+					}
+				}
+			}
+			break;
+		}
+	    	case WAPI_CMD_SET_MULTICAST_PN:
+		{
+			PRT_WAPI_T			pWapiInfo = &ieee->wapiInfo;
+			PRT_WAPI_STA_INFO	pWapiSta;
+			u8				data[22];
+			u8				k;
+
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_MULTICAST_PN!\n",__FUNCTION__);
+			if (!ieee->WapiSupport)
+			{
+				ret = -1;
+				break;    
+			}
+			if(wrq->u.data.length < 22){
+				ret = -1;
+				break;
+			}
+
+			memcpy(data, (u8 *)wrq->u.data.pointer, 22);
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if(!memcmp(pWapiSta->PeerMacAddr,data,6))
+				{
+					for(k=0;k<16;k++)
+						pWapiSta->lastRxMulticastPN[k] = data[21-k];
+					break;
+				}
+			}
+			WAPI_DATA(WAPI_API, "Multicast Rx PN:", pWapiSta->lastRxMulticastPN, 16);
+			break;
+		}
+	    	case WAPI_CMD_GET_PN:
+		{
+			PRT_WAPI_T		pWapiInfo = &ieee->wapiInfo;
+			
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_PN!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if(wrq->u.data.length<16){
+				ret = -1;
+				break;
+			}
+			if(copy_to_user((void *)(wrq->u.data.pointer), pWapiInfo->lastTxMulticastPN, 16)==0)
+				wrq->u.data.length = 16;
+			break;
+		}
+	    	case WAPI_CMD_GET_WAPIIE:
+		{
+			PRT_WAPI_T		pWapiInfo = &ieee->wapiInfo;
+			u8 				data[512];
+			u8				Length = 0;
+			
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_WAPIIE!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if(wrq->u.data.length<257){
+				ret = -1;
+				break;
+			}
+
+			if(ieee->iw_mode == IW_MODE_INFRA){
+				data[0]= pWapiInfo->assoReqWapiIELength;
+				Length ++;
+				memcpy(data+Length,pWapiInfo->assoReqWapiIE,pWapiInfo->assoReqWapiIELength);
+				Length += pWapiInfo->assoReqWapiIELength;
+			}
+			else if(ieee->iw_mode == IW_MODE_ADHOC){
+				WAPI_DATA(WAPI_API, "GetWapiIE - ADHOC", pWapiInfo->sendbeaconWapiIE, pWapiInfo->sendbeaconWapiIELength);
+				data[0] = pWapiInfo->sendbeaconWapiIELength;
+				Length++;
+				memcpy(data+Length,pWapiInfo->sendbeaconWapiIE,pWapiInfo->sendbeaconWapiIELength);
+				Length += pWapiInfo->sendbeaconWapiIELength;
+			}
+			
+			if(copy_to_user((void *)(wrq->u.data.pointer), data, Length)==0)
+				wrq->u.data.length = Length;
+			break;
+	    	}
+		case WAPI_CMD_SET_SSID:
+		{
+			u8 ssid[IW_ESSID_MAX_SIZE + 1];
+			
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_SSID!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if((wrq->u.data.length == 0) || (NULL == wrq->u.data.pointer)){
+				ret = -1;
+				break;
+			}
+			if(wrq->u.data.length > IW_ESSID_MAX_SIZE){
+				ret = -1;
+				break;
+			}
+			printk("===>%s(): wrq->u.essid.flags is %d\n",__FUNCTION__,wrq->u.essid.flags);
+			copy_from_user(ssid, (u8 *)wrq->u.essid.pointer, wrq->u.essid.length);
+
+#ifdef TO_DO_LIST
+			if(!ieee->wapiInfo.bWapiEnable)
+				SetEncryptState(dev);
+#endif			
+			if((priv->bHwRadioOff == true) || (!priv->up)){
+				ret = -1;
+				break;
+			}
+			ret = rtllib_wx_set_essid(ieee,NULL,(union iwreq_data *)&(wrq->u),ssid);
+			
+			break;
+		}
+		case WAPI_CMD_GET_BSSID:
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_BSSID!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_ADHOC) ){
+				if(copy_to_user((void *)(wrq->u.data.pointer), ieee->current_network.bssid, ETH_ALEN)==0)
+					wrq->u.data.length = ETH_ALEN;
+			}else{
+				ret = -1;
+			}
+			break;
+#if 0			
+		case WAPI_CMD_GET_LINK_STATUS:
+		{
+			u8 connect_status = 0;  
+			
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_LINK_STATUS!\n",__FUNCTION__);
+			if(ieee->state == IEEE80211_LINKED)
+				connect_status = 1;
+			if(copy_to_user((void *)(wrq->u.data.pointer), &connect_status, sizeof(u8))==0)
+				wrq->u.data.length = sizeof(u8);
+			break;
+		}
+#endif
+		case WAPI_CMD_SET_IW_MODE:
+		{
+			union iwreq_data *wrqu = (union iwreq_data *)&(wrq->u);
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_IW_MODE!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			WAPI_TRACE(WAPI_API, "%s(): Set iw_mode %d!\n",__FUNCTION__, wrqu->mode);
+			wapi_ioctl_set_mode(dev, NULL, wrqu, NULL);
+			if(wrqu->mode == IW_MODE_ADHOC)
+				ConstructWapiIEForInit(ieee);
+			break;
+		}
+		case WAPI_CMD_SET_DISASSOCIATE:
+		{
+			u8 destAddr[6];
+			
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_DISASSOCIATE!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if(wrq->u.data.length != 6){
+				ret = -1;
+				break;
+			}
+			copy_from_user(destAddr, (u8 *)(wrq->u.data.pointer), wrq->u.data.length);
+
+			if(ieee->iw_mode == IW_MODE_INFRA){
+				SendDisassociation(ieee,1,deauth_lv_ss);
+				ieee80211_disassociate_from_app(ieee);
+			}else if(ieee->iw_mode == IW_MODE_ADHOC){
+				WAPI_TRACE(WAPI_API, "%s(): Disassociate "MAC_FMT"!\n",__FUNCTION__, MAC_ARG(destAddr));
+				WapiReturnOneStaInfo(ieee, destAddr, 1);
+				DelStaInfo(ieee, destAddr);
+			}
+			break;
+		}
+		case WAPI_CMD_SAVE_PID:
+		{
+			u8 strPID[10];
+			u32 len = 0;
+			int i = 0;
+
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SAVE_PID!\n",__FUNCTION__);
+			if (!ieee->WapiSupport){
+				ret = -1;
+				break;    
+			}
+			if ( !wrq->u.data.pointer ){
+				ret = -1;
+				break;
+			}
+
+			len = wrq->u.data.length;
+			memset(strPID, 0, sizeof(strPID));
+			if(copy_from_user(strPID, (void *)wrq->u.data.pointer, len)){
+				ret = -1;
+				break;
+			}
+
+			pid_wapi = 0;
+			for(i = 0; i < len; i++) {
+				pid_wapi = pid_wapi * 10 + (strPID[i] - 48);
+			}		
+			WAPI_TRACE(WAPI_API, "%s(): strPID=%s pid_wapi=%d!\n",__FUNCTION__, strPID, pid_wapi);
+			break;	
+		}
+	    	case WAPI_CMD_DEQUEUE:
+		{
+			int QueueDataLen = 0;
+
+			WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_DEQUEUE!\n",__FUNCTION__);
+			if((ret = WAPI_DeQueue(&ieee->wapi_queue_lock, ieee->wapi_queue, QueueData, &QueueDataLen)) != 0){
+				if(copy_to_user((void *)(wrq->u.data.pointer), DATAQUEUE_EMPTY, sizeof(DATAQUEUE_EMPTY))==0)
+					wrq->u.data.length = sizeof(DATAQUEUE_EMPTY);
+			}else{
+				if(copy_to_user((void *)wrq->u.data.pointer, (void *)QueueData, QueueDataLen)==0)
+					wrq->u.data.length = QueueDataLen;
+			}	
+			break;
+		}
+		default:
+			WAPI_TRACE(WAPI_ERR, "%s(): Error CMD!\n",__FUNCTION__);
+			break;
+	}
+	
+	return ret;
+}
+#endif
+
+/* based on ipw2200 driver */
+int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct iwreq *wrq = (struct iwreq *)rq;
+	int ret=-1;
+	struct rtllib_device *ieee = priv->rtllib;
+	u32 key[4];
+	u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 zero_addr[6] = {0};
+	struct iw_point *p = &wrq->u.data;
+
+	down(&priv->wx_sem);
+
+	switch (cmd) {
+		case RTL_IOCTL_WPA_SUPPLICANT:
+		{
+			struct ieee_param *ipw = NULL;
+	if (p->length < sizeof(struct ieee_param) || !p->pointer){
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ipw = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
+	if (ipw == NULL){
+		ret = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(ipw, p->pointer, p->length)) {
+		kfree(ipw);
+		ret = -EFAULT;
+		goto out;
+	}
+
+			if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
+			{
+				if (ipw->u.crypt.set_tx)
+				{
+					if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+						ieee->pairwise_key_type = KEY_TYPE_CCMP;
+					else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+						ieee->pairwise_key_type = KEY_TYPE_TKIP;
+					else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
+					{
+						if (ipw->u.crypt.key_len == 13)
+							ieee->pairwise_key_type = KEY_TYPE_WEP104;
+						else if (ipw->u.crypt.key_len == 5)
+							ieee->pairwise_key_type = KEY_TYPE_WEP40;
+					}
+					else
+						ieee->pairwise_key_type = KEY_TYPE_NA;
+
+					if (ieee->pairwise_key_type)
+					{
+						if (memcmp(ieee->ap_mac_addr, zero_addr, 6) == 0)
+							ieee->iw_mode = IW_MODE_ADHOC;
+
+						memcpy((u8*)key, ipw->u.crypt.key, 16);
+						EnableHWSecurityConfig8192(dev);
+						set_swcam(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key,0);
+						setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
+						if (ieee->iw_mode == IW_MODE_ADHOC){  
+							set_swcam(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key,0);
+							setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
+						}
+					}
+#ifdef RTL8192E
+					if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
+						write_nic_byte(dev, 0x173, 1); 
+					}
+#endif
+
+				}
+				else 
+				{
+					memcpy((u8*)key, ipw->u.crypt.key, 16);
+					if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+						ieee->group_key_type= KEY_TYPE_CCMP;
+					else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+						ieee->group_key_type = KEY_TYPE_TKIP;
+					else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
+					{
+						if (ipw->u.crypt.key_len == 13)
+							ieee->group_key_type = KEY_TYPE_WEP104;
+						else if (ipw->u.crypt.key_len == 5)
+							ieee->group_key_type = KEY_TYPE_WEP40;
+					}
+					else
+						ieee->group_key_type = KEY_TYPE_NA;
+
+					if (ieee->group_key_type)
+					{
+						set_swcam(	dev, 
+								ipw->u.crypt.idx,
+								ipw->u.crypt.idx,		
+								ieee->group_key_type,	
+								broadcast_addr,	
+								0,		
+								key,		
+								0);
+						setKey(	dev, 
+								ipw->u.crypt.idx,
+								ipw->u.crypt.idx,		
+								ieee->group_key_type,	
+								broadcast_addr,	
+								0,		
+								key);		
+					}
+				}
+			}
+#ifdef JOHN_DEBUG
+			{
+				int i;
+				printk("@@ wrq->u pointer = ");
+				for(i=0;i<wrq->u.data.length;i++){
+					if(i%10==0) printk("\n");
+					printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
+				}
+				printk("\n");
+			}
+#endif 
+#ifdef _RTL8192_EXT_PATCH_
+			ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data,0);
+#else
+			ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data);
+#endif
+			kfree(ipw);
+			break; 
+		}
+#if defined (RTL8192S_WAPI_SUPPORT)
+	    	case WAPI_CMD_GET_WAPI_SUPPORT:
+	    	case WAPI_CMD_SET_WAPI_ENABLE:
+	    	case WAPI_CMD_SET_WAPI_PSK:
+	    	case WAPI_CMD_SET_KEY:
+	    	case WAPI_CMD_SET_MULTICAST_PN:
+	    	case WAPI_CMD_GET_PN:
+	    	case WAPI_CMD_GET_WAPIIE:
+	    	case WAPI_CMD_SET_SSID:
+	    	case WAPI_CMD_GET_BSSID:
+	    	case WAPI_CMD_SET_IW_MODE:
+	    	case WAPI_CMD_SET_DISASSOCIATE:
+		case WAPI_CMD_SAVE_PID:
+	    	case WAPI_CMD_DEQUEUE:
+			ret = WAPI_Ioctl(dev, wrq, cmd);
+			break;
+#endif
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+	}
+
+out:
+	up(&priv->wx_sem);
+
+	return ret;
+}
+
+irqreturn_type rtl8192_interrupt(int irq, void *netdev, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) netdev;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+#ifdef _RTL8192_EXT_PATCH_
+	struct net_device *meshdev = ((struct rtllib_device *)netdev_priv_rsl(dev))->meshdev;
+#endif
+	unsigned long flags;
+	u32 inta;
+	u32 intb;
+	intb = 0;
+	
+	if(priv->irq_enabled == 0){
+		goto done;
+	}
+
+	spin_lock_irqsave(&priv->irq_th_lock,flags);
+
+	priv->ops->interrupt_recognized(dev, &inta, &intb);
+	priv->stats.shints++;
+
+	if (!inta) {
+		spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+		goto done;
+	}
+
+	if (inta == 0xffff) {
+		spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+		goto done;
+	}
+
+	priv->stats.ints++;
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (!netif_running(dev) && !netif_running(meshdev)) 
+#else
+	if (!netif_running(dev)) 
+#endif
+	{
+		spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+		goto done;
+	}
+
+#if defined RTL8192SE 
+	if(intb & IMR_TBDOK){
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		priv->stats.txbeaconokint++;
+	}
+
+	if(intb & IMR_TBDER){
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		priv->stats.txbeaconerr++;
+	}
+#else
+	if(inta & IMR_TBDOK){
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		priv->stats.txbeaconokint++;
+	}
+
+	if(inta & IMR_TBDER){
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		priv->stats.txbeaconerr++;
+	}
+#endif
+
+	if(inta & IMR_BDOK) {
+		RT_TRACE(COMP_INTR, "beacon interrupt!\n");
+		rtl8192_tx_isr(dev, BEACON_QUEUE);
+	}
+
+	if(inta  & IMR_MGNTDOK ) {
+		RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
+		priv->stats.txmanageokint++;
+		rtl8192_tx_isr(dev,MGNT_QUEUE);
+		spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+		if (priv->rtllib->ack_tx_to_ieee){
+			if (rtl8192_is_tx_queue_empty(dev)){
+				priv->rtllib->ack_tx_to_ieee = 0;
+				rtllib_ps_tx_ack(priv->rtllib, 1);
+			}
+		}
+		spin_lock_irqsave(&priv->irq_th_lock,flags);
+	}
+
+#ifndef RTL8192CE
+	if (inta & IMR_COMDOK) {
+		priv->stats.txcmdpktokint++;
+		rtl8192_tx_isr(dev,TXCMD_QUEUE);
+	}
+#endif
+
+	if (inta & IMR_HIGHDOK) {
+		rtl8192_tx_isr(dev,HIGH_QUEUE);
+	}
+
+#ifdef RTL8192SE
+	if ((inta & IMR_ROK) || (inta & IMR_RXCMDOK))
+#else
+	if (inta & IMR_ROK) 
+#endif
+	{
+		priv->stats.rxint++;
+		priv->InterruptLog.nIMR_ROK++;
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
+
+	if (inta & IMR_BcnInt) {
+		RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
+		tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
+	}
+
+	if (inta & IMR_RDU) {
+		RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
+		priv->stats.rxrdu++;
+#ifndef RTL8192CE
+		write_nic_dword(dev,INTA_MASK,read_nic_dword(dev, INTA_MASK) & ~IMR_RDU); 
+#endif    
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
+
+	if (inta & IMR_RXFOVW) {
+		RT_TRACE(COMP_INTR, "rx overflow !\n");
+		priv->stats.rxoverflow++;
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
+
+	if (inta & IMR_TXFOVW) priv->stats.txoverflow++;
+
+	if (inta & IMR_BKDOK) { 
+		RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
+		priv->stats.txbkokint++;
+		priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(dev,BK_QUEUE);
+	}
+
+	if (inta & IMR_BEDOK) { 
+		RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
+		priv->stats.txbeokint++;
+		priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(dev,BE_QUEUE);
+	}
+
+	if (inta & IMR_VIDOK) { 
+		RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
+		priv->stats.txviokint++;
+		priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(dev,VI_QUEUE);
+	}
+
+	if (inta & IMR_VODOK) { 
+		priv->stats.txvookint++;
+		RT_TRACE(COMP_INTR, "Vo TX OK interrupt!\n");
+		priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(dev,VO_QUEUE);
+	}
+
+	spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+
+done:
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	return;
+#else
+	return IRQ_HANDLED;
+#endif
+}
+
+#ifdef RTL8192CE
+static void rtl8192_parse_pci_configuration(struct pci_dev *pdev, struct net_device *dev)
+{
+	u8 tmp;
+	
+	pci_read_config_byte(pdev, 0x98, &tmp);
+	tmp |=BIT4;
+	pci_write_config_byte(pdev, 0x98, tmp);
+
+	tmp = 0x17;
+	pci_write_config_byte(pdev, 0x70f, tmp);
+}
+#endif
+
+bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev)
+{
+	u16  DeviceID;
+	u8 RevisionID = 0;
+	
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	pci_read_config_word(pdev, 0x2, &DeviceID);
+	pci_read_config_byte(pdev, 0x8, &RevisionID);
+	if (DeviceID == HAL_HW_PCI_8190_DEVICE_ID ||DeviceID == HAL_HW_PCI_0045_DEVICE_ID ||
+	 	DeviceID == HAL_HW_PCI_0046_DEVICE_ID ||DeviceID == HAL_HW_PCI_DLINK_DEVICE_ID){
+		printk("Adapter(8190 PCI) is found - DeviceID=%x\n", DeviceID);
+		priv->ops->nic_type = priv->card_8192 = NIC_8190P;
+	} else if (DeviceID == HAL_HW_PCI_8192_DEVICE_ID ||DeviceID == HAL_HW_PCI_0044_DEVICE_ID ||
+		DeviceID == HAL_HW_PCI_0047_DEVICE_ID || DeviceID == HAL_HW_PCI_8192SE_DEVICE_ID ||
+		DeviceID == HAL_HW_PCI_8174_DEVICE_ID || DeviceID == HAL_HW_PCI_8173_DEVICE_ID ||
+		DeviceID == HAL_HW_PCI_8172_DEVICE_ID || DeviceID == HAL_HW_PCI_8171_DEVICE_ID) {
+		
+		switch(RevisionID)
+		{
+			case HAL_HW_PCI_REVISION_ID_8192PCIE:
+				printk("Adapter(8192 PCI-E) is found - DeviceID=%x\n", DeviceID);
+				priv->ops->nic_type = priv->card_8192 = NIC_8192E;
+				break;
+			case HAL_HW_PCI_REVISION_ID_8192SE:
+				printk("Adapter(8192SE) is found - DeviceID=%x\n", DeviceID);
+				priv->card_8192 = NIC_8192SE;
+				break;
+			default:
+				printk("UNKNOWN nic type(%4x:%4x)\n", pdev->vendor, pdev->device);
+				priv->card_8192 = NIC_UNKNOWN;
+
+			return false;
+			break;
+				
+		}
+	} else 
+		if (DeviceID == HAL_HW_PCI_8192CET_DEVICE_ID ||DeviceID == HAL_HW_PCI_8192CE_DEVICE_ID ||
+		DeviceID == HAL_HW_PCI_8191CE_DEVICE_ID ||DeviceID == HAL_HW_PCI_8188CE_DEVICE_ID) {
+			printk("Adapter(8192CE) is found - DeviceID=%x\n", DeviceID);
+			priv->ops->nic_type = priv->card_8192 = NIC_8192CE;
+	} else {
+		printk("Unknown device - DeviceID=%x\n", DeviceID);
+		priv->ops->nic_type = priv->card_8192 = NIC_8192DE;
+	}
+		
+#ifdef RTL8192CE
+	rtl8192_parse_pci_configuration(pdev, dev);
+#endif
+	
+	return true;
+}
+
+/****************************************************************************
+     ---------------------------- PCI_STUFF---------------------------
+*****************************************************************************/
+#ifdef HAVE_NET_DEVICE_OPS
+static const struct net_device_ops rtl8192_netdev_ops = {
+	.ndo_open = rtl8192_open,
+	.ndo_stop = rtl8192_close,
+	.ndo_tx_timeout = rtl8192_tx_timeout,
+	.ndo_do_ioctl = rtl8192_ioctl,
+	.ndo_set_multicast_list = r8192_set_multicast,
+	.ndo_set_mac_address = r8192_set_mac_adr,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_change_mtu = eth_change_mtu,
+	.ndo_start_xmit = rtllib_xmit,
+};
+#endif
+
+static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
+			 const struct pci_device_id *id)
+{
+	unsigned long ioaddr = 0;
+	struct net_device *dev = NULL;
+	struct r8192_priv *priv= NULL;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct rtl819x_ops *ops = (struct rtl819x_ops *)(id->driver_data);
+#endif
+	
+#ifdef CONFIG_RTL8192_IO_MAP
+	unsigned long pio_start, pio_len, pio_flags;
+#else
+	unsigned long pmem_start, pmem_len, pmem_flags;
+#endif 
+	int err = 0;
+#ifdef _RTL8192_EXT_PATCH_
+	int result;
+	struct net_device *meshdev = NULL;
+	struct meshdev_priv *mpriv;
+	char meshifname[]="mesh0";
+#endif	
+	bool bdma64 = false;
+
+	RT_TRACE(COMP_INIT,"Configuring chip resources");
+	
+	if( pci_enable_device (pdev) ){
+		RT_TRACE(COMP_ERR,"Failed to enable PCI device");
+		return -EIO;
+	}
+
+	pci_set_master(pdev);
+
+#ifdef CONFIG_64BIT_DMA
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		printk("RTL819xCE: Using 64bit DMA\n");
+		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+			printk( "Unable to obtain 64bit DMA for consistent allocations\n");
+			pci_disable_device(pdev);
+			return -ENOMEM;
+		}
+		bdma64 = true;
+	} else 
+#endif
+	{
+		if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+			if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+				printk( "Unable to obtain 32bit DMA for consistent allocations\n");
+				pci_disable_device(pdev);
+				return -ENOMEM;
+			} 
+#endif	
+		}
+	}
+	dev = alloc_rtllib(sizeof(struct r8192_priv));
+	if (!dev)
+		return -ENOMEM;
+	
+	if(bdma64){
+		dev->features |= NETIF_F_HIGHDMA;
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	SET_MODULE_OWNER(dev);
+#endif
+
+	pci_set_drvdata(pdev, dev);	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	SET_NETDEV_DEV(dev, &pdev->dev);
+#endif
+	priv = rtllib_priv(dev);
+	priv->rtllib = (struct rtllib_device *)netdev_priv_rsl(dev);
+	priv->pdev=pdev;
+	priv->rtllib->pdev=pdev;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	if((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK)&&(pdev->subsystem_device == 0x3304)){
+		priv->rtllib->bSupportRemoteWakeUp = 1;
+	} else 
+#endif
+	{
+		priv->rtllib->bSupportRemoteWakeUp = 0;
+	}
+
+#ifdef CONFIG_RTL8192_IO_MAP
+	pio_start = (unsigned long)pci_resource_start (pdev, 0);
+	pio_len = (unsigned long)pci_resource_len (pdev, 0);
+	pio_flags = (unsigned long)pci_resource_flags (pdev, 0);
+ 	
+      	if (!(pio_flags & IORESOURCE_IO)) {
+		RT_TRACE(COMP_ERR,"region #0 not a PIO resource, aborting");
+		goto fail;
+	}
+	
+	printk("Io mapped space start: 0x%08lx \n", pio_start );
+	if( ! request_region( pio_start, pio_len, DRV_NAME ) ){
+		RT_TRACE(COMP_ERR,"request_region failed!");
+		goto fail;
+	}
+	
+	ioaddr = pio_start;
+	dev->base_addr = ioaddr; 
+#else
+#ifdef RTL8192CE
+	pmem_start = pci_resource_start(pdev, 2);
+	pmem_len = pci_resource_len(pdev, 2);
+	pmem_flags = pci_resource_flags (pdev, 2);
+#else
+	pmem_start = pci_resource_start(pdev, 1);
+	pmem_len = pci_resource_len(pdev, 1);
+	pmem_flags = pci_resource_flags (pdev, 1);
+#endif
+	
+	if (!(pmem_flags & IORESOURCE_MEM)) {
+		RT_TRACE(COMP_ERR,"region #1 not a MMIO resource, aborting");
+		goto fail;
+	}
+	
+	printk("Memory mapped space start: 0x%08lx \n", pmem_start);
+	if (!request_mem_region(pmem_start, pmem_len, DRV_NAME)) {
+		RT_TRACE(COMP_ERR,"request_mem_region failed!");
+		goto fail;
+	}
+	
+	
+	ioaddr = (unsigned long)ioremap_nocache( pmem_start, pmem_len);	
+	if( ioaddr == (unsigned long)NULL ){
+		RT_TRACE(COMP_ERR,"ioremap failed!");
+		goto fail1;
+	}
+	
+	dev->mem_start = ioaddr; 
+	dev->mem_end = ioaddr + pci_resource_len(pdev, 0); 
+	
+#endif 
+#if defined RTL8192SE || defined RTL8192CE
+        pci_write_config_byte(pdev, 0x81,0);
+        pci_write_config_byte(pdev,0x44,0);
+        pci_write_config_byte(pdev,0x04,0x06);
+        pci_write_config_byte(pdev,0x04,0x07);
+#endif        
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	priv->ops = ops;
+#else
+#if defined RTL8190P || defined RTL8192E
+	priv->ops = &rtl819xp_ops;
+#else
+	priv->ops = &rtl8192se_ops;
+#endif
+#endif
+
+	if(rtl8192_pci_findadapter(pdev, dev) == false)
+		goto fail1;
+
+	dev->irq = pdev->irq;
+	priv->irq = 0;
+
+#ifdef HAVE_NET_DEVICE_OPS
+	dev->netdev_ops = &rtl8192_netdev_ops;
+#else	
+	dev->open = rtl8192_open;
+	dev->stop = rtl8192_close;
+	dev->tx_timeout = rtl8192_tx_timeout;
+	dev->do_ioctl = rtl8192_ioctl;
+	dev->set_multicast_list = r8192_set_multicast;
+	dev->set_mac_address = r8192_set_mac_adr;
+	dev->hard_start_xmit = rtllib_xmit;
+#endif	
+
+#if WIRELESS_EXT >= 12
+#if WIRELESS_EXT < 17
+        dev->get_wireless_stats = r8192_get_wireless_stats;
+#endif
+        dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	dev->ethtool_ops = &rtl819x_ethtool_ops;
+#endif
+
+	dev->type = ARPHRD_ETHER;
+	dev->watchdog_timeo = HZ*3;	
+
+	if (dev_alloc_name(dev, ifname) < 0){
+                RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
+		dev_alloc_name(dev, ifname);
+        }
+	
+	RT_TRACE(COMP_INIT, "Driver probe completed1\n");
+	if(rtl8192_init(dev)!=0){ 
+		RT_TRACE(COMP_ERR, "Initialization failed");
+		goto fail1;
+	}
+
+#ifdef CONFIG_CFG_80211 
+	if(!rtl8192_register_wiphy_dev(dev))
+		goto fail1;
+#endif
+
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+	
+	register_netdev(dev);
+	RT_TRACE(COMP_INIT, "dev name: %s\n",dev->name);
+	err = rtl_debug_module_init(priv, dev->name);
+	if (err) {
+		RT_TRACE(COMP_DBG, "failed to create debugfs files. Ignoring error: %d\n", err);	
+	}
+	rtl8192_proc_init_one(dev);
+	
+#ifdef ENABLE_GPIO_RADIO_CTL
+	if(priv->polling_timer_on == 0){
+		check_rfctrl_gpio_timer((unsigned long)dev);
+	}
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	meshdev = alloc_netdev(sizeof(struct meshdev_priv),meshifname,meshdev_init);
+	netif_stop_queue(meshdev);
+	memcpy(meshdev->dev_addr, dev->dev_addr, ETH_ALEN);
+	DMESG("Card MAC address for meshdev is "MAC_FMT, MAC_ARG(meshdev->dev_addr));
+
+	meshdev->base_addr = dev->base_addr;
+	meshdev->irq = dev->irq;
+	meshdev->mem_start = dev->mem_start;
+	meshdev->mem_end = dev->mem_end;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
+	SET_NETDEV_DEV(meshdev, dev->dev.parent);
+#endif
+
+	if ((result = register_netdev(meshdev)))
+	{
+		printk("Error %i registering device %s",result, meshdev->name);
+		goto fail;	
+	}
+	else
+	{
+		mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+		priv->rtllib->meshdev=meshdev;
+		priv->rtllib->meshstats=meshdev_stats(meshdev);
+		priv->rtllib->only_mesh = 1;  
+		priv->rtllib->p2pmode = 0;
+		priv->rtllib->serverExtChlOffset = 0;
+		priv->rtllib->APExtChlOffset = 0;
+		mpriv->rtllib = priv->rtllib;
+		mpriv->priv = priv;
+	}
+#endif
+	
+#ifdef RTL8192CE
+	mdelay(1000);
+#endif
+
+#ifdef CONFIG_RTL_RFKILL
+	if (priv->ops->init_before_adapter_start) {
+		priv->ops->init_before_adapter_start(dev);
+		priv->initialized_at_probe = true;
+	}
+	if (!rtl8192_rfkill_init(dev)) {
+		goto fail1;
+	}
+#endif	
+
+#if defined CONFIG_ASPM_OR_D3
+	rtl8192_initialize_adapter_common(dev);
+#endif
+
+	RT_TRACE(COMP_INIT, "Driver probe completed\n");
+	return 0;	
+
+fail1:
+#ifdef CONFIG_RTL8192_IO_MAP
+		
+	if( dev->base_addr != 0 ){
+			
+		release_region(dev->base_addr, 
+	       pci_resource_len(pdev, 0) );
+	}
+#else
+	if( dev->mem_start != (unsigned long)NULL ){
+		iounmap( (void *)dev->mem_start );
+#ifdef RTL8192CE
+		release_mem_region( pci_resource_start(pdev, 2), 
+				    pci_resource_len(pdev, 2) );
+#else
+		release_mem_region( pci_resource_start(pdev, 1), 
+				    pci_resource_len(pdev, 1) );
+#endif
+	}
+#endif 
+	
+fail:
+	if(dev){
+		
+		if (priv->irq) {
+			free_irq(dev->irq, dev);
+			dev->irq=0;
+		}
+		free_rtllib(dev);
+	}
+	
+	pci_disable_device(pdev);
+	
+	DMESG("wlan driver load failed\n");
+	pci_set_drvdata(pdev, NULL);
+	return -ENODEV;
+	
+}
+
+static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct r8192_priv *priv ;
+#ifdef _RTL8192_EXT_PATCH_
+	struct net_device *meshdev;
+#endif
+	if(dev){
+#ifdef CONFIG_RTL_RFKILL
+		rtl8192_rfkill_exit(dev);
+#endif
+		unregister_netdev(dev);
+		
+		priv = rtllib_priv(dev);
+		
+#ifdef _RTL8192_EXT_PATCH_
+		rtl8192_dinit_mshobj(priv);	
+#endif 
+
+#ifdef ENABLE_GPIO_RADIO_CTL
+		del_timer_sync(&priv->gpio_polling_timer);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+		cancel_delayed_work(&priv->gpio_change_rf_wq);
+#endif
+		priv->polling_timer_on = 0;
+#endif
+		rtl_debug_module_remove(priv);
+		rtl8192_proc_remove_one(dev);
+#ifdef _RTL8192_EXT_PATCH_
+		rtl8192_down(dev,true);
+		if(priv && priv->rtllib->meshdev)
+		{
+			meshdev = priv->rtllib->meshdev;
+			priv->rtllib->meshdev = NULL;
+		
+			if(meshdev){
+				meshdev_down(meshdev);
+				unregister_netdev(meshdev);
+			}
+		}
+#else		
+		rtl8192_down(dev,true);
+#endif
+		deinit_hal_dm(dev);
+#ifdef CONFIG_ASPM_OR_D3
+		;
+#endif
+#ifdef RTL8192SE
+		DeInitSwLeds(dev);
+#endif
+		if (priv->pFirmware)
+		{
+			vfree(priv->pFirmware);
+			priv->pFirmware = NULL;
+		}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+		destroy_workqueue(priv->priv_wq);
+#endif
+                {
+                    u32 i;
+                    rtl8192_free_rx_ring(dev);
+                    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
+                        rtl8192_free_tx_ring(dev, i);
+                    }
+                }
+
+		if(priv->irq){
+			
+			printk("Freeing irq %d\n",dev->irq);
+			free_irq(dev->irq, dev);
+			priv->irq=0;
+			
+		}
+#ifdef CONFIG_RTL8192_IO_MAP
+		if( dev->base_addr != 0 ){
+			
+			release_region(dev->base_addr, 
+				       pci_resource_len(pdev, 0) );
+		}
+#else
+		if( dev->mem_start != (unsigned long)NULL ){
+			iounmap( (void *)dev->mem_start );
+#ifdef RTL8192CE
+			release_mem_region( pci_resource_start(pdev, 2), 
+				    pci_resource_len(pdev, 2) );
+#else
+			release_mem_region( pci_resource_start(pdev, 1), 
+					    pci_resource_len(pdev, 1) );
+#endif
+		}
+#endif /*end #ifdef RTL_IO_MAP*/
+		free_rtllib(dev);
+
+		if(priv->scan_cmd)
+			kfree(priv->scan_cmd);
+
+	} else{
+		priv=rtllib_priv(dev);
+        }
+
+	pci_disable_device(pdev);
+#ifdef RTL8192SE   
+        pci_write_config_byte(pdev, 0x81,1);
+        pci_write_config_byte(pdev,0x44,3);
+#endif
+	RT_TRACE(COMP_DOWN, "wlan driver removed\n");
+}
+
+bool NicIFEnableNIC(struct net_device* dev)
+{
+	bool init_status = true;
+	struct r8192_priv* priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	if(IS_NIC_DOWN(priv)){
+		RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
+		priv->bdisable_nic = false;  
+		return RT_STATUS_FAILURE;
+	}
+
+	RT_TRACE(COMP_PS, "===========>%s()\n",__FUNCTION__);
+	priv->bfirst_init = true;
+	init_status = priv->ops->initialize_adapter(dev);
+	if (init_status != true) {
+		RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+		priv->bdisable_nic = false;  
+		return -1;
+	}
+	RT_TRACE(COMP_INIT, "start adapter finished\n");
+	RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+	priv->bfirst_init = false;
+
+	rtl8192_irq_enable(dev);
+	priv->bdisable_nic = false;
+	RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__);
+	return init_status;
+}
+bool NicIFDisableNIC(struct net_device* dev)
+{
+	bool	status = true;
+	struct r8192_priv* priv = rtllib_priv(dev);
+	u8 tmp_state = 0;
+	RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__);
+	priv->bdisable_nic = true;	
+	tmp_state = priv->rtllib->state;
+#ifdef _RTL8192_EXT_PATCH_
+	if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh)) 
+		rtllib_softmac_stop_protocol(priv->rtllib, 1, false);
+	else
+		rtllib_softmac_stop_protocol(priv->rtllib, 0, false);
+#else
+	rtllib_softmac_stop_protocol(priv->rtllib,false);
+#endif
+	priv->rtllib->state = tmp_state;
+	rtl8192_cancel_deferred_work(priv);
+	rtl8192_irq_disable(dev);
+
+	priv->ops->stop_adapter(dev, false);
+	RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__);
+
+	return status;
+}
+
+static int __init rtl8192_pci_module_init(void)
+{
+	int ret;
+	int error;
+
+#ifdef BUILT_IN_CRYPTO
+        ret = arc4_init();
+        if (ret) {
+                printk(KERN_ERR "arc4_init() failed %d\n", ret);
+                return ret;
+        }
+
+
+        ret = michael_mic_init();
+        if (ret) {
+                printk(KERN_ERR "michael_mic_init() failed %d\n", ret);
+                return ret;
+        }
+
+        ret = aes_init();
+        if (ret) {
+                printk(KERN_ERR "aes_init() failed %d\n", ret);
+                return ret;
+        }
+#endif
+#ifdef BUILT_IN_RTLLIB
+	ret = rtllib_init();
+	if (ret) {
+		printk(KERN_ERR "rtllib_init() failed %d\n", ret);
+		return ret;
+	}
+	ret = rtllib_crypto_init();
+	if (ret) {
+		printk(KERN_ERR "rtllib_crypto_init() failed %d\n", ret);
+		return ret;
+	}
+	ret = rtllib_crypto_tkip_init();
+	if (ret) {
+		printk(KERN_ERR "rtllib_crypto_tkip_init() failed %d\n", ret);
+		return ret;
+	}
+	ret = rtllib_crypto_ccmp_init();
+	if (ret) {
+		printk(KERN_ERR "rtllib_crypto_ccmp_init() failed %d\n", ret);
+		return ret;
+	}
+	ret = rtllib_crypto_wep_init();
+	if (ret) {
+		printk(KERN_ERR "rtllib_crypto_wep_init() failed %d\n", ret);
+		return ret;
+	}
+#endif
+#ifdef BUILT_IN_MSHCLASS
+	ret = msh_init();
+	if (ret) {
+		printk(KERN_ERR "msh_init() failed %d\n", ret);
+		return ret;
+	}
+#endif
+	printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
+	printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan Driver\n");
+	RT_TRACE(COMP_INIT, "Initializing module");
+	RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
+
+	error = rtl_create_debugfs_root();
+	if (error) {
+		RT_TRACE(COMP_DBG, "Create debugfs root fail: %d\n", error);
+		goto err_out;
+	}
+
+	rtl8192_proc_module_init();
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+      if(0!=pci_module_init(&rtl8192_pci_driver))
+#else
+      if(0!=pci_register_driver(&rtl8192_pci_driver))
+#endif
+	{
+		DMESG("No device found");
+		/*pci_unregister_driver (&rtl8192_pci_driver);*/
+		return -ENODEV;
+	}
+	return 0;
+err_out:
+        return error;
+
+}
+
+static void __exit rtl8192_pci_module_exit(void)
+{
+	pci_unregister_driver(&rtl8192_pci_driver);
+
+	RT_TRACE(COMP_DOWN, "Exiting");
+	rtl8192_proc_module_remove();
+	rtl_remove_debugfs_root();
+#ifdef BUILT_IN_RTLLIB
+	rtllib_crypto_tkip_exit();
+	rtllib_crypto_ccmp_exit();
+	rtllib_crypto_wep_exit();
+	rtllib_crypto_deinit();
+	rtllib_exit();
+#endif	
+#ifdef BUILT_IN_CRYPTO
+        arc4_exit();
+        michael_mic_exit();
+        aes_fini();
+#endif
+#ifdef BUILT_IN_MSHCLASS
+	msh_exit();
+#endif
+
+}
+
+void check_rfctrl_gpio_timer(unsigned long data)
+{
+	struct r8192_priv* priv = rtllib_priv((struct net_device *)data);
+
+	priv->polling_timer_on = 1;
+
+	queue_delayed_work_rsl(priv->priv_wq,&priv->gpio_change_rf_wq,0);
+
+	mod_timer(&priv->gpio_polling_timer, jiffies + MSECS(RTLLIB_WATCH_DOG_TIME));
+}
+
+/***************************************************************************
+     ------------------- module init / exit stubs ----------------
+****************************************************************************/
+module_init(rtl8192_pci_module_init);
+module_exit(rtl8192_pci_module_exit);
+
+MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards");
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+MODULE_VERSION(DRV_VERSION);
+#endif
+MODULE_LICENSE("GPL");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
+module_param(ifname, charp, S_IRUGO|S_IWUSR );
+module_param(hwwep,int, S_IRUGO|S_IWUSR);
+module_param(channels,int, S_IRUGO|S_IWUSR);
+#else
+MODULE_PARM(ifname, "s");
+MODULE_PARM(hwwep,"i");
+MODULE_PARM(channels,"i");
+#endif
+
+MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
+MODULE_PARM_DESC(hwwep," Try to use hardware WEP support(default use hw. set 0 to use software security)");
+MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_ethtool.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_ethtool.c
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ *****************************************************************************
+ */
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+
+#include "rtl_core.h"
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+static void rtl819x_ethtool_get_drvinfo(struct net_device *dev,
+		struct ethtool_drvinfo *info)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+#if defined RTL8192SE  
+	snprintf(info->fw_version, sizeof(info->fw_version), "%d",
+			priv->pFirmware->FirmwareVersion);
+#endif	
+	strcpy(info->bus_info, pci_name(priv->pdev));
+}
+
+static u32 rtl819x_ethtool_get_link(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	return ((priv->rtllib->state == RTLLIB_LINKED) || 
+		(priv->rtllib->state == RTLLIB_LINKED_SCANNING));
+}
+
+const struct ethtool_ops rtl819x_ethtool_ops = {
+	.get_drvinfo = rtl819x_ethtool_get_drvinfo,
+	.get_link = rtl819x_ethtool_get_link,
+};
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/Kconfig
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/Kconfig
@@ -0,0 +1,5 @@
+config RTL8192SE
+	tristate "Kernel module for RTL81991/2SE or RTL8171 wireless"
+	depends on X86
+	default m
+	---help---
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_ps.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_ps.c
@@ -0,0 +1,732 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ *****************************************************************************/
+#include "rtl_ps.h"
+#include "rtl_core.h"
+#ifdef RTL8192CE
+#include "rtl8192c/r8192C_phy.h"
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#include "rtl8192c/r8192C_Efuse.h"
+#elif defined RTL8192SE
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#include "rtl8192s/r8192S_Efuse.h"
+#else
+#include "rtl8192e/r8192E_phy.h"
+#include "rtl8192e/r8192E_phyreg.h"
+#include "rtl8192e/r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "rtl8192e/r8192E_cmdpkt.h"
+#endif
+
+#if defined(RTL8192E) || defined(RTL8192SE) || defined RTL8192CE
+void rtl8192_hw_sleep_down(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags = 0;
+#ifdef CONFIG_ASPM_OR_D3
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+#endif	
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	if (priv->RFChangeInProgress) {
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+		RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
+		printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
+		return;
+	}
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+	RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__);
+
+#ifdef CONFIG_RTLWIFI_DEBUGFS	
+	if(priv->debug->hw_holding) {
+		return;
+	}
+#endif	
+	MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
+#ifdef CONFIG_ASPM_OR_D3
+	if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM)
+	{
+		RT_ENABLE_ASPM(dev);
+		RT_SET_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM);
+	}
+#endif
+}
+
+void rtl8192_hw_sleep_wq(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct rtllib_device *ieee = container_of_dwork_rsl(data,struct rtllib_device,hw_sleep_wq);
+	struct net_device *dev = ieee->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+#endif
+        rtl8192_hw_sleep_down(dev);
+}
+
+void rtl8192_hw_wakeup(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags = 0;
+#ifdef CONFIG_ASPM_OR_D3
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+#endif	
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	if (priv->RFChangeInProgress) {
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+		RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
+		printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
+		queue_delayed_work_rsl(priv->rtllib->wq,&priv->rtllib->hw_wakeup_wq,MSECS(10));
+		return;
+	}
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+#ifdef CONFIG_ASPM_OR_D3
+	if (pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) {
+		RT_DISABLE_ASPM(dev);
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM);
+	}
+#endif
+	RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__);
+	MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
+}
+
+void rtl8192_hw_wakeup_wq(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct rtllib_device *ieee = container_of_dwork_rsl(data,struct rtllib_device,hw_wakeup_wq);  
+	struct net_device *dev = ieee->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+#endif
+	rtl8192_hw_wakeup(dev);
+
+}
+
+#define MIN_SLEEP_TIME 50
+#define MAX_SLEEP_TIME 10000
+void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
+{
+#ifdef _RTL8192_EXT_PATCH_
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 rb = jiffies, sleep_cost = MSECS(8+16+7), delta = 0;
+	unsigned long flags;
+
+	if((tl > rb) && (th > 0))
+		return;
+
+	spin_lock_irqsave(&priv->ps_lock,flags);
+
+	if (tl >= sleep_cost)
+		tl -= sleep_cost;
+	else if (th > 0) {
+		tl = 0xffffffff - sleep_cost + tl;  
+		th--;
+	} else {
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		return;
+	}
+
+	if (tl > rb) {
+		delta = tl - rb;
+	} else if (th > 0) {
+		delta = 0xffffffff - rb + tl;
+		th --;
+	} else {
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		return;
+	}
+
+	if (delta <= MSECS(MIN_SLEEP_TIME)) {
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		printk("too short to sleep::%x, %x, %lx\n",tl, rb,  MSECS(MIN_SLEEP_TIME));
+		return;
+	}	
+
+	if(delta > MSECS(MAX_SLEEP_TIME)) {
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		printk("========>too long to sleep:%x, %x, %lx\n", tl, rb,  MSECS(MAX_SLEEP_TIME));
+		return;
+	}
+
+	RT_TRACE(COMP_LPS, "==============>%s(): wake up time is %d,%d\n",__FUNCTION__,delta,jiffies_to_msecs(delta));
+	queue_delayed_work_rsl(priv->rtllib->wq,&priv->rtllib->hw_wakeup_wq,delta); 
+	queue_delayed_work_rsl(priv->rtllib->wq, (void *)&priv->rtllib->hw_sleep_wq,0);
+
+	spin_unlock_irqrestore(&priv->ps_lock,flags);
+#else
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	u32 rb = jiffies;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->ps_lock,flags);
+
+	tl -= MSECS(8+16+7);
+
+	if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
+			||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		printk("too short to sleep::%x, %x, %lx\n",tl, rb,  MSECS(MIN_SLEEP_TIME));
+		return;
+	}	
+
+	if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
+			((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
+			((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
+		printk("========>too long to sleep:%x, %x, %lx\n", tl, rb,  MSECS(MAX_SLEEP_TIME));
+		spin_unlock_irqrestore(&priv->ps_lock,flags);
+		return;
+	}
+	{
+		u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
+		queue_delayed_work_rsl(priv->rtllib->wq,
+				&priv->rtllib->hw_wakeup_wq,tmp); 
+	}
+	queue_delayed_work_rsl(priv->rtllib->wq, 
+			(void *)&priv->rtllib->hw_sleep_wq,0);
+	spin_unlock_irqrestore(&priv->ps_lock,flags);
+#endif
+}
+#endif
+
+#ifdef ENABLE_IPS
+void InactivePsWorkItemCallback(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() ---------> \n");			
+	pPSC->bSwRfProcessing = true;
+
+	RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n", \
+			pPSC->eInactivePowerState == eRfOff?"OFF":"ON");
+#ifdef CONFIG_ASPM_OR_D3
+	if(pPSC->eInactivePowerState == eRfOn)
+	{
+
+		if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM))
+		{
+			RT_DISABLE_ASPM(dev);
+			RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+		}
+#ifdef TODO		
+		else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3))
+		{
+			RT_LEAVE_D3(dev, false);
+			RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+		}
+#endif		
+	}
+#endif
+	MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
+
+#ifdef CONFIG_ASPM_OR_D3
+	if(pPSC->eInactivePowerState == eRfOff)
+	{
+		if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM)
+		{
+			RT_ENABLE_ASPM(dev);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+		}
+#ifdef TODO		
+		else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3)
+		{
+			RT_ENTER_D3(dev, false);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+		}
+#endif		
+	}
+#endif
+	
+#if 0
+	if(pPSC->eInactivePowerState == eRfOn)
+	{
+		while( index < 4 )
+		{
+			if( ( pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP104_Encryption ) ||
+				(pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP40_Encryption) )
+			{
+				if( pMgntInfo->SecurityInfo.KeyLen[index] != 0)
+				pAdapter->HalFunc.SetKeyHandler(pAdapter, index, 0, false, pMgntInfo->SecurityInfo.PairwiseEncAlgorithm, true, false);
+
+			}
+			index++;
+		}
+	}
+#endif
+	pPSC->bSwRfProcessing = false;	
+	RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <--------- \n");			
+}
+
+void
+IPSEnter(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL		pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	RT_RF_POWER_STATE 			rtState;
+
+	if (pPSC->bInactivePs)
+	{
+		rtState = priv->rtllib->eRFPowerState;
+		if (rtState == eRfOn && !pPSC->bSwRfProcessing &&\
+			(priv->rtllib->state != RTLLIB_LINKED)&&\
+			(priv->rtllib->iw_mode != IW_MODE_MASTER))
+		{
+			RT_TRACE(COMP_PS,"IPSEnter(): Turn off RF.\n");
+			pPSC->eInactivePowerState = eRfOff;
+			priv->isRFOff = true;
+			priv->bInPowerSaveMode = true;
+			InactivePsWorkItemCallback(dev);
+		}
+	}	
+}
+
+void
+IPSLeave(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	RT_RF_POWER_STATE 	rtState;
+
+	if (pPSC->bInactivePs)
+	{	
+		rtState = priv->rtllib->eRFPowerState;	
+		if (rtState != eRfOn  && !pPSC->bSwRfProcessing && priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS)
+		{
+			RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n");
+			pPSC->eInactivePowerState = eRfOn;
+			priv->bInPowerSaveMode = false;
+			InactivePsWorkItemCallback(dev);
+		}
+	}
+}
+void IPSLeave_wq(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct rtllib_device *ieee = container_of_work_rsl(data,struct rtllib_device,ips_leave_wq);
+	struct net_device *dev = ieee->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+#endif
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	down(&priv->rtllib->ips_sem);
+	IPSLeave(dev);	
+	up(&priv->rtllib->ips_sem);	
+}
+void rtllib_ips_leave_wq(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	RT_RF_POWER_STATE	rtState;
+	rtState = priv->rtllib->eRFPowerState;
+
+	if(priv->rtllib->PowerSaveControl.bInactivePs){ 
+		if(rtState == eRfOff){
+			if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+			{
+				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+				return;
+			}
+			else{
+				printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+				queue_work_rsl(priv->rtllib->wq,&priv->rtllib->ips_leave_wq);				
+			}
+		}
+	}
+}
+void rtllib_ips_leave(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	down(&priv->rtllib->ips_sem);
+	IPSLeave(dev);	
+	up(&priv->rtllib->ips_sem);	
+}
+#endif
+
+#ifdef ENABLE_LPS
+bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,	u8 rtPsMode)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+#ifdef _RTL8192_EXT_PATCH_
+	if((priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER)
+		|| (priv->rtllib->iw_mode == IW_MODE_MESH))	
+#else
+	if(priv->rtllib->iw_mode == IW_MODE_ADHOC)	
+#endif
+	{
+		return false;
+	}
+
+	
+	RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
+	if(!priv->ps_force) {
+		priv->rtllib->ps = rtPsMode;
+	}
+#if 0
+	priv->rtllib->dot11PowerSaveMode = rtPsMode;
+
+	if(priv->rtllib->dot11PowerSaveMode == eMaxPs)
+	{
+	}
+	else
+	{
+	}
+#endif
+	if(priv->rtllib->sta_sleep != 0 && rtPsMode == RTLLIB_PS_DISABLED)
+	{
+                unsigned long flags;
+
+		rtl8192_hw_wakeup(dev);
+		priv->rtllib->sta_sleep = 0;
+
+                spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags);
+		printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
+		rtllib_sta_ps_send_null_frame(priv->rtllib, 0);
+                spin_unlock_irqrestore(&(priv->rtllib->mgmt_tx_lock), flags);
+	}
+
+#if 0
+	if((pPSC->bFwCtrlLPS) && (pPSC->bLeisurePs))
+	{	
+		if(priv->rtllib->dot11PowerSaveMode == eActive)
+		{
+			RpwmVal = 0x0C; 
+			FwPwrMode = FW_PS_ACTIVE_MODE;
+			Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_SET_RPWM, (pu1Byte)(&RpwmVal));
+			Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_H2C_FW_PWRMODE, (pu1Byte)(&FwPwrMode));
+		}
+		else
+		{
+			if(GetFwLPS_Doze(Adapter))
+			{
+				RpwmVal = 0x02; 
+				Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_H2C_FW_PWRMODE, (pu1Byte)(&pPSC->FWCtrlPSMode));
+				Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_SET_RPWM, (pu1Byte)(&RpwmVal));
+			}
+			else
+			{
+				pMgntInfo->dot11PowerSaveMode = eActive;
+				Adapter->bInPowerSaveMode = false;	
+			}
+		}
+	}
+#endif
+	return true;
+}
+
+
+void LeisurePSEnter(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+	RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n", 
+		pPSC->bLeisurePs, priv->rtllib->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
+
+#ifdef _RTL8192_EXT_PATCH_
+	if(!((priv->rtllib->iw_mode == IW_MODE_INFRA) && (priv->rtllib->state == RTLLIB_LINKED))
+		|| (priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER)
+		|| (priv->rtllib->iw_mode == IW_MODE_MESH))
+#else
+	if(!((priv->rtllib->iw_mode == IW_MODE_INFRA) && (priv->rtllib->state == RTLLIB_LINKED))
+		|| (priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER))
+#endif
+		return;
+
+	if (pPSC->bLeisurePs)
+	{
+		if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) 
+		{
+	
+			if(priv->rtllib->ps == RTLLIB_PS_DISABLED)
+			{
+
+				RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+
+				if(!pPSC->bFwCtrlLPS)
+				{
+					if (priv->rtllib->SetFwCmdHandler)
+					{
+						priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_ENTER);
+					} 
+				}	
+				MgntActSet_802_11_PowerSaveMode(dev, RTLLIB_PS_MBCAST|RTLLIB_PS_UNICAST);
+
+				/*if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM)
+				{
+					RT_ENABLE_ASPM(pAdapter);
+					RT_SET_PS_LEVEL(pAdapter, RT_RF_LPS_LEVEL_ASPM);
+				}*/
+
+			}	
+		}
+		else
+			pPSC->LpsIdleCount++;
+	}	
+}
+
+
+void LeisurePSLeave(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+
+	RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+	RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n", 
+		pPSC->bLeisurePs, priv->rtllib->ps);
+
+	if (pPSC->bLeisurePs)
+	{	
+		if(priv->rtllib->ps != RTLLIB_PS_DISABLED)
+		{
+#ifdef CONFIG_ASPM_OR_D3
+			if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM && RT_IN_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM))
+			{
+				RT_DISABLE_ASPM(dev);
+				RT_CLEAR_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM);
+			} 
+#endif
+			RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+			MgntActSet_802_11_PowerSaveMode(dev, RTLLIB_PS_DISABLED);
+
+			if(!pPSC->bFwCtrlLPS) 
+			{
+				if (priv->rtllib->SetFwCmdHandler)
+				{
+					priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_LEAVE);
+				} 
+                    }
+		}
+	}
+}
+#endif
+
+#ifdef CONFIG_ASPM_OR_D3
+bool
+PlatformEnable92CEBackDoor(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	bool			bResult = true;
+	u8			value;
+
+	pci_read_config_byte(priv->pdev, 0x70f, &value);
+	value |= BIT7;
+	pci_write_config_byte(priv->pdev, 0x70f, value);
+
+
+	pci_read_config_byte(priv->pdev, 0x719, &value);
+	value |= (BIT3|BIT4);
+	pci_write_config_byte(priv->pdev, 0x719, value);
+	
+
+	return bResult;
+}
+
+bool PlatformSwitchDevicePciASPM(struct net_device *dev, u8 value)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	bool bResult = false;
+
+#ifdef RTL8192CE
+	value |= 0x40;
+#endif
+
+	pci_write_config_byte(priv->pdev, priv->ASPMRegOffset, value);
+	udelay(100);
+
+	return bResult;
+}
+
+bool PlatformSwitchClkReq(struct net_device *dev, u8 value)
+{
+	bool bResult = false;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8	Buffer;
+
+	Buffer= value;	
+	
+	pci_write_config_byte(priv->pdev,priv->ClkReqOffset,value);
+	bResult = true;
+#ifdef TODO
+	if(Buffer) {
+		priv->ClkReqState = true;
+	} else {
+		priv->ClkReqState = false;
+	}
+#endif
+	udelay(100);
+	return bResult;
+}
+
+void
+PlatformDisableASPM(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	u8	LinkCtrlReg;
+	u16	PciBridgeLinkCtrlReg, ASPMLevel=0;
+
+#ifdef RTL8192CE
+	if (!priv->aspm_clkreq_enable) {
+		RT_TRACE(COMP_INIT, "%s: Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n",\
+			       	__FUNCTION__);
+		return;
+	}
+#endif
+
+	LinkCtrlReg = priv->LinkCtrlReg;
+	ASPMLevel |= BIT0|BIT1;
+	LinkCtrlReg &=~ASPMLevel;
+
+	PciBridgeLinkCtrlReg = priv->PciBridgeLinkCtrlReg;
+	PciBridgeLinkCtrlReg &=~(BIT0|BIT1);
+
+	if (priv->aspm_clkreq_enable) {
+
+		pci_write_config_byte(priv->bridge_pdev,priv->PciBridgeASPMRegOffset,PciBridgeLinkCtrlReg);
+		RT_TRACE(COMP_POWER, "Write reg[%x]=%x\n", (priv->PciBridgeASPMRegOffset), PciBridgeLinkCtrlReg);
+		udelay(100);
+	}
+
+	PlatformSwitchDevicePciASPM(dev, priv->LinkCtrlReg);
+
+	PlatformSwitchClkReq(dev, 0x0);
+	if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ)
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_CLK_REQ);
+	udelay(100);
+}
+
+void PlatformEnableASPM(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	u16	ASPMLevel = 0;
+
+	if (!priv->aspm_clkreq_enable) {
+		RT_TRACE(COMP_INIT, "%s: Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n",\
+			       	__FUNCTION__);
+		return;
+	}
+
+	ASPMLevel |= priv->RegDevicePciASPMSetting;
+	PlatformSwitchDevicePciASPM(dev, (priv->LinkCtrlReg | ASPMLevel));
+
+	if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) {
+		PlatformSwitchClkReq(dev,(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
+		RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_CLK_REQ);
+	}
+	udelay(100);
+
+	pci_write_config_byte(priv->bridge_pdev,priv->PciBridgeASPMRegOffset,\
+			((priv->PciBridgeLinkCtrlReg | priv->RegHostPciASPMSetting)&~BIT0)&0xff);
+	RT_TRACE(COMP_INIT, "Write reg[%x] = %x\n",
+		priv->PciBridgeASPMRegOffset, 
+		(priv->PciBridgeLinkCtrlReg|priv->RegHostPciASPMSetting));
+	udelay(100);
+}
+
+u32 PlatformResetPciSpace(struct net_device *dev,u8 Value)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	pci_write_config_byte(priv->pdev,0x04,Value);	
+
+	return 1;
+	
+}
+bool PlatformSetPMCSR(struct net_device *dev,u8 value,bool bTempSetting)
+{
+	bool bResult = false;
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8  Buffer;
+	bool bActuallySet=false, bSetFunc=false;
+	unsigned long flag;
+
+	Buffer= value;
+	spin_lock_irqsave(&priv->D3_lock,flag);
+#ifdef TODO	
+	if(bTempSetting) 
+	{
+		if(Buffer==0x00) 
+		{
+			priv->LeaveD3Cnt++;
+
+			{
+				bActuallySet =true;
+			}
+		}
+		else 
+		{
+			priv->LeaveD3Cnt--;
+
+			if(priv->LeaveD3Cnt == 0) 
+			{
+				bActuallySet=true;
+			}
+		}
+	}
+	else
+	{
+		priv->LeaveD3Cnt=0;
+		bActuallySet=true;
+		bSetFunc=true;
+	}
+#endif
+	if (bActuallySet) {
+		if (Buffer) {
+			PlatformSwitchClkReq(dev, 0x01);
+		} else {
+			PlatformSwitchClkReq(dev, 0x00);
+		}
+		
+		pci_write_config_byte(priv->pdev,0x44,Buffer);
+		RT_TRACE(COMP_POWER, "PlatformSetPMCSR(): D3(value: %d)\n", Buffer);
+
+		bResult = true;
+		if (!Buffer) {
+			PlatformResetPciSpace(dev, 0x06);
+			PlatformResetPciSpace(dev, 0x07);
+		}
+
+		if (bSetFunc) {
+			if(Buffer) 
+			{
+#ifdef TO_DO_LIST
+				RT_DISABLE_FUNC(Adapter, DF_IO_D3_BIT);
+#endif
+			} else {
+#ifdef TO_DO_LIST
+				RT_ENABLE_FUNC(Adapter, DF_IO_D3_BIT);
+#endif
+			}
+		}
+		
+	}
+	spin_unlock_irqrestore(&priv->D3_lock,flag);
+	return bResult;
+}
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_regd.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_regd.c
@@ -0,0 +1,390 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the ath driver, which is:
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#ifdef CONFIG_CFG_80211
+#include "rtl_core.h"
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <net/cfg80211.h>
+
+#ifdef CONFIG_CRDA
+static struct country_code_to_enum_rd allCountries[] = {
+	{COUNTRY_CODE_FCC, "US"},
+	{COUNTRY_CODE_IC, "US"},
+	{COUNTRY_CODE_ETSI, "EC"},
+	{COUNTRY_CODE_SPAIN, "EC"},
+	{COUNTRY_CODE_FRANCE, "EC"},
+	{COUNTRY_CODE_MKK, "JP"},
+	{COUNTRY_CODE_MKK1, "JP"},
+	{COUNTRY_CODE_ISRAEL, "EC"},
+	{COUNTRY_CODE_TELEC, "JP"},
+	{COUNTRY_CODE_MIC, "JP"},
+	{COUNTRY_CODE_GLOBAL_DOMAIN, "JP"},
+	{COUNTRY_CODE_WORLD_WIDE_13, "EC"},
+	{COUNTRY_CODE_TELEC_NETGEAR, "EC"},
+};
+
+/* Only these channels all allow active scan on all world regulatory domains */
+#define RTL819x_2GHZ_CH01_11	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
+
+/* We enable active scan on these a case by case basis by regulatory domain */
+#define RTL819x_2GHZ_CH12_13	REG_RULE(2467-10, 2472+10, 40, 0, 20, NL80211_RRF_PASSIVE_SCAN)
+#define RTL819x_2GHZ_CH14	REG_RULE(2484-10, 2484+10, 40, 0, 20, NL80211_RRF_PASSIVE_SCAN | \
+								      NL80211_RRF_NO_OFDM)
+
+static const struct ieee80211_regdomain rtl_regdom_11 = {
+	.n_reg_rules = 1,
+	.alpha2 =  "99",
+	.reg_rules = {
+		RTL819x_2GHZ_CH01_11,
+	}
+};
+
+static const struct ieee80211_regdomain rtl_regdom_global = {
+	.n_reg_rules = 3,
+	.alpha2 =  "99",
+	.reg_rules = {
+		RTL819x_2GHZ_CH01_11,
+		RTL819x_2GHZ_CH12_13, 
+		RTL819x_2GHZ_CH14,
+	}
+};
+
+static const struct ieee80211_regdomain rtl_regdom_world = {
+	.n_reg_rules = 2,
+	.alpha2 =  "99",
+	.reg_rules = {
+		RTL819x_2GHZ_CH01_11,
+		RTL819x_2GHZ_CH12_13,
+	}
+};
+
+static void rtl_reg_apply_chan_plan(struct wiphy *wiphy)
+{
+	struct net_device *dev = wiphy_to_net_device(wiphy);
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_device *rtllib = priv->rtllib;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int i;
+
+	sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+
+	for (i = 0; i < sband->n_channels; i++) {
+		ch = &sband->channels[i];
+		if (ch->flags & IEEE80211_CHAN_DISABLED) {
+			GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 0;	
+		} else {
+			if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
+				GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 2;	
+			} else {
+				GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 1;	
+			}
+		}
+
+	}
+
+	for (i = sband->n_channels - 1; i >= 0; i--) {
+		ch = &sband->channels[i];
+		if (!(ch->flags & IEEE80211_CHAN_NO_IBSS)) {
+			rtllib->ibss_maxjoin_chal = ch->hw_value;
+			break;
+		}
+	}
+
+	rtllib->IbssStartChnl = 10;
+
+	return;
+}
+
+void rtl_dump_channel_map(struct wiphy *wiphy)
+{
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	unsigned int i;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+
+		if (!wiphy->bands[band])
+			continue;
+
+		sband = wiphy->bands[band];
+
+		for (i = 0; i < sband->n_channels; i++) {
+			ch = &sband->channels[i];
+			printk("chan:%d, NO_IBSS:%d," 
+					" PASSIVE_SCAN:%d, RADAR:%d, DISABLED:%d\n", i+1,
+					(ch->flags&IEEE80211_CHAN_NO_IBSS) ? 1:0, 
+					(ch->flags&IEEE80211_CHAN_PASSIVE_SCAN) ? 1:0,
+					(ch->flags&IEEE80211_CHAN_RADAR) ? 1:0,
+					(ch->flags&IEEE80211_CHAN_DISABLED) ? 1:0
+			      );
+		}
+
+	}
+}
+
+static void rtl_reg_apply_world_flags(struct wiphy *wiphy,
+				      enum nl80211_reg_initiator initiator,
+				      struct rtl_regulatory *reg)
+{
+	rtl_reg_apply_chan_plan(wiphy);
+	return;
+}
+
+int rtl_reg_notifier_apply(struct wiphy *wiphy,
+			   struct regulatory_request *request,
+			   struct rtl_regulatory *reg)
+{
+	switch (request->initiator) {
+	case NL80211_REGDOM_SET_BY_CORE:
+		break;
+	case NL80211_REGDOM_SET_BY_DRIVER:
+	case NL80211_REGDOM_SET_BY_USER:
+		rtl_reg_apply_world_flags(wiphy, request->initiator, reg);
+		rtl_dump_channel_map(wiphy);
+		break;
+	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+		rtl_reg_apply_world_flags(wiphy, request->initiator, reg);
+		rtl_dump_channel_map(wiphy);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct
+ieee80211_regdomain *rtl_regdomain_select(struct rtl_regulatory *reg)
+{
+	switch (reg->country_code) {
+	case COUNTRY_CODE_FCC:
+	case COUNTRY_CODE_IC:
+		return &rtl_regdom_11;
+	case COUNTRY_CODE_ETSI:
+	case COUNTRY_CODE_SPAIN:
+	case COUNTRY_CODE_FRANCE:
+	case COUNTRY_CODE_ISRAEL:
+	case COUNTRY_CODE_TELEC_NETGEAR:
+		return &rtl_regdom_world;
+	case COUNTRY_CODE_MKK:
+	case COUNTRY_CODE_MKK1:
+	case COUNTRY_CODE_TELEC:
+	case COUNTRY_CODE_MIC:
+		return &rtl_regdom_global;
+	case COUNTRY_CODE_GLOBAL_DOMAIN:
+		return &rtl_regdom_global;
+	case COUNTRY_CODE_WORLD_WIDE_13:
+		return &rtl_regdom_world;
+	default:
+		WARN_ON(1);
+		return &rtl_regdom_world;
+	}
+}
+
+static int
+rtl_regd_init_wiphy(struct rtl_regulatory *reg,
+		    struct wiphy *wiphy,
+		    int (*reg_notifier)(struct wiphy *wiphy,
+					struct regulatory_request *request))
+{
+	const struct ieee80211_regdomain *regd;
+
+	wiphy->reg_notifier = reg_notifier;
+
+	wiphy->custom_regulatory = true;
+	wiphy->strict_regulatory = false;
+
+	regd = rtl_regdomain_select(reg);
+
+	wiphy->disable_beacon_hints = true;
+	wiphy_apply_custom_regulatory(wiphy, regd);
+
+	rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
+	return 0;
+}
+
+static struct 
+country_code_to_enum_rd *rtl_regd_find_country(u16 countryCode)
+{       
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+		if (allCountries[i].countryCode == countryCode)
+			return &allCountries[i];
+	}
+	return NULL;
+} 
+
+int rtl_regd_init(struct net_device *dev,
+	      int (*reg_notifier)(struct wiphy *wiphy,
+				  struct regulatory_request *request))
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+	struct rtl_regulatory *reg = &priv->rtllib->regulatory;
+	struct wiphy *wiphy = priv->rtllib->wdev.wiphy;
+	struct country_code_to_enum_rd *country = NULL;
+
+	if (wiphy == NULL || reg == NULL){
+		return -EINVAL;
+	}
+
+	printk(KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", priv->ChannelPlan);
+
+	reg->country_code = priv->ChannelPlan;
+
+	if (reg->country_code >= COUNTRY_CODE_MAX) {
+		printk(KERN_DEBUG "rtl: EEPROM indicates invalid contry code"
+		       "world wide 13 should be used\n");
+		reg->country_code = COUNTRY_CODE_WORLD_WIDE_13;
+	}
+
+	country = rtl_regd_find_country(reg->country_code);
+
+	if (country) {
+		reg->alpha2[0] = country->isoName[0];
+		reg->alpha2[1] = country->isoName[1];
+	} else {
+		reg->alpha2[0] = '0';
+		reg->alpha2[1] = '0';
+	}
+
+	printk(KERN_DEBUG "rtl: Country alpha2 being used: %c%c\n",
+		reg->alpha2[0], reg->alpha2[1]);
+	rtl_regd_init_wiphy(reg, wiphy, reg_notifier);
+	rtl_dump_channel_map(wiphy);
+	return 0;
+}
+
+int rtl_reg_notifier(struct wiphy *wiphy,
+			      struct regulatory_request *request)
+{
+	struct net_device *dev = wiphy_to_net_device(wiphy);
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+	struct rtl_regulatory *reg = &priv->rtllib->regulatory;
+
+	printk("rtl_regd: %s\n", __func__);
+	return rtl_reg_notifier_apply(wiphy, request, reg);
+}
+#endif
+
+struct net_device *wiphy_to_net_device(struct wiphy *wiphy)
+{
+	struct rtllib_device *rtllib;
+
+	rtllib = wiphy_priv(wiphy);
+	return rtllib->dev;
+}
+
+static const struct ieee80211_rate rtl819x_rates[] = {
+	{ .bitrate = 10, .hw_value = 0, },
+	{ .bitrate = 20, .hw_value = 1, },
+	{ .bitrate = 55, .hw_value = 2, },
+	{ .bitrate = 110, .hw_value = 3, },
+	{ .bitrate = 60, .hw_value = 4, },
+	{ .bitrate = 90, .hw_value = 5, },
+	{ .bitrate = 120, .hw_value = 6, },
+	{ .bitrate = 180, .hw_value = 7, },
+	{ .bitrate = 240, .hw_value = 8, },
+	{ .bitrate = 360, .hw_value = 9, },
+	{ .bitrate = 480, .hw_value = 10, },
+	{ .bitrate = 540, .hw_value = 11, },
+};
+
+#define CHAN2G(_freq, _flags, _idx)  { \
+	        .band = IEEE80211_BAND_2GHZ, \
+	        .center_freq = (_freq), \
+		.flags = (_flags), \
+	        .hw_value = (_idx), \
+	        .max_power = 20, \
+}
+
+static struct ieee80211_channel rtl819x_2ghz_chantable[] = {
+	CHAN2G(2412, 0, 1), /* Channel 1 */
+	CHAN2G(2417, 0, 2), /* Channel 2 */
+	CHAN2G(2422, 0, 3), /* Channel 3 */
+	CHAN2G(2427, 0, 4), /* Channel 4 */
+	CHAN2G(2432, 0, 5), /* Channel 5 */
+	CHAN2G(2437, 0, 6), /* Channel 6 */
+	CHAN2G(2442, 0, 7), /* Channel 7 */
+	CHAN2G(2447, 0, 8), /* Channel 8 */
+	CHAN2G(2452, 0, 9), /* Channel 9 */
+	CHAN2G(2457, 0, 10), /* Channel 10 */
+	CHAN2G(2462, 0, 11), /* Channel 11 */
+	CHAN2G(2467, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 12), /* Channel 12 */
+	CHAN2G(2472, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 13), /* Channel 13 */
+	CHAN2G(2484, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 14), /* Channel 14 */
+};
+
+int rtllib_set_geo(struct r8192_priv *priv)
+{	
+	priv->bands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+	priv->bands[IEEE80211_BAND_2GHZ].channels = rtl819x_2ghz_chantable;
+	priv->bands[IEEE80211_BAND_2GHZ].n_channels = ARRAY_SIZE(rtl819x_2ghz_chantable);
+	
+	memcpy(&priv->rates[IEEE80211_BAND_2GHZ], rtl819x_rates, sizeof(rtl819x_rates));
+
+	priv->bands[IEEE80211_BAND_2GHZ].n_bitrates = ARRAY_SIZE(rtl819x_rates);
+	priv->bands[IEEE80211_BAND_2GHZ].bitrates = priv->rates[IEEE80211_BAND_2GHZ];
+
+	return 0;
+}
+
+bool rtl8192_register_wiphy_dev(struct net_device *dev)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct wireless_dev *wdev = &priv->rtllib->wdev;
+#ifdef CONFIG_CRDA
+	struct rtl_regulatory *reg;
+#endif
+	memcpy(wdev->wiphy->perm_addr, dev->dev_addr, ETH_ALEN);
+	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &(priv->bands[IEEE80211_BAND_2GHZ]);
+	set_wiphy_dev(wdev->wiphy, &priv->pdev->dev);
+
+#ifdef CONFIG_CRDA
+	if (rtl_regd_init(dev, rtl_reg_notifier)) {
+		return false;
+	}
+#endif
+
+	if (wiphy_register(wdev->wiphy)) {
+		return false;
+	}
+
+#ifdef CONFIG_CRDA
+	reg = &priv->rtllib->regulatory;
+	if (reg != NULL) {
+		if (regulatory_hint(wdev->wiphy, reg->alpha2)) {
+			printk("########>%s() regulatory_hint fail\n", __func__);
+			;
+		} else {
+			printk("########>#%s() regulatory_hint success\n", __func__);
+		}
+	} else {
+		printk("#########%s() regulator null\n", __func__);
+	}
+#endif
+	return true;
+}
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_rfkill.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_rfkill.c
@@ -0,0 +1,221 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#include "rtl_core.h"
+#include "rtl_dm.h"
+#include "rtl_rfkill.h"
+
+#ifdef CONFIG_RTL_RFKILL
+static void rtl8192_before_radio_check(struct net_device *dev, 
+				       bool *rf_state, 
+				       bool *turnonbypowerdomain)
+{  
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL   pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	*rf_state = (priv->rtllib->eRFPowerState != eRfOn);	
+#ifdef CONFIG_ASPM_OR_D3
+	if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM))
+	{
+		RT_DISABLE_ASPM(dev);
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+	}
+	else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3))
+	{
+#ifdef TODO             
+		RT_LEAVE_D3(dev, false);
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+#endif
+	}
+#endif	
+	if (RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
+		Power_DomainInit92SE(dev);
+		*turnonbypowerdomain = true;
+	}
+
+}
+
+static bool rtl8192_radio_on_off_checking(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8      u1Tmp = 0;
+	u8 	gpio;
+	
+	if (priv->pwrdown) {
+		u1Tmp = read_nic_byte(dev, 0x06);
+		gpio = u1Tmp & BIT6;
+	} else	
+#ifdef CONFIG_BT_COEXIST
+	if (pHalData->bt_coexist.BluetoothCoexist) {
+		if (pHalData->bt_coexist.BT_CoexistType == BT_2Wire) {
+			PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, 0xa);
+			u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL);
+			delay_us(100);
+			u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN);
+			RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp));
+			retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff;
+		} else if ((pHalData->bt_coexist.BT_CoexistType == BT_ISSC_3Wire) ||
+				(pHalData->bt_coexist.BT_CoexistType == BT_Accel) ||
+				(pHalData->bt_coexist.BT_CoexistType == BT_CSR)) {
+			u4tmp = PHY_QueryBBReg(pAdapter, 0x87c, bMaskDWord);
+			if ((u4tmp & BIT17) != 0) {
+				PHY_SetBBReg(pAdapter, 0x87c, bMaskDWord, u4tmp & ~BIT17);
+				delay_us(50);
+				RTPRINT(FBT, BT_RFPoll, ("BT write 0x87c (~BIT17) = 0x%x\n", u4tmp &~BIT17));
+			}
+			u4tmp = PHY_QueryBBReg(pAdapter, 0x8e0, bMaskDWord);
+			RTPRINT(FBT, BT_RFPoll, ("BT read 0x8e0 (BIT24)= 0x%x\n", u4tmp));
+			retval = (u4tmp & BIT24) ? eRfOn : eRfOff;
+			RTPRINT(FBT, BT_RFPoll, ("BT check RF state to %s\n", (retval==eRfOn)? "ON":"OFF"));
+		}
+	} else 
+#endif
+	{
+		write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO));
+		u1Tmp = read_nic_byte(dev, GPIO_IO_SEL);
+
+		u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK;
+		write_nic_byte(dev, GPIO_IO_SEL, u1Tmp);
+
+		mdelay(10);
+
+		u1Tmp = read_nic_byte(dev, GPIO_IN);
+		gpio = u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT;
+	}
+#ifdef DEBUG_RFKILL 
+	{
+		static u8 	gpio_test;
+		printk("%s: gpio = %x\n", __FUNCTION__, gpio);
+		if(gpio_test % 5 == 0) {
+			gpio = 0;
+		} else {
+			gpio = 1;
+		}
+		printk("%s: gpio_test = %d, gpio = %x\n", __FUNCTION__, gpio_test++ % 20, gpio);
+	}
+#endif 
+
+	return gpio;
+}
+
+static void  rtl8192_after_radio_check(struct net_device *dev, bool rf_state, bool turnonbypowerdomain)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+        PRT_POWER_SAVE_CONTROL  pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+	if (turnonbypowerdomain) {
+		PHY_SetRtl8192seRfHalt(dev);
+		RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+	}
+#ifdef CONFIG_ASPM_OR_D3
+	if (!rf_state) {
+		if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) {
+			RT_ENABLE_ASPM(dev);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+		}
+#ifdef TODO             
+		else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) {
+			RT_ENTER_D3(dev, false);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+		}
+#endif
+	}
+#endif
+	return;
+}
+
+static bool rtl8192_is_radio_enabled(struct net_device *dev, bool *radio_enabled)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	bool rf_state = false;
+	bool turnonbypowerdomain = false;
+	bool valid;
+
+	rtl8192_before_radio_check(dev, &rf_state, &turnonbypowerdomain);
+	*radio_enabled = rtl8192_radio_on_off_checking(dev);
+	rtl8192_after_radio_check(dev, rf_state, turnonbypowerdomain);
+	if (priv->bResetInProgress) {
+		priv->RFChangeInProgress = false;
+		valid = false;
+	} else {
+		valid = true;
+	}
+	
+	return valid;
+}
+
+bool rtl8192_rfkill_init(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct wireless_dev *wdev = &priv->rtllib->wdev;
+	bool radio_enabled;
+	bool valid = rtl8192_is_radio_enabled(dev, &radio_enabled);
+
+	if (valid) {
+		priv->rfkill_off = radio_enabled;
+		printk(KERN_INFO "rtl8192: wireless switch is %s\n",
+				priv->rfkill_off ? "on" : "off");
+		wiphy_rfkill_set_hw_state(wdev->wiphy, !priv->rfkill_off);
+		wiphy_rfkill_start_polling(wdev->wiphy);
+		return true;
+	} else {
+		return false;
+	}
+}
+
+void rtl8192_rfkill_poll(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct wireless_dev *wdev = &priv->rtllib->wdev;
+	bool radio_enabled;
+	bool valid;
+	
+	if (priv->being_init_adapter) {
+		return;
+	}
+
+	if (priv->ResetProgress == RESET_TYPE_SILENT) {
+		RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), 
+				"%s(): silent Reseting, ignore rf polling!\n", __FUNCTION__);
+		return;
+	}
+
+	valid = rtl8192_is_radio_enabled(dev, &radio_enabled);
+	if (valid) {
+		if (unlikely(radio_enabled != priv->rfkill_off)) {
+			priv->rfkill_off = radio_enabled;
+			printk(KERN_INFO "rtl8192: wireless radio switch turned %s\n",
+					radio_enabled ? "on" : "off");
+			wiphy_rfkill_set_hw_state(wdev->wiphy, !radio_enabled);
+		}
+	}
+}
+
+void rtl8192_rfkill_exit(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct wireless_dev *wdev = &priv->rtllib->wdev;
+
+	wiphy_rfkill_stop_polling(wdev->wiphy);
+}
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_debug.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_debug.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL_DEBUG_H
+#define _RTL_DEBUG_H
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9))
+#include <linux/debugfs.h>
+#endif
+
+struct r8192_priv;
+struct _tx_desc_8192se;
+struct _TX_DESC_8192CE;
+struct net_device;
+
+typedef struct _rtl_fs_debug
+{
+	const char *name;
+	struct dentry *dir_drv;
+	struct dentry *debug_register;
+	u32 hw_type;
+	u32 hw_offset; 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20))
+	bool hw_holding;
+#else
+	u8 hw_holding;
+#endif
+} rtl_fs_debug;
+
+void print_buffer(u32 *buffer, int len);
+void dump_eprom(struct net_device *dev);
+void rtl8192_dump_reg(struct net_device *dev);
+
+#ifdef RTL8192SE
+void rtl8192se_dump_tx_desc(struct _tx_desc_8192se *pDesc);
+#endif
+#ifdef RTL8192CE
+void rtl8192ce_dump_tx_desc(struct _TX_DESC_8192CE *pDesc);
+#endif
+
+/* debugfs stuff */
+#ifdef CONFIG_RTLWIFI_DEBUGFS
+int rtl_debug_module_init(struct r8192_priv *priv, const char *name);
+void rtl_debug_module_remove(struct r8192_priv *priv);
+int rtl_create_debugfs_root(void);
+void rtl_remove_debugfs_root(void);
+#else
+static inline int rtl_debug_module_init(struct r8192_priv *priv, const char *name) {
+	return 0;
+}
+static inline void rtl_debug_module_remove(struct r8192_priv *priv) {
+	
+}
+static inline int rtl_create_debugfs_root(void) {
+	return 0;
+}
+static inline void rtl_remove_debugfs_root(void) {
+}
+#endif
+
+/* proc stuff */
+void rtl8192_proc_init_one(struct net_device *dev);
+void rtl8192_proc_remove_one(struct net_device *dev);
+void rtl8192_proc_module_init(void);
+void rtl8192_proc_module_remove(void);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_dm.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_dm.c
@@ -0,0 +1,5294 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifdef RTL8192SE
+#include "rtl_core.h"
+#include "rtl_dm.h"
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#else
+#include "rtl_core.h"
+#include "rtl_dm.h"
+#include "rtl8192e/r8192E_hw.h"
+#include "rtl8192e/r8192E_phy.h"
+#include "rtl8192e/r8192E_phyreg.h"
+#include "rtl8192e/r8190P_rtl8256.h"
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+#include "../../mshclass/msh_class.h"
+#endif
+
+/*---------------------------Define Local Constant---------------------------*/
+#ifdef  RTL8190P
+static u32 edca_setting_DL[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0x5e4322, 	
+   0x5ea44f,	
+   0x5e4322,  	
+   0x604322, 	
+   0xa44f, 		
+   0x5e4322,	
+   0x5e4322	
+ };
+
+static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0x5e4322, 	
+   0x5e4322, 	
+   0x5e4322,  	
+   0x604322, 	
+   0xa44f, 		
+   0x5e4322,	
+   0x5e4322	
+};
+		
+static u32 edca_setting_UL[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0xa44f,   	
+   0x5ea44f,	
+   0x5e4322,  	 
+   0x604322, 	
+   0x5e4322, 	
+   0x5e4322,	
+   0x5e4322	
+};
+
+#elif defined RTL8192E
+static u32 edca_setting_DL[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0x5e4322, 	
+   0x5ea44f,	
+   0x5e4322, 	
+   0x604322, 	
+   0xa44f, 		
+   0x5e4322,	
+   0x5e4332	
+ };
+
+static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0x5e4322, 	
+   0x5e4322, 	
+   0x5e4322, 	
+   0x604322, 	
+   0xa44f, 		
+   0x5e4322,	
+   0x5e4322	
+};
+
+static u32 edca_setting_UL[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0xa44f,	  	
+   0x5ea44f,	
+   0x5e4322,  	
+   0x604322, 	
+   0x5e4322, 	
+   0x5e4322,	
+   0x5e4332	
+};
+
+#elif defined(RTL8192SE)
+static u32 edca_setting_DL[HT_IOT_PEER_MAX] = 
+{ 0xa44f, 		
+   0x5ea44f, 	
+   0x5ea44f,	
+   0xa630, 		
+   0xa44f,
+   0xa630, 		
+   0xa630,		
+   0xa42b,
+   0x5e4322,	
+   0x5e4322	
+ };	
+
+static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = 
+															
+{ 0x4322, 		
+   0xa44f, 		
+   0x5ea44f,	
+   0xa42b, 		
+   0x5e4322, 	
+   0x4322, 		
+   0xa430,		
+   0x5ea44f,	
+   0x5e4322,	
+   0x5e4322	
+};
+
+static u32 edca_setting_UL[HT_IOT_PEER_MAX] = 
+{ 0x5e4322, 	
+   0xa44f,		
+   0x5ea44f,	
+   0x5ea322, 	
+   0x5ea422,
+   0x5ea322, 	
+   0x3ea44f,	
+   0x5ea44f,	
+   0x5e4322,	
+   0x5e4322	
+ };	
+#endif
+
+#define RTK_UL_EDCA 0xa44f
+#define RTK_DL_EDCA 0x5e4322
+/*---------------------------Define Local Constant---------------------------*/
+
+
+/*------------------------Define global variable-----------------------------*/
+dig_t	dm_digtable;
+u8		dm_shadow[16][256] = {{0}};
+DRxPathSel	DM_RxPathSelTable;
+/*------------------------Define global variable-----------------------------*/
+
+
+/*------------------------Define local variable------------------------------*/
+/*------------------------Define local variable------------------------------*/
+
+
+/*--------------------Define export function prototype-----------------------*/
+extern	void	init_hal_dm(struct net_device *dev);
+extern	void deinit_hal_dm(struct net_device *dev);
+
+extern void hal_dm_watchdog(struct net_device *dev);
+
+
+extern	void	init_rate_adaptive(struct net_device *dev);
+extern	void	dm_txpower_trackingcallback(void *data);
+
+extern	void	dm_restore_dynamic_mechanism_state(struct net_device *dev);
+extern	void	dm_backup_dynamic_mechanism_state(struct net_device *dev);
+extern	void	dm_change_dynamic_initgain_thresh(struct net_device *dev,
+								u32		dm_type,
+								u32		dm_value);
+extern	void	DM_ChangeFsyncSetting(struct net_device *dev,
+												s32		DM_Type,
+												s32		DM_Value);
+extern	void dm_force_tx_fw_info(struct net_device *dev,
+										u32		force_type,
+										u32		force_value);
+extern	void	dm_init_edca_turbo(struct net_device *dev);
+extern	void	dm_rf_operation_test_callback(unsigned long data);
+extern	void	dm_rf_pathcheck_workitemcallback(void *data);
+extern	void dm_fsync_timer_callback(unsigned long data);
+#if 0
+extern	bool	dm_check_lbus_status(struct net_device *dev);
+#endif
+extern	void dm_check_fsync(struct net_device *dev);
+extern	void	dm_shadow_init(struct net_device *dev);
+extern	void dm_initialize_txpower_tracking(struct net_device *dev);
+
+#if (defined RTL8192E || defined RTL8192SE)
+extern  void    dm_CheckRfCtrlGPIO(void *data);
+#endif
+
+#ifdef RTL8192SE
+extern	void DM_TXPowerTracking92SDirectCall(struct net_device *dev);
+static	void dm_CtrlInitGainByTwoPort(struct net_device *dev);
+static	void dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(struct net_device *dev);
+static	void	dm_initial_gain_STABeforeConnect(struct net_device *dev);
+
+void	dm_InitRateAdaptiveMask(struct net_device *dev);
+#if 0
+static 	void Adhoc_dm_CheckRateAdaptive(struct net_device * dev);
+#endif
+void 		Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info  *pEntry);
+#endif
+
+/*--------------------Define export function prototype-----------------------*/
+
+
+/*---------------------Define local function prototype-----------------------*/
+static	void	dm_check_rate_adaptive(struct net_device *dev);
+
+static	void	dm_init_bandwidth_autoswitch(struct net_device *dev);
+static	void	dm_bandwidth_autoswitch(	struct net_device *dev);
+
+
+static	void	dm_check_txpower_tracking(struct net_device *dev);
+
+
+
+
+
+#if defined(RTL8192E)||defined(RTL8190P)
+static	void	dm_bb_initialgain_restore(struct net_device *dev);
+
+
+static	void	dm_bb_initialgain_backup(struct net_device *dev);
+#endif
+
+static	void dm_dig_init(struct net_device *dev);
+static	void dm_ctrl_initgain_byrssi(struct net_device *dev);
+static	void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev);
+static	void dm_ctrl_initgain_byrssi_by_driverrssi(	struct net_device *dev);
+static	void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev);
+static	void dm_initial_gain(struct net_device *dev);
+static	void dm_pd_th(struct net_device *dev);
+static	void dm_cs_ratio(struct net_device *dev);
+
+static	void dm_init_ctstoself(struct net_device *dev);
+static	void dm_Init_WA_Broadcom_IOT(struct net_device *dev);
+#ifdef RTL8192SE
+static	void dm_WA_Broadcom_IOT(struct net_device *dev);
+#endif
+
+static	void	dm_check_edca_turbo(struct net_device *dev);
+
+#if 0
+static	void	dm_check_rfctrl_gpio(struct net_device *dev);
+#endif
+
+#ifndef RTL8190P 
+#endif
+static	void dm_check_pbc_gpio(struct net_device *dev);
+
+
+static	void dm_check_rx_path_selection(struct net_device *dev);
+static 	void dm_init_rxpath_selection(struct net_device *dev);
+static	void dm_rxpath_sel_byrssi(struct net_device *dev);
+
+
+static void dm_init_fsync(struct net_device *dev);
+static void dm_deInit_fsync(struct net_device *dev);
+
+static	void dm_check_txrateandretrycount(struct net_device *dev);
+static  void dm_check_ac_dc_power(struct net_device *dev);
+
+/*---------------------Define local function prototype-----------------------*/
+
+static	void	dm_init_dynamic_txpower(struct net_device *dev);
+static	void	dm_dynamic_txpower(struct net_device *dev);
+
+
+static	void dm_send_rssi_tofw(struct net_device *dev);
+static	void	dm_ctstoself(struct net_device *dev);
+#if defined RTL8192SE
+static	void dm_RefreshRateAdaptiveMask(struct net_device *dev);
+#endif
+/*---------------------------Define function prototype------------------------*/
+
+extern	void
+init_hal_dm(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	priv->DM_Type = DM_Type_ByDriver;
+
+	priv->undecorated_smoothed_pwdb = -1;	
+	
+	dm_init_dynamic_txpower(dev);
+
+#ifdef RTL8192SE
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+		dm_InitRateAdaptiveMask(dev);
+	else
+#endif
+		init_rate_adaptive(dev);
+
+	dm_dig_init(dev);
+	dm_init_edca_turbo(dev);
+	dm_init_bandwidth_autoswitch(dev);
+	dm_init_fsync(dev);
+	dm_init_rxpath_selection(dev);
+	dm_init_ctstoself(dev);
+        if (IS_HARDWARE_TYPE_8192SE(dev))
+	dm_Init_WA_Broadcom_IOT(dev);
+		
+#if (defined RTL8192E || defined RTL8192SE)
+	INIT_DELAYED_WORK_RSL(&priv->gpio_change_rf_wq, (void *)dm_CheckRfCtrlGPIO,dev);
+#endif
+
+}	
+
+extern void deinit_hal_dm(struct net_device *dev)
+{
+
+	dm_deInit_fsync(dev);
+	
+}
+
+
+#ifdef USB_RX_AGGREGATION_SUPPORT
+void dm_CheckRxAggregation(struct net_device *dev) {
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	static unsigned long	lastTxOkCnt = 0;
+	static unsigned long	lastRxOkCnt = 0;
+	unsigned long		curTxOkCnt = 0;
+	unsigned long		curRxOkCnt = 0;
+
+	curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
+	curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
+
+	if((curTxOkCnt + curRxOkCnt) < 15000000) {
+		return;
+	}
+
+	if(curTxOkCnt > 4*curRxOkCnt) {
+		if (priv->bCurrentRxAggrEnable) {
+			write_nic_dword(dev, 0x1a8, 0);
+			priv->bCurrentRxAggrEnable = false;
+		}
+	}else{
+		if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) {
+			u32 ulValue;
+			ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
+				(pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
+			write_nic_dword(dev, 0x1a8, ulValue);
+			priv->bCurrentRxAggrEnable = true;
+		}
+	}
+
+	lastTxOkCnt = priv->stats.txbytesunicast;
+	lastRxOkCnt = priv->stats.rxbytesunicast;
+}	
+#endif	
+
+
+
+extern  void    hal_dm_watchdog(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	if(priv->being_init_adapter)
+		return;
+
+	dm_check_ac_dc_power(dev);
+
+	dm_check_pbc_gpio(dev);
+	dm_check_txrateandretrycount(dev);
+	dm_check_edca_turbo(dev);
+
+	if (IS_HARDWARE_TYPE_8192SE(dev)){
+#ifdef RTL8192SE
+		dm_RefreshRateAdaptiveMask(dev);
+		dm_WA_Broadcom_IOT(dev);
+		return;
+#if 0			
+		dm_check_txpower_tracking(dev);
+		dm_ctrl_initgain_byrssi(dev);	
+		dm_dynamic_txpower(dev);
+		dm_RefreshRateAdaptiveMask(dev);
+		dm_check_fsync(dev); 
+		if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+			Adhoc_dm_CheckRateAdaptive(dev);
+		else
+			dm_check_rate_adaptive(dev);
+#endif		
+#endif
+	}
+	dm_check_rate_adaptive(dev);
+	dm_dynamic_txpower(dev);	
+	dm_check_txpower_tracking(dev);
+
+	dm_ctrl_initgain_byrssi(dev);
+	dm_bandwidth_autoswitch(dev);
+
+	dm_check_rx_path_selection(dev);
+	dm_check_fsync(dev); 
+
+	dm_send_rssi_tofw(dev);
+	dm_ctstoself(dev);
+
+#ifdef USB_RX_AGGREGATION_SUPPORT
+	dm_CheckRxAggregation(dev);
+#endif	
+}	
+
+void dm_check_ac_dc_power(struct net_device *dev) 
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
+	char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
+	static char *envp[] = {"HOME=/", 
+			"TERM=linux", 
+			"PATH=/usr/bin:/bin", 
+			 NULL};
+
+	if(priv->ResetProgress == RESET_TYPE_SILENT)
+	{
+		RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+		return;
+	}
+
+	if(priv->rtllib->state != RTLLIB_LINKED) {
+		return;
+	}
+	call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
+
+	return;
+};
+
+
+extern void init_rate_adaptive(struct net_device * dev)	
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	prate_adaptive			pra = (prate_adaptive)&priv->rate_adaptive;
+	
+	pra->ratr_state = DM_RATR_STA_MAX;
+	pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
+	pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
+	pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
+
+	pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
+	pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
+	pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
+	
+	if(priv->CustomerID == RT_CID_819x_Netcore)
+		pra->ping_rssi_enable = 1;
+	else
+		pra->ping_rssi_enable = 0;				
+	pra->ping_rssi_thresh_for_ra = 15;
+	
+	
+	if (priv->rf_type == RF_2T4R)
+	{
+		pra->upper_rssi_threshold_ratr		= 	0x8f0f0000;
+		pra->middle_rssi_threshold_ratr		= 	0x8f0ff000;
+		pra->low_rssi_threshold_ratr		= 	0x8f0ff001;
+		pra->low_rssi_threshold_ratr_40M	= 	0x8f0ff005;
+		pra->low_rssi_threshold_ratr_20M	= 	0x8f0ff001;
+		pra->ping_rssi_ratr	= 	0x0000000d;
+	}
+	else if (priv->rf_type == RF_1T2R)
+	{
+		pra->upper_rssi_threshold_ratr		= 	0x000f0000;		
+		pra->middle_rssi_threshold_ratr		= 	0x000ff000;
+		pra->low_rssi_threshold_ratr		= 	0x000ff001;
+		pra->low_rssi_threshold_ratr_40M	= 	0x000ff005;
+		pra->low_rssi_threshold_ratr_20M	= 	0x000ff001;
+		pra->ping_rssi_ratr	= 	0x0000000d;
+	}
+	
+}	
+
+
+static void dm_check_rate_adaptive(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	prate_adaptive			pra = (prate_adaptive)&priv->rate_adaptive;
+	u32						currentRATR, targetRATR = 0;
+	u32						LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
+	bool						bshort_gi_enabled = false;
+	static u8					ping_rssi_state=0;
+
+	if(IS_NIC_DOWN(priv)){
+		RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
+		return;
+	}
+
+	if(pra->rate_adaptive_disabled)
+		return;
+
+	if( !(priv->rtllib->mode == WIRELESS_MODE_N_24G ||
+		 priv->rtllib->mode == WIRELESS_MODE_N_5G))
+		 return;
+		
+	if( priv->rtllib->state == RTLLIB_LINKED )
+	{
+
+		bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
+			(!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
+	
+
+		pra->upper_rssi_threshold_ratr =
+				(pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
+
+		pra->middle_rssi_threshold_ratr = 
+				(pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
+
+		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+		{
+			pra->low_rssi_threshold_ratr = 
+				(pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
+		}
+		else
+		{
+			pra->low_rssi_threshold_ratr = 
+			(pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
+		}
+		pra->ping_rssi_ratr = 
+				(pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
+		
+		if (pra->ratr_state == DM_RATR_STA_HIGH)
+		{
+			HighRSSIThreshForRA 	= pra->high2low_rssi_thresh_for_ra;
+			LowRSSIThreshForRA	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
+		}
+		else if (pra->ratr_state == DM_RATR_STA_LOW)
+		{
+			HighRSSIThreshForRA	= pra->high_rssi_thresh_for_ra;
+			LowRSSIThreshForRA 	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M);
+		}
+		else
+		{
+			HighRSSIThreshForRA	= pra->high_rssi_thresh_for_ra;
+			LowRSSIThreshForRA	= (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
+		}
+	
+		if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA)
+		{
+			pra->ratr_state = DM_RATR_STA_HIGH;
+			targetRATR = pra->upper_rssi_threshold_ratr;
+		}else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA)
+		{
+			pra->ratr_state = DM_RATR_STA_MIDDLE;
+			targetRATR = pra->middle_rssi_threshold_ratr;
+		}else
+		{
+			pra->ratr_state = DM_RATR_STA_LOW;
+			targetRATR = pra->low_rssi_threshold_ratr;
+		}
+
+		if(pra->ping_rssi_enable)
+		{
+			if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5))
+			{
+				if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
+					ping_rssi_state )
+				{
+					pra->ratr_state = DM_RATR_STA_LOW;
+					targetRATR = pra->ping_rssi_ratr;
+					ping_rssi_state = 1;
+				}
+			}
+			else
+			{
+				ping_rssi_state = 0;
+			}
+		}
+		
+#if 1		
+		if(priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev))
+			targetRATR &=  0xf00fffff;
+#endif
+
+		currentRATR = read_nic_dword(dev, RATR0);
+		if( targetRATR !=  currentRATR )
+		{
+			u32 ratr_value;
+			ratr_value = targetRATR;
+			RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);				
+			if(priv->rf_type == RF_1T2R)		
+			{
+				ratr_value &= ~(RATE_ALL_OFDM_2SS);
+			}
+			write_nic_dword(dev, RATR0, ratr_value);
+			write_nic_byte(dev, UFWP, 1);
+			
+			pra->last_ratr = targetRATR;
+		}
+		
+	}
+	else
+	{
+		pra->ratr_state = DM_RATR_STA_MAX;
+	}
+
+}	
+
+#ifdef RTL8192SE
+void dm_InitRateAdaptiveMask(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	prate_adaptive	pRA =  (prate_adaptive)&priv->rate_adaptive;
+
+	pRA->ratr_state = DM_RATR_STA_MAX;
+	pRA->PreRATRState = DM_RATR_STA_MAX;
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (priv->DM_Type == DM_Type_ByDriver && priv->pFirmware->FirmwareVersion >= 60)
+		priv->rtllib->bUseRAMask = true;
+	else
+#endif		
+		priv->rtllib->bUseRAMask = false;
+
+	printk("=========>%s: bUseRAMask=%d\n", __func__, priv->rtllib->bUseRAMask);
+	priv->bInformFWDriverControlDM = false;
+	
+}
+#endif
+
+static void dm_init_bandwidth_autoswitch(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
+	priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
+	priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
+	priv->rtllib->bandwidth_auto_switch.bautoswitch_enable = false;
+	
+}	
+
+
+static void dm_bandwidth_autoswitch(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->rtllib->bandwidth_auto_switch.bautoswitch_enable){
+		return;
+	}else{
+		if(priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz == false){
+			if(priv->undecorated_smoothed_pwdb <= priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
+				priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true;
+		}else{
+			if(priv->undecorated_smoothed_pwdb >= priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
+				priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
+	
+		}
+	}
+}	
+
+#ifdef Rtl8192SE
+u32	OFDMSwingTable[OFDM_Table_Length] = {
+	0x7f8001fe,	
+	0x788001e2,	
+	0x71c001c7,	
+	0x6b8001ae,	
+	0x65400195,	
+	0x5fc0017f,	
+	0x5a400169,	
+	0x55400155,	
+	0x50800142,	
+	0x4c000130,	
+	0x47c0011f,	
+	0x43c0010f,	
+	0x40000100,	
+	0x3c8000f2,	
+	0x390000e4,	
+	0x35c000d7,	
+	0x32c000cb,	
+	0x300000c0,	
+	0x2d4000b5,	
+	0x2ac000ab,	
+	0x288000a2,	
+	0x26000098,	
+	0x24000090,	
+	0x22000088,	
+	0x20000080,	
+	0x1e400079,	
+	0x1c800072,	
+	0x1b00006c,	
+	0x19800066,	
+	0x18000060,	
+	0x16c0005b,	
+	0x15800056,	
+	0x14400051,	
+	0x1300004c,	
+	0x12000048,	
+	0x11000044,	
+	0x10000040,	
+};
+
+u8	CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},	
+	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},	
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},	
+	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},	
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},	
+	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},	
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},	
+	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},	
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},	
+	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},	
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},	
+	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},	
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},	
+	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},	
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},	
+	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},	
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},	
+	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},	
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},	
+	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},	
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},	
+	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},	
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},	
+	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},	
+	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},	
+	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},	
+	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},	
+	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},	
+	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},	
+	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},	
+	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},	
+	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},	
+	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}	
+};
+
+
+u8	CCKSwingTable_Ch14[CCK_Table_length][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},	
+	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},	
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},	
+	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},	
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},	
+	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},	
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},	
+	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},	
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},	
+	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},	
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},	
+	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},	
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},	
+	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},	
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},	
+	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},	
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},	
+	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},	
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},	
+	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},	
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},	
+	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},	
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},	
+	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},	
+	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},	
+	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},	
+	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},	
+	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},	
+	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},	
+	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},	
+	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},	
+	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},	
+	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}	
+};
+#elif defined RTL8192E
+static u32 OFDMSwingTable[OFDM_Table_Length] = {
+	0x7f8001fe,	
+	0x71c001c7,	
+	0x65400195,	
+	0x5a400169,	
+	0x50800142,	
+	0x47c0011f,	
+	0x40000100,	
+	0x390000e4,	
+	0x32c000cb,	
+	0x2d4000b5,	
+	0x288000a2,	
+	0x24000090,	
+	0x20000080,	
+	0x1c800072,	
+	0x19800066,	
+	0x26c0005b,	
+	0x24400051,	
+	0x12000048,	
+	0x10000040	
+};
+static u8	CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},	
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},	
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},	
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},	
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},	
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},	
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},	
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},	
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},	
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},	
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},	
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}	
+};
+
+static u8	CCKSwingTable_Ch14[CCK_Table_length][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},	
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},	
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},	
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},	
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},	
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},	
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},	
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},	
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},	
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},	
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},	
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}	
+};
+#endif
+#define		Pw_Track_Flag				0x11d
+#define		Tssi_Mea_Value				0x13c
+#define		Tssi_Report_Value1			0x134
+#define		Tssi_Report_Value2			0x13e
+#define		FW_Busy_Flag				0x13f
+
+#ifndef RTL8192SE
+static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
+	{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool						bHighpowerstate, viviflag = false;
+	DCMD_TXCMD_T			tx_cmd;
+	u8					powerlevelOFDM24G;
+	int	    				i =0, j = 0, k = 0;
+	u8						RF_Type, tmp_report[5]={0, 0, 0, 0, 0};
+	u32						Value;
+	u8						Pwr_Flag;
+	u16					Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0;
+#ifdef RTL8192U
+	RT_STATUS 				rtStatus = RT_STATUS_SUCCESS;
+#endif
+	u32						delta=0;
+	RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
+	write_nic_byte(dev, Pw_Track_Flag, 0);
+	write_nic_byte(dev, FW_Busy_Flag, 0);
+	priv->rtllib->bdynamic_txpower_enable = false;
+	bHighpowerstate = priv->bDynamicTxHighPower;
+
+	powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); 
+	RF_Type = priv->rf_type;
+	Value = (RF_Type<<8) | powerlevelOFDM24G;
+
+	RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G);
+
+	
+#ifdef RTL8190P
+	for(j = 0; j<1; j++)	
+#else
+	for(j = 0; j<=30; j++)	
+#endif
+{	
+
+	tx_cmd.Op		= TXCMD_SET_TX_PWR_TRACKING;
+	tx_cmd.Length	= 4;
+	tx_cmd.Value		= Value;
+#ifdef RTL8192U
+	rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12);	
+	if (rtStatus == RT_STATUS_FAILURE)
+	{
+		RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n");
+	}
+#else
+	cmpk_message_handle_tx(dev, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
+#endif
+	mdelay(1);
+	for(i = 0;i <= 30; i++)
+	{
+		Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag);
+		
+		if (Pwr_Flag == 0)
+		{	
+			mdelay(1);
+
+			if(priv->bResetInProgress)	
+			{
+				RT_TRACE(COMP_POWER_TRACKING, "we are in slient reset progress, so return\n");		
+				write_nic_byte(dev, Pw_Track_Flag, 0);
+				write_nic_byte(dev, FW_Busy_Flag, 0);
+				return;
+			}
+#ifdef RTL8192E
+			if((priv->rtllib->eRFPowerState != eRfOn))
+			{
+				RT_TRACE(COMP_POWER_TRACKING, "we are in power save, so return\n");		
+				write_nic_byte(dev, Pw_Track_Flag, 0);
+				write_nic_byte(dev, FW_Busy_Flag, 0);
+				return;
+			}
+
+#endif
+			continue;
+		}
+
+		Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value);
+
+		if(Avg_TSSI_Meas == 0)
+		{
+			write_nic_byte(dev, Pw_Track_Flag, 0);
+			write_nic_byte(dev, FW_Busy_Flag, 0);
+			return;
+		}
+		
+		for(k = 0;k < 5; k++)
+		{
+			if(k !=4)
+				tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value1+k);
+			else
+				tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value2);
+
+			RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
+
+		        {
+			       if(tmp_report[k] <= 20)
+			       {	
+				      viviflag =true;
+				      break;
+			       }
+		        }
+		}
+
+		if(viviflag ==true)
+		{	
+			write_nic_byte(dev, Pw_Track_Flag, 0);
+			viviflag = false;
+			RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
+			for(k = 0;k < 5; k++)
+				tmp_report[k] = 0;
+			break;
+		}
+
+		for(k = 0;k < 5; k++)
+		{
+			Avg_TSSI_Meas_from_driver += tmp_report[k];
+		}
+
+		Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
+		RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver);
+		TSSI_13dBm = priv->TSSI_13dBm;
+		RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
+		
+		if(Avg_TSSI_Meas_from_driver > TSSI_13dBm)
+			delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
+		else
+			delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
+
+		if(delta <= E_FOR_TX_POWER_TRACK)
+		{
+			priv->rtllib->bdynamic_txpower_enable = true;
+			write_nic_byte(dev, Pw_Track_Flag, 0);
+			write_nic_byte(dev, FW_Busy_Flag, 0);
+			RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
+			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
+			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
+#ifdef RTL8190P					
+			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
+			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
+#endif
+			RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
+			RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
+			return;
+		}
+		else
+		{
+			if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
+			{
+				if (RF_Type == RF_2T4R)
+				{
+						
+						if((priv->rfa_txpowertrackingindex > 0) &&(priv->rfc_txpowertrackingindex > 0))
+				{
+					priv->rfa_txpowertrackingindex--;
+					if(priv->rfa_txpowertrackingindex_real > 4)
+					{
+						priv->rfa_txpowertrackingindex_real--;
+						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+					}
+
+					priv->rfc_txpowertrackingindex--;
+					if(priv->rfc_txpowertrackingindex_real > 4)
+					{
+						priv->rfc_txpowertrackingindex_real--;
+						rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+					}
+						}
+						else
+						{
+								rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+								rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+				}
+			}
+			else
+			{
+						{
+#ifdef RTL8190P
+								{
+						if(priv->rfc_txpowertrackingindex > 0)
+						{
+							priv->rfc_txpowertrackingindex--;
+							if(priv->rfc_txpowertrackingindex_real > 4)
+							{
+								priv->rfc_txpowertrackingindex_real--;
+								rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+							}
+						}
+						else
+							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);		
+				}
+#endif
+#ifdef RTL8192E
+								{
+									if(priv->rfa_txpowertrackingindex > 0)
+									{
+										priv->rfa_txpowertrackingindex--;
+										if(priv->rfa_txpowertrackingindex_real > 4)
+										{
+											priv->rfa_txpowertrackingindex_real--;
+											rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+										}
+									}
+									else
+											rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);							
+								}
+#endif
+						}
+
+				}
+			}
+			else
+			{
+				if (RF_Type == RF_2T4R)
+				{
+					if((priv->rfa_txpowertrackingindex < TxBBGainTableLength - 1) &&(priv->rfc_txpowertrackingindex < TxBBGainTableLength - 1))				
+				{
+					priv->rfa_txpowertrackingindex++;
+					priv->rfa_txpowertrackingindex_real++;					
+					rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+					priv->rfc_txpowertrackingindex++;
+					priv->rfc_txpowertrackingindex_real++;					
+					rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+				}
+					else
+					{
+						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+						rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+			}
+				}
+				else
+				{
+					{
+#ifdef RTL8190P
+							{
+					if(priv->rfc_txpowertrackingindex < (TxBBGainTableLength - 1))
+					{
+							priv->rfc_txpowertrackingindex++;
+							priv->rfc_txpowertrackingindex_real++;					
+							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+					}
+					else
+							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+				}
+#endif
+#ifdef RTL8192E
+							{
+								if(priv->rfa_txpowertrackingindex < (TxBBGainTableLength - 1))
+								{
+									priv->rfa_txpowertrackingindex++;
+									priv->rfa_txpowertrackingindex_real++;					
+									rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+			}
+								else
+									rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+							}
+#endif
+					}
+				}
+			}
+			if (RF_Type == RF_2T4R){
+			priv->CCKPresentAttentuation_difference
+				= priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
+			}else{
+				{
+#ifdef RTL8190P
+				priv->CCKPresentAttentuation_difference
+					= priv->rfc_txpowertrackingindex - priv->rfc_txpowertracking_default;
+#endif
+#ifdef RTL8192E
+						priv->CCKPresentAttentuation_difference
+							= priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default;
+#endif
+				}
+			}
+
+			if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)	
+				priv->CCKPresentAttentuation 
+				= priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference;
+			else
+				priv->CCKPresentAttentuation 
+				= priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference;
+
+			if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
+					priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
+			if(priv->CCKPresentAttentuation < 0)
+					priv->CCKPresentAttentuation = 0;
+
+			if(priv->CCKPresentAttentuation > -1&&priv->CCKPresentAttentuation < CCKTxBBGainTableLength)
+			{
+				if(priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14)
+				{
+					priv->bcck_in_ch14 = true;
+					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				}
+				else if(priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14)
+				{
+					priv->bcck_in_ch14 = false;
+					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				}
+				else
+					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);		
+			}
+		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
+		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
+#ifdef RTL8190P
+		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
+		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
+#endif
+		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
+		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
+
+		if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24)
+		{
+			priv->rtllib->bdynamic_txpower_enable = true;
+			write_nic_byte(dev, Pw_Track_Flag, 0);
+			write_nic_byte(dev, FW_Busy_Flag, 0);
+			RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
+			return;
+		}
+
+		
+	}
+		write_nic_byte(dev, Pw_Track_Flag, 0);
+		Avg_TSSI_Meas_from_driver = 0;
+		for(k = 0;k < 5; k++)
+			tmp_report[k] = 0;
+		break;
+	}
+	write_nic_byte(dev, FW_Busy_Flag, 0);
+}	
+		priv->rtllib->bdynamic_txpower_enable = true;
+		write_nic_byte(dev, Pw_Track_Flag, 0);
+}
+#endif
+
+#ifdef RTL8192E
+static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
+{
+#define ThermalMeterVal	9
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 tmpRegA, TempCCk;
+	u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
+	int i =0, CCKSwingNeedUpdate=0;
+
+	if(!priv->btxpower_trackingInit)
+	{
+		tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
+		for(i=0; i<OFDM_Table_Length; i++)	
+		{
+			if(tmpRegA == OFDMSwingTable[i])
+			{
+				priv->OFDM_index= (u8)i;
+				RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n", 
+					rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index);
+			}
+		}
+
+		TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+		for(i=0 ; i<CCK_Table_length ; i++)
+		{
+			if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0])
+			{
+				priv->CCK_index =(u8) i;
+				RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n", 
+					rCCK0_TxFilter1, TempCCk, priv->CCK_index);
+		break;
+	}
+}	
+		priv->btxpower_trackingInit = true;
+		return;
+	}
+
+#if 0
+{
+	UINT32	curr_addr;
+	UINT32	reg_value;
+	
+		for (curr_addr = 0; curr_addr < 0x2d; curr_addr++)	
+		{			  
+			reg_value = PHY_QueryRFReg(	dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+										curr_addr, bMaskDWord);
+		}
+
+	pHalData->TXPowercount = 0;
+	return;
+}
+#endif
+
+	tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);	
+	RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA);
+	if(tmpRegA < 3 || tmpRegA > 13)
+		return;
+	if(tmpRegA >= 12)	
+		tmpRegA = 12;
+	RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA);
+	priv->ThermalMeter[0] = ThermalMeterVal;	
+	priv->ThermalMeter[1] = ThermalMeterVal;	
+
+	if(priv->ThermalMeter[0] >= (u8)tmpRegA)	
+	{
+		tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
+		tmpCCK40Mindex = tmpCCK20Mindex - 6;
+		if(tmpOFDMindex >= OFDM_Table_Length)
+			tmpOFDMindex = OFDM_Table_Length-1;
+		if(tmpCCK20Mindex >= CCK_Table_length)
+			tmpCCK20Mindex = CCK_Table_length-1;
+		if(tmpCCK40Mindex >= CCK_Table_length)
+			tmpCCK40Mindex = CCK_Table_length-1;
+	}
+	else
+	{		
+		tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
+		if(tmpval >= 6)								
+			tmpOFDMindex = tmpCCK20Mindex = 0;		
+		else
+			tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
+		tmpCCK40Mindex = 0;
+	}
+	if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)	
+		tmpCCKindex = tmpCCK40Mindex;
+	else
+		tmpCCKindex = tmpCCK20Mindex;
+
+	priv->Record_CCK_20Mindex = tmpCCK20Mindex;
+	priv->Record_CCK_40Mindex = tmpCCK40Mindex;
+	RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n", 
+		priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
+
+	if(priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14)
+	{
+		priv->bcck_in_ch14 = true;
+		CCKSwingNeedUpdate = 1;
+	}
+	else if(priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14)
+	{
+		priv->bcck_in_ch14 = false;
+		CCKSwingNeedUpdate = 1;
+	}
+
+	if(priv->CCK_index != tmpCCKindex)
+{
+		priv->CCK_index = tmpCCKindex; 
+		CCKSwingNeedUpdate = 1;
+	}
+
+	if(CCKSwingNeedUpdate)
+	{
+		dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+	}
+	if(priv->OFDM_index != tmpOFDMindex)
+	{
+		priv->OFDM_index = tmpOFDMindex;
+		rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);		
+		RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", 
+			priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
+	}
+	priv->txpower_count = 0;
+}
+#elif defined (RTL8192SE)
+static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+        u8 	ThermalValue=0;
+	u32	FwCmdVal=0;
+
+	priv->btxpower_trackingInit = true;
+
+	
+	ThermalValue = (u8)rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, RF_T_METER, 0x1f);	
+	RT_TRACE(COMP_POWER_TRACKING, "Readback Thermal Meter = 0x%x\n", ThermalValue);
+	printk("%s()Readback Thermal Meter = 0x%x\n", __func__,ThermalValue);
+	if(ThermalValue)
+	{
+		priv->ThermalValue = ThermalValue;
+		if(priv->pFirmware->FirmwareVersion >= 0x35)
+		{
+			priv->rtllib->SetFwCmdHandler(dev, FW_CMD_TXPWR_TRACK_THERMAL);	
+		}
+		else
+		{
+		FwCmdVal = (FW_TXPWR_TRACK_THERMAL|
+		(priv->ThermalMeter[0]<<8)|(ThermalValue<<16));
+		RT_TRACE(COMP_POWER_TRACKING, "Write to FW Thermal Val = 0x%x\n", FwCmdVal);
+		write_nic_dword(dev, WFM5, FwCmdVal); 
+				ChkFwCmdIoDone(dev);
+		}
+	}
+
+	priv->txpower_count = 0;
+}
+#endif
+
+void	dm_txpower_trackingcallback(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,txpower_tracking_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else	   
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+	
+#ifdef RTL8190P
+	dm_TXPowerTrackingCallback_TSSI(dev);
+#elif defined(RTL8192E)
+	if(priv->IC_Cut >= IC_VersionCut_D)
+		dm_TXPowerTrackingCallback_TSSI(dev);
+	else
+		dm_TXPowerTrackingCallback_ThermalMeter(dev);
+#elif defined(RTL8192SE)
+	dm_TXPowerTrackingCallback_ThermalMeter(dev);
+#endif
+}
+
+#ifndef RTL8192SE
+static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->txbbgain_table[0].txbb_iq_amplifygain = 	 		12;
+	priv->txbbgain_table[0].txbbgain_value=0x7f8001fe;
+	priv->txbbgain_table[1].txbb_iq_amplifygain = 	 		11;
+	priv->txbbgain_table[1].txbbgain_value=0x788001e2;
+	priv->txbbgain_table[2].txbb_iq_amplifygain = 	 		10;
+	priv->txbbgain_table[2].txbbgain_value=0x71c001c7;
+	priv->txbbgain_table[3].txbb_iq_amplifygain = 	 		9;
+	priv->txbbgain_table[3].txbbgain_value=0x6b8001ae;
+	priv->txbbgain_table[4].txbb_iq_amplifygain = 		       8;
+	priv->txbbgain_table[4].txbbgain_value=0x65400195;
+	priv->txbbgain_table[5].txbb_iq_amplifygain = 		       7;
+	priv->txbbgain_table[5].txbbgain_value=0x5fc0017f;
+	priv->txbbgain_table[6].txbb_iq_amplifygain = 		       6;
+	priv->txbbgain_table[6].txbbgain_value=0x5a400169;
+	priv->txbbgain_table[7].txbb_iq_amplifygain = 		       5;
+	priv->txbbgain_table[7].txbbgain_value=0x55400155;
+	priv->txbbgain_table[8].txbb_iq_amplifygain = 		       4;
+	priv->txbbgain_table[8].txbbgain_value=0x50800142;
+	priv->txbbgain_table[9].txbb_iq_amplifygain = 		       3;
+	priv->txbbgain_table[9].txbbgain_value=0x4c000130;
+	priv->txbbgain_table[10].txbb_iq_amplifygain = 		       2;
+	priv->txbbgain_table[10].txbbgain_value=0x47c0011f;
+	priv->txbbgain_table[11].txbb_iq_amplifygain = 		       1;
+	priv->txbbgain_table[11].txbbgain_value=0x43c0010f;
+	priv->txbbgain_table[12].txbb_iq_amplifygain = 		       0;
+	priv->txbbgain_table[12].txbbgain_value=0x40000100;
+	priv->txbbgain_table[13].txbb_iq_amplifygain = 		       -1;
+	priv->txbbgain_table[13].txbbgain_value=0x3c8000f2;
+	priv->txbbgain_table[14].txbb_iq_amplifygain = 		     -2;
+	priv->txbbgain_table[14].txbbgain_value=0x390000e4;
+	priv->txbbgain_table[15].txbb_iq_amplifygain = 		     -3;
+	priv->txbbgain_table[15].txbbgain_value=0x35c000d7;
+	priv->txbbgain_table[16].txbb_iq_amplifygain = 		     -4;
+	priv->txbbgain_table[16].txbbgain_value=0x32c000cb;
+	priv->txbbgain_table[17].txbb_iq_amplifygain = 		     -5;
+	priv->txbbgain_table[17].txbbgain_value=0x300000c0;
+	priv->txbbgain_table[18].txbb_iq_amplifygain = 		 	    -6;
+	priv->txbbgain_table[18].txbbgain_value=0x2d4000b5;
+	priv->txbbgain_table[19].txbb_iq_amplifygain = 		     -7;
+	priv->txbbgain_table[19].txbbgain_value=0x2ac000ab;
+	priv->txbbgain_table[20].txbb_iq_amplifygain = 		     -8;
+	priv->txbbgain_table[20].txbbgain_value=0x288000a2;
+	priv->txbbgain_table[21].txbb_iq_amplifygain = 		     -9;
+	priv->txbbgain_table[21].txbbgain_value=0x26000098;
+	priv->txbbgain_table[22].txbb_iq_amplifygain = 		     -10;
+	priv->txbbgain_table[22].txbbgain_value=0x24000090;
+	priv->txbbgain_table[23].txbb_iq_amplifygain = 		     -11;
+	priv->txbbgain_table[23].txbbgain_value=0x22000088;
+	priv->txbbgain_table[24].txbb_iq_amplifygain = 		     -12;
+	priv->txbbgain_table[24].txbbgain_value=0x20000080;
+	priv->txbbgain_table[25].txbb_iq_amplifygain = 		     -13;
+	priv->txbbgain_table[25].txbbgain_value=0x1a00006c;
+	priv->txbbgain_table[26].txbb_iq_amplifygain = 		     -14;
+	priv->txbbgain_table[26].txbbgain_value=0x1c800072;
+	priv->txbbgain_table[27].txbb_iq_amplifygain = 		     -15;
+	priv->txbbgain_table[27].txbbgain_value=0x18000060;
+	priv->txbbgain_table[28].txbb_iq_amplifygain = 		     -16;
+	priv->txbbgain_table[28].txbbgain_value=0x19800066;
+	priv->txbbgain_table[29].txbb_iq_amplifygain = 		     -17;
+	priv->txbbgain_table[29].txbbgain_value=0x15800056;
+	priv->txbbgain_table[30].txbb_iq_amplifygain = 		     -18;
+	priv->txbbgain_table[30].txbbgain_value=0x26c0005b;
+	priv->txbbgain_table[31].txbb_iq_amplifygain = 		     -19;
+	priv->txbbgain_table[31].txbbgain_value=0x14400051;
+	priv->txbbgain_table[32].txbb_iq_amplifygain = 		     -20;
+	priv->txbbgain_table[32].txbbgain_value=0x24400051;
+	priv->txbbgain_table[33].txbb_iq_amplifygain = 		     -21;
+	priv->txbbgain_table[33].txbbgain_value=0x1300004c;
+	priv->txbbgain_table[34].txbb_iq_amplifygain = 		     -22;
+	priv->txbbgain_table[34].txbbgain_value=0x12000048;
+	priv->txbbgain_table[35].txbb_iq_amplifygain = 		     -23;
+	priv->txbbgain_table[35].txbbgain_value=0x11000044;
+	priv->txbbgain_table[36].txbb_iq_amplifygain = 		     -24;
+	priv->txbbgain_table[36].txbbgain_value=0x10000040;
+
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09;
+	priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04;
+
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08;
+	priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04;
+	
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08;
+	priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03;
+
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08;
+	priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03;
+	
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07;
+	priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03;
+
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07;
+	priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03;
+	
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06;
+	priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03;
+
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06;
+	priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03;
+	
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06;
+	priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05;
+	priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02;
+	
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05;
+	priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05;
+	priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04;
+	priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04;
+	priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04;
+	priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04;
+	priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04;
+	priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01;
+
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02;
+
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01;
+
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01;
+
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01;
+
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01;
+
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03;
+	priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01;
+	
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00;
+
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00;
+	
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00;
+	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00;
+
+	priv->btxpower_tracking = true;
+	priv->txpower_count       = 0;
+	priv->btxpower_trackingInit = false;
+
+}
+#endif
+#ifndef RTL8190P
+static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+#ifdef RTL8192SE
+		priv->btxpower_tracking = false;
+		priv->txpower_count       = 0;
+		priv->btxpower_trackingInit = false;
+#else
+
+	if(priv->rtllib->FwRWRF)
+		priv->btxpower_tracking = true;
+	else
+		priv->btxpower_tracking = false;
+	priv->txpower_count       = 0;
+	priv->btxpower_trackingInit = false;
+#endif
+	RT_TRACE(COMP_POWER_TRACKING, "pMgntInfo->bTXPowerTracking = %d\n", priv->btxpower_tracking);
+}
+#endif
+
+void dm_initialize_txpower_tracking(struct net_device *dev)
+{
+#ifdef RTL8192E
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+#ifdef RTL8190P
+	dm_InitializeTXPowerTracking_TSSI(dev);
+#elif defined RTL8192E
+	if(priv->IC_Cut >= IC_VersionCut_D)
+		dm_InitializeTXPowerTracking_TSSI(dev);
+	else
+		dm_InitializeTXPowerTracking_ThermalMeter(dev);
+#elif defined RTL8192SE
+	dm_InitializeTXPowerTracking_ThermalMeter(dev);
+#endif
+}	
+
+#if (defined RTL8192E || defined RTL8190P)
+static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u32 tx_power_track_counter = 0;
+	RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
+	if(read_nic_byte(dev, 0x11e) ==1)
+		return;
+	if(!priv->btxpower_tracking)
+		return;
+	tx_power_track_counter++;
+	
+	
+	 if(tx_power_track_counter >= 180)	
+	 	{
+		queue_delayed_work_rsl(priv->priv_wq,&priv->txpower_tracking_wq,0);
+		tx_power_track_counter =0;
+	 	}
+	
+}	
+#endif
+#ifndef RTL8190P
+static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u8 	TM_Trigger=0;
+	u8		TxPowerCheckCnt = 0;
+
+	if(IS_HARDWARE_TYPE_8192SE(dev))
+		TxPowerCheckCnt = 5;	
+	else
+		TxPowerCheckCnt = 2;	
+        if(!priv->btxpower_tracking){
+            return;
+        } else {
+            if(priv->txpower_count  <= TxPowerCheckCnt) {
+			priv->txpower_count++;
+			return;
+		}
+	}	
+
+	if(!TM_Trigger)
+	{
+#ifdef RTL8192SE
+		if(IS_HARDWARE_TYPE_8192SE(dev))
+		{
+                    rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
+                    RT_TRACE(COMP_POWER_TRACKING, "Trigger 92S Thermal Meter!!\n");
+                }
+                else
+#endif
+                {
+		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+                }
+		TM_Trigger = 1;
+		return;
+	} else {
+            printk("===============>Schedule TxPowerTrackingWorkItem\n");
+#ifdef RTL8192SE
+		DM_TXPowerTracking92SDirectCall(dev); 
+#else
+
+		queue_delayed_work_rsl(priv->priv_wq,&priv->txpower_tracking_wq,0);
+#endif
+		TM_Trigger = 0;
+		}
+
+	}	
+#endif
+
+#ifdef RTL8192SE
+void DM_TXPowerTracking92SDirectCall(struct net_device *dev)
+{	
+	dm_TXPowerTrackingCallback_ThermalMeter(dev);
+	}	
+#endif
+
+static void dm_check_txpower_tracking(struct net_device *dev)
+{
+#ifdef RTL8192E
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif	
+#ifdef  RTL8190P
+	dm_CheckTXPowerTracking_TSSI(dev);
+#elif defined RTL8192E
+	if(priv->IC_Cut >= IC_VersionCut_D)
+		dm_CheckTXPowerTracking_TSSI(dev);
+	else
+		dm_CheckTXPowerTracking_ThermalMeter(dev);
+#elif defined RTL8192SE
+	dm_CheckTXPowerTracking_ThermalMeter(dev);
+#endif
+	
+}	
+
+#ifndef RTL8192SE
+static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
+{
+	u32 TempVal;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	TempVal = 0;
+	if(!bInCH14){
+		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
+					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
+	
+		rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
+		TempVal = 0;
+		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
+					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
+					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
+					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
+		rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
+		TempVal = 0;
+		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
+					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
+		
+		rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
+	}
+	else
+	{
+		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
+					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
+	
+		rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
+		TempVal = 0;
+		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
+					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
+					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
+					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
+		rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
+		TempVal = 0;
+		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
+					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
+		
+		rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
+	}
+		
+	
+}
+#endif
+#ifdef RTL8192E
+static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH14)
+{
+	u32 TempVal;
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	TempVal = 0;
+	if(!bInCH14)
+	{
+		TempVal = 	CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
+					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
+		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_TxFilter1, TempVal);
+		TempVal = 0;
+		TempVal = 	CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
+					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
+					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+
+					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
+		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_TxFilter2, TempVal);
+		TempVal = 0;
+		TempVal = 	CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
+					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ;
+		
+		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_DebugPort, TempVal);
+	}
+	else
+	{
+		TempVal = 	CCKSwingTable_Ch14[priv->CCK_index][0] +
+					(CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
+
+		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_TxFilter1, TempVal);
+		TempVal = 0;
+		TempVal = 	CCKSwingTable_Ch14[priv->CCK_index][2] +
+					(CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
+					(CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+
+					(CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
+		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_TxFilter2, TempVal);
+		TempVal = 0;
+		TempVal = 	CCKSwingTable_Ch14[priv->CCK_index][6] +
+					(CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ;
+
+		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+		RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n", 
+			rCCK0_DebugPort, TempVal);
+	}
+	}
+#endif
+	
+#ifndef RTL8192SE
+extern void dm_cck_txpower_adjust(
+	struct net_device *dev,
+	bool  binch14
+)
+{	
+#ifndef RTL8190P
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+#ifdef RTL8190P
+	dm_CCKTxPowerAdjust_TSSI(dev, binch14);
+#else
+	if(priv->IC_Cut >= IC_VersionCut_D)
+		dm_CCKTxPowerAdjust_TSSI(dev, binch14);
+	else
+		dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
+#endif
+}
+#endif
+
+
+#if defined(RTL8192E)||defined(RTL8190P)
+static void dm_txpower_reset_recovery(
+	struct net_device *dev
+)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
+	rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->CCKPresentAttentuation);
+	dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);		
+
+	rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex);
+	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain);
+
+}	
+
+extern void dm_restore_dynamic_mechanism_state(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 	reg_ratr = priv->rate_adaptive.last_ratr;
+
+	if(IS_NIC_DOWN(priv)){
+		RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
+		return;
+	}
+
+	if(priv->rate_adaptive.rate_adaptive_disabled)
+		return;
+	if( !(priv->rtllib->mode==WIRELESS_MODE_N_24G ||
+		 priv->rtllib->mode==WIRELESS_MODE_N_5G))
+		 return;
+	{
+			u32 ratr_value;
+			ratr_value = reg_ratr;
+			if(priv->rf_type == RF_1T2R)	
+			{
+				ratr_value &=~ (RATE_ALL_OFDM_2SS);
+			}
+			write_nic_dword(dev, RATR0, ratr_value);
+			write_nic_byte(dev, UFWP, 1);
+#if 0		
+			u1Byte index;
+			u4Byte input_value;
+			index = (u1Byte)((((pu4Byte)(val))[0]) >> 28);
+			input_value = (((pu4Byte)(val))[0]) & 0x0fffffff;
+			PlatformEFIOWrite4Byte(dev, RATR0+index*4, input_value);
+#endif		
+	}
+	if(priv->btxpower_trackingInit && priv->btxpower_tracking){
+		dm_txpower_reset_recovery(dev);	
+	}
+
+	dm_bb_initialgain_restore(dev);
+	
+}	
+
+static void dm_bb_initialgain_restore(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 bit_mask = 0x7f; 
+	
+	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+		return;
+
+	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	
+	rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1);
+	rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1);
+	rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1);
+	rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1);
+	bit_mask  = bMaskByte2;
+	rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca);
+
+	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
+	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
+	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
+	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
+	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca);
+	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	
+	
+}	
+
+
+extern void dm_backup_dynamic_mechanism_state(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	priv->bswitch_fsync  = false;	
+	priv->bfsync_processing = false;
+	dm_bb_initialgain_backup(dev);
+	
+}	
+
+
+static void dm_bb_initialgain_backup(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 bit_mask = bMaskByte0; 
+
+	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+		return;
+
+	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	
+	priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
+	priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
+	priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
+	priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
+	bit_mask  = bMaskByte2;
+	priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
+
+	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
+	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
+	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
+	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
+	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca);
+
+}   
+
+#endif
+extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+								u32		dm_type,
+								u32		dm_value)
+{
+#ifdef RTL8192SE
+	struct r8192_priv *priv = rtllib_priv(dev);
+	if(dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
+		priv->MidHighPwrTHR_L2 = (u8)dm_value;
+	else if(dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW)
+		priv->MidHighPwrTHR_L1 = (u8)dm_value;
+	return;
+#endif
+	if (dm_type == DIG_TYPE_THRESH_HIGH)
+	{
+		dm_digtable.rssi_high_thresh = dm_value;		
+	}
+	else if (dm_type == DIG_TYPE_THRESH_LOW)
+	{
+		dm_digtable.rssi_low_thresh = dm_value;
+	}
+	else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
+	{
+		dm_digtable.rssi_high_power_highthresh = dm_value;
+	}
+	else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
+	{
+		dm_digtable.rssi_high_power_highthresh = dm_value;
+	}
+	else if (dm_type == DIG_TYPE_ENABLE)
+	{
+		dm_digtable.dig_state		= DM_STA_DIG_MAX;
+		dm_digtable.dig_enable_flag	= true;
+	}
+	else if (dm_type == DIG_TYPE_DISABLE)
+	{
+		dm_digtable.dig_state		= DM_STA_DIG_MAX;
+		dm_digtable.dig_enable_flag	= false;
+	}
+	else if (dm_type == DIG_TYPE_DBG_MODE)
+	{
+		if(dm_value >= DM_DBG_MAX)
+			dm_value = DM_DBG_OFF;
+		dm_digtable.dbg_mode		= (u8)dm_value;
+	}
+	else if (dm_type == DIG_TYPE_RSSI)
+	{
+		if(dm_value > 100)
+			dm_value = 30;
+		dm_digtable.rssi_val			= (long)dm_value;
+	}
+	else if (dm_type == DIG_TYPE_ALGORITHM)
+	{
+		if (dm_value >= DIG_ALGO_MAX)
+			dm_value = DIG_ALGO_BY_FALSE_ALARM;
+		if(dm_digtable.dig_algorithm != (u8)dm_value)
+			dm_digtable.dig_algorithm_switch = 1;
+		dm_digtable.dig_algorithm	= (u8)dm_value;
+	}
+	else if (dm_type == DIG_TYPE_BACKOFF)
+	{
+		if(dm_value > 30)
+			dm_value = 30;
+		dm_digtable.backoff_val		= (u8)dm_value;
+	}
+	else if(dm_type == DIG_TYPE_RX_GAIN_MIN)
+	{
+		if(dm_value == 0)
+			dm_value = 0x1;
+		dm_digtable.rx_gain_range_min = (u8)dm_value;
+	}
+	else if(dm_type == DIG_TYPE_RX_GAIN_MAX)
+	{
+		if(dm_value > 0x50)
+			dm_value = 0x50;
+		dm_digtable.rx_gain_range_max = (u8)dm_value;
+	}
+}	
+extern	void	
+dm_change_fsync_setting(
+	struct net_device *dev,
+	s32		DM_Type,
+	s32		DM_Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if (DM_Type == 0)	
+	{
+		if(DM_Value > 1)
+			DM_Value = 1;
+		priv->framesyncMonitor = (u8)DM_Value;
+	}
+}
+
+extern void	
+dm_change_rxpath_selection_setting(	
+	struct net_device *dev,
+	s32		DM_Type,
+	s32		DM_Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	prate_adaptive 	pRA = (prate_adaptive)&(priv->rate_adaptive);
+
+
+	if(DM_Type == 0)	
+	{
+		if(DM_Value > 1)
+			DM_Value = 1;
+		DM_RxPathSelTable.Enable = (u8)DM_Value;
+	}
+	else if(DM_Type == 1)
+	{
+		if(DM_Value > 1)
+			DM_Value = 1;
+		DM_RxPathSelTable.DbgMode = (u8)DM_Value;
+	}
+	else if(DM_Type == 2)
+	{
+		if(DM_Value > 40)
+			DM_Value = 40;
+		DM_RxPathSelTable.SS_TH_low = (u8)DM_Value;
+	}
+	else if(DM_Type == 3)
+	{
+		if(DM_Value > 25)
+			DM_Value = 25;
+		DM_RxPathSelTable.diff_TH = (u8)DM_Value;
+	}
+	else if(DM_Type == 4)
+	{
+		if(DM_Value >= CCK_Rx_Version_MAX)
+			DM_Value = CCK_Rx_Version_1;
+		DM_RxPathSelTable.cck_method= (u8)DM_Value;
+	}
+	else if(DM_Type == 10)
+	{
+		if(DM_Value > 100)
+			DM_Value = 50;
+		DM_RxPathSelTable.rf_rssi[0] = (u8)DM_Value;
+	}
+	else if(DM_Type == 11)
+	{
+		if(DM_Value > 100)
+			DM_Value = 50;
+		DM_RxPathSelTable.rf_rssi[1] = (u8)DM_Value;
+	}
+	else if(DM_Type == 12)
+	{
+		if(DM_Value > 100)
+			DM_Value = 50;
+		DM_RxPathSelTable.rf_rssi[2] = (u8)DM_Value;
+	}
+	else if(DM_Type == 13)
+	{
+		if(DM_Value > 100)
+			DM_Value = 50;
+		DM_RxPathSelTable.rf_rssi[3] = (u8)DM_Value;
+	}
+	else if(DM_Type == 20)
+	{
+		if(DM_Value > 1)
+			DM_Value = 1;
+		pRA->ping_rssi_enable = (u8)DM_Value;
+	}
+	else if(DM_Type == 21)
+	{
+		if(DM_Value > 30)
+			DM_Value = 30;
+		pRA->ping_rssi_thresh_for_ra = DM_Value;
+	}
+}
+
+#if 0
+extern void dm_force_tx_fw_info(struct net_device *dev,
+										u32		force_type,
+										u32		force_value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if (force_type == 0)	
+	{
+		priv->tx_fwinfo_force_subcarriermode = 0;
+	}
+	else if(force_type == 1) 
+	{
+		priv->tx_fwinfo_force_subcarriermode = 1;
+		if(force_value > 3)
+			force_value = 3;
+		priv->tx_fwinfo_force_subcarrierval = (u8)force_value;
+	}
+}
+#endif
+
+static void dm_dig_init(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	dm_digtable.dig_enable_flag	= true;
+	dm_digtable.Backoff_Enable_Flag = true;
+
+#ifdef RTL8192SE
+	if((priv->DM_Type  == DM_Type_ByDriver) && (priv->pFirmware->FirmwareVersion >= 0x3c))
+		dm_digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT;
+	else
+		dm_digtable.dig_algorithm = DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
+#else	
+	dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
+#endif
+
+	dm_digtable.Dig_TwoPort_Algorithm = DIG_TWO_PORT_ALGO_RSSI;
+	dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX;
+	dm_digtable.dbg_mode = DM_DBG_OFF;	
+	dm_digtable.dig_algorithm_switch = 0;
+	
+	dm_digtable.dig_state		= DM_STA_DIG_MAX;
+	dm_digtable.dig_highpwr_state	= DM_STA_DIG_MAX;
+	dm_digtable.CurSTAConnectState = dm_digtable.PreSTAConnectState = DIG_STA_DISCONNECT;
+	dm_digtable.CurAPConnectState = dm_digtable.PreAPConnectState = DIG_AP_DISCONNECT;
+	dm_digtable.initialgain_lowerbound_state = false;
+
+	dm_digtable.rssi_low_thresh 	= DM_DIG_THRESH_LOW;
+	dm_digtable.rssi_high_thresh 	= DM_DIG_THRESH_HIGH;
+
+	dm_digtable.FALowThresh	= DM_FALSEALARM_THRESH_LOW;
+	dm_digtable.FAHighThresh	= DM_FALSEALARM_THRESH_HIGH;
+	
+	dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
+	dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
+	
+	dm_digtable.rssi_val = 50;	
+	dm_digtable.backoff_val = DM_DIG_BACKOFF;
+	dm_digtable.rx_gain_range_max = DM_DIG_MAX;
+	if(priv->CustomerID == RT_CID_819x_Netcore)
+		dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;	
+	else
+		dm_digtable.rx_gain_range_min = DM_DIG_MIN;
+	
+	dm_digtable.BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
+	dm_digtable.BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
+}	
+
+void dm_FalseAlarmCounterStatistics(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 ret_value;
+	PFALSE_ALARM_STATISTICS FalseAlmCnt = &(priv->FalseAlmCnt);
+	
+	ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter1, bMaskDWord);
+        FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);	
+
+        ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter2, bMaskDWord);
+	FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
+	FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
+	ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter3, bMaskDWord);
+	FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
+
+	FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal +
+							  FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail;
+
+	ret_value = rtl8192_QueryBBReg(dev, 0xc64, bMaskDWord);	
+	FalseAlmCnt->Cnt_Cck_fail = (ret_value&0xffff);
+	FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Parity_Fail +
+						FalseAlmCnt->Cnt_Rate_Illegal +
+						FalseAlmCnt->Cnt_Crc8_fail +
+						FalseAlmCnt->Cnt_Mcs_fail +
+						FalseAlmCnt->Cnt_Cck_fail);	
+
+	RT_TRACE(COMP_DIG, "Cnt_Ofdm_fail = %d, Cnt_Cck_fail = %d, Cnt_all = %d\n", 
+				FalseAlmCnt->Cnt_Ofdm_fail, FalseAlmCnt->Cnt_Cck_fail , FalseAlmCnt->Cnt_all);		
+}
+
+#ifdef RTL8192SE
+static void dm_CtrlInitGainAPByFalseAlarm(struct net_device *dev)
+{
+	static u8		binitialized = false;
+
+	{
+		binitialized = false;
+		dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX;
+		return;
+	}	
+}
+#endif
+
+static void dm_ctrl_initgain_byrssi(struct net_device *dev)
+{
+	
+	if (dm_digtable.dig_enable_flag == false)
+		return;
+
+	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
+		dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev);
+	else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+		dm_ctrl_initgain_byrssi_by_driverrssi(dev);
+#ifdef RTL8192SE
+	else if(dm_digtable.dig_algorithm == DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM)
+		dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(dev);
+	else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_TOW_PORT)
+		dm_CtrlInitGainByTwoPort(dev);
+#endif
+	else
+		return;
+}
+
+#ifdef RTL8192SE
+static void dm_CtrlInitGainByTwoPort(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(rtllib_act_scanning(priv->rtllib,true) == true)
+		return;
+
+	if((priv->rtllib->state > RTLLIB_NOLINK) && (priv->rtllib->state < RTLLIB_LINKED))
+		dm_digtable.CurSTAConnectState = DIG_STA_BEFORE_CONNECT;
+	else if((priv->rtllib->state == RTLLIB_LINKED) ||(priv->rtllib->state == RTLLIB_LINKED_SCANNING))
+		dm_digtable.CurSTAConnectState = DIG_STA_CONNECT;
+	else
+		dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT;
+
+	dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;	
+	
+	if(dm_digtable.CurSTAConnectState != DIG_STA_DISCONNECT)
+	{	
+		if(dm_digtable.Dig_TwoPort_Algorithm == DIG_TWO_PORT_ALGO_FALSE_ALARM)
+		{
+			dm_digtable.Dig_TwoPort_Algorithm = DIG_TWO_PORT_ALGO_RSSI;
+			priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_MODE_SS);
+		}
+	}	
+	
+	dm_FalseAlarmCounterStatistics(dev);
+	dm_initial_gain_STABeforeConnect(dev);	
+	dm_CtrlInitGainAPByFalseAlarm(dev);
+	
+	dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState;
+}
+#endif
+
+/*-----------------------------------------------------------------------------
+ * Function:	dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm()
+ *
+ * Overview:	Driver monitor RSSI and False Alarm to change initial gain.
+ 			Only change initial gain during link in progress.
+ *
+ * Input:		IN	PADAPTER	pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	03/04/2009	hpfan	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+ 
+#ifdef RTL8192SE
+static void dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(rtllib_act_scanning(priv->rtllib,true) == true)
+		return;
+
+	if((priv->rtllib->state > RTLLIB_NOLINK) && (priv->rtllib->state < RTLLIB_LINKED))
+		dm_digtable.CurSTAConnectState = DIG_STA_BEFORE_CONNECT;
+	else if((priv->rtllib->state == RTLLIB_LINKED) ||(priv->rtllib->state == RTLLIB_LINKED_SCANNING))
+		dm_digtable.CurSTAConnectState = DIG_STA_CONNECT;
+	else
+		dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT;
+
+	if(dm_digtable.dbg_mode == DM_DBG_OFF)
+		dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
+
+	dm_FalseAlarmCounterStatistics(dev);
+	dm_initial_gain_STABeforeConnect(dev);
+	dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState;
+
+}
+#endif
+static void dm_ctrl_initgain_byrssi_by_driverrssi(
+	struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 i;
+	static u8 	fw_dig=0;
+	
+	if (dm_digtable.dig_enable_flag == false)
+		return;
+
+	if(dm_digtable.dig_algorithm_switch)	
+		fw_dig = 0;
+	if(fw_dig <= 3)	
+	{
+		for(i=0; i<3; i++)
+			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	
+		fw_dig++;
+		dm_digtable.dig_state = DM_STA_DIG_OFF;	
+	}
+		
+	if(priv->rtllib->state == RTLLIB_LINKED)
+		dm_digtable.CurSTAConnectState = DIG_STA_CONNECT;
+	else
+		dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT;
+
+
+	if(dm_digtable.dbg_mode == DM_DBG_OFF)
+		dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
+	dm_initial_gain(dev);
+	dm_pd_th(dev);
+	dm_cs_ratio(dev);
+	if(dm_digtable.dig_algorithm_switch)
+		dm_digtable.dig_algorithm_switch = 0;
+	dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState;
+
+}	
+
+static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
+	struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u32 reset_cnt = 0;
+	u8 i;
+	
+	if (dm_digtable.dig_enable_flag == false)
+		return;
+
+	if(dm_digtable.dig_algorithm_switch)
+	{
+		dm_digtable.dig_state = DM_STA_DIG_MAX;
+		for(i=0; i<3; i++)
+			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	
+		dm_digtable.dig_algorithm_switch = 0;
+	}
+		
+	if (priv->rtllib->state != RTLLIB_LINKED)
+		return;
+
+	if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
+		(priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
+	{
+		return;
+	}
+	if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
+	{		
+		if (dm_digtable.dig_state == DM_STA_DIG_OFF && 
+			(priv->reset_count == reset_cnt))
+		{			
+			return;
+		}
+		else
+		{
+			reset_cnt = priv->reset_count;
+		}
+		
+		dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
+		dm_digtable.dig_state = DM_STA_DIG_OFF;
+
+		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	
+
+		write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
+		write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
+		write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
+		write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
+
+		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+		{
+			#ifdef RTL8190P
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
+			#else 
+				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+				#endif
+			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+				write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40);
+			*/
+			
+				
+		}
+		else
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+
+		write_nic_byte(dev, 0xa0a, 0x08);
+		
+		return;
+		
+	}
+	
+	if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) )
+	{
+		u8 reset_flag = 0;
+		
+		if (dm_digtable.dig_state == DM_STA_DIG_ON && 
+			(priv->reset_count == reset_cnt))
+		{
+			dm_ctrl_initgain_byrssi_highpwr(dev);
+			return;
+		}
+		else
+		{
+			if (priv->reset_count != reset_cnt)
+				reset_flag = 1;
+
+			reset_cnt = priv->reset_count;
+		}
+		
+		dm_digtable.dig_state = DM_STA_DIG_ON;
+		
+		if (reset_flag == 1)
+		{
+			write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
+			write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
+			write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
+			write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
+		}
+		else
+		{
+		write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
+		write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
+		write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
+		write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
+		}
+
+		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+		{
+			#ifdef RTL8190P
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+			#else
+				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+				#endif
+			/*
+			else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+			*/
+			
+		}
+		else
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+
+		write_nic_byte(dev, 0xa0a, 0xcd);
+
+		
+		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	
+		
+	}
+
+	dm_ctrl_initgain_byrssi_highpwr(dev);
+
+}	
+
+
+static void dm_ctrl_initgain_byrssi_highpwr(
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u32 reset_cnt_highpwr = 0;
+	
+	if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
+		(priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
+	{
+		return;
+	}
+	
+	if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) 
+	{
+		if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && 
+			(priv->reset_count == reset_cnt_highpwr))
+			return;
+		else
+			dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
+
+		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+		{			
+			#ifdef RTL8190P
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
+			#else
+				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+				#endif
+			
+			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+				write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
+			*/
+
+		}
+		else
+			write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+	}
+	else
+	{
+		if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&& 
+			(priv->reset_count == reset_cnt_highpwr))		
+			return;
+		else
+			dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
+		
+		if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
+			 priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)
+		{
+			if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+			{				
+				#ifdef RTL8190P
+				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+				#else
+					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+					#endif
+				/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+				*/
+
+			}
+			else
+				write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+		}
+	}
+
+	reset_cnt_highpwr = priv->reset_count;
+
+}	
+
+
+static void dm_initial_gain(
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8					initial_gain=0;
+	static u8				initialized=0, force_write=0;
+	static u32			reset_cnt=0;
+
+	if(dm_digtable.dig_algorithm_switch)
+	{
+		initialized = 0;
+		reset_cnt = 0;
+	}
+	
+	if(rtllib_act_scanning(priv->rtllib,true) == true)
+	{
+		force_write = 1;
+		return;
+	}
+	
+	if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState)
+	{
+		if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT)
+		{
+			if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
+				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
+			else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
+				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
+			else
+				dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
+		}
+		else		
+		{
+			if(dm_digtable.cur_ig_value == 0)
+				dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
+			else
+				dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
+		}
+	}
+	else	
+	{
+		dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
+		dm_digtable.pre_ig_value = 0;
+	}
+
+	if(priv->reset_count != reset_cnt)
+	{
+		force_write = 1;
+		reset_cnt = priv->reset_count;
+	}
+	
+	if(dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1))
+		force_write = 1;
+	
+	{
+		if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) 
+			|| !initialized || force_write)
+		{
+			initial_gain = (u8)dm_digtable.cur_ig_value;
+			write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
+			write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
+			write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
+			write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+			dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
+			initialized = 1;
+			force_write = 0;
+		}
+	}
+}
+
+void dm_initial_gain_STABeforeConnect(
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8			initial_gain=0;
+	static u8		initialized=0, force_write=0;
+
+	RT_TRACE(COMP_DIG, "PreSTAConnectState = %x, CurSTAConnectState = %x\n", 
+				dm_digtable.PreSTAConnectState, dm_digtable.CurSTAConnectState);
+
+
+	if((dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) ||
+		(dm_digtable.CurSTAConnectState == DIG_STA_BEFORE_CONNECT))
+	{
+		if(dm_digtable.CurSTAConnectState == DIG_STA_BEFORE_CONNECT)
+		{
+			if(priv->rtllib->eRFPowerState != eRfOn)
+				return;
+			
+			if(dm_digtable.Backoff_Enable_Flag == true)
+			{
+				if(priv->FalseAlmCnt.Cnt_all > dm_digtable.FAHighThresh)
+				{
+					if((dm_digtable.backoff_val -6) < dm_digtable.BackoffVal_range_min)
+						dm_digtable.backoff_val = dm_digtable.BackoffVal_range_min;
+					else
+						dm_digtable.backoff_val -= 6; 
+				}	
+				else if(priv->FalseAlmCnt.Cnt_all < dm_digtable.FALowThresh)
+				{
+					if((dm_digtable.backoff_val+6) > dm_digtable.BackoffVal_range_max)
+						dm_digtable.backoff_val = dm_digtable.BackoffVal_range_max;
+					else
+						dm_digtable.backoff_val +=6;
+				}
+			}
+			else
+				dm_digtable.backoff_val =DM_DIG_BACKOFF;
+		
+			if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
+				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
+			else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
+				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
+			else
+				dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
+
+			if(priv->FalseAlmCnt.Cnt_all > 10000)
+				dm_digtable.cur_ig_value = (dm_digtable.cur_ig_value>0x33)?dm_digtable.cur_ig_value:0x33;
+
+			if(priv->FalseAlmCnt.Cnt_all > 16000)
+				dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
+
+		}
+		else 
+		{
+			return;	
+		}
+	}
+	else	
+	{		
+		dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX;
+		priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_ENABLE);
+
+		dm_digtable.backoff_val = DM_DIG_BACKOFF;
+		dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
+		dm_digtable.pre_ig_value = 0;
+		return;
+	}
+		
+	if(dm_digtable.pre_ig_value != rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bMaskByte0))
+		force_write = 1;
+	
+	if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) || !initialized || force_write)
+	{
+		priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_DISABLE);	
+
+		initial_gain = (u8)dm_digtable.cur_ig_value;
+
+		rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, initial_gain);
+		rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, initial_gain);
+		dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
+		initialized = 1;
+		force_write = 0;
+	}
+	
+	RT_TRACE(COMP_DIG, "CurIGValue = 0x%x, pre_ig_value = 0x%x, backoff_val = %d\n", 
+				dm_digtable.cur_ig_value, dm_digtable.pre_ig_value, dm_digtable.backoff_val);
+
+}
+
+static void dm_pd_th(	
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u8				initialized=0, force_write=0;
+	static u32			reset_cnt = 0;
+
+	if(dm_digtable.dig_algorithm_switch)
+	{
+		initialized = 0;
+		reset_cnt = 0;
+	}
+	
+	if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState)
+	{
+		if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT)
+		{
+			if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
+				dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
+			else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
+				dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+			else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
+					(dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
+				dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
+			else
+				dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
+		}
+		else
+		{
+			dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+		}
+	}
+	else	
+	{
+		dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+	}
+
+	if(priv->reset_count != reset_cnt)
+	{
+		force_write = 1;
+		reset_cnt = priv->reset_count;
+	}
+		
+	{
+		if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || 
+			(initialized<=3) || force_write)
+		{
+			if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER)
+			{
+				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+				{
+					#ifdef RTL8190P
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
+					#else
+						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+						#endif
+					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+						write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
+					*/
+				}
+				else
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+			}
+			else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER)
+			{
+				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+				{
+					#ifdef RTL8190P
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);	
+					#else
+						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+						#endif
+					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+						write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);		
+					*/
+				}
+				else
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+			}
+			else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER)
+			{
+				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+				{			
+					#ifdef RTL8190P
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
+					#else
+						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+						#endif
+					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
+						write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
+					*/
+				}
+				else
+					write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+			}	
+			dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
+			if(initialized <= 3)
+				initialized++;
+			force_write = 0;
+		}
+	}
+}
+
+static	void dm_cs_ratio(
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u8				initialized=0,force_write=0;
+	static u32			reset_cnt = 0;
+
+	if(dm_digtable.dig_algorithm_switch)
+	{
+		initialized = 0;
+		reset_cnt = 0;
+	}
+	
+	if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState)
+	{
+		if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT)
+		{
+			if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
+				dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+			else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) )
+				dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
+			else
+				dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
+		}
+		else
+		{
+			dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+		}
+	}
+	else	
+	{
+		dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+	}
+
+	if(priv->reset_count != reset_cnt)
+	{
+		force_write = 1;
+		reset_cnt = priv->reset_count;
+	}
+
+	
+	{
+		if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || 
+			!initialized || force_write)
+		{
+			if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
+			{
+				write_nic_byte(dev, 0xa0a, 0x08);
+			}
+			else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
+			{
+				write_nic_byte(dev, 0xa0a, 0xcd);
+			}	
+			dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
+			initialized = 1;
+			force_write = 0;
+		}
+	}
+}
+
+extern void dm_init_edca_turbo(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	priv->bcurrent_turbo_EDCA = false;
+	priv->rtllib->bis_any_nonbepkts = false;
+	priv->bis_cur_rdlstate = false;
+}	
+
+#if 1
+static void dm_check_edca_turbo(
+	struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	
+	static unsigned long			lastTxOkCnt = 0;
+	static unsigned long			lastRxOkCnt = 0;
+	unsigned long				curTxOkCnt = 0;
+	unsigned long				curRxOkCnt = 0;	
+
+	if(priv->rtllib->iw_mode == IW_MODE_ADHOC)
+	{
+		goto dm_CheckEdcaTurbo_EXIT;
+	}
+	if(priv->rtllib->state != RTLLIB_LINKED)
+	{
+		goto dm_CheckEdcaTurbo_EXIT;
+	}
+	if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
+	{
+		goto dm_CheckEdcaTurbo_EXIT;
+	}
+	
+	{
+		u8* peername[11] = {"unknown", "realtek_90", "realtek_92se","broadcom", "ralink", "atheros", "cisco", "marvell", "92u_softap", "self_softap"};
+		static int wb_tmp = 0;
+		if (wb_tmp == 0){
+			printk("%s():iot peer is %s, bssid:"MAC_FMT"\n",__FUNCTION__,peername[pHTInfo->IOTPeer], MAC_ARG(priv->rtllib->current_network.bssid));
+			wb_tmp = 1;
+		}
+	}
+	if(!priv->rtllib->bis_any_nonbepkts)
+	{
+		curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
+		curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
+		if(pHTInfo->IOTAction & HT_IOT_ACT_EDCA_BIAS_ON_RX)
+		{
+			if(curTxOkCnt > 4*curRxOkCnt)
+			{
+				if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
+				{
+					write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
+					priv->bis_cur_rdlstate = false;
+				}
+			}
+			else
+			{
+				if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
+				{
+					if(priv->rtllib->mode == WIRELESS_MODE_G)
+						write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+					else
+						write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
+					priv->bis_cur_rdlstate = true;
+				}
+			}
+			priv->bcurrent_turbo_EDCA = true;
+		}
+		else
+		{
+		if(curRxOkCnt > 4*curTxOkCnt)
+		{
+			if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
+			{
+				if(priv->rtllib->mode == WIRELESS_MODE_G)
+					write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+				else
+				write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
+				priv->bis_cur_rdlstate = true;
+			}
+		}
+		else
+		{
+			if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
+			{
+				write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
+				priv->bis_cur_rdlstate = false;
+			}
+
+		}
+
+		priv->bcurrent_turbo_EDCA = true;
+	}
+	}
+	else
+	{
+		 if(priv->bcurrent_turbo_EDCA)
+		{
+
+			{
+				u8		u1bAIFS;
+				u32		u4bAcParam;
+				struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters;
+				u8 mode = priv->rtllib->mode;
+
+				dm_init_edca_turbo(dev);
+				u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; 
+				u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
+					(((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)|
+					(((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)|
+					((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
+				write_nic_dword(dev, EDCAPARA_BE,  u4bAcParam);
+			
+				{
+
+					PACI_AIFSN	pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
+					u8		AcmCtrl = read_nic_byte( dev, AcmHwCtrl );
+					if( pAciAifsn->f.ACM )
+					{ 
+						AcmCtrl |= AcmHw_BeqEn;
+					}
+					else
+					{ 
+						AcmCtrl &= (~AcmHw_BeqEn);
+					}
+
+					RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ;
+					write_nic_byte(dev, AcmHwCtrl, AcmCtrl );
+				}
+			}
+			priv->bcurrent_turbo_EDCA = false;
+		}
+	}
+	
+		
+dm_CheckEdcaTurbo_EXIT:
+	priv->rtllib->bis_any_nonbepkts = false;
+	lastTxOkCnt = priv->stats.txbytesunicast;
+	lastRxOkCnt = priv->stats.rxbytesunicast;
+}	
+#endif
+
+extern void DM_CTSToSelfSetting(struct net_device * dev,u32 DM_Type, u32 DM_Value)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	
+	if (DM_Type == 0)	
+	{
+		if(DM_Value > 1)
+			DM_Value = 1;
+		priv->rtllib->bCTSToSelfEnable = (bool)DM_Value;
+	}
+	else if(DM_Type == 1) 
+	{
+		if(DM_Value >= 50)
+			DM_Value = 50;
+		priv->rtllib->CTSToSelfTH = (u8)DM_Value;
+	}
+}
+
+static void dm_init_ctstoself(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	
+	priv->rtllib->bCTSToSelfEnable = true;
+	priv->rtllib->CTSToSelfTH = CTSToSelfTHVal;
+}
+
+static void dm_ctstoself(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	static unsigned long				lastTxOkCnt = 0;
+	static unsigned long				lastRxOkCnt = 0;
+	unsigned long						curTxOkCnt = 0;
+	unsigned long						curRxOkCnt = 0;
+
+	if(priv->rtllib->bCTSToSelfEnable != true)
+	{
+		pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
+		return;
+	}
+	if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+	{
+		curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
+		curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
+		if(curRxOkCnt > 4*curTxOkCnt)	
+		{
+			pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
+		}
+		else	
+		{
+		#if 1
+			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
+		#else
+			if(priv->undecorated_smoothed_pwdb < priv->rtllib->CTSToSelfTH)	
+			{
+				pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
+			}
+			else if(priv->undecorated_smoothed_pwdb >= (priv->rtllib->CTSToSelfTH+5))	
+			{
+				pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
+			}
+		#endif
+		}
+
+		lastTxOkCnt = priv->stats.txbytesunicast;
+		lastRxOkCnt = priv->stats.rxbytesunicast;
+	}
+}
+
+
+static	void 
+dm_Init_WA_Broadcom_IOT(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	
+	pHTInfo->bWAIotBroadcom = false;
+	pHTInfo->WAIotTH = WAIotTHVal;
+}
+
+#ifdef RTL8192SE
+static	void
+dm_WA_Broadcom_IOT(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	u8					update=0;
+	static enum rtllib_state connectState = RTLLIB_NOLINK;
+
+	if( (pHTInfo->bWAIotBroadcom != true) ||
+		(priv->rtllib->mode == WIRELESS_MODE_B) ||
+		(pHTInfo->bCurBW40MHz))
+	{
+		if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+		{	
+			pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom;
+			update = 1;
+			printk(" dm_WA_Broadcom_IOT(), disable HT_IOT_ACT_WA_IOT_Broadcom\n");
+		}
+		else
+			return;
+	}
+
+	if(connectState == RTLLIB_LINKED && priv->rtllib->state == RTLLIB_LINKED)	
+	{
+		if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+		{	
+			pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom;
+			update = 1;
+			pHTInfo->bWAIotBroadcom = false;
+			printk("dm_WA_Broadcom_IOT(), from connect to disconnected, disable HT_IOT_ACT_WA_IOT_Broadcom\n");
+		}
+	}
+	connectState = priv->rtllib->state;
+		
+	if(!update && pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+	{
+		if(priv->undecorated_smoothed_pwdb < pHTInfo->WAIotTH)
+		{
+			if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+			{	
+				pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom;
+				update = 1;
+				printk("dm_WA_Broadcom_IOT() ==> WA_IOT enable cck rates\n");
+			}
+		}
+		else if(priv->undecorated_smoothed_pwdb >= (priv->rtllib->CTSToSelfTH+5))	
+		{
+			if((pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) == 0)
+			{
+				pHTInfo->IOTAction |= HT_IOT_ACT_WA_IOT_Broadcom;
+				update = 1;
+				printk("dm_WA_Broadcom_IOT() ==> WA_IOT disable cck rates\n");
+			}
+		}
+	}
+
+	if(update){
+		if(priv->rtllib->bUseRAMask){
+			priv->rtllib->UpdateHalRAMaskHandler(
+										dev,
+										false,
+										0,
+										priv->rtllib->pHTInfo->PeerMimoPs,
+										priv->rtllib->mode,
+										priv->rtllib->pHTInfo->bCurTxBW40MHz,
+										0);
+		}else{
+			priv->ops->update_ratr_table(dev, priv->rtllib->dot11HTOperationalRateSet, NULL);
+		}
+		priv->rtllib->SetHwRegHandler( dev, HW_VAR_BASIC_RATE, (u8*)(&priv->basic_rate));
+	}
+}
+#endif
+
+
+#if 0
+extern void dm_rf_operation_test_callback(unsigned long dev)
+{
+	u8 erfpath;
+		
+		
+	for(erfpath=0; erfpath<4; erfpath++) 
+	{
+		udelay(100); 
+	} 
+
+	{
+	}
+	
+	{
+#if 0
+		for(i=0; i<50; i++) 
+		{ 
+			PHY_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+			PHY_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+			PHY_SetRFReg(dev, RF90_PATH_C, 0x02, bMask12Bits, 0x4d);
+			PHY_SetRFReg(dev, RF90_PATH_C, 0x02, bMask12Bits, 0x4f);
+
+#if 0
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits);
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits);
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x12, bMask12Bits);
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x12, bMask12Bits);
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x21, bMask12Bits);
+			PHY_QueryRFReg(dev, RF90_PATH_A, 0x21, bMask12Bits);
+#endif
+		} 
+#endif
+	}
+	
+}	
+#endif
+
+#if 0
+static void dm_check_rfctrl_gpio(struct net_device * dev)
+{
+#ifdef RTL8192E
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+
+	
+#ifdef RTL8190P
+	return;
+#endif
+#ifdef RTL8192U
+	return;
+#endif
+#ifdef RTL8192E
+	queue_delayed_work_rsl(priv->priv_wq,&priv->gpio_change_rf_wq,0);
+#endif
+
+}	
+
+#endif
+static	void	dm_check_pbc_gpio(struct net_device *dev)
+{
+#ifdef RTL8192U
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 tmp1byte;
+
+	
+	tmp1byte = read_nic_byte(dev,GPI);
+	if(tmp1byte == 0xff)
+	return;
+
+	if (tmp1byte&BIT6 || tmp1byte&BIT0)
+	{
+		RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n");
+		priv->bpbc_pressed = true;
+	}
+#endif
+	
+}
+
+#ifdef RTL8192E 
+
+extern	void	dm_CheckRfCtrlGPIO(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+       struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,gpio_change_rf_wq);
+       struct net_device *dev = priv->rtllib->dev;
+#else
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
+	struct net_device *dev = priv->rtllib->dev;
+#endif
+	u8 tmp1byte;
+	RT_RF_POWER_STATE	eRfPowerStateToSet;
+	bool bActuallySet = false;
+
+	char *argv[3];
+	static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
+	static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
+
+	bActuallySet=false;
+
+	if((priv->up_first_time == 1) || (priv->being_init_adapter))
+	{
+		return;
+	}
+
+	if(priv->bfirst_after_down){
+		priv->bfirst_after_down = 1;
+		return;
+	}
+
+
+
+	{
+		tmp1byte = read_nic_byte(dev,GPI);
+
+		eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
+
+		if( (priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
+		{
+			RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio ON\n");
+			printk("gpiochangeRF  - HW Radio ON\n");
+			priv->bHwRadioOff = false;
+			bActuallySet = true;
+		}
+		else if ( (priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
+		{
+			RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio OFF\n");
+			printk("gpiochangeRF  - HW Radio OFF\n");
+			priv->bHwRadioOff = true;
+			bActuallySet = true;
+		}
+
+		if(bActuallySet)
+		{
+			mdelay(1000); 
+			priv->bHwRfOffAction = 1;
+			MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+			{
+				if(priv->bHwRadioOff == true)
+					argv[1] = "RFOFF";
+				else
+					argv[1] = "RFON";
+
+				argv[0] = RadioPowerPath;
+				argv[2] = NULL;
+				call_usermodehelper(RadioPowerPath,argv,envp,1);
+			}
+
+		}
+#if 0 
+		else
+		{
+			msleep(2000);
+		}
+#endif
+
+	}
+
+}	
+#elif defined RTL8192SE
+extern void Power_DomainInit92SE(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8				tmpU1b;
+	u16				tmpU2b;
+
+	
+	
+	priv->PwrDomainProtect = true;
+
+	tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1));
+	if(tmpU1b & BIT7)
+	{
+		tmpU1b &= ~(BIT6 | BIT7);
+		if(!HalSetSysClk8192SE(dev, tmpU1b)){
+			priv->PwrDomainProtect = false;
+			return; 
+	}
+	}
+	
+	write_nic_byte(dev, AFE_PLL_CTRL, 0x0);
+	write_nic_byte(dev, LDOA15_CTRL, 0x34);
+	
+#if 0
+	tmpU2b = read_nic_word(dev, SYS_CLKR);
+	if (tmpU2b & BIT15)	
+	{
+		tmpU2b &= ~(BIT14|BIT15);
+		RT_TRACE(COMP_INIT, DBG_LOUD, ("Return to HW CTRL\n"));
+		write_nic_word(dev, SYS_CLKR, tmpU2b);
+	}
+	udelay(200);
+#endif
+
+	tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1);
+	if (priv->rtllib->RfOffReason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) {
+		tmpU1b &= 0xFB;
+	} else {
+		tmpU1b &= 0x73;
+	}
+	
+	write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b);
+	udelay(1000);
+	
+	write_nic_byte(dev, CMDR, 0);
+	write_nic_byte(dev, TCR, 0);
+
+	tmpU1b = read_nic_byte(dev, 0x562);
+	tmpU1b |= 0x08;
+	write_nic_byte(dev, 0x562, tmpU1b);
+	tmpU1b &= ~(BIT3);
+	write_nic_byte(dev, 0x562, tmpU1b);
+
+	tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL);	
+	write_nic_byte(dev, AFE_XTAL_CTRL, (tmpU1b|0x01));
+	udelay(1500);	
+	tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL+1);	
+	write_nic_byte(dev, AFE_XTAL_CTRL+1, (tmpU1b&0xfb));
+
+
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|BIT0));
+	udelay(1000);
+
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|0x02));
+	udelay(1000);
+	
+	tmpU1b = read_nic_byte(dev, LDOA15_CTRL);	
+	write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|BIT0));
+
+	tmpU2b = read_nic_word(dev, SYS_ISO_CTRL);	
+	write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|BIT11));
+
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b |BIT13));
+
+	write_nic_byte(dev, SYS_ISO_CTRL+1, 0x68);
+
+	tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL);	
+	write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4));
+	tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL+1);	
+	write_nic_byte(dev, AFE_PLL_CTRL+1, (tmpU1b|BIT0));
+	udelay(1000);
+
+	write_nic_byte(dev, SYS_ISO_CTRL, 0xA6);
+
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, (tmpU2b|BIT12|BIT11));
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);	
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11));
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11|BIT15));
+
+	 tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, (tmpU2b&(~BIT2)));
+	
+	tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1));
+	tmpU1b = ((tmpU1b | BIT7) & (~BIT6));
+	if(!HalSetSysClk8192SE(dev, tmpU1b))
+	{
+		priv->PwrDomainProtect = false;
+		return; 
+	}
+#if 0
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, ((tmpU2b|BIT15)&(~BIT14)));
+#endif
+
+	write_nic_word(dev, CMDR, 0x37FC);	
+
+	gen_RefreshLedState(dev);
+
+	priv->PwrDomainProtect = false;
+
+}	
+
+void	SET_RTL8192SE_RF_HALT(struct net_device *dev)							
+{ 																	
+	u8		u1bTmp;												
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS && priv->LedStrategy == SW_LED_MODE8)	
+	{
+		SET_RTL8192SE_RF_SLEEP(dev);
+		return;
+	}
+	
+	u1bTmp = read_nic_byte(dev, LDOV12D_CTRL);		
+	u1bTmp |= BIT0; 												
+	write_nic_byte(dev, LDOV12D_CTRL, u1bTmp);		
+	write_nic_byte(dev, SPS1_CTRL, 0x0);				
+	write_nic_byte(dev, TXPAUSE, 0xFF);				
+	write_nic_word(dev, CMDR, 0x57FC);				
+	udelay(100);													
+	write_nic_word(dev, CMDR, 0x77FC);				
+	write_nic_byte(dev, PHY_CCA, 0x0);				
+	udelay(10);													
+	write_nic_word(dev, CMDR, 0x37FC);				
+	udelay(10);													
+	write_nic_word(dev, CMDR, 0x77FC);				
+	udelay(10);													
+	write_nic_word(dev, CMDR, 0x57FC);				
+	write_nic_word(dev, CMDR, 0x0000);				
+	u1bTmp = read_nic_byte(dev, (SYS_CLKR + 1));		
+	if(u1bTmp & BIT7)												
+	{																
+		u1bTmp &= ~(BIT6 | BIT7);									
+		if(!HalSetSysClk8192SE(dev, u1bTmp))					
+			return;													
+	}	
+	if(priv->rtllib->RfOffReason==RF_CHANGE_BY_IPS )
+	{
+		write_nic_byte(dev, 0x03, 0xF9);
+	}
+	else		
+	{
+		write_nic_byte(dev, 0x03, 0x71);
+	}
+	write_nic_byte(dev, SYS_CLKR+1, 0x70);					
+	write_nic_byte(dev, AFE_PLL_CTRL+1, 0x68);					
+	write_nic_byte(dev, AFE_PLL_CTRL, 0x00);					
+	write_nic_byte(dev, LDOA15_CTRL, 0x34);
+	write_nic_byte(dev, AFE_XTAL_CTRL, 0x0E);					
+															
+}
+
+u8 RfOnOffDetect(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	u1Tmp;
+	u8	retval=eRfOn;
+
+	if(priv->pwrdown)
+	{
+		u1Tmp = read_nic_byte(dev, 0x06);
+		printk("pwrdown, 0x6(BIT6)=%02x\n", u1Tmp);
+		retval = (u1Tmp & BIT6) ? eRfOn: eRfOff;
+	}
+	else
+	{
+#ifdef CONFIG_BT_COEXIST
+		if(pHalData->bt_coexist.BluetoothCoexist)
+		{
+			if(pHalData->bt_coexist.BT_CoexistType == BT_2Wire)
+			{
+				PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, 0xa);
+				u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL);
+				delay_us(100);
+				u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN);
+				RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp));
+				retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff;
+			}
+			else if( (pHalData->bt_coexist.BT_CoexistType == BT_ISSC_3Wire) ||
+					(pHalData->bt_coexist.BT_CoexistType == BT_Accel) ||
+					(pHalData->bt_coexist.BT_CoexistType == BT_CSR) )
+			{
+				u4tmp = PHY_QueryBBReg(pAdapter, 0x87c, bMaskDWord);
+				if((u4tmp & BIT17) != 0)
+				{
+					PHY_SetBBReg(pAdapter, 0x87c, bMaskDWord, u4tmp & ~BIT17);
+					delay_us(50);
+					RTPRINT(FBT, BT_RFPoll, ("BT write 0x87c (~BIT17) = 0x%x\n", u4tmp &~BIT17));
+				}
+				u4tmp = PHY_QueryBBReg(pAdapter, 0x8e0, bMaskDWord);
+				RTPRINT(FBT, BT_RFPoll, ("BT read 0x8e0 (BIT24)= 0x%x\n", u4tmp));
+				retval = (u4tmp & BIT24) ? eRfOn : eRfOff;
+				RTPRINT(FBT, BT_RFPoll, ("BT check RF state to %s\n", (retval==eRfOn)? "ON":"OFF"));
+			}
+		}
+		else
+#endif
+		{
+			write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO));
+			u1Tmp = read_nic_byte(dev, GPIO_IO_SEL);
+
+			u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK;
+			write_nic_byte(dev, GPIO_IO_SEL, u1Tmp);
+
+			mdelay(10);
+
+			u1Tmp = read_nic_byte(dev, GPIO_IN);
+			retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff;
+		}
+	}
+
+	return retval;
+}
+
+extern void dm_CheckRfCtrlGPIO(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,gpio_change_rf_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+
+	RT_RF_POWER_STATE	eRfPowerStateToSet, CurRfState;
+	bool					bActuallySet = false;
+	PRT_POWER_SAVE_CONTROL		pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	unsigned long flag = 0;
+	bool			turnonbypowerdomain = false;
+
+
+#ifdef CONFIG_RTL_RFKILL
+	return;
+#endif	
+	if((priv->up_first_time == 1) || (priv->being_init_adapter))
+	{
+		;
+		return;
+	}
+
+	if(priv->ResetProgress == RESET_TYPE_SILENT)
+	{
+		RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+		return;
+	}
+
+
+	if (pPSC->bSwRfProcessing) 
+	{
+		RT_TRACE(COMP_SCAN, "GPIOChangeRFWorkItemCallBack(): Rf is in switching state.\n");
+		return;
+	}
+
+	RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack() ---------> \n");
+
+	spin_lock_irqsave(&priv->rf_ps_lock,flag);
+	if (priv->RFChangeInProgress) {
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+		RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack(): RF Change in progress! \n");
+		return;
+	} else {
+		priv->RFChangeInProgress = true;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+	}
+	CurRfState = priv->rtllib->eRFPowerState;
+#ifdef CONFIG_ASPM_OR_D3
+	if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM))
+	{
+		RT_DISABLE_ASPM(dev);
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+	}
+	else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3))
+	{
+#ifdef TODO		
+		RT_LEAVE_D3(dev, false);
+		RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+#endif		
+	}
+
+#endif
+	if(RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+	{
+		Power_DomainInit92SE(dev);
+		turnonbypowerdomain = true;
+	}
+
+	eRfPowerStateToSet = RfOnOffDetect(dev);
+	if (priv->bResetInProgress) {
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		priv->RFChangeInProgress = false;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+		return;
+	}
+
+	if( (priv->bHwRadioOff == true) && \
+	   (((eRfPowerStateToSet == eRfOn)&&(priv->sw_radio_on == true))
+#ifdef CONFIG_RTLWIFI_DEBUGFS	    
+	    ||priv->debug->hw_holding
+#endif	    
+	    ))
+	{
+		RT_TRACE(COMP_RF, "GPIOChangeRF  - HW Radio ON, RF ON\n");
+		printk("GPIOChangeRF  - HW Radio ON, RF ON\n");
+                eRfPowerStateToSet = eRfOn;
+		bActuallySet = true;
+	} else if ((priv->bHwRadioOff == false) && 
+		 ((eRfPowerStateToSet == eRfOff) || (priv->sw_radio_on == false)))
+	{
+		RT_TRACE(COMP_RF, "GPIOChangeRF  - HW Radio OFF\n");
+		printk("GPIOChangeRF  - HW Radio OFF\n");
+                eRfPowerStateToSet = eRfOff;
+		bActuallySet = true;
+	}
+
+	if (bActuallySet) {
+		priv->bHwRfOffAction = 1;
+#ifdef CONFIG_ASPM_OR_D3
+		if(eRfPowerStateToSet == eRfOn)
+		{
+			if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM))
+			{
+				RT_DISABLE_ASPM(dev);
+				RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+			}
+#ifdef TODO			
+			else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3))
+			{
+				RT_LEAVE_D3(dev, false);
+				RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+			}
+#endif			
+		}
+#endif
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		priv->RFChangeInProgress = false;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+		MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+
+		{
+#ifdef CONFIG_CFG_80211			
+			struct wireless_dev *wdev = &priv->rtllib->wdev;
+			wiphy_rfkill_set_hw_state(wdev->wiphy, priv->bHwRadioOff);
+#else
+			char *argv[3];
+			static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
+			static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
+
+			if(priv->bHwRadioOff == true)
+				argv[1] = "RFOFF";
+			else
+				argv[1] = "RFON";
+
+			argv[0] = RadioPowerPath;
+			argv[2] = NULL;
+			call_usermodehelper(RadioPowerPath,argv,envp,1);
+
+#endif			
+		}
+
+		if(eRfPowerStateToSet == eRfOff)
+		{
+			if(priv->pwrdown){
+
+				write_nic_byte(dev, SYS_FUNC_EN+1, 0x31);
+			}
+#ifdef CONFIG_ASPM_OR_D3
+			if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM)
+			{
+				RT_ENABLE_ASPM(dev);
+				RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+			}
+#ifdef TODO			
+			else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3)
+			{
+				RT_ENTER_D3(dev, false);
+				RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+			}
+#endif			
+#endif
+		}
+	}
+	else if(eRfPowerStateToSet == eRfOff || CurRfState == eRfOff || priv->bDriverIsGoingToUnload)
+	{
+
+		if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && turnonbypowerdomain)
+		{ 
+			PHY_SetRtl8192seRfHalt(dev);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+		}
+#ifdef CONFIG_ASPM_OR_D3
+		if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM)
+		{
+			RT_ENABLE_ASPM(dev);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
+		}
+#ifdef TODO		
+		else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3)
+		{
+			RT_ENTER_D3(dev, false);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
+		}
+#endif		
+#endif
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		priv->RFChangeInProgress = false;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+	}
+	else
+	{
+		spin_lock_irqsave(&priv->rf_ps_lock,flag);
+		priv->RFChangeInProgress = false;
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+	}
+	RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack() <--------- \n");
+}
+#endif
+void	dm_rf_pathcheck_workitemcallback(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,rfpath_check_wq);
+	struct net_device *dev =priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+	u8 rfpath = 0, i;
+	
+		
+	rfpath = read_nic_byte(dev, 0xc04);
+	
+	for (i = 0; i < RF90_PATH_MAX; i++)
+	{
+		if (rfpath & (0x01<<i))		
+			priv->brfpath_rxenable[i] = 1;
+		else
+			priv->brfpath_rxenable[i] = 0;
+	}
+	if(!DM_RxPathSelTable.Enable)
+		return;
+
+	dm_rxpath_sel_byrssi(dev);
+}	
+
+static void dm_init_rxpath_selection(struct net_device * dev)
+{
+	u8 i;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	DM_RxPathSelTable.Enable = 1;	
+	DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
+	DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
+	if(priv->CustomerID == RT_CID_819x_Netcore)
+		DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
+	else	
+		DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
+	DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
+	DM_RxPathSelTable.disabledRF = 0;
+	for(i=0; i<4; i++)
+	{
+		DM_RxPathSelTable.rf_rssi[i] = 50;
+		DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
+		DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
+	}
+}
+
+static void dm_rxpath_sel_byrssi(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8				i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0;
+	u8				tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0;
+	u8				cck_default_Rx=0x2;	
+	u8				cck_optional_Rx=0x3;
+	long				tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0;
+	u8				cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0;
+	u8				cur_rf_rssi;
+	long				cur_cck_pwdb;
+	static u8			disabled_rf_cnt=0, cck_Rx_Path_initialized=0;
+	u8				update_cck_rx_path;
+
+	if(priv->rf_type != RF_2T4R)
+		return;
+
+	if(!cck_Rx_Path_initialized)
+	{
+		DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf);
+		cck_Rx_Path_initialized = 1;
+	}
+	
+	DM_RxPathSelTable.disabledRF = 0xf;
+	DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(dev, 0xc04));
+
+	if(priv->rtllib->mode == WIRELESS_MODE_B)
+	{
+		DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;	
+	}
+
+	for (i=0; i<RF90_PATH_MAX; i++)
+	{
+		if(!DM_RxPathSelTable.DbgMode)
+			DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
+
+		if(priv->brfpath_rxenable[i])
+		{
+			rf_num++;
+			cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
+			
+			if(rf_num == 1)	
+			{	
+				max_rssi_index = min_rssi_index = sec_rssi_index = i;
+				tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
+			}
+			else if(rf_num == 2)
+			{	
+				if(cur_rf_rssi >= tmp_max_rssi)
+				{
+					tmp_max_rssi = cur_rf_rssi;
+					max_rssi_index = i;
+				}
+				else
+				{
+					tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
+					sec_rssi_index = min_rssi_index = i;					
+				}
+			}
+			else
+			{
+				if(cur_rf_rssi > tmp_max_rssi)
+				{
+					tmp_sec_rssi = tmp_max_rssi;
+					sec_rssi_index = max_rssi_index;
+					tmp_max_rssi = cur_rf_rssi;
+					max_rssi_index = i;
+				}
+				else if(cur_rf_rssi == tmp_max_rssi)
+				{	
+					tmp_sec_rssi = cur_rf_rssi;
+					sec_rssi_index = i;
+				}
+				else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi))
+				{
+					tmp_sec_rssi = cur_rf_rssi;
+					sec_rssi_index = i;
+				}
+				else if(cur_rf_rssi == tmp_sec_rssi)
+				{
+					if(tmp_sec_rssi == tmp_min_rssi)
+					{	
+						tmp_sec_rssi = cur_rf_rssi;
+						sec_rssi_index = i;
+					}
+					else
+					{
+					}
+				}
+				else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi))
+				{
+				}
+				else if(cur_rf_rssi == tmp_min_rssi)
+				{
+					if(tmp_sec_rssi == tmp_min_rssi)
+					{	
+						tmp_min_rssi = cur_rf_rssi;
+						min_rssi_index = i;
+					}
+					else
+					{
+					}
+				}
+				else if(cur_rf_rssi < tmp_min_rssi)
+				{
+					tmp_min_rssi = cur_rf_rssi;
+					min_rssi_index = i;
+				}
+			}
+		}
+	}
+
+	rf_num = 0;
+	if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
+	{
+		for (i=0; i<RF90_PATH_MAX; i++)
+		{
+			if(priv->brfpath_rxenable[i])
+			{
+				rf_num++;
+				cur_cck_pwdb =  DM_RxPathSelTable.cck_pwdb_sta[i];
+				
+				if(rf_num == 1)	
+				{	
+					cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i;
+					tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb;
+				}
+				else if(rf_num == 2)
+				{	
+					if(cur_cck_pwdb >= tmp_cck_max_pwdb)
+					{
+						tmp_cck_max_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_max_index = i;
+					}
+					else
+					{
+						tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i;					
+					}
+				}
+				else
+				{
+					if(cur_cck_pwdb > tmp_cck_max_pwdb)
+					{
+						tmp_cck_sec_pwdb = tmp_cck_max_pwdb;
+						cck_rx_ver2_sec_index = cck_rx_ver2_max_index;
+						tmp_cck_max_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_max_index = i;
+					}
+					else if(cur_cck_pwdb == tmp_cck_max_pwdb)
+					{	
+						tmp_cck_sec_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_sec_index = i;
+					}
+					else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb))
+					{
+						tmp_cck_sec_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_sec_index = i;
+					}
+					else if(cur_cck_pwdb == tmp_cck_sec_pwdb)
+					{
+						if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
+						{	
+							tmp_cck_sec_pwdb = cur_cck_pwdb;
+							cck_rx_ver2_sec_index = i;
+						}
+						else
+						{
+						}
+					}
+					else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb))
+					{
+					}
+					else if(cur_cck_pwdb == tmp_cck_min_pwdb)
+					{
+						if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
+						{	
+							tmp_cck_min_pwdb = cur_cck_pwdb;
+							cck_rx_ver2_min_index = i;
+						}
+						else
+						{
+						}
+					}
+					else if(cur_cck_pwdb < tmp_cck_min_pwdb)
+					{
+						tmp_cck_min_pwdb = cur_cck_pwdb;
+						cck_rx_ver2_min_index = i;
+					}
+				}
+			
+			}
+		}
+	}
+
+
+	update_cck_rx_path = 0;
+	if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
+	{
+		cck_default_Rx = cck_rx_ver2_max_index;
+		cck_optional_Rx = cck_rx_ver2_sec_index;
+		if(tmp_cck_max_pwdb != -64)
+			update_cck_rx_path = 1;
+	}
+
+	if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2)
+	{
+		if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH)
+		{
+			DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
+			rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	
+			rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	
+			disabled_rf_cnt++;
+		}
+		if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1)
+		{
+			cck_default_Rx = max_rssi_index;
+			cck_optional_Rx = sec_rssi_index;
+			if(tmp_max_rssi)
+				update_cck_rx_path = 1;
+		}
+	}
+
+	if(update_cck_rx_path)
+	{
+		DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
+		rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
+	}
+	
+	if(DM_RxPathSelTable.disabledRF)
+	{
+		for(i=0; i<4; i++)
+		{
+			if((DM_RxPathSelTable.disabledRF>>i) & 0x1)	
+			{
+				if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i])
+				{
+					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);	
+					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);	
+					DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
+					disabled_rf_cnt--;
+				}
+			}
+		}
+	}
+}
+
+static	void	dm_check_rx_path_selection(struct net_device *dev)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	queue_delayed_work_rsl(priv->priv_wq,&priv->rfpath_check_wq,0);
+}	
+
+
+static void dm_init_fsync (struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	priv->rtllib->fsync_time_interval = 500;
+	priv->rtllib->fsync_rate_bitmap = 0x0f000800;
+	priv->rtllib->fsync_rssi_threshold = 30;
+#ifdef RTL8190P
+	priv->rtllib->bfsync_enable = true;
+#elif defined RTL8192E || defined RTL8192SE
+	priv->rtllib->bfsync_enable = false;
+#endif
+	priv->rtllib->fsync_multiple_timeinterval = 3;
+	priv->rtllib->fsync_firstdiff_ratethreshold= 100;
+	priv->rtllib->fsync_seconddiff_ratethreshold= 200;
+	priv->rtllib->fsync_state = Default_Fsync;
+
+#ifdef RTL8192SE
+	priv->framesyncMonitor = 0;	
+#elif defined RTL8192E || defined RTL8190P
+	priv->framesyncMonitor = 1;	
+#endif
+
+	setup_timer(&priv->fsync_timer, dm_fsync_timer_callback,(unsigned long) dev);
+}
+
+
+static void dm_deInit_fsync(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	del_timer_sync(&priv->fsync_timer);
+}
+
+extern void dm_fsync_timer_callback(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
+	u32 rate_index, rate_count = 0, rate_count_diff=0;
+	bool		bSwitchFromCountDiff = false;
+	bool		bDoubleTimeInterval = false;
+	
+	if(	priv->rtllib->state == RTLLIB_LINKED && 
+		priv->rtllib->bfsync_enable &&
+		(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
+	{	
+		u32 rate_bitmap;
+		for(rate_index = 0; rate_index <= 27; rate_index++)
+		{
+			rate_bitmap  = 1 << rate_index;
+			if(priv->rtllib->fsync_rate_bitmap &  rate_bitmap)
+		 		rate_count+= priv->stats.received_rate_histogram[1][rate_index];
+		}	
+
+		if(rate_count < priv->rate_record)
+			rate_count_diff = 0xffffffff - rate_count + priv->rate_record;
+		else	
+			rate_count_diff = rate_count - priv->rate_record;
+		if(rate_count_diff < priv->rateCountDiffRecord)
+		{
+			
+			u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
+			if(DiffNum >= priv->rtllib->fsync_seconddiff_ratethreshold)
+				priv->ContiuneDiffCount++;
+			else
+				priv->ContiuneDiffCount = 0;	
+			
+			if(priv->ContiuneDiffCount >=2)
+			{
+				bSwitchFromCountDiff = true;
+				priv->ContiuneDiffCount = 0;					
+			}				
+		}	
+		else
+		{
+			priv->ContiuneDiffCount = 0;
+		}	
+
+		if(rate_count_diff <= priv->rtllib->fsync_firstdiff_ratethreshold)
+		{
+			bSwitchFromCountDiff = true;
+			priv->ContiuneDiffCount = 0;
+		}	
+		priv->rate_record = rate_count;
+		priv->rateCountDiffRecord = rate_count_diff;
+		RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
+		if(priv->undecorated_smoothed_pwdb > priv->rtllib->fsync_rssi_threshold && bSwitchFromCountDiff)
+		{
+			bDoubleTimeInterval = true;
+			priv->bswitch_fsync = !priv->bswitch_fsync;
+			if(priv->bswitch_fsync)
+			{		
+			#ifdef RTL8190P
+				write_nic_byte(dev,0xC36, 0x00);
+#elif defined RTL8192E
+				write_nic_byte(dev,0xC36, 0x1c);
+			#endif
+				write_nic_byte(dev, 0xC3e, 0x90);
+			}	
+			else
+			{
+			#ifdef RTL8190P
+				write_nic_byte(dev, 0xC36, 0x40);
+			#else
+				write_nic_byte(dev, 0xC36, 0x5c);
+			#endif
+				write_nic_byte(dev, 0xC3e, 0x96);
+			}	
+		}
+		else if(priv->undecorated_smoothed_pwdb <= priv->rtllib->fsync_rssi_threshold)
+		{
+			if(priv->bswitch_fsync)
+			{
+				priv->bswitch_fsync  = false;		
+			#ifdef RTL8190P
+				write_nic_byte(dev, 0xC36, 0x40);
+#elif defined RTL8192E
+				write_nic_byte(dev, 0xC36, 0x5c);
+			#endif
+				write_nic_byte(dev, 0xC3e, 0x96);			
+			}	
+		}
+		if(bDoubleTimeInterval){
+			if(timer_pending(&priv->fsync_timer))
+				del_timer_sync(&priv->fsync_timer);
+			priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval*priv->rtllib->fsync_multiple_timeinterval);
+			add_timer(&priv->fsync_timer);
+		}
+		else{
+			if(timer_pending(&priv->fsync_timer))
+				del_timer_sync(&priv->fsync_timer);
+			priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval);
+			add_timer(&priv->fsync_timer);
+		}
+	}	
+	else
+	{
+		if(priv->bswitch_fsync)
+		{
+			priv->bswitch_fsync  = false;
+		#ifdef RTL8190P
+			write_nic_byte(dev, 0xC36, 0x40);
+#elif defined RTL8192E
+			write_nic_byte(dev, 0xC36, 0x5c);
+		#endif
+			write_nic_byte(dev, 0xC3e, 0x96);
+		}	
+		priv->ContiuneDiffCount = 0;
+	#ifdef RTL8190P
+		write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd);
+#elif defined RTL8192E
+		write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+	#endif
+	}
+	RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
+	RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
+}
+
+static void dm_StartHWFsync(struct net_device *dev)
+{
+	RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
+#if defined RTL8192E 
+	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
+	write_nic_byte(dev, 0xc3b, 0x41);
+#elif defined RTL8192SE
+	write_nic_byte(dev, rOFDM0_RxDetector3, 0x96);
+#endif
+}
+
+static void dm_EndHWFsync(struct net_device *dev)
+{
+	RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
+#if defined RTL8192E 
+	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+	write_nic_byte(dev, 0xc3b, 0x49);
+#elif defined RTL8192SE
+	write_nic_byte(dev, rOFDM0_RxDetector3, 0x94);
+#endif
+	
+}
+
+static void dm_EndSWFsync(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
+	del_timer_sync(&(priv->fsync_timer));
+
+	if(priv->bswitch_fsync)
+	{
+		priv->bswitch_fsync  = false;
+
+		#ifdef RTL8190P
+			write_nic_byte(dev, 0xC36, 0x40);
+#elif defined RTL8192E
+		write_nic_byte(dev, 0xC36, 0x5c);
+#endif
+
+		write_nic_byte(dev, 0xC3e, 0x96);				
+	}		
+				
+	priv->ContiuneDiffCount = 0;
+#ifdef RTL8192E
+	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+#endif
+
+}
+
+static void dm_StartSWFsync(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 			rateIndex;
+	u32 			rateBitmap;	
+
+	RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
+	priv->rate_record = 0;
+	priv->ContiuneDiffCount = 0;
+	priv->rateCountDiffRecord = 0;
+	priv->bswitch_fsync  = false;
+
+	if(priv->rtllib->mode == WIRELESS_MODE_N_24G)
+	{
+		priv->rtllib->fsync_firstdiff_ratethreshold= 600;
+		priv->rtllib->fsync_seconddiff_ratethreshold = 0xffff;
+	}	
+	else
+	{
+		priv->rtllib->fsync_firstdiff_ratethreshold= 200;
+		priv->rtllib->fsync_seconddiff_ratethreshold = 200;
+	}	
+	for(rateIndex = 0; rateIndex <= 27; rateIndex++)
+	{
+		rateBitmap  = 1 << rateIndex;
+		if(priv->rtllib->fsync_rate_bitmap &  rateBitmap)
+			priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
+	}	
+	if(timer_pending(&priv->fsync_timer))
+		del_timer_sync(&priv->fsync_timer);
+	priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval);
+	add_timer(&priv->fsync_timer);
+	
+#ifdef RTL8192E
+	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);		
+#endif
+
+}
+
+void dm_check_fsync(struct net_device *dev)
+{
+#define	RegC38_Default				0
+#define	RegC38_NonFsync_Other_AP	1
+#define	RegC38_Fsync_AP_BCM		2
+	struct r8192_priv *priv = rtllib_priv(dev);
+	static u8		reg_c38_State=RegC38_Default;
+	static u32	reset_cnt=0;
+	
+	RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->rtllib->fsync_rssi_threshold, priv->rtllib->fsync_time_interval, priv->rtllib->fsync_multiple_timeinterval);	
+	RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->rtllib->fsync_rate_bitmap, priv->rtllib->fsync_firstdiff_ratethreshold, priv->rtllib->fsync_seconddiff_ratethreshold);	
+	
+	if(	priv->rtllib->state == RTLLIB_LINKED && 
+		(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
+	{
+		if(priv->rtllib->bfsync_enable == 0)
+		{
+			switch(priv->rtllib->fsync_state)
+			{
+				case Default_Fsync:
+					dm_StartHWFsync(dev);
+					priv->rtllib->fsync_state = HW_Fsync;
+					break;
+				case SW_Fsync:
+					dm_EndSWFsync(dev);
+					dm_StartHWFsync(dev);
+					priv->rtllib->fsync_state = HW_Fsync;
+					break;
+				case HW_Fsync:
+				default:
+					break;
+			}	
+		}
+		else
+		{
+			switch(priv->rtllib->fsync_state)
+			{
+				case Default_Fsync:
+					dm_StartSWFsync(dev);
+					priv->rtllib->fsync_state = SW_Fsync;
+					break;
+				case HW_Fsync:
+					dm_EndHWFsync(dev);
+					dm_StartSWFsync(dev);
+					priv->rtllib->fsync_state = SW_Fsync;
+					break;
+				case SW_Fsync:
+				default:
+					break;
+
+			}	
+		}
+		if(priv->framesyncMonitor)
+		{
+			if(reg_c38_State != RegC38_Fsync_AP_BCM)
+			{	
+				#ifdef RTL8190P
+					write_nic_byte(dev, rOFDM0_RxDetector3, 0x15);
+				#else
+					write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
+				#endif
+				
+				reg_c38_State = RegC38_Fsync_AP_BCM;
+			}
+		}
+	}
+	else
+	{
+		switch(priv->rtllib->fsync_state)
+		{
+			case HW_Fsync:
+				dm_EndHWFsync(dev);
+				priv->rtllib->fsync_state = Default_Fsync;
+				break;
+			case SW_Fsync:
+				dm_EndSWFsync(dev);
+				priv->rtllib->fsync_state = Default_Fsync;
+				break;
+			case Default_Fsync:
+			default:
+				break;
+		}
+		
+		if(priv->framesyncMonitor)
+		{
+			if(priv->rtllib->state == RTLLIB_LINKED)
+			{
+				if(priv->undecorated_smoothed_pwdb <= RegC38_TH)
+				{
+					if(reg_c38_State != RegC38_NonFsync_Other_AP)
+					{
+						#ifdef RTL8190P
+							write_nic_byte(dev, rOFDM0_RxDetector3, 0x10);
+						#else
+							write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
+						#endif
+						
+						reg_c38_State = RegC38_NonFsync_Other_AP;
+					#if 0
+						if (dev->HardwareType == HARDWARE_TYPE_RTL8190P)
+							DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x10);
+						else
+							DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x90);
+					#endif
+					}
+				}
+				else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5))
+				{
+					if(reg_c38_State)
+					{
+						write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+						reg_c38_State = RegC38_Default;
+					}	
+				}
+			}
+			else
+			{
+				if(reg_c38_State)
+				{
+					write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+					reg_c38_State = RegC38_Default;
+				}
+			}
+		}
+	}	
+	if(priv->framesyncMonitor)
+	{
+		if(priv->reset_count != reset_cnt)
+		{	
+			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+			reg_c38_State = RegC38_Default;
+			reset_cnt = priv->reset_count;
+		}
+	}
+	else
+	{
+		if(reg_c38_State)
+		{
+			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+			reg_c38_State = RegC38_Default;
+		}
+	}		
+}
+
+#if 0
+extern	s1Byte	DM_CheckLBusStatus(IN	PADAPTER	dev)
+{
+	PMGNT_INFO	pMgntInfo=&dev->MgntInfo;
+
+#if (HAL_CODE_BASE & RTL819X)
+	
+#if (HAL_CODE_BASE == RTL8192)
+
+#if( DEV_BUS_TYPE==PCI_INTERFACE)
+	return true;
+#endif
+
+#if( DEV_BUS_TYPE==USB_INTERFACE)
+	return true;
+#endif
+
+#endif	
+
+#if (HAL_CODE_BASE == RTL8190)
+	return true;
+#endif	
+
+#endif	
+}	
+
+#endif
+
+extern void dm_shadow_init(struct net_device *dev)
+{
+	u8	page;
+	u16	offset;
+
+	for (page = 0; page < 5; page++)
+		for (offset = 0; offset < 256; offset++)
+		{
+			dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256);
+		}
+
+	for (page = 8; page < 11; page++)
+		for (offset = 0; offset < 256; offset++)
+			dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256);
+
+	for (page = 12; page < 15; page++)
+		for (offset = 0; offset < 256; offset++)
+			dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256);
+
+}   
+
+/*---------------------------Define function prototype------------------------*/
+static void dm_init_dynamic_txpower(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+#ifdef RTL8192SE
+	if(((priv->pFirmware->FirmwareVersion) >= 60) && 
+		(priv->DM_Type == DM_Type_ByDriver)){
+		priv->rtllib->bdynamic_txpower_enable = true; 
+		RT_TRACE(COMP_INIT, "Dynamic Tx Power is enabled by Driver \n");
+	} else {
+		priv->rtllib->bdynamic_txpower_enable = false; 
+		RT_TRACE(COMP_INIT, "Dynamic Tx Power is enabled by FW \n");
+	}
+	
+	priv->LastDTPLvl = TxHighPwrLevel_Normal;
+	priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+	
+#elif defined RTL8190P || defined RTL8192E
+	priv->rtllib->bdynamic_txpower_enable = true;    
+	priv->bLastDTPFlag_High = false;
+	priv->bLastDTPFlag_Low = false;
+	priv->bDynamicTxHighPower = false;
+	priv->bDynamicTxLowPower = false;
+#endif
+}
+
+#if defined RTL8190P || defined RTL8192E
+static void dm_dynamic_txpower(struct net_device *dev)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned int txhipower_threshhold=0;	
+        unsigned int txlowpower_threshold=0;
+	if(priv->rtllib->bdynamic_txpower_enable != true)
+	{
+		priv->bDynamicTxHighPower = false;
+		priv->bDynamicTxLowPower = false;
+		return;
+	}
+        if((priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) && (priv->rtllib->mode == IEEE_G)){
+		txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
+		txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
+	}
+	else
+	{
+		txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
+		txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; 
+	}
+
+
+	RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb);
+
+	if(priv->rtllib->state == RTLLIB_LINKED)
+	{
+		if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold)
+		{
+			priv->bDynamicTxHighPower = true;
+			priv->bDynamicTxLowPower = false;
+		}
+		else
+		{
+			if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true)
+			{
+				priv->bDynamicTxHighPower = false;
+			}
+			if(priv->undecorated_smoothed_pwdb < 35)
+			{
+				priv->bDynamicTxLowPower = true;
+			}
+			else if(priv->undecorated_smoothed_pwdb >= 40)
+			{
+				priv->bDynamicTxLowPower = false;
+			}
+		}
+	}
+	else
+	{
+		priv->bDynamicTxHighPower = false;
+		priv->bDynamicTxLowPower = false;
+	}
+
+	if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) ||
+		(priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) )
+	{
+		RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190()  channel = %d \n" , priv->rtllib->current_network.channel);
+		
+		rtl8192_phy_setTxPower(dev,priv->rtllib->current_network.channel); 
+	}
+	priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
+	priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
+
+}	
+#elif defined RTL8192SE
+static void dm_dynamic_txpower(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	long				UndecoratedSmoothedPWDB;
+
+	if( (priv->rtllib->bdynamic_txpower_enable != true) ||
+			(priv->DMFlag & HAL_DM_HIPWR_DISABLE) ||
+			priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER) {
+		priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+		return;
+	}
+
+	if((!priv->rtllib->state != RTLLIB_LINKED) &&	
+		(priv->EntryMinUndecoratedSmoothedPWDB == 0)) {
+		RT_TRACE(COMP_POWER, "Not connected to any \n");
+		priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+		return;
+	}
+	
+	if(priv->rtllib->state == RTLLIB_LINKED) {
+		if(priv->OpMode == RT_OP_MODE_IBSS) {
+			UndecoratedSmoothedPWDB = priv->EntryMinUndecoratedSmoothedPWDB;
+			RT_TRACE(COMP_POWER, "AP Client PWDB = %ld \n", UndecoratedSmoothedPWDB);
+		} else {
+			UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb;
+			RT_TRACE(COMP_POWER, "STA Default Port PWDB = %ld \n", UndecoratedSmoothedPWDB);
+		}
+	} else {
+		UndecoratedSmoothedPWDB = priv->EntryMinUndecoratedSmoothedPWDB;
+		RT_TRACE(COMP_POWER, "AP Ext Port PWDB = %ld \n", UndecoratedSmoothedPWDB);
+	}
+		
+	if(UndecoratedSmoothedPWDB >= TX_POWER_NEAR_FIELD_THRESH_LVL2)	{
+		priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Level2;
+		RT_TRACE(COMP_POWER, "TxHighPwrLevel_Level2 (TxPwr=0x0)\n");
+	} else if((UndecoratedSmoothedPWDB < (TX_POWER_NEAR_FIELD_THRESH_LVL2-3)) &&
+		(UndecoratedSmoothedPWDB >= TX_POWER_NEAR_FIELD_THRESH_LVL1) ) {
+		priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Level1;
+		RT_TRACE(COMP_POWER, "TxHighPwrLevel_Level1 (TxPwr=0x10)\n");
+	} else if(UndecoratedSmoothedPWDB < (TX_POWER_NEAR_FIELD_THRESH_LVL1-3)) {
+		priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+		RT_TRACE(COMP_POWER, "TxHighPwrLevel_Normal\n");
+	}
+
+	if( (priv->DynamicTxHighPowerLvl != priv->LastDTPLvl) ) {
+		RT_TRACE(COMP_POWER, "PHY_SetTxPowerLevel8192S() Channel = %d \n" , priv->rtllib->current_network.channel);
+		rtl8192_phy_setTxPower(dev, priv->rtllib->current_network.channel);
+	}
+	priv->LastDTPLvl = priv->DynamicTxHighPowerLvl;
+}	
+#endif
+
+static void dm_check_txrateandretrycount(struct net_device * dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	
+#ifdef RTL8192SE
+	static u8 LegacyRateSet[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c};
+	u8 RateIdx = 0;
+	RateIdx = read_nic_byte(dev, TX_RATE_REG);
+	
+	if(ieee->softmac_stats.CurrentShowTxate < 76)
+		ieee->softmac_stats.CurrentShowTxate = (RateIdx<12)?(LegacyRateSet[RateIdx]):((RateIdx-12)|0x80);
+	else
+		ieee->softmac_stats.CurrentShowTxate = 0;
+#else
+	ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);
+#endif
+
+	ieee->softmac_stats.last_packet_rate = read_nic_byte(dev ,Initial_Tx_Rate_Reg);	
+
+	ieee->softmac_stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);	
+}
+
+static void dm_send_rssi_tofw(struct net_device *dev)
+{
+#ifndef RTL8192SE
+	DCMD_TXCMD_T			tx_cmd;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
+	return;
+	tx_cmd.Op		= TXCMD_SET_RX_RSSI;
+	tx_cmd.Length	= 4;
+	tx_cmd.Value		= priv->undecorated_smoothed_pwdb;
+
+	cmpk_message_handle_tx(dev, (u8*)&tx_cmd, 
+								DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
+#endif
+}
+
+#if defined RTL8192SE
+/*-----------------------------------------------------------------------------
+ * Function:	dm_RefreshRateAdaptiveMask()
+ *
+ * Overview:	Update rate table mask according to rssi
+ *
+ * Input:		NONE
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/27/2009	hpfan	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+static void dm_RefreshRateAdaptiveMask(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	prate_adaptive	pRA = (prate_adaptive)&priv->rate_adaptive;
+	u32	LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
+	u8	rssi_level;
+	
+	if(IS_NIC_DOWN(priv)){
+		RT_TRACE(COMP_RATE,"<---- dm_RefreshRateAdaptiveMask(): driver is going to unload\n");
+		return;
+	}
+
+	if(!priv->rtllib->bUseRAMask){
+		return;
+	}
+
+	if(priv->pFirmware->FirmwareVersion >= 61 && !priv->bInformFWDriverControlDM){
+		RT_TRACE(COMP_RATE, "<---- dm_RefreshRateAdaptiveMask(): inform fw driver control dm\n");
+		priv->rtllib->SetFwCmdHandler(dev, FW_CMD_CTRL_DM_BY_DRIVER);
+		priv->bInformFWDriverControlDM = true;
+	}
+		
+	if((priv->rtllib->state == RTLLIB_LINKED && (priv->rtllib->iw_mode == IW_MODE_INFRA)) 
+#ifdef _RTL8192_EXT_PATCH_			
+		|| ((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0))
+#endif		
+		)
+	{
+		
+		switch (pRA->PreRATRState){
+			case DM_RATR_STA_HIGH:
+				HighRSSIThreshForRA = 50;
+				LowRSSIThreshForRA = 20;
+				break;
+			case DM_RATR_STA_MIDDLE:
+				HighRSSIThreshForRA = 55;
+				LowRSSIThreshForRA = 20;
+				break;
+			case DM_RATR_STA_LOW:
+				HighRSSIThreshForRA = 50;
+				LowRSSIThreshForRA = 25;
+				break;
+			default:
+				HighRSSIThreshForRA = 50;
+				LowRSSIThreshForRA = 20;
+				break;
+		}
+
+		if(priv->undecorated_smoothed_pwdb > (long)HighRSSIThreshForRA){
+			pRA->ratr_state = DM_RATR_STA_HIGH;
+			rssi_level = 1;
+		}
+		else if(priv->undecorated_smoothed_pwdb > (long)LowRSSIThreshForRA){
+			pRA->ratr_state = DM_RATR_STA_MIDDLE;
+			rssi_level = 2;
+		}else{
+			pRA->ratr_state = DM_RATR_STA_LOW;
+			rssi_level = 3;
+		}
+		if((pRA->PreRATRState != pRA->ratr_state) || ((pRA->PreRATRState == pRA->ratr_state) && (rssi_level != priv->rssi_level)))
+		{
+			RT_TRACE(COMP_RATE, "Target AP addr : "MAC_FMT"\n", MAC_ARG(priv->rtllib->current_network.bssid));
+			RT_TRACE(COMP_RATE, "RSSI = %ld\n", priv->undecorated_smoothed_pwdb);
+			RT_TRACE(COMP_RATE, "RSSI_LEVEL = %d\n", rssi_level);
+			RT_TRACE(COMP_RATE, "PreState = %d, CurState = %d\n", pRA->PreRATRState, pRA->ratr_state);
+			priv->rtllib->UpdateHalRAMaskHandler(
+									dev,
+									false,
+									0,
+									priv->rtllib->pHTInfo->PeerMimoPs,
+									priv->rtllib->mode,
+									priv->rtllib->pHTInfo->bCurTxBW40MHz,
+									rssi_level);
+			priv->rssi_level = rssi_level;
+			pRA->PreRATRState = pRA->ratr_state;
+		}
+	}
+	if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC)){
+		int	i;
+		struct sta_info *pEntry;
+
+		for(i = 0; i < PEER_MAX_ASSOC; i++){
+			pEntry = priv->rtllib->peer_assoc_list[i];
+			if(NULL != pEntry){
+				pRA = &pEntry->rate_adaptive;
+				switch (pRA->PreRATRState){
+					case DM_RATR_STA_HIGH:
+						HighRSSIThreshForRA = 50;
+						LowRSSIThreshForRA = 20;
+						break;
+					case DM_RATR_STA_MIDDLE:
+						HighRSSIThreshForRA = 55;
+						LowRSSIThreshForRA = 20;
+						break;
+					case DM_RATR_STA_LOW:
+						HighRSSIThreshForRA = 50;
+						LowRSSIThreshForRA = 25;
+						break;
+					default:
+						HighRSSIThreshForRA = 50;
+						LowRSSIThreshForRA = 20;
+						break;
+				}
+
+				if(pEntry->rssi_stat.UndecoratedSmoothedPWDB > HighRSSIThreshForRA){
+					pRA->ratr_state = DM_RATR_STA_HIGH;
+					rssi_level = 1;
+				}else if(pEntry->rssi_stat.UndecoratedSmoothedPWDB > LowRSSIThreshForRA){
+					pRA->ratr_state = DM_RATR_STA_MIDDLE;
+					rssi_level = 2;
+				}else{
+					pRA->ratr_state = DM_RATR_STA_LOW;
+					rssi_level = 3;
+				}
+
+				if(pRA->PreRATRState != pRA->ratr_state){
+					RT_TRACE(COMP_RATE, "AsocEntry addr : "MAC_FMT"\n", MAC_ARG(pEntry->macaddr));
+					RT_TRACE(COMP_RATE, "RSSI = %ld\n", pEntry->rssi_stat.UndecoratedSmoothedPWDB);
+					RT_TRACE(COMP_RATE, "RSSI_LEVEL = %d\n", rssi_level);
+					RT_TRACE(COMP_RATE, "PreState = %d, CurState = %d\n", pRA->PreRATRState, pRA->ratr_state);
+					priv->rtllib->UpdateHalRAMaskHandler(
+											dev,
+											false,
+											pEntry->aid+1,
+											pEntry->htinfo.MimoPs,
+											pEntry->wireless_mode,
+											pEntry->htinfo.bCurTxBW40MHz,
+											rssi_level);
+					pRA->PreRATRState = pRA->ratr_state;
+				}
+
+			}
+		}
+	}
+#ifdef _RTL8192_EXT_PATCH_			
+	if(priv->rtllib->iw_mode == IW_MODE_MESH)
+	{
+		if(priv->mshobj->ext_refresh_rate_adaptive_mask)
+			priv->mshobj->ext_refresh_rate_adaptive_mask(priv);
+	}
+#endif
+}
+
+void Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info  *pEntry)
+{
+	prate_adaptive	pRA = (prate_adaptive)&pEntry->rate_adaptive;
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	pRA->ratr_state = DM_RATR_STA_MAX;
+	pRA->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
+	pRA->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
+	pRA->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
+
+	pRA->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
+	pRA->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
+	pRA->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
+	
+	if (priv->rf_type == RF_2T4R)
+	{
+		/* 2008/01/11 MH Modify 2T RATR table for different RSSI. */
+		pRA->upper_rssi_threshold_ratr		= 	0x8f0f0000;
+		pRA->middle_rssi_threshold_ratr		= 	0x8d0ff000;
+		pRA->low_rssi_threshold_ratr		= 	0x8f0ff003;
+		pRA->low_rssi_threshold_ratr_40M	= 	0x8f0ff007;
+		pRA->low_rssi_threshold_ratr_20M	= 	0x8f0ff003;
+	}
+	else if (priv->rf_type == RF_1T2R)
+	{
+		pRA->upper_rssi_threshold_ratr		= 	0x000f0000;		
+		pRA->middle_rssi_threshold_ratr		= 	0x000ff000;
+		pRA->low_rssi_threshold_ratr		= 	0x000ff003;
+		pRA->low_rssi_threshold_ratr_40M	= 	0x000ff007;
+		pRA->low_rssi_threshold_ratr_20M	= 	0x000ff003;
+	}
+	
+}	
+
+
+void Adhoc_InitRateAdaptiveState(struct net_device *dev,struct sta_info  *pEntry)
+{
+	prate_adaptive	pRA = (prate_adaptive)&pEntry->rate_adaptive;
+
+	pRA->ratr_state = DM_RATR_STA_MAX;
+	pRA->PreRATRState = DM_RATR_STA_MAX;
+}
+
+#if 0
+static void Adhoc_dm_CheckRateAdaptive(struct net_device * dev)
+{
+	struct r8192_priv 			*priv = rtllib_priv(dev);
+	struct rtllib_device 	*ieee = priv->rtllib;
+	prate_adaptive			pRA;
+	u32						currentRATR, targetRATR = 0;
+	u32						LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
+	bool						bShortGIEnabled = false;
+	u8 						i = 0;
+	struct sta_info 			*pEntry = NULL;
+	
+	if(!priv->up)
+	{
+		RT_TRACE(COMP_RATE, "<---- AP_dm_CheckRateAdaptive(): driver is going to unload\n");
+		return;
+	}
+
+	for(i=0;i<PEER_MAX_ASSOC; i++)
+	{
+		pEntry = ieee->peer_assoc_list[i];
+		if(NULL != pEntry)
+		{
+			pRA = (prate_adaptive)&pEntry->rate_adaptive;
+			if(pRA->rate_adaptive_disabled)
+				continue;			
+			if((pEntry->wireless_mode!=WIRELESS_MODE_N_24G) && (pEntry->wireless_mode != WIRELESS_MODE_N_5G))
+				continue;
+			bShortGIEnabled = (pEntry->htinfo.bCurTxBW40MHz && priv->rtllib->pHTInfo->bCurShortGI40MHz && pEntry->htinfo.bCurShortGI40MHz) |
+				(!pEntry->htinfo.bCurTxBW40MHz && priv->rtllib->pHTInfo->bCurShortGI20MHz && pEntry->htinfo.bCurShortGI20MHz);
+			pRA->upper_rssi_threshold_ratr =
+				(pRA->upper_rssi_threshold_ratr & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ;
+
+			pRA->middle_rssi_threshold_ratr = 
+				(pRA->middle_rssi_threshold_ratr & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ;
+			
+
+			if (pEntry->htinfo.bBw40MHz)
+			{
+				pRA->low_rssi_threshold_ratr = 
+					(pRA->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ;
+			}
+			else
+			{
+				pRA->low_rssi_threshold_ratr = 
+					(pRA->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ;
+			}
+			if (pRA->ratr_state == DM_RATR_STA_HIGH)
+			{
+				HighRSSIThreshForRA 	= pRA->high2low_rssi_thresh_for_ra;
+				LowRSSIThreshForRA	= 
+					(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pRA->low_rssi_thresh_for_ra40M):(pRA->low_rssi_thresh_for_ra20M);
+			}
+			else if (pRA->ratr_state == DM_RATR_STA_LOW)
+			{
+				HighRSSIThreshForRA	= pRA->high_rssi_thresh_for_ra;
+				LowRSSIThreshForRA 	= 
+					(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pRA->low2high_rssi_thresh_for_ra40M):(pRA->low2high_rssi_thresh_for_ra20M);
+			}
+			else
+			{
+				HighRSSIThreshForRA	= pRA->high_rssi_thresh_for_ra;
+				LowRSSIThreshForRA	= 
+					(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
+					(pRA->low_rssi_thresh_for_ra40M):(pRA->low_rssi_thresh_for_ra20M);
+			}
+			if(priv->undecorated_smoothed_pwdb >= (int)HighRSSIThreshForRA)
+			{
+				pRA->ratr_state = DM_RATR_STA_HIGH;
+				targetRATR = pRA->upper_rssi_threshold_ratr;
+			}
+			else if(priv->undecorated_smoothed_pwdb >= (int)LowRSSIThreshForRA)
+			{
+				pRA->ratr_state = DM_RATR_STA_MIDDLE;
+				targetRATR = pRA->middle_rssi_threshold_ratr;
+			}
+			else
+			{
+				pRA->ratr_state = DM_RATR_STA_LOW;
+				targetRATR = pRA->low_rssi_threshold_ratr;
+			}
+			currentRATR = read_nic_dword(dev, pEntry->ratr_index*4 + RATR0);
+			if( targetRATR !=  currentRATR )
+			{
+				if(priv->rf_type == RF_1T2R)	
+				{	
+					targetRATR &=~ (RATE_ALL_OFDM_2SS);
+				}
+				printk("<<<<<<<<<<<currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);				
+				write_nic_dword(dev, RATR0+pEntry->ratr_index*4, targetRATR);
+				write_nic_byte(dev, UFWP, 1);
+				pRA->last_ratr = targetRATR;
+			}
+		}
+	}
+	
+}	
+#endif
+
+#endif
+/*---------------------------Define function prototype------------------------*/
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_regd.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_regd.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the ath driver, which is:
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#ifndef RTL_REGD_H
+#define RTL_REGD_H
+
+#ifdef CONFIG_CFG_80211 
+
+#include <linux/nl80211.h>
+#include <net/cfg80211.h>
+#include "rtl_core.h"
+
+struct r8192_priv;
+
+struct country_code_to_enum_rd {
+	u16 countryCode;
+	const char *isoName;
+};
+
+
+int rtl_regd_init(struct net_device *dev,
+		  int (*reg_notifier)(struct wiphy *wiphy,
+		  struct regulatory_request *request));
+int rtl_reg_notifier(struct wiphy *wiphy,
+		     struct regulatory_request *request);
+void rtl_dump_channel_map(struct wiphy *wiphy);
+int rtllib_set_geo(struct r8192_priv *priv);
+bool rtl8192_register_wiphy_dev(struct net_device *dev);
+
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_eeprom.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_eeprom.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+
+#define EPROM_DELAY 10
+#if 0
+#define EPROM_ANAPARAM_ADDRLWORD 0xd 
+#define EPROM_ANAPARAM_ADDRHWORD 0xe 
+
+#define EPROM_RFCHIPID 0x6
+#define EPROM_TXPW_BASE 0x05
+#define EPROM_RFCHIPID_RTL8225U 5 
+#define EPROM_RF_PARAM 0x4
+#define EPROM_CONFIG2 0xc
+
+#define EPROM_VERSION 0x1E
+#define MAC_ADR 0x7
+
+#define CIS 0x18 
+
+#define EPROM_TXPW0 0x16 
+#define EPROM_TXPW2 0x1b
+#define EPROM_TXPW1 0x3d
+#endif
+
+u32 eprom_read(struct net_device *dev,u32 addr); 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_wx.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_wx.c
@@ -0,0 +1,4231 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include <linux/string.h>
+#include "rtl_core.h"
+#ifdef ENABLE_DOT11D
+#include "rtllib/dot11d.h"
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+#include "../../mshclass/msh_class.h"
+#endif
+
+#ifdef CONFIG_MP
+#include "r8192S_mp.h"
+#endif
+
+#define RATE_COUNT 12
+u32 rtl8192_rates[] = {1000000,2000000,5500000,11000000,
+	6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
+	
+
+#ifndef ENETDOWN
+#define ENETDOWN 1
+#endif
+extern int  hwwep;
+#ifdef _RTL8192_EXT_PATCH_
+int r8192_wx_set_channel(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra);
+static int r8192_wx_mesh_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra);
+static int r8192_wx_get_mesh_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra);
+#endif
+
+static int r8192_wx_get_freq(struct net_device *dev,
+			     struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	return rtllib_wx_get_freq(priv->rtllib,a,wrqu,b,0);
+#else
+	return rtllib_wx_get_freq(priv->rtllib,a,wrqu,b);
+#endif
+}
+
+
+#if 0
+
+static int r8192_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa,
+			  union iwreq_data *wrqu, char *b)
+{
+	int *parms = (int *)b;
+	int bi = parms[0];
+	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	down(&priv->wx_sem);
+	DMESG("setting beacon interval to %x",bi);
+	
+	priv->rtllib->beacon_interval=bi;
+	rtl8192_commit(dev);
+	up(&priv->wx_sem);
+		
+	return 0;	
+}
+
+
+static int r8192_wx_set_forceassociate(struct net_device *dev, struct iw_request_info *aa,
+			  union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv=rtllib_priv(dev);	
+	int *parms = (int *)extra;
+	
+	priv->rtllib->force_associate = (parms[0] > 0);
+	
+
+	return 0;
+}
+
+#endif
+static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv=rtllib_priv(dev);	
+
+	return rtllib_wx_get_mode(priv->rtllib,a,wrqu,b);
+}
+
+static int r8192_wx_get_rate(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	return rtllib_wx_get_rate(priv->rtllib,info,wrqu,extra);
+}
+
+
+
+static int r8192_wx_set_rate(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	
+	if(priv->bHwRadioOff == true)
+		return 0;	
+	
+	down(&priv->wx_sem);
+
+	ret = rtllib_wx_set_rate(priv->rtllib,info,wrqu,extra);
+	
+	up(&priv->wx_sem);
+	
+	return ret;
+}
+
+
+static int r8192_wx_set_rts(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	
+	if(priv->bHwRadioOff == true)
+		return 0;	
+	
+	down(&priv->wx_sem);
+
+	ret = rtllib_wx_set_rts(priv->rtllib,info,wrqu,extra);
+	
+	up(&priv->wx_sem);
+	
+	return ret;
+}
+
+static int r8192_wx_get_rts(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	return rtllib_wx_get_rts(priv->rtllib,info,wrqu,extra);
+}
+
+static int r8192_wx_set_power(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	
+	if(priv->bHwRadioOff == true){
+		RT_TRACE(COMP_ERR,"%s():Hw is Radio Off, we can't set Power,return\n",__FUNCTION__);
+		return 0;
+	}
+	down(&priv->wx_sem);
+
+	ret = rtllib_wx_set_power(priv->rtllib,info,wrqu,extra);
+	
+	up(&priv->wx_sem);
+	
+	return ret;
+}
+
+static int r8192_wx_get_power(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	return rtllib_wx_get_power(priv->rtllib,info,wrqu,extra);
+}
+
+static int r8192_wx_set_rawtx(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret;
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	down(&priv->wx_sem);
+	
+	ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra);
+	
+	up(&priv->wx_sem);
+	
+	return ret;
+	 
+}
+
+static int r8192_wx_force_reset(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	down(&priv->wx_sem);
+
+	printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
+	priv->force_reset = *extra;
+	up(&priv->wx_sem);
+	return 0;
+
+}
+
+static int r8192_wx_force_mic_error(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	
+	down(&priv->wx_sem);
+
+	printk("%s(): force mic error ! \n",__FUNCTION__);
+	ieee->force_mic_error = true;
+	up(&priv->wx_sem);
+	return 0;
+
+}
+
+#define MAX_ADHOC_PEER_NUM 64 
+typedef struct 
+{
+	unsigned char MacAddr[ETH_ALEN];
+	unsigned char WirelessMode;
+	unsigned char bCurTxBW40MHz;		
+} adhoc_peer_entry_t, *p_adhoc_peer_entry_t;
+typedef struct 
+{
+	adhoc_peer_entry_t Entry[MAX_ADHOC_PEER_NUM];
+	unsigned char num;
+} adhoc_peers_info_t, *p_adhoc_peers_info_t;
+int r8192_wx_get_adhoc_peers(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+#ifndef RTL8192SE 
+	return 0;
+#else
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct sta_info * psta = NULL;
+	adhoc_peers_info_t adhoc_peers_info;
+	p_adhoc_peers_info_t  padhoc_peers_info = &adhoc_peers_info; 
+	p_adhoc_peer_entry_t padhoc_peer_entry = NULL;
+	int k=0;
+
+
+	memset(extra, 0, 2047);
+	padhoc_peers_info->num = 0;
+
+	down(&priv->wx_sem);
+
+	for(k=0; k<PEER_MAX_ASSOC; k++)
+	{
+		psta = priv->rtllib->peer_assoc_list[k];
+		if(NULL != psta)
+		{
+			padhoc_peer_entry = &padhoc_peers_info->Entry[padhoc_peers_info->num];
+			memset(padhoc_peer_entry,0, sizeof(adhoc_peer_entry_t));
+			memcpy(padhoc_peer_entry->MacAddr, psta->macaddr, ETH_ALEN);
+			padhoc_peer_entry->WirelessMode = psta->wireless_mode;
+			padhoc_peer_entry->bCurTxBW40MHz = psta->htinfo.bCurTxBW40MHz;
+			padhoc_peers_info->num ++;
+			printk("[%d] MacAddr:"MAC_FMT" \tWirelessMode:%d \tBW40MHz:%d \n", \
+				k, MAC_ARG(padhoc_peer_entry->MacAddr), padhoc_peer_entry->WirelessMode, padhoc_peer_entry->bCurTxBW40MHz);
+			sprintf(extra, "[%d] MacAddr:"MAC_FMT" \tWirelessMode:%d \tBW40MHz:%d \n",  \
+				k, MAC_ARG(padhoc_peer_entry->MacAddr), padhoc_peer_entry->WirelessMode, padhoc_peer_entry->bCurTxBW40MHz);
+		}
+	}
+
+	up(&priv->wx_sem);
+
+	wrqu->data.length = strlen(extra);
+	wrqu->data.flags = 0;
+	return 0;
+
+#endif
+}
+
+
+static int r8191se_wx_get_firm_version(struct net_device *dev,
+		struct iw_request_info *info,
+		struct iw_param *wrqu, char *extra)
+{
+#if defined RTL8192SE || defined RTL8192CE
+        struct r8192_priv *priv = rtllib_priv(dev);
+	u16 firmware_version;
+
+	down(&priv->wx_sem);
+	printk("%s(): Just Support 92SE tmp\n", __FUNCTION__);
+#ifdef RTL8192CE
+	firmware_version = priv->firmware_version;
+#else
+	firmware_version = priv->pFirmware->FirmwareVersion;
+#endif
+	wrqu->value = firmware_version;
+	wrqu->fixed = 1;
+
+	up(&priv->wx_sem);
+#endif
+	return 0;
+}
+
+static int r8192_wx_adapter_power_status(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+#ifdef ENABLE_LPS
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	struct rtllib_device* ieee = priv->rtllib;
+
+	down(&priv->wx_sem);
+
+	RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
+	if(*extra || priv->force_lps) {
+		priv->ps_force = false;
+		pPSC->bLeisurePs = true;
+	} else {	
+		if(priv->rtllib->state == RTLLIB_LINKED)
+			LeisurePSLeave(dev);
+	
+		priv->ps_force = true;
+		pPSC->bLeisurePs = false;
+		ieee->ps = *extra;	
+	}
+
+	up(&priv->wx_sem);
+#endif
+
+	return 0;
+
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+static int r8192_wx_print_reg(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	u8 reg1=0,reg2=0,reg3=0,reg4=0;
+	u32 reg5 = 0, len = 0;
+	
+	memset(extra, 0, 512);
+	sprintf(extra,"\nStart Log: Set 0x08000000 to 0x230\n");
+	write_nic_dword(dev, 0x230 , 0x08000000);
+	reg1 = read_nic_byte(dev, 0xf0);
+	reg2 = read_nic_byte(dev, 0xf4);
+	reg3 = read_nic_byte(dev, 0x140);
+	reg4 = read_nic_byte(dev, 0x124);
+	mdelay(10);
+	reg5 = read_nic_dword(dev, 0x230);
+	len = strlen(extra);
+	sprintf(extra+len, "0xf0: %2.2x\n0xf4: %2.2x\n0x140: %2.2x\n0x124: %2.2x\n", reg1,reg2,reg3,reg4);
+	len = strlen(extra);
+	sprintf(extra+len,"After delay 10ms, read 0x230: %8.8x\n", reg5);
+
+	write_nic_dword(dev, 0x230 , 0x40000000);
+	reg5 = read_nic_dword(dev, 0x230);
+	len = strlen(extra);
+	sprintf(extra+len,"Set 0x40000000 to 0x230. Read 0x230: %8.8x\n", reg5);
+
+	write_nic_dword(dev, 0x230 , 0x80000000);
+	reg5 = read_nic_dword(dev, 0x230);
+	len = strlen(extra);
+	sprintf(extra+len,"Set 0x80000000 to 0x230. Read 0x230: %8.8x\n", reg5);
+
+	wrqu->data.length = strlen(extra);
+	return 0;
+}
+
+static int r8192_wx_resume_firm(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+
+	write_nic_byte(dev, 0x42, 0xFF);
+	write_nic_word(dev, 0x40, 0x77FC);
+	write_nic_word(dev, 0x40, 0x57FC);
+	write_nic_word(dev, 0x40, 0x37FC);
+	write_nic_word(dev, 0x40, 0x77FC);
+	
+	udelay(100);
+
+	write_nic_word(dev, 0x40, 0x57FC);
+	write_nic_word(dev, 0x40, 0x37FC);
+	write_nic_byte(dev, 0x42, 0x00);
+
+	return 0;
+}
+#endif
+static int r8192se_wx_set_radio(struct net_device *dev,
+        struct iw_request_info *info,
+        union iwreq_data *wrqu, char *extra)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+
+    down(&priv->wx_sem);
+
+    printk("%s(): set radio ! extra is %d\n",__FUNCTION__, *extra);
+    if((*extra != 0) && (*extra != 1))
+    {
+        RT_TRACE(COMP_ERR, "%s(): set radio an err value,must 0(radio off) or 1(radio on)\n",__FUNCTION__);
+        return -1;
+    }
+    priv->sw_radio_on = *extra;
+    up(&priv->wx_sem);
+    return 0;
+
+}
+
+static int r8192se_wx_set_lps_awake_interval(struct net_device *dev,
+        struct iw_request_info *info,
+        union iwreq_data *wrqu, char *extra)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+    PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+
+    down(&priv->wx_sem);
+
+    printk("%s(): set lps awake interval ! extra is %d\n",__FUNCTION__, *extra);
+
+    pPSC->RegMaxLPSAwakeIntvl = *extra;
+    up(&priv->wx_sem);
+    return 0;
+
+}
+
+static int r8192se_wx_set_force_lps(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	down(&priv->wx_sem);
+
+	printk("%s(): force LPS ! extra is %d (1 is open 0 is close)\n",__FUNCTION__, *extra);
+	priv->force_lps = *extra;
+	up(&priv->wx_sem);
+	return 0;
+
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+static int r8192_wx_get_drv_version(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	memset(extra, 0, 64);
+	sprintf(extra, "Support Mesh");
+
+	((struct iw_point *)wrqu)->length = strlen(extra);
+	return 0;
+}
+#endif
+
+static int r8192_wx_set_debugflag(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 c = *extra;
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	printk("=====>%s(), *extra:%x, debugflag:%x\n", __FUNCTION__, *extra, rt_global_debug_component);
+	if (c > 0)  {
+		rt_global_debug_component |= (1<<c);
+	} else {
+		rt_global_debug_component &= BIT31; 
+	}
+	return 0;
+}
+
+static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = netdev_priv_rsl(dev);
+
+	RT_RF_POWER_STATE	rtState;
+	int ret;
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+#ifdef _RTL8192_EXT_PATCH_
+	if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)) {
+		return 0;	
+	}
+#endif
+	rtState = priv->rtllib->eRFPowerState;
+	down(&priv->wx_sem);
+#ifdef ENABLE_IPS	
+	if(wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR
+		|| ieee->bNetPromiscuousMode )
+	{
+		if(priv->rtllib->PowerSaveControl.bInactivePs){ 
+			if(rtState == eRfOff){
+				if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+				{
+					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+					up(&priv->wx_sem);
+					return -1;
+				} else {
+					printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					down(&priv->rtllib->ips_sem);
+					IPSLeave(dev);
+					up(&priv->rtllib->ips_sem);				
+				}
+			}
+		}
+	}
+#endif
+	ret = rtllib_wx_set_mode(priv->rtllib,a,wrqu,b);
+
+	up(&priv->wx_sem);
+	return ret;
+}
+#if defined (RTL8192S_WAPI_SUPPORT)
+int wapi_ioctl_set_mode(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	RT_RF_POWER_STATE	rtState;
+	int ret;
+
+	printk("===============================>%s\n", __FUNCTION__);	
+	if(priv->bHwRadioOff == true)
+		return 0;
+#ifdef _RTL8192_EXT_PATCH_
+	if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)) {
+		return 0;	
+	}
+#endif
+	rtState = priv->rtllib->eRFPowerState;
+#ifdef ENABLE_IPS	
+	if(wrqu->mode == IW_MODE_ADHOC){
+		if(priv->rtllib->PowerSaveControl.bInactivePs){ 
+			if(rtState == eRfOff){
+				if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+				{
+					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+					up(&priv->wx_sem);
+					return -1;
+				} else {
+					printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					down(&priv->rtllib->ips_sem);
+					IPSLeave(dev);
+					up(&priv->rtllib->ips_sem);				
+				}
+			}
+		}
+	}
+#endif
+	ret = rtllib_wx_set_mode(priv->rtllib,a,wrqu,b);
+
+	return ret;
+}
+#endif
+struct  iw_range_with_scan_capa
+{
+        /* Informative stuff (to choose between different interface) */
+        __u32           throughput;     /* To give an idea... */
+        /* In theory this value should be the maximum benchmarked
+         * TCP/IP throughput, because with most of these devices the
+         * bit rate is meaningless (overhead an co) to estimate how
+         * fast the connection will go and pick the fastest one.
+         * I suggest people to play with Netperf or any benchmark...
+         */
+
+        /* NWID (or domain id) */
+        __u32           min_nwid;       /* Minimal NWID we are able to set */
+        __u32           max_nwid;       /* Maximal NWID we are able to set */
+
+        /* Old Frequency (backward compat - moved lower ) */
+        __u16           old_num_channels;
+        __u8            old_num_frequency;
+
+        /* Scan capabilities */
+        __u8            scan_capa;       
+};
+
+static int rtl8192_wx_get_range(struct net_device *dev, 
+				struct iw_request_info *info, 
+				union iwreq_data *wrqu, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16 val;
+	int i;
+
+	wrqu->data.length = sizeof(*range);
+	memset(range, 0, sizeof(*range));
+
+	/* ~130 Mb/s real (802.11n) */
+	range->throughput = 130 * 1000 * 1000;     
+
+	if(priv->rf_set_sens != NULL)
+		range->sensitivity = priv->max_sens;	/* signal level threshold range */
+	
+	range->max_qual.qual = 100;
+	range->max_qual.level = 0;
+	range->max_qual.noise = 0;
+	range->max_qual.updated = 7; /* Updated all three */
+
+	range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = 7; /* Updated all three */
+
+	range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES);
+	
+	for (i = 0; i < range->num_bitrates; i++) {
+		range->bitrate[i] = rtl8192_rates[i];
+	}
+	
+	range->max_rts = DEFAULT_RTS_THRESHOLD;
+	range->min_frag = MIN_FRAG_THRESHOLD;
+	range->max_frag = MAX_FRAG_THRESHOLD;
+	
+	range->min_pmp = 0;
+	range->max_pmp = 5000000;
+	range->min_pmt = 0;
+	range->max_pmt = 65535*1000;	
+	range->pmp_flags = IW_POWER_PERIOD;
+	range->pmt_flags = IW_POWER_TIMEOUT;
+	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 18;
+
+	for (i = 0, val = 0; i < 14; i++) {
+		if ((priv->rtllib->active_channel_map)[i+1]) {
+		        range->freq[val].i = i + 1;
+			range->freq[val].m = rtllib_wlan_frequencies[i] * 100000;
+			range->freq[val].e = 1;
+			val++;
+		} else {
+		}
+		
+		if (val == IW_MAX_FREQUENCIES)
+		break;
+	}
+	range->num_frequency = val;
+	range->num_channels = val;
+#if WIRELESS_EXT > 17
+	range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
+			  IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+	{
+		struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
+		tmp->scan_capa = 0x01;
+	}
+#else
+	range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE;
+#endif
+
+        /* Event capability (kernel + driver) */ 
+
+	return 0;
+}
+
+static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	RT_RF_POWER_STATE	rtState;
+	int ret;
+	
+#ifdef CONFIG_MP
+	printk("######################%s(): In MP Test Can not Scan\n",__FUNCTION__);
+	return 0;
+#endif
+	if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){
+		if((ieee->state >= RTLLIB_ASSOCIATING) && (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)){
+			return 0;
+		}
+		if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->CntAfterLink<2)){
+			return 0;
+		}
+	}
+
+	if(priv->bHwRadioOff == true){
+		printk("================>%s(): hwradio off\n",__FUNCTION__);
+		return 0;
+	}
+	rtState = priv->rtllib->eRFPowerState;
+	if(!priv->up) return -ENETDOWN;
+	if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true)
+		return -EAGAIN;
+
+#ifdef _RTL8192_EXT_PATCH_	
+	if((ieee->iw_mode == IW_MODE_MESH)&&(ieee->mesh_state == RTLLIB_MESH_LINKED))
+	{
+		return 0;
+	}
+#endif
+#if WIRELESS_EXT > 17
+	if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
+	{
+		struct iw_scan_req* req = (struct iw_scan_req*)b;
+		if (req->essid_len)
+		{
+			ieee->current_network.ssid_len = req->essid_len;
+			memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 
+		}
+	}
+#endif	
+
+	down(&priv->wx_sem);
+
+	priv->rtllib->FirstIe_InScan = true;
+
+	if(priv->rtllib->state != RTLLIB_LINKED){
+#ifdef ENABLE_IPS
+		if(priv->rtllib->PowerSaveControl.bInactivePs){ 
+			if(rtState == eRfOff){
+				if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS){
+					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+					up(&priv->wx_sem);
+					return -1;
+				}else{
+					RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",__FUNCTION__);
+					down(&priv->rtllib->ips_sem);
+					IPSLeave(dev);
+					up(&priv->rtllib->ips_sem);				
+				}
+			}
+		}
+#endif
+		rtllib_stop_scan(priv->rtllib);
+		if(priv->rtllib->LedControlHandler)
+			priv->rtllib->LedControlHandler(dev, LED_CTL_SITE_SURVEY);
+		
+                if(priv->rtllib->eRFPowerState != eRfOff){
+			priv->rtllib->actscanning = true;
+			rtllib_start_scan_syncro(priv->rtllib, 0);
+                }
+		ret = 0;
+	} else {
+		priv->rtllib->actscanning = true;
+	ret = rtllib_wx_set_scan(priv->rtllib,a,wrqu,b);
+	}
+	
+	up(&priv->wx_sem);
+	return ret;
+}
+
+
+static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(!priv->up) return -ENETDOWN;
+			
+	if(priv->bHwRadioOff == true)
+		return 0;
+        
+			
+	down(&priv->wx_sem);
+
+	ret = rtllib_wx_get_scan(priv->rtllib,a,wrqu,b);
+		
+	up(&priv->wx_sem);
+	
+	return ret;
+}
+
+static int r8192_wx_set_essid(struct net_device *dev, 
+			      struct iw_request_info *a,
+			      union iwreq_data *wrqu, char *b)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret;
+		
+	if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		;
+	}
+#ifdef CONFIG_MP
+	printk("######################%s(): In MP Test Can not Set Essid\n",__FUNCTION__);
+	return 0;
+#endif
+	if(priv->bHwRadioOff == true){
+		printk("=========>%s():hw radio off,or Rf state is eRfOff, return\n",__FUNCTION__);
+		return 0;
+	}
+	down(&priv->wx_sem);
+	ret = rtllib_wx_set_essid(priv->rtllib,a,wrqu,b);
+
+	up(&priv->wx_sem);
+
+	return ret;
+}
+
+static int r8192_wx_get_essid(struct net_device *dev, 
+			      struct iw_request_info *a,
+			      union iwreq_data *wrqu, char *b)
+{
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	down(&priv->wx_sem);
+	
+	ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b);
+
+	up(&priv->wx_sem);
+	
+	return ret;
+}
+
+static int r8192_wx_set_nick(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+		return -E2BIG;
+	down(&priv->wx_sem);
+	wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick));
+	memset(priv->nick, 0, sizeof(priv->nick));
+	memcpy(priv->nick, extra, wrqu->data.length);
+	up(&priv->wx_sem);
+	return 0;
+
+}
+
+static int r8192_wx_get_nick(struct net_device *dev,
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	down(&priv->wx_sem);
+	wrqu->data.length = strlen(priv->nick);
+	memcpy(extra, priv->nick, wrqu->data.length);
+	wrqu->data.flags = 1;   /* active */
+	up(&priv->wx_sem);
+	return 0;
+}
+
+static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	down(&priv->wx_sem);
+	
+	ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b);
+	
+	up(&priv->wx_sem);
+	return ret;
+}
+
+static int r8192_wx_get_name(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra);
+}
+
+
+static int r8192_wx_set_frag(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	if (wrqu->frag.disabled)
+		priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
+	else {
+		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
+			return -EINVAL;
+		
+		priv->rtllib->fts = wrqu->frag.value & ~0x1;
+	}
+
+	return 0;
+}
+
+
+static int r8192_wx_get_frag(struct net_device *dev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	wrqu->frag.value = priv->rtllib->fts;
+	wrqu->frag.fixed = 0;	/* no auto select */
+	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
+
+	return 0;
+}
+
+
+static int r8192_wx_set_wap(struct net_device *dev,
+			 struct iw_request_info *info,
+			 union iwreq_data *awrq,
+			 char *extra)
+{
+
+	int ret;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		;
+	}
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)){
+		return 0;
+	}
+#endif
+	down(&priv->wx_sem);
+	
+	ret = rtllib_wx_set_wap(priv->rtllib,info,awrq,extra);
+
+	up(&priv->wx_sem);
+
+	return ret;
+	
+}
+	
+
+static int r8192_wx_get_wap(struct net_device *dev, 
+			    struct iw_request_info *info, 
+			    union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	return rtllib_wx_get_wap(priv->rtllib,info,wrqu,extra);
+}
+
+
+static int r8192_wx_get_enc(struct net_device *dev, 
+			    struct iw_request_info *info, 
+			    union iwreq_data *wrqu, char *key)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key,0);
+#else
+	return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key);
+#endif
+}
+
+static int r8192_wx_set_enc(struct net_device *dev, 
+			    struct iw_request_info *info, 
+			    union iwreq_data *wrqu, char *key)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret;
+
+	struct rtllib_device *ieee = priv->rtllib;
+	u32 hwkey[4]={0,0,0,0};
+	u8 mask=0xff;
+	u32 key_idx=0;
+	u8 zero_addr[4][6] ={	{0x00,0x00,0x00,0x00,0x00,0x00},
+				{0x00,0x00,0x00,0x00,0x00,0x01}, 
+				{0x00,0x00,0x00,0x00,0x00,0x02}, 
+				{0x00,0x00,0x00,0x00,0x00,0x03} };
+	int i;
+
+	if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		;
+	}
+#ifdef CONFIG_MP
+	printk("######################%s(): In MP Test Can not Set Enc\n",__FUNCTION__);
+	return 0;
+#endif
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+       if(!priv->up) return -ENETDOWN;
+
+        priv->rtllib->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+        down(&priv->rtllib->ips_sem);
+        IPSLeave(dev);
+        up(&priv->rtllib->ips_sem);			
+#endif
+	down(&priv->wx_sem);
+	
+	RT_TRACE(COMP_SEC, "Setting SW wep key");
+#ifdef _RTL8192_EXT_PATCH_
+	ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key,0);
+#else	
+	ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key);
+#endif
+	up(&priv->wx_sem);
+
+
+	if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
+		ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
+		CamResetAllEntry(dev);
+#ifdef _RTL8192_EXT_PATCH_
+		CamRestoreEachIFEntry(dev,1);
+		reset_IFswcam(dev,0);
+		priv->rtllib->wx_set_enc = 0;
+#else
+		memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+#endif
+		goto end_hw_sec;
+	}
+	if(wrqu->encoding.length!=0){
+
+		for(i=0 ; i<4 ; i++){
+			hwkey[i] |=  key[4*i+0]&mask;
+			if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
+			if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
+			hwkey[i] |= (key[4*i+1]&mask)<<8;
+			hwkey[i] |= (key[4*i+2]&mask)<<16;
+			hwkey[i] |= (key[4*i+3]&mask)<<24;
+		}
+
+		#define CONF_WEP40  0x4
+		#define CONF_WEP104 0x14
+
+		switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
+			case 0: key_idx = ieee->tx_keyidx; break;
+			case 1:	key_idx = 0; break;
+			case 2:	key_idx = 1; break;
+			case 3:	key_idx = 2; break;
+			case 4:	key_idx	= 3; break;
+			default: break;
+		}
+		if(wrqu->encoding.length==0x5){
+		ieee->pairwise_key_type = KEY_TYPE_WEP40;
+			EnableHWSecurityConfig8192(dev);
+#ifndef _RTL8192_EXT_PATCH_
+			setKey( dev,
+				key_idx,                
+				key_idx,                
+				KEY_TYPE_WEP40,         
+				zero_addr[key_idx],
+				0,                      
+				hwkey);                 
+
+			set_swcam( dev,
+				key_idx,                
+				key_idx,                
+				KEY_TYPE_WEP40,         
+				zero_addr[key_idx],
+				0,                      
+				hwkey,                 
+				0);
+
+#endif
+		}
+
+		else if(wrqu->encoding.length==0xd){
+			ieee->pairwise_key_type = KEY_TYPE_WEP104;
+				EnableHWSecurityConfig8192(dev);
+#ifndef _RTL8192_EXT_PATCH_
+			setKey( dev,
+				key_idx,                
+				key_idx,                
+				KEY_TYPE_WEP104,        
+				zero_addr[key_idx],
+				0,                      
+				hwkey);                 
+			set_swcam( dev,
+				key_idx,                
+				key_idx,                
+				KEY_TYPE_WEP104,        
+				zero_addr[key_idx],
+				0,                      
+				hwkey,                 
+				0);
+#endif
+		}
+		else printk("wrong type in WEP, not WEP40 and WEP104\n");
+#ifdef _RTL8192_EXT_PATCH_
+		if(ieee->state == RTLLIB_LINKED){
+			if(ieee->iw_mode == IW_MODE_ADHOC)
+			{
+				
+				setKey( dev,
+						key_idx,                      
+						key_idx,                      
+						ieee->pairwise_key_type,        
+						zero_addr[key_idx],		
+						0,                      
+						hwkey);                 
+				set_swcam( dev,
+						key_idx,                      
+						key_idx,                      
+						ieee->pairwise_key_type,        
+						zero_addr[key_idx],		
+						0,                      
+						hwkey,               
+						0);
+			}
+			else{
+			setKey( dev,
+					31,                      
+					key_idx,                      
+						ieee->pairwise_key_type,        
+					ieee->ap_mac_addr,         
+					0,                      
+					hwkey);                 
+			set_swcam( dev,
+					31,                      
+					key_idx,                      
+						ieee->pairwise_key_type,        
+					ieee->ap_mac_addr,         
+					0,                      
+					hwkey,               
+					0);
+		}
+	}
+#endif
+	}
+
+#if 0
+	if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
+		printk("===>1\n");		
+		EnableHWSecurityConfig8192(dev);
+		key_idx = (wrqu->encoding.flags & 0xf)-1 ;
+		write_cam(dev, (4*6),   0xffff0000|read_cam(dev, key_idx*6) );
+		write_cam(dev, (4*6)+1, 0xffffffff);
+		write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
+		write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
+		write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
+		write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
+	}
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	priv->rtllib->wx_set_enc = 0;
+	printk("===================>%s():set ieee->wx_set_enc 0\n",__FUNCTION__);
+end_hw_sec:
+#else
+end_hw_sec:
+	priv->rtllib->wx_set_enc = 0;
+#endif
+	return ret;
+}
+
+
+static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
+ iwreq_data *wrqu, char *p){
+  
+ 	struct r8192_priv *priv = rtllib_priv(dev);
+	int *parms=(int*)p;
+	int mode=parms[0];
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	priv->rtllib->active_scan = mode;
+	
+	return 1;
+}
+
+
+
+#define R8192_MAX_RETRY 255
+static int r8192_wx_set_retry(struct net_device *dev, 
+				struct iw_request_info *info, 
+				union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int err = 0;
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	down(&priv->wx_sem);
+	
+	if (wrqu->retry.flags & IW_RETRY_LIFETIME || 
+	    wrqu->retry.disabled){
+		err = -EINVAL;
+		goto exit;
+	}
+	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
+		err = -EINVAL;
+		goto exit;
+	}
+
+	if(wrqu->retry.value > R8192_MAX_RETRY){
+		err= -EINVAL;
+		goto exit;
+	}
+	if (wrqu->retry.flags & IW_RETRY_MAX) {
+		priv->retry_rts = wrqu->retry.value;
+		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
+	
+	}else {
+		priv->retry_data = wrqu->retry.value;
+		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
+	}
+	
+
+ 	rtl8192_commit(dev);
+	/*
+	if(priv->up){
+		rtl8180_halt_adapter(dev);
+		rtl8180_rx_enable(dev);
+		rtl8180_tx_enable(dev);
+			
+	}
+	*/
+exit:
+	up(&priv->wx_sem);
+	
+	return err;
+}
+
+static int r8192_wx_get_retry(struct net_device *dev, 
+				struct iw_request_info *info, 
+				union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+
+	wrqu->retry.disabled = 0; /* can't be disabled */
+
+	if ((wrqu->retry.flags & IW_RETRY_TYPE) == 
+	    IW_RETRY_LIFETIME) 
+		return -EINVAL;
+	
+	if (wrqu->retry.flags & IW_RETRY_MAX) {
+		wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
+		wrqu->retry.value = priv->retry_rts;
+	} else {
+		wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
+		wrqu->retry.value = priv->retry_data;
+	}
+	
+
+	return 0;
+}
+
+static int r8192_wx_get_sens(struct net_device *dev, 
+				struct iw_request_info *info, 
+				union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	if(priv->rf_set_sens == NULL) 
+		return -1; /* we have not this support for this radio */
+	wrqu->sens.value = priv->sens;
+	return 0;
+}
+
+
+static int r8192_wx_set_sens(struct net_device *dev, 
+				struct iw_request_info *info, 
+				union iwreq_data *wrqu, char *extra)
+{
+	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	short err = 0;
+	
+	if(priv->bHwRadioOff == true)
+		return 0;
+	
+	down(&priv->wx_sem);
+	if(priv->rf_set_sens == NULL) {
+		err= -1; /* we have not this support for this radio */
+		goto exit;
+	}
+	if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
+		priv->sens = wrqu->sens.value;
+	else
+		err= -EINVAL;
+
+exit:
+	up(&priv->wx_sem);
+	
+	return err;
+}
+
+#if (WIRELESS_EXT >= 18)
+#if 0
+static int r8192_wx_get_enc_ext(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret = 0;
+#ifdef _RTL8192_EXT_PATCH_
+	ret = rtllib_wx_get_encode_ext(priv->rtllib, info, wrqu, extra,0);
+#else
+	ret = rtllib_wx_get_encode_ext(priv->rtllib, info, wrqu, extra);
+#endif
+	return ret;
+}
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_	
+static int meshdev_set_key_for_linked_peers(struct net_device *dev, u8 KeyIndex,u16 KeyType, u32 *KeyContent );
+static int r8192_set_hw_enc(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *wrqu, char *extra, u8 is_mesh)
+{
+	int ret=0;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u32 key[4] = {0};
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct iw_point *encoding = &wrqu->encoding;
+	u8 idx = 0, alg = 0, group = 0;
+	u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 zero[6] = {0};
+        priv->rtllib->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+        down(&priv->rtllib->ips_sem);
+        IPSLeave(dev);
+        up(&priv->rtllib->ips_sem);			
+#endif
+#if 0
+	static u8 CAM_CONST_ADDR[4][6] = {
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
+#endif
+	if ((encoding->flags & IW_ENCODE_DISABLED) ||
+		ext->alg == IW_ENCODE_ALG_NONE) 
+	{
+		if(is_mesh)
+			ieee->mesh_pairwise_key_type = ieee->mesh_pairwise_key_type = KEY_TYPE_NA;
+		else
+			ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
+		CamResetAllEntry(dev);
+		if(is_mesh)
+			CamRestoreEachIFEntry(dev,0);
+		else
+			CamRestoreEachIFEntry(dev,1);
+		reset_IFswcam(dev,is_mesh);
+		goto end_hw_sec;
+	}
+	alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx)
+		idx --;
+	group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
+	printk("====>group is %x\n",group);
+	if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40) || (IW_MODE_MESH == ieee->iw_mode))
+	{
+		if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
+			alg = KEY_TYPE_WEP104;
+		if(is_mesh)
+			ieee->mesh_pairwise_key_type = alg;
+		else
+			ieee->pairwise_key_type = alg;
+		EnableHWSecurityConfig8192(dev);
+	}
+	memcpy((u8*)key, ext->key, 16); 
+	if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
+	{
+		printk("=====>set WEP key\n");
+		if (ext->key_len == 13){
+			if(is_mesh)
+				ieee->mesh_pairwise_key_type = alg = KEY_TYPE_WEP104;
+			else
+				ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
+		}
+		if(ieee->iw_mode == IW_MODE_ADHOC){
+			set_swcam( dev,
+					idx,
+					idx, 
+					alg,  
+					zero, 
+					0,              
+					key,		   
+					is_mesh);
+			setKey( dev,
+					idx,
+					idx, 
+					alg,  
+					zero, 
+					0,              
+					key);           
+		}
+			
+		if(!is_mesh){ 
+			if(ieee->state == RTLLIB_LINKED){
+				setKey( dev,
+						31,                      
+						idx,                      
+						ieee->pairwise_key_type,        
+						ieee->ap_mac_addr,         
+						0,                      
+						key);                 
+				set_swcam( dev,
+						31,                      
+						idx,                      
+						ieee->pairwise_key_type,        
+						ieee->ap_mac_addr,         
+						0,                      
+						key,               
+						0);
+			}
+		}
+	}
+	else if (group)
+	{
+		printk("set group key\n");
+		if(is_mesh)
+			ieee->mesh_group_key_type = alg;
+		else
+			ieee->group_key_type = alg;
+		if(ieee->iw_mode == IW_MODE_ADHOC){
+			set_swcam(  dev,
+					idx,
+					idx, 
+					alg,  
+					broadcast_addr, 
+					0,              
+					key,           
+					is_mesh);
+			setKey(  dev,
+					idx,
+					idx, 
+					alg,  
+					broadcast_addr, 
+					0,              
+					key);           
+		}
+			
+		if(is_mesh)
+			meshdev_set_key_for_linked_peers(dev,
+				idx, 
+				alg,  
+				key); 
+	}
+	else 
+	{
+		printk("=============>set pairwise key\n");
+#ifdef RTL8192E
+		if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
+			write_nic_byte(dev, 0x173, 1); 
+		}
+#endif
+		set_swcam( dev,
+				31, 
+				idx, 
+				alg,  
+				(u8*)ieee->ap_mac_addr, 
+				0,              
+				key,           
+				is_mesh);
+		setKey( dev,
+				31, 
+				idx, 
+				alg,  
+				(u8*)ieee->ap_mac_addr, 
+				0,              
+				key);           
+	}
+
+end_hw_sec:
+        priv->rtllib->wx_set_enc = 0;
+	return ret;	
+}
+	
+int rtl8192_set_key_for_AP(struct rtllib_device *ieee)
+{
+	struct rtllib_crypt_data **crypt;
+	int key_len=0;
+	char key[32]; 
+	u16 keytype = IW_ENCODE_ALG_NONE;
+#ifdef _RTL8192_EXT_PATCH_
+	crypt = &ieee->sta_crypt[ieee->tx_keyidx];
+#else
+	crypt = &ieee->crypt[ieee->tx_keyidx];
+#endif
+	if (*crypt == NULL || (*crypt)->ops == NULL)
+	{
+		printk("%s():no encrypt now\n",__FUNCTION__);
+		return 0;
+	}
+	if (!((*crypt)->ops->set_key && (*crypt)->ops->get_key)) 
+		return -1;
+	
+	key_len = (*crypt)->ops->get_key(key, 32, NULL, (*crypt)->priv);
+	if (strcmp((*crypt)->ops->name, "WEP") == 0 )
+	{
+		if(key_len == 5)
+			keytype = KEY_TYPE_WEP40;
+		else
+			keytype = KEY_TYPE_WEP104;
+	}
+	else if (strcmp((*crypt)->ops->name, "TKIP") == 0)
+		return 0;
+	else if (strcmp((*crypt)->ops->name, "CCMP") == 0)
+		return 0;
+
+	set_swcam( ieee->dev,
+				31,
+				ieee->tx_keyidx, 
+				keytype,  
+				ieee->ap_mac_addr, 
+				0,              
+				(u32 *)key ,          
+				0);
+	setKey( ieee->dev,
+			31,
+			ieee->tx_keyidx, 
+			keytype,  
+			ieee->ap_mac_addr, 
+			0,              
+			(u32 *)key);           
+	
+	
+	return 0;
+}
+
+static int r8192_wx_set_enc_ext(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *wrqu, char *extra)
+{
+	int ret=0;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra, 0);
+
+	ret |= r8192_set_hw_enc(dev,info,wrqu,extra, 0);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+#endif
+
+	return ret;	
+}
+/*
+ * set key for mesh, not a wireless extension handler. 
+ * place it here because of porting from r8192_wx_set_enc_ext().  
+ */ 
+int r8192_mesh_set_enc_ext(struct net_device *dev,
+                        struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr)
+{
+	int ret=0;
+	int i=0;
+	u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u8 entry_idx = 0;
+	down(&priv->wx_sem);
+	if(memcmp(addr,broadcast_addr,6))
+	{
+		if ((i=rtllib_find_MP(ieee, addr, 0)) < 0) 
+		{
+			i = rtllib_find_MP(ieee, addr, 1); 
+			if (i<0) 
+				return -1;
+		}
+	}
+	ret = rtllib_mesh_set_encode_ext(ieee, encoding, ext, i);
+	if ((-EINVAL == ret) || (-ENOMEM == ret)) {
+		goto end_hw_sec;
+	}
+	{
+#if 0		
+		u8 zero[6] = {0};
+#endif
+		u32 key[4] = {0};
+		u8 idx = 0, alg = 0, group = 0;
+		if ((encoding->flags & IW_ENCODE_DISABLED) ||
+			ext->alg == IW_ENCODE_ALG_NONE) 
+		{
+			CamResetAllEntry(dev);
+			CamRestoreEachIFEntry(dev,0);
+			reset_IFswcam(dev,1);
+			goto end_hw_sec;
+		}
+		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 
+		idx = encoding->flags & IW_ENCODE_INDEX;
+		if (idx)
+			idx --;
+		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
+
+		if (!group)
+		{
+			ieee->mesh_pairwise_key_type = alg;
+			EnableHWSecurityConfig8192(dev);	
+		}
+		
+		memcpy((u8*)key, ext->key, 16); 
+
+		if(group)
+		{
+			ieee->mesh_group_key_type = alg;
+#if 0
+			setKey( dev,
+					idx,
+					idx, 
+					alg,  
+					broadcast_addr, 
+					0,              
+					key);           
+#endif
+		}
+		else 
+		{
+#if 0	
+			if ((ieee->mesh_pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
+				write_nic_byte(dev, 0x173, 1); 
+			}
+#endif			
+			entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee,addr);
+#if 0 
+			printk("%s(): Can't find  free hw security cam entry\n",__FUNCTION__);
+			ret = -1;
+#else
+			if (entry_idx >= TOTAL_CAM_ENTRY-1) {
+				printk("%s(): Can't find  free hw security cam entry\n",__FUNCTION__);
+				ret = -1;
+			} else {
+				set_swcam( dev,
+					entry_idx,		
+					idx, 		
+					alg,  		
+					(u8*)addr, 	
+					0,              
+					key,		
+					1);           	
+				setKey( dev,
+					entry_idx,		
+					idx, 		
+					alg,  		
+					(u8*)addr, 	
+					0,              
+					key);           
+				ret = 0;
+			}
+#endif
+		}
+
+
+	}
+
+end_hw_sec:
+	up(&priv->wx_sem);
+#endif
+	return ret;	
+
+}
+#else
+static int r8192_wx_set_enc_ext(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *wrqu, char *extra)
+{
+	int ret=0;
+	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
+	down(&priv->wx_sem);
+
+        priv->rtllib->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+        down(&priv->rtllib->ips_sem);
+        IPSLeave(dev);
+        up(&priv->rtllib->ips_sem);			
+#endif
+
+	ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra);
+
+	{
+		u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+		u8 zero[6] = {0};
+		u32 key[4] = {0};
+		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+		struct iw_point *encoding = &wrqu->encoding;
+#if 0
+		static u8 CAM_CONST_ADDR[4][6] = {
+			{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+			{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+			{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+			{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
+#endif
+		u8 idx = 0, alg = 0, group = 0;
+		if ((encoding->flags & IW_ENCODE_DISABLED) ||
+		ext->alg == IW_ENCODE_ALG_NONE) 
+		{
+			ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
+			CamResetAllEntry(dev);
+			memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+			goto end_hw_sec;
+		}
+		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 
+		idx = encoding->flags & IW_ENCODE_INDEX;
+		if (idx)
+			idx --;
+		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
+
+		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
+		{
+			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
+				alg = KEY_TYPE_WEP104;
+			ieee->pairwise_key_type = alg;
+			EnableHWSecurityConfig8192(dev);
+		}
+		memcpy((u8*)key, ext->key, 16); 
+		
+		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
+		{
+			if (ext->key_len == 13)
+				ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
+			setKey( dev,
+					idx,
+					idx, 
+					alg,  
+					zero, 
+					0,              
+					key);           
+			set_swcam( dev,
+					idx,
+					idx, 
+					alg,  
+					zero, 
+					0,              
+					key,          
+					0);
+		}
+		else if (group)
+		{
+			ieee->group_key_type = alg;
+			setKey( dev,
+					idx,
+					idx, 
+					alg,  
+					broadcast_addr, 
+					0,              
+					key);           
+			set_swcam( dev,
+					idx,
+					idx, 
+					alg,  
+					broadcast_addr, 
+					0,              
+					key,                 
+					0);
+		}
+		else 
+		{
+			#ifdef RTL8192E
+			if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
+							write_nic_byte(dev, 0x173, 1); 
+			}
+			#endif
+			setKey( dev,
+					4,
+					idx, 
+					alg,  
+					(u8*)ieee->ap_mac_addr, 
+					0,              
+					key);           
+			set_swcam( dev,
+					4,
+					idx, 
+					alg,  
+					(u8*)ieee->ap_mac_addr, 
+					0,              
+					key,                 
+					0);
+		}
+
+
+	}
+
+end_hw_sec:
+        priv->rtllib->wx_set_enc = 0;
+	up(&priv->wx_sem);
+#endif
+	return ret;	
+
+}
+#endif
+static int r8192_wx_set_auth(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *data, char *extra)
+{
+	int ret=0;
+	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
+	down(&priv->wx_sem);
+	ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra);
+	up(&priv->wx_sem);
+#endif
+	return ret;
+}
+
+static int r8192_wx_set_mlme(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *wrqu, char *extra)
+{
+
+	int ret=0;
+	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
+	down(&priv->wx_sem);
+	ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra);
+	up(&priv->wx_sem);
+#endif
+	return ret;
+}
+#endif
+
+static int r8192_wx_set_gen_ie(struct net_device *dev,
+                                        struct iw_request_info *info,
+                                        union iwreq_data *data, char *extra)
+{
+	int ret = 0;
+	
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+        struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
+        down(&priv->wx_sem);
+        ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length);
+        up(&priv->wx_sem);
+#endif
+        return ret;
+}
+
+static int r8192_wx_get_gen_ie(struct net_device *dev,
+                               struct iw_request_info *info, 
+			       union iwreq_data *data, char *extra)
+{
+	int ret = 0;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+        struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+	if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
+		data->data.length = 0;
+		return 0;
+	}
+
+	if (data->data.length < ieee->wpa_ie_len) {
+		return -E2BIG;
+	}
+
+	data->data.length = ieee->wpa_ie_len;
+	memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
+#endif
+        return ret;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+/*
+   Output:
+     (case 1) Mesh: Enable. MESHID=[%s] (max length of %s is 32 bytes). 
+     (case 2) Mesh: Disable.
+*/
+static int r8192_wx_get_meshinfo(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_meshinfo )
+		return 0;
+	return priv->mshobj->ext_patch_r819x_wx_get_meshinfo(dev, info, wrqu, extra);
+}
+
+
+static int r8192_wx_enable_mesh(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	RT_RF_POWER_STATE       rtState;
+	int ret = 0;
+        rtState = priv->rtllib->eRFPowerState;
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_enable_mesh )
+		return 0;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	if(priv->mshobj->ext_patch_r819x_wx_enable_mesh(dev))
+	{
+		union iwreq_data tmprqu;
+#ifdef ENABLE_IPS
+		if(priv->rtllib->PowerSaveControl.bInactivePs){
+			if(rtState == eRfOff){
+				if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+				{
+					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+					SEM_UP_PRIV_WX(&priv->wx_sem);	
+					return -1;
+				}
+				else{
+					printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					IPSLeave(dev);
+				}
+			}
+		}
+#endif
+		if(ieee->only_mesh == 0) 
+		{
+			tmprqu.mode = ieee->iw_mode;
+			ieee->iw_mode = 0; 
+			ret = rtllib_wx_set_mode(ieee, info, &tmprqu, extra);
+		}
+	}
+
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	
+	return ret;
+	
+}
+
+static int r8192_wx_disable_mesh(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+
+	int ret = 0;
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_disable_mesh )
+		return 0;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	if(priv->mshobj->ext_patch_r819x_wx_disable_mesh(dev))
+	{
+		union iwreq_data tmprqu;
+		tmprqu.mode = ieee->iw_mode;
+		ieee->iw_mode = 999;
+		ret = rtllib_wx_set_mode(ieee, info, &tmprqu, extra);
+	}
+
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	
+	return ret;
+}
+
+
+int r8192_wx_set_channel(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	int ch = *extra;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	
+	if (!priv->mshobj || (ieee->iw_mode != IW_MODE_MESH) || !priv->mshobj->ext_patch_r819x_wx_set_channel || !ieee->only_mesh)
+		return 0;	
+			
+	if ( ch < 0 ) 	
+	{
+		rtllib_start_scan(ieee);			
+		ieee->meshScanMode =2;
+	}
+	else	
+	{	
+		ieee->meshScanMode =0;		
+		if(priv->mshobj->ext_patch_r819x_wx_set_channel)
+		{
+			priv->mshobj->ext_patch_r819x_wx_set_channel(ieee, ch);
+			priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch);
+		}
+		queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq);
+		ieee->set_chan(ieee->dev, ch);
+printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!set current mesh network channel %d\n", ch);
+		ieee->current_mesh_network.channel = ch;
+		if(ieee->only_mesh)
+			ieee->current_network.channel = ch;
+		
+		ieee->current_network.channel = ieee->current_mesh_network.channel; 
+		if(ieee->pHTInfo->bCurBW40MHz)
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+		else
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+		if(rtllib_act_scanning(ieee,true) == true)
+			rtllib_stop_scan_syncro(ieee);
+	}
+		
+	return 0;
+}
+
+static int r8192_wx_set_meshID(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_meshID )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, wrqu->data.pointer);	
+}
+
+
+/* reserved for future
+static int r8192_wx_add_mac_deny(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny(dev, info, wrqu, extra);
+}
+
+static int r8192_wx_del_mac_deny(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny(dev, info, wrqu, extra);
+}
+*/
+/* reserved for future
+static int r8192_wx_get_mac_deny(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_get_mac_deny(dev, info, wrqu, extra);
+}
+static int r8192_wx_join_mesh(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	int ret=0;
+	char ch;
+	if(priv->rtllib->iw_mode == IW_MODE_MESH) {
+		printk("join mesh %s\n",extra);
+		if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
+			ret= -E2BIG;
+			goto out;
+		}
+		if((wrqu->essid.length == 1) && (wrqu->essid.flags == 1)){
+			ret = 0;
+			goto out;
+		}
+		if (wrqu->essid.flags && wrqu->essid.length) {
+			if(priv->mshobj->ext_patch_r819x_wx_get_selected_mesh_channel(dev, extra, &ch))
+			{
+				priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, extra); 
+				priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch); 
+				r8192_wx_set_channel(dev, NULL, NULL, &ch);
+			}
+			else
+				printk("invalid mesh #\n");
+		}
+	}
+out:
+	return ret;
+}
+*/
+
+static int r8192_wx_get_mesh_list(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mesh_list )
+		return 0;
+	return priv->mshobj->ext_patch_r819x_wx_get_mesh_list(dev, info, wrqu, extra);
+}
+
+static int r8192_wx_mesh_scan(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_mesh_scan )
+		return 0;
+	return priv->mshobj->ext_patch_r819x_wx_mesh_scan(dev, info, wrqu, extra);
+}
+
+static int r8192_wx_set_meshmode(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+
+	printk("%s(): set mesh mode ! extra is %d\n",__FUNCTION__, *extra);
+	if((*extra != WIRELESS_MODE_A) && (*extra != WIRELESS_MODE_B) && 
+		(*extra != WIRELESS_MODE_G) && (*extra != WIRELESS_MODE_AUTO) &&
+		(*extra != WIRELESS_MODE_N_24G) && (*extra != WIRELESS_MODE_N_5G))
+	{
+		printk("ERR!! you should input 1 | 2 | 4 | 8 | 16 | 32\n");
+		SEM_UP_PRIV_WX(&priv->wx_sem);	
+		return -1;
+	}
+	if(priv->rtllib->state == RTLLIB_LINKED)
+	{
+		if((priv->rtllib->mode != WIRELESS_MODE_N_5G) && (priv->rtllib->mode != WIRELESS_MODE_N_24G)){
+			printk("===>wlan0 is linked,and ieee->mode is not N mode ,do not need to set mode,return\n");
+			SEM_UP_PRIV_WX(&priv->wx_sem);	
+			return 0;
+		}
+	}
+	priv->rtllib->mode = *extra;
+	if(priv->ResetProgress == RESET_TYPE_NORESET)
+		rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
+	 HTUseDefaultSetting(priv->rtllib);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	return 0;
+
+}
+
+static int r8192_wx_set_meshBW(struct net_device *dev,
+                struct iw_request_info *info,
+                union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+
+	printk("%s(): set mesh BW ! extra is %d\n",__FUNCTION__, *extra);
+	priv->rtllib->pHTInfo->bRegBW40MHz = *extra;
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	return 0;
+}
+static int r8192_wx_set_mesh_security(struct net_device *dev,
+                struct iw_request_info *info,
+                union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+        struct rtllib_device* ieee = priv->rtllib;
+
+        down(&priv->wx_sem);
+
+        printk("%s(): set mesh security! extra is %d\n",__FUNCTION__, *extra);
+        ieee->mesh_security_setting = *extra;
+
+        if (0 == ieee->mesh_security_setting)
+        {
+		ieee->mesh_pairwise_key_type = ieee->mesh_group_key_type = KEY_TYPE_NA;
+		CamResetAllEntry(dev);
+		CamRestoreEachIFEntry(dev,0);
+		reset_IFswcam(dev,1);
+        }
+	else
+	{
+		ieee->mesh_pairwise_key_type = KEY_TYPE_CCMP;
+		ieee->mesh_group_key_type = KEY_TYPE_CCMP;
+	}
+        up(&priv->wx_sem);
+        return 0;
+
+}
+
+static int r8192_wx_set_mkdd_id(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	printk("===>%s()\n",__FUNCTION__);	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_mkdd_id)
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_mkdd_id(dev, wrqu->data.pointer);	
+}
+
+static int r8192_wx_set_mesh_key(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	printk("===>%s()\n",__FUNCTION__);	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_mesh_key)
+		return 0;
+	return priv->mshobj->ext_patch_r819x_wx_set_mesh_key(dev, wrqu->data.pointer);	
+}
+
+static int r8192_wx_set_mesh_sec_type(struct net_device *dev,
+                struct iw_request_info *info,
+                union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+	printk("%s(): set mesh security type! extra is %d\n",__FUNCTION__, *extra);
+	if (ieee->mesh_sec_type == 1 && *extra != 1 && ieee->mesh_security_setting == 3) {
+		rtl8192_abbr_handshk_disable_key(ieee); 
+	
+		if(priv->mshobj->ext_patch_r819x_wx_release_sae_info)
+			priv->mshobj->ext_patch_r819x_wx_release_sae_info(ieee);
+	}
+	down(&priv->wx_sem);
+
+	ieee->mesh_sec_type = *extra;
+
+	if(ieee->mesh_sec_type == 0)
+		ieee->mesh_pairwise_key_type = ieee->mesh_group_key_type = KEY_TYPE_NA;
+
+	up(&priv->wx_sem);
+	return 0;
+}
+
+#endif 
+
+#define OID_RT_INTEL_PROMISCUOUS_MODE	0xFF0101F6
+
+static int r8192_wx_set_PromiscuousMode(struct net_device *dev,
+                struct iw_request_info *info,
+                union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+	u32 *info_buf = (u32*)(wrqu->data.pointer);
+
+	u32 oid = info_buf[0];
+	u32 bPromiscuousOn = info_buf[1];
+	u32 bFilterSourceStationFrame = info_buf[2];
+
+	if (OID_RT_INTEL_PROMISCUOUS_MODE == oid)
+	{
+		ieee->IntelPromiscuousModeInfo.bPromiscuousOn = 
+					(bPromiscuousOn)? (true) : (false);
+		ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame = 
+					(bFilterSourceStationFrame)? (true) : (false);
+
+		(bPromiscuousOn) ? (rtllib_EnableIntelPromiscuousMode(dev, false)) : 
+				(rtllib_DisableIntelPromiscuousMode(dev, false));	
+
+		printk("=======>%s(), on = %d, filter src sta = %d\n", __FUNCTION__, 
+			bPromiscuousOn, bFilterSourceStationFrame);
+	} else {
+		return -1;
+	}
+	
+	return 0;
+}
+
+
+static int r8192_wx_get_PromiscuousMode(struct net_device *dev,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+
+        down(&priv->wx_sem);
+
+        snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d",\
+			ieee->IntelPromiscuousModeInfo.bPromiscuousOn,\
+			ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame);
+        wrqu->data.length = strlen(extra) + 1;
+
+        up(&priv->wx_sem);
+
+	return 0;
+}
+
+
+#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+static iw_handler r8192_wx_handlers[] =
+{
+        IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name,   	  
+        IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq,        
+        IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq,        
+        IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode,        
+        IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode,        
+        IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens,        
+        IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens,        
+        IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range,	  
+        IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap,      	  
+        IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap,           
+        IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan,        
+        IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan,        
+        IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid,      
+        IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid,      
+        IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick,
+		IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick,
+        IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate,        
+        IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate,        
+        IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts,          
+        IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts,          
+        IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag,        
+        IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag,        
+        IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry,      
+        IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry,      
+        IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc,       
+        IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc,       
+        IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power,         
+        IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power,         
+#if (WIRELESS_EXT >= 18)
+		IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie, 	     
+		IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie,
+		IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme,        
+		IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth,	    
+		IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext,  
+#endif
+}; 
+
+/* 
+ * the following rule need to be follwing,
+ * Odd : get (world access), 
+ * even : set (root access) 
+ * */
+static const struct iw_priv_args r8192_private_args[] = { 
+	{
+		SIOCIWFIRSTPRIV + 0x0, 
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debugflag" 
+	}, 
+	{
+		SIOCIWFIRSTPRIV + 0x1,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x2, 
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x3,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x4,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "force_mic_error"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x5,
+		IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT|IW_PRIV_SIZE_FIXED|1, 
+		"firm_ver"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x6,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, 
+		"set_power"
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x7,
+		IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|512, 
+		"print_reg"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x8,
+		IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|64, 
+		"resume_firm"
+	}
+#endif
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x9,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, 
+		"radio"
+	}
+        ,
+	{
+		SIOCIWFIRSTPRIV + 0xa,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, 
+		"lps_interv"
+	}
+        ,
+	{
+		SIOCIWFIRSTPRIV + 0xb,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, 
+		"lps_force"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0xc,
+		0, IW_PRIV_TYPE_CHAR|2047, "adhoc_peer_list"
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	,
+	{
+		SIOCIWFIRSTPRIV + 0xd,
+		IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|64, 
+		"driverVer"
+	}
+#endif
+#ifdef CONFIG_MP	
+	,
+	{
+		SIOCIWFIRSTPRIV + 0xe,
+                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetChan"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0xf,
+                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetRate"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x10,
+                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetTxPower"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x11,
+                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetBW"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x12,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "TxStart"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x13,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,0, "SetSingleCarrier"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x14,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "WriteRF"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x15,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "WriteMAC"
+	}
+#endif
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x16,
+                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setpromisc"
+	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x17,
+		0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 45, "getpromisc"
+	}
+
+};
+
+static iw_handler r8192_private_handler[] = {
+	(iw_handler)r8192_wx_set_debugflag,   /*SIOCIWSECONDPRIV*/
+	(iw_handler)r8192_wx_set_scan_type,
+	(iw_handler)r8192_wx_set_rawtx,
+	(iw_handler)r8192_wx_force_reset,
+	(iw_handler)r8192_wx_force_mic_error,
+	(iw_handler)r8191se_wx_get_firm_version,
+	(iw_handler)r8192_wx_adapter_power_status,	    
+#ifdef _RTL8192_EXT_PATCH_
+	(iw_handler)r8192_wx_print_reg,	    
+	(iw_handler)r8192_wx_resume_firm,
+#else
+	(iw_handler)NULL, 
+	(iw_handler)NULL,
+#endif
+	(iw_handler)r8192se_wx_set_radio,
+	(iw_handler)r8192se_wx_set_lps_awake_interval,
+	(iw_handler)r8192se_wx_set_force_lps,
+	(iw_handler)r8192_wx_get_adhoc_peers,
+#ifdef _RTL8192_EXT_PATCH_
+	(iw_handler)r8192_wx_get_drv_version,
+#else
+	(iw_handler)NULL,
+#endif
+#ifdef CONFIG_MP
+	(iw_handler)r8192_wx_mp_set_chan,
+	(iw_handler)r8192_wx_mp_set_txrate,
+	(iw_handler)r8192_wx_mp_set_txpower,
+	(iw_handler)r8192_wx_mp_set_bw,
+        (iw_handler)r8192_wx_mp_set_txstart,
+        (iw_handler)r8192_wx_mp_set_singlecarrier,
+        (iw_handler)r8192_wx_mp_write_rf,
+	(iw_handler)r8192_wx_mp_write_mac,
+#else
+	(iw_handler)NULL,
+	(iw_handler)NULL,
+	(iw_handler)NULL,
+	(iw_handler)NULL,
+	(iw_handler)NULL,
+ 	(iw_handler)NULL,
+	(iw_handler)NULL,
+	(iw_handler)NULL,
+#endif
+	(iw_handler)r8192_wx_set_PromiscuousMode,
+	(iw_handler)r8192_wx_get_PromiscuousMode,
+};
+
+struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
+{
+       struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	struct iw_statistics* wstats = &priv->wstats;
+	int tmp_level = 0;
+	int tmp_qual = 0;
+	int tmp_noise = 0;
+	if(ieee->state < RTLLIB_LINKED)
+	{
+		wstats->qual.qual = 10;
+		wstats->qual.level = 0;
+		wstats->qual.noise = -100;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) 
+		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+		wstats->qual.updated = 0x0f;
+#endif
+		return wstats;
+	}
+	
+       tmp_level = (&ieee->current_network)->stats.rssi;
+	tmp_qual = (&ieee->current_network)->stats.signal;
+	tmp_noise = (&ieee->current_network)->stats.noise;			
+
+	wstats->qual.level = tmp_level;
+	wstats->qual.qual = tmp_qual;
+	wstats->qual.noise = tmp_noise;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) 
+	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+	wstats->qual.updated = 0x0f;
+#endif
+	return wstats;
+}
+
+#if defined RTL8192SE || defined RTL8192CE
+u8 SS_Rate_Map_G[6][2] = {{40, MGN_54M}, {30, MGN_48M}, {20, MGN_36M},
+	{12, MGN_24M}, {7, MGN_18M}, {0, MGN_12M}};
+u8 MSI_SS_Rate_Map_G[6][2] = {{40, MGN_54M}, {30, MGN_54M}, {20, MGN_54M},
+	{12, MGN_48M}, {7, MGN_36M}, {0, MGN_24M}};
+u8 SS_Rate_Map_B[2][2] = {{7, MGN_11M}, {0, MGN_5_5M}};
+u8 SS_Rate_Map_N_MCS7[7][2] = {{40, MGN_MCS7}, {30, MGN_MCS5}, {25, MGN_MCS4},
+	{23, MGN_MCS3}, {19, MGN_MCS2}, {8, MGN_MCS1}, {0, MGN_MCS0}};
+u8 SS_Rate_Map_N_MCS15[7][2] = {{40, MGN_MCS15}, {35, MGN_MCS14}, {31, MGN_MCS12},
+	{28, MGN_MCS7}, {25, MGN_MCS5}, {23, MGN_MCS3}, {20, MGN_MCS0}};
+#define TxRateTypeNormal        0
+#define TxRateTypeCurrent       1
+#define TxRateTypeStartRate     2
+
+u8 rtl8192_decorate_txrate_by_singalstrength(u32 SignalStrength, u8 *SS_Rate_Map, u8 MapSize)
+{
+	u8 index = 0;
+
+	for (index = 0; index < (MapSize * 2); index += 2) {
+		if (SignalStrength > SS_Rate_Map[index])
+			return SS_Rate_Map[index+1];
+	}
+
+	return MGN_1M;
+}
+
+u16 rtl8192_11n_user_show_rates(struct net_device* dev)
+{
+	struct r8192_priv  *priv = rtllib_priv(dev);
+	static u8  TimesForReportingFullRxSpeedAfterConnected = 100;
+	u8  rate = MGN_1M;
+	u32  Sgstrength;
+	bool TxorRx = priv->rtllib->bForcedShowRxRate;          
+
+
+	if (!TxorRx) {
+		{
+			return CONVERT_RATE(priv->rtllib, priv->rtllib->softmac_stats.CurrentShowTxate);
+		}
+	}
+
+	if(priv->rtllib->bForcedShowRateStill) {
+		Sgstrength = 100;
+	} else {
+		Sgstrength = priv->undecorated_smoothed_pwdb;
+	}
+
+	if (priv->rtllib->mode == WIRELESS_MODE_A ||
+			priv->rtllib->mode == WIRELESS_MODE_G ||
+			priv->rtllib->mode == (WIRELESS_MODE_G | WIRELESS_MODE_B )) {
+		if (priv->CustomerID == RT_CID_819x_MSI) {
+			rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength,
+					(u8*)MSI_SS_Rate_Map_G, sizeof(MSI_SS_Rate_Map_G)/2);
+		} else {
+			rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength,
+					(u8*)SS_Rate_Map_G, sizeof(SS_Rate_Map_G)/2);
+		}
+	} else if (priv->rtllib->mode == WIRELESS_MODE_B) {
+		rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_B,
+				sizeof(SS_Rate_Map_B)/2);
+	} else if(priv->rtllib->mode == WIRELESS_MODE_N_24G) {
+		bool  bMaxRateMcs15;
+		bool  b1SSSupport = priv->rtllib->b1x1RecvCombine;
+		u8    rftype = priv->rf_type;
+		if (((!TxorRx) && (rftype==RF_1T1R || rftype==RF_1T2R)) ||
+				(TxorRx && (rftype==RF_1T1R || (rftype==RF_1T2R && b1SSSupport))) ||
+				(rftype==RF_2T2R && priv->rtllib->HTHighestOperaRate<=MGN_MCS7))
+			bMaxRateMcs15 = false;
+		else
+			bMaxRateMcs15 = true;
+
+		if((priv->rtllib->state == RTLLIB_LINKED) && !(priv->rtllib->pHTInfo->bCurBW40MHz))
+			bMaxRateMcs15 = false;
+
+		if(priv->rtllib->state != RTLLIB_LINKED)
+			priv->rtllib->SystemQueryDataRateCount = 0;
+		if (TimesForReportingFullRxSpeedAfterConnected > priv->rtllib->SystemQueryDataRateCount) {
+			priv->rtllib->SystemQueryDataRateCount++;
+			if(bMaxRateMcs15)
+				return 600;
+			else
+				return 270;
+		}
+
+		if (bMaxRateMcs15)
+			rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_N_MCS15,
+					sizeof(SS_Rate_Map_N_MCS15)/2);
+		else
+			rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_N_MCS7,
+					sizeof(SS_Rate_Map_N_MCS7)/2);
+	} else if (priv->rtllib->mode == WIRELESS_MODE_N_5G) {
+		return 580;
+	} else {
+		return 2;
+	}
+
+	if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev)) {
+		if (rate < 0x80)
+			return rate;
+		else
+			return HTHalfMcsToDataRate(priv->rtllib, rate);
+	} else {
+                return CONVERT_RATE(priv->rtllib, rate);
+        }
+}
+#endif
+
+struct iw_handler_def  r8192_wx_handlers_def={
+	.standard = r8192_wx_handlers,
+	.num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
+	.private = r8192_private_handler,
+	.num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
+ 	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
+#if WIRELESS_EXT >= 17	
+	.get_wireless_stats = r8192_get_wireless_stats,
+#endif
+	.private_args = (struct iw_priv_args *)r8192_private_args,	
+};
+
+#ifdef _RTL8192_EXT_PATCH_
+#define OID_802_11_MESH_SECURITY_INFO 0x0651
+#define OID_802_11_MESH_ID 0x0652
+#define OID_802_11_MESH_AUTO_LINK 0x0653
+#define OID_802_11_MESH_LINK_STATUS 0x0654
+#define OID_802_11_MESH_LIST 0x0655
+#define OID_802_11_MESH_ROUTE_LIST 0x0656
+#define OID_802_11_MESH_ADD_LINK 0x0657
+#define OID_802_11_MESH_DEL_LINK 0x0658
+#define OID_802_11_MESH_MAX_TX_RATE 0x0659
+#define OID_802_11_MESH_CHANNEL 0x065A
+#define OID_802_11_MESH_HOSTNAME	0x065B
+#define OID_802_11_MESH_ONLY_MODE  0x065C
+
+#define OID_GET_SET_TOGGLE 0x8000
+#define RTL_OID_802_11_MESH_SECURITY_INFO (OID_GET_SET_TOGGLE + OID_802_11_MESH_SECURITY_INFO)
+#define RTL_OID_802_11_MESH_ID (OID_GET_SET_TOGGLE + OID_802_11_MESH_ID)
+#define RTL_OID_802_11_MESH_AUTO_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_AUTO_LINK)
+#define RTL_OID_802_11_MESH_ADD_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_ADD_LINK)
+#define RTL_OID_802_11_MESH_DEL_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_DEL_LINK)
+#define RTL_OID_802_11_MESH_MAX_TX_RATE (OID_GET_SET_TOGGLE + OID_802_11_MESH_MAX_TX_RATE)
+#define RTL_OID_802_11_MESH_CHANNEL (OID_GET_SET_TOGGLE + OID_802_11_MESH_CHANNEL)
+#define RTL_OID_802_11_MESH_HOSTNAME		(OID_GET_SET_TOGGLE + OID_802_11_MESH_HOSTNAME)
+#define RTL_OID_802_11_MESH_ONLY_MODE    (OID_GET_SET_TOGGLE + OID_802_11_MESH_ONLY_MODE)
+
+#define MAX_NEIGHBOR_NUM 64 
+typedef struct _MESH_NEIGHBOR_ENTRY
+{
+	char Rssi;
+	unsigned char HostName[MAX_HOST_NAME_LENGTH];
+	unsigned char MacAddr[ETH_ALEN];
+	unsigned char MeshId[MAX_MESH_ID_LEN];
+	unsigned char Channel;
+	unsigned char Status; 
+	unsigned char MeshEncrypType;		
+} MESH_NEIGHBOR_ENTRY, *PMESH_NEIGHBOR_ENTRY;
+typedef struct _MESH_NEIGHBOR_INFO
+{
+	MESH_NEIGHBOR_ENTRY Entry[MAX_NEIGHBOR_NUM];
+	unsigned char num;
+} MESH_NEIGHBOR_INFO, *PMESH_NEIGHBOR_INFO;
+
+static int meshdev_set_key_for_linked_peers(struct net_device *dev, u8 KeyIndex, 
+		                            u16 KeyType, u32 *KeyContent )
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	struct mshclass *mshobj = priv->mshobj;
+	PMESH_NEIGHBOR_INFO  pmesh_neighbor = NULL;
+	PMESH_NEIGHBOR_ENTRY pneighbor_entry = NULL;
+	u8 entry_idx = 0;
+	int i = 0;
+	int found_idx = MAX_MP-1;
+	pmesh_neighbor = (PMESH_NEIGHBOR_INFO)kmalloc(sizeof(MESH_NEIGHBOR_INFO), GFP_KERNEL);
+	if(NULL == pmesh_neighbor)
+		return -1;
+	
+	if(mshobj->ext_patch_r819x_get_peers)
+		mshobj->ext_patch_r819x_get_peers(dev, (void*)pmesh_neighbor);
+	
+	for (i=0; i<pmesh_neighbor->num; i++) {
+		pneighbor_entry = (PMESH_NEIGHBOR_ENTRY)&pmesh_neighbor->Entry[i];
+		if (mshobj->ext_patch_r819x_insert_linking_crypt_peer_queue)
+			found_idx = mshobj->ext_patch_r819x_insert_linking_crypt_peer_queue(ieee,pneighbor_entry->MacAddr);
+		if (found_idx == -1) {
+			printk("%s(): found_idx is -1 , something is wrong, return\n",__FUNCTION__);
+			return -1;
+		} else if (found_idx == (MAX_MP - 1)) {
+			printk("%s(): found_idx is MAX_MP-1, peer entry is full, return\n",__FUNCTION__);
+			return -1;
+		}
+		if ((((ieee->LinkingPeerBitMap>>found_idx) & (BIT0)) == BIT0) && ((ieee->LinkingPeerSecState[found_idx] == USED) )) {
+			entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee, pneighbor_entry->MacAddr);
+#if 0
+			printk("%s: Can not find free hw security cam entry, use software encryption entry(%d)\n", __FUNCTION__,entry_idx);
+			if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info)
+				mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,SW_SEC);
+			ieee->LinkingPeerSecState[found_idx] = SW_SEC; 
+#else
+			if (entry_idx >=  TOTAL_CAM_ENTRY-1) {
+				printk("%s: Can not find free hw security cam entry, use software encryption entry(%d)\n", __FUNCTION__,entry_idx);
+				if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info)
+					mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,SW_SEC);
+				ieee->LinkingPeerSecState[found_idx] = SW_SEC; 
+			} else {
+				printk("==========>%s():entry_idx is %d,set HW CAM\n",__FUNCTION__,entry_idx);
+				set_swcam( dev,
+						entry_idx,
+						KeyIndex, 
+						KeyType,  
+						pneighbor_entry->MacAddr, 
+						0,              
+						KeyContent,           
+						1);
+				setKey( dev,
+						entry_idx,
+						KeyIndex, 
+						KeyType,  
+						pneighbor_entry->MacAddr, 
+						0,              
+						KeyContent);           
+						if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info)
+							mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,HW_SEC);
+						ieee->LinkingPeerSecState[found_idx] = HW_SEC; 
+			}
+#endif
+		}
+	}
+	if(pmesh_neighbor)
+		kfree(pmesh_neighbor);
+	return 0;
+}
+
+int meshdev_set_key_for_peer(struct net_device *dev, 
+								u8 *Addr,
+								u8 KeyIndex, 
+								u16 KeyType, 
+								u32 *KeyContent )
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u8 entry_idx = 0;
+	
+	entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee, Addr);
+#if 0
+	printk("%s: Can not find free hw security cam entry\n", __FUNCTION__);
+	return -1;
+#else
+	if (entry_idx >=  TOTAL_CAM_ENTRY-1) {
+		printk("%s: Can not find free hw security cam entry\n", __FUNCTION__);
+		return -1;
+	} else {
+		set_swcam(dev,
+			entry_idx,
+			KeyIndex, 
+			KeyType,  
+			Addr, 
+			0,              
+			KeyContent,           
+			1);
+		setKey(dev,
+			entry_idx,
+			KeyIndex, 
+			KeyType,  
+			Addr, 
+			0,              
+			KeyContent);           
+	}
+	return 0;
+#endif
+}
+
+static struct net_device_stats *meshdev_stats(struct net_device *meshdev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 
+	return &((struct meshdev_priv*)netdev_priv(meshdev))->stats;
+#else
+	return &((struct meshdev_priv*)meshdev->priv)->stats;
+#endif
+}
+
+static int meshdev_wx_get_name(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_name(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_freq(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	return rtllib_wx_get_freq(priv->rtllib,info,wrqu,extra,1);
+}
+static int meshdev_wx_get_mode(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	if(0)
+		return r8192_wx_get_mode(dev, info, wrqu, extra);
+	else
+		return -1;
+}	
+static int meshdev_wx_get_sens(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+	return r8192_wx_get_sens(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_range(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return rtl8192_wx_get_range(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_wap(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_wap(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_essid(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct mshclass *mshobj = priv->mshobj;
+	int ret = 0;	
+
+	if(mshobj->ext_patch_r819x_wx_get_meshid)
+		ret = mshobj->ext_patch_r819x_wx_get_meshid(dev, info, wrqu, extra);
+
+	return ret;
+}
+static int meshdev_wx_get_rate(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_rate(dev, info, wrqu, extra);
+}
+#if 0
+static int meshdev_wx_set_freq(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+	return r8192_wx_set_freq(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_rate(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+	return r8192_wx_set_rate(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_sens(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_sens(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_scan(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_scan(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_scan(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_scan(dev, info, wrqu, extra);
+}
+#endif
+static int meshdev_wx_set_enc(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *key)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = (struct r8192_priv *)ieee->priv;
+	int ret;
+	u32 hwkey[4]={0,0,0,0};
+	u8 mask=0xff;
+	u32 key_idx=0;
+#if 0
+	u8 zero_addr[4][6] ={	{0x00,0x00,0x00,0x00,0x00,0x00},
+				{0x00,0x00,0x00,0x00,0x00,0x01}, 
+				{0x00,0x00,0x00,0x00,0x00,0x02}, 
+				{0x00,0x00,0x00,0x00,0x00,0x03} };
+#endif
+	int i;
+
+       if(!priv->mesh_up) return -ENETDOWN;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	
+	RT_TRACE(COMP_SEC, "Setting SW wep key");
+	ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key,1);
+
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+
+
+	if(wrqu->encoding.length!=0){
+
+		for(i=0 ; i<4 ; i++){
+			hwkey[i] |=  key[4*i+0]&mask;
+			if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
+			if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
+			hwkey[i] |= (key[4*i+1]&mask)<<8;
+			hwkey[i] |= (key[4*i+2]&mask)<<16;
+			hwkey[i] |= (key[4*i+3]&mask)<<24;
+		}
+
+		#define CONF_WEP40  0x4
+		#define CONF_WEP104 0x14
+
+		switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
+			case 0: key_idx = ieee->mesh_txkeyidx; break;
+			case 1:	key_idx = 0; break;
+			case 2:	key_idx = 1; break;
+			case 3:	key_idx = 2; break;
+			case 4:	key_idx	= 3; break;
+			default: break;
+		}
+
+		if(wrqu->encoding.length==0x5){
+		ieee->mesh_pairwise_key_type = KEY_TYPE_WEP40;
+			EnableHWSecurityConfig8192(dev);
+		}
+
+		else if(wrqu->encoding.length==0xd){
+			ieee->mesh_pairwise_key_type = KEY_TYPE_WEP104;
+				EnableHWSecurityConfig8192(dev);
+		}
+		else 
+			printk("wrong type in WEP, not WEP40 and WEP104\n");
+
+		meshdev_set_key_for_linked_peers(dev,
+						key_idx, 
+						ieee->mesh_pairwise_key_type,  
+						hwkey); 
+
+	}
+
+#if 0
+	if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
+		printk("===>1\n");		
+		EnableHWSecurityConfig8192(dev);
+		key_idx = (wrqu->encoding.flags & 0xf)-1 ;
+		write_cam(dev, (4*6),   0xffff0000|read_cam(dev, key_idx*6) );
+		write_cam(dev, (4*6)+1, 0xffffffff);
+		write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
+		write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
+		write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
+		write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
+	}
+#endif
+
+	return ret;
+}
+static int meshdev_wx_get_enc(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device * dev = ieee->dev;
+	struct r8192_priv* priv = rtllib_priv(dev);
+
+	if(!priv->mesh_up){
+		return -ENETDOWN;
+	}
+	return rtllib_wx_get_encode(ieee, info, wrqu, extra,1);
+}
+#if 0
+static int meshdev_wx_set_frag(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_frag(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_frag(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_frag(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_retry(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_retry(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_retry(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_get_retry(dev, info, wrqu, extra);
+}
+#endif
+static int meshdev_wx_set_mode(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+	return r8192_wx_set_mode(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_wap(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_wap(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_mlme(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_mlme(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_essid(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_essid(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_gen_ie(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_gen_ie(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_auth(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+#if 0
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	return r8192_wx_set_auth(dev, info, wrqu, extra);
+#endif
+	return 0;
+}
+static int meshdev_wx_set_enc_ext(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	int ret=0;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = (struct r8192_priv *)ieee->priv;
+
+	printk("============================================================>%s\n", __FUNCTION__);
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra, 1);
+
+	ret |= r8192_set_hw_enc(dev,info,wrqu,extra, 1);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+#endif
+
+	return ret;	
+}
+
+static int dummy(struct net_device *dev, struct iw_request_info *a,
+		 union iwreq_data *wrqu,char *b)
+{
+	return -1;
+}
+
+int rt_ioctl_siwpmksa(struct net_device *dev,
+			   struct iw_request_info *info,
+			   union iwreq_data *wrqu,
+			   char *extra)
+{
+	return 0;
+}
+
+static iw_handler meshdev_wx_handlers[] =
+{
+	NULL,                     /* SIOCSIWCOMMIT */
+	meshdev_wx_get_name,   	  /* SIOCGIWNAME */
+	dummy,                    /* SIOCSIWNWID */
+	dummy,                    /* SIOCGIWNWID */
+	NULL,  
+	meshdev_wx_get_freq,        /* SIOCGIWFREQ */
+	meshdev_wx_set_mode,        /* SIOCSIWMODE */
+	meshdev_wx_get_mode,        /* SIOCGIWMODE */
+	NULL,  
+	meshdev_wx_get_sens,        /* SIOCGIWSENS */
+	NULL,                     /* SIOCSIWRANGE */
+	meshdev_wx_get_range,	  /* SIOCGIWRANGE */
+	NULL,                     /* SIOCSIWPRIV */
+	NULL,                     /* SIOCGIWPRIV */
+	NULL,                     /* SIOCSIWSTATS */
+	NULL,                     /* SIOCGIWSTATS */
+	dummy,                    /* SIOCSIWSPY */
+	dummy,                    /* SIOCGIWSPY */
+	NULL,                     /* SIOCGIWTHRSPY */
+	NULL,                     /* SIOCWIWTHRSPY */
+	meshdev_wx_set_wap,      	  /* SIOCSIWAP */
+	meshdev_wx_get_wap,         /* SIOCGIWAP */
+	meshdev_wx_set_mlme, 
+	dummy,                     /* SIOCGIWAPLIST -- depricated */
+	NULL,  
+	NULL,  
+	meshdev_wx_set_essid,       /* SIOCSIWESSID */
+	meshdev_wx_get_essid,       /* SIOCGIWESSID */
+	dummy,                    /* SIOCSIWNICKN */
+	dummy,                    /* SIOCGIWNICKN */
+	NULL,                     /* -- hole -- */
+	NULL,                     /* -- hole -- */
+	NULL,  
+	meshdev_wx_get_rate,        /* SIOCGIWRATE */
+	dummy,                    /* SIOCSIWRTS */
+	dummy,                    /* SIOCGIWRTS */
+	NULL,  
+	NULL,  
+	dummy,                    /* SIOCSIWTXPOW */
+	dummy,                    /* SIOCGIWTXPOW */
+	NULL,  
+	NULL,  
+	meshdev_wx_set_enc,         /* SIOCSIWENCODE */
+	meshdev_wx_get_enc,         /* SIOCGIWENCODE */
+	dummy,                    /* SIOCSIWPOWER */
+	dummy,                    /* SIOCGIWPOWER */
+	NULL,			/*---hole---*/
+	NULL, 			/*---hole---*/
+	meshdev_wx_set_gen_ie,
+	NULL, 			/* SIOCSIWGENIE */
+	meshdev_wx_set_auth,
+	NULL, 
+	meshdev_wx_set_enc_ext, 			/* SIOCSIWENCODEEXT */
+	NULL, 
+	(iw_handler) rt_ioctl_siwpmksa,
+	NULL, 			 /*---hole---*/
+}; 
+
+static struct iw_priv_args meshdev_private_args[] = { 
+	{
+		SIOCIWFIRSTPRIV + 0x0, 
+		0, 0, "enablemesh" 
+ 	},
+	{
+		SIOCIWFIRSTPRIV + 0x1, 
+		0, IW_PRIV_TYPE_CHAR | 64, "getmeshinfo"
+ 	},
+	{
+		SIOCIWFIRSTPRIV + 0x2, 
+		0, 0, "disablemesh"
+ 	},
+ 	{
+		SIOCIWFIRSTPRIV + 0x3, 
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setch"
+ 	},
+ 	{
+		SIOCIWFIRSTPRIV + 0x4, 
+		IW_PRIV_TYPE_CHAR | 64  , 0, "setmeshid"
+ 	},
+        {	SIOCIWFIRSTPRIV + 0x5, 
+		0,IW_PRIV_TYPE_CHAR | 64 , "getmeshlist"
+ 	},
+	{	SIOCIWFIRSTPRIV + 0x6, 
+		IW_PRIV_TYPE_CHAR | 64,0 , "meshscan"
+ 	},
+	{
+		SIOCIWFIRSTPRIV + 0x7,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setmode"
+
+	},
+ 	{
+		SIOCIWFIRSTPRIV + 0x8, 
+		IW_PRIV_TYPE_CHAR | 64, 0, "sethostname"
+ 	},
+	{
+		SIOCIWFIRSTPRIV + 0x9,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setBW"
+
+	},
+	{
+		SIOCIWFIRSTPRIV + 0xa, 
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "updateBW"
+ 	}, 
+ 	{	SIOCIWFIRSTPRIV + 0xb, 
+		0,IW_PRIV_TYPE_CHAR | 256 , "macdenyget"
+ 	},
+ 	{	SIOCIWFIRSTPRIV + 0xc, 
+		IW_PRIV_TYPE_CHAR | 64,0 , "macdenyadd"
+ 	},
+	/*
+	{
+		SIOCIWFIRSTPRIV + 0xe, 
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, ""
+ 	},*/
+        {	SIOCIWFIRSTPRIV + 0xf, 
+		0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK , "getneighborlist"
+ 	},
+	/* Sub-ioctls definitions*/
+	/*
+	{
+		OID_802_11_MESH_ID, 
+		IW_PRIV_TYPE_INT | 2047, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, "meshid"
+	},
+	{
+		OID_802_11_MESH_LIST, 
+		IW_PRIV_TYPE_INT | 2047, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, "meshlist"
+	},*/
+	{	SIOCIWFIRSTPRIV + 0x10, 
+		IW_PRIV_TYPE_CHAR | 64, 0, "set"
+ 	},
+	{	SIOCIWFIRSTPRIV + 0x12, 
+		IW_PRIV_TYPE_CHAR | 64,0 , "macdenydel"
+ 	},
+	{
+		SIOCIWFIRSTPRIV + 0x14,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setmeshsec"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x15,
+		IW_PRIV_TYPE_CHAR | 6, 0, "setmkddid"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x16,
+		IW_PRIV_TYPE_CHAR | 64, 0, "setkey"
+	},
+	{
+		SIOCIWFIRSTPRIV + 0x17,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setsectype"
+	},
+};
+
+int meshdev_wx_mesh(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *meshpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device * ieee = meshpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct mshclass *mshobj = priv->mshobj;
+	int ret = 0;
+
+	printk("@@@@@%s: ", __FUNCTION__);
+	if(mshobj)
+	{
+		switch(wrqu->data.flags)
+		{
+			case OID_802_11_MESH_SECURITY_INFO:
+			{
+				printk("OID_802_11_MESH_SECURITY_INFO \n");
+				if(mshobj->ext_patch_r819x_wx_get_security_info)
+					ret = mshobj->ext_patch_r819x_wx_get_security_info(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_ID:
+			{
+				printk("OID_802_11_MESH_ID \n");
+				if(mshobj->ext_patch_r819x_wx_get_meshid)
+					ret = mshobj->ext_patch_r819x_wx_get_meshid(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_AUTO_LINK:
+			{
+				printk("OID_802_11_MESH_AUTO_LINK \n");
+				if(mshobj->ext_patch_r819x_wx_get_auto_link)
+					ret = mshobj->ext_patch_r819x_wx_get_auto_link(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_LINK_STATUS:
+			{
+				printk("OID_802_11_MESH_LINK_STATUS \n");
+				if(mshobj->ext_patch_r819x_wx_get_link_status)
+					ret = mshobj->ext_patch_r819x_wx_get_link_status(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_LIST:
+			{
+				printk("OID_802_11_MESH_LIST \n");
+				if(mshobj->ext_patch_r819x_wx_get_neighbor_list)
+					ret = mshobj->ext_patch_r819x_wx_get_neighbor_list(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_ROUTE_LIST:
+			{
+				printk("OID_802_11_MESH_ROUTE_LIST \n");
+				if(mshobj->ext_patch_r819x_wx_get_route_list)
+					ret = mshobj->ext_patch_r819x_wx_get_route_list(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_MAX_TX_RATE:
+			{
+				printk("OID_802_11_MESH_MAX_TX_RATE \n");
+				if(mshobj->ext_patch_r819x_wx_get_maxrate)
+					ret = mshobj->ext_patch_r819x_wx_get_maxrate(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_CHANNEL:
+			{
+				printk("OID_802_11_MESH_CHANNEL \n");
+				if(mshobj->ext_patch_r819x_wx_get_channel)
+					ret = mshobj->ext_patch_r819x_wx_get_channel(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_HOSTNAME:
+			{
+				printk("OID_802_11_MESH_HOSTNAME \n");
+				if(mshobj->ext_patch_r819x_wx_get_host_name)
+					ret = mshobj->ext_patch_r819x_wx_get_host_name(dev, info, wrqu, extra);
+				break;
+			}
+			case OID_802_11_MESH_ONLY_MODE:
+			{
+				printk("OID_802_11_MESH_ONLY_MODE \n");
+				if(mshobj->ext_patch_r819x_wx_get_mesh_only_mode)
+					ret = mshobj->ext_patch_r819x_wx_get_mesh_only_mode(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_SECURITY_INFO:
+			{
+				printk("RTL_OID_802_11_MESH_SECURITY_INFO \n");
+				if(mshobj->ext_patch_r819x_wx_set_security_info)
+					ret = mshobj->ext_patch_r819x_wx_set_security_info(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_ID:
+			{
+				printk("RTL_OID_802_11_MESH_ID \n");
+				if(mshobj->ext_patch_r819x_wx_set_meshID)
+					ret = mshobj->ext_patch_r819x_wx_set_meshID(dev, (u8*)wrqu->data.pointer);
+				break;
+			}
+			case RTL_OID_802_11_MESH_AUTO_LINK:
+			{
+				printk("RTL_OID_802_11_MESH_AUTO_LINK \n");
+				if(mshobj->ext_patch_r819x_wx_set_auto_link)
+					ret = mshobj->ext_patch_r819x_wx_set_auto_link(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_ADD_LINK:
+			{
+				printk("RTL_OID_802_11_MESH_ADD_LINK \n");
+				if(mshobj->ext_patch_r819x_wx_set_add_link)
+					ret = mshobj->ext_patch_r819x_wx_set_add_link(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_DEL_LINK:
+			{
+				printk("RTL_OID_802_11_MESH_DEL_LINK \n");
+				if(mshobj->ext_patch_r819x_wx_set_del_link)
+					ret = mshobj->ext_patch_r819x_wx_set_del_link(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_MAX_TX_RATE:
+			{
+				printk("RTL_OID_802_11_MESH_MAX_TX_RATE \n");
+				if(mshobj->ext_patch_r819x_wx_set_maxrate)
+					ret = mshobj->ext_patch_r819x_wx_set_maxrate(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_CHANNEL:
+			{
+				printk("RTL_OID_802_11_MESH_CHANNEL \n");
+				printk("channel = %d\n",*(u8*)wrqu->data.pointer);
+				r8192_wx_set_channel(dev, info, wrqu, wrqu->data.pointer);
+				break;
+			}
+			case RTL_OID_802_11_MESH_HOSTNAME:
+			{
+				printk("RTL_OID_802_11_MESH_HOSTNAME \n");
+				if(mshobj->ext_patch_r819x_wx_set_host_name)
+					ret = mshobj->ext_patch_r819x_wx_set_host_name(dev, info, wrqu, extra);
+				break;
+			}
+			case RTL_OID_802_11_MESH_ONLY_MODE:
+			{
+				printk("RTL_OID_802_11_MESH_ONLY_MODE \n");
+				if(mshobj->ext_patch_r819x_wx_set_mesh_only_mode)
+					ret = mshobj->ext_patch_r819x_wx_set_mesh_only_mode(dev, info, wrqu, extra);
+				break;
+			}
+			default:
+				printk("Default \n");
+				break;
+		}
+	}
+	return ret;
+}
+
+static int meshdev_wx_get_meshinfo(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct net_device *dev = mpriv->rtllib->dev;
+	
+printk("++++++======%s: dev=%p length=%d extra=%p\n", __FUNCTION__, dev, wrqu->data.length,extra);
+	return r8192_wx_get_meshinfo(dev, info, wrqu, extra);
+}
+
+static int meshdev_wx_enable_mesh(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_enable_mesh(dev, info, wrqu, extra);
+	
+}
+
+static int meshdev_wx_disable_mesh(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_disable_mesh(dev, info, wrqu, extra);
+}
+
+
+int meshdev_wx_set_channel(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+printk("++++++======%s\n", __FUNCTION__);
+
+	return r8192_wx_set_channel(dev, info, wrqu, extra);
+}
+
+static int meshdev_wx_set_meshid(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{	
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+printk("++++++======%s\n", __FUNCTION__);
+
+	return r8192_wx_set_meshID(dev, info, wrqu, extra);	
+}
+
+static int meshdev_wx_mesh_scan(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_mesh_scan(dev, info, wrqu, extra);
+}
+static int meshdev_wx_get_mesh_list(struct net_device *meshdev, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+printk("++++++======%s\n", __FUNCTION__);
+
+	return r8192_wx_get_mesh_list(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_meshmode(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_meshmode(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_meshbw(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_meshBW(dev, info, wrqu, extra);
+}
+static int meshdev_wx_update_beacon(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct mshclass *mshobj= (priv)->mshobj;
+	u8 updateBW = 0;
+	u8 bserverHT = 0;	
+	
+	printk("++++++======%s\n", __FUNCTION__);
+	if(*extra == 0)
+	{
+		ieee->p2pmode = 1;
+		ieee->current_network.channel = ieee->current_mesh_network.channel; 
+		if(ieee->state!=RTLLIB_LINKED){
+			if(ieee->pHTInfo->bCurBW40MHz)
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+			else
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+		}
+	}
+	else
+	{
+		ieee->p2pmode = 0;
+		updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT);
+		printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n", ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT);
+		if(updateBW == 1)
+		{
+			if(bserverHT == 0)
+			{
+				printk("===>server is not HT supported,set 20M\n");
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);  
+			}
+			else
+			{
+				printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset);		
+				if(ieee->pHTInfo->bCurBW40MHz)
+					HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset);  
+				else
+					HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset);  
+			}
+		}
+		else
+		{
+			printk("===>there is no same hostname server, ERR!!!\n");
+			return -1;
+		}
+	}
+	write_nic_dword(dev,BSSIDR,((u32*)priv->rtllib->current_mesh_network.bssid)[0]);
+	write_nic_word(dev,BSSIDR+4,((u16*)priv->rtllib->current_mesh_network.bssid)[2]);
+	return 0;
+}
+static int meshdev_wx_add_mac_deny(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny(dev, info, wrqu, extra);
+}
+
+static int meshdev_wx_del_mac_deny(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny(dev, info, wrqu, extra);
+}
+
+static int meshdev_wx_get_neighbor_list(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret = 0;
+
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_neighbor_list )
+		return 0;
+	ret = priv->mshobj->ext_patch_r819x_wx_get_neighbor_list(dev, info, wrqu, extra);
+#ifdef MESH_AUTO_TEST
+	ret |= r8192_wx_set_channel(dev, info, wrqu, &ieee->current_network.channel);
+#endif
+	return ret;
+}
+
+/* reserved for future
+static int r819x_wx_get_mac_allow(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_get_mac_allow(dev, info, wrqu, extra);
+}
+*/
+
+static int meshdev_wx_get_mac_deny(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mac_deny )
+		return 0;
+
+	return priv->mshobj->ext_patch_r819x_wx_get_mac_deny(dev, info, wrqu, extra);
+}
+
+
+static int meshdev_wx_set_hostname(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+
+	if(wrqu->data.length > MAX_HOST_NAME_LENGTH)
+	{
+		printk("%s: Host name is too long. len=%d\n", __FUNCTION__, wrqu->data.length);
+		return -1;
+	}
+
+	ieee->hostname_len = wrqu->data.length;
+	memcpy(ieee->hostname, extra, wrqu->data.length);
+	
+printk("++++++======%s: %s\n", __FUNCTION__, ieee->hostname);
+
+	return 0;
+}
+static int meshdev_wx_set_mesh_security(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = netdev_priv(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_mesh_security(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_mkdd_id(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = netdev_priv(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	
+
+	printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_mkdd_id(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_mesh_key(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = netdev_priv(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_mesh_key(dev, info, wrqu, extra);
+}
+static int meshdev_wx_set_sec_type(struct net_device *meshdev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct meshdev_priv *mpriv = netdev_priv(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+
+	printk("++++++======%s\n", __FUNCTION__);
+	return r8192_wx_set_mesh_sec_type(dev, info, wrqu, extra);
+}
+static u8 my_atoi(const char *arg)
+{
+	u8 val = 0;
+	for(; ; arg++){
+		switch (*arg){
+			case '0'...'9':
+				val = 10*val + (*arg-'0');
+				break;
+			default:
+				return val;
+		}
+	}
+	return val;
+}
+
+static int Set_Channel_Proc(struct net_device *meshdev, char *arg)
+{
+	int ch = my_atoi(arg);
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	struct net_device *dev = ieee->dev;
+
+	if (!priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_channel || !ieee->only_mesh)
+		return 0;	
+			
+printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!set current mesh network channel %d\n", ch);
+	if ( ch < 0 ) 	
+	{
+		rtllib_start_scan(ieee);			
+		ieee->meshScanMode =2;
+	}
+	else	
+	{	
+		ieee->meshScanMode =0;		
+		if(priv->mshobj->ext_patch_r819x_wx_set_channel)
+		{
+			priv->mshobj->ext_patch_r819x_wx_set_channel(ieee, ch);
+			priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch);
+		}
+		queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq);
+		ieee->set_chan(ieee->dev, ch);
+		ieee->current_mesh_network.channel = ch;
+		if(ieee->only_mesh)
+			ieee->current_network.channel = ch;
+		ieee->current_network.channel = ieee->current_mesh_network.channel; 
+		if(ieee->pHTInfo->bCurBW40MHz)
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+		else
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+		if(rtllib_act_scanning(ieee,true) == true)
+			rtllib_stop_scan_syncro(ieee);
+	}
+	return 0;		
+}
+static int Set_MeshID_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	RT_RF_POWER_STATE       rtState;
+	int ret = 0;
+        rtState = priv->rtllib->eRFPowerState;
+	
+	if(!priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_enable_mesh || !priv->mshobj->ext_patch_r819x_wx_set_meshID)
+		return 0;
+
+	if(rtllib_act_scanning(ieee,true) == true)
+		rtllib_stop_scan_syncro(ieee);
+	
+	/* Set Mesh ID */
+	ret = priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, arg);
+	if(ret)
+		goto End;
+	
+	/* Enable Mesh */
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = priv->mshobj->ext_patch_r819x_wx_enable_mesh(dev);
+	if(!ret)
+	{
+#ifdef ENABLE_IPS
+		if(priv->rtllib->PowerSaveControl.bInactivePs){
+			if(rtState == eRfOff){
+				if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS)
+				{
+					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+					SEM_UP_PRIV_WX(&priv->wx_sem);	
+					return -1;
+				}
+				else{
+					printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					IPSLeave(dev);
+				}
+			}
+		}
+#endif
+	}
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+#if 1
+	if (ieee->mesh_sec_type == 1) {	
+		rtl8192_abbr_handshk_set_GTK(ieee,1);
+	}
+#else
+	if (ieee->mesh_sec_type == 1) 	
+		rtl8192_abbr_handshk_set_key(ieee); 
+#endif
+End:
+	return ret;	
+}
+static int Set_Bw40MHz_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	u8 bBw40MHz = my_atoi(arg);
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	printk("%s(): set mesh BW ! extra is %d\n",__FUNCTION__, bBw40MHz);
+	priv->rtllib->pHTInfo->bRegBW40MHz = bBw40MHz;
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+
+	return 0;
+}
+static int Set_WirelessMode_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	struct net_device *dev = ieee->dev;
+	u8 wirelessmode = my_atoi(arg);
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+
+	printk("%s(): set mesh mode ! extra is %d\n",__FUNCTION__, wirelessmode);
+	if((wirelessmode != WIRELESS_MODE_A) && (wirelessmode != WIRELESS_MODE_B) && 
+		(wirelessmode != WIRELESS_MODE_G) && (wirelessmode != WIRELESS_MODE_AUTO) &&
+		(wirelessmode != WIRELESS_MODE_N_24G) && (wirelessmode != WIRELESS_MODE_N_5G))
+	{
+		printk("ERR!! you should input 1 | 2 | 4 | 8 | 16 | 32\n");
+		SEM_UP_PRIV_WX(&priv->wx_sem);	
+		return -1;
+	}
+	if(priv->rtllib->state == RTLLIB_LINKED)
+	{
+		if((priv->rtllib->mode != WIRELESS_MODE_N_5G) && (priv->rtllib->mode != WIRELESS_MODE_N_24G)){
+			printk("===>wlan0 is linked,and ieee->mode is not N mode ,do not need to set mode,return\n");
+			SEM_UP_PRIV_WX(&priv->wx_sem);	
+			return 0;
+		}
+	}
+	priv->rtllib->mode = wirelessmode;
+	if(priv->ResetProgress == RESET_TYPE_NORESET)
+		rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
+	HTUseDefaultSetting(priv->rtllib);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+	return 0;
+}
+static int Set_ExtChnOffset_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+#if 0
+	struct r8192_priv *priv = (void *)ieee->priv;
+	struct net_device *dev = ieee->dev;
+	struct mshclass *mshobj= priv->mshobj;
+	u8 updateBW = 0;
+	u8 bserverHT = 0;	
+#endif
+	ieee->p2pmode = 0;	
+#if 0
+	updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT);
+	printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n", ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT);
+	if(updateBW == 1)
+	{
+		if(bserverHT == 0)
+		{
+			printk("===>server is not HT supported,set 20M\n");
+			HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);  
+		}
+		else
+		{
+			printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset);		
+			if(ieee->pHTInfo->bCurBW40MHz)
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset);  
+			else
+				HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset);  
+		}
+	}
+	else
+	{
+		printk("===>there is no same hostname server, ERR!!!\n");
+		return -1;
+	}
+#endif
+	return 0;
+}
+static int Set_OnlyMesh_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	union iwreq_data tmprqu;
+	int ret = 0;
+
+	ieee->p2pmode = 1;	
+	ieee->only_mesh = my_atoi(arg);
+printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!mesh only = %d, p2pmode = %d\n", ieee->only_mesh, ieee->p2pmode);
+	if(ieee->only_mesh)
+		ieee->current_network.channel = ieee->current_mesh_network.channel;
+	if(ieee->only_mesh == 0)
+	{
+		tmprqu.mode = ieee->iw_mode;
+		ieee->iw_mode = IW_MODE_INFRA; 
+		ret = rtllib_wx_set_mode(ieee, NULL, &tmprqu, NULL);
+	}
+	return ret;
+}
+static int Set_AsPortal_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	u8 val = my_atoi(arg);
+	int ret = 0;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = priv->mshobj->ext_patch_r819x_wx_set_AsPortal(dev, val);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+
+	return ret;
+}
+static int Set_AsRoot_Proc(struct net_device *meshdev, char *arg)
+{
+	struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev);
+	struct rtllib_device *ieee = mpriv->rtllib;
+	struct net_device *dev = ieee->dev;
+	struct r8192_priv *priv = (void *)ieee->priv;
+	u8 val = my_atoi(arg);
+	int ret = 0;
+
+	SEM_DOWN_PRIV_WX(&priv->wx_sem);	
+	ret = priv->mshobj->ext_patch_r819x_wx_set_AsRoot(dev, val);
+	SEM_UP_PRIV_WX(&priv->wx_sem);	
+
+	return ret;
+}
+
+static struct {
+	char* name;
+	int (*set_proc)(struct net_device *dev, char *arg);
+} *private_set_proc, private_support_proc[] = {
+	{"Debug",				NULL},
+	{"Channel",				Set_Channel_Proc},            
+	{"MeshId",				Set_MeshID_Proc},
+	{"Bw40MHz",				Set_Bw40MHz_Proc},
+	{"WirelessMode",			Set_WirelessMode_Proc},
+	{"ExtChnOffset",			Set_ExtChnOffset_Proc},
+	{"OnlyMesh",				Set_OnlyMesh_Proc},
+	{"AsPortal",				Set_AsPortal_Proc},
+	{"AsRoot",				Set_AsRoot_Proc},
+	{"MeshAuthMode",			NULL},       
+	{"MeshEncrypType",			NULL},  
+	{"<NULL>",				NULL},
+};
+
+static char *rtlstrchr(const char *s, int c)
+{
+	for(; *s!=(char)c; ++s)
+		if(*s == '\0')
+			return NULL;
+	return (char *)s;
+}
+
+static int meshdev_wx_set_param(struct net_device *dev, struct iw_request_info *info,
+			       union iwreq_data *w, char *extra)
+{
+	char * this_char = extra;
+	char *value = NULL;
+	int  Status=0;
+
+	printk("=======>%s: extra=%s\n", __FUNCTION__,extra);
+	if (!*this_char)
+		return -EINVAL; 
+	
+	if ((value = rtlstrchr(this_char, '=')) != NULL)
+		*value++ = 0;
+
+	for (private_set_proc = private_support_proc; strcmp(private_set_proc->name, "<NULL>"); private_set_proc++)            
+	{
+		if (strcmp(this_char, private_set_proc->name) == 0)
+		{
+			if(private_set_proc->set_proc)
+			{
+				if(private_set_proc->set_proc(dev, value))
+				{	
+					Status = -EINVAL;
+				}
+			}
+			break;	
+		}
+	}
+	
+	if(strcmp(private_set_proc->name, "<NULL>") == 0)
+	{  
+		Status = -EINVAL;
+		printk("===>%s: (iwpriv) Not Support Set Command [%s]", __FUNCTION__, this_char);
+		if(value != NULL)
+			printk(" value=%s\n", value);
+		else
+			printk("\n");
+	}
+	
+	return Status;
+}
+
+
+static iw_handler meshdev_private_handler[] = {
+	meshdev_wx_enable_mesh,		
+	meshdev_wx_get_meshinfo, 		
+	meshdev_wx_disable_mesh,		
+	meshdev_wx_set_channel, 		
+	meshdev_wx_set_meshid,			
+	meshdev_wx_get_mesh_list, 		
+	meshdev_wx_mesh_scan, 			
+	meshdev_wx_set_meshmode,		
+	meshdev_wx_set_hostname,		
+	meshdev_wx_set_meshbw,			
+	meshdev_wx_update_beacon,		
+	meshdev_wx_get_mac_deny,		
+	meshdev_wx_add_mac_deny,		
+	NULL,			  		
+	NULL,
+	meshdev_wx_get_neighbor_list,		
+	meshdev_wx_set_param,			
+	NULL,			  		
+	meshdev_wx_del_mac_deny,		
+	NULL,							
+	meshdev_wx_set_mesh_security,		
+	meshdev_wx_set_mkdd_id,			
+	meshdev_wx_set_mesh_key,			
+	meshdev_wx_set_sec_type,		
+};
+
+struct iw_handler_def  meshdev_wx_handlers_def={
+	.standard = meshdev_wx_handlers,
+	.num_standard = sizeof(meshdev_wx_handlers) / sizeof(iw_handler),
+	.private = meshdev_private_handler,
+	.num_private = sizeof(meshdev_private_handler) / sizeof(iw_handler),
+ 	.num_private_args = sizeof(meshdev_private_args) / sizeof(struct iw_priv_args),
+#if WIRELESS_EXT >= 17	
+	.get_wireless_stats = (void*)meshdev_stats,
+#endif
+	.private_args = (struct iw_priv_args *)meshdev_private_args,	
+};
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/BOM
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/BOM
@@ -0,0 +1,2 @@
+Downloaded from:	http://www.realtek.com/products/productsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=230
+Current Version:	0015.0127.2010
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl_pm.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl_pm.c
@@ -0,0 +1,193 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifdef CONFIG_PM_RTL
+#ifdef RTL8192CE
+#include "rtl_core.h"
+#include "rtl8192c/r8192C_hw.h"
+#include "rtl8192c/r8192C_phy.h"
+#include "rtl8192c/r8192C_phyreg.h"
+#include "rtl8192c/r8192C_rtl6052.h"
+#elif defined RTL8192SE
+#include "rtl_core.h"
+#include "rtl8192s/r8192S_hw.h"
+#include "rtl8192s/r8192S_phy.h"
+#include "rtl8192s/r8192S_phyreg.h"
+#include "rtl8192s/r8192S_rtl6052.h"
+#else
+#include "rtl_core.h"
+#include "rtl8192e/r8192E_hw.h"
+#include "rtl8192e/r8190P_rtl8256.h"
+#endif
+#include "rtl_pm.h"
+
+int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+        printk(KERN_NOTICE "r8192E save state call (state %u).\n", state);
+#else
+        printk(KERN_NOTICE "r8192E save state call (state %u).\n", state.event);
+#endif
+	return(-EAGAIN);
+}
+
+
+int rtl8192E_suspend (struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct r8192_priv *priv = rtllib_priv(dev); 
+#if !(defined RTL8192SE || defined RTL8192CE)		
+	u32	ulRegRead;
+#endif
+
+        RT_TRACE(COMP_POWER, "============> r8192E suspend call.\n");
+        printk("============> r8192E suspend call.\n");
+#ifdef ENABLE_GPIO_RADIO_CTL
+	del_timer_sync(&priv->gpio_polling_timer);
+	cancel_delayed_work(&priv->gpio_change_rf_wq);
+	priv->polling_timer_on = 0;
+#endif
+
+        if (!netif_running(dev)){
+            printk("RTL819XE:UI is open out of suspend function\n");
+            goto out_pci_suspend;
+        }
+
+#ifdef HAVE_NET_DEVICE_OPS
+	if (dev->netdev_ops->ndo_stop)
+		dev->netdev_ops->ndo_stop(dev);
+#else
+	dev->stop(dev);
+#endif	
+	netif_device_detach(dev);
+
+#if !(defined RTL8192SE || defined RTL8192CE)		
+	if(!priv->rtllib->bSupportRemoteWakeUp) {
+		MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
+		ulRegRead = read_nic_dword(dev, CPU_GEN);	
+		ulRegRead|=CPU_GEN_SYSTEM_RESET;
+		write_nic_dword(dev, CPU_GEN, ulRegRead);
+	} else {
+		write_nic_dword(dev, WFCRC0, 0xffffffff);
+		write_nic_dword(dev, WFCRC1, 0xffffffff);
+		write_nic_dword(dev, WFCRC2, 0xffffffff);
+#ifdef RTL8190P
+		ucRegRead = read_nic_byte(dev, GPO);
+		ucRegRead |= BIT0;
+		write_nic_byte(dev, GPO, ucRegRead);
+#endif			
+		write_nic_byte(dev, PMR, 0x5);
+		write_nic_byte(dev, MacBlkCtrl, 0xa);
+	}
+#endif
+out_pci_suspend:
+	RT_TRACE(COMP_POWER, "r8192E support WOL call??????????????????????\n");
+	printk("r8192E support WOL call??????????????????????\n");
+	if(priv->rtllib->bSupportRemoteWakeUp) {
+		RT_TRACE(COMP_POWER, "r8192E support WOL call!!!!!!!!!!!!!!!!!!.\n");
+	}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+	pci_save_state(pdev,&(priv->pci_state));
+        pci_disable_device(pdev);
+        pci_enable_wake(pdev, state,\
+                        priv->rtllib->bSupportRemoteWakeUp?1:0);
+        pci_set_power_state(pdev,state);
+#else
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_enable_wake(pdev, pci_choose_state(pdev,state),\
+			priv->rtllib->bSupportRemoteWakeUp?1:0);
+	pci_set_power_state(pdev,pci_choose_state(pdev,state));
+#endif
+
+        mdelay(20);
+
+	return 0;
+}
+
+int rtl8192E_resume (struct pci_dev *pdev)
+{
+    struct net_device *dev = pci_get_drvdata(pdev);
+#ifdef ENABLE_GPIO_RADIO_CTL
+    struct r8192_priv *priv = rtllib_priv(dev); 
+#endif
+    int err;
+    u32 val;
+
+    RT_TRACE(COMP_POWER, "================>r8192E resume call.");
+    printk("================>r8192E resume call.\n");
+
+    pci_set_power_state(pdev, PCI_D0);
+
+    err = pci_enable_device(pdev);
+    if(err) {
+        printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
+                dev->name);
+        return err;
+    }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+    pci_restore_state(pdev,&(priv->pci_state));
+#else
+    pci_restore_state(pdev);
+#endif
+
+    pci_read_config_dword(pdev, 0x40, &val);
+    if ((val & 0x0000ff00) != 0) {
+        pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+    }
+
+    pci_enable_wake(pdev, PCI_D0, 0);
+
+#ifdef ENABLE_GPIO_RADIO_CTL
+    if(priv->polling_timer_on == 0){
+        check_rfctrl_gpio_timer((unsigned long)dev);
+    }
+#endif
+
+    if(!netif_running(dev)){
+        printk("RTL819XE:UI is open out of resume function\n");
+        goto out;
+    }
+
+    netif_device_attach(dev);
+#ifdef HAVE_NET_DEVICE_OPS
+    if (dev->netdev_ops->ndo_open)
+	    dev->netdev_ops->ndo_open(dev);
+#else
+    dev->open(dev);
+#endif    
+out:
+    RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
+    return 0;
+}
+
+
+int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+        printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", 
+	       state, enable);
+#else
+        printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", 
+	       state.event, enable);
+#endif
+	return(-EAGAIN);
+}
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_tkip.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_crypt_tkip.c
@@ -0,0 +1,1047 @@
+/*
+ * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <asm/string.h>
+#ifdef _RTL8192_EXT_PATCH_	
+#include <linux/etherdevice.h>
+#endif
+#include "rtllib.h"
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20))
+#endif
+
+
+#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "rtl_crypto.h"
+#else
+#include <linux/crypto.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) 
+    #include <asm/scatterlist.h>
+#else
+        #include <linux/scatterlist.h>
+#endif
+       
+#include <linux/crc32.h>
+
+#ifndef BUILT_IN_RTLLIB
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: TKIP");
+MODULE_LICENSE("GPL");
+#endif
+
+
+struct rtllib_tkip_data {
+#define TKIP_KEY_LEN 32
+	u8 key[TKIP_KEY_LEN];
+	int key_set;
+
+	u32 tx_iv32;
+	u16 tx_iv16;
+	u16 tx_ttak[5];
+	int tx_phase1_done;
+
+	u32 rx_iv32;
+	u16 rx_iv16;
+      bool initialized;
+	u16 rx_ttak[5];
+	int rx_phase1_done;
+	u32 rx_iv32_new;
+	u16 rx_iv16_new;
+
+	u32 dot11RSNAStatsTKIPReplays;
+	u32 dot11RSNAStatsTKIPICVErrors;
+	u32 dot11RSNAStatsTKIPLocalMICFailures;
+
+	int key_idx;
+#if  ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
+	struct crypto_blkcipher *rx_tfm_arc4;
+	struct crypto_hash *rx_tfm_michael;
+	struct crypto_blkcipher *tx_tfm_arc4;
+	struct crypto_hash *tx_tfm_michael;
+#else
+	struct crypto_tfm *tx_tfm_arc4;
+	struct crypto_tfm *tx_tfm_michael;
+	struct crypto_tfm *rx_tfm_arc4;
+	struct crypto_tfm *rx_tfm_michael;
+#endif
+	/* scratch buffers for virt_to_page() (crypto API) */
+	u8 rx_hdr[16], tx_hdr[16];
+};
+
+static void * rtllib_tkip_init(int key_idx)
+{
+	struct rtllib_tkip_data *priv;
+
+	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+	if (priv == NULL)
+		goto fail;
+	memset(priv, 0, sizeof(*priv));
+	priv->key_idx = key_idx;
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	priv->tx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
+	if (priv->tx_tfm_arc4 == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API arc4\n");
+		goto fail;
+	}
+
+	priv->tx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
+	if (priv->tx_tfm_michael == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API michael_mic\n");
+		goto fail;
+	}
+
+	priv->rx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
+	if (priv->rx_tfm_arc4 == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API arc4\n");
+		goto fail;
+	}
+
+	priv->rx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
+	if (priv->rx_tfm_michael == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API michael_mic\n");
+		goto fail;
+	}
+#else
+	priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+			CRYPTO_ALG_ASYNC);
+	if (IS_ERR(priv->tx_tfm_arc4)) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API arc4\n");
+		priv->tx_tfm_arc4 = NULL;
+		goto fail;
+	}
+
+	priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
+			CRYPTO_ALG_ASYNC);
+	if (IS_ERR(priv->tx_tfm_michael)) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API michael_mic\n");
+		priv->tx_tfm_michael = NULL;
+		goto fail;
+	}
+
+	priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+			CRYPTO_ALG_ASYNC);
+	if (IS_ERR(priv->rx_tfm_arc4)) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API arc4\n");
+		priv->rx_tfm_arc4 = NULL;
+		goto fail;
+	}
+
+	priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
+			CRYPTO_ALG_ASYNC);
+	if (IS_ERR(priv->rx_tfm_michael)) {
+		printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate "
+				"crypto API michael_mic\n");
+		priv->rx_tfm_michael = NULL;
+		goto fail;
+	}
+#endif
+	return priv;
+
+fail:
+	if (priv) {
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		if (priv->tx_tfm_michael)
+			crypto_free_tfm(priv->tx_tfm_michael);
+		if (priv->tx_tfm_arc4)
+			crypto_free_tfm(priv->tx_tfm_arc4);
+		if (priv->rx_tfm_michael)
+			crypto_free_tfm(priv->rx_tfm_michael);
+		if (priv->rx_tfm_arc4)
+			crypto_free_tfm(priv->rx_tfm_arc4);
+
+#else
+		if (priv->tx_tfm_michael)
+			crypto_free_hash(priv->tx_tfm_michael);
+		if (priv->tx_tfm_arc4)
+			crypto_free_blkcipher(priv->tx_tfm_arc4);
+		if (priv->rx_tfm_michael)
+			crypto_free_hash(priv->rx_tfm_michael);
+		if (priv->rx_tfm_arc4)
+			crypto_free_blkcipher(priv->rx_tfm_arc4);
+#endif
+		kfree(priv);
+	}
+
+	return NULL;
+}
+
+
+static void rtllib_tkip_deinit(void *priv)
+{
+	struct rtllib_tkip_data *_priv = priv;
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	if (_priv->tx_tfm_michael)
+		crypto_free_tfm(_priv->tx_tfm_michael);
+	if (_priv->tx_tfm_arc4)
+		crypto_free_tfm(_priv->tx_tfm_arc4);
+	if (_priv->rx_tfm_michael)
+		crypto_free_tfm(_priv->rx_tfm_michael);
+	if (_priv->rx_tfm_arc4)
+		crypto_free_tfm(_priv->rx_tfm_arc4);
+#else
+	if (_priv) {
+		if (_priv->tx_tfm_michael)
+			crypto_free_hash(_priv->tx_tfm_michael);
+		if (_priv->tx_tfm_arc4)
+			crypto_free_blkcipher(_priv->tx_tfm_arc4);
+		if (_priv->rx_tfm_michael)
+			crypto_free_hash(_priv->rx_tfm_michael);
+		if (_priv->rx_tfm_arc4)
+			crypto_free_blkcipher(_priv->rx_tfm_arc4);
+	}
+#endif
+	kfree(priv);
+}
+
+
+static inline u16 RotR1(u16 val)
+{
+	return (val >> 1) | (val << 15);
+}
+
+
+static inline u8 Lo8(u16 val)
+{
+	return val & 0xff;
+}
+
+
+static inline u8 Hi8(u16 val)
+{
+	return val >> 8;
+}
+
+
+static inline u16 Lo16(u32 val)
+{
+	return val & 0xffff;
+}
+
+
+static inline u16 Hi16(u32 val)
+{
+	return val >> 16;
+}
+
+
+static inline u16 Mk16(u8 hi, u8 lo)
+{
+	return lo | (((u16) hi) << 8);
+}
+
+
+static inline u16 Mk16_le(u16 *v)
+{
+	return le16_to_cpu(*v);
+}
+
+
+static const u16 Sbox[256] =
+{
+	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+
+static inline u16 _S_(u16 v)
+{
+	u16 t = Sbox[Hi8(v)];
+	return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
+}
+
+
+#define PHASE1_LOOP_COUNT 8
+
+
+static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
+{
+	int i, j;
+
+	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
+	TTAK[0] = Lo16(IV32);
+	TTAK[1] = Hi16(IV32);
+	TTAK[2] = Mk16(TA[1], TA[0]);
+	TTAK[3] = Mk16(TA[3], TA[2]);
+	TTAK[4] = Mk16(TA[5], TA[4]);
+
+	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
+		j = 2 * (i & 1);
+		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
+		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
+		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
+		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
+		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
+	}
+}
+
+
+static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
+			       u16 IV16)
+{
+	/* Make temporary area overlap WEP seed so that the final copy can be
+	 * avoided on little endian hosts. */
+	u16 *PPK = (u16 *) &WEPSeed[4];
+
+	/* Step 1 - make copy of TTAK and bring in TSC */
+	PPK[0] = TTAK[0];
+	PPK[1] = TTAK[1];
+	PPK[2] = TTAK[2];
+	PPK[3] = TTAK[3];
+	PPK[4] = TTAK[4];
+	PPK[5] = TTAK[4] + IV16;
+
+	/* Step 2 - 96-bit bijective mixing using S-box */
+	PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
+	PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
+	PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
+	PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
+	PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
+	PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
+
+	PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
+	PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
+	PPK[2] += RotR1(PPK[1]);
+	PPK[3] += RotR1(PPK[2]);
+	PPK[4] += RotR1(PPK[3]);
+	PPK[5] += RotR1(PPK[4]);
+
+	/* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
+	 * WEPSeed[0..2] is transmitted as WEP IV */
+	WEPSeed[0] = Hi8(IV16);
+	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
+	WEPSeed[2] = Lo8(IV16);
+	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
+
+#ifdef __BIG_ENDIAN
+	{
+		int i;
+		for (i = 0; i < 6; i++)
+			PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
+	}
+#endif
+}
+
+
+static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct rtllib_tkip_data *tkey = priv;
+		int len;
+	u8 *pos;
+	struct rtllib_hdr_4addr *hdr;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+
+	#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
+	struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
+	int ret = 0;
+	#endif
+	u8 rc4key[16],  *icv;
+	u32 crc;
+#ifdef _RTL8192_EXT_PATCH_	
+	u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 is_broadcast_data = 0;
+#endif
+	struct scatterlist sg;
+
+	if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
+	    skb->len < hdr_len)
+		return -1;
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+#ifdef _RTL8192_EXT_PATCH_	
+	if(tcb_desc->badhoc == 0){
+		if(memcmp(hdr->addr1,broadcastaddr,6) == 0){
+			is_broadcast_data = 1;
+			tcb_desc->bHwSec = 0;
+		}
+		if(is_multicast_ether_addr(hdr->addr1)){
+			tcb_desc->bHwSec = 0;
+		}
+	}
+#endif
+#if 0
+printk("@@ tkey\n");
+printk("%x|", ((u32*)tkey->key)[0]);
+printk("%x|", ((u32*)tkey->key)[1]);
+printk("%x|", ((u32*)tkey->key)[2]);
+printk("%x|", ((u32*)tkey->key)[3]);
+printk("%x|", ((u32*)tkey->key)[4]);
+printk("%x|", ((u32*)tkey->key)[5]);
+printk("%x|", ((u32*)tkey->key)[6]);
+printk("%x\n", ((u32*)tkey->key)[7]);
+#endif
+
+	if (!tcb_desc->bHwSec)
+	{
+		if (!tkey->tx_phase1_done) {
+			tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
+					tkey->tx_iv32);
+			tkey->tx_phase1_done = 1;
+		}
+		tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
+	}
+	else
+	tkey->tx_phase1_done = 1;
+	
+	
+	len = skb->len - hdr_len;
+	pos = skb_push(skb, 8);
+	memmove(pos, pos + 8, hdr_len);
+	pos += hdr_len;
+
+	if (tcb_desc->bHwSec)
+	{
+		*pos++ = Hi8(tkey->tx_iv16);
+		*pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
+		*pos++ = Lo8(tkey->tx_iv16);
+	}
+	else
+	{
+		*pos++ = rc4key[0];
+		*pos++ = rc4key[1];
+		*pos++ = rc4key[2];
+	}
+
+	*pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
+	*pos++ = tkey->tx_iv32 & 0xff;
+	*pos++ = (tkey->tx_iv32 >> 8) & 0xff;
+	*pos++ = (tkey->tx_iv32 >> 16) & 0xff;
+	*pos++ = (tkey->tx_iv32 >> 24) & 0xff;
+
+	if (!tcb_desc->bHwSec)
+	{
+		icv = skb_put(skb, 4);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+		crc = ~crc32_le(~0, pos, len);
+#else
+		crc = ~ether_crc_le(len, pos);
+#endif
+		icv[0] = crc;
+		icv[1] = crc >> 8;
+		icv[2] = crc >> 16;
+		icv[3] = crc >> 24;
+
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		sg.page = virt_to_page(pos);
+		sg.offset = offset_in_page(pos);
+		sg.length = len + 4;
+#else		
+		sg_init_one(&sg, pos, len+4);
+#endif
+
+
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+		crypto_cipher_encrypt(tkey->tx_tfm_arc4, &sg, &sg, len + 4);
+#else
+		crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+		ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
+#endif
+
+	}
+
+	tkey->tx_iv16++;
+	if (tkey->tx_iv16 == 0) {
+		tkey->tx_phase1_done = 0;
+		tkey->tx_iv32++;
+	}
+
+	if (!tcb_desc->bHwSec)
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		return 0;
+	#else
+		return ret;
+	#endif
+	else
+        	return 0;
+
+
+}
+
+static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct rtllib_tkip_data *tkey = priv;
+	u8 keyidx, *pos;
+	u32 iv32;
+	u16 iv16;
+	struct rtllib_hdr_4addr *hdr;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
+	struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4};
+	#endif
+	u8 rc4key[16];
+	u8 icv[4];
+	u32 crc;
+	struct scatterlist sg;
+	int plen;
+	if (skb->len < hdr_len + 8 + 4)
+		return -1;
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	pos = skb->data + hdr_len;
+	keyidx = pos[3];
+	if (!(keyidx & (1 << 5))) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
+			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+		}
+		return -2;
+	}
+	keyidx >>= 6;
+	if (tkey->key_idx != keyidx) {
+		printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
+		       "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
+		return -6;
+	}
+	if (!tkey->key_set) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+			       " with keyid=%d that does not have a configured"
+			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+		}
+		return -3;
+	}
+	iv16 = (pos[0] << 8) | pos[2];
+	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+	pos += 8;
+
+	if (!tcb_desc->bHwSec || (skb->cb[0] == 1))
+	{
+		if ((iv32 < tkey->rx_iv32 ||
+		(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16))&&tkey->initialized) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+				" previous TSC %08x%04x received TSC "
+				"%08x%04x\n", MAC_ARG(hdr->addr2),
+				tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
+			}
+			tkey->dot11RSNAStatsTKIPReplays++;
+			return -4;
+		}
+                tkey->initialized = true;
+	
+		if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
+			tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
+			tkey->rx_phase1_done = 1;
+		}
+		tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
+	
+		plen = skb->len - hdr_len - 12;
+	
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		sg.page = virt_to_page(pos);
+		sg.offset = offset_in_page(pos);
+		sg.length = plen + 4;
+#else
+		sg_init_one(&sg, pos, plen+4);
+#endif
+
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+		crypto_cipher_decrypt(tkey->rx_tfm_arc4, &sg, &sg, plen + 4);
+#else
+		crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+		if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG ": TKIP: failed to decrypt "
+						"received packet from " MAC_FMT "\n",
+						MAC_ARG(hdr->addr2));
+			}
+			return -7;
+		}
+#endif
+	
+	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+		crc = ~crc32_le(~0, pos, plen);
+	#else
+		crc = ~ether_crc_le(plen, pos);
+	#endif
+		icv[0] = crc;
+		icv[1] = crc >> 8;
+		icv[2] = crc >> 16;
+		icv[3] = crc >> 24;
+	
+		if (memcmp(icv, pos + plen, 4) != 0) {
+			if (iv32 != tkey->rx_iv32) {
+				/* Previously cached Phase1 result was already lost, so
+				* it needs to be recalculated for the next packet. */
+				tkey->rx_phase1_done = 0;
+			}
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "TKIP: ICV error detected: STA="
+				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			}
+			tkey->dot11RSNAStatsTKIPICVErrors++;
+			return -5;
+		}
+
+	}
+
+	/* Update real counters only after Michael MIC verification has
+	 * completed */
+	tkey->rx_iv32_new = iv32;
+	tkey->rx_iv16_new = iv16;
+
+	/* Remove IV and ICV */
+	memmove(skb->data + 8, skb->data, hdr_len);
+	skb_pull(skb, 8);
+	skb_trim(skb, skb->len - 4);
+
+#ifdef JOHN_DUMP 
+if( ((u16*)skb->data)[0] & 0x4000){
+        printk("@@ rx decrypted skb->data");
+        int i;
+        for(i=0;i<skb->len;i++){
+                if( (i%24)==0 ) printk("\n");
+                printk("%2x ", ((u8*)skb->data)[i]);
+        }
+        printk("\n");
+}
+#endif /*JOHN_DUMP*/
+	return keyidx;
+}
+
+
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+static int michael_mic(struct crypto_tfm * tfm_michael, u8 *key, u8 *hdr,
+		       u8 *data, size_t data_len, u8 *mic)
+{
+	struct scatterlist sg[2];
+#if ( !defined(BUILT_IN_CRYPTO) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) )
+        struct hash_desc desc;
+        int ret = 0;
+#endif
+
+	if (tfm_michael == NULL){
+		printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
+		return -1;
+	}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+	sg[0].page = virt_to_page(hdr);
+	sg[0].offset = offset_in_page(hdr);
+	sg[0].length = 16;
+
+	sg[1].page = virt_to_page(data);
+	sg[1].offset = offset_in_page(data);
+	sg[1].length = data_len;
+#else
+	sg_init_table(sg, 2);
+	sg_set_buf(&sg[0], hdr, 16);
+	sg_set_buf(&sg[1], data, data_len);
+#endif
+
+#if ( defined(BUILT_IN_CRYPTO) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
+	crypto_digest_init(tfm_michael);
+        crypto_digest_setkey(tfm_michael, key, 8);
+        crypto_digest_update(tfm_michael, sg, 2);
+        crypto_digest_final(tfm_michael, mic);
+        return 0;
+#else
+if (crypto_hash_setkey(tkey->tfm_michael, key, 8))
+                return -1;
+
+              desc.tfm = tkey->tfm_michael;
+              desc.flags = 0;
+              ret = crypto_hash_digest(&desc, sg, data_len + 16, mic);
+              return ret;
+#endif
+}
+#else
+static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
+                       u8 * data, size_t data_len, u8 * mic)
+{
+        struct hash_desc desc;
+        struct scatterlist sg[2];
+
+        if (tfm_michael == NULL) {
+                printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
+                return -1;
+        }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+        sg[0].page = virt_to_page(hdr);
+        sg[0].offset = offset_in_page(hdr);
+        sg[0].length = 16;
+
+        sg[1].page = virt_to_page(data);
+        sg[1].offset = offset_in_page(data);
+        sg[1].length = data_len;
+#else
+        sg_init_table(sg, 2);
+        sg_set_buf(&sg[0], hdr, 16);
+        sg_set_buf(&sg[1], data, data_len);
+#endif
+
+        if (crypto_hash_setkey(tfm_michael, key, 8))
+                return -1;
+
+        desc.tfm = tfm_michael;
+        desc.flags = 0;
+        return crypto_hash_digest(&desc, sg, data_len + 16, mic);
+}
+#endif
+
+
+
+static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
+{
+	struct rtllib_hdr_4addr *hdr11;
+
+	hdr11 = (struct rtllib_hdr_4addr *) skb->data;
+	switch (le16_to_cpu(hdr11->frame_ctl) &
+		(RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
+	case RTLLIB_FCTL_TODS:
+		memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+		break;
+	case RTLLIB_FCTL_FROMDS:
+		memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+		memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
+		break;
+	case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
+		memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+		memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
+		break;
+	case 0:
+		memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+		memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+		break;
+	}
+		
+	hdr[12] = 0; /* priority */
+	
+	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
+}
+
+
+static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct rtllib_tkip_data *tkey = priv;
+	u8 *pos;
+	struct rtllib_hdr_4addr *hdr;
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+	if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
+		printk(KERN_DEBUG "Invalid packet for Michael MIC add "
+		       "(tailroom=%d hdr_len=%d skb->len=%d)\n",
+		       skb_tailroom(skb), hdr_len, skb->len);
+		return -1;
+	}
+
+	michael_mic_hdr(skb, tkey->tx_hdr);
+
+	if(RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
+		tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
+	}
+	pos = skb_put(skb, 8);
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
+				skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
+#else
+	if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
+				skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
+#endif
+		return -1;
+
+	return 0;
+}
+
+
+#if WIRELESS_EXT >= 18
+static void rtllib_michael_mic_failure(struct net_device *dev,
+				       struct rtllib_hdr_4addr *hdr,
+				       int keyidx)
+{
+	union iwreq_data wrqu;
+	struct iw_michaelmicfailure ev;
+
+	/* TODO: needed parameters: count, keyid, key type, TSC */
+	memset(&ev, 0, sizeof(ev));
+	ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
+	if (hdr->addr1[0] & 0x01)
+		ev.flags |= IW_MICFAILURE_GROUP;
+	else
+		ev.flags |= IW_MICFAILURE_PAIRWISE;
+	ev.src_addr.sa_family = ARPHRD_ETHER;
+	memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
+	memset(&wrqu, 0, sizeof(wrqu));
+	wrqu.data.length = sizeof(ev);
+	wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
+}
+#elif WIRELESS_EXT >= 15
+static void rtllib_michael_mic_failure(struct net_device *dev,
+				       struct rtllib_hdr_4addr *hdr,
+				       int keyidx)
+{
+	union iwreq_data wrqu;
+	char buf[128];
+
+	/* TODO: needed parameters: count, keyid, key type, TSC */
+	sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
+		MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+		MAC_ARG(hdr->addr2));
+	memset(&wrqu, 0, sizeof(wrqu));
+	wrqu.data.length = strlen(buf);
+	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+}
+#else /* WIRELESS_EXT >= 15 */
+static inline void rtllib_michael_mic_failure(struct net_device *dev,
+					      struct rtllib_hdr_4addr *hdr,
+					      int keyidx)
+{
+}
+#endif /* WIRELESS_EXT >= 15 */
+
+static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
+				     int hdr_len, void *priv, struct rtllib_device* ieee)
+{
+	struct rtllib_tkip_data *tkey = priv;
+	u8 mic[8];
+	struct rtllib_hdr_4addr *hdr;
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+	if (!tkey->key_set)
+		return -1;
+
+	michael_mic_hdr(skb, tkey->rx_hdr);
+	if(RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
+		tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
+	}
+
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
+				skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
+#else
+	if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
+				skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
+#endif 
+            	return -1;
+    
+	if ((memcmp(mic, skb->data + skb->len - 8, 8) != 0)||(ieee->force_mic_error)) {
+		struct rtllib_hdr_4addr *hdr;
+		hdr = (struct rtllib_hdr_4addr *) skb->data;
+		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
+		       "MSDU from " MAC_FMT " keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+		       keyidx);
+                printk("%d, force_mic_error = %d\n", (memcmp(mic, skb->data + skb->len - 8, 8) != 0),\
+                        ieee->force_mic_error); 
+		if (skb->dev) {
+                        printk("skb->dev != NULL\n");
+			rtllib_michael_mic_failure(skb->dev, hdr, keyidx);
+                }
+		tkey->dot11RSNAStatsTKIPLocalMICFailures++;
+                ieee->force_mic_error = false;
+		return -1;
+	}
+
+	/* Update TSC counters for RX now that the packet verification has
+	 * completed. */
+	tkey->rx_iv32 = tkey->rx_iv32_new;
+	tkey->rx_iv16 = tkey->rx_iv16_new;
+
+	skb_trim(skb, skb->len - 8);
+
+	return 0;
+}
+
+
+static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct rtllib_tkip_data *tkey = priv;
+	int keyidx;
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	struct crypto_tfm *tfm = tkey->tx_tfm_michael;
+	struct crypto_tfm *tfm2 = tkey->tx_tfm_arc4;
+	struct crypto_tfm *tfm3 = tkey->rx_tfm_michael;
+	struct crypto_tfm *tfm4 = tkey->rx_tfm_arc4;
+#else
+	struct crypto_hash *tfm = tkey->tx_tfm_michael;
+	struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
+	struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
+	struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
+#endif
+
+	keyidx = tkey->key_idx;
+	memset(tkey, 0, sizeof(*tkey));
+	tkey->key_idx = keyidx;
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	tkey->tx_tfm_michael = tfm;
+	tkey->tx_tfm_arc4 = tfm2;
+	tkey->rx_tfm_michael = tfm3;
+	tkey->rx_tfm_arc4 = tfm4;
+#else
+	tkey->tx_tfm_michael = tfm;
+	tkey->tx_tfm_arc4 = tfm2;
+	tkey->rx_tfm_michael = tfm3;
+	tkey->rx_tfm_arc4 = tfm4;
+#endif
+
+	if (len == TKIP_KEY_LEN) {
+		memcpy(tkey->key, key, TKIP_KEY_LEN);
+		tkey->key_set = 1;
+		tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
+		if (seq) {
+			tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
+				(seq[3] << 8) | seq[2];
+			tkey->rx_iv16 = (seq[1] << 8) | seq[0];
+		}
+	} else if (len == 0)
+		tkey->key_set = 0;
+	else
+		return -1;
+
+	return 0;
+}
+
+
+static int rtllib_tkip_get_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct rtllib_tkip_data *tkey = priv;
+
+	if (len < TKIP_KEY_LEN)
+		return -1;
+
+	if (!tkey->key_set)
+		return 0;
+	memcpy(key, tkey->key, TKIP_KEY_LEN);
+
+	if (seq) {
+		/* Return the sequence number of the last transmitted frame. */
+		u16 iv16 = tkey->tx_iv16;
+		u32 iv32 = tkey->tx_iv32;
+		if (iv16 == 0)
+			iv32--;
+		iv16--;
+		seq[0] = tkey->tx_iv16;
+		seq[1] = tkey->tx_iv16 >> 8;
+		seq[2] = tkey->tx_iv32;
+		seq[3] = tkey->tx_iv32 >> 8;
+		seq[4] = tkey->tx_iv32 >> 16;
+		seq[5] = tkey->tx_iv32 >> 24;
+	}
+
+	return TKIP_KEY_LEN;
+}
+
+
+static char * rtllib_tkip_print_stats(char *p, void *priv)
+{
+	struct rtllib_tkip_data *tkip = priv;
+	p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
+		     "tx_pn=%02x%02x%02x%02x%02x%02x "
+		     "rx_pn=%02x%02x%02x%02x%02x%02x "
+		     "replays=%d icv_errors=%d local_mic_failures=%d\n",
+		     tkip->key_idx, tkip->key_set,
+		     (tkip->tx_iv32 >> 24) & 0xff,
+		     (tkip->tx_iv32 >> 16) & 0xff,
+		     (tkip->tx_iv32 >> 8) & 0xff,
+		     tkip->tx_iv32 & 0xff,
+		     (tkip->tx_iv16 >> 8) & 0xff,
+		     tkip->tx_iv16 & 0xff,
+		     (tkip->rx_iv32 >> 24) & 0xff,
+		     (tkip->rx_iv32 >> 16) & 0xff,
+		     (tkip->rx_iv32 >> 8) & 0xff,
+		     tkip->rx_iv32 & 0xff,
+		     (tkip->rx_iv16 >> 8) & 0xff,
+		     tkip->rx_iv16 & 0xff,
+		     tkip->dot11RSNAStatsTKIPReplays,
+		     tkip->dot11RSNAStatsTKIPICVErrors,
+		     tkip->dot11RSNAStatsTKIPLocalMICFailures);
+	return p;
+}
+
+
+static struct rtllib_crypto_ops rtllib_crypt_tkip = {
+	.name			= "TKIP",
+	.init			= rtllib_tkip_init,
+	.deinit			= rtllib_tkip_deinit,
+	.encrypt_mpdu		= rtllib_tkip_encrypt,
+	.decrypt_mpdu		= rtllib_tkip_decrypt,
+	.encrypt_msdu		= rtllib_michael_mic_add,
+	.decrypt_msdu		= rtllib_michael_mic_verify,
+	.set_key		= rtllib_tkip_set_key,
+	.get_key		= rtllib_tkip_get_key,
+	.print_stats		= rtllib_tkip_print_stats,
+	.extra_prefix_len	= 4 + 4, /* IV + ExtIV */
+	.extra_postfix_len	= 8 + 4, /* MIC + ICV */
+	.owner		        = THIS_MODULE,
+};
+
+
+int __init rtllib_crypto_tkip_init(void)
+{
+	return rtllib_register_crypto_ops(&rtllib_crypt_tkip);
+}
+
+
+void __exit rtllib_crypto_tkip_exit(void)
+{
+	rtllib_unregister_crypto_ops(&rtllib_crypt_tkip);
+}
+
+void rtllib_tkip_null(void)
+{
+        return;
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_tkip_null);
+
+module_init(rtllib_crypto_tkip_init);
+module_exit(rtllib_crypto_tkip_exit);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/readme
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/readme
@@ -0,0 +1,162 @@
+What this layer should do
+
+- It mantain the old mechanism as alternative, so the
+  ipw2100 driver works with really few changes.
+- Encapsulate / Decapsulate rtllib packet 
+- Handle fragmentation 
+- Optionally provide an alterantive mechanism for netif queue stop/wake, 
+  so that the rtllib layer will pass one fragment per time instead of
+  one txb struct per time. so the driver can stop the queue in the middle
+  of a packet.
+- Provide two different TX interfaces for cards that can handle management
+  frames on one HW queue, and data on another, and for cards that have only
+  one HW queue  (the latter untested and very, very rough).
+- Optionally provide the logic for handling IBSS/MASTER/MONITOR/BSS modes
+  and for the channel, essid and wap get/set wireless extension requests.
+  so that the driver has only to change channel when the ieee stack tell it.
+- Optionally provide a scanning mechanism so that the driver has not to
+  worry about this, just implement the set channel calback and pass 
+  frames to the upper layer
+- Optionally provide the bss client protocol handshaking (just with open 
+  authentication)
+- Optionally provide the probe request send mechanism
+- Optionally provide the bss master mode logic to handle association
+  protocol (only open authentication) and probe responses.
+- SW wep encryption (with open authentication)
+- It collects some stats
+- It provides beacons to the card when it ask for them
+
+What this layer doesn't do (yet)
+- Perform shared authentication
+- Have full support for master mode (the AP should loop back in the air
+  frames from an associated client to another. This could be done easily
+  with few lines of code, and it is done in my previous version of the 
+  stach, but a table of association must be keept and a disassociation
+  policy must be decided and implemented.
+- Handle cleanly the full ieee 802.11 protocol. In AP mode it never
+  disassociate clients, and it is really prone to always allow access.
+  In bss client mode it is a bit rough with AP deauth and disassoc requests.
+- It has not any entry point to view the collected stats.
+- Altought it takes care of the card supported rates in the management frame
+  it sends, support for rate changing on TXed packet is not complete.
+- Give up once associated in bss client mode (it never detect a
+  signal loss condition to disassociate and restart scanning)
+- Provide a mechanism for enabling the TX in monitor mode, so
+  userspace programs can TX raw packets.
+- Provide a mechanism for cards that need that the SW take care of beacon
+  TX completely, in sense that the SW has to enqueue by itself beacons
+  to the card so it TX them (if any...)
+APIs
+
+Callback functions in the original stack has been mantained.
+following has been added (from rtllib.h)
+
+	/* Softmac-generated frames (mamagement) are TXed via this 
+	 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is 
+	 * not set. As some cards may have different HW queues that 
+	 * one might want to use for data and management frames
+	 * the option to have two callbacks might be useful.
+	 * This fucntion can't sleep.
+	 */
+	int (*softmac_hard_start_xmit)(struct sk_buff *skb,
+			       struct net_device *dev);
+	
+	/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
+	 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
+	 * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
+	 * then also management frames are sent via this callback.
+	 * This function can't sleep.
+	 */    
+	void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
+			       struct net_device *dev);
+
+	/* stops the HW queue for DATA frames. Useful to avoid
+	 * waste time to TX data frame when we are reassociating
+	 * This function can sleep.
+	 */	 
+	void (*data_hard_stop)(struct net_device *dev);
+	
+	/* OK this is complementar to data_poll_hard_stop */
+	void (*data_hard_resume)(struct net_device *dev);
+	
+	/* ask to the driver to retune the radio .
+	 * This function can sleep. the driver should ensure
+	 * the radio has been swithced before return.
+	 */
+	void (*set_chan)(struct net_device *dev,short ch);
+	
+	/* These are not used if the ieee stack takes care of
+	 * scanning (IEEE_SOFTMAC_SCAN feature set). 
+	 * In this case only the set_chan is used.
+	 *
+	 * The syncro version is similar to the start_scan but
+	 * does not return until all channels has been scanned.
+	 * this is called in user context and should sleep, 
+	 * it is called in a work_queue when swithcing to ad-hoc mode
+	 * or in behalf of iwlist scan when the card is associated 
+	 * and root user ask for a scan. 
+	 * the fucntion stop_scan should stop both the syncro and
+	 * background scanning and can sleep.
+	 * The fucntion start_scan should initiate the background 
+	 * scanning and can't sleep.
+	 */ 
+	void (*scan_syncro)(struct net_device *dev);
+	void (*start_scan)(struct net_device *dev);
+	void (*stop_scan)(struct net_device *dev);
+	
+	/* indicate the driver that the link state is changed
+	 * for example it may indicate the card is associated now.
+	 * Driver might be interested in this to apply RX filter 
+	 * rules or simply light the LINK led 
+	 */
+	void (*link_change)(struct net_device *dev);
+	
+Functions hard_data_[resume/stop] are optional and should not be used
+if the driver decides to uses data+management frames enqueue in a 
+single HQ queue (thus using just the softmac_hard_data_start_xmit 
+callback).
+ 
+Function that the driver can use are:
+
+rtllib_get_beacon             - this is called by the driver when
+                                   the HW needs a beacon.
+rtllib_softmac_start_protocol - this should normally be called in the
+                                   driver open function
+rtllib_softmac_stop_protocol  - the opposite of the above
+rtllib_wake_queue             - this is similar to netif_wake_queue 
+rtllib_reset_queue            - this throw away fragments pending(if any)
+rtllib_stop_queue             - this is similar to netif_stop_queue
+
+
+known BUGS:
+- When performing syncro scan (possiblily when swithcing to ad-hoc mode
+  and when running iwlist scan when associated) there is still an odd
+  behaviour.. I have not looked in this more accurately (yet).
+
+locking:
+locking is done by means of three structures.
+1- ieee->lock (by means of spin_[un]lock_irq[save/restore]
+2- ieee->wx_sem
+3- ieee->scan_sem
+
+the lock 1 is what protect most of the critical sections in the ieee stack.
+the lock 2 is used to avoid that more than one of the SET wireless extension 
+handlers (as well as start/stop protocol function) are running at the same time. 
+the lock 1 is used when we need to modify or read the shared data in the wx handlers. 
+In other words the lock 2 will prevent one SET action will run across another SET
+action (by make sleep the 2nd one) but allow GET actions, while the lock 1
+make atomic those little shared data access in both GET and SET operation.
+So get operation will be never be delayed really: they will never sleep..
+Furthermore in the top of some SET operations a flag is set before acquiring
+the lock. This is an help to make the previous running SET operation to
+finish faster if needed (just in case the second one will totally undo the
+first, so there is not need to complete the 1st really.. ).
+The background scanning mechaninsm is protected by the lock 1 except for the
+workqueue. this wq is here just to let the set_chan callback sleep (I thinked it
+might be appreciated by USB network card driver developer). In this case the lock 3 
+take its turn. 
+Thus the stop function needs both the locks.
+Funny in the syncro scan the lock 2 play its role (as both the syncro_scan
+function and the stop scan function are called with this semaphore held).
+
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/EndianFree.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/EndianFree.h
@@ -0,0 +1,160 @@
+#ifndef __INC_ENDIANFREE_H
+#define __INC_ENDIANFREE_H
+
+/*
+ *	Call endian free function when
+ *		1. Read/write packet content.
+ *		2. Before write integer to IO.
+ *		3. After read integer from IO.
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+#ifndef bool
+typedef enum{false = 0, true} bool;
+#endif
+#endif
+
+#define __MACHINE_LITTLE_ENDIAN 1234    /* LSB first: i386, vax */
+#define __MACHINE_BIG_ENDIAN    4321    /* MSB first: 68000, ibm, net, ppc */
+
+#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN
+
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define EF1Byte(_val)				((u8)(_val))
+#define EF2Byte(_val)				((u16)(_val))
+#define EF4Byte(_val)				((u32)(_val))
+
+#else
+#define EF1Byte(_val)				((u8)(_val))
+#define EF2Byte(_val)				(((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8))
+#define EF4Byte(_val)				(((((u32)(_val))&0x000000ff)<<24)|\
+						((((u32)(_val))&0x0000ff00)<<8)|\
+						((((u32)(_val))&0x00ff0000)>>8)|\
+						((((u32)(_val))&0xff000000)>>24))
+#endif
+
+#define ReadEF1Byte(_ptr)		EF1Byte(*((u8 *)(_ptr)))
+#define ReadEF2Byte(_ptr)		EF2Byte(*((u16 *)(_ptr)))
+#define ReadEF4Byte(_ptr)		EF4Byte(*((u32 *)(_ptr)))
+
+#define WriteEF1Byte(_ptr, _val)	(*((u8 *)(_ptr)))=EF1Byte(_val)
+#define WriteEF2Byte(_ptr, _val)	(*((u16 *)(_ptr)))=EF2Byte(_val)
+#define WriteEF4Byte(_ptr, _val)	(*((u32 *)(_ptr)))=EF4Byte(_val)									
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define H2N1BYTE(_val)	((u8)(_val))
+#define H2N2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
+			((((u16)(_val))&0xff00)>>8))
+#define H2N4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
+			((((u32)(_val))&0x0000ff00)<<8)	|\
+			((((u32)(_val))&0x00ff0000)>>8)	|\
+			((((u32)(_val))&0xff000000)>>24))
+#else
+#define H2N1BYTE(_val)			((u8)(_val))
+#define H2N2BYTE(_val)			((u16)(_val))
+#define H2N4BYTE(_val)			((u32)(_val))
+#endif
+
+#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN
+#define N2H1BYTE(_val)	((u8)(_val))
+#define N2H2BYTE(_val)	(((((u16)(_val))&0x00ff)<<8)|\
+			((((u16)(_val))&0xff00)>>8))
+#define N2H4BYTE(_val)	(((((u32)(_val))&0x000000ff)<<24)|\
+			((((u32)(_val))&0x0000ff00)<<8)	|\
+			((((u32)(_val))&0x00ff0000)>>8)	|\
+			((((u32)(_val))&0xff000000)>>24))
+#else
+#define N2H1BYTE(_val)			((u8)(_val))
+#define N2H2BYTE(_val)			((u16)(_val))
+#define N2H4BYTE(_val)			((u32)(_val))
+#endif
+
+#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen)))
+#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset)) 
+
+#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart))))
+
+#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_32(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P4BYTE_TO_HOST_4BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u32 *)(__pStart)) = \
+	EF4Byte( \
+	LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \
+	| \
+	( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \
+       );
+
+
+#define BIT_LEN_MASK_16(__BitLen) \
+	(0xFFFF >> (16 - (__BitLen)))
+
+#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \
+	(BIT_LEN_MASK_16(__BitLen) << (__BitOffset))
+
+#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
+	(EF2Byte(*((u16 *)(__pStart))))
+
+#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_16(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P2BYTE_TO_HOST_2BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u16 *)(__pStart)) = \
+	EF2Byte( \
+		LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \
+		| \
+		( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \
+       );
+
+#define BIT_LEN_MASK_8(__BitLen) \
+	(0xFF >> (8 - (__BitLen)))
+
+#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \
+	(BIT_LEN_MASK_8(__BitLen) << (__BitOffset))
+
+#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
+	(EF1Byte(*((u8 *)(__pStart))))
+
+#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \
+	  & \
+	  BIT_LEN_MASK_8(__BitLen) \
+	)
+
+#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+	( \
+	  LE_P1BYTE_TO_HOST_1BYTE(__pStart) \
+	  & \
+	  ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \
+	)
+
+#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \
+	*((u8 *)(__pStart)) = \
+	EF1Byte( \
+		LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \
+		| \
+		( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \
+       );
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/dot11d.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/dot11d.c
@@ -0,0 +1,261 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifdef ENABLE_DOT11D
+#include "dot11d.h"
+
+typedef struct _CHANNEL_LIST
+{
+	u8      Channel[32];
+	u8      Len;
+}CHANNEL_LIST, *PCHANNEL_LIST;
+
+static CHANNEL_LIST ChannelPlan[] = {
+	{{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24},
+	{{1,2,3,4,5,6,7,8,9,10,11},11},    
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21},
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},   
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},   
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, 
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, 
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},   
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, 
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, 
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, 
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13},13},    
+	{{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}    
+};
+
+void Dot11d_Init(struct rtllib_device *ieee)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
+#ifdef CONFIG_CRDA 
+	ieee->bGlobalDomain = true;
+	pDot11dInfo->bEnabled = true;
+#else
+	pDot11dInfo->bEnabled = false;
+#endif	
+
+	pDot11dInfo->State = DOT11D_STATE_NONE;
+	pDot11dInfo->CountryIeLen = 0;
+	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);  
+	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+	RESET_CIE_WATCHDOG(ieee);
+
+}
+
+void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device* ieee)
+{
+	int i, max_chan = 14, min_chan = 1;
+
+	ieee->bGlobalDomain = false;
+
+	if (ChannelPlan[channel_plan].Len != 0) {
+		memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
+		for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
+			if (ChannelPlan[channel_plan].Channel[i] < min_chan ||
+					ChannelPlan[channel_plan].Channel[i] > max_chan)
+				break;
+			GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
+		}
+	}
+
+	switch (channel_plan) {
+		case COUNTRY_CODE_GLOBAL_DOMAIN:
+			ieee->bGlobalDomain = true;
+			for (i = 12; i <= 14; i++) {
+				GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
+			}
+			ieee->IbssStartChnl= 10;
+			ieee->ibss_maxjoin_chal = 11;
+			break;
+
+		case COUNTRY_CODE_WORLD_WIDE_13:
+			for (i = 12; i <= 13; i++) {
+				GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
+			}
+			ieee->IbssStartChnl = 10;
+			ieee->ibss_maxjoin_chal = 11;
+			break;
+
+		default:
+			ieee->IbssStartChnl = 1;
+			ieee->ibss_maxjoin_chal = 14;
+			break;
+	}
+}
+						
+
+void Dot11d_Reset(struct rtllib_device *ieee)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
+#if 0
+	if(!pDot11dInfo->bEnabled)
+		return;
+#endif
+
+#ifndef CONFIG_CRDA
+	u32 i;
+	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+	for (i=1; i<=11; i++) {
+		(pDot11dInfo->channel_map)[i] = 1;
+	}
+	for (i=12; i<=14; i++) {
+		(pDot11dInfo->channel_map)[i] = 2;
+	}
+#endif
+	pDot11dInfo->State = DOT11D_STATE_NONE;
+	pDot11dInfo->CountryIeLen = 0;
+	RESET_CIE_WATCHDOG(ieee);
+
+}
+
+void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
+	                    u16 CoutryIeLen, u8* pCoutryIe)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+#ifdef CONFIG_CRDA 
+	
+#else	
+	u8 i, j, NumTriples, MaxChnlNum;
+	PCHNL_TXPOWER_TRIPLE pTriple;
+
+	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+	MaxChnlNum = 0;
+	NumTriples = (CoutryIeLen - 3) / 3; 
+	pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
+	for(i = 0; i < NumTriples; i++)
+	{
+		if(MaxChnlNum >= pTriple->FirstChnl)
+		{ 
+			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
+			return; 
+		}
+		if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
+		{ 
+			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
+			return; 
+		}
+
+		for(j = 0 ; j < pTriple->NumChnls; j++)
+		{
+			pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
+			pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
+			MaxChnlNum = pTriple->FirstChnl + j;
+		}	
+
+		pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
+	}
+#if 0
+	printk("Channel List:");
+	for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
+		if(pDot11dInfo->channel_map[i] > 0)
+			printk(" %d", i);
+	printk("\n");
+#endif
+#endif	
+
+	UPDATE_CIE_SRC(dev, pTaddr);
+
+	pDot11dInfo->CountryIeLen = CoutryIeLen;
+	memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
+	pDot11dInfo->State = DOT11D_STATE_LEARNED;
+
+#ifdef CONFIG_CRDA 
+   	queue_delayed_work_rsl(dev->wq, &dev->softmac_hint11d_wq, 0);
+#endif	
+}
+
+u8 DOT11D_GetMaxTxPwrInDbm( struct rtllib_device *dev, u8 Channel)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+	u8 MaxTxPwrInDbm = 255;
+
+	if(MAX_CHANNEL_NUMBER < Channel)
+	{ 
+		printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
+		return MaxTxPwrInDbm; 
+	}
+	if(pDot11dInfo->channel_map[Channel])
+	{
+		MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];	
+	}
+
+	return MaxTxPwrInDbm;
+}
+
+void DOT11D_ScanComplete( struct rtllib_device * dev)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+
+	switch(pDot11dInfo->State)
+	{
+	case DOT11D_STATE_LEARNED:
+		pDot11dInfo->State = DOT11D_STATE_DONE;
+		break;
+
+	case DOT11D_STATE_DONE:
+		{ 
+			Dot11d_Reset(dev); 
+		}
+		break;
+	case DOT11D_STATE_NONE:
+		break;
+	}
+}
+
+int ToLegalChannel( struct rtllib_device * dev, u8 channel)
+{
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+	u8 default_chn = 0;
+	u32 i = 0;
+
+	for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
+	{
+		if(pDot11dInfo->channel_map[i] > 0)
+		{
+			default_chn = i;
+			break;
+		}
+	}
+
+	if(MAX_CHANNEL_NUMBER < channel)
+	{ 
+		printk("%s(): Invalid Channel\n", __FUNCTION__);
+		return default_chn; 
+	}
+	
+	if(pDot11dInfo->channel_map[channel] > 0)
+		return channel;
+	
+	return default_chn;
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(Dot11d_Init);
+EXPORT_SYMBOL_RSL(Dot11d_Channelmap);
+EXPORT_SYMBOL_RSL(Dot11d_Reset);
+EXPORT_SYMBOL_RSL(Dot11d_UpdateCountryIe);
+EXPORT_SYMBOL_RSL(DOT11D_GetMaxTxPwrInDbm);
+EXPORT_SYMBOL_RSL(DOT11D_ScanComplete);
+EXPORT_SYMBOL_RSL(ToLegalChannel);
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/internal.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/internal.h
@@ -0,0 +1,130 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#ifndef _CRYPTO_INTERNAL_H
+#define _CRYPTO_INTERNAL_H
+
+
+#include <linux/version.h>
+#include "rtl_crypto.h"
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))
+#include <asm/hardirq.h>
+#else
+#include <linux/hardirq.h>
+#include <linux/sched.h>
+#endif
+#include <asm/kmap_types.h>
+
+#ifdef BUILT_IN_CRYPTO
+#ifdef CONFIG_CRYPTO_HMAC
+#undef CONFIG_CRYPTO_HMAC
+#endif
+
+#ifdef CONFIG_KMOD
+#undef CONFIG_KMOD
+#endif
+#endif /* BUILT_IN_CRYPTO */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		     prefetch(pos->member.next);			\
+	     &pos->member != (head); 					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
+		     prefetch(pos->member.next))
+
+static inline void cond_resched(void)
+{
+	if (need_resched()) {
+		set_current_state(TASK_RUNNING);
+		schedule();
+	}
+}
+#endif
+
+extern enum km_type crypto_km_types[];
+
+static inline enum km_type crypto_kmap_type(int out)
+{
+	return crypto_km_types[(in_softirq() ? 2 : 0) + out];
+}
+
+static inline void *crypto_kmap(struct page *page, int out)
+{
+	return kmap_atomic(page, crypto_kmap_type(out));
+}
+
+static inline void crypto_kunmap(void *vaddr, int out)
+{
+	kunmap_atomic(vaddr, crypto_kmap_type(out));
+}
+
+static inline void crypto_yield(struct crypto_tfm *tfm)
+{
+	if (!in_softirq())
+		cond_resched();
+}
+
+static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm)
+{
+	return (void *)&tfm[1];
+}
+
+struct crypto_alg *crypto_alg_lookup(const char *name);
+
+#ifdef CONFIG_KMOD
+void crypto_alg_autoload(const char *name);
+struct crypto_alg *crypto_alg_mod_lookup(const char *name);
+#else
+static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
+{
+	return crypto_alg_lookup(name);
+}
+#endif
+
+#ifdef CONFIG_CRYPTO_HMAC
+int crypto_alloc_hmac_block(struct crypto_tfm *tfm);
+void crypto_free_hmac_block(struct crypto_tfm *tfm);
+#else
+static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static inline void crypto_free_hmac_block(struct crypto_tfm *tfm)
+{ }
+#endif
+
+#ifdef CONFIG_PROC_FS
+void __init crypto_init_proc(void);
+#else
+static inline void crypto_init_proc(void)
+{ }
+#endif
+
+int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
+int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
+int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
+
+int crypto_init_digest_ops(struct crypto_tfm *tfm);
+int crypto_init_cipher_ops(struct crypto_tfm *tfm);
+int crypto_init_compress_ops(struct crypto_tfm *tfm);
+
+void crypto_exit_digest_ops(struct crypto_tfm *tfm);
+void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
+void crypto_exit_compress_ops(struct crypto_tfm *tfm);
+
+#endif	/* _CRYPTO_INTERNAL_H */
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_BA.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_BA.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _BATYPE_H_
+#define _BATYPE_H_
+
+#define 	TOTAL_TXBA_NUM	16
+#define	TOTAL_RXBA_NUM	16
+
+#define	BA_SETUP_TIMEOUT	200
+#define	BA_INACT_TIMEOUT	60000
+
+#define	BA_POLICY_DELAYED		0
+#define	BA_POLICY_IMMEDIATE	1
+
+#define	ADDBA_STATUS_SUCCESS			0
+#define	ADDBA_STATUS_REFUSED		37
+#define	ADDBA_STATUS_INVALID_PARAM	38
+
+#define	DELBA_REASON_QSTA_LEAVING	36
+#define	DELBA_REASON_END_BA			37
+#define	DELBA_REASON_UNKNOWN_BA	38
+#define	DELBA_REASON_TIMEOUT			39
+typedef union _SEQUENCE_CONTROL{
+	u16 ShortData;
+	struct
+	{
+		u16	FragNum:4;
+		u16	SeqNum:12;
+	}field;
+}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL;
+
+typedef union _BA_PARAM_SET {
+	u8 charData[2];
+	u16 shortData;
+	struct {
+		u16 AMSDU_Support:1;
+		u16 BAPolicy:1;
+		u16 TID:4;
+		u16 BufferSize:10;
+	} field;
+} BA_PARAM_SET, *PBA_PARAM_SET;
+
+typedef union _DELBA_PARAM_SET {
+	u8 charData[2];
+	u16 shortData;
+	struct {
+		u16 Reserved:11;
+		u16 Initiator:1;
+		u16 TID:4;
+	} field;
+} DELBA_PARAM_SET, *PDELBA_PARAM_SET;
+
+typedef struct _BA_RECORD {
+	struct timer_list		Timer;
+	u8				bValid;
+	u8				DialogToken;
+	BA_PARAM_SET		BaParamSet;
+	u16				BaTimeoutValue;
+	SEQUENCE_CONTROL	BaStartSeqCtrl;
+} BA_RECORD, *PBA_RECORD;
+
+#endif 
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_HTProc.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_HTProc.c
@@ -0,0 +1,1683 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtllib.h"
+#include "rtl819x_HT.h"
+u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+u16 MCS_DATA_RATE[2][2][77] = 
+	{	{	{13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78 ,104, 156, 208, 234, 260,
+			39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520, 
+			0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195,
+			195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260, 
+			286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429},			
+			{14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, 
+			43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578, 
+			0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217, 
+			217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289, 
+			318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477}	},		
+		{	{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, 
+			81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080, 
+			12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405, 
+			405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540, 
+			594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891}, 	
+			{30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, 
+			90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200, 
+			13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450, 
+			450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600, 
+			660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990}	}	
+	};
+
+static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
+static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
+static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
+static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};	
+static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
+static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
+static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
+static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
+static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0};
+static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91};
+static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+#if defined(RTL8192SU)
+static u8 NETGEAR_BROADCOM[3] = {0x00, 0x1f, 0x33};
+#endif
+static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4}; 
+void HTUpdateDefaultSetting(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	
+#ifdef RTL8192CE
+	pHTInfo->bRDGEnable = 0;
+#endif
+	
+	pHTInfo->bRegShortGI20MHz= 1;
+	pHTInfo->bRegShortGI40MHz= 1;
+
+	pHTInfo->bRegBW40MHz = 1;
+
+	if(pHTInfo->bRegBW40MHz)
+		pHTInfo->bRegSuppCCK = 1;
+	else
+		pHTInfo->bRegSuppCCK = true;
+
+	pHTInfo->nAMSDU_MaxSize = 7935UL;
+	pHTInfo->bAMSDU_Support = 0;
+
+	pHTInfo->bAMPDUEnable = 1; 
+	pHTInfo->AMPDU_Factor = 2; 
+	pHTInfo->MPDU_Density = 0;
+
+	pHTInfo->SelfMimoPs = 3;
+	if(pHTInfo->SelfMimoPs == 2)
+		pHTInfo->SelfMimoPs = 3;
+	ieee->bTxDisableRateFallBack = 0;
+	ieee->bTxUseDriverAssingedRate = 0;	
+
+	ieee->bTxEnableFwCalcDur = 1;
+
+	pHTInfo->bRegRT2RTAggregation = 1;
+	
+	pHTInfo->bRegRxReorderEnable = 1;
+	pHTInfo->RxReorderWinSize = 64;
+	pHTInfo->RxReorderPendingTime = 30;
+
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+	pHTInfo->UsbTxAggrNum = 4;
+#endif
+#ifdef USB_RX_AGGREGATION_SUPPORT
+#ifdef RTL8192SU
+	pHTInfo->UsbRxFwAggrEn = 1;
+	pHTInfo->UsbRxFwAggrPageNum = 48;
+	pHTInfo->UsbRxFwAggrPacketNum = 8;
+	pHTInfo->UsbRxFwAggrTimeout = 4;
+	pHTInfo->UsbRxPageSize= 128;
+#else
+	pHTInfo->UsbRxFwAggrEn = 1;
+	pHTInfo->UsbRxFwAggrPageNum = 24;
+	pHTInfo->UsbRxFwAggrPacketNum = 8;
+	pHTInfo->UsbRxFwAggrTimeout = 8; 
+#endif
+#endif
+	
+
+}
+void HTDebugHTCapability(u8* CapIE, u8* TitleString )
+{
+	
+	static u8	EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};	
+	PHT_CAPABILITY_ELE 		pCapELE;
+	
+	if(!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap)))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
+		pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]);		
+	}else
+		pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]);		
+	
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "<Log HT Capability>. Called by %s\n", TitleString );
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth)?"20MHz": "20/40MHz");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz)?"YES": "NO");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz)?"YES": "NO");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC)?"YES": "NO");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize)?"3839": "7935");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk)?"YES": "NO");
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor);
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMPDU Density = %d\n", pCapELE->MPDUDensity);
+	RTLLIB_DEBUG(RTLLIB_DL_HT,  "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\
+				pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]);
+	return;
+		
+}
+void HTDebugHTInfo(u8*	InfoIE, u8* TitleString)
+{
+	
+	static u8	EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};	
+	PHT_INFORMATION_ELE		pHTInfoEle;
+	
+	if(!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
+		pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]);			
+	}else
+		pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]);
+	
+		
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "<Log HT Information Element>. Called by %s\n", TitleString);
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl);
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSenondary channel =");
+	switch(pHTInfoEle->ExtChlOffset)
+	{
+		case 0:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "Not Present\n");		
+			break;
+		case 1:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "Upper channel\n");
+			break;
+		case 2:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "Reserved. Eooro!!!\n");		
+			break;
+		case 3:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "Lower Channel\n");		
+			break;
+	}
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth)?"20Mhz": "40Mhz");
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "\tOperation mode for protection = ");
+	switch(pHTInfoEle->OptMode)
+	{
+		case 0:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "No Protection\n");		
+			break;
+		case 1:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "HT non-member protection mode\n");
+			break;
+		case 2:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "Suggest to open protection\n");		
+			break;
+		case 3:
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "HT mixed mode\n");		
+			break;
+	}
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\
+				pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]);
+	return;
+}
+
+bool IsHTHalfNmode40Bandwidth(struct rtllib_device* ieee)
+{
+	bool			retValue = false;
+	PRT_HIGH_THROUGHPUT	 pHTInfo = ieee->pHTInfo;
+
+	if(pHTInfo->bCurrentHTSupport == false )	
+		retValue = false;
+	else if(pHTInfo->bRegBW40MHz == false)	
+		retValue = false;
+	else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 	
+		retValue = false;
+	else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) 
+		retValue = true;
+	else
+		retValue = false;
+
+	return retValue;	
+}
+
+bool IsHTHalfNmodeSGI(struct rtllib_device* ieee, bool is40MHz)
+{
+	bool			retValue = false;
+	PRT_HIGH_THROUGHPUT	 pHTInfo = ieee->pHTInfo;
+
+	if(pHTInfo->bCurrentHTSupport == false )	
+		retValue = false;
+	else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 	
+		retValue = false;
+	else if(is40MHz) 
+	{
+		if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) 
+			retValue = true;
+		else
+			retValue = false;
+	}
+	else
+	{
+		if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) 
+			retValue = true;
+		else
+			retValue = false;
+	}	
+
+	return retValue;	
+}
+
+u16 HTHalfMcsToDataRate(struct rtllib_device* ieee, 	u8	nMcsRate)
+{
+	
+	u8	is40MHz;
+	u8	isShortGI;
+	
+	is40MHz  =  (IsHTHalfNmode40Bandwidth(ieee))?1:0;
+	isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz))? 1:0;
+						
+	return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
+}
+
+
+u16 HTMcsToDataRate( struct rtllib_device* ieee, u8 nMcsRate)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	
+	u8	is40MHz = (pHTInfo->bCurBW40MHz)?1:0;
+	u8	isShortGI = (pHTInfo->bCurBW40MHz)?
+						((pHTInfo->bCurShortGI40MHz)?1:0):
+						((pHTInfo->bCurShortGI20MHz)?1:0);
+	return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
+}
+
+u16  TxCountToDataRate( struct rtllib_device* ieee, u8 nDataRate)
+{
+	u16		CCKOFDMRate[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c};
+	u8	is40MHz = 0;
+	u8	isShortGI = 0;
+	
+	if(nDataRate < 12)
+	{
+		return CCKOFDMRate[nDataRate];
+	}
+	else
+	{
+		if (nDataRate >= 0x10 && nDataRate <= 0x1f)
+		{
+			is40MHz = 0;
+			isShortGI = 0;
+
+		}
+		else if(nDataRate >=0x20  && nDataRate <= 0x2f ) 
+		{
+			is40MHz = 1;
+			isShortGI = 0;		
+
+		}
+		else if(nDataRate >= 0x30  && nDataRate <= 0x3f )  
+		{
+			is40MHz = 0;
+			isShortGI = 1;		
+
+		}
+		else if(nDataRate >= 0x40  && nDataRate <= 0x4f ) 
+		{
+			is40MHz = 1;
+			isShortGI = 1;		
+
+		}
+		return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
+	}
+}
+
+
+
+bool IsHTHalfNmodeAPs(struct rtllib_device* ieee)
+{
+	bool			retValue = false;
+	struct rtllib_network* net = &ieee->current_network;
+#if 0
+	if(ieee->bHalfNMode == false)
+		retValue = false;		
+	else
+#endif		
+	if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
+		     (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
+		     (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
+		     (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
+		     (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
+		     (net->ralink_cap_exist))
+		retValue = true;
+	else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
+    		    (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
+    		    (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
+    		    (net->broadcom_cap_exist))
+    		  retValue = true;
+	else if(net->bssht.bdRT2RTAggregation)
+		retValue = true;
+	else
+		retValue = false;
+
+	return retValue;
+}
+
+void HTIOTPeerDetermine(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	struct rtllib_network* net = &ieee->current_network;
+	if(net->bssht.bdRT2RTAggregation){
+		pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
+		if(net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_92SE){
+			pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK_92SE;
+		}
+		if(net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_SOFTAP){
+			pHTInfo->IOTPeer = HT_IOT_PEER_92U_SOFTAP;
+		}
+	}
+	else if(net->broadcom_cap_exist)
+		pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+	else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
+			(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
+			(memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)/*||
+			(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) */)
+		pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+	else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
+			(memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
+			(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
+			(memcmp(net->bssid, EDIMAX_RALINK, 3)==0) || 
+			(memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
+			 net->ralink_cap_exist)
+		pHTInfo->IOTPeer = HT_IOT_PEER_RALINK;
+	else if((net->atheros_cap_exist )|| 
+		(memcmp(net->bssid, DLINK_ATHEROS_1, 3) == 0)||
+		(memcmp(net->bssid, DLINK_ATHEROS_2, 3) == 0))
+		pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
+	else if((memcmp(net->bssid, CISCO_BROADCOM, 3)==0)||net->cisco_cap_exist)
+		pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
+	else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
+		  net->marvell_cap_exist)
+		pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
+	else
+		pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
+
+	RTLLIB_DEBUG(RTLLIB_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer);
+}
+
+u8 HTIOTActIsDisableMCS14(struct rtllib_device* ieee, u8* PeerMacAddr)
+{
+	u8 ret = 0;
+#if 0
+#if (HAL_CODE_BASE==RTL8192 && DEV_BUS_TYPE==USB_INTERFACE)
+	if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) ||
+    		(memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)	
+	    )
+	{
+		ret = 1;
+	}
+
+		
+	if(pHTInfo->bCurrentRT2RTAggregation)
+	{
+		ret = 1;
+	}
+#endif
+#endif		
+	return ret;
+ }
+
+
+bool HTIOTActIsDisableMCS15(struct rtllib_device* ieee)
+{
+	bool retValue = false;
+
+#if defined(RTL8192U)
+	if(ieee->current_network.bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40)
+	retValue = true;
+	else
+		retValue = false;
+#endif
+
+	
+	return retValue;
+}
+
+bool HTIOTActIsDisableMCSTwoSpatialStream(struct rtllib_device* ieee)
+{
+	bool retValue = false;
+#ifdef RTL8192U
+	struct rtllib_network* net = &ieee->current_network;
+
+	if((ieee->pHTInfo->bCurrentHTSupport == true) && (ieee->pairwise_key_type == KEY_TYPE_CCMP))
+	{
+		if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
+				(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
+				(memcmp(net->bssid, EDIMAX_RALINK, 3)==0))
+		{
+			retValue = false;
+		}
+	}
+#endif
+#if defined(RTL8192SU) || defined RTL8192CE
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if (ieee->rtllib_ap_sec_type && 
+		(ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP)))
+	{
+		if( (pHTInfo->IOTPeer != HT_IOT_PEER_ATHEROS) &&
+			(pHTInfo->IOTPeer != HT_IOT_PEER_UNKNOWN) &&
+			(pHTInfo->IOTPeer != HT_IOT_PEER_MARVELL) &&
+			(pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK_92SE) &&
+			(pHTInfo->IOTPeer != HT_IOT_PEER_RALINK) )
+			retValue = true;
+	}
+#elif defined(RTL8192SE) 
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if (ieee->rtllib_ap_sec_type && 
+		(ieee->rtllib_ap_sec_type(ieee)&SEC_ALG_TKIP)) {
+			if(pHTInfo->IOTPeer == HT_IOT_PEER_RALINK){
+				retValue = true;
+			}
+		}
+#endif
+	return retValue;
+}
+
+u8 HTIOTActIsDisableEDCATurbo(struct rtllib_device* 	ieee, u8* PeerMacAddr)
+{
+	u8	retValue = false;	
+	
+	return retValue;
+#if 0
+	if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0)|| 
+		(memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
+		(memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0))
+
+	{
+		retValue = 1;	
+	}
+
+	return retValue;
+#endif
+}
+
+
+bool HTIOTActIsEnableBETxOPLimit(struct rtllib_device* ieee)
+{
+	bool	retValue = false;
+
+#if defined RTL8192SU 
+	if(ieee->mode == IEEE_G)
+		retValue = true;
+#elif defined RTL8192CE
+	if(ieee->mode == IEEE_G ||
+		(ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP)))
+		retValue = true;
+#endif
+
+	return retValue;
+}
+
+
+u8 HTIOTActIsMgntUseCCK6M(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+
+		
+#if (defined RTL8192U || defined RTL8192E || defined RTL8190P)	
+	{		
+	if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)	
+	{
+		retValue = 1;
+	}	
+	}
+#endif
+
+	return retValue;
+}
+
+u8
+HTIOTActWAIOTBroadcom(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	u8		retValue = false;
+	u8		boundary=59;
+
+	pHTInfo->bWAIotBroadcom = false;
+	if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)	
+	{	
+		if(ieee->current_network.bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40)		
+		{	
+			if(!(pHTInfo->bCurBW40MHz))
+			{	
+				if(ieee->current_network.mode != WIRELESS_MODE_B)
+				{
+					pHTInfo->bWAIotBroadcom = true;
+					
+					if(ieee->b_customer_lenovo_id == true)
+						boundary = 30;
+
+					if( ieee->current_network.RSSI >= boundary)
+						retValue = true;
+				}
+			}else{
+				;
+			}
+		}
+	}
+	return retValue;
+}
+
+u8 HTIOTActIsForcedCTS2Self(struct rtllib_device *ieee, struct rtllib_network *network)
+{
+	u8 	retValue = 0;
+#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE)
+	if((ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL) ||(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) )
+#else
+	if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+#endif
+	{
+		retValue = 1;
+	}
+	
+	return retValue;
+}
+
+u8 HTIOTActIsForcedRTSCTS(struct rtllib_device *ieee, struct rtllib_network *network)
+{
+	u8	retValue = 0;
+#if defined(RTL8192SE) || defined(RTL8192SU) 
+	if(ieee->pHTInfo->bCurrentHTSupport)
+	{
+		if((ieee->pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK)&&
+		   (ieee->pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK_92SE))
+	{
+			if((ieee->pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION) == 0)
+				retValue = 1;
+		}
+	}
+#endif
+	return retValue;
+}
+
+u8
+HTIOTActIsForcedAMSDU8K(struct rtllib_device *ieee, struct rtllib_network *network)
+{
+	u8 retValue = 0;
+
+	return retValue;
+}
+
+u8 HTIOTActIsCCDFsync(struct rtllib_device *ieee)
+{
+	u8	retValue = 0;
+#if (defined RTL8190P || defined RTL8192U  || defined RTL8192SU)
+	if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+	{
+		retValue = 1;
+	}
+#endif	
+	return retValue;
+}
+	
+u8
+HTIOCActRejcectADDBARequest(struct rtllib_network *network)
+{
+	u8	retValue = 0;
+#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE)
+	{
+		
+		
+	}
+#endif
+	
+	return retValue;
+
+}
+
+u8
+  HTIOTActIsEDCABiasRx(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+#ifdef RTL8192SU
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+		if(pHTInfo->IOTPeer==HT_IOT_PEER_ATHEROS || 
+		   pHTInfo->IOTPeer==HT_IOT_PEER_BROADCOM ||
+		   pHTInfo->IOTPeer==HT_IOT_PEER_RALINK)
+			return 1;
+		
+	}
+#elif defined RTL8192CE
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+		if(pHTInfo->IOTPeer==HT_IOT_PEER_ATHEROS || 
+		   pHTInfo->IOTPeer==HT_IOT_PEER_RALINK)
+			return 1;
+		
+	}
+#elif defined RTL8192SE 
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+            if(ieee->rtllib_ap_sec_type != NULL) 
+                if(ieee->rtllib_ap_sec_type(ieee) == SEC_ALG_CCMP)
+                    if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK){
+                        return 1;
+                    }
+		
+	}
+#endif
+	return retValue;
+}
+
+u8
+HTIOTActDisableShortGI(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+
+	if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK)
+	{
+			retValue = 1;
+	}
+
+	return retValue;
+}
+
+u8
+HTIOTActDisableHighPower(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+#endif
+
+#ifdef RTL8192SU
+	if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK ||
+		pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK ||
+		pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK_92SE)
+	{
+			retValue = 1;
+	}
+#elif defined RTL8192SE || defined RTL8192CE
+	if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK ||
+		pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK )
+	{
+			retValue = 1;
+	}
+#endif
+	return retValue;
+}
+
+void
+HTIOTActDetermineRaFunc(struct rtllib_device* ieee,	bool	bPeerRx2ss)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	pHTInfo->IOTRaFunc &= HT_IOT_RAFUNC_DISABLE_ALL;
+
+	if(pHTInfo->IOTPeer == HT_IOT_PEER_RALINK && !bPeerRx2ss)
+		pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_PEER_1R;
+
+	if(pHTInfo->IOTAction & HT_IOT_ACT_AMSDU_ENABLE)
+		pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_TX_AMSDU;
+
+}
+
+
+u8
+HTIOTActIsDisableTx40MHz(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+
+#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if(	(KEY_TYPE_WEP104 == ieee->pairwise_key_type) || 
+		(KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
+		(KEY_TYPE_WEP104 == ieee->group_key_type) ||
+		(KEY_TYPE_WEP40 == ieee->group_key_type) ||
+		(KEY_TYPE_TKIP == ieee->pairwise_key_type) )
+	{
+		if((pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK) && (network->bssht.bdSupportHT)) 
+			retValue = 1;
+	}
+#endif
+
+	return retValue;
+}
+
+u8
+HTIOTActIsTxNoAggregation(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8 retValue = 0;
+
+#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if(	(KEY_TYPE_WEP104 == ieee->pairwise_key_type) || 
+		(KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
+		(KEY_TYPE_WEP104 == ieee->group_key_type) ||
+		(KEY_TYPE_WEP40 == ieee->group_key_type) ||
+		(KEY_TYPE_TKIP == ieee->pairwise_key_type) )
+	{
+		if(pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK)
+			retValue = 1;
+	}
+#endif
+
+	return retValue;
+}
+
+
+u8
+HTIOTActIsDisableTx2SS(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	u8	retValue = 0;
+
+#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if(	(KEY_TYPE_WEP104 == ieee->pairwise_key_type) || 
+		(KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
+		(KEY_TYPE_WEP104 == ieee->group_key_type) ||
+		(KEY_TYPE_WEP40 == ieee->group_key_type) ||
+		(KEY_TYPE_TKIP == ieee->pairwise_key_type) )
+	{
+		if((pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK) && (network->bssht.bdSupportHT))
+			retValue = 1;
+	}
+#endif
+
+	return retValue;
+}
+
+
+bool HTIOCActIsDisableCckRate(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	bool 	retValue = false;
+#if defined(RTL8192SU)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+	{
+		if((memcmp(network->bssid, NETGEAR_BROADCOM, 3)==0)
+			&& (network->bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40))
+			return true;
+	}
+#endif
+	return retValue;
+}
+
+
+bool HTIOCActAllowPeerAggOnePacket(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	bool 	retValue = false;
+#if defined(RTL8192SE) || defined(RTL8192SU) 
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+		if(ieee->VersionID<2)
+		if(pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+			return true;
+		
+	}
+#endif
+	return retValue;
+}
+
+bool
+HTIOTActIsNullDataPowerSaving(struct rtllib_device* ieee,struct rtllib_network *network)
+{
+	bool	retValue = false;
+#if defined(RTL8192SE) || defined(RTL8192SU)
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+		if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) 
+			return true;
+		
+	}
+#endif
+	return retValue;
+}
+
+void HTResetIOTSetting(
+	PRT_HIGH_THROUGHPUT		pHTInfo
+)
+{
+	pHTInfo->IOTAction = 0;
+	pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
+	pHTInfo->IOTRaFunc = 0;
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_
+void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt, u8 bIsBcn)
+#else	
+void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt)
+#endif	
+{	
+	PRT_HIGH_THROUGHPUT	pHT = ieee->pHTInfo;
+	PHT_CAPABILITY_ELE 	pCapELE = NULL;
+	
+	if ((posHTCap == NULL) || (pHT == NULL))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n");
+		return;
+	}
+	memset(posHTCap, 0, *len);	
+	if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
+	{
+		u8	EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};	
+		memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap));
+		pCapELE = (PHT_CAPABILITY_ELE)&(posHTCap[4]);
+	}else 
+	{
+		pCapELE = (PHT_CAPABILITY_ELE)posHTCap;
+	}
+
+	pCapELE->AdvCoding 		= 0; 
+	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	{
+		pCapELE->ChlWidth = 0;
+	}	
+	else
+	{
+#ifdef _RTL8192_EXT_PATCH_
+		if(bIsBcn)
+			pCapELE->ChlWidth = (pHT->bCurBW40MHz?1:0);
+		else
+#endif	
+			pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0);
+	}
+	
+	pCapELE->MimoPwrSave 		= pHT->SelfMimoPs;
+	pCapELE->GreenField		= 0; 
+	pCapELE->ShortGI20Mhz		= 1; 
+	pCapELE->ShortGI40Mhz		= 1; 
+	pCapELE->TxSTBC 		= 1;
+#ifdef Rtl8192SE
+	pCapELE->TxSTBC 		= 0;
+#endif
+	pCapELE->RxSTBC 		= 0;
+	pCapELE->DelayBA		= 0;	
+	pCapELE->MaxAMSDUSize	= (MAX_RECEIVE_BUFFER_SIZE>=7935)?1:0;
+	pCapELE->DssCCk 		= ((pHT->bRegBW40MHz)?(pHT->bRegSuppCCK?1:0):0);
+	pCapELE->PSMP			= 0; 
+	pCapELE->LSigTxopProtect	= 0; 
+
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
+
+	if( IsEncrypt) 
+	{
+		pCapELE->MPDUDensity 	= 7; 
+		pCapELE->MaxRxAMPDUFactor 	= 2; 
+	}
+	else
+	{
+		pCapELE->MaxRxAMPDUFactor 	= 3; 
+		pCapELE->MPDUDensity 	= 0; 
+	}		
+
+	memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16);
+	if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15)
+		pCapELE->MCS[1] &= 0x7f;
+
+	if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14)
+		pCapELE->MCS[1] &= 0xbf;
+
+	if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS)
+		pCapELE->MCS[1] &= 0x00;
+
+	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	{	
+		int i;
+		for(i = 1; i< 16; i++)
+			pCapELE->MCS[i] = 0;
+	}
+	
+	memset(&pCapELE->ExtHTCapInfo, 0, 2);
+
+
+	memset(pCapELE->TxBFCap, 0, 4);
+
+	pCapELE->ASCap = 0;
+	if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
+		*len = 30 + 2;
+	else
+		*len = 26 + 2;
+		
+
+		
+	
+	return;
+	
+}
+void HTConstructInfoElement(struct rtllib_device* ieee, u8* posHTInfo, u8* len, u8 IsEncrypt)
+{
+	PRT_HIGH_THROUGHPUT	pHT = ieee->pHTInfo;	
+	PHT_INFORMATION_ELE		pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo;
+	if ((posHTInfo == NULL) || (pHTInfoEle == NULL))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n");
+		return;
+	}
+	
+	memset(posHTInfo, 0, *len);
+#ifdef _RTL8192_EXT_PATCH_
+	if ((ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER) ||(ieee->iw_mode == IW_MODE_MESH) ) 
+#else
+	if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) 
+#endif
+	{
+		pHTInfoEle->ControlChl 			= ieee->current_network.channel; 
+#ifdef _RTL8192_EXT_PATCH_
+		if((!ieee->only_mesh) && (ieee->iw_mode == IW_MODE_MESH) && (ieee->state == RTLLIB_LINKED))
+			pHTInfoEle->ExtChlOffset 			= ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+												ieee->APExtChlOffset);
+		else if(ieee->iw_mode == IW_MODE_MESH)
+			pHTInfoEle->ExtChlOffset 			= ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+											(ieee->current_mesh_network.channel<=6)?
+												HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
+		else
+#endif
+			pHTInfoEle->ExtChlOffset 			= ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+											(ieee->current_network.channel<=6)?
+												HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
+		pHTInfoEle->RecommemdedTxWidth	= pHT->bRegBW40MHz;
+		pHTInfoEle->RIFS 					= 0;
+		pHTInfoEle->PSMPAccessOnly		= 0;
+		pHTInfoEle->SrvIntGranularity		= 0;
+		pHTInfoEle->OptMode				= pHT->CurrentOpMode;
+		pHTInfoEle->NonGFDevPresent		= 0;
+		pHTInfoEle->DualBeacon			= 0;
+		pHTInfoEle->SecondaryBeacon		= 0;
+		pHTInfoEle->LSigTxopProtectFull		= 0;
+		pHTInfoEle->PcoActive				= 0;
+		pHTInfoEle->PcoPhase				= 0;
+
+		memset(pHTInfoEle->BasicMSC, 0, 16);
+
+
+		*len = 22 + 2; 
+
+	}
+	else
+	{
+		*len = 0;
+	}	
+	return;
+}	
+
+void HTConstructRT2RTAggElement(struct rtllib_device* ieee, u8* posRT2RTAgg, u8* len)
+{
+	if (posRT2RTAgg == NULL) {
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n");
+		return;
+	}
+	memset(posRT2RTAgg, 0, *len);
+	*posRT2RTAgg++ = 0x00;
+	*posRT2RTAgg++ = 0xe0;
+	*posRT2RTAgg++ = 0x4c;
+	*posRT2RTAgg++ = 0x02;
+	*posRT2RTAgg++ = 0x01;
+
+#ifdef RTL8192CE
+	*posRT2RTAgg = 0x70;
+#else
+	*posRT2RTAgg = 0x10;
+#endif
+	
+	if(ieee->bSupportRemoteWakeUp) {
+		*posRT2RTAgg |= RT_HT_CAP_USE_WOW;
+	}
+
+	*len = 6 + 2;
+	
+	return;
+
+#ifdef TODO
+	posRT2RTAgg->Length = 6;
+#endif
+
+
+
+
+}
+
+u8 HT_PickMCSRate(struct rtllib_device* ieee, u8* pOperateMCS)
+{
+	u8					i;
+	if (pOperateMCS == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "pOperateMCS can't be null in HT_PickMCSRate()\n");
+		return false;
+	}
+
+	switch(ieee->mode)
+	{
+	case IEEE_A:
+	case IEEE_B:
+	case IEEE_G:
+			
+			for(i=0;i<=15;i++){
+				pOperateMCS[i] = 0;
+			}
+			break;
+		
+	case IEEE_N_24G:	
+	case IEEE_N_5G:
+			
+			pOperateMCS[0] &=RATE_ADPT_1SS_MASK;	
+			pOperateMCS[1] &=RATE_ADPT_2SS_MASK;
+			pOperateMCS[3] &=RATE_ADPT_MCS32_MASK;
+			break;
+
+	default:
+			
+			break;
+		
+	}
+
+	return true;
+}
+
+u8 HTGetHighestMCSRate(struct rtllib_device* ieee, u8* pMCSRateSet, u8* pMCSFilter)
+{
+	u8		i, j;
+	u8		bitMap;
+	u8		mcsRate = 0;
+	u8		availableMcsRate[16];
+	if (pMCSRateSet == NULL || pMCSFilter == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n");
+		return false;
+	}
+	for(i=0; i<16; i++)
+		availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];
+
+	for(i = 0; i < 16; i++)
+	{
+		if(availableMcsRate[i] != 0)
+			break;
+	}
+	if(i == 16)
+		return false;
+
+	for(i = 0; i < 16; i++)
+	{
+		if(availableMcsRate[i] != 0)
+		{
+			bitMap = availableMcsRate[i];
+			for(j = 0; j < 8; j++)
+			{
+				if((bitMap%2) != 0)
+				{
+					if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate))
+						mcsRate = (8*i+j);
+				}
+				bitMap = bitMap>>1;
+			}
+		}
+	}
+	return (mcsRate|0x80);
+}
+	
+u8 HTFilterMCSRate( struct rtllib_device* ieee, u8* pSupportMCS, u8* pOperateMCS)
+{
+	
+	u8 i=0;
+	
+	for(i=0;i<=15;i++){
+		pOperateMCS[i] = ieee->Regdot11TxHTOperationalRateSet[i]&pSupportMCS[i];
+	}
+
+	
+
+	HT_PickMCSRate(ieee, pOperateMCS);
+
+	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+		pOperateMCS[1] = 0;
+	
+	for(i=2; i<=15; i++)
+		pOperateMCS[i] = 0;
+	
+	return true;
+}
+void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH	Bandwidth, HT_EXTCHNL_OFFSET	Offset);
+void HTOnAssocRsp(struct rtllib_device *ieee)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	PHT_CAPABILITY_ELE		pPeerHTCap = NULL;
+	PHT_INFORMATION_ELE		pPeerHTInfo = NULL;
+	u16	nMaxAMSDUSize = 0;
+	u8*	pMcsFilter = NULL;
+
+	static u8				EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};		
+	static u8				EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};	
+	
+	if( pHTInfo->bCurrentHTSupport == false )
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n");
+		return;
+	}
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
+		
+	if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap)))
+		pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
+	else
+		pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
+
+	if(!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
+		pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]);
+	else		
+		pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->APExtChlOffset = (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset);
+#endif
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE));
+	HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset));
+#if defined RTL8192SE || defined RTL8192SU || defined RTL8192CE
+	if(pHTInfo->bCurBW40MHz == true)
+#endif
+		pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false);
+
+	pHTInfo->bCurShortGI20MHz= 
+		((pHTInfo->bRegShortGI20MHz)?((pPeerHTCap->ShortGI20Mhz==1)?true:false):false);
+	pHTInfo->bCurShortGI40MHz= 
+		((pHTInfo->bRegShortGI40MHz)?((pPeerHTCap->ShortGI40Mhz==1)?true:false):false);
+
+	pHTInfo->bCurSuppCCK = 
+		((pHTInfo->bRegSuppCCK)?((pPeerHTCap->DssCCk==1)?true:false):false);
+
+
+	pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+
+	nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
+
+	if(pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize )
+		pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize;
+	else
+		pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+
+	pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+	if (ieee->rtllib_ap_sec_type && 
+	   (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
+		if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
+				(pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
+			pHTInfo->bCurrentAMPDUEnable = false;
+	}		
+		
+	if(!pHTInfo->bRegRT2RTAggregation)
+	{
+		if(pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor)
+			pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
+		else
+			pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+	} else {
+#if 0	
+		osTmp= PacketGetElement( asocpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE);
+		if(osTmp.Length >= 5)	
+#endif
+		if (ieee->current_network.bssht.bdRT2RTAggregation)
+		{
+			if( ieee->pairwise_key_type != KEY_TYPE_NA) 
+				pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
+			else
+				pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K;
+		}else
+		{
+			if(pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K)
+				pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
+			else
+				pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K;
+		}
+	}
+
+#if 0
+	if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
+		pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
+	else
+		pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
+	if(ieee->pairwise_key_type != KEY_TYPE_NA ) 
+		pHTInfo->CurrentMPDUDensity 	= 7; 
+#else
+	if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
+		pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
+	else
+		pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
+#endif
+#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE)
+        if(ieee->SetHwRegHandler != NULL) {
+            ieee->SetHwRegHandler( ieee->dev, HW_VAR_SHORTGI_DENSITY,  (u8*)(&ieee->MaxMssDensity));
+            ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor);
+            ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity);
+        }
+#elif defined RTL8192CE
+        if(ieee->SetHwRegHandler != NULL) {
+            ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor);
+            ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity);
+        }
+#endif        
+#ifndef RTL8190P
+	if(pHTInfo->IOTAction & HT_IOT_ACT_TX_USE_AMSDU_8K)
+#else
+	if( 0 )
+#endif
+	{
+		pHTInfo->bCurrentAMPDUEnable = false;
+		pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE;
+		pHTInfo->ForcedAMSDUMaxSize = 7935;
+	}
+	pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable;
+
+	
+	if(pPeerHTCap->MCS[0] == 0)
+		pPeerHTCap->MCS[0] = 0xff;
+		
+	HTIOTActDetermineRaFunc(ieee, ((pPeerHTCap->MCS[1])!=0));
+
+	HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet);
+
+	pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave;
+	if(pHTInfo->PeerMimoPs == MIMO_PS_STATIC)
+		pMcsFilter = MCS_FILTER_1SS;
+	else
+		pMcsFilter = MCS_FILTER_ALL;
+	ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter);
+	ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
+
+	pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
+
+}	
+
+void HTSetConnectBwModeCallback(struct rtllib_device* ieee);
+void HTInitializeHTInfo(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "===========>%s()\n", __FUNCTION__);
+	pHTInfo->bCurrentHTSupport = false;
+
+	pHTInfo->bCurBW40MHz = false;
+	pHTInfo->bCurTxBW40MHz = false;
+
+	pHTInfo->bCurShortGI20MHz = false;
+	pHTInfo->bCurShortGI40MHz = false;
+	pHTInfo->bForcedShortGI = false;
+
+	pHTInfo->bCurSuppCCK = true;
+
+	pHTInfo->bCurrent_AMSDU_Support = false;
+	pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+#ifdef _RTL8192_EXT_PATCH_
+	pHTInfo->bCurrent_Mesh_AMSDU_Support = true;
+#endif
+	pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
+	pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+	memset((void*)(&(pHTInfo->SelfHTCap)), 0, sizeof(pHTInfo->SelfHTCap));
+	memset((void*)(&(pHTInfo->SelfHTInfo)), 0, sizeof(pHTInfo->SelfHTInfo));
+	memset((void*)(&(pHTInfo->PeerHTCapBuf)), 0, sizeof(pHTInfo->PeerHTCapBuf));
+	memset((void*)(&(pHTInfo->PeerHTInfoBuf)), 0, sizeof(pHTInfo->PeerHTInfoBuf));
+
+	pHTInfo->bSwBwInProgress = false;
+	pHTInfo->ChnlOp = CHNLOP_NONE;
+
+	pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE;
+
+	pHTInfo->bCurrentRT2RTAggregation = false;
+	pHTInfo->bCurrentRT2RTLongSlotTime = false;
+	pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0;
+	
+	pHTInfo->IOTPeer = 0;
+	pHTInfo->IOTAction = 0;
+	pHTInfo->IOTRaFunc = 0;
+	
+	{
+		u8* RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]);
+		RegHTSuppRateSets[0] = 0xFF;	
+		RegHTSuppRateSets[1] = 0xFF;	
+		RegHTSuppRateSets[4] = 0x01;	
+	}
+}
+void HTInitializeBssDesc(PBSS_HT pBssHT)
+{
+
+	pBssHT->bdSupportHT = false;
+	memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf));
+	pBssHT->bdHTCapLen = 0;
+	memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf));
+	pBssHT->bdHTInfoLen = 0;
+
+	pBssHT->bdHTSpecVer= HT_SPEC_VER_IEEE;
+
+	pBssHT->bdRT2RTAggregation = false;
+	pBssHT->bdRT2RTLongSlotTime = false;
+	pBssHT->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0;
+}
+
+void HTResetSelfAndSavePeerSetting(struct rtllib_device* ieee, 	struct rtllib_network * pNetwork)
+{
+	PRT_HIGH_THROUGHPUT		pHTInfo = ieee->pHTInfo;
+	u8	bIOTAction = 0;
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "==============>%s()\n", __FUNCTION__);
+	/*unmark bEnableHT flag here is the same reason why unmarked in function rtllib_softmac_new_net. WB 2008.09.10*/
+	if (pNetwork->bssht.bdSupportHT)
+	{
+		pHTInfo->bCurrentHTSupport = true;
+		pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
+
+		if(pNetwork->bssht.bdHTCapLen > 0 && 	pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf))
+			memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen);
+
+		if(pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf))
+			memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen);
+
+		if(pHTInfo->bRegRT2RTAggregation)
+		{
+			pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation;
+			pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime;
+			pHTInfo->RT2RT_HT_Mode = pNetwork->bssht.RT2RT_HT_Mode;
+		}
+		else
+		{
+			pHTInfo->bCurrentRT2RTAggregation = false;	
+			pHTInfo->bCurrentRT2RTLongSlotTime = false;
+			pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0;
+		}
+	
+		HTIOTPeerDetermine(ieee);
+				 			
+		pHTInfo->IOTAction = 0;
+		bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
+
+		bIOTAction = HTIOTActIsDisableMCS15(ieee);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15;
+
+		bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS;
+
+
+		bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO;
+
+#if defined(RTL8190P) || defined(RTL8192E) || defined(RTL8192U)
+		bIOTAction = HTIOTActIsMgntUseCCK6M(ieee,pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M;
+#elif defined(RTL8192SE) || defined(RTL8192SU) || defined RTL8192CE
+		bIOTAction = HTIOTActWAIOTBroadcom(ieee);
+		if(bIOTAction)
+		{
+			pHTInfo->IOTAction |= HT_IOT_ACT_WA_IOT_Broadcom;
+		}
+#endif
+		bIOTAction = HTIOTActIsCCDFsync(ieee);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
+#if defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE
+		bIOTAction = HTIOTActIsForcedCTS2Self(ieee,pNetwork);
+		if(bIOTAction)	
+			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
+
+
+		bIOTAction = HTIOTActIsEnableBETxOPLimit(ieee);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_ENABLE_BE_TXOP;
+
+#if defined(RTL8192SU)
+		bIOTAction = HTIOCActRejcectADDBARequest(pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_REJECT_ADDBA_REQ;
+#endif
+
+		bIOTAction = HTIOCActAllowPeerAggOnePacket(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT;
+
+		bIOTAction = HTIOTActIsEDCABiasRx(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_EDCA_BIAS_ON_RX;
+
+#if defined(RTL8192SU)
+		bIOTAction = HTIOCActIsDisableCckRate(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_CCK_RATE;
+#endif
+		bIOTAction = HTIOTActDisableShortGI(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_SHORT_GI;
+
+		bIOTAction = HTIOTActDisableHighPower(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_HIGH_POWER;
+
+
+		bIOTAction = HTIOTActIsForcedAMSDU8K(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_TX_USE_AMSDU_8K;
+
+#if defined(RTL8192SU)
+		bIOTAction = HTIOTActIsTxNoAggregation(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_TX_NO_AGGREGATION;
+
+		bIOTAction = HTIOTActIsDisableTx40MHz(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_TX_40_MHZ;
+
+		bIOTAction = HTIOTActIsDisableTx2SS(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_TX_2SS;
+#endif
+
+		bIOTAction = HTIOTActIsForcedRTSCTS(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_RTS;
+
+		bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
+#endif
+	}
+	else
+	{
+		pHTInfo->bCurrentHTSupport = false;
+		pHTInfo->bCurrentRT2RTAggregation = false;
+		pHTInfo->bCurrentRT2RTLongSlotTime = false;
+		pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0;
+
+		pHTInfo->IOTAction = 0;
+		pHTInfo->IOTRaFunc = 0;
+	}
+	
+}
+
+void HTUpdateSelfAndPeerSetting(struct rtllib_device* ieee, 	struct rtllib_network * pNetwork)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	PHT_INFORMATION_ELE		pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
+
+	if(pHTInfo->bCurrentHTSupport)
+	{
+		if(pNetwork->bssht.bdHTInfoLen != 0)
+			pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
+
+	}
+}
+
+void HTUseDefaultSetting(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+		
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->current_mesh_network.qos_data.supported = 1;
+	ieee->current_mesh_network.qos_data.active = ieee->current_mesh_network.qos_data.supported;
+#endif	
+	if(pHTInfo->bEnableHT)
+	{
+		pHTInfo->bCurrentHTSupport = true;
+		pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK;
+
+#ifdef _RTL8192_EXT_PATCH_
+		if(!((ieee->iw_mode == IW_MODE_MESH) && ieee->proto_started && (ieee->state == RTLLIB_LINKED)))
+			pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz;
+#else
+		pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz;
+#endif
+		pHTInfo->bCurShortGI20MHz= pHTInfo->bRegShortGI20MHz;
+
+		pHTInfo->bCurShortGI40MHz= pHTInfo->bRegShortGI40MHz;
+#ifdef _RTL8192_EXT_PATCH_
+		ieee->current_mesh_network.qos_data.supported = 1;
+		ieee->current_mesh_network.qos_data.active = ieee->current_mesh_network.qos_data.supported;
+#endif		
+
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+		{
+			ieee->current_network.qos_data.active = ieee->current_network.qos_data.supported;
+		}
+#ifdef ENABLE_AMSDU
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+		{
+			pHTInfo->bCurrent_AMSDU_Support = 1;
+		}
+#ifdef _RTL8192_EXT_PATCH_
+		else if(ieee->iw_mode == IW_MODE_MESH)
+		{
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+			pHTInfo->bCurrent_Mesh_AMSDU_Support = 0;
+#else
+			pHTInfo->bCurrent_Mesh_AMSDU_Support = 1;
+#endif
+			pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+		}
+#endif
+		else
+			pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+#else
+		pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+#endif
+		pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+
+#ifdef ENABLE_AMSDU
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+			pHTInfo->bCurrentAMPDUEnable = 0;
+#ifdef _RTL8192_EXT_PATCH_
+		else if(ieee->iw_mode == IW_MODE_MESH)
+		{
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+			pHTInfo->bCurrentMeshAMPDUEnable = 1;
+#else
+			pHTInfo->bCurrentMeshAMPDUEnable = 0;
+#endif
+			pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+		}
+#endif
+		else
+			pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+#else
+		pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+#endif
+		pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+		pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
+
+
+		HTFilterMCSRate(ieee, ieee->Regdot11TxHTOperationalRateSet, ieee->dot11HTOperationalRateSet);
+#ifdef TODO
+		Adapter->HalFunc.InitHalRATRTableHandler( Adapter, &pMgntInfo->dot11OperationalRateSet, pMgntInfo->dot11HTOperationalRateSet);
+#endif
+		ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, MCS_FILTER_ALL);
+		ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
+
+#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE)
+        	if(ieee->SetHwRegHandler != NULL) {
+           	 	ieee->SetHwRegHandler( ieee->dev, HW_VAR_SHORTGI_DENSITY,  (u8*)(&ieee->MaxMssDensity));
+            		ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor);
+           	 	ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity);
+        	}
+#endif  
+
+	}
+	else
+	{
+		pHTInfo->bCurrentHTSupport = false;
+	}
+	return;
+}
+u8 HTCCheck(struct rtllib_device* ieee, u8*	pFrame)
+{
+	if(ieee->pHTInfo->bCurrentHTSupport)
+	{
+		if( (IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_HT, "HT CONTROL FILED EXIST!!\n");
+			return true;
+		}
+	}
+	return false;
+}
+
+void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH	Bandwidth, HT_EXTCHNL_OFFSET	Offset)
+{
+	PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+
+	if(pHTInfo->bRegBW40MHz == false)
+		return;
+
+	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+		Bandwidth=HT_CHANNEL_WIDTH_20;
+	
+
+	if(pHTInfo->bSwBwInProgress) {
+		printk("%s: bSwBwInProgress!!\n", __FUNCTION__);
+		return;
+	}
+	if(Bandwidth==HT_CHANNEL_WIDTH_20_40)
+	 {
+		if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER)
+			Offset = HT_EXTCHNL_OFFSET_NO_EXT;
+		if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) {
+			pHTInfo->bCurBW40MHz = true;
+			pHTInfo->CurSTAExtChnlOffset = Offset;
+		} else {
+			pHTInfo->bCurBW40MHz = false;
+			pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
+		}
+	} else {
+		pHTInfo->bCurBW40MHz = false;
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
+	}
+
+	printk("%s():pHTInfo->bCurBW40MHz:%x\n", __func__, pHTInfo->bCurBW40MHz);
+
+	pHTInfo->bSwBwInProgress = true;
+
+	HTSetConnectBwModeCallback(ieee);
+
+}
+
+void HTSetConnectBwModeCallback(struct rtllib_device* ieee)
+{
+	PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+
+	RTLLIB_DEBUG(RTLLIB_DL_HT, "======>%s()\n", __FUNCTION__);
+	if(pHTInfo->bCurBW40MHz)
+	{
+		if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER)
+			ieee->set_chan(ieee->dev, ieee->current_network.channel+2);
+		else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER)
+			ieee->set_chan(ieee->dev, ieee->current_network.channel-2);
+		else
+			ieee->set_chan(ieee->dev, ieee->current_network.channel);
+		
+		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+	} else {
+		ieee->set_chan(ieee->dev, ieee->current_network.channel);
+		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+	}
+
+	pHTInfo->bSwBwInProgress = false;
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(HTUpdateSelfAndPeerSetting);
+EXPORT_SYMBOL_RSL(HTFilterMCSRate);
+EXPORT_SYMBOL_RSL(HTGetHighestMCSRate);
+EXPORT_SYMBOL_RSL(MCS_FILTER_ALL);
+EXPORT_SYMBOL_RSL(MCS_FILTER_1SS);
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(HTSetConnectBwMode);
+EXPORT_SYMBOL_RSL(HTConstructCapabilityElement);
+EXPORT_SYMBOL_RSL(HTConstructRT2RTAggElement);
+EXPORT_SYMBOL_RSL(HTUseDefaultSetting);
+EXPORT_SYMBOL_RSL(HTConstructInfoElement);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/digest.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/digest.c
@@ -0,0 +1,120 @@
+/*
+ * Cryptographic API.
+ *
+ * Digest operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include <linux/version.h>
+#include "rtl_crypto.h"
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+#include <asm/scatterlist.h>
+#else
+#include <linux/scatterlist.h>
+#endif
+#include "internal.h"
+
+static void init(struct crypto_tfm *tfm)
+{
+	tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
+}
+
+static void update(struct crypto_tfm *tfm,
+                   struct scatterlist *sg, unsigned int nsg)
+{
+	unsigned int i;
+
+	for (i = 0; i < nsg; i++) {
+
+	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		struct page *pg = sg[i].page;
+	#else
+		struct page *pg = sg_page(&sg[i]);
+	#endif
+		unsigned int offset = sg[i].offset;
+		unsigned int l = sg[i].length;
+
+		do {
+			unsigned int bytes_from_page = min(l, ((unsigned int)
+							   (PAGE_SIZE)) - 
+							   offset);
+			char *p = crypto_kmap(pg, 0) + offset;
+
+			tfm->__crt_alg->cra_digest.dia_update
+					(crypto_tfm_ctx(tfm), p,
+					 bytes_from_page);
+			crypto_kunmap(p, 0);
+			crypto_yield(tfm);
+			offset = 0;
+			pg++;
+			l -= bytes_from_page;
+		} while (l > 0);
+	}
+}
+
+static void final(struct crypto_tfm *tfm, u8 *out)
+{
+	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
+}
+
+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	u32 flags;
+	if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+		return -ENOSYS;
+	return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+						     key, keylen, &flags);
+}
+
+static void digest(struct crypto_tfm *tfm,
+                   struct scatterlist *sg, unsigned int nsg, u8 *out)
+{
+	unsigned int i;
+
+	tfm->crt_digest.dit_init(tfm);
+		
+	for (i = 0; i < nsg; i++) {
+	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
+	#else
+		char *p = crypto_kmap(sg_page(&sg[i]), 0) + sg[i].offset;
+	#endif
+		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
+		                                      p, sg[i].length);
+		crypto_kunmap(p, 0);
+		crypto_yield(tfm);
+	}
+	crypto_digest_final(tfm, out);
+}
+
+int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
+{
+	return flags ? -EINVAL : 0;
+}
+
+int crypto_init_digest_ops(struct crypto_tfm *tfm)
+{
+	struct digest_tfm *ops = &tfm->crt_digest;
+	
+	ops->dit_init	= init;
+	ops->dit_update	= update;
+	ops->dit_final	= final;
+	ops->dit_digest	= digest;
+	ops->dit_setkey	= setkey;
+	
+	return crypto_alloc_hmac_block(tfm);
+}
+
+void crypto_exit_digest_ops(struct crypto_tfm *tfm)
+{
+	crypto_free_hmac_block(tfm);
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/Makefile
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/Makefile
@@ -0,0 +1,214 @@
+NIC_SELECT = RTL8192SE
+
+KVER  := $(shell uname -r)
+MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/$(NIC_SELECT)
+
+CC = gcc
+ifneq ($(shell uname -r|cut -d. -f1,2), 2.4)
+EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless
+EXTRA_CFLAGS += -O2
+
+#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem.
+ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0)
+EXTRA_CFLAGS += -DOPENSUSE_SLED
+endif
+ifeq ($(NIC_SELECT), RTL8192SE)
+	EXTRA_CFLAGS += -DRTL8192S_DISABLE_FW_DM=0
+	EXTRA_CFLAGS += -DRTL8192SE
+	EXTRA_CFLAGS += -DENABLE_IPS
+	EXTRA_CFLAGS += -DENABLE_LPS
+endif
+ifeq ($(NIC_SELECT), RTL8192SU)
+	EXTRA_CFLAGS += -DRTL8192S_DISABLE_FW_DM=0
+	EXTRA_CFLAGS += -DRTL8192SU
+	EXTRA_CFLAGS += -DENABLE_IPS
+	EXTRA_CFLAGS += -DENABLE_LPS
+	EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT
+	EXTRA_CFLAGS += -DTCP_CSUM_OFFLOAD_RX
+endif
+ifeq ($(NIC_SELECT), RTL8190P)
+	EXTRA_CFLAGS += -DRTL8190P
+endif
+ifeq ($(NIC_SELECT), RTL8192E)
+	EXTRA_CFLAGS += -DRTL8192E
+        EXTRA_CFLAGS += -DENABLE_IPS
+        EXTRA_CFLAGS += -DENABLE_LPS
+endif
+ifeq ($(NIC_SELECT),RTL8192U)
+EXTRA_CFLAGS += -DRTL8192U
+#EXTRA_CFLAGS += -DENABLE_AMSDU
+EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
+EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT
+
+# For RTK DMP platform
+#EXTRA_CFLAGS += -DRTK_DMP_PLATFORM
+#EXTRA_CFLAGS += -DWIFI_TEST
+
+endif
+ifeq ($(NIC_SELECT), RTL8191SE_MESH)
+AUTHTYPE=SAE
+#AUTHTYPE=OPEN
+EXTRA_CFLAGS += -DRTL8192SE \
+		-DRTL8192S_DISABLE_FW_DM=0 \
+		-D_RTL8192_EXT_PATCH_\
+		-DENABLE_IPS \
+		-DENABLE_LPS \
+		-DCUSTOMER_ID_INTEL_CMPC
+ifeq ($(AUTHTYPE),SAE)
+EXTRA_CFLAGS += -DMESH_ABBR_HANDSHK_SUPPORT\
+		-DMESH_ATH_2
+endif
+endif
+#EXTRA_CFLAGS += -DJOHN_NOCPY
+EXTRA_CFLAGS += -DTHOMAS_TURBO
+#flags to enable or disble 80211D feature
+EXTRA_CFLAGS += -DENABLE_DOT11D
+rtllib-rsl-objs := rtllib_rx.o \
+		      rtllib_softmac.o \
+		      rtllib_tx.o \
+		      rtllib_wx.o \
+		      rtllib_module.o \
+		      rtllib_softmac_wx.o\
+		      rtl819x_HTProc.o\
+		      rtl819x_TSProc.o\
+		      rtl819x_BAProc.o\
+		      dot11d.o
+
+rtllib_crypt-rsl-objs := rtllib_crypt.o
+rtllib_crypt_tkip-rsl-objs := rtllib_crypt_tkip.o
+rtllib_crypt_ccmp-rsl-objs := rtllib_crypt_ccmp.o
+rtllib_crypt_wep-rsl-objs := rtllib_crypt_wep.o
+
+obj-m +=rtllib-rsl.o
+obj-m +=rtllib_crypt-rsl.o
+obj-m +=rtllib_crypt_wep-rsl.o
+obj-m +=rtllib_crypt_tkip-rsl.o
+obj-m +=rtllib_crypt_ccmp-rsl.o
+
+KSRC := /lib/modules/$(KVER)/build
+INSTALL_PREFIX :=
+
+all: modules
+
+modules:
+	$(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules
+
+install: modules
+	rm -fr $(MODDESTDIR)
+	mkdir -p $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt-rsl.ko $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_wep-rsl.ko $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_tkip-rsl.ko $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_ccmp-rsl.ko $(MODDESTDIR)
+	@install -p -m 644 rtllib-rsl.ko $(MODDESTDIR)
+	depmod -a
+uninstall:
+	rm -fr $(MODDESTDIR)
+	depmod -a 
+
+else
+LD := ld
+KSRC := /lib/modules/$(KVER)/build
+CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
+
+CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
+CFLAGS += -I$(KSRC)/include -I.
+#Kernel 2.4.31
+CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h
+#Kernel 2.4.20
+#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB 
+CFLAGS += -DENABLE_DOT11D
+CFLAGS += -DTHOMAS_TURBO
+
+ifeq ($(NIC_SELECT),RTL8192U)
+CFLAGS += -DRTL8192U
+#EXTRA_CFLAGS += -DENABLE_AMSDU
+EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
+EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT
+endif
+ifeq ($(NIC_SELECT),RTL8192E)
+CFLAGS += -DRTL8192E
+endif
+ifeq ($(NIC_SELECT),RTL8190P)
+CFLAGS += -DRTL8190P
+endif
+ifeq ($(NIC_SELECT),RTL8192SE)
+CFLAGS += -DRTL8192SE
+CFLAGS += -DRTL8192S_DISABLE_FW_DM=0
+endif
+ifeq ($(NIC_SELECT), RTL8191SE_MESH)
+AUTHTYPE=SAE
+#AUTHTYPE=OPEN
+CFLAGS += -DRTL8192SE
+CFLAGS += -DRTL8192S_DISABLE_FW_DM=0
+CFLAGS += -D_RTL8192_EXT_PATCH_
+ifeq ($(AUTHTYPE),SAE)
+CFLAGS += -DMESH_ABBR_HANDSHK_SUPPORT\
+CFLAGS += -DMESH_ATH_2
+endif
+endif
+
+SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \
+   grep CONFIG_SMP | awk '{print $$3}')
+ifneq ($(SMP),1)
+   SMP := 0
+endif
+ifeq ($(SMP),1)
+   CFLAGS    += -D__SMP__
+endif
+
+#CFLAGS += -DJOHN_NOCPY
+
+OBJS := ${patsubst %.c, %.o, ${wildcard *.c}}
+all:${OBJS} rtllib_crypt-rsl.o michael_mic-rsl.o aes-rsl.o rtllib_crypt_wep-rsl.o rtllib_crypt_tkip-rsl.o rtllib_crypt_ccmp-rsl.o crypto-rsl.o rtllib-rsl.o
+
+rtllib_crypt-rsl.o: rtllib_crypt.o
+	mv $^ $@	
+
+michael_mic-rsl.o: michael_mic.o
+	mv $^ $@
+
+aes-rsl.o: aes.o
+	mv $^ $@
+
+rtllib_crypt_wep-rsl.o: rtllib_crypt_wep.o
+	mv $^ $@
+
+rtllib_crypt_tkip-rsl.o: rtllib_crypt_tkip.o
+	mv $^ $@
+
+rtllib_crypt_ccmp-rsl.o: rtllib_crypt_ccmp.o
+	mv $^ $@
+
+crypto-rsl.o: arc4.o api.o autoload.o cipher.o compress.o digest.o scatterwalk.o proc.o
+	$(LD) -r $^ -o $@
+
+rtllib-rsl.o: rtllib_rx.o rtllib_tx.o rtllib_wx.o rtllib_module.o rtllib_softmac_wx.o rtllib_softmac.o rtl819x_HTProc.o rtl819x_TSProc.o rtl819x_BAProc.o dot11d.o
+	$(LD) -r $^ -o $@
+install:
+	rm -fr $(MODDESTDIR)
+	mkdir -p $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt-rsl.o $(MODDESTDIR)
+	@install -p -m 644 crypto-rsl.o $(MODDESTDIR)
+	@install -p -m 644 michael_mic-rsl.o $(MODDESTDIR)
+	@install -p -m 644 aes-rsl.o $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_wep-rsl.o $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_tkip-rsl.o $(MODDESTDIR)
+	@install -p -m 644 rtllib_crypt_ccmp-rsl.o $(MODDESTDIR)
+	@install -p -m 644 rtllib-rsl.o $(MODDESTDIR)
+	/sbin/depmod -a ${shell uname -r}
+
+uninstall:
+	rm -fr $(MODDESTDIR)
+	/sbin/depmod -a ${shell uname -r}
+
+endif
+
+.PHONY: clean
+clean:
+	rm -fr *.mod.c *.mod *.o .*.cmd *.mod.* *.ko *.o *~
+	rm -rf .tmp_versions
+	rm -rf Module.symvers
+	rm -fr Module.markers
+	rm -fr modules.order
+	rm -fr tags
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/kmap_types.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/kmap_types.h
@@ -0,0 +1,20 @@
+#ifndef __KMAP_TYPES_H
+
+#define __KMAP_TYPES_H
+
+
+enum km_type {
+	KM_BOUNCE_READ,
+	KM_SKB_SUNRPC_DATA,
+	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
+	KM_BH_IRQ,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	KM_TYPE_NR
+};
+
+#define _ASM_KMAP_TYPES_H
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_rx.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_rx.c
@@ -0,0 +1,5266 @@
+/*
+ * Original code based Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * 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. See README and COPYING for
+ * more details.
+ ******************************************************************************
+
+  Few modifications for Realtek's Wi-Fi drivers by 
+  Andrea Merello <andreamrl@tiscali.it>
+  
+  A special thanks goes to Realtek for their support ! 
+
+******************************************************************************/
+ 
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
+
+#include "rtllib.h"
+#ifdef ENABLE_DOT11D
+#include "dot11d.h"
+#endif
+
+#ifdef RTLLIB_RADIOTAP
+#include <net/ieee80211_radiotap.h>
+#endif
+
+#if defined CONFIG_CFG_80211
+#include <linux/crc32.h>
+
+struct ieee80211_channel *rtllib_get_channel(struct wiphy *wiphy,
+						  int freq)
+{
+	enum ieee80211_band band;
+	struct ieee80211_supported_band *sband;
+	int i;
+
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		sband = wiphy->bands[band];
+
+		if (!sband)
+			continue;
+
+		for (i = 0; i < sband->n_channels; i++) {
+			if (sband->channels[i].center_freq == freq)
+				return &sband->channels[i];
+		}
+	}
+
+	return NULL;
+}
+
+int rtllib_channel_to_frequency(int chan)
+{
+	if (chan < 14)
+		return 2407 + chan * 5;
+
+	if (chan == 14)
+		return 2484;
+
+	/* FIXME: 802.11j 17.3.8.3.2 */
+	return (chan + 1000) * 5;
+}
+
+u32 rtllib_parse_elems_crc(u8 *start, size_t len,
+			       struct ieee802_11_elems *elems,
+			       u64 filter, u32 crc)
+{
+	size_t left = len;
+	u8 *pos = start;
+	bool calc_crc = filter != 0;
+
+	memset(elems, 0, sizeof(*elems));
+	elems->ie_start = start;
+	elems->total_len = len;
+
+	while (left >= 2) {
+		u8 id, elen;
+
+		id = *pos++;
+		elen = *pos++;
+		left -= 2;
+
+		if (elen > left)
+			break;
+
+		if (calc_crc && id < 64 && (filter & BIT(id)))
+			crc = crc32_be(crc, pos - 2, elen + 2);
+
+		switch (id) {
+		case WLAN_EID_SSID:
+			elems->ssid = pos;
+			elems->ssid_len = elen;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			elems->supp_rates = pos;
+			elems->supp_rates_len = elen;
+			break;
+		case WLAN_EID_FH_PARAMS:
+			elems->fh_params = pos;
+			elems->fh_params_len = elen;
+			break;
+		case WLAN_EID_DS_PARAMS:
+			elems->ds_params = pos;
+			elems->ds_params_len = elen;
+			break;
+		case WLAN_EID_CF_PARAMS:
+			elems->cf_params = pos;
+			elems->cf_params_len = elen;
+			break;
+		case WLAN_EID_TIM:
+			if (elen >= sizeof(struct ieee80211_tim_ie)) {
+				elems->tim = (void *)pos;
+				elems->tim_len = elen;
+			}
+			break;
+		case WLAN_EID_IBSS_PARAMS:
+			elems->ibss_params = pos;
+			elems->ibss_params_len = elen;
+			break;
+		case WLAN_EID_CHALLENGE:
+			elems->challenge = pos;
+			elems->challenge_len = elen;
+			break;
+		case WLAN_EID_VENDOR_SPECIFIC:
+			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
+			    pos[2] == 0xf2) {
+				/* Microsoft OUI (00:50:F2) */
+
+				if (calc_crc)
+					crc = crc32_be(crc, pos - 2, elen + 2);
+
+				if (pos[3] == 1) {
+					/* OUI Type 1 - WPA IE */
+					elems->wpa = pos;
+					elems->wpa_len = elen;
+				} else if (elen >= 5 && pos[3] == 2) {
+					/* OUI Type 2 - WMM IE */
+					if (pos[4] == 0) {
+						elems->wmm_info = pos;
+						elems->wmm_info_len = elen;
+					} else if (pos[4] == 1) {
+						elems->wmm_param = pos;
+						elems->wmm_param_len = elen;
+					}
+				}
+			}
+			break;
+		case WLAN_EID_RSN:
+			elems->rsn = pos;
+			elems->rsn_len = elen;
+			break;
+		case WLAN_EID_ERP_INFO:
+			elems->erp_info = pos;
+			elems->erp_info_len = elen;
+			break;
+		case WLAN_EID_EXT_SUPP_RATES:
+			elems->ext_supp_rates = pos;
+			elems->ext_supp_rates_len = elen;
+			break;
+		case WLAN_EID_HT_CAPABILITY:
+			if (elen >= sizeof(struct ieee80211_ht_cap))
+				elems->ht_cap_elem = (void *)pos;
+			break;
+		case WLAN_EID_HT_INFORMATION:
+			if (elen >= sizeof(struct ieee80211_ht_info))
+				elems->ht_info_elem = (void *)pos;
+			break;
+		case WLAN_EID_MESH_ID:
+			elems->mesh_id = pos;
+			elems->mesh_id_len = elen;
+			break;
+		case WLAN_EID_MESH_CONFIG:
+			elems->mesh_config = pos;
+			elems->mesh_config_len = elen;
+			break;
+		case WLAN_EID_PEER_LINK:
+			elems->peer_link = pos;
+			elems->peer_link_len = elen;
+			break;
+		case WLAN_EID_PREQ:
+			elems->preq = pos;
+			elems->preq_len = elen;
+			break;
+		case WLAN_EID_PREP:
+			elems->prep = pos;
+			elems->prep_len = elen;
+			break;
+		case WLAN_EID_PERR:
+			elems->perr = pos;
+			elems->perr_len = elen;
+			break;
+		case WLAN_EID_CHANNEL_SWITCH:
+			elems->ch_switch_elem = pos;
+			elems->ch_switch_elem_len = elen;
+			break;
+		case WLAN_EID_QUIET:
+			if (!elems->quiet_elem) {
+				elems->quiet_elem = pos;
+				elems->quiet_elem_len = elen;
+			}
+			elems->num_of_quiet_elem++;
+			break;
+		case WLAN_EID_COUNTRY:
+			elems->country_elem = pos;
+			elems->country_elem_len = elen;
+			break;
+		case WLAN_EID_PWR_CONSTRAINT:
+			elems->pwr_constr_elem = pos;
+			elems->pwr_constr_elem_len = elen;
+			break;
+		case WLAN_EID_TIMEOUT_INTERVAL:
+			elems->timeout_int = pos;
+			elems->timeout_int_len = elen;
+			break;
+		default:
+			break;
+		}
+
+		left -= elen;
+		pos += elen;
+	}
+
+	return crc;
+}
+
+void rtllib_parse_elems(u8 *start, size_t len,
+			    struct ieee802_11_elems *elems)
+{
+	rtllib_parse_elems_crc(start, len, elems, 0, 0);
+}
+
+void ieee80211_scan_rx(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_status)
+{
+	struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ;
+	struct ieee80211_mgmt *mgmt;
+	struct ieee80211_bss *bss;
+	u8 *elements;
+	struct ieee80211_channel *channel;
+	size_t baselen;
+	int freq;
+	__le16 fc;
+	bool presp, beacon = false;
+	struct ieee802_11_elems elems;
+	s32 signal = 0;
+
+	if (skb->len < 2)
+		return;
+
+	mgmt = (struct ieee80211_mgmt *) skb->data;
+	fc = mgmt->frame_control;
+
+	if (skb->len < 24)
+		return;
+	
+	presp = (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_PROBE_RESP);
+	if (presp) {
+		/* ignore ProbeResp to foreign address */
+		if (memcmp(mgmt->da, ieee->dev->dev_addr, ETH_ALEN))
+			return ;;
+
+		presp = true;
+		elements = mgmt->u.probe_resp.variable;
+		baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+	} else {
+		beacon =  (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_BEACON);
+		baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		elements = mgmt->u.beacon.variable;
+	}
+
+	if (!presp && !beacon)
+		return;
+
+	if (baselen > skb->len)
+		return;
+
+	rtllib_parse_elems(elements, skb->len - baselen, &elems);
+
+	if (elems.ds_params && elems.ds_params_len == 1)
+		freq = rtllib_channel_to_frequency(elems.ds_params[0]);
+	else
+		return;
+
+	channel = rtllib_get_channel(ieee->wdev.wiphy, freq);
+
+	if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
+		return;
+
+		signal = rx_status->signal * 100;
+
+	bss = (void *)cfg80211_inform_bss_frame(ieee->wdev.wiphy, channel,
+						mgmt, skb->len, signal, GFP_ATOMIC);
+
+	return;
+}
+#endif
+
+#ifdef RTLLIB_RADIOTAP
+static int rtllib_rx_radiotap_len(struct rtllib_device *ieee, struct rtllib_rx_stats *rx_status) 
+{
+	int len;
+
+	/* always present fields */
+	len = sizeof(struct ieee80211_radiotap_header) + 9 +
+		8 + /* TSFT */
+		1 + /* HW SIGNAL DBM */
+		1;  /* HW NOISE DBM */
+
+	if (len & 1) /* padding for RX_FLAGS if necessary */
+		len++;
+
+	/* make sure radiotap starts at a naturally aligned address */
+	if (len % 8)
+		len = roundup(len, 8);
+
+	return len;
+}
+
+static void rtllib_add_rx_radiotap_header(struct rtllib_device *ieee, 
+		struct sk_buff *skb, int rtap_len, struct rtllib_rx_stats *rx_status)
+{
+	struct ieee80211_radiotap_header *rthdr;
+	unsigned char *pos;
+	printk("add header!\n");
+	rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
+	memset(rthdr, 0, rtap_len);
+	
+	rthdr->it_version = PKTHDR_RADIOTAP_VERSION;
+	rthdr->it_pad = 0;
+	rthdr->it_len = cpu_to_le16(rtap_len);
+	/* radiotap header, set always present flags */
+	rthdr->it_present = cpu_to_le32(
+		(1 << IEEE80211_RADIOTAP_TSFT) |
+		(1 << IEEE80211_RADIOTAP_FLAGS) |
+		(1 << IEEE80211_RADIOTAP_RATE) |
+		(1 << IEEE80211_RADIOTAP_CHANNEL) |
+		(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+		(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+		(1 << IEEE80211_RADIOTAP_ANTENNA));
+
+	pos = (unsigned char *)(rthdr+1);
+	/* the order of the following fields is important */
+	/* IEEE80211_RADIOTAP_TSFT */
+	*(__le64 *)pos = cpu_to_le64((rx_status->mac_time[1] << 32) | \
+			rx_status->mac_time[0]);
+	pos += 8;
+
+	/* IEEE80211_RADIOTAP_FLAGS */
+	if (rx_status->bCRC)
+		*pos |= IEEE80211_RADIOTAP_F_BADFCS;
+	if (rx_status->bShortPreamble)
+		*pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
+	pos++;
+
+	/* IEEE80211_RADIOTAP_RATE */
+	*pos = rx_status->rate / 5;
+	pos++;
+
+	/* IEEE80211_RADIOTAP_CHANNEL */
+	*(__le16 *)pos = cpu_to_le16(rx_status->received_channel);
+	pos += 2;
+#if 0	
+	if (status->band == IEEE80211_BAND_5GHZ)
+		*(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
+				IEEE80211_CHAN_5GHZ);
+	else if (rate->flags & IEEE80211_RATE_ERP_G)
+		*(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
+				IEEE80211_CHAN_2GHZ);
+	else
+		*(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK |
+				IEEE80211_CHAN_2GHZ);
+#endif	
+	pos += 2;
+
+	
+	/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
+	*pos = rx_status->RxPower;
+	pos++;
+
+	/* IEEE80211_RADIOTAP_DBM_ANTNOISE */
+	*pos = rx_status->noise;
+	pos++;
+
+	/* IEEE80211_RADIOTAP_ANTENNA */
+	*pos = rx_status->Antenna;
+	pos++;
+
+	/* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
+
+	/* IEEE80211_RADIOTAP_RX_FLAGS */
+	/* ensure 2 byte alignment for the 2 byte field as required */
+#if 0	
+	if ((pos - (unsigned char *)rthdr) & 1)
+		pos++;
+	if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
+		*(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP);
+	pos += 2;
+#endif	
+}
+#endif
+
+static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
+				struct sk_buff *skb,struct rtllib_rx_stats *rx_status, 
+				size_t hdr_length)
+{
+#ifdef RTLLIB_RADIOTAP
+	int needed_headroom = 0;
+	struct sk_buff *radiotap_skb;
+
+	needed_headroom = rtllib_rx_radiotap_len(ieee, rx_status);
+	printk("needed_headroom = %d\n", needed_headroom);
+	radiotap_skb = skb_copy_expand(skb, needed_headroom, 0, GFP_ATOMIC);
+	dev_kfree_skb(skb);
+	if (!radiotap_skb) {
+		return;
+	}
+
+	rtllib_add_rx_radiotap_header(ieee, skb, needed_headroom, rx_status);
+	radiotap_skb->dev = ieee->dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+        skb_reset_mac_header(radiotap_skb);
+#else
+        radiotap_skb->mac.raw = skb->data;
+#endif
+	radiotap_skb->ip_summed = CHECKSUM_UNNECESSARY;
+	radiotap_skb->pkt_type = PACKET_OTHERHOST;
+	radiotap_skb->protocol = htons(ETH_P_802_2);
+	memset(radiotap_skb->cb, 0, sizeof(radiotap_skb->cb));
+	netif_rx(radiotap_skb);
+#else	
+	skb->dev = ieee->dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+        skb_reset_mac_header(skb);
+#else
+        skb->mac.raw = skb->data;
+#endif
+	skb_pull(skb, hdr_length);
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = __constant_htons(ETH_P_80211_RAW);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx(skb);
+#endif	
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct rtllib_frag_entry *
+rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq,
+			  unsigned int frag, u8 tid,u8 *src, u8 *dst)
+{
+	struct rtllib_frag_entry *entry;
+	int i;
+
+	for (i = 0; i < RTLLIB_FRAG_CACHE_LEN; i++) {
+		entry = &ieee->frag_cache[tid][i];
+		if (entry->skb != NULL &&
+		    time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+			RTLLIB_DEBUG_FRAG(
+				"expiring fragment cache entry "
+				"seq=%u last_frag=%u\n",
+				entry->seq, entry->last_frag);
+			dev_kfree_skb_any(entry->skb);
+			entry->skb = NULL;
+		}
+
+		if (entry->skb != NULL && entry->seq == seq &&
+		    (entry->last_frag + 1 == frag || frag == -1) &&
+		    memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
+		    memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
+			return entry;
+	}
+
+	return NULL;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *
+rtllib_frag_cache_get(struct rtllib_device *ieee,
+			 struct rtllib_hdr_4addr *hdr)
+{
+	struct sk_buff *skb = NULL;
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	u16 sc = le16_to_cpu(hdr->seq_ctl);
+	unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
+	unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
+	struct rtllib_frag_entry *entry;
+	struct rtllib_hdr_3addrqos *hdr_3addrqos;
+	struct rtllib_hdr_4addrqos *hdr_4addrqos;
+	u8 tid;
+	
+	if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) {
+	  hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
+	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else if (RTLLIB_QOS_HAS_SEQ(fc)) {
+	  hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
+	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else {
+	  tid = 0;
+	}
+
+	if (frag == 0) {
+		/* Reserve enough space to fit maximum frame length */
+		skb = dev_alloc_skb(ieee->dev->mtu +
+				    sizeof(struct rtllib_hdr_4addr) +
+				    8 /* LLC */ +
+				    2 /* alignment */ +
+				    8 /* WEP */ + 
+				    ETH_ALEN /* WDS */ +
+				    (RTLLIB_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
+		if (skb == NULL)
+			return NULL;
+
+		entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
+		ieee->frag_next_idx[tid]++;
+		if (ieee->frag_next_idx[tid] >= RTLLIB_FRAG_CACHE_LEN)
+			ieee->frag_next_idx[tid] = 0;
+
+		if (entry->skb != NULL)
+			dev_kfree_skb_any(entry->skb);
+
+		entry->first_frag_time = jiffies;
+		entry->seq = seq;
+		entry->last_frag = frag;
+		entry->skb = skb;
+		memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+		memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+	} else {
+		/* received a fragment of a frame for which the head fragment
+		 * should have already been received */
+		entry = rtllib_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
+						  hdr->addr1);
+		if (entry != NULL) {
+			entry->last_frag = frag;
+			skb = entry->skb;
+		}
+	}
+
+	return skb;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee,
+					   struct rtllib_hdr_4addr *hdr)
+{
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	u16 sc = le16_to_cpu(hdr->seq_ctl);
+	unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
+	struct rtllib_frag_entry *entry;
+	struct rtllib_hdr_3addrqos *hdr_3addrqos;
+	struct rtllib_hdr_4addrqos *hdr_4addrqos;
+	u8 tid;
+	
+	if(((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) {
+	  hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
+	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else if (RTLLIB_QOS_HAS_SEQ(fc)) {
+	  hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
+	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else {
+	  tid = 0;
+	}
+
+	entry = rtllib_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
+					  hdr->addr1);
+
+	if (entry == NULL) {
+		RTLLIB_DEBUG_FRAG(
+			"could not invalidate fragment cache "
+			"entry (seq=%u)\n", seq);
+		return -1;
+	}
+
+	entry->skb = NULL;
+	return 0;
+}
+
+
+
+/* rtllib_rx_frame_mgtmt
+ *
+ * Responsible for handling management control frames
+ *
+ * Called by rtllib_rx */
+static inline int
+rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
+			struct rtllib_rx_stats *rx_stats, u16 type,
+			u16 stype)
+{
+	/* On the struct stats definition there is written that
+	 * this is not mandatory.... but seems that the probe
+	 * response parser uses it
+	 */
+	struct rtllib_hdr_3addr * hdr = (struct rtllib_hdr_3addr *)skb->data;
+
+	rx_stats->len = skb->len;
+	rtllib_rx_mgt(ieee,skb,rx_stats);	
+#ifdef _RTL8192_EXT_PATCH_   
+	if(ieee->iw_mode == IW_MODE_MESH){
+		if ((stype != RTLLIB_STYPE_MESH_ACT) && (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))
+		{
+			dev_kfree_skb_any(skb);
+			return 0;
+		}
+	}
+	else
+#endif
+	{
+		if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))
+		{
+			dev_kfree_skb_any(skb);
+			return 0;
+		}
+	}
+	rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
+
+	dev_kfree_skb_any(skb);
+	
+	return 0;
+	
+#ifdef NOT_YET
+	if (ieee->iw_mode == IW_MODE_MASTER) {
+		printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
+		       ieee->dev->name);
+		return 0;
+/*
+  hostap_update_sta_ps(ieee, (struct hostap_rtllib_hdr_4addr *)
+  skb->data);*/
+	}
+
+	if (ieee->hostapd && type == RTLLIB_TYPE_MGMT) {
+		if (stype == WLAN_FC_STYPE_BEACON &&
+		    ieee->iw_mode == IW_MODE_MASTER) {
+			struct sk_buff *skb2;
+			/* Process beacon frames also in kernel driver to
+			 * update STA(AP) table statistics */
+			skb2 = skb_clone(skb, GFP_ATOMIC);
+			if (skb2)
+				hostap_rx(skb2->dev, skb2, rx_stats);
+		}
+
+		/* send management frames to the user space daemon for
+		 * processing */
+		ieee->apdevstats.rx_packets++;
+		ieee->apdevstats.rx_bytes += skb->len;
+		prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
+		return 0;
+	}
+
+	    if (ieee->iw_mode == IW_MODE_MASTER) {
+		if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
+			printk(KERN_DEBUG "%s: unknown management frame "
+			       "(type=0x%02x, stype=0x%02x) dropped\n",
+			       skb->dev->name, type, stype);
+			return -1;
+		}
+
+		hostap_rx(skb->dev, skb, rx_stats);
+		return 0;
+	}
+
+	printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
+	       "received in non-Host AP mode\n", skb->dev->name);
+	return -1;
+#endif
+}
+
+#ifndef CONFIG_CFG_80211
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+#endif
+
+/* Called by rtllib_rx_frame_decrypt */
+static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
+				    struct sk_buff *skb, size_t hdrlen)
+{
+	struct net_device *dev = ieee->dev;
+	u16 fc, ethertype;
+	struct rtllib_hdr_4addr *hdr;
+	u8 *pos;
+
+	if (skb->len < 24)
+		return 0;
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	fc = le16_to_cpu(hdr->frame_ctl);
+
+	/* check that the frame is unicast frame to us */
+	if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+	    RTLLIB_FCTL_TODS &&
+	    memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
+	    memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+		/* ToDS frame with own addr BSSID and DA */
+	} else if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+		   RTLLIB_FCTL_FROMDS &&
+		   memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+		/* FromDS frame with own addr as DA */
+	} else
+		return 0;
+
+	if (skb->len < 24 + 8)
+		return 0;
+
+	/* check for port access entity Ethernet type */
+	pos = skb->data + hdrlen;
+	ethertype = (pos[6] << 8) | pos[7];
+	if (ethertype == ETH_P_PAE)
+		return 1;
+
+	return 0;
+}
+
+/* Called only as a tasklet (software IRQ), by rtllib_rx */
+static inline int
+rtllib_rx_frame_decrypt(struct rtllib_device* ieee, struct sk_buff *skb,
+			   struct rtllib_crypt_data *crypt)
+{
+	struct rtllib_hdr_4addr *hdr;
+	int res, hdrlen;
+
+	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+		return 0;
+#if 1
+	if (ieee->hwsec_active)
+	{
+		cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
+		tcb_desc->bHwSec = 1;
+
+		if(ieee->need_sw_enc)
+			tcb_desc->bHwSec = 0;
+	}
+#endif	
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+#ifdef CONFIG_RTLLIB_CRYPT_TKIP
+	if (ieee->tkip_countermeasures &&
+	    strcmp(crypt->ops->name, "TKIP") == 0) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			       "received packet from " MAC_FMT "\n",
+			       ieee->dev->name, MAC_ARG(hdr->addr2));
+		}
+		return -1;
+	}
+#endif
+
+	atomic_inc(&crypt->refcnt);
+	res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+	atomic_dec(&crypt->refcnt);
+	if (res < 0) {
+		RTLLIB_DEBUG_DROP(
+			"decryption failed (SA=" MAC_FMT
+			") res=%d\n", MAC_ARG(hdr->addr2), res);
+		if (res == -2)
+			RTLLIB_DEBUG_DROP("Decryption failed ICV "
+					     "mismatch (key %d)\n",
+					     skb->data[hdrlen + 3] >> 6);
+		ieee->ieee_stats.rx_discards_undecryptable++;
+		return -1;
+	}
+
+	return res;
+}
+
+
+/* Called only as a tasklet (software IRQ), by rtllib_rx */
+static inline int
+rtllib_rx_frame_decrypt_msdu(struct rtllib_device* ieee, struct sk_buff *skb,
+			     int keyidx, struct rtllib_crypt_data *crypt)
+{
+	struct rtllib_hdr_4addr *hdr;
+	int res, hdrlen;
+
+	if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+		return 0;
+	if (ieee->hwsec_active)
+	{
+		cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
+		tcb_desc->bHwSec = 1;
+	
+		if(ieee->need_sw_enc)
+			tcb_desc->bHwSec = 0;
+	}
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+	atomic_inc(&crypt->refcnt);
+	res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv,ieee);
+	atomic_dec(&crypt->refcnt);
+	if (res < 0) {
+		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
+		       " (SA=" MAC_FMT " keyidx=%d)\n",
+		       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef _RTL8192_EXT_PATCH_	
+static inline int rtllib_has_retry(u16 fc)
+{
+    return ((fc&RTLLIB_FCTL_RETRY)!=0);
+}
+#endif	
+
+/* this function is stolen from ipw2200 driver*/
+#define IEEE_PACKET_RETRY_TIME (5*HZ)
+static int is_duplicate_packet(struct rtllib_device *ieee,
+				      struct rtllib_hdr_4addr *header)
+{
+	u16 fc = le16_to_cpu(header->frame_ctl);
+	u16 sc = le16_to_cpu(header->seq_ctl);
+	u16 seq = WLAN_GET_SEQ_SEQ(sc);
+	u16 frag = WLAN_GET_SEQ_FRAG(sc);
+	u16 *last_seq, *last_frag;
+	unsigned long *last_time;
+	struct rtllib_hdr_3addrqos *hdr_3addrqos;
+	struct rtllib_hdr_4addrqos *hdr_4addrqos;
+	u8 tid;
+	
+	if(((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) {
+	  hdr_4addrqos = (struct rtllib_hdr_4addrqos *)header;
+	  tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else if(RTLLIB_QOS_HAS_SEQ(fc)) { 
+	  hdr_3addrqos = (struct rtllib_hdr_3addrqos*)header;
+	  tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+	  tid = UP2AC(tid);
+	  tid ++;
+	} else { 
+	  tid = 0;
+	}
+
+	switch (ieee->iw_mode) {
+	case IW_MODE_ADHOC:
+	{
+		struct list_head *p;
+		struct ieee_ibss_seq *entry = NULL;
+		u8 *mac = header->addr2;
+		int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
+		list_for_each(p, &ieee->ibss_mac_hash[index]) {
+			entry = list_entry(p, struct ieee_ibss_seq, list);
+			if (!memcmp(entry->mac, mac, ETH_ALEN))
+				break;
+		}
+		if (p == &ieee->ibss_mac_hash[index]) {
+			entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
+			if (!entry) {
+				printk(KERN_WARNING "Cannot malloc new mac entry\n");
+				return 0;
+			}
+			memcpy(entry->mac, mac, ETH_ALEN);
+			entry->seq_num[tid] = seq;
+			entry->frag_num[tid] = frag;
+			entry->packet_time[tid] = jiffies;
+			list_add(&entry->list, &ieee->ibss_mac_hash[index]);
+			return 0;
+		}
+		last_seq = &entry->seq_num[tid];
+		last_frag = &entry->frag_num[tid];
+		last_time = &entry->packet_time[tid];
+		break;
+	}
+	
+	case IW_MODE_INFRA:
+		last_seq = &ieee->last_rxseq_num[tid];
+		last_frag = &ieee->last_rxfrag_num[tid];
+		last_time = &ieee->last_packet_time[tid];
+		
+		break;
+
+#ifdef _RTL8192_EXT_PATCH_	
+	case IW_MODE_MESH:
+		/* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
+		if(!is_multicast_ether_addr(header->addr1)){
+			struct list_head *p;
+			struct ieee_mesh_seq *entry = NULL;
+			u8 *mac = header->addr2;
+			int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
+			list_for_each(p, &ieee->mesh_mac_hash[index]) {
+				entry = list_entry(p, struct ieee_mesh_seq, list);
+				if (!memcmp(entry->mac, mac, ETH_ALEN))
+					break;
+			}
+
+			if (p == &ieee->mesh_mac_hash[index]) {
+				entry = kmalloc(sizeof(struct ieee_mesh_seq), GFP_ATOMIC);
+				if (!entry) {
+					printk(KERN_WARNING "Cannot malloc new mac entry\n");
+					return 0;
+				}
+				memcpy(entry->mac, mac, ETH_ALEN);
+				entry->seq_num[tid] = header->seq_ctl;
+				entry->packet_time[tid] = jiffies;
+				list_add(&entry->list, &ieee->mesh_mac_hash[index]);
+				return 0;
+			}
+			last_seq = &entry->seq_num[tid];
+			last_time = &entry->packet_time[tid];
+
+			if (unlikely(rtllib_has_retry(fc) &&
+				*last_seq == header->seq_ctl)) {
+				goto drop;
+			} else {
+				*last_seq = header->seq_ctl;
+			}
+			*last_time = jiffies;
+		}
+		return 0;
+#endif	
+	default:
+		return 0;
+	}
+
+	if ((*last_seq == seq) &&
+	    time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
+		if (*last_frag == frag){
+			goto drop;
+
+		}
+		if (*last_frag + 1 != frag)
+			/* out-of-order fragment */
+			goto drop;
+	} else
+		*last_seq = seq;
+
+	*last_frag = frag;
+	*last_time = jiffies;
+	return 0;
+
+drop:
+	
+	return 1;
+}
+bool
+AddReorderEntry(
+	PRX_TS_RECORD			pTS,
+	PRX_REORDER_ENTRY		pReorderEntry
+	)
+{
+	struct list_head *pList = &pTS->RxPendingPktList;
+
+	while(pList->next != &pTS->RxPendingPktList)
+	{
+		if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
+		{
+			pList = pList->next;
+		}
+		else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
+		{
+			return false;
+		}
+		else
+		{
+			break;
+		}
+	}
+	pReorderEntry->List.next = pList->next;
+	pReorderEntry->List.next->prev = &pReorderEntry->List;
+	pReorderEntry->List.prev = pList;
+	pList->next = &pReorderEntry->List;
+
+	return true;
+}
+
+void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb** prxbIndicateArray,u8  index)
+{
+	struct net_device_stats *stats = &ieee->stats;
+	u8 i = 0 , j=0;
+	u16 ethertype;
+	for(j = 0; j<index; j++)
+	{
+		struct rtllib_rxb* prxb = prxbIndicateArray[j];
+#ifdef RTL8192S_WAPI_SUPPORT
+             if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable))
+             {
+        		if(WapiCheckDropForRxReorderCase(ieee,prxb))
+        		{
+        			WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__);
+				for(i = 0; i<prxb->nr_subframes; i++) {
+					if(prxb->subframes[i])
+        					dev_kfree_skb(prxb->subframes[i]);
+				}
+				prxb->nr_subframes = 0;
+        		}
+		}
+#endif
+		for(i = 0; i<prxb->nr_subframes; i++) {
+			struct sk_buff *sub_skb = prxb->subframes[i];
+				
+		/* convert hdr + possible LLC headers into Ethernet header */
+			ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
+			if (sub_skb->len >= 8 &&
+				((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
+				  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+				 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+			/* remove RFC1042 or Bridge-Tunnel encapsulation and
+			 * replace EtherType */
+				skb_pull(sub_skb, SNAP_SIZE);
+				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
+				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
+			} else {
+				u16 len;
+			/* Leave Ethernet header part of hdr and full payload */
+				len = htons(sub_skb->len);
+				memcpy(skb_push(sub_skb, 2), &len, 2);
+				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
+				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
+			}
+
+		/* Indicat the packets to upper layer */
+			if (sub_skb) {
+				stats->rx_packets++;
+				stats->rx_bytes += sub_skb->len;
+
+				memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
+#ifdef _RTL8192_EXT_PATCH_	
+				sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev);
+#else
+				sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
+				sub_skb->dev = ieee->dev;
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+				sub_skb->dev->stats.rx_packets++;
+				sub_skb->dev->stats.rx_bytes += sub_skb->len;
+#endif
+#ifdef TCP_CSUM_OFFLOAD_RX
+				if ( prxb->tcp_csum_valid)
+					sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
+				else
+					sub_skb->ip_summed = CHECKSUM_NONE;
+
+#else
+				sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+#endif				
+				ieee->last_rx_ps_time = jiffies;
+				netif_rx(sub_skb);
+			}
+		}
+		kfree(prxb);
+		prxb = NULL;	
+	}
+}
+
+void
+rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,	PRX_TS_RECORD pTS)
+{
+	PRX_REORDER_ENTRY	pRxReorderEntry;
+	struct rtllib_rxb*		RfdArray[REORDER_WIN_SIZE];
+	u8					RfdCnt = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+	
+	del_timer_sync(&pTS->RxPktPendingTimer);
+	while(!list_empty(&pTS->RxPendingPktList))
+	{
+		if(RfdCnt >= REORDER_WIN_SIZE){
+			printk("-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n", __func__);
+			break;
+		}
+
+		pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum %d!\n",__FUNCTION__, pRxReorderEntry->SeqNum);
+		list_del_init(&pRxReorderEntry->List);
+		
+		RfdArray[RfdCnt] = pRxReorderEntry->prxb;
+		
+		RfdCnt = RfdCnt + 1;
+		list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
+	}
+	rtllib_indicate_packets(ieee, RfdArray, RfdCnt);
+	
+	pTS->RxIndicateSeq = 0xffff;
+	
+	spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+#ifdef MERGE_TO_DO
+#endif	
+}
+
+
+void RxReorderIndicatePacket( struct rtllib_device *ieee,
+		struct rtllib_rxb* prxb,
+		PRX_TS_RECORD		pTS,
+		u16			SeqNum)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	PRX_REORDER_ENTRY 	pReorderEntry = NULL;
+	struct rtllib_rxb* prxbIndicateArray[REORDER_WIN_SIZE];
+	u8			WinSize = pHTInfo->RxReorderWinSize;
+	u16			WinEnd = 0;
+	u8			index = 0;
+	bool			bMatchWinStart = false, bPktInBuf = false;
+	unsigned long flags;
+	
+	RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize);
+
+	spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+
+	WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;
+#if 0
+	if(!list_empty(&ieee->RxReorder_Unused_List))
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): ieee->RxReorder_Unused_List is nut NULL\n");
+#endif
+	/* Rx Reorder initialize condition.*/
+	if(pTS->RxIndicateSeq == 0xffff) {
+		pTS->RxIndicateSeq = SeqNum;
+	}
+
+	/* Drop out the packet which SeqNum is smaller than WinStart */
+	if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
+				 pTS->RxIndicateSeq, SeqNum);
+		pHTInfo->RxReorderDropCounter++;
+		{
+			int i;
+			for(i =0; i < prxb->nr_subframes; i++) {
+				dev_kfree_skb(prxb->subframes[i]);
+			}
+			kfree(prxb);
+			prxb = NULL;
+		}
+		spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+		return;
+	}
+
+	/*
+	 * Sliding window manipulation. Conditions includes:
+	 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
+	 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
+	 */
+	if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
+		pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
+		bMatchWinStart = true;
+	} else if(SN_LESS(WinEnd, SeqNum)) {
+		if(SeqNum >= (WinSize - 1)) {
+			pTS->RxIndicateSeq = SeqNum + 1 -WinSize;
+		} else {
+			pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1;
+		}
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
+	}
+
+	/*
+	 * Indication process.
+	 * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
+	 * with the SeqNum smaller than latest WinStart and buffer other packets.
+	 */
+	/* For Rx Reorder condition:
+	 * 1. All packets with SeqNum smaller than WinStart => Indicate
+	 * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
+	 */
+	if(bMatchWinStart) {
+		/* Current packet is going to be indicated.*/
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
+				pTS->RxIndicateSeq, SeqNum);
+		prxbIndicateArray[0] = prxb;
+		index = 1;
+	} else {
+		/* Current packet is going to be inserted into pending list.*/
+		if(!list_empty(&ieee->RxReorder_Unused_List)) {
+			pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
+			list_del_init(&pReorderEntry->List);
+			
+			/* Make a reorder entry and insert into a the packet list.*/
+			pReorderEntry->SeqNum = SeqNum;
+			pReorderEntry->prxb = prxb;
+
+#if 1 
+			if(!AddReorderEntry(pTS, pReorderEntry)) {
+				RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", 
+					__FUNCTION__, pTS->RxIndicateSeq, SeqNum);
+				list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
+				{
+					int i;
+					for(i =0; i < prxb->nr_subframes; i++) {
+						dev_kfree_skb(prxb->subframes[i]);
+					}
+					kfree(prxb);
+					prxb = NULL;
+				}
+			} else {
+				RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+					 "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
+			}
+#endif
+		} 
+		else {
+			/*
+			 * Packets are dropped if there is not enough reorder entries.
+			 * This part shall be modified!! We can just indicate all the 
+			 * packets in buffer and get reorder entries.
+			 */
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
+			{
+				int i;
+				for(i =0; i < prxb->nr_subframes; i++) {
+					dev_kfree_skb(prxb->subframes[i]);
+				}
+				kfree(prxb);
+				prxb = NULL;
+			}
+		}
+	}
+
+	/* Check if there is any packet need indicate.*/
+	while(!list_empty(&pTS->RxPendingPktList)) {
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__);
+#if 1 
+		pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
+		if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) || 
+				SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
+		{
+			/* This protect buffer from overflow. */
+			if(index >= REORDER_WIN_SIZE) {
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n");
+				bPktInBuf = true;
+				break;
+			}
+
+			list_del_init(&pReorderEntry->List);
+
+			if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
+				pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
+
+			prxbIndicateArray[index] = pReorderEntry->prxb;
+			RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum %d!\n",__FUNCTION__, pReorderEntry->SeqNum);
+			index++;
+
+			list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
+		} else {
+			bPktInBuf = true;
+			break;
+		}
+#endif
+	}
+
+	/* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
+	if(index>0) {
+		if(timer_pending(&pTS->RxPktPendingTimer)){
+			del_timer_sync(&pTS->RxPktPendingTimer);
+		}
+		pTS->RxTimeoutIndicateSeq = 0xffff;
+
+		if(index>REORDER_WIN_SIZE){
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
+			spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+			return;
+		}
+		rtllib_indicate_packets(ieee, prxbIndicateArray, index);
+		bPktInBuf = false;
+	}
+
+	if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
+		RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__);
+		pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
+		mod_timer(&pTS->RxPktPendingTimer,  jiffies + MSECS(pHTInfo->RxReorderPendingTime));
+	}
+	spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+}
+
+u8 parse_subframe(struct rtllib_device* ieee,struct sk_buff *skb, 
+                  struct rtllib_rx_stats *rx_stats,
+		  struct rtllib_rxb *rxb,u8* src,u8* dst)
+{
+	struct rtllib_hdr_3addr  *hdr = (struct rtllib_hdr_3addr* )skb->data;
+	u16		fc = le16_to_cpu(hdr->frame_ctl);
+
+	u16		LLCOffset= sizeof(struct rtllib_hdr_3addr);
+	u16		ChkLength;
+	bool		bIsAggregateFrame = false;
+	u16		nSubframe_Length;
+	u8		nPadding_Length = 0;
+	u16		SeqNum=0;
+	struct sk_buff *sub_skb;
+	u8             *data_ptr;	
+	/* just for debug purpose */
+	SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
+	if((RTLLIB_QOS_HAS_SEQ(fc))&&\
+			(((frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved)) {
+		bIsAggregateFrame = true;
+	}
+
+	if(RTLLIB_QOS_HAS_SEQ(fc)) {
+		LLCOffset += 2;
+	}
+	if(rx_stats->bContainHTC) {
+		LLCOffset += sHTCLng;
+	}
+	ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
+
+	if( skb->len <= ChkLength ) {
+		return 0;
+	}
+
+	skb_pull(skb, LLCOffset);
+	ieee->bIsAggregateFrame = bIsAggregateFrame;
+	if(!bIsAggregateFrame) {
+		rxb->nr_subframes = 1;
+#ifndef RTK_DMP_PLATFORM
+#ifdef JOHN_NOCPY
+		rxb->subframes[0] = skb;
+#else
+		rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC);
+#endif
+#else
+		rxb->subframes[0] = skb_clone(skb, GFP_ATOMIC);
+#endif
+		memcpy(rxb->src,src,ETH_ALEN);
+		memcpy(rxb->dst,dst,ETH_ALEN);
+		rxb->subframes[0]->dev = ieee->dev;
+		return 1;
+	} else {
+		rxb->nr_subframes = 0;
+		memcpy(rxb->src,src,ETH_ALEN);
+		memcpy(rxb->dst,dst,ETH_ALEN);
+		while(skb->len > ETHERNET_HEADER_SIZE) {
+			/* Offset 12 denote 2 mac address */
+			nSubframe_Length = *((u16*)(skb->data + 12));
+			nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
+
+			if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
+				printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
+						__FUNCTION__,rxb->nr_subframes);
+				printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length);
+				printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length);
+				printk("The Packet SeqNum is %d\n",SeqNum);
+				return 0;
+			}
+
+			/* move the data point to data content */
+			skb_pull(skb, ETHERNET_HEADER_SIZE);
+
+#ifdef JOHN_NOCPY
+			sub_skb = skb_clone(skb, GFP_ATOMIC);
+			sub_skb->len = nSubframe_Length;
+			sub_skb->tail = sub_skb->data + nSubframe_Length;
+#else
+			/* Allocate new skb for releasing to upper layer */
+			sub_skb = dev_alloc_skb(nSubframe_Length + 12);
+			skb_reserve(sub_skb, 12);
+			data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+			memcpy(data_ptr,skb->data,nSubframe_Length);
+#endif
+			sub_skb->dev = ieee->dev;
+			rxb->subframes[rxb->nr_subframes++] = sub_skb;
+			if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
+				RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
+				break;
+			}
+			skb_pull(skb,nSubframe_Length);
+
+			if(skb->len != 0) {
+				nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4);
+				if(nPadding_Length == 4) {
+					nPadding_Length = 0;
+				}
+
+				if(skb->len < nPadding_Length) {
+					return 0;
+				}
+
+				skb_pull(skb,nPadding_Length);	
+			}			
+		}
+#ifdef JOHN_NOCPY
+		dev_kfree_skb(skb);
+#endif
+		return rxb->nr_subframes;
+	}
+}
+
+
+size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	size_t hdrlen = 0;
+	
+	hdrlen = rtllib_get_hdrlen(fc);
+	if (HTCCheck(ieee, skb->data)) {
+		if(net_ratelimit())
+			printk("%s: find HTCControl!\n", __func__);
+		hdrlen += 4;
+		rx_stats->bContainHTC = 1;
+	} 
+
+	 if(RTLLIB_QOS_HAS_SEQ(fc))
+		rx_stats->bIsQosData = 1;
+
+	return hdrlen;
+}
+
+int rtllib_rx_check_duplicate(struct rtllib_device *ieee, struct sk_buff *skb, u8 multicast)
+{
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	u16 fc, sc;
+	u8 frag, type, stype;
+
+	fc = le16_to_cpu(hdr->frame_ctl);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+	sc = le16_to_cpu(hdr->seq_ctl);
+	frag = WLAN_GET_SEQ_FRAG(sc);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if( (ieee->pHTInfo->bCurRxReorderEnable == false) || 
+		!ieee->current_network.qos_data.active|| 
+		!IsDataFrame(skb->data) || 
+		IsLegacyDataFrame(skb->data) || 
+		multicast) {
+		if (!multicast) {
+			if (is_duplicate_packet(ieee, hdr)){
+				return -1;
+			}
+		}
+	}
+#else
+	if( (ieee->pHTInfo->bCurRxReorderEnable == false) || 
+		!ieee->current_network.qos_data.active || 
+		!IsDataFrame(skb->data) || 
+		IsLegacyDataFrame(skb->data)) {
+		if(!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))){
+			if (is_duplicate_packet(ieee, hdr)){
+				return -1;
+			}
+		}
+	}
+#endif
+	else {
+		PRX_TS_RECORD pRxTS = NULL;
+		if (GetTs(ieee, (PTS_COMMON_INFO*) &pRxTS, hdr->addr2, 
+			(u8)Frame_QoSTID((u8*)(skb->data)), RX_DIR, true)) {
+			if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) && 
+			    (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)) {
+				return -1;
+			} else {
+				pRxTS->RxLastFragNum = frag;
+				pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
+			}
+		} else {
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n",__FUNCTION__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+void rtllib_rx_extract_addr(struct rtllib_device *ieee, struct rtllib_hdr_4addr *hdr, u8 *dst, u8 *src, u8 *bssid)
+{
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	
+	switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
+		case RTLLIB_FCTL_FROMDS:
+			memcpy(dst, hdr->addr1, ETH_ALEN);
+			memcpy(src, hdr->addr3, ETH_ALEN);
+			memcpy(bssid, hdr->addr2, ETH_ALEN);
+			break;
+		case RTLLIB_FCTL_TODS:
+			memcpy(dst, hdr->addr3, ETH_ALEN);
+			memcpy(src, hdr->addr2, ETH_ALEN);
+			memcpy(bssid, hdr->addr1, ETH_ALEN);
+			break;
+		case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
+			memcpy(dst, hdr->addr3, ETH_ALEN);
+			memcpy(src, hdr->addr4, ETH_ALEN);
+#ifdef _RTL8192_EXT_PATCH_
+			memcpy(bssid, ieee->current_mesh_network.bssid, ETH_ALEN);
+#else
+			memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
+#endif
+			break;
+		case 0:
+			memcpy(dst, hdr->addr1, ETH_ALEN);
+			memcpy(src, hdr->addr2, ETH_ALEN);
+			memcpy(bssid, hdr->addr3, ETH_ALEN);
+			break;
+	}
+}
+int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc, u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
+{
+	u8 zero_addr[ETH_ALEN] = {0};
+	u8 type, stype;
+	
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+	
+	/* Filter frames from different BSS */
+	if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS)
+                && (compare_ether_addr(ieee->current_network.bssid, bssid) != 0) 
+                && memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) {
+		return -1;
+	}
+
+	/* Filter packets sent by an STA that will be forwarded by AP */
+	if ( ieee->IntelPromiscuousModeInfo.bPromiscuousOn  &&
+                ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame ) {
+		if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
+			(compare_ether_addr(dst, ieee->current_network.bssid) != 0) &&	   
+			(compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) {   
+			return -1;
+		}
+	}
+
+	/* Nullfunc frames may have PS-bit set, so they must be passed to
+	 * hostap_handle_sta_rx() before being dropped here. */
+	if(!ieee->IntelPromiscuousModeInfo.bPromiscuousOn){
+		if (stype != RTLLIB_STYPE_DATA &&
+		    stype != RTLLIB_STYPE_DATA_CFACK &&
+		    stype != RTLLIB_STYPE_DATA_CFPOLL &&
+		    stype != RTLLIB_STYPE_DATA_CFACKPOLL&&
+		    stype != RTLLIB_STYPE_QOS_DATA
+		    ) {
+			if (stype != RTLLIB_STYPE_NULLFUNC)
+				RTLLIB_DEBUG_DROP(
+					"RX: dropped data frame "
+					"with no data (type=0x%02x, "
+					"subtype=0x%02x)\n",
+					type, stype);
+			return -1;
+		}
+	}
+
+	if(ieee->iw_mode == IW_MODE_MESH) {
+#ifdef _RTL8192_EXT_PATCH_
+		/* check whether it exists the mesh entry for data packet */
+		if(ieee->ext_patch_rtllib_is_mesh&&\
+				(false ==ieee->ext_patch_rtllib_is_mesh(ieee, addr2))) {
+			if(ieee->only_mesh) {
+				return -1;
+			} else if(memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) {   
+				return -1;
+			}
+		} 
+#endif
+	} else {
+		/* packets from our adapter are dropped (echo) */
+		if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN))
+			return -1;
+
+		/* {broad,multi}cast packets to our BSS go through */
+		if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) {
+			if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) {
+				return -1;
+			}
+		}
+	}
+	return 0;
+}
+int rtllib_rx_get_crypt(
+		struct rtllib_device *ieee, 
+		struct sk_buff *skb, 
+		struct rtllib_crypt_data **crypt, 
+		size_t hdrlen)
+{
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	int idx = 0;
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable))
+#else
+	if (ieee->host_decrypt)
+#endif
+	{
+		if (skb->len >= hdrlen + 3)
+			idx = skb->data[hdrlen + 3] >> 6;
+
+#ifdef _RTL8192_EXT_PATCH_
+		*crypt = ieee->sta_crypt[idx];
+#else
+		*crypt = ieee->crypt[idx];
+#endif
+		/* allow NULL decrypt to indicate an station specific override
+		 * for default encryption */
+		if (*crypt && ((*crypt)->ops == NULL ||
+			      (*crypt)->ops->decrypt_mpdu == NULL))
+			*crypt = NULL;
+
+		if (!*crypt && (fc & RTLLIB_FCTL_WEP)) {
+			/* This seems to be triggered by some (multicast?)
+			 * frames from other than current BSS, so just drop the
+			 * frames silently instead of filling system log with
+			 * these reports. */
+			RTLLIB_DEBUG_DROP("Decryption failed (not set)"
+					     " (SA=" MAC_FMT ")\n",
+					     MAC_ARG(hdr->addr2));
+			ieee->ieee_stats.rx_discards_undecryptable++;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+int rtllib_rx_decrypt(
+		struct rtllib_device *ieee, 
+		struct sk_buff *skb, 
+		struct rtllib_rx_stats *rx_stats, 
+		struct rtllib_crypt_data *crypt,
+		size_t hdrlen)
+{
+	struct rtllib_hdr_4addr *hdr;
+	int keyidx = 0;
+	u16 fc, sc;
+	u8 frag;
+
+	hdr = (struct rtllib_hdr_4addr *)skb->data;
+	fc = le16_to_cpu(hdr->frame_ctl);
+	sc = le16_to_cpu(hdr->seq_ctl);
+	frag = WLAN_GET_SEQ_FRAG(sc);
+	
+	if((!rx_stats->Decrypted)){
+		ieee->need_sw_enc = 1;
+	}else{
+		ieee->need_sw_enc = 0;
+	}
+
+	if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
+	    ((keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt)) < 0) 
+#if defined (RTL8192S_WAPI_SUPPORT)
+	    && (!ieee->wapiInfo.bWapiEnable)
+#endif
+	    )
+	{
+		printk("%s: decrypt frame error\n", __func__);
+		return -1;
+	}
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if(ieee->wapiInfo.bWapiEnable){
+		if(ieee->pairwise_key_type == KEY_TYPE_SMS4){
+			if(false == SecSWSMS4Decryption(ieee, skb, rx_stats)){
+				WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__func__);
+				return -1;
+			}
+		}
+	}
+#endif
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) {
+		int flen;
+		struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr);
+		RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
+
+		if (!frag_skb) {
+			RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG,
+					"Rx cannot get skb from fragment "
+					"cache (morefrag=%d seq=%u frag=%u)\n",
+					(fc & RTLLIB_FCTL_MOREFRAGS) != 0,
+					WLAN_GET_SEQ_SEQ(sc), frag);
+			return -1;
+		}
+		flen = skb->len;
+		if (frag != 0)
+			flen -= hdrlen;
+
+		if (frag_skb->tail + flen > frag_skb->end) {
+			printk(KERN_WARNING "%s: host decrypted and "
+			       "reassembled frame did not fit skb\n",
+			       __func__);
+			rtllib_frag_cache_invalidate(ieee, hdr);
+			return -1;
+		}
+
+		if (frag == 0) {
+			/* copy first fragment (including full headers) into
+			 * beginning of the fragment cache skb */
+			memcpy(skb_put(frag_skb, flen), skb->data, flen);
+		} else {
+			/* append frame payload to the end of the fragment
+			 * cache skb */
+			memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+			       flen);
+		}
+		dev_kfree_skb_any(skb);
+		skb = NULL;
+
+		if (fc & RTLLIB_FCTL_MOREFRAGS) {
+			/* more fragments expected - leave the skb in fragment
+			 * cache for now; it will be delivered to upper layers
+			 * after all fragments have been received */
+			return -2;
+		}
+
+		/* this was the last fragment and the frame will be
+		 * delivered, so remove skb from fragment cache */
+		skb = frag_skb;
+		hdr = (struct rtllib_hdr_4addr *) skb->data;
+		rtllib_frag_cache_invalidate(ieee, hdr);
+	}
+
+	/* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+	 * encrypted/authenticated */
+	if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && 
+#if defined (RTL8192S_WAPI_SUPPORT)
+		(!ieee->wapiInfo.bWapiEnable) &&
+#endif		
+	    	rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
+	{
+		printk("%s: ==>decrypt msdu error\n", __func__);
+		return -1;
+	}
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) {
+		if (/*ieee->ieee802_1x &&*/
+		    rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+
+#ifdef CONFIG_RTLLIB_DEBUG
+			/* pass unencrypted EAPOL frames even if encryption is
+			 * configured */
+			struct eapol *eap = (struct eapol *)(skb->data +
+				24);
+			RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+						eap_get_type(eap->type));
+#endif
+		} else {
+			RTLLIB_DEBUG_DROP(
+				"encryption configured, but RX "
+				"frame not encrypted (SA=" MAC_FMT ")\n",
+				MAC_ARG(hdr->addr2));
+			return -1;
+		}
+	} 
+
+#ifdef CONFIG_RTLLIB_DEBUG
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) &&
+	    rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+			struct eapol *eap = (struct eapol *)(skb->data +
+				24);
+			RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+						eap_get_type(eap->type));
+	}
+#endif
+
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep &&
+	    !rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+		RTLLIB_DEBUG_DROP(
+			"dropped unencrypted RX data "
+			"frame from " MAC_FMT
+			" (drop_unencrypted=1)\n",
+			MAC_ARG(hdr->addr2));
+		return -1;
+	}
+
+	if(rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+		printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
+	}
+
+	return 0;
+}
+void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes)
+{
+#if !defined(RTL8192SU) && !defined(RTL8192U) 
+#ifdef ENABLE_LPS
+	if(unicast){
+		ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes;
+		
+		if((ieee->state == RTLLIB_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+		{
+			if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+				(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+			{
+				if(ieee->LeisurePSLeave)
+					ieee->LeisurePSLeave(ieee->dev);
+			}
+		}
+	}	
+#endif
+#endif
+	ieee->last_rx_ps_time = jiffies;
+}
+void rtllib_rx_indicate_pkt_legacy(
+		struct rtllib_device *ieee, 
+		struct rtllib_rx_stats *rx_stats, 
+		struct rtllib_rxb* rxb, 
+		u8 *dst, 
+		u8 *src)
+{
+#ifndef _RTL8192_EXT_PATCH_
+	struct net_device *dev = ieee->dev;
+#endif
+	u16 ethertype;
+	int i = 0;
+
+	if(rxb == NULL){
+		printk("%s: rxb is NULL!!\n", __func__);
+		return ;
+	}
+	
+	for(i = 0; i<rxb->nr_subframes; i++) {
+		struct sk_buff *sub_skb = rxb->subframes[i];
+
+		if (sub_skb) {
+			/* convert hdr + possible LLC headers into Ethernet header */
+			ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
+			if (sub_skb->len >= 8 &&
+					((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
+					  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+					 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+				/* remove RFC1042 or Bridge-Tunnel encapsulation and
+				 * replace EtherType */
+				skb_pull(sub_skb, SNAP_SIZE);
+				memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+				memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+			} else {
+				u16 len;
+				/* Leave Ethernet header part of hdr and full payload */
+				len = htons(sub_skb->len);
+				memcpy(skb_push(sub_skb, 2), &len, 2);
+				memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+				memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+			}
+
+			ieee->stats.rx_packets++;
+			ieee->stats.rx_bytes += sub_skb->len;
+
+			if(is_multicast_ether_addr(dst)) {
+				ieee->stats.multicast++;
+			}
+
+			/* Indicat the packets to upper layer */
+			memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
+#ifdef _RTL8192_EXT_PATCH_
+			sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev);
+#else
+			sub_skb->protocol = eth_type_trans(sub_skb, dev);
+			sub_skb->dev = dev;
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+			sub_skb->dev->stats.rx_packets++;
+			sub_skb->dev->stats.rx_bytes += sub_skb->len;	
+#endif
+#ifdef TCP_CSUM_OFFLOAD_RX
+			if ( rx_stats->tcp_csum_valid)
+				sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				sub_skb->ip_summed = CHECKSUM_NONE;
+#else
+			sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+#endif				
+			netif_rx(sub_skb);
+		}
+	}
+	kfree(rxb);
+	rxb = NULL;
+}
+int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	struct net_device *dev = ieee->dev;
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	struct rtllib_crypt_data *crypt = NULL;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	struct sta_info * psta = NULL;
+#endif
+	struct rtllib_rxb* rxb = NULL;
+	PRX_TS_RECORD pTS = NULL;
+	u16 fc, sc, SeqNum = 0;
+	u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0;
+	u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload;
+	size_t hdrlen = 0;
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8 wapiDectResult = 0;
+#endif
+	bool bToOtherSTA = false;
+	int ret = 0, i = 0;
+
+	hdr = (struct rtllib_hdr_4addr *)skb->data;
+	fc = le16_to_cpu(hdr->frame_ctl);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+	sc = le16_to_cpu(hdr->seq_ctl);
+
+	/*Filter pkt not to me*/
+	multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1);
+	unicast = !multicast;
+	if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
+		if(ieee->bNetPromiscuousMode)
+			bToOtherSTA = true;
+		else
+			goto rx_dropped;
+	}
+	
+	/*Filter pkt has too small length */
+	hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
+	if(skb->len < hdrlen){
+		printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__);
+		goto rx_dropped;
+	}
+
+	/* Filter Duplicate pkt */
+	ret = rtllib_rx_check_duplicate(ieee, skb, multicast);
+	if(ret < 0)
+		goto rx_dropped;
+	
+	/* Filter CTRL Frame */
+	if (type == RTLLIB_FTYPE_CTL) {
+		goto rx_dropped;
+	}
+
+	/* Filter MGNT Frame */
+	if (type == RTLLIB_FTYPE_MGMT) {
+		if(bToOtherSTA)
+			goto rx_dropped;
+		if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
+			goto rx_dropped;
+		else
+			goto rx_exit;
+	}
+
+	/* Filter WAPI DATA Frame */
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){
+		wapiDectResult = SecIsWAIPacket(ieee, skb);
+		if(wapiDectResult !=0){
+			if(memcmp(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2))
+				WapiHandleRecvPacket(ieee, skb, wapiDectResult);
+			memcpy(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2);
+			dev_kfree_skb_any(skb);
+			goto rx_exit;
+		}
+	}
+#endif	
+
+	/* Update statstics for AP roaming */
+	if(!bToOtherSTA){
+		ieee->LinkDetectInfo.NumRecvDataInPeriod++;
+		ieee->LinkDetectInfo.NumRxOkInPeriod++;
+	}
+	dev->last_rx = jiffies;
+	
+	/* Data frame - extract src/dst addresses */
+	rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid);
+
+	/* Filter Data frames */
+	ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2);
+	if(ret < 0)
+		goto rx_dropped;
+
+	if(skb->len == hdrlen){
+		goto rx_dropped;
+	}
+
+	/* Send pspoll based on moredata */
+#ifdef ENABLE_LPS
+	if ((ieee->iw_mode == IW_MODE_INFRA)  && (ieee->sta_sleep == 1) 
+		&& (ieee->polling) && (!bToOtherSTA)) {
+		if (WLAN_FC_MORE_DATA(fc)) {
+			/* more data bit is set, let's request a new frame from the AP */
+			rtllib_sta_ps_send_pspoll_frame(ieee);
+		} else {
+			ieee->polling =  false;
+		}
+	}
+#endif
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(ieee->iw_mode == IW_MODE_ADHOC){
+		psta = GetStaInfo(ieee, src);
+		if(NULL != psta)
+			psta->LastActiveTime = jiffies;
+	}
+#endif
+
+	/* Get crypt if encrypted */
+	ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen);
+	if(ret == -1)
+		goto rx_dropped;
+
+	/* Decrypt data frame (including reassemble) */
+	ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen);
+	if(ret == -1)
+		goto rx_dropped;
+	else if(ret == -2)
+		goto rx_exit;
+
+	/* Get TS for Rx Reorder  */
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) 
+		&& !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1) 
+		&& (!bToOtherSTA))
+	{
+		TID = Frame_QoSTID(skb->data);
+		SeqNum = WLAN_GET_SEQ_SEQ(sc);
+		GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
+		if(TID !=0 && TID !=3){
+			ieee->bis_any_nonbepkts = true;
+		}
+	}
+
+	/* Parse rx data frame (For AMSDU) */
+	/* skb: hdr + (possible reassembled) full plaintext payload */
+	payload = skb->data + hdrlen;
+	rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC);
+	if(rxb == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__);
+		goto rx_dropped;
+	}
+	/* to parse amsdu packets */
+	/* qos data packets & reserved bit is 1 */
+	if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) {
+		/* only to free rxb, and not submit the packets to upper layer */
+		for(i =0; i < rxb->nr_subframes; i++) {
+			dev_kfree_skb(rxb->subframes[i]);
+		}
+		kfree(rxb);
+		rxb = NULL;
+		goto rx_dropped;
+	}
+
+	/* Update WAPI PN */
+#ifdef RTL8192S_WAPI_SUPPORT
+	if(ieee->wapiInfo.bWapiEnable){
+		if(rxb){
+			rxb->UserPriority = TID;
+			memcpy(rxb->WapiTempPN, rx_stats->WapiTempPN, 16);
+			memcpy(rxb->WapiSrcAddr, rx_stats->WapiSrcAddr, 6);
+			rxb->bWapiCheckPNInDecrypt = rx_stats->bWapiCheckPNInDecrypt;
+		}
+	}
+#endif
+
+	/* Check if leave LPS */
+	if(!bToOtherSTA){
+		if(ieee->bIsAggregateFrame)
+			nr_subframes = rxb->nr_subframes;
+		else
+			nr_subframes = 1;
+		rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes);
+	}
+	
+	/* Indicate packets to upper layer or Rx Reorder */
+	if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL || bToOtherSTA){
+		rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src);
+	}else{
+#ifdef TCP_CSUM_OFFLOAD_RX
+		rxb->tcp_csum_valid = rx_stats->tcp_csum_valid;
+#endif		
+		RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
+	}
+
+#ifndef JOHN_NOCPY
+	dev_kfree_skb(skb);
+#endif
+
+ rx_exit:
+	return 1;
+
+ rx_dropped:
+	if (rxb != NULL)
+	{
+		kfree(rxb);
+		rxb = NULL;
+	}		
+	ieee->stats.rx_dropped++;
+
+	/* Returning 0 indicates to caller that we have not handled the SKB--
+	 * so it is still allocated and can be used again by underlying
+	 * hardware as a DMA target */
+	return 0;
+}
+
+int rtllib_rx_Master(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	return 0;
+}
+int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	size_t hdrlen = rtllib_get_hdrlen(fc);
+	
+	if(skb->len < hdrlen){
+		printk("%s():ERR!!! skb->len is smaller than hdrlen\n", __func__);
+		return 0;
+	}
+	
+	if (HTCCheck(ieee, skb->data)) {
+		if(net_ratelimit())
+			printk("%s: Find HTCControl!\n", __func__);
+		hdrlen += 4;
+	} 
+
+#if WIRELESS_EXT > 15
+	rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen);
+	ieee->stats.rx_packets++;
+	ieee->stats.rx_bytes += skb->len;
+#endif
+	return 1;
+}
+#ifdef _RTL8192_EXT_PATCH_
+extern u8 msh_parse_subframe(struct rtllib_device *ieee,struct sk_buff *skb, struct rtllib_rxb *rxb);
+extern int msh_rx_process_dataframe(struct rtllib_device *ieee, struct rtllib_rxb *rxb, struct rtllib_rx_stats *rx_stats);
+int rtllib_rx_get_mesh_crypt(
+		struct rtllib_device *ieee, 
+		struct sk_buff *skb, 
+		struct rtllib_crypt_data **crypt, 
+		size_t hdrlen)
+{
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	u16 fc = le16_to_cpu(hdr->frame_ctl);
+	int idx = 0, i;
+	u8 find_crypt = false;
+	
+	if (ieee->host_decrypt){
+		if (skb->len >= hdrlen + 3)
+			idx = skb->data[hdrlen + 3] >> 6;
+		if (ieee->mesh_sec_type == 1) { 
+			if(ieee->mesh_security_setting==1 ||ieee->mesh_security_setting==3){
+				i = rtllib_find_MP(ieee, hdr->addr2, 0);
+				if(is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){
+					if(ieee->only_mesh){
+						if(i != -1){
+							i=0;
+						}else{
+							printk("%s: Err find MP ("MAC_FMT")!SAE, Multicast and only mesh\n", __func__, MAC_ARG(hdr->addr2));
+							return -1;
+						}
+					}else{
+						if(i != -1){
+							i=0;
+						}else{
+							find_crypt = true;
+							*crypt = ieee->sta_crypt[idx];
+						}
+					}
+				}else{
+					if(ieee->only_mesh){
+						if (i == -1){
+							printk("%s: Err find MP ("MAC_FMT")!SAE, Unicast and only mesh\n", __func__, MAC_ARG(hdr->addr2));
+							return -1;
+						}
+					}else{
+						if (i == -1){
+							find_crypt = true;
+							*crypt = ieee->sta_crypt[idx];
+						}
+					}
+				}
+				if(find_crypt == false){  
+					if(ieee->cryptlist[i] == NULL)
+						return -1;
+					else
+						*crypt = ieee->cryptlist[i]->crypt[idx];
+				}
+			}
+		}
+		else {
+			*crypt = ieee->cryptlist[0]->crypt[idx];
+			if(*crypt){
+				int i = rtllib_find_MP(ieee, hdr->addr2, 0);
+				if(ieee->only_mesh){
+					if (i == -1){
+						printk("%s: Err find MP ("MAC_FMT")!Not SAE, Only mesh.\n", __func__, MAC_ARG(hdr->addr2));
+						return -1;
+					}
+					if (ieee->cryptlist[i] && ieee->cryptlist[i]->crypt[idx])
+						*crypt = ieee->cryptlist[i]->crypt[idx];
+					else{
+						*crypt = NULL;
+						printk("%s: Err find crypt!Not SAE, Only mesh.\n", __func__);
+						return -1;
+					}
+				}else{
+					if(i != -1)
+					{
+						if (ieee->cryptlist[i] && ieee->cryptlist[i]->crypt[idx])
+							*crypt = ieee->cryptlist[i]->crypt[idx];
+						else{
+							*crypt = NULL;
+							printk("%s: Err find crypt!Not SAE, Only mesh.\n", __func__);
+							return -1;
+						}
+					}
+					else
+						*crypt = ieee->sta_crypt[idx];
+				}
+			}
+			else{
+				if(!ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2))	
+					*crypt = ieee->sta_crypt[idx];
+			}
+		}
+
+		/* allow NULL decrypt to indicate an station specific override
+		 * for default encryption */
+		if (*crypt && ((*crypt)->ops == NULL ||
+			      (*crypt)->ops->decrypt_mpdu == NULL))
+			*crypt = NULL;
+
+		if (!*crypt && (fc & RTLLIB_FCTL_WEP)) {
+			/* This seems to be triggered by some (multicast?)
+			 * frames from other than current BSS, so just drop the
+			 * frames silently instead of filling system log with
+			 * these reports. */
+			RTLLIB_DEBUG_DROP("Decryption failed (not set)"
+					     " (SA=" MAC_FMT ")\n",
+					     MAC_ARG(hdr->addr2));
+			ieee->ieee_stats.rx_discards_undecryptable++;
+			return -1;
+		}
+	}
+	return 0;
+}
+#endif
+
+int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+#ifdef _RTL8192_EXT_PATCH_
+	struct net_device *dev = ieee->dev;
+	struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+	struct rtllib_crypt_data *crypt = NULL;
+	struct rtllib_rxb* rxb = NULL;
+	PRX_TS_RECORD pTS = NULL;
+	u16 fc, sc, SeqNum = 0;
+	u8 type, stype, multicast = 0, unicast = 0, TID = 0;
+	u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload;
+	size_t hdrlen = 0;
+	int ret = 0, i = 0;
+
+	hdr = (struct rtllib_hdr_4addr *)skb->data;
+	fc = le16_to_cpu(hdr->frame_ctl);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+	sc = le16_to_cpu(hdr->seq_ctl);
+
+	/*Filter pkt not to me*/
+	multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1);
+	unicast = !multicast;
+	if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
+		goto rx_dropped;
+	}
+	
+	/*Filter pkt has too small length */
+	hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
+	if(skb->len < hdrlen){
+		printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__);
+		goto rx_dropped;
+	}
+
+	/* Filter Duplicate pkt */
+	ret = rtllib_rx_check_duplicate(ieee, skb, multicast);
+	if(ret < 0){
+		goto rx_dropped;
+	}
+
+	/* Update PeerMP expire time */
+	if(ieee->ext_patch_rtllib_rx_mgt_update_expire)
+		ieee->ext_patch_rtllib_rx_mgt_update_expire( ieee, skb );
+
+	/* Filter CTRL Frame */
+	if (type == RTLLIB_FTYPE_CTL) {
+		goto rx_dropped;
+	}
+
+	/* Filter MGNT Frame */
+	if (type == RTLLIB_FTYPE_MGMT) {
+		if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)){
+			printk("%s: Mgnt Frame! ret!=0\n", __func__);
+			goto rx_dropped;
+		}
+		else
+			goto rx_exit;
+	}
+
+	/* Update statstics for AP roaming */
+	if(ieee->only_mesh == 0){
+		ieee->LinkDetectInfo.NumRecvDataInPeriod++;
+		ieee->LinkDetectInfo.NumRxOkInPeriod++;
+		dev->last_rx = jiffies;
+	}
+	
+	/* Data frame - extract src/dst addresses */
+	rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid);
+
+	/* Filter Data frames */
+	ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2);
+	if(ret < 0){
+		goto rx_dropped;
+	}
+	if(skb->len == hdrlen){
+		goto rx_dropped;
+	}
+
+	/* Get crypt if encrypted */
+	ret = rtllib_rx_get_mesh_crypt(ieee, skb, &crypt, hdrlen);
+	if(ret == -1)
+		goto rx_dropped;
+
+	/* Decrypt data frame (including reassemble) */
+	ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen);
+	if(ret == -1)
+		goto rx_dropped;
+	else if(ret == -2)
+		goto rx_exit;
+
+	/* Get TS for Rx Reorder  */
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) 
+		&& !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
+	{
+		TID = Frame_QoSTID(skb->data);
+		SeqNum = WLAN_GET_SEQ_SEQ(sc);
+		GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
+		if(TID !=0 && TID !=3){
+			ieee->bis_any_nonbepkts = true;
+		}
+	}
+
+	/* Parse rx data frame */
+	if((fc & (WIFI_MESH_TYPE | RTLLIB_FCTL_DSTODS))
+		== (WIFI_MESH_TYPE | RTLLIB_FCTL_DSTODS))
+	{
+		/* Parse Mesh data frame */
+		rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC);
+		if(rxb == NULL)
+		{
+			printk("%s(): kmalloc rxb error\n", __func__);
+			goto rx_dropped;
+		}
+		memset(rxb, 0, sizeof(struct rtllib_rxb));
+		if(msh_parse_subframe(ieee, skb, rxb)==0){
+			/* only to free rxb, and not submit the packets to upper layer */
+			for(i =0; i < rxb->nr_subframes; i++) {
+				if(rxb->subframes[i])
+					dev_kfree_skb(rxb->subframes[i]);
+			}
+			kfree(rxb);
+			rxb = NULL;
+			goto rx_dropped;
+		}
+		ret = msh_rx_process_dataframe(ieee,rxb,rx_stats);
+		if(ret < 0) {
+			for(i =0; i < rxb->nr_subframes; i++) {
+				if(rxb->subframes[i])
+					dev_kfree_skb(rxb->subframes[i]);
+			}
+			kfree(rxb);
+			rxb = NULL;
+			goto rx_dropped;
+		}else{
+			kfree(rxb);
+			rxb = NULL;
+		}
+	}
+	else{
+		/* Parse INFRA data frame (Server Ra0 mode) */
+		/* skb: hdr + (possible reassembled) full plaintext payload */
+		payload = skb->data + hdrlen;
+		rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC);
+		if(rxb == NULL)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n", __func__);
+			goto rx_dropped;
+		}
+		/* to parse amsdu packets */
+		/* qos data packets & reserved bit is 1 */
+		if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) {
+			/* only to free rxb, and not submit the packets to upper layer */
+			for(i =0; i < rxb->nr_subframes; i++) {
+				dev_kfree_skb(rxb->subframes[i]);
+			}
+			kfree(rxb);
+			rxb = NULL;
+			goto rx_dropped;
+		}
+
+		/* Indicate packets to upper layer or Rx Reorder */
+		if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
+			rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src);
+		}else{
+			RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__);		
+#ifdef TCP_CSUM_OFFLOAD_RX
+			rxb->tcp_csum_valid = rx_stats->tcp_csum_valid;
+#endif		
+			RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
+		}
+	}
+#ifndef JOHN_NOCPY
+	dev_kfree_skb(skb);
+#endif
+
+ rx_exit:
+	return 1;
+
+ rx_dropped:
+	if (rxb != NULL)
+	{
+		kfree(rxb);
+		rxb = NULL;
+	}		
+	ieee->stats.rx_dropped++;
+
+	/* Returning 0 indicates to caller that we have not handled the SKB--
+	 * so it is still allocated and can be used again by underlying
+	 * hardware as a DMA target */
+#endif
+	return 0;
+}
+
+#if 1
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ). */
+int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	int ret = 0;
+
+	if((NULL==ieee) || (NULL==skb) || (NULL==rx_stats)){
+		printk(KERN_INFO "%s: Input parameters NULL!\n", __func__);
+		goto rx_dropped;
+	}
+	if (skb->len < 10) {
+		printk(KERN_INFO "%s: SKB length < 10 \n", __func__);
+		goto rx_dropped;
+	}
+
+	switch(ieee->iw_mode){
+		case IW_MODE_ADHOC:
+		case IW_MODE_INFRA:
+			ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats);
+			break;
+		case IW_MODE_MASTER:
+		case IW_MODE_REPEAT:	
+			ret = rtllib_rx_Master(ieee, skb, rx_stats);
+			break;
+		case IW_MODE_MONITOR:
+			ret = rtllib_rx_Monitor(ieee, skb, rx_stats);
+			break;
+		case IW_MODE_MESH:
+			ret = rtllib_rx_Mesh(ieee, skb, rx_stats);
+			break;
+		default:
+			printk(KERN_INFO"%s: ERR iw mode!!!\n", __func__);
+			break;
+	}
+
+	return ret;	
+	
+ rx_dropped:
+	ieee->stats.rx_dropped++;
+	return 0;
+}
+#else
+int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+		 struct rtllib_rx_stats *rx_stats)
+{
+	struct net_device *dev = ieee->dev;
+	struct rtllib_hdr_4addr *hdr;
+	size_t hdrlen;
+	u16 fc, type, stype, sc;
+	struct net_device_stats *stats = NULL;
+	unsigned int frag;
+	u8 *payload;
+	u16 ethertype;
+	u8	TID = 0;
+	u16	SeqNum = 0;
+	PRX_TS_RECORD pTS = NULL;
+#ifdef NOT_YET
+	struct net_device *wds = NULL;
+	struct sk_buff *skb2 = NULL;
+	struct net_device *wds = NULL;
+	int frame_authorized = 0;
+	int from_assoc_ap = 0;
+	void *sta = NULL;
+#endif
+	u8 dst[ETH_ALEN];
+	u8 src[ETH_ALEN];
+	u8 bssid[ETH_ALEN] = {0};
+	u8 zero_addr[ETH_ALEN] = {0};
+	struct rtllib_crypt_data *crypt = NULL;
+	int keyidx = 0;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	struct sta_info * psta = NULL;
+#endif
+	bool unicast_packet = false;
+	int i;
+	struct rtllib_rxb* rxb = NULL;
+	int multicast = 0;
+	bool tmp_dump = false;
+#if defined _RTL8192_EXT_PATCH_ 
+	int ret = 0;
+#endif
+	bool bToOtherSTA = false;
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8	wapiDectResult = 0;
+#endif
+	hdr = (struct rtllib_hdr_4addr *)skb->data;
+	stats = &ieee->stats;
+
+	multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1);
+	if (!multicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
+		if ((ieee->iw_mode == IW_MODE_MONITOR) || ieee->bNetPromiscuousMode){
+			bToOtherSTA = true;
+		}else{
+			goto rx_dropped;
+		}
+	}
+
+	fc = le16_to_cpu(hdr->frame_ctl);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+	sc = le16_to_cpu(hdr->seq_ctl);
+	frag = WLAN_GET_SEQ_FRAG(sc);
+
+	ieee->need_sw_enc = 0;
+
+	hdrlen = rtllib_get_hdrlen(fc);
+	if(skb->len < hdrlen){
+		printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__);
+		goto rx_dropped;
+	}
+	
+	if (HTCCheck(ieee, skb->data)) {
+		if(net_ratelimit())
+			printk("find HTCControl\n");
+		hdrlen += 4;
+		rx_stats->bContainHTC = 1;
+	} 
+ 	if(RTLLIB_QOS_HAS_SEQ(fc))
+		rx_stats->bIsQosData = 1;
+  	if ((0) && (type == RTLLIB_FTYPE_DATA) && ((is_broadcast_ether_addr(hdr->addr1)) || (compare_ether_addr(dev->dev_addr, hdr->addr1) == 0))) {
+		printk("===>RX data before decrypt\n"); 
+		tmp_dump = true;
+		dump_buf(skb->data,skb->len);
+	}
+#ifdef NOT_YET
+	hostap_update_rx_stats(local->ap, hdr, rx_stats);
+#endif
+
+#ifndef _RTL8192_EXT_PATCH_
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable))
+#else
+	if (ieee->host_decrypt)
+#endif
+	{
+		int idx = 0;
+		if (skb->len >= hdrlen + 3)
+			idx = skb->data[hdrlen + 3] >> 6;
+		crypt = ieee->crypt[idx];
+#ifdef NOT_YET
+		sta = NULL;
+
+		/* Use station specific key to override default keys if the
+		 * receiver address is a unicast address ("individual RA"). If
+		 * bcrx_sta_key parameter is set, station specific key is used
+		 * even with broad/multicast targets (this is against IEEE
+		 * 802.11, but makes it easier to use different keys with
+		 * stations that do not support WEP key mapping). */
+
+		if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+			(void) hostap_handle_sta_crypto(local, hdr, &crypt,
+							&sta);
+#endif
+
+		/* allow NULL decrypt to indicate an station specific override
+		 * for default encryption */
+		if (crypt && (crypt->ops == NULL ||
+			      crypt->ops->decrypt_mpdu == NULL))
+			crypt = NULL;
+
+		if (!crypt && (fc & RTLLIB_FCTL_WEP)) {
+			/* This seems to be triggered by some (multicast?)
+			 * frames from other than current BSS, so just drop the
+			 * frames silently instead of filling system log with
+			 * these reports. */
+			RTLLIB_DEBUG_DROP("Decryption failed (not set)"
+					     " (SA=" MAC_FMT ")\n",
+					     MAC_ARG(hdr->addr2));
+			ieee->ieee_stats.rx_discards_undecryptable++;
+			goto rx_dropped;
+		}
+	}
+#endif
+
+	if (skb->len < RTLLIB_DATA_HDR3_LEN)
+		goto rx_dropped;
+
+#ifdef _RTL8192_EXT_PATCH_
+	if( (ieee->pHTInfo->bCurRxReorderEnable == false) || 
+		!ieee->current_network.qos_data.active|| 
+		!IsDataFrame(skb->data) || 
+		IsLegacyDataFrame(skb->data) || 
+		multicast) {
+		if (!multicast) {
+			if (is_duplicate_packet(ieee, hdr)){
+				goto rx_dropped;
+			}
+		}
+	}
+#else
+	if( (ieee->pHTInfo->bCurRxReorderEnable == false) || 
+		!ieee->current_network.qos_data.active || 
+		!IsDataFrame(skb->data) || 
+		IsLegacyDataFrame(skb->data)) {
+		if(!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))){
+			if (is_duplicate_packet(ieee, hdr)){
+				goto rx_dropped;
+			}
+		}
+	}
+#endif
+	else {
+		PRX_TS_RECORD pRxTS = NULL;
+		if (GetTs(ieee, (PTS_COMMON_INFO*) &pRxTS, hdr->addr2, 
+			(u8)Frame_QoSTID((u8*)(skb->data)), RX_DIR, true)) {
+			if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) && 
+			    (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)) {
+				goto rx_dropped;
+			} else {
+				pRxTS->RxLastFragNum = frag;
+				pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
+			}
+		} else {
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n",__FUNCTION__);
+			goto rx_dropped;
+		}
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_mgt_update_expire)
+		ieee->ext_patch_rtllib_rx_mgt_update_expire( ieee, skb );
+#endif
+	if (type == RTLLIB_FTYPE_MGMT) {
+		if (bToOtherSTA){
+			goto rx_dropped;
+		}		
+		if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
+			goto rx_dropped;
+		else
+			goto rx_exit;
+	}
+	if (type == RTLLIB_FTYPE_CTL) {
+		goto rx_dropped;
+	}
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){
+		wapiDectResult = SecIsWAIPacket(ieee, skb);
+		if(wapiDectResult !=0){
+			if(memcmp(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2))
+				WapiHandleRecvPacket(ieee, skb, wapiDectResult);
+			memcpy(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2);
+			dev_kfree_skb_any(skb);
+			goto rx_exit;
+		}
+	}
+#endif	
+	/* Data frame - extract src/dst addresses */
+	switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
+	case RTLLIB_FCTL_FROMDS:
+		memcpy(dst, hdr->addr1, ETH_ALEN);
+		memcpy(src, hdr->addr3, ETH_ALEN);
+		memcpy(bssid, hdr->addr2, ETH_ALEN);
+		break;
+	case RTLLIB_FCTL_TODS:
+		memcpy(dst, hdr->addr3, ETH_ALEN);
+		memcpy(src, hdr->addr2, ETH_ALEN);
+		memcpy(bssid, hdr->addr1, ETH_ALEN);
+		break;
+	case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
+		if (skb->len < RTLLIB_DATA_HDR4_LEN)
+			goto rx_dropped;
+		memcpy(dst, hdr->addr3, ETH_ALEN);
+		memcpy(src, hdr->addr4, ETH_ALEN);
+#ifdef _RTL8192_EXT_PATCH_
+		memcpy(bssid, ieee->current_mesh_network.bssid, ETH_ALEN);
+#else
+		memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
+#endif
+		break;
+	case 0:
+		memcpy(dst, hdr->addr1, ETH_ALEN);
+		memcpy(src, hdr->addr2, ETH_ALEN);
+		memcpy(bssid, hdr->addr3, ETH_ALEN);
+		break;
+	}
+
+	/* Filter frames from different BSS */
+	if ((type != RTLLIB_FTYPE_CTL) && ((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS)
+                && (compare_ether_addr(ieee->current_network.bssid, bssid) != 0) && memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) {
+		goto rx_dropped;
+	}
+
+	/* Filter packets sent by an STA that will be forwarded by AP */
+	if ( ieee->IntelPromiscuousModeInfo.bPromiscuousOn  &&
+                ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame ) {
+		if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
+			(compare_ether_addr(dst, ieee->current_network.bssid) != 0) &&	   
+			(compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) {   
+			goto rx_dropped;
+		}
+	}
+
+#ifdef NOT_YET
+	if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
+		goto rx_dropped;
+	if (wds) {
+		skb->dev = dev = wds;
+		stats = hostap_get_stats(dev);
+	}
+
+	if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
+	    (fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == RTLLIB_FCTL_FROMDS &&
+	    ieee->stadev &&
+	    memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
+		/* Frame from BSSID of the AP for which we are a client */
+		skb->dev = dev = ieee->stadev;
+		stats = hostap_get_stats(dev);
+		from_assoc_ap = 1;
+	}
+#endif
+
+	dev->last_rx = jiffies;
+
+#ifdef NOT_YET
+	if ((ieee->iw_mode == IW_MODE_MASTER ||
+	     ieee->iw_mode == IW_MODE_REPEAT) &&
+	    !from_assoc_ap) {
+		switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
+					     wds != NULL)) {
+		case AP_RX_CONTINUE_NOT_AUTHORIZED:
+			frame_authorized = 0;
+			break;
+		case AP_RX_CONTINUE:
+			frame_authorized = 1;
+			break;
+		case AP_RX_DROP:
+			goto rx_dropped;
+		case AP_RX_EXIT:
+			goto rx_exit;
+		}
+	}
+#endif
+	/* Nullfunc frames may have PS-bit set, so they must be passed to
+	 * hostap_handle_sta_rx() before being dropped here. */
+	if (stype != RTLLIB_STYPE_DATA &&
+	    stype != RTLLIB_STYPE_DATA_CFACK &&
+	    stype != RTLLIB_STYPE_DATA_CFPOLL &&
+	    stype != RTLLIB_STYPE_DATA_CFACKPOLL&&
+	    stype != RTLLIB_STYPE_QOS_DATA
+	    ) {
+		if (stype != RTLLIB_STYPE_NULLFUNC)
+			RTLLIB_DEBUG_DROP(
+				"RX: dropped data frame "
+				"with no data (type=0x%02x, "
+				"subtype=0x%02x, len=%d)\n",
+				type, stype, skb->len);
+		goto rx_dropped;
+	}
+
+	if(skb->len == hdrlen){
+		goto rx_dropped;
+	}
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if(ieee->iw_mode == IW_MODE_MESH) {
+		/* check whether it exists the mesh entry for data packet */
+		if(ieee->ext_patch_rtllib_is_mesh&&\
+				(false ==ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2))) {
+			if(ieee->only_mesh) {
+				goto rx_dropped;
+			} else if(memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) {   
+				goto rx_dropped;
+			}
+		} 
+	} else
+#endif
+	{
+#if 0		
+		/* check bssid under none mesh mode */
+		if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) {
+			goto rx_dropped;
+		}
+#endif
+		/* network filter more precisely */
+		switch (ieee->iw_mode) {
+			case IW_MODE_ADHOC:
+				/* packets from our adapter are dropped (echo) */
+				if (!memcmp(hdr->addr2, dev->dev_addr, ETH_ALEN))
+					goto rx_dropped;
+
+				/* {broad,multi}cast packets to our BSSID go through */
+				if (is_multicast_ether_addr(hdr->addr1)) {
+					if(!memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))
+						break;
+					else
+						goto rx_dropped;
+				} 
+
+				/* packets not to our adapter, just discard it */
+				if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+					if (bToOtherSTA)
+						break;
+					else	 
+						goto rx_dropped;
+				}
+
+				break;
+
+			case IW_MODE_INFRA:     
+				/* packets from our adapter are dropped (echo) */
+				if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
+					goto rx_dropped;
+
+				/* {broad,multi}cast packets to our BSS go through */
+				if (is_multicast_ether_addr(hdr->addr1)) {
+					if (!memcmp(hdr->addr2, ieee->current_network.bssid, ETH_ALEN)) {
+						break;
+					} else {
+						goto rx_dropped;
+					}
+				}
+
+				/* packets to our adapter go through */
+				if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
+					if (bToOtherSTA)        
+						break;
+					else
+						goto rx_dropped;
+				}
+
+				break;
+		}
+
+
+	}
+
+#ifdef ENABLE_LPS
+	if ((ieee->iw_mode == IW_MODE_INFRA)  && (ieee->sta_sleep == 1) 
+		&& (ieee->polling)) {
+		if (WLAN_FC_MORE_DATA(fc)) {
+			/* more data bit is set, let's request a new frame from the AP */
+			rtllib_sta_ps_send_pspoll_frame(ieee);
+		} else {
+			ieee->polling =  false;
+		}
+	}
+#endif
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(ieee->iw_mode == IW_MODE_ADHOC){
+		psta = GetStaInfo(ieee, src);
+		if(NULL != psta)
+			psta->LastActiveTime = jiffies;
+	}
+#endif
+	/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
+#ifdef _RTL8192_EXT_PATCH_
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable))
+#else
+	if (ieee->host_decrypt)
+#endif
+	{
+
+		int idx = 0;
+		if (skb->len >= hdrlen + 3)
+			idx = skb->data[hdrlen + 3] >> 6;
+		if (ieee->iw_mode == IW_MODE_MESH) 
+		{
+			if (ieee->mesh_sec_type == 1) { 
+				if(ieee->mesh_security_setting==1 ||ieee->mesh_security_setting==3)
+				{
+					bool find_crypt = false;
+					i = rtllib_find_MP(ieee, hdr->addr2, 0);
+					if(is_multicast_ether_addr(((struct rtllib_hdr_3addr*)skb->data)->addr1) || is_broadcast_ether_addr(((struct rtllib_hdr_3addr*)skb->data)->addr1))
+					{
+						if(ieee->only_mesh){
+							if(i != -1){
+								i=0;
+							}else{
+								printk("err find crypt\n");
+								goto rx_dropped;
+							}
+						}else{
+							if(i != -1){
+								i=0;
+							}else{
+								find_crypt = true;
+								crypt = ieee->sta_crypt[idx];
+							}
+						}
+					}else{
+						if(ieee->only_mesh){
+							if (i != -1){
+							}else{
+								printk("err find crypt\n");
+								goto rx_dropped;
+							}
+						}else{
+							if (i != -1){
+							}else{
+								find_crypt = true;
+								crypt = ieee->sta_crypt[idx];
+							}
+						}
+					}
+					if(find_crypt == false){
+						if(ieee->cryptlist[i] == NULL)
+							goto rx_dropped;
+						else
+							crypt = ieee->cryptlist[i]->crypt[idx];
+					}
+				}
+			}
+			else {
+			crypt = ieee->cryptlist[0]->crypt[idx];
+			if(crypt)
+			{
+				int i = rtllib_find_MP(ieee, hdr->addr2, 0);
+				if(ieee->only_mesh)
+				{
+					if (i == -1)
+					{
+						printk("error find entry in entry list\n");
+						goto rx_dropped;
+					}
+					if (ieee->cryptlist[i]&&ieee->cryptlist[i]->crypt[idx])
+						crypt = ieee->cryptlist[i]->crypt[idx];
+
+					else
+						crypt = NULL;
+				}
+				else 
+				{
+					if(i != -1)
+					{
+						if (ieee->cryptlist[i]&&ieee->cryptlist[i]->crypt[idx])
+							crypt = ieee->cryptlist[i]->crypt[idx];
+						else
+							crypt = NULL;
+					}
+					else
+						crypt = ieee->sta_crypt[idx];
+
+				}
+			}
+			else
+			{
+				if(!ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2))	
+					crypt = ieee->sta_crypt[idx];
+			}
+		}
+		}
+		else 
+			crypt = ieee->sta_crypt[idx];
+#ifdef NOT_YET
+		sta = NULL;
+
+		/* Use station specific key to override default keys if the
+		 * receiver address is a unicast address ("individual RA"). If
+		 * bcrx_sta_key parameter is set, station specific key is used
+		 * even with broad/multicast targets (this is against IEEE
+		 * 802.11, but makes it easier to use different keys with
+		 * stations that do not support WEP key mapping). */
+
+		if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+			(void) hostap_handle_sta_crypto(local, hdr, &crypt,
+							&sta);
+#endif
+
+		/* allow NULL decrypt to indicate an station specific override
+		 * for default encryption */
+		if (crypt && (crypt->ops == NULL ||
+			      crypt->ops->decrypt_mpdu == NULL))
+			crypt = NULL;
+
+		if (!crypt && (fc & RTLLIB_FCTL_WEP)) {
+			/* This seems to be triggered by some (multicast?)
+			 * frames from other than current BSS, so just drop the
+			 * frames silently instead of filling system log with
+			 * these reports. */
+			RTLLIB_DEBUG_DROP("Decryption failed (not set)"
+					     " (SA=" MAC_FMT ")\n",
+					     MAC_ARG(hdr->addr2));
+			ieee->ieee_stats.rx_discards_undecryptable++;
+			goto rx_dropped;
+		}
+	}
+#endif
+	if((!rx_stats->Decrypted)){
+		ieee->need_sw_enc = 1;
+	}
+
+	if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
+	    ((keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt)) < 0) 
+#if defined (RTL8192S_WAPI_SUPPORT)
+	    && (!ieee->wapiInfo.bWapiEnable)
+#endif
+	    )
+	{
+		printk("decrypt frame error\n");
+		goto rx_dropped;
+	}
+	if (tmp_dump) {
+		printk("************after decrypt\n");
+		dump_buf(skb->data,skb->len);
+	}
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if(ieee->wapiInfo.bWapiEnable){
+		if(ieee->pairwise_key_type == KEY_TYPE_SMS4){
+			if(false == SecSWSMS4Decryption(ieee, skb, rx_stats)){
+				WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__);
+				goto rx_dropped;
+			}
+		}
+	}
+#endif
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+	/* skb: hdr + (possibly fragmented) plaintext payload */
+	if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) {
+		int flen;
+		struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr);
+		RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
+
+		if (!frag_skb) {
+			RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG,
+					"Rx cannot get skb from fragment "
+					"cache (morefrag=%d seq=%u frag=%u)\n",
+					(fc & RTLLIB_FCTL_MOREFRAGS) != 0,
+					WLAN_GET_SEQ_SEQ(sc), frag);
+			goto rx_dropped;
+		}
+		flen = skb->len;
+		if (frag != 0)
+			flen -= hdrlen;
+
+		if (frag_skb->tail + flen > frag_skb->end) {
+			printk(KERN_WARNING "%s: host decrypted and "
+			       "reassembled frame did not fit skb\n",
+			       dev->name);
+			rtllib_frag_cache_invalidate(ieee, hdr);
+			goto rx_dropped;
+		}
+
+		if (frag == 0) {
+			/* copy first fragment (including full headers) into
+			 * beginning of the fragment cache skb */
+			memcpy(skb_put(frag_skb, flen), skb->data, flen);
+		} else {
+			/* append frame payload to the end of the fragment
+			 * cache skb */
+			memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+			       flen);
+		}
+		dev_kfree_skb_any(skb);
+		skb = NULL;
+
+		if (fc & RTLLIB_FCTL_MOREFRAGS) {
+			/* more fragments expected - leave the skb in fragment
+			 * cache for now; it will be delivered to upper layers
+			 * after all fragments have been received */
+			goto rx_exit;
+		}
+
+		/* this was the last fragment and the frame will be
+		 * delivered, so remove skb from fragment cache */
+		skb = frag_skb;
+		hdr = (struct rtllib_hdr_4addr *) skb->data;
+		rtllib_frag_cache_invalidate(ieee, hdr);
+	}
+
+	/* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+	 * encrypted/authenticated */
+	if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && 
+#if defined (RTL8192S_WAPI_SUPPORT)
+		(!ieee->wapiInfo.bWapiEnable) &&
+#endif		
+	    	rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
+	{
+		printk("==>decrypt msdu error\n");
+		goto rx_dropped;
+	}
+
+	ieee->LinkDetectInfo.NumRecvDataInPeriod++;
+	ieee->LinkDetectInfo.NumRxOkInPeriod++;
+	
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
+		unicast_packet = true;
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) {
+		if (/*ieee->ieee802_1x &&*/
+		    rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+
+#ifdef CONFIG_RTLLIB_DEBUG
+			/* pass unencrypted EAPOL frames even if encryption is
+			 * configured */
+			struct eapol *eap = (struct eapol *)(skb->data +
+				24);
+			RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+						eap_get_type(eap->type));
+#endif
+		} else {
+			RTLLIB_DEBUG_DROP(
+				"encryption configured, but RX "
+				"frame not encrypted (SA=" MAC_FMT ")\n",
+				MAC_ARG(hdr->addr2));
+			goto rx_dropped;
+		}
+	} 
+
+#ifdef CONFIG_RTLLIB_DEBUG
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) &&
+	    rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+			struct eapol *eap = (struct eapol *)(skb->data +
+				24);
+			RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+						eap_get_type(eap->type));
+	}
+#endif
+
+	if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep &&
+	    !rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+		RTLLIB_DEBUG_DROP(
+			"dropped unencrypted RX data "
+			"frame from " MAC_FMT
+			" (drop_unencrypted=1)\n",
+			MAC_ARG(hdr->addr2));
+		goto rx_dropped;
+	}
+/*
+	if(rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+		printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
+	}
+*/
+	if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) 
+		&& !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
+	{
+		TID = Frame_QoSTID(skb->data);
+		SeqNum = WLAN_GET_SEQ_SEQ(sc);
+		GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
+		if(TID !=0 && TID !=3){
+			ieee->bis_any_nonbepkts = true;
+		}
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if((fc & (WIFI_MESH_TYPE | RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS))
+		== (WIFI_MESH_TYPE | RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS))
+	{
+		if(ieee->iw_mode == IW_MODE_MESH){
+			rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC);
+			if(rxb == NULL)
+			{
+				printk("%s(): kmalloc rxb error\n",__FUNCTION__);
+				goto rx_dropped;
+			}
+			memset(rxb, 0, sizeof(struct rtllib_rxb));
+			if(msh_parse_subframe(ieee, skb, rxb)==0){
+				/* only to free rxb, and not submit the packets to upper layer */
+				for(i =0; i < rxb->nr_subframes; i++) {
+					if(rxb->subframes[i])
+						dev_kfree_skb(rxb->subframes[i]);
+				}
+				kfree(rxb);
+				rxb = NULL;
+				goto rx_dropped;
+			}
+			ret = msh_rx_process_dataframe(ieee,rxb,rx_stats);
+			if(ret < 0) {
+				for(i =0; i < rxb->nr_subframes; i++) {
+					if(rxb->subframes[i])
+						dev_kfree_skb(rxb->subframes[i]);
+				}
+				kfree(rxb);
+				rxb = NULL;
+				goto rx_dropped;
+			}else{
+				kfree(rxb);
+				rxb = NULL;
+			}
+		}else
+			goto rx_dropped;
+	}else{
+#endif
+		/* skb: hdr + (possible reassembled) full plaintext payload */
+		payload = skb->data + hdrlen;
+		rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC);
+		if(rxb == NULL)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__);
+			goto rx_dropped;
+		}
+		/* to parse amsdu packets */
+		/* qos data packets & reserved bit is 1 */
+		if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) {
+			/* only to free rxb, and not submit the packets to upper layer */
+			for(i =0; i < rxb->nr_subframes; i++) {
+				dev_kfree_skb(rxb->subframes[i]);
+			}
+			kfree(rxb);
+			rxb = NULL;
+			goto rx_dropped;
+		}
+#ifdef RTL8192S_WAPI_SUPPORT
+		if(ieee->wapiInfo.bWapiEnable){
+			if(rxb){
+				rxb->UserPriority = TID;
+				memcpy(rxb->WapiTempPN, rx_stats->WapiTempPN, 16);
+				memcpy(rxb->WapiSrcAddr, rx_stats->WapiSrcAddr, 6);
+				rxb->bWapiCheckPNInDecrypt = rx_stats->bWapiCheckPNInDecrypt;
+			}
+		}
+#endif
+#if !defined(RTL8192SU) && !defined(RTL8192U) 
+#ifdef ENABLE_LPS
+		if(unicast_packet)
+		{
+			if (type == RTLLIB_FTYPE_DATA)
+			{
+				
+				if(ieee->bIsAggregateFrame)
+					ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
+				else
+					ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
+				
+				if((ieee->state == RTLLIB_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+				{
+					if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+						(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+					{
+						if(ieee->LeisurePSLeave)
+							ieee->LeisurePSLeave(dev);
+					}
+				}
+			}
+		}	
+#endif
+#endif
+		ieee->last_rx_ps_time = jiffies;
+		if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL || bToOtherSTA ){
+			for(i = 0; i<rxb->nr_subframes; i++) {
+				struct sk_buff *sub_skb = rxb->subframes[i];
+
+				if (sub_skb) {
+					/* convert hdr + possible LLC headers into Ethernet header */
+					ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
+					if (sub_skb->len >= 8 &&
+							((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
+							  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+							 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+						/* remove RFC1042 or Bridge-Tunnel encapsulation and
+						 * replace EtherType */
+						skb_pull(sub_skb, SNAP_SIZE);
+						memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+						memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+					} else {
+						u16 len;
+						/* Leave Ethernet header part of hdr and full payload */
+						len = htons(sub_skb->len);
+						memcpy(skb_push(sub_skb, 2), &len, 2);
+						memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+						memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+					}
+
+					stats->rx_packets++;
+					stats->rx_bytes += sub_skb->len;
+
+					if(is_multicast_ether_addr(dst)) {
+						stats->multicast++;
+					}
+
+					/* Indicat the packets to upper layer */
+					memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
+#ifdef _RTL8192_EXT_PATCH_
+					sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev);
+#else
+					sub_skb->protocol = eth_type_trans(sub_skb, dev);
+					sub_skb->dev = dev;
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+					sub_skb->dev->stats.rx_packets++;
+					sub_skb->dev->stats.rx_bytes += sub_skb->len;	
+#endif
+#ifdef TCP_CSUM_OFFLOAD_RX
+					if ( rx_stats->tcp_csum_valid)
+						sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
+					else
+						sub_skb->ip_summed = CHECKSUM_NONE;
+#else
+					sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+#endif				
+
+					netif_rx(sub_skb);
+				}
+			}
+			kfree(rxb);
+			rxb = NULL;
+
+		}
+		else
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__);		
+#ifdef TCP_CSUM_OFFLOAD_RX
+			rxb->tcp_csum_valid = rx_stats->tcp_csum_valid;
+#endif		
+			RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
+		}
+#ifdef _RTL8192_EXT_PATCH_
+	}
+#endif	
+#ifndef JOHN_NOCPY
+	dev_kfree_skb(skb);
+#endif
+
+ rx_exit:
+#ifdef NOT_YET
+	if (sta)
+		hostap_handle_sta_release(sta);
+#endif
+	return 1;
+
+ rx_dropped:
+	if (rxb != NULL)
+	{
+		kfree(rxb);
+		rxb = NULL;
+	}		
+	stats->rx_dropped++;
+
+	/* Returning 0 indicates to caller that we have not handled the SKB--
+	 * so it is still allocated and can be used again by underlying
+	 * hardware as a DMA target */
+	return 0;
+}
+#endif
+
+#define MGMT_FRAME_FIXED_PART_LENGTH            0x24
+
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/*
+* Make ther structure we read from the beacon packet has
+* the right values
+*/
+static int rtllib_verify_qos_info(struct rtllib_qos_information_element
+                                     *info_element, int sub_type)
+{
+
+        if (info_element->qui_subtype != sub_type)
+                return -1;
+        if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+                return -1;
+        if (info_element->qui_type != QOS_OUI_TYPE)
+                return -1;
+        if (info_element->version != QOS_VERSION_1)
+                return -1;
+
+        return 0;
+}
+
+
+/*
+ * Parse a QoS parameter element
+ */
+static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
+                                            *element_param, struct rtllib_info_element
+                                            *info_element)
+{
+        int ret = 0;
+        u16 size = sizeof(struct rtllib_qos_parameter_info) - 2;
+
+        if ((info_element == NULL) || (element_param == NULL))
+                return -1;
+
+        if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+                memcpy(element_param->info_element.qui, info_element->data,
+                       info_element->len);
+                element_param->info_element.elementID = info_element->id;
+                element_param->info_element.length = info_element->len;
+        } else
+                ret = -1;
+        if (ret == 0)
+                ret = rtllib_verify_qos_info(&element_param->info_element,
+                                                QOS_OUI_PARAM_SUB_TYPE);
+        return ret;
+}
+
+/*
+ * Parse a QoS information element
+ */
+static int rtllib_read_qos_info_element(struct
+                                           rtllib_qos_information_element
+                                           *element_info, struct rtllib_info_element
+                                           *info_element)
+{
+        int ret = 0;
+        u16 size = sizeof(struct rtllib_qos_information_element) - 2;
+
+        if (element_info == NULL)
+                return -1;
+        if (info_element == NULL)
+                return -1;
+
+        if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+                memcpy(element_info->qui, info_element->data,
+                       info_element->len);
+                element_info->elementID = info_element->id;
+                element_info->length = info_element->len;
+        } else
+                ret = -1;
+
+        if (ret == 0)
+                ret = rtllib_verify_qos_info(element_info,
+                                                QOS_OUI_INFO_SUB_TYPE);
+        return ret;
+}
+
+
+/*
+ * Write QoS parameters from the ac parameters.
+ */
+static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm, 
+		struct rtllib_qos_data *qos_data)
+{
+        struct rtllib_qos_ac_parameter *ac_params;
+	struct rtllib_qos_parameters *qos_param = &(qos_data->parameters);
+        int rc = 0;
+        int i;
+	u8 aci;
+	u8 acm;
+
+	qos_data->wmm_acm = 0;
+        for (i = 0; i < QOS_QUEUE_NUM; i++) {
+                ac_params = &(param_elm->ac_params_record[i]);
+
+		aci = (ac_params->aci_aifsn & 0x60) >> 5;
+		acm = (ac_params->aci_aifsn & 0x10) >> 4;
+
+		if(aci >= QOS_QUEUE_NUM)
+			continue;
+		switch (aci) {
+			case 1:
+				/* BIT(0) | BIT(3) */
+				if (acm)
+					qos_data->wmm_acm |= (0x01<<0)|(0x01<<3);
+				break;
+			case 2: 
+				/* BIT(4) | BIT(5) */
+				if (acm)
+					qos_data->wmm_acm |= (0x01<<4)|(0x01<<5);
+				break;
+			case 3:
+				/* BIT(6) | BIT(7) */
+				if (acm)
+					qos_data->wmm_acm |= (0x01<<6)|(0x01<<7);
+				break;
+			case 0:
+			default:
+				/* BIT(1) | BIT(2) */
+				if (acm)
+					qos_data->wmm_acm |= (0x01<<1)|(0x01<<2);
+				break;
+		}
+
+                qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
+
+		/* WMM spec P.11: The minimum value for AIFSN shall be 2 */
+                qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; 
+
+                qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F;
+
+                qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4;
+
+                qos_param->flag[aci] =
+                    (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+                qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit);
+        }
+        return rc;
+}
+
+/*
+ * we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int rtllib_parse_qos_info_param_IE(struct rtllib_info_element
+                                             *info_element,
+                                             struct rtllib_network *network)
+{
+        int rc = 0;
+        struct rtllib_qos_information_element qos_info_element;
+
+        rc = rtllib_read_qos_info_element(&qos_info_element, info_element);
+
+        if (rc == 0) {
+                network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+                network->flags |= NETWORK_HAS_QOS_INFORMATION;
+        } else {
+                struct rtllib_qos_parameter_info param_element;
+
+                rc = rtllib_read_qos_param_element(&param_element,
+                                                      info_element);
+                if (rc == 0) {
+                        rtllib_qos_convert_ac_to_parameters(&param_element,
+                                                               &(network->qos_data));
+                        network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+                        network->qos_data.param_count =
+                            param_element.info_element.ac_info & 0x0F;
+                }
+        }
+
+        if (rc == 0) {
+                RTLLIB_DEBUG_QOS("QoS is supported\n");
+                network->qos_data.supported = 1;
+        }
+        return rc;
+}
+
+#ifdef CONFIG_RTLLIB_DEBUG
+#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
+
+static const char *get_info_element_string(u16 id)
+{
+        switch (id) {
+                MFIE_STRING(SSID);
+                MFIE_STRING(RATES);
+                MFIE_STRING(FH_SET);
+                MFIE_STRING(DS_SET);
+                MFIE_STRING(CF_SET);
+                MFIE_STRING(TIM);
+                MFIE_STRING(IBSS_SET);
+                MFIE_STRING(COUNTRY);
+                MFIE_STRING(HOP_PARAMS);
+                MFIE_STRING(HOP_TABLE);
+                MFIE_STRING(REQUEST);
+                MFIE_STRING(CHALLENGE);
+                MFIE_STRING(POWER_CONSTRAINT);
+                MFIE_STRING(POWER_CAPABILITY);
+                MFIE_STRING(TPC_REQUEST);
+                MFIE_STRING(TPC_REPORT);
+                MFIE_STRING(SUPP_CHANNELS);
+                MFIE_STRING(CSA);
+                MFIE_STRING(MEASURE_REQUEST);
+                MFIE_STRING(MEASURE_REPORT);
+                MFIE_STRING(QUIET);
+                MFIE_STRING(IBSS_DFS);
+                MFIE_STRING(RSN);
+                MFIE_STRING(RATES_EX);
+                MFIE_STRING(GENERIC);
+                MFIE_STRING(QOS_PARAMETER);
+        default:
+                return "UNKNOWN";
+        }
+}
+#endif
+
+#ifdef ENABLE_DOT11D
+static inline void rtllib_extract_country_ie(
+	struct rtllib_device *ieee,
+	struct rtllib_info_element *info_element,
+	struct rtllib_network *network,
+	u8 * addr2)
+{
+	if (IS_DOT11D_ENABLE(ieee)) {
+		if(info_element->len!= 0) {
+			memcpy(network->CountryIeBuf, info_element->data, info_element->len);
+			network->CountryIeLen = info_element->len;
+
+			if(!IS_COUNTRY_IE_VALID(ieee))
+			{
+				if((rtllib_act_scanning(ieee,false) == true) && (ieee->FirstIe_InScan == 1))
+					printk("Received beacon ContryIE, SSID: <%s>\n",network->ssid);
+				Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
+			}
+		}
+
+		if (IS_EQUAL_CIE_SRC(ieee, addr2)) {
+			UPDATE_CIE_WATCHDOG(ieee);
+		}
+	}
+
+}
+#endif
+
+int rtllib_parse_info_param(struct rtllib_device *ieee,
+		struct rtllib_info_element *info_element, 
+		u16 length,
+		struct rtllib_network *network,
+		struct rtllib_rx_stats *stats)
+{
+	u8 i;
+	short offset;
+        u16	tmp_htcap_len=0;
+	u16	tmp_htinfo_len=0;
+	u16 ht_realtek_agg_len=0;
+	u8  ht_realtek_agg_buf[MAX_IE_LEN];
+#ifdef CONFIG_RTLLIB_DEBUG
+	char rates_str[64];
+	char *p;
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	u8 tmp_wapi_len = 0;
+#endif
+	while (length >= sizeof(*info_element)) {
+		if (sizeof(*info_element) + info_element->len > length) {
+			RTLLIB_DEBUG_MGMT("Info elem: parse failed: "
+					     "info_element->len + 2 > left : "
+					     "info_element->len+2=%zd left=%d, id=%d.\n",
+					     info_element->len +
+					     sizeof(*info_element),
+					     length, info_element->id);
+			/* We stop processing but don't return an error here
+			 * because some misbehaviour APs break this rule. ie.
+			 * Orinoco AP1000. */
+			break;
+		}
+
+		switch (info_element->id) {
+		case MFIE_TYPE_SSID:
+			if (rtllib_is_empty_essid(info_element->data,
+						     info_element->len)) {
+				network->flags |= NETWORK_EMPTY_ESSID;
+				break;
+			}
+
+			network->ssid_len = min(info_element->len,
+						(u8) IW_ESSID_MAX_SIZE);
+			memcpy(network->ssid, info_element->data, network->ssid_len);
+			if (network->ssid_len < IW_ESSID_MAX_SIZE)
+				memset(network->ssid + network->ssid_len, 0,
+				       IW_ESSID_MAX_SIZE - network->ssid_len);
+
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
+					     network->ssid, network->ssid_len);
+			break;
+
+		case MFIE_TYPE_RATES:
+#ifdef CONFIG_RTLLIB_DEBUG
+			p = rates_str;
+#endif
+			network->rates_len = min(info_element->len,
+						 MAX_RATES_LENGTH);
+			for (i = 0; i < network->rates_len; i++) {
+				network->rates[i] = info_element->data[i];
+#ifdef CONFIG_RTLLIB_DEBUG
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
+#endif
+				if (rtllib_is_ofdm_rate
+				    (info_element->data[i])) {
+					network->flags |= NETWORK_HAS_OFDM;
+					if (info_element->data[i] &
+					    RTLLIB_BASIC_RATE_MASK)
+						network->flags &=
+						    ~NETWORK_HAS_CCK;
+				}
+
+				if (rtllib_is_cck_rate
+				    (info_element->data[i])) {
+					network->flags |= NETWORK_HAS_CCK;
+				}
+			}
+
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
+					     rates_str, network->rates_len);
+			break;
+
+		case MFIE_TYPE_RATES_EX:
+#ifdef CONFIG_RTLLIB_DEBUG
+			p = rates_str;
+#endif
+			network->rates_ex_len = min(info_element->len,
+						    MAX_RATES_EX_LENGTH);
+			for (i = 0; i < network->rates_ex_len; i++) {
+				network->rates_ex[i] = info_element->data[i];
+#ifdef CONFIG_RTLLIB_DEBUG
+				p += snprintf(p, sizeof(rates_str) -
+					      (p - rates_str), "%02X ",
+					      network->rates[i]);
+#endif
+				if (rtllib_is_ofdm_rate
+				    (info_element->data[i])) {
+					network->flags |= NETWORK_HAS_OFDM;
+					if (info_element->data[i] &
+					    RTLLIB_BASIC_RATE_MASK)
+						network->flags &=
+						    ~NETWORK_HAS_CCK;
+				}
+			}
+
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+					     rates_str, network->rates_ex_len);
+			break;
+
+		case MFIE_TYPE_DS_SET:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
+					     info_element->data[0]);
+			network->channel = info_element->data[0];
+			break;
+
+		case MFIE_TYPE_FH_SET:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
+			break;
+
+		case MFIE_TYPE_CF_SET:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
+			break;
+
+		case MFIE_TYPE_TIM:
+			if(info_element->len < 4) 
+				break;
+
+			network->tim.tim_count = info_element->data[0];
+			network->tim.tim_period = info_element->data[1];
+
+                        network->dtim_period = info_element->data[1];
+                        if(ieee->state != RTLLIB_LINKED)
+                                break;
+#if 0
+                        network->last_dtim_sta_time[0] = stats->mac_time[0];
+#else
+			network->last_dtim_sta_time[0] = jiffies;
+#endif
+                        network->last_dtim_sta_time[1] = stats->mac_time[1];
+
+                        network->dtim_data = RTLLIB_DTIM_VALID;
+                        
+
+                        if(info_element->data[2] & 1)
+                                network->dtim_data |= RTLLIB_DTIM_MBCAST;
+                                
+#if 1
+                        offset = (info_element->data[2] >> 1)*2;
+                        
+                
+                        if(ieee->assoc_id < 8*offset || 
+                                ieee->assoc_id > 8*(offset + info_element->len -3))
+                                
+                                break;
+
+                        offset = (ieee->assoc_id / 8) - offset;
+                        if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
+                                network->dtim_data |= RTLLIB_DTIM_UCAST;
+#else
+			{
+				u16 numSta = 0;
+				u16 offset_byte = 0;
+				u16 offset_bit = 0;
+
+				numSta = (info_element->data[2] &0xFE)*8;
+
+				if(ieee->assoc_id < numSta ||
+						ieee->assoc_id > (numSta + (info_element->len -3)*8))
+					break;
+
+				offset = ieee->assoc_id - numSta;
+				offset_byte = offset / 8;
+				offset_bit = offset % 8;
+				if(info_element->data[3+offset_byte] & (0x01<<offset_bit))
+					network->dtim_data |= RTLLIB_DTIM_UCAST;
+			}
+#endif
+
+			network->listen_interval = network->dtim_period;
+			break;
+
+		case MFIE_TYPE_ERP:
+			network->erp_value = info_element->data[0];
+			network->flags |= NETWORK_HAS_ERP_VALUE;
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
+					     network->erp_value);
+			break;
+		case MFIE_TYPE_IBSS_SET:
+			network->atim_window = info_element->data[0];
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
+					     network->atim_window);
+			break;
+
+		case MFIE_TYPE_CHALLENGE:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
+			break;
+
+		case MFIE_TYPE_GENERIC:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
+					     info_element->len);
+			if (!rtllib_parse_qos_info_param_IE(info_element,
+							       network))
+				break;
+			if (info_element->len >= 4 &&
+			    info_element->data[0] == 0x00 &&
+			    info_element->data[1] == 0x50 &&
+			    info_element->data[2] == 0xf2 &&
+			    info_element->data[3] == 0x01) {
+				network->wpa_ie_len = min(info_element->len + 2,
+							  MAX_WPA_IE_LEN);
+				memcpy(network->wpa_ie, info_element,
+				       network->wpa_ie_len);
+				break;
+			}
+#ifdef THOMAS_TURBO
+                        if (info_element->len == 7 &&
+                            info_element->data[0] == 0x00 &&
+                            info_element->data[1] == 0xe0 &&
+                            info_element->data[2] == 0x4c &&
+                            info_element->data[3] == 0x01 &&
+                            info_element->data[4] == 0x02) {
+                                network->Turbo_Enable = 1;
+                        }
+#endif
+
+			if(tmp_htcap_len == 0){
+				if(info_element->len >= 4 &&
+				   info_element->data[0] == 0x00 &&
+				   info_element->data[1] == 0x90 &&
+				   info_element->data[2] == 0x4c &&
+				   info_element->data[3] == 0x033){
+				   
+						tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
+				   		if(tmp_htcap_len != 0){
+				   			network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+							network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
+								sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
+							memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);							
+				   		}
+				}
+				if(tmp_htcap_len != 0){
+					network->bssht.bdSupportHT = true;
+					network->bssht.bdHT1R = ((((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->MCS[1]) == 0);
+				}else{
+					network->bssht.bdSupportHT = false;
+					network->bssht.bdHT1R = false;
+				}
+			}
+			
+			
+			if(tmp_htinfo_len == 0){
+				if(info_element->len >= 4 &&
+					info_element->data[0] == 0x00 &&
+				   	info_element->data[1] == 0x90 &&
+				   	info_element->data[2] == 0x4c &&
+				   	info_element->data[3] == 0x034){
+
+						tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
+						if(tmp_htinfo_len != 0){
+							network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+							if(tmp_htinfo_len){
+								network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
+									sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
+								memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
+							}
+							
+						}
+						
+				}
+			}
+
+			if(ieee->aggregation){
+				if(network->bssht.bdSupportHT){
+					if(info_element->len >= 4 &&
+						info_element->data[0] == 0x00 &&
+						info_element->data[1] == 0xe0 &&
+						info_element->data[2] == 0x4c &&
+						info_element->data[3] == 0x02){
+
+						ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN);
+						memcpy(ht_realtek_agg_buf,info_element->data,info_element->len);
+						
+					}
+					if(ht_realtek_agg_len >= 5){
+						network->realtek_cap_exit = true;
+						network->bssht.bdRT2RTAggregation = true;
+
+						if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
+						network->bssht.bdRT2RTLongSlotTime = true;
+
+						if((ht_realtek_agg_buf[4]==1) && (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE))
+						{
+							network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE;
+						}
+					}
+				}
+				if(ht_realtek_agg_len >= 5){
+					if((ht_realtek_agg_buf[5] & RT_HT_CAP_USE_SOFTAP))
+						network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_SOFTAP;
+				}
+			}
+
+			{
+				if((info_element->len >= 3 &&
+					 info_element->data[0] == 0x00 &&
+					 info_element->data[1] == 0x05 &&
+					 info_element->data[2] == 0xb5) || 
+					 (info_element->len >= 3 &&
+					 info_element->data[0] == 0x00 &&
+					 info_element->data[1] == 0x0a &&
+					 info_element->data[2] == 0xf7) ||
+					 (info_element->len >= 3 &&
+					 info_element->data[0] == 0x00 &&
+					 info_element->data[1] == 0x10 &&
+					 info_element->data[2] == 0x18)){
+
+						network->broadcom_cap_exist = true;
+
+				}
+			}
+#if 0	
+			if (tmp_htcap_len !=0)
+				{
+					u16 cap_ext = ((PHT_CAPABILITY_ELE)&info_element->data[0])->ExtHTCapInfo;
+					if ((cap_ext & 0x0c00) == 0x0c00)
+						{
+							network->ralink_cap_exist = true;
+						}
+				}
+#endif
+			if(info_element->len >= 3 &&
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x0c &&
+				info_element->data[2] == 0x43)
+			{
+				network->ralink_cap_exist = true;
+			}
+			if((info_element->len >= 3 && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x03 &&
+				info_element->data[2] == 0x7f) ||
+				(info_element->len >= 3 &&
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x13 &&
+				info_element->data[2] == 0x74))
+			{
+				network->atheros_cap_exist = true;
+			}
+
+			if ((info_element->len >= 3 && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x50 &&
+				info_element->data[2] == 0x43) )
+				{
+					network->marvell_cap_exist = true;
+				}
+			if(info_element->len >= 3 &&
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x40 &&
+				info_element->data[2] == 0x96)
+			{
+				network->cisco_cap_exist = true;
+			}
+			if(info_element->len > 4 && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x40 &&
+				info_element->data[2] == 0x96 &&
+				info_element->data[3] == 0x01)
+			{
+				if(info_element->len == 6)
+				{
+					memcpy(network->CcxRmState, &info_element[4], 2);
+					if(network->CcxRmState[0] != 0)
+					{
+						network->bCcxRmEnable = true;
+					}
+					else
+						network->bCcxRmEnable = false;
+					network->MBssidMask = network->CcxRmState[1] & 0x07;
+					if(network->MBssidMask != 0)
+					{
+						network->bMBssidValid = true;
+						network->MBssidMask = 0xff << (network->MBssidMask);
+						memcpy(network->MBssid, network->bssid, ETH_ALEN);
+						network->MBssid[5] &= network->MBssidMask;
+					}
+					else
+					{
+						network->bMBssidValid = false;
+					}
+				}
+				else
+				{
+					network->bCcxRmEnable = false;
+				}
+			}
+			if(info_element->len > 4  && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x40 &&
+				info_element->data[2] == 0x96 &&
+				info_element->data[3] == 0x03)
+			{
+				if(info_element->len == 5)
+				{
+					network->bWithCcxVerNum = true;
+					network->BssCcxVerNumber = info_element->data[4];
+				}
+				else
+				{
+					network->bWithCcxVerNum = false;
+					network->BssCcxVerNumber = 0;
+				}
+			}
+			if(info_element->len > 4  && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x50 &&
+				info_element->data[2] == 0xf2 &&
+				info_element->data[3] == 0x04)
+			{
+				RTLLIB_DEBUG_MGMT("MFIE_TYPE_WZC: %d bytes\n",
+						     info_element->len);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+				network->wzc_ie_len = min(info_element->len+2,
+							  MAX_WZC_IE_LEN);
+				memcpy(network->wzc_ie, info_element,
+						network->wzc_ie_len);
+#endif
+			}
+#ifdef _RTL8192_EXT_PATCH_
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+			if(info_element->len > 3  && 
+				info_element->data[0] == 0x00 &&
+				info_element->data[1] == 0x0F &&
+				info_element->data[2] == 0xAC)
+			{
+				network->hostname_len = info_element->len - 3;
+				memcpy(network->hostname, (info_element->data+3), network->hostname_len);
+			}
+#else			
+			if(info_element->len > 4  && 
+				info_element->data[0] == 0x48 &&
+				info_element->data[1] == 0x4F &&
+				info_element->data[2] == 0x53 &&
+				info_element->data[3] == 0x54)
+			{
+				network->hostname_len = info_element->len - 4;
+				memcpy(network->hostname, (info_element->data+4), network->hostname_len);
+			}
+#endif
+#endif
+			break;
+
+		case MFIE_TYPE_RSN:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
+					     info_element->len);
+			network->rsn_ie_len = min(info_element->len + 2,
+						  MAX_WPA_IE_LEN);
+			memcpy(network->rsn_ie, info_element,
+			       network->rsn_ie_len);
+			break;
+
+		case MFIE_TYPE_HT_CAP:
+			RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
+					     info_element->len);
+			tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
+			if(tmp_htcap_len != 0){
+				network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+				network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
+					sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
+				memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
+				
+				network->bssht.bdSupportHT = true;
+				network->bssht.bdHT1R = ((((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->MCS[1]) == 0);
+
+				network->bssht.bdBandWidth = (HT_CHANNEL_WIDTH)(((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->ChlWidth);
+			}
+			else{
+				network->bssht.bdSupportHT = false;
+				network->bssht.bdHT1R = false;
+				network->bssht.bdBandWidth = HT_CHANNEL_WIDTH_20 ;
+			}
+			break;
+
+
+		case MFIE_TYPE_HT_INFO:
+			RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
+					     info_element->len);
+			tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
+			if(tmp_htinfo_len){
+				network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
+				network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
+					sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
+				memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
+			}
+			break;
+
+		case MFIE_TYPE_AIRONET:
+			RTLLIB_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
+					     info_element->len);
+			if(info_element->len >IE_CISCO_FLAG_POSITION)
+			{
+				network->bWithAironetIE = true;
+
+				if(	(info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC)	||
+					(info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK)	)
+				{
+		 			network->bCkipSupported = true;
+				}
+				else
+				{
+					network->bCkipSupported = false;
+				}
+			}
+			else
+			{
+				network->bWithAironetIE = false;
+		 		network->bCkipSupported = false;
+			}
+			break;
+		case MFIE_TYPE_QOS_PARAMETER:
+			printk(KERN_ERR
+			       "QoS Error need to parse QOS_PARAMETER IE\n");
+			break;
+
+#ifdef ENABLE_DOT11D
+		case MFIE_TYPE_COUNTRY:
+			RTLLIB_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
+					     info_element->len);
+			rtllib_extract_country_ie(ieee, info_element, network, network->bssid);
+			break;
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+		case MFIE_TYPE_MESH_ID:
+			network->mesh_id_len = min(info_element->len, (u8)MAX_MESH_ID_LEN);
+			memcpy(network->mesh_id, info_element->data, network->mesh_id_len);
+			if (network->mesh_id_len < MAX_MESH_ID_LEN) {
+				memset(network->mesh_id + network->mesh_id_len, 0,
+					MAX_MESH_ID_LEN - network->mesh_id_len);
+			}
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_MESH_ID: '%s'len=%d.\n", network->mesh_id, 
+					network->mesh_id_len);
+			break;
+
+		case MFIE_TYPE_MESH_CONFIGURATION:
+			network->mesh_config_len = min(info_element->len, (u8)MESH_CONF_TOTAL_LEN); 
+			memcpy(network->mesh_config.path_proto_id, info_element->data + 1, 4);
+			memcpy(network->mesh_config.path_metric_id, info_element->data + 5, 4);
+			memcpy(network->mesh_config.congest_ctl_mode, info_element->data + 9, 4);
+			memcpy(network->mesh_config.mesh_capability, info_element->data + 17, 2);
+			break;
+#endif
+/* TODO */
+#if 0
+			/* 802.11h */
+		case MFIE_TYPE_POWER_CONSTRAINT:
+			network->power_constraint = info_element->data[0];
+			network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
+			break;
+
+		case MFIE_TYPE_CSA:
+			network->power_constraint = info_element->data[0];
+			network->flags |= NETWORK_HAS_CSA;
+			break;
+
+		case MFIE_TYPE_QUIET:
+			network->quiet.count = info_element->data[0];
+			network->quiet.period = info_element->data[1];
+			network->quiet.duration = info_element->data[2];
+			network->quiet.offset = info_element->data[3];
+			network->flags |= NETWORK_HAS_QUIET;
+			break;
+
+		case MFIE_TYPE_IBSS_DFS:
+			if (network->ibss_dfs)
+				break;
+			network->ibss_dfs = kmemdup(info_element->data,
+						    info_element->len,
+						    GFP_ATOMIC);
+			if (!network->ibss_dfs)
+				return 1;
+			network->flags |= NETWORK_HAS_IBSS_DFS;
+			break;
+
+		case MFIE_TYPE_TPC_REPORT:
+			network->tpc_report.transmit_power =
+			    info_element->data[0];
+			network->tpc_report.link_margin = info_element->data[1];
+			network->flags |= NETWORK_HAS_TPC_REPORT;
+			break;
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+		case MFIE_TYPE_WAPI:
+			RTLLIB_DEBUG_MGMT("MFIE_TYPE_WAPI: %d bytes\n", info_element->len);
+			tmp_wapi_len = min(info_element->len,(u8)MAX_WAPI_IE_LEN);
+			if(tmp_wapi_len){
+				network->wapi_ie_len = tmp_wapi_len;
+				memcpy(network->wapi_ie,info_element->data,network->wapi_ie_len);
+			}
+			break;
+#endif
+		default:
+			RTLLIB_DEBUG_MGMT
+			    ("Unsupported info element: %s (%d)\n",
+			     get_info_element_string(info_element->id),
+			     info_element->id);
+			break;
+		}
+
+		length -= sizeof(*info_element) + info_element->len;
+		info_element =
+		    (struct rtllib_info_element *)&info_element->
+		    data[info_element->len];
+	}
+
+	if(!network->atheros_cap_exist && !network->broadcom_cap_exist && 
+		!network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation)
+	{
+		network->unknown_cap_exist = true;
+	}
+	else
+	{
+		network->unknown_cap_exist = false;
+	}
+	return 0;
+}
+
+static inline u8 rtllib_SignalStrengthTranslate(
+	u8  CurrSS
+	)
+{
+	u8 RetSS;
+
+	if(CurrSS >= 71 && CurrSS <= 100)
+	{
+		RetSS = 90 + ((CurrSS - 70) / 3);
+	}	
+	else if(CurrSS >= 41 && CurrSS <= 70)
+	{
+		RetSS = 78 + ((CurrSS - 40) / 3);
+	}	
+	else if(CurrSS >= 31 && CurrSS <= 40)
+	{
+		RetSS = 66 + (CurrSS - 30);
+	}	
+	else if(CurrSS >= 21 && CurrSS <= 30)
+	{
+		RetSS = 54 + (CurrSS - 20);
+	}	
+	else if(CurrSS >= 5 && CurrSS <= 20)
+	{
+		RetSS = 42 + (((CurrSS - 5) * 2) / 3);
+	}	
+	else if(CurrSS == 4)
+	{
+		RetSS = 36; 
+	}
+	else if(CurrSS == 3)
+	{
+		RetSS = 27; 
+	}
+	else if(CurrSS == 2)
+	{
+		RetSS = 18; 
+	}
+	else if(CurrSS == 1)
+	{
+		RetSS = 9; 
+	}
+	else
+	{
+		RetSS = CurrSS; 
+	}
+
+	
+
+	return RetSS;
+}
+
+long rtllib_translate_todbm(u8 signal_strength_index	)
+{
+	long	signal_power; 
+
+	signal_power = (long)((signal_strength_index + 1) >> 1); 
+	signal_power -= 95; 
+
+	return signal_power;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_network_init(
+#else
+static inline int rtllib_network_init(
+#endif
+	struct rtllib_device *ieee,
+	struct rtllib_probe_response *beacon,
+	struct rtllib_network *network,
+	struct rtllib_rx_stats *stats)
+{
+#ifdef CONFIG_RTLLIB_DEBUG
+#endif
+
+	/*	
+        network->qos_data.active = 0;
+        network->qos_data.supported = 0;
+        network->qos_data.param_count = 0;
+        network->qos_data.old_param_count = 0;
+	*/
+	memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data));
+
+	/* Pull out fixed field data */
+	memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+	network->capability = le16_to_cpu(beacon->capability);
+	network->last_scanned = jiffies;
+	network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+	network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+	network->beacon_interval = le32_to_cpu(beacon->beacon_interval);
+	/* Where to pull this? beacon->listen_interval;*/
+	network->listen_interval = 0x0A;
+	network->rates_len = network->rates_ex_len = 0;
+	network->last_associate = 0;
+	network->ssid_len = 0;
+	network->hidden_ssid_len = 0;
+	memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid));
+	network->flags = 0;
+	network->atim_window = 0;
+	network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+            0x3 : 0x0;
+	network->berp_info_valid = false;
+        network->broadcom_cap_exist = false;
+	network->ralink_cap_exist = false;
+	network->atheros_cap_exist = false;
+	network->cisco_cap_exist = false;
+	network->unknown_cap_exist = false;
+	network->realtek_cap_exit = false;
+	network->marvell_cap_exist = false;
+#ifdef THOMAS_TURBO
+	network->Turbo_Enable = 0;
+#endif
+	network->SignalStrength = stats->SignalStrength;	
+	network->RSSI = stats->SignalStrength;	
+#ifdef ENABLE_DOT11D
+	network->CountryIeLen = 0;
+	memset(network->CountryIeBuf, 0, MAX_IE_LEN);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	memset(network->hostname, 0, MAX_HOST_NAME_LENGTH);
+	network->hostname_len = 0;
+#endif
+	HTInitializeBssDesc(&network->bssht);	
+	if (stats->freq == RTLLIB_52GHZ_BAND) {
+		/* for A band (No DS info) */
+		network->channel = stats->received_channel;
+	} else
+		network->flags |= NETWORK_HAS_CCK;
+
+ 	network->wpa_ie_len = 0;
+ 	network->rsn_ie_len = 0;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	network->wzc_ie_len = 0;
+#endif
+
+        if (rtllib_parse_info_param(ieee,
+			beacon->info_element, 
+			(stats->len - sizeof(*beacon)), 
+			network, 
+			stats))
+                return 1;
+
+	network->mode = 0;
+	if (stats->freq == RTLLIB_52GHZ_BAND)
+		network->mode = IEEE_A;
+	else {
+		if (network->flags & NETWORK_HAS_OFDM)
+			network->mode |= IEEE_G;
+		if (network->flags & NETWORK_HAS_CCK)
+			network->mode |= IEEE_B;
+	}
+
+	if (network->mode == 0) {
+		RTLLIB_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+				     "network.\n",
+				     escape_essid(network->ssid,
+						  network->ssid_len),
+				     MAC_ARG(network->bssid));
+		return 1;
+	}
+
+	if(network->bssht.bdSupportHT){
+#ifdef _RTL8192_EXT_PATCH_
+		if(network->mode == IEEE_A)
+			network->mode |= IEEE_N_5G;
+		else if(network->mode & (IEEE_G | IEEE_B))
+			network->mode |= IEEE_N_24G;
+#else
+		if(network->mode == IEEE_A)
+			network->mode = IEEE_N_5G;
+		else if(network->mode & (IEEE_G | IEEE_B))
+			network->mode = IEEE_N_24G;
+#endif
+	}
+	if (rtllib_is_empty_essid(network->ssid, network->ssid_len))
+		network->flags |= NETWORK_EMPTY_ESSID;
+
+#if  0	
+        {
+            static u8 Netgear845T_Mac[3] = {0x00, 0x1B, 0x2F};
+            static u8 Buffalo300N_Mac[3] = {0x00, 0x16, 0x01};
+
+            if(ieee->RF_Type == RF_1T1R || ieee->b1SSSupport == true)
+            {
+                if((memcmp(network->bssid, Netgear845T_Mac, 3)==0) ||(memcmp(network->bssid, Buffalo300N_Mac, 3)==0))
+                {
+                    network->bIsNetgear854T = true;
+                    network->bssht.bdSupportHT = false;
+                    if(network->mode == WIRELESS_MODE_N_24G)
+                    {
+                        network->mode = WIRELESS_MODE_B | WIRELESS_MODE_G;
+                    }
+
+                }
+                else
+                {
+                    network->bIsNetgear854T = false;
+                }
+            }
+        }
+#endif
+
+#if 1	
+	stats->signal = 30 + (stats->SignalStrength * 70) / 100;
+	stats->noise = rtllib_translate_todbm((u8)(100-stats->signal)) -25;
+#endif
+
+	memcpy(&network->stats, stats, sizeof(network->stats));
+
+	return 0;
+}
+
+static inline int is_same_network(struct rtllib_network *src,
+				  struct rtllib_network *dst, u8 ssidbroad)
+{
+	/* A network is only a duplicate if the channel, BSSID, ESSID
+	 * and the capability field (in particular IBSS and BSS) all match.  
+	 * We treat all <hidden> with the same BSSID and channel
+	 * as one network */
+	return 
+		(((src->ssid_len == dst->ssid_len) || (!ssidbroad)) &&
+		(src->channel == dst->channel) &&
+		!memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
+		(!memcmp(src->ssid, dst->ssid, src->ssid_len) || (!ssidbroad)) &&
+		((src->capability & WLAN_CAPABILITY_IBSS) == 
+		(dst->capability & WLAN_CAPABILITY_IBSS)) &&
+		((src->capability & WLAN_CAPABILITY_ESS) == 
+		(dst->capability & WLAN_CAPABILITY_ESS)));
+}
+
+static inline void update_network(struct rtllib_network *dst,
+				  struct rtllib_network *src)
+{
+	int qos_active;
+	u8 old_param;
+
+	memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats));
+	dst->capability = src->capability;
+	memcpy(dst->rates, src->rates, src->rates_len);
+	dst->rates_len = src->rates_len;
+	memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
+	dst->rates_ex_len = src->rates_ex_len;
+	if(src->ssid_len > 0)
+	{
+		if(dst->ssid_len == 0)
+		{
+			memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid));
+			dst->hidden_ssid_len = src->ssid_len;
+			memcpy(dst->hidden_ssid, src->ssid, src->ssid_len);
+		}else{
+			memset(dst->ssid, 0, dst->ssid_len);
+			dst->ssid_len = src->ssid_len;
+			memcpy(dst->ssid, src->ssid, src->ssid_len);
+		}
+	}
+	dst->mode = src->mode;
+	dst->flags = src->flags;
+	dst->time_stamp[0] = src->time_stamp[0];
+	dst->time_stamp[1] = src->time_stamp[1];
+	if (src->flags & NETWORK_HAS_ERP_VALUE)
+	{
+		dst->erp_value = src->erp_value;
+		dst->berp_info_valid = src->berp_info_valid = true;
+	}
+	dst->beacon_interval = src->beacon_interval;
+	dst->listen_interval = src->listen_interval;
+	dst->atim_window = src->atim_window;
+	dst->dtim_period = src->dtim_period;
+	dst->dtim_data = src->dtim_data;
+	dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
+	dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
+	memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters));
+	
+        dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
+	dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
+	dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen;
+	memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen);
+	dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen;
+	memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen);
+	dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
+	dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
+	dst->broadcom_cap_exist = src->broadcom_cap_exist;
+	dst->ralink_cap_exist = src->ralink_cap_exist;
+	dst->atheros_cap_exist = src->atheros_cap_exist;
+	dst->realtek_cap_exit = src->realtek_cap_exit;
+	dst->marvell_cap_exist = src->marvell_cap_exist;
+	dst->cisco_cap_exist = src->cisco_cap_exist;
+	dst->unknown_cap_exist = src->unknown_cap_exist;
+	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
+	dst->wpa_ie_len = src->wpa_ie_len;
+	memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
+	dst->rsn_ie_len = src->rsn_ie_len;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len);
+	dst->wzc_ie_len = src->wzc_ie_len;
+#endif
+
+	dst->last_scanned = jiffies;
+	/* qos related parameters */
+	qos_active = dst->qos_data.active;
+	old_param = dst->qos_data.param_count;
+#if 0
+	if(dst->flags & NETWORK_HAS_QOS_MASK){
+	}
+	else {
+		dst->qos_data.supported = src->qos_data.supported;
+		dst->qos_data.param_count = src->qos_data.param_count;
+	}
+#else
+	dst->qos_data.supported = src->qos_data.supported;
+	if(dst->flags & NETWORK_HAS_QOS_PARAMETERS){
+		memcpy(&dst->qos_data, &src->qos_data, sizeof(struct rtllib_qos_data));
+	}
+#endif	
+	if(dst->qos_data.supported == 1) {
+		if(dst->ssid_len)
+			RTLLIB_DEBUG_QOS
+				("QoS the network %s is QoS supported\n",
+				dst->ssid);
+		else 
+			RTLLIB_DEBUG_QOS
+				("QoS the network is QoS supported\n");
+	}
+	dst->qos_data.active = qos_active;
+	dst->qos_data.old_param_count = old_param;
+
+	/* dst->last_associate is not overwritten */
+	dst->wmm_info = src->wmm_info; 
+	if(src->wmm_param[0].ac_aci_acm_aifsn|| \
+	   src->wmm_param[1].ac_aci_acm_aifsn|| \
+	   src->wmm_param[2].ac_aci_acm_aifsn|| \
+	   src->wmm_param[1].ac_aci_acm_aifsn) {
+	  memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
+	}
+
+	dst->SignalStrength = src->SignalStrength;
+	dst->RSSI = src->RSSI;	
+#ifdef THOMAS_TURBO
+	dst->Turbo_Enable = src->Turbo_Enable;
+#endif
+
+#ifdef ENABLE_DOT11D
+	dst->CountryIeLen = src->CountryIeLen;
+	memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
+#endif
+
+	dst->bWithAironetIE = src->bWithAironetIE;
+	dst->bCkipSupported = src->bCkipSupported;
+	memcpy(dst->CcxRmState,src->CcxRmState,2);
+	dst->bCcxRmEnable = src->bCcxRmEnable;
+	dst->MBssidMask = src->MBssidMask;
+	dst->bMBssidValid = src->bMBssidValid;
+	memcpy(dst->MBssid,src->MBssid,6);
+	dst->bWithCcxVerNum = src->bWithCcxVerNum;
+	dst->BssCcxVerNumber = src->BssCcxVerNumber;
+
+}
+static inline int is_beacon(__le16 fc) 
+{
+	return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == RTLLIB_STYPE_BEACON);
+}
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) 
+u8 AsocEntry_ComputeSum(u8 *paddr)
+{
+	u32 sum;
+
+	sum =	paddr[0]+
+			paddr[1]+
+			paddr[2]+
+			paddr[3]+
+			paddr[4]+
+			paddr[5];
+
+	return (u8)(sum % PEER_MAX_ASSOC);
+}
+u8 AsocEntry_AssignAvailableAID(struct rtllib_device *ieee, u8 *paddr)
+{
+	int		i;
+	
+	for(i = 0; i < PEER_MAX_ASSOC; i++)
+	{
+		if(ieee->AvailableAIDTable[i] == 99)
+		{
+			ieee->AvailableAIDTable[i] = AsocEntry_ComputeSum(paddr);
+			return i+1;
+		}
+	}
+
+	return 1;
+}
+
+void InitStaInfo(struct rtllib_device *ieee,int index)
+{
+	int idx = index;
+	ieee->peer_assoc_list[idx]->StaDataRate = 0;
+	ieee->peer_assoc_list[idx]->StaSS = 0;
+	ieee->peer_assoc_list[idx]->RetryFrameCnt = 0;
+	ieee->peer_assoc_list[idx]->NoRetryFrameCnt = 0;
+	ieee->peer_assoc_list[idx]->LastRetryCnt = 0;
+	ieee->peer_assoc_list[idx]->LastNoRetryCnt = 0;
+	ieee->peer_assoc_list[idx]->AvgRetryRate = 0;
+	ieee->peer_assoc_list[idx]->LastRetryRate = 0;
+	ieee->peer_assoc_list[idx]->txRateIndex = 11;
+	ieee->peer_assoc_list[idx]->APDataRate = 0x2; 
+	ieee->peer_assoc_list[idx]->ForcedDataRate = 0x2; 
+
+}
+static u8 IsStaInfoExist(struct rtllib_device *ieee, u8 *addr)
+{
+	int k=0;
+	struct sta_info * psta = NULL;
+	u8 sta_idx = PEER_MAX_ASSOC;
+	
+	for(k=0; k<PEER_MAX_ASSOC; k++)
+	{
+		psta = ieee->peer_assoc_list[k];
+		if(NULL != psta)
+		{
+			if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0)
+			{
+				sta_idx = k;
+				break;
+			}
+		}
+	}
+	return sta_idx;
+}
+static u8 GetFreeStaInfoIdx(struct rtllib_device *ieee, u8 *addr)
+{
+	int k = 0;
+	while((ieee->peer_assoc_list[k] != NULL) && (k < PEER_MAX_ASSOC))
+		k++;
+	printk("%s: addr:"MAC_FMT" index: %d\n", __FUNCTION__, MAC_ARG(addr), k);
+	return k;
+}
+struct sta_info *GetStaInfo(struct rtllib_device *ieee, u8 *addr)
+{
+	int k=0;
+	struct sta_info * psta = NULL;
+	struct sta_info * psta_find = NULL;
+	
+	for(k=0; k<PEER_MAX_ASSOC; k++)
+	{
+		psta = ieee->peer_assoc_list[k];
+		if(NULL != psta)
+		{
+			if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0)
+			{
+				psta_find = psta;
+				break;
+			}
+		}
+	}
+	return psta_find;
+}
+void DelStaInfoList(struct rtllib_device *ieee)
+{
+	int idx = 0;
+	struct sta_info * AsocEntry = NULL;
+
+	atomic_set(&ieee->AsocEntryNum, 0);
+	for(idx=0; idx<PEER_MAX_ASSOC; idx++){
+		AsocEntry = ieee->peer_assoc_list[idx];
+		if(NULL != AsocEntry){
+			kfree(AsocEntry);
+			ieee->peer_assoc_list[idx] = NULL;
+		}
+		ieee->AvailableAIDTable[idx] = 99;
+	}
+}	
+void DelStaInfo(struct rtllib_device *ieee, u8 *addr)
+{
+	struct sta_info * psta = NULL;
+	int k=0;
+	
+	for(k=0; k<PEER_MAX_ASSOC; k++)
+	{
+		psta = ieee->peer_assoc_list[k];
+		if(NULL != psta){
+			if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0){
+				if (psta->aid > 0 && psta->aid-1 < PEER_MAX_ASSOC)
+					ieee->AvailableAIDTable[psta->aid-1] = 99;
+				else
+					printk("%s(): clear non-existing entry AID\n", __func__);
+				
+				kfree(psta);
+				ieee->peer_assoc_list[k] = NULL;
+				atomic_dec(&ieee->AsocEntryNum);
+			}
+		}
+	}
+}
+void IbssAgeFunction(struct rtllib_device *ieee)
+{
+	struct sta_info*	AsocEntry = NULL;
+	int				idx;
+	unsigned long		CurrentTime;
+	signed long		TimeDifference;
+	struct rtllib_network *target;
+
+	CurrentTime = jiffies;
+
+	for(idx = 0; idx < PEER_MAX_ASSOC; idx++)
+	{
+		AsocEntry = ieee->peer_assoc_list[idx];
+		if(AsocEntry)
+		{
+			TimeDifference = jiffies_to_msecs(CurrentTime - AsocEntry->LastActiveTime);
+
+			if(TimeDifference > 20000)
+			{
+				printk("IbssAgeFunction(): "MAC_FMT" timeout\n", MAC_ARG(AsocEntry->macaddr));
+#ifdef RTL8192S_WAPI_SUPPORT
+				if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable))
+				{
+					WapiReturnOneStaInfo(ieee, AsocEntry->macaddr, 0);
+				}
+#endif	
+				kfree(AsocEntry);
+				ieee->peer_assoc_list[idx] = NULL;
+				atomic_dec(&ieee->AsocEntryNum);
+			
+				if(atomic_read(&ieee->AsocEntryNum) == 0){
+
+					down(&ieee->wx_sem);
+					rtllib_stop_protocol(ieee,true);
+	
+					list_for_each_entry(target, &ieee->network_list, list) {
+						if (is_same_network(target, &ieee->current_network,(target->ssid_len?1:0))){
+							printk("delete sta of previous Ad-hoc\n");
+							list_del(&target->list);
+							break;
+						}
+					}
+					
+					rtllib_start_protocol(ieee);
+					up(&ieee->wx_sem);
+				}else{
+#if defined (RTL8192S_WAPI_SUPPORT)
+					if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+						WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+					}
+#endif
+				}
+			}
+		}
+	}
+	
+#ifdef TO_DO_LIST
+	if(AsocEntry_AnyStationAssociated(pMgntInfo)==false)
+		DrvIFIndicateDisassociation(Adapter, unspec_reason);
+
+	if(pMgntInfo->dot11CurrentWirelessMode == WIRELESS_MODE_G ||
+		(IS_WIRELESS_MODE_N_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK)	)
+	{
+		if(nBModeStaCnt == 0)
+		{
+			pMgntInfo->bUseProtection = false;
+			ActUpdate_mCapInfo(Adapter, pMgntInfo->mCap);
+		}
+	}
+
+	if(IS_WIRELESS_MODE_N_24G(Adapter) || IS_WIRELESS_MODE_N_5G(Adapter) )
+	{
+		if(nLegacyStaCnt > 0)
+		{
+			pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_MIXED;
+		}
+		else
+		{
+			if((pMgntInfo->pHTInfo->bCurBW40MHz) && (n20MHzStaCnt > 0))
+				pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_40MHZ_PROTECT;
+			else
+				pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_NO_PROTECT;
+				
+		}
+	}
+
+	if(IS_WIRELESS_MODE_G(Adapter) ||
+		(IS_WIRELESS_MODE_N_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK))
+	{
+		if(pMgntInfo->bUseProtection)
+		{
+			u8 CckRate[4] = { MGN_1M, MGN_2M, MGN_5_5M, MGN_11M };
+			OCTET_STRING osCckRate;
+			FillOctetString(osCckRate, CckRate, 4);
+			FilterSupportRate(pMgntInfo->mBrates, &osCckRate, false);
+			Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_BASIC_RATE, (pu1Byte)&osCckRate);
+		}
+		else
+		{
+			Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_BASIC_RATE, (pu1Byte)(&pMgntInfo->mBrates) );
+		}
+	}
+#endif
+}
+#endif
+
+static int IsPassiveChannel( struct rtllib_device *rtllib, u8 channel)
+{
+	if (MAX_CHANNEL_NUMBER < channel) {
+		printk("%s(): Invalid Channel\n", __FUNCTION__);
+		return 0;
+	}
+
+	if(rtllib->active_channel_map[channel] == 2)
+		return 1;
+
+	return 0;
+}
+
+int IsLegalChannel( struct rtllib_device *rtllib, u8 channel)
+{
+	if (MAX_CHANNEL_NUMBER < channel) {
+		printk("%s(): Invalid Channel\n", __FUNCTION__);
+		return 0;
+	}
+	if (rtllib->active_channel_map[channel] > 0)
+		return 1;
+
+	return 0;
+}
+
+
+static inline void rtllib_process_probe_response(
+	struct rtllib_device *ieee,
+	struct rtllib_probe_response *beacon,
+	struct rtllib_rx_stats *stats)
+{
+	struct rtllib_network *target;
+	struct rtllib_network *oldest = NULL;
+#ifdef CONFIG_RTLLIB_DEBUG
+	struct rtllib_info_element *info_element = &beacon->info_element[0];
+#endif
+	unsigned long flags;
+	short renew;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+	struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network), GFP_ATOMIC);
+#else
+	struct rtllib_network *network = kmalloc(sizeof(*network), GFP_KERNEL);
+	memset(network,0,sizeof(*network));
+#endif
+
+	if (!network) {
+		return;
+	}
+
+#ifdef _RTL8192_EXT_PATCH_
+	if(ieee->ext_patch_rtllib_process_probe_response_1) {
+		/* 2 deonte the normal beacon packet,
+		 * discard it under mesh only mode  */
+		if(ieee->ext_patch_rtllib_process_probe_response_1(ieee, beacon, stats) != 2){
+			goto free_network;
+		} else if((ieee->iw_mode == IW_MODE_MESH)&&ieee->only_mesh) {
+			goto free_network;
+		}
+	}
+#endif
+
+	RTLLIB_DEBUG_SCAN(
+		"'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+		escape_essid(info_element->data, info_element->len),
+		MAC_ARG(beacon->header.addr3),
+		(beacon->capability & (1<<0xf)) ? '1' : '0',
+		(beacon->capability & (1<<0xe)) ? '1' : '0',
+		(beacon->capability & (1<<0xd)) ? '1' : '0',
+		(beacon->capability & (1<<0xc)) ? '1' : '0',
+		(beacon->capability & (1<<0xb)) ? '1' : '0',
+		(beacon->capability & (1<<0xa)) ? '1' : '0',
+		(beacon->capability & (1<<0x9)) ? '1' : '0',
+		(beacon->capability & (1<<0x8)) ? '1' : '0',
+		(beacon->capability & (1<<0x7)) ? '1' : '0',
+		(beacon->capability & (1<<0x6)) ? '1' : '0',
+		(beacon->capability & (1<<0x5)) ? '1' : '0',
+		(beacon->capability & (1<<0x4)) ? '1' : '0',
+		(beacon->capability & (1<<0x3)) ? '1' : '0',
+		(beacon->capability & (1<<0x2)) ? '1' : '0',
+		(beacon->capability & (1<<0x1)) ? '1' : '0',
+		(beacon->capability & (1<<0x0)) ? '1' : '0');
+
+	if (rtllib_network_init(ieee, beacon, network, stats)) {
+		RTLLIB_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+				     escape_essid(info_element->data,
+						  info_element->len),
+				     MAC_ARG(beacon->header.addr3),
+				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
+				     RTLLIB_STYPE_PROBE_RESP ?
+				     "PROBE RESPONSE" : "BEACON");
+		goto free_network;
+	}
+
+
+	if (!IsLegalChannel(ieee, network->channel))
+		goto free_network;
+
+	if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == RTLLIB_STYPE_PROBE_RESP) {
+		if (IsPassiveChannel(ieee, network->channel)) {
+			printk("GetScanInfo(): For Global Domain, "
+			       "filter probe response at channel(%d).\n", network->channel);
+			goto free_network;
+		}
+	} 
+
+	/* The network parsed correctly -- so now we scan our known networks
+	 * to see if we can find it in our list.
+	 *
+	 * NOTE:  This search is definitely not optimized.  Once its doing
+	 *        the "right thing" we'll optimize it for efficiency if
+	 *        necessary */
+
+	/* Search for this entry in the list and update it if it is
+	 * already there. */
+
+	spin_lock_irqsave(&ieee->lock, flags);
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(is_beacon(beacon->header.frame_ctl)){
+		if((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->state == RTLLIB_LINKED))
+		{
+			if((network->ssid_len == ieee->current_network.ssid_len) 
+				&& (!memcmp(network->ssid,ieee->current_network.ssid,ieee->current_network.ssid_len))
+				&& (network->channel == ieee->current_network.channel)
+				&& (ieee->current_network.channel > 0) 
+				&& (ieee->current_network.channel <= 14))
+			{
+				if(!memcmp(ieee->current_network.bssid,network->bssid,6))
+				{
+					int idx = 0;
+					struct rtllib_hdr_3addr* header = NULL;
+					int idx_exist = 0;
+					if(timer_pending(&ieee->ibss_wait_timer))
+						del_timer_sync(&ieee->ibss_wait_timer);
+					header = (struct rtllib_hdr_3addr*)&(beacon->header);
+					idx_exist = IsStaInfoExist(ieee,header->addr2);
+					if(idx_exist >= PEER_MAX_ASSOC) {
+						idx = GetFreeStaInfoIdx(ieee, header->addr2);
+					} else {
+						ieee->peer_assoc_list[idx_exist]->LastActiveTime = jiffies;
+						goto no_alloc;
+					}
+					if (idx >= PEER_MAX_ASSOC - 1) {
+						printk("\n%s():ERR!!!Buffer overflow - could not append!!!",__FUNCTION__);
+						goto free_network;
+					} else {
+						ieee->peer_assoc_list[idx] = (struct sta_info *)kmalloc(sizeof(struct sta_info), GFP_ATOMIC);
+						memset(ieee->peer_assoc_list[idx], 0, sizeof(struct sta_info));
+						ieee->peer_assoc_list[idx]->LastActiveTime = jiffies;
+						memcpy(ieee->peer_assoc_list[idx]->macaddr,header->addr2,ETH_ALEN);
+						ieee->peer_assoc_list[idx]->ratr_index = 8;
+						InitStaInfo(ieee,idx);
+						atomic_inc(&ieee->AsocEntryNum);
+						ieee->peer_assoc_list[idx]->aid = AsocEntry_AssignAvailableAID(ieee, ieee->peer_assoc_list[idx]->macaddr);
+						ieee->check_ht_cap(ieee->dev,ieee->peer_assoc_list[idx],network);
+						queue_delayed_work_rsl(ieee->wq, &ieee->update_assoc_sta_info_wq, 0);
+						ieee->Adhoc_InitRateAdaptive(ieee->dev,ieee->peer_assoc_list[idx]);
+					}
+#if defined (RTL8192S_WAPI_SUPPORT)
+					if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+						WapiCreateAppEventAndSend(ieee,NULL,0,header->addr2,false, false, false, 0, false);
+					}
+#endif
+				}
+				else
+				{
+#if 0
+					printk("%s(): SSID matched but BSSID mismatched.\n",__FUNCTION__);
+
+					ieee->TargetTsf = beacon->time_stamp[1];
+					ieee->TargetTsf <<= 32;
+					ieee->TargetTsf |= beacon->time_stamp[0];
+
+					ieee->CurrTsf = stats->TimeStampLow;
+
+					queue_delayed_work_rsl(ieee->wq, &ieee->check_tsf_wq, 0);
+#endif
+				}
+			}
+		}
+	}
+	if(ieee->iw_mode == IW_MODE_ADHOC){
+		if((network->ssid_len == ieee->current_network.ssid_len) 
+			&& (!memcmp(network->ssid,ieee->current_network.ssid,ieee->current_network.ssid_len))
+			&& (network->capability & WLAN_CAPABILITY_IBSS)
+			&& (ieee->state == RTLLIB_LINKED_SCANNING))
+		{
+			if(memcmp(ieee->current_network.bssid,network->bssid,6))
+			{
+				printk("%s(): SSID matched but BSSID mismatched.\n",__FUNCTION__);
+
+				ieee->TargetTsf = beacon->time_stamp[1];
+				ieee->TargetTsf <<= 32;
+				ieee->TargetTsf |= beacon->time_stamp[0];
+
+				ieee->CurrTsf = stats->TimeStampLow;
+
+				queue_delayed_work_rsl(ieee->wq, &ieee->check_tsf_wq, 0);
+			}
+		}
+	}
+#endif
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+no_alloc:
+	if(ieee->iw_mode == IW_MODE_INFRA)
+#endif
+	{
+		if(is_same_network(&ieee->current_network, network, (network->ssid_len?1:0))) {
+			update_network(&ieee->current_network, network);
+			if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
+			&& ieee->current_network.berp_info_valid){
+			if(ieee->current_network.erp_value& ERP_UseProtection)
+				ieee->current_network.buseprotection = true;
+		else
+			ieee->current_network.buseprotection = false;
+		}
+		if(is_beacon(beacon->header.frame_ctl))
+		{
+				if(ieee->state >= RTLLIB_LINKED)
+					ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
+			}
+#if 0 
+			else 
+				network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
+#endif                        
+		}
+	}
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	else if(ieee->iw_mode == IW_MODE_ADHOC)
+	{
+		ieee->current_network.last_scanned = jiffies;
+	}
+#endif
+	list_for_each_entry(target, &ieee->network_list, list) {
+		if (is_same_network(target, network,(target->ssid_len?1:0)))
+			break;
+		if ((oldest == NULL) ||
+		    (target->last_scanned < oldest->last_scanned))
+			oldest = target;
+	}
+
+	/* If we didn't find a match, then get a new network slot to initialize
+	 * with this beacon's information */
+	if (&target->list == &ieee->network_list) {
+		if (list_empty(&ieee->network_free_list)) {
+			/* If there are no more slots, expire the oldest */
+			list_del(&oldest->list);
+			target = oldest;
+			RTLLIB_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+					     "network list.\n",
+					     escape_essid(target->ssid,
+							  target->ssid_len),
+					     MAC_ARG(target->bssid));
+		} else {
+			/* Otherwise just pull from the free list */
+			target = list_entry(ieee->network_free_list.next,
+					    struct rtllib_network, list);
+			list_del(ieee->network_free_list.next);
+		}
+
+
+#ifdef CONFIG_RTLLIB_DEBUG
+		RTLLIB_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+				     escape_essid(network->ssid,
+						  network->ssid_len),
+				     MAC_ARG(network->bssid),
+				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
+				     RTLLIB_STYPE_PROBE_RESP ?
+				     "PROBE RESPONSE" : "BEACON");
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+		network->ext_entry = target->ext_entry;
+#endif	
+		memcpy(target, network, sizeof(*target));
+		list_add_tail(&target->list, &ieee->network_list);
+		if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
+			rtllib_softmac_new_net(ieee, network); 
+	} else {
+		RTLLIB_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+				     escape_essid(target->ssid,
+						  target->ssid_len),
+				     MAC_ARG(target->bssid),
+				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
+				     RTLLIB_STYPE_PROBE_RESP ?
+				     "PROBE RESPONSE" : "BEACON");
+		
+		/* we have an entry and we are going to update it. But this entry may
+		 * be already expired. In this case we do the same as we found a new 
+		 * net and call the new_net handler
+		 */
+		renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
+#if 0		
+		if(is_beacon(beacon->header.frame_ctl) == 0)
+			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
+		if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
+		    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
+		    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == RTLLIB_NOLINK))))
+			renew = 1;
+#else
+		if((!target->ssid_len) &&   
+			(((network->ssid_len > 0) && (target->hidden_ssid_len == 0)) 
+			|| ((ieee->current_network.ssid_len == network->ssid_len) && 
+			   (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && 
+			   (ieee->state == RTLLIB_NOLINK)))
+			) { 
+			renew = 1;
+		}
+#endif
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+			target->last_scanned = jiffies;
+		else
+			update_network(target, network);
+#else
+		update_network(target, network);
+#endif
+		if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
+			rtllib_softmac_new_net(ieee, network); 
+	}
+
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, network, (network->ssid_len?1:0))&&\
+		(ieee->state == RTLLIB_LINKED)) {
+		if(ieee->handle_beacon != NULL) {
+			ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
+		}	
+	}
+free_network:
+	kfree(network);
+	return;	
+}
+
+void rtllib_rx_mgt(struct rtllib_device *ieee,
+                      struct sk_buff *skb,
+		      struct rtllib_rx_stats *stats)
+{
+    struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ;
+#if 0
+    if(ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
+                ieee->iw_mode == IW_MODE_INFRA && 
+                ieee->state == RTLLIB_LINKED))
+    {       
+        tasklet_schedule(&ieee->ps_task);
+    }
+#endif
+    if(WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_PROBE_RESP &&
+            WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_BEACON)
+        ieee->last_rx_ps_time = jiffies;
+
+    switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+
+        case RTLLIB_STYPE_BEACON:
+            RTLLIB_DEBUG_MGMT("received BEACON (%d)\n",
+                    WLAN_FC_GET_STYPE(header->frame_ctl));
+            RTLLIB_DEBUG_SCAN("Beacon\n");
+            rtllib_process_probe_response(
+                    ieee, (struct rtllib_probe_response *)header, stats);
+			
+#ifdef ENABLE_LPS
+            if(ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
+                        ieee->iw_mode == IW_MODE_INFRA && 
+                        ieee->state == RTLLIB_LINKED))
+            {       
+                tasklet_schedule(&ieee->ps_task);
+            }
+#endif
+
+            break;
+
+        case RTLLIB_STYPE_PROBE_RESP:
+            RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
+                    WLAN_FC_GET_STYPE(header->frame_ctl));
+            RTLLIB_DEBUG_SCAN("Probe response\n");
+            rtllib_process_probe_response(
+                    ieee, (struct rtllib_probe_response *)header, stats);
+            break;
+        case RTLLIB_STYPE_PROBE_REQ:
+            RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n",
+                    WLAN_FC_GET_STYPE(header->frame_ctl));
+            RTLLIB_DEBUG_SCAN("Probe request\n");
+            if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
+                    ((ieee->iw_mode == IW_MODE_ADHOC ||
+                      ieee->iw_mode == IW_MODE_MASTER) &&
+                     ieee->state == RTLLIB_LINKED)){
+                rtllib_rx_probe_rq(ieee, skb);
+            }
+#ifdef _RTL8192_EXT_PATCH_
+			if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_mgt_on_probe_req )
+				ieee->ext_patch_rtllib_rx_mgt_on_probe_req( ieee, (struct rtllib_probe_request *)header, stats);
+#endif 
+            break;
+    }
+
+#if 0
+#ifdef CONFIG_CFG_80211 
+	if((rtllib_act_scanning(ieee,false) == true) && ((WLAN_FC_GET_STYPE(header->frame_ctl) ==RTLLIB_STYPE_PROBE_RESP) ||
+		(WLAN_FC_GET_STYPE(header->frame_ctl) ==RTLLIB_STYPE_BEACON)))
+		return ieee80211_scan_rx(ieee, skb, stats);
+#endif
+#endif
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_rx_mgt);
+EXPORT_SYMBOL_RSL(rtllib_rx);
+EXPORT_SYMBOL_RSL(IsLegalChannel);
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+EXPORT_SYMBOL_RSL(IbssAgeFunction);
+EXPORT_SYMBOL_RSL(GetStaInfo);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(rtllib_network_init);
+EXPORT_SYMBOL_RSL(rtllib_parse_info_param);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib.h
@@ -0,0 +1,4134 @@
+/*
+ * Merged with mainline rtllib.h in Aug 2004.  Original ieee802_11
+ * remains copyright by the original authors
+ *
+ * Portions of the merged code are based on Host AP (software wireless
+ * LAN access point) driver for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * Modified for Realtek's wi-fi cards by Andrea Merello
+ * <andreamrl@tiscali.it>
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+#ifndef RTLLIB_H
+#define RTLLIB_H
+#include <linux/if_ether.h> /* ETH_ALEN */
+#include <linux/kernel.h>   /* ARRAY_SIZE */
+#include <linux/version.h>
+#include <linux/module.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#include <linux/jiffies.h>
+#else
+#include <linux/jffs.h>
+#include <linux/tqueue.h>
+#endif
+#include <linux/timer.h>
+#include <linux/sched.h>
+
+#include <linux/delay.h>
+#include <linux/wireless.h>
+
+#ifdef CONFIG_CFG_80211 
+#include <net/cfg80211.h>
+#endif
+
+#include "rtl819x_HT.h"
+#include "rtl819x_BA.h"
+#include "rtl819x_TS.h"
+
+#include <linux/netdevice.h>
+#include <linux/if_arp.h> /* ARPHRD_ETHER */
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY		
+#endif
+#include <net/iw_handler.h>	
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+#include "wapi.h"
+#include "wapi_interface.h"
+#endif
+
+#ifndef RTK_DMP_PLATFORM
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+#ifndef bool
+typedef enum{false = 0, true} bool;
+#endif
+#endif
+#endif
+
+#ifndef IW_MODE_MONITOR
+#define IW_MODE_MONITOR 6
+#endif
+
+#ifndef IWEVCUSTOM
+#define IWEVCUSTOM 0x8c02
+#endif
+
+#ifndef IW_CUSTOM_MAX
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX	256	/* In bytes */
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define jiffies_to_msecs(t)  ((t) * 1000 / HZ)
+#ifndef __bitwise
+#define __bitwise __attribute__((bitwise))
+#endif
+typedef __u16  __le16;
+
+#if (WIRELESS_EXT < 16)
+struct iw_spy_data{
+	/* --- Standard spy support --- */
+	int 			spy_number;
+	u_char 			spy_address[IW_MAX_SPY][ETH_ALEN];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+	/* --- Enhanced spy support (event) */
+	struct iw_quality	spy_thr_low; /* Low threshold */
+	struct iw_quality	spy_thr_high; /* High threshold */
+	u_char			spy_thr_under[IW_MAX_SPY];
+}; 
+#endif
+#endif
+
+#ifndef container_of
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+#define skb_tail_pointer_rsl(skb) skb_tail_pointer(skb)
+#else
+#define skb_tail_pointer_rsl(skb) skb->tail
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+	#define EXPORT_SYMBOL_RSL(x) EXPORT_SYMBOL(x)
+#else
+	#define EXPORT_SYMBOL_RSL(x) EXPORT_SYMBOL_NOVERS(x)
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static inline void tq_init(struct tq_struct * task, void(*func)(void *), void *data)
+{
+	task->routine = func;
+	task->data 	= data;
+	INIT_LIST_HEAD(&task->list);
+	task->sync = 0;
+}
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+static inline void setup_timer(struct timer_list * timer, void(*function)(unsigned long), unsigned long data)
+{
+	timer->function = function;
+	timer->data 	= data;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	typedef struct delayed_work delayed_work_struct_rsl;
+	#define queue_delayed_work_rsl(x,y,z) queue_delayed_work(x,y,z)
+	#define INIT_DELAYED_WORK_RSL(x,y,z) INIT_DELAYED_WORK(x,y)
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40)
+	typedef struct tq_struct delayed_work_struct_rsl;
+	#define queue_delayed_work_rsl(x,y,z) schedule_task(y)
+	#define INIT_DELAYED_WORK_RSL(x,y,z) tq_init(x,y,z)
+#else
+	typedef struct work_struct delayed_work_struct_rsl;
+	#define queue_delayed_work_rsl(x,y,z) queue_delayed_work(x,y,z)
+	#define INIT_DELAYED_WORK_RSL(x,y,z) INIT_WORK(x,y,z)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	typedef struct work_struct work_struct_rsl;
+	#define queue_work_rsl(x,y) queue_work(x,y)
+	#define INIT_WORK_RSL(x,y,z) INIT_WORK(x,y)
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40)
+	typedef struct tq_struct work_struct_rsl;
+	#define queue_work_rsl(x,y) schedule_task(y)
+	#define INIT_WORK_RSL(x,y,z) tq_init(x,y,z)
+#else
+	typedef struct work_struct work_struct_rsl;
+	#define queue_work_rsl(x,y) queue_work(x,y)
+	#define INIT_WORK_RSL(x,y,z) INIT_WORK(x,y,z)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)	
+	#define container_of_work_rsl(x,y,z) container_of(x,y,z)
+	#define container_of_dwork_rsl(x,y,z) container_of(container_of(x, struct delayed_work, work), y, z) 
+#else
+	#define container_of_work_rsl(x,y,z) (x)
+	#define container_of_dwork_rsl(x,y,z) (x) 
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static inline char *
+iwe_stream_add_event_rsl(struct iw_request_info *info,
+			char *     stream,         /* Stream of events */
+			char *     ends,           /* End of stream */
+			struct iw_event *iwe,      /* Payload */
+			int        event_len)      /* Real size of payload */
+{
+        /* Check if it's possible */
+        if((stream + event_len) < ends) {
+                iwe->len = event_len;
+		ndelay(1);   
+                memcpy(stream, (char *) iwe, event_len);
+                stream += event_len;
+        }
+        return stream;
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+	#define iwe_stream_add_event_rsl(info,start,stop,iwe,len) iwe_stream_add_event(info,start,stop,iwe,len)
+#else
+	#define iwe_stream_add_event_rsl(info,start,stop,iwe,len) iwe_stream_add_event(start,stop,iwe,len)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+	#define iwe_stream_add_point_rsl(info,start,stop,iwe,p) iwe_stream_add_point(info,start,stop,iwe,p)
+#else
+	#define iwe_stream_add_point_rsl(info,start,stop,iwe,p) iwe_stream_add_point(start,stop,iwe,p)
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 
+	#define usb_alloc_urb_rsl(x,y) usb_alloc_urb(x,y)
+	#define usb_submit_urb_rsl(x,y) usb_submit_urb(x,y)
+#else
+	#define usb_alloc_urb_rsl(x,y) usb_alloc_urb(x)
+	#define usb_submit_urb_rsl(x,y) usb_submit_urb(x)
+#endif
+
+static inline void *netdev_priv_rsl(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 
+	return netdev_priv(dev);
+#else
+	return dev->priv;
+#endif
+}
+
+#define KEY_TYPE_NA		0x0
+#define KEY_TYPE_WEP40 		0x1
+#define KEY_TYPE_TKIP		0x2
+#define KEY_TYPE_CCMP		0x4
+#define KEY_TYPE_WEP104		0x5
+#if defined (RTL8192S_WAPI_SUPPORT)
+#define KEY_TYPE_SMS4		0x8
+#endif
+/* added for rtl819x tx procedure */
+#define MAX_QUEUE_SIZE		0x10
+
+#if defined(RTL8192SU) || defined(RTL8190P) ||defined(RTL8192U) ||defined(RTL8192E)
+#define BK_QUEUE                               0
+#define BE_QUEUE                               1
+#define VI_QUEUE                               2
+#define VO_QUEUE                               3
+#define HCCA_QUEUE                             4
+#define TXCMD_QUEUE                            5
+#define MGNT_QUEUE                             6
+#define HIGH_QUEUE                             7
+#define BEACON_QUEUE                           8
+#elif defined(RTL8192SE)
+#define BK_QUEUE                               0
+#define BE_QUEUE                               1
+#define VI_QUEUE                               2
+#define VO_QUEUE                               3
+#define BEACON_QUEUE                          4
+#define TXCMD_QUEUE                            5
+#define MGNT_QUEUE                             6
+#define HIGH_QUEUE                             7
+#define HCCA_QUEUE                             8
+
+#elif defined(RTL8192CE)
+
+#define BK_QUEUE						0		
+#define BE_QUEUE						1		
+#define VI_QUEUE						2		
+#define VO_QUEUE						3		
+#define BEACON_QUEUE				4		
+#define TXCMD_QUEUE						5		
+#define MGNT_QUEUE						6	
+#define HIGH_QUEUE						7	
+#define HCCA_QUEUE					8
+#endif
+
+#ifdef RTL8192CE
+#define LOW_QUEUE						BE_QUEUE
+#define NORMAL_QUEUE					MGNT_QUEUE
+#else
+#define LOW_QUEUE                              BE_QUEUE
+#define NORMAL_QUEUE                           MGNT_QUEUE
+#endif
+
+#ifndef IW_MODE_MESH 
+#define IW_MODE_MESH			7	
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+#define WIFI_MESH_TYPE	RTLLIB_FTYPE_DATA
+
+#define WLAN_MESH_HDR_LEN 6
+#define WLAN_MESH_HDR_6ADDR_LEN 18			
+#define WLAN_MESH_HDR_4ADDR_LEN 6			
+#define MAX_MP 						65			
+#define IEEE_MESH_MAC_HASH_SIZE 31
+#define MAX_MESH_ID_LEN 33
+#define MAX_HOST_NAME_LENGTH			33
+#endif
+#define AMSDU_SUBHEADER_LEN 14
+#define SWRF_TIMEOUT				50
+
+#define IE_CISCO_FLAG_POSITION		0x08	
+#define SUPPORT_CKIP_MIC			0x08	
+#define SUPPORT_CKIP_PK			0x10	
+#define	RT_RF_OFF_LEVL_ASPM			BIT0	
+#define	RT_RF_OFF_LEVL_CLK_REQ		BIT1	
+#define	RT_RF_OFF_LEVL_PCI_D3			BIT2	
+#define	RT_RF_OFF_LEVL_HALT_NIC		BIT3	
+#define	RT_RF_OFF_LEVL_FREE_FW		BIT4	
+#define	RT_RF_OFF_LEVL_FW_32K		BIT5	
+#define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT6	
+#define	RT_RF_LPS_DISALBE_2R			BIT30	
+#define	RT_RF_LPS_LEVEL_ASPM			BIT31	
+#define	RT_IN_PS_LEVEL(pPSC, _PS_FLAG)	((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
+#define	RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG)	(pPSC->CurPsLevel &= (~(_PS_FLAG)))
+#define	RT_SET_PS_LEVEL(pPSC, _PS_FLAG)	(pPSC->CurPsLevel |= _PS_FLAG)
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+#define SMS4_MIC_LEN                16
+#define WAPI_EXT_LEN                18
+#define MAX_WAPI_IE_LEN		255
+#define sMacHdrLng				24		
+#endif
+
+/* defined for skb cb field */
+/* At most 28 byte */
+typedef struct cb_desc {
+	/* Tx Desc Related flags (8-9) */
+	u8 bLastIniPkt:1;
+	u8 bCmdOrInit:1;
+	u8 bFirstSeg:1;
+	u8 bLastSeg:1;
+	u8 bEncrypt:1;
+	u8 bTxDisableRateFallBack:1;
+	u8 bTxUseDriverAssingedRate:1;
+	u8 bHwSec:1; 
+
+	u8 nStuckCount; 
+
+	/* Tx Firmware Relaged flags (10-11)*/
+	u8 bCTSEnable:1;
+	u8 bRTSEnable:1;
+	u8 bUseShortGI:1;
+	u8 bUseShortPreamble:1;
+	u8 bTxEnableFwCalcDur:1;
+	u8 bAMPDUEnable:1;
+	u8 bRTSSTBC:1;
+	u8 RTSSC:1;
+
+	u8 bRTSBW:1;
+	u8 bPacketBW:1;
+	u8 bRTSUseShortPreamble:1;
+	u8 bRTSUseShortGI:1;
+	u8 bMulticast:1;
+	u8 bBroadcast:1;
+	u8 drv_agg_enable:1;
+#ifdef _RTL8192_EXT_PATCH_
+	u8 mesh_pkt:1;
+#else
+	u8 reserved2:1;
+#endif
+
+	/* Tx Desc related element(12-19) */
+	u8 rata_index;
+	u8 queue_index;
+	u16 txbuf_size;
+	u8 RATRIndex;
+#ifdef _RTL8192_EXT_PATCH_
+	u8 mesh_type:2;
+	u8 bFromAggrQ:1;
+	u8 bAMSDU:1;
+	u8 brelay_pkt:1;
+	u8 badhoc:1;
+	u8 bretry_pkt:1;
+	u8 bFromRx:1;
+#else
+	u8 bAMSDU:1;
+	u8 bFromAggrQ:1;
+	u8 reserved6:6;
+#endif
+	u8 macId;
+	u8 priority;
+
+	/* Tx firmware related element(20-27) */
+	u8 data_rate;
+	u8 rts_rate;
+	u8 ampdu_factor;
+	u8 ampdu_density;
+	u8 DrvAggrNum;
+	u8 bdhcp;
+	u16 pkt_size;
+	u8 bIsSpecialDataFrame;
+}cb_desc, *pcb_desc;
+                        
+/*--------------------------Define -------------------------------------------*/
+#define MGN_1M                  0x02
+#define MGN_2M                  0x04
+#define MGN_5_5M                0x0b
+#define MGN_11M                 0x16
+
+#define MGN_6M                  0x0c
+#define MGN_9M                  0x12
+#define MGN_12M                 0x18
+#define MGN_18M                 0x24
+#define MGN_24M                 0x30
+#define MGN_36M                 0x48
+#define MGN_48M                 0x60
+#define MGN_54M                 0x6c
+
+#define MGN_MCS0                0x80
+#define MGN_MCS1                0x81
+#define MGN_MCS2                0x82
+#define MGN_MCS3                0x83
+#define MGN_MCS4                0x84
+#define MGN_MCS5                0x85
+#define MGN_MCS6                0x86
+#define MGN_MCS7                0x87
+#define MGN_MCS8                0x88
+#define MGN_MCS9                0x89
+#define MGN_MCS10               0x8a
+#define MGN_MCS11               0x8b
+#define MGN_MCS12               0x8c
+#define MGN_MCS13               0x8d
+#define MGN_MCS14               0x8e
+#define MGN_MCS15               0x8f
+#define	MGN_MCS0_SG			0x90
+#define	MGN_MCS1_SG			0x91
+#define	MGN_MCS2_SG			0x92
+#define	MGN_MCS3_SG			0x93
+#define	MGN_MCS4_SG			0x94
+#define	MGN_MCS5_SG			0x95
+#define	MGN_MCS6_SG			0x96
+#define	MGN_MCS7_SG			0x97
+#define	MGN_MCS8_SG			0x98
+#define	MGN_MCS9_SG			0x99
+#define	MGN_MCS10_SG		0x9a
+#define	MGN_MCS11_SG		0x9b
+#define	MGN_MCS12_SG		0x9c
+#define	MGN_MCS13_SG		0x9d
+#define	MGN_MCS14_SG		0x9e
+#define	MGN_MCS15_SG		0x9f
+
+
+enum	_ReasonCode{
+	unspec_reason	= 0x1,
+	auth_not_valid	= 0x2,
+	deauth_lv_ss	= 0x3, 
+	inactivity		= 0x4,
+	ap_overload 	= 0x5, 
+	class2_err		= 0x6,
+	class3_err		= 0x7, 
+	disas_lv_ss 	= 0x8,
+	asoc_not_auth	= 0x9,
+
+	mic_failure 	= 0xe,
+
+	invalid_IE		= 0x0d,
+	four_way_tmout	= 0x0f,
+	two_way_tmout	= 0x10,
+	IE_dismatch 	= 0x11,
+	invalid_Gcipher = 0x12,
+	invalid_Pcipher = 0x13,
+	invalid_AKMP	= 0x14,
+	unsup_RSNIEver = 0x15,
+	invalid_RSNIE	= 0x16,
+	auth_802_1x_fail= 0x17,
+	ciper_reject		= 0x18,
+
+	QoS_unspec		= 0x20, 
+	QAP_bandwidth	= 0x21, 
+	poor_condition	= 0x22, 
+	no_facility 	= 0x23, 
+	req_declined	= 0x25, 
+	invalid_param	= 0x26, 
+	req_not_honored= 0x27,	
+	TS_not_created	= 0x2F, 
+	DL_not_allowed	= 0x30, 
+	dest_not_exist	= 0x31, 
+	dest_not_QSTA	= 0x32, 
+};
+
+typedef enum _HAL_DEF_VARIABLE{
+	HAL_DEF_TPC_ENABLE,				
+	HAL_DEF_INIT_GAIN, 				
+	HAL_DEF_PROT_IMP_MODE,			
+	HAL_DEF_HIGH_POWER_MECHANISM,	
+	HAL_DEF_RATE_ADAPTIVE_MECHANISM,	
+	HAL_DEF_ANTENNA_DIVERSITY_MECHANISM,	
+	HAL_DEF_LED,					
+	HAL_DEF_CW_MAX_MIN,				
+	 
+	HAL_DEF_WOWLAN,
+	HAL_DEF_ENDPOINTS,				
+	HAL_DEF_MIN_TX_POWER_DBM,		
+	HAL_DEF_MAX_TX_POWER_DBM,		
+	HW_DEF_EFUSE_REPG_SECTION1_FLAG, 
+	HW_DEF_EFUSE_REPG_DATA, 
+	HW_DEF_GPIO,
+	HAL_DEF_PCI_SUPPORT_ASPM,		
+	HAL_DEF_THERMAL_VALUE,
+      HAL_DEF_USB_IN_TOKEN_REV, 
+}HAL_DEF_VARIABLE;
+
+
+typedef enum _HW_VARIABLES{
+	HW_VAR_ETHER_ADDR,
+	HW_VAR_MULTICAST_REG,		
+	HW_VAR_BASIC_RATE,
+	HW_VAR_BSSID,
+	HW_VAR_MEDIA_STATUS,
+	HW_VAR_SECURITY_CONF,
+	HW_VAR_BEACON_INTERVAL,
+	HW_VAR_ATIM_WINDOW,	
+	HW_VAR_LISTEN_INTERVAL,
+	HW_VAR_CS_COUNTER,
+	HW_VAR_DEFAULTKEY0,
+	HW_VAR_DEFAULTKEY1,
+	HW_VAR_DEFAULTKEY2,
+	HW_VAR_DEFAULTKEY3,
+	HW_VAR_SIFS,
+	HW_VAR_DIFS,
+	HW_VAR_EIFS,
+	HW_VAR_SLOT_TIME,
+	HW_VAR_ACK_PREAMBLE,
+	HW_VAR_CW_CONFIG,
+	HW_VAR_CW_VALUES,
+	HW_VAR_RATE_FALLBACK_CONTROL,
+	HW_VAR_CONTENTION_WINDOW,
+	HW_VAR_RETRY_COUNT,
+	HW_VAR_TR_SWITCH,
+	HW_VAR_COMMAND,			
+	HW_VAR_WPA_CONFIG,		
+	HW_VAR_AMPDU_MIN_SPACE,	
+	HW_VAR_SHORTGI_DENSITY,	
+	HW_VAR_AMPDU_FACTOR,
+	HW_VAR_MCS_RATE_AVAILABLE,
+	HW_VAR_AC_PARAM,			
+	HW_VAR_ACM_CTRL,			
+	HW_VAR_DIS_Req_Qsize,		
+	HW_VAR_CCX_CHNL_LOAD,		
+	HW_VAR_CCX_NOISE_HISTOGRAM,	
+	HW_VAR_CCX_CLM_NHM,			
+	HW_VAR_TxOPLimit,				
+	HW_VAR_TURBO_MODE,			
+	HW_VAR_RF_STATE, 			
+	HW_VAR_RF_OFF_BY_HW,		
+	HW_VAR_BUS_SPEED, 		
+        HW_VAR_SET_DEV_POWER,	
+
+	HW_VAR_RCR,				
+	HW_VAR_RATR_0,
+	HW_VAR_RRSR,
+	HW_VAR_CPU_RST,
+	HW_VAR_CECHK_BSSID,
+        HW_VAR_LBK_MODE,			
+	HW_VAR_AES_11N_FIX,
+	HW_VAR_USB_RX_AGGR,
+	HW_VAR_USER_CONTROL_TURBO_MODE,
+	HW_VAR_RETRY_LIMIT,
+	HW_VAR_INIT_TX_RATE,  
+	HW_VAR_TX_RATE_REG,  
+	HW_VAR_EFUSE_USAGE, 
+	HW_VAR_EFUSE_BYTES,
+	HW_VAR_AUTOLOAD_STATUS, 
+	HW_VAR_RF_2R_DISABLE, 
+	HW_VAR_SET_RPWM,
+	HW_VAR_H2C_FW_PWRMODE, 
+	HW_VAR_H2C_FW_JOINBSSRPT, 
+	HW_VAR_1X1_RECV_COMBINE,	
+	HW_VAR_STOP_SEND_BEACON,
+	HW_VAR_TSF_TIMER,			
+	HW_VAR_IO_CMD,
+	HW_VAR_HANDLE_FW_C2H,		
+	HW_VAR_DL_FW_RSVD_PAGE, 		
+	HW_VAR_AID,				
+	HW_VAR_HW_SEQ_ENABLE,		
+	HW_VAR_CORRECT_TSF,			
+	HW_VAR_BCN_VALID,				
+	HW_VAR_FWLPS_RF_ON,			
+	HW_VAR_DUAL_TSF_RST,			
+        HW_VAR_H2C_FW_UPDATE_GTK, 
+        HW_VAR_WF_MASK,	
+	HW_VAR_WF_CRC,	
+	HW_VAR_WF_IS_MAC_ADDR, 
+	HW_VAR_H2C_FW_OFFLOAD, 
+	HW_VAR_RESET_WFCRC, 
+	HW_VAR_SWITCH_EPHY_WoWLAN, 
+}HW_VARIABLES;
+
+
+#define aSifsTime	 (((priv->rtllib->current_network.mode == IEEE_A)||(priv->rtllib->current_network.mode == IEEE_N_24G)||(priv->rtllib->current_network.mode == IEEE_N_5G))? 16 : 10)
+
+#define MGMT_QUEUE_NUM 5
+
+#define IEEE_CMD_SET_WPA_PARAM			1
+#define	IEEE_CMD_SET_WPA_IE			2
+#define IEEE_CMD_SET_ENCRYPTION			3
+#define IEEE_CMD_MLME				4
+
+#define IEEE_PARAM_WPA_ENABLED			1
+#define IEEE_PARAM_TKIP_COUNTERMEASURES		2
+#define IEEE_PARAM_DROP_UNENCRYPTED		3
+#define IEEE_PARAM_PRIVACY_INVOKED		4
+#define IEEE_PARAM_AUTH_ALGS			5
+#define IEEE_PARAM_IEEE_802_1X			6
+#define IEEE_PARAM_WPAX_SELECT			7
+#define IEEE_PROTO_WPA				1	
+#define IEEE_PROTO_RSN				2
+#define IEEE_WPAX_USEGROUP			0
+#define IEEE_WPAX_WEP40				1
+#define IEEE_WPAX_TKIP				2
+#define IEEE_WPAX_WRAP   			3
+#define IEEE_WPAX_CCMP				4
+#define IEEE_WPAX_WEP104			5
+
+#define IEEE_KEY_MGMT_IEEE8021X			1
+#define IEEE_KEY_MGMT_PSK			2
+
+#define IEEE_MLME_STA_DEAUTH			1
+#define IEEE_MLME_STA_DISASSOC			2
+
+
+#define IEEE_CRYPT_ERR_UNKNOWN_ALG		2
+#define IEEE_CRYPT_ERR_UNKNOWN_ADDR		3
+#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED	4
+#define IEEE_CRYPT_ERR_KEY_SET_FAILED		5
+#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED	6
+#define IEEE_CRYPT_ERR_CARD_CONF_FAILED		7
+#define	IEEE_CRYPT_ALG_NAME_LEN			16
+
+#define MAX_IE_LEN  0xff
+#ifdef _RTL8192_EXT_PATCH_
+#define ENABLE_NULL_PT_DEBUG
+#endif
+#ifdef ENABLE_NULL_PT_DEBUG
+#define RT_ASSERT_RET(_Exp)								\
+		if(!(_Exp))									\
+		{											\
+			printk("Rtl819x: ");					\
+                	printk( "Assertion failed! %s,%s,line=%d\n", \
+                	#_Exp,__FUNCTION__,__LINE__);          \
+			return;						\
+		}
+#define RT_ASSERT_RET_VALUE(_Exp,Ret)								\
+		if(!(_Exp))									\
+		{											\
+			printk("Rtl819x: ");					\
+                	printk( "Assertion failed! %s,%s,line=%d\n", \
+                	#_Exp,__FUNCTION__,__LINE__);          \
+			return (Ret);						\
+		}
+#else
+#define RT_ASSERT_RET(_Exp) do {} while(0)
+#define RT_ASSERT_RET_VALUE(_Exp,Ret) do {} while(0)
+#endif
+
+typedef struct ieee_param {
+	u32 cmd;
+	u8 sta_addr[ETH_ALEN];
+        union {
+		struct {
+			u8 name;
+			u32 value;
+		} wpa_param;
+		struct {
+			u32 len;
+			u8 reserved[32];
+			u8 data[0];
+		} wpa_ie;
+	        struct{
+			int command;
+    			int reason_code;
+		} mlme;
+		struct {
+			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
+			u8 set_tx;
+			u32 err;
+			u8 idx;
+			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+			u16 key_len;
+			u8 key[0];
+		} crypt;
+	} u;
+}ieee_param;
+
+
+#if WIRELESS_EXT < 17
+#define IW_QUAL_QUAL_INVALID   0x10
+#define IW_QUAL_LEVEL_INVALID  0x20
+#define IW_QUAL_NOISE_INVALID  0x40
+#define IW_QUAL_QUAL_UPDATED   0x1
+#define IW_QUAL_LEVEL_UPDATED  0x2
+#define IW_QUAL_NOISE_UPDATED  0x4
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9))
+#define MSECS(t)	(HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000)
+static inline unsigned long msleep_interruptible_rsl(unsigned int msecs)
+{
+         unsigned long timeout = MSECS(msecs) + 1;
+ 
+         while (timeout) {
+                 set_current_state(TASK_INTERRUPTIBLE);
+                 timeout = schedule_timeout(timeout);
+         }
+         return timeout;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,31))
+static inline void msleep(unsigned int msecs)
+{
+         unsigned long timeout = MSECS(msecs) + 1;
+ 
+         while (timeout) {
+                 set_current_state(TASK_UNINTERRUPTIBLE);
+                 timeout = schedule_timeout(timeout);
+         }
+}
+#endif
+#else
+#define MSECS(t) msecs_to_jiffies(t)
+#define msleep_interruptible_rsl  msleep_interruptible
+#endif
+
+#define RTLLIB_DATA_LEN		2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+   6.2.1.1.2.
+
+   The figure in section 7.1.2 suggests a body size of up to 2312
+   bytes is allowed, which is a bit confusing, I suspect this
+   represents the 2304 bytes of real data, plus a possible 8 bytes of
+   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
+#define RTLLIB_1ADDR_LEN 10
+#define RTLLIB_2ADDR_LEN 16
+#define RTLLIB_3ADDR_LEN 24
+#define RTLLIB_4ADDR_LEN 30
+#define RTLLIB_FCS_LEN    4
+#define RTLLIB_HLEN                  (RTLLIB_4ADDR_LEN)
+#define RTLLIB_FRAME_LEN             (RTLLIB_DATA_LEN + RTLLIB_HLEN)
+#define RTLLIB_MGMT_HDR_LEN 24
+#define RTLLIB_DATA_HDR3_LEN 24
+#define RTLLIB_DATA_HDR4_LEN 30
+
+#define MIN_FRAG_THRESHOLD     256U
+#define MAX_FRAG_THRESHOLD     2346U
+#define MAX_HT_DATA_FRAG_THRESHOLD 0x2000
+
+#define HT_AMSDU_SIZE_4K 3839
+#define HT_AMSDU_SIZE_8K 7935
+
+/* Frame control field constants */
+#define RTLLIB_FCTL_VERS		0x0003
+#define RTLLIB_FCTL_FTYPE		0x000c
+#define RTLLIB_FCTL_STYPE		0x00f0
+#define RTLLIB_FCTL_FRAMETYPE	0x00fc
+#define RTLLIB_FCTL_TODS		0x0100
+#define RTLLIB_FCTL_FROMDS		0x0200
+#define RTLLIB_FCTL_DSTODS		0x0300 
+#define RTLLIB_FCTL_MOREFRAGS	0x0400
+#define RTLLIB_FCTL_RETRY		0x0800
+#define RTLLIB_FCTL_PM		0x1000
+#define RTLLIB_FCTL_MOREDATA		0x2000
+#define RTLLIB_FCTL_WEP		0x4000
+#define RTLLIB_FCTL_ORDER		0x8000
+
+#define RTLLIB_FTYPE_MGMT		0x0000
+#define RTLLIB_FTYPE_CTL		0x0004
+#define RTLLIB_FTYPE_DATA		0x0008
+
+/* management */
+#define RTLLIB_STYPE_ASSOC_REQ	0x0000
+#define RTLLIB_STYPE_ASSOC_RESP 	0x0010
+#define RTLLIB_STYPE_REASSOC_REQ	0x0020
+#define RTLLIB_STYPE_REASSOC_RESP	0x0030
+#define RTLLIB_STYPE_PROBE_REQ	0x0040
+#define RTLLIB_STYPE_PROBE_RESP	0x0050
+#define RTLLIB_STYPE_BEACON		0x0080
+#define RTLLIB_STYPE_ATIM		0x0090
+#define RTLLIB_STYPE_DISASSOC	0x00A0
+#define RTLLIB_STYPE_AUTH		0x00B0
+#define RTLLIB_STYPE_DEAUTH		0x00C0
+#define RTLLIB_STYPE_MANAGE_ACT	0x00D0
+#ifdef _RTL8192_EXT_PATCH_
+/* added for mesh action frame type */
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+#define RTLLIB_STYPE_MESH_ACT        0x00F0
+#else
+#define RTLLIB_STYPE_MESH_ACT        RTLLIB_STYPE_MANAGE_ACT
+#endif
+#endif
+
+/* control */
+#define RTLLIB_STYPE_PSPOLL		0x00A0
+#define RTLLIB_STYPE_RTS		0x00B0
+#define RTLLIB_STYPE_CTS		0x00C0
+#define RTLLIB_STYPE_ACK		0x00D0
+#define RTLLIB_STYPE_CFEND		0x00E0
+#define RTLLIB_STYPE_CFENDACK	0x00F0
+#define RTLLIB_STYPE_BLOCKACK   0x0094
+
+/* data */
+#define RTLLIB_STYPE_DATA		0x0000
+#define RTLLIB_STYPE_DATA_CFACK	0x0010
+#define RTLLIB_STYPE_DATA_CFPOLL	0x0020
+#define RTLLIB_STYPE_DATA_CFACKPOLL	0x0030
+#define RTLLIB_STYPE_NULLFUNC	0x0040
+#define RTLLIB_STYPE_CFACK		0x0050
+#define RTLLIB_STYPE_CFPOLL		0x0060
+#define RTLLIB_STYPE_CFACKPOLL	0x0070
+#define RTLLIB_STYPE_QOS_DATA	0x0080 
+#define RTLLIB_STYPE_QOS_NULL	0x00C0
+
+#define RTLLIB_SCTL_FRAG		0x000F
+#define RTLLIB_SCTL_SEQ		0xFFF0
+
+/* QOS control */
+#define RTLLIB_QCTL_TID              0x000F
+
+#define	FC_QOS_BIT					BIT7
+#define IsDataFrame(pdu)			( ((pdu[0] & 0x0C)==0x08) ? true : false )
+#define	IsLegacyDataFrame(pdu)	(IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) )	
+#define IsQoSDataFrame(pframe)  ((*(u16*)pframe&(RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) == (RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA))
+#define Frame_Order(pframe)     (*(u16*)pframe&RTLLIB_FCTL_ORDER)
+#define SN_LESS(a, b)		(((a-b)&0x800)!=0)
+#define SN_EQUAL(a, b)	(a == b)
+#define MAX_DEV_ADDR_SIZE 8
+
+typedef enum _ACT_CATEGORY{
+        ACT_CAT_QOS = 1,
+        ACT_CAT_DLS = 2,
+        ACT_CAT_BA  = 3,
+        ACT_CAT_HT  = 7,
+        ACT_CAT_WMM = 17,
+#ifdef _RTL8192_EXT_PATCH_
+        ACT_CAT_MESH_PEERLINK_MGNT = 0x0f, 
+        ACT_CAT_MESH_LINK_METRIC = 0x10, 
+        ACT_CAT_MESH_PATH_SELECT = 0x11, 
+        ACT_CAT_MESH_INTERWORKING = 0x12, 
+        ACT_CAT_MESH_SECURITY_INFO = 35,
+#endif
+} ACT_CATEGORY, *PACT_CATEGORY;
+
+typedef enum _TS_ACTION{
+        ACT_ADDTSREQ = 0,
+        ACT_ADDTSRSP = 1,
+        ACT_DELTS    = 2,
+        ACT_SCHEDULE = 3,
+} TS_ACTION, *PTS_ACTION;
+
+typedef enum _BA_ACTION{
+        ACT_ADDBAREQ = 0,
+        ACT_ADDBARSP = 1,
+        ACT_DELBA    = 2,
+} BA_ACTION, *PBA_ACTION;
+#ifdef _RTL8192_EXT_PATCH_
+typedef enum _PEERLINK_ACTION{
+	ACT_PEERLINK_OPEN = 0,
+	ACT_PEERLINK_CONFIRM = 1,
+	ACT_PEERLINK_CLOSE =2,
+} PEERLINK_ACTION, *PPEERLINK_ACTION;
+
+typedef enum _LINK_METRIC_ACTION{
+	ACT_LINKMETRIC_REQ = 0,
+	ACT_LINKMETRIC_RSP = 1,
+} LINK_METRIC_ACTION, *PLINK_METRIC_ACTION;
+
+typedef enum _PATH_SELECT_ACTION{
+	ACT_PATH_REQ = 0,
+	ACT_PATH_REPLY = 1,
+	ACT_PATH_ERR =2,
+	ACT_RANN =3,
+} PATH_SELECT_ACTION, *PPATH_SELECT_ACTION;
+
+typedef enum _MESH_PEERING_PROTOCOL_VERSION_VALUE{
+	Mesh_Peering_Management_Protocol_V =42,
+	Abbreviated_Handshake_Protocol_V = 43,
+}MESH_PEERING_PROTOCOL_VERSION_VALUE;
+#endif
+
+typedef enum _InitialGainOpType{
+	IG_Backup=0,
+	IG_Restore,
+	IG_Max
+}InitialGainOpType;
+typedef enum _LED_CTL_MODE{
+        LED_CTL_POWER_ON = 1,
+        LED_CTL_LINK = 2,
+        LED_CTL_NO_LINK = 3,
+        LED_CTL_TX = 4,
+        LED_CTL_RX = 5,
+        LED_CTL_SITE_SURVEY = 6,
+        LED_CTL_POWER_OFF = 7,
+        LED_CTL_START_TO_LINK = 8,
+        LED_CTL_START_WPS = 9,
+        LED_CTL_STOP_WPS = 10,
+        LED_CTL_START_WPS_BOTTON = 11, 
+        LED_CTL_STOP_WPS_FAIL = 12, 
+	 LED_CTL_STOP_WPS_FAIL_OVERLAP = 13, 
+}LED_CTL_MODE;
+
+typedef enum _RT_RF_TYPE_DEF
+{
+	RF_1T2R = 0,
+	RF_2T4R,
+	RF_2T2R,
+	RF_1T1R,
+	RF_2T2R_GREEN,
+	RF_819X_MAX_TYPE
+}RT_RF_TYPE_DEF;
+
+typedef enum _WIRELESS_MODE {
+	WIRELESS_MODE_UNKNOWN = 0x00,
+	WIRELESS_MODE_A = 0x01,
+	WIRELESS_MODE_B = 0x02,
+	WIRELESS_MODE_G = 0x04,
+	WIRELESS_MODE_AUTO = 0x08,
+	WIRELESS_MODE_N_24G = 0x10,
+	WIRELESS_MODE_N_5G = 0x20
+} WIRELESS_MODE;
+
+typedef enum _NETWORK_TYPE{
+	WIRELESS_11B = 1,
+	WIRELESS_11G = 2,
+	WIRELESS_11A = 4,
+	WIRELESS_11N = 8
+} WIRELESS_NETWORK_TYPE;
+
+#define OUI_SUBTYPE_WMM_INFO		0
+#define OUI_SUBTYPE_WMM_PARAM	1
+#define OUI_SUBTYPE_QOS_CAPABI	5
+
+/* debug macros */
+#define CONFIG_RTLLIB_DEBUG
+#ifdef CONFIG_RTLLIB_DEBUG
+extern u32 rtllib_debug_level;
+#define RTLLIB_DEBUG(level, fmt, args...) \
+do { if (rtllib_debug_level & (level)) \
+  printk(KERN_DEBUG "rtllib: " fmt, ## args); } while (0)
+#define RTLLIB_DEBUG_DATA(level, data, datalen)	\
+	do{ if ((rtllib_debug_level & (level)) == (level))	\
+		{ 	\
+			int i;					\
+			u8* pdata = (u8*) data;			\
+			printk(KERN_DEBUG "rtllib: %s()\n", __FUNCTION__);	\
+			for(i=0; i<(int)(datalen); i++)			\
+			{						\
+				printk("%2.2x ", pdata[i]);		\
+				if ((i+1)%16 == 0) printk("\n");	\
+			}				\
+			printk("\n");			\
+		}					\
+	} while (0)		
+#else
+#define RTLLIB_DEBUG(level, fmt, args...) do {} while (0)
+#define RTLLIB_DEBUG_DATA(level, data, datalen) do {} while(0)
+#endif	/* CONFIG_RTLLIB_DEBUG */
+
+/* debug macros not dependent on CONFIG_RTLLIB_DEBUG */
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define RTLLIB_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry.  xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a RTLLIB_xxxx_DEBUG() macro definition for your
+ * classification, or use RTLLIB_DEBUG(RTLLIB_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/ipw then you do not have
+ * CONFIG_RTLLIB_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define RTLLIB_DL_INFO          (1<<0)
+#define RTLLIB_DL_WX            (1<<1)
+#define RTLLIB_DL_SCAN          (1<<2)
+#define RTLLIB_DL_STATE         (1<<3)
+#define RTLLIB_DL_MGMT          (1<<4)
+#define RTLLIB_DL_FRAG          (1<<5)
+#define RTLLIB_DL_EAP           (1<<6)
+#define RTLLIB_DL_DROP          (1<<7)
+
+#define RTLLIB_DL_TX            (1<<8)
+#define RTLLIB_DL_RX            (1<<9)
+
+#define RTLLIB_DL_HT		   (1<<10)  
+#define RTLLIB_DL_BA		   (1<<11)  
+#define RTLLIB_DL_TS		   (1<<12)  
+#define RTLLIB_DL_QOS           (1<<13)
+#define RTLLIB_DL_REORDER	   (1<<14)
+#define RTLLIB_DL_IOT	   (1<<15)
+#define RTLLIB_DL_IPS	   (1<<16)
+#define RTLLIB_DL_TRACE	   (1<<29)  
+#define RTLLIB_DL_DATA	   (1<<30)   
+#define RTLLIB_DL_ERR	   (1<<31)   
+#define RTLLIB_ERROR(f, a...) printk(KERN_ERR "rtllib: " f, ## a)
+#define RTLLIB_WARNING(f, a...) printk(KERN_WARNING "rtllib: " f, ## a)
+#define RTLLIB_DEBUG_INFO(f, a...)   RTLLIB_DEBUG(RTLLIB_DL_INFO, f, ## a)
+
+#define RTLLIB_DEBUG_WX(f, a...)     RTLLIB_DEBUG(RTLLIB_DL_WX, f, ## a)
+#define RTLLIB_DEBUG_SCAN(f, a...)   RTLLIB_DEBUG(RTLLIB_DL_SCAN, f, ## a)
+#define RTLLIB_DEBUG_STATE(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_STATE, f, ## a)
+#define RTLLIB_DEBUG_MGMT(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_MGMT, f, ## a)
+#define RTLLIB_DEBUG_FRAG(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_FRAG, f, ## a)
+#define RTLLIB_DEBUG_EAP(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_EAP, f, ## a)
+#define RTLLIB_DEBUG_DROP(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_DROP, f, ## a)
+#define RTLLIB_DEBUG_TX(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_TX, f, ## a)
+#define RTLLIB_DEBUG_RX(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_RX, f, ## a)
+#define RTLLIB_DEBUG_QOS(f, a...)  RTLLIB_DEBUG(RTLLIB_DL_QOS, f, ## a)
+
+#ifdef CONFIG_RTLLIB_DEBUG
+/* Added by Annie, 2005-11-22. */
+#define MAX_STR_LEN     64
+/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/
+#define PRINTABLE(_ch)  (_ch>'!' && _ch<'~')    
+#define RTLLIB_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)                            	\
+                        if((_Comp) & level)   							\
+                        {                                                                       \
+                                int             __i;                                            \
+                                u8  buffer[MAX_STR_LEN];                                    	\
+                                int length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ;  	\
+                                memset(buffer, 0, MAX_STR_LEN);                      		\
+                                memcpy(buffer, (u8 *)_Ptr, length );            		\
+                                for( __i=0; __i<MAX_STR_LEN; __i++ )                            \
+                                {                                                               \
+                                     if( !PRINTABLE(buffer[__i]) )   buffer[__i] = '?';     	\
+                                }                                                               \
+                                buffer[length] = '\0';                                          \
+                                printk("Rtl819x: ");                                         	\
+                                printk(_TitleString);                                         \
+                                printk(": %d, <%s>\n", _Len, buffer);                         \
+                        }
+#else
+#define RTLLIB_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)  do {} while (0)
+#endif
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
+#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
+#endif /* ETH_P_PAE */
+
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+/* IEEE 802.11 defines */
+
+#define P80211_OUI_LEN 3
+
+struct rtllib_snap_hdr {
+
+        u8    dsap;   /* always 0xAA */
+        u8    ssap;   /* always 0xAA */
+        u8    ctrl;   /* always 0x03 */
+        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
+
+} __attribute__ ((packed));
+
+#define SNAP_SIZE sizeof(struct rtllib_snap_hdr)
+
+#define WLAN_FC_GET_VERS(fc) ((fc) & RTLLIB_FCTL_VERS)
+#define WLAN_FC_GET_TYPE(fc) ((fc) & RTLLIB_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc) ((fc) & RTLLIB_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc) ((fc) & RTLLIB_FCTL_MOREDATA)
+
+#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & RTLLIB_FCTL_FRAMETYPE)
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTLLIB_SCTL_FRAG)
+#define WLAN_GET_SEQ_SEQ(seq)  (((seq) & RTLLIB_SCTL_SEQ) >> 4)
+
+#ifndef CONFIG_CFG_80211
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_QOS (1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
+#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
+
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
+/* Status codes */
+enum rtllib_statuscode {
+        WLAN_STATUS_SUCCESS = 0,
+        WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
+        WLAN_STATUS_CAPS_UNSUPPORTED = 10,
+        WLAN_STATUS_REASSOC_NO_ASSOC = 11,
+        WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
+        WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
+        WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
+        WLAN_STATUS_CHALLENGE_FAIL = 15,
+        WLAN_STATUS_AUTH_TIMEOUT = 16,
+        WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+        WLAN_STATUS_ASSOC_DENIED_RATES = 18,
+        /* 802.11b */
+        WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
+        WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
+        WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
+        /* 802.11h */
+        WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
+        WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
+        WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
+        /* 802.11g */
+        WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
+        WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
+        /* 802.11i */
+        WLAN_STATUS_INVALID_IE = 40,
+        WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
+        WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
+        WLAN_STATUS_INVALID_AKMP = 43,
+        WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
+        WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
+        WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
+};
+
+/* Reason codes */
+enum rtllib_reasoncode {
+        WLAN_REASON_UNSPECIFIED = 1,
+        WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+        WLAN_REASON_DEAUTH_LEAVING = 3,
+        WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
+        WLAN_REASON_DISASSOC_AP_BUSY = 5,
+        WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+        WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+        WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
+        WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+        /* 802.11h */
+        WLAN_REASON_DISASSOC_BAD_POWER = 10,
+        WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
+        /* 802.11i */
+        WLAN_REASON_INVALID_IE = 13,
+        WLAN_REASON_MIC_FAILURE = 14,
+        WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
+        WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
+        WLAN_REASON_IE_DIFFERENT = 17,
+        WLAN_REASON_INVALID_GROUP_CIPHER = 18,
+        WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
+        WLAN_REASON_INVALID_AKMP = 20,
+        WLAN_REASON_UNSUPP_RSN_VERSION = 21,
+        WLAN_REASON_INVALID_RSN_IE_CAP = 22,
+        WLAN_REASON_IEEE8021X_FAILED = 23,
+        WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
+};
+#endif
+
+#define RTLLIB_STATMASK_SIGNAL (1<<0)
+#define RTLLIB_STATMASK_RSSI (1<<1)
+#define RTLLIB_STATMASK_NOISE (1<<2)
+#define RTLLIB_STATMASK_RATE (1<<3)
+#define RTLLIB_STATMASK_WEMASK 0x7
+
+#define RTLLIB_CCK_MODULATION    (1<<0)
+#define RTLLIB_OFDM_MODULATION   (1<<1)
+
+#define RTLLIB_24GHZ_BAND     (1<<0)
+#define RTLLIB_52GHZ_BAND     (1<<1)
+
+#define RTLLIB_CCK_RATE_LEN  		4
+#define RTLLIB_CCK_RATE_1MB		        0x02
+#define RTLLIB_CCK_RATE_2MB		        0x04
+#define RTLLIB_CCK_RATE_5MB		        0x0B
+#define RTLLIB_CCK_RATE_11MB		        0x16
+#define RTLLIB_OFDM_RATE_LEN 		8
+#define RTLLIB_OFDM_RATE_6MB		        0x0C
+#define RTLLIB_OFDM_RATE_9MB		        0x12
+#define RTLLIB_OFDM_RATE_12MB		0x18
+#define RTLLIB_OFDM_RATE_18MB		0x24
+#define RTLLIB_OFDM_RATE_24MB		0x30
+#define RTLLIB_OFDM_RATE_36MB		0x48
+#define RTLLIB_OFDM_RATE_48MB		0x60
+#define RTLLIB_OFDM_RATE_54MB		0x6C
+#define RTLLIB_BASIC_RATE_MASK		0x80
+
+#define RTLLIB_CCK_RATE_1MB_MASK		(1<<0)
+#define RTLLIB_CCK_RATE_2MB_MASK		(1<<1)
+#define RTLLIB_CCK_RATE_5MB_MASK		(1<<2)
+#define RTLLIB_CCK_RATE_11MB_MASK		(1<<3)
+#define RTLLIB_OFDM_RATE_6MB_MASK		(1<<4)
+#define RTLLIB_OFDM_RATE_9MB_MASK		(1<<5)
+#define RTLLIB_OFDM_RATE_12MB_MASK		(1<<6)
+#define RTLLIB_OFDM_RATE_18MB_MASK		(1<<7)
+#define RTLLIB_OFDM_RATE_24MB_MASK		(1<<8)
+#define RTLLIB_OFDM_RATE_36MB_MASK		(1<<9)
+#define RTLLIB_OFDM_RATE_48MB_MASK		(1<<10)
+#define RTLLIB_OFDM_RATE_54MB_MASK		(1<<11)
+
+#define RTLLIB_CCK_RATES_MASK	        0x0000000F
+#define RTLLIB_CCK_BASIC_RATES_MASK	(RTLLIB_CCK_RATE_1MB_MASK | \
+	RTLLIB_CCK_RATE_2MB_MASK)
+#define RTLLIB_CCK_DEFAULT_RATES_MASK	(RTLLIB_CCK_BASIC_RATES_MASK | \
+        RTLLIB_CCK_RATE_5MB_MASK | \
+        RTLLIB_CCK_RATE_11MB_MASK)
+
+#define RTLLIB_OFDM_RATES_MASK		0x00000FF0
+#define RTLLIB_OFDM_BASIC_RATES_MASK	(RTLLIB_OFDM_RATE_6MB_MASK | \
+	RTLLIB_OFDM_RATE_12MB_MASK | \
+	RTLLIB_OFDM_RATE_24MB_MASK)
+#define RTLLIB_OFDM_DEFAULT_RATES_MASK	(RTLLIB_OFDM_BASIC_RATES_MASK | \
+	RTLLIB_OFDM_RATE_9MB_MASK  | \
+	RTLLIB_OFDM_RATE_18MB_MASK | \
+	RTLLIB_OFDM_RATE_36MB_MASK | \
+	RTLLIB_OFDM_RATE_48MB_MASK | \
+	RTLLIB_OFDM_RATE_54MB_MASK)
+#define RTLLIB_DEFAULT_RATES_MASK (RTLLIB_OFDM_DEFAULT_RATES_MASK | \
+                                RTLLIB_CCK_DEFAULT_RATES_MASK)
+
+#define RTLLIB_NUM_OFDM_RATES	    8
+#define RTLLIB_NUM_CCK_RATES	            4
+#define RTLLIB_OFDM_SHIFT_MASK_A         4
+
+
+/* this is stolen and modified from the madwifi driver*/
+#define RTLLIB_FC0_TYPE_MASK		0x0c
+#define RTLLIB_FC0_TYPE_DATA		0x08
+#define RTLLIB_FC0_SUBTYPE_MASK	0xB0
+#define RTLLIB_FC0_SUBTYPE_QOS	0x80
+
+#define RTLLIB_QOS_HAS_SEQ(fc) \
+	(((fc) & (RTLLIB_FC0_TYPE_MASK | RTLLIB_FC0_SUBTYPE_MASK)) == \
+	 (RTLLIB_FC0_TYPE_DATA | RTLLIB_FC0_SUBTYPE_QOS))
+	
+/* this is stolen from ipw2200 driver */
+#define IEEE_IBSS_MAC_HASH_SIZE 31
+struct ieee_ibss_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num[17];
+	u16 frag_num[17];
+	unsigned long packet_time[17];
+	struct list_head list;
+};
+
+#ifdef _RTL8192_EXT_PATCH_
+struct ieee_mesh_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num[17];
+	u16 frag_num[17];
+	unsigned long packet_time[17];
+	struct list_head list;
+};
+#endif
+/* NOTE: This data is for statistical purposes; not all hardware provides this
+ *       information for frames received.  Not setting these will not cause
+ *       any adverse affects. */
+struct rtllib_rx_stats {
+#if 1
+	u32 mac_time[2];
+	s8  rssi;
+	u8  signal;
+	u8  noise;
+	u16 rate; /* in 100 kbps */
+	u8  received_channel;
+	u8  control;
+	u8  mask;
+	u8  freq;
+	u16 len;
+	u64 tsf;
+	u32 beacon_time;
+	u8  nic_type;
+	u16 Length;
+	u8  SignalQuality; 
+	s32 RecvSignalPower; 
+	s8  RxPower; 
+	u8  SignalStrength; 
+	u16 bHwError:1;
+	u16 bCRC:1;
+	u16 bICV:1;
+	u16 bShortPreamble:1;
+	u16 Antenna:1;      
+	u16 Decrypted:1;    
+	u16 Wakeup:1;       
+	u16 Reserved0:1;    
+	u8  AGC;
+	u32 TimeStampLow;
+	u32 TimeStampHigh;
+	bool bShift;
+	bool bIsQosData;             
+	u8   UserPriority;
+
+	u8    RxDrvInfoSize;
+	u8    RxBufShift;
+	bool  bIsAMPDU;
+	bool  bFirstMPDU;
+	bool  bContainHTC;
+	bool  RxIs40MHzPacket;
+	u32   RxPWDBAll;
+	u8    RxMIMOSignalStrength[4];        
+	s8    RxMIMOSignalQuality[2];
+	bool  bPacketMatchBSSID;
+	bool  bIsCCK;
+	bool  bPacketToSelf;
+	u8*    virtual_address;
+	u16    packetlength;        
+	u16    fraglength;          
+	u16    fragoffset;          
+	u16    ntotalfrag;
+	bool   bisrxaggrsubframe;
+	bool   bPacketBeacon;       
+	bool   bToSelfBA;	    
+	char   cck_adc_pwdb[4];	    
+	u16    Seq_Num;
+	u8     nTotalAggPkt;	    
+#ifdef TCP_CSUM_OFFLOAD_RX
+	u8	tcp_csum_valid;
+#endif
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8	WapiTempPN[16];
+	u8	WapiSrcAddr[6];
+	u8	bWapiCheckPNInDecrypt;
+#endif
+#endif
+
+};
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
+#define RTLLIB_FRAG_CACHE_LEN 4
+
+struct rtllib_frag_entry {
+	unsigned long first_frag_time;
+	unsigned int seq;
+	unsigned int last_frag;
+	struct sk_buff *skb;
+	u8 src_addr[ETH_ALEN];
+	u8 dst_addr[ETH_ALEN];
+};
+
+struct rtllib_stats {
+	unsigned int tx_unicast_frames;
+	unsigned int tx_multicast_frames;
+	unsigned int tx_fragments;
+	unsigned int tx_unicast_octets;
+	unsigned int tx_multicast_octets;
+	unsigned int tx_deferred_transmissions;
+	unsigned int tx_single_retry_frames;
+	unsigned int tx_multiple_retry_frames;
+	unsigned int tx_retry_limit_exceeded;
+	unsigned int tx_discards;
+	unsigned int rx_unicast_frames;
+	unsigned int rx_multicast_frames;
+	unsigned int rx_fragments;
+	unsigned int rx_unicast_octets;
+	unsigned int rx_multicast_octets;
+	unsigned int rx_fcs_errors;
+	unsigned int rx_discards_no_buffer;
+	unsigned int tx_discards_wrong_sa;
+	unsigned int rx_discards_undecryptable;
+	unsigned int rx_message_in_msg_fragments;
+	unsigned int rx_message_in_bad_msg_fragments;
+};
+
+struct rtllib_device;
+
+#include "rtllib_crypt.h"
+
+#define SEC_KEY_1         (1<<0)
+#define SEC_KEY_2         (1<<1)
+#define SEC_KEY_3         (1<<2)
+#define SEC_KEY_4         (1<<3)
+#define SEC_ACTIVE_KEY    (1<<4)
+#define SEC_AUTH_MODE     (1<<5)
+#define SEC_UNICAST_GROUP (1<<6)
+#define SEC_LEVEL         (1<<7)
+#define SEC_ENABLED       (1<<8)
+#define SEC_ENCRYPT       (1<<9)
+
+#define SEC_LEVEL_0      0 /* None */
+#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
+#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
+
+#define SEC_ALG_NONE            0
+#define SEC_ALG_WEP             1
+#define SEC_ALG_TKIP            2
+#define SEC_ALG_CCMP            4
+
+#define WEP_KEYS 		4
+#define WEP_KEY_LEN		13
+#define SCM_KEY_LEN             32
+#define SCM_TEMPORAL_KEY_LENGTH 16
+
+struct rtllib_security {
+	u16 active_key:2,
+            enabled:1,
+	    auth_mode:2,
+            auth_algo:4,
+            unicast_uses_group:1,
+	    encrypt:1;
+	u8 key_sizes[WEP_KEYS];
+	u8 keys[WEP_KEYS][SCM_KEY_LEN];
+	u8 level;
+	u16 flags;
+} __attribute__ ((packed));
+
+
+/*
+ 802.11 data frame from AP
+      ,-------------------------------------------------------------------.
+Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+      |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
+      |      | tion | (BSSID) |         |         | ence |  data   |      |
+      `-------------------------------------------------------------------'
+Total: 28-2340 bytes
+*/
+
+/* Management Frame Information Element Types */
+enum rtllib_mfie {
+        MFIE_TYPE_SSID = 0,
+        MFIE_TYPE_RATES = 1,
+        MFIE_TYPE_FH_SET = 2,
+        MFIE_TYPE_DS_SET = 3,
+        MFIE_TYPE_CF_SET = 4,
+        MFIE_TYPE_TIM = 5,
+        MFIE_TYPE_IBSS_SET = 6,
+        MFIE_TYPE_COUNTRY = 7,
+        MFIE_TYPE_HOP_PARAMS = 8,
+        MFIE_TYPE_HOP_TABLE = 9,
+        MFIE_TYPE_REQUEST = 10,
+        MFIE_TYPE_CHALLENGE = 16,
+        MFIE_TYPE_POWER_CONSTRAINT = 32,
+        MFIE_TYPE_POWER_CAPABILITY = 33,
+        MFIE_TYPE_TPC_REQUEST = 34,
+        MFIE_TYPE_TPC_REPORT = 35,
+        MFIE_TYPE_SUPP_CHANNELS = 36,
+        MFIE_TYPE_CSA = 37,
+        MFIE_TYPE_MEASURE_REQUEST = 38,
+        MFIE_TYPE_MEASURE_REPORT = 39,
+        MFIE_TYPE_QUIET = 40,
+        MFIE_TYPE_IBSS_DFS = 41,
+        MFIE_TYPE_ERP = 42,
+	MFIE_TYPE_HT_CAP= 45,
+	MFIE_TYPE_RSN = 48,
+	MFIE_TYPE_RATES_EX = 50,
+#ifdef _RTL8192_EXT_PATCH_
+	MFIE_TYPE_MESH_PANN = 51,
+	MFIE_TYPE_MESH_RANN = 52,
+	MFIE_TYPE_MESH_PATH_REQ = 138, 
+	MFIE_TYPE_MESH_PATH_REP = 139, 
+	MFIE_TYPE_MESH_PATH_ERR = 140, 
+#endif
+	MFIE_TYPE_HT_INFO= 61,
+#if defined (RTL8192S_WAPI_SUPPORT)
+	MFIE_TYPE_WAPI	= 68,
+#endif
+	MFIE_TYPE_AIRONET=133,
+#ifdef _RTL8192_EXT_PATCH_
+	MFIE_TYPE_MESH_CONFIGURATION = 121, 
+	MFIE_TYPE_MESH_ID = 122, 
+	MFIE_TYPE_MESH_LOCAL_LINK_STATE_ANNOU = 138,   
+	MFIE_TYPE_MESH_ABBR_HANDSHAKE_IE_	=139,  
+	MFIE_TYPE_MESH_PEER_LINK_MGNT = 125, 
+	MFIE_TYPE_MESH_NEIGHBOR_LIST = 142,     
+	MFIE_TYPE_MESH_TIM = 143,     
+	MFIE_TYPE_MESH_ATIM_WINDOW = 144,     
+	MFIE_TYPE_MESH_BEACON_TIMING = 145,     
+	MFIE_TYPE_MESH_MDAOP_ADVERTISMENTS = 148,   
+	MFIE_TYPE_MESH_MSC = 149, 
+	MFIE_TYPE_MESH_MSA = 150, 
+	MFIE_TYPE_MESH_MOAOP_SET_TEARDOWN = 212,   
+#endif
+	MFIE_TYPE_GENERIC = 221,
+        MFIE_TYPE_QOS_PARAMETER = 222,
+};
+
+/* Minimal header; can be used for passing 802.11 frames with sufficient
+ * information to determine what type of underlying data type is actually
+ * stored in the data. */
+struct rtllib_pspoll_hdr {
+        __le16 frame_ctl;
+        __le16 aid;
+	u8 bssid[ETH_ALEN];
+        u8 ta[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct rtllib_hdr {
+        __le16 frame_ctl;
+        __le16 duration_id;
+        u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_1addr {
+        __le16 frame_ctl;
+        __le16 duration_id;
+        u8 addr1[ETH_ALEN];
+        u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_2addr {
+        __le16 frame_ctl;
+        __le16 duration_id;
+        u8 addr1[ETH_ALEN];
+        u8 addr2[ETH_ALEN];
+        u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_3addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+        u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_4addr {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+        u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_3addrqos {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	__le16 qos_ctl;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_hdr_4addrqos {
+	__le16 frame_ctl;
+	__le16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	__le16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	__le16 qos_ctl;
+	u8 payload[0];
+} __attribute__ ((packed));
+
+struct rtllib_info_element {
+	u8 id;
+	u8 len;
+	u8 data[0];
+} __attribute__ ((packed));
+
+#ifdef _RTL8192_EXT_PATCH_
+
+struct mesh_peering_protocol_version_t{
+    u8 OUI[3]; 
+    u8 value;
+} __attribute__ ((packed));
+struct rtllib_plink_open {
+	struct rtllib_hdr_3addr header;
+	u8       category;
+	u8       action;
+#ifndef COMPATIBLE_WITH_RALINK_MESH
+	struct mesh_peering_protocol_version_t mesh_peering_protocol_version;
+#endif
+	__le16 capability;
+	/* SSID, supported rates, RSN */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_plink_confirm {
+	struct rtllib_hdr_3addr header;
+	u8       category;
+	u8       action;
+#ifndef COMPATIBLE_WITH_RALINK_MESH
+	struct mesh_peering_protocol_version_t mesh_peering_protocol_version;
+#endif
+	__le16 capability;
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+	__le16 status_code;
+#endif
+	__le16 aid;
+	/* SSID, supported rates, RSN */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_plink_close {
+	struct rtllib_hdr_3addr header;
+	u8       category;
+	u8       action;
+#ifndef COMPATIBLE_WITH_RALINK_MESH
+	struct mesh_peering_protocol_version_t mesh_peering_protocol_version;
+#endif
+	/* SSID, supported rates, RSN */
+	struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_linkmetric_report {
+	struct rtllib_hdr_3addr header;
+	u8       category;
+	u8       action;
+	struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_linkmetric_req {
+	struct rtllib_hdr_3addr header;
+	u8       category;
+	u8       action;
+} __attribute__ ((packed));
+#endif
+
+struct rtllib_authentication {
+	struct rtllib_hdr_3addr header;
+	__le16 algorithm;
+	__le16 transaction;
+	__le16 status;
+	/*challenge*/
+	struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_disauth {
+        struct rtllib_hdr_3addr header;
+        __le16 reason;
+} __attribute__ ((packed));
+
+struct rtllib_disassoc {
+        struct rtllib_hdr_3addr header;
+        __le16 reason;
+} __attribute__ ((packed));
+
+struct rtllib_probe_request {
+	struct rtllib_hdr_3addr header;
+	/* SSID, supported rates */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_probe_response {
+	struct rtllib_hdr_3addr header;
+	u32 time_stamp[2];
+	__le16 beacon_interval;
+	__le16 capability;
+        /* SSID, supported rates, FH params, DS params,
+         * CF params, IBSS params, TIM (if beacon), RSN */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+/* Alias beacon for probe_response */
+#define rtllib_beacon rtllib_probe_response
+
+struct rtllib_assoc_request_frame {
+	struct rtllib_hdr_3addr header;
+	__le16 capability;
+	__le16 listen_interval;
+	/* SSID, supported rates, RSN */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_reassoc_request_frame {
+	struct rtllib_hdr_3addr header;
+	__le16 capability;
+	__le16 listen_interval;
+	u8 current_ap[ETH_ALEN];
+	/* SSID, supported rates, RSN */
+        struct rtllib_info_element info_element[0];
+} __attribute__ ((packed));
+
+struct rtllib_assoc_response_frame {
+	struct rtllib_hdr_3addr header;
+	__le16 capability;
+	__le16 status;
+	__le16 aid;
+	struct rtllib_info_element info_element[0]; /* supported rates */
+} __attribute__ ((packed));
+
+struct rtllib_txb {
+	u8 nr_frags;
+	u8 encrypted;
+	u8 queue_index;
+	u8 rts_included;
+	u16 reserved;
+	__le16 frag_size;
+	__le16 payload_size;
+	struct sk_buff *fragments[0];
+};
+
+#define MAX_TX_AGG_COUNT		  16
+struct rtllib_drv_agg_txb {
+	u8 nr_drv_agg_frames;
+	struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
+}__attribute__((packed));
+
+#define MAX_SUBFRAME_COUNT 		  64
+struct rtllib_rxb {
+	u8 nr_subframes;
+	struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
+	u8 dst[ETH_ALEN];
+	u8 src[ETH_ALEN];
+#ifdef TCP_CSUM_OFFLOAD_RX
+	u8 tcp_csum_valid;
+#endif
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8 UserPriority;
+	u8 WapiTempPN[16];
+	u8 WapiSrcAddr[6];
+	u8 bWapiCheckPNInDecrypt;
+#endif
+}__attribute__((packed));
+
+typedef union _frameqos {
+	u16 shortdata;
+	u8  chardata[2];
+	struct {
+		u16 tid:4;
+		u16 eosp:1;
+		u16 ack_policy:2;
+		u16 reserved:1;
+		u16 txop:8;
+	}field;
+}frameqos,*pframeqos;
+
+/* SWEEP TABLE ENTRIES NUMBER*/
+#define MAX_SWEEP_TAB_ENTRIES		  42
+#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
+/* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
+ * only use 8, and then use extended rates for the remaining supported
+ * rates.  Other APs, however, stick all of their supported rates on the
+ * main rates information element... */
+#define MAX_RATES_LENGTH                  ((u8)12)
+#define MAX_RATES_EX_LENGTH               ((u8)16)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define MAX_NETWORK_COUNT                  16 
+#else
+#define MAX_NETWORK_COUNT                  96 
+#endif			
+
+#define MAX_CHANNEL_NUMBER                 161
+#define RTLLIB_SOFTMAC_SCAN_TIME	   100
+#define RTLLIB_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
+
+#define CRC_LENGTH                 4U
+
+#define MAX_WPA_IE_LEN 64
+#define MAX_WZC_IE_LEN 256
+
+#define NETWORK_EMPTY_ESSID (1<<0)
+#define NETWORK_HAS_OFDM    (1<<1)
+#define NETWORK_HAS_CCK     (1<<2)
+
+/* QoS structure */
+#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
+#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
+#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | \
+                                         NETWORK_HAS_QOS_INFORMATION)
+/* 802.11h */
+#define NETWORK_HAS_POWER_CONSTRAINT    (1<<5)
+#define NETWORK_HAS_CSA                 (1<<6)
+#define NETWORK_HAS_QUIET               (1<<7)
+#define NETWORK_HAS_IBSS_DFS            (1<<8)
+#define NETWORK_HAS_TPC_REPORT          (1<<9)
+
+#define NETWORK_HAS_ERP_VALUE           (1<<10)
+
+#define QOS_QUEUE_NUM                   4
+#define QOS_OUI_LEN                     3
+#define QOS_OUI_TYPE                    2
+#define QOS_ELEMENT_ID                  221
+#define QOS_OUI_INFO_SUB_TYPE           0
+#define QOS_OUI_PARAM_SUB_TYPE          1
+#define QOS_VERSION_1                   1
+#define QOS_AIFSN_MIN_VALUE             2
+#if 1
+struct rtllib_qos_information_element {
+        u8 elementID;
+        u8 length;
+        u8 qui[QOS_OUI_LEN];
+        u8 qui_type;
+        u8 qui_subtype;
+        u8 version;
+        u8 ac_info;
+} __attribute__ ((packed));
+
+struct rtllib_qos_ac_parameter {
+        u8 aci_aifsn;
+        u8 ecw_min_max;
+        __le16 tx_op_limit;
+} __attribute__ ((packed));
+
+struct rtllib_qos_parameter_info {
+        struct rtllib_qos_information_element info_element;
+        u8 reserved;
+        struct rtllib_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct rtllib_qos_parameters {
+        __le16 cw_min[QOS_QUEUE_NUM];
+        __le16 cw_max[QOS_QUEUE_NUM];
+        u8 aifs[QOS_QUEUE_NUM];
+        u8 flag[QOS_QUEUE_NUM];
+        __le16 tx_op_limit[QOS_QUEUE_NUM];
+} __attribute__ ((packed));
+
+struct rtllib_qos_data {
+        struct rtllib_qos_parameters parameters;
+	unsigned int wmm_acm;
+        int active;
+        int supported;
+        u8 param_count;
+        u8 old_param_count;
+};
+
+struct rtllib_tim_parameters {
+        u8 tim_count;
+        u8 tim_period;
+} __attribute__ ((packed));
+
+struct rtllib_wmm_ac_param {
+	u8 ac_aci_acm_aifsn;
+	u8 ac_ecwmin_ecwmax;
+	u16 ac_txop_limit;
+};
+
+struct rtllib_wmm_ts_info {
+	u8 ac_dir_tid;
+	u8 ac_up_psb;
+	u8 reserved;
+} __attribute__ ((packed));
+
+struct rtllib_wmm_tspec_elem {
+	struct rtllib_wmm_ts_info ts_info;
+	u16 norm_msdu_size;
+	u16 max_msdu_size;
+	u32 min_serv_inter;
+	u32 max_serv_inter;
+	u32 inact_inter;
+	u32 suspen_inter;
+	u32 serv_start_time;
+	u32 min_data_rate;
+	u32 mean_data_rate;
+	u32 peak_data_rate;
+	u32 max_burst_size;
+	u32 delay_bound;
+	u32 min_phy_rate;
+	u16 surp_band_allow;
+	u16 medium_time;
+}__attribute__((packed));
+#endif
+enum eap_type {
+	EAP_PACKET = 0,
+	EAPOL_START,
+	EAPOL_LOGOFF,
+	EAPOL_KEY,
+	EAPOL_ENCAP_ASF_ALERT
+};
+
+static const char *eap_types[] = {
+	[EAP_PACKET]		= "EAP-Packet",
+	[EAPOL_START]		= "EAPOL-Start",
+	[EAPOL_LOGOFF]		= "EAPOL-Logoff",
+	[EAPOL_KEY]		= "EAPOL-Key",
+	[EAPOL_ENCAP_ASF_ALERT]	= "EAPOL-Encap-ASF-Alert"
+};
+
+static inline const char *eap_get_type(int type)
+{
+	return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
+}
+static inline u8 Frame_QoSTID(u8* buf)
+{
+	struct rtllib_hdr_3addr *hdr;
+	u16 fc;
+	hdr = (struct rtllib_hdr_3addr *)buf;
+	fc = le16_to_cpu(hdr->frame_ctl);
+	return (u8)((frameqos*)(buf + (((fc & RTLLIB_FCTL_TODS)&&(fc & RTLLIB_FCTL_FROMDS))? 30 : 24)))->field.tid;
+}
+
+
+struct eapol {
+	u8 snap[6];
+	u16 ethertype;
+	u8 version;
+	u8 type;
+	u16 length;
+} __attribute__ ((packed));
+
+struct rtllib_softmac_stats{
+	unsigned int rx_ass_ok;
+	unsigned int rx_ass_err;
+	unsigned int rx_probe_rq;
+	unsigned int tx_probe_rs;
+	unsigned int tx_beacons;
+	unsigned int rx_auth_rq;
+	unsigned int rx_auth_rs_ok;
+	unsigned int rx_auth_rs_err;
+	unsigned int tx_auth_rq;
+	unsigned int no_auth_rs;
+	unsigned int no_ass_rs;
+	unsigned int tx_ass_rq;
+	unsigned int rx_ass_rq;
+	unsigned int tx_probe_rq;
+	unsigned int reassoc;
+	unsigned int swtxstop;
+	unsigned int swtxawake;
+	unsigned char CurrentShowTxate;
+	unsigned char last_packet_rate;
+	unsigned int txretrycount;
+};
+
+#define BEACON_PROBE_SSID_ID_POSITION 12
+
+struct rtllib_info_element_hdr {
+	u8 id;
+	u8 len;
+} __attribute__ ((packed));
+
+/*
+ * These are the data types that can make up management packets
+ *
+	u16 auth_algorithm;
+	u16 auth_sequence;
+	u16 beacon_interval;
+	u16 capability;
+	u8 current_ap[ETH_ALEN];
+	u16 listen_interval;
+	struct {
+		u16 association_id:14, reserved:2;
+	} __attribute__ ((packed));
+	u32 time_stamp[2];
+	u16 reason;
+	u16 status;
+*/
+
+#define RTLLIB_DEFAULT_TX_ESSID "Penguin"
+#define RTLLIB_DEFAULT_BASIC_RATE 2 
+#ifdef _RTL8192_EXT_PATCH_
+#define RTLLIB_DEFAULT_MESHID "CMPC-mesh"
+#define RTLLIB_DEFAULT_MESH_CHAN 7 
+#endif
+
+enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
+#define MAX_SP_Len  (WMM_all_frame << 4)
+#define RTLLIB_QOS_TID 0x0f
+#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
+#ifdef ENABLE_AMSDU
+#define QOS_CTL_AMSDU_PRESENT (0x01 << 7)
+#endif
+
+#define RTLLIB_DTIM_MBCAST 4
+#define RTLLIB_DTIM_UCAST 2
+#define RTLLIB_DTIM_VALID 1
+#define RTLLIB_DTIM_INVALID 0
+
+#define RTLLIB_PS_DISABLED 0
+#define RTLLIB_PS_UNICAST RTLLIB_DTIM_UCAST
+#define RTLLIB_PS_MBCAST RTLLIB_DTIM_MBCAST
+
+#ifdef WMM_Hang_8187
+#undef WMM_Hang_8187
+#endif
+
+#define WME_AC_BK   0x00
+#define WME_AC_BE   0x01
+#define WME_AC_VI   0x02
+#define WME_AC_VO   0x03
+#define WME_ACI_MASK 0x03
+#define WME_AIFSN_MASK 0x03
+#define WME_AC_PRAM_LEN 16
+
+#define MAX_RECEIVE_BUFFER_SIZE 9100
+
+#if 1
+#define UP2AC(up) (		   \
+	((up) < 1) ? WME_AC_BE : \
+	((up) < 3) ? WME_AC_BK : \
+	((up) < 4) ? WME_AC_BE : \
+	((up) < 6) ? WME_AC_VI : \
+	WME_AC_VO)	
+#endif
+#define AC2UP(_ac)	(       \
+	((_ac) == WME_AC_VO) ? 6 : \
+	((_ac) == WME_AC_VI) ? 5 : \
+	((_ac) == WME_AC_BK) ? 1 : \
+	0)
+
+#define	ETHER_ADDR_LEN		6	/* length of an Ethernet address */
+#define ETHERNET_HEADER_SIZE    14      /* length of two Ethernet address plus ether type*/
+
+struct	ether_header {
+	u8 ether_dhost[ETHER_ADDR_LEN];
+	u8 ether_shost[ETHER_ADDR_LEN];
+	u16 ether_type;
+} __attribute__((packed)); 
+
+#ifndef ETHERTYPE_PAE
+#define	ETHERTYPE_PAE	0x888e		/* EAPOL PAE/802.1x */
+#endif
+#ifndef ETHERTYPE_IP
+#define	ETHERTYPE_IP	0x0800		/* IP protocol */
+#endif
+
+
+typedef enum _erp_t{
+	ERP_NonERPpresent	= 0x01,
+	ERP_UseProtection	= 0x02,
+	ERP_BarkerPreambleMode = 0x04,
+} erp_t;
+
+#ifdef _RTL8192_EXT_PATCH_
+typedef struct _mesh_config_t {
+	u8 path_proto_id[4];
+	u8 path_metric_id[4];
+	u8 congest_ctl_mode[4];
+	u8 mesh_capability[2];
+} mesh_config_t;
+#define MESH_CONF_TOTAL_LEN 19
+#endif
+
+struct rtllib_network {
+	/* These entries are used to identify a unique network */
+	u8 bssid[ETH_ALEN];
+	u8 channel;
+	/* Ensure null-terminated for any debug msgs */
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 ssid_len;
+	u8 hidden_ssid[IW_ESSID_MAX_SIZE + 1];
+	u8 hidden_ssid_len;
+	struct rtllib_qos_data qos_data;
+
+	bool	bWithAironetIE;
+	bool	bCkipSupported;
+	bool	bCcxRmEnable;
+	u16 	CcxRmState[2];
+	bool	bMBssidValid;
+	u8	MBssidMask;
+	u8	MBssid[6];
+	bool	bWithCcxVerNum;
+	u8	BssCcxVerNumber;
+	/* These are network statistics */
+	struct rtllib_rx_stats stats;
+	u16 capability;
+	u8  rates[MAX_RATES_LENGTH];
+	u8  rates_len;
+	u8  rates_ex[MAX_RATES_EX_LENGTH];
+	u8  rates_ex_len;
+	unsigned long last_scanned;
+	u8  mode;
+	u32 flags;
+	u32 last_associate;
+	u32 time_stamp[2];
+	u16 beacon_interval;
+	u16 listen_interval;
+	u16 atim_window;
+	u8  erp_value;
+	u8  wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
+	u8  rsn_ie[MAX_WPA_IE_LEN];
+	size_t rsn_ie_len;
+#if defined RTL8192S_WAPI_SUPPORT
+	u8  wapi_ie[MAX_WAPI_IE_LEN];
+	size_t wapi_ie_len;
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	u8  wzc_ie[MAX_WZC_IE_LEN];
+	size_t wzc_ie_len;
+#endif
+
+        struct rtllib_tim_parameters tim;
+	u8  dtim_period;
+	u8  dtim_data;
+	u32 last_dtim_sta_time[2];
+
+        u8 wmm_info;
+        struct rtllib_wmm_ac_param wmm_param[4];
+#ifdef THOMAS_TURBO
+	u8 Turbo_Enable;
+#endif
+#ifdef ENABLE_DOT11D
+	u16 CountryIeLen;
+	u8 CountryIeBuf[MAX_IE_LEN];
+#endif
+	BSS_HT	bssht;
+	bool broadcom_cap_exist;
+	bool realtek_cap_exit;
+	bool marvell_cap_exist;
+	bool ralink_cap_exist;
+	bool atheros_cap_exist;
+	bool cisco_cap_exist;
+	bool unknown_cap_exist;
+	bool	berp_info_valid;
+	bool buseprotection;
+	bool bIsNetgear854T;
+	u8 SignalStrength;
+	u8 RSSI; 
+#ifdef _RTL8192_EXT_PATCH_
+	u8 hostname[MAX_HOST_NAME_LENGTH];
+	u8 hostname_len;
+	u8 mesh_id[MAX_MESH_ID_LEN];
+	u8 mesh_id_len;
+	mesh_config_t mesh_config;
+	u8 mesh_config_len;
+	void *ext_entry;
+#endif
+
+	struct list_head list;
+};
+
+#if 1
+enum rtllib_state {
+
+	/* the card is not linked at all */
+	RTLLIB_NOLINK = 0,
+	
+	/* RTLLIB_ASSOCIATING* are for BSS client mode
+	 * the driver shall not perform RX filtering unless
+	 * the state is LINKED.
+	 * The driver shall just check for the state LINKED and
+	 * defaults to NOLINK for ALL the other states (including
+	 * LINKED_SCANNING)
+	 */
+	
+	/* the association procedure will start (wq scheduling)*/
+	RTLLIB_ASSOCIATING,
+	RTLLIB_ASSOCIATING_RETRY,
+	
+	/* the association procedure is sending AUTH request*/
+	RTLLIB_ASSOCIATING_AUTHENTICATING,
+	
+	/* the association procedure has successfully authentcated
+	 * and is sending association request
+	 */
+	RTLLIB_ASSOCIATING_AUTHENTICATED,
+	
+	/* the link is ok. the card associated to a BSS or linked
+	 * to a ibss cell or acting as an AP and creating the bss
+	 */
+	RTLLIB_LINKED,
+	
+	/* same as LINKED, but the driver shall apply RX filter
+	 * rules as we are in NO_LINK mode. As the card is still
+	 * logically linked, but it is doing a syncro site survey
+	 * then it will be back to LINKED state.
+	 */
+	RTLLIB_LINKED_SCANNING,
+#ifdef _RTL8192_EXT_PATCH_
+	RTLLIB_MESH_SCANNING,
+	RTLLIB_MESH_LINKED,
+#endif
+};
+#else
+enum rtllib_state {
+        RTLLIB_UNINITIALIZED = 0,
+        RTLLIB_INITIALIZED,
+        RTLLIB_ASSOCIATING,
+        RTLLIB_ASSOCIATED,
+        RTLLIB_AUTHENTICATING,
+        RTLLIB_AUTHENTICATED,
+        RTLLIB_SHUTDOWN
+};
+#endif
+
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+#define DEFAULT_FTS 2346
+
+#define CFG_RTLLIB_RESERVE_FCS (1<<0)
+#define CFG_RTLLIB_COMPUTE_FCS (1<<1)
+#define CFG_RTLLIB_RTS (1<<2)
+
+#define RTLLIB_24GHZ_MIN_CHANNEL 1
+#define RTLLIB_24GHZ_MAX_CHANNEL 14
+#define RTLLIB_24GHZ_CHANNELS (RTLLIB_24GHZ_MAX_CHANNEL - \
+                                  RTLLIB_24GHZ_MIN_CHANNEL + 1)
+
+#define RTLLIB_52GHZ_MIN_CHANNEL 34
+#define RTLLIB_52GHZ_MAX_CHANNEL 165
+#define RTLLIB_52GHZ_CHANNELS (RTLLIB_52GHZ_MAX_CHANNEL - \
+                                  RTLLIB_52GHZ_MIN_CHANNEL + 1)
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11))
+extern inline int is_multicast_ether_addr(const u8 *addr)
+{
+        return ((addr[0] != 0xff) && (0x01 & addr[0]));
+}
+#endif
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13))
+extern inline int is_broadcast_ether_addr(const u8 *addr)
+{
+	return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
+		(addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
+}
+#endif
+#ifndef eqMacAddr
+#define eqMacAddr(a,b)		( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
+#endif
+typedef struct tx_pending_t{
+	int frag;
+	struct rtllib_txb *txb;
+}tx_pending_t;
+
+typedef struct _bandwidth_autoswitch
+{
+	long threshold_20Mhzto40Mhz;
+	long	threshold_40Mhzto20Mhz;	
+	bool bforced_tx20Mhz;
+	bool bautoswitch_enable;	
+}bandwidth_autoswitch,*pbandwidth_autoswitch;
+
+
+
+#define REORDER_WIN_SIZE	128
+#define REORDER_ENTRY_NUM	128
+typedef struct _RX_REORDER_ENTRY
+{
+	struct list_head	List;
+	u16			SeqNum;
+	struct rtllib_rxb* prxb;
+} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY;
+typedef enum _Fsync_State{
+	Default_Fsync,
+	HW_Fsync,
+	SW_Fsync
+}Fsync_State;	
+
+typedef	enum _RT_PS_MODE	
+{
+	eActive,	
+	eMaxPs,		
+	eFastPs,		
+	eAutoPs,	
+}RT_PS_MODE;
+
+typedef enum _IPS_CALLBACK_FUNCION
+{
+	IPS_CALLBACK_NONE = 0,
+	IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
+	IPS_CALLBACK_JOIN_REQUEST = 2,
+}IPS_CALLBACK_FUNCION;
+
+typedef enum _RT_JOIN_ACTION{
+	RT_JOIN_INFRA   = 1,
+	RT_JOIN_IBSS  = 2,
+	RT_START_IBSS = 3,
+	RT_NO_ACTION  = 4,
+}RT_JOIN_ACTION;
+
+typedef struct _IbssParms{
+	u16   atimWin;
+}IbssParms, *PIbssParms;
+#define MAX_NUM_RATES	264 
+
+typedef	enum _RT_RF_POWER_STATE
+{
+	eRfOn,
+	eRfSleep,
+	eRfOff
+}RT_RF_POWER_STATE;
+
+#define	MAX_SUPPORT_WOL_PATTERN_NUM		8
+
+#define	MAX_WOL_BIT_MASK_SIZE		16 
+#define	MAX_WOL_PATTERN_SIZE		128
+
+typedef enum _WOLPATTERN_TYPE
+{
+	eNetBIOS = 0,
+	eIPv4IPv6ARP,
+	eIPv4IPv6TCPSYN,
+	eMACIDOnly,
+	eNoDefined,
+}WOLPATTERN_TYPE;
+
+typedef struct _RT_PM_WOL_PATTERN_INFO
+{
+	u32	PatternId; 
+	u32	Mask[4];
+	u16	CrcRemainder;
+	u8	WFMIndex; 
+	WOLPATTERN_TYPE	PatternType;
+}RT_PM_WOL_PATTERN_INFO, *PRT_PM_WOL_PATTERN_INFO;
+
+typedef struct _RT_POWER_SAVE_CONTROL
+{
+
+	bool				bInactivePs;
+	bool				bIPSModeBackup;
+	bool				bHaltAdapterClkRQ;
+	bool				bSwRfProcessing;
+	RT_RF_POWER_STATE	eInactivePowerState;
+	work_struct_rsl 	InactivePsWorkItem;
+	struct timer_list	InactivePsTimer;
+
+	IPS_CALLBACK_FUNCION	ReturnPoint;
+	
+	bool				bTmpBssDesc;
+	RT_JOIN_ACTION		tmpJoinAction;
+	struct rtllib_network tmpBssDesc;
+
+	bool				bTmpScanOnly;
+	bool				bTmpActiveScan;
+	bool				bTmpFilterHiddenAP;
+	bool				bTmpUpdateParms;
+	u8				tmpSsidBuf[33];
+	OCTET_STRING			tmpSsid2Scan;
+	bool				bTmpSsid2Scan;
+	u8				tmpNetworkType;
+	u8				tmpChannelNumber;
+	u16				tmpBcnPeriod;
+	u8				tmpDtimPeriod;
+	u16				tmpmCap;
+	OCTET_STRING			tmpSuppRateSet;
+	u8				tmpSuppRateBuf[MAX_NUM_RATES];
+	bool				bTmpSuppRate;
+	IbssParms				tmpIbpm;
+	bool				bTmpIbpm;
+
+	bool				bLeisurePs;
+	u32				PowerProfile;
+	u8				LpsIdleCount;
+	u8				RegMaxLPSAwakeIntvl;
+	u8				LPSAwakeIntvl;
+
+	u32				CurPsLevel;
+	u32				RegRfPsLevel;
+
+	bool				bFwCtrlLPS;
+	u8				FWCtrlPSMode;
+
+	bool				LinkReqInIPSRFOffPgs;
+	bool				BufConnectinfoBefore;
+	
+
+	bool				bGpioRfSw;
+
+	u8				oWLANMode;
+	RT_PM_WOL_PATTERN_INFO		PmWoLPatternInfo[MAX_SUPPORT_WOL_PATTERN_NUM]; 
+
+}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
+
+typedef u32 RT_RF_CHANGE_SOURCE;
+#define RF_CHANGE_BY_SW BIT31
+#define RF_CHANGE_BY_HW BIT30
+#define RF_CHANGE_BY_PS BIT29
+#define RF_CHANGE_BY_IPS BIT28
+#define RF_CHANGE_BY_INIT	0	
+
+typedef enum 
+{
+	COUNTRY_CODE_FCC = 0,
+	COUNTRY_CODE_IC = 1,
+	COUNTRY_CODE_ETSI = 2,
+	COUNTRY_CODE_SPAIN = 3,
+	COUNTRY_CODE_FRANCE = 4,
+	COUNTRY_CODE_MKK = 5,
+	COUNTRY_CODE_MKK1 = 6,
+	COUNTRY_CODE_ISRAEL = 7,
+	COUNTRY_CODE_TELEC = 8,
+	COUNTRY_CODE_MIC = 9,
+	COUNTRY_CODE_GLOBAL_DOMAIN = 10,
+	COUNTRY_CODE_WORLD_WIDE_13 = 11,
+	COUNTRY_CODE_TELEC_NETGEAR = 12,
+	COUNTRY_CODE_MAX
+}country_code_type_t;	
+
+typedef enum _SCAN_OPERATION_BACKUP_OPT{
+	SCAN_OPT_BACKUP=0,
+	SCAN_OPT_RESTORE,
+	SCAN_OPT_MAX
+}SCAN_OPERATION_BACKUP_OPT;
+
+typedef	enum _FW_CMD_IO_TYPE{
+	FW_CMD_DIG_ENABLE = 0, 
+	FW_CMD_DIG_DISABLE = 1,
+	FW_CMD_DIG_HALT = 2,
+	FW_CMD_DIG_RESUME = 3,
+	FW_CMD_HIGH_PWR_ENABLE = 4, 
+	FW_CMD_HIGH_PWR_DISABLE = 5,
+	FW_CMD_RA_RESET = 6, 
+	FW_CMD_RA_ACTIVE= 7,
+	FW_CMD_RA_REFRESH_N= 8,
+	FW_CMD_RA_REFRESH_BG= 9,
+	FW_CMD_RA_INIT= 10,
+	FW_CMD_IQK_ENABLE = 11, 
+	FW_CMD_TXPWR_TRACK_ENABLE = 12,	
+	FW_CMD_TXPWR_TRACK_DISABLE = 13,	
+	FW_CMD_TXPWR_TRACK_THERMAL = 14, 
+	FW_CMD_PAUSE_DM_BY_SCAN = 15,
+	FW_CMD_RESUME_DM_BY_SCAN = 16,
+	FW_CMD_RA_REFRESH_N_COMB = 17,
+	FW_CMD_RA_REFRESH_BG_COMB = 18,
+	FW_CMD_ANTENNA_SW_ENABLE = 19,
+	FW_CMD_ANTENNA_SW_DISABLE = 20,
+	FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, 
+	FW_CMD_LPS_ENTER = 22,			
+	FW_CMD_LPS_LEAVE = 23,			
+	FW_CMD_DIG_MODE_SS = 24, 			
+	FW_CMD_DIG_MODE_FA = 25,			
+	FW_CMD_ADD_A2_ENTRY = 26,
+	FW_CMD_CTRL_DM_BY_DRIVER = 27,
+	FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28,
+	FW_CMD_PAPE_CONTROL = 29,
+	FW_CMD_CHAN_SET = 30,
+}FW_CMD_IO_TYPE,*PFW_CMD_IO_TYPE;
+
+#define RT_MAX_LD_SLOT_NUM	10
+typedef struct _RT_LINK_DETECT_T{
+
+	u32				NumRecvBcnInPeriod;
+	u32				NumRecvDataInPeriod;
+
+	u32				RxBcnNum[RT_MAX_LD_SLOT_NUM];	
+	u32				RxDataNum[RT_MAX_LD_SLOT_NUM];	
+	u16				SlotNum;	
+	u16				SlotIndex;
+
+	u32				NumTxOkInPeriod;
+	u32				NumRxOkInPeriod;
+	u32				NumRxUnicastOkInPeriod;
+	bool				bBusyTraffic;
+
+#ifdef _RTL8192_EXT_PATCH_
+	u8				IdleCount;
+	u32				LastNumTxUnicast;
+	u32				LastNumRxUnicast;
+#endif	
+}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
+
+#ifdef _RTL8192_EXT_PATCH_
+struct rtllib_crypt_data_list{
+	u8 used;
+	u8 mac_addr[ETH_ALEN];  
+	struct rtllib_crypt_data *crypt[WEP_KEYS];
+}__attribute__((packed));
+
+typedef struct _SW_RATR_TABLE{
+	bool bused;
+	u32  ratr_value;
+}SW_RATR_TABLE, *PSW_RATR_TABLE;
+#endif
+
+typedef struct _SW_CAM_TABLE{
+
+	u8				macaddr[6];
+	bool				bused;
+	u8				key_buf[16];
+	u16 				key_type;
+	u8				useDK;
+	u8				key_index;				
+	
+}SW_CAM_TABLE,*PSW_CAM_TABLE;
+#define   TOTAL_CAM_ENTRY				32
+typedef struct _rate_adaptive
+{
+	u8				rate_adaptive_disabled;
+	u8				ratr_state;
+	u16				reserve;	
+	
+	u32				high_rssi_thresh_for_ra;
+	u32				high2low_rssi_thresh_for_ra;
+	u8				low2high_rssi_thresh_for_ra40M;
+	u32				low_rssi_thresh_for_ra40M;
+	u8				low2high_rssi_thresh_for_ra20M;
+	u32				low_rssi_thresh_for_ra20M;
+	u32				upper_rssi_threshold_ratr;
+	u32				middle_rssi_threshold_ratr;
+	u32				low_rssi_threshold_ratr;
+	u32				low_rssi_threshold_ratr_40M;
+	u32				low_rssi_threshold_ratr_20M;
+	u8				ping_rssi_enable;	
+	u32				ping_rssi_ratr;	
+	u32				ping_rssi_thresh_for_ra;
+	u32				last_ratr;
+	u8				PreRATRState;
+	
+} rate_adaptive, *prate_adaptive;
+typedef enum _RATR_TABLE_MODE_8192S{
+	RATR_INX_WIRELESS_NGB = 0,
+	RATR_INX_WIRELESS_NG = 1,
+	RATR_INX_WIRELESS_NB = 2,
+	RATR_INX_WIRELESS_N = 3,
+	RATR_INX_WIRELESS_GB = 4,
+	RATR_INX_WIRELESS_G = 5,
+	RATR_INX_WIRELESS_B = 6,
+	RATR_INX_WIRELESS_MC = 7,
+	RATR_INX_WIRELESS_A = 8,
+}RATR_TABLE_MODE_8192S, *PRATR_TABLE_MODE_8192S;
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE
+#define PEER_MAX_ASSOC 10
+typedef struct _RSSI_STA{
+	long	UndecoratedSmoothedPWDB;
+}RSSI_STA, *PRSSI_STA;
+
+struct sta_info {
+	u8 macaddr[ETH_ALEN];
+	u16 aid;
+	u8 authentication;
+	u8 encryption;
+	u16 capability;
+	u8 ratr_index;
+	int wireless_mode;
+	RT_HTINFO_STA_ENTRY htinfo;
+	u8 wme_enable;
+	u32 CurDataRate;
+	RSSI_STA rssi_stat;
+	rate_adaptive     rate_adaptive;
+	u8 bPowerSave;		
+	struct sk_buff_head PsQueue;		
+	u32	LastActiveTime; 
+	u16			StaDataRate;  
+	u32			StaSS; 
+	u16			RetryFrameCnt;
+	u16			LastRetryCnt;
+	u16			NoRetryFrameCnt;
+	u16			LastNoRetryCnt;
+	int			AvgRetryRate;
+	int			LastRetryRate;
+	u8			txRateIndex;
+	u16			APDataRate;
+	u16			ForcedDataRate;	
+} __attribute__ ((packed));
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+typedef struct _RT_PEERMP_HTINFO{
+	u8				bEnableHT;
+	u8				bCurrentHTSupport;
+
+	u8				bRegBW40MHz;				
+	u8				bCurBW40MHz;				
+
+	u8				bRegShortGI40MHz;			
+	u8				bCurShortGI40MHz;			
+
+	u8				bRegShortGI20MHz;			
+	u8				bCurShortGI20MHz;			
+
+	u8				bCurSuppCCK;				
+
+	
+
+
+	u8				PeerHTCapBuf[32];
+	u8				PeerHTInfoBuf[32];
+
+
+	u8				bAMSDU_Support;			
+	u16				nAMSDU_MaxSize;			
+	u8				bCurrent_Mesh_AMSDU_Support;	
+	
+
+	u8				bAMPDUEnable;				
+	u8				bCurrentMeshAMPDUEnable;		
+	u8				AMPDU_Factor;				
+	u8				CurrentAMPDUFactor;		
+	u8				MPDU_Density;				
+	u8				CurrentMPDUDensity;			
+
+	u8				ForcedAMPDUFactor;
+	u8				ForcedMPDUDensity;
+
+	HT_AGGRE_MODE_E	ForcedAMSDUMode;
+	u16				ForcedAMSDUMaxSize;
+
+	u8				bForcedShortGI;
+
+	u8				CurrentOpMode;
+
+	u8				MimoPs;
+	
+	HT_EXTCHNL_OFFSET	CurSTAExtChnlOffset;
+	u8				bCurTxBW40MHz;	
+	u8				PeerBandwidth;
+
+	u8				bSwBwInProgress;
+	CHNLOP				ChnlOp; 
+	u8				SwBwStep;
+
+	u8				bRegRT2RTAggregation;
+	u8				bCurrentRT2RTAggregation;
+	u8				bCurrentRT2RTLongSlotTime;
+	u8				szRT2RTAggBuffer[10];
+
+	u8				bRegRxReorderEnable;
+	u8				bCurRxReorderEnable;
+	u8				RxReorderWinSize;
+	u8				RxReorderPendingTime;
+	u16				RxReorderDropCounter;
+
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+	u8				UsbTxAggrNum;
+#endif
+#ifdef USB_RX_AGGREGATION_SUPPORT
+	u8				UsbRxFwAggrEn;
+	u8				UsbRxFwAggrPageNum;
+	u8				UsbRxFwAggrPacketNum;
+	u8				UsbRxFwAggrTimeout;
+#endif
+
+	u8				bIsPeerBcm;
+
+	u8				McsRateSet[16];
+	u8				HTHighestOperaRate;
+	u8				IOTPeer;
+	u32				IOTAction;
+} __attribute__ ((packed)) peerMP_htinfo, *ppeerMP_htinfo;
+#endif
+
+#define	NUM_PMKID_CACHE		16
+typedef struct _RT_PMKID_LIST
+{
+	u8						bUsed;
+	u8 						Bssid[6];
+	u8						PMKID[16];
+	u8						SsidBuf[33];
+	u8*						ssid_octet;
+	u16 					ssid_length;
+} RT_PMKID_LIST, *PRT_PMKID_LIST;
+
+#ifdef CONFIG_CFG_80211 
+enum {
+	LIBIPW_CH_PASSIVE_ONLY 		= (1 << 0),
+	LIBIPW_CH_80211H_RULES 		= (1 << 1),
+	LIBIPW_CH_B_ONLY 		= (1 << 2),
+	LIBIPW_CH_NO_IBSS 		= (1 << 3),
+	LIBIPW_CH_UNIFORM_SPREADING 	= (1 << 4),
+	LIBIPW_CH_RADAR_DETECT 		= (1 << 5),
+	LIBIPW_CH_INVALID 		= (1 << 6),
+};
+struct rtllib_channel {
+	u32 freq;
+	u8 channel;
+	u8 flags;
+	u8 max_power;
+};
+
+#define RTLLIB_24GHZ_MIN_CHANNEL 1
+#define RTLLIB_24GHZ_MAX_CHANNEL 14
+#define RTLLIB_24GHZ_CHANNELS (RTLLIB_24GHZ_MAX_CHANNEL - \
+		RTLLIB_24GHZ_MIN_CHANNEL + 1)
+
+struct reg_dmn_pair_mapping {
+	u16 regDmnEnum;
+	u16 reg_5ghz_ctl;
+	u16 reg_2ghz_ctl;
+};
+
+struct rtl_regulatory {
+	char alpha2[2];
+	u16 country_code;
+	u16 max_power_level;
+	u32 tp_scale;
+	u16 current_rd;
+	u16 current_rd_ext;
+	int16_t power_limit;
+	struct reg_dmn_pair_mapping *regpair;
+};
+
+struct ieee80211_bss {
+	/* Yes, this is a hack */
+	struct cfg80211_bss cbss;
+
+	/* don't want to look up all the time */
+	size_t ssid_len;
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+	u8 dtim_period;
+
+	bool wmm_used;
+
+	unsigned long last_probe_resp;
+
+#ifdef CONFIG_MAC80211_MESH
+	u8 *mesh_id;
+	size_t mesh_id_len;
+	u8 *mesh_cfg;
+#endif
+
+	#define IEEE80211_MAX_SUPP_RATES 32
+	u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
+	size_t supp_rates_len;
+
+	/*
+	 * During assocation, we save an ERP value from a probe response so
+	 * that we can feed ERP info to the driver when handling the
+	 * association completes. these fields probably won't be up-to-date
+	 * otherwise, you probably don't want to use them.
+	 */
+	bool has_erp_value;
+	u8 erp_value;
+};
+
+/* Parsed Information Elements */
+struct ieee802_11_elems {
+	u8 *ie_start;
+	size_t total_len;
+
+	/* pointers to IEs */
+	u8 *ssid;
+	u8 *supp_rates;
+	u8 *fh_params;
+	u8 *ds_params;
+	u8 *cf_params;
+	struct ieee80211_tim_ie *tim;
+	u8 *ibss_params;
+	u8 *challenge;
+	u8 *wpa;
+	u8 *rsn;
+	u8 *erp_info;
+	u8 *ext_supp_rates;
+	u8 *wmm_info;
+	u8 *wmm_param;
+	struct ieee80211_ht_cap *ht_cap_elem;
+	struct ieee80211_ht_info *ht_info_elem;
+	u8 *mesh_config;
+	u8 *mesh_id;
+	u8 *peer_link;
+	u8 *preq;
+	u8 *prep;
+	u8 *perr;
+	u8 *ch_switch_elem;
+	u8 *country_elem;
+	u8 *pwr_constr_elem;
+	u8 *quiet_elem; 	/* first quite element */
+	u8 *timeout_int;
+
+	/* length of them, respectively */
+	u8 ssid_len;
+	u8 supp_rates_len;
+	u8 fh_params_len;
+	u8 ds_params_len;
+	u8 cf_params_len;
+	u8 tim_len;
+	u8 ibss_params_len;
+	u8 challenge_len;
+	u8 wpa_len;
+	u8 rsn_len;
+	u8 erp_info_len;
+	u8 ext_supp_rates_len;
+	u8 wmm_info_len;
+	u8 wmm_param_len;
+	u8 mesh_config_len;
+	u8 mesh_id_len;
+	u8 peer_link_len;
+	u8 preq_len;
+	u8 prep_len;
+	u8 perr_len;
+	u8 ch_switch_elem_len;
+	u8 country_elem_len;
+	u8 pwr_constr_elem_len;
+	u8 quiet_elem_len;
+	u8 num_of_quiet_elem;	/* can be more the one */
+	u8 timeout_int_len;
+};
+
+#endif
+
+
+typedef struct _RT_INTEL_PROMISCUOUS_MODE_INFO {
+     bool bPromiscuousOn;
+     bool bFilterSourceStationFrame;
+} RT_INTEL_PROMISCUOUS_MODE_INFO, *PRT_INTEL_PROMISCUOUS_MODE_INFO;
+
+
+/*************** DRIVER STATUS   *****/
+#define STATUS_SCANNING			0
+#define STATUS_SCAN_HW			1
+#define STATUS_SCAN_ABORTING	2
+#define STATUS_SETTING_CHAN		3
+/*************** DRIVER STATUS   *****/
+
+enum {
+	NO_USE 		= 0,
+	USED		= 1,
+	HW_SEC 	= 2,
+	SW_SEC		= 3,
+};
+
+struct rtllib_device {
+	struct pci_dev *pdev;
+	struct net_device *dev;
+	struct rtllib_security sec;
+
+	bool disable_mgnt_queue;
+
+	unsigned long status;
+	short hwscan_ch_bk;
+	HT_EXTCHNL_OFFSET chan_offset_bk;
+	HT_CHANNEL_WIDTH bandwidth_bk;
+	u8 hwscan_sem_up;
+#ifdef CONFIG_CFG_80211
+	struct wireless_dev wdev;
+	struct rtl_regulatory regulatory;
+#endif
+	u8	CntAfterLink;
+
+	u8 VersionID;
+	/* The last AssocReq/Resp IEs */
+	u8 *assocreq_ies, *assocresp_ies;
+	size_t assocreq_ies_len, assocresp_ies_len;
+	
+	bool b_customer_lenovo_id;
+	bool	bForcedShowRxRate;
+	bool	bForcedShowRateStill;
+	u8	SystemQueryDataRateCount;
+	bool	bForcedBgMode;
+	bool bUseRAMask;
+	bool b1x1RecvCombine;
+	u8 RF_Type; 
+	bool b1SSSupport;
+	
+	u8 hwsec_active;  
+	bool is_silent_reset;
+      bool force_mic_error;
+	bool is_roaming;
+	bool ieee_up;	
+	bool cannot_notify;	
+	bool bSupportRemoteWakeUp;
+	RT_PS_MODE	dot11PowerSaveMode; 
+	bool actscanning;
+	bool FirstIe_InScan;
+	bool be_scan_inprogress;
+	bool beinretry;
+	RT_RF_POWER_STATE		eRFPowerState;
+	RT_RF_CHANGE_SOURCE	RfOffReason;
+	bool is_set_key;
+	bool wx_set_enc; 
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE
+	struct sta_info *peer_assoc_list[PEER_MAX_ASSOC];
+	u8 AvailableAIDTable[PEER_MAX_ASSOC];  
+	atomic_t	AsocEntryNum;
+	u64	CurrTsf;
+	u64	TargetTsf;
+	bool	Peer_bCurBW40M;
+#endif
+	PRT_HIGH_THROUGHPUT	pHTInfo;
+	spinlock_t bw_spinlock;
+
+	spinlock_t reorder_spinlock;
+	u8	Regdot11HTOperationalRateSet[16];		
+	u8	Regdot11TxHTOperationalRateSet[16];		
+	u8	dot11HTOperationalRateSet[16];		
+	u8	RegHTSuppRateSet[16];
+	u8				HTCurrentOperaRate;
+	u8				HTHighestOperaRate;
+       u8		MinSpaceCfg;
+	u8		MaxMssDensity;
+	u8	bTxDisableRateFallBack;
+	u8 	bTxUseDriverAssingedRate;
+	u8	bTxEnableFwCalcDur;
+	atomic_t	atm_chnlop;
+	atomic_t	atm_swbw;
+
+	struct list_head		Tx_TS_Admit_List;
+	struct list_head		Tx_TS_Pending_List;
+	struct list_head		Tx_TS_Unused_List;
+	TX_TS_RECORD		TxTsRecord[TOTAL_TS_NUM];
+	struct list_head		Rx_TS_Admit_List;
+	struct list_head		Rx_TS_Pending_List;
+	struct list_head		Rx_TS_Unused_List;
+	RX_TS_RECORD		RxTsRecord[TOTAL_TS_NUM];
+	RX_REORDER_ENTRY	RxReorderEntry[128];
+	struct list_head		RxReorder_Unused_List;
+	u8				ForcedPriority;		
+	
+
+	/* Bookkeeping structures */
+	struct net_device_stats stats;
+	struct rtllib_stats ieee_stats;
+	struct rtllib_softmac_stats softmac_stats;
+	
+	/* Probe / Beacon management */
+	struct list_head network_free_list;
+	struct list_head network_list;
+#ifdef RTL8192U
+	struct list_head network_bssid_free_list;
+	struct list_head network_bssid_list;
+#endif
+	struct rtllib_network *networks;
+	int scans;
+	int scan_age;
+
+	int iw_mode; /* operating mode (IW_MODE_*) */
+	bool bNetPromiscuousMode; 
+	RT_INTEL_PROMISCUOUS_MODE_INFO IntelPromiscuousModeInfo;
+	
+	struct iw_spy_data spy_data; 
+
+	spinlock_t lock;
+	spinlock_t wpax_suitlist_lock;
+	
+	int tx_headroom; /* Set to size of any additional room needed at front
+			  * of allocated Tx SKBs */
+	u32 config;
+
+	/* WEP and other encryption related settings at the device level */
+	int open_wep; /* Set to 1 to allow unencrypted frames */
+	int auth_mode;
+	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+				 * WEP key changes */
+
+	/* If the host performs {en,de}cryption, then set to 1 */
+	int host_encrypt;
+	int host_encrypt_msdu;
+	int host_decrypt;
+        /* host performs multicast decryption */
+        int host_mc_decrypt;
+
+        /* host should strip IV and ICV from protected frames */
+        /* meaningful only when hardware decryption is being used */
+        int host_strip_iv_icv;
+
+        int host_open_frag;
+        int host_build_iv;
+	int ieee802_1x; /* is IEEE 802.1X used */
+
+	/* WPA data */
+	bool bHalfNMode;
+	bool bHalfWirelessN24GMode;
+	int wpa_enabled;
+	int drop_unencrypted;
+	int tkip_countermeasures;
+	int privacy_invoked;
+	size_t wpa_ie_len;
+	u8 *wpa_ie;
+	size_t wps_ie_len;
+	u8 *wps_ie;
+	u8 ap_mac_addr[6];
+	u16 pairwise_key_type;
+	u16 group_key_type;
+	struct list_head crypt_deinit_list;
+#ifdef _RTL8192_EXT_PATCH_
+	struct rtllib_crypt_data_list* cryptlist[MAX_MP];
+	struct rtllib_crypt_data *sta_crypt[WEP_KEYS];
+#else
+	struct rtllib_crypt_data *crypt[WEP_KEYS];
+#endif
+
+	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
+	SW_CAM_TABLE swcamtable[TOTAL_CAM_ENTRY];
+	struct timer_list crypt_deinit_timer;
+        int crypt_quiesced;
+
+	int bcrx_sta_key; /* use individual keys to override default keys even
+			   * with RX of broad/multicast frames */
+	
+	RT_PMKID_LIST		PMKIDList[NUM_PMKID_CACHE];
+
+	/* Fragmentation structures */
+	struct rtllib_frag_entry frag_cache[17][RTLLIB_FRAG_CACHE_LEN];
+	unsigned int frag_next_idx[17];
+	u16 fts; /* Fragmentation Threshold */
+#define DEFAULT_RTS_THRESHOLD 2346U
+#define MIN_RTS_THRESHOLD 1
+#define MAX_RTS_THRESHOLD 2346U
+        u16 rts; /* RTS threshold */
+
+        /* Association info */
+        u8 bssid[ETH_ALEN];
+
+	/* This stores infos for the current network.
+	 * Either the network we are associated in INFRASTRUCTURE
+	 * or the network that we are creating in MASTER mode.
+	 * ad-hoc is a mixture ;-).
+	 * Note that in infrastructure mode, even when not associated,
+	 * fields bssid and essid may be valid (if wpa_set and essid_set
+	 * are true) as thy carry the value set by the user via iwconfig  
+	 */
+	struct rtllib_network current_network;
+
+	enum rtllib_state state;
+
+	int short_slot;
+	int reg_mode;
+	int mode;       /* A, B, G */
+	int modulation; /* CCK, OFDM */
+	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
+	int abg_true;   /* ABG flag              */
+	
+	/* used for forcing the ibss workqueue to terminate 
+	 * without wait for the syncro scan to terminate
+	 */
+	short sync_scan_hurryup; 
+	u16 scan_watch_dog;
+        int perfect_rssi;
+        int worst_rssi;
+
+        u16 prev_seq_ctl;       /* used to drop duplicate frames */
+
+	/* map of allowed channels. 0 is dummy */
+#ifdef ENABLE_DOT11D
+	void* pDot11dInfo;
+	bool bGlobalDomain;
+#else
+	u8 channel_map[MAX_CHANNEL_NUMBER+1];
+#endif	
+	u8 active_channel_map[MAX_CHANNEL_NUMBER+1];
+
+	u8   IbssStartChnl;
+	u8   ibss_maxjoin_chal;
+
+#ifdef _RTL8192_EXT_PATCH_
+	u8 backup_channel;
+	bool bUseProtection;
+#endif	
+	int rate;       /* current rate */
+	int basic_rate;
+	u32	currentRate;
+	
+	short active_scan;
+	
+	/* this contains flags for selectively enable softmac support */
+	u16 softmac_features;
+	
+	/* if the sequence control field is not filled by HW */
+	u16 seq_ctrl[5];
+	
+	/* association procedure transaction sequence number */
+	u16 associate_seq;
+	
+	/* AID for RTXed association responses */
+	u16 assoc_id;
+	
+	/* power save mode related*/
+	u8 ack_tx_to_ieee;
+	short ps;
+	short sta_sleep;
+	int ps_timeout;
+	int ps_period;
+	struct tasklet_struct ps_task;
+	u32 ps_th;
+	u32 ps_tl;
+	bool polling;
+	
+	short raw_tx;
+	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
+	short queue_stop;
+	short scanning_continue ;
+	short proto_started;
+	short proto_stoppping;
+	
+	struct semaphore wx_sem;
+	struct semaphore scan_sem;
+	struct semaphore ips_sem;
+	
+	spinlock_t mgmt_tx_lock;	
+	spinlock_t beacon_lock;
+
+	short beacon_txing;
+
+	short wap_set;
+	short ssid_set;
+	
+	/* set on initialization */
+	unsigned int wmm_acm;
+	
+	/* for discarding duplicated packets in IBSS */
+	struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
+	
+	/* for discarding duplicated packets in BSS */
+	u16 last_rxseq_num[17]; /* rx seq previous per-tid */
+	u16 last_rxfrag_num[17];/* tx frag previous per-tid */
+	unsigned long last_packet_time[17];
+	
+	/* for PS mode */
+	unsigned long last_rx_ps_time;
+	bool			bAwakePktSent; 
+	u8			LPSDelayCnt;
+	
+	/* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
+	struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
+	int mgmt_queue_head;
+	int mgmt_queue_tail;
+#define RTLLIB_QUEUE_LIMIT 128
+	u8 AsocRetryCount;
+	unsigned int hw_header;
+	struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE];
+	struct sk_buff_head  skb_aggQ[MAX_QUEUE_SIZE]; 
+	struct sk_buff_head  skb_drv_aggQ[MAX_QUEUE_SIZE]; 
+	u32	sta_edca_param[4];
+	bool aggregation;
+	bool enable_rx_imm_BA;
+	bool bibsscoordinator;
+
+	bool	bdynamic_txpower_enable; 
+
+	bool bCTSToSelfEnable;
+	u8 	CTSToSelfTH;
+	
+	u32 	fsync_time_interval;
+	u32	fsync_rate_bitmap;
+	u8	fsync_rssi_threshold;
+	bool	bfsync_enable;
+
+	u8	fsync_multiple_timeinterval;		
+	u32	fsync_firstdiff_ratethreshold;		
+	u32	fsync_seconddiff_ratethreshold;	 
+	Fsync_State			fsync_state;
+	bool		bis_any_nonbepkts;
+	bandwidth_autoswitch bandwidth_auto_switch;
+	bool FwRWRF;
+
+	RT_LINK_DETECT_T	LinkDetectInfo;
+	bool bIsAggregateFrame;
+	RT_POWER_SAVE_CONTROL	PowerSaveControl;
+	u8 amsdu_in_process;
+
+	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
+	struct  tx_pending_t tx_pending;
+	
+	/* used if IEEE_SOFTMAC_ASSOCIATE is set */
+	struct timer_list associate_timer;
+
+	/* used if IEEE_SOFTMAC_BEACONS is set */
+	struct timer_list beacon_timer;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	struct timer_list ibss_wait_timer;
+#endif
+	u8 need_sw_enc;
+#ifdef _RTL8192_EXT_PATCH_
+	struct net_device *meshdev;
+	struct net_device_stats *meshstats;
+	u8 only_mesh;  
+	u8 hostname[MAX_HOST_NAME_LENGTH];
+	u8 hostname_len;
+	struct list_head mesh_network_free_list;
+	struct list_head mesh_network_list;
+	struct rtllib_network *mesh_networks;
+	struct rtllib_network current_mesh_network;
+	enum rtllib_state mesh_state;
+	short mesh_started;
+	int mesh_security_setting;
+	int mesh_sec_type;
+	struct list_head mesh_mac_hash[IEEE_MESH_MAC_HASH_SIZE];
+	u64 LinkingPeerBitMap;
+	u8 LinkingPeerAddr[MAX_MP-1][ETH_ALEN]; 
+	u8 LinkingPeerSecState[MAX_MP-1];
+	u8 mesh_cached_PTK[MAX_MP-1][16];
+	u32 peer_AID_bitmap;
+	u8 peer_AID_Addr[30][ETH_ALEN];
+	int mesh_txkeyidx;
+	u16 mesh_pairwise_key_type;
+	u16 mesh_group_key_type;
+	u32 HwSecCamBitMap; 
+	u8 HwSecCamStaAddr[TOTAL_CAM_ENTRY][ETH_ALEN]; 
+	SW_CAM_TABLE swmeshcamtable[TOTAL_CAM_ENTRY];
+	SW_RATR_TABLE swmeshratrtable[8];
+	short meshid_set;
+	u8 p2pmode;
+	u8 serverExtChlOffset;
+	u8 APExtChlOffset;
+	short meshScanMode;
+	struct sk_buff_head  skb_meshaggQ[MAX_QUEUE_SIZE]; 
+	u8 mesh_amsdu_in_process;
+#endif
+	work_struct_rsl associate_complete_wq;
+#ifdef ENABLE_IPS
+	work_struct_rsl ips_leave_wq;
+#endif    
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	delayed_work_struct_rsl check_tsf_wq;
+	delayed_work_struct_rsl update_assoc_sta_info_wq;
+#endif
+	delayed_work_struct_rsl associate_procedure_wq;
+	delayed_work_struct_rsl softmac_scan_wq;
+	delayed_work_struct_rsl softmac_hint11d_wq;
+	delayed_work_struct_rsl associate_retry_wq;
+	delayed_work_struct_rsl start_ibss_wq;
+#ifndef RTL8190P
+	delayed_work_struct_rsl hw_wakeup_wq;
+	delayed_work_struct_rsl hw_sleep_wq;
+#endif
+	delayed_work_struct_rsl link_change_wq;
+	work_struct_rsl wx_sync_scan_wq;
+#ifdef _RTL8192_EXT_PATCH_
+	work_struct_rsl ext_stop_scan_wq;
+	work_struct_rsl ext_send_beacon_wq;
+	work_struct_rsl ext_create_crypt_for_peers_wq;  
+	work_struct_rsl ext_path_sel_ops_wq;  
+	work_struct_rsl ext_update_extchnloffset_wq;  
+	delayed_work_struct_rsl ext_wx_set_key_wq;
+	work_struct_rsl ext_start_mesh_protocol_wq;  
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)  
+	struct workqueue_struct *wq;
+#else
+	u32 *wq;
+#endif
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40)  
+	/* used for periodly scan */
+	struct timer_list scan_timer;
+#endif
+#if defined (RTL8192S_WAPI_SUPPORT)
+	u8	WapiSupport;    
+	RT_WAPI_T	wapiInfo;
+	struct list_head cache_frag_list;
+	spinlock_t wapi_queue_lock; 
+	WAPI_QUEUE *wapi_queue;	
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+	int (*set_mesh_key)(struct net_device *dev,
+                        struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr);
+#endif
+	/* Callback functions */
+	void (*set_security)(struct net_device *dev,
+			     struct rtllib_security *sec);
+	
+	/* Used to TX data frame by using txb structs.
+	 * this is not used if in the softmac_features
+	 * is set the flag IEEE_SOFTMAC_TX_QUEUE
+	 */
+	int (*hard_start_xmit)(struct rtllib_txb *txb,
+			       struct net_device *dev);
+	
+	int (*reset_port)(struct net_device *dev);
+        int (*is_queue_full) (struct net_device * dev, int pri);
+
+        int (*handle_management) (struct net_device * dev,
+                                  struct rtllib_network * network, u16 type);
+        int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
+
+	/* Softmac-generated frames (mamagement) are TXed via this 
+	 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is 
+	 * not set. As some cards may have different HW queues that 
+	 * one might want to use for data and management frames
+	 * the option to have two callbacks might be useful.
+	 * This fucntion can't sleep.
+	 */
+	int (*softmac_hard_start_xmit)(struct sk_buff *skb,
+			       struct net_device *dev);
+	
+	/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
+	 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
+	 * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
+	 * then also management frames are sent via this callback.
+	 * This function can't sleep.
+	 */    
+	void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
+			       struct net_device *dev,int rate);
+
+	/* stops the HW queue for DATA frames. Useful to avoid
+	 * waste time to TX data frame when we are reassociating
+	 * This function can sleep.
+	 */	 
+	void (*data_hard_stop)(struct net_device *dev);
+	
+	/* OK this is complementar to data_poll_hard_stop */
+	void (*data_hard_resume)(struct net_device *dev);
+	
+	/* ask to the driver to retune the radio .
+	 * This function can sleep. the driver should ensure
+	 * the radio has been swithced before return.
+	 */
+	void (*set_chan)(struct net_device *dev,short ch);
+	
+	/* These are not used if the ieee stack takes care of
+	 * scanning (IEEE_SOFTMAC_SCAN feature set). 
+	 * In this case only the set_chan is used.
+	 *
+	 * The syncro version is similar to the start_scan but
+	 * does not return until all channels has been scanned.
+	 * this is called in user context and should sleep, 
+	 * it is called in a work_queue when swithcing to ad-hoc mode
+	 * or in behalf of iwlist scan when the card is associated 
+	 * and root user ask for a scan. 
+	 * the fucntion stop_scan should stop both the syncro and
+	 * background scanning and can sleep.
+	 * The fucntion start_scan should initiate the background 
+	 * scanning and can't sleep.
+	 */ 
+	void (*scan_syncro)(struct net_device *dev);
+	void (*start_scan)(struct net_device *dev);
+	void (*stop_scan)(struct net_device *dev);
+	
+	void (*rtllib_start_hw_scan)(struct net_device *dev);
+	void (*rtllib_stop_hw_scan)(struct net_device *dev);
+	
+	/* indicate the driver that the link state is changed
+	 * for example it may indicate the card is associated now.
+	 * Driver might be interested in this to apply RX filter 
+	 * rules or simply light the LINK led 
+	 */
+	void (*link_change)(struct net_device *dev);
+	
+	/* these two function indicates to the HW when to start
+	 * and stop to send beacons. This is used when the 
+	 * IEEE_SOFTMAC_BEACONS is not set. For now the
+	 * stop_send_bacons is NOT guaranteed to be called only
+	 * after start_send_beacons.
+	 */
+	void (*start_send_beacons) (struct net_device *dev);
+	void (*stop_send_beacons) (struct net_device *dev);
+	
+	/* power save mode related */
+	void (*sta_wake_up) (struct net_device *dev);
+	void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl);
+	short (*ps_is_queue_empty) (struct net_device *dev);
+#if 0
+	/* Typical STA methods */
+        int (*handle_auth) (struct net_device * dev,
+                            struct rtllib_auth * auth);
+        int (*handle_deauth) (struct net_device * dev,
+                              struct rtllib_deauth * auth);
+        int (*handle_action) (struct net_device * dev,
+                              struct rtllib_action * action,
+                              struct rtllib_rx_stats * stats);
+        int (*handle_disassoc) (struct net_device * dev,
+                                struct rtllib_disassoc * assoc);
+#endif
+        int (*handle_beacon) (struct net_device * dev, struct rtllib_beacon * beacon, struct rtllib_network * network);
+#if 0
+        int (*handle_probe_response) (struct net_device * dev,
+                                      struct rtllib_probe_response * resp,
+                                      struct rtllib_network * network);
+        int (*handle_probe_request) (struct net_device * dev,
+                                     struct rtllib_probe_request * req,
+                                     struct rtllib_rx_stats * stats);
+#endif
+        int (*handle_assoc_response) (struct net_device * dev, struct rtllib_assoc_response_frame * resp, struct rtllib_network * network);
+
+#if 0
+        /* Typical AP methods */
+        int (*handle_assoc_request) (struct net_device * dev);
+        int (*handle_reassoc_request) (struct net_device * dev,
+                                       struct rtllib_reassoc_request * req);
+#endif
+
+	/* check whether Tx hw resouce available */
+	short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
+	short (*get_nic_desc_num)(struct net_device *dev, int queue_index);
+	void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+	bool (*GetNmodeSupportBySecCfg)(struct net_device* dev);
+	void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode);
+	bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev); 
+	u8   (*rtllib_ap_sec_type)(struct rtllib_device *ieee);
+	void (*HalUsbRxAggrHandler)(struct net_device *dev, bool Value);
+	void (*InitialGainHandler)(struct net_device *dev, u8 Operation);
+#ifdef _RTL8192_EXT_PATCH_
+	int (*set_key_for_AP)(struct rtllib_device *ieee);
+	void (*del_hwsec_cam_entry)(struct rtllib_device *ieee, u8 *addr); 
+	int (*set_key_for_peer) (struct net_device *dev,u8 *Addr,u8 KeyIndex,u16 KeyType,u32 *KeyContent );
+	int (*ext_patch_rtllib_start_protocol) (struct rtllib_device *ieee); 
+
+	short (*ext_patch_rtllib_probe_req_1) (struct rtllib_device *ieee); 
+	u8* (*ext_patch_rtllib_probe_req_2) (struct rtllib_device *ieee, struct sk_buff *skb, u8 *tag); 
+
+	void (*ext_patch_rtllib_stop_protocol) (struct rtllib_device *ieee,bool is_silent_reset); 
+	
+	int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_open) (struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm) (struct rtllib_device *ieee, struct sk_buff *skb);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_close) (struct rtllib_device *ieee, struct sk_buff *skb);
+	void (*ext_patch_rtllib_close_all_peerlink) (struct rtllib_device *ieee, __le16 reason);
+
+	int (*ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report) (struct rtllib_device *ieee, struct sk_buff *skb);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req) (struct rtllib_device *ieee, struct sk_buff *skb);
+
+	int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats);
+
+	int (*ext_patch_rtllib_ext_stop_scan_wq_set_channel) (struct rtllib_device *ieee);
+	int (*ext_patch_r819x_wx_set_mesh_chan)(struct net_device *dev, unsigned char channel);
+	void (*ext_patch_r819x_wx_set_channel) (struct rtllib_device *ieee, int ch);
+	
+	int (*ext_patch_rtllib_softmac_xmit_get_rate) (struct rtllib_device *ieee, struct sk_buff *skb);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_auth)(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_rx_frame_softmac_on_deauth)(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats);
+	int (*ext_patch_rtllib_tx_data)(struct rtllib_device *ieee, struct rtllib_hdr_4addrqos* header, u8* is_peer_n_mode, u8* is_peer_40M,
+		u8* is_peer_shortGI_40M, u8* is_peer_shortGI_20M,u8* peer_highest_opra_rate,u8* peer_ratr_index, u8* AID);
+	bool (*ext_patch_rtllib_is_mesh)(struct rtllib_device * ieee,u8 * addr);
+	ppeerMP_htinfo (*ext_patch_rtllib_get_peermp_htinfo) (struct rtllib_device *ieee,u8 * daddr);
+	int (* ext_patch_rtllib_create_crypt_for_peer)(struct rtllib_device * ieee);
+	void (*ext_patch_rtllib_start_mesh)(struct rtllib_device *ieee);
+	void (*ext_patch_rtllib_rx_mgt_on_probe_req) ( struct rtllib_device *ieee, struct rtllib_probe_request *beacon, struct rtllib_rx_stats *stats);
+	unsigned int(*ext_patch_rtllib_process_probe_response_1)(struct rtllib_device *ieee,	struct rtllib_probe_response *beacon,	struct rtllib_rx_stats *stats);
+	
+	void (*ext_patch_rtllib_rx_mgt_update_expire) ( struct rtllib_device *ieee, struct sk_buff *skb);
+	struct sk_buff* (*ext_patch_get_beacon_get_probersp)(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net);
+
+	int (*ext_patch_rtllib_rx_on_rx) (struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats, u16 type, u16 stype);
+	
+	int (*ext_patch_rtllib_rx_frame_get_hdrlen) (struct rtllib_device *ieee, struct sk_buff *skb);
+	
+	int (*ext_patch_rtllib_rx_frame_get_mac_hdrlen) (struct rtllib_device *ieee, struct sk_buff *skb);
+	
+	int (*ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc) (struct rtllib_device *ieee, struct sk_buff *skb);
+	int (*ext_patch_rtllib_rx_is_valid_framectl) (struct rtllib_device *ieee, u16 fc, u16 type, u16 stype);
+	
+	
+	/* added by david for setting acl dynamically */
+	u8 (*ext_patch_rtllib_acl_query) (struct rtllib_device *ieee, u8 *sa);
+
+	
+	struct sk_buff* (*ext_patch_rtllib_send_ath_commit) (struct rtllib_device * ieee,u8 * addr);
+	struct sk_buff* (*ext_patch_rtllib_send_ath_confirm) (struct rtllib_device * ieee,u8 * addr);
+	int (*ext_patch_rtllib_rx_ath_commit) (struct rtllib_device * ieee,u8 * addr);
+	u8 (*ext_patch_rtllib_rx_ath_confirm) (struct rtllib_device *ieee, u8* pframe,u16 strlen,u8 *addr);
+
+#endif 
+	bool (*SetFwCmdHandler)(struct net_device *dev,	FW_CMD_IO_TYPE		FwCmdIO);
+	void (*UpdateHalRAMaskHandler)(struct net_device* dev, bool bMulticast, u8 macId, u8 MimoPs, u8 WirelessMode, u8 bCurTxBW40MHz,	u8 rssi_level);
+	void (*UpdateBeaconInterruptHandler)(struct net_device* dev, bool start);
+	u16  (*rtl_11n_user_show_rates)(struct net_device *dev);
+	void (*ScanOperationBackupHandler)(struct net_device *dev, u8 Operation);
+	void (*LedControlHandler)(struct net_device * dev, LED_CTL_MODE LedAction);
+	void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+	void (*GetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+
+	void (*AllowAllDestAddrHandler)(struct net_device *dev, bool bAllowAllDA, bool WriteIntoReg);
+	
+#ifdef ENABLE_IPS
+        void (*rtllib_ips_leave_wq) (struct net_device *dev);
+        void (*rtllib_ips_leave)(struct net_device *dev);
+#endif
+#ifdef ENABLE_LPS
+	void (*LeisurePSLeave)(struct net_device *dev);
+#endif
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	void (*SetBeaconRelatedRegistersHandler)(struct net_device* dev);
+	bool (*check_ht_cap)(struct net_device* dev, struct sta_info *sta, struct rtllib_network* net);
+	void (*Adhoc_InitRateAdaptive)(struct net_device *dev,struct sta_info  *pEntry);
+#endif
+	void (*rtllib_rfkill_poll)(struct net_device *dev);
+
+	/* This must be the last item so that it points to the data
+	 * allocated beyond this structure by alloc_rtllib */
+	u8 priv[0];
+};
+
+#define IEEE_A            (1<<0)
+#define IEEE_B            (1<<1)
+#define IEEE_G            (1<<2)
+#define IEEE_N_24G 		  (1<<4)
+#define	IEEE_N_5G		  (1<<5)
+#define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
+
+/* Generate a 802.11 header */
+
+/* Uses the channel change callback directly
+ * instead of [start/stop] scan callbacks
+ */
+#define IEEE_SOFTMAC_SCAN (1<<2)
+
+/* Perform authentication and association handshake */
+#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
+
+/* Generate probe requests */
+#define IEEE_SOFTMAC_PROBERQ (1<<4)
+
+/* Generate respones to probe requests */
+#define IEEE_SOFTMAC_PROBERS (1<<5)
+
+/* The ieee802.11 stack will manages the netif queue
+ * wake/stop for the driver, taking care of 802.11
+ * fragmentation. See softmac.c for details. */
+#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
+
+/* Uses only the softmac_data_hard_start_xmit
+ * even for TX management frames.
+ */
+#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
+
+/* Generate beacons.  The stack will enqueue beacons
+ * to the card 
+ */ 
+#define IEEE_SOFTMAC_BEACONS (1<<6)
+
+#ifdef _RTL8192_EXT_PATCH_
+static inline int rtllib_find_MP(struct rtllib_device* ieee, const u8* addr, u8 set)
+{
+	int i=0;
+	for (i=1; i<MAX_MP; i++) {
+		if ((ieee->cryptlist[i]->used == 0) && set) {
+			memcpy(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN);
+			ieee->cryptlist[i]->used = 1;
+			return i;
+		} else if (0 == memcmp(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN)) {
+			return i;
+		}
+	}
+	return -1;
+}
+#endif
+
+static inline void *rtllib_priv(struct net_device *dev)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 
+	return ((struct rtllib_device *)netdev_priv(dev))->priv;
+#else
+	return ((struct rtllib_device *)dev->priv)->priv;
+#endif
+}
+
+extern inline int rtllib_is_empty_essid(const char *essid, int essid_len)
+{
+	/* Single white space is for Linksys APs */
+	if (essid_len == 1 && essid[0] == ' ')
+		return 1;
+
+	/* Otherwise, if the entire essid is 0, we assume it is hidden */
+	while (essid_len) {
+		essid_len--;
+		if (essid[essid_len] != '\0')
+			return 0;
+	}
+
+	return 1;
+}
+
+extern inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
+{
+	/*
+	 * It is possible for both access points and our device to support
+	 * combinations of modes, so as long as there is one valid combination
+	 * of ap/device supported modes, then return success
+	 *
+	 */
+	if ((mode & IEEE_A) &&
+	    (ieee->modulation & RTLLIB_OFDM_MODULATION) &&
+	    (ieee->freq_band & RTLLIB_52GHZ_BAND))
+		return 1;
+
+	if ((mode & IEEE_G) &&
+	    (ieee->modulation & RTLLIB_OFDM_MODULATION) &&
+	    (ieee->freq_band & RTLLIB_24GHZ_BAND))
+		return 1;
+
+	if ((mode & IEEE_B) &&
+	    (ieee->modulation & RTLLIB_CCK_MODULATION) &&
+	    (ieee->freq_band & RTLLIB_24GHZ_BAND))
+		return 1;
+
+	return 0;
+}
+
+extern inline int rtllib_get_hdrlen(u16 fc)
+{
+	int hdrlen = RTLLIB_3ADDR_LEN;
+
+	switch (WLAN_FC_GET_TYPE(fc)) {
+	case RTLLIB_FTYPE_DATA:
+		if ((fc & RTLLIB_FCTL_FROMDS) && (fc & RTLLIB_FCTL_TODS))
+			hdrlen = RTLLIB_4ADDR_LEN; /* Addr4 */
+		if(RTLLIB_QOS_HAS_SEQ(fc))
+			hdrlen += 2; /* QOS ctrl*/
+		break;
+	case RTLLIB_FTYPE_CTL:
+		switch (WLAN_FC_GET_STYPE(fc)) {
+		case RTLLIB_STYPE_CTS:
+		case RTLLIB_STYPE_ACK:
+			hdrlen = RTLLIB_1ADDR_LEN;
+			break;
+		default:
+			hdrlen = RTLLIB_2ADDR_LEN;
+			break;
+		}
+		break;
+	}
+
+	return hdrlen;
+}
+
+static inline u8 *rtllib_get_payload(struct rtllib_hdr *hdr)
+{
+        switch (rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+        case RTLLIB_1ADDR_LEN:
+                return ((struct rtllib_hdr_1addr *)hdr)->payload;
+        case RTLLIB_2ADDR_LEN:
+                return ((struct rtllib_hdr_2addr *)hdr)->payload;
+        case RTLLIB_3ADDR_LEN:
+                return ((struct rtllib_hdr_3addr *)hdr)->payload;
+        case RTLLIB_4ADDR_LEN:
+                return ((struct rtllib_hdr_4addr *)hdr)->payload;
+        }
+        return NULL;
+}
+
+static inline int rtllib_is_ofdm_rate(u8 rate)
+{
+        switch (rate & ~RTLLIB_BASIC_RATE_MASK) {
+        case RTLLIB_OFDM_RATE_6MB:
+        case RTLLIB_OFDM_RATE_9MB:
+        case RTLLIB_OFDM_RATE_12MB:
+        case RTLLIB_OFDM_RATE_18MB:
+        case RTLLIB_OFDM_RATE_24MB:
+        case RTLLIB_OFDM_RATE_36MB:
+        case RTLLIB_OFDM_RATE_48MB:
+        case RTLLIB_OFDM_RATE_54MB:
+                return 1;
+        }
+        return 0;
+}
+
+static inline int rtllib_is_cck_rate(u8 rate)
+{
+        switch (rate & ~RTLLIB_BASIC_RATE_MASK) {
+        case RTLLIB_CCK_RATE_1MB:
+        case RTLLIB_CCK_RATE_2MB:
+        case RTLLIB_CCK_RATE_5MB:
+        case RTLLIB_CCK_RATE_11MB:
+                return 1;
+        }
+        return 0;
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
+static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2)
+{
+	const u16 *a = (const u16 *) addr1;
+	const u16 *b = (const u16 *) addr2;
+
+	BUILD_BUG_ON(ETH_ALEN != 6);
+	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+}
+#endif
+
+/* rtllib.c */
+extern void free_rtllib(struct net_device *dev);
+extern struct net_device *alloc_rtllib(int sizeof_priv);
+
+extern int rtllib_set_encryption(struct rtllib_device *ieee);
+
+/* rtllib_tx.c */
+
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_encrypt_fragment(
+	struct rtllib_device *ieee,
+	struct sk_buff *frag,
+	int hdr_len, u8 is_mesh, u8 entry);
+#else
+extern int rtllib_encrypt_fragment(
+	struct rtllib_device *ieee,
+	struct sk_buff *frag,
+	int hdr_len);
+#endif
+
+extern int rtllib_xmit(struct sk_buff *skb,  struct net_device *dev);
+extern int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev);
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu);
+extern int rtllib_mesh_xmit(struct sk_buff *skb,  struct net_device *dev);
+extern inline int rtllib_put_snap(u8 *data, u16 h_proto);
+#endif
+extern void rtllib_txb_free(struct rtllib_txb *);
+
+#ifdef ENABLE_AMSDU
+extern struct sk_buff *AMSDU_Aggregation(struct rtllib_device *ieee, struct sk_buff_head *pSendList);
+extern u8 AMSDU_GetAggregatibleList(struct rtllib_device *ieee, struct sk_buff *pCurSkb, struct sk_buff_head	*pSendList, u8 queue_index);
+extern struct sk_buff *msh_AMSDU_Aggregation(struct rtllib_device *ieee, struct sk_buff_head *pSendList);
+extern u8 msh_AMSDU_GetAggregatibleList(struct rtllib_device *ieee, struct sk_buff *pCurSkb, struct sk_buff_head *pSendList, u8 queue_index);
+#endif
+
+/* rtllib_rx.c */
+extern int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+			struct rtllib_rx_stats *rx_stats);
+extern void rtllib_rx_mgt(struct rtllib_device *ieee,
+			     struct sk_buff *skb,
+			     struct rtllib_rx_stats *stats);
+extern void rtllib_rx_probe_rq(struct rtllib_device *ieee, 
+                           struct sk_buff *skb);
+extern int IsLegalChannel( struct rtllib_device *rtllib, u8 channel);
+
+/* rtllib_wx.c */
+extern int rtllib_wx_get_scan(struct rtllib_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *key);
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_wx_set_encode(struct rtllib_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key, u8 is_mesh);
+extern int rtllib_wx_get_encode(struct rtllib_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key, u8 is_mesh);
+extern int rtllib_mesh_set_encode_ext(struct rtllib_device *ieee,
+                               struct iw_point *encoding, struct iw_encode_ext *ext, int entry);
+#if WIRELESS_EXT >= 18
+extern int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+                            struct iw_request_info *info,
+                            union iwreq_data* wrqu, char *extra, u8 is_mesh);
+extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+                            struct iw_request_info *info,
+                            union iwreq_data* wrqu, char *extra, u8 is_mesh);
+#endif
+#else
+extern int rtllib_wx_set_encode(struct rtllib_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key);
+extern int rtllib_wx_get_encode(struct rtllib_device *ieee,
+				   struct iw_request_info *info,
+				   union iwreq_data *wrqu, char *key);
+#if WIRELESS_EXT >= 18
+extern int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+                            struct iw_request_info *info,
+                            union iwreq_data* wrqu, char *extra);
+extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+                            struct iw_request_info *info,
+                            union iwreq_data* wrqu, char *extra);
+#endif
+#endif
+extern int rtllib_wx_set_auth(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               struct iw_param *data, char *extra);
+extern int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra);
+extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
+
+/* rtllib_softmac.c */
+extern short rtllib_is_54g(struct rtllib_network *net);
+extern short rtllib_is_shortslot(struct rtllib_network net);
+extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb,
+			struct rtllib_rx_stats *rx_stats, u16 type,
+			u16 stype);
+extern void rtllib_softmac_new_net(struct rtllib_device *ieee, struct rtllib_network *net);
+
+void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn);
+extern void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee);
+
+extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+extern void notify_wx_assoc_event(struct rtllib_device *ieee);
+extern void rtllib_softmac_check_all_nets(struct rtllib_device *ieee);
+extern void rtllib_start_bss(struct rtllib_device *ieee);
+extern void rtllib_start_master_bss(struct rtllib_device *ieee);
+extern void rtllib_start_ibss(struct rtllib_device *ieee);
+extern void rtllib_softmac_init(struct rtllib_device *ieee);
+extern void rtllib_softmac_free(struct rtllib_device *ieee);
+extern void rtllib_associate_abort(struct rtllib_device *ieee);
+extern void rtllib_disassociate(struct rtllib_device *ieee);
+extern void rtllib_stop_scan(struct rtllib_device *ieee);
+extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
+extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
+extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+extern inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee);
+extern u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee);
+extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr);
+extern void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
+extern void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
+extern void rtllib_check_all_nets(struct rtllib_device *ieee);
+extern void rtllib_start_protocol(struct rtllib_device *ieee);
+extern void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
+
+extern void rtllib_EnableNetMonitorMode(struct net_device* dev, bool bInitState);
+extern void rtllib_DisableNetMonitorMode(struct net_device* dev, bool bInitState);
+extern void rtllib_EnableIntelPromiscuousMode(struct net_device* dev, bool bInitState);
+extern void rtllib_DisableIntelPromiscuousMode(struct net_device* dev, bool bInitState);
+#ifdef _RTL8192_EXT_PATCH_
+extern void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh);
+#else
+extern void rtllib_send_probe_requests(struct rtllib_device *ieee);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee,u8 mesh_flag);
+extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown);
+extern void rtllib_start_mesh_protocol(struct rtllib_device *ieee);
+extern void rtllib_stop_mesh_protocol(struct rtllib_device *ieee);
+#else
+extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee);
+extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
+#endif
+extern void rtllib_reset_queue(struct rtllib_device *ieee);
+extern void rtllib_wake_queue(struct rtllib_device *ieee);
+extern void rtllib_stop_queue(struct rtllib_device *ieee);
+extern void rtllib_wake_all_queues(struct rtllib_device *ieee);
+extern void rtllib_stop_all_queues(struct rtllib_device *ieee);
+extern struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
+extern void rtllib_start_send_beacons(struct rtllib_device *ieee);
+extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, u8 is_mesh);
+#else
+extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p);
+#endif
+extern void notify_wx_assoc_event(struct rtllib_device *ieee);
+extern void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
+
+extern void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee);
+extern u16 rtllib_query_seqnum(struct rtllib_device*ieee, struct sk_buff* skb, u8* dst);
+extern u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
+
+#ifdef _RTL8192_EXT_PATCH_
+extern void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8* dest);
+extern void rtllib_associate_step1(struct rtllib_device *ieee,u8 * addr);
+extern bool rtllib_ext_prepare_to_joinmesh(struct rtllib_device *ieee, struct rtllib_network *pstat);
+extern u8 HTFilterMCSRate( struct rtllib_device* ieee, u8* pSupportMCS, u8* pOperateMCS);
+extern void HTUseDefaultSetting(struct rtllib_device* ieee);
+extern void rtllib_start_scan(struct rtllib_device *ieee);
+extern struct sk_buff* rtllib_ext_probe_resp_by_net(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net);
+extern int rtllib_network_init(struct rtllib_device *ieee, struct rtllib_probe_response *beacon, struct rtllib_network *network, struct rtllib_rx_stats *stats);
+extern struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, int gfp_mask);
+extern void rtllib_ext_send_11s_beacon(struct rtllib_device *ieee);
+#endif
+
+/* rtllib_crypt_ccmp&tkip&wep.c */
+extern void rtllib_tkip_null(void);
+extern void rtllib_wep_null(void);
+extern void rtllib_ccmp_null(void);
+
+/* rtllib_softmac_wx.c */
+
+extern int rtllib_wx_get_wap(struct rtllib_device *ieee, 
+			    struct iw_request_info *info, 
+			    union iwreq_data *wrqu, char *ext);
+			    
+extern int rtllib_wx_set_wap(struct rtllib_device *ieee,
+			 struct iw_request_info *info,
+			 union iwreq_data *awrq,
+			 char *extra);
+			 
+extern int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
+
+extern int rtllib_wx_set_rate(struct rtllib_device *ieee, 
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra);
+			     
+extern int rtllib_wx_get_rate(struct rtllib_device *ieee, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra);
+			     
+extern int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b);
+			     
+extern int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b);
+			     
+extern int rtllib_wx_set_essid(struct rtllib_device *ieee, 
+			      struct iw_request_info *a,
+			      union iwreq_data *wrqu, char *extra);
+			      
+extern int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b);
+
+#ifdef _RTL8192_EXT_PATCH_
+extern int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b, u8 is_mesh);
+#else
+extern int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b);
+#endif
+extern void rtllib_wx_sync_scan_wq(void *data);
+
+extern int rtllib_wx_set_rawtx(struct rtllib_device *ieee, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra);
+			       
+extern int rtllib_wx_get_name(struct rtllib_device *ieee, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_set_power(struct rtllib_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_power(struct rtllib_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_set_rts(struct rtllib_device *ieee, 
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_rts(struct rtllib_device *ieee, 
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra);
+#ifdef _RTL8192_EXT_PATCH_
+extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr);
+#endif
+#define MAX_RECEIVE_BUFFER_SIZE 9100  
+extern void HTDebugHTCapability(u8* CapIE, u8* TitleString );
+extern void HTDebugHTInfo(u8*  InfoIE, u8* TitleString);
+
+void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET    Offset);
+extern void HTUpdateDefaultSetting(struct rtllib_device* ieee);
+#ifdef _RTL8192_EXT_PATCH_
+extern void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt, u8 bIsBcn);
+#else
+extern void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt);
+#endif
+extern void HTConstructInfoElement(struct rtllib_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt);
+extern void HTConstructRT2RTAggElement(struct rtllib_device* ieee, u8* posRT2RTAgg, u8* len);
+extern void HTOnAssocRsp(struct rtllib_device *ieee);
+extern void HTInitializeHTInfo(struct rtllib_device* ieee);
+extern void HTInitializeBssDesc(PBSS_HT pBssHT);
+extern void HTResetSelfAndSavePeerSetting(struct rtllib_device* ieee, struct rtllib_network * pNetwork);
+extern void HTUpdateSelfAndPeerSetting(struct rtllib_device* ieee,   struct rtllib_network * pNetwork);
+extern u8 HTGetHighestMCSRate(struct rtllib_device* ieee, u8* pMCSRateSet, u8* pMCSFilter);
+extern u8 MCS_FILTER_ALL[];
+extern u16 MCS_DATA_RATE[2][2][77] ;
+extern u8 HTCCheck(struct rtllib_device* ieee, u8*   pFrame);
+extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT  pHTInfo);
+extern bool IsHTHalfNmodeAPs(struct rtllib_device* ieee);
+extern u16 HTHalfMcsToDataRate(struct rtllib_device* ieee,  u8      nMcsRate);
+extern u16 HTMcsToDataRate( struct rtllib_device* ieee, u8 nMcsRate);
+extern u16  TxCountToDataRate( struct rtllib_device* ieee, u8 nDataRate);
+extern int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb);
+extern int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb);
+extern int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb);
+extern void TsInitAddBA( struct rtllib_device* ieee, PTX_TS_RECORD   pTS, u8 Policy, u8 bOverwritePending);
+extern void TsInitDelBA( struct rtllib_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
+extern void BaSetupTimeOut(unsigned long data);
+extern void TxBaInactTimeout(unsigned long data);
+extern void RxBaInactTimeout(unsigned long data);
+extern void ResetBaEntry( PBA_RECORD pBA);
+extern bool GetTs(
+        struct rtllib_device*        ieee,
+        PTS_COMMON_INFO                 *ppTS,
+        u8*                             Addr,
+        u8                              TID,
+        TR_SELECT                       TxRxSelect,  
+        bool                            bAddNewTs
+        );
+extern void TSInitialize(struct rtllib_device *ieee);
+extern  void TsStartAddBaProcess(struct rtllib_device* ieee, PTX_TS_RECORD   pTxTS);			 			     
+extern void RemovePeerTS(struct rtllib_device* ieee, u8* Addr);
+extern void RemoveAllTS(struct rtllib_device* ieee);
+#ifdef _RTL8192_EXT_PATCH_
+extern void ResetAdmitTRStream(struct rtllib_device *ieee, u8 *Addr);
+#endif
+void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+
+extern const long rtllib_wlan_frequencies[];
+
+extern inline void rtllib_increment_scans(struct rtllib_device *ieee)
+{
+	ieee->scans++;
+}
+
+extern inline int rtllib_get_scans(struct rtllib_device *ieee)
+{
+	return ieee->scans;
+}
+
+static inline const char *escape_essid(const char *essid, u8 essid_len) {
+	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+	const char *s = essid;
+	char *d = escaped;
+
+	if (rtllib_is_empty_essid(essid, essid_len)) {
+		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
+		return escaped;
+	}
+
+	essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
+	while (essid_len--) {
+		if (*s == '\0') {
+			*d++ = '\\';
+			*d++ = '0';
+			s++;
+		} else {
+			*d++ = *s++;
+		}
+	}
+	*d = '\0';
+	return escaped;
+}
+
+#define CONVERT_RATE(_ieee, _MGN_RATE)	(_MGN_RATE<MGN_MCS0)?(_MGN_RATE):(HTMcsToDataRate(_ieee, (u8)_MGN_RATE))
+
+#ifdef BUILT_IN_RTLLIB
+/* fun with the built-in rtllib stack... */
+int rtllib_init(void);
+void rtllib_exit(void);
+int rtllib_crypto_init(void);
+void rtllib_crypto_deinit(void);
+int rtllib_crypto_tkip_init(void);
+void rtllib_crypto_tkip_exit(void);
+int rtllib_crypto_ccmp_init(void);
+void rtllib_crypto_ccmp_exit(void);
+int rtllib_crypto_wep_init(void);
+void rtllib_crypto_wep_exit(void);
+#endif
+/* For the function is more related to hardware setting, it's better to use the  
+ * ieee handler to refer to it.
+ */
+extern void rtllib_update_active_chan_map(struct rtllib_device *ieee);
+extern void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee, PRX_TS_RECORD pTS);
+extern int rtllib_data_xmit(struct sk_buff *skb, struct net_device *dev);
+extern int rtllib_parse_info_param(struct rtllib_device *ieee,
+		struct rtllib_info_element *info_element, 
+		u16 length,
+		struct rtllib_network *network,
+		struct rtllib_rx_stats *stats);
+
+void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb** prxbIndicateArray,u8  index);
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+extern void IbssAgeFunction(struct rtllib_device *ieee);
+extern struct sta_info *GetStaInfo(struct rtllib_device *ieee, u8 *addr);
+extern void DelStaInfoList(struct rtllib_device *ieee);
+extern void DelStaInfo(struct rtllib_device *ieee, u8 *addr);
+#endif
+extern u8 HTFilterMCSRate( struct rtllib_device* ieee, u8* pSupportMCS, u8* pOperateMCS);
+extern void HTUseDefaultSetting(struct rtllib_device* ieee);
+#define RT_ASOC_RETRY_LIMIT	5
+u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee);
+#ifdef _RTL8192_EXT_PATCH_
+extern unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee);
+extern void rtllib_MFIE_Brate(struct rtllib_device *ieee, u8 **tag_p);
+extern void rtllib_MFIE_Grate(struct rtllib_device *ieee, u8 **tag_p);
+extern void rtllib_WMM_Info(struct rtllib_device *ieee, u8 **tag_p);
+#endif
+#ifdef THOMAS_TURBO
+extern void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p);
+#endif
+#ifndef ENABLE_LOCK_DEBUG
+#define SPIN_LOCK_IEEE(plock) spin_lock_irqsave((plock), flags)	
+#define SPIN_UNLOCK_IEEE(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_REORDER(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_REORDER(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_WPAX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_WPAX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_MGNTTX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_MGNTTX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_BCN(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_BCN(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_STAINFO(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_STAINFO(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_PREQ(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_PREQ(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_QUEUE(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_QUEUE(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_RFPS(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_RFPS(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_IRQTH(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_IRQTH(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_TX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_TX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_D3(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_D3(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_RF(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_RF(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_PS(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_PS(plock) spin_unlock_irqrestore((plock), flags)
+#define SEM_DOWN_IEEE_WX(psem) down(psem)
+#define SEM_UP_IEEE_WX(psem) up(psem)
+#define SEM_DOWN_IEEE_SCAN(psem) down(psem)
+#define SEM_UP_IEEE_SCAN(psem) up(psem)
+#define SEM_DOWN_IEEE_IPS(psem) down(psem)
+#define SEM_UP_IEEE_IPS(psem) up(psem)
+#define SEM_DOWN_PRIV_WX(psem) down(psem)
+#define SEM_UP_PRIV_WX(psem) up(psem)
+#define SEM_DOWN_PRIV_RF(psem) down(psem)
+#define SEM_UP_PRIV_RF(psem) up(psem)
+#define MUTEX_LOCK_PRIV(pmutex) mutex_lock(pmutex)
+#define MUTEX_UNLOCK_PRIV(pmutex) mutex_unlock(pmutex)
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+extern void WapiInit(struct rtllib_device *ieee);
+extern void WapiExit(struct rtllib_device *ieee);
+extern int WAPI_CreateEvent_Send(struct rtllib_device *ieee, u8 EventId, u8 *MacAddr, u8 *Buff, u16 BufLen);
+extern void WapiCreateAppEventAndSend(
+	struct rtllib_device *ieee,
+	u8 		*pbuffer,
+	u16		buf_len,
+	u8 		*DestAddr,
+	u8		bUpdateBK,
+	u8		bUpdateUSK,
+	u8		bUpdateMSK,
+	u8		RcvPktType,
+	u8		bDisconnect);
+extern void WapiReturnAllStaInfo(struct rtllib_device *ieee);
+extern void WapiReturnOneStaInfo(struct rtllib_device *ieee, u8 *MacAddr, u8 from_app);
+extern void WapiFreeAllStaInfo(struct rtllib_device *ieee);
+extern u8 SecIsWAIPacket(struct rtllib_device* ieee,struct sk_buff *skb);
+extern void WapiHandleRecvPacket(struct rtllib_device* ieee,struct sk_buff *skb,u8 WaiPkt);
+extern void WapiSetIE(struct rtllib_device *ieee);
+extern u32 WapiComparePN(u8 *PN1, u8 *PN2);
+extern u8 WapiIncreasePN(u8 *PN, u8 AddCount);
+extern void WapiGetLastRxUnicastPNForQoSData(
+	u8 			UserPriority,
+	PRT_WAPI_STA_INFO    pWapiStaInfo,
+	u8 *PNOut);
+extern void WapiSetLastRxUnicastPNForQoSData(
+	u8 		UserPriority,
+	u8           *PNIn,
+	PRT_WAPI_STA_INFO    pWapiStaInfo);
+extern u8 WapiCheckPnInSwDecrypt(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb);
+extern u8 WapiCheckDropForRxReorderCase(
+	struct rtllib_device *ieee,
+	struct rtllib_rxb* prxb);
+extern int SecSMS4HeaderFillIV(struct rtllib_device *ieee, struct sk_buff *pskb);
+extern void SecSWSMS4Encryption(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb);
+extern u8 SecSWSMS4Decryption(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb,
+	struct rtllib_rx_stats *rx_stats);
+
+extern int WapiSendWaiPacket(struct rtllib_device *ieee, struct sk_buff *pskb);
+extern void ieee80211_disassociate_from_app(struct rtllib_device *ieee);
+extern void ConstructWapiIEForInit(struct rtllib_device* ieee);
+extern void wapi_test_init(struct rtllib_device *ieee);
+#endif
+static inline void dump_buf(u8 *buf, u32 len)
+{
+	u32 i;
+	printk("-----------------Len %d----------------\n", len);
+	for(i=0; i<len; i++)
+		printk("%2.2x-", *(buf+i));
+	printk("\n");
+}
+#endif /* RTLLIB_H */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/wapi_interface.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/wapi_interface.c
@@ -0,0 +1,151 @@
+#if defined (RTL8192S_WAPI_SUPPORT)
+
+#include "wapi.h"
+#include "wapi_interface.h"  
+#include "rtllib.h"
+
+
+/*************************************************************
+ * WAPI EVENT QUEUE : 										 *
+ * Buffer events from driver to application.            					 * 
+ *************************************************************/
+void WAPI_InitQueue(WAPI_QUEUE * q, int szMaxItem, int szMaxData)
+{
+	RT_ASSERT_RET(q);
+	
+	q->Head = 0;
+	q->Tail = 0;
+	q->NumItem = 0;
+	q->MaxItem = szMaxItem;
+	q->MaxData = szMaxData;
+}
+
+int WAPI_EnQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int itemsize)
+{
+	unsigned long flags;
+
+	RT_ASSERT_RET_VALUE(plock, (-E_WAPI_QNULL));
+	RT_ASSERT_RET_VALUE(q, (-E_WAPI_QNULL));
+	RT_ASSERT_RET_VALUE(item, (-E_WAPI_QNULL));
+	
+	if(WAPI_IsFullQueue(q))
+		return -E_WAPI_QFULL;
+	if(itemsize > q->MaxData)
+		return -E_WAPI_ITEM_TOO_LARGE;
+
+ 	spin_lock_irqsave(plock, flags);
+
+	q->ItemArray[q->Tail].ItemSize = itemsize;
+	memset(q->ItemArray[q->Tail].Item, 0, sizeof(q->ItemArray[q->Tail].Item));
+	memcpy(q->ItemArray[q->Tail].Item, item, itemsize);
+	q->NumItem++;
+	if((q->Tail+1) == q->MaxItem)
+		q->Tail = 0;
+	else
+		q->Tail++;
+
+	spin_unlock_irqrestore(plock, flags);
+	
+	return E_WAPI_OK;
+}
+
+
+int WAPI_DeQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int *itemsize)
+{
+	unsigned long flags;
+
+	RT_ASSERT_RET_VALUE(plock, (-E_WAPI_QNULL));
+	RT_ASSERT_RET_VALUE(q, (-E_WAPI_QNULL));
+	RT_ASSERT_RET_VALUE(item, (-E_WAPI_QNULL));
+	
+	if(WAPI_IsEmptyQueue(q))
+		return -E_WAPI_QEMPTY;
+
+ 	spin_lock_irqsave(plock, flags);
+	
+	memcpy(item, q->ItemArray[q->Head].Item, q->ItemArray[q->Head].ItemSize);
+	*itemsize = q->ItemArray[q->Head].ItemSize;
+	q->NumItem--;
+	if((q->Head+1) == q->MaxItem)
+		q->Head = 0;
+	else
+		q->Head++;
+
+	spin_unlock_irqrestore(plock, flags);
+	
+	return E_WAPI_OK;
+}
+
+void WAPI_PrintQueue(WAPI_QUEUE *q)
+{
+	int i, j, index;
+
+	RT_ASSERT_RET(q);
+	
+	printk("\n/-------------------------------------------------\n");
+	printk("[DOT11_PrintQueue]: MaxItem = %d, NumItem = %d, Head = %d, Tail = %d\n", q->MaxItem, q->NumItem, q->Head, q->Tail);
+	for(i=0; i<q->NumItem; i++) {
+		index = (i + q->Head) % q->MaxItem;
+		printk("Queue[%d].ItemSize = %d  ", index, q->ItemArray[index].ItemSize);
+		for(j=0; j<q->ItemArray[index].ItemSize; j++)
+			printk(" %x", q->ItemArray[index].Item[j]);
+		printk("\n");
+	}
+	printk("------------------------------------------------/\n");
+}
+
+int pid_wapi = 0;
+void notifyWapiApplication()
+{ 
+	struct task_struct *p;
+        
+	if(pid_wapi != 0){
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		p = find_task_by_pid(pid_wapi);
+#else
+                p = find_task_by_vpid(pid_wapi);
+#endif
+		if(p){
+			send_sig(SIGUSR1,p,0); 
+		}else {
+			pid_wapi = 0;
+		}
+	}
+}
+
+int WAPI_CreateEvent_Send(struct rtllib_device *ieee, u8 EventId, u8 *MacAddr, u8 *Buff, u16 BufLen)
+{
+	WAPI_EVENT_T *pEvent;
+	u8 *pbuf = NULL;
+	int ret = 0;
+	
+	WAPI_TRACE(WAPI_API, "==========> %s: EventId=%d\n", __FUNCTION__, EventId);
+	
+	RT_ASSERT_RET_VALUE(ieee, -1);
+	RT_ASSERT_RET_VALUE(MacAddr, -1);
+
+	pbuf= (u8 *)kmalloc((sizeof(WAPI_EVENT_T) + BufLen), GFP_ATOMIC);
+	if(NULL == pbuf)
+	    return -1;
+
+	pEvent = (WAPI_EVENT_T *)pbuf;	
+	pEvent->EventId = EventId;
+	memcpy(pEvent->MACAddr, MacAddr, ETH_ALEN);
+	pEvent->BuffLength = BufLen;
+	if(BufLen > 0){
+		memcpy(pEvent->Buff, Buff, BufLen);
+	}
+
+	ret = WAPI_EnQueue(&ieee->wapi_queue_lock, ieee->wapi_queue, pbuf, (sizeof(WAPI_EVENT_T) + BufLen));
+	notifyWapiApplication();
+
+	if(pbuf)
+		kfree(pbuf);
+
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+	return ret;
+}
+
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/autoload.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/autoload.c
@@ -0,0 +1,41 @@
+/*
+ * Cryptographic API.
+ *
+ * Algorithm autoloader.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include "kmap_types.h"
+
+#include <linux/kernel.h>
+#include "rtl_crypto.h"
+#include <linux/string.h>
+#include <linux/kmod.h>
+#include "internal.h"
+
+#ifdef CONFIG_KMOD
+/*
+ * A far more intelligent version of this is planned.  For now, just
+ * try an exact match on the name of the algorithm.
+ */
+void crypto_alg_autoload(const char *name)
+{
+	request_module(name);
+}
+
+struct crypto_alg *crypto_alg_mod_lookup(const char *name)
+{
+	struct crypto_alg *alg = crypto_alg_lookup(name);
+	if (alg == NULL) {
+		crypto_alg_autoload(name);
+		alg = crypto_alg_lookup(name);
+	}
+	return alg;
+}
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/license
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/license
@@ -0,0 +1,339 @@
+
+"This software program is licensed subject to the GNU General Public License 
+(GPL). Version 2, June 1991, available at 
+<http:
+
+GNU General Public License 
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to 
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure 
+the software is free for all its users. This General Public License applies 
+to most of the Free Software Foundation's software and to any other program 
+whose authors commit to using it. (Some other Free Software Foundation 
+software is covered by the GNU Library General Public License instead.) You 
+can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom 
+to distribute copies of free software (and charge for this service if you 
+wish), that you receive source code or can get it if you want it, that you 
+can change the software or use pieces of it in new free programs; and that 
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to 
+deny you these rights or to ask you to surrender the rights. These 
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or 
+for a fee, you must give the recipients all the rights that you have. You 
+must make sure that they, too, receive or can get the source code. And you 
+must show them these terms so they know their rights.
+ 
+We protect your rights with two steps: (1) copyright the software, and (2) 
+offer you this license which gives you legal permission to copy, distribute 
+and/or modify the software. 
+
+Also, for each author's protection and ours, we want to make certain that 
+everyone understands that there is no warranty for this free software. If 
+the software is modified by someone else and passed on, we want its 
+recipients to know that what they have is not the original, so that any 
+problems introduced by others will not reflect on the original authors' 
+reputations. 
+
+Finally, any free program is threatened constantly by software patents. We 
+wish to avoid the danger that redistributors of a free program will 
+individually obtain patent licenses, in effect making the program 
+proprietary. To prevent this, we have made it clear that any patent must be 
+licensed for everyone's free use or not licensed at all. 
+
+The precise terms and conditions for copying, distribution and modification 
+follow. 
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+   placed by the copyright holder saying it may be distributed under the 
+   terms of this General Public License. The "Program", below, refers to any
+   such program or work, and a "work based on the Program" means either the 
+   Program or any derivative work under copyright law: that is to say, a 
+   work containing the Program or a portion of it, either verbatim or with 
+   modifications and/or translated into another language. (Hereinafter, 
+   translation is included without limitation in the term "modification".) 
+   Each licensee is addressed as "you". 
+
+   Activities other than copying, distribution and modification are not 
+   covered by this License; they are outside its scope. The act of running 
+   the Program is not restricted, and the output from the Program is covered 
+   only if its contents constitute a work based on the Program (independent 
+   of having been made by running the Program). Whether that is true depends
+   on what the Program does. 
+
+1. You may copy and distribute verbatim copies of the Program's source code 
+   as you receive it, in any medium, provided that you conspicuously and 
+   appropriately publish on each copy an appropriate copyright notice and 
+   disclaimer of warranty; keep intact all the notices that refer to this 
+   License and to the absence of any warranty; and give any other recipients 
+   of the Program a copy of this License along with the Program. 
+
+   You may charge a fee for the physical act of transferring a copy, and you 
+   may at your option offer warranty protection in exchange for a fee. 
+
+2. You may modify your copy or copies of the Program or any portion of it, 
+   thus forming a work based on the Program, and copy and distribute such 
+   modifications or work under the terms of Section 1 above, provided that 
+   you also meet all of these conditions: 
+
+   * a) You must cause the modified files to carry prominent notices stating 
+        that you changed the files and the date of any change. 
+
+   * b) You must cause any work that you distribute or publish, that in 
+        whole or in part contains or is derived from the Program or any part 
+        thereof, to be licensed as a whole at no charge to all third parties
+        under the terms of this License. 
+
+   * c) If the modified program normally reads commands interactively when 
+        run, you must cause it, when started running for such interactive 
+        use in the most ordinary way, to print or display an announcement 
+        including an appropriate copyright notice and a notice that there is
+        no warranty (or else, saying that you provide a warranty) and that 
+        users may redistribute the program under these conditions, and 
+        telling the user how to view a copy of this License. (Exception: if 
+        the Program itself is interactive but does not normally print such 
+        an announcement, your work based on the Program is not required to 
+        print an announcement.) 
+
+   These requirements apply to the modified work as a whole. If identifiable 
+   sections of that work are not derived from the Program, and can be 
+   reasonably considered independent and separate works in themselves, then 
+   this License, and its terms, do not apply to those sections when you 
+   distribute them as separate works. But when you distribute the same 
+   sections as part of a whole which is a work based on the Program, the 
+   distribution of the whole must be on the terms of this License, whose 
+   permissions for other licensees extend to the entire whole, and thus to 
+   each and every part regardless of who wrote it. 
+
+   Thus, it is not the intent of this section to claim rights or contest 
+   your rights to work written entirely by you; rather, the intent is to 
+   exercise the right to control the distribution of derivative or 
+   collective works based on the Program. 
+
+   In addition, mere aggregation of another work not based on the Program 
+   with the Program (or with a work based on the Program) on a volume of a 
+   storage or distribution medium does not bring the other work under the 
+   scope of this License. 
+
+3. You may copy and distribute the Program (or a work based on it, under 
+   Section 2) in object code or executable form under the terms of Sections 
+   1 and 2 above provided that you also do one of the following: 
+
+   * a) Accompany it with the complete corresponding machine-readable source 
+        code, which must be distributed under the terms of Sections 1 and 2 
+        above on a medium customarily used for software interchange; or, 
+
+   * b) Accompany it with a written offer, valid for at least three years, 
+        to give any third party, for a charge no more than your cost of 
+        physically performing source distribution, a complete machine-
+        readable copy of the corresponding source code, to be distributed 
+        under the terms of Sections 1 and 2 above on a medium customarily 
+        used for software interchange; or, 
+
+   * c) Accompany it with the information you received as to the offer to 
+        distribute corresponding source code. (This alternative is allowed 
+        only for noncommercial distribution and only if you received the 
+        program in object code or executable form with such an offer, in 
+        accord with Subsection b above.) 
+
+   The source code for a work means the preferred form of the work for 
+   making modifications to it. For an executable work, complete source code 
+   means all the source code for all modules it contains, plus any 
+   associated interface definition files, plus the scripts used to control 
+   compilation and installation of the executable. However, as a special 
+   exception, the source code distributed need not include anything that is 
+   normally distributed (in either source or binary form) with the major 
+   components (compiler, kernel, and so on) of the operating system on which
+   the executable runs, unless that component itself accompanies the 
+   executable. 
+
+   If distribution of executable or object code is made by offering access 
+   to copy from a designated place, then offering equivalent access to copy 
+   the source code from the same place counts as distribution of the source 
+   code, even though third parties are not compelled to copy the source 
+   along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+   expressly provided under this License. Any attempt otherwise to copy, 
+   modify, sublicense or distribute the Program is void, and will 
+   automatically terminate your rights under this License. However, parties 
+   who have received copies, or rights, from you under this License will not
+   have their licenses terminated so long as such parties remain in full 
+   compliance. 
+
+5. You are not required to accept this License, since you have not signed 
+   it. However, nothing else grants you permission to modify or distribute 
+   the Program or its derivative works. These actions are prohibited by law 
+   if you do not accept this License. Therefore, by modifying or 
+   distributing the Program (or any work based on the Program), you 
+   indicate your acceptance of this License to do so, and all its terms and
+   conditions for copying, distributing or modifying the Program or works 
+   based on it. 
+
+6. Each time you redistribute the Program (or any work based on the 
+   Program), the recipient automatically receives a license from the 
+   original licensor to copy, distribute or modify the Program subject to 
+   these terms and conditions. You may not impose any further restrictions 
+   on the recipients' exercise of the rights granted herein. You are not 
+   responsible for enforcing compliance by third parties to this License. 
+
+7. If, as a consequence of a court judgment or allegation of patent 
+   infringement or for any other reason (not limited to patent issues), 
+   conditions are imposed on you (whether by court order, agreement or 
+   otherwise) that contradict the conditions of this License, they do not 
+   excuse you from the conditions of this License. If you cannot distribute 
+   so as to satisfy simultaneously your obligations under this License and 
+   any other pertinent obligations, then as a consequence you may not 
+   distribute the Program at all. For example, if a patent license would 
+   not permit royalty-free redistribution of the Program by all those who 
+   receive copies directly or indirectly through you, then the only way you 
+   could satisfy both it and this License would be to refrain entirely from 
+   distribution of the Program. 
+
+   If any portion of this section is held invalid or unenforceable under any
+   particular circumstance, the balance of the section is intended to apply
+   and the section as a whole is intended to apply in other circumstances. 
+
+   It is not the purpose of this section to induce you to infringe any 
+   patents or other property right claims or to contest validity of any 
+   such claims; this section has the sole purpose of protecting the 
+   integrity of the free software distribution system, which is implemented 
+   by public license practices. Many people have made generous contributions
+   to the wide range of software distributed through that system in 
+   reliance on consistent application of that system; it is up to the 
+   author/donor to decide if he or she is willing to distribute software 
+   through any other system and a licensee cannot impose that choice. 
+
+   This section is intended to make thoroughly clear what is believed to be 
+   a consequence of the rest of this License. 
+
+8. If the distribution and/or use of the Program is restricted in certain 
+   countries either by patents or by copyrighted interfaces, the original 
+   copyright holder who places the Program under this License may add an 
+   explicit geographical distribution limitation excluding those countries, 
+   so that distribution is permitted only in or among countries not thus 
+   excluded. In such case, this License incorporates the limitation as if 
+   written in the body of this License. 
+
+9. The Free Software Foundation may publish revised and/or new versions of 
+   the General Public License from time to time. Such new versions will be 
+   similar in spirit to the present version, but may differ in detail to 
+   address new problems or concerns. 
+
+   Each version is given a distinguishing version number. If the Program 
+   specifies a version number of this License which applies to it and "any 
+   later version", you have the option of following the terms and 
+   conditions either of that version or of any later version published by 
+   the Free Software Foundation. If the Program does not specify a version 
+   number of this License, you may choose any version ever published by the 
+   Free Software Foundation. 
+
+10. If you wish to incorporate parts of the Program into other free programs
+    whose distribution conditions are different, write to the author to ask 
+    for permission. For software which is copyrighted by the Free Software 
+    Foundation, write to the Free Software Foundation; we sometimes make 
+    exceptions for this. Our decision will be guided by the two goals of 
+    preserving the free status of all derivatives of our free software and 
+    of promoting the sharing and reuse of software generally. 
+
+   NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
+    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
+    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
+    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
+    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
+    YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+    NECESSARY SERVICING, REPAIR OR CORRECTION. 
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+    DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+    DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
+    (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
+    INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
+    THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
+    OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest 
+possible use to the public, the best way to achieve this is to make it free 
+software which everyone can redistribute and change under these terms. 
+
+To do so, attach the following notices to the program. It is safest to 
+attach them to the start of each source file to most effectively convey the
+exclusion of warranty; and each file should have at least the "copyright" 
+line and a pointer to where the full notice is found. 
+
+one line to give the program's name and an idea of what it does.
+Copyright (C) yyyy  name of author
+
+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.
+
+Also add information on how to contact you by electronic and paper mail. 
+
+If the program is interactive, make it output a short notice like this when 
+it starts in an interactive mode: 
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 
+with ABSOLUTELY NO WARRANTY; for details type 'show w'.  This is free 
+software, and you are welcome to redistribute it under certain conditions; 
+type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate 
+parts of the General Public License. Of course, the commands you use may be 
+called something other than 'show w' and 'show c'; they could even be 
+mouse-clicks or menu items--whatever suits your program. 
+
+You should also get your employer (if you work as a programmer) or your 
+school, if any, to sign a "copyright disclaimer" for the program, if 
+necessary. Here is a sample; alter the names: 
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
+'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into 
+proprietary programs. If your program is a subroutine library, you may 
+consider it more useful to permit linking proprietary applications with the 
+library. If this is what you want to do, use the GNU Library General Public 
+License instead of this License.
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/crypto_compat.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/crypto_compat.h
@@ -0,0 +1,88 @@
+/*
+ * Header file to maintain compatibility among different kernel versions.
+ *
+ * Copyright (c) 2004-2006  <lawrence_wang@realsil.com.cn>
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/crypto.h>
+
+static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
+                                        struct scatterlist *dst,
+                                        struct scatterlist *src,
+                                        unsigned int nbytes)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
+}         
+
+
+static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
+                                        struct scatterlist *dst,
+                                        struct scatterlist *src,
+                                        unsigned int nbytes)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
+}
+
+#if 0 
+/*
+ *	crypto_free_tfm - Free crypto transform
+ *	@tfm: Transform to free
+ *
+ *	crypto_free_tfm() frees up the transform and any associated resources,
+ *	then drops the refcount on the associated algorithm.
+ */
+void crypto_free_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *alg;
+	int size;
+
+	if (unlikely(!tfm))
+		return;
+
+	alg = tfm->__crt_alg;
+	size = sizeof(*tfm) + alg->cra_ctxsize;
+
+	if (alg->cra_exit)
+		alg->cra_exit(tfm);
+	crypto_exit_ops(tfm);
+	crypto_mod_put(alg);
+	memset(tfm, 0, size);
+	kfree(tfm);
+}
+
+#endif
+#if 1
+ struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
+{
+	struct crypto_tfm *tfm = NULL;
+	int err;
+	printk("call crypto_alloc_tfm!!!\n");
+	do {
+		struct crypto_alg *alg;
+
+		alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
+		err = PTR_ERR(alg);
+		if (IS_ERR(alg))
+			continue;
+
+		tfm = __crypto_alloc_tfm(alg, flags);
+		err = 0;
+		if (IS_ERR(tfm)) {
+			crypto_mod_put(alg);
+			err = PTR_ERR(tfm);
+			tfm = NULL;
+		}
+	} while (err == -EAGAIN && !signal_pending(current));
+
+	return tfm;
+}
+#endif
+
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_module.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_module.c
@@ -0,0 +1,587 @@
+/*******************************************************************************
+
+  Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+  Portions of this file are based on the WEP enablement code provided by the
+  Host AP project hostap-drivers v0.1.3
+  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+  <jkmaline@cc.hut.fi>
+  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  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.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <net/arp.h>
+
+#include "rtllib.h"
+
+
+#ifndef BUILT_IN_RTLLIB
+MODULE_DESCRIPTION("802.11 data/management/control stack");
+MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
+MODULE_LICENSE("GPL");
+#endif
+
+#define DRV_NAME "rtllib"
+
+#ifdef CONFIG_CFG_80211 
+#ifdef CONFIG_RTL_RFKILL
+static inline void rtllib_rfkill_poll(struct wiphy *wiphy)
+{
+	struct rtllib_device *rtllib = NULL;
+
+	rtllib = (struct rtllib_device *)wiphy_priv(wiphy);
+
+	rtllib = (struct rtllib_device *)netdev_priv_rsl(rtllib->dev);
+
+	if (rtllib->rtllib_rfkill_poll)
+		rtllib->rtllib_rfkill_poll(rtllib->dev);
+}
+#else
+static inline void rtllib_rfkill_poll(struct wiphy *wiphy) {}
+#endif
+struct cfg80211_ops rtllib_config_ops = {.rfkill_poll = rtllib_rfkill_poll };
+void *rtllib_wiphy_privid = &rtllib_wiphy_privid;
+#endif
+
+void _setup_timer( struct timer_list* ptimer, void* fun, unsigned long data )
+{
+   ptimer->function = fun;
+   ptimer->data = data;
+   init_timer( ptimer );
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+static inline int rtllib_mesh_networks_allocate(struct rtllib_device *ieee)
+{
+	if (ieee->mesh_networks)
+		return 0;
+
+	ieee->mesh_networks = kmalloc(
+		MAX_NETWORK_COUNT * sizeof(struct rtllib_network),
+		GFP_KERNEL);
+	
+	if (!ieee->mesh_networks) {
+		printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
+		       ieee->dev->name);
+		return -ENOMEM;
+	}
+
+	memset(ieee->mesh_networks, 0,
+	       MAX_NETWORK_COUNT * sizeof(struct rtllib_network));
+
+	return 0;
+}
+
+static inline void rtllib_mesh_networks_free(struct rtllib_device *ieee)
+{
+	if (!ieee->mesh_networks)
+		return;
+	kfree(ieee->mesh_networks);
+	ieee->mesh_networks = NULL;
+}
+#endif
+
+static inline int rtllib_networks_allocate(struct rtllib_device *ieee)
+{
+	if (ieee->networks)
+		return 0;
+
+#ifndef RTK_DMP_PLATFORM
+	ieee->networks = kmalloc(
+		MAX_NETWORK_COUNT * sizeof(struct rtllib_network),
+		GFP_KERNEL);
+#else
+	ieee->networks = dvr_malloc(MAX_NETWORK_COUNT * sizeof(struct rtllib_network));
+#endif
+	if (!ieee->networks) {
+		printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
+		       ieee->dev->name);
+		return -ENOMEM;
+	}
+
+	memset(ieee->networks, 0,
+	       MAX_NETWORK_COUNT * sizeof(struct rtllib_network));
+
+	return 0;
+}
+
+static inline void rtllib_networks_free(struct rtllib_device *ieee)
+{
+	if (!ieee->networks)
+		return;
+#ifndef RTK_DMP_PLATFORM
+	kfree(ieee->networks);
+#else
+	dvr_free(ieee->networks);
+#endif
+	ieee->networks = NULL;
+}
+
+static inline void rtllib_networks_initialize(struct rtllib_device *ieee)
+{
+	int i;
+
+	INIT_LIST_HEAD(&ieee->network_free_list);
+	INIT_LIST_HEAD(&ieee->network_list);
+	for (i = 0; i < MAX_NETWORK_COUNT; i++)
+		list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
+#ifdef _RTL8192_EXT_PATCH_
+	INIT_LIST_HEAD(&ieee->mesh_network_free_list);
+	INIT_LIST_HEAD(&ieee->mesh_network_list);
+	for (i = 0; i < MAX_NETWORK_COUNT; i++)
+		list_add_tail(&ieee->mesh_networks[i].list, &ieee->mesh_network_free_list);
+#endif
+}
+
+#if defined CONFIG_CFG_80211 
+static bool rtllib_wdev_alloc(struct rtllib_device *ieee, int sizeof_priv)
+{
+	int priv_size;
+	struct rtllib_device *rtllib = NULL;
+
+	priv_size = ALIGN(sizeof(struct rtllib_device),NETDEV_ALIGN) + sizeof_priv;
+
+	ieee->wdev.wiphy = wiphy_new(&rtllib_config_ops, priv_size);
+	if (!ieee->wdev.wiphy) {
+		RTLLIB_ERROR("Unable to allocate wiphy.\n");
+		goto out_err_new;
+	}
+
+	rtllib = (struct rtllib_device *)wiphy_priv(ieee->wdev.wiphy);
+	rtllib->dev = ieee->dev;
+	
+	ieee->dev->ieee80211_ptr = &ieee->wdev;
+	ieee->wdev.iftype = NL80211_IFTYPE_STATION;
+
+	/* Fill-out wiphy structure bits we know...  Not enough info
+	 *            here to call set_wiphy_dev or set MAC address or channel info
+	 *                       -- have to do that in ->ndo_init... */
+	ieee->wdev.wiphy->privid = rtllib_wiphy_privid;
+
+	ieee->wdev.wiphy->max_scan_ssids = 1;
+	ieee->wdev.wiphy->max_scan_ie_len = 0;
+	ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)	| BIT(NL80211_IFTYPE_ADHOC);
+
+	return true;
+
+out_err_new:
+	wiphy_free(ieee->wdev.wiphy);
+	return false;
+}
+#endif
+
+struct net_device *alloc_rtllib(int sizeof_priv)
+{
+	struct rtllib_device *ieee = NULL;
+	struct net_device *dev;
+	int i,err;
+
+	RTLLIB_DEBUG_INFO("Initializing...\n");
+
+	dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv);
+	if (!dev) {
+		RTLLIB_ERROR("Unable to network device.\n");
+		goto failed;
+	}
+	ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
+	memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv);
+	ieee->dev = dev;
+
+#ifdef CONFIG_CFG_80211
+	if(!rtllib_wdev_alloc(ieee, sizeof_priv))
+		goto failed;
+#endif
+	err = rtllib_networks_allocate(ieee);
+	if (err) {
+		RTLLIB_ERROR("Unable to allocate beacon storage: %d\n",
+				err);
+		goto failed;
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	err = rtllib_mesh_networks_allocate(ieee);
+	if (err) {
+		RTLLIB_ERROR("Unable to allocate mesh_beacon storage: %d\n",
+				err);
+		goto failed;
+	}
+#endif
+	rtllib_networks_initialize(ieee);
+
+
+	/* Default fragmentation threshold is maximum payload size */
+	ieee->fts = DEFAULT_FTS;
+	ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
+	ieee->open_wep = 1;
+
+	/* Default to enabling full open WEP with host based encrypt/decrypt */
+	ieee->host_encrypt = 1;
+	ieee->host_decrypt = 1;
+	ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
+
+	INIT_LIST_HEAD(&ieee->crypt_deinit_list);
+	_setup_timer(&ieee->crypt_deinit_timer,
+		    rtllib_crypt_deinit_handler,
+		    (unsigned long) ieee);
+	ieee->rtllib_ap_sec_type = rtllib_ap_sec_type;
+
+	spin_lock_init(&ieee->lock);
+	spin_lock_init(&ieee->wpax_suitlist_lock);
+	spin_lock_init(&ieee->bw_spinlock);
+	spin_lock_init(&ieee->reorder_spinlock);
+	atomic_set(&(ieee->atm_chnlop), 0);
+	atomic_set(&(ieee->atm_swbw), 0);
+
+	ieee->bHalfNMode = false;
+ 	ieee->wpa_enabled = 0;
+ 	ieee->tkip_countermeasures = 0;
+ 	ieee->drop_unencrypted = 0;
+ 	ieee->privacy_invoked = 0;
+ 	ieee->ieee802_1x = 1;
+	ieee->raw_tx = 0;
+	ieee->hwsec_active = 0; 
+
+#ifdef _RTL8192_EXT_PATCH_
+	for (i=0; i<MAX_MP; i++)
+	{
+		ieee->cryptlist[i] = (struct rtllib_crypt_data_list*) kmalloc(sizeof(struct rtllib_crypt_data_list), GFP_KERNEL);
+		if (NULL == ieee->cryptlist[i])
+                {
+			printk("error kmalloc cryptlist\n");
+			goto failed;
+		}
+		memset(ieee->cryptlist[i], 0, sizeof(struct rtllib_crypt_data_list));
+	}
+	memset(ieee->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32);
+#endif	
+	memset(ieee->swcamtable,0,sizeof(SW_CAM_TABLE)*32);
+	rtllib_softmac_init(ieee);
+	
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+	ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
+#else
+	ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kmalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
+	memset(ieee->pHTInfo,0,sizeof(RT_HIGH_THROUGHPUT));
+#endif
+	if (ieee->pHTInfo == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for HTInfo\n");
+		return NULL;
+	}	
+	HTUpdateDefaultSetting(ieee);
+	HTInitializeHTInfo(ieee); 
+	TSInitialize(ieee);
+#if 0
+	INIT_WORK_RSL(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq, ieee);
+#endif
+	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
+
+#ifdef _RTL8192_EXT_PATCH_
+	for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&ieee->mesh_mac_hash[i]);
+#endif	
+	
+	for (i = 0; i < 17; i++) {
+	  ieee->last_rxseq_num[i] = -1;
+	  ieee->last_rxfrag_num[i] = -1;
+	  ieee->last_packet_time[i] = 0;
+	}
+
+	rtllib_tkip_null();
+	rtllib_wep_null();
+	rtllib_ccmp_null();
+
+	return dev;
+
+ failed:
+#ifdef _RTL8192_EXT_PATCH_
+	for (i=0; i<MAX_MP; i++)
+	{
+		if (ieee->cryptlist[i]==NULL){
+			continue;
+		}
+		kfree(ieee->cryptlist[i]);
+		ieee->cryptlist[i] = NULL;
+
+	}
+#endif
+
+	if (dev)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
+		free_netdev(dev);
+#else
+		kfree(dev);
+#endif
+	return NULL;
+}
+
+
+void free_rtllib(struct net_device *dev)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
+	int i;
+#ifdef _RTL8192_EXT_PATCH_
+	int j;
+	struct list_head *p, *q;
+	struct rtllib_crypt_data *crypt = NULL;
+#endif	
+#if 1	
+	if (ieee->pHTInfo != NULL)
+	{
+		kfree(ieee->pHTInfo);
+		ieee->pHTInfo = NULL;
+	}
+#endif	
+	rtllib_softmac_free(ieee);
+	del_timer_sync(&ieee->crypt_deinit_timer);
+	rtllib_crypt_deinit_entries(ieee, 1);
+
+#ifdef _RTL8192_EXT_PATCH_
+	for (j=0;j<MAX_MP; j++)
+	{
+		if (ieee->cryptlist[j] == NULL)
+			continue;
+		for (i = 0; i < WEP_KEYS; i++) {
+			crypt = ieee->cryptlist[j]->crypt[i];
+			
+			if (crypt) 
+			{
+				if (crypt->ops) {
+					crypt->ops->deinit(crypt->priv);
+					printk("===>%s():j is %d,i is %d\n",__FUNCTION__,j,i);
+#ifndef BUILT_IN_RTLLIB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+					module_put(crypt->ops->owner);
+#else
+					__MOD_DEC_USE_COUNT(crypt->ops->owner);
+#endif				
+#endif
+				}
+				kfree(crypt);
+				ieee->cryptlist[j]->crypt[i] = NULL;
+			}
+		}
+		kfree(ieee->cryptlist[j]);
+	}
+	for (i = 0; i < WEP_KEYS; i++) {
+		crypt = ieee->sta_crypt[i];
+		if (crypt) 
+		{
+			if (crypt->ops) {
+				crypt->ops->deinit(crypt->priv);
+#ifndef BUILT_IN_RTLLIB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+				module_put(crypt->ops->owner);
+#else
+				__MOD_DEC_USE_COUNT(crypt->ops->owner);
+#endif				
+#endif
+			}
+			kfree(crypt);
+		}
+		ieee->sta_crypt[i] = NULL;
+	}
+#else
+	for (i = 0; i < WEP_KEYS; i++) {
+		struct rtllib_crypt_data *crypt = ieee->crypt[i];
+		if (crypt) {
+			if (crypt->ops) {
+				crypt->ops->deinit(crypt->priv);
+#ifndef BUILT_IN_RTLLIB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+				module_put(crypt->ops->owner);
+#else
+				__MOD_DEC_USE_COUNT(crypt->ops->owner);
+#endif				
+#endif
+			}
+			kfree(crypt);
+			ieee->crypt[i] = NULL;
+		}
+	}
+#endif
+
+	rtllib_networks_free(ieee);
+#ifdef _RTL8192_EXT_PATCH_
+	rtllib_mesh_networks_free(ieee);
+#endif
+#if 0	
+	for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) {
+		list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) {
+			kfree(list_entry(p, struct ieee_ibss_seq, list));
+			list_del(p);
+		}
+	}
+
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++) {
+		list_for_each_safe(p, q, &ieee->mesh_mac_hash[i]) {
+			kfree(list_entry(p, struct ieee_mesh_seq, list));
+			list_del(p);
+		}
+	}
+#endif
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if (ieee->WapiSupport)
+	{
+		WapiFreeAllStaInfo(ieee);
+	}
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))	
+#ifdef CONFIG_CFG_80211
+	wiphy_unregister(ieee->wdev.wiphy);
+	wiphy_free(ieee->wdev.wiphy);
+#endif
+	free_netdev(dev);
+#else
+	kfree(dev);
+#endif
+}
+
+#ifdef CONFIG_RTLLIB_DEBUG
+
+u32 rtllib_debug_level = 0;
+static int debug = \
+			    RTLLIB_DL_ERR	  
+			    ;
+struct proc_dir_entry *rtllib_proc = NULL;
+
+static int show_debug_level(char *page, char **start, off_t offset,
+			    int count, int *eof, void *data)
+{
+	return snprintf(page, count, "0x%08X\n", rtllib_debug_level);
+}
+
+static int store_debug_level(struct file *file, const char *buffer,
+			     unsigned long count, void *data)
+{
+	char buf[] = "0x00000000";
+	unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
+	char *p = (char *)buf;
+	unsigned long val;
+
+	if (copy_from_user(buf, buffer, len))
+		return count;
+	buf[len] = 0;
+	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+		p++;
+		if (p[0] == 'x' || p[0] == 'X')
+			p++;
+		val = simple_strtoul(p, &p, 16);
+	} else
+		val = simple_strtoul(p, &p, 10);
+	if (p == buf)
+		printk(KERN_INFO DRV_NAME
+		       ": %s is not in hex or decimal form.\n", buf);
+	else
+		rtllib_debug_level = val;
+
+	return strnlen(buf, count);
+}
+
+int __init rtllib_init(void)
+{
+#ifdef CONFIG_RTLLIB_DEBUG
+	struct proc_dir_entry *e;
+
+	rtllib_debug_level = debug;
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+	rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
+#else
+	rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net);
+#endif
+	if (rtllib_proc == NULL) {
+		RTLLIB_ERROR("Unable to create " DRV_NAME
+				" proc directory\n");
+		return -EIO;
+	}
+	e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
+			      rtllib_proc);
+	if (!e) {
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		remove_proc_entry(DRV_NAME, proc_net);
+#else
+		remove_proc_entry(DRV_NAME, init_net.proc_net);
+#endif
+		rtllib_proc = NULL;
+		return -EIO;
+	}
+	e->read_proc = show_debug_level;
+	e->write_proc = store_debug_level;
+	e->data = NULL;
+#endif
+
+	return 0;
+}
+
+void __exit rtllib_exit(void)
+{
+#ifdef CONFIG_RTLLIB_DEBUG
+	if (rtllib_proc) {
+		remove_proc_entry("debug_level", rtllib_proc);
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		remove_proc_entry(DRV_NAME, proc_net);
+#else
+		remove_proc_entry(DRV_NAME, init_net.proc_net);
+#endif
+		rtllib_proc = NULL;
+	}
+#endif
+}
+
+#ifndef BUILT_IN_RTLLIB
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#include <linux/moduleparam.h>
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "debug output mask");
+
+
+module_exit(rtllib_exit);
+module_init(rtllib_init);
+#endif
+
+EXPORT_SYMBOL_RSL(alloc_rtllib);
+EXPORT_SYMBOL_RSL(free_rtllib);
+EXPORT_SYMBOL_RSL(rtllib_debug_level);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/api.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/api.c
@@ -0,0 +1,261 @@
+/*
+ * Scatterlist Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ *
+ * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
+ * and Nettle, by Niels M鰈ler.
+ *
+ * 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.
+ *
+ */
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include "rtl_crypto.h"
+#include <linux/errno.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include "internal.h"
+
+LIST_HEAD(crypto_alg_list);
+DECLARE_RWSEM(crypto_alg_sem);
+
+static inline int crypto_alg_get(struct crypto_alg *alg)
+{
+#ifdef BUILT_IN_CRYPTO
+	return 1;
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	return try_module_get(alg->cra_module);
+#else
+	return try_inc_mod_count(alg->cra_module);
+#endif			
+#endif
+}
+
+static inline void crypto_alg_put(struct crypto_alg *alg)
+{
+#ifndef BUILT_IN_CRYPTO
+	if (alg->cra_module)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		
+		module_put(alg->cra_module);
+#else
+		__MOD_DEC_USE_COUNT(alg->cra_module);
+#endif		
+#endif
+}
+
+struct crypto_alg *crypto_alg_lookup(const char *name)
+{
+	struct crypto_alg *q, *alg = NULL;
+
+	if (!name)
+		return NULL;
+	
+	down_read(&crypto_alg_sem);
+	
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		if (!(strcmp(q->cra_name, name))) {
+			if (crypto_alg_get(q))
+				alg = q;
+			break;
+		}
+	}
+	
+	up_read(&crypto_alg_sem);
+	return alg;
+}
+
+static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
+{
+	tfm->crt_flags = 0;
+	
+	switch (crypto_tfm_alg_type(tfm)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		return crypto_init_cipher_flags(tfm, flags);
+		
+	case CRYPTO_ALG_TYPE_DIGEST:
+		return crypto_init_digest_flags(tfm, flags);
+		
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		return crypto_init_compress_flags(tfm, flags);
+	
+	default:
+		break;
+	}
+	
+	BUG();
+	return -EINVAL;
+}
+
+static int crypto_init_ops(struct crypto_tfm *tfm)
+{
+	switch (crypto_tfm_alg_type(tfm)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		return crypto_init_cipher_ops(tfm);
+		
+	case CRYPTO_ALG_TYPE_DIGEST:
+		return crypto_init_digest_ops(tfm);
+		
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		return crypto_init_compress_ops(tfm);
+	
+	default:
+		break;
+	}
+	
+	BUG();
+	return -EINVAL;
+}
+
+static void crypto_exit_ops(struct crypto_tfm *tfm)
+{
+	switch (crypto_tfm_alg_type(tfm)) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		crypto_exit_cipher_ops(tfm);
+		break;
+		
+	case CRYPTO_ALG_TYPE_DIGEST:
+		crypto_exit_digest_ops(tfm);
+		break;
+		
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		crypto_exit_compress_ops(tfm);
+		break;
+	
+	default:
+		BUG();
+		
+	}
+}
+
+struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
+{
+	struct crypto_tfm *tfm = NULL;
+	struct crypto_alg *alg;
+
+	alg = crypto_alg_mod_lookup(name);
+	if (alg == NULL)
+		goto out;
+	
+	tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL);
+	if (tfm == NULL)
+		goto out_put;
+
+	memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize);
+	
+	tfm->__crt_alg = alg;
+	
+	if (crypto_init_flags(tfm, flags))
+		goto out_free_tfm;
+		
+	if (crypto_init_ops(tfm)) {
+		crypto_exit_ops(tfm);
+		goto out_free_tfm;
+	}
+
+	goto out;
+
+out_free_tfm:
+	kfree(tfm);
+	tfm = NULL;
+out_put:
+	crypto_alg_put(alg);
+out:
+	return tfm;
+}
+
+void crypto_free_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *alg = tfm->__crt_alg;
+	int size = sizeof(*tfm) + alg->cra_ctxsize;
+
+	crypto_exit_ops(tfm);
+	crypto_alg_put(alg);
+	memset(tfm, 0, size);
+	kfree(tfm);
+}
+
+int crypto_register_alg(struct crypto_alg *alg)
+{
+	int ret = 0;
+	struct crypto_alg *q;
+	
+	down_write(&crypto_alg_sem);
+	
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		if (!(strcmp(q->cra_name, alg->cra_name))) {
+			ret = -EEXIST;
+			goto out;
+		}
+	}
+	
+	list_add_tail(&alg->cra_list, &crypto_alg_list);
+out:	
+	up_write(&crypto_alg_sem);
+	return ret;
+}
+
+int crypto_unregister_alg(struct crypto_alg *alg)
+{
+	int ret = -ENOENT;
+	struct crypto_alg *q;
+	
+	BUG_ON(!alg->cra_module);
+	
+	down_write(&crypto_alg_sem);
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		if (alg == q) {
+			list_del(&alg->cra_list);
+			ret = 0;
+			goto out;
+		}
+	}
+out:	
+	up_write(&crypto_alg_sem);
+	return ret;
+}
+
+int crypto_alg_available(const char *name, u32 flags)
+{
+	int ret = 0;
+	struct crypto_alg *alg = crypto_alg_mod_lookup(name);
+	
+	if (alg) {
+		crypto_alg_put(alg);
+		ret = 1;
+	}
+	
+	return ret;
+}
+
+#ifndef BUILT_IN_CRYPTO
+static int __init init_crypto(void)
+{
+	printk(KERN_INFO "Initializing Cryptographic API\n");
+	crypto_init_proc();
+	return 0;
+}
+
+__initcall(init_crypto);
+
+
+/*
+EXPORT_SYMBOL_GPL(crypto_register_alg);
+EXPORT_SYMBOL_GPL(crypto_unregister_alg);
+EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
+EXPORT_SYMBOL_GPL(crypto_free_tfm);
+EXPORT_SYMBOL_GPL(crypto_alg_available);
+*/
+EXPORT_SYMBOL_RSL(crypto_register_alg);
+EXPORT_SYMBOL_RSL(crypto_unregister_alg);
+EXPORT_SYMBOL_RSL(crypto_alloc_tfm);
+EXPORT_SYMBOL_RSL(crypto_free_tfm);
+EXPORT_SYMBOL_RSL(crypto_alg_available);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/wapi.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/wapi.c
@@ -0,0 +1,1842 @@
+#if defined (RTL8192S_WAPI_SUPPORT)
+
+#include <linux/unistd.h>
+#include <linux/etherdevice.h>
+#include "wapi.h"
+#include "wapi_interface.h"
+#include "rtllib.h"
+
+#define LITTLE_ENDIAN   
+#define ENCRYPT  0     
+#define DECRYPT  1     
+
+u32 wapi_debug_component = 	WAPI_INIT    	|
+				WAPI_ERR ; 
+
+void WapiInit(struct rtllib_device *ieee)
+{
+	PRT_WAPI_T		pWapiInfo;
+	int				i;
+
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	RT_ASSERT_RET(ieee);
+
+	pWapiInfo =  &ieee->wapiInfo;
+	pWapiInfo->bWapiEnable = false;
+
+	INIT_LIST_HEAD(&ieee->cache_frag_list);
+
+	INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList);
+	INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList);
+	for(i=0;i<WAPI_MAX_BKID_NUM;i++)
+	{
+		list_add_tail(&pWapiInfo->wapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList);
+	}
+
+	INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList);
+	INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList);
+	for(i=0;i<WAPI_MAX_STAINFO_NUM;i++)
+	{
+		list_add_tail(&pWapiInfo->wapiSta[i].list, &pWapiInfo->wapiSTAIdleList);
+	}
+
+	spin_lock_init(&ieee->wapi_queue_lock);
+
+	ieee->wapi_queue = (WAPI_QUEUE *)kmalloc((sizeof(WAPI_QUEUE)), GFP_KERNEL);
+	if (!ieee->wapi_queue) {
+		return;
+	}
+	memset((void *)ieee->wapi_queue, 0, sizeof (WAPI_QUEUE));
+	WAPI_InitQueue(ieee->wapi_queue, WAPI_MAX_QUEUE_LEN, WAPI_MAX_BUFF_LEN);	
+	
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void WapiExit(struct rtllib_device *ieee)
+{
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	RT_ASSERT_RET(ieee);
+	
+	if(ieee->wapi_queue)
+		kfree(ieee->wapi_queue);
+	ieee->wapi_queue = 0;
+	
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void WapiCreateAppEventAndSend(
+	struct rtllib_device *ieee,
+	u8 		*pbuffer,
+	u16		buf_len,
+	u8 		*DestAddr,
+	u8		bUpdateBK,
+	u8		bUpdateUSK,
+	u8		bUpdateMSK,
+	u8		RcvPktType,
+	u8		bDisconnect
+)
+{
+	PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo);
+	PRT_WAPI_STA_INFO pWapiSta = NULL;
+	u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;	
+	u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;	
+	u8 bFind = false, bRecvAEPacket = false, bRecvASUEPacket = false, EventId = 0;
+
+	WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__);
+	WAPI_TRACE(WAPI_API, "DestAddr="MAC_FMT" bUpdateBK=%d bUpdateUSK=%d bUpdateMSK=%d RcvPktType=%d bDisconnect=%d\n", 
+			MAC_ARG(DestAddr), bUpdateBK, bUpdateUSK, bUpdateMSK, RcvPktType,bDisconnect);
+
+	/*if(!pWapiInfo->bWapiEnable){
+		WAPI_TRACE(WAPI_ERR,"%s: ieee->WapiSupport = 0!!\n",__FUNCTION__);
+		return;
+	}*/
+	
+	if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+		bFind = false;
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(DestAddr,pWapiSta->PeerMacAddr,ETH_ALEN)){
+				bFind = true;
+				break;
+			}
+		}
+	}
+
+	WAPI_TRACE(WAPI_API, "%s: DestAddr="MAC_FMT" bFind=%d\n", __FUNCTION__, MAC_ARG(DestAddr), bFind);
+	switch(RcvPktType){
+		case WAPI_PREAUTHENTICATE:
+			 EventId = WAPI_EVENT_RCV_PREAUTHENTICATE;
+			 bRecvAEPacket = true;
+			 bRecvASUEPacket = false;
+			 break;
+		case WAPI_ACCESS_AUTHENTICATE_REQUEST:
+			 EventId = WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_REQUEST;
+			 bRecvAEPacket = true;
+			 bRecvASUEPacket = false;
+			 break;
+		case WAPI_USK_RESPONSE:
+			 EventId = WAPI_EVENT_RCV_USK_RESPONSE;
+			 bRecvAEPacket = true;
+			 bRecvASUEPacket = false;
+			 break;
+		case WAPI_MSK_RESPONSE:
+			 EventId = WAPI_EVENT_RCV_MSK_RESPONSE;
+			 bRecvAEPacket = true;
+			 bRecvASUEPacket = false;
+			 break;
+		case WAPI_STAKEY_REQUEST:
+			 EventId = WAPI_EVENT_RCV_STAKEY_REQUEST;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		case WAPI_AUTHENTICATE_ACTIVE:
+			 EventId = WAPI_EVENT_RCV_AUTHENTICATE_ACTIVE;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		case WAPI_ACCESS_AUTHENTICATE_RESPONSE:
+			 EventId = WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_RESPONSE;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		case WAPI_USK_REQUEST:
+			 EventId = WAPI_EVENT_RCV_USK_REQUEST;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		case WAPI_USK_CONFIRM:
+			 EventId = WAPI_EVENT_RCV_USK_CONFIRM;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		case WAPI_MSK_NOTIFICATION:
+			 EventId = WAPI_EVENT_RCV_MSK_NOTIFICATION;
+			 bRecvAEPacket = false;
+			 bRecvASUEPacket = true;
+			 break;
+		default:
+			 break;
+	}
+
+	if(ieee->iw_mode == IW_MODE_INFRA){
+		if(bRecvAEPacket || bUpdateMSK){
+			goto out;
+		}
+		if(bRecvASUEPacket){
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len);
+			goto out;
+		}
+		if(bUpdateBK && bFind){
+			EventId = WAPI_EVENT_ASUE_UPDATE_BK;
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+			goto out;
+		}
+		if(bUpdateUSK&& bFind){
+			EventId = WAPI_EVENT_ASUE_UPDATE_USK;
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+			goto out;
+		}
+		if(bDisconnect && bFind){
+			EventId = WAPI_EVENT_DISCONNECT;
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+			goto out;
+		}
+	}
+	else if(ieee->iw_mode == IW_MODE_ADHOC)
+	{
+		if((bFind )&& (!pWapiSta->bSetkeyOk) && (bUpdateBK ||bUpdateUSK||bUpdateMSK))
+			goto out;
+		if(bRecvASUEPacket){
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len);
+			if(EventId != WAPI_EVENT_RCV_USK_REQUEST)
+				goto out;
+		}
+		if((!bFind) && (!bDisconnect) && (!bUpdateMSK))
+		{
+			if(!list_empty(&pWapiInfo->wapiSTAIdleList))
+			{
+				pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+				list_del_init(&pWapiSta->list);
+				list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList);
+				WAPI_TRACE(WAPI_API, "%s: Add wapi station "MAC_FMT"\n", __FUNCTION__, MAC_ARG(DestAddr));
+				memcpy(pWapiSta->PeerMacAddr,DestAddr,6);
+				memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+				memcpy(pWapiSta->lastRxUnicastPN, WapiASUEPNInitialValueSrc, 16);
+			}
+			
+			pWapiInfo->bFirstAuthentiateInProgress= true;
+
+			EventId = WAPI_EVENT_FIRST_AUTHENTICATOR;
+			WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+			goto out;
+		}else{
+			if(bRecvAEPacket){
+				WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len);
+				goto out;
+			}
+			if(bDisconnect){
+				EventId = WAPI_EVENT_DISCONNECT;
+				WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+				goto out;
+			}
+			if(bUpdateBK){
+				EventId = WAPI_EVENT_AE_UPDATE_BK;
+				WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+				goto out;
+			}
+			if(bUpdateUSK){
+				EventId = WAPI_EVENT_AE_UPDATE_USK;
+				WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0);
+				goto out;
+			}
+			if(bUpdateMSK){
+				list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+					if(pWapiSta->bSetkeyOk){
+						EventId = WAPI_EVENT_AE_UPDATE_MSK;
+						WAPI_CreateEvent_Send(ieee, EventId, pWapiSta->PeerMacAddr, NULL, 0);
+					}
+				}
+				goto out;
+			}
+		}
+	}
+	
+out:	
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+	return;
+}
+
+
+void WapiReturnAllStaInfo(struct rtllib_device *ieee)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo;
+	PRT_WAPI_BKID			pWapiBkid;
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	
+	pWapiInfo = &ieee->wapiInfo;
+
+	while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+	{
+		pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+		list_del_init(&pWapiStaInfo->list);
+		memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+		pWapiStaInfo->bSetkeyOk = 0;
+		list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+	}
+
+	while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+	{
+		pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+		list_del_init(&pWapiBkid->list);
+		memset(pWapiBkid->bkid,0,16);
+		list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+	}
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void WapiReturnOneStaInfo(struct rtllib_device *ieee, u8 *MacAddr, u8 from_app)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo = NULL;
+	PRT_WAPI_BKID			pWapiBkid = NULL;
+
+	pWapiInfo = &ieee->wapiInfo;
+
+	WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__);
+
+	if(!from_app)
+		WapiCreateAppEventAndSend(ieee,NULL,0,MacAddr, false,false,false,0,true);
+	if(list_empty(&(pWapiInfo->wapiSTAUsedList))){
+		return;
+	}else{
+		list_for_each_entry(pWapiStaInfo, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(pWapiStaInfo->PeerMacAddr,MacAddr,ETH_ALEN)){
+				pWapiStaInfo->bAuthenticateInProgress = false;
+				pWapiStaInfo->bSetkeyOk = false;
+				memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+				list_del_init(&pWapiStaInfo->list);
+				list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+				break;
+			}
+
+		}
+	}
+
+	if(ieee->iw_mode == IW_MODE_INFRA){
+		while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+		{
+			pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+			list_del_init(&pWapiBkid->list);
+			memset(pWapiBkid->bkid,0,16);
+			list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+		}
+	}
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+	return;
+}
+
+void WapiFreeAllStaInfo(struct rtllib_device *ieee)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo;
+	PRT_WAPI_BKID			pWapiBkid;
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	pWapiInfo = &ieee->wapiInfo;
+
+	WapiReturnAllStaInfo(ieee);
+	while(!list_empty(&(pWapiInfo->wapiSTAIdleList)))
+	{
+		pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+		list_del_init(&pWapiStaInfo->list);
+	}
+
+	while(!list_empty(&(pWapiInfo->wapiBKIDIdleList)))
+	{
+		pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+		list_del_init(&pWapiBkid->list);
+	}
+	WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__);
+	return;
+}
+
+u8 SecIsWAIPacket(struct rtllib_device* ieee,struct sk_buff *skb)
+{
+	PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo);
+	PRT_WAPI_STA_INFO pWapiSta = NULL;
+	u8 WaiPkt = 0, *pTaddr, bFind = false;
+	u8 Offset_TypeWAI = 24 + 6;	
+	struct rtllib_hdr_3addrqos *header;
+	u16 mask = 1, fc = 0;
+
+	if((!pWapiInfo->bWapiEnable) || (!ieee->wapiInfo.bWapiEnable))
+		return 0;
+
+	header = (struct rtllib_hdr_3addrqos *)skb->data;
+
+	fc = le16_to_cpu(header->frame_ctl);
+	if(fc & RTLLIB_FCTL_WEP)
+	    return 0;
+
+	pTaddr = header->addr2;
+	if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+		bFind = false;
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+			if(!memcmp(pTaddr,pWapiSta->PeerMacAddr,6)){
+				bFind = true;
+				break;
+			}
+		}
+	}
+
+	WAPI_TRACE(WAPI_API, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr));
+
+	if( IsQoSDataFrame(skb->data) ){
+		Offset_TypeWAI += sQoSCtlLng;	
+	}
+
+	if((header->frame_ctl & (mask<<14)) != 0){
+		Offset_TypeWAI += WAPI_EXT_LEN;	
+	}
+
+	if( skb->len < (Offset_TypeWAI+1) ){
+		WAPI_TRACE(WAPI_ERR, "%s(): invalid length(%d)\n",__FUNCTION__,skb->len);
+		return 0;
+	}
+
+	if( (skb->data[Offset_TypeWAI]==0x88) && (skb->data[Offset_TypeWAI+1]==0xb4) ){
+		WaiPkt = skb->data[Offset_TypeWAI+5];
+		if(ieee->iw_mode == IW_MODE_ADHOC){
+			if(bFind){
+				if((WaiPkt == 8) && (pWapiInfo->wapiTxMsk.bSet) && (pWapiSta->wapiMsk.bSet) && ((skb->data[Offset_TypeWAI+14] & 0x10)==0)){
+					printk("==============> %s(): Receive USK Request After MSK set!\n", __FUNCTION__);
+					DelStaInfo(ieee, pTaddr);
+					WapiReturnOneStaInfo (ieee, pTaddr, 0);
+					WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+				}
+
+			}
+		}
+	}else{
+		WAPI_TRACE(WAPI_API, "%s(): non wai packet\n",__FUNCTION__);
+	}
+
+	WAPI_TRACE(WAPI_API, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt);
+
+	return	WaiPkt;
+}
+
+/******************
+*********************/
+u8 Wapi_defragment(struct rtllib_device* ieee,u8* data, u16 len,
+	          u8* pTaddr,bool bAuthenticator,u8* rxbuffer,u16* rxbuffer_len)
+{
+	PRT_CACHE_INFO pcache_info = NULL;
+	bool bfind = false;
+	
+	if(!list_empty(&ieee->cache_frag_list)){
+		list_for_each_entry(pcache_info, &ieee->cache_frag_list, list) {
+			if((memcmp(pcache_info->saddr,pTaddr,ETH_ALEN)==0) 
+				&& (pcache_info->bAuthenticator == bAuthenticator))
+			{
+				bfind = true;
+				break;
+			}
+		}		
+	}
+	WAPI_TRACE(WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bfind, MAC_ARG(pTaddr));
+	if(bfind == false) {
+		pcache_info = kmalloc(sizeof(RT_CACHE_INFO),GFP_ATOMIC);
+		if(pcache_info == NULL){
+			WAPI_TRACE(WAPI_ERR,"%s(): can't malloc mem\n", __FUNCTION__);
+			goto drop2;
+		}
+		memset(pcache_info,0,sizeof(RT_CACHE_INFO));
+		if(data[11] == 0x1){
+			WAPI_TRACE(WAPI_RX, "%s(): First fragment, and have More fragments\n",__FUNCTION__);
+			memcpy(&(pcache_info->recvSeq),data+8, 2);
+			if(data[10] != 0x00)
+			{
+				WAPI_TRACE(WAPI_ERR, "%s(): First fragment,but fragnum is not 0.\n",__FUNCTION__);
+				goto drop1;
+			}else{	
+				data[10] = 0x0;
+				data[11] = 0x0;
+				if (len > 2000) {
+					WAPI_TRACE(WAPI_ERR,"111****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,len);
+					goto drop1;
+				}
+				pcache_info->lastFragNum= 0x00;
+				memcpy(pcache_info->cache_buffer,data,len);
+				pcache_info->cache_buffer_len = len;
+				pcache_info->bAuthenticator = bAuthenticator;
+				memcpy(pcache_info->saddr,pTaddr,ETH_ALEN);
+				list_add_tail(&pcache_info->list, &ieee->cache_frag_list);
+				WAPI_TRACE(WAPI_RX, "%s(): First fragment, allocate cache to store.\n",__FUNCTION__);
+				goto drop2;
+			}
+		}else{
+			if(data[10] == 0){
+				WAPI_TRACE(WAPI_RX, "%s(): First fragment, no More fragment, ready to send to App.\n",__FUNCTION__);
+				if (len > 2000) {
+					WAPI_TRACE(WAPI_ERR,"222****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,len);
+					goto drop1;
+				}
+				memcpy(rxbuffer,data,len);
+				*rxbuffer_len = len;
+				goto success;
+			}else{
+				WAPI_TRACE(WAPI_ERR, "%s(): First fragment,no More fragment, but fragnum is not 0.\n",__FUNCTION__);
+				goto drop1;
+			}
+		}
+	}
+	else{
+		if(data[11] == 0x1){
+			if(memcmp(data+8,&(pcache_info->recvSeq),2)) {
+				WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, More fragment, seq num error.\n",__FUNCTION__);
+				list_del(&pcache_info->list);
+				goto drop1;
+			}else{
+				if(data[10] == (pcache_info->lastFragNum+1)){
+					WAPI_TRACE(WAPI_RX, "%s(): Not First fragment, More fragment, same seq num, copy to cache.\n",__FUNCTION__);
+					if ((pcache_info->cache_buffer_len + len - 12) > 2000) {
+						WAPI_TRACE(WAPI_ERR,"333****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,pcache_info->cache_buffer_len + len - 12);
+						list_del(&pcache_info->list);
+						goto drop1;
+					}
+					memcpy(pcache_info->cache_buffer+(pcache_info->cache_buffer_len),data+12,len-12);
+					pcache_info->cache_buffer_len += len-12;
+					pcache_info->lastFragNum  = data[10];
+					goto drop2;
+				}else{
+					WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, More fragment, same seq num, fragnum error.\n",__FUNCTION__);
+					list_del(&pcache_info->list);
+					goto drop1;
+				}
+			}
+		}else{
+			if(memcmp(data+8,&(pcache_info->recvSeq),2)) {
+				WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, no More fragment, seq num error.\n",__FUNCTION__);
+				list_del(&pcache_info->list);
+				goto drop1;
+			}else{
+				if(data[10] == (pcache_info->lastFragNum+1)){					
+					WAPI_TRACE(WAPI_RX, "%s(): Not First fragment, no More fragment, same seq num, ready to send to App.\n",__FUNCTION__);
+					if ((pcache_info->cache_buffer_len + len - 12) > 2000) {
+						WAPI_TRACE(WAPI_ERR,"444****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,pcache_info->cache_buffer_len + len - 12);
+						list_del(&pcache_info->list);
+						goto drop1;
+					}
+					memcpy(pcache_info->cache_buffer+(pcache_info->cache_buffer_len),data+12,len-12);
+					pcache_info->cache_buffer_len += len-12;
+					memcpy(rxbuffer,pcache_info->cache_buffer,pcache_info->cache_buffer_len);
+					*rxbuffer_len = pcache_info->cache_buffer_len;
+					list_del(&pcache_info->list);
+					goto success;
+				}else{
+					WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, no More fragment, same seq num, fragnum error.\n",__FUNCTION__);
+					list_del(&pcache_info->list);
+					goto drop1;
+				}
+			}
+		}
+	}
+
+drop1:
+	if(pcache_info)
+		kfree(pcache_info);
+	pcache_info = NULL;
+	return false;
+drop2:
+	return false;
+success:
+	if(pcache_info)
+		kfree(pcache_info);
+	pcache_info = NULL;
+	return true;
+}
+
+/****************************************************************************
+ * data[8-9]: Sequence Number
+ * data[10]: Fragment No
+ * data[11]: Flag = 1 indicates more data.
+ *****************************************************************************/
+void WapiHandleRecvPacket(struct rtllib_device* ieee,struct sk_buff *skb,u8 WaiPkt)
+{
+	PRT_WAPI_T			pWapiInfo;
+	struct rtllib_hdr_3addrqos *hdr;
+	u8 *pTaddr, *recvPtr, *rxbuffer;
+ 	u8 bAuthenticator = false, receive_result = false;
+	int hdrlen = 0;
+	u16 recvLength = 0, fc = 0, rxbuffer_len = 0;
+
+	WAPI_TRACE(WAPI_RX, "===========> %s: WaiPkt is %d\n", __FUNCTION__,WaiPkt);
+	
+	hdr = (struct rtllib_hdr_3addrqos *)skb->data;
+	pTaddr = hdr->addr2;
+	fc = hdr->frame_ctl;
+	hdrlen = rtllib_get_hdrlen(fc);
+	
+	pWapiInfo = &(ieee->wapiInfo);
+	if((WaiPkt == WAPI_CERTIFICATE_AUTHENTICATE_REQUEST) 
+		||(WaiPkt == WAPI_CERTIFICATE_AUTHENTICATE_RESPONSE)) 
+	{
+		WAPI_TRACE(WAPI_RX, "%s: Valid Wai Packet \n", __FUNCTION__);
+		return;
+	}else{
+		switch(WaiPkt)
+		{
+			case WAPI_PREAUTHENTICATE:
+			case WAPI_ACCESS_AUTHENTICATE_REQUEST:
+			case WAPI_USK_RESPONSE:
+			case WAPI_MSK_RESPONSE:
+				 bAuthenticator = true;
+				 break;
+			default:
+				  break;
+		}
+		recvLength = skb->len - hdrlen - (SNAP_SIZE + sizeof(u16));
+		recvPtr = skb->data + hdrlen + (SNAP_SIZE + sizeof(u16));
+
+		rxbuffer = kmalloc(2000, GFP_ATOMIC);
+		if(NULL == rxbuffer)
+			return;
+		
+		receive_result = Wapi_defragment(ieee,recvPtr, recvLength,pTaddr,bAuthenticator,rxbuffer,&rxbuffer_len);
+		if(receive_result)
+			WapiCreateAppEventAndSend(ieee, rxbuffer, rxbuffer_len, pTaddr, false,false, false, WaiPkt, false);
+		
+		kfree(rxbuffer);
+	}
+	WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+void WapiSetIE(struct rtllib_device *ieee)
+{
+	PRT_WAPI_T		pWapiInfo = &(ieee->wapiInfo);
+	u16		protocolVer = 1;
+	u16		akmCnt = 1;
+	u16		suiteCnt = 1;
+	u16		capability = 0;
+	u8		OUI[3];
+
+	OUI[0] = 0x00;
+	OUI[1] = 0x14;
+	OUI[2] = 0x72;
+	
+	pWapiInfo->wapiIELength = 0;
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2);
+	pWapiInfo->wapiIELength +=2;
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2);
+	pWapiInfo->wapiIELength +=2;
+
+	if(pWapiInfo->bWapiPSK){
+		memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+		pWapiInfo->wapiIELength +=3;
+		pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2;
+		pWapiInfo->wapiIELength +=1;
+	}else{
+		memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+		pWapiInfo->wapiIELength +=3;
+		pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+		pWapiInfo->wapiIELength +=1;
+	}
+
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2);
+	pWapiInfo->wapiIELength +=2;
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+	pWapiInfo->wapiIELength +=3;
+	pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+	pWapiInfo->wapiIELength +=1;
+
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+	pWapiInfo->wapiIELength +=3;
+	pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+	pWapiInfo->wapiIELength +=1;
+
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2);
+	pWapiInfo->wapiIELength +=2;
+}
+
+
+/*  PN1 > PN2, return 1,
+ *  else return 0.
+ */
+u32 WapiComparePN(u8 *PN1, u8 *PN2)
+{
+	char i;
+
+	if ((NULL == PN1) || (NULL == PN2))
+		return 1;
+
+	if ((PN2[15] - PN1[15]) & 0x80)
+		return 1;
+
+	for (i=16; i>0; i--)
+	{
+		if(PN1[i-1] == PN2[i-1])
+		    	continue;
+		else if(PN1[i-1] > PN2[i-1])
+			return 1;
+		else
+			return 0;			
+	}
+
+	return 0;
+}
+
+/* AddCount: 1 or 2. 
+ *  If overflow, return 1,
+ *  else return 0.
+ */
+u8 WapiIncreasePN(u8 *PN, u8 AddCount)
+{
+	u8  i;
+
+	if (NULL == PN)
+		return 1;
+	/*
+	if(AddCount == 2){
+		printk("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]);
+		if(PN[0] == 0x48){
+			PN[0] += AddCount;
+			return 1;
+		}else{
+			PN[0] += AddCount;
+			return 0;
+		}
+	}
+	*/
+
+	for (i=0; i<16; i++)
+	{
+		if (PN[i] + AddCount <= 0xff)
+		{
+			PN[i] += AddCount;
+			return 0;
+		}
+		else
+		{
+			PN[i] += AddCount;
+			AddCount = 1;
+		}
+	}
+
+	return 1;
+}
+
+
+void WapiGetLastRxUnicastPNForQoSData(
+	u8 			UserPriority,
+	PRT_WAPI_STA_INFO    pWapiStaInfo,
+	u8 *PNOut
+)
+{
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+	switch(UserPriority)
+	{
+		case 0:
+		case 3:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16);
+			      break;
+		case 1:
+		case 2:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16);
+			      break;
+		case 4:
+		case 5:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16);
+			      break;
+		case 6:
+		case 7:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16);
+			      break;
+		default:
+				WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+				break;
+	}
+	WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+void WapiSetLastRxUnicastPNForQoSData(
+	u8 		UserPriority,
+	u8           *PNIn,
+	PRT_WAPI_STA_INFO    pWapiStaInfo
+)
+{
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+	switch(UserPriority)
+	{
+		case 0:
+		case 3:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16);
+			      break;
+		case 1:
+		case 2:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16);
+			      break;
+		case 4:
+		case 5:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16);
+			      break;
+		case 6:
+		case 7:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16);
+			      break;
+		default:
+				WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+				break;
+	}
+	WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+/****************************************************************************
+TRUE-----------------bRxReorder == FALSE not RX-Reorder
+FALSE----------------bRxReorder == TRUE do RX Reorder
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 WapiCheckPnInSwDecrypt(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb
+)
+{
+	struct rtllib_hdr_3addrqos *header;
+	u16 				fc;
+	u8				*pDaddr, *pTaddr, *pRaddr;
+	u8 				ret = false;
+
+	header = (struct rtllib_hdr_3addrqos *)pskb->data;
+	pTaddr = header->addr2;
+	pRaddr = header->addr1;
+	fc = le16_to_cpu(header->frame_ctl);
+	
+	if((fc & RTLLIB_FCTL_TODS) == RTLLIB_FCTL_TODS)
+		pDaddr = header->addr3;
+	else
+		pDaddr = header->addr1;
+	
+	if(eqMacAddr(pRaddr, ieee->dev->dev_addr) &&
+		!is_multicast_ether_addr(pDaddr) &&
+		ieee->current_network.qos_data.active &&
+		IsQoSDataFrame(pskb->data) && ieee->pHTInfo->bCurrentHTSupport &&
+		ieee->pHTInfo->bCurRxReorderEnable)
+		ret = false;
+	else
+		ret = true;
+
+	WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret);
+	return ret;
+}
+
+
+/****************************************************************************
+TRUE-----------------Drop
+FALSE---------------- handle 
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 WapiCheckDropForRxReorderCase(
+	struct rtllib_device *ieee,
+	struct rtllib_rxb* prxb
+)
+{
+	PRT_WAPI_T     pWapiInfo = &(ieee->wapiInfo);
+	u8			*pLastRecvPN = NULL;
+	u8			bFind = false;
+	PRT_WAPI_STA_INFO	pWapiSta = NULL;
+
+	if(!pWapiInfo->bWapiEnable)
+		return false;
+
+	if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+		bFind = false;
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(prxb->WapiSrcAddr,pWapiSta->PeerMacAddr,ETH_ALEN)){
+				bFind = true;
+				break;
+			}
+		}
+	}
+	WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(prxb->WapiSrcAddr));
+
+	if(bFind){
+		switch(prxb->UserPriority)
+		{
+			case 0:
+			case 3:
+				pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue;
+				break;
+			case 1:
+			case 2:
+				pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue;
+				break;
+			case 4:
+			case 5:
+				pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue;
+				break;
+			case 6:
+			case 7:
+				pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue;
+				break;
+			default:
+				WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__);
+				break;
+		}
+
+		if(!WapiComparePN(prxb->WapiTempPN,pLastRecvPN))
+		{
+			WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__);
+			return true;
+		}
+		else
+		{
+			memcpy(pLastRecvPN,prxb->WapiTempPN,16);
+			return false;
+		}
+	}
+	else
+		return false;
+}
+
+int WapiSendWaiPacket(struct rtllib_device *ieee, struct sk_buff *pskb)
+{
+	struct sk_buff * newskb = NULL;
+	struct rtllib_hdr_3addr *mac_hdr=NULL;
+	cb_desc *tcb_desc = NULL;
+
+	RT_ASSERT_RET_VALUE(ieee,-1);
+	RT_ASSERT_RET_VALUE(pskb,-1);
+
+	if(pskb->len < (14 + sizeof(struct rtllib_hdr_3addr)))
+	{
+		WAPI_TRACE(WAPI_ERR, "%s: WAI frame is too small!!\n", __FUNCTION__);
+		goto failed;
+	}
+
+	skb_pull(pskb, 14);
+	
+	newskb = dev_alloc_skb(pskb->len+ieee->tx_headroom); 
+	if(!newskb){
+	    	WAPI_TRACE(WAPI_ERR,"%s: can't alloc skb\n",__FUNCTION__);
+		goto failed;
+	}
+	skb_reserve(newskb, ieee->tx_headroom);	
+	memcpy(skb_put(newskb, pskb->len), pskb->data, pskb->len);
+	dev_kfree_skb_any(pskb);
+	/* called with 2nd parm 0, no tx mgmt lock required */
+	rtllib_sta_wakeup(ieee,0);
+
+	tcb_desc = (cb_desc *)(newskb->cb + MAX_DEV_ADDR_SIZE);
+#ifdef RTL8192SU_FPGA_UNSPECIFIED_NETWORK
+	tcb_desc->queue_index = NORMAL_QUEUE;
+#else
+	tcb_desc->queue_index = BE_QUEUE;
+#endif
+	tcb_desc->data_rate = 0x02;	
+	tcb_desc->bTxUseDriverAssingedRate = true;
+	tcb_desc->RATRIndex = 7;
+	tcb_desc->bTxDisableRateFallBack = 1;
+#ifdef _RTL8192_EXT_PATCH_
+	tcb_desc->macId = 0;
+#endif	
+
+	mac_hdr = (struct rtllib_hdr_3addr *)(newskb->data);
+	mac_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+	if (ieee->seq_ctrl[0] == 0xFFF)
+		ieee->seq_ctrl[0] = 0;
+	else
+		ieee->seq_ctrl[0]++;
+
+	if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
+			(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
+			(ieee->queue_stop) ) {
+		WAPI_TRACE(WAPI_TX, "%s: Insert to waitqueue (idx=%d)!!\n", __FUNCTION__, tcb_desc->queue_index);
+		skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], newskb);
+	} else {
+		ieee->softmac_hard_start_xmit(newskb,ieee->dev);
+	}
+
+	return 0;
+	
+failed:	
+	dev_kfree_skb_any(pskb);
+	return -1;
+}
+/**********************************************************
+ **********************************************************/
+const u8 Sbox[256] = {
+0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
+0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
+0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
+0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
+0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
+0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
+0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
+0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
+0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
+0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
+0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
+0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
+0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
+0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
+0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
+0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
+};
+
+const u32 CK[32] = {
+	0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+	0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+	0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+	0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+	0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+	0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+	0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+	0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
+
+#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))
+
+#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \
+                     Sbox[(_A) >> 16 & 0xFF] << 16 | \
+                     Sbox[(_A) >>  8 & 0xFF] <<  8 | \
+                     Sbox[(_A) & 0xFF])
+
+#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))
+#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))
+
+static void
+xor_block(void *dst, void *src1, void *src2)
+/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned  */
+{
+    ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0];
+    ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1];
+    ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2];
+    ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3];
+}
+
+
+void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk)
+{
+	 u32 r, mid, x0, x1, x2, x3, *p;
+	 p = (u32 *)Input;
+	 x0 = p[0];
+	 x1 = p[1];
+	 x2 = p[2];
+	 x3 = p[3];
+#ifdef LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+	 for (r = 0; r < 32; r += 4)
+	 {
+		  mid = x1 ^ x2 ^ x3 ^ rk[r + 0];
+		  mid = ByteSub(mid);
+		  x0 ^= L1(mid);
+		  mid = x2 ^ x3 ^ x0 ^ rk[r + 1];
+		  mid = ByteSub(mid);
+		  x1 ^= L1(mid);
+		  mid = x3 ^ x0 ^ x1 ^ rk[r + 2];
+		  mid = ByteSub(mid);
+		  x2 ^= L1(mid);
+		  mid = x0 ^ x1 ^ x2 ^ rk[r + 3];
+		  mid = ByteSub(mid);
+		  x3 ^= L1(mid);
+	 }
+#ifdef LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+	 p = (u32 *)Output;
+	 p[0] = x3;
+	 p[1] = x2;
+	 p[2] = x1;
+	 p[3] = x0;
+}
+
+
+
+void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag)
+{
+	 u32 r, mid, x0, x1, x2, x3, *p;
+	 
+	 p = (u32 *)Key;
+	 x0 = p[0];
+	 x1 = p[1];
+	 x2 = p[2];
+	 x3 = p[3];
+#ifdef LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+
+	 x0 ^= 0xa3b1bac6;
+	 x1 ^= 0x56aa3350;
+	 x2 ^= 0x677d9197;
+	 x3 ^= 0xb27022dc;
+	 for (r = 0; r < 32; r += 4)
+	 {
+		  mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
+		  mid = ByteSub(mid);
+		  rk[r + 0] = x0 ^= L2(mid);
+		  mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
+		  mid = ByteSub(mid);
+		  rk[r + 1] = x1 ^= L2(mid);
+		  mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
+		  mid = ByteSub(mid);
+		  rk[r + 2] = x2 ^= L2(mid);
+		  mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
+		  mid = ByteSub(mid);
+		  rk[r + 3] = x3 ^= L2(mid);
+	 }
+	 if (CryptFlag == DECRYPT)
+	 {
+	 	  for (r = 0; r < 16; r++)
+	 	  	 mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid;
+	 }
+}
+
+
+void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, 
+                                                u8 *Output, u16 *OutputLength, u32 CryptFlag)
+{
+	u32 blockNum,i,j, rk[32];
+	u16 remainder;
+	u8 blockIn[16],blockOut[16], tempIV[16], k;
+
+	*OutputLength = 0;
+	remainder = InputLength & 0x0F;
+	blockNum = InputLength >> 4;
+	if(remainder !=0)
+		blockNum++;
+	else
+		remainder = 16;
+
+	for(k=0;k<16;k++)
+		tempIV[k] = IV[15-k];
+
+	memcpy(blockIn, tempIV, 16);
+
+      SMS4KeyExt((u8 *)Key, rk,CryptFlag);
+ 
+	for(i=0; i<blockNum-1; i++)
+	{
+		SMS4Crypt((u8 *)blockIn, blockOut, rk);
+             xor_block(&Output[i*16], &Input[i*16], blockOut);
+		memcpy(blockIn,blockOut,16);
+	}
+	
+	*OutputLength = i*16;
+
+	SMS4Crypt((u8 *)blockIn, blockOut, rk);
+
+	for(j=0; j<remainder; j++)
+	{
+		Output[i*16+j] = Input[i*16+j] ^ blockOut[j];
+	}
+      *OutputLength += remainder;  
+
+}
+
+void WapiSMS4Encryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, 
+                                                    u8 *Output, u16 *OutputLength)
+{
+    
+	WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4Decryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, 
+                                                    u8 *Output, u16 *OutputLength)
+{
+	WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4CalculateMic(u8 *Key, u8 *IV, u8 *Input1, u8 Input1Length,
+                                                 u8 *Input2, u16 Input2Length, u8 *Output, u8 *OutputLength)
+{
+	u32 blockNum, i, remainder, rk[32];
+	u8 BlockIn[16], BlockOut[16], TempBlock[16], tempIV[16], k;
+
+	*OutputLength = 0;
+	remainder = Input1Length & 0x0F;
+	blockNum = Input1Length >> 4;
+
+	for(k=0;k<16;k++)
+		tempIV[k] = IV[15-k];
+
+	memcpy(BlockIn, tempIV, 16);
+
+	SMS4KeyExt((u8 *)Key, rk, ENCRYPT);
+
+	SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+      
+	for(i=0; i<blockNum; i++){
+		xor_block(BlockIn, (Input1+i*16), BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+
+	if(remainder !=0){
+		memset(TempBlock, 0, 16);
+		memcpy(TempBlock, (Input1+blockNum*16), remainder);
+
+		xor_block(BlockIn, TempBlock, BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);	
+      }
+
+	remainder = Input2Length & 0x0F;
+	blockNum = Input2Length >> 4;
+
+  	for(i=0; i<blockNum; i++){
+		xor_block(BlockIn, (Input2+i*16), BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+
+	if(remainder !=0){
+		memset(TempBlock, 0, 16);
+		memcpy(TempBlock, (Input2+blockNum*16), remainder);
+
+		xor_block(BlockIn, TempBlock, BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+	
+	memcpy(Output, BlockOut, 16);
+	*OutputLength = 16;
+}
+
+void SecCalculateMicSMS4(
+	u8		KeyIdx,
+	u8        *MicKey, 
+	u8        *pHeader,
+	u8        *pData,
+	u16       DataLen,
+	u8        *MicBuffer
+	)
+{
+	struct rtllib_hdr_3addrqos *header;
+	u8 TempBuf[34], TempLen = 32, MicLen, QosOffset, *IV;
+	u16 *pTemp, fc;
+
+	header = (struct rtllib_hdr_3addrqos *)pHeader;
+	memset(TempBuf, 0, 34);
+	memcpy(TempBuf, pHeader, 2); 
+	pTemp = (u16*)TempBuf;
+	*pTemp &= 0xc78f;       
+
+	memcpy((TempBuf+2), (pHeader+4), 12); 
+	memcpy((TempBuf+14), (pHeader+22), 2); 
+	pTemp = (u16*)(TempBuf + 14);
+	*pTemp &= 0x000f;
+    
+	memcpy((TempBuf+16), (pHeader+16), 6); 
+
+	fc = le16_to_cpu(header->frame_ctl);
+	if((fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) == (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS))
+	{
+		memcpy((TempBuf+22), (pHeader+24), 6);
+		QosOffset = 30;
+	}else{
+		memset((TempBuf+22), 0, 6);
+		QosOffset = 24;
+	}
+
+	if( IsQoSDataFrame(pHeader)){ 
+		memcpy((TempBuf+28), (pHeader+QosOffset), 2);
+		TempLen += 2;
+		IV = pHeader + QosOffset + 2 + 2;
+	}else{
+		IV = pHeader + QosOffset + 2;
+	}
+
+	TempBuf[TempLen-1] = (u8)(DataLen & 0xff);
+	TempBuf[TempLen-2] = (u8)((DataLen & 0xff00)>>8);
+	TempBuf[TempLen-4] = KeyIdx;
+
+	WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16);
+	WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16);
+	WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen);
+	WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen);
+
+	WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen,
+	                                             pData, DataLen, MicBuffer, &MicLen);
+
+	if (MicLen != 16)
+		WAPI_TRACE(WAPI_ERR,"%s: MIC Length Error!!\n",__FUNCTION__);
+}
+	
+int SecSMS4HeaderFillIV(struct rtllib_device *ieee, struct sk_buff *pskb)
+{
+	u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL;
+	u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0;
+	PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+	PRT_WAPI_T         pWapiInfo = &ieee->wapiInfo; 
+	PRT_WAPI_STA_INFO  pWapiSta = NULL; 
+	int ret = 0;
+
+	if ((!ieee->WapiSupport) || (!ieee->wapiInfo.bWapiEnable)){
+		WAPI_TRACE(WAPI_ERR,"%s: ieee->WapiSupport = 0!!\n",__FUNCTION__);
+		return -1;
+	}
+
+	hdr_len = sMacHdrLng;
+	if(IsQoSDataFrame(pskb->data) ){
+		hdr_len += sQoSCtlLng;
+	}
+
+	pos = skb_push(pskb, ieee->wapiInfo.extra_prefix_len);
+	memmove(pos, pos+ieee->wapiInfo.extra_prefix_len, hdr_len);
+
+	pSecHeader = pskb->data + hdr_len;
+	pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader;
+	pRA = pskb->data + 4;
+
+	WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len);
+
+	if( is_multicast_ether_addr(pRA) ){ 
+		if(!pWapiInfo->wapiTxMsk.bTxEnable){
+			WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+			return -2;
+		}
+		if(pWapiInfo->wapiTxMsk.keyId <= 1){
+			pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+			pWapiExt->Reserved = 0;
+			bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+			memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+			if (bPNOverflow){
+				WAPI_TRACE(WAPI_ERR,"===============>%s():multicast PN overflow\n",__FUNCTION__);
+				WapiCreateAppEventAndSend(ieee,NULL,0,pRA, false, false, true, 0, false);
+			}		          
+		}else{
+			WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Multicast KeyIdx!!\n",__FUNCTION__);
+			ret = -3;
+		}
+	}
+    	else{ 
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(pWapiSta->PeerMacAddr,pRA,6)){
+    				bFindMatchPeer = true;
+				break;
+			}
+		}
+		if (bFindMatchPeer){
+			if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)){
+				WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+				return -4;
+			}
+			if (pWapiSta->wapiUsk.keyId <= 1){
+				if(pWapiSta->wapiUskUpdate.bTxEnable)
+					pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+				else
+					pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+
+				pWapiExt->Reserved = 0;
+				bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+				memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+				if (bPNOverflow){
+					WAPI_TRACE(WAPI_ERR,"===============>%s():unicast PN overflow\n",__FUNCTION__);
+					WapiCreateAppEventAndSend(ieee,NULL,0,pWapiSta->PeerMacAddr, false, true, false, 0, false);
+				}
+			}else{
+				WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Unicast KeyIdx!!\n",__FUNCTION__);
+				ret = -5;
+			}
+		}
+		else{		
+			WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta "MAC_FMT"!!\n",__FUNCTION__, MAC_ARG(pRA));
+			ret = -6;
+		}
+    	}
+		
+	WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len);
+	return ret;
+}
+
+void SecSWSMS4Encryption(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb
+	)
+{
+	PRT_WAPI_T		pWapiInfo = &ieee->wapiInfo; 
+	PRT_WAPI_STA_INFO   pWapiSta = NULL; 	
+	u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL, *pHeader = pskb->data;	
+	u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16];	
+	u16 OutputLength;
+
+#if defined(RTL8192U) || defined(RTL8192SU)
+	u32 SpecificHeadOverhead = 0;
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+	cb_desc *tcb_desc = (cb_desc *)(pskb->cb + MAX_DEV_ADDR_SIZE);
+	if (tcb_desc->drv_agg_enable) 
+		SpecificHeadOverhead = TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES;
+	else
+#endif
+	SpecificHeadOverhead = TX_PACKET_SHIFT_BYTES;
+
+	pHeader += SpecificHeadOverhead;
+#endif
+	WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+	if( IsQoSDataFrame(pHeader) ){
+		IVOffset = sMacHdrLng + sQoSCtlLng;
+	}else{
+		IVOffset = sMacHdrLng;
+	}
+	
+	DataOffset = IVOffset + ieee->wapiInfo.extra_prefix_len;
+	
+	pRA = pHeader + 4;
+	if( is_multicast_ether_addr(pRA) ){ 
+		KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+		pIV = pWapiInfo->lastTxMulticastPN;
+		pMicKey = pWapiInfo->wapiTxMsk.micKey;
+		pDataKey = pWapiInfo->wapiTxMsk.dataKey;
+	}else{ 
+		if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)){
+					bFindMatchPeer = true;	    
+					break;
+				}
+			}    
+			
+			if (bFindMatchPeer){
+				if (pWapiSta->wapiUskUpdate.bTxEnable){
+					KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+					WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+					pIV = pWapiSta->lastTxUnicastPN;
+					pMicKey = pWapiSta->wapiUskUpdate.micKey;
+					pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+				}else{
+					KeyIdx = pWapiSta->wapiUsk.keyId;
+					WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+					pIV = pWapiSta->lastTxUnicastPN;
+					pMicKey = pWapiSta->wapiUsk.micKey;
+					pDataKey = pWapiSta->wapiUsk.dataKey;
+				}
+  			}else{
+				WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__);
+				return;
+			}
+		}else{
+			WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__);
+			return;
+		}
+	}	
+
+	SecPtr = pHeader;
+	SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr+DataOffset), pskb->len-DataOffset, MicBuffer);
+
+	WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, ieee->wapiInfo.extra_postfix_len);
+
+	memcpy(skb_put(pskb,ieee->wapiInfo.extra_postfix_len),
+			MicBuffer,
+			ieee->wapiInfo.extra_postfix_len
+			);
+		
+	WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset), pskb->len-DataOffset, (SecPtr+DataOffset), &OutputLength);
+	
+	WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption", pskb->data,pskb->len);
+
+	if (OutputLength != pskb->len-DataOffset)
+		WAPI_TRACE(WAPI_ERR,"%s: Output Length Error!!\n",__FUNCTION__);
+
+	WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+}
+
+u8 SecSWSMS4Decryption(
+	struct rtllib_device *ieee,
+	struct sk_buff *pskb,
+	struct rtllib_rx_stats *rx_stats
+	)
+{
+	PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; 
+	PRT_WAPI_STA_INFO   pWapiSta = NULL; 	
+	u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false;
+	u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16];
+	u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos;
+	u8 TID = 0;
+	u16 OutputLength, DataLen;
+
+	rx_stats->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(ieee, pskb);
+	WAPI_TRACE(WAPI_RX, "=========>%s: check PN  %d\n", __FUNCTION__,rx_stats->bWapiCheckPNInDecrypt);
+	WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len);
+
+	IVOffset = sMacHdrLng;
+	if( rx_stats->bIsQosData ){
+		IVOffset += sQoSCtlLng;
+	}
+	if( rx_stats->bContainHTC )
+		IVOffset += sHTCLng;
+	
+		
+	DataOffset = IVOffset + ieee->wapiInfo.extra_prefix_len;
+
+	pRA = pskb->data + 4;
+	pTA = pskb->data + 10;
+	KeyIdx = *(pskb->data + IVOffset);
+	pRecvPN = pskb->data + IVOffset + 2;
+	pSecData = pskb->data + DataOffset;
+	DataLen = pskb->len - DataOffset;
+	pRecvMic = pskb->data + pskb->len - ieee->wapiInfo.extra_postfix_len;
+	TID = Frame_QoSTID(pskb->data);
+
+	if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)){
+				bFindMatchPeer = true;	    
+				break;
+			}
+		}    
+	}	
+
+	if (!bFindMatchPeer){
+		WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA));
+		return false;
+	}
+
+	if( is_multicast_ether_addr(pRA) ){
+		WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__);
+		if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){
+			pLastRxPN = pWapiSta->lastRxMulticastPN;  
+			if (!WapiComparePN(pRecvPN, pLastRxPN)){
+				WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__);
+				WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16);
+				WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16);
+				return false;
+			}
+
+			memcpy(pLastRxPN, pRecvPN, 16);
+			pMicKey = pWapiSta->wapiMsk.micKey;
+			pDataKey = pWapiSta->wapiMsk.dataKey;
+		}else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){
+			WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__);
+			bUseUpdatedKey = true;
+			memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16);
+			pMicKey = pWapiSta->wapiMskUpdate.micKey;
+			pDataKey = pWapiSta->wapiMskUpdate.dataKey;
+		}else{
+			WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx);
+			return false;
+		}     
+	}
+	else{ 
+		WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__);
+		if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){
+			WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__);
+			if(rx_stats->bWapiCheckPNInDecrypt){
+				if(rx_stats->bIsQosData){
+					WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS);
+					pLastRxPN = lastRxPNforQoS;
+				}else{
+					pLastRxPN = pWapiSta->lastRxUnicastPN;  
+				}
+				if (!WapiComparePN(pRecvPN, pLastRxPN)){
+					return false;
+				}
+				if(rx_stats->bIsQosData){
+					WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+				}else{
+					memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+				}
+			}else{
+				memcpy(rx_stats->WapiTempPN,pRecvPN,16);
+			}
+
+			if (ieee->iw_mode == IW_MODE_INFRA){
+				if ((pRecvPN[0] & 0x1) == 0){
+					WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__);
+					return false;
+				}
+			}
+                   
+			pMicKey = pWapiSta->wapiUsk.micKey;
+			pDataKey = pWapiSta->wapiUsk.dataKey;
+		}
+		else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){
+			WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__);
+			if(pWapiSta->bAuthenticatorInUpdata)
+				bUseUpdatedKey = true;
+			else
+				bUseUpdatedKey = false;
+
+			if(rx_stats->bIsQosData){
+				WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+			}else{
+				memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+			}
+			pMicKey = pWapiSta->wapiUskUpdate.micKey;
+			pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+		}else{
+			WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId);
+			dump_buf(pskb->data,pskb->len);
+			return false;
+		}     	
+	}	
+
+	WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16);
+	WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16);
+	WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength);
+
+	if (OutputLength != DataLen)
+		WAPI_TRACE(WAPI_ERR, "%s:  Output Length Error!!!!\n", __FUNCTION__);      
+
+	WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len);
+
+	DataLen -= ieee->wapiInfo.extra_postfix_len;     
+
+	SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer);
+
+	WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN);
+	WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN);
+
+	if (0 == memcmp(MicBuffer, pRecvMic, ieee->wapiInfo.extra_postfix_len)){
+		WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__);
+		if (bUseUpdatedKey){
+			if ( is_multicast_ether_addr(pRA) ){
+				WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__);
+				pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId;
+				memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16);  
+				memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16);  
+				pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false;
+			}else{
+				WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__);
+				pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId;
+				memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16);  
+				memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16);  
+				pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false; 
+			}       
+		}
+	}else{
+		WAPI_TRACE(WAPI_ERR, "%s:  Check MIC Error, Dropped !!!!\n", __FUNCTION__);      
+		return false;
+	}
+
+	pos = pskb->data;
+	memmove(pos+ieee->wapiInfo.extra_prefix_len, pos, IVOffset);
+	skb_pull(pskb, ieee->wapiInfo.extra_prefix_len);
+
+	WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+
+	return true;
+}
+
+void wapi_test_set_key(struct rtllib_device *ieee, u8* buf)
+{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/
+	PRT_WAPI_T			pWapiInfo = &ieee->wapiInfo;
+	PRT_WAPI_BKID		pWapiBkid;
+	PRT_WAPI_STA_INFO	pWapiSta;
+	u8					data[43];
+	bool					bTxEnable;
+	bool					bUpdate;
+	bool					bAuthenticator;
+	u8					PeerAddr[6];
+	u8					WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8					WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8					WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;		
+
+	WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+	if (!ieee->WapiSupport){
+	    return;
+	}
+
+	copy_from_user(data, buf, 43);
+	bTxEnable = data[1];
+	bAuthenticator = data[2];
+	bUpdate = data[3];
+ 	memcpy(PeerAddr,data+4,6);
+		
+	if(data[0] == 0x3){
+		if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){
+			pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+			list_del_init(&pWapiBkid->list);
+			memcpy(pWapiBkid->bkid, data+10, 16);
+			WAPI_DATA(WAPI_INIT, "SetKey - BKID", pWapiBkid->bkid, 16);
+			list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList);
+		}
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){
+				pWapiSta->bAuthenticatorInUpdata = false;
+				switch(data[0]){
+				case 1:              
+					if(bAuthenticator){         
+						memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16);
+						if(!bUpdate) {     
+							WAPI_TRACE(WAPI_INIT,"AE fisrt set usk \n");
+							pWapiSta->wapiUsk.bSet = true;
+							memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+							pWapiSta->wapiUsk.keyId = *(data+42);
+							pWapiSta->wapiUsk.bTxEnable = true;
+							WAPI_DATA(WAPI_INIT, "SetKey - AE USK Data Key", pWapiSta->wapiUsk.dataKey, 16);
+							WAPI_DATA(WAPI_INIT, "SetKey - AE USK Mic Key", pWapiSta->wapiUsk.micKey, 16);
+						}
+						else               
+						{
+							WAPI_TRACE(WAPI_INIT, "AE update usk \n");
+							pWapiSta->wapiUskUpdate.bSet = true;
+							pWapiSta->bAuthenticatorInUpdata = true;
+							memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+							memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							pWapiSta->wapiUskUpdate.keyId = *(data+42);
+							pWapiSta->wapiUskUpdate.bTxEnable = true;
+						}
+					}
+					else{
+						if(!bUpdate){
+							WAPI_TRACE(WAPI_INIT,"ASUE fisrt set usk \n");
+							if(bTxEnable){
+								pWapiSta->wapiUsk.bTxEnable = true;
+								memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							}else{
+								pWapiSta->wapiUsk.bSet = true;
+								memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+								memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+								pWapiSta->wapiUsk.keyId = *(data+42);
+								pWapiSta->wapiUsk.bTxEnable = false;
+							}
+						}else{
+							WAPI_TRACE(WAPI_INIT,"ASUE update usk \n");
+							if(bTxEnable){
+								pWapiSta->wapiUskUpdate.bTxEnable = true;
+								if(pWapiSta->wapiUskUpdate.bSet){
+									memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16);
+									memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16);
+									pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId;
+									memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+									pWapiSta->wapiUskUpdate.bTxEnable = false;
+									pWapiSta->wapiUskUpdate.bSet = false;
+								}
+								memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							}else{
+								pWapiSta->wapiUskUpdate.bSet = true;
+								memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+								memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+								pWapiSta->wapiUskUpdate.keyId = *(data+42);
+								pWapiSta->wapiUskUpdate.bTxEnable = false;
+							}
+						}
+					}
+					break;
+				case 2:		
+					if(bAuthenticator){          
+						pWapiInfo->wapiTxMsk.bSet = true;
+						memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16);													
+						memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16);
+						pWapiInfo->wapiTxMsk.keyId = *(data+42);
+						pWapiInfo->wapiTxMsk.bTxEnable = true;
+						memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16);
+
+						if(!bUpdate){      
+							WAPI_TRACE(WAPI_INIT, "AE fisrt set msk \n");
+							if(!pWapiSta->bSetkeyOk)
+								pWapiSta->bSetkeyOk = true;
+							pWapiInfo->bFirstAuthentiateInProgress= false;
+						}else{               
+							WAPI_TRACE(WAPI_INIT,"AE update msk \n");
+						}
+
+						WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Data Key", pWapiInfo->wapiTxMsk.dataKey, 16);
+						WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Mic Key", pWapiInfo->wapiTxMsk.micKey, 16);
+					}
+					else{
+						if(!bUpdate){
+							WAPI_TRACE(WAPI_INIT,"ASUE fisrt set msk \n");
+							pWapiSta->wapiMsk.bSet = true;
+							memcpy(pWapiSta->wapiMsk.dataKey,data+10,16);													
+							memcpy(pWapiSta->wapiMsk.micKey,data+26,16);
+							pWapiSta->wapiMsk.keyId = *(data+42);
+							pWapiSta->wapiMsk.bTxEnable = false;
+							if(!pWapiSta->bSetkeyOk)
+								pWapiSta->bSetkeyOk = true;
+							pWapiInfo->bFirstAuthentiateInProgress= false;
+							WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Data Key", pWapiSta->wapiMsk.dataKey, 16);
+							WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Mic Key", pWapiSta->wapiMsk.micKey, 16);
+						}else{
+							WAPI_TRACE(WAPI_INIT,"ASUE update msk \n");
+							pWapiSta->wapiMskUpdate.bSet = true;
+							memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16);													
+							memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16);
+							pWapiSta->wapiMskUpdate.keyId = *(data+42);
+							pWapiSta->wapiMskUpdate.bTxEnable = false;
+						}
+					}
+					break;
+				default:
+					WAPI_TRACE(WAPI_ERR,"Unknown Flag \n");
+					break;
+				}
+			}
+		}
+	}
+	WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+
+void wapi_test_init(struct rtllib_device *ieee)
+{
+	u8 keybuf[100];
+	u8 mac_addr[6]={0x00,0xe0,0x4c,0x72,0x04,0x70};
+	u8 UskDataKey[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
+	u8 UskMicKey[16]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+	u8 UskId = 0;
+	u8 MskDataKey[16]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
+	u8 MskMicKey[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f};
+	u8 MskId = 0;
+
+	WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+	WAPI_TRACE(WAPI_INIT, "%s: Enable wapi!!!!\n", __FUNCTION__);
+	ieee->wapiInfo.bWapiEnable = true;
+	ieee->pairwise_key_type = KEY_TYPE_SMS4;
+	ieee->group_key_type = KEY_TYPE_SMS4;
+	ieee->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+	ieee->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+
+	WAPI_TRACE(WAPI_INIT, "%s: Set USK!!!!\n", __FUNCTION__);
+	memset(keybuf,0,100);
+	keybuf[0] = 1;                           
+	keybuf[1] = 1; 				
+	keybuf[2] = 1; 				
+	keybuf[3] = 0; 				
+	
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,UskDataKey,16);
+	memcpy(keybuf+26,UskMicKey,16);
+	keybuf[42]=UskId;
+	wapi_test_set_key(ieee, keybuf);
+	
+	memset(keybuf,0,100);
+	keybuf[0] = 1;                           
+	keybuf[1] = 1; 				
+	keybuf[2] = 0; 				
+	keybuf[3] = 0; 				
+	
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,UskDataKey,16);
+	memcpy(keybuf+26,UskMicKey,16);
+	keybuf[42]=UskId;
+	wapi_test_set_key(ieee, keybuf);
+	
+	WAPI_TRACE(WAPI_INIT, "%s: Set MSK!!!!\n", __FUNCTION__);
+	memset(keybuf,0,100);
+	keybuf[0] = 2;                                
+	keybuf[1] = 1;                               
+	keybuf[2] = 1; 				
+	keybuf[3] = 0;                              
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,MskDataKey,16);
+	memcpy(keybuf+26,MskMicKey,16);
+	keybuf[42] = MskId;
+	wapi_test_set_key(ieee, keybuf);
+
+	memset(keybuf,0,100);
+	keybuf[0] = 2;                                
+	keybuf[1] = 1;                               
+	keybuf[2] = 0; 				
+	keybuf[3] = 0;                              
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,MskDataKey,16);
+	memcpy(keybuf+26,MskMicKey,16);
+	keybuf[42] = MskId;
+	wapi_test_set_key(ieee, keybuf);
+	WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/michael_mic.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/michael_mic.c
@@ -0,0 +1,194 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "rtl_crypto.h"
+
+
+struct michael_mic_ctx {
+	u8 pending[4];
+	size_t pending_len;
+
+	u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+	return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+	return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r)	\
+do {				\
+	r ^= rotl(l, 17);	\
+	l += r;			\
+	r ^= xswap(l);		\
+	l += r;			\
+	r ^= rotl(l, 3);	\
+	l += r;			\
+	r ^= rotr(l, 2);	\
+	l += r;			\
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+	p[0] = v;
+	p[1] = v >> 8;
+	p[2] = v >> 16;
+	p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+	struct michael_mic_ctx *mctx = ctx;
+
+	if (mctx->pending_len) {
+		int flen = 4 - mctx->pending_len;
+		if (flen > len)
+			flen = len;
+		memcpy(&mctx->pending[mctx->pending_len], data, flen);
+		mctx->pending_len += flen;
+		data += flen;
+		len -= flen;
+
+		if (mctx->pending_len < 4)
+			return;
+
+		mctx->l ^= get_le32(mctx->pending);
+		michael_block(mctx->l, mctx->r);
+		mctx->pending_len = 0;
+	}
+
+	while (len >= 4) {
+		mctx->l ^= get_le32(data);
+		michael_block(mctx->l, mctx->r);
+		data += 4;
+		len -= 4;
+	}
+
+	if (len > 0) {
+		mctx->pending_len = len;
+		memcpy(mctx->pending, data, len);
+	}
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	u8 *data = mctx->pending;
+
+	/* Last block and padding (0x5a, 4..7 x 0) */
+	switch (mctx->pending_len) {
+	case 0:
+		mctx->l ^= 0x5a;
+		break;
+	case 1:
+		mctx->l ^= data[0] | 0x5a00;
+		break;
+	case 2:
+		mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+		break;
+	case 3:
+		mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+			0x5a000000;
+		break;
+	}
+	michael_block(mctx->l, mctx->r);
+	/* l ^= 0; */
+	michael_block(mctx->l, mctx->r);
+
+	put_le32(out, mctx->l);
+	put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+			  u32 *flags)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	if (keylen != 8) {
+		if (flags)
+			*flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+	mctx->l = get_le32(key);
+	mctx->r = get_le32(key + 4);
+	return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+	.cra_name	= "michael_mic",
+	.cra_flags	= CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	= 8,
+	.cra_ctxsize	= sizeof(struct michael_mic_ctx),
+	.cra_module	= THIS_MODULE,
+	.cra_list	= LIST_HEAD_INIT(michael_mic_alg.cra_list),
+	.cra_u		= { .digest = {
+	.dia_digestsize	= 8,
+	.dia_init	= michael_init,
+	.dia_update	= michael_update,
+	.dia_final	= michael_final,
+	.dia_setkey	= michael_setkey } }
+};
+
+
+int __init michael_mic_init(void)
+{
+	return crypto_register_alg(&michael_mic_alg);
+}
+
+
+void __exit michael_mic_exit(void)
+{
+	crypto_unregister_alg(&michael_mic_alg);
+}
+
+#ifndef BUILT_IN_CRYPTO
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_wx.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_wx.c
@@ -0,0 +1,1346 @@
+/******************************************************************************
+
+  Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+  Portions of this file are based on the WEP enablement code provided by the
+  Host AP project hostap-drivers v0.1.3
+  Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+  <jkmaline@cc.hut.fi>
+  Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  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.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/wireless.h>
+#include <linux/version.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+
+#include "rtllib.h"
+#if 0
+static const char *rtllib_modes[] = {
+	"?", "a", "b", "ab", "g", "ag", "bg", "abg"
+};
+#endif
+struct modes_unit {
+	char *mode_string;
+	int mode_size;
+};
+static struct modes_unit rtllib_modes[] = {
+	{"a",1}, 
+	{"b",1}, 
+	{"g",1}, 
+	{"?",1},
+#ifdef _RTL8192_EXT_PATCH_
+	{"n",5},
+	{"n",4},
+#else
+	{"N-24G",5},
+	{"N-5G",4},
+#endif
+};
+
+#define MAX_CUSTOM_LEN 64
+static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
+ 					   char *start, char *stop,
+					   struct rtllib_network *network,
+                                           struct iw_request_info *info)
+{
+	char custom[MAX_CUSTOM_LEN];
+	char proto_name[IFNAMSIZ];
+	char *pname = proto_name;
+	char *p;
+	struct iw_event iwe;
+	int i, j;
+	u16 max_rate, rate;
+	static u8	EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
+
+	/* First entry *MUST* be the AP MAC address */
+	iwe.cmd = SIOCGIWAP;
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
+	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
+	/* Remaining entries will be displayed in the order we provide them */
+
+	/* Add the ESSID */
+	iwe.cmd = SIOCGIWESSID;
+	iwe.u.data.flags = 1;
+	if(network->ssid_len > 0){
+		iwe.u.data.length = min(network->ssid_len, (u8)32);
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->ssid);
+        }else if(network->hidden_ssid_len == 0){
+		iwe.u.data.length = sizeof("<hidden>");
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, "<hidden>");
+        }else {
+		iwe.u.data.length = min(network->hidden_ssid_len, (u8)32);
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->hidden_ssid);
+	}
+	/* Add the protocol name */
+	iwe.cmd = SIOCGIWNAME;
+	for(i=0; i<(sizeof(rtllib_modes)/sizeof(rtllib_modes[0])); i++) {
+		if(network->mode&(1<<i)) {
+			sprintf(pname,rtllib_modes[i].mode_string,rtllib_modes[i].mode_size);
+			pname +=rtllib_modes[i].mode_size;
+		}	
+	}
+	*pname = '\0';
+	snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
+        start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
+        /* Add mode */
+        iwe.cmd = SIOCGIWMODE;
+        if (network->capability &
+	    (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+		if (network->capability & WLAN_CAPABILITY_ESS)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_ADHOC;
+		start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
+        }
+
+        /* Add frequency/channel */
+	iwe.cmd = SIOCGIWFREQ;
+/*	iwe.u.freq.m = rtllib_frequency(network->channel, network->mode);
+	iwe.u.freq.e = 3; */
+	iwe.u.freq.m = network->channel;
+	iwe.u.freq.e = 0;
+	iwe.u.freq.i = 0;
+	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
+
+	/* Add encryption capability */
+	iwe.cmd = SIOCGIWENCODE;
+	if (network->capability & WLAN_CAPABILITY_PRIVACY)
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	else
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	iwe.u.data.length = 0;
+	start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->ssid);
+	/* Add basic and extended rates */
+	max_rate = 0;
+	p = custom;
+	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+	for (i = 0, j = 0; i < network->rates_len; ) {
+		if (j < network->rates_ex_len &&
+		    ((network->rates_ex[j] & 0x7F) <
+		     (network->rates[i] & 0x7F)))
+			rate = network->rates_ex[j++] & 0x7F;
+		else
+			rate = network->rates[i++] & 0x7F;
+		if (rate > max_rate)
+			max_rate = rate;
+		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+	}
+	for (; j < network->rates_ex_len; j++) {
+		rate = network->rates_ex[j] & 0x7F;
+		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+		if (rate > max_rate)
+			max_rate = rate;
+	}
+	
+	if (network->mode >= IEEE_N_24G)
+	{
+		PHT_CAPABILITY_ELE ht_cap = NULL;
+		bool is40M = false, isShortGI = false;
+		u8 max_mcs = 0;
+		if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
+			ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
+		else
+			ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
+		is40M = (ht_cap->ChlWidth)?1:0;
+		isShortGI = (ht_cap->ChlWidth)?
+						((ht_cap->ShortGI40Mhz)?1:0):
+						((ht_cap->ShortGI20Mhz)?1:0);
+		
+		max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
+		rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
+		if (rate > max_rate)
+			max_rate = rate;	
+	}
+#if 0	
+	printk("max rate:%d ===basic rate:\n", max_rate);
+	for (i=0;i<network->rates_len;i++)
+		printk(" %x", network->rates[i]);
+	printk("\n=======extend rate\n");
+	for (i=0; i<network->rates_ex_len; i++)
+		printk(" %x", network->rates_ex[i]);
+	printk("\n");
+#endif
+	iwe.cmd = SIOCGIWRATE;
+	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+	iwe.u.bitrate.value = max_rate * 500000;
+	start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
+				     IW_EV_PARAM_LEN);
+	iwe.cmd = IWEVCUSTOM;
+	iwe.u.data.length = p - custom;
+	if (iwe.u.data.length)
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom);
+	/* Add quality statistics */
+	/* TODO: Fix these values... */
+	iwe.cmd = IWEVQUAL;
+	iwe.u.qual.qual = network->stats.signal;
+	iwe.u.qual.level = network->stats.rssi;
+	iwe.u.qual.noise = network->stats.noise;
+	iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
+	if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
+		iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
+	if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
+		iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
+	if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
+		iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+	iwe.u.qual.updated = 7;
+	start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
+
+	iwe.cmd = IWEVCUSTOM;
+	p = custom;
+	iwe.u.data.length = p - custom;
+	if (iwe.u.data.length)
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom);
+#if (WIRELESS_EXT < 18) 
+	if (ieee->wpa_enabled && network->wpa_ie_len){
+		char buf[MAX_WPA_IE_LEN * 2 + 30];
+		u8 *p = buf;
+		p += sprintf(p, "wpa_ie=");
+		for (i = 0; i < network->wpa_ie_len; i++) {
+			p += sprintf(p, "%02x", network->wpa_ie[i]);
+		}
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		iwe.u.data.length = strlen(buf);
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+        }
+
+	if (ieee->wpa_enabled && network->rsn_ie_len){
+		char buf[MAX_WPA_IE_LEN * 2 + 30];
+
+		u8 *p = buf;
+		p += sprintf(p, "rsn_ie=");
+		for (i = 0; i < network->rsn_ie_len; i++) {
+			p += sprintf(p, "%02x", network->rsn_ie[i]);
+		}
+
+		memset(&iwe, 0, sizeof(iwe));
+		iwe.cmd = IWEVCUSTOM;
+		iwe.u.data.length = strlen(buf);
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+        }
+#else
+	memset(&iwe, 0, sizeof(iwe));
+	if (network->wpa_ie_len)
+	{
+		char buf[MAX_WPA_IE_LEN];
+		memcpy(buf, network->wpa_ie, network->wpa_ie_len);
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = network->wpa_ie_len;
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+        }
+	memset(&iwe, 0, sizeof(iwe));
+	if (network->rsn_ie_len)
+	{
+		char buf[MAX_WPA_IE_LEN];
+		memcpy(buf, network->rsn_ie, network->rsn_ie_len);
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = network->rsn_ie_len;
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+        }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+#ifndef CUSTOMER_ID_INTEL_CMPC
+	/* add info for WZC */
+	memset(&iwe, 0, sizeof(iwe));
+	if (network->wzc_ie_len)
+	{
+		char buf[MAX_WZC_IE_LEN];
+		memcpy(buf, network->wzc_ie, network->wzc_ie_len);
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = network->wzc_ie_len;
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+        }
+#endif	
+#endif
+#endif
+
+	/* Add EXTRA: Age to display seconds since last beacon/probe response
+	 * for given network. */
+	iwe.cmd = IWEVCUSTOM;
+	p = custom;
+	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+		      " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
+	iwe.u.data.length = p - custom;
+	if (iwe.u.data.length)
+		start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom);
+
+	return start;
+}
+
+int rtllib_wx_get_scan(struct rtllib_device *ieee,
+			  struct iw_request_info *info,
+			  union iwreq_data *wrqu, char *extra)
+{
+	struct rtllib_network *network;
+	unsigned long flags;
+
+	char *ev = extra;
+	char *stop = ev + wrqu->data.length;
+	int i = 0;
+	int err = 0;
+	RTLLIB_DEBUG_WX("Getting scan\n");
+	down(&ieee->wx_sem);
+	spin_lock_irqsave(&ieee->lock, flags);
+
+	list_for_each_entry(network, &ieee->network_list, list) {
+		i++;
+		if((stop-ev)<200)
+		{
+			err = -E2BIG;		
+			break;	
+												}
+		if (ieee->scan_age == 0 ||
+		    time_after(network->last_scanned + ieee->scan_age, jiffies))
+			ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
+		else
+			RTLLIB_DEBUG_SCAN(
+				"Not showing network '%s ("
+				MAC_FMT ")' due to age (%lums).\n",
+				escape_essid(network->ssid,
+					     network->ssid_len),
+				MAC_ARG(network->bssid),
+				(jiffies - network->last_scanned) / (HZ / 100));
+	}
+
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	up(&ieee->wx_sem);
+	wrqu->data.length = ev -  extra;
+	wrqu->data.flags = 0;
+
+	RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
+
+	return err;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_wx_set_encode(struct rtllib_device *ieee,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *keybuf, u8 is_mesh)
+#else
+int rtllib_wx_set_encode(struct rtllib_device *ieee,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *keybuf)
+#endif
+{
+	struct iw_point *erq = &(wrqu->encoding);
+	struct net_device *dev = ieee->dev;
+	struct rtllib_security sec = {
+		.flags = 0
+	};
+	int i, key, key_provided, len;
+	struct rtllib_crypt_data **crypt;
+
+	RTLLIB_DEBUG_WX("SET_ENCODE\n");
+
+	key = erq->flags & IW_ENCODE_INDEX;
+	if (key) {
+		if (key > WEP_KEYS)
+			return -EINVAL;
+		key--;
+		key_provided = 1;
+	} else {
+		key_provided = 0;
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			key = ieee->mesh_txkeyidx;
+		else
+#endif
+		key = ieee->tx_keyidx;
+	}
+
+	RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
+			   "provided" : "default");
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		crypt = &ieee->cryptlist[0]->crypt[key];
+	else
+		crypt = &ieee->sta_crypt[key];
+#else
+	crypt = &ieee->crypt[key];
+#endif
+	if (erq->flags & IW_ENCODE_DISABLED) {
+		if (key_provided && *crypt) {
+			RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
+					   key);
+			rtllib_crypt_delayed_deinit(ieee, crypt);
+		} else
+			RTLLIB_DEBUG_WX("Disabling encryption.\n");
+
+		/* Check all the keys to see if any are still configured,
+		 * and if no key index was provided, de-init them all */
+		for (i = 0; i < WEP_KEYS; i++) {
+#ifdef _RTL8192_EXT_PATCH_
+			bool null_crypt = false;
+			if(is_mesh)
+				null_crypt = (ieee->cryptlist[0]->crypt[i] != NULL) ? true:false; 
+			else
+				null_crypt = (ieee->sta_crypt[i] != NULL) ? true:false;
+			if (null_crypt)	
+#else
+				if (ieee->crypt[i] != NULL) 
+#endif
+				{
+					if (key_provided)
+						break;
+#ifdef _RTL8192_EXT_PATCH_			
+					if(is_mesh)
+						rtllib_crypt_delayed_deinit(ieee, &ieee->cryptlist[0]->crypt[i]);
+					else
+						rtllib_crypt_delayed_deinit(ieee, &ieee->sta_crypt[i]);
+#else
+					rtllib_crypt_delayed_deinit(ieee, &ieee->crypt[i]);
+#endif
+
+				}
+		}
+
+		if (i == WEP_KEYS) {
+			sec.enabled = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_ENABLED | SEC_LEVEL;
+		}
+
+		goto done;
+	}
+
+
+
+	sec.enabled = 1;
+	sec.flags |= SEC_ENABLED;
+
+	if (*crypt != NULL && (*crypt)->ops != NULL &&
+	    strcmp((*crypt)->ops->name, "WEP") != 0) {
+		/* changing to use WEP; deinit previously used algorithm
+		 * on this key */
+		rtllib_crypt_delayed_deinit(ieee, crypt);
+	}
+
+	if (*crypt == NULL) {
+		struct rtllib_crypt_data *new_crypt;
+
+		/* take WEP into use */
+		new_crypt = kmalloc(sizeof(struct rtllib_crypt_data),
+				    GFP_KERNEL);
+		if (new_crypt == NULL)
+			return -ENOMEM;
+		memset(new_crypt, 0, sizeof(struct rtllib_crypt_data));
+		new_crypt->ops = rtllib_get_crypto_ops("WEP");
+		if (!new_crypt->ops) {
+			request_module("rtllib_crypt_wep");
+			new_crypt->ops = rtllib_get_crypto_ops("WEP");
+		}
+
+#ifdef BUILT_IN_RTLLIB
+		if (new_crypt->ops)
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+#else			
+		if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
+#endif
+#endif
+		{
+			new_crypt->priv = new_crypt->ops->init(key);
+		}	
+
+		if (!new_crypt->ops || !new_crypt->priv) {
+			kfree(new_crypt);
+			new_crypt = NULL;
+
+			printk(KERN_WARNING "%s: could not initialize WEP: "
+			       "load module rtllib_crypt_wep\n",
+			       dev->name);
+			return -EOPNOTSUPP;
+		}
+		*crypt = new_crypt;
+	}
+
+	/* If a new key was provided, set it up */
+	if (erq->length > 0) {
+		len = erq->length <= 5 ? 5 : 13;
+		memcpy(sec.keys[key], keybuf, erq->length);
+		if (len > erq->length)
+			memset(sec.keys[key] + erq->length, 0,
+			       len - erq->length);
+		RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
+				   key, escape_essid(sec.keys[key], len),
+				   erq->length, len);
+		sec.key_sizes[key] = len;
+ 		(*crypt)->ops->set_key(sec.keys[key], len, NULL,
+				       (*crypt)->priv);
+		sec.flags |= (1 << key);
+		/* This ensures a key will be activated if no key is
+		 * explicitely set */
+		if (key == sec.active_key)
+			sec.flags |= SEC_ACTIVE_KEY;
+#ifdef _RTL8192_EXT_PATCH_			
+		if(is_mesh)
+			ieee->mesh_txkeyidx = key;
+		else
+#endif
+		ieee->tx_keyidx = key;
+
+	} else {
+		len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+					     NULL, (*crypt)->priv);
+		if (len == 0) {
+			/* Set a default key of all 0 */
+			printk("Setting key %d to all zero.\n",
+					   key);
+
+			RTLLIB_DEBUG_WX("Setting key %d to all zero.\n",
+					   key);
+			memset(sec.keys[key], 0, 13);
+			(*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+					       (*crypt)->priv);
+			sec.key_sizes[key] = 13;
+			sec.flags |= (1 << key);
+		}
+
+		/* No key data - just set the default TX key index */
+		if (key_provided) {
+			RTLLIB_DEBUG_WX(
+				"Setting key %d to default Tx key.\n", key);
+#ifdef _RTL8192_EXT_PATCH_
+			if(is_mesh)
+				ieee->mesh_txkeyidx = key;
+			else
+#endif
+			ieee->tx_keyidx = key;
+			sec.active_key = key;
+			sec.flags |= SEC_ACTIVE_KEY;
+		}
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh)&&ieee->ext_patch_rtllib_create_crypt_for_peer)
+	{
+		ieee->ext_patch_rtllib_create_crypt_for_peer(ieee);
+	}
+#endif
+ done:
+	ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+	ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
+	sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
+	sec.flags |= SEC_AUTH_MODE;
+	RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
+			   "OPEN" : "SHARED KEY");
+
+	/* For now we just support WEP, so only set that security level...
+	 * TODO: When WPA is added this is one place that needs to change */
+	sec.flags |= SEC_LEVEL;
+	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
+
+	if (ieee->set_security)
+		ieee->set_security(dev, &sec);
+
+	/* Do not reset port if card is in Managed mode since resetting will
+	 * generate new IEEE 802.11 authentication which may end up in looping
+	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
+	 * configuration (for example... Prism2), implement the reset_port in
+	 * the callbacks structures used to initialize the 802.11 stack. */
+	if (ieee->reset_on_keychange &&
+	    ieee->iw_mode != IW_MODE_INFRA &&
+	    ieee->reset_port && ieee->reset_port(dev)) {
+		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_wx_get_encode(struct rtllib_device *ieee,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *keybuf, u8 is_mesh)
+#else
+int rtllib_wx_get_encode(struct rtllib_device *ieee,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *keybuf)
+#endif
+{
+	struct iw_point *erq = &(wrqu->encoding);
+	int len, key;
+	struct rtllib_crypt_data *crypt;
+
+	RTLLIB_DEBUG_WX("GET_ENCODE\n");
+
+	if(ieee->iw_mode == IW_MODE_MONITOR)
+		return -1;
+	
+	key = erq->flags & IW_ENCODE_INDEX;
+	if (key) {
+		if (key > WEP_KEYS)
+			return -EINVAL;
+		key--;
+	} else {
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			key = ieee->mesh_txkeyidx;
+		else
+#endif
+		key = ieee->tx_keyidx;
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		crypt = ieee->cryptlist[0]->crypt[key];
+	else
+		crypt = ieee->sta_crypt[key];
+#else
+	crypt = ieee->crypt[key];
+#endif
+
+	erq->flags = key + 1;
+
+	if (crypt == NULL || crypt->ops == NULL) {
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_DISABLED;
+		return 0;
+	}
+#if 0
+	if (strcmp(crypt->ops->name, "WEP") != 0) {
+		/* only WEP is supported with wireless extensions, so just
+		 * report that encryption is used */
+		erq->length = 0;
+		erq->flags |= IW_ENCODE_ENABLED;
+		return 0;
+	}
+#endif
+	len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
+	erq->length = (len >= 0 ? len : 0);
+
+	erq->flags |= IW_ENCODE_ENABLED;
+
+	if (ieee->open_wep)
+		erq->flags |= IW_ENCODE_OPEN;
+	else
+		erq->flags |= IW_ENCODE_RESTRICTED;
+
+	return 0;
+}
+#if (WIRELESS_EXT >= 18)
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra, u8 is_mesh)
+#else
+int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+#endif
+{
+	int ret = 0;
+	struct net_device *dev = ieee->dev;
+        struct iw_point *encoding = &wrqu->encoding;
+        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+        int i, idx;
+        int group_key = 0;
+        const char *alg, *module;
+        struct rtllib_crypto_ops *ops;
+        struct rtllib_crypt_data **crypt;
+
+        struct rtllib_security sec = {
+                .flags = 0,
+        };
+        idx = encoding->flags & IW_ENCODE_INDEX;
+        if (idx) {
+                if (idx < 1 || idx > WEP_KEYS)
+                        return -EINVAL;
+                idx--;
+	} else{
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			idx = ieee->mesh_txkeyidx;
+		else
+#endif
+			idx = ieee->tx_keyidx;
+	}
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			crypt = &ieee->cryptlist[0]->crypt[idx];
+		else
+			crypt = &ieee->sta_crypt[idx];
+#else
+		crypt = &ieee->crypt[idx];
+#endif
+		group_key = 1;
+	} else {
+		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
+		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
+                        return -EINVAL;
+#ifdef _RTL8192_EXT_PATCH_
+		if ((ieee->iw_mode == IW_MODE_INFRA)||
+			((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))){
+			if(is_mesh)
+				crypt = &ieee->cryptlist[0]->crypt[idx];
+			else
+				crypt = &ieee->sta_crypt[idx];
+		}
+		else
+			return -EINVAL;
+#else
+		if (ieee->iw_mode == IW_MODE_INFRA)
+			crypt = &ieee->crypt[idx];
+		else
+			return -EINVAL;
+#endif
+	}
+
+	sec.flags |= SEC_ENABLED;
+	if ((encoding->flags & IW_ENCODE_DISABLED) ||
+            ext->alg == IW_ENCODE_ALG_NONE) {
+		if (*crypt)
+			rtllib_crypt_delayed_deinit(ieee, crypt);
+
+		for (i = 0; i < WEP_KEYS; i++)
+		{
+#ifdef _RTL8192_EXT_PATCH_
+			if ((is_mesh)&&(ieee->cryptlist[0]->crypt[i] != NULL))
+				break;
+			if ((!is_mesh)&&(ieee->sta_crypt[i] != NULL))
+				break;
+#else
+			if (ieee->crypt[i] != NULL)
+				break;
+#endif	
+		}
+		if (i == WEP_KEYS) {
+			sec.enabled = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_LEVEL;
+		}
+		goto done;
+	}
+	
+	sec.enabled = 1;
+#if 0
+        if (group_key ? !ieee->host_mc_decrypt :
+            !(ieee->host_encrypt || ieee->host_decrypt ||
+              ieee->host_encrypt_msdu))
+                goto skip_host_crypt;
+#endif
+        switch (ext->alg) {
+        case IW_ENCODE_ALG_WEP:
+                alg = "WEP";
+                module = "rtllib_crypt_wep";
+                break;
+        case IW_ENCODE_ALG_TKIP:
+                alg = "TKIP";
+                module = "rtllib_crypt_tkip";
+                break;
+        case IW_ENCODE_ALG_CCMP:
+                alg = "CCMP";
+                module = "rtllib_crypt_ccmp";
+                break;
+        default:
+                RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
+                                   dev->name, ext->alg);
+                ret = -EINVAL;
+                goto done;
+        }
+	printk("alg name:%s\n",alg);
+
+	 ops = rtllib_get_crypto_ops(alg);
+        if (ops == NULL) {
+                char tempbuf[100];
+
+                memset( tempbuf, 0x00, 100 );
+                sprintf( tempbuf, "%s", module);
+                request_module("%s",tempbuf);
+                ops = rtllib_get_crypto_ops(alg);
+        }
+        if (ops == NULL) {
+                RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
+                                   dev->name, ext->alg);
+		printk("========>unknown crypto alg %d\n", ext->alg);
+                ret = -EINVAL;
+                goto done;
+        }
+
+        if (*crypt == NULL || (*crypt)->ops != ops) {
+                struct rtllib_crypt_data *new_crypt;
+
+                rtllib_crypt_delayed_deinit(ieee, crypt);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+                new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
+#else
+                new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+		memset(new_crypt,0,sizeof(*new_crypt));
+#endif
+                if (new_crypt == NULL) {
+                        ret = -ENOMEM;
+                        goto done;
+                }
+                new_crypt->ops = ops;
+#ifdef BUILT_IN_RTLLIB
+		if (new_crypt->ops)
+#else
+                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+#endif			
+		{
+                        new_crypt->priv = new_crypt->ops->init(idx);
+		}
+
+                if (new_crypt->priv == NULL) {
+                        kfree(new_crypt);
+                        ret = -EINVAL;
+                        goto done;
+                }
+                *crypt = new_crypt;
+
+ 	}
+#ifdef _RTL8192_EXT_PATCH_
+	if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh))
+	{
+		int j;
+		for (j=1; j<MAX_MP; j++)
+		{
+			struct rtllib_crypt_data ** crypttmp =  &ieee->cryptlist[j]->crypt[idx];
+			if (*crypttmp == NULL)
+				break;
+			if (*crypttmp && (*crypttmp)->ops != ops)
+				rtllib_crypt_delayed_deinit(ieee, crypttmp);
+		}	
+	}
+#endif	
+
+        if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+            (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+                                   (*crypt)->priv) < 0) {
+                RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
+		printk("key setting failed\n");
+                ret = -EINVAL;
+                goto done;
+        }
+#if 1	
+        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+#ifdef _RTL8192_EXT_PATCH_
+			if(is_mesh)
+				ieee->mesh_txkeyidx = idx;
+			else
+#endif
+                ieee->tx_keyidx = idx;
+                sec.active_key = idx;
+                sec.flags |= SEC_ACTIVE_KEY;
+        }
+#ifdef _RTL8192_EXT_PATCH_
+	if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh)&&ieee->ext_patch_rtllib_create_crypt_for_peer)
+	{
+		ieee->ext_patch_rtllib_create_crypt_for_peer(ieee);
+	}
+#endif
+        if (ext->alg != IW_ENCODE_ALG_NONE) {
+                sec.key_sizes[idx] = ext->key_len;
+                sec.flags |= (1 << idx);
+                if (ext->alg == IW_ENCODE_ALG_WEP) {
+                        sec.flags |= SEC_LEVEL;
+                        sec.level = SEC_LEVEL_1;
+                } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+                        sec.flags |= SEC_LEVEL;
+                        sec.level = SEC_LEVEL_2;
+                } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+                        sec.flags |= SEC_LEVEL;
+                        sec.level = SEC_LEVEL_3;
+                }
+                /* Don't set sec level for group keys. */
+                if (group_key)
+                        sec.flags &= ~SEC_LEVEL;
+        }
+#endif
+done:
+        if (ieee->set_security)
+                ieee->set_security(ieee->dev, &sec);
+
+	 if (ieee->reset_on_keychange &&
+            ieee->iw_mode != IW_MODE_INFRA &&
+            ieee->reset_port && ieee->reset_port(dev)) {
+                RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
+                return -EINVAL;
+        }
+        return ret;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra, u8 is_mesh)
+#else
+int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+#endif			
+{
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	struct rtllib_crypt_data *crypt;
+	int idx, max_key_len;
+
+	max_key_len = encoding->length - sizeof(*ext);
+	if (max_key_len < 0)
+		return -EINVAL;
+
+	idx = encoding->flags & IW_ENCODE_INDEX;
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else{
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			idx = ieee->mesh_txkeyidx;
+		else
+#endif			
+			idx = ieee->tx_keyidx;
+	}
+	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
+	    (ext->alg != IW_ENCODE_ALG_WEP))
+#ifdef _RTL8192_EXT_PATCH_
+		if (idx != 0 || !((ieee->iw_mode == IW_MODE_INFRA) || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))))
+#else
+		if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA)) 
+#endif			
+			return -EINVAL;
+		
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		crypt = ieee->cryptlist[0]->crypt[idx];
+	else
+		crypt = ieee->sta_crypt[idx];
+#else
+	crypt = ieee->crypt[idx];
+#endif
+
+	encoding->flags = idx + 1;
+	memset(ext, 0, sizeof(*ext));
+
+	if (crypt == NULL || crypt->ops == NULL ) {
+		ext->alg = IW_ENCODE_ALG_NONE;
+		ext->key_len = 0;
+		encoding->flags |= IW_ENCODE_DISABLED;
+	} else {
+		if (strcmp(crypt->ops->name, "WEP") == 0 )
+			ext->alg = IW_ENCODE_ALG_WEP;
+		else if (strcmp(crypt->ops->name, "TKIP"))
+			ext->alg = IW_ENCODE_ALG_TKIP;
+		else if (strcmp(crypt->ops->name, "CCMP"))
+			ext->alg = IW_ENCODE_ALG_CCMP;
+		else
+			return -EINVAL;
+		ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
+		encoding->flags |= IW_ENCODE_ENABLED;
+		if (ext->key_len &&
+		    (ext->alg == IW_ENCODE_ALG_TKIP ||
+		     ext->alg == IW_ENCODE_ALG_CCMP))
+			ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+	}
+
+	return 0;
+}
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_mesh_set_encode_ext(struct rtllib_device *ieee,
+                               struct iw_point *encoding, struct iw_encode_ext *ext, int entry)
+{
+	int ret = 0;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	struct net_device *dev = ieee->dev;
+	int i, idx;
+	int group_key = 0;
+	const char *alg, *module;
+	struct rtllib_crypto_ops *ops;
+	struct rtllib_crypt_data **crypt;
+
+	struct rtllib_security sec = {
+	        .flags = 0,
+	};
+	idx = encoding->flags & IW_ENCODE_INDEX;
+
+	if (idx) {
+		if (idx < 1 || idx > WEP_KEYS)
+			return -EINVAL;
+		idx--;
+	} else
+		idx = ieee->tx_keyidx;
+
+
+	if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+		crypt = &ieee->cryptlist[0]->crypt[idx];
+		group_key = 1;
+	} else {
+		/* some Cisco APs use idx>0 for unicast in dynamic WEP */
+		if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
+			return -EINVAL;
+		if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->mesh_started==1))
+		{
+			crypt = &ieee->cryptlist[entry]->crypt[idx];
+#if 0  
+			if(*crypt == NULL )
+				printk("%s: ERR! &ieee->cryptlist[%d]->crypt[%d] is  NULL.\n",__func__, entry,idx);
+#endif			
+		}
+		else
+			return -EINVAL;
+	}
+
+	sec.flags |= SEC_ENABLED;
+	if ((encoding->flags & IW_ENCODE_DISABLED) ||
+		ext->alg == IW_ENCODE_ALG_NONE) {
+		if (*crypt){
+			printk("=====>%s():DISABLE crypt is not NULL\n",__FUNCTION__);
+		 	rtllib_crypt_delayed_deinit(ieee, crypt);
+		}
+#ifdef _RTL8192_EXT_PATCH_
+		if(1)
+		{
+			int j;
+			for (j=1; j<MAX_MP; j++)
+			{
+				struct rtllib_crypt_data ** crypttmp =  &ieee->cryptlist[j]->crypt[idx];
+				if (*crypttmp == NULL)
+					continue;
+				printk("======>crypt is not NULL\n");
+				rtllib_crypt_delayed_deinit(ieee, crypttmp);
+			}
+		}
+#endif
+
+		for (i = 0; i < WEP_KEYS; i++){
+			if (ieee->cryptlist[0]->crypt[i] != NULL)
+				break;
+		}
+		if (i == WEP_KEYS) {
+			sec.enabled = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_LEVEL;
+		}
+		goto done;
+	}
+	
+	sec.enabled = 1;
+#if 0
+	if (group_key ? !ieee->host_mc_decrypt :
+		!(ieee->host_encrypt || ieee->host_decrypt ||
+		ieee->host_encrypt_msdu))
+		goto skip_host_crypt;
+#endif
+	switch (ext->alg) {
+		case IW_ENCODE_ALG_WEP:
+			alg = "WEP";
+			module = "rtllib_crypt_wep";
+			break;
+		case IW_ENCODE_ALG_TKIP:
+			alg = "TKIP";
+			module = "rtllib_crypt_tkip";
+			break;
+		case IW_ENCODE_ALG_CCMP:
+			alg = "CCMP";
+			module = "rtllib_crypt_ccmp";
+			break;
+		default:
+			RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
+			                   dev->name, ext->alg);
+			ret = -EINVAL;
+			goto done;
+	}
+	printk("%s: alg name:%s\n",__FUNCTION__, alg);
+
+	ops = rtllib_get_crypto_ops(alg);
+	if (ops == NULL) {
+		request_module("%s",module);
+		ops = rtllib_get_crypto_ops(alg);
+	}
+	if (ops == NULL) {
+		RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
+		               dev->name, ext->alg);
+		printk("========>unknown crypto alg %d\n", ext->alg);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	if (*crypt == NULL || (*crypt)->ops != ops) {
+
+		struct rtllib_crypt_data *new_crypt;
+
+		rtllib_crypt_delayed_deinit(ieee, crypt);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
+#else
+		new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+		memset(new_crypt,0,sizeof(*new_crypt));
+#endif
+		if (new_crypt == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+		new_crypt->ops = ops;
+#ifdef BUILT_IN_RTLLIB
+		if (new_crypt->ops)
+#else
+		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+#endif
+		{
+			new_crypt->priv = new_crypt->ops->init(idx);
+		}
+		if (new_crypt->priv == NULL) {
+			kfree(new_crypt);
+			ret = -EINVAL;
+			goto done;
+		}
+		*crypt = new_crypt;
+	}
+
+	printk("%s: key_len %x \n",__FUNCTION__, ext->key_len);
+
+	if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+		(*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+                                   (*crypt)->priv) < 0) {
+		RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name);
+		printk("key setting failed\n");
+		ret = -EINVAL;
+		goto done;
+	}
+#if 1	
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+		ieee->mesh_txkeyidx = idx;
+		sec.active_key = idx;
+		sec.flags |= SEC_ACTIVE_KEY;
+	}
+
+	if (ext->alg != IW_ENCODE_ALG_NONE) {
+		sec.key_sizes[idx] = ext->key_len;
+		sec.flags |= (1 << idx);
+		if (ext->alg == IW_ENCODE_ALG_WEP) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_1;
+		} else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_2;
+		} else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_3;
+		}
+		/* Don't set sec level for group keys. */
+		if (group_key)
+			sec.flags &= ~SEC_LEVEL;
+	}
+#endif
+done:
+	if (ieee->set_security)
+		ieee->set_security(ieee->dev, &sec);
+
+	if (ieee->reset_on_keychange &&
+		ieee->iw_mode != IW_MODE_INFRA &&
+		ieee->reset_port && ieee->reset_port(dev)) {
+		RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
+		return -EINVAL;
+	}
+#endif
+	return ret;
+}
+#endif
+
+int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	u8 i = 0;
+	bool deauth = false;
+	struct iw_mlme *mlme = (struct iw_mlme *) extra;
+
+	if (ieee->state != RTLLIB_LINKED)
+		return -ENOLINK;
+	
+	down(&ieee->wx_sem);
+	
+	switch (mlme->cmd) {
+		case IW_MLME_DEAUTH:
+			deauth = true;
+			/* leave break out intentionly */
+
+		case IW_MLME_DISASSOC:
+#ifdef _RTL8192_EXT_PATCH_
+			if(!((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 1)))
+			{
+#endif
+				if(deauth == true) {
+					printk("disauth packet !\n");
+				} else {
+					printk("dis associate packet!\n");
+				}
+
+				ieee->cannot_notify = true;
+
+				SendDisassociation(ieee,deauth,mlme->reason_code);
+				rtllib_disassociate(ieee);
+
+				ieee->wap_set = 0;
+				for(i=0;i<6;i++)  ieee->current_network.bssid[i]= 0x55;
+
+				ieee->ssid_set = 0;
+				ieee->current_network.ssid[0] = '\0';
+				ieee->current_network.ssid_len = 0;
+#ifdef _RTL8192_EXT_PATCH_
+			}
+#endif
+			break;
+		default:
+			up(&ieee->wx_sem);
+			return -EOPNOTSUPP;
+	}
+
+	up(&ieee->wx_sem);
+	
+#endif		
+	return 0;
+}
+
+int rtllib_wx_set_auth(struct rtllib_device *ieee,
+                               struct iw_request_info *info,
+                               struct iw_param *data, char *extra)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	switch (data->flags & IW_AUTH_INDEX) {
+        case IW_AUTH_WPA_VERSION:
+		break;
+        case IW_AUTH_CIPHER_PAIRWISE:
+        case IW_AUTH_CIPHER_GROUP:
+        case IW_AUTH_KEY_MGMT:
+		/*
+		 * Host AP driver does not use these parameters and allows
+		 * wpa_supplicant to control them internally.
+		 */
+                break;
+        case IW_AUTH_TKIP_COUNTERMEASURES:
+                ieee->tkip_countermeasures = data->value;
+                break;
+        case IW_AUTH_DROP_UNENCRYPTED:
+                ieee->drop_unencrypted = data->value;
+		break;
+
+	case IW_AUTH_80211_AUTH_ALG:
+		if(data->value & IW_AUTH_ALG_SHARED_KEY){
+			ieee->open_wep = 0;
+			ieee->auth_mode = 1;
+		}
+		else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
+			ieee->open_wep = 1;
+			ieee->auth_mode = 0;
+		}
+		else if(data->value & IW_AUTH_ALG_LEAP){
+			ieee->open_wep = 1;
+			ieee->auth_mode = 2;
+		}
+		else
+			return -EINVAL;
+		break;
+
+#if 1
+	case IW_AUTH_WPA_ENABLED:
+		ieee->wpa_enabled = (data->value)?1:0;
+		break;
+
+#endif
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+                ieee->ieee802_1x = data->value;
+		break;
+	case IW_AUTH_PRIVACY_INVOKED:
+		ieee->privacy_invoked = data->value;
+		break;
+	default:
+                return -EOPNOTSUPP;
+	}	
+#endif
+	return 0;
+}
+#endif
+
+int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
+{
+#if (WIRELESS_EXT >= 18 )
+	u8 *buf;
+	u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
+	
+	if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) {
+		return -EINVAL;
+	}
+
+	if (len) {
+		eid = ie[0];
+		if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2], wps_oui, 4))) {
+
+			ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len):(MAX_WZC_IE_LEN);
+			buf = kmalloc(ieee->wps_ie_len, GFP_KERNEL);
+			if (buf == NULL)
+				return -ENOMEM;
+			memcpy(buf, ie, ieee->wps_ie_len);
+			ieee->wps_ie = buf;				
+			return 0;
+		}			
+	}
+	ieee->wps_ie_len = 0;	
+	if (ieee->wps_ie)
+		kfree(ieee->wps_ie);
+	ieee->wps_ie = NULL;		
+	if (len) {
+		if (len != ie[1]+2) {
+			return -EINVAL;
+		}
+		buf = kmalloc(len, GFP_KERNEL);
+		if (buf == NULL)
+			return -ENOMEM;
+		memcpy(buf, ie, len);
+		kfree(ieee->wpa_ie);
+		ieee->wpa_ie = buf;
+		ieee->wpa_ie_len = len;	
+	} else {
+		if (ieee->wpa_ie)
+		kfree(ieee->wpa_ie);
+		ieee->wpa_ie = NULL;
+		ieee->wpa_ie_len = 0;
+	}
+#endif
+	return 0;
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_wx_set_gen_ie);
+#if (WIRELESS_EXT >= 18)
+EXPORT_SYMBOL_RSL(rtllib_wx_set_mlme);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_auth);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_encode_ext);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_encode_ext);
+#endif
+EXPORT_SYMBOL_RSL(rtllib_wx_get_scan);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_encode);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_encode);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(rtllib_mesh_set_encode_ext);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_BAProc.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_BAProc.c
@@ -0,0 +1,669 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtllib.h"
+#include "rtl819x_BA.h"
+#ifdef RTK_DMP_PLATFORM
+#include <linux/usb_setting.h> 
+#endif
+
+void ActivateBAEntry(struct rtllib_device* ieee, PBA_RECORD pBA, u16 Time)
+{
+	pBA->bValid = true;
+	if(Time != 0)
+		mod_timer(&pBA->Timer, jiffies + MSECS(Time));
+}
+
+void DeActivateBAEntry( struct rtllib_device* ieee, PBA_RECORD pBA)
+{
+	pBA->bValid = false;
+	del_timer_sync(&pBA->Timer);
+}
+u8 TxTsDeleteBA( struct rtllib_device* ieee, PTX_TS_RECORD	pTxTs)
+{
+	PBA_RECORD		pAdmittedBa = &pTxTs->TxAdmittedBARecord;  
+	PBA_RECORD		pPendingBa = &pTxTs->TxPendingBARecord;
+	u8			bSendDELBA = false;
+
+	if(pPendingBa->bValid)
+	{
+		DeActivateBAEntry(ieee, pPendingBa);
+		bSendDELBA = true;
+	}
+
+	if(pAdmittedBa->bValid)
+	{
+		DeActivateBAEntry(ieee, pAdmittedBa);
+		bSendDELBA = true;
+	}
+
+	return bSendDELBA;
+}
+
+u8 RxTsDeleteBA( struct rtllib_device* ieee, PRX_TS_RECORD	pRxTs)
+{
+	PBA_RECORD		pBa = &pRxTs->RxAdmittedBARecord;
+	u8			bSendDELBA = false;
+
+	if(pBa->bValid)
+	{
+		DeActivateBAEntry(ieee, pBa);
+		bSendDELBA = true;
+	}
+
+	return bSendDELBA;
+}
+
+void ResetBaEntry( PBA_RECORD pBA)
+{
+	pBA->bValid			= false;
+	pBA->BaParamSet.shortData	= 0;
+	pBA->BaTimeoutValue		= 0;
+	pBA->DialogToken		= 0;
+	pBA->BaStartSeqCtrl.ShortData	= 0;
+}
+static struct sk_buff* rtllib_ADDBA(struct rtllib_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
+{
+	struct sk_buff *skb = NULL;
+	 struct rtllib_hdr_3addr* BAReq = NULL;
+	u8* tag = NULL;
+	u16 tmp = 0;
+	u16 len = ieee->tx_headroom + 9;
+	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+	if (pBA == NULL||ieee == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
+		return NULL;
+	}
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr) + USB_512B_ALIGNMENT_SIZE); 
+#else
+	skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); 
+#endif
+	if (skb == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
+		return NULL;
+	}
+
+	memset(skb->data, 0, sizeof( struct rtllib_hdr_3addr));  	
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+
+	skb_reserve(skb, ieee->tx_headroom);
+
+	BAReq = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr));
+
+	memcpy(BAReq->addr1, Dst, ETH_ALEN);
+	memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
+
+#ifdef _RTL8192_EXT_PATCH_ 
+	if((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0) && ieee->ext_patch_rtllib_is_mesh && ieee->ext_patch_rtllib_is_mesh(ieee, Dst)){
+#ifdef COMPATIBLE_WITH_RALINK_MESH		
+		memcpy(BAReq->addr3, Dst, ETH_ALEN);
+#else
+		memcpy(BAReq->addr3, ieee->current_mesh_network.bssid, ETH_ALEN);
+#endif		
+	}
+	else
+		memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
+#else	
+	memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
+#endif
+	BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); 
+
+	tag = (u8*)skb_put(skb, 9);
+	*tag ++= ACT_CAT_BA;  
+	*tag ++= type;
+	*tag ++= pBA->DialogToken;
+
+	if (ACT_ADDBARSP == type)
+	{
+		printk("====>to send ADDBARSP\n");
+		tmp = cpu_to_le16(StatusCode);
+		memcpy(tag, (u8*)&tmp, 2);
+		tag += 2;	
+	}
+	tmp = cpu_to_le16(pBA->BaParamSet.shortData);
+	memcpy(tag, (u8*)&tmp, 2);
+	tag += 2;
+	tmp = cpu_to_le16(pBA->BaTimeoutValue);
+	memcpy(tag, (u8*)&tmp, 2);
+	tag += 2;
+	
+	if (ACT_ADDBAREQ == type)
+	{
+		memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
+		tag += 2;
+	}
+	
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+	return skb;
+}
+
+static struct sk_buff* rtllib_DELBA(
+	struct rtllib_device* ieee,
+	u8*		         dst,
+	PBA_RECORD		 pBA,
+	TR_SELECT		 TxRxSelect,
+	u16			 ReasonCode
+	)
+{
+	DELBA_PARAM_SET	DelbaParamSet;
+	struct sk_buff *skb = NULL;
+	 struct rtllib_hdr_3addr* Delba = NULL;
+	u8* tag = NULL;
+	u16 tmp = 0;
+	u16 len = 6 + ieee->tx_headroom;	
+
+	if (net_ratelimit())
+	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+
+	memset(&DelbaParamSet, 0, 2);
+
+	DelbaParamSet.field.Initiator	= (TxRxSelect==TX_DIR)?1:0;
+	DelbaParamSet.field.TID	= pBA->BaParamSet.field.TID;
+	
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+	skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr) + USB_512B_ALIGNMENT_SIZE); 
+#else	
+	skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); 
+#endif
+	if (skb == NULL)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
+		return NULL;
+	}
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	Delba = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr));
+
+	memcpy(Delba->addr1, dst, ETH_ALEN);
+	memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
+#ifdef _RTL8192_EXT_PATCH_ 
+	if((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0) && ieee->ext_patch_rtllib_is_mesh && ieee->ext_patch_rtllib_is_mesh(ieee, dst)){
+#ifdef COMPATIBLE_WITH_RALINK_MESH		
+		memcpy(Delba->addr3, dst, ETH_ALEN);
+#else
+		memcpy(Delba->addr3, ieee->current_mesh_network.bssid, ETH_ALEN);
+#endif		
+	}
+	else
+		memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
+#else	
+	memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
+#endif
+	Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); 
+	
+	tag = (u8*)skb_put(skb, 6);	
+
+	*tag ++= ACT_CAT_BA;  
+	*tag ++= ACT_DELBA;
+
+	tmp = cpu_to_le16(DelbaParamSet.shortData);
+	memcpy(tag, (u8*)&tmp, 2);
+	tag += 2;
+	tmp = cpu_to_le16(ReasonCode);
+	memcpy(tag, (u8*)&tmp, 2);
+	tag += 2;
+
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+	if (net_ratelimit())
+	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n", __FUNCTION__);
+	return skb;
+}
+
+void rtllib_send_ADDBAReq(struct rtllib_device* ieee, u8*	dst, PBA_RECORD	pBA)
+{
+	struct sk_buff *skb = NULL;
+	skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); 
+
+	if (skb)
+	{
+		printk("====>to send ADDBAREQ!!!!!\n");
+		softmac_mgmt_xmit(skb, ieee);
+	}
+	else
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
+	}
+	return;
+}
+
+void rtllib_send_ADDBARsp(struct rtllib_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode) 
+{
+	struct sk_buff *skb = NULL;
+	skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); 
+	if (skb)
+	{
+		softmac_mgmt_xmit(skb, ieee);
+	}
+	else
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
+	}
+
+	return;
+
+}
+
+void rtllib_send_DELBA(struct rtllib_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
+{
+	struct sk_buff *skb = NULL;
+	skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); 
+	if (skb)
+	{
+		softmac_mgmt_xmit(skb, ieee);
+	}
+	else
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
+	}
+	return ;
+}
+
+int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb)
+{
+	 struct rtllib_hdr_3addr* req = NULL;
+	u16 rc = 0;
+	u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
+	PBA_RECORD pBA = NULL;
+	PBA_PARAM_SET	pBaParamSet = NULL;
+	u16* pBaTimeoutVal = NULL;
+	PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
+	PRX_TS_RECORD	pTS = NULL;	
+
+	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n",(int)skb->len, 	(int)(sizeof( struct rtllib_hdr_3addr) + 9));
+		return -1;
+	}
+
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+	
+	req = ( struct rtllib_hdr_3addr*) skb->data;
+	tag = (u8*)req;
+	dst = (u8*)(&req->addr2[0]);
+	tag += sizeof( struct rtllib_hdr_3addr);
+	pDialogToken = tag + 2;  
+	pBaParamSet = (PBA_PARAM_SET)(tag + 3);   
+	pBaTimeoutVal = (u16*)(tag + 5); 
+	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
+	
+	printk("====>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));	
+	if(
+#ifdef _RTL8192_EXT_PATCH_
+		(ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) ||
+#else
+		ieee->current_network.qos_data.active == 0  ||
+#endif	
+		(ieee->pHTInfo->bCurrentHTSupport == false) ||
+		(ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) 
+	{
+		rc = ADDBA_STATUS_REFUSED;
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
+		goto OnADDBAReq_Fail;
+	}
+	if(	!GetTs(
+			ieee, 
+			(PTS_COMMON_INFO*)(&pTS), 
+			dst, 
+			(u8)(pBaParamSet->field.TID), 
+			RX_DIR,
+			true)	)
+	{
+		rc = ADDBA_STATUS_REFUSED;
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
+		goto OnADDBAReq_Fail;
+	}
+	pBA = &pTS->RxAdmittedBARecord;
+
+	if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
+	{
+		rc = ADDBA_STATUS_INVALID_PARAM;
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
+		goto OnADDBAReq_Fail;
+	}
+
+
+	rtllib_FlushRxTsPendingPkts(ieee, pTS);
+	
+	DeActivateBAEntry(ieee, pBA);	
+	pBA->DialogToken = *pDialogToken;
+	pBA->BaParamSet = *pBaParamSet;
+	pBA->BaTimeoutValue = *pBaTimeoutVal;
+	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
+	
+	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)||
+	(ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
+	pBA->BaParamSet.field.BufferSize = 1;
+	else
+	pBA->BaParamSet.field.BufferSize = 32;
+	
+	ActivateBAEntry(ieee, pBA, 0);
+	rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
+
+	return 0;
+	
+OnADDBAReq_Fail:
+	{
+		BA_RECORD	BA;
+		BA.BaParamSet = *pBaParamSet;
+		BA.BaTimeoutValue = *pBaTimeoutVal;
+		BA.DialogToken = *pDialogToken;
+		BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
+		rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
+		return 0; 
+	}
+
+}
+
+int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb)
+{
+	 struct rtllib_hdr_3addr* rsp = NULL;
+	PBA_RECORD		pPendingBA, pAdmittedBA;
+	PTX_TS_RECORD		pTS = NULL;
+	u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
+	u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
+	PBA_PARAM_SET		pBaParamSet = NULL;
+	u16			ReasonCode;
+
+	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", (int)skb->len, 	(int)(sizeof( struct rtllib_hdr_3addr) + 9));
+		return -1;
+	}
+	rsp = ( struct rtllib_hdr_3addr*)skb->data;
+	tag = (u8*)rsp;
+	dst = (u8*)(&rsp->addr2[0]);
+	tag += sizeof( struct rtllib_hdr_3addr);
+	pDialogToken = tag + 2;
+	pStatusCode = (u16*)(tag + 3);
+	pBaParamSet = (PBA_PARAM_SET)(tag + 5);
+	pBaTimeoutVal = (u16*)(tag + 7);
+
+	printk("====>rx ADDBARSP from :"MAC_FMT"\n", MAC_ARG(dst));	
+	if(     
+#ifdef _RTL8192_EXT_PATCH_
+		(ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) ||
+#else
+		ieee->current_network.qos_data.active == 0  ||
+#endif	
+		ieee->pHTInfo->bCurrentHTSupport == false ||
+		ieee->pHTInfo->bCurrentAMPDUEnable == false )
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
+		ReasonCode = DELBA_REASON_UNKNOWN_BA;
+		goto OnADDBARsp_Reject;
+	}
+
+	
+	if (!GetTs(
+			ieee, 
+			(PTS_COMMON_INFO*)(&pTS), 
+			dst, 
+			(u8)(pBaParamSet->field.TID), 
+			TX_DIR,
+			false)	)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
+		ReasonCode = DELBA_REASON_UNKNOWN_BA;
+		goto OnADDBARsp_Reject;
+	}
+	
+	pTS->bAddBaReqInProgress = false;
+	pPendingBA = &pTS->TxPendingBARecord;
+	pAdmittedBA = &pTS->TxAdmittedBARecord;
+
+
+	if((pAdmittedBA->bValid==true))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
+		return -1;
+	}
+	else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
+		ReasonCode = DELBA_REASON_UNKNOWN_BA;
+		goto OnADDBARsp_Reject;
+	}
+	else
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
+		DeActivateBAEntry(ieee, pPendingBA);
+	}
+
+
+	if(*pStatusCode == ADDBA_STATUS_SUCCESS)
+	{
+		if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
+		{
+			pTS->bAddBaReqDelayed = true;
+			DeActivateBAEntry(ieee, pAdmittedBA);
+			ReasonCode = DELBA_REASON_END_BA;
+			goto OnADDBARsp_Reject;
+		}
+
+
+		pAdmittedBA->DialogToken = *pDialogToken;
+		pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
+		pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
+		pAdmittedBA->BaParamSet = *pBaParamSet;
+		DeActivateBAEntry(ieee, pAdmittedBA);
+		ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
+	} else {
+		pTS->bAddBaReqDelayed = true;
+		pTS->bDisable_AddBa = true;
+		ReasonCode = DELBA_REASON_END_BA;
+		goto OnADDBARsp_Reject;
+	}
+
+	return 0;
+
+OnADDBARsp_Reject:
+	{
+		BA_RECORD	BA;
+		BA.BaParamSet = *pBaParamSet;
+		rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
+		return 0;
+	}
+	
+}
+
+int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb)
+{
+	 struct rtllib_hdr_3addr* delba = NULL;
+	PDELBA_PARAM_SET	pDelBaParamSet = NULL;
+	u16*			pReasonCode = NULL;
+	u8*			dst = NULL;
+
+	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 6)
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", (int)skb->len, 	(int)(sizeof( struct rtllib_hdr_3addr) + 6));
+		return -1;
+	}
+	
+	if(
+#ifdef _RTL8192_EXT_PATCH_
+		(ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) ||
+#else
+		ieee->current_network.qos_data.active == 0  ||
+#endif	
+		ieee->pHTInfo->bCurrentHTSupport == false )
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
+		return -1;
+	}
+	
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+	delba = ( struct rtllib_hdr_3addr*)skb->data;
+	dst = (u8*)(&delba->addr2[0]);
+	delba += sizeof( struct rtllib_hdr_3addr);
+	pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
+	pReasonCode = (u16*)(delba+4);
+
+	if(pDelBaParamSet->field.Initiator == 1)
+	{
+		PRX_TS_RECORD 	pRxTs;
+
+		if( !GetTs(
+				ieee, 
+				(PTS_COMMON_INFO*)&pRxTs, 
+				dst, 
+				(u8)pDelBaParamSet->field.TID, 
+				RX_DIR,
+				false)	)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for RXTS in %s().dst:"MAC_FMT" TID:%d\n", __FUNCTION__, MAC_ARG(dst), (u8)pDelBaParamSet->field.TID);
+			return -1;
+		}
+		
+		RxTsDeleteBA(ieee, pRxTs);
+	}
+	else
+	{
+		PTX_TS_RECORD	pTxTs;
+
+		if(!GetTs(
+			ieee, 
+			(PTS_COMMON_INFO*)&pTxTs, 
+			dst, 
+			(u8)pDelBaParamSet->field.TID, 
+			TX_DIR,
+			false)	)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for TXTS in %s()\n", __FUNCTION__);
+			return -1;
+		}
+		
+		pTxTs->bUsingBa = false;
+		pTxTs->bAddBaReqInProgress = false;
+		pTxTs->bAddBaReqDelayed = false;
+		del_timer_sync(&pTxTs->TsAddBaTimer);
+		TxTsDeleteBA(ieee, pTxTs);
+	}
+	return 0;
+}
+
+void
+TsInitAddBA(
+	struct rtllib_device* ieee,
+	PTX_TS_RECORD	pTS,
+	u8		Policy,
+	u8		bOverwritePending
+	)
+{
+	PBA_RECORD			pBA = &pTS->TxPendingBARecord;
+
+	if(pBA->bValid==true && bOverwritePending==false)
+		return;
+
+	DeActivateBAEntry(ieee, pBA);
+	
+	pBA->DialogToken++;						
+	pBA->BaParamSet.field.AMSDU_Support = 0;	
+	pBA->BaParamSet.field.BAPolicy = Policy;	
+	pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;	
+	pBA->BaParamSet.field.BufferSize = 32;		
+	pBA->BaTimeoutValue = 0;					
+	pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; 	
+
+	ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
+
+	rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
+}
+
+void
+TsInitDelBA( struct rtllib_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
+{
+
+	if(TxRxSelect == TX_DIR)
+	{
+		PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
+
+		if(TxTsDeleteBA(ieee, pTxTs))
+			rtllib_send_DELBA(
+				ieee, 
+				pTsCommonInfo->Addr, 
+				(pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), 
+				TxRxSelect, 
+				DELBA_REASON_END_BA);
+	}
+	else if(TxRxSelect == RX_DIR)
+	{
+		PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
+		if(RxTsDeleteBA(ieee, pRxTs))
+			rtllib_send_DELBA(
+				ieee, 
+				pTsCommonInfo->Addr, 
+				&pRxTs->RxAdmittedBARecord, 
+				TxRxSelect, 
+				DELBA_REASON_END_BA	);
+	}
+}
+void BaSetupTimeOut(unsigned long data)
+{
+	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
+
+	pTxTs->bAddBaReqInProgress = false;
+	pTxTs->bAddBaReqDelayed = true;
+	pTxTs->TxPendingBARecord.bValid = false;
+}
+
+void TxBaInactTimeout(unsigned long data)
+{
+	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
+	struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[pTxTs->num]);
+	TxTsDeleteBA(ieee, pTxTs);
+	rtllib_send_DELBA(
+		ieee, 
+		pTxTs->TsCommonInfo.Addr, 
+		&pTxTs->TxAdmittedBARecord,
+		TX_DIR, 
+		DELBA_REASON_TIMEOUT);
+}
+
+void RxBaInactTimeout(unsigned long data)
+{
+	PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)data;
+	struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]);
+	
+	RxTsDeleteBA(ieee, pRxTs);
+	rtllib_send_DELBA(
+		ieee, 
+		pRxTs->TsCommonInfo.Addr, 
+		&pRxTs->RxAdmittedBARecord,
+		RX_DIR, 
+		DELBA_REASON_TIMEOUT);
+	return ;
+}
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_crypt.c
@@ -0,0 +1,268 @@
+/*
+ * Host AP crypto routines
+ *
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.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. See README and COPYING for
+ * more details.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/string.h>
+#include <asm/errno.h>
+
+#include "rtllib.h"
+
+#ifndef BUILT_IN_RTLLIB
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("HostAP crypto");
+MODULE_LICENSE("GPL");
+#endif
+
+struct rtllib_crypto_alg {
+	struct list_head list;
+	struct rtllib_crypto_ops *ops;
+};
+
+
+struct rtllib_crypto {
+	struct list_head algs;
+	spinlock_t lock;
+};
+
+static struct rtllib_crypto *hcrypt;
+
+void rtllib_crypt_deinit_entries(struct rtllib_device *ieee,
+					   int force)
+{
+	struct list_head *ptr, *n;
+	struct rtllib_crypt_data *entry;
+
+	for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
+	     ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
+		entry = list_entry(ptr, struct rtllib_crypt_data, list);
+
+		if (atomic_read(&entry->refcnt) != 0 && !force)
+			continue;
+
+		list_del(ptr);
+
+		if (entry->ops) {
+			entry->ops->deinit(entry->priv);
+#ifndef BUILT_IN_RTLLIB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		
+			module_put(entry->ops->owner);
+#else
+			__MOD_DEC_USE_COUNT(entry->ops->owner);	
+#endif			
+#endif
+		}
+		kfree(entry);
+	}
+}
+
+void rtllib_crypt_deinit_handler(unsigned long data)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	rtllib_crypt_deinit_entries(ieee, 0);
+	if (!list_empty(&ieee->crypt_deinit_list)) {
+		printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
+		       "deletion list\n", ieee->dev->name);
+		ieee->crypt_deinit_timer.expires = jiffies + HZ;
+		add_timer(&ieee->crypt_deinit_timer);
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+
+}
+
+void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
+				    struct rtllib_crypt_data **crypt)
+{
+	struct rtllib_crypt_data *tmp;
+	unsigned long flags;
+
+	if (*crypt == NULL)
+		return;
+
+	tmp = *crypt;
+	*crypt = NULL;
+
+	/* must not run ops->deinit() while there may be pending encrypt or
+	 * decrypt operations. Use a list of delayed deinits to avoid needing
+	 * locking. */
+
+	spin_lock_irqsave(&ieee->lock, flags);
+	list_add(&tmp->list, &ieee->crypt_deinit_list);
+	if (!timer_pending(&ieee->crypt_deinit_timer)) {
+		ieee->crypt_deinit_timer.expires = jiffies + HZ;
+		add_timer(&ieee->crypt_deinit_timer);
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops)
+{
+	unsigned long flags;
+	struct rtllib_crypto_alg *alg;
+
+	if (hcrypt == NULL)
+		return -1;
+
+	alg = kmalloc(sizeof(*alg), GFP_KERNEL);
+	if (alg == NULL)
+		return -ENOMEM;
+
+	memset(alg, 0, sizeof(*alg));
+	alg->ops = ops;
+
+	spin_lock_irqsave(&hcrypt->lock, flags);
+	list_add(&alg->list, &hcrypt->algs);
+	spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+	printk(KERN_DEBUG "rtllib_crypt: registered algorithm '%s'\n",
+	       ops->name);
+
+	return 0;
+}
+
+int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops)
+{
+	unsigned long flags;
+	struct list_head *ptr;
+	struct rtllib_crypto_alg *del_alg = NULL;
+
+	if (hcrypt == NULL)
+		return -1;
+
+	spin_lock_irqsave(&hcrypt->lock, flags);
+	for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+		struct rtllib_crypto_alg *alg =
+			(struct rtllib_crypto_alg *) ptr;
+		if (alg->ops == ops) {
+			list_del(&alg->list);
+			del_alg = alg;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+	if (del_alg) {
+		printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
+		       "'%s'\n", ops->name);
+		kfree(del_alg);
+	}
+
+	return del_alg ? 0 : -1;
+}
+
+
+struct rtllib_crypto_ops * rtllib_get_crypto_ops(const char *name)
+{
+	unsigned long flags;
+	struct list_head *ptr;
+	struct rtllib_crypto_alg *found_alg = NULL;
+
+	if (hcrypt == NULL)
+		return NULL;
+
+	spin_lock_irqsave(&hcrypt->lock, flags);
+	for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+		struct rtllib_crypto_alg *alg =
+			(struct rtllib_crypto_alg *) ptr;
+		if (strcmp(alg->ops->name, name) == 0) {
+			found_alg = alg;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+	if (found_alg)
+		return found_alg->ops;
+	else
+		return NULL;
+}
+
+
+static void * rtllib_crypt_null_init(int keyidx) { return (void *) 1; }
+static void rtllib_crypt_null_deinit(void *priv) {}
+
+static struct rtllib_crypto_ops rtllib_crypt_null = {
+	.name			= "NULL",
+	.init			= rtllib_crypt_null_init,
+	.deinit			= rtllib_crypt_null_deinit,
+	.encrypt_mpdu		= NULL,
+	.decrypt_mpdu		= NULL,
+	.encrypt_msdu		= NULL,
+	.decrypt_msdu		= NULL,
+	.set_key		= NULL,
+	.get_key		= NULL,
+	.extra_prefix_len	= 0,
+	.extra_postfix_len	= 0,
+	.owner			= THIS_MODULE,
+};
+
+
+int __init rtllib_crypto_init(void)
+{
+	int ret = -ENOMEM;
+
+	hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
+	if (!hcrypt)
+		goto out;
+
+	memset(hcrypt, 0, sizeof(*hcrypt));
+	INIT_LIST_HEAD(&hcrypt->algs);
+	spin_lock_init(&hcrypt->lock);
+
+	ret = rtllib_register_crypto_ops(&rtllib_crypt_null);
+	if (ret < 0) {
+		kfree(hcrypt);
+		hcrypt = NULL;
+	}
+out:
+	return ret;
+}
+
+
+void __exit rtllib_crypto_deinit(void)
+{
+	struct list_head *ptr, *n;
+
+	if (hcrypt == NULL)
+		return;
+
+	for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
+	     ptr = n, n = ptr->next) {
+		struct rtllib_crypto_alg *alg =
+			(struct rtllib_crypto_alg *) ptr;
+		list_del(ptr);
+		printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
+		       "'%s' (deinit)\n", alg->ops->name);
+		kfree(alg);
+	}
+
+	kfree(hcrypt);
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_entries);
+EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_handler);
+EXPORT_SYMBOL_RSL(rtllib_crypt_delayed_deinit);
+
+EXPORT_SYMBOL_RSL(rtllib_register_crypto_ops);
+EXPORT_SYMBOL_RSL(rtllib_unregister_crypto_ops);
+EXPORT_SYMBOL_RSL(rtllib_get_crypto_ops);
+
+module_init(rtllib_crypto_init);
+module_exit(rtllib_crypto_deinit);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_Qos.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_Qos.h
@@ -0,0 +1,619 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_QOS_TYPE_H
+#define __INC_QOS_TYPE_H
+
+#define BIT0                    0x00000001
+#define BIT1                    0x00000002
+#define BIT2                    0x00000004
+#define BIT3                    0x00000008
+#define BIT4                    0x00000010
+#define BIT5                    0x00000020
+#define BIT6                    0x00000040
+#define BIT7                    0x00000080
+#define BIT8                    0x00000100
+#define BIT9                    0x00000200
+#define BIT10                   0x00000400
+#define BIT11                   0x00000800
+#define BIT12                   0x00001000
+#define BIT13                   0x00002000
+#define BIT14                   0x00004000
+#define BIT15                   0x00008000
+#define BIT16                   0x00010000
+#define BIT17                   0x00020000
+#define BIT18                   0x00040000
+#define BIT19                   0x00080000
+#define BIT20                   0x00100000
+#define BIT21                   0x00200000
+#define BIT22                   0x00400000
+#define BIT23                   0x00800000
+#define BIT24                   0x01000000
+#define BIT25                   0x02000000
+#define BIT26                   0x04000000
+#define BIT27                   0x08000000
+#define BIT28                   0x10000000
+#define BIT29                   0x20000000
+#define BIT30                   0x40000000
+#define BIT31                   0x80000000
+
+#define	MAX_WMMELE_LENGTH	64
+
+typedef u32 QOS_MODE, *PQOS_MODE;
+#define QOS_DISABLE		0
+#define QOS_WMM			1
+#define QOS_WMMSA		2
+#define QOS_EDCA		4
+#define QOS_HCCA		8
+#define QOS_WMM_UAPSD		16   
+
+#define AC_PARAM_SIZE	4
+#define WMM_PARAM_ELE_BODY_LEN	18
+
+typedef	enum _ACK_POLICY{
+	eAckPlc0_ACK		= 0x00,
+	eAckPlc1_NoACK		= 0x01,
+}ACK_POLICY,*PACK_POLICY;
+
+#define WMM_PARAM_ELEMENT_SIZE	(8+(4*AC_PARAM_SIZE))
+#if 0
+#define GET_QOS_CTRL(_pStart)	ReadEF2Byte((u8 *)(_pStart) + 24)
+#define SET_QOS_CTRL(_pStart, _value)	WriteEF2Byte((u8 *)(_pStart) + 24, _value)
+
+#define GET_QOS_CTRL_WMM_UP(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 3))
+#define SET_QOS_CTRL_WMM_UP(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 3, (u8)(_value))
+
+#define GET_QOS_CTRL_WMM_EOSP(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
+#define SET_QOS_CTRL_WMM_EOSP(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
+
+#define GET_QOS_CTRL_WMM_ACK_POLICY(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
+#define SET_QOS_CTRL_WMM_ACK_POLICY(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
+
+#define GET_QOS_CTRL_STA_DATA_TID(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
+#define SET_QOS_CTRL_STA_DATA_TID(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
+
+#define GET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
+#define SET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
+
+#define GET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
+#define SET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
+
+#define GET_QOS_CTRL_STA_DATA_TXOP(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
+#define SET_QOS_CTRL_STA_DATA_TXOP(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
+
+#define GET_QOS_CTRL_STA_DATA_QSIZE(_pStart)	GET_QOS_CTRL_STA_DATA_TXOP(_pStart)
+#define SET_QOS_CTRL_STA_DATA_QSIZE(_pStart, _value)	SET_QOS_CTRL_STA_DATA_TXOP(_pStart)
+
+#define GET_QOS_CTRL_HC_DATA_TID(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
+#define SET_QOS_CTRL_HC_DATA_TID(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_DATA_EOSP(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
+#define SET_QOS_CTRL_HC_DATA_EOSP(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
+#define SET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
+#define SET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_CFP_TID(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 0, 4))
+#define SET_QOS_CTRL_HC_CFP_TID(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 0, 4, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_CFP_EOSP(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 4, 1))
+#define SET_QOS_CTRL_HC_CFP_EOSP(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 4, 1, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 5, 2))
+#define SET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 5, 2, (u8)(_value))
+
+#define GET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart)	((u8)LE_BITS_TO_2BYTE((u8 *)(_pStart)+24, 8, 8))
+#define SET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart, _value)	SET_BITS_TO_LE_2BYTE((u8 *)(_pStart)+24, 8, 8, (u8)(_value))
+
+#define SET_WMM_QOS_INFO_FIELD(_pStart, _val)	WriteEF1Byte(_pStart, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart)	LE_BITS_TO_1BYTE(_pStart, 0, 4)
+#define SET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 0, 4, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart)	LE_BITS_TO_1BYTE(_pStart, 7, 1)
+#define SET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 7, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart)	LE_BITS_TO_1BYTE(_pStart, 0, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 0, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart)	LE_BITS_TO_1BYTE(_pStart, 1, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 1, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart)	LE_BITS_TO_1BYTE(_pStart, 2, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 2, 1, _val)
+	
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart)	LE_BITS_TO_1BYTE(_pStart, 3, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 3, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart)	LE_BITS_TO_1BYTE(_pStart, 5, 2)
+#define SET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart, _val)	SET_BITS_TO_LE_1BYTE(_pStart, 5, 2, _val)
+		
+
+#define WMM_INFO_ELEMENT_SIZE	7
+
+#define GET_WMM_INFO_ELE_OUI(_pStart)	((u8 *)(_pStart))
+#define SET_WMM_INFO_ELE_OUI(_pStart, _pVal)	PlatformMoveMemory(_pStart, _pVal, 3);
+
+#define GET_WMM_INFO_ELE_OUI_TYPE(_pStart)	( EF1Byte( *((u8 *)(_pStart)+3) ) )
+#define SET_WMM_INFO_ELE_OUI_TYPE(_pStart, _val)	( *((u8 *)(_pStart)+3) = EF1Byte(_val) )
+
+#define GET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart)	( EF1Byte( *((u8 *)(_pStart)+4) ) )
+#define SET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart, _val)	( *((u8 *)(_pStart)+4) = EF1Byte(_val) )
+
+#define GET_WMM_INFO_ELE_VERSION(_pStart)	( EF1Byte( *((u8 *)(_pStart)+5) ) )
+#define SET_WMM_INFO_ELE_VERSION(_pStart, _val)	( *((u8 *)(_pStart)+5) = EF1Byte(_val) )
+
+#define GET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart)	( EF1Byte( *((u8 *)(_pStart)+6) ) )
+#define SET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart, _val)	( *((u8 *)(_pStart)+6) = EF1Byte(_val) )
+
+	
+
+#define GET_WMM_AC_PARAM_AIFSN(_pStart)	( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 4) )
+#define SET_WMM_AC_PARAM_AIFSN(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 0, 4, _val)
+
+#define GET_WMM_AC_PARAM_ACM(_pStart)	( (u8)LE_BITS_TO_4BYTE(_pStart, 4, 1) )
+#define SET_WMM_AC_PARAM_ACM(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 4, 1, _val)
+
+#define GET_WMM_AC_PARAM_ACI(_pStart)		( (u8)LE_BITS_TO_4BYTE(_pStart, 5, 2) )
+#define SET_WMM_AC_PARAM_ACI(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 5, 2, _val)
+
+#define GET_WMM_AC_PARAM_ACI_AIFSN(_pStart)	( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 8) )
+#define SET_WMM_AC_PARAM_ACI_AIFSN(_pStart, _val)	SET_BTIS_TO_LE_4BYTE(_pStart, 0, 8, _val)
+
+#define GET_WMM_AC_PARAM_ECWMIN(_pStart)	( (u8)LE_BITS_TO_4BYTE(_pStart, 8, 4) )
+#define SET_WMM_AC_PARAM_ECWMIN(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 8, 4, _val)
+
+#define GET_WMM_AC_PARAM_ECWMAX(_pStart)	( (u8)LE_BITS_TO_4BYTE(_pStart, 12, 4) )
+#define SET_WMM_AC_PARAM_ECWMAX(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 12, 4, _val)
+
+#define GET_WMM_AC_PARAM_TXOP_LIMIT(_pStart)		( (u16)LE_BITS_TO_4BYTE(_pStart, 16, 16) )
+#define SET_WMM_AC_PARAM_TXOP_LIMIT(_pStart, _val)	SET_BITS_TO_LE_4BYTE(_pStart, 16, 16, _val)
+
+
+
+
+#define GET_WMM_PARAM_ELE_OUI(_pStart)	((u8 *)(_pStart))
+#define SET_WMM_PARAM_ELE_OUI(_pStart, _pVal)	PlatformMoveMemory(_pStart, _pVal, 3)
+
+#define GET_WMM_PARAM_ELE_OUI_TYPE(_pStart)	( EF1Byte( *((u8 *)(_pStart)+3) ) )
+#define SET_WMM_PARAM_ELE_OUI_TYPE(_pStart, _val)	( *((u8 *)(_pStart)+3) = EF1Byte(_val) )
+
+#define GET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart)	( EF1Byte( *((u8 *)(_pStart)+4) ) )
+#define SET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart, _val)	( *((u8 *)(_pStart)+4) = EF1Byte(_val) )
+
+#define GET_WMM_PARAM_ELE_VERSION(_pStart)	( EF1Byte( *((u8 *)(_pStart)+5) ) )
+#define SET_WMM_PARAM_ELE_VERSION(_pStart, _val)	( *((u8 *)(_pStart)+5) = EF1Byte(_val) )
+
+#define GET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart)	( EF1Byte( *((u8 *)(_pStart)+6) ) )
+#define SET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart, _val)	( *((u8 *)(_pStart)+6) = EF1Byte(_val) )
+
+#define GET_WMM_PARAM_ELE_AC_PARAM(_pStart)	( (u8 *)(_pStart)+8 )
+#define SET_WMM_PARAM_ELE_AC_PARAM(_pStart, _pVal) PlatformMoveMemory((_pStart)+8, _pVal, 16)
+#endif
+
+typedef	union _QOS_CTRL_FIELD{
+	u8	charData[2];
+	u16	shortData;
+
+	struct
+	{
+		u8		UP:3;
+		u8		usRsvd1:1;
+		u8		EOSP:1;
+		u8		AckPolicy:2;
+		u8		usRsvd2:1;
+		u8		ucRsvdByte;
+	}WMM;
+
+	struct
+	{
+		u8		TID:4;
+		u8		bIsQsize:1;
+		u8		AckPolicy:2;
+		u8		usRsvd:1;
+		u8		TxopOrQsize;	
+	}BySta;
+
+	struct
+	{
+		u8		TID:4;
+		u8		EOSP:1;
+		u8		AckPolicy:2;
+		u8		usRsvd:1;
+		u8		PSBufState;		
+	}ByHc_Data;
+
+	struct
+	{
+		u8		TID:4;
+		u8		EOSP:1;
+		u8		AckPolicy:2;
+		u8		usRsvd:1;
+		u8		TxopLimit;		
+	}ByHc_CFP;
+
+}QOS_CTRL_FIELD, *PQOS_CTRL_FIELD;
+
+
+typedef	union _QOS_INFO_FIELD{
+	u8	charData;
+	
+	struct
+	{
+		u8		ucParameterSetCount:4;
+		u8		ucReserved:4;	
+	}WMM;
+
+	struct 
+	{
+		u8		ucAC_VO_UAPSD:1;
+		u8		ucAC_VI_UAPSD:1;
+		u8		ucAC_BE_UAPSD:1;
+		u8		ucAC_BK_UAPSD:1;
+		u8		ucReserved1:1;
+		u8		ucMaxSPLen:2;
+		u8		ucReserved2:1;
+		
+	}ByWmmPsSta;
+
+	struct
+	{
+		u8		ucParameterSetCount:4;
+		u8		ucReserved:3; 
+		u8		ucApUapsd:1;
+	}ByWmmPsAp;
+
+	struct
+	{
+		u8		ucAC3_UAPSD:1;
+		u8		ucAC2_UAPSD:1;
+		u8		ucAC1_UAPSD:1;
+		u8		ucAC0_UAPSD:1;
+		u8		ucQAck:1;
+		u8		ucMaxSPLen:2;
+		u8		ucMoreDataAck:1;
+	} By11eSta;
+
+	struct
+	{
+		u8		ucParameterSetCount:4;
+		u8		ucQAck:1;
+		u8		ucQueueReq:1;
+		u8		ucTXOPReq:1;
+		u8		ucReserved:1;
+	} By11eAp;
+
+	struct
+	{
+		u8		ucReserved1:4;
+		u8		ucQAck:1;
+		u8		ucReserved2:2;
+		u8		ucMoreDataAck:1;
+	} ByWmmsaSta;
+
+	struct
+	{
+		u8		ucReserved1:4;
+		u8		ucQAck:1;
+		u8		ucQueueReq:1;
+		u8		ucTXOPReq:1;
+		u8		ucReserved2:1;	
+	} ByWmmsaAp;
+
+	struct
+	{
+		u8		ucAC3_UAPSD:1;
+		u8		ucAC2_UAPSD:1;
+		u8		ucAC1_UAPSD:1;
+		u8		ucAC0_UAPSD:1;
+		u8		ucQAck:1;
+		u8		ucMaxSPLen:2;
+		u8		ucMoreDataAck:1;	
+	} ByAllSta;
+
+	struct
+	{
+		u8		ucParameterSetCount:4;
+		u8		ucQAck:1;
+		u8		ucQueueReq:1;
+		u8		ucTXOPReq:1;
+		u8		ucApUapsd:1;	
+	} ByAllAp;
+
+}QOS_INFO_FIELD, *PQOS_INFO_FIELD;
+
+#if 0
+typedef struct _WMM_INFO_ELEMENT{
+	u8			OUI[3];
+	u8			OUI_Type;
+	u8			OUI_SubType;
+	u8			Version;
+	QOS_INFO_FIELD	QosInfo;
+}WMM_INFO_ELEMENT, *PWMM_INFO_ELEMENT;
+#endif
+
+typedef u32 AC_CODING;
+#define AC0_BE	0		
+#define AC1_BK	1		
+#define AC2_VI	2		
+#define AC3_VO	3		
+#define AC_MAX	4		
+
+typedef	union _ACI_AIFSN{
+	u8	charData;
+	
+	struct
+	{
+		u8	AIFSN:4;
+		u8	ACM:1;
+		u8	ACI:2;
+		u8	Reserved:1;
+	}f;	
+}ACI_AIFSN, *PACI_AIFSN;
+
+typedef	union _ECW{
+	u8	charData;
+	struct
+	{
+		u8	ECWmin:4;
+		u8	ECWmax:4;
+	}f;	
+}ECW, *PECW;
+
+typedef	union _AC_PARAM{
+	u32	longData;
+	u8	charData[4];
+
+	struct
+	{
+		ACI_AIFSN	AciAifsn;
+		ECW		Ecw;
+		u16		TXOPLimit;
+	}f;	
+}AC_PARAM, *PAC_PARAM;
+
+
+
+typedef	enum _QOS_ELE_SUBTYPE{
+	QOSELE_TYPE_INFO	= 0x00,		
+	QOSELE_TYPE_PARAM	= 0x01,		
+}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE;
+
+
+typedef	enum _DIRECTION_VALUE{
+	DIR_UP			= 0,		
+	DIR_DOWN		= 1,		
+	DIR_DIRECT		= 2,		
+	DIR_BI_DIR		= 3,		
+}DIRECTION_VALUE,*PDIRECTION_VALUE;
+
+
+typedef union _QOS_TSINFO{
+	u8		charData[3];
+	struct {
+		u8		ucTrafficType:1;			
+		u8		ucTSID:4;
+		u8		ucDirection:2;
+		u8		ucAccessPolicy:2;	
+		u8		ucAggregation:1;		
+		u8		ucPSB:1;				
+		u8		ucUP:3;
+		u8		ucTSInfoAckPolicy:2;		
+		u8		ucSchedule:1;			
+		u8		ucReserved:7;
+	}field;
+}QOS_TSINFO, *PQOS_TSINFO;
+
+typedef union _TSPEC_BODY{
+	u8		charData[55];
+	
+	struct
+	{
+		QOS_TSINFO	TSInfo;	
+		u16	NominalMSDUsize;
+		u16	MaxMSDUsize;
+		u32	MinServiceItv;
+		u32	MaxServiceItv;
+		u32	InactivityItv;
+		u32	SuspenItv;
+		u32	ServiceStartTime;
+		u32	MinDataRate;
+		u32	MeanDataRate;
+		u32	PeakDataRate;
+		u32	MaxBurstSize;
+		u32	DelayBound;
+		u32	MinPhyRate;
+		u16	SurplusBandwidthAllowance;
+		u16	MediumTime;
+	} f;	
+}TSPEC_BODY, *PTSPEC_BODY;
+
+
+typedef struct _WMM_TSPEC{
+	u8		ID;
+	u8		Length;
+	u8		OUI[3];
+	u8		OUI_Type;
+	u8		OUI_SubType;
+	u8		Version;
+	TSPEC_BODY	Body;
+} WMM_TSPEC, *PWMM_TSPEC;
+
+typedef	enum _ACM_METHOD{
+	eAcmWay0_SwAndHw		= 0,		
+	eAcmWay1_HW			= 1,		
+	eAcmWay2_SW			= 2,		
+}ACM_METHOD,*PACM_METHOD;
+
+
+typedef struct _ACM{
+	u64		UsedTime;
+	u64		MediumTime;
+	u8		HwAcmCtl;	
+}ACM, *PACM;
+
+typedef	u8		AC_UAPSD, *PAC_UAPSD;
+
+#define	GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
+#define	SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
+	
+#define	GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
+#define	SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
+
+#define	GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
+#define	SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
+
+#define	GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
+#define	SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
+	
+
+typedef union _QOS_TCLAS{
+
+	struct _TYPE_GENERAL{
+		u8		Priority;
+		u8 		ClassifierType;
+		u8 		Mask;
+	} TYPE_GENERAL;
+
+	struct _TYPE0_ETH{
+		u8		Priority;
+		u8 		ClassifierType;
+		u8 		Mask;
+		u8		SrcAddr[6];
+		u8		DstAddr[6];
+		u16		Type;
+	} TYPE0_ETH;
+
+	struct _TYPE1_IPV4{
+		u8		Priority;
+		u8 		ClassifierType;
+		u8 		Mask;
+		u8 		Version;
+		u8		SrcIP[4];
+		u8		DstIP[4];
+		u16		SrcPort;
+		u16		DstPort;
+		u8		DSCP;
+		u8		Protocol;
+		u8		Reserved;
+	} TYPE1_IPV4;
+
+	struct _TYPE1_IPV6{
+		u8		Priority;
+		u8 		ClassifierType;
+		u8 		Mask;
+		u8 		Version;
+		u8		SrcIP[16];
+		u8		DstIP[16];
+		u16		SrcPort;
+		u16		DstPort;
+		u8		FlowLabel[3];
+	} TYPE1_IPV6;
+
+	struct _TYPE2_8021Q{
+		u8		Priority;
+		u8 		ClassifierType;
+		u8 		Mask;
+		u16		TagType;
+	} TYPE2_8021Q;
+} QOS_TCLAS, *PQOS_TCLAS;
+
+typedef struct _QOS_TSTREAM{
+	u8			AC;
+	WMM_TSPEC		TSpec;
+	QOS_TCLAS		TClass;
+} QOS_TSTREAM, *PQOS_TSTREAM;
+
+
+
+typedef struct _OCTET_STRING{
+        u8        	*Octet;
+        u16             Length;
+}OCTET_STRING, *POCTET_STRING;
+#if 0
+#define FillOctetString(_os,_octet,_len)             \
+        (_os).Octet=(u8 *)(_octet);                  \
+        (_os).Length=(_len);
+
+#define WMM_ELEM_HDR_LEN        		     6
+#define WMMElemSkipHdr(_osWMMElem)                   \
+        (_osWMMElem).Octet += WMM_ELEM_HDR_LEN;      \
+        (_osWMMElem).Length -= WMM_ELEM_HDR_LEN;
+#endif
+typedef struct _STA_QOS{
+	u8				WMMIEBuf[MAX_WMMELE_LENGTH];
+	u8*				WMMIE;
+
+	QOS_MODE			QosCapability; 
+	QOS_MODE			CurrentQosMode;
+
+	AC_UAPSD			b4ac_Uapsd;  
+	AC_UAPSD			Curr4acUapsd;
+	u8				bInServicePeriod;
+	u8				MaxSPLength;
+	int 				NumBcnBeforeTrigger;
+
+	u8 *				pWMMInfoEle;
+	u8				WMMParamEle[WMM_PARAM_ELEMENT_SIZE];
+	u8				WMMPELength;
+
+	QOS_INFO_FIELD			QosInfoField_STA; 	
+	QOS_INFO_FIELD			QosInfoField_AP;	
+
+	AC_PARAM			CurAcParameters[4];
+
+	ACM				acm[4];
+	ACM_METHOD			AcmMethod;
+
+	QOS_TSTREAM			TStream[16];
+	WMM_TSPEC			TSpec;
+
+	u32				QBssWirelessMode;
+
+	u8				bNoAck;
+
+	u8				bEnableRxImmBA;
+
+}STA_QOS, *PSTA_QOS;
+
+typedef struct _BSS_QOS{
+	QOS_MODE		bdQoSMode;
+
+	u8			bdWMMIEBuf[MAX_WMMELE_LENGTH];
+	u8*		bdWMMIE;
+
+	QOS_ELE_SUBTYPE		EleSubType;
+
+	u8 *			pWMMInfoEle;
+	u8 *			pWMMParamEle;
+	
+	QOS_INFO_FIELD		QosInfoField;
+	AC_PARAM		AcParameter[4];
+}BSS_QOS, *PBSS_QOS;
+
+
+#define sQoSCtlLng			2
+#define	QOS_CTRL_LEN(_QosMode)		((_QosMode > QOS_DISABLE)? sQoSCtlLng : 0)
+
+
+#define IsACValid(ac)			((ac<=7 )?true:false )
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_tx.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_tx.c
@@ -0,0 +1,1631 @@
+/******************************************************************************
+
+  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of version 2 of the GNU General Public License as
+  published by the Free Software Foundation.
+
+  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.
+
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************
+
+  Few modifications for Realtek's Wi-Fi drivers by 
+  Andrea Merello <andreamrl@tiscali.it>
+  
+  A special thanks goes to Realtek for their support ! 
+
+******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <linux/if_vlan.h>
+
+#include "rtllib.h"
+
+#ifdef RTK_DMP_PLATFORM
+#include <linux/usb_setting.h> 
+#endif
+
+/*
+
+
+802.11 Data Frame
+
+
+802.11 frame_contorl for data frames - 2 bytes
+     ,-----------------------------------------------------------------------------------------.
+bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
+     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
+     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
+     |          |           | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
+     '-----------------------------------------------------------------------------------------'
+		                                    /\
+                                                    |
+802.11 Data Frame                                   |
+           ,--------- 'ctrl' expands to >-----------'
+          |
+      ,--'---,-------------------------------------------------------------.
+Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
+      |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
+      |      | tion | (BSSID) |         |         | ence |  data   |      |
+      `--------------------------------------------------|         |------'
+Total: 28 non-data bytes                                 `----.----'
+                                                              |
+       .- 'Frame data' expands to <---------------------------'
+       |
+       V
+      ,---------------------------------------------------.
+Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
+      |------|------|---------|----------|------|---------|
+Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
+      | DSAP | SSAP |         |          |      | Packet  |
+      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
+      `-----------------------------------------|         |
+Total: 8 non-data bytes                         `----.----'
+                                                     |
+       .- 'IP Packet' expands, if WEP enabled, to <--'
+       |
+       V
+      ,-----------------------.
+Bytes |  4  |   0-2296  |  4  |
+      |-----|-----------|-----|
+Desc. | IV  | Encrypted | ICV |
+      |     | IP Packet |     |
+      `-----------------------'
+Total: 8 non-data bytes
+
+
+802.3 Ethernet Data Frame
+
+      ,-----------------------------------------.
+Bytes |   6   |   6   |  2   |  Variable |   4  |
+      |-------|-------|------|-----------|------|
+Desc. | Dest. | Source| Type | IP Packet |  fcs |
+      |  MAC  |  MAC  |      |           |      |
+      `-----------------------------------------'
+Total: 18 non-data bytes
+
+In the event that fragmentation is required, the incoming payload is split into
+N parts of size ieee->fts.  The first fragment contains the SNAP header and the
+remaining packets are just data.
+
+If encryption is enabled, each fragment payload size is reduced by enough space
+to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
+So if you have 1500 bytes of payload with ieee->fts set to 500 without
+encryption it will take 3 frames.  With WEP it will take 4 frames as the
+payload of each frame is reduced to 492 bytes.
+
+* SKB visualization
+*
+*  ,- skb->data
+* |
+* |    ETHERNET HEADER        ,-<-- PAYLOAD
+* |                           |     14 bytes from skb->data
+* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
+* |                       | | |
+* |,-Dest.--. ,--Src.---. | | |
+* |  6 bytes| | 6 bytes | | | |
+* v         | |         | | | |
+* 0         | v       1 | v | v           2
+* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+*     ^     | ^         | ^ |
+*     |     | |         | | |
+*     |     | |         | `T' <---- 2 bytes for Type
+*     |     | |         |
+*     |     | '---SNAP--' <-------- 6 bytes for SNAP
+*     |     |
+*     `-IV--' <-------------------- 4 bytes for IV (WEP)
+*
+*      SNAP HEADER
+*
+*/
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+inline int rtllib_put_snap(u8 *data, u16 h_proto)
+{
+	struct rtllib_snap_hdr *snap;
+	u8 *oui;
+
+	snap = (struct rtllib_snap_hdr *)data;
+	snap->dsap = 0xaa;
+	snap->ssap = 0xaa;
+	snap->ctrl = 0x03;
+
+	if (h_proto == 0x8137 || h_proto == 0x80f3)
+		oui = P802_1H_OUI;
+	else
+		oui = RFC1042_OUI;
+	snap->oui[0] = oui[0];
+	snap->oui[1] = oui[1];
+	snap->oui[2] = oui[2];
+
+	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
+
+	return SNAP_SIZE + sizeof(u16);
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_encrypt_fragment(
+	struct rtllib_device *ieee,
+	struct sk_buff *frag,
+	int hdr_len,
+	u8 is_mesh,
+	u8 entry)
+#else
+int rtllib_encrypt_fragment(
+	struct rtllib_device *ieee,
+	struct sk_buff *frag,
+	int hdr_len)
+#endif
+{
+	struct rtllib_crypt_data* crypt = NULL;
+	int res;
+	
+#ifdef _RTL8192_EXT_PATCH_
+      	if (is_mesh) {
+		crypt = ieee->cryptlist[entry]->crypt[ieee->mesh_txkeyidx]; 
+	} else
+		crypt = ieee->sta_crypt[ieee->tx_keyidx]; 		
+#else
+	crypt = ieee->crypt[ieee->tx_keyidx];
+#endif
+
+	if (!(crypt && crypt->ops))
+	{
+		printk("=========>%s(), crypt is null\n", __FUNCTION__);
+		return -1;
+	}
+#ifdef CONFIG_RTLLIB_CRYPT_TKIP
+	struct rtllib_hdr_1addr *header;
+
+	if (ieee->tkip_countermeasures &&
+	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
+		header = (struct rtllib_hdr_1addr *) frag->data;
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
+			       "TX packet to " MAC_FMT "\n",
+			       ieee->dev->name, MAC_ARG(header->addr1));
+		}
+		return -1;
+	}
+#endif
+	/* To encrypt, frame format is:
+	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
+
+	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+	 * call both MSDU and MPDU encryption functions from here. */
+	atomic_inc(&crypt->refcnt);
+	res = 0;
+	if (crypt->ops->encrypt_msdu)
+		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
+	if (res == 0 && crypt->ops->encrypt_mpdu)
+		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
+
+	atomic_dec(&crypt->refcnt);
+	if (res < 0) {
+		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
+		       ieee->dev->name, frag->len);
+		ieee->ieee_stats.tx_discards++;
+		return -1;
+	}
+
+	return 0;
+}
+
+
+void rtllib_txb_free(struct rtllib_txb *txb) {
+	if (unlikely(!txb))
+		return;
+#if 0
+	for (i = 0; i < txb->nr_frags; i++)
+		if (txb->fragments[i])
+			dev_kfree_skb_any(txb->fragments[i]);
+#endif
+	kfree(txb);
+}
+
+struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size,
+					  int gfp_mask)
+{
+#ifdef USB_USE_ALIGNMENT
+	u32 Tmpaddr=0;
+	int alignment=0;
+#endif
+	struct rtllib_txb *txb;
+	int i;
+	txb = kmalloc(
+		sizeof(struct rtllib_txb) + (sizeof(u8*) * nr_frags),
+		gfp_mask);
+	if (!txb)
+		return NULL;
+
+	memset(txb, 0, sizeof(struct rtllib_txb));
+	txb->nr_frags = nr_frags;
+	txb->frag_size = txb_size;
+
+	for (i = 0; i < nr_frags; i++) {
+#ifdef USB_USE_ALIGNMENT
+		txb->fragments[i] = dev_alloc_skb(txb_size+USB_512B_ALIGNMENT_SIZE);
+#else
+		txb->fragments[i] = dev_alloc_skb(txb_size);
+#endif
+		if (unlikely(!txb->fragments[i])) {
+			i--;
+			break;
+		}
+#ifdef USB_USE_ALIGNMENT
+		Tmpaddr = (u32)(txb->fragments[i]->data);
+		alignment = Tmpaddr & 0x1ff;
+		skb_reserve(txb->fragments[i],(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+		memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
+	}
+	if (unlikely(i != nr_frags)) {
+		while (i >= 0)
+			dev_kfree_skb_any(txb->fragments[i--]);
+		kfree(txb);
+		return NULL;
+	}
+	return txb;
+}
+
+int 
+rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
+{
+	struct ethhdr *eth;
+	struct iphdr *ip;
+
+	eth = (struct ethhdr *)skb->data;
+	if (eth->h_proto != htons(ETH_P_IP))
+		return 0;
+
+#ifdef ENABLE_AMSDU
+	if(bIsAmsdu)
+		ip = (struct iphdr*)(skb->data + sizeof(struct ether_header) + AMSDU_SUBHEADER_LEN + SNAP_SIZE + sizeof(u16));
+	else
+		ip = (struct iphdr*)(skb->data + sizeof(struct ether_header));
+#else
+	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+	ip = ip_hdr(skb);
+#else
+	ip = (struct iphdr*)(skb->data + sizeof(struct ether_header));
+#endif
+#endif
+	switch (ip->tos & 0xfc) {
+		case 0x20:
+			return 2;
+		case 0x40:
+			return 1;
+		case 0x60:
+			return 3;
+		case 0x80:
+			return 4;
+		case 0xa0:
+			return 5;
+		case 0xc0:
+			return 6;
+		case 0xe0:
+			return 7;
+		default:
+			return 0;
+	}
+}
+
+#define SN_LESS(a, b)		(((a-b)&0x800)!=0)
+void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	PTX_TS_RECORD			pTxTs = NULL;
+	struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data;
+
+	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT){
+		return;
+	}
+	if (!IsQoSDataFrame(skb->data)){
+		return;
+	}
+	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){
+		return;
+	}
+#ifdef TO_DO_LIST
+	if(pTcb->PacketLength >= 4096)
+		return;
+	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
+		return; 
+#endif
+
+	if(tcb_desc->bdhcp || ieee->CntAfterLink<2){
+		return;
+	}
+	
+	if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION){
+		return;
+	}	
+
+	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)){
+		return; 
+	}
+	if(pHTInfo->bCurrentAMPDUEnable){
+		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)){
+			printk("%s: can't get TS\n", __func__);
+			return;
+		}
+		if (pTxTs->TxAdmittedBARecord.bValid == false){
+			if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) {
+				;
+			} else if (tcb_desc->bdhcp == 1){
+				;
+			} else if (!pTxTs->bDisable_AddBa){
+				TsStartAddBaProcess(ieee, pTxTs);
+			}
+			goto FORCED_AGG_SETTING;
+		}
+		else if (pTxTs->bUsingBa == false)
+		{
+			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
+				pTxTs->bUsingBa = true;
+			else
+				goto FORCED_AGG_SETTING;
+		}
+#ifndef _RTL8192_EXT_PATCH_
+#ifndef RTL8192S_WAPI_SUPPORT  
+		if (ieee->iw_mode == IW_MODE_INFRA)
+#endif
+#endif
+		{
+			tcb_desc->bAMPDUEnable = true;
+			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
+			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
+		}
+	}
+FORCED_AGG_SETTING:
+	switch(pHTInfo->ForcedAMPDUMode )
+	{
+		case HT_AGG_AUTO:
+			break;
+
+		case HT_AGG_FORCE_ENABLE:
+			tcb_desc->bAMPDUEnable = true;
+			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
+			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
+			break;
+
+		case HT_AGG_FORCE_DISABLE:
+			tcb_desc->bAMPDUEnable = false;
+			tcb_desc->ampdu_density = 0;
+			tcb_desc->ampdu_factor = 0;
+			break;
+
+	}	
+		return;
+}
+
+extern void rtllib_qurey_ShortPreambleMode(struct rtllib_device* ieee, cb_desc* tcb_desc)
+{
+	tcb_desc->bUseShortPreamble = false;
+	if (tcb_desc->data_rate == 2)
+	{
+		return;
+	}
+	else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+	{
+		tcb_desc->bUseShortPreamble = true;
+	}
+	return;	
+}
+
+extern	void	
+rtllib_query_HTCapShortGI(struct rtllib_device *ieee, cb_desc *tcb_desc)
+{
+	PRT_HIGH_THROUGHPUT		pHTInfo = ieee->pHTInfo;
+
+	tcb_desc->bUseShortGI 		= false;
+
+	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
+		return;
+
+	if(pHTInfo->bForcedShortGI)
+	{
+		tcb_desc->bUseShortGI = true;
+		return;
+	}
+
+	if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
+		tcb_desc->bUseShortGI = true;
+	else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
+		tcb_desc->bUseShortGI = true;
+}
+
+void rtllib_query_BandwidthMode(struct rtllib_device* ieee, cb_desc *tcb_desc)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+
+	tcb_desc->bPacketBW = false;
+
+	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
+		return;
+
+	if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
+		return;
+
+	if((tcb_desc->data_rate & 0x80)==0) 
+		return;
+	if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
+		tcb_desc->bPacketBW = true;
+	return;
+}
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+extern void rtllib_ibss_query_HTCapShortGI(struct rtllib_device *ieee, cb_desc *tcb_desc,u8 is_peer_shortGI_40M,u8 is_peer_shortGI_20M)
+{
+	PRT_HIGH_THROUGHPUT		pHTInfo = ieee->pHTInfo;
+
+	tcb_desc->bUseShortGI 		= false;
+
+	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT || (ieee->iw_mode != IW_MODE_ADHOC))
+	{
+		return;
+	}
+
+	if(pHTInfo->bForcedShortGI)
+	{
+		tcb_desc->bUseShortGI = true;
+		return;
+	}
+	if((pHTInfo->bCurBW40MHz==true) && is_peer_shortGI_40M)
+		tcb_desc->bUseShortGI = true;
+	else if((pHTInfo->bCurBW40MHz==false) && is_peer_shortGI_20M)
+		tcb_desc->bUseShortGI = true;
+}
+void rtllib_ibss_query_BandwidthMode(struct rtllib_device* ieee, cb_desc *tcb_desc, u8 is_peer_40M)
+{
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+
+	tcb_desc->bPacketBW = false;
+
+	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT || (ieee->iw_mode != IW_MODE_ADHOC))
+	{
+		return;
+	}
+
+	if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
+	{
+		return;
+	}
+
+	if((tcb_desc->data_rate & 0x80)==0) 
+	{
+		return;
+	}
+	if(pHTInfo->bCurBW40MHz && is_peer_40M && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
+		tcb_desc->bPacketBW = true;
+	return;
+}
+#endif
+void rtllib_query_protectionmode(struct rtllib_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
+{
+	tcb_desc->bRTSSTBC			= false;
+	tcb_desc->bRTSUseShortGI		= false; 
+	tcb_desc->bCTSEnable			= false; 
+	tcb_desc->RTSSC				= 0;		
+	tcb_desc->bRTSBW			= false; 
+	
+	if(tcb_desc->bBroadcast || tcb_desc->bMulticast)
+		return;
+	
+	if (is_broadcast_ether_addr(skb->data+16))  
+		return;
+
+	if (ieee->mode < IEEE_N_24G) 
+	{
+		if (skb->len > ieee->rts)
+		{
+			tcb_desc->bRTSEnable = true;
+			tcb_desc->rts_rate = MGN_24M;
+		}
+		else if (ieee->current_network.buseprotection)
+		{
+			tcb_desc->bRTSEnable = true;
+			tcb_desc->bCTSEnable = true;
+			tcb_desc->rts_rate = MGN_24M;
+		}
+		return;
+	}
+	else
+	{
+		PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+		while (true)
+		{
+			if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
+			{
+				tcb_desc->bCTSEnable	= true;
+				tcb_desc->rts_rate  = 	MGN_24M;
+#if defined(RTL8192SE) || defined(RTL8192SU) || defined RTL8192CE
+				tcb_desc->bRTSEnable = false;
+#else
+				tcb_desc->bRTSEnable = true;
+#endif
+				break;
+			}
+			else if(pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS|HT_IOT_ACT_PURE_N_MODE))
+			{
+				tcb_desc->bRTSEnable = true;
+				tcb_desc->rts_rate  = 	MGN_24M;
+				break;
+			}
+			if (ieee->current_network.buseprotection)
+			{
+				tcb_desc->bRTSEnable = true;
+				tcb_desc->bCTSEnable = true;
+				tcb_desc->rts_rate = MGN_24M;
+				break;
+			}
+			if(pHTInfo->bCurrentHTSupport  && pHTInfo->bEnableHT)
+			{
+				u8 HTOpMode = pHTInfo->CurrentOpMode;
+				if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
+							(!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
+				{
+					tcb_desc->rts_rate = MGN_24M; 
+					tcb_desc->bRTSEnable = true;
+					break;
+				}
+			}
+			if (skb->len > ieee->rts)
+			{
+				tcb_desc->rts_rate = MGN_24M; 
+				tcb_desc->bRTSEnable = true;
+				break;
+			}
+			if(tcb_desc->bAMPDUEnable)
+			{
+				tcb_desc->rts_rate = MGN_24M; 
+				tcb_desc->bRTSEnable = false;
+				break;
+			}
+			goto NO_PROTECTION;
+		}
+		}
+	if( 0 )
+	{
+		tcb_desc->bCTSEnable	= true;
+		tcb_desc->rts_rate = MGN_24M;
+		tcb_desc->bRTSEnable 	= true;
+	}
+	if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		tcb_desc->bUseShortPreamble = true;
+	if (ieee->iw_mode == IW_MODE_MASTER)
+			goto NO_PROTECTION;
+	return;
+NO_PROTECTION:
+	tcb_desc->bRTSEnable	= false;
+	tcb_desc->bCTSEnable	= false;
+	tcb_desc->rts_rate		= 0;
+	tcb_desc->RTSSC		= 0;
+	tcb_desc->bRTSBW		= false;
+}
+
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) 
+void rtllib_txrate_selectmode(struct rtllib_device* ieee, cb_desc* tcb_desc,struct sta_info *psta)
+#else
+void rtllib_txrate_selectmode(struct rtllib_device* ieee, cb_desc* tcb_desc)
+#endif
+{
+#ifdef TO_DO_LIST	
+	if(!IsDataFrame(pFrame))
+	{
+		pTcb->bTxDisableRateFallBack = true;
+		pTcb->bTxUseDriverAssingedRate = true;
+		pTcb->RATRIndex = 7;
+		return;
+	}
+
+	if(pMgntInfo->ForcedDataRate!= 0)
+	{
+		pTcb->bTxDisableRateFallBack = true;
+		pTcb->bTxUseDriverAssingedRate = true;
+		return;
+	}
+#endif
+	if(ieee->bTxDisableRateFallBack)
+		tcb_desc->bTxDisableRateFallBack = true;
+
+	if(ieee->bTxUseDriverAssingedRate)
+		tcb_desc->bTxUseDriverAssingedRate = true;
+	if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
+	{
+#ifdef _RTL8192_EXT_PATCH_
+		if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_MESH)) 
+			tcb_desc->RATRIndex = 0;
+		else if (ieee->iw_mode == IW_MODE_ADHOC){
+			if(tcb_desc->bMulticast ||  tcb_desc->bBroadcast){
+				tcb_desc->data_rate = ieee->basic_rate;
+				tcb_desc->bTxUseDriverAssingedRate = 1;
+			}else{
+				if(psta != NULL)
+					tcb_desc->RATRIndex = psta->ratr_index;
+				else
+					tcb_desc->RATRIndex = 7;
+			}	
+		}
+#else			
+		if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) 
+			tcb_desc->RATRIndex = 0;
+#endif		
+	}
+#if 0
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(ieee->iw_mode == IW_MODE_ADHOC)
+		tcb_desc->RATRIndex = ratr_index;
+#endif
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	if(ieee->bUseRAMask){
+		if((ieee->iw_mode == IW_MODE_ADHOC) && (NULL != psta)){
+			short peer_AID = psta->aid;
+		
+			tcb_desc->macId =0;
+			if((peer_AID > 0) && (peer_AID < PEER_MAX_ASSOC))
+			{
+				tcb_desc->macId = peer_AID + 1;
+			}else{
+				tcb_desc->macId = 1;
+			}
+		}
+		else{
+			if((ieee->mode & WIRELESS_MODE_N_24G) || (ieee->mode & WIRELESS_MODE_N_5G))
+				tcb_desc->RATRIndex = RATR_INX_WIRELESS_NGB;
+			else if(ieee->mode & WIRELESS_MODE_G)
+				tcb_desc->RATRIndex = RATR_INX_WIRELESS_GB;
+			else if(ieee->mode & WIRELESS_MODE_B)
+				tcb_desc->RATRIndex = RATR_INX_WIRELESS_B;
+				
+			tcb_desc->macId = 0;
+		}
+	}
+#endif
+}
+
+u16 rtllib_query_seqnum(struct rtllib_device*ieee, struct sk_buff* skb, u8* dst)
+{
+	u16 seqnum = 0;
+
+	if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
+		return 0;
+	if (IsQoSDataFrame(skb->data)) 
+	{
+		PTX_TS_RECORD pTS = NULL;
+		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
+		{
+			return 0;
+		}
+		seqnum = pTS->TxCurSeq;
+		pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
+		return seqnum;
+	}
+	return 0;
+}
+
+
+
+#ifdef ENABLE_AMSDU
+#if 0
+static void CB_DESC_DUMP(pcb_desc tcb, char* func)
+{
+	printk("\n%s",func);
+	printk("\n-------------------CB DESC DUMP ><------------------------");
+	printk("\npkt_size:\t %d", tcb->pkt_size);
+	printk("\nqueue_index:\t %d", tcb->queue_index);
+	printk("\nbMulticast:\t %d", tcb->bMulticast);
+	printk("\nbBroadcast:\t %d", tcb->bBroadcast);
+	printk("\nbPacketBw:\t %d", tcb->bPacketBW);
+	printk("\nbRTSEnable:\t %d", tcb->bRTSEnable);
+	printk("\nrts_rate:\t %d", tcb->rts_rate);
+	printk("\nbUseShortGI:\t %d", tcb->bUseShortGI);
+	printk("\nbAMSDU:\t %d", tcb->bAMSDU);
+	printk("\nFromAggrQ:\t %d", tcb->bFromAggrQ);
+	printk("\nRATRIndex:\t %d", tcb->RATRIndex);
+	printk("\ndata_rate:\t %d", tcb->data_rate);
+	printk("\n-------------------CB DESC DUMP <>------------------------\n");
+}
+#endif
+struct sk_buff *AMSDU_Aggregation(
+	struct rtllib_device 	*ieee,
+	struct sk_buff_head 		*pSendList
+	)
+{
+	struct sk_buff *	pSkb;
+	struct sk_buff * 	pAggrSkb;
+	u8		i;
+	u32		total_length = 0;
+	u32		skb_len, num_skb;
+	pcb_desc 	pcb;
+	u8 		amsdu_shdr[AMSDU_SUBHEADER_LEN];
+	u8		padding = 0;
+	u8		*p = NULL, *q=NULL;
+	u16		ether_type;
+
+	num_skb = skb_queue_len(pSendList);
+	if(num_skb == 0)
+		return NULL;
+	if(num_skb == 1)
+	{
+		pSkb = (struct sk_buff *)skb_dequeue(pSendList);
+		memset(pSkb->cb, 0, sizeof(pSkb->cb));
+		pcb = (pcb_desc)(pSkb->cb + MAX_DEV_ADDR_SIZE);
+		pcb->bFromAggrQ = true;
+		return pSkb;
+	}
+
+	total_length += sizeof(struct ethhdr);
+	for(i=0; i<num_skb; i++)	
+	{
+		pSkb= (struct sk_buff *)skb_dequeue(pSendList);
+		if(pSkb->len <= (ETH_ALEN*2))
+		{
+			dev_kfree_skb_any(pSkb);
+			continue;
+		}
+		skb_len = pSkb->len - ETH_ALEN*2 + SNAP_SIZE + AMSDU_SUBHEADER_LEN;
+		if(i < (num_skb-1))
+		{
+			skb_len += ((4-skb_len%4)==4)?0:(4-skb_len%4);
+		}
+		total_length += skb_len;
+		skb_queue_tail(pSendList, pSkb);
+	}
+	
+	pAggrSkb = dev_alloc_skb(total_length);
+	if(NULL == pAggrSkb)
+	{
+		skb_queue_purge(pSendList);
+		printk("%s: Can not alloc skb!\n", __FUNCTION__);
+		return NULL;
+	}
+	skb_put(pAggrSkb,total_length);
+	pAggrSkb->priority = pSkb->priority;
+
+	memset(pAggrSkb->cb, 0, sizeof(pAggrSkb->cb));
+	pcb = (pcb_desc)(pAggrSkb->cb + MAX_DEV_ADDR_SIZE);
+	pcb->bFromAggrQ = true;
+	pcb->bAMSDU = true;
+
+	memset(amsdu_shdr, 0, AMSDU_SUBHEADER_LEN);
+	p = pAggrSkb->data;
+	for(i=0; i<num_skb; i++)	
+	{
+		q = p;
+		pSkb= (struct sk_buff *)skb_dequeue(pSendList);
+		ether_type = ntohs(((struct ethhdr *)pSkb->data)->h_proto);
+
+		skb_len = pSkb->len - sizeof(struct ethhdr) + AMSDU_SUBHEADER_LEN + SNAP_SIZE + sizeof(u16);
+		if(i < (num_skb-1))
+		{
+			padding = ((4-skb_len%4)==4)?0:(4-skb_len%4);
+			skb_len += padding;
+		}
+		if(i == 0)
+		{
+			memcpy(p, pSkb->data, sizeof(struct ethhdr));
+			p += sizeof(struct ethhdr);
+		}
+		memcpy(amsdu_shdr, pSkb->data, (ETH_ALEN*2));
+		skb_pull(pSkb, sizeof(struct ethhdr));
+		*(u16*)(amsdu_shdr+ETH_ALEN*2) = ntohs(pSkb->len + SNAP_SIZE + sizeof(u16));
+		memcpy(p, amsdu_shdr, AMSDU_SUBHEADER_LEN);
+		p += AMSDU_SUBHEADER_LEN;
+
+		rtllib_put_snap(p, ether_type);
+		p += SNAP_SIZE + sizeof(u16);
+
+		memcpy(p, pSkb->data, pSkb->len);
+		p += pSkb->len;
+		if(padding > 0)
+		{
+			memset(p, 0, padding);
+			p += padding;
+			padding = 0;
+		}
+		dev_kfree_skb_any(pSkb);
+	}
+	
+	return pAggrSkb;
+}
+
+
+/* NOTE:
+	This function return a list of SKB which is proper to be aggregated. 
+	If no proper SKB is found to do aggregation, SendList will only contain the input SKB.
+*/
+u8 AMSDU_GetAggregatibleList(
+	struct rtllib_device *	ieee,
+	struct sk_buff *		pCurSkb,
+	struct sk_buff_head 		*pSendList,
+	u8				queue_index
+	)
+{
+	struct sk_buff 			*pSkb = NULL;
+	u16				nMaxAMSDUSize = 0;
+	u32				AggrSize = 0;
+	u32				nAggrSkbNum = 0;
+	u8 				padding = 0;
+	struct sta_info			*psta = NULL;	
+	u8 				*addr = (u8*)(pCurSkb->data);	
+	struct sk_buff_head *header;
+	struct sk_buff 	  *punlinkskb = NULL;	
+
+	padding = ((4-pCurSkb->len%4)==4)?0:(4-pCurSkb->len%4);
+	AggrSize = AMSDU_SUBHEADER_LEN + pCurSkb->len + padding;
+	skb_queue_tail(pSendList, pCurSkb);
+	nAggrSkbNum++;
+
+	if(ieee->iw_mode == IW_MODE_MASTER){	
+		psta = GetStaInfo(ieee, addr);
+		if(NULL != psta)
+			nMaxAMSDUSize = psta->htinfo.AMSDU_MaxSize;
+		else
+			return 1;
+	}else if(ieee->iw_mode == IW_MODE_ADHOC){
+		psta = GetStaInfo(ieee, addr);
+		if(NULL != psta)
+			nMaxAMSDUSize = psta->htinfo.AMSDU_MaxSize;
+		else
+			return 1;
+	}else{
+		nMaxAMSDUSize = ieee->pHTInfo->nCurrent_AMSDU_MaxSize;
+	}
+
+	if(ieee->pHTInfo->ForcedAMSDUMode == HT_AGG_FORCE_ENABLE)
+	{
+		nMaxAMSDUSize = ieee->pHTInfo->ForcedAMSDUMaxSize;
+	}
+	
+	header = (&ieee->skb_aggQ[queue_index]);
+	pSkb = header->next;
+	while(pSkb != (struct sk_buff*)header)
+	{
+		if((ieee->iw_mode == IW_MODE_MASTER) ||(ieee->iw_mode == IW_MODE_ADHOC))
+		{
+			if(memcmp(pCurSkb->data, pSkb->data, ETH_ALEN) != 0) 
+			{
+				pSkb = pSkb->next;
+				continue;				
+			}
+		}
+		if((AMSDU_SUBHEADER_LEN + pSkb->len + AggrSize < nMaxAMSDUSize) )
+		{
+			punlinkskb = pSkb;
+			pSkb = pSkb->next;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
+			skb_unlink(punlinkskb, header);	
+#else
+			/*
+			 * __skb_unlink before linux2.6.14 does not use spinlock to protect list head.
+			 * add spinlock function manually. john,2008/12/03
+			 */
+			{
+				unsigned long flags;
+				spin_lock_irqsave(&ieee->lock, flags);
+				__skb_unlink(punlinkskb,header);
+				spin_unlock_irqrestore(&ieee->lock, flags);
+			}
+#endif
+			
+			padding = ((4-punlinkskb->len%4)==4)?0:(4-punlinkskb->len%4);
+			AggrSize += AMSDU_SUBHEADER_LEN + punlinkskb->len + padding;
+			skb_queue_tail(pSendList, punlinkskb);
+			nAggrSkbNum++;
+		}
+		else
+		{
+			if(!(AMSDU_SUBHEADER_LEN + pSkb->len + AggrSize < nMaxAMSDUSize))
+				;
+		
+			break; 
+		}
+	}
+	return nAggrSkbNum;
+}
+#endif
+static int wme_downgrade_ac(struct sk_buff *skb)
+{
+	switch (skb->priority) {
+		case 6:
+		case 7:
+			skb->priority = 5; /* VO -> VI */
+			return 0;
+		case 4:
+		case 5:
+			skb->priority = 3; /* VI -> BE */
+			return 0;
+		case 0:
+		case 3:
+			skb->priority = 1; /* BE -> BK */
+			return 0;
+		default:
+			return -1;
+	}
+}
+
+int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
+	struct rtllib_txb *txb = NULL;
+	struct rtllib_hdr_3addrqos *frag_hdr;
+	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
+	unsigned long flags;
+	struct net_device_stats *stats = &ieee->stats;
+	int ether_type = 0, encrypt;
+	int bytes, fc, qos_ctl = 0, hdr_len;
+	struct sk_buff *skb_frag;
+	struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
+		.duration_id = 0,
+		.seq_ctl = 0,
+		.qos_ctl = 0
+	};
+	u8 dest[ETH_ALEN], src[ETH_ALEN];
+	int qos_actived = ieee->current_network.qos_data.active;
+	struct rtllib_crypt_data* crypt = NULL;
+	cb_desc *tcb_desc;
+	u8 bIsMulticast = false;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) 
+	struct sta_info *p_sta = NULL;
+#endif	
+	u8 IsAmsdu = false;
+#ifdef ENABLE_AMSDU	
+	u8 queue_index = WME_AC_BE;
+	cb_desc *tcb_desc_skb;
+	u8 bIsSptAmsdu = false;
+#endif	
+
+	bool	bdhcp =false;
+#ifndef _RTL8192_EXT_PATCH_
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	static u8 zero14[14] = {0};
+#endif
+	spin_lock_irqsave(&ieee->lock, flags);
+
+	/* If there is no driver handler to take the TXB, dont' bother
+	 * creating it... */
+	if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
+	   ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
+		printk(KERN_WARNING "%s: No xmit handler.\n",
+		       ieee->dev->name);
+		goto success;
+	}
+	
+
+	if(likely(ieee->raw_tx == 0)){
+		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
+			printk(KERN_WARNING "%s: skb too small (%d).\n",
+			ieee->dev->name, skb->len);
+			goto success;
+		}
+#ifdef RTL8192S_WAPI_SUPPORT
+		if(memcmp(skb->data, zero14, sizeof(zero14))==0){
+			if(WapiSendWaiPacket(ieee, skb)< 0)
+				goto failed;
+			else{
+				spin_unlock_irqrestore(&ieee->lock, flags);
+				return 0;
+			}
+		}
+#endif
+		/* Save source and destination addresses */
+		memcpy(dest, skb->data, ETH_ALEN);
+		memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
+	
+#ifdef ENABLE_AMSDU	
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+		{
+			p_sta = GetStaInfo(ieee, dest);
+			if(p_sta)	{
+				if(p_sta->htinfo.bEnableHT)
+					bIsSptAmsdu = true;
+			}
+		}else if(ieee->iw_mode == IW_MODE_INFRA) {
+			bIsSptAmsdu = true;
+		}else
+			bIsSptAmsdu = true;
+		bIsSptAmsdu = (bIsSptAmsdu && ieee->pHTInfo->bCurrent_AMSDU_Support && qos_actived);
+			
+		tcb_desc_skb = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE);  
+		if(bIsSptAmsdu) {
+			if(!tcb_desc_skb->bFromAggrQ)  
+			{
+				if(qos_actived)
+				{
+					queue_index = UP2AC(skb->priority);
+				} else {
+					queue_index = WME_AC_BE;
+				}
+
+				if ((skb_queue_len(&ieee->skb_aggQ[queue_index]) != 0)||
+#if defined RTL8192SE || defined RTL8192CE
+				   (ieee->get_nic_desc_num(ieee->dev,queue_index)) > 1||
+#else
+				   (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||
+#endif
+				   (ieee->queue_stop) ||
+				   (ieee->amsdu_in_process)) 
+				{
+					/* insert the skb packet to the Aggregation queue */
+					skb_queue_tail(&ieee->skb_aggQ[queue_index], skb);
+					spin_unlock_irqrestore(&ieee->lock, flags);
+					return 0;
+				}
+			}
+			else  
+			{
+				if(tcb_desc_skb->bAMSDU)
+					IsAmsdu = true;
+				
+				ieee->amsdu_in_process = false;
+			}
+		}
+#endif	
+		memset(skb->cb, 0, sizeof(skb->cb));
+		ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
+
+		if(ieee->iw_mode == IW_MODE_MONITOR)
+		{
+			txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
+			if (unlikely(!txb)) {
+				printk(KERN_WARNING "%s: Could not allocate TXB\n",
+				ieee->dev->name);
+				goto failed;
+			}
+
+			txb->encrypted = 0;
+			txb->payload_size = skb->len;
+			memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
+
+			goto success;
+		}
+
+		if (skb->len > 282){
+			if (ETH_P_IP == ether_type) {
+				const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
+				if (IPPROTO_UDP == ip->protocol) {
+					struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
+					if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
+					    ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
+						printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
+
+						bdhcp = true;
+#ifdef _RTL8192_EXT_PATCH_
+						ieee->LPSDelayCnt = 100;
+#else
+						ieee->LPSDelayCnt = 100;
+#endif	
+					}
+				}
+			}else if(ETH_P_ARP == ether_type){
+				printk("=================>DHCP Protocol start tx ARP pkt!!\n");
+				bdhcp = true;
+				ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
+
+
+			}
+		}
+		
+		skb->priority = rtllib_classify(skb, IsAmsdu);
+#ifdef RTL8192S_WAPI_SUPPORT
+		if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){
+			crypt = NULL;
+			encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
+				ieee->host_encrypt && ieee->WapiSupport && ieee->wapiInfo.bWapiEnable;
+		}
+		else{
+#endif	
+#ifdef _RTL8192_EXT_PATCH_
+		crypt = ieee->sta_crypt[ieee->tx_keyidx];
+#else
+		crypt = ieee->crypt[ieee->tx_keyidx];
+#endif	
+		encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
+			ieee->host_encrypt && crypt && crypt->ops;
+#ifdef RTL8192S_WAPI_SUPPORT
+		}
+#endif		
+		if (!encrypt && ieee->ieee802_1x &&
+		ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
+			stats->tx_dropped++;
+			goto success;
+		}
+	#ifdef CONFIG_RTLLIB_DEBUG
+		if (crypt && !encrypt && ether_type == ETH_P_PAE) {
+			struct eapol *eap = (struct eapol *)(skb->data +
+				sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
+			RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
+				eap_get_type(eap->type));
+		}
+	#endif
+	
+		/* Advance the SKB to the start of the payload */
+		skb_pull(skb, sizeof(struct ethhdr));
+
+                /* Determine total amount of storage required for TXB packets */
+#ifdef ENABLE_AMSDU	
+		if(!IsAmsdu)
+			bytes = skb->len + SNAP_SIZE + sizeof(u16);
+		else
+			bytes = skb->len;
+#else
+		bytes = skb->len + SNAP_SIZE + sizeof(u16);
+#endif	
+
+		if (encrypt)
+			fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
+		else 
+			fc = RTLLIB_FTYPE_DATA; 
+		
+		if(qos_actived)
+			fc |= RTLLIB_STYPE_QOS_DATA; 
+		else
+			fc |= RTLLIB_STYPE_DATA;
+	
+#ifdef _RTL8192_EXT_PATCH_
+		if ((ieee->iw_mode == IW_MODE_INFRA) 
+			|| (ieee->iw_mode == IW_MODE_MESH) ) 
+#else
+		if (ieee->iw_mode == IW_MODE_INFRA) 
+#endif
+		{
+			fc |= RTLLIB_FCTL_TODS;
+			/* To DS: Addr1 = BSSID, Addr2 = SA,
+			Addr3 = DA */
+			memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
+			memcpy(&header.addr2, &src, ETH_ALEN);
+			if(IsAmsdu)
+				memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
+			else
+				memcpy(&header.addr3, &dest, ETH_ALEN);
+		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
+			/* not From/To DS: Addr1 = DA, Addr2 = SA,
+			Addr3 = BSSID */
+			memcpy(&header.addr1, dest, ETH_ALEN);
+			memcpy(&header.addr2, src, ETH_ALEN);
+			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
+		}
+
+		bIsMulticast = is_broadcast_ether_addr(header.addr1) ||is_multicast_ether_addr(header.addr1);
+
+                header.frame_ctl = cpu_to_le16(fc);
+
+		/* Determine fragmentation size based on destination (multicast
+		* and broadcast are not fragmented) */
+		if (bIsMulticast) {
+			frag_size = MAX_FRAG_THRESHOLD;
+			qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
+		}
+		else {
+#ifdef ENABLE_AMSDU	
+			if(bIsSptAmsdu) {
+				if(ieee->iw_mode == IW_MODE_ADHOC) {
+					if(p_sta)
+						frag_size = p_sta->htinfo.AMSDU_MaxSize;
+					else
+						frag_size = ieee->pHTInfo->nAMSDU_MaxSize;
+				}
+				else
+					frag_size = ieee->pHTInfo->nAMSDU_MaxSize;
+				qos_ctl = 0;
+			}
+			else
+#endif	
+			{
+				frag_size = ieee->fts;
+				qos_ctl = 0;
+			}
+		}
+	
+		if(qos_actived)
+		{
+			hdr_len = RTLLIB_3ADDR_LEN + 2;
+
+                    /* in case we are a client verify acm is not set for this ac */
+                    while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
+                        printk("skb->priority = %x\n", skb->priority);
+                        if (wme_downgrade_ac(skb)) {
+                            break;
+                        }
+                        printk("converted skb->priority = %x\n", skb->priority);
+                    }
+                    qos_ctl |= skb->priority; 
+#ifdef ENABLE_AMSDU	
+			if(IsAmsdu)
+			{
+				qos_ctl |= QOS_CTL_AMSDU_PRESENT;
+			}
+                    header.qos_ctl = cpu_to_le16(qos_ctl);
+#else	
+                    header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
+#endif
+		} else {
+			hdr_len = RTLLIB_3ADDR_LEN;		
+		}
+		/* Determine amount of payload per fragment.  Regardless of if
+		* this stack is providing the full 802.11 header, one will
+		* eventually be affixed to this fragment -- so we must account for
+		* it when determining the amount of payload space. */
+		bytes_per_frag = frag_size - hdr_len;
+		if (ieee->config &
+		(CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
+			bytes_per_frag -= RTLLIB_FCS_LEN;
+	
+		/* Each fragment may need to have room for encryptiong pre/postfix */
+		if (encrypt) {
+#ifdef RTL8192S_WAPI_SUPPORT
+			if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable)
+				bytes_per_frag -= ieee->wapiInfo.extra_prefix_len +
+					ieee->wapiInfo.extra_postfix_len;
+			else
+#endif
+			bytes_per_frag -= crypt->ops->extra_prefix_len +
+				crypt->ops->extra_postfix_len;
+		}
+		/* Number of fragments is the total bytes_per_frag /
+		* payload_per_fragment */
+		nr_frags = bytes / bytes_per_frag;
+		bytes_last_frag = bytes % bytes_per_frag;
+		if (bytes_last_frag)
+			nr_frags++;
+		else
+			bytes_last_frag = bytes_per_frag;
+	
+		/* When we allocate the TXB we allocate enough space for the reserve
+		* and full fragment bytes (bytes_per_frag doesn't include prefix,
+		* postfix, header, FCS, etc.) */
+		txb = rtllib_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
+		if (unlikely(!txb)) {
+			printk(KERN_WARNING "%s: Could not allocate TXB\n",
+			ieee->dev->name);
+			goto failed;
+		}
+		txb->encrypted = encrypt;
+		txb->payload_size = bytes;
+
+		if(qos_actived)
+		{
+			txb->queue_index = UP2AC(skb->priority);
+		} else {
+			txb->queue_index = WME_AC_BE;;
+		}
+
+		for (i = 0; i < nr_frags; i++) {
+			skb_frag = txb->fragments[i];
+			tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
+#ifdef _RTL8192_EXT_PATCH_
+			tcb_desc->mesh_pkt = 0;
+			if(ieee->iw_mode == IW_MODE_ADHOC)
+				tcb_desc->badhoc = 1;
+			else
+				tcb_desc->badhoc = 0;
+#endif
+			if(qos_actived){
+				skb_frag->priority = skb->priority;
+				tcb_desc->queue_index =  UP2AC(skb->priority);
+			} else {
+				skb_frag->priority = WME_AC_BE;
+				tcb_desc->queue_index = WME_AC_BE;
+			}
+			skb_reserve(skb_frag, ieee->tx_headroom);
+
+			if (encrypt){
+				if (ieee->hwsec_active)
+					tcb_desc->bHwSec = 1;
+				else
+					tcb_desc->bHwSec = 0;
+#ifdef RTL8192S_WAPI_SUPPORT
+				if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable)
+					skb_reserve(skb_frag, ieee->wapiInfo.extra_prefix_len);
+				else
+#endif	
+				skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
+			}
+			else
+			{
+				tcb_desc->bHwSec = 0;
+			}
+			frag_hdr = (struct rtllib_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
+			memcpy(frag_hdr, &header, hdr_len);
+	
+			/* If this is not the last fragment, then add the MOREFRAGS
+			* bit to the frame control */
+			if (i != nr_frags - 1) {
+				frag_hdr->frame_ctl = cpu_to_le16(
+					fc | RTLLIB_FCTL_MOREFRAGS);
+				bytes = bytes_per_frag;
+		
+			} else {
+				/* The last fragment takes the remaining length */
+				bytes = bytes_last_frag;
+			}
+			if((qos_actived) && (!bIsMulticast))
+			{	
+				frag_hdr->seq_ctl = rtllib_query_seqnum(ieee, skb_frag, header.addr1); 
+				frag_hdr->seq_ctl = cpu_to_le16(frag_hdr->seq_ctl<<4 | i);
+			} else {
+				frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
+			}
+			/* Put a SNAP header on the first fragment */
+#ifdef ENABLE_AMSDU	
+			if ((i == 0) && (!IsAmsdu)) 
+#else
+			if (i == 0) 
+#endif	
+			{
+				rtllib_put_snap(
+					skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
+					ether_type);
+				bytes -= SNAP_SIZE + sizeof(u16);
+			}
+	
+			memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
+	
+			/* Advance the SKB... */
+			skb_pull(skb, bytes);
+	
+			/* Encryption routine will move the header forward in order
+			* to insert the IV between the header and the payload */
+			if (encrypt) {
+#ifdef RTL8192S_WAPI_SUPPORT
+				if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){
+					if(SecSMS4HeaderFillIV(ieee, skb_frag) == 0){
+						SecSWSMS4Encryption(ieee, skb_frag);
+					} else {
+						spin_unlock_irqrestore(&ieee->lock, flags);
+						dev_kfree_skb_any(skb);
+						rtllib_txb_free(txb);
+						return 0;
+					}
+				}
+				else
+#endif		
+				{
+
+#ifdef _RTL8192_EXT_PATCH_
+				rtllib_encrypt_fragment(ieee, skb_frag, hdr_len, 0, 0);
+#else
+				rtllib_encrypt_fragment(ieee, skb_frag, hdr_len);
+#endif
+				}
+			}
+			if (ieee->config &
+			(CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
+				skb_put(skb_frag, 4);
+		}
+
+		if((qos_actived) && (!bIsMulticast))
+		{
+		  if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
+			ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
+		  else
+			ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
+		} else {
+  		  if (ieee->seq_ctrl[0] == 0xFFF)
+			ieee->seq_ctrl[0] = 0;
+		  else
+			ieee->seq_ctrl[0]++;
+		}
+	}else{
+		if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
+			printk(KERN_WARNING "%s: skb too small (%d).\n",
+			ieee->dev->name, skb->len);
+			goto success;
+		}
+	
+		txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
+		if(!txb){
+			printk(KERN_WARNING "%s: Could not allocate TXB\n",
+			ieee->dev->name);
+			goto failed;
+		}
+		
+		txb->encrypted = 0;
+		txb->payload_size = skb->len;
+		memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
+	}	
+
+ success:
+	if (txb)
+	{
+#if 1	
+		cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
+		tcb_desc->bTxEnableFwCalcDur = 1;
+		tcb_desc->priority = skb->priority;
+
+		if(ether_type == ETH_P_PAE) {
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)	
+			{
+				tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee);
+				tcb_desc->bTxDisableRateFallBack = false;
+			}else{
+				tcb_desc->data_rate = ieee->basic_rate;
+				tcb_desc->bTxDisableRateFallBack = 1;
+			}
+			
+			
+			tcb_desc->RATRIndex = 7;                        
+			tcb_desc->bTxUseDriverAssingedRate = 1;
+		} else {
+			if (is_multicast_ether_addr(header.addr1))
+				tcb_desc->bMulticast = 1;
+			if (is_broadcast_ether_addr(header.addr1))
+				tcb_desc->bBroadcast = 1;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) 
+			if ( tcb_desc->bMulticast ||  tcb_desc->bBroadcast){
+				rtllib_txrate_selectmode(ieee, tcb_desc, p_sta);  
+				tcb_desc->data_rate = ieee->basic_rate;
+			}
+			else
+			{
+				if(ieee->iw_mode == IW_MODE_ADHOC)
+				{
+					u8 is_peer_shortGI_40M = 0;
+					u8 is_peer_shortGI_20M = 0;
+					u8 is_peer_BW_40M = 0;
+					p_sta = GetStaInfo(ieee, header.addr1);
+					if(NULL == p_sta)
+					{
+						rtllib_txrate_selectmode(ieee, tcb_desc, p_sta);
+						tcb_desc->data_rate = ieee->rate;
+					}
+					else
+					{
+						rtllib_txrate_selectmode(ieee, tcb_desc, p_sta);
+						tcb_desc->data_rate = CURRENT_RATE(p_sta->wireless_mode, p_sta->CurDataRate, p_sta->htinfo.HTHighestOperaRate);
+						is_peer_shortGI_40M = p_sta->htinfo.bCurShortGI40MHz;
+						is_peer_shortGI_20M = p_sta->htinfo.bCurShortGI20MHz;
+						is_peer_BW_40M = p_sta->htinfo.bCurTxBW40MHz;
+					}
+					rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
+					rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
+					rtllib_ibss_query_HTCapShortGI(ieee, tcb_desc,is_peer_shortGI_40M,is_peer_shortGI_20M); 
+					rtllib_ibss_query_BandwidthMode(ieee, tcb_desc,is_peer_BW_40M);
+					rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
+				}
+				else {
+					rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); 
+					tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
+					if(bdhcp == true){
+						if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
+							tcb_desc->data_rate = MGN_1M;
+							tcb_desc->bTxDisableRateFallBack = false;
+						}else{
+							tcb_desc->data_rate = MGN_1M;
+							tcb_desc->bTxDisableRateFallBack = 1;
+						}
+
+						tcb_desc->RATRIndex = 7;
+						tcb_desc->bTxUseDriverAssingedRate = 1;
+						tcb_desc->bdhcp = 1;
+					}
+					rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
+					rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
+					rtllib_query_HTCapShortGI(ieee, tcb_desc); 
+					rtllib_query_BandwidthMode(ieee, tcb_desc);
+					rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
+					
+				}
+			}
+#else
+			rtllib_txrate_selectmode(ieee, tcb_desc);
+			if ( tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
+				tcb_desc->data_rate = ieee->basic_rate;
+			else
+				tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
+
+			if(bdhcp == true){
+				if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)	
+				{
+					tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee);
+					tcb_desc->bTxDisableRateFallBack = false;
+				}else{
+					tcb_desc->data_rate = MGN_1M;
+					tcb_desc->bTxDisableRateFallBack = 1;
+				}
+
+				
+				tcb_desc->RATRIndex = 7;
+				tcb_desc->bTxUseDriverAssingedRate = 1;
+				tcb_desc->bdhcp = 1;
+			}
+			
+			rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
+			rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
+			rtllib_query_HTCapShortGI(ieee, tcb_desc); 
+			rtllib_query_BandwidthMode(ieee, tcb_desc);
+			rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
+#endif
+		} 		
+#endif
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	dev_kfree_skb_any(skb);
+	if (txb) {
+		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes += txb->payload_size;
+#endif	
+			rtllib_softmac_xmit(txb, ieee);
+		}else{
+			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
+				stats->tx_packets++;
+				stats->tx_bytes += txb->payload_size;
+				return 0;
+			}
+			rtllib_txb_free(txb);
+		}
+	}
+
+	return 0;
+
+ failed:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	netif_stop_queue(dev);
+	stats->tx_errors++;
+	return 1;
+
+}
+int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	memset(skb->cb, 0, sizeof(skb->cb));
+	return rtllib_xmit_inter(skb, dev);
+}
+
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_txb_free);
+#ifdef ENABLE_AMSDU
+EXPORT_SYMBOL_RSL(rtllib_xmit_inter);
+EXPORT_SYMBOL_RSL(AMSDU_Aggregation);
+EXPORT_SYMBOL_RSL(AMSDU_GetAggregatibleList);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(rtllib_query_seqnum);
+EXPORT_SYMBOL_RSL(rtllib_alloc_txb);
+EXPORT_SYMBOL_RSL(rtllib_encrypt_fragment);
+#endif 
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/scatterwalk.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/scatterwalk.c
@@ -0,0 +1,138 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *               2002 Adam J. Richter <adam@yggdrasil.com>
+ *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/version.h>
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "kmap_types.h"
+#endif
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+#include <asm/scatterlist.h>
+#else
+#include <linux/scatterlist.h>
+#endif
+#include "internal.h"
+#include "scatterwalk.h"
+
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
+{
+	if (nbytes <= walk->len_this_page &&
+	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
+	    PAGE_CACHE_SIZE)
+		return walk->data;
+	else
+		return scratch;
+}
+
+static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+{
+	if (out)
+		memcpy(sgdata, buf, nbytes);
+	else
+		memcpy(buf, sgdata, nbytes);
+}
+
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
+{
+	unsigned int rest_of_page;
+
+	walk->sg = sg;
+
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+	walk->page = sg->page;
+#else
+	walk->page = sg_page(sg);
+#endif	
+	walk->len_this_segment = sg->length;
+
+	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
+	walk->len_this_page = min(sg->length, rest_of_page);
+	walk->offset = sg->offset;
+}
+
+void scatterwalk_map(struct scatter_walk *walk, int out)
+{
+	walk->data = crypto_kmap(walk->page, out) + walk->offset;
+}
+
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+				 unsigned int more)
+{
+	/* walk->data may be pointing the first byte of the next page;
+	   however, we know we transfered at least one byte.  So,
+	   walk->data - 1 will be a virtual address in the mapped page. */
+
+	if (out)
+		flush_dcache_page(walk->page);
+
+	if (more) {
+		walk->len_this_segment -= walk->len_this_page;
+
+		if (walk->len_this_segment) {
+			walk->page++;
+			walk->len_this_page = min(walk->len_this_segment,
+						  (unsigned)PAGE_CACHE_SIZE);
+			walk->offset = 0;
+		}
+		else
+			scatterwalk_start(walk, sg_next(walk->sg));
+	}
+}
+
+void scatterwalk_done(struct scatter_walk *walk, int out, int more)
+{
+	crypto_kunmap(walk->data, out);
+	if (walk->len_this_page == 0 || !more)
+		scatterwalk_pagedone(walk, out, more);
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+			   size_t nbytes, int out)
+{
+	if (buf != walk->data) {
+		while (nbytes > walk->len_this_page) {
+			memcpy_dir(buf, walk->data, walk->len_this_page, out);
+			buf += walk->len_this_page;
+			nbytes -= walk->len_this_page;
+
+			crypto_kunmap(walk->data, out);
+			scatterwalk_pagedone(walk, out, 1);
+			scatterwalk_map(walk, out);
+		}
+
+		memcpy_dir(buf, walk->data, nbytes, out);
+	}
+
+	walk->offset += nbytes;
+	walk->len_this_page -= nbytes;
+	walk->len_this_segment -= nbytes;
+	return 0;
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/scatterwalk.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/scatterwalk.h
@@ -0,0 +1,53 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
+ * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _CRYPTO_SCATTERWALK_H
+#define _CRYPTO_SCATTERWALK_H
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+struct scatter_walk {
+	struct scatterlist	*sg;
+	struct page		*page;
+	void			*data;
+	unsigned int		len_this_page;
+	unsigned int		len_this_segment;
+	unsigned int		offset;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+/* Define sg_next is an inline routine now in case we want to change
+   scatterlist to a linked list later. */
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+	return sg + 1;
+}
+#endif
+
+static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
+				      struct scatter_walk *walk_out,
+				      void *src_p, void *dst_p)
+{
+	return walk_in->page == walk_out->page &&
+	       walk_in->offset == walk_out->offset &&
+	       walk_in->data == src_p && walk_out->data == dst_p;
+}
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
+void scatterwalk_map(struct scatter_walk *walk, int out);
+void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+
+#endif  /* _CRYPTO_SCATTERWALK_H */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/aes.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/aes.c
@@ -0,0 +1,468 @@
+/* 
+ * Cryptographic API.
+ *
+ * AES Cipher Algorithm.
+ *
+ * Based on Brian Gladman's code.
+ *
+ * Linux developers:
+ *  Alexander Kjeldaas <astor@fast.no>
+ *  Herbert Valerio Riedel <hvr@hvrlab.org>
+ *  Kyle McMartin <kyle@debian.org>
+ *  Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
+ *
+ * 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.
+ *
+ * ---------------------------------------------------------------------------
+ * Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
+ * All rights reserved.
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+/* Some changes from the Gladman version:
+    s/RIJNDAEL(e_key)/E_KEY/g
+    s/RIJNDAEL(d_key)/D_KEY/g
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include "rtl_crypto.h"
+#include <asm/byteorder.h>
+
+#define AES_MIN_KEY_SIZE	16
+#define AES_MAX_KEY_SIZE	32
+
+#define AES_BLOCK_SIZE		16
+
+static inline 
+u32 generic_rotr32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x >> n) | (x << (32 - n));
+}
+
+static inline 
+u32 generic_rotl32 (const u32 x, const unsigned bits)
+{
+	const unsigned n = bits % 32;
+	return (x << n) | (x >> (32 - n));
+}
+
+#define rotl generic_rotl32
+#define rotr generic_rotr32
+
+/*
+ * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
+ */
+inline static u8
+byte(const u32 x, const unsigned n)
+{
+	return x >> (n << 3);
+}
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+struct aes_ctx {
+	int key_length;
+	u32 E[60];
+	u32 D[60];
+};
+
+#define E_KEY ctx->E
+#define D_KEY ctx->D
+
+static u8 pow_tab[256] __initdata;
+static u8 log_tab[256] __initdata;
+static u8 sbx_tab[256] __initdata;
+static u8 isb_tab[256] __initdata;
+static u32 rco_tab[10];
+static u32 ft_tab[4][256];
+static u32 it_tab[4][256];
+
+static u32 fl_tab[4][256];
+static u32 il_tab[4][256];
+
+static inline u8 __init
+f_mult (u8 a, u8 b)
+{
+	u8 aa = log_tab[a], cc = aa + log_tab[b];
+
+	return pow_tab[cc + (cc < aa ? 1 : 0)];
+}
+
+#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
+
+#define f_rn(bo, bi, n, k)					\
+    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
+             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rn(bo, bi, n, k)					\
+    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
+             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+#define ls_box(x)				\
+    ( fl_tab[0][byte(x, 0)] ^			\
+      fl_tab[1][byte(x, 1)] ^			\
+      fl_tab[2][byte(x, 2)] ^			\
+      fl_tab[3][byte(x, 3)] )
+
+#define f_rl(bo, bi, n, k)					\
+    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
+             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
+
+#define i_rl(bo, bi, n, k)					\
+    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
+             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
+
+static void __init
+gen_tabs (void)
+{
+	u32 i, t;
+	u8 p, q;
+
+	/* log and power tables for GF(2**8) finite field with
+	   0x011b as modular polynomial - the simplest primitive
+	   root is 0x03, used here to generate the tables */
+
+	for (i = 0, p = 1; i < 256; ++i) {
+		pow_tab[i] = (u8) p;
+		log_tab[p] = (u8) i;
+
+		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	log_tab[1] = 0;
+
+	for (i = 0, p = 1; i < 10; ++i) {
+		rco_tab[i] = p;
+
+		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = (i ? pow_tab[255 - log_tab[i]] : 0);
+		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+		sbx_tab[i] = p;
+		isb_tab[p] = (u8) i;
+	}
+
+	for (i = 0; i < 256; ++i) {
+		p = sbx_tab[i];
+
+		t = p;
+		fl_tab[0][i] = t;
+		fl_tab[1][i] = rotl (t, 8);
+		fl_tab[2][i] = rotl (t, 16);
+		fl_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (2, p)) |
+		    ((u32) p << 8) |
+		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
+
+		ft_tab[0][i] = t;
+		ft_tab[1][i] = rotl (t, 8);
+		ft_tab[2][i] = rotl (t, 16);
+		ft_tab[3][i] = rotl (t, 24);
+
+		p = isb_tab[i];
+
+		t = p;
+		il_tab[0][i] = t;
+		il_tab[1][i] = rotl (t, 8);
+		il_tab[2][i] = rotl (t, 16);
+		il_tab[3][i] = rotl (t, 24);
+
+		t = ((u32) ff_mult (14, p)) |
+		    ((u32) ff_mult (9, p) << 8) |
+		    ((u32) ff_mult (13, p) << 16) |
+		    ((u32) ff_mult (11, p) << 24);
+
+		it_tab[0][i] = t;
+		it_tab[1][i] = rotl (t, 8);
+		it_tab[2][i] = rotl (t, 16);
+		it_tab[3][i] = rotl (t, 24);
+	}
+}
+
+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+
+#define imix_col(y,x)       \
+    u   = star_x(x);        \
+    v   = star_x(u);        \
+    w   = star_x(v);        \
+    t   = w ^ (x);          \
+   (y)  = u ^ v ^ w;        \
+   (y) ^= rotr(u ^ t,  8) ^ \
+          rotr(v ^ t, 16) ^ \
+          rotr(t,24)
+
+/* initialise the key schedule from the user supplied key */
+
+#define loop4(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
+    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
+    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
+    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
+}
+
+#define loop6(i)                                    \
+{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
+    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
+    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
+    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
+    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
+    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
+}
+
+#define loop8(i)                                    \
+{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
+    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
+    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
+    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
+    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
+    E_KEY[8 * i + 12] = t;                \
+    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
+    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
+    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
+}
+
+static int
+aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct aes_ctx *ctx = ctx_arg;
+	u32 i, t, u, v, w;
+
+	if (key_len != 16 && key_len != 24 && key_len != 32) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	ctx->key_length = key_len;
+
+	E_KEY[0] = u32_in (in_key);
+	E_KEY[1] = u32_in (in_key + 4);
+	E_KEY[2] = u32_in (in_key + 8);
+	E_KEY[3] = u32_in (in_key + 12);
+
+	switch (key_len) {
+	case 16:
+		t = E_KEY[3];
+		for (i = 0; i < 10; ++i)
+			loop4 (i);
+		break;
+
+	case 24:
+		E_KEY[4] = u32_in (in_key + 16);
+		t = E_KEY[5] = u32_in (in_key + 20);
+		for (i = 0; i < 8; ++i)
+			loop6 (i);
+		break;
+
+	case 32:
+		E_KEY[4] = u32_in (in_key + 16);
+		E_KEY[5] = u32_in (in_key + 20);
+		E_KEY[6] = u32_in (in_key + 24);
+		t = E_KEY[7] = u32_in (in_key + 28);
+		for (i = 0; i < 7; ++i)
+			loop8 (i);
+		break;
+	}
+
+	D_KEY[0] = E_KEY[0];
+	D_KEY[1] = E_KEY[1];
+	D_KEY[2] = E_KEY[2];
+	D_KEY[3] = E_KEY[3];
+
+	for (i = 4; i < key_len + 24; ++i) {
+		imix_col (D_KEY[i], E_KEY[i]);
+	}
+
+	return 0;
+}
+
+/* encrypt a block of text */
+
+#define f_nround(bo, bi, k) \
+    f_rn(bo, bi, 0, k);     \
+    f_rn(bo, bi, 1, k);     \
+    f_rn(bo, bi, 2, k);     \
+    f_rn(bo, bi, 3, k);     \
+    k += 4
+
+#define f_lround(bo, bi, k) \
+    f_rl(bo, bi, 0, k);     \
+    f_rl(bo, bi, 1, k);     \
+    f_rl(bo, bi, 2, k);     \
+    f_rl(bo, bi, 3, k)
+
+static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	const struct aes_ctx *ctx = ctx_arg;
+	u32 b0[4], b1[4];
+	const u32 *kp = E_KEY + 4;
+	b0[0] = u32_in (in) ^ E_KEY[0];
+	b0[1] = u32_in (in + 4) ^ E_KEY[1];
+	b0[2] = u32_in (in + 8) ^ E_KEY[2];
+	b0[3] = u32_in (in + 12) ^ E_KEY[3];
+
+	if (ctx->key_length > 24) {
+		f_nround (b1, b0, kp);
+		f_nround (b0, b1, kp);
+	}
+
+	if (ctx->key_length > 16) {
+		f_nround (b1, b0, kp);
+		f_nround (b0, b1, kp);
+	}
+
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_nround (b0, b1, kp);
+	f_nround (b1, b0, kp);
+	f_lround (b0, b1, kp);
+
+	u32_out (out, b0[0]);
+	u32_out (out + 4, b0[1]);
+	u32_out (out + 8, b0[2]);
+	u32_out (out + 12, b0[3]);
+}
+
+/* decrypt a block of text */
+
+#define i_nround(bo, bi, k) \
+    i_rn(bo, bi, 0, k);     \
+    i_rn(bo, bi, 1, k);     \
+    i_rn(bo, bi, 2, k);     \
+    i_rn(bo, bi, 3, k);     \
+    k -= 4
+
+#define i_lround(bo, bi, k) \
+    i_rl(bo, bi, 0, k);     \
+    i_rl(bo, bi, 1, k);     \
+    i_rl(bo, bi, 2, k);     \
+    i_rl(bo, bi, 3, k)
+
+static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	const struct aes_ctx *ctx = ctx_arg;
+	u32 b0[4], b1[4];
+	const int key_len = ctx->key_length;
+	const u32 *kp = D_KEY + key_len + 20;
+
+	b0[0] = u32_in (in) ^ E_KEY[key_len + 24];
+	b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25];
+	b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26];
+	b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27];
+
+	if (key_len > 24) {
+		i_nround (b1, b0, kp);
+		i_nround (b0, b1, kp);
+	}
+
+	if (key_len > 16) {
+		i_nround (b1, b0, kp);
+		i_nround (b0, b1, kp);
+	}
+
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_nround (b0, b1, kp);
+	i_nround (b1, b0, kp);
+	i_lround (b0, b1, kp);
+
+	u32_out (out, b0[0]);
+	u32_out (out + 4, b0[1]);
+	u32_out (out + 8, b0[2]);
+	u32_out (out + 12, b0[3]);
+}
+
+
+static struct crypto_alg aes_alg = {
+	.cra_name		=	"aes",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	AES_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct aes_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
+			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
+			.cia_setkey	   	= 	aes_set_key,
+			.cia_encrypt	 	=	aes_encrypt,
+			.cia_decrypt	  	=	aes_decrypt
+		}
+	}
+};
+
+int __init aes_init(void)
+{
+	gen_tabs();
+	return crypto_register_alg(&aes_alg);
+}
+
+void __exit aes_fini(void)
+{
+	crypto_unregister_alg(&aes_alg);
+}
+
+#ifndef BUILT_IN_CRYPTO
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
+MODULE_LICENSE("Dual BSD/GPL");
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_TSProc.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_TSProc.c
@@ -0,0 +1,672 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtllib.h"
+#include <linux/etherdevice.h>
+#include "rtl819x_TS.h"
+extern void _setup_timer( struct timer_list*, void*, unsigned long);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define list_for_each_entry_safe(pos, n, head, member) \
+	for (pos = list_entry((head)->next, typeof(*pos), member), \
+		n = list_entry(pos->member.next, typeof(*pos), member); \
+		&pos->member != (head); \
+		pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#endif
+void TsSetupTimeOut(unsigned long data)
+{
+}
+
+void TsInactTimeout(unsigned long data)
+{
+}
+
+void RxPktPendingTimeout(unsigned long data)
+{
+	PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)data;
+	struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]);
+	
+	PRX_REORDER_ENTRY 	pReorderEntry = NULL;
+
+	unsigned long flags = 0;
+	struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
+	u8 index = 0;
+	bool bPktInBuf = false;
+
+	spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+	if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
+	{
+		while(!list_empty(&pRxTs->RxPendingPktList))
+		{
+			pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
+			if(index == 0)
+				pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
+
+			if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || 
+				SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)	)
+			{
+				list_del_init(&pReorderEntry->List);
+			
+				if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
+					pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;
+
+				RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum: %d\n",__func__, pReorderEntry->SeqNum);
+				stats_IndicateArray[index] = pReorderEntry->prxb;
+				index++;
+				
+				list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
+			}
+			else
+			{
+				bPktInBuf = true;
+				break;
+			}
+		}
+	}
+
+	if(index>0){
+		pRxTs->RxTimeoutIndicateSeq = 0xffff;
+	
+		if(index > REORDER_WIN_SIZE){
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
+			spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+			return;
+		}
+		rtllib_indicate_packets(ieee, stats_IndicateArray, index);
+		bPktInBuf = false;
+	}
+
+	if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)){
+		pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
+		mod_timer(&pRxTs->RxPktPendingTimer,  jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime));
+	}
+	spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+}
+
+void TsAddBaProcess(unsigned long data)
+{
+	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
+	u8 num = pTxTs->num;
+	struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[num]);
+
+	TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
+	RTLLIB_DEBUG(RTLLIB_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
+}
+
+
+void ResetTsCommonInfo(PTS_COMMON_INFO	pTsCommonInfo)
+{
+	memset(pTsCommonInfo->Addr, 0, 6);
+	memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
+	memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
+	pTsCommonInfo->TClasProc = 0;
+	pTsCommonInfo->TClasNum = 0;
+}
+
+void ResetTxTsEntry(PTX_TS_RECORD pTS)
+{
+	ResetTsCommonInfo(&pTS->TsCommonInfo);
+	pTS->TxCurSeq = 0;
+	pTS->bAddBaReqInProgress = false;
+	pTS->bAddBaReqDelayed = false;
+	pTS->bUsingBa = false;
+	pTS->bDisable_AddBa = false;
+	ResetBaEntry(&pTS->TxAdmittedBARecord); 
+	ResetBaEntry(&pTS->TxPendingBARecord);
+}
+
+void ResetRxTsEntry(PRX_TS_RECORD pTS)
+{
+	ResetTsCommonInfo(&pTS->TsCommonInfo);
+	pTS->RxIndicateSeq = 0xffff; 
+	pTS->RxTimeoutIndicateSeq = 0xffff; 
+	ResetBaEntry(&pTS->RxAdmittedBARecord);	  
+}
+#ifdef _RTL8192_EXT_PATCH_
+void ResetAdmitTRStream(struct rtllib_device *ieee, u8 *Addr)
+{
+	u8 	dir;
+	bool				search_dir[4] = {0, 0, 0, 0};
+	struct list_head*		psearch_list; 
+	PTS_COMMON_INFO	pRet = NULL;
+	PRX_TS_RECORD pRxTS = NULL;
+	PTX_TS_RECORD pTxTS = NULL;
+
+	if(ieee->iw_mode != IW_MODE_MESH) 
+		return;
+
+	search_dir[DIR_DOWN] 	= true;
+	psearch_list = &ieee->Rx_TS_Admit_List;
+	for(dir = 0; dir <= DIR_BI_DIR; dir++)
+	{
+		if(search_dir[dir] ==false )
+			continue;
+		list_for_each_entry(pRet, psearch_list, List){
+			if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir))
+			{
+				pRxTS = (PRX_TS_RECORD)pRet;
+				pRxTS->RxIndicateSeq = 0xffff;
+				pRxTS->RxTimeoutIndicateSeq = 0xffff;
+			}
+					
+		}	
+	}
+	search_dir[DIR_UP] 	= true;
+	psearch_list = &ieee->Tx_TS_Admit_List;
+	for(dir = 0; dir <= DIR_BI_DIR; dir++)
+	{
+		if(search_dir[dir] ==false )
+			continue;
+		list_for_each_entry(pRet, psearch_list, List){
+			if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir))
+			{
+				pTxTS = (PTX_TS_RECORD)pRet;
+				pTxTS->TxCurSeq = 0xffff;
+			}
+					
+		}	
+	}
+
+	return;
+}
+#endif
+
+void TSInitialize(struct rtllib_device *ieee)
+{
+	PTX_TS_RECORD		pTxTS  = ieee->TxTsRecord;
+	PRX_TS_RECORD		pRxTS  = ieee->RxTsRecord;
+	PRX_REORDER_ENTRY	pRxReorderEntry = ieee->RxReorderEntry;
+	u8				count = 0;
+	RTLLIB_DEBUG(RTLLIB_DL_TS, "==========>%s()\n", __FUNCTION__);
+	INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
+	INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
+	INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
+
+	for(count = 0; count < TOTAL_TS_NUM; count++)
+	{
+		pTxTS->num = count;
+		_setup_timer(&pTxTS->TsCommonInfo.SetupTimer,
+			    TsSetupTimeOut,
+			    (unsigned long) pTxTS);
+
+		_setup_timer(&pTxTS->TsCommonInfo.InactTimer,
+			    TsInactTimeout,
+			    (unsigned long) pTxTS);
+
+		_setup_timer(&pTxTS->TsAddBaTimer,
+			    TsAddBaProcess,
+			    (unsigned long) pTxTS);
+		
+		_setup_timer(&pTxTS->TxPendingBARecord.Timer,
+			    BaSetupTimeOut, 
+			    (unsigned long) pTxTS);
+		_setup_timer(&pTxTS->TxAdmittedBARecord.Timer,
+			    TxBaInactTimeout,
+			    (unsigned long) pTxTS);
+		
+		ResetTxTsEntry(pTxTS);
+		list_add_tail(&pTxTS->TsCommonInfo.List, 
+				&ieee->Tx_TS_Unused_List); 
+		pTxTS++;
+	}
+
+	INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
+	INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
+	INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
+	for(count = 0; count < TOTAL_TS_NUM; count++)
+	{
+		pRxTS->num = count;
+		INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
+		
+		_setup_timer(&pRxTS->TsCommonInfo.SetupTimer,
+			    TsSetupTimeOut,
+			    (unsigned long) pRxTS);
+	
+		_setup_timer(&pRxTS->TsCommonInfo.InactTimer,
+			    TsInactTimeout,
+			    (unsigned long) pRxTS);
+
+		_setup_timer(&pRxTS->RxAdmittedBARecord.Timer,
+			    RxBaInactTimeout,
+			    (unsigned long) pRxTS);
+		
+		_setup_timer(&pRxTS->RxPktPendingTimer,
+			    RxPktPendingTimeout,
+			    (unsigned long) pRxTS);
+		
+		ResetRxTsEntry(pRxTS);
+		list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
+		pRxTS++;
+	}
+	INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
+	for(count = 0; count < REORDER_ENTRY_NUM; count++)
+	{
+		list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
+		if(count == (REORDER_ENTRY_NUM-1))
+			break;
+		pRxReorderEntry = &ieee->RxReorderEntry[count+1];
+	}
+
+}
+
+void AdmitTS(struct rtllib_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime)
+{
+	del_timer_sync(&pTsCommonInfo->SetupTimer);
+	del_timer_sync(&pTsCommonInfo->InactTimer);
+
+	if(InactTime!=0)
+		mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime));
+}
+
+
+PTS_COMMON_INFO SearchAdmitTRStream(struct rtllib_device *ieee, u8*	Addr, u8 TID, TR_SELECT	TxRxSelect)
+{
+	u8 	dir;
+	bool				search_dir[4] = {0, 0, 0, 0};
+	struct list_head*		psearch_list; 
+	PTS_COMMON_INFO	pRet = NULL;
+	if(ieee->iw_mode == IW_MODE_MASTER) 
+	{
+		if(TxRxSelect == TX_DIR)
+		{
+			search_dir[DIR_DOWN] = true;
+			search_dir[DIR_BI_DIR]= true;
+		}
+		else
+		{
+			search_dir[DIR_UP] 	= true;
+			search_dir[DIR_BI_DIR]= true;
+		}
+	}
+	else if(ieee->iw_mode == IW_MODE_ADHOC)
+	{
+		if(TxRxSelect == TX_DIR)
+			search_dir[DIR_UP] 	= true;
+		else
+			search_dir[DIR_DOWN] = true;
+	}
+	else
+	{
+		if(TxRxSelect == TX_DIR)
+		{
+			search_dir[DIR_UP] 	= true;
+			search_dir[DIR_BI_DIR]= true;
+			search_dir[DIR_DIRECT]= true;
+		}
+		else
+		{
+			search_dir[DIR_DOWN] = true;
+			search_dir[DIR_BI_DIR]= true;
+			search_dir[DIR_DIRECT]= true;
+		}
+	}
+
+	if(TxRxSelect == TX_DIR)
+		psearch_list = &ieee->Tx_TS_Admit_List;
+	else
+		psearch_list = &ieee->Rx_TS_Admit_List;
+	
+	for(dir = 0; dir <= DIR_BI_DIR; dir++)
+	{
+		if(search_dir[dir] ==false )
+			continue;
+		list_for_each_entry(pRet, psearch_list, List){
+			if (memcmp(pRet->Addr, Addr, 6) == 0)
+				if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
+					if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
+					{
+						break;
+					}
+					
+		}	
+		if(&pRet->List  != psearch_list)
+			break;
+	}
+
+	if(&pRet->List  != psearch_list){
+		return pRet ;
+	}
+	else 
+		return NULL;
+}
+
+void MakeTSEntry(
+		PTS_COMMON_INFO	pTsCommonInfo,
+		u8*		Addr,
+		PTSPEC_BODY	pTSPEC,
+		PQOS_TCLAS	pTCLAS,
+		u8		TCLAS_Num,
+		u8		TCLAS_Proc
+	)
+{
+	u8	count;
+
+	if(pTsCommonInfo == NULL)
+		return;
+	
+	memcpy(pTsCommonInfo->Addr, Addr, 6);
+
+	if(pTSPEC != NULL)
+		memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY));
+
+	for(count = 0; count < TCLAS_Num; count++)
+		memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS));
+
+	pTsCommonInfo->TClasProc = TCLAS_Proc;
+	pTsCommonInfo->TClasNum = TCLAS_Num;
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+void dump_ts_list(struct list_head * ts_list)
+{
+	PTS_COMMON_INFO	pRet = NULL;
+	u8 i=0;
+	list_for_each_entry(pRet, ts_list, List){
+		printk("i=%d ADD:"MAC_FMT", TID:%d, dir:%d\n",i,MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+		i++;
+ 	}
+	
+}
+#endif
+
+bool GetTs(
+	struct rtllib_device*	ieee,
+	PTS_COMMON_INFO			*ppTS,
+	u8*				Addr,
+	u8				TID,
+	TR_SELECT			TxRxSelect,  
+	bool				bAddNewTs
+	)
+{
+	u8	UP = 0;
+	if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
+	{
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or Multicast\n");
+		return false;
+	}
+#if 0
+	if(ieee->pStaQos->CurrentQosMode == QOS_DISABLE)
+	{	UP = 0; } 
+	else if(ieee->pStaQos->CurrentQosMode & QOS_WMM)
+	{
+#else
+	if (ieee->current_network.qos_data.supported == 0)
+		UP = 0;
+	else
+	{
+#endif
+		if (!IsACValid(TID))
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! in %s(), TID(%d) is not valid\n", __FUNCTION__, TID);
+			return false;
+		}
+
+		switch(TID)
+		{
+		case 0:
+		case 3:
+			UP = 0;
+			break;
+
+		case 1:
+		case 2:
+			UP = 2;
+			break;
+			
+		case 4:
+		case 5:
+			UP = 5;
+			break;
+			
+		case 6:
+		case 7:
+			UP = 7;
+			break;
+		}
+	}
+
+	*ppTS = SearchAdmitTRStream(
+			ieee, 
+			Addr,
+			UP, 
+			TxRxSelect);
+	if(*ppTS != NULL)
+	{
+		return true;
+	}
+	else
+	{
+		if(bAddNewTs == false)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed(tid:%d)\n", UP);
+			return false;
+		}
+		else
+		{
+			TSPEC_BODY	TSpec;
+			PQOS_TSINFO		pTSInfo = &TSpec.f.TSInfo;
+			struct list_head*	pUnusedList = 
+								(TxRxSelect == TX_DIR)?
+								(&ieee->Tx_TS_Unused_List):
+								(&ieee->Rx_TS_Unused_List);
+								
+			struct list_head*	pAddmitList = 
+								(TxRxSelect == TX_DIR)?
+								(&ieee->Tx_TS_Admit_List):
+								(&ieee->Rx_TS_Admit_List);
+
+			DIRECTION_VALUE		Dir =		(ieee->iw_mode == IW_MODE_MASTER)? 
+								((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
+								((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
+			RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n");
+			if(!list_empty(pUnusedList))
+			{
+				(*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
+				list_del_init(&(*ppTS)->List);	
+				if(TxRxSelect==TX_DIR)
+				{
+					PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
+					ResetTxTsEntry(tmp);
+				}
+				else{
+					PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);	
+					ResetRxTsEntry(tmp);
+				}
+				
+				RTLLIB_DEBUG(RTLLIB_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+				pTSInfo->field.ucTrafficType = 0;			
+				pTSInfo->field.ucTSID = UP;			
+				pTSInfo->field.ucDirection = Dir;			
+				pTSInfo->field.ucAccessPolicy = 1;		
+				pTSInfo->field.ucAggregation = 0; 		
+				pTSInfo->field.ucPSB = 0; 				
+				pTSInfo->field.ucUP = UP;				
+				pTSInfo->field.ucTSInfoAckPolicy = 0;		
+				pTSInfo->field.ucSchedule = 0;			
+					
+				MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
+				AdmitTS(ieee, *ppTS, 0);
+				list_add_tail(&((*ppTS)->List), pAddmitList);
+
+				return true;
+			}
+			else
+			{
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!in function %s() There is not enough dir=%d(0=up down=1) TS record to be used!!", __FUNCTION__,Dir);
+				return false;
+			}		
+		}		
+	}
+}
+
+void RemoveTsEntry(
+	struct rtllib_device*	ieee,
+	PTS_COMMON_INFO			pTs,
+	TR_SELECT			TxRxSelect
+	)
+{
+	unsigned long flags = 0;
+	del_timer_sync(&pTs->SetupTimer);
+	del_timer_sync(&pTs->InactTimer);
+	TsInitDelBA(ieee, pTs, TxRxSelect);
+
+	if(TxRxSelect == RX_DIR)
+	{
+		PRX_REORDER_ENTRY	pRxReorderEntry;
+		PRX_TS_RECORD 		pRxTS = (PRX_TS_RECORD)pTs;
+		spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+
+		if(timer_pending(&pRxTS->RxPktPendingTimer))	
+			del_timer_sync(&pRxTS->RxPktPendingTimer);
+
+		while(!list_empty(&pRxTS->RxPendingPktList)){
+			pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
+			RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Delete SeqNum %d!\n",__FUNCTION__, pRxReorderEntry->SeqNum);
+			list_del_init(&pRxReorderEntry->List);
+			{
+				int i = 0;
+				struct rtllib_rxb * prxb = pRxReorderEntry->prxb;
+				if (unlikely(!prxb)){
+					spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+					return;
+				}
+				for(i =0; i < prxb->nr_subframes; i++) {
+					dev_kfree_skb(prxb->subframes[i]);
+				}
+				kfree(prxb);
+				prxb = NULL;
+			}
+			list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
+		}
+		spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+	}
+	else{
+		PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
+		del_timer_sync(&pTxTS->TsAddBaTimer);
+	}
+}
+
+void RemovePeerTS(struct rtllib_device* ieee, u8* Addr)
+{
+	PTS_COMMON_INFO	pTS, pTmpTS;
+	printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+#if 1
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
+	{
+		if (memcmp(pTS->Addr, Addr, 6) == 0)
+		{
+			RemoveTsEntry(ieee, pTS, TX_DIR);
+			list_del_init(&pTS->List);
+			list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+		}
+	}
+	
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
+	{
+		if (memcmp(pTS->Addr, Addr, 6) == 0)
+		{
+			printk("====>remove Tx_TS_admin_list\n");
+			RemoveTsEntry(ieee, pTS, TX_DIR);
+			list_del_init(&pTS->List);
+			list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+		}
+	}
+	
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
+	{
+		if (memcmp(pTS->Addr, Addr, 6) == 0)
+		{
+			RemoveTsEntry(ieee, pTS, RX_DIR);
+			list_del_init(&pTS->List);
+			list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+		}
+	}
+
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
+	{
+		if (memcmp(pTS->Addr, Addr, 6) == 0)
+		{
+			RemoveTsEntry(ieee, pTS, RX_DIR);
+			list_del_init(&pTS->List);
+			list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+		}
+	}
+#endif
+}
+
+void RemoveAllTS(struct rtllib_device* ieee)
+{
+	PTS_COMMON_INFO pTS, pTmpTS;
+#if 1	
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
+	{
+		RemoveTsEntry(ieee, pTS, TX_DIR);
+		list_del_init(&pTS->List);
+		list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);	
+	}
+
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
+	{
+		RemoveTsEntry(ieee, pTS, TX_DIR);
+		list_del_init(&pTS->List);
+		list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+	}
+	
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
+	{
+		RemoveTsEntry(ieee, pTS, RX_DIR);
+		list_del_init(&pTS->List);
+		list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+	}
+
+	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
+	{
+		RemoveTsEntry(ieee, pTS, RX_DIR);
+		list_del_init(&pTS->List);
+		list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+	}
+#endif
+}
+
+void TsStartAddBaProcess(struct rtllib_device* ieee, PTX_TS_RECORD	pTxTS)
+{
+	if(pTxTS->bAddBaReqInProgress == false)
+	{
+		pTxTS->bAddBaReqInProgress = true;
+#if 1
+		if(pTxTS->bAddBaReqDelayed)
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
+			mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY));
+		}
+		else
+		{
+			RTLLIB_DEBUG(RTLLIB_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
+			mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); 
+		}
+#endif
+	}
+	else
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(RemovePeerTS);
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(ResetAdmitTRStream);
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_softmac.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_softmac.c
@@ -0,0 +1,5255 @@
+/* IEEE 802.11 SoftMAC layer
+ * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Mostly extracted from the rtl8180-sa2400 driver for the 
+ * in-kernel generic ieee802.11 stack.
+ *
+ * Few lines might be stolen from other part of the rtllib
+ * stack. Copyright who own it's copyright
+ *
+ * WPA code stolen from the ipw2200 driver.
+ * Copyright who own it's copyright. 
+ *
+ * released under the GPL
+ */
+
+
+#include "rtllib.h"
+
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#ifdef ENABLE_DOT11D
+#include "dot11d.h"
+#endif
+
+#ifdef RTK_DMP_PLATFORM
+#include <linux/usb_setting.h> 
+#endif
+extern void _setup_timer( struct timer_list*, void*, unsigned long );
+u8 rsn_authen_cipher_suite[16][4] = {
+	{0x00,0x0F,0xAC,0x00}, 
+	{0x00,0x0F,0xAC,0x01}, 
+	{0x00,0x0F,0xAC,0x02}, 
+	{0x00,0x0F,0xAC,0x03}, 
+	{0x00,0x0F,0xAC,0x04}, 
+	{0x00,0x0F,0xAC,0x05}, 
+};
+
+short rtllib_is_54g(struct rtllib_network *net)
+{
+	return ((net->rates_ex_len > 0) || (net->rates_len > 4));
+}
+
+short rtllib_is_shortslot(struct rtllib_network net)
+{
+	return (net.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME);
+}
+
+/* returns the total length needed for pleacing the RATE MFIE
+ * tag and the EXTENDED RATE MFIE tag if needed.
+ * It encludes two bytes per tag for the tag itself and its len
+ */
+unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee)
+{
+	unsigned int rate_len = 0;
+	
+	if (ieee->modulation & RTLLIB_CCK_MODULATION)
+		rate_len = RTLLIB_CCK_RATE_LEN + 2;
+		
+	if (ieee->modulation & RTLLIB_OFDM_MODULATION)
+		
+		rate_len += RTLLIB_OFDM_RATE_LEN + 2;
+	
+	return rate_len;
+}
+
+/* pleace the MFIE rate, tag to the memory (double) poined. 
+ * Then it updates the pointer so that
+ * it points after the new MFIE tag added.
+ */  
+void rtllib_MFIE_Brate(struct rtllib_device *ieee, u8 **tag_p)
+{
+	u8 *tag = *tag_p; 
+	
+	if (ieee->modulation & RTLLIB_CCK_MODULATION){
+		*tag++ = MFIE_TYPE_RATES;
+		*tag++ = 4;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB;
+	}
+	
+	/* We may add an option for custom rates that specific HW might support */
+	*tag_p = tag;
+}
+
+void rtllib_MFIE_Grate(struct rtllib_device *ieee, u8 **tag_p)
+{	
+	u8 *tag = *tag_p; 
+	
+		if (ieee->modulation & RTLLIB_OFDM_MODULATION){
+		
+		*tag++ = MFIE_TYPE_RATES_EX;
+		*tag++ = 8;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB;
+		*tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB;
+		
+	}
+	
+	/* We may add an option for custom rates that specific HW might support */
+	*tag_p = tag;
+}
+
+void rtllib_WMM_Info(struct rtllib_device *ieee, u8 **tag_p) {
+	u8 *tag = *tag_p;
+
+	*tag++ = MFIE_TYPE_GENERIC; 
+	*tag++ = 7;
+	*tag++ = 0x00;
+	*tag++ = 0x50;
+	*tag++ = 0xf2;
+	*tag++ = 0x02;
+	*tag++ = 0x00;
+	*tag++ = 0x01;
+#ifdef SUPPORT_USPD	
+	if(ieee->current_network.wmm_info & 0x80) {
+		*tag++ = 0x0f|MAX_SP_Len;
+	} else {
+		*tag++ = MAX_SP_Len;
+	}
+#else 
+	*tag++ = MAX_SP_Len;
+#endif
+	*tag_p = tag;
+}
+
+#ifdef THOMAS_TURBO
+void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p) {
+	u8 *tag = *tag_p;
+
+        *tag++ = MFIE_TYPE_GENERIC; 
+        *tag++ = 7;
+        *tag++ = 0x00;
+        *tag++ = 0xe0;
+        *tag++ = 0x4c;
+        *tag++ = 0x01;
+        *tag++ = 0x02;
+        *tag++ = 0x11;
+	*tag++ = 0x00;
+
+	*tag_p = tag;
+	printk(KERN_ALERT "This is enable turbo mode IE process\n");
+}
+#endif
+
+void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+	int nh;
+	nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
+			
+/*
+ * if the queue is full but we have newer frames then
+ * just overwrites the oldest.
+ *	
+ * if (nh == ieee->mgmt_queue_tail)
+ *		return -1;
+ */		
+	ieee->mgmt_queue_head = nh;
+	ieee->mgmt_queue_ring[nh] = skb;
+	
+}
+
+struct sk_buff *dequeue_mgmt(struct rtllib_device *ieee)
+{
+	struct sk_buff *ret;
+	
+	if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
+		return NULL;
+		
+	ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
+	
+	ieee->mgmt_queue_tail = 
+		(ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
+	
+	return ret;
+}
+
+void init_mgmt_queue(struct rtllib_device *ieee)
+{
+	ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
+}
+
+
+u8
+MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee)
+{
+	u16	i;
+	u8	QueryRate = 0;
+	u8	BasicRate;
+
+	
+	for( i = 0; i < ieee->current_network.rates_len; i++)
+	{
+		BasicRate = ieee->current_network.rates[i]&0x7F;
+		if(!rtllib_is_cck_rate(BasicRate))
+		{
+			if(QueryRate == 0)
+			{
+				QueryRate = BasicRate;
+			}
+			else
+			{
+				if(BasicRate < QueryRate)
+				{
+					QueryRate = BasicRate;
+				}
+			}
+		}		
+	}
+
+	if(QueryRate == 0)
+	{
+		QueryRate = 12;	
+		printk("No BasicRate found!!\n");
+	}
+	return QueryRate;
+}
+
+u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee)
+{
+	PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
+	u8 rate;
+
+#if defined RTL8190P || defined RTL8192E || defined RTL8192U
+	if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
+		rate = 0x0c;    
+	else
+		rate = ieee->basic_rate & 0x7f;
+#elif defined RTL8192SE || defined RTL8192SU || defined RTL8192CE
+	if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+	{
+		rate = MgntQuery_TxRateExcludeCCKRates(ieee);
+	}
+	else
+		rate = ieee->basic_rate & 0x7f;
+#endif
+
+	if(rate == 0){
+		if(ieee->mode == IEEE_A||
+		   ieee->mode== IEEE_N_5G||
+		   (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
+			rate = 0x0c;
+		else
+			rate = 0x02;
+	}
+
+	/*
+	if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
+	{
+	if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
+	rate = 0x0c;
+	else
+	rate = 0x02;
+	}
+	 */
+	return rate;
+}
+
+
+void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
+
+inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee)
+{
+	unsigned long flags;
+	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
+	struct rtllib_hdr_3addr  *header=
+		(struct rtllib_hdr_3addr  *) skb->data;
+
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	/* called with 2nd param 0, no mgmt lock required */
+	rtllib_sta_wakeup(ieee,0);
+	
+	tcb_desc->queue_index = MGNT_QUEUE;
+#ifdef RTL8192CE
+	tcb_desc->queue_index = MGNT_QUEUE;
+#endif
+
+	if(ieee->disable_mgnt_queue)
+		tcb_desc->queue_index = HIGH_QUEUE;
+	
+	tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);	
+	tcb_desc->RATRIndex = 7;
+	tcb_desc->bTxDisableRateFallBack = 1;
+	tcb_desc->bTxUseDriverAssingedRate = 1;
+#ifdef _RTL8192_EXT_PATCH_
+	tcb_desc->macId = 0;
+#endif	
+	if(single){
+		if(ieee->queue_stop){
+			enqueue_mgmt(ieee,skb);
+		}else{
+			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
+
+			if (ieee->seq_ctrl[0] == 0xFFF)
+				ieee->seq_ctrl[0] = 0;
+			else
+				ieee->seq_ctrl[0]++;
+			
+			/* avoid watchdog triggers */
+			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
+		}
+		
+		spin_unlock_irqrestore(&ieee->lock, flags);
+	}else{
+		spin_unlock_irqrestore(&ieee->lock, flags);
+		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
+
+		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+		if (ieee->seq_ctrl[0] == 0xFFF)
+			ieee->seq_ctrl[0] = 0;
+		else
+			ieee->seq_ctrl[0]++;
+
+		/* check wether the managed packet queued greater than 5 */
+		if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
+				(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
+				(ieee->queue_stop) ) {
+			/* insert the skb packet to the management queue */
+			/* as for the completion function, it does not need 
+			 * to check it any more.
+			 * */
+			printk("%s():insert to waitqueue, queue_index:%d!\n",__FUNCTION__,tcb_desc->queue_index);
+			skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
+		} else {
+			ieee->softmac_hard_start_xmit(skb,ieee->dev);
+		}
+		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
+	}
+}
+
+inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, 
+		struct rtllib_device *ieee)
+{
+	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
+	struct rtllib_hdr_3addr  *header =
+		(struct rtllib_hdr_3addr  *) skb->data;
+	u16 fc,type,stype;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
+
+	fc = header->frame_ctl;
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+
+
+	if(stype != RTLLIB_STYPE_PSPOLL) 
+		tcb_desc->queue_index = MGNT_QUEUE;
+	else
+		tcb_desc->queue_index = HIGH_QUEUE;
+
+	if(ieee->disable_mgnt_queue)
+		tcb_desc->queue_index = HIGH_QUEUE;
+		
+#ifdef RTL8192CE
+	tcb_desc->queue_index = MGNT_QUEUE;
+#endif
+
+	tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
+	tcb_desc->RATRIndex = 7;
+	tcb_desc->bTxDisableRateFallBack = 1;
+	tcb_desc->bTxUseDriverAssingedRate = 1;
+	if (single) {
+		if (type != RTLLIB_FTYPE_CTL) {
+			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+			if (ieee->seq_ctrl[0] == 0xFFF)
+				ieee->seq_ctrl[0] = 0;
+			else
+				ieee->seq_ctrl[0]++;
+
+		}
+		/* avoid watchdog triggers */
+		ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
+
+	} else {
+		if (type != RTLLIB_FTYPE_CTL) {
+			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+			if (ieee->seq_ctrl[0] == 0xFFF)
+				ieee->seq_ctrl[0] = 0;
+			else
+				ieee->seq_ctrl[0]++;
+		}
+		ieee->softmac_hard_start_xmit(skb,ieee->dev);
+
+	}
+}
+
+inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee)
+{
+	unsigned int len,rate_len;
+	u8 *tag;
+	struct sk_buff *skb;
+	struct rtllib_probe_request *req;
+	
+#ifdef _RTL8192_EXT_PATCH_
+	short extMore = 0;
+	if(ieee->ext_patch_rtllib_probe_req_1)
+		extMore = ieee->ext_patch_rtllib_probe_req_1(ieee);
+#endif
+
+	len = ieee->current_network.ssid_len;
+	
+	rate_len = rtllib_MFIE_rate_len(ieee);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if(!extMore)
+		skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+			    2 + len + rate_len + ieee->tx_headroom);
+	else
+		skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+			    2 + len + rate_len+128+ieee->tx_headroom); 
+#else
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr;
+        int alignment;
+        skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+                            2 + len + rate_len + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+			    2 + len + rate_len + ieee->tx_headroom);
+#endif
+#endif
+
+	if (!skb) 
+		return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	req = (struct rtllib_probe_request *) skb_put(skb,sizeof(struct rtllib_probe_request));
+	req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ);
+	req->header.duration_id = 0; 
+	
+	memset(req->header.addr1, 0xff, ETH_ALEN);
+	memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memset(req->header.addr3, 0xff, ETH_ALEN);
+	
+	tag = (u8 *) skb_put(skb,len+2+rate_len);
+	
+	*tag++ = MFIE_TYPE_SSID;
+	*tag++ = len;
+	memcpy(tag, ieee->current_network.ssid, len);
+	tag += len;
+	
+	rtllib_MFIE_Brate(ieee,&tag);
+	rtllib_MFIE_Grate(ieee,&tag);
+
+#ifdef _RTL8192_EXT_PATCH_
+	if(extMore)
+		ieee->ext_patch_rtllib_probe_req_2(ieee, skb, tag);
+#endif
+
+	return skb;
+}
+
+struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
+
+#ifdef _RTL8192_EXT_PATCH_
+void ext_rtllib_send_beacon_wq(void *data)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl((struct work_struct *)data, struct rtllib_device, ext_send_beacon_wq);
+	struct sk_buff *skb;
+	
+	skb = rtllib_get_beacon_(ieee);
+
+	if (skb){
+		softmac_mgmt_xmit(skb, ieee);
+		ieee->softmac_stats.tx_beacons++;
+	}
+	
+
+	
+}
+#endif
+void rtllib_send_beacon(struct rtllib_device *ieee)
+{
+	struct sk_buff *skb;
+	if(!ieee->ieee_up)
+		return;		
+	skb = rtllib_get_beacon_(ieee);
+	
+	if (skb){
+		softmac_mgmt_xmit(skb, ieee);
+		ieee->softmac_stats.tx_beacons++;
+	}
+	
+	if(ieee->beacon_txing && ieee->ieee_up){
+		mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
+	}
+}
+
+
+void rtllib_send_beacon_cb(unsigned long _ieee)
+{
+	struct rtllib_device *ieee =
+		(struct rtllib_device *) _ieee;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->beacon_lock, flags);
+	rtllib_send_beacon(ieee);
+	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+
+inline struct sk_buff *rtllib_probe_req_with_SSID(struct rtllib_device *ieee, char *ssid, int len_ssid)
+{
+	unsigned int len,rate_len;
+	u8 *tag;
+	struct sk_buff *skb;
+	struct rtllib_probe_request *req;
+	
+#ifdef _RTL8192_EXT_PATCH_
+	short extMore = 0;
+	if(ieee->ext_patch_rtllib_probe_req_1)
+		extMore = ieee->ext_patch_rtllib_probe_req_1(ieee);
+#endif
+
+	len = len_ssid;
+	
+	rate_len = rtllib_MFIE_rate_len(ieee);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if(!extMore)
+#endif
+		skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+			    2 + len + rate_len + ieee->tx_headroom);
+#ifdef _RTL8192_EXT_PATCH_
+	else
+		skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+			    2 + len + rate_len+128+ieee->tx_headroom); 
+#endif
+	
+	if (!skb) 
+		return NULL;
+	
+	req = (struct rtllib_probe_request *) skb_put(skb,sizeof(struct rtllib_probe_request));
+	req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ);
+	req->header.duration_id = 0; 
+	
+	memset(req->header.addr1, 0xff, ETH_ALEN);
+	memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memset(req->header.addr3, 0xff, ETH_ALEN);
+	
+	tag = (u8 *) skb_put(skb,len+2+rate_len);
+	
+	*tag++ = MFIE_TYPE_SSID;
+	*tag++ = len;
+	if(len)
+	{
+		memcpy(tag, ssid, len);
+		tag += len;
+	}
+	
+	rtllib_MFIE_Brate(ieee,&tag);
+	rtllib_MFIE_Grate(ieee,&tag);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if(extMore)
+		ieee->ext_patch_rtllib_probe_req_2(ieee, skb, tag);
+#endif
+	return skb;
+}
+
+#endif 
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+void rtllib_ibss_wait_timeout(unsigned long _ieee)
+{
+	struct rtllib_device *ieee =
+		(struct rtllib_device *) _ieee;
+	printk("======>%s():oh oh ibss wait beacon time out, search a new ibss now\n",__FUNCTION__);	
+	rtllib_stop_send_beacons(ieee);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	cancel_delayed_work(&ieee->start_ibss_wq);
+	cancel_delayed_work(&ieee->link_change_wq);
+#endif	
+	rtllib_stop_scan(ieee);
+	queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq, MSECS(150)); 
+}
+#endif
+
+
+/*
+ * Description:
+ *              Enable network monitor mode, all rx packets will be received.
+ */
+void rtllib_EnableNetMonitorMode(struct net_device* dev,
+                bool bInitState)
+{
+        struct rtllib_device* ieee = netdev_priv_rsl(dev);
+
+        printk("========>Enter Monitor Mode\n");
+
+        ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
+}
+
+
+/*
+ *      Description:
+ *              Disable network network monitor mode, only packets destinated to
+ *              us will be received.
+ */
+void rtllib_DisableNetMonitorMode(struct net_device* dev,
+                bool bInitState)
+{
+	struct rtllib_device* ieee = netdev_priv_rsl(dev);
+
+        printk("========>Exit Monitor Mode\n");
+
+        ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
+}
+
+
+/*
+ * Description:
+ *              This enables the specialized promiscuous mode required by Intel.
+ *              In this mode, Intel intends to hear traffics from/to other STAs in the same BSS.
+ *              Therefore we don't have to disable checking BSSID and we only need to allow all dest.
+ *              BUT: if we enable checking BSSID then we can't recv packets from other STA.
+ */
+void rtllib_EnableIntelPromiscuousMode(struct net_device* dev,
+                bool bInitState)
+{
+        bool bFilterOutNonAssociatedBSSID = false;
+
+	struct rtllib_device* ieee = netdev_priv_rsl(dev);
+
+        printk("========>Enter Intel Promiscuous Mode\n");
+
+        ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
+        ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)&bFilterOutNonAssociatedBSSID);
+
+        ieee->bNetPromiscuousMode = true;
+}
+
+
+/*
+ * Description:
+ *              This disables the specialized promiscuous mode required by Intel.
+ *              See MgntEnableIntelPromiscuousMode for detail.
+ */
+void rtllib_DisableIntelPromiscuousMode(struct net_device* dev,
+                bool bInitState)
+{
+        bool bFilterOutNonAssociatedBSSID = true;
+
+	struct rtllib_device* ieee = netdev_priv_rsl(dev);
+
+        printk("========>Exit Intel Promiscuous Mode\n");
+
+        ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
+        ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)&bFilterOutNonAssociatedBSSID);
+
+        ieee->bNetPromiscuousMode = false;
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh)
+#else
+void rtllib_send_probe(struct rtllib_device *ieee)
+#endif
+{
+	struct sk_buff *skb;
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh) 
+		skb = rtllib_probe_req_with_SSID(ieee, NULL, 0);
+	else
+#endif
+	skb = rtllib_probe_req(ieee);
+	if (skb){
+		softmac_mgmt_xmit(skb, ieee);
+		ieee->softmac_stats.tx_probe_rq++;
+	}
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
+{
+	if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
+		rtllib_send_probe(ieee,is_mesh);
+		rtllib_send_probe(ieee,is_mesh);
+	}
+}
+#else
+void rtllib_send_probe_requests(struct rtllib_device *ieee)
+{
+	if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
+		rtllib_send_probe(ieee);
+		rtllib_send_probe(ieee);
+	}
+}
+#endif
+
+void rtllib_softmac_hint11d_wq(void *data)
+{
+#ifdef CONFIG_CRDA 
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, softmac_hint11d_wq);
+	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
+	struct wireless_dev *wdev = &ieee->wdev;
+
+   	regulatory_hint_11d(wdev->wiphy, pDot11dInfo->CountryIeBuf, pDot11dInfo->CountryIeLen);
+#endif
+}
+
+void rtllib_update_active_chan_map(struct rtllib_device *ieee)
+{
+#ifdef ENABLE_DOT11D
+	memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
+#else
+	memcpy(ieee->active_channel_map, ieee->channel_map, MAX_CHANNEL_NUMBER+1);
+#endif
+#if 0
+	{
+		int i;
+		for(i=1;i<=14;i++)
+			printk("%d ", ieee->active_channel_map[i]);
+		printk("\n");
+	}
+#endif
+}
+
+/* this performs syncro scan blocking the caller until all channels
+ * in the allowed channel map has been checked. 
+ */
+void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+{
+	short ch = 0;
+
+	rtllib_update_active_chan_map(ieee);
+
+	ieee->be_scan_inprogress = true;
+
+	down(&ieee->scan_sem);
+	
+	while(1)
+	{
+		
+		do {
+			ch++;
+			if (ch > MAX_CHANNEL_NUMBER) 
+				goto out; /* scan completed */
+		} while(!ieee->active_channel_map[ch]);
+	
+		/* this fuction can be called in two situations
+		 * 1- We have switched to ad-hoc mode and we are
+		 *    performing a complete syncro scan before conclude
+		 *    there are no interesting cell and to create a 
+		 *    new one. In this case the link state is 
+		 *    RTLLIB_NOLINK until we found an interesting cell.
+		 *    If so the ieee8021_new_net, called by the RX path
+		 *    will set the state to RTLLIB_LINKED, so we stop
+		 *    scanning
+		 * 2- We are linked and the root uses run iwlist scan.
+		 *    So we switch to RTLLIB_LINKED_SCANNING to remember
+		 *    that we are still logically linked (not interested in
+		 *    new network events, despite for updating the net list,
+		 *    but we are temporarly 'unlinked' as the driver shall
+		 *    not filter RX frames and the channel is changing.
+		 * So the only situation in witch are interested is to check
+		 * if the state become LINKED because of the #1 situation
+		 */    
+		    
+		if (ieee->state == RTLLIB_LINKED)
+			goto out;
+		if (ieee->sync_scan_hurryup){
+			printk("============>sync_scan_hurryup out\n");
+			goto out;
+		}
+
+		ieee->set_chan(ieee->dev, ch);
+		if(ieee->active_channel_map[ch] == 1)
+#ifdef _RTL8192_EXT_PATCH_
+		rtllib_send_probe_requests(ieee, is_mesh);
+#else
+		rtllib_send_probe_requests(ieee);
+#endif
+		
+		/* this prevent excessive time wait when we
+		 * need to wait for a syncro scan to end..
+		 */  		
+		msleep_interruptible_rsl(RTLLIB_SOFTMAC_SCAN_TIME);
+	}
+out:
+	ieee->actscanning = false;
+	ieee->sync_scan_hurryup = 0;
+
+	if(ieee->state >= RTLLIB_LINKED){
+#ifdef ENABLE_DOT11D
+		if(IS_DOT11D_ENABLE(ieee))
+			DOT11D_ScanComplete(ieee);
+#endif	
+	}
+	up(&ieee->scan_sem);
+	
+	ieee->be_scan_inprogress = false;
+
+#ifndef FOR_MOBLIN
+	{
+	union iwreq_data wrqu;
+	memset(&wrqu, 0, sizeof(wrqu));
+	wireless_send_event(ieee->dev,SIOCGIWSCAN,&wrqu,NULL);
+	}
+#endif
+}
+
+void rtllib_softmac_scan_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, softmac_scan_wq);
+
+#ifndef _RTL8192_EXT_PATCH_
+	u8 last_channel = ieee->current_network.channel; 
+#endif
+	rtllib_update_active_chan_map(ieee);
+
+	if(!ieee->ieee_up)
+		return;	
+	if(rtllib_act_scanning(ieee,true) == true)
+		return;
+
+	down(&ieee->scan_sem);
+
+	if(ieee->eRFPowerState == eRfOff)
+	{
+		printk("======>%s():rf state is eRfOff, return\n",__FUNCTION__);
+		goto out1;
+	}
+
+	do{
+		ieee->current_network.channel = 
+			(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
+		if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER) 
+		{
+			if (!ieee->active_channel_map[ieee->current_network.channel])
+				ieee->current_network.channel = 6;
+			goto out; /* no good chans */
+		}
+	} while(!ieee->active_channel_map[ieee->current_network.channel]);
+
+	if (ieee->scanning_continue == 0 )
+		goto out;
+
+	ieee->set_chan(ieee->dev, ieee->current_network.channel);
+
+	if(ieee->active_channel_map[ieee->current_network.channel] == 1)
+#ifdef _RTL8192_EXT_PATCH_
+	rtllib_send_probe_requests(ieee, 0);
+#else
+	rtllib_send_probe_requests(ieee);
+#endif				
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40)
+	queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq, MSECS(RTLLIB_SOFTMAC_SCAN_TIME));
+#else
+	if (ieee->scanning_continue == 1) 
+		mod_timer(&ieee->scan_timer,(jiffies + MSECS(RTLLIB_SOFTMAC_SCAN_TIME)));
+#endif
+
+	up(&ieee->scan_sem);
+	return;
+	
+out:
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee))
+		DOT11D_ScanComplete(ieee);
+#endif	
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->current_network.channel = ieee->backup_channel;
+	ieee->set_chan(ieee->dev, ieee->current_network.channel);
+#else
+	ieee->current_network.channel = last_channel;
+#endif
+
+out1:
+	ieee->actscanning = false;
+	ieee->scan_watch_dog = 0;
+	ieee->scanning_continue = 0;
+	up(&ieee->scan_sem);
+}
+
+
+
+void rtllib_beacons_start(struct rtllib_device *ieee)
+{
+	unsigned long flags;	
+	spin_lock_irqsave(&ieee->beacon_lock,flags);
+
+	ieee->beacon_txing = 1;
+	rtllib_send_beacon(ieee);
+	
+	spin_unlock_irqrestore(&ieee->beacon_lock,flags);
+}
+
+void rtllib_beacons_stop(struct rtllib_device *ieee)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ieee->beacon_lock,flags);
+
+	ieee->beacon_txing = 0;
+ 	del_timer_sync(&ieee->beacon_timer);
+
+	spin_unlock_irqrestore(&ieee->beacon_lock,flags);
+
+}
+
+
+void rtllib_stop_send_beacons(struct rtllib_device *ieee)
+{
+	if(ieee->stop_send_beacons)
+		ieee->stop_send_beacons(ieee->dev);
+	if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
+		rtllib_beacons_stop(ieee);
+}
+
+
+void rtllib_start_send_beacons(struct rtllib_device *ieee)
+{
+	if(ieee->start_send_beacons)
+		ieee->start_send_beacons(ieee->dev);
+	if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
+		rtllib_beacons_start(ieee); 
+}
+
+
+void rtllib_softmac_stop_scan(struct rtllib_device *ieee)
+{
+	
+	
+	down(&ieee->scan_sem);
+	ieee->scan_watch_dog = 0;
+	if (ieee->scanning_continue == 1){
+		ieee->scanning_continue = 0;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67)
+		cancel_delayed_work(&ieee->softmac_scan_wq);
+#endif
+#else
+		del_timer_sync(&ieee->scan_timer);
+#endif
+	}
+	
+	up(&ieee->scan_sem);
+}
+
+void rtllib_stop_scan(struct rtllib_device *ieee)
+{
+	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
+		rtllib_softmac_stop_scan(ieee);
+	}else{
+		if(ieee->rtllib_stop_hw_scan)
+			ieee->rtllib_stop_hw_scan(ieee->dev);
+	}
+}
+
+void rtllib_stop_scan_syncro(struct rtllib_device *ieee)
+{
+	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
+			ieee->sync_scan_hurryup = 1;
+	}else{
+		if(ieee->rtllib_stop_hw_scan)
+			ieee->rtllib_stop_hw_scan(ieee->dev);
+	}
+}
+
+bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan)
+{
+	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
+		if(sync_scan){ 
+			return ieee->be_scan_inprogress;
+		}else{
+			return (ieee->actscanning ||ieee->be_scan_inprogress);
+		}
+	}else{
+		return test_bit(STATUS_SCANNING, &ieee->status);
+	}
+}
+
+/* called with ieee->lock held */
+void rtllib_start_scan(struct rtllib_device *ieee)
+{
+	printk("===>%s()\n",__FUNCTION__);
+#ifdef ENABLE_IPS
+	if(ieee->rtllib_ips_leave_wq != NULL)
+	ieee->rtllib_ips_leave_wq(ieee->dev);
+#endif
+
+
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee) )
+	{			
+		if(IS_COUNTRY_IE_VALID(ieee))
+		{
+			RESET_CIE_WATCHDOG(ieee); 
+		}
+	}
+#endif
+	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){	
+		if (ieee->scanning_continue == 0){
+			ieee->actscanning = true;
+			ieee->scanning_continue = 1;
+#ifdef _RTL8192_EXT_PATCH_
+			ieee->backup_channel = ieee->current_network.channel;
+			printk("===>backup_channel is %d\n",ieee->backup_channel);
+#endif
+			queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq, 0);
+		}
+	}else{
+		if(ieee->rtllib_start_hw_scan)
+			ieee->rtllib_start_hw_scan(ieee->dev);
+	}
+	
+}
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40)	
+void rtllib_softmac_scan_cb(unsigned long _dev)
+{
+	unsigned long flags;
+	struct rtllib_device *ieee = (struct rtllib_device *)_dev;
+	
+	spin_lock_irqsave(&ieee->lock, flags);
+	rtllib_start_scan(ieee);
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+#endif
+
+/* called with wx_sem held */
+void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+{
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee) )
+	{			
+		if(IS_COUNTRY_IE_VALID(ieee))
+		{
+			RESET_CIE_WATCHDOG(ieee); 
+		}
+	}
+#endif
+	ieee->sync_scan_hurryup = 0;
+	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
+		rtllib_softmac_scan_syncro(ieee, is_mesh);
+	}else{
+		if(ieee->rtllib_start_hw_scan)
+			ieee->rtllib_start_hw_scan(ieee->dev);
+	}
+		
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, 
+	struct rtllib_device *ieee, int challengelen,u8 * daddr)
+#else
+inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, 
+	struct rtllib_device *ieee, int challengelen)
+#endif
+{
+	struct sk_buff *skb;	
+	struct rtllib_authentication *auth;
+	int  len = 0;
+#ifdef _RTL8192_EXT_PATCH_
+	bool is_mesh = false;
+	is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,daddr);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	if((ieee->mesh_sec_type == 1) && (ieee->mesh_security_setting == 3) && is_mesh){
+		skb = ieee->ext_patch_rtllib_send_ath_commit(ieee,daddr);
+		return skb;
+	}
+#endif
+	len = sizeof(struct rtllib_authentication) + challengelen + ieee->tx_headroom + 4;
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr;
+        int alignment;
+        skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE);
+#else
+	skb = dev_alloc_skb(len); 
+#endif
+
+	if (!skb) return NULL;
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	auth = (struct rtllib_authentication *)
+		skb_put(skb, sizeof(struct rtllib_authentication));
+	
+	auth->header.frame_ctl = RTLLIB_STYPE_AUTH;
+	if (challengelen) auth->header.frame_ctl |= RTLLIB_FCTL_WEP;
+	
+	auth->header.duration_id = 0x013a; 
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		memcpy(auth->header.addr1,daddr,ETH_ALEN);
+	else
+#endif
+		memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
+	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		memcpy(auth->header.addr3, ieee->current_mesh_network.bssid, ETH_ALEN); 
+	else
+		memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
+#else
+	memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
+#endif	
+	if(ieee->auth_mode == 0)
+		auth->algorithm = WLAN_AUTH_OPEN;
+	else if(ieee->auth_mode == 1)
+		auth->algorithm = WLAN_AUTH_SHARED_KEY;
+	else if(ieee->auth_mode == 2)
+		auth->algorithm = WLAN_AUTH_OPEN;
+	auth->transaction = cpu_to_le16(ieee->associate_seq);
+	ieee->associate_seq++;
+	
+	auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
+	
+	return skb;
+	
+}
+
+void constructWMMIE(u8* wmmie, u8* wmm_len,u8 oui_subtype)
+{
+	u8	szQoSOUI[] ={221, 0, 0x00, 0x50, 0xf2, 0x02, 0, 1};
+	
+	if (oui_subtype == OUI_SUBTYPE_QOS_CAPABI)
+	{
+		szQoSOUI[0] = 46;
+		szQoSOUI[1] = *wmm_len;
+		memcpy(wmmie,szQoSOUI,3);
+		*wmm_len = 3;
+	}	
+	else
+	{
+		szQoSOUI[1] = *wmm_len + 6;
+		szQoSOUI[6] = oui_subtype;
+		memcpy(wmmie, szQoSOUI, 8);
+		*(wmmie+8) = 0;
+		*wmm_len = 9;
+	}	
+}
+
+static struct sk_buff* rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest)
+{
+	u8 *tag;
+	int beacon_size;
+	struct rtllib_probe_response *beacon_buf;
+	struct sk_buff *skb = NULL;
+	int encrypt;
+	int atim_len,erp_len;
+	struct rtllib_crypt_data* crypt;
+	
+	char *ssid = ieee->current_network.ssid;
+	int ssid_len = ieee->current_network.ssid_len;
+	int rate_len = ieee->current_network.rates_len+2;
+	int rate_ex_len = ieee->current_network.rates_ex_len;
+	int wpa_ie_len = ieee->wpa_ie_len;
+	u8 erpinfo_content = 0;
+
+	u8* tmp_ht_cap_buf=NULL;
+	u8 tmp_ht_cap_len=0;
+	u8* tmp_ht_info_buf=NULL;
+	u8 tmp_ht_info_len=0;
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	u8* tmp_generic_ie_buf=NULL;
+	u8 tmp_generic_ie_len=0;
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	u8 wmmie[9] = {0};
+	u8 wmm_len = 0;
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo);
+	u8 pWapiIELen = 0;
+#endif
+	if(rate_ex_len > 0) rate_ex_len+=2;
+	
+	if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
+		atim_len = 4;
+	else
+		atim_len = 0;
+	
+#if 0
+	if(rtllib_is_54g(&ieee->current_network)) 
+		erp_len = 3;
+	else
+		erp_len = 0;
+#else
+      if((ieee->current_network.mode == IEEE_G) 
+	  	||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
+	  	erp_len = 3;
+		erpinfo_content = 0;
+		if(ieee->current_network.buseprotection)
+			erpinfo_content |= ERP_UseProtection;
+      	}
+	else
+		erp_len = 0;
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+	crypt = ieee->sta_crypt[ieee->tx_keyidx];
+#else
+	crypt = ieee->crypt[ieee->tx_keyidx];
+#endif	
+	encrypt = ieee->host_encrypt && crypt && crypt->ops && 
+		((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
+#if 1	
+	if(ieee->pHTInfo->bCurrentHTSupport){
+		tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
+		tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
+		tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
+		tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
+#ifdef _RTL8192_EXT_PATCH_
+		HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt, 1);
+#else
+		HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
+#endif	
+		HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
+		
+
+		if(pHTInfo->bRegRT2RTAggregation)
+		{
+			tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
+			tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
+			HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
+		}
+	}
+#endif
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(ieee->iw_mode == IW_MODE_ADHOC){
+		if(ieee->current_network.qos_data.supported){
+			wmm_len = 1;
+			constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO);
+		}else{
+			wmm_len = 0;
+		}
+	}
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	if(ieee->WapiSupport && pWapiInfo->bWapiEnable)
+	{
+		WapiSetIE(ieee);
+		pWapiIELen = pWapiInfo->wapiIELength;
+	}
+#endif
+	beacon_size = sizeof(struct rtllib_probe_response)+2+
+		ssid_len
+		+3 
+		+rate_len
+		+rate_ex_len
+		+atim_len
+		+erp_len
+		+wpa_ie_len
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+		+tmp_ht_cap_len
+		+tmp_ht_info_len
+		+tmp_generic_ie_len
+		+wmm_len
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+		+pWapiIELen+2
+#endif
+		+ieee->tx_headroom;
+#ifdef USB_USE_ALIGNMENT        
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(beacon_size + USB_512B_ALIGNMENT_SIZE);
+#else
+	skb = dev_alloc_skb(beacon_size);
+#endif
+	if (!skb) 
+		return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	beacon_buf = (struct rtllib_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
+	memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
+	memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
+
+	beacon_buf->header.duration_id = 0; 
+	beacon_buf->beacon_interval = 
+		cpu_to_le16(ieee->current_network.beacon_interval);
+	beacon_buf->capability = 
+		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
+	beacon_buf->capability |= 
+		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); 
+
+	if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
+		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME));		
+	
+#ifndef _RTL8192_EXT_PATCH_
+	crypt = ieee->crypt[ieee->tx_keyidx];
+#endif
+	if (encrypt)	
+		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+	
+		
+	beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP);
+	beacon_buf->info_element[0].id = MFIE_TYPE_SSID;	
+	beacon_buf->info_element[0].len = ssid_len;
+	
+	tag = (u8*) beacon_buf->info_element[0].data;
+	
+	memcpy(tag, ssid, ssid_len);
+	
+	tag += ssid_len;
+	
+	*(tag++) = MFIE_TYPE_RATES;
+	*(tag++) = rate_len-2; 
+	memcpy(tag,ieee->current_network.rates,rate_len-2);
+	tag+=rate_len-2;
+	
+	*(tag++) = MFIE_TYPE_DS_SET;
+	*(tag++) = 1;
+	*(tag++) = ieee->current_network.channel;
+	
+	if(atim_len){
+	u16 val16;
+		*(tag++) = MFIE_TYPE_IBSS_SET;
+		*(tag++) = 2;
+		 val16 = cpu_to_le16(ieee->current_network.atim_window);
+		memcpy((u8 *)tag, (u8 *)&val16, 2);
+		tag+=2;
+	}
+	
+	if(erp_len){
+		*(tag++) = MFIE_TYPE_ERP;
+		*(tag++) = 1;
+		*(tag++) = erpinfo_content; 
+	}
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(tmp_ht_cap_len){
+		*(tag++) = MFIE_TYPE_HT_CAP;
+		*(tag++) = tmp_ht_cap_len - 2;
+		memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);	
+		tag += tmp_ht_cap_len - 2;
+	}
+#endif
+	if(rate_ex_len){
+		*(tag++) = MFIE_TYPE_RATES_EX;
+		*(tag++) = rate_ex_len-2; 
+		memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
+		tag+=rate_ex_len-2;
+	}
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(tmp_ht_info_len){
+		*(tag++) = MFIE_TYPE_HT_INFO;
+		*(tag++) = tmp_ht_info_len - 2;
+		memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
+		tag += tmp_ht_info_len - 2;
+	}
+#endif
+	
+	if (wpa_ie_len)
+	{	
+		if (ieee->iw_mode == IW_MODE_ADHOC)
+		{
+			memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
+		}
+		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
+		tag += ieee->wpa_ie_len;
+	}
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(tmp_generic_ie_len)
+	{
+		(*tag++) = 0xdd;
+		(*tag++) = tmp_generic_ie_len - 2;
+		memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
+		tag += tmp_generic_ie_len -2;
+		
+	}
+#endif
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(wmm_len) {
+		memcpy(tag,wmmie,wmm_len);
+		tag += wmm_len;
+	}
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	if(pWapiIELen)
+	{
+		*(tag++) = MFIE_TYPE_WAPI;
+		*(tag++) = pWapiIELen;
+		memcpy(tag, pWapiInfo->wapiIE, pWapiIELen);
+		tag += pWapiIELen;
+
+		pWapiInfo->sendbeaconWapiIE[0] = MFIE_TYPE_WAPI;
+		pWapiInfo->sendbeaconWapiIE[1] = pWapiIELen;
+		pWapiInfo->sendbeaconWapiIELength = pWapiIELen+2;
+		memcpy(pWapiInfo->sendbeaconWapiIE+2,  pWapiInfo->wapiIE, pWapiIELen);
+	}
+#endif
+	return skb;
+}
+
+#ifdef RTL8192S_WAPI_SUPPORT
+void ConstructWapiIEForInit(struct rtllib_device* ieee)
+{
+	PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo);
+	u8 pWapiIELen = 0;
+
+	if(ieee->WapiSupport && pWapiInfo->bWapiEnable){
+		WapiSetIE(ieee);
+		pWapiIELen = pWapiInfo->wapiIELength;
+		if(pWapiIELen){
+			pWapiInfo->sendbeaconWapiIE[0] = MFIE_TYPE_WAPI;
+			pWapiInfo->sendbeaconWapiIE[1] = pWapiIELen;
+			pWapiInfo->sendbeaconWapiIELength = pWapiIELen+2;
+			memcpy(pWapiInfo->sendbeaconWapiIE+2,  pWapiInfo->wapiIE, pWapiIELen);
+		}
+	}
+}
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+extern void ConstructRalinkHostNameIE(struct rtllib_device* ieee, 
+		u8* p_hostname_ie, u8* hostname_ie_len);
+#else
+extern void ConstructHostNameIE(struct rtllib_device* ieee, 
+		u8* hostname_ie, u8* hostname_ie_len);
+#endif
+struct sk_buff* rtllib_ext_probe_resp_by_net(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net)
+{
+	u8 *tag;
+	int beacon_size;
+	struct rtllib_probe_response *beacon_buf;
+	struct sk_buff *skb;
+	int encrypt;
+	int atim_len = 0,erp_len = 0;
+	struct rtllib_crypt_data* crypt;
+	u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	
+	char *ssid = net->ssid;
+	int ssid_len = net->ssid_len;
+
+	int rate_len = ieee->current_mesh_network.rates_len+2;
+	int rate_ex_len = ieee->current_mesh_network.rates_ex_len;
+	int wpa_ie_len = 0;
+	u8 erpinfo_content = 0;
+#if 0
+	u8* tmp_ht_cap_buf=NULL;
+	u8 tmp_ht_cap_len=0;
+	u8* tmp_ht_info_buf=NULL;
+	u8 tmp_ht_info_len=0;
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	u8* tmp_generic_ie_buf=NULL;
+	u8 tmp_generic_ie_len=0;
+#endif
+	u8 wmmie[9] = {0};
+	u8 wmm_len = 0;
+	u8 hostname_ie_buf[MAX_HOST_NAME_LENGTH+4];
+	u8 hostname_ie_len=0;
+	if(rate_ex_len > 0) rate_ex_len+=2;
+	if( ieee->meshScanMode&4){
+		ieee->current_mesh_network.channel = ieee->ext_patch_rtllib_ext_stop_scan_wq_set_channel(ieee);
+		if(ieee->current_mesh_network.channel == 0)
+			ieee->current_mesh_network.channel = 1;
+	}
+	if( ieee->meshScanMode&6)
+	{
+		queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq);
+	}	
+	if(ieee->current_mesh_network.capability & WLAN_CAPABILITY_IBSS) 
+		atim_len = 4;
+	else
+		atim_len = 0;
+	
+	
+	if((ieee->current_mesh_network.mode == IEEE_G) 
+	  	||( ieee->mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)){ 
+		erp_len = 3;
+		erpinfo_content = 0;
+		if(ieee->bUseProtection)
+			erpinfo_content |= ERP_UseProtection;
+	}	
+	else
+		erp_len = 0;
+	
+	if ((IW_MODE_MESH==ieee->iw_mode))
+	{
+		wpa_ie_len = ieee->wpa_ie_len; 
+	}
+		
+	crypt = ieee->cryptlist[0]->crypt[ieee->mesh_txkeyidx];
+	
+	encrypt = ieee->host_encrypt && crypt && crypt->ops && 
+		((0 == strcmp(crypt->ops->name, "WEP")||wpa_ie_len));
+#if 0
+	if(ieee->pHTInfo->bCurrentHTSupport){
+		tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
+		tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
+		tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
+		tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
+		HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt, 1);
+		HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
+
+
+		if(pHTInfo->bRegRT2RTAggregation)
+		{
+			tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
+			tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
+			HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
+		}
+	}
+#endif
+	{
+#ifdef COMPATIBLE_WITH_RALINK_MESH		
+		ConstructRalinkHostNameIE(ieee, hostname_ie_buf, &hostname_ie_len);
+#else
+		ConstructHostNameIE(ieee, hostname_ie_buf, &hostname_ie_len);
+#endif
+	}
+	if((ieee->iw_mode == IW_MODE_MESH) && (ieee->current_mesh_network.qos_data.supported == 1)){
+		wmm_len = 1;
+		constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO);
+	}
+	beacon_size = sizeof(struct rtllib_probe_response)+2+
+		ssid_len
+		+3 
+		+rate_len
+		+rate_ex_len
+		+atim_len
+		+erp_len
+		+wpa_ie_len
+#if 0
+		+tmp_ht_cap_len
+		+tmp_ht_info_len
+		+tmp_generic_ie_len
+#endif
+		+hostname_ie_len
+		+wmm_len
+		+ieee->tx_headroom;
+	skb = dev_alloc_skb(beacon_size+300); 
+	
+	if (!skb) 
+ 		return NULL;
+	skb_reserve(skb, ieee->tx_headroom);
+	beacon_buf = (struct rtllib_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
+	
+	memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
+	memcpy (beacon_buf->header.addr2, ieee->meshdev->dev_addr, ETH_ALEN);
+	memcpy (beacon_buf->header.addr3, ieee->current_mesh_network.bssid, ETH_ALEN);
+
+	beacon_buf->header.duration_id = 0; 
+	
+	beacon_buf->beacon_interval = 
+		cpu_to_le16(ieee->current_mesh_network.beacon_interval);  
+	beacon_buf->capability = 
+		cpu_to_le16(ieee->current_mesh_network.capability & WLAN_CAPABILITY_IBSS);
+	
+	if(ieee->short_slot && (ieee->current_mesh_network.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
+		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME));		
+
+	if (encrypt)	
+		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+	
+		
+	beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP);
+	
+	beacon_buf->info_element[0].id = MFIE_TYPE_SSID;	
+	beacon_buf->info_element[0].len = ssid_len;
+	
+	tag = (u8*) beacon_buf->info_element[0].data;
+	
+	if(memcmp(dest, broadcast_addr, ETH_ALEN ))
+		memcpy(tag, ssid, ssid_len);	
+	else	
+		ssid_len=0;
+	
+	tag += ssid_len;
+	
+		
+	*(tag++) = MFIE_TYPE_RATES;
+	*(tag++) = rate_len-2; 
+	memcpy(tag,ieee->current_mesh_network.rates,rate_len-2);
+	tag+=rate_len-2;
+	
+	*(tag++) = MFIE_TYPE_DS_SET;
+	*(tag++) = 1;
+	*(tag++) = ieee->current_mesh_network.channel;  
+	
+	
+	if(atim_len){
+		u16 val16;
+		*(tag++) = MFIE_TYPE_IBSS_SET;
+		*(tag++) = 2;
+		 val16 = cpu_to_le16(ieee->current_mesh_network.atim_window);
+		memcpy((u8 *)tag, (u8 *)&val16, 2);
+		tag+=2;
+	}
+	
+	if(erp_len){
+		*(tag++) = MFIE_TYPE_ERP;
+		*(tag++) = 1;
+		*(tag++) = erpinfo_content; 
+	}
+#if 0	
+	if(tmp_ht_cap_len){
+	*(tag++) = MFIE_TYPE_HT_CAP;
+	*(tag++) = tmp_ht_cap_len - 2;
+	memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);	
+	tag += tmp_ht_cap_len - 2;
+	}
+#endif
+
+	if(rate_ex_len){
+		*(tag++) = MFIE_TYPE_RATES_EX;
+		*(tag++) = rate_ex_len-2; 
+		memcpy(tag,ieee->current_mesh_network.rates_ex,rate_ex_len-2);
+		tag+=rate_ex_len-2;
+	}
+
+#if 0 
+	if(tmp_ht_info_len){
+	*(tag++) = MFIE_TYPE_HT_INFO;
+	*(tag++) = tmp_ht_info_len - 2;
+	memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
+	tag += tmp_ht_info_len - 2;
+	}
+#endif
+	if (wpa_ie_len) {
+		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
+		tag+=ieee->wpa_ie_len;
+	}
+
+#if 0	
+	if(tmp_generic_ie_len)
+	{
+		(*tag++) = 0xdd;
+		(*tag++) = tmp_generic_ie_len - 2;
+		memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
+		tag += tmp_generic_ie_len -2;
+		
+	}
+#endif	
+	if(hostname_ie_len)
+	{
+		(*tag++) = 0xdd;
+		(*tag++) = hostname_ie_len - 2;
+		memcpy(tag, hostname_ie_buf, hostname_ie_len - 2);
+		tag += hostname_ie_len -2;
+	}
+
+	if(wmm_len)
+	{
+		memcpy(tag,wmmie,wmm_len);
+	}
+
+	skb->dev = ieee->dev;
+	return skb;
+}
+#endif
+
+struct sk_buff* rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest)
+{
+	struct sk_buff *skb;
+	u8* tag;
+	
+	struct rtllib_crypt_data* crypt;
+	struct rtllib_assoc_response_frame *assoc;
+	short encrypt;
+	
+	unsigned int rate_len = rtllib_MFIE_rate_len(ieee);
+	int len = sizeof(struct rtllib_assoc_response_frame) + rate_len + ieee->tx_headroom;
+	
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(len); 	
+#endif
+	
+	if (!skb) 
+		return NULL;
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	assoc = (struct rtllib_assoc_response_frame *)
+		skb_put(skb,sizeof(struct rtllib_assoc_response_frame));
+	
+	assoc->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_ASSOC_RESP);
+	memcpy(assoc->header.addr1, dest,ETH_ALEN);
+	memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? 
+		WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS);
+	
+		
+	if(ieee->short_slot)
+		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
+		
+	if (ieee->host_encrypt){
+#ifdef _RTL8192_EXT_PATCH_
+		crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx];
+#else
+		crypt = ieee->crypt[ieee->tx_keyidx];
+#endif
+
+	}		
+	else crypt = NULL;
+	
+	encrypt = ( crypt && crypt->ops);
+	   
+	if (encrypt)
+		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+	
+	assoc->status = 0;
+	assoc->aid = cpu_to_le16(ieee->assoc_id);
+	if (ieee->assoc_id == 0x2007) 
+		ieee->assoc_id=0;
+	else 
+		ieee->assoc_id++;
+	
+	tag = (u8*) skb_put(skb, rate_len);
+	rtllib_MFIE_Brate(ieee, &tag);
+	rtllib_MFIE_Grate(ieee, &tag);
+	
+	return skb;
+}
+
+struct sk_buff* rtllib_auth_resp(struct rtllib_device *ieee,int status, u8 *dest)
+{
+	struct sk_buff *skb = NULL;
+	struct rtllib_authentication *auth;
+	int len = ieee->tx_headroom + sizeof(struct rtllib_authentication)+1;
+#ifdef _RTL8192_EXT_PATCH_
+	bool is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,dest);
+	if(is_mesh && (ieee->mesh_sec_type == 1) && (ieee->mesh_security_setting == 3))
+		skb = ieee->ext_patch_rtllib_send_ath_confirm(ieee,dest);
+	return skb;
+#endif
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(len); 	
+#endif
+	if (!skb) 
+		return NULL;
+	
+	skb->len = sizeof(struct rtllib_authentication);
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	
+	skb_reserve(skb, ieee->tx_headroom);
+
+	auth = (struct rtllib_authentication *)
+		skb_put(skb, sizeof(struct rtllib_authentication));
+	
+	auth->status = cpu_to_le16(status);
+	auth->transaction = cpu_to_le16(2);
+	auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)
+		memset(auth->header.addr3, 0, ETH_ALEN);
+	else
+		memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
+#else
+	memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
+#endif
+	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(auth->header.addr1, dest, ETH_ALEN);
+	auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH); 
+	return skb;
+	
+	
+}
+
+struct sk_buff* rtllib_null_func(struct rtllib_device *ieee,short pwr)
+{
+	struct sk_buff *skb;
+	struct rtllib_hdr_3addr* hdr;
+	
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr)+ieee->tx_headroom); 
+#endif	
+	if (!skb) 
+		return NULL;
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif	
+	skb_reserve(skb, ieee->tx_headroom);
+
+	hdr = (struct rtllib_hdr_3addr*)skb_put(skb,sizeof(struct rtllib_hdr_3addr));
+	
+	memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
+	memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
+	
+	hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_DATA | 
+		RTLLIB_STYPE_NULLFUNC | RTLLIB_FCTL_TODS | 
+		(pwr ? RTLLIB_FCTL_PM:0)); 
+	
+	return skb;
+	
+	
+}
+
+struct sk_buff* rtllib_pspoll_func(struct rtllib_device *ieee)
+{
+	struct sk_buff *skb;
+	struct rtllib_pspoll_hdr* hdr;
+	
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr)+ieee->tx_headroom); 
+#endif	
+	if (!skb) 
+		return NULL;
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif	
+	skb_reserve(skb, ieee->tx_headroom);
+
+	hdr = (struct rtllib_pspoll_hdr*)skb_put(skb,sizeof(struct rtllib_pspoll_hdr));
+
+	memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
+	memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
+
+	hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000); 
+	hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_CTL |RTLLIB_STYPE_PSPOLL | RTLLIB_FCTL_PM); 
+	
+	return skb;	
+	
+}
+
+void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8* dest)
+{
+	struct sk_buff *buf = rtllib_assoc_resp(ieee, dest);
+	
+	if (buf)
+		softmac_mgmt_xmit(buf, ieee);
+}
+
+
+void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8* dest)
+{
+	struct sk_buff *buf = rtllib_auth_resp(ieee, s, dest);
+	
+	if (buf)
+		softmac_mgmt_xmit(buf, ieee);
+}
+
+
+void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest)
+{
+	
+
+	struct sk_buff *buf = rtllib_probe_resp(ieee, dest);
+	if (buf) 
+		softmac_mgmt_xmit(buf, ieee);
+}
+
+
+inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid)
+{
+	int i = 0;
+
+	do 
+	{
+		if ((ieee->PMKIDList[i].bUsed) && (memcmp(ieee->PMKIDList[i].Bssid, bssid, ETH_ALEN) == 0))
+		{
+			break;
+		}
+		else
+		{	
+			i++;
+		}
+	} while (i < NUM_PMKID_CACHE);
+
+	if (i == NUM_PMKID_CACHE)
+	{ 
+		i = -1;
+	}
+	else
+	{ 
+	}
+
+	return (i);
+	
+}
+
+
+inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,struct rtllib_device *ieee)
+{
+	struct sk_buff *skb;
+	
+	struct rtllib_assoc_request_frame *hdr;
+	u8 *tag, *ies;
+	int i;
+	u8* ht_cap_buf = NULL;
+	u8 ht_cap_len=0;
+	u8* realtek_ie_buf=NULL;
+	u8 realtek_ie_len=0;
+	int wpa_ie_len= ieee->wpa_ie_len;
+	int wps_ie_len = ieee->wps_ie_len;
+	unsigned int ckip_ie_len=0;
+	unsigned int ccxrm_ie_len=0;
+	unsigned int cxvernum_ie_len=0;
+	struct rtllib_crypt_data* crypt;
+	int encrypt;
+	int	PMKCacheIdx;
+	
+	unsigned int rate_len = (beacon->rates_len?(beacon->rates_len+2):0) + (beacon->rates_ex_len?(beacon->rates_ex_len)+2:0);
+	
+	unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
+#ifdef THOMAS_TURBO	
+	unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
+#endif
+
+	int len = 0; 
+#ifdef RTL8192S_WAPI_SUPPORT
+	PRT_WAPI_BKID		pWapiBKID;
+	u16					bkidNum;
+	PRT_WAPI_T			pWapiInfo = &(ieee->wapiInfo);
+	u8					WapiIE[256];
+	u8					WapiIELength = 0;
+#endif                             
+#ifdef _RTL8192_EXT_PATCH_
+	crypt = ieee->sta_crypt[ieee->tx_keyidx];
+#else
+	crypt = ieee->crypt[ieee->tx_keyidx];
+#endif
+	if(crypt != NULL) {
+		encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
+	} else {
+		encrypt = 0;
+	}
+
+#ifdef ENABLE_TKIP11N
+	if (ieee->bForcedBgMode == true)
+#else
+	if ((ieee->rtllib_ap_sec_type && (ieee->rtllib_ap_sec_type(ieee)&SEC_ALG_TKIP)) ||(ieee->bForcedBgMode == true)) 
+#endif
+	{
+		ieee->pHTInfo->bEnableHT = 0;
+		ieee->mode = WIRELESS_MODE_G;
+	}
+	
+	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
+	{
+		ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
+		ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
+#ifdef _RTL8192_EXT_PATCH_
+		HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt, 0);
+#else
+		HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
+#endif
+		if(ieee->pHTInfo->bCurrentRT2RTAggregation)
+		{
+			realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
+			realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
+			HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
+       	 			
+		}
+	}
+
+	if(beacon->bCkipSupported)
+	{
+		ckip_ie_len = 30+2;
+	}
+	if(beacon->bCcxRmEnable)
+	{	
+		ccxrm_ie_len = 6+2;
+	}
+	if( beacon->BssCcxVerNumber >= 2 )
+	{	
+		cxvernum_ie_len = 5+2;
+	}
+	
+	PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
+	if (PMKCacheIdx >= 0)
+	{
+		wpa_ie_len += 18;
+		printk("[PMK cache]: WPA2 IE length: %x\n", wpa_ie_len);
+	}	
+#ifdef RTL8192S_WAPI_SUPPORT
+	if(ieee->WapiSupport && pWapiInfo->bWapiEnable)
+	{
+		wpa_ie_len = 0;
+		
+		WAPI_TRACE(WAPI_API, "%s(): Set WAPI IE in assoc req!!\n",__FUNCTION__);
+		WapiSetIE(ieee);
+		WapiIELength = pWapiInfo->wapiIELength;
+		memcpy(WapiIE, pWapiInfo->wapiIE ,pWapiInfo->wapiIELength);
+		
+		bkidNum = 0;
+		WapiIELength +=2;
+		if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){
+			list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) {
+				bkidNum ++;
+				memcpy(WapiIE+WapiIELength, pWapiBKID->bkid,16);
+				WapiIELength += 16;
+			}
+		
+		}
+		memcpy(WapiIE+pWapiInfo->wapiIELength,&bkidNum,2);
+	}
+#endif
+	
+	len = sizeof(struct rtllib_assoc_request_frame)+ 2
+		+ beacon->ssid_len
+		+ rate_len
+		+ wpa_ie_len 
+		+ wps_ie_len
+#ifdef RTL8192S_WAPI_SUPPORT
+		+ WapiIELength + 2
+#endif
+		+ wmm_info_len
+#ifdef THOMAS_TURBO
+		+ turbo_info_len
+#endif
+                + ht_cap_len
+		+ realtek_ie_len
+		+ ckip_ie_len
+		+ ccxrm_ie_len
+		+ cxvernum_ie_len
+		+ ieee->tx_headroom;
+
+#ifdef USB_USE_ALIGNMENT
+	u32 Tmpaddr=0;
+	int alignment=0;
+	skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE);
+#else	
+	skb = dev_alloc_skb(len);
+#endif
+	
+	if (!skb) 
+		return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	hdr = (struct rtllib_assoc_request_frame *)
+		skb_put(skb, sizeof(struct rtllib_assoc_request_frame)+2);
+	
+	
+	hdr->header.frame_ctl = RTLLIB_STYPE_ASSOC_REQ;
+	hdr->header.duration_id= 37; 
+	memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
+	memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
+
+	memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);
+	
+	hdr->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+	if (beacon->capability & WLAN_CAPABILITY_PRIVACY ) 
+		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+
+	if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); 
+
+	if(ieee->short_slot && (beacon->capability&WLAN_CAPABILITY_SHORT_SLOT_TIME))
+		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+
+	hdr->listen_interval = beacon->listen_interval;
+	
+	hdr->info_element[0].id = MFIE_TYPE_SSID;
+
+	hdr->info_element[0].len = beacon->ssid_len;
+	tag = skb_put(skb, beacon->ssid_len);
+	memcpy(tag, beacon->ssid, beacon->ssid_len);
+	
+	tag = skb_put(skb, rate_len); 
+	
+	if(beacon->rates_len){
+		*tag++ = MFIE_TYPE_RATES;
+		*tag++ = beacon->rates_len;
+		for(i=0;i<beacon->rates_len;i++){
+			*tag++ = beacon->rates[i];
+		}
+	}
+
+	if(beacon->rates_ex_len){
+		*tag++ = MFIE_TYPE_RATES_EX;
+		*tag++ = beacon->rates_ex_len;
+		for(i=0;i<beacon->rates_ex_len;i++){
+			*tag++ = beacon->rates_ex[i];
+		}
+	}
+
+	if( beacon->bCkipSupported )
+	{
+		static u8	AironetIeOui[] = {0x00, 0x01, 0x66}; 
+		u8	CcxAironetBuf[30];
+		OCTET_STRING	osCcxAironetIE;
+
+		memset(CcxAironetBuf, 0,30);
+		osCcxAironetIE.Octet = CcxAironetBuf;
+		osCcxAironetIE.Length = sizeof(CcxAironetBuf);
+		memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
+
+		osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=  (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
+		tag = skb_put(skb, ckip_ie_len);
+		*tag++ = MFIE_TYPE_AIRONET;
+		*tag++ = osCcxAironetIE.Length;
+		memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
+		tag += osCcxAironetIE.Length;
+	}
+
+	if(beacon->bCcxRmEnable)
+	{
+		static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
+		OCTET_STRING osCcxRmCap;
+
+		osCcxRmCap.Octet = CcxRmCapBuf;
+		osCcxRmCap.Length = sizeof(CcxRmCapBuf);
+		tag = skb_put(skb,ccxrm_ie_len);
+		*tag++ = MFIE_TYPE_GENERIC;
+		*tag++ = osCcxRmCap.Length;
+		memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
+		tag += osCcxRmCap.Length;
+	}
+
+	if( beacon->BssCcxVerNumber >= 2 )
+	{
+		u8			CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
+		OCTET_STRING	osCcxVerNum;
+		CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
+		osCcxVerNum.Octet = CcxVerNumBuf;
+		osCcxVerNum.Length = sizeof(CcxVerNumBuf);
+		tag = skb_put(skb,cxvernum_ie_len);
+		*tag++ = MFIE_TYPE_GENERIC;
+		*tag++ = osCcxVerNum.Length;
+		memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
+		tag += osCcxVerNum.Length;
+	}
+	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
+		if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
+		{
+			tag = skb_put(skb, ht_cap_len);
+			*tag++ = MFIE_TYPE_HT_CAP;
+			*tag++ = ht_cap_len - 2;
+			memcpy(tag, ht_cap_buf,ht_cap_len -2);
+			tag += ht_cap_len -2;
+		}
+	}	         
+
+	
+	if (wpa_ie_len){
+		tag = skb_put(skb, ieee->wpa_ie_len);	
+		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
+		
+		if (PMKCacheIdx >= 0)
+		{
+			tag = skb_put(skb, 18);		
+			*tag = 1;
+			*(tag + 1) = 0;	
+			memcpy((tag + 2), &ieee->PMKIDList[PMKCacheIdx].PMKID, 16);
+		}
+	}
+#ifdef RTL8192S_WAPI_SUPPORT
+	if(WapiIELength){
+		tag = skb_put(skb, WapiIELength+2);
+		*tag = MFIE_TYPE_WAPI;
+		*(tag+1) = WapiIELength;
+		memcpy((tag+2), WapiIE, WapiIELength);
+
+		pWapiInfo->assoReqWapiIELength = WapiIELength+2;
+		pWapiInfo->assoReqWapiIE[0] = MFIE_TYPE_WAPI;
+		pWapiInfo->assoReqWapiIE[1] = WapiIELength;
+		memcpy(pWapiInfo->assoReqWapiIE+2,WapiIE,WapiIELength);
+	}
+#endif
+
+	if(wmm_info_len) {
+		tag = skb_put(skb,wmm_info_len);
+		rtllib_WMM_Info(ieee, &tag);
+	}
+
+	if(wps_ie_len && ieee->wps_ie)
+	{
+		tag = skb_put(skb, wps_ie_len);		
+		memcpy(tag, ieee->wps_ie, wps_ie_len);		
+	}	
+	
+#ifdef THOMAS_TURBO
+	tag = skb_put(skb,turbo_info_len);
+        if(turbo_info_len) {
+                rtllib_TURBO_Info(ieee, &tag);
+        }
+#endif
+
+	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
+		if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
+		{
+			tag = skb_put(skb, ht_cap_len);
+			*tag++ = MFIE_TYPE_GENERIC;
+			*tag++ = ht_cap_len - 2;
+			memcpy(tag, ht_cap_buf,ht_cap_len - 2);
+			tag += ht_cap_len -2;
+		}
+
+		if(ieee->pHTInfo->bCurrentRT2RTAggregation){
+			tag = skb_put(skb, realtek_ie_len);
+			*tag++ = MFIE_TYPE_GENERIC;
+			*tag++ = realtek_ie_len - 2;
+			memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
+		}
+	}
+
+	if(ieee->assocreq_ies){
+		kfree(ieee->assocreq_ies);
+		ieee->assocreq_ies = NULL;
+	}
+	ies = &(hdr->info_element[0].id);
+	ieee->assocreq_ies_len = (skb->data + skb->len) - ies;
+	ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC);
+	if (ieee->assocreq_ies)
+		memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len);
+	else{
+		printk("%s()Warning: can't alloc memory for assocreq_ies\n", __func__);
+		ieee->assocreq_ies_len = 0;
+	}	
+	
+	return skb;
+}
+
+void rtllib_associate_abort(struct rtllib_device *ieee)
+{
+	
+	unsigned long flags;
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	ieee->associate_seq++;
+	
+	/* don't scan, and avoid to have the RX path possibily
+	 * try again to associate. Even do not react to AUTH or
+	 * ASSOC response. Just wait for the retry wq to be scheduled.
+	 * Here we will check if there are good nets to associate
+	 * with, so we retry or just get back to NO_LINK and scanning
+	 */
+	if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING){
+		RTLLIB_DEBUG_MGMT("Authentication failed\n"); 
+		ieee->softmac_stats.no_auth_rs++;
+	}else{
+		RTLLIB_DEBUG_MGMT("Association failed\n"); 
+		ieee->softmac_stats.no_ass_rs++;
+	}
+		
+	ieee->state = RTLLIB_ASSOCIATING_RETRY;
+		
+	queue_delayed_work_rsl(ieee->wq, &ieee->associate_retry_wq, \
+                           RTLLIB_SOFTMAC_ASSOC_RETRY_TIME);
+	
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+void rtllib_associate_abort_cb(unsigned long dev)
+{
+	rtllib_associate_abort((struct rtllib_device *) dev);
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtllib_associate_step1(struct rtllib_device *ieee,u8 * daddr)
+#else
+void rtllib_associate_step1(struct rtllib_device *ieee)
+#endif
+{
+	struct rtllib_network *beacon = &ieee->current_network;
+	struct sk_buff *skb;
+#ifdef _RTL8192_EXT_PATCH_
+	bool is_mesh = false;
+#endif
+	RTLLIB_DEBUG_MGMT("Stopping scan\n");
+
+	ieee->softmac_stats.tx_auth_rq++;
+#ifdef _RTL8192_EXT_PATCH_
+	skb=rtllib_authentication_req(beacon, ieee, 0,daddr);
+#else
+	skb=rtllib_authentication_req(beacon, ieee, 0);
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,daddr);
+	if(is_mesh)	{
+		if(skb){	
+			softmac_mgmt_xmit(skb, ieee);
+		}
+		return;
+	}else
+#endif		
+	if (!skb) 
+		rtllib_associate_abort(ieee);
+	else{ 
+		ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING ;
+		RTLLIB_DEBUG_MGMT("Sending authentication request\n");
+		softmac_mgmt_xmit(skb, ieee);
+		if(!timer_pending(&ieee->associate_timer)){
+			ieee->associate_timer.expires = jiffies + (HZ / 2);
+			add_timer(&ieee->associate_timer);
+		}
+	}
+}
+
+void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, int chlen)
+{
+	u8 *c;	
+	struct sk_buff *skb;
+	struct rtllib_network *beacon = &ieee->current_network;
+	
+	ieee->associate_seq++;
+	ieee->softmac_stats.tx_auth_rq++;
+	
+#ifdef _RTL8192_EXT_PATCH_
+	skb = rtllib_authentication_req(beacon, ieee, chlen+2,beacon->bssid);
+#else
+	skb = rtllib_authentication_req(beacon, ieee, chlen+2);
+#endif		
+	if (!skb) 
+		rtllib_associate_abort(ieee);
+	else{
+		c = skb_put(skb, chlen+2);
+		*(c++) = MFIE_TYPE_CHALLENGE;
+		*(c++) = chlen;
+		memcpy(c, challenge, chlen);
+		
+		RTLLIB_DEBUG_MGMT("Sending authentication challenge response\n");
+		
+#ifdef _RTL8192_EXT_PATCH_
+		rtllib_encrypt_fragment(ieee, skb, sizeof(struct rtllib_hdr_3addr  ), 0, 0);
+#else
+		rtllib_encrypt_fragment(ieee, skb, sizeof(struct rtllib_hdr_3addr  ));
+#endif		
+			
+		softmac_mgmt_xmit(skb, ieee);
+		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+#if 0
+		ieee->associate_timer.expires = jiffies + (HZ / 2);
+		add_timer(&ieee->associate_timer);
+#endif
+	}	
+	kfree(challenge);
+}
+
+void rtllib_associate_step2(struct rtllib_device *ieee)
+{
+	struct sk_buff* skb;
+	struct rtllib_network *beacon = &ieee->current_network;
+	
+	del_timer_sync(&ieee->associate_timer);
+	
+	RTLLIB_DEBUG_MGMT("Sending association request\n");
+	
+	ieee->softmac_stats.tx_ass_rq++;
+	skb=rtllib_association_req(beacon, ieee);
+	if (!skb) 
+		rtllib_associate_abort(ieee);
+	else{
+		softmac_mgmt_xmit(skb, ieee);
+		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+#if 0
+		ieee->associate_timer.expires = jiffies + (HZ / 2);
+		add_timer(&ieee->associate_timer);
+#endif
+	}	
+}
+
+#define CANCELLED  2
+void rtllib_associate_complete_wq(void *data)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl(data, struct rtllib_device, associate_complete_wq);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
+	printk(KERN_INFO "Associated successfully\n");
+	if(ieee->is_silent_reset == 0){
+            printk("normal associate\n");
+            notify_wx_assoc_event(ieee); 
+        }
+
+	netif_carrier_on(ieee->dev);
+	ieee->is_roaming = false;
+	if(rtllib_is_54g(&ieee->current_network) && 
+		(ieee->modulation & RTLLIB_OFDM_MODULATION)){
+		
+		ieee->rate = 108;
+		printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
+	}else{
+		ieee->rate = 22;
+		ieee->SetWirelessMode(ieee->dev, IEEE_B);
+		printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
+	}
+	if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
+	{
+		printk("Successfully associated, ht enabled\n");
+		HTOnAssocRsp(ieee);
+	} else {
+		printk("Successfully associated, ht not enabled(%d, %d)\n", 
+				ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
+		memset(ieee->dot11HTOperationalRateSet, 0, 16);
+	}
+	ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
+	if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
+	{
+		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
+		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;	
+	}
+	pPSC->LpsIdleCount = 0;
+	ieee->link_change(ieee->dev);
+
+#ifdef _RTL8192_EXT_PATCH_	
+	if(ieee->set_key_for_AP)
+		ieee->set_key_for_AP(ieee);
+	/* Synchronize mesh channel to wlan channel in MSTA mode.*/
+	{
+		if(ieee->current_mesh_network.channel != ieee->current_network.channel)
+		{
+			printk("^^^^^^^^^^^^^^^^Change mesh channel %d with wlan channel %d\n", 
+					ieee->current_mesh_network.channel, ieee->current_network.channel);
+			ieee->ext_patch_rtllib_close_all_peerlink(ieee, CANCELLED);
+			ieee->current_mesh_network.channel = ieee->current_network.channel;
+			if(ieee->ext_patch_r819x_wx_set_channel)
+			{
+				ieee->ext_patch_r819x_wx_set_channel(ieee, ieee->current_network.channel);
+				ieee->ext_patch_r819x_wx_set_mesh_chan(ieee->dev,ieee->current_network.channel);
+			}
+		}
+	}
+#endif	
+        if(ieee->is_silent_reset == 0){
+        } else if(ieee->is_silent_reset == 1) {
+            printk("silent reset associate\n");
+            ieee->is_silent_reset = 0;
+        }
+
+	if (ieee->data_hard_resume)
+		ieee->data_hard_resume(ieee->dev);
+
+#ifdef RTK_DMP_PLATFORM
+	kobject_hotplug(&ieee->dev->class_dev.kobj, KOBJ_LINKUP);
+#endif
+}
+
+static void rtllib_sta_send_associnfo(struct rtllib_device *ieee)
+{
+	char *buf;
+	size_t len;
+	int i;
+	union iwreq_data wrqu;
+
+		return;
+
+	
+	buf = kmalloc(50 + 2 * (ieee->assocreq_ies_len + ieee->assocresp_ies_len), GFP_ATOMIC);
+	if (!buf)
+		return;
+
+	len = sprintf(buf, "ASSOCINFO(");
+	if (ieee->assocreq_ies) {
+		len += sprintf(buf + len, "ReqIEs=");
+		for (i = 0; i < ieee->assocreq_ies_len; i++) {
+			len += sprintf(buf + len, "%02x", ieee->assocreq_ies[i]);
+		}
+	}
+	if (ieee->assocresp_ies) {
+		if (ieee->assocreq_ies)
+			len += sprintf(buf + len, " ");
+		len += sprintf(buf + len, "RespIEs=");
+		for (i = 0; i < ieee->assocresp_ies_len; i++) {
+			len += sprintf(buf + len, "%02x", ieee->assocresp_ies[i]);
+		}
+	}
+	len += sprintf(buf + len, ")");
+
+	if (len > IW_CUSTOM_MAX) {
+		len = sprintf(buf, "ASSOCRESPIE=");
+		for (i = 0; i < ieee->assocresp_ies_len; i++) {
+			len += sprintf(buf + len, "%02x", ieee->assocresp_ies[i]);
+		}
+	}
+
+	if (len <= IW_CUSTOM_MAX) {
+		memset(&wrqu, 0, sizeof(wrqu));
+		wrqu.data.length = len;
+		wireless_send_event(ieee->dev, IWEVCUSTOM, &wrqu, buf);
+	}
+
+	kfree(buf);
+}
+
+void rtllib_associate_complete(struct rtllib_device *ieee)
+{
+	del_timer_sync(&ieee->associate_timer);
+
+#if 0
+	for(i = 0; i < 6; i++) {
+	  ieee->seq_ctrl[i] = 0;
+	}
+#endif	
+	ieee->state = RTLLIB_LINKED;
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+		WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+	}
+#endif
+#if 0
+	if (ieee->pHTInfo->bCurrentHTSupport)
+	{
+		printk("Successfully associated, ht enabled\n");
+		queue_work_rsl(ieee->wq, &ieee->ht_onAssRsp);
+	}
+	else
+	{
+		printk("Successfully associated, ht not enabled\n");
+		memset(ieee->dot11HTOperationalRateSet, 0, 16);
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+	}
+#endif
+
+	rtllib_sta_send_associnfo(ieee);
+
+	queue_work_rsl(ieee->wq, &ieee->associate_complete_wq);
+}
+
+void rtllib_associate_procedure_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, associate_procedure_wq);
+	rtllib_stop_scan_syncro(ieee);
+#ifdef ENABLE_IPS
+	if(ieee->rtllib_ips_leave != NULL)
+        	ieee->rtllib_ips_leave(ieee->dev);
+#endif
+	down(&ieee->wx_sem);
+	
+	if (ieee->data_hard_stop)
+		ieee->data_hard_stop(ieee->dev);
+	
+	rtllib_stop_scan(ieee);
+	printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);	
+	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+	if(ieee->eRFPowerState == eRfOff)
+	{
+            printk("=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",__FUNCTION__);
+#ifdef ENABLE_IPS
+		if(ieee->rtllib_ips_leave_wq != NULL)
+			ieee->rtllib_ips_leave_wq(ieee->dev);
+#endif
+		up(&ieee->wx_sem);
+		return;
+	}
+	ieee->associate_seq = 1;
+#ifdef _RTL8192_EXT_PATCH_
+	rtllib_associate_step1(ieee, ieee->current_network.bssid);
+#else
+	rtllib_associate_step1(ieee);
+#endif	
+	up(&ieee->wx_sem);
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+
+void rtllib_ext_stop_scan_wq(void *data)
+{
+	struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl(data, struct rtllib_device, ext_stop_scan_wq);
+	rtllib_stop_scan_syncro(ieee);
+	
+	down(&ieee->wx_sem);
+	
+	if (ieee->data_hard_stop)
+		ieee->data_hard_stop(ieee->dev);
+	
+	rtllib_stop_scan(ieee);
+
+	up(&ieee->wx_sem);
+}
+
+
+void rtllib_ext_send_11s_beacon(struct rtllib_device *ieee)
+{	
+	queue_work_rsl(ieee->wq, &ieee->ext_send_beacon_wq);
+}
+
+#endif 
+
+
+inline void rtllib_softmac_new_net(struct rtllib_device *ieee, struct rtllib_network *net)
+{
+	u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
+	int tmp_ssid_len = 0;
+	
+	short apset,ssidset,ssidbroad,apmatch,ssidmatch;
+	
+	/* we are interested in new new only if we are not associated 
+	 * and we are not associating / authenticating
+	 */
+	if (ieee->state != RTLLIB_NOLINK)
+		return; 
+
+	if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_ESS))
+		return;
+	
+	if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
+		return;
+
+	if ((ieee->iw_mode == IW_MODE_ADHOC) && (net->channel > ieee->ibss_maxjoin_chal)) {
+		return;
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC 
+	    || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))
+#else
+	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) 
+#endif
+		{
+		/* if the user specified the AP MAC, we need also the essid
+		 * This could be obtained by beacons or, if the network does not
+		 * broadcast it, it can be put manually.
+		 */
+		apset = ieee->wap_set;
+		ssidset = ieee->ssid_set;
+		ssidbroad =  !(net->ssid_len == 0 || net->ssid[0]== '\0');
+		apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
+		if(!ssidbroad){
+		    	ssidmatch = (ieee->current_network.ssid_len == net->hidden_ssid_len)&&\
+					(!strncmp(ieee->current_network.ssid, net->hidden_ssid, net->hidden_ssid_len));
+			if(net->hidden_ssid_len > 0)
+                        {
+			        strncpy(net->ssid, net->hidden_ssid, net->hidden_ssid_len);
+			        net->ssid_len = net->hidden_ssid_len;
+                                ssidbroad = 1;
+                        }
+		}
+		else
+			ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
+					(!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
+
+		if (	/* if the user set the AP check if match.
+		         * if the network does not broadcast essid we check the user supplyed ANY essid
+			 * if the network does broadcast and the user does not set essid it is OK
+			 * if the network does broadcast and the user did set essid chech if essid match
+			 */
+			( apset && apmatch && 
+				((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) )
+			/* if the ap is not set, check that the user set the bssid
+			 * and the network does bradcast and that those two bssid matches
+			 */ 
+			 ||  (!apset && ssidset && ssidbroad && ssidmatch) || (ieee->is_roaming && ssidset && ssidbroad && ssidmatch) 
+			){
+				/* if the essid is hidden replace it with the
+				* essid provided by the user.
+				*/
+				if (!ssidbroad){
+					strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
+					tmp_ssid_len = ieee->current_network.ssid_len;
+				}
+				memcpy(&ieee->current_network, net, sizeof(struct rtllib_network));
+				if (!ssidbroad){
+					strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
+					ieee->current_network.ssid_len = tmp_ssid_len;
+				}
+				printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x cur_net.flags:0x%x\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT, ieee->current_network.mode, ieee->current_network.flags);
+
+				if ((rtllib_act_scanning(ieee, false)) && !(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){
+					rtllib_stop_scan_syncro(ieee);
+				}
+
+				ieee->hwscan_ch_bk = ieee->current_network.channel;
+				HTResetIOTSetting(ieee->pHTInfo);
+				ieee->wmm_acm = 0;
+#ifdef _RTL8192_EXT_PATCH_
+				if ((ieee->iw_mode == IW_MODE_INFRA) || 
+					((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))  
+#else
+				if (ieee->iw_mode == IW_MODE_INFRA)
+#endif
+				{
+					/* Join the network for the first time */
+					ieee->AsocRetryCount = 0;	
+					if((ieee->current_network.qos_data.supported == 1) &&
+					   ieee->current_network.bssht.bdSupportHT)
+/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
+					{
+#ifdef ENABLE_AMSDU   
+						if((ieee->mode == IEEE_N_24G) && (ieee->mode == IEEE_N_5G))
+							HTUseDefaultSetting(ieee);
+#endif
+						HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
+					}
+					else
+					{
+						ieee->pHTInfo->bCurrentHTSupport = false;
+					}
+
+					ieee->state = RTLLIB_ASSOCIATING;
+					if(ieee->LedControlHandler != NULL)
+					        ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); 
+					queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0);
+				}else{
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+#if defined (RTL8192S_WAPI_SUPPORT)
+					if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+						WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+					}
+#endif		
+					ieee->state = RTLLIB_LINKED;
+					if(ieee->mode > ieee->current_network.mode)
+						ieee->SetWirelessMode(ieee->dev, ieee->current_network.mode);
+					else
+						ieee->SetWirelessMode(ieee->dev, ieee->mode);
+					mod_timer(&ieee->ibss_wait_timer,jiffies+(MSECS(20000)));
+#else
+					if(rtllib_is_54g(&ieee->current_network) && 
+						(ieee->modulation & RTLLIB_OFDM_MODULATION)){
+						ieee->rate = 108;
+						ieee->SetWirelessMode(ieee->dev, IEEE_G);
+						printk(KERN_INFO"Using G rates\n");
+					}else{
+						ieee->rate = 22;
+						ieee->SetWirelessMode(ieee->dev, IEEE_B);
+						printk(KERN_INFO"Using B rates\n");
+					}
+					memset(ieee->dot11HTOperationalRateSet, 0, 16);
+					ieee->state = RTLLIB_LINKED;
+#endif
+				}
+			
+		}
+	}
+
+}
+
+void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
+{
+	unsigned long flags;
+	struct rtllib_network *target;
+
+	spin_lock_irqsave(&ieee->lock, flags);
+			
+	list_for_each_entry(target, &ieee->network_list, list) {
+		
+		/* if the state become different that NOLINK means
+		 * we had found what we are searching for
+		 */
+
+		if (ieee->state != RTLLIB_NOLINK) 
+			break;
+	
+		if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
+		rtllib_softmac_new_net(ieee, target);
+	}
+	
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+}
+
+
+static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
+{
+	struct rtllib_authentication *a;
+	u8 *t;
+	if (skb->len <  (sizeof(struct rtllib_authentication)-sizeof(struct rtllib_info_element))){ 
+		RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
+		return 0xcafe;
+	}
+	*challenge = NULL;
+	a = (struct rtllib_authentication*) skb->data;
+	if(skb->len > (sizeof(struct rtllib_authentication) +3)){
+		t = skb->data + sizeof(struct rtllib_authentication);
+		
+		if(*(t++) == MFIE_TYPE_CHALLENGE){
+			*chlen = *(t++);
+			*challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
+			memcpy(*challenge, t, *chlen);
+		}
+	}
+	
+	return cpu_to_le16(a->status);
+	
+}
+
+
+int auth_rq_parse(struct sk_buff *skb,u8* dest)
+{
+	struct rtllib_authentication *a;
+	
+	if (skb->len <  (sizeof(struct rtllib_authentication)-sizeof(struct rtllib_info_element))){ 
+		RTLLIB_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);	
+		return -1;
+	}
+	a = (struct rtllib_authentication*) skb->data;
+	
+	memcpy(dest,a->header.addr2, ETH_ALEN);
+	
+	if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) 
+		return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
+	
+	return WLAN_STATUS_SUCCESS;
+}
+
+static short probe_rq_parse(struct rtllib_device *ieee, struct sk_buff *skb, u8 *src)
+{
+	u8 *tag;
+	u8 *skbend;
+	u8 *ssid=NULL;
+	u8 ssidlen = 0;
+	
+	struct rtllib_hdr_3addr   *header =
+		(struct rtllib_hdr_3addr   *) skb->data;
+	
+	if (skb->len < sizeof (struct rtllib_hdr_3addr  )) 
+		return -1; /* corrupted */
+        if((memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) != 0)&&
+                (memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) != 0)) {
+            return -1;
+        }
+
+        if(memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) == 0) {
+        }
+	
+        if(memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) == 0) {
+        }
+	memcpy(src,header->addr2, ETH_ALEN);
+	
+	skbend = (u8*)skb->data + skb->len;
+	
+	tag = skb->data + sizeof (struct rtllib_hdr_3addr  );
+	
+	while (tag+1 < skbend){
+		if (*tag == 0){ 
+			ssid = tag+2;
+			ssidlen = *(tag+1);
+			break;
+		}
+		tag++; /* point to the len field */
+		tag = tag + *(tag); /* point to the last data byte of the tag */
+		tag++; /* point to the next tag */
+	}
+	
+	if (ssidlen == 0) return 1;
+	
+	if (!ssid) return 1; /* ssid not found in tagged param */
+	return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
+		
+}
+
+int assoc_rq_parse(struct sk_buff *skb,u8* dest)
+{
+	struct rtllib_assoc_request_frame *a;
+	
+	if (skb->len < (sizeof(struct rtllib_assoc_request_frame) - 
+		sizeof(struct rtllib_info_element))) { 
+		
+		RTLLIB_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
+		return -1;
+	}
+	
+	a = (struct rtllib_assoc_request_frame*) skb->data;
+		
+	memcpy(dest,a->header.addr2,ETH_ALEN);
+	
+	return 0;
+}
+
+static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb, int *aid)
+{
+	struct rtllib_assoc_response_frame *response_head;
+	u16 status_code;
+
+	if (skb->len <  sizeof(struct rtllib_assoc_response_frame)){ 
+		RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
+		return 0xcafe;
+	}
+	
+	response_head = (struct rtllib_assoc_response_frame*) skb->data;
+	*aid = le16_to_cpu(response_head->aid) & 0x3fff;
+
+	status_code = le16_to_cpu(response_head->status);
+	if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
+	   status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
+	   ((ieee->mode == IEEE_G) && 
+	    (ieee->current_network.mode == IEEE_N_24G) &&
+            (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
+                 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
+	}else {
+		 ieee->AsocRetryCount = 0;
+	}
+
+	return le16_to_cpu(response_head->status);
+}
+
+void rtllib_rx_probe_rq(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+	u8 dest[ETH_ALEN];
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	struct sta_info *psta = NULL;
+#endif
+	ieee->softmac_stats.rx_probe_rq++;
+	if (probe_rq_parse(ieee, skb, dest) > 0){
+		ieee->softmac_stats.tx_probe_rs++;
+		rtllib_resp_to_probe(ieee, dest);
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+		if(ieee->iw_mode == IW_MODE_ADHOC){
+			psta = GetStaInfo(ieee, dest);
+			if(NULL != psta)
+				psta->LastActiveTime = jiffies;
+		}
+#endif
+	}
+}
+
+static inline void rtllib_rx_auth_rq(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+	u8 dest[ETH_ALEN];
+	int status;
+	ieee->softmac_stats.rx_auth_rq++;
+
+	if ((status = auth_rq_parse(skb, dest))!= -1){
+		rtllib_resp_to_auth(ieee, status, dest);
+	}
+
+}
+
+static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+	
+	u8 dest[ETH_ALEN];
+	
+	ieee->softmac_stats.rx_ass_rq++;
+	if (assoc_rq_parse(skb,dest) != -1){
+		rtllib_resp_to_assoc_rq(ieee, dest);
+	}
+	
+	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+	#if 0
+	spin_lock_irqsave(&ieee->lock,flags);
+	add_associate(ieee,dest);
+	spin_unlock_irqrestore(&ieee->lock,flags);
+	#endif
+}
+
+
+void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr)
+{
+	
+	struct sk_buff *buf = rtllib_null_func(ieee, pwr);
+	
+	if (buf)
+		softmac_ps_mgmt_xmit(buf, ieee);
+
+} 
+
+void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee)
+{
+	
+	struct sk_buff *buf = rtllib_pspoll_func(ieee);
+	
+	if (buf)
+		softmac_ps_mgmt_xmit(buf, ieee);
+
+} 
+
+short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u32 *time_h, u32 *time_l)
+{	
+	int timeout = ieee->ps_timeout;
+	u8 dtim;
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
+	/*if(ieee->ps == RTLLIB_PS_DISABLED ||
+		ieee->iw_mode != IW_MODE_INFRA || 
+		ieee->state != RTLLIB_LINKED)
+		
+		return 0;
+	*/
+
+	if(ieee->LPSDelayCnt)
+	{
+		ieee->LPSDelayCnt --;
+		return 0;
+	}
+		
+	dtim = ieee->current_network.dtim_data;
+	if(!(dtim & RTLLIB_DTIM_VALID))
+		return 0;
+	timeout = ieee->current_network.beacon_interval; 
+	ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID;
+	/* there's no need to nofity AP that I find you buffered with broadcast packet */
+	if(dtim & (RTLLIB_DTIM_UCAST & ieee->ps))
+		return 2;
+	
+	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
+		return 0;
+	}
+	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
+		return 0;
+	}
+	if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
+		(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
+		return 0;
+	
+	if(time_l){
+		if(ieee->bAwakePktSent == true) {
+			pPSC->LPSAwakeIntvl = 1;
+		} else {
+			u8		MaxPeriod = 1;
+
+			if(pPSC->LPSAwakeIntvl == 0)
+				pPSC->LPSAwakeIntvl = 1;
+			if(pPSC->RegMaxLPSAwakeIntvl == 0) 
+				MaxPeriod = 1; 
+			else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) 
+				MaxPeriod = ieee->current_network.dtim_period;
+			else
+				MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
+			pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
+		}
+		{
+			u8 LPSAwakeIntvl_tmp = 0;
+			u8 period = ieee->current_network.dtim_period;
+			u8 count = ieee->current_network.tim.tim_count;
+			if(count == 0 ) {
+				if(pPSC->LPSAwakeIntvl > period)
+					LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
+				else
+					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+
+			} else {
+				if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
+					LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
+				else
+					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+			}
+		
+		*time_l = ieee->current_network.last_dtim_sta_time[0] 
+			+ MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp); 
+	}
+	}
+	
+	if(time_h){
+#ifdef _RTL8192_EXT_PATCH_
+		if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
+			*time_h =1;
+		else
+			*time_h =0;
+#else
+		*time_h = ieee->current_network.last_dtim_sta_time[1];
+		if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
+			*time_h += 1;
+#endif
+	}
+	
+	return 1;
+	
+	
+}
+
+inline void rtllib_sta_ps(struct rtllib_device *ieee)
+{
+
+	u32 th,tl;
+	short sleep;
+	
+	unsigned long flags,flags2;
+	
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if((ieee->ps == RTLLIB_PS_DISABLED ||
+		ieee->iw_mode != IW_MODE_INFRA || 
+		ieee->state != RTLLIB_LINKED)){
+		
+		printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
+			__FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
+		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+		
+		rtllib_sta_wakeup(ieee, 1);	
+		
+		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+	}
+	
+	sleep = rtllib_sta_ps_sleep(ieee,&th, &tl);
+	/* 2 wake, 1 sleep, 0 do nothing */
+	if(sleep == 0)
+	{
+		goto out;
+	}
+	if(sleep == 1){
+		if(ieee->sta_sleep == 1){
+			ieee->enter_sleep_state(ieee->dev,th,tl);
+		}
+		
+		else if(ieee->sta_sleep == 0){
+			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+			
+			if(ieee->ps_is_queue_empty(ieee->dev)){
+				ieee->sta_sleep = 2;
+				ieee->ack_tx_to_ieee = 1;
+				rtllib_sta_ps_send_null_frame(ieee,1);
+				ieee->ps_th = th;
+				ieee->ps_tl = tl;
+			}		
+			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+			
+		}
+		
+		ieee->bAwakePktSent = false;
+		
+	}else if(sleep == 2){
+		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+			
+		rtllib_sta_wakeup(ieee,1);
+		
+		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+	}
+
+out:	
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+}
+
+void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
+{
+	if(ieee->sta_sleep == 0){
+		if(nl){
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+			{
+				ieee->ack_tx_to_ieee = 1;
+				rtllib_sta_ps_send_null_frame(ieee, 0);
+			}
+			else 
+			{
+				ieee->ack_tx_to_ieee = 1;
+				rtllib_sta_ps_send_pspoll_frame(ieee);
+			}
+		}
+		return;
+		
+	}
+	
+	if(ieee->sta_sleep == 1) 
+		ieee->sta_wake_up(ieee->dev);
+	if(nl){
+		/*		
+			ieee->ack_tx_to_ieee = 1;
+			printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+			rtllib_sta_ps_send_null_frame(ieee, 0);
+		*/
+		if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+		{
+			ieee->ack_tx_to_ieee = 1;
+			rtllib_sta_ps_send_null_frame(ieee, 0);
+		}
+		else 
+		{
+			ieee->ack_tx_to_ieee = 1;
+			ieee->polling = true;
+			rtllib_sta_ps_send_pspoll_frame(ieee);
+		}
+
+	} else {
+		ieee->sta_sleep = 0;
+		ieee->polling = false;
+	}
+}
+
+void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success)
+{
+	unsigned long flags,flags2;
+	
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if(ieee->sta_sleep == 2){
+		/* Null frame with PS bit set */
+		if(success){
+			ieee->sta_sleep = 1;
+			ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
+		}
+		/* if the card report not success we can't be sure the AP
+		 * has not RXed so we can't assume the AP believe us awake
+		 */
+	} else {/* 21112005 - tx again null without PS bit if lost */
+	
+		if((ieee->sta_sleep == 0) && !success){
+			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+			{
+				rtllib_sta_ps_send_null_frame(ieee, 0);
+			}
+			else 
+			{
+				rtllib_sta_ps_send_pspoll_frame(ieee);
+			}
+			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+		}
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+void rtllib_process_action(struct rtllib_device* ieee, struct sk_buff* skb)
+{
+	struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+	u8* act = rtllib_get_payload((struct rtllib_hdr *)header);
+	u8 category = 0;
+
+	if (act == NULL) {
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "error to get payload of action frame\n");
+		return;
+	}
+
+	category = *act;
+	act ++;
+	switch (category) {
+		case ACT_CAT_BA:
+			switch (*act) {
+				case ACT_ADDBAREQ:
+					rtllib_rx_ADDBAReq(ieee, skb);
+					break;
+				case ACT_ADDBARSP:
+					rtllib_rx_ADDBARsp(ieee, skb);
+					break;
+				case ACT_DELBA:
+					rtllib_rx_DELBA(ieee, skb);
+					break;
+			}
+			break;
+		default:
+			break;
+	}
+	return;
+}
+
+#ifdef _RTL8192_EXT_PATCH_      
+void rtllib_process_action_mesh(struct rtllib_device* ieee, struct sk_buff* skb,
+		struct rtllib_rx_stats *rx_stats)
+{
+	struct rtllib_hdr_3addr *header = NULL;
+	u8* act = NULL;
+	u8 category = 0;
+
+#ifdef COMPATIBLE_WITH_RALINK_MESH	
+	memmove(skb->data + WLAN_MESH_HDR_LEN, skb->data, sizeof(struct rtllib_hdr_3addr));
+	skb_pull(skb, WLAN_MESH_HDR_LEN);
+#endif
+	
+	header = (struct rtllib_hdr_3addr *) skb->data;
+	act = rtllib_get_payload((struct rtllib_hdr *)header);
+
+	if (act == NULL) {
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "error to get payload of action frame\n");
+		return;
+	}
+	if (ieee->iw_mode != IW_MODE_MESH) {
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n");
+		return;
+	}
+
+	category = *act;
+	act ++;
+	switch (category) {
+		case ACT_CAT_MESH_PEERLINK_MGNT:
+			if(ieee->iw_mode != IW_MODE_MESH) {
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "peerlink received not in mesh mode\n");
+				return;
+			}
+			switch (*act) {
+				case ACT_PEERLINK_OPEN:
+					if (ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open(ieee, skb, rx_stats);
+					}
+					break;
+				case ACT_PEERLINK_CONFIRM:
+					if (ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm(ieee, skb);
+					}
+					break;
+				case ACT_PEERLINK_CLOSE:
+					if ( ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close(ieee, skb);
+					}
+					break;
+			}
+			break;
+		case ACT_CAT_MESH_LINK_METRIC:
+			if (ieee->iw_mode != IW_MODE_MESH) {
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "link metric received not in mesh mode\n");
+				return;
+			}
+			switch (*act) {
+				case ACT_LINKMETRIC_REQ:
+					if (ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req(
+								ieee, skb);
+					}
+					break;
+				case ACT_LINKMETRIC_RSP:
+					if (ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report(
+								ieee, skb);
+					}
+					break;
+			}
+
+			break;
+		case ACT_CAT_MESH_PATH_SELECT:
+			if (ieee->iw_mode != IW_MODE_MESH) {
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n");
+				return;
+			}
+
+			switch (*act) {
+				case ACT_PATH_REQ:
+					if( ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq(
+								ieee, skb, rx_stats);
+					}
+					break;
+				case ACT_PATH_REPLY:
+					if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep(
+								ieee, skb, rx_stats);
+					}
+					break;
+				case ACT_PATH_ERR:
+					if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr(
+								ieee, skb, rx_stats);
+					}
+					break;
+				case ACT_RANN:
+					if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann) {
+						ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann(
+								ieee, skb, rx_stats);
+					}
+					break;
+			}
+			break;
+		case ACT_CAT_MESH_INTERWORKING:
+			if (ieee->iw_mode != IW_MODE_MESH) {
+				RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n");
+				return;
+			}
+			if (*act == 0) {
+				if (ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann) {
+					ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann(
+							ieee, skb, rx_stats);
+				}
+			}
+			break;
+		default:
+			break;
+	}
+	return;
+}
+#endif
+
+inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb,
+			struct rtllib_rx_stats *rx_stats, u16 type,
+			u16 stype)
+{
+	struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+	u8* ies;
+	u16 errcode;
+	u8* challenge;
+	int chlen=0;
+	int aid;
+#ifdef _RTL8192_EXT_PATCH_
+	u8 mesh_bssid[6] = {0,0,0,0,0,0};
+#endif
+	struct rtllib_assoc_response_frame *assoc_resp;
+	bool bSupportNmode = true, bHalfSupportNmode = false; 
+	
+#ifdef _RTL8192_EXT_PATCH_
+	if((!ieee->proto_started)&&(!ieee->mesh_started))
+#else
+	if(!ieee->proto_started)
+#endif
+		return 0;
+		
+	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+	
+		case RTLLIB_STYPE_ASSOC_RESP:
+		case RTLLIB_STYPE_REASSOC_RESP:
+		
+			RTLLIB_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
+					WLAN_FC_GET_STYPE(header->frame_ctl));
+			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+				ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATED && 
+#ifdef _RTL8192_EXT_PATCH_
+				((ieee->iw_mode == IW_MODE_INFRA) || 
+				(ieee->iw_mode == IW_MODE_MESH && ieee->only_mesh == 0)))
+#else
+				(ieee->iw_mode == IW_MODE_INFRA)) 
+#endif
+			{
+				if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+					struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network), GFP_ATOMIC);
+#else
+					struct rtllib_network *network = kmalloc(sizeof(*network), GFP_KERNEL);
+#endif
+					if (!network) {
+						return 1;
+					}
+					memset(network,0,sizeof(*network));
+					ieee->state=RTLLIB_LINKED;
+					ieee->assoc_id = aid;
+					ieee->softmac_stats.rx_ass_ok++;
+					/* station support qos */
+					/* Let the register setting defaultly with Legacy station */
+					assoc_resp = (struct rtllib_assoc_response_frame*)skb->data;
+					if(ieee->current_network.qos_data.supported == 1) {
+						if (rtllib_parse_info_param(ieee,assoc_resp->info_element,\
+									rx_stats->len - sizeof(*assoc_resp),\
+									network,rx_stats)){
+							kfree(network);
+							return 1;
+						}
+						else
+						{	
+							memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
+							memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
+						}
+						if (ieee->handle_assoc_response != NULL)
+							ieee->handle_assoc_response(ieee->dev, (struct rtllib_assoc_response_frame*)header, network);
+						kfree(network);
+					}
+
+					if(ieee->assocresp_ies){
+						kfree(ieee->assocresp_ies);
+						ieee->assocresp_ies = NULL;
+					}
+					ies = &(assoc_resp->info_element[0].id);
+					ieee->assocresp_ies_len = (skb->data + skb->len) - ies;
+					ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len, GFP_ATOMIC);
+					if (ieee->assocresp_ies)
+						memcpy(ieee->assocresp_ies, ies, ieee->assocresp_ies_len);
+					else{
+						printk("%s()Warning: can't alloc memory for assocresp_ies\n", __func__);
+						ieee->assocresp_ies_len = 0;
+					}	
+#ifdef RTL8192S_WAPI_SUPPORT
+					{
+						PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo);
+						PRT_WAPI_STA_INFO pWapiSta;
+						u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+						u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;	
+						if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable))
+						{
+							pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+							list_del_init(&pWapiSta->list);
+							list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList);
+							WAPI_TRACE(WAPI_API, "%s(): New WAPI STA ("MAC_FMT")!!\n",__FUNCTION__,MAC_ARG(ieee->current_network.bssid));
+							memcpy(pWapiSta->PeerMacAddr,ieee->current_network.bssid,6);
+							memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+							memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+							pWapiInfo->bFirstAuthentiateInProgress= true;
+							pWapiInfo->assoRspWapiIE[0] = MFIE_TYPE_WAPI;
+							pWapiInfo->assoRspWapiIE[1] = network->wapi_ie_len;
+							pWapiInfo->assoRspWapiIELength = network->wapi_ie_len+2;
+							memcpy(pWapiInfo->assoRspWapiIE+2,network->wapi_ie,network->wapi_ie_len);
+						}
+					}
+#endif	
+					rtllib_associate_complete(ieee);
+				} else {
+					/* aid could not been allocated */
+					ieee->softmac_stats.rx_ass_err++;
+					printk(
+						"Association response status code 0x%x\n",
+						errcode);
+					RTLLIB_DEBUG_MGMT(
+						"Association response status code 0x%x\n",
+						errcode);
+					if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
+						queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0);
+					} else {
+						rtllib_associate_abort(ieee); 
+					}
+				}
+			}
+			break;
+		
+		case RTLLIB_STYPE_ASSOC_REQ:
+		case RTLLIB_STYPE_REASSOC_REQ:
+		
+			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+				ieee->iw_mode == IW_MODE_MASTER)
+					
+				rtllib_rx_assoc_rq(ieee, skb);
+			break;
+			
+		case RTLLIB_STYPE_AUTH:
+#ifdef _RTL8192_EXT_PATCH_
+			if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_frame_softmac_on_auth && ieee->mesh_started && ((memcmp(header->addr3, ieee->current_network.bssid, 6)) || (memcmp(ieee->current_network.bssid, mesh_bssid, 6) == 0))) 
+				ieee->ext_patch_rtllib_rx_frame_softmac_on_auth(ieee, skb, rx_stats);
+			else
+#endif
+			if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
+				if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING && 
+#ifdef _RTL8192_EXT_PATCH_
+					((ieee->iw_mode == IW_MODE_INFRA)||
+					((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))))
+#else
+					(ieee->iw_mode == IW_MODE_INFRA))
+#endif
+				{
+						RTLLIB_DEBUG_MGMT("Received authentication response");
+						
+						if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
+							if(ieee->open_wep || !challenge){
+								ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED;
+								ieee->softmac_stats.rx_auth_rs_ok++;
+								if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
+								{
+									if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
+									{
+										if(IsHTHalfNmodeAPs(ieee))
+										{	
+											bSupportNmode = true;
+											bHalfSupportNmode = true;
+										}
+										else
+										{
+											bSupportNmode = false;
+											bHalfSupportNmode = false;
+										}
+									printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
+									}
+								}								
+								/* Dummy wirless mode setting to avoid encryption issue */
+								if(bSupportNmode) {
+									ieee->SetWirelessMode(ieee->dev, \
+											ieee->current_network.mode);
+								}else{
+									/*TODO*/
+									ieee->SetWirelessMode(ieee->dev, IEEE_G);
+								}
+
+								if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
+								{
+									printk("===============>entern half N mode\n");
+									ieee->bHalfWirelessN24GMode = true;
+								}
+								else
+									ieee->bHalfWirelessN24GMode = false;
+								
+								rtllib_associate_step2(ieee);
+							}else{
+								rtllib_auth_challenge(ieee, challenge, chlen);
+							}
+						}else{
+							ieee->softmac_stats.rx_auth_rs_err++;
+							RTLLIB_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
+
+							printk("Authentication respose status code 0x%x",errcode);
+							rtllib_associate_abort(ieee);
+						}
+						
+					}else if (ieee->iw_mode == IW_MODE_MASTER){
+						rtllib_rx_auth_rq(ieee, skb);
+					}
+				}
+			break;
+#if 0				
+		case RTLLIB_STYPE_PROBE_REQ:
+
+			if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && 
+				((ieee->iw_mode == IW_MODE_ADHOC || 
+				ieee->iw_mode == IW_MODE_MASTER) &&
+				ieee->state == RTLLIB_LINKED)){
+				rtllib_rx_probe_rq(ieee, skb);
+			}
+			break;
+#endif			
+		case RTLLIB_STYPE_DISASSOC:
+		case RTLLIB_STYPE_DEAUTH:
+
+			if(memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0)
+				break;
+			/* FIXME for now repeat all the association procedure 
+			* both for disassociation and deauthentication
+			*/
+			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+				ieee->state == RTLLIB_LINKED && 
+#ifdef _RTL8192_EXT_PATCH_
+				((ieee->iw_mode == IW_MODE_INFRA) ||
+				((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))))
+#else
+				(ieee->iw_mode == IW_MODE_INFRA))
+#endif
+			{
+				printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct rtllib_disassoc*)skb->data)->reason);	
+				ieee->state = RTLLIB_ASSOCIATING;
+				ieee->softmac_stats.reassoc++;
+				ieee->is_roaming = true;
+				ieee->LinkDetectInfo.bBusyTraffic = false;
+				rtllib_disassociate(ieee);
+				RemovePeerTS(ieee, header->addr2); 	
+				if(ieee->LedControlHandler != NULL)
+				        ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); 
+				queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 5);
+			}
+			break;
+		case RTLLIB_STYPE_MANAGE_ACT:
+			rtllib_process_action(ieee,skb);
+#ifdef _RTL8192_EXT_PATCH_
+			rtllib_process_action_mesh(ieee,skb,rx_stats);
+#endif
+			break;
+#ifdef COMPATIBLE_WITH_RALINK_MESH
+		case RTLLIB_STYPE_MESH_ACT:
+			rtllib_process_action_mesh(ieee,skb,rx_stats);
+			break;
+#endif			
+		default: 
+			return -1;
+			break;
+	}
+	
+	return 0;
+}
+
+/* following are for a simplier TX queue management.
+ * Instead of using netif_[stop/wake]_queue the driver
+ * will uses these two function (plus a reset one), that
+ * will internally uses the kernel netif_* and takes
+ * care of the ieee802.11 fragmentation.
+ * So the driver receives a fragment per time and might
+ * call the stop function when it want without take care
+ * to have enought room to TX an entire packet.
+ * This might be useful if each fragment need it's own
+ * descriptor, thus just keep a total free memory > than
+ * the max fragmentation treshold is not enought.. If the
+ * ieee802.11 stack passed a TXB struct then you needed  
+ * to keep N free descriptors where 
+ * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
+ * In this way you need just one and the 802.11 stack
+ * will take care of buffering fragments and pass them to 
+ * to the driver later, when it wakes the queue.
+ */ 
+void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee)
+{
+
+	unsigned int queue_index = txb->queue_index;
+	unsigned long flags;
+	int  i;
+	cb_desc *tcb_desc = NULL;
+	unsigned long queue_len = 0;
+
+	spin_lock_irqsave(&ieee->lock,flags);
+
+	/* called with 2nd parm 0, no tx mgmt lock required */
+	rtllib_sta_wakeup(ieee,0);
+
+	/* update the tx status */
+	tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
+	if(tcb_desc->bMulticast) {
+		ieee->stats.multicast++;
+	}
+#if 1
+	/* if xmit available, just xmit it immediately, else just insert it to the wait queue */
+	for(i = 0; i < txb->nr_frags; i++) {
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+		queue_len = skb_queue_len(&ieee->skb_drv_aggQ[queue_index]);
+#else
+		queue_len = skb_queue_len(&ieee->skb_waitQ[queue_index]);
+#endif
+		if((queue_len  != 0) ||\
+			(!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
+		       (ieee->queue_stop)) {
+			/* insert the skb packet to the wait queue */
+			/* as for the completion function, it does not need 
+			 * to check it any more.
+			 * */
+#ifdef WIFI_TEST
+			if (1) 
+#else
+			if(queue_len < 200)
+#endif
+			{
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+				skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
+#else
+				skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
+#endif
+			}else{
+				kfree_skb(txb->fragments[i]);
+			}
+		}else{
+			ieee->softmac_data_hard_start_xmit(
+					txb->fragments[i],
+					ieee->dev,ieee->rate);
+		}
+	}	
+#endif
+	rtllib_txb_free(txb);
+
+	spin_unlock_irqrestore(&ieee->lock,flags);
+
+}
+
+/* called with ieee->lock acquired */
+void rtllib_resume_tx(struct rtllib_device *ieee)
+{
+	int i;
+	for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
+		
+		if (ieee->queue_stop){
+			ieee->tx_pending.frag = i;
+			return;
+		}else{
+		
+			ieee->softmac_data_hard_start_xmit( 
+				ieee->tx_pending.txb->fragments[i],
+				ieee->dev,ieee->rate);
+			ieee->stats.tx_packets++;
+		}
+	}
+	
+	rtllib_txb_free(ieee->tx_pending.txb);
+	ieee->tx_pending.txb = NULL;
+}
+
+
+void rtllib_reset_queue(struct rtllib_device *ieee)
+{
+	unsigned long flags;
+	
+	spin_lock_irqsave(&ieee->lock,flags);
+	init_mgmt_queue(ieee);
+	if (ieee->tx_pending.txb){
+		rtllib_txb_free(ieee->tx_pending.txb);
+		ieee->tx_pending.txb = NULL;
+	}
+	ieee->queue_stop = 0;
+	spin_unlock_irqrestore(&ieee->lock,flags);
+
+}
+
+void rtllib_wake_queue(struct rtllib_device *ieee)
+{
+
+	unsigned long flags;
+	struct sk_buff *skb;
+	struct rtllib_hdr_3addr  *header;
+	
+	spin_lock_irqsave(&ieee->lock,flags);
+	if (! ieee->queue_stop) goto exit;
+	
+	ieee->queue_stop = 0;
+	
+	if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
+		while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
+			
+			header = (struct rtllib_hdr_3addr  *) skb->data;
+			
+			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+			if (ieee->seq_ctrl[0] == 0xFFF)
+				ieee->seq_ctrl[0] = 0;
+			else
+				ieee->seq_ctrl[0]++;
+
+			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
+		}
+	}
+	if (!ieee->queue_stop && ieee->tx_pending.txb)
+		rtllib_resume_tx(ieee);
+	
+	if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
+		ieee->softmac_stats.swtxawake++;
+		netif_wake_queue(ieee->dev);
+	}
+	
+exit :
+	spin_unlock_irqrestore(&ieee->lock,flags);
+}
+
+
+void rtllib_stop_queue(struct rtllib_device *ieee)
+{
+
+	if (! netif_queue_stopped(ieee->dev)){
+		netif_stop_queue(ieee->dev);
+		ieee->softmac_stats.swtxstop++;
+	}
+	ieee->queue_stop = 1;
+	
+}
+
+void rtllib_stop_all_queues(struct rtllib_device *ieee)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
+	unsigned int i;
+	for(i=0; i < ieee->dev->num_tx_queues; i++)
+                netdev_get_tx_queue(ieee->dev,i)->trans_start = jiffies;
+#else
+	ieee->dev->trans_start = jiffies;
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 
+	netif_carrier_off(ieee->dev);
+#else
+	netif_tx_stop_all_queues(ieee->dev);
+#endif
+}
+
+void rtllib_wake_all_queues(struct rtllib_device *ieee)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 
+	netif_carrier_on(ieee->dev);
+#else
+	netif_tx_wake_all_queues(ieee->dev);
+#endif
+}
+
+inline void rtllib_randomize_cell(struct rtllib_device *ieee)
+{
+	
+	get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
+	
+	/* an IBSS cell address must have the two less significant
+	 * bits of the first byte = 2 
+	 */
+	ieee->current_network.bssid[0] &= ~0x01;
+	ieee->current_network.bssid[0] |= 0x02;
+}
+
+/* called in user context only */
+void rtllib_start_master_bss(struct rtllib_device *ieee)
+{
+	ieee->assoc_id = 1;
+	
+	if (ieee->current_network.ssid_len == 0){
+		strncpy(ieee->current_network.ssid, 
+			RTLLIB_DEFAULT_TX_ESSID,
+			IW_ESSID_MAX_SIZE);
+			
+		ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID);
+		ieee->ssid_set = 1;
+	}
+	
+	memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
+	 
+	ieee->set_chan(ieee->dev, ieee->current_network.channel);
+	ieee->state = RTLLIB_LINKED;
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+		WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+	}
+#endif
+	ieee->link_change(ieee->dev);
+	notify_wx_assoc_event(ieee);
+	
+	if (ieee->data_hard_resume)
+		ieee->data_hard_resume(ieee->dev);
+	
+	netif_carrier_on(ieee->dev);
+}
+
+void rtllib_start_monitor_mode(struct rtllib_device *ieee)
+{
+	/* reset hardware status */
+	if(ieee->raw_tx){
+		if (ieee->data_hard_resume)
+			ieee->data_hard_resume(ieee->dev);
+	
+		netif_carrier_on(ieee->dev);
+	}
+}
+
+void rtllib_start_ibss_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, start_ibss_wq);
+	/* iwconfig mode ad-hoc will schedule this and return
+	 * on the other hand this will block further iwconfig SET
+	 * operations because of the wx_sem hold.
+	 * Anyway some most set operations set a flag to speed-up
+	 * (abort) this wq (when syncro scanning) before sleeping 
+	 * on the semaphore
+	 */
+	if(!ieee->proto_started){
+		printk("==========oh driver down return\n");
+		return;
+	}
+	down(&ieee->wx_sem);
+	
+	if (ieee->current_network.ssid_len == 0){
+		strcpy(ieee->current_network.ssid,RTLLIB_DEFAULT_TX_ESSID);
+		ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID);
+		ieee->ssid_set = 1;
+	} 
+	
+	ieee->state = RTLLIB_NOLINK;
+#ifdef ADHOC_11N
+	ieee->mode = IEEE_N_24G;
+#else
+	ieee->mode = IEEE_G;
+#endif
+	/* check if we have this cell in our network list */
+	rtllib_softmac_check_all_nets(ieee);
+	
+
+	/* if not then the state is not linked. Maybe the user swithced to
+	 * ad-hoc mode just after being in monitor mode, or just after
+	 * being very few time in managed mode (so the card have had no
+	 * time to scan all the chans..) or we have just run up the iface
+	 * after setting ad-hoc mode. So we have to give another try..
+	 * Here, in ibss mode, should be safe to do this without extra care
+	 * (in bss mode we had to make sure no-one tryed to associate when
+	 * we had just checked the ieee->state and we was going to start the
+	 * scan) beacause in ibss mode the rtllib_new_net function, when
+	 * finds a good net, just set the ieee->state to RTLLIB_LINKED,
+	 * so, at worst, we waste a bit of time to initiate an unneeded syncro
+	 * scan, that will stop at the first round because it sees the state
+	 * associated.
+	 */
+	if (ieee->state == RTLLIB_NOLINK)
+		rtllib_start_scan_syncro(ieee, 0);
+
+	/* the network definitively is not here.. create a new cell */
+	if (ieee->state == RTLLIB_NOLINK){
+		printk("creating new IBSS cell\n"); 
+		ieee->current_network.channel = ieee->IbssStartChnl;
+		if(!ieee->wap_set)
+			rtllib_randomize_cell(ieee);
+		
+		if(ieee->modulation & RTLLIB_CCK_MODULATION){
+		
+			ieee->current_network.rates_len = 4;
+			
+			ieee->current_network.rates[0] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB;
+			ieee->current_network.rates[1] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB;
+			ieee->current_network.rates[2] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB;
+			ieee->current_network.rates[3] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB;
+				
+		}else
+			ieee->current_network.rates_len = 0;
+		
+		if(ieee->modulation & RTLLIB_OFDM_MODULATION){
+			ieee->current_network.rates_ex_len = 8;
+			
+			/*ieee->current_network.rates_ex[0] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB;
+			ieee->current_network.rates_ex[1] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB;
+			ieee->current_network.rates_ex[2] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB;
+			ieee->current_network.rates_ex[3] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB;
+			ieee->current_network.rates_ex[4] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB;
+			ieee->current_network.rates_ex[5] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB;
+			ieee->current_network.rates_ex[6] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB;
+			ieee->current_network.rates_ex[7] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB;*/
+
+			ieee->current_network.rates_ex[0] = RTLLIB_OFDM_RATE_6MB;
+			ieee->current_network.rates_ex[1] = RTLLIB_OFDM_RATE_9MB;
+			ieee->current_network.rates_ex[2] = RTLLIB_OFDM_RATE_12MB;
+			ieee->current_network.rates_ex[3] = RTLLIB_OFDM_RATE_18MB;
+			ieee->current_network.rates_ex[4] = RTLLIB_OFDM_RATE_24MB;
+			ieee->current_network.rates_ex[5] = RTLLIB_OFDM_RATE_36MB;
+			ieee->current_network.rates_ex[6] = RTLLIB_OFDM_RATE_48MB;
+			ieee->current_network.rates_ex[7] = RTLLIB_OFDM_RATE_54MB;
+			
+			ieee->rate = 108;
+		}else{
+			ieee->current_network.rates_ex_len = 0;
+			ieee->rate = 22;
+		}
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+#ifdef ADHOC_11N
+		ieee->current_network.qos_data.supported = 1;
+#else
+		ieee->current_network.qos_data.supported = 0;
+#endif
+		ieee->SetWirelessMode(ieee->dev, ieee->mode);
+#else
+		ieee->current_network.qos_data.supported = 0;
+		ieee->SetWirelessMode(ieee->dev, IEEE_G);	
+#endif
+		ieee->current_network.mode = ieee->mode;
+		ieee->current_network.atim_window = 0;
+		ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
+	}
+
+	printk("%s(): ieee->mode = %d\n", __FUNCTION__, ieee->mode);
+	if((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G))
+		HTUseDefaultSetting(ieee);
+	else
+		ieee->pHTInfo->bCurrentHTSupport = false;	
+
+	ieee->SetHwRegHandler(ieee->dev, HW_VAR_MEDIA_STATUS, (u8 *)(&ieee->state));
+
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){
+		WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0);
+	}
+#endif		
+	ieee->state = RTLLIB_LINKED;
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->set_chan(ieee->dev, ieee->current_network.channel);  
+#endif
+	ieee->link_change(ieee->dev);
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+
+	if(ieee->pHTInfo->bCurBW40MHz)
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+	else
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+#else
+	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+#endif
+	if(ieee->LedControlHandler != NULL)
+	        ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
+	
+	rtllib_start_send_beacons(ieee);
+	
+	notify_wx_assoc_event(ieee);
+	
+	if (ieee->data_hard_resume)
+		ieee->data_hard_resume(ieee->dev);
+
+	netif_carrier_on(ieee->dev);
+	
+	up(&ieee->wx_sem);
+}
+
+inline void rtllib_start_ibss(struct rtllib_device *ieee)
+{
+	queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq, MSECS(150));
+}
+
+/* this is called only in user context, with wx_sem held */
+void rtllib_start_bss(struct rtllib_device *ieee)
+{
+	unsigned long flags;
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
+	{
+		if(! ieee->bGlobalDomain)
+		{
+			return;
+		}
+	}
+#endif	
+	/* check if we have already found the net we
+	 * are interested in (if any).
+	 * if not (we are disassociated and we are not
+	 * in associating / authenticating phase) start the background scanning.
+	 */
+	rtllib_softmac_check_all_nets(ieee);
+	
+	/* ensure no-one start an associating process (thus setting
+	 * the ieee->state to rtllib_ASSOCIATING) while we
+	 * have just cheked it and we are going to enable scan.
+	 * The rtllib_new_net function is always called with
+	 * lock held (from both rtllib_softmac_check_all_nets and
+	 * the rx path), so we cannot be in the middle of such function
+	 */
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if (ieee->state == RTLLIB_NOLINK) {
+		rtllib_start_scan(ieee);
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+void rtllib_link_change_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, link_change_wq);
+	ieee->link_change(ieee->dev);
+}
+/* called only in userspace context */
+void rtllib_disassociate(struct rtllib_device *ieee)
+{
+	netif_carrier_off(ieee->dev);
+	if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
+			rtllib_reset_queue(ieee);
+	
+	if (ieee->data_hard_stop)
+			ieee->data_hard_stop(ieee->dev);
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee))
+		Dot11d_Reset(ieee);
+#endif
+	ieee->state = RTLLIB_NOLINK;
+	ieee->is_set_key = false;
+	ieee->wap_set = 0;
+
+	queue_delayed_work_rsl(ieee->wq, &ieee->link_change_wq, 0);
+
+
+#ifndef FOR_ANDROID_X86
+	notify_wx_assoc_event(ieee);
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	printk("==============> %s()\n", __FUNCTION__);
+	WapiReturnOneStaInfo(ieee, ieee->current_network.bssid, 0);
+#endif
+}
+#ifdef RTL8192S_WAPI_SUPPORT
+void ieee80211_disassociate_from_app(struct rtllib_device *ieee)
+{
+	netif_carrier_off(ieee->dev);
+	if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
+			rtllib_reset_queue(ieee);
+	
+	if (ieee->data_hard_stop)
+			ieee->data_hard_stop(ieee->dev);
+#ifdef ENABLE_DOT11D
+	if(IS_DOT11D_ENABLE(ieee))
+		Dot11d_Reset(ieee);
+#endif
+	ieee->state = RTLLIB_NOLINK;
+	ieee->is_set_key = false;
+	ieee->wap_set = 0;
+
+	queue_delayed_work_rsl(ieee->wq, &ieee->link_change_wq, 0);
+
+
+#ifndef FOR_ANDROID_X86
+	notify_wx_assoc_event(ieee);
+#endif
+	
+	printk("==============> %s()\n", __FUNCTION__);
+	WapiReturnOneStaInfo(ieee, ieee->current_network.bssid, 1);
+}
+
+#endif
+void rtllib_associate_retry_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, associate_retry_wq);
+	unsigned long flags;
+	
+	down(&ieee->wx_sem);
+	if(!ieee->proto_started)
+		goto exit;
+		
+	if(ieee->state != RTLLIB_ASSOCIATING_RETRY)
+		goto exit;
+		
+	/* until we do not set the state to RTLLIB_NOLINK 
+	* there are no possibility to have someone else trying
+	* to start an association procdure (we get here with
+	* ieee->state = RTLLIB_ASSOCIATING).
+	* When we set the state to RTLLIB_NOLINK it is possible
+	* that the RX path run an attempt to associate, but
+	* both rtllib_softmac_check_all_nets and the
+	* RX path works with ieee->lock held so there are no
+	* problems. If we are still disassociated then start a scan.
+	* the lock here is necessary to ensure no one try to start
+	* an association procedure when we have just checked the 
+	* state and we are going to start the scan.
+	*/
+	ieee->beinretry = true;
+	ieee->state = RTLLIB_NOLINK;
+
+	rtllib_softmac_check_all_nets(ieee);
+	
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if(ieee->state == RTLLIB_NOLINK)
+	{
+		rtllib_start_scan(ieee);
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+
+	ieee->beinretry = false;
+exit:
+	up(&ieee->wx_sem);
+}
+
+struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
+{
+	u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	
+	struct sk_buff *skb;
+	struct rtllib_probe_response *b;
+#ifdef _RTL8192_EXT_PATCH_
+	if((ieee->iw_mode == IW_MODE_MESH)&&(ieee->ext_patch_get_beacon_get_probersp ))
+		skb = ieee->ext_patch_get_beacon_get_probersp(ieee, broadcast_addr, &(ieee->current_mesh_network));
+	else
+		skb = rtllib_probe_resp(ieee, broadcast_addr);
+#else
+	skb = rtllib_probe_resp(ieee, broadcast_addr);
+#endif
+	
+	if (!skb) 
+		return NULL;
+	
+	b = (struct rtllib_probe_response *) skb->data;
+	b->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_BEACON);
+		
+	return skb;
+	
+}
+
+struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee)
+{
+	struct sk_buff *skb;
+	struct rtllib_probe_response *b;
+	
+	skb = rtllib_get_beacon_(ieee);
+	if(!skb) 
+		return NULL;
+		
+	b = (struct rtllib_probe_response *) skb->data;	
+	b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+	
+	if (ieee->seq_ctrl[0] == 0xFFF)
+		ieee->seq_ctrl[0] = 0;
+	else
+		ieee->seq_ctrl[0]++;
+	
+	return skb;
+}
+
+#ifdef _RTL8192_EXT_PATCH_	
+void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown)
+#else
+void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,u8 shutdown)
+#endif
+{
+	rtllib_stop_scan_syncro(ieee);
+	down(&ieee->wx_sem);
+#ifdef _RTL8192_EXT_PATCH_	
+	if(mesh_flag) {
+		rtllib_stop_mesh_protocol(ieee);
+	}
+	else
+#endif	
+		rtllib_stop_protocol(ieee,shutdown);
+	up(&ieee->wx_sem);
+}
+
+
+void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown)
+{
+	if (!ieee->proto_started)
+		return;
+	
+	if(shutdown){
+	ieee->proto_started = 0;
+		ieee->proto_stoppping = 1;
+#ifdef ENABLE_IPS
+		if(ieee->rtllib_ips_leave != NULL)
+			ieee->rtllib_ips_leave(ieee->dev);
+#endif
+	}
+	
+	rtllib_stop_send_beacons(ieee);
+	del_timer_sync(&ieee->associate_timer);
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	del_timer_sync(&ieee->ibss_wait_timer);
+#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	cancel_delayed_work(&ieee->associate_retry_wq);	
+	cancel_delayed_work(&ieee->start_ibss_wq);
+	cancel_delayed_work(&ieee->link_change_wq);
+#endif	
+	rtllib_stop_scan(ieee);
+
+	if(ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)
+		ieee->state = RTLLIB_NOLINK;
+
+	if (ieee->state == RTLLIB_LINKED){
+		if (ieee->iw_mode == IW_MODE_INFRA)
+			SendDisassociation(ieee,1,deauth_lv_ss);
+		rtllib_disassociate(ieee);
+	}
+	
+	if(shutdown){
+		RemoveAllTS(ieee); 
+		ieee->proto_stoppping = 0;
+#ifdef RTL8192S_WAPI_SUPPORT
+		if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable))
+		{
+			WapiReturnAllStaInfo(ieee);
+		}
+#endif
+	}
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	if(ieee->iw_mode == IW_MODE_ADHOC) 
+		DelStaInfoList(ieee);
+#endif
+
+	if(ieee->assocreq_ies){
+		kfree(ieee->assocreq_ies);
+		ieee->assocreq_ies = NULL;
+		ieee->assocreq_ies_len = 0;
+	}
+	if(ieee->assocresp_ies){
+		kfree(ieee->assocresp_ies);
+		ieee->assocresp_ies = NULL;
+		ieee->assocresp_ies_len = 0;
+	}
+}
+
+#ifdef _RTL8192_EXT_PATCH_	
+void rtllib_stop_mesh_protocol(struct rtllib_device *ieee)
+{
+	if (!ieee->mesh_started)
+		return;
+	ieee->mesh_started = 0;
+
+	if(ieee->ext_patch_rtllib_stop_protocol)
+		ieee->ext_patch_rtllib_stop_protocol(ieee,0);
+	
+	rtllib_stop_send_beacons(ieee);
+}
+#endif	
+
+#ifdef _RTL8192_EXT_PATCH_	
+void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag)
+#else
+void rtllib_softmac_start_protocol(struct rtllib_device *ieee)
+#endif	
+{
+	down(&ieee->wx_sem);
+#ifdef _RTL8192_EXT_PATCH_	
+	if (mesh_flag) {
+		rtllib_start_mesh_protocol(ieee);
+	}
+	else
+#endif	
+		rtllib_start_protocol(ieee);
+	up(&ieee->wx_sem);
+}
+
+void rtllib_start_protocol(struct rtllib_device *ieee)
+{
+	short ch = 0;
+ 	int i = 0;	
+
+	rtllib_update_active_chan_map(ieee);
+
+	if (ieee->proto_started)
+		return;
+		
+	ieee->proto_started = 1;
+	
+	if (ieee->current_network.channel == 0) {
+		do {
+			ch++;
+			if (ch > MAX_CHANNEL_NUMBER) 
+				return; /* no channel found */
+		} while(!ieee->active_channel_map[ch]);
+		ieee->current_network.channel = ch;
+	}
+	
+	if (ieee->current_network.beacon_interval == 0)
+		ieee->current_network.beacon_interval = 100;
+	
+	for(i = 0; i < 17; i++) {
+		ieee->last_rxseq_num[i] = -1;
+		ieee->last_rxfrag_num[i] = -1;
+		ieee->last_packet_time[i] = 0;
+	}
+
+	if(ieee->UpdateBeaconInterruptHandler)
+		ieee->UpdateBeaconInterruptHandler(ieee->dev, false);
+		
+	ieee->wmm_acm = 0;
+	/* if the user set the MAC of the ad-hoc cell and then
+	 * switch to managed mode, shall we  make sure that association
+	 * attempts does not fail just because the user provide the essid
+	 * and the nic is still checking for the AP MAC ??
+	 */
+#ifdef _RTL8192_EXT_PATCH_
+	if ((ieee->iw_mode == IW_MODE_INFRA) || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))  
+#else
+	if (ieee->iw_mode == IW_MODE_INFRA)  
+#endif		
+	{
+		rtllib_start_bss(ieee);
+	}else if (ieee->iw_mode == IW_MODE_ADHOC){
+		if(ieee->UpdateBeaconInterruptHandler)
+			ieee->UpdateBeaconInterruptHandler(ieee->dev, true);
+		
+		rtllib_start_ibss(ieee);
+		
+	}else if (ieee->iw_mode == IW_MODE_MASTER)
+		rtllib_start_master_bss(ieee);
+		
+	else if(ieee->iw_mode == IW_MODE_MONITOR)
+		rtllib_start_monitor_mode(ieee);	
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtllib_start_mesh_protocol(struct rtllib_device *ieee)
+{
+	short ch = 0;
+
+	rtllib_update_active_chan_map(ieee);
+
+	if (ieee->mesh_started)
+		return;
+
+	ieee->mesh_started = 1;
+	
+	if (ieee->current_mesh_network.channel == 0){
+		do {
+			ch++;
+			if (ch > MAX_CHANNEL_NUMBER) 
+				return; /* no channel found */
+		} while(ieee->active_channel_map[ch]);
+
+		ieee->current_mesh_network.channel = ch;
+	}
+	
+	if (ieee->current_mesh_network.beacon_interval == 0)
+		ieee->current_mesh_network.beacon_interval = 100;
+	ieee->wmm_acm = 0;
+
+	if(ieee->ext_patch_rtllib_start_mesh)
+		ieee->ext_patch_rtllib_start_mesh(ieee);
+}
+#endif
+
+
+#define DRV_NAME  "Ieee80211"
+void rtllib_softmac_init(struct rtllib_device *ieee)
+{
+	int i;
+	memset(&ieee->current_network, 0, sizeof(struct rtllib_network));
+	
+	ieee->state = RTLLIB_NOLINK;
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->mesh_state = RTLLIB_NOLINK;
+#endif
+	for(i = 0; i < 5; i++) {
+	  ieee->seq_ctrl[i] = 0;
+	}
+#ifdef ENABLE_DOT11D
+	ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
+	if (!ieee->pDot11dInfo)
+		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for DOT11D\n");
+	memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
+#endif
+	ieee->LinkDetectInfo.SlotIndex = 0;
+	ieee->LinkDetectInfo.SlotNum = 2;
+	ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
+        ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
+	ieee->LinkDetectInfo.NumTxOkInPeriod =0;
+	ieee->LinkDetectInfo.NumRxOkInPeriod =0;
+	ieee->LinkDetectInfo.NumRxUnicastOkInPeriod=0;
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->LinkDetectInfo.LastNumRxUnicast = 0;
+	ieee->LinkDetectInfo.LastNumTxUnicast = 0;
+	ieee->LinkDetectInfo.IdleCount = 0;
+#endif
+	ieee->bIsAggregateFrame = false;
+	ieee->assoc_id = 0;
+	ieee->queue_stop = 0;
+	ieee->scanning_continue = 0;
+	ieee->softmac_features = 0; 
+	ieee->wap_set = 0;
+	ieee->ssid_set = 0;
+	ieee->proto_started = 0;
+	ieee->proto_stoppping = 0;
+	ieee->basic_rate = RTLLIB_DEFAULT_BASIC_RATE;
+	ieee->rate = 22;
+	ieee->ps = RTLLIB_PS_DISABLED;
+	ieee->sta_sleep = 0;
+
+#ifdef _RTL8192_EXT_PATCH_
+	ieee->mesh_started = 0;
+#endif
+	ieee->Regdot11HTOperationalRateSet[0]= 0xff;
+	ieee->Regdot11HTOperationalRateSet[1]= 0xff;
+	ieee->Regdot11HTOperationalRateSet[4]= 0x01;
+
+	ieee->Regdot11TxHTOperationalRateSet[0]= 0xff;
+	ieee->Regdot11TxHTOperationalRateSet[1]= 0xff;
+	ieee->Regdot11TxHTOperationalRateSet[4]= 0x01;
+	
+	ieee->FirstIe_InScan = false;
+	ieee->actscanning = false;
+	ieee->beinretry = false;
+	ieee->is_set_key = false;
+	init_mgmt_queue(ieee);
+
+	ieee->sta_edca_param[0] = 0x0000A403;
+	ieee->sta_edca_param[1] = 0x0000A427;
+	ieee->sta_edca_param[2] = 0x005E4342;
+	ieee->sta_edca_param[3] = 0x002F3262;
+	ieee->aggregation = true;
+	ieee->enable_rx_imm_BA = 1;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40)	
+	_setup_timer(&ieee->scan_timer,
+		    rtllib_softmac_scan_cb,
+		    (unsigned long) ieee);
+#endif
+	ieee->tx_pending.txb = NULL;
+	
+	_setup_timer(&ieee->associate_timer,
+		    rtllib_associate_abort_cb,
+		    (unsigned long) ieee);
+
+	_setup_timer(&ieee->beacon_timer,
+		    rtllib_send_beacon_cb,
+		    (unsigned long) ieee);
+
+#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE)
+	_setup_timer(&ieee->ibss_wait_timer,
+		    rtllib_ibss_wait_timeout,
+		    (unsigned long) ieee);
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+#ifdef PF_SYNCTHREAD
+	ieee->wq = create_workqueue(DRV_NAME,0);
+#else	
+	ieee->wq = create_workqueue(DRV_NAME);
+#endif
+#endif
+
+	INIT_DELAYED_WORK_RSL(&ieee->link_change_wq,(void*)rtllib_link_change_wq,ieee);
+	INIT_DELAYED_WORK_RSL(&ieee->start_ibss_wq,(void*)rtllib_start_ibss_wq,ieee);
+	INIT_WORK_RSL(&ieee->associate_complete_wq, (void*)rtllib_associate_complete_wq,ieee);
+	INIT_DELAYED_WORK_RSL(&ieee->associate_procedure_wq, (void*)rtllib_associate_procedure_wq,ieee);
+	INIT_DELAYED_WORK_RSL(&ieee->softmac_scan_wq,(void*)rtllib_softmac_scan_wq,ieee);
+	INIT_DELAYED_WORK_RSL(&ieee->softmac_hint11d_wq,(void*)rtllib_softmac_hint11d_wq,ieee);
+	INIT_DELAYED_WORK_RSL(&ieee->associate_retry_wq, (void*)rtllib_associate_retry_wq,ieee);
+	INIT_WORK_RSL(&ieee->wx_sync_scan_wq,(void*)rtllib_wx_sync_scan_wq,ieee);
+
+#ifdef _RTL8192_EXT_PATCH_
+	INIT_WORK_RSL(&ieee->ext_stop_scan_wq,(void*) rtllib_ext_stop_scan_wq,ieee);
+	INIT_WORK_RSL(&ieee->ext_send_beacon_wq,(void*) ext_rtllib_send_beacon_wq,ieee);
+#endif 
+
+	sema_init(&ieee->wx_sem, 1);
+	sema_init(&ieee->scan_sem, 1);
+	sema_init(&ieee->ips_sem,1);
+	
+	spin_lock_init(&ieee->mgmt_tx_lock);
+	spin_lock_init(&ieee->beacon_lock);
+	
+	tasklet_init(&ieee->ps_task,
+	     (void(*)(unsigned long)) rtllib_sta_ps,
+	     (unsigned long)ieee);
+
+}
+
+void rtllib_softmac_free(struct rtllib_device *ieee)
+{
+	down(&ieee->wx_sem);
+#ifdef ENABLE_DOT11D
+	if(NULL != ieee->pDot11dInfo)
+	{
+		kfree(ieee->pDot11dInfo);
+		ieee->pDot11dInfo = NULL;
+	}
+#endif
+	del_timer_sync(&ieee->associate_timer);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	
+	cancel_delayed_work(&ieee->associate_retry_wq);
+	destroy_workqueue(ieee->wq);
+#endif
+	
+	up(&ieee->wx_sem);
+}
+
+/******************************************************** 
+ * Start of WPA code.                                   *
+ * this is stolen from the ipw2200 driver               *
+ ********************************************************/
+
+ 
+static int rtllib_wpa_enable(struct rtllib_device *ieee, int value)
+{
+	/* This is called when wpa_supplicant loads and closes the driver
+	 * interface. */
+	printk("%s WPA\n",value ? "enabling" : "disabling");
+	ieee->wpa_enabled = value;
+	memset(ieee->ap_mac_addr, 0, 6); 
+	return 0;
+}
+
+ 
+void rtllib_wpa_assoc_frame(struct rtllib_device *ieee, char *wpa_ie, int wpa_ie_len)
+{
+	/* make sure WPA is enabled */
+	rtllib_wpa_enable(ieee, 1);
+
+	rtllib_disassociate(ieee);
+}
+
+
+static int rtllib_wpa_mlme(struct rtllib_device *ieee, int command, int reason)
+{
+	
+	int ret = 0;
+
+	switch (command) {
+	case IEEE_MLME_STA_DEAUTH:
+		break;
+
+	case IEEE_MLME_STA_DISASSOC:
+		rtllib_disassociate(ieee);
+		break;
+
+	default:
+		printk("Unknown MLME request: %d\n", command);
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+
+static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee,
+			      struct ieee_param *param, int plen)
+{
+	u8 *buf;
+
+	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
+	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
+		return -EINVAL;
+
+	if (param->u.wpa_ie.len) {
+		buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
+		if (buf == NULL)
+			return -ENOMEM;
+
+		memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
+		kfree(ieee->wpa_ie);
+		ieee->wpa_ie = buf;
+		ieee->wpa_ie_len = param->u.wpa_ie.len;
+	} else {
+		kfree(ieee->wpa_ie);
+		ieee->wpa_ie = NULL;
+		ieee->wpa_ie_len = 0;
+	}
+
+	rtllib_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
+	return 0;
+}
+
+#define AUTH_ALG_OPEN_SYSTEM			0x1
+#define AUTH_ALG_SHARED_KEY			0x2
+#define AUTH_ALG_LEAP				0x4
+static int rtllib_wpa_set_auth_algs(struct rtllib_device *ieee, int value)
+{
+	
+	struct rtllib_security sec = {
+		.flags = SEC_AUTH_MODE,
+	};
+	int ret = 0;
+
+	if (value & AUTH_ALG_SHARED_KEY) {
+		sec.auth_mode = WLAN_AUTH_SHARED_KEY;
+		ieee->open_wep = 0;
+		ieee->auth_mode = 1;
+	} else if (value & AUTH_ALG_OPEN_SYSTEM){
+		sec.auth_mode = WLAN_AUTH_OPEN;
+		ieee->open_wep = 1;
+		ieee->auth_mode = 0;
+	}
+	else if (value & AUTH_ALG_LEAP){
+		sec.auth_mode = WLAN_AUTH_LEAP  >> 6;
+		ieee->open_wep = 1;
+		ieee->auth_mode = 2;
+	}
+
+
+	if (ieee->set_security)
+		ieee->set_security(ieee->dev, &sec);
+
+	return ret;
+}
+
+static int rtllib_wpa_set_param(struct rtllib_device *ieee, u8 name, u32 value)
+{
+	int ret=0;
+	unsigned long flags;
+
+	switch (name) {
+	case IEEE_PARAM_WPA_ENABLED:
+		ret = rtllib_wpa_enable(ieee, value);
+		break;
+
+	case IEEE_PARAM_TKIP_COUNTERMEASURES:
+		ieee->tkip_countermeasures=value;
+		break;
+
+		case IEEE_PARAM_DROP_UNENCRYPTED: 
+		{
+		/* HACK:
+		 *
+		 * wpa_supplicant calls set_wpa_enabled when the driver
+		 * is loaded and unloaded, regardless of if WPA is being
+		 * used.  No other calls are made which can be used to
+		 * determine if encryption will be used or not prior to
+		 * association being expected.  If encryption is not being
+		 * used, drop_unencrypted is set to false, else true -- we
+		 * can use this to determine if the CAP_PRIVACY_ON bit should
+		 * be set.
+		 */
+		struct rtllib_security sec = {
+			.flags = SEC_ENABLED,
+			.enabled = value,
+		};
+ 		ieee->drop_unencrypted = value;
+		/* We only change SEC_LEVEL for open mode. Others
+		 * are set by ipw_wpa_set_encryption.
+		 */
+		if (!value) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_0;
+		}
+		else {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_1;
+		}
+		if (ieee->set_security)
+			ieee->set_security(ieee->dev, &sec);
+		break;
+	}
+
+	case IEEE_PARAM_PRIVACY_INVOKED:
+		ieee->privacy_invoked=value;
+		break;
+
+	case IEEE_PARAM_AUTH_ALGS:
+		ret = rtllib_wpa_set_auth_algs(ieee, value);
+		break;
+
+	case IEEE_PARAM_IEEE_802_1X:
+		ieee->ieee802_1x=value;
+		break;
+	case IEEE_PARAM_WPAX_SELECT:
+		spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
+		spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
+		break;
+
+	default:
+		printk("Unknown WPA param: %d\n",name);
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/* implementation borrowed from hostap driver */
+
+#ifdef _RTL8192_EXT_PATCH_
+static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
+				  struct ieee_param *param, int param_len, u8 is_mesh)
+#else
+static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
+				  struct ieee_param *param, int param_len)
+#endif
+{
+	int ret = 0;
+#ifdef _RTL8192_EXT_PATCH_
+	u8 i = 0;
+#endif
+	struct rtllib_crypto_ops *ops;
+	struct rtllib_crypt_data **crypt;
+
+	struct rtllib_security sec = {
+		.flags = 0,
+	};
+
+	param->u.crypt.err = 0;
+	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+	if (param_len !=
+	    (int) ((char *) param->u.crypt.key - (char *) param) +
+	    param->u.crypt.key_len) {
+		printk("Len mismatch %d, %d\n", param_len,
+			       param->u.crypt.key_len);
+		return -EINVAL;
+	}
+	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+		if (param->u.crypt.idx >= WEP_KEYS)
+			return -EINVAL;
+#ifdef _RTL8192_EXT_PATCH_
+		if(is_mesh)
+			crypt = &ieee->cryptlist[0]->crypt[param->u.crypt.idx];
+		else
+			crypt = &ieee->sta_crypt[param->u.crypt.idx];
+#else
+		crypt = &ieee->crypt[param->u.crypt.idx];
+#endif
+	} else {
+		return -EINVAL;
+	}
+
+	if (strcmp(param->u.crypt.alg, "none") == 0) {
+		if (crypt) {
+			sec.enabled = 0;
+			sec.level = SEC_LEVEL_0;
+			sec.flags |= SEC_ENABLED | SEC_LEVEL;
+			rtllib_crypt_delayed_deinit(ieee, crypt);
+		}
+		goto done;
+	}
+	sec.enabled = 1;
+	sec.flags |= SEC_ENABLED;
+
+	/* IPW HW cannot build TKIP MIC, host decryption still needed. */
+	if (!(ieee->host_encrypt || ieee->host_decrypt) &&
+	    strcmp(param->u.crypt.alg, "TKIP"))
+		goto skip_host_crypt;
+
+	ops = rtllib_get_crypto_ops(param->u.crypt.alg);
+	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
+		request_module("rtllib_crypt_wep");
+		ops = rtllib_get_crypto_ops(param->u.crypt.alg);
+	} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
+		request_module("rtllib_crypt_tkip");
+		ops = rtllib_get_crypto_ops(param->u.crypt.alg);
+	} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
+		request_module("rtllib_crypt_ccmp");
+		ops = rtllib_get_crypto_ops(param->u.crypt.alg);
+	}
+	if (ops == NULL) {
+		printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
+		param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
+		ret = -EINVAL;
+		goto done;
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	if(is_mesh)  
+	{
+		for (i=0; i<MAX_MP; i++){
+			crypt = &ieee->cryptlist[i]->crypt[param->u.crypt.idx];
+
+			*crypt = ieee->cryptlist[i]->crypt[param->u.crypt.idx];
+		}
+#endif
+
+		if (*crypt == NULL || (*crypt)->ops != ops) {
+			struct rtllib_crypt_data *new_crypt;
+
+			rtllib_crypt_delayed_deinit(ieee, crypt);
+
+			new_crypt = (struct rtllib_crypt_data *)
+				kmalloc(sizeof(*new_crypt), GFP_KERNEL);
+			if (new_crypt == NULL) {
+				ret = -ENOMEM;
+				goto done;
+			}
+			memset(new_crypt, 0, sizeof(struct rtllib_crypt_data));
+			new_crypt->ops = ops;
+#ifdef BUILT_IN_RTLLIB
+			if (new_crypt->ops)
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+			if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+#else
+			if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
+#endif			
+#endif			
+					new_crypt->priv =
+						new_crypt->ops->init(param->u.crypt.idx);
+
+			if (new_crypt->priv == NULL) {
+				kfree(new_crypt);
+				param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
+				ret = -EINVAL;
+				goto done;
+			}
+
+			*crypt = new_crypt;
+		}
+
+		if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
+				(*crypt)->ops->set_key(param->u.crypt.key,
+					param->u.crypt.key_len, param->u.crypt.seq,
+					(*crypt)->priv) < 0) {
+			printk("key setting failed\n");
+			param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
+			ret = -EINVAL;
+			goto done;
+		}
+#ifdef _RTL8192_EXT_PATCH_
+	}
+#endif
+
+ skip_host_crypt:
+	if (param->u.crypt.set_tx) {
+		ieee->tx_keyidx = param->u.crypt.idx;
+		sec.active_key = param->u.crypt.idx;
+		sec.flags |= SEC_ACTIVE_KEY;
+	} else
+		sec.flags &= ~SEC_ACTIVE_KEY;
+
+	if (param->u.crypt.alg != NULL) {
+		memcpy(sec.keys[param->u.crypt.idx],
+		       param->u.crypt.key,
+		       param->u.crypt.key_len);
+		sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
+		sec.flags |= (1 << param->u.crypt.idx);
+
+		if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_1;
+		} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_2;
+		} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+			sec.flags |= SEC_LEVEL;
+			sec.level = SEC_LEVEL_3;
+		}
+	}
+ done:
+	if (ieee->set_security)
+		ieee->set_security(ieee->dev, &sec);
+
+#ifdef _RTL8192_EXT_PATCH_
+	if (ret != 0)
+	{
+		if(is_mesh)   
+		{
+			for (i=0; i<MAX_MP; i++)
+			{
+				if (ieee->cryptlist[i]->crypt[param->u.crypt.idx]==NULL){
+					break;
+				}
+				else{
+					kfree(ieee->cryptlist[i]->crypt[param->u.crypt.idx]);
+					ieee->cryptlist[i]->crypt[param->u.crypt.idx] = NULL;
+				}
+			}
+		}
+		else
+		{
+			kfree(ieee->sta_crypt[param->u.crypt.idx]);
+			ieee->sta_crypt[param->u.crypt.idx] = NULL;
+		}
+	}
+#endif
+	
+
+	/* Do not reset port if card is in Managed mode since resetting will
+	 * generate new IEEE 802.11 authentication which may end up in looping
+	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
+	 * configuration (for example... Prism2), implement the reset_port in
+	 * the callbacks structures used to initialize the 802.11 stack. */
+	if (ieee->reset_on_keychange &&
+	    ieee->iw_mode != IW_MODE_INFRA &&
+	    ieee->reset_port &&
+	    ieee->reset_port(ieee->dev)) {
+		printk("reset_port failed\n");
+		param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+inline struct sk_buff *rtllib_disauth_skb( struct rtllib_network *beacon,
+		struct rtllib_device *ieee, u16 asRsn)
+{
+	struct sk_buff *skb;
+	struct rtllib_disauth *disauth;
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+	int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE;
+#else
+	int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom;
+
+#endif
+	skb = dev_alloc_skb(len);
+	if (!skb) {
+		return NULL;
+	}
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	skb_reserve(skb, ieee->tx_headroom);
+	
+	disauth = (struct rtllib_disauth *) skb_put(skb,sizeof(struct rtllib_disauth));
+	disauth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DEAUTH);
+	disauth->header.duration_id = 0;
+	
+	memcpy(disauth->header.addr1, beacon->bssid, ETH_ALEN);
+	memcpy(disauth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(disauth->header.addr3, beacon->bssid, ETH_ALEN);
+	
+	disauth->reason = cpu_to_le16(asRsn);
+	return skb;
+}
+
+inline struct sk_buff *rtllib_disassociate_skb( struct rtllib_network *beacon,
+		struct rtllib_device *ieee, u16 asRsn)
+{
+	struct sk_buff *skb;
+	struct rtllib_disassoc *disass;
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+	int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE;
+#else
+	int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom;
+#endif
+	skb = dev_alloc_skb(len);
+
+	if (!skb) {
+		return NULL;
+	}
+	
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	skb_reserve(skb, ieee->tx_headroom);
+
+	disass = (struct rtllib_disassoc *) skb_put(skb,sizeof(struct rtllib_disassoc));
+	disass->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DISASSOC);
+	disass->header.duration_id = 0;
+	
+	memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
+	memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+	memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
+	
+	disass->reason = cpu_to_le16(asRsn);
+	return skb;
+}
+
+void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn)
+{
+	struct rtllib_network *beacon = &ieee->current_network;
+	struct sk_buff *skb;
+
+	if(deauth) {
+		skb = rtllib_disauth_skb(beacon,ieee,asRsn);
+	} else {
+		skb = rtllib_disassociate_skb(beacon,ieee,asRsn);
+	}
+
+	if (skb){
+		softmac_mgmt_xmit(skb, ieee);
+	}
+}
+
+u8 rtllib_ap_sec_type(struct rtllib_device *ieee)
+{
+	static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
+	static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+	int wpa_ie_len= ieee->wpa_ie_len;
+	struct rtllib_crypt_data* crypt;
+	int encrypt;
+
+#ifdef _RTL8192_EXT_PATCH_
+	crypt = ieee->sta_crypt[ieee->tx_keyidx];
+#else
+	crypt = ieee->crypt[ieee->tx_keyidx];
+#endif
+	encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\
+		  (ieee->host_encrypt && crypt && crypt->ops && \
+		   (0 == strcmp(crypt->ops->name,"WEP")));
+
+	/* simply judge  */
+	if(encrypt && (wpa_ie_len == 0)) {
+		return SEC_ALG_WEP;
+	} else if((wpa_ie_len != 0)) {
+		if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) || 
+				((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
+			return SEC_ALG_CCMP;
+		else
+			return SEC_ALG_TKIP;
+	} else {
+		return SEC_ALG_NONE;
+	}
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, u8 is_mesh)
+#else
+int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p)
+#endif
+{
+	struct ieee_param *param;
+	int ret=0;
+
+	down(&ieee->wx_sem);
+
+	if (p->length < sizeof(struct ieee_param) || !p->pointer){
+		ret = -EINVAL;
+		goto out;
+	}
+	
+	param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
+	if (param == NULL){
+		ret = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(param, p->pointer, p->length)) {
+		kfree(param);
+		ret = -EFAULT;
+		goto out;
+	}
+
+	switch (param->cmd) {
+
+	case IEEE_CMD_SET_WPA_PARAM:
+		ret = rtllib_wpa_set_param(ieee, param->u.wpa_param.name,
+					param->u.wpa_param.value);
+		break;
+
+	case IEEE_CMD_SET_WPA_IE:
+		ret = rtllib_wpa_set_wpa_ie(ieee, param, p->length);
+		break;
+
+	case IEEE_CMD_SET_ENCRYPTION:
+#ifdef _RTL8192_EXT_PATCH_
+		ret = rtllib_wpa_set_encryption(ieee, param, p->length, is_mesh);
+#else
+		ret = rtllib_wpa_set_encryption(ieee, param, p->length);
+#endif
+		break;
+
+	case IEEE_CMD_MLME:
+		ret = rtllib_wpa_mlme(ieee, param->u.mlme.command,
+				   param->u.mlme.reason_code);
+		break;
+
+	default:
+		printk("Unknown WPA supplicant request: %d\n",param->cmd);
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+		ret = -EFAULT;
+
+	kfree(param);
+out:
+	up(&ieee->wx_sem);
+	
+	return ret;
+}
+
+void notify_wx_assoc_event(struct rtllib_device *ieee)
+{
+	union iwreq_data wrqu;
+
+	if(ieee->cannot_notify)
+		return;
+
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	if (ieee->state == RTLLIB_LINKED)
+		memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
+	else{
+
+		printk("%s(): Tell user space disconnected\n",__func__);
+		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+	}
+	wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_get_beacon);
+EXPORT_SYMBOL_RSL(rtllib_wake_queue);
+EXPORT_SYMBOL_RSL(rtllib_stop_queue);
+EXPORT_SYMBOL_RSL(rtllib_reset_queue);
+EXPORT_SYMBOL_RSL(rtllib_softmac_stop_protocol);
+EXPORT_SYMBOL_RSL(rtllib_softmac_start_protocol);
+EXPORT_SYMBOL_RSL(rtllib_is_shortslot);
+EXPORT_SYMBOL_RSL(rtllib_is_54g);
+EXPORT_SYMBOL_RSL(rtllib_wpa_supplicant_ioctl);
+EXPORT_SYMBOL_RSL(rtllib_ps_tx_ack);
+EXPORT_SYMBOL_RSL(rtllib_softmac_xmit);
+EXPORT_SYMBOL_RSL(rtllib_stop_send_beacons);
+EXPORT_SYMBOL_RSL(notify_wx_assoc_event);
+EXPORT_SYMBOL_RSL(SendDisassociation);
+EXPORT_SYMBOL_RSL(rtllib_disassociate);
+EXPORT_SYMBOL_RSL(rtllib_start_send_beacons);
+EXPORT_SYMBOL_RSL(rtllib_stop_scan);
+EXPORT_SYMBOL_RSL(rtllib_send_probe_requests);
+EXPORT_SYMBOL_RSL(rtllib_softmac_scan_syncro);
+EXPORT_SYMBOL_RSL(rtllib_start_scan_syncro);
+EXPORT_SYMBOL_RSL(rtllib_sta_ps_send_null_frame);
+EXPORT_SYMBOL_RSL(rtllib_sta_ps_send_pspoll_frame);
+EXPORT_SYMBOL_RSL(rtllib_sta_wakeup);
+EXPORT_SYMBOL_RSL(rtllib_ap_sec_type);
+#ifdef _RTL8192_EXT_PATCH_
+EXPORT_SYMBOL_RSL(rtllib_MFIE_rate_len);
+EXPORT_SYMBOL_RSL(rtllib_MFIE_Brate);
+EXPORT_SYMBOL_RSL(rtllib_MFIE_Grate);
+EXPORT_SYMBOL_RSL(rtllib_WMM_Info);
+EXPORT_SYMBOL_RSL(rtllib_TURBO_Info);
+EXPORT_SYMBOL_RSL(rtllib_ext_probe_resp_by_net);
+EXPORT_SYMBOL_RSL(softmac_mgmt_xmit);
+EXPORT_SYMBOL_RSL(rtllib_start_scan);
+EXPORT_SYMBOL_RSL(rtllib_ext_send_11s_beacon);
+EXPORT_SYMBOL_RSL(rtllib_rx_auth_rq);
+EXPORT_SYMBOL_RSL(rtllib_associate_step1);
+EXPORT_SYMBOL_RSL(rtllib_stop_protocol);
+EXPORT_SYMBOL_RSL(rtllib_start_protocol);
+EXPORT_SYMBOL_RSL(rtllib_resp_to_auth);
+
+#endif 
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/dot11d.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/dot11d.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_DOT11D_H
+#define __INC_DOT11D_H
+
+#ifdef ENABLE_DOT11D
+#include "rtllib.h"
+
+
+
+typedef struct _CHNL_TXPOWER_TRIPLE {
+	u8 FirstChnl;
+	u8  NumChnls;
+	u8  MaxTxPowerInDbm;
+}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
+
+typedef enum _DOT11D_STATE {
+	DOT11D_STATE_NONE = 0,
+	DOT11D_STATE_LEARNED,
+	DOT11D_STATE_DONE,
+}DOT11D_STATE;
+
+typedef struct _RT_DOT11D_INFO {
+
+	bool bEnabled; 
+
+	u16 CountryIeLen; 
+	u8  CountryIeBuf[MAX_IE_LEN];
+	u8  CountryIeSrcAddr[6]; 
+	u8  CountryIeWatchdog; 
+
+	u8  channel_map[MAX_CHANNEL_NUMBER+1];  
+	u8  MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
+
+	DOT11D_STATE State;
+}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
+#define eqMacAddr(a,b)		( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
+#define cpMacAddr(des,src)	((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
+#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
+
+#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
+#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
+
+#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) 
+#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+
+#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
+	(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
+	false : \
+	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
+
+#define CIE_WATCHDOG_TH 1
+#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
+#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 
+#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
+
+#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
+
+void Dot11d_Init( struct rtllib_device *dev); 
+void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device* ieee);
+void Dot11d_Reset(struct rtllib_device *dev);
+void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, u16 CoutryIeLen, u8 *pCoutryIe);
+u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel);
+void DOT11D_ScanComplete(struct rtllib_device *dev);
+int ToLegalChannel(struct rtllib_device *dev, u8 channel);
+#endif 
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/cipher.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/cipher.c
@@ -0,0 +1,298 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include <linux/kernel.h>
+#include "rtl_crypto.h"
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include "internal.h"
+#include "scatterwalk.h"
+
+typedef void (cryptfn_t)(void *, u8 *, const u8 *);
+typedef void (procfn_t)(struct crypto_tfm *, u8 *,
+                        u8*, cryptfn_t, int enc, void *, int);
+
+static inline void xor_64(u8 *a, const u8 *b)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+}
+
+static inline void xor_128(u8 *a, const u8 *b)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+	((u32 *)a)[2] ^= ((u32 *)b)[2];
+	((u32 *)a)[3] ^= ((u32 *)b)[3];
+}
+
+
+/* 
+ * Generic encrypt/decrypt wrapper for ciphers, handles operations across
+ * multiple page boundaries by using temporary blocks.  In user context,
+ * the kernel is given a chance to schedule us once per block.
+ */
+static int crypt(struct crypto_tfm *tfm,
+		 struct scatterlist *dst,
+		 struct scatterlist *src,
+                 unsigned int nbytes, cryptfn_t crfn,
+                 procfn_t prfn, int enc, void *info)
+{
+	struct scatter_walk walk_in, walk_out;
+	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
+	u8 tmp_src[bsize];
+	u8 tmp_dst[bsize];
+
+	if (!nbytes)
+		return 0;
+
+	if (nbytes % bsize) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
+		return -EINVAL;
+	}
+
+	scatterwalk_start(&walk_in, src);
+	scatterwalk_start(&walk_out, dst);
+
+	for(;;) {
+		u8 *src_p, *dst_p;
+		int in_place;
+
+		scatterwalk_map(&walk_in, 0);
+		scatterwalk_map(&walk_out, 1);
+		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
+		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
+		in_place = scatterwalk_samebuf(&walk_in, &walk_out,
+					       src_p, dst_p);
+
+		nbytes -= bsize;
+
+		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
+
+		prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
+
+		scatterwalk_done(&walk_in, 0, nbytes);
+
+		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+		scatterwalk_done(&walk_out, 1, nbytes);
+
+		if (!nbytes)
+			return 0;
+
+		crypto_yield(tfm);
+	}
+}
+
+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
+{
+	u8 *iv = info;
+	
+	/* Null encryption */
+	if (!iv)
+		return;
+		
+	if (enc) {
+		tfm->crt_u.cipher.cit_xor_block(iv, src);
+		fn(crypto_tfm_ctx(tfm), dst, iv);
+		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
+	} else {
+		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+		u8 *buf = in_place ? stack : dst;
+
+		fn(crypto_tfm_ctx(tfm), buf, src);
+		tfm->crt_u.cipher.cit_xor_block(buf, iv);
+		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
+		if (buf != dst)
+			memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
+	}
+}
+
+static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
+{
+	fn(crypto_tfm_ctx(tfm), dst, src);
+}
+
+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
+	
+	if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	} else
+		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
+		                       &tfm->crt_flags);
+}
+
+static int ecb_encrypt(struct crypto_tfm *tfm,
+		       struct scatterlist *dst,
+                       struct scatterlist *src, unsigned int nbytes)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             ecb_process, 1, NULL);
+}
+
+static int ecb_decrypt(struct crypto_tfm *tfm,
+                       struct scatterlist *dst,
+                       struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             ecb_process, 1, NULL);
+}
+
+static int cbc_encrypt(struct crypto_tfm *tfm,
+                       struct scatterlist *dst,
+                       struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_encrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_encrypt,
+	             cbc_process, 1, iv);
+}
+
+static int cbc_decrypt(struct crypto_tfm *tfm,
+                       struct scatterlist *dst,
+                       struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, tfm->crt_cipher.cit_iv);
+}
+
+static int cbc_decrypt_iv(struct crypto_tfm *tfm,
+                          struct scatterlist *dst,
+                          struct scatterlist *src,
+                          unsigned int nbytes, u8 *iv)
+{
+	return crypt(tfm, dst, src, nbytes,
+	             tfm->__crt_alg->cra_cipher.cia_decrypt,
+	             cbc_process, 0, iv);
+}
+
+static int nocrypt(struct crypto_tfm *tfm,
+                   struct scatterlist *dst,
+                   struct scatterlist *src,
+		   unsigned int nbytes)
+{
+	return -ENOSYS;
+}
+
+static int nocrypt_iv(struct crypto_tfm *tfm,
+                      struct scatterlist *dst,
+                      struct scatterlist *src,
+                      unsigned int nbytes, u8 *iv)
+{
+	return -ENOSYS;
+}
+
+int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
+{
+	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
+	
+	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
+	if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
+		tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
+	
+	return 0;
+}
+
+int crypto_init_cipher_ops(struct crypto_tfm *tfm)
+{
+	int ret = 0;
+	struct cipher_tfm *ops = &tfm->crt_cipher;
+
+	ops->cit_setkey = setkey;
+
+	switch (tfm->crt_cipher.cit_mode) {
+	case CRYPTO_TFM_MODE_ECB:
+		ops->cit_encrypt = ecb_encrypt;
+		ops->cit_decrypt = ecb_decrypt;
+		break;
+		
+	case CRYPTO_TFM_MODE_CBC:
+		ops->cit_encrypt = cbc_encrypt;
+		ops->cit_decrypt = cbc_decrypt;
+		ops->cit_encrypt_iv = cbc_encrypt_iv;
+		ops->cit_decrypt_iv = cbc_decrypt_iv;
+		break;
+		
+	case CRYPTO_TFM_MODE_CFB:
+		ops->cit_encrypt = nocrypt;
+		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
+		break;
+	
+	case CRYPTO_TFM_MODE_CTR:
+		ops->cit_encrypt = nocrypt;
+		ops->cit_decrypt = nocrypt;
+		ops->cit_encrypt_iv = nocrypt_iv;
+		ops->cit_decrypt_iv = nocrypt_iv;
+		break;
+
+	default:
+		BUG();
+	}
+	
+	if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
+	    	
+	    	switch (crypto_tfm_alg_blocksize(tfm)) {
+	    	case 8:
+	    		ops->cit_xor_block = xor_64;
+	    		break;
+	    		
+	    	case 16:
+	    		ops->cit_xor_block = xor_128;
+	    		break;
+	    		
+	    	default:
+	    		printk(KERN_WARNING "%s: block size %u not supported\n",
+	    		       crypto_tfm_alg_name(tfm),
+	    		       crypto_tfm_alg_blocksize(tfm));
+	    		ret = -EINVAL;
+	    		goto out;
+	    	}
+	    	
+		ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
+	    	ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL);
+		if (ops->cit_iv == NULL)
+			ret = -ENOMEM;
+	}
+
+out:	
+	return ret;
+}
+
+void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
+{
+	if (tfm->crt_cipher.cit_iv)
+		kfree(tfm->crt_cipher.cit_iv);
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_softmac_wx.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_softmac_wx.c
@@ -0,0 +1,769 @@
+/* IEEE 802.11 SoftMAC layer
+ * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Mostly extracted from the rtl8180-sa2400 driver for the 
+ * in-kernel generic ieee802.11 stack.
+ *
+ * Some pieces of code might be stolen from ipw2100 driver
+ * copyright of who own it's copyright ;-)
+ *
+ * PS wx handler mostly stolen from hostap, copyright who
+ * own it's copyright ;-)
+ *
+ * released under the GPL
+ */
+
+
+#include "rtllib.h"
+#ifdef ENABLE_DOT11D
+#include "dot11d.h"
+#endif
+/* FIXME: add A freqs */
+
+const long rtllib_wlan_frequencies[] = {  
+	2412, 2417, 2422, 2427, 
+	2432, 2437, 2442, 2447, 
+	2452, 2457, 2462, 2467, 
+	2472, 2484  
+};
+
+
+int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	int ret;
+	struct iw_freq *fwrq = & wrqu->freq;
+
+	down(&ieee->wx_sem);
+	
+	if(ieee->iw_mode == IW_MODE_INFRA){ 
+		ret = 0;
+		goto out;
+	}
+
+	/* if setting by freq convert to channel */
+	if (fwrq->e == 1) {
+		if ((fwrq->m >= (int) 2.412e8 &&
+		     fwrq->m <= (int) 2.487e8)) {
+			int f = fwrq->m / 100000;
+			int c = 0;
+			
+			while ((c < 14) && (f != rtllib_wlan_frequencies[c]))
+				c++;
+			
+			/* hack to fall through */
+			fwrq->e = 0;
+			fwrq->m = c + 1;
+		}
+	}
+	
+	if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ 
+		ret = -EOPNOTSUPP;
+		goto out;
+	
+	}else { /* Set the channel */
+		
+#ifdef ENABLE_DOT11D
+		if (ieee->active_channel_map[fwrq->m] != 1) {
+			ret = -EINVAL;
+			goto out;
+		}
+#endif
+		ieee->current_network.channel = fwrq->m;
+		ieee->set_chan(ieee->dev, ieee->current_network.channel);
+		
+		if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+			if(ieee->state == RTLLIB_LINKED){
+			
+			rtllib_stop_send_beacons(ieee);
+			rtllib_start_send_beacons(ieee);
+			}
+	}
+
+	ret = 0;
+out:
+	up(&ieee->wx_sem);
+	return ret;
+}
+
+
+#ifdef _RTL8192_EXT_PATCH_	
+int rtllib_wx_get_freq(struct rtllib_device *ieee,
+			     struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b, u8 is_mesh)
+#else
+int rtllib_wx_get_freq(struct rtllib_device *ieee,
+			     struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+#endif	
+{
+	struct iw_freq *fwrq = & wrqu->freq;
+
+#ifdef _RTL8192_EXT_PATCH_	
+	if(is_mesh)
+	{
+		if (ieee->current_mesh_network.channel == 0)
+			return -1;
+		fwrq->m = rtllib_wlan_frequencies[ieee->current_mesh_network.channel-1] * 100000;
+		fwrq->e = 1;	
+	}
+	else
+#endif	
+	{
+	if (ieee->current_network.channel == 0)
+		return -1;
+	fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * 100000;
+	fwrq->e = 1;	
+	}
+	return 0;
+}
+
+int rtllib_wx_get_wap(struct rtllib_device *ieee, 
+			    struct iw_request_info *info, 
+			    union iwreq_data *wrqu, char *extra)
+{
+	unsigned long flags;	
+	
+	wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+	
+	if (ieee->iw_mode == IW_MODE_MONITOR)
+		return -1;
+	
+	/* We want avoid to give to the user inconsistent infos*/
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if (ieee->state != RTLLIB_LINKED && 
+		ieee->state != RTLLIB_LINKED_SCANNING &&
+		ieee->wap_set == 0)
+		
+		memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
+	else
+		memcpy(wrqu->ap_addr.sa_data, 
+		       ieee->current_network.bssid, ETH_ALEN);
+	
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+	return 0;
+}
+
+
+int rtllib_wx_set_wap(struct rtllib_device *ieee,
+			 struct iw_request_info *info,
+			 union iwreq_data *awrq,
+			 char *extra)
+{
+	
+	int ret = 0;
+	u8 zero[] = {0,0,0,0,0,0};
+	unsigned long flags;
+	
+	short ifup = ieee->proto_started;
+	struct sockaddr *temp = (struct sockaddr *)awrq;
+
+	rtllib_stop_scan_syncro(ieee);
+
+	down(&ieee->wx_sem);
+	/* use ifconfig hw ether */
+	if (ieee->iw_mode == IW_MODE_MASTER){
+		ret = -1;
+		goto out;
+	}
+	
+	if (temp->sa_family != ARPHRD_ETHER){
+		ret = -EINVAL;
+		goto out;
+	}
+	
+        if (memcmp(temp->sa_data, zero,ETH_ALEN) == 0){
+                spin_lock_irqsave(&ieee->lock, flags);
+                memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
+                ieee->wap_set = 0;
+                spin_unlock_irqrestore(&ieee->lock, flags);
+                ret = -1;
+                goto out;
+        }
+
+	
+	if (ifup)
+		rtllib_stop_protocol(ieee,true);
+	
+	/* just to avoid to give inconsistent infos in the
+	 * get wx method. not really needed otherwise 
+	 */
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	ieee->cannot_notify = false;
+	memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); 
+	ieee->wap_set = (memcmp(temp->sa_data, zero,ETH_ALEN)!=0);
+	
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+	if (ifup)
+		rtllib_start_protocol(ieee);
+out:
+	up(&ieee->wx_sem);
+	return ret;
+}
+	
+ int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
+{
+	int len,ret = 0;
+	unsigned long flags;
+	
+	if (ieee->iw_mode == IW_MODE_MONITOR)
+		return -1;
+	
+	/* We want avoid to give to the user inconsistent infos*/	
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if (ieee->current_network.ssid[0] == '\0' ||
+		ieee->current_network.ssid_len == 0){ 
+		ret = -1;
+		goto out;
+	}
+	
+	if (ieee->state != RTLLIB_LINKED && 
+		ieee->state != RTLLIB_LINKED_SCANNING &&
+		ieee->ssid_set == 0){
+		ret = -1;
+		goto out;
+	}
+	len = ieee->current_network.ssid_len;
+	wrqu->essid.length = len;
+	strncpy(b,ieee->current_network.ssid,len);
+	wrqu->essid.flags = 1;
+
+out:
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+	return ret;
+	
+}
+
+int rtllib_wx_set_rate(struct rtllib_device *ieee, 
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+
+	u32 target_rate = wrqu->bitrate.value;
+	
+	ieee->rate = target_rate/100000;
+	return 0; 
+}
+
+int rtllib_wx_get_rate(struct rtllib_device *ieee, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	u32 tmp_rate = 0;
+#if defined RTL8192SU|| defined RTL8192CE
+	if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G))
+		tmp_rate = ieee->rate;
+	else if (ieee->mode & IEEE_N_5G)
+		tmp_rate = 580;
+	else if (ieee->mode & IEEE_N_24G) {
+		if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+			tmp_rate = HTHalfMcsToDataRate(ieee, 15);
+		else
+			tmp_rate = HTMcsToDataRate(ieee, 15);
+	}
+#elif defined RTL8192SE
+	tmp_rate = ieee->rtl_11n_user_show_rates(ieee->dev);
+#else
+        tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
+#endif
+	wrqu->bitrate.value = tmp_rate * 500000;
+	
+	return 0;
+}
+
+
+int rtllib_wx_set_rts(struct rtllib_device *ieee, 
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu, char *extra)
+{
+	if (wrqu->rts.disabled || !wrqu->rts.fixed)
+		ieee->rts = DEFAULT_RTS_THRESHOLD;
+	else
+	{
+		if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
+				wrqu->rts.value > MAX_RTS_THRESHOLD) 
+			return -EINVAL;
+		ieee->rts = wrqu->rts.value;
+	}
+	return 0;
+}
+
+int rtllib_wx_get_rts(struct rtllib_device *ieee, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	wrqu->rts.value = ieee->rts;
+	wrqu->rts.fixed = 0;	/* no auto select */
+	wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
+	return 0;
+}
+
+int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	int set_mode_status = 0;
+
+	rtllib_stop_scan_syncro(ieee);
+	down(&ieee->wx_sem);
+	switch (wrqu->mode) {
+	case IW_MODE_MONITOR:
+	case IW_MODE_ADHOC:
+	case IW_MODE_INFRA:
+#ifdef _RTL8192_EXT_PATCH_
+	case IW_MODE_MESH:
+#endif
+		break;
+	case IW_MODE_AUTO:
+		wrqu->mode = IW_MODE_INFRA;
+		break;
+	default:
+		set_mode_status = -EINVAL;
+		goto out;
+	}
+
+	if (wrqu->mode == ieee->iw_mode)
+		goto out;
+	
+	if (wrqu->mode == IW_MODE_MONITOR) {
+#ifdef CONFIG_RTL819x_RADIOTAP
+		ieee->dev->type = ARPHRD_IEEE80211_RADIOTAP;
+#else
+		ieee->dev->type = ARPHRD_IEEE80211;
+#endif
+		rtllib_EnableNetMonitorMode(ieee->dev,false);	
+		
+	} else {
+		ieee->dev->type = ARPHRD_ETHER;
+		if (ieee->iw_mode == IW_MODE_MONITOR)
+			rtllib_DisableNetMonitorMode(ieee->dev,false);
+	}
+	
+	if (!ieee->proto_started) {
+		ieee->iw_mode = wrqu->mode;
+	} else {
+		rtllib_stop_protocol(ieee,true);
+		ieee->iw_mode = wrqu->mode;
+#if defined (RTL8192S_WAPI_SUPPORT)
+		if(ieee->iw_mode == IW_MODE_ADHOC)
+			ieee->wapiInfo.bWapiPSK = true;
+#endif
+		rtllib_start_protocol(ieee);
+	}
+
+out:
+	up(&ieee->wx_sem);
+	return set_mode_status;
+}
+
+void rtllib_wx_sync_scan_wq(void *data)
+{
+	struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, wx_sync_scan_wq);
+	short chan;
+	HT_EXTCHNL_OFFSET chan_offset=0;
+	HT_CHANNEL_WIDTH bandwidth=0;
+	int b40M = 0;
+	static int count = 0;
+
+	if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){	
+		rtllib_start_scan_syncro(ieee, 0);
+		goto out;
+	}
+
+	chan = ieee->current_network.channel;
+
+#ifdef ENABLE_LPS
+	if (ieee->LeisurePSLeave) {
+		ieee->LeisurePSLeave(ieee->dev);
+	}
+	/* notify AP to be in PS mode */
+	rtllib_sta_ps_send_null_frame(ieee, 1);
+	rtllib_sta_ps_send_null_frame(ieee, 1);
+#endif
+
+	rtllib_stop_all_queues(ieee);
+
+	if (ieee->data_hard_stop)
+		ieee->data_hard_stop(ieee->dev);
+	rtllib_stop_send_beacons(ieee);
+	ieee->state = RTLLIB_LINKED_SCANNING;
+	ieee->link_change(ieee->dev);
+	/* wait for ps packet to be kicked out successfully */
+	msleep(50);
+
+#if !(defined RTL8192SE ||defined RTL8192CE)	
+	ieee->InitialGainHandler(ieee->dev,IG_Backup);
+#endif
+#if defined(RTL8192SE)
+#if(RTL8192S_DISABLE_FW_DM == 0)
+	if (ieee->SetFwCmdHandler) {
+		ieee->SetFwCmdHandler(ieee->dev, FW_CMD_PAUSE_DM_BY_SCAN);
+	}
+#endif
+#endif	
+#if defined RTL8192SU || defined RTL8192CE
+	ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_BACKUP);
+#endif
+
+	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
+		b40M = 1;
+		chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
+		bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
+		printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
+		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+		}
+
+	rtllib_start_scan_syncro(ieee, 0);
+
+	if (b40M) {
+		printk("Scan in 20M, back to 40M\n");
+		if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
+			ieee->set_chan(ieee->dev, chan + 2);
+		else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
+			ieee->set_chan(ieee->dev, chan - 2);
+		else
+			ieee->set_chan(ieee->dev, chan);
+		ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
+	} else {
+		ieee->set_chan(ieee->dev, chan);
+	}
+	
+#if !(defined RTL8192SE ||defined RTL8192CE)
+	ieee->InitialGainHandler(ieee->dev,IG_Restore);
+#endif
+
+#if defined(RTL8192SE)
+#if(RTL8192S_DISABLE_FW_DM == 0)
+	if (ieee->SetFwCmdHandler) {
+		ieee->SetFwCmdHandler(ieee->dev, FW_CMD_RESUME_DM_BY_SCAN);
+	}
+#endif
+#endif	
+#if defined RTL8192SU || defined RTL8192CE
+	ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_RESTORE);
+#endif
+	ieee->state = RTLLIB_LINKED;
+	ieee->link_change(ieee->dev);
+
+#ifdef ENABLE_LPS
+	/* Notify AP that I wake up again */
+	rtllib_sta_ps_send_null_frame(ieee, 0);
+#endif
+
+	if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || 
+			ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) {
+		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
+		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;	
+	}
+
+	if (ieee->data_hard_resume)
+		ieee->data_hard_resume(ieee->dev);
+	
+	if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+		rtllib_start_send_beacons(ieee);
+	
+	rtllib_wake_all_queues(ieee);
+
+	count = 0;	
+out:
+	up(&ieee->wx_sem);
+	
+}
+
+int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+	int ret = 0;
+	
+	down(&ieee->wx_sem);
+	
+	if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ 
+		ret = -1;
+		goto out;
+	}
+	
+	if ( ieee->state == RTLLIB_LINKED){
+		queue_work_rsl(ieee->wq, &ieee->wx_sync_scan_wq);
+		/* intentionally forget to up sem */
+		return 0;
+	}
+		
+out:
+	up(&ieee->wx_sem);
+	return ret;
+}
+
+int rtllib_wx_set_essid(struct rtllib_device *ieee, 
+			      struct iw_request_info *a,
+			      union iwreq_data *wrqu, char *extra)
+{
+	
+	int ret=0,len,i;
+	short proto_started;
+	unsigned long flags;
+	
+	rtllib_stop_scan_syncro(ieee);
+	down(&ieee->wx_sem);
+	
+	proto_started = ieee->proto_started;
+	
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+	len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
+#else
+	len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE;
+#endif
+
+	if (len > IW_ESSID_MAX_SIZE){
+		ret= -E2BIG;
+		goto out;
+	}
+	
+	if (ieee->iw_mode == IW_MODE_MONITOR){
+		ret= -1;
+		goto out;
+	}
+	
+	for (i=0; i<len; i++){
+		if(extra[i] < 0){
+			ret= -1;
+			goto out;
+		}
+	}
+	
+	if(proto_started)
+		rtllib_stop_protocol(ieee,true);
+	
+	
+	/* this is just to be sure that the GET wx callback
+	 * has consisten infos. not needed otherwise
+	 */
+	spin_lock_irqsave(&ieee->lock, flags);
+	
+	if (wrqu->essid.flags && wrqu->essid.length) {
+		strncpy(ieee->current_network.ssid, extra, len);
+		ieee->current_network.ssid_len = len;
+#if 0
+		{
+			int i;
+			for (i=0; i<len; i++)
+				printk("%c:%d ", extra[i], extra[i]);
+			printk("\n");
+		}
+#endif
+		ieee->cannot_notify = false;
+		ieee->ssid_set = 1;
+	}
+	else{ 
+		ieee->ssid_set = 0;
+		ieee->current_network.ssid[0] = '\0';
+		ieee->current_network.ssid_len = 0;
+	}
+	spin_unlock_irqrestore(&ieee->lock, flags);
+	
+	if (proto_started)
+		rtllib_start_protocol(ieee);
+out:
+	up(&ieee->wx_sem);
+	return ret;
+}
+
+ int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+			     union iwreq_data *wrqu, char *b)
+{
+#ifdef _RTL8192_EXT_PATCH_
+	if(ieee->iw_mode == IW_MODE_MESH) {
+		/* WEXT could not show mesh mode properly,
+		 * just disable it */
+		if(ieee->only_mesh) {
+			return -1;
+		} else {
+			wrqu->mode = IW_MODE_INFRA;
+		}
+	}
+	else
+#endif
+		wrqu->mode = ieee->iw_mode;
+	return 0;
+}
+
+ int rtllib_wx_set_rawtx(struct rtllib_device *ieee, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	
+	int *parms = (int *)extra;
+	int enable = (parms[0] > 0);
+	short prev = ieee->raw_tx;
+
+	down(&ieee->wx_sem);
+	
+	if(enable) 
+		ieee->raw_tx = 1;
+	else 
+		ieee->raw_tx = 0;
+
+	printk(KERN_INFO"raw TX is %s\n", 
+	      ieee->raw_tx ? "enabled" : "disabled");
+
+	if(ieee->iw_mode == IW_MODE_MONITOR)
+	{
+		if(prev == 0 && ieee->raw_tx){
+			if (ieee->data_hard_resume)
+				ieee->data_hard_resume(ieee->dev);
+	
+			netif_carrier_on(ieee->dev);	
+		}
+		
+		if(prev && ieee->raw_tx == 1)
+			netif_carrier_off(ieee->dev); 
+	}
+	
+	up(&ieee->wx_sem);
+	
+	return 0;
+}
+ 
+int rtllib_wx_get_name(struct rtllib_device *ieee, 
+			     struct iw_request_info *info, 
+			     union iwreq_data *wrqu, char *extra)
+{
+	strcpy(wrqu->name, "802.11");
+
+	if (ieee->modulation & RTLLIB_CCK_MODULATION)
+		strcat(wrqu->name, "b");
+	if (ieee->modulation & RTLLIB_OFDM_MODULATION)
+		strcat(wrqu->name, "g");
+	if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
+		strcat(wrqu->name, "n");
+#if 0	
+	if((ieee->state == RTLLIB_LINKED) || 
+		(ieee->state == RTLLIB_LINKED_SCANNING))
+		strcat(wrqu->name," linked");
+	else if(ieee->state != RTLLIB_NOLINK)
+		strcat(wrqu->name," link..");
+#endif	
+	return 0;
+}
+
+
+/* this is mostly stolen from hostap */
+int rtllib_wx_set_power(struct rtllib_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+	int ret = 0;
+#if 1
+	if(
+		(!ieee->sta_wake_up) ||
+		(!ieee->enter_sleep_state) ||
+		(!ieee->ps_is_queue_empty)){
+		
+		RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): PS mode is tryied to be use but driver missed a callback\n\n",__FUNCTION__);	
+	
+		return -1;
+	}
+#endif	
+	down(&ieee->wx_sem);
+	
+	if (wrqu->power.disabled){
+		printk("===>%s(): power disable\n",__FUNCTION__);
+		ieee->ps = RTLLIB_PS_DISABLED;
+		goto exit;
+	}
+	if (wrqu->power.flags & IW_POWER_TIMEOUT) {
+		ieee->ps_timeout = wrqu->power.value / 1000;
+		printk("===>%s():ps_timeout is %d\n",__FUNCTION__,ieee->ps_timeout);
+	}
+	
+	if (wrqu->power.flags & IW_POWER_PERIOD) {
+		
+		ieee->ps_period = wrqu->power.value / 1000;
+		
+	}
+	switch (wrqu->power.flags & IW_POWER_MODE) {
+	case IW_POWER_UNICAST_R:
+		ieee->ps = RTLLIB_PS_UNICAST;
+		break;
+	case IW_POWER_MULTICAST_R:
+		ieee->ps = RTLLIB_PS_MBCAST;
+		break;
+	case IW_POWER_ALL_R:
+		ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST;	
+		break;
+		
+	case IW_POWER_ON:
+		break;
+		
+	default:
+		ret = -EINVAL;
+		goto exit;
+		
+	}
+exit:
+	up(&ieee->wx_sem);
+	return ret;
+
+}
+
+/* this is stolen from hostap */
+int rtllib_wx_get_power(struct rtllib_device *ieee,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu, char *extra)
+{
+	int ret =0;
+	
+	down(&ieee->wx_sem);
+	
+	if(ieee->ps == RTLLIB_PS_DISABLED){	
+		wrqu->power.disabled = 1;
+		goto exit;
+	}
+
+	wrqu->power.disabled = 0;
+
+	if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+		wrqu->power.flags = IW_POWER_TIMEOUT;
+		wrqu->power.value = ieee->ps_timeout * 1000;
+	} else {
+		wrqu->power.flags = IW_POWER_PERIOD;
+		wrqu->power.value = ieee->ps_period * 1000; 
+	}
+
+       if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST))
+	   	wrqu->power.flags |= IW_POWER_ALL_R;
+	else if (ieee->ps & RTLLIB_PS_MBCAST)
+		wrqu->power.flags |= IW_POWER_MULTICAST_R;
+	else
+		wrqu->power.flags |= IW_POWER_UNICAST_R;
+
+exit:
+	up(&ieee->wx_sem);
+	return ret;
+
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_wx_get_essid);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_essid);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_rate);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_rate);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_wap);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_wap);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_mode);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_mode);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_scan);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_freq);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_freq);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_rawtx);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_name);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_power);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_power);
+EXPORT_SYMBOL_RSL(rtllib_wlan_frequencies);
+EXPORT_SYMBOL_RSL(rtllib_wx_set_rts);
+EXPORT_SYMBOL_RSL(rtllib_wx_get_rts);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_ccmp.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_crypt_ccmp.c
@@ -0,0 +1,544 @@
+/*
+ * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <asm/string.h>
+#include <linux/wireless.h>
+#ifdef _RTL8192_EXT_PATCH_	
+#include <linux/etherdevice.h>
+#endif
+#include "rtllib.h"
+
+#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "rtl_crypto.h"
+#else
+#include <linux/crypto.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) 
+    #include <asm/scatterlist.h>
+#else
+    #include <linux/scatterlist.h>
+#endif
+
+#ifndef BUILT_IN_RTLLIB
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: CCMP");
+MODULE_LICENSE("GPL");
+#endif
+
+
+#define AES_BLOCK_LEN 16
+#define CCMP_HDR_LEN 8
+#define CCMP_MIC_LEN 8
+#define CCMP_TK_LEN 16
+#define CCMP_PN_LEN 6
+
+struct rtllib_ccmp_data {
+	u8 key[CCMP_TK_LEN];
+	int key_set;
+
+	u8 tx_pn[CCMP_PN_LEN];
+	u8 rx_pn[CCMP_PN_LEN];
+
+	u32 dot11RSNAStatsCCMPFormatErrors;
+	u32 dot11RSNAStatsCCMPReplays;
+	u32 dot11RSNAStatsCCMPDecryptErrors;
+
+	int key_idx;
+
+	struct crypto_tfm *tfm;
+
+	/* scratch buffers for virt_to_page() (crypto API) */
+	u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
+		tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
+	u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
+};
+
+void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm,
+			     const u8 pt[16], u8 ct[16])
+{
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	struct scatterlist src, dst;
+
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+	src.page = virt_to_page(pt);
+	src.offset = offset_in_page(pt);
+	src.length = AES_BLOCK_LEN;
+
+	dst.page = virt_to_page(ct);
+	dst.offset = offset_in_page(ct);
+	dst.length = AES_BLOCK_LEN;
+
+#else
+	sg_init_one(&src, pt, AES_BLOCK_LEN);
+	sg_init_one(&dst, ct, AES_BLOCK_LEN);
+#endif
+
+	crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN);
+#else
+	crypto_cipher_encrypt_one((void*)tfm, ct, pt);
+#endif
+}
+
+static void * rtllib_ccmp_init(int key_idx)
+{
+	struct rtllib_ccmp_data *priv;
+
+	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+	if (priv == NULL)
+		goto fail;
+	memset(priv, 0, sizeof(*priv));
+	priv->key_idx = key_idx;
+
+#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	priv->tfm = crypto_alloc_tfm("aes", 0);
+	if (priv->tfm == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_ccmp: could not allocate "
+		       "crypto API aes\n");
+		goto fail;
+	}
+       #else
+       priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(priv->tfm)) {
+		printk(KERN_DEBUG "rtllib_crypt_ccmp: could not allocate "
+		       "crypto API aes\n");
+		priv->tfm = NULL;
+		goto fail;
+	}
+	#endif
+	return priv;
+
+fail:
+	if (priv) {
+		if (priv->tfm)
+			#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
+			crypto_free_tfm(priv->tfm);
+                    #else
+			crypto_free_cipher((void*)priv->tfm);
+		      #endif
+		kfree(priv);
+	}
+
+	return NULL;
+}
+
+
+static void rtllib_ccmp_deinit(void *priv)
+{
+	struct rtllib_ccmp_data *_priv = priv;
+	if (_priv && _priv->tfm)
+#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
+		crypto_free_tfm(_priv->tfm);
+#else
+		crypto_free_cipher((void*)_priv->tfm);
+#endif
+	kfree(priv);
+}
+
+
+static inline void xor_block(u8 *b, u8 *a, size_t len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		b[i] ^= a[i];
+}
+
+
+
+static void ccmp_init_blocks(struct crypto_tfm *tfm,
+			     struct rtllib_hdr_4addr *hdr,
+			     u8 *pn, size_t dlen, u8 *b0, u8 *auth,
+			     u8 *s0)
+{
+	u8 *pos, qc = 0;
+	size_t aad_len;
+	u16 fc;
+	int a4_included, qc_included;
+	u8 aad[2 * AES_BLOCK_LEN];
+
+	fc = le16_to_cpu(hdr->frame_ctl);
+	a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+		       (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS));
+	/*
+	qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) &&
+		       (WLAN_FC_GET_STYPE(fc) & 0x08));
+        */		       
+	qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) &&
+		       (WLAN_FC_GET_STYPE(fc) & 0x80));
+	aad_len = 22;
+	if (a4_included)
+		aad_len += 6;
+	if (qc_included) {
+		pos = (u8 *) &hdr->addr4;
+		if (a4_included)
+			pos += 6;
+		qc = *pos & 0x0f;
+		aad_len += 2;
+	}
+	/* CCM Initial Block:
+	 * Flag (Include authentication header, M=3 (8-octet MIC),
+	 *       L=1 (2-octet Dlen))
+	 * Nonce: 0x00 | A2 | PN
+	 * Dlen */
+	b0[0] = 0x59;
+	b0[1] = qc;
+	memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
+	memcpy(b0 + 8, pn, CCMP_PN_LEN);
+	b0[14] = (dlen >> 8) & 0xff;
+	b0[15] = dlen & 0xff;
+
+	/* AAD:
+	 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
+	 * A1 | A2 | A3
+	 * SC with bits 4..15 (seq#) masked to zero
+	 * A4 (if present)
+	 * QC (if present)
+	 */
+	pos = (u8 *) hdr;
+	aad[0] = 0; /* aad_len >> 8 */
+	aad[1] = aad_len & 0xff;
+	aad[2] = pos[0] & 0x8f;
+	aad[3] = pos[1] & 0xc7;
+	memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
+	pos = (u8 *) &hdr->seq_ctl;
+	aad[22] = pos[0] & 0x0f;
+	aad[23] = 0; /* all bits masked */
+	memset(aad + 24, 0, 8);
+	if (a4_included)
+		memcpy(aad + 24, hdr->addr4, ETH_ALEN);
+	if (qc_included) {
+		aad[a4_included ? 30 : 24] = qc;
+		/* rest of QC masked */
+	}
+
+	/* Start with the first block and AAD */
+	rtllib_ccmp_aes_encrypt(tfm, b0, auth);
+	xor_block(auth, aad, AES_BLOCK_LEN);
+	rtllib_ccmp_aes_encrypt(tfm, auth, auth);
+	xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
+	rtllib_ccmp_aes_encrypt(tfm, auth, auth);
+	b0[0] &= 0x07;
+	b0[14] = b0[15] = 0;
+	rtllib_ccmp_aes_encrypt(tfm, b0, s0);
+}
+
+
+
+static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct rtllib_ccmp_data *key = priv;
+	int data_len, i;
+	u8 *pos;
+	struct rtllib_hdr_4addr *hdr;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+#ifdef _RTL8192_EXT_PATCH_	
+	u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 is_broadcast_data = 0;
+#endif
+	if (skb_headroom(skb) < CCMP_HDR_LEN ||
+	    skb_tailroom(skb) < CCMP_MIC_LEN ||
+	    skb->len < hdr_len)
+		return -1;
+
+	data_len = skb->len - hdr_len;
+	pos = skb_push(skb, CCMP_HDR_LEN);
+	memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
+	pos += hdr_len;
+
+	i = CCMP_PN_LEN - 1;
+	while (i >= 0) {
+		key->tx_pn[i]++;
+		if (key->tx_pn[i] != 0)
+			break;
+		i--;
+	}
+
+	*pos++ = key->tx_pn[5];
+	*pos++ = key->tx_pn[4];
+	*pos++ = 0;
+	*pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
+	*pos++ = key->tx_pn[3];
+	*pos++ = key->tx_pn[2];
+	*pos++ = key->tx_pn[1];
+	*pos++ = key->tx_pn[0];
+
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+#ifdef _RTL8192_EXT_PATCH_	
+	if(tcb_desc->badhoc == 0){
+		if(memcmp(hdr->addr1,broadcastaddr,6) == 0){
+			is_broadcast_data = 1;
+			tcb_desc->bHwSec = 0;
+		}
+		if(is_multicast_ether_addr(hdr->addr1)){
+			tcb_desc->bHwSec = 0;
+		}
+	}
+#endif
+	if (!tcb_desc->bHwSec)
+	{
+		int blocks, last, len;
+		u8 *mic;
+		u8 *b0 = key->tx_b0;
+		u8 *b = key->tx_b;
+		u8 *e = key->tx_e;
+		u8 *s0 = key->tx_s0;
+
+		mic = skb_put(skb, CCMP_MIC_LEN);
+		
+		ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
+	
+		blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+		last = data_len % AES_BLOCK_LEN;
+	
+		for (i = 1; i <= blocks; i++) {
+			len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+			/* Authentication */
+			xor_block(b, pos, len);
+			rtllib_ccmp_aes_encrypt(key->tfm, b, b);
+			/* Encryption, with counter */
+			b0[14] = (i >> 8) & 0xff;
+			b0[15] = i & 0xff;
+			rtllib_ccmp_aes_encrypt(key->tfm, b0, e);
+			xor_block(pos, e, len);
+			pos += len;
+		}
+	
+		for (i = 0; i < CCMP_MIC_LEN; i++)
+			mic[i] = b[i] ^ s0[i];
+	}
+	return 0;
+}
+
+
+static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct rtllib_ccmp_data *key = priv;
+	u8 keyidx, *pos;
+	struct rtllib_hdr_4addr *hdr;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	u8 pn[6];
+
+	if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
+		key->dot11RSNAStatsCCMPFormatErrors++;
+		return -1;
+	}
+
+	hdr = (struct rtllib_hdr_4addr *) skb->data;
+	pos = skb->data + hdr_len;
+	keyidx = pos[3];
+	if (!(keyidx & (1 << 5))) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
+			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+		}
+		key->dot11RSNAStatsCCMPFormatErrors++;
+		return -2;
+	}
+	keyidx >>= 6;
+	if (key->key_idx != keyidx) {
+		printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
+		       "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
+		return -6;
+	}
+	if (!key->key_set) {
+		if (net_ratelimit()) {
+			printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+			       " with keyid=%d that does not have a configured"
+			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+		}
+		return -3;
+	}
+
+	pn[0] = pos[7];
+	pn[1] = pos[6];
+	pn[2] = pos[5];
+	pn[3] = pos[4];
+	pn[4] = pos[1];
+	pn[5] = pos[0];
+	pos += 8;
+#ifndef _RTL8192_EXT_PATCH_	
+	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
+		if (net_ratelimit()) {
+			;
+		}
+		key->dot11RSNAStatsCCMPReplays++;
+		return -4;
+	}
+#endif
+	if (!tcb_desc->bHwSec)
+	{
+		size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
+		u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
+		u8 *b0 = key->rx_b0;
+		u8 *b = key->rx_b;
+		u8 *a = key->rx_a;
+		int i, blocks, last, len;
+		
+
+		ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
+		xor_block(mic, b, CCMP_MIC_LEN);
+	
+		blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+		last = data_len % AES_BLOCK_LEN;
+	
+		for (i = 1; i <= blocks; i++) {
+			len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+			/* Decrypt, with counter */
+			b0[14] = (i >> 8) & 0xff;
+			b0[15] = i & 0xff;
+			rtllib_ccmp_aes_encrypt(key->tfm, b0, b);
+			xor_block(pos, b, len);
+			/* Authentication */
+			xor_block(a, pos, len);
+			rtllib_ccmp_aes_encrypt(key->tfm, a, a);
+			pos += len;
+		}
+	
+		if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
+			if (net_ratelimit()) {
+				printk(KERN_DEBUG "CCMP: decrypt failed: STA="
+				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			}
+			key->dot11RSNAStatsCCMPDecryptErrors++;
+			return -5;
+		}
+	
+		memcpy(key->rx_pn, pn, CCMP_PN_LEN);
+	}
+	/* Remove hdr and MIC */
+	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
+	skb_pull(skb, CCMP_HDR_LEN);
+	skb_trim(skb, skb->len - CCMP_MIC_LEN);
+
+	return keyidx;
+}
+
+
+static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct rtllib_ccmp_data *data = priv;
+	int keyidx;
+	struct crypto_tfm *tfm = data->tfm;
+
+	keyidx = data->key_idx;
+	memset(data, 0, sizeof(*data));
+	data->key_idx = keyidx;
+	data->tfm = tfm;
+	if (len == CCMP_TK_LEN) {
+		memcpy(data->key, key, CCMP_TK_LEN);
+		data->key_set = 1;
+		if (seq) {
+			data->rx_pn[0] = seq[5];
+			data->rx_pn[1] = seq[4];
+			data->rx_pn[2] = seq[3];
+			data->rx_pn[3] = seq[2];
+			data->rx_pn[4] = seq[1];
+			data->rx_pn[5] = seq[0];
+		}
+		crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN);
+	} else if (len == 0)
+		data->key_set = 0;
+	else
+		return -1;
+
+	return 0;
+}
+
+
+static int rtllib_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct rtllib_ccmp_data *data = priv;
+
+	if (len < CCMP_TK_LEN)
+		return -1;
+
+	if (!data->key_set)
+		return 0;
+	memcpy(key, data->key, CCMP_TK_LEN);
+
+	if (seq) {
+		seq[0] = data->tx_pn[5];
+		seq[1] = data->tx_pn[4];
+		seq[2] = data->tx_pn[3];
+		seq[3] = data->tx_pn[2];
+		seq[4] = data->tx_pn[1];
+		seq[5] = data->tx_pn[0];
+	}
+
+	return CCMP_TK_LEN;
+}
+
+
+static char * rtllib_ccmp_print_stats(char *p, void *priv)
+{
+	struct rtllib_ccmp_data *ccmp = priv;
+	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
+		     "tx_pn=%02x%02x%02x%02x%02x%02x "
+		     "rx_pn=%02x%02x%02x%02x%02x%02x "
+		     "format_errors=%d replays=%d decrypt_errors=%d\n",
+		     ccmp->key_idx, ccmp->key_set,
+		     MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+		     ccmp->dot11RSNAStatsCCMPFormatErrors,
+		     ccmp->dot11RSNAStatsCCMPReplays,
+		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
+
+	return p;
+}
+
+void rtllib_ccmp_null(void)
+{
+	return;
+}
+
+static struct rtllib_crypto_ops rtllib_crypt_ccmp = {
+	.name			= "CCMP",
+	.init			= rtllib_ccmp_init,
+	.deinit			= rtllib_ccmp_deinit,
+	.encrypt_mpdu		= rtllib_ccmp_encrypt,
+	.decrypt_mpdu		= rtllib_ccmp_decrypt,
+	.encrypt_msdu		= NULL,
+	.decrypt_msdu		= NULL,
+	.set_key		= rtllib_ccmp_set_key,
+	.get_key		= rtllib_ccmp_get_key,
+	.print_stats		= rtllib_ccmp_print_stats,
+	.extra_prefix_len	= CCMP_HDR_LEN,
+	.extra_postfix_len	= CCMP_MIC_LEN,
+	.owner			= THIS_MODULE,
+};
+
+
+int __init rtllib_crypto_ccmp_init(void)
+{
+	return rtllib_register_crypto_ops(&rtllib_crypt_ccmp);
+}
+
+
+void __exit rtllib_crypto_ccmp_exit(void)
+{
+	rtllib_unregister_crypto_ops(&rtllib_crypt_ccmp);
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_ccmp_null);
+
+module_init(rtllib_crypto_ccmp_init);
+module_exit(rtllib_crypto_ccmp_exit);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_wep.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_crypt_wep.c
@@ -0,0 +1,404 @@
+/*
+ * Host AP crypt: host-based WEP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <asm/string.h>
+#ifdef _RTL8192_EXT_PATCH_	
+#include <linux/etherdevice.h>
+#endif
+#include "rtllib.h"
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20))
+#endif
+
+
+#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "rtl_crypto.h"
+#else
+#include <linux/crypto.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) 
+    #include <asm/scatterlist.h>
+#else
+    #include <linux/scatterlist.h>
+#endif
+#include <linux/crc32.h>
+/*
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include "rtl_crypto.h"
+#else
+#include <linux/crypto.h>
+#endif
+
+#include <asm/scatterlist.h>
+#include <linux/crc32.h>
+*/
+#ifndef BUILT_IN_RTLLIB
+MODULE_AUTHOR("Jouni Malinen");
+MODULE_DESCRIPTION("Host AP crypt: WEP");
+MODULE_LICENSE("GPL");
+#endif
+struct prism2_wep_data {
+	u32 iv;
+#define WEP_KEY_LEN 13
+	u8 key[WEP_KEY_LEN + 1];
+	u8 key_len;
+	u8 key_idx;
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	struct crypto_tfm *tfm;
+	#else
+        struct crypto_blkcipher *tx_tfm;
+        struct crypto_blkcipher *rx_tfm;
+        #endif
+};
+
+
+static void * prism2_wep_init(int keyidx)
+{
+	struct prism2_wep_data *priv;
+
+	priv = kmalloc(sizeof(*priv), GFP_ATOMIC);
+	if (priv == NULL)
+		goto fail;
+	memset(priv, 0, sizeof(*priv));
+	priv->key_idx = keyidx;
+
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	priv->tfm = crypto_alloc_tfm("arc4", 0);
+	if (priv->tfm == NULL) {
+		printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate "
+		       "crypto API arc4\n");
+		goto fail;
+	}
+	#else
+	priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
+        if (IS_ERR(priv->tx_tfm)) {
+                printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate "
+                       "crypto API arc4\n");
+                priv->tx_tfm = NULL;
+                goto fail;
+        }
+        priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
+        if (IS_ERR(priv->rx_tfm)) {
+                printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate "
+                       "crypto API arc4\n");
+                priv->rx_tfm = NULL;
+                goto fail;
+        }
+        #endif
+
+	/* start WEP IV from a random value */
+	get_random_bytes(&priv->iv, 4);
+
+	return priv;
+
+fail:
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	if (priv) {
+		if (priv->tfm)
+			crypto_free_tfm(priv->tfm);
+		kfree(priv);
+	}
+	#else
+	if (priv) {
+                if (priv->tx_tfm)
+                        crypto_free_blkcipher(priv->tx_tfm);
+                if (priv->rx_tfm)
+                        crypto_free_blkcipher(priv->rx_tfm);
+                kfree(priv);
+        }
+        #endif
+	return NULL;
+}
+
+
+static void prism2_wep_deinit(void *priv)
+{
+	struct prism2_wep_data *_priv = priv;
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+	if (_priv && _priv->tfm)
+		crypto_free_tfm(_priv->tfm);
+	#else
+	if (_priv) {
+                if (_priv->tx_tfm)
+                        crypto_free_blkcipher(_priv->tx_tfm);
+                if (_priv->rx_tfm)
+                        crypto_free_blkcipher(_priv->rx_tfm);
+        }
+        #endif
+	kfree(priv);
+}
+
+/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
+ * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
+ * so the payload length increases with 8 bytes.
+ *
+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
+ */
+static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct prism2_wep_data *wep = priv;
+	u32 klen, len;
+	u8 key[WEP_KEY_LEN + 3];
+	u8 *pos;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
+	struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
+	#endif
+	u32 crc;
+	u8 *icv;
+#ifdef _RTL8192_EXT_PATCH_	
+	u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct rtllib_hdr_3addr* tmp_header = (struct rtllib_hdr_3addr*)(skb->data);
+	u8 is_broadcast_data = 0;
+	u8 is_multicast_data = 0;
+#endif
+	struct scatterlist sg;
+	if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
+	    skb->len < hdr_len){
+		printk("Error!!!headroom=%d tailroom=%d skblen=%d hdr_len=%d\n",skb_headroom(skb),skb_tailroom(skb),skb->len,hdr_len);
+		return -1;
+	}
+#ifdef _RTL8192_EXT_PATCH_	
+	if(tcb_desc->badhoc==0){
+		if(memcmp(tmp_header->addr1,broadcastaddr,6) == 0){
+			is_broadcast_data = 1;
+			tcb_desc->bHwSec = 0;
+		}
+		if(is_multicast_ether_addr(tmp_header->addr1)){
+			is_multicast_data = 1;
+			tcb_desc->bHwSec = 0;
+		}
+	}
+#endif
+	len = skb->len - hdr_len;
+	pos = skb_push(skb, 4);
+	memmove(pos, pos + 4, hdr_len);
+	pos += hdr_len;
+
+	klen = 3 + wep->key_len;
+
+	wep->iv++;
+
+	/* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
+	 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
+	 * can be used to speedup attacks, so avoid using them. */
+	if ((wep->iv & 0xff00) == 0xff00) {
+		u8 B = (wep->iv >> 16) & 0xff;
+		if (B >= 3 && B < klen)
+			wep->iv += 0x0100;
+	}
+
+	/* Prepend 24-bit IV to RC4 key and TX frame */
+	*pos++ = key[0] = (wep->iv >> 16) & 0xff;
+	*pos++ = key[1] = (wep->iv >> 8) & 0xff;
+	*pos++ = key[2] = wep->iv & 0xff;
+	*pos++ = wep->key_idx << 6;
+
+	/* Copy rest of the WEP key (the secret part) */
+	memcpy(key + 3, wep->key, wep->key_len);
+
+	if (!tcb_desc->bHwSec)
+	{
+	
+		/* Append little-endian CRC32 and encrypt it to produce ICV */
+	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+		crc = ~crc32_le(~0, pos, len);
+	#else
+		crc = ~ether_crc_le(len, pos);
+	#endif
+		icv = skb_put(skb, 4);
+		icv[0] = crc;
+		icv[1] = crc >> 8;
+		icv[2] = crc >> 16;
+		icv[3] = crc >> 24;
+		
+	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		sg.page = virt_to_page(pos);
+		sg.offset = offset_in_page(pos);
+		sg.length = len + 4;
+	#else
+		sg_init_one(&sg, pos, len+4);
+	#endif
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		crypto_cipher_setkey(wep->tfm, key, klen);
+		crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
+		return 0;
+	#else
+		crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
+		return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
+	#endif
+	}
+
+	return 0;
+}
+
+
+/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
+ * the frame: IV (4 bytes), encrypted payload (including SNAP header),
+ * ICV (4 bytes). len includes both IV and ICV.
+ *
+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
+ * failure. If frame is OK, IV and ICV will be removed.
+ */
+static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+	struct prism2_wep_data *wep = priv;
+	u32  klen, plen;
+	u8 key[WEP_KEY_LEN + 3];
+	u8 keyidx, *pos;
+	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+	#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) )
+	struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
+	#endif
+	u32 crc;
+	u8 icv[4];
+	struct scatterlist sg;
+	if (skb->len < hdr_len + 8)
+		return -1;
+
+	pos = skb->data + hdr_len;
+	key[0] = *pos++;
+	key[1] = *pos++;
+	key[2] = *pos++;
+	keyidx = *pos++ >> 6;
+	if (keyidx != wep->key_idx)
+		return -1;
+
+	klen = 3 + wep->key_len;
+
+	/* Copy rest of the WEP key (the secret part) */
+	memcpy(key + 3, wep->key, wep->key_len);
+
+	/* Apply RC4 to data and compute CRC32 over decrypted data */
+	plen = skb->len - hdr_len - 8;
+
+	if (!tcb_desc->bHwSec)
+	{
+	#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+		sg.page = virt_to_page(pos);
+		sg.offset = offset_in_page(pos);
+		sg.length = plen + 4;
+	#else
+		sg_init_one(&sg, pos, plen+4);
+	#endif
+	#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) )
+		crypto_cipher_setkey(wep->tfm, key, klen);
+		crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
+	#else
+		crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
+		if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
+			return -7;
+	#endif
+	#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+		crc = ~crc32_le(~0, pos, plen);
+	#else
+		crc = ~ether_crc_le(plen, pos);
+	#endif
+		icv[0] = crc;
+		icv[1] = crc >> 8;
+		icv[2] = crc >> 16;
+		icv[3] = crc >> 24;
+		if (memcmp(icv, pos + plen, 4) != 0) {
+			/* ICV mismatch - drop frame */
+			return -2;
+		}
+	}
+	/* Remove IV and ICV */
+	memmove(skb->data + 4, skb->data, hdr_len);
+	skb_pull(skb, 4);
+	skb_trim(skb, skb->len - 4);
+
+	return 0;
+}
+
+
+static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct prism2_wep_data *wep = priv;
+
+	if (len < 0 || len > WEP_KEY_LEN)
+		return -1;
+
+	memcpy(wep->key, key, len);
+	wep->key_len = len;
+
+	return 0;
+}
+
+
+static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
+{
+	struct prism2_wep_data *wep = priv;
+
+	if (len < wep->key_len)
+		return -1;
+
+	memcpy(key, wep->key, wep->key_len);
+
+	return wep->key_len;
+}
+
+
+static char * prism2_wep_print_stats(char *p, void *priv)
+{
+	struct prism2_wep_data *wep = priv;
+	p += sprintf(p, "key[%d] alg=WEP len=%d\n",
+		     wep->key_idx, wep->key_len);
+	return p;
+}
+
+
+static struct rtllib_crypto_ops rtllib_crypt_wep = {
+	.name			= "WEP",
+	.init			= prism2_wep_init,
+	.deinit			= prism2_wep_deinit,
+	.encrypt_mpdu		= prism2_wep_encrypt,
+	.decrypt_mpdu		= prism2_wep_decrypt,
+	.encrypt_msdu		= NULL,
+	.decrypt_msdu		= NULL,
+	.set_key		= prism2_wep_set_key,
+	.get_key		= prism2_wep_get_key,
+	.print_stats		= prism2_wep_print_stats,
+	.extra_prefix_len	= 4, /* IV */
+	.extra_postfix_len	= 4, /* ICV */
+	.owner			= THIS_MODULE,
+};
+
+
+int __init rtllib_crypto_wep_init(void)
+{
+	return rtllib_register_crypto_ops(&rtllib_crypt_wep);
+}
+
+
+void __exit rtllib_crypto_wep_exit(void)
+{
+	rtllib_unregister_crypto_ops(&rtllib_crypt_wep);
+}
+
+void rtllib_wep_null(void)
+{
+        return;
+}
+
+#ifndef BUILT_IN_RTLLIB
+EXPORT_SYMBOL_RSL(rtllib_wep_null);
+
+module_init(rtllib_crypto_wep_init);
+module_exit(rtllib_crypto_wep_exit);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/wapi.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/wapi.h
@@ -0,0 +1,135 @@
+#ifndef __INC_WAPI_H
+#define __INC_WAPI_H
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include "rtl819x_Qos.h"
+
+/* WAPI trace debug */
+extern u32 wapi_debug_component;
+
+#define WAPI_TRACE(component, x, args...) \
+do { if(wapi_debug_component & (component)) \
+	printk(KERN_DEBUG "WAPI" ":" x "" , \
+	       ##args);\
+}while(0);
+
+#define WAPI_DATA(component, x, buf, len) \
+do { if(wapi_debug_component & (component)){ \
+	printk("%s:\n", x);\
+	dump_buf((buf), (len));}\
+}while(0);
+
+enum WAPI_DEBUG {
+	WAPI_INIT				=BIT0,
+	WAPI_API				= BIT1,	 
+	WAPI_TX				= BIT2,	 
+	WAPI_RX				= BIT3,
+	WAPI_ERR		        	= BIT31
+};
+
+#define			WAPI_MAX_BKID_NUM				64
+#define			WAPI_MAX_STAINFO_NUM			64
+typedef struct  _RT_WAPI_BKID
+{
+	struct list_head	list;
+	u8				bkid[16];
+}RT_WAPI_BKID,*PRT_WAPI_BKID;
+
+typedef struct  _RT_WAPI_KEY
+{
+	u8			dataKey[16];
+	u8			micKey[16];
+	u8			keyId;
+	bool			bSet;
+	bool             bTxEnable;
+}RT_WAPI_KEY,*PRT_WAPI_KEY;
+
+typedef enum _RT_WAPI_PACKET_TYPE
+{
+	WAPI_NONE = 0,
+	WAPI_PREAUTHENTICATE=1,
+	WAPI_STAKEY_REQUEST=2,
+	WAPI_AUTHENTICATE_ACTIVE=3,
+	WAPI_ACCESS_AUTHENTICATE_REQUEST=4,
+	WAPI_ACCESS_AUTHENTICATE_RESPONSE=5,
+	WAPI_CERTIFICATE_AUTHENTICATE_REQUEST=6,
+	WAPI_CERTIFICATE_AUTHENTICATE_RESPONSE=7,
+	WAPI_USK_REQUEST=8,
+	WAPI_USK_RESPONSE=9,
+	WAPI_USK_CONFIRM=10,
+	WAPI_MSK_NOTIFICATION=11,
+	WAPI_MSK_RESPONSE=12
+}RT_WAPI_PACKET_TYPE;
+
+typedef struct _RT_CACHE_INFO {
+	u8	cache_buffer[2000];
+	u16	cache_buffer_len;
+	u8 saddr[6];
+	bool bAuthenticator;
+	u16	recvSeq;
+	u8	lastFragNum;
+	struct list_head list;
+}RT_CACHE_INFO, *PRT_CACHE_INFO;
+
+typedef struct	_RT_WAPI_STA_INFO
+{
+	struct list_head		list;
+	u8					PeerMacAddr[6];	
+	RT_WAPI_KEY		      wapiUsk;
+	RT_WAPI_KEY		      wapiUskUpdate;
+	RT_WAPI_KEY		      wapiMsk;
+	RT_WAPI_KEY		      wapiMskUpdate;	
+	u8					lastRxUnicastPN[16];
+	u8					lastTxUnicastPN[16];
+	u8					lastRxMulticastPN[16];
+	u8					lastRxUnicastPNBEQueue[16];
+	u8					lastRxUnicastPNBKQueue[16];
+	u8					lastRxUnicastPNVIQueue[16];
+	u8					lastRxUnicastPNVOQueue[16];
+	bool					bSetkeyOk;
+	bool					bAuthenticateInProgress;
+	bool					bAuthenticatorInUpdata;
+}RT_WAPI_STA_INFO,*PRT_WAPI_STA_INFO;
+
+typedef struct _RT_WAPI_T
+{
+   	u8		assoReqWapiIE[256];
+	u8		assoReqWapiIELength;
+	u8		assoRspWapiIE[256];
+	u8		assoRspWapiIELength;
+	u8		sendbeaconWapiIE[256];
+	u8		sendbeaconWapiIELength;
+	RT_WAPI_BKID		wapiBKID[WAPI_MAX_BKID_NUM];
+	struct list_head		wapiBKIDIdleList;
+	struct list_head  		wapiBKIDStoreList;
+	RT_WAPI_KEY		      wapiTxMsk;
+
+	u8				wapiDestMacAddr[6];
+	bool				bAuthenticator;
+	u8				lastTxMulticastPN[16];
+	RT_WAPI_STA_INFO	wapiSta[WAPI_MAX_STAINFO_NUM];
+	struct list_head		wapiSTAIdleList;
+	struct list_head		wapiSTAUsedList;
+	bool				bWapiEnable;
+	bool				bUpdateUsk;
+	bool				bUpdateMsk;
+
+	u8				wapiIE[256];
+	u8				wapiIELength;
+	bool				bWapiNotSetEncMacHeader;
+	bool				bWapiPSK;
+	bool				bFirstAuthentiateInProgress;
+	u16				wapiSeqnumAndFragNum;
+	int extra_prefix_len;
+	int extra_postfix_len;
+}RT_WAPI_T,*PRT_WAPI_T;
+
+typedef struct _WLAN_HEADER_WAPI_EXTENSION
+{
+    u8      KeyIdx;
+    u8      Reserved;
+    u8      PN[16];
+} WLAN_HEADER_WAPI_EXTENSION, *PWLAN_HEADER_WAPI_EXTENSION;
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/arc4.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/arc4.c
@@ -0,0 +1,105 @@
+/* 
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@oberheide.org>
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include "rtl_crypto.h"
+
+#define ARC4_MIN_KEY_SIZE	1
+#define ARC4_MAX_KEY_SIZE	256
+#define ARC4_BLOCK_SIZE		1
+
+struct arc4_ctx {
+	u8 S[256];
+	u8 x, y;
+};
+
+static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+	int i, j = 0, k = 0;
+
+	ctx->x = 1;
+	ctx->y = 0;
+
+	for(i = 0; i < 256; i++)
+		ctx->S[i] = i;
+
+	for(i = 0; i < 256; i++)
+	{
+		u8 a = ctx->S[i];
+		j = (j + in_key[k] + a) & 0xff;
+		ctx->S[i] = ctx->S[j];
+		ctx->S[j] = a;
+		if((unsigned int)++k >= key_len)
+			k = 0;
+	}
+
+	return 0;
+}
+
+static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+
+	u8 *const S = ctx->S;
+	u8 x = ctx->x;
+	u8 y = ctx->y;
+	u8 a, b;
+
+	a = S[x];
+	y = (y + a) & 0xff;
+	b = S[y];
+	S[x] = b;
+	S[y] = a;
+	x = (x + 1) & 0xff;
+	*out++ = *in ^ S[(a + b) & 0xff];
+
+	ctx->x = x;
+	ctx->y = y;
+}
+
+static struct crypto_alg arc4_alg = {
+	.cra_name		=	"arc4",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	ARC4_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct arc4_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
+	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
+	.cia_setkey	   	= 	arc4_set_key,
+	.cia_encrypt	 	=	arc4_crypt,
+	.cia_decrypt	  	=	arc4_crypt } }
+};
+
+int __init arc4_init(void)
+{
+	return crypto_register_alg(&arc4_alg);
+}
+
+
+void __exit arc4_exit(void)
+{
+	crypto_unregister_alg(&arc4_alg);
+}
+
+#ifndef BUILT_IN_CRYPTO
+module_init(arc4_init);
+module_exit(arc4_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
+MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl_crypto.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl_crypto.h
@@ -0,0 +1,409 @@
+/*
+ * Scatterlist Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ *
+ * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
+ * and Nettle, by Niels M鰈ler.
+ * 
+ * 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.
+ *
+ */
+#ifndef _LINUX_CRYPTO_H
+#define _LINUX_CRYPTO_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <asm/errno.h>
+
+#ifdef BUILT_IN_CRYPTO
+#ifdef CONFIG_CRYPTO_HMAC
+#undef CONFIG_CRYPTO_HMAC
+#endif
+
+#ifdef CONFIG_KMOD
+#undef CONFIG_KMOD
+#endif
+#endif /* BUILT_IN_CRYPTO */
+
+#define crypto_register_alg crypto_register_alg_rsl
+#define crypto_unregister_alg crypto_unregister_alg_rsl
+#define crypto_alloc_tfm crypto_alloc_tfm_rsl
+#define crypto_free_tfm crypto_free_tfm_rsl
+#define crypto_alg_available crypto_alg_available_rsl
+
+/*
+ * Algorithm masks and types.
+ */
+#define CRYPTO_ALG_TYPE_MASK		0x000000ff
+#define CRYPTO_ALG_TYPE_CIPHER		0x00000001
+#define CRYPTO_ALG_TYPE_DIGEST		0x00000002
+#define CRYPTO_ALG_TYPE_COMPRESS	0x00000004
+
+/*
+ * Transform masks and values (for crt_flags).
+ */
+#define CRYPTO_TFM_MODE_MASK		0x000000ff
+#define CRYPTO_TFM_REQ_MASK		0x000fff00
+#define CRYPTO_TFM_RES_MASK		0xfff00000
+
+#define CRYPTO_TFM_MODE_ECB		0x00000001
+#define CRYPTO_TFM_MODE_CBC		0x00000002
+#define CRYPTO_TFM_MODE_CFB		0x00000004
+#define CRYPTO_TFM_MODE_CTR		0x00000008
+
+#define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
+#define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
+#define CRYPTO_TFM_RES_BAD_KEY_LEN   	0x00200000
+#define CRYPTO_TFM_RES_BAD_KEY_SCHED 	0x00400000
+#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 	0x00800000
+#define CRYPTO_TFM_RES_BAD_FLAGS 	0x01000000
+
+/*
+ * Miscellaneous stuff.
+ */
+#define CRYPTO_UNSPEC			0
+#define CRYPTO_MAX_ALG_NAME		64
+
+struct scatterlist;
+
+/*
+ * Algorithms: modular crypto algorithm implementations, managed
+ * via crypto_register_alg() and crypto_unregister_alg().
+ */
+struct cipher_alg {
+	unsigned int cia_min_keysize;
+	unsigned int cia_max_keysize;
+	int (*cia_setkey)(void *ctx, const u8 *key,
+	                  unsigned int keylen, u32 *flags);
+	void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
+	void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
+};
+
+struct digest_alg {
+	unsigned int dia_digestsize;
+	void (*dia_init)(void *ctx);
+	void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
+	void (*dia_final)(void *ctx, u8 *out);
+	int (*dia_setkey)(void *ctx, const u8 *key,
+	                  unsigned int keylen, u32 *flags);
+};
+
+struct compress_alg {
+	int (*coa_init)(void *ctx);
+	void (*coa_exit)(void *ctx);
+	int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
+	                    u8 *dst, unsigned int *dlen);
+	int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
+	                      u8 *dst, unsigned int *dlen);
+};
+
+#define cra_cipher	cra_u.cipher
+#define cra_digest	cra_u.digest
+#define cra_compress	cra_u.compress
+
+struct crypto_alg {
+	struct list_head cra_list;
+	u32 cra_flags;
+	unsigned int cra_blocksize;
+	unsigned int cra_ctxsize;
+	const char cra_name[CRYPTO_MAX_ALG_NAME];
+
+	union {
+		struct cipher_alg cipher;
+		struct digest_alg digest;
+		struct compress_alg compress;
+	} cra_u;
+	
+	struct module *cra_module;
+};
+
+/*
+ * Algorithm registration interface.
+ */
+int crypto_register_alg(struct crypto_alg *alg);
+int crypto_unregister_alg(struct crypto_alg *alg);
+
+/*
+ * Algorithm query interface.
+ */
+int crypto_alg_available(const char *name, u32 flags);
+
+/*
+ * Transforms: user-instantiated objects which encapsulate algorithms
+ * and core processing logic.  Managed via crypto_alloc_tfm() and
+ * crypto_free_tfm(), as well as the various helpers below.
+ */
+struct crypto_tfm;
+
+struct cipher_tfm {
+	void *cit_iv;
+	unsigned int cit_ivsize;
+	u32 cit_mode;
+	int (*cit_setkey)(struct crypto_tfm *tfm,
+	                  const u8 *key, unsigned int keylen);
+	int (*cit_encrypt)(struct crypto_tfm *tfm,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int nbytes);
+	int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
+	                      struct scatterlist *dst,
+	                      struct scatterlist *src,
+	                      unsigned int nbytes, u8 *iv);
+	int (*cit_decrypt)(struct crypto_tfm *tfm,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int nbytes);
+	int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int nbytes, u8 *iv);
+	void (*cit_xor_block)(u8 *dst, const u8 *src);
+};
+
+struct digest_tfm {
+	void (*dit_init)(struct crypto_tfm *tfm);
+	void (*dit_update)(struct crypto_tfm *tfm,
+	                   struct scatterlist *sg, unsigned int nsg);
+	void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
+	void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
+	                   unsigned int nsg, u8 *out);
+	int (*dit_setkey)(struct crypto_tfm *tfm,
+	                  const u8 *key, unsigned int keylen);
+#ifdef CONFIG_CRYPTO_HMAC
+	void *dit_hmac_block;
+#endif
+};
+
+struct compress_tfm {
+	int (*cot_compress)(struct crypto_tfm *tfm,
+	                    const u8 *src, unsigned int slen,
+	                    u8 *dst, unsigned int *dlen);
+	int (*cot_decompress)(struct crypto_tfm *tfm,
+	                      const u8 *src, unsigned int slen,
+	                      u8 *dst, unsigned int *dlen);
+};
+
+#define crt_cipher	crt_u.cipher
+#define crt_digest	crt_u.digest
+#define crt_compress	crt_u.compress
+
+struct crypto_tfm {
+
+	u32 crt_flags;
+	
+	union {
+		struct cipher_tfm cipher;
+		struct digest_tfm digest;
+		struct compress_tfm compress;
+	} crt_u;
+	
+	struct crypto_alg *__crt_alg;
+};
+
+/* 
+ * Transform user interface.
+ */
+ 
+/*
+ * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
+ * If that fails and the kernel supports dynamically loadable modules, it
+ * will then attempt to load a module of the same name or alias.  A refcount
+ * is grabbed on the algorithm which is then associated with the new transform.
+ *
+ * crypto_free_tfm() frees up the transform and any associated resources,
+ * then drops the refcount on the associated algorithm.
+ */
+struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
+void crypto_free_tfm(struct crypto_tfm *tfm);
+
+/*
+ * Transform helpers which query the underlying algorithm.
+ */
+static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
+{
+	return tfm->__crt_alg->cra_name;
+}
+
+static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *alg = tfm->__crt_alg;
+	
+	if (alg->cra_module)
+		return alg->cra_module->name;
+	else
+		return NULL;
+}
+
+static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
+{
+	return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
+}
+
+static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->__crt_alg->cra_cipher.cia_min_keysize;
+}
+
+static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->__crt_alg->cra_cipher.cia_max_keysize;
+}
+
+static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_ivsize;
+}
+
+static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
+{
+	return tfm->__crt_alg->cra_blocksize;
+}
+
+static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	return tfm->__crt_alg->cra_digest.dia_digestsize;
+}
+
+/*
+ * API wrappers.
+ */
+static inline void crypto_digest_init(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	tfm->crt_digest.dit_init(tfm);
+}
+
+static inline void crypto_digest_update(struct crypto_tfm *tfm,
+                                        struct scatterlist *sg,
+                                        unsigned int nsg)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	tfm->crt_digest.dit_update(tfm, sg, nsg);
+}
+
+static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	tfm->crt_digest.dit_final(tfm, out);
+}
+
+static inline void crypto_digest_digest(struct crypto_tfm *tfm,
+                                        struct scatterlist *sg,
+                                        unsigned int nsg, u8 *out)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+}
+
+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+                                       const u8 *key, unsigned int keylen)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	if (tfm->crt_digest.dit_setkey == NULL)
+		return -ENOSYS;
+	return tfm->crt_digest.dit_setkey(tfm, key, keylen);
+}
+
+static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
+                                       const u8 *key, unsigned int keylen)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
+}
+
+static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
+                                        struct scatterlist *dst,
+                                        struct scatterlist *src,
+                                        unsigned int nbytes)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
+}                                        
+
+static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
+}                                        
+
+static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
+                                        struct scatterlist *dst,
+                                        struct scatterlist *src,
+                                        unsigned int nbytes)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
+}
+
+static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
+                                           struct scatterlist *dst,
+                                           struct scatterlist *src,
+                                           unsigned int nbytes, u8 *iv)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
+}
+
+static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
+                                        const u8 *src, unsigned int len)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	memcpy(tfm->crt_cipher.cit_iv, src, len);
+}
+
+static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
+                                        u8 *dst, unsigned int len)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	memcpy(dst, tfm->crt_cipher.cit_iv, len);
+}
+
+static inline int crypto_comp_compress(struct crypto_tfm *tfm,
+                                       const u8 *src, unsigned int slen,
+                                       u8 *dst, unsigned int *dlen)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+	return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
+}
+
+static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
+                                         const u8 *src, unsigned int slen,
+                                         u8 *dst, unsigned int *dlen)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+	return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
+}
+
+/*
+ * HMAC support.
+ */
+#ifdef CONFIG_CRYPTO_HMAC
+void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
+void crypto_hmac_update(struct crypto_tfm *tfm,
+                        struct scatterlist *sg, unsigned int nsg);
+void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
+                       unsigned int *keylen, u8 *out);
+void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
+                 struct scatterlist *sg, unsigned int nsg, u8 *out);
+#endif	/* CONFIG_CRYPTO_HMAC */
+
+#endif	/* _LINUX_CRYPTO_H */
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_HT.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_HT.h
@@ -0,0 +1,489 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL819XU_HTTYPE_H_
+#define _RTL819XU_HTTYPE_H_
+
+
+#define HT_OPMODE_NO_PROTECT		0
+#define HT_OPMODE_OPTIONAL		1
+#define HT_OPMODE_40MHZ_PROTECT	2
+#define HT_OPMODE_MIXED			3
+
+#define MIMO_PS_STATIC				0
+#define MIMO_PS_DYNAMIC			1
+#define MIMO_PS_NOLIMIT			3
+
+
+
+#define sHTCLng	4
+
+
+#define HT_SUPPORTED_MCS_1SS_BITMAP					0x000000ff
+#define HT_SUPPORTED_MCS_2SS_BITMAP					0x0000ff00
+#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP			HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
+
+
+typedef enum _HT_MCS_RATE{
+	HT_MCS0   = 0x00000001,
+	HT_MCS1   = 0x00000002,
+	HT_MCS2   = 0x00000004,
+	HT_MCS3   = 0x00000008,
+	HT_MCS4   = 0x00000010,
+	HT_MCS5   = 0x00000020,
+	HT_MCS6   = 0x00000040,
+	HT_MCS7   = 0x00000080,
+	HT_MCS8   = 0x00000100,
+	HT_MCS9   = 0x00000200,
+	HT_MCS10 = 0x00000400,
+	HT_MCS11 = 0x00000800,
+	HT_MCS12 = 0x00001000,
+	HT_MCS13 = 0x00002000,
+	HT_MCS14 = 0x00004000,
+	HT_MCS15 = 0x00008000,	
+}HT_MCS_RATE,*PHT_MCS_RATE;
+
+typedef enum _HT_CHANNEL_WIDTH{
+	HT_CHANNEL_WIDTH_20 = 0,
+	HT_CHANNEL_WIDTH_20_40 = 1,
+}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
+
+typedef enum _HT_EXTCHNL_OFFSET{
+	HT_EXTCHNL_OFFSET_NO_EXT = 0,
+	HT_EXTCHNL_OFFSET_UPPER = 1,
+	HT_EXTCHNL_OFFSET_NO_DEF = 2,
+	HT_EXTCHNL_OFFSET_LOWER = 3,
+}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
+
+typedef enum _CHNLOP{
+	CHNLOP_NONE = 0, 
+	CHNLOP_SCAN = 1, 
+	CHNLOP_SWBW = 2, 
+	CHNLOP_SWCHNL = 3, 
+} CHNLOP, *PCHNLOP;
+
+#define CHHLOP_IN_PROGRESS(_pHTInfo)	\
+		((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? true : false
+
+/*
+typedef	union _HT_CAPABILITY{
+	u16	ShortData;
+	u8	CharData[2];
+	struct
+	{
+		u16	AdvCoding:1;
+		u16	ChlWidth:1;
+		u16	MimoPwrSave:2;
+		u16	GreenField:1;
+		u16	ShortGI20Mhz:1;
+		u16	ShortGI40Mhz:1;
+		u16	STBC:1;
+		u16	BeamForm:1;
+		u16	DelayBA:1;
+		u16	MaxAMSDUSize:1;
+		u16	DssCCk:1;
+		u16	PSMP:1;
+		u16	Rsvd:3;
+	}Field;
+}HT_CAPABILITY, *PHT_CAPABILITY;
+
+typedef	union _HT_CAPABILITY_MACPARA{
+	u8	ShortData;
+	u8	CharData[1];
+	struct
+	{
+		u8	MaxRxAMPDU:2;
+		u8	MPDUDensity:2;
+		u8	Rsvd:4;
+	}Field;
+}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA;
+*/
+
+typedef enum _HT_ACTION{
+	ACT_RECOMMAND_WIDTH		= 0,
+	ACT_MIMO_PWR_SAVE 		= 1,
+	ACT_PSMP					= 2,
+	ACT_SET_PCO_PHASE		= 3,
+	ACT_MIMO_CHL_MEASURE	= 4,
+	ACT_RECIPROCITY_CORRECT	= 5,
+	ACT_MIMO_CSI_MATRICS		= 6,
+	ACT_MIMO_NOCOMPR_STEER	= 7,
+	ACT_MIMO_COMPR_STEER		= 8,
+	ACT_ANTENNA_SELECT		= 9,
+} HT_ACTION, *PHT_ACTION;
+
+
+typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
+	SC_MODE_DUPLICATE = 0,
+	SC_MODE_LOWER = 1,
+	SC_MODE_UPPER = 2,
+	SC_MODE_FULL40MHZ = 3,
+}HT_BW40_SC_E;
+
+typedef	struct _HT_CAPABILITY_ELE{
+
+	u8	AdvCoding:1;
+	u8	ChlWidth:1;
+	u8	MimoPwrSave:2;
+	u8	GreenField:1;
+	u8	ShortGI20Mhz:1;
+	u8	ShortGI40Mhz:1;
+	u8	TxSTBC:1;
+	u8	RxSTBC:2;
+	u8	DelayBA:1;
+	u8	MaxAMSDUSize:1;
+	u8	DssCCk:1;
+	u8	PSMP:1;
+	u8	Rsvd1:1;
+	u8	LSigTxopProtect:1;
+
+	u8	MaxRxAMPDUFactor:2;
+	u8	MPDUDensity:3;
+	u8	Rsvd2:3;
+
+	u8	MCS[16];
+			
+
+	u16	ExtHTCapInfo;
+
+	u8	TxBFCap[4];
+
+	u8	ASCap;
+
+} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
+
+
+typedef struct _HT_INFORMATION_ELE{
+	u8	ControlChl;
+
+	u8	ExtChlOffset:2;
+	u8	RecommemdedTxWidth:1;
+	u8	RIFS:1;
+	u8	PSMPAccessOnly:1;
+	u8	SrvIntGranularity:3;
+
+	u8	OptMode:2;
+	u8	NonGFDevPresent:1;
+	u8	Revd1:5;
+	u8	Revd2:8;
+
+	u8	Rsvd3:6;
+	u8	DualBeacon:1;
+	u8	DualCTSProtect:1;
+
+	u8	SecondaryBeacon:1;
+	u8	LSigTxopProtectFull:1;
+	u8	PcoActive:1;
+	u8	PcoPhase:1;
+	u8	Rsvd4:4;
+
+	u8	BasicMSC[16];
+} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
+
+typedef struct _MIMOPS_CTRL{
+	u8	MimoPsEnable:1;
+	u8	MimoPsMode:1;
+	u8	Reserved:6;
+} MIMOPS_CTRL, *PMIMOPS_CTRL;
+
+typedef enum _HT_SPEC_VER{
+	HT_SPEC_VER_IEEE = 0,
+	HT_SPEC_VER_EWC = 1,
+}HT_SPEC_VER, *PHT_SPEC_VER;
+
+typedef enum _HT_AGGRE_MODE_E{
+	HT_AGG_AUTO = 0,
+	HT_AGG_FORCE_ENABLE = 1,
+	HT_AGG_FORCE_DISABLE = 2,
+}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
+
+
+typedef struct _RT_HIGH_THROUGHPUT{
+	u8				bEnableHT;
+	u8				bCurrentHTSupport;
+
+	u8				bRegBW40MHz;				
+	u8				bCurBW40MHz;				
+
+	u8				bRegShortGI40MHz;			
+	u8				bCurShortGI40MHz;			
+
+	u8				bRegShortGI20MHz;			
+	u8				bCurShortGI20MHz;			
+
+	u8				bRegSuppCCK;				
+	u8				bCurSuppCCK;				
+
+	HT_SPEC_VER			ePeerHTSpecVer;
+	
+
+	HT_CAPABILITY_ELE	SelfHTCap;		
+	HT_INFORMATION_ELE	SelfHTInfo;		
+
+	u8				PeerHTCapBuf[32];
+	u8				PeerHTInfoBuf[32];
+
+
+	u8				bAMSDU_Support;			
+	u16				nAMSDU_MaxSize;			
+	u8				bCurrent_AMSDU_Support;	
+	u16				nCurrent_AMSDU_MaxSize;	
+#ifdef _RTL8192_EXT_PATCH_
+	u8				bCurrent_Mesh_AMSDU_Support;	
+#endif	
+
+	u8				bAMPDUEnable;				
+	u8				bCurrentAMPDUEnable;		
+	u8				AMPDU_Factor;				
+	u8				CurrentAMPDUFactor;		
+	u8				MPDU_Density;				
+	u8				CurrentMPDUDensity;			
+#ifdef _RTL8192_EXT_PATCH_
+	u8				bCurrentMeshAMPDUEnable;		
+#endif	
+
+	HT_AGGRE_MODE_E	ForcedAMPDUMode;
+	u8				ForcedAMPDUFactor;
+	u8				ForcedMPDUDensity;
+
+	HT_AGGRE_MODE_E	ForcedAMSDUMode;
+	u16				ForcedAMSDUMaxSize;
+
+	u8				bForcedShortGI;
+
+	u8				CurrentOpMode;
+
+	u8				SelfMimoPs;
+	u8				PeerMimoPs;
+	
+	HT_EXTCHNL_OFFSET	CurSTAExtChnlOffset;
+	u8				bCurTxBW40MHz;	
+	u8				PeerBandwidth;
+
+	u8				bSwBwInProgress;
+	CHNLOP				ChnlOp; 
+	u8				SwBwStep;
+
+	u8				bRegRT2RTAggregation;
+	u8				RT2RT_HT_Mode;	
+	u8				bCurrentRT2RTAggregation;
+	u8				bCurrentRT2RTLongSlotTime;
+	u8				szRT2RTAggBuffer[10];
+
+	u8				bRegRxReorderEnable;
+	u8				bCurRxReorderEnable;
+	u8				RxReorderWinSize;
+	u8				RxReorderPendingTime;
+	u16				RxReorderDropCounter;
+
+#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
+	u8				UsbTxAggrNum;
+#endif
+#ifdef USB_RX_AGGREGATION_SUPPORT
+	u8				UsbRxFwAggrEn;
+	u8				UsbRxFwAggrPageNum;
+	u8				UsbRxFwAggrPacketNum;
+	u8				UsbRxFwAggrTimeout;
+	u8				UsbRxPageSize;
+#endif
+
+	u8				bIsPeerBcm;
+
+	u8				IOTPeer;
+	u32				IOTAction;
+	u8				IOTRaFunc;
+
+	u8	bWAIotBroadcom;
+	u8	WAIotTH;
+
+#ifdef RTL8192CE
+	u8				bRDGEnable;
+#endif
+} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
+
+
+
+typedef struct _RT_HTINFO_STA_ENTRY{
+	u8			bEnableHT;
+	
+	u8			bSupportCck;
+	
+	u16			AMSDU_MaxSize;
+	
+	u8			AMPDU_Factor;
+	u8			MPDU_Density;
+	
+	u8			HTHighestOperaRate;
+
+	u8			bBw40MHz;
+
+	u8			bCurTxBW40MHz;
+
+	u8			bCurShortGI20MHz;
+
+	u8			bCurShortGI40MHz;
+
+	u8			MimoPs;
+
+	u8			McsRateSet[16];
+	
+	u8                      bCurRxReorderEnable;
+
+	u16                     nAMSDU_MaxSize;
+	
+}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
+
+
+
+
+
+
+typedef struct _BSS_HT{
+
+	u8				bdSupportHT;
+
+	u8					bdHTCapBuf[32];
+	u16					bdHTCapLen;
+	u8					bdHTInfoBuf[32];
+	u16					bdHTInfoLen;
+
+	HT_SPEC_VER				bdHTSpecVer;
+	HT_CHANNEL_WIDTH			bdBandWidth;
+
+	u8					bdRT2RTAggregation;
+	u8					bdRT2RTLongSlotTime;
+	u8					RT2RT_HT_Mode;
+	u8					bdHT1R;
+} __attribute__ ((packed)) BSS_HT, *PBSS_HT;
+
+typedef struct _MIMO_RSSI{
+	u32	EnableAntenna;
+	u32	AntennaA;
+	u32 	AntennaB;
+	u32 	AntennaC;
+	u32 	AntennaD;
+	u32	Average;
+}MIMO_RSSI, *PMIMO_RSSI;
+
+typedef struct _MIMO_EVM{
+	u32	EVM1;
+	u32    EVM2;
+}MIMO_EVM, *PMIMO_EVM;
+
+typedef struct _FALSE_ALARM_STATISTICS{
+	u32	Cnt_Parity_Fail;
+	u32	Cnt_Rate_Illegal;
+	u32	Cnt_Crc8_fail;
+	u32	Cnt_Mcs_fail;
+	u32	Cnt_Ofdm_fail;
+	u32	Cnt_Cck_fail;
+	u32	Cnt_all;
+}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
+
+
+extern u8 MCS_FILTER_ALL[16];
+extern u8 MCS_FILTER_1SS[16];
+
+#define PICK_RATE(_nLegacyRate, _nMcsRate)	\
+		(_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate)
+#define	LEGACY_WIRELESS_MODE	IEEE_MODE_MASK
+
+#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate)	\
+					((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\
+						(LegacyRate):\
+						(PICK_RATE(LegacyRate, HTRate))
+
+
+
+#define	RATE_ADPT_1SS_MASK 		0xFF
+#define	RATE_ADPT_2SS_MASK	   	0xF0 
+#define	RATE_ADPT_MCS32_MASK		0x01
+
+#define 	IS_11N_MCS_RATE(rate)		(rate&0x80)
+
+typedef enum _HT_AGGRE_SIZE{
+	HT_AGG_SIZE_8K = 0,
+	HT_AGG_SIZE_16K = 1,
+	HT_AGG_SIZE_32K = 2,
+	HT_AGG_SIZE_64K = 3,
+}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E;
+
+typedef enum _HT_IOT_PEER
+{
+	HT_IOT_PEER_UNKNOWN = 0,
+	HT_IOT_PEER_REALTEK = 1,
+	HT_IOT_PEER_REALTEK_92SE = 2,
+	HT_IOT_PEER_BROADCOM = 3,
+	HT_IOT_PEER_RALINK = 4,
+	HT_IOT_PEER_ATHEROS = 5,
+	HT_IOT_PEER_CISCO= 6,
+	HT_IOT_PEER_MARVELL=7,
+	HT_IOT_PEER_92U_SOFTAP = 8,
+	HT_IOT_PEER_SELF_SOFTAP = 9,
+	HT_IOT_PEER_MAX = 10,
+}HT_IOT_PEER_E, *PHTIOT_PEER_E;
+
+typedef enum _HT_IOT_ACTION{
+	HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
+	HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,	
+	HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
+	HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
+	HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
+	HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
+	HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
+	HT_IOT_ACT_CDD_FSYNC = 0x00000080,
+	HT_IOT_ACT_PURE_N_MODE = 0x00000100,
+	HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
+	HT_IOT_ACT_FORCED_RTS = 0x00000400,
+	HT_IOT_ACT_AMSDU_ENABLE = 0x00000800,
+	HT_IOT_ACT_REJECT_ADDBA_REQ = 0x00001000,
+	HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT = 0x00002000,
+	HT_IOT_ACT_EDCA_BIAS_ON_RX = 0x00004000,
+
+	HT_IOT_ACT_HYBRID_AGGREGATION = 0x00010000,
+	HT_IOT_ACT_DISABLE_SHORT_GI = 0x00020000,
+	HT_IOT_ACT_DISABLE_HIGH_POWER = 0x00040000,
+	HT_IOT_ACT_DISABLE_TX_40_MHZ = 0x00080000,
+	HT_IOT_ACT_TX_NO_AGGREGATION = 0x00100000,
+	HT_IOT_ACT_DISABLE_TX_2SS = 0x00200000,
+	
+        HT_IOT_ACT_MID_HIGHPOWER = 0x00400000,
+        HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
+        
+        HT_IOT_ACT_DISABLE_CCK_RATE = 0x01000000,
+	HT_IOT_ACT_FORCED_ENABLE_BE_TXOP = 0x02000000,
+	HT_IOT_ACT_WA_IOT_Broadcom = 0x04000000,
+}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
+
+typedef enum _HT_IOT_RAFUNC{
+	HT_IOT_RAFUNC_DISABLE_ALL = 0x00,
+	HT_IOT_RAFUNC_PEER_1R = 0x01,
+	HT_IOT_RAFUNC_TX_AMSDU = 0x02,
+}HT_IOT_RAFUNC, *PHT_IOT_RAFUNC;
+
+typedef enum _RT_HT_CAP{
+	RT_HT_CAP_USE_TURBO_AGGR = 0x01,
+	RT_HT_CAP_USE_LONG_PREAMBLE = 0x02,
+	RT_HT_CAP_USE_AMPDU = 0x04,
+	RT_HT_CAP_USE_WOW = 0x8,	
+	RT_HT_CAP_USE_SOFTAP = 0x10,	
+	RT_HT_CAP_USE_92SE = 0x20,
+}RT_HT_CAPBILITY, *PRT_HT_CAPBILITY;
+
+#endif 
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/compress.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/compress.c
@@ -0,0 +1,63 @@
+/*
+ * Cryptographic API.
+ *
+ * Compression operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include <linux/types.h>
+#include "rtl_crypto.h"
+#include <linux/errno.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include "internal.h"
+
+static int crypto_compress(struct crypto_tfm *tfm,
+                            const u8 *src, unsigned int slen,
+                            u8 *dst, unsigned int *dlen)
+{
+	return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm),
+	                                                 src, slen, dst,
+	                                                 dlen);
+}
+
+static int crypto_decompress(struct crypto_tfm *tfm,
+                             const u8 *src, unsigned int slen,
+                             u8 *dst, unsigned int *dlen)
+{
+	return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm),
+	                                                   src, slen, dst,
+	                                                   dlen);
+}
+
+int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
+{
+	return flags ? -EINVAL : 0;
+}
+
+int crypto_init_compress_ops(struct crypto_tfm *tfm)
+{
+	int ret = 0;
+	struct compress_tfm *ops = &tfm->crt_compress;
+	
+	ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm));
+	if (ret)
+		goto out;
+
+	ops->cot_compress = crypto_compress;
+	ops->cot_decompress = crypto_decompress;
+	
+out:
+	return ret;
+}
+
+void crypto_exit_compress_ops(struct crypto_tfm *tfm)
+{
+	tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtl819x_TS.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtl819x_TS.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _TSTYPE_H_
+#define _TSTYPE_H_
+#include "rtl819x_Qos.h"
+#define TS_SETUP_TIMEOUT	60  
+#define TS_INACT_TIMEOUT	60
+#define TS_ADDBA_DELAY		60
+
+#define TOTAL_TS_NUM		16
+#define TCLAS_NUM		4
+
+typedef enum _TR_SELECT {
+	TX_DIR = 0, 
+	RX_DIR = 1,
+} TR_SELECT, *PTR_SELECT;
+
+typedef struct _TS_COMMON_INFO{
+	struct list_head		List;
+	struct timer_list		SetupTimer;
+	struct timer_list		InactTimer;
+	u8				Addr[6];
+	TSPEC_BODY			TSpec;
+	QOS_TCLAS			TClass[TCLAS_NUM];
+	u8				TClasProc;
+	u8				TClasNum;
+} TS_COMMON_INFO, *PTS_COMMON_INFO;
+
+typedef struct _TX_TS_RECORD{
+	TS_COMMON_INFO		TsCommonInfo;
+	u16				TxCurSeq;
+	BA_RECORD			TxPendingBARecord;  	
+	BA_RECORD			TxAdmittedBARecord;	
+	u8				bAddBaReqInProgress;
+	u8				bAddBaReqDelayed;
+	u8				bUsingBa;
+	u8 				bDisable_AddBa;
+	struct timer_list		TsAddBaTimer;
+	u8				num;
+} TX_TS_RECORD, *PTX_TS_RECORD;
+
+typedef struct _RX_TS_RECORD {
+	TS_COMMON_INFO		TsCommonInfo;
+	u16				RxIndicateSeq;
+	u16				RxTimeoutIndicateSeq;
+	struct list_head		RxPendingPktList;
+	struct timer_list		RxPktPendingTimer;
+	BA_RECORD			RxAdmittedBARecord;	 
+	u16				RxLastSeqNum;
+	u8				RxLastFragNum;
+	u8				num;
+} RX_TS_RECORD, *PRX_TS_RECORD;
+
+
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/proc.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/proc.c
@@ -0,0 +1,115 @@
+/*
+ * Scatterlist Cryptographic API.
+ *
+ * Procfs information.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * 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.
+ *
+ */
+#include <linux/init.h>
+#include "rtl_crypto.h"
+#include <linux/rwsem.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include "internal.h"
+
+extern struct list_head crypto_alg_list;
+extern struct rw_semaphore crypto_alg_sem;
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	struct list_head *v;
+	loff_t n = *pos;
+
+	down_read(&crypto_alg_sem);
+	list_for_each(v, &crypto_alg_list)
+		if (!n--)
+			return list_entry(v, struct crypto_alg, cra_list);
+	return NULL;
+}
+
+static void *c_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	struct list_head *v = p;
+	
+	(*pos)++;
+	v = v->next;
+	return (v == &crypto_alg_list) ?
+		NULL : list_entry(v, struct crypto_alg, cra_list);
+}
+
+static void c_stop(struct seq_file *m, void *p)
+{
+	up_read(&crypto_alg_sem);
+}
+
+static int c_show(struct seq_file *m, void *p)
+{
+	struct crypto_alg *alg = (struct crypto_alg *)p;
+	
+	seq_printf(m, "name         : %s\n", alg->cra_name);
+	seq_printf(m, "module       : %s\n",
+		   (alg->cra_module ?
+		    alg->cra_module->name :
+		    "kernel"));
+	
+	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
+	case CRYPTO_ALG_TYPE_CIPHER:
+		seq_printf(m, "type         : cipher\n");
+		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+		seq_printf(m, "min keysize  : %u\n",
+					alg->cra_cipher.cia_min_keysize);
+		seq_printf(m, "max keysize  : %u\n",
+					alg->cra_cipher.cia_max_keysize);
+		break;
+		
+	case CRYPTO_ALG_TYPE_DIGEST:
+		seq_printf(m, "type         : digest\n");
+		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+		seq_printf(m, "digestsize   : %u\n",
+		           alg->cra_digest.dia_digestsize);
+		break;
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		seq_printf(m, "type         : compression\n");
+		break;
+	default:
+		seq_printf(m, "type         : unknown\n");
+		break;
+	}
+
+	seq_putc(m, '\n');
+	return 0;
+}
+
+static struct seq_operations crypto_seq_ops = {
+	.start		= c_start,
+	.next		= c_next,
+	.stop		= c_stop,
+	.show		= c_show
+};
+
+static int crypto_info_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &crypto_seq_ops);
+}
+        
+static struct file_operations proc_crypto_ops = {
+	.open		= crypto_info_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release
+};
+
+void __init crypto_init_proc(void)
+{
+	struct proc_dir_entry *proc;
+	
+	proc = create_proc_entry("crypto", 0, NULL);
+	if (proc)
+		proc->proc_fops = &proc_crypto_ops;
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/wapi_interface.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/wapi_interface.h
@@ -0,0 +1,98 @@
+#ifndef __INC_WAPI_INTERFACE_H
+#define __INC_WAPI_INTERFACE_H
+#include <linux/spinlock.h>
+#include <linux/if_ether.h> /* ETH_ALEN */
+
+/*************************************************************
+ * WAPI EVENT QUEUE : 										 *
+ * Buffer events from driver to application.            					 * 
+ *************************************************************/
+#define WAPI_MAX_BUFF_LEN		2000	
+#define WAPI_MAX_QUEUE_LEN		6
+
+typedef enum
+{
+	E_WAPI_OK = 0,
+	E_WAPI_ITEM_TOO_LARGE = 1,
+	E_WAPI_QFULL = 2,
+	E_WAPI_QEMPTY = 3,
+	E_WAPI_QNULL = 4		
+}WAPI_QUEUE_RET_VAL;
+
+typedef struct _WAPI_QUEUE_NODE
+{
+    u16  ItemSize;
+    u8   Item[WAPI_MAX_BUFF_LEN];
+}WAPI_QUEUE_NODE;
+
+typedef struct _WAPI_QUEUE
+{
+    int     Head;
+    int     Tail;
+    int     NumItem;
+    int     MaxItem;
+    WAPI_QUEUE_NODE        ItemArray[WAPI_MAX_QUEUE_LEN];
+    int	MaxData;
+}WAPI_QUEUE;
+
+typedef enum{
+    WAPI_EVENT_RCV_PREAUTHENTICATE = 1, 
+    WAPI_EVENT_RCV_STAKEY_REQUEST = 2,
+    WAPI_EVENT_RCV_AUTHENTICATE_ACTIVE = 3,
+    WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_REQUEST = 4,
+    WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_RESPONSE = 5,
+    WAPI_EVENT_RCV_CERTIFICATE_AUTHENTICATE_REQUEST = 6,
+    WAPI_EVENT_RCV_CERTIFICATE_AUTHENTICATE_RESPONSE = 7,
+    WAPI_EVENT_RCV_USK_REQUEST = 8,
+    WAPI_EVENT_RCV_USK_RESPONSE = 9,                    
+    WAPI_EVENT_RCV_USK_CONFIRM = 10,
+    WAPI_EVENT_RCV_MSK_NOTIFICATION = 11,
+    WAPI_EVENT_RCV_MSK_RESPONSE = 12,                   
+    WAPI_EVENT_AE_UPDATE_BK = 13,
+    WAPI_EVENT_AE_UPDATE_USK = 14,
+    WAPI_EVENT_AE_UPDATE_MSK = 15,
+    WAPI_EVENT_ASUE_UPDATE_BK = 16,
+    WAPI_EVENT_ASUE_UPDATE_USK = 17,
+    WAPI_EVENT_FIRST_AUTHENTICATOR = 18,
+    WAPI_EVENT_CONNECT = 19,
+    WAPI_EVENT_DISCONNECT = 20,
+    WAPI_EVENT_MAX_NUM = 21
+} WAPI_EVENT_ID;
+
+typedef struct _WAPI_EVENT_T{
+    u8	EventId;
+    u8	MACAddr[ETH_ALEN];
+    u16	BuffLength;
+    u8  Buff[0];
+}__attribute__ ((packed))WAPI_EVENT_T;
+
+#define WAPI_IsEmptyQueue(q) (q->NumItem==0 ? 1:0)
+#define WAPI_IsFullQueue(q) (q->NumItem==q->MaxItem? 1:0)
+#define WAPI_NumItemQueue(q) q->NumItem
+
+void WAPI_InitQueue(WAPI_QUEUE *q, int szMaxItem, int szMaxData);
+int WAPI_EnQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int itemsize);
+int WAPI_DeQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int *itemsize);
+void WAPI_PrintQueue(WAPI_QUEUE *q);
+
+extern int pid_wapi;
+extern void notifyWapiApplication(void);
+/*************************************************************
+ * WAPI IOCTL: FROM APPLICATION TO DRIVER 					 *
+ *************************************************************/
+#define WAPI_CMD_GET_WAPI_SUPPORT 	0X8B81
+#define WAPI_CMD_SET_WAPI_ENABLE 	0X8B82
+#define WAPI_CMD_SET_WAPI_PSK	 	0X8B83
+#define WAPI_CMD_SET_KEY 				0X8B84
+#define WAPI_CMD_SET_MULTICAST_PN 	0X8B85
+#define WAPI_CMD_GET_PN 				0X8B86
+#define WAPI_CMD_GET_WAPIIE 			0X8B87
+#define WAPI_CMD_SET_SSID				0X8B88
+#define WAPI_CMD_GET_BSSID			0X8B89
+#define WAPI_CMD_SET_IW_MODE			0X8B8b
+#define WAPI_CMD_SET_DISASSOCIATE		0X8B8c
+#define WAPI_CMD_SAVE_PID			0X8B8d
+#define WAPI_CMD_DEQUEUE 				0X8B90
+
+#endif 
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtllib/rtllib_crypt.h
@@ -0,0 +1,93 @@
+/*
+ * Original code based on Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ *
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+/*
+ * This file defines the interface to the rtllib crypto module.
+ */
+#ifndef RTLLIB_CRYPT_H
+#define RTLLIB_CRYPT_H
+
+#include <linux/skbuff.h>
+
+struct rtllib_crypto_ops {
+	const char *name;
+
+	/* init new crypto context (e.g., allocate private data space,
+	 * select IV, etc.); returns NULL on failure or pointer to allocated
+	 * private data on success */
+	void * (*init)(int keyidx);
+
+	/* deinitialize crypto context and free allocated private data */
+	void (*deinit)(void *priv);
+
+	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
+	 * value from decrypt_mpdu is passed as the keyidx value for
+	 * decrypt_msdu. skb must have enough head and tail room for the
+	 * encryption; if not, error will be returned; these functions are
+	 * called for all MPDUs (i.e., fragments).
+	 */
+	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
+
+	/* These functions are called for full MSDUs, i.e. full frames.
+	 * These can be NULL if full MSDU operations are not needed. */
+	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
+	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
+			    void *priv, struct rtllib_device* ieee);
+
+	int (*set_key)(void *key, int len, u8 *seq, void *priv);
+	int (*get_key)(void *key, int len, u8 *seq, void *priv);
+
+	/* procfs handler for printing out key information and possible
+	 * statistics */
+	char * (*print_stats)(char *p, void *priv);
+
+	/* maximum number of bytes added by encryption; encrypt buf is
+	 * allocated with extra_prefix_len bytes, copy of in_buf, and
+	 * extra_postfix_len; encrypt need not use all this space, but
+	 * the result must start at the beginning of the buffer and correct
+	 * length must be returned */
+	int extra_prefix_len, extra_postfix_len;
+
+	struct module *owner;
+};
+
+struct rtllib_crypt_data {
+	struct list_head list; /* delayed deletion list */
+	struct rtllib_crypto_ops *ops;
+	void *priv;
+	atomic_t refcnt;
+};
+
+int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops);
+int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops);
+struct rtllib_crypto_ops * rtllib_get_crypto_ops(const char *name);
+void rtllib_crypt_deinit_entries(struct rtllib_device *, int);
+void rtllib_crypt_deinit_handler(unsigned long);
+void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
+				    struct rtllib_crypt_data **crypt);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,31))
+#define crypto_alloc_tfm crypto_alloc_tfm_rsl
+#define crypto_free_tfm crypto_free_tfm_rsl
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.h
@@ -0,0 +1,419 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_FIRMWARE_H
+#define __INC_FIRMWARE_H
+
+#include "r8192S_def.h"
+
+#define 	RTL8190_MAX_FIRMWARE_CODE_SIZE	64000	
+#define 	RTL8190_CPU_START_OFFSET			0x80
+#define	MAX_FIRMWARE_CODE_SIZE	0xFF00  
+
+#define		H2C_TX_CMD_HDR_LEN				8
+
+#define		RTL8192S_FW_PKT_FRAG_SIZE		0x4000	
+
+#ifdef RTL8192SE
+#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v)	4*(v/4) - 8
+#else 
+#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v)	(4*(v/4) - 8 - USB_HWDESC_HEADER_LEN)
+#endif
+
+typedef enum _DESC_PACKET_TYPE{
+	DESC_PACKET_TYPE_INIT = 0,
+	DESC_PACKET_TYPE_NORMAL = 1,	
+}DESC_PACKET_TYPE;
+
+
+#ifdef RTL8192S
+typedef enum _firmware_init_step{
+	FW_INIT_STEP0_IMEM = 0,
+	FW_INIT_STEP1_MAIN = 1,
+	FW_INIT_STEP2_DATA = 2,
+}firmware_init_step_e;
+#else
+typedef enum _firmware_init_step{
+	FW_INIT_STEP0_BOOT = 0,
+	FW_INIT_STEP1_MAIN = 1,
+	FW_INIT_STEP2_DATA = 2,
+}firmware_init_step_e;
+#endif
+
+typedef enum _firmware_source{
+	FW_SOURCE_IMG_FILE = 0,
+	FW_SOURCE_HEADER_FILE = 1,		
+}firmware_source_e, *pfirmware_source_e;
+
+typedef enum _opt_rst_type{
+	OPT_SYSTEM_RESET = 0,
+	OPT_FIRMWARE_RESET = 1,
+}opt_rst_type_e;
+
+typedef enum _FIRMWARE_STATUS{
+	FW_STATUS_0_INIT = 0,
+	FW_STATUS_1_MOVE_BOOT_CODE = 1,
+	FW_STATUS_2_MOVE_MAIN_CODE = 2,
+	FW_STATUS_3_TURNON_CPU = 3,
+	FW_STATUS_4_MOVE_DATA_CODE = 4,
+	FW_STATUS_5_READY = 5,
+}FIRMWARE_STATUS;
+
+typedef enum _H2C_CMD{
+	FW_H2C_SETPWRMODE	= 0,
+	FW_H2C_JOINBSSRPT	= 1,
+	FW_H2C_WoWLAN_UPDATE_GTK = 2,
+	FW_H2C_WoWLAN_UPDATE_IV = 3,
+	FW_H2C_WoWLAN_OFFLOAD = 4,
+	FW_H2C_SITESURVEY=5,
+}H2C_CMD;
+
+ typedef struct _H2C_SETPWRMODE_PARM {
+ 	u8	mode;
+ 	u8	flag_low_traffic_en; 
+ 	u8	flag_lpnav_en;
+ 	u8	flag_rf_low_snr_en;
+ 	u8	flag_dps_en; 
+ 	u8	bcn_rx_en;
+ 	u8	bcn_pass_cnt;
+ 	u8	bcn_to;  // beacon TO (ms). ��=0�� no limit.
+ 	u16	bcn_itv;
+ 	u8	app_itv; 
+ 	u8	awake_bcn_itvl;
+ 	u8	smart_ps;
+	u8	bcn_pass_period; 
+ }H2C_SETPWRMODE_PARM, *PH2C_SETPWRMODE_PARM; 
+
+typedef struct _H2C_JOINBSSRPT_PARM {	
+	u8	OpMode;	
+	u8	Ps_Qos_Info;
+	u8	Bssid[6];	
+	u16	BcnItv;	
+	u16	Aid;
+}H2C_JOINBSSRPT_PARM, *PH2C_JOINBSSRPT_PARM;
+
+typedef struct _H2C_WPA_PTK {
+ 	u8 	kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */
+ 	u8 	kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */
+	u8	tk1[16]; /* Temporal Key 1 (TK1) */
+	union {
+		u8	tk2[16]; 
+		struct {
+			u8	tx_mic_key[8];
+			u8	rx_mic_key[8];
+		}Athu;
+	}U;
+}H2C_WPA_PTK;
+
+typedef struct _H2C_WPA_TWO_WAY_PARA{
+	u8			pairwise_en_alg;
+	u8			group_en_alg;
+	H2C_WPA_PTK		wpa_ptk_value;
+}H2C_WPA_TWO_WAY_PARA, *PH2C_WPA_TWO_WAY_PARA;
+
+typedef struct _tx_desc_8192se_fw{
+
+        u32             PktSize:16;
+        u32             Offset:8;
+        u32             Type:2; 
+        u32             LastSeg:1;
+        u32             FirstSeg:1;
+        u32             LINIP:1;
+        u32             AMSDU:1;
+        u32             GF:1;
+        u32             OWN:1;
+
+        u32             MacID:5;
+        u32             MoreData:1;
+        u32             MoreFrag:1;
+        u32             PIFS:1;
+        u32             QueueSel:5;
+        u32             AckPolicy:2;
+        u32             NoACM:1;
+        u32             NonQos:1;
+        u32             KeyID:2;
+        u32             OUI:1;
+        u32             PktType:1;
+        u32             EnDescID:1;
+        u32             SecType:2;
+        u32             HTC:1;  
+        u32             WDS:1;  
+        u32             PktOffset:5;    
+        u32             HWPC:1;
+
+        u32             DataRetryLmt:6;
+        u32             RetryLmtEn:1;
+        u32             TSFL:5;
+        u32             RTSRC:6;        
+        u32             DATARC:6;       
+
+        u32             Rsvd1:5;
+        u32             AggEn:1;
+        u32             BK:1;   
+        u32             OwnMAC:1;
+
+        u32             NextHeadPage:8;
+        u32             TailPage:8;
+        u32             Seq:12;
+        u32             Frag:4;
+
+        u32             RTSRate:6;
+        u32             DisRTSFB:1;
+        u32             RTSRateFBLmt:4;
+        u32             CTS2Self:1;
+        u32             RTSEn:1;
+        u32             RaBRSRID:3;     
+        u32             TXHT:1;
+        u32             TxShort:1;
+        u32             TxBw:1;
+        u32             TXSC:2;
+        u32             STBC:2;
+        u32             RD:1;
+        u32             RTSHT:1;
+        u32             RTSShort:1;
+        u32             RTSBW:1;
+        u32             RTSSC:2;
+        u32             RTSSTBC:2;
+        u32             UserRate:1;
+
+        u32             PktID:9;
+        u32             TxRate:6;
+        u32             DISFB:1;
+        u32             DataRateFBLmt:5;
+        u32             TxAGC:11;
+
+        u32             IPChkSum:16;
+        u32             TCPChkSum:16;
+
+        u32             TxBufferSize:16;
+        u32             IPHdrOffset:8;
+        u32             Rsvd3:7;
+        u32             TCPEn:1;
+} tx_desc_fw, *ptx_desc_fw;
+
+typedef struct _H2C_SITESURVEY_PARA {
+    	u32 		start_flag; 
+    	u32 		probe_req_len; 
+  	tx_desc_fw	desc;		
+	u8		probe_req[0];
+}H2C_SITESURVEY_PARA, *PH2C_SITESURVEY_PARA;
+
+ typedef enum _FIRMWARE_H2C_CMD{
+	H2C_Read_MACREG_CMD ,		/*0*/
+	H2C_Write_MACREG_CMD ,		
+	H2C_ReadBB_CMD ,	
+	H2C_WriteBB_CMD ,		
+	H2C_ReadRF_CMD ,		
+	H2C_WriteRF_CMD ,		/*5*/
+	H2C_Read_EEPROM_CMD ,		
+	H2C_Write_EEPROM_CMD ,		
+	H2C_Read_EFUSE_CMD ,		
+	H2C_Write_EFUSE_CMD ,		
+	H2C_Read_CAM_CMD ,			/*10*/
+	H2C_Write_CAM_CMD ,			
+	H2C_setBCNITV_CMD,
+	H2C_setMBIDCFG_CMD,
+	H2C_JoinBss_CMD ,				
+	H2C_DisConnect_CMD,			/*15*/
+	H2C_CreateBss_CMD ,
+	H2C_SetOpMode_CMD,	
+	H2C_SiteSurvey_CMD,
+	H2C_SetAuth_CMD,
+	H2C_SetKey_CMD ,				/*20*/
+	H2C_SetStaKey_CMD ,
+	H2C_SetAssocSta_CMD,
+	H2C_DelAssocSta_CMD ,
+	H2C_SetStaPwrState_CMD ,
+	H2C_SetBasicRate_CMD ,		/*25*/
+	H2C_GetBasicRate_CMD ,
+	H2C_SetDataRate_CMD ,
+	H2C_GetDataRate_CMD ,
+	H2C_SetPhyInfo_CMD ,
+	H2C_GetPhyInfo_CMD ,			/*30*/
+	H2C_SetPhy_CMD ,
+	H2C_GetPhy_CMD ,
+	H2C_readRssi_CMD ,
+	H2C_readGain_CMD ,
+	H2C_SetAtim_CMD ,			/*35*/
+	H2C_SetPwrMode_CMD ,
+	H2C_JoinbssRpt_CMD,
+	H2C_SetRaTable_CMD ,	
+	H2C_GetRaTable_CMD ,	
+	H2C_GetCCXReport_CMD,            /*40*/
+	H2C_GetDTMReport_CMD,		
+	H2C_GetTXRateStatistics_CMD,
+	H2C_SetUsbSuspend_CMD,
+	H2C_SetH2cLbk_CMD ,
+	H2C_tmp1 ,			/*45*/
+	H2C_WoWLAN_UPDATE_GTK_CMD ,	
+	H2C_WoWLAN_FW_OFFLOAD , 
+	H2C_tmp2 , 
+	H2C_tmp3 , 
+	H2C_WoWLAN_UPDATE_IV_CMD , 		/*50*/		
+	H2C_tmp4,	
+	MAX_H2CCMD							/*52*/
+}FIRMWARE_H2C_CMD;
+
+
+typedef  struct _RT_8192S_FIRMWARE_PRIV { 
+
+	u8		signature_0;		
+	u8		signature_1;		
+	u8		hci_sel;			
+	u8		chip_version;	
+	u8		customer_ID_0;	
+	u8		customer_ID_1;	
+	u8		rf_config;		
+	u8		usb_ep_num;	
+	
+	u8		regulatory_class_0;	
+	u8		regulatory_class_1;	
+	u8		regulatory_class_2;	
+	u8		regulatory_class_3;	
+	u8		rfintfs;				
+	u8		def_nettype;		
+	u8		rsvd010;
+	u8		rsvd011;
+	
+	
+	u8		lbk_mode;	
+	u8		mp_mode;	
+	u8		rsvd020;
+	u8		rsvd021;
+	u8		rsvd022;
+	u8		rsvd023;
+	u8		rsvd024;
+	u8		rsvd025;
+
+	u8		qos_en;				
+	u8		bw_40MHz_en;		
+	u8		AMSDU2AMPDU_en;	
+	u8		AMPDU_en;			
+	u8		rate_control_offload;
+	u8		aggregation_offload;	
+	u8		rsvd030;
+	u8		rsvd031;
+
+	
+	unsigned char		beacon_offload;			
+	unsigned char		MLME_offload;			
+	unsigned char		hwpc_offload;			
+	unsigned char		tcp_checksum_offload;	
+	unsigned char		tcp_offload;				
+	unsigned char		ps_control_offload;		
+	unsigned char		WWLAN_offload;			
+	unsigned char		rsvd040;
+
+	u8		tcp_tx_frame_len_L;		
+	u8		tcp_tx_frame_len_H;		
+	u8		tcp_rx_frame_len_L;		
+	u8		tcp_rx_frame_len_H;		
+	u8		rsvd050;
+	u8		rsvd051;
+	u8		rsvd052;
+	u8		rsvd053;
+}RT_8192S_FIRMWARE_PRIV, *PRT_8192S_FIRMWARE_PRIV;
+
+typedef struct _RT_8192S_FIRMWARE_HDR {
+
+	u16		Signature;
+	u16		Version;		  
+	u32		DMEMSize;    
+
+
+	u32		IMG_IMEM_SIZE;    
+	u32		IMG_SRAM_SIZE;    
+
+	u32		FW_PRIV_SIZE;       
+	u32		Rsvd0;  
+
+	u32		Rsvd1;
+	u32		Rsvd2;
+
+	RT_8192S_FIRMWARE_PRIV	FWPriv;
+	
+}RT_8192S_FIRMWARE_HDR, *PRT_8192S_FIRMWARE_HDR;
+
+#define	RT_8192S_FIRMWARE_HDR_SIZE	80
+#define   RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE	32
+
+typedef enum _FIRMWARE_8192S_STATUS{
+	FW_STATUS_INIT = 0,
+	FW_STATUS_LOAD_IMEM = 1,
+	FW_STATUS_LOAD_EMEM = 2,
+	FW_STATUS_LOAD_DMEM = 3,
+	FW_STATUS_READY = 4,
+}FIRMWARE_8192S_STATUS;
+
+typedef struct _rt_firmware{	
+	firmware_source_e	eFWSource;	
+	PRT_8192S_FIRMWARE_HDR	pFwHeader;
+	FIRMWARE_8192S_STATUS	FWStatus;
+	u16		FirmwareVersion;
+	u8		FwIMEM[RTL8190_MAX_FIRMWARE_CODE_SIZE];
+	u8		FwEMEM[RTL8190_MAX_FIRMWARE_CODE_SIZE];
+	u32		FwIMEMLen;
+	u32		FwEMEMLen;	
+	u8		szFwTmpBuffer[164000];	
+	u32		szFwTmpBufferLen;
+	u16		CmdPacketFragThresold;		
+}rt_firmware, *prt_firmware;
+
+#define		FW_DIG_ENABLE_CTL			BIT0
+#define		FW_HIGH_PWR_ENABLE_CTL	BIT1
+#define		FW_SS_CTL					BIT2
+#define		FW_RA_INIT_CTL				BIT3
+#define		FW_RA_BG_CTL				BIT4
+#define		FW_RA_N_CTL				BIT5
+#define		FW_PWR_TRK_CTL			BIT6
+#define		FW_IQK_CTL					BIT7
+#define		FW_FA_CTL					BIT8
+#define		FW_DRIVER_CTRL_DM_CTL		BIT9
+#define		FW_PAPE_CTL_BY_SW_HW	BIT10
+#define		FW_DISABLE_ALL_DM			0
+
+#define		FW_PWR_TRK_PARAM_CLR		0x0000ffff
+#define		FW_RA_PARAM_CLR			0xffff0000
+
+#define FW_CMD_IO_CLR(priv, _Bit)		\
+	udelay(1000);	\
+	priv->FwCmdIOMap &= (~_Bit);
+
+#define FW_CMD_IO_UPDATE(priv, _val)		\
+	priv->FwCmdIOMap = _val;
+
+#define FW_CMD_IO_SET(priv, _val) 	\
+	write_nic_word(priv->rtllib->dev, LBUS_MON_ADDR, (u16)_val);	\
+	FW_CMD_IO_UPDATE(priv, _val);\
+
+#define FW_CMD_PARA_SET(priv, _val) 		\
+	write_nic_dword(priv->rtllib->dev, LBUS_ADDR_MASK, _val);	\
+	priv->FwCmdIOParam = _val;
+
+#define FW_CMD_IO_QUERY(priv)	(u16)(priv->FwCmdIOMap)
+#define FW_CMD_IO_PARA_QUERY(priv)	((u32)(priv->FwCmdIOParam))
+
+bool FirmwareEnableCPU(struct net_device *dev);
+bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus);
+
+bool FirmwareDownload92S(struct net_device *dev);
+int rtl8192se_send_scan_cmd(struct net_device 	*dev, bool start);
+
+void rtl8192se_dump_skb_data(struct sk_buff *skb);
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/Makefile
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/Makefile
@@ -0,0 +1,10 @@
+.PHONY:clean
+clean:
+	rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~
+	rm -fr .tmp_versions
+	rm -fr Modules.symvers
+	rm -fr Module.symvers
+	rm -fr Module.markers
+	rm -fr modules.order
+	rm -fr tags
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_def.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_def.h
@@ -0,0 +1,756 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef R8192SE_DEF_H
+#define R8192SE_DEF_H
+
+#include <linux/types.h>
+#include "../rtl_endianfree.h"
+
+#define HAL_RETRY_LIMIT_INFRA		48	
+#define HAL_RETRY_LIMIT_AP_ADHOC	7
+
+#define	HAL_DM_DIG_DISABLE				BIT0	
+#define	HAL_DM_HIPWR_DISABLE				BIT1	
+
+#define RX_DESC_SIZE				24
+#define RX_DRV_INFO_SIZE_UNIT	8
+
+
+#define TX_DESC_SIZE 				32
+
+#define SET_TX_DESC_PKT_SIZE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 0, 16, __Value)
+#define SET_TX_DESC_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 16, 8, __Value)
+#define SET_TX_DESC_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 24, 2, __Value)
+#define SET_TX_DESC_LAST_SEG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 26, 1, __Value)
+#define SET_TX_DESC_FIRST_SEG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 27, 1, __Value)
+#define SET_TX_DESC_LINIP(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 28, 1, __Value)
+#define SET_TX_DESC_AMSDU(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 29, 1, __Value)
+#define SET_TX_DESC_GREEN_FIELD(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 30, 1, __Value)
+#define SET_TX_DESC_OWN(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 31, 1, __Value)
+
+#define SET_TX_DESC_MACID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 0, 5, __Value)
+#define SET_TX_DESC_MORE_DATA(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 5, 1, __Value)
+#define SET_TX_DESC_MORE_FRAG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 6, 1, __Value)
+#define SET_TX_DESC_PIFS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 7, 1, __Value)
+#define SET_TX_DESC_QUEUE_SEL(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 8, 5, __Value)
+#define SET_TX_DESC_ACK_POLICY(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 13, 2, __Value)
+#define SET_TX_DESC_NO_ACM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 15, 1, __Value)
+#define SET_TX_DESC_NON_QOS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 16, 1, __Value)
+#define SET_TX_DESC_KEY_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 17, 2, __Value)
+#define SET_TX_DESC_OUI(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 19, 1, __Value)
+#define SET_TX_DESC_PKT_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 20, 1, __Value)
+#define SET_TX_DESC_EN_DESC_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 21, 1, __Value)
+#define SET_TX_DESC_SEC_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 22, 2, __Value)
+#define SET_TX_DESC_WDS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 24, 1, __Value)
+#define SET_TX_DESC_HTC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 25, 1, __Value)
+#define SET_TX_DESC_PKT_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 26, 5, __Value)
+#define SET_TX_DESC_HWPC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 27, 1, __Value)
+
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 0, 6, __Value)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 6, 1, __Value)
+#define SET_TX_DESC_TSFL(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 7, 5, __Value)
+#define SET_TX_DESC_RTS_RETRY_COUNT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 12, 6, __Value)
+#define SET_TX_DESC_DATA_RETRY_COUNT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 18, 6, __Value)
+#define	SET_TX_DESC_RSVD_MACID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(((__pTxDesc) + 8), 24, 5, __Value)
+#define SET_TX_DESC_AGG_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 29, 1, __Value)
+#define SET_TX_DESC_AGG_BREAK(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 30, 1, __Value)
+#define SET_TX_DESC_OWN_MAC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 31, 1, __Value)
+
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 0, 8, __Value)
+#define SET_TX_DESC_TAIL_PAGE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 8, 8, __Value)
+#define SET_TX_DESC_SEQ(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 16, 12, __Value)
+#define SET_TX_DESC_FRAG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 28, 4, __Value)
+
+#define SET_TX_DESC_RTS_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 0, 6, __Value)
+#define SET_TX_DESC_DISABLE_RTS_FB(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 6, 1, __Value)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 7, 4, __Value)
+#define SET_TX_DESC_CTS_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 11, 1, __Value)
+#define SET_TX_DESC_RTS_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 12, 1, __Value)
+#define SET_TX_DESC_RA_BRSR_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 13, 3, __Value)
+#define SET_TX_DESC_TXHT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 16, 1, __Value)
+#define SET_TX_DESC_TX_SHORT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 17, 1, __Value)
+#define SET_TX_DESC_TX_BANDWIDTH(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 18, 1, __Value)
+#define SET_TX_DESC_TX_SUB_CARRIER(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 19, 2, __Value)
+#define SET_TX_DESC_TX_STBC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 21, 2, __Value)
+#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 23, 1, __Value)
+#define SET_TX_DESC_RTS_HT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 24, 1, __Value)
+#define SET_TX_DESC_RTS_SHORT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 25, 1, __Value)
+#define SET_TX_DESC_RTS_BANDWIDTH(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 26, 1, __Value)
+#define SET_TX_DESC_RTS_SUB_CARRIER(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 27, 2, __Value)
+#define SET_TX_DESC_RTS_STBC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 29, 2, __Value)
+#define SET_TX_DESC_USER_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 31, 1, __Value)
+
+#define SET_TX_DESC_PACKET_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 0, 9, __Value)
+#define SET_TX_DESC_TX_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 9, 6, __Value)
+#define SET_TX_DESC_DISABLE_FB(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 15, 1, __Value)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 16, 5, __Value)
+#define SET_TX_DESC_TX_AGC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 21, 11, __Value)
+
+#define SET_TX_DESC_IP_CHECK_SUM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+24, 0, 16, __Value)
+#define SET_TX_DESC_TCP_CHECK_SUM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+24, 16, 16, __Value)
+
+#define SET_TX_DESC_TX_BUFFER_SIZE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 0, 16, __Value)
+#define SET_TX_DESC_IP_HEADER_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 16, 8, __Value)
+#define SET_TX_DESC_TCP_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 31, 1, __Value)
+
+#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+32, 0, 32, __Value)
+
+
+#define	TX_DESC_NEXT_DESC_OFFSET	36
+#define	CLEAR_PCI_TX_DESC_CONTENT(__pTxDesc, _size)											\
+	{																						\
+		if(_size > TX_DESC_NEXT_DESC_OFFSET)												\
+			memset((void*)__pTxDesc, 0, TX_DESC_NEXT_DESC_OFFSET);					\
+		else																				\
+			memset((void*)__pTxDesc, 0, _size);									\
+		if(_size > (TX_DESC_NEXT_DESC_OFFSET + 4))											\
+			memset((void*)(__pTxDesc + (TX_DESC_NEXT_DESC_OFFSET + 4)), 0, (_size - TX_DESC_NEXT_DESC_OFFSET));	\
+	}
+
+#define	C2H_RX_CMD_HDR_LEN		8 
+#define	GET_C2H_CMD_CMD_LEN(__pRxHeader)	LE_BITS_TO_4BYTE((__pRxHeader), 0, 16)
+#define	GET_C2H_CMD_ELEMENT_ID(__pRxHeader)	LE_BITS_TO_4BYTE((__pRxHeader), 16, 8)
+#define	GET_C2H_CMD_CMD_SEQ(__pRxHeader)	LE_BITS_TO_4BYTE((__pRxHeader), 24, 7)
+#define	GET_C2H_CMD_CONTINUE(__pRxHeader)	LE_BITS_TO_4BYTE((__pRxHeader), 31, 1)
+#define	GET_C2H_CMD_CONTENT(__pRxHeader)	((u8*)(__pRxHeader) + C2H_RX_CMD_HDR_LEN)
+
+#define	GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pCmdFBHeader)	LE_BITS_TO_4BYTE((__pCmdFBHeader), 0, 8)
+#define	GET_C2H_CMD_FEEDBACK_CCX_LEN(__pCmdFBHeader)	LE_BITS_TO_4BYTE((__pCmdFBHeader), 8, 8)
+#define	GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pCmdFBHeader)	LE_BITS_TO_4BYTE((__pCmdFBHeader), 16, 16)
+#define	GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 0, 5)
+#define	GET_C2H_CMD_FEEDBACK_CCX_VALID(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 7, 1)
+#define	GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 8, 5)
+#define	GET_C2H_CMD_FEEDBACK_CCX_TOK(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 15, 1)
+#define	GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 16, 4)
+#define	GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pCmdFBHeader)	LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 20, 12)
+
+
+#if 0
+#define BK_QUEUE					0		
+#define BE_QUEUE					1		
+#define VI_QUEUE					2		
+#define VO_QUEUE				3	
+#define BEACON_QUEUE			4
+#define TXCMD_QUEUE				5		
+#define MGNT_QUEUE				6	
+#define HIGH_QUEUE				7	
+#define HCCA_QUEUE				8	
+
+#define LOW_QUEUE				BE_QUEUE
+#define NORMAL_QUEUE			MGNT_QUEUE
+#endif
+
+#define RX_MPDU_QUEUE			0
+#define RX_CMD_QUEUE			1
+#define RX_MAX_QUEUE			2
+
+
+typedef enum _rtl819x_loopback{
+	RTL819X_NO_LOOPBACK = 0,
+	RTL819X_MAC_LOOPBACK = 1,
+	RTL819X_DMA_LOOPBACK = 2,
+	RTL819X_CCK_LOOPBACK = 3,
+}rtl819x_loopback_e;
+
+#define RESET_DELAY_8185		20
+
+#define RT_IBSS_INT_MASKS		0
+
+#define DESC92S_RATE1M			0x00
+#define DESC92S_RATE2M			0x01
+#define DESC92S_RATE5_5M		0x02
+#define DESC92S_RATE11M			0x03
+#define DESC92S_RATE6M			0x04
+#define DESC92S_RATE9M			0x05
+#define DESC92S_RATE12M			0x06
+#define DESC92S_RATE18M			0x07
+#define DESC92S_RATE24M			0x08
+#define DESC92S_RATE36M			0x09
+#define DESC92S_RATE48M			0x0a
+#define DESC92S_RATE54M			0x0b
+#define DESC92S_RATEMCS0		0x0c
+#define DESC92S_RATEMCS1		0x0d
+#define DESC92S_RATEMCS2		0x0e
+#define DESC92S_RATEMCS3		0x0f
+#define DESC92S_RATEMCS4		0x10
+#define DESC92S_RATEMCS5		0x11
+#define DESC92S_RATEMCS6		0x12
+#define DESC92S_RATEMCS7		0x13
+#define DESC92S_RATEMCS8		0x14
+#define DESC92S_RATEMCS9		0x15
+#define DESC92S_RATEMCS10		0x16
+#define DESC92S_RATEMCS11		0x17
+#define DESC92S_RATEMCS12		0x18
+#define DESC92S_RATEMCS13		0x19
+#define DESC92S_RATEMCS14		0x1a
+#define DESC92S_RATEMCS15		0x1b
+#define DESC92S_RATEMCS15_SG	0x1c
+#define DESC92S_RATEMCS32		0x20	
+
+#define SHORT_SLOT_TIME			9
+#define NON_SHORT_SLOT_TIME	20
+
+
+#define	MAX_LINES_HWCONFIG_TXT			1000
+#define MAX_BYTES_LINE_HWCONFIG_TXT		256
+
+#define SW_THREE_WIRE			0
+#define HW_THREE_WIRE			2
+
+#define BT_DEMO_BOARD			0 
+#define BT_QA_BOARD				1 
+#define BT_FPGA					2 
+
+#define	Rx_Smooth_Factor			20
+
+#define QSLT_BK					0x2
+#define QSLT_BE					0x0
+#define QSLT_VI					0x5
+#define QSLT_VO					0x7
+#define QSLT_BEACON				0x10
+#define QSLT_HIGH				0x11
+#define QSLT_MGNT				0x12
+#define QSLT_CMD				0x13
+
+#define NUM_OF_FIRMWARE_QUEUE				10
+#define NUM_OF_PAGES_IN_FW					0x100
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK		0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE		0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI		0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO		0x07
+#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA		0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_CMD		0x0
+#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT		0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH		0x02
+#define NUM_OF_PAGE_IN_FW_QUEUE_BCN		0x2
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB		0xA1
+
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM	0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM	0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM	0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM	0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM	0x00
+                                        	
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE	0
+#define HAL_PRIME_CHNL_OFFSET_LOWER		1
+#define HAL_PRIME_CHNL_OFFSET_UPPER		2
+
+
+
+#define 	MAX_SILENT_RESET_RX_SLOT_NUM	10
+typedef enum tag_Rf_OpType
+{    
+    RF_OP_By_SW_3wire = 0,
+    RF_OP_By_FW,   
+    RF_OP_MAX
+}RF_OpType_E;
+
+
+typedef	enum _POWER_SAVE_MODE	
+{
+	POWER_SAVE_MODE_ACTIVE,
+	POWER_SAVE_MODE_SAVE,
+}POWER_SAVE_MODE;
+
+typedef	enum _INTERFACE_SELECT_8190PCI{
+	INTF_SEL1_MINICARD	= 0,		
+	INTF_SEL0_PCIE			= 1,		
+	INTF_SEL2_RSV			= 2,		
+	INTF_SEL3_RSV			= 3,		
+} INTERFACE_SELECT_8190PCI, *PINTERFACE_SELECT_8190PCI;
+
+
+typedef struct _BB_REGISTER_DEFINITION{
+	u32 rfintfs; 			
+	u32 rfintfi; 			
+	u32 rfintfo; 			
+	u32 rfintfe; 			
+	u32 rf3wireOffset; 		
+	u32 rfLSSI_Select; 		
+	u32 rfTxGainStage;		
+	u32 rfHSSIPara1; 		
+	u32 rfHSSIPara2; 		
+	u32 rfSwitchControl; 	
+	u32 rfAGCControl1; 	
+	u32 rfAGCControl2; 	
+	u32 rfRxIQImbalance; 	
+	u32 rfRxAFE;  			
+	u32 rfTxIQImbalance; 	
+	u32 rfTxAFE; 			
+	u32 rfLSSIReadBack; 	
+	u32 rfLSSIReadBackPi; 	
+}BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T;
+
+
+
+
+typedef struct  _rx_fwinfo_8192s{
+	
+	/*u32			gain_0:7;
+	u32			trsw_0:1;
+	u32			gain_1:7;
+	u32			trsw_1:1;
+	u32			gain_2:7;
+	u32			trsw_2:1;
+	u32			gain_3:7;
+	u32			trsw_3:1;	*/
+	u8			gain_trsw[4];
+
+	/*u32			pwdb_all:8;
+	u32			cfosho_0:8;
+	u32			cfosho_1:8;
+	u32			cfosho_2:8;*/
+	u8			pwdb_all;
+	u8			cfosho[4];
+
+	/*u32			cfosho_3:8;
+	u32			cfotail_0:8;
+	u32			cfotail_1:8;
+	u32			cfotail_2:8;*/
+	u8			cfotail[4];
+
+	/*u32			cfotail_3:8;
+	u32			rxevm_0:8;
+	u32			rxevm_1:8;
+	u32			rxsnr_0:8;*/
+	s8			rxevm[2];
+	s8			rxsnr[4];
+
+	/*u32			rxsnr_1:8;
+	u32			rxsnr_2:8;
+	u32			rxsnr_3:8;
+	u32			pdsnr_0:8;*/
+	u8			pdsnr[2];
+
+	/*u32			pdsnr_1:8;
+	u32			csi_current_0:8;
+	u32			csi_current_1:8;
+	u32			csi_target_0:8;*/
+	u8			csi_current[2];
+	u8			csi_target[2];
+
+	/*u32			csi_target_1:8;
+	u32			sigevm:8;
+	u32			max_ex_pwr:8;
+	u32			ex_intf_flag:1;
+	u32			sgi_en:1;
+	u32			rxsc:2;
+	u32			reserve:4;*/
+	u8			sigevm;
+	u8			max_ex_pwr;
+	u8			ex_intf_flag:1;
+	u8			sgi_en:1;
+	u8			rxsc:2;
+	u8			reserve:4;
+	
+}rx_fwinfo, *prx_fwinfo;
+
+typedef struct _LOG_INTERRUPT_8190
+{
+	u32	nIMR_COMDOK;
+	u32	nIMR_MGNTDOK;
+	u32	nIMR_HIGH;
+	u32	nIMR_VODOK;
+	u32	nIMR_VIDOK;
+	u32	nIMR_BEDOK;
+	u32	nIMR_BKDOK;
+	u32	nIMR_ROK;
+	u32	nIMR_RCOK;
+	u32	nIMR_TBDOK;
+	u32	nIMR_BDOK;
+	u32	nIMR_RXFOVW;
+} LOG_INTERRUPT_8190_T, *PLOG_INTERRUPT_8190_T;
+
+typedef struct _phy_cck_rx_status_report_819xpci
+{
+	u8	adc_pwdb_X[4];
+	u8	sq_rpt; 
+	u8	cck_agc_rpt;
+}phy_sts_cck_819xpci_t, phy_sts_cck_8192s_t;
+
+#define		PHY_RSSI_SLID_WIN_MAX				100
+#define		PHY_LINKQUALITY_SLID_WIN_MAX		20
+#define		PHY_Beacon_RSSI_SLID_WIN_MAX		10
+
+typedef struct _tx_desc_8192se{
+
+	u32		PktSize:16;
+	u32		Offset:8;
+	u32		Type:2;	
+	u32		LastSeg:1;
+	u32		FirstSeg:1;
+	u32		LINIP:1;
+	u32		AMSDU:1;
+	u32		GF:1;
+	u32		OWN:1;	
+	
+	u32		MacID:5;			
+	u32		MoreData:1;
+	u32		MoreFrag:1;
+	u32		PIFS:1;
+	u32		QueueSel:5;
+	u32		AckPolicy:2;
+	u32		NoACM:1;
+	u32		NonQos:1;
+	u32		KeyID:2;
+	u32		OUI:1;
+	u32		PktType:1;
+	u32		EnDescID:1;
+	u32		SecType:2;
+	u32		HTC:1;	
+	u32		WDS:1;	
+	u32		PktOffset:5;	
+	u32		HWPC:1;		
+	
+	u32		DataRetryLmt:6;
+	u32		RetryLmtEn:1;
+	u32		TSFL:5;	
+	u32		RTSRC:6;	
+	u32		DATARC:6;	
+	u32		Rsvd_MacID:5;
+	u32		AggEn:1;
+	u32		BK:1;	
+	u32		OwnMAC:1;
+	
+	u32		NextHeadPage:8;
+	u32		TailPage:8;
+	u32		Seq:12;
+	u32		Frag:4;	
+
+	u32		RTSRate:6;
+	u32		DisRTSFB:1;
+	u32		RTSRateFBLmt:4;
+	u32		CTS2Self:1;
+	u32		RTSEn:1;
+	u32		RaBRSRID:3;	
+	u32		TXHT:1;
+	u32		TxShort:1;
+	u32		TxBw:1;
+	u32		TXSC:2;
+	u32		STBC:2;
+	u32		RD:1;
+	u32		RTSHT:1;
+	u32		RTSShort:1;
+	u32		RTSBW:1;
+	u32		RTSSC:2;
+	u32		RTSSTBC:2;
+	u32		UserRate:1;	
+
+	u32		PktID:9;
+	u32		TxRate:6;
+	u32		DISFB:1;
+	u32		DataRateFBLmt:5;
+	u32		TxAGC:11;
+
+	u32		IPChkSum:16;
+	u32		TCPChkSum:16;
+
+	u32		TxBufferSize:16;
+	u32		IPHdrOffset:8;
+	u32		Rsvd3:7;
+	u32		TCPEn:1;
+
+	u32		TxBuffAddr;
+
+	u32		NextDescAddress;
+
+	u32		Reserve_Pass_92S_PCIE_MM_Limit[6];
+	
+} tx_desc, *ptx_desc;
+
+
+typedef struct _tx_desc_cmd_8192se{  
+	u32		PktSize:16;
+	u32		Offset:8;	
+	u32		Rsvd0:2;
+	u32		FirstSeg:1;
+	u32		LastSeg:1;
+	u32		LINIP:1;
+	u32		Rsvd1:2;
+	u32		OWN:1;	
+	
+	u32		Rsvd2;
+	u32		Rsvd3;
+	u32		Rsvd4;
+	u32		Rsvd5;
+	u32		Rsvd6;
+	u32		Rsvd7;	
+
+	u32		TxBufferSize:16;
+	u32		Rsvd8:16;
+
+	u32		TxBufferAddr;
+
+	u32		NextTxDescAddress;
+
+	u32		Reserve_Pass_92S_PCIE_MM_Limit[6];
+	
+}tx_desc_cmd, *ptx_desc_cmd;
+
+
+typedef struct _tx_status_desc_8192se{ 
+
+	u32		PktSize:16;
+	u32		Offset:8;
+	u32		Type:2;	
+	u32		LastSeg:1;
+	u32		FirstSeg:1;
+	u32		LINIP:1;
+	u32		AMSDU:1;
+	u32		GF:1;
+	u32		OWN:1;	
+	
+	u32		MacID:5;			
+	u32		MoreData:1;
+	u32		MoreFrag:1;
+	u32		PIFS:1;
+	u32		QueueSel:5;
+	u32		AckPolicy:2;
+	u32		NoACM:1;
+	u32		NonQos:1;
+	u32		KeyID:2;
+	u32		OUI:1;
+	u32		PktType:1;
+	u32		EnDescID:1;
+	u32		SecType:2;
+	u32		HTC:1;	
+	u32		WDS:1;	
+	u32		PktOffset:5;	
+	u32		HWPC:1;		
+	
+	u32		DataRetryLmt:6;
+	u32		RetryLmtEn:1;
+	u32		TSFL:5;	
+	u32		RTSRC:6;	
+	u32		DATARC:6;	
+	u32		Rsvd1:5;
+	u32		AggEn:1;
+	u32		BK:1;	
+	u32		OwnMAC:1;
+	
+	u32		NextHeadPage:8;
+	u32		TailPage:8;
+	u32		Seq:12;
+	u32		Frag:4;	
+
+	u32		RTSRate:6;
+	u32		DisRTSFB:1;
+	u32		RTSRateFBLmt:4;
+	u32		CTS2Self:1;
+	u32		RTSEn:1;
+	u32		RaBRSRID:3;	
+	u32		TXHT:1;
+	u32		TxShort:1;
+	u32		TxBw:1;
+	u32		TXSC:2;
+	u32		STBC:2;
+	u32		RD:1;
+	u32		RTSHT:1;
+	u32		RTSShort:1;
+	u32		RTSBW:1;
+	u32		RTSSC:2;
+	u32		RTSSTBC:2;
+	u32		UserRate:1;	
+
+	u32		PktID:9;
+	u32		TxRate:6;
+	u32		DISFB:1;
+	u32		DataRateFBLmt:5;
+	u32		TxAGC:11;	
+
+	u32		IPChkSum:16;
+	u32		TCPChkSum:16;
+
+	u32		TxBufferSize:16;
+	u32		IPHdrOffset:8;
+	u32		Rsvd2:7;
+	u32		TCPEn:1;
+
+	u32		TxBufferAddr;
+
+	u32		NextDescAddress;
+
+	u32		Reserve_Pass_92S_PCIE_MM_Limit[6];
+
+}tx_status_desc, *ptx_status_desc;
+
+
+typedef struct _rx_desc_8192se{
+	u32		Length:14;
+	u32		CRC32:1;
+	u32		ICVError:1;
+	u32		DrvInfoSize:4;
+	u32		Security:3;
+	u32		Qos:1;
+	u32		Shift:2;
+	u32		PHYStatus:1;
+	u32		SWDec:1;
+	u32		LastSeg:1;
+	u32		FirstSeg:1;
+	u32		EOR:1;
+	u32		OWN:1;	
+
+	u32		MACID:5;
+	u32		TID:4;
+	u32		HwRsvd:5;
+	u32		PAGGR:1;
+	u32		FAGGR:1;
+	u32		A1_FIT:4;
+	u32		A2_FIT:4;
+	u32		PAM:1;
+	u32		PWR:1;
+	u32		MoreData:1;
+	u32		MoreFrag:1;
+	u32		Type:2;
+	u32		MC:1;
+	u32		BC:1;
+
+	u32		Seq:12;
+	u32		Frag:4;
+	u32		NextPktLen:14;
+	u32		NextIND:1;
+	u32		Rsvd:1;
+
+	u32		RxMCS:6;
+	u32		RxHT:1;
+	u32		AMSDU:1;
+	u32		SPLCP:1;
+	u32		BandWidth:1;
+	u32		HTC:1;
+	u32		TCPChkRpt:1;
+	u32		IPChkRpt:1;
+	u32		TCPChkValID:1;
+	u32		HwPCErr:1;
+	u32		HwPCInd:1;
+	u32		IV0:16;
+
+	u32		IV1;
+
+	u32		TSFL;
+
+	u32		BufferAddress;
+
+	u32		NextRxDescAddress;
+
+#if 0		
+	u32		BA_SSN:12;
+	u32		BA_VLD:1;
+	u32		RSVD:19;
+#endif
+
+} rx_desc, *prx_desc;
+
+
+
+typedef struct _rx_desc_status_8192se{
+	u32		Length:14;
+	u32		CRC32:1;
+	u32		ICVError:1;
+	u32		DrvInfoSize:4;
+	u32		Security:3;
+	u32		Qos:1;
+	u32		Shift:2;
+	u32		PHYStatus:1;
+	u32		SWDec:1;
+	u32		LastSeg:1;
+	u32		FirstSeg:1;
+	u32		EOR:1;
+	u32		OWN:1;	
+
+	u32		MACID:5;
+	u32		TID:4;
+	u32		HwRsvd:5;
+	u32		PAGGR:1;
+	u32		FAGGR:1;
+	u32		A1_FIT:4;
+	u32		A2_FIT:4;
+	u32		PAM:1;
+	u32		PWR:1;
+	u32		MoreData:1;
+	u32		MoreFrag:1;
+	u32		Type:2;
+	u32		MC:1;
+	u32		BC:1;
+
+	u32		Seq:12;
+	u32		Frag:4;
+	u32		NextPktLen:14;
+	u32		NextIND:1;
+	u32		Rsvd:1;
+
+	u32		RxMCS:6;
+	u32		RxHT:1;
+	u32		AMSDU:1;
+	u32		SPLCP:1;
+	u32		BW:1;
+	u32		HTC:1;
+	u32		TCPChkRpt:1;
+	u32		IPChkRpt:1;
+	u32		TCPChkValID:1;
+	u32		HwPCErr:1;
+	u32		HwPCInd:1;
+	u32		IV0:16;
+
+	u32		IV1;
+
+	u32		TSFL;
+
+
+	u32		BufferAddress;
+
+	u32		NextRxDescAddress;
+
+#if 0		
+	u32		BA_SSN:12;
+	u32		BA_VLD:1;
+	u32		RSVD:19;
+#endif
+}rx_desc_status, *prx_desc_status;
+
+typedef enum _HAL_FW_C2H_CMD_ID
+{
+	HAL_FW_C2H_CMD_Read_MACREG = 0,
+	HAL_FW_C2H_CMD_Read_BBREG = 1,
+	HAL_FW_C2H_CMD_Read_RFREG = 2,
+	HAL_FW_C2H_CMD_Read_EEPROM = 3,
+	HAL_FW_C2H_CMD_Read_EFUSE = 4,
+	HAL_FW_C2H_CMD_Read_CAM = 5,
+	HAL_FW_C2H_CMD_Get_BasicRate = 6,			
+	HAL_FW_C2H_CMD_Get_DataRate = 7,				
+	HAL_FW_C2H_CMD_Survey = 8 ,
+	HAL_FW_C2H_CMD_SurveyDone = 9,
+	HAL_FW_C2H_CMD_JoinBss = 10,
+	HAL_FW_C2H_CMD_AddSTA = 11,
+	HAL_FW_C2H_CMD_DelSTA = 12,
+	HAL_FW_C2H_CMD_AtimDone = 13,
+	HAL_FW_C2H_CMD_TX_Report = 14,
+	HAL_FW_C2H_CMD_CCX_Report = 15,
+	HAL_FW_C2H_CMD_DTM_Report = 16,
+	HAL_FW_C2H_CMD_TX_Rate_Statistics = 17,
+	HAL_FW_C2H_CMD_C2HLBK = 18,
+	HAL_FW_C2H_CMD_C2HDBG = 19,
+	HAL_FW_C2H_CMD_C2HFEEDBACK = 20,
+	HAL_FW_C2H_CMD_BT_State = 25,
+	HAL_FW_C2H_CMD_BT_Service = 26,
+	HAL_FW_C2H_CMD_MAX
+}HAL_FW_C2H_CMD_ID;
+
+#define	HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT			0x04
+#define	HAL_FW_C2H_CMD_C2HFEEDBACK_DTM_TX_STATISTICS_RPT	0x05
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.c
@@ -0,0 +1,974 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifdef RTL8192SE
+#include "../rtl_core.h"
+#include "../rtl_dm.h"
+#include "r8192S_phyreg.h"
+#include "r8192S_phy.h"
+#include "r8192S_rtl6052.h"
+
+/*---------------------------Define Local Constant---------------------------*/
+typedef struct RF_Shadow_Compare_Map {
+	u32		Value;
+	u8		Compare;
+	u8		ErrorOrNot;
+	u8		Recorver;
+	u8		Driver_Write;
+}RF_SHADOW_T;
+/*---------------------------Define Local Constant---------------------------*/
+
+
+/*------------------------Define global variable-----------------------------*/
+/*------------------------Define global variable-----------------------------*/
+
+
+
+
+/*---------------------Define local function prototype-----------------------*/
+void phy_RF6052_Config_HardCode(struct net_device* dev);
+
+bool phy_RF6052_Config_ParaFile(struct net_device* dev);
+/*---------------------Define local function prototype-----------------------*/
+
+/*------------------------Define function prototype--------------------------*/
+extern void RF_ChangeTxPath(struct net_device* dev,  u16 DataRate);
+
+/*------------------------Define function prototype--------------------------*/
+
+/*------------------------Define local variable------------------------------*/
+static	RF_SHADOW_T	RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG];
+/*------------------------Define local variable------------------------------*/
+
+/*------------------------Define function prototype--------------------------*/
+extern void RF_ChangeTxPath(struct net_device* dev,  u16 DataRate)
+{
+#if 0
+	static	u1Byte	RF_Path_Type = 2;	
+	static	u4Byte	tx_gain_tbl1[6] 
+			= {0x17f50, 0x11f40, 0x0cf30, 0x08720, 0x04310, 0x00100};
+	static	u4Byte	tx_gain_tbl2[6] 
+			= {0x15ea0, 0x10e90, 0x0c680, 0x08250, 0x04040, 0x00030};
+	u1Byte	i;
+	
+	if (RF_Path_Type == 2 && (DataRate&0xF) <= 0x7)
+	{
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G2, bMask20Bits, 0x0f000);
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G3, bMask20Bits, 0xeacf1);
+
+		for (i = 0; i < 6; i++)					
+			PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+						RF_TX_AGC, bMask20Bits, tx_gain_tbl1[i]);
+
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G2, bMask20Bits, 0x01e39);
+	}
+	else if (RF_Path_Type == 1 && (DataRate&0xF) >= 0x8)
+	{
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G2, bMask20Bits, 0x04440);
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G3, bMask20Bits, 0xea4f1);
+
+		for (i = 0; i < 6; i++)
+			PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+						RF_TX_AGC, bMask20Bits, tx_gain_tbl2[i]);
+
+		PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, 
+					RF_TXPA_G2, bMask20Bits, 0x01e19);
+	}
+#endif	
+	
+}	/* RF_ChangeTxPath */
+
+
+void PHY_RF6052SetBandwidth(struct net_device* dev, HT_CHANNEL_WIDTH Bandwidth)	
+{	
+	u8				eRFPath;	
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	
+
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+	{		
+#if (RTL92SE_FPGA_VERIFY == 0)
+		switch(Bandwidth)
+		{
+			case HT_CHANNEL_WIDTH_20:
+#if 1
+				priv->RfRegChnlVal[0] = ((priv->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400);
+				rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_CHNLBW, bRFRegOffsetMask, priv->RfRegChnlVal[0]);
+#else
+				rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, RF_CHNLBW, BIT10|BIT11, 0x01);
+#endif
+				break;
+			case HT_CHANNEL_WIDTH_20_40:
+#if 1
+				priv->RfRegChnlVal[0] = ((priv->RfRegChnlVal[0] & 0xfffff3ff));
+				rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_CHNLBW, bRFRegOffsetMask, priv->RfRegChnlVal[0]);
+#else
+				rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, RF_CHNLBW, BIT10|BIT11, 0x00);
+#endif
+				break;
+			default:
+				RT_TRACE(COMP_DBG, "PHY_SetRF6052Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth);
+				break;			
+		}
+#endif	
+	}
+	else
+	{
+		for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+		{
+			switch(Bandwidth)
+			{
+				case HT_CHANNEL_WIDTH_20:
+					break;
+				case HT_CHANNEL_WIDTH_20_40:
+					break;
+				default:
+					RT_TRACE(COMP_DBG, "PHY_SetRF8225Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth );
+					break;
+					
+			}
+		}
+	}
+}
+
+
+extern void PHY_RF6052SetCckTxPower(struct net_device* dev, u8	powerlevel)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32				TxAGC=0;
+	bool				dontIncCCKOrTurboScanOff=false;
+
+	if (((priv->eeprom_version >= 2) && (priv->TxPwrSafetyFlag == 1)) ||
+	     ((priv->eeprom_version >= 2) && (priv->EEPROMRegulatory != 0))) {
+		dontIncCCKOrTurboScanOff = true;
+	}
+
+	if(rtllib_act_scanning(priv->rtllib,true) == true){
+		TxAGC = 0x3f;
+
+		if(dontIncCCKOrTurboScanOff )
+			TxAGC = powerlevel;
+	} else {
+		TxAGC = powerlevel;
+
+		if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
+			TxAGC = 0x10;
+		else if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
+			TxAGC = 0x0;
+	}
+	
+	if(TxAGC > RF6052_MAX_TX_PWR)
+		TxAGC = RF6052_MAX_TX_PWR;
+
+	rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
+
+}	/* PHY_RF6052SetCckTxPower */
+
+
+#if 0
+extern void PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8 powerlevel, u8 Channel)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 	writeVal, powerBase0, powerBase1;
+	u8 	index = 0;
+	u16 	RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
+	u8	rfa_pwr[4];
+	u8 	rfa_lower_bound = 0, rfa_upper_bound = 0;
+	u8	i;
+	u8	rf_pwr_diff = 0, chnlGroup = 0;
+	u8	Legacy_pwrdiff=0, HT20_pwrdiff=0;
+
+	if (priv->eeprom_version < 2)
+		powerBase0 = powerlevel + (priv->LegacyHTTxPowerDiff & 0xf); 
+	else if (priv->eeprom_version >= 2)	
+	{
+		Legacy_pwrdiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][Channel-1];
+		powerBase0 = powerlevel + Legacy_pwrdiff; 
+		RT_TRACE(COMP_POWER, " [LagacyToHT40 pwr diff = %d]\n", Legacy_pwrdiff);		
+		RT_TRACE(COMP_POWER, " [OFDM power base index = 0x%x]\n", powerBase0);
+	}
+	powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
+	
+	if(priv->eeprom_version >= 2)
+	{	
+	
+		if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+		{
+			HT20_pwrdiff = priv->TxPwrHt20Diff[RF90_PATH_A][Channel-1];
+
+			if (HT20_pwrdiff < 8)	
+				powerlevel += HT20_pwrdiff;	
+			else				
+				powerlevel -= (16-HT20_pwrdiff);
+
+			RT_TRACE(COMP_POWER, " [HT20 to HT40 pwrdiff = %d]\n", HT20_pwrdiff);
+			RT_TRACE(COMP_POWER, " [MCS power base index = 0x%x]\n", powerlevel);
+		}
+	}
+	powerBase1 = powerlevel;							
+	powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
+
+	RT_TRACE(COMP_POWER, " [Legacy/HT power index= %x/%x]\n", powerBase0, powerBase1);
+	
+	for(index=0; index<6; index++)
+	{
+
+		if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+		{
+			writeVal = ((index<2)?powerBase0:powerBase1);
+		}
+		else
+		{
+			if(priv->pwrGroupCnt == 0)
+				chnlGroup = 0;
+			if(priv->pwrGroupCnt >= 3)
+			{
+				if(Channel <= 3)
+					chnlGroup = 0;
+				else if(Channel >= 4 && Channel <= 9)
+					chnlGroup = 1;
+				else if(Channel >= 10)
+					chnlGroup = 2;
+				if(priv->pwrGroupCnt == 4)
+					chnlGroup ++;
+			}
+		else
+				chnlGroup = 0;
+			writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + 
+					((index<2)?powerBase0:powerBase1);
+		}
+		RT_TRACE(COMP_POWER, "Reg 0x%x, chnlGroup = %d, Original=%x writeVal=%x\n", 
+			RegOffset[index], chnlGroup, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index], 
+			writeVal);
+
+		if (priv->rf_type == RF_2T2R)
+		{			
+			rf_pwr_diff = priv->AntennaTxPwDiff[0];
+			RT_TRACE(COMP_POWER, "2T2R RF-B to RF-A PWR DIFF=%d\n", rf_pwr_diff);
+
+			if (rf_pwr_diff >= 8)		
+			{	
+				rfa_lower_bound = 0x10-rf_pwr_diff;
+				RT_TRACE(COMP_POWER, "rfa_lower_bound= %d\n", rfa_lower_bound);
+			}
+			else if (rf_pwr_diff >= 0)	
+			{
+				rfa_upper_bound = RF6052_MAX_TX_PWR-rf_pwr_diff;
+				RT_TRACE(COMP_POWER, "rfa_upper_bound= %d\n", rfa_upper_bound);
+			}			
+		}
+
+		for (i=  0; i <4; i++)
+		{
+			rfa_pwr[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8));
+			if (rfa_pwr[i]  > RF6052_MAX_TX_PWR)
+				rfa_pwr[i]  = RF6052_MAX_TX_PWR;
+
+			if (priv->rf_type == RF_2T2R)
+			{
+				if (rf_pwr_diff >= 8)		
+				{	
+					if (rfa_pwr[i] <rfa_lower_bound)
+					{
+						RT_TRACE(COMP_POWER, "Underflow");
+						rfa_pwr[i] = rfa_lower_bound;
+					}
+				}
+				else if (rf_pwr_diff >= 1)	
+				{	
+					if (rfa_pwr[i] > rfa_upper_bound)
+					{
+						RT_TRACE(COMP_POWER, "Overflow");
+						rfa_pwr[i] = rfa_upper_bound;
+					}
+				}
+				RT_TRACE(COMP_POWER, "rfa_pwr[%d]=%x\n", i, rfa_pwr[i]);
+			}
+
+		}
+
+#if 1
+		writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0];
+		RT_TRACE(COMP_POWER, "WritePower=%08x\n", writeVal);
+#else
+		if(priv->bDynamicTxHighPower == true)     
+		{	
+			if(index > 1)	
+			{
+				writeVal = 0x03030303;
+			}
+			else
+			{
+				writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0];
+			}
+			RT_TRACE(COMP_POWER, "HighPower=%08x\n", writeVal);
+		}
+		else
+		{
+			writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0];
+			RT_TRACE(COMP_POWER, "NormalPower=%08x\n", writeVal);
+		}
+#endif
+		rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+	}
+
+}	/* PHY_RF6052SetOFDMTxPower */
+#endif
+
+void getPowerBase(
+	struct net_device* dev,
+	u8*		pPowerLevel,
+	u8		Channel,
+	u32*	OfdmBase,
+	u32*	MCSBase,
+	u8*		pFinalPowerIndex
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32			powerBase0, powerBase1;
+	u8			Legacy_pwrdiff=0, HT20_pwrdiff=0;
+	u8			i, powerlevel[4];
+	
+	for(i=0; i<2; i++)
+		powerlevel[i] = pPowerLevel[i];
+	if (priv->eeprom_version < 2)
+		powerBase0 = powerlevel[0] + (priv->LegacyHTTxPowerDiff & 0xf); 
+	else if (priv->eeprom_version >= 2)
+	{
+		Legacy_pwrdiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][Channel-1];
+		powerBase0 = powerlevel[0] + Legacy_pwrdiff; 
+	}
+	powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
+	*OfdmBase = powerBase0;
+	RT_TRACE(COMP_POWER, " [OFDM power base index = 0x%x]\n", powerBase0);
+	
+	if(priv->eeprom_version >= 2)
+	{
+		if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+		{
+			for(i=0; i<2; i++)	
+			{	
+				HT20_pwrdiff = priv->TxPwrHt20Diff[i][Channel-1];
+				if (HT20_pwrdiff < 8)	
+					powerlevel[i] += HT20_pwrdiff;	
+				else				
+					powerlevel[i] -= (16-HT20_pwrdiff);
+			}
+		}
+	}
+	powerBase1 = powerlevel[0];	
+	powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
+	*MCSBase = powerBase1;
+	
+	RT_TRACE(COMP_POWER, " [MCS power base index = 0x%x]\n", powerBase1);
+
+	pFinalPowerIndex[0] = powerlevel[0];
+	pFinalPowerIndex[1] = powerlevel[1];
+	switch(priv->EEPROMRegulatory)
+	{
+		case 3:
+			if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+			{
+				pFinalPowerIndex[0] += priv->PwrGroupHT40[RF90_PATH_A][Channel-1];
+				pFinalPowerIndex[1] += priv->PwrGroupHT40[RF90_PATH_B][Channel-1];
+			}
+			else
+			{
+				pFinalPowerIndex[0] += priv->PwrGroupHT20[RF90_PATH_A][Channel-1];
+				pFinalPowerIndex[1] += priv->PwrGroupHT20[RF90_PATH_B][Channel-1];
+			}
+			break;
+		default:
+			break;
+	}
+	if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+	{
+		RT_TRACE(COMP_POWER, "40MHz finalPowerIndex (A / B) = 0x%x / 0x%x\n", 
+			pFinalPowerIndex[0], pFinalPowerIndex[1]);
+	}
+	else
+	{
+		RT_TRACE(COMP_POWER, "20MHz finalPowerIndex (A / B) = 0x%x / 0x%x\n", 
+			pFinalPowerIndex[0], pFinalPowerIndex[1]);
+	}
+}
+
+void getTxPowerWriteValByRegulatory(
+	struct net_device* dev,
+	u8		Channel,
+	u8		index,
+	u32		powerBase0,
+	u32		powerBase1,
+	u32*	pOutWriteVal
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8		i, chnlGroup, pwr_diff_limit[4];
+	u32 		writeVal, customer_limit;
+	
+	switch(priv->EEPROMRegulatory)
+	{
+		case 0:	
+			chnlGroup = 0;
+			RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", 
+				chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]);
+			writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + 
+				((index<2)?powerBase0:powerBase1);
+			RT_TRACE(COMP_POWER,"RTK better performance, writeVal = 0x%x\n", writeVal);
+			break;
+		case 1:	
+			if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+			{
+				writeVal = ((index<2)?powerBase0:powerBase1);
+				RT_TRACE(COMP_POWER,"Realtek regulatory, 40MHz, writeVal = 0x%x\n", writeVal);
+			}
+			else
+			{
+				if(priv->pwrGroupCnt == 1)
+					chnlGroup = 0;
+				if(priv->pwrGroupCnt >= 3)
+				{
+					if(Channel <= 3)
+						chnlGroup = 0;
+					else if(Channel >= 4 && Channel <= 8)
+						chnlGroup = 1;
+					else if(Channel > 8)
+						chnlGroup = 2;
+					if(priv->pwrGroupCnt == 4)
+						chnlGroup++;
+				}
+				RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", 
+				chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]);
+				writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + 
+						((index<2)?powerBase0:powerBase1);
+				RT_TRACE(COMP_POWER,"Realtek regulatory, 20MHz, writeVal = 0x%x\n", writeVal);
+			}
+			break;
+		case 2:	
+			writeVal = ((index<2)?powerBase0:powerBase1);
+			RT_TRACE(COMP_POWER,"Better regulatory, writeVal = 0x%x\n", writeVal);
+			break;
+		case 3:	
+			chnlGroup = 0;
+			RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", 
+				chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]);
+
+			if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+			{
+				RT_TRACE(COMP_POWER,"customer's limit, 40MHz = 0x%x\n", 
+					priv->PwrGroupHT40[RF90_PATH_A][Channel-1]);
+			}
+			else
+			{
+				RT_TRACE(COMP_POWER,"customer's limit, 20MHz = 0x%x\n", 
+					priv->PwrGroupHT20[RF90_PATH_A][Channel-1]);
+			}
+			for (i=0; i<4; i++)
+			{
+				pwr_diff_limit[i] = (u8)((priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]&(0x7f<<(i*8)))>>(i*8));
+				if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+				{
+					if(pwr_diff_limit[i] > priv->PwrGroupHT40[RF90_PATH_A][Channel-1])
+					{
+						pwr_diff_limit[i] = priv->PwrGroupHT40[RF90_PATH_A][Channel-1];
+					}
+				}
+				else
+				{
+					if(pwr_diff_limit[i] > priv->PwrGroupHT20[RF90_PATH_A][Channel-1])
+					{
+						pwr_diff_limit[i] = priv->PwrGroupHT20[RF90_PATH_A][Channel-1];
+					}
+				}
+			}
+			customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) |
+							(pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]);
+			RT_TRACE(COMP_POWER,"Customer's limit = 0x%x\n", customer_limit);
+
+			writeVal = customer_limit + ((index<2)?powerBase0:powerBase1);
+			RT_TRACE(COMP_POWER,"Customer, writeVal = 0x%x\n", writeVal);
+			break;
+		default:
+			chnlGroup = 0;
+			writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + 
+				((index<2)?powerBase0:powerBase1);
+			RT_TRACE(COMP_POWER,"RTK better performance, writeVal = 0x%x\n", writeVal);
+			break;
+	}
+
+	if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
+		writeVal = 0x10101010;
+	else if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
+		writeVal = 0x0;
+
+	*pOutWriteVal = writeVal;
+
+}
+
+void setAntennaDiff(
+	struct net_device* dev,
+	u8*		pFinalPowerIndex
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	char	ant_pwr_diff=0;
+	u32	u4RegValue=0;
+
+	if (priv->rf_type == RF_2T2R)
+	{
+		ant_pwr_diff = pFinalPowerIndex[1] - pFinalPowerIndex[0];
+		
+		if(ant_pwr_diff > 7)
+			ant_pwr_diff = 7;
+		if(ant_pwr_diff < -8)
+			ant_pwr_diff = -8;
+		RT_TRACE(COMP_POWER,"Antenna Diff from RF-B to RF-A = %d (0x%x)\n", 
+			ant_pwr_diff, ant_pwr_diff&0xf);
+		ant_pwr_diff &= 0xf;
+	}
+	priv->AntennaTxPwDiff[2] = 0;
+	priv->AntennaTxPwDiff[1] = 0;
+	priv->AntennaTxPwDiff[0] = (u8)(ant_pwr_diff);		
+
+	u4RegValue = (priv->AntennaTxPwDiff[2]<<8 | 
+				priv->AntennaTxPwDiff[1]<<4 | 
+				priv->AntennaTxPwDiff[0]	);
+
+	rtl8192_setBBreg(dev, rFPGA0_TxGainStage, 
+		(bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+
+	RT_TRACE(COMP_POWER,"Write BCD-Diff(0x%x) = 0x%x\n", 
+		rFPGA0_TxGainStage, u4RegValue);
+}
+
+void writeOFDMPowerReg(
+	struct net_device* dev,
+	u8		index,
+	u32		Value
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
+	u8 i, rfa_pwr[4];
+	u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0;
+	u32 writeVal=Value;
+	if (priv->rf_type == RF_2T2R)
+	{			
+		rf_pwr_diff = priv->AntennaTxPwDiff[0];
+
+		if (rf_pwr_diff >= 8)		
+		{	
+			rfa_lower_bound = 0x10-rf_pwr_diff;
+			RT_TRACE(COMP_POWER,"rfa_lower_bound= %d\n", rfa_lower_bound);
+		}
+		else
+		{
+			rfa_upper_bound = RF6052_MAX_TX_PWR-rf_pwr_diff;
+			RT_TRACE(COMP_POWER,"rfa_upper_bound= %d\n", rfa_upper_bound);
+		}			
+	}
+
+	for (i=0; i<4; i++)
+	{
+		rfa_pwr[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8));
+		if (rfa_pwr[i]  > RF6052_MAX_TX_PWR)
+			rfa_pwr[i]  = RF6052_MAX_TX_PWR;
+
+		if (priv->rf_type == RF_2T2R)
+		{
+			if (rf_pwr_diff >= 8)		
+			{	
+				if (rfa_pwr[i] <rfa_lower_bound)
+				{
+					RT_TRACE(COMP_POWER,"Underflow");
+					rfa_pwr[i] = rfa_lower_bound;
+				}
+			}
+			else if (rf_pwr_diff >= 1)	
+			{	
+				if (rfa_pwr[i] > rfa_upper_bound)
+				{
+					RT_TRACE(COMP_POWER,"Overflow");
+					rfa_pwr[i] = rfa_upper_bound;
+				}
+			}
+			RT_TRACE(COMP_POWER,"rfa_pwr[%d]=%x\n", i, rfa_pwr[i]);
+		}
+
+	}
+
+	writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0];
+
+	rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+	RT_TRACE(COMP_POWER,"Set 0x%x = %08x\n",RegOffset[index], writeVal);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	PHY_RF6052SetOFDMTxPower
+ *
+ * Overview:	For legacy and HY OFDM, we must read EEPROM TX power index for 
+ *			different channel and read original value in TX power register area from
+ *			0xe00. We increase offset and original value to be correct tx pwr.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/05/2008 	MHC		Simulate 8192 series method.
+ * 01/06/2009	MHC		1. Prevent Path B tx power overflow or underflow dure to
+ *						A/B pwr difference or legacy/HT pwr diff.
+ *						2. We concern with path B legacy/HT OFDM difference.
+ * 01/22/2009	MHC		Support new EPRO format from SD3.
+ *
+ *---------------------------------------------------------------------------*/
+extern	void 
+PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8* pPowerLevel, u8 Channel)
+{
+	u32 writeVal, powerBase0, powerBase1;
+	u8 index = 0;
+	u8 finalPowerIndex[4];
+
+	getPowerBase(dev, pPowerLevel, Channel, &powerBase0, &powerBase1, &finalPowerIndex[0]);
+	setAntennaDiff(dev, &finalPowerIndex[0]	);
+	
+	for(index=0; index<6; index++)
+	{
+		getTxPowerWriteValByRegulatory(dev, Channel, index, 
+			powerBase0, powerBase1, &writeVal);
+
+		writeOFDMPowerReg(dev, index, writeVal);
+	}
+}
+
+bool PHY_RF6052_Config(struct net_device* dev)
+{
+	struct r8192_priv 			*priv = rtllib_priv(dev);
+	bool rtStatus = true;	
+	u8 bRegHwParaFile = 1;
+	
+	if(priv->rf_type == RF_1T1R)
+		priv->NumTotalRFPath = 1;
+	else
+	priv->NumTotalRFPath = 2;
+
+	switch(bRegHwParaFile)
+	{
+		case 0:
+			phy_RF6052_Config_HardCode(dev);
+			break;
+
+		case 1:
+			rtStatus = phy_RF6052_Config_ParaFile(dev);
+			break;
+
+		case 2:
+			phy_RF6052_Config_HardCode(dev);
+			phy_RF6052_Config_ParaFile(dev);
+			break;
+
+		default:
+			phy_RF6052_Config_HardCode(dev);
+			break;
+	}
+	return rtStatus;
+		
+}
+
+void phy_RF6052_Config_HardCode(struct net_device* dev)
+{
+	
+
+	
+}
+
+bool phy_RF6052_Config_ParaFile(struct net_device* dev)
+{
+	u32			u4RegValue = 0;
+	u8			eRFPath;
+	bool rtStatus = true;
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	BB_REGISTER_DEFINITION_T	*pPhyReg;	
+
+
+	for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+	{
+
+		pPhyReg = &priv->PHYRegDef[eRFPath];
+		
+		switch(eRFPath)
+		{
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV);
+			break;
+		case RF90_PATH_B :
+		case RF90_PATH_D:
+			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16);
+			break;
+		}
+
+		rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+		
+		rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+
+		rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); 	
+		rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0);	
+
+
+		switch(eRFPath)
+		{
+		case RF90_PATH_A:
+#if	RTL8190_Download_Firmware_From_Header
+			rtStatus= rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+#else
+			rtStatus = PHY_ConfigRFWithParaFile(dev, (char* )&szRadioAFile, (RF90_RADIO_PATH_E)eRFPath);
+#endif
+			break;
+		case RF90_PATH_B:
+#if	RTL8190_Download_Firmware_From_Header
+			rtStatus= rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
+#else
+			if(priv->rf_type == RF_2T2R_GREEN)
+				rtStatus = PHY_ConfigRFWithParaFile(dev, (char *)&szRadioBGMFile, (RF90_RADIO_PATH_E)eRFPath);
+			else
+				rtStatus = PHY_ConfigRFWithParaFile(dev, (char* )&szRadioBFile, (RF90_RADIO_PATH_E)eRFPath);
+#endif
+			break;
+		case RF90_PATH_C:
+			break;
+		case RF90_PATH_D:
+			break;
+		}
+
+		switch(eRFPath)
+		{
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
+			break;
+		case RF90_PATH_B :
+		case RF90_PATH_D:
+			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
+			break;
+		}
+
+		if(rtStatus != true){
+			printk("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath);
+			goto phy_RF6052_Config_ParaFile_Fail;
+		}
+
+	}
+
+	RT_TRACE(COMP_INIT, "<---phy_RF6052_Config_ParaFile()\n");
+	return rtStatus;
+	
+phy_RF6052_Config_ParaFile_Fail:	
+	return rtStatus;
+}
+
+
+extern u32 PHY_RFShadowRead(
+	struct net_device		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset)
+{
+	return	RF_Shadow[eRFPath][Offset].Value;
+	
+}	/* PHY_RFShadowRead */
+
+
+extern void PHY_RFShadowWrite(
+	struct net_device		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset,
+	u32					Data)
+{
+	RF_Shadow[eRFPath][Offset].Value = (Data & bMask20Bits);
+	RF_Shadow[eRFPath][Offset].Driver_Write = true;
+	
+}	/* PHY_RFShadowWrite */
+
+
+extern bool PHY_RFShadowCompare(
+	struct net_device		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset)
+{
+	u32	reg;
+	
+	if (RF_Shadow[eRFPath][Offset].Compare == true)
+	{
+		reg = rtl8192_phy_QueryRFReg(dev, eRFPath, Offset, bMask20Bits);
+		if (RF_Shadow[eRFPath][Offset].Value != reg)
+		{
+			RF_Shadow[eRFPath][Offset].ErrorOrNot = true;
+			RT_TRACE(COMP_INIT, "PHY_RFShadowCompare RF-%d Addr%02xErr = %05x", eRFPath, Offset, reg);
+		}
+		else
+		{
+			RT_TRACE(COMP_INIT, "PHY_RFShadowCompare RF-%d Addr%02x Err = %05x return false\n", eRFPath, Offset, reg);
+			RF_Shadow[eRFPath][Offset].ErrorOrNot = false;
+		}
+		return RF_Shadow[eRFPath][Offset].ErrorOrNot;
+	}
+	return false;
+}	/* PHY_RFShadowCompare */
+
+extern void PHY_RFShadowRecorver(
+	struct net_device		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset)
+{
+	if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true)
+	{
+		if (RF_Shadow[eRFPath][Offset].Recorver == true)
+		{
+			rtl8192_phy_SetRFReg(dev, eRFPath, Offset, bMask20Bits, RF_Shadow[eRFPath][Offset].Value);
+			RT_TRACE(COMP_INIT, "PHY_RFShadowRecorver RF-%d Addr%02x=%05x", 
+			eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value);
+		}
+	}
+	
+}	/* PHY_RFShadowRecorver */
+
+
+extern void PHY_RFShadowCompareAll(struct net_device * dev)
+{
+	u32		eRFPath;
+	u32		Offset;
+
+	for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+	{
+		for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
+		{
+			PHY_RFShadowCompare(dev, (RF90_RADIO_PATH_E)eRFPath, Offset);
+		}
+	}
+	
+}	/* PHY_RFShadowCompareAll */
+
+
+extern void PHY_RFShadowRecorverAll(struct net_device * dev)
+{
+	u32		eRFPath;
+	u32		Offset;
+
+	for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+	{
+		for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
+		{
+			PHY_RFShadowRecorver(dev, (RF90_RADIO_PATH_E)eRFPath, Offset);
+		}
+	}
+	
+}	/* PHY_RFShadowRecorverAll */
+
+
+extern void PHY_RFShadowCompareFlagSet(
+	struct net_device 		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset,
+	u8					Type)
+{
+	RF_Shadow[eRFPath][Offset].Compare = Type;
+		
+}	/* PHY_RFShadowCompareFlagSet */
+
+
+extern void PHY_RFShadowRecorverFlagSet(
+	struct net_device 		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset,
+	u8					Type)
+{
+	RF_Shadow[eRFPath][Offset].Recorver= Type;
+		
+}	/* PHY_RFShadowRecorverFlagSet */
+
+
+extern void PHY_RFShadowCompareFlagSetAll(struct net_device  * dev)
+{
+	u32		eRFPath;
+	u32		Offset;
+
+	for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+	{
+		for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
+		{
+			if (Offset != 0x26 && Offset != 0x27)
+				PHY_RFShadowCompareFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, false);
+			else
+				PHY_RFShadowCompareFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, true);
+		}
+	}
+		
+}	/* PHY_RFShadowCompareFlagSetAll */
+
+
+extern void PHY_RFShadowRecorverFlagSetAll(struct net_device  * dev)
+{
+	u32		eRFPath;
+	u32		Offset;
+
+	for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+	{
+		for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
+		{
+			if (Offset != 0x26 && Offset != 0x27)
+				PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, false);
+			else
+				PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, true);
+		}
+	}
+		
+}	/* PHY_RFShadowCompareFlagSetAll */
+
+
+
+extern void PHY_RFShadowRefresh(struct net_device  * dev)
+{
+	u32		eRFPath;
+	u32		Offset;
+
+	for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
+	{
+		for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
+		{
+			RF_Shadow[eRFPath][Offset].Value = 0;
+			RF_Shadow[eRFPath][Offset].Compare = false;
+			RF_Shadow[eRFPath][Offset].Recorver  = false;
+			RF_Shadow[eRFPath][Offset].ErrorOrNot = false;
+			RF_Shadow[eRFPath][Offset].Driver_Write = false;
+		}
+	}
+	
+}	/* PHY_RFShadowRead */
+
+/* End of HalRf6052.c */
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_dev.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_dev.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL8192SE_H
+#define _RTL8192SE_H
+
+#include "r8192S_def.h"
+
+u8 rtl8192se_QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc);
+bool rtl8192se_GetHalfNmodeSupportByAPs(struct net_device* dev);
+bool rtl8192se_GetNmodeSupportBySecCfg(struct net_device *dev);
+bool rtl8192se_HalTxCheckStuck(struct net_device *dev);
+bool rtl8192se_HalRxCheckStuck(struct net_device *dev);
+void rtl8192se_interrupt_recognized(struct net_device *dev, u32 *p_inta, u32 *p_intb);
+void rtl8192se_enable_rx(struct net_device *dev);
+void rtl8192se_enable_tx(struct net_device *dev);
+void rtl8192se_EnableInterrupt(struct net_device *dev);
+void rtl8192se_DisableInterrupt(struct net_device *dev);
+void rtl8192se_ClearInterrupt(struct net_device *dev);
+void rtl8192se_InitializeVariables(struct net_device  *dev);
+void rtl8192se_start_beacon(struct net_device *dev);
+u8 MRateToHwRate8192SE(struct net_device*dev, u8 rate);
+void rtl8192se_get_eeprom_size(struct net_device* dev);
+void MacConfigBeforeFwDownload(struct net_device *dev);
+bool rtl8192se_adapter_start(struct net_device* dev);
+void rtl8192se_link_change(struct net_device *dev);
+void rtl8192se_AllowAllDestAddr(struct net_device* dev, bool bAllowAllDA, bool WriteIntoReg);
+void rtl8192se_tx_fill_desc(struct net_device *dev, tx_desc *pDesc, cb_desc *cb_desc, struct sk_buff *skb);
+void rtl8192se_tx_fill_cmd_desc(struct net_device *dev, tx_desc_cmd *entry, cb_desc *cb_desc, 
+		struct sk_buff *skb);
+bool rtl8192se_rx_query_status_desc(struct net_device* dev, struct rtllib_rx_stats*  stats, 
+		rx_desc *pdesc, struct sk_buff* skb);
+void rtl8192se_halt_adapter(struct net_device *dev, bool bReset);
+void rtl8192se_update_ratr_table(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry);
+int r8192se_resume_firm(struct net_device *dev);
+void PHY_SetRtl8192seRfHalt(struct net_device* dev);
+void UpdateHalRAMask8192SE(struct net_device* dev, bool bMulticast, u8 macId, u8 MimoPs, u8 WirelessMode, u8 bCurTxBW40MHz,	u8 rssi_level);
+u8 HalSetSysClk8192SE(struct net_device *dev, u8 Data);
+bool	rtl8192se_RxCommandPacketHandle(struct net_device *dev, struct sk_buff* skb,rx_desc *pdesc);
+bool rtl8192se_check_ht_cap(struct net_device* dev, struct sta_info *sta, 
+		struct rtllib_network* net);
+u8 rtl8192se_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority);
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.h
@@ -0,0 +1,42 @@
+#ifndef __INC_HAL8192SE_FW_IMG_H
+#define __INC_HAL8192SE_FW_IMG_H
+
+/*Created on  2010/ 2/24,  2:32*/
+
+#include <linux/types.h>
+#define ImgArrayLength 80976
+extern u8 Rtl8192SEFwImgArray[ImgArrayLength];
+#define MainArrayLength 1
+extern u8 Rtl8192SEFwMainArray[MainArrayLength];
+#define DataArrayLength 1
+extern u8 Rtl8192SEFwDataArray[DataArrayLength];
+#define PHY_REG_2T2RArrayLength 372
+extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength];
+#define PHY_REG_1T2RArrayLength 1
+extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength];
+#define PHY_ChangeTo_1T1RArrayLength 48
+extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength];
+#define PHY_ChangeTo_1T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength];
+#define PHY_ChangeTo_2T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength];
+#define PHY_REG_Array_PGLength 84
+extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength];
+#define RadioA_1T_ArrayLength 202
+extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength];
+#define RadioB_ArrayLength 22
+extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength];
+#define RadioA_to1T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength];
+#define RadioA_to2T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength];
+#define RadioB_GM_ArrayLength 10
+extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength];
+#define MAC_2T_ArrayLength 106
+extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength];
+#define MACPHY_Array_PGLength 1
+extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength];
+#define AGCTAB_ArrayLength 320
+extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength];
+
+#endif //__INC_HAL8192SE_FW_IMG_H
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.c
@@ -0,0 +1,5610 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+/*Created on  2009/ 7/23,  5: 4*/
+
+#ifdef RTL8192SE
+#include "r8192S_hwimg.h"
+
+u8 Rtl8192SEFwImgArray[ImgArrayLength] = {
+0x92,0x81,0x31,0x70,0x30,0x00,0x00,0x00,0x08,0x84,0x00,0x00,0x48,0xa4,0x00,0x00,
+0x30,0x00,0x00,0x00,0xc0,0xa2,0x00,0x00,0x31,0x00,0x02,0x00,0x07,0x20,0x16,0x06,
+0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37,
+0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,
+0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x00,0x80,0x1a,0x3c,0x44,0x7c,0x5a,0x27,
+0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf,
+0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf,
+0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf,
+0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf,
+0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf,
+0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf,
+0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf,
+0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xac,0x1e,0x00,0x08,
+0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34,
+0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c,
+0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c,
+0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10,
+0x03,0x46,0x08,0x00,0x24,0x7e,0x42,0x8d,0x68,0x15,0x05,0x26,0xe0,0x63,0xa4,0x94,
+0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0,
+0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xe4,0x63,0xa2,0x94,0xe0,0x63,0xa0,0xa4,
+0xe4,0x63,0xa0,0xa4,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xac,0x00,0x00,0x20,0xad,
+0x01,0x00,0x82,0x24,0x24,0x7e,0x47,0xad,0xe0,0x63,0xa2,0xa4,0x12,0x00,0x00,0x05,
+0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
+0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
+0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x64,0x10,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,
+0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,
+0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,
+0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,
+0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,
+0x58,0x9f,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,
+0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,
+0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,
+0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,
+0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
+0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
+0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08,
+0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x25,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,
+0x18,0x03,0x67,0x34,0x00,0x80,0x02,0x3c,0x43,0xb0,0x03,0x3c,0x34,0x05,0x46,0x24,
+0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,
+0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xe6,0xac,
+0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,
+0xf4,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,
+0x90,0x05,0x42,0x24,0x00,0x00,0x62,0xac,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
+0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x0c,0x00,0xf2,0x84,0x08,0x00,0xf5,0x8c,
+0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x23,0x10,0x46,0x00,0xff,0xff,0x51,0x30,
+0xd0,0x03,0x08,0x35,0xff,0x00,0x96,0x30,0x00,0x00,0x12,0xad,0x21,0xa0,0xa0,0x00,
+0x21,0x30,0xc5,0x00,0x00,0x00,0x15,0xad,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,
+0x21,0x38,0x20,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,
+0xff,0xff,0x82,0x32,0x00,0x94,0x03,0x00,0x03,0x94,0x12,0x00,0xa6,0x01,0x00,0x08,
+0x02,0x9a,0x02,0x00,0x28,0xb0,0x03,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x90,0x25,0xb0,0x10,0x3c,0x20,0x10,0x02,0x3c,0xff,0x00,0x93,0x30,
+0x00,0x22,0x13,0x00,0xff,0xff,0x43,0x32,0x01,0x01,0x45,0x2a,0x21,0xa0,0x82,0x00,
+0x21,0xa8,0xb1,0x02,0xd0,0x03,0x02,0x36,0x00,0x01,0x11,0x24,0x0b,0x88,0x65,0x00,
+0x21,0x20,0xc0,0x02,0x00,0x00,0x53,0xac,0x4d,0x01,0x00,0x0c,0xb0,0x03,0x10,0x36,
+0x21,0x30,0x80,0x02,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,0x21,0x38,0x20,0x02,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,0x00,0x94,0x03,0x00,
+0x03,0x94,0x12,0x00,0x00,0x00,0x12,0xae,0xe2,0xff,0x40,0x1e,0x00,0x00,0x00,0x00,
+0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x68,0x15,0x52,0x24,0x00,0x80,0x02,0x3c,
+0x18,0x03,0x83,0x34,0xc8,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0xb4,0x64,0x42,0x8e,
+0x20,0x65,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0xb8,0x64,0x42,0xae,
+0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x20,0x65,0x44,0x8e,
+0x24,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
+0x0a,0x18,0x82,0x00,0x20,0x65,0x43,0xae,0x20,0x65,0x85,0x8e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
+0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,
+0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
+0x68,0x64,0x91,0xa2,0xb4,0x64,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x00,0x00,0x05,0x96,0x18,0x64,0x83,0x8e,0x2a,0xb0,0x02,0x3c,0x27,0x20,0x05,0x00,
+0x01,0x00,0x46,0x34,0x21,0x10,0x65,0x00,0x2b,0x18,0x64,0x00,0x02,0x00,0x60,0x10,
+0x00,0x00,0x00,0x00,0x18,0x64,0x82,0xae,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
+0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0xc0,0xff,0x02,0x24,0x25,0x18,0x64,0x00,
+0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0xc2,0xa0,0x00,0x00,0xc3,0xa0,0xbc,0xff,0x35,0x16,0x41,0xb0,0x03,0x3c,
+0xfc,0x4a,0x82,0x8e,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,
+0x2c,0x00,0xb5,0x8f,0xfc,0x4a,0x82,0xae,0x24,0x00,0xb3,0x8f,0x28,0x00,0xb4,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
+0x18,0x03,0x83,0x34,0x54,0x08,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,
+0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x52,0x24,0xb0,0x03,0x95,0x34,0x39,0x02,0x00,0x08,
+0x21,0xf0,0x40,0x02,0x08,0x00,0x04,0xae,0x76,0x4b,0x82,0x92,0x00,0x00,0x00,0x00,
+0x45,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24,
+0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x5a,0x00,0x36,0x12,
+0x00,0x00,0x00,0x00,0xcc,0x64,0x42,0x8e,0x38,0x65,0x53,0x8e,0x01,0x00,0x04,0x24,
+0x00,0x00,0xa2,0xae,0xd0,0x64,0x42,0xae,0x00,0x00,0xb3,0xae,0x4d,0x01,0x00,0x0c,
+0x21,0xa0,0xc0,0x03,0x38,0x65,0x44,0x8e,0x3c,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,
+0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x38,0x65,0x43,0xae,
+0x38,0x65,0xc5,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa5,0xae,0x02,0x80,0x17,0x3c,
+0xff,0xff,0x62,0x32,0x25,0x80,0x57,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x02,0x92,
+0xff,0x00,0x16,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0x0c,0x00,0x11,0x92,
+0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,
+0x05,0x00,0x36,0x12,0x21,0x30,0x60,0x00,0xcc,0x64,0xc3,0xaf,0x70,0x64,0xd1,0xa3,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
+0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,
+0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xbd,0xff,0x40,0x10,
+0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,0x76,0x4b,0x82,0x92,0x00,0x00,0x00,0x00,
+0xbd,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x00,0x03,0x24,0x76,0x4b,0x83,0xa2,
+0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,
+0x25,0x10,0x57,0x00,0x02,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0xff,0xc0,0x64,0x30,
+0x00,0xc0,0x84,0x34,0xe3,0x18,0x00,0x0c,0x77,0x4b,0x83,0xa2,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,
+0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,
+0xa8,0xff,0x36,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,
+0xfc,0x4a,0x43,0x8c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34,
+0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
+0xfc,0x4a,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
+0x18,0x03,0x83,0x34,0xa4,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,
+0x68,0x15,0xd3,0x26,0xb0,0x03,0x94,0x34,0x02,0x80,0x15,0x3c,0x21,0xb8,0x60,0x02,
+0xc0,0x64,0x62,0x8e,0x2c,0x65,0x70,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x82,0xae,
+0xc4,0x64,0x62,0xae,0x00,0x00,0x90,0xae,0x4d,0x01,0x00,0x0c,0x21,0x88,0xe0,0x02,
+0x2c,0x65,0x64,0x8e,0x30,0x65,0x63,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x2c,0x65,0x63,0xae,0x2c,0x65,0xe5,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x90,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x82,0xae,0x0c,0x00,0x12,0x92,0xff,0x00,0x02,0x24,0x0a,0x00,0x42,0x12,
+0x00,0x1a,0x12,0x00,0x20,0x10,0x02,0x3c,0x21,0x18,0x62,0x00,0xc0,0x64,0xe3,0xae,
+0x6c,0x64,0xf2,0xa2,0x21,0x30,0x60,0x00,0x01,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xf8,0x63,0x22,0x8e,0x04,0x00,0x03,0x8e,
+0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x5d,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,
+0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
+0x00,0x26,0x04,0x00,0x25,0x28,0x44,0x00,0x08,0x00,0x05,0xae,0xc2,0x11,0x05,0x00,
+0x01,0x00,0x43,0x30,0x47,0x00,0x60,0x14,0x01,0x00,0x02,0x24,0x00,0x00,0x04,0x96,
+0x1c,0x64,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x05,0x00,0x40,0x10,
+0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0x1c,0x64,0x22,0xae,0x08,0x00,0x05,0x8e,
+0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x40,0x03,0x3c,
+0x25,0x28,0xa3,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0x03,0x00,0x40,0x14,
+0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x04,0x00,0x45,0x34,0x08,0x00,0x05,0xae,
+0x68,0x15,0xc2,0x26,0x76,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x3b,0x00,0x83,0x10,
+0x7f,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x08,0x00,0x02,0xae,0x68,0x15,0xc5,0x26,
+0xc4,0x64,0xa2,0x8c,0x20,0x00,0x10,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x2a,0xb0,0x03,0x3c,0x08,0x00,0x50,0xac,0x05,0x00,0x70,0x34,0x01,0x00,0x02,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x02,0xa2,0x00,0x00,0x03,0xa2,0x2a,0x7e,0xa2,0x96,
+0xff,0x00,0x03,0x24,0x01,0x00,0x42,0x24,0x2a,0x7e,0xa2,0xa6,0x2a,0x7e,0xa4,0x96,
+0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,0x00,0x00,0x44,0xa4,0x98,0xff,0x43,0x16,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03,
+0xfc,0x4a,0xa2,0xac,0xc3,0xff,0x62,0x14,0xff,0xdf,0x02,0x3c,0x00,0x00,0x04,0x96,
+0x18,0x64,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0xbd,0xff,0x40,0x10,
+0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0xff,0x02,0x00,0x08,0x18,0x64,0x22,0xae,
+0x08,0x00,0x05,0x8e,0xf4,0x02,0x00,0x08,0xc2,0x11,0x05,0x00,0x80,0x00,0xa5,0x34,
+0x13,0x03,0x00,0x08,0x08,0x00,0x05,0xae,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x38,0x0d,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc2,0x90,0x25,0xb0,0x04,0x3c,
+0x88,0x02,0x83,0x34,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0xb0,0x03,0x93,0x34,
+0x02,0x80,0x14,0x3c,0xc0,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x4c,0x64,0xf1,0xa2,
+0x68,0x15,0xa2,0x26,0x84,0x64,0x46,0x8c,0xf0,0x64,0x45,0x8c,0x03,0x00,0x04,0x24,
+0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26,
+0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x18,0x44,0x00,
+0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00,
+0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac,
+0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04,0x00,0x00,0x00,0x00,
+0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,
+0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,
+0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x43,0x00,
+0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,
+0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x0d,0x00,0xe2,0x34,
+0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,
+0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,
+0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
+0x84,0x64,0x42,0x8e,0xf0,0x64,0x50,0x8e,0x03,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
+0x88,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xf0,0x64,0x44,0x8e,0xf4,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xf0,0x64,0x43,0xae,0xf0,0x64,0xe2,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x9f,0xff,0x22,0x12,
+0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x93,0xff,0xc0,0x16,
+0x84,0x64,0xe2,0xae,0x74,0x03,0x00,0x08,0x48,0x64,0xf1,0xa2,0x08,0x00,0x03,0x8e,
+0xa8,0x03,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xab,0xff,0x40,0x14,
+0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,
+0x96,0x03,0x00,0x08,0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12,0x68,0x15,0xa2,0x26,
+0x4c,0x64,0x43,0x90,0x41,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x00,0x80,0x42,0x34,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0x48,0x64,0x43,0x90,
+0x40,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,
+0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
+0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0xc8,0x10,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,
+0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,0xa5,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,
+0x54,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26,0x90,0x64,0x46,0x8c,0xfc,0x64,0x45,0x8c,
+0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,
+0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,
+0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,
+0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c,
+0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,
+0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04,
+0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,
+0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,
+0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,
+0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,
+0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,
+0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,
+0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12,
+0x00,0x00,0x00,0x00,0x90,0x64,0x42,0x8e,0xfc,0x64,0x50,0x8e,0x04,0x00,0x04,0x24,
+0x00,0x00,0x62,0xae,0x94,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xfc,0x64,0x44,0x8e,0x00,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,
+0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xfc,0x64,0x43,0xae,
+0xfc,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
+0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
+0x9f,0xff,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
+0x93,0xff,0xc0,0x16,0x90,0x64,0xe2,0xae,0x59,0x04,0x00,0x08,0x50,0x64,0xf1,0xa2,
+0x08,0x00,0x03,0x8e,0x8d,0x04,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,
+0xab,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x10,0x82,0x00,0x7b,0x04,0x00,0x08,0x10,0x00,0x02,0xae,0x1f,0x00,0xc0,0x12,
+0x68,0x15,0xa2,0x26,0x54,0x64,0x43,0x90,0x43,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x50,0x64,0x43,0x90,
+0x42,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,
+0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
+0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,
+0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf,
+0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
+0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0x54,0x14,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xb0,0x00,0x00,
+0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,0x01,0x00,0x16,0x24,
+0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,
+0x5c,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,
+0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,0x08,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,
+0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,
+0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x1d,0x00,0xe2,0x34,
+0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,
+0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,
+0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
+0x9c,0x64,0x42,0x8e,0x08,0x65,0x50,0x8e,0x05,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
+0xa0,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x08,0x65,0x44,0x8e,0x0c,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x08,0x65,0x43,0xae,0x08,0x65,0xe2,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
+0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x66,0x00,0xc0,0x12,
+0x9c,0x64,0xe2,0xae,0x64,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26,0x9c,0x64,0x46,0x8c,
+0x08,0x65,0x45,0x8c,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e,
+0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,
+0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
+0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae,0x00,0x00,0x04,0x96,
+0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,
+0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,
+0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x96,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
+0x1d,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,
+0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
+0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
+0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
+0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12,0x68,0x15,0xa2,0x26,
+0x64,0x64,0x43,0x90,0x45,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x7e,0x05,0x00,0x08,0x58,0x64,0xf1,0xa2,
+0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,
+0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0xa0,0x05,0x00,0x08,0x10,0x00,0x02,0xae,
+0x58,0x64,0x43,0x90,0x44,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x38,0x18,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0xfd,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0x21,0x98,0x40,0x00,
+0x02,0x80,0x14,0x3c,0x55,0x06,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
+0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,
+0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,
+0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,
+0x25,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,
+0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,
+0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12,
+0x00,0x00,0x00,0x00,0xa8,0x64,0x42,0x8e,0x14,0x65,0x50,0x8e,0x06,0x00,0x04,0x24,
+0x00,0x00,0x62,0xae,0xac,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x14,0x65,0x44,0x8e,0x18,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,
+0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x14,0x65,0x43,0xae,
+0x14,0x65,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
+0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
+0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
+0x66,0x00,0xc0,0x12,0xa8,0x64,0xe2,0xae,0x60,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26,
+0xa8,0x64,0x46,0x8c,0x14,0x65,0x45,0x8c,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,
+0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,
+0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae,
+0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,
+0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,
+0x96,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00,
+0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,
+0x2a,0xb0,0x07,0x3c,0x25,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24,
+0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,
+0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,
+0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,
+0x00,0x00,0xa2,0xa4,0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12,
+0x68,0x15,0xa2,0x26,0x60,0x64,0x43,0x90,0x47,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x77,0x06,0x00,0x08,
+0x5c,0x64,0xf1,0xa2,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,
+0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,
+0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x99,0x06,0x00,0x08,
+0x10,0x00,0x02,0xae,0x5c,0x64,0x43,0x90,0x46,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x00,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x1c,0x1c,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,
+0x68,0x15,0xa5,0x24,0x04,0x4b,0xa2,0x8c,0xfc,0x4a,0xa4,0x8c,0x00,0x08,0x03,0x3c,
+0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
+0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x78,0x1c,0x42,0x24,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
+0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x2a,0xb0,0x03,0x3c,0x68,0x15,0x51,0x24,
+0xb0,0x03,0x93,0x34,0x2c,0x00,0x77,0x34,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,
+0x41,0x07,0x00,0x08,0x02,0x80,0x1e,0x3c,0x74,0x64,0x26,0x92,0x44,0x65,0x25,0x8e,
+0x00,0x32,0x06,0x00,0x21,0x30,0xc2,0x00,0xd8,0x64,0x26,0xae,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x44,0x65,0x30,0x8e,0x0a,0x00,0x04,0x24,0x21,0x90,0x00,0x00,
+0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c,
+0x25,0x80,0x02,0x02,0x0c,0x00,0x05,0x92,0x02,0x00,0x04,0x92,0xff,0x00,0x02,0x24,
+0xff,0x00,0xa3,0x30,0x04,0x00,0x62,0x10,0x21,0x80,0x04,0x02,0x00,0x00,0x63,0xae,
+0x01,0x00,0x12,0x24,0x74,0x64,0x25,0xa2,0x48,0xa4,0xb0,0xae,0x21,0x28,0x00,0x02,
+0x02,0x00,0xa2,0x90,0x08,0x00,0x10,0x26,0x21,0x20,0x00,0x02,0xff,0x00,0x42,0x30,
+0x00,0x00,0x62,0xae,0x03,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x63,0x30,
+0x00,0x00,0x63,0xae,0x00,0x00,0x72,0xae,0x03,0x00,0xa2,0x90,0x44,0xa4,0xc3,0x92,
+0x02,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2f,0x00,0x42,0x28,
+0x11,0x00,0x40,0x10,0x08,0x00,0x02,0x24,0x03,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
+0x7f,0x00,0x42,0x30,0x44,0xa4,0xc2,0xa2,0x02,0x00,0xa3,0x90,0x02,0x80,0x02,0x3c,
+0xf4,0x91,0x42,0x24,0xff,0x00,0x63,0x30,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,
+0x04,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00,0x40,0xa4,0xc2,0xaf,
+0x21,0xa0,0x40,0x00,0x08,0x00,0x02,0x24,0x0a,0x00,0x04,0x24,0x05,0x00,0x82,0x12,
+0x00,0x01,0x07,0x24,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,0x01,0x00,0xe2,0xa2,
+0x01,0x00,0xe3,0xa2,0xbc,0xff,0x40,0x16,0x20,0x10,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xfc,0x4a,0x22,0x8e,
+0x00,0x04,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,
+0x3c,0x00,0xbf,0x8f,0xfc,0x4a,0x22,0xae,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x40,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c,
+0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,
+0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00,
+0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00,
+0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34,
+0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30,
+0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad,
+0x68,0x15,0xa5,0x26,0xe2,0x63,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,
+0xe2,0x63,0xa2,0xa0,0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26,
+0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00,
+0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00,
+0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10,
+0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,0x68,0x15,0xb4,0x26,
+0xb4,0x65,0x86,0x8e,0xb8,0x65,0x90,0x8e,0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00,
+0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02,
+0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30,
+0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c,
+0xb4,0x65,0x82,0xae,0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02,
+0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c,0x10,0x01,0x00,0x0c,0x68,0x15,0xb1,0x26,
+0xb4,0x65,0x23,0x8e,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
+0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x65,0x25,0x8e,
+0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,
+0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,
+0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02,
+0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa2,0xaf,0xb4,0x65,0x83,0x8e,0x68,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c,
+0x21,0x18,0x72,0x00,0xb4,0x65,0x83,0xae,0xb4,0x65,0x23,0x8e,0xb0,0x03,0x02,0x36,
+0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xb4,0x65,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,
+0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,
+0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,
+0x10,0x00,0xb0,0xaf,0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00,
+0x08,0x00,0x06,0x24,0x04,0x00,0x63,0x2c,0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x03,0x3c,0x60,0x7b,0x63,0x24,0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae,
+0x04,0x00,0x71,0xac,0x00,0x00,0x91,0xac,0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,0x58,0x45,0x00,0x0c,
+0x25,0x20,0x44,0x00,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96,
+0x95,0x07,0x00,0x0c,0x09,0x00,0x04,0x24,0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e,
+0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae,
+0x70,0x4f,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x47,0x24,0xec,0x64,0xe3,0x90,0xff,0xff,0xa5,0x30,
+0x09,0x00,0xa3,0x10,0x21,0x20,0xc0,0x00,0x5c,0x65,0xe2,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0xc2,0xac,0x66,0x65,0xe3,0x94,0x0e,0x00,0x02,0x24,0x14,0x00,0xc2,0xac,
+0x30,0x08,0x00,0x08,0x0c,0x00,0xc3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,0x03,0x00,0x82,0x90,0x04,0x00,0x84,0x24,
+0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x10,0x22,0x63,0x24,0x18,0x03,0x42,0x34,
+0xd0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,0x24,0x00,0xb3,0xaf,0x28,0x00,0xbf,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x78,0x08,0x00,0x0c,0x18,0x00,0xb0,0xaf,
+0x06,0x00,0x40,0x10,0x02,0x80,0x13,0x3c,0x68,0x15,0x63,0x26,0x76,0x4b,0x62,0x90,
+0x00,0x00,0x00,0x00,0x9b,0x00,0x40,0x14,0x00,0xc0,0x04,0x34,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,
+0x00,0x00,0x43,0x90,0x68,0x15,0x66,0x26,0xbc,0x65,0xc5,0x8c,0xc0,0x18,0x03,0x00,
+0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,
+0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x2b,0x38,0x85,0x00,
+0x00,0x04,0x22,0x26,0x60,0x65,0xc3,0x8c,0x0b,0x88,0x47,0x00,0x01,0x04,0x25,0x2e,
+0x5c,0x65,0xc3,0xac,0xc0,0x65,0xc4,0xac,0x66,0x65,0xc0,0xa4,0x11,0x00,0xa0,0x14,
+0x65,0x65,0xc0,0xa0,0x00,0xfc,0x83,0x24,0x23,0x10,0x02,0x3c,0x0b,0x18,0x87,0x00,
+0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x33,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x23,0x88,0x83,0x00,0x2b,0x10,0x83,0x00,0xbc,0x65,0xc3,0xac,0x03,0x00,0x40,0x10,
+0x01,0x04,0x25,0x2e,0x00,0x04,0x31,0x26,0x01,0x04,0x25,0x2e,0x0e,0x00,0xa0,0x10,
+0x68,0x15,0x70,0x26,0x68,0x15,0x70,0x26,0xc0,0x65,0x03,0x8e,0xbc,0x65,0x04,0x8e,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x25,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,
+0x51,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x68,0x15,0x70,0x26,0xbc,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
+0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8e,0x12,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x66,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
+0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xb8,0x08,0x00,0x08,0x00,0xfc,0x63,0x24,
+0x5c,0x65,0x05,0x8e,0x21,0x30,0x80,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e,0x66,0x65,0x05,0x96,
+0xbc,0x65,0x02,0x8e,0x21,0x18,0x71,0x00,0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,
+0x09,0x00,0x04,0x24,0xbc,0x65,0x02,0xae,0x5c,0x65,0x03,0xae,0x4d,0x01,0x00,0x0c,
+0x66,0x65,0x05,0xa6,0x68,0x15,0x70,0x26,0xbc,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
+0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8e,0x12,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x66,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
+0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xc4,0x65,0x02,0x8e,0x5c,0x65,0x05,0x8e,
+0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e,0x66,0x65,0x02,0x96,
+0xc0,0x65,0x12,0x96,0x21,0x18,0x71,0x00,0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,
+0x5c,0x65,0x03,0xae,0x66,0x65,0x02,0xa6,0x0c,0x00,0x40,0x16,0xbc,0x65,0x11,0xae,
+0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0x68,0x15,0x70,0x26,0xfe,0x08,0x00,0x08,
+0x00,0x00,0x00,0x00,0x44,0x67,0x62,0x94,0x76,0x4b,0x60,0xa0,0xe3,0x18,0x00,0x0c,
+0x21,0x20,0x44,0x00,0x97,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c,
+0x09,0x00,0x04,0x24,0x5c,0x65,0x05,0x8e,0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c,
+0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e,
+0x66,0x65,0x02,0x96,0x21,0x20,0x51,0x02,0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02,
+0xbc,0x65,0x04,0xae,0x09,0x00,0x04,0x24,0x5c,0x65,0x03,0xae,0x2d,0x09,0x00,0x08,
+0x66,0x65,0x02,0xa6,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x05,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x02,0x80,0x09,0x3c,
+0x68,0x15,0x28,0x25,0xe8,0x63,0x06,0x8d,0xff,0xff,0x02,0x34,0x3f,0x00,0xc2,0x10,
+0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x30,0x00,0x40,0x10,0x02,0x19,0x06,0x00,
+0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xe8,0x63,0x06,0xad,
+0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0xec,0x63,0x02,0xad,0xff,0xff,0x02,0x34,
+0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00,0x1f,0x00,0x40,0x10,
+0x02,0x19,0x04,0x00,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x44,0x24,
+0x04,0x40,0xc4,0xac,0xec,0x63,0xc2,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0x23,0x25,0x80,0x10,0x02,0x00,
+0x21,0x28,0x43,0x00,0x74,0x51,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,
+0x0a,0x30,0x82,0x00,0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,
+0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x74,0x51,0xa6,0xac,
+0x08,0x00,0xe0,0x03,0x78,0x51,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,
+0x74,0x51,0xa2,0xac,0x08,0x00,0xe0,0x03,0x78,0x51,0xa2,0xac,0x21,0x10,0x87,0x00,
+0x23,0x10,0x43,0x00,0x69,0x09,0x00,0x08,0x04,0x40,0xc2,0xac,0x21,0x10,0xc7,0x00,
+0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0x23,0x10,0x43,0x00,0xe8,0x63,0x02,0xad,
+0xec,0x63,0x02,0xad,0xff,0xff,0x02,0x34,0xd4,0xff,0x82,0x14,0x2b,0x10,0x87,0x00,
+0x00,0x21,0x07,0x00,0x62,0x09,0x00,0x08,0x04,0x40,0xc4,0xac,0x00,0x31,0x04,0x00,
+0x55,0x09,0x00,0x08,0xe8,0x63,0x06,0xad,0x63,0x00,0x82,0x24,0x77,0x00,0x42,0x2c,
+0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x64,0x00,0x82,0x24,
+0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,
+0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x24,0x08,0x42,0x34,0x00,0x00,0x43,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x16,0x00,0x60,0x14,0x01,0x00,0x02,0x24,
+0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,0x28,0x00,0x82,0x10,
+0xf5,0xff,0x02,0x24,0x02,0x00,0x82,0x28,0x39,0x00,0x40,0x14,0x02,0x00,0x02,0x24,
+0x2e,0x00,0x82,0x10,0xe9,0xff,0x02,0x24,0x03,0x00,0x02,0x24,0x24,0x00,0x82,0x10,
+0x3e,0x00,0x63,0x30,0x05,0x00,0xc4,0x24,0x96,0x09,0x00,0x08,0x00,0x00,0x00,0x00,
+0x04,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x42,0x20,0x04,0x00,0x96,0x09,0x00,0x08,
+0x96,0xff,0x84,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,
+0x42,0x21,0x04,0x00,0x0e,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,0x02,0x00,0x82,0x28,
+0x1d,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x14,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,
+0x03,0x00,0x02,0x24,0xeb,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,
+0xdd,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0xba,0x09,0x00,0x08,0x05,0x00,0xc4,0x24,
+0x40,0x10,0x02,0x00,0xf5,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
+0x3e,0x00,0x63,0x30,0x23,0x30,0x43,0x00,0xba,0x09,0x00,0x08,0x05,0x00,0xc4,0x24,
+0xdd,0xff,0x02,0x24,0xda,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0x40,0x10,0x02,0x00,
+0xe9,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00,0x3e,0x00,0x63,0x30,
+0xda,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0xd2,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,
+0x40,0x10,0x02,0x00,0xf8,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
+0xcc,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,0xf8,0xff,0x02,0x24,0xda,0x09,0x00,0x08,
+0x23,0x30,0x43,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,
+0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14,0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c,
+0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30,0x40,0x20,0x04,0x00,0x96,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf0,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,
+0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,
+0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0xf0,0x63,0xa4,0xac,0x00,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0x96,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf4,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,
+0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,
+0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0xf4,0x63,0xa4,0xac,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00,
+0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0xf4,0x63,0xa2,0xac,
+0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0xf0,0x63,0xa2,0xac,0x00,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0x96,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf4,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14,0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00,
+0x1b,0x0a,0x00,0x08,0xf4,0x63,0xa4,0xac,0x00,0x21,0x03,0x00,0x07,0x0a,0x00,0x08,
+0xf0,0x63,0xa4,0xac,0x98,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x58,0x00,0xb6,0xaf,
+0x64,0x00,0xbf,0xaf,0x60,0x00,0xbe,0xaf,0x5c,0x00,0xb7,0xaf,0x54,0x00,0xb5,0xaf,
+0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf,0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf,
+0x40,0x00,0xb0,0xaf,0x68,0x15,0x56,0x24,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,
+0x00,0x00,0x43,0x8c,0xa4,0x65,0xc7,0x8e,0x00,0x00,0x00,0x00,0x34,0x00,0xe3,0x10,
+0xa8,0x65,0xc3,0xae,0x2b,0x10,0x67,0x00,0xaa,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,
+0xd4,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24,0x78,0x65,0x83,0x94,
+0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00,0x19,0x00,0x40,0x1a,0x25,0x98,0x62,0x00,
+0x21,0xf0,0x80,0x00,0x21,0xb8,0x80,0x00,0x01,0x00,0x15,0x24,0x21,0x20,0x00,0x00,
+0x21,0x80,0x93,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0xa0,0x10,
+0x01,0x00,0x22,0x26,0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,
+0x24,0x10,0x43,0x00,0x1f,0x00,0x44,0x10,0x06,0x00,0x22,0x26,0xff,0xff,0x51,0x30,
+0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x35,0x00,0x55,0x10,0x00,0x00,0x00,0x00,
+0x80,0x20,0x11,0x00,0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0x38,0x00,0xa4,0x8f,0x70,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x08,0x04,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c,
+0x21,0x38,0x00,0x00,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c,
+0xa4,0x65,0xc7,0x8e,0x00,0x00,0x00,0x00,0xce,0xff,0xe3,0x14,0xa8,0x65,0xc3,0xae,
+0x25,0xb0,0x03,0x3c,0x00,0x01,0x62,0x34,0x00,0x00,0x47,0xac,0x7f,0x0a,0x00,0x08,
+0xa4,0x65,0xc7,0xae,0xbc,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xbc,0x4c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30,
+0x65,0x00,0x62,0x10,0x21,0x28,0xc0,0x03,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24,
+0x5a,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24,
+0x04,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0x73,0x0a,0x00,0x08,
+0x06,0x00,0x22,0x26,0xc8,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xc8,0x4c,0xc2,0xaf,0x00,0x00,0x05,0x8e,0x73,0x0a,0x00,0x08,0x06,0x00,0x22,0x26,
+0x00,0x40,0xe2,0x8e,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30,
+0x05,0x00,0x55,0x10,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,
+0x78,0x0a,0x00,0x08,0xff,0xff,0x51,0x30,0x02,0x40,0xe2,0x92,0x00,0x00,0x00,0x00,
+0x1f,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,0x18,0x00,0x40,0x14,0x02,0x17,0x03,0x00,
+0x03,0x00,0x44,0x30,0x08,0x00,0x80,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00,
+0x12,0x00,0x40,0x14,0x03,0x00,0x02,0x24,0x11,0x00,0x82,0x10,0x02,0x80,0x03,0x3c,
+0x10,0x00,0x80,0x10,0x68,0x15,0x63,0x24,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00,
+0xec,0xff,0x83,0x8e,0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x28,0x80,0x02,
+0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0x20,0x40,0x00,0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x68,0x15,0x63,0x24,0x02,0x40,0x62,0x90,0x00,0x00,0x00,0x00,0x88,0x00,0x55,0x10,
+0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x02,0x40,0x83,0x90,
+0x02,0x00,0x02,0x24,0x6a,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,
+0x4c,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
+0x08,0x00,0x55,0x10,0x02,0x80,0x04,0x3c,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,
+0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0x78,0x0a,0x00,0x08,
+0xff,0xff,0x51,0x30,0xd0,0x02,0x02,0x24,0x68,0x15,0x84,0x24,0xe8,0x63,0x82,0xac,
+0x00,0x00,0x05,0x8e,0xed,0x0a,0x00,0x08,0xc2,0x13,0x05,0x00,0xc4,0x4c,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc4,0x4c,0xa2,0xac,0x0c,0x00,0x04,0x8e,
+0x9f,0x0a,0x00,0x08,0x3f,0x00,0x83,0x30,0xc0,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x24,0xc0,0x4c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0x9b,0x0a,0x00,0x08,
+0x3f,0x00,0x83,0x30,0xac,0x65,0xc2,0x8e,0xff,0xff,0x71,0x30,0x23,0x10,0x47,0x00,
+0xff,0xff,0x50,0x30,0x21,0x18,0x11,0x02,0xff,0xff,0x72,0x30,0x54,0x4f,0x00,0x0c,
+0x21,0x20,0x40,0x02,0x7d,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f,
+0xa4,0x65,0xc6,0x8e,0x21,0x38,0x00,0x02,0x08,0x00,0x62,0x8c,0x08,0x00,0x04,0x24,
+0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x74,0x65,0xc3,0xae,
+0x10,0x01,0x00,0x0c,0x78,0x65,0xc2,0xae,0x4d,0x01,0x00,0x0c,0x08,0x00,0x04,0x24,
+0x78,0x65,0xc5,0x8e,0x25,0xb0,0x04,0x3c,0x24,0x10,0x02,0x3c,0x21,0x28,0xb0,0x00,
+0x00,0x01,0x90,0x34,0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,0x08,0x00,0x04,0x24,
+0x24,0x10,0x06,0x3c,0xa4,0x65,0xc2,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0xa8,0x65,0xc3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0xa4,0x65,0xc3,0xae,
+0xa4,0x65,0xc2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,0x5e,0x0a,0x00,0x08,
+0x02,0x80,0x02,0x3c,0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,0x54,0x4f,0x00,0x0c,
+0x21,0x20,0x40,0x02,0x5c,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f,
+0xa4,0x65,0xc6,0x8e,0x08,0x00,0x04,0x24,0x08,0x00,0x62,0x8c,0x21,0x38,0x40,0x02,
+0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x74,0x65,0xc3,0xae,
+0x10,0x01,0x00,0x0c,0x78,0x65,0xc2,0xae,0xa8,0x65,0xc3,0x8e,0x08,0x00,0x04,0x24,
+0x4d,0x01,0x00,0x0c,0xa4,0x65,0xc3,0xae,0xa4,0x65,0xc3,0x8e,0x25,0xb0,0x04,0x3c,
+0x00,0x01,0x82,0x34,0x00,0x00,0x43,0xac,0x5e,0x0a,0x00,0x08,0x02,0x80,0x02,0x3c,
+0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,
+0x08,0x00,0x42,0x28,0x91,0xff,0x40,0x10,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
+0x8e,0xff,0x40,0x14,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00,0xec,0xff,0x83,0x8e,
+0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x28,0x80,0x02,0x21,0x20,0x00,0x02,
+0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,
+0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0xe4,0x0a,0x00,0x08,0x25,0xb0,0x03,0x3c,
+0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,
+0x08,0x00,0x42,0x28,0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x03,0x00,
+0x03,0x00,0x42,0x30,0x0c,0x00,0x40,0x10,0x80,0x10,0x11,0x00,0x00,0xc0,0x02,0x3c,
+0x24,0x10,0x62,0x00,0x6c,0xff,0x40,0x14,0x02,0x80,0x04,0x3c,0x02,0x17,0x03,0x00,
+0x03,0x00,0x42,0x30,0x03,0x00,0x03,0x24,0x68,0xff,0x43,0x10,0x68,0x15,0x84,0x24,
+0x64,0xff,0x40,0x10,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00,0xec,0xff,0x83,0x8e,
+0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x21,0x28,0x80,0x02,
+0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,
+0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0x21,0x20,0x00,0x02,0xf1,0x09,0x00,0x0c,
+0x21,0x28,0x80,0x02,0xde,0x0a,0x00,0x08,0x02,0x80,0x04,0x3c,0x25,0xb0,0x04,0x3c,
+0x44,0x44,0x02,0x3c,0xbc,0x02,0x83,0x34,0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac,
+0x80,0x0a,0x00,0x08,0x02,0x80,0x02,0x3c,0xa8,0x65,0xc5,0x8e,0x25,0xb0,0x02,0x3c,
+0x00,0x01,0x43,0x34,0xbc,0x02,0x44,0x34,0x66,0x66,0x02,0x3c,0x66,0x66,0x42,0x34,
+0x00,0x00,0x65,0xac,0x00,0x00,0x82,0xac,0x7f,0x0a,0x00,0x08,0xa4,0x65,0xc5,0xae,
+0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0x2a,0xb0,0x04,0x3c,0x18,0x03,0xc5,0x34,
+0x70,0x2e,0x42,0x24,0x00,0x00,0xa2,0xac,0x22,0x00,0x83,0x34,0x1a,0x00,0x85,0x34,
+0x00,0x00,0x67,0x94,0x06,0x00,0x84,0x34,0x00,0x00,0xa2,0x94,0x00,0x00,0x83,0x94,
+0xff,0x00,0xed,0x30,0xff,0x00,0x42,0x30,0x21,0x68,0x4d,0x00,0xff,0x00,0x63,0x30,
+0x21,0x68,0x6d,0x00,0x68,0x03,0xc2,0x34,0x02,0x80,0x07,0x3c,0x00,0x00,0x4d,0xa4,
+0x68,0x15,0xe7,0x24,0xc6,0x00,0xc3,0x34,0xca,0x00,0xc4,0x34,0x00,0x00,0x6b,0x90,
+0x60,0x4b,0xe5,0x8c,0x00,0x00,0x82,0x90,0xcc,0x00,0xc3,0x34,0x00,0x00,0x68,0x90,
+0xd4,0x00,0xc4,0x34,0x64,0x4b,0xe3,0x8c,0x00,0x00,0x8a,0x90,0x61,0x4b,0xec,0x90,
+0xff,0x00,0x04,0x3c,0x00,0x4a,0x0d,0x00,0x23,0x48,0x2d,0x01,0x24,0x28,0xa4,0x00,
+0xff,0x00,0x6d,0x31,0xff,0x00,0x42,0x30,0x21,0x10,0xa2,0x01,0x24,0x18,0x64,0x00,
+0x02,0x2c,0x05,0x00,0x69,0x4b,0xe4,0x90,0xff,0x00,0x08,0x31,0x21,0x60,0x85,0x01,
+0x02,0x1c,0x03,0x00,0x21,0x10,0x48,0x00,0xff,0x00,0x4a,0x31,0x21,0x10,0x4a,0x00,
+0x21,0x60,0x83,0x01,0x21,0x60,0x84,0x01,0xff,0xff,0x4d,0x30,0x23,0x18,0x8d,0x01,
+0xff,0xff,0x6c,0x30,0xff,0xff,0x29,0x31,0x6a,0x03,0xc2,0x34,0x6c,0x03,0xc3,0x34,
+0x1f,0x03,0xc5,0x34,0x2b,0x20,0x2c,0x01,0x6e,0x03,0xc6,0x34,0x00,0x00,0x49,0xa4,
+0x00,0x00,0x6d,0xa4,0x00,0x00,0xcc,0xa4,0x05,0x00,0x80,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0xa3,0xa0,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x70,0x9a,0x64,0xac,
+0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x70,0x9a,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0xac,0x2f,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,0x1e,0x00,0xa2,0x10,
+0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,0x03,0x00,0x02,0x24,
+0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,
+0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,0x06,0x00,0x02,0x24,
+0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,0x23,0x10,0x44,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,0x23,0x18,0x62,0x00,
+0x01,0x0c,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,
+0x01,0x0c,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,0x70,0x9a,0x45,0x8c,
+0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x68,0x30,0x63,0x24,
+0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,0x06,0x00,0xa2,0x2c,
+0x09,0x00,0x40,0x14,0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,0x0f,0x00,0xa2,0x10,
+0x00,0x11,0x04,0x00,0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x29,0x0c,0x00,0x08,0x40,0x20,0x02,0x00,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x29,0x0c,0x00,0x08,0x80,0x20,0x02,0x00,0x23,0x10,0x44,0x00,
+0x29,0x0c,0x00,0x08,0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24,
+0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30,
+0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0x4f,0x0c,0x00,0x08,
+0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,
+0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14,
+0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,
+0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c,
+0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c,
+0x63,0x0c,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0,
+0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24,
+0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30,
+0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36,
+0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,
+0xa8,0x00,0x14,0x36,0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,
+0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae,
+0x00,0x00,0x00,0xae,0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,
+0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,
+0x00,0x00,0x22,0xa6,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c,0x64,0x4b,0x44,0x8c,
+0xfc,0x37,0x02,0x24,0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae,
+0x00,0x00,0x22,0xa6,0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0xc8,0xff,0xbd,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,
+0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40,
+0x01,0x00,0xc1,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c,
+0x40,0x00,0x30,0x36,0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24,
+0x00,0x00,0xc2,0xa3,0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0x1a,0x0c,0x00,0x0c,
+0x32,0x00,0x04,0x24,0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,
+0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6,
+0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0x1a,0x0c,0x00,0x0c,
+0x32,0x00,0x04,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0x1a,0x0c,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36,
+0x24,0x10,0x43,0x00,0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36,
+0xa4,0x00,0x35,0x36,0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae,
+0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x12,0xa6,0x3a,0x0c,0x00,0x0c,0x56,0x01,0x31,0x36,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c,
+0x64,0x4b,0x44,0x8c,0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae,
+0x00,0x00,0x65,0xae,0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3,
+0x00,0x60,0x96,0x40,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,
+0x00,0x00,0xa2,0x94,0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,
+0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,
+0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,
+0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,
+0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x25,0xb0,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,
+0x24,0x10,0x43,0x00,0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xff,0xff,0xc6,0x30,0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10,0x11,0x00,0xc3,0x28,
+0x06,0x00,0x60,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x0d,0x00,0xc2,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x06,0x00,0xc2,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa4,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0xa5,0x24,
+0x00,0x2c,0x05,0x00,0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00,0xff,0xff,0x87,0x30,
+0x00,0x00,0x43,0xa0,0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00,0x21,0x30,0x40,0x00,
+0x07,0x10,0xa7,0x00,0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30,0x00,0x00,0x42,0x38,
+0x02,0x00,0x63,0x34,0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0,0x04,0x00,0x63,0x34,
+0x00,0x00,0xc3,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,
+0xff,0xff,0x42,0x24,0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0x04,0x00,0x02,0x24,
+0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0xa2,0x24,
+0x00,0x2c,0x02,0x00,0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04,0x07,0x10,0xa7,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,
+0x00,0x00,0x43,0x90,0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,
+0xff,0x00,0x65,0x30,0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00,0x21,0x30,0x40,0x00,
+0x01,0x00,0x08,0x24,0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30,0x05,0x00,0x60,0x10,
+0x04,0x00,0x02,0x24,0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00,0xff,0xff,0x47,0x30,
+0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,
+0xfb,0x00,0xa5,0x30,0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24,0x00,0x24,0x02,0x00,
+0x03,0x24,0x04,0x00,0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0xe0,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,
+0x0a,0x00,0x10,0x36,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x00,0x00,0x02,0x92,
+0xff,0xff,0x91,0x30,0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30,0x80,0x00,0x43,0x34,
+0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,
+0x00,0x00,0x03,0xa2,0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,
+0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x64,0x0d,0x00,0x0c,
+0x06,0x00,0x04,0x24,0x42,0x20,0x11,0x00,0x64,0x0d,0x00,0x0c,0x06,0x00,0x05,0x24,
+0x8a,0x0d,0x00,0x0c,0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0xff,0xff,0xb1,0x30,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,
+0x21,0x90,0xc0,0x00,0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30,0xb1,0x0d,0x00,0x0c,
+0x21,0x20,0x00,0x02,0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26,0x00,0x00,0x42,0xa6,
+0xff,0xff,0x71,0x30,0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16,0x02,0x00,0x52,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x0a,0x00,0x68,0x34,
+0x00,0x00,0x02,0x91,0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30,0x1f,0x00,0xa0,0x10,
+0xff,0x00,0x47,0x30,0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34,0x0b,0x00,0x6b,0x34,
+0xc0,0xff,0x0a,0x24,0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00,0xff,0x00,0x47,0x30,
+0x00,0x00,0x64,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,
+0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,
+0x21,0x40,0xa0,0x01,0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,
+0xc0,0x00,0xe3,0x30,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8d,
+0xfc,0xff,0xa3,0x24,0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30,0x00,0x00,0xc2,0xac,
+0xff,0x00,0x84,0x30,0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00,0xff,0xff,0xa5,0x30,
+0xc0,0x50,0x04,0x00,0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x25,0xb0,0x07,0x3c,
+0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00,0x01,0x80,0x08,0x3c,
+0x25,0x20,0xa3,0x00,0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01,0x44,0x02,0xe7,0x34,
+0x00,0x00,0xe4,0xac,0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90,0x02,0x00,0xc4,0x90,
+0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,
+0x00,0x1c,0x03,0x00,0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00,0x00,0x2e,0x05,0x00,
+0x25,0x40,0x48,0x01,0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,
+0x00,0x00,0x28,0xad,0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00,0x21,0x10,0xa8,0x01,
+0x01,0x00,0x43,0x90,0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90,0x03,0x00,0x46,0x90,
+0x00,0x1a,0x03,0x00,0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa4,0x00,
+0x00,0x36,0x06,0x00,0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01,0x25,0x20,0xa6,0x00,
+0x10,0x00,0x03,0x2d,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x22,0xad,
+0xee,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00,
+0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00,
+0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24,
+0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00,
+0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c,
+0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,
+0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24,
+0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00,
+0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00,
+0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0,
+0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x74,0x9a,0x42,0x24,
+0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac,
+0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac,
+0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0x7a,0x0e,0x00,0x08,
+0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0x7a,0x0e,0x00,0x08,0x10,0x00,0x82,0xac,
+0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,
+0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x14,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x80,0x16,0x3c,
+0x02,0x80,0x14,0x3c,0x02,0x80,0x11,0x3c,0x02,0x80,0x15,0x3c,0x24,0x7e,0x24,0x8e,
+0x25,0xb0,0x02,0x3c,0x88,0x3a,0xc3,0x26,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x74,0x9a,0x90,0x8e,0x18,0x00,0x80,0x10,0x74,0x9a,0x82,0x26,0x15,0x00,0x02,0x12,
+0x00,0x00,0x00,0x00,0x21,0x98,0x40,0x00,0x01,0x00,0x12,0x24,0x14,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x1d,0x00,0x52,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0x24,0x7e,0x22,0x8e,0x00,0x00,0x00,0x00,
+0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0c,0x00,0x04,0xae,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0xef,0xff,0x13,0x16,
+0x00,0x00,0x00,0x00,0x24,0x7e,0x20,0xae,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00,
+0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0xaf,0x0e,0x00,0x08,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,
+0x00,0x00,0x00,0x00,0xc9,0x0e,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,
+0x24,0x7e,0x22,0x8e,0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,
+0xe7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,
+0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,0xc9,0x0e,0x00,0x08,
+0x0c,0x00,0x03,0xae,0x02,0x80,0x02,0x3c,0x60,0x79,0x43,0x8c,0xff,0x00,0xa5,0x30,
+0x25,0xb0,0x02,0x3c,0x42,0x18,0x03,0x00,0x21,0x30,0xa2,0x00,0x01,0x00,0x63,0x30,
+0x01,0x00,0x02,0x24,0x10,0x00,0xa7,0x2c,0x04,0x00,0x62,0x10,0xff,0x00,0x84,0x30,
+0x60,0x01,0xc4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,
+0x10,0x00,0xa2,0x34,0xfa,0xff,0xe0,0x10,0x21,0x40,0x43,0x00,0x60,0x01,0xc4,0xa0,
+0x60,0x01,0x04,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,
+0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,
+0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,
+0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0xa5,0x30,
+0x04,0x00,0xa2,0x2c,0x14,0x00,0x40,0x10,0xff,0x00,0x84,0x30,0x02,0x80,0x03,0x3c,
+0xee,0x7d,0x62,0x90,0x00,0x00,0x00,0x00,0xef,0xff,0x42,0x24,0xff,0x00,0x42,0x30,
+0x02,0x00,0x42,0x2c,0x0e,0x00,0x40,0x10,0x02,0x00,0x03,0x24,0x24,0x00,0x83,0x10,
+0x0f,0x10,0x02,0x3c,0x03,0x00,0x82,0x28,0x14,0x00,0x40,0x10,0x03,0x00,0x02,0x24,
+0x01,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0xff,0xff,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x35,0x00,0x83,0x10,0x0f,0x1f,0x02,0x3c,0x03,0x00,0x82,0x28,0x16,0x00,0x40,0x10,
+0x03,0x00,0x02,0x24,0x01,0x00,0x02,0x24,0xf4,0xff,0x82,0x14,0x00,0x00,0x00,0x00,
+0x0f,0x1f,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,0xf0,0xff,0x82,0x14,
+0xff,0x1f,0x02,0x3c,0x01,0x00,0x02,0x24,0x29,0x00,0xa2,0x10,0x0f,0x10,0x02,0x3c,
+0x02,0x00,0xa2,0x28,0x1f,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x28,0x00,0xa3,0x10,
+0x00,0x00,0x00,0x00,0xe5,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,0xe1,0xff,0x82,0x14,0xff,0x1f,0x02,0x3c,
+0x01,0x00,0x02,0x24,0x1c,0x00,0xa2,0x10,0x0f,0x00,0x02,0x3c,0x02,0x00,0xa2,0x28,
+0x0b,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x00,0xa3,0x10,0x00,0x00,0x00,0x00,
+0xd6,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
+0x00,0xf0,0x42,0x34,0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,
+0xce,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
+0x15,0xf0,0x42,0x34,0xc9,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0x15,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,
+0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,
+0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0x0f,0x00,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01,
+0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00,
+0x68,0x15,0x42,0x24,0x21,0x18,0x62,0x00,0x80,0x51,0x66,0x8c,0x21,0x38,0x60,0x00,
+0x86,0x51,0x60,0xa0,0x87,0x51,0x60,0xa0,0x1c,0x00,0x05,0x24,0x7b,0x0f,0x00,0x08,
+0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00,
+0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24,
+0x86,0x51,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x21,0x18,0x43,0x00,
+0x80,0x51,0x66,0x8c,0x21,0x28,0x00,0x00,0x8f,0x0f,0x00,0x08,0x01,0x00,0x07,0x24,
+0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00,
+0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24,
+0x08,0x00,0xe0,0x03,0x87,0x51,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x02,0x80,0x16,0x3c,0x30,0x00,0xbe,0xaf,
+0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x01,0x00,0x15,0x24,0x21,0x88,0x00,0x00,0x68,0x15,0xde,0x26,
+0x21,0xa0,0x00,0x00,0x21,0x90,0x00,0x00,0x25,0xb0,0x17,0x3c,0x34,0x00,0xbf,0xaf,
+0x1c,0x00,0xb3,0xaf,0xb0,0x0f,0x00,0x08,0x10,0x00,0xb0,0xaf,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0x2e,0x00,0x40,0x10,0x94,0x00,0x94,0x26,
+0x68,0x15,0xc2,0x26,0x21,0x30,0x42,0x02,0x84,0x51,0xc5,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x13,0x05,0x00,0x01,0x00,0x42,0x30,0xf4,0xff,0x55,0x14,0x42,0x1a,0x05,0x00,
+0x74,0x51,0xc2,0x8c,0x07,0x00,0x64,0x30,0x02,0x11,0x02,0x00,0x7f,0x00,0x43,0x30,
+0x2d,0x00,0x95,0x10,0x07,0x00,0xb3,0x30,0x02,0x00,0x82,0x28,0x3a,0x00,0x40,0x14,
+0x02,0x00,0x02,0x24,0x30,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x3c,0x00,0x82,0x10,
+0x1a,0x00,0x62,0x2c,0x21,0x80,0x9e,0x02,0x84,0x51,0x02,0x8e,0x04,0x00,0x63,0x2e,
+0x42,0x12,0x02,0x00,0x0a,0x00,0x60,0x10,0x07,0x00,0x44,0x30,0x0f,0x0f,0x00,0x0c,
+0x21,0x28,0x60,0x02,0x80,0x20,0x13,0x00,0x7c,0x51,0x02,0xae,0x21,0x20,0x97,0x00,
+0x84,0x01,0x83,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x62,0x00,0x80,0x51,0x03,0xae,
+0x6a,0x0f,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x10,0x37,0x02,0x01,0x00,0x31,0x26,
+0x60,0x01,0x43,0x90,0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0xd4,0xff,0x40,0x14,
+0x94,0x00,0x94,0x26,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x32,0x00,0x62,0x2c,0xda,0xff,0x40,0x10,
+0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x04,0x42,0x34,
+0xc5,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac,0x38,0x00,0x62,0x2c,0x12,0x00,0x40,0x14,
+0x14,0x00,0x62,0x2c,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x02,0x42,0x34,
+0xc5,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac,0xcb,0xff,0x80,0x14,0x21,0x80,0x9e,0x02,
+0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0xc6,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac,
+0xc5,0xff,0x40,0x14,0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,
+0xf0,0x0f,0x00,0x08,0x00,0x04,0x42,0x34,0xbf,0xff,0x40,0x10,0x21,0x80,0x9e,0x02,
+0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x06,0x42,0x34,0xc6,0x0f,0x00,0x08,
+0x84,0x51,0xc2,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
+0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x80,0x10,0x00,
+0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,
+0x14,0x00,0xb1,0xaf,0x84,0x51,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,
+0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,
+0x7c,0x51,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,
+0x24,0x10,0x45,0x00,0x6a,0x0f,0x00,0x0c,0x80,0x51,0x02,0xae,0x86,0x51,0x04,0x92,
+0xe9,0x0e,0x00,0x0c,0xff,0x00,0x45,0x32,0x86,0x51,0x04,0x92,0xff,0x0e,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,
+0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,
+0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0xa0,0x9f,0x63,0x24,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x90,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x68,0x00,0xbe,0xaf,0x64,0x00,0xb7,0xaf,
+0x60,0x00,0xb6,0xaf,0x5c,0x00,0xb5,0xaf,0x54,0x00,0xb3,0xaf,0x50,0x00,0xb2,0xaf,
+0x6c,0x00,0xbf,0xaf,0x58,0x00,0xb4,0xaf,0x4c,0x00,0xb1,0xaf,0x48,0x00,0xb0,0xaf,
+0xd0,0x9f,0x42,0x24,0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24,0x10,0x00,0xa3,0xaf,
+0x21,0x98,0x00,0x00,0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,
+0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,
+0x21,0xb0,0x00,0x00,0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf,
+0x30,0x00,0xa0,0xaf,0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf,
+0x40,0x00,0xa0,0xaf,0x21,0x90,0x80,0x02,0x84,0x51,0x42,0x8e,0x00,0x00,0x00,0x00,
+0x02,0x13,0x02,0x00,0x01,0x00,0x42,0x30,0x6c,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,
+0x21,0x10,0x62,0x02,0x60,0x01,0x44,0x90,0x6c,0x51,0x43,0x8e,0x68,0x51,0x46,0x8e,
+0xff,0x00,0x91,0x30,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x24,0x02,
+0x73,0x44,0x44,0x90,0x56,0x44,0x45,0x90,0x50,0x51,0x47,0x8e,0x18,0x00,0x64,0x00,
+0x12,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,
+0x12,0x30,0x00,0x00,0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x25,0x01,0x40,0x14,
+0x23,0x10,0xe6,0x00,0x50,0x51,0x42,0xae,0x6c,0x51,0x44,0x8e,0x68,0x51,0x47,0x8e,
+0x54,0x51,0x48,0x8e,0x58,0x51,0x45,0x8e,0x60,0x51,0x46,0x8e,0x64,0x51,0x43,0x8e,
+0x21,0x38,0xe4,0x00,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x24,0x02,
+0x21,0x40,0x05,0x01,0x21,0x30,0xc3,0x00,0xca,0x44,0x42,0x90,0x50,0x51,0x4a,0x8e,
+0x0c,0x00,0xe0,0x10,0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,
+0x02,0x80,0x02,0x3c,0x07,0x00,0x22,0x2e,0x93,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,
+0x0c,0x00,0x02,0x24,0x8f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24,0x8e,0x01,0x22,0x12,
+0xc0,0x10,0x07,0x00,0x81,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
+0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02,0xc2,0x51,0x85,0x90,
+0xec,0x44,0x62,0x8c,0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,
+0x76,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xe0,0x51,0x42,0x8e,0x01,0x00,0x07,0x24,
+0x04,0x18,0x27,0x02,0x24,0x10,0x43,0x00,0x04,0x01,0x40,0x10,0x1c,0x00,0x22,0x2e,
+0x21,0x28,0x51,0x02,0x88,0x51,0xa6,0x90,0xc2,0x51,0xa2,0x90,0x0a,0x00,0x04,0x24,
+0xff,0x00,0xc3,0x30,0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xfb,0x00,0x60,0x10,
+0x1c,0x00,0x22,0x2e,0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x8c,0x01,0x64,0x10,
+0x88,0x51,0xa2,0xa0,0x02,0x80,0x04,0x3c,0x68,0x15,0x85,0x24,0x80,0x10,0x11,0x00,
+0x21,0x10,0x45,0x00,0x60,0x45,0x44,0x8c,0xec,0x44,0x43,0x8c,0x21,0x30,0xc5,0x02,
+0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,
+0x50,0x51,0xca,0xac,0xec,0x65,0xa3,0x8c,0xff,0xff,0x02,0x34,0x03,0x00,0x62,0x10,
+0x21,0x20,0x20,0x02,0xe9,0x0e,0x00,0x0c,0xff,0x00,0x65,0x32,0xff,0x0e,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,
+0x0a,0x20,0x62,0x00,0xbc,0x00,0x60,0x12,0x10,0x00,0xa4,0xaf,0x02,0x80,0x03,0x3c,
+0x68,0x15,0x62,0x24,0x21,0x10,0xa2,0x02,0x64,0x51,0x40,0xac,0x68,0x51,0x40,0xac,
+0x6c,0x51,0x40,0xac,0x54,0x51,0x40,0xac,0x58,0x51,0x40,0xac,0x5c,0x51,0x40,0xac,
+0x60,0x51,0x40,0xac,0x40,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0x8f,0x01,0x00,0x73,0x26,
+0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x40,0x00,0xa4,0xaf,0x3c,0x00,0xa2,0xaf,
+0x38,0x00,0xa4,0x8f,0x34,0x00,0xa2,0x8f,0x20,0x00,0x63,0x2a,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x38,0x00,0xa4,0xaf,0x34,0x00,0xa2,0xaf,0x30,0x00,0xa4,0x8f,
+0x2c,0x00,0xa2,0x8f,0x94,0x00,0x52,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,
+0x30,0x00,0xa4,0xaf,0x2c,0x00,0xa2,0xaf,0x28,0x00,0xa4,0x8f,0x24,0x00,0xa2,0x8f,
+0x94,0x00,0xd6,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0xaf,
+0x24,0x00,0xa2,0xaf,0x20,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0x8f,0x94,0x00,0xde,0x27,
+0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x20,0x00,0xa4,0xaf,0x1c,0x00,0xa2,0xaf,
+0x18,0x00,0xa4,0x8f,0x14,0x00,0xa2,0x8f,0x94,0x00,0x94,0x26,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0xaf,0x14,0x00,0xa2,0xaf,0x94,0x00,0xf7,0x26,
+0x59,0xff,0x60,0x14,0x94,0x00,0xb5,0x26,0x10,0x00,0xa3,0x8f,0x6c,0x00,0xbf,0x8f,
+0x68,0x00,0xbe,0x8f,0x64,0x00,0xb7,0x8f,0x60,0x00,0xb6,0x8f,0x5c,0x00,0xb5,0x8f,
+0x58,0x00,0xb4,0x8f,0x54,0x00,0xb3,0x8f,0x50,0x00,0xb2,0x8f,0x4c,0x00,0xb1,0x8f,
+0x48,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x70,0x00,0xbd,0x27,
+0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x87,0x00,0xe0,0x10,
+0x00,0x00,0x00,0x00,0x87,0x00,0x20,0x15,0x02,0x80,0x03,0x3c,0x40,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0xa7,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x20,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,0x68,0x15,0x88,0x24,
+0x21,0x20,0x48,0x00,0x21,0x30,0x91,0x00,0xe0,0x51,0x83,0x8c,0x01,0x00,0x05,0x24,
+0x04,0x10,0x25,0x02,0xa5,0x51,0xc7,0x90,0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,
+0xe0,0x51,0x83,0xac,0x09,0x00,0xe5,0x10,0x88,0x51,0xc0,0xa0,0x1c,0x00,0xa3,0x8f,
+0x21,0x38,0x00,0x00,0x21,0x20,0x68,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,
+0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xc2,0x51,0x60,0xa0,0x02,0x80,0x04,0x3c,
+0x68,0x15,0x83,0x24,0x18,0x00,0xa4,0x8f,0x21,0x50,0x60,0x00,0x21,0x38,0x00,0x00,
+0x21,0x10,0x83,0x00,0x21,0x10,0x51,0x00,0xa5,0x51,0x40,0xa0,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0xe4,0x9e,0x49,0x24,0x70,0x9e,0x68,0x24,0x80,0x18,0x07,0x00,
+0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,
+0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,0xec,0x44,0x65,0xac,
+0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x15,0x00,0x20,0x12,0x02,0x80,0x05,0x3c,
+0x87,0x51,0x82,0x92,0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00,0x10,0x00,0x40,0x14,
+0x02,0x80,0x03,0x3c,0x14,0x00,0xa4,0x8f,0x68,0x15,0x62,0x24,0x21,0x10,0x82,0x00,
+0x87,0x51,0x45,0x90,0x80,0x51,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,
+0x24,0x10,0x83,0x00,0x06,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,
+0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,
+0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24,0xe8,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x04,0x3c,0x68,0x15,0x83,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00,
+0x60,0x45,0x44,0x8c,0xec,0x44,0x43,0x8c,0xee,0x7d,0xa5,0x90,0x40,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xd6,0x00,0xa2,0x10,
+0x82,0x50,0x03,0x00,0xe0,0x51,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02,
+0x25,0x18,0x62,0x00,0xe0,0x51,0x83,0xae,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,
+0x21,0x10,0xe3,0x02,0x50,0x51,0x4a,0xac,0xec,0x65,0x64,0x8c,0xff,0xff,0x02,0x34,
+0x44,0xff,0x82,0x14,0x21,0x20,0x20,0x02,0xff,0x0e,0x00,0x0c,0x21,0x20,0x20,0x02,
+0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,
+0x46,0xff,0x60,0x16,0x10,0x00,0xa4,0xaf,0x02,0x80,0x02,0x3c,0x68,0x15,0x50,0x24,
+0x58,0x51,0x05,0x96,0x54,0x51,0x02,0x96,0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00,
+0x21,0x28,0x45,0x00,0x82,0x4f,0x00,0x0c,0x68,0x0c,0x24,0x36,0x64,0x51,0x02,0x8e,
+0x60,0x51,0x05,0x8e,0x5c,0x51,0x03,0x96,0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00,
+0x00,0x2c,0x05,0x00,0x82,0x4f,0x00,0x0c,0x21,0x28,0x65,0x00,0xf8,0x10,0x00,0x08,
+0x02,0x80,0x03,0x3c,0xa2,0x10,0x00,0x08,0x50,0x51,0x40,0xae,0x27,0xff,0x20,0x11,
+0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,
+0x60,0x45,0x64,0x8c,0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x1f,0xff,0x80,0x10,
+0x00,0x00,0x00,0x00,0x49,0x11,0x00,0x08,0x00,0x00,0x00,0x00,0x0a,0xff,0x40,0x10,
+0x02,0x80,0x04,0x3c,0x21,0x20,0x51,0x02,0xa5,0x51,0x83,0x90,0x01,0x00,0x02,0x24,
+0x78,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x40,0x00,0xa3,0x8f,0x68,0x15,0x42,0x24,
+0x21,0x20,0x62,0x00,0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,
+0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xc2,0x51,0x60,0xa0,0x3c,0x00,0xa2,0x8f,
+0x02,0x80,0x04,0x3c,0x68,0x15,0x85,0x24,0x21,0x30,0x45,0x00,0xe0,0x51,0xc2,0x8c,
+0x01,0x00,0x03,0x24,0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd1,0x00,
+0x24,0x10,0x43,0x00,0xa5,0x51,0x80,0xa0,0xe0,0x51,0xc2,0xac,0x12,0x00,0x20,0x16,
+0x88,0x51,0x80,0xa0,0x86,0x51,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,
+0x01,0x00,0x07,0x24,0x38,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x65,0x00,
+0x86,0x51,0x44,0x90,0x80,0x51,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,
+0x8d,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,
+0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24,
+0x34,0x00,0xa2,0x8f,0x01,0x00,0x27,0x26,0x21,0x18,0x44,0x00,0x86,0x51,0x62,0x90,
+0x00,0x00,0x00,0x00,0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c,
+0x30,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x86,0x51,0x45,0x90,
+0x80,0x51,0x44,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x73,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,
+0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24,
+0x3e,0x00,0x62,0x10,0xee,0xff,0x22,0x26,0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24,
+0xbd,0xfe,0x62,0x14,0x02,0x80,0x04,0x3c,0x28,0x00,0xa2,0x8f,0x68,0x15,0x86,0x24,
+0x21,0x20,0x46,0x00,0x84,0x51,0x85,0x8c,0x01,0x00,0x03,0x24,0x42,0x13,0x05,0x00,
+0x07,0x00,0x42,0x30,0xb3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e,0xb1,0xfe,0x40,0x14,
+0x1c,0x00,0x22,0x2e,0xaf,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,
+0x24,0x10,0xa2,0x00,0x00,0x20,0x42,0x34,0x84,0x51,0x82,0xac,0x87,0x51,0x83,0x90,
+0xff,0xff,0x27,0x26,0x2a,0x18,0xe3,0x00,0xa6,0xfe,0x60,0x14,0x00,0x00,0x00,0x00,
+0x24,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00,0x87,0x51,0x45,0x90,
+0x80,0x51,0x44,0x8c,0x42,0x12,0x00,0x08,0x01,0x00,0x06,0x24,0x2a,0x10,0xe5,0x00,
+0x9c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,
+0xfa,0xff,0x43,0x14,0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24,0xdd,0x10,0x00,0x08,
+0xff,0x00,0xf1,0x30,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,0xc2,0x10,0x02,0x00,
+0x2b,0x10,0x48,0x00,0x7c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0xbd,0x10,0x00,0x08,
+0x00,0x00,0x00,0x00,0x18,0x00,0x22,0x2e,0x17,0x00,0x40,0x14,0x05,0x00,0x22,0x2e,
+0xc2,0x51,0x83,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x62,0x2c,0x8b,0xff,0x40,0x10,
+0x01,0x00,0x62,0x24,0xe3,0x11,0x00,0x08,0xc2,0x51,0x82,0xa0,0xff,0x00,0x42,0x30,
+0x02,0x00,0x42,0x2c,0xc0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x2c,0x00,0xa3,0x8f,
+0x68,0x15,0x82,0x24,0x21,0x10,0x62,0x00,0x80,0x51,0x43,0x8c,0x00,0x01,0x04,0x3c,
+0x18,0x00,0x02,0x24,0x24,0x18,0x64,0x00,0x1e,0x12,0x00,0x08,0x0b,0x88,0x43,0x00,
+0xdd,0x10,0x00,0x08,0xa5,0x51,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0xc2,0x51,0x83,0x90,0x57,0x12,0x00,0x08,0x03,0x00,0x62,0x2c,0xc2,0x51,0x83,0x90,
+0x57,0x12,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x29,0xff,0x22,0x16,
+0x02,0x80,0x02,0x3c,0xa4,0x11,0x00,0x08,0x68,0x15,0x43,0x24,0x68,0x15,0x62,0x24,
+0x21,0x20,0xc2,0x03,0x84,0x51,0x83,0x8c,0x00,0x00,0x00,0x00,0x42,0x13,0x03,0x00,
+0x07,0x00,0x42,0x30,0x12,0xff,0x40,0x10,0x14,0x00,0x22,0x2e,0x10,0xff,0x40,0x10,
+0x0c,0x00,0x22,0x2e,0x0e,0xff,0x40,0x14,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,
+0x24,0x10,0x62,0x00,0x90,0x11,0x00,0x08,0x84,0x51,0x82,0xac,0xff,0x00,0xf1,0x30,
+0x1a,0x12,0x00,0x08,0x02,0x80,0x05,0x3c,0x02,0x12,0x00,0x08,0xff,0x00,0xf1,0x30,
+0x8b,0x11,0x00,0x08,0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x38,0x00,0xb2,0xaf,0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf,0x4c,0x00,0xb7,0xaf,
+0x48,0x00,0xb6,0xaf,0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf,0x3c,0x00,0xb3,0xaf,
+0x34,0x00,0xb1,0xaf,0x30,0x00,0xb0,0xaf,0x68,0x15,0x46,0x24,0x65,0x65,0xc4,0x90,
+0x60,0x65,0xc3,0x8c,0x5c,0x65,0xc2,0x8c,0x21,0x90,0x64,0x00,0x2b,0x10,0x42,0x02,
+0x7e,0x00,0x40,0x10,0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c,0x02,0x80,0x17,0x3c,
+0x21,0xa8,0xc0,0x00,0x21,0xb0,0xc0,0x00,0xad,0x12,0x00,0x08,0x01,0x00,0x14,0x24,
+0x5c,0x65,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x73,0x00,0x40,0x10,
+0x21,0x88,0xc0,0x02,0x65,0x65,0x22,0x92,0xff,0xff,0x45,0x32,0x25,0x28,0xb7,0x00,
+0x10,0x00,0x42,0x24,0x65,0x65,0x22,0xa2,0x38,0x79,0xc4,0x27,0x60,0x45,0x00,0x0c,
+0x10,0x00,0x06,0x24,0xf8,0x63,0x23,0x8e,0x00,0x00,0x00,0x00,0x42,0x18,0x03,0x00,
+0x01,0x00,0x63,0x30,0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,
+0xd4,0x63,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00,0x1f,0x00,0x10,0x32,
+0xc0,0x48,0x10,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x55,0x00,0x84,0x51,0x45,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x1b,0x05,0x00,0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10,0x21,0x30,0xa0,0x02,
+0x25,0xb0,0x02,0x3c,0x21,0x40,0x02,0x02,0xd0,0x63,0xa7,0x8e,0xf8,0x63,0xa2,0x8e,
+0x60,0x01,0x03,0x91,0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30,0xff,0x00,0x6b,0x30,
+0x9a,0x00,0x54,0x10,0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c,0xd4,0x9f,0x84,0x24,
+0x00,0x00,0x86,0x8c,0x04,0x00,0x04,0x24,0xd0,0x63,0xc3,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x15,0x03,0x00,0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x0a,0x00,0x60,0x04,
+0x0a,0x50,0x82,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x70,0x51,0x43,0x8c,0x04,0x00,0x0a,0x24,
+0x01,0x00,0x63,0x24,0x70,0x51,0x43,0xac,0xd4,0x63,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x13,0x02,0x00,0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0xb8,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0xd0,0x63,0xc2,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,
+0xb3,0xff,0x4b,0x14,0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11,0x21,0x10,0x30,0x01,
+0xa8,0x00,0x54,0x11,0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24,0xb0,0x00,0x42,0x11,
+0x21,0x10,0x30,0x01,0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11,0x21,0x10,0x30,0x01,
+0xc0,0x00,0x44,0x11,0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x74,0x51,0xa3,0x8c,
+0x21,0x10,0x66,0x01,0x90,0x44,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,
+0xc8,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x68,0x51,0xa3,0x8c,0x80,0x10,0x0b,0x00,
+0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00,0x68,0x51,0xa3,0xac,
+0x21,0x10,0x4a,0x00,0x34,0x43,0x44,0x90,0x50,0x51,0xa3,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x64,0x00,0x50,0x51,0xa3,0xac,0x5c,0x65,0xc2,0x8e,0x10,0x00,0x52,0x26,
+0x2b,0x10,0x42,0x02,0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02,0x54,0x00,0xbf,0x8f,
+0x50,0x00,0xbe,0x8f,0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f,
+0x40,0x00,0xb4,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,
+0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27,0xd4,0x63,0x22,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30,0x90,0xff,0x60,0x10,
+0x0f,0x00,0x50,0x30,0x54,0x4f,0x00,0x0c,0x48,0x00,0x04,0x24,0x74,0xff,0x40,0x10,
+0x21,0x98,0x40,0x00,0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24,0x14,0x00,0x62,0xae,
+0x0c,0x00,0x64,0xae,0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24,0x08,0x00,0x07,0x24,
+0x80,0x00,0x63,0x34,0x14,0x00,0xa3,0xaf,0xd4,0x63,0x26,0x8e,0x24,0x18,0x64,0x00,
+0xff,0xe0,0x04,0x24,0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30,0x25,0x18,0x62,0x00,
+0x14,0x00,0xa3,0xaf,0xd0,0x63,0x25,0x8e,0x24,0x18,0x64,0x00,0x02,0x23,0x06,0x00,
+0x82,0x13,0x05,0x00,0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00,0xff,0xff,0x02,0x3c,
+0xff,0x7f,0x42,0x34,0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00,0xc0,0x2b,0x05,0x00,
+0x0f,0x00,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x00,0x35,0x06,0x00,0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34,
+0x0f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,
+0x02,0x80,0x04,0x3c,0x10,0x00,0xa5,0x27,0x8c,0x79,0x84,0x24,0x02,0x00,0x06,0x24,
+0x04,0x00,0x02,0x24,0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf,0x6c,0x45,0x00,0x0c,
+0x10,0x00,0xa2,0xa3,0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27,0x02,0x00,0x06,0x24,
+0x25,0x20,0x97,0x00,0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x30,0x08,0x00,0x0c,
+0x21,0x20,0x60,0x02,0xc1,0x12,0x00,0x08,0xc0,0x48,0x10,0x00,0x02,0x12,0x05,0x00,
+0x01,0x00,0x42,0x30,0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00,0x01,0x00,0x42,0x30,
+0x76,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x04,0x64,0xa2,0x96,0x60,0x01,0x03,0x91,
+0xc2,0x27,0x07,0x00,0x21,0x10,0x42,0x01,0x20,0x64,0xa3,0xa2,0x13,0x00,0x80,0x10,
+0x04,0x64,0xa2,0xa6,0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c,0x00,0x64,0xa2,0x96,
+0x0a,0x64,0xa3,0x96,0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0x00,0x64,0xa2,0xa6,
+0xd7,0x12,0x00,0x08,0x0a,0x64,0xa3,0xa6,0x5d,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,
+0x02,0x64,0xa3,0x96,0x0e,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x0e,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4,0x02,0x64,0xa3,0x96,
+0x10,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x10,0x64,0xa2,0xa6,
+0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x54,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,
+0x01,0x00,0x63,0x24,0x5c,0xff,0x54,0x15,0x54,0x51,0x43,0xac,0x21,0x10,0x30,0x01,
+0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,
+0x58,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x58,0x51,0x43,0xac,
+0x02,0x00,0x02,0x24,0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24,0x21,0x10,0x30,0x01,
+0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,
+0x5c,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x5c,0x51,0x43,0xac,
+0x03,0x00,0x02,0x24,0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x60,0x51,0x43,0x8c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15,0x60,0x51,0x43,0xac,
+0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x46,0x00,0x64,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,
+0x64,0x51,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x74,0x51,0xa3,0x8c,0x21,0x10,0x66,0x01,
+0x90,0x44,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0x3a,0xff,0x60,0x10,
+0x00,0x00,0x00,0x00,0x6c,0x51,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x02,0x80,0x04,0x3c,
+0x68,0x15,0x84,0x24,0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x44,0x00,
+0x6c,0x51,0xa3,0xac,0x21,0x10,0x4a,0x00,0xc5,0x43,0x44,0x90,0x50,0x51,0xa3,0x8c,
+0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,0x1a,0x13,0x00,0x08,0x50,0x51,0xa3,0xac,
+0x00,0x64,0xa3,0x96,0x08,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x08,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x00,0x64,0xc3,0xa4,0x08,0x00,0xe0,0x04,
+0x00,0x00,0x00,0x00,0x02,0x64,0xa3,0x96,0x0c,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,
+0x01,0x00,0x42,0x24,0x0c,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4,
+0x00,0x64,0xa3,0x96,0x06,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x06,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x00,0x64,0xc3,0xa4,0x25,0xb0,0x05,0x3c,
+0x4c,0x00,0xa2,0x34,0x02,0x80,0x07,0x3c,0x00,0x00,0x43,0x90,0x68,0x15,0xe4,0x24,
+0xed,0x4a,0x82,0x90,0x03,0x00,0x66,0x30,0x24,0x00,0x46,0x10,0x00,0x00,0x00,0x00,
+0x18,0x00,0xc0,0x14,0x25,0xb0,0x03,0x3c,0xe6,0x42,0x82,0x90,0x00,0x00,0x00,0x00,
+0x15,0x00,0x40,0x14,0x58,0x00,0x62,0x34,0x1c,0x00,0x02,0x24,0x50,0x0c,0xa3,0x34,
+0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,
+0x58,0x0c,0x42,0x34,0x1c,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x25,0xb0,0x03,0x3c,0x58,0x00,0x62,0x34,0x00,0x00,0x45,0x8c,0x29,0xb0,0x04,0x3c,
+0x5c,0x00,0x63,0x34,0x00,0x00,0x85,0xac,0x00,0x00,0x65,0x8c,0x68,0x15,0xe2,0x24,
+0x04,0x00,0x84,0x34,0xed,0x4a,0x46,0xa0,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x25,0xb0,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,
+0x2d,0x0a,0x46,0x34,0xa2,0x0d,0x43,0x34,0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34,
+0xa8,0x0d,0x42,0x34,0x00,0x00,0x67,0x94,0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94,
+0x00,0x00,0x44,0x94,0x00,0x00,0xc3,0x90,0x02,0x80,0x0a,0x3c,0x68,0x15,0x42,0x25,
+0x40,0x00,0x63,0x34,0xff,0x00,0x63,0x30,0xde,0x42,0x44,0xa4,0x00,0x00,0xc3,0xa0,
+0xd8,0x42,0x47,0xa4,0xda,0x42,0x48,0xa4,0xdc,0x42,0x49,0xa4,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,0x5b,0x0a,0xe2,0x34,0x00,0x00,0x44,0x90,
+0x68,0x15,0x46,0x25,0x5c,0x0a,0xe2,0x34,0x00,0x00,0x45,0x90,0xd8,0x42,0xc3,0x94,
+0xda,0x42,0xc2,0x94,0xdc,0x42,0xc9,0x94,0xde,0x42,0xc8,0x94,0xff,0x00,0x84,0x30,
+0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00,0xff,0x00,0xa5,0x30,0x21,0x20,0x85,0x00,
+0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30,0x21,0x18,0x68,0x00,0x21,0x18,0x62,0x00,
+0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30,0xe0,0x42,0xc3,0xac,0x00,0x00,0xe2,0xa4,
+0xe4,0x42,0xc4,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x45,0x25,
+0x00,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x0f,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
+0x00,0x00,0x00,0x00,0x88,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xe4,0x42,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0xf5,0xff,0x40,0x14,
+0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x03,0x00,0x63,0x30,0x3f,0x00,0x64,0x10,0x68,0x15,0x44,0x25,0xe6,0x42,0x82,0x90,
+0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14,0x01,0x00,0x03,0x24,0x00,0x40,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30,0x3c,0x00,0x43,0x10,
+0x25,0xb0,0x02,0x3c,0x68,0x15,0x45,0x25,0xe6,0x42,0xa3,0x90,0xff,0x00,0x02,0x24,
+0xe0,0xff,0x62,0x14,0x25,0xb0,0x03,0x3c,0xc8,0x42,0xa2,0x94,0xe0,0x42,0xa6,0x8c,
+0x50,0x0c,0x63,0x34,0x00,0x00,0x64,0x90,0x2b,0x10,0xc2,0x00,0x85,0x00,0x40,0x10,
+0x7f,0x00,0x84,0x30,0xff,0xff,0x82,0x24,0xff,0x00,0x44,0x30,0x68,0x15,0x45,0x25,
+0xd0,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x64,0x00,0x78,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x21,0x20,0x60,0x00,0x68,0x15,0x43,0x25,0xe0,0x42,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x6d,0x00,0x40,0x14,0x3a,0x00,0x82,0x2c,
+0x32,0x00,0x04,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,
+0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x69,0x14,0x00,0x08,
+0x00,0x00,0x00,0x00,0xe6,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xbf,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,0x7b,0x14,0x00,0x08,0xe6,0x42,0xa2,0xa0,
+0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,
+0xa4,0xff,0x60,0x10,0xff,0xff,0x02,0x34,0xe8,0x63,0x83,0x8c,0x00,0x00,0x00,0x00,
+0xa0,0xff,0x62,0x10,0x00,0x00,0x00,0x00,0xe0,0x42,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x65,0x00,0x62,0x2c,0x59,0x00,0x40,0x14,0x28,0x00,0x62,0x2c,0xd2,0x42,0x83,0x90,
+0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,
+0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,
+0xd2,0x42,0x82,0xa0,0x68,0x15,0x45,0x25,0xe8,0x63,0xa2,0x8c,0xd2,0x42,0xa3,0x90,
+0xce,0x42,0xa6,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x0a,0x00,0x44,0x24,
+0x23,0x18,0x83,0x00,0x00,0x26,0x03,0x00,0x03,0x26,0x04,0x00,0xff,0x00,0xc2,0x30,
+0x2a,0x10,0x44,0x00,0x4d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x26,0x06,0x00,
+0x03,0x26,0x04,0x00,0x68,0x15,0x43,0x25,0xe0,0x42,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x11,0x27,0x42,0x2c,0x33,0x00,0x40,0x14,0x3a,0x00,0x82,0x28,0x32,0x00,0x82,0x28,
+0x30,0x00,0x40,0x10,0x3a,0x00,0x82,0x28,0x32,0x00,0x04,0x24,0x44,0x00,0x03,0x24,
+0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,
+0x50,0x0c,0x42,0x34,0xff,0x00,0x84,0x30,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x69,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
+0x95,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0xa2,0x14,0x00,0x08,0x44,0x00,0x03,0x24,
+0xd1,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x9a,0x14,0x00,0x08,
+0x0b,0x20,0x62,0x00,0xca,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xc2,0x00,
+0x7a,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xcc,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,
+0x2b,0x10,0xc2,0x00,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x92,0x14,0x00,0x08,
+0x01,0x00,0x82,0x24,0xd2,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0xf4,0x14,0x00,0x08,
+0x44,0x00,0x03,0x24,0x92,0x14,0x00,0x08,0x02,0x00,0x82,0x24,0xb2,0xff,0x40,0x10,
+0x68,0x15,0x45,0x25,0xd2,0x42,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,
+0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28,0x09,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xd8,0x14,0x00,0x08,0x0c,0x00,0x02,0x24,0xcf,0x42,0xa3,0x80,
+0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x2a,0x10,0x82,0x00,0xe9,0x14,0x00,0x08,
+0x0b,0x20,0x62,0x00,0xd8,0x14,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,
+0x28,0x00,0xb4,0xaf,0x25,0xb0,0x14,0x3c,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x86,0x36,
+0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,0x68,0x15,0x51,0x24,0x2a,0xb0,0x10,0x3c,
+0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x34,0x00,0x05,0x36,0xfe,0xff,0x02,0x24,
+0xbc,0x42,0x32,0x92,0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,
+0x54,0x4f,0x00,0x0c,0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x8d,0x00,0x60,0x12,
+0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,0xb0,0x03,0x82,0x36,0x25,0xb0,0x1e,0x3c,
+0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0xfb,0x44,0x00,0x0c,0x21,0xb8,0x20,0x02,
+0x42,0x00,0xd5,0x37,0x03,0x0c,0xd1,0x37,0x17,0x0e,0xd6,0x37,0x04,0x00,0x14,0x24,
+0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
+0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
+0x94,0xa2,0x84,0x24,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,
+0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,0x01,0x00,0x04,0x24,0x00,0xfe,0xc6,0x34,
+0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa4,0xaf,0x4d,0x01,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x98,0xa2,0x42,0x24,0x00,0x00,0x45,0x8c,
+0x01,0x00,0x03,0x24,0x21,0x20,0x00,0x00,0x00,0x00,0xa3,0xa0,0xff,0xff,0x03,0x24,
+0x00,0x00,0xa3,0xa2,0x00,0x00,0x22,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,
+0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x02,0x00,0x02,0x24,
+0x02,0x80,0x04,0x3c,0x00,0x00,0xa2,0xa0,0x68,0x15,0x83,0x24,0xc1,0x42,0x62,0x90,
+0x00,0x00,0xc4,0x92,0x21,0x28,0x00,0x00,0x00,0x00,0xc2,0xa2,0xff,0x00,0x90,0x30,
+0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0xa2,0x24,0xef,0xff,0x02,0x24,0x64,0x00,0x04,0x24,0x00,0x00,0xa2,0xa2,
+0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,
+0xbf,0x00,0x42,0x30,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x1a,0x0c,0x00,0x0c,
+0x84,0x03,0x04,0x24,0xf4,0x08,0xc2,0x37,0x00,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,
+0xdf,0x07,0x84,0x34,0x00,0x00,0xd0,0xa2,0x21,0x10,0x00,0x00,0x24,0x28,0x64,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x00,0x00,0xa0,0xa2,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,
+0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,
+0xbe,0x42,0xe2,0x92,0x1f,0x00,0xa3,0x30,0x2b,0x10,0x62,0x00,0x0a,0x00,0x40,0x10,
+0x02,0x80,0x02,0x3c,0xbf,0x42,0xe2,0x92,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,
+0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x02,0x3c,0x25,0x10,0x62,0x00,
+0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,0xee,0x7d,0x43,0x90,0x22,0x00,0x02,0x24,
+0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,
+0xff,0xff,0x94,0x26,0x1a,0x0c,0x00,0x0c,0xf4,0x01,0x04,0x24,0x89,0xff,0x81,0x06,
+0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,0x25,0xb0,0x02,0x3c,0x70,0x4f,0x00,0x0c,
+0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,
+0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xbe,0x42,0x62,0x90,
+0xc0,0x07,0xa3,0x30,0x82,0x19,0x03,0x00,0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,
+0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0xbf,0x42,0x82,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0xd8,0x15,0x00,0x08,0x21,0x90,0x42,0x02,0xe0,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,
+0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c,
+0x14,0x00,0xb1,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,
+0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,
+0x68,0x15,0x51,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x04,0x43,0x23,0x92,
+0x04,0x00,0x02,0x24,0x20,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x14,0x43,0x25,0x8e,
+0x25,0xb0,0x10,0x3c,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,
+0x15,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0x18,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,
+0x08,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36,
+0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,
+0x15,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,
+0x1c,0x0e,0x04,0x36,0x68,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x04,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,
+0x14,0x43,0x25,0x8e,0x00,0x00,0x00,0x00,0xde,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,
+0x32,0x16,0x00,0x08,0x68,0x15,0x43,0x26,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,
+0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,
+0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,
+0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x68,0x15,0x02,0x26,0x04,0x43,0x46,0x90,0x25,0xb0,0x11,0x3c,
+0x10,0x10,0x12,0x3c,0x01,0x00,0x03,0x24,0x00,0x0e,0x24,0x36,0x1e,0x00,0xc3,0x10,
+0x10,0x10,0x45,0x36,0x15,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x0e,0x24,0x36,
+0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x08,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,
+0x10,0x10,0x05,0x24,0x10,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,
+0x14,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x18,0x0e,0x24,0x36,
+0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x1c,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,
+0x10,0x10,0x45,0x36,0x68,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,
+0xe0,0xff,0xc5,0x14,0x68,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c,0xff,0xff,0x25,0x36,
+0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x6a,0x44,0x00,0x0c,
+0x18,0x00,0xb2,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x56,0x30,0x06,0x36,
+0xff,0xff,0x25,0x36,0x1a,0x00,0x04,0x24,0x6a,0x44,0x00,0x0c,0x02,0x80,0x11,0x3c,
+0x68,0x15,0x30,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x04,0x43,0x02,0x92,
+0x25,0xb0,0x12,0x3c,0x08,0x00,0x40,0x14,0x08,0x0e,0x44,0x36,0x25,0xb0,0x02,0x3c,
+0x00,0x0e,0x42,0x34,0x00,0x00,0x45,0x8c,0xec,0x42,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x17,0x00,0xa3,0x10,0x68,0x15,0x22,0x26,0xe8,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xec,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x44,0x36,
+0xf0,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x04,0x0e,0x44,0x36,0xf4,0x42,0x05,0x8e,
+0x15,0x5a,0x00,0x0c,0x10,0x0e,0x44,0x36,0xf8,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,
+0x14,0x0e,0x44,0x36,0xfc,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x18,0x0e,0x44,0x36,
+0x00,0x43,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x1c,0x0e,0x44,0x36,0x68,0x15,0x22,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,0xe0,0xff,0xbd,0x27,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c,
+0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,
+0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x02,0x80,0x12,0x3c,0xff,0xff,0x25,0x36,0x56,0x30,0x06,0x36,0x6a,0x44,0x00,0x0c,
+0x1a,0x00,0x04,0x24,0x68,0x15,0x51,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x04,0x43,0x23,0x92,0x03,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
+0xec,0x42,0x25,0x8e,0x25,0xb0,0x10,0x3c,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,
+0xf0,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0xf4,0x42,0x25,0x8e,
+0x15,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36,0xf8,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c,
+0x14,0x0e,0x04,0x36,0xfc,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36,
+0x00,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x08,0x43,0x24,0x8e,
+0xe8,0x42,0x22,0x8e,0x00,0x00,0x00,0x00,0x21,0x28,0x44,0x00,0x00,0xff,0xa3,0x30,
+0xff,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x01,0x3f,0x63,0x2c,0x24,0x10,0xa2,0x00,
+0x0c,0x00,0x60,0x10,0x08,0x0e,0x04,0x36,0x15,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x68,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x04,0x43,0x62,0xa0,0xfa,0x16,0x00,0x08,0x00,0x3f,0x45,0x34,0x00,0x0e,0x42,0x34,
+0x00,0x00,0x43,0x8c,0xec,0x42,0x25,0x8e,0x00,0x00,0x00,0x00,0xd2,0xff,0x65,0x14,
+0x25,0xb0,0x10,0x3c,0xfd,0x16,0x00,0x08,0x68,0x15,0x43,0x26,0xd0,0xff,0xbd,0x27,
+0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,
+0x68,0x15,0x42,0x26,0x28,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0xe8,0x63,0x43,0x8c,0x02,0x80,0x15,0x3c,0xee,0x7d,0xa4,0x92,
+0x04,0x43,0x53,0x90,0x25,0xb0,0x02,0x3c,0x0f,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,
+0x00,0x00,0x44,0xa0,0x7f,0x00,0x74,0x30,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x68,0x15,0x42,0x26,0x00,0x40,0x43,0x8c,0x00,0x10,0x02,0x24,0xf0,0xf0,0x63,0x30,
+0x98,0x00,0x62,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x09,0x3c,0x4c,0x00,0x23,0x35,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x3f,0x00,0x40,0x10,
+0x68,0x15,0x45,0x26,0x68,0x15,0x4a,0x26,0x00,0x40,0x42,0x8d,0x00,0x00,0x00,0x00,
+0x02,0x13,0x02,0x00,0x0f,0x00,0x42,0x30,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x00,0x0e,0x25,0x35,0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x8c,0x00,0x40,0x10,
+0x10,0x0e,0x26,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x0e,0x22,0x35,0x04,0x0e,0x24,0x35,0x00,0x00,0x43,0x8c,
+0x00,0x00,0xa5,0x8c,0x00,0x00,0x82,0x8c,0xe8,0x42,0x43,0xad,0xec,0x42,0x45,0xad,
+0xf0,0x42,0x42,0xad,0x14,0x0e,0x24,0x35,0x18,0x0e,0x22,0x35,0x1c,0x0e,0x25,0x35,
+0x00,0x00,0xc6,0x8c,0x00,0x00,0x87,0x8c,0x00,0x00,0x48,0x8c,0x00,0x00,0xa4,0x8c,
+0x00,0xff,0x63,0x30,0x9a,0x0c,0x22,0x35,0x02,0x1a,0x03,0x00,0x00,0x43,0x44,0xad,
+0x00,0x00,0x43,0xa0,0xf4,0x42,0x46,0xad,0xf8,0x42,0x47,0xad,0xfc,0x42,0x48,0xad,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xee,0x7d,0xa3,0x92,0x22,0x00,0x02,0x24,
+0xac,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0xab,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x68,0x15,0x44,0x26,
+0x00,0x40,0x83,0x8c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x18,0x62,0x00,
+0x00,0x10,0x63,0x34,0x00,0x40,0x83,0xac,0x68,0x15,0x45,0x26,0x04,0x43,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x40,0x14,0x68,0x15,0x42,0x26,
+0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,
+0x8c,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,
+0x45,0x00,0x02,0x24,0x1c,0x43,0xa3,0xa0,0x1d,0x43,0xa2,0xa0,0x43,0x00,0x03,0x24,
+0x1e,0x43,0xa3,0xa0,0x68,0x15,0x42,0x26,0xe8,0x63,0x43,0x8c,0x25,0xb0,0x02,0x3c,
+0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26,0x04,0x40,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0x98,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26,
+0x1e,0x43,0x44,0x90,0x25,0xb0,0x03,0x3c,0x66,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26,0x1c,0x43,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x67,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x44,0x26,0x00,0x40,0x85,0x8c,0x10,0x10,0x02,0x24,
+0xf0,0xf0,0xa3,0x30,0x2b,0x00,0x62,0x10,0xff,0xff,0x02,0x34,0x28,0x00,0xbf,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x30,0x00,0xbd,0x27,0x0d,0x00,0x62,0x12,0x04,0x00,0x02,0x24,0x0b,0x00,0x62,0x12,
+0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x2e,0x17,0x00,0x08,0x04,0x43,0x62,0xa0,
+0x00,0x00,0xc3,0x8c,0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x71,0xff,0x62,0x14,
+0x00,0x00,0x00,0x00,0x73,0x17,0x00,0x08,0x68,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c,
+0x01,0x00,0x11,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x6a,0x44,0x00,0x0c,
+0x15,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
+0x56,0x30,0x26,0x36,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x2e,0x17,0x00,0x08,
+0x04,0x43,0x62,0xa0,0xe8,0x63,0x83,0x8c,0x00,0x00,0x00,0x00,0xd3,0xff,0x62,0x10,
+0x02,0x12,0x05,0x00,0x0f,0x00,0x45,0x30,0x01,0x00,0x03,0x24,0xcf,0xff,0xa3,0x14,
+0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x03,0x00,0x63,0x30,0xc9,0xff,0x60,0x10,0x03,0x00,0x02,0x24,0x4d,0x00,0x62,0x12,
+0x04,0x00,0x62,0x2a,0x2f,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x52,0x00,0x60,0x12,
+0x00,0x00,0x00,0x00,0xc1,0xff,0x65,0x16,0x00,0x00,0x00,0x00,0x1c,0x43,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x3e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x1f,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x30,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x86,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,
+0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,
+0x1c,0x43,0xa3,0xa0,0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24,0x84,0x17,0x00,0x08,
+0x1d,0x43,0xa2,0xa0,0x25,0xb0,0x02,0x3c,0x0d,0x08,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30,0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,
+0x4f,0xff,0x40,0x14,0x01,0x00,0x65,0x24,0x00,0x1c,0x05,0x00,0x00,0x16,0x05,0x00,
+0x25,0x10,0x43,0x00,0x00,0x22,0x05,0x00,0x25,0x10,0x44,0x00,0x68,0x15,0x43,0x26,
+0x25,0x20,0x85,0x00,0x25,0x10,0x45,0x00,0x18,0x43,0x64,0xac,0x68,0x17,0x00,0x08,
+0x14,0x43,0x62,0xac,0x04,0x00,0x02,0x24,0x11,0x00,0x62,0x12,0xff,0x00,0x02,0x24,
+0x92,0xff,0x62,0x16,0x00,0x00,0x00,0x00,0x1e,0x43,0x82,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x82,0x02,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x43,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x42,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00,
+0x1d,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0xf8,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x03,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,
+0x00,0x00,0x00,0x00,0x20,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,
+0xc0,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc3,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00,0x1e,0x43,0x82,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x82,0x02,0xe6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x43,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0xb2,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0xc3,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00,
+0x02,0x80,0x08,0x3c,0x68,0x15,0x05,0x25,0xe8,0x63,0xa4,0x8c,0xe6,0x42,0xa3,0x90,
+0x02,0x11,0x04,0x00,0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,0x25,0xb0,0x07,0x3c,
+0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x10,
+0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10,0x00,0x00,0x00,0x00,
+0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0x19,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10,0x01,0x00,0x04,0x24,
+0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,
+0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x44,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0x20,0x00,0x03,0x24,
+0x00,0x00,0x43,0xa0,0xd3,0x42,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10,0x01,0x00,0x04,0x24,
+0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,
+0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x3f,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x44,0x00,0x03,0x24,
+0x00,0x00,0x43,0xa0,0xd3,0x42,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,
+0xe7,0xff,0x44,0x10,0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34,0xd3,0x42,0xa4,0xa0,
+0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xc0,0xff,0x44,0x10,
+0x10,0x00,0x02,0x24,0x87,0x0c,0xe3,0x34,0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0xc7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,
+0x02,0x00,0x03,0x24,0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0x87,0x0c,0x42,0x34,0xd3,0x42,0x83,0xa0,0x00,0x00,0x40,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xb4,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x02,0x00,0x03,0x24,
+0xaf,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xd3,0x42,0x83,0xa0,
+0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xff,0xff,0x8d,0x30,
+0x00,0x60,0x0f,0x40,0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x06,0x3c,0x68,0x15,0xce,0x24,0x76,0x4b,0xc2,0x91,0x00,0x00,0x00,0x00,
+0x1d,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34,0x80,0xff,0x02,0x24,
+0x00,0x00,0x82,0xa0,0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34,0xd6,0x01,0x66,0x34,
+0xda,0x01,0x67,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94,0x00,0x00,0xc9,0x94,
+0x00,0x00,0xeb,0x94,0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95,0xb0,0xfe,0xa2,0x25,
+0xff,0xff,0x4d,0x30,0x74,0x4b,0xc4,0xa5,0x00,0x00,0xa0,0xa4,0x6c,0x4b,0xc8,0xa5,
+0x00,0x00,0xc0,0xa4,0x6e,0x4b,0xc9,0xa5,0x00,0x00,0xe0,0xa4,0x70,0x4b,0xcb,0xa5,
+0x00,0x00,0x60,0xa4,0x00,0x00,0x4d,0xa5,0x72,0x4b,0xcc,0xa5,0x00,0x60,0x8f,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c,0x0a,0x00,0x45,0x34,
+0x63,0x00,0x03,0x24,0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
+0x0a,0x00,0x40,0x10,0x68,0x15,0xc2,0x24,0x64,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x42,0x30,0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24,0xff,0xff,0x62,0x24,
+0xff,0xff,0x43,0x30,0xf4,0xff,0x64,0x14,0x68,0x15,0xc2,0x24,0x74,0x4b,0x48,0x94,
+0x72,0x4b,0x47,0x94,0x6c,0x4b,0x49,0x94,0x6e,0x4b,0x4a,0x94,0x70,0x4b,0x4b,0x94,
+0x25,0xb0,0x03,0x3c,0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34,0xd2,0x01,0x64,0x34,
+0xd6,0x01,0x65,0x34,0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0x48,0xa4,
+0x00,0x00,0x89,0xa4,0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4,0x00,0x00,0x67,0xa4,
+0x00,0x00,0x80,0xa1,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,0x00,0x00,0x64,0x94,0x03,0x00,0x49,0x34,
+0x40,0x00,0x45,0x34,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,0xfc,0x77,0x0a,0x24,
+0x00,0x03,0x46,0x34,0x04,0x03,0x47,0x34,0x0f,0x00,0x80,0x04,0x23,0x00,0x48,0x34,
+0x00,0x00,0x22,0x91,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x00,0x00,0x22,0xa1,
+0x22,0x00,0x02,0x24,0x00,0x00,0xc0,0xac,0x00,0x00,0xe0,0xac,0x00,0x00,0x02,0xa1,
+0xfc,0x37,0x02,0x24,0x00,0x00,0xaa,0xa4,0x00,0x00,0xa2,0xa4,0x00,0x00,0xaa,0xa4,
+0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x28,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,0x02,0x80,0x13,0x3c,
+0x41,0xb0,0x02,0x3c,0x68,0x15,0x66,0x26,0x04,0x00,0x42,0x34,0x00,0x00,0x47,0x8c,
+0x00,0x4b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0xf6,0x7d,0x64,0x90,0xfc,0x4a,0xc8,0x8c,
+0x02,0x80,0x02,0x3c,0x18,0x7e,0x49,0x90,0x25,0xb0,0x0a,0x3c,0x25,0x90,0xa7,0x00,
+0xb0,0x03,0x42,0x35,0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,0x00,0x00,0x48,0xac,
+0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,0x00,0x00,0x72,0xac,
+0x00,0x00,0xa4,0xac,0x88,0x04,0x22,0x11,0x00,0x4b,0xd2,0xac,0x68,0x15,0x64,0x26,
+0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x01,0x00,0x42,0x30,
+0x0e,0x00,0x40,0x10,0x68,0x15,0x66,0x26,0x25,0xb0,0x0b,0x3c,0xb0,0x03,0x63,0x35,
+0x01,0x00,0x06,0x24,0x00,0x00,0x66,0xac,0x04,0x00,0x62,0x35,0x00,0x00,0x4a,0x8c,
+0x00,0x4b,0x83,0x8c,0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01,0x01,0x00,0x63,0x38,
+0x47,0x04,0x40,0x10,0x00,0x4b,0x83,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc2,0x8c,
+0x00,0x00,0x00,0x00,0x24,0x28,0x52,0x00,0x04,0x00,0xa3,0x30,0x09,0x00,0x60,0x10,
+0x08,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0x04,0x00,0x04,0x24,
+0x04,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac,
+0x08,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x10,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x10,0x00,0xa2,0x30,
+0x06,0x00,0x40,0x10,0x20,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x10,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x20,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,
+0x40,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38,
+0x00,0x4b,0xc2,0xac,0x40,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x80,0x00,0xa2,0x30,
+0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,
+0x80,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x00,0x01,0xa2,0x30,0x00,0x4b,0xc2,0x8c,
+0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x00,0x01,0xa2,0x30,
+0x06,0x00,0x40,0x10,0x00,0x02,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x01,0x42,0x38,0x00,0x4b,0xc2,0xac,0x00,0x02,0xa2,0x30,0x06,0x00,0x40,0x10,
+0x00,0x04,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38,
+0x00,0x4b,0xc2,0xac,0x00,0x04,0xa2,0x30,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x00,0x4b,0xc2,0xac,
+0x00,0x08,0xa2,0x30,0x36,0x00,0x40,0x10,0x2a,0xb0,0x03,0x3c,0x00,0x00,0x6a,0x8c,
+0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,0x00,0x80,0x42,0x31,
+0x35,0x04,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x68,0x64,0xc2,0x90,0x20,0xb0,0x03,0x3c,
+0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,
+0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,
+0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x20,0x65,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0xb4,0x64,0x03,0xae,0x21,0x20,0x00,0x00,0x68,0x64,0x0a,0xa2,0x20,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,
+0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,
+0x04,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
+0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,
+0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x00,0x4b,0x62,0xac,
+0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
+0x00,0x10,0x42,0x30,0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,
+0x00,0x80,0x42,0x31,0xfb,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
+0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x70,0x64,0xa2,0x90,
+0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,
+0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,
+0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,
+0x38,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0xcc,0x64,0x03,0xae,0x01,0x00,0x04,0x24,0x70,0x64,0x0a,0xa2,
+0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,
+0x02,0x80,0x06,0x3c,0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,
+0x25,0xb0,0x02,0x3c,0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,
+0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,
+0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x52,0x00,0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,
+0x04,0x00,0x43,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,
+0xe9,0x03,0x82,0x10,0x00,0x80,0x42,0x31,0xc1,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x6c,0x64,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,
+0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,
+0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x2c,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xc0,0x64,0x03,0xae,0x01,0x00,0x04,0x24,
+0x6c,0x64,0x0a,0xa2,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,
+0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,0x80,0x03,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac,
+0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x20,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,0x58,0x00,0x40,0x10,
+0x2a,0xb0,0x06,0x3c,0x0c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,
+0xff,0x00,0x44,0x31,0x9d,0x03,0x87,0x10,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,
+0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,
+0xff,0x00,0x02,0x24,0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x48,0x64,0xa4,0xa0,
+0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
+0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
+0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x48,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,
+0x48,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,
+0x00,0x00,0x4a,0xac,0xa9,0x1a,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
+0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,
+0xf0,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0x48,0x64,0x0a,0xa2,0x84,0x64,0x03,0xae,0x03,0x00,0x04,0x24,
+0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,
+0xdc,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,
+0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,0x00,0x80,0x03,0x35,
+0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
+0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,0x00,0x00,0x66,0xac,0xcc,0x7e,0x25,0xad,
+0xdc,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,
+0xfc,0x4a,0xa2,0x8c,0x01,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,
+0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x10,0x00,0xc3,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x49,0x03,0x87,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
+0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x4c,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,
+0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
+0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
+0xff,0x00,0x44,0x30,0x4c,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x4c,0x64,0x43,0x90,
+0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,
+0x08,0x1b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,
+0x22,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xf0,0x64,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x84,0x64,0x03,0xae,0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x4c,0x64,0x0a,0xa2,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91,
+0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x01,0x00,0x02,0x3c,
+0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
+0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,
+0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,
+0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,
+0x00,0x4b,0x43,0x8c,0x01,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
+0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x02,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
+0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x14,0x00,0xc3,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xcf,0x02,0x87,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
+0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x50,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,
+0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
+0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
+0xff,0x00,0x44,0x30,0x50,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x50,0x64,0x43,0x90,
+0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,
+0x64,0x1b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,
+0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xfc,0x64,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x50,0x64,0x0a,0xa2,0x90,0x64,0x03,0xae,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91,
+0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c,
+0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,
+0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,
+0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,
+0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1,
+0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,
+0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,
+0xfc,0x4a,0xa2,0x8c,0x04,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,
+0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x62,0x34,
+0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,0x18,0x00,0x06,0x35,0x00,0x00,0xca,0x8c,
+0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xa1,0x02,0x87,0x10,0x04,0x00,0x02,0x24,
+0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
+0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x43,0x00,0x06,0x35,
+0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,
+0x68,0x15,0x62,0x26,0x54,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,
+0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,
+0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,
+0x54,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x54,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0xc7,0x1b,0x00,0x08,
+0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,
+0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xfc,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x90,0x64,0x03,0xae,
+0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x54,0x64,0x0a,0xa2,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,
+0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c,0x10,0x00,0xe7,0x34,
+0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,0x00,0x26,0x07,0x00,
+0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1,
+0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x04,0x00,0x04,0x3c,
+0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
+0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,
+0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,
+0xff,0x00,0x44,0x31,0x3e,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,
+0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x44,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,
+0x58,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
+0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x58,0x64,0xe3,0xa0,
+0x68,0x15,0x62,0x26,0x58,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x22,0x1c,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x08,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x58,0x64,0x0a,0xa2,0x9c,0x64,0x03,0xae,
+0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,
+0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x08,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
+0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c,
+0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,
+0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,
+0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,
+0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x08,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x10,0x00,0x03,0x3c,
+0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,
+0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,
+0x20,0x00,0x03,0x35,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,
+0xe0,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,
+0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,
+0xff,0x00,0x02,0x24,0x45,0x00,0x06,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x64,0x64,0xa4,0xa0,
+0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
+0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
+0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x64,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,
+0x64,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,
+0x00,0x00,0x4a,0xac,0x85,0x1c,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
+0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,
+0x08,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0x9c,0x64,0x03,0xae,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
+0x64,0x64,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
+0xdc,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,
+0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
+0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,
+0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,
+0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,
+0x00,0x4b,0x43,0x8c,0x10,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
+0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x20,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
+0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x24,0x00,0xc3,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x58,0x01,0x87,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
+0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x5c,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,
+0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
+0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
+0xff,0x00,0x44,0x30,0x5c,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x5c,0x64,0x43,0x90,
+0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,
+0xe0,0x1c,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,
+0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x65,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x5c,0x64,0x0a,0xa2,0xa8,0x64,0x03,0xae,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91,
+0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x60,0x00,0x02,0x3c,
+0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34,
+0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,
+0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,
+0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1,
+0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,
+0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,
+0xfc,0x4a,0xa2,0x8c,0x40,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,
+0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x68,0x15,0x70,0x26,0x25,0xb0,0x02,0x3c,
+0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x51,0xac,0x28,0x00,0xe3,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x06,0x24,0xff,0x00,0x44,0x31,0xfe,0x00,0x86,0x10,
+0x25,0xbd,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
+0x0e,0x00,0x86,0x10,0x68,0x15,0x62,0x26,0x60,0x64,0xa4,0xa0,0x00,0x00,0xe2,0x90,
+0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x30,0xa0,0x00,
+0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
+0xff,0x00,0x44,0x30,0x60,0x64,0xc3,0xa0,0x68,0x15,0x62,0x26,0x60,0x64,0x43,0x90,
+0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,
+0x44,0x1d,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,
+0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x65,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0xa8,0x64,0x03,0xae,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x60,0x64,0x0a,0xa2,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91,
+0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x60,0x00,0x02,0x3c,
+0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34,
+0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xcc,0x7e,0x05,0xad,
+0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,
+0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x70,0x26,
+0xfc,0x4a,0x06,0x8e,0x00,0x04,0x11,0x3c,0x24,0x10,0xd2,0x00,0x24,0x10,0x51,0x00,
+0x77,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x24,0x28,0xd2,0x00,0x00,0x08,0x04,0x3c,
+0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x07,0x3c,0x00,0x4b,0x03,0x8e,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac,
+0x00,0x4b,0x03,0xae,0x80,0x00,0x07,0x3c,0x24,0x10,0xa7,0x00,0x21,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x00,0x4b,0x03,0x8e,0x25,0xb0,0x08,0x3c,0xb0,0x03,0x09,0x35,
+0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,0xf0,0x07,0x63,0x30,
+0xbc,0x65,0x05,0x8e,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x84,0x00,0x65,0x10,0xc0,0x65,0x03,0xae,0x02,0x80,0x05,0x3c,0xcc,0x7e,0xa3,0x8c,
+0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,0x00,0x08,0x63,0x34,0x41,0xb0,0x02,0x3c,
+0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,0xcc,0x7e,0xa3,0xac,0xfc,0x4a,0x04,0xae,
+0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x80,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x00,0x4b,0x43,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc3,0x8c,0x00,0x01,0x04,0x3c,
+0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,
+0x00,0x4b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac,
+0x00,0x4b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,
+0x02,0x80,0x02,0x3c,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,
+0x26,0x10,0x44,0x00,0x00,0x4b,0xc2,0xac,0x00,0x00,0x64,0xac,0x02,0x80,0x02,0x3c,
+0xea,0x7d,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30,0x3f,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x28,0x00,0xbf,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35,0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35,
+0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34,0x00,0x00,0x46,0xa4,0x00,0x00,0x00,0xa1,
+0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac,0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c,
+0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30,0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01,
+0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35,0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1,
+0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac,0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0,
+0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10,0x02,0x00,0x62,0x35,0x84,0xff,0x02,0x24,
+0x00,0x00,0x42,0xa1,0x02,0x00,0x62,0x35,0x00,0x00,0x43,0x94,0xff,0xbf,0x04,0x24,
+0x24,0x18,0x64,0x00,0x00,0x00,0x43,0xa4,0x7f,0x19,0x00,0x08,0x68,0x15,0x66,0x26,
+0x0e,0x4f,0x00,0x0c,0x07,0x00,0x04,0x24,0x00,0x4b,0x03,0x8e,0xfc,0x4a,0x06,0x8e,
+0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x72,0x1d,0x00,0x08,0x00,0x4b,0x03,0xae,0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,
+0x00,0x00,0x00,0x00,0x75,0xfb,0x60,0x10,0x00,0x00,0x00,0x00,0x0e,0x4f,0x00,0x0c,
+0x07,0x00,0x04,0x24,0x6c,0x19,0x00,0x08,0x68,0x15,0x64,0x26,0x28,0x00,0xbf,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x30,0x19,0x00,0x08,0x30,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0xdc,0x19,0x00,0x08,
+0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x19,0x1a,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0x56,0x1a,0x00,0x08,0xff,0x00,0x02,0x24,0x05,0x00,0x03,0x24,
+0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x8b,0x1b,0x00,0x08,0x68,0x15,0x62,0x26,
+0x02,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x07,0x1d,0x00,0x08,
+0x68,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
+0x9d,0x1d,0x00,0x08,0x68,0x15,0x62,0x26,0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x67,0x1d,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,
+0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26,
+0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0xd3,0x1a,0x00,0x08,
+0x00,0x4b,0x62,0xac,0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x2c,0x1b,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,
+0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,0x76,0x1a,0x00,0x08,0x00,0x4b,0x62,0xac,
+0x03,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x49,0x1c,0x00,0x08,
+0x68,0x15,0x62,0x26,0x00,0x00,0x40,0xac,0xa8,0x1c,0x00,0x08,0x68,0x15,0x62,0x26,
+0x90,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0xea,0x1b,0x00,0x08,0x68,0x15,0x62,0x26,
+0x25,0xb0,0x0d,0x3c,0x00,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35,0x10,0x79,0x42,0x24,
+0x02,0x80,0x03,0x3c,0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac,0x68,0x15,0x6a,0x24,
+0x0a,0x00,0x02,0x35,0x00,0x00,0x44,0x94,0x0a,0x4b,0x43,0x95,0x08,0x4b,0x4b,0x95,
+0x25,0x18,0x64,0x00,0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01,0x02,0x00,0x42,0x30,
+0x53,0x00,0x40,0x10,0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24,0xc0,0x03,0xa3,0x35,
+0x00,0x00,0x62,0xac,0x0a,0x4b,0x44,0xa5,0x24,0x38,0x8b,0x01,0x04,0x00,0xe2,0x30,
+0x0a,0x00,0x40,0x10,0x08,0x00,0xe2,0x30,0x0a,0x4b,0x43,0x95,0x0c,0x00,0x04,0x35,
+0xc0,0x03,0xa5,0x35,0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c,
+0x00,0x00,0xa2,0xac,0x0a,0x4b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,
+0x10,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x08,0x00,0x03,0x24,
+0x08,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x10,0x00,0xe2,0x30,
+0x08,0x00,0x40,0x10,0x20,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,
+0x10,0x00,0x03,0x24,0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,
+0x20,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,
+0xc0,0x03,0xa4,0x35,0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38,0x00,0x00,0x83,0xac,
+0x0a,0x4b,0x42,0xa5,0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10,0x24,0x10,0x8b,0x01,
+0x02,0x80,0x09,0x3c,0x0a,0x4b,0x46,0x95,0xcc,0x7e,0x25,0x8d,0x08,0x00,0x02,0x3c,
+0x7f,0xff,0x04,0x24,0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00,0x80,0x00,0xc6,0x38,
+0xb0,0x03,0xa7,0x35,0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35,0x80,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac,0x0a,0x4b,0x46,0xa5,
+0xcc,0x7e,0x25,0xad,0x00,0x00,0x04,0xa5,0x08,0x4b,0x44,0xa5,0x24,0x10,0x8b,0x01,
+0x00,0x30,0x42,0x30,0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x0a,0x4b,0x42,0x95,
+0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,0x0a,0x4b,0x42,0xa5,
+0x02,0x80,0x02,0x3c,0xea,0x7d,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30,
+0x05,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x5a,0x1e,0x00,0x08,0x0a,0x4b,0x43,0xa5,0x30,0x19,0x00,0x08,0x00,0x00,0x00,0x00,
+0xf8,0xff,0xbd,0x27,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x00,0x40,0x02,0x40,
+0x00,0x68,0x08,0x40,0x00,0x70,0x02,0x40,0x00,0x60,0x09,0x40,0x25,0xb0,0x05,0x3c,
+0x00,0x80,0x02,0x3c,0x18,0x03,0xa3,0x34,0xb0,0x7a,0x42,0x24,0x00,0x00,0x62,0xac,
+0x80,0x00,0x87,0x8c,0x7c,0x02,0xa2,0x34,0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34,
+0x00,0x00,0x47,0xac,0x00,0x00,0x68,0xac,0x00,0x00,0xc9,0xac,0x74,0x00,0x83,0x8c,
+0x8c,0x02,0xa2,0x34,0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,
+0x94,0x02,0xa8,0x34,0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,
+0x9c,0x02,0xa6,0x34,0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,
+0xa4,0x02,0xa8,0x34,0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,
+0xac,0x02,0xa9,0x34,0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,
+0xb4,0x02,0xa6,0x34,0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,
+0xbc,0x02,0xa7,0x34,0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,
+0xc4,0x02,0xa8,0x34,0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,
+0xcc,0x02,0xaa,0x34,0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,
+0xd4,0x02,0xa9,0x34,0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,
+0x70,0x02,0xab,0x34,0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,
+0x78,0x02,0xa5,0x34,0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xe2,0xac,0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,
+0x3c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x42,0xad,0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,
+0x4c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xad,0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,
+0x5c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x0f,0x1f,0x00,0x08,
+0x00,0x00,0x00,0x00,0x00,0x80,0x1b,0x3c,0x44,0x7c,0x7b,0x27,0x25,0xb0,0x1a,0x3c,
+0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,
+0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,
+0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,
+0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,
+0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,
+0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,
+0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,
+0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,
+0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,
+0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,
+0x80,0x00,0x6a,0xaf,0x00,0x68,0x1a,0x40,0x25,0xb0,0x1b,0x3c,0x1c,0x03,0x7b,0x37,
+0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
+0x00,0x00,0x7a,0xaf,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,
+0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,
+0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,
+0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,
+0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,
+0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,
+0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,
+0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,
+0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,
+0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,
+0x80,0x00,0x6a,0xaf,0xac,0x1e,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x08,0x3c,0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,
+0x00,0x04,0x5b,0x33,0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,
+0x30,0x65,0x08,0x25,0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,
+0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,
+0x00,0x08,0x5b,0x33,0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1b,0xad,0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,
+0x10,0x79,0x08,0x25,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,
+0x02,0x80,0x1a,0x3c,0xcc,0x7e,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,
+0x30,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,
+0x00,0x00,0x00,0x00,0x08,0xec,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,
+0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,
+0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,
+0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,
+0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,
+0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0xfc,0x1f,0x00,0x08,0x00,0x00,0x00,0x00,
+0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,
+0x08,0x00,0x5b,0xaf,0xfc,0xef,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,
+0x21,0x00,0x40,0x11,0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x2c,0x7e,0x08,0x25,
+0x21,0x48,0x00,0x00,0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,
+0x24,0x70,0x4b,0x01,0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,
+0x04,0x00,0x44,0xa3,0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,
+0x21,0x80,0x08,0x02,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,
+0x00,0x00,0x00,0x00,0x00,0x80,0x1b,0x3c,0x1c,0x7f,0x7b,0x27,0x25,0xb0,0x1a,0x3c,
+0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0xcc,0x7e,0x5a,0x27,
+0xe1,0xff,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,
+0xbf,0x1f,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0xcc,0x7e,0x7b,0x27,
+0x21,0x60,0x00,0x00,0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,
+0xf8,0xff,0x5a,0x27,0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,
+0x84,0x00,0x44,0x8f,0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,
+0x04,0x00,0x41,0x8f,0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,
+0xfc,0x00,0x46,0x7b,0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,
+0x7c,0x01,0x4a,0x7b,0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,
+0x7c,0x02,0x52,0x7b,0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,
+0x7c,0x03,0x5c,0x7b,0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0x60,0x03,0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,
+0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,
+0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,
+0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,
+0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,
+0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,
+0x54,0x00,0x95,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,
+0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,
+0x74,0x00,0x9f,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,
+0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,
+0x84,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,
+0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
+0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
+0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
+0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
+0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
+0x80,0x00,0x7b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,
+0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,
+0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,
+0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,
+0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,
+0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,
+0x5c,0x00,0x96,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,
+0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,
+0x80,0x00,0x9f,0xac,0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,
+0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,
+0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,
+0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,
+0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,
+0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,
+0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x60,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27,
+0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24,
+0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c,
+0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
+0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27,
+0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35,
+0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c,
+0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34,
+0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,
+0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c,
+0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c,
+0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c,
+0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84,
+0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c,
+0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00,
+0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c,
+0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0xe8,0x7d,0xa5,0x24,0xff,0xff,0xa5,0x30,
+0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00,
+0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac,
+0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x8b,0x5b,0x00,0x08,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00,
+0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00,
+0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28,
+0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,
+0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00,
+0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf,
+0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x31,0x26,0x44,0x65,0x30,0x96,
+0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c,
+0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26,
+0x00,0x00,0x43,0xac,0x6c,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02,
+0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0x44,0x65,0x22,0x8e,
+0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24,
+0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x30,0x08,0x00,0x08,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00,
+0x68,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90,
+0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x44,0x4c,0x82,0xa0,0x1e,0x00,0xa3,0x90,
+0x1e,0x00,0xe6,0x28,0x62,0x4c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
+0x80,0x4c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0x9e,0x4c,0x83,0xa0,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24,
+0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04,
+0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0,
+0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0,
+0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24,
+0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24,
+0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00,
+0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34,
+0xa8,0x08,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24,
+0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x80,0x4b,0xc2,0xac,
+0x40,0x08,0x02,0x24,0x84,0x4b,0xc3,0xac,0x90,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0x94,0x4b,0xc3,0xac,0x98,0x4b,0xc2,0xac,0x10,0x08,0x03,0x24,
+0x20,0x08,0x02,0x24,0x9c,0x4b,0xc3,0xac,0xa0,0x4b,0xc2,0xac,0x24,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xa4,0x4b,0xc3,0xac,0xa8,0x4b,0xc2,0xac,0x50,0x0c,0x03,0x24,
+0x54,0x0c,0x02,0x24,0xac,0x4b,0xc3,0xac,0xb0,0x4b,0xc2,0xac,0x14,0x0c,0x03,0x24,
+0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xb4,0x4b,0xc3,0xac,0xb8,0x4b,0xc2,0xac,
+0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xc0,0x4b,0xc2,0xac,
+0x8c,0x4b,0xc5,0xac,0xbc,0x4b,0xc3,0xac,0x7d,0x4b,0xc0,0xa0,0x88,0x4b,0xc5,0xac,
+0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
+0xc4,0x4b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x80,0x4b,0xc2,0xac,
+0x44,0x08,0x02,0x24,0x84,0x4b,0xc3,0xac,0x90,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0x94,0x4b,0xc3,0xac,0x98,0x4b,0xc2,0xac,0x14,0x08,0x03,0x24,
+0x28,0x08,0x02,0x24,0x9c,0x4b,0xc3,0xac,0xa0,0x4b,0xc2,0xac,0x2c,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xa4,0x4b,0xc3,0xac,0xa8,0x4b,0xc2,0xac,0x58,0x0c,0x03,0x24,
+0x5c,0x0c,0x02,0x24,0xac,0x4b,0xc3,0xac,0xb0,0x4b,0xc2,0xac,0x1c,0x0c,0x03,0x24,
+0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xb4,0x4b,0xc3,0xac,0xb8,0x4b,0xc2,0xac,
+0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xc0,0x4b,0xc2,0xac,
+0x7d,0x4b,0xc7,0xa0,0x8c,0x4b,0xc5,0xac,0xbc,0x4b,0xc3,0xac,0x88,0x4b,0xc5,0xac,
+0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
+0xc4,0x4b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xac,0x08,0x03,0x24,
+0xc4,0x4b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x80,0x4b,0x43,0xac,
+0x4c,0x08,0x03,0x24,0x84,0x4b,0x44,0xac,0x90,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,
+0x0c,0x08,0x03,0x24,0x94,0x4b,0x44,0xac,0x98,0x4b,0x43,0xac,0x1c,0x08,0x04,0x24,
+0x38,0x08,0x03,0x24,0x9c,0x4b,0x44,0xac,0xa0,0x4b,0x43,0xac,0x3c,0x08,0x04,0x24,
+0x5c,0x08,0x03,0x24,0xa4,0x4b,0x44,0xac,0xa8,0x4b,0x43,0xac,0x68,0x0c,0x04,0x24,
+0x6c,0x0c,0x03,0x24,0xac,0x4b,0x44,0xac,0xb0,0x4b,0x43,0xac,0x2c,0x0c,0x04,0x24,
+0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xb4,0x4b,0x44,0xac,0xb8,0x4b,0x43,0xac,
+0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x7d,0x4b,0x47,0xa0,0x8c,0x4b,0x45,0xac,
+0xbc,0x4b,0x44,0xac,0xc0,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x88,0x4b,0x45,0xac,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xc4,0x4b,0x43,0xac,
+0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x80,0x4b,0x43,0xac,0x48,0x08,0x03,0x24,
+0x84,0x4b,0x44,0xac,0x90,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24,
+0x94,0x4b,0x44,0xac,0x98,0x4b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24,
+0x9c,0x4b,0x44,0xac,0xa0,0x4b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24,
+0xa4,0x4b,0x44,0xac,0xa8,0x4b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24,
+0xac,0x4b,0x44,0xac,0xb0,0x4b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24,
+0x68,0x08,0x05,0x24,0xb4,0x4b,0x44,0xac,0xb8,0x4b,0x43,0xac,0x90,0x0c,0x04,0x24,
+0x94,0x0c,0x03,0x24,0x7d,0x4b,0x47,0xa0,0x8c,0x4b,0x45,0xac,0xbc,0x4b,0x44,0xac,
+0xc0,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x88,0x4b,0x45,0xac,0xe6,0x42,0x00,0x08,
+0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24,
+0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27,
+0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,
+0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,
+0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0xe1,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00,
+0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xf8,0x60,0x44,0x8c,
+0xed,0x42,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
+0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,
+0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00,
+0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,
+0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf,
+0x68,0x15,0x31,0x26,0xa4,0x4b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36,
+0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c,
+0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02,
+0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c,
+0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0x25,0xa8,0x74,0x00,
+0xa4,0x4b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00,
+0x00,0x00,0x55,0xac,0xeb,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae,
+0xeb,0x0b,0x00,0x0c,0x01,0x00,0x04,0x24,0xc4,0x4b,0x24,0x8e,0x0f,0x00,0x05,0x3c,
+0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34,
+0x18,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x68,0x15,0x27,0x26,
+0x7f,0x4b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x70,0x0d,0x63,0x24,
+0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10,
+0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e,
+0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x29,0x43,0x00,0x08,
+0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x7d,0x4b,0xe4,0x90,
+0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,
+0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
+0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,
+0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,0x68,0x15,0x22,0x26,0x7d,0x4b,0x44,0x90,
+0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,
+0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14,
+0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,0xff,0x00,0x04,0x32,
+0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,
+0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,
+0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,
+0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,
+0x68,0x15,0x28,0x26,0x7f,0x4b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x1c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf,
+0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,
+0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10,
+0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x25,0x20,0x44,0x00,0x13,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14,
+0x0f,0x00,0x04,0x3c,0x7d,0x4b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,
+0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10,
+0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,
+0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,
+0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,
+0x68,0x15,0x22,0x26,0x7d,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,
+0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,
+0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,
+0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,
+0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14,
+0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,
+0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,
+0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
+0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,
+0x21,0x30,0x00,0x00,0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x29,0x43,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e,
+0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34,
+0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,
+0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26,
+0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00,
+0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d,
+0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xd8,0xff,0xbd,0x27,0xa8,0x11,0x42,0x24,
+0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,
+0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00,0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40,
+0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12,0x21,0x28,0xc0,0x00,0x5c,0x43,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0xe1,0x42,0x00,0x0c,0x21,0x80,0x40,0x00,
+0x04,0x10,0x53,0x00,0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00,
+0xc7,0x43,0x00,0x0c,0xff,0x00,0x84,0x32,0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f,
+0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x54,0x12,0x63,0x24,0x18,0x03,0x42,0x34,
+0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x5c,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0x80,0x40,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0x40,0x02,0x24,0x80,0x12,0x02,
+0x06,0x80,0x50,0x00,0x00,0x60,0x91,0x40,0x21,0x10,0x00,0x02,0x1c,0x00,0xbf,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,
+0x21,0x88,0x80,0x00,0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,
+0x30,0x00,0xb2,0xaf,0x58,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,
+0x02,0x80,0x02,0x3c,0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,
+0x58,0x45,0x00,0x0c,0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,
+0x10,0x00,0xa5,0x27,0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,
+0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,
+0x00,0x00,0x44,0x8c,0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,
+0x00,0x00,0xa2,0x8c,0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,
+0x00,0x00,0xc7,0x8c,0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,
+0x00,0x00,0x62,0x8c,0x1a,0x00,0x12,0x24,0x60,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf,
+0x30,0x00,0x04,0x26,0x20,0x00,0xa5,0x27,0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,
+0x13,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,
+0x04,0x00,0x04,0x8e,0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,
+0x10,0x00,0x07,0x8e,0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,
+0x24,0x20,0x83,0x00,0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,
+0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,
+0x24,0x20,0x82,0x00,0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,
+0x20,0x00,0x02,0x24,0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,
+0x14,0x00,0x06,0xae,0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,
+0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0x54,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,
+0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,
+0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,
+0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,
+0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,
+0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,
+0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,
+0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,
+0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,
+0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,
+0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,
+0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,
+0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,
+0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0xab,0x45,0x00,0x08,0x21,0x18,0x86,0x00,
+0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,
+0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,
+0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,
+0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0x40,0xa3,0x4b,0x24,
+0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,
+0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,
+0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,
+0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,
+0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,
+0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0xfa,0x45,0x00,0x08,
+0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,
+0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
+0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,
+0x0b,0x46,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,
+0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,
+0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,
+0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,
+0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,
+0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,
+0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,
+0x3c,0x46,0x00,0x08,0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,
+0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x00,0x00,0x82,0x80,0x48,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,
+0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,
+0x42,0x46,0x00,0x0c,0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,
+0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,
+0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,
+0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,
+0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,
+0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,
+0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,
+0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,
+0x00,0x00,0xc2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,
+0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,
+0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,
+0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,
+0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,
+0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
+0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,
+0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,
+0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x68,0xa4,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0,0xce,0x46,0x00,0x08,0x01,0x00,0x63,0x24,
+0x02,0x80,0x02,0x3c,0x68,0xa4,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,
+0x21,0x18,0x00,0x00,0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,
+0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,
+0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x02,0x80,0x02,0x3c,0x68,0xa4,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
+0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,
+0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,
+0x79,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
+0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,
+0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,
+0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,
+0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0,0x07,0x47,0x00,0x08,0x00,0x00,0x44,0xae,
+0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x42,0x46,0x00,0x0c,0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,
+0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0x42,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,
+0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,
+0x21,0x30,0x40,0x02,0x95,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,
+0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x23,0x47,0x00,0x08,
+0x21,0x10,0x20,0x02,0x01,0x80,0x02,0x3c,0x0c,0x1d,0x43,0x24,0x25,0xb0,0x02,0x3c,
+0xc0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x43,0xac,0x21,0xf0,0x00,0x00,0x02,0x80,0x15,0x3c,0x02,0x80,0x17,0x3c,
+0x02,0x80,0x16,0x3c,0x25,0xb0,0x05,0x3c,0x01,0x80,0x04,0x3c,0x0c,0x1d,0x82,0x24,
+0x18,0x03,0xa3,0x34,0x00,0x00,0x62,0xac,0xa0,0x02,0xa8,0x34,0x68,0x15,0xae,0x26,
+0x00,0x00,0x04,0x8d,0xe4,0x63,0xc3,0x95,0xff,0x0f,0x02,0x3c,0xff,0xff,0x47,0x34,
+0x24,0x98,0x87,0x00,0x01,0x00,0x06,0x3c,0x01,0x00,0x63,0x24,0x2b,0x10,0xd3,0x00,
+0x07,0x00,0x40,0x10,0xe4,0x63,0xc3,0xa5,0xa4,0x02,0xa2,0x34,0x00,0x00,0x54,0x8c,
+0x00,0xb0,0x03,0x3c,0x25,0x98,0x63,0x02,0x00,0x00,0x74,0xae,0x00,0x00,0x00,0xad,
+0xb0,0x02,0xa4,0x34,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x98,0x47,0x00,
+0x2b,0x18,0xd3,0x00,0x08,0x00,0x60,0x10,0x25,0xb0,0x02,0x3c,0x00,0xb0,0x02,0x3c,
+0x25,0x98,0x62,0x02,0x00,0x00,0x74,0x8e,0xb4,0x02,0xa2,0x34,0x00,0x00,0x54,0xac,
+0x00,0x00,0x80,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x4a,0x34,0x00,0x00,0x53,0x8d,
+0xff,0x00,0x05,0x3c,0xff,0xff,0xa2,0x34,0x2b,0x10,0x53,0x00,0x4f,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x11,0x3c,0x00,0x00,0x23,0x8e,0x00,0xff,0x09,0x3c,
+0xff,0x00,0x22,0x35,0x00,0xfd,0x08,0x3c,0x01,0x00,0x66,0x24,0x24,0x38,0x62,0x02,
+0xac,0x02,0x24,0x36,0xbc,0x02,0x23,0x36,0x05,0x00,0x02,0x35,0x00,0x00,0x86,0xac,
+0x2b,0x10,0x47,0x00,0x00,0x00,0x73,0xac,0x00,0x00,0x86,0x8c,0xb7,0x00,0x40,0x14,
+0xa6,0x00,0x02,0x35,0x04,0x00,0x02,0x35,0x2b,0x10,0xe2,0x00,0x39,0x00,0x40,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0xf8,0x03,0x3c,0x15,0x00,0x62,0x34,0x1d,0x04,0xe2,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x1e,0x01,0x40,0x14,0x00,0xf9,0x04,0x3c,
+0x00,0xf1,0x04,0x3c,0x20,0x04,0xe4,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00,
+0x82,0x01,0x40,0x14,0x10,0x00,0x62,0x34,0x00,0xf0,0x03,0x3c,0x01,0x00,0x62,0x34,
+0x5b,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x59,0x02,0x40,0x14,
+0x03,0x00,0x62,0x34,0x00,0xd0,0x02,0x3c,0x36,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x71,0x03,0x40,0x14,0x00,0xe0,0x02,0x3c,0x00,0xc0,0x02,0x3c,0x4b,0x05,0xe2,0x10,
+0x00,0x00,0x00,0x00,0x00,0xf0,0x02,0x3c,0x24,0x38,0x62,0x02,0x18,0x00,0xe2,0x10,
+0x0f,0x00,0x03,0x3c,0x00,0x70,0x09,0x3c,0x24,0x10,0x69,0x02,0x02,0x25,0x13,0x00,
+0xff,0xff,0x63,0x34,0x00,0x50,0x08,0x3c,0x24,0x28,0x63,0x02,0x02,0x57,0x02,0x00,
+0xff,0x00,0x84,0x30,0xa7,0x01,0xe8,0x10,0xff,0x00,0x66,0x32,0x2b,0x10,0x07,0x01,
+0x9b,0x01,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0xb5,0x03,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0xa3,0x02,0x40,0x14,0x00,0x30,0x02,0x3c,0xb2,0x03,0xe0,0x10,
+0x80,0x10,0x04,0x00,0x00,0x10,0x02,0x3c,0xaf,0x03,0xe2,0x10,0x80,0x10,0x04,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x07,0x3c,
+0x64,0x03,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x28,0x7e,0xe3,0xa2,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x28,0x7e,0xe2,0x92,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x55,0x00,0x40,0x10,0x68,0x15,0xa5,0x26,
+0x68,0x15,0xa6,0x26,0x00,0x40,0xc4,0x8c,0xe4,0x42,0xc5,0x8c,0xf0,0xff,0x02,0x24,
+0x24,0x20,0x82,0x00,0x00,0x50,0x03,0x3c,0x01,0x00,0x84,0x34,0x24,0x28,0xa3,0x00,
+0x00,0x10,0x02,0x3c,0x00,0x40,0xc4,0xac,0x95,0x03,0xa2,0x10,0xd6,0x42,0xc0,0xa0,
+0x28,0x7e,0xe2,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x40,0x00,0x40,0x10,
+0x68,0x15,0xa2,0x26,0x00,0x40,0x43,0x8c,0x0f,0xff,0x04,0x24,0x24,0x18,0x64,0x00,
+0x10,0x00,0x63,0x34,0x00,0x40,0x43,0xac,0x28,0x7e,0xe2,0x92,0x00,0x00,0x00,0x00,
+0x04,0x00,0x42,0x30,0x32,0x00,0x40,0x10,0x68,0x15,0xa2,0x26,0x00,0x40,0x43,0x8c,
+0xff,0xf0,0x04,0x24,0x24,0x18,0x64,0x00,0x00,0x01,0x63,0x34,0x25,0xb0,0x05,0x3c,
+0x00,0x40,0x43,0xac,0x4c,0x00,0xa3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x30,0x06,0x00,0x40,0x14,0x68,0x15,0xa4,0x26,0x00,0x40,0x83,0x8c,
+0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x83,0xac,
+0x60,0x7b,0xc4,0x8e,0x01,0x80,0x06,0x3c,0x0c,0x1e,0xc2,0x24,0x18,0x03,0xa3,0x34,
+0x60,0x7b,0xc6,0x26,0x00,0x00,0x62,0xac,0x11,0x00,0x86,0x10,0x02,0x80,0x02,0x3c,
+0xbf,0x00,0xb2,0x34,0x68,0x15,0x51,0x24,0x21,0x80,0xc0,0x00,0x21,0xf0,0x00,0x00,
+0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,0x09,0x00,0x40,0x10,
+0x02,0x80,0x02,0x3c,0xf8,0x65,0x24,0x8e,0x30,0x08,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x60,0x7b,0xc2,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x50,0x14,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x08,0x08,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0x58,0x47,0x00,0x08,0x25,0xb0,0x05,0x3c,
+0x00,0x40,0x43,0x8c,0xff,0xf0,0x04,0x24,0x01,0x48,0x00,0x08,0x24,0x18,0x64,0x00,
+0x00,0x40,0x43,0x8c,0x0f,0xff,0x04,0x24,0xf7,0x47,0x00,0x08,0x24,0x18,0x64,0x00,
+0x00,0x40,0xa4,0x8c,0xe4,0x42,0xa6,0x8c,0xf0,0xff,0x02,0x24,0x00,0x90,0x03,0x3c,
+0x24,0x20,0x82,0x00,0x24,0x18,0xc3,0x00,0x00,0x10,0x02,0x3c,0xb0,0xff,0x62,0x14,
+0x00,0x40,0xa4,0xac,0x50,0x0c,0xe3,0x34,0xff,0xbf,0x02,0x3c,0x00,0x00,0x64,0x90,
+0xff,0xff,0x42,0x34,0x24,0x10,0xc2,0x00,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,
+0xe4,0x42,0xa2,0xac,0xee,0x47,0x00,0x08,0xd7,0x42,0xa4,0xa0,0x55,0x03,0xe2,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x18,0x00,0x40,0x14,0x00,0xfe,0x03,0x3c,
+0x20,0x00,0x02,0x35,0x53,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0x85,0x00,0x40,0x14,
+0xa0,0x00,0x02,0x35,0x15,0x00,0x02,0x35,0x9d,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x17,0x01,0x40,0x14,0x17,0x00,0x02,0x35,0x08,0x00,0x02,0x35,0x16,0x04,0xe2,0x10,
+0x64,0x03,0x23,0x36,0x2b,0x10,0x47,0x00,0x24,0x02,0x40,0x14,0x09,0x00,0x02,0x35,
+0x07,0x00,0x02,0x35,0x53,0xff,0xe2,0x14,0x00,0x00,0x00,0x00,0xd9,0x58,0x00,0x0c,
+0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x18,0x00,0x62,0x34,
+0x42,0x03,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x95,0x00,0x40,0x14,
+0x07,0x00,0x22,0x35,0xad,0x00,0x02,0x35,0x8c,0x03,0xe2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x47,0x00,0xd2,0x00,0x40,0x14,0x10,0x00,0x62,0x34,0xaa,0x00,0x02,0x35,
+0x75,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x6e,0x01,0x40,0x14,
+0xab,0x00,0x02,0x35,0xa7,0x00,0x02,0x35,0x3b,0xff,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x00,0xff,0x62,0x32,0x02,0xa2,0x02,0x00,0x02,0x1c,0x13,0x00,0x01,0x00,0x02,0x24,
+0xbd,0x05,0x82,0x12,0xff,0x00,0x65,0x30,0x02,0x00,0x02,0x24,0xae,0x05,0x82,0x12,
+0xc0,0x10,0x05,0x00,0x03,0x00,0x02,0x24,0x9e,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,
+0x04,0x00,0x02,0x24,0xc5,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x08,0x00,0x02,0x24,
+0x29,0x06,0x82,0x12,0xc0,0x10,0x05,0x00,0x09,0x00,0x02,0x24,0x19,0x06,0x82,0x12,
+0xc0,0x10,0x05,0x00,0x0a,0x00,0x02,0x24,0x09,0x06,0x82,0x12,0xc0,0x10,0x05,0x00,
+0x0b,0x00,0x02,0x24,0xf9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x0c,0x00,0x02,0x24,
+0xe9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x0d,0x00,0x02,0x24,0xd9,0x05,0x82,0x12,
+0xc0,0x10,0x05,0x00,0x0e,0x00,0x02,0x24,0xc9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,
+0x0f,0x00,0x02,0x24,0xb9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x10,0x00,0x02,0x24,
+0x2b,0xff,0x82,0x16,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x58,0x51,0x44,0x94,0x54,0x51,0x45,0x94,0x25,0xb0,0x06,0x3c,0x00,0x24,0x04,0x00,
+0xc4,0x02,0xc3,0x34,0x21,0x28,0xa4,0x00,0x00,0x00,0x65,0xac,0x64,0x51,0x47,0x8c,
+0x60,0x51,0x43,0x8c,0x5c,0x51,0x44,0x94,0xc8,0x02,0xc6,0x34,0x21,0x18,0x67,0x00,
+0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0x00,0x00,0xc4,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x06,0x00,0x82,0x34,0xfe,0x02,0xe2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x47,0x00,0x52,0x00,0x40,0x14,0x01,0x00,0x82,0x34,0x3b,0x03,0xe2,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x6a,0x01,0x40,0x14,0x03,0x00,0x82,0x34,
+0x17,0x00,0x62,0x34,0xaa,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,
+0x7d,0x04,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0x62,0x34,0x40,0x05,0xe2,0x10,
+0x00,0x00,0x00,0x00,0xe3,0xfe,0xe4,0x14,0x68,0x15,0xa2,0x26,0x64,0x64,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x0b,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xf8,0x00,0x40,0x14,
+0xa3,0x00,0x02,0x35,0x22,0x00,0x02,0x35,0x8b,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,
+0xbb,0x01,0x40,0x14,0x68,0x15,0xa4,0x26,0x28,0x00,0x02,0x35,0xe7,0x04,0xe2,0x10,
+0x0f,0x00,0x10,0x3c,0x29,0x00,0x02,0x35,0xcf,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x02,0x1c,0x13,0x00,0x00,0x1f,0x62,0x32,0x68,0x15,0xb0,0x26,0x02,0xa2,0x02,0x00,
+0x3f,0x00,0x66,0x30,0xc1,0x42,0x06,0xa2,0xbc,0x42,0x14,0xa2,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x3b,0x15,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x21,0xa0,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x54,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x03,0x40,0x02,0x92,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xce,0x47,0x00,0x08,
+0x03,0x40,0x02,0xa2,0xf5,0x02,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,
+0x4d,0x00,0x40,0x14,0x0e,0x00,0x22,0x35,0x1a,0x00,0x62,0x34,0x43,0x03,0xe2,0x10,
+0x2b,0x10,0xe2,0x00,0x38,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0xf0,0x04,0xe9,0x10,
+0x00,0x00,0x00,0x00,0x01,0x00,0x22,0x35,0xa6,0xfe,0xe2,0x14,0x00,0x00,0x00,0x00,
+0x0e,0x4f,0x00,0x0c,0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0xfb,0x03,0x3c,0x02,0x00,0x62,0x34,0x14,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xd6,0x00,0x40,0x14,0x01,0x00,0x02,0x35,0x20,0x00,0x82,0x34,0xd2,0x03,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0x25,0x02,0x40,0x14,0x07,0x00,0x82,0x34,0x95,0xfe,0xe2,0x14,
+0x68,0x15,0xa2,0x26,0x48,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xea,0x02,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0xef,0x00,0x40,0x14,0x12,0x00,0x62,0x34,0x02,0x00,0x82,0x34,
+0xa3,0xfe,0xe2,0x10,0x2b,0x10,0xe2,0x00,0xa4,0x01,0x40,0x14,0x00,0xff,0x62,0x32,
+0x03,0x00,0x82,0x34,0xd6,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x82,0x34,
+0x81,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x02,0x14,0x13,0x00,0xff,0x00,0x54,0x30,
+0x00,0xff,0x63,0x32,0x07,0x00,0x82,0x2e,0x95,0xfe,0x40,0x10,0x02,0xf2,0x03,0x00,
+0x02,0x80,0x04,0x3c,0x84,0x9f,0x83,0x24,0x80,0x10,0x14,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
+0xec,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0x12,0x01,0x40,0x14,0x11,0x00,0x62,0x34,
+0xae,0x00,0x02,0x35,0x9e,0x04,0xe2,0x10,0x02,0x24,0x13,0x00,0xaf,0x00,0x02,0x35,
+0x68,0xfe,0xe2,0x14,0x00,0x00,0x00,0x00,0x76,0x50,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x0d,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xfa,0x00,0x40,0x14,0x0f,0x00,0x22,0x35,0x0c,0x00,0x22,0x35,0xf6,0x03,0xe2,0x10,
+0x68,0x15,0xa2,0x26,0x0d,0x00,0x22,0x35,0x5b,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x68,0x15,0xa3,0x26,0x01,0x00,0x02,0x24,0xce,0x47,0x00,0x08,0x46,0x64,0x62,0xa4,
+0x02,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0x15,0x01,0x40,0x14,0x00,0xa0,0x02,0x3c,
+0x00,0x60,0x02,0x3c,0x04,0x00,0xe2,0x10,0x80,0x10,0x04,0x00,0x69,0xfe,0xe9,0x14,
+0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26,
+0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0xc1,0x43,0x46,0xa0,
+0x07,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x37,0x01,0x40,0x14,0x00,0xff,0x62,0x32,
+0x18,0x00,0x02,0x35,0xe3,0x03,0xe2,0x10,0x19,0x00,0x02,0x35,0x3e,0xfe,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xc0,0x02,0x62,0x34,0x00,0x00,0x40,0xac,
+0x94,0x0e,0x64,0x34,0x9c,0x0e,0x62,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,
+0x00,0x00,0x89,0x8c,0x68,0x15,0xaf,0x26,0x00,0x00,0x4b,0x8c,0x00,0x00,0xac,0x8c,
+0x00,0x00,0xc4,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x40,0xe5,0x8d,0x10,0x40,0xe6,0x8d,
+0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,
+0x24,0x48,0x27,0x01,0x24,0x20,0x87,0x00,0x00,0x00,0x4d,0x8c,0x24,0x30,0xc8,0x00,
+0x02,0x4c,0x09,0x00,0x24,0x28,0xa8,0x00,0x02,0x24,0x04,0x00,0xcc,0x0e,0x68,0x34,
+0xf0,0xff,0x02,0x3c,0xc4,0x0e,0x63,0x34,0xff,0x03,0x42,0x34,0x25,0x28,0xa9,0x00,
+0x25,0x30,0xc4,0x00,0x00,0x00,0x69,0x8c,0x08,0x40,0xe4,0x8d,0x00,0x00,0x0e,0x8d,
+0x24,0x58,0x67,0x01,0x24,0x50,0x47,0x01,0x24,0x30,0xc2,0x00,0x24,0x28,0xa2,0x00,
+0x82,0x59,0x0b,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x03,0x3c,0xff,0x9f,0x02,0x3c,
+0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x25,0x28,0xab,0x00,0x25,0x30,0xca,0x00,
+0x24,0x60,0x87,0x01,0x24,0x68,0xa7,0x01,0xff,0x00,0x08,0x3c,0x24,0x20,0x82,0x00,
+0x24,0x30,0xc3,0x00,0x24,0x28,0xa3,0x00,0x24,0x70,0xc7,0x01,0x00,0x61,0x0c,0x00,
+0x00,0x69,0x0d,0x00,0x24,0x48,0x27,0x01,0x00,0xff,0x03,0x35,0x00,0x20,0x02,0x3c,
+0x25,0x20,0x82,0x00,0x25,0x28,0xac,0x00,0x25,0x30,0xcd,0x00,0x02,0x4c,0x09,0x00,
+0x02,0x74,0x0e,0x00,0x24,0x18,0x63,0x02,0x08,0x40,0xe4,0xad,0x0c,0x40,0xe5,0xad,
+0x10,0x40,0xe6,0xad,0x14,0x40,0xe9,0xa5,0x4d,0x04,0x60,0x10,0x16,0x40,0xee,0xa5,
+0x24,0x10,0x68,0x02,0x02,0x14,0x02,0x00,0x02,0x1a,0x13,0x00,0xc7,0x42,0xe2,0xa1,
+0xc3,0x42,0xe3,0xa1,0x68,0x15,0xa2,0x26,0xc3,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x92,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0xda,0x00,0x40,0x14,0xa4,0x00,0x02,0x35,
+0xa1,0x00,0x02,0x35,0x26,0x03,0xe2,0x10,0x02,0x24,0x13,0x00,0xa2,0x00,0x02,0x35,
+0xd8,0xfd,0xe2,0x14,0xc4,0x02,0x22,0x36,0x00,0xff,0xa3,0x34,0x24,0x18,0x63,0x02,
+0x00,0x00,0x45,0x8c,0x02,0xf2,0x03,0x00,0xb2,0x51,0x00,0x0c,0x21,0x20,0xc0,0x03,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x11,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,
+0xac,0x00,0x02,0x35,0xcb,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x8b,0x4f,0x00,0x0c,
+0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x46,0x03,0xe2,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x3e,0x01,0x40,0x14,0x02,0x00,0x02,0x35,
+0x03,0x00,0x62,0x34,0xfb,0x03,0xe2,0x10,0x68,0x15,0xa3,0x26,0xbe,0xfd,0xe8,0x14,
+0x00,0xf0,0x02,0x3c,0xcc,0x58,0x00,0x0c,0x21,0x20,0x60,0x02,0x00,0xff,0x63,0x32,
+0x00,0xcc,0x02,0x34,0xd3,0xfd,0x62,0x14,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,
+0xe4,0x42,0x43,0x8c,0x00,0x10,0x04,0x3c,0x25,0x18,0x64,0x00,0xce,0x47,0x00,0x08,
+0xe4,0x42,0x43,0xac,0x04,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x04,0x01,0x40,0x14,
+0x24,0x10,0x65,0x02,0x08,0x00,0x62,0x34,0x7b,0x03,0xe2,0x10,0x20,0x00,0x62,0x34,
+0xa8,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x07,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x0c,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x9e,0x00,0x40,0x14,
+0x00,0xff,0x62,0x32,0x13,0x00,0x62,0x34,0x75,0x03,0xe2,0x10,0x14,0x00,0x62,0x34,
+0x94,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x3a,0x0c,0x00,0x0c,0xfd,0x00,0x04,0x24,
+0x25,0xb0,0x03,0x3c,0x10,0x10,0x02,0x3c,0xa0,0x00,0x64,0x34,0x10,0x10,0x42,0x34,
+0x00,0x00,0x82,0xac,0x00,0xc0,0x02,0x3c,0xa8,0x00,0x65,0x34,0x00,0xa1,0x42,0x34,
+0xa4,0x00,0x63,0x34,0x00,0x00,0x60,0xac,0x00,0x00,0xa2,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0xd2,0x02,0xe2,0x10,0xc4,0x02,0x23,0x36,0x2b,0x10,0xe2,0x00,
+0x09,0x01,0x40,0x14,0x68,0x15,0xa2,0x26,0x04,0x00,0x82,0x34,0xaa,0x03,0xe2,0x10,
+0x68,0x15,0xa2,0x26,0x05,0x00,0x82,0x34,0x7a,0xfd,0xe2,0x14,0x68,0x15,0xa2,0x26,
+0x50,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa2,0x26,0x76,0x4b,0x44,0x90,
+0xc4,0x02,0x23,0x36,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xf2,0x02,0xe2,0x10,
+0x10,0x00,0x22,0x35,0x64,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x00,0xff,0x63,0x32,
+0x00,0xff,0x02,0x34,0xbe,0x03,0x62,0x10,0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08,
+0xec,0x65,0x40,0xac,0x5c,0x03,0xe2,0x10,0x00,0x00,0x00,0x00,0x12,0x00,0x62,0x34,
+0x58,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x68,0x15,0xa3,0x26,0x77,0x4b,0x7e,0xa0,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x0f,0x01,0xe2,0x10,0x00,0x40,0x02,0x3c,0x61,0xfd,0xe2,0x14,
+0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26,
+0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0xc1,0x43,0x46,0xa0,
+0xc4,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0xd3,0x00,0x40,0x14,0x00,0xb0,0x02,0x3c,
+0x00,0x90,0x02,0x3c,0x53,0xfd,0xe2,0x14,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,
+0x21,0x10,0x82,0x00,0xce,0x47,0x00,0x08,0x73,0x44,0x46,0xa0,0xe0,0x02,0xe2,0x10,
+0x25,0xb0,0x02,0x3c,0x14,0x00,0x02,0x35,0x2f,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0xff,0x00,0x04,0x3c,0x00,0xff,0x82,0x34,0x24,0x10,0x62,0x02,0x45,0xfd,0x40,0x10,
+0x25,0xb0,0x02,0x3c,0x68,0x15,0xa3,0x26,0x04,0x43,0x66,0x90,0x24,0x20,0x64,0x02,
+0x00,0xff,0x65,0x32,0x02,0x24,0x04,0x00,0x02,0x2a,0x05,0x00,0x00,0x01,0xc6,0x34,
+0xfb,0xff,0x87,0x24,0xfb,0xff,0xa2,0x24,0x1f,0x43,0x62,0xa0,0x04,0x43,0x66,0xac,
+0x1d,0x43,0x67,0xa0,0x1c,0x43,0x64,0xa0,0xce,0x47,0x00,0x08,0x1e,0x43,0x65,0xa0,
+0x08,0x40,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x02,0x34,0x13,0x00,0x00,0x1f,0x65,0x32,0x00,0x20,0x02,0x3c,0x25,0x18,0x62,0x00,
+0x02,0xa2,0x05,0x00,0x3f,0x00,0xc6,0x30,0xc1,0x42,0x86,0xa0,0x08,0x40,0x83,0xac,
+0xce,0x47,0x00,0x08,0xbc,0x42,0x94,0xa0,0x02,0x22,0x02,0x00,0x03,0x00,0x83,0x2c,
+0x24,0xfd,0x60,0x10,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08,
+0x02,0x40,0x44,0xa0,0xae,0x02,0xe2,0x10,0xa5,0x00,0x02,0x35,0x01,0xfd,0xe2,0x14,
+0x00,0x00,0x00,0x00,0x02,0x24,0x13,0x00,0xec,0x51,0x00,0x0c,0xff,0x00,0x84,0x30,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x22,0x02,0x00,0x21,0xa0,0x00,0x00,
+0xbf,0x4a,0x00,0x08,0x27,0xb0,0x07,0x3c,0x00,0x01,0x82,0x2e,0x0b,0x00,0x40,0x10,
+0x08,0x00,0xe7,0x24,0x00,0x00,0xe2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30,
+0xff,0x00,0xc3,0x33,0xf8,0xff,0x64,0x14,0x01,0x00,0x94,0x26,0xff,0xff,0x94,0x26,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xa4,0xff,0x00,0x82,0x2e,
+0x03,0xfd,0x40,0x14,0x25,0xb0,0x02,0x3c,0x12,0x87,0x03,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0xf2,0x02,0x00,
+0x80,0x00,0xc0,0x13,0x00,0x00,0x00,0x00,0x94,0x00,0x22,0x36,0x00,0x00,0x43,0x94,
+0xb0,0x03,0x25,0x36,0x68,0x15,0xa6,0x26,0xff,0xff,0x74,0x30,0x1b,0x00,0x9e,0x02,
+0x02,0x00,0xc0,0x17,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xb4,0xac,
+0xe6,0x4a,0xc7,0x94,0xff,0xff,0xc3,0x27,0x01,0x00,0x02,0x24,0xe3,0x4a,0xc2,0xa0,
+0x80,0xff,0x02,0x24,0x6a,0x03,0x2a,0x36,0x4f,0x00,0x2b,0x36,0x9e,0x00,0x2c,0x36,
+0x44,0x00,0x28,0x36,0xd8,0x00,0x2d,0x36,0x12,0xa0,0x00,0x00,0x80,0x22,0x14,0x00,
+0x00,0xf8,0x84,0x24,0x18,0x00,0xd4,0x03,0xff,0xff,0x7e,0x30,0x00,0x19,0x1e,0x00,
+0x25,0x18,0x62,0x00,0x26,0xb0,0x02,0x3c,0x7c,0x00,0x42,0x34,0x12,0x48,0x00,0x00,
+0x23,0x38,0xe9,0x00,0x00,0x00,0x47,0xa5,0x00,0x00,0xbe,0xac,0x00,0x00,0x63,0xa1,
+0x00,0x00,0xb4,0xac,0x00,0x00,0x94,0xa5,0x42,0xa1,0x04,0x00,0x00,0x00,0xb4,0xac,
+0x00,0x00,0x54,0xa4,0x00,0x00,0x03,0x95,0xff,0xfd,0x02,0x24,0xe8,0x4a,0xc7,0xa4,
+0x24,0x18,0x62,0x00,0x00,0x00,0x03,0xa5,0x00,0x00,0x02,0x95,0x00,0x00,0x00,0x00,
+0x00,0x02,0x42,0x34,0x00,0x00,0x02,0xa5,0x00,0x00,0xa3,0x91,0x00,0x00,0x00,0x00,
+0x40,0x00,0x63,0x34,0x00,0x00,0xa3,0xa1,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0xcc,0x02,0x23,0x36,0x00,0xff,0x64,0x32,0x02,0xf4,0x02,0x00,0x00,0x00,0x73,0xac,
+0x04,0x00,0xc0,0x13,0x02,0x9a,0x04,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,
+0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x0c,0x0f,0x00,0x10,0x3c,
+0xff,0xff,0x05,0x36,0x95,0x44,0x00,0x0c,0x21,0x20,0x60,0x02,0xff,0xff,0x10,0x36,
+0x24,0xa0,0x50,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xd6,0xfe,0xe2,0x10,0x00,0x00,0x00,0x00,
+0x90,0xfc,0xe3,0x14,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0x9a,0x02,0x00,
+0xcc,0x02,0x23,0x36,0x00,0x00,0x73,0xac,0x21,0x20,0x71,0x02,0x00,0x00,0x94,0x8c,
+0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xac,0x00,0x00,0x94,0x8c,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x7c,0x02,0xe2,0x10,0x25,0xb0,0x02,0x3c,0x03,0x00,0x02,0x35,
+0x81,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x68,0x15,0xa4,0x26,0xe4,0x42,0x83,0x8c,
+0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xe4,0x42,0x83,0xac,
+0xce,0x47,0x00,0x08,0xe6,0x42,0x80,0xa0,0x5c,0x64,0x44,0x90,0xc4,0x02,0x23,0x36,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x28,0x02,0xe3,0x10,
+0x01,0x00,0x62,0x34,0x70,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x68,0x15,0xa2,0x26,
+0xf8,0x63,0x43,0x8c,0xfd,0xff,0x04,0x24,0x24,0x18,0x64,0x00,0x01,0x00,0x63,0x34,
+0xce,0x47,0x00,0x08,0xf8,0x63,0x43,0xac,0x82,0xfc,0xe2,0x14,0x25,0xb0,0x02,0x3c,
+0x80,0x10,0x04,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00,0xce,0x47,0x00,0x08,
+0x60,0x45,0x45,0xac,0x25,0xb0,0x05,0x3c,0x4f,0x00,0xa2,0x34,0x9e,0x00,0xa3,0x34,
+0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94,
+0x9a,0x00,0xa4,0x34,0x98,0x00,0xa6,0x34,0xff,0xff,0x74,0x30,0x80,0x12,0x14,0x00,
+0x00,0xf8,0x42,0x24,0x42,0xa1,0x02,0x00,0x00,0x14,0x02,0x24,0x00,0x00,0x82,0xa4,
+0x26,0xb0,0x02,0x3c,0xb0,0x03,0xa7,0x34,0xa0,0x80,0x03,0x24,0x7c,0x00,0x42,0x34,
+0x00,0x00,0xc3,0xa4,0x44,0x00,0xa4,0x34,0x00,0x00,0xf4,0xac,0x00,0x00,0x54,0xa4,
+0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,0xd8,0x00,0xa5,0x34,0x24,0x18,0x62,0x00,
+0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,0x68,0x15,0xa6,0x26,0x00,0x02,0x42,0x34,
+0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0xbf,0xff,0x02,0x24,0xe8,0x4a,0xc0,0xa4,
+0x24,0x18,0x62,0x00,0xe3,0x4a,0xc0,0xa0,0x00,0x00,0xa3,0xa0,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26,
+0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0x34,0x43,0x46,0xa0,
+0xd7,0x42,0xc3,0x90,0x50,0x0c,0xe2,0x34,0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x68,0x15,0xa2,0x26,0xd7,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x68,0x15,0xa5,0x26,0xe4,0x42,0xa3,0x8c,0x00,0x40,0x04,0x3c,0xff,0x7f,0x02,0x3c,
+0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xee,0x47,0x00,0x08,
+0xe4,0x42,0xa3,0xac,0xee,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x08,0x40,0xc3,0x8d,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0xce,0x47,0x00,0x08,0x08,0x40,0xc3,0xad,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x77,0x4b,0xc4,0x91,
+0xc4,0x02,0x23,0x36,0xcc,0x02,0x22,0x36,0x00,0x00,0x53,0xac,0x00,0x00,0x64,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x6e,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x4c,0x64,0xc3,0x91,0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa5,0x34,0x24,0x28,0x65,0x02,
+0x02,0x2a,0x05,0x00,0x40,0x11,0x05,0x00,0x26,0xb0,0x04,0x3c,0x94,0x00,0x23,0x36,
+0x00,0x00,0x65,0xa4,0xc0,0xff,0x54,0x24,0x7c,0x00,0x8b,0x34,0x04,0x00,0x07,0x24,
+0x7a,0x00,0x84,0x34,0x00,0x04,0x02,0x24,0xa0,0x80,0x03,0x24,0x9a,0x00,0x26,0x36,
+0x98,0x00,0x28,0x36,0x96,0x00,0x29,0x36,0xb0,0x03,0x2a,0x36,0x00,0x00,0xc2,0xa4,
+0x00,0x00,0x03,0xa5,0x00,0x00,0x27,0xa5,0x00,0x00,0x87,0xa0,0x00,0x00,0x54,0xad,
+0x44,0x00,0x24,0x36,0x00,0x00,0x74,0xa5,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,
+0xe6,0x4a,0xc5,0xa5,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,
+0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x00,0x0f,0x62,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,
+0xda,0x02,0x83,0x10,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x24,0xdb,0x02,0x82,0x10,
+0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x24,0xf7,0x00,0x82,0x10,0x00,0x00,0x00,0x00,
+0xa6,0x50,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x04,0x43,0xc2,0x91,0xce,0x47,0x00,0x08,0x04,0x43,0xc2,0xad,0x0e,0x4f,0x00,0x0c,
+0x07,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x9a,0x4f,0x00,0x0c,
+0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x60,0x64,0xc3,0x91,
+0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0x9a,0x02,0x00,0xcc,0x02,0x23,0x36,
+0x00,0x00,0x73,0xac,0xc4,0x02,0x24,0x36,0x00,0x00,0x94,0x8c,0x21,0x10,0x71,0x02,
+0x00,0x00,0x54,0xac,0x00,0x00,0x54,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0xa0,0x00,0x00,0x16,0x4c,0x00,0x08,
+0x27,0xb0,0x04,0x3c,0x00,0x01,0x82,0x2e,0x0c,0x00,0x40,0x10,0x08,0x00,0x84,0x24,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0x30,0xff,0x00,0xc2,0x33,
+0xf0,0x00,0x42,0x28,0xf7,0xff,0x40,0x14,0x01,0x00,0x94,0x26,0xff,0xff,0x94,0x26,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x5e,0xa4,0xff,0x00,0x82,0x2e,
+0xab,0xfb,0x40,0x14,0x25,0xb0,0x02,0x3c,0x12,0x87,0x03,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xf8,0x63,0xc2,0x8d,
+0xfe,0xff,0x03,0x24,0x02,0x00,0x42,0x34,0x24,0x10,0x43,0x00,0xce,0x47,0x00,0x08,
+0xf8,0x63,0xc2,0xad,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x68,0x15,0xae,0x26,0x76,0x4b,0xc2,0x91,0x00,0x00,0x00,0x00,
+0x97,0xfb,0x40,0x14,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,
+0xcc,0x02,0x22,0x36,0x00,0x00,0x5e,0xac,0xc8,0x02,0x25,0x36,0xff,0x00,0xc3,0x33,
+0x01,0x00,0x02,0x24,0x00,0x00,0xa3,0xac,0x21,0x20,0xc0,0x03,0x76,0x4b,0xc2,0xa1,
+0xe3,0x18,0x00,0x0c,0x77,0x4b,0xde,0xa1,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa2,0x34,
+0x24,0x10,0x62,0x02,0x25,0xb0,0x05,0x3c,0x02,0xf2,0x02,0x00,0xcc,0x02,0xa3,0x34,
+0x01,0x00,0x02,0x24,0x00,0x00,0x7e,0xac,0x01,0x01,0xc2,0x13,0x68,0x15,0xa2,0x26,
+0x02,0x00,0xc2,0x2b,0x28,0x01,0x40,0x14,0x03,0x00,0x02,0x24,0x20,0x01,0xc2,0x13,
+0xc4,0x02,0xa3,0x34,0x68,0x15,0xa2,0x26,0x70,0x4b,0x44,0x94,0x25,0xb0,0x03,0x3c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08,0x46,0x64,0x40,0xa4,0x68,0x15,0xa2,0x26,
+0x21,0x10,0x82,0x00,0xce,0x47,0x00,0x08,0x56,0x44,0x46,0xa0,0x68,0x15,0xa2,0x26,
+0xce,0x47,0x00,0x08,0xec,0x65,0x40,0xac,0x00,0x1f,0x63,0x32,0x02,0x14,0x13,0x00,
+0x02,0xa2,0x03,0x00,0x3f,0x00,0x46,0x30,0x68,0x15,0xa3,0x26,0xc1,0x42,0x66,0xa0,
+0xce,0x47,0x00,0x08,0xbc,0x42,0x74,0xa0,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0xfd,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xae,0x26,0x08,0x40,0xc7,0x8d,0x00,0x00,0x40,0xad,0x42,0x17,0x07,0x00,
+0x03,0x00,0x42,0x30,0x5c,0x00,0x40,0x14,0x68,0x15,0xa2,0x26,0x03,0x0d,0x22,0x36,
+0x00,0x00,0x45,0x90,0x10,0x40,0xc6,0x8d,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,
+0xff,0x3f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0xe3,0x00,0x00,0x20,0x04,0x3c,
+0x24,0x60,0xc2,0x00,0x25,0x18,0x64,0x00,0x00,0x40,0x02,0x3c,0x70,0x00,0xa5,0x30,
+0x25,0x60,0x82,0x01,0x93,0x01,0xa0,0x10,0x08,0x40,0xc3,0xad,0x94,0x0e,0x22,0x36,
+0x9c,0x0e,0x23,0x36,0xa4,0x0e,0x24,0x36,0xac,0x0e,0x27,0x36,0x00,0x00,0x45,0x8c,
+0x00,0x00,0x69,0x8c,0x00,0x00,0x8b,0x8c,0x00,0x00,0xe6,0x8c,0x0c,0x40,0xc3,0x8d,
+0xb4,0x0e,0x22,0x36,0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24,
+0xbc,0x0e,0x22,0x36,0x24,0x28,0xa7,0x00,0x24,0x30,0xc7,0x00,0x24,0x20,0x88,0x01,
+0x02,0x2c,0x05,0x00,0x00,0x00,0x4c,0x8c,0x24,0x18,0x68,0x00,0x02,0x34,0x06,0x00,
+0xcc,0x0e,0x2d,0x36,0xc4,0x0e,0x28,0x36,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,
+0x25,0x18,0x65,0x00,0x25,0x20,0x86,0x00,0x00,0x00,0x05,0x8d,0x24,0x48,0x27,0x01,
+0x00,0x00,0xa6,0x8d,0x24,0x50,0x47,0x01,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,
+0x82,0x49,0x09,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x25,0x18,0x69,0x00,0x25,0x20,0x8a,0x00,0x24,0x58,0x67,0x01,0x24,0x60,0x87,0x01,
+0x24,0x20,0x82,0x00,0x24,0x30,0xc7,0x00,0x00,0x59,0x0b,0x00,0x24,0x18,0x62,0x00,
+0x00,0x61,0x0c,0x00,0x24,0x28,0xa7,0x00,0x25,0x18,0x6b,0x00,0x25,0x20,0x8c,0x00,
+0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0x16,0x40,0xc6,0xa5,0x0c,0x40,0xc3,0xad,
+0x10,0x40,0xc4,0xad,0x14,0x40,0xc5,0xa5,0x68,0x15,0xa3,0x26,0x0c,0x40,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x53,0x01,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x32,
+0x29,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0xc3,0x42,0x62,0xa0,
+0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0x38,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x68,0x15,0xa2,0x26,0x0c,0x40,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00,
+0x0c,0x40,0x43,0xac,0x68,0x15,0xa2,0x26,0xc3,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c,0x03,0x00,0x04,0x24,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xd2,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,
+0x02,0xf2,0x02,0x00,0x07,0x00,0x03,0x24,0x25,0x01,0xc3,0x13,0x02,0x80,0x04,0x3c,
+0x08,0x00,0xc2,0x2b,0x0a,0x01,0x40,0x10,0x20,0x00,0x02,0x24,0xd8,0xfa,0xc0,0x17,
+0x02,0x80,0x02,0x3c,0xe8,0x7d,0x43,0x94,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x24,0x13,0x00,
+0x0f,0x10,0x00,0x0c,0xff,0x00,0x84,0x30,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa2,0x26,0x58,0x64,0x44,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x24,0x10,0x65,0x02,0xcc,0x02,0x23,0x36,
+0x00,0xff,0x64,0x32,0x02,0xf4,0x02,0x00,0x00,0x00,0x73,0xac,0x04,0x00,0xc0,0x13,
+0x02,0x9a,0x04,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,
+0x21,0x20,0x00,0x00,0x25,0xb0,0x10,0x3c,0x2a,0x42,0x00,0x0c,0xc4,0x02,0x12,0x36,
+0x00,0x00,0x54,0x8e,0x0f,0x00,0x11,0x3c,0x21,0x20,0x60,0x02,0x21,0x30,0x80,0x02,
+0x6a,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x20,0x60,0x02,0x95,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0xc8,0x02,0x10,0x36,0x00,0x00,0x42,0xae,0x00,0x00,0x02,0xae,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x28,0xb0,0x02,0x3c,0x00,0x00,0x43,0x90,
+0xff,0x00,0x02,0x24,0xff,0x00,0x73,0x30,0xa5,0xfa,0x62,0x12,0xff,0x00,0x04,0x24,
+0x28,0xb0,0x05,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x73,0x30,0xfa,0xff,0x64,0x16,0x25,0xb0,0x02,0x3c,
+0xd0,0x47,0x00,0x08,0xc0,0x02,0x42,0x34,0x64,0x03,0x23,0x36,0x00,0x00,0x62,0x90,
+0x00,0x00,0x00,0x00,0xfa,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00,
+0xce,0x47,0x00,0x08,0xec,0x44,0x45,0xac,0x25,0xb0,0x03,0x3c,0xff,0x00,0x02,0x24,
+0x56,0x01,0x63,0x34,0x01,0x00,0x04,0x24,0x02,0x80,0x06,0x3c,0x00,0x00,0x62,0xa4,
+0xce,0x47,0x00,0x08,0x18,0x7e,0xc4,0xa0,0xa8,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x44,0x64,0x44,0x94,0x25,0xb0,0x03,0x3c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xa4,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x6e,0x4b,0x44,0x94,0xc4,0x02,0xa3,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x68,0x15,0xa4,0x26,0x08,0x40,0x83,0x8c,0xff,0x9f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xce,0x47,0x00,0x08,0x08,0x40,0x83,0xac,
+0x68,0x15,0xa3,0x26,0xff,0xff,0x02,0x34,0xce,0x47,0x00,0x08,0xec,0x65,0x62,0xac,
+0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x74,0x30,
+0x02,0x00,0x84,0x36,0x00,0x00,0x44,0xa0,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0xfd,0xff,0x03,0x24,0xfe,0xff,0x04,0x24,
+0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,0xce,0x47,0x00,0x08,0xf8,0x63,0xa2,0xac,
+0x34,0x0d,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa2,0x26,0x72,0x4b,0x44,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xda,0xfe,0xc0,0x17,0xc4,0x02,0xa3,0x34,
+0x68,0x15,0xa2,0x26,0x6c,0x4b,0x44,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x63,0x32,0x25,0xb0,0x02,0x3c,
+0x02,0x9a,0x03,0x00,0xcc,0x02,0x42,0x34,0x00,0x00,0x53,0xac,0xbf,0x00,0x60,0x12,
+0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x59,0x01,0x62,0x12,0x00,0x00,0x00,0x00,
+0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x28,0xb0,0x14,0x3c,0x00,0x00,0x82,0x96,0x02,0x1c,0x13,0x00,0xff,0x00,0x64,0x30,
+0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0x0c,0x00,0x83,0x10,0xff,0x7f,0x03,0x3c,
+0x08,0x00,0x94,0x26,0x00,0x00,0x82,0x96,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30,
+0xff,0x00,0xc3,0x33,0x05,0x00,0x83,0x10,0xff,0x7f,0x03,0x3c,0xff,0xff,0x82,0x32,
+0x00,0x08,0x42,0x2c,0xf6,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x34,
+0x25,0xb0,0x02,0x3c,0x24,0x18,0x83,0x02,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x74,0x30,0x05,0x00,0x84,0x36,0x00,0x00,0x44,0xa0,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa3,0x26,
+0xcc,0x02,0x42,0x34,0x76,0x4b,0x60,0xa0,0x21,0x20,0xc0,0x03,0x00,0x00,0x5e,0xac,
+0xe3,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xff,0xff,0x05,0x36,
+0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,
+0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,
+0x1f,0x00,0x54,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xa0,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x54,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0xff,0x65,0x32,0xff,0x00,0x84,0x30,0x28,0x50,0x00,0x0c,0x02,0x2a,0x05,0x00,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0xf8,0x63,0x62,0x8c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x34,
+0xce,0x47,0x00,0x08,0xf8,0x63,0x62,0xac,0xcd,0x4c,0x00,0x08,0x12,0x00,0x02,0x24,
+0xb8,0x59,0x00,0x0c,0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x0e,0x4f,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0xcf,0xf9,0xc2,0x17,0x02,0x80,0x06,0x3c,0x08,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x49,0x09,0x00,0x0c,0x21,0x20,0xc0,0x03,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x12,0x00,0x02,0x24,0xc7,0x42,0xe2,0xa1,0xc3,0x49,0x00,0x08,0xc3,0x42,0xe2,0xa1,
+0x01,0x0d,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa3,0x26,0xff,0xff,0x02,0x34,0xce,0x47,0x00,0x08,0xec,0x65,0x62,0xac,
+0xef,0x7d,0x83,0x90,0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0xd8,0x4c,0x00,0x08,
+0x68,0x15,0xa2,0x26,0x07,0x52,0x00,0x0c,0x10,0x40,0xcc,0xad,0xc5,0x4c,0x00,0x08,
+0x68,0x15,0xa3,0x26,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,
+0x21,0x10,0x45,0x00,0xec,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x80,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x7c,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x2a,0x42,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0xe0,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x45,0x00,0x0c,0x67,0x83,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,
+0x08,0x67,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,
+0x21,0x10,0x45,0x00,0x04,0x67,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,0x00,0x67,0xc3,0x24,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x45,0x00,0xfc,0x66,0x83,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,
+0xf8,0x66,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,
+0x21,0x10,0x45,0x00,0xf4,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,0xf0,0x66,0xc3,0x24,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c,
+0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c,
+0x02,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,
+0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x2c,0x43,0x64,0x94,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0x11,0x1e,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00,0x28,0x43,0x44,0x8c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x42,0x26,0x04,0x00,0x00,0x00,0x44,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x11,0x1e,0x00,0x68,0x15,0xa3,0x26,
+0x21,0x10,0x43,0x00,0x2b,0x43,0x44,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x01,0x00,0x84,0x30,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x32,0x43,0x64,0x94,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,
+0x31,0x43,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,
+0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00,
+0x21,0x18,0x62,0x00,0x30,0x43,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,
+0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x2e,0x43,0x64,0x94,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,0x04,0x30,0x86,0x00,
+0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x38,0x3c,0x42,0x24,0x18,0x03,0xa5,0x34,
+0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
+0x25,0xb0,0x03,0x3c,0x94,0x3c,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac,
+0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,0x21,0x20,0x00,0x00,
+0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,0x07,0x00,0x04,0x24,
+0x0e,0x4f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0xd0,0x3c,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xac,
+0x08,0x00,0xe0,0x03,0x24,0x7e,0x80,0xac,0x02,0x80,0x02,0x3c,0x68,0x7b,0x42,0x24,
+0xc0,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,0x00,0x60,0x06,0x40,
+0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x43,0x8c,
+0x21,0x28,0x40,0x00,0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,
+0x04,0x00,0x43,0xac,0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,0x00,0x60,0x86,0x40,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x21,0x18,0x80,0x00,0xe8,0xff,0xbd,0x27,
+0x01,0x01,0x62,0x2c,0x10,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,0x01,0x02,0x65,0x2c,
+0x0a,0x00,0x40,0x14,0x21,0x30,0x00,0x00,0x02,0x00,0x04,0x24,0x07,0x00,0xa0,0x14,
+0x01,0x08,0x62,0x2c,0x05,0x00,0x40,0x14,0x03,0x00,0x04,0x24,0x10,0x00,0xbf,0x8f,
+0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x3c,0x4f,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x30,0x40,0x00,0x21,0x10,0xc0,0x00,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x80,0x7b,0x62,0x8c,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c,
+0x68,0x7b,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,0x00,0x00,0x64,0xac,
+0x04,0x00,0x83,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,
+0x21,0x18,0x64,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,
+0x68,0x15,0x42,0x24,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x84,0x51,0x64,0x8c,
+0xff,0xf1,0x02,0x24,0x24,0x20,0x82,0x00,0x08,0x00,0xe0,0x03,0x84,0x51,0x64,0xac,
+0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,0x21,0x18,0x64,0x00,
+0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
+0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x84,0x51,0x64,0x8c,0xff,0xf1,0x02,0x24,
+0x24,0x20,0x82,0x00,0x00,0x02,0x84,0x34,0x08,0x00,0xe0,0x03,0x84,0x51,0x64,0xac,
+0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,
+0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
+0x80,0x80,0x10,0x00,0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x84,0x51,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,
+0xff,0xff,0x42,0x34,0xf8,0xff,0x03,0x24,0x7c,0x51,0x02,0xae,0x84,0x01,0x46,0x36,
+0x24,0x28,0xa3,0x00,0xff,0xfe,0x02,0x24,0x00,0x00,0xc7,0x8c,0x24,0x28,0xa2,0x00,
+0xff,0xef,0x03,0x24,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x28,0xa3,0x00,
+0x24,0x28,0xa2,0x00,0x80,0x51,0x07,0xae,0x84,0x51,0x05,0xae,0x6a,0x0f,0x00,0x0c,
+0x21,0x88,0x80,0x00,0x86,0x51,0x02,0x92,0x21,0x88,0x32,0x02,0x1c,0x00,0xbf,0x8f,
+0x60,0x01,0x22,0xa2,0x18,0x00,0xb2,0x8f,0x70,0x51,0x00,0xae,0x54,0x51,0x00,0xae,
+0x58,0x51,0x00,0xae,0x5c,0x51,0x00,0xae,0x60,0x51,0x00,0xae,0x64,0x51,0x00,0xae,
+0x68,0x51,0x00,0xae,0x6c,0x51,0x00,0xae,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00,
+0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c,
+0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x51,0x43,0x8c,
+0x25,0xb0,0x05,0x3c,0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90,
+0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30,
+0xff,0x00,0x49,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,
+0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,
+0x21,0x28,0x00,0x00,0xfd,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,
+0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,
+0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,
+0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,
+0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,
+0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,
+0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,
+0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,
+0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,
+0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,
+0x23,0x10,0x09,0x01,0x1e,0x50,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,
+0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c,
+0x84,0x51,0x43,0x8c,0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00,
+0x60,0x01,0x82,0x90,0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,
+0x21,0x18,0x66,0x00,0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c,
+0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,
+0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0x4b,0x50,0x00,0x08,
+0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,
+0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,
+0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,
+0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,
+0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,
+0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,
+0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,
+0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,
+0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,
+0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
+0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0x6c,0x50,0x00,0x08,
+0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
+0xd8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c,
+0x68,0x15,0x52,0x24,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x20,0x00,0xbf,0xaf,0xff,0x1f,0x73,0x34,0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02,
+0xaa,0x4f,0x00,0x0c,0x21,0x20,0x20,0x02,0x84,0x51,0x02,0x8e,0x21,0x28,0x00,0x00,
+0x24,0x10,0x53,0x00,0x00,0x20,0x42,0x34,0x84,0x51,0x02,0xae,0x86,0x51,0x03,0x92,
+0x00,0x00,0x00,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x72,0x00,0xec,0x44,0x64,0x8c,
+0x60,0x45,0x62,0x8c,0x00,0x00,0x00,0x00,0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00,
+0x50,0x51,0x02,0xae,0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28,
+0xc2,0x51,0x40,0xa0,0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xa5,0x51,0x40,0xa0,
+0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xe0,0x51,0x00,0xae,0xe4,0xff,0x40,0x14,
+0x94,0x00,0x10,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0xc0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x68,0x15,0x46,0x24,
+0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,
+0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0xec,0x65,0xc2,0x8c,0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30,
+0xff,0xff,0x42,0x38,0x0b,0x18,0x02,0x00,0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf,
+0xec,0x65,0xc4,0xac,0xb9,0x00,0xa0,0x11,0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c,
+0x50,0x9e,0x45,0x24,0x90,0x44,0xc4,0x24,0xc7,0x50,0x00,0x08,0x21,0x88,0x00,0x00,
+0x01,0x00,0x31,0x26,0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,
+0x01,0x00,0x84,0x24,0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,
+0xf7,0xff,0x40,0x10,0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
+0x00,0x00,0x83,0xa0,0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,
+0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xe8,0x9b,0x6c,0x24,
+0x70,0x9b,0x4b,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
+0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
+0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
+0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,
+0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
+0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,
+0x05,0x00,0x29,0x25,0xaf,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x48,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xe4,0x9e,0x69,0x24,0x70,0x9e,0x47,0x24,
+0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,
+0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,
+0x04,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xe4,0x9e,0x68,0x24,0x70,0x9e,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,
+0x21,0x10,0x88,0x00,0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,
+0x01,0x00,0x31,0x26,0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,
+0x1d,0x00,0x22,0x2a,0xec,0x44,0x83,0xac,0xf4,0xff,0x40,0x14,0x60,0x45,0x85,0xac,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x56,0x24,0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02,
+0xff,0x1f,0x57,0x34,0x21,0x88,0x00,0x00,0x21,0xa0,0x00,0x00,0x24,0x51,0x00,0x08,
+0x21,0x90,0xc0,0x02,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,
+0x3d,0x00,0x40,0x10,0x94,0x00,0x94,0x26,0x84,0x51,0x44,0x8e,0x01,0x00,0x03,0x24,
+0x02,0x13,0x04,0x00,0x01,0x00,0x53,0x30,0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,
+0x25,0xb0,0x03,0x3c,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,
+0x7c,0x51,0x43,0x8e,0x21,0x20,0x20,0x02,0x24,0x28,0xa3,0x00,0x6a,0x0f,0x00,0x0c,
+0x80,0x51,0x45,0xae,0x86,0x51,0x44,0x92,0xe9,0x0e,0x00,0x0c,0xff,0x00,0x25,0x32,
+0x84,0x51,0x42,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34,
+0x84,0x51,0x42,0xae,0x86,0x51,0x50,0x92,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02,
+0xff,0x0e,0x00,0x0c,0x80,0x80,0x10,0x00,0x21,0x80,0x16,0x02,0x54,0x51,0x40,0xae,
+0x58,0x51,0x40,0xae,0x5c,0x51,0x40,0xae,0x60,0x51,0x40,0xae,0x64,0x51,0x40,0xae,
+0x68,0x51,0x40,0xae,0x6c,0x51,0x40,0xae,0x70,0x51,0x40,0xae,0xec,0x44,0x04,0x8e,
+0x60,0x45,0x03,0x8e,0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00,
+0x42,0x18,0x03,0x00,0x04,0x00,0x04,0x24,0x0a,0xa8,0x82,0x00,0x50,0x51,0x43,0xae,
+0x21,0x20,0x9e,0x02,0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,
+0xc2,0x51,0x40,0xa0,0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xa5,0x51,0x40,0xa0,
+0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xe0,0x51,0x80,0xac,0x94,0x00,0x52,0x26,
+0xc5,0xff,0x40,0x14,0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,
+0x00,0x00,0x55,0xa0,0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,
+0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,0xec,0x65,0x40,0xac,0x3c,0x00,0xbf,0x8f,
+0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x50,0x9e,0x45,0x24,0x90,0x44,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,
+0x00,0x00,0x43,0x90,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,
+0xfa,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x0c,0x9d,0x6c,0x24,0xac,0x9b,0x4b,0x24,
+0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,
+0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0,
+0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,
+0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
+0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xe4,0x9e,0x68,0x24,0x70,0x9e,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,
+0x21,0x10,0x68,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,
+0x01,0x00,0x31,0x26,0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,
+0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x17,0x51,0x00,0x08,0x02,0x80,0x02,0x3c,
+0xd8,0xff,0xbd,0x27,0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,
+0x02,0x91,0x12,0x00,0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,
+0x80,0x88,0x11,0x00,0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
+0x80,0x88,0x11,0x00,0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
+0x10,0x00,0xb0,0xaf,0x84,0x51,0x30,0x8e,0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24,
+0x2b,0x18,0x03,0x00,0x00,0x10,0x10,0x36,0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00,
+0x00,0x04,0x82,0x30,0x25,0x80,0x03,0x02,0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24,
+0x24,0x80,0x03,0x02,0xc0,0x10,0x02,0x00,0x25,0x80,0x02,0x02,0x7c,0x51,0x25,0xae,
+0x84,0x51,0x30,0xae,0x3c,0x10,0x00,0x0c,0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24,
+0x24,0x80,0x03,0x02,0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32,
+0x25,0xb0,0x02,0x3c,0x80,0x18,0x03,0x00,0x84,0x51,0x30,0xae,0x21,0x18,0x62,0x00,
+0x84,0x01,0x62,0x8c,0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,0x6a,0x0f,0x00,0x0c,
+0x80,0x51,0x22,0xae,0x86,0x51,0x24,0x92,0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0xe9,0x0e,0x00,0x08,0x28,0x00,0xbd,0x27,0xaa,0x4f,0x00,0x08,0xff,0x00,0x84,0x30,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,0x84,0x51,0x62,0x8c,
+0xff,0xff,0x84,0x24,0x00,0x10,0x42,0x34,0x84,0x51,0x62,0xac,0xfb,0xff,0x81,0x04,
+0x94,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x23,0x10,0xa4,0x00,0x2b,0x18,0xa4,0x00,0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03,
+0x0b,0x10,0x83,0x00,0x20,0xff,0xbd,0x27,0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf,
+0xd8,0x00,0xbe,0xaf,0xd4,0x00,0xb7,0xaf,0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf,
+0xc4,0x00,0xb3,0xaf,0xc0,0x00,0xb2,0xaf,0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf,
+0x21,0xa8,0x00,0x00,0x40,0x11,0x15,0x00,0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00,
+0x07,0x00,0x16,0x24,0xff,0xff,0xd6,0x26,0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06,
+0x04,0x00,0x42,0x24,0x01,0x00,0xb5,0x26,0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14,
+0x40,0x11,0x15,0x00,0x25,0xb0,0x10,0x3c,0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac,
+0x04,0x00,0x03,0x36,0x00,0x00,0x62,0x8c,0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c,
+0x08,0x0c,0x04,0x36,0x0f,0x00,0x11,0x3c,0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c,
+0x24,0x10,0x51,0x00,0x02,0xf4,0x02,0x00,0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,
+0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x74,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xe0,0x0e,0x02,0x36,0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c,
+0xdc,0x0e,0x12,0x36,0x70,0x0e,0x13,0x36,0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e,
+0x74,0x0e,0x14,0x36,0x78,0x0e,0x15,0x36,0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e,
+0x7c,0x0e,0x16,0x36,0x80,0x0e,0x17,0x36,0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e,
+0xd4,0x0e,0x10,0x36,0xed,0x3f,0x11,0x3c,0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e,
+0xfb,0x92,0x25,0x36,0x88,0x00,0xa3,0xaf,0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,
+0x8c,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8e,0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34,
+0x90,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34,
+0x94,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34,
+0x98,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34,
+0x9c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf,
+0x00,0x00,0x02,0x8e,0x25,0xb0,0x03,0x3c,0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf,
+0x00,0x00,0x63,0x8c,0xf9,0x51,0x00,0x0c,0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02,
+0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0x60,0x02,0xf9,0x51,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x21,0x20,0x80,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x21,0x20,0xa0,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02,
+0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xe0,0x02,0xf9,0x51,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c,0xd8,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,
+0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c,
+0xdc,0x9f,0x63,0x24,0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,
+0x21,0xb0,0x00,0x00,0x02,0x80,0x02,0x3c,0xe0,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,
+0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c,
+0xe4,0x9f,0x63,0x24,0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,
+0x10,0x00,0xb7,0x27,0x21,0x20,0x00,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x02,0x80,0x02,0x3c,0xe8,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,0xf9,0x51,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0xe5,0x52,0x00,0x08,0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13,
+0x02,0x80,0x02,0x3c,0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,
+0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,
+0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,
+0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,
+0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,
+0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10,
+0x02,0x3c,0x07,0x00,0xe6,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10,
+0x00,0x00,0x00,0x00,0xe2,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,
+0x08,0x00,0x83,0x10,0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,
+0xe0,0x03,0x03,0x24,0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10,
+0x01,0x00,0x04,0x24,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11,
+0x00,0x00,0x00,0x00,0xd7,0x00,0x80,0x14,0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26,
+0x0a,0x00,0xa2,0x2e,0x01,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17,
+0x01,0x00,0x02,0x24,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0xf9,0x51,0x00,0x0c,
+0x04,0x0c,0x64,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0xf9,0x51,0x00,0x0c,
+0x08,0x0c,0x64,0x36,0x28,0x0e,0x64,0x36,0xf9,0x51,0x00,0x0c,0x80,0x80,0x05,0x3c,
+0x14,0x02,0x02,0x3c,0x48,0x01,0x45,0x34,0xf9,0x51,0x00,0x0c,0x40,0x0e,0x64,0x36,
+0x16,0x68,0x05,0x3c,0xa2,0x04,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x44,0x0e,0x64,0x36,
+0x4c,0x0e,0x64,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c,
+0x4d,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c,
+0xba,0x08,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36,
+0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34,
+0xf9,0x51,0x00,0x0c,0x48,0x0e,0x64,0x36,0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34,
+0xf9,0x51,0x00,0x0c,0x48,0x0e,0x64,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,
+0xa0,0x00,0x02,0x3c,0x33,0x54,0x45,0x34,0xf9,0x51,0x00,0x0c,0x04,0x0c,0x64,0x36,
+0x08,0x0c,0x64,0x36,0xf9,0x51,0x00,0x0c,0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36,
+0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17,
+0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c,0xec,0x9f,0x42,0x24,0x25,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0x8c,0x20,0x08,0x63,0x34,0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c,
+0x00,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c,
+0x00,0x01,0x45,0x34,0xf9,0x51,0x00,0x0c,0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c,
+0x30,0x54,0x65,0x34,0xf9,0x51,0x00,0x0c,0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c,
+0xe4,0x00,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36,
+0xf9,0x51,0x00,0x0c,0x80,0x80,0x05,0x3c,0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34,
+0xf9,0x51,0x00,0x0c,0x30,0x0e,0x44,0x36,0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34,
+0xf9,0x51,0x00,0x0c,0x34,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34,
+0xf9,0x51,0x00,0x0c,0x38,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34,
+0xf9,0x51,0x00,0x0c,0x3c,0x0e,0x44,0x36,0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34,
+0xf9,0x51,0x00,0x0c,0x40,0x0e,0x44,0x36,0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34,
+0xf9,0x51,0x00,0x0c,0x44,0x0e,0x44,0x36,0x4c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,
+0xd1,0x28,0x05,0x24,0x6c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24,
+0x00,0x01,0x03,0x3c,0x00,0x7c,0x65,0x34,0xf9,0x51,0x00,0x0c,0x50,0x0e,0x44,0x36,
+0x00,0x01,0x02,0x3c,0x00,0x48,0x45,0x34,0xf9,0x51,0x00,0x0c,0x54,0x0e,0x44,0x36,
+0x00,0x10,0x03,0x3c,0x23,0xdc,0x65,0x34,0xf9,0x51,0x00,0x0c,0x58,0x0e,0x44,0x36,
+0x00,0x10,0x02,0x3c,0x23,0x8c,0x45,0x34,0xf9,0x51,0x00,0x0c,0x5c,0x0e,0x44,0x36,
+0x14,0x02,0x03,0x3c,0x02,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x60,0x0e,0x44,0x36,
+0x16,0x28,0x05,0x3c,0x07,0x0d,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x64,0x0e,0x44,0x36,
+0x48,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,
+0xf9,0x51,0x00,0x0c,0x48,0x0e,0x44,0x36,0x00,0x02,0x10,0x3c,0xeb,0x0b,0x00,0x0c,
+0x03,0x00,0x04,0x24,0x4c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x36,
+0xd1,0x28,0x05,0x36,0xf9,0x51,0x00,0x0c,0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,
+0xf9,0x51,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0xf9,0x51,0x00,0x0c,
+0x48,0x0e,0x44,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f,
+0x04,0x0c,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f,
+0x08,0x0c,0x44,0x36,0xf9,0x51,0x00,0x0c,0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36,
+0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36,
+0x02,0x80,0x02,0x3c,0xec,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,0xf9,0x51,0x00,0x0c,
+0x00,0x01,0x05,0x3c,0x28,0x08,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0x01,0x05,0x3c,
+0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,
+0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,
+0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,
+0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,
+0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,
+0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,
+0x80,0x00,0x03,0x24,0x20,0xff,0x83,0x14,0x21,0x40,0x00,0x00,0xdb,0x52,0x00,0x08,
+0x21,0x20,0x00,0x00,0x00,0x00,0x62,0x8c,0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36,
+0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c,
+0xac,0x0e,0x67,0x36,0xb4,0x0e,0x65,0x36,0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00,
+0x04,0x00,0xe4,0xae,0x00,0x00,0xc3,0x8c,0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00,
+0x02,0x1c,0x03,0x00,0x08,0x00,0xe3,0xae,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c,
+0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae,
+0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae,
+0x25,0xb0,0x03,0x3c,0xcc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26,
+0x03,0x00,0xc2,0x2e,0xc7,0xfe,0x40,0x14,0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f,
+0x00,0x00,0x00,0x00,0x49,0x01,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f,
+0x00,0x00,0x00,0x00,0x06,0x00,0x20,0x16,0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f,
+0x00,0x00,0x00,0x00,0x29,0x00,0x40,0x10,0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02,
+0x02,0x52,0x00,0x0c,0x21,0x28,0x20,0x02,0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x34,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00,
+0x50,0x00,0xb2,0x8f,0x21,0x20,0x00,0x02,0x02,0x52,0x00,0x0c,0x21,0x28,0x40,0x02,
+0x03,0x00,0x42,0x2c,0x09,0x00,0x40,0x10,0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f,
+0x14,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,
+0x0e,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x21,0x20,0x20,0x02,0x02,0x52,0x00,0x0c,
+0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c,0xe0,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x54,0x00,0xa5,0x8f,0x34,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x2c,0xd9,0x00,0x40,0x10,0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24,
+0xdb,0x00,0xa2,0x10,0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00,
+0x02,0x80,0x0f,0x3c,0x21,0x28,0xa2,0x00,0x68,0x15,0xec,0x25,0x00,0x00,0xa6,0x8c,
+0x0c,0x00,0xa7,0x8c,0x0c,0x40,0x83,0x8d,0x10,0x40,0x84,0x8d,0x04,0x00,0xa8,0x8c,
+0x10,0x00,0xa9,0x8c,0x00,0xfc,0x02,0x24,0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c,
+0x24,0x20,0x82,0x00,0xff,0x03,0xc6,0x30,0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30,
+0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00,
+0xff,0x03,0x08,0x31,0xff,0x03,0x29,0x31,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,
+0x80,0x42,0x08,0x00,0x80,0x4a,0x09,0x00,0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c,
+0x18,0x00,0xa7,0x8c,0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00,
+0xff,0x03,0x4a,0x31,0xff,0x03,0x6b,0x31,0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00,
+0x24,0x18,0x62,0x00,0x00,0x5d,0x0b,0x00,0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,
+0x16,0x40,0x86,0xa5,0x0c,0x40,0x83,0xad,0x10,0x40,0x84,0xad,0x14,0x40,0x87,0xa5,
+0x68,0x15,0xf1,0x25,0x10,0x40,0x22,0x8e,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,
+0x4d,0x00,0x43,0x10,0x25,0xb0,0x12,0x3c,0x0c,0x40,0x23,0x8e,0x80,0x0c,0x44,0x36,
+0x00,0x00,0x88,0x8c,0x00,0x02,0x62,0x30,0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00,
+0x03,0x00,0x40,0x10,0xff,0x03,0x65,0x30,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,
+0x18,0x00,0xad,0x00,0x82,0x62,0x03,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,
+0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,
+0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36,
+0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,
+0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0xf9,0x51,0x00,0x0c,0x25,0x28,0xa6,0x00,
+0x94,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34,
+0xc0,0x03,0x10,0x32,0x24,0x28,0xb5,0x00,0x80,0x85,0x10,0x00,0xf9,0x51,0x00,0x0c,
+0x25,0x28,0xb0,0x00,0x10,0x40,0x2c,0x8e,0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,
+0x82,0x2a,0x0c,0x00,0xff,0x03,0xa5,0x30,0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30,
+0x03,0x00,0x60,0x10,0x82,0x6d,0x02,0x00,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,
+0x18,0x00,0xad,0x00,0x02,0x65,0x0c,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,
+0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,
+0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01,
+0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,
+0x25,0x28,0xa2,0x00,0xf9,0x51,0x00,0x0c,0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36,
+0x00,0x00,0x85,0x8c,0xc0,0x03,0x10,0x32,0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00,
+0xf9,0x51,0x00,0x0c,0x25,0x28,0xb0,0x00,0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c,
+0xf9,0x51,0x00,0x0c,0xe0,0x0e,0x04,0x36,0x7c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,
+0xdc,0x0e,0x04,0x36,0x80,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x70,0x0e,0x04,0x36,
+0x84,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f,
+0xf9,0x51,0x00,0x0c,0x78,0x0e,0x04,0x36,0x8c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,
+0x7c,0x0e,0x04,0x36,0x90,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x80,0x0e,0x04,0x36,
+0x94,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f,
+0xf9,0x51,0x00,0x0c,0x88,0x0e,0x04,0x36,0x9c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,
+0x8c,0x0e,0x04,0x36,0xa0,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0xd0,0x0e,0x04,0x36,
+0xa4,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f,
+0x88,0x0e,0x04,0x36,0xf9,0x51,0x00,0x0c,0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f,
+0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f,
+0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xff,0xff,0x05,0x36,
+0x95,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0x21,0x88,0x40,0x00,0xfd,0xff,0x06,0x24,
+0x01,0x00,0x42,0x34,0x24,0x30,0x46,0x00,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,
+0x1e,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
+0x03,0x00,0x26,0x36,0x6a,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0xdc,0x00,0xbf,0x8f,
+0xd8,0x00,0xbe,0x8f,0xd4,0x00,0xb7,0x8f,0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f,
+0xc8,0x00,0xb4,0x8f,0xc4,0x00,0xb3,0x8f,0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f,
+0xb8,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24,
+0xff,0x00,0x02,0x24,0x29,0xff,0xa2,0x14,0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c,
+0x94,0x0e,0x62,0x34,0x9c,0x0e,0x64,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,
+0x02,0x80,0x0f,0x3c,0x00,0x00,0x49,0x8c,0x68,0x15,0xed,0x25,0x00,0x00,0x8c,0x8c,
+0x00,0x00,0xae,0x8c,0x00,0x00,0xc7,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x40,0xa4,0x8d,
+0x10,0x40,0xa5,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24,
+0xbc,0x0e,0x62,0x34,0x24,0x48,0x26,0x01,0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c,
+0x24,0x28,0xa8,0x00,0x24,0x20,0x88,0x00,0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34,
+0x02,0x4c,0x09,0x00,0xc4,0x0e,0x63,0x34,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,
+0x25,0x28,0xa7,0x00,0x25,0x20,0x89,0x00,0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01,
+0x00,0x00,0x03,0x8d,0x24,0x50,0x46,0x01,0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,
+0x82,0x61,0x0c,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x25,0x20,0x8c,0x00,0x25,0x28,0xaa,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,
+0x24,0x28,0xa2,0x00,0x24,0x18,0x66,0x00,0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00,
+0x00,0x59,0x0b,0x00,0x24,0x38,0xe6,0x00,0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00,
+0x02,0x3c,0x07,0x00,0x02,0x1c,0x03,0x00,0x16,0x40,0xa3,0xa5,0x0c,0x40,0xa4,0xad,
+0x10,0x40,0xa5,0xad,0x4e,0x54,0x00,0x08,0x14,0x40,0xa7,0xa5,0x30,0x00,0xb1,0x8f,
+0xf6,0x53,0x00,0x08,0x21,0x20,0x00,0x02,0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,
+0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,
+0x68,0xa5,0xe7,0x24,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,
+0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,
+0xf4,0x57,0xc6,0x24,0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,
+0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,
+0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x03,0x0d,0x64,0x34,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30,
+0x70,0x00,0x93,0x32,0x63,0x00,0x60,0x12,0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32,
+0x00,0x00,0x82,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x21,0xb0,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x64,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c,0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36,
+0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02,
+0x25,0x30,0xd2,0x00,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,0x2a,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,
+0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0xeb,0x0b,0x00,0x0c,
+0x03,0x00,0x04,0x24,0x27,0x00,0x60,0x16,0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,
+0x42,0x00,0x42,0x34,0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,
+0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,
+0x00,0x80,0x06,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12,
+0x25,0xb0,0x02,0x3c,0x03,0x0d,0x42,0x34,0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x0f,0x00,0x10,0x3c,0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36,
+0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02,
+0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,
+0x28,0x00,0xb4,0xaf,0x02,0x80,0x14,0x3c,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf,
+0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x68,0x15,0x85,0x26,0x0c,0x40,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,
+0x06,0x00,0x16,0x24,0x08,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x42,0x17,0x02,0x00,
+0x03,0x00,0x42,0x30,0x5d,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c,0x68,0x15,0x85,0x26,
+0x0c,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x01,0x00,0x44,0x30,
+0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x40,0xa2,0x8c,0x00,0x00,0x00,0x00,
+0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0xef,0xff,0x44,0x14,0x25,0xb0,0x02,0x3c,
+0x0e,0x0c,0x44,0x34,0x00,0x00,0x83,0x90,0x00,0x01,0x02,0x24,0xff,0x00,0x63,0x30,
+0x01,0x00,0x63,0x24,0x59,0x02,0x62,0x10,0xff,0x00,0x62,0x30,0x00,0x00,0x82,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x84,0x26,0x10,0x40,0x82,0x8c,
+0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x73,0x02,0x43,0x10,0x0f,0x00,0x10,0x3c,
+0xc7,0x42,0x93,0x90,0x25,0xb0,0x02,0x3c,0x62,0x0c,0x42,0x34,0xff,0x00,0x63,0x32,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x90,0x26,
+0xc6,0x42,0x02,0x92,0x00,0x00,0x00,0x00,0x79,0x01,0x40,0x10,0x01,0x00,0x02,0x24,
+0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x70,0x00,0x42,0x30,0x9f,0x01,0x40,0x14,0xcc,0x00,0x02,0x24,0xc4,0x42,0x02,0x96,
+0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00,0x2b,0x18,0x53,0x00,0x23,0x10,0x62,0x02,
+0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c,0x6c,0x01,0x40,0x10,0x00,0x00,0x00,0x00,
+0xc4,0x42,0x03,0x92,0x63,0x0c,0x22,0x36,0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,0x08,0x40,0x66,0x8c,
+0xc2,0x42,0x73,0xa0,0x23,0x20,0x53,0x00,0x2b,0x38,0x62,0x02,0x23,0x90,0x62,0x02,
+0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00,0x3f,0x00,0xa5,0x30,0x3f,0x00,0xc4,0x30,
+0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,0x23,0x10,0x44,0x00,0x8a,0x01,0x40,0x16,
+0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00,0x21,0xa8,0xa0,0x00,0x02,0x80,0x17,0x3c,
+0x2b,0x28,0xc8,0x02,0x81,0x01,0xa0,0x10,0x68,0x15,0x82,0x26,0x80,0x10,0x08,0x00,
+0x68,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x40,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x25,0x04,0x00,0x68,0x15,0x86,0x26,0x0c,0x40,0xc3,0x8c,0x00,0x00,0x00,0x00,
+0xff,0x03,0x67,0x30,0xe9,0x01,0xe0,0x10,0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,
+0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,
+0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,
+0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,
+0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,
+0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,
+0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,
+0x21,0x28,0x60,0x00,0xf9,0x51,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,
+0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,
+0x10,0x00,0xa3,0xaf,0xf9,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x68,0x15,0x83,0x26,
+0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0x5b,0x01,0x40,0x04,0xc0,0x28,0x15,0x00,
+0x21,0x10,0xa3,0x00,0xac,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xad,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xae,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xaf,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xb0,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xb1,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xb2,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,
+0x21,0x10,0xa2,0x00,0xb3,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xee,0x7d,0xe3,0x92,
+0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0xfe,0xfe,0x62,0x14,
+0x00,0x00,0x00,0x00,0x68,0x15,0x82,0x26,0x08,0x40,0x43,0x8c,0x01,0x00,0x44,0x3a,
+0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,0x3f,0x00,0x63,0x30,0x01,0x00,0x84,0x30,
+0x87,0x01,0x80,0x10,0x23,0x28,0x43,0x00,0x42,0x18,0x12,0x00,0x40,0x10,0x03,0x00,
+0x21,0x90,0x43,0x00,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x62,0x02,0x50,0x01,0x40,0x10,0x2b,0x10,0x45,0x02,0x06,0x00,0x40,0x10,
+0x24,0x00,0x06,0x24,0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
+0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00,0x2b,0x28,0xc6,0x02,0x50,0x01,0xa0,0x10,
+0x68,0x15,0x82,0x26,0x80,0x10,0x06,0x00,0x68,0x15,0x83,0x26,0x21,0x10,0x43,0x00,
+0x18,0x40,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x68,0x15,0x83,0x26,
+0x10,0x40,0x70,0x8c,0x00,0x00,0x00,0x00,0x82,0x3a,0x10,0x00,0xff,0x03,0xe7,0x30,
+0x5a,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,
+0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,0x02,0x85,0x10,0x00,
+0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,
+0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,
+0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,0x88,0x0c,0x24,0x36,
+0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,
+0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,
+0xf9,0x51,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32,0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,
+0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,0xf9,0x51,0x00,0x0c,
+0x10,0x00,0xa3,0xaf,0x1c,0x56,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x0c,0x42,0x34,
+0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00,0xc0,0xff,0x02,0x3c,0x24,0x20,0x62,0x00,
+0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,0x7e,0x57,0x00,0x08,0x18,0x40,0xc3,0x24,
+0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0x0d,0x00,0x40,0x10,0x02,0x80,0x17,0x3c,
+0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,
+0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,
+0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,0x08,0x40,0xc2,0xac,0x02,0x80,0x17,0x3c,
+0xee,0x7d,0xe3,0x92,0x22,0x00,0x02,0x24,0x44,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
+0x43,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,
+0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x16,0x56,0x53,0x24,0x1e,0x57,0x72,0x24,
+0x21,0x88,0x00,0x00,0xa5,0x57,0x00,0x08,0x10,0x00,0xa4,0xaf,0x95,0x45,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x4d,0x00,0x40,0x10,0x68,0x15,0x85,0x26,0x01,0x00,0x31,0x26,
+0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,0x68,0x15,0x84,0x26,0xc0,0x80,0x11,0x00,
+0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,0x95,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,
+0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,
+0x68,0x15,0x85,0x26,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,
+0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x40,0xa3,0xac,
+0x68,0x15,0x84,0x26,0x0c,0x40,0x83,0x8c,0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00,
+0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x42,0x34,0x0c,0x40,0x83,0xac,0x00,0x00,0x40,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x16,0x56,0x00,0x08,0x68,0x15,0x85,0x26,
+0xc6,0x42,0x02,0xa2,0x52,0x56,0x00,0x08,0xc4,0x42,0x13,0xa6,0x50,0x55,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x62,0x56,0x00,0x08,0xc4,0x42,0x13,0xa6,0x25,0xb0,0x02,0x3c,
+0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24,
+0xc0,0xff,0x02,0x3c,0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,
+0xe0,0x57,0x00,0x08,0x18,0x40,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,
+0xb2,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,
+0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,
+0x25,0x10,0x43,0x00,0x90,0x57,0x00,0x08,0x08,0x40,0xc2,0xac,0x08,0x40,0xa3,0x8c,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,
+0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0xb9,0x57,0x00,0x08,
+0x25,0x18,0x62,0x00,0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x6c,0x56,0x00,0x08,0x68,0x15,0x83,0x26,0x30,0x40,0x43,0x8c,
+0x87,0x56,0x00,0x08,0x82,0x25,0x03,0x00,0x91,0x00,0xe0,0x10,0x21,0x40,0x00,0x00,
+0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38,0x24,0x00,0x08,0x24,
+0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x70,0xfe,0x60,0x10,0x20,0x00,0x15,0x24,
+0x68,0x15,0x83,0x26,0x0a,0x40,0x62,0x94,0x02,0x80,0x17,0x3c,0x3f,0x00,0x42,0x30,
+0x7e,0x56,0x00,0x08,0x21,0xa8,0x52,0x00,0x21,0x10,0xa3,0x00,0xb4,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x41,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x19,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x10,
+0x80,0x10,0x08,0x00,0x21,0x10,0x46,0x00,0x18,0x40,0x45,0x8c,0x25,0xb0,0x04,0x3c,
+0xf9,0x51,0x00,0x0c,0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34,
+0xb3,0x56,0x00,0x08,0x21,0x28,0x00,0x00,0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xb2,0xfe,0x60,0x14,
+0x23,0x30,0x52,0x00,0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x68,0x15,0x82,0x26,
+0x30,0x40,0x43,0x8c,0x41,0x57,0x00,0x08,0x82,0x25,0x03,0x00,0x00,0x00,0x80,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3d,0x56,0x00,0x08,0x68,0x15,0x84,0x26,
+0x23,0x10,0x92,0x00,0x2b,0x18,0x44,0x02,0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00,
+0xe2,0xfd,0x80,0x14,0x23,0xa8,0xb2,0x00,0x7d,0x56,0x00,0x08,0x21,0xa8,0x00,0x00,
+0x30,0x40,0xc5,0x8c,0x7a,0x58,0x00,0x08,0x25,0xb0,0x04,0x3c,0x27,0x00,0xa0,0x10,
+0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x40,0x45,0x8c,0x25,0xb0,0x04,0x3c,
+0xf9,0x51,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x9c,0x0c,0x84,0x34,
+0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x1c,0x56,0x00,0x08,0x00,0x00,0x00,0x00,
+0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
+0x2b,0x57,0x00,0x08,0x01,0x00,0x52,0x24,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,
+0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0xe8,0x03,0x04,0x24,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x44,0x56,0x00,0x08,0x25,0xb0,0x02,0x3c,0x30,0x40,0x65,0x8c,
+0xa6,0x58,0x00,0x08,0x25,0xb0,0x04,0x3c,0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,
+0x08,0x00,0x80,0x10,0x02,0x80,0x02,0x3c,0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,
+0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x4e,0x58,0x43,0xa0,
+0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x4e,0x58,0x44,0xa0,0x02,0x24,0x04,0x00,
+0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,
+0x20,0x00,0x84,0x2c,0x09,0x00,0x80,0x10,0x21,0x10,0x43,0x00,0x74,0x51,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,
+0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x50,0x79,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,
+0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xff,0x00,0x85,0x30,0xd2,0xff,0xa3,0x24,0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,
+0x04,0x00,0x63,0x2c,0x08,0x00,0x84,0x2c,0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,
+0xf0,0xff,0xa2,0x24,0xfc,0xff,0xa3,0x24,0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,
+0xff,0x00,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,
+0xfc,0xff,0xc0,0x10,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,
+0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,
+0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,0x30,0xa5,0xe7,0x24,
+0x68,0x15,0x08,0x25,0xff,0xff,0x09,0x34,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,
+0xf4,0x01,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0xe0,0x00,0x9c,0x64,0xc6,0x24,0xf4,0x63,0x09,0xad,0x0c,0x00,0xe3,0xac,
+0x14,0x00,0xe2,0xa0,0xf0,0x63,0x09,0xad,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0xee,0x7d,0x44,0x90,0x22,0x00,0x03,0x24,
+0x07,0x00,0x83,0x10,0x25,0xb0,0x04,0x3c,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x4c,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
+0xf5,0xff,0x40,0x10,0x02,0x80,0x11,0x3c,0x68,0x15,0x22,0x26,0xf0,0x63,0x43,0x8c,
+0x98,0x0c,0x84,0x34,0x21,0x10,0x00,0x00,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,
+0x00,0x00,0x83,0xa0,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x22,0x26,0xf4,0x63,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0x99,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x30,0x26,
+0xf0,0x63,0x04,0x8e,0xff,0xff,0x02,0x34,0xd7,0xff,0x82,0x10,0x00,0x00,0x00,0x00,
+0xe8,0x63,0x02,0x8e,0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,
+0x3f,0x00,0x43,0x2c,0x12,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0xf4,0x63,0x02,0x8e,
+0x02,0x19,0x04,0x00,0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x1e,0x00,0x60,0x18,
+0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,0x0c,0x09,0x84,0x34,0x13,0x13,0xa5,0x34,
+0xf9,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0xe4,0x42,0x43,0x8c,
+0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x30,0x59,0x00,0x08,0xe4,0x42,0x43,0xac,
+0xbd,0xff,0x40,0x10,0x01,0x00,0x03,0x24,0xe4,0x42,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0xb7,0xff,0x43,0x14,0x25,0xb0,0x04,0x3c,
+0x32,0x03,0x05,0x3c,0x0c,0x09,0x84,0x34,0xf9,0x51,0x00,0x0c,0x33,0x13,0xa5,0x34,
+0xe4,0x42,0x03,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x30,0x59,0x00,0x08,0xe4,0x42,0x03,0xae,0x22,0x02,0x05,0x3c,0x0c,0x09,0x84,0x34,
+0x6a,0x59,0x00,0x08,0x23,0x13,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34,
+0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x08,0x00,0x42,0x34,
+0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34,
+0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,
+0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,
+0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,
+0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,
+0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,0x02,0x3c,0x02,0x00,
+0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,0x02,0x32,0x04,0x00,
+0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xce,0x4c,0xa2,0xa0,0xbc,0x4c,0xa0,0xac,
+0xc0,0x4c,0xa0,0xac,0xc4,0x4c,0xa0,0xac,0x06,0x00,0x80,0x14,0xc8,0x4c,0xa0,0xac,
+0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xcc,0x4c,0xa2,0xa0,0x08,0x00,0xe0,0x03,
+0xcd,0x4c,0xa3,0xa0,0xcd,0x4c,0xa7,0xa0,0x08,0x00,0xe0,0x03,0xcc,0x4c,0xa6,0xa0,
+0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xcd,0x4c,0x66,0x90,0xcc,0x4c,0x65,0x90,
+0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,0x00,0x00,0x45,0xa0,
+0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xce,0x4c,0x60,0xa0,0x02,0x80,0x08,0x3c,
+0x68,0x15,0x04,0x25,0xce,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10,
+0x21,0x18,0x00,0x00,0xc0,0x4c,0x82,0x8c,0xbc,0x4c,0x85,0x8c,0x25,0xb0,0x03,0x3c,
+0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,0x0f,0x00,0x40,0x10,
+0x81,0x01,0x66,0x34,0xcd,0x4c,0x83,0x90,0xcc,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30,
+0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,0x68,0x15,0x02,0x25,
+0x01,0x00,0x03,0x24,0xc8,0x4c,0x40,0xac,0xbc,0x4c,0x40,0xac,0xc0,0x4c,0x40,0xac,
+0xc4,0x4c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xc4,0x4c,0x82,0x8c,
+0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,
+0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xc8,0x4c,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0xcd,0x4c,0x83,0x90,0xcc,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa0,
+0x00,0x00,0x23,0xa1,0xf2,0x59,0x00,0x08,0x68,0x15,0x02,0x25,0xcd,0x4c,0x83,0x90,
+0xcc,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,
+0x00,0x00,0x23,0xa1,0xf2,0x59,0x00,0x08,0x68,0x15,0x02,0x25,0x00,0x00,0x85,0xac,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0,
+0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10,
+0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf,
+0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90,
+0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10,
+0x68,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x46,0x64,0x43,0x96,
+0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0x1e,0x5a,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0x1e,0x5a,0x00,0x0c,0x21,0x80,0x40,0x00,
+0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32,
+0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0x94,0x44,0x64,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34,
+0x01,0x00,0x63,0x24,0x44,0x64,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4,
+0x3b,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,0x68,0x15,0x50,0x24,
+0xf8,0x63,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,0x01,0x00,0x63,0x30,
+0x10,0x00,0xa4,0x27,0x64,0x79,0x25,0x26,0x07,0x00,0x62,0x10,0x0a,0x00,0x06,0x24,
+0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x6c,0x45,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x21,0x28,0x00,0x00,0x64,0x79,0x24,0x26,0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24,
+0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0xfd,0x63,0x03,0xa2,0xfc,0x63,0x02,0xa2,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x54,0x4f,0x00,0x0c,
+0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,0xe4,0xff,0x40,0x10,
+0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,0x14,0x00,0x02,0xae,
+0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,0x0c,0x00,0x03,0xae,
+0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x30,0x08,0x00,0x0c,0x21,0x20,0x00,0x02,
+0x6e,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x60,0x6a,0x63,0x24,0x00,0x00,0x43,0xac,0x63,0x00,0x02,0x24,
+0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x02,0x80,0x02,0x3c,
+0xe8,0x7d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xeb,0x7d,0x66,0x90,
+0xf8,0x7d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x03,0x7e,0x69,0x90,
+0x05,0x7e,0x4a,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x08,0x7e,0x6b,0x90,
+0x0a,0x7e,0x4c,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c,
+0xf5,0x7d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x02,0x80,0x18,0x3c,
+0xea,0x7d,0x08,0x93,0x00,0x00,0x85,0xac,0xf6,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
+0x00,0x00,0x86,0xac,0x02,0x80,0x0f,0x3c,0xf7,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
+0x00,0x00,0x87,0xac,0x68,0x15,0xee,0x25,0x18,0x7e,0x40,0xa0,0xfd,0xff,0x02,0x24,
+0xd5,0x4a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,0xd4,0x4a,0xc3,0xa1,
+0xd8,0x4a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x0d,0x31,0x02,0x00,0x02,0x24,
+0xda,0x4a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac,
+0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,0x17,0x00,0xa2,0x11,0x02,0x80,0x02,0x3c,
+0xea,0x7d,0x02,0x93,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x05,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x2a,0x7e,0x40,0xa4,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c,0x68,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34,
+0x68,0x4b,0x82,0xac,0x15,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x07,0x07,0x63,0x34,
+0x64,0x4b,0x82,0xac,0x02,0x80,0x02,0x3c,0x60,0x4b,0x83,0xac,0x2a,0x7e,0x40,0xa4,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xef,0x7d,0x44,0x90,0x06,0x00,0x03,0x24,
+0x15,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x0a,0x00,0x82,0x10,0x00,0xe0,0x02,0x3c,
+0x68,0x15,0xe4,0x25,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x68,0x4b,0x82,0xac,
+0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x60,0x4b,0x83,0xac,0xd2,0x5a,0x00,0x08,
+0x64,0x4b,0x82,0xac,0x00,0x80,0x02,0x3c,0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c,
+0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,0x60,0x4b,0xc3,0xad,
+0xd2,0x5a,0x00,0x08,0x64,0x4b,0xc2,0xad,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34,
+0x1c,0x1c,0x03,0x3c,0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,
+0x60,0x4b,0xc3,0xad,0xd2,0x5a,0x00,0x08,0x64,0x4b,0xc2,0xad,0x25,0xb0,0x02,0x3c,
+0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
+0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x44,0x6c,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0xfd,0xbf,0x45,0x34,
+0x80,0x04,0x03,0x3c,0x25,0x28,0xa3,0x00,0x00,0x08,0x04,0x3c,0x02,0x80,0x02,0x3c,
+0x68,0x15,0x42,0x24,0x25,0x28,0xa4,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x65,0xac,
+0x04,0x4b,0x45,0xac,0xfc,0x4a,0x45,0xac,0x08,0x00,0x63,0x34,0x86,0x00,0x05,0x24,
+0x00,0x00,0x65,0xa4,0x08,0x4b,0x45,0xa4,0x00,0x4b,0x40,0xac,0x0a,0x4b,0x40,0xa4,
+0x0c,0x4b,0x45,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x30,0x5b,0x00,0x08,0x00,0x00,0x00,0x00,
+0x42,0xb0,0x02,0x3c,0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,
+0x21,0x20,0x00,0x00,0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,
+0x10,0x00,0xbf,0xaf,0x51,0x0e,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
+0x03,0x00,0x04,0x24,0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0x51,0x0e,0x00,0x08,
+0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,
+0x68,0x15,0x10,0x26,0x76,0x4b,0x00,0xa2,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,
+0x5e,0x5e,0x00,0x0c,0x21,0x88,0x00,0x02,0x48,0x01,0x02,0x24,0xec,0x63,0x02,0xae,
+0xe8,0x63,0x02,0xae,0x21,0x10,0x00,0x02,0x1f,0x00,0x03,0x24,0xff,0xff,0x63,0x24,
+0xd0,0x4c,0x40,0xa4,0xd2,0x4c,0x40,0xa4,0xd4,0x4c,0x40,0xa4,0xd6,0x4c,0x40,0xa4,
+0xd8,0x4c,0x40,0xa4,0xda,0x4c,0x40,0xa4,0xdc,0x4c,0x40,0xa4,0xde,0x4c,0x40,0xa4,
+0xe0,0x4c,0x40,0xa4,0xf5,0xff,0x61,0x04,0x24,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,
+0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c,0x8c,0x58,0x84,0x24,
+0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,
+0x2c,0x5f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x5f,0x00,0x0c,0xec,0x65,0x20,0xae,
+0xea,0x60,0x00,0x0c,0x00,0x00,0x00,0x00,0x0a,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x02,0x80,0x03,0x3c,0xee,0x7d,0x64,0x90,0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0x49,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,0x2f,0x61,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xce,0x5f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb7,0x61,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x44,0x64,0x20,0xa6,0x9d,0x61,0x00,0x0c,0x46,0x64,0x20,0xa6,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x04,0x3c,
+0x02,0x80,0x05,0x3c,0x58,0x7b,0x82,0x24,0x60,0x7b,0xa3,0x24,0x20,0x00,0xbd,0x27,
+0x04,0x00,0x42,0xac,0x58,0x7b,0x82,0xac,0x60,0x7b,0xa3,0xac,0x08,0x00,0xe0,0x03,
+0x04,0x00,0x63,0xac,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,
+0x25,0xb0,0x10,0x3c,0x18,0x03,0x03,0x36,0x2c,0x6e,0x42,0x24,0x00,0x00,0x62,0xac,
+0x14,0x00,0xbf,0xaf,0x98,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x12,0x5c,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x3a,0x5e,0x00,0x0c,
+0xe7,0x60,0x43,0xa0,0x09,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x41,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x43,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36,
+0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,
+0x11,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x06,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00,0xcb,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x80,0x04,0x3c,0x14,0x29,0x84,0x24,0x23,0x5e,0x00,0x0c,0x01,0x00,0x05,0x24,
+0x01,0x80,0x04,0x3c,0x0c,0x1d,0x84,0x24,0x23,0x5e,0x00,0x0c,0x02,0x00,0x05,0x24,
+0x34,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0x88,0x3a,0x84,0x24,
+0x23,0x5e,0x00,0x0c,0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,0xf8,0x7d,0x43,0x90,
+0x43,0x00,0x04,0x36,0x29,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24,
+0x2b,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34,
+0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34,
+0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c,
+0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,
+0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,
+0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,
+0x18,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,
+0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,
+0x30,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,
+0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,
+0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c,
+0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0x18,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0x30,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x21,0x20,0x00,0x00,0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34,
+0x21,0x18,0x86,0x00,0x04,0x00,0x84,0x24,0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac,
+0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xb8,0xff,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,
+0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,
+0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,
+0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,
+0x0c,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x10,0x00,0x42,0x30,0x66,0x01,0x40,0x10,0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34,
+0x50,0x00,0x82,0x34,0x00,0x00,0x45,0xac,0x00,0x00,0x65,0xa4,0x36,0x5c,0x00,0x08,
+0x02,0x80,0x03,0x3c,0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,
+0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c,
+0x68,0x15,0x62,0x24,0xd5,0x4a,0x43,0x90,0xda,0x4a,0x45,0x94,0x25,0xb0,0x1e,0x3c,
+0x1c,0x00,0xa3,0xa3,0x60,0x4b,0x43,0x8c,0x58,0x00,0xc6,0x37,0xff,0xff,0x04,0x24,
+0x10,0x00,0xa3,0xaf,0x64,0x4b,0x43,0x8c,0x5c,0x00,0xc7,0x37,0x60,0x00,0xc8,0x37,
+0x14,0x00,0xa3,0xaf,0x68,0x4b,0x42,0x8c,0x64,0x00,0xc9,0x37,0x8a,0x00,0xca,0x37,
+0x18,0x00,0xa2,0xaf,0x24,0x10,0x02,0x3c,0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,
+0x00,0xe0,0x42,0x34,0x00,0x00,0xc2,0xac,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24,
+0x00,0x00,0xe3,0xac,0x89,0x00,0xcb,0x37,0x00,0x00,0x04,0xad,0x8c,0x00,0xcc,0x37,
+0x00,0x00,0x24,0xad,0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa5,0x10,0x10,0x02,0x24,
+0x00,0x00,0x63,0xa1,0x8e,0x00,0xcd,0x37,0x00,0x00,0x82,0xa5,0x0a,0x0a,0x03,0x24,
+0x13,0x00,0x02,0x24,0x90,0x00,0xce,0x37,0x00,0x00,0xa3,0xa5,0x00,0x00,0xc2,0xa1,
+0x25,0xb0,0x02,0x3c,0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
+0x25,0xb0,0x03,0x3c,0x3a,0x01,0x02,0x24,0x92,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,
+0xb5,0x00,0xd1,0x37,0x21,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x10,0x00,0xa2,0x8f,
+0xa0,0x00,0xd2,0x37,0xa4,0x00,0xd3,0x37,0x00,0x00,0x42,0xae,0x14,0x00,0xa3,0x8f,
+0xa8,0x00,0xd4,0x37,0xac,0x00,0xd5,0x37,0x00,0x00,0x63,0xae,0x18,0x00,0xa2,0x8f,
+0x25,0xb0,0x03,0x3c,0xb0,0x00,0x63,0x34,0x00,0x00,0x82,0xae,0x21,0x10,0x02,0x3c,
+0xff,0x77,0x42,0x34,0x00,0x00,0xa2,0xae,0x25,0xb0,0x02,0x3c,0xd8,0x00,0x42,0x34,
+0x00,0x00,0x65,0xac,0x00,0x00,0x40,0xa0,0x1c,0x00,0xa2,0x93,0x25,0xb0,0x03,0x3c,
+0xb4,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x24,
+0xb6,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x0f,0x00,0x02,0x24,
+0xba,0x00,0x63,0x34,0xb9,0x00,0xdf,0x37,0x00,0x00,0xe4,0xa3,0x00,0x00,0x62,0xa4,
+0x25,0xb0,0x02,0x3c,0x1a,0x01,0x42,0x34,0x16,0x01,0xd0,0x37,0x18,0x01,0xcf,0x37,
+0x00,0x00,0x00,0xa6,0x25,0xb0,0x03,0x3c,0x00,0x00,0xe0,0xa5,0x00,0x00,0x40,0xa4,
+0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34,0x00,0x00,0x62,0xac,
+0x2f,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34,0xd0,0x01,0x42,0x34,
+0x00,0x00,0x43,0xac,0x5e,0x00,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x32,0x43,0x42,0x34,
+0xd4,0x01,0x63,0x34,0x00,0x00,0x62,0xac,0x08,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x30,0xa5,0x63,0x34,0xd8,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x01,0xc4,0x37,
+0x02,0x80,0x03,0x3c,0x49,0xa5,0x02,0x34,0xee,0x7d,0x6d,0x90,0x00,0x00,0x82,0xac,
+0xc2,0x00,0x02,0x3c,0x1a,0x06,0x03,0x24,0x51,0x10,0x42,0x34,0xe0,0x01,0xc5,0x37,
+0xf4,0x01,0xc6,0x37,0xf8,0x01,0xc7,0x37,0x07,0x07,0x04,0x24,0x00,0x00,0xa3,0xa4,
+0x00,0x02,0xc8,0x37,0x00,0x00,0xc4,0xa4,0x26,0x00,0x03,0x24,0x00,0x00,0xe2,0xac,
+0x03,0x02,0xc9,0x37,0x04,0x00,0x02,0x24,0x00,0x00,0x03,0xa5,0x36,0x02,0xca,0x37,
+0x00,0x00,0x22,0xa1,0xc0,0x01,0x03,0x24,0x0c,0x00,0x02,0x24,0x34,0x02,0xcb,0x37,
+0x00,0x00,0x42,0xa1,0x37,0x02,0xcc,0x37,0x00,0x00,0x63,0xa5,0x03,0x00,0x02,0x24,
+0x22,0x00,0x03,0x24,0x00,0x00,0x82,0xa1,0xd6,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c,
+0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37,
+0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37,
+0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac,
+0x02,0x80,0x03,0x3c,0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac,
+0x00,0x00,0x02,0xad,0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0xee,0x7d,0x65,0x90,
+0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34,
+0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xb5,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c,
+0x92,0x00,0x02,0x24,0xb2,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c,
+0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24,
+0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35,
+0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad,
+0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac,
+0x25,0xb0,0x05,0x3c,0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35,
+0xf0,0x0f,0x03,0x24,0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35,
+0x00,0x00,0x42,0xad,0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,
+0x00,0x00,0x6d,0xad,0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2,0x00,0x00,0xe2,0xa2,
+0x25,0xb0,0x02,0x3c,0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0x42,0x34,
+0x00,0x00,0xc9,0xae,0x03,0x04,0x04,0x3c,0x00,0x00,0x49,0xac,0x07,0x08,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x01,0x02,0x84,0x34,0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34,
+0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,0x00,0x00,0x44,0xac,
+0x00,0x00,0x23,0xae,0x25,0xb0,0x02,0x3c,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,
+0x25,0xb0,0x03,0x3c,0x0c,0x00,0x06,0x24,0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34,
+0x0d,0x00,0x08,0x24,0xc2,0x01,0x63,0x34,0xc3,0x01,0x42,0x34,0x00,0x00,0x86,0xa2,
+0xc4,0x01,0xab,0x34,0x00,0x00,0xa6,0xa2,0xc5,0x01,0xac,0x34,0x00,0x00,0x66,0xa0,
+0x0e,0x00,0x07,0x24,0x00,0x00,0x48,0xa0,0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,
+0x0f,0x00,0x02,0x24,0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,
+0x00,0x00,0xa2,0xa1,0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,
+0x0e,0xe2,0x42,0x34,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf,
+0x4d,0x00,0xb9,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3,
+0x25,0xb0,0x02,0x3c,0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,
+0x25,0xb0,0x03,0x3c,0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,
+0x00,0x00,0x00,0xa3,0xd8,0x00,0xa7,0x34,0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90,
+0x80,0xff,0x02,0x24,0x2a,0xb0,0x04,0x3c,0x25,0x18,0x62,0x00,0x00,0x00,0xe3,0xa0,
+0x26,0xb0,0x06,0x3c,0x30,0x00,0x89,0x34,0x20,0x20,0x02,0x24,0x38,0x00,0x84,0x34,
+0x40,0x00,0x03,0x24,0x00,0x00,0x82,0xa4,0x79,0x00,0xc8,0x34,0x00,0x00,0x23,0xa1,
+0x94,0x00,0xaa,0x34,0x16,0x00,0x02,0x24,0x64,0x00,0x03,0x24,0x00,0x00,0x02,0xa1,
+0x7c,0x00,0xd2,0x34,0x00,0x00,0x43,0xa5,0x98,0x00,0xab,0x34,0x7a,0x00,0xc6,0x34,
+0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x00,0x00,0x62,0xa5,0x9c,0x00,0xac,0x34,
+0x00,0x00,0xc3,0xa0,0x20,0x0c,0x02,0x24,0x0a,0x00,0x03,0x24,0x00,0x00,0x42,0xa6,
+0x9a,0x00,0xad,0x34,0x00,0x00,0x83,0xa1,0x96,0x00,0xae,0x34,0xff,0x03,0x02,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,
+0x20,0x00,0x02,0x24,0xb7,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x89,0x00,0xb1,0x34,
+0x09,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x44,0x00,0xa5,0x34,0x00,0x00,0xa3,0x94,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x46,0x24,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,
+0x00,0x00,0xa3,0xa4,0x00,0x00,0xa2,0x94,0xd5,0x4a,0xc4,0x90,0x04,0x02,0x03,0x24,
+0x00,0x02,0x42,0x34,0x00,0x00,0xa2,0xa4,0x29,0xb0,0x02,0x3c,0x40,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa4,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f,
+0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,
+0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,
+0x20,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,
+0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,
+0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xa4,0x36,0x5c,0x00,0x08,0x02,0x80,0x03,0x3c,
+0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0xea,0x5c,0x00,0x08,
+0xff,0xff,0x0e,0x24,0xc8,0x5c,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c,
+0x00,0x00,0x62,0xa4,0x94,0x8d,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
+0x02,0x80,0x02,0x3c,0x8c,0x87,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x04,0x78,0x42,0x24,
+0x02,0x80,0x03,0x3c,0x2c,0x7e,0xa2,0xac,0x00,0x80,0x02,0x3c,0xcc,0x7e,0x60,0xac,
+0x2c,0x7e,0xa4,0x24,0x02,0x80,0x03,0x3c,0xc8,0x06,0x42,0x24,0xd0,0x7e,0x60,0xa4,
+0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0xd2,0x7e,0x60,0xa4,
+0x02,0x80,0x06,0x3c,0xa4,0x0a,0x42,0x24,0x00,0x80,0x03,0x3c,0xd4,0x7e,0xc7,0x24,
+0x14,0x00,0x82,0xac,0x54,0x08,0x63,0x24,0x02,0x80,0x02,0x3c,0xd4,0x7e,0xc0,0xac,
+0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac,0xdc,0x7e,0x40,0xa0,0x00,0x80,0x02,0x3c,
+0x1c,0x1c,0x42,0x24,0x3c,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,
+0x38,0x0d,0x63,0x24,0xc8,0x10,0x42,0x24,0x1c,0x00,0x83,0xac,0x20,0x00,0x82,0xac,
+0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x54,0x14,0x63,0x24,0x38,0x18,0x42,0x24,
+0x24,0x00,0x83,0xac,0x28,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,
+0x10,0x22,0x63,0x24,0xd0,0x04,0x42,0x24,0x2c,0x00,0x83,0xac,0x30,0x00,0x82,0xac,
+0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x78,0x1c,0x63,0x24,0x00,0x03,0x42,0x24,
+0x38,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,0x4c,0x00,0x82,0xac,0x25,0xb0,0x02,0x3c,
+0x08,0x00,0x42,0x34,0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x0e,0x3c,0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0xf8,0x03,0x4d,0x24,0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,
+0xff,0xff,0x0a,0x24,0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,
+0x00,0x00,0x42,0xac,0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,
+0x08,0x00,0x45,0x24,0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,
+0x00,0x00,0x44,0xac,0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,
+0x6c,0x00,0xa3,0xac,0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0xc9,0xad,0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,
+0x02,0x80,0x02,0x3c,0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,
+0x21,0x30,0x62,0x00,0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,
+0x00,0x00,0x00,0x00,0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,
+0x90,0x00,0xc5,0xac,0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,
+0x25,0xb0,0x04,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,0xe8,0x78,0x42,0x24,
+0xe0,0xff,0xbd,0x27,0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,0xdb,0xff,0x03,0x24,
+0x27,0x00,0x84,0x34,0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x83,0xa0,0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,0x01,0x00,0x11,0x24,
+0x21,0x80,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,0x01,0x00,0x02,0x26,
+0xff,0x00,0x50,0x30,0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,0x00,0x00,0x00,0x00,
+0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x40,0x10,0x03,0x3c,0xff,0xff,0x44,0x30,
+0x25,0xc0,0x83,0x00,0xf4,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0x00,0x65,0x58,0xac,
+0x40,0x00,0x18,0x27,0x0c,0x65,0x58,0xac,0x40,0x00,0x18,0x27,0x18,0x65,0x58,0xac,
+0x40,0x00,0x18,0x27,0xe0,0xff,0xbd,0x27,0x24,0x65,0x58,0xac,0x40,0x00,0x18,0x27,
+0x1c,0x00,0xb7,0xaf,0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,
+0x0c,0x00,0xb3,0xaf,0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,
+0x30,0x65,0x58,0xac,0x00,0x65,0x45,0x8c,0x0c,0x65,0x46,0x8c,0x18,0x65,0x47,0x8c,
+0x24,0x65,0x48,0x8c,0x30,0x65,0x49,0x8c,0x40,0x00,0x18,0x27,0x3c,0x65,0x58,0xac,
+0x21,0x50,0x00,0x03,0x25,0x20,0x83,0x00,0x40,0x00,0x18,0x27,0x20,0x10,0x03,0x3c,
+0xf0,0x64,0x44,0xac,0xfc,0x64,0x45,0xac,0x08,0x65,0x46,0xac,0x14,0x65,0x47,0xac,
+0x20,0x65,0x48,0xac,0x2c,0x65,0x49,0xac,0x25,0xb0,0x06,0x3c,0x88,0x64,0x43,0xac,
+0x84,0x64,0x43,0xac,0x94,0x64,0x43,0xac,0x90,0x64,0x43,0xac,0xa0,0x64,0x43,0xac,
+0x9c,0x64,0x43,0xac,0xac,0x64,0x43,0xac,0xa8,0x64,0x43,0xac,0x48,0x65,0x58,0xac,
+0x00,0x02,0x18,0x27,0x38,0x65,0x4a,0xac,0x60,0x65,0x58,0xac,0xb8,0x64,0x43,0xac,
+0xb4,0x64,0x43,0xac,0xc4,0x64,0x43,0xac,0xc0,0x64,0x43,0xac,0xd0,0x64,0x43,0xac,
+0xcc,0x64,0x43,0xac,0xac,0x00,0xc4,0x34,0xb0,0x00,0xc5,0x34,0x00,0x00,0x92,0x8c,
+0x48,0x65,0x50,0x8c,0x00,0x00,0xb3,0x8c,0x21,0x10,0x04,0x3c,0x23,0x10,0x09,0x3c,
+0x22,0x10,0x0c,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,
+0x02,0x80,0x17,0x3c,0x24,0x10,0x05,0x3c,0x21,0x88,0x00,0x03,0x68,0x7b,0x87,0x26,
+0x00,0x04,0x18,0x27,0x70,0x7b,0xa8,0x26,0x78,0x7b,0xca,0x26,0x80,0x7b,0xeb,0x26,
+0x00,0x04,0x2d,0x35,0x00,0x40,0x8e,0x34,0x00,0x80,0x8f,0x35,0x00,0x01,0xc6,0x34,
+0x44,0x65,0x50,0xac,0x5c,0x65,0x51,0xac,0xc4,0x65,0x4d,0xac,0x88,0x65,0x52,0xac,
+0x94,0x65,0x4e,0xac,0xb8,0x65,0x4f,0xac,0xac,0x65,0x53,0xac,0x00,0x00,0xc5,0xac,
+0xa8,0x65,0x45,0xac,0xc8,0x65,0x43,0xac,0xd4,0x65,0x58,0xac,0xdc,0x64,0x43,0xac,
+0xd8,0x64,0x43,0xac,0x66,0x65,0x40,0xa4,0x65,0x65,0x40,0xa0,0x64,0x65,0x40,0xa0,
+0xbc,0x65,0x49,0xac,0xc0,0x65,0x49,0xac,0x80,0x65,0x44,0xac,0x84,0x65,0x44,0xac,
+0x8c,0x65,0x44,0xac,0x90,0x65,0x44,0xac,0xb0,0x65,0x4c,0xac,0xb4,0x65,0x4c,0xac,
+0xa4,0x65,0x45,0xac,0xcc,0x65,0x43,0xac,0xd8,0x65,0x58,0xac,0x04,0x00,0x08,0xad,
+0x68,0x7b,0x87,0xae,0x04,0x00,0x4a,0xad,0x70,0x7b,0xa8,0xae,0x04,0x00,0x6b,0xad,
+0x78,0x7b,0xca,0xae,0x80,0x7b,0xeb,0xae,0x04,0x00,0xe7,0xac,0x02,0x80,0x02,0x3c,
+0x00,0x14,0x43,0x24,0x21,0x20,0xe0,0x00,0x03,0x00,0x06,0x24,0x21,0x10,0x80,0x00,
+0xff,0xff,0xc6,0x24,0x08,0x00,0x78,0xac,0x00,0x00,0x63,0xac,0x10,0x00,0x60,0xac,
+0x00,0x00,0x67,0xac,0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac,0x00,0x00,0x43,0xac,
+0x00,0x01,0x18,0x27,0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,
+0x70,0x7b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x28,0x8d,
+0x60,0x14,0x4b,0x24,0x04,0x00,0xe4,0xac,0x00,0x14,0x6a,0x24,0x01,0x00,0x07,0x24,
+0x21,0x28,0x00,0x00,0x07,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,
+0xff,0xff,0xc6,0x24,0x68,0x00,0x58,0xac,0x70,0x00,0x47,0xac,0x18,0x00,0xa5,0x24,
+0x00,0x00,0x89,0xac,0x04,0x00,0x88,0xac,0x00,0x00,0x04,0xad,0x00,0x01,0x18,0x27,
+0xf5,0xff,0xc1,0x04,0x21,0x40,0x80,0x00,0x02,0x80,0x02,0x3c,0x78,0x7b,0x4a,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x45,0x8d,0x20,0x15,0x4b,0x24,
+0x04,0x00,0x24,0xad,0x02,0x00,0x07,0x24,0x00,0x14,0x69,0x24,0x21,0x20,0x00,0x00,
+0x01,0x00,0x06,0x24,0x21,0x40,0x8b,0x00,0x21,0x10,0x89,0x00,0xff,0xff,0xc6,0x24,
+0x28,0x01,0x58,0xac,0x30,0x01,0x47,0xac,0x18,0x00,0x84,0x24,0x00,0x00,0x0a,0xad,
+0x04,0x00,0x05,0xad,0x00,0x00,0xa8,0xac,0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04,
+0x21,0x28,0x00,0x01,0x02,0x80,0x05,0x3c,0x80,0x7b,0xa5,0x24,0x04,0x00,0xa6,0x8c,
+0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f,
+0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f,
+0x02,0x80,0x07,0x3c,0x02,0x80,0x03,0x3c,0x50,0x15,0xe4,0x24,0x00,0x14,0x63,0x24,
+0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x58,0x01,0x78,0xac,0x04,0x00,0x48,0xad,
+0x04,0x00,0xa4,0xac,0x60,0x01,0x62,0xac,0x50,0x15,0xe5,0xac,0x04,0x00,0x86,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0xc4,0xac,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x70,0x9e,0x74,0x24,
+0xe4,0x9e,0x53,0x24,0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c,0x2c,0x00,0xb5,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x30,0x00,0xbf,0xaf,
+0xff,0x1f,0x55,0x34,0x68,0x15,0x70,0x24,0x21,0x88,0x00,0x00,0x02,0x80,0x12,0x3c,
+0xaa,0x4f,0x00,0x0c,0x21,0x20,0x20,0x02,0x84,0x51,0x02,0x8e,0x6c,0x00,0x86,0x8e,
+0x50,0x9e,0x43,0x26,0x6c,0x00,0x64,0x8e,0x1b,0x00,0x65,0x90,0x24,0x10,0x55,0x00,
+0x00,0x20,0x42,0x34,0xff,0xf1,0x03,0x24,0x21,0x20,0x86,0x00,0x24,0x10,0x43,0x00,
+0x00,0x29,0x05,0x00,0x42,0x20,0x04,0x00,0x00,0x02,0x42,0x34,0x50,0x51,0x04,0xae,
+0x74,0x51,0x05,0xae,0x84,0x51,0x02,0xae,0x78,0x51,0x05,0xae,0x21,0x30,0x00,0x00,
+0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xa5,0x51,0x40,0xa0,
+0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xc2,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xe0,0x51,0x00,0xae,0xe1,0xff,0x40,0x14,0x94,0x00,0x10,0x26,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x68,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c,
+0xe4,0x9e,0x6f,0x24,0x70,0x9e,0x4d,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x50,0x9e,0x6e,0x24,0x30,0x9e,0x4c,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,
+0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,
+0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,
+0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,
+0xec,0x44,0x68,0xac,0xca,0x44,0x47,0xa0,0x60,0x45,0x6a,0xac,0xef,0xff,0x80,0x14,
+0x90,0x44,0x49,0xa0,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x0c,0x9d,0x6b,0x24,0xac,0x9b,0x4c,0x24,0x21,0x88,0x00,0x00,
+0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,
+0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
+0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,
+0x34,0x43,0x65,0xa0,0x21,0x10,0x2c,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,
+0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x52,0x00,0x02,0x24,
+0x10,0x00,0xa2,0xa3,0x41,0x00,0x03,0x24,0x4d,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,
+0xdc,0xa4,0xe7,0x24,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xe8,0x03,0x03,0x24,
+0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,
+0x60,0x3e,0xc6,0x24,0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x88,0x0e,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x42,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x55,0x60,0x40,0xa0,0x4e,0x00,0x03,0x24,
+0x43,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x14,0xa5,0xe7,0x24,0x11,0x00,0xa2,0xa3,
+0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x00,0x80,0x06,0x3c,
+0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xec,0x4f,0xc6,0x24,0x0c,0x00,0xe2,0xac,
+0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,
+0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x48,0xfd,0xbd,0x27,0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,0x02,0x80,0x13,0x3c,
+0xf0,0x9f,0x46,0x24,0x68,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,0xac,0x02,0xb1,0xaf,
+0xa8,0x02,0xb0,0xaf,0x03,0x40,0x60,0xa0,0x21,0x38,0xa0,0x03,0x90,0x00,0xc8,0x24,
+0x00,0x00,0xc2,0x8c,0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,0x0c,0x00,0xc5,0x8c,
+0x10,0x00,0xc6,0x24,0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,0x08,0x00,0xe4,0xac,
+0x0c,0x00,0xe5,0xac,0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,0x00,0x00,0xc3,0x8c,
+0x02,0x80,0x02,0x3c,0x84,0xa0,0x58,0x24,0x00,0x00,0xe3,0xac,0x98,0x00,0xb9,0x27,
+0x00,0x01,0x12,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,
+0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,
+0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,
+0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,
+0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,
+0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,
+0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,
+0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,
+0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,
+0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,
+0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,
+0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,
+0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,
+0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,
+0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,
+0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,
+0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,0x25,0x38,0xe4,0x00,
+0x25,0x30,0xc5,0x00,0x8c,0xa1,0x58,0x24,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,
+0x00,0x01,0x12,0x27,0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
+0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,
+0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,
+0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,
+0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
+0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,
+0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,
+0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,
+0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,
+0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,
+0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,
+0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,
+0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,
+0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,
+0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,
+0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,
+0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x25,0x30,0xc5,0x00,
+0x25,0x38,0xe4,0x00,0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,
+0x68,0x15,0x46,0x24,0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,0x21,0x10,0x9d,0x00,
+0x00,0x00,0x45,0x8c,0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,0x21,0x20,0x86,0x00,
+0x25,0x00,0x42,0x2d,0xf8,0xff,0x40,0x14,0x18,0x40,0x85,0xac,0x02,0x80,0x02,0x3c,
+0x68,0x15,0x4b,0x24,0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,0x21,0x48,0x5d,0x00,
+0x21,0x38,0x00,0x00,0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,0xa0,0x01,0x46,0x90,
+0x98,0x00,0x45,0x90,0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,0xff,0x00,0x87,0x30,
+0x08,0x00,0xe2,0x2c,0xb4,0x41,0x66,0xa0,0xf7,0xff,0x40,0x14,0xac,0x40,0x65,0xa0,
+0x01,0x00,0x42,0x25,0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,0xef,0xff,0x60,0x14,
+0xc0,0x10,0x0a,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x20,0x00,0x63,0x30,0x42,0x00,0x60,0x10,0x68,0x15,0x64,0x26,
+0x33,0x00,0x02,0x24,0xc1,0x42,0x62,0xa1,0x1c,0x00,0x03,0x24,0x0f,0x00,0x02,0x24,
+0xbc,0x42,0x63,0xa1,0xbd,0x42,0x62,0xa1,0x68,0x15,0x65,0x26,0x08,0x40,0xa4,0x8c,
+0xff,0x7f,0x08,0x3c,0xff,0xff,0x08,0x35,0xc0,0xff,0x02,0x24,0x24,0x20,0x88,0x00,
+0x24,0x20,0x82,0x00,0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,0x24,0x20,0x82,0x00,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,0xbf,0xff,0x03,0x3c,
+0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,
+0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x0c,0x40,0xa6,0x8c,0x7f,0xff,0x03,0x24,
+0x40,0x40,0x84,0x34,0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0x7f,0x42,0x34,
+0xff,0xbf,0x03,0x3c,0x10,0x40,0xa7,0x8c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,
+0xff,0x9f,0x02,0x3c,0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c,
+0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x12,0x00,0x02,0x24,0xb4,0x02,0xb3,0x8f,
+0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,0xa8,0x02,0xb0,0x8f,0x24,0x38,0xe3,0x00,
+0xc7,0x42,0xa2,0xa0,0x1f,0x00,0x03,0x24,0x01,0x00,0x02,0x24,0x24,0x30,0xc8,0x00,
+0xbe,0x42,0xa3,0xa0,0xc0,0x42,0xa2,0xa0,0xff,0x00,0x03,0x24,0xff,0xff,0x02,0x24,
+0xb8,0x02,0xbd,0x27,0x08,0x40,0xa4,0xac,0x10,0x40,0xa7,0xac,0x0c,0x40,0xa6,0xac,
+0xc2,0x42,0xa2,0xa0,0xc4,0x42,0xa3,0xa4,0xbf,0x42,0xa0,0xa0,0x08,0x00,0xe0,0x03,
+0xc6,0x42,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x42,0x82,0xa0,0x0d,0x00,0x03,0x24,
+0x03,0x00,0x02,0x24,0xbc,0x42,0x83,0xa0,0xa8,0x60,0x00,0x08,0xbd,0x42,0x82,0xa0,
+0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,
+0xe6,0x42,0xe0,0xa0,0xe4,0x42,0xe8,0x8c,0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34,
+0xff,0xbf,0x03,0x3c,0x00,0x40,0xe9,0x8c,0x24,0x40,0x02,0x01,0xff,0xff,0x63,0x34,
+0xff,0x7f,0x02,0x3c,0x24,0x40,0x03,0x01,0xff,0xff,0x42,0x34,0xf0,0xff,0x04,0x24,
+0x24,0x40,0x02,0x01,0xff,0xdf,0x02,0x3c,0x24,0x48,0x24,0x01,0xff,0xf0,0x03,0x24,
+0xff,0xff,0x42,0x34,0x24,0x48,0x23,0x01,0x24,0x40,0x02,0x01,0x20,0x00,0x03,0x24,
+0x0a,0x00,0x02,0x24,0xd2,0x42,0xe2,0xa0,0xd7,0x42,0xe3,0xa0,0x20,0x00,0x02,0x24,
+0x00,0x01,0x03,0x24,0xc8,0x42,0xe2,0xa4,0xca,0x42,0xe3,0xa4,0x00,0x02,0x02,0x24,
+0x49,0x00,0x03,0x24,0x02,0x80,0x0a,0x3c,0x00,0x40,0xe9,0xac,0xe4,0x42,0xe8,0xac,
+0xf8,0xa4,0x4a,0x25,0xff,0xff,0x0c,0x34,0x3e,0x00,0x0d,0x24,0x1c,0x00,0x0e,0x24,
+0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xcc,0x42,0xe2,0xa4,0xd0,0x07,0x03,0x24,
+0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3,0x10,0x00,0xa5,0x27,
+0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xa4,0x50,0xc6,0x24,0x04,0x40,0xec,0xac,
+0xd0,0x42,0xed,0xa0,0xd1,0x42,0xee,0xa0,0x02,0x40,0xeb,0xa0,0x0c,0x00,0x43,0xad,
+0x14,0x00,0x4b,0xa1,0xe8,0x63,0xec,0xac,0xce,0x42,0xed,0xa0,0xcf,0x42,0xee,0xa0,
+0xd6,0x42,0xe0,0xa0,0xd4,0x42,0xe0,0xa0,0x12,0x00,0xa2,0xa3,0x88,0x0e,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,
+0x10,0x00,0xa3,0xa3,0x36,0x62,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,
+0x02,0x80,0x07,0x3c,0xa0,0xa5,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,
+0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0xe0,0x00,0x74,0x67,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
+0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,
+0x18,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x68,0x15,0x10,0x26,0x20,0x00,0xbf,0xaf,
+0x1c,0x00,0xb1,0xaf,0x00,0x40,0x09,0x8e,0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,
+0x0f,0xff,0x02,0x24,0x24,0x48,0x22,0x01,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,
+0x24,0x48,0x22,0x01,0x01,0x00,0x07,0x3c,0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,
+0x02,0x80,0x08,0x3c,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,0xbc,0xa5,0x08,0x25,
+0x56,0x30,0xea,0x34,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0xf4,0x98,0xe7,0x34,
+0x00,0x80,0x06,0x3c,0x04,0x43,0x0b,0xae,0x00,0x40,0x09,0xae,0x43,0x00,0x11,0x24,
+0x10,0x00,0xa5,0x27,0x0c,0x43,0x07,0xae,0x10,0x43,0x0a,0xae,0x0c,0x00,0x02,0xad,
+0x14,0x00,0x03,0xa1,0x08,0x43,0x00,0xae,0x14,0x43,0x00,0xae,0x18,0x43,0x00,0xae,
+0x21,0x20,0x00,0x01,0x3c,0x5c,0xc6,0x24,0x12,0x00,0xb1,0xa3,0x88,0x0e,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x1e,0x00,0x02,0x24,0x21,0x43,0x02,0xa2,0x4a,0x00,0x03,0x24,
+0x45,0x00,0x02,0x24,0x1c,0x43,0x03,0xa2,0x1d,0x43,0x02,0xa2,0x23,0x00,0x03,0x24,
+0x3e,0x00,0x02,0x24,0x1e,0x43,0x11,0xa2,0x1f,0x43,0x02,0xa2,0x20,0x43,0x03,0xa2,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,
+0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x07,0x3c,0xd8,0xa5,0xe7,0x24,0x12,0x00,0xa2,0xa3,0x3b,0x58,0x60,0xa0,
+0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0xe0,0x00,0x60,0x61,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
+0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0xac,0x79,0x40,0xa4,
+0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x10,0xa6,0xe7,0x24,
+0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xb8,0x68,0xc6,0x24,
+0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xd8,0xff,0xbd,0x27,0x64,0x79,0x84,0x24,
+0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf,0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24,
+0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0xf8,0x63,0xe3,0x8c,0xfd,0xff,0x02,0x24,
+0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00,0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00,
+0x05,0x00,0x02,0x24,0xf8,0x63,0xe3,0xac,0xfc,0x63,0xe2,0xa0,0x28,0x00,0x03,0x24,
+0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0xfd,0x63,0xe3,0xa0,0x4b,0x00,0x02,0x24,
+0x42,0x00,0x03,0x24,0x2c,0xa6,0x08,0x25,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,
+0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0x00,0x01,0x80,0x69,0xc6,0x24,0xfa,0x63,0xe0,0xa4,0x0c,0x00,0x03,0xad,
+0x14,0x00,0x02,0xa1,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00,
+0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00,
+0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00,
+0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00,
+0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,
+0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00,
+0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00,
+0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00,
+0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00,
+0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00,
+0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,
+0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,
+0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00,
+0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00,
+0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00,
+0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00,
+0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00,
+0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00,
+0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00,
+0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00,
+0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00,
+0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00,
+0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00,
+0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00,
+0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00,
+0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00,
+0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00,
+0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00,
+0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00,
+0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x14,0x35,0x00,0x80,0x10,0x00,0x00,0x00,0x20,0x35,0x00,0x80,0x10,0x00,0x00,0x00,
+0xa0,0x08,0x01,0x80,0x10,0x00,0x00,0x00,0x2c,0x25,0x00,0x80,0x10,0x00,0x00,0x00,
+0x24,0x25,0x00,0x80,0x10,0x00,0x00,0x00,0x34,0x25,0x00,0x80,0x08,0x00,0x00,0x00,
+0x38,0x06,0x01,0x80,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,
+0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,
+0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,
+0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,
+0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,
+0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,
+0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,
+0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,
+0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,
+0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,
+0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,
+0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,
+0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,
+0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,
+0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,
+0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,
+0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,
+0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,
+0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,
+0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,
+0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,
+0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,
+0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,
+0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,
+0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,
+0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,
+0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,
+0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,
+0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,
+0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,
+0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,
+0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,
+0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,
+0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,
+0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,
+0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,
+0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,
+0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,
+0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,
+0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,
+0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,
+0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,
+0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,
+0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,
+0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,
+0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,
+0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,
+0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,
+0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,
+0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,
+0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,
+0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,
+0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,
+0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,
+0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,
+0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,
+0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,
+0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,
+0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,
+0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,
+0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,
+0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,
+0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,
+0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,
+0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,
+0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,
+0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,
+0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,
+0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,
+0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,
+0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,
+0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,
+0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,
+0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,
+0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,
+0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,
+0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,
+0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,
+0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,
+0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,
+0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,
+0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,
+0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,
+0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,
+0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,
+0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,
+0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,
+0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,
+0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,
+0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,
+0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,
+0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,
+0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,
+0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,
+0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,
+0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,
+0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,
+0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,
+0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,
+0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,
+0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,
+0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,
+0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,
+0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,
+0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,
+0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,
+0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,
+0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,
+0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,
+0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,
+0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,
+0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54,
+0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00,
+0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68,
+0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x20,0x99,0x01,0x80,0x2c,0x13,0x01,0x80,0x10,0x00,0x00,0x00,
+0x2c,0x99,0x01,0x80,0x34,0x13,0x01,0x80,0x20,0x00,0x00,0x00,0x38,0x99,0x01,0x80,
+0x2c,0x13,0x01,0x80,0x30,0x00,0x00,0x00,0x48,0x99,0x01,0x80,0x34,0x13,0x01,0x80,
+0x40,0x00,0x00,0x00,0x58,0x99,0x01,0x80,0x3c,0x13,0x01,0x80,0x50,0x00,0x00,0x00,
+0x64,0x99,0x01,0x80,0x44,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x70,0x99,0x01,0x80,
+0xac,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x7c,0x99,0x01,0x80,0xac,0x13,0x01,0x80,
+0x80,0x00,0x00,0x00,0x88,0x99,0x01,0x80,0x4c,0x13,0x01,0x80,0x90,0x00,0x00,0x00,
+0x94,0x99,0x01,0x80,0x54,0x13,0x01,0x80,0xa0,0x00,0x00,0x00,0x9c,0x99,0x01,0x80,
+0x5c,0x13,0x01,0x80,0xb0,0x00,0x00,0x00,0xa8,0x99,0x01,0x80,0x94,0x13,0x01,0x80,
+0xc0,0x00,0x00,0x00,0xb0,0x99,0x01,0x80,0x9c,0x13,0x01,0x80,0xd0,0x00,0x00,0x00,
+0xbc,0x99,0x01,0x80,0xa4,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x74,0x9a,0x01,0x80,
+0x74,0x9a,0x01,0x80,0x31,0x10,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,
+0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,
+0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,
+0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10,0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,
+0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,
+0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,
+0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,
+0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06,0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,
+0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02,0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,
+0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02,0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,
+0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,
+0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,
+0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,
+0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,
+0x08,0x20,0x20,0x20,0x30,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,
+0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,
+0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,
+0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,
+0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,
+0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,
+0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,
+0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,
+0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,
+0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,
+0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,
+0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,
+0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,
+0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,
+0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
+0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,
+0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,
+0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,
+0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,
+0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,
+0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,
+0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,
+0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,
+0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,
+0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,
+0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,
+0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,
+0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,
+0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,
+0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,
+0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,
+0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,
+0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,
+0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,
+0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,
+0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,
+0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,
+0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,
+0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,
+0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,
+0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,
+0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x25,0x27,0x2c,0x19,0x1b,0x1e,0x20,0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,
+0x25,0x29,0x2b,0x2e,0x2e,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
+0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,
+0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,
+0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,
+0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,
+0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00,0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,
+0xe0,0x01,0x00,0x00,0xd0,0x02,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,
+0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00,0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,
+0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
+0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,
+0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,
+0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,
+0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,
+0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,
+0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80,0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80,
+0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80,0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80,
+0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80,0x78,0x04,0x00,0x80,0x70,0x3b,0x01,0x80,
+0x48,0x3b,0x01,0x80,0x24,0x3b,0x01,0x80,0x14,0x3c,0x01,0x80,0xf0,0x3b,0x01,0x80,
+0xcc,0x3b,0x01,0x80,0xa8,0x3b,0x01,0x80,0x30,0x41,0x00,0x80,0x3c,0x41,0x00,0x80,
+0x48,0x41,0x00,0x80,0x54,0x41,0x00,0x80,0x30,0x41,0x00,0x80,0x30,0x41,0x00,0x80,
+0x30,0x41,0x00,0x80,0x30,0x41,0x00,0x80,0x60,0x41,0x00,0x80,0x6c,0x41,0x00,0x80,
+0x78,0x41,0x00,0x80,0x84,0x41,0x00,0x80,0x68,0x15,0x02,0x80,0x68,0x15,0x02,0x80,
+0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,0x8c,0x0e,0x25,0xb0,0xd0,0x0e,0x25,0xb0,
+0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,0xfe,0x01,0x80,0x7f,0xe2,0x01,0x80,0x78,
+0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,0x7f,0x01,0xc0,0x5f,
+0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,0x30,0x01,0x00,0x4c,
+0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,0xf2,0x00,0x80,0x3c,
+0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,0xc0,0x00,0x00,0x30,
+0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,0x98,0x00,0x00,0x26,
+0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,0x79,0x00,0x40,0x1e,
+0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,0x60,0x00,0x00,0x18,
+0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,0x4c,0x00,0x00,0x13,
+0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,0x36,0x35,0x2e,0x25,
+0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,0x30,0x2f,0x29,0x21,
+0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,0x2b,0x2a,0x25,0x1e,
+0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,0x26,0x25,0x21,0x1b,
+0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,0x22,0x21,0x1d,0x18,
+0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,0x1f,0x1e,0x1a,0x15,
+0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,0x1b,0x1a,0x17,0x13,
+0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,0x18,0x17,0x15,0x11,
+0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,0x16,0x15,0x12,0x0f,
+0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,0x13,0x13,0x10,0x0d,
+0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,0x11,0x11,0x0f,0x0c,
+0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,0x0f,0x0f,0x0d,0x0b,
+0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,0x0d,0x0d,0x0c,0x0a,
+0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,0x0c,0x0c,0x0a,0x09,
+0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,0x0b,0x0a,0x09,0x08,
+0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,0x0a,0x09,0x08,0x07,
+0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,0x09,0x08,0x07,0x06,
+0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,0x33,0x32,0x2b,0x19,
+0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,0x2d,0x2d,0x17,0x17,
+0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,0x28,0x28,0x24,0x14,
+0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,0x24,0x23,0x1f,0x12,
+0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,0x20,0x20,0x1b,0x10,
+0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,0x1d,0x1c,0x18,0x0e,
+0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,0x1a,0x19,0x16,0x0d,
+0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,0x17,0x16,0x13,0x0b,
+0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,0x14,0x14,0x11,0x0a,
+0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,0x12,0x12,0x0f,0x09,
+0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,0x10,0x10,0x0e,0x08,
+0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0c,0x07,
+0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0c,0x0b,0x06,
+0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06,
+0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05,
+0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x05,
+0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x2a,0xb0,
+0x05,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0xa5,0x76,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x26,0x72,0xb0,0x00,0x26,0x72,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x26,0x65,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x5a,0x00,0xb8,0xff,0xff,0xff,0xff,
+};
+
+u8 Rtl8192SEFwMainArray[MainArrayLength] = {
+0x0, };
+
+u8 Rtl8192SEFwDataArray[DataArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = {
+0x01c,0x07000000,
+0x800,0x00040000,
+0x804,0x00008003,
+0x808,0x0000fc00,
+0x80c,0x0000000a,
+0x810,0x10005088,
+0x814,0x020c3d10,
+0x818,0x00200185,
+0x81c,0x00000000,
+0x820,0x01000000,
+0x824,0x00390004,
+0x828,0x01000000,
+0x82c,0x00390004,
+0x830,0x00000004,
+0x834,0x00690200,
+0x838,0x00000004,
+0x83c,0x00690200,
+0x840,0x00010000,
+0x844,0x00010000,
+0x848,0x00000000,
+0x84c,0x00000000,
+0x850,0x00000000,
+0x854,0x00000000,
+0x858,0x48484848,
+0x85c,0x65a965a9,
+0x860,0x0f7f0130,
+0x864,0x0f7f0130,
+0x868,0x0f7f0130,
+0x86c,0x0f7f0130,
+0x870,0x03000700,
+0x874,0x03000300,
+0x878,0x00020002,
+0x87c,0x004f0201,
+0x880,0xa8300ac1,
+0x884,0x00000058,
+0x888,0x00000008,
+0x88c,0x00000004,
+0x890,0x00000000,
+0x894,0xfffffffe,
+0x898,0x40302010,
+0x89c,0x00706050,
+0x8b0,0x00000000,
+0x8e0,0x00000000,
+0x8e4,0x00000000,
+0xe00,0x30333333,
+0xe04,0x2a2d2e2f,
+0xe08,0x00003232,
+0xe10,0x30333333,
+0xe14,0x2a2d2e2f,
+0xe18,0x30333333,
+0xe1c,0x2a2d2e2f,
+0xe30,0x01007c00,
+0xe34,0x01004800,
+0xe38,0x1000dc1f,
+0xe3c,0x10008c1f,
+0xe40,0x021400a0,
+0xe44,0x281600a0,
+0xe48,0xf8000001,
+0xe4c,0x00002910,
+0xe50,0x01007c00,
+0xe54,0x01004800,
+0xe58,0x1000dc1f,
+0xe5c,0x10008c1f,
+0xe60,0x021400a0,
+0xe64,0x281600a0,
+0xe6c,0x00002910,
+0xe70,0x31ed92fb,
+0xe74,0x361536fb,
+0xe78,0x361536fb,
+0xe7c,0x361536fb,
+0xe80,0x361536fb,
+0xe84,0x000d92fb,
+0xe88,0x000d92fb,
+0xe8c,0x31ed92fb,
+0xed0,0x31ed92fb,
+0xed4,0x31ed92fb,
+0xed8,0x000d92fb,
+0xedc,0x000d92fb,
+0xee0,0x000d92fb,
+0xee4,0x015e5448,
+0xee8,0x21555448,
+0x900,0x00000000,
+0x904,0x00000023,
+0x908,0x00000000,
+0x90c,0x01121313,
+0xa00,0x00d047c8,
+0xa04,0x80ff0008,
+0xa08,0x8ccd8300,
+0xa0c,0x2e62120f,
+0xa10,0x9500bb78,
+0xa14,0x11144028,
+0xa18,0x00881117,
+0xa1c,0x89140f00,
+0xa20,0x1a1b0000,
+0xa24,0x090e1317,
+0xa28,0x00000204,
+0xa2c,0x10d30000,
+0xc00,0x40071d40,
+0xc04,0x00a05633,
+0xc08,0x000000e4,
+0xc0c,0x6c6c6c6c,
+0xc10,0x08800000,
+0xc14,0x40000100,
+0xc18,0x08000000,
+0xc1c,0x40000100,
+0xc20,0x08000000,
+0xc24,0x40000100,
+0xc28,0x08000000,
+0xc2c,0x40000100,
+0xc30,0x6de9ac44,
+0xc34,0x469652cf,
+0xc38,0x49795994,
+0xc3c,0x0a979764,
+0xc40,0x1f7c403f,
+0xc44,0x000100b7,
+0xc48,0xec020000,
+0xc4c,0x007f037f,
+0xc50,0x69543420,
+0xc54,0x433c0094,
+0xc58,0x69543420,
+0xc5c,0x433c0094,
+0xc60,0x69543420,
+0xc64,0x433c0094,
+0xc68,0x69543420,
+0xc6c,0x433c0094,
+0xc70,0x2c7f000d,
+0xc74,0x0186155b,
+0xc78,0x0000001f,
+0xc7c,0x00b91612,
+0xc80,0x40000100,
+0xc84,0x20f60000,
+0xc88,0x20000080,
+0xc8c,0x20200000,
+0xc90,0x40000100,
+0xc94,0x00000000,
+0xc98,0x40000100,
+0xc9c,0x00000000,
+0xca0,0x00492492,
+0xca4,0x00000000,
+0xca8,0x00000000,
+0xcac,0x00000000,
+0xcb0,0x00000000,
+0xcb4,0x00000000,
+0xcb8,0x00000000,
+0xcbc,0x28000000,
+0xcc0,0x00000000,
+0xcc4,0x00000000,
+0xcc8,0x00000000,
+0xccc,0x00000000,
+0xcd0,0x00000000,
+0xcd4,0x00000000,
+0xcd8,0x64b22427,
+0xcdc,0x00766932,
+0xce0,0x00222222,
+0xce4,0x00000000,
+0xce8,0x37644302,
+0xcec,0x2f97d40c,
+0xd00,0x00000750,
+0xd04,0x00000403,
+0xd08,0x0000907f,
+0xd0c,0x00000001,
+0xd10,0xa0633333,
+0xd14,0x33333c63,
+0xd18,0x6a8f5b6b,
+0xd1c,0x00000000,
+0xd20,0x00000000,
+0xd24,0x00000000,
+0xd28,0x00000000,
+0xd2c,0xcc979975,
+0xd30,0x00000000,
+0xd34,0x00000000,
+0xd38,0x00000000,
+0xd3c,0x00027293,
+0xd40,0x00000000,
+0xd44,0x00000000,
+0xd48,0x00000000,
+0xd50,0x6437140a,
+0xd54,0x024dbd02,
+0xd58,0x00000000,
+0xd5c,0x30032064,
+0xd60,0x4653de68,
+0xd64,0x00518a3c,
+0xd68,0x00002101,
+0xf14,0x00000003,
+0xf4c,0x00000000,
+0xf00,0x00000300,
+};
+
+u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = {
+0x844,0xffffffff,0x00010000,
+0x804,0x0000000f,0x00000001,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00100002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000011,
+0xd04,0x0000000f,0x00000001,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300004,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000001,
+0x878,0x000f000f,0x00020002,
+0xe74,0x0f000000,0x00000006,
+0xe78,0x0f000000,0x00000006,
+0xe7c,0x0f000000,0x00000006,
+0xe80,0x0f000000,0x00000006,
+0x90c,0x000000ff,0x00000033,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x0000ffff,
+0x234,0xf8000000,0x00000013,
+};
+
+u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = {
+0xe00,0xffffffff,0x06090909,
+0xe04,0xffffffff,0x00030406,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x0a0c0d0e,
+0xe14,0xffffffff,0x04070809,
+0xe18,0xffffffff,0x0a0c0d0e,
+0xe1c,0xffffffff,0x04070809,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x02020202,
+0xe04,0xffffffff,0x00020202,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02020202,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02020202,
+0xe1c,0xffffffff,0x00000002,
+};
+
+u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x010,0x0002000f,
+0x011,0x00020101,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x0000f8f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x0009bd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x032,0x0000130d,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+0x013,0x00017cb0,
+0x013,0x00011cc0,
+0x013,0x0000dc60,
+0x013,0x00008c60,
+0x013,0x00004450,
+0x013,0x00000020,
+};
+
+u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+};
+
+u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = {
+0x020,0x00000035,
+0x048,0x0000000e,
+0x049,0x000000f0,
+0x04a,0x00000077,
+0x04b,0x00000083,
+0x0b5,0x00000021,
+0x0dc,0x000000ff,
+0x0dd,0x000000ff,
+0x0de,0x000000ff,
+0x0df,0x000000ff,
+0x116,0x00000000,
+0x117,0x00000000,
+0x118,0x00000000,
+0x119,0x00000000,
+0x11a,0x00000000,
+0x11b,0x00000000,
+0x11c,0x00000000,
+0x11d,0x00000000,
+0x160,0x0000000b,
+0x161,0x0000000b,
+0x162,0x0000000b,
+0x163,0x0000000b,
+0x164,0x0000000b,
+0x165,0x0000000b,
+0x166,0x0000000b,
+0x167,0x0000000b,
+0x168,0x0000000b,
+0x169,0x0000000b,
+0x16a,0x0000000b,
+0x16b,0x0000000b,
+0x16c,0x0000000b,
+0x16d,0x0000000b,
+0x16e,0x0000000b,
+0x16f,0x0000000b,
+0x170,0x0000000b,
+0x171,0x0000000b,
+0x172,0x0000000b,
+0x173,0x0000000b,
+0x174,0x0000000b,
+0x175,0x0000000b,
+0x176,0x0000000b,
+0x177,0x0000000b,
+0x178,0x0000000b,
+0x179,0x0000000b,
+0x17a,0x0000000b,
+0x17b,0x0000000b,
+0x17c,0x0000000b,
+0x17d,0x0000000b,
+0x17e,0x0000000b,
+0x17f,0x0000000b,
+0x236,0x0000000c,
+0x503,0x00000022,
+0x560,0x00000000,
+};
+
+u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = {
+0x0, };
+
+u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = {
+0xc78,0x7f000001,
+0xc78,0x7f010001,
+0xc78,0x7e020001,
+0xc78,0x7d030001,
+0xc78,0x7c040001,
+0xc78,0x7b050001,
+0xc78,0x7a060001,
+0xc78,0x79070001,
+0xc78,0x78080001,
+0xc78,0x77090001,
+0xc78,0x760a0001,
+0xc78,0x750b0001,
+0xc78,0x740c0001,
+0xc78,0x730d0001,
+0xc78,0x720e0001,
+0xc78,0x710f0001,
+0xc78,0x70100001,
+0xc78,0x6f110001,
+0xc78,0x6f120001,
+0xc78,0x6e130001,
+0xc78,0x6d140001,
+0xc78,0x6d150001,
+0xc78,0x6c160001,
+0xc78,0x6b170001,
+0xc78,0x6a180001,
+0xc78,0x6a190001,
+0xc78,0x691a0001,
+0xc78,0x681b0001,
+0xc78,0x671c0001,
+0xc78,0x661d0001,
+0xc78,0x651e0001,
+0xc78,0x641f0001,
+0xc78,0x63200001,
+0xc78,0x4c210001,
+0xc78,0x4b220001,
+0xc78,0x4a230001,
+0xc78,0x49240001,
+0xc78,0x48250001,
+0xc78,0x47260001,
+0xc78,0x46270001,
+0xc78,0x45280001,
+0xc78,0x44290001,
+0xc78,0x2c2a0001,
+0xc78,0x2b2b0001,
+0xc78,0x2a2c0001,
+0xc78,0x292d0001,
+0xc78,0x282e0001,
+0xc78,0x272f0001,
+0xc78,0x26300001,
+0xc78,0x25310001,
+0xc78,0x24320001,
+0xc78,0x23330001,
+0xc78,0x22340001,
+0xc78,0x09350001,
+0xc78,0x08360001,
+0xc78,0x07370001,
+0xc78,0x06380001,
+0xc78,0x05390001,
+0xc78,0x043a0001,
+0xc78,0x033b0001,
+0xc78,0x023c0001,
+0xc78,0x013d0001,
+0xc78,0x003e0001,
+0xc78,0x003f0001,
+0xc78,0x7f400001,
+0xc78,0x7f410001,
+0xc78,0x7e420001,
+0xc78,0x7d430001,
+0xc78,0x7c440001,
+0xc78,0x7b450001,
+0xc78,0x7a460001,
+0xc78,0x79470001,
+0xc78,0x78480001,
+0xc78,0x77490001,
+0xc78,0x764a0001,
+0xc78,0x754b0001,
+0xc78,0x744c0001,
+0xc78,0x734d0001,
+0xc78,0x724e0001,
+0xc78,0x714f0001,
+0xc78,0x70500001,
+0xc78,0x6f510001,
+0xc78,0x6f520001,
+0xc78,0x6e530001,
+0xc78,0x6d540001,
+0xc78,0x6d550001,
+0xc78,0x6c560001,
+0xc78,0x6b570001,
+0xc78,0x6a580001,
+0xc78,0x6a590001,
+0xc78,0x695a0001,
+0xc78,0x685b0001,
+0xc78,0x675c0001,
+0xc78,0x665d0001,
+0xc78,0x655e0001,
+0xc78,0x645f0001,
+0xc78,0x63600001,
+0xc78,0x4c610001,
+0xc78,0x4b620001,
+0xc78,0x4a630001,
+0xc78,0x49640001,
+0xc78,0x48650001,
+0xc78,0x47660001,
+0xc78,0x46670001,
+0xc78,0x45680001,
+0xc78,0x44690001,
+0xc78,0x2c6a0001,
+0xc78,0x2b6b0001,
+0xc78,0x2a6c0001,
+0xc78,0x296d0001,
+0xc78,0x286e0001,
+0xc78,0x276f0001,
+0xc78,0x26700001,
+0xc78,0x25710001,
+0xc78,0x24720001,
+0xc78,0x23730001,
+0xc78,0x22740001,
+0xc78,0x09750001,
+0xc78,0x08760001,
+0xc78,0x07770001,
+0xc78,0x06780001,
+0xc78,0x05790001,
+0xc78,0x047a0001,
+0xc78,0x037b0001,
+0xc78,0x027c0001,
+0xc78,0x017d0001,
+0xc78,0x007e0001,
+0xc78,0x007f0001,
+0xc78,0x3000001e,
+0xc78,0x3001001e,
+0xc78,0x3002001e,
+0xc78,0x3003001e,
+0xc78,0x3004001e,
+0xc78,0x3405001e,
+0xc78,0x3806001e,
+0xc78,0x3e07001e,
+0xc78,0x3e08001e,
+0xc78,0x4409001e,
+0xc78,0x460a001e,
+0xc78,0x480b001e,
+0xc78,0x480c001e,
+0xc78,0x4e0d001e,
+0xc78,0x560e001e,
+0xc78,0x5a0f001e,
+0xc78,0x5e10001e,
+0xc78,0x6211001e,
+0xc78,0x6c12001e,
+0xc78,0x7213001e,
+0xc78,0x7214001e,
+0xc78,0x7215001e,
+0xc78,0x7216001e,
+0xc78,0x7217001e,
+0xc78,0x7218001e,
+0xc78,0x7219001e,
+0xc78,0x721a001e,
+0xc78,0x721b001e,
+0xc78,0x721c001e,
+0xc78,0x721d001e,
+0xc78,0x721e001e,
+0xc78,0x721f001e,
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_mp.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_mp.c
@@ -0,0 +1,1256 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifdef CONFIG_MP
+#include "../rtl_core.h"
+#include "r8192S_phy.h"
+#include "r8192S_phyreg.h"
+#include "r8192S_mp.h"
+
+void rtl8192_init_mp(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	priv->chan_forced = false;
+
+	priv->bSingleCarrier = false;
+	priv->RegBoard = 0;
+	priv->bCckContTx = false; 
+	priv->bOfdmContTx = false; 
+	priv->bStartContTx = false; 
+	priv->RegPaModel = 0; 
+	priv->btMpCckTxPower = 0; 
+	priv->btMpOfdmTxPower = 0; 
+}
+
+static bool r8192_MgntIsRateValidForWirelessMode(u8 rate, u8 wirelessmode)
+{
+	bool bReturn = false;
+
+	switch(wirelessmode)
+	{
+	case WIRELESS_MODE_A:
+	case WIRELESS_MODE_N_5G:
+		if((rate >= 12) && (rate <= 108) && (rate != 22) && (rate != 44))
+		{
+			bReturn = true;
+		}
+		break;
+
+	case WIRELESS_MODE_B:
+		if( ((rate <= 22) && (rate != 12) && (rate != 18)) || 
+			(rate == 44) )
+		{
+			bReturn = true;
+		}
+		break;
+
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_G | WIRELESS_MODE_B:
+	case WIRELESS_MODE_N_24G:
+		if((rate >= 2) && (rate <= 108))
+		{
+			bReturn = true;
+		}
+		break;
+
+	case WIRELESS_MODE_AUTO:
+		printk("MgntIsRateValidForWirelessMode(): wirelessmode should not be WIRELESS_MODE_AUTO\n");
+		break;
+
+	default:
+		printk("MgntIsRateValidForWirelessMode(): Unknown wirelessmode: %d\n", wirelessmode);
+		break;
+	}
+
+	if(!bReturn)
+	{
+		if(wirelessmode&(WIRELESS_MODE_N_24G|WIRELESS_MODE_N_5G))
+		{
+			if((rate>=0x80) && (rate<=MGN_MCS15_SG)) 
+				bReturn = true;
+		}
+	}
+	return bReturn;
+}
+
+inline u8 r8192_is_wireless_b_mode(u16 rate)
+{
+	if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) )
+		return 1;
+	else return 0;
+}
+
+static void r8192_XmitOnePacket(struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	struct sk_buff* skb = rtllib_get_beacon(ieee);
+	
+	if (unlikely(!skb)){
+		printk("========>error alloc skb\n");
+		return;
+	}
+
+	priv->rtllib->softmac_data_hard_start_xmit(skb, dev, ieee->rate);
+}
+
+int r8192_wx_mp_set_chan(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+        int ret = -1;
+	u8 channel;
+
+	down(&priv->wx_sem);
+
+	channel = *extra;
+	
+	rtllib_stop_scan(ieee);
+
+        printk("####RTL819X MP####set channel[1-11] %d\n",channel);
+
+	if((channel > 11) || (channel < 1)) {
+	up(&priv->wx_sem);
+       	 	return ret;
+	}
+
+	priv->rtllib->current_network.channel = channel;
+	priv->MptChannelToSw = channel;	
+
+	priv->chan_forced = false;
+	MPT_ProSwChannel(dev);
+	priv->chan_forced = true;
+
+	ret = 0;
+        up(&priv->wx_sem);
+		
+        return ret;
+	 
+}
+
+int r8192_wx_mp_set_txrate(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	int ret = -1;
+	u32 data_rate_index = 0;
+
+        down(&priv->wx_sem);
+             
+	data_rate_index = *extra;
+
+	printk("####RTL819X MP####set tx rate index %d\n",data_rate_index);
+	
+	priv->MptRateIndex = data_rate_index;
+
+	if((data_rate_index > 27) || (data_rate_index < 0)) {
+        	up(&priv->wx_sem);		
+       	 	return ret;
+	} else if(data_rate_index <= 3) {
+		ieee->mode = WIRELESS_MODE_B;
+	} else if (data_rate_index <= 11) {
+		ieee->mode = WIRELESS_MODE_G;
+	} else {
+		ieee->mode = WIRELESS_MODE_N_24G;
+	}	
+
+	MPT_ProSetDataRate819x(dev);
+	
+	printk("####RTL819X MP####set tx rate %d\n",ieee->rate);
+	
+	ret = 0;
+        up(&priv->wx_sem);
+
+	return ret;
+}
+
+int r8192_wx_mp_set_txpower(struct net_device *dev, 
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret = -1;
+	u8 power_index = 0;
+	
+	down(&priv->wx_sem);
+
+	power_index = *extra;
+
+        printk("####RTL819X MP####set tx power index %d\n",power_index);
+
+	if((power_index > 0x3F) || (power_index < 0x00)) {
+        	up(&priv->wx_sem);		
+       	 	return ret;
+	}
+
+	mpt_ProSetTxPower(dev, power_index);
+
+	ret = 0;
+	up(&priv->wx_sem);
+	
+	return ret;
+	
+}
+
+int r8192_wx_mp_set_bw(struct net_device *dev,
+			       struct iw_request_info *info, 
+			       union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	int ret = -1;
+	u8 bw_index = 0;
+
+        down(&priv->wx_sem);
+
+	bw_index = *extra;
+
+        printk("####RTL819X MP####set bandwith  index %d [0: 20MHz 1: 40MHz]\n",bw_index);
+
+	priv->MptBandWidth = bw_index;
+
+#if 0
+	if((bw_index > 1) || (bw_index < 0)) {
+	up(&priv->wx_sem);
+       	 	return ret;
+	} else if(bw_index == 1) {
+		HTSetConnectBwMode(priv->rtllib, HT_CHANNEL_WIDTH_20_40, 
+			(priv->rtllib->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+	} else {
+		HTSetConnectBwMode(priv->rtllib, HT_CHANNEL_WIDTH_20, 
+			(priv->rtllib->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+	}
+#else
+	MPT_ProSetBandWidth819x(dev);
+#endif
+
+	ret = 0;
+	up(&priv->wx_sem);
+	
+	return ret;
+	
+}
+
+
+
+int r8192_wx_mp_set_txstart(struct net_device *dev,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+    struct rtllib_device *ieee = priv->rtllib;
+    int ret = -1;
+    u8 start_flag = 0;
+
+        down(&priv->wx_sem);
+
+    start_flag = *extra;
+
+    if(start_flag == 1) { 
+	if (priv->bCckContTx || priv->bOfdmContTx) {
+	    printk("####RTL819X MP####continious Tx is undergoing, please close it first\n");
+	    ret = -EBUSY;
+        up(&priv->wx_sem);
+	    return ret;
+	}
+
+	if(r8192_is_wireless_b_mode(ieee->rate)) {
+	    printk("####RTL819X MP####start cck continious TX, rate:%d\n", ieee->rate);
+	    mpt_StartCckContTx(dev, true);
+	    r8192_XmitOnePacket(dev);
+	} else {
+	    printk("####RTL819X MP####start  ofdm continious TX, rate:%d\n", ieee->rate);
+	    mpt_StartOfdmContTx(dev);
+	    r8192_XmitOnePacket(dev);
+	} 
+    } else if(start_flag == 2) {
+	bool	bCckContTx = priv->bCckContTx;
+	bool	bOfdmContTx = priv->bOfdmContTx;
+
+	if(bCckContTx && !bOfdmContTx) {
+	    printk("####RTL819X MP####stop cck continious TX\n");
+	    mpt_StopCckCoNtTx(dev);
+	} else if (!bCckContTx && bOfdmContTx) {
+	    printk("####RTL819X MP####stop ofdm continious TX\n");
+	    mpt_StopOfdmContTx(dev);
+	} else if(!bCckContTx && !bOfdmContTx) { 
+	    ;
+	} else { 
+	    printk("####RTL819X MP#### Unexpected case! bCckContTx: %d , bOfdmContTx: %d\n",
+		    bCckContTx, bOfdmContTx);
+}
+    } else {
+	ret = -1;
+	up(&priv->wx_sem);
+	return ret;
+    }
+
+
+    ret = 0;
+    up(&priv->wx_sem);
+
+    return ret;
+
+}
+
+int r8192_wx_mp_set_singlecarrier(struct net_device *dev,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+        int ret = -1;
+	u8 start_flag = 0;
+
+	if((ieee->rate > 108) || (ieee->rate < 12))
+		printk("####RTL819X MP#### we did not do singlecarrier when rate not in [6M-54M] tmp, see StartTesting_SingleCarrierTx to get more\n");
+
+        down(&priv->wx_sem);
+	
+	start_flag = *extra;
+
+	if(start_flag == 1){ 
+		if (priv->bCckContTx || priv->bOfdmContTx || priv->bSingleCarrier){
+			printk("####RTL819X MP#### single carrier continious Tx is undergoing, please close it first\n");
+			ret = -EBUSY;
+        up(&priv->wx_sem);
+			return ret;
+		}	
+
+		printk("####RTL819X MP####start single carrier cck continious TX\n");
+		mpt_StartOfdmContTx(dev);
+		r8192_XmitOnePacket(dev);
+		
+	} else if(start_flag == 2) {
+		 if (priv->bCckContTx) {
+			printk("####RTL819X MP####stop single cck continious TX\n");
+			mpt_StopCckCoNtTx(dev);
+		} 
+		 if (priv->bOfdmContTx) {
+			printk("####RTL819X MP####stop single ofdm continious TX\n");
+			mpt_StopOfdmContTx(dev);
+		} 
+		 if (priv->bSingleCarrier) {
+			printk("####RTL819X MP####stop single carrier mode\n");
+			MPT_ProSetSingleCarrier(dev, false);
+		}
+	} else {
+		ret = -1;
+		up(&priv->wx_sem);
+
+		return ret;
+	}
+
+	ret = 0;
+        up(&priv->wx_sem);
+		
+        return ret;
+
+}
+int r8192_wx_mp_write_rf(struct net_device *dev,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	u32	ulIoType, INulRegOffset, INulRegValue;
+	u32 *info_buf = (u32*)(&wrqu->freq.m);
+        u32 ulRegOffset = info_buf[0];
+	u32 ulRegValue = info_buf[1];
+	u32 RF_PATH = info_buf[2];
+
+        down(&priv->wx_sem);
+	printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, RF_PATH:%x\n", 
+		__func__, ulRegOffset, ulRegValue, RF_PATH);
+
+	ulIoType = MPT_WRITE_RF;
+	INulRegOffset = ulRegOffset & bRFRegOffsetMask;
+	INulRegValue = ulRegValue & bRFRegOffsetMask;
+
+
+	priv->MptIoOffset = INulRegOffset;
+	priv->MptIoValue = INulRegValue;
+	priv->MptRfPath = RF_PATH;
+	priv->MptActType = ulIoType;
+
+	mpt_Pro819xIoCallback(dev);
+
+        up(&priv->wx_sem);
+        return 0;
+
+}
+
+int r8192_wx_mp_write_mac(struct net_device *dev,
+                               struct iw_request_info *info,
+                               union iwreq_data *wrqu, char *extra)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	u32 *info_buf = (u32*)(&wrqu->freq.m);
+        u32 ulRegOffset = info_buf[0];
+	u32 ulRegValue = info_buf[1];
+	u32 ulRegDataWidth = info_buf[2];
+	u32 ulIoType = 0;
+
+        down(&priv->wx_sem);
+
+	printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, ulRegDataWidth:%x\n", 
+		__func__, ulRegOffset, ulRegValue, ulRegDataWidth);
+		
+	switch(ulRegDataWidth)
+	{
+	case 1:
+		ulIoType = MPT_WRITE_MAC_1BYTE;
+		break;
+
+	case 2:
+		ulIoType = MPT_WRITE_MAC_2BYTE;
+		break;
+	case 4:
+		ulIoType = MPT_WRITE_MAC_4BYTE;
+		break;
+	default:
+		printk("####RTL819X MP####%s :error ulRegDataWidth:%x\n", __func__, ulRegDataWidth);
+		break;
+                }
+
+	if(ulIoType != 0){
+		priv->MptIoOffset = ulRegOffset;
+		priv->MptIoValue = ulRegValue;
+		priv->MptActType = ulIoType;
+		mpt_Pro819xIoCallback(dev);
+        }
+
+        up(&priv->wx_sem);
+
+	return 0;
+
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_StartCckContTx()
+ *
+ * Overview:	Start CCK Continuous Tx.
+ *
+ * Input:		PADAPTER	pAdapter
+ *				BOOLEAN		bScrambleOn
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void mpt_StartCckContTx(struct net_device *dev,bool bScrambleOn)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u32			cckrate;
+
+	if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bCCKEn))
+		rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, bEnable);
+
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+	switch(priv->rtllib->rate)
+	{
+		case 2:
+			cckrate = 0;
+			break;
+		case 4:
+			cckrate = 1;
+			break;
+		case 11:
+			cckrate = 2;
+			break;
+		case 22:
+			cckrate = 3;
+			break;
+		default:
+			cckrate = 0;
+			break;
+	}
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKTxRate, cckrate);
+
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, 0x2);    
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, 0x1);  
+
+	priv->bCckContTx = true;
+	priv->bOfdmContTx = false;
+	
+}	/* mpt_StartCckContTx */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_StartOfdmContTx()
+ *
+ * Overview:	Start OFDM Continuous Tx.
+ *
+ * Input:		PADAPTER	pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void mpt_StartOfdmContTx(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bOFDMEn))
+		rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, bEnable);
+
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, bDisable);
+
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, bEnable);
+
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+
+	priv->bCckContTx = false;
+	priv->bOfdmContTx = true;
+
+}	/* mpt_StartOfdmContTx */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_StopCckCoNtTx()
+ *
+ * Overview:	Stop CCK Continuous Tx.
+ *
+ * Input:		PADAPTER	pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void mpt_StopCckCoNtTx(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	priv->bCckContTx = false;
+	priv->bOfdmContTx = false;
+
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, 0x0);    
+	rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, 0x1);  
+
+	rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0);
+	rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1);
+	
+}	/* mpt_StopCckCoNtTx */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_StopOfdmContTx()
+ *
+ * Overview:	Stop 818xB OFDM Continuous Tx.
+ *
+ * Input:		PADAPTER	pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void mpt_StopOfdmContTx(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	priv->bCckContTx = false;
+	priv->bOfdmContTx = false;
+
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+	rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+	mdelay(10);
+	rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0);
+	rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1);
+
+}	/* mpt_StopOfdmContTx */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_SwitchRfSetting92S
+ *
+ * Overview:	Change RF Setting when we siwthc channel/rate/BW for 92S series MP.
+ *
+ * Input:       IN	PADAPTER				pAdapter
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 01/08/2009	MHC		Suggestion from SD3 Willis for 92S series.
+ * 01/09/2009	MHC		Add CCK modification for 40MHZ. Suggestion from SD3.
+ *
+ *---------------------------------------------------------------------------*/
+ void mpt_SwitchRfSetting92S(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8	ChannelToSw = priv->MptChannelToSw;
+	u32	ulRateIdx = priv->MptRateIndex;
+	u32	ulbandwidth = priv->MptBandWidth;
+
+	if (ulbandwidth == BAND_20MHZ_MODE)
+	{
+		if (ChannelToSw == 1)
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0A8F4);
+		}
+		else if (ChannelToSw == 11)
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F5);
+		}
+		else	
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F4);
+		}
+	}
+	else 	
+	{
+		if (ChannelToSw == 3)
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0A8F4);
+		}
+		else if (ChannelToSw == 9 || ChannelToSw == 10 || ChannelToSw == 11)
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F5);
+		}
+		else	
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F4);
+		}
+	}
+
+
+	if (ulRateIdx < MPT_RATE_6M)	
+		rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_SYN_G2, 0xFFFFF, 0x04440);
+	else		
+		rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_SYN_G2, 0xFFFFF, 0x0F200);
+}	
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_ProSetTxPower()
+ *
+ * Overview:	Change Tx Power of current channel for 
+ *				OID_RT_PRO_SET_TX_POWER_CONTROL.
+ *
+ * Input:		NONE
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+bool mpt_ProSetTxPower(	struct net_device *dev,	u32 ulTxPower)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8		CurrChannel = priv->rtllib->current_network.channel;
+	bool		bResult = true;
+	
+	CurrChannel = priv->MptChannelToSw;
+	
+	if(CurrChannel > 11 || CurrChannel < 1)
+	{
+		printk("mpt_ProSetTxPower(): CurrentChannel:%d is not valid\n", CurrChannel);		
+		return false;
+	}
+
+	if(ulTxPower > MAX_TX_PWR_INDEX_N_MODE)
+	{
+		printk("mpt_ProSetTxPower(): TxPWR:%d is invalid\n", ulTxPower);		
+		return false;
+	}
+
+	if( priv->MptRateIndex >= MPT_RATE_1M &&
+		priv->MptRateIndex <= MPT_RATE_11M )
+	{
+		priv->TxPowerLevelCCK[CurrChannel-1] = (u8)ulTxPower;
+		
+		priv->RfTxPwrLevelCck[0][CurrChannel-1] = (u8)ulTxPower;
+	}
+	else if(priv->MptRateIndex >= MPT_RATE_6M &&
+			priv->MptRateIndex <= MPT_RATE_MCS15 )
+	{
+		priv->TxPowerLevelOFDM24G[CurrChannel-1] = (u8)ulTxPower;
+
+		priv->RfTxPwrLevelOfdm1T[0][CurrChannel-1] = (u8)ulTxPower;
+		priv->RfTxPwrLevelOfdm2T[0][CurrChannel-1] = (u8)ulTxPower;
+	}
+
+	 rtl8192_phy_setTxPower(dev,CurrChannel);
+
+	return bResult;
+
+}	/* mpt_ProSetTxPower */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_ProSetTxAGCOffset()
+ *
+ * Overview:	Change Tx AGC Offset 
+ *				OID_RT_PRO_SET_TX_AGC_OFFSET.
+ *
+ * Input:			NONE
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	08/09/2007	Cosa	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+bool mpt_ProSetTxAGCOffset(struct net_device *dev,	u32	ulTxAGCOffset)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	bool	bResult = true;
+	u32	TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D;
+
+	TxAGCOffset_B = (ulTxAGCOffset&0x000000ff);
+	TxAGCOffset_C = ((ulTxAGCOffset&0x0000ff00)>>8);
+	TxAGCOffset_D = ((ulTxAGCOffset&0x00ff0000)>>16);
+
+	if( TxAGCOffset_B > TxAGC_Offset_neg1 ||
+		TxAGCOffset_C > TxAGC_Offset_neg1 ||
+		TxAGCOffset_D > TxAGC_Offset_neg1 )
+	{
+		printk("mpt_ProSetTxAGCOffset(): TxAGCOffset:%d is invalid\n", ulTxAGCOffset);
+		return false;
+	}
+
+	priv->AntennaTxPwDiff[0] = TxAGCOffset_B;
+	priv->AntennaTxPwDiff[1] = TxAGCOffset_C;
+	priv->AntennaTxPwDiff[2] = TxAGCOffset_D;
+	
+	MPT_ProSetTxAGCOffset(dev);
+
+	return bResult;
+
+}	/* mpt_ProSetTxPower */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_ProSetTxAGCOffset()
+ *
+ * Overview:	Change Tx AGC Offset 
+ *				OID_RT_PRO_SET_TX_AGC_OFFSET.
+ *
+ * Input:			NONE
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	08/09/2007	Cosa	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+bool mpt_ProSetRxFilter(struct net_device *dev, u32	RCRMode)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	if(RCRMode == 1)
+	{ 
+		priv->MptRCR &= ~(RCR_AAP|RCR_AM|RCR_AB);
+		priv->MptRCR |= RCR_APM;
+		write_nic_dword(dev, RCR, priv->MptRCR);
+	}
+	else
+	{ 
+		priv->MptRCR |= (RCR_AAP|RCR_APM|RCR_AM|RCR_AB);
+		write_nic_dword(dev, RCR, priv->MptRCR);
+	}
+
+	return 1;
+}	/* mpt_ProSetTxPower */
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_ProSetModulation()
+ *
+ * Overview:	Switch wireless mode for OID_RT_PRO_SET_MODULATION.
+ *
+ * Input:		PADAPTER	pAdapter
+ *				ULONG		ulWirelessMode
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+bool mpt_ProSetModulation(struct net_device *dev, u32 ulWirelessMode)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	WIRELESS_MODE	WirelessMode;
+	bool				bResult = false;
+
+	switch(ulWirelessMode)
+	{
+	case WIRELESS_MODE_A: 
+		WirelessMode = WIRELESS_MODE_A;
+		break;
+
+	case WIRELESS_MODE_B: 
+		WirelessMode = WIRELESS_MODE_B;
+		break;
+
+	case WIRELESS_MODE_G: 
+	case WIRELESS_MODE_G |WIRELESS_MODE_B: 
+		WirelessMode = WIRELESS_MODE_G;
+		break;
+
+	case WIRELESS_MODE_N_24G:
+		WirelessMode = WIRELESS_MODE_N_24G;
+		break;
+
+	case WIRELESS_MODE_N_5G:
+		WirelessMode = WIRELESS_MODE_N_5G;
+		break;
+
+	case WIRELESS_MODE_AUTO: 
+	default:
+		bResult = false;
+		return bResult;
+		break;
+	}
+
+	priv->rtllib->mode = WirelessMode;
+	priv->RegWirelessMode = WirelessMode;
+	rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
+	HTUseDefaultSetting(priv->rtllib);
+	
+
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+	{		
+		mpt_SwitchRfSetting92S(dev);
+	}
+	
+	bResult = true;
+	
+	return bResult;
+
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_Pro819xIoCallback()
+ *
+ * Overview:	Callback function of a workitem for IO.	
+ *
+ * Input:		NONE
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void mpt_Pro819xIoCallback(struct net_device *dev)
+{
+
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u32 MptActType = priv->MptActType;
+
+	printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, MptActType:%x, MptRfPath:%x\n", 
+		__func__, priv->MptIoOffset, priv->MptIoValue, MptActType, priv->MptRfPath);
+
+	switch(MptActType)
+	{
+	case MPT_WRITE_MAC_1BYTE:
+		write_nic_byte(dev, priv->MptIoOffset, (u8)(priv->MptIoValue));
+		break;
+
+	case MPT_WRITE_MAC_2BYTE:
+		write_nic_word(dev, priv->MptIoOffset, (u16)(priv->MptIoValue));
+		break;
+
+	case MPT_WRITE_MAC_4BYTE:
+		write_nic_dword(dev, priv->MptIoOffset, (u32)(priv->MptIoValue));
+		break;
+
+	case MPT_WRITE_RF:
+		rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)priv->MptRfPath, 
+			priv->MptIoOffset, bRFRegOffsetMask, priv->MptIoValue);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void MPT_ProSetSingleCarrier(struct net_device *dev, bool ulMode)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+	if(ulMode == 1) { 
+		priv->bSingleCarrier = true;
+	} else { 
+		priv->bSingleCarrier = false;
+	}
+	
+	if(priv->bSingleCarrier)
+	{
+		if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bOFDMEn))
+			rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, bEnable);
+
+		rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, bDisable);
+
+		rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, bEnable);
+
+		rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+		rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
+		rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+	}
+	else
+	{ 
+	    rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
+	    rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
+	    rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
+	    mdelay(10);
+	    rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0);
+	    rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1);
+	}
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	MPT_ProSetBandWidth819x()
+ *
+ * Overview:	None
+ *
+ * Input:		PADAPTER			pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	01/03/2007	Cosa	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void MPT_ProSetBandWidth819x(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	PRT_HIGH_THROUGHPUT	pHTInfo = priv->rtllib->pHTInfo;
+	u32	ulbandwidth = priv->MptBandWidth;
+
+	printk("##################MPT_ProSetBandWidth819x() is start. \n");
+	/* 2007/06/07 MH Call normal driver API and set 40MHZ mode. */			
+	if (ulbandwidth == BAND_20MHZ_MODE) {
+		/* 20 MHZ sub-carrier mode --> dont care. */
+		pHTInfo->bCurBW40MHz = false;
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
+		priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20, pHTInfo->CurSTAExtChnlOffset);
+	} else if (ulbandwidth == BAND_40MHZ_DUPLICATE_MODE) {
+		/* Sub-Carrier mode is defined in MAC data sheet chapter 12.3. */	
+		/* 40MHX sub-carrier mode --> duplicate. */
+		pHTInfo->bCurBW40MHz = true;				
+		pHTInfo->bCurTxBW40MHz = true;								
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_DEF;			
+		
+		priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+	} else if (ulbandwidth == BAND_40MHZ_LOWER_MODE) {
+		/* 40MHX sub-carrier mode --> lower mode  */
+		pHTInfo->bCurBW40MHz = true;				
+		pHTInfo->bCurTxBW40MHz = true;								
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_LOWER;
+		
+		/* Extention channel is lower. Current channel must > 3. */
+		/*if (pMgntInfo->dot11CurrentChannelNumber < 3)				
+			DbgPrint("Illegal Current_Chl=%d\r\n", pMgntInfo->dot11CurrentChannelNumber);
+		else
+			pAdapter->HalFunc.SwChnlByTimerHandler(pAdapter, pMgntInfo->dot11CurrentChannelNumber-2);*/
+		
+		priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+	} else if (ulbandwidth == BAND_40MHZ_UPPER_MODE)	{
+		/* 40MHX sub-carrier mode --> upper mode  */
+		pHTInfo->bCurBW40MHz = true;				
+		pHTInfo->bCurTxBW40MHz = true;
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_UPPER;
+		
+		/* Extention channel is upper. Current channel must < 12. */
+		/*if (pMgntInfo->dot11CurrentChannelNumber > 12)
+			DbgPrint("Illegal Current_Chl=%d", pMgntInfo->dot11CurrentChannelNumber);
+		else
+			pAdapter->HalFunc.SwChnlByTimerHandler(pAdapter, pMgntInfo->dot11CurrentChannelNumber+2);*/
+		
+		priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+	} else if (ulbandwidth == BAND_40MHZ_DONTCARE_MODE) {
+		/* 40MHX sub-carrier mode --> dont care mode  */
+		pHTInfo->bCurBW40MHz = true;
+		pHTInfo->bCurTxBW40MHz = true;
+		pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_LOWER;
+		
+		priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+	} else {
+		printk("##################MPT_ProSetBandWidth819x() error BW. \n");
+		return;
+	}
+
+{
+		mpt_SwitchRfSetting92S(dev);
+		return;
+	}
+	
+	printk("##################MPT_ProSetBandWidth819x() is finished. \n");
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	MPT_ProSwChannel()
+ *
+ * Overview:	Callback function of a work item to switch channel for 
+ *				OID_RT_PRO_SET_CHANNEL_DIRECT_CALL
+ *
+ * Input:		PVOID	Context
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/16/2007	MHC		Create Version 0.  
+ *	06/07/2007	MHC		Normal driver change switch channel handler. 
+ *	09/03/2008	MHC		RF channel register for 92S.
+ *	01/08/2008	MHC		For MP verification for 92S,weneed to change setting according
+ *						to SD3 Willis's document.
+ *
+ *---------------------------------------------------------------------------*/
+void MPT_ProSwChannel(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8	ChannelToSw = priv->MptChannelToSw;
+	u8	eRFPath;
+
+	priv->rtllib->current_network.channel = ChannelToSw;
+	priv->MptChannelToSw = ChannelToSw;	
+
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+	{
+		for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+		{
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw);
+		}
+
+		if (IS_HARDWARE_TYPE_8192SE(dev))
+		{
+			mpt_SwitchRfSetting92S(dev);
+		}
+	}
+
+#ifdef MP_DEVELOP_READY 
+	for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+	{
+		if (IS_HARDWARE_TYPE_8192SE(dev))
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw);		
+
+		udelay(100);
+	}
+
+	
+	for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+	{
+		if (IS_HARDWARE_TYPE_8192SE(dev))
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw);		
+
+		udelay(100);
+	}
+#endif
+	
+	/* 2007/06/07 MH Normal driver change sw channel handler. It does not 
+	   support SwChnlByDelayHandler ans replace with SwChnlByTimerHandler. */
+	priv->rtllib->set_chan(dev, ChannelToSw);
+
+#if 0 
+	if(pHalData->CurrentChannel == 14 && !pHalData->bCCKinCH14){
+		pHalData->bCCKinCH14 = true;
+		MPT_CCKTxPowerAdjust(pAdapter,pHalData->bCCKinCH14);
+	}
+	else if(pHalData->CurrentChannel != 14 && pHalData->bCCKinCH14){
+		pHalData->bCCKinCH14 = false;
+		MPT_CCKTxPowerAdjust(pAdapter,pHalData->bCCKinCH14);
+	}
+#endif
+}	/* MPT_ProSwChannel */
+
+/*-----------------------------------------------------------------------------
+ * Function:	MPT_ProSetDataRate819x()
+ *
+ * Overview:	None
+ *
+ * Input:		PADAPTER			pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	01/03/2007	Cosa	Create Version 0.  
+ *
+ *---------------------------------------------------------------------------*/
+void MPT_ProSetDataRate819x(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u8 	DataRate = 0xFF;
+	u32	ulRateIdx = priv->MptRateIndex;
+
+
+	printk("################MPT_ProSetDataRate819x():Rate=%d\n", ulRateIdx);
+	switch(ulRateIdx)
+	{
+		/* CCK rate. */
+		case	MPT_RATE_1M:		DataRate = 2;		break;
+		case	MPT_RATE_2M:		DataRate = 4;		break;
+		case	MPT_RATE_55M:	DataRate = 11;		break;
+		case	MPT_RATE_11M:	DataRate = 22;		break;
+	
+		/* OFDM rate. */
+		case	MPT_RATE_6M:		DataRate = 12;		break;
+		case	MPT_RATE_9M:		DataRate = 18;		break;
+		case	MPT_RATE_12M:	DataRate = 24;		break;
+		case	MPT_RATE_18M:	DataRate = 36;		break;
+		case	MPT_RATE_24M:	DataRate = 48;		break;			
+		case	MPT_RATE_36M:	DataRate = 72;		break;
+		case	MPT_RATE_48M:	DataRate = 96;		break;
+		case	MPT_RATE_54M:	DataRate = 108;	break;
+	
+		/* HT rate. */
+		case	MPT_RATE_MCS0:	DataRate = 0x80;	break;
+		case	MPT_RATE_MCS1:	DataRate = 0x81;	break;
+		case	MPT_RATE_MCS2:	DataRate = 0x82;	break;
+		case	MPT_RATE_MCS3:	DataRate = 0x83;	break;
+		case	MPT_RATE_MCS4:	DataRate = 0x84;	break;
+		case	MPT_RATE_MCS5:	DataRate = 0x85;	break;
+		case	MPT_RATE_MCS6:	DataRate = 0x86;	break;
+		case	MPT_RATE_MCS7:	DataRate = 0x87;	break;
+		case	MPT_RATE_MCS8:	DataRate = 0x88;	break;
+		case	MPT_RATE_MCS9:	DataRate = 0x89;	break;
+		case	MPT_RATE_MCS10:	DataRate = 0x8A;	break;
+		case	MPT_RATE_MCS11:	DataRate = 0x8B;	break;
+		case	MPT_RATE_MCS12:	DataRate = 0x8C;	break;
+		case	MPT_RATE_MCS13:	DataRate = 0x8D;	break;
+		case	MPT_RATE_MCS14:	DataRate = 0x8E;	break;
+		case	MPT_RATE_MCS15:	DataRate = 0x8F;	break;
+		case MPT_RATE_LAST:
+		break;
+
+	default:
+		break;
+	}
+	
+	{
+		mpt_SwitchRfSetting92S(dev);
+	}
+	
+#ifdef MP_DEVELOP_READY 	
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+	{
+		for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+		{
+			if (ulbandwidth == BAND_20MHZ_MODE)
+				rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, (BIT11|BIT10), 0x01);		
+			else
+				rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, (BIT11|BIT10), 0x00);		
+
+			delay_us(100);
+		}
+	} 	
+#endif
+
+
+	if(!r8192_MgntIsRateValidForWirelessMode(DataRate, 	priv->rtllib->mode) && 	DataRate != 0 ) 
+	{
+		printk("[MPT]: unknow wmode=%d", priv->rtllib->mode);
+	}	
+	if (DataRate != 0xFF)
+	{
+		printk("[MPT]: Force rate=0x%02x", DataRate);
+		priv->rtllib->rate = (int)DataRate;
+	}
+
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	MPT_ProSetTxAGCOffset()
+ *
+ * Overview:	Set Tx power level for
+ *				OID_RT_PRO_SET_TX_AGC_OFFSET
+ *
+ * Input:			PVOID	Context
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	08/09/2007	Cosa	Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void MPT_ProSetTxAGCOffset(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u32	u4RegValue, TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D;
+
+	TxAGCOffset_B = priv->AntennaTxPwDiff[0];
+	TxAGCOffset_C = priv->AntennaTxPwDiff[1];
+	TxAGCOffset_D = priv->AntennaTxPwDiff[2];
+
+
+	u4RegValue = (TxAGCOffset_D<<8 | TxAGCOffset_C<<4 | TxAGCOffset_B);
+	rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+	printk("##################MPT_ProSetTxAGCOffset() is finished \n");
+}
+
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phy.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_phy.c
@@ -0,0 +1,3464 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifdef RTL8192SE
+
+#include "../rtl_core.h"
+#include "../rtl_dm.h"
+#include "r8192S_phy.h"
+#include "r8192S_phyreg.h"
+#include "r8192S_rtl6052.h"
+#include "r8192S_hwimg.h"
+
+#ifdef ENABLE_DOT11D
+#include "../rtllib/dot11d.h"
+#endif
+
+/*---------------------------Define Local Constant---------------------------*/
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define	PHY_STOP_SWITCH_CLKREQ			0
+/*---------------------------Define Local Constant---------------------------*/
+
+/*------------------------Define global variable-----------------------------*/
+
+#define Rtl819XMAC_Array			Rtl8192SEMAC_2T_Array
+#define Rtl819XAGCTAB_Array			Rtl8192SEAGCTAB_Array
+#define Rtl819XPHY_REG_Array			Rtl8192SEPHY_REG_2T2RArray
+#define Rtl819XPHY_REG_to1T1R_Array 		Rtl8192SEPHY_ChangeTo_1T1RArray
+#define Rtl819XPHY_REG_to1T2R_Array		Rtl8192SEPHY_ChangeTo_1T2RArray
+#define Rtl819XPHY_REG_to2T2R_Array		Rtl8192SEPHY_ChangeTo_2T2RArray
+#define Rtl819XPHY_REG_Array_PG			Rtl8192SEPHY_REG_Array_PG
+#define Rtl819XRadioA_Array			Rtl8192SERadioA_1T_Array
+#define Rtl819XRadioB_Array			Rtl8192SERadioB_Array
+#define Rtl819XRadioB_GM_Array					Rtl8192SERadioB_GM_Array
+#define Rtl819XRadioA_to1T_Array		Rtl8192SERadioA_to1T_Array
+#define Rtl819XRadioA_to2T_Array		Rtl8192SERadioA_to2T_Array
+
+/*------------------------Define local variable------------------------------*/
+#if 0
+static u32	RF_CHANNEL_TABLE_ZEBRA[]={
+		0,
+		0x085c,
+		0x08dc,
+		0x095c,
+		0x09dc,
+		0x0a5c,
+		0x0adc,
+		0x0b5c,
+		0x0bdc,
+		0x0c5c,
+		0x0cdc,
+		0x0d5c,
+		0x0ddc,
+		0x0e5c,
+		0x0f72,
+};
+#endif
+
+/*------------------------Define local variable------------------------------*/
+
+
+/*--------------------Define export function prototype-----------------------*/
+/*--------------------Define export function prototype-----------------------*/
+
+
+/*---------------------Define local function prototype-----------------------*/
+
+static  u32 phy_FwRFSerialRead( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset); 
+static	void phy_FwRFSerialWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+
+static u32 phy_RFSerialRead(struct net_device* dev,RF90_RADIO_PATH_E eRFPath,u32 Offset);
+static void phy_RFSerialWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+static	u32 phy_CalculateBitShift(u32 BitMask);
+static	bool	phy_BB8190_Config_HardCode(struct net_device* dev);
+static	bool	phy_BB8192S_Config_ParaFile(struct net_device* dev);
+	
+static bool phy_ConfigMACWithHeaderFile(struct net_device* dev);
+	
+static bool phy_ConfigBBWithHeaderFile(struct net_device* dev,u8 ConfigType);
+
+static bool phy_ConfigBBWithPgHeaderFile(struct net_device* dev,u8 ConfigType);
+
+static bool phy_SetBBtoDiffRFWithHeaderFile(struct net_device* dev,u8 ConfigType);
+
+static void phy_InitBBRFRegisterDefinition(struct net_device* dev);
+static bool phy_SetSwChnlCmdArray(	SwChnlCmd*		CmdTable,
+		u32			CmdTableIdx,
+		u32			CmdTableSz,
+		SwChnlCmdID		CmdID,
+		u32			Para1,
+		u32			Para2,
+		u32			msDelay	);
+
+static bool phy_SwChnlStepByStep(
+	struct net_device* dev,
+	u8		channel,
+	u8		*stage,
+	u8		*step,
+	u32		*delay
+	);
+
+static void phy_FinishSwChnlNow(struct net_device* dev,u8 channel);
+
+static u8 phy_DbmToTxPwrIdx( struct net_device* dev, WIRELESS_MODE WirelessMode, long PowerInDbm);
+static bool phy_SetRFPowerState8192SE(struct net_device* dev,RT_RF_POWER_STATE eRFPowerState);
+static void phy_CheckEphySwitchReady( struct net_device* dev);
+
+static long phy_TxPwrIdxToDbm( struct net_device* dev, WIRELESS_MODE   WirelessMode, u8 TxPwrIdx);
+void rtl8192_SetFwCmdIOCallback(struct net_device* dev);
+
+						
+/*---------------------Define local function prototype-----------------------*/
+
+
+/*----------------------------Function Body----------------------------------*/
+u32 rtl8192_QueryBBReg(struct net_device* dev, u32 RegAddr, u32 BitMask)
+{
+
+  	u32	ReturnValue = 0, OriginalValue, BitShift;
+
+#if (DISABLE_BB_RF == 1)
+	return 0;
+#endif
+
+	RT_TRACE(COMP_RF, "--->PHY_QueryBBReg(): RegAddr(%#x), BitMask(%#x)\n", RegAddr, BitMask);
+
+	OriginalValue = read_nic_dword(dev, RegAddr);
+
+	BitShift = phy_CalculateBitShift(BitMask);
+	ReturnValue = (OriginalValue & BitMask) >> BitShift;
+
+	RT_TRACE(COMP_RF, "<---PHY_QueryBBReg(): RegAddr(%#x), BitMask(%#x), OriginalValue(%#x)\n", RegAddr, BitMask, OriginalValue);
+	return (ReturnValue);
+}
+
+void rtl8192_setBBreg(struct net_device* dev, u32 RegAddr, u32 BitMask, u32 Data)
+{
+	u32	OriginalValue, BitShift, NewValue;
+
+#if (DISABLE_BB_RF == 1)
+	return;
+#endif
+
+
+	{
+		if(BitMask!= bMaskDWord)
+		{
+			OriginalValue = read_nic_dword(dev, RegAddr);
+			BitShift = phy_CalculateBitShift(BitMask);
+			NewValue = (((OriginalValue) & (~BitMask)) | (Data << BitShift));
+			write_nic_dword(dev, RegAddr, NewValue);	
+		}else
+			write_nic_dword(dev, RegAddr, Data);	
+	}
+
+	return;
+}
+
+
+u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask)
+{
+	u32 Original_Value, Readback_Value, BitShift;
+	struct r8192_priv *priv = rtllib_priv(dev);
+        unsigned long flags;
+	
+#if (DISABLE_BB_RF == 1) 
+	return 0;
+#endif
+	
+	RT_TRACE(COMP_RF, "--->PHY_QueryRFReg(): RegAddr(%#x), eRFPath(%#x), BitMask(%#x)\n", RegAddr, eRFPath,BitMask);
+	
+	if (!((priv->rf_pathmap >> eRFPath) & 0x1))
+		return 0;
+	
+	if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+		return	0;
+	
+	spin_lock_irqsave(&priv->rf_lock, flags);	
+	if (priv->Rf_Mode == RF_OP_By_FW)
+	{	
+		Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr);
+	}
+	else
+	{	
+		Original_Value = phy_RFSerialRead(dev, eRFPath, RegAddr);	   	
+	}
+	
+	BitShift =  phy_CalculateBitShift(BitMask);
+	Readback_Value = (Original_Value & BitMask) >> BitShift;	
+	spin_unlock_irqrestore(&priv->rf_lock, flags);
+
+	
+	return (Readback_Value);
+}
+
+
+void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 Original_Value, BitShift, New_Value;
+        unsigned long flags;
+#if (DISABLE_BB_RF == 1)
+	return;
+#endif
+	
+	RT_TRACE(COMP_RF, "--->PHY_SetRFReg(): RegAddr(%#x), BitMask(%#x), Data(%#x), eRFPath(%#x)\n", 
+		RegAddr, BitMask, Data, eRFPath);
+
+	if (!((priv->rf_pathmap >> eRFPath) & 0x1))
+		return ;
+	if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+	{
+		return;
+	}
+	
+	spin_lock_irqsave(&priv->rf_lock, flags);	
+	if (priv->Rf_Mode == RF_OP_By_FW)	
+	{		
+		if (BitMask != bRFRegOffsetMask) 
+		{
+			Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr);
+			BitShift =  phy_CalculateBitShift(BitMask);
+			New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
+		
+			phy_FwRFSerialWrite(dev, eRFPath, RegAddr, New_Value);
+		}
+		else
+			phy_FwRFSerialWrite(dev, eRFPath, RegAddr, Data);		
+	}
+	else
+	{		
+		if (BitMask != bRFRegOffsetMask) 
+		{
+			Original_Value = phy_RFSerialRead(dev, eRFPath, RegAddr);
+			BitShift =  phy_CalculateBitShift(BitMask);
+			New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
+		
+			phy_RFSerialWrite(dev, eRFPath, RegAddr, New_Value);
+		}
+		else
+			phy_RFSerialWrite(dev, eRFPath, RegAddr, Data);
+	
+	}
+	spin_unlock_irqrestore(&priv->rf_lock, flags);
+	RT_TRACE(COMP_RF, "<---PHY_SetRFReg(): RegAddr(%#x), BitMask(%#x), Data(%#x), eRFPath(%#x)\n", 
+			RegAddr, BitMask, Data, eRFPath);
+	
+}
+
+static	u32
+phy_FwRFSerialRead(
+	struct net_device* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32				Offset	)
+{
+	u32		retValue = 0;		
+#if 0	
+	u32		Data = 0;
+	u8		time = 0;
+	Data |= ((Offset&0xFF)<<12);
+	Data |= ((eRFPath&0x3)<<20);
+	Data |= 0x80000000;		
+	while (PlatformIORead4Byte(dev, QPNR)&0x80000000)
+	{
+		if (time++ < 100)
+		{
+			delay_us(10);
+		}
+		else
+			break;
+	}
+	PlatformIOWrite4Byte(dev, QPNR, Data);		
+	while (PlatformIORead4Byte(dev, QPNR)&0x80000000)
+	{
+		if (time++ < 100)
+		{
+			delay_us(10);
+		}
+		else
+			return	(0);
+	}
+	retValue = PlatformIORead4Byte(dev, RF_DATA);
+#endif	
+	return	(retValue);
+
+}	/* phy_FwRFSerialRead */
+
+static	void
+phy_FwRFSerialWrite(
+	struct net_device* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32				Offset,
+	u32				Data	)
+{
+#if 0	
+	u8	time = 0;
+	DbgPrint("N FW RF CTRL RF-%d OF%02x DATA=%03x\n\r", eRFPath, Offset, Data);
+	
+	Data |= ((Offset&0xFF)<<12);
+	Data |= ((eRFPath&0x3)<<20);
+	Data |= 0x400000;
+	Data |= 0x80000000;
+	
+	while (PlatformIORead4Byte(dev, QPNR)&0x80000000)
+	{
+		if (time++ < 100)
+		{
+			delay_us(10);
+		}
+		else
+			break;
+	}
+	PlatformIOWrite4Byte(dev, QPNR, Data);
+#endif		
+}	/* phy_FwRFSerialWrite */
+
+#if (RTL92SE_FPGA_VERIFY == 1)
+static u32 phy_RFSerialRead(struct net_device* dev,RF90_RADIO_PATH_E eRFPath,u32 Offset)
+{
+
+	u32						retValue = 0;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	BB_REGISTER_DEFINITION_T	*pPhyReg = &priv->PHYRegDef[eRFPath];
+	u32						NewOffset;
+
+	Offset &= 0x3f;
+
+	if(	priv->rf_chip == RF_8256 || 
+		priv->rf_chip == RF_8225 ||	
+		priv->rf_chip == RF_6052)
+	{
+		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+
+		if(Offset>=31)
+		{
+			priv->RFReadPageCnt[2]++;
+			priv->RfReg0Value[eRFPath] |= 0x140;
+
+			rtl8192_setBBreg(dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+
+			NewOffset = Offset - 30;
+			
+		}else if(Offset>=16)
+		{
+			priv->RFReadPageCnt[1]++;
+			priv->RfReg0Value[eRFPath] |= 0x100;
+			priv->RfReg0Value[eRFPath] &= (~0x40);
+
+			rtl8192_setBBreg(dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+
+			NewOffset = Offset - 15;
+		}
+		else
+		{
+			priv->RFReadPageCnt[0]++;
+			NewOffset = Offset;
+	}	
+	}	
+	else
+		NewOffset = Offset;
+
+#if (RTL92SE_FPGA_VERIFY == 1)
+	{
+		u32	temp1, temp2;
+
+		temp1 = rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff);
+		temp2 = rtl8192_QueryBBReg(dev, pPhyReg->rfHSSIPara2, 0xffffffff);
+		temp2 = temp2 & (~bLSSIReadAddress) | (NewOffset<<24) | bLSSIReadEdge;
+
+		rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff, temp1&(~bLSSIReadEdge));
+		msleep(1);
+		rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, 0xffffffff, temp2);
+		msleep(1);
+		rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff, temp1|bLSSIReadEdge);
+		msleep(1);
+		
+	}
+#else
+	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset);
+
+	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x0);	
+	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x1);	
+#endif
+	
+	mdelay(1);
+
+	retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
+	
+	if(	priv->rf_chip == RF_8256 || 
+		priv->rf_chip == RF_8225 ||
+		priv->rf_chip == RF_6052)
+	{
+		if (Offset >= 0x10)
+		{
+			priv->RfReg0Value[eRFPath] &= 0xebf;
+		
+			rtl8192_setBBreg(
+				dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+		}
+
+		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf);
+	}
+	
+	return retValue;	
+}
+
+
+static void
+phy_RFSerialWrite(
+	struct net_device* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32				Offset,
+	u32				Data
+	)
+{
+	u32					DataAndAddr = 0;
+	struct r8192_priv 			*priv = rtllib_priv(dev);
+	BB_REGISTER_DEFINITION_T	*pPhyReg = &priv->PHYRegDef[eRFPath];
+	u32					NewOffset;
+
+	Offset &= 0x3f;
+
+	PHY_RFShadowWrite(dev, eRFPath, Offset, Data);	
+
+	if( 	priv->rf_chip == RF_8256 || 
+		priv->rf_chip == RF_8225 ||
+		priv->rf_chip == RF_6052)
+	{
+		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+				
+		if(Offset>=31)
+		{
+			priv->RFWritePageCnt[2]++;
+			priv->RfReg0Value[eRFPath] |= 0x140;
+			
+			rtl8192_setBBreg(dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+
+			NewOffset = Offset - 30;
+			
+		}else if(Offset>=16)
+		{
+			priv->RFWritePageCnt[1]++;
+			priv->RfReg0Value[eRFPath] |= 0x100;
+			priv->RfReg0Value[eRFPath] &= (~0x40);			
+							
+
+			rtl8192_setBBreg(dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+
+			NewOffset = Offset - 15;
+		}
+		else
+		{
+			priv->RFWritePageCnt[0]++;
+			NewOffset = Offset;
+	}
+	}
+	else
+		NewOffset = Offset;
+
+	DataAndAddr = (Data<<16) | (NewOffset&0x3f);
+
+	rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+
+
+	if(Offset==0x0)
+		priv->RfReg0Value[eRFPath] = Data;
+
+ 	if(	priv->rf_chip == RF_8256 || 
+		priv->rf_chip == RF_8225 ||
+		priv->rf_chip == RF_6052)
+	{
+		if (Offset >= 0x10)
+		{
+			if(Offset != 0)
+			{
+				priv->RfReg0Value[eRFPath] &= 0xebf;
+				rtl8192_setBBreg(
+				dev, 
+				pPhyReg->rf3wireOffset, 
+				bMaskDWord, 
+				(priv->RfReg0Value[eRFPath] << 16)	);
+			}
+		}	
+		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf);
+	}
+	
+}
+#else
+static	u32
+phy_RFSerialRead(
+	struct net_device* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32				Offset
+	)
+{
+
+	u32					retValue = 0;
+	struct r8192_priv 			*priv = rtllib_priv(dev);
+	BB_REGISTER_DEFINITION_T	*pPhyReg = &priv->PHYRegDef[eRFPath];
+	u32					NewOffset;
+	u32 					tmplong,tmplong2;
+	u8					RfPiEnable=0;
+#if 0
+	if(priv->rf_chip == RF_8225 && Offset > 0x24) 
+		return	retValue;
+	if(priv->rf_chip == RF_8256 && Offset > 0x2D) 
+		return	retValue;
+#endif
+	Offset &= 0x3f;
+
+	NewOffset = Offset;
+
+	tmplong = rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord);
+	if(eRFPath == RF90_PATH_A)
+		tmplong2 = tmplong;
+	else
+	tmplong2 = rtl8192_QueryBBReg(dev, pPhyReg->rfHSSIPara2, bMaskDWord);
+	tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge;	
+
+	rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong&(~bLSSIReadEdge));
+	udelay(1000);
+	
+	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2);
+	udelay(1000);
+	
+	rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong|bLSSIReadEdge);
+
+	if(eRFPath == RF90_PATH_A)
+		RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter1, BIT8);
+	else if(eRFPath == RF90_PATH_B)
+		RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XB_HSSIParameter1, BIT8);
+	
+	if(RfPiEnable)
+	{	
+		retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData);
+	}
+	else
+	{	
+		retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
+	}
+	
+	retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
+	
+	return retValue;	
+		
+}
+
+static	void
+phy_RFSerialWrite(
+	struct net_device* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32				Offset,
+	u32				Data
+	)
+{
+	u32					DataAndAddr = 0;
+	struct r8192_priv 			*priv = rtllib_priv(dev);
+	BB_REGISTER_DEFINITION_T	*pPhyReg = &priv->PHYRegDef[eRFPath];
+	u32					NewOffset;
+	
+#if 0
+	if(priv->rf_chip == RF_8225 && Offset > 0x24) 
+		return;
+	if(priv->rf_chip == RF_8256 && Offset > 0x2D) 
+		return;
+#endif
+
+	Offset &= 0x3f;
+
+	PHY_RFShadowWrite(dev, eRFPath, Offset, Data);	
+
+		NewOffset = Offset;
+
+	DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff;	
+
+	rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+	
+}
+
+#endif
+
+static u32 phy_CalculateBitShift(u32 BitMask)
+{
+	u32 i;
+
+	for(i=0; i<=31; i++)
+	{
+		if ( ((BitMask>>i) &  0x1 ) == 1)
+			break;
+	}
+
+	return (i);
+}
+
+
+extern bool PHY_MACConfig8192S(struct net_device* dev)
+{
+	bool rtStatus = true;
+
+#if RTL8190_Download_Firmware_From_Header
+	rtStatus = phy_ConfigMACWithHeaderFile(dev);
+#else
+	
+	RT_TRACE(COMP_INIT, "Read MACREG.txt\n");
+#endif
+	return (rtStatus == true) ? 1:0;
+
+}
+
+extern	bool
+PHY_BBConfig8192S(struct net_device* dev)
+{
+	bool rtStatus = true;
+	u8 PathMap = 0, index = 0, rf_num = 0;
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	u8 bRegHwParaFile = 1;
+	
+	phy_InitBBRFRegisterDefinition(dev);
+
+	switch(bRegHwParaFile)
+	{
+		case 0:
+			phy_BB8190_Config_HardCode(dev);
+			break;
+
+		case 1:
+			rtStatus = phy_BB8192S_Config_ParaFile(dev);
+			break;
+
+		case 2:
+			phy_BB8190_Config_HardCode(dev);
+			phy_BB8192S_Config_ParaFile(dev);
+			break;
+
+		default:
+			phy_BB8190_Config_HardCode(dev);
+			break;
+	}
+
+	PathMap = (u8)(rtl8192_QueryBBReg(dev, rFPGA0_TxInfo, 0xf) |
+				rtl8192_QueryBBReg(dev, rOFDM0_TRxPathEnable, 0xf));
+	priv->rf_pathmap = PathMap;
+	for(index = 0; index<4; index++)
+	{
+		if((PathMap>>index)&0x1)
+			rf_num++;
+	}
+
+	if((priv->rf_type==RF_1T1R && rf_num!=1) ||
+		(priv->rf_type==RF_1T2R && rf_num!=2) ||
+		(priv->rf_type==RF_2T2R && rf_num!=2) ||
+		(priv->rf_type==RF_2T2R_GREEN && rf_num!=2) ||
+		(priv->rf_type==RF_2T4R && rf_num!=4))
+	{
+		RT_TRACE( COMP_INIT, "PHY_BBConfig8192S: RF_Type(%x) does not match RF_Num(%x)!!\n", priv->rf_type, rf_num);
+	}
+	return rtStatus;
+}
+
+extern	bool
+PHY_RFConfig8192S(struct net_device* dev)
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	bool    		rtStatus = true;
+
+
+	if (IS_HARDWARE_TYPE_8192SE(dev))
+		priv->rf_chip = RF_6052;
+
+	switch(priv->rf_chip)
+	{
+	case RF_8225:
+	case RF_6052:
+		rtStatus = PHY_RF6052_Config(dev);
+		break;
+		
+	case RF_8256:			
+		break;
+		
+	case RF_8258:
+		break;
+		
+	case RF_PSEUDO_11N:
+		break;
+        default:
+            break;
+	}
+
+	return rtStatus;
+}
+
+
+static bool  
+phy_BB8190_Config_HardCode(struct net_device* dev)
+{
+	return true;
+}
+
+
+static bool 	
+phy_BB8192S_Config_ParaFile(struct net_device* dev)
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	bool rtStatus = true;	
+	
+	RT_TRACE(COMP_INIT, "==>phy_BB8192S_Config_ParaFile\n");
+
+#if	RTL8190_Download_Firmware_From_Header
+	if (priv->rf_type == RF_1T2R || priv->rf_type == RF_2T2R ||
+	    priv->rf_type == RF_1T1R ||priv->rf_type == RF_2T2R_GREEN)
+	{
+		rtStatus = phy_ConfigBBWithHeaderFile(dev,BaseBand_Config_PHY_REG);
+		if(priv->rf_type != RF_2T2R && priv->rf_type != RF_2T2R_GREEN)
+		{
+			rtStatus = phy_SetBBtoDiffRFWithHeaderFile(dev,BaseBand_Config_PHY_REG);
+		}
+	}else
+		rtStatus = false;
+#else
+	RT_TRACE(COMP_INIT, "RF_Type == %d\n", priv->rf_type);		
+	if (priv->rf_type == RF_1T2R || priv->rf_type == RF_2T2R ||
+	    priv->rf_type == RF_1T1R ||priv->rf_type == RF_2T2R_GREEN)
+	{
+		rtStatus = phy_ConfigBBWithParaFile(dev, (char* )&szBBRegFile);
+		if(priv->rf_type != RF_2T2R && priv->rf_type != RF_2T2R_GREEN)
+		{
+			if(priv->rf_type == RF_1T1R)
+				rtStatus = phy_SetBBtoDiffRFWithParaFile(dev, (char* )&szBBRegto1T1RFile);
+			else if(priv->rf_type == RF_1T2R)
+				rtStatus = phy_SetBBtoDiffRFWithParaFile(dev, (char* )&szBBRegto1T2RFile);
+		}
+
+	}else
+		rtStatus = false;
+#endif
+
+	if(rtStatus != true){
+		RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile():Write BB Reg Fail!!");
+		goto phy_BB8190_Config_ParaFile_Fail;
+	}
+
+	if (priv->AutoloadFailFlag == false)
+	{
+		priv->pwrGroupCnt = 0;
+
+#if	RTL8190_Download_Firmware_From_Header
+		rtStatus = phy_ConfigBBWithPgHeaderFile(dev,BaseBand_Config_PHY_REG);
+#else
+		rtStatus = phy_ConfigBBWithPgParaFile(dev, (char* )&szBBRegPgFile);
+#endif
+	}
+	if(rtStatus != true){
+		RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile():BB_PG Reg Fail!!");
+		goto phy_BB8190_Config_ParaFile_Fail;
+	}
+	
+#if RTL8190_Download_Firmware_From_Header
+	rtStatus = phy_ConfigBBWithHeaderFile(dev,BaseBand_Config_AGC_TAB);
+#else
+	RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile AGC_TAB.txt\n");
+	rtStatus = phy_ConfigBBWithParaFile(dev, (char* )&szAGCTableFile);
+#endif
+
+	if(rtStatus != true){
+		printk( "phy_BB8192S_Config_ParaFile():AGC Table Fail\n");
+		goto phy_BB8190_Config_ParaFile_Fail;
+	}
+
+
+#if 0	
+	if(pHalData->VersionID > VERSION_8190_BD)
+	{
+		u4RegValue = (  pHalData->AntennaTxPwDiff[2]<<8 | 
+						pHalData->AntennaTxPwDiff[1]<<4 | 
+						pHalData->AntennaTxPwDiff[0]);
+		
+		PHY_SetBBReg(dev, rFPGA0_TxGainStage, 
+			(bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+    	
+		u4RegValue = pHalData->CrystalCap;
+		PHY_SetBBReg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, u4RegValue);
+
+	}
+#endif
+
+	priv->bCckHighPower = (bool)(rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0x200));
+
+
+phy_BB8190_Config_ParaFile_Fail:	
+	return rtStatus;
+}
+
+static bool	
+phy_ConfigMACWithHeaderFile(struct net_device* dev)
+{
+	u32					i = 0;
+	u32					ArrayLength = 0;
+	u32*					ptrArray;	
+	
+	/*if(dev->bInHctTest)
+	{
+		RT_TRACE(COMP_INIT, DBG_LOUD, ("Rtl819XMACPHY_ArrayDTM\n"));
+		ArrayLength = MACPHY_ArrayLengthDTM;
+		ptrArray = Rtl819XMACPHY_ArrayDTM;
+	}
+	else if(pHalData->bTXPowerDataReadFromEEPORM)
+	{
+
+	}else*/
+	{ 
+		RT_TRACE(COMP_INIT, "Read Rtl819XMACPHY_Array\n");
+		ArrayLength = MAC_2T_ArrayLength;
+		ptrArray = Rtl819XMAC_Array;	
+	}
+		
+	/*for(i = 0 ;i < ArrayLength;i=i+3){
+		RT_TRACE(COMP_SEND, DBG_LOUD, ("The Rtl819XMACPHY_Array[0] is %lx Rtl819XMACPHY_Array[1] is %lx Rtl819XMACPHY_Array[2] is %lx\n",ptrArray[i], ptrArray[i+1], ptrArray[i+2]));
+		if(ptrArray[i] == 0x318)
+		{
+			ptrArray[i+2] = 0x00000800;
+		}
+		PHY_SetBBReg(dev, ptrArray[i], ptrArray[i+1], ptrArray[i+2]);
+	}*/
+	for(i = 0 ;i < ArrayLength;i=i+2){ 
+		write_nic_byte(dev, ptrArray[i], (u8)ptrArray[i+1]);
+	}
+	return true;
+}
+
+
+static bool 	
+phy_ConfigBBWithHeaderFile(struct net_device* dev,u8 ConfigType)
+{
+	int 		i;
+	u32*	Rtl819XPHY_REGArray_Table;
+	u32*	Rtl819XAGCTAB_Array_Table;
+	u16		PHY_REGArrayLen, AGCTAB_ArrayLen;
+	/*if(dev->bInHctTest)
+	{	
+	
+		AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM;
+		Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM;
+
+		if(pHalData->RF_Type == RF_2T4R)
+		{
+			PHY_REGArrayLen = PHY_REGArrayLengthDTM;
+			Rtl819XPHY_REGArray_Table = Rtl819XPHY_REGArrayDTM;
+		}
+		else if (pHalData->RF_Type == RF_1T2R)
+		{
+			PHY_REGArrayLen = PHY_REG_1T2RArrayLengthDTM;
+			Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_1T2RArrayDTM;
+		}		
+	
+	}
+	else
+	*/
+	AGCTAB_ArrayLen = AGCTAB_ArrayLength;
+	Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_Array;
+	PHY_REGArrayLen = PHY_REG_2T2RArrayLength; 
+	Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_Array;
+
+	if(ConfigType == BaseBand_Config_PHY_REG)
+	{
+		for(i=0;i<PHY_REGArrayLen;i=i+2)
+		{
+			if (Rtl819XPHY_REGArray_Table[i] == 0xfe)
+				mdelay(50);
+			else if (Rtl819XPHY_REGArray_Table[i] == 0xfd)
+				mdelay(5);
+			else if (Rtl819XPHY_REGArray_Table[i] == 0xfc)
+				mdelay(1);
+			else if (Rtl819XPHY_REGArray_Table[i] == 0xfb)
+				udelay(50);
+			else if (Rtl819XPHY_REGArray_Table[i] == 0xfa)
+				udelay(5);
+			else if (Rtl819XPHY_REGArray_Table[i] == 0xf9)
+				udelay(1);
+#ifdef ECS_T20_INIT_DELAY 
+				udelay(1);
+#endif
+			rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i], bMaskDWord, Rtl819XPHY_REGArray_Table[i+1]);		
+
+		}
+	}
+	else if(ConfigType == BaseBand_Config_AGC_TAB){
+		for(i=0;i<AGCTAB_ArrayLen;i=i+2)
+		{
+			rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i], bMaskDWord, Rtl819XAGCTAB_Array_Table[i+1]);		
+#ifdef ECS_T20_INIT_DELAY 
+			udelay(1);
+#endif
+		}
+	}
+	return true;
+}
+
+
+static bool  
+phy_SetBBtoDiffRFWithHeaderFile(struct net_device* dev, u8 ConfigType)
+{
+	int i;
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	u32* 			Rtl819XPHY_REGArraytoXTXR_Table;
+	u16				PHY_REGArraytoXTXRLen;
+	
+	if(priv->rf_type == RF_1T1R)
+	{
+		Rtl819XPHY_REGArraytoXTXR_Table = Rtl819XPHY_REG_to1T1R_Array;
+		PHY_REGArraytoXTXRLen = PHY_ChangeTo_1T1RArrayLength;
+	} 
+	else if(priv->rf_type == RF_1T2R)
+	{
+		Rtl819XPHY_REGArraytoXTXR_Table = Rtl819XPHY_REG_to1T2R_Array;
+		PHY_REGArraytoXTXRLen = PHY_ChangeTo_1T2RArrayLength;
+	}
+	else
+	{
+		return false;
+	}
+
+	if(ConfigType == BaseBand_Config_PHY_REG)
+	{
+		for(i=0;i<PHY_REGArraytoXTXRLen;i=i+3)
+		{
+			if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xfe)
+				mdelay(50);
+			else if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xfd)
+				mdelay(5);
+			else if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xfc)
+				mdelay(1);
+			else if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xfb)
+				udelay(50);
+			else if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xfa)
+				udelay(5);
+			else if (Rtl819XPHY_REGArraytoXTXR_Table[i] == 0xf9)
+				udelay(1);
+			rtl8192_setBBreg(dev, Rtl819XPHY_REGArraytoXTXR_Table[i], Rtl819XPHY_REGArraytoXTXR_Table[i+1], Rtl819XPHY_REGArraytoXTXR_Table[i+2]);		
+		}
+	}
+	else {
+		RT_TRACE(COMP_SEND, "phy_SetBBtoDiffRFWithHeaderFile(): ConfigType != BaseBand_Config_PHY_REG\n");
+	}
+	return true;
+}
+
+void
+storePwrIndexDiffRateOffset(
+	struct net_device* dev,
+	u32		RegAddr,
+	u32		BitMask,
+	u32		Data
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if(RegAddr == rTxAGC_Rate18_06)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][0] = Data;
+	}
+	if(RegAddr == rTxAGC_Rate54_24)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][1] = Data;
+	}
+	if(RegAddr == rTxAGC_CCK_Mcs32)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][6] = Data;
+	}
+	if(RegAddr == rTxAGC_Mcs03_Mcs00)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][2] = Data;
+	}
+	if(RegAddr == rTxAGC_Mcs07_Mcs04)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][3] = Data;
+	}
+	if(RegAddr == rTxAGC_Mcs11_Mcs08)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][4] = Data;
+	}
+	if(RegAddr == rTxAGC_Mcs15_Mcs12)
+	{
+		priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][5] = Data;
+		priv->pwrGroupCnt++;
+	}
+}
+
+static bool 
+phy_ConfigBBWithPgHeaderFile(struct net_device* dev,u8 ConfigType)
+{
+	int i;
+	u32*	Rtl819XPHY_REGArray_Table_PG;
+	u16	PHY_REGArrayPGLen;
+
+	PHY_REGArrayPGLen = PHY_REG_Array_PGLength;
+	Rtl819XPHY_REGArray_Table_PG = Rtl819XPHY_REG_Array_PG;
+
+	if(ConfigType == BaseBand_Config_PHY_REG)
+	{
+		for(i=0;i<PHY_REGArrayPGLen;i=i+3)
+		{
+			if (Rtl819XPHY_REGArray_Table_PG[i] == 0xfe)
+				mdelay(50);
+			else if (Rtl819XPHY_REGArray_Table_PG[i] == 0xfd)
+				mdelay(5);
+			else if (Rtl819XPHY_REGArray_Table_PG[i] == 0xfc)
+				mdelay(1);
+			else if (Rtl819XPHY_REGArray_Table_PG[i] == 0xfb)
+				udelay(50);
+			else if (Rtl819XPHY_REGArray_Table_PG[i] == 0xfa)
+				udelay(5);
+			else if (Rtl819XPHY_REGArray_Table_PG[i] == 0xf9)
+				udelay(1);
+			storePwrIndexDiffRateOffset(dev, Rtl819XPHY_REGArray_Table_PG[i], 
+				Rtl819XPHY_REGArray_Table_PG[i+1], 
+				Rtl819XPHY_REGArray_Table_PG[i+2]);
+			rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table_PG[i], Rtl819XPHY_REGArray_Table_PG[i+1], Rtl819XPHY_REGArray_Table_PG[i+2]);		
+		}
+	}
+	else{
+		RT_TRACE(COMP_SEND, "phy_ConfigBBWithPgHeaderFile(): ConfigType != BaseBand_Config_PHY_REG\n");
+	}
+	return true;
+	
+}	/* phy_ConfigBBWithPgHeaderFile */
+
+RT_STATUS rtl8192_phy_configRFPABiascurrent(struct net_device *dev, RF90_RADIO_PATH_E eRFPath)
+{
+	struct r8192_priv  *priv = rtllib_priv(dev);
+	RT_STATUS       rtStatus = RT_STATUS_SUCCESS;
+	u32          tmpval=0;
+
+	if(priv->IC_Class != IC_INFERIORITY_A)
+	{
+		tmpval = rtl8192_phy_QueryRFReg(dev, eRFPath, RF_IPA, 0xf);
+		rtl8192_phy_SetRFReg(dev, eRFPath, RF_IPA, 0xf, tmpval+1);
+	}
+
+	return rtStatus;
+}
+
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E	eRFPath)
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	int			i;
+	bool 		rtStatus = true;
+	u32			*Rtl819XRadioA_Array_Table;
+	u32			*Rtl819XRadioB_Array_Table;
+	u16			RadioA_ArrayLen,RadioB_ArrayLen;
+
+	RadioA_ArrayLen = RadioA_1T_ArrayLength;
+	Rtl819XRadioA_Array_Table=Rtl819XRadioA_Array;
+
+	if(priv->rf_type == RF_2T2R_GREEN)
+	{
+		Rtl819XRadioB_Array_Table = Rtl819XRadioB_GM_Array;
+		RadioB_ArrayLen = RadioB_GM_ArrayLength;
+	}
+	else
+	{		
+		Rtl819XRadioB_Array_Table=Rtl819XRadioB_Array;
+		RadioB_ArrayLen = RadioB_ArrayLength;	
+	}
+
+
+	RT_TRACE(COMP_INIT, "PHY_ConfigRFWithHeaderFile: Radio No %x\n", eRFPath);
+	rtStatus = true;
+
+	switch(eRFPath){
+		case RF90_PATH_A:
+			for(i = 0;i<RadioA_ArrayLen; i=i+2)
+			{
+				if(Rtl819XRadioA_Array_Table[i] == 0xfe)
+				{ 
+					mdelay(50);
+				}
+				else if (Rtl819XRadioA_Array_Table[i] == 0xfd)
+					mdelay(5);
+				else if (Rtl819XRadioA_Array_Table[i] == 0xfc)
+					mdelay(1);
+				else if (Rtl819XRadioA_Array_Table[i] == 0xfb)
+					udelay(50);
+				else if (Rtl819XRadioA_Array_Table[i] == 0xfa)
+					udelay(5);
+				else if (Rtl819XRadioA_Array_Table[i] == 0xf9)
+					udelay(1);
+				else {
+					rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioA_Array_Table[i], 
+							bMask20Bits, Rtl819XRadioA_Array_Table[i+1]);
+				}
+			}
+			rtl8192_phy_configRFPABiascurrent(dev, eRFPath);
+			break;
+		case RF90_PATH_B:
+			for(i = 0;i<RadioB_ArrayLen; i=i+2){
+				if(Rtl819XRadioB_Array_Table[i] == 0xfe)
+				{ 
+					mdelay(50);
+				}
+				else if (Rtl819XRadioB_Array_Table[i] == 0xfd)
+					mdelay(5);
+				else if (Rtl819XRadioB_Array_Table[i] == 0xfc)
+					mdelay(1);
+				else if (Rtl819XRadioB_Array_Table[i] == 0xfb)
+					udelay(50);
+				else if (Rtl819XRadioB_Array_Table[i] == 0xfa)
+					udelay(5);
+				else if (Rtl819XRadioB_Array_Table[i] == 0xf9)
+					udelay(1);
+				else
+				{
+					rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioB_Array_Table[i], bMask20Bits, Rtl819XRadioB_Array_Table[i+1]);
+				}
+#ifdef ECS_T20_INIT_DELAY 
+			udelay(1);
+#endif
+			}			
+			break;
+		case RF90_PATH_C:
+			break;
+		case RF90_PATH_D:
+			break;
+		default:
+			break;
+	}
+	return rtStatus;
+
+}
+
+bool rtl8192_phy_checkBBAndRF(
+	struct net_device* dev,
+	HW90_BLOCK_E		CheckBlock,
+	RF90_RADIO_PATH_E	eRFPath
+	)
+{
+	bool rtStatus = true;
+	u32				i, CheckTimes = 4,ulRegRead = 0;
+	u32				WriteAddr[4];
+	u32				WriteData[] = {0xfffff027, 0xaa55a02f, 0x00000027, 0x55aa502f};
+
+	WriteAddr[HW90_BLOCK_MAC] = 0x100;
+	WriteAddr[HW90_BLOCK_PHY0] = 0x900;
+	WriteAddr[HW90_BLOCK_PHY1] = 0x800;
+	WriteAddr[HW90_BLOCK_RF] = 0x3;
+	
+	for(i=0 ; i < CheckTimes ; i++)
+	{
+
+		switch(CheckBlock)
+		{
+		case HW90_BLOCK_MAC:
+			RT_TRACE(COMP_INIT, "PHY_CheckBBRFOK(): Never Write 0x100 here!\n");
+			break;
+			
+		case HW90_BLOCK_PHY0:
+		case HW90_BLOCK_PHY1:
+			write_nic_dword(dev, WriteAddr[CheckBlock], WriteData[i]);
+			ulRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]);
+			break;
+
+		case HW90_BLOCK_RF:
+			WriteData[i] &= 0xfff;
+			rtl8192_phy_SetRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask20Bits, WriteData[i]);
+			mdelay(10);
+			ulRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMaskDWord);				
+			mdelay(10);
+			break;
+			
+		default:
+			rtStatus = false;
+			break;
+		}
+
+
+		if(ulRegRead != WriteData[i])
+		{
+			RT_TRACE(COMP_ERR, "read back error(read:%x, write:%x)\n", ulRegRead, WriteData[i]);
+			rtStatus = false;			
+			break;
+		}
+	}
+
+	return rtStatus;
+}
+
+#ifdef TO_DO_LIST
+void
+PHY_SetRFPowerState8192SUsb(
+	struct net_device* dev,
+	RF_POWER_STATE	RFPowerState
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool			WaitShutDown = false;
+	u32			DWordContent;
+	u8				eRFPath;
+	BB_REGISTER_DEFINITION_T	*pPhyReg;
+	
+	if(priv->SetRFPowerStateInProgress == true)
+		return;
+	
+	priv->SetRFPowerStateInProgress = true;
+	
+
+	if(RFPowerState==RF_SHUT_DOWN)
+	{
+		RFPowerState=RF_OFF;
+		WaitShutDown=true;
+	}
+	
+	
+	priv->RFPowerState = RFPowerState;
+	switch( priv->rf_chip )
+	{
+	case RF_8225:
+	case RF_6052:
+		switch( RFPowerState )
+		{
+		case RF_ON:
+			break;
+	
+		case RF_SLEEP:
+			break;
+	
+		case RF_OFF:
+			break;
+		}
+		break;
+
+	case RF_8256:
+		switch( RFPowerState )
+		{
+		case RF_ON:
+			break;
+	
+		case RF_SLEEP:
+			break;
+	
+		case RF_OFF:
+			for(eRFPath=(RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath < RF90_PATH_MAX; eRFPath++)
+			{
+				if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))		
+					continue;	
+				
+				pPhyReg = &priv->PHYRegDef[eRFPath];
+				rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, bRFSI_RFENV);
+				rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0);
+			}
+			break;
+		}
+		break;
+		
+	case RF_8258:
+		break;
+	}
+
+	priv->SetRFPowerStateInProgress = false;
+}
+#endif
+
+void PHY_GetHWRegOriginalValue(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+#if 0
+	priv->MCSTxPowerLevelOriginalOffset[0] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Rate18_06, bMaskDWord);
+	priv->MCSTxPowerLevelOriginalOffset[1] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Rate54_24, bMaskDWord);
+	priv->MCSTxPowerLevelOriginalOffset[2] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Mcs03_Mcs00, bMaskDWord);
+	priv->MCSTxPowerLevelOriginalOffset[3] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Mcs07_Mcs04, bMaskDWord);
+	priv->MCSTxPowerLevelOriginalOffset[4] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Mcs11_Mcs08, bMaskDWord);
+	priv->MCSTxPowerLevelOriginalOffset[5] =
+		rtl8192_QueryBBReg(dev, rTxAGC_Mcs15_Mcs12, bMaskDWord);
+
+	priv->CCKTxPowerLevelOriginalOffset=
+		rtl8192_QueryBBReg(dev, rTxAGC_CCK_Mcs32, bMaskDWord);
+	RT_TRACE(COMP_INIT, "Legacy OFDM =%08x/%08x HT_OFDM=%08x/%08x/%08x/%08x\n", 
+	priv->MCSTxPowerLevelOriginalOffset[0], priv->MCSTxPowerLevelOriginalOffset[1] ,
+	priv->MCSTxPowerLevelOriginalOffset[2], priv->MCSTxPowerLevelOriginalOffset[3] ,
+	priv->MCSTxPowerLevelOriginalOffset[4], priv->MCSTxPowerLevelOriginalOffset[5] );
+#endif
+
+	priv->DefaultInitialGain[0] = rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bMaskByte0);
+	priv->DefaultInitialGain[1] = rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bMaskByte0);
+	priv->DefaultInitialGain[2] = rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bMaskByte0);
+	priv->DefaultInitialGain[3] = rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bMaskByte0);
+	RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x) \n", 
+			priv->DefaultInitialGain[0], priv->DefaultInitialGain[1], 
+			priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
+
+	priv->framesync = rtl8192_QueryBBReg(dev, rOFDM0_RxDetector3, bMaskByte0);
+	priv->framesyncC34 = rtl8192_QueryBBReg(dev, rOFDM0_RxDetector2, bMaskDWord);
+	RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x \n", 
+				rOFDM0_RxDetector3, priv->framesync);
+
+}
+
+
+
+static void phy_InitBBRFRegisterDefinition(	struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; 
+	priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; 
+	priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;
+	priv->PHYRegDef[RF90_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;
+
+	priv->PHYRegDef[RF90_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; 
+	priv->PHYRegDef[RF90_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;
+	priv->PHYRegDef[RF90_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;
+	priv->PHYRegDef[RF90_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;
+
+	priv->PHYRegDef[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; 
+	priv->PHYRegDef[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; 
+	priv->PHYRegDef[RF90_PATH_C].rfintfo = rFPGA0_XC_RFInterfaceOE;
+	priv->PHYRegDef[RF90_PATH_D].rfintfo = rFPGA0_XD_RFInterfaceOE;
+
+	priv->PHYRegDef[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; 
+	priv->PHYRegDef[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; 
+	priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE;
+	priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE;
+
+	priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; 
+	priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
+	priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter;
+	priv->PHYRegDef[RF90_PATH_D].rf3wireOffset = rFPGA0_XD_LSSIParameter;
+
+	priv->PHYRegDef[RF90_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter;  
+	priv->PHYRegDef[RF90_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
+	priv->PHYRegDef[RF90_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+	priv->PHYRegDef[RF90_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+
+	priv->PHYRegDef[RF90_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; 
+	priv->PHYRegDef[RF90_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; 
+	priv->PHYRegDef[RF90_PATH_C].rfTxGainStage = rFPGA0_TxGainStage; 
+	priv->PHYRegDef[RF90_PATH_D].rfTxGainStage = rFPGA0_TxGainStage; 
+
+	priv->PHYRegDef[RF90_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;  
+	priv->PHYRegDef[RF90_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;  
+	priv->PHYRegDef[RF90_PATH_C].rfHSSIPara1 = rFPGA0_XC_HSSIParameter1;  
+	priv->PHYRegDef[RF90_PATH_D].rfHSSIPara1 = rFPGA0_XD_HSSIParameter1;  
+
+	priv->PHYRegDef[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;  
+	priv->PHYRegDef[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;  
+	priv->PHYRegDef[RF90_PATH_C].rfHSSIPara2 = rFPGA0_XC_HSSIParameter2;  
+	priv->PHYRegDef[RF90_PATH_D].rfHSSIPara2 = rFPGA0_XD_HSSIParameter2;  
+
+	priv->PHYRegDef[RF90_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; 
+	priv->PHYRegDef[RF90_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl;
+	priv->PHYRegDef[RF90_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+	priv->PHYRegDef[RF90_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+
+	priv->PHYRegDef[RF90_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
+	priv->PHYRegDef[RF90_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
+	priv->PHYRegDef[RF90_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
+	priv->PHYRegDef[RF90_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
+
+	priv->PHYRegDef[RF90_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
+	priv->PHYRegDef[RF90_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
+	priv->PHYRegDef[RF90_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
+	priv->PHYRegDef[RF90_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
+
+	priv->PHYRegDef[RF90_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;	
+
+	priv->PHYRegDef[RF90_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
+	priv->PHYRegDef[RF90_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
+	priv->PHYRegDef[RF90_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
+	priv->PHYRegDef[RF90_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;	
+
+	priv->PHYRegDef[RF90_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
+	priv->PHYRegDef[RF90_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;	
+
+	priv->PHYRegDef[RF90_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
+	priv->PHYRegDef[RF90_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
+	priv->PHYRegDef[RF90_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
+	priv->PHYRegDef[RF90_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;	
+
+	priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+	priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+	priv->PHYRegDef[RF90_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
+	priv->PHYRegDef[RF90_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;	
+
+	priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+	priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+
+}
+
+
+bool PHY_SetRFPowerState(struct net_device* dev, RT_RF_POWER_STATE eRFPowerState)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool			bResult = false;
+
+	RT_TRACE((COMP_PS | COMP_RF), "---------> PHY_SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState);
+
+	if(eRFPowerState == priv->rtllib->eRFPowerState)
+	{
+		;
+		return bResult;
+	}
+
+	bResult = phy_SetRFPowerState8192SE(dev, eRFPowerState);
+	
+	RT_TRACE((COMP_PS | COMP_RF), "<--------- PHY_SetRFPowerState(): bResult(%d)\n", bResult);
+
+	return bResult;
+}
+
+static bool phy_SetRFPowerState8192SE(struct net_device* dev,RT_RF_POWER_STATE eRFPowerState)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	bool 	bResult = true;
+	u8		i, QueueID;
+	struct rtl8192_tx_ring  *ring = NULL;
+	priv->SetRFPowerStateInProgress = true;
+	
+	switch(priv->rf_chip )
+	{
+		default:	
+		switch( eRFPowerState )
+		{
+			case eRfOn:
+                                RT_TRACE(COMP_PS,"========>%s():eRfOn\n", __func__);
+				{
+									if((priv->rtllib->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+					{ 
+						bool rtstatus = true;
+						u32 InitializeCount = 0;
+						do
+						{	
+							InitializeCount++;
+							rtstatus = NicIFEnableNIC(dev);
+						}while( (rtstatus != true) &&(InitializeCount < 10) );
+						if(rtstatus != true)
+						{
+							RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__);
+							priv->SetRFPowerStateInProgress = false;
+							return false;
+						}
+						RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+					}
+					else
+					{ 
+						write_nic_word(dev, CMDR, 0x37FC);
+						write_nic_byte(dev, TXPAUSE, 0x00);
+						write_nic_byte(dev, PHY_CCA, 0x3);
+					}
+
+#if 1
+					if(priv->rtllib->state == RTLLIB_LINKED)
+					{
+						LedControl8192SE(dev, LED_CTL_LINK); 
+					}
+					else
+					{
+						LedControl8192SE(dev, LED_CTL_NO_LINK); 
+					}
+#endif
+				}
+				break;
+			case eRfOff:  
+                                RT_TRACE(COMP_PS,"========>%s():eRfOff\n", __func__);
+				{					
+					for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+					{
+						ring = &priv->tx_ring[QueueID];
+						if(skb_queue_len(&ring->queue) == 0)
+						{
+							QueueID++;
+							continue;
+						}
+					#ifdef TO_DO_LIST
+					#if( DEV_BUS_TYPE==PCI_INTERFACE)
+						else if(IsLowPowerState(Adapter))
+						{
+							RT_TRACE(COMP_PS, DBG_LOUD, 
+							("eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", (i+1), QueueID));
+							break;
+						}
+					#endif
+					#endif
+						else
+						{
+							RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+							udelay(10);
+							i++;
+						}
+						
+						if(i >= MAX_DOZE_WAITING_TIMES_9x)
+						{
+							RT_TRACE(COMP_PS, "\n\n\n %s(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", __FUNCTION__,MAX_DOZE_WAITING_TIMES_9x, QueueID);
+							break;
+						}
+					}
+
+					if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+					{ 
+						NicIFDisableNIC(dev);
+						RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+						if(priv->pwrdown && priv->rtllib->RfOffReason>= RF_CHANGE_BY_HW)
+							write_nic_byte(dev,0x03,0x31);
+					}
+					else  if(!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
+					{ 
+						SET_RTL8192SE_RF_SLEEP(dev);
+
+#if 1
+						if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS )
+						{
+							LedControl8192SE(dev,LED_CTL_NO_LINK); 
+						}
+						else
+						{
+							LedControl8192SE(dev, LED_CTL_POWER_OFF); 
+						}
+#endif
+					}
+				}
+				break;
+
+			case eRfSleep:
+                                RT_TRACE(COMP_PS,"========>%s():eRfSleep\n", __func__);
+				{
+					if(priv->rtllib->eRFPowerState == eRfOff)
+						break;
+					
+					for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+					{
+						ring = &priv->tx_ring[QueueID];
+						if(skb_queue_len(&ring->queue) == 0)
+						{
+							QueueID++;
+							continue;
+						}
+						#ifdef TO_DO_LIST
+						#if( DEV_BUS_TYPE==PCI_INTERFACE)
+							else if(IsLowPowerState(Adapter))
+							{
+								RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", (i+1), QueueID);
+								break;
+							}
+						#endif
+						#endif
+						else
+						{
+							RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+							udelay(10);
+							i++;
+						}
+						
+						if(i >= MAX_DOZE_WAITING_TIMES_9x)
+						{
+							RT_TRACE(COMP_PS, "\n\n\n %s(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", __FUNCTION__,MAX_DOZE_WAITING_TIMES_9x, QueueID);
+							break;
+						}
+					}		
+
+					SET_RTL8192SE_RF_SLEEP(dev);
+				}
+				break;
+
+			default:
+				bResult = false;
+				RT_TRACE(COMP_ERR, "phy_SetRFPowerState8192S(): unknow state to set: 0x%X!!!\n", eRFPowerState);
+				break;
+		} 
+		break;
+	}
+
+	if(bResult)
+	{
+		priv->rtllib->eRFPowerState = eRFPowerState;
+	}
+	
+	priv->SetRFPowerStateInProgress = false;
+
+	return bResult;
+}
+
+
+void
+PHY_SwitchEphyParameter(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	write_nic_dword(dev, 0x540, 0x73c11);
+	write_nic_dword(dev, 0x548, 0x2407c);
+	
+	write_nic_word(dev, 0x550, 0x1000);
+	write_nic_byte(dev, 0x554, 0x20);	
+	phy_CheckEphySwitchReady(dev);
+
+	write_nic_word(dev, 0x550, 0xa0eb);
+	write_nic_byte(dev, 0x554, 0x3e);
+	phy_CheckEphySwitchReady(dev);
+	
+	write_nic_word(dev, 0x550, 0xff80);
+	write_nic_byte(dev, 0x554, 0x39);
+	phy_CheckEphySwitchReady(dev);
+
+	if (priv->pci_bridge_vendor & (PCI_BRIDGE_VENDOR_INTEL | PCI_BRIDGE_VENDOR_SIS))
+		write_nic_byte(dev, 0x560, 0x40);
+	else
+		write_nic_byte(dev, 0x560, 0x00);
+	
+}	
+
+
+ void
+PHY_GetTxPowerLevel8192S(
+	struct net_device* dev,
+	 long*    		powerlevel
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8			TxPwrLevel = 0;
+	long			TxPwrDbm;
+
+	TxPwrLevel = priv->CurrentCckTxPwrIdx;
+	TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_B, TxPwrLevel);
+
+	TxPwrLevel = priv->CurrentOfdm24GTxPwrIdx + priv->LegacyHTTxPowerDiff;
+
+	if(phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_G, TxPwrLevel) > TxPwrDbm)
+		TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_G, TxPwrLevel);
+	TxPwrLevel = priv->CurrentOfdm24GTxPwrIdx;
+
+	if(phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_N_24G, TxPwrLevel) > TxPwrDbm)
+		TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_N_24G, TxPwrLevel);
+	*powerlevel = TxPwrDbm;
+}
+
+#if 1
+void getTxPowerIndex(
+	struct net_device* 	dev,
+	u8				channel,
+	u8*				cckPowerLevel,
+	u8*				ofdmPowerLevel
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8				index = (channel -1);
+	cckPowerLevel[0] = priv->RfTxPwrLevelCck[0][index];	
+	cckPowerLevel[1] = priv->RfTxPwrLevelCck[1][index];	
+
+	if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R)
+	{
+		ofdmPowerLevel[0] = priv->RfTxPwrLevelOfdm1T[0][index];
+		ofdmPowerLevel[1] = priv->RfTxPwrLevelOfdm1T[1][index];
+	}
+	else if (priv->rf_type == RF_2T2R)
+	{
+		ofdmPowerLevel[0] = priv->RfTxPwrLevelOfdm2T[0][index];
+		ofdmPowerLevel[1] = priv->RfTxPwrLevelOfdm2T[1][index];
+	}
+	RT_TRACE(COMP_POWER,"Channel-%d, set tx power index !!\n", channel);
+}
+
+void ccxPowerIndexCheck(
+	struct net_device* 	dev,
+	u8				channel,
+	u8*				cckPowerLevel,
+	u8*				ofdmPowerLevel
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+#ifdef TODO 
+	if(	priv->rtllib->iw_mode != IW_MODE_INFRA && priv->bWithCcxCellPwr &&
+		channel == priv->rtllib->current_network.channel)
+	{
+		u8	CckCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, priv->CcxCellPwr);
+		u8	LegacyOfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_G, priv->CcxCellPwr);
+		u8	OfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, priv->CcxCellPwr);
+
+		RT_TRACE(COMP_TXAGC,  
+		"CCX Cell Limit: %d dbm => CCK Tx power index : %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", 
+		priv->CcxCellPwr, CckCellPwrIdx, LegacyOfdmCellPwrIdx, OfdmCellPwrIdx);
+		RT_TRACE(COMP_TXAGC, 
+		"EEPROM channel(%d) => CCK Tx power index: %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n",
+		channel, cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]); 
+
+		if(cckPowerLevel[0] > CckCellPwrIdx)
+			cckPowerLevel[0] = CckCellPwrIdx;
+		if(ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff > LegacyOfdmCellPwrIdx)
+		{
+			if((OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff) > 0)
+			{
+				ofdmPowerLevel[0] = OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff;
+			}
+			else
+			{
+				ofdmPowerLevel[0] = 0;
+			}
+		}
+
+		RT_TRACE(COMP_TXAGC,  
+		"Altered CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", 
+		cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]);
+	}
+
+#endif
+	priv->CurrentCckTxPwrIdx = cckPowerLevel[0];
+	priv->CurrentOfdm24GTxPwrIdx = ofdmPowerLevel[0];
+
+	RT_TRACE(COMP_TXAGC,  
+		"PHY_SetTxPowerLevel8192S(): CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", 
+		cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]);
+
+}
+/*-----------------------------------------------------------------------------
+ * Function:    SetTxPowerLevel8190()
+ *
+ * Overview:    This function is export to "HalCommon" moudule
+ *			We must consider RF path later!!!!!!!
+ *
+ * Input:       PADAPTER		Adapter
+ *			u1Byte		channel
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *	2008/11/04	MHC		We remove EEPROM_93C56.
+ *						We need to move CCX relative code to independet file.
+ *	2009/01/21	MHC		Support new EEPROM format from SD3 requirement.
+ *
+ *---------------------------------------------------------------------------*/
+void rtl8192_phy_setTxPower(struct net_device* dev, u8	channel)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	cckPowerLevel[2], ofdmPowerLevel[2];	
+
+	if(priv->bTXPowerDataReadFromEEPORM == false)
+		return;
+	getTxPowerIndex(dev, channel, &cckPowerLevel[0], &ofdmPowerLevel[0]);
+	RT_TRACE(COMP_POWER, "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x,   ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", 
+		channel, cckPowerLevel[0], cckPowerLevel[1], ofdmPowerLevel[0], ofdmPowerLevel[1]);
+
+	ccxPowerIndexCheck(dev, channel, &cckPowerLevel[0], &ofdmPowerLevel[0]);
+
+	switch(priv->rf_chip)
+	{
+		case RF_8225:
+		break;
+
+		case RF_8256:
+			;
+			break;
+
+		case RF_6052:
+			PHY_RF6052SetCckTxPower(dev, cckPowerLevel[0]);
+			PHY_RF6052SetOFDMTxPower(dev, &ofdmPowerLevel[0], channel);
+			break;
+
+		case RF_8258:
+			break;
+		default:
+            		break;
+	}
+}
+#else
+void rtl8192_phy_setTxPower(struct net_device* dev, u8	channel)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	powerlevel = (u8)EEPROM_Default_TxPower, powerlevelOFDM24G = 0x10;
+	s8 ant_pwr_diff = 0;
+	u32	u4RegValue;
+	u8	index = (channel -1);
+	u8	pwrdiff[2] = {0};
+	u8	ht20pwr[2] = {0}, ht40pwr[2] = {0};
+	u8	rfpath = 0, rfpathnum = 2;
+
+	if(priv->bTXPowerDataReadFromEEPORM == false)
+		return;
+
+
+	powerlevel = priv->RfTxPwrLevelCck[0][index];
+		
+	if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R)
+	{
+		powerlevelOFDM24G = priv->RfTxPwrLevelOfdm1T[0][index];
+		
+		
+		rfpathnum = 1;
+		ht20pwr[0] = ht40pwr[0] = priv->RfTxPwrLevelOfdm1T[0][index];
+	}
+	else if (priv->rf_type == RF_2T2R)
+	{
+		powerlevelOFDM24G = priv->RfTxPwrLevelOfdm2T[0][index];
+		ant_pwr_diff = 	priv->RfTxPwrLevelOfdm2T[1][index] - 
+						priv->RfTxPwrLevelOfdm2T[0][index];
+	
+		RT_TRACE(COMP_POWER, "CH-%d HT40 A/B Pwr index = %x/%x(%d/%d)\n", 
+			channel, priv->RfTxPwrLevelOfdm2T[0][index], 
+			priv->RfTxPwrLevelOfdm2T[1][index],
+			priv->RfTxPwrLevelOfdm2T[0][index],
+			priv->RfTxPwrLevelOfdm2T[1][index]);	
+
+		ht20pwr[0] = ht40pwr[0] = priv->RfTxPwrLevelOfdm2T[0][index];
+		ht20pwr[1] = ht40pwr[1] = priv->RfTxPwrLevelOfdm2T[1][index];
+	}
+	RT_TRACE(COMP_POWER, "Channel-%d, set tx power index\n", channel);
+				
+	if (priv->eeprom_version >= 2)	
+	{		
+		if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+		{
+			for (rfpath = 0; rfpath < rfpathnum; rfpath++)
+			{
+				pwrdiff[rfpath] = priv->TxPwrHt20Diff[rfpath][index];
+
+				if (pwrdiff[rfpath] < 8)	
+				{
+					ht20pwr[rfpath] += pwrdiff[rfpath];
+				}
+				else				
+				{
+					ht20pwr[rfpath] -= (16-pwrdiff[rfpath]);
+				}
+			}
+
+			if (priv->rf_type == RF_2T2R)
+				ant_pwr_diff = ht20pwr[1] - ht20pwr[0];
+
+			RT_TRACE(COMP_POWER, "HT20 to HT40 pwrdiff[A/B]=%d/%d, ant_pwr_diff=%d(B-A=%d-%d)\n", 
+				pwrdiff[0], pwrdiff[1], ant_pwr_diff, ht20pwr[1], ht20pwr[0]);	
+		}
+	}
+				
+	if(ant_pwr_diff > 7)
+		ant_pwr_diff = 7;
+	if(ant_pwr_diff < -8)
+		ant_pwr_diff = -8;
+				
+	RT_TRACE(COMP_POWER, "CCK/HT Power index = %x/%x(%d/%d), ant_pwr_diff=%d\n", 
+		powerlevel, powerlevelOFDM24G, powerlevel, powerlevelOFDM24G, ant_pwr_diff);
+		
+	ant_pwr_diff &= 0xf;	
+
+	priv->AntennaTxPwDiff[2] = 0;
+	priv->AntennaTxPwDiff[1] = 0;
+	priv->AntennaTxPwDiff[0] = (u8)(ant_pwr_diff);		
+	RT_TRACE(COMP_POWER, "pHalData->AntennaTxPwDiff[0]/[1]/[2] = 0x%x/0x%x/0x%x\n", 
+		priv->AntennaTxPwDiff[0], priv->AntennaTxPwDiff[1], priv->AntennaTxPwDiff[2]);
+	u4RegValue = (	priv->AntennaTxPwDiff[2]<<8 | 
+					priv->AntennaTxPwDiff[1]<<4 | 
+					priv->AntennaTxPwDiff[0]	);
+	RT_TRACE(COMP_POWER, "BCD-Diff=0x%x\n", u4RegValue);
+
+	rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+		
+#ifdef TODO 
+	if(	priv->rtllib->iw_mode != IW_MODE_INFRA && priv->bWithCcxCellPwr &&
+		channel == priv->rtllib->current_network.channel)
+	{
+		u8	CckCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, priv->CcxCellPwr);
+		u8	LegacyOfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_G, priv->CcxCellPwr);
+		u8	OfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, priv->CcxCellPwr);
+
+		RT_TRACE(COMP_TXAGC,  
+		("CCX Cell Limit: %d dbm => CCK Tx power index : %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", 
+		priv->CcxCellPwr, CckCellPwrIdx, LegacyOfdmCellPwrIdx, OfdmCellPwrIdx));
+		RT_TRACE(COMP_TXAGC,  
+		("EEPROM channel(%d) => CCK Tx power index: %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n",
+		channel, powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G)); 
+
+		if(powerlevel > CckCellPwrIdx)
+			powerlevel = CckCellPwrIdx;
+		if(powerlevelOFDM24G + priv->LegacyHTTxPowerDiff > LegacyOfdmCellPwrIdx)
+		{
+			if((OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff) > 0)
+			{
+				powerlevelOFDM24G = OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff;
+			}
+			else
+			{
+				powerlevelOFDM24G = 0;
+			}
+		}
+
+		RT_TRACE(COMP_TXAGC, 
+		("Altered CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", 
+		powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G));
+	}
+#endif
+	priv->CurrentCckTxPwrIdx = powerlevel;
+	priv->CurrentOfdm24GTxPwrIdx = powerlevelOFDM24G;
+
+	RT_TRACE(COMP_POWER, "PHY_SetTxPowerLevel8192S(): CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", 
+		powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G);
+	
+	switch(priv->rf_chip)
+	{
+		case RF_8225:
+			break;
+
+		case RF_8256:
+			break;
+
+		case RF_6052:
+			PHY_RF6052SetCckTxPower(dev, powerlevel);
+			PHY_RF6052SetOFDMTxPower(dev, powerlevelOFDM24G, channel);
+			break;
+
+		case RF_8258:
+			break;
+		default:
+			break;
+	}	
+
+}
+#endif
+
+bool PHY_UpdateTxPowerDbm8192S(struct net_device* dev, long powerInDbm)
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	u8				idx;
+	u8				rf_path;
+
+	u8	CckTxPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, powerInDbm);
+	u8	OfdmTxPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, powerInDbm);
+
+	if(OfdmTxPwrIdx - priv->LegacyHTTxPowerDiff > 0)
+		OfdmTxPwrIdx -= priv->LegacyHTTxPowerDiff;
+	else
+		OfdmTxPwrIdx = 0;
+
+	RT_TRACE(COMP_POWER, "PHY_UpdateTxPowerDbm8192S(): %ld dBm , CckTxPwrIdx = %d, OfdmTxPwrIdx = %d\n", powerInDbm, CckTxPwrIdx, OfdmTxPwrIdx);
+
+	for(idx = 0; idx < 14; idx++)
+	{
+		priv->TxPowerLevelCCK[idx] = CckTxPwrIdx;
+		priv->TxPowerLevelCCK_A[idx] = CckTxPwrIdx;
+		priv->TxPowerLevelCCK_C[idx] = CckTxPwrIdx;
+		priv->TxPowerLevelOFDM24G[idx] = OfdmTxPwrIdx;
+		priv->TxPowerLevelOFDM24G_A[idx] = OfdmTxPwrIdx;
+		priv->TxPowerLevelOFDM24G_C[idx] = OfdmTxPwrIdx;
+		for (rf_path = 0; rf_path < 2; rf_path++)
+		{
+			priv->RfTxPwrLevelCck[rf_path][idx] = CckTxPwrIdx;
+			priv->RfTxPwrLevelOfdm1T[rf_path][idx] = 
+			priv->RfTxPwrLevelOfdm2T[rf_path][idx] = OfdmTxPwrIdx;
+		}
+	}
+
+	rtl8192_phy_setTxPower(dev, priv->chan);
+
+	return true;	
+}
+
+extern void PHY_SetBeaconHwReg(	struct net_device* dev, u16 BeaconInterval)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32 NewBeaconNum;	
+
+	if(priv->pFirmware->FirmwareVersion >= 0x33) 
+	{
+		write_nic_dword(dev,WFM5,0xF1000000|(BeaconInterval<<8));
+	}
+	else
+	{
+	NewBeaconNum = BeaconInterval *32 - 64;
+	write_nic_dword(dev, WFM3+4, NewBeaconNum);
+	write_nic_dword(dev, WFM3, 0xB026007C);
+}
+}
+
+static u8 phy_DbmToTxPwrIdx(
+	struct net_device* dev, 
+	WIRELESS_MODE	WirelessMode,
+	long			PowerInDbm
+	)
+{
+	u8				TxPwrIdx = 0;
+	long				Offset = 0;
+	
+
+	switch(WirelessMode)
+	{
+	case WIRELESS_MODE_B:
+		Offset = -7;
+		break;
+
+	case WIRELESS_MODE_G:
+		Offset = -8;
+		break;
+
+	case WIRELESS_MODE_N_24G:
+	default:
+		Offset = -8;
+		break;
+	}
+
+	if((PowerInDbm - Offset) > 0)
+	{
+		TxPwrIdx = (u8)((PowerInDbm - Offset) * 2);
+	}
+	else
+	{
+		TxPwrIdx = 0;
+	}
+
+	if(TxPwrIdx > MAX_TXPWR_IDX_NMODE_92S)
+		TxPwrIdx = MAX_TXPWR_IDX_NMODE_92S;
+
+	return TxPwrIdx;
+}
+
+static long phy_TxPwrIdxToDbm(
+	struct net_device* dev,
+	WIRELESS_MODE	WirelessMode,
+	u8			TxPwrIdx
+	)
+{
+	long				Offset = 0;
+	long				PwrOutDbm = 0;
+	
+	switch(WirelessMode)
+	{
+	case WIRELESS_MODE_B:
+		Offset = -7;
+		break;
+
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		Offset = -8;
+		break;
+	default:
+		Offset = -8;
+		break;
+	}
+
+	PwrOutDbm = TxPwrIdx / 2 + Offset; 
+
+	return PwrOutDbm;
+}
+
+#ifdef TO_DO_LIST
+extern	void 
+PHY_ScanOperationBackup8192S(
+	struct net_device* dev,
+	u8 Operation
+	)
+{
+#if(RTL8192S_DISABLE_FW_DM == 0)
+
+	if(!Adapter->bDriverStopped)
+	{
+		switch(Operation)
+		{
+			case SCAN_OPT_BACKUP:
+				Adapter->HalFunc.SetFwCmdHandler(Adapter, FW_CMD_PAUSE_DM_BY_SCAN);
+				break;
+
+			case SCAN_OPT_RESTORE:
+				Adapter->HalFunc.SetFwCmdHandler(Adapter, FW_CMD_RESUME_DM_BY_SCAN);
+				break;
+
+			default:
+				RT_TRACE(COMP_SCAN, DBG_LOUD, ("Unknown Scan Backup Operation. \n"));
+				break;
+		}
+	}
+#endif
+}
+#endif
+void PHY_SetBWModeCallback8192S(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	 			regBwOpMode, regRRSR_RSC;
+
+
+
+	RT_TRACE(COMP_SWBW, "==>SetBWModeCallback8192s()  Switch to %s bandwidth\n", \
+					priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20?"20MHz":"40MHz");
+
+	if(priv->rf_chip == RF_PSEUDO_11N)
+	{
+		priv->SetBWModeInProgress= false;
+		return;
+	}
+	if(IS_NIC_DOWN(priv)){
+		priv->SwChnlInProgress = priv->SetBWModeInProgress = false;
+		return;
+	}
+		
+	regBwOpMode = read_nic_byte(dev, BW_OPMODE);
+	regRRSR_RSC = read_nic_byte(dev, RRSR+2);
+	
+	switch(priv->CurrentChannelBW)
+	{
+		case HT_CHANNEL_WIDTH_20:
+			regBwOpMode |= BW_OPMODE_20MHZ;
+			write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+			break;
+			   
+		case HT_CHANNEL_WIDTH_20_40:
+			regBwOpMode &= ~BW_OPMODE_20MHZ;
+			write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+
+			break;
+
+		default:
+			RT_TRACE(COMP_DBG, "SetBWModeCallback8192s():\
+						unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+			break;
+	}
+	
+	switch(priv->CurrentChannelBW)
+	{
+		case HT_CHANNEL_WIDTH_20:
+			rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
+			rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
+
+			if(priv->card_8192_version >= VERSION_8192S_BCUT)
+				write_nic_byte(dev, rFPGA0_AnalogParameter2, 0x58);
+			break;
+
+		case HT_CHANNEL_WIDTH_20_40:
+			rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
+			rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
+			
+
+			rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
+			rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);			
+			
+			if(priv->card_8192_version >= VERSION_8192S_BCUT)
+				write_nic_byte(dev, rFPGA0_AnalogParameter2, 0x18);
+			break;
+			
+		default:
+			RT_TRACE(COMP_DBG, "SetBWModeCallback8192s(): unknown Bandwidth: %#X\n"\
+						,priv->CurrentChannelBW);
+			break;
+			
+	}
+
+
+	switch( priv->rf_chip )
+	{
+		case RF_8225:		
+			break;	
+			
+		case RF_8256:
+			break;
+			
+		case RF_8258:
+			break;
+
+		case RF_PSEUDO_11N:
+			break;
+
+		case RF_6052:
+			PHY_RF6052SetBandwidth(dev, priv->CurrentChannelBW);
+			break;
+		default:
+			printk("Unknown rf_chip: %d\n", priv->rf_chip);
+			break;
+	}
+
+	priv->SetBWModeInProgress= false;
+
+	RT_TRACE(COMP_SWBW, "<==SetBWModeCallback8192s() \n" );
+}
+
+
+void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH	Bandwidth, HT_EXTCHNL_OFFSET Offset)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+
+	
+
+
+	if(priv->SetBWModeInProgress)
+		return;
+
+	priv->SetBWModeInProgress= true;
+	
+	priv->CurrentChannelBW = Bandwidth;
+	
+	if(Offset==HT_EXTCHNL_OFFSET_LOWER)
+		priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_UPPER;
+	else if(Offset==HT_EXTCHNL_OFFSET_UPPER)
+		priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_LOWER;
+	else
+		priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+#if 0
+	if(!priv->bDriverStopped)
+	{
+#ifdef USE_WORKITEM	
+		PlatformScheduleWorkItem(&(priv->SetBWModeWorkItem));
+#else
+		PlatformSetTimer(dev, &(priv->SetBWModeTimer), 0);
+#endif		
+	}
+#endif
+	if(!IS_NIC_DOWN(priv)){
+		PHY_SetBWModeCallback8192S(dev);
+	} else {
+		priv->SetBWModeInProgress= false;
+	}
+}
+
+void PHY_SwChnlCallback8192S(struct net_device *dev)
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32		delay;
+	
+	RT_TRACE(COMP_CH, "==>SwChnlCallback8190Pci(), switch to channel %d\n", priv->chan);
+	
+	if(IS_NIC_DOWN(priv))
+	{	
+		printk("%s: driver is not up\n", __FUNCTION__);
+		priv->SwChnlInProgress = priv->SetBWModeInProgress = false;
+		return;
+	}	
+	if(priv->rf_chip == RF_PSEUDO_11N)
+	{
+		printk("%s: rt chip is RF_PSEUDO_11N\n", __FUNCTION__);
+		priv->SwChnlInProgress=false;
+		return; 								
+	}
+	
+	do{
+		if(!priv->SwChnlInProgress)
+			break;
+
+		if(!phy_SwChnlStepByStep(dev, priv->chan, &priv->SwChnlStage, &priv->SwChnlStep, &delay))
+		{
+			if(delay>0)
+			{
+				mdelay(delay);
+			}
+			else
+			continue;
+		}
+		else
+		{
+			priv->SwChnlInProgress=false;
+			break;
+		}
+	}while(true);
+}
+
+u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(IS_NIC_DOWN(priv))
+	{
+		printk("%s: driver is not up.\n",__FUNCTION__);
+		priv->SwChnlInProgress = priv->SetBWModeInProgress = false;
+		return false;
+	}	
+	if(priv->SwChnlInProgress){
+		printk("%s: SwChnl is in progress\n",__FUNCTION__);
+		return false;
+	}
+
+	if(priv->SetBWModeInProgress){
+		printk("%s: Set BWMode is in progress\n",__FUNCTION__);
+		return false;
+	}
+	if (0)
+	{
+		u8 path;
+		for(path=0; path<2; path++){
+		printk("============>to set channel:%x\n", rtl8192_phy_QueryRFReg(dev, path, 0x18, 0x3ff));
+		udelay(10);
+		}
+	}
+	switch(priv->rtllib->mode)
+	{
+	case WIRELESS_MODE_A:
+	case WIRELESS_MODE_N_5G:
+		if (channel<=14){
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14");
+			return false;
+		}
+		break;
+		
+	case WIRELESS_MODE_B:
+		if (channel>14){
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14");
+			return false;
+		}
+		break;
+		
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		if (channel>14){
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14");
+			return false;
+		}
+		break;
+
+	default:
+		break;
+	}
+	
+	priv->SwChnlInProgress = true;
+	if( channel == 0)
+		channel = 1;
+	
+	priv->chan=channel;
+
+	priv->SwChnlStage=0;
+	priv->SwChnlStep=0;
+
+#if 0
+	if(!dev->bDriverStopped)
+	{
+#ifdef USE_WORKITEM	
+		PlatformScheduleWorkItem(&(priv->SwChnlWorkItem));
+#else
+		PlatformSetTimer(dev, &(priv->SwChnlTimer), 0);
+#endif
+	}
+#endif
+
+	if(!IS_NIC_DOWN(priv)){
+		PHY_SwChnlCallback8192S(dev);
+	} else {
+		priv->SwChnlInProgress = false;
+	}
+	return true;	
+}
+
+
+void PHY_SwChnlPhy8192S(	
+	struct net_device* dev,
+	u8		channel
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	RT_TRACE(COMP_SCAN, "==>PHY_SwChnlPhy8192S(), switch to channel %d.\n", priv->chan);
+
+#ifdef TO_DO_LIST
+	if(RT_CANNOT_IO(dev))
+		return;
+#endif
+
+	if(priv->SwChnlInProgress)
+		return;
+	
+	if(priv->rf_chip == RF_PSEUDO_11N)
+	{
+		priv->SwChnlInProgress=false;
+		return;
+	}
+	
+	priv->SwChnlInProgress = true;
+	if( channel == 0)
+		channel = 1;
+	
+	priv->chan=channel;
+	
+	priv->SwChnlStage = 0;
+	priv->SwChnlStep = 0;
+	
+	phy_FinishSwChnlNow(dev,channel);
+	
+	priv->SwChnlInProgress = false;
+}
+
+static bool
+phy_SwChnlStepByStep(
+	struct net_device* dev,
+	u8		channel,
+	u8		*stage,
+	u8		*step,
+	u32		*delay
+	)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	SwChnlCmd				PreCommonCmd[MAX_PRECMD_CNT];
+	u32					PreCommonCmdCnt;
+	SwChnlCmd				PostCommonCmd[MAX_POSTCMD_CNT];
+	u32					PostCommonCmdCnt;
+	SwChnlCmd				RfDependCmd[MAX_RFDEPENDCMD_CNT];
+	u32					RfDependCmdCnt;
+	SwChnlCmd				*CurrentCmd = NULL;	
+	u8					eRFPath;	
+	u16					u2Channel = 0;
+	
+	RT_TRACE(COMP_CH, "===========>%s(), channel:%d, stage:%d, step:%d\n", __FUNCTION__, channel, *stage, *step);		
+	if (!IsLegalChannel(priv->rtllib, channel))
+	{
+		RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n", channel);
+		return true; 
+	}		
+
+	
+	PreCommonCmdCnt = 0;
+	phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, 
+				CmdID_SetTxPowerLevel, 0, 0, 0);
+	phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, 
+				CmdID_End, 0, 0, 0);
+	
+	PostCommonCmdCnt = 0;
+
+	phy_SetSwChnlCmdArray(PostCommonCmd, PostCommonCmdCnt++, MAX_POSTCMD_CNT, 
+				CmdID_End, 0, 0, 0);
+	
+	RfDependCmdCnt = 0;
+	switch( priv->rf_chip )
+	{
+		case RF_8225:		
+		if (channel < 1 || channel > 14)
+			RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel);
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+			CmdID_RF_WriteReg, rRfChannel, channel, 10);
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+		CmdID_End, 0, 0, 0);
+		break;	
+		
+	case RF_8256:
+		if (channel < 1 || channel > 14)
+			RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel);
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+			CmdID_RF_WriteReg, rRfChannel, channel, 10);
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+		CmdID_End, 0, 0, 0);
+		break;
+		
+	case RF_6052:
+		if (channel < 1 || channel > 14)
+			RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel);
+		
+		u2Channel = channel;
+		
+		switch(priv->CurrentChannelBW)
+		{
+		case HT_CHANNEL_WIDTH_20:
+			u2Channel |= BIT10;
+			break;
+			
+		case HT_CHANNEL_WIDTH_20_40:
+			u2Channel &= ~BIT10;
+			break;
+		default:
+			u2Channel |= BIT10; 
+			break;
+		}	
+		u2Channel |= BIT12|BIT13|BIT14;
+		
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+			CmdID_RF_WriteReg, RF_CHNLBW, u2Channel, 10);
+		phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, 
+			CmdID_End, 0, 0, 0);		
+		break;
+
+	case RF_8258:
+		break;
+		
+	default:
+		return false;
+		break;
+	}
+
+	
+	do{
+		switch(*stage)
+		{
+		case 0:
+			CurrentCmd=&PreCommonCmd[*step];
+			break;
+		case 1:
+			CurrentCmd=&RfDependCmd[*step];
+			break;
+		case 2:
+			CurrentCmd=&PostCommonCmd[*step];
+			break;
+		}
+		
+		if(CurrentCmd->CmdID==CmdID_End)
+		{
+			if((*stage)==2)
+			{
+				return true;
+			}
+			else
+			{
+				(*stage)++;
+				(*step)=0;
+				continue;
+			}
+		}
+		
+		switch(CurrentCmd->CmdID)
+		{
+		case CmdID_SetTxPowerLevel:
+#ifndef CONFIG_MP
+				rtl8192_phy_setTxPower(dev,channel);
+#endif
+			break;
+		case CmdID_WritePortUlong:
+			write_nic_dword(dev, CurrentCmd->Para1, CurrentCmd->Para2);
+			break;
+		case CmdID_WritePortUshort:
+			write_nic_word(dev, CurrentCmd->Para1, (u16)CurrentCmd->Para2);
+			break;
+		case CmdID_WritePortUchar:
+			write_nic_byte(dev, CurrentCmd->Para1, (u8)CurrentCmd->Para2);
+			break;
+		case CmdID_RF_WriteReg:	
+			for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+			{
+				if (IS_HARDWARE_TYPE_8192SE(dev)) {
+#ifdef CONFIG_FW_SETCHAN
+					u32 rf_bw = ((priv->RfRegChnlVal[eRFPath] & 0xfffffc00) | (CurrentCmd->Para2 & 0xFF00));
+#endif
+					priv->RfRegChnlVal[eRFPath] = ((priv->RfRegChnlVal[eRFPath] & 0xfffffc00) | CurrentCmd->Para2);
+
+#ifdef CONFIG_FW_SETCHAN
+					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, rf_bw);				
+#else
+					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, priv->RfRegChnlVal[eRFPath]);				
+#endif
+				} else {
+					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, (CurrentCmd->Para2));
+				}
+			}
+			break;
+                default:
+                        break;
+		}
+		
+		break;
+	}while(true);
+
+	(*delay)=CurrentCmd->msDelay;
+	(*step)++;
+	RT_TRACE(COMP_CH, "<===========%s(), channel:%d, stage:%d, step:%d\n", __FUNCTION__, channel, *stage, *step);		
+	return false;
+}
+
+static bool
+phy_SetSwChnlCmdArray(
+	SwChnlCmd*		CmdTable,
+	u32			CmdTableIdx,
+	u32			CmdTableSz,
+	SwChnlCmdID		CmdID,
+	u32			Para1,
+	u32			Para2,
+	u32			msDelay
+	)
+{
+	SwChnlCmd* pCmd;
+
+	if(CmdTable == NULL)
+	{
+		return false;
+	}
+	if(CmdTableIdx >= CmdTableSz)
+	{
+		return false;
+	}
+
+	pCmd = CmdTable + CmdTableIdx;
+	pCmd->CmdID = CmdID;
+	pCmd->Para1 = Para1;
+	pCmd->Para2 = Para2;
+	pCmd->msDelay = msDelay;
+
+	return true;
+}
+
+static void
+phy_FinishSwChnlNow(	
+	struct net_device* dev,
+	u8		channel
+		)
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	u32			delay;
+  
+	while(!phy_SwChnlStepByStep(dev,channel,&priv->SwChnlStage,&priv->SwChnlStep,&delay))
+	{
+		if(delay>0)
+			mdelay(delay);
+		if(IS_NIC_DOWN(priv))
+			break;
+	}
+}
+
+
+u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath)
+{
+	bool				rtValue = true;
+
+#if 0	
+	if (priv->rf_type == RF_1T2R && eRFPath != RF90_PATH_A)
+	{		
+		rtValue = false;
+	}
+	if (priv->rf_type == RF_1T2R && eRFPath != RF90_PATH_A)
+	{
+
+	}
+#endif
+	return	rtValue;
+
+}	/* PHY_CheckIsLegalRfPath8192S */
+
+
+
+void	
+PHY_IQCalibrate(	struct net_device* dev)
+{
+	u32				i, reg;
+	u32				old_value;
+	long				X, Y, TX0[4];
+	u32				TXA[4];
+	
+
+	for (i = 0; i < 10; i++)
+	{
+		rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05430);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000800e4);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x80800000);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe40, bMaskDWord, 0x02140148);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe44, bMaskDWord, 0x681604a2);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe4c, bMaskDWord, 0x000028d1);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe60, bMaskDWord, 0x0214014d);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe64, bMaskDWord, 0x281608ba);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe6c, bMaskDWord, 0x000028d1);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000001);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000001);
+		udelay(2000);
+		rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05433);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000000e4);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x0);		
+
+	
+		reg = rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord);
+
+		if (!(reg&(BIT27|BIT28|BIT30|BIT31)))
+		{
+			old_value = (rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord) & 0x3FF);
+
+			X = (rtl8192_QueryBBReg(dev, 0xe94, bMaskDWord) & 0x03FF0000)>>16;
+			TXA[RF90_PATH_A] = (X * old_value)/0x100;
+			reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord);
+			reg = (reg & 0xFFFFFC00) | (u32)TXA[RF90_PATH_A];
+			rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg);
+			udelay(5);
+
+			Y = ( rtl8192_QueryBBReg(dev, 0xe9C, bMaskDWord) & 0x03FF0000)>>16;
+			TX0[RF90_PATH_C] = ((Y * old_value)/0x100);
+			reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord);
+			reg = (reg & 0xffc0ffff) |((u32) (TX0[RF90_PATH_C]&0x3F)<<16);			
+			rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg);
+			reg = rtl8192_QueryBBReg(dev, 0xc94, bMaskDWord);		
+			reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28);
+			rtl8192_setBBreg(dev, 0xc94, bMaskDWord, reg);
+			udelay(5);
+
+			reg = rtl8192_QueryBBReg(dev, 0xc14, bMaskDWord);
+			X = (rtl8192_QueryBBReg(dev, 0xea4, bMaskDWord) & 0x03FF0000)>>16;			
+			reg = (reg & 0xFFFFFC00) |X;
+			rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg);
+			Y = (rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord) & 0x003F0000)>>16;
+			reg = (reg & 0xFFFF03FF) |Y<<10;
+			rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg);
+			udelay(5);
+			old_value = (rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord) & 0x3FF);
+			
+			X = (rtl8192_QueryBBReg(dev, 0xeb4, bMaskDWord) & 0x03FF0000)>>16;
+			reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord);
+			TXA[RF90_PATH_A] = (X * old_value) / 0x100;
+			reg = (reg & 0xFFFFFC00) | TXA[RF90_PATH_A];
+			rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg);
+			udelay(5);
+
+			Y = (rtl8192_QueryBBReg(dev, 0xebc, bMaskDWord)& 0x03FF0000)>>16;
+			TX0[RF90_PATH_C] = ((Y * old_value)/0x100);
+			reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord);
+			reg = (reg & 0xffc0ffff) |( (TX0[RF90_PATH_C]&0x3F)<<16);
+			rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg);
+			reg = rtl8192_QueryBBReg(dev, 0xc9c, bMaskDWord);
+			reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28);
+			rtl8192_setBBreg(dev, 0xc9c, bMaskDWord, reg);
+			udelay(5);
+
+			reg = rtl8192_QueryBBReg(dev, 0xc1c, bMaskDWord);
+			X = (rtl8192_QueryBBReg(dev, 0xec4, bMaskDWord) & 0x03FF0000)>>16;			
+			reg = (reg & 0xFFFFFC00) |X;
+			rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg);
+			
+			Y = (rtl8192_QueryBBReg(dev, 0xecc, bMaskDWord) & 0x003F0000)>>16;
+			reg = (reg & 0xFFFF03FF) |Y<<10;
+			rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg);
+			udelay(5);
+			
+			RT_TRACE(COMP_INIT, "PHY_IQCalibrate OK\n");
+			break;
+		}
+
+	}
+	
+	
+
+
+}
+
+extern void PHY_IQCalibrateBcut(struct net_device* dev)
+{
+	u32				i, reg;
+	u32				old_value;
+	long				X, Y, TX0[4];
+	u32				TXA[4];	
+	u32				calibrate_set[13] = {0};
+	u32				load_value[13];
+	u8			RfPiEnable=0;
+	
+	/*
+	0xee0[31:0]=0x3fed92fb;   
+	0xedc[31:0] =0x3fed92fb;   
+	0xe70[31:0] =0x3fed92fb;   
+	0xe74[31:0] =0x3fed92fb;   
+	0xe78[31:0] =0x3fed92fb;   
+	0xe7c[31:0]= 0x3fed92fb;   
+	0xe80[31:0]= 0x3fed92fb;   
+	0xe84[31:0]= 0x3fed92fb; 
+	0xe88[31:0]= 0x3fed92fb;  
+	0xe8c[31:0]= 0x3fed92fb;   
+	0xed0[31:0]= 0x3fed92fb;   
+	0xed4[31:0]= 0x3fed92fb;  
+	0xed8[31:0]= 0x3fed92fb;
+	*/
+	calibrate_set [0] = 0xee0;
+	calibrate_set [1] = 0xedc;
+	calibrate_set [2] = 0xe70;
+	calibrate_set [3] = 0xe74;
+	calibrate_set [4] = 0xe78;
+	calibrate_set [5] = 0xe7c;
+	calibrate_set [6] = 0xe80;
+	calibrate_set [7] = 0xe84;
+	calibrate_set [8] = 0xe88;
+	calibrate_set [9] = 0xe8c;
+	calibrate_set [10] = 0xed0;
+	calibrate_set [11] = 0xed4;
+	calibrate_set [12] = 0xed8;
+	for (i = 0; i < 13; i++)
+	{
+		load_value[i] = rtl8192_QueryBBReg(dev, calibrate_set[i], bMaskDWord);
+		rtl8192_setBBreg(dev, calibrate_set[i], bMaskDWord, 0x3fed92fb);		
+		
+	}
+	
+	RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter1, BIT8);
+	for (i = 0; i < 10; i++)
+	{
+		RT_TRACE(COMP_INIT, "IQK -%d\n", i);	
+		if (!RfPiEnable)	
+		{
+			rtl8192_setBBreg(dev, 0x820, bMaskDWord, 0x01000100);
+			rtl8192_setBBreg(dev, 0x828, bMaskDWord, 0x01000100);
+		}
+	
+		rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05430);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000800e4);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x80800000);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe40, bMaskDWord, 0x02140102);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe44, bMaskDWord, 0x681604c2);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe4c, bMaskDWord, 0x000028d1);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe60, bMaskDWord, 0x02140102);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe64, bMaskDWord, 0x28160d05);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000000);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000000);
+		udelay(5);
+
+		udelay(2000);
+
+		rtl8192_setBBreg(dev, 0xe6c, bMaskDWord, 0x020028d1);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000000);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000000);
+
+		udelay(2000);
+
+		rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05433);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000000e4);
+		udelay(5);
+		rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x0);		
+
+		if (!RfPiEnable)	
+		{
+			rtl8192_setBBreg(dev, 0x820, bMaskDWord, 0x01000000);
+			rtl8192_setBBreg(dev, 0x828, bMaskDWord, 0x01000000);
+		}
+
+	
+		reg = rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord);
+
+		if (!(reg&(BIT27|BIT28|BIT30|BIT31)))
+		{			
+			old_value = (rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord) & 0x3FF);
+
+			X = (rtl8192_QueryBBReg(dev, 0xe94, bMaskDWord) & 0x03FF0000)>>16;
+			TXA[RF90_PATH_A] = (X * old_value)/0x100;
+			reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord);
+			reg = (reg & 0xFFFFFC00) | (u32)TXA[RF90_PATH_A];
+			rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg);
+			udelay(5);
+
+			Y = ( rtl8192_QueryBBReg(dev, 0xe9C, bMaskDWord) & 0x03FF0000)>>16;
+			TX0[RF90_PATH_C] = ((Y * old_value)/0x100);
+			reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord);
+			reg = (reg & 0xffc0ffff) |((u32) (TX0[RF90_PATH_C]&0x3F)<<16);			
+			rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg);
+			reg = rtl8192_QueryBBReg(dev, 0xc94, bMaskDWord);		
+			reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28);
+			rtl8192_setBBreg(dev, 0xc94, bMaskDWord, reg);
+			udelay(5);
+
+			reg = rtl8192_QueryBBReg(dev, 0xc14, bMaskDWord);
+			X = (rtl8192_QueryBBReg(dev, 0xea4, bMaskDWord) & 0x03FF0000)>>16;			
+			reg = (reg & 0xFFFFFC00) |X;
+			rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg);
+			Y = (rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord) & 0x003F0000)>>16;
+			reg = (reg & 0xFFFF03FF) |Y<<10;
+			rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg);
+			udelay(5);
+			old_value = (rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord) & 0x3FF);
+			
+			X = (rtl8192_QueryBBReg(dev, 0xeb4, bMaskDWord) & 0x03FF0000)>>16;
+			reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord);
+			TXA[RF90_PATH_A] = (X * old_value) / 0x100;
+			reg = (reg & 0xFFFFFC00) | TXA[RF90_PATH_A];
+			rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg);
+			udelay(5);
+
+			Y = (rtl8192_QueryBBReg(dev, 0xebc, bMaskDWord)& 0x03FF0000)>>16;
+			TX0[RF90_PATH_C] = ((Y * old_value)/0x100);
+			reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord);
+			reg = (reg & 0xffc0ffff) |( (TX0[RF90_PATH_C]&0x3F)<<16);
+			rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg);
+			reg = rtl8192_QueryBBReg(dev, 0xc9c, bMaskDWord);
+			reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28);
+			rtl8192_setBBreg(dev, 0xc9c, bMaskDWord, reg);
+			udelay(5);
+
+			reg = rtl8192_QueryBBReg(dev, 0xc1c, bMaskDWord);
+			X = (rtl8192_QueryBBReg(dev, 0xec4, bMaskDWord) & 0x03FF0000)>>16;			
+			reg = (reg & 0xFFFFFC00) |X;
+			rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg);
+			
+			Y = (rtl8192_QueryBBReg(dev, 0xecc, bMaskDWord) & 0x003F0000)>>16;
+			reg = (reg & 0xFFFF03FF) |Y<<10;
+			rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg);
+			udelay(5);
+			
+			RT_TRACE(COMP_INIT, "PHY_IQCalibrate OK\n");
+			break;
+		}
+
+	}
+	
+	for (i = 0; i < 13; i++)
+		rtl8192_setBBreg(dev, calibrate_set[i], bMaskDWord, load_value[i]);
+	
+	
+	
+
+
+}	
+
+#define HalGetFirmwareVerison(priv) (priv->pFirmware->FirmwareVersion )
+bool rtl8192se_set_fw_cmd(struct net_device* dev, FW_CMD_IO_TYPE		FwCmdIO)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32	FwParam = FW_CMD_IO_PARA_QUERY(priv);
+	u16	FwCmdMap = FW_CMD_IO_QUERY(priv);
+	bool	bPostProcessing = false;
+
+	RT_TRACE(COMP_CMD, "-->HalSetFwCmd8192S(): Set FW Cmd(%#x), SetFwCmdInProgress(%d)\n", FwCmdIO, priv->SetFwCmdInProgress);
+
+
+
+
+
+	RT_TRACE(COMP_CMD, "-->HalSetFwCmd8192S(): Set FW Cmd(%#x), SetFwCmdInProgress(%d)\n", 
+		FwCmdIO, priv->SetFwCmdInProgress);
+
+	do{
+
+		if(HalGetFirmwareVerison(priv) >= 0x35)
+	{
+			switch(FwCmdIO)
+			{
+				case FW_CMD_RA_REFRESH_N:
+					FwCmdIO = FW_CMD_RA_REFRESH_N_COMB;
+					break;
+				case FW_CMD_RA_REFRESH_BG:
+					FwCmdIO = FW_CMD_RA_REFRESH_BG_COMB;
+					break;
+				default:
+					break;
+			}
+		}
+		else
+		{			
+			if((FwCmdIO == FW_CMD_IQK_ENABLE) ||
+				(FwCmdIO == FW_CMD_RA_REFRESH_N) ||
+				(FwCmdIO == FW_CMD_RA_REFRESH_BG))
+			{
+				bPostProcessing = true;
+				break;
+			}
+	}
+
+		if(HalGetFirmwareVerison(priv) >= 0x3E)
+	{
+			if(FwCmdIO == FW_CMD_CTRL_DM_BY_DRIVER)
+				FwCmdIO = FW_CMD_CTRL_DM_BY_DRIVER_NEW;
+	}
+
+
+		switch(FwCmdIO)
+	{
+
+			case FW_CMD_RA_INIT:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] RA init!!\n");
+				FwCmdMap |= FW_RA_INIT_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);	
+				FW_CMD_IO_CLR(priv, FW_RA_INIT_CTL);	 
+				break;
+
+			case FW_CMD_DIG_DISABLE:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG disable!!\n");
+				FwCmdMap &= ~FW_DIG_ENABLE_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);			
+				break;
+				
+			case FW_CMD_DIG_ENABLE:
+			case FW_CMD_DIG_RESUME:
+				if(!(priv->DMFlag & HAL_DM_DIG_DISABLE))
+				{
+					RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG enable or resume!!\n");
+					FwCmdMap |= (FW_DIG_ENABLE_CTL|FW_SS_CTL);
+					FW_CMD_IO_SET(priv, FwCmdMap);	
+	}
+				break;
+
+			case FW_CMD_DIG_HALT:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG halt!!\n");
+				FwCmdMap &= ~(FW_DIG_ENABLE_CTL|FW_SS_CTL);
+				FW_CMD_IO_SET(priv, FwCmdMap);				
+				break;
+				
+			case FW_CMD_TXPWR_TRACK_THERMAL:
+	{
+					u8	ThermalVal = 0;
+					FwCmdMap |= FW_PWR_TRK_CTL;
+					FwParam &= FW_PWR_TRK_PARAM_CLR; 
+					ThermalVal = priv->ThermalValue;
+					FwParam |= ((ThermalVal<<24) |(priv->ThermalMeter[0]<<16));					
+					RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam);
+					FW_CMD_PARA_SET(priv, FwParam);
+					FW_CMD_IO_SET(priv, FwCmdMap);
+					FW_CMD_IO_CLR(priv, FW_PWR_TRK_CTL);	 
+	}
+				break;
+				
+			case FW_CMD_RA_REFRESH_N_COMB:
+				FwCmdMap |= FW_RA_N_CTL;
+				FwCmdMap &= ~(FW_RA_BG_CTL |FW_RA_INIT_CTL);
+				FwParam &= FW_RA_PARAM_CLR; 
+				if(!(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL))
+					FwParam |= ((priv->rtllib->pHTInfo->IOTRaFunc)&0xf);
+				FwParam |= ((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<4);
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam);
+				FW_CMD_PARA_SET(priv, FwParam);
+				FW_CMD_IO_SET(priv, FwCmdMap);	
+				FW_CMD_IO_CLR(priv, FW_RA_N_CTL); 
+				break;	
+
+			case FW_CMD_RA_REFRESH_BG_COMB:				
+				FwCmdMap |= FW_RA_BG_CTL;
+				FwCmdMap &= ~(FW_RA_N_CTL|FW_RA_INIT_CTL); 
+				FwParam &= FW_RA_PARAM_CLR; 
+				if(!(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL))
+					FwParam |= ((priv->rtllib->pHTInfo->IOTRaFunc)&0xf);
+				FwParam |= ((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<4);
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set RA/IOT Comb in BG mode!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam);
+				FW_CMD_PARA_SET(priv, FwParam);
+				FW_CMD_IO_SET(priv, FwCmdMap);	
+				FW_CMD_IO_CLR(priv, FW_RA_BG_CTL); 
+				break;
+
+			case FW_CMD_IQK_ENABLE:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] IQK enable.\n");
+				FwCmdMap |= FW_IQK_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);	
+				FW_CMD_IO_CLR(priv, FW_IQK_CTL); 
+				break;
+
+			case FW_CMD_CTRL_DM_BY_DRIVER_NEW:
+				RT_TRACE(COMP_CMD, "[FW CMD][New Version] Inform FW driver control some DM!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam);
+				FwCmdMap |= FW_DRIVER_CTRL_DM_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);
+				break;
+
+			case FW_CMD_RESUME_DM_BY_SCAN:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Resume DM after scan.\n");
+				FwCmdMap |= (FW_DIG_ENABLE_CTL|FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL);
+				
+				if(priv->DMFlag & HAL_DM_DIG_DISABLE || !dm_digtable.dig_enable_flag)
+					FwCmdMap &= ~FW_DIG_ENABLE_CTL;	
+
+				if((priv->DMFlag & HAL_DM_HIPWR_DISABLE) ||
+					(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER) ||
+					(priv->rtllib->bdynamic_txpower_enable == true))
+					FwCmdMap &= ~FW_HIGH_PWR_ENABLE_CTL;
+				
+				if(	(dm_digtable.Dig_Ext_Port_Stage == DIG_EXT_PORT_STAGE_0) ||
+					(dm_digtable.Dig_Ext_Port_Stage == DIG_EXT_PORT_STAGE_1))
+					FwCmdMap &= ~FW_DIG_ENABLE_CTL;
+				
+				FW_CMD_IO_SET(priv, FwCmdMap);		
+				bPostProcessing = true;
+				break;
+		
+			case FW_CMD_PAUSE_DM_BY_SCAN:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Pause DM before scan.\n");
+				FwCmdMap &= ~(FW_DIG_ENABLE_CTL|FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL);
+				FW_CMD_IO_SET(priv, FwCmdMap);	
+				bPostProcessing = true;
+				break;
+
+			case FW_CMD_HIGH_PWR_DISABLE:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version]  Set HighPwr disable!!\n");
+				FwCmdMap &= ~FW_HIGH_PWR_ENABLE_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);		
+				bPostProcessing = true;
+				break;			
+
+			case FW_CMD_HIGH_PWR_ENABLE:	
+				if(((priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER)==0) &&
+					!(priv->DMFlag & HAL_DM_HIPWR_DISABLE) &&
+					(priv->rtllib->bdynamic_txpower_enable != true))
+				{
+					RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set HighPwr enable!!\n");
+					FwCmdMap |= (FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL);
+					FW_CMD_IO_SET(priv, FwCmdMap);		
+					bPostProcessing = true;
+				}
+				break;
+				
+			case FW_CMD_DIG_MODE_FA:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG Mode to FA.\n");
+				FwCmdMap |= FW_FA_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);
+				break;
+
+			case FW_CMD_DIG_MODE_SS:
+				RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG Mode to SS.\n");
+				FwCmdMap &= ~FW_FA_CTL;
+				FW_CMD_IO_SET(priv, FwCmdMap);
+				break;
+				
+			case FW_CMD_PAPE_CONTROL:
+				RT_TRACE(COMP_CMD, "[FW CMD] Set PAPE Control \n");
+#ifdef MERGE_TO_DO
+				if(pHalData->bt_coexist.BT_PapeCtrl)
+				{
+					RTPRINT(FBT, BT_TRACE, ("BT set PAPE Control to SW/HW dynamically. \n"));
+					FwCmdMap |= FW_PAPE_CTL_BY_SW_HW;
+				}
+				else
+#endif
+				{
+					printk("BT set PAPE Control to SW\n");
+					FwCmdMap &= ~FW_PAPE_CTL_BY_SW_HW;
+				}
+				FW_CMD_IO_SET(priv, FwCmdMap);
+				break;
+
+			default:				
+				bPostProcessing = true; 
+				break;
+		}
+	}while(false);
+
+	RT_TRACE(COMP_CMD, "[FW CMD] Current FwCmdMap(%#x)\n", priv->FwCmdIOMap);
+	RT_TRACE(COMP_CMD, "[FW CMD] Current FwCmdIOParam(%#x)\n", priv->FwCmdIOParam);
+
+	if(bPostProcessing && !priv->SetFwCmdInProgress)
+	{
+		priv->SetFwCmdInProgress = true;
+		priv->CurrentFwCmdIO = FwCmdIO; 
+	}
+	else
+	{
+		return false;
+	}
+
+#if 0
+#ifdef USE_WORKITEM			
+	PlatformScheduleWorkItem(&(pHalData->FwCmdIOWorkItem));
+#else
+	PlatformSetTimer(Adapter, &(pHalData->SetFwCmdIOTimer), 0);
+#endif
+#endif
+	rtl8192_SetFwCmdIOCallback(dev);
+	return true;
+}
+void ChkFwCmdIoDone(struct net_device* dev)
+{
+	u16 PollingCnt = 10000;		
+	u32 tmpValue;
+	
+	do
+	{
+		
+		udelay(10); 
+		
+		tmpValue = read_nic_dword(dev, WFM5);
+		if(tmpValue == 0)
+		{
+			RT_TRACE(COMP_CMD, "[FW CMD] Set FW Cmd success!!\n");
+			break;
+		}			
+		else
+		{
+			RT_TRACE(COMP_CMD, "[FW CMD] Polling FW Cmd PollingCnt(%d)!!\n", PollingCnt);
+		}
+	}while( --PollingCnt );
+
+	if(PollingCnt == 0)
+	{
+		RT_TRACE(COMP_ERR, "[FW CMD] Set FW Cmd fail!!\n");
+	}
+}
+void rtl8192_SetFwCmdIOCallback(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u32		input,CurrentAID = 0;
+	
+	if(IS_NIC_DOWN(priv)){
+		RT_TRACE(COMP_CMD, "SetFwCmdIOTimerCallback(): driver is going to unload\n");
+		return;
+	}
+	
+	RT_TRACE(COMP_CMD, "--->SetFwCmdIOTimerCallback(): Cmd(%#x), SetFwCmdInProgress(%d)\n", priv->CurrentFwCmdIO, priv->SetFwCmdInProgress);
+
+	if(HalGetFirmwareVerison(priv) >= 0x34)
+                        {
+		switch(priv->CurrentFwCmdIO)
+		{
+			case FW_CMD_RA_REFRESH_N:
+				priv->CurrentFwCmdIO = FW_CMD_RA_REFRESH_N_COMB;
+			break;
+			case FW_CMD_RA_REFRESH_BG:
+				priv->CurrentFwCmdIO = FW_CMD_RA_REFRESH_BG_COMB;
+			break;
+			default:
+			break;
+		}
+	}
+			
+	switch(priv->CurrentFwCmdIO)
+	{
+
+		case FW_CMD_RA_RESET:
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA Reset!!\n");
+			write_nic_dword(dev, WFM5, FW_RA_RESET);	
+			ChkFwCmdIoDone(dev);	
+			break;
+			
+		case FW_CMD_RA_ACTIVE:
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA Active!!\n");
+			write_nic_dword(dev, WFM5, FW_RA_ACTIVE); 
+			ChkFwCmdIoDone(dev);	
+			break;
+
+		case FW_CMD_RA_REFRESH_N:
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA n refresh!!\n");
+			if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL)
+				input = FW_RA_REFRESH;
+			else
+				input = FW_RA_REFRESH | (priv->rtllib->pHTInfo->IOTRaFunc << 8);
+			write_nic_dword(dev, WFM5, input); 
+			ChkFwCmdIoDone(dev);
+			write_nic_dword(dev, WFM5, FW_RA_ENABLE_RSSI_MASK); 
+			ChkFwCmdIoDone(dev);	
+			break;
+			
+		case FW_CMD_RA_REFRESH_BG:
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA BG refresh!!\n");
+			write_nic_dword(dev, WFM5, FW_RA_REFRESH); 
+			ChkFwCmdIoDone(dev);
+			write_nic_dword(dev, WFM5, FW_RA_DISABLE_RSSI_MASK); 			
+			ChkFwCmdIoDone(dev);	
+			break;
+
+		case FW_CMD_RA_REFRESH_N_COMB:
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA n Combo refresh!!\n");
+			if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL)
+				input = FW_RA_IOT_N_COMB;
+			else
+				input = FW_RA_IOT_N_COMB | (((priv->rtllib->pHTInfo->IOTRaFunc)&0x0f) << 8);
+			input = input |((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<12);
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA/IOT Comb in n mode!! input(%#x)\n", input);
+			write_nic_dword(dev, WFM5, input); 			
+			ChkFwCmdIoDone(dev);	
+			break;		
+
+		case FW_CMD_RA_REFRESH_BG_COMB:		
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA B/G Combo refresh!!\n");
+			if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL)
+				input = FW_RA_IOT_BG_COMB;
+			else
+				input = FW_RA_IOT_BG_COMB | (((priv->rtllib->pHTInfo->IOTRaFunc)&0x0f) << 8);
+			input = input |((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<12);
+			RT_TRACE(COMP_CMD, "[FW CMD] Set RA/IOT Comb in B/G mode!! input(%#x)\n", input);
+			write_nic_dword(dev, WFM5, input); 
+			ChkFwCmdIoDone(dev);	
+			break;
+
+		case FW_CMD_IQK_ENABLE:
+			RT_TRACE(COMP_CMD, "[FW CMD] IQK Enable!!\n");
+			write_nic_dword(dev, WFM5, FW_IQK_ENABLE); 
+			ChkFwCmdIoDone(dev);	
+			break;
+
+		case FW_CMD_PAUSE_DM_BY_SCAN:
+			RT_TRACE(COMP_CMD, "[FW CMD] Pause DM by Scan!!\n");
+			rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, 0x17);
+			rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, 0x17);
+			rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x40);
+			break;
+
+		case FW_CMD_RESUME_DM_BY_SCAN:		
+			RT_TRACE(COMP_CMD, "[FW CMD] Resume DM by Scan!!\n");
+			rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x83);	
+			rtl8192_phy_setTxPower(dev, priv->rtllib->current_network.channel);
+			break;
+		
+		case FW_CMD_HIGH_PWR_DISABLE:
+			RT_TRACE(COMP_CMD, "[FW CMD] High Pwr Disable!!\n");
+			if(priv->DMFlag & HAL_DM_HIPWR_DISABLE)
+				break;
+			rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, 0x17);
+			rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, 0x17);
+			rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x40);
+			break;
+			
+		case FW_CMD_HIGH_PWR_ENABLE:
+			RT_TRACE(COMP_CMD, "[FW CMD] High Pwr Enable!!\n");
+			if((priv->DMFlag & HAL_DM_HIPWR_DISABLE) ||
+				(priv->rtllib->bdynamic_txpower_enable == true))
+				break;
+			rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x83);				
+			break;
+
+		case FW_CMD_LPS_ENTER:
+			RT_TRACE(COMP_CMD, "[FW CMD] Enter LPS mode!!\n");
+			CurrentAID = priv->rtllib->assoc_id;
+			write_nic_dword(dev, WFM5, (FW_LPS_ENTER| ((CurrentAID|0xc000)<<8))    );
+			ChkFwCmdIoDone(dev);	
+			priv->rtllib->pHTInfo->IOTAction |=  HT_IOT_ACT_DISABLE_EDCA_TURBO;
+			break;
+
+		case FW_CMD_LPS_LEAVE:
+			RT_TRACE(COMP_CMD, "[FW CMD] Leave LPS mode!!\n");
+			write_nic_dword(dev, WFM5, FW_LPS_LEAVE );
+			ChkFwCmdIoDone(dev);	
+			priv->rtllib->pHTInfo->IOTAction &=  (~HT_IOT_ACT_DISABLE_EDCA_TURBO);
+			break;
+
+		case FW_CMD_ADD_A2_ENTRY:
+			RT_TRACE(COMP_CMD, "[FW CMD] ADD A2 entry!!\n");
+			write_nic_dword(dev, WFM5, FW_ADD_A2_ENTRY);
+			ChkFwCmdIoDone(dev);
+			break;
+		
+		case FW_CMD_CTRL_DM_BY_DRIVER:
+			RT_TRACE(COMP_CMD, "[FW CMD] Inform fw driver will do some dm at driver\n");
+			write_nic_dword(dev, WFM5, FW_CTRL_DM_BY_DRIVER);
+	                ChkFwCmdIoDone(dev);		
+			break;
+		case FW_CMD_CHAN_SET:
+			input = FW_CHAN_SET | (((priv->chan)&0xff) << 8);
+			RT_TRACE(COMP_CMD, "[FW CMD] Inform fw to set channel to %x!!, input(%#x):\n", priv->chan,input);
+			write_nic_dword(dev, WFM5, input);
+	                ChkFwCmdIoDone(dev);		
+			break;
+			
+		default:
+			break;
+	}
+	
+			
+	ChkFwCmdIoDone(dev);		
+	
+	
+	priv->SetFwCmdInProgress = false;
+	RT_TRACE(COMP_CMD, "<---SetFwCmdIOWorkItemCallback()\n");
+}
+
+static	void
+phy_CheckEphySwitchReady(struct net_device* dev)
+{
+	u32	delay = 100;	
+	u8	regu1;
+
+	regu1 = read_nic_byte(dev, 0x554);
+	while ((regu1 & BIT5) && (delay > 0))
+	{
+		regu1 = read_nic_byte(dev, 0x554);
+		delay--;
+		udelay(50);
+	}	
+	RT_TRACE(COMP_INIT, "regu1=%02x  delay = %d\n", regu1, delay);	
+	
+}	
+
+#ifdef TO_DO_LIST
+void
+HW_RadioGpioChk92SE(
+	IN	PADAPTER	pAdapter
+	)
+{
+	PMGNT_INFO		pMgntInfo = &(pAdapter->MgntInfo);
+	u1Byte				u1Tmp = 0;
+	HAL_DATA_TYPE		*pHalData = GET_HAL_DATA(pAdapter);
+	RT_RF_POWER_STATE	eRfPowerStateToSet;
+	BOOLEAN				bActuallySet = false;
+
+#if 0
+	if (!RT_IN_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3) &&
+		pMgntInfo->RfOffReason != RF_CHANGE_BY_HW)
+	{
+		return;
+	}
+	
+		PlatformSwitchClkReq(pAdapter, 0x00);
+
+	if (RT_IN_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3))
+	{		
+		RT_LEAVE_D3(pAdapter, false);
+		RT_CLEAR_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3);
+		Power_DomainInit92SE(pAdapter);
+	}
+
+	PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO));
+
+	u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL);
+	u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK;
+	PlatformEFIOWrite1Byte(pAdapter, GPIO_IO_SEL, u1Tmp);
+
+	RT_TRACE(COMP_CMD, DBG_LOUD, 
+	("HW_RadioGpioChk92SE HW_RadioGpioChk92SE=%02x\n", HW_RadioGpioChk92SE));
+	
+	u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN);
+
+	eRfPowerStateToSet = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff;
+
+	if( (pHalData->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
+	{
+		RT_TRACE(COMP_RF, DBG_LOUD, ("HW_RadioGpioChk92SE  - HW Radio ON\n"));
+		pHalData->bHwRadioOff = false;
+		bActuallySet = true;
+	}
+	else if ( (pHalData->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
+	{
+		RT_TRACE(COMP_RF, DBG_LOUD, ("HW_RadioGpioChk92SE  - HW Radio OFF\n"));
+		pHalData->bHwRadioOff = true;
+		bActuallySet = true;
+	}
+			
+	if(bActuallySet)
+	{
+		pHalData->bHwRfOffAction = 1;
+		MgntActSet_RF_State(pAdapter, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+		DrvIFIndicateCurrentPhyStatus(pAdapter);
+
+	
+		{
+			PMP_ADAPTER		pDevice = &(pAdapter->NdisAdapter);
+			if(pDevice->RegHwSwRfOffD3 == 1 || pDevice->RegHwSwRfOffD3 == 2) 
+				(eRfPowerStateToSet == eRfOff) ? RT_ENABLE_ASPM(pAdapter) : RT_DISABLE_ASPM(pAdapter);
+		}
+	}
+	RT_TRACE(COMP_RF, DBG_TRACE, ("HW_RadioGpioChk92SE() <--------- \n"));
+#endif
+}/* HW_RadioGpioChk92SE */
+#endif
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.c
@@ -0,0 +1,1869 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "../rtl_core.h"
+#include "r8192S_Efuse.h"
+
+#include <linux/types.h>
+
+#ifdef RTL8192SE
+/*---------------------------Define Local Constant---------------------------*/
+#define 	_POWERON_DELAY_
+#define 	_PRE_EXECUTE_READ_CMD_
+
+#define		EFUSE_REPEAT_THRESHOLD_		3
+#define		EFUSE_ERROE_HANDLE		1
+
+
+typedef struct _EFUSE_MAP_A{
+	u8 offset;		
+	u8 word_start;	
+	u8 byte_start;	
+	u8 byte_cnts;
+	
+}EFUSE_MAP, *PEFUSE_MAP;
+
+typedef struct PG_PKT_STRUCT_A{
+	u8 offset;
+	u8 word_en;
+	u8 data[8];	
+}PGPKT_STRUCT,*PPGPKT_STRUCT;
+
+typedef enum _EFUSE_DATA_ITEM{
+	EFUSE_CHIP_ID=0,
+	EFUSE_LDO_SETTING,
+	EFUSE_CLK_SETTING,
+	EFUSE_SDIO_SETTING,
+	EFUSE_CCCR,
+	EFUSE_SDIO_MODE,
+	EFUSE_OCR,
+	EFUSE_F0CIS,
+	EFUSE_F1CIS,
+	EFUSE_MAC_ADDR,
+	EFUSE_EEPROM_VER,
+	EFUSE_CHAN_PLAN,
+	EFUSE_TXPW_TAB
+} EFUSE_DATA_ITEM;
+
+struct efuse_priv 
+{    
+	u8		id[2];
+	u8		ldo_setting[2];
+	u8		clk_setting[2];
+	u8		cccr;
+	u8		sdio_mode;
+	u8		ocr[3];
+	u8		cis0[17];
+	u8		cis1[48];	
+	u8		mac_addr[6];
+	u8		eeprom_verno;	
+	u8		channel_plan;
+	u8		tx_power_b[14];
+	u8		tx_power_g[14];	
+};
+
+/*---------------------------Define Local Constant---------------------------*/
+
+
+/*------------------------Define global variable-----------------------------*/
+const u8 MAX_PGPKT_SIZE = 9; 
+const u8 PGPKT_DATA_SIZE = 8; 
+const u32 EFUSE_MAX_SIZE = 512;
+
+const u8 EFUSE_OOB_PROTECT_BYTES = 15; 
+
+
+const EFUSE_MAP RTL8712_SDIO_EFUSE_TABLE[]={
+/*ID*/		{0		,0		,0			,2	}, 
+/*LDO Setting*/	{0		,1		,0			,2	}, 
+/*CLK Setting*/	{0		,2		,0			,2	}, 
+/*SDIO Setting*/{1		,0		,0			,1	}, 
+/*CCCR*/	{1		,0		,1			,1	}, 
+/*SDIO MODE*/	{1		,1		,0			,1	}, 
+/*OCR*/		{1		,1		,1			,3	}, 
+/*CCIS*/	{1		,3		,0			,17	}, 
+/*F1CIS*/	{3		,3		,1			,48	}, 
+/*MAC Addr*/	{10		,0		,0			,6	}, 
+/*EEPROM ver*/	{10		,3		,0			,1	}, 
+/*Channel plan*/{10		,3		,1			,1	}, 
+/*TxPwIndex */	{11		,0		,0			,28	}  
+};
+
+/*------------------------Define global variable-----------------------------*/
+
+
+/*------------------------Define local variable------------------------------*/
+
+/*------------------------Define local variable------------------------------*/
+
+
+/*--------------------Define function prototype-----------------------*/
+extern	void	
+EFUSE_Initialize(struct net_device* dev);
+extern	u8	
+EFUSE_Read1Byte(struct net_device* dev, u16 Address);
+extern	void	
+EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value);
+
+static	void
+efuse_ShadowRead1Byte(struct net_device* dev,u16 Offset,u8 *Value);
+static	void
+efuse_ShadowRead2Byte(struct net_device* dev,	u16 Offset,u16 *Value	);
+static	void
+efuse_ShadowRead4Byte(struct net_device* dev,	u16 Offset,u32 *Value	);
+static	void
+efuse_ShadowWrite1Byte(struct net_device* dev,	u16 Offset, u8 Value);
+static	void
+efuse_ShadowWrite2Byte(struct net_device* dev,	u16 Offset,u16 Value);
+static	void
+efuse_ShadowWrite4Byte(struct net_device* dev,	u16 Offset,u32 Value);
+
+static	u8
+efuse_OneByteRead(struct net_device* dev,u16 addr,u8 *data);
+static	u8
+efuse_OneByteWrite(struct net_device* dev,u16 addr, u8 data);
+
+static	void 
+efuse_ReadAllMap(struct net_device* dev,u8 *Efuse);
+#ifdef TO_DO_LIST
+static	void
+efuse_WriteAllMap(struct net_device* dev,u8 *eeprom,u32 eeprom_size);
+static	bool	
+efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove);
+#endif
+static	u8
+efuse_PgPacketRead(	struct net_device* dev,u8	offset,u8 *data);
+static	u8 
+efuse_PgPacketWrite(struct net_device* dev,u8 offset,u8 word_en,u8	*data);
+static	void
+efuse_WordEnableDataRead(	u8 word_en,u8 *sourdata,u8 *targetdata);
+static	u8
+efuse_WordEnableDataWrite(	struct net_device* dev, u16 efuse_addr, u8 word_en, u8 *data);
+static	void
+efuse_PowerSwitch(struct net_device* dev,u8 PwrState);
+static	u16
+efuse_GetCurrentSize(struct net_device* dev);
+static u8
+efuse_CalculateWordCnts(u8 word_en);
+#if 0
+static	void
+efuse_ResetLoader(struct net_device* dev);
+#endif
+#ifdef TO_DO_LIST
+static void efuse_reg_ctrl(struct net_device* dev, u8 bPowerOn);
+#endif
+/*--------------------Define function prototype-----------------------*/
+
+
+
+extern	void	
+EFUSE_Initialize(struct net_device* dev)
+{
+	u8	Bytetemp = {0x00};
+	u8	temp = {0x00};
+
+	Bytetemp = read_nic_byte(dev, SYS_FUNC_EN+1);
+	temp = Bytetemp | 0x20;
+	write_nic_byte(dev, SYS_FUNC_EN+1, temp);
+
+	Bytetemp = read_nic_byte(dev, SYS_ISO_CTRL+1);
+	temp = Bytetemp & 0xFE;
+	write_nic_byte(dev, SYS_ISO_CTRL+1, temp);
+
+	
+	Bytetemp = read_nic_byte(dev, EFUSE_TEST+3);
+	temp = Bytetemp | 0x80;
+	write_nic_byte(dev, EFUSE_TEST+3, temp);
+
+	write_nic_byte(dev, 0x2F8, 0x3);
+	
+	write_nic_byte(dev, EFUSE_CTRL+3, 0x72);
+	
+}	/* EFUSE_Initialize */
+
+
+extern	u8	
+EFUSE_Read1Byte(struct net_device* dev, u16	Address)
+{
+	u8	data;
+	u8	Bytetemp = {0x00};
+	u8	temp = {0x00};
+	u32	k=0;
+
+	if (Address < EFUSE_REAL_CONTENT_LEN)	
+	{
+		temp = Address & 0xFF;	
+		write_nic_byte(dev, EFUSE_CTRL+1, temp);	
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2);	
+		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);	
+		write_nic_byte(dev, EFUSE_CTRL+2, temp);	
+
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);
+		temp = Bytetemp & 0x7F;
+		write_nic_byte(dev, EFUSE_CTRL+3, temp);
+
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);
+		while(!(Bytetemp & 0x80))
+		{				
+			Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);
+			k++;
+			if(k==1000)
+			{
+				k=0;
+				break;
+			}
+		}
+		data=read_nic_byte(dev, EFUSE_CTRL);
+		return data;
+	}
+	else
+		return 0xFF;
+	
+}	/* EFUSE_Read1Byte */
+
+
+extern	void	
+EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value)
+{
+	u8	Bytetemp = {0x00};
+	u8	temp = {0x00};
+	u32	k=0;
+
+	
+	if( Address < EFUSE_REAL_CONTENT_LEN)	
+	{
+		write_nic_byte(dev, EFUSE_CTRL, Value);
+
+		temp = Address & 0xFF;	
+		write_nic_byte(dev, EFUSE_CTRL+1, temp);	
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2);	
+		
+		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);	
+		write_nic_byte(dev, EFUSE_CTRL+2, temp);	
+
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);
+		temp = Bytetemp | 0x80;
+		write_nic_byte(dev, EFUSE_CTRL+3, temp);
+
+		Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);
+		while(Bytetemp & 0x80)
+		{
+			Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3);			
+			k++;
+			if(k==100)
+			{
+				k=0;
+				break;
+			}
+		}
+	}
+	
+}	/* EFUSE_Write1Byte */
+
+
+#ifdef EFUSE_FOR_92SU
+void do_93c46(struct net_device* dev,  u8 addorvalue)
+{
+	u8  cs[1] = {0x88};        
+	u8  cssk[1] = {0x8c};      
+	u8  csdi[1] = {0x8a};      
+    	u8  csskdi[1] = {0x8e};    
+    	u8  count;
+	
+    	for(count=0 ; count<8 ; count++)
+	{
+		if((addorvalue&0x80)!=0)
+		{
+			write_nic_byte(dev, EPROM_CMD, csdi[0]);  		
+			write_nic_byte(dev, EPROM_CMD, csskdi[0]);  		
+		}
+		else
+		{
+			write_nic_byte(dev, EPROM_CMD, cs[0]);  		
+			write_nic_byte(dev, EPROM_CMD, cssk[0]);  		
+		}
+		addorvalue = addorvalue << 1;
+	}
+}
+
+
+u16 Read93C46(struct net_device*	dev,	u16	Reg	)
+{
+
+   	u8  	clear[1] = {0x0};      
+	u8  	cs[1] = {0x88};        
+	u8  	cssk[1] = {0x8c};      
+	u8  	csdi[1] = {0x8a};      
+   	u8  	csskdi[1] = {0x8e};    
+	u8  	EepromSEL[1]={0x00};
+	u8  	address;
+	
+	u16   	storedataF[1] = {0x0};   
+	u8   	t,data[1],storedata[1];
+	
+
+	address = (u8)Reg;
+	
+	*EepromSEL= read_nic_byte(dev, EPROM_CMD);
+
+	if((*EepromSEL & 0x10) == 0x10) 
+	{
+		address = address | 0x80;
+
+		write_nic_byte(dev, EPROM_CMD, csdi[0]);  		
+		write_nic_byte(dev, EPROM_CMD, csskdi[0]);  		
+   		do_93c46(dev, address);
+	}
+
+
+	for(t=0 ; t<16 ; t++)      
+	{
+		write_nic_byte(dev, EPROM_CMD, cs[0]);  		
+		write_nic_byte(dev, EPROM_CMD, cssk[0]); 
+		*data= read_nic_byte(dev, EPROM_CMD);		
+		
+		if(*data & 0x8d) 
+		{
+			*data = *data & 0x01;
+			*storedata = *data;
+		}
+		else 
+		{
+			*data = *data & 0x01 ; 
+			*storedata = *data;   
+		} 
+		*storedataF = (*storedataF << 1 ) + *storedata;
+	}
+	write_nic_byte(dev, EPROM_CMD, cs[0]);     
+	write_nic_byte(dev, EPROM_CMD, clear[0]);     
+
+	return *storedataF;
+}
+
+
+void
+ReadEFuseByte(struct net_device* dev,u16 _offset, u8 *pbuf) 
+{
+
+	u32  value32;
+	u8 	readbyte;
+	u16 	retry;
+	
+
+	write_nic_byte(dev, EFUSE_CTRL+1, (_offset & 0xff));  		
+	readbyte = read_nic_byte(dev, EFUSE_CTRL+2);
+	write_nic_byte(dev, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));  		
+
+	readbyte = read_nic_byte(dev, EFUSE_CTRL+3);		
+	write_nic_byte(dev, EFUSE_CTRL+3, (readbyte & 0x7f));  	
+	
+	retry = 0;
+	value32 = read_nic_dword(dev, EFUSE_CTRL);
+	while(!(((value32 >> 24) & 0xff) & 0x80)  && (retry<10000))
+	{
+		value32 = read_nic_dword(dev, EFUSE_CTRL);
+		retry++;
+	}	
+	*pbuf = (u8)(value32 & 0xff);
+}
+
+
+#define		EFUSE_READ_SWITCH		1
+void
+ReadEFuse(struct net_device* dev, u16	 _offset, u16 _size_byte, u8 *pbuf)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8  	efuseTbl[EFUSE_MAP_LEN];
+	u8  	rtemp8[1];
+	u16 	eFuse_Addr = 0;
+	u8  	offset, wren;
+	u16  	i, j;
+	u16 	eFuseWord[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT];
+	u16	efuse_utilized = 0;
+	u16	efuse_usage = 0;
+#ifdef EFUSE_REPG_WORKAROUND
+	u16	sec1_addr = 0, sec5_addr = 0;
+#endif
+
+	if((_offset + _size_byte)>EFUSE_MAP_LEN)
+	{
+		printk("ReadEFuse(): Invalid offset with read bytes!!\n");
+		return;
+	}
+
+	for (i = 0; i < EFUSE_MAX_SECTION; i++)
+		for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+			eFuseWord[i][j]=0xFFFF;
+	
+	for (i = 0; i < EFUSE_MAP_LEN; i++)
+		efuseTbl[i] = 0xFF;
+
+	ReadEFuseByte(dev, eFuse_Addr, rtemp8);	
+	if(*rtemp8 != 0xFF)		
+	{
+		efuse_utilized++;
+		eFuse_Addr++;
+	}
+	while((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN))
+	{
+		offset = ((*rtemp8 >> 4) & 0x0f);
+#ifdef EFUSE_REPG_WORKAROUND
+		if (IS_HARDWARE_TYPE_8192SE(dev))
+		{
+			if (offset == 1)
+			{
+				sec1_addr = eFuse_Addr;	
+			}
+			else if (offset == 5)
+			{
+				sec5_addr = eFuse_Addr;
+			}
+		
+			if (sec1_addr > sec5_addr)
+			{
+				priv->efuse_RePGSec1Flag = false;
+			}
+			else
+			{
+				priv->efuse_RePGSec1Flag = true;
+		       }
+		}
+#endif
+		if(offset < EFUSE_MAX_SECTION){
+			wren = (*rtemp8 & 0x0f);
+			for(i=0; i<4; i++){
+				if(!(wren & 0x01)){
+					ReadEFuseByte(dev, eFuse_Addr, rtemp8);	eFuse_Addr++;
+					efuse_utilized++;
+					eFuseWord[offset][i] = (*rtemp8 & 0xff);
+					if(eFuse_Addr >= EFUSE_REAL_CONTENT_LEN) break;
+					ReadEFuseByte(dev, eFuse_Addr, rtemp8);	eFuse_Addr++;
+					efuse_utilized++;
+					eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00);
+					if(eFuse_Addr >= EFUSE_REAL_CONTENT_LEN) break;
+				}
+				wren >>= 1;
+			}
+		}
+		ReadEFuseByte(dev, eFuse_Addr, rtemp8);	
+		if(*rtemp8 != 0xFF && (eFuse_Addr < 512))	
+		{
+			efuse_utilized++;
+			eFuse_Addr++;
+		}
+	}
+
+	for(i=0; i<EFUSE_MAX_SECTION; i++){
+		for(j=0; j<EFUSE_MAX_WORD_UNIT; j++){
+			efuseTbl[(i*8)+(j*2)]=(eFuseWord[i][j] & 0xff);
+			efuseTbl[(i*8)+((j*2)+1)]=((eFuseWord[i][j] >> 8) & 0xff);
+#ifdef FUSE_REPG_WORKAROUND
+			if ((i == 1) && (priv->efuse_RePGSec1Flag == true))
+			{
+				priv->efuse_RePGData[j*2]=(eFuseWord[i][j] & 0xff);
+				priv->efuse_RePGData[(j*2)+1]=((eFuseWord[i][j] >> 8) & 0xff);
+			}
+#endif
+		}
+	}
+	for(i=0; i<_size_byte; i++)
+		pbuf[i] = efuseTbl[_offset+i];
+	priv->EfuseUsedBytes = efuse_utilized;
+	efuse_usage = (u8)((efuse_utilized*100)/EFUSE_REAL_CONTENT_LEN);
+	priv->EfuseUsedPercentage = efuse_usage;	
+}
+#endif	
+
+extern bool EFUSE_ShadowUpdateChk(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8   SectionIdx, i, Base;
+	u16  WordsNeed = 0, HdrNum = 0, TotalBytes = 0, EfuseUsed = 0;
+	bool bWordChanged, bResult = true;
+
+	for (SectionIdx = 0; SectionIdx < 16; SectionIdx++) {
+		Base = SectionIdx * 8;
+		bWordChanged = false;
+
+		for (i = 0; i < 8; i=i+2) {
+			if((priv->EfuseMap[EFUSE_INIT_MAP][Base+i] !=
+						priv->EfuseMap[EFUSE_MODIFY_MAP][Base+i]) ||
+					(priv->EfuseMap[EFUSE_INIT_MAP][Base+i+1] !=
+					 priv->EfuseMap[EFUSE_MODIFY_MAP][Base+i+1])) {
+				WordsNeed++;
+				bWordChanged = true;
+			}
+		}
+
+		if( bWordChanged == true )
+			HdrNum++;
+	}
+
+	TotalBytes = HdrNum + WordsNeed * 2;
+	EfuseUsed = priv->EfuseUsedBytes;
+
+	if ((TotalBytes + EfuseUsed) >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))
+		bResult = false;
+
+	return bResult;
+}
+
+extern void
+EFUSE_ShadowRead(	struct net_device*	dev,	u8 Type, u16 Offset, u32 *Value)
+{
+
+	if (Type == 1)
+		efuse_ShadowRead1Byte(dev, Offset, (u8 *)Value);
+	else if (Type == 2)
+		efuse_ShadowRead2Byte(dev, Offset, (u16 *)Value);
+	else if (Type == 4)
+		efuse_ShadowRead4Byte(dev, Offset, (u32 *)Value);
+	
+}	
+
+
+extern	void
+EFUSE_ShadowWrite(	struct net_device*	dev,	u8 Type, u16 Offset,u32	Value)
+{
+
+	if (Offset >= 0x18 && Offset <= 0x1F)
+		return;
+
+	if (Type == 1)
+		efuse_ShadowWrite1Byte(dev, Offset, (u8)Value);
+	else if (Type == 2)
+		efuse_ShadowWrite2Byte(dev, Offset, (u16)Value);
+	else if (Type == 4)
+		efuse_ShadowWrite4Byte(dev, Offset, (u32)Value);
+	
+}	
+
+
+extern bool EFUSE_ShadowUpdate(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16  i, offset, base = 0;
+	u8   word_en = 0x0F;
+	bool first_pg = false;
+
+	if (!EFUSE_ShadowUpdateChk(dev)) {
+		efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]);
+		memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0],
+				(void *)&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S);
+
+		printk("<---EFUSE_ShadowUpdate(): Efuse out of capacity!!\n");
+		return false;
+	}
+
+	efuse_PowerSwitch(dev, true);
+
+	for (offset = 0; offset < 16; offset++)
+	{
+		if(IS_HARDWARE_TYPE_8192SE(dev)){
+			if (offset == 3)
+				continue;
+		}
+		word_en = 0x0F;		
+		base = offset * 8;
+
+		for (i = 0; i < 8; i++)
+		{
+			if (offset == 0 && priv->EfuseMap[EFUSE_INIT_MAP][base+i] == 0xFF)
+			{
+				first_pg = true;				
+			}
+
+			if (first_pg == true && offset == 1 && IS_HARDWARE_TYPE_8192SE(dev))
+			{
+				continue;
+			}
+
+			if (first_pg == true)
+			{
+				word_en &= ~(BIT(i/2));	
+				priv->EfuseMap[EFUSE_INIT_MAP][base+i] = 
+				priv->EfuseMap[EFUSE_MODIFY_MAP][base+i];
+			}else
+			{
+				if (	priv->EfuseMap[EFUSE_INIT_MAP][base+i] != 
+					priv->EfuseMap[EFUSE_MODIFY_MAP][base+i])
+				{
+					word_en &= ~(EFUSE_BIT(i/2));
+
+					priv->EfuseMap[EFUSE_INIT_MAP][base+i] = 
+					priv->EfuseMap[EFUSE_MODIFY_MAP][base+i];
+				}
+			}
+		}
+		
+		if (word_en != 0x0F)
+		{
+			u8	tmpdata[8];
+
+			memcpy(tmpdata, &(priv->EfuseMap[EFUSE_MODIFY_MAP][base]), 8);
+			efuse_PgPacketWrite(dev,(u8)offset,word_en,tmpdata);
+		}
+		
+	}
+	if (first_pg == true && IS_HARDWARE_TYPE_8192SE(dev))
+	{
+		u8	tmpdata[8];
+
+		memcpy(tmpdata, (&priv->EfuseMap[EFUSE_MODIFY_MAP][8]), 8);
+		efuse_PgPacketWrite(dev, 1, 0x0, tmpdata);		
+#if 0
+		u1Byte	tmpdata[8] = {0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF};
+		
+		efuse_PgPacketWrite(pAdapter, 1, 0xD, tmpdata);
+#endif		
+	}
+
+
+	efuse_PowerSwitch(dev, false);
+	efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]);
+	memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0],
+		(void *)&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S);
+		
+	return true;	
+}	
+
+
+extern void EFUSE_ShadowMapUpdate(struct net_device* dev)
+{	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if (priv->AutoloadFailFlag == true){
+		memset(&(priv->EfuseMap[EFUSE_INIT_MAP][0]), 0xff, 128);
+	}else{	
+		efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]);
+	}
+	memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], 
+		&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S);
+	
+}	
+
+
+extern	void 
+EFUSE_ForceWriteVendorId( struct net_device* dev)
+{
+	u8 tmpdata[8] = {0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF};
+
+	efuse_PowerSwitch(dev, true);
+		
+	efuse_PgPacketWrite(dev, 1, 0xD, tmpdata);
+
+	efuse_PowerSwitch(dev, false);
+	
+}	
+
+extern	void 
+EFUSE_RePgSection1(struct net_device* dev)
+{
+#ifdef EFUSE_REPG_WORKAROUND
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	if (priv->efuse_RePGSec1Flag == true)
+	{
+		efuse_PowerSwitch(dev, true);		
+		RT_TRACE(COMP_INIT, "EFUSE REPG: %p, %u\n", priv->efuse_RePGData, 8);
+				
+		efuse_PgPacketWrite(dev, 1, 0x0d, priv->efuse_RePGData);	
+		efuse_PowerSwitch(dev, false);
+		priv->efuse_RePGSec1Flag = false;
+	}
+#endif	
+}	
+
+
+static	void
+efuse_ShadowRead1Byte(struct net_device*	dev,	u16 Offset,	u8 *Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	*Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset];
+	
+}	
+
+static	void
+efuse_ShadowRead2Byte(struct net_device*	dev,	u16 Offset,	u16 *Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	*Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset];
+	*Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8;
+	
+}	
+
+static	void
+efuse_ShadowRead4Byte(struct net_device*	dev,	u16 Offset,	u32 *Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	*Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset];
+	*Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8;
+	*Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2]<<16;
+	*Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3]<<24;
+	
+}	
+
+
+
+static	void
+efuse_ShadowWrite1Byte(struct net_device*	dev,	u16 Offset,	u8 Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value;
+	
+}	
+
+static	void
+efuse_ShadowWrite2Byte(struct net_device*	dev,	u16 Offset,	u16 Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value&0x00FF;
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = Value>>8;
+	
+}	
+
+static	void
+efuse_ShadowWrite4Byte(struct net_device*	dev,	u16 Offset,	u32 Value)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = (u8)(Value&0x000000FF);
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = (u8)((Value>>8)&0x0000FF);
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2] = (u8)((Value>>16)&0x00FF);
+	priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3] = (u8)((Value>>24)&0xFF);
+	
+}	
+
+
+static	u8
+efuse_OneByteRead(struct net_device* dev, u16 addr,u8 *data)
+{
+	u8 tmpidx = 0;
+	u8 bResult;
+	
+	write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff));		
+	write_nic_byte(dev, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03) ) | 
+	(read_nic_byte(dev, EFUSE_CTRL+2)&0xFC ));	
+
+	write_nic_byte(dev, EFUSE_CTRL+3,  0x72);
+
+	while(!(0x80 &read_nic_byte(dev, EFUSE_CTRL+3))&&(tmpidx<100))
+	{
+		tmpidx++;
+	}
+	if(tmpidx<100)
+	{			
+		*data=read_nic_byte(dev, EFUSE_CTRL);		
+		bResult = true;
+	}
+	else
+	{
+		*data = 0xff;	
+		bResult = false;
+	}
+	return bResult;
+}	
+		
+static	u8
+efuse_OneByteWrite(struct net_device* dev,  u16 addr, u8 data)
+{
+	u8 tmpidx = 0;
+	u8 bResult;
+	
+
+
+	write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff));		
+	write_nic_byte(dev, EFUSE_CTRL+2, 
+	read_nic_byte(dev, EFUSE_CTRL+2)|(u8)((addr>>8)&0x03) );
+
+	write_nic_byte(dev, EFUSE_CTRL, data);
+	write_nic_byte(dev, EFUSE_CTRL+3, 0xF2);
+		
+	while((0x80 &  read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){
+		tmpidx++;
+	}
+	
+	if(tmpidx<100)
+	{					
+		bResult = true;
+	}
+	else
+	{			
+		bResult = false;
+	}		
+	
+	return bResult;	
+}	
+
+
+static	void 
+efuse_ReadAllMap(struct net_device*	dev, u8	*Efuse)
+{	
+		
+	efuse_PowerSwitch(dev, true);
+	ReadEFuse(dev, 0, 128, Efuse);
+	efuse_PowerSwitch(dev, false);
+#if 0
+	RT_TRACE(COMP_INIT, "efuse_ResetLoader\n");
+	efuse_ResetLoader(dev);
+
+	write_nic_byte(dev, EFUSE_CLK, 0x03);
+	
+	ReadEFuse(dev, 0, 128, Efuse);
+
+	write_nic_byte(dev, EFUSE_CLK, 0x02);
+#if 0	
+	for(offset = 0;offset<16;offset++)	
+	{		
+		PlatformFillMemory((PVOID)pg_data, 8, 0xff);
+		efuse_PgPacketRead(pAdapter,offset,pg_data);
+
+		PlatformMoveMemory((PVOID)&Efuse[offset*8], (PVOID)pg_data, 8);
+	}
+#endif
+
+	if (Efuse[0] != 0x29 || Efuse[1] != 0x81)
+	{
+		if (index ++ < 5)
+		{
+			RT_TRACE(COMP_INIT, "EFUSE R FAIL %d\n", index);
+			efuse_ReadAllMap(dev, Efuse);
+		}
+	}
+	else
+	{
+		index = 0;
+	}
+
+#endif	
+}	
+
+
+#ifdef TO_DO_LIST
+static	void
+efuse_WriteAllMap(struct net_device* dev,u8 *eeprom, u32 eeprom_size)
+{	
+	unsigned char word_en = 0x00;
+
+	unsigned char tmpdata[8];
+	unsigned char offset;
+
+	efuse_PowerSwitch(dev, true);
+
+	for(offset=0 ; offset< eeprom_size/PGPKT_DATA_SIZE ; offset++)
+	{
+		if (IS_HARDWARE_TYPE_8192SE(dev))
+		{
+			if (offset == 3/* || offset > 9*/)	
+				continue;
+			else
+				word_en = 0x00;
+		}
+		
+		memcpy(tmpdata, (eeprom+(offset*PGPKT_DATA_SIZE)), 8);
+
+	
+		efuse_PgPacketWrite(dev,offset,word_en,tmpdata);
+
+		
+	}
+
+	efuse_PowerSwitch(dev, false);
+	
+}	
+#endif
+static	u8
+efuse_PgPacketRead(	struct net_device*	dev,	u8 offset, u8	*data)
+{	
+	u8 ReadState = PG_STATE_HEADER;	
+	
+	bool bContinual = true;
+	bool  bDataEmpty = true ;	
+
+	u8 efuse_data,word_cnts=0;
+	u16 efuse_addr = 0;
+	u8 hoffset=0,hworden=0;	
+	u8 tmpidx=0;
+	u8 tmpdata[8];
+	
+	if(data==NULL)	return false;
+	if(offset>15)		return false;	
+	
+	memset(data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+	memset(tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+	
+	
+	while(bContinual && (efuse_addr  < EFUSE_MAX_SIZE) )
+	{			
+		if(ReadState & PG_STATE_HEADER)
+		{
+			if(efuse_OneByteRead(dev, efuse_addr ,&efuse_data)&&(efuse_data!=0xFF)){				
+				hoffset = (efuse_data>>4) & 0x0F;
+				hworden =  efuse_data & 0x0F;									
+				word_cnts = efuse_CalculateWordCnts(hworden);
+				bDataEmpty = true ;
+
+				if(hoffset==offset){
+					for(tmpidx = 0;tmpidx< word_cnts*2 ;tmpidx++){
+						if(efuse_OneByteRead(dev, efuse_addr+1+tmpidx ,&efuse_data) ){
+							tmpdata[tmpidx] = efuse_data;
+							if(efuse_data!=0xff){						
+								bDataEmpty = false;
+							}
+						}					
+					}
+					if(bDataEmpty==false){
+						ReadState = PG_STATE_DATA;							
+					}else{
+						efuse_addr = efuse_addr + (word_cnts*2)+1;
+						ReadState = PG_STATE_HEADER; 
+					}
+				}
+				else{
+					efuse_addr = efuse_addr + (word_cnts*2)+1;
+					ReadState = PG_STATE_HEADER; 
+				}
+				
+			}
+			else{
+				bContinual = false ;
+			}
+		}		
+		else if(ReadState & PG_STATE_DATA)
+		{
+			efuse_WordEnableDataRead(hworden,tmpdata,data);
+			efuse_addr = efuse_addr + (word_cnts*2)+1;
+			ReadState = PG_STATE_HEADER; 
+		}
+		
+	}			
+	
+	
+	if(	(data[0]==0xff) &&(data[1]==0xff) && (data[2]==0xff)  && (data[3]==0xff) &&
+		(data[4]==0xff) &&(data[5]==0xff) && (data[6]==0xff)  && (data[7]==0xff))
+		return false;
+	else
+		return true;
+
+}	
+
+
+static u8 efuse_PgPacketWrite(struct net_device* dev, u8 offset, u8 word_en,u8 *data)
+{
+	u8 WriteState = PG_STATE_HEADER;		
+	bool bContinual = true,bDataEmpty=true, bResult = true;
+	u16 efuse_addr = 0;
+	u8 efuse_data;
+
+	u8 pg_header = 0;
+
+	u8 tmp_word_cnts=0,target_word_cnts=0;
+	u8 tmp_header,match_word_en,tmp_word_en;
+
+	PGPKT_STRUCT target_pkt;	
+	PGPKT_STRUCT tmp_pkt;
+
+	u8 originaldata[sizeof(u8)*8];
+	u8 tmpindex = 0,badworden = 0x0F;
+
+	static u32 repeat_times = 0;
+
+	if (efuse_GetCurrentSize(dev) >= EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES) {
+		printk("efuse_PgPacketWrite error \n");
+		return false;
+	}
+
+	target_pkt.offset = offset;
+	target_pkt.word_en= word_en;
+
+	memset(target_pkt.data,0xFF,sizeof(u8)*8);
+	
+	efuse_WordEnableDataRead(word_en,data,target_pkt.data);
+	target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en);
+
+	printk("EFUSE Power ON\n");
+
+	while (bContinual && (efuse_addr  < (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)))
+	{
+		if(WriteState==PG_STATE_HEADER)
+		{	
+			bDataEmpty=true;
+			badworden = 0x0F;		
+			printk("EFUSE PG_STATE_HEADER\n");
+			if (	efuse_OneByteRead(dev, efuse_addr ,&efuse_data) &&
+				(efuse_data!=0xFF))
+			{ 	
+				tmp_header  =  efuse_data;
+				
+				tmp_pkt.offset 	= (tmp_header>>4) & 0x0F;
+				tmp_pkt.word_en 	= tmp_header & 0x0F;					
+				tmp_word_cnts =  efuse_CalculateWordCnts(tmp_pkt.word_en);
+
+				if(tmp_pkt.offset  != target_pkt.offset)
+				{
+					efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; 
+					#if (EFUSE_ERROE_HANDLE == 1)
+					WriteState = PG_STATE_HEADER;
+					#endif
+				}
+				else
+				{	
+					for(tmpindex=0 ; tmpindex<(tmp_word_cnts*2) ; tmpindex++)
+					{
+						if(efuse_OneByteRead(dev, (efuse_addr+1+tmpindex) ,&efuse_data)&&(efuse_data != 0xFF)){
+							bDataEmpty = false;	
+						}
+					}	
+					if(bDataEmpty == false)
+					{						
+						efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; 
+						#if (EFUSE_ERROE_HANDLE == 1)
+						WriteState=PG_STATE_HEADER;
+						#endif
+					}
+					else
+					{
+						match_word_en = 0x0F;
+						if(   !( (target_pkt.word_en&BIT0)|(tmp_pkt.word_en&BIT0)  ))
+						{
+							 match_word_en &= (~BIT0);
+						}	
+						if(   !( (target_pkt.word_en&BIT1)|(tmp_pkt.word_en&BIT1)  ))
+						{
+							 match_word_en &= (~BIT1);
+						}
+						if(   !( (target_pkt.word_en&BIT2)|(tmp_pkt.word_en&BIT2)  ))
+						{
+							 match_word_en &= (~BIT2);
+						}
+						if(   !( (target_pkt.word_en&BIT3)|(tmp_pkt.word_en&BIT3)  ))
+						{
+							 match_word_en &= (~BIT3);
+						}					
+												
+						if((match_word_en&0x0F)!=0x0F)
+						{							
+							badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1, tmp_pkt.word_en ,target_pkt.data);
+							
+							if(0x0F != (badworden&0x0F))
+							{														
+								u8 reorg_offset = offset;
+								u8 reorg_worden=badworden;								
+								efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata);	
+							}	
+
+							tmp_word_en = 0x0F;	
+							if(  (target_pkt.word_en&BIT0)^(match_word_en&BIT0)  )
+							{
+								tmp_word_en &= (~BIT0);
+							}
+							if(   (target_pkt.word_en&BIT1)^(match_word_en&BIT1) )
+							{
+								tmp_word_en &=  (~BIT1);
+							}
+							if(   (target_pkt.word_en&BIT2)^(match_word_en&BIT2) )
+							{
+								tmp_word_en &= (~BIT2);
+							}						
+							if(   (target_pkt.word_en&BIT3)^(match_word_en&BIT3) )
+							{
+								tmp_word_en &=(~BIT3);
+							}							
+						
+							if((tmp_word_en&0x0F)!=0x0F){
+								efuse_addr = efuse_GetCurrentSize(dev);
+								target_pkt.offset = offset;
+								target_pkt.word_en= tmp_word_en;					
+							}else{								
+								bContinual = false;
+							}
+							#if (EFUSE_ERROE_HANDLE == 1)
+							WriteState=PG_STATE_HEADER;
+							repeat_times++;
+							if(repeat_times>EFUSE_REPEAT_THRESHOLD_){
+								bContinual = false;
+								bResult = false;
+							}
+							#endif
+						}
+						else{
+							efuse_addr = efuse_addr + (2*tmp_word_cnts) +1;
+							target_pkt.offset = offset;
+							target_pkt.word_en= target_pkt.word_en;					
+							#if (EFUSE_ERROE_HANDLE == 1)
+							WriteState=PG_STATE_HEADER;
+							#endif
+						}		
+					}				
+				}				
+				printk("EFUSE PG_STATE_HEADER-1\n");
+			}
+			else		
+			{
+				pg_header = ((target_pkt.offset << 4)&0xf0) |target_pkt.word_en;
+
+				efuse_OneByteWrite(dev,efuse_addr, pg_header);
+				efuse_OneByteRead(dev,efuse_addr, &tmp_header);		
+		
+				if(tmp_header == pg_header)
+				{ 
+					WriteState = PG_STATE_DATA;						
+				}				
+				#if (EFUSE_ERROE_HANDLE == 1)
+				else if(tmp_header == 0xFF){
+					WriteState = PG_STATE_HEADER;					
+					repeat_times++;
+					if(repeat_times>EFUSE_REPEAT_THRESHOLD_){
+						bContinual = false;
+						bResult = false;
+					}
+				}
+				#endif
+				else
+				{
+					tmp_pkt.offset = (tmp_header>>4) & 0x0F;
+					tmp_pkt.word_en=  tmp_header & 0x0F;					
+					tmp_word_cnts =  efuse_CalculateWordCnts(tmp_pkt.word_en);
+																											
+					memset(originaldata,0xff,sizeof(u8)*8);
+					
+					if(efuse_PgPacketRead( dev, tmp_pkt.offset,originaldata))
+					{	
+						badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,tmp_pkt.word_en,originaldata);	
+						if(0x0F != (badworden&0x0F))
+						{														
+							u8 reorg_offset = tmp_pkt.offset;
+							u8 reorg_worden=badworden;								
+							efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata);	
+							efuse_addr = efuse_GetCurrentSize(dev);	 
+						}
+						else{
+							efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; 
+						}
+					}
+					else
+					{
+						efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; 
+					}
+
+					#if (EFUSE_ERROE_HANDLE == 1)
+					WriteState=PG_STATE_HEADER;	
+					repeat_times++;
+					if(repeat_times>EFUSE_REPEAT_THRESHOLD_){
+						bContinual = false;
+						bResult = false;
+					}
+					#endif
+					
+					printk("EFUSE PG_STATE_HEADER-2\n");
+				}
+
+			}
+
+		}
+		else if(WriteState==PG_STATE_DATA) 
+		{	
+			printk("EFUSE PG_STATE_DATA\n");
+			badworden = 0x0f;
+			badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,target_pkt.word_en,target_pkt.data);	
+			if((badworden&0x0F)==0x0F)
+			{ 
+				bContinual = false;
+			}
+			else
+			{
+				efuse_addr = efuse_addr + (2*target_word_cnts) +1;
+										
+				target_pkt.offset = offset;
+				target_pkt.word_en= badworden;		
+				target_word_cnts =  efuse_CalculateWordCnts(target_pkt.word_en); 
+				#if (EFUSE_ERROE_HANDLE == 1)
+				WriteState=PG_STATE_HEADER;	
+				repeat_times++;
+				if(repeat_times>EFUSE_REPEAT_THRESHOLD_){
+					bContinual = false;
+					bResult = false;
+				}
+				#endif
+				printk("EFUSE PG_STATE_HEADER-3\n");
+			}
+		}
+	}
+
+	
+	return true;
+}	
+
+
+static	void
+efuse_WordEnableDataRead(	u8 word_en,u8 *sourdata,u8 *targetdata)
+{	
+
+
+
+	if (!(word_en&BIT0))
+	{
+		targetdata[0] = sourdata[0];
+		targetdata[1] = sourdata[1];
+	}
+	if (!(word_en&BIT1))
+	{
+		targetdata[2] = sourdata[2];
+		targetdata[3] = sourdata[3];
+	}
+	if (!(word_en&BIT2))
+	{
+		targetdata[4] = sourdata[4];
+		targetdata[5] = sourdata[5];
+	}
+	if (!(word_en&BIT3))
+	{
+		targetdata[6] = sourdata[6];
+		targetdata[7] = sourdata[7];
+	}
+}	
+
+
+static	u8
+efuse_WordEnableDataWrite(	struct net_device*	dev,	u16 efuse_addr, u8 word_en, u8 *data)
+{		
+	u16 tmpaddr = 0;
+	u16 start_addr = efuse_addr;
+	u8 badworden = 0x0F;
+	u8 tmpdata[8]; 
+	
+	memset(tmpdata,0xff,PGPKT_DATA_SIZE);
+	
+
+
+	if(!(word_en&BIT0))
+	{
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(dev,start_addr++, data[0]);
+		efuse_OneByteWrite(dev,start_addr++, data[1]);
+
+		efuse_OneByteRead(dev,tmpaddr, &tmpdata[0]);
+		efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[1]);
+		if((data[0]!=tmpdata[0])||(data[1]!=tmpdata[1])){
+			badworden &= (~BIT0);
+		}
+	}
+	if(!(word_en&BIT1))
+	{
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(dev,start_addr++, data[2]);
+		efuse_OneByteWrite(dev,start_addr++, data[3]);
+				
+		efuse_OneByteRead(dev,tmpaddr    , &tmpdata[2]);
+		efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[3]);
+		if((data[2]!=tmpdata[2])||(data[3]!=tmpdata[3])){
+			badworden &=( ~BIT1);
+		}
+	}
+	if(!(word_en&BIT2))
+	{
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(dev,start_addr++, data[4]);
+		efuse_OneByteWrite(dev,start_addr++, data[5]);
+
+		efuse_OneByteRead(dev,tmpaddr, &tmpdata[4]);							
+		efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[5]);
+		if((data[4]!=tmpdata[4])||(data[5]!=tmpdata[5])){
+			badworden &=( ~BIT2);
+		}
+	}
+	if(!(word_en&BIT3))
+	{
+		tmpaddr = start_addr;
+		efuse_OneByteWrite(dev,start_addr++, data[6]);
+		efuse_OneByteWrite(dev,start_addr++, data[7]);
+
+		efuse_OneByteRead(dev,tmpaddr, &tmpdata[6]);
+		efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[7]);
+		if((data[6]!=tmpdata[6])||(data[7]!=tmpdata[7])){
+			badworden &=( ~BIT3);
+		}
+	}
+	return badworden;
+}	
+
+
+static	void
+efuse_PowerSwitch(struct net_device* dev, u8 PwrState)
+{
+	u8	tempval;
+	if (PwrState == true)
+	{
+		tempval = read_nic_byte(dev, EFUSE_TEST+3);
+		write_nic_byte(dev, EFUSE_TEST+3, (tempval | 0x80));
+
+		write_nic_byte(dev, EFUSE_CLK, 0x03);
+	}
+	else
+	{
+		tempval = read_nic_byte(dev, EFUSE_TEST+3);
+		write_nic_byte(dev, EFUSE_TEST+3, (tempval & 0x7F));
+
+		write_nic_byte(dev, EFUSE_CLK, 0x02);
+	}	
+	
+}	/* efuse_PowerSwitch */
+
+
+static	u16
+efuse_GetCurrentSize(struct net_device*	dev)
+{
+	bool bContinual = true;
+
+	u16 efuse_addr = 0;
+	u8 hoffset=0,hworden=0;	
+	u8 efuse_data,word_cnts=0;
+		
+	
+	while (	bContinual && 
+			efuse_OneByteRead(dev, efuse_addr ,&efuse_data) && 
+			(efuse_addr  < EFUSE_MAX_SIZE) )
+	{			
+		if(efuse_data!=0xFF)
+		{					
+			hoffset = (efuse_data>>4) & 0x0F;
+			hworden =  efuse_data & 0x0F;									
+			word_cnts = efuse_CalculateWordCnts(hworden);
+			efuse_addr = efuse_addr + (word_cnts*2)+1;						
+		}
+		else
+		{
+			bContinual = false ;			
+		}
+	}
+
+	
+	return efuse_addr;
+	
+}	
+
+
+static u8
+efuse_CalculateWordCnts(u8	word_en)
+{
+	u8 word_cnts = 0;
+	if(!(word_en & BIT0))	word_cnts++; 
+	if(!(word_en & BIT1))	word_cnts++;
+	if(!(word_en & BIT2))	word_cnts++;
+	if(!(word_en & BIT3))	word_cnts++;
+	return word_cnts;
+}	
+
+
+#if 0
+static void efuse_ResetLoader(struct net_device* dev)
+{
+	u16	tmpU2b;
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b&~(BIT12)));
+	mdelay(10);
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT12));
+	mdelay(10);
+	
+}	
+#endif
+
+ #ifdef TO_DO_LIST
+extern	bool	
+EFUSE_ProgramMap(struct net_device* dev, char* pFileName,u8	TableType)		
+{
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	s4Byte			nLinesRead, ithLine;
+	RT_STATUS		rtStatus = RT_STATUS_SUCCESS;
+	char* 			szLine;
+	u32			u4bRegValue, u4RegMask;
+	u32			u4bMove;
+	u16			index = 0;
+	u16			i;
+	u8			eeprom[HWSET_MAX_SIZE_92S];	
+	
+	rtStatus = PlatformReadFile(
+					dev, 
+					pFileName,
+					(u8*)(priv->BufOfLines),
+					MAX_LINES_HWCONFIG_TXT,
+					MAX_BYTES_LINE_HWCONFIG_TXT,
+					&nLinesRead
+					);
+
+	if(rtStatus == RT_STATUS_SUCCESS)
+	{	
+		memcp(pHalData->BufOfLines3, pHalData->BufOfLines,
+			nLinesRead*MAX_BYTES_LINE_HWCONFIG_TXT);
+		pHalData->nLinesRead3 = nLinesRead;
+	}
+
+	if(rtStatus == RT_STATUS_SUCCESS)
+	{		
+		printk("szEepromFile(): read %s ok\n", pFileName);
+		for(ithLine = 0; ithLine < nLinesRead; ithLine++)
+		{
+			szLine = pHalData->BufOfLines[ithLine];
+			printk("Line-%d String =%s\n", ithLine, szLine);
+			
+			if(!IsCommentString(szLine))
+			{
+				for (i = 0; i < 8; i++)
+				{
+					u32	j;
+
+					efuse_ParsingMap(szLine, &u4bRegValue, &u4bMove);
+
+					szLine += u4bMove;
+					eeprom[index++] = (u8)(u4bRegValue&0xff);
+					eeprom[index++] = (u8)((u4bRegValue>>8)&0xff);
+					
+					printk("Addr-%d = %x\n", (ithLine*8+i), u4bRegValue);
+				}
+			}
+			
+		}
+	
+	}
+	else
+	{
+		printk("szEepromFile(): Fail read%s\n", pFileName);
+		return	RT_STATUS_FAILURE;
+	}
+
+
+
+	if (TableType == 1)
+	{
+		efuse_WriteAllMap(dev, eeprom, HWSET_MAX_SIZE_92S);
+	}
+	else
+	{
+		for (i = 0; i < HWSET_MAX_SIZE_92S; i++)
+			EFUSE_ShadowWrite(dev, 1, i, (u32)eeprom[i]);
+	}
+	
+	return	rtStatus;
+}	/* EFUSE_ProgramMap */
+
+#endif
+
+bool IsHexDigit(	char chTmp)
+{
+	if( (chTmp >= '0' && chTmp <= '9') ||  
+		(chTmp >= 'a' && chTmp <= 'f') ||
+		(chTmp >= 'A' && chTmp <= 'F') )
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+u32 MapCharToHexDigit(char chTmp)
+{
+	if(chTmp >= '0' && chTmp <= '9')
+		return (chTmp - '0');
+	else if(chTmp >= 'a' && chTmp <= 'f')
+		return (10 + (chTmp - 'a'));
+	else if(chTmp >= 'A' && chTmp <= 'F') 
+		return (10 + (chTmp - 'A'));
+	else
+		return 0;	
+}
+
+#ifdef TO_DO_LIST
+static	bool	
+efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove)
+{
+	char* 		szScan = szStr;
+
+	if(szStr == NULL || pu4bVal == NULL || pu4bMove == NULL)
+	{
+		return false;
+	}
+
+	*pu4bMove = 0;
+	*pu4bVal = 0;
+
+	while(	*szScan != '\0' && 
+			(*szScan == ' ' || *szScan == '\t') )
+	{
+		szScan++;
+		(*pu4bMove)++;
+	}
+
+	if(!IsHexDigit(*szScan))
+	{
+		return false;
+	}
+
+	do
+	{
+		(*pu4bVal) <<= 4;
+		*pu4bVal += MapCharToHexDigit(*szScan);
+
+		szScan++;
+		(*pu4bMove)++;
+	} while(IsHexDigit(*szScan));
+
+	return true;
+	
+}	/* efuse_ParsingMap */
+#endif
+
+int efuse_one_byte_rw(struct net_device* dev, u8 bRead, u16 addr, u8 *data)
+{
+	u32 bResult;
+	u8 tmpidx = 0;
+	u8 tmpv8=0;
+	
+
+	write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff));		
+	tmpv8 = ((u8)((addr>>8) &0x03) ) | (read_nic_byte(dev, EFUSE_CTRL+2)&0xFC );	
+	write_nic_byte(dev, EFUSE_CTRL+2, tmpv8);
+
+	if(true==bRead){
+		
+		write_nic_byte(dev, EFUSE_CTRL+3,  0x72);
+
+		while(!(0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){
+			tmpidx++;
+		}
+		if(tmpidx<100){			
+			*data=read_nic_byte(dev, EFUSE_CTRL);
+			bResult = true;
+		}
+		else
+		{
+			*data = 0;
+			bResult = false;
+		}
+		
+	}
+	else{
+		write_nic_byte(dev, EFUSE_CTRL, *data);
+		
+		write_nic_byte(dev, EFUSE_CTRL+3, 0xF2);
+		
+		while((0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){
+			tmpidx++;
+		}
+		if(tmpidx<100)
+		{			
+			*data=read_nic_byte(dev, EFUSE_CTRL);
+			bResult = true;
+		}
+		else
+		{
+			*data = 0;
+			bResult = false;
+		}
+		
+	}
+	return bResult;	
+}
+void efuse_access(struct net_device* dev, u8 bRead,u16 start_addr, u8 cnts, u8 *data)
+{
+	u8	efuse_clk_ori,efuse_clk_new;
+	u32 i = 0;
+
+	if(start_addr>0x200) return;
+	efuse_clk_ori = read_nic_byte(dev,SYS_FUNC_EN+1);
+	efuse_clk_new = efuse_clk_ori|0x20;
+	
+	if(efuse_clk_new!= efuse_clk_ori){
+		write_nic_byte(dev, SYS_FUNC_EN+1, efuse_clk_new);
+	}
+#ifdef _POWERON_DELAY_
+	mdelay(10);
+#endif	
+	write_nic_byte(dev, EFUSE_TEST+3, (read_nic_byte(dev, EFUSE_TEST+3)|0x80));
+	write_nic_byte(dev, EFUSE_CLK_CTRL, (read_nic_byte(dev, EFUSE_CLK_CTRL)|0x03));
+	
+#ifdef _PRE_EXECUTE_READ_CMD_
+	{
+		unsigned char tmpdata;
+		efuse_OneByteRead(dev, 0,&tmpdata);
+	}		
+#endif	
+	
+	for(i=0;i<cnts;i++){		
+		efuse_one_byte_rw(dev,bRead, start_addr+i , data+i);		
+	}
+	write_nic_byte(dev, EFUSE_TEST+3, read_nic_byte(dev, EFUSE_TEST+3)&0x7f);
+	write_nic_byte(dev, EFUSE_CLK_CTRL, read_nic_byte(dev, EFUSE_CLK_CTRL)&0xfd);
+			
+	if(efuse_clk_new != efuse_clk_ori)	write_nic_byte(dev, 0x10250003, efuse_clk_ori);
+	
+}
+
+#ifdef TO_DO_LIST
+static	void efuse_reg_ctrl(struct net_device* dev, u8 bPowerOn)
+{		
+	if(true==bPowerOn){
+		write_nic_byte(dev, SYS_FUNC_EN+1,  read_nic_byte(dev,SYS_FUNC_EN+1)|0x20);
+#ifdef _POWERON_DELAY_	
+		mdelay(10);	
+#endif
+		write_nic_byte(dev, EFUSE_TEST+4, (read_nic_byte(dev, EFUSE_TEST+4)|0x80));
+		write_nic_byte(dev, EFUSE_CLK_CTRL, (read_nic_byte(dev, EFUSE_CLK_CTRL)|0x03));
+#ifdef _PRE_EXECUTE_READ_CMD_
+		{
+			unsigned char tmpdata;
+			efuse_OneByteRead(dev, 0,&tmpdata);
+		}
+		
+#endif
+	}
+	else{
+		write_nic_byte(dev, EFUSE_TEST+4, read_nic_byte(dev, EFUSE_TEST+4)&0x7f);
+		write_nic_byte(dev, EFUSE_CLK_CTRL, read_nic_byte(dev, EFUSE_CLK_CTRL)&0xfd);
+
+	}
+
+	
+}
+#endif
+
+void efuse_read_data(struct net_device* dev,u8 efuse_read_item,u8 *data,u32 data_size)
+{
+	u8 offset, word_start,byte_start,byte_cnts;
+	u8	efusedata[EFUSE_REAL_CONTENT_LEN];
+	u8 *tmpdata = NULL;
+
+	u8 pg_pkt_cnts ;
+	
+	u8 tmpidx;
+	u8 pg_data[8];
+
+	if(efuse_read_item>  (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){
+		return ;
+	}
+		
+	offset		= RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].offset ;
+	word_start	= RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].word_start;
+	byte_start 	= RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_start;
+	byte_cnts   	= RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_cnts;
+
+	if(data_size!=byte_cnts){
+		return;		
+	}
+	
+	pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1;		
+	
+	if(pg_pkt_cnts > 1){
+		tmpdata = efusedata;
+
+		if(tmpdata!=NULL)
+		{
+			memset(tmpdata,0xff,pg_pkt_cnts*PGPKT_DATA_SIZE);	
+						
+			for(tmpidx=0;tmpidx<pg_pkt_cnts;tmpidx++)
+			{				
+				memset(pg_data,0xff,PGPKT_DATA_SIZE);
+				if(true== efuse_PgPacketRead(dev,offset+tmpidx,pg_data))
+				{	
+					memcpy(tmpdata+(PGPKT_DATA_SIZE*tmpidx),pg_data,PGPKT_DATA_SIZE);
+				}
+			}
+			memcpy(data,(tmpdata+ (2*word_start)+byte_start ),data_size);					
+		}		
+	}
+	else
+	{
+		memset(pg_data,0xff,PGPKT_DATA_SIZE);
+		if(true==efuse_PgPacketRead(dev,offset,pg_data)){	
+			memcpy(data,pg_data+ (2*word_start)+byte_start ,data_size);
+		}
+	}	
+	
+}
+void efuse_write_data(struct net_device* dev,u8 efuse_write_item,u8 *data,u32 data_size,u32 bWordUnit)
+{
+	u8 offset, word_start,byte_start,byte_cnts;	
+	u8 word_en = 0x0f,word_cnts;
+	u8 pg_pkt_cnts ;
+	
+	u8 tmpidx,tmpbitmask;
+	u8 pg_data[8],tmpbytes=0;
+
+	if(efuse_write_item>  (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){
+		return ;
+	}
+	
+	offset		= RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].offset ;
+	word_start	= RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].word_start;
+	byte_start 	= RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_start;
+	byte_cnts   	= RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_cnts;
+	
+	if(data_size >  byte_cnts){
+		return;		
+	}
+	pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1;	
+	word_cnts = byte_cnts /2 ;
+
+	if(byte_cnts %2){
+		word_cnts+=1;
+	}		
+	if((byte_start==1)||((byte_cnts%2)==1)){
+
+		if((efuse_write_item==EFUSE_F0CIS)||(efuse_write_item==EFUSE_F1CIS)){
+			memset(pg_data,0xff,PGPKT_DATA_SIZE);
+			efuse_PgPacketRead(dev,offset,pg_data);		
+			
+			if(efuse_write_item==EFUSE_F0CIS){
+				word_en = 0x07;
+				memcpy(pg_data+word_start*2+byte_start,data,sizeof(u8)*2);
+				efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2));	
+
+				word_en = 0x00;
+				efuse_PgPacketWrite(dev,(offset+1),word_en,data+2);
+
+				word_en = 0x00;
+				efuse_PgPacketRead(dev,offset+2,pg_data);
+				memcpy(pg_data,data+2+8,sizeof(u8)*7);
+				
+				efuse_PgPacketWrite(dev,(offset+2),word_en,pg_data);
+			}
+			else if(efuse_write_item==EFUSE_F1CIS){
+				word_en = 0x07;
+				efuse_PgPacketRead(dev,offset,pg_data);
+				pg_data[7] = data[0];
+				efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2));	
+				
+				word_en = 0x00;
+				for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++){
+					efuse_PgPacketWrite(dev,(offset+1+tmpidx),word_en,data+1+(tmpidx*PGPKT_DATA_SIZE));
+				}				
+			}
+			
+		}
+		else{			
+			memset(pg_data,0xff,PGPKT_DATA_SIZE);
+			if((efuse_write_item==EFUSE_SDIO_SETTING)||(efuse_write_item==EFUSE_CCCR)){
+				word_en = 0x0e ;
+				tmpbytes = 2;
+			}
+			else if(efuse_write_item == EFUSE_SDIO_MODE){
+				word_en = 0x0d ;
+				tmpbytes = 2;
+			}
+			else if(efuse_write_item == EFUSE_OCR){
+				word_en = 0x09 ;
+				tmpbytes = 4;
+			}
+			else if((efuse_write_item == EFUSE_EEPROM_VER)||(efuse_write_item==EFUSE_CHAN_PLAN)){
+				word_en = 0x07 ;
+				tmpbytes = 2;
+			}
+			if(bWordUnit==true){
+				memcpy(pg_data+word_start*2 ,data,sizeof(u8)*tmpbytes);
+			}
+			else{																
+				efuse_PgPacketRead(dev,offset,pg_data);
+				memcpy(pg_data+(2*word_start)+byte_start,data,sizeof(u8)*byte_cnts);			
+			}
+					
+			efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2));	
+			
+		}		
+		
+	}
+	else if(pg_pkt_cnts>1){
+		if(word_start==0){
+			word_en = 0x00;
+			for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++)
+			{
+				efuse_PgPacketWrite(dev,(offset+tmpidx),word_en,data+(tmpidx*PGPKT_DATA_SIZE));
+			}
+			word_en = 0x0f;
+			for(tmpidx= 0; tmpidx<(word_cnts%4) ; tmpidx++)
+			{
+				tmpbitmask =tmpidx;
+				word_en &= (~(EFUSE_BIT(tmpbitmask)));
+			}		
+			efuse_PgPacketWrite(dev,offset+(word_cnts/4),word_en,data+((word_cnts/4)*PGPKT_DATA_SIZE));
+		}else
+		{
+
+		}
+	}
+	else{
+		word_en = 0x0f;
+		for(tmpidx= 0; tmpidx<word_cnts ; tmpidx++)
+		{			
+			tmpbitmask = word_start + tmpidx ;
+			word_en &= (~(EFUSE_BIT(tmpbitmask)));
+		}
+		efuse_PgPacketWrite(dev,offset,word_en,data);
+	}
+		
+}
+
+void efuset_test_func_read(struct net_device* dev)
+{
+	u8 chipid[2];
+	u8 ocr[3];
+	u8 macaddr[6];	
+	u8 txpowertable[28];
+	
+	memset(chipid,0,sizeof(u8)*2);	
+	efuse_read_data(dev,EFUSE_CHIP_ID,chipid,sizeof(chipid));
+	
+	memset(ocr,0,sizeof(u8)*3);	
+	efuse_read_data(dev,EFUSE_CCCR,ocr,sizeof(ocr));
+
+	memset(macaddr,0,sizeof(u8)*6);
+	efuse_read_data(dev,EFUSE_MAC_ADDR,macaddr,sizeof(macaddr));
+	
+	memset(txpowertable,0,sizeof(u8)*28);
+	efuse_read_data(dev,EFUSE_TXPW_TAB,txpowertable,sizeof(txpowertable));
+}
+
+void efuset_test_func_write(struct net_device* dev)
+{
+	u32 bWordUnit = true;	
+	u8 CCCR=0x02,SDIO_SETTING = 0xFF;
+	u8 tmpdata[2];
+	
+	u8 macaddr[6] = {0x00,0xe0,0x4c,0x87,0x12,0x66};	
+	efuse_write_data(dev,EFUSE_MAC_ADDR,macaddr,sizeof(macaddr),bWordUnit);
+
+	bWordUnit = false;
+	efuse_write_data(dev,EFUSE_CCCR,&CCCR,sizeof(u8),bWordUnit);
+	
+	bWordUnit = false;
+	efuse_write_data(dev,EFUSE_SDIO_SETTING,&SDIO_SETTING,sizeof(u8),bWordUnit);
+
+	bWordUnit = true;	
+	tmpdata[0] =SDIO_SETTING ;
+	tmpdata[1] =CCCR ;
+	efuse_write_data(dev,EFUSE_SDIO_SETTING,tmpdata,sizeof(tmpdata),bWordUnit);
+	
+}
+#endif	
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_scan.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_scan.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL8192SE_SCAN
+#define _RTL8192SE_SCAN
+
+void rtl8192se_hw_scan_simu(void *data);
+void rtl8192se_rx_surveydone_cmd(struct net_device *dev);
+void	rtl8192se_check_hw_scan(void *data);
+void rtl8192se_start_hw_scan(void *data);
+void rtl8192se_abort_hw_scan(struct net_device *dev);
+void rtl8192se_hw_scan_initiate(struct net_device *dev);
+void rtl8192se_send_scan_abort(struct net_device *dev);
+void rtl8192se_cancel_hw_scan(struct net_device *dev);
+
+#endif
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_dev.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_dev.c
@@ -0,0 +1,5004 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "../rtl_core.h"
+#include "../rtl_dm.h"
+#include "../rtl_wx.h"
+#include "r8192S_phy.h"
+#include "r8192S_phyreg.h"
+#include "r8192S_rtl6052.h"
+#include "r8192S_Efuse.h"
+
+#ifdef _RTL8192_EXT_PATCH_
+#include "../../../mshclass/msh_class.h"
+#include "../rtl_mesh.h"
+#endif
+
+extern int WDCAPARA_ADD[];
+
+void rtl8192se_start_beacon(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_network *net = &priv->rtllib->current_network;
+	u16 BcnTimeCfg = 0;
+        u16 BcnCW = 6;
+        u16 BcnIFS = 0xf;
+
+	DMESG("Enabling beacon TX");
+	rtl8192_irq_disable(dev);
+
+	write_nic_word(dev, ATIMWND, 2);
+
+	write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+	PHY_SetBeaconHwReg(dev, net->beacon_interval);
+
+#ifdef RTL8192SE
+	write_nic_word(dev, BCN_DRV_EARLY_INT, 10<<4);
+#else
+	write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
+#endif
+	write_nic_word(dev, BCN_DMATIME, 256); 
+
+	write_nic_byte(dev, BCN_ERR_THRESH, 100);	
+
+#if 1
+	switch(priv->rtllib->iw_mode)
+	{
+		case IW_MODE_ADHOC:
+		case IW_MODE_MESH:
+			BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
+			break;
+		default:
+			printk("Invalid Operation Mode!!\n");
+			break;
+	}
+
+	BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+
+
+	{
+		u8 u1Temp = (u8)(net->beacon_interval);
+		write_nic_dword(dev, WFM5, 0xF1000000 |((u16)( u1Temp) << 8));
+		ChkFwCmdIoDone(dev);
+	}
+#else	
+	BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
+	BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+	write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+#endif	
+	rtl8192_irq_enable(dev);
+}
+
+void rtl8192se_update_msr(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8 msr;
+	LED_CTL_MODE	LedAction = LED_CTL_NO_LINK;
+	msr  = read_nic_byte(dev, MSR);
+	msr &= ~ MSR_LINK_MASK;
+	
+	switch (priv->rtllib->iw_mode) {
+	case IW_MODE_INFRA:
+		if (priv->rtllib->state == RTLLIB_LINKED)
+			msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
+		else
+			msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+		LedAction = LED_CTL_LINK;
+		break;
+	case IW_MODE_ADHOC:
+		if (priv->rtllib->state == RTLLIB_LINKED)
+			msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT);
+		else
+			msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+		break;
+	case IW_MODE_MASTER:
+		if (priv->rtllib->state == RTLLIB_LINKED)
+			msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT);
+		else
+			msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+		break;
+#ifdef _RTL8192_EXT_PATCH_
+	case IW_MODE_MESH:
+		printk("%s: iw_mode=%d state=%d only_mesh=%d mesh_state=%d\n", __FUNCTION__,priv->rtllib->iw_mode,priv->rtllib->state, priv->rtllib->only_mesh, priv->rtllib->mesh_state); 
+		if (priv->rtllib->only_mesh) {
+			if (priv->rtllib->mesh_state == RTLLIB_MESH_LINKED)
+				msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT); 
+			else
+				msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
+		} else {
+			if (priv->rtllib->mesh_state == RTLLIB_MESH_LINKED) {
+				msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT);
+			} else {	
+				msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+			}
+			if (priv->rtllib->state == RTLLIB_LINKED)
+				msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
+		}
+		break;
+#endif			
+	default:
+		break;
+	}
+
+	write_nic_byte(dev, MSR, msr);
+	if(priv->rtllib->LedControlHandler)
+		priv->rtllib->LedControlHandler(dev, LedAction);
+}
+
+static void rtl8192se_config_hw_for_load_fail(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16			i;
+	u8 			sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x92, 0x00};
+	u8			rf_path, index;
+	u32			tmp1111 = 0;
+	u32			tmp2222 = 0;
+
+	RT_TRACE(COMP_INIT, "====> rtl8192se_config_hw_for_load_fail\n");
+
+	for(;tmp2222<0xff;tmp2222+=4)
+	{
+		tmp1111= read_nic_dword(dev, tmp2222);
+	}
+
+	write_nic_byte(dev, SYS_ISO_CTRL+1, 0xE8); 
+	mdelay(10);
+	write_nic_byte(dev, PMC_FSM, 0x02); 
+	
+	priv->eeprom_vid= 0;
+	priv->eeprom_did= 0;		
+	priv->eeprom_ChannelPlan= 0;
+	priv->eeprom_CustomerID= 0;	
+
+       get_random_bytes(&sMacAddr[5], 1);
+	for(i = 0; i < 6; i++)
+		dev->dev_addr[i] = sMacAddr[i];			
+
+
+	priv->rf_type= RTL819X_DEFAULT_RF_TYPE;	
+	priv->rf_chip = RF_6052;
+
+#if (EEPROM_OLD_FORMAT_SUPPORT == 1)
+	for(i=0; i<14; i++)
+	{
+		priv->EEPROMTxPowerLevelCCK[i] = (u8)(EEPROM_Default_TxPower & 0xff);
+		RT_TRACE(COMP_INIT, "CCK 2.4G Tx Pwr Index %d = 0x%02x\n", 
+		i, priv->EEPROMTxPowerLevelCCK[i]);
+	}			
+
+	for(i=0; i<14; i++)
+	{
+		priv->EEPROMTxPowerLevelOFDM24G[i] = (u8)(EEPROM_Default_TxPower & 0xff);
+		RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Pwr Index %d = 0x%02x\n", 
+		i, priv->EEPROMTxPowerLevelOFDM24G[i]);				
+	}	
+
+	for(i=0; i<14; i++)
+	{			
+		priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i];
+		priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i];
+	}	
+	for(i=0; i<6; i++)
+	{
+		priv->EEPROMHT2T_TxPwr[i] = EEPROM_Default_HT2T_TxPwr;
+	}
+	
+#else
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for (i = 0; i < 3; i++)
+		{
+			priv->RfCckChnlAreaTxPwr[rf_path][i] = 
+			priv->RfOfdmChnlAreaTxPwr1T[rf_path][i] = 
+			priv->RfOfdmChnlAreaTxPwr2T[rf_path][i] = 
+			EEPROM_Default_TxPowerLevel;
+		}
+	}	
+				
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for(i=0; i<14; i++)	
+		{
+			if (i < 3)			
+				index = 0;
+			else if (i < 8)		
+				index = 1;
+			else				
+				index = 2;
+
+			priv->RfTxPwrLevelCck[rf_path][i]  = 
+			priv->RfCckChnlAreaTxPwr[rf_path][index] = 
+			priv->RfTxPwrLevelOfdm1T[rf_path][i]  = 
+			priv->RfOfdmChnlAreaTxPwr1T[rf_path][index] = 
+			priv->RfTxPwrLevelOfdm2T[rf_path][i]  = 
+			priv->RfOfdmChnlAreaTxPwr2T[rf_path][index] = 
+			(u8)(EEPROM_Default_TxPower & 0xff);				
+
+			if (rf_path == 0)
+			{
+				priv->TxPowerLevelOFDM24G[i] = (u8)(EEPROM_Default_TxPower & 0xff);
+				priv->TxPowerLevelCCK[i] = (u8)(EEPROM_Default_TxPower & 0xff);
+			}
+		}
+		
+	}
+	
+	RT_TRACE(COMP_INIT, "All TxPwr = 0x%x\n", EEPROM_Default_TxPower);
+
+	for(i=0; i<14; i++)	
+	{			
+		priv->TxPwrHt20Diff[RF90_PATH_A][i] = DEFAULT_HT20_TXPWR_DIFF;
+		priv->TxPwrHt20Diff[RF90_PATH_B][i] = DEFAULT_HT20_TXPWR_DIFF;
+
+		priv->TxPwrLegacyHtDiff[0][i] = EEPROM_Default_LegacyHTTxPowerDiff;
+		priv->TxPwrLegacyHtDiff[1][i] = EEPROM_Default_LegacyHTTxPowerDiff;
+	}
+	
+	priv->TxPwrSafetyFlag = 0;
+#endif
+	
+	priv->EEPROMTxPowerDiff = EEPROM_Default_LegacyHTTxPowerDiff;
+	priv->LegacyHTTxPowerDiff = priv->EEPROMTxPowerDiff;
+	RT_TRACE(COMP_INIT, "TxPowerDiff = %#x\n", priv->EEPROMTxPowerDiff);
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for (i = 0; i < 3; i++)
+		{
+			priv->EEPROMPwrGroup[rf_path][i] = 0;
+		}
+	}
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for(i=0; i<14; i++)
+		{
+			if (i < 3)			
+				index = 0;
+			else if (i < 8)		
+				index = 1;
+			else				
+				index = 2;
+			priv->PwrGroupHT20[rf_path][i] = (priv->EEPROMPwrGroup[rf_path][index]&0xf);
+			priv->PwrGroupHT40[rf_path][i] = ((priv->EEPROMPwrGroup[rf_path][index]&0xf0)>>4);
+		}
+	}
+	priv->EEPROMRegulatory = 0;
+
+	priv->EEPROMTSSI_A = EEPROM_Default_TSSI;
+	priv->EEPROMTSSI_B = EEPROM_Default_TSSI;			
+
+	for(i=0; i<6; i++)
+	{
+		priv->EEPROMHT2T_TxPwr[i] = EEPROM_Default_HT2T_TxPwr;
+	}
+
+	
+	priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
+	priv->ThermalMeter[0] = (priv->EEPROMThermalMeter&0x1f);	
+	priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
+
+	priv->BluetoothCoexist = EEPROM_Default_BlueToothCoexist;
+	priv->EEPROMBluetoothType = EEPROM_Default_BlueToothType;
+	priv->EEPROMBluetoothAntNum = EEPROM_Default_BlueToothAntNum;
+	priv->EEPROMBluetoothAntIsolation = EEPROM_Default_BlueToothAntIso;
+	
+	priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap;
+	priv->CrystalCap = priv->EEPROMCrystalCap;
+
+	priv->eeprom_ChannelPlan = 0;
+	priv->eeprom_version = 1;		
+	priv->bTXPowerDataReadFromEEPORM = false;
+
+	priv->rf_type = RTL819X_DEFAULT_RF_TYPE;	
+	priv->rf_chip = RF_6052;
+	priv->eeprom_CustomerID = 0;
+	RT_TRACE(COMP_INIT, "EEPROM Customer ID: 0x%2x\n", priv->eeprom_CustomerID);
+
+			
+	priv->EEPROMBoardType = EEPROM_Default_BoardType;	
+	RT_TRACE(COMP_INIT, "BoardType = %#x\n", priv->EEPROMBoardType);
+
+	priv->LedStrategy = SW_LED_MODE7;
+
+	
+	RT_TRACE(COMP_INIT,"<==== rtl8192se_config_hw_for_load_fail\n");
+}
+
+static void rtl8192se_get_IC_Inferiority(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8  Efuse_ID;
+
+	priv->IC_Class = IC_INFERIORITY_A; 
+	if((priv->epromtype == EEPROM_BOOT_EFUSE) && !priv->AutoloadFailFlag) 
+	{
+		Efuse_ID = EFUSE_Read1Byte(dev, EFUSE_IC_ID_OFFSET);
+
+		if(Efuse_ID == 0xfe)
+		{
+			priv->IC_Class = IC_INFERIORITY_B;
+
+		}
+	}
+}
+
+void
+HalCustomizedBehavior8192S(struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	priv->rtllib->bForcedShowRateStill = false;
+	switch(priv->CustomerID)
+	{
+		case RT_CID_DEFAULT:
+			priv->LedStrategy = SW_LED_MODE7;
+			if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 &&
+				priv->eeprom_svid == 0x1A3B && priv->eeprom_smid == 0x1A07)
+			{
+				priv->RegWirelessMode = WIRELESS_MODE_G;
+				priv->rtllib->mode = WIRELESS_MODE_G;
+				priv->rtllib->bForcedBgMode = true;
+				priv->rtllib->bForcedShowRateStill = true;
+			}
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 &&
+					priv->eeprom_svid == 0x1A3B && priv->eeprom_smid == 0x1A04)
+			{
+				priv->RegWirelessMode = WIRELESS_MODE_G;	
+				priv->rtllib->mode = WIRELESS_MODE_G;
+				priv->rtllib->bForcedBgMode = true;
+				priv->rtllib->bForcedShowRateStill = true;
+			}
+			else if(priv->eeprom_svid == 0x1A3B && (priv->eeprom_smid == 0x1104 ||
+				priv->eeprom_smid == 0x1107))
+			{
+				priv->rtllib->bForcedShowRateStill = true;
+			}
+			else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8171 &&
+				priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7171){
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+				priv->rtllib->bForcedBgMode = true;
+			}else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8174 &&
+				priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7174){
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8174 &&
+				priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7150){
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8172 &&
+				priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7172){
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8172 &&
+				priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7186){
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}
+			break;
+			
+			break;
+			
+		case RT_CID_819x_Acer:
+			priv->LedStrategy = SW_LED_MODE7;	
+			break;
+			
+		case RT_CID_TOSHIBA:
+			priv->rtllib->current_network.channel = 10;
+			priv->LedStrategy = SW_LED_MODE7;
+			priv->EEPROMRegulatory = 1;		
+			if(priv->eeprom_smid >=  0x7000 && priv->eeprom_smid < 0x8000){
+				priv->RegWirelessMode = WIRELESS_MODE_G;
+				priv->rtllib->mode = WIRELESS_MODE_G;
+				priv->rtllib->bForcedBgMode = true;
+			}
+			break;
+		case RT_CID_CCX:
+			priv->DMFlag |= (HAL_DM_DIG_DISABLE | HAL_DM_HIPWR_DISABLE);
+			break;
+
+		case RT_CID_819x_Lenovo:
+			priv->LedStrategy = SW_LED_MODE7;
+			if(priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE025){
+				priv->RegWirelessMode = WIRELESS_MODE_G;
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}
+			break;
+
+		case RT_CID_819x_QMI:
+			priv->LedStrategy = SW_LED_MODE8;			
+			if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x897A){
+				priv->RegWirelessMode = WIRELESS_MODE_G;
+				 priv->RegWirelessMode = WIRELESS_MODE_G;	
+				 priv->rtllib->mode = WIRELESS_MODE_G;
+			}
+			break;
+
+		case RT_CID_819x_MSI:	
+			priv->LedStrategy = SW_LED_MODE9;			
+			break;
+
+		case RT_CID_819x_HP:
+			priv->LedStrategy = SW_LED_MODE7;
+			priv->bLedOpenDrain = true;
+			
+		case RT_CID_WHQL:
+			;
+			break;
+	
+		default:
+			RT_TRACE(COMP_INIT,"Unkown hardware Type \n");
+			break;
+	}
+}
+
+static	void rtl8192se_read_eeprom_info(struct net_device* dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16			i,usValue;
+	u16			EEPROMId;
+#if (EEPROM_OLD_FORMAT_SUPPORT == 1)
+	u8			tmpBuffer[30];	
+#endif
+	u8			tempval;
+	u8			hwinfo[HWSET_MAX_SIZE_92S];
+	u8			rf_path, index;	
+
+	RT_TRACE(COMP_INIT, "====> rtl8192se_read_eeprom_info\n");
+
+	if (priv->epromtype== EEPROM_93C46)
+	{	
+		write_nic_byte(dev, SYS_ISO_CTRL+1, 0xE8); 
+		mdelay(10);
+		write_nic_byte(dev, PMC_FSM, 0x02); 
+
+		RT_TRACE(COMP_INIT, "EEPROM\n");
+		for(i = 0; i < HWSET_MAX_SIZE_92S; i += 2)
+		{
+			usValue = eprom_read(dev, (u16) (i>>1));
+			*((u16*)(&hwinfo[i])) = usValue;					
+		}	
+	}
+	else if (priv->epromtype == EEPROM_BOOT_EFUSE)
+	{	
+		RT_TRACE(COMP_INIT, "EFUSE\n");
+
+		EFUSE_ShadowMapUpdate(dev);
+
+		memcpy( hwinfo, &priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S);		
+	}
+
+
+	EEPROMId = *((u16 *)&hwinfo[0]);
+	if( EEPROMId != RTL8190_EEPROM_ID )
+	{
+		RT_TRACE(COMP_ERR, "EEPROM ID(%#x) is invalid!!\n", EEPROMId); 
+		priv->AutoloadFailFlag=true;
+	}
+	else
+	{
+		RT_TRACE(COMP_EPROM, "Autoload OK\n"); 
+		priv->AutoloadFailFlag=false;
+	}	
+
+	if (priv->AutoloadFailFlag == true)
+	{
+		rtl8192se_config_hw_for_load_fail(dev);
+		return;
+	}
+
+	rtl8192se_get_IC_Inferiority(dev);
+	
+	priv->eeprom_vid		= *(u16 *)&hwinfo[EEPROM_VID];
+	priv->eeprom_did         = *(u16 *)&hwinfo[EEPROM_DID];
+	priv->eeprom_svid		= *(u16 *)&hwinfo[EEPROM_SVID];
+	priv->eeprom_smid		= *(u16 *)&hwinfo[EEPROM_SMID];
+	priv->eeprom_version 	= *(u16 *)&hwinfo[EEPROM_Version];
+
+	RT_TRACE(COMP_EPROM, "EEPROMId = 0x%4x\n", EEPROMId);
+	RT_TRACE(COMP_EPROM, "EEPROM VID = 0x%4x\n", priv->eeprom_vid);
+	RT_TRACE(COMP_EPROM, "EEPROM DID = 0x%4x\n", priv->eeprom_did);
+	RT_TRACE(COMP_EPROM, "EEPROM SVID = 0x%4x\n", priv->eeprom_svid);
+	RT_TRACE(COMP_EPROM, "EEPROM SMID = 0x%4x\n", priv->eeprom_smid);
+
+	priv->EEPROMOptional = *(u8 *)&hwinfo[EEPROM_Optional]; 
+    	priv->ShowRateMode = 2;
+	priv->rtllib->bForcedShowRxRate = false;
+
+	if(priv->ShowRateMode == 0) {
+	    if((priv->EEPROMOptional & BIT3) == 0x08/*0000_1000*/) {
+		priv->rtllib->bForcedShowRxRate = true;
+	    }
+	} else if(priv->ShowRateMode == 2){
+		  priv->rtllib->bForcedShowRxRate = true;
+	}
+	
+	for(i = 0; i < 6; i += 2)
+	{
+		usValue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR+i];
+		*((u16*)(&dev->dev_addr[i])) = usValue;
+	}
+	for (i=0;i<6;i++)
+		write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); 	
+
+	RT_TRACE(COMP_EPROM, "ReadAdapterInfo8192S(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n", 
+	dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], 
+	dev->dev_addr[4], dev->dev_addr[5]); 	
+
+#if (EEPROM_OLD_FORMAT_SUPPORT == 1)
+	for(i = 0; i < EEPROM_TX_PWR_INDEX_RANGE; i += 2)
+	{
+		usValue = *(u16 *)&hwinfo[EEPROM_TxPowerBase+i];
+		*((u16 *)(&tmpBuffer[i])) = usValue;					
+	}
+	for(i=0; i<14; i++)
+	{
+		priv->EEPROMTxPowerLevelCCK[i] = (u8)tmpBuffer[i];
+		priv->EEPROMTxPowerLevelOFDM24G[i] = (u8)tmpBuffer[i+14];
+	}
+		
+
+	for(i=0; i<14; i++)
+	{
+		priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i];
+		priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i];
+		
+		RT_TRACE(COMP_EPROM, "CH%d CCK Tx PWR IDX = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK[i]);
+		RT_TRACE(COMP_EPROM, "CH%d OFDM Tx PWR IDX = 0x%02x\n", i, priv->EEPROMTxPowerLevelOFDM24G[i]);
+	}
+
+	for(i = 0; i < 6; i += 2)
+	{
+		usValue = *(u16 *)&hwinfo[EEPROM_HT2T_CH1_A+i];
+		*((u16*)(&priv->EEPROMHT2T_TxPwr[i])) = usValue;
+	}		
+	for(i=0; i<6; i++)
+	{
+		RT_TRACE(COMP_EPROM, "EEPROMHT2T_TxPwr, Index %d = 0x%02x\n", i, priv->EEPROMHT2T_TxPwr[i]);					
+	}
+	
+#else	
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for (i = 0; i < 3; i++)
+		{
+			priv->RfCckChnlAreaTxPwr[rf_path][i] = 
+			hwinfo[EEPROM_TxPowerBase+rf_path*3+i];
+
+			priv->RfOfdmChnlAreaTxPwr1T[rf_path][i] = 
+			hwinfo[EEPROM_TxPowerBase+6+rf_path*3+i];
+
+			priv->RfOfdmChnlAreaTxPwr2T[rf_path][i] = 
+			hwinfo[EEPROM_TxPowerBase+12+rf_path*3+i];
+		}
+	}
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for (i = 0; i < 3; i++)
+		{
+			RT_TRACE(COMP_EPROM,"CCK RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
+			priv->RfCckChnlAreaTxPwr[rf_path][i]);
+			RT_TRACE(COMP_EPROM, "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
+			priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
+			RT_TRACE(COMP_EPROM,"OFDM-2T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
+			priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);			
+		}
+
+		for(i=0; i<14; i++)	
+		{
+			if (i < 3)			
+				index = 0;
+			else if (i < 8)		
+				index = 1;
+			else				
+				index = 2;
+
+			priv->RfTxPwrLevelCck[rf_path][i]  = 
+			priv->RfCckChnlAreaTxPwr[rf_path][index];
+			priv->RfTxPwrLevelOfdm1T[rf_path][i]  = 
+			priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
+			priv->RfTxPwrLevelOfdm2T[rf_path][i]  = 
+			priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
+
+			if (rf_path == 0)
+			{
+				priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ;
+				priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i];					
+                    }
+		}
+
+		for(i=0; i<14; i++)
+		{
+			RT_TRACE(COMP_EPROM, "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n", 
+			rf_path, i, priv->RfTxPwrLevelCck[rf_path][i], 
+			priv->RfTxPwrLevelOfdm1T[rf_path][i] ,
+			priv->RfTxPwrLevelOfdm2T[rf_path][i] );
+		}
+	}	
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for (i = 0; i < 3; i++)
+		{
+			priv->EEPROMPwrGroup[rf_path][i] = hwinfo[EEPROM_TxPWRGroup+rf_path*3+i];
+		}
+	}
+
+	for (rf_path = 0; rf_path < 2; rf_path++)
+	{
+		for(i=0; i<14; i++)
+		{
+			if (i < 3)			
+				index = 0;
+			else if (i < 8)		
+				index = 1;
+			else				
+				index = 2;
+			priv->PwrGroupHT20[rf_path][i] = (priv->EEPROMPwrGroup[rf_path][index]&0xf);
+			priv->PwrGroupHT40[rf_path][i] = ((priv->EEPROMPwrGroup[rf_path][index]&0xf0)>>4);
+			RT_TRACE(COMP_INIT, "RF-%d PwrGroupHT20[%d] = 0x%x\n", rf_path, i, priv->PwrGroupHT20[rf_path][i]);
+			RT_TRACE(COMP_INIT, "RF-%d PwrGroupHT40[%d] = 0x%x\n", rf_path, i, priv->PwrGroupHT40[rf_path][i]);
+		}
+	}
+
+	for(i=0; i<14; i++)	
+	{
+		if (i < 3)			
+			index = 0;
+			else if (i < 8)		
+			index = 1;
+		else				
+			index = 2;
+		
+		tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_HT20_DIFF+index])&0xff;
+		priv->TxPwrHt20Diff[RF90_PATH_A][i] = (tempval&0xF);
+		priv->TxPwrHt20Diff[RF90_PATH_B][i] = ((tempval>>4)&0xF);
+
+		if (i < 3)			
+			index = 0;
+		else if (i < 8)		
+			index = 0x11;
+		else				
+			index = 1;
+
+		tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_OFDM_DIFF+index])&0xff;
+		priv->TxPwrLegacyHtDiff[RF90_PATH_A][i] = (tempval&0xF);
+		priv->TxPwrLegacyHtDiff[RF90_PATH_B][i] = ((tempval>>4)&0xF);
+
+		tempval = (*(u8 *)&hwinfo[TX_PWR_SAFETY_CHK]);
+		priv->TxPwrSafetyFlag = (tempval&0x01);		
+	}
+	
+	priv->EEPROMRegulatory = 0;
+	if(priv->eeprom_version >= 2)
+	{
+		if(priv->eeprom_version >= 4)
+			priv->EEPROMRegulatory = (hwinfo[EEPROM_Regulatory]&0x7);	
+		else
+			priv->EEPROMRegulatory = (hwinfo[EEPROM_Regulatory]&0x1);	
+	}
+	RT_TRACE(COMP_INIT, "EEPROMRegulatory = 0x%x\n", priv->EEPROMRegulatory);
+
+	for(i=0; i<14; i++)
+		RT_TRACE(COMP_EPROM, "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrHt20Diff[RF90_PATH_A][i]);
+	for(i=0; i<14; i++)
+		RT_TRACE(COMP_EPROM, "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, priv->TxPwrLegacyHtDiff[RF90_PATH_A][i]);
+	for(i=0; i<14; i++)
+		RT_TRACE(COMP_EPROM, "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrHt20Diff[RF90_PATH_B][i]);
+	for(i=0; i<14; i++)
+		RT_TRACE(COMP_EPROM, "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrLegacyHtDiff[RF90_PATH_B][i]);
+#endif	
+	RT_TRACE(COMP_EPROM, "TxPwrSafetyFlag = %d\n", priv->TxPwrSafetyFlag);
+
+	tempval = (*(u8 *)&hwinfo[EEPROM_RFInd_PowerDiff])&0xff;
+	priv->EEPROMTxPowerDiff = tempval;	
+	priv->LegacyHTTxPowerDiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][0];
+
+	RT_TRACE(COMP_EPROM, "TxPowerDiff = %#x\n", priv->EEPROMTxPowerDiff);
+
+	usValue = *(u16 *)&hwinfo[EEPROM_TSSI_A];
+	priv->EEPROMTSSI_A = (u8)((usValue&0xff00)>>8);
+	usValue = *(u8 *)&hwinfo[EEPROM_TSSI_B];
+	priv->EEPROMTSSI_B = (u8)(usValue&0xff);
+	RT_TRACE(COMP_EPROM, "TSSI_A = %#x, TSSI_B = %#x\n", 
+			priv->EEPROMTSSI_A, priv->EEPROMTSSI_B);
+		
+	tempval = *(u8 *)&hwinfo[EEPROM_ThermalMeter];
+	priv->EEPROMThermalMeter = tempval;			
+	RT_TRACE(COMP_EPROM, "ThermalMeter = %#x\n", priv->EEPROMThermalMeter);
+	priv->ThermalMeter[0] =(priv->EEPROMThermalMeter&0x1f);
+	priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
+	
+	tempval = *(u8 *)&hwinfo[EEPROM_BLUETOOTH_COEXIST];
+	priv->EEPROMBluetoothCoexist = ((tempval&0x2)>>1);	
+	priv->BluetoothCoexist = priv->EEPROMBluetoothCoexist;
+	tempval = hwinfo[EEPROM_BLUETOOTH_TYPE];
+	priv->EEPROMBluetoothType = ((tempval&0xe)>>1);
+	priv->EEPROMBluetoothAntNum = (tempval&0x1);
+	priv->EEPROMBluetoothAntIsolation = ((tempval&0x10)>>4);
+	RT_TRACE(COMP_EPROM, "BlueTooth Coexistance = %#x\n", priv->BluetoothCoexist);
+
+#ifdef MERGE_TO_DO
+	BT_VAR_INIT(Adapter);
+
+	tempval = hwinfo[EEPROM_WoWLAN];
+	priv->EEPROMSupportWoWLAN = ((tempval&0x4)>>2); 
+	if (priv->EEPROMSupportWoWLAN)
+		priv->bHwSupportRemoteWakeUp = true;
+	else
+		priv->bHwSupportRemoteWakeUp = false;
+#endif
+#ifdef RTL8192S_WAPI_SUPPORT
+	tempval = *(u8 *)&hwinfo[EEPROM_WAPI_SUPPORT];
+	priv->EEPROMWapiSupport = ((tempval&0x10)>>4);	
+	priv->EEPROMWapiSupport = 1;
+
+	priv->WapiSupport = priv->EEPROMWapiSupport;
+	priv->rtllib->WapiSupport = priv->WapiSupport;		
+	RT_TRACE(COMP_EPROM, "WAPI Support = %#x\n", priv->WapiSupport);
+#endif
+
+	tempval = (*(u8 *)&hwinfo[EEPROM_CrystalCap])>>4;
+	priv->EEPROMCrystalCap =tempval;		
+	RT_TRACE(COMP_EPROM, "CrystalCap = %#x\n", priv->EEPROMCrystalCap);
+	priv->CrystalCap = priv->EEPROMCrystalCap;	
+	
+	priv->eeprom_ChannelPlan = *(u8 *)&hwinfo[EEPROM_ChannelPlan];
+	priv->bTXPowerDataReadFromEEPORM = true;
+	RT_TRACE(COMP_EPROM, "EEPROM ChannelPlan = 0x%4x\n", priv->eeprom_ChannelPlan);
+	
+	tempval = *(u8*)&hwinfo[EEPROM_BoardType];  
+	if (tempval == 0)	
+		priv->rf_type= RF_2T2R;
+	else if (tempval == 1)	 
+		priv->rf_type = RF_1T2R;
+	else if (tempval == 2)	 
+		priv->rf_type = RF_1T2R;
+	else if (tempval == 3)	 
+		priv->rf_type = RF_1T1R;
+
+	priv->rtllib->RF_Type = priv->rf_type;
+	priv->rtllib->b1x1RecvCombine = false;
+	if (priv->rf_type == RF_1T2R)
+	{
+		tempval = read_nic_byte(dev, 0x07);
+		if (!(tempval & BIT0))
+		{
+			priv->rtllib->b1x1RecvCombine = true;
+			RT_TRACE(COMP_INIT, "RF_TYPE=1T2R but only 1SS\n");
+		}
+	}
+	priv->rtllib->b1SSSupport = 	priv->rtllib->b1x1RecvCombine;
+	
+	priv->rf_chip = RF_6052;
+
+	priv->eeprom_CustomerID = *(u8 *)&hwinfo[EEPROM_CustomID];
+
+	RT_TRACE(COMP_EPROM, "EEPROM Customer ID: 0x%2x, rf_chip:%x\n", priv->eeprom_CustomerID, priv->rf_chip);
+	
+	priv->rtllib->b_customer_lenovo_id = false;
+	
+	switch(priv->eeprom_CustomerID)
+	{	
+		case EEPROM_CID_DEFAULT:
+			if(priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE020){
+				priv->CustomerID = RT_CID_819x_Lenovo;	
+				priv->rtllib->b_customer_lenovo_id = true;
+                        }
+			else if(priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE025)
+					priv->CustomerID = RT_CID_819x_Lenovo;
+			else if(priv->eeprom_svid == 0x1A32 && priv->eeprom_smid == 0x4308)
+					priv->CustomerID = RT_CID_819x_QMI;											
+			else if(priv->eeprom_svid == 0x1A32 && priv->eeprom_smid == 0x0311)
+					priv->CustomerID = RT_CID_819x_QMI;
+			else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x6897)
+				priv->CustomerID = RT_CID_819x_MSI;
+			else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x3821)
+				priv->CustomerID = RT_CID_819x_MSI;			
+			else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x897A)
+				priv->CustomerID = RT_CID_819x_MSI;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8156)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8157)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE021)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE022)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8158)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8159)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8186)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8187)
+				priv->CustomerID = RT_CID_819x_Acer;
+				else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8156)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 &&
+					priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8157)
+				priv->CustomerID = RT_CID_819x_Acer;
+			else if(	priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 &&
+			 		priv->eeprom_svid == 0x103C && priv->eeprom_smid == 0x1467)
+			 priv->CustomerID = RT_CID_819x_HP;
+			else
+			priv->CustomerID = RT_CID_DEFAULT;
+			break;
+			
+		case EEPROM_CID_TOSHIBA:       
+			priv->CustomerID = RT_CID_TOSHIBA;
+			break;
+
+		case EEPROM_CID_QMI:
+			priv->CustomerID = RT_CID_819x_QMI;
+			break;
+			
+		case EEPROM_CID_WHQL:
+#ifdef TO_DO_LIST			
+			priv->bInHctTest = true;
+			priv->bSupportTurboMode = false;
+			priv->bAutoTurboBy8186 = false;
+			priv->PowerSaveControl.bInactivePs = false;
+			priv->PowerSaveControl.bIPSModeBackup = false;
+			priv->PowerSaveControl.bLeisurePs = false;
+			priv->keepAliveLevel = 0;	
+			priv->bUnloadDriverwhenS3S4 = false;
+#endif
+			break;
+				
+		default:
+			priv->CustomerID = RT_CID_DEFAULT;
+			break;
+				
+	}
+	
+#if defined (RTL8192S_WAPI_SUPPORT)
+	if (priv->rtllib->WapiSupport)
+	{
+            WapiInit(priv->rtllib);
+	}
+#endif	
+	RT_TRACE(COMP_INIT, "<==== rtl8192se_read_eeprom_info\n");
+}
+
+void rtl8192se_get_eeprom_size(struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	u8 curCR = 0;
+	curCR = read_nic_byte(dev, EPROM_CMD);
+	PHY_RFShadowRefresh(dev);
+	if (curCR & BIT4){
+		RT_TRACE(COMP_EPROM, "Boot from EEPROM\n");
+		priv->epromtype = EEPROM_93C46;
+	}
+	else{
+		RT_TRACE(COMP_EPROM, "Boot from EFUSE\n");
+		priv->epromtype = EEPROM_BOOT_EFUSE;
+	}
+	if (curCR & BIT5){
+		RT_TRACE(COMP_EPROM,"Autoload OK\n"); 
+		priv->AutoloadFailFlag=false;		
+		rtl8192se_read_eeprom_info(dev);
+	}
+	else{
+		RT_TRACE(COMP_INIT, "AutoLoad Fail reported from CR9346!!\n"); 
+		priv->AutoloadFailFlag=true;		
+		rtl8192se_config_hw_for_load_fail(dev);		
+
+		if (priv->epromtype == EEPROM_BOOT_EFUSE)
+		{
+#if (RTL92SE_FPGA_VERIFY == 0)
+			EFUSE_ShadowMapUpdate(dev);
+#endif
+		}
+	}			
+#ifdef TO_DO_LIST
+	if(Adapter->bInHctTest)
+	{
+		pMgntInfo->PowerSaveControl.bInactivePs = false;
+		pMgntInfo->PowerSaveControl.bIPSModeBackup = false;
+		pMgntInfo->PowerSaveControl.bLeisurePs = false;
+		pMgntInfo->keepAliveLevel = 0;
+	}
+#endif	
+#ifdef ENABLE_DOT11D
+	priv->ChannelPlan = COUNTRY_CODE_WORLD_WIDE_13;
+
+	if(priv->ChannelPlan == COUNTRY_CODE_GLOBAL_DOMAIN) {
+		GET_DOT11D_INFO(priv->rtllib)->bEnabled = 1;
+		RT_TRACE(COMP_INIT, "%s: Enable dot11d when RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN!\n", __FUNCTION__);
+	}
+#endif
+	
+	RT_TRACE(COMP_INIT, "RegChannelPlan(%d) EEPROMChannelPlan(%d)", \
+			priv->RegChannelPlan, priv->eeprom_ChannelPlan);
+	RT_TRACE(COMP_INIT, "ChannelPlan = %d\n" , priv->ChannelPlan);
+	HalCustomizedBehavior8192S(dev);
+}
+
+#if (RTL92SE_FPGA_VERIFY == 1)
+static void MacConfigBeforeFwDownload(struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	u8				i;
+	u8				tmpU1b;
+	u16				tmpU2b;
+	u32				addr;
+	
+	RT_TRACE(COMP_INIT, "Set some register before enable NIC\r\n");
+
+	tmpU1b = read_nic_byte(dev, 0x562);
+	tmpU1b |= 0x08;
+	write_nic_byte(dev, 0x562, tmpU1b);
+	tmpU1b &= ~(BIT3);
+	write_nic_byte(dev, 0x562, tmpU1b);
+	
+	tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1);
+	tmpU1b &= 0x73;
+	write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b);
+
+	tmpU1b = read_nic_byte(dev, SYS_CLKR);	
+	tmpU1b &= 0xfa;
+	write_nic_byte(dev, SYS_CLKR, tmpU1b);
+
+	RT_TRACE(COMP_INIT, "Delay 1000ms before reset NIC. I dont know how long should we delay!!!!!\r\n");	
+	ssleep(1);
+
+	write_nic_byte(dev, SYS_CLKR, SYS_CLKSEL_80M);
+	
+	tmpU1b = read_nic_byte(dev, SPS1_CTRL);	
+	write_nic_byte(dev, SPS1_CTRL, (tmpU1b|SPS1_LDEN));
+	
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|AFE_BGEN));
+
+	tmpU1b = read_nic_byte(dev, LDOA15_CTRL);	
+	write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|LDA15_EN));
+
+	tmpU1b = read_nic_byte(dev, SPS1_CTRL);	
+	write_nic_byte(dev, SPS1_CTRL, (tmpU1b|SPS1_SWEN));
+
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|AFE_MBEN));
+
+	tmpU2b = read_nic_word(dev, SYS_ISO_CTRL);	
+	write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|ISO_PWC_DV2RP));
+
+	tmpU2b = read_nic_word(dev, SYS_ISO_CTRL);	
+	write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b &(~ISO_PWC_RV2RP)));
+
+	tmpU2b = read_nic_word(dev, AFE_XTAL_CTRL);	
+	write_nic_word(dev, AFE_XTAL_CTRL, (tmpU2b &(~XTAL_GATE_AFE)));
+
+	tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL);	
+	write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|APLL_EN));
+
+	write_nic_byte(dev, SYS_ISO_CTRL, 0xEE);
+
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, (tmpU2b|SYS_MAC_CLK_EN));
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);	
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_DCORE|FEN_MREGEN));
+
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, ((tmpU2b|SYS_FWHW_SEL)&(~SYS_SWHW_SEL)));
+
+	write_nic_byte(dev, RF_CTRL, 0);
+	write_nic_byte(dev, RF_CTRL, 7);
+
+	write_nic_word(dev, CMDR, 0x37FC);	
+	
+#if 1
+	write_nic_byte(dev, 0x6, 0x30);
+	write_nic_byte(dev, 0x49, 0xf0);
+
+	write_nic_byte(dev, 0x4b, 0x81);
+
+	write_nic_byte(dev, 0xb5, 0x21);
+
+	write_nic_byte(dev, 0xdc, 0xff);
+	write_nic_byte(dev, 0xdd, 0xff);	
+	write_nic_byte(dev, 0xde, 0xff);
+	write_nic_byte(dev, 0xdf, 0xff);
+
+	write_nic_byte(dev, 0x11a, 0x00);
+	write_nic_byte(dev, 0x11b, 0x00);
+
+	for (i = 0; i < 32; i++)
+		write_nic_byte(dev, INIMCS_SEL+i, 0x1b);	
+
+	write_nic_byte(dev, 0x236, 0xff);
+	
+	write_nic_byte(dev, 0x503, 0x22);
+
+	if(priv->bIntelBridgeExist) {
+		write_nic_byte(dev, 0x560, 0x40);
+	} else {
+		write_nic_byte(dev, 0x560, 0x00);
+	}
+
+	write_nic_byte(dev, DBG_PORT, 0x91);	
+#endif
+
+#ifdef CONFIG_RX_CMD 
+	write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]);
+#endif
+	write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
+	rtl8192_tx_enable(dev);
+	
+	RT_TRACE(COMP_INIT, "<---MacConfig8192SE()\n");
+
+}	/* MacConfigBeforeFwDownload */
+#else
+void gen_RefreshLedState(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);	
+
+	if(priv->bfirst_init)
+	{
+		RT_TRACE(COMP_INIT, "gen_RefreshLedState first init\n");
+		return;
+	}
+
+	if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS )
+	{
+		SwLedOn(dev, pLed0);
+	}
+	else		
+	{
+		SwLedOff(dev, pLed0);		
+	}
+
+}	
+void MacConfigBeforeFwDownload(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	u8				i;
+	u8				tmpU1b;
+	u16				tmpU2b;
+	u8				PollingCnt = 20;
+
+	RT_TRACE(COMP_INIT, "--->MacConfigBeforeFwDownload()\n");
+
+	if (priv->initialized_at_probe) {
+		return;
+	}
+
+	if(priv->bfirst_init)
+	{
+		tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1);
+		tmpU1b &= 0xFE;
+		write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b);
+		udelay(1);
+		write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b|BIT0);
+	}
+
+	tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1));
+	if(tmpU1b & BIT7)
+	{
+		tmpU1b &= ~(BIT6 | BIT7);
+		if(!HalSetSysClk8192SE(dev, tmpU1b))
+			return; 
+	}
+
+#ifdef MERGE_TO_DO
+	if( (pHalData->bt_coexist.BluetoothCoexist) &&
+		(pHalData->bt_coexist.BT_CoexistType == BT_CSR) )
+	{
+		write_nic_byte(dev, AFE_PLL_CTRL, 0x0);
+		udelay(50);
+		write_nic_byte(dev, LDOA15_CTRL, 0x34);
+		udelay(50);
+	}
+	else
+#endif
+	{
+        write_nic_byte(dev, AFE_PLL_CTRL, 0x0);
+		udelay(50);
+		write_nic_byte(dev, LDOA15_CTRL, 0x34);
+		udelay(50);
+	}
+	
+
+	write_nic_byte(dev, RPWM, 0x0);
+
+	tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1);
+	tmpU1b &= 0x73;
+	write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b);
+	mdelay(1);
+	
+	write_nic_byte(dev, CMDR, 0);
+	write_nic_byte(dev, TCR, 0);
+
+#if (DEMO_BOARD_SUPPORT == 0)
+	tmpU1b = read_nic_byte(dev, SPS1_CTRL);
+	tmpU1b &= 0xfc;
+	write_nic_byte(dev, SPS1_CTRL, tmpU1b);
+#endif
+
+	tmpU1b = read_nic_byte(dev, 0x562);
+	tmpU1b |= 0x08;
+	write_nic_byte(dev, 0x562, tmpU1b);
+	tmpU1b &= ~(BIT3);
+	write_nic_byte(dev, 0x562, tmpU1b);
+	
+
+
+	
+
+	RT_TRACE(COMP_INIT, "Enable AFE clock source\r\n");	
+	tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL);	
+	write_nic_byte(dev, AFE_XTAL_CTRL, (tmpU1b|0x01));
+	udelay(2000);	
+	tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL+1);	
+	write_nic_byte(dev, AFE_XTAL_CTRL+1, (tmpU1b&0xfb));
+
+
+	RT_TRACE(COMP_INIT, "Enable AFE Macro Block's Bandgap\r\n");	
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|BIT0));
+	mdelay(1);
+
+	RT_TRACE(COMP_INIT, "Enable AFE Mbias\r\n");	
+	tmpU1b = read_nic_byte(dev, AFE_MISC);	
+	write_nic_byte(dev, AFE_MISC, (tmpU1b|0x02));
+	mdelay(1);
+	
+	tmpU1b = read_nic_byte(dev, LDOA15_CTRL);	
+	write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|BIT0));
+
+
+
+	tmpU2b = read_nic_word(dev, SYS_ISO_CTRL);	
+	write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|BIT11));
+
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b |BIT13));
+
+
+	write_nic_byte(dev, SYS_ISO_CTRL+1, 0x68);
+
+	udelay(200);
+	tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL);	
+	write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4));
+
+#if 1 
+	udelay(100);
+	write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4|BIT6));
+	udelay(10);
+	write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4));
+	udelay(10);
+#endif
+	tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL+1);	
+	write_nic_byte(dev, AFE_PLL_CTRL+1, (tmpU1b|BIT0));
+	mdelay(1);
+
+	write_nic_byte(dev, SYS_ISO_CTRL, 0xA6);
+
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, (tmpU2b|BIT12|BIT11));
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);	
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11));
+
+	tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1);
+	write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b&~(BIT7));
+	
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11|BIT15));
+
+	 tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, (tmpU2b&(~BIT2)));
+
+	tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1));
+	tmpU1b = ((tmpU1b | BIT7) & (~BIT6));
+	if(!HalSetSysClk8192SE(dev, tmpU1b))
+		return; 
+
+#if 0	
+	tmpU2b = read_nic_word(dev, SYS_CLKR);	
+	write_nic_word(dev, SYS_CLKR, ((tmpU2b|BIT15)&(~BIT14)));
+#endif
+
+	write_nic_word(dev, CMDR, 0x07FC);
+	
+#if 1
+	write_nic_byte(dev, 0x6, 0x30);
+	write_nic_byte(dev, 0x49, 0xf0);
+
+	write_nic_byte(dev, 0x4b, 0x81);
+
+	write_nic_byte(dev, 0xb5, 0x21);
+
+	write_nic_byte(dev, 0xdc, 0xff);
+	write_nic_byte(dev, 0xdd, 0xff);	
+	write_nic_byte(dev, 0xde, 0xff);
+	write_nic_byte(dev, 0xdf, 0xff);
+
+	write_nic_byte(dev, 0x11a, 0x00);
+	write_nic_byte(dev, 0x11b, 0x00);
+
+	for (i = 0; i < 32; i++)
+		write_nic_byte(dev, INIMCS_SEL+i, 0x1b);	
+
+	write_nic_byte(dev, 0x236, 0xff);
+	
+	write_nic_byte(dev, 0x503, 0x22);
+	if (priv->pci_bridge_vendor & (PCI_BRIDGE_VENDOR_INTEL | PCI_BRIDGE_VENDOR_SIS)) {
+		write_nic_byte(dev, 0x560, 0x40);
+	} else {
+		write_nic_byte(dev, 0x560, 0x00);
+	}
+
+	write_nic_byte(dev, DBG_PORT, 0x91);	
+#endif
+
+	write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
+#ifdef CONFIG_RX_CMD
+	write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]);
+#endif	
+	rtl8192_tx_enable(dev);
+
+	write_nic_word(dev, CMDR, 0x37FC);
+	do {
+		tmpU1b = read_nic_byte(dev, TCR);
+		if((tmpU1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE)
+			break;	
+
+		udelay(5);
+	} while(PollingCnt--);	
+	
+	if(PollingCnt <= 0 )
+	{
+		RT_TRACE(COMP_ERR, "MacConfigBeforeFwDownloadASIC(): Polling TXDMA_INIT_VALUE timeout!! Current TCR(%#x)\n", tmpU1b);
+		tmpU1b = read_nic_byte(dev, CMDR);			
+		write_nic_byte(dev, CMDR, tmpU1b&(~TXDMA_EN));
+		udelay(2);
+		write_nic_byte(dev, CMDR, tmpU1b|TXDMA_EN);
+	}
+
+	gen_RefreshLedState(dev);
+
+	RT_TRACE(COMP_INIT, "<---MacConfigBeforeFwDownload()\n");
+
+}	/* MacConfigBeforeFwDownload */
+#endif
+
+static void MacConfigAfterFwDownload(struct net_device* dev)
+{
+	u8				i;
+	u16				tmpU2b;
+	struct r8192_priv* priv = rtllib_priv(dev);
+
+	
+	write_nic_byte(dev, CMDR, 
+	(u8)(BBRSTn|BB_GLB_RSTn|SCHEDULE_EN|MACRXEN|MACTXEN|DDMA_EN|FW2HW_EN|
+	RXDMA_EN|TXDMA_EN|HCI_RXDMA_EN|HCI_TXDMA_EN));
+	write_nic_dword(dev, TCR, 
+	read_nic_dword(dev, TCR)|TXDMAPRE2FULL);
+	write_nic_dword(dev, RCR, priv->ReceiveConfig);
+
+#if 0
+	for (i=0;i<6;i++)
+	write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); 	
+#endif
+	write_nic_word(dev, SIFS_CCK, 0x0a0a); 
+	write_nic_word(dev, SIFS_OFDM, 0x1010);
+	write_nic_byte(dev, ACK_TIMEOUT, 0x40);
+	
+	write_nic_word(dev, BCN_INTERVAL, 100);
+	write_nic_word(dev, ATIMWND, 2);	
+#ifdef _ENABLE_SW_BEACON
+        write_nic_word(dev, BCN_DRV_EARLY_INT, BIT15);
+#endif        
+
+#if 0
+	write_nic_dword(dev, RQPN1,  
+	NUM_OF_PAGE_IN_FW_QUEUE_BK<<0 | NUM_OF_PAGE_IN_FW_QUEUE_BE<<8 |\
+	NUM_OF_PAGE_IN_FW_QUEUE_VI<<16 | NUM_OF_PAGE_IN_FW_QUEUE_VO<<24);												
+	write_nic_dword(dev, RQPN2, 
+	NUM_OF_PAGE_IN_FW_QUEUE_HCCA << 0 | NUM_OF_PAGE_IN_FW_QUEUE_CMD << 8|\
+	NUM_OF_PAGE_IN_FW_QUEUE_MGNT << 16 |NUM_OF_PAGE_IN_FW_QUEUE_HIGH << 24);
+	write_nic_dword(dev, RQPN3, 
+	NUM_OF_PAGE_IN_FW_QUEUE_BCN<<0 | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<8);
+	write_nic_byte(dev, LD_RQPN, BIT7);
+#endif
+
+
+
+
+	write_nic_byte(dev, RXDMA, 
+							read_nic_byte(dev, RXDMA)|BIT6);
+
+	if (priv->card_8192_version== VERSION_8192S_ACUT)
+		write_nic_byte(dev, RRSR, 0xf0);
+	else if (priv->card_8192_version == VERSION_8192S_BCUT)
+		write_nic_byte(dev, RRSR, 0xff);
+	write_nic_byte(dev, RRSR+1, 0x01);
+	write_nic_byte(dev, RRSR+2, 0x00);
+
+	for (i = 0; i < 8; i++)
+	{
+
+		if (priv->card_8192_version == VERSION_8192S_ACUT)
+			write_nic_dword(dev, ARFR0+i*4, 0x1f0ff0f0);
+#if 0 
+		else if (priv->card_8192_version == VERSION_8192S_BCUT)
+			write_nic_dword(dev, ARFR0+i*4, 0x1f0ff0f0);
+#endif
+	}
+
+	write_nic_byte(dev, AGGLEN_LMT_H, 0x0f);
+	write_nic_word(dev, AGGLEN_LMT_L, 0x7442);
+	write_nic_word(dev, AGGLEN_LMT_L+2, 0xddd7);
+	write_nic_word(dev, AGGLEN_LMT_L+4, 0xd772);
+	write_nic_word(dev, AGGLEN_LMT_L+6, 0xfffd);
+
+	write_nic_dword(dev, DARFRC, 0x04010000);
+	write_nic_dword(dev, DARFRC+4, 0x09070605);
+	write_nic_dword(dev, RARFRC, 0x04010000);
+	write_nic_dword(dev, RARFRC+4, 0x09070605);
+
+	
+	
+	write_nic_word(dev, SG_RATE, 0xFFFF);
+
+
+	write_nic_word(dev, NAV_PROT_LEN, 0x0080);	
+	write_nic_byte(dev, CFEND_TH, 0xFF);	
+	write_nic_byte(dev, AMPDU_MIN_SPACE, 0x07);
+	write_nic_byte(dev, TXOP_STALL_CTRL, 0x00);
+	
+
+	/*write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) | \
+											(MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) | \
+											(1<<MULRW_SHIFT)));*/
+
+	write_nic_byte(dev, RXDRVINFO_SZ, 4);  
+
+	tmpU2b= read_nic_byte(dev, SYS_FUNC_EN);
+	write_nic_byte(dev, SYS_FUNC_EN, tmpU2b | BIT13);  
+	tmpU2b= read_nic_byte(dev, SYS_ISO_CTRL);
+	write_nic_byte(dev, SYS_ISO_CTRL, tmpU2b & (~BIT8));  
+
+	if (priv->epromtype == EEPROM_BOOT_EFUSE)	
+	{	
+		u8	tempval;		
+		
+		tempval = read_nic_byte(dev, SYS_ISO_CTRL+1); 
+		tempval &= 0xFE;
+		write_nic_byte(dev, SYS_ISO_CTRL+1, tempval); 
+
+
+		
+		write_nic_byte(dev, EFUSE_CTRL+3, 0x72); 
+		RT_TRACE(COMP_INIT, "EFUSE CONFIG OK\n");
+	}
+	RT_TRACE(COMP_INIT, "MacConfigAfterFwDownload OK\n");
+
+}	/* MacConfigAfterFwDownload */
+
+static void rtl8192se_HalDetectPwrDownMode(struct net_device*dev)
+{
+    u8 tmpvalue;
+    struct r8192_priv *priv = rtllib_priv(dev);	
+    EFUSE_ShadowRead(dev, 1, 0x78, (u32 *)&tmpvalue);
+
+    if (tmpvalue & BIT0) {
+        priv->pwrdown = true;
+    } else {
+        priv->pwrdown = false;
+    }
+}
+
+void HwConfigureRTL8192SE(struct net_device *dev)
+{
+
+	struct r8192_priv* priv = rtllib_priv(dev);
+	
+	u8	regBwOpMode = 0;
+	u32	regRATR = 0, regRRSR = 0;
+	u8	regTmp = 0;
+
+
+	switch(priv->rtllib->mode)
+	{
+	case WIRELESS_MODE_B:
+		regBwOpMode = BW_OPMODE_20MHZ;
+		regRATR = RATE_ALL_CCK;
+		regRRSR = RATE_ALL_CCK;
+		break;
+	case WIRELESS_MODE_A:
+		regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
+		regRATR = RATE_ALL_OFDM_AG;
+		regRRSR = RATE_ALL_OFDM_AG;
+		break;
+	case WIRELESS_MODE_G:
+		regBwOpMode = BW_OPMODE_20MHZ;
+		regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+		regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+		break;
+	case WIRELESS_MODE_AUTO:
+	case WIRELESS_MODE_N_24G:
+			regBwOpMode = BW_OPMODE_20MHZ;
+			regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+			regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+		break;
+	case WIRELESS_MODE_N_5G:
+		regBwOpMode = BW_OPMODE_5G;
+		regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+		regRRSR = RATE_ALL_OFDM_AG;
+		break;
+	default:
+		regBwOpMode = BW_OPMODE_20MHZ;
+		regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+		regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+		break;
+	}
+
+	regTmp = read_nic_byte(dev, INIRTSMCS_SEL);
+#if (RTL8192SU_DISABLE_CCK_RATE == 1)
+	regRRSR = ((regRRSR & 0x000ffff0)<<8) | regTmp;
+#else
+	regRRSR = ((regRRSR & 0x000fffff)<<8) | regTmp;
+#endif
+	write_nic_dword(dev, INIRTSMCS_SEL, regRRSR);
+
+	write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_RETRY_LIMIT, (u8*)(&priv->ShortRetryLimit));
+
+	write_nic_byte(dev, MLT, 0x8f);
+
+
+		
+#if 1
+	switch(priv->rf_type)
+	{
+		case RF_1T2R:
+		case RF_1T1R:
+			RT_TRACE(COMP_INIT, "Initializeadapter: RF_Type%s\n", priv->rf_type==RF_1T1R? "(1T1R)":"(1T2R)");
+                priv->rtllib->MinSpaceCfg = (MAX_MSS_DENSITY_1T<<3);						
+			break;
+		case RF_2T2R:
+		case RF_2T2R_GREEN:
+			RT_TRACE(COMP_INIT, "Initializeadapter:RF_Type(2T2R)\n");
+                priv->rtllib->MinSpaceCfg = (MAX_MSS_DENSITY_2T<<3);			
+			break;
+	}
+	write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg);
+#else
+	priv->rtllib->MinSpaceCfg = 0x90;	
+	SetHwReg8192SE(dev, HW_VAR_AMPDU_MIN_SPACE, (u8*)(&priv->rtllib->MinSpaceCfg));
+#endif
+}
+
+void 
+RF_RECOVERY(struct net_device*dev	,u8 Start, u8 End)
+{
+	u8	offset;
+	u8	counter;
+
+
+	for(offset = Start; offset<End; offset++)
+	{
+		PHY_RFShadowCompareFlagSet(dev, (RF90_RADIO_PATH_E)0, offset,true);
+		
+		if(PHY_RFShadowCompare(dev, (RF90_RADIO_PATH_E)0, offset))
+		{
+			PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)0, offset, true);
+
+			for (counter = 0; counter < 10; counter++)
+			{
+				RT_TRACE(COMP_INIT, "PHY_RFShadowCompare OKCNT=%d offset=%0x\n", counter, offset);
+			PHY_RFShadowRecorver( dev, (RF90_RADIO_PATH_E)0, offset);
+				if (offset == 0x18)
+				{
+					if (!PHY_RFShadowCompare(dev, (RF90_RADIO_PATH_E)0, offset))
+					{
+						RT_TRACE(COMP_INIT, "PHY_RFShadowCompare OKCNT=%d\n", counter);
+						PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)0, offset, false);
+						break;
+					}
+				}
+				else
+				{
+					PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)0, offset, false);
+					break;
+		}
+	}
+}
+	}
+
+}
+
+bool rtl8192se_adapter_start(struct net_device* dev)
+{ 	
+	struct r8192_priv *priv = rtllib_priv(dev);	
+	bool rtStatus 	= true;	
+	u8				tmpU1b;
+	u8				eRFPath;
+	u8				fw_download_times = 1;
+	u8				i=0;
+	RT_TRACE(COMP_INIT, "rtl8192se_adapter_start()\n");
+	priv->being_init_adapter = true;	
+#ifdef CONFIG_ASPM_OR_D3
+	RT_DISABLE_ASPM(dev);
+#endif
+start:
+	rtl8192_pci_resetdescring(dev);
+	MacConfigBeforeFwDownload(dev);
+	priv->initialized_at_probe = false;
+
+	priv->card_8192_version = priv->rtllib->VersionID
+	= (VERSION_8192S)((read_nic_dword(dev, PMC_FSM)>>16)&0xF);
+
+	RT_TRACE(COMP_INIT, "NIC version : %s\n", ((read_nic_dword(dev, PMC_FSM)>>15)&0x1)?"C-cut":"B-cut");
+
+	rtStatus = FirmwareDownload92S((struct net_device*)dev); 
+	if(rtStatus != true)
+	{
+		if(fw_download_times <= 10){
+			RT_TRACE(COMP_INIT, "rtl8192se_adapter_start(): Download Firmware failed %d times, Download again!!\n",fw_download_times);
+			fw_download_times = fw_download_times + 1;
+			goto start;
+		}else{
+			RT_TRACE(COMP_INIT, "rtl8192se_adapter_start(): Download Firmware failed 10, end!!\n");
+			goto end;
+		}
+	}
+
+	MacConfigAfterFwDownload(dev);
+
+	priv->FwCmdIOMap = 	read_nic_word(dev, LBUS_MON_ADDR);
+	priv->FwCmdIOParam = read_nic_dword(dev, LBUS_ADDR_MASK);
+
+	
+#if (RTL8192S_DISABLE_FW_DM == 1)
+	write_nic_dword(dev, WFM5, FW_DM_DISABLE); 
+	ChkFwCmdIoDone(dev);
+	write_nic_dword(dev, WFM5, FW_TXANT_SWITCH_DISABLE); 
+	ChkFwCmdIoDone(dev);
+#endif
+
+#if (HAL_MAC_ENABLE == 1)
+	RT_TRACE(COMP_INIT, "MAC Config Start!\n");
+	if (PHY_MACConfig8192S(dev) != true)
+	{
+		RT_TRACE(COMP_ERR, "MAC Config failed\n");
+		return rtStatus;
+	}
+	RT_TRACE(COMP_INIT, "MAC Config Finished!\n");
+#endif	
+
+	write_nic_dword(dev, CMDR, 0x37FC); 
+
+#if (HAL_BB_ENABLE == 1)
+	RT_TRACE(COMP_INIT, "BB Config Start!\n");
+	if (PHY_BBConfig8192S(dev) != true)
+	{
+		RT_TRACE(COMP_INIT, "BB Config failed\n");
+		return rtStatus;
+	}
+	RT_TRACE(COMP_INIT, "BB Config Finished!\n");
+#endif	
+
+
+	priv->Rf_Mode = RF_OP_By_SW_3wire;
+#if (HAL_RF_ENABLE == 1)		
+	RT_TRACE(COMP_INIT, "RF Config started!\n");
+
+#if (RTL92SE_FPGA_VERIFY == 0)
+	write_nic_byte(dev, AFE_XTAL_CTRL+1, 0xDB);
+	if(priv->card_8192_version== VERSION_8192S_ACUT)
+		write_nic_byte(dev, SPS1_CTRL+3, 0x07);
+	else
+		write_nic_byte(dev, RF_CTRL, 0x07);
+#endif	
+	if(PHY_RFConfig8192S(dev) != true)
+	{
+		RT_TRACE(COMP_ERR, "RF Config failed\n");
+		return rtStatus;
+	}
+	RT_TRACE(COMP_INIT, "RF Config Finished!\n");	
+#endif	
+
+
+	priv->RfRegChnlVal[0] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)0, RF_CHNLBW, bRFRegOffsetMask);
+	priv->RfRegChnlVal[1] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)1, RF_CHNLBW, bRFRegOffsetMask);
+
+	rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
+	rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
+	
+	HwConfigureRTL8192SE(dev);
+
+	if(priv->ResetProgress == RESET_TYPE_NORESET)
+		rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
+	CamResetAllEntry(dev);
+	{
+		u8 SECR_value = 0x0;
+		SECR_value |= SCR_TxEncEnable;
+		SECR_value |= SCR_RxDecEnable;
+		SECR_value |= SCR_NoSKMC;
+		write_nic_byte(dev, SECR, SECR_value);
+	}
+
+	{
+		int i;
+		for (i=0; i<4; i++)
+		 write_nic_dword(dev, WDCAPARA_ADD[i], 0x5e4322); 
+	}
+	{
+		PHY_GetHWRegOriginalValue(dev);
+#ifndef CONFIG_MP
+		rtl8192_phy_setTxPower(dev, priv->chan);
+#endif
+	}
+
+	rtl8192se_HalDetectPwrDownMode(dev);
+#if 1
+	if(priv->RegRfOff == true)
+	{ 
+		RT_TRACE((COMP_INIT|COMP_RF), "InitializeAdapter8190(): Turn off RF for RegRfOff ----------\n");
+		MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW);
+
+		for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
+			rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
+	
+	}
+	else if(priv->rtllib->RfOffReason > RF_CHANGE_BY_PS)
+	{ 
+		RT_TRACE((COMP_INIT|COMP_RF), "InitializeAdapter8190(): Turn off RF for RfOffReason(%d) ----------\n", priv->rtllib->RfOffReason);
+		MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason);
+	}
+	else
+	{
+            if(priv->bHwRadioOff == false){
+		priv->rtllib->eRFPowerState = eRfOn;
+		priv->rtllib->RfOffReason = 0; 
+		if(priv->rtllib->LedControlHandler)
+			priv->rtllib->LedControlHandler(dev, LED_CTL_POWER_ON);
+	}		
+	}		
+#endif
+
+
+	
+	{
+		int i;
+		for (i=0;i<6;i++)
+			write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); 	
+	}
+
+	tmpU1b = read_nic_byte(dev, MAC_PINMUX_CFG);
+	write_nic_byte(dev, MAC_PINMUX_CFG, tmpU1b&(~BIT3));
+	
+	if(priv->CustomerID == RT_CID_CCX)
+	{
+		RT_TRACE(COMP_INIT ,"InitializeAdapter8192SE(): Set FW Cmd FW_TX_FEEDBACK_CCX_ENABLE\n");
+		write_nic_dword(dev, WFM5, FW_TX_FEEDBACK_CCX_ENABLE); 
+		ChkFwCmdIoDone(dev);
+		
+		write_nic_dword(dev, WFM5, FW_HIGH_PWR_DISABLE); 
+		ChkFwCmdIoDone(dev);
+		write_nic_dword(dev, WFM5, FW_DIG_HALT);
+		ChkFwCmdIoDone(dev);
+
+		write_nic_byte(dev, 0xC50, 0x1C);
+		write_nic_byte(dev, 0xC58, 0x1C);
+	}
+	
+	if(priv->pFirmware->FirmwareVersion >= 0x49){
+		u8 tmp_byte = 0;
+		
+		tmp_byte = read_nic_byte(dev, FW_RSVD_PG_CRTL) & (~BIT4);
+		tmp_byte = tmp_byte | BIT5;
+		write_nic_byte(dev, FW_RSVD_PG_CRTL, tmp_byte); 
+
+		write_nic_dword(dev, TXDESC_MSK, 0xFFFFCFFF); 
+	}
+	
+	if(priv->pFirmware->FirmwareVersion >= 0x35)
+	{
+		priv->rtllib->SetFwCmdHandler(dev, FW_CMD_RA_INIT);
+	}
+       else if(priv->pFirmware->FirmwareVersion >= 0x34) 
+	{
+		write_nic_dword(dev, WFM5, FW_RA_INIT); 
+		ChkFwCmdIoDone(dev);
+	}
+	else
+	{
+	write_nic_dword(dev, WFM5, FW_RA_RESET); 
+	ChkFwCmdIoDone(dev);
+	write_nic_dword(dev, WFM5, FW_RA_ACTIVE); 
+	ChkFwCmdIoDone(dev);
+	write_nic_dword(dev, WFM5, FW_RA_REFRESH); 
+		ChkFwCmdIoDone(dev);
+        }
+	
+	
+
+		PHY_SwitchEphyParameter(dev);
+	RF_RECOVERY(dev, 0x25, 0x29);
+
+	priv->SilentResetRxSlotIndex = 0;
+	for( i=0; i < MAX_SILENT_RESET_RX_SLOT_NUM; i++ )
+	{
+		priv->SilentResetRxStuckEvent[i] = 0;
+	}
+
+	if(priv->BluetoothCoexist)
+	{
+		printk("Write reg 0x%x = 1 for Bluetooth Co-existance\n", SYSF_CFG);
+		write_nic_byte(dev, SYSF_CFG, 0x1);
+	}		
+	
+	priv->bIgnoreSilentReset = true;
+	
+#ifdef CONFIG_FW_PARSEBEACON
+	if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		write_nic_dword(dev, RXFILTERMAP, 0x0100);
+	}	
+#endif
+	rtl8192_irq_enable(dev);
+end:
+	priv->being_init_adapter = false;
+	return rtStatus;
+
+	
+}
+
+void rtl8192se_net_update(struct net_device *dev)
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_network *net = &priv->rtllib->current_network;
+	u16 rate_config = 0;
+	u32 regTmp = 0;
+	u8 rateIndex = 0;
+	u8	RetryLimit = 0x30;
+	u16 cap = net->capability;
+
+	priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
+	
+	{
+	rtl8192_config_rate(dev, &rate_config);	
+	if (priv->card_8192_version== VERSION_8192S_ACUT)
+		priv->basic_rate = rate_config  = rate_config & 0x150;
+	else if (priv->card_8192_version == VERSION_8192S_BCUT)
+		priv->basic_rate= rate_config = rate_config & 0x15f;
+
+#if 1	
+  	if(priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_CISCO && ((rate_config &0x150)==0))
+	{
+		rate_config |=0x010;
+	}
+	if(priv->rtllib->pHTInfo->IOTPeer & HT_IOT_ACT_WA_IOT_Broadcom)
+	{	
+		rate_config &= 0x1f0;
+		printk("HW_VAR_BASIC_RATE, HT_IOT_ACT_WA_IOT_Broadcom, BrateCfg = 0x%x\n", rate_config);
+	}
+
+	write_nic_byte(dev, RRSR, rate_config&0xff);
+	write_nic_byte(dev, RRSR+1, (rate_config>>8)&0xff);
+
+	while(rate_config > 0x1)
+	{
+		rate_config = (rate_config>> 1);
+		rateIndex++;
+	}
+	write_nic_byte(dev, INIRTSMCS_SEL, rateIndex);
+
+	regTmp = (priv->nCur40MhzPrimeSC) << 5;
+	if (priv->short_preamble)
+		regTmp |= 0x80;
+	write_nic_byte(dev, RRSR+2, regTmp);
+#endif
+	}
+
+	write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]);
+	write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]);
+
+	if (priv->rtllib->iw_mode == IW_MODE_ADHOC){
+		RetryLimit = HAL_RETRY_LIMIT_AP_ADHOC;
+	} else {
+		RetryLimit = (priv->CustomerID == RT_CID_CCX) ? 7 : HAL_RETRY_LIMIT_INFRA;
+	}	
+	priv->rtllib->SetHwRegHandler(dev, HW_VAR_RETRY_LIMIT, (u8*)(&RetryLimit));
+		
+	if (priv->rtllib->iw_mode == IW_MODE_ADHOC){
+		priv->rtllib->SetHwRegHandler( dev, HW_VAR_BEACON_INTERVAL, (u8*)(&net->beacon_interval));
+	}
+			
+	rtl8192_update_cap(dev, cap);
+}
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtl8192se_mesh_net_update(struct net_device *dev)
+{
+
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_network *net = &priv->rtllib->current_mesh_network;
+	u16 rate_config = 0;
+	u32 regTmp = 0;
+	u8 rateIndex = 0;
+	u8	retrylimit = 0x7;
+	u16 cap = net->capability;
+	/* At the peer mesh mode, the peer MP shall recognize the short preamble */
+	priv->short_preamble = 1;
+	
+	if (priv->card_8192_version== VERSION_8192S_ACUT)
+		priv->basic_rate = rate_config  = 0x150;
+	else if (priv->card_8192_version == VERSION_8192S_BCUT)
+		priv->basic_rate= rate_config = 0x15f;
+
+	write_nic_byte(dev, RRSR, rate_config&0xff);
+	write_nic_byte(dev, RRSR+1, (rate_config>>8)&0xff);
+
+	while(rate_config > 0x1)
+	{
+		rate_config = (rate_config>> 1);
+		rateIndex++;
+	}
+	write_nic_byte(dev, INIRTSMCS_SEL, rateIndex);
+
+	regTmp = (priv->nCur40MhzPrimeSC) << 5;
+	if (priv->short_preamble)
+		regTmp |= 0x80;
+	write_nic_byte(dev, RRSR+2, regTmp);
+
+
+	write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+	PHY_SetBeaconHwReg( dev, net->beacon_interval);
+	rtl8192_update_cap(dev, cap);
+	
+	priv->ShortRetryLimit = 
+		priv->LongRetryLimit = retrylimit;
+			
+	write_nic_word(dev,RETRY_LIMIT, \
+			retrylimit << RETRY_LIMIT_SHORT_SHIFT | \
+			retrylimit << RETRY_LIMIT_LONG_SHIFT);	
+}
+#endif
+
+void rtl8192se_link_change(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u32 reg = 0;
+
+	if(IS_NIC_DOWN(priv))
+		return;
+
+	priv->rtllib->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&reg));
+	
+	printk("===>%s():ieee->iw_mode is %d\n",__FUNCTION__,ieee->iw_mode);
+	if (ieee->state == RTLLIB_LINKED) {
+#ifdef CONFIG_FW_PARSEBEACON
+		if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+			write_nic_dword(dev, RXFILTERMAP, 0x0000);
+		}	
+#endif
+		if(priv->DM_Type == DM_Type_ByFW) {
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER)
+				ieee->SetFwCmdHandler(dev, FW_CMD_HIGH_PWR_DISABLE);
+			else
+				ieee->SetFwCmdHandler(dev, FW_CMD_HIGH_PWR_ENABLE);	
+		}
+		rtl8192se_net_update(dev);
+
+		if(ieee->bUseRAMask){
+			ieee->UpdateHalRAMaskHandler(
+									dev,
+									false,
+									0,
+									ieee->pHTInfo->PeerMimoPs,
+									ieee->mode,
+									ieee->pHTInfo->bCurTxBW40MHz,
+									0);
+			priv->rssi_level = 0;
+		}else{
+			rtl8192se_update_ratr_table(dev,ieee->dot11HTOperationalRateSet,NULL);
+		}
+		if(ieee->IntelPromiscuousModeInfo.bPromiscuousOn)
+			;
+		else
+			reg |= RCR_CBSSID;
+	} 
+#ifdef _RTL8192_EXT_PATCH_
+	else if ((ieee->mesh_state == RTLLIB_MESH_LINKED) && ieee->only_mesh) {
+		rtl8192se_mesh_net_update(dev);
+		if(ieee->bUseRAMask){
+			ieee->UpdateHalRAMaskHandler(
+									dev,
+									false,
+									0,
+									ieee->pHTInfo->PeerMimoPs,
+									ieee->mode,
+									ieee->pHTInfo->bCurTxBW40MHz,
+									0);
+			priv->rssi_level = 0;
+		}else{
+			rtl8192se_update_ratr_table(dev,ieee->dot11HTOperationalRateSet,NULL);
+		}
+#ifdef CONFIG_FW_PARSEBEACON
+		if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+			write_nic_dword(dev, RXFILTERMAP, 0x0100);
+		}	
+#endif
+		reg &= ~RCR_CBSSID;
+	} 
+#endif
+	else{
+#ifdef CONFIG_FW_PARSEBEACON
+		if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+			write_nic_dword(dev, RXFILTERMAP, 0x0100);
+		}	
+#endif
+		reg &= ~RCR_CBSSID;
+	}
+	priv->rtllib->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&reg) );
+
+	rtl8192se_update_msr(dev);
+	{		
+		u32	temp = read_nic_dword(dev, TCR);
+		write_nic_dword(dev, TCR, temp&(~BIT8));
+		write_nic_dword(dev, TCR, temp|BIT8);
+	}
+}
+
+void rtl8192se_AllowAllDestAddr(struct net_device* dev,
+                        bool bAllowAllDA, bool WriteIntoReg)
+{
+        struct r8192_priv* priv = rtllib_priv(dev);
+
+	if( bAllowAllDA )
+        {
+                priv->ReceiveConfig |= RCR_AAP;         
+        }
+        else
+        {
+                priv->ReceiveConfig &= ~RCR_AAP;                
+        }
+
+        if( WriteIntoReg )
+        {
+                write_nic_dword( dev, RCR, priv->ReceiveConfig );
+        }
+}
+
+
+u8 MRateToHwRate8192SE(struct net_device*dev, u8 rate)
+{
+	u8	ret = DESC92S_RATE1M;
+	u16	max_sg_rate;
+	static	u16	multibss_sg_old = 0x1234;
+	u16	multibss_sg;
+		
+	switch(rate)
+	{
+	case MGN_1M:	ret = DESC92S_RATE1M;		break;
+	case MGN_2M:	ret = DESC92S_RATE2M;		break;
+	case MGN_5_5M:	ret = DESC92S_RATE5_5M;	break;
+	case MGN_11M:	ret = DESC92S_RATE11M;	break;
+	case MGN_6M:	ret = DESC92S_RATE6M;		break;
+	case MGN_9M:	ret = DESC92S_RATE9M;		break;
+	case MGN_12M:	ret = DESC92S_RATE12M;	break;
+	case MGN_18M:	ret = DESC92S_RATE18M;	break;
+	case MGN_24M:	ret = DESC92S_RATE24M;	break;
+	case MGN_36M:	ret = DESC92S_RATE36M;	break;
+	case MGN_48M:	ret = DESC92S_RATE48M;	break;
+	case MGN_54M:	ret = DESC92S_RATE54M;	break;
+
+	case MGN_MCS0:		ret = DESC92S_RATEMCS0;	break;
+	case MGN_MCS1:		ret = DESC92S_RATEMCS1;	break;
+	case MGN_MCS2:		ret = DESC92S_RATEMCS2;	break;
+	case MGN_MCS3:		ret = DESC92S_RATEMCS3;	break;
+	case MGN_MCS4:		ret = DESC92S_RATEMCS4;	break;
+	case MGN_MCS5:		ret = DESC92S_RATEMCS5;	break;
+	case MGN_MCS6:		ret = DESC92S_RATEMCS6;	break;
+	case MGN_MCS7:		ret = DESC92S_RATEMCS7;	break;
+	case MGN_MCS8:		ret = DESC92S_RATEMCS8;	break;
+	case MGN_MCS9:		ret = DESC92S_RATEMCS9;	break;
+	case MGN_MCS10:	ret = DESC92S_RATEMCS10;	break;
+	case MGN_MCS11:	ret = DESC92S_RATEMCS11;	break;
+	case MGN_MCS12:	ret = DESC92S_RATEMCS12;	break;
+	case MGN_MCS13:	ret = DESC92S_RATEMCS13;	break;
+	case MGN_MCS14:	ret = DESC92S_RATEMCS14;	break;
+	case MGN_MCS15:	ret = DESC92S_RATEMCS15;	break;	
+
+	case MGN_MCS0_SG:	
+	case MGN_MCS1_SG:
+	case MGN_MCS2_SG:	
+	case MGN_MCS3_SG:	
+	case MGN_MCS4_SG:	
+	case MGN_MCS5_SG:
+	case MGN_MCS6_SG:	
+	case MGN_MCS7_SG:	
+	case MGN_MCS8_SG:	
+	case MGN_MCS9_SG:
+	case MGN_MCS10_SG:
+	case MGN_MCS11_SG:	
+	case MGN_MCS12_SG:	
+	case MGN_MCS13_SG:	
+	case MGN_MCS14_SG:
+	case MGN_MCS15_SG:	
+			ret = DESC92S_RATEMCS15_SG;
+			max_sg_rate = rate&0xf;
+			multibss_sg = max_sg_rate | (max_sg_rate<<4) | (max_sg_rate<<8) | (max_sg_rate<<12);
+			if (multibss_sg_old != multibss_sg)
+			{
+				write_nic_dword(dev, SG_RATE, multibss_sg);
+				multibss_sg_old = multibss_sg;
+			}
+			break;
+
+
+	case (0x80|0x20): 	ret = DESC92S_RATEMCS32; break;
+
+	default:				ret = DESC92S_RATEMCS15;	break;
+
+	}
+
+	return ret;
+}
+
+u8 rtl8192se_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority)
+{
+	u8 QueueSelect = 0x0;       
+
+	switch(QueueID) {
+#if defined RTL8192E || defined RTL8190P
+		case BE_QUEUE:
+			QueueSelect = QSLT_BE;  
+			break;
+
+		case BK_QUEUE:
+			QueueSelect = QSLT_BK;  
+			break;
+
+		case VO_QUEUE:
+			QueueSelect = QSLT_VO;  
+			break;
+
+		case VI_QUEUE:
+			QueueSelect = QSLT_VI;  
+			break;
+		case MGNT_QUEUE:
+			QueueSelect = QSLT_MGNT;
+			break;
+		case BEACON_QUEUE:
+			QueueSelect = QSLT_BEACON;
+			break;
+		case TXCMD_QUEUE:
+			QueueSelect = QSLT_CMD;
+			break;
+		case HIGH_QUEUE:
+			QueueSelect = QSLT_HIGH;
+			break;
+#elif defined RTL8192SE
+		case BE_QUEUE:
+			QueueSelect = priority; 
+			break;
+		case BK_QUEUE:
+			QueueSelect = priority; 
+			break;
+		case VO_QUEUE:
+			QueueSelect = priority; 
+			break;
+		case VI_QUEUE:
+			QueueSelect = priority; 
+			break;
+		case MGNT_QUEUE:
+			QueueSelect = QSLT_BE;
+			break;
+		case BEACON_QUEUE:
+			QueueSelect = QSLT_BEACON;
+			break;
+		case TXCMD_QUEUE:
+			QueueSelect = QSLT_CMD;
+			break;
+		case HIGH_QUEUE:
+			QueueSelect = QSLT_HIGH;
+			break;
+#endif
+		default:
+			RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID);
+			break;
+	}
+	return QueueSelect;
+}
+
+
+void  rtl8192se_tx_fill_desc(struct net_device* dev, tx_desc * pDesc, cb_desc * cb_desc, struct sk_buff* skb)
+{
+	u8				*pSeq;
+	u16				Temp;
+	struct r8192_priv* priv = rtllib_priv(dev);
+
+	struct rtllib_hdr_1addr * header = NULL;
+
+	dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+
+	u16 fc=0, stype=0;
+	header = (struct rtllib_hdr_1addr *)(((u8*)skb->data));
+	fc = header->frame_ctl;
+	stype = WLAN_FC_GET_STYPE(fc);
+	memset((void*)pDesc, 0, 32);		
+
+	{
+		
+		if(priv->rtllib->bUseRAMask){
+			if(cb_desc->macId < 32)
+			{
+				pDesc->MacID = cb_desc->macId;
+				pDesc->Rsvd_MacID = cb_desc->macId;
+			}
+		}
+		pDesc->TXHT		= (cb_desc->data_rate&0x80)?1:0;	
+
+#if (RTL92SE_FPGA_VERIFY == 0)
+		if (priv->card_8192_version== VERSION_8192S_ACUT)
+		{
+			if (cb_desc->data_rate== MGN_1M || cb_desc->data_rate == MGN_2M || 
+				cb_desc->data_rate == MGN_5_5M || cb_desc->data_rate == MGN_11M)
+			{
+				cb_desc->data_rate = MGN_12M;
+			}
+		}
+#endif			
+		pDesc->TxRate	= MRateToHwRate8192SE(dev,cb_desc->data_rate);
+		pDesc->TxShort	= rtl8192se_QueryIsShort(((cb_desc->data_rate&0x80)?1:0), MRateToHwRate8192SE(dev,cb_desc->data_rate), cb_desc);
+
+		if(cb_desc->bAMPDUEnable)
+		{			
+			pDesc->AggEn = 1;
+		}
+		else
+		{			
+			pDesc->AggEn = 0;
+		}
+
+		{
+			pSeq = (u8 *)(skb->data+22);
+			Temp = pSeq[0];
+			Temp <<= 12;			
+			Temp |= (*(u16 *)pSeq)>>4;
+			pDesc->Seq = Temp;
+		}
+		
+		pDesc->RTSEn	= (cb_desc->bRTSEnable && cb_desc->bCTSEnable==false)?1:0;				
+		pDesc->CTS2Self	= (cb_desc->bCTSEnable)?1:0;		
+		pDesc->RTSSTBC	= (cb_desc->bRTSSTBC)?1:0;
+		pDesc->RTSHT	= (cb_desc->rts_rate&0x80)?1:0;
+
+#if (RTL92SE_FPGA_VERIFY == 0)
+		if (priv->card_8192_version== VERSION_8192S_ACUT)
+		{
+			if (cb_desc->rts_rate == MGN_1M || cb_desc->rts_rate == MGN_2M || 
+				cb_desc->rts_rate == MGN_5_5M || cb_desc->rts_rate == MGN_11M)
+			{
+				cb_desc->rts_rate = MGN_12M;
+			}
+		}
+#endif	
+		pDesc->RTSRate	= MRateToHwRate8192SE(dev,cb_desc->rts_rate);
+		pDesc->RTSRate	= MRateToHwRate8192SE(dev,MGN_24M);
+		pDesc->RTSBW	= 0;
+		pDesc->RTSSC	= cb_desc->RTSSC;
+		pDesc->RTSShort	= (pDesc->RTSHT==0)?(cb_desc->bRTSUseShortPreamble?1:0):(cb_desc->bRTSUseShortGI?1:0);
+		if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)
+		{
+			if(cb_desc->bPacketBW)
+			{
+				pDesc->TxBw		= 1;
+				pDesc->TXSC		= 0;
+			}
+			else
+			{				
+				pDesc->TxBw		= 0;
+				pDesc->TXSC		= priv->nCur40MhzPrimeSC;
+			}
+		}
+		else
+		{
+			pDesc->TxBw		= 0;
+			pDesc->TXSC		= 0;
+		}
+
+		pDesc->LINIP = 0;
+		pDesc->Offset = 32;
+		pDesc->PktSize = (u16)skb->len;		
+		
+		pDesc->RaBRSRID = cb_desc->RATRIndex;
+#if 0		
+printk("*************TXDESC:\n");
+printk("\tTxRate: %d\n", pDesc->TxRate);
+printk("\tAMPDUEn: %d\n", pDesc->AggEn);
+printk("\tTxBw: %d\n", pDesc->TxBw);
+printk("\tTXSC: %d\n", pDesc->TXSC);
+printk("\tPktSize: %d\n", pDesc->PktSize);
+printk("\tRatrIdx: %d\n", pDesc->RaBRSRID);
+#endif
+		 if (cb_desc->bHwSec) {
+       		 static u8 tmp =0;
+       		 if (!tmp) {
+            		 tmp = 1;
+	        	}
+#ifdef _RTL8192_EXT_PATCH_
+			if(cb_desc->mesh_pkt == 0)
+#endif	
+			{
+				switch (priv->rtllib->pairwise_key_type) {
+					case KEY_TYPE_WEP40:
+					case KEY_TYPE_WEP104:
+						pDesc->SecType = 0x1;
+						break;
+					case KEY_TYPE_TKIP:
+						pDesc->SecType = 0x2;
+						break;
+					case KEY_TYPE_CCMP:
+						pDesc->SecType = 0x3;
+						break;
+					case KEY_TYPE_NA:
+						pDesc->SecType = 0x0;
+						break;
+				}
+			}
+#ifdef _RTL8192_EXT_PATCH_
+			else if(cb_desc->mesh_pkt == 1)
+			{
+				switch (priv->rtllib->mesh_pairwise_key_type) {
+					case KEY_TYPE_WEP40:
+					case KEY_TYPE_WEP104:
+						pDesc->SecType = 0x1;
+						break;
+					case KEY_TYPE_TKIP:
+						pDesc->SecType = 0x2;
+						break;
+					case KEY_TYPE_CCMP:
+						pDesc->SecType = 0x3;
+						break;
+					case KEY_TYPE_NA:
+						pDesc->SecType = 0x0;
+						break;
+				}
+			}
+#endif			
+		}
+
+		pDesc->PktID			= 0x0;		
+		pDesc->QueueSel		= rtl8192se_MapHwQueueToFirmwareQueue(cb_desc->queue_index, cb_desc->priority); 
+		
+		pDesc->DataRateFBLmt	= 0x1F;		
+		pDesc->DISFB	= cb_desc->bTxDisableRateFallBack;
+		pDesc->UserRate	= cb_desc->bTxUseDriverAssingedRate;
+
+		if (pDesc->UserRate == true && pDesc->TXHT == true)		
+			RF_ChangeTxPath(dev, cb_desc->data_rate);
+
+	}
+	
+
+	pDesc->FirstSeg	= 1;
+	pDesc->LastSeg	= 1;
+	
+	pDesc->TxBufferSize= (u16)skb->len;	
+	
+	pDesc->TxBuffAddr = cpu_to_le32(mapping);
+
+}
+
+void  rtl8192se_tx_fill_cmd_desc(struct net_device* dev, tx_desc_cmd * entry, cb_desc * cb_desc, struct sk_buff* skb)
+{
+    struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(cb_desc->bCmdOrInit == DESC_PACKET_TYPE_INIT) {
+		
+    dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+		
+	memset((void*)entry, 0, 32); 	
+	
+	entry->LINIP = cb_desc->bLastIniPkt;
+		
+	entry->FirstSeg = 1;
+	entry->LastSeg = 1;
+	
+	entry->TxBufferSize= (u16)(skb->len);
+	entry->TxBufferAddr = cpu_to_le32(mapping);
+	entry->PktSize = (u16)(skb->len);
+	
+	{
+		entry->OWN = 1;
+	}
+	} else { 
+
+		u8*	pDesc = (u8*)entry;
+		
+    		dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+		
+		CLEAR_PCI_TX_DESC_CONTENT(pDesc, sizeof(tx_desc_cmd));
+
+		SET_TX_DESC_FIRST_SEG(pDesc, 1); 
+		SET_TX_DESC_LAST_SEG(pDesc, 1); 
+
+		SET_TX_DESC_OFFSET(pDesc, 0x20); 
+
+		SET_TX_DESC_PKT_SIZE(pDesc, (u16)(skb->len)); 
+		SET_TX_DESC_QUEUE_SEL(pDesc, 0x13); 
+
+		
+		SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, priv->H2CTxCmdSeq);
+
+		SET_TX_DESC_TX_BUFFER_SIZE(pDesc, (u16)(skb->len));
+		SET_TX_DESC_TX_BUFFER_ADDRESS(pDesc, cpu_to_le32(mapping));
+
+		SET_TX_DESC_OWN(pDesc, 1);
+
+		RT_TRACE(COMP_CMD, "TxFillCmdDesc8192SE(): H2C Tx Cmd Content ----->\n");
+	}
+}
+
+u8 HwRateToMRate92S(bool bIsHT,	u8 rate)
+{
+	u8	ret_rate = 0x02;
+
+	if (!bIsHT) {
+		switch (rate) {
+		case DESC92S_RATE1M:		
+			ret_rate = MGN_1M;		
+			break;
+		case DESC92S_RATE2M:		
+			ret_rate = MGN_2M;		
+			break;
+		case DESC92S_RATE5_5M:		
+			ret_rate = MGN_5_5M;		
+			break;
+		case DESC92S_RATE11M:		
+			ret_rate = MGN_11M;		
+			break;
+		case DESC92S_RATE6M:		
+			ret_rate = MGN_6M;		
+			break;
+		case DESC92S_RATE9M:		
+			ret_rate = MGN_9M;		
+			break;
+		case DESC92S_RATE12M:		
+			ret_rate = MGN_12M;		
+			break;
+		case DESC92S_RATE18M:		
+			ret_rate = MGN_18M;		
+			break;
+		case DESC92S_RATE24M:		
+			ret_rate = MGN_24M;		
+			break;
+		case DESC92S_RATE36M:		
+			ret_rate = MGN_36M;		
+			break;
+		case DESC92S_RATE48M:		
+			ret_rate = MGN_48M;		
+			break;
+		case DESC92S_RATE54M:		
+			ret_rate = MGN_54M;		
+			break;
+		default:							
+			ret_rate = 0xff;
+			break;
+		}
+	} else {
+		switch (rate) {
+		case DESC92S_RATEMCS0:	
+			ret_rate = MGN_MCS0;		
+			break;
+		case DESC92S_RATEMCS1:	
+			ret_rate = MGN_MCS1;		
+			break;
+		case DESC92S_RATEMCS2:	
+			ret_rate = MGN_MCS2;		
+			break;
+		case DESC92S_RATEMCS3:	
+			ret_rate = MGN_MCS3;		
+			break;
+		case DESC92S_RATEMCS4:	
+			ret_rate = MGN_MCS4;		
+			break;
+		case DESC92S_RATEMCS5:	
+			ret_rate = MGN_MCS5;		
+			break;
+		case DESC92S_RATEMCS6:	
+			ret_rate = MGN_MCS6;		
+			break;
+		case DESC92S_RATEMCS7:	
+			ret_rate = MGN_MCS7;		
+			break;
+		case DESC92S_RATEMCS8:	
+			ret_rate = MGN_MCS8;		
+			break;
+		case DESC92S_RATEMCS9:	
+			ret_rate = MGN_MCS9;		
+			break;
+		case DESC92S_RATEMCS10:	
+			ret_rate = MGN_MCS10;	
+			break;
+		case DESC92S_RATEMCS11:	
+			ret_rate = MGN_MCS11;	
+			break;
+		case DESC92S_RATEMCS12:	
+			ret_rate = MGN_MCS12;	
+			break;
+		case DESC92S_RATEMCS13:	
+			ret_rate = MGN_MCS13;	
+			break;
+		case DESC92S_RATEMCS14:	
+			ret_rate = MGN_MCS14;	
+			break;
+		case DESC92S_RATEMCS15:	
+			ret_rate = MGN_MCS15;	
+			break;
+		case DESC92S_RATEMCS32:	
+			ret_rate = (0x80|0x20);	
+			break;
+		default:							
+			ret_rate = 0xff;
+			break;
+		}
+
+	}	
+	return ret_rate;
+}
+
+long
+rtl8192se_signal_scale_mapping(struct r8192_priv * priv,
+	long currsig
+	)
+{
+	long retsig;
+
+#if defined RTL8192SE || defined RTL8192CE
+	if(priv->CustomerID == RT_CID_819x_Lenovo)
+	{
+		return currsig;
+	}
+	else if(priv->CustomerID == RT_CID_819x_Netcore)
+	{	
+		if(currsig >= 31 && currsig <= 100)
+		{
+			retsig = 100;
+		}	
+		else if(currsig >= 21 && currsig <= 30)
+		{
+			retsig = 90 + ((currsig - 20) / 1);
+		}
+		else if(currsig >= 11 && currsig <= 20)
+		{
+			retsig = 80 + ((currsig - 10) / 1);
+		}
+		else if(currsig >= 7 && currsig <= 10)
+		{
+			retsig = 69 + (currsig - 7);
+		}
+		else if(currsig == 6)
+		{
+			retsig = 54;
+		}
+		else if(currsig == 5)
+		{
+			retsig = 45;
+		}
+		else if(currsig == 4)
+		{
+			retsig = 36;
+		}
+		else if(currsig == 3)
+		{
+			retsig = 27;
+		}
+		else if(currsig == 2)
+		{
+			retsig = 18;
+		}
+		else if(currsig == 1)
+		{
+			retsig = 9;
+		}
+		else
+		{
+			retsig = currsig;
+		}
+		return retsig;
+	}
+#endif
+
+	if(currsig >= 61 && currsig <= 100)
+	{
+		retsig = 90 + ((currsig - 60) / 4);
+	}
+	else if(currsig >= 41 && currsig <= 60)
+	{
+		retsig = 78 + ((currsig - 40) / 2);
+	}
+	else if(currsig >= 31 && currsig <= 40)
+	{
+		retsig = 66 + (currsig - 30);
+	}
+	else if(currsig >= 21 && currsig <= 30)
+	{
+		retsig = 54 + (currsig - 20);
+	}
+	else if(currsig >= 5 && currsig <= 20)
+	{
+		retsig = 42 + (((currsig - 5) * 2) / 3);
+	}
+	else if(currsig == 4)
+	{
+		retsig = 36;
+	}
+	else if(currsig == 3)
+	{
+		retsig = 27;
+	}
+	else if(currsig == 2)
+	{
+		retsig = 18;
+	}
+	else if(currsig == 1)
+	{
+		retsig = 9;
+	}
+	else
+	{
+		retsig = currsig;
+	}
+	
+	return retsig;
+}
+
+
+#define 	rx_hal_is_cck_rate(_pdesc)\
+			(_pdesc->RxMCS == DESC92S_RATE1M ||\
+			 _pdesc->RxMCS == DESC92S_RATE2M ||\
+			 _pdesc->RxMCS == DESC92S_RATE5_5M ||\
+			 _pdesc->RxMCS == DESC92S_RATE11M)
+#ifdef _RTL8192_EXT_PATCH_
+void rtl8192se_query_rxphystatus(
+	struct r8192_priv * priv,
+	struct rtllib_rx_stats * pstats,
+	prx_desc  pdesc,	
+	prx_fwinfo   pDrvInfo,
+	bool bpacket_match_bssid,
+	bool bpacket_toself,
+	bool bPacketBeacon
+	)
+{
+	bool is_cck_rate;
+	phy_sts_cck_8192s_t* cck_buf;
+	u8 rx_pwr_all=0, rx_pwr[4], rf_rx_num=0, EVM, PWDB_ALL;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+	u8 cck_highpwr = 0;
+	is_cck_rate = rx_hal_is_cck_rate(pdesc);
+
+	pstats->bPacketMatchBSSID = bpacket_match_bssid;
+	pstats->bPacketToSelf = bpacket_toself;
+	pstats->bIsCCK = is_cck_rate;
+	pstats->bPacketBeacon = bPacketBeacon;
+
+	pstats->RxMIMOSignalQuality[0] = -1;
+	pstats->RxMIMOSignalQuality[1] = -1;
+
+	if (is_cck_rate){
+		u8 report;
+			
+		cck_buf = (phy_sts_cck_8192s_t*)pDrvInfo;
+
+		if(priv->rtllib->eRFPowerState == eRfOn)
+			cck_highpwr = (u8)priv->bCckHighPower;
+		else
+			cck_highpwr = false;
+		if (!cck_highpwr){
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch(report){
+				case 0x3:
+					rx_pwr_all = -40 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x2:
+					rx_pwr_all = -20 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x1:
+					rx_pwr_all = -2 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x0:
+					rx_pwr_all = 14 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+			}
+		}
+		else{
+			report = pDrvInfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch(report){
+				case 0x3:
+					rx_pwr_all = -40 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x2:
+					rx_pwr_all = -20 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x1:
+					rx_pwr_all = -2 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x0:
+					rx_pwr_all = 14 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+			}
+		}
+
+		PWDB_ALL= rtl819x_query_rxpwrpercentage(rx_pwr_all);
+		{
+			PWDB_ALL+=6;
+			if(PWDB_ALL > 100)
+				PWDB_ALL = 100;
+			if(PWDB_ALL > 34 && PWDB_ALL <= 42)
+				PWDB_ALL -= 2;
+			else if(PWDB_ALL > 26 && PWDB_ALL <= 34)
+				PWDB_ALL -= 6;
+			else if(PWDB_ALL > 14 && PWDB_ALL <= 26)
+				PWDB_ALL -= 8;
+			else if(PWDB_ALL > 4 && PWDB_ALL <= 14)
+				PWDB_ALL -= 4;
+		}
+		pstats->RxPWDBAll = PWDB_ALL;
+		pstats->RecvSignalPower = rx_pwr_all;
+
+		if (bpacket_match_bssid){
+			u8 sq;
+			if(priv->CustomerID == RT_CID_819x_Lenovo)		
+			{
+				if(PWDB_ALL >= 50)
+					sq = 100;
+				else if(PWDB_ALL >= 35 && PWDB_ALL < 50)
+					sq = 80;
+				else if(PWDB_ALL >= 22 && PWDB_ALL < 35)
+					sq = 60;
+				else if(PWDB_ALL >= 18 && PWDB_ALL < 22)
+					sq = 40;
+				else
+					sq = 20;
+			}
+			else
+			{
+			if (pstats->RxPWDBAll > 40)
+				sq = 100;
+			else{
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if(sq < 20)
+					sq = 100;
+				else
+					sq = ((64-sq)*100)/44;
+			}
+			}
+			pstats->SignalQuality = sq;
+			pstats->RxMIMOSignalQuality[0] = sq;
+			pstats->RxMIMOSignalQuality[1] = -1;
+		}
+	}
+	else{
+		priv->brfpath_rxenable[0] = priv->brfpath_rxenable[1] = true;
+
+		for (i=RF90_PATH_A; i<RF90_PATH_MAX; i++){
+			if (priv->brfpath_rxenable[i])
+				rf_rx_num ++;
+
+			rx_pwr[i] = ((pDrvInfo->gain_trsw[i]&0x3f)*2) - 110;
+			rssi = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+
+			priv->stats.rxSNRdB[i] = (long)(pDrvInfo->rxsnr[i]/2);
+
+			if (bpacket_match_bssid){
+				pstats->RxMIMOSignalStrength[i] = (u8)rssi;
+				if(priv->CustomerID == RT_CID_819x_Lenovo)
+				{
+					u8	SQ;
+					
+					if(i == 0)
+					{
+						if(rssi >= 50)
+							SQ = 100;
+						else if(rssi >= 35 && rssi < 50)
+							SQ = 80;
+						else if(rssi >= 22 && rssi < 35)
+							SQ = 60;
+						else if(rssi >= 18 && rssi < 22)
+							SQ = 40;
+						else
+							SQ = 20;
+						pstats->SignalQuality = SQ;
+			}
+		}
+			}
+		}
+		rx_pwr_all = ((pDrvInfo->pwdb_all >> 1) & 0x7f) - 106;
+		PWDB_ALL = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+
+		pstats->RxPWDBAll = PWDB_ALL;
+		pstats->RxPower = rx_pwr_all;
+		pstats->RecvSignalPower = rx_pwr_all;
+
+		if(priv->CustomerID != RT_CID_819x_Lenovo){	
+		if (pdesc->RxHT && pdesc->RxMCS >= DESC92S_RATEMCS8 && pdesc->RxMCS <= DESC92S_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+
+		for(i=0; i<max_spatial_stream; i++){
+			EVM = rtl819x_evm_dbtopercentage(pDrvInfo->rxevm[i]);
+
+			if (bpacket_match_bssid)
+			{
+				if (i==0)
+						pstats->SignalQuality = (u8)(EVM & 0xff);
+					pstats->RxMIMOSignalQuality[i] = (u8)(EVM&0xff);
+				}
+			}
+		}
+#if 1
+		if (pdesc->BandWidth)
+			priv->stats.received_bwtype[1+pDrvInfo->rxsc]++;
+		else
+			priv->stats.received_bwtype[0]++;
+#endif
+	}
+
+	if (is_cck_rate){
+		pstats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,PWDB_ALL));
+	}
+	else {
+		if (rf_rx_num != 0)
+			pstats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,total_rssi/=rf_rx_num));
+	}
+}
+#else
+void rtl8192se_query_rxphystatus(
+	struct r8192_priv * priv,
+	struct rtllib_rx_stats * pstats,
+	prx_desc  pdesc,	
+	prx_fwinfo   pDrvInfo,
+	struct rtllib_rx_stats * precord_stats,
+	bool bpacket_match_bssid,
+	bool bpacket_toself,
+	bool bPacketBeacon,
+	bool bToSelfBA
+	)
+{
+	bool is_cck_rate;
+	phy_sts_cck_8192s_t* cck_buf;
+	s8 rx_pwr_all=0, rx_pwr[4]; 
+	u8 rf_rx_num=0, EVM, PWDB_ALL;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+
+	is_cck_rate = rx_hal_is_cck_rate(pdesc);
+
+	memset(precord_stats, 0, sizeof(struct rtllib_rx_stats));
+	pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
+	pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
+	pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
+	pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
+	pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
+	pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
+
+	pstats->RxMIMOSignalQuality[0] = -1;
+	pstats->RxMIMOSignalQuality[1] = -1;
+	precord_stats->RxMIMOSignalQuality[0] = -1;
+	precord_stats->RxMIMOSignalQuality[1] = -1;
+
+	if (is_cck_rate){
+		u8 report, cck_highpwr;
+			
+		cck_buf = (phy_sts_cck_8192s_t*)pDrvInfo;
+
+		if(!priv->bInPowerSaveMode)
+		cck_highpwr = (u8)rtl8192_QueryBBReg(priv->rtllib->dev, rFPGA0_XA_HSSIParameter2, BIT9);
+		else
+			cck_highpwr = false;
+		if (!cck_highpwr){
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch(report){
+				case 0x3:
+					rx_pwr_all = -35 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x2:
+					rx_pwr_all = -23 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x1:
+					rx_pwr_all = -11 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+				case 0x0:
+					rx_pwr_all = 8 - (cck_buf->cck_agc_rpt&0x3e);
+					break;
+			}
+		}
+		else{
+			report = pDrvInfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch(report){
+				case 0x3:
+					rx_pwr_all = -35 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x2:
+					rx_pwr_all = -23 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x1:
+					rx_pwr_all = -11 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+				case 0x0:
+					rx_pwr_all = -8 - ((cck_buf->cck_agc_rpt & 0x1f)<<1);
+					break;
+			}
+		}
+
+		PWDB_ALL= rtl819x_query_rxpwrpercentage(rx_pwr_all);
+		pstats->RxPWDBAll = precord_stats->RxPWDBAll = PWDB_ALL;
+		pstats->RecvSignalPower = rx_pwr_all;
+
+		if (bpacket_match_bssid){
+			u8 sq;
+			if (pstats->RxPWDBAll > 40)
+				sq = 100;
+			else{
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if(sq < 20)
+					sq = 100;
+				else
+					sq = ((64-sq)*100)/44;
+			}
+			pstats->SignalQuality = precord_stats->SignalQuality = sq;
+			pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
+			pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
+		}
+	}
+	else{
+		priv->brfpath_rxenable[0] = priv->brfpath_rxenable[1] = true;
+
+		for (i=RF90_PATH_A; i<RF90_PATH_MAX; i++){
+			if (priv->brfpath_rxenable[i])
+				rf_rx_num ++;
+
+			rx_pwr[i] = ((pDrvInfo->gain_trsw[i]&0x3f)*2) - 110;
+			rssi = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+
+			priv->stats.rxSNRdB[i] = (long)(pDrvInfo->rxsnr[i]/2);
+
+			if (bpacket_match_bssid){
+				pstats->RxMIMOSignalStrength[i] = (u8)rssi;
+				precord_stats->RxMIMOSignalStrength [i] = (u8)rssi;
+			}
+		}
+
+		rx_pwr_all = ((pDrvInfo->pwdb_all >> 1) & 0x7f) - 0x106;
+		PWDB_ALL = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+
+		pstats->RxPWDBAll = precord_stats->RxPWDBAll = PWDB_ALL;
+		pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
+		pstats->RecvSignalPower = precord_stats->RecvSignalPower = rx_pwr_all;
+
+		if (pdesc->RxHT && pdesc->RxMCS >= DESC92S_RATEMCS8 && pdesc->RxMCS <= DESC92S_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+
+		for(i=0; i<max_spatial_stream; i++){
+			EVM = rtl819x_evm_dbtopercentage(pDrvInfo->rxevm[i]);
+
+			if (bpacket_match_bssid)
+			{
+				if (i==0)
+					pstats->SignalQuality = 
+					precord_stats->SignalQuality = (u8)(EVM&0xff);
+				pstats->RxMIMOSignalQuality[i] =
+				precord_stats->RxMIMOSignalQuality[i] = (u8)(EVM&0xff);
+			}
+		}
+#if 0
+		if (pdesc->BW)
+			priv->stats.received_bwtype[1+pDrvInfo->rxsc]++;
+		else
+			priv->stats.received_bwtype[0]++;
+#endif
+	}
+
+	if (is_cck_rate)
+		pstats->SignalStrength = 
+		precord_stats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,PWDB_ALL));
+	else
+		if (rf_rx_num != 0)
+			pstats->SignalStrength = 
+			precord_stats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,total_rssi/=rf_rx_num));
+
+}
+#endif
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtl819x_update_rxsignalstatistics8192S(
+	struct r8192_priv * priv,
+	struct rtllib_rx_stats * pstats
+	)
+{
+	int	weighting = 0;
+
+
+	if(priv->stats.recv_signal_power == 0)
+		priv->stats.recv_signal_power = pstats->RecvSignalPower;
+
+	if(pstats->RecvSignalPower > priv->stats.recv_signal_power)
+		weighting = 5;
+	else if(pstats->RecvSignalPower < priv->stats.recv_signal_power)
+		weighting = (-5);
+	priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pstats->RecvSignalPower + weighting) / 6;
+
+}	
+
+void Process_UI_RSSI_8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats)
+{
+	u8			rfPath;
+	u32			last_rssi, tmpVal;
+
+	if(pstats->bPacketToSelf || pstats->bPacketBeacon)
+	{
+		priv->stats.RssiCalculateCnt++;	
+		if(priv->stats.ui_rssi.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX)
+		{
+			priv->stats.ui_rssi.TotalNum = PHY_RSSI_SLID_WIN_MAX;
+			last_rssi = priv->stats.ui_rssi.elements[priv->stats.ui_rssi.index];
+			priv->stats.ui_rssi.TotalVal -= last_rssi;
+		}
+		priv->stats.ui_rssi.TotalVal += pstats->SignalStrength;
+	
+		priv->stats.ui_rssi.elements[priv->stats.ui_rssi.index++] = pstats->SignalStrength;
+		if(priv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+			priv->stats.ui_rssi.index = 0;
+	
+		tmpVal = priv->stats.ui_rssi.TotalVal/priv->stats.ui_rssi.TotalNum;
+		priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmpVal);
+
+	}
+
+	if(!pstats->bIsCCK && pstats->bPacketToSelf)
+	{
+		for (rfPath = RF90_PATH_A; rfPath < priv->NumTotalRFPath; rfPath++)
+		{
+			if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev, rfPath))
+				continue;
+			RT_TRACE(COMP_DBG, "pstats->RxMIMOSignalStrength[%d]  = %d \n", rfPath, pstats->RxMIMOSignalStrength[rfPath] );
+
+			if(priv->stats.rx_rssi_percentage[rfPath] == 0)	
+			{
+				priv->stats.rx_rssi_percentage[rfPath] = pstats->RxMIMOSignalStrength[rfPath];
+			}
+			
+			if(pstats->RxMIMOSignalStrength[rfPath]  > priv->stats.rx_rssi_percentage[rfPath])
+			{
+				priv->stats.rx_rssi_percentage[rfPath] = 
+					( (priv->stats.rx_rssi_percentage[rfPath]*(Rx_Smooth_Factor-1)) + 
+					(pstats->RxMIMOSignalStrength[rfPath])) /(Rx_Smooth_Factor);
+				priv->stats.rx_rssi_percentage[rfPath] = priv->stats.rx_rssi_percentage[rfPath] + 1;
+			}
+			else
+			{
+				priv->stats.rx_rssi_percentage[rfPath] = 
+					( (priv->stats.rx_rssi_percentage[rfPath]*(Rx_Smooth_Factor-1)) + 
+					(pstats->RxMIMOSignalStrength[rfPath])) /(Rx_Smooth_Factor);
+			}
+			RT_TRACE(COMP_DBG, "priv->stats.rx_rssi_percentage[%d]  = %d \n",rfPath, priv->stats.rx_rssi_percentage[rfPath] );
+		}
+	}
+	
+}	
+
+void Process_PWDB_8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats,struct rtllib_network* pnet, struct sta_info *pEntry)
+{
+	long	UndecoratedSmoothedPWDB=0;
+
+	if(priv->rtllib->iw_mode == IW_MODE_MESH){
+		if(pnet){
+			if(priv->mshobj->ext_patch_get_peermp_rssi_param)
+				UndecoratedSmoothedPWDB = priv->mshobj->ext_patch_get_peermp_rssi_param(pnet);
+		}else
+			UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb;
+	}
+	else if(priv->rtllib->iw_mode == IW_MODE_ADHOC){
+		if(pEntry){
+			UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
+		}
+	}else
+		UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb;
+
+	if(pstats->bPacketToSelf || pstats->bPacketBeacon){
+		if(UndecoratedSmoothedPWDB < 0){	
+			UndecoratedSmoothedPWDB = pstats->RxPWDBAll;
+		}
+		
+		if(pstats->RxPWDBAll > (u32)UndecoratedSmoothedPWDB){
+			UndecoratedSmoothedPWDB = 	
+					( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) + 
+					(pstats->RxPWDBAll)) /(Rx_Smooth_Factor);
+			UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB + 1;
+		}else{
+			UndecoratedSmoothedPWDB = 	
+					( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) + 
+					(pstats->RxPWDBAll)) /(Rx_Smooth_Factor);
+		}
+		if(priv->rtllib->iw_mode == IW_MODE_MESH){
+			if(pnet){
+				if(priv->mshobj->ext_patch_set_peermp_rssi_param)
+					priv->mshobj->ext_patch_set_peermp_rssi_param(pnet,UndecoratedSmoothedPWDB);
+			}else
+				priv->undecorated_smoothed_pwdb = UndecoratedSmoothedPWDB;
+		}else if(priv->rtllib->iw_mode == IW_MODE_ADHOC){
+			if(pEntry){
+				pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
+			}
+		}else{
+			priv->undecorated_smoothed_pwdb = UndecoratedSmoothedPWDB;
+		}
+		rtl819x_update_rxsignalstatistics8192S(priv, pstats);
+	}
+}
+
+void Process_UiLinkQuality8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats)
+{
+	u32	last_evm=0, nSpatialStream, tmpVal;
+
+	if(pstats->SignalQuality != 0)	
+	{
+		if (pstats->bPacketToSelf || pstats->bPacketBeacon)
+		{
+			if(priv->stats.ui_link_quality.TotalNum++ >= PHY_LINKQUALITY_SLID_WIN_MAX)
+			{
+				priv->stats.ui_link_quality.TotalNum = PHY_LINKQUALITY_SLID_WIN_MAX;
+				last_evm = priv->stats.ui_link_quality.elements[priv->stats.ui_link_quality.index];
+				priv->stats.ui_link_quality.TotalVal -= last_evm;
+			}
+			priv->stats.ui_link_quality.TotalVal += pstats->SignalQuality;
+
+			priv->stats.ui_link_quality.elements[priv->stats.ui_link_quality.index++] = pstats->SignalQuality;
+			if(priv->stats.ui_link_quality.index >= PHY_LINKQUALITY_SLID_WIN_MAX)
+				priv->stats.ui_link_quality.index = 0;
+
+
+			tmpVal = priv->stats.ui_link_quality.TotalVal/priv->stats.ui_link_quality.TotalNum;
+			priv->stats.signal_quality = tmpVal;
+			priv->stats.last_signal_strength_inpercent = tmpVal;
+		
+			for(nSpatialStream = 0; nSpatialStream<2 ; nSpatialStream++)	
+			{
+				if(pstats->RxMIMOSignalQuality[nSpatialStream] != -1)
+				{
+					if(priv->stats.rx_evm_percentage[nSpatialStream] == 0)	
+					{
+						priv->stats.rx_evm_percentage[nSpatialStream] = pstats->RxMIMOSignalQuality[nSpatialStream];
+					}
+					priv->stats.rx_evm_percentage[nSpatialStream] = 
+					( (priv->stats.rx_evm_percentage[nSpatialStream]*(Rx_Smooth_Factor-1)) + 
+					(pstats->RxMIMOSignalQuality[nSpatialStream]* 1)) /(Rx_Smooth_Factor);
+				}
+			}
+		}
+	}
+	else
+		;
+	
+}	
+#endif
+
+
+#ifdef _RTL8192_EXT_PATCH_
+void rtl8192se_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct rtllib_rx_stats * pcurrent_stats,struct rtllib_network * pnet, struct sta_info *pEntry)
+#else
+void rtl8192se_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct rtllib_rx_stats * pprevious_stats, struct rtllib_rx_stats * pcurrent_stats)
+#endif
+{
+#ifdef _RTL8192_EXT_PATCH_
+	if(!pcurrent_stats->bPacketMatchBSSID)
+		return;
+	Process_UI_RSSI_8192S(priv, pcurrent_stats);
+	Process_PWDB_8192S(priv, pcurrent_stats, pnet, pEntry);
+	Process_UiLinkQuality8192S(priv, pcurrent_stats);	
+#else
+	bool bcheck = false;
+	u8	rfpath;
+	u32 nspatial_stream, tmp_val;
+	static u32 slide_rssi_index=0, slide_rssi_statistics=0; 
+	static u32 slide_evm_index=0, slide_evm_statistics=0;
+	static u32 last_rssi=0, last_evm=0;
+	static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
+	static u32 last_beacon_adc_pwdb=0;
+
+	struct rtllib_hdr_3addr *hdr;
+	u16 sc ;
+	unsigned int frag,seq;
+	hdr = (struct rtllib_hdr_3addr *)buffer;
+	sc = le16_to_cpu(hdr->seq_ctl);
+	frag = WLAN_GET_SEQ_FRAG(sc);
+	seq = WLAN_GET_SEQ_SEQ(sc);
+	pcurrent_stats->Seq_Num = seq;
+	if(!pprevious_stats->bIsAMPDU)
+	{
+		bcheck = true;
+	}else {
+#if 0
+		if( !pcurrent_stats->bIsAMPDU || pcurrent_stats->bFirstMPDU)
+			bcheck = true;
+#endif
+	}
+		
+	if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
+	{
+		slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
+		last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
+		priv->stats.slide_rssi_total -= last_rssi;
+	}
+	priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
+	
+	priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
+	if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
+		slide_rssi_index = 0;
+	
+	tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
+	priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmp_val);
+	pcurrent_stats->rssi = priv->stats.signal_strength;
+	if(!pprevious_stats->bPacketMatchBSSID)
+	{
+		if(!pprevious_stats->bToSelfBA)
+			return;
+	}
+	
+	if(!bcheck)
+		return;
+
+	rtl819x_process_cck_rxpathsel(priv,pprevious_stats);
+
+	priv->stats.num_process_phyinfo++;
+#if 0
+	if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
+	{
+		slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
+		last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
+		priv->stats.slide_rssi_total -= last_rssi;
+	}
+	priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
+	
+	priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
+	if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
+		slide_rssi_index = 0;
+	
+	tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
+	priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmp_val);
+
+#endif
+	if(!pprevious_stats->bIsCCK && pprevious_stats->bPacketToSelf)
+	{
+		for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++)
+		{
+			if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev, rfpath))
+				continue;
+			RT_TRACE(COMP_DBG,"Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath]  = %d \n" ,pprevious_stats->RxMIMOSignalStrength[rfpath] );		 
+			if(priv->stats.rx_rssi_percentage[rfpath] == 0)
+			{
+				priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
+			}	
+			if(pprevious_stats->RxMIMOSignalStrength[rfpath]  > priv->stats.rx_rssi_percentage[rfpath])
+			{
+				priv->stats.rx_rssi_percentage[rfpath] = 
+					( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + 
+					(pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
+				priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath]  + 1;
+			}
+			else
+			{
+				priv->stats.rx_rssi_percentage[rfpath] = 
+					( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + 
+					(pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
+			}	
+			RT_TRACE(COMP_DBG,"Jacken -> priv->RxStats.RxRSSIPercentage[rfPath]  = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
+		}		
+	}
+	
+	
+	if(pprevious_stats->bPacketBeacon)
+	{
+		if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
+		{
+			slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;	
+			last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
+			priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
+		}
+		priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
+		priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
+		slide_beacon_adc_pwdb_index++;
+		if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
+			slide_beacon_adc_pwdb_index = 0;
+		pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
+		if(pprevious_stats->RxPWDBAll >= 3)
+			pprevious_stats->RxPWDBAll -= 3;
+	}
+
+	RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n", 
+				pprevious_stats->bIsCCK? "CCK": "OFDM",
+				pprevious_stats->RxPWDBAll);
+
+	if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
+	{
+		if(priv->undecorated_smoothed_pwdb < 0)	
+		{
+			priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
+		}
+#if 1
+		if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
+		{
+			priv->undecorated_smoothed_pwdb =	
+					( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + 
+					(pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
+			priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
+		}
+		else
+		{
+			priv->undecorated_smoothed_pwdb =	
+					( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + 
+					(pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
+		}
+#else
+		if(pPreviousRfd->Status.RxPWDBAll > (u32)pHalData->UndecoratedSmoothedPWDB)
+		{
+			pHalData->UndecoratedSmoothedPWDB = 	
+					( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
+			pHalData->UndecoratedSmoothedPWDB = pHalData->UndecoratedSmoothedPWDB + 1;
+		}
+		else
+		{
+			pHalData->UndecoratedSmoothedPWDB = 	
+					( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
+		}		
+#endif
+		rtl819x_update_rxsignalstatistics8190pci(priv,pprevious_stats);
+	}
+
+	if(pprevious_stats->SignalQuality == 0)
+	{
+	}
+	else
+	{
+		if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
+			if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
+				slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
+				last_evm = priv->stats.slide_evm[slide_evm_index];
+				priv->stats.slide_evm_total -= last_evm;
+			}
+	
+			priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
+	
+			priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
+			if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
+				slide_evm_index = 0;
+	
+			tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
+			priv->stats.signal_quality = tmp_val;
+			priv->stats.last_signal_strength_inpercent = tmp_val;
+		}
+
+		if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
+		{
+			for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) 
+			{
+				if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
+				{
+					if(priv->stats.rx_evm_percentage[nspatial_stream] == 0)	
+					{
+						priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
+					}
+					priv->stats.rx_evm_percentage[nspatial_stream] = 
+						( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) + 
+						(pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
+				}
+			}
+		}
+	}
+#endif
+	
+}
+
+
+
+void rtl8192se_TranslateRxSignalStuff(struct net_device *dev, 
+        struct sk_buff *skb,
+        struct rtllib_rx_stats * pstats,
+        prx_desc pdesc,	
+        prx_fwinfo pdrvinfo)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	bool bpacket_match_bssid, bpacket_toself;
+	bool bPacketBeacon=false;
+	struct rtllib_hdr_3addr *hdr;
+#ifdef _RTL8192_EXT_PATCH_
+	struct rtllib_network* pnet=NULL;
+	u8	*psaddr;
+	struct sta_info *pEntry = NULL;
+#else
+	bool bToSelfBA=false;
+	static struct rtllib_rx_stats  previous_stats;
+#endif
+	u16 fc,type;
+	u8* tmp_buf;
+	u8	*praddr;
+
+	tmp_buf = skb->data + pstats->RxDrvInfoSize + pstats->RxBufShift;
+
+	hdr = (struct rtllib_hdr_3addr *)tmp_buf;
+	fc = le16_to_cpu(hdr->frame_ctl);
+	type = WLAN_FC_GET_TYPE(fc);	
+	praddr = hdr->addr1;
+
+#ifdef _RTL8192_EXT_PATCH_
+	psaddr = hdr->addr2;
+	if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->mshobj->ext_patch_get_mpinfo))
+		pnet = priv->mshobj->ext_patch_get_mpinfo(dev,psaddr);	
+	if(priv->rtllib->iw_mode == IW_MODE_ADHOC){
+		pEntry = GetStaInfo(priv->rtllib, psaddr);
+	}
+#endif
+#ifdef _RTL8192_EXT_PATCH_
+	bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
+	if(pnet){
+		bpacket_match_bssid = bpacket_match_bssid;
+	}
+	else{
+		bpacket_match_bssid = bpacket_match_bssid &&
+			(!compare_ether_addr(priv->rtllib->current_network.bssid, 
+					     (fc & RTLLIB_FCTL_TODS)? hdr->addr1 : 
+					     (fc & RTLLIB_FCTL_FROMDS )? hdr->addr2 : hdr->addr3));
+	}
+#else
+	bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) &&
+			(!compare_ether_addr(priv->rtllib->current_network.bssid,	
+					     (fc & RTLLIB_FCTL_TODS)? hdr->addr1 : 
+					     (fc & RTLLIB_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
+			&& (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
+#endif
+	bpacket_toself =  bpacket_match_bssid & (!compare_ether_addr(praddr, priv->rtllib->dev->dev_addr));
+	if(WLAN_FC_GET_FRAMETYPE(fc)== RTLLIB_STYPE_BEACON){
+		bPacketBeacon = true;
+	}
+#ifndef _RTL8192_EXT_PATCH_  
+	if(WLAN_FC_GET_FRAMETYPE(fc) == RTLLIB_STYPE_BLOCKACK){
+		if ((!compare_ether_addr(praddr,dev->dev_addr)))
+			bToSelfBA = true;
+	}
+#endif	
+	if(bpacket_match_bssid){
+		priv->stats.numpacket_matchbssid++;
+	}
+	if(bpacket_toself){
+		priv->stats.numpacket_toself++;
+	}
+#ifdef _RTL8192_EXT_PATCH_
+	rtl8192se_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, bpacket_match_bssid,
+			bpacket_toself ,bPacketBeacon);
+	rtl8192se_process_phyinfo(priv, tmp_buf,pstats,pnet, pEntry);
+
+#else
+	rtl8192se_process_phyinfo(priv, tmp_buf,&previous_stats, pstats);
+	rtl8192se_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &previous_stats, bpacket_match_bssid,
+			bpacket_toself ,bPacketBeacon, bToSelfBA);
+	rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
+#endif	
+
+}
+
+void rtl8192se_UpdateReceivedRateHistogramStatistics(
+	struct net_device *dev,
+	struct rtllib_rx_stats* pstats
+	)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u32 rcvType=1;   
+	u32 rateIndex;
+	u32 preamble_guardinterval;  
+	    
+	#if 0
+	if (pRfd->queue_id == CMPK_RX_QUEUE_ID)
+		return;
+	#endif
+	if(pstats->bCRC)
+		rcvType = 2;
+	else if(pstats->bICV)
+		rcvType = 3;
+	    
+	if(pstats->bShortPreamble)
+		preamble_guardinterval = 1;
+	else
+		preamble_guardinterval = 0;
+
+	switch(pstats->rate)
+	{
+		case MGN_1M:    rateIndex = 0;  break;
+	    	case MGN_2M:    rateIndex = 1;  break;
+	    	case MGN_5_5M:  rateIndex = 2;  break;
+	    	case MGN_11M:   rateIndex = 3;  break;
+	    	case MGN_6M:    rateIndex = 4;  break;
+	    	case MGN_9M:    rateIndex = 5;  break;
+	    	case MGN_12M:   rateIndex = 6;  break;
+	    	case MGN_18M:   rateIndex = 7;  break;
+	    	case MGN_24M:   rateIndex = 8;  break;
+	    	case MGN_36M:   rateIndex = 9;  break;
+	    	case MGN_48M:   rateIndex = 10; break;
+	    	case MGN_54M:   rateIndex = 11; break;
+	    	case MGN_MCS0:  rateIndex = 12; break;
+	    	case MGN_MCS1:  rateIndex = 13; break;
+	    	case MGN_MCS2:  rateIndex = 14; break;
+	    	case MGN_MCS3:  rateIndex = 15; break;
+	    	case MGN_MCS4:  rateIndex = 16; break;
+	    	case MGN_MCS5:  rateIndex = 17; break;
+	    	case MGN_MCS6:  rateIndex = 18; break;
+	    	case MGN_MCS7:  rateIndex = 19; break;
+	    	case MGN_MCS8:  rateIndex = 20; break;
+	    	case MGN_MCS9:  rateIndex = 21; break;
+	    	case MGN_MCS10: rateIndex = 22; break;
+	    	case MGN_MCS11: rateIndex = 23; break;
+	    	case MGN_MCS12: rateIndex = 24; break;
+	    	case MGN_MCS13: rateIndex = 25; break;
+	    	case MGN_MCS14: rateIndex = 26; break;
+	    	case MGN_MCS15: rateIndex = 27; break;
+		default:        rateIndex = 28; break;
+	}
+	priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
+	priv->stats.received_rate_histogram[0][rateIndex]++; 
+	priv->stats.received_rate_histogram[rcvType][rateIndex]++;
+}
+
+bool rtl8192se_rx_query_status_desc(struct net_device* dev, struct rtllib_rx_stats*  stats, rx_desc *pdesc, struct sk_buff* skb)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u32	PHYStatus	= pdesc->PHYStatus;
+	rx_fwinfo*		pDrvInfo;
+	stats->Length 		= (u16)pdesc->Length;	
+	stats->RxDrvInfoSize = (u8)pdesc->DrvInfoSize*8;
+	stats->RxBufShift 	= (u8)((pdesc->Shift)&0x03);      
+	stats->bICV 			= (u16)pdesc->ICVError;
+	stats->bCRC 			= (u16)pdesc->CRC32;
+	stats->bHwError 		= (u16)(pdesc->CRC32|pdesc->ICVError);	
+	stats->Decrypted 	= !pdesc->SWDec;
+	stats->rate = (u8)pdesc->RxMCS;
+	stats->bShortPreamble= (u16)pdesc->SPLCP;
+	stats->bIsAMPDU 		= (bool)(pdesc->PAGGR==1);
+	stats->bFirstMPDU 	= (bool)((pdesc->PAGGR==1) && (pdesc->FAGGR==1));
+	stats->TimeStampLow 	= pdesc->TSFL;
+	stats->RxIs40MHzPacket= (bool)pdesc->BandWidth;
+	if(IS_UNDER_11N_AES_MODE(ieee))
+	{
+		if(stats->bICV && !stats->bCRC)
+		{
+			stats->bICV = false;
+			stats->bHwError = false;
+		}
+	}
+
+	
+	if(stats->Length > 0x2000 || stats->Length < 24)
+	{
+		RT_TRACE(COMP_ERR, "Err RX pkt len = 0x%x\n", stats->Length);
+		stats->bHwError |= 1;
+	}
+	rtl8192se_UpdateReceivedRateHistogramStatistics(dev, stats);
+
+	if(!stats->bHwError)
+		stats->rate = HwRateToMRate92S((bool)(pdesc->RxHT), (u8)(pdesc->RxMCS));
+	else
+	{
+		stats->rate = MGN_1M;
+		return false;
+	}
+
+	rtl819x_UpdateRxPktTimeStamp(dev, stats);	
+
+	if((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
+		stats->bShift = 1;	
+
+	if (PHYStatus == true)
+	{
+		pDrvInfo = (rx_fwinfo*)(skb->data + stats->RxBufShift);
+			
+		rtl8192se_TranslateRxSignalStuff(dev, skb, stats, pdesc, pDrvInfo); 
+
+	}
+	return true;	
+}
+
+void rtl8192se_halt_adapter(struct net_device *dev, bool bReset)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+        int i;
+	u8	wait = 30;	
+
+	RT_TRACE(COMP_INIT, "==> rtl8192se_halt_adapter()\n");
+	
+#if 1
+	while (wait-- >= 10 && priv->PwrDomainProtect == true)
+	{
+		if (priv->PwrDomainProtect == true)
+		{
+			RT_TRACE(COMP_INIT, "Delay 20ms to wait PwrDomainProtect\n");
+			mdelay(20);
+		}
+		else
+			break;
+	}
+
+	if (wait == 9)
+		RT_TRACE(COMP_INIT, "PwrDomainProtect FAIL\n");
+#endif
+
+	priv->rtllib->state = RTLLIB_NOLINK;
+	rtl8192se_update_msr(dev);
+#if 1
+	PHY_SetRtl8192seRfHalt(dev);
+#endif
+	udelay(100);
+
+#if 0
+	udelay(20);
+	if (!bReset) {
+		mdelay(20);
+	}	
+#endif	
+        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+                skb_queue_purge(&priv->rtllib->skb_waitQ [i]);
+        }
+        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+                skb_queue_purge(&priv->rtllib->skb_aggQ [i]);
+        }
+#ifdef _RTL8192_EXT_PATCH_	
+		for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+                skb_queue_purge(&priv->rtllib->skb_meshaggQ [i]);
+        }
+#endif
+
+	skb_queue_purge(&priv->skb_queue);
+	RT_TRACE(COMP_INIT, "<== HaltAdapter8192SE()\n");
+	return;
+}
+
+u8 GetFreeRATRIndex8192SE (struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	u8 bitmap = priv->RATRTableBitmap;
+	u8 ratr_index = 0;
+	for(	;ratr_index<7; ratr_index++)
+	{
+		if((bitmap & BIT0) == 0)
+			{
+				priv->RATRTableBitmap |= BIT0<<ratr_index;
+				return ratr_index;
+			}
+		bitmap = bitmap >>1;
+	}
+	return ratr_index;
+}
+
+void rtl8192se_update_ratr_table(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u32 ratr_value = 0;
+	u8 ratr_index = 0;
+	u8 bNMode = 0;
+	u16 shortGI_rate = 0;
+	u32 tmp_ratr_value = 0;
+	u8 MimoPs;
+	WIRELESS_MODE WirelessMode;
+	u8 bCurTxBW40MHz, bCurShortGI40MHz, bCurShortGI20MHz;
+	
+	if(ieee->iw_mode == IW_MODE_ADHOC){	
+		if(pEntry == NULL){
+			printk("Doesn't have match Entry\n");
+			return;
+		}	
+
+		if(pEntry->ratr_index != 8)
+			ratr_index = pEntry->ratr_index;
+		else
+		        ratr_index = GetFreeRATRIndex8192SE(dev);
+		
+		if(ratr_index == 7){
+			RT_TRACE(COMP_RATE, "Ratrtable are full");
+			return;
+		}
+		MimoPs = pEntry->htinfo.MimoPs;
+
+		if((ieee->mode == WIRELESS_MODE_G) && (pEntry->wireless_mode == WIRELESS_MODE_N_24G))
+			WirelessMode = ieee->mode;
+		else	
+			WirelessMode = pEntry->wireless_mode;
+
+		bCurTxBW40MHz = pEntry->htinfo.bCurTxBW40MHz;
+		bCurShortGI40MHz = pEntry->htinfo.bCurShortGI40MHz;
+		bCurShortGI20MHz = pEntry->htinfo.bCurShortGI20MHz;		
+		pEntry->ratr_index = ratr_index;
+	}
+	else  
+	{
+		ratr_index = 0;
+		WirelessMode = ieee->mode;
+		MimoPs = ieee->pHTInfo->PeerMimoPs;
+		bCurTxBW40MHz = ieee->pHTInfo->bCurTxBW40MHz;
+		bCurShortGI40MHz = ieee->pHTInfo->bCurShortGI40MHz;
+		bCurShortGI20MHz = ieee->pHTInfo->bCurShortGI20MHz;					
+	}
+
+	rtl8192_config_rate(dev, (u16*)(&ratr_value));
+	ratr_value |= (*(u16*)(pMcsRate)) << 12;
+	switch (WirelessMode)
+	{
+		case IEEE_A:
+			ratr_value &= 0x00000FF0;
+			break;
+		case IEEE_B:
+			ratr_value &= 0x0000000D;
+			break;
+		case IEEE_G:
+		case IEEE_G|IEEE_B:
+			ratr_value &= 0x00000FF5;
+			break;
+		case IEEE_N_24G:
+		case IEEE_N_5G:
+			bNMode = 1;
+			if (MimoPs == 0) 
+				ratr_value &= 0x0007F005;
+			else{
+				if (priv->rf_type == RF_1T2R ||priv->rf_type  == RF_1T1R || (ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_2SS)){
+					if ((bCurTxBW40MHz) && !(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_40_MHZ))
+						ratr_value &= 0x000FF015;
+					else
+						ratr_value &= 0x000ff005;
+				}else{
+					if ((bCurTxBW40MHz) && !(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_40_MHZ))
+						ratr_value &= 0x0f0ff015;
+					else
+						ratr_value &= 0x0f0ff005;
+					}
+			}
+			break;
+		default:
+			printk("====>%s(), mode is not correct:%x\n", __FUNCTION__,WirelessMode);
+			break; 
+	}
+	if (priv->card_8192_version>= VERSION_8192S_BCUT)
+		ratr_value &= 0x0FFFFFFF;
+	else if (priv->card_8192_version == VERSION_8192S_ACUT)
+		ratr_value &= 0x0FFFFFF0;	
+	
+	if (((ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_SHORT_GI)==0) &&
+		bNMode && ((bCurTxBW40MHz && bCurShortGI40MHz) ||
+	    (!bCurTxBW40MHz && bCurShortGI20MHz)))
+	{
+		ratr_value |= 0x10000000;  
+		tmp_ratr_value = (ratr_value>>12);
+		for(shortGI_rate=15; shortGI_rate>0; shortGI_rate--)
+		{
+			if((1<<shortGI_rate) & tmp_ratr_value)
+				break;
+		}	
+		shortGI_rate = (shortGI_rate<<12)|(shortGI_rate<<8)|\
+			       (shortGI_rate<<4)|(shortGI_rate);
+		write_nic_byte(dev, SG_RATE, shortGI_rate);
+	}
+
+	if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+	{
+		ratr_value &= 0xfffffff0; 
+		printk("UpdateHalRATRTable8192SE(), for HT_IOT_ACT_WA_IOT_Broadcom, ratr_value = 0x%x\n", ratr_value);
+	}
+	
+	write_nic_dword(dev, ARFR0+ratr_index*4, ratr_value);
+	RT_TRACE(COMP_RATE, "%s: ratr_index=%d ratr_table=0x%8.8x\n", __FUNCTION__,ratr_index, read_nic_dword(dev, ARFR0+ratr_index*4));
+	if (ratr_value & 0xfffff000){
+		rtl8192se_set_fw_cmd(dev, FW_CMD_RA_REFRESH_N);
+	}
+	else{
+		rtl8192se_set_fw_cmd(dev, FW_CMD_RA_REFRESH_BG);
+	}
+}
+
+int r8192se_resume_firm(struct net_device *dev)
+{
+	write_nic_byte(dev, 0x42, 0xFF);
+	write_nic_word(dev, 0x40, 0x77FC);
+	write_nic_word(dev, 0x40, 0x57FC);
+	write_nic_word(dev, 0x40, 0x37FC);
+	write_nic_word(dev, 0x40, 0x77FC);
+	
+	udelay(100);
+
+	write_nic_word(dev, 0x40, 0x57FC);
+	write_nic_word(dev, 0x40, 0x37FC);
+	write_nic_byte(dev, 0x42, 0x00);
+
+	return 0;
+}
+void PHY_SetRtl8192seRfHalt(struct net_device* dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
+	u8 u1bTmp;
+
+	if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS && priv->LedStrategy == SW_LED_MODE8)	
+	{
+		SET_RTL8192SE_RF_SLEEP(dev);
+		return;
+	}
+
+#ifdef LOW_DOWN_POWER
+	if(0)
+#else
+	if(priv->bDriverIsGoingToUnload)
+#endif
+		write_nic_byte(dev,0x560,0x0);
+
+	RT_TRACE(COMP_PS, "PHY_SetRtl8192seRfHalt save BB/RF\n");
+	u1bTmp = read_nic_byte(dev, LDOV12D_CTRL);
+	u1bTmp |= BIT0;
+	write_nic_byte(dev, LDOV12D_CTRL, u1bTmp);
+	write_nic_byte(dev, SPS1_CTRL, 0x0);
+	write_nic_byte(dev, TXPAUSE, 0xFF);
+	write_nic_word(dev, CMDR, 0x57FC);
+	udelay(100);
+	write_nic_word(dev, CMDR, 0x77FC);
+	write_nic_byte(dev, PHY_CCA, 0x0);
+	udelay(10);
+	write_nic_word(dev, CMDR, 0x37FC);
+	udelay(10);
+	write_nic_word(dev, CMDR, 0x77FC);			
+	udelay(10);
+	write_nic_word(dev, CMDR, 0x57FC);
+	write_nic_word(dev, CMDR, 0x0000);
+
+
+#ifdef LOW_DOWN_POWER
+	if(0)
+#else
+	if(priv->bDriverIsGoingToUnload)
+#endif
+        {
+	       u1bTmp = read_nic_byte(dev, (SYS_FUNC_EN+ 1));	
+		u1bTmp &= ~(BIT0);
+		write_nic_byte(dev, SYS_FUNC_EN+1, u1bTmp);
+        }
+
+	
+	u1bTmp = read_nic_byte(dev, (SYS_CLKR + 1));
+	
+	if (u1bTmp & BIT7) {
+		u1bTmp &= ~(BIT6 | BIT7);					
+		if(!HalSetSysClk8192SE(dev, u1bTmp)) {
+			printk("Switch ctrl path fail\n");
+			return;
+		}
+	}
+
+#ifdef LOW_DOWN_POWER
+        if((priv->rtllib->RfOffReason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) &&
+                !priv->bDriverIsGoingToUnload)
+#else
+	if(priv->rtllib->RfOffReason==RF_CHANGE_BY_IPS  && !priv->bDriverIsGoingToUnload)
+#endif
+	{
+		write_nic_byte(dev, 0x03, 0xF9);
+	} else		
+	{
+		write_nic_byte(dev, 0x03, 0xF9);
+	}
+	write_nic_byte(dev, SYS_CLKR+1, 0x70);
+	write_nic_byte(dev, AFE_PLL_CTRL+1, 0x68);
+	write_nic_byte(dev,  AFE_PLL_CTRL, 0x00);	
+	write_nic_byte(dev, LDOA15_CTRL, 0x34);
+	write_nic_byte(dev, AFE_XTAL_CTRL, 0x0E);
+	RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+}	
+
+
+/*
+*	Description:
+*		Set RateAdaptive Mask
+*	/param 	Adapter		Pionter to Adapter entity
+*	/param	bMulticast	TURE if broadcast or multicast, used for softAP basic rate
+*	/param	macId		macID to set
+*	/param 	wirelessMode	wireless mode of associated AP/client
+*	/return	void
+*	
+*/
+void UpdateHalRAMask8192SE(
+			struct net_device* dev,
+			bool bMulticast,
+			u8   macId,
+			u8   MimoPs,
+			u8   WirelessMode,
+			u8   bCurTxBW40MHz,
+			u8   rssi_level){
+	struct r8192_priv* 	priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo;
+	u8* 	pMcsRate = ieee->dot11HTOperationalRateSet;
+	u32	ratr_bitmap, RateSet, mask=0, band = 0, ratr_value = 0;
+	u8   shortGI_rate = 0, bShortGI = false; 
+
+	RT_TRACE(COMP_RATE, "%s: macid:%d MimoPs=%d WirelessMode=0x%x bCurTxBW40MHz=%d rssid_level=%d\n",__FUNCTION__, macId, MimoPs, WirelessMode,bCurTxBW40MHz, rssi_level);
+	rtl8192_config_rate(dev, (u16*)&RateSet);
+	RateSet |= (*(u16*)(pMcsRate)) << 12;
+	ratr_bitmap = RateSet;
+	
+	switch (WirelessMode){
+		case WIRELESS_MODE_B:
+			band |= WIRELESS_11B;
+			ratr_bitmap &= 0x0000000d;
+			break;
+		case WIRELESS_MODE_G:
+		case (WIRELESS_MODE_G |WIRELESS_MODE_B):
+			band |= (WIRELESS_11G | WIRELESS_11B);
+			
+			if(rssi_level == 1)
+				ratr_bitmap &= 0x00000f00;
+			else if(rssi_level == 2)
+				ratr_bitmap &= 0x00000ff0;
+			else
+				ratr_bitmap &= 0x00000ff5;
+			break;
+		case WIRELESS_MODE_A:
+			band |= WIRELESS_11A;
+			ratr_bitmap &= 0x00000ff0;
+			break;
+		case WIRELESS_MODE_N_24G:
+		case WIRELESS_MODE_N_5G:
+		{
+			band |= (WIRELESS_11N| WIRELESS_11G| WIRELESS_11B);
+			if(MimoPs == MIMO_PS_STATIC){
+				if(rssi_level == 1)
+					ratr_bitmap &= 0x00070000;
+				else if(rssi_level == 2)
+					ratr_bitmap &= 0x0007f000;
+				else
+					ratr_bitmap &= 0x0007f005;
+			}else{
+				if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R){
+					if (bCurTxBW40MHz){
+						if(rssi_level == 1)
+							ratr_bitmap &= 0x000f0000;
+						else if(rssi_level == 2)
+							ratr_bitmap &= 0x000ff000;
+						else
+							ratr_bitmap &= 0x000ff015;
+					}else{
+						if(rssi_level == 1)
+							ratr_bitmap &= 0x000f0000;
+						else if(rssi_level == 2)
+							ratr_bitmap &= 0x000ff000;
+						else
+							ratr_bitmap &= 0x000ff005;
+					}	
+				}else{
+					if (bCurTxBW40MHz){
+						if(rssi_level == 1)
+							ratr_bitmap &= 0x0f0f0000;
+						else if(rssi_level == 2)
+							ratr_bitmap &= 0x0f0ff000;
+						else
+							ratr_bitmap &= 0x0f0ff015;
+					}else{
+						if(rssi_level == 1)
+							ratr_bitmap &= 0x0f0f0000;
+						else if(rssi_level == 2)
+							ratr_bitmap &= 0x0f0ff000;
+						else
+							ratr_bitmap &= 0x0f0ff005;
+					}
+				}
+			}
+			if( (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
+				(!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz)){
+				if(macId == 0)
+					bShortGI = true;
+				else
+					bShortGI = false;
+			}
+			break;
+		}
+		default:
+			band |= (WIRELESS_11N| WIRELESS_11G| WIRELESS_11B);
+			
+			if(priv->rf_type == RF_1T2R)
+				ratr_bitmap &= 0x000ff0ff;
+			else
+				ratr_bitmap &= 0x0f0ff0ff;
+			break;
+	}
+
+	if (priv->card_8192_version  >= VERSION_8192S_BCUT)
+		ratr_bitmap &= 0x0FFFFFFF;
+	else if (priv->card_8192_version  == VERSION_8192S_ACUT)
+		ratr_bitmap &= 0x0FFFFFF0;	
+
+	if(bShortGI){
+		ratr_bitmap |= 0x10000000;
+		ratr_value = (ratr_bitmap>>12);
+		for(shortGI_rate=15; shortGI_rate>0; shortGI_rate--){
+			if((1<<shortGI_rate) & ratr_value)
+				break;
+		}	
+		shortGI_rate = (shortGI_rate<<12)|(shortGI_rate<<8)|(shortGI_rate<<4)|(shortGI_rate);
+		write_nic_byte(dev, SG_RATE, shortGI_rate);
+	}	
+	
+	if(macId == 0)
+	{
+		if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+			ratr_bitmap &= 0xfffffff0; 
+		if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_SHORT_GI)
+			ratr_bitmap &=0x0fffffff;
+	}		
+	mask |= (bMulticast ? 1 : 0)<<9 | (macId & 0x1f)<<4 | (band & 0xf);
+
+	RT_TRACE(COMP_RATE, "%s(): mask = %x, bitmap = %x\n",__func__, mask, ratr_bitmap);
+	write_nic_dword(dev, 0x2c4, ratr_bitmap);
+	write_nic_dword(dev, WFM5, (FW_RA_UPDATE_MASK | (mask << 8)));
+}
+
+u8 HalSetSysClk8192SE( struct net_device *dev, u8 Data)
+{
+#if 0
+	write_nic_byte(dev, (SYS_CLKR + 1), Data);
+	udelay(200);;
+	return 1;
+#else
+	{
+		u8				WaitCount = 100;
+		bool bResult = false;
+
+#ifdef TO_DO_LIST
+		RT_DISABLE_FUNC(Adapter, DF_IO_BIT);
+
+		do
+		{
+			if(pDevice->IOCount == 0)
+				break;
+			delay_us(10);
+		}while(WaitCount -- > 0);
+
+		if(WaitCount == 0)
+		{ 
+			RT_ENABLE_FUNC(Adapter, DF_IO_BIT);
+			RT_TRACE(COMP_POWER, DBG_WARNING, ("HalSetSysClk8192SE(): Wait too long! Skip ....\n"));
+			return false;
+		}
+		#endif
+		write_nic_byte(dev,SYS_CLKR + 1,Data);
+
+		udelay(400);
+
+
+		{
+			u8 TmpValue;
+			TmpValue=read_nic_byte(dev,SYS_CLKR + 1);
+			bResult = ((TmpValue&BIT7)== (Data & BIT7));
+			if((Data &(BIT6|BIT7)) == false)
+			{			
+				WaitCount = 100;
+				TmpValue = 0;
+				while(1) 
+				{
+					WaitCount--;
+					TmpValue=read_nic_byte(dev, SYS_CLKR + 1); 
+					if((TmpValue &BIT6))
+						break;
+					printk("wait for BIT6 return value %x\n",TmpValue);	
+					if(WaitCount==0)
+						break;
+					udelay(10);
+				}
+				if(WaitCount == 0)
+					bResult = false;
+				else
+					bResult = true;
+			}
+		}
+#ifdef TO_DO_LIST
+		RT_ENABLE_FUNC(Adapter, DF_IO_BIT);
+#endif
+		RT_TRACE(COMP_PS,"HalSetSysClk8192SE():Value = %02X, return: %d\n", Data, bResult);
+		return bResult;
+	}
+#endif
+}
+
+static u8 LegacyRateSet[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c};
+void GetHwReg8192SE(struct net_device *dev,u8 variable,u8* val)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	switch(variable)
+	{
+		case HW_VAR_INIT_TX_RATE: 
+			{
+				u8 RateIdx = read_nic_byte(dev, TX_RATE_REG);
+				if(RateIdx < 76)
+					*((u8*)(val)) = (RateIdx<12)?(LegacyRateSet[RateIdx]):((RateIdx-12)|0x80);
+				else
+					*((u8*)(val)) = 0;
+			}
+			break;
+
+		case HW_VAR_RCR:
+			*((u32*)(val)) = priv->ReceiveConfig;
+		break;
+		
+		default:
+			break;
+	}
+}
+
+void SetHwReg8192SE(struct net_device *dev,u8 variable,u8* val)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	switch(variable)
+	{
+		case HW_VAR_AMPDU_MIN_SPACE:
+		{
+			u8	MinSpacingToSet;
+			u8	SecMinSpace;
+
+			MinSpacingToSet = *((u8*)val);
+			if(MinSpacingToSet <= 7)
+			{
+				if((priv->rtllib->current_network.capability & WLAN_CAPABILITY_PRIVACY) == 0)  
+					SecMinSpace = 0;
+				else if (priv->rtllib->rtllib_ap_sec_type && 
+						(priv->rtllib->rtllib_ap_sec_type(priv->rtllib) 
+							 & (SEC_ALG_WEP|SEC_ALG_TKIP))) 
+					SecMinSpace = 7;
+				else
+					SecMinSpace = 1;
+
+				if(MinSpacingToSet < SecMinSpace)
+					MinSpacingToSet = SecMinSpace;
+				priv->rtllib->MinSpaceCfg = ((priv->rtllib->MinSpaceCfg&0xf8) |MinSpacingToSet);
+				RT_TRACE(COMP_MLME, "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", priv->rtllib->MinSpaceCfg);
+				write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg);	
+			}
+		}
+		break;	
+		case HW_VAR_SHORTGI_DENSITY:
+		{
+			u8	DensityToSet;
+		
+			DensityToSet = *((u8*)val);		
+			priv->rtllib->MinSpaceCfg|= (DensityToSet<<3);		
+			RT_TRACE(COMP_MLME, "Set HW_VAR_SHORTGI_DENSITY: %#x\n", priv->rtllib->MinSpaceCfg);
+			write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg);
+			break;		
+		}
+		case HW_VAR_AMPDU_FACTOR:
+		{
+			u8	FactorToSet;
+			u8	RegToSet;
+			u8	FactorLevel[18] = {2, 4, 4, 7, 7, 13, 13, 13, 2, 7, 7, 13, 13, 15, 15, 15, 15, 0};
+			u8	index = 0;
+		
+			FactorToSet = *((u8*)val);
+			if(FactorToSet <= 3)
+			{
+				FactorToSet = (1<<(FactorToSet + 2));
+				if(FactorToSet>0xf)
+					FactorToSet = 0xf;
+
+				for(index=0; index<17; index++)
+				{
+					if(FactorLevel[index] > FactorToSet)
+						FactorLevel[index] = FactorToSet;
+				}
+
+				for(index=0; index<8; index++)
+				{
+					RegToSet = ((FactorLevel[index*2]) | (FactorLevel[index*2+1]<<4));
+					write_nic_byte(dev, AGGLEN_LMT_L+index, RegToSet);
+				}
+				RegToSet = ((FactorLevel[16]) | (FactorLevel[17]<<4));
+				write_nic_byte(dev, AGGLEN_LMT_H, RegToSet);
+
+				RT_TRACE(COMP_MLME, "Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet);
+			}
+		}
+		break;
+		case HW_VAR_BASIC_RATE:
+		{
+			u16				BrateCfg = 0;
+			u8				RateIndex = 0;
+
+			
+			rtl8192_config_rate(dev, &BrateCfg);
+
+			if (priv->card_8192_version == VERSION_8192S_ACUT)
+				priv->basic_rate = BrateCfg = BrateCfg & 0x150;
+			else if (priv->card_8192_version == VERSION_8192S_BCUT)
+				priv->basic_rate = BrateCfg = BrateCfg & 0x15f;
+		
+  	                if(priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_CISCO && ((BrateCfg &0x150)==0))
+			{
+				BrateCfg |=0x010;
+			}
+			if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+			{	
+				BrateCfg &= 0x1f0;
+				printk("HW_VAR_BASIC_RATE, HT_IOT_ACT_WA_IOT_Broadcom, BrateCfg = 0x%x\n", BrateCfg);
+			}
+			write_nic_byte(dev, RRSR, BrateCfg&0xff);
+			write_nic_byte(dev, RRSR+1, (BrateCfg>>8)&0xff);
+
+			while(BrateCfg > 0x1)
+			{
+				BrateCfg = (BrateCfg >> 1);
+				RateIndex++;
+			}
+			write_nic_byte(dev, INIRTSMCS_SEL, RateIndex);
+		}
+		break;
+		case HW_VAR_RETRY_LIMIT:
+		{
+			u8 RetryLimit = ((u8*)(val))[0];
+			
+			priv->ShortRetryLimit = RetryLimit;
+			priv->LongRetryLimit = RetryLimit;
+			
+			write_nic_word(dev, RETRY_LIMIT, 
+							RetryLimit << RETRY_LIMIT_SHORT_SHIFT | \
+							RetryLimit << RETRY_LIMIT_LONG_SHIFT);
+		}					
+		break;
+		case HW_VAR_BEACON_INTERVAL:
+		{
+			write_nic_word(dev, BCN_INTERVAL, *((u16*)val));
+			PHY_SetBeaconHwReg(dev, *((u16*)val));
+		}
+		break;
+		
+		case HW_VAR_BSSID:
+			write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
+			write_nic_word(dev, BSSIDR+4, ((u16*)(val+4))[0]);
+		break;
+
+		case HW_VAR_MEDIA_STATUS:
+		{
+			RT_OP_MODE	OpMode = *((RT_OP_MODE *)(val));
+			LED_CTL_MODE	LedAction = LED_CTL_NO_LINK;
+			u8		btMsr = read_nic_byte(dev, MSR);
+
+			btMsr &= 0xfc;
+			switch(OpMode)
+			{
+			case RT_OP_MODE_INFRASTRUCTURE:
+				btMsr |= MSR_INFRA;
+				LedAction = LED_CTL_LINK;
+				break;
+
+			case RT_OP_MODE_IBSS:
+				btMsr |= MSR_ADHOC;
+				break;
+
+			case RT_OP_MODE_AP:
+				btMsr |= MSR_AP;
+				LedAction = LED_CTL_LINK;
+				break;
+
+			default:
+				btMsr |= MSR_NOLINK;
+				break;
+			}
+
+			write_nic_byte(dev, MSR, btMsr);
+
+			{
+				u32	temp = read_nic_dword(dev, TCR);
+				write_nic_dword(dev, TCR, temp&(~BIT8));
+				write_nic_dword(dev, TCR, temp|BIT8);
+			}
+			priv->rtllib->LedControlHandler(dev, LedAction);
+		}
+		break;
+		
+		case HW_VAR_RCR:
+		{
+			write_nic_dword(dev, RCR,((u32*)(val))[0]);
+			priv->ReceiveConfig = ((u32*)(val))[0];
+		}
+		break;
+		
+		case HW_VAR_CECHK_BSSID:
+		{
+			u32	RegRCR, Type;
+
+			Type = ((u8*)(val))[0];
+			priv->rtllib->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR));
+			
+#if (RTL92SE_FPGA_VERIFY == 1)
+			RegRCR &= (~RCR_CBSSID);
+#else
+#if 1
+			if (Type == true)
+				RegRCR |= (RCR_CBSSID);
+			else if (Type == false)
+				RegRCR &= (~RCR_CBSSID);
+#endif
+			priv->rtllib->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) );
+#endif			
+		}
+		break;
+		
+		case HW_VAR_SLOT_TIME:
+		{
+
+			priv->slot_time = val[0];		
+			write_nic_byte(dev, SLOT_TIME, val[0]);
+
+#ifdef MERGE_TO_DO
+			if(priv->rtllib->current_network.qos_data.supported !=0)
+			{
+				for(eACI = 0; eACI < AC_MAX; eACI++)
+				{
+					priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, GET_WMM_PARAM_ELE_SINGLE_AC_PARAM(pStaQos->WMMParamEle, eACI) );
+				}
+			}
+			else
+			{
+				u8	u1bAIFS = aSifsTime + (2 * priv->slot_time);
+				
+				write_nic_byte(dev, REG_EDCA_VO_PARAM, u1bAIFS);
+				write_nic_byte(dev, REG_EDCA_VI_PARAM, u1bAIFS);
+				write_nic_byte(dev, REG_EDCA_BE_PARAM, u1bAIFS);
+				write_nic_byte(dev, REG_EDCA_BK_PARAM, u1bAIFS);
+			}
+#endif
+		}
+		break;
+
+		case HW_VAR_ACK_PREAMBLE:	
+		{
+			u8	regTmp;
+			priv->short_preamble = (bool)(*(u8*)val );
+			regTmp = (priv->nCur40MhzPrimeSC)<<5;		
+			if(priv->short_preamble)
+				regTmp |= 0x80;
+
+			write_nic_byte(dev, RRSR+2, regTmp);
+		}
+		break;	
+
+		default:
+			break;
+	}
+}
+
+void SetBeaconRelatedRegisters8192SE(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	struct rtllib_network *net = &priv->rtllib->current_network;
+	u16			BcnTimeCfg = 0;
+	u16			BcnCW = 6, BcnIFS = 0xf;
+	u16			AtimWindow = 2;	
+	int			OpMode = priv->rtllib->iw_mode;
+	u16			BcnInterval = net->beacon_interval;
+	write_nic_word(dev, ATIMWND, AtimWindow);
+	
+	write_nic_word(dev, BCN_INTERVAL, BcnInterval);
+	PHY_SetBeaconHwReg( dev, BcnInterval);
+
+	write_nic_word(dev, BCN_DRV_EARLY_INT, 10<<4);
+
+	write_nic_word(dev, BCN_DMATIME, 256); 
+
+	write_nic_byte(dev, BCN_ERR_THRESH, 100); 
+
+		
+	switch(OpMode)
+	{
+		case IW_MODE_ADHOC:
+			BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
+			break;
+		default:
+			printk("Invalid Operation Mode!!\n");
+			break;
+	}
+
+	BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+
+
+	{
+		u8 u1Temp = (u8)(BcnInterval);
+		write_nic_dword(dev, WFM5, 0xF1000000 |((u16)( u1Temp) << 8));
+		ChkFwCmdIoDone(dev);
+	}
+}
+
+void UpdateHalRATRTableIndex(struct net_device *dev)
+{
+	struct r8192_priv* priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	u8		bitmap = 0;
+	int		i;
+
+	for (i = 0; i < PEER_MAX_ASSOC; i++) {
+		if (NULL != ieee->peer_assoc_list[i]) {
+			bitmap |= BIT0 << ieee->peer_assoc_list[i]->ratr_index;
+		}
+	}
+
+	priv->RATRTableBitmap = bitmap;
+	return;
+}
+
+bool rtl8192se_check_ht_cap(struct net_device* dev, struct sta_info *sta, 
+		struct rtllib_network* net)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	PHT_CAPABILITY_ELE  pHTCapIE = NULL;
+	PHT_INFORMATION_ELE  pPeerHTInfo = NULL;
+	u8 ExtChlOffset=0;
+	u8	*pMcsFilter = NULL;
+	u16	nMaxAMSDUSize = 0;	
+	static u8	EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};	
+	static u8 	EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};
+
+	if ((ieee->mode != WIRELESS_MODE_N_24G) && 
+			(ieee->mode != WIRELESS_MODE_N_5G)) {
+		if (net->mode == IEEE_N_5G)
+			sta->wireless_mode = IEEE_A;
+		else if (net->mode == IEEE_N_24G) {
+			if (net->rates_ex_len > 0)
+				sta->wireless_mode = IEEE_G;
+			else
+				sta->wireless_mode = IEEE_B;
+		} else
+			sta->wireless_mode = net->mode;
+		printk("%s():i am G mode ,do not need to check Cap IE. wireless_mode=0x%x\n",
+				__FUNCTION__, sta->wireless_mode);
+		return false;
+	}
+	if ((ieee->mode ==WIRELESS_MODE_N_24G) 
+		&& ieee->pHTInfo->bRegSuppCCK== false) {
+		if(net->mode == IEEE_B){
+			sta->wireless_mode = net->mode;
+			printk("%s(): peer is B MODE return\n", __FUNCTION__);
+			return false;
+		}
+	}
+	if(net->bssht.bdHTCapLen  != 0)
+	{
+		sta->htinfo.bEnableHT = true;
+		sta->htinfo.bCurRxReorderEnable = ieee->pHTInfo->bRegRxReorderEnable;
+		if(net->mode == IEEE_A)
+			sta->wireless_mode = IEEE_N_5G;
+		else
+			sta->wireless_mode = IEEE_N_24G;
+	} else {
+		printk("%s(): have no HTCap IE, mode is %d\n",__FUNCTION__,net->mode);
+		sta->wireless_mode = net->mode;
+		sta->htinfo.bEnableHT = false;
+		return true;
+	}
+
+	if (!memcmp(net->bssht.bdHTCapBuf ,EWC11NHTCap, sizeof(EWC11NHTCap)))
+		pHTCapIE = (PHT_CAPABILITY_ELE)(&(net->bssht.bdHTCapBuf[4]));
+	else
+		pHTCapIE = (PHT_CAPABILITY_ELE)(net->bssht.bdHTCapBuf);
+
+	if (!memcmp(net->bssht.bdHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
+		pPeerHTInfo = (PHT_INFORMATION_ELE)(&net->bssht.bdHTInfoBuf[4]);
+	else		
+		pPeerHTInfo = (PHT_INFORMATION_ELE)(net->bssht.bdHTInfoBuf);
+	
+	ExtChlOffset=((ieee->pHTInfo->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+					(ieee->current_network.channel<=6)?
+					HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
+	printk("******** STA wireless mode %d\n", sta->wireless_mode);
+		
+	if (ieee->pHTInfo->bRegSuppCCK)
+		sta->htinfo.bSupportCck = (pHTCapIE->DssCCk==1)?true:false;
+	else {
+		if(pHTCapIE->DssCCk==1)
+			return false;
+	}
+
+	sta->htinfo.MimoPs= pHTCapIE->MimoPwrSave;
+
+	printk("******** PEER MP MimoPs %d\n", sta->htinfo.MimoPs);
+	if(ieee->pHTInfo->bRegBW40MHz)
+		sta->htinfo.bBw40MHz= (pHTCapIE->ChlWidth==1)?true:false;
+	else
+		sta->htinfo.bBw40MHz = false;
+
+	if((pPeerHTInfo->ExtChlOffset) != ExtChlOffset)
+		sta->htinfo.bBw40MHz = false;
+	
+	ieee->Peer_bCurBW40M = sta->htinfo.bBw40MHz;
+	printk("******** PEER MP bCurBW40M %d\n", sta->htinfo.bBw40MHz);
+	if(ieee->pHTInfo->bRegBW40MHz == true)
+		sta->htinfo.bCurTxBW40MHz = sta->htinfo.bBw40MHz;
+
+	printk("******** PEER MP bCurTxBW40MHz %d\n", sta->htinfo.bCurTxBW40MHz);
+	sta->htinfo.bCurShortGI20MHz= 
+		((ieee->pHTInfo->bRegShortGI20MHz)?((pHTCapIE->ShortGI20Mhz==1)?true:false):false);
+	sta->htinfo.bCurShortGI40MHz= 
+		((ieee->pHTInfo->bRegShortGI40MHz)?((pHTCapIE->ShortGI40Mhz==1)?true:false):false);
+	
+	printk("******** PEER MP bCurShortGI20MHz %d, bCurShortGI40MHz %d\n",sta->htinfo.bCurShortGI20MHz,sta->htinfo.bCurShortGI40MHz);
+	nMaxAMSDUSize = (pHTCapIE->MaxAMSDUSize==0)?3839:7935;
+	if(ieee->pHTInfo->nAMSDU_MaxSize >= nMaxAMSDUSize)	
+		sta->htinfo.AMSDU_MaxSize = nMaxAMSDUSize;
+	else
+		sta->htinfo.AMSDU_MaxSize = ieee->pHTInfo->nAMSDU_MaxSize;
+
+	printk("****************AMSDU_MaxSize=%d\n",sta->htinfo.AMSDU_MaxSize);
+		
+	if(ieee->pHTInfo->AMPDU_Factor >= pHTCapIE->MaxRxAMPDUFactor)
+		sta->htinfo.AMPDU_Factor = pHTCapIE->MaxRxAMPDUFactor;
+	else
+		sta->htinfo.AMPDU_Factor = ieee->pHTInfo->AMPDU_Factor;
+
+	if(ieee->pHTInfo->MPDU_Density >= pHTCapIE->MPDUDensity)
+		sta->htinfo.MPDU_Density = pHTCapIE->MPDUDensity;
+	else
+		sta->htinfo.MPDU_Density = ieee->pHTInfo->MPDU_Density;
+
+	HTFilterMCSRate(ieee, pHTCapIE->MCS, sta->htinfo.McsRateSet);
+	if(sta->htinfo.MimoPs == 0)  
+		pMcsFilter = MCS_FILTER_1SS;
+	else
+		pMcsFilter = MCS_FILTER_ALL;
+
+	sta->htinfo.HTHighestOperaRate = HTGetHighestMCSRate(ieee, sta->htinfo.McsRateSet, pMcsFilter);
+	printk("******** PEER MP HTHighestOperaRate %x\n",sta->htinfo.HTHighestOperaRate);
+
+	return true;
+	
+}
+
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
+void rtl8192se_check_tsf_wq(struct work_struct * work)
+{
+	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
+	struct rtllib_device *ieee = container_of(dwork, struct rtllib_device, check_tsf_wq);
+	struct net_device *dev = ieee->dev;
+#else
+void rtl8192se_check_tsf_wq(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+#endif
+	u32	CurrTsfHigh,CurrTsfLow;
+	u32	TargetTsfHigh,TargetTsfLow;
+					
+	CurrTsfHigh = read_nic_dword(dev, TSFR+4);
+	CurrTsfLow = (u32)(ieee->CurrTsf & 0xffff);
+	TargetTsfHigh = (u32)(ieee->TargetTsf >> 32);
+	TargetTsfLow = (u32)(ieee->TargetTsf & 0xffff);
+
+	printk("Current TSF Low = %x, Hight = %x\n",CurrTsfLow,CurrTsfHigh);
+	printk("Target TSF Low = %x, Hight = %x\n",TargetTsfLow,TargetTsfHigh);
+
+	ieee->CurrTsf |= (u64)CurrTsfHigh << 32;
+
+	if(ieee->CurrTsf < ieee->TargetTsf)
+	{
+		down(&ieee->wx_sem);
+
+		rtllib_stop_protocol(ieee,true);
+
+		ieee->ssid_set = 1;
+
+		rtllib_start_protocol(ieee);
+
+		up(&ieee->wx_sem);
+	}
+}
+
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20)
+void rtl8192se_update_assoc_sta_info_wq(struct work_struct * work)
+{
+	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
+	struct rtllib_device *ieee = container_of(dwork, struct rtllib_device, update_assoc_sta_info_wq);
+        struct net_device *dev = ieee->dev;
+#else
+void rtl8192se_update_assoc_sta_info_wq(struct net_device *dev)
+{
+        struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+#endif
+	struct sta_info * pEntry = NULL;
+	int idx = 0;
+	for(idx=0; idx<PEER_MAX_ASSOC; idx++)
+	{	
+		pEntry = ieee->peer_assoc_list[idx];
+		if(NULL != pEntry)
+		{
+			u8 * addr = pEntry->macaddr;
+				
+			if(ieee->bUseRAMask){
+				if((pEntry->wireless_mode & WIRELESS_MODE_N_24G) || (pEntry->wireless_mode & WIRELESS_MODE_N_5G))
+					pEntry->ratr_index = RATR_INX_WIRELESS_NGB;
+				else if(pEntry->wireless_mode & WIRELESS_MODE_G)
+					pEntry->ratr_index = RATR_INX_WIRELESS_GB;
+				else if(pEntry->wireless_mode & WIRELESS_MODE_B)
+					pEntry->ratr_index = RATR_INX_WIRELESS_B;
+				ieee->UpdateHalRAMaskHandler(dev,
+										false,
+										pEntry->aid+1,
+										pEntry->htinfo.MimoPs,
+										pEntry->wireless_mode,	
+										pEntry->htinfo.bCurTxBW40MHz,
+										0);
+			}
+			else	
+				rtl8192se_update_ratr_table(dev,pEntry->htinfo.McsRateSet,pEntry);
+			printk("%s: STA:"MAC_FMT", aid:%d, wireless_mode=0x%x ratr_index=%d\n",__FUNCTION__,MAC_ARG(addr), pEntry->aid, pEntry->wireless_mode, pEntry->ratr_index);
+		}
+	}
+	if(!ieee->bUseRAMask)
+		UpdateHalRATRTableIndex(dev);
+
+	if(ieee->Peer_bCurBW40M)
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+	else
+		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);  
+}
+
+bool	
+rtl8192se_RxCommandPacketHandle(
+	struct net_device *dev, 
+	struct sk_buff* skb,
+	rx_desc *pdesc)
+{
+	u8*			pRxCmdHeader;
+	u8*			pCmdContent;
+	u16			total_length, offset;
+	u16			RxCmdLen;
+	u8			RxCmdElementID, RxCmdSeq;
+	bool			RxCmdContinue;
+
+#if 0
+	if ((pRfd->queue_id != CMPK_RX_QUEUE_ID) || (pRfd == NULL))
+	{
+		return 0;
+	}
+#endif
+	
+	
+#if 0
+	if(pdesc->MACID == 0x1e)
+	{	
+		return 0;
+	}
+#endif	
+
+	total_length = pdesc->Length;
+	pRxCmdHeader = skb->data;
+	offset = 0;
+
+	do
+	{
+		RxCmdLen = (u16)GET_C2H_CMD_CMD_LEN(pRxCmdHeader + offset);
+		RxCmdElementID = (u8)GET_C2H_CMD_ELEMENT_ID(pRxCmdHeader + offset);
+		RxCmdSeq = (u8)GET_C2H_CMD_CMD_SEQ(pRxCmdHeader + offset);
+		RxCmdContinue = (bool)GET_C2H_CMD_CONTINUE(pRxCmdHeader + offset);
+		pCmdContent = (u8*)GET_C2H_CMD_CONTENT(pRxCmdHeader + offset);
+
+		if((offset + C2H_RX_CMD_HDR_LEN + RxCmdLen) > total_length)
+		{
+			printk("Wrong C2H Cmd length!\n");
+			break;
+		}
+
+		RT_TRACE(COMP_CMD, "RxCmdLen = 0x%x, RxCmdElementID = 0x%x, RxCmdSeq = 0x%x, RxCmdContinue = 0x%x\n", 
+			RxCmdLen, RxCmdElementID, RxCmdSeq, RxCmdContinue);
+		RT_TRACE(COMP_CMD, "Rx CMD Packet Hex Data :%x\n", total_length);
+		RT_TRACE(COMP_CMD, "Rx CMD Content Hex Data :%x:%x\n", *pCmdContent, RxCmdLen);
+
+		switch(RxCmdElementID)
+		{
+		case HAL_FW_C2H_CMD_C2HFEEDBACK:
+			{
+				switch(GET_C2H_CMD_FEEDBACK_ELEMENT_ID(pCmdContent))
+				{
+				case HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT:
+					{
+						RT_TRACE(COMP_CMD, "HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT FW_DBG CMD Hex:%x\n", total_length);
+					}
+					break;
+
+				case HAL_FW_C2H_CMD_C2HFEEDBACK_DTM_TX_STATISTICS_RPT:
+					break;
+
+				default:
+					break;
+				}
+			}
+			break;
+
+		case HAL_FW_C2H_CMD_C2HDBG:
+			RT_TRACE(COMP_CMD,  "rtl8192se_RxCommandPacketHandle(): %x:%x<*** FW_DBG CMD String ***>\n", *pCmdContent, RxCmdLen);
+			break;
+
+		case HAL_FW_C2H_CMD_BT_State:
+			{
+			}
+			break;
+		case HAL_FW_C2H_CMD_BT_Service:
+			{
+			}
+			break;		
+		case HAL_FW_C2H_CMD_SurveyDone:
+			{
+				rtl8192se_rx_surveydone_cmd(dev);
+			}
+			break;
+		default:
+			RT_TRACE(COMP_CMD, "rtl8192se_RxCommandPacketHandle(): Receive unhandled C2H CMD (%d)\n", RxCmdElementID);
+			break;
+		}
+
+		offset += (C2H_RX_CMD_HDR_LEN + N_BYTE_ALIGMENT(RxCmdLen, 8));
+
+		if(!RxCmdContinue || ((offset + C2H_RX_CMD_HDR_LEN) > total_length))
+		{
+			break;
+		}
+	}while(true);
+	RT_TRACE(COMP_RECV, "RxCommandPacketHandle8190Pci(): It is a command packet\n");
+	
+	return 1;
+}
+
+void
+rtl8192se_InitializeVariables(struct net_device  *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if (priv->rf_type == RF_1T1R) 
+		strcpy(priv->nick, "rtl8191SEVA1");
+	else if (priv->rf_type == RF_1T2R)
+		strcpy(priv->nick, "rtl8191SEVA2");
+	else
+		strcpy(priv->nick, "rtl8192SE");
+
+#ifdef _ENABLE_SW_BEACON
+	priv->rtllib->softmac_features  = IEEE_SOFTMAC_SCAN | 
+		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | 
+		IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE  |
+		IEEE_SOFTMAC_BEACONS;
+#else
+#ifdef _RTL8192_EXT_PATCH_	
+	priv->rtllib->softmac_features  = IEEE_SOFTMAC_SCAN | 
+		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | 
+		IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE /* |
+		IEEE_SOFTMAC_BEACONS*/;
+#else
+	priv->rtllib->softmac_features  = IEEE_SOFTMAC_SCAN | 
+		IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | 
+		IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE /* |
+		IEEE_SOFTMAC_BEACONS*/;
+#endif
+#endif
+
+	priv->rtllib->tx_headroom = 0;
+
+	priv->ShortRetryLimit = 0x30;
+	priv->LongRetryLimit = 0x30;
+	
+	priv->EarlyRxThreshold = 7;
+	priv->pwrGroupCnt = 0;
+
+	priv->bIgnoreSilentReset = false;  
+	priv->enable_gpio0 = 0;
+
+	priv->TransmitConfig = 0;
+
+	priv->ReceiveConfig = 
+	RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/
+	RCR_AMF	| RCR_ADF | RCR_APP_MIC | RCR_APP_ICV |
+       RCR_AICV	| RCR_ACRC32	|				
+	RCR_AB 		| RCR_AM		|				
+     	RCR_APM 	|  								
+     	/*RCR_AAP		|*/	 						
+     	RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF |	
+	(priv->EarlyRxThreshold<<RCR_FIFO_OFFSET)	;
+
+#if 0
+	priv->irq_mask[0] = 
+	(IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |		\
+	IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | 					\
+	IMR_BDOK | IMR_RXCMDOK | /*IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW/*	|			\
+	IMR_BcnInt| IMR_TXFOVW | IMR_TBDOK | IMR_TBDER*/);
+#else
+	priv->irq_mask[0] = 
+	(IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |		\
+	IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | 					\
+	IMR_BDOK | IMR_RXCMDOK | /*IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW	|		\
+	IMR_BcnInt/*| IMR_TXFOVW*/ /*| IMR_TBDOK | IMR_TBDER*/);
+#endif
+	priv->irq_mask[1] = 0;/* IMR_TBDOK | IMR_TBDER*/
+
+
+	priv->MidHighPwrTHR_L1 = 0x3B;
+	priv->MidHighPwrTHR_L2 = 0x40;
+	priv->PwrDomainProtect = false;
+
+	if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){
+		if (!priv->scan_cmd) {
+			priv->scan_cmd = kmalloc(sizeof(H2C_SITESURVEY_PARA) +
+				RTL_MAX_SCAN_SIZE, GFP_KERNEL);
+		}
+	}
+}
+
+void rtl8192se_EnableInterrupt(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+	priv->irq_enabled = 1;
+	
+#ifdef RTL8192CE
+	write_nic_dword(dev, REG_HIMR, priv->irq_mask[0]&0xFFFFFFFF);	
+#else
+	write_nic_dword(dev,INTA_MASK, priv->irq_mask[0]);
+#endif
+
+#ifdef RTL8192SE	
+	write_nic_dword(dev,INTA_MASK+4, priv->irq_mask[1]&0x3F);
+#endif	
+
+}
+
+void rtl8192se_DisableInterrupt(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);	
+
+#ifdef RTL8192CE
+	write_nic_dword(dev, REG_HIMR, IMR8190_DISABLED);	
+#else
+	write_nic_dword(dev,INTA_MASK,0);
+#endif
+
+#ifdef RTL8192SE	
+	write_nic_dword(dev,INTA_MASK + 4,0);
+#endif	
+	priv->irq_enabled = 0;
+}
+
+void rtl8192se_ClearInterrupt(struct net_device *dev)
+{
+	u32 tmp = 0;
+#ifdef RTL8192CE
+	tmp = read_nic_dword(dev, REG_HISR);	
+	write_nic_dword(dev, REG_HISR, tmp);
+#else
+	tmp = read_nic_dword(dev, ISR);	
+	write_nic_dword(dev, ISR, tmp);
+#endif
+
+#ifdef RTL8192SE	
+	tmp = read_nic_dword(dev, ISR+4);	
+	write_nic_dword(dev, ISR+4, tmp);
+#endif
+}
+
+void rtl8192se_enable_rx(struct net_device *dev)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+    write_nic_dword(dev, RDQDA,priv->rx_ring_dma[RX_MPDU_QUEUE]);
+#ifdef CONFIG_RX_CMD
+    write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]);
+#endif
+}
+
+u32 TX_DESC_BASE[] = {TBKDA, TBEDA, TVIDA, TVODA, TBDA, TCDA, TMDA, THPDA, HDA};
+void rtl8192se_enable_tx(struct net_device *dev)
+{
+    struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+    u32 i;
+	
+    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+        write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
+}
+
+
+void rtl8192se_beacon_disable(struct net_device *dev) 
+{
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	u32 reg;
+
+#ifdef RTL8192CE
+	reg = read_nic_dword(priv->rtllib->dev,REG_HIMR);
+
+	reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
+	write_nic_dword(priv->rtllib->dev, REG_HIMR, reg);	
+#else
+	reg = read_nic_dword(priv->rtllib->dev,INTA_MASK);
+
+	reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
+	write_nic_dword(priv->rtllib->dev, INTA_MASK, reg);	
+#endif
+}
+
+void rtl8192se_interrupt_recognized(struct net_device *dev, u32 *p_inta, u32 *p_intb)
+{
+#ifdef RTL8192SE
+	struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+	*p_inta = read_nic_dword(dev, ISR) & priv->irq_mask[0];
+#else
+	*p_inta = read_nic_dword(dev, ISR) ;
+#endif
+	write_nic_dword(dev,ISR,*p_inta); 
+#ifdef RTL8192SE
+	*p_intb = read_nic_dword(dev, ISR+4);
+	write_nic_dword(dev, ISR+4, *p_intb);
+#endif
+}
+
+bool rtl8192se_HalRxCheckStuck(struct net_device *dev)
+{
+	
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u16 				RegRxCounter = (u16)(priv->InterruptLog.nIMR_ROK&0xffff);
+	bool				bStuck = false;
+	u32 				SlotIndex = 0, TotalRxStuckCount = 0;
+	u8				i;
+	u8				SilentResetRxSoltNum = 4;
+
+
+	SlotIndex = (priv->SilentResetRxSlotIndex++)%SilentResetRxSoltNum;
+
+	if(priv->RxCounter==RegRxCounter)
+	{		
+		priv->SilentResetRxStuckEvent[SlotIndex] = 1;
+
+		for( i = 0; i < SilentResetRxSoltNum ; i++ )
+			TotalRxStuckCount += priv->SilentResetRxStuckEvent[i];
+
+		if(TotalRxStuckCount  == SilentResetRxSoltNum)
+		{
+			bStuck = true;
+			for( i = 0; i < SilentResetRxSoltNum ; i++ )
+				TotalRxStuckCount += priv->SilentResetRxStuckEvent[i];
+		}
+
+
+	} else {
+		priv->SilentResetRxStuckEvent[SlotIndex] = 0;
+	}
+
+	priv->RxCounter = RegRxCounter;
+
+	return bStuck;
+}
+
+bool rtl8192se_HalTxCheckStuck(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool   	bStuck = false;
+#if defined(RTL8192E) || defined(RTL8190P)
+	u16    RegTxCounter = read_nic_word(dev, 0x128);
+#elif defined (RTL8192SE) || defined (RTL8192CE)
+	u16 	RegTxCounter = read_nic_word(dev, 0x366);
+#else
+	u16 	RegTxCounter = priv->TxCounter + 1;
+ 	WARN_ON(1);	
+#endif
+
+	RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", 
+			__FUNCTION__,RegTxCounter,priv->TxCounter);
+
+	if(priv->TxCounter == RegTxCounter)
+		bStuck = true;
+
+	priv->TxCounter = RegTxCounter;
+
+	return bStuck;
+}
+
+bool rtl8192se_GetNmodeSupportBySecCfg(struct net_device *dev)
+{
+#ifdef RTL8192SE
+	return true;
+#else
+	struct r8192_priv *priv = rtllib_priv(dev);
+	struct rtllib_device *ieee = priv->rtllib;
+	if (ieee->rtllib_ap_sec_type && 
+	   (ieee->rtllib_ap_sec_type(priv->rtllib)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
+		return false;
+	} else {
+		return true;
+	}
+#endif
+}
+
+bool rtl8192se_GetHalfNmodeSupportByAPs(struct net_device* dev)
+{
+#ifdef RTL8192SE
+	return false;
+#else	
+	bool			Reval;
+	struct r8192_priv* priv = rtllib_priv(dev);
+	struct rtllib_device* ieee = priv->rtllib;
+	
+	if(ieee->bHalfWirelessN24GMode == true)
+		Reval = true;
+	else
+		Reval =  false;
+
+	return Reval;
+#endif
+}
+
+u8 rtl8192se_QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
+{
+	u8   tmp_Short;
+
+	tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
+#if defined RTL8192SE || defined RTL8192CE
+	if(TxHT==1 && TxRate != DESC92S_RATEMCS15)
+#elif defined RTL8192E || defined RTL8190P
+	if(TxHT==1 && TxRate != DESC90_RATEMCS15)
+#endif
+		tmp_Short = 0;
+
+	return tmp_Short;
+}
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_scan.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_scan.c
@@ -0,0 +1,413 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "../rtl_core.h"
+
+#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
+
+void rtl8192se_hw_scan_simu(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,hw_scan_simu_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+
+	rtllib_update_active_chan_map(priv->rtllib);
+
+	priv->rtllib->current_network.channel =	(priv->rtllib->current_network.channel + 1) % 12;
+	if (priv->rtllib->scan_watch_dog++ > 12)
+	{
+		goto out; /* no good chans */
+	}
+
+	if ((!test_bit(STATUS_SCANNING, &priv->rtllib->status)) || 
+			(test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status))){
+		goto out;
+	}
+
+	if(priv->rtllib->current_network.channel != 0){
+		priv->rtllib->set_chan(dev,priv->rtllib->current_network.channel);
+#ifdef _RTL8192_EXT_PATCH_
+		rtllib_send_probe_requests(priv->rtllib, 1);
+#else
+		rtllib_send_probe_requests(priv->rtllib);
+#endif
+	}
+
+	queue_delayed_work_rsl(priv->priv_wq, &priv->hw_scan_simu_wq, MSECS(RTLLIB_SOFTMAC_SCAN_TIME));
+
+	return;
+out:
+	priv->rtllib->scan_watch_dog =0;
+	rtl8192se_rx_surveydone_cmd(dev);
+
+	if(priv->rtllib->state == RTLLIB_LINKED_SCANNING){
+		priv->rtllib->current_network.channel = priv->rtllib->hwscan_ch_bk;
+		printk("%s():back to linked chan:%d\n", __func__,priv->rtllib->current_network.channel);
+		priv->rtllib->set_chan(dev,priv->rtllib->current_network.channel);
+	}
+}
+
+void rtl8192se_before_hw_scan(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	HT_EXTCHNL_OFFSET chan_offset=0;
+	HT_CHANNEL_WIDTH bandwidth=0;
+	struct rtllib_device *ieee = priv->rtllib;
+
+	if(priv->rtllib->state != RTLLIB_LINKED)
+		return;
+
+
+#ifdef ENABLE_LPS
+	if (ieee->LeisurePSLeave) {
+		ieee->LeisurePSLeave(ieee->dev);
+	}
+	/* notify AP to be in PS mode */
+	rtllib_sta_ps_send_null_frame(ieee, 1);
+	rtllib_sta_ps_send_null_frame(ieee, 1);
+#endif
+
+	rtllib_stop_all_queues(ieee);
+
+	if (ieee->data_hard_stop)
+		ieee->data_hard_stop(ieee->dev);
+	rtllib_stop_send_beacons(ieee);
+	ieee->state = RTLLIB_LINKED_SCANNING;
+	ieee->link_change(ieee->dev);
+	/* wait for ps packet to be kicked out successfully */
+	mdelay(50);
+
+#if(RTL8192S_DISABLE_FW_DM == 0)
+	if (ieee->SetFwCmdHandler) {
+		ieee->SetFwCmdHandler(ieee->dev, FW_CMD_PAUSE_DM_BY_SCAN);
+	}
+#endif
+
+	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
+		priv->hwscan_bw_40 = 1;
+		priv->rtllib->chan_offset_bk = chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
+		priv->rtllib->bandwidth_bk = bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
+		printk("before scan force BW to 20M:%d, %d\n", chan_offset, bandwidth);
+		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+	}
+}
+void rtl8192se_after_hw_scan(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	HT_EXTCHNL_OFFSET chan_offset = priv->rtllib->chan_offset_bk;
+	HT_CHANNEL_WIDTH bandwidth = priv->rtllib->bandwidth_bk;
+	struct rtllib_device *ieee = priv->rtllib;
+
+	if(priv->rtllib->state != RTLLIB_LINKED_SCANNING){
+		goto out;
+	}
+
+	if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || 
+			ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) {
+		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
+		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;	
+	}
+
+	if (priv->hwscan_bw_40) {
+		priv->hwscan_bw_40 = 0;
+		printk("after scan back BW to 40M:%d, %d\n", chan_offset, bandwidth);
+#if 1
+		if (chan_offset == HT_EXTCHNL_OFFSET_UPPER){
+			ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk + 2);
+		}else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER){
+			ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk - 2);
+		}else{
+			priv->rtllib->current_network.channel = priv->rtllib->hwscan_ch_bk;
+			ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk);
+		}
+#endif
+		ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
+	} else {
+		ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk);
+	}
+	
+#if(RTL8192S_DISABLE_FW_DM == 0)
+	if (ieee->SetFwCmdHandler) {
+		ieee->SetFwCmdHandler(ieee->dev, FW_CMD_RESUME_DM_BY_SCAN);
+	}
+#endif
+	ieee->state = RTLLIB_LINKED;
+	ieee->link_change(ieee->dev);
+
+#ifdef ENABLE_LPS
+	/* Notify AP that I wake up again */
+	rtllib_sta_ps_send_null_frame(ieee, 0);
+#endif
+
+	if (ieee->data_hard_resume)
+		ieee->data_hard_resume(ieee->dev);
+	
+	if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+		rtllib_start_send_beacons(ieee);
+	
+	rtllib_wake_all_queues(ieee);
+	
+out:
+	return;
+}
+/* Service HAL_FW_C2H_CMD_SurveyDone (0x9) */
+void rtl8192se_rx_surveydone_cmd(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	
+	
+
+	cancel_delayed_work(&priv->check_hw_scan_wq);
+
+	/* If a request to abort was given, or the scan did not succeed
+	 * then we reset the scan state machine and terminate,
+	 * re-queuing another scan if one has been requested */
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) {
+		RT_TRACE(COMP_ERR, "Aborted scan completed.\n");
+		clear_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status);
+	} 
+	
+	rtl8192se_after_hw_scan(dev);
+
+#ifdef CONFIG_FW_PARSEBEACON
+	if(priv->rtllib->state < RTLLIB_LINKED)
+	write_nic_dword(dev, RXFILTERMAP, 0x0100);
+#endif
+
+	mdelay(1);
+
+	clear_bit(STATUS_SCANNING, &priv->rtllib->status);
+
+	{
+		union iwreq_data wrqu;
+		memset(&wrqu, 0, sizeof(wrqu));
+		wireless_send_event(priv->rtllib->dev,SIOCGIWSCAN,&wrqu,NULL);
+	}
+
+	if(priv->rtllib->hwscan_sem_up == 0){
+		up(&priv->wx_sem);
+		priv->rtllib->hwscan_sem_up = 1;
+	}
+
+
+	return;
+}
+
+
+void	rtl8192se_check_hw_scan(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,check_hw_scan_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+	unsigned long flags;
+
+
+	spin_lock_irqsave(&priv->fw_scan_lock,flags);
+	printk("----------->%s()\n", __func__);
+
+	if (test_bit(STATUS_SCANNING, &priv->rtllib->status) ||
+	    test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) {
+		printk("FW Scan long time without stop, stop hw scan\n");
+		rtl8192se_send_scan_abort(dev);
+	}
+	
+
+	if(priv->rtllib->hwscan_sem_up == 0){
+		up(&priv->wx_sem);
+		priv->rtllib->hwscan_sem_up = 1;
+	}
+
+	printk("<-----------%s()\n", __func__);
+	spin_unlock_irqrestore(&priv->fw_scan_lock,flags);
+}
+
+void rtl8192se_start_hw_scan(void *data)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
+	struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,start_hw_scan_wq);
+	struct net_device *dev = priv->rtllib->dev;
+#else
+	struct net_device *dev = (struct net_device *)data;
+	struct r8192_priv *priv = rtllib_priv(dev);
+#endif
+	bool start_flag =true;
+	unsigned long flags;
+
+	down(&priv->wx_sem);
+	priv->rtllib->hwscan_sem_up = 0;
+
+	spin_lock_irqsave(&priv->fw_scan_lock,flags);
+
+
+	cancel_delayed_work(&priv->check_hw_scan_wq);
+
+	/* Make sure the scan wasn't canceled before this queued work
+	 * was given the chance to run... */
+	if (!test_bit(STATUS_SCANNING, &priv->rtllib->status)){
+		RT_TRACE(COMP_ERR,"scan was canceled.");
+		goto done;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) {
+		RT_TRACE(COMP_ERR, "Scan request while abort pending.  Queuing.");
+		goto done;
+	}
+	
+	
+#ifdef CONFIG_FW_PARSEBEACON
+	if(priv->rtllib->state < RTLLIB_LINKED)
+	write_nic_dword(dev, RXFILTERMAP, 0x0000);
+#endif
+
+	rtl8192se_before_hw_scan(dev);
+	rtl8192se_send_scan_cmd(dev,start_flag);
+
+	queue_delayed_work_rsl(priv->priv_wq,&priv->check_hw_scan_wq,MSECS(7000));
+
+	
+	spin_unlock_irqrestore(&priv->fw_scan_lock,flags);
+	
+	return;
+
+ done:
+	up(&priv->wx_sem);
+	priv->rtllib->hwscan_sem_up = 1;
+	/* Cannot perform scan. Make sure we clear scanning
+	* bits from status so next scan request can be performed.
+	* If we don't clear scanning status bit here all next scan
+	* will fail
+	*/
+	clear_bit(STATUS_SCANNING, &priv->rtllib->status);
+	
+	/* inform mac80211 scan aborted */
+	
+	spin_unlock_irqrestore(&priv->fw_scan_lock,flags);
+
+	return;
+}
+
+void rtl8192se_hw_scan_initiate(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->fw_scan_lock,flags);
+
+
+	if (test_bit(STATUS_SCANNING, &priv->rtllib->status)) {
+		printk("Scan already in progress.\n");
+		goto done;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) {
+		printk("Scan request while abort pending\n");
+		goto done;
+	}
+
+	
+	set_bit(STATUS_SCANNING, &priv->rtllib->status);
+
+	queue_delayed_work_rsl(priv->priv_wq,&priv->start_hw_scan_wq,0);
+
+done:
+	spin_unlock_irqrestore(&priv->fw_scan_lock,flags);
+
+	return;
+}
+
+void rtl8192se_send_scan_abort(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	int ret = true;
+	bool start_flag =false;
+
+
+	/* If there isn't a scan actively going on in the hardware
+	 * then we are in between scan bands and not actually
+	 * actively scanning, so don't send the abort command */
+	if (!test_bit(STATUS_SCANNING, &priv->rtllib->status)) {
+		goto done;
+	}
+
+	ret = rtl8192se_send_scan_cmd(dev, start_flag);
+	mdelay(1); 
+
+#ifdef CONFIG_FW_PARSEBEACON
+	if(priv->rtllib->state < RTLLIB_LINKED)
+	write_nic_dword(dev, RXFILTERMAP, 0x0100);
+#endif
+
+	if (ret) {
+		goto done;
+	}
+	
+
+done:	
+	clear_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status);
+	clear_bit(STATUS_SCANNING, &priv->rtllib->status);
+	
+	return;
+}
+
+/**
+ * rtl8192se_cancel_hw_scan - Cancel any currently executing HW scan
+ *
+ * NOTE: priv->mutex is not required before calling this function
+ */
+void rtl8192se_cancel_hw_scan(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	unsigned long flags;
+	
+	spin_lock_irqsave(&priv->fw_scan_lock,flags);
+
+	if (test_bit(STATUS_SCANNING, &priv->rtllib->status)) {
+		if (!test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) {
+			printk("====>%s stop HW scan\n", __func__);
+			cancel_delayed_work(&priv->check_hw_scan_wq);
+
+			set_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status);
+			rtl8192se_send_scan_abort(dev);
+		} else {
+			printk("-------------->%s()Scan abort already in progress.\n", __func__);
+		}
+	}
+
+	if(priv->rtllib->hwscan_sem_up == 0){
+		up(&priv->wx_sem);
+		priv->rtllib->hwscan_sem_up = 1;
+	}
+
+	spin_unlock_irqrestore(&priv->fw_scan_lock,flags);
+	return;
+}
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hw.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hw.h
@@ -0,0 +1,1070 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *			
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192SREG_H
+#define __INC_HAL8192SREG_H
+
+
+#if 0
+typedef enum _RT_RF_TYPE_DEF
+{
+	RF_1T2R = 0,
+	RF_2T4R,
+	RF_2T2R,
+	RF_1T1R,
+	RF_2T2R_GREEN,
+	RF_819X_MAX_TYPE
+}RT_RF_TYPE_DEF;
+#endif
+
+#define		SYS_ISO_CTRL			0x0000	
+#define		SYS_FUNC_EN			0x0002	
+#define		PMC_FSM				0x0004	
+#define		SYS_CLKR			0x0008	
+#define		EPROM_CMD			0x000A	
+#define		EE_VPD				0x000C	
+#define		AFE_MISC			0x0010	
+#define		SPS0_CTRL			0x0011	
+#define		SPS1_CTRL			0x0018	
+#define		RF_CTRL				0x001F	
+#define		LDOA15_CTRL			0x0020	
+#define		LDOV12D_CTRL			0x0021	
+#define		LDOHCI12_CTRL			0x0022	
+#define		LDO_USB_SDIO			0x0023	
+#define		LPLDO_CTRL			0x0024	
+#define		AFE_XTAL_CTRL			0x0026	
+#define		AFE_PLL_CTRL			0x0028	
+#define		EFUSE_CTRL			0x0030	
+#define		EFUSE_TEST			0x0034	
+#define		PWR_DATA			0x0038	
+#define		DBG_PORT			0x003A	
+#define		DPS_TIMER			0x003C	
+#define		RCLK_MON			0x003E	
+
+#define		CMDR				0x0040	
+#define		TXPAUSE				0x0042	
+#define		LBKMD_SEL			0x0043	
+#define		TCR				0x0044	
+#define		RCR				0x0048	
+#define		MSR				0x004C	
+#define		SYSF_CFG			0x004D	
+#define		RX_PKY_LIMIT			0x004E	
+#define		MBIDCTRL			0x004F	
+
+#define		MACIDR				0x0050	
+#define		MACIDR0				0x0050	
+#define		MACIDR4				0x0054	
+#define		BSSIDR				0x0058	
+#define		HWVID				0x005E	
+#define		MAR				0x0060	
+#define		MBIDCAMCONTENT			0x0068	
+#define		MBIDCAMCFG			0x0070	
+#define		BUILDTIME			0x0074	
+#define		BUILDUSER			0x0078	
+
+#define		IDR0				MACIDR0
+#define		IDR4				MACIDR4
+
+#define		TSFR				0x0080	
+#define		SLOT_TIME			0x0089	
+#define		USTIME				0x008A	
+#define		SIFS_CCK			0x008C	
+#define		SIFS_OFDM			0x008E	
+#define		PIFS_TIME			0x0090	
+#define		ACK_TIMEOUT			0x0091	
+#define		EIFSTR				0x0092	
+#define		BCN_INTERVAL			0x0094	
+#define		ATIMWND				0x0096	
+#define		BCN_DRV_EARLY_INT		0x0098	
+#define		BCN_DMATIME			0x009A	
+#define		BCN_ERR_THRESH			0x009C	
+#define		MLT				0x009D	
+#define		RSVD_MAC_TUNE_US		0x009E	
+
+#define 	RQPN				0x00A0
+#define		RQPN1				0x00A0	
+#define		RQPN2				0x00A1	
+#define		RQPN3				0x00A2	
+#define		RQPN4				0x00A3	
+#define		RQPN5				0x00A4	
+#define		RQPN6				0x00A5	
+#define		RQPN7				0x00A6	
+#define		RQPN8				0x00A7	
+#define		RQPN9				0x00A8	
+#define		RQPN10				0x00A9	
+#define		LD_RQPN				0x00AB  
+#define		RXFF_BNDY			0x00AC  
+#define		RXRPT_BNDY			0x00B0  
+#define		TXPKTBUF_PGBNDY			0x00B4  
+#define		PBP				0x00B5  
+#define		RXDRVINFO_SZ			0x00B6  
+#define		TXFF_STATUS			0x00B7  
+#define		RXFF_STATUS			0x00B8  
+#define		TXFF_EMPTY_TH			0x00B9  
+#define		SDIO_RX_BLKSZ			0x00BC  
+#define		RXDMA				0x00BD  
+#define		RXPKT_NUM			0x00BE  
+#define		C2HCMD_UDT_SIZE			0x00C0  
+#define		C2HCMD_UDT_ADDR			0x00C2  
+#define		FIFOPAGE1			0x00C4  
+#define		FIFOPAGE2			0x00C8  
+#define		FIFOPAGE3			0x00CC  
+#define		FIFOPAGE4			0x00D0  
+#define		FIFOPAGE5			0x00D4  
+#define		FW_RSVD_PG_CRTL			0x00D8  
+#define		RXDMA_AGG_PG_TH			0x00D9  
+#define		TXDESC_MSK 			0x00DC  
+#define		TXRPTFF_RDPTR			0x00E0  
+#define		TXRPTFF_WTPTR			0x00E4  
+#define		C2HFF_RDPTR			0x00E8	
+#define		C2HFF_WTPTR			0x00EC	
+#define		RXFF0_RDPTR			0x00F0	
+#define		RXFF0_WTPTR			0x00F4  
+#define		RXFF1_RDPTR			0x00F8  
+#define		RXFF1_WTPTR			0x00FC  
+#define		RXRPT0_RDPTR			0x0100  
+#define		RXRPT0_WTPTR			0x0104  
+#define		RXRPT1_RDPTR			0x0108  
+#define		RXRPT1_WTPTR			0x010C  
+#define		RX0_UDT_SIZE			0x0110  
+#define		RX1PKTNUM			0x0114  
+#define		RXFILTERMAP			0x0116  
+#define		RXFILTERMAP_GP1			0x0118  
+#define		RXFILTERMAP_GP2			0x011A  
+#define		RXFILTERMAP_GP3			0x011C  
+#define		BCNQ_CTRL			0x0120  
+#define		MGTQ_CTRL			0x0124  
+#define		HIQ_CTRL			0x0128  
+#define		VOTID7_CTRL			0x012c  
+#define		VOTID6_CTRL			0x0130  
+#define		VITID5_CTRL			0x0134  
+#define		VITID4_CTRL			0x0138  
+#define		BETID3_CTRL			0x013c  
+#define		BETID0_CTRL			0x0140  
+#define		BKTID2_CTRL			0x0144  
+#define		BKTID1_CTRL			0x0148  
+#define		CMDQ_CTRL			0x014c  
+#define		TXPKT_NUM_CTRL			0x0150  
+#define		TXQ_PGADD			0x0152  
+#define		TXFF_PG_NUM			0x0154  
+#define		TRXDMA_STATUS			0x0156  
+
+#define		INIMCS_SEL			0x0160	
+#define		TX_RATE_REG			INIMCS_SEL 
+#define		INIRTSMCS_SEL			0x0180	
+#define		RRSR				0x0181	
+#define		ARFR0				0x0184	
+#define		ARFR1				0x0188	
+#define		ARFR2				0x018C  
+#define		ARFR3				0x0190  
+#define		ARFR4				0x0194  
+#define		ARFR5				0x0198  
+#define		ARFR6				0x019C  
+#define		ARFR7				0x01A0  
+#define		AGGLEN_LMT_H			0x01A7	
+#define		AGGLEN_LMT_L			0x01A8	
+#define		DARFRC				0x01B0	
+#define		RARFRC				0x01B8	
+#define		MCS_TXAGC			0x01C0
+#define		CCK_TXAGC			0x01C8
+
+#define		EDCAPARA_VO 			0x01D0	
+#define		EDCAPARA_VI			0x01D4	
+#define		EDCAPARA_BE			0x01D8	
+#define		EDCAPARA_BK			0x01DC	
+#define		BCNTCFG				0x01E0	
+#define		CWRR				0x01E2	
+#define		ACMAVG				0x01E4	
+#define		AcmHwCtrl			0x01E7	
+#define		VO_ADMTM			0x01E8	
+#define		VI_ADMTM			0x01EC
+#define		BE_ADMTM			0x01F0
+#define		RETRY_LIMIT			0x01F4	
+#define		SG_RATE				0x01F6	
+
+#define		NAV_CTRL			0x0200
+#define		BW_OPMODE			0x0203
+#define		BACAMCMD			0x0204
+#define		BACAMCONTENT			0x0208	
+
+#define		LBDLY				0x0210	
+#define		FWDLY				0x0211	
+#define		HWPC_RX_CTRL			0x0218	
+#define		MQIR				0x0220	
+#define		MAIR				0x0222	
+#define		MSIR				0x0224	
+#define		CLM_RESULT			0x0227	
+#define		NHM_RPI_CNT			0x0228	
+#define		RXERR_RPT			0x0230	
+#define		NAV_PROT_LEN			0x0234	
+#define		CFEND_TH			0x0236	
+#define		AMPDU_MIN_SPACE			0x0237	
+#define		TXOP_STALL_CTRL			0x0238
+
+#define		RWCAM				0x0240	
+#define		WCAMI				0x0244	
+#define		RCAMO				0x0248	
+#define		CAMDBG				0x024C
+#define		SECR				0x0250	
+
+#define		WOW_CTRL			0x0260	
+#define		PSSTATUS			0x0261	
+#define		PSSWITCH			0x0262	
+#define		MIMOPS_WAIT_PERIOD		0x0263
+#define		LPNAV_CTRL			0x0264
+#define		WFM0				0x0270	
+#define		WFM1				0x0280	
+#define		WFM2				0x0290  
+#define		WFM3				0x02A0  
+#define		WFM4				0x02B0  
+#define		WFM5				0x02C0  
+#define		WFCRC				0x02D0	
+#define		FW_RPT_REG			0x02c4
+
+#define		PSTIME				0x02E0  
+#define		TIMER0				0x02E4  
+#define		TIMER1				0x02E8  
+#define		GPIO_CTRL			0x02EC  
+#define		GPIO_IN				0x02EC	
+#define		GPIO_OUT			0x02ED	
+#define		GPIO_IO_SEL			0x02EE	
+#define		GPIO_MOD			0x02EF	
+#define		GPIO_INTCTRL			0x02F0  
+#define		MAC_PINMUX_CFG			0x02F1  
+#define		LEDCFG				0x02F2  
+#define		PHY_REG				0x02F3  
+#define		PHY_REG_DATA			0x02F4  
+#define		EFUSE_CLK			0x02F8  
+
+#define		INTA_MASK				0x0300	
+#define		ISR				0x0308	
+
+#define		DBG_PORT_SWITCH			0x003A
+#define		BIST				0x0310	
+#define		DBS				0x0314	
+#define		CPUINST				0x0318	
+#define		CPUCAUSE			0x031C	
+#define		LBUS_ERR_ADDR			0x0320	
+#define		LBUS_ERR_CMD			0x0324	
+#define		LBUS_ERR_DATA_L			0x0328	
+#define		LBUS_ERR_DATA_H			0x032C	
+#define		LX_EXCEPTION_ADDR		0x0330	
+#define		WDG_CTRL			0x0334	
+#define		INTMTU				0x0338	
+#define		INTM				0x033A	
+#define		FDLOCKTURN0			0x033C	
+#define		FDLOCKTURN1			0x033D	
+#define		TRXPKTBUF_DBG_DATA		0x0340	
+#define		TRXPKTBUF_DBG_CTRL		0x0348	
+#define		DPLL				0x034A	
+#define		CBUS_ERR_ADDR			0x0350	
+#define		CBUS_ERR_CMD			0x0354	
+#define		CBUS_ERR_DATA_L			0x0358	
+#define		CBUS_ERR_DATA_H 		0x035C	
+#define		USB_SIE_INTF_ADDR		0x0360	
+#define		USB_SIE_INTF_WD			0x0361	
+#define		USB_SIE_INTF_RD			0x0362	
+#define		USB_SIE_INTF_CTRL		0x0363	
+#define 		LBUS_MON_ADDR 		0x0364	
+#define 		LBUS_ADDR_MASK 		0x0368	
+
+
+#define		TPPoll				0x0500	
+#define		PM_CTRL				0x0502	
+#define		PCIF				0x0503	
+
+#define		THPDA				0x0514	
+#define		TMDA				0x0518	
+#define		TCDA				0x051C	
+#define		HDA				0x0520	
+#define		TVODA				0x0524	
+#define		TVIDA				0x0528	
+#define		TBEDA				0x052C	
+#define		TBKDA				0x0530	
+#define		TBDA				0x0534	
+#define		RCDA				0x0538	
+#define		RDQDA				0x053C	
+#define		DBI_WDATA			0x0540	
+#define		DBI_RDATA			0x0544	
+#define		DBI_CTRL			0x0548	
+#define		MDIO_DATA			0x0550	
+#define		MDIO_CTRL			0x0554	
+#define		PCI_RPWM			0x0561	
+#define		PCI_CPWM				0x0563	
+
+
+#define		PHY_CCA			0x803	
+
+
+#define	USB_RX_AGG_TIMEOUT			0xFE5B	
+
+#define	FW_OFFLOAD_EN				BIT7
+
+#define	MAX_MSS_DENSITY_2T 			0x13
+#define	MAX_MSS_DENSITY_1T 			0x0A
+
+#define	RXDMA_AGG_EN				BIT7
+
+#define	RXDMA_AGG_TIMEOUT_DISABLE		0x00
+#define	RXDMA_AGG_TIMEOUT_17MS  		0x01
+#define	RXDMA_AGG_TIMEOUT_17_2_MS  		0x02
+#define	RXDMA_AGG_TIMEOUT_17_4_MS  		0x04
+#define	RXDMA_AGG_TIMEOUT_17_10_MS  		0x0A
+
+#define	InvalidBBRFValue		0x12345678
+
+#define	USB_RPWM			0xFE58
+
+#ifdef RTL8192SE 
+#define	RPWM		PCI_RPWM
+#endif
+#ifdef RTL8192SU 
+#define	RPWM		USB_RPWM
+#endif
+
+#if 1	
+#define		AFR				0x010	
+#define		BCN_TCFG			0x062	
+#define		RATR0				0x320	
+#endif
+#define		UnusedRegister			0x0320		
+#define		PSR				UnusedRegister	
+#define		DCAM				UnusedRegister	
+#define		BBAddr				UnusedRegister	
+#define		PhyDataR			UnusedRegister	
+#define		UFWP				UnusedRegister
+
+
+
+#define		ISO_MD2PP			BIT0	
+#define		ISO_PA2PCIE			BIT3	
+#define		ISO_PLL2MD			BIT4	
+#define		ISO_PWC_DV2RP		BIT11	
+#define		ISO_PWC_RV2RP		BIT12	
+
+#define		FEN_MREGEN			BIT15	
+#define		FEN_DCORE			BIT11	
+#define		FEN_CPUEN			BIT10	
+
+#define		PAD_HWPD_IDN		BIT22	
+
+#define		SYS_CLKSEL_80M		BIT0	
+#define		SYS_PS_CLKSEL		BIT1	 
+#define		SYS_CPU_CLKSEL		BIT2	
+#define		SYS_MAC_CLK_EN		BIT11	
+#define		SYS_SWHW_SEL		BIT14	
+#define		SYS_FWHW_SEL		BIT15	
+
+
+#define		CmdEEPROM_En						BIT5	 
+#define		CmdEERPOMSEL						BIT4 
+#define		Cmd9346CR_9356SEL					BIT4
+#define		AutoLoadEEPROM					(CmdEEPROM_En|CmdEERPOMSEL)
+#define		AutoLoadEFUSE						CmdEEPROM_En
+#define EPROM_CMD_OPERATING_MODE_SHIFT 6
+#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
+#define EPROM_CMD_CONFIG 0x3
+#define EPROM_CMD_NORMAL 0 
+#define EPROM_CMD_LOAD 1
+#define EPROM_CMD_PROGRAM 2
+#define EPROM_CS_SHIFT 3
+#define EPROM_CK_SHIFT 2
+#define EPROM_W_SHIFT 1
+#define EPROM_R_SHIFT 0
+
+#define		AFE_MBEN			BIT1	
+#define		AFE_BGEN			BIT0	
+
+#define		SPS1_SWEN			BIT1	
+#define		SPS1_LDEN			BIT0	
+
+#define		RF_EN				BIT0 
+#define		RF_RSTB			BIT1 
+#define		RF_SDMRSTB			BIT2 
+
+#define		LDA15_EN			BIT0	
+
+#define		LDV12_EN			BIT0	
+#define		LDV12_SDBY			BIT1	
+
+#define		XTAL_GATE_AFE		BIT10	
+
+#define		APLL_EN				BIT0	
+
+#define		AFR_CardBEn			BIT0
+#define		AFR_CLKRUN_SEL		BIT1
+#define		AFR_FuncRegEn		BIT2
+
+#define		APSDOFF_STATUS		BIT15	
+#define		APSDOFF				BIT14   
+#define		BBRSTn				BIT13   
+#define		BB_GLB_RSTn			BIT12   
+#define		SCHEDULE_EN			BIT10   
+#define		MACRXEN				BIT9    
+#define		MACTXEN				BIT8    
+#define		DDMA_EN				BIT7    
+#define		FW2HW_EN			BIT6    
+#define		RXDMA_EN			BIT5    
+#define		TXDMA_EN			BIT4    
+#define		HCI_RXDMA_EN		BIT3    
+#define		HCI_TXDMA_EN		BIT2    
+
+#define		StopHCCA			BIT6
+#define		StopHigh			BIT5
+#define		StopMgt				BIT4
+#define		StopVO				BIT3
+#define		StopVI				BIT2
+#define		StopBE				BIT1
+#define		StopBK				BIT0
+
+#define		LBK_NORMAL		0x00
+#define		LBK_MAC_LB		(BIT0|BIT1|BIT3)
+#define		LBK_MAC_DLB		(BIT0|BIT1)
+#define		LBK_DMA_LB		(BIT0|BIT1|BIT2)	
+
+#define		TCP_OFDL_EN				BIT25	
+#define		HWPC_TX_EN				BIT24   
+#define		TXDMAPRE2FULL			BIT23   
+#define		DISCW					BIT20   
+#define		TCRICV					BIT19   
+#define		CfendForm				BIT17   
+#define		TCRCRC					BIT16   
+#define		FAKE_IMEM_EN			BIT15   
+#define		TSFRST					BIT9    
+#define		TSFEN					BIT8    
+#define		FWALLRDY				(BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7)
+#define		FWRDY					BIT7
+#define		BASECHG					BIT6
+#define		IMEM					BIT5
+#define		DMEM_CODE_DONE			BIT4
+#define		EXT_IMEM_CHK_RPT		BIT3
+#define		EXT_IMEM_CODE_DONE		BIT2
+#define		IMEM_CHK_RPT			BIT1
+#define		IMEM_CODE_DONE			BIT0
+#define		IMEM_CODE_DONE		BIT0	
+#define		IMEM_CHK_RPT		BIT1
+#define		EMEM_CODE_DONE		BIT2
+#define		EMEM_CHK_RPT		BIT3
+#define		DMEM_CODE_DONE		BIT4
+#define		IMEM_RDY			BIT5
+#define		BASECHG				BIT6
+#define		FWRDY				BIT7
+#define		LOAD_FW_READY	(IMEM_CODE_DONE|IMEM_CHK_RPT|EMEM_CODE_DONE|\
+								EMEM_CHK_RPT|DMEM_CODE_DONE|IMEM_RDY|BASECHG|\
+								FWRDY)
+#define		TCR_TSFEN			BIT8		
+#define		TCR_TSFRST			BIT9		
+#define		TCR_FAKE_IMEM_EN	BIT15
+#define		TCR_CRC				BIT16
+#define		TCR_ICV				BIT19	
+#define		TCR_DISCW			BIT20	
+#define		TCR_HWPC_TX_EN		BIT24
+#define		TCR_TCP_OFDL_EN		BIT25
+#define		TXDMA_INIT_VALUE	(IMEM_CHK_RPT|EXT_IMEM_CHK_RPT)
+
+#define		RCR_APPFCS			BIT31		
+#define		RCR_DIS_ENC_2BYTE	BIT30       
+#define		RCR_DIS_AES_2BYTE	BIT29       
+#define		RCR_HTC_LOC_CTRL	BIT28       
+#define		RCR_ENMBID			BIT27		
+#define		RCR_RX_TCPOFDL_EN	BIT26		
+#define		RCR_APP_PHYST_RXFF	BIT25       
+#define		RCR_APP_PHYST_STAFF	BIT24       
+#define		RCR_CBSSID			BIT23		
+#define		RCR_APWRMGT			BIT22		
+#define		RCR_ADD3			BIT21		
+#define		RCR_AMF				BIT20		
+#define		RCR_ACF				BIT19		
+#define		RCR_ADF				BIT18		
+#define		RCR_APP_MIC			BIT17		
+#define		RCR_APP_ICV			BIT16       
+#define		RCR_RXFTH			BIT13		
+#define		RCR_AICV			BIT12		
+#define		RCR_RXDESC_LK_EN	BIT11		
+#define		RCR_APP_BA_SSN		BIT6		
+#define		RCR_ACRC32			BIT5		
+#define		RCR_RXSHFT_EN		BIT4		
+#define		RCR_AB				BIT3		
+#define		RCR_AM				BIT2		
+#define		RCR_APM				BIT1		
+#define		RCR_AAP				BIT0		
+#define		RCR_MXDMA_OFFSET	8
+#define		RCR_FIFO_OFFSET		13
+
+/*
+Network Type
+00: No link
+01: Link in ad hoc network
+10: Link in infrastructure network
+11: AP mode
+Default: 00b.
+*/
+#define MSR_LINK_MASK      ((1<<0)|(1<<1))
+#define MSR_LINK_MANAGED   2
+#define MSR_LINK_NONE      0
+#define MSR_LINK_SHIFT     0
+#define MSR_LINK_ADHOC     1
+#define MSR_LINK_MASTER    3
+#if 1
+#define		MSR_NOLINK				0x00
+#define		MSR_ADHOC				0x01
+#define		MSR_INFRA				0x02
+#define		MSR_AP					0x03
+#endif
+#define		ENUART					BIT7
+#define		ENJTAG					BIT3
+#define		BTMODE					(BIT2|BIT1)
+#define		ENBT					BIT0
+
+#define		ENMBID					BIT7
+#define		BCNUM					(BIT6|BIT5|BIT4)
+
+
+#define		USTIME_EDCA				0xFF00
+#define		USTIME_TSF				0x00FF
+
+#define		SIFS_TRX				0xFF00
+#define		SIFS_CTX				0x00FF
+
+#define		ENSWBCN					BIT15
+#define		DRVERLY_TU				0x0FF0
+#define		DRVERLY_US				0x000F
+#define		BCN_TCFG_CW_SHIFT		8
+#define		BCN_TCFG_IFS			0	
+
+
+#define		RRSR_RSC_OFFSET			21
+#define		RRSR_SHORT_OFFSET		23
+#define		RRSR_RSC_BW_40M		0x600000
+#define		RRSR_RSC_UPSUBCHNL		0x400000
+#define		RRSR_RSC_LOWSUBCHNL		0x200000
+#define		RRSR_SHORT				0x800000
+#define		RRSR_1M					BIT0
+#define		RRSR_2M					BIT1 
+#define		RRSR_5_5M				BIT2 
+#define		RRSR_11M				BIT3 
+#define		RRSR_6M					BIT4 
+#define		RRSR_9M					BIT5 
+#define		RRSR_12M				BIT6 
+#define		RRSR_18M				BIT7 
+#define		RRSR_24M				BIT8 
+#define		RRSR_36M				BIT9 
+#define		RRSR_48M				BIT10 
+#define		RRSR_54M				BIT11
+#define		RRSR_MCS0				BIT12
+#define		RRSR_MCS1				BIT13
+#define		RRSR_MCS2				BIT14
+#define		RRSR_MCS3				BIT15
+#define		RRSR_MCS4				BIT16
+#define		RRSR_MCS5				BIT17
+#define		RRSR_MCS6				BIT18
+#define		RRSR_MCS7				BIT19
+#define		BRSR_AckShortPmb		BIT23	
+
+#define		RATR_1M					0x00000001
+#define		RATR_2M					0x00000002
+#define		RATR_55M				0x00000004
+#define		RATR_11M				0x00000008
+#define		RATR_6M					0x00000010
+#define		RATR_9M					0x00000020
+#define		RATR_12M				0x00000040
+#define		RATR_18M				0x00000080
+#define		RATR_24M				0x00000100
+#define		RATR_36M				0x00000200
+#define		RATR_48M				0x00000400
+#define		RATR_54M				0x00000800
+#define		RATR_MCS0				0x00001000
+#define		RATR_MCS1				0x00002000
+#define		RATR_MCS2				0x00004000
+#define		RATR_MCS3				0x00008000
+#define		RATR_MCS4				0x00010000
+#define		RATR_MCS5				0x00020000
+#define		RATR_MCS6				0x00040000
+#define		RATR_MCS7				0x00080000
+#define		RATR_MCS8				0x00100000
+#define		RATR_MCS9				0x00200000
+#define		RATR_MCS10				0x00400000
+#define		RATR_MCS11				0x00800000
+#define		RATR_MCS12				0x01000000
+#define		RATR_MCS13				0x02000000
+#define		RATR_MCS14				0x04000000
+#define		RATR_MCS15				0x08000000
+#define	RATE_ALL_CCK				RATR_1M|RATR_2M|RATR_55M|RATR_11M 
+#define	RATE_ALL_OFDM_AG			RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|\
+									RATR_36M|RATR_48M|RATR_54M	
+#define	RATE_ALL_OFDM_1SS			RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 |\
+									RATR_MCS4|RATR_MCS5|RATR_MCS6	|RATR_MCS7	
+#define	RATE_ALL_OFDM_2SS			RATR_MCS8|RATR_MCS9	|RATR_MCS10|RATR_MCS11|\
+									RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15
+									
+#define		AC_PARAM_TXOP_LIMIT_OFFSET		16
+#define		AC_PARAM_ECW_MAX_OFFSET			12
+#define		AC_PARAM_ECW_MIN_OFFSET			8
+#define		AC_PARAM_AIFS_OFFSET			0
+
+#define		AcmHw_HwEn				BIT0
+#define		AcmHw_BeqEn				BIT1
+#define		AcmHw_ViqEn				BIT2
+#define		AcmHw_VoqEn				BIT3
+#define		AcmHw_BeqStatus			BIT4
+#define		AcmHw_ViqStatus			BIT5
+#define		AcmHw_VoqStatus			BIT6
+
+#define		RETRY_LIMIT_SHORT_SHIFT	8
+#define		RETRY_LIMIT_LONG_SHIFT	0
+
+#define		NAV_UPPER_EN			BIT16
+#define		NAV_UPPER				0xFF00
+#define		NAV_RTSRST				0xFF
+#define		BW_OPMODE_20MHZ			BIT2
+#define		BW_OPMODE_5G			BIT1
+#define		BW_OPMODE_11J			BIT0
+
+#define		RXERR_RPT_RST			BIT27 
+#define		RXERR_OFDM_PPDU			0
+#define		RXERR_OFDM_FALSE_ALARM	1
+#define		RXERR_OFDM_MPDU_OK		2
+#define		RXERR_OFDM_MPDU_FAIL	3
+#define		RXERR_CCK_PPDU			4
+#define		RXERR_CCK_FALSE_ALARM	5
+#define		RXERR_CCK_MPDU_OK		6
+#define		RXERR_CCK_MPDU_FAIL		7
+#define		RXERR_HT_PPDU			8
+#define		RXERR_HT_FALSE_ALARM	9
+#define		RXERR_HT_MPDU_TOTAL		10
+#define		RXERR_HT_MPDU_OK		11
+#define		RXERR_HT_MPDU_FAIL		12
+#define		RXERR_RX_FULL_DROP		15
+
+
+#define		CAM_CM_SecCAMPolling	BIT31		
+#define		CAM_CM_SecCAMClr		BIT30		
+#define		CAM_CM_SecCAMWE			BIT16		
+#define		CAM_ADDR				0xFF		
+
+#define		Dbg_CAM_TXSecCAMInfo	BIT31		
+#define		Dbg_CAM_SecKeyFound		BIT30		
+
+
+#define		SCR_TxUseDK				BIT0			
+#define		SCR_RxUseDK				BIT1			
+#define		SCR_TxEncEnable			BIT2			
+#define		SCR_RxDecEnable			BIT3			
+#define		SCR_SKByA2				BIT4			
+#define		SCR_NoSKMC				BIT5			
+#define		CAM_VALID				BIT15
+#define		CAM_NOTVALID			0x0000
+#define		CAM_USEDK				BIT5
+       	       		
+#define		CAM_NONE				0x0
+#define		CAM_WEP40				0x01
+#define		CAM_TKIP				0x02
+#define		CAM_AES					0x04
+#define		CAM_WEP104				0x05
+        		
+#define		TOTAL_CAM_ENTRY			32
+#define		HALF_CAM_ENTRY				16
+       		
+#define		CAM_CONFIG_USEDK		true
+#define		CAM_CONFIG_NO_USEDK		false
+       		
+#define		CAM_WRITE				BIT16
+#define		CAM_READ				0x00000000
+#define		CAM_POLLINIG			BIT31
+       		
+#define		SCR_UseDK				0x01
+#define		SCR_TxSecEnable		0x02
+#define		SCR_RxSecEnable		0x04
+
+#define		WOW_PMEN				BIT0 
+#define		WOW_WOMEN			BIT1 
+#define		WOW_MAGIC				BIT2 
+#define		WOW_UWF				BIT3 
+
+#define		GPIOMUX_EN			BIT3 
+#define		GPIOSEL_GPIO		0	
+#define		GPIOSEL_PHYDBG		1	
+#define		GPIOSEL_BT			2	
+#define		GPIOSEL_WLANDBG		3	
+#define		GPIOSEL_GPIO_MASK	~(BIT0|BIT1)
+
+#define		HST_RDBUSY				BIT0
+#define		CPU_WTBUSY			BIT1
+
+#define		IMR8190_DISABLED	0x0
+#define		IMR_CPUERR			BIT5		
+#define		IMR_ATIMEND			BIT4		
+#define		IMR_TBDOK			BIT3		
+#define		IMR_TBDER			BIT2		
+#define		IMR_BCNDMAINT8		BIT1		
+#define		IMR_BCNDMAINT7		BIT0		
+#define		IMR_BCNDMAINT6		BIT31		
+#define		IMR_BCNDMAINT5		BIT30		
+#define		IMR_BCNDMAINT4		BIT29		
+#define		IMR_BCNDMAINT3		BIT28		
+#define		IMR_BCNDMAINT2		BIT27		
+#define		IMR_BCNDMAINT1		BIT26		
+#define		IMR_BCNDOK8			BIT25		
+#define		IMR_BCNDOK7			BIT24		
+#define		IMR_BCNDOK6			BIT23		
+#define		IMR_BCNDOK5			BIT22		
+#define		IMR_BCNDOK4			BIT21		
+#define		IMR_BCNDOK3			BIT20		
+#define		IMR_BCNDOK2			BIT19		
+#define		IMR_BCNDOK1			BIT18		
+#define		IMR_TIMEOUT2		BIT17		
+#define		IMR_TIMEOUT1		BIT16		
+#define		IMR_TXFOVW			BIT15		
+#define		IMR_PSTIMEOUT		BIT14		
+#define		IMR_BcnInt			BIT13		
+#define		IMR_RXFOVW			BIT12		
+#define		IMR_RDU				BIT11		
+#define		IMR_RXCMDOK			BIT10		
+#define		IMR_BDOK			BIT9		
+#define		IMR_HIGHDOK			BIT8		
+#define		IMR_COMDOK			BIT7		
+#define		IMR_MGNTDOK			BIT6		
+#define		IMR_HCCADOK			BIT5		
+#define		IMR_BKDOK			BIT4		
+#define		IMR_BEDOK			BIT3		
+#define		IMR_VIDOK			BIT2		
+#define		IMR_VODOK			BIT1		
+#define		IMR_ROK				BIT0		
+
+
+#define		TPPoll_BKQ			BIT0			
+#define		TPPoll_BEQ			BIT1			
+#define		TPPoll_VIQ			BIT2			
+#define		TPPoll_VOQ			BIT3			
+#define		TPPoll_BQ			BIT4			
+#define		TPPoll_CQ			BIT5			
+#define		TPPoll_MQ			BIT6			
+#define		TPPoll_HQ			BIT7			
+#define		TPPoll_HCCAQ		BIT8			
+#define		TPPoll_StopBK		BIT9			
+#define		TPPoll_StopBE		BIT10			
+#define		TPPoll_StopVI		BIT11			
+#define		TPPoll_StopVO		BIT12			
+#define		TPPoll_StopMgt		BIT13			
+#define		TPPoll_StopHigh		BIT14			
+#define		TPPoll_StopHCCA		BIT15			
+#define		TPPoll_SHIFT		8				
+
+#define		MXDMA2_16bytes		0x000
+#define		MXDMA2_32bytes		0x001
+#define		MXDMA2_64bytes		0x010
+#define		MXDMA2_128bytes		0x011
+#define		MXDMA2_256bytes		0x100
+#define		MXDMA2_512bytes		0x101
+#define		MXDMA2_1024bytes	0x110
+#define		MXDMA2_NoLimit		0x7
+       		
+#define		MULRW_SHIFT			3
+#define		MXDMA2_RX_SHIFT		4
+#define		MXDMA2_TX_SHIFT		0
+
+#define		CCX_CMD_CLM_ENABLE				BIT0	
+#define		CCX_CMD_NHM_ENABLE				BIT1	
+#define		CCX_CMD_FUNCTION_ENABLE			BIT8	
+#define		CCX_CMD_IGNORE_CCA				BIT9	
+#define		CCX_CMD_IGNORE_TXON				BIT10	
+#define		CCX_CLM_RESULT_READY			BIT16	
+#define		CCX_NHM_RESULT_READY			BIT16	
+#define		CCX_CMD_RESET					0x0		
+
+
+#define		HWSET_MAX_SIZE_92S				128
+
+
+
+#ifdef RTL8192SE 
+#define 	RTL8190_EEPROM_ID		0x8129	
+#define 	EEPROM_HPON			0x02 
+#define 	EEPROM_CLK			0x06 
+#define 	EEPROM_TESTR			0x08 
+
+#define 	EEPROM_VID			0x0A 
+#define 	EEPROM_DID			0x0C 
+#define 	EEPROM_SVID			0x0E 
+#define 	EEPROM_SMID			0x10 
+
+#define 	EEPROM_MAC_ADDR			0x12 
+#define 	EEPROM_NODE_ADDRESS_BYTE_0	0x12 
+
+#define 	EEPROM_PwDiff			0x54 
+
+#define 	EEPROM_TxPowerBase			0x50 
+#define		EEPROM_TX_PWR_INDEX_RANGE	28		
+
+#define 	EEPROM_TX_PWR_HT20_DIFF		0x62
+#define 	DEFAULT_HT20_TXPWR_DIFF		2	
+#define 	EEPROM_TX_PWR_OFDM_DIFF		0x65
+
+#define	EEPROM_TxPWRGroup			0x67
+#define 	EEPROM_Regulatory				0x6D
+
+#define 	TX_PWR_SAFETY_CHK		0x6D
+#define 	EEPROM_TxPwIndex_CCK_24G	0x5D 
+#define 	EEPROM_TxPwIndex_OFDM_24G	0x6B 
+#define 	EEPROM_HT2T_CH1_A		0x6c 
+#define 	EEPROM_HT2T_CH7_A		0x6d 
+#define 	EEPROM_HT2T_CH13_A		0x6e 
+#define 	EEPROM_HT2T_CH1_B		0x6f 
+#define 	EEPROM_HT2T_CH7_B		0x70 
+#define 	EEPROM_HT2T_CH13_B		0x71 
+#define 	EEPROM_TSSI_A			0x74 
+#define 	EEPROM_TSSI_B			0x75 
+#define		EEPROM_RFInd_PowerDiff			0x76
+#define		EEPROM_Default_LegacyHTTxPowerDiff	0x3
+#define 	EEPROM_ThermalMeter			0x77 
+#define		EEPROM_BLUETOOTH_COEXIST		0x78 
+#define		EEPROM_BLUETOOTH_TYPE		0x4f 
+
+#define	EEPROM_Optional	0x78 
+#ifdef RTL8192S_WAPI_SUPPORT
+#define		EEPROM_WAPI_SUPPORT			0x78
+#endif
+#define		EEPROM_WoWLAN				0x78 
+
+#define 	EEPROM_CrystalCap			0x79 
+#define 	EEPROM_ChannelPlan			0x7B 
+#define 	EEPROM_Version				0x7C 
+#define		EEPROM_CustomID				0x7A
+#define 	EEPROM_BoardType			0x7E 
+
+#define		EEPROM_Default_TSSI			0x0
+#define 	EEPROM_Default_TxPowerDiff		0x0
+#define 	EEPROM_Default_CrystalCap		0x5
+#define 	EEPROM_Default_BoardType		0x02 
+#define 	EEPROM_Default_TxPower			0x1010
+#define		EEPROM_Default_HT2T_TxPwr		0x10
+
+#define		EEPROM_Default_LegacyHTTxPowerDiff	0x3
+#define		EEPROM_Default_ThermalMeter		0x12
+#define		EEPROM_Default_BlueToothCoexist		0x0
+#define		EEPROM_Default_BlueToothAntNum	0x0
+#define		EEPROM_Default_BlueToothAntIso		0x0
+#define		EEPROM_Default_BlueToothType		0x0
+#define		EEPROM_Default_AntTxPowerDiff		0x0
+#define		EEPROM_Default_TxPwDiff_CrystalCap	0x5
+#define		EEPROM_Default_TxPowerLevel		0x22
+
+#define		EEPROM_CHANNEL_PLAN_FCC			0x0
+#define		EEPROM_CHANNEL_PLAN_IC			0x1
+#define		EEPROM_CHANNEL_PLAN_ETSI		0x2
+#define		EEPROM_CHANNEL_PLAN_SPAIN		0x3
+#define		EEPROM_CHANNEL_PLAN_FRANCE		0x4
+#define		EEPROM_CHANNEL_PLAN_MKK			0x5
+#define		EEPROM_CHANNEL_PLAN_MKK1		0x6
+#define		EEPROM_CHANNEL_PLAN_ISRAEL		0x7
+#define		EEPROM_CHANNEL_PLAN_TELEC		0x8
+#define		EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN	0x9
+#define		EEPROM_CHANNEL_PLAN_WORLD_WIDE_13	0xA
+#define		EEPROM_CHANNEL_PLAN_NCC				0xB
+#define		EEPROM_CHANNEL_PLAN_BY_HW_MASK	0x80
+
+
+#define 	EEPROM_CID_DEFAULT		0x0
+#define 	EEPROM_CID_TOSHIBA		0x4
+#define	EEPROM_CID_CCX				0x10 
+#define	EEPROM_CID_QMI				0x0D
+#define 	EEPROM_CID_WHQL 			0xFE 
+
+#else 
+#define 	RTL8190_EEPROM_ID		0x8129
+#define 	EEPROM_HPON			0x02 
+#define 	EEPROM_VID			0x08 
+#define 	EEPROM_PID			0x0A 
+#define 	EEPROM_USB_OPTIONAL		0x0C 
+#define 	EEPROM_USB_PHY_PARA1		0x0D 
+#define 	EEPROM_NODE_ADDRESS_BYTE_0	0x12 
+#define 	EEPROM_Version			0x50	
+#define 	EEPROM_ChannelPlan		0x51 
+#define		EEPROM_CustomID			0x52
+#define 	EEPROM_SubCustomID		0x53 
+
+#if (EEPROM_OLD_FORMAT_SUPPORT ==1)
+#define 	EEPROM_PwDiff		0x54 
+#define 	EEPROM_ThermalMeter		0x55 
+#define 	EEPROM_Reserved			0x56 
+#define 	EEPROM_CrystalCap		0x57 
+#define 	EEPROM_TxPowerBase		0x58 
+#define 	EEPROM_TxPwIndex_CCK_24G	0x59 
+#define 	EEPROM_TxPwIndex_OFDM_24G	0x67 
+#define 	EEPROM_TSSI_A			0x75 
+#define 	EEPROM_TSSI_B			0x76 
+#define 	EEPROM_TxPwTkMode		0x77 
+#define 	EEPROM_HT2T_CH1_A		0x78 
+#define 	EEPROM_HT2T_CH7_A		0x79 
+#define 	EEPROM_HT2T_CH13_A		0x7a 
+#define 	EEPROM_HT2T_CH1_B		0x7b 
+#define 	EEPROM_HT2T_CH7_B		0x7c 
+#define 	EEPROM_HT2T_CH13_B		0x7d 
+#define 	EEPROM_BoardType		0x7e 
+#else
+#define 	EEPROM_BoardType			0x54 
+#define		EEPROM_TxPwIndex			0x55 
+#define 	EEPROM_PwDiff				0x67 
+#define 	EEPROM_ThermalMeter			0x68 
+#define 	EEPROM_CrystalCap			0x69 
+#define 	EEPROM_TxPowerBase			0x6a 
+#define 	EEPROM_TSSI_A				0x6b 
+#define 	EEPROM_TSSI_B				0x6c 
+#define 	EEPROM_TxPwTkMode			0x6d 
+
+#define 	EEPROM_TX_PWR_HT20_DIFF			0x6e
+#define 	DEFAULT_HT20_TXPWR_DIFF			2
+#define 	EEPROM_TX_PWR_OFDM_DIFF			0x71
+#define 	TX_PWR_SAFETY_CHK			0x79
+#endif
+#define		EEPROM_USB_Default_OPTIONAL_FUNC	0x8
+#define		EEPROM_USB_Default_PHY_PARAM		0x0
+#define		EEPROM_Default_TSSI			0x0
+#define		EEPROM_Default_TxPwrTkMode		0x0
+#define 	EEPROM_Default_TxPowerDiff		0x0
+#define 	EEPROM_Default_TxPowerBase		0x0
+#define 	EEPROM_Default_ThermalMeter		0x7
+#define 	EEPROM_Default_PwDiff			0x4
+#define 	EEPROM_Default_CrystalCap		0x5
+#define 	EEPROM_Default_TxPower			0x1010
+#define 	EEPROM_Default_BoardType		0x02 
+#define		EEPROM_Default_HT2T_TxPwr			0x10
+#define		EEPROM_USB_SN					BIT0
+#define		EEPROM_USB_REMOTE_WAKEUP	BIT1
+#define		EEPROM_USB_DEVICE_PWR		BIT2
+#define		EEPROM_EP_NUMBER				(BIT3|BIT4)
+
+
+#define		EEPROM_CHANNEL_PLAN_FCC				0x0
+#define		EEPROM_CHANNEL_PLAN_IC				0x1
+#define		EEPROM_CHANNEL_PLAN_ETSI			0x2
+#define		EEPROM_CHANNEL_PLAN_SPAIN			0x3
+#define		EEPROM_CHANNEL_PLAN_FRANCE			0x4
+#define		EEPROM_CHANNEL_PLAN_MKK				0x5
+#define		EEPROM_CHANNEL_PLAN_MKK1			0x6
+#define		EEPROM_CHANNEL_PLAN_ISRAEL			0x7
+#define		EEPROM_CHANNEL_PLAN_TELEC			0x8
+#define		EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN	0x9
+#define		EEPROM_CHANNEL_PLAN_WORLD_WIDE_13	0xA
+#define		EEPROM_CHANNEL_PLAN_BY_HW_MASK	0x80
+
+#define 	EEPROM_CID_DEFAULT				0x0
+#define 	EEPROM_CID_ALPHA				0x1
+#define 	EEPROM_CID_TOSHIBA				0x4
+#define 	EEPROM_CID_WHQL 				0xFE 
+#endif
+
+
+#define		FW_DIG_DISABLE				0xfd00cc00
+#define		FW_DIG_ENABLE					0xfd000000
+#define		FW_DIG_HALT					0xfd000001
+#define		FW_DIG_RESUME					0xfd000002
+#define		FW_HIGH_PWR_DISABLE			0xfd000008
+#define		FW_HIGH_PWR_ENABLE			0xfd000009
+#define		FW_ADD_A2_ENTRY				0xfd000016
+#define		FW_TXPWR_TRACK_ENABLE		0xfd000017
+#define		FW_TXPWR_TRACK_DISABLE		0xfd000018
+#define		FW_TXPWR_TRACK_THERMAL		0xfd000019
+#define		FW_TXANT_SWITCH_ENABLE		0xfd000023
+#define		FW_TXANT_SWITCH_DISABLE		0xfd000024
+#define		FW_RA_INIT						0xfd000026 
+#define		FW_CTRL_DM_BY_DRIVER			0Xfd00002a 
+#define		FW_RA_IOT_BG_COMB			0xfd000030 
+#define		FW_RA_IOT_N_COMB				0xfd000031 
+#define		FW_RA_REFRESH					0xfd0000a0
+#define		FW_RA_UPDATE_MASK				0xfd0000a2
+#define		FW_RA_DISABLE					0xfd0000a4 
+#define		FW_RA_ACTIVE					0xfd0000a6
+#define		FW_RA_DISABLE_RSSI_MASK		0xfd0000ac 
+#define		FW_RA_ENABLE_RSSI_MASK		0xfd0000ad 
+#define		FW_RA_RESET					0xfd0000af
+#define		FW_DM_DISABLE					0xfd00aa00
+#define		FW_IQK_ENABLE					0xf0000020
+#define		FW_IQK_SUCCESS				0x0000dddd
+#define		FW_IQK_FAIL					0x0000ffff
+#define		FW_OP_FAILURE					0xffffffff
+#define		FW_TX_FEEDBACK_NONE			0xfb000000					
+#define		FW_TX_FEEDBACK_DTM_ENABLE	(FW_TX_FEEDBACK_NONE | 0x1)	
+#define		FW_TX_FEEDBACK_CCX_ENABLE	(FW_TX_FEEDBACK_NONE | 0x2) 
+#define		FW_BB_RESET_ENABLE			0xff00000d
+#define		FW_BB_RESET_DISABLE			0xff00000e
+#define		FW_LPS_ENTER					0xfe000010
+#define		FW_LPS_LEAVE					0xfe000011
+#define		FW_INDIRECT_READ				0xf2000000
+#define		FW_INDIRECT_WRITE				0xf2000001
+#define		FW_CHAN_SET					0xf3000001 
+
+
+
+
+
+
+
+#define RFPC					0x5F			
+#define RCR_9356SEL			BIT6
+#define TCR_LRL_OFFSET		0
+#define TCR_SRL_OFFSET		8
+#define TCR_MXDMA_OFFSET	21
+#define TCR_SAT				BIT24		
+#define RCR_MXDMA_OFFSET	8
+#define RCR_FIFO_OFFSET		13
+#define RCR_OnlyErlPkt		BIT31				
+#define CWR					0xDC			
+#define RetryCTR				0xDE			
+
+
+#define		LED1Cfg				UnusedRegister	
+#define 	LED0Cfg				UnusedRegister	
+#define 	GPI					UnusedRegister	
+#define 	BRSR				UnusedRegister	
+#define 	CPU_GEN				UnusedRegister	
+#define 	SIFS				UnusedRegister	
+
+#define 	CPU_GEN_SYSTEM_RESET		0x00000001
+
+
+
+
+#define		CCX_COMMAND_REG			0x890	
+#define		CLM_PERIOD_REG			0x894	
+#define		NHM_PERIOD_REG			0x896	
+#define		NHM_THRESHOLD0			0x898	
+#define		NHM_THRESHOLD1			0x899	
+#define		NHM_THRESHOLD2			0x89A	
+#define		NHM_THRESHOLD3			0x89B	
+#define		NHM_THRESHOLD4			0x89C	
+#define		NHM_THRESHOLD5			0x89D	
+#define		NHM_THRESHOLD6			0x89E	
+#define		CLM_RESULT_REG			0x8D0	
+#define		NHM_RESULT_REG			0x8D4	
+#define		NHM_RPI_COUNTER0		0x8D8	
+#define		NHM_RPI_COUNTER1		0x8D9	
+#define		NHM_RPI_COUNTER2		0x8DA	      
+#define		NHM_RPI_COUNTER3		0x8DB	      
+#define		NHM_RPI_COUNTER4		0x8DC	      
+#define		NHM_RPI_COUNTER5		0x8DD	      
+#define		NHM_RPI_COUNTER6		0x8DE	      
+#define		NHM_RPI_COUNTER7		0x8DF	      
+
+
+#define		HAL_8192S_HW_GPIO_OFF_BIT	BIT3
+#define		HAL_8192S_HW_GPIO_OFF_MASK	0xF7
+#define		HAL_8192S_HW_GPIO_WPS_BIT	BIT4
+
+#endif 
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ * 
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ * 
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef __INC_EFUSE_H
+#define __INC_EFUSE_H
+
+#define		EFUSE_FOR_92SU		1
+
+/*--------------------------Define Parameters-------------------------------*/
+#define		EFUSE_REAL_CONTENT_LEN			512
+#define		EFUSE_MAP_LEN				128
+#define		EFUSE_MAX_SECTION			16
+#define		EFUSE_MAX_WORD_UNIT			4
+#define 	       EFUSE_IC_ID_OFFSET			506 
+
+#define		EFUSE_INIT_MAP				0
+#define		EFUSE_MODIFY_MAP				1
+
+#define		EFUSE_CLK_CTRL			EFUSE_CTRL
+#define 	EFUSE_BIT(x)  (1 << (x))
+
+#define		PG_STATE_HEADER 	0x01
+#define		PG_STATE_WORD_0		0x02
+#define		PG_STATE_WORD_1		0x04
+#define		PG_STATE_WORD_2		0x08
+#define		PG_STATE_WORD_3		0x10
+#define		PG_STATE_DATA		0x20
+
+#define		PG_SWBYTE_H			0x01
+#define		PG_SWBYTE_L			0x02
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/ 
+
+/*------------------------------Define structure----------------------------*/ 
+
+
+/*------------------------Export global variable----------------------------*/
+/*------------------------Export global variable----------------------------*/
+
+/*------------------------Export Marco Definition---------------------------*/
+
+/*------------------------Export Marco Definition---------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+extern	void	
+EFUSE_Initialize(struct net_device* dev);
+extern	u8	
+EFUSE_Read1Byte(struct net_device* dev,u16 Address);
+extern	void	
+EFUSE_Write1Byte(struct net_device* dev,u16 Address,u8 Value);
+
+#ifdef EFUSE_FOR_92SU 
+extern 	void 
+ReadEFuse(struct net_device* dev,u16 _offset,u16 _size_byte,u8* pbuf);
+extern	void
+ReadEFuseByte(struct net_device* dev,u16  _offset,u8  *pbuf);
+#endif	
+
+extern	void
+EFUSE_ShadowRead(struct net_device* dev,unsigned char Type,unsigned short Offset,u32 *Value);
+extern	void
+EFUSE_ShadowWrite(struct net_device* dev,unsigned char Type,unsigned short Offset,u32 Value);
+extern	bool
+EFUSE_ShadowUpdate(struct net_device* dev);
+extern	bool
+EFUSE_ShadowUpdateChk(struct net_device* dev);
+extern	void 
+EFUSE_ShadowMapUpdate(struct net_device* dev);
+extern	void 
+EFUSE_RePgSection1(struct net_device* dev);
+
+extern	bool	
+EFUSE_ProgramMap(struct net_device* dev,char* pFileName, u8 TableType);		
+/*--------------------------Exported Function prototype---------------------*/
+
+/* End of Efuse.h */
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.c
@@ -0,0 +1,5904 @@
+/*Created on  2010/ 2/24,  2:32*/
+
+#ifdef RTL8192SE
+#include "r8192S_hwimg.h"
+
+u8 Rtl8192SEFwImgArray[ImgArrayLength] = {
+0x92,0x81,0x3e,0x70,0x30,0x00,0x00,0x00,0x08,0xb4,0x00,0x00,0xc8,0x87,0x00,0x00,
+0x30,0x00,0x00,0x00,0x40,0x86,0x00,0x00,0x3e,0x00,0x0c,0x00,0x01,0x18,0x17,0x51,
+0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37,
+0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,
+0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x01,0x80,0x1a,0x3c,0xcc,0xac,0x5a,0x27,
+0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf,
+0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf,
+0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf,
+0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf,
+0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf,
+0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf,
+0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf,
+0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xcb,0x2a,0x00,0x08,
+0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34,
+0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c,
+0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c,
+0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10,
+0x03,0x46,0x08,0x00,0xcc,0x3d,0x42,0x8d,0x38,0x15,0x05,0x26,0xec,0x23,0xa4,0x94,
+0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0,
+0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xf0,0x23,0xa2,0x94,0xec,0x23,0xa0,0xa4,
+0xf0,0x23,0xa0,0xa4,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xa0,0x00,0x00,0x20,0xad,
+0x01,0x00,0x82,0x24,0xcc,0x3d,0x47,0xad,0xec,0x23,0xa2,0xa4,0x12,0x00,0x00,0x05,
+0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x38,0x15,0x04,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
+0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
+0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x54,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x04,0x26,
+0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,
+0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,
+0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,
+0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,
+0xc0,0x82,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,
+0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,
+0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,
+0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,
+0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
+0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
+0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08,
+0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x43,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,
+0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,
+0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa2,0x94,
+0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,0xf5,0xff,0x40,0x1c,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
+0x00,0x80,0x02,0x3c,0xd0,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,0x7c,0x05,0x42,0x24,
+0x00,0x00,0x62,0xac,0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,
+0x2c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x08,0x00,0xf3,0x8c,
+0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x0c,0x00,0xf1,0x84,0x23,0x10,0x46,0x00,
+0xff,0xff,0xa3,0x30,0xff,0xff,0x50,0x30,0xff,0x00,0x94,0x30,0xd0,0x03,0x08,0x35,
+0x21,0x30,0xc5,0x00,0x21,0x20,0x80,0x02,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,
+0x02,0x92,0x03,0x00,0x00,0x00,0x11,0xad,0x00,0x00,0x13,0xad,0x8f,0x01,0x00,0x08,
+0x00,0x00,0x00,0x00,0x01,0x01,0x23,0x2a,0xff,0xff,0x22,0x32,0x21,0x98,0x70,0x02,
+0x21,0x20,0x80,0x02,0x00,0x01,0x10,0x24,0x4d,0x01,0x00,0x0c,0x0b,0x80,0x43,0x00,
+0xc0,0x10,0x12,0x00,0x28,0xb0,0x03,0x3c,0x21,0x10,0x43,0x00,0x00,0x00,0x45,0x90,
+0x20,0x10,0x06,0x3c,0x21,0x20,0x80,0x02,0xff,0x00,0xb2,0x30,0x00,0x12,0x12,0x00,
+0x21,0x30,0x46,0x00,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x23,0x18,0x30,0x02,0x00,0x8c,0x03,0x00,0x03,0x8c,0x11,0x00,
+0xe8,0xff,0x20,0x1e,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x38,0x15,0x52,0x24,0x00,0x80,0x02,0x3c,
+0x18,0x03,0x83,0x34,0x78,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0xc0,0x24,0x42,0x8e,
+0x2c,0x25,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0xc4,0x24,0x42,0xae,
+0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x2c,0x25,0x44,0x8e,
+0x30,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
+0x0a,0x18,0x82,0x00,0x2c,0x25,0x43,0xae,0x2c,0x25,0x85,0x8e,0x00,0x00,0x00,0x00,
+0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
+0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x40,0x00,0x07,0x24,
+0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
+0x74,0x24,0x91,0xa2,0xc0,0x24,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x00,0x00,0x05,0x96,0x24,0x24,0x83,0x8e,0x2a,0xb0,0x02,0x3c,0x27,0x20,0x05,0x00,
+0x01,0x00,0x46,0x34,0x21,0x10,0x65,0x00,0x2b,0x18,0x64,0x00,0x02,0x00,0x60,0x10,
+0x00,0x00,0x00,0x00,0x24,0x24,0x82,0xae,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
+0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0xc0,0xff,0x02,0x24,0x25,0x18,0x64,0x00,
+0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0xc2,0xa0,0x00,0x00,0xc3,0xa0,0xbc,0xff,0x35,0x16,0x41,0xb0,0x03,0x3c,
+0x08,0x0b,0x82,0x8e,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,
+0x2c,0x00,0xb5,0x8f,0x08,0x0b,0x82,0xae,0x24,0x00,0xb3,0x8f,0x28,0x00,0xb4,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
+0x18,0x03,0x83,0x34,0x04,0x08,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,
+0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x52,0x24,0xb0,0x03,0x95,0x34,0x25,0x02,0x00,0x08,
+0x21,0xf0,0x40,0x02,0x08,0x00,0x04,0xae,0x82,0x0b,0x82,0x92,0x00,0x00,0x00,0x00,
+0x45,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24,
+0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x5a,0x00,0x36,0x12,
+0x00,0x00,0x00,0x00,0xd8,0x24,0x42,0x8e,0x44,0x25,0x53,0x8e,0x01,0x00,0x04,0x24,
+0x00,0x00,0xa2,0xae,0xdc,0x24,0x42,0xae,0x00,0x00,0xb3,0xae,0x4d,0x01,0x00,0x0c,
+0x21,0xa0,0xc0,0x03,0x44,0x25,0x44,0x8e,0x48,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,
+0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x44,0x25,0x43,0xae,
+0x44,0x25,0xc5,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa5,0xae,0x02,0x80,0x17,0x3c,
+0xff,0xff,0x62,0x32,0x25,0x80,0x57,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x02,0x92,
+0xff,0x00,0x16,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0x0c,0x00,0x11,0x92,
+0x20,0x10,0x02,0x3c,0x40,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,
+0x05,0x00,0x36,0x12,0x21,0x30,0x60,0x00,0xd8,0x24,0xc3,0xaf,0x7c,0x24,0xd1,0xa3,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
+0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,
+0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xbd,0xff,0x40,0x10,
+0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,0x82,0x0b,0x82,0x92,0x00,0x00,0x00,0x00,
+0xbd,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x00,0x03,0x24,0x82,0x0b,0x83,0xa2,
+0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,
+0x25,0x10,0x57,0x00,0x02,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0xff,0xc0,0x64,0x30,
+0x00,0xc0,0x84,0x34,0xe0,0x24,0x00,0x0c,0x83,0x0b,0x83,0xa2,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,
+0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,
+0xa8,0xff,0x36,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x24,
+0x08,0x0b,0x43,0x8c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34,
+0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
+0x18,0x03,0x83,0x34,0x54,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,
+0x38,0x15,0xd3,0x26,0xb0,0x03,0x94,0x34,0x02,0x80,0x15,0x3c,0x21,0xb8,0x60,0x02,
+0xcc,0x24,0x62,0x8e,0x38,0x25,0x70,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x82,0xae,
+0xd0,0x24,0x62,0xae,0x00,0x00,0x90,0xae,0x4d,0x01,0x00,0x0c,0x21,0x88,0xe0,0x02,
+0x38,0x25,0x64,0x8e,0x3c,0x25,0x63,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x38,0x25,0x63,0xae,0x38,0x25,0xe5,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x90,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x82,0xae,0x0c,0x00,0x12,0x92,0xff,0x00,0x02,0x24,0x0a,0x00,0x42,0x12,
+0x00,0x1a,0x12,0x00,0x20,0x10,0x02,0x3c,0x21,0x18,0x62,0x00,0xcc,0x24,0xe3,0xae,
+0x78,0x24,0xf2,0xa2,0x21,0x30,0x60,0x00,0x01,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x24,0x22,0x8e,0x04,0x00,0x03,0x8e,
+0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x5d,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,
+0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
+0x00,0x26,0x04,0x00,0x25,0x28,0x44,0x00,0x08,0x00,0x05,0xae,0xc2,0x11,0x05,0x00,
+0x01,0x00,0x43,0x30,0x47,0x00,0x60,0x14,0x01,0x00,0x02,0x24,0x00,0x00,0x04,0x96,
+0x28,0x24,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x05,0x00,0x40,0x10,
+0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0x28,0x24,0x22,0xae,0x08,0x00,0x05,0x8e,
+0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x40,0x03,0x3c,
+0x25,0x28,0xa3,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0x03,0x00,0x40,0x14,
+0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x04,0x00,0x45,0x34,0x08,0x00,0x05,0xae,
+0x38,0x15,0xc2,0x26,0x82,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x3b,0x00,0x83,0x10,
+0x7f,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x08,0x00,0x02,0xae,0x38,0x15,0xc5,0x26,
+0xd0,0x24,0xa2,0x8c,0x20,0x00,0x10,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x2a,0xb0,0x03,0x3c,0x08,0x00,0x50,0xac,0x05,0x00,0x70,0x34,0x01,0x00,0x02,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x02,0xa2,0x00,0x00,0x03,0xa2,0xdc,0x3d,0xa2,0x96,
+0xff,0x00,0x03,0x24,0x01,0x00,0x42,0x24,0xdc,0x3d,0xa2,0xa6,0xdc,0x3d,0xa4,0x96,
+0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,0x00,0x00,0x44,0xa4,0x98,0xff,0x43,0x16,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0xa2,0xac,0xc3,0xff,0x62,0x14,0xff,0xdf,0x02,0x3c,0x00,0x00,0x04,0x96,
+0x24,0x24,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0xbd,0xff,0x40,0x10,
+0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0xeb,0x02,0x00,0x08,0x24,0x24,0x22,0xae,
+0x08,0x00,0x05,0x8e,0xe0,0x02,0x00,0x08,0xc2,0x11,0x05,0x00,0x80,0x00,0xa5,0x34,
+0xff,0x02,0x00,0x08,0x08,0x00,0x05,0xae,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0x94,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0xe8,0x0c,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0x94,0x3e,0xc2,0xa0,0x94,0x3e,0xc2,0x90,0x25,0xb0,0x04,0x3c,
+0x88,0x02,0x83,0x34,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x38,0x15,0xb2,0x26,0xb0,0x03,0x93,0x34,
+0x02,0x80,0x14,0x3c,0xac,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x58,0x24,0xf1,0xa2,
+0x38,0x15,0xa2,0x26,0x90,0x24,0x46,0x8c,0xfc,0x24,0x45,0x8c,0x03,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x38,0x15,0xa5,0x26,
+0x04,0x24,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x18,0x44,0x00,
+0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x28,0x24,0xa3,0x8c,0x27,0x10,0x04,0x00,
+0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x28,0x24,0xa2,0xac,
+0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04,0x00,0x00,0x00,0x00,
+0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,
+0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,
+0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x43,0x00,
+0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,
+0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x0d,0x00,0xe2,0x34,
+0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xdc,0x3d,0x84,0x96,0x25,0xb0,0x06,0x3c,
+0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xdc,0x3d,0x84,0xa6,0xdc,0x3d,0x82,0x96,
+0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
+0x90,0x24,0x42,0x8e,0xfc,0x24,0x50,0x8e,0x03,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
+0x94,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xfc,0x24,0x44,0x8e,0x00,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xfc,0x24,0x43,0xae,0xfc,0x24,0xe2,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x9f,0xff,0x22,0x12,
+0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x93,0xff,0xc0,0x16,
+0x90,0x24,0xe2,0xae,0x60,0x03,0x00,0x08,0x54,0x24,0xf1,0xa2,0x08,0x00,0x03,0x8e,
+0x94,0x03,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xab,0xff,0x40,0x14,
+0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,
+0x82,0x03,0x00,0x08,0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12,0x38,0x15,0xa2,0x26,
+0x58,0x24,0x43,0x90,0x41,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x38,0x15,0xa5,0x26,0x08,0x0b,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x00,0x80,0x42,0x34,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0x54,0x24,0x43,0x90,
+0x40,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0xa5,0x26,
+0x08,0x0b,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
+0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0x94,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x78,0x10,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0x94,0x3e,0xc2,0xa0,0x94,0x3e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x38,0x15,0xb2,0x26,
+0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,0x91,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,
+0x60,0x24,0xf1,0xa2,0x38,0x15,0xa2,0x26,0x9c,0x24,0x46,0x8c,0x08,0x25,0x45,0x8c,
+0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x38,0x15,0xa5,0x26,0x04,0x24,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,
+0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,
+0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,
+0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x28,0x24,0xa3,0x8c,
+0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,
+0x28,0x24,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04,
+0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,
+0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,
+0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,
+0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,
+0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xdc,0x3d,0x84,0x96,
+0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xdc,0x3d,0x84,0xa6,
+0xdc,0x3d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12,
+0x00,0x00,0x00,0x00,0x9c,0x24,0x42,0x8e,0x08,0x25,0x50,0x8e,0x04,0x00,0x04,0x24,
+0x00,0x00,0x62,0xae,0xa0,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x08,0x25,0x44,0x8e,0x0c,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,
+0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x08,0x25,0x43,0xae,
+0x08,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
+0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
+0x9f,0xff,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
+0x93,0xff,0xc0,0x16,0x9c,0x24,0xe2,0xae,0x45,0x04,0x00,0x08,0x5c,0x24,0xf1,0xa2,
+0x08,0x00,0x03,0x8e,0x79,0x04,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,
+0xab,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x10,0x82,0x00,0x67,0x04,0x00,0x08,0x10,0x00,0x02,0xae,0x1f,0x00,0xc0,0x12,
+0x38,0x15,0xa2,0x26,0x60,0x24,0x43,0x90,0x43,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x38,0x15,0xa5,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x5c,0x24,0x43,0x90,
+0x42,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0xa5,0x26,
+0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
+0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf,
+0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
+0x94,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0x04,0x14,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xb0,0x00,0x00,
+0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,0x01,0x00,0x16,0x24,
+0x94,0x3e,0xc2,0xa0,0x94,0x3e,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x15,0x3c,0x38,0x15,0xb2,0x26,0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,
+0x48,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,
+0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,0x08,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,
+0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,
+0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x1d,0x00,0xe2,0x34,
+0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
+0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xdc,0x3d,0x84,0x96,0x25,0xb0,0x06,0x3c,
+0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xdc,0x3d,0x84,0xa6,0xdc,0x3d,0x82,0x96,
+0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
+0xa8,0x24,0x42,0x8e,0x14,0x25,0x50,0x8e,0x05,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
+0xac,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x14,0x25,0x44,0x8e,0x18,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,
+0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x14,0x25,0x43,0xae,0x14,0x25,0xe2,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
+0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
+0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x66,0x00,0xc0,0x12,
+0xa8,0x24,0xe2,0xae,0x70,0x24,0xf1,0xa2,0x38,0x15,0xa2,0x26,0xa8,0x24,0x46,0x8c,
+0x14,0x25,0x45,0x8c,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x38,0x15,0xa5,0x26,0x04,0x24,0xa2,0x8c,0x04,0x00,0x03,0x8e,
+0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,
+0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
+0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae,0x00,0x00,0x04,0x96,
+0x28,0x24,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,
+0x21,0x10,0x64,0x00,0x28,0x24,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,
+0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x96,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
+0x1d,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,
+0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
+0xdc,0x3d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
+0xdc,0x3d,0x84,0xa6,0xdc,0x3d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
+0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12,0x38,0x15,0xa2,0x26,
+0x70,0x24,0x43,0x90,0x45,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x38,0x15,0xa5,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x6a,0x05,0x00,0x08,0x64,0x24,0xf1,0xa2,
+0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,
+0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x8c,0x05,0x00,0x08,0x10,0x00,0x02,0xae,
+0x64,0x24,0x43,0x90,0x44,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
+0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x38,0x15,0xa5,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,
+0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0x94,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0xe8,0x17,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0xfd,0x00,0xa2,0x30,
+0x01,0x00,0x16,0x24,0x94,0x3e,0xc2,0xa0,0x94,0x3e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x38,0x15,0xb2,0x26,0x21,0x98,0x40,0x00,
+0x02,0x80,0x14,0x3c,0x41,0x06,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
+0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,
+0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,
+0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,
+0x25,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xdc,0x3d,0x84,0x96,
+0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xdc,0x3d,0x84,0xa6,
+0xdc,0x3d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12,
+0x00,0x00,0x00,0x00,0xb4,0x24,0x42,0x8e,0x20,0x25,0x50,0x8e,0x06,0x00,0x04,0x24,
+0x00,0x00,0x62,0xae,0xb8,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x20,0x25,0x44,0x8e,0x24,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,
+0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x20,0x25,0x43,0xae,
+0x20,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
+0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
+0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
+0x66,0x00,0xc0,0x12,0xb4,0x24,0xe2,0xae,0x6c,0x24,0xf1,0xa2,0x38,0x15,0xa2,0x26,
+0xb4,0x24,0x46,0x8c,0x20,0x25,0x45,0x8c,0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x38,0x15,0xa5,0x26,0x04,0x24,0xa2,0x8c,
+0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,
+0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae,
+0x00,0x00,0x04,0x96,0x28,0x24,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,
+0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x28,0x24,0xa2,0xac,0x10,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,
+0x96,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00,
+0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,
+0x2a,0xb0,0x07,0x3c,0x25,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24,
+0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,
+0x00,0x00,0x43,0xa0,0xdc,0x3d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,
+0x01,0x00,0x84,0x24,0xdc,0x3d,0x84,0xa6,0xdc,0x3d,0x82,0x96,0xff,0x00,0x03,0x24,
+0x00,0x00,0xa2,0xa4,0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12,
+0x38,0x15,0xa2,0x26,0x6c,0x24,0x43,0x90,0x47,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x38,0x15,0xa5,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x63,0x06,0x00,0x08,
+0x68,0x24,0xf1,0xa2,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,
+0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,
+0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x85,0x06,0x00,0x08,
+0x10,0x00,0x02,0xae,0x68,0x24,0x43,0x90,0x46,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,
+0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x38,0x15,0xa5,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x00,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xcc,0x1b,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,
+0x38,0x15,0xa5,0x24,0x10,0x0b,0xa2,0x8c,0x08,0x0b,0xa4,0x8c,0x00,0x08,0x03,0x3c,
+0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c,
+0xc0,0xff,0xbd,0x27,0x18,0x03,0xa4,0x34,0x28,0x1c,0x42,0x24,0x2a,0xb0,0x03,0x3c,
+0x00,0x00,0x82,0xac,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x2c,0x00,0x63,0x34,
+0x00,0x00,0x69,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x24,0x31,0xaf,0x00,0x82,0x10,
+0x00,0x80,0x22,0x31,0x37,0x00,0x40,0x10,0x00,0xff,0x02,0x3c,0x00,0x80,0x02,0x3c,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x14,0x00,0x82,0x10,0x02,0x80,0x03,0x3c,
+0x38,0x15,0x70,0x24,0xff,0x00,0x23,0x31,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x50,0x25,0x05,0x8e,0x25,0xb0,0x02,0x3c,0xff,0x00,0x28,0x31,
+0x7c,0x03,0x42,0x34,0x00,0x00,0x48,0xa4,0x21,0x30,0x60,0x00,0xe4,0x24,0x03,0xae,
+0x80,0x24,0x09,0xa2,0x0a,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x01,0x00,0x03,0x24,0x58,0x25,0x03,0xa2,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x44,0x24,0x58,0x25,0x83,0x90,0x01,0x00,0x02,0x24,0x28,0x00,0x62,0x10,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x50,0x24,0x59,0x25,0x02,0x92,0x00,0x00,0x00,0x00,
+0x08,0x00,0x40,0x10,0x00,0x04,0x03,0x3c,0x10,0x0b,0x02,0x8e,0x08,0x0b,0x04,0x8e,
+0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,
+0x08,0x0b,0x04,0xae,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x40,0x00,0xbd,0x27,0x24,0x10,0x22,0x01,0xcb,0xff,0x40,0x10,0xff,0x00,0x02,0x24,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,0x80,0x24,0x62,0x90,0x20,0xb0,0x03,0x3c,
+0xb0,0x03,0xa4,0x34,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x49,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xac,0x25,0x07,0x00,0x08,0xff,0x00,0x24,0x31,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,
+0x21,0x88,0x80,0x00,0x2a,0xb0,0x04,0x3c,0x2c,0x00,0x9e,0x34,0xb0,0x03,0x54,0x34,
+0x21,0x98,0x20,0x02,0x7c,0x03,0x57,0x34,0x01,0x00,0x16,0x24,0x99,0x07,0x00,0x08,
+0x01,0x00,0x15,0x24,0xf2,0x23,0x22,0x96,0x25,0xb0,0x03,0x3c,0x1e,0x03,0x63,0x34,
+0x01,0x00,0x42,0x34,0x59,0x25,0x36,0xa2,0x00,0x00,0x62,0xa4,0xf2,0x23,0x22,0xa6,
+0x30,0x00,0x02,0x24,0x03,0x00,0x42,0x12,0x02,0x00,0x02,0x24,0x01,0x00,0xd6,0xa3,
+0x01,0x00,0xc2,0xa3,0x59,0x25,0x62,0x92,0x00,0x00,0x00,0x00,0x4f,0x00,0x55,0x14,
+0x02,0x80,0x02,0x3c,0x0c,0x00,0x03,0x92,0xff,0x00,0x02,0x24,0xff,0x00,0x69,0x30,
+0x4a,0x00,0x22,0x11,0x02,0x80,0x02,0x3c,0x80,0x24,0x63,0xa2,0x80,0x24,0x28,0x92,
+0x50,0x25,0x25,0x8e,0x20,0x10,0x02,0x3c,0xff,0x00,0x03,0x31,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x00,0x00,0x89,0xae,0x21,0x30,0x60,0x00,0x00,0x00,0xe8,0xa6,
+0x0a,0x00,0x04,0x24,0xe4,0x24,0x23,0xae,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x50,0x25,0x30,0x8e,0x0a,0x00,0x04,0x24,0x00,0x00,0x90,0xae,
+0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c,0x25,0x80,0x02,0x02,
+0x02,0x00,0x03,0x92,0x20,0x00,0x02,0x24,0xd2,0xff,0x62,0x14,0x21,0x38,0x03,0x02,
+0x02,0x80,0x02,0x3c,0xc8,0x87,0x47,0xac,0x20,0x00,0x03,0x26,0x02,0x00,0x62,0x90,
+0x59,0x25,0x25,0x92,0x03,0x00,0x64,0x90,0xff,0x00,0x52,0x30,0x28,0x00,0x07,0x26,
+0x13,0x00,0xb5,0x14,0x7f,0x00,0x86,0x30,0x02,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,
+0xbc,0x3d,0x43,0x94,0xd1,0x3d,0xa4,0x90,0x01,0x00,0x63,0x24,0x7f,0x00,0x84,0x30,
+0x08,0x00,0xc4,0x10,0xbc,0x3d,0x43,0xa4,0xf2,0x23,0x22,0x96,0x25,0xb0,0x03,0x3c,
+0x1e,0x03,0x63,0x34,0x10,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0xd1,0x3d,0xa6,0xa0,
+0xf2,0x23,0x22,0xa6,0x31,0x00,0x42,0x2e,0xbd,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x01,0x80,0x02,0x3c,0x02,0x80,0x06,0x3c,0xc0,0x18,0x12,0x00,0x1c,0x74,0x42,0x24,
+0xbe,0x3d,0xc5,0x94,0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,0x01,0x00,0xa5,0x24,
+0x02,0x80,0x03,0x3c,0x21,0x20,0xe0,0x00,0xbe,0x3d,0xc5,0xa4,0x09,0xf8,0x40,0x00,
+0xc4,0x87,0x62,0xac,0x7d,0x07,0x00,0x08,0x30,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,
+0x38,0x15,0x62,0x24,0x3b,0x07,0x00,0x08,0x58,0x25,0x40,0xa0,0x84,0x3e,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x41,0x07,0x00,0x08,
+0x02,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c,
+0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,
+0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00,
+0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00,
+0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34,
+0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30,
+0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad,
+0x38,0x15,0xa5,0x26,0xee,0x23,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,
+0xee,0x23,0xa2,0xa0,0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26,
+0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00,
+0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00,
+0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10,
+0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,0x38,0x15,0xb4,0x26,
+0xb4,0x25,0x86,0x8e,0xb8,0x25,0x90,0x8e,0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00,
+0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02,
+0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30,
+0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c,
+0xb4,0x25,0x82,0xae,0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02,
+0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c,0x10,0x01,0x00,0x0c,0x38,0x15,0xb1,0x26,
+0xb4,0x25,0x23,0x8e,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
+0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x25,0x25,0x8e,
+0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,
+0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,
+0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02,
+0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa2,0xaf,0xb4,0x25,0x83,0x8e,0x38,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c,
+0x21,0x18,0x72,0x00,0xb4,0x25,0x83,0xae,0xb4,0x25,0x23,0x8e,0xb0,0x03,0x02,0x36,
+0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xb4,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,
+0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,
+0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,
+0x10,0x00,0xb0,0xaf,0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00,
+0x08,0x00,0x06,0x24,0x04,0x00,0x63,0x2c,0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x03,0x3c,0x30,0x3b,0x63,0x24,0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae,
+0x04,0x00,0x71,0xac,0x00,0x00,0x91,0xac,0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,0x58,0x45,0x00,0x0c,
+0x25,0x20,0x44,0x00,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96,
+0xdd,0x07,0x00,0x0c,0x09,0x00,0x04,0x24,0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e,
+0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae,
+0xaa,0x47,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc0,0x22,0x63,0x24,0x18,0x03,0x42,0x34,
+0xe0,0xff,0xbd,0x27,0xff,0xff,0x84,0x30,0x00,0x00,0x43,0xac,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0xff,0xff,0xb0,0x30,
+0xff,0xff,0xd2,0x30,0x89,0x47,0x00,0x0c,0xff,0xff,0xf1,0x30,0x21,0x20,0x40,0x00,
+0x0a,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x08,0x00,0x43,0x94,0x14,0x00,0x50,0xac,
+0x02,0x80,0x02,0x3c,0x25,0x18,0x62,0x00,0x18,0x00,0x63,0x24,0x06,0x00,0x71,0xa4,
+0x78,0x08,0x00,0x0c,0x04,0x00,0x72,0xa4,0x01,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,
+0x03,0x00,0x82,0x90,0x04,0x00,0x84,0x24,0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,
+0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x78,0x23,0x63,0x24,0x18,0x03,0x42,0x34,0xd0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,
+0x24,0x00,0xb3,0xaf,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0xd2,0x08,0x00,0x0c,0x18,0x00,0xb0,0xaf,0x06,0x00,0x40,0x10,0x02,0x80,0x13,0x3c,
+0x38,0x15,0x63,0x26,0x82,0x0b,0x62,0x90,0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x14,
+0x00,0xc0,0x04,0x34,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x38,0x15,0x66,0x26,
+0xbc,0x25,0xc5,0x8c,0xc0,0x18,0x03,0x00,0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,
+0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,
+0x23,0x88,0x85,0x00,0x00,0x04,0x22,0x26,0x2b,0x28,0x85,0x00,0x6c,0x25,0xc3,0x8c,
+0x0b,0x88,0x45,0x00,0xe1,0x01,0x22,0x2e,0x68,0x25,0xc3,0xac,0xc0,0x25,0xc4,0xac,
+0x72,0x25,0xc0,0xa4,0x14,0x00,0x40,0x14,0x71,0x25,0xc0,0xa0,0x20,0xfe,0x82,0x24,
+0x20,0x02,0x83,0x24,0x0a,0x18,0x45,0x00,0x23,0x10,0x02,0x3c,0xff,0x03,0x42,0x34,
+0x2b,0x10,0x43,0x00,0x21,0x28,0x60,0x00,0x34,0x00,0x40,0x14,0xbc,0x25,0xc3,0xac,
+0xc0,0x25,0xc2,0x8c,0x00,0x00,0x00,0x00,0x2b,0x18,0x45,0x00,0x23,0x88,0x45,0x00,
+0x03,0x00,0x60,0x10,0xe1,0x01,0x22,0x2e,0x00,0x04,0x31,0x26,0xe1,0x01,0x22,0x2e,
+0x0e,0x00,0x40,0x10,0x38,0x15,0x70,0x26,0x38,0x15,0x70,0x26,0xc0,0x25,0x03,0x8e,
+0xbc,0x25,0x04,0x8e,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x26,0x00,0x40,0x14,
+0x2b,0x10,0x64,0x00,0x52,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,
+0xd0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x38,0x15,0x70,0x26,0xbc,0x25,0x03,0x96,
+0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,
+0x7e,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e,0x80,0x00,0x03,0x3c,
+0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,
+0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0xfc,0xa5,0x24,
+0x14,0x09,0x00,0x08,0xbc,0x25,0xc5,0xac,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,
+0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x68,0x25,0x03,0x8e,0x72,0x25,0x05,0x96,0xbc,0x25,0x02,0x8e,0x21,0x18,0x71,0x00,
+0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,0x09,0x00,0x04,0x24,0xbc,0x25,0x02,0xae,
+0x68,0x25,0x03,0xae,0x4d,0x01,0x00,0x0c,0x72,0x25,0x05,0xa6,0x38,0x15,0x70,0x26,
+0xbc,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,
+0x00,0x00,0x51,0xa0,0x7e,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e,
+0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,
+0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0xc4,0x25,0x02,0x8e,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,
+0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x68,0x25,0x03,0x8e,0x72,0x25,0x02,0x96,0xc0,0x25,0x12,0x96,0x21,0x18,0x71,0x00,
+0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,0x68,0x25,0x03,0xae,0x72,0x25,0x02,0xa6,
+0x0c,0x00,0x40,0x16,0xbc,0x25,0x11,0xae,0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,
+0x38,0x15,0x70,0x26,0x5c,0x09,0x00,0x08,0x00,0x00,0x00,0x00,0x1c,0x27,0x62,0x94,
+0x82,0x0b,0x60,0xa0,0xe0,0x24,0x00,0x0c,0x21,0x20,0x44,0x00,0xf1,0x08,0x00,0x08,
+0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c,0x09,0x00,0x04,0x24,0x68,0x25,0x05,0x8e,
+0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c,0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x68,0x25,0x03,0x8e,0x72,0x25,0x02,0x96,0x21,0x20,0x51,0x02,
+0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02,0xbc,0x25,0x04,0xae,0x09,0x00,0x04,0x24,
+0x68,0x25,0x03,0xae,0x8b,0x09,0x00,0x08,0x72,0x25,0x02,0xa6,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x05,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x09,0x00,0x02,0x24,0x02,0x80,0x09,0x3c,0x38,0x15,0x28,0x25,0xf4,0x23,0x06,0x8d,
+0xff,0xff,0x02,0x34,0x44,0x00,0xc2,0x10,0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,
+0x34,0x00,0x40,0x10,0x02,0x19,0x06,0x00,0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,
+0x10,0x00,0x46,0x24,0xf4,0x23,0x06,0xad,0xf8,0x23,0x02,0xad,0x38,0x15,0x26,0x25,
+0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34,0xff,0xff,0x83,0x30,0x33,0x00,0x62,0x10,
+0x00,0x11,0x07,0x00,0xff,0xff,0x84,0x30,0x2b,0x10,0x87,0x00,0x20,0x00,0x40,0x10,
+0x03,0x19,0x04,0x00,0x03,0x11,0x04,0x00,0x21,0x18,0x87,0x00,0x23,0x18,0x62,0x00,
+0x10,0x00,0x64,0x24,0x06,0x00,0xc4,0xa4,0xf8,0x23,0xc3,0xac,0xc0,0x10,0x05,0x00,
+0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x38,0x15,0x23,0x25,
+0x80,0x10,0x02,0x00,0x21,0x28,0x43,0x00,0x80,0x11,0xa6,0x8c,0x00,0x21,0x07,0x00,
+0xff,0xff,0xc2,0x38,0x0a,0x30,0x82,0x00,0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,
+0x21,0x10,0xc7,0x00,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,
+0x80,0x11,0xa6,0xac,0x08,0x00,0xe0,0x03,0x84,0x11,0xa2,0xac,0x02,0x19,0x06,0x00,
+0x23,0x10,0x43,0x00,0x80,0x11,0xa2,0xac,0x08,0x00,0xe0,0x03,0x84,0x11,0xa2,0xac,
+0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,0x06,0x00,0xc2,0xa4,0xcb,0x09,0x00,0x08,
+0xf8,0x23,0xc2,0xac,0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0xf4,0x23,0x02,0xad,
+0xf8,0x23,0x02,0xad,0x38,0x15,0x26,0x25,0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34,
+0xff,0xff,0x83,0x30,0xcf,0xff,0x62,0x14,0x00,0x11,0x07,0x00,0x21,0x20,0x40,0x00,
+0xc1,0x09,0x00,0x08,0x06,0x00,0xc2,0xa4,0x00,0x31,0x04,0x00,0xb3,0x09,0x00,0x08,
+0xf4,0x23,0x06,0xad,0x63,0x00,0x82,0x24,0x77,0x00,0x42,0x2c,0x00,0x00,0x85,0x28,
+0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x64,0x00,0x82,0x24,0x64,0x00,0x03,0x24,
+0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xe8,0xff,0xbd,0x27,
+0x10,0x00,0xbf,0xaf,0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,
+0x04,0x00,0x42,0x28,0x07,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x04,0x00,0xa4,0x90,
+0x10,0x00,0xbf,0x8f,0x18,0x00,0xbd,0x27,0x42,0x20,0x04,0x00,0xf9,0x09,0x00,0x08,
+0x96,0xff,0x84,0x24,0x24,0x08,0x42,0x34,0x00,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x02,0x63,0x30,0x1b,0x00,0x60,0x14,0x01,0x00,0x02,0x24,0x05,0x00,0xa3,0x90,
+0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,0x3c,0x00,0x82,0x10,0x02,0x00,0x82,0x28,
+0x57,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x46,0x00,0x82,0x10,0x03,0x00,0x02,0x24,
+0x2e,0x00,0x82,0x10,0x3e,0x00,0x63,0x30,0xf9,0x09,0x00,0x0c,0x21,0x20,0xc0,0x00,
+0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c,0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00,
+0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,0x1f,0x00,0x40,0x10,0xe5,0xff,0xa2,0x24,
+0xfe,0xff,0xa5,0x24,0x10,0x00,0xbf,0x8f,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,
+0x42,0x21,0x04,0x00,0x25,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x36,0x00,0x40,0x14,
+0x02,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xe6,0xff,0x82,0x14,
+0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0xd8,0xff,0x03,0x24,0x23,0x30,0x62,0x00,
+0xf9,0x09,0x00,0x0c,0x21,0x20,0xc0,0x00,0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c,
+0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00,0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,
+0xe3,0xff,0x40,0x14,0xe5,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,0x06,0x00,0x40,0x10,
+0xf1,0xff,0xa2,0x24,0x2d,0x0a,0x00,0x08,0xfa,0xff,0xa5,0x24,0xd8,0xff,0x02,0x24,
+0x22,0x0a,0x00,0x08,0x23,0x30,0x43,0x00,0x0c,0x00,0x42,0x2c,0x0c,0x00,0x40,0x10,
+0xfb,0xff,0xa2,0x24,0x2d,0x0a,0x00,0x08,0xf8,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30,
+0xfe,0xff,0x02,0x24,0x22,0x0a,0x00,0x08,0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30,
+0x40,0x10,0x02,0x00,0xfe,0xff,0x03,0x24,0x40,0x0a,0x00,0x08,0x23,0x30,0x62,0x00,
+0x0a,0x00,0x42,0x2c,0xcb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x2d,0x0a,0x00,0x08,
+0xfc,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30,0xec,0xff,0x02,0x24,0x22,0x0a,0x00,0x08,
+0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0xec,0xff,0x03,0x24,
+0x40,0x0a,0x00,0x08,0x23,0x30,0x62,0x00,0xb3,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,
+0x40,0x10,0x02,0x00,0x0e,0x00,0x03,0x24,0x40,0x0a,0x00,0x08,0x23,0x30,0x62,0x00,
+0xad,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,0x0e,0x00,0x02,0x24,0x22,0x0a,0x00,0x08,
+0x23,0x30,0x43,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,
+0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14,0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c,
+0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30,0x40,0x20,0x04,0x00,0xf9,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26,0xfc,0x23,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,
+0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,
+0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0xfc,0x23,0xa4,0xac,0x00,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0xf9,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26,0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,
+0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,
+0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0x00,0x24,0xa4,0xac,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00,
+0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x24,0xa2,0xac,
+0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0xfc,0x23,0xa2,0xac,0x00,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0xf9,0x09,0x00,0x0c,
+0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26,0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,
+0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14,0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00,
+0xa3,0x0a,0x00,0x08,0x00,0x24,0xa4,0xac,0x00,0x21,0x03,0x00,0x8f,0x0a,0x00,0x08,
+0xfc,0x23,0xa4,0xac,0x98,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x58,0x00,0xb6,0xaf,
+0x64,0x00,0xbf,0xaf,0x60,0x00,0xbe,0xaf,0x5c,0x00,0xb7,0xaf,0x54,0x00,0xb5,0xaf,
+0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf,0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf,
+0x40,0x00,0xb0,0xaf,0x38,0x15,0x56,0x24,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,
+0x00,0x00,0x43,0x8c,0xa4,0x25,0xc7,0x8e,0x00,0x00,0x00,0x00,0x33,0x00,0xe3,0x10,
+0xa8,0x25,0xc3,0xae,0x2b,0x10,0x67,0x00,0xbf,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,
+0xe9,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x38,0x15,0x44,0x24,0x78,0x25,0x83,0x94,
+0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00,0x18,0x00,0x40,0x1a,0x25,0x98,0x62,0x00,
+0x21,0xf0,0x80,0x00,0x01,0x00,0x14,0x24,0x21,0x20,0x00,0x00,0x21,0x80,0x93,0x00,
+0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0xa0,0x10,0x01,0x00,0x22,0x26,
+0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,0x24,0x10,0x43,0x00,
+0x1f,0x00,0x44,0x10,0x06,0x00,0x22,0x26,0xff,0xff,0x51,0x30,0x82,0x16,0x05,0x00,
+0x01,0x00,0x42,0x30,0x35,0x00,0x54,0x10,0x02,0x80,0x03,0x3c,0x80,0x20,0x11,0x00,
+0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0xa4,0x8f,
+0xaa,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,
+0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x1c,0x2c,0x00,0x0c,0x21,0x38,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c,0xa4,0x25,0xc7,0x8e,
+0x00,0x00,0x00,0x00,0xcf,0xff,0xe3,0x14,0xa8,0x25,0xc3,0xae,0x25,0xb0,0x04,0x3c,
+0x00,0x01,0x82,0x34,0x00,0x00,0x47,0xac,0x06,0x0b,0x00,0x08,0xa4,0x25,0xc7,0xae,
+0xc8,0x0c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc8,0x0c,0xc2,0xaf,
+0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30,0x7b,0x00,0x62,0x10,
+0x21,0x28,0xc0,0x03,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24,0x70,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24,0x04,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0xfa,0x0a,0x00,0x08,0x06,0x00,0x22,0x26,
+0xd4,0x0c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xd4,0x0c,0xc2,0xaf,
+0x00,0x00,0x05,0x8e,0xfa,0x0a,0x00,0x08,0x06,0x00,0x22,0x26,0x38,0x15,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x54,0x10,
+0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0xff,0x0a,0x00,0x08,
+0xff,0xff,0x51,0x30,0x38,0x15,0x64,0x24,0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
+0x24,0x00,0x40,0x14,0x02,0x80,0x04,0x3c,0x04,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,
+0x02,0x14,0x04,0x00,0x0f,0x00,0x45,0x30,0x08,0x00,0xa3,0x28,0x1c,0x00,0x60,0x10,
+0x02,0x17,0x04,0x00,0x03,0x00,0x43,0x30,0x08,0x00,0x60,0x10,0x00,0xc0,0x02,0x3c,
+0x24,0x10,0x82,0x00,0x16,0x00,0x40,0x14,0x03,0x00,0x02,0x24,0x15,0x00,0x62,0x10,
+0x02,0x80,0x04,0x3c,0x14,0x00,0x60,0x10,0x38,0x15,0x82,0x24,0x80,0x10,0x11,0x00,
+0x21,0xa8,0x53,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x21,0x18,0xa2,0x00,
+0xec,0xff,0xa2,0x8e,0xf0,0x04,0x77,0x90,0x25,0xb0,0x03,0x3c,0xd4,0x02,0x63,0x34,
+0x21,0x28,0xa0,0x02,0x21,0x20,0x00,0x02,0x00,0x00,0x62,0xac,0x03,0x0a,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0xad,0x09,0x00,0x0c,0x21,0x28,0xe0,0x02,
+0x02,0x80,0x04,0x3c,0x38,0x15,0x82,0x24,0x01,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x80,0x00,0x74,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,
+0x01,0x00,0x83,0x90,0x02,0x00,0x02,0x24,0x08,0x00,0x62,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,
+0x21,0x10,0x51,0x00,0xff,0x0a,0x00,0x08,0xff,0xff,0x51,0x30,0x04,0x00,0x04,0x8e,
+0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x46,0x30,0x08,0x00,0xc3,0x28,
+0xf3,0xff,0x60,0x10,0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30,0xf0,0xff,0x40,0x14,
+0x80,0x10,0x11,0x00,0x21,0xa8,0x53,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,
+0x21,0x18,0xc2,0x00,0xec,0xff,0xa2,0x8e,0xf0,0x04,0x77,0x90,0x25,0xb0,0x03,0x3c,
+0xd4,0x02,0x63,0x34,0x21,0x28,0xa0,0x02,0x21,0x20,0x00,0x02,0x00,0x00,0x62,0xac,
+0x03,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0xad,0x09,0x00,0x0c,
+0x21,0x28,0xe0,0x02,0x00,0x00,0x05,0x8e,0x73,0x0b,0x00,0x08,0xc2,0x13,0x05,0x00,
+0xd0,0x0c,0xa2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xd0,0x0c,0xa2,0xac,
+0x0c,0x00,0x04,0x8e,0x26,0x0b,0x00,0x08,0x3f,0x00,0x83,0x30,0xcc,0x0c,0xc2,0x8f,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xcc,0x0c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,
+0x22,0x0b,0x00,0x08,0x3f,0x00,0x83,0x30,0xac,0x25,0xc2,0x8e,0xff,0xff,0x71,0x30,
+0x23,0x10,0x47,0x00,0xff,0xff,0x50,0x30,0x21,0x18,0x11,0x02,0xff,0xff,0x72,0x30,
+0x89,0x47,0x00,0x0c,0x21,0x20,0x40,0x02,0x74,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,
+0x38,0x00,0xa3,0x8f,0xa4,0x25,0xc6,0x8e,0x21,0x38,0x00,0x02,0x08,0x00,0x62,0x8c,
+0x08,0x00,0x04,0x24,0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,
+0x74,0x25,0xc3,0xae,0x10,0x01,0x00,0x0c,0x78,0x25,0xc2,0xae,0x4d,0x01,0x00,0x0c,
+0x08,0x00,0x04,0x24,0x78,0x25,0xc5,0x8e,0x25,0xb0,0x04,0x3c,0x24,0x10,0x02,0x3c,
+0x21,0x28,0xb0,0x00,0x00,0x01,0x90,0x34,0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,
+0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c,0xa4,0x25,0xc2,0xae,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0xa8,0x25,0xc3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,
+0xa4,0x25,0xc3,0xae,0xa4,0x25,0xc2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,
+0xe6,0x0a,0x00,0x08,0x02,0x80,0x02,0x3c,0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,
+0x89,0x47,0x00,0x0c,0x21,0x20,0x40,0x02,0x53,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,
+0x38,0x00,0xa3,0x8f,0xa4,0x25,0xc6,0x8e,0x08,0x00,0x04,0x24,0x08,0x00,0x62,0x8c,
+0x21,0x38,0x40,0x02,0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,
+0x74,0x25,0xc3,0xae,0x10,0x01,0x00,0x0c,0x78,0x25,0xc2,0xae,0xa8,0x25,0xc3,0x8e,
+0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0xa4,0x25,0xc3,0xae,0xa4,0x25,0xc3,0x8e,
+0x25,0xb0,0x04,0x3c,0x00,0x01,0x82,0x34,0x00,0x00,0x43,0xac,0xe6,0x0a,0x00,0x08,
+0x02,0x80,0x02,0x3c,0x04,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,
+0x0f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,
+0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30,0x0b,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,
+0x00,0xc0,0x02,0x3c,0x24,0x10,0x82,0x00,0x73,0xff,0x40,0x14,0x02,0x17,0x04,0x00,
+0x03,0x00,0x42,0x30,0x03,0x00,0x03,0x24,0x6f,0xff,0x43,0x10,0x00,0x00,0x00,0x00,
+0x6d,0xff,0x40,0x10,0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x15,0x00,0x54,0x10,0x21,0xb8,0x00,0x00,
+0x80,0x10,0x11,0x00,0x21,0xa8,0x53,0x00,0xec,0xff,0xa3,0x8e,0x25,0xb0,0x02,0x3c,
+0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x21,0x28,0xa0,0x02,0x00,0x00,0x43,0xac,
+0x03,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0xad,0x09,0x00,0x0c,
+0x21,0x28,0xe0,0x02,0x58,0xff,0xe0,0x16,0x00,0x00,0x00,0x00,0x21,0x28,0xa0,0x02,
+0x79,0x0a,0x00,0x0c,0x21,0x20,0x00,0x02,0x6b,0x0b,0x00,0x08,0x02,0x80,0x04,0x3c,
+0x02,0x14,0x04,0x00,0x0f,0x00,0x42,0x30,0x38,0x15,0x63,0x24,0x21,0x10,0x43,0x00,
+0xf0,0x04,0x57,0x90,0x05,0x0c,0x00,0x08,0x80,0x10,0x11,0x00,0x25,0xb0,0x04,0x3c,
+0x44,0x44,0x02,0x3c,0xbc,0x02,0x83,0x34,0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac,
+0x07,0x0b,0x00,0x08,0x02,0x80,0x02,0x3c,0xa8,0x25,0xc5,0x8e,0x25,0xb0,0x02,0x3c,
+0x00,0x01,0x43,0x34,0xbc,0x02,0x44,0x34,0x66,0x66,0x02,0x3c,0x66,0x66,0x42,0x34,
+0x00,0x00,0x65,0xac,0x00,0x00,0x82,0xac,0x06,0x0b,0x00,0x08,0xa4,0x25,0xc5,0xae,
+0x00,0x80,0x02,0x3c,0xc0,0x30,0x43,0x24,0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,
+0x18,0x03,0x42,0x34,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,
+0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x3c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,
+0x21,0xf0,0x00,0x00,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,
+0x02,0x80,0x17,0x3c,0x38,0x15,0x85,0x26,0xf0,0x23,0xa3,0x94,0x25,0xb0,0x08,0x3c,
+0x00,0x80,0x06,0x3c,0x18,0x03,0x04,0x35,0x01,0x00,0x63,0x24,0xc0,0x30,0xc2,0x24,
+0x00,0x00,0x82,0xac,0xf0,0x23,0xa3,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xc6,0x00,0x03,0x35,0x00,0x00,0x62,0x94,
+0x00,0x00,0x00,0x00,0x11,0x00,0x42,0x2c,0x08,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x04,0x3c,0x84,0x3e,0x62,0x8c,0x9c,0x3e,0x83,0x8c,0x02,0x80,0x06,0x3c,
+0x9c,0x3e,0x80,0xac,0x25,0x10,0x43,0x00,0x84,0x3e,0xc2,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xc0,0x02,0x02,0x35,0x00,0x00,0x52,0x8c,
+0xff,0x00,0x03,0x3c,0xff,0xff,0x62,0x34,0x2b,0x10,0x52,0x00,0x42,0x00,0x40,0x10,
+0x00,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x00,0xfd,0x04,0x3c,0x24,0x38,0x42,0x02,
+0x12,0x00,0x82,0x34,0x2e,0x06,0xe2,0x10,0x2b,0x10,0x47,0x00,0x41,0x02,0x40,0x14,
+0xa5,0x00,0x82,0x34,0x00,0xf8,0x06,0x3c,0x18,0x00,0xc2,0x34,0x71,0x06,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0xc0,0x02,0x40,0x14,0x00,0xfb,0x09,0x3c,0x00,0xf1,0x04,0x3c,
+0x02,0x00,0x82,0x34,0x2d,0x00,0xe2,0x10,0x2b,0x10,0x47,0x00,0x3e,0x03,0x40,0x14,
+0x11,0x00,0xc2,0x34,0x00,0xf0,0x04,0x3c,0x02,0x00,0x82,0x34,0xc4,0x06,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0x39,0x04,0x40,0x14,0x20,0x00,0x82,0x34,0x00,0xe0,0x02,0x3c,
+0xe9,0x06,0xe2,0x10,0x2b,0x10,0x47,0x00,0xd9,0x04,0x40,0x14,0x00,0xc0,0x02,0x3c,
+0x25,0x07,0xe2,0x10,0x00,0xd0,0x02,0x3c,0xaa,0x07,0xe2,0x10,0x00,0x0f,0x42,0x32,
+0x00,0xf0,0x02,0x3c,0x24,0x28,0x42,0x02,0x18,0x00,0xa2,0x10,0x00,0x70,0x08,0x3c,
+0x0f,0x00,0x03,0x3c,0x24,0x10,0x48,0x02,0x02,0x25,0x12,0x00,0xff,0xff,0x63,0x34,
+0x00,0x50,0x06,0x3c,0x24,0x38,0x43,0x02,0x02,0x57,0x02,0x00,0xff,0x00,0x84,0x30,
+0x7b,0x03,0xa6,0x10,0xff,0x00,0x49,0x32,0x2b,0x10,0xc5,0x00,0x6f,0x03,0x40,0x14,
+0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0xf2,0x05,0xa2,0x10,0x2b,0x10,0x45,0x00,
+0x30,0x04,0x40,0x14,0x00,0x30,0x02,0x3c,0xef,0x05,0xa0,0x10,0x80,0x10,0x04,0x00,
+0x00,0x10,0x02,0x3c,0xec,0x05,0xa2,0x10,0x80,0x10,0x04,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x08,0x3c,0x64,0x03,0x02,0x35,
+0x00,0x00,0x43,0x94,0x68,0x03,0x04,0x35,0xd0,0x3d,0xa3,0xa6,0x00,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0xe0,0x3d,0xc2,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0xca,0x01,0x40,0x10,0x38,0x15,0x86,0x26,0x38,0x15,0x87,0x26,0x38,0x15,0x84,0x8e,
+0xd8,0x02,0xe5,0x8c,0xe8,0x02,0xe6,0x8c,0xf0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x00,0x50,0x03,0x3c,0x24,0x28,0xa2,0x00,0x01,0x00,0x84,0x34,0x24,0x30,0xc3,0x00,
+0x00,0x10,0x02,0x3c,0x38,0x15,0x84,0xae,0xe2,0x05,0xc2,0x10,0xd8,0x02,0xe5,0xac,
+0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0xb4,0x01,0x40,0x10,
+0xf3,0xff,0x03,0x24,0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,
+0x04,0x00,0x42,0x34,0x38,0x15,0x82,0xae,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x04,0x00,0x42,0x30,0x41,0x01,0x40,0x10,0xcf,0xff,0x03,0x24,0x38,0x15,0x82,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x10,0x00,0x42,0x34,0x38,0x15,0x82,0xae,
+0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0x40,0x01,0x40,0x14,
+0x00,0x00,0x00,0x00,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,
+0x26,0x00,0x40,0x10,0x38,0x15,0x84,0x26,0xc9,0x02,0x82,0x90,0xe0,0x3d,0xc3,0x8e,
+0x01,0x00,0x42,0x24,0xc9,0x02,0x82,0xa0,0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,
+0xdb,0x05,0x62,0x10,0x02,0x80,0x04,0x3c,0xe0,0x3d,0x82,0x8c,0x02,0x00,0x03,0x24,
+0x0f,0x00,0x42,0x30,0xd8,0x05,0x43,0x10,0x00,0x00,0x00,0x00,0xe0,0x3d,0x82,0x8c,
+0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,
+0x21,0x20,0x00,0x00,0xc9,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,0xe0,0x3d,0xc3,0x8e,
+0xd0,0x3d,0xa5,0x96,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,
+0x02,0x19,0x03,0x00,0xef,0x00,0xa5,0x30,0x38,0x15,0x84,0x26,0x02,0x00,0x83,0xa0,
+0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xd0,0x3d,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,0x26,0x00,0x40,0x10,0x38,0x15,0x84,0x26,
+0xca,0x02,0x82,0x90,0xe0,0x3d,0xc3,0x8e,0x01,0x00,0x42,0x24,0xca,0x02,0x82,0xa0,
+0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,0xaf,0x05,0x62,0x10,0x02,0x80,0x04,0x3c,
+0xe0,0x3d,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xb0,0x05,0x43,0x10,
+0x00,0x00,0x00,0x00,0xe0,0x3d,0x82,0x8c,0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,
+0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0xc9,0x48,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xe0,0x3d,0xc3,0x8e,0xd0,0x3d,0xa5,0x96,0x25,0xb0,0x02,0x3c,
+0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,0x02,0x19,0x03,0x00,0xdf,0x00,0xa5,0x30,
+0x38,0x15,0x84,0x26,0x02,0x00,0x83,0xa0,0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x30,
+0xbc,0x00,0x40,0x10,0x38,0x15,0x84,0x26,0x38,0x15,0x8f,0x26,0x08,0x00,0xe4,0x8d,
+0x00,0x00,0x00,0x00,0x42,0x17,0x04,0x00,0x03,0x00,0x42,0x30,0x6f,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xe0,0x3d,0xc2,0x8e,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,
+0x24,0x18,0x83,0x00,0x00,0xff,0x11,0x3c,0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,
+0x24,0x10,0x51,0x00,0x08,0x00,0xe3,0xad,0x91,0x01,0x40,0x14,0x02,0x80,0x10,0x3c,
+0x25,0xb0,0x0e,0x3c,0x03,0x0d,0xc2,0x35,0x00,0x00,0x43,0x90,0x10,0x00,0xe4,0x8d,
+0xff,0x3f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x58,0x82,0x00,0x70,0x00,0x63,0x30,
+0x00,0x40,0x02,0x3c,0x78,0x05,0x60,0x10,0x25,0x58,0x62,0x01,0x94,0x0e,0xc2,0x35,
+0x9c,0x0e,0xc3,0x35,0xa4,0x0e,0xc4,0x35,0xac,0x0e,0xc5,0x35,0x00,0x00,0x47,0x8c,
+0x00,0x00,0x6a,0x8c,0x00,0x00,0x8c,0x8c,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xe4,0x8d,
+0xb4,0x0e,0xc2,0x35,0x00,0x00,0x49,0x8c,0xff,0x03,0x05,0x3c,0x00,0xfc,0x08,0x24,
+0xbc,0x0e,0xc2,0x35,0x24,0x38,0xe5,0x00,0x24,0x30,0xc5,0x00,0x24,0x18,0x68,0x01,
+0x02,0x3c,0x07,0x00,0x00,0x00,0x4b,0x8c,0x24,0x20,0x88,0x00,0x02,0x34,0x06,0x00,
+0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x20,0x87,0x00,0x25,0x18,0x66,0x00,
+0x24,0x50,0x45,0x01,0x24,0x48,0x25,0x01,0x24,0x18,0x62,0x00,0x24,0x20,0x82,0x00,
+0x82,0x51,0x0a,0x00,0x82,0x49,0x09,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x25,0x20,0x8a,0x00,0x25,0x18,0x69,0x00,0x24,0x60,0x85,0x01,0x24,0x58,0x65,0x01,
+0x24,0x18,0x62,0x00,0x24,0x20,0x82,0x00,0xcc,0x0e,0xcd,0x35,0xc4,0x0e,0xc8,0x35,
+0x00,0x61,0x0c,0x00,0x00,0x59,0x0b,0x00,0x00,0x00,0x07,0x8d,0x25,0x18,0x6b,0x00,
+0x00,0x00,0xa6,0x8d,0x25,0x20,0x8c,0x00,0x10,0x00,0xe3,0xad,0x0c,0x00,0xe4,0xad,
+0x38,0x15,0x83,0x26,0x0c,0x00,0x62,0x8c,0x24,0x30,0xc5,0x00,0x24,0x38,0xe5,0x00,
+0x02,0x3c,0x07,0x00,0x02,0x34,0x06,0x00,0x16,0x00,0xe6,0xa5,0x45,0x05,0x40,0x04,
+0x14,0x00,0xe7,0xa5,0xe0,0x3d,0xc2,0x8e,0xff,0x00,0x04,0x3c,0x24,0x10,0x44,0x00,
+0x05,0x00,0x40,0x10,0x12,0x00,0x02,0x24,0xe0,0x3d,0xc2,0x8e,0x00,0x00,0x00,0x00,
+0x24,0x10,0x44,0x00,0x02,0x14,0x02,0x00,0xc3,0x02,0x62,0xa0,0x10,0x4e,0x00,0x0c,
+0x10,0x00,0xa4,0x27,0x4b,0x4d,0x00,0x0c,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x0c,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00,0x0c,0x00,0x43,0xac,
+0x38,0x15,0x82,0x26,0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xd0,0x3d,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0x4c,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x00,0x01,0x42,0x30,0xd8,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x38,0x15,0x82,0x26,
+0xea,0x02,0x40,0xa0,0xd0,0x3d,0xa2,0x96,0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30,
+0xd9,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e,0xfd,0xff,0x03,0x24,
+0x24,0x10,0x43,0x00,0x38,0x15,0x82,0xae,0x25,0xb0,0x05,0x3c,0x4c,0x00,0xa3,0x34,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x40,0x14,
+0x3f,0xff,0x03,0x24,0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,
+0x38,0x15,0x82,0xae,0x30,0x3b,0xe4,0x8e,0x00,0x80,0x06,0x3c,0xc0,0x31,0xc2,0x24,
+0x18,0x03,0xa3,0x34,0x30,0x3b,0xe6,0x26,0x00,0x00,0x62,0xac,0x11,0x00,0x86,0x10,
+0x02,0x80,0x02,0x3c,0xbf,0x00,0xb2,0x34,0x38,0x15,0x51,0x24,0x21,0x80,0xc0,0x00,
+0x21,0xf0,0x00,0x00,0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,
+0x09,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0xf8,0x25,0x24,0x8e,0x78,0x08,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x30,0x3b,0xe2,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x50,0x14,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x08,0x08,0x44,0x24,0x21,0x28,0x00,0x00,
+0x21,0x30,0x00,0x00,0x1c,0x2c,0x00,0x0c,0x21,0x38,0x00,0x00,0x46,0x0c,0x00,0x08,
+0x38,0x15,0x85,0x26,0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x08,0x00,0x83,0xac,0xd0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x80,0x00,0x42,0x30,0xb6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x85,0x26,
+0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x1f,0x04,0x00,
+0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00,0x25,0x20,0x83,0x00,
+0x2a,0x4a,0x00,0x0c,0xc8,0x02,0xa4,0xac,0xd0,0x3d,0xa3,0x96,0x25,0xb0,0x02,0x3c,
+0x64,0x03,0x42,0x34,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0xb8,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x38,0x15,0x82,0xae,0xd0,0x3d,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0xc2,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,
+0x38,0x15,0x85,0x26,0xc8,0x02,0xa4,0x8c,0xff,0xf0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x02,0x1e,0x04,0x00,0x0f,0x00,0x63,0x30,0x01,0x00,0x63,0x24,0x0f,0x00,0x63,0x30,
+0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,0x25,0x20,0x83,0x00,0x99,0x48,0x00,0x0c,
+0xc8,0x02,0xa4,0xac,0x11,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,0xe0,0x3d,0xc2,0x8e,
+0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xef,0x09,0x43,0x10,0x02,0x80,0x04,0x3c,
+0xe0,0x3d,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xec,0x09,0x43,0x10,
+0x00,0x00,0x00,0x00,0xe0,0x3d,0x82,0x8c,0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,
+0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0xc9,0x48,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x29,0xb0,0x02,0x3c,0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,
+0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34,0x3c,0x00,0x51,0x34,0x04,0x00,0x43,0x34,
+0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34,0x20,0x00,0x4a,0x34,
+0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34,0x30,0x00,0x4e,0x34,
+0x34,0x00,0x4f,0x34,0x38,0x00,0x50,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac,
+0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0xff,0xff,0x04,0x24,0x00,0x00,0xc0,0xac,
+0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,0x38,0x15,0x46,0x24,0x00,0x00,0x00,0xad,
+0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,
+0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,
+0x00,0x00,0x20,0xae,0x21,0x18,0xa6,0x00,0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,
+0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,
+0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,
+0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04,0x94,0x00,0x63,0x24,0xd0,0x3d,0xa3,0x96,
+0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0xf7,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xe5,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x38,0x15,0x82,0x8e,0xd5,0x0c,0x00,0x08,0x24,0x10,0x43,0x00,0x38,0x15,0x84,0x8e,
+0xe8,0x02,0xc5,0x8c,0xfe,0xff,0x02,0x24,0x00,0x90,0x03,0x3c,0x24,0x20,0x82,0x00,
+0x24,0x18,0xa3,0x00,0x00,0x10,0x02,0x3c,0x3d,0xfe,0x62,0x14,0x38,0x15,0x84,0xae,
+0x50,0x0c,0x03,0x35,0xff,0xbf,0x02,0x3c,0x00,0x00,0x64,0x90,0xff,0xff,0x42,0x34,
+0x24,0x10,0xa2,0x00,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,0xe8,0x02,0xc2,0xac,
+0xcc,0x0c,0x00,0x08,0xdb,0x02,0xc4,0xa0,0xff,0xff,0x03,0x24,0x38,0x15,0x42,0x24,
+0xea,0x02,0x43,0xa0,0xd0,0x3d,0xa2,0x96,0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30,
+0x29,0xff,0x43,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e,0x25,0xb0,0x03,0x3c,
+0x77,0x00,0x04,0x24,0x02,0x00,0x42,0x34,0x99,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,
+0x38,0x15,0x82,0xae,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xcf,0x0d,0x00,0x08,
+0x25,0xb0,0x05,0x3c,0x2b,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0xa0,0x00,0x40,0x14,
+0x24,0x00,0x82,0x34,0x36,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0x1f,0x01,0x40,0x14,
+0x30,0x00,0x82,0x34,0x18,0x00,0x82,0x34,0xa1,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xe1,0x01,0x40,0x14,0x21,0x00,0x82,0x34,0x15,0x00,0x82,0x34,0xe7,0xfd,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0x7c,0x02,0x40,0x14,0x16,0x00,0x82,0x34,0x13,0x00,0x82,0x34,
+0xb8,0x06,0xe2,0x10,0x14,0x00,0x82,0x34,0xc6,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0xff,0x00,0x04,0x3c,0x00,0xff,0x82,0x34,0x24,0x10,0x42,0x02,0xdc,0xfd,0x40,0x10,
+0x25,0xb0,0x02,0x3c,0x38,0x15,0x83,0x26,0x00,0xff,0x45,0x32,0x08,0x03,0x66,0x90,
+0x02,0x2a,0x05,0x00,0xfb,0xff,0xa2,0x24,0x24,0x20,0x44,0x02,0x02,0x24,0x04,0x00,
+0x23,0x03,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x00,0x01,0xc6,0x34,0xfb,0xff,0x87,0x24,
+0xc0,0x02,0x42,0x34,0x08,0x03,0x66,0xac,0x21,0x03,0x67,0xa0,0x20,0x03,0x64,0xa0,
+0x22,0x03,0x65,0xa0,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x04,0x3c,0x94,0x0e,0x82,0x34,0x9c,0x0e,0x83,0x34,0xa4,0x0e,0x85,0x34,
+0xac,0x0e,0x86,0x34,0x00,0x00,0x49,0x8c,0x00,0x00,0x6c,0x8c,0xb4,0x0e,0x82,0x34,
+0x00,0x00,0xae,0x8c,0x10,0x00,0xe3,0x8d,0x00,0x00,0xc8,0x8c,0x0c,0x00,0xe5,0x8d,
+0x00,0x00,0x4a,0x8c,0xff,0x3f,0x02,0x3c,0xff,0x03,0x06,0x3c,0xff,0xff,0x42,0x34,
+0x00,0xfc,0x07,0x24,0x24,0x18,0x62,0x00,0x24,0x48,0x26,0x01,0xbc,0x0e,0x82,0x34,
+0x24,0x40,0x06,0x01,0x00,0x00,0x4b,0x8c,0x24,0x18,0x67,0x00,0x24,0x28,0xa7,0x00,
+0x02,0x44,0x08,0x00,0xcc,0x0e,0x8d,0x34,0x02,0x4c,0x09,0x00,0xc4,0x0e,0x84,0x34,
+0xf0,0xff,0x02,0x3c,0x00,0x00,0x87,0x8c,0xff,0x03,0x42,0x34,0x00,0x00,0xa4,0x8d,
+0x25,0x18,0x68,0x00,0x25,0x28,0xa9,0x00,0x24,0x60,0x86,0x01,0x24,0x50,0x46,0x01,
+0xe0,0x3d,0x08,0x8e,0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00,0x82,0x61,0x0c,0x00,
+0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x28,0xac,0x00,
+0x25,0x18,0x6a,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x18,0x62,0x00,
+0x24,0x28,0xa2,0x00,0x24,0x20,0x86,0x00,0x00,0x71,0x0e,0x00,0x00,0x59,0x0b,0x00,
+0x24,0x38,0xe6,0x00,0xff,0xff,0x02,0x3c,0x25,0x28,0xae,0x00,0x25,0x18,0x6b,0x00,
+0x02,0x3c,0x07,0x00,0x02,0x24,0x04,0x00,0x24,0x40,0x02,0x01,0x0c,0x00,0xe5,0xad,
+0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5,0x82,0x00,0x00,0x11,0x16,0x00,0xe4,0xa5,
+0xe0,0x3d,0x03,0x8e,0xe0,0x3d,0x02,0x8e,0x02,0x1c,0x03,0x00,0x24,0x10,0x51,0x00,
+0x02,0x16,0x02,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,0x10,0x4e,0x00,0x0c,
+0x10,0x00,0xa4,0x27,0xd0,0x3d,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,
+0xbf,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0xa9,0x0d,0x00,0x08,0x38,0x15,0x82,0x26,0x01,0x00,0x22,0x35,0xc8,0x03,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0xb7,0x00,0x40,0x14,0x05,0x00,0x82,0x34,0x00,0xf9,0x03,0x3c,
+0x03,0x00,0x62,0x34,0x28,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0x25,0x01,0x40,0x14,
+0x06,0x00,0x62,0x34,0xbd,0x04,0xe3,0x10,0x2b,0x10,0x67,0x00,0x42,0x02,0x40,0x14,
+0x01,0x00,0x62,0x34,0x20,0x00,0xc2,0x34,0xdc,0x04,0xe2,0x10,0x21,0x00,0xc2,0x34,
+0x44,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x10,0x0b,0x43,0x8c,
+0x00,0x04,0x04,0x3c,0x25,0x18,0x64,0x00,0x10,0x0b,0x43,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x00,0xff,0x05,0x3c,0xb4,0x03,0xe5,0x10,0x2b,0x10,0xa7,0x00,0x4d,0x00,0x40,0x14,
+0x0f,0x00,0xa2,0x34,0xaf,0x00,0x82,0x34,0x33,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xc2,0x00,0x40,0x14,0xaa,0x00,0x82,0x34,0xbd,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x87,0x01,0x40,0x14,0xab,0x00,0x82,0x34,0xa6,0x00,0x82,0x34,0xca,0x04,0xe2,0x10,
+0xa7,0x00,0x82,0x34,0x27,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x00,0xff,0x42,0x32,
+0x02,0x9a,0x02,0x00,0x02,0x1c,0x12,0x00,0x01,0x00,0x02,0x24,0xaa,0x08,0x62,0x12,
+0xff,0x00,0x67,0x30,0x02,0x00,0x02,0x24,0x97,0x08,0x62,0x12,0x03,0x00,0x02,0x24,
+0x84,0x08,0x62,0x12,0x04,0x00,0x02,0x24,0x72,0x08,0x62,0x12,0x08,0x00,0x02,0x24,
+0x5f,0x08,0x62,0x12,0x09,0x00,0x02,0x24,0x4c,0x08,0x62,0x12,0x0a,0x00,0x02,0x24,
+0x39,0x08,0x62,0x12,0x0b,0x00,0x02,0x24,0x26,0x08,0x62,0x12,0x0c,0x00,0x02,0x24,
+0xce,0x07,0x62,0x12,0x0d,0x00,0x02,0x24,0xbb,0x07,0x62,0x12,0x0e,0x00,0x02,0x24,
+0xa8,0x07,0x62,0x12,0x0f,0x00,0x02,0x24,0x95,0x07,0x62,0x12,0x10,0x00,0x02,0x24,
+0x23,0xfd,0x62,0x16,0x25,0xb0,0x02,0x3c,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x64,0x11,0x44,0x94,0x60,0x11,0x45,0x94,0x25,0xb0,0x06,0x3c,
+0x00,0x24,0x04,0x00,0xc4,0x02,0xc3,0x34,0x21,0x28,0xa4,0x00,0x00,0x00,0x65,0xac,
+0x70,0x11,0x47,0x8c,0x6c,0x11,0x43,0x8c,0x68,0x11,0x44,0x94,0x25,0xb0,0x02,0x3c,
+0x21,0x18,0x67,0x00,0x00,0x1c,0x03,0x00,0xc8,0x02,0xc6,0x34,0x21,0x20,0x83,0x00,
+0xc0,0x02,0x42,0x34,0x00,0x00,0xc4,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1,0x27,0x0f,0x00,0x08,
+0xc3,0x02,0xe2,0xa1,0x6b,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xaa,0x00,0x40,0x14,
+0x21,0x00,0xa2,0x34,0x0c,0x00,0xa2,0x34,0x5e,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x56,0x02,0x40,0x14,0x0d,0x00,0xa2,0x34,0x01,0x00,0xa2,0x34,0xac,0x06,0xe2,0x10,
+0x07,0x00,0xa2,0x34,0xdb,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x43,0x47,0x00,0x0c,
+0x07,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x6c,0x03,0xe2,0x10,0x00,0xf8,0x05,0x3c,
+0x2b,0x10,0x47,0x00,0xba,0x00,0x40,0x14,0x14,0x00,0xc2,0x34,0x00,0xf2,0x03,0x3c,
+0x2a,0x04,0xe3,0x10,0x2b,0x10,0x67,0x00,0xe2,0x01,0x40,0x14,0x01,0x00,0x62,0x34,
+0x03,0x00,0x82,0x34,0x80,0x05,0xe2,0x10,0x04,0x00,0x82,0x34,0xc5,0xfc,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x02,0x14,0x12,0x00,0xff,0x00,0x53,0x30,0x00,0xff,0x43,0x32,
+0x07,0x00,0x62,0x2e,0xd9,0xfc,0x40,0x10,0x02,0xf2,0x03,0x00,0x02,0x80,0x04,0x3c,
+0xec,0x82,0x83,0x24,0x80,0x10,0x13,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x44,0x03,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0xd8,0x00,0x40,0x14,0xa1,0x00,0x82,0x34,0x28,0x00,0x82,0x34,
+0x45,0x05,0xe2,0x10,0x2b,0x10,0x47,0x00,0x2f,0x02,0x40,0x14,0x29,0x00,0x82,0x34,
+0x25,0x00,0x82,0x34,0x5c,0x05,0xe2,0x10,0x26,0x00,0x82,0x34,0xa9,0xfc,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x73,0x30,0x08,0x00,0x64,0x36,0x00,0x00,0x44,0xa0,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x4b,0x00,0x40,0x14,0x09,0x00,0x82,0x34,
+0x03,0x00,0x82,0x34,0x2b,0x10,0xe2,0x00,0xb1,0xfc,0x40,0x10,0x25,0xb0,0x02,0x3c,
+0x75,0x03,0xe4,0x10,0x2b,0x10,0x87,0x00,0x71,0x02,0x40,0x14,0x01,0x00,0x82,0x34,
+0x02,0x00,0x22,0x35,0x6d,0x05,0xe2,0x10,0x03,0x00,0x22,0x35,0x8d,0xfc,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x38,0x15,0x83,0x26,0x04,0x24,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x34,0x04,0x24,0x62,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x89,0x03,0xa2,0x10,
+0x2b,0x10,0x45,0x00,0xcb,0x00,0x40,0x14,0x00,0xa0,0x02,0x3c,0x00,0x60,0x02,0x3c,
+0x04,0x00,0xa2,0x10,0x80,0x10,0x04,0x00,0x95,0xfc,0xa8,0x14,0x25,0xb0,0x02,0x3c,
+0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,
+0x21,0x10,0x4a,0x00,0xc5,0x03,0x49,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xfe,0x04,0x3c,
+0x12,0x00,0x82,0x34,0x7b,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xd5,0x00,0x40,0x14,
+0x19,0x00,0x82,0x34,0x10,0x00,0x82,0x34,0x2a,0x05,0xe2,0x10,0x11,0x00,0x82,0x34,
+0x64,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x38,0x15,0x83,0x26,0x21,0x20,0xc0,0x03,
+0xe0,0x24,0x00,0x0c,0x82,0x0b,0x60,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x77,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xd0,0x00,0x40,0x14,0x10,0x00,0x82,0x34,0x07,0x00,0x82,0x34,0x00,0x04,0xe2,0x10,
+0x08,0x00,0x82,0x34,0x47,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0x64,0x03,0x63,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0xfd,0x00,0x42,0x30,
+0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x71,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x3f,0x01,0x40,0x14,0x30,0x00,0xa2,0x34,0x10,0x00,0xa2,0x34,0xf3,0x03,0xe2,0x10,
+0x20,0x00,0xa2,0x34,0x33,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x02,0x80,0x04,0x3c,
+0x84,0x3e,0x83,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x68,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xc7,0x01,0x40,0x14,
+0x20,0x00,0x62,0x34,0x04,0x00,0x62,0x34,0xea,0x03,0xe2,0x10,0x05,0x00,0x62,0x34,
+0x20,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x5c,0x24,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xf9,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xda,0x00,0x40,0x14,0x16,0x00,0xa2,0x34,
+0x12,0x00,0xc2,0x34,0xe1,0x03,0xe2,0x10,0x13,0x00,0xc2,0x34,0x0d,0xfc,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x28,0xb0,0x13,0x3c,0x00,0x00,0x62,0x96,0x02,0x1c,0x12,0x00,
+0xff,0x00,0x64,0x30,0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0x0c,0x00,0x83,0x10,
+0xff,0x7f,0x03,0x3c,0x08,0x00,0x73,0x26,0x00,0x00,0x62,0x96,0x00,0x00,0x00,0x00,
+0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0x04,0x00,0x83,0x10,0xff,0xff,0x62,0x32,
+0x00,0x08,0x42,0x2c,0xf7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0x7f,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x24,0x18,0x63,0x02,
+0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x39,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0x7d,0x01,0x40,0x14,0x22,0x00,0x82,0x34,0x19,0x00,0x82,0x34,0x20,0x04,0xe2,0x10,
+0x20,0x00,0x82,0x34,0xe7,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x84,0x26,
+0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x08,0x00,0x83,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xfb,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,
+0xbf,0x00,0x40,0x14,0xa3,0x00,0x82,0x34,0x31,0x00,0x82,0x34,0x00,0x04,0xe2,0x10,
+0xa0,0x00,0x82,0x34,0x8a,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xe4,0x03,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0x07,0x01,0x40,0x14,0x00,0xf1,0x02,0x3c,0x03,0x00,0x82,0x34,
+0xc4,0x03,0xe2,0x10,0x08,0x00,0x82,0x34,0xca,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x00,0xff,0x42,0x32,0x02,0x92,0x02,0x00,0xc2,0x06,0x40,0x12,0x01,0x00,0x02,0x24,
+0x61,0x07,0x42,0x12,0x00,0x00,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xbf,0x01,0xa2,0x10,0x00,0x40,0x02,0x3c,0x40,0xff,0xa2,0x10,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x39,0x03,0xa2,0x10,0x2b,0x10,0x45,0x00,0x6f,0x01,0x40,0x14,
+0x00,0xb0,0x02,0x3c,0x00,0x90,0x02,0x3c,0xc9,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x38,0x15,0x82,0x26,0x21,0x10,0x82,0x00,0x77,0x04,0x49,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xaf,0x04,0xe2,0x10,0xae,0x00,0x82,0x34,0xa2,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x00,0xff,0x45,0x32,0x02,0x24,0x12,0x00,0xff,0x00,0x84,0x30,0x4b,0x48,0x00,0x0c,
+0x02,0x2a,0x05,0x00,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xa0,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xfd,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0x5a,0x01,0x40,0x14,
+0x1a,0x00,0x82,0x34,0x18,0x00,0x82,0x34,0x8e,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x38,0x15,0x82,0x26,0x83,0x0b,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xae,0x04,0xe2,0x10,0x11,0x00,0x82,0x34,0x79,0xfb,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x02,0x1c,0x12,0x00,0x1f,0x00,0x67,0x30,0xc0,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x25,0xb0,0x04,0x3c,0x21,0x10,0x47,0x00,
+0x02,0x80,0x03,0x3c,0xc8,0x02,0x85,0x34,0x38,0x15,0x63,0x24,0xc4,0x02,0x84,0x34,
+0x80,0x10,0x02,0x00,0x00,0x00,0x93,0x8c,0x21,0x48,0x43,0x00,0x00,0x00,0xa8,0x8c,
+0x21,0x58,0x80,0x00,0x21,0x28,0x00,0x00,0xff,0x00,0x0a,0x24,0x29,0xb0,0x06,0x3c,
+0x21,0x20,0xa3,0x00,0xf0,0x04,0x82,0x90,0x00,0x00,0x00,0x00,0x39,0x07,0x4a,0x10,
+0x00,0x00,0x00,0x00,0x37,0x07,0x47,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x24,
+0x08,0x00,0xa2,0x28,0xf6,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,0x08,0x00,0x02,0x24,
+0x73,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0xff,0xff,0x03,0x24,
+0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xd0,0x04,0xe2,0x10,0x17,0x00,0x82,0x34,
+0x4c,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x04,0x3c,0x68,0x03,0x85,0x34,
+0x00,0x00,0xa3,0x8c,0x00,0xff,0x42,0x32,0x00,0x12,0x02,0x00,0xff,0xff,0x73,0x30,
+0x25,0x10,0x53,0x00,0x00,0x00,0xa2,0xac,0x64,0x03,0x84,0x34,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x53,0x30,0x25,0xb0,0x02,0x3c,0x40,0x00,0x63,0x36,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xb2,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0x61,0x04,0x40,0x14,
+0x00,0x00,0x00,0x00,0x2e,0x19,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x49,0x04,0xe4,0x10,0x01,0x00,0x82,0x34,0x2a,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,0xc4,0x02,0x44,0x34,0x00,0xff,0x63,0x34,
+0x00,0x00,0x93,0x8c,0x24,0x18,0x43,0x02,0x02,0x92,0x03,0x00,0x21,0x10,0x42,0x02,
+0x00,0x00,0x53,0xac,0x00,0x00,0x53,0x8c,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x93,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x01,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0x13,0x01,0x40,0x14,0xff,0xff,0x02,0x34,
+0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,0xc4,0x02,0x42,0x34,0x00,0xff,0x63,0x34,
+0x00,0x00,0x45,0x8c,0x24,0x18,0x43,0x02,0x02,0xf2,0x03,0x00,0xd5,0x49,0x00,0x0c,
+0x21,0x20,0xc0,0x03,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x47,0x05,0xe2,0x10,0x02,0x00,0x62,0x34,
+0x04,0xfb,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x68,0x24,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xce,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00,0xa8,0x00,0x40,0x14,0x31,0x00,0xa2,0x34,
+0x22,0x00,0xa2,0x34,0xf3,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x02,0x80,0x02,0x3c,
+0x9c,0x3e,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xec,0x04,0xe2,0x10,0x10,0x00,0xa2,0x34,0xe5,0xfa,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x21,0x98,0x00,0x00,0xaf,0x11,0x00,0x08,0x27,0xb0,0x04,0x3c,
+0x00,0x01,0x62,0x2e,0x0c,0x00,0x40,0x10,0x08,0x00,0x84,0x24,0x00,0x00,0x83,0x94,
+0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0x30,0xff,0x00,0xc2,0x33,0xf0,0x00,0x42,0x28,
+0xf7,0xff,0x40,0x14,0x01,0x00,0x73,0x26,0xff,0xff,0x73,0x26,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x5e,0xa4,0xff,0x00,0x62,0x2e,0xec,0xfa,0x40,0x14,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x12,0x87,0x03,0x3c,0x00,0x00,0x43,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xe0,0x04,0xe2,0x10,0x01,0x00,0x42,0x34,0xc5,0xfa,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x00,0xff,0x42,0x32,0x02,0xf2,0x02,0x00,0x0c,0x05,0xc0,0x13,
+0x25,0xb0,0x05,0x3c,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94,0xb0,0x03,0xa6,0x34,
+0xff,0xff,0xca,0x27,0xff,0xff,0x73,0x30,0x1b,0x00,0x7e,0x02,0x02,0x00,0xc0,0x17,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xd3,0xac,0x38,0x15,0x88,0x26,
+0x01,0x00,0x02,0x24,0xef,0x0a,0x02,0xa1,0x80,0xff,0x02,0x24,0x4f,0x00,0xab,0x34,
+0x9e,0x00,0xac,0x34,0xf2,0x0a,0x09,0x95,0x44,0x00,0xa7,0x34,0xd8,0x00,0xa5,0x34,
+0x12,0x98,0x00,0x00,0x80,0x22,0x13,0x00,0x00,0xf8,0x84,0x24,0x18,0x00,0xd3,0x03,
+0xff,0xff,0x5e,0x31,0x00,0x19,0x1e,0x00,0x25,0x18,0x62,0x00,0x26,0xb0,0x02,0x3c,
+0x00,0x00,0xde,0xac,0x7c,0x00,0x42,0x34,0x00,0x00,0x63,0xa1,0x00,0x00,0xd3,0xac,
+0x00,0x00,0x93,0xa5,0x42,0x99,0x04,0x00,0x00,0x00,0xd3,0xac,0x00,0x00,0x53,0xa4,
+0x00,0x00,0xe3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0xe3,0xa4,
+0x00,0x00,0xe4,0x94,0x12,0x68,0x00,0x00,0x23,0x48,0x2d,0x01,0x00,0x02,0x84,0x34,
+0xf4,0x0a,0x09,0xa5,0x00,0x00,0xe4,0xa4,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
+0x40,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x86,0x04,0xe2,0x10,
+0x0e,0x00,0xa2,0x34,0x87,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,
+0x52,0x24,0x40,0xa4,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x5e,0x04,0xe2,0x10,0x2a,0x00,0x82,0x34,
+0x7c,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x65,0x03,0x42,0x34,
+0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x73,0x30,0x02,0x00,0x64,0x36,
+0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x1d,0x04,0xe2,0x10,0x23,0x00,0x82,0x34,
+0x6c,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x85,0x26,0xd8,0x02,0xa3,0x8c,
+0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x10,0x00,0x04,0x3c,
+0x25,0xb0,0x02,0x3c,0x25,0x18,0x64,0x00,0xc0,0x02,0x42,0x34,0xd8,0x02,0xa3,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x18,0x04,0xe2,0x10,
+0x2b,0x10,0x47,0x00,0x4a,0x00,0x40,0x14,0x07,0x00,0x62,0x34,0x59,0xfa,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x54,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x4d,0xfa,0xe2,0x14,
+0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x54,0x25,0x44,0x8c,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x5c,0xfa,0xa2,0x14,
+0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,
+0x6c,0x05,0x47,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x36,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,
+0x01,0x00,0x03,0x24,0x12,0x05,0xc3,0x13,0x02,0x00,0xc2,0x2b,0x05,0x05,0x40,0x14,
+0x03,0x00,0x02,0x24,0xfa,0x04,0xc2,0x13,0x38,0x15,0x82,0x26,0x7c,0x0b,0x44,0x94,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xc4,0x03,0xe2,0x10,0x02,0x00,0x82,0x34,0x1e,0xfa,0xe2,0x14,0x00,0xf0,0x02,0x3c,
+0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x73,0x30,0x05,0x00,0x64,0x36,0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x10,0xfa,0xe9,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x85,0x26,0x04,0x24,0xa2,0x8c,
+0xfd,0xff,0x03,0x24,0xfe,0xff,0x04,0x24,0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,
+0x04,0x24,0xa2,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x83,0x26,0xec,0x25,0x62,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x38,0x15,0x83,0x26,
+0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0x38,0x03,0x49,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x24,0x10,0x43,0x02,0x02,0x3c,0x02,0x00,0xc0,0x18,0x07,0x00,0x21,0x18,0x67,0x00,
+0x80,0x18,0x03,0x00,0x00,0xff,0x42,0x32,0x21,0x18,0x67,0x00,0x02,0x99,0x02,0x00,
+0x80,0x18,0x03,0x00,0x25,0xb0,0x02,0x3c,0x21,0x18,0x65,0x00,0xc0,0x02,0x42,0x34,
+0x80,0x11,0x73,0xac,0x84,0x11,0x73,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xdb,0x02,0xe3,0x90,0x50,0x0c,0x02,0x35,0x21,0x28,0x00,0x00,
+0x00,0x00,0x43,0xa0,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,0x38,0x15,0x82,0x26,0xdb,0x02,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x85,0x26,0xe8,0x02,0xa3,0x8c,0x00,0x40,0x04,0x3c,
+0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0xcc,0x0c,0x00,0x08,0xe8,0x02,0xa3,0xac,0x27,0x0d,0x00,0x08,0x01,0x00,0x04,0x24,
+0xfd,0x0c,0x00,0x08,0x01,0x00,0x04,0x24,0xfd,0x0c,0x00,0x08,0x02,0x00,0x04,0x24,
+0x27,0x0d,0x00,0x08,0x02,0x00,0x04,0x24,0x2a,0x4a,0x00,0x0c,0x10,0x00,0xeb,0xad,
+0x38,0x15,0x83,0x26,0x0c,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0xbd,0xfa,0x41,0x04,
+0x00,0x00,0x00,0x00,0x10,0x4e,0x00,0x0c,0x10,0x00,0xa4,0x27,0xa9,0x0d,0x00,0x08,
+0x38,0x15,0x82,0x26,0x24,0x20,0x43,0x02,0x0f,0x4a,0x00,0x0c,0x02,0x24,0x04,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xc1,0x19,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x12,0x01,0x02,0x3c,0x13,0x13,0x42,0x34,0x0c,0x09,0x04,0x35,0xd8,0x02,0xa3,0xac,
+0x00,0x00,0x82,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x04,0x24,0xa2,0x8c,0xfd,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x01,0x00,0x42,0x34,
+0x04,0x24,0xa2,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x43,0x47,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x56,0x01,0x02,0x35,0xff,0x00,0x03,0x24,0x00,0x00,0x43,0xa4,
+0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0xc0,0x3d,0x44,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x64,0x03,0x02,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x73,0x30,
+0x10,0x00,0x64,0x36,0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x48,0x32,
+0x02,0x22,0x08,0x00,0x21,0x98,0x00,0x00,0x2f,0x13,0x00,0x08,0x27,0xb0,0x07,0x3c,
+0x00,0x01,0x62,0x2e,0x0b,0x00,0x40,0x10,0x08,0x00,0xe7,0x24,0x00,0x00,0xe2,0x94,
+0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0xf8,0xff,0x64,0x14,
+0x01,0x00,0x73,0x26,0xff,0xff,0x73,0x26,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x53,0xa4,0xff,0x00,0x62,0x2e,0x6d,0xf9,0x40,0x14,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x12,0x87,0x03,0x3c,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x24,0x10,0x43,0x02,0x02,0xf4,0x02,0x00,0x00,0xff,0x43,0x32,0x04,0x00,0xc0,0x13,
+0x02,0x92,0x03,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,
+0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x0c,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,
+0x95,0x44,0x00,0x0c,0x21,0x20,0x40,0x02,0xff,0xff,0x10,0x36,0x24,0x98,0x50,0x00,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x53,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x08,0x00,0xa3,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x08,0x00,0xa3,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x64,0x24,0xa3,0x90,0xc4,0x02,0x02,0x35,
+0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x48,0x32,0x02,0x1a,0x08,0x00,
+0xff,0x00,0x02,0x24,0x2d,0x02,0x62,0x10,0x25,0xb0,0x05,0x3c,0x0e,0x00,0x60,0x14,
+0x00,0xcc,0x02,0x34,0x25,0xb0,0x04,0x3c,0x64,0x03,0x84,0x34,0x38,0x15,0x87,0x26,
+0x00,0x00,0x85,0x94,0xe8,0x02,0xe6,0x8c,0xff,0xef,0x02,0x3c,0xff,0xfe,0x03,0x24,
+0xff,0xff,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x30,0xc2,0x00,0x00,0x00,0x85,0xa4,
+0xe8,0x02,0xe6,0xac,0x00,0xcc,0x02,0x34,0x25,0xf9,0x02,0x15,0x25,0xb0,0x02,0x3c,
+0x38,0x15,0x82,0x26,0xe8,0x02,0x43,0x8c,0x00,0x10,0x04,0x3c,0x25,0x18,0x64,0x00,
+0xe8,0x02,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x99,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x21,0x10,0x82,0x00,0x5a,0x04,0x49,0xa0,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x00,0xff,0x62,0x34,0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,
+0x38,0x15,0x83,0x26,0x83,0x0b,0x7e,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x24,0x12,0x00,0xff,0x1b,0x00,0x0c,
+0xff,0x00,0x84,0x30,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,
+0x00,0x00,0x44,0x90,0x38,0x15,0x85,0x26,0x08,0x03,0xa6,0x90,0xff,0x00,0x93,0x30,
+0x02,0x00,0x63,0x36,0x08,0x03,0xa6,0xac,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x02,0x80,0x06,0x3c,0x98,0x3e,0xc3,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x58,0x24,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x38,0x15,0x84,0x26,0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x20,0x02,0x3c,0x25,0x18,0x62,0x00,0x02,0x34,0x12,0x00,
+0x00,0x1f,0x45,0x32,0x25,0xb0,0x02,0x3c,0x02,0x9a,0x05,0x00,0x3f,0x00,0xc8,0x30,
+0xc0,0x02,0x42,0x34,0xc1,0x02,0x88,0xa0,0x08,0x00,0x83,0xac,0xbc,0x02,0x93,0xa0,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,
+0xc4,0x02,0xa3,0x34,0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x90,0x82,0x00,0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0xb4,0xf8,0x60,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0xb0,0x02,0x3c,0x25,0x90,0x42,0x02,0x00,0x00,0x53,0x8e,
+0xc8,0x02,0xa2,0x34,0x00,0x00,0x53,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x70,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x50,0x24,0x44,0x94,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xa4,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x04,0x00,
+0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0xf8,0x04,0x47,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x03,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x84,0x26,
+0x10,0x0b,0x83,0x8c,0xff,0xfb,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x10,0x0b,0x83,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x11,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,0x26,0x04,0x83,0x10,
+0x02,0x00,0x02,0x24,0x1d,0x04,0x82,0x10,0x03,0x00,0x02,0x24,0x3e,0x03,0x82,0x10,
+0x00,0x00,0x00,0x00,0xc9,0x48,0x00,0x0c,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xcc,0x50,0x00,0x0c,0x21,0x20,0x40,0x02,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x43,0x32,
+0x00,0xff,0x02,0x34,0x33,0x03,0x62,0x10,0x38,0x15,0x82,0x26,0xec,0x25,0x40,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x60,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x28,0xb0,0x02,0x3c,
+0x00,0x00,0x43,0x90,0xff,0x00,0x02,0x24,0xff,0x00,0x72,0x30,0x43,0xf8,0x42,0x12,
+0x28,0xb0,0x05,0x3c,0xff,0x00,0x04,0x24,0xc0,0x10,0x12,0x00,0x21,0x10,0x45,0x00,
+0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x72,0x30,0xfb,0xff,0x44,0x16,
+0xc0,0x10,0x12,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xfa,0x18,0x00,0x0c,0xfd,0x00,0x04,0x24,
+0x25,0xb0,0x04,0x3c,0x00,0x1c,0x02,0x3c,0xa0,0x00,0x85,0x34,0x00,0x1c,0x42,0x34,
+0x00,0x00,0xa2,0xac,0x00,0xe0,0x02,0x3c,0xa8,0x00,0x86,0x34,0x00,0xbe,0x42,0x34,
+0xa4,0x00,0x84,0x34,0x00,0x04,0x03,0x24,0x00,0x00,0x83,0xac,0x00,0x00,0xc2,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x14,0x12,0x00,0x00,0xff,0x43,0x32,0xff,0x00,0x5e,0x30,
+0x04,0x00,0xc0,0x13,0x02,0x92,0x03,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,
+0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x25,0xb0,0x10,0x3c,0x2a,0x42,0x00,0x0c,
+0xc4,0x02,0x10,0x36,0x00,0x00,0x13,0x8e,0x0f,0x00,0x11,0x3c,0x21,0x20,0x40,0x02,
+0x21,0x30,0x60,0x02,0x6a,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x20,0x40,0x02,
+0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x00,0x00,0x02,0xae,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x38,0x15,0x85,0x26,0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00,
+0x25,0x20,0x83,0x00,0xc8,0x02,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x2a,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x73,0x30,0x20,0x00,0x64,0x36,0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0xc0,0x02,0x62,0x34,0x00,0x00,0x40,0xac,0x94,0x0e,0x64,0x34,
+0x9c,0x0e,0x62,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x00,0x00,0x89,0x8c,
+0x38,0x15,0x8f,0x26,0x00,0x00,0x4b,0x8c,0x00,0x00,0xac,0x8c,0x00,0x00,0xc4,0x8c,
+0xb4,0x0e,0x62,0x34,0x0c,0x00,0xe5,0x8d,0x10,0x00,0xe6,0x8d,0x00,0x00,0x4a,0x8c,
+0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,0x24,0x48,0x27,0x01,
+0x24,0x20,0x87,0x00,0x00,0x00,0x4d,0x8c,0x24,0x30,0xc8,0x00,0x02,0x4c,0x09,0x00,
+0x24,0x28,0xa8,0x00,0x02,0x24,0x04,0x00,0xcc,0x0e,0x68,0x34,0xf0,0xff,0x02,0x3c,
+0xc4,0x0e,0x63,0x34,0xff,0x03,0x42,0x34,0x25,0x28,0xa9,0x00,0x25,0x30,0xc4,0x00,
+0x00,0x00,0x69,0x8c,0x08,0x00,0xe4,0x8d,0x00,0x00,0x0e,0x8d,0x24,0x58,0x67,0x01,
+0x24,0x50,0x47,0x01,0x24,0x30,0xc2,0x00,0x24,0x28,0xa2,0x00,0x82,0x59,0x0b,0x00,
+0x82,0x51,0x0a,0x00,0x0f,0xc0,0x03,0x3c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x63,0x34,
+0xff,0xff,0x42,0x34,0x25,0x28,0xab,0x00,0x25,0x30,0xca,0x00,0x24,0x60,0x87,0x01,
+0x24,0x68,0xa7,0x01,0xff,0x00,0x08,0x3c,0x24,0x20,0x82,0x00,0x24,0x30,0xc3,0x00,
+0x24,0x28,0xa3,0x00,0x24,0x70,0xc7,0x01,0x00,0x61,0x0c,0x00,0x00,0x69,0x0d,0x00,
+0x24,0x48,0x27,0x01,0x00,0xff,0x03,0x35,0x00,0x20,0x02,0x3c,0x25,0x20,0x82,0x00,
+0x25,0x28,0xac,0x00,0x25,0x30,0xcd,0x00,0x02,0x4c,0x09,0x00,0x02,0x74,0x0e,0x00,
+0x24,0x18,0x43,0x02,0x08,0x00,0xe4,0xad,0x0c,0x00,0xe5,0xad,0x10,0x00,0xe6,0xad,
+0x14,0x00,0xe9,0xa5,0x43,0x00,0x60,0x10,0x16,0x00,0xee,0xa5,0x24,0x10,0x48,0x02,
+0x02,0x14,0x02,0x00,0x02,0x1a,0x12,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,
+0x38,0x15,0x82,0x26,0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x10,0x4e,0x00,0x0c,
+0x10,0x00,0xa4,0x27,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,
+0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xab,0x18,0x00,0x0c,
+0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,
+0x1f,0x00,0x53,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x53,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x02,0x1a,0x12,0x00,
+0x02,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xa7,0x09,0x00,0x0c,0x21,0x20,0xc0,0x03,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1,0x10,0x15,0x00,0x08,
+0xc3,0x02,0xe2,0xa1,0x38,0x15,0x83,0x26,0x82,0x0b,0x62,0x90,0x00,0x00,0x00,0x00,
+0x53,0xf7,0x40,0x14,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x02,0x24,0x21,0x20,0xc0,0x03,
+0x82,0x0b,0x62,0xa0,0xe0,0x24,0x00,0x0c,0x83,0x0b,0x7e,0xa0,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x04,0x24,0x43,0x8c,0xfe,0xff,0x04,0x24,0x02,0x00,0x63,0x34,0x24,0x18,0x64,0x00,
+0x04,0x24,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0xec,0x25,0x40,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x1c,0x12,0x00,0x1f,0x00,0x67,0x30,0xc0,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,
+0x38,0x15,0x84,0x26,0x21,0x30,0x44,0x00,0x90,0x11,0xc3,0x90,0x0f,0x00,0x02,0x24,
+0x02,0x29,0x03,0x00,0x05,0x00,0xa2,0x10,0x21,0x18,0xa4,0x00,0xf0,0x04,0x62,0x90,
+0x00,0x00,0x00,0x00,0x02,0x02,0x47,0x10,0xff,0xff,0x02,0x24,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0xff,0xff,0x03,0x24,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xe9,0x51,0x00,0x0c,0x21,0x20,0x40,0x02,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x64,0x03,0xa5,0x34,
+0x38,0x15,0x86,0x26,0x00,0x00,0xa3,0x94,0xe8,0x02,0xc4,0x8c,0xff,0xef,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x00,0x01,0x63,0x34,0x00,0x00,0xa3,0xa4,
+0x81,0x13,0x00,0x08,0xe8,0x02,0xc4,0xac,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x42,0x02,0x25,0xb0,0x03,0x3c,0x02,0x92,0x02,0x00,0x21,0x10,0x43,0x02,
+0x00,0x00,0x53,0x8c,0xc4,0x02,0x63,0x34,0x00,0x00,0x73,0xac,0x00,0x00,0x53,0x8c,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xf4,0x19,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x29,0xb0,0x02,0x3c,0x00,0x00,0x40,0xac,0x04,0x00,0x44,0x34,0x08,0x00,0x45,0x34,
+0x0c,0x00,0x46,0x34,0x3c,0x00,0x43,0x34,0x10,0x00,0x47,0x34,0x14,0x00,0x48,0x34,
+0x18,0x00,0x49,0x34,0x1c,0x00,0x4a,0x34,0x20,0x00,0x4b,0x34,0x24,0x00,0x4c,0x34,
+0x28,0x00,0x4d,0x34,0x2c,0x00,0x4e,0x34,0x30,0x00,0x4f,0x34,0x34,0x00,0x50,0x34,
+0x38,0x00,0x51,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,
+0x38,0x15,0x44,0x24,0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,
+0xff,0xff,0x06,0x24,0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,
+0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,
+0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x00,0x00,0x60,0xac,
+0x21,0x18,0xa4,0x00,0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,
+0xf0,0x04,0x66,0xa0,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,0x1f,0x00,0x05,0x24,
+0x90,0x11,0x62,0x8c,0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,
+0xfb,0xff,0xa1,0x04,0x94,0x00,0x63,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x82,0x26,
+0x82,0x0b,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x68,0x19,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x14,0x12,0x00,
+0x1f,0x00,0x47,0x30,0xc0,0x18,0x07,0x00,0x21,0x18,0x67,0x00,0x00,0x0f,0x44,0x32,
+0x80,0x18,0x03,0x00,0x02,0x4a,0x04,0x00,0x25,0xb0,0x02,0x3c,0x38,0x15,0x84,0x26,
+0x21,0x18,0x67,0x00,0xc8,0x02,0x46,0x34,0x21,0x28,0x24,0x01,0xc4,0x02,0x42,0x34,
+0x80,0x18,0x03,0x00,0x00,0x00,0x53,0x8c,0x21,0x18,0x64,0x00,0x00,0x00,0xc8,0x8c,
+0xf0,0x04,0xa7,0xa0,0x90,0x11,0x64,0x8c,0x0f,0xff,0x02,0x24,0xc0,0x28,0x09,0x00,
+0x24,0x20,0x82,0x00,0x29,0xb0,0x02,0x3c,0x21,0x28,0xa2,0x00,0x00,0x31,0x09,0x00,
+0x25,0xb0,0x02,0x3c,0x25,0x20,0x86,0x00,0xc0,0x02,0x42,0x34,0x90,0x11,0x64,0xac,
+0x00,0x00,0xb3,0xac,0x04,0x00,0xa8,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x64,0x03,0x63,0x34,0x00,0x00,0x62,0x90,
+0x00,0x00,0x00,0x00,0xfa,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x02,0x14,0x12,0x00,0x00,0x1f,0x43,0x32,0x3f,0x00,0x48,0x30,0x25,0xb0,0x02,0x3c,
+0x02,0x9a,0x03,0x00,0xc0,0x02,0x42,0x34,0x38,0x15,0x83,0x26,0xc1,0x02,0x68,0xa0,
+0xbc,0x02,0x73,0xa0,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,
+0x07,0x00,0x03,0x24,0xc0,0x00,0xc3,0x13,0x08,0x00,0xc2,0x2b,0xb2,0x00,0x40,0x10,
+0x20,0x00,0x02,0x24,0x56,0xf6,0xc0,0x17,0x25,0xb0,0x02,0x3c,0x02,0x80,0x04,0x3c,
+0x90,0x3d,0x83,0x94,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x43,0x47,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x59,0x25,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x1c,0x12,0x00,0x00,0x1f,0x42,0x32,0x38,0x15,0x90,0x26,
+0x02,0x9a,0x02,0x00,0x3f,0x00,0x68,0x30,0xc1,0x02,0x08,0xa2,0xbc,0x02,0x13,0xa2,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x65,0x21,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x98,0x40,0x00,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x53,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x03,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0x03,0x00,0x02,0xa2,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x38,0x15,0x83,0x26,
+0x52,0x24,0x62,0xa4,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,0xc4,0x02,0xa3,0x34,
+0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x90,0x82,0x00,
+0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0x0d,0xf6,0x60,0x10,0x25,0xb0,0x02,0x3c,
+0xc8,0x02,0xa2,0x34,0x00,0x00,0x53,0x8c,0x00,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x25,0x90,0x43,0x02,0xc0,0x02,0x42,0x34,0x00,0x00,0x53,0xae,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x05,0x3c,0x00,0xff,0xa5,0x34,
+0x24,0x28,0x45,0x02,0x25,0xb0,0x04,0x3c,0x02,0x2a,0x05,0x00,0x94,0x00,0x83,0x34,
+0x40,0x11,0x05,0x00,0x26,0xb0,0x06,0x3c,0x00,0x00,0x65,0xa4,0xc0,0xff,0x53,0x24,
+0x7c,0x00,0xcc,0x34,0x04,0x00,0x07,0x24,0x9a,0x00,0x88,0x34,0x98,0x00,0x89,0x34,
+0x96,0x00,0x8a,0x34,0x7a,0x00,0xc6,0x34,0xb0,0x03,0x8b,0x34,0x00,0x04,0x02,0x24,
+0xa0,0x00,0x03,0x24,0x00,0x00,0x02,0xa5,0x44,0x00,0x84,0x34,0x00,0x00,0x23,0xa5,
+0x00,0x00,0x47,0xa5,0x00,0x00,0xc7,0xa0,0x00,0x00,0x73,0xad,0x00,0x00,0x93,0xa5,
+0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,0x38,0x15,0x86,0x26,0x24,0x18,0x62,0x00,
+0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,0xf2,0x0a,0xc5,0xa4,0x00,0x02,0x42,0x34,
+0x00,0x00,0x82,0xa4,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x6c,0x24,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x4f,0x00,0xa2,0x34,0x9e,0x00,0xa3,0x34,0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,
+0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94,0x9a,0x00,0xa4,0x34,0x98,0x00,0xa6,0x34,
+0xff,0xff,0x73,0x30,0x80,0x12,0x13,0x00,0x00,0xf8,0x42,0x24,0x42,0x99,0x02,0x00,
+0x00,0x14,0x02,0x24,0x00,0x00,0x82,0xa4,0x26,0xb0,0x02,0x3c,0xb0,0x03,0xa7,0x34,
+0xa0,0x80,0x03,0x24,0x7c,0x00,0x42,0x34,0x00,0x00,0xc3,0xa4,0x44,0x00,0xa4,0x34,
+0x00,0x00,0xf3,0xac,0x00,0x00,0x53,0xa4,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,
+0xd8,0x00,0xa5,0x34,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,
+0x38,0x15,0x86,0x26,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,
+0xbf,0xff,0x02,0x24,0xf4,0x0a,0xc0,0xa4,0x24,0x18,0x62,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0xef,0x0a,0xc0,0xa0,0x00,0x00,0xa3,0xa0,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xa5,0xf5,0xc2,0x17,0x25,0xb0,0x02,0x3c,
+0x02,0x80,0x02,0x3c,0xaa,0x3d,0x43,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x06,0x3c,0x97,0x3d,0xc3,0x90,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,
+0x21,0x10,0x47,0x00,0xe8,0x26,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c,0xe4,0x26,0xc3,0x24,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xe0,0x26,0x83,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c,
+0xdc,0x26,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x7e,0x0b,0x44,0x94,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xfd,0xfa,0xc0,0x17,0x38,0x15,0x82,0x26,0x78,0x0b,0x44,0x94,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0x38,0x15,0x82,0x26,0x7a,0x0b,0x44,0x94,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc9,0x48,0x00,0x0c,0x03,0x00,0x04,0x24,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x38,0x15,0x83,0x26,0xec,0x25,0x62,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xf0,0x04,0x62,0xa0,0x90,0x11,0xc3,0x8c,0x29,0xb0,0x02,0x3c,0xc0,0x20,0x05,0x00,
+0x21,0x20,0x82,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0xf0,0x00,0x63,0x34,
+0x90,0x11,0xc3,0xac,0x00,0x00,0x80,0xac,0x04,0x00,0x80,0xac,0x00,0x00,0x45,0xac,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,
+0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xd8,0x26,0x83,0x24,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c,0xd4,0x26,0xc3,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,
+0xd0,0x26,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,
+0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,
+0x02,0x80,0x06,0x3c,0xcc,0x26,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0xec,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,
+0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,
+0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xc8,0x26,0x83,0x24,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x8c,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26,0x80,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x88,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x43,0x0e,0x00,0x08,0x01,0x00,0x04,0x24,
+0x43,0x0e,0x00,0x08,0x02,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x00,0x11,0x1e,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,
+0x2c,0x03,0x44,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x42,0x26,0x04,0x00,
+0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x11,0x1e,0x00,0x38,0x15,0x83,0x26,
+0x21,0x10,0x43,0x00,0x2f,0x03,0x44,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x01,0x00,0x84,0x30,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x36,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,
+0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc9,0x48,0x00,0x0c,
+0x02,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xc9,0x48,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0xaa,0x0c,0x00,0x08,
+0x00,0x00,0x00,0x00,0xf0,0x04,0x87,0xa0,0x90,0x11,0x22,0x8d,0x0f,0x00,0xa3,0x30,
+0x0f,0xff,0x04,0x24,0x00,0x19,0x03,0x00,0x24,0x10,0x44,0x00,0x25,0x10,0x43,0x00,
+0x90,0x11,0x22,0xad,0x00,0x00,0xd3,0xac,0x04,0x00,0xc8,0xac,0x00,0x00,0x65,0xad,
+0x34,0x11,0x00,0x08,0x08,0x00,0x02,0x24,0x38,0x15,0x82,0x26,0x00,0x19,0x1e,0x00,
+0x21,0x18,0x62,0x00,0x35,0x03,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x00,0x19,0x1e,0x00,
+0x21,0x18,0x62,0x00,0x34,0x03,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x00,0x19,0x1e,0x00,
+0x21,0x18,0x62,0x00,0x32,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x00,0x19,0x1e,0x00,
+0x21,0x18,0x62,0x00,0x30,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,
+0xaa,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x80,0x03,0x3c,0xd8,0x7d,0x64,0xac,
+0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
+0xd8,0x7d,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0xac,0x62,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,0x1e,0x00,0xa2,0x10,
+0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,0x03,0x00,0x02,0x24,
+0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,
+0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,0x06,0x00,0x02,0x24,
+0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,0x23,0x10,0x44,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,0x23,0x18,0x62,0x00,
+0xc1,0x18,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,
+0xc1,0x18,0x00,0x08,0x00,0x19,0x02,0x00,0x01,0x80,0x02,0x3c,0xd8,0x7d,0x45,0x8c,
+0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x68,0x63,0x63,0x24,
+0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,0x06,0x00,0xa2,0x2c,
+0x09,0x00,0x40,0x14,0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,0x0f,0x00,0xa2,0x10,
+0x00,0x11,0x04,0x00,0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0xe9,0x18,0x00,0x08,0x40,0x20,0x02,0x00,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0xe9,0x18,0x00,0x08,0x80,0x20,0x02,0x00,0x23,0x10,0x44,0x00,
+0xe9,0x18,0x00,0x08,0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24,
+0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30,
+0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0x0f,0x19,0x00,0x08,
+0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,
+0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14,
+0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,
+0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c,
+0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c,
+0x23,0x19,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0,
+0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24,
+0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30,
+0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36,
+0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,
+0xa8,0x00,0x14,0x36,0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,
+0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae,
+0x00,0x00,0x00,0xae,0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,
+0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,
+0x00,0x00,0x22,0xa6,0xfa,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,0x70,0x0b,0x44,0x8c,
+0xfc,0x37,0x02,0x24,0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae,
+0x00,0x00,0x22,0xa6,0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0xc8,0xff,0xbd,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,
+0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40,
+0x01,0x00,0xc1,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c,
+0x40,0x00,0x30,0x36,0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24,
+0x00,0x00,0xc2,0xa3,0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0xda,0x18,0x00,0x0c,
+0x32,0x00,0x04,0x24,0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,
+0xda,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6,
+0xda,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0xda,0x18,0x00,0x0c,
+0x32,0x00,0x04,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0xda,0x18,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36,
+0x24,0x10,0x43,0x00,0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36,
+0xa4,0x00,0x35,0x36,0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae,
+0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x12,0xa6,0xfa,0x18,0x00,0x0c,0x56,0x01,0x31,0x36,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,
+0x70,0x0b,0x44,0x8c,0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae,
+0x00,0x00,0x65,0xae,0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3,
+0x00,0x60,0x96,0x40,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,
+0x00,0x00,0xa2,0x94,0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,
+0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,
+0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,
+0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,
+0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0xfa,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x25,0xb0,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,
+0x24,0x10,0x43,0x00,0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xff,0xff,0xc6,0x30,0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10,0x11,0x00,0xc3,0x28,
+0x06,0x00,0x60,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x0d,0x00,0xc2,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x06,0x00,0xc2,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa4,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0xa5,0x24,
+0x00,0x2c,0x05,0x00,0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00,0xff,0xff,0x87,0x30,
+0x00,0x00,0x43,0xa0,0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00,0x21,0x30,0x40,0x00,
+0x07,0x10,0xa7,0x00,0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30,0x00,0x00,0x42,0x38,
+0x02,0x00,0x63,0x34,0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0,0x04,0x00,0x63,0x34,
+0x00,0x00,0xc3,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,
+0xff,0xff,0x42,0x24,0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0x04,0x00,0x02,0x24,
+0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0xa2,0x24,
+0x00,0x2c,0x02,0x00,0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04,0x07,0x10,0xa7,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,
+0x00,0x00,0x43,0x90,0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,
+0xff,0x00,0x65,0x30,0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00,0x21,0x30,0x40,0x00,
+0x01,0x00,0x08,0x24,0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30,0x05,0x00,0x60,0x10,
+0x04,0x00,0x02,0x24,0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00,0xff,0xff,0x47,0x30,
+0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,
+0xfb,0x00,0xa5,0x30,0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24,0x00,0x24,0x02,0x00,
+0x03,0x24,0x04,0x00,0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0xe0,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,
+0x0a,0x00,0x10,0x36,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x00,0x00,0x02,0x92,
+0xff,0xff,0x91,0x30,0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30,0x80,0x00,0x43,0x34,
+0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,
+0x00,0x00,0x03,0xa2,0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,
+0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x24,0x1a,0x00,0x0c,
+0x06,0x00,0x04,0x24,0x42,0x20,0x11,0x00,0x24,0x1a,0x00,0x0c,0x06,0x00,0x05,0x24,
+0x4a,0x1a,0x00,0x0c,0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0xff,0xff,0xb1,0x30,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,
+0x21,0x90,0xc0,0x00,0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30,0x71,0x1a,0x00,0x0c,
+0x21,0x20,0x00,0x02,0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26,0x00,0x00,0x42,0xa6,
+0xff,0xff,0x71,0x30,0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16,0x02,0x00,0x52,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x0a,0x00,0x68,0x34,
+0x00,0x00,0x02,0x91,0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30,0x1f,0x00,0xa0,0x10,
+0xff,0x00,0x47,0x30,0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34,0x0b,0x00,0x6b,0x34,
+0xc0,0xff,0x0a,0x24,0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00,0xff,0x00,0x47,0x30,
+0x00,0x00,0x64,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,
+0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,
+0x21,0x40,0xa0,0x01,0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,
+0xc0,0x00,0xe3,0x30,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8d,
+0xfc,0xff,0xa3,0x24,0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30,0x00,0x00,0xc2,0xac,
+0xff,0x00,0x84,0x30,0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00,0xff,0xff,0xa5,0x30,
+0xc0,0x50,0x04,0x00,0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x25,0xb0,0x07,0x3c,
+0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00,0x01,0x80,0x08,0x3c,
+0x25,0x20,0xa3,0x00,0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01,0x44,0x02,0xe7,0x34,
+0x00,0x00,0xe4,0xac,0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90,0x02,0x00,0xc4,0x90,
+0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,
+0x00,0x1c,0x03,0x00,0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00,0x00,0x2e,0x05,0x00,
+0x25,0x40,0x48,0x01,0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,
+0x00,0x00,0x28,0xad,0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00,0x21,0x10,0xa8,0x01,
+0x01,0x00,0x43,0x90,0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90,0x03,0x00,0x46,0x90,
+0x00,0x1a,0x03,0x00,0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa4,0x00,
+0x00,0x36,0x06,0x00,0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01,0x25,0x20,0xa6,0x00,
+0x10,0x00,0x03,0x2d,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x22,0xad,
+0xee,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00,
+0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00,
+0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24,
+0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00,
+0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c,
+0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,
+0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24,
+0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00,
+0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00,
+0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0,
+0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x80,0x02,0x3c,0xdc,0x7d,0x42,0x24,
+0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac,
+0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac,
+0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0x3a,0x1b,0x00,0x08,
+0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0x3a,0x1b,0x00,0x08,0x10,0x00,0x82,0xac,
+0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,
+0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x14,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x80,0x16,0x3c,
+0x01,0x80,0x14,0x3c,0x02,0x80,0x11,0x3c,0x02,0x80,0x15,0x3c,0xcc,0x3d,0x24,0x8e,
+0x25,0xb0,0x02,0x3c,0x88,0x6d,0xc3,0x26,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0xdc,0x7d,0x90,0x8e,0x18,0x00,0x80,0x10,0xdc,0x7d,0x82,0x26,0x15,0x00,0x02,0x12,
+0x00,0x00,0x00,0x00,0x21,0x98,0x40,0x00,0x01,0x00,0x12,0x24,0x14,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x1d,0x00,0x52,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0xcc,0x3d,0x22,0x8e,0x00,0x00,0x00,0x00,
+0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0c,0x00,0x04,0xae,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0xef,0xff,0x13,0x16,
+0x00,0x00,0x00,0x00,0xcc,0x3d,0x20,0xae,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00,
+0x21,0x30,0x00,0x00,0x1c,0x2c,0x00,0x0c,0x21,0x38,0x00,0x00,0x6f,0x1b,0x00,0x08,
+0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,
+0x00,0x00,0x00,0x00,0x89,0x1b,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,
+0xcc,0x3d,0x22,0x8e,0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,
+0xe7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,
+0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,0x89,0x1b,0x00,0x08,
+0x0c,0x00,0x03,0xae,0x02,0x80,0x02,0x3c,0x3c,0x39,0x43,0x8c,0xff,0x00,0xa5,0x30,
+0x25,0xb0,0x02,0x3c,0x42,0x18,0x03,0x00,0x21,0x30,0xa2,0x00,0x01,0x00,0x63,0x30,
+0x01,0x00,0x02,0x24,0x10,0x00,0xa7,0x2c,0x04,0x00,0x62,0x10,0xff,0x00,0x84,0x30,
+0x60,0x01,0xc4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,
+0x10,0x00,0xa2,0x34,0xfa,0xff,0xe0,0x10,0x21,0x40,0x43,0x00,0x60,0x01,0xc4,0xa0,
+0x60,0x01,0x04,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,
+0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,
+0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,
+0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc0,0x40,0x04,0x00,
+0x21,0x18,0x04,0x01,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,
+0x80,0x18,0x03,0x00,0x38,0x15,0x42,0x24,0x21,0x18,0x62,0x00,0x8c,0x11,0x66,0x8c,
+0x21,0x38,0x60,0x00,0x92,0x11,0x60,0xa0,0x93,0x11,0x60,0xa0,0x1c,0x00,0x05,0x24,
+0xe0,0x1b,0x00,0x08,0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,
+0x04,0x10,0xa3,0x00,0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,
+0x01,0x00,0xa5,0x24,0x92,0x11,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x38,0x15,0x63,0x24,
+0x21,0x18,0x43,0x00,0x8c,0x11,0x66,0x8c,0x21,0x28,0x00,0x00,0xf4,0x1b,0x00,0x08,
+0x01,0x00,0x07,0x24,0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x04,0x10,0xa7,0x00,0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,
+0xff,0xff,0xa5,0x24,0x08,0x00,0xe0,0x03,0x93,0x11,0x65,0xa0,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
+0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x80,0x80,0x10,0x00,
+0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,
+0x14,0x00,0xb1,0xaf,0x90,0x11,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,
+0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,
+0x88,0x11,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,
+0x24,0x10,0x45,0x00,0xcf,0x1b,0x00,0x0c,0x8c,0x11,0x02,0xae,0x92,0x11,0x04,0x92,
+0xa9,0x1b,0x00,0x0c,0xff,0x00,0x45,0x32,0x92,0x11,0x04,0x92,0xbf,0x1b,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,
+0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,
+0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0x08,0x83,0x63,0x24,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
+0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x90,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x68,0x00,0xbe,0xaf,0x64,0x00,0xb7,0xaf,
+0x60,0x00,0xb6,0xaf,0x5c,0x00,0xb5,0xaf,0x54,0x00,0xb3,0xaf,0x50,0x00,0xb2,0xaf,
+0x6c,0x00,0xbf,0xaf,0x58,0x00,0xb4,0xaf,0x4c,0x00,0xb1,0xaf,0x48,0x00,0xb0,0xaf,
+0x38,0x83,0x42,0x24,0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24,0x10,0x00,0xa3,0xaf,
+0x21,0x98,0x00,0x00,0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,
+0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,
+0x21,0xb0,0x00,0x00,0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf,
+0x30,0x00,0xa0,0xaf,0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf,
+0x40,0x00,0xa0,0xaf,0x21,0x90,0x80,0x02,0x90,0x11,0x42,0x8e,0x00,0x00,0x00,0x00,
+0x02,0x13,0x02,0x00,0x01,0x00,0x42,0x30,0x6c,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,
+0x21,0x10,0x62,0x02,0x60,0x01,0x44,0x90,0x78,0x11,0x43,0x8e,0x74,0x11,0x46,0x8e,
+0xff,0x00,0x91,0x30,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x21,0x10,0x24,0x02,
+0x77,0x04,0x44,0x90,0x5a,0x04,0x45,0x90,0x5c,0x11,0x47,0x8e,0x18,0x00,0x64,0x00,
+0x12,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,
+0x12,0x30,0x00,0x00,0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x25,0x01,0x40,0x14,
+0x23,0x10,0xe6,0x00,0x5c,0x11,0x42,0xae,0x78,0x11,0x44,0x8e,0x74,0x11,0x47,0x8e,
+0x60,0x11,0x48,0x8e,0x64,0x11,0x45,0x8e,0x6c,0x11,0x46,0x8e,0x70,0x11,0x43,0x8e,
+0x21,0x38,0xe4,0x00,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x21,0x10,0x24,0x02,
+0x21,0x40,0x05,0x01,0x21,0x30,0xc3,0x00,0xce,0x04,0x42,0x90,0x5c,0x11,0x4a,0x8e,
+0x0c,0x00,0xe0,0x10,0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,
+0x02,0x80,0x02,0x3c,0x07,0x00,0x22,0x2e,0x93,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,
+0x0c,0x00,0x02,0x24,0x8f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24,0x8e,0x01,0x22,0x12,
+0xc0,0x10,0x07,0x00,0x81,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,
+0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02,0xce,0x11,0x85,0x90,
+0xf8,0x04,0x62,0x8c,0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,
+0x76,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xec,0x11,0x42,0x8e,0x01,0x00,0x07,0x24,
+0x04,0x18,0x27,0x02,0x24,0x10,0x43,0x00,0x04,0x01,0x40,0x10,0x1c,0x00,0x22,0x2e,
+0x21,0x28,0x51,0x02,0x94,0x11,0xa6,0x90,0xce,0x11,0xa2,0x90,0x0a,0x00,0x04,0x24,
+0xff,0x00,0xc3,0x30,0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xfb,0x00,0x60,0x10,
+0x1c,0x00,0x22,0x2e,0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x8c,0x01,0x64,0x10,
+0x94,0x11,0xa2,0xa0,0x02,0x80,0x04,0x3c,0x38,0x15,0x85,0x24,0x80,0x10,0x11,0x00,
+0x21,0x10,0x45,0x00,0x6c,0x05,0x44,0x8c,0xf8,0x04,0x43,0x8c,0x21,0x30,0xc5,0x02,
+0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,
+0x5c,0x11,0xca,0xac,0xec,0x25,0xa3,0x8c,0xff,0xff,0x02,0x34,0x03,0x00,0x62,0x10,
+0x21,0x20,0x20,0x02,0xa9,0x1b,0x00,0x0c,0xff,0x00,0x65,0x32,0xbf,0x1b,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,
+0x0a,0x20,0x62,0x00,0xbc,0x00,0x60,0x12,0x10,0x00,0xa4,0xaf,0x02,0x80,0x03,0x3c,
+0x38,0x15,0x62,0x24,0x21,0x10,0xa2,0x02,0x70,0x11,0x40,0xac,0x74,0x11,0x40,0xac,
+0x78,0x11,0x40,0xac,0x60,0x11,0x40,0xac,0x64,0x11,0x40,0xac,0x68,0x11,0x40,0xac,
+0x6c,0x11,0x40,0xac,0x40,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0x8f,0x01,0x00,0x73,0x26,
+0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x40,0x00,0xa4,0xaf,0x3c,0x00,0xa2,0xaf,
+0x38,0x00,0xa4,0x8f,0x34,0x00,0xa2,0x8f,0x20,0x00,0x63,0x2a,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x38,0x00,0xa4,0xaf,0x34,0x00,0xa2,0xaf,0x30,0x00,0xa4,0x8f,
+0x2c,0x00,0xa2,0x8f,0x94,0x00,0x52,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,
+0x30,0x00,0xa4,0xaf,0x2c,0x00,0xa2,0xaf,0x28,0x00,0xa4,0x8f,0x24,0x00,0xa2,0x8f,
+0x94,0x00,0xd6,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0xaf,
+0x24,0x00,0xa2,0xaf,0x20,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0x8f,0x94,0x00,0xde,0x27,
+0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x20,0x00,0xa4,0xaf,0x1c,0x00,0xa2,0xaf,
+0x18,0x00,0xa4,0x8f,0x14,0x00,0xa2,0x8f,0x94,0x00,0x94,0x26,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0xaf,0x14,0x00,0xa2,0xaf,0x94,0x00,0xf7,0x26,
+0x59,0xff,0x60,0x14,0x94,0x00,0xb5,0x26,0x10,0x00,0xa3,0x8f,0x6c,0x00,0xbf,0x8f,
+0x68,0x00,0xbe,0x8f,0x64,0x00,0xb7,0x8f,0x60,0x00,0xb6,0x8f,0x5c,0x00,0xb5,0x8f,
+0x58,0x00,0xb4,0x8f,0x54,0x00,0xb3,0x8f,0x50,0x00,0xb2,0x8f,0x4c,0x00,0xb1,0x8f,
+0x48,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x70,0x00,0xbd,0x27,
+0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x87,0x00,0xe0,0x10,
+0x00,0x00,0x00,0x00,0x87,0x00,0x20,0x15,0x02,0x80,0x03,0x3c,0x40,0x10,0x07,0x00,
+0x21,0x10,0x47,0x00,0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0xa7,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x20,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,0x38,0x15,0x88,0x24,
+0x21,0x20,0x48,0x00,0x21,0x30,0x91,0x00,0xec,0x11,0x83,0x8c,0x01,0x00,0x05,0x24,
+0x04,0x10,0x25,0x02,0xb1,0x11,0xc7,0x90,0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,
+0xec,0x11,0x83,0xac,0x09,0x00,0xe5,0x10,0x94,0x11,0xc0,0xa0,0x1c,0x00,0xa3,0x8f,
+0x21,0x38,0x00,0x00,0x21,0x20,0x68,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,
+0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x02,0x80,0x04,0x3c,
+0x38,0x15,0x83,0x24,0x18,0x00,0xa4,0x8f,0x21,0x50,0x60,0x00,0x21,0x38,0x00,0x00,
+0x21,0x10,0x83,0x00,0x21,0x10,0x51,0x00,0xb1,0x11,0x40,0xa0,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x4c,0x82,0x49,0x24,0xd8,0x81,0x68,0x24,0x80,0x18,0x07,0x00,
+0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,
+0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,0xf8,0x04,0x65,0xac,
+0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x15,0x00,0x20,0x12,0x02,0x80,0x05,0x3c,
+0x93,0x11,0x82,0x92,0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00,0x10,0x00,0x40,0x14,
+0x02,0x80,0x03,0x3c,0x14,0x00,0xa4,0x8f,0x38,0x15,0x62,0x24,0x21,0x10,0x82,0x00,
+0x93,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,
+0x24,0x10,0x83,0x00,0x06,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,
+0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,
+0x96,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24,0xe8,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x04,0x3c,0x38,0x15,0x83,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00,
+0x6c,0x05,0x44,0x8c,0xf8,0x04,0x43,0x8c,0x96,0x3d,0xa5,0x90,0x40,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xd6,0x00,0xa2,0x10,
+0x82,0x50,0x03,0x00,0xec,0x11,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02,
+0x25,0x18,0x62,0x00,0xec,0x11,0x83,0xae,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,
+0x21,0x10,0xe3,0x02,0x5c,0x11,0x4a,0xac,0xec,0x25,0x64,0x8c,0xff,0xff,0x02,0x34,
+0x44,0xff,0x82,0x14,0x21,0x20,0x20,0x02,0xbf,0x1b,0x00,0x0c,0x21,0x20,0x20,0x02,
+0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,
+0x46,0xff,0x60,0x16,0x10,0x00,0xa4,0xaf,0x02,0x80,0x02,0x3c,0x38,0x15,0x50,0x24,
+0x64,0x11,0x05,0x96,0x60,0x11,0x02,0x96,0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00,
+0x21,0x28,0x45,0x00,0xc4,0x47,0x00,0x0c,0x68,0x0c,0x24,0x36,0x70,0x11,0x02,0x8e,
+0x6c,0x11,0x05,0x8e,0x68,0x11,0x03,0x96,0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00,
+0x00,0x2c,0x05,0x00,0xc4,0x47,0x00,0x0c,0x21,0x28,0x65,0x00,0xe8,0x1c,0x00,0x08,
+0x02,0x80,0x03,0x3c,0x92,0x1c,0x00,0x08,0x5c,0x11,0x40,0xae,0x27,0xff,0x20,0x11,
+0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,
+0x6c,0x05,0x64,0x8c,0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x1f,0xff,0x80,0x10,
+0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x0a,0xff,0x40,0x10,
+0x02,0x80,0x04,0x3c,0x21,0x20,0x51,0x02,0xb1,0x11,0x83,0x90,0x01,0x00,0x02,0x24,
+0x78,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x40,0x00,0xa3,0x8f,0x38,0x15,0x42,0x24,
+0x21,0x20,0x62,0x00,0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,
+0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x3c,0x00,0xa2,0x8f,
+0x02,0x80,0x04,0x3c,0x38,0x15,0x85,0x24,0x21,0x30,0x45,0x00,0xec,0x11,0xc2,0x8c,
+0x01,0x00,0x03,0x24,0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd1,0x00,
+0x24,0x10,0x43,0x00,0xb1,0x11,0x80,0xa0,0xec,0x11,0xc2,0xac,0x12,0x00,0x20,0x16,
+0x94,0x11,0x80,0xa0,0x92,0x11,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,
+0x01,0x00,0x07,0x24,0x38,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x65,0x00,
+0x92,0x11,0x44,0x90,0x8c,0x11,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,
+0x8d,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,
+0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x44,0x24,
+0x34,0x00,0xa2,0x8f,0x01,0x00,0x27,0x26,0x21,0x18,0x44,0x00,0x92,0x11,0x62,0x90,
+0x00,0x00,0x00,0x00,0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c,
+0x30,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x92,0x11,0x45,0x90,
+0x8c,0x11,0x44,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x73,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,
+0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0x96,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24,
+0x3e,0x00,0x62,0x10,0xee,0xff,0x22,0x26,0x96,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24,
+0xbd,0xfe,0x62,0x14,0x02,0x80,0x04,0x3c,0x28,0x00,0xa2,0x8f,0x38,0x15,0x86,0x24,
+0x21,0x20,0x46,0x00,0x90,0x11,0x85,0x8c,0x01,0x00,0x03,0x24,0x42,0x13,0x05,0x00,
+0x07,0x00,0x42,0x30,0xb3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e,0xb1,0xfe,0x40,0x14,
+0x1c,0x00,0x22,0x2e,0xaf,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,
+0x24,0x10,0xa2,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x82,0xac,0x93,0x11,0x83,0x90,
+0xff,0xff,0x27,0x26,0x2a,0x18,0xe3,0x00,0xa6,0xfe,0x60,0x14,0x00,0x00,0x00,0x00,
+0x24,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00,0x93,0x11,0x45,0x90,
+0x8c,0x11,0x44,0x8c,0x32,0x1e,0x00,0x08,0x01,0x00,0x06,0x24,0x2a,0x10,0xe5,0x00,
+0x9c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,
+0xfa,0xff,0x43,0x14,0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24,0xcd,0x1c,0x00,0x08,
+0xff,0x00,0xf1,0x30,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,0xc2,0x10,0x02,0x00,
+0x2b,0x10,0x48,0x00,0x7c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0xad,0x1c,0x00,0x08,
+0x00,0x00,0x00,0x00,0x18,0x00,0x22,0x2e,0x17,0x00,0x40,0x14,0x05,0x00,0x22,0x2e,
+0xce,0x11,0x83,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x62,0x2c,0x8b,0xff,0x40,0x10,
+0x01,0x00,0x62,0x24,0xd3,0x1d,0x00,0x08,0xce,0x11,0x82,0xa0,0xff,0x00,0x42,0x30,
+0x02,0x00,0x42,0x2c,0xc0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x2c,0x00,0xa3,0x8f,
+0x38,0x15,0x82,0x24,0x21,0x10,0x62,0x00,0x8c,0x11,0x43,0x8c,0x00,0x01,0x04,0x3c,
+0x18,0x00,0x02,0x24,0x24,0x18,0x64,0x00,0x0e,0x1e,0x00,0x08,0x0b,0x88,0x43,0x00,
+0xcd,0x1c,0x00,0x08,0xb1,0x11,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0xce,0x11,0x83,0x90,0x47,0x1e,0x00,0x08,0x03,0x00,0x62,0x2c,0xce,0x11,0x83,0x90,
+0x47,0x1e,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x29,0xff,0x22,0x16,
+0x02,0x80,0x02,0x3c,0x94,0x1d,0x00,0x08,0x38,0x15,0x43,0x24,0x38,0x15,0x62,0x24,
+0x21,0x20,0xc2,0x03,0x90,0x11,0x83,0x8c,0x00,0x00,0x00,0x00,0x42,0x13,0x03,0x00,
+0x07,0x00,0x42,0x30,0x12,0xff,0x40,0x10,0x14,0x00,0x22,0x2e,0x10,0xff,0x40,0x10,
+0x0c,0x00,0x22,0x2e,0x0e,0xff,0x40,0x14,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,
+0x24,0x10,0x62,0x00,0x80,0x1d,0x00,0x08,0x90,0x11,0x82,0xac,0xff,0x00,0xf1,0x30,
+0x0a,0x1e,0x00,0x08,0x02,0x80,0x05,0x3c,0xf2,0x1d,0x00,0x08,0xff,0x00,0xf1,0x30,
+0x7b,0x1d,0x00,0x08,0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x38,0x00,0xb2,0xaf,0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf,0x4c,0x00,0xb7,0xaf,
+0x48,0x00,0xb6,0xaf,0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf,0x3c,0x00,0xb3,0xaf,
+0x34,0x00,0xb1,0xaf,0x30,0x00,0xb0,0xaf,0x38,0x15,0x46,0x24,0x71,0x25,0xc4,0x90,
+0x6c,0x25,0xc3,0x8c,0x68,0x25,0xc2,0x8c,0x21,0x90,0x64,0x00,0x2b,0x10,0x42,0x02,
+0x7e,0x00,0x40,0x10,0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c,0x02,0x80,0x17,0x3c,
+0x21,0xa8,0xc0,0x00,0x21,0xb0,0xc0,0x00,0x9d,0x1e,0x00,0x08,0x01,0x00,0x14,0x24,
+0x68,0x25,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x73,0x00,0x40,0x10,
+0x21,0x88,0xc0,0x02,0x71,0x25,0x22,0x92,0xff,0xff,0x45,0x32,0x25,0x28,0xb7,0x00,
+0x10,0x00,0x42,0x24,0x71,0x25,0x22,0xa2,0x14,0x39,0xc4,0x27,0x60,0x45,0x00,0x0c,
+0x10,0x00,0x06,0x24,0x04,0x24,0x23,0x8e,0x00,0x00,0x00,0x00,0x42,0x18,0x03,0x00,
+0x01,0x00,0x63,0x30,0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,
+0xe0,0x23,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00,0x1f,0x00,0x10,0x32,
+0xc0,0x48,0x10,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x55,0x00,0x90,0x11,0x45,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x1b,0x05,0x00,0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10,0x21,0x30,0xa0,0x02,
+0x25,0xb0,0x02,0x3c,0x21,0x40,0x02,0x02,0xdc,0x23,0xa7,0x8e,0x04,0x24,0xa2,0x8e,
+0x60,0x01,0x03,0x91,0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30,0xff,0x00,0x6b,0x30,
+0x9a,0x00,0x54,0x10,0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c,0x3c,0x83,0x84,0x24,
+0x00,0x00,0x86,0x8c,0x04,0x00,0x04,0x24,0xdc,0x23,0xc3,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x15,0x03,0x00,0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x0a,0x00,0x60,0x04,
+0x0a,0x50,0x82,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x7c,0x11,0x43,0x8c,0x04,0x00,0x0a,0x24,
+0x01,0x00,0x63,0x24,0x7c,0x11,0x43,0xac,0xe0,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x13,0x02,0x00,0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0xb8,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0xdc,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,
+0xb3,0xff,0x4b,0x14,0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11,0x21,0x10,0x30,0x01,
+0xa8,0x00,0x54,0x11,0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24,0xb0,0x00,0x42,0x11,
+0x21,0x10,0x30,0x01,0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11,0x21,0x10,0x30,0x01,
+0xc0,0x00,0x44,0x11,0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,
+0x21,0x10,0x66,0x01,0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,
+0xc8,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x74,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,
+0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00,0x74,0x11,0xa3,0xac,
+0x21,0x10,0x4a,0x00,0x38,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x64,0x00,0x5c,0x11,0xa3,0xac,0x68,0x25,0xc2,0x8e,0x10,0x00,0x52,0x26,
+0x2b,0x10,0x42,0x02,0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02,0x54,0x00,0xbf,0x8f,
+0x50,0x00,0xbe,0x8f,0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f,
+0x40,0x00,0xb4,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,
+0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27,0xe0,0x23,0x22,0x8e,
+0x00,0x00,0x00,0x00,0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30,0x90,0xff,0x60,0x10,
+0x0f,0x00,0x50,0x30,0x89,0x47,0x00,0x0c,0x48,0x00,0x04,0x24,0x74,0xff,0x40,0x10,
+0x21,0x98,0x40,0x00,0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24,0x14,0x00,0x62,0xae,
+0x0c,0x00,0x64,0xae,0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24,0x08,0x00,0x07,0x24,
+0x80,0x00,0x63,0x34,0x14,0x00,0xa3,0xaf,0xe0,0x23,0x26,0x8e,0x24,0x18,0x64,0x00,
+0xff,0xe0,0x04,0x24,0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30,0x25,0x18,0x62,0x00,
+0x14,0x00,0xa3,0xaf,0xdc,0x23,0x25,0x8e,0x24,0x18,0x64,0x00,0x02,0x23,0x06,0x00,
+0x82,0x13,0x05,0x00,0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00,0xff,0xff,0x02,0x3c,
+0xff,0x7f,0x42,0x34,0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00,0xc0,0x2b,0x05,0x00,
+0x0f,0x00,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x00,0x35,0x06,0x00,0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34,
+0x0f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,
+0x02,0x80,0x04,0x3c,0x10,0x00,0xa5,0x27,0x68,0x39,0x84,0x24,0x02,0x00,0x06,0x24,
+0x04,0x00,0x02,0x24,0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf,0x6c,0x45,0x00,0x0c,
+0x10,0x00,0xa2,0xa3,0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27,0x02,0x00,0x06,0x24,
+0x25,0x20,0x97,0x00,0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x78,0x08,0x00,0x0c,
+0x21,0x20,0x60,0x02,0xb1,0x1e,0x00,0x08,0xc0,0x48,0x10,0x00,0x02,0x12,0x05,0x00,
+0x01,0x00,0x42,0x30,0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00,0x01,0x00,0x42,0x30,
+0x76,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x10,0x24,0xa2,0x96,0x60,0x01,0x03,0x91,
+0xc2,0x27,0x07,0x00,0x21,0x10,0x42,0x01,0x2c,0x24,0xa3,0xa2,0x13,0x00,0x80,0x10,
+0x10,0x24,0xa2,0xa6,0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c,0x0c,0x24,0xa2,0x96,
+0x16,0x24,0xa3,0x96,0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0x0c,0x24,0xa2,0xa6,
+0xc7,0x1e,0x00,0x08,0x16,0x24,0xa3,0xa6,0x5d,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,
+0x0e,0x24,0xa3,0x96,0x1a,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x1a,0x24,0xa2,0xa6,0xc6,0x1e,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x0e,0x24,0xa3,0x96,
+0x1c,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x1c,0x24,0xa2,0xa6,
+0xc6,0x1e,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x60,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,
+0x01,0x00,0x63,0x24,0x5c,0xff,0x54,0x15,0x60,0x11,0x43,0xac,0x21,0x10,0x30,0x01,
+0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,
+0x64,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x64,0x11,0x43,0xac,
+0x02,0x00,0x02,0x24,0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24,0x21,0x10,0x30,0x01,
+0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,
+0x68,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x68,0x11,0x43,0xac,
+0x03,0x00,0x02,0x24,0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x6c,0x11,0x43,0x8c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15,0x6c,0x11,0x43,0xac,
+0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x46,0x00,0x70,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,
+0x70,0x11,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01,
+0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0x3a,0xff,0x60,0x10,
+0x00,0x00,0x00,0x00,0x78,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x02,0x80,0x04,0x3c,
+0x38,0x15,0x84,0x24,0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x44,0x00,
+0x78,0x11,0xa3,0xac,0x21,0x10,0x4a,0x00,0xc9,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,
+0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,0x0a,0x1f,0x00,0x08,0x5c,0x11,0xa3,0xac,
+0x0c,0x24,0xa3,0x96,0x14,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x14,0x24,0xa2,0xa6,0xc6,0x1e,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x08,0x00,0xe0,0x04,
+0x00,0x00,0x00,0x00,0x0e,0x24,0xa3,0x96,0x18,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,
+0x01,0x00,0x42,0x24,0x18,0x24,0xa2,0xa6,0xc6,0x1e,0x00,0x08,0x0e,0x24,0xc3,0xa4,
+0x0c,0x24,0xa3,0x96,0x12,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x12,0x24,0xa2,0xa6,0xc6,0x1e,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x02,0x80,0x0a,0x3c,
+0x38,0x15,0x42,0x8d,0xe8,0xff,0xbd,0x27,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x11,0x00,0x40,0x14,0x10,0x00,0xbf,0xaf,0x25,0xb0,0x05,0x3c,0x4c,0x00,0xa2,0x34,
+0x00,0x00,0x43,0x90,0x38,0x15,0x46,0x25,0xf9,0x0a,0xc2,0x90,0x03,0x00,0x67,0x30,
+0x09,0x00,0x47,0x10,0x58,0x00,0xa2,0x34,0x00,0x00,0x44,0x8c,0x29,0xb0,0x03,0x3c,
+0x5c,0x00,0xa2,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x44,0x8c,0x04,0x00,0x63,0x34,
+0xf9,0x0a,0xc7,0xa0,0x00,0x00,0x64,0xac,0x25,0xb0,0x02,0x3c,0x2d,0x0a,0x46,0x34,
+0xa2,0x0d,0x43,0x34,0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34,0xa8,0x0d,0x42,0x34,
+0x00,0x00,0x67,0x94,0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94,0x00,0x00,0x44,0x94,
+0x00,0x00,0xc3,0x90,0x38,0x15,0x42,0x25,0xe2,0x02,0x44,0xa4,0x40,0x00,0x63,0x34,
+0xff,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0xdc,0x02,0x47,0xa4,0xde,0x02,0x48,0xa4,
+0xe0,0x02,0x49,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,
+0x5b,0x0a,0xe2,0x34,0x00,0x00,0x44,0x90,0x38,0x15,0x46,0x25,0x5c,0x0a,0xe2,0x34,
+0x00,0x00,0x45,0x90,0xdc,0x02,0xc3,0x94,0xde,0x02,0xc2,0x94,0xe0,0x02,0xc9,0x94,
+0xe2,0x02,0xc8,0x94,0xff,0x00,0x84,0x30,0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00,
+0xff,0x00,0xa5,0x30,0x21,0x20,0x85,0x00,0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30,
+0x21,0x18,0x68,0x00,0x21,0x18,0x62,0x00,0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30,
+0xe4,0x02,0xc3,0xac,0x00,0x00,0xe2,0xa4,0xe8,0x02,0xc4,0xa4,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x42,0x8d,0x01,0x00,0x03,0x24,0x01,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x38,0x15,0x45,0x25,0xb9,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x10,0x00,0xbf,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0xe8,0x02,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30,
+0xf5,0xff,0x40,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x4e,0x00,0x64,0x10,0x00,0x00,0x00,0x00,
+0x38,0x15,0x45,0x25,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14,
+0x38,0x15,0x46,0x25,0x38,0x15,0x42,0x8d,0x01,0x00,0x03,0x24,0x02,0x11,0x02,0x00,
+0x03,0x00,0x42,0x30,0x49,0x00,0x43,0x10,0x3e,0x00,0x02,0x24,0xea,0x02,0xc3,0x90,
+0xff,0x00,0x02,0x24,0xe0,0xff,0x62,0x14,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,
+0x00,0x00,0x45,0x90,0xcc,0x02,0xc4,0x94,0xe4,0x02,0xc7,0x8c,0x32,0x00,0x02,0x24,
+0x20,0x00,0x03,0x24,0x7f,0x00,0xa5,0x30,0x2b,0x20,0xe4,0x00,0xd4,0x02,0xc2,0xa0,
+0xd5,0x02,0xc3,0xa0,0x0c,0x00,0x80,0x14,0xff,0xff,0xa2,0x24,0xce,0x02,0xc2,0x94,
+0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x09,0x00,0x40,0x14,0x38,0x15,0x44,0x25,
+0xd0,0x02,0xc2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x02,0x00,0x40,0x10,
+0x02,0x00,0xa2,0x24,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x38,0x15,0x44,0x25,
+0xd4,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x65,0x00,0xb9,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x21,0x28,0x60,0x00,0x38,0x15,0x43,0x25,0xe4,0x02,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0xae,0x00,0x40,0x14,0x3a,0x00,0xa2,0x2c,
+0x32,0x00,0x05,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,
+0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3e,0x20,0x00,0x08,
+0x00,0x00,0x00,0x00,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0xb0,0xff,0x40,0x14,
+0xff,0xff,0x02,0x24,0x50,0x20,0x00,0x08,0xea,0x02,0xa2,0xa0,0x02,0x00,0xa4,0x90,
+0xd4,0x02,0xa2,0xa0,0x1c,0x00,0x03,0x24,0x06,0x00,0x02,0x24,0x92,0x00,0x82,0x10,
+0xd5,0x02,0xa3,0xa0,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x8f,0xff,0x60,0x10,0x38,0x15,0x44,0x25,
+0xfc,0x23,0x83,0x8c,0xff,0xff,0x02,0x34,0x8b,0xff,0x62,0x10,0x00,0x00,0x00,0x00,
+0xe4,0x02,0x83,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x62,0x2c,0x97,0x00,0x40,0x14,
+0x90,0x01,0x62,0x2c,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,
+0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,
+0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,0xd6,0x02,0x82,0xa0,0x38,0x15,0x44,0x25,
+0x90,0x11,0x82,0x8c,0x06,0x00,0x03,0x24,0x07,0x00,0x42,0x30,0x96,0x00,0x43,0x10,
+0x25,0xb0,0x03,0x3c,0x00,0x24,0x82,0x8c,0xfc,0x23,0x84,0x8c,0x02,0x11,0x02,0x00,
+0x7f,0x00,0x4c,0x30,0x02,0x21,0x04,0x00,0x66,0x0c,0x63,0x34,0x00,0x00,0x6c,0xa0,
+0x7f,0x00,0x8b,0x30,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,
+0x67,0x0c,0x42,0x34,0x00,0x00,0x4b,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x00,0x3e,0x0b,0x00,0x00,0x16,0x0c,0x00,0x2b,0x20,0x8b,0x01,0x03,0x3e,0x07,0x00,
+0x03,0x16,0x02,0x00,0x0a,0x38,0x44,0x00,0x25,0xb0,0x02,0x3c,0x04,0x0d,0x42,0x34,
+0x00,0x00,0x43,0x90,0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x6f,0x00,0x62,0x10,
+0x04,0x00,0xe2,0x24,0x02,0x00,0x80,0x14,0x23,0x10,0x6c,0x01,0x23,0x10,0x8b,0x01,
+0xff,0x00,0x42,0x30,0x15,0x00,0x42,0x2c,0x05,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,
+0x38,0x15,0x43,0x25,0x0a,0x00,0x02,0x24,0xd6,0x02,0x62,0xa0,0x25,0xb0,0x02,0x3c,
+0x6c,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,
+0x03,0x16,0x02,0x00,0x02,0x00,0x40,0x14,0x0a,0x00,0x42,0x24,0x0a,0x00,0xe2,0x24,
+0x38,0x15,0x44,0x25,0xd6,0x02,0x83,0x90,0x00,0x3e,0x02,0x00,0x03,0x3e,0x07,0x00,
+0xd2,0x02,0x85,0x90,0x23,0x18,0xe3,0x00,0x00,0x3e,0x03,0x00,0x03,0x3e,0x07,0x00,
+0xff,0x00,0xa2,0x30,0x2a,0x10,0x47,0x00,0x3e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x00,0x3e,0x05,0x00,0x03,0x3e,0x07,0x00,0x38,0x15,0x43,0x25,0xe4,0x02,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x32,0x00,0x40,0x14,0x3a,0x00,0xe2,0x28,
+0x32,0x00,0xe2,0x28,0x2f,0x00,0x40,0x10,0x3a,0x00,0xe2,0x28,0x32,0x00,0x07,0x24,
+0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,
+0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0xff,0x00,0xe4,0x30,0x00,0x00,0x44,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,
+0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3e,0x20,0x00,0x08,
+0x00,0x00,0x00,0x00,0x54,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0x86,0x20,0x00,0x08,
+0x44,0x00,0x03,0x24,0xd5,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0xa3,0x00,
+0x7e,0x20,0x00,0x08,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c,0x00,0x08,0x42,0x34,
+0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x27,0x18,0x03,0x00,0x01,0x00,0x63,0x30,
+0x69,0xff,0x60,0x10,0x25,0xb0,0x02,0x3c,0x36,0x00,0x02,0x24,0xa9,0x20,0x00,0x08,
+0xd2,0x02,0xa2,0xa0,0xd3,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0x19,0x21,0x00,0x08,
+0x44,0x00,0x03,0x24,0xd3,0x02,0x83,0x80,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,
+0x2a,0x10,0xe2,0x00,0x0e,0x21,0x00,0x08,0x0b,0x38,0x62,0x00,0x73,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,
+0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28,0x0b,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xc2,0x20,0x00,0x08,0x0c,0x00,0x02,0x24,0x00,0x3e,0x02,0x00,
+0xed,0x20,0x00,0x08,0x03,0x3e,0x07,0x00,0x80,0x11,0x82,0x8c,0x2b,0x20,0x8b,0x01,
+0x02,0x11,0x02,0x00,0xe6,0x20,0x00,0x08,0x7f,0x00,0x47,0x30,0xc2,0x20,0x00,0x08,
+0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x25,0xb0,0x14,0x3c,
+0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
+0x20,0x00,0xb2,0xaf,0xd8,0x00,0x86,0x36,0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x51,0x24,0x2a,0xb0,0x10,0x3c,0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,
+0x34,0x00,0x05,0x36,0xfe,0xff,0x02,0x24,0xbc,0x02,0x32,0x92,0x40,0x00,0x04,0x24,
+0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,0x89,0x47,0x00,0x0c,0x00,0x96,0x12,0x00,
+0x21,0x98,0x40,0x00,0x8d,0x00,0x60,0x12,0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,
+0xb0,0x03,0x82,0x36,0x25,0xb0,0x1e,0x3c,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,
+0xfb,0x44,0x00,0x0c,0x21,0xb8,0x20,0x02,0x42,0x00,0xd5,0x37,0x03,0x0c,0xd1,0x37,
+0x17,0x0e,0xd6,0x37,0x04,0x00,0x14,0x24,0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,
+0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,
+0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0xfc,0x85,0x84,0x24,0x00,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,
+0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,
+0x01,0x00,0x04,0x24,0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa4,0xaf,0x4d,0x01,0x00,0x0c,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,
+0x00,0x86,0x42,0x24,0x00,0x00,0x45,0x8c,0x01,0x00,0x03,0x24,0x21,0x20,0x00,0x00,
+0x00,0x00,0xa3,0xa0,0xff,0xff,0x03,0x24,0x00,0x00,0xa3,0xa2,0x00,0x00,0x22,0x92,
+0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x02,0x00,0x02,0x24,0x02,0x80,0x04,0x3c,0x00,0x00,0xa2,0xa0,
+0x38,0x15,0x83,0x24,0xc1,0x02,0x62,0x90,0x00,0x00,0xc4,0x92,0x21,0x28,0x00,0x00,
+0x00,0x00,0xc2,0xa2,0xff,0x00,0x90,0x30,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,
+0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,0xef,0xff,0x02,0x24,
+0x64,0x00,0x04,0x24,0x00,0x00,0xa2,0xa2,0xda,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xbf,0x00,0x42,0x30,0x00,0x00,0x22,0xa2,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0xda,0x18,0x00,0x0c,0x84,0x03,0x04,0x24,0xf4,0x08,0xc2,0x37,
+0x00,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0xdf,0x07,0x84,0x34,0x00,0x00,0xd0,0xa2,
+0x21,0x10,0x00,0x00,0x24,0x28,0x64,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa0,0xa2,
+0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,
+0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0xbe,0x02,0xe2,0x92,0x1f,0x00,0xa3,0x30,
+0x2b,0x10,0x62,0x00,0x0a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0xbf,0x02,0xe2,0x92,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x01,0x00,0x02,0x3c,0x25,0x10,0x62,0x00,0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,
+0x96,0x3d,0x43,0x90,0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
+0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26,0xda,0x18,0x00,0x0c,
+0xf4,0x01,0x04,0x24,0x89,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,
+0x25,0xb0,0x02,0x3c,0xaa,0x47,0x00,0x0c,0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,
+0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,
+0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
+0x38,0x15,0x63,0x24,0xbe,0x02,0x62,0x90,0xc0,0x07,0xa3,0x30,0x82,0x19,0x03,0x00,
+0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,
+0xbf,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,
+0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x02,0x22,0x00,0x08,
+0x21,0x90,0x42,0x02,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,
+0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,
+0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,0xda,0x18,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,
+0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x38,0x15,0x51,0x26,0xda,0x18,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,0x04,0x00,0x02,0x24,0x20,0x00,0x62,0x10,
+0x25,0xb0,0x02,0x3c,0x18,0x03,0x25,0x8e,0x25,0xb0,0x10,0x3c,0x46,0x52,0x00,0x0c,
+0x00,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,0x04,0x0e,0x04,0x36,
+0x1c,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,0x08,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,
+0x46,0x52,0x00,0x0c,0x10,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,
+0x14,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,0x18,0x0e,0x04,0x36,
+0x18,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x38,0x15,0x43,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x04,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,
+0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0x18,0x03,0x25,0x8e,0x00,0x00,0x00,0x00,
+0xde,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,0x5c,0x22,0x00,0x08,0x38,0x15,0x43,0x26,
+0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,
+0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
+0x6a,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,
+0x02,0x80,0x10,0x3c,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x38,0x15,0x02,0x26,
+0x08,0x03,0x46,0x90,0x25,0xb0,0x11,0x3c,0x10,0x10,0x12,0x3c,0x01,0x00,0x03,0x24,
+0x00,0x0e,0x24,0x36,0x1e,0x00,0xc3,0x10,0x10,0x10,0x45,0x36,0x46,0x52,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x04,0x0e,0x24,0x36,0x46,0x52,0x00,0x0c,0x10,0x10,0x45,0x36,
+0x08,0x0e,0x24,0x36,0x46,0x52,0x00,0x0c,0x10,0x10,0x05,0x24,0x10,0x0e,0x24,0x36,
+0x46,0x52,0x00,0x0c,0x10,0x10,0x45,0x36,0x14,0x0e,0x24,0x36,0x46,0x52,0x00,0x0c,
+0x10,0x10,0x45,0x36,0x18,0x0e,0x24,0x36,0x46,0x52,0x00,0x0c,0x10,0x10,0x45,0x36,
+0x1c,0x0e,0x24,0x36,0x46,0x52,0x00,0x0c,0x10,0x10,0x45,0x36,0x38,0x15,0x03,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,
+0x00,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xe0,0xff,0xc5,0x14,0x38,0x15,0x03,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,
+0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,
+0x01,0x00,0x10,0x3c,0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,
+0x1c,0x00,0xbf,0xaf,0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0xda,0x18,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x56,0x30,0x06,0x36,0xff,0xff,0x25,0x36,0x1a,0x00,0x04,0x24,
+0x6a,0x44,0x00,0x0c,0x02,0x80,0x11,0x3c,0x38,0x15,0x30,0x26,0xda,0x18,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x08,0x03,0x02,0x92,0x25,0xb0,0x12,0x3c,0x08,0x00,0x40,0x14,
+0x08,0x0e,0x44,0x36,0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34,0x00,0x00,0x45,0x8c,
+0xf0,0x02,0x03,0x8e,0x00,0x00,0x00,0x00,0x17,0x00,0xa3,0x10,0x38,0x15,0x22,0x26,
+0xec,0x02,0x05,0x8e,0x46,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0xf0,0x02,0x05,0x8e,
+0x46,0x52,0x00,0x0c,0x00,0x0e,0x44,0x36,0xf4,0x02,0x05,0x8e,0x46,0x52,0x00,0x0c,
+0x04,0x0e,0x44,0x36,0xf8,0x02,0x05,0x8e,0x46,0x52,0x00,0x0c,0x10,0x0e,0x44,0x36,
+0xfc,0x02,0x05,0x8e,0x46,0x52,0x00,0x0c,0x14,0x0e,0x44,0x36,0x00,0x03,0x05,0x8e,
+0x46,0x52,0x00,0x0c,0x18,0x0e,0x44,0x36,0x04,0x03,0x05,0x8e,0x46,0x52,0x00,0x0c,
+0x1c,0x0e,0x44,0x36,0x38,0x15,0x22,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x08,0x03,0x40,0xa0,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c,0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,
+0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,0xff,0xff,0x25,0x36,
+0x56,0x30,0x06,0x36,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x38,0x15,0x51,0x26,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,0x03,0x00,0x02,0x24,
+0x2c,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0xf0,0x02,0x25,0x8e,0x25,0xb0,0x10,0x3c,
+0x46,0x52,0x00,0x0c,0x00,0x0e,0x04,0x36,0xf4,0x02,0x25,0x8e,0x46,0x52,0x00,0x0c,
+0x04,0x0e,0x04,0x36,0xf8,0x02,0x25,0x8e,0x46,0x52,0x00,0x0c,0x10,0x0e,0x04,0x36,
+0xfc,0x02,0x25,0x8e,0x46,0x52,0x00,0x0c,0x14,0x0e,0x04,0x36,0x00,0x03,0x25,0x8e,
+0x46,0x52,0x00,0x0c,0x18,0x0e,0x04,0x36,0x04,0x03,0x25,0x8e,0x46,0x52,0x00,0x0c,
+0x1c,0x0e,0x04,0x36,0x0c,0x03,0x24,0x8e,0xec,0x02,0x22,0x8e,0x00,0x00,0x00,0x00,
+0x21,0x28,0x44,0x00,0x00,0xff,0xa3,0x30,0xff,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,
+0x01,0x3f,0x63,0x2c,0x24,0x10,0xa2,0x00,0x0c,0x00,0x60,0x10,0x08,0x0e,0x04,0x36,
+0x46,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x38,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x03,0x00,0x02,0x24,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,0x24,0x23,0x00,0x08,
+0x00,0x3f,0x45,0x34,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0xf0,0x02,0x25,0x8e,
+0x00,0x00,0x00,0x00,0xd2,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,0x27,0x23,0x00,0x08,
+0x38,0x15,0x43,0x26,0xd8,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,
+0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x38,0x15,0x44,0x26,0x90,0x11,0x82,0x8c,0x06,0x00,0x03,0x24,
+0x07,0x00,0x42,0x30,0xa3,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x24,0x82,0x8c,
+0xfc,0x23,0x83,0x8c,0x02,0x11,0x02,0x00,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,
+0x7f,0x00,0x42,0x30,0x2b,0x20,0x43,0x00,0x21,0xa0,0x60,0x00,0x0a,0xa0,0x44,0x00,
+0x38,0x15,0x42,0x8e,0x38,0x15,0x44,0x26,0x40,0x00,0x03,0x24,0xcc,0x00,0x42,0x30,
+0x08,0x03,0x93,0x90,0x8c,0x00,0x43,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x08,0x3c,
+0x4c,0x00,0x03,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
+0x07,0x00,0x40,0x10,0x38,0x15,0x45,0x26,0x38,0x15,0x42,0x92,0x00,0x00,0x00,0x00,
+0x82,0x11,0x02,0x00,0x2f,0x00,0x40,0x10,0x00,0x0e,0x05,0x35,0x38,0x15,0x45,0x26,
+0x08,0x03,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x40,0x14,
+0x38,0x15,0x42,0x26,0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,0x00,0x00,0x44,0x8c,
+0x0d,0x00,0x03,0x24,0x80,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,
+0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x45,0x00,0x02,0x24,0x43,0x00,0x03,0x24,
+0x21,0x03,0xa2,0xa0,0x22,0x03,0xa3,0xa0,0x38,0x15,0x42,0x26,0x80,0x11,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x45,0x8e,
+0x44,0x00,0x02,0x24,0xcc,0x00,0xa3,0x30,0x37,0x00,0x62,0x10,0x38,0x15,0x44,0x26,
+0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x63,0x00,0x40,0x10,
+0x10,0x0e,0x07,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x0e,0x02,0x35,0x04,0x0e,0x03,0x35,0x00,0x00,0x44,0x8c,
+0x00,0x00,0xa5,0x8c,0x00,0x00,0x66,0x8c,0x02,0x80,0x02,0x3c,0x38,0x15,0x49,0x24,
+0xec,0x02,0x24,0xad,0xf0,0x02,0x25,0xad,0xf4,0x02,0x26,0xad,0x14,0x0e,0x04,0x35,
+0x02,0x80,0x02,0x3c,0x18,0x0e,0x05,0x35,0x00,0x00,0xe7,0x8c,0x1c,0x0e,0x06,0x35,
+0x00,0x00,0x83,0x8c,0x96,0x3d,0x4a,0x90,0x00,0x00,0xa2,0x8c,0x00,0x00,0xc4,0x8c,
+0xf8,0x02,0x27,0xad,0x00,0x03,0x22,0xad,0x22,0x00,0x02,0x24,0xfc,0x02,0x23,0xad,
+0x5f,0x00,0x42,0x11,0x04,0x03,0x24,0xad,0x92,0x00,0x02,0x24,0x5d,0x00,0x42,0x11,
+0x0d,0x08,0x02,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x38,0x15,0x42,0x8e,0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x40,0x00,0x42,0x34,
+0x63,0x23,0x00,0x08,0x38,0x15,0x42,0xae,0xfc,0x23,0x83,0x8c,0xff,0xff,0x02,0x34,
+0xc7,0xff,0x62,0x10,0x02,0x11,0x05,0x00,0x03,0x00,0x45,0x30,0x01,0x00,0x03,0x24,
+0xc3,0xff,0xa3,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0xbd,0xff,0x60,0x10,0x03,0x00,0x02,0x24,
+0x71,0x00,0x62,0x12,0x04,0x00,0x62,0x2a,0x53,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x76,0x00,0x60,0x12,0x00,0x00,0x00,0x00,0xb5,0xff,0x65,0x16,0x00,0x00,0x00,0x00,
+0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x62,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x23,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,
+0x54,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xb0,0x22,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x88,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x1b,0x00,0x62,0x12,0x04,0x00,0x02,0x24,
+0x19,0x00,0x62,0x12,0x38,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x57,0x23,0x00,0x08,
+0x08,0x03,0x62,0xa0,0x80,0x11,0x82,0x8c,0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,
+0x50,0x23,0x00,0x08,0x7f,0x00,0x54,0x30,0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24,
+0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24,
+0x21,0x03,0xa2,0xa0,0x76,0x23,0x00,0x08,0x22,0x03,0xa3,0xa0,0x00,0x00,0xe3,0x8c,
+0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x9a,0xff,0x62,0x14,0x00,0x00,0x00,0x00,
+0x64,0x23,0x00,0x08,0x38,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c,0x01,0x00,0x11,0x3c,
+0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x6a,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x26,0x36,
+0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x38,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x57,0x23,0x00,0x08,0x08,0x03,0x62,0xa0,
+0x0d,0x08,0x02,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30,
+0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0x9e,0xff,0x40,0x14,0x01,0x00,0x65,0x24,
+0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,0x25,0x10,0x44,0x00,
+0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,0x1c,0x03,0x23,0xad,
+0xb5,0x23,0x00,0x08,0x18,0x03,0x22,0xad,0x04,0x00,0x02,0x24,0x11,0x00,0x62,0x12,
+0xff,0x00,0x02,0x24,0x62,0xff,0x62,0x16,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0a,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x6c,0x22,0x00,0x0c,0x00,0x00,0x00,0x00,0x88,0x23,0x00,0x08,
+0x00,0x00,0x00,0x00,0x21,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,
+0xf8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x88,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x03,0x82,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x82,0x02,0x9c,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xed,0x22,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x88,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0xe6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x25,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x8e,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0xed,0x22,0x00,0x0c,0x00,0x00,0x00,0x00,0x88,0x23,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x38,0x15,0x05,0x25,0x80,0x11,0xa4,0x8c,
+0xea,0x02,0xa3,0x90,0x02,0x11,0x04,0x00,0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,
+0x25,0xb0,0x07,0x3c,0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x20,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x30,0x19,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10,
+0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x38,0x15,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,
+0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,
+0x20,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10,
+0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x38,0x15,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,
+0x3f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x44,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,
+0x00,0x00,0x00,0x00,0xe7,0xff,0x44,0x10,0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34,
+0xd7,0x02,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,
+0xc0,0xff,0x44,0x10,0x10,0x00,0x02,0x24,0x87,0x0c,0xe3,0x34,0xd7,0x02,0xa4,0xa0,
+0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0xc7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x04,0x25,
+0xd7,0x02,0x82,0x90,0x02,0x00,0x03,0x24,0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0xd7,0x02,0x83,0xa0,0x00,0x00,0x40,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0xb4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x04,0x25,0xd7,0x02,0x82,0x90,
+0x02,0x00,0x03,0x24,0xaf,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xd7,0x02,0x83,0xa0,0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0xff,0xff,0x8d,0x30,0x00,0x60,0x0f,0x40,0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c,0x38,0x15,0xce,0x24,0x82,0x0b,0xc2,0x91,
+0x00,0x00,0x00,0x00,0x1d,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34,
+0x80,0xff,0x02,0x24,0x00,0x00,0x82,0xa0,0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34,
+0xd6,0x01,0x66,0x34,0xda,0x01,0x67,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94,
+0x00,0x00,0xc9,0x94,0x00,0x00,0xeb,0x94,0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95,
+0xb0,0xfe,0xa2,0x25,0xff,0xff,0x4d,0x30,0x80,0x0b,0xc4,0xa5,0x00,0x00,0xa0,0xa4,
+0x78,0x0b,0xc8,0xa5,0x00,0x00,0xc0,0xa4,0x7a,0x0b,0xc9,0xa5,0x00,0x00,0xe0,0xa4,
+0x7c,0x0b,0xcb,0xa5,0x00,0x00,0x60,0xa4,0x00,0x00,0x4d,0xa5,0x7e,0x0b,0xcc,0xa5,
+0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c,
+0x0a,0x00,0x45,0x34,0x63,0x00,0x03,0x24,0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90,
+0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x10,0x38,0x15,0xc2,0x24,0x64,0x00,0x02,0x24,
+0xff,0xff,0x42,0x24,0xff,0xff,0x42,0x30,0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24,
+0xff,0xff,0x62,0x24,0xff,0xff,0x43,0x30,0xf4,0xff,0x64,0x14,0x38,0x15,0xc2,0x24,
+0x80,0x0b,0x48,0x94,0x7e,0x0b,0x47,0x94,0x78,0x0b,0x49,0x94,0x7a,0x0b,0x4a,0x94,
+0x7c,0x0b,0x4b,0x94,0x25,0xb0,0x03,0x3c,0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34,
+0xd2,0x01,0x64,0x34,0xd6,0x01,0x65,0x34,0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34,
+0x00,0x00,0x48,0xa4,0x00,0x00,0x89,0xa4,0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4,
+0x00,0x00,0x67,0xa4,0x00,0x00,0x80,0xa1,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x08,0x00,0x83,0x34,0x00,0x00,0x62,0x94,
+0x00,0x00,0x00,0x00,0x00,0x14,0x02,0x00,0x03,0x14,0x02,0x00,0x1a,0x00,0x40,0x04,
+0x60,0x02,0x85,0x34,0x00,0x00,0xa3,0x90,0x05,0x00,0x02,0x24,0x00,0x03,0x8b,0x34,
+0xff,0x00,0x63,0x30,0x04,0x03,0x8c,0x34,0xbd,0x00,0x8a,0x34,0x03,0x00,0x86,0x34,
+0x40,0x00,0x85,0x34,0xfc,0x77,0x09,0x24,0x11,0x00,0x62,0x10,0x23,0x00,0x84,0x34,
+0x00,0x00,0xc2,0x90,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x00,0x00,0xc2,0xa0,
+0x22,0x00,0x02,0x24,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x82,0xa0,
+0xfc,0x37,0x02,0x24,0x00,0x00,0xa9,0xa4,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa9,0xa4,
+0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x42,0x91,0x00,0x00,0x00,0x00,
+0x08,0x00,0x42,0x34,0x00,0x00,0x42,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,
+0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c,0x38,0x15,0x66,0x26,0x04,0x00,0x42,0x34,
+0x00,0x00,0x47,0x8c,0x0c,0x0b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0x9e,0x3d,0x64,0x90,
+0x08,0x0b,0xc8,0x8c,0x02,0x80,0x02,0x3c,0xc0,0x3d,0x49,0x90,0x25,0xb0,0x0a,0x3c,
+0x25,0x90,0xa7,0x00,0xb0,0x03,0x42,0x35,0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,
+0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,
+0x00,0x00,0x72,0xac,0x00,0x00,0xa4,0xac,0x8d,0x04,0x22,0x11,0x0c,0x0b,0xd2,0xac,
+0x38,0x15,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
+0x01,0x00,0x42,0x30,0x31,0x00,0x40,0x10,0x02,0x80,0x14,0x3c,0x25,0xb0,0x0b,0x3c,
+0x04,0x00,0x63,0x35,0x00,0x00,0x6a,0x8c,0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x70,0x04,0x40,0x14,0x01,0x00,0x03,0x24,0x92,0x3d,0x82,0x92,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0xcd,0x04,0x43,0x10,0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35,
+0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35,0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34,
+0x00,0x00,0x43,0xa4,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac,
+0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c,0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30,
+0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01,0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35,
+0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac,
+0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0,0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10,
+0x02,0x00,0x65,0x35,0x84,0xff,0x02,0x24,0x00,0x00,0x42,0xa1,0x02,0x00,0x65,0x35,
+0x00,0x00,0xa3,0x94,0x0c,0x0b,0x04,0x8e,0xff,0xbf,0x02,0x24,0x24,0x18,0x62,0x00,
+0x01,0x00,0x84,0x38,0x00,0x00,0xa3,0xa4,0x0c,0x0b,0x04,0xae,0x38,0x15,0x66,0x26,
+0x08,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x24,0x28,0x52,0x00,0x04,0x00,0xa3,0x30,
+0x09,0x00,0x60,0x10,0x08,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,
+0x04,0x00,0x04,0x24,0x04,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,
+0x0c,0x0b,0xc2,0xac,0x08,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x10,0x00,0xa2,0x30,
+0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,
+0x10,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x20,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,
+0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x20,0x00,0xa2,0x30,
+0x06,0x00,0x40,0x10,0x40,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x20,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x40,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,
+0x80,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,
+0x0c,0x0b,0xc2,0xac,0x80,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x00,0x01,0xa2,0x30,
+0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,
+0x00,0x01,0xa2,0x30,0x06,0x00,0x40,0x10,0x00,0x02,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x00,0x02,0xa2,0x30,
+0x06,0x00,0x40,0x10,0x00,0x04,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x02,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x00,0x04,0xa2,0x30,0x05,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,
+0x0c,0x0b,0xc2,0xac,0x00,0x08,0xa2,0x30,0x36,0x00,0x40,0x10,0x2a,0xb0,0x03,0x3c,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,
+0x00,0x80,0x42,0x31,0x17,0x04,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
+0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x74,0x24,0xc2,0x90,
+0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,
+0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,
+0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,
+0x2c,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0xc0,0x24,0x03,0xae,0x21,0x20,0x00,0x00,0x74,0x24,0x0a,0xa2,
+0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x08,0x0b,0x05,0x8e,
+0x02,0x80,0x06,0x3c,0x84,0x3e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,
+0x25,0xb0,0x02,0x3c,0x04,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x84,0x3e,0xc4,0xac,0x08,0x0b,0x05,0xae,
+0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,
+0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x52,0x00,0x00,0x10,0x42,0x30,0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,
+0x08,0x00,0x43,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,
+0x2c,0x00,0x82,0x10,0x00,0x80,0x42,0x31,0xdd,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x7c,0x24,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,
+0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,
+0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x38,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x44,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xd8,0x24,0x03,0xae,0x01,0x00,0x04,0x24,
+0x7c,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x08,0x0b,0x05,0x8e,0x02,0x80,0x06,0x3c,0x84,0x3e,0xc4,0x8c,0xff,0xc7,0x02,0x24,
+0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x84,0x3e,0xc4,0xac,
+0x08,0x0b,0x05,0xae,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x10,0x42,0x38,0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,
+0x2a,0xb0,0x02,0x3c,0x04,0x00,0x43,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,
+0xff,0x00,0x44,0x31,0xc1,0x03,0x82,0x10,0x00,0x80,0x42,0x31,0xa3,0x03,0x40,0x14,
+0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,
+0xff,0x00,0x02,0x24,0x78,0x24,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,
+0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,
+0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,
+0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x38,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xcc,0x24,0x03,0xae,
+0x01,0x00,0x04,0x24,0x78,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x08,0x0b,0x05,0x8e,0x02,0x80,0x06,0x3c,0x84,0x3e,0xc4,0x8c,
+0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,
+0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,
+0x84,0x3e,0xc4,0xac,0x08,0x0b,0x05,0xae,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26,
+0x08,0x0b,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,
+0x59,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x0c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,
+0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x75,0x03,0x87,0x10,0x00,0x80,0x42,0x31,
+0x24,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x22,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0f,0x00,0x87,0x10,0x38,0x15,0x62,0x26,
+0x54,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x09,0x00,0x83,0x10,0x38,0x15,0x62,0x26,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,
+0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,
+0x54,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x54,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0xdb,0x26,0x00,0x08,
+0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,
+0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x54,0x24,0x0a,0xa2,
+0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0x94,0x3e,0x47,0x91,0x02,0x80,0x09,0x3c,
+0x84,0x3e,0x25,0x8d,0x08,0x0b,0x06,0x8e,0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,
+0x25,0x38,0xe2,0x00,0x00,0x80,0x03,0x35,0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,
+0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,
+0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,
+0x00,0x00,0x66,0xac,0x84,0x3e,0x25,0xad,0x94,0x3e,0x47,0xa1,0x08,0x0b,0x06,0xae,
+0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,
+0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x01,0x00,0x03,0x3c,
+0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,
+0x2a,0xb0,0x06,0x3c,0x10,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,
+0xff,0x00,0x44,0x31,0x20,0x03,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,
+0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,
+0x58,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
+0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x58,0x24,0xe3,0xa0,
+0x38,0x15,0x62,0x26,0x58,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x3a,0x27,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x22,0x00,0x82,0x10,0x38,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0x58,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x09,0x3c,0x94,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c,0x84,0x3e,0x05,0x8d,
+0x08,0x0b,0x06,0x8e,0x01,0x00,0x02,0x3c,0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,
+0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,
+0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0x84,0x3e,0x05,0xad,0x94,0x3e,0x27,0xa1,
+0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x01,0x00,0x04,0x3c,
+0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,
+0x02,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,
+0x2a,0xb0,0x06,0x3c,0x14,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,
+0xff,0x00,0x44,0x31,0xe4,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,
+0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,
+0x5c,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
+0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x5c,0x24,0xe3,0xa0,
+0x38,0x15,0x62,0x26,0x5c,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x96,0x27,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x08,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x5c,0x24,0x0a,0xa2,0x9c,0x24,0x03,0xae,
+0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x0a,0x3c,0x94,0x3e,0x47,0x91,0x02,0x80,0x09,0x3c,0x84,0x3e,0x25,0x8d,
+0x08,0x0b,0x06,0x8e,0x06,0x00,0x02,0x3c,0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
+0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,
+0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,
+0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,
+0x84,0x3e,0x25,0xad,0x94,0x3e,0x47,0xa1,0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad,
+0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x04,0x00,0x03,0x3c,
+0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,
+0x25,0xb0,0x03,0x3c,0xb0,0x03,0x62,0x34,0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,
+0x18,0x00,0x06,0x35,0x00,0x00,0xca,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,
+0x70,0x02,0x87,0x10,0x04,0x00,0x02,0x24,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,
+0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,
+0xff,0x00,0x02,0x24,0x43,0x00,0x06,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x60,0x24,0xa4,0xa0,
+0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
+0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
+0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x60,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,
+0x60,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,
+0x00,0x00,0x4a,0xac,0xf9,0x27,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,
+0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,
+0x08,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0x9c,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0x60,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
+0x94,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c,0x84,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e,
+0x06,0x00,0x02,0x3c,0x10,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
+0x00,0x01,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,
+0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,
+0x84,0x3e,0x05,0xad,0x94,0x3e,0x27,0xa1,0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26,
+0x0c,0x0b,0x43,0x8c,0x04,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,
+0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
+0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,
+0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x19,0x02,0x87,0x10,
+0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
+0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
+0x44,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
+0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x64,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,
+0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
+0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
+0xff,0x00,0x44,0x30,0x64,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x64,0x24,0x43,0x90,
+0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,
+0x54,0x28,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,
+0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x64,0x24,0x0a,0xa2,0xa8,0x24,0x03,0xae,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0x94,0x3e,0x47,0x91,
+0x02,0x80,0x09,0x3c,0x84,0x3e,0x25,0x8d,0x08,0x0b,0x06,0x8e,0x18,0x00,0x02,0x3c,
+0x08,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,
+0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,
+0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,
+0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0x84,0x3e,0x25,0xad,0x94,0x3e,0x47,0xa1,
+0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,
+0x08,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,
+0x08,0x0b,0xa2,0x8c,0x10,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,
+0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,
+0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,0x20,0x00,0x03,0x35,0x00,0x00,0x6a,0x8c,
+0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xbb,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,
+0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
+0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x45,0x00,0x06,0x35,
+0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,
+0x38,0x15,0x62,0x26,0x70,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,
+0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,
+0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,
+0x70,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x70,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0xb7,0x28,0x00,0x08,
+0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,
+0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xa8,0x24,0x03,0xae,
+0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x70,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0x94,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c,
+0x84,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e,0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,
+0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,
+0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
+0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0x84,0x3e,0x05,0xad,0x94,0x3e,0x27,0xa1,
+0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x10,0x00,0x04,0x3c,
+0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,
+0x20,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,
+0x2a,0xb0,0x06,0x3c,0x24,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,
+0xff,0x00,0x44,0x31,0x63,0x01,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,
+0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,
+0x68,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
+0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x68,0x24,0xe3,0xa0,
+0x38,0x15,0x62,0x26,0x68,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x12,0x29,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x68,0x24,0x0a,0xa2,0xb4,0x24,0x03,0xae,
+0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x0a,0x3c,0x94,0x3e,0x47,0x91,0x02,0x80,0x09,0x3c,0x84,0x3e,0x25,0x8d,
+0x08,0x0b,0x06,0x8e,0x60,0x00,0x02,0x3c,0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
+0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,
+0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,
+0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,
+0x84,0x3e,0x25,0xad,0x94,0x3e,0x47,0xa1,0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad,
+0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x40,0x00,0x03,0x3c,
+0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,
+0x38,0x15,0x70,0x26,0x25,0xb0,0x02,0x3c,0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x51,0xac,0x28,0x00,0xe3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x06,0x24,
+0xff,0x00,0x44,0x31,0xd0,0x00,0x86,0x10,0x25,0xbd,0x02,0x3c,0x00,0x80,0x42,0x31,
+0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x86,0x10,0x38,0x15,0x62,0x26,
+0x6c,0x24,0xa4,0xa0,0x00,0x00,0xe2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x21,0x30,0xa0,0x00,0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,
+0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x6c,0x24,0xc3,0xa0,
+0x38,0x15,0x62,0x26,0x6c,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x76,0x29,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x38,0x15,0x70,0x26,
+0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xb4,0x24,0x03,0xae,0x06,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0x6c,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x09,0x3c,0x94,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c,0x84,0x3e,0x05,0x8d,
+0x08,0x0b,0x06,0x8e,0x60,0x00,0x02,0x3c,0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
+0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
+0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
+0x00,0x00,0x66,0xac,0x84,0x3e,0x05,0xad,0x94,0x3e,0x27,0xa1,0x08,0x0b,0x06,0xae,
+0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x0c,0x0b,0x43,0xac,0x38,0x15,0x70,0x26,0x08,0x0b,0x06,0x8e,0x00,0x04,0x11,0x3c,
+0x24,0x10,0xd2,0x00,0x24,0x10,0x51,0x00,0x57,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x24,0x28,0xd2,0x00,0x00,0x08,0x04,0x3c,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,
+0x80,0x00,0x07,0x3c,0x0c,0x0b,0x03,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac,0x0c,0x0b,0x03,0xae,0x80,0x00,0x07,0x3c,
+0x24,0x10,0xa7,0x00,0x21,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x0b,0x03,0x8e,
+0x25,0xb0,0x08,0x3c,0xb0,0x03,0x09,0x35,0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,
+0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,
+0xc0,0x18,0x03,0x00,0xf0,0x07,0x63,0x30,0xbc,0x25,0x05,0x8e,0x21,0x18,0x64,0x00,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x60,0x00,0x65,0x10,0xc0,0x25,0x03,0xae,
+0x02,0x80,0x05,0x3c,0x84,0x3e,0xa3,0x8c,0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,
+0x00,0x08,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,
+0x84,0x3e,0xa3,0xac,0x08,0x0b,0x04,0xae,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,
+0x80,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x66,0x26,
+0x08,0x0b,0xc3,0x8c,0x00,0x01,0x04,0x3c,0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,
+0x06,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x0c,0x0b,0xc3,0x8c,0xb0,0x03,0x42,0x34,
+0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac,0x0c,0x0b,0xc3,0xac,0x00,0x02,0x04,0x3c,
+0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x0c,0x0b,0xc2,0x8c,
+0xb0,0x03,0x63,0x34,0x26,0x10,0x44,0x00,0x0c,0x0b,0xc2,0xac,0x00,0x00,0x64,0xac,
+0x92,0x3d,0x82,0x92,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x21,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x30,0x00,0xbd,0x27,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,
+0xaf,0x25,0x00,0x08,0x0c,0x0b,0x02,0xae,0x43,0x47,0x00,0x0c,0x07,0x00,0x04,0x24,
+0x0c,0x0b,0x03,0x8e,0x08,0x0b,0x06,0x8e,0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xa4,0x29,0x00,0x08,0x0c,0x0b,0x03,0xae,
+0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0x70,0xfb,0x60,0x10,
+0x00,0x00,0x00,0x00,0x43,0x47,0x00,0x0c,0x07,0x00,0x04,0x24,0x79,0x25,0x00,0x08,
+0x38,0x15,0x70,0x26,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x2d,0x25,0x00,0x08,
+0x30,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0x0d,0x26,0x00,0x08,0xff,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0x4a,0x26,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
+0x87,0x26,0x00,0x08,0xff,0x00,0x02,0x24,0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x99,0x29,0x00,0x08,0x38,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,
+0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xcf,0x29,0x00,0x08,0x38,0x15,0x62,0x26,
+0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,
+0x05,0x27,0x00,0x08,0x0c,0x0b,0x62,0xac,0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x5e,0x27,0x00,0x08,0x38,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,
+0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x38,0x15,0x63,0x26,
+0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,0xa7,0x26,0x00,0x08,
+0x0c,0x0b,0x62,0xac,0x90,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0x1c,0x28,0x00,0x08,
+0x38,0x15,0x62,0x26,0x03,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x7b,0x28,0x00,0x08,0x38,0x15,0x62,0x26,0x00,0x00,0x40,0xac,0xda,0x28,0x00,0x08,
+0x38,0x15,0x62,0x26,0x02,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x39,0x29,0x00,0x08,0x38,0x15,0x62,0x26,0x05,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0xbd,0x27,0x00,0x08,0x38,0x15,0x62,0x26,0x01,0x00,0x04,0x24,
+0x17,0x00,0x05,0x24,0x21,0x30,0x00,0x00,0xb0,0x08,0x00,0x0c,0x21,0x38,0x00,0x00,
+0x53,0xfb,0x40,0x10,0x38,0x15,0x66,0x26,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x38,0xb0,0x25,0x00,0x08,0x0c,0x0b,0x02,0xae,0x25,0xb0,0x0d,0x3c,
+0x01,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35,0x8c,0xa9,0x42,0x24,0x02,0x80,0x03,0x3c,
+0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac,0x38,0x15,0x6a,0x24,0x0a,0x00,0x02,0x35,
+0x00,0x00,0x44,0x94,0x16,0x0b,0x43,0x95,0x14,0x0b,0x4b,0x95,0x25,0x18,0x64,0x00,
+0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01,0x02,0x00,0x42,0x30,0x53,0x00,0x40,0x10,
+0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24,0xc0,0x03,0xa3,0x35,0x00,0x00,0x62,0xac,
+0x16,0x0b,0x44,0xa5,0x24,0x38,0x8b,0x01,0x04,0x00,0xe2,0x30,0x0a,0x00,0x40,0x10,
+0x08,0x00,0xe2,0x30,0x16,0x0b,0x43,0x95,0x0c,0x00,0x04,0x35,0xc0,0x03,0xa5,0x35,
+0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c,0x00,0x00,0xa2,0xac,
+0x16,0x0b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x10,0x00,0xe2,0x30,
+0x16,0x0b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x08,0x00,0x03,0x24,0x08,0x00,0x42,0x38,
+0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,0x10,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,
+0x20,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x10,0x00,0x03,0x24,
+0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,0x20,0x00,0xe2,0x30,
+0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95,0xc0,0x03,0xa4,0x35,
+0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,
+0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10,0x24,0x10,0x8b,0x01,0x02,0x80,0x09,0x3c,
+0x16,0x0b,0x46,0x95,0x84,0x3e,0x25,0x8d,0x10,0x00,0x02,0x3c,0x7f,0xff,0x04,0x24,
+0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00,0x80,0x00,0xc6,0x38,0xb0,0x03,0xa7,0x35,
+0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
+0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac,0x16,0x0b,0x46,0xa5,0x84,0x3e,0x25,0xad,
+0x00,0x00,0x04,0xa5,0x14,0x0b,0x44,0xa5,0x24,0x10,0x8b,0x01,0x00,0x30,0x42,0x30,
+0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x16,0x0b,0x42,0x95,0x00,0x00,0x00,0x00,
+0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,0x16,0x0b,0x42,0xa5,0x02,0x80,0x02,0x3c,
+0x92,0x3d,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30,0x05,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x79,0x2a,0x00,0x08,
+0x16,0x0b,0x43,0xa5,0x2d,0x25,0x00,0x08,0x00,0x00,0x00,0x00,0xf8,0xff,0xbd,0x27,
+0x25,0xb0,0x05,0x3c,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x18,0x03,0xa6,0x34,
+0x00,0x00,0xc3,0x8c,0x1c,0x03,0xa2,0x34,0x00,0x00,0x43,0xac,0x00,0x40,0x07,0x40,
+0x00,0x68,0x09,0x40,0x00,0x70,0x02,0x40,0x00,0x60,0x08,0x40,0x01,0x80,0x02,0x3c,
+0x2c,0xab,0x42,0x24,0x00,0x00,0xc2,0xac,0x80,0x00,0x87,0x8c,0x7c,0x02,0xa2,0x34,
+0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34,0x00,0x00,0x47,0xac,0x00,0x00,0x69,0xac,
+0x00,0x00,0xc8,0xac,0x74,0x00,0x83,0x8c,0x8c,0x02,0xa2,0x34,0x90,0x02,0xa7,0x34,
+0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,0x94,0x02,0xa8,0x34,0x98,0x02,0xa9,0x34,
+0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,0x9c,0x02,0xa6,0x34,0xa0,0x02,0xa7,0x34,
+0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,0xa4,0x02,0xa8,0x34,0xa8,0x02,0xaa,0x34,
+0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,0xac,0x02,0xa9,0x34,0xb0,0x02,0xab,0x34,
+0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,0xb4,0x02,0xa6,0x34,0xb8,0x02,0xac,0x34,
+0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,0xbc,0x02,0xa7,0x34,0xc0,0x02,0xad,0x34,
+0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,0xc4,0x02,0xa8,0x34,0xc8,0x02,0xae,0x34,
+0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,0xcc,0x02,0xaa,0x34,0xd0,0x02,0xaf,0x34,
+0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,0xd4,0x02,0xa9,0x34,0xd8,0x02,0xb0,0x34,
+0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,0x70,0x02,0xab,0x34,0x74,0x02,0xb1,0x34,
+0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,0x78,0x02,0xa5,0x34,0x00,0x00,0x83,0xad,
+0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xac,0x38,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,0x3c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xad,
+0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xad,0x48,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,0x4c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,
+0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xad,0x58,0x00,0x83,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0x5c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0xac,0x31,0x2b,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,
+0xcc,0xac,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,
+0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,
+0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,
+0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,
+0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,
+0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,
+0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,
+0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,
+0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,0x00,0x68,0x1a,0x40,
+0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,
+0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,0x00,0x00,0x00,0x00,
+0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,
+0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,
+0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,
+0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,
+0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,
+0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,
+0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,
+0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,
+0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,0xcb,0x2a,0x00,0x08,
+0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x20,0x03,0x08,0x35,
+0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,0x00,0x04,0x5b,0x33,0x0a,0x00,0x60,0x13,
+0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0x60,0x95,0x08,0x25,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xaf,
+0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x5b,0x33,0x25,0xb0,0x08,0x3c,
+0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x06,0x00,0x60,0x13,
+0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0x8c,0xa9,0x08,0x25,0x00,0x00,0x00,0x00,
+0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x1a,0x3c,0x84,0x3e,0x5a,0x27,
+0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,0x30,0x03,0x08,0x35,0x00,0x00,0x00,0x00,
+0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x08,0xec,0x9b,0x27,
+0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,
+0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,
+0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,
+0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,
+0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,
+0x1a,0x2c,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,
+0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x08,0x00,0x5b,0xaf,0xfc,0xef,0x9d,0x27,
+0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,0x21,0x00,0x40,0x11,0x00,0x00,0x00,0x00,
+0x02,0x80,0x08,0x3c,0xe4,0x3d,0x08,0x25,0x21,0x48,0x00,0x00,0x21,0x58,0x00,0x00,
+0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,0x24,0x70,0x4b,0x01,0x14,0x00,0xc0,0x11,
+0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,0x04,0x00,0x44,0xa3,0x26,0x50,0x4b,0x01,
+0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,0x21,0x80,0x08,0x02,0x00,0x00,0x10,0x8e,
+0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,
+0x94,0xaf,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x02,0x80,0x1a,0x3c,0x84,0x3e,0x5a,0x27,0xe1,0xff,0x00,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,0xdd,0x2b,0x00,0x08,0x00,0x00,0x00,0x00,
+0x02,0x80,0x1b,0x3c,0x84,0x3e,0x7b,0x27,0x21,0x60,0x00,0x00,0x04,0x00,0x6c,0xa7,
+0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,0xf8,0xff,0x5a,0x27,0x00,0x00,0x5a,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,0x84,0x00,0x44,0x8f,0x00,0x00,0x00,0x00,
+0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x41,0x8f,0xfc,0x03,0x50,0x7b,
+0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,0xfc,0x00,0x46,0x7b,0x3c,0x01,0x48,0x7b,
+0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x4a,0x7b,0xbc,0x01,0x4c,0x7b,
+0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,0x7c,0x02,0x52,0x7b,0xbc,0x02,0x54,0x7b,
+0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,0x7c,0x03,0x5c,0x7b,0xbc,0x03,0x5e,0x7b,
+0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x10,0x00,0x00,0x42,
+0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,
+0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,
+0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,
+0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,
+0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x95,0xac,0x58,0x00,0x96,0xac,
+0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,
+0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x74,0x00,0x9f,0xac,0x78,0x00,0x88,0xac,
+0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,
+0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,
+0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,
+0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,
+0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,
+0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,
+0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,
+0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,
+0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,
+0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,
+0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,
+0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,
+0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x96,0xac,0x60,0x00,0x98,0xac,
+0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,
+0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0x84,0x00,0x80,0xac,
+0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,
+0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,
+0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,
+0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,
+0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,
+0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,
+0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,
+0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x50,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27,
+0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24,
+0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c,
+0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
+0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27,
+0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35,
+0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c,
+0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34,
+0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,
+0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c,
+0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c,
+0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c,
+0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84,
+0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c,
+0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00,
+0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c,
+0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0x90,0x3d,0xa5,0x24,0xff,0xff,0xa5,0x30,
+0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00,
+0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac,
+0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0xe3,0x53,0x00,0x08,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00,
+0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00,
+0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28,
+0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,
+0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00,
+0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf,
+0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x38,0x15,0x31,0x26,0x50,0x25,0x30,0x96,
+0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c,
+0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26,
+0x00,0x00,0x43,0xac,0x6c,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02,
+0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0x50,0x25,0x22,0x8e,
+0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24,
+0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x78,0x08,0x00,0x08,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00,
+0x38,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90,
+0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x50,0x0c,0x82,0xa0,0x1e,0x00,0xa3,0x90,
+0x1e,0x00,0xe6,0x28,0x6e,0x0c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
+0x8c,0x0c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0xaa,0x0c,0x83,0xa0,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24,
+0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04,
+0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0,
+0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0,
+0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24,
+0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24,
+0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00,
+0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34,
+0xa8,0x08,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24,
+0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x38,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xc2,0xac,
+0x40,0x08,0x02,0x24,0x90,0x0b,0xc3,0xac,0x9c,0x0b,0xc2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0xa0,0x0b,0xc3,0xac,0xa4,0x0b,0xc2,0xac,0x10,0x08,0x03,0x24,
+0x20,0x08,0x02,0x24,0xa8,0x0b,0xc3,0xac,0xac,0x0b,0xc2,0xac,0x24,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xb0,0x0b,0xc3,0xac,0xb4,0x0b,0xc2,0xac,0x50,0x0c,0x03,0x24,
+0x54,0x0c,0x02,0x24,0xb8,0x0b,0xc3,0xac,0xbc,0x0b,0xc2,0xac,0x14,0x0c,0x03,0x24,
+0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xc0,0x0b,0xc3,0xac,0xc4,0x0b,0xc2,0xac,
+0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xc2,0xac,
+0x98,0x0b,0xc5,0xac,0xc8,0x0b,0xc3,0xac,0x89,0x0b,0xc0,0xa0,0x94,0x0b,0xc5,0xac,
+0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
+0xd0,0x0b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x38,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xc2,0xac,
+0x44,0x08,0x02,0x24,0x90,0x0b,0xc3,0xac,0x9c,0x0b,0xc2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0xa0,0x0b,0xc3,0xac,0xa4,0x0b,0xc2,0xac,0x14,0x08,0x03,0x24,
+0x28,0x08,0x02,0x24,0xa8,0x0b,0xc3,0xac,0xac,0x0b,0xc2,0xac,0x2c,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xb0,0x0b,0xc3,0xac,0xb4,0x0b,0xc2,0xac,0x58,0x0c,0x03,0x24,
+0x5c,0x0c,0x02,0x24,0xb8,0x0b,0xc3,0xac,0xbc,0x0b,0xc2,0xac,0x1c,0x0c,0x03,0x24,
+0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xc0,0x0b,0xc3,0xac,0xc4,0x0b,0xc2,0xac,
+0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xc2,0xac,
+0x89,0x0b,0xc7,0xa0,0x98,0x0b,0xc5,0xac,0xc8,0x0b,0xc3,0xac,0x94,0x0b,0xc5,0xac,
+0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
+0xd0,0x0b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xac,0x08,0x03,0x24,
+0xd0,0x0b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x8c,0x0b,0x43,0xac,
+0x4c,0x08,0x03,0x24,0x90,0x0b,0x44,0xac,0x9c,0x0b,0x43,0xac,0x7c,0x08,0x04,0x24,
+0x0c,0x08,0x03,0x24,0xa0,0x0b,0x44,0xac,0xa4,0x0b,0x43,0xac,0x1c,0x08,0x04,0x24,
+0x38,0x08,0x03,0x24,0xa8,0x0b,0x44,0xac,0xac,0x0b,0x43,0xac,0x3c,0x08,0x04,0x24,
+0x5c,0x08,0x03,0x24,0xb0,0x0b,0x44,0xac,0xb4,0x0b,0x43,0xac,0x68,0x0c,0x04,0x24,
+0x6c,0x0c,0x03,0x24,0xb8,0x0b,0x44,0xac,0xbc,0x0b,0x43,0xac,0x2c,0x0c,0x04,0x24,
+0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xc0,0x0b,0x44,0xac,0xc4,0x0b,0x43,0xac,
+0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x89,0x0b,0x47,0xa0,0x98,0x0b,0x45,0xac,
+0xc8,0x0b,0x44,0xac,0xcc,0x0b,0x43,0xac,0x08,0x00,0xe0,0x03,0x94,0x0b,0x45,0xac,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xd0,0x0b,0x43,0xac,
+0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x8c,0x0b,0x43,0xac,0x48,0x08,0x03,0x24,
+0x90,0x0b,0x44,0xac,0x9c,0x0b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24,
+0xa0,0x0b,0x44,0xac,0xa4,0x0b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24,
+0xa8,0x0b,0x44,0xac,0xac,0x0b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24,
+0xb0,0x0b,0x44,0xac,0xb4,0x0b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24,
+0xb8,0x0b,0x44,0xac,0xbc,0x0b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24,
+0x68,0x08,0x05,0x24,0xc0,0x0b,0x44,0xac,0xc4,0x0b,0x43,0xac,0x90,0x0c,0x04,0x24,
+0x94,0x0c,0x03,0x24,0x89,0x0b,0x47,0xa0,0x98,0x0b,0x45,0xac,0xc8,0x0b,0x44,0xac,
+0xcc,0x0b,0x43,0xac,0x08,0x00,0xe0,0x03,0x94,0x0b,0x45,0xac,0xe6,0x42,0x00,0x08,
+0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24,
+0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27,
+0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,
+0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,
+0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0xe1,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00,
+0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xd4,0x20,0x44,0x8c,
+0xed,0x42,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
+0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,
+0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00,
+0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,
+0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf,
+0x38,0x15,0x31,0x26,0xb0,0x0b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36,
+0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c,
+0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02,
+0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c,
+0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0xab,0x18,0x00,0x0c,0x25,0xa8,0x74,0x00,
+0xb0,0x0b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00,
+0x00,0x00,0x55,0xac,0xab,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae,
+0xab,0x18,0x00,0x0c,0x01,0x00,0x04,0x24,0xd0,0x0b,0x24,0x8e,0x0f,0x00,0x05,0x3c,
+0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34,
+0x18,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x38,0x15,0x27,0x26,
+0x8b,0x0b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x70,0x0d,0x63,0x24,
+0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10,
+0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e,
+0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x29,0x43,0x00,0x08,
+0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x89,0x0b,0xe4,0x90,
+0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x38,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,
+0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
+0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,
+0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,0x38,0x15,0x22,0x26,0x89,0x0b,0x44,0x90,
+0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,
+0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14,
+0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,0xff,0x00,0x04,0x32,
+0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xcc,0xff,0x80,0x14,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,
+0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,
+0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,
+0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,
+0x38,0x15,0x28,0x26,0x8b,0x0b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x1c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf,
+0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,
+0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10,
+0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x25,0x20,0x44,0x00,0x13,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14,
+0x0f,0x00,0x04,0x3c,0x89,0x0b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,
+0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10,
+0x38,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,
+0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,
+0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,
+0x38,0x15,0x22,0x26,0x89,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,
+0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,
+0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,
+0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14,
+0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x38,0x15,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x38,0x15,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
+0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,
+0x21,0x30,0x00,0x00,0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x29,0x43,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e,
+0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34,
+0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,
+0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26,
+0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00,
+0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d,
+0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xd8,0xff,0xbd,0x27,0xa8,0x11,0x42,0x24,
+0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,
+0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
+0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00,0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40,
+0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12,0x21,0x28,0xc0,0x00,0x5c,0x43,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0xe1,0x42,0x00,0x0c,0x21,0x80,0x40,0x00,
+0x04,0x10,0x53,0x00,0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00,
+0xc7,0x43,0x00,0x0c,0xff,0x00,0x84,0x32,0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f,
+0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x54,0x12,0x63,0x24,0x18,0x03,0x42,0x34,
+0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x5c,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0x80,0x40,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0x40,0x02,0x24,0x80,0x12,0x02,
+0x06,0x80,0x50,0x00,0x00,0x60,0x91,0x40,0x21,0x10,0x00,0x02,0x1c,0x00,0xbf,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,
+0x21,0x88,0x80,0x00,0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,
+0x30,0x00,0xb2,0xaf,0x58,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,
+0x02,0x80,0x02,0x3c,0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,
+0x58,0x45,0x00,0x0c,0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,
+0x10,0x00,0xa5,0x27,0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,
+0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,
+0x00,0x00,0x44,0x8c,0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,
+0x00,0x00,0xa2,0x8c,0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,
+0x00,0x00,0xc7,0x8c,0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,
+0x00,0x00,0x62,0x8c,0x1a,0x00,0x12,0x24,0x60,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf,
+0x30,0x00,0x04,0x26,0x20,0x00,0xa5,0x27,0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,
+0x13,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,
+0x04,0x00,0x04,0x8e,0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,
+0x10,0x00,0x07,0x8e,0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,
+0x24,0x20,0x83,0x00,0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,
+0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,
+0x24,0x20,0x82,0x00,0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,
+0x20,0x00,0x02,0x24,0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,
+0x14,0x00,0x06,0xae,0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,
+0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0x54,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,
+0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,
+0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,
+0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,
+0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,
+0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,
+0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,
+0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,
+0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,
+0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,
+0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,
+0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,
+0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,
+0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0xab,0x45,0x00,0x08,0x21,0x18,0x86,0x00,
+0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,
+0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,
+0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,
+0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0xc0,0x86,0x4b,0x24,
+0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,
+0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,
+0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,
+0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,
+0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,
+0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0xfa,0x45,0x00,0x08,
+0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,
+0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
+0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,
+0x0b,0x46,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,
+0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,
+0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,
+0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,
+0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,
+0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,
+0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,
+0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,
+0x3c,0x46,0x00,0x08,0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,
+0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x00,0x00,0x82,0x80,0x48,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,
+0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,
+0x42,0x46,0x00,0x0c,0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,
+0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,
+0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,
+0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,
+0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,
+0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,
+0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,
+0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,
+0x00,0x00,0xc2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,
+0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,
+0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,
+0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,
+0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,
+0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,
+0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
+0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,
+0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,
+0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0xe8,0x87,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0,0xce,0x46,0x00,0x08,0x01,0x00,0x63,0x24,
+0x02,0x80,0x02,0x3c,0xe8,0x87,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,
+0x21,0x18,0x00,0x00,0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,
+0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,
+0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x02,0x80,0x02,0x3c,0xe8,0x87,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
+0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,
+0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,
+0x79,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
+0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,
+0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,
+0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,
+0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0,0x07,0x47,0x00,0x08,0x00,0x00,0x44,0xae,
+0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x42,0x46,0x00,0x0c,0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,
+0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
+0x42,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,
+0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,
+0x21,0x30,0x40,0x02,0x95,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,
+0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x23,0x47,0x00,0x08,
+0x21,0x10,0x20,0x02,0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,
+0x04,0x30,0x86,0x00,0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x0c,0x1d,0x42,0x24,
+0x18,0x03,0xa5,0x34,0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,
+0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
+0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
+0x00,0x00,0x80,0xa0,0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x68,0x1d,0x42,0x24,0x18,0x03,0x63,0x34,
+0x00,0x00,0x62,0xac,0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,
+0x21,0x20,0x00,0x00,0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,
+0x07,0x00,0x04,0x24,0x43,0x47,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
+0x25,0xb0,0x03,0x3c,0xa4,0x1d,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,
+0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03,0xcc,0x3d,0x80,0xac,0x02,0x80,0x02,0x3c,
+0x38,0x3b,0x42,0x24,0xc0,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,
+0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,
+0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00,0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,
+0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0xe8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x01,0x01,0x02,0x2e,0x14,0x00,0xbf,0xaf,
+0x01,0x00,0x04,0x24,0x01,0x02,0x03,0x2e,0x0b,0x00,0x40,0x14,0x21,0x28,0x00,0x00,
+0x02,0x00,0x04,0x24,0x08,0x00,0x60,0x14,0x01,0x08,0x02,0x2e,0x06,0x00,0x40,0x14,
+0x03,0x00,0x04,0x24,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x71,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xf8,0xff,0x40,0x10,0x21,0x28,0x40,0x00,0x0c,0x00,0x50,0xac,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0x02,0x80,0x03,0x3c,0x50,0x3b,0x62,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c,0x38,0x3b,0x42,0x24,0xc0,0x18,0x03,0x00,
+0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c,0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,
+0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,0x04,0x00,0x83,0xac,0x98,0x3e,0xe5,0x8c,
+0x00,0x00,0x00,0x00,0x05,0x00,0xa0,0x10,0x00,0x00,0x64,0xac,0x84,0x3e,0x02,0x8d,
+0x98,0x3e,0xe0,0xac,0x25,0x10,0x45,0x00,0x84,0x3e,0x02,0xad,0x00,0x60,0x86,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
+0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x80,0x80,0x10,0x00,
+0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
+0x90,0x11,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,0xff,0xff,0x42,0x34,
+0xf8,0xff,0x03,0x24,0x88,0x11,0x02,0xae,0x84,0x01,0x46,0x36,0x24,0x28,0xa3,0x00,
+0xff,0xfe,0x02,0x24,0x00,0x00,0xc7,0x8c,0x24,0x28,0xa2,0x00,0xff,0xef,0x03,0x24,
+0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x28,0xa2,0x00,
+0x8c,0x11,0x07,0xae,0x90,0x11,0x05,0xae,0xcf,0x1b,0x00,0x0c,0x21,0x88,0x80,0x00,
+0x92,0x11,0x02,0x92,0x21,0x88,0x32,0x02,0x1c,0x00,0xbf,0x8f,0x60,0x01,0x22,0xa2,
+0x18,0x00,0xb2,0x8f,0x7c,0x11,0x00,0xae,0x60,0x11,0x00,0xae,0x64,0x11,0x00,0xae,
+0x68,0x11,0x00,0xae,0x6c,0x11,0x00,0xae,0x70,0x11,0x00,0xae,0x74,0x11,0x00,0xae,
+0x78,0x11,0x00,0xae,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x90,0x11,0x43,0x8c,0x25,0xb0,0x05,0x3c,
+0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30,
+0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30,
+0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,
+0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,
+0x20,0x48,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,
+0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,
+0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,
+0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,
+0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,
+0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,
+0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,
+0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,
+0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,
+0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,
+0x41,0x48,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c,0x90,0x11,0x43,0x8c,
+0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90,
+0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00,
+0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,
+0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,
+0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0x6e,0x48,0x00,0x08,0x01,0x00,0x07,0x24,
+0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,
+0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,
+0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,
+0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,
+0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,
+0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,
+0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,
+0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,
+0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,
+0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,
+0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0x8f,0x48,0x00,0x08,0xff,0x00,0x44,0x30,
+0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xd8,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c,0x38,0x15,0x52,0x24,
+0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf,
+0xff,0x1f,0x73,0x34,0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02,0xcd,0x47,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x90,0x11,0x02,0x8e,0x21,0x28,0x00,0x00,0x24,0x10,0x53,0x00,
+0x00,0x20,0x42,0x34,0x90,0x11,0x02,0xae,0x92,0x11,0x03,0x92,0x00,0x00,0x00,0x00,
+0x80,0x18,0x03,0x00,0x21,0x18,0x72,0x00,0xf8,0x04,0x64,0x8c,0x6c,0x05,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00,0x5c,0x11,0x02,0xae,
+0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28,0xce,0x11,0x40,0xa0,
+0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae,0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x38,0x15,0x46,0x24,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0xec,0x25,0xc2,0x8c,0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30,0xff,0xff,0x42,0x38,
+0x0b,0x18,0x02,0x00,0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf,0xec,0x25,0xc4,0xac,
+0xb9,0x00,0xa0,0x11,0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c,0xb8,0x81,0x45,0x24,
+0x94,0x04,0xc4,0x24,0xea,0x48,0x00,0x08,0x21,0x88,0x00,0x00,0x01,0x00,0x31,0x26,
+0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,0x01,0x00,0x84,0x24,
+0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0xf7,0xff,0x40,0x10,
+0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,
+0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x38,0x15,0x4a,0x24,
+0x01,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,0x50,0x7f,0x6c,0x24,0xd8,0x7e,0x4b,0x24,
+0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,
+0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,
+0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,
+0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
+0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,
+0xaf,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x38,0x15,0x48,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x4c,0x82,0x69,0x24,0xd8,0x81,0x47,0x24,0x21,0x88,0x00,0x00,
+0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,
+0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,0x04,0x00,0x22,0x2a,
+0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x82,0x68,0x24,
+0xd8,0x81,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,0x21,0x10,0x88,0x00,
+0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,0x01,0x00,0x31,0x26,
+0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,0x1d,0x00,0x22,0x2a,
+0xf8,0x04,0x83,0xac,0xf4,0xff,0x40,0x14,0x6c,0x05,0x85,0xac,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x56,0x24,0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02,0xff,0x1f,0x57,0x34,
+0x21,0x88,0x00,0x00,0x21,0xa0,0x00,0x00,0x47,0x49,0x00,0x08,0x21,0x90,0xc0,0x02,
+0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x3d,0x00,0x40,0x10,
+0x94,0x00,0x94,0x26,0x90,0x11,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00,
+0x01,0x00,0x53,0x30,0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x88,0x11,0x43,0x8e,
+0x21,0x20,0x20,0x02,0x24,0x28,0xa3,0x00,0xcf,0x1b,0x00,0x0c,0x8c,0x11,0x45,0xae,
+0x92,0x11,0x44,0x92,0xa9,0x1b,0x00,0x0c,0xff,0x00,0x25,0x32,0x90,0x11,0x42,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x42,0xae,
+0x92,0x11,0x50,0x92,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02,0xbf,0x1b,0x00,0x0c,
+0x80,0x80,0x10,0x00,0x21,0x80,0x16,0x02,0x60,0x11,0x40,0xae,0x64,0x11,0x40,0xae,
+0x68,0x11,0x40,0xae,0x6c,0x11,0x40,0xae,0x70,0x11,0x40,0xae,0x74,0x11,0x40,0xae,
+0x78,0x11,0x40,0xae,0x7c,0x11,0x40,0xae,0xf8,0x04,0x04,0x8e,0x6c,0x05,0x03,0x8e,
+0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00,
+0x04,0x00,0x04,0x24,0x0a,0xa8,0x82,0x00,0x5c,0x11,0x43,0xae,0x21,0x20,0x9e,0x02,
+0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xce,0x11,0x40,0xa0,
+0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xec,0x11,0x80,0xac,0x94,0x00,0x52,0x26,0xc5,0xff,0x40,0x14,
+0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x00,0x00,0x55,0xa0,
+0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x02,0x80,0x03,0x3c,
+0x38,0x15,0x62,0x24,0xec,0x25,0x40,0xac,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0xb8,0x81,0x45,0x24,
+0x94,0x04,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90,
+0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14,
+0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x38,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,
+0x01,0x80,0x02,0x3c,0x74,0x80,0x6c,0x24,0x14,0x7f,0x4b,0x24,0x21,0x88,0x00,0x00,
+0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,
+0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
+0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,
+0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,
+0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x82,0x68,0x24,
+0xd8,0x81,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00,
+0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,
+0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,
+0x6c,0x05,0x66,0xac,0x3a,0x49,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27,
+0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00,
+0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00,
+0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x80,0x88,0x11,0x00,
+0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,
+0x90,0x11,0x30,0x8e,0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24,0x2b,0x18,0x03,0x00,
+0x00,0x10,0x10,0x36,0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00,0x00,0x04,0x82,0x30,
+0x25,0x80,0x03,0x02,0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24,0x24,0x80,0x03,0x02,
+0xc0,0x10,0x02,0x00,0x25,0x80,0x02,0x02,0x88,0x11,0x25,0xae,0x90,0x11,0x30,0xae,
+0x2c,0x1c,0x00,0x0c,0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02,
+0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c,
+0x80,0x18,0x03,0x00,0x90,0x11,0x30,0xae,0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c,
+0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,0xcf,0x1b,0x00,0x0c,0x8c,0x11,0x22,0xae,
+0x92,0x11,0x24,0x92,0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xa9,0x1b,0x00,0x08,
+0x28,0x00,0xbd,0x27,0xcd,0x47,0x00,0x08,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,
+0x38,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,
+0x00,0x10,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x23,0x10,0xa4,0x00,
+0x2b,0x18,0xa4,0x00,0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03,0x0b,0x10,0x83,0x00,
+0x20,0xff,0xbd,0x27,0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf,0xd8,0x00,0xbe,0xaf,
+0xd4,0x00,0xb7,0xaf,0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf,0xc4,0x00,0xb3,0xaf,
+0xc0,0x00,0xb2,0xaf,0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf,0x21,0xa8,0x00,0x00,
+0x40,0x11,0x15,0x00,0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00,0x07,0x00,0x16,0x24,
+0xff,0xff,0xd6,0x26,0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06,0x04,0x00,0x42,0x24,
+0x01,0x00,0xb5,0x26,0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14,0x40,0x11,0x15,0x00,
+0x25,0xb0,0x10,0x3c,0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac,0x04,0x00,0x03,0x36,
+0x00,0x00,0x62,0x8c,0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c,0x08,0x0c,0x04,0x36,
+0x0f,0x00,0x11,0x3c,0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c,0x24,0x10,0x51,0x00,
+0x02,0xf4,0x02,0x00,0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x74,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0xe0,0x0e,0x02,0x36,0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c,0xdc,0x0e,0x12,0x36,
+0x70,0x0e,0x13,0x36,0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e,0x74,0x0e,0x14,0x36,
+0x78,0x0e,0x15,0x36,0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e,0x7c,0x0e,0x16,0x36,
+0x80,0x0e,0x17,0x36,0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e,0xd4,0x0e,0x10,0x36,
+0xed,0x3f,0x11,0x3c,0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e,0xfb,0x92,0x25,0x36,
+0x88,0x00,0xa3,0xaf,0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x8c,0x00,0xa2,0xaf,
+0x00,0x00,0xe3,0x8e,0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34,0x90,0x00,0xa3,0xaf,
+0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34,0x94,0x00,0xa2,0xaf,
+0x00,0x00,0x63,0x8c,0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34,0x98,0x00,0xa3,0xaf,
+0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34,0x9c,0x00,0xa2,0xaf,
+0x00,0x00,0x63,0x8c,0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf,0x00,0x00,0x02,0x8e,
+0x25,0xb0,0x03,0x3c,0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,
+0x1c,0x4a,0x00,0x0c,0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02,0x1c,0x4a,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x21,0x20,0x60,0x02,0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x21,0x20,0x80,0x02,0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xa0,0x02,
+0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02,0x1c,0x4a,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x21,0x20,0xe0,0x02,0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x02,0x80,0x02,0x3c,0x40,0x83,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,
+0x1c,0x4a,0x00,0x0c,0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c,0x44,0x83,0x63,0x24,
+0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x1c,0x4a,0x00,0x0c,0x21,0xb0,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x48,0x83,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,
+0x1c,0x4a,0x00,0x0c,0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c,0x4c,0x83,0x63,0x24,
+0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x1c,0x4a,0x00,0x0c,0x10,0x00,0xb7,0x27,
+0x21,0x20,0x00,0x02,0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c,
+0x50,0x83,0x42,0x24,0x00,0x00,0x44,0x8c,0x1c,0x4a,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x08,0x4b,0x00,0x08,0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13,0x02,0x80,0x02,0x3c,
+0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,
+0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,
+0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,
+0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,
+0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,
+0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10,0x02,0x3c,0x07,0x00,
+0xe6,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,
+0xe2,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,0x08,0x00,0x83,0x10,
+0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,0xe0,0x03,0x03,0x24,
+0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10,0x01,0x00,0x04,0x24,
+0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11,0x00,0x00,0x00,0x00,
+0xd7,0x00,0x80,0x14,0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26,0x0a,0x00,0xa2,0x2e,
+0x01,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17,0x01,0x00,0x02,0x24,
+0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0x1c,0x4a,0x00,0x0c,0x04,0x0c,0x64,0x36,
+0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0x1c,0x4a,0x00,0x0c,0x08,0x0c,0x64,0x36,
+0x28,0x0e,0x64,0x36,0x1c,0x4a,0x00,0x0c,0x80,0x80,0x05,0x3c,0x14,0x02,0x02,0x3c,
+0x48,0x01,0x45,0x34,0x1c,0x4a,0x00,0x0c,0x40,0x0e,0x64,0x36,0x16,0x68,0x05,0x3c,
+0xa2,0x04,0xa5,0x34,0x1c,0x4a,0x00,0x0c,0x44,0x0e,0x64,0x36,0x4c,0x0e,0x64,0x36,
+0x1c,0x4a,0x00,0x0c,0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c,0x4d,0x01,0x65,0x34,
+0x1c,0x4a,0x00,0x0c,0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c,0xba,0x08,0xa5,0x34,
+0x1c,0x4a,0x00,0x0c,0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36,0x1c,0x4a,0x00,0x0c,
+0xd1,0x28,0x05,0x24,0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34,0x1c,0x4a,0x00,0x0c,
+0x48,0x0e,0x64,0x36,0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34,0x1c,0x4a,0x00,0x0c,
+0x48,0x0e,0x64,0x36,0xab,0x18,0x00,0x0c,0x03,0x00,0x04,0x24,0xa0,0x00,0x02,0x3c,
+0x33,0x54,0x45,0x34,0x1c,0x4a,0x00,0x0c,0x04,0x0c,0x64,0x36,0x08,0x0c,0x64,0x36,
+0x1c,0x4a,0x00,0x0c,0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36,0x1c,0x4a,0x00,0x0c,
+0x21,0x28,0x00,0x00,0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17,0xac,0x0e,0x62,0x36,
+0x02,0x80,0x02,0x3c,0x54,0x83,0x42,0x24,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x20,0x08,0x63,0x34,0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c,0x00,0x01,0x65,0x34,
+0x1c,0x4a,0x00,0x0c,0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c,0x00,0x01,0x45,0x34,
+0x1c,0x4a,0x00,0x0c,0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,
+0x1c,0x4a,0x00,0x0c,0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,
+0x1c,0x4a,0x00,0x0c,0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,
+0x80,0x80,0x05,0x3c,0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34,0x1c,0x4a,0x00,0x0c,
+0x30,0x0e,0x44,0x36,0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34,0x1c,0x4a,0x00,0x0c,
+0x34,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34,0x1c,0x4a,0x00,0x0c,
+0x38,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34,0x1c,0x4a,0x00,0x0c,
+0x3c,0x0e,0x44,0x36,0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34,0x1c,0x4a,0x00,0x0c,
+0x40,0x0e,0x44,0x36,0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34,0x1c,0x4a,0x00,0x0c,
+0x44,0x0e,0x44,0x36,0x4c,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,0xd1,0x28,0x05,0x24,
+0x6c,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0x01,0x03,0x3c,
+0x00,0x7c,0x65,0x34,0x1c,0x4a,0x00,0x0c,0x50,0x0e,0x44,0x36,0x00,0x01,0x02,0x3c,
+0x00,0x48,0x45,0x34,0x1c,0x4a,0x00,0x0c,0x54,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,
+0x23,0xdc,0x65,0x34,0x1c,0x4a,0x00,0x0c,0x58,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,
+0x23,0x8c,0x45,0x34,0x1c,0x4a,0x00,0x0c,0x5c,0x0e,0x44,0x36,0x14,0x02,0x03,0x3c,
+0x02,0x01,0x65,0x34,0x1c,0x4a,0x00,0x0c,0x60,0x0e,0x44,0x36,0x16,0x28,0x05,0x3c,
+0x07,0x0d,0xa5,0x34,0x1c,0x4a,0x00,0x0c,0x64,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,
+0x1c,0x4a,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x1c,0x4a,0x00,0x0c,
+0x48,0x0e,0x44,0x36,0x00,0x02,0x10,0x3c,0xab,0x18,0x00,0x0c,0x03,0x00,0x04,0x24,
+0x4c,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,0xd1,0x28,0x05,0x36,0xd1,0x28,0x05,0x36,
+0x1c,0x4a,0x00,0x0c,0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,
+0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x1c,0x4a,0x00,0x0c,0x48,0x0e,0x44,0x36,
+0xab,0x18,0x00,0x0c,0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f,0x04,0x0c,0x44,0x36,
+0x1c,0x4a,0x00,0x0c,0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f,0x08,0x0c,0x44,0x36,
+0x1c,0x4a,0x00,0x0c,0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36,0x1c,0x4a,0x00,0x0c,
+0x21,0x28,0x00,0x00,0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c,
+0x54,0x83,0x42,0x24,0x00,0x00,0x44,0x8c,0x1c,0x4a,0x00,0x0c,0x00,0x01,0x05,0x3c,
+0x28,0x08,0x44,0x36,0x1c,0x4a,0x00,0x0c,0x00,0x01,0x05,0x3c,0xac,0x0e,0x62,0x36,
+0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36,
+0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c,
+0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c,
+0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00,
+0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,
+0x02,0x34,0x06,0x00,0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24,
+0x20,0xff,0x83,0x14,0x21,0x40,0x00,0x00,0xfe,0x4a,0x00,0x08,0x21,0x20,0x00,0x00,
+0x00,0x00,0x62,0x8c,0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c,0xac,0x0e,0x67,0x36,
+0xb4,0x0e,0x65,0x36,0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00,0x04,0x00,0xe4,0xae,
+0x00,0x00,0xc3,0x8c,0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,
+0x08,0x00,0xe3,0xae,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,
+0xbc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,
+0xcc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26,0x03,0x00,0xc2,0x2e,
+0xc7,0xfe,0x40,0x14,0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f,0x00,0x00,0x00,0x00,
+0x39,0x01,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f,0x00,0x00,0x00,0x00,
+0x06,0x00,0x20,0x16,0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,
+0x29,0x00,0x40,0x10,0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02,0x25,0x4a,0x00,0x0c,
+0x21,0x28,0x20,0x02,0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x34,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0x25,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x2c,0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x50,0x00,0xb2,0x8f,
+0x21,0x20,0x00,0x02,0x25,0x4a,0x00,0x0c,0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c,
+0x09,0x00,0x40,0x10,0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,
+0x25,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x0e,0x00,0x40,0x14,
+0x21,0x28,0x00,0x00,0x21,0x20,0x20,0x02,0x25,0x4a,0x00,0x0c,0x21,0x28,0x40,0x02,
+0x03,0x00,0x42,0x2c,0xd0,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x54,0x00,0xa5,0x8f,
+0x34,0x00,0xa4,0x8f,0x25,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,
+0xc9,0x00,0x40,0x10,0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24,0xcb,0x00,0xa2,0x10,
+0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00,0x02,0x80,0x0f,0x3c,
+0x21,0x28,0xa2,0x00,0x38,0x15,0xec,0x25,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xa7,0x8c,
+0x0c,0x00,0x83,0x8d,0x10,0x00,0x84,0x8d,0x04,0x00,0xa8,0x8c,0x10,0x00,0xa9,0x8c,
+0x00,0xfc,0x02,0x24,0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c,0x24,0x20,0x82,0x00,
+0xff,0x03,0xc6,0x30,0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30,0xf0,0xff,0x02,0x3c,
+0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00,0xff,0x03,0x08,0x31,
+0xff,0x03,0x29,0x31,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x80,0x42,0x08,0x00,
+0x80,0x4a,0x09,0x00,0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c,0x18,0x00,0xa7,0x8c,
+0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00,0xff,0x03,0x4a,0x31,
+0xff,0x03,0x6b,0x31,0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00,0x24,0x18,0x62,0x00,
+0x00,0x5d,0x0b,0x00,0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x16,0x00,0x86,0xa5,
+0x0c,0x00,0x83,0xad,0x10,0x00,0x84,0xad,0x14,0x00,0x87,0xa5,0x38,0x15,0xf1,0x25,
+0x10,0x00,0x22,0x8e,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x4d,0x00,0x43,0x10,
+0x25,0xb0,0x12,0x3c,0x0c,0x00,0x23,0x8e,0x80,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,
+0x00,0x02,0x62,0x30,0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00,0x03,0x00,0x40,0x10,
+0xff,0x03,0x65,0x30,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,
+0x82,0x62,0x03,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,
+0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,
+0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36,0x24,0x28,0x14,0x01,
+0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,
+0x25,0x28,0xa2,0x00,0x1c,0x4a,0x00,0x0c,0x25,0x28,0xa6,0x00,0x94,0x0c,0x44,0x36,
+0x00,0x00,0x85,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34,0xc0,0x03,0x10,0x32,
+0x24,0x28,0xb5,0x00,0x80,0x85,0x10,0x00,0x1c,0x4a,0x00,0x0c,0x25,0x28,0xb0,0x00,
+0x10,0x00,0x2c,0x8e,0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,0x82,0x2a,0x0c,0x00,
+0xff,0x03,0xa5,0x30,0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30,0x03,0x00,0x60,0x10,
+0x82,0x6d,0x02,0x00,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,
+0x02,0x65,0x0c,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,
+0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,
+0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00,
+0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,
+0x1c,0x4a,0x00,0x0c,0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c,
+0xc0,0x03,0x10,0x32,0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00,0x1c,0x4a,0x00,0x0c,
+0x25,0x28,0xb0,0x00,0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c,0x1c,0x4a,0x00,0x0c,
+0xe0,0x0e,0x04,0x36,0x7c,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0xdc,0x0e,0x04,0x36,
+0x80,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0x70,0x0e,0x04,0x36,0x84,0x00,0xa5,0x8f,
+0x1c,0x4a,0x00,0x0c,0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,
+0x78,0x0e,0x04,0x36,0x8c,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0x7c,0x0e,0x04,0x36,
+0x90,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0x80,0x0e,0x04,0x36,0x94,0x00,0xa5,0x8f,
+0x1c,0x4a,0x00,0x0c,0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,
+0x88,0x0e,0x04,0x36,0x9c,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0x8c,0x0e,0x04,0x36,
+0xa0,0x00,0xa5,0x8f,0x1c,0x4a,0x00,0x0c,0xd0,0x0e,0x04,0x36,0xa4,0x00,0xa5,0x8f,
+0x1c,0x4a,0x00,0x0c,0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f,0x88,0x0e,0x04,0x36,
+0x1c,0x4a,0x00,0x0c,0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,
+0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,
+0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xdc,0x00,0xbf,0x8f,0xd8,0x00,0xbe,0x8f,
+0xd4,0x00,0xb7,0x8f,0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f,0xc8,0x00,0xb4,0x8f,
+0xc4,0x00,0xb3,0x8f,0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f,0xb8,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24,0xff,0x00,0x02,0x24,
+0x39,0xff,0xa2,0x14,0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c,0x94,0x0e,0x62,0x34,
+0x9c,0x0e,0x64,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x02,0x80,0x0f,0x3c,
+0x00,0x00,0x49,0x8c,0x38,0x15,0xed,0x25,0x00,0x00,0x8c,0x8c,0x00,0x00,0xae,0x8c,
+0x00,0x00,0xc7,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x00,0xa4,0x8d,0x10,0x00,0xa5,0x8d,
+0x00,0x00,0x4a,0x8c,0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,
+0x24,0x48,0x26,0x01,0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c,0x24,0x28,0xa8,0x00,
+0x24,0x20,0x88,0x00,0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34,0x02,0x4c,0x09,0x00,
+0xc4,0x0e,0x63,0x34,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x28,0xa7,0x00,
+0x25,0x20,0x89,0x00,0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01,0x00,0x00,0x03,0x8d,
+0x24,0x50,0x46,0x01,0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0x82,0x61,0x0c,0x00,
+0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8c,0x00,
+0x25,0x28,0xaa,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x28,0xa2,0x00,
+0x24,0x18,0x66,0x00,0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00,
+0x24,0x38,0xe6,0x00,0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00,0x02,0x3c,0x07,0x00,
+0x02,0x1c,0x03,0x00,0x16,0x00,0xa3,0xa5,0x0c,0x00,0xa4,0xad,0x10,0x00,0xa5,0xad,
+0x71,0x4c,0x00,0x08,0x14,0x00,0xa7,0xa5,0x30,0x00,0xb1,0x8f,0x19,0x4c,0x00,0x08,
+0x21,0x20,0x00,0x02,0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,
+0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0xcc,0x88,0xe7,0x24,
+0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x40,0x38,0xc6,0x24,
+0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0x48,0x1b,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x03,0x0d,0x64,0x34,
+0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30,0x70,0x00,0x93,0x32,
+0x63,0x00,0x60,0x12,0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32,0x00,0x00,0x82,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24,
+0xda,0x18,0x00,0x0c,0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36,0x2a,0x42,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00,
+0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xda,0x18,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,
+0x6a,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0xab,0x18,0x00,0x0c,0x03,0x00,0x04,0x24,
+0x27,0x00,0x60,0x16,0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x42,0x00,0x42,0x34,
+0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xff,0xff,0x02,0x24,0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,
+0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,
+0xab,0x18,0x00,0x0c,0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12,0x25,0xb0,0x02,0x3c,
+0x03,0x0d,0x42,0x34,0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x0f,0x00,0x10,0x3c,0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02,0x6a,0x44,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00,
+0x2a,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,
+0x02,0x80,0x14,0x3c,0x30,0x00,0xb6,0xaf,0x38,0x15,0x85,0x26,0x38,0x00,0xbf,0xaf,
+0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x0c,0x00,0xa2,0x8c,0xc8,0x02,0xa3,0x90,
+0x06,0x00,0x16,0x24,0x82,0x17,0x02,0x00,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x14,0xc8,0x02,0xa3,0xa0,0x08,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,
+0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0x4e,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c,
+0x38,0x15,0x85,0x26,0x0c,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,
+0x01,0x00,0x44,0x30,0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x00,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x42,0x17,0x02,0x00,0x03,0x00,0x43,0x30,0xef,0xff,0x64,0x14,
+0x00,0x00,0x00,0x00,0x10,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,
+0x60,0x02,0x43,0x10,0x0f,0x00,0x10,0x3c,0xc7,0x02,0xb3,0x90,0x25,0xb0,0x02,0x3c,
+0x62,0x0c,0x42,0x34,0xff,0x00,0x63,0x32,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x90,0x26,0xc6,0x02,0x02,0x92,0x00,0x00,0x00,0x00,
+0x6f,0x01,0x40,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,0x95,0x01,0x40,0x14,
+0xcc,0x00,0x02,0x24,0xc4,0x02,0x02,0x96,0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00,
+0x2b,0x18,0x53,0x00,0x23,0x10,0x62,0x02,0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c,
+0x62,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x02,0x03,0x92,0x63,0x0c,0x22,0x36,
+0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x38,0x15,0x83,0x26,
+0xc3,0x02,0x62,0x90,0x08,0x00,0x66,0x8c,0xc2,0x02,0x73,0xa0,0x23,0x20,0x53,0x00,
+0x2b,0x38,0x62,0x02,0x23,0x90,0x62,0x02,0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00,
+0x3f,0x00,0xa5,0x30,0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,
+0x23,0x10,0x44,0x00,0x7d,0x01,0x40,0x16,0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00,
+0x21,0xa8,0xa0,0x00,0x02,0x80,0x17,0x3c,0x2b,0x28,0xc8,0x02,0xf3,0x01,0xa0,0x10,
+0x38,0x15,0x82,0x26,0x80,0x10,0x08,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,
+0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x38,0x15,0x86,0x26,
+0x0c,0x00,0xc3,0x8c,0x00,0x00,0x00,0x00,0xff,0x03,0x67,0x30,0x7b,0x01,0xe0,0x10,
+0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,
+0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32,
+0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,
+0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,
+0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36,
+0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,
+0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x1c,0x4a,0x00,0x0c,
+0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,
+0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,0x10,0x00,0xa3,0xaf,0x1c,0x4a,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x38,0x15,0x83,0x26,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x59,0x01,0x40,0x04,0xc0,0x28,0x15,0x00,0x21,0x10,0xa3,0x00,0xac,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xad,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xae,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xaf,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb0,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb1,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb2,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb3,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x96,0x3d,0xe3,0x92,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,
+0x92,0x00,0x02,0x24,0x0d,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,
+0x08,0x00,0x43,0x8c,0x01,0x00,0x44,0x3a,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,
+0x3f,0x00,0x63,0x30,0x01,0x00,0x84,0x30,0x67,0x01,0x80,0x10,0x23,0x28,0x43,0x00,
+0x42,0x18,0x12,0x00,0x40,0x10,0x03,0x00,0x21,0x90,0x43,0x00,0x38,0x15,0x83,0x26,
+0xc3,0x02,0x62,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x62,0x02,0x46,0x01,0x40,0x10,
+0x2b,0x10,0x45,0x02,0x06,0x00,0x40,0x10,0x24,0x00,0x06,0x24,0x08,0x00,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00,
+0x2b,0x28,0xc6,0x02,0x46,0x01,0xa0,0x10,0x38,0x15,0x82,0x26,0x80,0x10,0x06,0x00,
+0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x25,0x04,0x00,0x38,0x15,0x83,0x26,0x10,0x00,0x70,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x3a,0x10,0x00,0xff,0x03,0xe7,0x30,0x4d,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30,
+0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,
+0x18,0x00,0xe4,0x00,0x02,0x85,0x10,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,
+0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,
+0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,
+0x25,0xb0,0x11,0x3c,0x88,0x0c,0x24,0x36,0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,
+0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,
+0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x1c,0x4a,0x00,0x0c,0x10,0x00,0xa3,0xaf,
+0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32,
+0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,
+0x21,0x28,0x60,0x00,0x1c,0x4a,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x31,0x4e,0x00,0x08,
+0x00,0x00,0x00,0x00,0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00,
+0xc0,0xff,0x02,0x3c,0x24,0x20,0x62,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,
+0x84,0x4f,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,
+0x0d,0x00,0x40,0x10,0x02,0x80,0x17,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,
+0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,
+0x08,0x00,0xc2,0xac,0x02,0x80,0x17,0x3c,0x96,0x3d,0xe3,0x92,0x22,0x00,0x02,0x24,
+0x3a,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x39,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
+0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,
+0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0xe6,0x15,0x53,0x24,0xee,0x16,0x72,0x24,0x21,0x88,0x00,0x00,0xab,0x4f,0x00,0x08,
+0x10,0x00,0xa4,0xaf,0x95,0x45,0x00,0x0c,0x00,0x00,0x00,0x00,0x43,0x00,0x40,0x10,
+0x38,0x15,0x85,0x26,0x01,0x00,0x31,0x26,0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,
+0x38,0x15,0x82,0x26,0xc0,0x80,0x11,0x00,0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,
+0x95,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,
+0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,0x38,0x15,0x85,0x26,0x08,0x00,0xa3,0x8c,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,
+0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x08,0x00,0xa3,0xac,0x38,0x15,0x82,0x26,0x0c,0x00,0x43,0x8c,
+0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x2a,0x4e,0x00,0x08,0x0c,0x00,0x43,0xac,
+0xc6,0x02,0x02,0xa2,0x58,0x4e,0x00,0x08,0xc4,0x02,0x13,0xa6,0x63,0x4d,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x68,0x4e,0x00,0x08,0xc4,0x02,0x13,0xa6,0x25,0xb0,0x02,0x3c,
+0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x38,0x15,0x66,0x24,
+0xc0,0xff,0x02,0x3c,0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,
+0xdc,0x4f,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,
+0xbc,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,
+0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,
+0x25,0x10,0x43,0x00,0x96,0x4f,0x00,0x08,0x08,0x00,0xc2,0xac,0x08,0x00,0xa3,0x8c,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,
+0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0xbf,0x4f,0x00,0x08,
+0x25,0x18,0x62,0x00,0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x72,0x4e,0x00,0x08,0x38,0x15,0x83,0x26,0x8b,0x00,0xe0,0x10,
+0x21,0x40,0x00,0x00,0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38,
+0x24,0x00,0x08,0x24,0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x7d,0xfe,0x60,0x10,
+0x20,0x00,0x15,0x24,0x38,0x15,0x83,0x26,0x0a,0x00,0x62,0x94,0x02,0x80,0x17,0x3c,
+0x3f,0x00,0x42,0x30,0x84,0x4e,0x00,0x08,0x21,0xa8,0x52,0x00,0x83,0x00,0xa0,0x10,
+0x80,0x10,0x08,0x00,0x21,0x10,0x46,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c,
+0x1c,0x4a,0x00,0x0c,0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34,
+0xb9,0x4e,0x00,0x08,0x21,0x28,0x00,0x00,0x21,0x10,0xa3,0x00,0xb4,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x1f,0x4f,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x00,0x43,0x8c,
+0x8d,0x4e,0x00,0x08,0x82,0x25,0x03,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xbc,0xfe,0x60,0x14,
+0x23,0x30,0x52,0x00,0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x38,0x15,0x82,0x26,
+0x30,0x00,0x43,0x8c,0x47,0x4f,0x00,0x08,0x82,0x25,0x03,0x00,0x23,0x10,0x92,0x00,
+0x2b,0x18,0x44,0x02,0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00,0xf5,0xfd,0x80,0x14,
+0x23,0xa8,0xb2,0x00,0x83,0x4e,0x00,0x08,0x21,0xa8,0x00,0x00,0x30,0x00,0xc5,0x8c,
+0x12,0x50,0x00,0x08,0x25,0xb0,0x04,0x3c,0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,
+0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x31,0x4f,0x00,0x08,0x01,0x00,0x52,0x24,
+0x21,0x00,0xa0,0x10,0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x00,0x45,0x8c,
+0x25,0xb0,0x04,0x3c,0x1c,0x4a,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,
+0x9c,0x0c,0x84,0x34,0x1c,0x4a,0x00,0x0c,0x21,0x28,0x00,0x00,0x31,0x4e,0x00,0x08,
+0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,
+0x24,0x00,0x04,0x24,0xab,0x18,0x00,0x0c,0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,
+0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xda,0x18,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x4a,0x4e,0x00,0x08,0x25,0xb0,0x02,0x3c,0x30,0x00,0x65,0x8c,0x9f,0x50,0x00,0x08,
+0x25,0xb0,0x04,0x3c,0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10,
+0x02,0x80,0x02,0x3c,0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24,
+0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x22,0x18,0x43,0xa0,0x02,0x80,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0x22,0x18,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,
+0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x38,0x15,0x63,0x24,0x20,0x00,0x84,0x2c,
+0x09,0x00,0x80,0x10,0x21,0x10,0x43,0x00,0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x2c,0x39,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,
+0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30,
+0xd2,0xff,0xa3,0x24,0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c,
+0x08,0x00,0x84,0x2c,0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24,
+0xfc,0xff,0xa3,0x24,0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10,
+0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0xe0,0xff,0xbd,0x27,
+0x02,0x80,0x08,0x3c,0x18,0x00,0xbf,0xaf,0x38,0x15,0x08,0x25,0xe8,0x02,0x07,0x8d,
+0x02,0x80,0x02,0x3c,0x96,0x3d,0x49,0x90,0x00,0x03,0x02,0x3c,0x25,0x38,0xe2,0x00,
+0xff,0xf3,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x80,0x03,0x3c,0x24,0x38,0xe2,0x00,
+0x94,0x88,0x6a,0x24,0x01,0x80,0x06,0x3c,0x22,0x00,0x02,0x24,0x21,0x20,0x40,0x01,
+0x98,0x44,0xc6,0x24,0x10,0x00,0xa5,0x27,0x05,0x00,0x22,0x11,0xe8,0x02,0x07,0xad,
+0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,
+0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,
+0x13,0x00,0xa0,0xa3,0x0c,0x00,0x43,0xad,0x48,0x1b,0x00,0x0c,0x14,0x00,0x42,0xa1,
+0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x38,0x15,0x04,0x26,0xd8,0x02,0x82,0x8c,0x01,0x00,0x03,0x24,
+0x02,0x15,0x02,0x00,0x0f,0x00,0x42,0x30,0x07,0x00,0x43,0x10,0x25,0xb0,0x06,0x3c,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x4c,0x00,0xc3,0x34,0x00,0x00,0x62,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x45,0x00,0x40,0x10,0xff,0xf3,0x02,0x3c,
+0xe8,0x02,0x85,0x8c,0x00,0x00,0x00,0x00,0x82,0x16,0x05,0x00,0x03,0x00,0x42,0x30,
+0x17,0x00,0x40,0x14,0x38,0x15,0x11,0x26,0x0c,0x09,0xc3,0x34,0x00,0x00,0x63,0x8c,
+0x12,0x01,0x02,0x3c,0x13,0x13,0x42,0x34,0x6b,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,
+0x22,0x02,0x02,0x3c,0x23,0x13,0x42,0x34,0x52,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,
+0x00,0x03,0x02,0x3c,0x25,0x10,0xa2,0x00,0xe8,0x02,0x82,0xac,0x38,0x15,0x05,0x26,
+0xe8,0x02,0xa3,0x8c,0xff,0xf3,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x00,0x04,0x04,0x3c,0x25,0x18,0x64,0x00,0xe8,0x02,0xa3,0xac,0x38,0x15,0x11,0x26,
+0xfc,0x23,0x24,0x8e,0xff,0xff,0x02,0x34,0xd5,0xff,0x82,0x10,0x00,0x00,0x00,0x00,
+0x80,0x11,0x22,0x8e,0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,
+0x3f,0x00,0x43,0x2c,0x28,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0x00,0x24,0x22,0x8e,
+0x02,0x19,0x04,0x00,0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x3a,0x00,0x60,0x18,
+0x01,0x00,0x03,0x24,0xeb,0x02,0x22,0x92,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
+0x0e,0x00,0x43,0x10,0x38,0x15,0x02,0x26,0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,
+0x0c,0x09,0x84,0x34,0x1c,0x4a,0x00,0x0c,0x13,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,
+0xff,0xfc,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x01,0x04,0x3c,
+0x25,0x18,0x64,0x00,0xe8,0x02,0x23,0xae,0x38,0x15,0x02,0x26,0xe8,0x02,0x43,0x8c,
+0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x32,0x51,0x00,0x08,0xe8,0x02,0x43,0xac,
+0xe8,0x02,0x83,0x8c,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x20,0x00,0xbd,0x27,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0xe8,0x02,0x83,0xac,0xa5,0xff,0x40,0x10,0x03,0x00,0x03,0x24,
+0xeb,0x02,0x22,0x92,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0xa0,0xff,0x43,0x10,
+0x32,0x03,0x05,0x3c,0x25,0xb0,0x04,0x3c,0x0c,0x09,0x84,0x34,0x1c,0x4a,0x00,0x0c,
+0x33,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x03,0x04,0x3c,0x25,0x18,0x64,0x00,0x32,0x51,0x00,0x08,
+0xe8,0x02,0x23,0xae,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x02,0x03,0x3c,
+0x50,0x51,0x00,0x08,0x25,0x10,0x43,0x00,0xeb,0x02,0x22,0x92,0x02,0x00,0x03,0x24,
+0x03,0x00,0x42,0x30,0xd5,0xff,0x43,0x10,0x38,0x15,0x02,0x26,0x25,0xb0,0x04,0x3c,
+0x22,0x02,0x05,0x3c,0x0c,0x09,0x84,0x34,0x1c,0x4a,0x00,0x0c,0x23,0x13,0xa5,0x34,
+0xe8,0x02,0x23,0x8e,0xff,0xfc,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x7a,0x51,0x00,0x08,0x00,0x02,0x04,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,
+0x00,0x01,0x03,0x3c,0x50,0x51,0x00,0x08,0x25,0x10,0x43,0x00,0x25,0xb0,0x03,0x3c,
+0x03,0x0d,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,
+0x08,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,
+0x03,0x0d,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,
+0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,
+0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,
+0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xff,0x00,0x03,0x3c,0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,
+0x02,0x3c,0x02,0x00,0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x38,0x15,0x45,0x24,
+0x02,0x32,0x04,0x00,0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xda,0x0c,0xa2,0xa0,
+0xc8,0x0c,0xa0,0xac,0xcc,0x0c,0xa0,0xac,0xd0,0x0c,0xa0,0xac,0x06,0x00,0x80,0x14,
+0xd4,0x0c,0xa0,0xac,0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xd8,0x0c,0xa2,0xa0,
+0x08,0x00,0xe0,0x03,0xd9,0x0c,0xa3,0xa0,0xd9,0x0c,0xa7,0xa0,0x08,0x00,0xe0,0x03,
+0xd8,0x0c,0xa6,0xa0,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,0xd9,0x0c,0x66,0x90,
+0xd8,0x0c,0x65,0x90,0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,
+0x00,0x00,0x45,0xa0,0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xda,0x0c,0x60,0xa0,
+0x02,0x80,0x08,0x3c,0x38,0x15,0x04,0x25,0xda,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,
+0x15,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xcc,0x0c,0x82,0x8c,0xc8,0x0c,0x85,0x8c,
+0x25,0xb0,0x03,0x3c,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,
+0x0f,0x00,0x40,0x10,0x81,0x01,0x66,0x34,0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,
+0xf0,0x00,0x63,0x30,0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,
+0x38,0x15,0x02,0x25,0x01,0x00,0x03,0x24,0xd4,0x0c,0x40,0xac,0xc8,0x0c,0x40,0xac,
+0xcc,0x0c,0x40,0xac,0xd0,0x0c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0xd0,0x0c,0x82,0x8c,0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,
+0x2b,0x10,0xa2,0x00,0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xd4,0x0c,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0x23,0x52,0x00,0x08,0x38,0x15,0x02,0x25,
+0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,
+0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0x23,0x52,0x00,0x08,0x38,0x15,0x02,0x25,
+0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,
+0x00,0x00,0xa2,0xa0,0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,
+0x02,0x00,0xa0,0x10,0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,
+0x18,0x00,0xb2,0xaf,0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x44,0x90,0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,
+0x07,0x00,0x82,0x10,0x38,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x52,0x24,0x43,0x96,0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,
+0x4f,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0x4f,0x52,0x00,0x0c,
+0x21,0x80,0x40,0x00,0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,
+0xff,0xff,0x10,0x32,0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x94,0x50,0x24,0x43,0x96,0xff,0xdf,0x42,0x30,
+0x00,0x20,0x44,0x34,0x01,0x00,0x63,0x24,0x50,0x24,0x43,0xa6,0x00,0x00,0xa2,0xa4,
+0x00,0x00,0xa4,0xa4,0x6c,0x52,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,
+0x38,0x15,0x50,0x24,0x04,0x24,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,
+0x01,0x00,0x63,0x30,0x10,0x00,0xa4,0x27,0x40,0x39,0x25,0x26,0x07,0x00,0x62,0x10,
+0x0a,0x00,0x06,0x24,0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x6c,0x45,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x21,0x28,0x00,0x00,0x40,0x39,0x24,0x26,0x58,0x45,0x00,0x0c,
+0x0a,0x00,0x06,0x24,0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0x09,0x24,0x03,0xa2,
+0x08,0x24,0x02,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x89,0x47,0x00,0x0c,0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,
+0xe4,0xff,0x40,0x10,0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,
+0x14,0x00,0x02,0xae,0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,
+0x0c,0x00,0x03,0xae,0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x78,0x08,0x00,0x0c,
+0x21,0x20,0x00,0x02,0x9f,0x52,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x24,0x4b,0x63,0x24,0x00,0x00,0x43,0xac,
+0x63,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,
+0x02,0x80,0x02,0x3c,0x90,0x3d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x93,0x3d,0x66,0x90,0xa0,0x3d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xab,0x3d,0x6a,0x90,0xad,0x3d,0x4b,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xb0,0x3d,0x6c,0x90,0xb2,0x3d,0x4d,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,
+0x25,0xb0,0x04,0x3c,0x9d,0x3d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x18,0x3c,0x92,0x3d,0x08,0x93,0x00,0x00,0x85,0xac,0x9e,0x3d,0x40,0xa0,
+0x02,0x80,0x02,0x3c,0x00,0x00,0x86,0xac,0x9f,0x3d,0x40,0xa0,0x02,0x80,0x02,0x3c,
+0x00,0x00,0x87,0xac,0x02,0x80,0x0f,0x3c,0xc0,0x3d,0x40,0xa0,0x02,0x80,0x02,0x3c,
+0xbc,0x3d,0x40,0xa4,0x38,0x15,0xee,0x25,0x02,0x80,0x03,0x3c,0xfd,0xff,0x02,0x24,
+0xbe,0x3d,0x60,0xa4,0xe2,0x0a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,
+0xe0,0x0a,0xc3,0xa1,0xe4,0x0a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x09,0x31,
+0x02,0x00,0x02,0x24,0xe6,0x0a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x8a,0xac,
+0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,0x00,0x00,0x8d,0xac,0x0c,0x00,0x22,0x11,
+0x82,0x0b,0xc0,0xa1,0x92,0x3d,0x02,0x93,0x01,0x00,0x05,0x24,0x0f,0x00,0x42,0x30,
+0x20,0x00,0x45,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0xdc,0x3d,0x40,0xa4,0xd1,0x3d,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x97,0x3d,0x44,0x90,0x06,0x00,0x03,0x24,0x2d,0x00,0x83,0x10,
+0x0b,0x00,0x02,0x24,0x22,0x00,0x82,0x10,0x02,0x80,0x02,0x3c,0xaa,0x3d,0x43,0x90,
+0x00,0x00,0x00,0x00,0x36,0x00,0x60,0x10,0x00,0xe0,0x02,0x3c,0x04,0xe0,0x02,0x3c,
+0x38,0x15,0xe4,0x25,0x00,0x8e,0x42,0x34,0x00,0x15,0x03,0x3c,0x74,0x0b,0x82,0xac,
+0x00,0x15,0x63,0x34,0x00,0x42,0x02,0x24,0x6c,0x0b,0x83,0xac,0x70,0x0b,0x82,0xac,
+0x92,0x3d,0x02,0x93,0x01,0x00,0x05,0x24,0x0f,0x00,0x42,0x30,0xe2,0xff,0x45,0x14,
+0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c,0x38,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34,
+0x15,0x15,0x03,0x3c,0x07,0x07,0x63,0x34,0x74,0x0b,0x82,0xac,0x02,0x02,0x02,0x3c,
+0x6c,0x0b,0x83,0xac,0x70,0x0b,0x82,0xac,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xdc,0x3d,0x40,0xa4,0xd1,0x3d,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x00,0x80,0x02,0x3c,0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c,0x74,0x0b,0xc2,0xad,
+0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,0x6c,0x0b,0xc3,0xad,0x07,0x53,0x00,0x08,
+0x70,0x0b,0xc2,0xad,0x02,0x80,0x02,0x3c,0xaa,0x3d,0x43,0x90,0x00,0x00,0x00,0x00,
+0x14,0x00,0x60,0x10,0x00,0xc0,0x02,0x3c,0x04,0xc0,0x02,0x3c,0x00,0xb8,0x42,0x34,
+0x74,0x0b,0xc2,0xad,0x00,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x00,0x07,0x63,0x34,
+0x00,0x22,0x42,0x34,0x6c,0x0b,0xc3,0xad,0x07,0x53,0x00,0x08,0x70,0x0b,0xc2,0xad,
+0x38,0x15,0xe4,0x25,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x74,0x0b,0x82,0xac,
+0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x6c,0x0b,0x83,0xac,0x26,0x53,0x00,0x08,
+0x70,0x0b,0x82,0xac,0x00,0xb2,0x42,0x34,0x1c,0x1c,0x03,0x3c,0x74,0x0b,0xc2,0xad,
+0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,0x6c,0x0b,0xc3,0xad,0x07,0x53,0x00,0x08,
+0x70,0x0b,0xc2,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x94,0x4d,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0x0d,0xb8,0x46,0x34,
+0x80,0x00,0x03,0x3c,0x25,0x30,0xc3,0x00,0x00,0x04,0x02,0x3c,0x25,0x30,0xc2,0x00,
+0x00,0x08,0x03,0x3c,0x25,0x30,0xc3,0x00,0x02,0x80,0x04,0x3c,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x38,0x15,0x84,0x24,0x41,0xb0,0x05,0x3c,0xb0,0x4d,0x63,0x24,
+0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xa6,0xac,0x10,0x0b,0x86,0xac,
+0x08,0x0b,0x86,0xac,0x08,0x00,0xa5,0x34,0x86,0x00,0x06,0x24,0x00,0x00,0xa6,0xa4,
+0x14,0x0b,0x86,0xa4,0x0c,0x0b,0x80,0xac,0x16,0x0b,0x80,0xa4,0x18,0x0b,0x86,0xa4,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x8b,0x53,0x00,0x08,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,
+0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,0x21,0x20,0x00,0x00,
+0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,0x10,0x00,0xbf,0xaf,
+0x11,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x03,0x00,0x04,0x24,
+0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0x11,0x1b,0x00,0x08,0x18,0x00,0xbd,0x27,
+0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf,0xb7,0x56,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xff,0xff,0x03,0x34,
+0xf8,0x23,0x43,0xac,0xf4,0x23,0x43,0xac,0x21,0x80,0x40,0x00,0xf0,0x23,0x40,0xa4,
+0xf2,0x23,0x40,0xa4,0x1f,0x00,0x03,0x24,0xff,0xff,0x63,0x24,0xdc,0x0c,0x40,0xa4,
+0xde,0x0c,0x40,0xa4,0xe0,0x0c,0x40,0xa4,0xe2,0x0c,0x40,0xa4,0xe4,0x0c,0x40,0xa4,
+0xe6,0x0c,0x40,0xa4,0xe8,0x0c,0x40,0xa4,0xea,0x0c,0x40,0xa4,0xec,0x0c,0x40,0xa4,
+0xf5,0xff,0x61,0x04,0x24,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24,
+0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c,0x60,0x18,0x84,0x24,0x00,0x00,0x43,0xac,
+0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,0x87,0x57,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xfa,0x57,0x00,0x0c,0xec,0x25,0x00,0xae,0x5c,0x59,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x96,0x3d,0x64,0x90,0x92,0x00,0x02,0x24,
+0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xd4,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xba,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,0x33,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x41,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x50,0x24,0x00,0xa6,0x27,0x5a,0x00,0x0c,
+0x52,0x24,0x00,0xa6,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x04,0x3c,
+0x02,0x80,0x05,0x3c,0x28,0x3b,0x82,0x24,0x30,0x3b,0xa3,0x24,0x18,0x00,0xbd,0x27,
+0x04,0x00,0x42,0xac,0x28,0x3b,0x82,0xac,0x30,0x3b,0xa3,0xac,0x08,0x00,0xe0,0x03,
+0x04,0x00,0x63,0xac,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,
+0x25,0xb0,0x10,0x3c,0x18,0x03,0x03,0x36,0x8c,0x4f,0x42,0x24,0x00,0x00,0x62,0xac,
+0x14,0x00,0xbf,0xaf,0xc9,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x68,0x54,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x93,0x56,0x00,0x0c,
+0xc3,0x20,0x43,0xa0,0x32,0x41,0x00,0x0c,0x00,0x00,0x00,0x00,0x9e,0x53,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
+0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0x65,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x8d,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0x5f,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x23,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0x34,0x2b,0x84,0x24,
+0x7c,0x56,0x00,0x0c,0x01,0x00,0x05,0x24,0x00,0x80,0x04,0x3c,0xc0,0x30,0x84,0x24,
+0x7c,0x56,0x00,0x0c,0x02,0x00,0x05,0x24,0x69,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x80,0x04,0x3c,0x88,0x6d,0x84,0x24,0x7c,0x56,0x00,0x0c,0x03,0x00,0x05,0x24,
+0x02,0x80,0x02,0x3c,0xa0,0x3d,0x43,0x90,0x43,0x00,0x04,0x36,0x29,0x00,0x60,0x10,
+0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24,0x2b,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,
+0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34,0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,
+0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34,0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,
+0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,
+0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,
+0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0x6c,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0x1c,0x2c,0x00,0x0c,0x21,0x38,0x00,0x00,0x8b,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24,
+0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,
+0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,
+0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,
+0x6c,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,
+0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x1c,0x2c,0x00,0x0c,0x21,0x38,0x00,0x00,
+0x8b,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x21,0x20,0x00,0x00,
+0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34,0x21,0x18,0x86,0x00,0x04,0x00,0x84,0x24,
+0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac,0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x25,0xb0,0x04,0x3c,
+0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,
+0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,
+0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,
+0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,0x0c,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,0x68,0x01,0x40,0x10,
+0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34,0x50,0x00,0x82,0x34,0x00,0x00,0x45,0xac,
+0x00,0x00,0x65,0xa4,0x8c,0x54,0x00,0x08,0x02,0x80,0x03,0x3c,0x54,0x00,0x85,0x34,
+0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,
+0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x24,0xe2,0x0a,0x43,0x90,
+0xe6,0x0a,0x45,0x94,0x25,0xb0,0x1e,0x3c,0x1c,0x00,0xa3,0xa3,0x6c,0x0b,0x43,0x8c,
+0x58,0x00,0xc6,0x37,0x5c,0x00,0xc7,0x37,0x10,0x00,0xa3,0xaf,0x70,0x0b,0x43,0x8c,
+0xff,0xff,0x04,0x24,0x60,0x00,0xc8,0x37,0x14,0x00,0xa3,0xaf,0x74,0x0b,0x42,0x8c,
+0x96,0x01,0x03,0x24,0x64,0x00,0xc9,0x37,0x18,0x00,0xa2,0xaf,0x24,0x10,0x02,0x3c,
+0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,0x00,0xe0,0x42,0x34,0x00,0x00,0xc2,0xac,
+0x8a,0x00,0xca,0x37,0x00,0x00,0xe3,0xac,0x89,0x00,0xcb,0x37,0x28,0x28,0x02,0x24,
+0x09,0x00,0x03,0x24,0x00,0x00,0x04,0xad,0x8c,0x00,0xcd,0x37,0x00,0x00,0x24,0xad,
+0x8e,0x00,0xce,0x37,0x00,0x00,0x42,0xa5,0x00,0x00,0x63,0xa1,0x10,0x10,0x02,0x24,
+0x0a,0x0a,0x03,0x24,0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,
+0x13,0x00,0x02,0x24,0x90,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,
+0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x92,0x00,0xd1,0x37,
+0x3a,0x01,0x02,0x24,0x21,0x00,0x03,0x24,0xb5,0x00,0xd2,0x37,0x00,0x00,0x22,0xa6,
+0x00,0x00,0x43,0xa2,0x10,0x00,0xa3,0x8f,0xa0,0x00,0xd3,0x37,0xa4,0x00,0xd4,0x37,
+0x00,0x00,0x63,0xae,0x14,0x00,0xa2,0x8f,0xa8,0x00,0xd5,0x37,0xb6,0x00,0xdf,0x37,
+0x00,0x00,0x82,0xae,0x18,0x00,0xa3,0x8f,0x21,0x10,0x02,0x3c,0xff,0x77,0x42,0x34,
+0x00,0x00,0xa3,0xae,0x25,0xb0,0x03,0x3c,0xac,0x00,0x63,0x34,0x00,0x00,0x62,0xac,
+0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xb0,0x00,0x42,0x34,0xd8,0x00,0x63,0x34,
+0x00,0x00,0x45,0xac,0x00,0x00,0x60,0xa0,0x1c,0x00,0xa3,0x93,0x25,0xb0,0x02,0x3c,
+0xb4,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x24,
+0xb9,0x00,0x63,0x34,0x00,0x00,0xe2,0xa3,0x00,0x00,0x64,0xa0,0x25,0xb0,0x03,0x3c,
+0x0f,0x00,0x02,0x24,0xba,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c,
+0x16,0x01,0x42,0x34,0x00,0x00,0x40,0xa4,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x01,0x63,0x34,0x1a,0x01,0x42,0x34,0x00,0x00,0x60,0xa4,0x00,0x00,0x40,0xa4,
+0x25,0xb0,0x03,0x3c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34,
+0x00,0x00,0x62,0xac,0x2f,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34,
+0xd0,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0x5e,0x00,0x0c,0x3c,0x25,0xb0,0x03,0x3c,
+0x08,0x00,0x02,0x3c,0x32,0x43,0x90,0x35,0xd4,0x01,0x63,0x34,0x30,0xa5,0x42,0x34,
+0xd8,0x01,0xcf,0x37,0x00,0x00,0x70,0xac,0x00,0x00,0xe2,0xad,0x02,0x80,0x02,0x3c,
+0x96,0x3d,0x4d,0x90,0xdc,0x01,0xc3,0x37,0x1a,0x06,0x02,0x24,0x28,0x83,0x8c,0x35,
+0xe0,0x01,0xc4,0x37,0x00,0x00,0x6c,0xac,0xf4,0x01,0xc5,0x37,0x00,0x00,0x82,0xa4,
+0x07,0x07,0x03,0x24,0xc2,0x00,0x02,0x3c,0x00,0x00,0xa3,0xa4,0x51,0x10,0x42,0x34,
+0x26,0x00,0x03,0x24,0xf8,0x01,0xc6,0x37,0x00,0x02,0xc7,0x37,0x00,0x00,0xc2,0xac,
+0x03,0x02,0xc8,0x37,0x00,0x00,0xe3,0xa4,0x04,0x00,0x03,0x24,0x00,0x00,0x03,0xa1,
+0x0c,0x00,0x02,0x24,0xc0,0x01,0x03,0x24,0x36,0x02,0xc9,0x37,0x34,0x02,0xca,0x37,
+0x00,0x00,0x22,0xa1,0x37,0x02,0xcb,0x37,0x00,0x00,0x43,0xa5,0x03,0x00,0x02,0x24,
+0x22,0x00,0x03,0x24,0x00,0x00,0x62,0xa1,0xd6,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c,
+0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37,
+0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37,
+0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac,
+0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac,0x00,0x00,0x02,0xad,
+0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0x02,0x80,0x02,0x3c,0x96,0x3d,0x45,0x90,
+0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34,
+0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xb5,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c,
+0x92,0x00,0x02,0x24,0xb2,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c,
+0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24,
+0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35,
+0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad,
+0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac,
+0x25,0xb0,0x05,0x3c,0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35,
+0xf0,0x0f,0x03,0x24,0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35,
+0x00,0x00,0x42,0xad,0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,
+0x00,0x00,0x6d,0xad,0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2,0x00,0x00,0xe2,0xa2,
+0x25,0xb0,0x02,0x3c,0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0x42,0x34,
+0x00,0x00,0xc9,0xae,0x03,0x04,0x04,0x3c,0x00,0x00,0x49,0xac,0x07,0x08,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x01,0x02,0x84,0x34,0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34,
+0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,0x00,0x00,0x44,0xac,
+0x00,0x00,0x23,0xae,0x25,0xb0,0x02,0x3c,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,
+0x25,0xb0,0x03,0x3c,0x0c,0x00,0x06,0x24,0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34,
+0x0d,0x00,0x08,0x24,0xc2,0x01,0x63,0x34,0xc3,0x01,0x42,0x34,0x00,0x00,0x86,0xa2,
+0xc4,0x01,0xab,0x34,0x00,0x00,0xa6,0xa2,0xc5,0x01,0xac,0x34,0x00,0x00,0x66,0xa0,
+0x0e,0x00,0x07,0x24,0x00,0x00,0x48,0xa0,0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,
+0x0f,0x00,0x02,0x24,0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,
+0x00,0x00,0xa2,0xa1,0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,
+0x0e,0xe2,0x42,0x34,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf,
+0x4d,0x00,0xb9,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3,
+0x25,0xb0,0x02,0x3c,0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,
+0x25,0xb0,0x03,0x3c,0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,
+0x00,0x00,0x00,0xa3,0xd8,0x00,0xa7,0x34,0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90,
+0x80,0xff,0x02,0x24,0x2a,0xb0,0x04,0x3c,0x25,0x18,0x62,0x00,0x00,0x00,0xe3,0xa0,
+0x26,0xb0,0x06,0x3c,0x30,0x00,0x89,0x34,0x20,0x20,0x02,0x24,0x38,0x00,0x84,0x34,
+0x40,0x00,0x03,0x24,0x00,0x00,0x82,0xa4,0x79,0x00,0xc8,0x34,0x00,0x00,0x23,0xa1,
+0x94,0x00,0xaa,0x34,0x16,0x00,0x02,0x24,0x64,0x00,0x03,0x24,0x00,0x00,0x02,0xa1,
+0x7c,0x00,0xd2,0x34,0x00,0x00,0x43,0xa5,0x98,0x00,0xab,0x34,0x7a,0x00,0xc6,0x34,
+0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x00,0x00,0x62,0xa5,0x9c,0x00,0xac,0x34,
+0x00,0x00,0xc3,0xa0,0x20,0x0c,0x02,0x24,0x0a,0x00,0x03,0x24,0x00,0x00,0x42,0xa6,
+0x9a,0x00,0xad,0x34,0x00,0x00,0x83,0xa1,0x96,0x00,0xae,0x34,0xff,0x03,0x02,0x24,
+0x02,0x00,0x03,0x24,0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,
+0x20,0x00,0x02,0x24,0xb7,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x89,0x00,0xb1,0x34,
+0x09,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x44,0x00,0xa5,0x34,0x00,0x00,0xa3,0x94,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x46,0x24,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,
+0x00,0x00,0xa3,0xa4,0x00,0x00,0xa2,0x94,0xe2,0x0a,0xc4,0x90,0x04,0x02,0x03,0x24,
+0x00,0x02,0x42,0x34,0x00,0x00,0xa2,0xa4,0x29,0xb0,0x02,0x3c,0x40,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa4,0xfa,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f,
+0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,
+0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,
+0x20,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,
+0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,
+0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xa4,0x8c,0x54,0x00,0x08,0x02,0x80,0x03,0x3c,
+0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x42,0x55,0x00,0x08,
+0xff,0xff,0x0e,0x24,0x20,0x55,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x01,0x80,0x04,0x3c,
+0x00,0x00,0x62,0xa4,0xbc,0x6f,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
+0x01,0x80,0x02,0x3c,0xb4,0x69,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x68,0x59,0x42,0x24,
+0x02,0x80,0x03,0x3c,0xe4,0x3d,0xa2,0xac,0x00,0x80,0x02,0x3c,0x84,0x3e,0x60,0xac,
+0xe4,0x3d,0xa4,0x24,0x02,0x80,0x03,0x3c,0x78,0x06,0x42,0x24,0x88,0x3e,0x60,0xa4,
+0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x8a,0x3e,0x60,0xa4,
+0x02,0x80,0x06,0x3c,0x54,0x0a,0x42,0x24,0x00,0x80,0x03,0x3c,0x8c,0x3e,0xc7,0x24,
+0x14,0x00,0x82,0xac,0x04,0x08,0x63,0x24,0x02,0x80,0x02,0x3c,0x8c,0x3e,0xc0,0xac,
+0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac,0x02,0x80,0x03,0x3c,0x94,0x3e,0x40,0xa0,
+0x02,0x80,0x02,0x3c,0x98,0x3e,0x60,0xac,0x9c,0x3e,0x40,0xac,0x00,0x80,0x02,0x3c,
+0x00,0x80,0x03,0x3c,0xcc,0x1b,0x42,0x24,0xe8,0x0c,0x63,0x24,0x40,0x00,0x82,0xac,
+0x1c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0x78,0x10,0x42,0x24,
+0x04,0x14,0x63,0x24,0x20,0x00,0x82,0xac,0x24,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,
+0x00,0x80,0x03,0x3c,0xe8,0x17,0x42,0x24,0x78,0x23,0x63,0x24,0x28,0x00,0x82,0xac,
+0x2c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0x28,0x1c,0x42,0x24,
+0x00,0x03,0x63,0x24,0x3c,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x50,0x00,0x83,0xac,
+0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34,0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c,0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24,0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,
+0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24,0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,
+0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac,0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,
+0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24,0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,
+0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac,0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,
+0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac,0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad,0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,
+0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,
+0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00,0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,
+0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00,0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,
+0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,
+0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac,0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0xe0,0x00,0x25,0xb0,0x04,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,
+0x4c,0x5a,0x42,0x24,0xe0,0xff,0xbd,0x27,0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,
+0xdb,0xff,0x03,0x24,0x27,0x00,0x84,0x34,0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0xa0,0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,
+0x01,0x00,0x11,0x24,0x21,0x80,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,
+0x01,0x00,0x02,0x26,0xff,0x00,0x50,0x30,0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,
+0x00,0x00,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x3c,0x00,0x80,0x63,0x24,0x40,0x10,0x04,0x3c,
+0xff,0xff,0x63,0x30,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x25,0xc0,0x64,0x00,
+0x00,0x25,0x58,0xac,0x80,0x00,0x18,0x27,0x0c,0x25,0x58,0xac,0x80,0x00,0x18,0x27,
+0x18,0x25,0x58,0xac,0x80,0x00,0x18,0x27,0x24,0x25,0x58,0xac,0x80,0x00,0x18,0x27,
+0xe0,0xff,0xbd,0x27,0x30,0x25,0x58,0xac,0x80,0x00,0x18,0x27,0x1c,0x00,0xb7,0xaf,
+0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,
+0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x3c,0x25,0x58,0xac,
+0x0c,0x25,0x45,0x8c,0x18,0x25,0x46,0x8c,0x24,0x25,0x47,0x8c,0x30,0x25,0x48,0x8c,
+0x3c,0x25,0x49,0x8c,0x80,0x00,0x18,0x27,0x48,0x25,0x58,0xac,0x21,0x50,0x00,0x03,
+0x25,0x18,0x64,0x00,0x25,0xb0,0x0e,0x3c,0x20,0x10,0x04,0x3c,0x80,0x00,0x18,0x27,
+0xfc,0x24,0x43,0xac,0x08,0x25,0x45,0xac,0x14,0x25,0x46,0xac,0x20,0x25,0x47,0xac,
+0x2c,0x25,0x48,0xac,0x38,0x25,0x49,0xac,0xac,0x00,0xc3,0x35,0x94,0x24,0x44,0xac,
+0x90,0x24,0x44,0xac,0xa0,0x24,0x44,0xac,0x9c,0x24,0x44,0xac,0xac,0x24,0x44,0xac,
+0xa8,0x24,0x44,0xac,0xb8,0x24,0x44,0xac,0xb4,0x24,0x44,0xac,0x54,0x25,0x58,0xac,
+0x44,0x25,0x4a,0xac,0xc4,0x24,0x44,0xac,0xc0,0x24,0x44,0xac,0xd0,0x24,0x44,0xac,
+0xcc,0x24,0x44,0xac,0xdc,0x24,0x44,0xac,0xd8,0x24,0x44,0xac,0x00,0x02,0x18,0x27,
+0x00,0x00,0x68,0x8c,0xe4,0x0a,0x46,0x94,0x6c,0x25,0x58,0xac,0xb0,0x00,0xc3,0x35,
+0x00,0x00,0x76,0x8c,0x21,0x10,0x05,0x3c,0x54,0x25,0x52,0x8c,0x23,0x10,0x0c,0x3c,
+0x22,0x10,0x0d,0x3c,0x02,0x80,0x11,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,
+0x02,0x80,0x17,0x3c,0x00,0x80,0xa3,0x34,0x24,0x10,0x07,0x3c,0x21,0x98,0x00,0x03,
+0x23,0x18,0x66,0x00,0x00,0x02,0x18,0x27,0x38,0x3b,0x26,0x26,0x40,0x3b,0x8a,0x26,
+0x48,0x3b,0xa9,0x26,0x50,0x3b,0xeb,0x26,0x00,0x04,0x8f,0x35,0x01,0x00,0x08,0x25,
+0x00,0x40,0xb0,0x35,0x00,0x01,0xce,0x35,0x50,0x25,0x52,0xac,0x68,0x25,0x53,0xac,
+0xc4,0x25,0x4f,0xac,0x88,0x25,0x48,0xac,0x94,0x25,0x43,0xac,0xb8,0x25,0x50,0xac,
+0xac,0x25,0x56,0xac,0x00,0x00,0xc7,0xad,0xa8,0x25,0x47,0xac,0xc8,0x25,0x44,0xac,
+0xe8,0x24,0x44,0xac,0xe4,0x24,0x44,0xac,0x72,0x25,0x40,0xa4,0x71,0x25,0x40,0xa0,
+0x70,0x25,0x40,0xa0,0xbc,0x25,0x4c,0xac,0xc0,0x25,0x4c,0xac,0x80,0x25,0x45,0xac,
+0x84,0x25,0x45,0xac,0x8c,0x25,0x45,0xac,0x90,0x25,0x45,0xac,0xb0,0x25,0x4d,0xac,
+0xb4,0x25,0x4d,0xac,0xa4,0x25,0x47,0xac,0xcc,0x25,0x44,0xac,0xd8,0x25,0x58,0xac,
+0xd4,0x25,0x58,0xac,0x04,0x00,0x29,0xad,0x40,0x3b,0x8a,0xae,0x04,0x00,0x6b,0xad,
+0x48,0x3b,0xa9,0xae,0x04,0x00,0xc6,0xac,0x50,0x3b,0xeb,0xae,0x38,0x3b,0x26,0xae,
+0x04,0x00,0x4a,0xad,0x02,0x80,0x03,0x3c,0x00,0x14,0x62,0x24,0x00,0x14,0x66,0xac,
+0x04,0x00,0xc2,0xac,0x38,0x3b,0x22,0xae,0x04,0x00,0x46,0xac,0x08,0x00,0x58,0xac,
+0x10,0x00,0x40,0xac,0x00,0x01,0x18,0x27,0x21,0x48,0x40,0x00,0x18,0x00,0x48,0x24,
+0x01,0x00,0x07,0x24,0x21,0x18,0x40,0x01,0x21,0x28,0x00,0x00,0x07,0x00,0x06,0x24,
+0x21,0x20,0xa8,0x00,0x21,0x10,0xa9,0x00,0xff,0xff,0xc6,0x24,0x20,0x00,0x58,0xac,
+0x28,0x00,0x47,0xac,0x18,0x00,0xa5,0x24,0x00,0x00,0x8a,0xac,0x04,0x00,0x83,0xac,
+0x00,0x00,0x64,0xac,0x00,0x01,0x18,0x27,0xf5,0xff,0xc1,0x04,0x21,0x18,0x80,0x00,
+0x02,0x80,0x02,0x3c,0x48,0x3b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x04,0x00,0x27,0x8d,0xd8,0x14,0x4b,0x24,0x04,0x00,0x44,0xad,0x02,0x00,0x08,0x24,
+0x00,0x14,0x6a,0x24,0x21,0x28,0x00,0x00,0x01,0x00,0x06,0x24,0x21,0x20,0xab,0x00,
+0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,0xe0,0x00,0x58,0xac,0xe8,0x00,0x48,0xac,
+0x18,0x00,0xa5,0x24,0x00,0x00,0x89,0xac,0x04,0x00,0x87,0xac,0x00,0x00,0xe4,0xac,
+0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04,0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c,
+0x50,0x3b,0x48,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x07,0x8d,
+0x08,0x15,0x4b,0x24,0x04,0x00,0x24,0xad,0x00,0x14,0x6a,0x24,0x03,0x00,0x09,0x24,
+0x21,0x28,0x00,0x00,0x01,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,
+0xff,0xff,0xc6,0x24,0x10,0x01,0x58,0xac,0x18,0x01,0x49,0xac,0x18,0x00,0xa5,0x24,
+0x00,0x00,0x88,0xac,0x04,0x00,0x87,0xac,0x00,0x00,0xe4,0xac,0x00,0x08,0x18,0x27,
+0xf5,0xff,0xc1,0x04,0x21,0x38,0x80,0x00,0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,
+0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f,0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,
+0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x04,0x00,0x04,0xad,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x81,0x73,0x24,0x4c,0x82,0x52,0x24,
+0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x30,0x00,0xbf,0xaf,0xff,0x1f,0x54,0x34,
+0x38,0x15,0x70,0x24,0x21,0x88,0x00,0x00,0x02,0x80,0x15,0x3c,0xcd,0x47,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x90,0x11,0x05,0x8e,0x6c,0x00,0x66,0x8e,0x6c,0x00,0x43,0x8e,
+0xb8,0x81,0xa2,0x26,0x1b,0x00,0x44,0x90,0x21,0x18,0x66,0x00,0x24,0x28,0xb4,0x00,
+0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00,0x00,0x20,0xa5,0x34,0x5c,0x11,0x03,0xae,
+0x80,0x11,0x04,0xae,0x90,0x11,0x05,0xae,0x84,0x11,0x04,0xae,0x21,0x30,0x00,0x00,
+0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xb1,0x11,0x40,0xa0,
+0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xce,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae,0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x38,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c,
+0x4c,0x82,0x6f,0x24,0xd8,0x81,0x4d,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xb8,0x81,0x6e,0x24,0x98,0x81,0x4c,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,
+0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,
+0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,
+0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,
+0xf8,0x04,0x68,0xac,0xce,0x04,0x47,0xa0,0x6c,0x05,0x6a,0xac,0xef,0xff,0x80,0x14,
+0x94,0x04,0x49,0xa0,0x02,0x80,0x02,0x3c,0x38,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,
+0x01,0x80,0x02,0x3c,0x74,0x80,0x6b,0x24,0x14,0x7f,0x4c,0x24,0x21,0x88,0x00,0x00,
+0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,
+0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
+0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,
+0x38,0x03,0x65,0xa0,0x21,0x10,0x2c,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,
+0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x30,0x00,0xbf,0x8f,
+0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0x29,0xb0,0x02,0x3c,0xf8,0xff,0xbd,0x27,0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,
+0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34,0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,
+0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34,0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,
+0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34,0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,
+0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x3c,0x00,0x51,0x34,0x38,0x00,0x50,0x34,
+0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,
+0x21,0x20,0x00,0x00,0x00,0x00,0xc0,0xac,0xff,0xff,0x05,0x24,0x00,0x00,0xe0,0xac,
+0x38,0x15,0x46,0x24,0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,
+0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,
+0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x21,0x18,0x86,0x00,
+0x01,0x00,0x84,0x24,0x08,0x00,0x82,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x65,0xa0,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,
+0xff,0xff,0x84,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,
+0x94,0x00,0x63,0x24,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x08,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27,0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x13,0x3c,0x58,0x83,0x46,0x24,0x38,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,
+0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf,0x03,0x00,0x60,0xa0,0x21,0x38,0xa0,0x03,
+0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c,0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,
+0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24,0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,
+0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac,0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,
+0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c,0xec,0x83,0x58,0x24,0x00,0x00,0xe3,0xac,
+0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
+0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,
+0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,
+0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,
+0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
+0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,
+0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,
+0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,
+0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,
+0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,
+0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,
+0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,
+0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,
+0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,
+0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,
+0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,
+0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,
+0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0xf4,0x84,0x58,0x24,0x04,0x00,0x26,0xaf,
+0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27,0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,
+0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,
+0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,
+0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,
+0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,
+0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,
+0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,
+0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,
+0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,
+0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,
+0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,
+0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,
+0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
+0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,
+0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
+0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,
+0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,
+0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00,0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,
+0x00,0x00,0x27,0xaf,0x38,0x15,0x46,0x24,0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,
+0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c,0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,
+0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d,0xf8,0xff,0x40,0x14,0x18,0x00,0x85,0xac,
+0x02,0x80,0x02,0x3c,0x38,0x15,0x4b,0x24,0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,
+0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00,0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,
+0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90,0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,
+0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c,0xb4,0x01,0x66,0xa0,0xf7,0xff,0x40,0x14,
+0xac,0x00,0x65,0xa0,0x01,0x00,0x42,0x25,0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,
+0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,
+0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x63,0x30,0x4f,0x00,0x60,0x10,
+0x38,0x15,0x64,0x26,0x33,0x00,0x02,0x24,0xc1,0x02,0x62,0xa1,0x1c,0x00,0x03,0x24,
+0x0f,0x00,0x02,0x24,0xbc,0x02,0x63,0xa1,0xbd,0x02,0x62,0xa1,0x38,0x15,0x65,0x26,
+0x08,0x00,0xa4,0x8c,0xff,0x7f,0x09,0x3c,0xff,0xff,0x29,0x35,0xc0,0xff,0x02,0x24,
+0x24,0x20,0x89,0x00,0x24,0x20,0x82,0x00,0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,
+0xc8,0x02,0xa0,0xa0,0x24,0x20,0x82,0x00,0xc0,0xff,0x02,0x3c,0xc8,0x02,0xa6,0x8c,
+0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,0x24,0x20,0x82,0x00,0xff,0x0f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0xbf,0xff,0x03,0x3c,0x24,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,
+0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,
+0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34,0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,
+0xff,0x7f,0x42,0x34,0xc8,0x02,0xa6,0xac,0x24,0x20,0x82,0x00,0xc9,0x02,0xa0,0xa0,
+0x0c,0x00,0xa6,0x8c,0xff,0x9f,0x02,0x3c,0xc8,0x02,0xa7,0x8c,0xff,0xff,0x42,0x34,
+0xff,0xbf,0x03,0x3c,0x10,0x00,0xa8,0x8c,0xff,0xff,0x63,0x34,0x24,0x20,0x82,0x00,
+0xff,0xf0,0x02,0x3c,0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x24,0x38,0xe2,0x00,0xb4,0x02,0xb3,0x8f,0x1f,0x00,0x02,0x24,
+0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,0xa8,0x02,0xb0,0x8f,0x24,0x40,0x03,0x01,
+0xbe,0x02,0xa2,0xa0,0x01,0x00,0x03,0x24,0xff,0xff,0x02,0x24,0x24,0x30,0xc9,0x00,
+0xc0,0x02,0xa3,0xa0,0xc2,0x02,0xa2,0xa0,0xff,0x00,0x03,0x24,0x12,0x00,0x02,0x24,
+0xb8,0x02,0xbd,0x27,0xc8,0x02,0xa7,0xac,0x08,0x00,0xa4,0xac,0x10,0x00,0xa8,0xac,
+0x0c,0x00,0xa6,0xac,0xc4,0x02,0xa3,0xa4,0xc7,0x02,0xa2,0xa0,0xca,0x02,0xa0,0xa0,
+0xbf,0x02,0xa0,0xa0,0x08,0x00,0xe0,0x03,0xc6,0x02,0xa0,0xa0,0x33,0x00,0x02,0x24,
+0xc1,0x02,0x82,0xa0,0x0d,0x00,0x03,0x24,0x03,0x00,0x02,0x24,0xbc,0x02,0x83,0xa0,
+0x0d,0x59,0x00,0x08,0xbd,0x02,0x82,0xa0,0x02,0x80,0x19,0x3c,0x38,0x15,0x22,0x27,
+0xff,0xff,0x03,0x34,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x21,0xc0,0x40,0x00,
+0x00,0x24,0x43,0xac,0xea,0x02,0x40,0xa0,0xf4,0x23,0x43,0xac,0xfc,0x23,0x43,0xac,
+0x1f,0x00,0x0f,0x24,0xff,0xff,0xef,0x25,0x80,0x11,0x43,0xac,0x84,0x11,0x43,0xac,
+0xfc,0xff,0xe1,0x05,0x94,0x00,0x42,0x24,0x38,0x15,0x24,0x8f,0xd8,0x02,0x05,0x8f,
+0xf0,0xff,0x02,0x3c,0xe8,0x02,0x07,0x8f,0xfd,0xff,0x03,0x24,0xff,0xff,0x42,0x34,
+0x24,0x20,0x83,0x00,0x24,0x28,0xa2,0x00,0x20,0x00,0x0f,0x24,0xff,0xff,0x0e,0x24,
+0xff,0xef,0x02,0x3c,0x38,0x15,0x24,0xaf,0xff,0xff,0x42,0x34,0xd8,0x02,0x05,0xaf,
+0x02,0x00,0x0e,0xa3,0xdb,0x02,0x0f,0xa3,0xd8,0x02,0x00,0xa3,0xff,0xbf,0x03,0x3c,
+0x38,0x15,0x28,0x8f,0xd8,0x02,0x09,0x8f,0x24,0x38,0xe2,0x00,0xff,0xff,0x63,0x34,
+0x24,0x38,0xe3,0x00,0xff,0x7f,0x02,0x3c,0x0f,0xff,0x03,0x3c,0xfe,0xff,0x04,0x24,
+0xff,0xff,0x42,0x34,0xff,0xff,0x63,0x34,0x24,0x40,0x04,0x01,0x24,0x38,0xe2,0x00,
+0x24,0x48,0x23,0x01,0xff,0xdf,0x02,0x3c,0xcf,0xff,0x03,0x24,0x24,0x40,0x03,0x01,
+0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x3c,0x24,0x38,0xe2,0x00,0x25,0x48,0x23,0x01,
+0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,0x38,0x15,0x28,0xaf,0x02,0x80,0x0a,0x3c,
+0xd6,0x02,0x02,0xa3,0xd0,0x02,0x03,0xa7,0x00,0x01,0x02,0x24,0x49,0x00,0x03,0x24,
+0xe8,0x02,0x07,0xaf,0xd8,0x02,0x09,0xaf,0x5c,0x88,0x4a,0x25,0x3e,0x00,0x0c,0x24,
+0x1c,0x00,0x0d,0x24,0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xce,0x02,0x02,0xa7,
+0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3,
+0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xac,0x7f,0xc6,0x24,
+0xd4,0x02,0x0c,0xa3,0xd5,0x02,0x0d,0xa3,0xcc,0x02,0x0f,0xa7,0x01,0x00,0x0b,0xa3,
+0x0c,0x00,0x43,0xad,0x14,0x00,0x4b,0xa1,0x06,0x00,0x0e,0xa7,0xd2,0x02,0x0c,0xa3,
+0xd3,0x02,0x0d,0xa3,0x12,0x00,0xa2,0xa3,0x48,0x1b,0x00,0x0c,0x13,0x00,0xa0,0xa3,
+0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,
+0x12,0x22,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,
+0x04,0x89,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,
+0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,
+0x38,0x48,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,
+0x48,0x1b,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x09,0x3c,0x38,0x15,0x23,0x8d,
+0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,0xf3,0xff,0x02,0x24,0x24,0x18,0x62,0x00,
+0x3f,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0xd8,0xff,0xbd,0x27,0x38,0x15,0x23,0xad,
+0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,0x02,0x80,0x08,0x3c,0x20,0x89,0x08,0x25,
+0x18,0x00,0xb0,0xaf,0x10,0x00,0xa2,0xa3,0x38,0x15,0x30,0x25,0x11,0x00,0xa3,0xa3,
+0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x00,0x07,0x3c,0x01,0x80,0x06,0x3c,
+0x08,0x03,0x0b,0xae,0x1c,0x00,0xb1,0xaf,0x56,0x30,0xea,0x34,0x43,0x00,0x11,0x24,
+0xf4,0x98,0xe7,0x34,0x10,0x00,0xa5,0x27,0x0c,0x00,0x02,0xad,0x14,0x00,0x03,0xa1,
+0x21,0x20,0x00,0x01,0xe4,0x8c,0xc6,0x24,0x20,0x00,0xbf,0xaf,0x12,0x00,0xb1,0xa3,
+0x10,0x03,0x07,0xae,0x14,0x03,0x0a,0xae,0x13,0x00,0xa0,0xa3,0x0c,0x03,0x00,0xae,
+0x18,0x03,0x00,0xae,0x48,0x1b,0x00,0x0c,0x1c,0x03,0x00,0xae,0x1e,0x00,0x02,0x24,
+0x25,0x03,0x02,0xa2,0x4a,0x00,0x03,0x24,0x45,0x00,0x02,0x24,0x20,0x03,0x03,0xa2,
+0x21,0x03,0x02,0xa2,0x23,0x00,0x03,0x24,0x3e,0x00,0x02,0x24,0x22,0x03,0x11,0xa2,
+0x23,0x03,0x02,0xa2,0x24,0x03,0x03,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
+0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,
+0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0x3c,0x89,0xe7,0x24,
+0x12,0x00,0xa2,0xa3,0x0f,0x18,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x54,0x91,0xc6,0x24,
+0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0x48,0x1b,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,
+0x10,0x00,0xa3,0xa3,0x88,0x39,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,
+0x02,0x80,0x07,0x3c,0x74,0x89,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,
+0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0xe0,0x00,0x7c,0x49,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
+0x18,0x00,0xbf,0xaf,0x48,0x1b,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,
+0xd8,0xff,0xbd,0x27,0x40,0x39,0x84,0x24,0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf,
+0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24,0x02,0x80,0x07,0x3c,0x38,0x15,0xe7,0x24,
+0x04,0x24,0xe3,0x8c,0xfd,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00,
+0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x05,0x00,0x02,0x24,0x04,0x24,0xe3,0xac,
+0x08,0x24,0xe2,0xa0,0x28,0x00,0x03,0x24,0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,
+0x09,0x24,0xe3,0xa0,0x4b,0x00,0x02,0x24,0x42,0x00,0x03,0x24,0x90,0x89,0x08,0x25,
+0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,0x44,0x4a,0xc6,0x24,
+0x06,0x24,0xe0,0xa4,0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0x48,0x1b,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00,0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00,0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00,0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00,0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00,0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00,0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00,0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00,0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00,0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00,0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00,0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00,0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00,0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00,0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00,0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00,0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00,0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00,0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00,0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00,0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00,0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00,0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00,0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00,0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00,0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00,0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00,0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00,0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00,0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00,0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00,0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00,0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00,0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00,0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00,0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00,0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00,0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00,0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00,0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00,0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00,0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00,0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00,0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00,0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00,0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00,0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,
+0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00,0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,
+0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00,0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,
+0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00,0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,
+0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00,0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,
+0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,
+0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,
+0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,
+0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,
+0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,
+0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,
+0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00,0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,
+0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,
+0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,
+0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00,0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,
+0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00,0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,
+0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,
+0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,
+0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,
+0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00,0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,
+0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00,0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,
+0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00,0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,
+0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00,0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,
+0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00,0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,
+0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00,0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,
+0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00,0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,
+0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00,0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,
+0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00,0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,
+0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00,0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,
+0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,
+0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00,0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,
+0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,
+0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00,0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,
+0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,
+0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00,0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,
+0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00,0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,
+0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00,0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,
+0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00,0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,
+0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,
+0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,
+0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00,0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00,0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,
+0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00,0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,
+0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x34,0x01,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x34,0x01,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x30,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x13,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x17,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x06,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x06,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x08,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x0c,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x1f,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x38,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x02,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0xac,0x26,0x00,0x80,0x00,0xb7,0x00,0x00,
+0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
+0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
+0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
+0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
+0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
+0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
+0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
+0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
+0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
+0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
+0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
+0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
+0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
+0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
+0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
+0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
+0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
+0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
+0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
+0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
+0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
+0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
+0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
+0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
+0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
+0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
+0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
+0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
+0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
+0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
+0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
+0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
+0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
+0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
+0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
+0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
+0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
+0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
+0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
+0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
+0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
+0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
+0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
+0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
+0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
+0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
+0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
+0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
+0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
+0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
+0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
+0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
+0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
+0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,
+0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
+0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
+0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
+0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
+0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
+0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
+0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
+0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
+0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
+0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
+0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
+0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
+0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
+0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
+0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
+0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
+0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
+0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
+0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
+0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
+0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
+0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
+0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
+0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
+0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
+0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
+0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
+0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
+0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
+0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
+0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
+0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
+0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
+0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
+0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
+0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
+0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
+0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
+0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
+0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
+0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
+0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
+0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
+0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
+0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
+0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
+0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
+0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
+0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
+0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
+0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
+0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
+0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
+0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,
+0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,
+0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
+0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
+0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,
+0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,
+0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,
+0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,
+0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54,0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,
+0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00,0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,
+0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,
+0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x7c,0x01,0x80,
+0x2c,0x13,0x01,0x80,0x10,0x00,0x00,0x00,0x94,0x7c,0x01,0x80,0x34,0x13,0x01,0x80,
+0x20,0x00,0x00,0x00,0xa0,0x7c,0x01,0x80,0x2c,0x13,0x01,0x80,0x30,0x00,0x00,0x00,
+0xb0,0x7c,0x01,0x80,0x34,0x13,0x01,0x80,0x40,0x00,0x00,0x00,0xc0,0x7c,0x01,0x80,
+0x3c,0x13,0x01,0x80,0x50,0x00,0x00,0x00,0xcc,0x7c,0x01,0x80,0x44,0x13,0x01,0x80,
+0x00,0x00,0x00,0x00,0xd8,0x7c,0x01,0x80,0xac,0x13,0x01,0x80,0x00,0x00,0x00,0x00,
+0xe4,0x7c,0x01,0x80,0xac,0x13,0x01,0x80,0x80,0x00,0x00,0x00,0xf0,0x7c,0x01,0x80,
+0x4c,0x13,0x01,0x80,0x90,0x00,0x00,0x00,0xfc,0x7c,0x01,0x80,0x54,0x13,0x01,0x80,
+0xa0,0x00,0x00,0x00,0x04,0x7d,0x01,0x80,0x5c,0x13,0x01,0x80,0xb0,0x00,0x00,0x00,
+0x10,0x7d,0x01,0x80,0x94,0x13,0x01,0x80,0xc0,0x00,0x00,0x00,0x18,0x7d,0x01,0x80,
+0x9c,0x13,0x01,0x80,0xd0,0x00,0x00,0x00,0x24,0x7d,0x01,0x80,0xa4,0x13,0x01,0x80,
+0x00,0x00,0x00,0x00,0xdc,0x7d,0x01,0x80,0xdc,0x7d,0x01,0x80,0x31,0x10,0x10,0x00,
+0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00,
+0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10,
+0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10,
+0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08,
+0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08,
+0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18,
+0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08,
+0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02,
+0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06,
+0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02,
+0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02,
+0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,
+0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,
+0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04,
+0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,
+0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x30,0x08,0x08,0x08,
+0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,
+0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,
+0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18,
+0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,
+0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
+0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,
+0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,
+0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,
+0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,
+0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02,
+0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,
+0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,
+0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,
+0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,
+0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,
+0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,
+0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,
+0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,
+0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,
+0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,
+0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,
+0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
+0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,
+0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,
+0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
+0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,
+0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00,
+0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,
+0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,
+0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,
+0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,
+0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,
+0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,
+0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,
+0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,
+0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,
+0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,
+0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,
+0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c,
+0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x27,0x2c,0x19,0x1b,0x1e,0x20,
+0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,0x25,0x29,0x2b,0x2e,0x2e,0x00,0x00,0x00,
+0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
+0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
+0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,
+0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,
+0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00,
+0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0xd0,0x02,0x00,0x00,
+0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00,
+0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
+0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
+0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
+0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00,
+0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
+0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
+0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,
+0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80,
+0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80,0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80,
+0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80,0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80,
+0x78,0x04,0x00,0x80,0xf8,0x60,0x00,0x80,0xc4,0x60,0x00,0x80,0x58,0x62,0x00,0x80,
+0x28,0x62,0x00,0x80,0xf8,0x61,0x00,0x80,0xc8,0x61,0x00,0x80,0x2c,0x61,0x00,0x80,
+0xf0,0x70,0x00,0x80,0xfc,0x70,0x00,0x80,0x08,0x71,0x00,0x80,0x14,0x71,0x00,0x80,
+0xf0,0x70,0x00,0x80,0xf0,0x70,0x00,0x80,0xf0,0x70,0x00,0x80,0xf0,0x70,0x00,0x80,
+0x20,0x71,0x00,0x80,0x2c,0x71,0x00,0x80,0x38,0x71,0x00,0x80,0x44,0x71,0x00,0x80,
+0x38,0x15,0x02,0x80,0x38,0x15,0x02,0x80,0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,
+0x8c,0x0e,0x25,0xb0,0xd0,0x0e,0x25,0xb0,0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,
+0xfe,0x01,0x80,0x7f,0xe2,0x01,0x80,0x78,0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,
+0x95,0x01,0x40,0x65,0x7f,0x01,0xc0,0x5f,0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,
+0x42,0x01,0x80,0x50,0x30,0x01,0x00,0x4c,0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,
+0x00,0x01,0x00,0x40,0xf2,0x00,0x80,0x3c,0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,
+0xcb,0x00,0xc0,0x32,0xc0,0x00,0x00,0x30,0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,
+0xa2,0x00,0x80,0x28,0x98,0x00,0x00,0x26,0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,
+0x80,0x00,0x00,0x20,0x79,0x00,0x40,0x1e,0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,
+0x66,0x00,0x80,0x19,0x60,0x00,0x00,0x18,0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,
+0x51,0x00,0x40,0x14,0x4c,0x00,0x00,0x13,0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,
+0x40,0x00,0x00,0x10,0x36,0x35,0x2e,0x25,0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,
+0x1a,0x11,0x08,0x04,0x30,0x2f,0x29,0x21,0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,
+0x18,0x0f,0x08,0x03,0x2b,0x2a,0x25,0x1e,0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,
+0x15,0x0d,0x07,0x03,0x26,0x25,0x21,0x1b,0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,
+0x13,0x0c,0x06,0x03,0x22,0x21,0x1d,0x18,0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,
+0x11,0x08,0x05,0x02,0x1f,0x1e,0x1a,0x15,0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,
+0x0f,0x0a,0x05,0x02,0x1b,0x1a,0x17,0x13,0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,
+0x0d,0x09,0x04,0x02,0x18,0x17,0x15,0x11,0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,
+0x0c,0x08,0x04,0x02,0x16,0x15,0x12,0x0f,0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,
+0x0b,0x07,0x03,0x02,0x13,0x13,0x10,0x0d,0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,
+0x09,0x06,0x03,0x01,0x11,0x11,0x0f,0x0c,0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,
+0x08,0x05,0x03,0x01,0x0f,0x0f,0x0d,0x0b,0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,
+0x08,0x05,0x02,0x01,0x0d,0x0d,0x0c,0x0a,0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,
+0x07,0x04,0x02,0x01,0x0c,0x0c,0x0a,0x09,0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,
+0x06,0x04,0x02,0x01,0x0b,0x0a,0x09,0x08,0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,
+0x05,0x03,0x02,0x01,0x0a,0x09,0x08,0x07,0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,
+0x05,0x03,0x01,0x01,0x09,0x08,0x07,0x06,0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,
+0x00,0x00,0x00,0x00,0x33,0x32,0x2b,0x19,0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,
+0x00,0x00,0x00,0x00,0x2d,0x2d,0x17,0x17,0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,
+0x00,0x00,0x00,0x00,0x28,0x28,0x24,0x14,0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,
+0x00,0x00,0x00,0x00,0x24,0x23,0x1f,0x12,0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,
+0x00,0x00,0x00,0x00,0x20,0x20,0x1b,0x10,0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,
+0x00,0x00,0x00,0x00,0x1d,0x1c,0x18,0x0e,0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,
+0x00,0x00,0x00,0x00,0x1a,0x19,0x16,0x0d,0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,
+0x00,0x00,0x00,0x00,0x17,0x16,0x13,0x0b,0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,
+0x00,0x00,0x00,0x00,0x14,0x14,0x11,0x0a,0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,
+0x00,0x00,0x00,0x00,0x12,0x12,0x0f,0x09,0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,
+0x00,0x00,0x00,0x00,0x10,0x10,0x0e,0x08,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,
+0x00,0x00,0x00,0x00,0x0e,0x0e,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,
+0x00,0x00,0x00,0x00,0x0d,0x0c,0x0b,0x06,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,
+0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,
+0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,
+0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,
+0x00,0x00,0x00,0x00,0x06,0x00,0x2a,0xb0,0x05,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x7f,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x6b,0x34,0xf0,0x00,0x6b,0x34,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x6b,0x25,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x10,0xb8,0xff,0xff,0xff,0xff,
+};
+
+u8 Rtl8192SEFwMainArray[MainArrayLength] = {
+0x0, };
+
+u8 Rtl8192SEFwDataArray[DataArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = {
+0x01c,0x07000000,
+0x800,0x00040000,
+0x804,0x00008003,
+0x808,0x0000fc00,
+0x80c,0x0000000a,
+0x810,0x10005088,
+0x814,0x020c3d10,
+0x818,0x00200185,
+0x81c,0x00000000,
+0x820,0x01000000,
+0x824,0x00390004,
+0x828,0x01000000,
+0x82c,0x00390004,
+0x830,0x00000004,
+0x834,0x00690200,
+0x838,0x00000004,
+0x83c,0x00690200,
+0x840,0x00010000,
+0x844,0x00010000,
+0x848,0x00000000,
+0x84c,0x00000000,
+0x850,0x00000000,
+0x854,0x00000000,
+0x858,0x48484848,
+0x85c,0x65a965a9,
+0x860,0x0f7f0130,
+0x864,0x0f7f0130,
+0x868,0x0f7f0130,
+0x86c,0x0f7f0130,
+0x870,0x03000700,
+0x874,0x03000300,
+0x878,0x00020002,
+0x87c,0x004f0201,
+0x880,0xa8300ac1,
+0x884,0x00000058,
+0x888,0x00000008,
+0x88c,0x00000004,
+0x890,0x00000000,
+0x894,0xfffffffe,
+0x898,0x40302010,
+0x89c,0x00706050,
+0x8b0,0x00000000,
+0x8e0,0x00000000,
+0x8e4,0x00000000,
+0xe00,0x30333333,
+0xe04,0x2a2d2e2f,
+0xe08,0x00003232,
+0xe10,0x30333333,
+0xe14,0x2a2d2e2f,
+0xe18,0x30333333,
+0xe1c,0x2a2d2e2f,
+0xe30,0x01007c00,
+0xe34,0x01004800,
+0xe38,0x1000dc1f,
+0xe3c,0x10008c1f,
+0xe40,0x021400a0,
+0xe44,0x281600a0,
+0xe48,0xf8000001,
+0xe4c,0x00002910,
+0xe50,0x01007c00,
+0xe54,0x01004800,
+0xe58,0x1000dc1f,
+0xe5c,0x10008c1f,
+0xe60,0x021400a0,
+0xe64,0x281600a0,
+0xe6c,0x00002910,
+0xe70,0x31ed92fb,
+0xe74,0x361536fb,
+0xe78,0x361536fb,
+0xe7c,0x361536fb,
+0xe80,0x361536fb,
+0xe84,0x000d92fb,
+0xe88,0x000d92fb,
+0xe8c,0x31ed92fb,
+0xed0,0x31ed92fb,
+0xed4,0x31ed92fb,
+0xed8,0x000d92fb,
+0xedc,0x000d92fb,
+0xee0,0x000d92fb,
+0xee4,0x015e5448,
+0xee8,0x21555448,
+0x900,0x00000000,
+0x904,0x00000023,
+0x908,0x00000000,
+0x90c,0x01121313,
+0xa00,0x00d047c8,
+0xa04,0x80ff0008,
+0xa08,0x8ccd8300,
+0xa0c,0x2e62120f,
+0xa10,0x9500bb78,
+0xa14,0x11144028,
+0xa18,0x00881117,
+0xa1c,0x89140f00,
+0xa20,0x1a1b0000,
+0xa24,0x090e1317,
+0xa28,0x00000204,
+0xa2c,0x10d30000,
+0xc00,0x40071d40,
+0xc04,0x00a05633,
+0xc08,0x000000e4,
+0xc0c,0x6c6c6c6c,
+0xc10,0x08800000,
+0xc14,0x40000100,
+0xc18,0x08000000,
+0xc1c,0x40000100,
+0xc20,0x08000000,
+0xc24,0x40000100,
+0xc28,0x08000000,
+0xc2c,0x40000100,
+0xc30,0x6de9ac44,
+0xc34,0x469652cf,
+0xc38,0x49795994,
+0xc3c,0x0a979764,
+0xc40,0x1f7c403f,
+0xc44,0x000100b7,
+0xc48,0xec020000,
+0xc4c,0x007f037f,
+0xc50,0x69543420,
+0xc54,0x433c0094,
+0xc58,0x69543420,
+0xc5c,0x433c0094,
+0xc60,0x69543420,
+0xc64,0x433c0094,
+0xc68,0x69543420,
+0xc6c,0x433c0094,
+0xc70,0x2c7f000d,
+0xc74,0x0186175b,
+0xc78,0x0000001f,
+0xc7c,0x00b91612,
+0xc80,0x40000100,
+0xc84,0x20f60000,
+0xc88,0x20000080,
+0xc8c,0x20200000,
+0xc90,0x40000100,
+0xc94,0x00000000,
+0xc98,0x40000100,
+0xc9c,0x00000000,
+0xca0,0x00492492,
+0xca4,0x00000000,
+0xca8,0x00000000,
+0xcac,0x00000000,
+0xcb0,0x00000000,
+0xcb4,0x00000000,
+0xcb8,0x00000000,
+0xcbc,0x28000000,
+0xcc0,0x00000000,
+0xcc4,0x00000000,
+0xcc8,0x00000000,
+0xccc,0x00000000,
+0xcd0,0x00000000,
+0xcd4,0x00000000,
+0xcd8,0x64b22427,
+0xcdc,0x00766932,
+0xce0,0x00222222,
+0xce4,0x00000000,
+0xce8,0x37644302,
+0xcec,0x2f97d40c,
+0xd00,0x00000750,
+0xd04,0x00000403,
+0xd08,0x0000907f,
+0xd0c,0x00000001,
+0xd10,0xa0633333,
+0xd14,0x33333c63,
+0xd18,0x6a8f5b6b,
+0xd1c,0x00000000,
+0xd20,0x00000000,
+0xd24,0x00000000,
+0xd28,0x00000000,
+0xd2c,0xcc979975,
+0xd30,0x00000000,
+0xd34,0x00000000,
+0xd38,0x00000000,
+0xd3c,0x00027293,
+0xd40,0x00000000,
+0xd44,0x00000000,
+0xd48,0x00000000,
+0xd50,0x6437140a,
+0xd54,0x024dbd02,
+0xd58,0x00000000,
+0xd5c,0x30032064,
+0xd60,0x4653de68,
+0xd64,0x00518a3c,
+0xd68,0x00002101,
+0xf14,0x00000003,
+0xf4c,0x00000000,
+0xf00,0x00000300,
+};
+
+u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = {
+0x844,0xffffffff,0x00010000,
+0x804,0x0000000f,0x00000001,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00100002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000011,
+0xd04,0x0000000f,0x00000001,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300004,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000001,
+0x878,0x000f000f,0x00020002,
+0xe74,0x0f000000,0x00000006,
+0xe78,0x0f000000,0x00000006,
+0xe7c,0x0f000000,0x00000006,
+0xe80,0x0f000000,0x00000006,
+0x90c,0x000000ff,0x00000033,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x0000ffff,
+0x234,0xf8000000,0x00000013,
+};
+
+u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = {
+0xe00,0xffffffff,0x06090909,
+0xe04,0xffffffff,0x00030406,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x0a0c0d0e,
+0xe14,0xffffffff,0x04070809,
+0xe18,0xffffffff,0x0a0c0d0e,
+0xe1c,0xffffffff,0x04070809,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x02020202,
+0xe04,0xffffffff,0x00020202,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02020202,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02020202,
+0xe1c,0xffffffff,0x00000002,
+};
+
+u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x010,0x0002000f,
+0x011,0x00020101,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x0000f8f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x0009bd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x032,0x0000130d,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+0x013,0x00017cb0,
+0x013,0x00011cc0,
+0x013,0x0000dc60,
+0x013,0x00008c60,
+0x013,0x00004450,
+0x013,0x00000020,
+};
+
+u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+};
+
+u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = {
+0x020,0x00000035,
+0x048,0x0000000e,
+0x049,0x000000f0,
+0x04a,0x00000077,
+0x04b,0x00000083,
+0x0b5,0x00000021,
+0x0dc,0x000000ff,
+0x0dd,0x000000ff,
+0x0de,0x000000ff,
+0x0df,0x000000ff,
+0x116,0x00000000,
+0x117,0x00000000,
+0x118,0x00000000,
+0x119,0x00000000,
+0x11a,0x00000000,
+0x11b,0x00000000,
+0x11c,0x00000000,
+0x11d,0x00000000,
+0x160,0x0000000b,
+0x161,0x0000000b,
+0x162,0x0000000b,
+0x163,0x0000000b,
+0x164,0x0000000b,
+0x165,0x0000000b,
+0x166,0x0000000b,
+0x167,0x0000000b,
+0x168,0x0000000b,
+0x169,0x0000000b,
+0x16a,0x0000000b,
+0x16b,0x0000000b,
+0x16c,0x0000000b,
+0x16d,0x0000000b,
+0x16e,0x0000000b,
+0x16f,0x0000000b,
+0x170,0x0000000b,
+0x171,0x0000000b,
+0x172,0x0000000b,
+0x173,0x0000000b,
+0x174,0x0000000b,
+0x175,0x0000000b,
+0x176,0x0000000b,
+0x177,0x0000000b,
+0x178,0x0000000b,
+0x179,0x0000000b,
+0x17a,0x0000000b,
+0x17b,0x0000000b,
+0x17c,0x0000000b,
+0x17d,0x0000000b,
+0x17e,0x0000000b,
+0x17f,0x0000000b,
+0x236,0x0000000c,
+0x503,0x00000022,
+0x560,0x00000000,
+};
+
+u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = {
+0x0, };
+
+u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = {
+0xc78,0x7f000001,
+0xc78,0x7f010001,
+0xc78,0x7e020001,
+0xc78,0x7d030001,
+0xc78,0x7c040001,
+0xc78,0x7b050001,
+0xc78,0x7a060001,
+0xc78,0x79070001,
+0xc78,0x78080001,
+0xc78,0x77090001,
+0xc78,0x760a0001,
+0xc78,0x750b0001,
+0xc78,0x740c0001,
+0xc78,0x730d0001,
+0xc78,0x720e0001,
+0xc78,0x710f0001,
+0xc78,0x70100001,
+0xc78,0x6f110001,
+0xc78,0x6f120001,
+0xc78,0x6e130001,
+0xc78,0x6d140001,
+0xc78,0x6d150001,
+0xc78,0x6c160001,
+0xc78,0x6b170001,
+0xc78,0x6a180001,
+0xc78,0x6a190001,
+0xc78,0x691a0001,
+0xc78,0x681b0001,
+0xc78,0x671c0001,
+0xc78,0x661d0001,
+0xc78,0x651e0001,
+0xc78,0x641f0001,
+0xc78,0x63200001,
+0xc78,0x4c210001,
+0xc78,0x4b220001,
+0xc78,0x4a230001,
+0xc78,0x49240001,
+0xc78,0x48250001,
+0xc78,0x47260001,
+0xc78,0x46270001,
+0xc78,0x45280001,
+0xc78,0x44290001,
+0xc78,0x2c2a0001,
+0xc78,0x2b2b0001,
+0xc78,0x2a2c0001,
+0xc78,0x292d0001,
+0xc78,0x282e0001,
+0xc78,0x272f0001,
+0xc78,0x26300001,
+0xc78,0x25310001,
+0xc78,0x24320001,
+0xc78,0x23330001,
+0xc78,0x22340001,
+0xc78,0x09350001,
+0xc78,0x08360001,
+0xc78,0x07370001,
+0xc78,0x06380001,
+0xc78,0x05390001,
+0xc78,0x043a0001,
+0xc78,0x033b0001,
+0xc78,0x023c0001,
+0xc78,0x013d0001,
+0xc78,0x003e0001,
+0xc78,0x003f0001,
+0xc78,0x7f400001,
+0xc78,0x7f410001,
+0xc78,0x7e420001,
+0xc78,0x7d430001,
+0xc78,0x7c440001,
+0xc78,0x7b450001,
+0xc78,0x7a460001,
+0xc78,0x79470001,
+0xc78,0x78480001,
+0xc78,0x77490001,
+0xc78,0x764a0001,
+0xc78,0x754b0001,
+0xc78,0x744c0001,
+0xc78,0x734d0001,
+0xc78,0x724e0001,
+0xc78,0x714f0001,
+0xc78,0x70500001,
+0xc78,0x6f510001,
+0xc78,0x6f520001,
+0xc78,0x6e530001,
+0xc78,0x6d540001,
+0xc78,0x6d550001,
+0xc78,0x6c560001,
+0xc78,0x6b570001,
+0xc78,0x6a580001,
+0xc78,0x6a590001,
+0xc78,0x695a0001,
+0xc78,0x685b0001,
+0xc78,0x675c0001,
+0xc78,0x665d0001,
+0xc78,0x655e0001,
+0xc78,0x645f0001,
+0xc78,0x63600001,
+0xc78,0x4c610001,
+0xc78,0x4b620001,
+0xc78,0x4a630001,
+0xc78,0x49640001,
+0xc78,0x48650001,
+0xc78,0x47660001,
+0xc78,0x46670001,
+0xc78,0x45680001,
+0xc78,0x44690001,
+0xc78,0x2c6a0001,
+0xc78,0x2b6b0001,
+0xc78,0x2a6c0001,
+0xc78,0x296d0001,
+0xc78,0x286e0001,
+0xc78,0x276f0001,
+0xc78,0x26700001,
+0xc78,0x25710001,
+0xc78,0x24720001,
+0xc78,0x23730001,
+0xc78,0x22740001,
+0xc78,0x09750001,
+0xc78,0x08760001,
+0xc78,0x07770001,
+0xc78,0x06780001,
+0xc78,0x05790001,
+0xc78,0x047a0001,
+0xc78,0x037b0001,
+0xc78,0x027c0001,
+0xc78,0x017d0001,
+0xc78,0x007e0001,
+0xc78,0x007f0001,
+0xc78,0x3000001e,
+0xc78,0x3001001e,
+0xc78,0x3002001e,
+0xc78,0x3003001e,
+0xc78,0x3004001e,
+0xc78,0x3405001e,
+0xc78,0x3806001e,
+0xc78,0x3e07001e,
+0xc78,0x3e08001e,
+0xc78,0x4409001e,
+0xc78,0x460a001e,
+0xc78,0x480b001e,
+0xc78,0x480c001e,
+0xc78,0x4e0d001e,
+0xc78,0x560e001e,
+0xc78,0x5a0f001e,
+0xc78,0x5e10001e,
+0xc78,0x6211001e,
+0xc78,0x6c12001e,
+0xc78,0x7213001e,
+0xc78,0x7214001e,
+0xc78,0x7215001e,
+0xc78,0x7216001e,
+0xc78,0x7217001e,
+0xc78,0x7218001e,
+0xc78,0x7219001e,
+0xc78,0x721a001e,
+0xc78,0x721b001e,
+0xc78,0x721c001e,
+0xc78,0x721d001e,
+0xc78,0x721e001e,
+0xc78,0x721f001e,
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.c
@@ -0,0 +1,6398 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+/*Created on  2009/11/17, 16:15*/
+
+#ifdef RTL8192SE
+#include "r8192S_hwimg.h"
+
+u8 Rtl8192SEFwImgArray[ImgArrayLength] = {
+0x92,0x81,0x4a,0x70,0x30,0x00,0x00,0x00,0x08,0xa4,0x00,0x00,0x88,0xb5,0x00,0x00,
+0x30,0x00,0x00,0x00,0x00,0xb4,0x00,0x00,0x4a,0x00,0x00,0x00,0x11,0x17,0x13,0x29,
+0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37,
+0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,
+0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x01,0x80,0x1a,0x3c,0x10,0x9d,0x5a,0x27,
+0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf,
+0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf,
+0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf,
+0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00,
+0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf,
+0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf,
+0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf,
+0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf,
+0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xda,0x26,0x00,0x08,
+0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xff,0xff,0x88,0x30,0x80,0x28,0x08,0x00,0x2a,0xb0,0x0a,0x3c,0x21,0x38,0xaa,0x00,
+0x0c,0x00,0xe6,0x8c,0x02,0x80,0x03,0x3c,0xcc,0x3f,0x63,0x24,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x21,0x28,0xa3,0x00,0xff,0x00,0xc4,0x30,0xff,0x00,0x09,0x24,
+0x00,0x00,0x45,0xac,0x00,0x00,0x43,0xac,0x05,0x00,0x89,0x10,0x00,0x00,0x00,0x00,
+0x00,0x80,0xc2,0x30,0x04,0x00,0x40,0x10,0x00,0x80,0x02,0x3c,0x0c,0x00,0xe2,0xac,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0x00,0xff,0x02,0x3c,0x24,0x10,0xc2,0x00,
+0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x0a,0x01,0x40,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x43,0x30,0x12,0x00,0x69,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa3,0xa0,0x40,0x00,0x83,0x90,0x00,0x00,0xa6,0x90,0xff,0x00,0x63,0x30,
+0xff,0x00,0xc2,0x30,0xfa,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x20,0xb0,0x03,0x3c,
+0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x46,0x8c,0x25,0xb0,0x03,0x3c,
+0xb0,0x03,0x63,0x34,0x21,0x10,0xc0,0x00,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x90,0xe7,0x00,0x00,0x08,0xff,0x00,0xc2,0x30,
+0xff,0xff,0x84,0x30,0x80,0x20,0x04,0x00,0x2a,0xb0,0x02,0x3c,0x21,0x48,0x82,0x00,
+0x00,0x00,0x25,0x8d,0x02,0x80,0x02,0x3c,0xec,0x3f,0x42,0x24,0x21,0x40,0x82,0x00,
+0x25,0xb0,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb0,0x03,0x67,0x34,0xcc,0x3f,0x42,0x24,
+0xff,0x00,0xa4,0x30,0xff,0x00,0x03,0x24,0x00,0x00,0xe8,0xac,0x00,0x80,0xa6,0x30,
+0x00,0x00,0xe2,0xac,0x06,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0xff,0x02,0x3c,
+0x05,0x00,0xc0,0x10,0x24,0x10,0xa2,0x00,0x00,0x80,0x02,0x3c,0x00,0x00,0x22,0xad,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0xfd,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x00,0x00,0x03,0x91,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x0c,0x00,0x65,0x8c,0x00,0x00,0x00,0x00,0x21,0x10,0xa0,0x00,0x00,0x00,0xe5,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c,
+0xe0,0xff,0xbd,0x27,0x18,0x03,0xa3,0x34,0x68,0x04,0x42,0x24,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x02,0x3c,0x03,0x00,0x46,0x34,
+0x00,0x00,0xc3,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x70,0x30,0x10,0x00,0x02,0x32,
+0x18,0x00,0x40,0x10,0x02,0x80,0x11,0x3c,0x78,0x1b,0x27,0x26,0xec,0x23,0xe4,0x94,
+0x10,0x00,0x02,0x24,0x00,0x00,0xc2,0xa0,0x08,0x00,0x80,0x10,0x1c,0x03,0xa3,0x34,
+0xf0,0x23,0xe2,0x94,0xb0,0x03,0xa4,0x34,0x00,0x00,0x62,0xa0,0x00,0x00,0x80,0xac,
+0xec,0x23,0xe0,0xa4,0xf0,0x23,0xe0,0xa4,0x00,0x00,0x04,0x24,0x02,0x80,0x05,0x3c,
+0x02,0x80,0x06,0x3c,0x8c,0x43,0xa2,0x8c,0xbc,0x44,0xc3,0x8c,0x01,0x00,0x84,0x24,
+0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0xec,0x23,0xe4,0xa4,0x8c,0x43,0xa2,0xac,
+0xbc,0x44,0xc3,0xac,0x00,0x16,0x10,0x00,0x03,0x16,0x02,0x00,0x71,0x00,0x40,0x04,
+0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x40,0x00,0x02,0x32,0x16,0x00,0x40,0x10,0x78,0x1b,0x24,0x26,
+0x42,0xb0,0x03,0x3c,0x40,0x00,0x02,0x24,0x03,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,
+0x02,0x80,0x03,0x3c,0xb6,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x1a,0x00,0x40,0x10,
+0x02,0x80,0x04,0x3c,0xb6,0x44,0x60,0xa0,0x02,0x80,0x04,0x3c,0xb2,0x44,0x83,0x90,
+0xfd,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0xb2,0x44,0x83,0xa0,0xb2,0x44,0x82,0x90,
+0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30,0x2c,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x24,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
+0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
+0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x9e,0x44,0x82,0x90,0x02,0x80,0x05,0x3c,
+0x01,0x00,0x42,0x24,0x9e,0x44,0x82,0xa0,0xb2,0x44,0xa3,0x90,0xef,0xff,0x02,0x24,
+0x24,0x18,0x62,0x00,0xb2,0x44,0xa3,0xa0,0x9e,0x44,0x82,0x90,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x2c,0x24,0x00,0x40,0x14,0x78,0x1b,0x23,0x26,0xe8,0x0a,0x62,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x3d,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xdc,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xb9,0x44,0x62,0xa0,0x65,0x01,0x00,0x08,0x78,0x1b,0x24,0x26,0xb0,0x44,0x40,0xa0,
+0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,
+0x78,0x1b,0x24,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
+0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
+0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x02,0x80,0x05,0x3c,0x02,0x80,0x03,0x3c,
+0xac,0x44,0xa2,0x8c,0xa4,0x44,0x64,0x8c,0x02,0x80,0x03,0x3c,0x21,0x10,0x44,0x00,
+0xac,0x44,0xa2,0xac,0xac,0x44,0xa4,0x8c,0x25,0xb0,0x02,0x3c,0xe4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0xa0,0x44,0x62,0x94,0x02,0x80,0x05,0x3c,0x99,0x44,0xa4,0x90,
+0xff,0xff,0x42,0x30,0x40,0x10,0x02,0x00,0xf6,0xff,0x42,0x24,0x02,0x80,0x03,0x3c,
+0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x0c,0x88,0x44,0x62,0xac,0x95,0x01,0x00,0x08,
+0x78,0x1b,0x24,0x26,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
+0x1b,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0x49,0x01,0x00,0x08,0x00,0x00,0x00,0x00,
+0xb9,0x44,0x40,0xa0,0x65,0x01,0x00,0x08,0x78,0x1b,0x24,0x26,0xff,0x00,0x84,0x30,
+0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,0x19,0x00,0x40,0x10,
+0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0x48,0xaf,0x63,0x24,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,
+0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,0x07,0x00,0xe2,0x30,
+0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,0x00,0x00,0x00,0x00,
+0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,0x21,0x10,0xe8,0x00,
+0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,0x08,0x00,0x82,0xac,
+0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x43,0xb0,0x02,0x3c,
+0xd3,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,
+0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x54,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x48,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0xd3,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,
+0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x24,0x00,0x44,0x34,
+0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x18,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
+0xd3,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0xd3,0x01,0x00,0x08,0x43,0xb0,0x04,0x3c,
+0x01,0x00,0x02,0x24,0x43,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,0x88,0x00,0x65,0x34,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,0x05,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00,
+0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,0xf5,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c,
+0xd0,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,0x48,0x08,0x42,0x24,0x00,0x00,0x62,0xac,
+0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x2c,0x00,0xbf,0xaf,
+0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x08,0x00,0xf3,0x8c,0xff,0x00,0xc6,0x30,
+0x00,0x01,0x02,0x24,0x0c,0x00,0xf1,0x84,0x23,0x10,0x46,0x00,0xff,0xff,0xa3,0x30,
+0xff,0xff,0x50,0x30,0xff,0x00,0x94,0x30,0xd0,0x03,0x08,0x35,0x21,0x30,0xc5,0x00,
+0x21,0x20,0x80,0x02,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0x02,0x92,0x03,0x00,
+0x00,0x00,0x11,0xad,0x00,0x00,0x13,0xad,0x42,0x02,0x00,0x08,0x00,0x00,0x00,0x00,
+0x01,0x01,0x23,0x2a,0xff,0xff,0x22,0x32,0x21,0x98,0x70,0x02,0x21,0x20,0x80,0x02,
+0x00,0x01,0x10,0x24,0x00,0x02,0x00,0x0c,0x0b,0x80,0x43,0x00,0xc0,0x10,0x12,0x00,
+0x28,0xb0,0x03,0x3c,0x21,0x10,0x43,0x00,0x00,0x00,0x45,0x90,0x20,0x10,0x06,0x3c,
+0x21,0x20,0x80,0x02,0xff,0x00,0xb2,0x30,0x00,0x12,0x12,0x00,0x21,0x30,0x46,0x00,
+0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x23,0x18,0x30,0x02,0x00,0x8c,0x03,0x00,0x03,0x8c,0x11,0x00,0xe8,0xff,0x20,0x1e,
+0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,
+0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x00,0x00,0xe8,0x94,
+0x28,0x24,0x83,0x8c,0x21,0x80,0xa0,0x00,0x27,0x10,0x08,0x00,0x2b,0x10,0x62,0x00,
+0x03,0x00,0x40,0x10,0x21,0x28,0xc0,0x00,0x21,0x10,0x68,0x00,0x28,0x24,0x82,0xac,
+0x04,0x24,0x82,0x8c,0x04,0x00,0xe3,0x8c,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x20,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0xe2,0x8c,0xff,0xe0,0x03,0x3c,
+0xff,0xff,0x63,0x34,0x00,0x26,0x04,0x00,0x24,0x10,0x43,0x00,0x25,0x18,0x44,0x00,
+0x10,0x00,0xe4,0x8c,0x00,0x00,0x00,0x00,0x1a,0x00,0x80,0x04,0x08,0x00,0xe3,0xac,
+0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x02,0x00,0x04,0x24,
+0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x0f,0x00,0x42,0x34,0x08,0x00,0xe2,0xac,
+0x21,0x30,0x00,0x02,0x01,0x00,0x02,0x24,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xa2,0xaf,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x50,0xac,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb0,0x8f,0x02,0x00,0x04,0x24,0x00,0x02,0x00,0x08,
+0x20,0x00,0xbd,0x27,0x10,0x00,0xe4,0x8c,0x08,0x00,0xe3,0x8c,0xe9,0xff,0x81,0x04,
+0x82,0x11,0x03,0x00,0x14,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x42,0x12,0x02,0x00,
+0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xe2,0xff,0x40,0x14,0x82,0x11,0x03,0x00,
+0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x70,0x02,0x00,0x08,
+0x10,0x00,0xe2,0xac,0xff,0xff,0x84,0x30,0x2a,0xb0,0x02,0x3c,0x0d,0x00,0x42,0x34,
+0x80,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x04,0x00,0x82,0x24,0xff,0xff,0xa5,0x30,
+0x0b,0x20,0x45,0x00,0x01,0x00,0x03,0x24,0x02,0x00,0x02,0x24,0x00,0x00,0x83,0xa0,
+0x00,0x00,0x82,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc0,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x24,0x00,0xb3,0xaf,0x78,0x1b,0x53,0x24,
+0x00,0x80,0x02,0x3c,0x38,0x00,0xbe,0xaf,0x8c,0x0a,0x42,0x24,0xb0,0x03,0x7e,0x34,
+0x18,0x03,0x63,0x34,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x21,0xa8,0x60,0x02,0xc0,0x24,0x62,0x8e,
+0x2c,0x25,0x72,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc4,0x24,0x62,0xae,
+0x00,0x00,0xd2,0xaf,0x00,0x02,0x00,0x0c,0x21,0xa0,0xa0,0x02,0x2c,0x25,0x64,0x8e,
+0x30,0x25,0x63,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
+0x0a,0x18,0x82,0x00,0x02,0x80,0x02,0x3c,0x2c,0x25,0x63,0xae,0x74,0xaf,0x42,0x24,
+0x2c,0x25,0xa5,0x8e,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,
+0x02,0x80,0x02,0x3c,0xff,0xff,0x43,0x32,0x25,0x80,0x62,0x00,0x00,0x00,0x90,0xac,
+0x0c,0x00,0x02,0x92,0xff,0x00,0x16,0x24,0x01,0x00,0x17,0x24,0x00,0x00,0x82,0xac,
+0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x21,0x20,0x00,0x00,0x00,0x1a,0x11,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x05,0x00,0x36,0x12,0x40,0x00,0x07,0x24,
+0xc0,0x24,0xa3,0xae,0x74,0x24,0xb1,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x00,0x00,0x02,0x96,0x24,0x24,0x83,0x8e,0x21,0x28,0x40,0x02,0x27,0x30,0x02,0x00,
+0x21,0x10,0x62,0x00,0x2b,0x18,0x66,0x00,0x21,0x20,0x00,0x00,0x02,0x00,0x60,0x10,
+0x40,0x00,0x07,0x24,0x24,0x24,0x82,0xae,0x04,0x00,0x06,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0xc6,0x30,0x24,0x18,0x62,0x00,
+0x00,0x36,0x06,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x06,0x3c,0x25,0x18,0x66,0x00,0xc0,0xff,0x02,0x24,
+0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0xc4,0x24,0xa6,0x8e,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xb7,0xaf,0xc4,0x24,0xa3,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x21,0x20,0x00,0x00,0x2a,0xb0,0x02,0x3c,
+0x01,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x57,0xa0,0x00,0x00,0x43,0xa0,
+0xae,0xff,0x36,0x16,0x41,0xb0,0x03,0x3c,0x08,0x0b,0xa2,0x8e,0x3c,0x00,0xbf,0x8f,
+0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,0x38,0x00,0xbe,0x8f,0x08,0x0b,0xa2,0xae,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
+0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x68,0x0c,0x42,0x24,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
+0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x55,0x24,0xb0,0x03,0x96,0x34,
+0x4e,0x03,0x00,0x08,0x21,0xf0,0xa0,0x02,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x71,0x24,0x08,0x00,0x02,0xae,0xdc,0x24,0x26,0x8e,
+0x01,0x00,0x04,0x24,0x21,0x28,0x80,0x02,0x40,0x00,0x07,0x24,0x01,0x00,0x12,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xb2,0xaf,0xdc,0x24,0x23,0x8e,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x82,0x0b,0x22,0x92,0x00,0x00,0x00,0x00,0x88,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,
+0x09,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x52,0xa0,0x00,0x00,0x43,0xa0,
+0x9d,0x00,0x77,0x12,0x00,0x00,0x00,0x00,0xd8,0x24,0xa2,0x8e,0x44,0x25,0xb4,0x8e,
+0x01,0x00,0x04,0x24,0x00,0x00,0xc2,0xae,0xdc,0x24,0xa2,0xae,0x00,0x00,0xd4,0xae,
+0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x25,0xa4,0x8e,0x48,0x25,0xa3,0x8e,
+0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,
+0x44,0x25,0xa3,0xae,0x44,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xae,
+0x02,0x80,0x11,0x3c,0xff,0xff,0x82,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xd0,0xae,
+0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xae,0x02,0x00,0x02,0x92,
+0x06,0x00,0x03,0x96,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30,
+0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00,
+0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c,
+0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00,
+0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00,
+0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c,
+0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x17,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,
+0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x77,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0b,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30,
+0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,
+0x6a,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x0c,0x00,0x13,0x92,0xff,0x00,0x17,0x24,
+0x0d,0x00,0x77,0x12,0x02,0x80,0x02,0x3c,0x78,0x1b,0x48,0x24,0x00,0x1a,0x13,0x00,
+0x20,0x10,0x02,0x3c,0x44,0x25,0x05,0x8d,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x01,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0xd8,0x24,0x03,0xad,0x78,0x24,0x13,0xa1,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
+0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
+0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x82,0x11,0x03,0x00,
+0x01,0x00,0x42,0x30,0x78,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x08,0x00,0x03,0xae,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x71,0x24,0xdc,0x24,0x26,0x8e,0x01,0x00,0x04,0x24,
+0x21,0x28,0x80,0x02,0x40,0x00,0x07,0x24,0x01,0x00,0x12,0x24,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xb2,0xaf,0xdc,0x24,0x23,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
+0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24,0x82,0x0b,0x22,0x92,
+0x00,0x00,0x00,0x00,0x7a,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0x32,0xa2,
+0x02,0x00,0x02,0x92,0x02,0x80,0x03,0x3c,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30,
+0x25,0x10,0x43,0x00,0x02,0x00,0x45,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0xa4,0x30,
+0x00,0xc0,0x84,0x24,0xff,0xff,0x84,0x30,0x2c,0x22,0x00,0x0c,0x83,0x0b,0x25,0xa2,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,
+0x09,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x52,0xa0,0x00,0x00,0x43,0xa0,
+0x65,0xff,0x77,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x22,0x8e,0x41,0xb0,0x03,0x3c,
+0x3c,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,0x38,0x00,0xbe,0x8f,
+0x08,0x0b,0x22,0xae,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x55,0x1f,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x8a,0x03,0x00,0x08,0x02,0x80,0x03,0x3c,0xb1,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0x94,0xff,0x60,0x14,0x00,0x10,0x82,0x34,0x9a,0x03,0x00,0x08,
+0x00,0x00,0xa2,0xa4,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x10,0x63,0x24,
+0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,
+0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
+0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0x40,0x10,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xa8,0x00,0x00,
+0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,0x01,0x00,0x15,0x24,
+0x54,0x44,0xc2,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x52,0x24,0x02,0x80,0x17,0x3c,0x02,0x80,0x14,0x3c,
+0x21,0xf0,0x40,0x02,0x4c,0x04,0x00,0x08,0x21,0xb0,0x40,0x02,0x58,0x24,0xd0,0xa3,
+0xfc,0x24,0x45,0x8e,0x90,0x24,0x46,0x8e,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x94,0x24,0xc5,0x8e,0x21,0x20,0x20,0x02,
+0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02,0x21,0x20,0x00,0x00,0x21,0x28,0xa0,0x02,
+0x95,0x02,0x00,0x0c,0x21,0x30,0x00,0x02,0x9c,0x43,0x82,0x96,0x25,0xb0,0x05,0x3c,
+0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24,0x9c,0x43,0x82,0xa6,0x9c,0x43,0x83,0x96,
+0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x5f,0x00,0x02,0x12,0x00,0x00,0x00,0x00,
+0x90,0x24,0x42,0x8e,0x03,0x00,0x04,0x24,0xfc,0x24,0x53,0x8e,0x00,0x02,0x00,0x0c,
+0x94,0x24,0x42,0xae,0xfc,0x24,0x44,0x8e,0x00,0x25,0x43,0x8e,0x02,0x80,0x10,0x3c,
+0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,
+0xff,0xff,0x65,0x32,0x25,0x88,0xb0,0x00,0xfc,0x24,0x43,0xae,0x02,0x00,0x22,0x92,
+0x06,0x00,0x23,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30,
+0x11,0x00,0x60,0x10,0x25,0x28,0x50,0x00,0xec,0x0c,0x44,0x96,0x00,0xf0,0x06,0x3c,
+0xff,0xff,0xc6,0x34,0x01,0x00,0x82,0x24,0xec,0x0c,0x42,0xa6,0x0c,0x00,0x23,0x8e,
+0xff,0x0f,0x84,0x30,0x00,0x14,0x04,0x00,0x24,0x18,0x66,0x00,0x25,0x18,0x62,0x00,
+0x0c,0x00,0x23,0xae,0x16,0x00,0xa2,0x94,0x00,0x21,0x04,0x00,0x0f,0x00,0x42,0x30,
+0x25,0x10,0x44,0x00,0x16,0x00,0xa2,0xa4,0x98,0x44,0xe2,0x92,0x00,0x00,0x00,0x00,
+0x1c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x30,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,
+0x0b,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x00,0x22,0x92,0x00,0x00,0x00,0x00,
+0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x25,0x28,0x50,0x00,0x00,0x00,0xa4,0x94,
+0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,0x43,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,
+0x98,0x44,0xe2,0x92,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10,
+0x02,0x80,0x03,0x3c,0x0c,0x00,0x30,0x92,0xff,0x00,0x02,0x24,0xa6,0xff,0x02,0x12,
+0x00,0x12,0x10,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x9b,0xff,0xa0,0x16,
+0x90,0x24,0xc2,0xaf,0x34,0x04,0x00,0x08,0x54,0x24,0xd0,0xa3,0x55,0x1f,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x7c,0x04,0x00,0x08,0x02,0x80,0x03,0x3c,0xb3,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0,
+0x91,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x29,0x00,0xa0,0x12,0x2a,0xb0,0x02,0x3c,
+0x58,0x24,0xc3,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x41,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x08,0x0b,0xa4,0x8c,
+0x01,0x00,0x02,0x3c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
+0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00,
+0xbb,0xff,0x60,0x14,0x00,0x10,0x82,0x34,0x8c,0x04,0x00,0x08,0x00,0x00,0xa2,0xa4,
+0x54,0x24,0xc3,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x40,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x08,0x0b,0xa4,0x8c,
+0x01,0x00,0x02,0x3c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,
+0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
+0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf,
+0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,
+0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,
+0x20,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0xd8,0x13,0x63,0x24,0x10,0x00,0xa4,0x30,
+0x00,0x00,0x43,0xac,0x18,0x00,0xa0,0xaf,0x04,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,
+0x01,0x00,0x03,0x24,0xef,0x00,0xa2,0x30,0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0,
+0x54,0x44,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26,0x21,0xa8,0x40,0x00,0x02,0x80,0x16,0x3c,
+0x39,0x05,0x00,0x08,0x21,0xf0,0x80,0x02,0x60,0x24,0x71,0xa0,0x78,0x1b,0xe2,0x26,
+0x9c,0x24,0x46,0x8c,0x08,0x25,0x45,0x8c,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x78,0x1b,0xf2,0x26,0xa0,0x24,0x45,0x8e,
+0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02,0x18,0x00,0xa5,0x8f,
+0x02,0x00,0x04,0x24,0x95,0x02,0x00,0x0c,0x21,0x30,0x20,0x02,0x9c,0x43,0xc2,0x96,
+0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24,0x9c,0x43,0xc2,0xa6,
+0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x71,0x00,0x22,0x12,
+0x00,0x00,0x00,0x00,0x9c,0x24,0x82,0x8e,0x08,0x25,0x93,0x8e,0x04,0x00,0x04,0x24,
+0x00,0x00,0xa2,0xae,0xa0,0x24,0x82,0xae,0x00,0x00,0xb3,0xae,0x00,0x02,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x08,0x25,0x84,0x8e,0x0c,0x25,0x83,0x8e,0x40,0x00,0x84,0x24,
+0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x08,0x25,0x83,0xae,
+0x08,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae,0x02,0x80,0x11,0x3c,
+0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x03,0x92,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae,0x02,0x00,0x02,0x92,0x06,0x00,0x03,0x96,
+0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30,0x12,0x00,0x60,0x10,
+0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,
+0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c,0xff,0x0f,0x63,0x30,
+0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00,0x25,0x20,0x85,0x00,
+0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00,0x0f,0x00,0x42,0x30,
+0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x31,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,
+0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,
+0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,
+0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,
+0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10,0x02,0x80,0x03,0x3c,
+0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x97,0xff,0x22,0x12,0x20,0x10,0x03,0x3c,
+0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00,0x78,0x1b,0xe3,0x26,0x9c,0x24,0x62,0xac,
+0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x87,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0x1f,0x05,0x00,0x08,0x5c,0x24,0x71,0xa0,0xb3,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0,0x8c,0x05,0x00,0x08,
+0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24,0x76,0x05,0x00,0x08,
+0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x28,0x00,0x60,0x10,
+0x2a,0xb0,0x02,0x3c,0x60,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,
+0x43,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,
+0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,
+0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,
+0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0xb7,0xff,0x60,0x14,
+0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34,0x87,0x05,0x00,0x08,0x00,0x00,0xa2,0xa4,
+0x5c,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x42,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,
+0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,
+0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,
+0x20,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,
+0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,
+0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,
+0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,
+0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
+0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0xd0,0x17,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x18,0x00,0xa0,0xaf,
+0x04,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0x01,0x00,0x03,0x24,0xfe,0x00,0xa2,0x30,
+0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0,0x54,0x44,0xc3,0x90,0x25,0xb0,0x02,0x3c,
+0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26,0x21,0xa8,0x40,0x00,
+0x02,0x80,0x16,0x3c,0x36,0x06,0x00,0x08,0x21,0xf0,0x80,0x02,0x68,0x24,0x71,0xa0,
+0x78,0x1b,0xe2,0x26,0xa8,0x24,0x46,0x8c,0x14,0x25,0x45,0x8c,0x05,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x78,0x1b,0xf2,0x26,
+0xac,0x24,0x45,0x8e,0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02,
+0x18,0x00,0xa5,0x8f,0x04,0x00,0x04,0x24,0x95,0x02,0x00,0x0c,0x21,0x30,0x20,0x02,
+0x9c,0x43,0xc2,0x96,0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24,
+0x9c,0x43,0xc2,0xa6,0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,
+0x71,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xa8,0x24,0x82,0x8e,0x14,0x25,0x93,0x8e,
+0x05,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0xac,0x24,0x82,0xae,0x00,0x00,0xb3,0xae,
+0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x25,0x84,0x8e,0x18,0x25,0x83,0x8e,
+0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,
+0x14,0x25,0x83,0xae,0x14,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae,
+0x02,0x80,0x11,0x3c,0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xb0,0xae,
+0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae,0x02,0x00,0x02,0x92,
+0x06,0x00,0x03,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30,
+0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00,
+0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c,
+0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00,
+0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00,
+0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c,
+0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,
+0x31,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0c,0x00,0x40,0x10,
+0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,
+0xff,0xff,0x42,0x30,0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24,
+0x0c,0x00,0x83,0x30,0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0x98,0x44,0x62,0x90,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10,
+0x02,0x80,0x03,0x3c,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x97,0xff,0x22,0x12,
+0x20,0x10,0x03,0x3c,0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00,0x78,0x1b,0xe3,0x26,
+0xa8,0x24,0x62,0xac,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x87,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x1c,0x06,0x00,0x08,0x64,0x24,0x71,0xa0,0xb3,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0,
+0x89,0x06,0x00,0x08,0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x73,0x06,0x00,0x08,0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,
+0x28,0x00,0x60,0x10,0x2a,0xb0,0x02,0x3c,0x68,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,
+0x21,0x20,0x60,0x00,0x45,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,
+0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,
+0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,
+0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00,
+0xb7,0xff,0x60,0x14,0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34,0x84,0x06,0x00,0x08,
+0x00,0x00,0xa2,0xa4,0x64,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,
+0x44,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,
+0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,
+0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,
+0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,
+0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0xa2,0xac,0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,
+0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,
+0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,
+0x02,0x80,0x06,0x3c,0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0xc4,0x1b,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
+0x18,0x00,0xa0,0xaf,0x04,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0x01,0x00,0x03,0x24,
+0xfd,0x00,0xa2,0x30,0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0,0x54,0x44,0xc3,0x90,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26,
+0x21,0xa8,0x40,0x00,0x02,0x80,0x16,0x3c,0x33,0x07,0x00,0x08,0x21,0xf0,0x80,0x02,
+0x70,0x24,0x71,0xa0,0x78,0x1b,0xe2,0x26,0xb4,0x24,0x46,0x8c,0x20,0x25,0x45,0x8c,
+0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x78,0x1b,0xf2,0x26,0xb8,0x24,0x45,0x8e,0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c,
+0x21,0x30,0x60,0x02,0x18,0x00,0xa5,0x8f,0x06,0x00,0x04,0x24,0x95,0x02,0x00,0x0c,
+0x21,0x30,0x20,0x02,0x9c,0x43,0xc2,0x96,0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34,
+0x01,0x00,0x42,0x24,0x9c,0x43,0xc2,0xa6,0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24,
+0x00,0x00,0x83,0xa4,0x71,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xb4,0x24,0x82,0x8e,
+0x20,0x25,0x93,0x8e,0x06,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0xb8,0x24,0x82,0xae,
+0x00,0x00,0xb3,0xae,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x20,0x25,0x84,0x8e,
+0x24,0x25,0x83,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
+0x0a,0x18,0x82,0x00,0x20,0x25,0x83,0xae,0x20,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0xae,0x02,0x80,0x11,0x3c,0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00,
+0x00,0x00,0xb0,0xae,0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae,
+0x02,0x00,0x02,0x92,0x06,0x00,0x03,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,
+0x01,0x00,0x63,0x30,0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,
+0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,
+0x00,0xf0,0x02,0x3c,0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,
+0x24,0x20,0x82,0x00,0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,
+0x00,0x19,0x03,0x00,0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,
+0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x30,0x31,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,
+0x0c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
+0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,
+0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,
+0x0f,0x00,0x43,0x10,0x02,0x80,0x03,0x3c,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
+0x97,0xff,0x22,0x12,0x20,0x10,0x03,0x3c,0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00,
+0x78,0x1b,0xe3,0x26,0xb4,0x24,0x62,0xac,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,
+0x87,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x19,0x07,0x00,0x08,0x6c,0x24,0x71,0xa0,
+0xb3,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0xee,0xff,0x40,0x10,
+0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,
+0xb2,0x44,0x62,0xa0,0x86,0x07,0x00,0x08,0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x70,0x07,0x00,0x08,0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f,
+0x00,0x00,0x00,0x00,0x28,0x00,0x60,0x10,0x2a,0xb0,0x02,0x3c,0x70,0x24,0x43,0x92,
+0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x47,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
+0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,
+0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,
+0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,
+0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,
+0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0xb7,0xff,0x60,0x14,0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34,
+0x81,0x07,0x00,0x08,0x00,0x00,0xa2,0xa4,0x6c,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,
+0x21,0x20,0x60,0x00,0x46,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,
+0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,
+0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,
+0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,
+0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xb8,0x1f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,
+0x10,0x0b,0xa2,0x8c,0x08,0x0b,0xa4,0x8c,0x00,0x08,0x03,0x3c,0x24,0x10,0x43,0x00,
+0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,
+0x08,0x0b,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,
+0x18,0x03,0x83,0x34,0x14,0x20,0x42,0x24,0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
+0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x02,0x80,0x14,0x3c,0x78,0x1b,0x93,0x26,0xfc,0x00,0x82,0x34,
+0x00,0x00,0x45,0x8c,0xe4,0x0a,0x66,0x96,0x94,0x25,0x63,0x96,0x8c,0x25,0x67,0x8e,
+0x23,0x28,0xa6,0x00,0x21,0x10,0xa3,0x00,0x23,0x88,0x47,0x00,0xb0,0x03,0x84,0x34,
+0x23,0x30,0x23,0x02,0x2b,0x10,0x71,0x00,0x00,0x00,0x83,0xac,0x00,0x00,0x91,0xac,
+0x0b,0x88,0xc2,0x00,0x21,0x20,0x20,0x02,0x39,0x15,0x00,0x0c,0x90,0x25,0x65,0xae,
+0x4b,0x00,0x40,0x10,0x21,0x90,0x40,0x00,0x0c,0x00,0x51,0xac,0x8c,0x25,0x68,0x8e,
+0x90,0x25,0x62,0x8e,0x08,0x00,0x45,0x8e,0x20,0xbd,0x03,0x3c,0x88,0x03,0x63,0x34,
+0x2b,0x10,0x48,0x00,0x40,0x10,0x15,0x3c,0x21,0x20,0x00,0x00,0xff,0xff,0x27,0x32,
+0x00,0x00,0x65,0xac,0x28,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xe4,0x0a,0x66,0x96,
+0x08,0x00,0x42,0x96,0x40,0x10,0x05,0x3c,0x21,0x20,0x00,0x00,0x21,0x30,0x06,0x01,
+0x25,0x28,0x45,0x00,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x02,0x3c,
+0x68,0x41,0x42,0x24,0x78,0x1b,0x84,0x26,0x90,0x25,0x83,0x8c,0x04,0x00,0x45,0x8c,
+0x8c,0x25,0x83,0xac,0x00,0x00,0x42,0xae,0x04,0x00,0x52,0xac,0x00,0x00,0xb2,0xac,
+0x04,0x00,0x45,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x78,0x1b,0x85,0x26,0x10,0x0b,0xa2,0x8c,0x08,0x0b,0xa3,0x8c,
+0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
+0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x04,0x00,0x42,0x30,
+0x25,0x18,0x62,0x00,0x41,0xb0,0x04,0x3c,0x38,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,
+0x08,0x00,0xe0,0x03,0x08,0x0b,0xa3,0xac,0x94,0x25,0x70,0x8e,0x08,0x00,0x45,0x96,
+0xe4,0x0a,0x66,0x96,0x23,0x80,0x08,0x02,0xff,0xff,0x10,0x32,0x21,0x30,0x06,0x01,
+0x25,0x28,0xb5,0x00,0x21,0x38,0x00,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x00,0x02,0x00,0x0c,0x21,0x20,0x00,0x00,0x08,0x00,0x45,0x96,0xe4,0x0a,0x62,0x96,
+0x23,0x38,0x30,0x02,0x25,0x28,0xb5,0x00,0x21,0xb0,0x06,0x3c,0x21,0x28,0xb0,0x00,
+0x21,0x30,0x46,0x00,0xff,0xff,0xe7,0x30,0x3d,0x08,0x00,0x08,0x21,0x20,0x00,0x00,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x04,0x3c,0x58,0x44,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x63,0x34,
+0x58,0x44,0x83,0xac,0x00,0x60,0x82,0x40,0x49,0x08,0x00,0x08,0x00,0x00,0x00,0x00,
+0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x00,0x22,0x63,0x24,
+0x18,0x03,0x42,0x34,0x2a,0xb0,0x04,0x3c,0x00,0x00,0x43,0xac,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
+0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
+0x18,0x00,0xb0,0xaf,0x2c,0x00,0x84,0x34,0x00,0x00,0x88,0x8c,0xff,0x00,0x02,0x24,
+0xff,0x00,0x03,0x31,0x9e,0x00,0x62,0x10,0x00,0x80,0x02,0x31,0x33,0x00,0x40,0x10,
+0x00,0xff,0x02,0x3c,0x00,0x80,0x02,0x3c,0x00,0x00,0x82,0xac,0xff,0x00,0x02,0x24,
+0x10,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x78,0x1b,0x50,0x24,0xff,0x00,0x03,0x31,
+0x50,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0xe4,0x24,0x03,0xae,0x21,0x30,0x60,0x00,0x80,0x24,0x08,0xa2,0x0a,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x01,0x00,0x03,0x24,
+0x58,0x25,0x03,0xa2,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x58,0x25,0x83,0x90,
+0x01,0x00,0x02,0x24,0x25,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0x78,0x1b,0x70,0x24,
+0x59,0x25,0x02,0x92,0x00,0x00,0x00,0x00,0x08,0x00,0x40,0x10,0x00,0x04,0x03,0x3c,
+0x10,0x0b,0x02,0x8e,0x08,0x0b,0x04,0x8e,0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x0b,0x04,0xae,0x3c,0x00,0xbf,0x8f,
+0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x24,0x10,0x02,0x01,
+0xcf,0xff,0x40,0x10,0xff,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24,
+0x80,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x0c,0x00,0x68,0x8c,0x9b,0x08,0x00,0x08,0xff,0x00,0x03,0x31,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0x21,0x88,0x80,0x00,
+0x7c,0x03,0x57,0x34,0x1e,0x03,0x5e,0x34,0x21,0x98,0x80,0x00,0xb0,0x03,0x56,0x34,
+0x01,0x00,0x15,0x24,0x07,0x09,0x00,0x08,0x01,0x00,0x14,0x24,0xf2,0x23,0x22,0x96,
+0x59,0x25,0x35,0xa2,0x01,0x00,0x42,0x34,0x00,0x00,0xc2,0xa7,0xf2,0x23,0x22,0xa6,
+0x30,0x00,0x02,0x24,0x06,0x00,0x42,0x12,0x02,0x80,0x02,0x3c,0x78,0xaf,0x42,0x24,
+0x00,0x00,0x48,0x8c,0x02,0x00,0x02,0x24,0x01,0x00,0x15,0xa1,0x01,0x00,0x02,0xa1,
+0x59,0x25,0x62,0x92,0x00,0x00,0x00,0x00,0x45,0x00,0x54,0x14,0xff,0x00,0x02,0x24,
+0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x69,0x30,0x40,0x00,0x22,0x11,
+0x20,0x10,0x02,0x3c,0x80,0x24,0x63,0xa2,0x80,0x24,0x28,0x92,0x50,0x25,0x25,0x8e,
+0xff,0x00,0x03,0x31,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0xc9,0xae,
+0x21,0x30,0x60,0x00,0x00,0x00,0xe8,0xa6,0x0a,0x00,0x04,0x24,0xe4,0x24,0x23,0xae,
+0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x50,0x25,0x30,0x8e,
+0x00,0x02,0x00,0x0c,0x0a,0x00,0x04,0x24,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c,
+0x25,0x80,0x02,0x02,0x02,0x00,0x03,0x92,0x20,0x00,0x02,0x24,0xd3,0xff,0x62,0x14,
+0x21,0x20,0x03,0x02,0x02,0x80,0x02,0x3c,0x88,0xb5,0x44,0xac,0x20,0x00,0x03,0x26,
+0x02,0x00,0x62,0x90,0x59,0x25,0x25,0x92,0x03,0x00,0x64,0x90,0xff,0x00,0x52,0x30,
+0x7f,0x00,0x83,0x30,0x10,0x00,0xb4,0x14,0x28,0x00,0x04,0x26,0x02,0x80,0x05,0x3c,
+0x91,0x43,0xa2,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x42,0x30,0x08,0x00,0x62,0x10,
+0x32,0x00,0x42,0x2e,0xf2,0x23,0x22,0x96,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x34,
+0x00,0x00,0xc2,0xa7,0x91,0x43,0xa3,0xa0,0xf2,0x23,0x22,0xa6,0x32,0x00,0x42,0x2e,
+0xbf,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xc0,0x18,0x12,0x00,
+0x94,0x9f,0x42,0x24,0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,0x02,0x80,0x03,0x3c,
+0x09,0xf8,0x40,0x00,0x84,0xb5,0x62,0xac,0xe9,0x08,0x00,0x08,0x30,0x00,0x02,0x24,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24,0xad,0x08,0x00,0x08,0x58,0x25,0x40,0xa0,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0xb3,0x08,0x00,0x08,0x02,0x80,0x03,0x3c,0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,
+0x02,0x80,0x02,0x3c,0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,
+0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,
+0x21,0xb0,0xa0,0x00,0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,
+0x24,0x18,0x62,0x00,0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,
+0xff,0x01,0xc6,0x34,0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,
+0xff,0xff,0xe7,0x30,0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,
+0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,
+0x18,0x00,0x03,0xad,0x78,0x1b,0xa5,0x26,0xee,0x23,0xa3,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x62,0x24,0xee,0x23,0xa2,0xa0,0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,
+0x20,0x00,0x45,0x26,0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,
+0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,
+0x25,0x20,0x83,0x00,0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,
+0x03,0x00,0xa0,0x10,0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,
+0x78,0x1b,0xb4,0x26,0xb4,0x25,0x86,0x8e,0xb8,0x25,0x90,0x8e,0xf8,0xff,0x52,0x30,
+0x21,0x10,0xd2,0x00,0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,
+0x23,0x80,0x06,0x02,0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,
+0x21,0x20,0x60,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,
+0xff,0xff,0x72,0x30,0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,
+0x00,0x02,0x00,0x0c,0xb4,0x25,0x82,0xae,0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,
+0x21,0x20,0x60,0x02,0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c,0xc3,0x01,0x00,0x0c,
+0x78,0x1b,0xb1,0x26,0xb4,0x25,0x23,0x8e,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,
+0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xb4,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,
+0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,
+0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,
+0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0x21,0x28,0xc0,0x02,0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,0xb4,0x25,0x83,0x8e,0x78,0x1b,0xb1,0x26,
+0x25,0xb0,0x10,0x3c,0x21,0x18,0x72,0x00,0xb4,0x25,0x83,0xae,0xb4,0x25,0x23,0x8e,
+0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xb4,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,
+0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,
+0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,
+0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x21,0x88,0x80,0x00,0x00,0x60,0x14,0x40,
+0x01,0x00,0x81,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x14,0x00,0x83,0x8c,
+0x02,0x80,0x15,0x3c,0x15,0x00,0x02,0x24,0x78,0x1b,0xb3,0x26,0x21,0x28,0x00,0x00,
+0x1d,0x00,0x62,0x10,0x08,0x00,0x06,0x24,0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,
+0x3e,0x46,0x00,0x0c,0x25,0x20,0x44,0x00,0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,
+0x14,0x00,0x27,0x96,0x3e,0x09,0x00,0x0c,0x09,0x00,0x04,0x24,0x04,0x00,0x22,0x8e,
+0x00,0x00,0x23,0x8e,0x21,0x20,0x20,0x02,0x00,0x00,0x43,0xac,0x04,0x00,0x62,0xac,
+0x00,0x00,0x31,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x94,0x40,
+0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x0c,0x00,0x90,0x8c,0x25,0xb0,0x02,0x3c,
+0xc0,0x00,0x42,0x34,0xb4,0x25,0x68,0x8e,0x07,0x00,0x07,0x32,0x00,0x00,0x50,0xa4,
+0x08,0x00,0x05,0x26,0x0b,0x80,0xa7,0x00,0xb8,0x25,0x63,0x8e,0xf8,0xff,0x10,0x32,
+0x21,0x10,0x10,0x01,0x23,0x90,0x68,0x00,0x2b,0x18,0x62,0x00,0x01,0x00,0x16,0x24,
+0x09,0x00,0x04,0x24,0x21,0x30,0x00,0x01,0x33,0x00,0x60,0x10,0xff,0xff,0x07,0x32,
+0x08,0x00,0x25,0x8e,0xff,0xff,0x47,0x32,0x23,0x80,0x12,0x02,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xb6,0xaf,0x22,0x10,0x03,0x3c,0x21,0x18,0x03,0x02,0x09,0x00,0x04,0x24,
+0x00,0x02,0x00,0x0c,0xb4,0x25,0x63,0xae,0x08,0x00,0x25,0x8e,0xff,0xff,0x07,0x32,
+0x09,0x00,0x04,0x24,0x21,0x28,0xb2,0x00,0x22,0x10,0x06,0x3c,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xb6,0xaf,0x00,0x02,0x00,0x0c,0x09,0x00,0x04,0x24,0x78,0x1b,0xa2,0x26,
+0xb4,0x25,0x46,0x8c,0x25,0xb0,0x03,0x3c,0xec,0x00,0x64,0x34,0x00,0x00,0x86,0xac,
+0xbd,0x00,0x65,0x34,0x00,0x00,0xa2,0x90,0xc2,0x00,0x63,0x34,0x21,0x20,0x20,0x02,
+0x10,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x00,0x00,0x66,0xa4,0x04,0x00,0x22,0x8e,
+0x00,0x00,0x23,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xac,0x04,0x00,0x62,0xac,
+0x00,0x00,0x31,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x94,0x40,
+0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x08,0x00,0x25,0x8e,0x01,0x00,0x02,0x24,
+0x21,0x30,0x00,0x01,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,
+0xb4,0x25,0x63,0x8e,0x00,0x00,0x00,0x00,0x21,0x18,0x70,0x00,0x2d,0x0a,0x00,0x08,
+0xb4,0x25,0x63,0xae,0xe8,0xff,0xbd,0x27,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x21,0x28,0x80,0x00,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x04,0x00,0x63,0x2c,0x05,0x00,0x60,0x10,0x02,0x80,0x06,0x3c,
+0x70,0x41,0xc3,0x8c,0x70,0x41,0xc2,0x24,0x0c,0x00,0x62,0x10,0x00,0x00,0x00,0x00,
+0x70,0x41,0xc2,0x24,0x04,0x00,0x43,0x8c,0x00,0x00,0xa2,0xac,0x04,0x00,0x45,0xac,
+0x00,0x00,0x65,0xac,0x04,0x00,0xa3,0xac,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xd9,0x09,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xd0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,0xf8,0x29,0x63,0x24,0x28,0x00,0xbf,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x00,0x00,0x43,0xac,0x02,0x80,0x04,0x3c,0x98,0x44,0x82,0x90,0x00,0x00,0x00,0x00,
+0x09,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x02,0x3c,0xb1,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0x61,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0x9c,0x1e,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x78,0x41,0x43,0x8c,0x78,0x41,0x42,0x24,
+0x66,0x00,0x62,0x10,0x02,0x80,0x13,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x78,0x1b,0x66,0x26,0xbc,0x25,0xc5,0x8c,0xc0,0x18,0x03,0x00,0x23,0xb0,0x04,0x3c,
+0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x00,0x04,0x22,0x26,0x2b,0x28,0x85,0x00,
+0x6c,0x25,0xc3,0x8c,0x0b,0x88,0x45,0x00,0xe1,0x01,0x22,0x2e,0x68,0x25,0xc3,0xac,
+0xc0,0x25,0xc4,0xac,0x72,0x25,0xc0,0xa4,0x14,0x00,0x40,0x14,0x71,0x25,0xc0,0xa0,
+0x20,0xfe,0x82,0x24,0x20,0x02,0x83,0x24,0x0a,0x18,0x45,0x00,0x23,0x10,0x02,0x3c,
+0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x21,0x28,0x60,0x00,0x34,0x00,0x40,0x14,
+0xbc,0x25,0xc3,0xac,0xc0,0x25,0xc2,0x8c,0x00,0x00,0x00,0x00,0x2b,0x18,0x45,0x00,
+0x23,0x88,0x45,0x00,0x03,0x00,0x60,0x10,0xe1,0x01,0x22,0x2e,0x00,0x04,0x31,0x26,
+0xe1,0x01,0x22,0x2e,0x0e,0x00,0x40,0x10,0x78,0x1b,0x70,0x26,0x78,0x1b,0x70,0x26,
+0xc0,0x25,0x03,0x8e,0xbc,0x25,0x04,0x8e,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,
+0x41,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,0x6d,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,
+0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x78,0x1b,0x70,0x26,
+0xbc,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,
+0x00,0x00,0x51,0xa0,0x45,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e,
+0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,
+0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0x00,0xfc,0xa5,0x24,0xbd,0x0a,0x00,0x08,0xbc,0x25,0xc5,0xac,0x01,0x00,0x04,0x24,
+0xba,0x44,0x44,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x02,0x80,0x13,0x3c,
+0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,0x78,0x41,0x43,0x8c,
+0x78,0x41,0x42,0x24,0x9c,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x90,0x1e,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x98,0xff,0x40,0x10,0x78,0x1b,0x63,0x26,0x82,0x0b,0x62,0x90,
+0x00,0x00,0x00,0x00,0x94,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x98,0x26,0x64,0x94,
+0x82,0x0b,0x60,0xa0,0x00,0xc0,0x84,0x24,0x2c,0x22,0x00,0x0c,0xff,0xff,0x84,0x30,
+0x9a,0x0a,0x00,0x08,0x00,0x00,0x00,0x00,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,
+0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x68,0x25,0x03,0x8e,0x72,0x25,0x05,0x96,0xbc,0x25,0x02,0x8e,0x21,0x18,0x71,0x00,
+0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,0x09,0x00,0x04,0x24,0xbc,0x25,0x02,0xae,
+0x68,0x25,0x03,0xae,0x00,0x02,0x00,0x0c,0x72,0x25,0x05,0xa6,0x78,0x1b,0x70,0x26,
+0xbc,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,
+0x00,0x00,0x51,0xa0,0x45,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e,
+0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,
+0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0xc4,0x25,0x02,0x8e,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,
+0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x68,0x25,0x03,0x8e,0x72,0x25,0x02,0x96,0xc0,0x25,0x12,0x96,0x21,0x18,0x71,0x00,
+0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,0x68,0x25,0x03,0xae,0x72,0x25,0x02,0xa6,
+0x06,0x00,0x40,0x16,0xbc,0x25,0x11,0xae,0x09,0x00,0x04,0x24,0x00,0x02,0x00,0x0c,
+0x78,0x1b,0x70,0x26,0x20,0x0b,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0c,
+0x09,0x00,0x04,0x24,0x68,0x25,0x05,0x8e,0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c,
+0x21,0x38,0x40,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x25,0x03,0x8e,
+0x72,0x25,0x02,0x96,0x21,0x20,0x51,0x02,0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02,
+0xbc,0x25,0x04,0xae,0x09,0x00,0x04,0x24,0x68,0x25,0x03,0xae,0x4f,0x0b,0x00,0x08,
+0x72,0x25,0x02,0xa6,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x08,0x00,0x02,0x24,0xfc,0x00,0x84,0x30,
+0x50,0x00,0x02,0x24,0x11,0x00,0x82,0x10,0x05,0x00,0x03,0x24,0x51,0x00,0x82,0x28,
+0x10,0x00,0x40,0x10,0xa0,0x00,0x02,0x24,0x20,0x00,0x02,0x24,0x0b,0x00,0x82,0x10,
+0x02,0x00,0x03,0x24,0x21,0x00,0x82,0x28,0x15,0x00,0x40,0x14,0x30,0x00,0x02,0x24,
+0x06,0x00,0x82,0x10,0x03,0x00,0x03,0x24,0x04,0x00,0x03,0x24,0x40,0x00,0x02,0x24,
+0x02,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0xfd,0xff,0x82,0x10,0x08,0x00,0x03,0x24,0xa1,0x00,0x82,0x28,
+0x0c,0x00,0x40,0x10,0xc0,0x00,0x02,0x24,0x80,0x00,0x02,0x24,0xf7,0xff,0x82,0x10,
+0x06,0x00,0x03,0x24,0x07,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,0x90,0x00,0x02,0x24,
+0xf2,0xff,0x80,0x10,0x21,0x18,0x00,0x00,0x01,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,
+0x10,0x00,0x02,0x24,0xed,0xff,0x82,0x10,0x0a,0x00,0x03,0x24,0xc1,0x00,0x82,0x28,
+0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,
+0xb0,0x00,0x02,0x24,0x0b,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,0xd0,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,0x25,0xb0,0x04,0x3c,
+0x98,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x80,0x03,0x3c,
+0x25,0xb0,0x04,0x3c,0xdc,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,0x25,0xb0,0x04,0x3c,
+0xf8,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x7c,0x2f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x25,0xb0,0x03,0x3c,0x00,0x80,0x02,0x3c,
+0xb0,0x03,0x65,0x34,0x98,0x2f,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac,
+0x00,0x00,0xa4,0xac,0x00,0x00,0x83,0x8c,0x21,0x10,0x00,0x00,0xff,0x3f,0x63,0x30,
+0x00,0x00,0xa3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x98,0xff,0xbd,0x27,0x60,0x00,0xbe,0xaf,0x5c,0x00,0xb7,0xaf,
+0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf,0x64,0x00,0xbf,0xaf,0x58,0x00,0xb6,0xaf,
+0x54,0x00,0xb5,0xaf,0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf,0x40,0x00,0xb0,0xaf,
+0x21,0x88,0x80,0x00,0x02,0x00,0x84,0x90,0x21,0xf0,0x00,0x00,0x21,0xb8,0x00,0x00,
+0x0f,0x00,0x84,0x30,0xc0,0x20,0x04,0x00,0x21,0x20,0x91,0x00,0x18,0x00,0x92,0x24,
+0x00,0x60,0x13,0x40,0x01,0x00,0x61,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x05,0x3c,0x28,0x00,0x84,0x24,0x18,0x42,0xa5,0x24,0x7b,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0xa6,0x00,0x40,0x14,0x02,0x80,0x14,0x3c,0x98,0x44,0x82,0x92,
+0x00,0x00,0x00,0x00,0xb0,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,
+0xe8,0x0a,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xaa,0x00,0x40,0x10,
+0x02,0x80,0x09,0x3c,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x10,
+0x02,0x80,0x02,0x3c,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x24,
+0xb9,0x44,0x22,0xa1,0x02,0x80,0x02,0x3c,0x9e,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x62,0x90,0xfd,0xff,0x03,0x24,0x42,0xb0,0x04,0x3c,0x24,0x10,0x43,0x00,
+0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0xa0,0x00,0x00,0x83,0x90,0xef,0xff,0x02,0x24,
+0x03,0x00,0x85,0x34,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0x83,0xa0,
+0x02,0x80,0x16,0x3c,0x00,0x00,0xa2,0xa0,0xa0,0x44,0xc2,0x96,0x20,0x00,0x43,0x96,
+0xff,0xff,0x42,0x30,0x0a,0x00,0x43,0x10,0x02,0x80,0x15,0x3c,0x25,0xb0,0x02,0x3c,
+0x94,0x00,0x42,0x34,0xa0,0x44,0xc3,0xa6,0x00,0x00,0x43,0xa4,0xa0,0x44,0xc3,0x96,
+0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x30,0x80,0x1a,0x03,0x00,0xa4,0x44,0xa3,0xae,
+0x25,0xb0,0x10,0x3c,0x84,0x00,0x02,0x36,0x00,0x00,0x44,0x8c,0x80,0x00,0x10,0x36,
+0x00,0x00,0x02,0x8e,0xa4,0x44,0xa6,0x8e,0x21,0x18,0x00,0x00,0x00,0x28,0x04,0x00,
+0x21,0x20,0x00,0x00,0x25,0x28,0xa3,0x00,0x25,0x20,0x82,0x00,0x24,0x22,0x00,0x0c,
+0x38,0x00,0xa9,0xaf,0x02,0x80,0x05,0x3c,0x00,0x00,0x04,0x8e,0xa4,0x44,0xa6,0x8e,
+0xa8,0x44,0xa3,0x94,0x23,0x20,0x82,0x00,0x21,0x20,0x86,0x00,0xff,0xff,0x63,0x30,
+0x80,0x1a,0x03,0x00,0x23,0x20,0x83,0x00,0x02,0x80,0x08,0x3c,0xac,0x44,0x04,0xad,
+0x00,0x00,0x02,0x8e,0x21,0x18,0x00,0x00,0x21,0x38,0x00,0x00,0x00,0x50,0x42,0x24,
+0x00,0x50,0x45,0x2c,0x21,0x18,0x65,0x00,0x2b,0x20,0xe3,0x00,0xac,0x44,0x06,0x8d,
+0x38,0x00,0xa9,0x8f,0x8f,0x00,0x80,0x14,0x00,0x00,0x00,0x00,0x8b,0x00,0x67,0x10,
+0x2b,0x10,0xc2,0x00,0xac,0x44,0x04,0x8d,0x25,0xb0,0x02,0x3c,0xe4,0x02,0x42,0x34,
+0x00,0x00,0x44,0xac,0xa0,0x44,0xc3,0x96,0x02,0x80,0x02,0x3c,0x05,0x00,0x05,0x24,
+0xff,0xff,0x63,0x30,0x40,0x18,0x03,0x00,0xf6,0xff,0x63,0x24,0x88,0x44,0x43,0xac,
+0x00,0x00,0x27,0x8e,0x24,0x00,0x44,0x26,0x30,0x00,0xa6,0x27,0xff,0x3f,0xe7,0x30,
+0x8a,0x11,0x00,0x0c,0xdc,0xff,0xe7,0x24,0x2c,0x00,0x40,0x10,0x21,0x28,0x40,0x00,
+0x98,0x44,0x82,0x92,0x02,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x7f,0x00,0x43,0x10,
+0x02,0x80,0x04,0x3c,0x02,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0x08,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x04,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x30,
+0x04,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x17,0x24,0xb6,0x44,0x57,0xa0,
+0x04,0x00,0xa3,0x90,0x30,0x00,0xa7,0x8f,0x00,0x00,0x00,0x00,0x04,0x00,0xe2,0x28,
+0x16,0x00,0x40,0x14,0xfe,0x00,0x66,0x30,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,
+0x98,0x26,0x64,0x94,0xc0,0x10,0x06,0x00,0x2a,0x10,0x82,0x00,0x10,0x00,0x40,0x14,
+0x02,0x80,0x03,0x3c,0x21,0x10,0xc7,0x00,0xfd,0xff,0x42,0x24,0xc0,0x10,0x02,0x00,
+0x2a,0x10,0x44,0x00,0x0a,0x00,0x40,0x14,0xc2,0x10,0x04,0x00,0x23,0x30,0x46,0x00,
+0x21,0x18,0xa6,0x00,0x05,0x00,0x62,0x90,0x07,0x00,0x84,0x30,0x01,0x00,0x03,0x24,
+0x07,0x10,0x82,0x00,0x01,0x00,0x42,0x30,0x0b,0xf0,0x62,0x00,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x62,0x90,0xef,0xff,0x03,0x24,0x21,0x20,0xe0,0x02,0x24,0x10,0x43,0x00,
+0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0xa0,0x98,0x44,0x83,0x92,0x02,0x80,0x02,0x3c,
+0x10,0xaf,0x42,0x24,0xff,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,
+0x00,0x00,0x66,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0xc0,0x00,0x21,0x28,0xc0,0x03,
+0x00,0x60,0x93,0x40,0x64,0x00,0xbf,0x8f,0x60,0x00,0xbe,0x8f,0x5c,0x00,0xb7,0x8f,
+0x58,0x00,0xb6,0x8f,0x54,0x00,0xb5,0x8f,0x50,0x00,0xb4,0x8f,0x4c,0x00,0xb3,0x8f,
+0x48,0x00,0xb2,0x8f,0x44,0x00,0xb1,0x8f,0x40,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x68,0x00,0xbd,0x27,0x98,0x44,0x82,0x92,0x00,0x00,0x00,0x00,
+0xef,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x78,0x1b,0x70,0x24,0xe8,0x0a,0x02,0x92,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xe9,0xff,0x40,0x10,0x24,0x00,0x44,0x26,
+0x00,0x00,0x27,0x8e,0x05,0x00,0x05,0x24,0xff,0x3f,0xe7,0x30,0xdc,0xff,0xe7,0x24,
+0x8a,0x11,0x00,0x0c,0x30,0x00,0xa6,0x27,0xe1,0xff,0x40,0x10,0x21,0x28,0x40,0x00,
+0x30,0x00,0xa7,0x8f,0x04,0x00,0x42,0x90,0x04,0x00,0xe3,0x28,0xdc,0xff,0x60,0x14,
+0xfe,0x00,0x46,0x30,0x98,0x26,0x04,0x96,0xc0,0x10,0x06,0x00,0x2a,0x10,0x82,0x00,
+0xd7,0xff,0x40,0x14,0x21,0x10,0xc7,0x00,0xfd,0xff,0x42,0x24,0xc0,0x10,0x02,0x00,
+0x2a,0x10,0x44,0x00,0xd2,0xff,0x40,0x14,0xc2,0x10,0x04,0x00,0x23,0x30,0x46,0x00,
+0x21,0x18,0xa6,0x00,0x05,0x00,0x62,0x90,0x07,0x00,0x84,0x30,0x07,0x10,0x82,0x00,
+0x01,0x00,0x42,0x30,0xca,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x0e,0x46,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xc4,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x75,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x71,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xb9,0x44,0x22,0xa1,0x75,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0xa2,0x90,
+0x02,0x80,0x07,0x3c,0xb4,0x44,0xe2,0xa0,0x02,0x00,0xa3,0x90,0x21,0x30,0x80,0x00,
+0xb5,0x44,0x83,0xa0,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xb4,0x44,0xe2,0x90,0x00,0x00,0x00,0x00,0xb5,0x44,0xc2,0xa0,
+0x8d,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00,
+0xb5,0x44,0xc2,0xa0,0x8d,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x09,0x3c,
+0x78,0x1b,0x28,0x25,0xf4,0x23,0x06,0x8d,0xff,0xff,0x02,0x34,0x44,0x00,0xc2,0x10,
+0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x34,0x00,0x40,0x10,0x02,0x19,0x06,0x00,
+0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xf4,0x23,0x06,0xad,
+0xf8,0x23,0x02,0xad,0x78,0x1b,0x26,0x25,0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34,
+0xff,0xff,0x83,0x30,0x33,0x00,0x62,0x10,0x00,0x11,0x07,0x00,0xff,0xff,0x84,0x30,
+0x2b,0x10,0x87,0x00,0x20,0x00,0x40,0x10,0x03,0x19,0x04,0x00,0x03,0x11,0x04,0x00,
+0x21,0x18,0x87,0x00,0x23,0x18,0x62,0x00,0x10,0x00,0x64,0x24,0x06,0x00,0xc4,0xa4,
+0xf8,0x23,0xc3,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x78,0x1b,0x23,0x25,0x80,0x10,0x02,0x00,0x21,0x28,0x43,0x00,
+0x80,0x11,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,0x0a,0x30,0x82,0x00,
+0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,0x02,0x19,0x06,0x00,
+0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x80,0x11,0xa6,0xac,0x08,0x00,0xe0,0x03,
+0x84,0x11,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x80,0x11,0xa2,0xac,
+0x08,0x00,0xe0,0x03,0x84,0x11,0xa2,0xac,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,
+0x06,0x00,0xc2,0xa4,0x3d,0x0d,0x00,0x08,0xf8,0x23,0xc2,0xac,0x21,0x10,0xc7,0x00,
+0x23,0x10,0x43,0x00,0xf4,0x23,0x02,0xad,0xf8,0x23,0x02,0xad,0x78,0x1b,0x26,0x25,
+0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34,0xff,0xff,0x83,0x30,0xcf,0xff,0x62,0x14,
+0x00,0x11,0x07,0x00,0x21,0x20,0x40,0x00,0x33,0x0d,0x00,0x08,0x06,0x00,0xc2,0xa4,
+0x00,0x31,0x04,0x00,0x25,0x0d,0x00,0x08,0xf4,0x23,0x06,0xad,0x63,0x00,0x82,0x24,
+0x77,0x00,0x42,0x2c,0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,
+0x64,0x00,0x82,0x24,0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x0c,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x07,0x00,0x40,0x14,
+0x25,0xb0,0x02,0x3c,0x04,0x00,0xa4,0x90,0x10,0x00,0xbf,0x8f,0x18,0x00,0xbd,0x27,
+0x42,0x20,0x04,0x00,0x6b,0x0d,0x00,0x08,0x96,0xff,0x84,0x24,0x24,0x08,0x42,0x34,
+0x00,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x1b,0x00,0x60,0x14,
+0x01,0x00,0x02,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,
+0x3c,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x57,0x00,0x40,0x14,0x02,0x00,0x02,0x24,
+0x46,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x2e,0x00,0x82,0x10,0x3e,0x00,0x63,0x30,
+0x6b,0x0d,0x00,0x0c,0x21,0x20,0xc0,0x00,0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c,
+0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00,0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,
+0x1f,0x00,0x40,0x10,0xe5,0xff,0xa2,0x24,0xfe,0xff,0xa5,0x24,0x10,0x00,0xbf,0x8f,
+0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x05,0x00,0xa3,0x90,
+0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,0x42,0x21,0x04,0x00,0x25,0x00,0x82,0x10,
+0x02,0x00,0x82,0x28,0x36,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,
+0x03,0x00,0x02,0x24,0xe6,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,
+0xd8,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0x6b,0x0d,0x00,0x0c,0x21,0x20,0xc0,0x00,
+0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c,0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00,
+0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,0xe3,0xff,0x40,0x14,0xe5,0xff,0xa2,0x24,
+0x08,0x00,0x42,0x2c,0x06,0x00,0x40,0x10,0xf1,0xff,0xa2,0x24,0x9f,0x0d,0x00,0x08,
+0xfa,0xff,0xa5,0x24,0xd8,0xff,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00,
+0x0c,0x00,0x42,0x2c,0x0c,0x00,0x40,0x10,0xfb,0xff,0xa2,0x24,0x9f,0x0d,0x00,0x08,
+0xf8,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30,0xfe,0xff,0x02,0x24,0x94,0x0d,0x00,0x08,
+0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0xfe,0xff,0x03,0x24,
+0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00,0x0a,0x00,0x42,0x2c,0xcb,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x9f,0x0d,0x00,0x08,0xfc,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30,
+0xec,0xff,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30,
+0x40,0x10,0x02,0x00,0xec,0xff,0x03,0x24,0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00,
+0xb3,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0x0e,0x00,0x03,0x24,
+0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00,0xad,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,
+0x0e,0x00,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00,0xa0,0xff,0xbd,0x27,
+0x5c,0x00,0xbf,0xaf,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,0x50,0x00,0xb6,0xaf,
+0x4c,0x00,0xb5,0xaf,0x48,0x00,0xb4,0xaf,0x44,0x00,0xb3,0xaf,0x40,0x00,0xb2,0xaf,
+0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0x68,0x41,0x45,0x8c,
+0x00,0x80,0x04,0x3c,0xac,0x37,0x83,0x24,0x68,0x41,0x44,0x24,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xbb,0x00,0xa4,0x10,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0x7c,0xaf,0x42,0x24,0x80,0xaf,0x63,0x24,0x00,0x00,0x5e,0x8c,
+0x00,0x00,0x75,0x8c,0xf0,0x25,0xd6,0x8f,0x21,0x20,0x00,0x00,0x21,0xb8,0x00,0x00,
+0x08,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae,0x08,0x00,0xc3,0x96,
+0x02,0x80,0x02,0x3c,0x00,0x02,0x00,0x0c,0x25,0xa0,0x62,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xe4,0x0a,0xc3,0x97,
+0x8c,0x25,0xc2,0x8f,0x25,0xb0,0x04,0x3c,0xf8,0x00,0x84,0x34,0x21,0x10,0x43,0x00,
+0x00,0x00,0x82,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0x23,0x0e,0x00,0x08,0x00,0x00,0x00,0x00,0x0c,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,
+0x2b,0x10,0xe2,0x02,0x86,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8e,
+0x21,0x98,0x80,0x02,0x42,0x1b,0x02,0x00,0x78,0x00,0x63,0x30,0x02,0x26,0x02,0x00,
+0xff,0x3f,0x42,0x30,0x21,0x10,0x43,0x00,0x03,0x00,0x84,0x30,0x21,0x10,0x44,0x00,
+0x18,0x00,0x42,0x24,0xff,0xff,0x52,0x30,0x7f,0x00,0x43,0x32,0x00,0x00,0xb2,0xae,
+0x03,0x00,0x60,0x10,0x80,0xff,0x42,0x32,0x80,0x00,0x42,0x26,0x80,0xff,0x42,0x30,
+0x00,0x00,0xa2,0xae,0x21,0x90,0x40,0x00,0x02,0x00,0x62,0x96,0x21,0x18,0xf2,0x02,
+0xff,0xff,0x77,0x30,0x0f,0x00,0x42,0x30,0x00,0x00,0xa2,0xae,0x00,0x00,0x63,0x8e,
+0x21,0xa0,0x92,0x02,0x42,0x13,0x03,0x00,0x78,0x00,0x42,0x30,0x02,0x1e,0x03,0x00,
+0x03,0x00,0x63,0x30,0x21,0x10,0x53,0x00,0x21,0x88,0x43,0x00,0x18,0x00,0x25,0x26,
+0x00,0x00,0xa5,0xae,0x01,0x00,0xa4,0x90,0x18,0x00,0x22,0x92,0x00,0x22,0x04,0x00,
+0x73,0x0b,0x00,0x0c,0x25,0x20,0x82,0x00,0x40,0x18,0x02,0x00,0x21,0x18,0x62,0x00,
+0x02,0x80,0x04,0x3c,0x21,0x80,0x40,0x00,0x80,0x18,0x03,0x00,0x98,0xa8,0x82,0x24,
+0x21,0x18,0x62,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00,
+0x21,0x20,0x60,0x02,0x06,0x00,0x03,0x24,0xc7,0xff,0x03,0x16,0x00,0x00,0x00,0x00,
+0xe8,0x0a,0xc2,0x93,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xc2,0xff,0x40,0x10,
+0x02,0x80,0x02,0x3c,0x28,0x00,0x24,0x26,0x18,0x42,0x45,0x24,0x7b,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0xbc,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0xbc,0x44,0x64,0x8c,0x9c,0x44,0x43,0x90,0x02,0x80,0x02,0x3c,0x38,0xa9,0x45,0x8c,
+0xff,0x00,0x63,0x30,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0xc0,0x10,0x02,0x00,
+0x21,0x10,0x43,0x00,0x23,0x20,0x85,0x00,0x80,0x10,0x02,0x00,0x2b,0x20,0x82,0x00,
+0xad,0xff,0x80,0x14,0x02,0x80,0x03,0x3c,0xbc,0x44,0x62,0x8c,0x21,0x20,0x40,0x02,
+0x02,0x80,0x03,0x3c,0x39,0x15,0x00,0x0c,0x38,0xa9,0x62,0xac,0x1d,0x01,0x40,0x10,
+0x21,0x88,0x40,0x00,0x00,0x00,0x65,0x8e,0x08,0x00,0x50,0x94,0x04,0x00,0x64,0x8e,
+0xf0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0xe0,0xff,0x03,0x24,0x24,0x28,0xa2,0x00,
+0xff,0xfb,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0xff,0x42,0x34,0x02,0x80,0x03,0x3c,
+0x25,0x80,0x03,0x02,0x24,0x28,0xa2,0x00,0x1e,0x00,0x84,0x34,0x04,0x00,0x64,0xae,
+0x00,0x00,0x65,0xae,0x21,0x20,0x00,0x02,0x21,0x28,0x60,0x02,0x52,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0xc8,0xff,0x46,0x26,0xcb,0xff,0x43,0x26,0x00,0x00,0xc2,0x28,
+0x0b,0x30,0x62,0x00,0x18,0x00,0x04,0x26,0x83,0x30,0x06,0x00,0x52,0x46,0x00,0x0c,
+0x38,0x00,0x65,0x26,0x15,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x00,0x00,0x62,0x8e,
+0x21,0x20,0x20,0x02,0x42,0x1b,0x02,0x00,0x78,0x00,0x63,0x30,0x02,0x2e,0x02,0x00,
+0xff,0x3f,0x42,0x30,0x21,0x10,0x43,0x00,0x03,0x00,0xa5,0x30,0x21,0x10,0x45,0x00,
+0x18,0x00,0x42,0x24,0x59,0x0a,0x00,0x0c,0x0c,0x00,0x22,0xae,0x0c,0x00,0xc2,0x8e,
+0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x02,0x7c,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x04,0x00,0xc3,0x8e,0x00,0x00,0xc2,0x8e,0x21,0x20,0xc0,0x02,0x00,0x00,0x62,0xac,
+0x04,0x00,0x43,0xac,0x00,0x00,0xd6,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0xd6,0xae,
+0x00,0x60,0x90,0x40,0x02,0x80,0x04,0x3c,0x68,0x41,0x83,0x8c,0x68,0x41,0x82,0x24,
+0x4c,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x7c,0xaf,0x42,0x24,
+0x00,0x00,0x51,0x8c,0x25,0xb0,0x10,0x3c,0x04,0x01,0x02,0x36,0x00,0x00,0x43,0x8c,
+0xa4,0x25,0x27,0x8e,0x00,0x00,0x00,0x00,0xc5,0x00,0xe3,0x10,0xa8,0x25,0x23,0xae,
+0x2b,0x10,0x67,0x00,0xe4,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,0x0c,0x01,0x40,0x14,
+0x23,0x10,0x67,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x64,0x24,0x78,0x25,0x83,0x94,
+0x02,0x80,0x02,0x3c,0x21,0x90,0x00,0x00,0x22,0x00,0xe0,0x1a,0x25,0x88,0x62,0x00,
+0x21,0xa8,0x80,0x00,0x21,0xf0,0x80,0x00,0x21,0x80,0x00,0x00,0x01,0x00,0x14,0x24,
+0x21,0x98,0x11,0x02,0x04,0x00,0x62,0x8e,0x02,0x00,0x03,0x24,0x02,0x17,0x02,0x00,
+0x03,0x00,0x42,0x30,0x31,0x00,0x43,0x10,0x02,0x80,0x04,0x3c,0x21,0x10,0x11,0x02,
+0x00,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x10,0x01,0x00,0x42,0x26,
+0x04,0x00,0x62,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,0x24,0x10,0x43,0x00,
+0x10,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x06,0x00,0x42,0x26,0x00,0x00,0x65,0x8e,
+0xff,0xff,0x52,0x30,0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x4a,0x00,0x54,0x10,
+0x02,0x80,0x03,0x3c,0x80,0x80,0x12,0x00,0x2a,0x10,0x17,0x02,0xe4,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x56,0x15,0x00,0x0c,0x21,0x20,0xc0,0x02,0x8e,0x0f,0x00,0x08,
+0x02,0x80,0x02,0x3c,0xc8,0x0c,0xa2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xc8,0x0c,0xa2,0xae,0x0c,0x00,0x64,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30,
+0xa6,0x00,0x62,0x10,0x21,0x28,0xa0,0x02,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24,
+0x9b,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24,
+0xe2,0xff,0x62,0x14,0x06,0x00,0x42,0x26,0xd4,0x0c,0xa2,0x8e,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x24,0xe6,0x0e,0x00,0x08,0xd4,0x0c,0xa2,0xae,0x98,0x44,0x82,0x90,
+0x00,0x00,0x00,0x00,0xce,0xff,0x40,0x10,0x21,0x10,0x11,0x02,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x98,0x44,0x82,0x90,
+0x02,0x80,0x03,0x3c,0xe4,0xae,0x65,0x24,0xff,0x00,0x42,0x30,0x80,0x10,0x02,0x00,
+0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x8c,0x00,0x00,0x64,0x8e,0x04,0x00,0x65,0x8e,
+0x09,0xf8,0x60,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x9a,0x44,0x82,0x90,
+0x0c,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x10,0x02,0x80,0x03,0x3c,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xdc,0x0e,0x00,0x08,
+0x21,0x10,0x11,0x02,0xb1,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xf8,0xff,0x40,0x10,
+0x02,0x80,0x04,0x3c,0xb7,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xb7,0x44,0x82,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xdc,0x0e,0x00,0x08,0x21,0x10,0x11,0x02,0x78,0x1b,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x11,0x02,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x54,0x10,0xc2,0x13,0x05,0x00,
+0x1e,0x00,0x42,0x30,0x21,0x10,0x52,0x00,0xed,0x0e,0x00,0x08,0xff,0xff,0x52,0x30,
+0x01,0x00,0xc2,0x93,0x00,0x00,0x00,0x00,0x1c,0x00,0x40,0x14,0x02,0x80,0x04,0x3c,
+0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x45,0x30,
+0x08,0x00,0xa3,0x28,0x14,0x00,0x60,0x10,0x02,0x17,0x04,0x00,0x03,0x00,0x43,0x30,
+0x08,0x00,0x60,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x82,0x00,0x0e,0x00,0x40,0x14,
+0x03,0x00,0x02,0x24,0x0d,0x00,0x62,0x10,0x02,0x80,0x04,0x3c,0x0c,0x00,0x60,0x10,
+0x78,0x1b,0x82,0x24,0x21,0x10,0xbe,0x00,0xf0,0x04,0x50,0x90,0x80,0x28,0x12,0x00,
+0x21,0x28,0xb1,0x00,0x75,0x0d,0x00,0x0c,0x21,0x20,0x60,0x02,0x21,0x20,0x40,0x00,
+0x1f,0x0d,0x00,0x0c,0x21,0x28,0x00,0x02,0x02,0x80,0x04,0x3c,0x78,0x1b,0x82,0x24,
+0x01,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x89,0x00,0x74,0x10,0x00,0x00,0x00,0x00,
+0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x01,0x00,0x83,0x90,0x02,0x00,0x02,0x24,
+0x08,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x8e,0x00,0x00,0x00,0x00,
+0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x52,0x00,0xed,0x0e,0x00,0x08,
+0xff,0xff,0x52,0x30,0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,
+0x0f,0x00,0x45,0x30,0x08,0x00,0xa3,0x28,0xf3,0xff,0x60,0x10,0x02,0x17,0x04,0x00,
+0x03,0x00,0x42,0x30,0xf0,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,
+0x21,0x10,0xa3,0x00,0xf0,0x04,0x50,0x90,0x80,0x28,0x12,0x00,0x21,0x28,0xb1,0x00,
+0x75,0x0d,0x00,0x0c,0x21,0x20,0x60,0x02,0x21,0x20,0x40,0x00,0x1f,0x0d,0x00,0x0c,
+0x21,0x28,0x00,0x02,0x00,0x00,0x65,0x8e,0x6d,0x0f,0x00,0x08,0xc2,0x13,0x05,0x00,
+0x02,0x80,0x04,0x3c,0x00,0x01,0x02,0x36,0x78,0x1b,0x84,0x24,0x00,0x00,0x47,0xac,
+0xa4,0x25,0x87,0xac,0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,0x21,0x28,0x00,0x00,
+0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0xf7,0x0d,0x00,0x08,
+0x02,0x80,0x02,0x3c,0x99,0x99,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x96,0x99,0x63,0x34,
+0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x1e,0x0e,0x00,0x08,0x00,0x00,0x00,0x00,
+0xd0,0x0c,0xa2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xd0,0x0c,0xa2,0xac,
+0x0c,0x00,0x64,0x8e,0x03,0x0f,0x00,0x08,0x3f,0x00,0x83,0x30,0xcc,0x0c,0xa2,0x8e,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xcc,0x0c,0xa2,0xae,0x0c,0x00,0x64,0x8e,
+0xff,0x0e,0x00,0x08,0x3f,0x00,0x83,0x30,0xac,0x25,0x22,0x8e,0xff,0xff,0x73,0x30,
+0x23,0x10,0x47,0x00,0xff,0xff,0x52,0x30,0x21,0x18,0x53,0x02,0xff,0xff,0x77,0x30,
+0x39,0x15,0x00,0x0c,0x21,0x20,0xe0,0x02,0xda,0xff,0x40,0x10,0x21,0xb0,0x40,0x00,
+0x08,0x00,0x42,0x8c,0xa4,0x25,0x26,0x8e,0x21,0x38,0x40,0x02,0x21,0x18,0x57,0x00,
+0x74,0x25,0x23,0xae,0x21,0x28,0x40,0x00,0x08,0x00,0x04,0x24,0x78,0x25,0x22,0xae,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x00,0x02,0x00,0x0c,0x08,0x00,0x04,0x24,
+0x78,0x25,0x25,0x8e,0x24,0x10,0x02,0x3c,0x00,0x01,0x10,0x36,0x00,0x00,0x02,0xae,
+0x21,0x38,0x60,0x02,0x21,0x28,0xb2,0x00,0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c,
+0xa4,0x25,0x22,0xae,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xa8,0x25,0x23,0x8e,
+0x08,0x00,0x04,0x24,0x00,0x02,0x00,0x0c,0xa4,0x25,0x23,0xae,0xa4,0x25,0x22,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,0xca,0x0e,0x00,0x08,0x02,0x80,0x03,0x3c,
+0xff,0xff,0x57,0x30,0x39,0x15,0x00,0x0c,0x21,0x20,0xe0,0x02,0x42,0x00,0x40,0x10,
+0x21,0xb0,0x40,0x00,0x08,0x00,0x42,0x8c,0xa4,0x25,0x26,0x8e,0x08,0x00,0x04,0x24,
+0x21,0x18,0x57,0x00,0x74,0x25,0x23,0xae,0x21,0x28,0x40,0x00,0x21,0x38,0xe0,0x02,
+0x78,0x25,0x22,0xae,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xa8,0x25,0x23,0x8e,
+0x08,0x00,0x04,0x24,0x00,0x02,0x00,0x0c,0xa4,0x25,0x23,0xae,0xa4,0x25,0x23,0x8e,
+0x00,0x01,0x02,0x36,0x00,0x00,0x43,0xac,0xca,0x0e,0x00,0x08,0x02,0x80,0x03,0x3c,
+0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x42,0x30,
+0x08,0x00,0x42,0x28,0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x04,0x00,
+0x03,0x00,0x42,0x30,0x0b,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x00,0xc0,0x02,0x3c,
+0x24,0x10,0x82,0x00,0x6a,0xff,0x40,0x14,0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30,
+0x03,0x00,0x03,0x24,0x66,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x64,0xff,0x40,0x10,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,
+0x01,0x00,0x42,0x30,0x06,0x00,0x54,0x14,0x21,0x80,0x00,0x00,0x02,0x14,0x04,0x00,
+0x0f,0x00,0x42,0x30,0x78,0x1b,0x63,0x24,0x21,0x10,0x43,0x00,0xf0,0x04,0x50,0x90,
+0x80,0x28,0x12,0x00,0x21,0x28,0xb1,0x00,0xec,0xff,0xa2,0x8c,0x25,0xb0,0x03,0x3c,
+0xd4,0x02,0x63,0x34,0x21,0x20,0x60,0x02,0x00,0x00,0x62,0xac,0x75,0x0d,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x1f,0x0d,0x00,0x0c,0x21,0x28,0x00,0x02,
+0x65,0x0f,0x00,0x08,0x02,0x80,0x04,0x3c,0xa8,0x25,0x23,0x8e,0x00,0x01,0x02,0x36,
+0x00,0x00,0x43,0xac,0x8d,0x0f,0x00,0x08,0xa4,0x25,0x23,0xae,0xe0,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14,
+0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c,0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30,
+0x40,0x20,0x04,0x00,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26,
+0xfc,0x23,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00,
+0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,
+0xfc,0x23,0xa4,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,
+0x7e,0x00,0x84,0x30,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26,
+0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00,
+0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,
+0x00,0x24,0xa4,0xac,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x00,0x24,0xa2,0xac,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,
+0xfc,0x23,0xa2,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,
+0x7e,0x00,0x84,0x30,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26,
+0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14,
+0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00,0x49,0x10,0x00,0x08,0x00,0x24,0xa4,0xac,
+0x00,0x21,0x03,0x00,0x35,0x10,0x00,0x08,0xfc,0x23,0xa4,0xac,0xb8,0xff,0xbd,0x27,
+0x25,0xb0,0x03,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,
+0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,
+0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x44,0x00,0x63,0x34,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,
+0x0e,0x00,0x40,0x04,0x18,0x00,0xa0,0xaf,0x21,0x20,0x60,0x00,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,0x64,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x02,0x00,
+0x03,0x16,0x02,0x00,0xf6,0xff,0x41,0x04,0x21,0x10,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x78,0x41,0x43,0x8c,0x00,0x80,0x06,0x3c,0xcc,0x41,0xc2,0x24,0x25,0xb0,0x05,0x3c,
+0x02,0x80,0x06,0x3c,0x18,0x03,0xa4,0x34,0x78,0x41,0xd1,0x24,0x00,0x00,0x82,0xac,
+0x5d,0x00,0x71,0x10,0x01,0x00,0x15,0x24,0x2a,0xb0,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0x06,0x00,0x56,0x34,0x78,0x1b,0x74,0x24,0xb0,0x03,0xb7,0x34,0x21,0xf0,0x80,0x00,
+0x05,0x00,0x53,0x34,0x01,0x00,0x12,0x24,0x1b,0x00,0xa0,0x12,0x02,0x80,0x03,0x3c,
+0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x17,0x00,0x40,0x10,0x21,0xa8,0x00,0x00,
+0x01,0x00,0x06,0x24,0x18,0x00,0xa6,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x57,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x02,0x80,0x06,0x3c,0x56,0x43,0xc2,0x90,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x30,0x4d,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x96,0x00,0x26,0x90,0x8e,
+0x00,0xff,0x42,0x30,0x00,0x00,0xf0,0xae,0x0d,0x00,0x40,0x18,0x02,0x80,0x02,0x3c,
+0x84,0xaf,0x42,0x24,0x21,0x28,0xc0,0x03,0x00,0x00,0x44,0x8c,0x02,0x80,0x06,0x3c,
+0x88,0xaf,0xc6,0x24,0x00,0x00,0xc3,0x8c,0x00,0x00,0xa4,0xac,0x00,0x00,0x62,0x94,
+0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfb,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,
+0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0x62,0x30,0x48,0x00,0x40,0x14,
+0x08,0x00,0x62,0x24,0xc2,0x10,0x03,0x00,0x08,0x00,0x05,0x8e,0xcc,0x24,0x86,0x8e,
+0xc0,0x10,0x02,0x00,0x20,0x00,0x42,0x24,0xff,0xff,0x47,0x30,0x01,0x00,0x04,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xb2,0xaf,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x02,0x00,0x02,0x24,0x00,0x00,0x72,0xa2,0x00,0x00,0x62,0xa2,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x04,0x00,0x03,0x8e,
+0x00,0x00,0x02,0x8e,0x21,0x20,0x00,0x02,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,
+0x00,0x00,0x10,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x10,0xae,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x00,0x22,0x8e,0x00,0x00,0x00,0x00,
+0xad,0xff,0x51,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,
+0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,
+0x00,0x00,0x00,0x00,0x11,0x00,0x40,0x14,0x18,0x00,0xa0,0xaf,0x02,0x80,0x02,0x3c,
+0x08,0x08,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c,
+0x21,0x38,0x00,0x00,0x94,0x10,0x00,0x08,0x02,0x80,0x02,0x3c,0x55,0x1f,0x00,0x0c,
+0x01,0x00,0x04,0x24,0xbf,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0xf9,0x1f,0x00,0x0c,
+0x04,0x00,0x04,0x24,0xba,0x10,0x00,0x08,0x02,0x80,0x06,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c,
+0x99,0x44,0xc4,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x04,0x11,0x00,0x08,0x02,0x80,0x02,0x3c,
+0xda,0x10,0x00,0x08,0xc2,0x10,0x02,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
+0x08,0x00,0xe0,0x03,0x08,0x00,0x82,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,
+0x24,0x11,0x00,0x0c,0x74,0x00,0x84,0x24,0x21,0x28,0x40,0x00,0x10,0x00,0xa4,0x27,
+0x46,0x46,0x00,0x0c,0x02,0x00,0x06,0x24,0x10,0x00,0xa2,0x97,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
+0x18,0x00,0xbf,0xaf,0x24,0x11,0x00,0x0c,0x10,0x00,0xa5,0xa7,0x21,0x20,0x40,0x00,
+0x10,0x00,0xa5,0x27,0x46,0x46,0x00,0x0c,0x02,0x00,0x06,0x24,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x0a,0x00,0x82,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x3f,0x11,0x00,0x0c,
+0x74,0x00,0x84,0x24,0x21,0x28,0x40,0x00,0x10,0x00,0xa4,0x27,0x46,0x46,0x00,0x0c,
+0x02,0x00,0x06,0x24,0x10,0x00,0xa2,0x97,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0x21,0x80,0x80,0x00,0x00,0x00,0x05,0xa2,0x01,0x00,0x06,0xa2,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,0x21,0x88,0xc0,0x00,0x02,0x00,0x84,0x24,
+0x30,0x00,0xb2,0x8f,0x0d,0x00,0xc0,0x14,0x21,0x28,0xe0,0x00,0x00,0x00,0x43,0x8e,
+0x21,0x10,0x11,0x02,0x1c,0x00,0xbf,0x8f,0x21,0x18,0x71,0x00,0x02,0x00,0x63,0x24,
+0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f,0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f,
+0x02,0x00,0x42,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x8e,0x21,0x10,0x11,0x02,0x1c,0x00,0xbf,0x8f,
+0x21,0x18,0x71,0x00,0x02,0x00,0x63,0x24,0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f,
+0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x00,0x42,0x24,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00,
+0x18,0x00,0xb2,0xaf,0x21,0x28,0xc0,0x00,0x21,0x90,0xe0,0x00,0x21,0x30,0x00,0x02,
+0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x46,0x46,0x00,0x0c,0x21,0x88,0x80,0x00,
+0x00,0x00,0x43,0x8e,0x21,0x10,0x30,0x02,0x1c,0x00,0xbf,0x8f,0x21,0x18,0x70,0x00,
+0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f,0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x10,0x00,0xe0,0x18,0x21,0x18,0x00,0x00,
+0x00,0x00,0xc0,0xac,0x21,0x40,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
+0x0c,0x00,0x45,0x10,0x21,0x18,0x80,0x00,0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
+0x21,0x18,0x48,0x00,0x02,0x00,0x68,0x24,0x21,0x10,0x82,0x00,0x2b,0x18,0x07,0x01,
+0xf5,0xff,0x60,0x14,0x02,0x00,0x44,0x24,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xac,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x7f,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,
+0x0a,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,
+0x8c,0xaf,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x6c,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x60,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x48,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x30,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x24,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x18,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x12,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x0c,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x16,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x0b,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xc8,0xff,0xbd,0x27,0x24,0x00,0xb5,0xaf,
+0x02,0x80,0x15,0x3c,0x2c,0x00,0xb7,0xaf,0x28,0x00,0xb6,0xaf,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x30,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x21,0xb8,0x80,0x00,0x21,0xa0,0x00,0x00,0x21,0x98,0x00,0x00,
+0x78,0x1b,0xb6,0x26,0x78,0x1b,0xa2,0x26,0x21,0x10,0x62,0x02,0x44,0x0b,0x51,0x90,
+0xfe,0x00,0x03,0x24,0x1e,0x00,0x23,0x12,0xff,0x00,0x02,0x24,0x21,0x00,0x22,0x12,
+0x21,0x10,0x80,0x02,0xa2,0x11,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x88,0x40,0x00,
+0x21,0x80,0x00,0x00,0x21,0x90,0xc0,0x02,0x21,0x10,0x12,0x02,0x26,0x0b,0x44,0x90,
+0x00,0x00,0x00,0x00,0x02,0x00,0x82,0x24,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c,
+0x05,0x00,0x40,0x14,0x01,0x00,0x10,0x26,0xa2,0x11,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x05,0x00,0x51,0x10,0x01,0x00,0x03,0x24,0x1e,0x00,0x02,0x2a,0xf3,0xff,0x40,0x14,
+0x21,0x10,0x12,0x02,0x21,0x18,0x00,0x00,0x01,0x00,0x02,0x24,0x14,0x00,0x62,0x10,
+0xff,0x00,0x22,0x32,0x21,0x10,0xf4,0x02,0x00,0x00,0x51,0xa0,0x01,0x00,0x94,0x26,
+0x01,0x00,0x73,0x26,0x1e,0x00,0x62,0x2a,0xdb,0xff,0x40,0x14,0x78,0x1b,0xa2,0x26,
+0x21,0x10,0x80,0x02,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0x01,0x12,0x00,0x08,0x80,0x00,0x51,0x34,0xb8,0xff,0xbd,0x27,0x3c,0x00,0xb3,0xaf,
+0x38,0x00,0xb2,0xaf,0x30,0x00,0xb0,0xaf,0x21,0x90,0xc0,0x00,0x21,0x98,0xa0,0x00,
+0x1e,0x00,0x06,0x24,0x21,0x28,0x00,0x00,0x21,0x80,0x80,0x00,0x10,0x00,0xa4,0x27,
+0x40,0x00,0xbf,0xaf,0x35,0x46,0x00,0x0c,0x34,0x00,0xb1,0xaf,0x10,0x00,0xa4,0x27,
+0xd2,0x11,0x00,0x0c,0x00,0x00,0x40,0xae,0x21,0x88,0x40,0x00,0x09,0x00,0x43,0x28,
+0x21,0x38,0x40,0x00,0x08,0x00,0x02,0x24,0x0a,0x88,0x43,0x00,0x01,0x00,0x02,0x24,
+0x21,0x20,0x60,0x02,0x10,0x00,0xa5,0x27,0x0e,0x00,0x02,0x12,0x21,0x30,0x20,0x02,
+0x05,0x00,0x60,0x14,0xf8,0xff,0xf1,0x24,0x21,0x20,0x60,0x02,0x18,0x00,0xa5,0x27,
+0x08,0x00,0x20,0x16,0x21,0x30,0x20,0x02,0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb3,0x8f,
+0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x48,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xae,
+0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,
+0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0x94,
+0x21,0x30,0x80,0x00,0x10,0x00,0x85,0x24,0x42,0x1a,0x02,0x00,0xc2,0x11,0x02,0x00,
+0x02,0x00,0x42,0x30,0x01,0x00,0x63,0x30,0x25,0x18,0x43,0x00,0x01,0x00,0x04,0x24,
+0x07,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x05,0x00,0x60,0x10,0x0a,0x00,0xc5,0x24,
+0x02,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x00,0x00,0x82,0x94,0x21,0x30,0x80,0x00,
+0x04,0x00,0x85,0x24,0x42,0x1a,0x02,0x00,0xc2,0x11,0x02,0x00,0x02,0x00,0x42,0x30,
+0x01,0x00,0x63,0x30,0x25,0x18,0x43,0x00,0x01,0x00,0x04,0x24,0x04,0x00,0x64,0x10,
+0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0xc5,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x13,0x00,0xa0,0x18,0x21,0x30,0x00,0x00,
+0x02,0x00,0x07,0x24,0x04,0x00,0x08,0x24,0x0b,0x00,0x09,0x24,0x16,0x00,0x0a,0x24,
+0x21,0x10,0x86,0x00,0x00,0x00,0x43,0x90,0x01,0x00,0xc6,0x24,0x7f,0x00,0x63,0x30,
+0x07,0x00,0x67,0x10,0x2a,0x10,0xc5,0x00,0x05,0x00,0x68,0x10,0x00,0x00,0x00,0x00,
+0x03,0x00,0x69,0x10,0x00,0x00,0x00,0x00,0x05,0x00,0x6a,0x14,0x00,0x00,0x00,0x00,
+0xf3,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,
+0x6a,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x01,0x00,0x44,0x38,
+0x03,0x00,0x03,0x24,0x01,0x00,0x02,0x24,0x0b,0x10,0x64,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40,
+0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,
+0xfc,0xa9,0x64,0xac,0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0xfc,0xa9,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x18,0x03,0x42,0x34,0x70,0x4a,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,
+0x1e,0x00,0xa2,0x10,0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,
+0x03,0x00,0x02,0x24,0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
+0x21,0x10,0x44,0x00,0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,
+0x06,0x00,0x02,0x24,0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,
+0x23,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,
+0x23,0x18,0x62,0x00,0xb2,0x12,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
+0x21,0x10,0x44,0x00,0xb2,0x12,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,
+0xfc,0xa9,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
+0x2c,0x4b,0x63,0x24,0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x06,0x00,0xa2,0x10,
+0x06,0x00,0xa2,0x2c,0x0c,0x00,0x40,0x10,0x06,0x00,0x02,0x24,0x04,0x00,0x02,0x24,
+0x0e,0x00,0xa2,0x10,0x80,0x10,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0x80,0x10,0x02,0x00,0xff,0xff,0x42,0x24,0xfe,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf7,0xff,0xa2,0x14,0x00,0x11,0x04,0x00,
+0x23,0x10,0x44,0x00,0xdd,0x12,0x00,0x08,0x40,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
+0xdd,0x12,0x00,0x08,0x40,0x10,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24,
+0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30,
+0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0xff,0x12,0x00,0x08,
+0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,
+0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14,
+0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,
+0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c,
+0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c,
+0x13,0x13,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0,
+0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24,
+0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30,
+0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36,
+0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,
+0xa8,0x00,0x14,0x36,0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,
+0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae,
+0x00,0x00,0x00,0xae,0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,
+0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,
+0x00,0x00,0x22,0xa6,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,0x70,0x0b,0x44,0x8c,
+0xfc,0x37,0x02,0x24,0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae,
+0x00,0x00,0x22,0xa6,0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0xc8,0xff,0xbd,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,
+0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40,
+0x01,0x00,0xc1,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c,
+0x40,0x00,0x30,0x36,0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24,
+0x00,0x00,0xc2,0xa3,0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0xcb,0x12,0x00,0x0c,
+0x32,0x00,0x04,0x24,0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,
+0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6,
+0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0xcb,0x12,0x00,0x0c,
+0x32,0x00,0x04,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0xcb,0x12,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36,
+0x24,0x10,0x43,0x00,0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36,
+0xa4,0x00,0x35,0x36,0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae,
+0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,
+0x00,0x00,0xa3,0xa0,0x00,0x00,0x12,0xa6,0xea,0x12,0x00,0x0c,0x56,0x01,0x31,0x36,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,
+0x70,0x0b,0x44,0x8c,0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae,
+0x00,0x00,0x65,0xae,0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3,
+0x00,0x60,0x96,0x40,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x38,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
+0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,
+0x00,0x00,0xa2,0x94,0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,
+0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,
+0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,
+0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,
+0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x25,0xb0,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,
+0x24,0x10,0x43,0x00,0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x1c,0x00,0xb3,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x34,0x00,0xbf,0xaf,
+0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
+0x20,0x00,0xb4,0xaf,0x0a,0x00,0x67,0x34,0x00,0x00,0xe2,0x90,0xff,0xff,0xb2,0x30,
+0x21,0x98,0xc0,0x00,0xff,0x00,0x91,0x30,0x20,0x00,0x40,0x12,0xff,0x00,0x50,0x30,
+0x21,0xa0,0xe0,0x00,0x0c,0x00,0x77,0x34,0x0b,0x00,0x76,0x34,0x21,0xf0,0xe0,0x00,
+0xc0,0xff,0x15,0x24,0x25,0x10,0x15,0x02,0xff,0x00,0x50,0x30,0x00,0x00,0xd1,0xa2,
+0x00,0x00,0x90,0xa2,0x00,0x00,0x82,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x50,0x30,
+0xc0,0x00,0x03,0x32,0x07,0x00,0x60,0x10,0x21,0x20,0xc0,0x03,0x00,0x00,0x82,0x90,
+0x00,0x00,0x00,0x00,0xff,0x00,0x50,0x30,0xc0,0x00,0x03,0x32,0xfb,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x8e,0x04,0x00,0x23,0x26,0x64,0x00,0x04,0x24,
+0x00,0x00,0x62,0xae,0x9c,0x12,0x00,0x0c,0xff,0x00,0x71,0x30,0xfc,0xff,0x42,0x26,
+0xff,0xff,0x52,0x30,0xe7,0xff,0x40,0x16,0x04,0x00,0x73,0x26,0x34,0x00,0xbf,0x8f,
+0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,
+0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xff,0x00,0x84,0x30,
+0xff,0xff,0xac,0x30,0xc0,0x48,0x04,0x00,0x00,0x60,0x0e,0x40,0x01,0x00,0xc1,0x35,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0x40,0x02,0x4d,0x34,
+0xf8,0xff,0xe7,0x24,0x21,0x40,0x00,0x00,0x01,0x00,0x0f,0x24,0x44,0x02,0x4b,0x34,
+0x57,0x14,0x00,0x08,0x01,0x80,0x0a,0x3c,0x28,0x00,0x0f,0x11,0x00,0x00,0x00,0x00,
+0x01,0x00,0xe2,0x90,0x00,0x00,0xe4,0x90,0x02,0x00,0xe3,0x90,0x03,0x00,0xe5,0x90,
+0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,0x00,0x1c,0x03,0x00,0x25,0x20,0x83,0x00,
+0x21,0x10,0x28,0x01,0x00,0x2e,0x05,0x00,0x01,0x00,0x08,0x25,0x25,0x20,0x85,0x00,
+0x25,0x10,0x4a,0x00,0x06,0x00,0x03,0x2d,0x00,0x00,0x64,0xad,0x04,0x00,0xe7,0x24,
+0x00,0x00,0xa2,0xad,0x12,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0xea,0xff,0x00,0x15,
+0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x04,0x00,0xe7,0x24,
+0x00,0x14,0x02,0x00,0x25,0x10,0x82,0x01,0x00,0x1e,0x03,0x00,0x25,0x20,0x43,0x00,
+0x21,0x10,0x28,0x01,0x01,0x00,0x08,0x25,0x25,0x10,0x4a,0x00,0x06,0x00,0x03,0x2d,
+0x00,0x00,0x64,0xad,0x00,0x00,0xa2,0xad,0xf0,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x00,0x60,0x8e,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x03,0x00,0xc2,0x90,
+0x02,0x00,0xc4,0x90,0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x49,0x14,0x00,0x08,
+0x00,0x12,0x02,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00,
+0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00,
+0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24,
+0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00,
+0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c,
+0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,
+0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24,
+0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00,
+0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00,
+0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0,
+0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x00,0xaa,0x42,0x24,
+0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac,
+0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac,
+0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0x9a,0x14,0x00,0x08,
+0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0x9a,0x14,0x00,0x08,0x10,0x00,0x82,0xac,
+0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,
+0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,
+0x25,0xb0,0x02,0x3c,0x02,0x80,0x16,0x3c,0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,
+0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x30,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x03,0x55,0x34,0x00,0x80,0x17,0x3c,
+0x02,0x80,0x13,0x3c,0x02,0x80,0x14,0x3c,0x00,0xaa,0xd2,0x26,0x08,0x53,0xe2,0x26,
+0x00,0x00,0xa2,0xae,0x00,0xaa,0xd0,0x8e,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x8c,0x43,0x71,0x8e,0x00,0x00,0x00,0x00,
+0x25,0x00,0x20,0x12,0x00,0x00,0x00,0x00,0x8c,0x43,0x60,0xae,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x23,0x00,0x12,0x12,0x08,0x0c,0x84,0x26,
+0x14,0x00,0x03,0x92,0x01,0x00,0x02,0x24,0x2b,0x00,0x62,0x10,0x00,0x00,0x00,0x00,
+0x0a,0x00,0x60,0x14,0x02,0x00,0x02,0x24,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x23,0x02,0x1e,0x00,0x40,0x10,0x23,0x10,0x71,0x00,0x0c,0x00,0x02,0xae,
+0x00,0x00,0x10,0x8e,0xe2,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0xfc,0xff,0x62,0x14,
+0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0xf8,0xff,0x60,0x10,
+0x2b,0x10,0x23,0x02,0xf5,0xff,0x40,0x14,0x23,0x10,0x71,0x00,0x08,0x00,0x02,0x8e,
+0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x0c,0x00,0x00,0xae,0x00,0x00,0x10,0x8e,
+0xe2,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x08,0x0c,0x84,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0xd4,0x14,0x00,0x08,0x08,0x53,0xe2,0x26,
+0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,
+0xf0,0x14,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x23,0x02,0xd9,0xff,0x40,0x14,0x23,0x10,0x71,0x00,0x08,0x00,0x02,0x8e,
+0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0xae,0x00,0x00,0x10,0x8e,0xe2,0x14,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x80,0x41,0x42,0x24,0xc0,0x20,0x04,0x00,
+0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00,
+0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,
+0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,
+0x21,0x10,0xa0,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,
+0x01,0x01,0x02,0x2e,0x14,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,0x01,0x02,0x03,0x2e,
+0x0b,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x02,0x00,0x04,0x24,0x08,0x00,0x60,0x14,
+0x01,0x08,0x02,0x2e,0x06,0x00,0x40,0x14,0x03,0x00,0x04,0x24,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0x21,0x15,0x00,0x0c,0x00,0x00,0x00,0x00,0xf8,0xff,0x40,0x10,0x21,0x28,0x40,0x00,
+0x0c,0x00,0x50,0xac,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c,
+0x80,0x41,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c,
+0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,
+0x04,0x00,0x83,0xac,0x58,0x44,0xe5,0x8c,0x00,0x00,0x00,0x00,0x05,0x00,0xa0,0x10,
+0x00,0x00,0x64,0xac,0x44,0x44,0x02,0x8d,0x58,0x44,0xe0,0xac,0x25,0x10,0x45,0x00,
+0x44,0x44,0x02,0xad,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x7c,0x3f,0x43,0x8c,0xff,0x00,0xa5,0x30,0x25,0xb0,0x02,0x3c,
+0x42,0x18,0x03,0x00,0x21,0x30,0xa2,0x00,0x01,0x00,0x63,0x30,0x01,0x00,0x02,0x24,
+0x10,0x00,0xa7,0x2c,0x04,0x00,0x62,0x10,0xff,0x00,0x84,0x30,0x60,0x01,0xc4,0xa0,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x34,
+0xfa,0xff,0xe0,0x10,0x21,0x40,0x43,0x00,0x60,0x01,0xc4,0xa0,0x60,0x01,0x04,0xa1,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x01,0x00,0x03,0x24,
+0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,0x15,0x00,0x84,0x2c,
+0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,0x04,0x00,0xa0,0x14,
+0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01,
+0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00,
+0x78,0x1b,0x42,0x24,0x21,0x18,0x62,0x00,0x8c,0x11,0x66,0x8c,0x21,0x38,0x60,0x00,
+0x92,0x11,0x60,0xa0,0x93,0x11,0x60,0xa0,0x1c,0x00,0x05,0x24,0xa7,0x15,0x00,0x08,
+0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00,
+0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24,
+0x92,0x11,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x78,0x1b,0x63,0x24,0x21,0x18,0x43,0x00,
+0x8c,0x11,0x66,0x8c,0x21,0x28,0x00,0x00,0xbb,0x15,0x00,0x08,0x01,0x00,0x07,0x24,
+0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00,
+0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24,
+0x08,0x00,0xe0,0x03,0x93,0x11,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x80,0x10,0x00,0x20,0x00,0xbf,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,0x14,0x00,0xb1,0xaf,
+0x90,0x11,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,0x07,0x00,0x63,0x30,
+0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,0x88,0x11,0x05,0x8e,
+0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,0x24,0x10,0x45,0x00,
+0x96,0x15,0x00,0x0c,0x8c,0x11,0x02,0xae,0x92,0x11,0x04,0x92,0x70,0x15,0x00,0x0c,
+0xff,0x00,0x45,0x32,0x92,0x11,0x04,0x92,0x86,0x15,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,0x00,0x00,0x71,0xa2,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xff,0xff,0x84,0x30,
+0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,0x0b,0x00,0x84,0x30,
+0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x80,0x10,0x04,0x00,0xe0,0xaf,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x03,0x00,0x03,0x24,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x90,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x68,0x00,0xbe,0xaf,0x64,0x00,0xb7,0xaf,0x60,0x00,0xb6,0xaf,
+0x5c,0x00,0xb5,0xaf,0x54,0x00,0xb3,0xaf,0x50,0x00,0xb2,0xaf,0x6c,0x00,0xbf,0xaf,
+0x58,0x00,0xb4,0xaf,0x4c,0x00,0xb1,0xaf,0x48,0x00,0xb0,0xaf,0x10,0xb0,0x42,0x24,
+0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24,0x10,0x00,0xa3,0xaf,0x21,0x98,0x00,0x00,
+0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,0x14,0x00,0xa0,0xaf,
+0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,0x21,0xb0,0x00,0x00,
+0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf,0x30,0x00,0xa0,0xaf,
+0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf,0x40,0x00,0xa0,0xaf,
+0x21,0x90,0x80,0x02,0x90,0x11,0x42,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00,
+0x01,0x00,0x42,0x30,0x6c,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x21,0x10,0x62,0x02,
+0x60,0x01,0x44,0x90,0x78,0x11,0x43,0x8e,0x74,0x11,0x46,0x8e,0xff,0x00,0x91,0x30,
+0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x21,0x10,0x24,0x02,0x77,0x04,0x44,0x90,
+0x5a,0x04,0x45,0x90,0x5c,0x11,0x47,0x8e,0x18,0x00,0x64,0x00,0x12,0x18,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,0x12,0x30,0x00,0x00,
+0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x25,0x01,0x40,0x14,0x23,0x10,0xe6,0x00,
+0x5c,0x11,0x42,0xae,0x78,0x11,0x44,0x8e,0x74,0x11,0x47,0x8e,0x60,0x11,0x48,0x8e,
+0x64,0x11,0x45,0x8e,0x6c,0x11,0x46,0x8e,0x70,0x11,0x43,0x8e,0x21,0x38,0xe4,0x00,
+0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x21,0x10,0x24,0x02,0x21,0x40,0x05,0x01,
+0x21,0x30,0xc3,0x00,0xce,0x04,0x42,0x90,0x5c,0x11,0x4a,0x8e,0x0c,0x00,0xe0,0x10,
+0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,0x02,0x80,0x02,0x3c,
+0x07,0x00,0x22,0x2e,0x93,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,0x0c,0x00,0x02,0x24,
+0x8f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24,0x8e,0x01,0x22,0x12,0xc0,0x10,0x07,0x00,
+0x81,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x18,0x11,0x00,
+0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02,0xce,0x11,0x85,0x90,0xf8,0x04,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,0x76,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0xec,0x11,0x42,0x8e,0x01,0x00,0x07,0x24,0x04,0x18,0x27,0x02,
+0x24,0x10,0x43,0x00,0x04,0x01,0x40,0x10,0x1c,0x00,0x22,0x2e,0x21,0x28,0x51,0x02,
+0x94,0x11,0xa6,0x90,0xce,0x11,0xa2,0x90,0x0a,0x00,0x04,0x24,0xff,0x00,0xc3,0x30,
+0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xfb,0x00,0x60,0x10,0x1c,0x00,0x22,0x2e,
+0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x8c,0x01,0x64,0x10,0x94,0x11,0xa2,0xa0,
+0x02,0x80,0x04,0x3c,0x78,0x1b,0x85,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x45,0x00,
+0x6c,0x05,0x44,0x8c,0xf8,0x04,0x43,0x8c,0x21,0x30,0xc5,0x02,0x40,0x10,0x04,0x00,
+0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,0x5c,0x11,0xca,0xac,
+0xec,0x25,0xa3,0x8c,0xff,0xff,0x02,0x34,0x03,0x00,0x62,0x10,0x21,0x20,0x20,0x02,
+0x70,0x15,0x00,0x0c,0xff,0x00,0x65,0x32,0x86,0x15,0x00,0x0c,0x21,0x20,0x20,0x02,
+0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,
+0xbc,0x00,0x60,0x12,0x10,0x00,0xa4,0xaf,0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24,
+0x21,0x10,0xa2,0x02,0x70,0x11,0x40,0xac,0x74,0x11,0x40,0xac,0x78,0x11,0x40,0xac,
+0x60,0x11,0x40,0xac,0x64,0x11,0x40,0xac,0x68,0x11,0x40,0xac,0x6c,0x11,0x40,0xac,
+0x40,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0x8f,0x01,0x00,0x73,0x26,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x40,0x00,0xa4,0xaf,0x3c,0x00,0xa2,0xaf,0x38,0x00,0xa4,0x8f,
+0x34,0x00,0xa2,0x8f,0x20,0x00,0x63,0x2a,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,
+0x38,0x00,0xa4,0xaf,0x34,0x00,0xa2,0xaf,0x30,0x00,0xa4,0x8f,0x2c,0x00,0xa2,0x8f,
+0x94,0x00,0x52,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x30,0x00,0xa4,0xaf,
+0x2c,0x00,0xa2,0xaf,0x28,0x00,0xa4,0x8f,0x24,0x00,0xa2,0x8f,0x94,0x00,0xd6,0x26,
+0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0xaf,0x24,0x00,0xa2,0xaf,
+0x20,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0x8f,0x94,0x00,0xde,0x27,0x94,0x00,0x84,0x24,
+0x94,0x00,0x42,0x24,0x20,0x00,0xa4,0xaf,0x1c,0x00,0xa2,0xaf,0x18,0x00,0xa4,0x8f,
+0x14,0x00,0xa2,0x8f,0x94,0x00,0x94,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,
+0x18,0x00,0xa4,0xaf,0x14,0x00,0xa2,0xaf,0x94,0x00,0xf7,0x26,0x59,0xff,0x60,0x14,
+0x94,0x00,0xb5,0x26,0x10,0x00,0xa3,0x8f,0x6c,0x00,0xbf,0x8f,0x68,0x00,0xbe,0x8f,
+0x64,0x00,0xb7,0x8f,0x60,0x00,0xb6,0x8f,0x5c,0x00,0xb5,0x8f,0x58,0x00,0xb4,0x8f,
+0x54,0x00,0xb3,0x8f,0x50,0x00,0xb2,0x8f,0x4c,0x00,0xb1,0x8f,0x48,0x00,0xb0,0x8f,
+0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x70,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x87,0x00,0xe0,0x10,0x00,0x00,0x00,0x00,
+0x87,0x00,0x20,0x15,0x02,0x80,0x03,0x3c,0x40,0x10,0x07,0x00,0x21,0x10,0x47,0x00,
+0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0xa7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x20,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,0x78,0x1b,0x88,0x24,0x21,0x20,0x48,0x00,
+0x21,0x30,0x91,0x00,0xec,0x11,0x83,0x8c,0x01,0x00,0x05,0x24,0x04,0x10,0x25,0x02,
+0xb1,0x11,0xc7,0x90,0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,0xec,0x11,0x83,0xac,
+0x09,0x00,0xe5,0x10,0x94,0x11,0xc0,0xa0,0x1c,0x00,0xa3,0x8f,0x21,0x38,0x00,0x00,
+0x21,0x20,0x68,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,
+0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x02,0x80,0x04,0x3c,0x78,0x1b,0x83,0x24,
+0x18,0x00,0xa4,0x8f,0x21,0x50,0x60,0x00,0x21,0x38,0x00,0x00,0x21,0x10,0x83,0x00,
+0x21,0x10,0x51,0x00,0xb1,0x11,0x40,0xa0,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x70,0xae,0x49,0x24,0xfc,0xad,0x68,0x24,0x80,0x18,0x07,0x00,0x21,0x10,0x69,0x00,
+0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0xe7,0x24,
+0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,
+0x6c,0x05,0x66,0xac,0x15,0x00,0x20,0x12,0x02,0x80,0x05,0x3c,0x93,0x11,0x82,0x92,
+0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00,0x10,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,
+0x14,0x00,0xa4,0x8f,0x78,0x1b,0x62,0x24,0x21,0x10,0x82,0x00,0x93,0x11,0x45,0x90,
+0x8c,0x11,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,
+0x06,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,0x2a,0x10,0xe5,0x00,
+0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0x56,0x43,0xa3,0x90,
+0x22,0x00,0x02,0x24,0xe8,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0x02,0x80,0x04,0x3c,
+0x78,0x1b,0x83,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00,0x6c,0x05,0x44,0x8c,
+0xf8,0x04,0x43,0x8c,0x56,0x43,0xa5,0x90,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xd6,0x00,0xa2,0x10,0x82,0x50,0x03,0x00,
+0xec,0x11,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02,0x25,0x18,0x62,0x00,
+0xec,0x11,0x83,0xae,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x21,0x10,0xe3,0x02,
+0x5c,0x11,0x4a,0xac,0xec,0x25,0x64,0x8c,0xff,0xff,0x02,0x34,0x44,0xff,0x82,0x14,
+0x21,0x20,0x20,0x02,0x86,0x15,0x00,0x0c,0x21,0x20,0x20,0x02,0x10,0x00,0xa4,0x8f,
+0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,0x46,0xff,0x60,0x16,
+0x10,0x00,0xa4,0xaf,0x02,0x80,0x02,0x3c,0x78,0x1b,0x50,0x24,0x64,0x11,0x05,0x96,
+0x60,0x11,0x02,0x96,0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00,0x21,0x28,0x45,0x00,
+0x10,0x50,0x00,0x0c,0x68,0x0c,0x24,0x36,0x70,0x11,0x02,0x8e,0x6c,0x11,0x05,0x8e,
+0x68,0x11,0x03,0x96,0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00,0x00,0x2c,0x05,0x00,
+0x10,0x50,0x00,0x0c,0x21,0x28,0x65,0x00,0xaf,0x16,0x00,0x08,0x02,0x80,0x03,0x3c,
+0x59,0x16,0x00,0x08,0x5c,0x11,0x40,0xae,0x27,0xff,0x20,0x11,0x02,0x80,0x03,0x3c,
+0x78,0x1b,0x62,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x6c,0x05,0x64,0x8c,
+0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x1f,0xff,0x80,0x10,0x00,0x00,0x00,0x00,
+0x00,0x17,0x00,0x08,0x00,0x00,0x00,0x00,0x0a,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,
+0x21,0x20,0x51,0x02,0xb1,0x11,0x83,0x90,0x01,0x00,0x02,0x24,0x78,0x00,0x62,0x10,
+0x02,0x80,0x02,0x3c,0x40,0x00,0xa3,0x8f,0x78,0x1b,0x42,0x24,0x21,0x20,0x62,0x00,
+0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,
+0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x3c,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,
+0x78,0x1b,0x85,0x24,0x21,0x30,0x45,0x00,0xec,0x11,0xc2,0x8c,0x01,0x00,0x03,0x24,
+0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd1,0x00,0x24,0x10,0x43,0x00,
+0xb1,0x11,0x80,0xa0,0xec,0x11,0xc2,0xac,0x12,0x00,0x20,0x16,0x94,0x11,0x80,0xa0,
+0x92,0x11,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,0x01,0x00,0x07,0x24,
+0x38,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x65,0x00,0x92,0x11,0x44,0x90,
+0x8c,0x11,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,0x8d,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,0xfa,0xff,0x40,0x10,
+0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x34,0x00,0xa2,0x8f,
+0x01,0x00,0x27,0x26,0x21,0x18,0x44,0x00,0x92,0x11,0x62,0x90,0x00,0x00,0x00,0x00,
+0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c,0x30,0x00,0xa3,0x8f,
+0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x92,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c,
+0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x73,0x00,0x43,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,
+0x02,0x80,0x05,0x3c,0x56,0x43,0xa3,0x90,0x22,0x00,0x02,0x24,0x3e,0x00,0x62,0x10,
+0xee,0xff,0x22,0x26,0x56,0x43,0xa3,0x90,0x22,0x00,0x02,0x24,0xbd,0xfe,0x62,0x14,
+0x02,0x80,0x04,0x3c,0x28,0x00,0xa2,0x8f,0x78,0x1b,0x86,0x24,0x21,0x20,0x46,0x00,
+0x90,0x11,0x85,0x8c,0x01,0x00,0x03,0x24,0x42,0x13,0x05,0x00,0x07,0x00,0x42,0x30,
+0xb3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e,0xb1,0xfe,0x40,0x14,0x1c,0x00,0x22,0x2e,
+0xaf,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x10,0xa2,0x00,
+0x00,0x20,0x42,0x34,0x90,0x11,0x82,0xac,0x93,0x11,0x83,0x90,0xff,0xff,0x27,0x26,
+0x2a,0x18,0xe3,0x00,0xa6,0xfe,0x60,0x14,0x00,0x00,0x00,0x00,0x24,0x00,0xa3,0x8f,
+0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00,0x93,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c,
+0xf9,0x17,0x00,0x08,0x01,0x00,0x06,0x24,0x2a,0x10,0xe5,0x00,0x9c,0xfe,0x40,0x14,
+0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0xfa,0xff,0x43,0x14,
+0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24,0x94,0x16,0x00,0x08,0xff,0x00,0xf1,0x30,
+0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,0xc2,0x10,0x02,0x00,0x2b,0x10,0x48,0x00,
+0x7c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x74,0x16,0x00,0x08,0x00,0x00,0x00,0x00,
+0x18,0x00,0x22,0x2e,0x17,0x00,0x40,0x14,0x05,0x00,0x22,0x2e,0xce,0x11,0x83,0x90,
+0x00,0x00,0x00,0x00,0x05,0x00,0x62,0x2c,0x8b,0xff,0x40,0x10,0x01,0x00,0x62,0x24,
+0x9a,0x17,0x00,0x08,0xce,0x11,0x82,0xa0,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c,
+0xc0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x2c,0x00,0xa3,0x8f,0x78,0x1b,0x82,0x24,
+0x21,0x10,0x62,0x00,0x8c,0x11,0x43,0x8c,0x00,0x01,0x04,0x3c,0x18,0x00,0x02,0x24,
+0x24,0x18,0x64,0x00,0xd5,0x17,0x00,0x08,0x0b,0x88,0x43,0x00,0x94,0x16,0x00,0x08,
+0xb1,0x11,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xce,0x11,0x83,0x90,
+0x0e,0x18,0x00,0x08,0x03,0x00,0x62,0x2c,0xce,0x11,0x83,0x90,0x0e,0x18,0x00,0x08,
+0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x29,0xff,0x22,0x16,0x02,0x80,0x02,0x3c,
+0x5b,0x17,0x00,0x08,0x78,0x1b,0x43,0x24,0x78,0x1b,0x62,0x24,0x21,0x20,0xc2,0x03,
+0x90,0x11,0x83,0x8c,0x00,0x00,0x00,0x00,0x42,0x13,0x03,0x00,0x07,0x00,0x42,0x30,
+0x12,0xff,0x40,0x10,0x14,0x00,0x22,0x2e,0x10,0xff,0x40,0x10,0x0c,0x00,0x22,0x2e,
+0x0e,0xff,0x40,0x14,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x10,0x62,0x00,
+0x47,0x17,0x00,0x08,0x90,0x11,0x82,0xac,0xff,0x00,0xf1,0x30,0xd1,0x17,0x00,0x08,
+0x02,0x80,0x05,0x3c,0xb9,0x17,0x00,0x08,0xff,0x00,0xf1,0x30,0x42,0x17,0x00,0x08,
+0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x38,0x00,0xb2,0xaf,
+0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf,0x4c,0x00,0xb7,0xaf,0x48,0x00,0xb6,0xaf,
+0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf,0x3c,0x00,0xb3,0xaf,0x34,0x00,0xb1,0xaf,
+0x30,0x00,0xb0,0xaf,0x78,0x1b,0x46,0x24,0x71,0x25,0xc4,0x90,0x6c,0x25,0xc3,0x8c,
+0x68,0x25,0xc2,0x8c,0x21,0x90,0x64,0x00,0x2b,0x10,0x42,0x02,0x7e,0x00,0x40,0x10,
+0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c,0x02,0x80,0x17,0x3c,0x21,0xa8,0xc0,0x00,
+0x21,0xb0,0xc0,0x00,0x64,0x18,0x00,0x08,0x01,0x00,0x14,0x24,0x68,0x25,0xc2,0x8e,
+0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x73,0x00,0x40,0x10,0x21,0x88,0xc0,0x02,
+0x71,0x25,0x22,0x92,0xff,0xff,0x45,0x32,0x25,0x28,0xb7,0x00,0x10,0x00,0x42,0x24,
+0x71,0x25,0x22,0xa2,0x54,0x3f,0xc4,0x27,0x46,0x46,0x00,0x0c,0x10,0x00,0x06,0x24,
+0x04,0x24,0x23,0x8e,0x00,0x00,0x00,0x00,0x42,0x18,0x03,0x00,0x01,0x00,0x63,0x30,
+0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xe0,0x23,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00,0x1f,0x00,0x10,0x32,0xc0,0x48,0x10,0x00,
+0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x55,0x00,0x90,0x11,0x45,0x8c,0x00,0x00,0x00,0x00,0x02,0x1b,0x05,0x00,
+0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10,0x21,0x30,0xa0,0x02,0x25,0xb0,0x02,0x3c,
+0x21,0x40,0x02,0x02,0xdc,0x23,0xa7,0x8e,0x04,0x24,0xa2,0x8e,0x60,0x01,0x03,0x91,
+0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30,0xff,0x00,0x6b,0x30,0x9a,0x00,0x54,0x10,
+0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c,0x14,0xb0,0x84,0x24,0x00,0x00,0x86,0x8c,
+0x04,0x00,0x04,0x24,0xdc,0x23,0xc3,0x8c,0x00,0x00,0x00,0x00,0x82,0x15,0x03,0x00,
+0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x0a,0x00,0x60,0x04,0x0a,0x50,0x82,0x00,
+0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x46,0x00,0x7c,0x11,0x43,0x8c,0x04,0x00,0x0a,0x24,0x01,0x00,0x63,0x24,
+0x7c,0x11,0x43,0xac,0xe0,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00,
+0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0xb8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0xdc,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0xb3,0xff,0x4b,0x14,
+0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11,0x21,0x10,0x30,0x01,0xa8,0x00,0x54,0x11,
+0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24,0xb0,0x00,0x42,0x11,0x21,0x10,0x30,0x01,
+0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11,0x21,0x10,0x30,0x01,0xc0,0x00,0x44,0x11,
+0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01,
+0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0xc8,0x00,0x60,0x14,
+0x00,0x00,0x00,0x00,0x74,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x21,0x10,0x4b,0x00,
+0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00,0x74,0x11,0xa3,0xac,0x21,0x10,0x4a,0x00,
+0x38,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,
+0x5c,0x11,0xa3,0xac,0x68,0x25,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,
+0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02,0x54,0x00,0xbf,0x8f,0x50,0x00,0xbe,0x8f,
+0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f,0x40,0x00,0xb4,0x8f,
+0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27,0xe0,0x23,0x22,0x8e,0x00,0x00,0x00,0x00,
+0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30,0x90,0xff,0x60,0x10,0x0f,0x00,0x50,0x30,
+0x39,0x15,0x00,0x0c,0x48,0x00,0x04,0x24,0x74,0xff,0x40,0x10,0x21,0x98,0x40,0x00,
+0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24,0x14,0x00,0x62,0xae,0x0c,0x00,0x64,0xae,
+0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24,0x08,0x00,0x07,0x24,0x80,0x00,0x63,0x34,
+0x14,0x00,0xa3,0xaf,0xe0,0x23,0x26,0x8e,0x24,0x18,0x64,0x00,0xff,0xe0,0x04,0x24,
+0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30,0x25,0x18,0x62,0x00,0x14,0x00,0xa3,0xaf,
+0xdc,0x23,0x25,0x8e,0x24,0x18,0x64,0x00,0x02,0x23,0x06,0x00,0x82,0x13,0x05,0x00,
+0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00,0xff,0xff,0x02,0x3c,0xff,0x7f,0x42,0x34,
+0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00,0xc0,0x2b,0x05,0x00,0x0f,0x00,0x02,0x3c,
+0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x35,0x06,0x00,
+0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34,0x0f,0x00,0x84,0x30,
+0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x02,0x80,0x04,0x3c,
+0x10,0x00,0xa5,0x27,0xa8,0x3f,0x84,0x24,0x02,0x00,0x06,0x24,0x04,0x00,0x02,0x24,
+0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf,0x52,0x46,0x00,0x0c,0x10,0x00,0xa2,0xa3,
+0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27,0x02,0x00,0x06,0x24,0x25,0x20,0x97,0x00,
+0x52,0x46,0x00,0x0c,0x20,0x00,0x84,0x24,0x59,0x0a,0x00,0x0c,0x21,0x20,0x60,0x02,
+0x78,0x18,0x00,0x08,0xc0,0x48,0x10,0x00,0x02,0x12,0x05,0x00,0x01,0x00,0x42,0x30,
+0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00,0x01,0x00,0x42,0x30,0x76,0x00,0x54,0x10,
+0x00,0x00,0x00,0x00,0x10,0x24,0xa2,0x96,0x60,0x01,0x03,0x91,0xc2,0x27,0x07,0x00,
+0x21,0x10,0x42,0x01,0x2c,0x24,0xa3,0xa2,0x13,0x00,0x80,0x10,0x10,0x24,0xa2,0xa6,
+0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c,0x0c,0x24,0xa2,0x96,0x16,0x24,0xa3,0x96,
+0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0x0c,0x24,0xa2,0xa6,0x8e,0x18,0x00,0x08,
+0x16,0x24,0xa3,0xa6,0x5d,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,0x0e,0x24,0xa3,0x96,
+0x1a,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x1a,0x24,0xa2,0xa6,
+0x8d,0x18,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x0e,0x24,0xa3,0x96,0x1c,0x24,0xa2,0x96,
+0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x1c,0x24,0xa2,0xa6,0x8d,0x18,0x00,0x08,
+0x0e,0x24,0xc3,0xa4,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x46,0x00,0x60,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,
+0x5c,0xff,0x54,0x15,0x60,0x11,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x64,0x11,0x43,0x8c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x64,0x11,0x43,0xac,0x02,0x00,0x02,0x24,
+0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,
+0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x68,0x11,0x43,0x8c,
+0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x68,0x11,0x43,0xac,0x03,0x00,0x02,0x24,
+0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x6c,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,
+0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15,0x6c,0x11,0x43,0xac,0x21,0x10,0x30,0x01,
+0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,
+0x70,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x70,0x11,0x43,0xac,
+0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,
+0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01,0x94,0x04,0x44,0x90,
+0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0x3a,0xff,0x60,0x10,0x00,0x00,0x00,0x00,
+0x78,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,
+0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x44,0x00,0x78,0x11,0xa3,0xac,
+0x21,0x10,0x4a,0x00,0xc9,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x64,0x00,0xd1,0x18,0x00,0x08,0x5c,0x11,0xa3,0xac,0x0c,0x24,0xa3,0x96,
+0x14,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x14,0x24,0xa2,0xa6,
+0x8d,0x18,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x08,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,
+0x0e,0x24,0xa3,0x96,0x18,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,
+0x18,0x24,0xa2,0xa6,0x8d,0x18,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x0c,0x24,0xa3,0x96,
+0x12,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x12,0x24,0xa2,0xa6,
+0x8d,0x18,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x02,0x80,0x0a,0x3c,0x78,0x1b,0x42,0x8d,
+0xe8,0xff,0xbd,0x27,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x11,0x00,0x40,0x14,
+0x10,0x00,0xbf,0xaf,0x25,0xb0,0x05,0x3c,0x4c,0x00,0xa2,0x34,0x00,0x00,0x43,0x90,
+0x78,0x1b,0x46,0x25,0xf9,0x0a,0xc2,0x90,0x03,0x00,0x67,0x30,0x09,0x00,0x47,0x10,
+0x58,0x00,0xa2,0x34,0x00,0x00,0x44,0x8c,0x29,0xb0,0x03,0x3c,0x5c,0x00,0xa2,0x34,
+0x00,0x00,0x64,0xac,0x00,0x00,0x44,0x8c,0x04,0x00,0x63,0x34,0xf9,0x0a,0xc7,0xa0,
+0x00,0x00,0x64,0xac,0x78,0x1b,0x42,0x25,0xcb,0x02,0x43,0x90,0x25,0xb0,0x02,0x3c,
+0x90,0x0c,0x42,0x34,0x0f,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25,0xc9,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x91,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x78,0x1b,0x42,0x25,0xca,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x92,0x0c,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25,
+0xc8,0x02,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x93,0x0c,0x42,0x34,0x02,0x1f,0x03,0x00,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25,
+0xea,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x98,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x2d,0x0a,0x46,0x34,
+0xa2,0x0d,0x43,0x34,0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34,0xa8,0x0d,0x42,0x34,
+0x00,0x00,0x67,0x94,0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94,0x00,0x00,0x44,0x94,
+0x00,0x00,0xc3,0x90,0x78,0x1b,0x42,0x25,0xe2,0x02,0x44,0xa4,0x40,0x00,0x63,0x34,
+0xff,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0xdc,0x02,0x47,0xa4,0xde,0x02,0x48,0xa4,
+0xe0,0x02,0x49,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,
+0x5b,0x0a,0xe2,0x34,0x00,0x00,0x44,0x90,0x78,0x1b,0x46,0x25,0x5c,0x0a,0xe2,0x34,
+0x00,0x00,0x45,0x90,0xdc,0x02,0xc3,0x94,0xde,0x02,0xc2,0x94,0xe0,0x02,0xc9,0x94,
+0xe2,0x02,0xc8,0x94,0xff,0x00,0x84,0x30,0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00,
+0xff,0x00,0xa5,0x30,0x21,0x20,0x85,0x00,0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30,
+0x21,0x18,0x68,0x00,0x21,0x18,0x62,0x00,0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30,
+0xe4,0x02,0xc3,0xac,0x00,0x00,0xe2,0xa4,0xe8,0x02,0xc4,0xa4,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x8d,0x01,0x00,0x03,0x24,0x01,0x00,0x44,0x30,
+0x07,0x00,0x83,0x10,0x78,0x1b,0x45,0x25,0x24,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x10,0x00,0xbf,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0xe8,0x02,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30,
+0xf5,0xff,0x40,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x4e,0x00,0x64,0x10,0x00,0x00,0x00,0x00,
+0x78,0x1b,0x45,0x25,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14,
+0x78,0x1b,0x46,0x25,0x78,0x1b,0x42,0x8d,0x01,0x00,0x03,0x24,0x02,0x11,0x02,0x00,
+0x03,0x00,0x42,0x30,0x49,0x00,0x43,0x10,0x3e,0x00,0x02,0x24,0xea,0x02,0xc3,0x90,
+0xff,0x00,0x02,0x24,0xe0,0xff,0x62,0x14,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,
+0x00,0x00,0x45,0x90,0xcc,0x02,0xc4,0x94,0xe4,0x02,0xc7,0x8c,0x32,0x00,0x02,0x24,
+0x20,0x00,0x03,0x24,0x7f,0x00,0xa5,0x30,0x2b,0x20,0xe4,0x00,0xd4,0x02,0xc2,0xa0,
+0xd5,0x02,0xc3,0xa0,0x0c,0x00,0x80,0x14,0xff,0xff,0xa2,0x24,0xce,0x02,0xc2,0x94,
+0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x09,0x00,0x40,0x14,0x78,0x1b,0x44,0x25,
+0xd0,0x02,0xc2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x02,0x00,0x40,0x10,
+0x02,0x00,0xa2,0x24,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x78,0x1b,0x44,0x25,
+0xd4,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x65,0x00,0x7e,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x21,0x28,0x60,0x00,0x78,0x1b,0x43,0x25,0xe4,0x02,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x73,0x00,0x40,0x14,0x3a,0x00,0xa2,0x2c,
+0x32,0x00,0x05,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,
+0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3e,0x1a,0x00,0x08,
+0x00,0x00,0x00,0x00,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0xb0,0xff,0x40,0x14,
+0xff,0xff,0x02,0x24,0x50,0x1a,0x00,0x08,0xea,0x02,0xa2,0xa0,0x02,0x00,0xa4,0x90,
+0xd4,0x02,0xa2,0xa0,0x1c,0x00,0x03,0x24,0x06,0x00,0x02,0x24,0x57,0x00,0x82,0x10,
+0xd5,0x02,0xa3,0xa0,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x8f,0xff,0x60,0x10,0x78,0x1b,0x44,0x25,
+0x80,0x11,0x83,0x8c,0xff,0xff,0x02,0x34,0x8b,0xff,0x62,0x10,0x00,0x00,0x00,0x00,
+0xe4,0x02,0x83,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x62,0x2c,0x5c,0x00,0x40,0x14,
+0x90,0x01,0x62,0x2c,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,
+0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,
+0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,0xd6,0x02,0x82,0xa0,0x78,0x1b,0x44,0x25,
+0x80,0x11,0x82,0x8c,0xd6,0x02,0x83,0x90,0xd2,0x02,0x85,0x90,0x02,0x11,0x02,0x00,
+0x7f,0x00,0x42,0x30,0x0a,0x00,0x47,0x24,0x23,0x18,0xe3,0x00,0x00,0x3e,0x03,0x00,
+0x03,0x3e,0x07,0x00,0xff,0x00,0xa2,0x30,0x2a,0x10,0x47,0x00,0x3e,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x00,0x3e,0x05,0x00,0x03,0x3e,0x07,0x00,0x78,0x1b,0x43,0x25,
+0xe4,0x02,0x62,0x8c,0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x32,0x00,0x40,0x14,
+0x3a,0x00,0xe2,0x28,0x32,0x00,0xe2,0x28,0x2f,0x00,0x40,0x10,0x3a,0x00,0xe2,0x28,
+0x32,0x00,0x07,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0xff,0x00,0xe4,0x30,
+0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,
+0x58,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x3e,0x1a,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0xff,0x40,0x10,0x48,0x00,0x03,0x24,
+0x86,0x1a,0x00,0x08,0x44,0x00,0x03,0x24,0xd5,0x02,0x83,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0xa3,0x00,0x7e,0x1a,0x00,0x08,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c,
+0x00,0x08,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x27,0x18,0x03,0x00,
+0x01,0x00,0x63,0x30,0xa4,0xff,0x60,0x10,0x25,0xb0,0x02,0x3c,0x36,0x00,0x02,0x24,
+0xa9,0x1a,0x00,0x08,0xd2,0x02,0xa2,0xa0,0xd3,0xff,0x40,0x10,0x48,0x00,0x03,0x24,
+0xde,0x1a,0x00,0x08,0x44,0x00,0x03,0x24,0xd3,0x02,0x83,0x80,0x00,0x00,0x00,0x00,
+0xff,0x00,0x62,0x30,0x2a,0x10,0xe2,0x00,0xd3,0x1a,0x00,0x08,0x0b,0x38,0x62,0x00,
+0xae,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00,
+0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28,
+0x03,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xc2,0x1a,0x00,0x08,0x0c,0x00,0x02,0x24,
+0xc2,0x1a,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,
+0x25,0xb0,0x14,0x3c,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,
+0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x86,0x36,0x00,0x00,0xc3,0x90,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x51,0x24,0x2a,0xb0,0x10,0x3c,0xa0,0xff,0x02,0x24,
+0x25,0x18,0x62,0x00,0x34,0x00,0x05,0x36,0xfe,0xff,0x02,0x24,0xbc,0x02,0x32,0x92,
+0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,0x39,0x15,0x00,0x0c,
+0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x8d,0x00,0x60,0x12,0x00,0x40,0x02,0x3c,
+0x08,0x00,0x63,0x8e,0xb0,0x03,0x82,0x36,0x25,0xb0,0x1e,0x3c,0x21,0x20,0x60,0x02,
+0x00,0x00,0x43,0xac,0x02,0x45,0x00,0x0c,0x21,0xb8,0x20,0x02,0x42,0x00,0xd5,0x37,
+0x03,0x0c,0xd1,0x37,0x17,0x0e,0xd6,0x37,0x04,0x00,0x14,0x24,0x2a,0xb0,0x03,0x3c,
+0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,
+0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0xd4,0xb2,0x84,0x24,
+0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
+0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0x65,0x8e,
+0x20,0x10,0x06,0x3c,0x01,0x00,0x04,0x24,0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa4,0xaf,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x02,0x80,0x02,0x3c,0xd8,0xb2,0x42,0x24,0x00,0x00,0x45,0x8c,0x01,0x00,0x03,0x24,
+0x21,0x20,0x00,0x00,0x00,0x00,0xa3,0xa0,0xff,0xff,0x03,0x24,0x00,0x00,0xa3,0xa2,
+0x00,0x00,0x22,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,
+0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x02,0x00,0x02,0x24,0x02,0x80,0x04,0x3c,
+0x00,0x00,0xa2,0xa0,0x78,0x1b,0x83,0x24,0xc1,0x02,0x62,0x90,0x00,0x00,0xc4,0x92,
+0x21,0x28,0x00,0x00,0x00,0x00,0xc2,0xa2,0xff,0x00,0x90,0x30,0x01,0x00,0xa2,0x24,
+0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,
+0xef,0xff,0x02,0x24,0x64,0x00,0x04,0x24,0x00,0x00,0xa2,0xa2,0xcb,0x12,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xbf,0x00,0x42,0x30,
+0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0xcb,0x12,0x00,0x0c,0x84,0x03,0x04,0x24,
+0xf4,0x08,0xc2,0x37,0x00,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0xdf,0x07,0x84,0x34,
+0x00,0x00,0xd0,0xa2,0x21,0x10,0x00,0x00,0x24,0x28,0x64,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x00,0x00,0xa0,0xa2,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,
+0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0xbe,0x02,0xe2,0x92,
+0x1f,0x00,0xa3,0x30,0x2b,0x10,0x62,0x00,0x0a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0xbf,0x02,0xe2,0x92,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0x05,0x00,0x40,0x10,
+0x02,0x80,0x02,0x3c,0x01,0x00,0x02,0x3c,0x25,0x10,0x62,0x00,0x21,0x90,0x42,0x02,
+0x02,0x80,0x02,0x3c,0x56,0x43,0x43,0x90,0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10,
+0x92,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26,
+0xcb,0x12,0x00,0x0c,0xf4,0x01,0x04,0x24,0x89,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c,
+0x04,0x00,0x60,0x12,0x25,0xb0,0x02,0x3c,0x56,0x15,0x00,0x0c,0x21,0x20,0x60,0x02,
+0x25,0xb0,0x02,0x3c,0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02,
+0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
+0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
+0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xbe,0x02,0x62,0x90,0xc0,0x07,0xa3,0x30,
+0x82,0x19,0x03,0x00,0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,
+0x78,0x1b,0x84,0x24,0xbf,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,
+0xda,0xff,0x40,0x10,0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,
+0xbf,0x1b,0x00,0x08,0x21,0x90,0x42,0x02,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,
+0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,
+0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0xb8,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,0xff,0xff,0x05,0x36,
+0x56,0x30,0x06,0x24,0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x78,0x1b,0x51,0x26,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,0x04,0x00,0x02,0x24,
+0x20,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x18,0x03,0x25,0x8e,0x25,0xb0,0x10,0x3c,
+0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,
+0x04,0x0e,0x04,0x36,0x1c,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x08,0x0e,0x04,0x36,
+0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,
+0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,
+0x18,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36,
+0x78,0x1b,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x04,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x08,0x03,0x62,0xa0,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0x18,0x03,0x25,0x8e,
+0x00,0x00,0x00,0x00,0xde,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,0x19,0x1c,0x00,0x08,
+0x78,0x1b,0x43,0x26,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,
+0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,
+0x18,0x00,0xb2,0xaf,0xb8,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,0xcb,0x12,0x00,0x0c,
+0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0xb8,0x44,0x00,0x0c,
+0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x78,0x1b,0x02,0x26,0x08,0x03,0x46,0x90,0x25,0xb0,0x11,0x3c,0x10,0x10,0x12,0x3c,
+0x01,0x00,0x03,0x24,0x00,0x0e,0x24,0x36,0x1e,0x00,0xc3,0x10,0x10,0x10,0x45,0x36,
+0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,
+0x10,0x10,0x45,0x36,0x08,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x05,0x24,
+0x10,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x14,0x0e,0x24,0x36,
+0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x18,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,
+0x10,0x10,0x45,0x36,0x1c,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,
+0x78,0x1b,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x08,0x03,0x62,0xa0,0x00,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xe0,0xff,0xc5,0x14,
+0x78,0x1b,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
+0x08,0x03,0x62,0xa0,0xd8,0xff,0xbd,0x27,0x1c,0x00,0xb3,0xaf,0x02,0x80,0x13,0x3c,
+0x14,0x00,0xb1,0xaf,0x78,0x1b,0x71,0x26,0x10,0x03,0x26,0x8e,0x10,0x00,0xb0,0xaf,
+0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0x15,0x00,0x04,0x24,0x20,0x00,0xbf,0xaf,
+0xb8,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x14,0x03,0x26,0x8e,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x22,0x92,0x25,0xb0,0x12,0x3c,
+0x08,0x00,0x40,0x14,0x08,0x0e,0x44,0x36,0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34,
+0x00,0x00,0x45,0x8c,0xf0,0x02,0x23,0x8e,0x00,0x00,0x00,0x00,0x17,0x00,0xa3,0x10,
+0x78,0x1b,0x62,0x26,0xec,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xf0,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x44,0x36,0xf4,0x02,0x25,0x8e,
+0xb1,0x5a,0x00,0x0c,0x04,0x0e,0x44,0x36,0xf8,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,
+0x10,0x0e,0x44,0x36,0xfc,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x44,0x36,
+0x00,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x18,0x0e,0x44,0x36,0x04,0x03,0x25,0x8e,
+0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x44,0x36,0x78,0x1b,0x62,0x26,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x28,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x40,0xa0,0xe0,0xff,0xbd,0x27,
+0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,0x14,0x00,0xb1,0xaf,0x78,0x1b,0x51,0x26,
+0x10,0x03,0x26,0x8e,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,
+0x1c,0x00,0xbf,0xaf,0xb8,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x14,0x03,0x26,0x8e,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,
+0x1a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,
+0x03,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0xf0,0x02,0x25,0x8e,
+0x25,0xb0,0x10,0x3c,0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0xf4,0x02,0x25,0x8e,
+0xb1,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0xf8,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,
+0x10,0x0e,0x04,0x36,0xfc,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36,
+0x00,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36,0x04,0x03,0x25,0x8e,
+0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x0c,0x03,0x24,0x8e,0xec,0x02,0x22,0x8e,
+0x00,0x00,0x00,0x00,0x21,0x28,0x44,0x00,0x00,0xff,0xa3,0x30,0xff,0xff,0x02,0x3c,
+0xff,0x00,0x42,0x34,0x01,0x3f,0x63,0x2c,0x24,0x10,0xa2,0x00,0x0c,0x00,0x60,0x10,
+0x08,0x0e,0x04,0x36,0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x78,0x1b,0x43,0x26,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,
+0xe1,0x1c,0x00,0x08,0x00,0x3f,0x45,0x34,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,
+0xf0,0x02,0x25,0x8e,0x00,0x00,0x00,0x00,0xd2,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,
+0xe4,0x1c,0x00,0x08,0x78,0x1b,0x43,0x26,0xd8,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,
+0x02,0x80,0x12,0x3c,0x20,0x00,0xb4,0xaf,0x24,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x78,0x1b,0x44,0x26,0x80,0x11,0x82,0x8c,
+0x78,0x1b,0x43,0x8e,0x08,0x03,0x93,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x54,0x30,
+0xcc,0x00,0x63,0x30,0x40,0x00,0x02,0x24,0x68,0x00,0x62,0x10,0x01,0x00,0x02,0x24,
+0x25,0xb0,0x08,0x3c,0x4c,0x00,0x03,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x30,0x07,0x00,0x40,0x10,0x78,0x1b,0x45,0x26,0x78,0x1b,0x42,0x92,
+0x00,0x00,0x00,0x00,0x82,0x11,0x02,0x00,0x2f,0x00,0x40,0x10,0x00,0x0e,0x05,0x35,
+0x78,0x1b,0x45,0x26,0x08,0x03,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
+0x0f,0x00,0x40,0x14,0x78,0x1b,0x42,0x26,0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,
+0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,0x7b,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,
+0x4a,0x00,0x03,0x24,0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x45,0x00,0x02,0x24,
+0x43,0x00,0x03,0x24,0x21,0x03,0xa2,0xa0,0x22,0x03,0xa3,0xa0,0x78,0x1b,0x42,0x26,
+0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,
+0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x78,0x1b,0x45,0x8e,0x44,0x00,0x02,0x24,0xcc,0x00,0xa3,0x30,0x3e,0x00,0x62,0x10,
+0x78,0x1b,0x44,0x26,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,
+0x5e,0x00,0x40,0x10,0x10,0x0e,0x07,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0e,0x02,0x35,0x04,0x0e,0x03,0x35,
+0x00,0x00,0x44,0x8c,0x00,0x00,0xa5,0x8c,0x00,0x00,0x66,0x8c,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x49,0x24,0xec,0x02,0x24,0xad,0xf0,0x02,0x25,0xad,0xf4,0x02,0x26,0xad,
+0x14,0x0e,0x04,0x35,0x02,0x80,0x02,0x3c,0x18,0x0e,0x05,0x35,0x00,0x00,0xe7,0x8c,
+0x1c,0x0e,0x06,0x35,0x00,0x00,0x83,0x8c,0x56,0x43,0x4a,0x90,0x00,0x00,0xa2,0x8c,
+0x00,0x00,0xc4,0x8c,0xf8,0x02,0x27,0xad,0x00,0x03,0x22,0xad,0x22,0x00,0x02,0x24,
+0xfc,0x02,0x23,0xad,0x5a,0x00,0x42,0x11,0x04,0x03,0x24,0xad,0x92,0x00,0x02,0x24,
+0x58,0x00,0x42,0x11,0x0d,0x08,0x02,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x78,0x1b,0x42,0x8e,0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00,
+0x40,0x00,0x42,0x34,0x14,0x1d,0x00,0x08,0x78,0x1b,0x42,0xae,0x3a,0x00,0x62,0x12,
+0x04,0x00,0x02,0x24,0x38,0x00,0x62,0x12,0x78,0x1b,0x43,0x26,0xff,0xff,0x02,0x24,
+0x08,0x1d,0x00,0x08,0x08,0x03,0x62,0xa0,0x80,0x11,0x83,0x8c,0xff,0xff,0x02,0x34,
+0xc0,0xff,0x62,0x10,0x02,0x11,0x05,0x00,0x03,0x00,0x45,0x30,0x01,0x00,0x03,0x24,
+0xbc,0xff,0xa3,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0xb6,0xff,0x60,0x10,0x03,0x00,0x02,0x24,
+0x65,0x00,0x62,0x12,0x04,0x00,0x62,0x2a,0x47,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x6a,0x00,0x60,0x12,0x00,0x00,0x00,0x00,0xae,0xff,0x65,0x16,0x00,0x00,0x00,0x00,
+0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x56,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x23,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,
+0x48,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x6d,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24,
+0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24,
+0x21,0x03,0xa2,0xa0,0x27,0x1d,0x00,0x08,0x22,0x03,0xa3,0xa0,0x00,0x00,0xe3,0x8c,
+0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x9f,0xff,0x62,0x14,0x00,0x00,0x00,0x00,
+0x15,0x1d,0x00,0x08,0x78,0x1b,0x45,0x26,0x0f,0x00,0x10,0x3c,0x01,0x00,0x11,0x3c,
+0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0xb8,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x26,0x36,
+0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x78,0x1b,0x43,0x26,0xff,0xff,0x02,0x24,0x08,0x1d,0x00,0x08,0x08,0x03,0x62,0xa0,
+0x0d,0x08,0x02,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30,
+0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0xa3,0xff,0x40,0x14,0x01,0x00,0x65,0x24,
+0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,0x25,0x10,0x44,0x00,
+0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,0x1c,0x03,0x23,0xad,
+0x66,0x1d,0x00,0x08,0x18,0x03,0x22,0xad,0x04,0x00,0x02,0x24,0x11,0x00,0x62,0x12,
+0xff,0x00,0x02,0x24,0x67,0xff,0x62,0x16,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0a,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x29,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08,
+0x00,0x00,0x00,0x00,0x21,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,
+0xf8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xea,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x03,0x82,0x90,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x82,0x02,0xa8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xab,0x1c,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90,
+0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0xe6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
+0x25,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x9a,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0xab,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x78,0x1b,0x05,0x25,0x80,0x11,0xa4,0x8c,
+0xea,0x02,0xa3,0x90,0x02,0x11,0x04,0x00,0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,
+0x25,0xb0,0x07,0x3c,0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x20,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x30,0x19,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10,
+0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,
+0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,
+0x20,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10,
+0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10,
+0x23,0x00,0xc2,0x2c,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,
+0x3f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,
+0x44,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,
+0x00,0x00,0x00,0x00,0xe7,0xff,0x44,0x10,0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34,
+0xd7,0x02,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,
+0xc0,0xff,0x44,0x10,0x10,0x00,0x02,0x24,0x87,0x0c,0xe3,0x34,0xd7,0x02,0xa4,0xa0,
+0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0xc7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x04,0x25,
+0xd7,0x02,0x82,0x90,0x02,0x00,0x03,0x24,0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0xd7,0x02,0x83,0xa0,0x00,0x00,0x40,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0xb4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90,
+0x02,0x00,0x03,0x24,0xaf,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
+0xd7,0x02,0x83,0xa0,0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,0x02,0x00,0x82,0x94,0x04,0x00,0x84,0x24,
+0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x40,0x10,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0xb8,0x44,0x43,0xa0,
+0x14,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x6c,0x44,0x44,0xac,
+0xb7,0x44,0x60,0xa0,0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x9e,0x44,0x40,0xa0,0xff,0x00,0x85,0x30,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb0,0x44,0x60,0xa0,0x08,0x00,0xa4,0x2c,
+0xb2,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xba,0x44,0x60,0xa0,
+0x98,0x44,0x45,0xa0,0x11,0x00,0x80,0x10,0x02,0x80,0x03,0x3c,0x80,0x10,0x05,0x00,
+0xdc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,
+0x08,0x0b,0xa4,0x8c,0x00,0x70,0x02,0x3c,0x08,0x00,0x42,0x34,0x25,0x20,0x82,0x00,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x0b,0xa4,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa4,0x8c,
+0x00,0x70,0x02,0x3c,0x08,0x00,0x42,0x34,0x27,0x10,0x02,0x00,0x24,0x20,0x82,0x00,
+0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,
+0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa2,0x8c,0x14,0x0b,0xa6,0x94,
+0x00,0x70,0x04,0x3c,0x41,0xb0,0x03,0x3c,0x08,0x00,0x42,0x34,0x27,0x20,0x04,0x00,
+0x00,0x00,0x62,0xac,0x24,0x20,0x44,0x00,0x10,0x00,0xc6,0x34,0x08,0x00,0x67,0x34,
+0x02,0x80,0x08,0x3c,0x01,0x00,0x02,0x24,0x00,0x00,0x64,0xac,0x00,0x00,0xe6,0xa4,
+0xb4,0x44,0x02,0xa1,0xb4,0x44,0x03,0x91,0x02,0x80,0x02,0x3c,0x14,0x0b,0xa6,0xa4,
+0xb5,0x44,0x43,0xa0,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0x02,0x80,0x05,0x3c,
+0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa3,0x8c,0x14,0x0b,0xa6,0x94,0x00,0x70,0x02,0x3c,
+0x41,0xb0,0x04,0x3c,0x08,0x00,0x63,0x34,0x27,0x10,0x02,0x00,0x24,0x10,0x62,0x00,
+0x10,0x00,0xc6,0x34,0x08,0x00,0x87,0x34,0x14,0x0b,0xa6,0xa4,0x00,0x00,0x83,0xac,
+0x00,0x00,0x82,0xac,0x00,0x00,0xe6,0xa4,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,
+0x25,0xb0,0x03,0x3c,0xbe,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x42,0x2c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x15,0x00,0x40,0x10,0x78,0x41,0x64,0x24,
+0x78,0x41,0x62,0x8c,0x00,0x00,0x00,0x00,0x11,0x00,0x44,0x14,0x02,0x80,0x02,0x3c,
+0xb8,0x44,0x43,0x90,0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x0c,0x00,0x62,0x10,
+0x01,0x00,0x04,0x24,0x02,0x80,0x03,0x3c,0x99,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x05,0x00,0x40,0x10,0x21,0x10,0x80,0x00,
+0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0x10,0x00,0xbf,0x8f,0x21,0x20,0x00,0x00,0x21,0x10,0x80,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x25,0x00,0x40,0x10,0x78,0x41,0x64,0x24,
+0x78,0x41,0x62,0x8c,0x00,0x00,0x00,0x00,0x21,0x00,0x44,0x14,0x01,0x00,0x05,0x24,
+0x02,0x80,0x03,0x3c,0xb0,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,
+0x1b,0x00,0x45,0x10,0x02,0x80,0x03,0x3c,0x99,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x03,0x00,0x42,0x28,0x15,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0x10,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,
+0x0b,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0xb8,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x42,0x30,0x06,0x00,0x45,0x10,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,
+0xb9,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,
+0x21,0x20,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x10,0x80,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0xff,0x00,0x84,0x30,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x29,0x00,0x80,0x10,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x03,0x3c,
+0x04,0x0c,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x34,
+0x04,0x0c,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x04,0x0d,0x62,0x90,
+0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x34,0x04,0x0d,0x62,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x25,0xb0,0x10,0x3c,0x70,0x0e,0x05,0x8e,0x80,0x01,0x11,0x3c,
+0x70,0x0e,0x04,0x24,0x34,0x5b,0x00,0x0c,0x25,0x28,0xb1,0x00,0x8c,0x0e,0x05,0x8e,
+0x8c,0x0e,0x04,0x24,0x34,0x5b,0x00,0x0c,0x25,0x28,0xb1,0x00,0x03,0x00,0x05,0x3c,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x59,0x01,0xa5,0x34,
+0x44,0x08,0x04,0x24,0x34,0x5b,0x00,0x08,0x20,0x00,0xbd,0x27,0x44,0x08,0x04,0x24,
+0x34,0x5b,0x00,0x0c,0x21,0x28,0x00,0x00,0x25,0xb0,0x03,0x3c,0x04,0x0c,0x62,0x90,
+0x21,0x20,0x00,0x00,0xfd,0x00,0x42,0x30,0x04,0x0c,0x62,0xa0,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,
+0x25,0xb0,0x03,0x3c,0x04,0x0d,0x62,0x90,0x21,0x20,0x00,0x00,0xfd,0x00,0x42,0x30,
+0x04,0x0d,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x11,0x3c,0x70,0x0e,0x25,0x8e,
+0x7f,0xfe,0x10,0x3c,0xff,0xff,0x10,0x36,0x24,0x28,0xb0,0x00,0x34,0x5b,0x00,0x0c,
+0x70,0x0e,0x04,0x24,0x8c,0x0e,0x25,0x8e,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x24,0x28,0xb0,0x00,0x8c,0x0e,0x04,0x24,0x10,0x00,0xb0,0x8f,0x34,0x5b,0x00,0x08,
+0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x64,0x34,
+0x00,0x00,0x82,0xa4,0x42,0x00,0x65,0x34,0x03,0x00,0x02,0x24,0x00,0x00,0xa0,0xa0,
+0x03,0x08,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0x98,0x44,0x43,0x90,0x00,0x00,0x00,0x00,
+0x07,0x00,0x60,0x10,0x25,0xb0,0x10,0x3c,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,
+0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x2e,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x21,0x00,0x06,0x36,0x00,0x00,0xc2,0x90,0x18,0x00,0x03,0x36,0x42,0x00,0x05,0x36,
+0x01,0x00,0x42,0x34,0x00,0x00,0xc2,0xa0,0x40,0x00,0x11,0x36,0x00,0x00,0x60,0xa0,
+0xff,0xff,0x02,0x24,0xfc,0x57,0x03,0x24,0x00,0x00,0xa2,0xa0,0x64,0x00,0x04,0x24,
+0x00,0x00,0x23,0xa6,0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0xfc,0x77,0x02,0x24,
+0x00,0x00,0x22,0xa6,0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0x03,0x08,0x00,0xa2,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x0a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,
+0x25,0xb0,0x10,0x3c,0x40,0x00,0x10,0x36,0xfc,0x37,0x02,0x24,0x00,0x00,0x02,0xa6,
+0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0xfc,0x77,0x02,0x24,0x00,0x00,0x02,0xa6,
+0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0xfc,0x57,0x02,0x24,0x00,0x00,0x02,0xa6,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x55,0x1f,0x00,0x0c,0x21,0x20,0x00,0x00,0xc8,0x1f,0x00,0x08,
+0x25,0xb0,0x10,0x3c,0xd8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf,
+0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0xff,0x00,0x90,0x30,
+0x00,0x60,0x13,0x40,0x01,0x00,0x61,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x02,0x80,0x11,0x3c,0x9a,0x44,0x22,0x92,0x0f,0x00,0x12,0x32,0x0f,0x00,0x42,0x30,
+0x0d,0x00,0x52,0x10,0x04,0x00,0x02,0x32,0x13,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x9a,0x44,0x22,0x92,0x0c,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x2f,0x00,0x43,0x10,
+0x08,0x00,0x02,0x32,0x9a,0x44,0x22,0x92,0x04,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,
+0x5a,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x60,0x93,0x40,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x9a,0x44,0x22,0x92,0x00,0x00,0x00,0x00,
+0x04,0x00,0x42,0x30,0x33,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,
+0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0x32,0x00,0x40,0x10,0x08,0x00,0x02,0x32,
+0x30,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x30,0x3d,0x00,0x40,0x14,0x01,0x00,0x04,0x24,0x9a,0x44,0x22,0x92,
+0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x9a,0x44,0x22,0xa2,0x9a,0x44,0x23,0x92,
+0x00,0x00,0x00,0x00,0x25,0x18,0x43,0x02,0x9a,0x44,0x23,0xa2,0x00,0x60,0x93,0x40,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xd1,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x05,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0xd2,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,
+0x9a,0x44,0x22,0xa2,0x02,0x80,0x03,0x3c,0x9a,0x44,0x22,0x92,0x60,0x26,0x64,0x90,
+0x04,0x00,0x42,0x34,0x01,0x00,0x84,0x30,0x9a,0x44,0x22,0xa2,0xc1,0xff,0x80,0x10,
+0x00,0x00,0x00,0x00,0x0e,0x46,0x00,0x0c,0x01,0x00,0x04,0x24,0x11,0x20,0x00,0x08,
+0x00,0x00,0x00,0x00,0xa9,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0x23,0x20,0x00,0x08,
+0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,
+0xd2,0xff,0x40,0x14,0x08,0x00,0x02,0x32,0xd0,0xff,0x40,0x10,0x02,0x80,0x02,0x3c,
+0xb1,0x44,0x43,0x90,0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x1b,0x00,0x62,0x10,
+0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0xc6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x00,0x0e,0x46,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x2f,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0x1f,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xa4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xb9,0x1f,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,
+0x9a,0x44,0x22,0xa2,0x9a,0x44,0x23,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x63,0x34,
+0x9a,0x44,0x23,0xa2,0x37,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x98,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0xac,0xff,0x60,0x14,0x02,0x80,0x03,0x3c,
+0x65,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x98,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0x0c,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0xb1,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0x0a,0x00,0x60,0x14,0x0c,0x00,0x04,0x24,0x02,0x80,0x03,0x3c,
+0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,
+0x03,0x00,0x40,0x14,0x04,0x00,0x04,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xf9,0x1f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xe8,0xff,0xbd,0x27,0x68,0x82,0x63,0x24,0x18,0x03,0x42,0x34,0x14,0x00,0xbf,0xaf,
+0x10,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x17,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x02,0x3c,0x9a,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30,
+0x04,0x00,0x63,0x28,0x17,0x00,0x60,0x14,0x04,0x00,0x04,0x24,0x02,0x80,0x03,0x3c,
+0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0c,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb9,0x44,0x62,0xa0,
+0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xb9,0x44,0x40,0xa0,0x00,0x60,0x90,0x40,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0xf9,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x20,0x00,0x08,
+0x02,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xe8,0xff,0xbd,0x27,
+0x34,0x83,0x42,0x24,0x18,0x03,0x63,0x34,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x04,0x3c,0xb7,0x44,0x82,0x90,0x00,0x00,0x00,0x00,
+0x0a,0x00,0x40,0x10,0x14,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x6c,0x44,0x43,0xac,
+0xb7,0x44,0x80,0xa0,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
+0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0xba,0x44,0x44,0xa0,0xb8,0x44,0x60,0xa0,
+0x02,0x80,0x02,0x3c,0x99,0x44,0x44,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,
+0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x42,0x11,0x05,0x00,0x0f,0x00,0x46,0x30,
+0xe8,0xff,0xbd,0x27,0x09,0x00,0xc3,0x28,0x14,0x00,0xbf,0xaf,0x15,0x00,0x60,0x10,
+0x10,0x00,0xb0,0xaf,0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x15,0x00,0x40,0x10,
+0x00,0xc0,0x02,0x3c,0x24,0x10,0xa2,0x00,0x47,0x00,0x40,0x14,0xc2,0x15,0x04,0x00,
+0x01,0x00,0x42,0x30,0x54,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x3c,0xaf,0x63,0x24,0x21,0x18,0xc3,0x00,0x02,0x80,0x04,0x3c,0xb3,0x44,0x85,0x90,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0x4a,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x24,0x10,0xa2,0x00,0x1f,0x00,0x40,0x14,0xc2,0x15,0x04,0x00,
+0x01,0x00,0x42,0x30,0x0b,0x00,0x40,0x10,0x02,0x80,0x04,0x3c,0x02,0x80,0x03,0x3c,
+0x3c,0xaf,0x63,0x24,0x21,0x18,0xc3,0x00,0x02,0x80,0x04,0x3c,0xb3,0x44,0x85,0x90,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0x3b,0x00,0x40,0x14,
+0x02,0x80,0x04,0x3c,0xb2,0x44,0x82,0x90,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,
+0xb2,0x44,0x82,0xa0,0xb2,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30,
+0xe4,0xff,0x40,0x14,0x02,0x80,0x02,0x3c,0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,
+0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,
+0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xb2,0x44,0x82,0x90,
+0xfd,0xff,0x03,0x24,0x14,0x00,0xbf,0x8f,0x24,0x10,0x43,0x00,0x02,0x80,0x03,0x3c,
+0xb2,0x44,0x82,0xa0,0xb6,0x44,0x60,0xa0,0x42,0xb0,0x04,0x3c,0x00,0x00,0x82,0x90,
+0x10,0x00,0xb0,0x8f,0xef,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x03,0x00,0x85,0x34,
+0x40,0x00,0x03,0x24,0x18,0x00,0xbd,0x27,0x00,0x00,0x82,0xa0,0x00,0x00,0xa3,0xa0,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x07,0x3c,0x00,0x00,0xe3,0x90,
+0xef,0xff,0x02,0x24,0x03,0x00,0xf0,0x34,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,
+0x00,0x00,0xe3,0xa0,0x02,0x00,0x04,0x24,0x00,0x00,0x02,0xa2,0x21,0x28,0x00,0x00,
+0x71,0x14,0x00,0x0c,0x00,0x03,0x06,0x24,0x44,0x00,0x02,0x24,0x00,0x00,0x02,0xa2,
+0x11,0x21,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x01,0x00,0x04,0x24,0x1c,0x46,0x00,0x08,0x18,0x00,0xbd,0x27,0xb2,0x44,0x82,0x90,
+0x27,0x21,0x00,0x08,0xfb,0xff,0x03,0x24,0x82,0x26,0x05,0x00,0xe8,0xff,0xbd,0x27,
+0x00,0xc0,0x02,0x3c,0x01,0x00,0x84,0x30,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x0c,0x00,0x80,0x10,0x24,0x10,0xa2,0x00,0x42,0xb0,0x07,0x3c,0x03,0x00,0xf0,0x34,
+0x02,0x00,0x04,0x24,0x21,0x28,0x00,0x00,0x31,0x00,0x40,0x14,0x00,0x03,0x06,0x24,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x04,0x24,0x1c,0x46,0x00,0x08,
+0x18,0x00,0xbd,0x27,0x42,0xb0,0x04,0x3c,0x02,0x80,0x06,0x3c,0x0f,0x00,0x40,0x14,
+0x03,0x00,0x87,0x34,0x02,0x80,0x06,0x3c,0xb2,0x44,0xc3,0x90,0xfe,0xff,0x02,0x24,
+0x24,0x18,0x62,0x00,0xb2,0x44,0xc3,0xa0,0xb2,0x44,0xc2,0x90,0x00,0x00,0x00,0x00,
+0x07,0x00,0x42,0x30,0x16,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xb2,0x44,0xc3,0x90,
+0xfd,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x02,0x80,0x02,0x3c,0xb2,0x44,0xc3,0xa0,
+0xb6,0x44,0x40,0xa0,0x00,0x00,0x83,0x90,0xef,0xff,0x02,0x24,0x24,0x18,0x62,0x00,
+0x40,0x00,0x02,0x24,0x00,0x00,0x83,0xa0,0x00,0x00,0xe2,0xa0,0xb2,0x44,0xc2,0x90,
+0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30,0xec,0xff,0x40,0x14,0x02,0x80,0x02,0x3c,
+0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27,
+0x00,0x00,0xe3,0x90,0xef,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,
+0x00,0x00,0xe3,0xa0,0x00,0x00,0x02,0xa2,0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x44,0x00,0x02,0x24,0x00,0x00,0x02,0xa2,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0xff,0x00,0xa5,0x30,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x02,0x80,0x10,0x3c,
+0x03,0x00,0xa0,0x14,0xff,0x00,0x91,0x30,0x19,0x00,0x20,0x12,0x02,0x80,0x02,0x3c,
+0xb2,0x44,0x03,0x92,0xfb,0xff,0x02,0x24,0x01,0x00,0x04,0x24,0x24,0x18,0x62,0x00,
+0xb2,0x44,0x03,0xa2,0x2e,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0xb2,0x44,0x02,0x92,
+0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0xb2,0x44,0x02,0xa2,0x02,0x00,0x04,0x24,
+0x21,0x28,0x00,0x00,0x13,0x00,0x20,0x16,0x00,0x03,0x06,0x24,0xb2,0x44,0x02,0x92,
+0xfd,0xff,0x03,0x24,0x18,0x00,0xbf,0x8f,0x24,0x10,0x43,0x00,0xb2,0x44,0x02,0xa2,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08,
+0x20,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x01,0x00,0x07,0x24,0xb0,0x44,0x47,0xa0,
+0xb2,0x44,0x03,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x63,0x34,0xb2,0x44,0x03,0xa2,
+0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x42,0xb0,0x02,0x3c,0x44,0x00,0x03,0x24,0x03,0x00,0x42,0x34,
+0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x02,0x80,0x03,0x3c,0xb0,0x44,0x62,0xa0,0xb2,0x44,0x05,0x92,0x00,0x00,0x00,0x00,
+0x01,0x00,0xa5,0x34,0xb2,0x44,0x05,0xa2,0x1c,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xc4,0x21,0x00,0x08,0x02,0x00,0x04,0x24,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0xe8,0xff,0xbd,0x27,0xd8,0x87,0x42,0x24,0x18,0x03,0x63,0x34,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x62,0xac,0x02,0x80,0x10,0x3c,0x99,0x44,0x02,0x92,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x03,0x00,0x42,0x28,0x05,0x00,0x40,0x10,0x14,0x00,0xbf,0xaf,
+0x25,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x99,0x44,0x04,0x92,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x02,0x80,0x04,0x3c,
+0x78,0x1b,0x84,0x24,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x02,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,
+0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,
+0x14,0x0b,0x83,0xa4,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf,
+0x02,0x80,0x10,0x3c,0x08,0x14,0x04,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x1e,0x22,0x00,0x08,0x08,0x14,0x04,0x26,
+0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x82,0x5b,0x00,0x0c,0x21,0x38,0x00,0x00,
+0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0xff,0xff,0x8d,0x30,0x00,0x60,0x0f,0x40,0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c,0x78,0x1b,0xce,0x24,0x82,0x0b,0xc2,0x91,
+0x00,0x00,0x00,0x00,0x1d,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34,
+0x80,0xff,0x02,0x24,0x00,0x00,0x82,0xa0,0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34,
+0xd6,0x01,0x66,0x34,0xda,0x01,0x67,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94,
+0x00,0x00,0xc9,0x94,0x00,0x00,0xeb,0x94,0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95,
+0xb0,0xfe,0xa2,0x25,0xff,0xff,0x4d,0x30,0x80,0x0b,0xc4,0xa5,0x00,0x00,0xa0,0xa4,
+0x78,0x0b,0xc8,0xa5,0x00,0x00,0xc0,0xa4,0x7a,0x0b,0xc9,0xa5,0x00,0x00,0xe0,0xa4,
+0x7c,0x0b,0xcb,0xa5,0x00,0x00,0x60,0xa4,0x00,0x00,0x4d,0xa5,0x7e,0x0b,0xcc,0xa5,
+0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c,
+0x0a,0x00,0x45,0x34,0x63,0x00,0x03,0x24,0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90,
+0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x10,0x78,0x1b,0xc2,0x24,0x64,0x00,0x02,0x24,
+0xff,0xff,0x42,0x24,0xff,0xff,0x42,0x30,0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24,
+0xff,0xff,0x62,0x24,0xff,0xff,0x43,0x30,0xf4,0xff,0x64,0x14,0x78,0x1b,0xc2,0x24,
+0x80,0x0b,0x48,0x94,0x7e,0x0b,0x47,0x94,0x78,0x0b,0x49,0x94,0x7a,0x0b,0x4a,0x94,
+0x7c,0x0b,0x4b,0x94,0x25,0xb0,0x03,0x3c,0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34,
+0xd2,0x01,0x64,0x34,0xd6,0x01,0x65,0x34,0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34,
+0x00,0x00,0x48,0xa4,0x00,0x00,0x89,0xa4,0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4,
+0x00,0x00,0x67,0xa4,0x00,0x00,0x80,0xa1,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x08,0x00,0x83,0x34,0x00,0x00,0x62,0x94,
+0x00,0x00,0x00,0x00,0x00,0x14,0x02,0x00,0x03,0x14,0x02,0x00,0x1a,0x00,0x40,0x04,
+0x60,0x02,0x85,0x34,0x00,0x00,0xa3,0x90,0x05,0x00,0x02,0x24,0x00,0x03,0x8b,0x34,
+0xff,0x00,0x63,0x30,0x04,0x03,0x8c,0x34,0xbd,0x00,0x8a,0x34,0x03,0x00,0x86,0x34,
+0x40,0x00,0x85,0x34,0xfc,0x77,0x09,0x24,0x11,0x00,0x62,0x10,0x23,0x00,0x84,0x34,
+0x00,0x00,0xc2,0x90,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x00,0x00,0xc2,0xa0,
+0x22,0x00,0x02,0x24,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x82,0xa0,
+0xfc,0x37,0x02,0x24,0x00,0x00,0xa9,0xa4,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa9,0xa4,
+0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x42,0x91,0x00,0x00,0x00,0x00,
+0x08,0x00,0x42,0x34,0x00,0x00,0x42,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xd0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x2c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,
+0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x14,0x24,
+0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c,0x78,0x1b,0x66,0x26,0x04,0x00,0x42,0x34,
+0x00,0x00,0x47,0x8c,0x0c,0x0b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0x5e,0x43,0x64,0x90,
+0x08,0x0b,0xc8,0x8c,0x02,0x80,0x02,0x3c,0x80,0x43,0x49,0x90,0x25,0xb0,0x0a,0x3c,
+0x25,0x88,0xa7,0x00,0xb0,0x03,0x42,0x35,0x00,0x00,0x51,0xac,0x00,0x24,0x04,0x00,
+0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,
+0x00,0x00,0x71,0xac,0x00,0x00,0xa4,0xac,0x0a,0x03,0x22,0x11,0x0c,0x0b,0xd1,0xac,
+0x78,0x1b,0x64,0x26,0x08,0x0b,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00,
+0x01,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,0x78,0x1b,0x67,0x26,0x25,0xb0,0x0b,0x3c,
+0xb0,0x03,0x63,0x35,0x01,0x00,0x06,0x24,0x00,0x00,0x66,0xac,0x04,0x00,0x62,0x35,
+0x00,0x00,0x4a,0x8c,0x0c,0x0b,0x83,0x8c,0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01,
+0x01,0x00,0x63,0x38,0x18,0x01,0x40,0x10,0x0c,0x0b,0x83,0xac,0x78,0x1b,0x67,0x26,
+0x08,0x0b,0xe8,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x11,0x01,0x04,0x00,0x42,0x30,
+0x18,0x00,0x40,0x10,0x78,0x1b,0x70,0x26,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x64,0x34,
+0x04,0x00,0x02,0x24,0x00,0x00,0x82,0xac,0x0c,0x0b,0xe2,0x8c,0xfc,0x00,0x63,0x34,
+0xe4,0x0a,0xe5,0x94,0x8c,0x25,0xe4,0x8c,0x00,0x00,0x66,0x8c,0x04,0x00,0x42,0x38,
+0x21,0x50,0x85,0x00,0x0a,0x00,0xca,0x10,0x0c,0x0b,0xe2,0xac,0x02,0x80,0x05,0x3c,
+0x44,0x44,0xa2,0x8c,0xfb,0xff,0x04,0x24,0x24,0x20,0x04,0x01,0x00,0x10,0x42,0x34,
+0x41,0xb0,0x03,0x3c,0x44,0x44,0xa2,0xac,0x00,0x00,0x64,0xac,0x08,0x0b,0xe4,0xac,
+0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x20,0x51,0x00,
+0x08,0x00,0x83,0x30,0x06,0x00,0x60,0x10,0x10,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e,
+0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x10,0x00,0x82,0x30,
+0x06,0x00,0x40,0x10,0x20,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x10,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x20,0x00,0x82,0x30,0x06,0x00,0x40,0x10,
+0x40,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38,
+0x0c,0x0b,0x02,0xae,0x40,0x00,0x82,0x30,0x06,0x00,0x40,0x10,0x80,0x00,0x82,0x30,
+0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,
+0x80,0x00,0x82,0x30,0x06,0x00,0x40,0x10,0x00,0x01,0x82,0x30,0x0c,0x0b,0x02,0x8e,
+0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x00,0x01,0x82,0x30,
+0x06,0x00,0x40,0x10,0x00,0x02,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x00,0x01,0x42,0x38,0x0c,0x0b,0x02,0xae,0x00,0x02,0x82,0x30,0x06,0x00,0x40,0x10,
+0x00,0x04,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38,
+0x0c,0x0b,0x02,0xae,0x00,0x04,0x82,0x30,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x0c,0x0b,0x02,0xae,
+0x00,0x08,0x82,0x30,0x7a,0x02,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,
+0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00,0x00,0x10,0x42,0x30,
+0x50,0x02,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x03,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x71,0x00,0x00,0x20,0x42,0x30,0x42,0x02,0x40,0x14,
+0x00,0x00,0x00,0x00,0x24,0x10,0x71,0x00,0x00,0x80,0x42,0x30,0xf6,0x00,0x40,0x14,
+0x01,0x00,0x12,0x3c,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0x20,0x01,0x40,0x14,
+0x00,0x00,0x00,0x00,0x08,0x0b,0x02,0x8e,0x02,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,
+0x24,0x10,0x52,0x00,0x48,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,
+0x08,0x0b,0x02,0x8e,0x04,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,
+0x24,0x10,0x52,0x00,0x71,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,
+0x08,0x0b,0x02,0x8e,0x08,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,
+0x98,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,
+0x10,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,
+0xc1,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,
+0x20,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0xe8,0x01,0x40,0x14,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x40,0x00,0x12,0x3c,
+0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0x9a,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x68,0x26,0x08,0x0b,0x07,0x8d,0x00,0x04,0x05,0x3c,
+0x24,0x10,0xf1,0x00,0x24,0x10,0x45,0x00,0x1b,0x00,0x40,0x10,0x78,0x1b,0x66,0x26,
+0x2a,0xb0,0x02,0x3c,0x2c,0x00,0x42,0x34,0x00,0x00,0x4a,0x8c,0xff,0x00,0x02,0x24,
+0xff,0x00,0x43,0x31,0x58,0x02,0x62,0x10,0x02,0x80,0x06,0x3c,0x44,0x44,0xc4,0x8c,
+0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x80,0x84,0x34,0x27,0x28,0x05,0x00,
+0x00,0x00,0x44,0xac,0x24,0x28,0xe5,0x00,0x41,0xb0,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x00,0x00,0x65,0xac,0x44,0x44,0xc4,0xac,0x08,0x0b,0x05,0xad,0x9a,0x43,0x40,0xa4,
+0x78,0x1b,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x00,0x04,0x04,0x3c,0x26,0x18,0x64,0x00,
+0x0c,0x0b,0x43,0xac,0x78,0x1b,0x66,0x26,0x08,0x0b,0xc7,0x8c,0x00,0x08,0x04,0x3c,
+0x24,0x28,0xf1,0x00,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x08,0x3c,
+0x0c,0x0b,0xc3,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
+0x00,0x00,0x44,0xac,0x0c,0x0b,0xc3,0xac,0x80,0x00,0x08,0x3c,0x24,0x10,0xa8,0x00,
+0x21,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x0b,0xc3,0x8c,0x25,0xb0,0x09,0x3c,
+0xb0,0x03,0x2a,0x35,0x2a,0xb0,0x02,0x3c,0x00,0x00,0x43,0xad,0x36,0x00,0x42,0x34,
+0x00,0x00,0x43,0x90,0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,
+0xf0,0x07,0x63,0x30,0xbc,0x25,0xc5,0x8c,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x2a,0x02,0x65,0x10,0xc0,0x25,0xc3,0xac,0x02,0x80,0x05,0x3c,
+0x44,0x44,0xa3,0x8c,0x27,0x20,0x08,0x00,0x24,0x20,0xe4,0x00,0x00,0x08,0x63,0x34,
+0x41,0xb0,0x02,0x3c,0x00,0x00,0x43,0xad,0x00,0x00,0x44,0xac,0x44,0x44,0xa3,0xac,
+0x08,0x0b,0xc4,0xac,0x78,0x1b,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x80,0x00,0x04,0x3c,
+0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x78,0x1b,0x66,0x26,0x08,0x0b,0xc3,0x8c,
+0x00,0x01,0x04,0x3c,0x24,0x28,0x71,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,
+0x25,0xb0,0x02,0x3c,0x0c,0x0b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
+0x00,0x00,0x44,0xac,0x0c,0x0b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,
+0x08,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x0c,0x0b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,
+0xb0,0x03,0x63,0x34,0x26,0x10,0x44,0x00,0x0c,0x0b,0xc2,0xac,0x00,0x00,0x64,0xac,
+0x02,0x80,0x02,0x3c,0x52,0x43,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30,
+0xf1,0x01,0x62,0x10,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35,
+0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35,0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34,
+0x00,0x00,0x46,0xa4,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac,
+0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c,0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30,
+0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01,0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35,
+0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac,
+0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0,0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10,
+0x02,0x00,0x62,0x35,0x84,0xff,0x02,0x24,0x00,0x00,0x42,0xa1,0x02,0x00,0x62,0x35,
+0x00,0x00,0x43,0x94,0xff,0xbf,0x04,0x24,0x24,0x18,0x64,0x00,0x00,0x00,0x43,0xa4,
+0xd8,0x22,0x00,0x08,0x78,0x1b,0x67,0x26,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xc0,0x00,0x00,0x0c,0x07,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,
+0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0xb4,0x24,0x03,0xae,0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x70,0x24,0x0a,0xa2,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,
+0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x60,0x00,0x02,0x3c,
+0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x04,0x63,0x34,0x02,0x00,0x84,0x34,
+0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac,
+0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,
+0x79,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xc0,0x00,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,
+0xff,0x00,0x02,0x24,0x1e,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x54,0x24,0x0a,0xa2,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,
+0x44,0x44,0xe5,0x8c,0x54,0x44,0x06,0x91,0x08,0x0b,0x04,0x8e,0x01,0x00,0x09,0x3c,
+0x00,0x80,0x22,0x35,0x27,0x10,0x02,0x00,0x80,0xff,0x03,0x24,0x24,0x20,0x82,0x00,
+0x25,0x30,0xc3,0x00,0x80,0x00,0xa5,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xe5,0xac,
+0x54,0x44,0x06,0xa1,0x27,0xa0,0x09,0x00,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae,
+0x0c,0x0b,0x02,0x8e,0x01,0x00,0x12,0x3c,0x00,0x80,0x42,0x38,0x0c,0x0b,0x02,0xae,
+0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00,
+0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0xe2,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,
+0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,
+0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0x58,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,
+0x08,0x0b,0x05,0x8e,0x00,0x80,0x42,0x36,0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,
+0x80,0x00,0x63,0x34,0x40,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,
+0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,
+0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,
+0x08,0x0b,0x02,0x8e,0x02,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,
+0xbb,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xc0,0x00,0x00,0x0c,0x02,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,
+0xff,0x00,0x02,0x24,0x1d,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x08,0x25,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0x9c,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x5c,0x24,0x0a,0xa2,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c,
+0x02,0x80,0x07,0x3c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x06,0x00,0x02,0x3c,
+0x27,0x10,0x02,0x00,0x00,0x01,0x63,0x34,0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac,
+0x20,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x04,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0,
+0x26,0xa0,0x83,0x02,0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,
+0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,
+0x08,0x0b,0x02,0x8e,0x04,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,
+0x24,0x10,0x52,0x00,0x92,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x50,0x40,0x00,
+0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31,
+0x08,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
+0x21,0x30,0x60,0x00,0x9c,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,
+0x60,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,
+0x02,0x80,0x07,0x3c,0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,
+0x06,0x00,0x02,0x3c,0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x01,0x63,0x34,
+0x10,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0,
+0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,
+0x08,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0x6b,0xfe,0x40,0x10,
+0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,
+0x04,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,
+0x1d,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xa8,0x24,0x03,0xae,
+0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x64,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c,0x02,0x80,0x07,0x3c,
+0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x18,0x00,0x02,0x3c,0x27,0x10,0x02,0x00,
+0x00,0x02,0x63,0x34,0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac,0x08,0x00,0x84,0x34,
+0x41,0xb0,0x02,0x3c,0x10,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0,0x26,0xa0,0x83,0x02,
+0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,
+0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,
+0x10,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,
+0x42,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xc0,0x00,0x00,0x0c,0x05,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,
+0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
+0xa8,0x24,0x03,0xae,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x68,0x24,0x0a,0xa2,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,
+0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x18,0x00,0x02,0x3c,
+0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x02,0x63,0x34,0x01,0x00,0x84,0x34,
+0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac,
+0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,
+0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x20,0x00,0x12,0x3c,
+0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0x1b,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,
+0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x06,0x00,0x04,0x24,
+0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1d,0x00,0x62,0x10,
+0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
+0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xb4,0x24,0x03,0xae,0x06,0x00,0x04,0x24,
+0x40,0x00,0x07,0x24,0x6c,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
+0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c,0x02,0x80,0x07,0x3c,0x54,0x44,0xe4,0x90,
+0x08,0x0b,0x05,0x8e,0x60,0x00,0x02,0x3c,0x27,0x10,0x02,0x00,0x00,0x04,0x63,0x34,
+0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac,0x04,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,
+0x40,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0,0x26,0xa0,0x83,0x02,0x00,0x00,0x45,0xac,
+0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,
+0x71,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x0c,0x0b,0x02,0x8e,0x08,0x0b,0x03,0x8e,0x00,0x20,0x42,0x38,0x41,0x23,0x00,0x08,
+0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xf4,0x00,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,
+0x16,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x44,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,
+0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0xd8,0x24,0x03,0xae,0x21,0x30,0x60,0x00,
+0x01,0x00,0x04,0x24,0x78,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,
+0x10,0x00,0xa0,0xaf,0x02,0x80,0x05,0x3c,0x44,0x44,0xa3,0x8c,0x08,0x0b,0x04,0x8e,
+0xff,0xc7,0x02,0x24,0x10,0x00,0x63,0x34,0x24,0x20,0x82,0x00,0x41,0xb0,0x02,0x3c,
+0x44,0x44,0xa3,0xac,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae,0x0c,0x0b,0x02,0x8e,
+0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x3a,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae,
+0xf4,0x00,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,
+0xff,0x00,0x02,0x24,0x16,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x2c,0x25,0x05,0x8e,
+0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0xc0,0x24,0x03,0xae,
+0x21,0x30,0x60,0x00,0x21,0x20,0x00,0x00,0x74,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,
+0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x05,0x3c,0x44,0x44,0xa3,0x8c,
+0x08,0x0b,0x04,0x8e,0xff,0xc7,0x02,0x24,0x04,0x00,0x63,0x34,0x24,0x20,0x82,0x00,
+0x41,0xb0,0x02,0x3c,0x44,0x44,0xa3,0xac,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae,
+0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x33,0x23,0x00,0x08,
+0x0c,0x0b,0x02,0xae,0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,0x00,0x00,0x00,0x00,
+0xf3,0xfc,0x60,0x10,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x07,0x00,0x04,0x24,
+0xc5,0x22,0x00,0x08,0x78,0x1b,0x64,0x26,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x79,0x22,0x00,0x08,0x30,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x01,0x00,0x03,0x24,
+0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x95,0x23,0x00,0x08,0x78,0x1b,0x62,0x26,
+0xd0,0x03,0x23,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xc6,0x23,0x00,0x08,
+0x78,0x1b,0x62,0x26,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,
+0x10,0x00,0xb0,0xaf,0x25,0xb0,0x0c,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0x83,0x35,
+0xa4,0x97,0x42,0x24,0x02,0x80,0x11,0x3c,0x41,0xb0,0x0b,0x3c,0x00,0x00,0x62,0xac,
+0x78,0x1b,0x2a,0x26,0x0a,0x00,0x62,0x35,0x00,0x00,0x44,0x94,0x16,0x0b,0x43,0x95,
+0x14,0x0b,0x49,0x95,0x25,0x30,0x64,0x00,0xff,0xff,0xd0,0x30,0x24,0x10,0x09,0x02,
+0x02,0x00,0x42,0x30,0x9e,0x00,0x40,0x10,0xc0,0x03,0x83,0x35,0x02,0x00,0x02,0x24,
+0x00,0x00,0x62,0xac,0x02,0x80,0x08,0x3c,0x44,0x44,0x04,0x8d,0xdc,0x02,0x82,0x35,
+0x00,0x00,0x47,0x90,0xfd,0xff,0x03,0x24,0x00,0x80,0x02,0x3c,0x24,0x18,0x23,0x01,
+0x25,0x20,0x82,0x00,0x02,0x00,0xc6,0x38,0x08,0x00,0x65,0x35,0x02,0x80,0x02,0x3c,
+0x99,0x44,0x47,0xa0,0x44,0x44,0x04,0xad,0x16,0x0b,0x46,0xa5,0x21,0x48,0x60,0x00,
+0x00,0x00,0xa3,0xa4,0x14,0x0b,0x43,0xa5,0x24,0x38,0x09,0x02,0x04,0x00,0xe2,0x30,
+0x0a,0x00,0x40,0x10,0x08,0x00,0xe2,0x30,0x16,0x0b,0x43,0x95,0x0c,0x00,0x64,0x35,
+0xc0,0x03,0x85,0x35,0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c,
+0x00,0x00,0xa2,0xac,0x16,0x0b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,
+0x10,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95,0xc0,0x03,0x84,0x35,0x08,0x00,0x03,0x24,
+0x08,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,0x10,0x00,0xe2,0x30,
+0x3a,0x00,0x40,0x10,0x78,0x1b,0x29,0x26,0xc0,0x03,0x84,0x35,0x10,0x00,0x02,0x24,
+0x00,0x00,0x82,0xac,0x16,0x0b,0x43,0x95,0x02,0x80,0x05,0x3c,0xba,0x44,0xa4,0x90,
+0x10,0x00,0x63,0x38,0x02,0x80,0x02,0x3c,0x16,0x0b,0x43,0xa5,0x7c,0x44,0x47,0x24,
+0x69,0x00,0x80,0x14,0x21,0x30,0x00,0x00,0xe8,0x0a,0x42,0x91,0x00,0x00,0x00,0x00,
+0x01,0x00,0x42,0x30,0x69,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
+0x98,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x64,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x98,0x44,0x82,0x90,0x02,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x66,0x00,0x43,0x10,
+0x00,0x00,0x00,0x00,0x98,0x44,0x82,0x90,0x03,0x00,0x03,0x24,0xff,0x00,0x42,0x30,
+0x61,0x00,0x43,0x10,0x02,0x80,0x05,0x3c,0xb2,0x44,0xa2,0x90,0x02,0x80,0x03,0x3c,
+0x02,0x00,0x04,0x24,0x10,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0,0x9d,0x44,0x66,0x90,
+0x21,0x28,0x00,0x00,0x0c,0x00,0xe0,0xac,0xff,0x00,0xc6,0x30,0x71,0x14,0x00,0x0c,
+0x00,0x32,0x06,0x00,0x42,0xb0,0x02,0x3c,0x03,0x00,0x42,0x34,0x44,0x00,0x04,0x24,
+0x00,0x00,0x44,0xa0,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x04,0x00,0x40,0x10,0x78,0x1b,0x29,0x26,
+0xf9,0x1f,0x00,0x0c,0x04,0x00,0x04,0x24,0x78,0x1b,0x29,0x26,0x14,0x0b,0x27,0x95,
+0x00,0x00,0x00,0x00,0x24,0x28,0x07,0x02,0x20,0x00,0xa2,0x30,0x09,0x00,0x40,0x10,
+0x80,0x00,0xa2,0x30,0x16,0x0b,0x22,0x95,0x25,0xb0,0x03,0x3c,0x20,0x00,0x04,0x24,
+0x20,0x00,0x42,0x38,0xc0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x16,0x0b,0x22,0xa5,
+0x80,0x00,0xa2,0x30,0x17,0x00,0x40,0x10,0x24,0x10,0x07,0x02,0x02,0x80,0x08,0x3c,
+0x44,0x44,0x04,0x8d,0x16,0x0b,0x26,0x95,0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c,
+0x7f,0xff,0x05,0x24,0x24,0x28,0xe5,0x00,0x25,0x20,0x82,0x00,0xb0,0x03,0x67,0x34,
+0x80,0x00,0x02,0x24,0xc0,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0x41,0xb0,0x02,0x3c,
+0x80,0x00,0xc6,0x38,0x08,0x00,0x42,0x34,0x00,0x00,0xe4,0xac,0x16,0x0b,0x26,0xa5,
+0x44,0x44,0x04,0xad,0x21,0x38,0xa0,0x00,0x00,0x00,0x45,0xa4,0x14,0x0b,0x25,0xa5,
+0x24,0x10,0x07,0x02,0x00,0x30,0x42,0x30,0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x16,0x0b,0x22,0x95,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,
+0x16,0x0b,0x22,0xa5,0x02,0x80,0x02,0x3c,0x52,0x43,0x43,0x90,0x01,0x00,0x02,0x24,
+0x0f,0x00,0x63,0x30,0x0f,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x12,0x26,0x00,0x08,0x16,0x0b,0x46,0xa5,0xe8,0x0a,0x42,0x91,0xba,0x44,0xa0,0xa0,
+0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x14,0x01,0x00,0x06,0x24,0x62,0x26,0x00,0x08,
+0x0c,0x00,0xe0,0xac,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x79,0x22,0x00,0x08,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xb5,0x44,0x82,0x90,
+0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x24,0xb5,0x44,0x82,0xa0,0xb5,0x44,0x83,0x90,
+0x00,0x00,0x00,0x00,0x07,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0x9e,0x44,0x43,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x12,0x00,0xc0,0x10,
+0x02,0x80,0x02,0x3c,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x14,
+0x0c,0x00,0xe0,0xac,0x02,0x80,0x02,0x3c,0xb4,0x44,0x43,0x90,0x00,0x00,0x00,0x00,
+0xb5,0x44,0x83,0xa0,0x02,0x80,0x05,0x3c,0xb2,0x44,0xa2,0x90,0x02,0x80,0x03,0x3c,
+0x02,0x00,0x04,0x24,0x10,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0,0x9d,0x44,0x66,0x90,
+0x52,0x26,0x00,0x08,0x21,0x28,0x00,0x00,0x02,0x80,0x04,0x3c,0xac,0x44,0x83,0x8c,
+0xa4,0x44,0x45,0x8c,0xe4,0x02,0x86,0x35,0x21,0x18,0x65,0x00,0xac,0x44,0x83,0xac,
+0xac,0x44,0x82,0x8c,0x02,0x80,0x03,0x3c,0x00,0x00,0xc2,0xac,0xa0,0x44,0x62,0x94,
+0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x40,0x10,0x02,0x00,0xf6,0xff,0x42,0x24,
+0x62,0x26,0x00,0x08,0x0c,0x00,0xe2,0xac,0xf8,0xff,0xbd,0x27,0x04,0x00,0xb1,0xaf,
+0x00,0x00,0xb0,0xaf,0x00,0x40,0x09,0x40,0x00,0x68,0x0a,0x40,0x00,0x70,0x02,0x40,
+0x00,0x60,0x0b,0x40,0x25,0xb0,0x05,0x3c,0x18,0x03,0xa7,0x34,0x00,0x00,0xe6,0x8c,
+0x01,0x80,0x02,0x3c,0x1c,0x03,0xa3,0x34,0x68,0x9b,0x42,0x24,0x00,0x00,0x66,0xac,
+0x00,0x00,0xe2,0xac,0x80,0x00,0x83,0x8c,0x7c,0x02,0xa2,0x34,0x80,0x02,0xa6,0x34,
+0x84,0x02,0xa7,0x34,0x88,0x02,0xa8,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xc9,0xac,
+0x00,0x00,0xea,0xac,0x00,0x00,0x0b,0xad,0x74,0x00,0x83,0x8c,0x8c,0x02,0xa2,0x34,
+0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,0x94,0x02,0xa8,0x34,
+0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,0x9c,0x02,0xa6,0x34,
+0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,0xa4,0x02,0xa8,0x34,
+0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,0xac,0x02,0xa9,0x34,
+0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,0xb4,0x02,0xa6,0x34,
+0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,0xbc,0x02,0xa7,0x34,
+0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,0xc4,0x02,0xa8,0x34,
+0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,0xcc,0x02,0xaa,0x34,
+0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,0xd4,0x02,0xa9,0x34,
+0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,0x70,0x02,0xab,0x34,
+0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,0x78,0x02,0xa5,0x34,
+0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xac,
+0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,0x3c,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xad,
+0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,0x4c,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xad,
+0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0x5c,0x00,0x82,0x8c,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x42,0x27,0x00,0x08,0x00,0x00,0x00,0x00,
+0x01,0x80,0x1b,0x3c,0x10,0x9d,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
+0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
+0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
+0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
+0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
+0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
+0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
+0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
+0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
+0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
+0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
+0x00,0x68,0x1a,0x40,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,
+0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
+0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
+0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
+0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
+0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
+0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
+0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
+0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
+0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
+0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
+0xda,0x26,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
+0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,0x00,0x04,0x5b,0x33,
+0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0x90,0x8a,0x08,0x25,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
+0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x5b,0x33,
+0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,
+0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0xa4,0x97,0x08,0x25,
+0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x1a,0x3c,
+0x44,0x44,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,0x30,0x03,0x08,0x35,
+0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
+0x08,0xe8,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
+0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
+0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
+0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
+0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
+0x80,0x00,0x7b,0x8f,0x2b,0x28,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,
+0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x08,0x00,0x5b,0xaf,
+0xfc,0xeb,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,0x21,0x00,0x40,0x11,
+0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0xa4,0x43,0x08,0x25,0x21,0x48,0x00,0x00,
+0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,0x24,0x70,0x4b,0x01,
+0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,0x04,0x00,0x44,0xa3,
+0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,0x21,0x80,0x08,0x02,
+0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,0x00,0x00,0x00,0x00,
+0x01,0x80,0x1b,0x3c,0xd8,0x9f,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
+0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x44,0x44,0x5a,0x27,0xe1,0xff,0x00,0x10,
+0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,0xee,0x27,0x00,0x08,
+0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0x44,0x44,0x7b,0x27,0x21,0x60,0x00,0x00,
+0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,0xf8,0xff,0x5a,0x27,
+0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,0x84,0x00,0x44,0x8f,
+0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x41,0x8f,
+0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,0xfc,0x00,0x46,0x7b,
+0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x4a,0x7b,
+0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,0x7c,0x02,0x52,0x7b,
+0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,0x7c,0x03,0x5c,0x7b,
+0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,
+0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,
+0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,
+0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,
+0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,
+0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,
+0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x95,0xac,
+0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,
+0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x74,0x00,0x9f,0xac,
+0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0xf8,0xff,0x84,0x24,
+0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,
+0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,
+0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,
+0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,
+0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,
+0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,
+0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x60,0x05,0x40,
+0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,
+0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,
+0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,
+0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,
+0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,
+0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x96,0xac,
+0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,
+0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,
+0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,
+0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,
+0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
+0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
+0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
+0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
+0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
+0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0xd7,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27,
+0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24,
+0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c,
+0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
+0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27,
+0x02,0x80,0x1c,0x3c,0x00,0x18,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35,
+0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c,
+0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34,
+0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x02,0x80,0x08,0x3c,0x00,0x00,0x08,0x25,
+0x00,0x00,0x00,0xad,0x03,0x80,0x09,0x3c,0x7c,0xc3,0x29,0x25,0x04,0x00,0x08,0x25,
+0xfe,0xff,0x09,0x15,0x00,0x00,0x00,0xad,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,
+0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c,
+0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c,
+0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c,
+0x44,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84,
+0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c,
+0x74,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
+0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00,
+0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c,
+0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0x50,0x43,0xa5,0x24,0xff,0xff,0xa5,0x30,
+0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00,
+0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac,
+0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x7e,0x5e,0x00,0x08,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
+0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24,
+0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x00,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x30,0x80,0x00,0x21,0x90,0x00,0x00,
+0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x0d,0x00,0x83,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x14,0x02,0x80,0x02,0x3c,
+0x01,0x00,0x03,0x24,0x9c,0x44,0x43,0xa0,0x0c,0x00,0xc2,0x90,0x02,0x80,0x05,0x3c,
+0xb1,0x44,0xa2,0xa0,0x00,0x00,0xc4,0x90,0x05,0x00,0x02,0x24,0xff,0x00,0x83,0x30,
+0x4b,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x24,0x3b,0x00,0x62,0x10,
+0xff,0x00,0x84,0x30,0x09,0x00,0x82,0x2c,0x2f,0x00,0x40,0x10,0x02,0x80,0x10,0x3c,
+0x98,0x44,0x02,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2b,0x00,0x82,0x10,
+0x00,0x00,0x00,0x00,0xad,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x98,0x44,0x02,0x92,
+0x00,0x00,0x00,0x00,0x3e,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x5a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x40,0x14,
+0x25,0xb0,0x02,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0xb9,0x44,0x62,0xa0,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x04,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,
+0xf9,0x1f,0x00,0x0c,0x04,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0x00,0x01,0x03,0x24,
+0x16,0x01,0x42,0x34,0x00,0x00,0x43,0xa4,0x00,0x60,0x91,0x40,0x21,0x10,0x40,0x02,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x04,0x00,0x12,0x24,0x00,0x60,0x91,0x40,
+0x21,0x10,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x0b,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0x03,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x03,0x3c,
+0x01,0x00,0x02,0x24,0xb4,0x44,0x62,0xa0,0xb4,0x44,0x63,0x90,0x02,0x80,0x02,0x3c,
+0xb5,0x44,0x43,0xa0,0x00,0x00,0xc4,0x90,0xb7,0x41,0x00,0x08,0xff,0x00,0x84,0x30,
+0xb1,0x44,0xa0,0xa0,0x00,0x00,0xc4,0x90,0xb4,0x41,0x00,0x08,0xff,0x00,0x83,0x30,
+0x42,0xb0,0x05,0x3c,0x00,0x00,0xa3,0x90,0xef,0xff,0x02,0x24,0x03,0x00,0xa6,0x34,
+0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0xa3,0xa0,0x0c,0x00,0x04,0x24,
+0x00,0x00,0xc2,0xa0,0x02,0x80,0x03,0x3c,0xf9,0x1f,0x00,0x0c,0x88,0x44,0x60,0xac,
+0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,
+0x17,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,
+0x82,0x0b,0xa3,0x90,0x25,0xb0,0x02,0x3c,0x16,0x01,0x42,0x34,0x00,0x00,0x40,0xa4,
+0xce,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x98,0x26,0xa4,0x94,0x82,0x0b,0xa0,0xa0,
+0x00,0xc0,0x84,0x24,0x2c,0x22,0x00,0x0c,0xff,0xff,0x84,0x30,0xe9,0x41,0x00,0x08,
+0x00,0x00,0x00,0x00,0xb9,0x44,0x40,0xa0,0x25,0xb0,0x02,0x3c,0x00,0x01,0x03,0x24,
+0x16,0x01,0x42,0x34,0x00,0x00,0x43,0xa4,0xe0,0x41,0x00,0x08,0x00,0x00,0x00,0x00,
+0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24,0x15,0x42,0x00,0x08,0x02,0x80,0x02,0x3c,
+0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
+0x14,0x00,0xb1,0xaf,0x21,0x80,0x80,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x02,0x92,0x02,0x80,0x04,0x3c,
+0x25,0xb0,0x05,0x3c,0x02,0x80,0x07,0x3c,0x98,0x26,0x84,0x24,0x50,0x00,0xa5,0x34,
+0x06,0x00,0x06,0x24,0x13,0x00,0x40,0x14,0x78,0x1b,0xe3,0x24,0xe8,0x0a,0x62,0x90,
+0x78,0x1b,0xf2,0x24,0x02,0x80,0x04,0x3c,0xfe,0x00,0x42,0x30,0xe8,0x0a,0x62,0xa0,
+0xe8,0x0a,0x42,0x92,0x18,0x42,0x84,0x24,0x01,0x00,0x42,0x30,0x18,0x00,0x40,0x14,
+0x02,0x00,0x05,0x26,0x00,0x60,0x91,0x40,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x07,0x3c,
+0x78,0x1b,0xe3,0x24,0xe8,0x0a,0x62,0x90,0x78,0x1b,0xf2,0x24,0x02,0x80,0x04,0x3c,
+0x01,0x00,0x42,0x34,0xe8,0x0a,0x62,0xa0,0xe8,0x0a,0x42,0x92,0x18,0x42,0x84,0x24,
+0x02,0x00,0x05,0x26,0x01,0x00,0x42,0x30,0xea,0xff,0x40,0x10,0x06,0x00,0x06,0x24,
+0x01,0x00,0x03,0x92,0x02,0x80,0x02,0x3c,0xb3,0x44,0x43,0xa0,0x46,0x46,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x96,0x02,0x80,0x03,0x3c,0xa0,0x44,0x64,0xa4,
+0xa0,0x44,0x62,0x94,0x02,0x80,0x03,0x3c,0xff,0xff,0x42,0x30,0x80,0x12,0x02,0x00,
+0xa4,0x44,0x62,0xac,0x0a,0x00,0x04,0x96,0x14,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,
+0xb9,0x44,0x43,0xa0,0x98,0x26,0x44,0xa6,0x00,0x60,0x91,0x40,0x1c,0x00,0xbf,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x21,0x20,0x82,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
+0x25,0xb0,0x06,0x3c,0x78,0x1b,0x45,0x24,0x01,0x80,0x02,0x3c,0x18,0x03,0xc3,0x34,
+0x54,0x0a,0x42,0x24,0x20,0x08,0xc8,0x34,0x21,0x38,0x80,0x00,0x60,0x08,0x09,0x24,
+0x00,0x00,0x62,0xac,0x07,0x00,0x80,0x10,0x70,0x08,0x02,0x24,0x01,0x00,0x02,0x24,
+0x28,0x08,0xc3,0x34,0x2a,0x00,0x82,0x10,0x64,0x08,0x06,0x24,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x8d,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xa2,0xac,
+0x40,0x08,0x02,0x24,0x90,0x0b,0xa3,0xac,0x9c,0x0b,0xa2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0xa0,0x0b,0xa3,0xac,0xa4,0x0b,0xa2,0xac,0x10,0x08,0x03,0x24,
+0x20,0x08,0x02,0x24,0xa8,0x0b,0xa3,0xac,0xac,0x0b,0xa2,0xac,0x24,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xb0,0x0b,0xa3,0xac,0xb4,0x0b,0xa2,0xac,0x50,0x0c,0x03,0x24,
+0x54,0x0c,0x02,0x24,0xb8,0x0b,0xa3,0xac,0xbc,0x0b,0xa2,0xac,0x14,0x0c,0x03,0x24,
+0x10,0x0c,0x02,0x24,0xc0,0x0b,0xa3,0xac,0xc4,0x0b,0xa2,0xac,0x80,0x0c,0x03,0x24,
+0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xa2,0xac,0x98,0x0b,0xa9,0xac,
+0xc8,0x0b,0xa3,0xac,0x89,0x0b,0xa0,0xa0,0x94,0x0b,0xa9,0xac,0x02,0x00,0x80,0x10,
+0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,0xd0,0x0b,0xa2,0xac,
+0x70,0x08,0x02,0x24,0x00,0x00,0x64,0x8c,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xa2,0xac,
+0x44,0x08,0x02,0x24,0x90,0x0b,0xa3,0xac,0x9c,0x0b,0xa2,0xac,0x78,0x08,0x03,0x24,
+0x0c,0x08,0x02,0x24,0xa0,0x0b,0xa3,0xac,0xa4,0x0b,0xa2,0xac,0x14,0x08,0x03,0x24,
+0x28,0x08,0x02,0x24,0xa8,0x0b,0xa3,0xac,0xac,0x0b,0xa2,0xac,0x2c,0x08,0x03,0x24,
+0x58,0x08,0x02,0x24,0xb0,0x0b,0xa3,0xac,0xb4,0x0b,0xa2,0xac,0x58,0x0c,0x03,0x24,
+0x5c,0x0c,0x02,0x24,0xb8,0x0b,0xa3,0xac,0xbc,0x0b,0xa2,0xac,0x1c,0x0c,0x03,0x24,
+0x18,0x0c,0x02,0x24,0xc0,0x0b,0xa3,0xac,0xc4,0x0b,0xa2,0xac,0x88,0x0c,0x03,0x24,
+0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xa2,0xac,0x89,0x0b,0xa7,0xa0,
+0x98,0x0b,0xa6,0xac,0xc8,0x0b,0xa3,0xac,0x94,0x0b,0xa6,0xac,0xda,0xff,0x80,0x10,
+0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,0xd0,0x0b,0xa2,0xac,
+0xfb,0x42,0x00,0x08,0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,
+0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x02,0x3c,0x21,0x88,0xa0,0x00,
+0xff,0xff,0x03,0x24,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,
+0x20,0x00,0xbf,0xaf,0x21,0x98,0xc0,0x00,0x21,0x28,0xc0,0x00,0x21,0x90,0x80,0x00,
+0x09,0x00,0x23,0x12,0x21,0x80,0x82,0x00,0x00,0x00,0x10,0x8e,0xf6,0x42,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x27,0x28,0x11,0x00,0x24,0x28,0xb0,0x00,0x04,0x10,0x53,0x00,
+0x25,0x28,0xa2,0x00,0x21,0x20,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x8a,0x42,0x00,0x08,
+0x28,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0x14,0x27,0x44,0x8c,
+0x02,0x43,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
+0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,
+0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00,
+0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,
+0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x20,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
+0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,0x78,0x1b,0x31,0x26,0xb0,0x0b,0x23,0x8e,
+0x25,0xb0,0x02,0x3c,0x24,0x08,0x53,0x8c,0x21,0x18,0x62,0x00,0x00,0x00,0x70,0x8c,
+0x7f,0x80,0x02,0x3c,0xff,0xff,0x42,0x34,0xff,0x7f,0x05,0x3c,0x24,0x80,0x02,0x02,
+0xc0,0x25,0x04,0x00,0xff,0xff,0xa5,0x34,0x24,0x28,0x65,0x02,0x25,0x80,0x04,0x02,
+0x8a,0x42,0x00,0x0c,0x24,0x08,0x04,0x24,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x00,0x80,0x12,0x3c,0xb0,0x0b,0x24,0x8e,0x25,0x80,0x12,0x02,0x8a,0x42,0x00,0x0c,
+0x21,0x28,0x00,0x02,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0x28,0x72,0x02,
+0x8a,0x42,0x00,0x0c,0x24,0x08,0x04,0x24,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24,
+0xd0,0x0b,0x24,0x8e,0x0f,0x00,0x05,0x3c,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34,
+0x24,0x43,0x00,0x08,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x78,0x1b,0x27,0x26,
+0x8b,0x0b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x90,0x0d,0x63,0x24,
+0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10,
+0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e,
+0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x35,0x43,0x00,0x08,
+0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x89,0x0b,0xe4,0x90,
+0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,
+0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x78,0x1b,0x22,0x26,0x2e,0x00,0x83,0x10,
+0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x24,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
+0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,
+0x02,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0x78,0x1b,0x22,0x26,0x89,0x0b,0x44,0x90,
+0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,
+0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0x7a,0x43,0x00,0x08,0xff,0x00,0x04,0x32,
+0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
+0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0x8c,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xcc,0xff,0x80,0x14,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,
+0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0x8c,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
+0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,
+0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0x7a,0x43,0x00,0x08,
+0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,
+0x78,0x1b,0x28,0x26,0x8b,0x0b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0x3c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf,
+0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,
+0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10,
+0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x25,0x20,0x44,0x00,0x1f,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14,
+0x0f,0x00,0x04,0x3c,0x89,0x0b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,
+0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10,
+0x78,0x1b,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,
+0x24,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,
+0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0x02,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
+0x78,0x1b,0x22,0x26,0x89,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,
+0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,
+0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,
+0xe7,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14,
+0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x78,0x1b,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xfe,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x78,0x1b,0x22,0x26,
+0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
+0xfe,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
+0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c,
+0x21,0x30,0x00,0x00,0xe7,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x35,0x43,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e,
+0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34,
+0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x1f,0x43,0x00,0x0c,
+0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x1f,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26,
+0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,0x00,0x00,0x90,0x8c,
+0x21,0x88,0xa0,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00,0x24,0x80,0x11,0x02,
+0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
+0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,0x1c,0x00,0xb3,0xaf,
+0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x88,0xa0,0x00,
+0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,0x21,0x98,0xc0,0x00,
+0x00,0x00,0x50,0x8e,0xf6,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,0x27,0x18,0x11,0x00,
+0x24,0x18,0x70,0x00,0x04,0x10,0x53,0x00,0x25,0x18,0x62,0x00,0x00,0x00,0x43,0xae,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x02,0x3c,0x21,0x38,0x82,0x00,0xff,0xff,0x02,0x24,0x27,0x40,0x05,0x00,
+0x08,0x00,0xa2,0x10,0x24,0x18,0xc5,0x00,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x02,0x01,0x25,0x10,0x43,0x00,0x00,0x00,0xe2,0xac,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x21,0x38,0xa0,0x00,0x25,0xb0,0x02,0x3c,0xff,0xff,0x03,0x24,0x27,0x48,0x05,0x00,
+0x24,0x40,0xc7,0x00,0x21,0x28,0xc0,0x00,0x05,0x00,0xe3,0x10,0x21,0x30,0x82,0x00,
+0x00,0x00,0xc5,0x8c,0x00,0x00,0x00,0x00,0x24,0x28,0x25,0x01,0x25,0x28,0xa8,0x00,
+0x8a,0x42,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0xd8,0xff,0xbd,0x27,0xe0,0x12,0x42,0x24,0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
+0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00,
+0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12,
+0x21,0x28,0xc0,0x00,0x64,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,
+0xf6,0x42,0x00,0x0c,0x21,0x80,0x40,0x00,0x27,0x28,0x11,0x00,0x24,0x28,0xb0,0x00,
+0x04,0x10,0x53,0x00,0x25,0x28,0xa2,0x00,0xcf,0x43,0x00,0x0c,0xff,0x00,0x84,0x32,
+0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x8c,0x13,0x63,0x24,
+0x18,0x03,0x42,0x34,0xe0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,0x18,0x00,0xbf,0xaf,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x64,0x43,0x00,0x0c,0x21,0x88,0xa0,0x00,
+0x21,0x80,0x40,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0x20,0x02,0x24,0x80,0x11,0x02,
+0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,
+0x95,0x42,0x00,0x0c,0xff,0x00,0x84,0x30,0x10,0x00,0xbf,0x8f,0x01,0x00,0x02,0x24,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,0x21,0x88,0x80,0x00,
+0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xb2,0xaf,
+0x3e,0x46,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,0x02,0x80,0x02,0x3c,
+0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,0x3e,0x46,0x00,0x0c,
+0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,0x10,0x00,0xa5,0x27,
+0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,0x46,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,0x00,0x00,0x44,0x8c,
+0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,0x00,0x00,0xa2,0x8c,
+0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,0x00,0x00,0xc7,0x8c,
+0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,0x00,0x00,0x62,0x8c,
+0x1a,0x00,0x12,0x24,0x46,0x46,0x00,0x0c,0x24,0x00,0xa2,0xaf,0x30,0x00,0x04,0x26,
+0x20,0x00,0xa5,0x27,0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x13,0x00,0x03,0x24,
+0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,0x04,0x00,0x04,0x8e,
+0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,0x10,0x00,0x07,0x8e,
+0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,0x24,0x20,0x83,0x00,
+0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,0x24,0x30,0xc3,0x00,
+0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,0x24,0x20,0x82,0x00,
+0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,0x20,0x00,0x02,0x24,
+0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,0x14,0x00,0x06,0xae,
+0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,0x30,0x00,0xb2,0x8f,
+0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
+0xc8,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0xf4,0x30,
+0x25,0xb0,0x10,0x3c,0x01,0x80,0x02,0x3c,0x1c,0x00,0xb1,0xaf,0x18,0x03,0x03,0x36,
+0x58,0x15,0x42,0x24,0x20,0x00,0x91,0x26,0x30,0x00,0xb6,0xaf,0x24,0x00,0xb3,0xaf,
+0x21,0xb0,0x80,0x00,0x48,0x00,0xb3,0x93,0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac,
+0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,0xff,0x00,0xb5,0x30,
+0x39,0x15,0x00,0x0c,0xff,0x00,0xd2,0x30,0x0b,0x00,0x40,0x14,0x10,0x00,0xa2,0xaf,
+0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x08,0x00,0x43,0x8c,0xb0,0x03,0x02,0x36,
+0x02,0x80,0x10,0x3c,0x00,0x00,0x43,0xac,0x10,0x00,0xa2,0x8f,0x21,0x30,0x20,0x02,
+0x21,0x28,0x00,0x00,0x08,0x00,0x44,0x94,0x35,0x46,0x00,0x0c,0x25,0x20,0x90,0x00,
+0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
+0x25,0x88,0x50,0x00,0x50,0x00,0x60,0x16,0x20,0x00,0x30,0x26,0x20,0x00,0x32,0xa6,
+0x48,0x00,0x02,0x24,0x6b,0x00,0x42,0x12,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x24,
+0x4c,0x00,0xa2,0x16,0x21,0x28,0xc0,0x02,0xa4,0x00,0x02,0x24,0x6a,0x00,0x42,0x12,
+0x02,0x80,0x02,0x3c,0x10,0x00,0xa2,0x8f,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x10,0x36,
+0x0c,0x00,0x54,0xac,0x10,0x00,0xa2,0x8f,0x12,0x00,0x03,0x24,0x21,0x28,0x00,0x00,
+0x14,0x00,0x43,0xac,0x00,0x00,0x14,0xae,0x10,0x00,0xa2,0x8f,0x08,0x00,0x06,0x24,
+0x08,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,0x10,0x00,0xa2,0x8f,
+0x02,0x80,0x03,0x3c,0x08,0x00,0x44,0x94,0x00,0x00,0x00,0x00,0x25,0x88,0x83,0x00,
+0x3e,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x04,0x00,0x25,0x8e,0x08,0x00,0x26,0x8e,
+0x14,0x00,0x27,0x8e,0x10,0x00,0x24,0x8e,0xff,0xe0,0x03,0x24,0xff,0xdf,0x02,0x3c,
+0x24,0x28,0xa3,0x00,0xff,0xff,0x42,0x34,0xff,0x81,0x03,0x24,0x24,0x38,0xe3,0x00,
+0x24,0x30,0xc2,0x00,0x00,0x80,0x03,0x3c,0x00,0x40,0x02,0x3c,0x25,0x30,0xc2,0x00,
+0x25,0x20,0x83,0x00,0x00,0x12,0xa5,0x34,0x20,0x00,0x02,0x24,0x10,0x00,0x24,0xae,
+0x00,0x00,0x34,0xa6,0x02,0x00,0x22,0xa2,0x04,0x00,0x25,0xae,0x14,0x00,0x27,0xae,
+0x08,0x00,0x26,0xae,0x00,0x60,0x05,0x40,0x01,0x00,0xa1,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x10,0x00,0xa3,0x8f,0x78,0x41,0x42,0x24,
+0x04,0x00,0x44,0x8c,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x10,0x00,0xa2,0x27,
+0x00,0x00,0x83,0xac,0x04,0x00,0x64,0xac,0x00,0x00,0x02,0xae,0x00,0x60,0x85,0x40,
+0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x00,0x10,0x42,0x36,0x8a,0x45,0x00,0x08,
+0x20,0x00,0x22,0xa6,0x24,0x00,0x24,0x26,0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,
+0x02,0x80,0x05,0x3c,0x98,0x26,0xa5,0x24,0x2a,0x00,0x24,0x26,0x46,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x30,0x00,0x24,0x26,0x18,0x42,0xa5,0x24,
+0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,
+0xec,0x0c,0xa6,0x94,0x00,0x00,0x00,0x00,0x01,0x00,0xc2,0x24,0x00,0x21,0x06,0x00,
+0xff,0xff,0x46,0x30,0xff,0xff,0x84,0x30,0x00,0x10,0xc2,0x2c,0x0a,0x30,0x02,0x00,
+0x02,0x1a,0x04,0x00,0x17,0x00,0x03,0xa2,0x16,0x00,0x04,0xa2,0x93,0x45,0x00,0x08,
+0xec,0x0c,0xa6,0xa4,0x20,0x00,0x22,0x96,0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x34,
+0x8d,0x45,0x00,0x08,0x20,0x00,0x22,0xa6,0x10,0x42,0x43,0x94,0x02,0x80,0x05,0x3c,
+0x24,0x00,0x24,0x26,0x00,0xc0,0x63,0x24,0xff,0xff,0x63,0x30,0x02,0x12,0x03,0x00,
+0x18,0x42,0xa5,0x24,0x03,0x00,0x02,0xa2,0x02,0x00,0x03,0xa2,0x46,0x46,0x00,0x0c,
+0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x2a,0x00,0x24,0x26,0x98,0x26,0xa5,0x24,
+0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x93,0x45,0x00,0x08,0x00,0x00,0x00,0x00,
+0xff,0x00,0x82,0x30,0x02,0x80,0x04,0x3c,0xe0,0xff,0xbd,0x27,0x18,0x42,0x84,0x24,
+0x08,0x00,0x05,0x24,0x48,0x00,0x06,0x24,0x18,0x00,0x07,0x24,0x18,0x00,0xbf,0xaf,
+0x56,0x45,0x00,0x0c,0x10,0x00,0xa2,0xaf,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x05,0x3c,
+0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb0,0xaf,0x78,0x1b,0xa5,0x24,0x98,0x26,0xa2,0x94,
+0x01,0x00,0x03,0x24,0xff,0x00,0x90,0x30,0x00,0xc0,0x42,0x24,0xff,0xff,0x44,0x30,
+0x2c,0x22,0x00,0x0c,0x82,0x0b,0xa3,0xa0,0x02,0x80,0x04,0x3c,0x18,0x42,0x84,0x24,
+0x04,0x00,0x05,0x24,0xa4,0x00,0x06,0x24,0x10,0x00,0x07,0x24,0x56,0x45,0x00,0x0c,
+0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x3a,0x46,0x00,0x08,
+0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,
+0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24,
+0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,
+0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0,
+0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
+0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,
+0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac,
+0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
+0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24,
+0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90,
+0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14,
+0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00,
+0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00,
+0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,
+0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,
+0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00,
+0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24,
+0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,
+0x91,0x46,0x00,0x08,0x21,0x18,0x86,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
+0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10,
+0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90,
+0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x80,0xb4,0x4b,0x24,0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90,
+0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10,
+0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10,
+0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
+0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30,
+0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00,
+0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00,
+0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,
+0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,
+0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,
+0x00,0x00,0x82,0x80,0xe0,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24,
+0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,
+0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10,
+0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,0xf1,0x46,0x00,0x08,0x00,0x00,0x00,0x00,
+0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,
+0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,
+0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14,
+0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
+0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00,
+0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,
+0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,
+0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,
+0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14,
+0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80,
+0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,0x22,0x47,0x00,0x08,0x03,0x2e,0x05,0x00,
+0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00,
+0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x00,0x82,0x80,0x2e,0x47,0x00,0x08,
+0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,
+0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf,
+0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,0x28,0x47,0x00,0x0c,0x00,0x86,0x10,0x00,
+0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,
+0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00,
+0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80,
+0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24,
+0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80,
+0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,
+0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11,
+0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01,
+0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90,
+0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14,
+0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14,
+0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90,
+0x73,0x47,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0xc2,0x90,0x73,0x47,0x00,0x08,
+0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10,
+0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00,
+0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00,
+0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80,
+0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
+0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,
+0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00,
+0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,0x5f,0x47,0x00,0x0c,0x21,0x20,0x00,0x02,
+0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,
+0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x83,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,
+0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x43,0xac,
+0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0,
+0xb4,0x47,0x00,0x08,0x01,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x50,0x8c,
+0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,0x21,0x18,0x00,0x00,0x5f,0x47,0x00,0x0c,
+0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,
+0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x40,0xac,
+0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
+0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00,
+0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,0x5f,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,
+0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x83,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02,
+0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80,
+0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0,
+0xed,0x47,0x00,0x08,0x00,0x00,0x44,0xae,0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
+0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
+0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x28,0x47,0x00,0x0c,0x21,0x98,0xa0,0x00,
+0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f,
+0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x28,0x47,0x00,0x0c,0x21,0x20,0x20,0x02,
+0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,0x21,0x30,0x40,0x02,0x7b,0x46,0x00,0x0c,
+0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10,
+0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0x09,0x48,0x00,0x08,0x21,0x10,0x20,0x02,0x01,0x80,0x02,0x3c,
+0xa4,0x20,0x43,0x24,0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,
+0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x20,0x00,0xb2,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x21,0xa0,0x00,0x00,
+0x02,0x80,0x13,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x17,0x3c,0x02,0x80,0x16,0x3c,
+0x78,0x1b,0x67,0x26,0xf0,0x23,0xe3,0x94,0x25,0xb0,0x11,0x3c,0x01,0x80,0x05,0x3c,
+0x18,0x03,0x24,0x36,0x01,0x00,0x63,0x24,0xa4,0x20,0xa2,0x24,0x00,0x00,0x82,0xac,
+0xf0,0x23,0xe3,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0xc6,0x00,0x23,0x36,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
+0x11,0x00,0x42,0x2c,0x08,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x04,0x3c,
+0x44,0x44,0x62,0x8c,0x5c,0x44,0x83,0x8c,0x02,0x80,0x05,0x3c,0x5c,0x44,0x80,0xac,
+0x25,0x10,0x43,0x00,0x44,0x44,0xa2,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xc0,0x02,0x26,0x36,0x00,0x00,0xd2,0x8c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x40,0x12,0xff,0x00,0x03,0x3c,0x01,0x00,0x82,0x26,0xff,0xff,0x54,0x30,
+0xff,0xff,0x62,0x34,0x2b,0x10,0x52,0x00,0x1d,0x02,0x40,0x10,0x00,0x50,0x82,0x2e,
+0x00,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x00,0xfd,0x06,0x3c,0x24,0x28,0x42,0x02,
+0x14,0x00,0xc2,0x34,0xf7,0x04,0xa2,0x10,0x2b,0x10,0x45,0x00,0x33,0x02,0x40,0x14,
+0x00,0xfd,0x04,0x3c,0x00,0xf2,0x08,0x3c,0x01,0x00,0x02,0x35,0x0b,0x05,0xa2,0x10,
+0x2b,0x10,0x45,0x00,0xd3,0x02,0x40,0x14,0x00,0xfb,0x04,0x3c,0x00,0xf0,0x04,0x3c,
+0x20,0x00,0x82,0x34,0x59,0x05,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,
+0xfe,0x02,0x40,0x14,0x01,0x00,0x82,0x34,0x68,0x05,0xa2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x45,0x00,0x07,0x04,0x40,0x14,0x03,0x00,0x82,0x34,0x00,0xe0,0x02,0x3c,
+0xb7,0x05,0xa2,0x10,0x00,0xff,0x48,0x32,0xb3,0x04,0xa4,0x10,0xff,0x00,0x02,0x3c,
+0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x21,0xa0,0x00,0x00,0x00,0x00,0x40,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x25,0xb0,0x08,0x3c,0x64,0x03,0x02,0x35,0x00,0x00,0x43,0x94,0x68,0x03,0x04,0x35,
+0x90,0x43,0xa3,0xa6,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0xae,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x90,0x43,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xd2,0x01,0x40,0x10,0x78,0x1b,0x66,0x26,
+0x78,0x1b,0x67,0x26,0x78,0x1b,0x64,0x8e,0xd8,0x02,0xe5,0x8c,0xe8,0x02,0xe6,0x8c,
+0xf0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x50,0x03,0x3c,0x24,0x28,0xa2,0x00,
+0x01,0x00,0x84,0x34,0x24,0x30,0xc3,0x00,0x00,0x10,0x02,0x3c,0x78,0x1b,0x64,0xae,
+0x9b,0x04,0xc2,0x10,0xd8,0x02,0xe5,0xac,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x02,0x00,0x42,0x30,0xbc,0x01,0x40,0x10,0xf3,0xff,0x03,0x24,0x78,0x1b,0x62,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x04,0x00,0x42,0x34,0x78,0x1b,0x62,0xae,
+0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0x49,0x01,0x40,0x10,
+0xcf,0xff,0x03,0x24,0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,
+0x10,0x00,0x42,0x34,0x78,0x1b,0x62,0xae,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x08,0x00,0x42,0x30,0x48,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x90,0x43,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,0x26,0x00,0x40,0x10,0x78,0x1b,0x64,0x26,
+0xc9,0x02,0x82,0x90,0xa0,0x43,0xe3,0x8e,0x01,0x00,0x42,0x24,0xc9,0x02,0x82,0xa0,
+0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,0xa6,0x04,0x62,0x10,0x02,0x80,0x04,0x3c,
+0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xa5,0x04,0x43,0x10,
+0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c,0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,
+0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xa0,0x43,0xe3,0x8e,0x90,0x43,0xa5,0x96,0x25,0xb0,0x02,0x3c,
+0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,0x02,0x19,0x03,0x00,0xef,0x00,0xa5,0x30,
+0x78,0x1b,0x64,0x26,0x02,0x00,0x83,0xa0,0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,
+0x26,0x00,0x40,0x10,0x78,0x1b,0x64,0x26,0xca,0x02,0x82,0x90,0xa0,0x43,0xe3,0x8e,
+0x01,0x00,0x42,0x24,0xca,0x02,0x82,0xa0,0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,
+0x7a,0x04,0x62,0x10,0x02,0x80,0x04,0x3c,0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24,
+0x0f,0x00,0x42,0x30,0x79,0x04,0x43,0x10,0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c,
+0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,
+0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0xa0,0x43,0xe3,0x8e,
+0x90,0x43,0xa5,0x96,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,
+0x02,0x19,0x03,0x00,0xdf,0x00,0xa5,0x30,0x78,0x1b,0x64,0x26,0x02,0x00,0x83,0xa0,
+0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x30,0xc4,0x00,0x40,0x10,0x78,0x1b,0x64,0x26,
+0x78,0x1b,0x6f,0x26,0x08,0x00,0xe4,0x8d,0x00,0x00,0x00,0x00,0x42,0x17,0x04,0x00,
+0x03,0x00,0x42,0x30,0x71,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e,
+0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x83,0x00,0x00,0xff,0x11,0x3c,
+0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x24,0x10,0x51,0x00,0x08,0x00,0xe3,0xad,
+0x98,0x01,0x40,0x14,0x02,0x80,0x10,0x3c,0x25,0xb0,0x0e,0x3c,0x03,0x0d,0xc2,0x35,
+0x00,0x00,0x43,0x90,0x10,0x00,0xe4,0x8d,0xff,0x3f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x58,0x82,0x00,0x70,0x00,0x63,0x30,0x00,0x40,0x02,0x3c,0x56,0x04,0x60,0x10,
+0x25,0x58,0x62,0x01,0x94,0x0e,0xc2,0x35,0x9c,0x0e,0xc3,0x35,0xa4,0x0e,0xc4,0x35,
+0xac,0x0e,0xc5,0x35,0x00,0x00,0x47,0x8c,0x00,0x00,0x6a,0x8c,0x00,0x00,0x8c,0x8c,
+0x00,0x00,0xa6,0x8c,0x0c,0x00,0xe4,0x8d,0xb4,0x0e,0xc2,0x35,0x00,0x00,0x49,0x8c,
+0xff,0x03,0x05,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0xc2,0x35,0x24,0x38,0xe5,0x00,
+0x24,0x30,0xc5,0x00,0x24,0x18,0x68,0x01,0x02,0x3c,0x07,0x00,0x00,0x00,0x4b,0x8c,
+0x24,0x20,0x88,0x00,0x02,0x34,0x06,0x00,0xcc,0x0e,0xcd,0x35,0xc4,0x0e,0xc8,0x35,
+0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x20,0x87,0x00,0x25,0x18,0x66,0x00,
+0x00,0x00,0x07,0x8d,0x24,0x50,0x45,0x01,0x00,0x00,0xa6,0x8d,0x24,0x48,0x25,0x01,
+0x24,0x18,0x62,0x00,0x24,0x20,0x82,0x00,0x82,0x51,0x0a,0x00,0x82,0x49,0x09,0x00,
+0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8a,0x00,0x25,0x18,0x69,0x00,
+0x24,0x60,0x85,0x01,0x24,0x58,0x65,0x01,0x24,0x18,0x62,0x00,0x24,0x30,0xc5,0x00,
+0x00,0x61,0x0c,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00,0x24,0x38,0xe5,0x00,
+0x25,0x20,0x8c,0x00,0x25,0x18,0x6b,0x00,0x02,0x3c,0x07,0x00,0x02,0x34,0x06,0x00,
+0x16,0x00,0xe6,0xa5,0x0c,0x00,0xe4,0xad,0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5,
+0x78,0x1b,0x63,0x26,0x0c,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x16,0x04,0x40,0x04,
+0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e,0xff,0x00,0x04,0x3c,0x24,0x10,0x44,0x00,
+0x05,0x00,0x40,0x10,0x12,0x00,0x02,0x24,0xa0,0x43,0xe2,0x8e,0x00,0x00,0x00,0x00,
+0x24,0x10,0x44,0x00,0x02,0x14,0x02,0x00,0xc3,0x02,0x62,0xa0,0x6c,0x56,0x00,0x0c,
+0x10,0x00,0xa4,0x27,0xa7,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x26,
+0x0c,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00,0x0c,0x00,0x43,0xac,
+0x78,0x1b,0x62,0x26,0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
+0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96,
+0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0x52,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,
+0x00,0x01,0x42,0x30,0xe6,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x78,0x1b,0x62,0x26,
+0xea,0x02,0x40,0xa0,0x90,0x43,0xa2,0x96,0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30,
+0xe7,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0xfd,0xff,0x03,0x24,
+0x24,0x10,0x43,0x00,0x78,0x1b,0x62,0xae,0x25,0xb0,0x04,0x3c,0x4c,0x00,0x83,0x34,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x40,0x14,
+0x01,0x80,0x05,0x3c,0x78,0x1b,0x62,0x8e,0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00,
+0x78,0x1b,0x62,0xae,0x18,0x03,0x82,0x34,0xa4,0x21,0xa3,0x24,0x00,0x00,0x43,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x70,0x41,0xc2,0x8e,0x70,0x41,0xc3,0x26,0x11,0x00,0x43,0x10,0x02,0x80,0x02,0x3c,
+0xbf,0x00,0x92,0x34,0x78,0x1b,0x51,0x24,0x21,0x80,0x60,0x00,0x21,0xf0,0x00,0x00,
+0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,
+0x00,0x00,0x00,0x00,0xf8,0x25,0x24,0x8e,0xd9,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x70,0x41,0xc3,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x70,0x14,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,
+0x21,0x28,0x00,0x00,0x08,0x10,0x44,0x24,0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c,
+0x21,0x38,0x00,0x00,0x3f,0x48,0x00,0x08,0x78,0x1b,0x67,0x26,0x08,0x00,0x83,0x8c,
+0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x00,0x83,0xac,
+0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0xb0,0xff,0x40,0x10,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26,0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00,
+0x00,0x1f,0x03,0x00,0x25,0x20,0x83,0x00,0x76,0x52,0x00,0x0c,0xc8,0x02,0xa4,0xac,
+0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x7f,0x00,0x63,0x30,
+0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x9a,0x49,0x00,0x08,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,
+0x78,0x1b,0x62,0xae,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,
+0xba,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26,0xc8,0x02,0xa4,0x8c,
+0xff,0xf0,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x1e,0x04,0x00,0x0f,0x00,0x63,0x30,
+0x01,0x00,0x63,0x24,0x0f,0x00,0x63,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,
+0x25,0x20,0x83,0x00,0xe5,0x50,0x00,0x0c,0xc8,0x02,0xa4,0xac,0x5d,0x52,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,
+0x86,0x05,0x43,0x10,0x02,0x80,0x04,0x3c,0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24,
+0x0f,0x00,0x42,0x30,0x83,0x05,0x43,0x10,0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c,
+0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,
+0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x29,0xb0,0x02,0x3c,
+0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34,
+0x3c,0x00,0x51,0x34,0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,
+0x1c,0x00,0x49,0x34,0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,
+0x2c,0x00,0x4d,0x34,0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x38,0x00,0x50,0x34,
+0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,
+0xff,0xff,0x04,0x24,0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,
+0x78,0x1b,0x46,0x24,0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,
+0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,
+0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x21,0x18,0xa6,0x00,
+0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c,
+0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04,
+0x94,0x00,0x63,0x24,0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,
+0xf7,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0xc5,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0xb5,0x48,0x00,0x08,
+0x24,0x10,0x43,0x00,0x78,0x1b,0x64,0x8e,0xe8,0x02,0xc5,0x8c,0xfe,0xff,0x02,0x24,
+0x00,0x90,0x03,0x3c,0x24,0x20,0x82,0x00,0x24,0x18,0xa3,0x00,0x00,0x10,0x02,0x3c,
+0x35,0xfe,0x62,0x14,0x78,0x1b,0x64,0xae,0x50,0x0c,0x03,0x35,0xff,0xbf,0x02,0x3c,
+0x00,0x00,0x64,0x90,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x80,0x03,0x3c,
+0x25,0x10,0x43,0x00,0xe8,0x02,0xc2,0xac,0xac,0x48,0x00,0x08,0xdb,0x02,0xc4,0xa0,
+0x07,0xfe,0x40,0x14,0xc4,0x02,0x23,0x36,0xff,0xff,0x02,0x24,0x21,0xa0,0x00,0x00,
+0x00,0x00,0xc0,0xac,0x00,0x00,0x62,0xac,0x8a,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
+0xff,0xff,0x03,0x24,0x78,0x1b,0x42,0x24,0xea,0x02,0x43,0xa0,0x90,0x43,0xa2,0x96,
+0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30,0x1b,0xff,0x43,0x14,0x00,0x00,0x00,0x00,
+0x78,0x1b,0x62,0x8e,0x25,0xb0,0x03,0x3c,0x77,0x00,0x04,0x24,0x02,0x00,0x42,0x34,
+0x99,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x78,0x1b,0x62,0xae,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0xb1,0x49,0x00,0x08,0x25,0xb0,0x04,0x3c,0xa5,0x00,0x82,0x34,
+0xf1,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x77,0x00,0x40,0x14,
+0x00,0xfe,0x06,0x3c,0x28,0x00,0x82,0x34,0x0b,0x03,0xa2,0x10,0x0f,0x00,0x10,0x3c,
+0x2b,0x10,0x45,0x00,0xb4,0x00,0x40,0x14,0xa1,0x00,0x82,0x34,0x18,0x00,0x82,0x34,
+0x1c,0x03,0xa2,0x10,0x2b,0x10,0x45,0x00,0x41,0x01,0x40,0x14,0x23,0x00,0x82,0x34,
+0x16,0x00,0x82,0x34,0xf2,0x03,0xa2,0x10,0x02,0x14,0x12,0x00,0x17,0x00,0x82,0x34,
+0xcf,0xfd,0xa2,0x14,0x25,0xb0,0x04,0x3c,0x68,0x03,0x85,0x34,0x00,0x00,0xa3,0x8c,
+0x00,0xff,0x42,0x32,0x00,0x12,0x02,0x00,0xff,0xff,0x74,0x30,0x25,0x10,0x54,0x00,
+0x00,0x00,0xa2,0xac,0x64,0x03,0x84,0x34,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
+0xff,0x00,0x54,0x30,0x40,0x00,0x83,0x36,0x00,0x00,0x83,0xa0,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x25,0xb0,0x04,0x3c,0x94,0x0e,0x82,0x34,0x9c,0x0e,0x83,0x34,
+0xa4,0x0e,0x85,0x34,0xac,0x0e,0x86,0x34,0x00,0x00,0x49,0x8c,0x00,0x00,0x6c,0x8c,
+0xb4,0x0e,0x82,0x34,0x00,0x00,0xae,0x8c,0x10,0x00,0xe3,0x8d,0x00,0x00,0xc8,0x8c,
+0x0c,0x00,0xe5,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x3f,0x02,0x3c,0xff,0x03,0x06,0x3c,
+0xff,0xff,0x42,0x34,0x00,0xfc,0x07,0x24,0x24,0x18,0x62,0x00,0x24,0x48,0x26,0x01,
+0xbc,0x0e,0x82,0x34,0x24,0x40,0x06,0x01,0x00,0x00,0x4b,0x8c,0x24,0x18,0x67,0x00,
+0x24,0x28,0xa7,0x00,0x02,0x44,0x08,0x00,0xcc,0x0e,0x8d,0x34,0x02,0x4c,0x09,0x00,
+0xc4,0x0e,0x84,0x34,0xf0,0xff,0x02,0x3c,0x00,0x00,0x87,0x8c,0xff,0x03,0x42,0x34,
+0x00,0x00,0xa4,0x8d,0x25,0x18,0x68,0x00,0x25,0x28,0xa9,0x00,0x24,0x60,0x86,0x01,
+0x24,0x50,0x46,0x01,0xa0,0x43,0x08,0x8e,0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00,
+0x82,0x61,0x0c,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x25,0x28,0xac,0x00,0x25,0x18,0x6a,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,
+0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00,0x24,0x20,0x86,0x00,0x00,0x71,0x0e,0x00,
+0x00,0x59,0x0b,0x00,0x24,0x38,0xe6,0x00,0xff,0xff,0x02,0x3c,0x25,0x28,0xae,0x00,
+0x25,0x18,0x6b,0x00,0x02,0x3c,0x07,0x00,0x02,0x24,0x04,0x00,0x24,0x40,0x02,0x01,
+0x0c,0x00,0xe5,0xad,0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5,0x56,0x00,0x00,0x11,
+0x16,0x00,0xe4,0xa5,0xa0,0x43,0x03,0x8e,0xa0,0x43,0x02,0x8e,0x02,0x1c,0x03,0x00,
+0x24,0x10,0x51,0x00,0x02,0x16,0x02,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,
+0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27,0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c,
+0x64,0x03,0x42,0x34,0xbf,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x8b,0x49,0x00,0x08,0x78,0x1b,0x62,0x26,0x10,0x00,0xc2,0x34,
+0x7a,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0x9a,0x00,0x40,0x14,0x19,0x00,0xc2,0x34,
+0xaa,0x00,0x82,0x34,0x12,0x03,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,
+0x2d,0x01,0x40,0x14,0xae,0x00,0x82,0x34,0xa6,0x00,0x82,0x34,0xdf,0x03,0xa2,0x10,
+0x00,0x00,0x00,0x00,0xa7,0x00,0x82,0x34,0x5a,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x00,0xff,0x42,0x32,0x02,0xa2,0x02,0x00,0x02,0x1c,0x12,0x00,0x01,0x00,0x02,0x24,
+0x50,0x04,0x82,0x12,0xff,0x00,0x68,0x30,0x02,0x00,0x02,0x24,0x41,0x04,0x82,0x12,
+0xc0,0x10,0x08,0x00,0x03,0x00,0x02,0x24,0x4d,0xfd,0x82,0x16,0xc0,0x10,0x08,0x00,
+0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x48,0x00,
+0x08,0x2d,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x02,0x00,0x82,0x34,0x65,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,
+0x8b,0x00,0x40,0x14,0x10,0x00,0xc2,0x34,0x00,0xf8,0x03,0x3c,0x17,0x00,0x62,0x34,
+0x4b,0x03,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x0e,0x01,0x40,0x14,
+0x15,0x00,0x62,0x34,0x3c,0x04,0xa2,0x10,0x00,0x00,0x00,0x00,0x16,0x00,0x62,0x34,
+0x2f,0xfd,0xa2,0x14,0x00,0x00,0x00,0x00,0x58,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1,
+0x0e,0x4b,0x00,0x08,0xc3,0x02,0xe2,0xa1,0xd0,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x45,0x00,0x7f,0x00,0x40,0x14,0xa3,0x00,0x82,0x34,0x29,0x00,0x82,0x34,
+0xa6,0x03,0xa2,0x10,0xa0,0x00,0x82,0x34,0x1e,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x00,0x0f,0x42,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,0x3b,0x04,0x83,0x10,
+0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x24,0x45,0x04,0x82,0x10,0x00,0x00,0x00,0x00,
+0x03,0x00,0x02,0x24,0xff,0x03,0x82,0x10,0x00,0x00,0x00,0x00,0x15,0x51,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xf1,0x04,0x3c,
+0x02,0x00,0x82,0x34,0x0a,0xfd,0xa2,0x10,0x2b,0x10,0x45,0x00,0x1c,0x01,0x40,0x14,
+0x04,0x00,0x82,0x34,0x44,0x03,0xa4,0x10,0x26,0xb0,0x06,0x3c,0x01,0x00,0x82,0x34,
+0x04,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x00,0xff,0x42,0x32,0x02,0xf2,0x02,0x00,
+0xba,0x03,0xc0,0x13,0x25,0xb0,0x05,0x3c,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94,
+0xb0,0x03,0xa6,0x34,0xff,0xff,0xca,0x27,0xff,0xff,0x74,0x30,0x1b,0x00,0x9e,0x02,
+0x02,0x00,0xc0,0x17,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xd4,0xac,
+0x78,0x1b,0x68,0x26,0x01,0x00,0x02,0x24,0xef,0x0a,0x02,0xa1,0x80,0xff,0x02,0x24,
+0x4f,0x00,0xab,0x34,0x9e,0x00,0xac,0x34,0xf2,0x0a,0x09,0x95,0x44,0x00,0xa7,0x34,
+0xd8,0x00,0xa5,0x34,0x12,0xa0,0x00,0x00,0x80,0x22,0x14,0x00,0x00,0xf8,0x84,0x24,
+0x18,0x00,0xd4,0x03,0xff,0xff,0x5e,0x31,0x00,0x19,0x1e,0x00,0x25,0x18,0x62,0x00,
+0x26,0xb0,0x02,0x3c,0x00,0x00,0xde,0xac,0x7c,0x00,0x42,0x34,0x00,0x00,0x63,0xa1,
+0x00,0x00,0xd4,0xac,0x00,0x00,0x94,0xa5,0x42,0xa1,0x04,0x00,0x00,0x00,0xd4,0xac,
+0x00,0x00,0x54,0xa4,0x00,0x00,0xe3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,
+0x00,0x00,0xe3,0xa4,0x00,0x00,0xe4,0x94,0x12,0x68,0x00,0x00,0x23,0x48,0x2d,0x01,
+0x00,0x02,0x84,0x34,0xf4,0x0a,0x09,0xa5,0x00,0x00,0xe4,0xa4,0x00,0x00,0xa2,0x90,
+0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x35,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,
+0xac,0x00,0x40,0x14,0x12,0x00,0xc2,0x34,0xac,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0xa2,0x00,0x2d,0x03,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xc2,0x34,
+0xbf,0xfc,0xa2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0x62,0x26,0x83,0x0b,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x26,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0xd7,0x00,0x40,0x14,0x12,0x00,0xc2,0x34,
+0x03,0x00,0x82,0x34,0x23,0x03,0xa2,0x10,0x07,0x00,0xc2,0x34,0xa8,0xfc,0xa2,0x14,
+0x00,0x00,0x00,0x00,0x34,0x59,0x00,0x0c,0x21,0x20,0x40,0x02,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x5f,0x01,0xa2,0x10,0x2b,0x10,0x45,0x00,0x01,0x01,0x40,0x14,
+0x78,0x1b,0x63,0x26,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0xff,0x63,0x34,0x24,0x18,0x43,0x02,0x00,0x00,0x45,0x8c,0x02,0xf2,0x03,0x00,
+0x21,0x52,0x00,0x0c,0x21,0x20,0xc0,0x03,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x9e,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0xfb,0x00,0x40,0x14,0x24,0x00,0x82,0x34,
+0x19,0x00,0x82,0x34,0x8f,0xfc,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0xc0,0x02,0x62,0x34,0x00,0x00,0x40,0xac,0x94,0x0e,0x64,0x34,0x9c,0x0e,0x62,0x34,
+0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x00,0x00,0x89,0x8c,0x78,0x1b,0x6f,0x26,
+0x00,0x00,0x4b,0x8c,0x00,0x00,0xac,0x8c,0x00,0x00,0xc4,0x8c,0xb4,0x0e,0x62,0x34,
+0x0c,0x00,0xe5,0x8d,0x10,0x00,0xe6,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,
+0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,0x24,0x48,0x27,0x01,0x24,0x20,0x87,0x00,
+0x00,0x00,0x4d,0x8c,0x24,0x30,0xc8,0x00,0x02,0x4c,0x09,0x00,0x24,0x28,0xa8,0x00,
+0x02,0x24,0x04,0x00,0xcc,0x0e,0x68,0x34,0xf0,0xff,0x02,0x3c,0xc4,0x0e,0x63,0x34,
+0xff,0x03,0x42,0x34,0x25,0x28,0xa9,0x00,0x25,0x30,0xc4,0x00,0x00,0x00,0x69,0x8c,
+0x08,0x00,0xe4,0x8d,0x00,0x00,0x0e,0x8d,0x24,0x58,0x67,0x01,0x24,0x50,0x47,0x01,
+0x24,0x30,0xc2,0x00,0x24,0x28,0xa2,0x00,0x82,0x59,0x0b,0x00,0x82,0x51,0x0a,0x00,
+0x0f,0xc0,0x03,0x3c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,
+0x25,0x28,0xab,0x00,0x25,0x30,0xca,0x00,0x24,0x60,0x87,0x01,0x24,0x68,0xa7,0x01,
+0xff,0x00,0x08,0x3c,0x24,0x20,0x82,0x00,0x24,0x30,0xc3,0x00,0x24,0x28,0xa3,0x00,
+0x24,0x70,0xc7,0x01,0x00,0x61,0x0c,0x00,0x00,0x69,0x0d,0x00,0x24,0x48,0x27,0x01,
+0x00,0xff,0x03,0x35,0x00,0x20,0x02,0x3c,0x25,0x20,0x82,0x00,0x25,0x28,0xac,0x00,
+0x25,0x30,0xcd,0x00,0x02,0x4c,0x09,0x00,0x02,0x74,0x0e,0x00,0x24,0x18,0x43,0x02,
+0x08,0x00,0xe4,0xad,0x0c,0x00,0xe5,0xad,0x10,0x00,0xe6,0xad,0x14,0x00,0xe9,0xa5,
+0x55,0x03,0x60,0x10,0x16,0x00,0xee,0xa5,0x24,0x10,0x48,0x02,0x02,0x14,0x02,0x00,
+0x02,0x1a,0x12,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,0x78,0x1b,0x62,0x26,
+0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x92,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,
+0x2b,0x10,0x45,0x00,0x82,0x00,0x40,0x14,0xaf,0x00,0x82,0x34,0xab,0x00,0x82,0x34,
+0x2b,0xfc,0xa2,0x14,0x00,0x00,0x00,0x00,0x54,0x5a,0x00,0x0c,0x21,0x20,0x40,0x02,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x3d,0x02,0xa4,0x10,0x2b,0x10,0x85,0x00,
+0x87,0x00,0x40,0x14,0x78,0x1b,0x62,0x26,0x18,0x00,0x62,0x34,0x20,0xfc,0xa2,0x14,
+0x00,0x00,0x00,0x00,0xb1,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x00,0xff,0x03,0x3c,0x0f,0x00,0x62,0x34,0x0d,0x02,0xa2,0x10,
+0x2b,0x10,0x45,0x00,0x70,0x00,0x40,0x14,0x10,0x00,0x62,0x34,0x1a,0x00,0xc2,0x34,
+0x14,0xfc,0xa2,0x14,0x25,0xb0,0x02,0x3c,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,
+0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x03,0x24,0x28,0x03,0xc3,0x13,
+0x78,0x1b,0x62,0x26,0x02,0x00,0xc2,0x2b,0x1f,0x03,0x40,0x14,0x03,0x00,0x02,0x24,
+0x19,0x03,0xc2,0x13,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x26,0x7c,0x0b,0x44,0x94,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0xcd,0x01,0xa2,0x10,0x2b,0x10,0xa2,0x00,0x7b,0x00,0x40,0x14,
+0x02,0x14,0x12,0x00,0x08,0x00,0x82,0x34,0xfa,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x00,0xff,0x42,0x32,0x02,0x92,0x02,0x00,0x05,0x00,0x40,0x12,0x21,0x20,0x00,0x00,
+0x01,0x00,0x02,0x24,0x02,0x00,0x42,0x12,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,
+0x95,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0xe8,0x01,0xa2,0x10,0x2b,0x10,0xa2,0x00,0x68,0x02,0x40,0x14,0x00,0x00,0x00,0x00,
+0xe8,0xfb,0xa8,0x14,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x05,0x3c,0xc4,0x02,0xa3,0x34,
+0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x90,0x82,0x00,
+0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0xdd,0xfb,0x60,0x10,0x00,0xb0,0x02,0x3c,
+0x25,0x90,0x42,0x02,0x00,0x00,0x54,0x8e,0xc8,0x02,0xa2,0x34,0x00,0x00,0x54,0xac,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x75,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,
+0x66,0x00,0x40,0x14,0x02,0x1c,0x12,0x00,0x1f,0x00,0x68,0x30,0xc0,0x10,0x08,0x00,
+0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x25,0xb0,0x04,0x3c,0x21,0x10,0x48,0x00,
+0x02,0x80,0x03,0x3c,0xc8,0x02,0x85,0x34,0x78,0x1b,0x63,0x24,0xc4,0x02,0x84,0x34,
+0x80,0x10,0x02,0x00,0x00,0x00,0x94,0x8c,0x21,0x48,0x43,0x00,0x00,0x00,0xa7,0x8c,
+0x21,0x58,0x80,0x00,0x21,0x28,0x00,0x00,0xff,0x00,0x0a,0x24,0x29,0xb0,0x06,0x3c,
+0x21,0x20,0xa3,0x00,0xf0,0x04,0x82,0x90,0x00,0x00,0x00,0x00,0x6a,0x02,0x4a,0x10,
+0x00,0x00,0x00,0x00,0x68,0x02,0x48,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x24,
+0x08,0x00,0xa2,0x28,0xf6,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,0x08,0x00,0x02,0x24,
+0xb3,0xfb,0xa2,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0xff,0x03,0x24,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0xab,0xfb,0xa2,0x14,0x00,0x00,0x00,0x00,0xe5,0x50,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x00,0xff,0x43,0x32,0x00,0xff,0x02,0x34,0x5f,0x00,0x62,0x14,0x78,0x1b,0x62,0x26,
+0x78,0x1b,0x63,0x26,0xff,0xff,0x02,0x34,0x86,0x48,0x00,0x08,0xec,0x25,0x62,0xac,
+0x04,0x24,0x43,0x8c,0xfd,0xff,0x04,0x24,0x24,0x18,0x64,0x00,0x01,0x00,0x63,0x34,
+0x86,0x48,0x00,0x08,0x04,0x24,0x43,0xac,0x96,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,
+0x78,0x1b,0x65,0x26,0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x12,0x01,0x04,0x3c,0x25,0xb0,0x02,0x3c,0x0c,0x09,0x42,0x34,
+0x13,0x13,0x84,0x34,0xd8,0x02,0xa3,0xac,0x00,0x00,0x44,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x43,0x32,
+0xff,0x00,0x5e,0x30,0x04,0x00,0xc0,0x13,0x02,0x92,0x03,0x00,0x01,0x00,0x02,0x24,
+0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x95,0x42,0x00,0x0c,
+0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xe3,0x44,0x00,0x0c,0x21,0x20,0x40,0x02,
+0xff,0xff,0x10,0x36,0x24,0xa0,0x50,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
+0x00,0x00,0x54,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x1f,0x00,0x68,0x30,
+0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00,
+0x80,0x10,0x02,0x00,0x78,0x1b,0x64,0x26,0x21,0x30,0x44,0x00,0x90,0x11,0xc3,0x90,
+0x0f,0x00,0x02,0x24,0x02,0x29,0x03,0x00,0xaf,0xff,0xa2,0x10,0x21,0x18,0xa4,0x00,
+0xf0,0x04,0x62,0x90,0x00,0x00,0x00,0x00,0xab,0xff,0x48,0x14,0xc0,0x20,0x05,0x00,
+0xff,0xff,0x02,0x24,0xf0,0x04,0x62,0xa0,0x90,0x11,0xc3,0x8c,0x29,0xb0,0x02,0x3c,
+0x21,0x20,0x82,0x00,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x34,0xc4,0x02,0x42,0x34,
+0x90,0x11,0xc3,0xac,0x00,0x00,0x80,0xac,0x04,0x00,0x80,0xac,0x00,0x00,0x45,0xac,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02,
+0x25,0xb0,0x03,0x3c,0x02,0x92,0x02,0x00,0x21,0x10,0x43,0x02,0x00,0x00,0x54,0x8c,
+0xc4,0x02,0x63,0x34,0x00,0x00,0x74,0xac,0x00,0x00,0x54,0x8c,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x78,0x1b,0x62,0x26,0x86,0x48,0x00,0x08,0xec,0x25,0x40,0xac,
+0xdb,0x02,0xe3,0x90,0x50,0x0c,0x02,0x35,0x21,0x28,0x00,0x00,0x00,0x00,0x43,0xa0,
+0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0xa2,0x24,0x78,0x1b,0x62,0x26,0xdb,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,
+0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x78,0x1b,0x65,0x26,0xe8,0x02,0xa3,0x8c,0x00,0x40,0x04,0x3c,0xff,0x7f,0x02,0x3c,
+0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xac,0x48,0x00,0x08,
+0xe8,0x02,0xa3,0xac,0x00,0xff,0x62,0x34,0x24,0x10,0x42,0x02,0x21,0xfb,0x40,0x10,
+0x25,0xb0,0x02,0x3c,0x08,0x03,0xe5,0x90,0x24,0x18,0x43,0x02,0x00,0xff,0x44,0x32,
+0x02,0x1c,0x03,0x00,0x02,0x22,0x04,0x00,0x00,0x01,0xa5,0x34,0xfb,0xff,0x66,0x24,
+0xfb,0xff,0x82,0x24,0x23,0x03,0xe2,0xa0,0x08,0x03,0xe5,0xac,0x21,0x03,0xe6,0xa0,
+0x20,0x03,0xe3,0xa0,0x86,0x48,0x00,0x08,0x22,0x03,0xe4,0xa0,0x07,0x49,0x00,0x08,
+0x01,0x00,0x04,0x24,0xdd,0x48,0x00,0x08,0x01,0x00,0x04,0x24,0x07,0x49,0x00,0x08,
+0x02,0x00,0x04,0x24,0xdd,0x48,0x00,0x08,0x02,0x00,0x04,0x24,0xc4,0x02,0x23,0x36,
+0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x90,0x82,0x00,
+0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0x01,0xfb,0x60,0x10,0xc8,0x02,0x22,0x36,
+0x00,0x00,0x54,0x8c,0x00,0xb0,0x03,0x3c,0x25,0x90,0x43,0x02,0x00,0x00,0x54,0xae,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27,
+0x8b,0x49,0x00,0x08,0x78,0x1b,0x62,0x26,0x76,0x52,0x00,0x0c,0x10,0x00,0xeb,0xad,
+0x73,0x49,0x00,0x08,0x78,0x1b,0x63,0x26,0x24,0x20,0x43,0x02,0x5b,0x52,0x00,0x0c,
+0x02,0x24,0x04,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0xe2,0x90,
+0x00,0x00,0x00,0x00,0x31,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x34,
+0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x02,0x24,0x21,0x20,0xc0,0x03,
+0x82,0x0b,0xe2,0xa0,0x2c,0x22,0x00,0x0c,0x83,0x0b,0xfe,0xa0,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x04,0x24,0xe2,0x8c,0xfe,0xff,0x03,0x24,0x02,0x00,0x42,0x34,0x24,0x10,0x43,0x00,
+0x86,0x48,0x00,0x08,0x04,0x24,0xe2,0xac,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,
+0xb8,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x9c,0x12,0x00,0x0c,0xe8,0x03,0x04,0x24,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x24,0x00,0x04,0x24,0xe3,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x54,0x30,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,
+0x64,0x00,0x04,0x24,0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xa0,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x08,0x00,0xe3,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x86,0x48,0x00,0x08,0x08,0x00,0xe3,0xac,0xc8,0x02,0xe4,0x8c,
+0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,
+0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00,0x25,0x20,0x83,0x00,0xc8,0x02,0xe4,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x76,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x62,0x34,
+0xc4,0x02,0x24,0x36,0x00,0x00,0x94,0x8c,0x24,0x10,0x42,0x02,0x02,0x92,0x02,0x00,
+0x21,0x18,0x51,0x02,0x00,0x00,0x74,0xac,0x00,0x00,0x74,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x94,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0xe3,0x90,
+0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x29,0xb0,0x02,0x3c,
+0x00,0x00,0x40,0xac,0x04,0x00,0x44,0x34,0x08,0x00,0x45,0x34,0x0c,0x00,0x46,0x34,
+0x3c,0x00,0x43,0x34,0x10,0x00,0x47,0x34,0x14,0x00,0x48,0x34,0x18,0x00,0x49,0x34,
+0x1c,0x00,0x4a,0x34,0x20,0x00,0x4b,0x34,0x24,0x00,0x4c,0x34,0x28,0x00,0x4d,0x34,
+0x2c,0x00,0x4e,0x34,0x30,0x00,0x4f,0x34,0x34,0x00,0x50,0x34,0x38,0x00,0x51,0x34,
+0x02,0x80,0x02,0x3c,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0xff,0xff,0x04,0x24,
+0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,0x78,0x1b,0x46,0x24,
+0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad,
+0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad,
+0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x00,0x00,0x60,0xac,0x21,0x18,0xa6,0x00,
+0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c,
+0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04,
+0x94,0x00,0x63,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x24,0x20,0x43,0x02,
+0xc6,0x15,0x00,0x0c,0x02,0x24,0x04,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x6e,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x02,0x1a,0x08,0x00,0xff,0x00,0x02,0x24,0x2b,0x01,0x62,0x10,0x25,0xb0,0x05,0x3c,
+0x0e,0x00,0x60,0x14,0x00,0xcc,0x02,0x34,0x25,0xb0,0x04,0x3c,0x64,0x03,0x84,0x34,
+0x78,0x1b,0x67,0x26,0x00,0x00,0x85,0x94,0xe8,0x02,0xe6,0x8c,0xff,0xef,0x02,0x3c,
+0xff,0xfe,0x03,0x24,0xff,0xff,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x30,0xc2,0x00,
+0x00,0x00,0x85,0xa4,0xe8,0x02,0xe6,0xac,0x00,0xcc,0x02,0x34,0x39,0xfa,0x02,0x15,
+0x25,0xb0,0x02,0x3c,0x78,0x1b,0x62,0x26,0xe8,0x02,0x43,0x8c,0x00,0x10,0x04,0x3c,
+0x25,0x18,0x64,0x00,0x86,0x48,0x00,0x08,0xe8,0x02,0x43,0xac,0x24,0x10,0x43,0x02,
+0x02,0xf4,0x02,0x00,0x00,0xff,0x43,0x32,0x04,0x00,0xc0,0x13,0x02,0x92,0x03,0x00,
+0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,
+0x25,0xb0,0x10,0x3c,0x95,0x42,0x00,0x0c,0xc4,0x02,0x10,0x36,0x00,0x00,0x14,0x8e,
+0x0f,0x00,0x11,0x3c,0x21,0x20,0x40,0x02,0x21,0x30,0x80,0x02,0xb8,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x21,0x20,0x40,0x02,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x00,0x00,0x02,0xae,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0xff,0x62,0x34,
+0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x78,0x1b,0x63,0x26,0x83,0x0b,0x7e,0xa0,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xff,0x00,0x02,0x24,0x56,0x01,0x63,0x34,
+0x00,0x00,0x62,0xa4,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x86,0x48,0x00,0x08,
+0x80,0x43,0x44,0xa0,0x24,0x10,0x43,0x02,0x02,0xa4,0x02,0x00,0x00,0xff,0x43,0x32,
+0x07,0x00,0x82,0x2e,0xfe,0xf9,0x40,0x10,0x02,0xf2,0x03,0x00,0x02,0x80,0x04,0x3c,
+0xbc,0xaf,0x83,0x24,0x80,0x10,0x14,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
+0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26,
+0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x10,0x00,0x04,0x3c,0x25,0x18,0x64,0x00,0x86,0x48,0x00,0x08,0xd8,0x02,0xa3,0xac,
+0xe4,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x78,0x1b,0x65,0x26,0x04,0x24,0xa2,0x8c,0xfd,0xff,0x03,0x24,0xfe,0xff,0x04,0x24,
+0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,0x86,0x48,0x00,0x08,0x04,0x24,0xa2,0xac,
+0x1f,0x00,0x48,0x30,0xc0,0x18,0x08,0x00,0x21,0x18,0x68,0x00,0x00,0x0f,0x45,0x32,
+0x80,0x18,0x03,0x00,0x02,0x2a,0x05,0x00,0x78,0x1b,0x64,0x26,0x25,0xb0,0x02,0x3c,
+0x21,0x18,0x68,0x00,0x21,0x30,0xa4,0x00,0xc8,0x02,0x47,0x34,0x80,0x18,0x03,0x00,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0x8c,0x21,0x18,0x64,0x00,0x00,0x00,0xe7,0x8c,
+0xf0,0x04,0xc8,0xa0,0x90,0x11,0x64,0x8c,0x0f,0xff,0x02,0x24,0xc0,0x30,0x05,0x00,
+0x24,0x20,0x82,0x00,0x00,0x29,0x05,0x00,0x29,0xb0,0x02,0x3c,0x21,0x30,0xc2,0x00,
+0x25,0x20,0x85,0x00,0x90,0x11,0x64,0xac,0x00,0x00,0xd4,0xac,0x04,0x00,0xc7,0xac,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x65,0x34,0x24,0x28,0x45,0x02,
+0x25,0xb0,0x04,0x3c,0x02,0x2a,0x05,0x00,0x94,0x00,0x83,0x34,0x40,0x11,0x05,0x00,
+0x00,0x00,0x65,0xa4,0xc0,0xff,0x54,0x24,0x7c,0x00,0xcc,0x34,0x04,0x00,0x07,0x24,
+0x9a,0x00,0x88,0x34,0x98,0x00,0x89,0x34,0x96,0x00,0x8a,0x34,0x7a,0x00,0xc6,0x34,
+0xb0,0x03,0x8b,0x34,0x00,0x04,0x02,0x24,0xa0,0x00,0x03,0x24,0x00,0x00,0x02,0xa5,
+0x44,0x00,0x84,0x34,0x00,0x00,0x23,0xa5,0x00,0x00,0x47,0xa5,0x00,0x00,0xc7,0xa0,
+0x00,0x00,0x74,0xad,0x00,0x00,0x94,0xa5,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,
+0x78,0x1b,0x66,0x26,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,
+0xf2,0x0a,0xc5,0xa4,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x24,0x20,0x43,0x02,0x00,0xff,0x45,0x32,0x02,0x24,0x04,0x00,
+0x97,0x50,0x00,0x0c,0x02,0x2a,0x05,0x00,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,
+0x00,0x00,0x62,0xa0,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,
+0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x78,0x1b,0x63,0x26,
+0x21,0x20,0xc0,0x03,0x2c,0x22,0x00,0x0c,0x82,0x0b,0x60,0xa0,0xa9,0x4d,0x00,0x08,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x63,0x26,0x04,0x24,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x34,0x86,0x48,0x00,0x08,0x04,0x24,0x62,0xac,0x6f,0x0b,0x00,0x0c,
+0x21,0x20,0xc0,0x03,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x5d,0x52,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x1c,0x12,0x00,
+0x00,0x1f,0x42,0x32,0x78,0x1b,0x70,0x26,0x02,0xa2,0x02,0x00,0x3f,0x00,0x67,0x30,
+0xc1,0x02,0x07,0xa2,0xbc,0x02,0x14,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x22,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x21,0xa0,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xac,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x03,0x00,0x02,0x92,
+0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x86,0x48,0x00,0x08,0x03,0x00,0x02,0xa2,
+0x24,0x18,0x43,0x02,0x02,0x44,0x03,0x00,0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00,0x00,0xff,0x44,0x32,0x80,0x10,0x02,0x00,
+0x78,0x1b,0x63,0x26,0x21,0x10,0x43,0x00,0x02,0xa1,0x04,0x00,0x80,0x11,0x54,0xac,
+0x86,0x48,0x00,0x08,0x84,0x11,0x54,0xac,0xf0,0x04,0x88,0xa0,0x90,0x11,0x22,0x8d,
+0x0f,0x00,0xa3,0x30,0x0f,0xff,0x04,0x24,0x00,0x19,0x03,0x00,0x24,0x10,0x44,0x00,
+0x25,0x10,0x43,0x00,0x90,0x11,0x22,0xad,0x00,0x00,0xd4,0xac,0x04,0x00,0xc7,0xac,
+0x00,0x00,0x65,0xad,0xd2,0x4c,0x00,0x08,0x08,0x00,0x02,0x24,0x4f,0x00,0xa2,0x34,
+0x9e,0x00,0xa3,0x34,0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,0x94,0x00,0xa2,0x34,
+0x00,0x00,0x43,0x94,0x9a,0x00,0xa4,0x34,0x98,0x00,0xa6,0x34,0xff,0xff,0x74,0x30,
+0x80,0x12,0x14,0x00,0x00,0xf8,0x42,0x24,0x42,0xa1,0x02,0x00,0x00,0x14,0x02,0x24,
+0x00,0x00,0x82,0xa4,0x26,0xb0,0x02,0x3c,0xb0,0x03,0xa7,0x34,0xa0,0x80,0x03,0x24,
+0x7c,0x00,0x42,0x34,0x00,0x00,0xc3,0xa4,0x44,0x00,0xa4,0x34,0x00,0x00,0xf4,0xac,
+0x00,0x00,0x54,0xa4,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,0xd8,0x00,0xa5,0x34,
+0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,0x78,0x1b,0x66,0x26,
+0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0xbf,0xff,0x02,0x24,
+0xf4,0x0a,0xc0,0xa4,0x24,0x18,0x62,0x00,0xef,0x0a,0xc0,0xa0,0x00,0x00,0xa3,0xa0,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x64,0x03,0xa5,0x34,0x78,0x1b,0x66,0x26,
+0x00,0x00,0xa3,0x94,0xe8,0x02,0xc4,0x8c,0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x20,0x82,0x00,0x00,0x01,0x63,0x34,0x00,0x00,0xa3,0xa4,0x4c,0x4e,0x00,0x08,
+0xe8,0x02,0xc4,0xac,0x15,0x51,0x00,0x0c,0x03,0x00,0x04,0x24,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00,
+0x78,0x1b,0x63,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x8c,0x11,0x44,0x8c,
+0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08,
+0x25,0xb0,0x02,0x3c,0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,
+0x21,0x10,0x48,0x00,0x78,0x1b,0x63,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
+0x88,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x1e,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1,
+0x45,0x4c,0x00,0x08,0xc3,0x02,0xe2,0xa1,0x78,0x1b,0x62,0x26,0x7e,0x0b,0x44,0x94,
+0x43,0x4b,0x00,0x08,0x25,0xb0,0x03,0x3c,0xe3,0xfc,0xc0,0x17,0x25,0xb0,0x03,0x3c,
+0x78,0x1b,0x62,0x26,0x78,0x0b,0x44,0x94,0x44,0x4b,0x00,0x08,0xc4,0x02,0x63,0x34,
+0x7a,0x0b,0x44,0x94,0x43,0x4b,0x00,0x08,0x25,0xb0,0x03,0x3c,0x2b,0x4a,0x00,0x08,
+0x01,0x00,0x04,0x24,0x2b,0x4a,0x00,0x08,0x02,0x00,0x04,0x24,0x15,0x51,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00,
+0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x36,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x15,0x51,0x00,0x0c,0x02,0x00,0x04,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x35,0x03,0x64,0x90,
+0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,
+0x21,0x18,0x62,0x00,0x34,0x03,0x64,0x90,0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x32,0x03,0x64,0x94,
+0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,
+0x21,0x18,0x62,0x00,0x30,0x03,0x64,0x94,0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,
+0x00,0x11,0x1e,0x00,0x78,0x1b,0x63,0x26,0x21,0x10,0x43,0x00,0x2c,0x03,0x44,0x8c,
+0xb1,0x4f,0x00,0x08,0x42,0x26,0x04,0x00,0x00,0x11,0x1e,0x00,0x78,0x1b,0x63,0x26,
+0x21,0x10,0x43,0x00,0x2f,0x03,0x44,0x90,0xb1,0x4f,0x00,0x08,0x01,0x00,0x84,0x30,
+0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,0x04,0x30,0x86,0x00,
+0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x78,0x3f,0x42,0x24,0x18,0x03,0xa5,0x34,
+0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,
+0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
+0x25,0xb0,0x03,0x3c,0xd4,0x3f,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac,
+0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,0x21,0x20,0x00,0x00,
+0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,0x07,0x00,0x04,0x24,
+0xde,0x4f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0x10,0x40,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xac,
+0x08,0x00,0xe0,0x03,0x8c,0x43,0x80,0xac,0x02,0x80,0x03,0x3c,0x98,0x41,0x62,0x8c,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
+0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x80,0x10,0x00,
+0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
+0x90,0x11,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,0xff,0xff,0x42,0x34,
+0xf8,0xff,0x03,0x24,0x88,0x11,0x02,0xae,0x84,0x01,0x46,0x36,0x24,0x28,0xa3,0x00,
+0xff,0xfe,0x02,0x24,0x00,0x00,0xc7,0x8c,0x24,0x28,0xa2,0x00,0xff,0xef,0x03,0x24,
+0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x28,0xa2,0x00,
+0x8c,0x11,0x07,0xae,0x90,0x11,0x05,0xae,0x96,0x15,0x00,0x0c,0x21,0x88,0x80,0x00,
+0x92,0x11,0x02,0x92,0x21,0x88,0x32,0x02,0x1c,0x00,0xbf,0x8f,0x60,0x01,0x22,0xa2,
+0x18,0x00,0xb2,0x8f,0x7c,0x11,0x00,0xae,0x60,0x11,0x00,0xae,0x64,0x11,0x00,0xae,
+0x68,0x11,0x00,0xae,0x6c,0x11,0x00,0xae,0x70,0x11,0x00,0xae,0x74,0x11,0x00,0xae,
+0x78,0x11,0x00,0xae,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x90,0x11,0x43,0x8c,0x25,0xb0,0x05,0x3c,
+0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30,
+0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30,
+0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,
+0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,
+0x6c,0x50,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,
+0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,
+0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,
+0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,
+0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,
+0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,
+0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,
+0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,
+0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,
+0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,
+0x8d,0x50,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,
+0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
+0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c,0x90,0x11,0x43,0x8c,
+0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90,
+0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00,
+0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,
+0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,
+0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0xba,0x50,0x00,0x08,0x01,0x00,0x07,0x24,
+0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,
+0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,
+0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,
+0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,
+0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,
+0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,
+0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,
+0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,
+0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,
+0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,
+0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0xdb,0x50,0x00,0x08,0xff,0x00,0x44,0x30,
+0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xd8,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c,0x78,0x1b,0x52,0x24,
+0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf,
+0xff,0x1f,0x73,0x34,0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02,0x19,0x50,0x00,0x0c,
+0x21,0x20,0x20,0x02,0x90,0x11,0x02,0x8e,0x21,0x28,0x00,0x00,0x24,0x10,0x53,0x00,
+0x00,0x20,0x42,0x34,0x90,0x11,0x02,0xae,0x92,0x11,0x03,0x92,0x00,0x00,0x00,0x00,
+0x80,0x18,0x03,0x00,0x21,0x18,0x72,0x00,0xf8,0x04,0x64,0x8c,0x6c,0x05,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00,0x5c,0x11,0x02,0xae,
+0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28,0xce,0x11,0x40,0xa0,
+0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae,0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,
+0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x78,0x1b,0x46,0x24,0x3c,0x00,0xbf,0xaf,
+0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
+0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0xec,0x25,0xc2,0x8c,0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30,0xff,0xff,0x42,0x38,
+0x0b,0x18,0x02,0x00,0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf,0xec,0x25,0xc4,0xac,
+0xb9,0x00,0xa0,0x11,0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c,0xdc,0xad,0x45,0x24,
+0x94,0x04,0xc4,0x24,0x36,0x51,0x00,0x08,0x21,0x88,0x00,0x00,0x01,0x00,0x31,0x26,
+0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,0x01,0x00,0x84,0x24,
+0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0xf7,0xff,0x40,0x10,
+0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,
+0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4a,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x74,0xab,0x6c,0x24,0xfc,0xaa,0x4b,0x24,
+0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,
+0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,
+0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,
+0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
+0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,
+0xaf,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x78,0x1b,0x48,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x70,0xae,0x69,0x24,0xfc,0xad,0x47,0x24,0x21,0x88,0x00,0x00,
+0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,
+0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,0x04,0x00,0x22,0x2a,
+0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x70,0xae,0x68,0x24,
+0xfc,0xad,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,0x21,0x10,0x88,0x00,
+0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,0x01,0x00,0x31,0x26,
+0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,0x1d,0x00,0x22,0x2a,
+0xf8,0x04,0x83,0xac,0xf4,0xff,0x40,0x14,0x6c,0x05,0x85,0xac,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x56,0x24,0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02,0xff,0x1f,0x57,0x34,
+0x21,0x88,0x00,0x00,0x21,0xa0,0x00,0x00,0x93,0x51,0x00,0x08,0x21,0x90,0xc0,0x02,
+0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x3d,0x00,0x40,0x10,
+0x94,0x00,0x94,0x26,0x90,0x11,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00,
+0x01,0x00,0x53,0x30,0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c,
+0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x88,0x11,0x43,0x8e,
+0x21,0x20,0x20,0x02,0x24,0x28,0xa3,0x00,0x96,0x15,0x00,0x0c,0x8c,0x11,0x45,0xae,
+0x92,0x11,0x44,0x92,0x70,0x15,0x00,0x0c,0xff,0x00,0x25,0x32,0x90,0x11,0x42,0x8e,
+0x00,0x00,0x00,0x00,0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x42,0xae,
+0x92,0x11,0x50,0x92,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02,0x86,0x15,0x00,0x0c,
+0x80,0x80,0x10,0x00,0x21,0x80,0x16,0x02,0x60,0x11,0x40,0xae,0x64,0x11,0x40,0xae,
+0x68,0x11,0x40,0xae,0x6c,0x11,0x40,0xae,0x70,0x11,0x40,0xae,0x74,0x11,0x40,0xae,
+0x78,0x11,0x40,0xae,0x7c,0x11,0x40,0xae,0xf8,0x04,0x04,0x8e,0x6c,0x05,0x03,0x8e,
+0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00,
+0x04,0x00,0x04,0x24,0x0a,0xa8,0x82,0x00,0x5c,0x11,0x43,0xae,0x21,0x20,0x9e,0x02,
+0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xce,0x11,0x40,0xa0,
+0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,
+0x20,0x00,0x22,0x2a,0xec,0x11,0x80,0xac,0x94,0x00,0x52,0x26,0xc5,0xff,0x40,0x14,
+0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x00,0x00,0x55,0xa0,
+0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x02,0x80,0x03,0x3c,
+0x78,0x1b,0x62,0x24,0xec,0x25,0x40,0xac,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0xdc,0xad,0x45,0x24,
+0x94,0x04,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90,
+0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14,
+0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4a,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x98,0xac,0x6c,0x24,0x38,0xab,0x4b,0x24,0x21,0x88,0x00,0x00,
+0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,
+0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
+0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,
+0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
+0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,
+0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x70,0xae,0x68,0x24,
+0xfc,0xad,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00,
+0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,
+0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,
+0x6c,0x05,0x66,0xac,0x86,0x51,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27,
+0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00,
+0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00,
+0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x88,0x11,0x00,
+0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,
+0x90,0x11,0x30,0x8e,0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24,0x2b,0x18,0x03,0x00,
+0x00,0x10,0x10,0x36,0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00,0x00,0x04,0x82,0x30,
+0x25,0x80,0x03,0x02,0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24,0x24,0x80,0x03,0x02,
+0xc0,0x10,0x02,0x00,0x25,0x80,0x02,0x02,0x88,0x11,0x25,0xae,0x90,0x11,0x30,0xae,
+0xf3,0x15,0x00,0x0c,0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02,
+0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c,
+0x80,0x18,0x03,0x00,0x90,0x11,0x30,0xae,0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c,
+0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,0x96,0x15,0x00,0x0c,0x8c,0x11,0x22,0xae,
+0x92,0x11,0x24,0x92,0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x70,0x15,0x00,0x08,
+0x28,0x00,0xbd,0x27,0x19,0x50,0x00,0x08,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x43,0x24,0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,
+0x00,0x10,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x23,0x10,0xa4,0x00,
+0x2b,0x18,0xa4,0x00,0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03,0x0b,0x10,0x83,0x00,
+0x20,0xff,0xbd,0x27,0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf,0xd8,0x00,0xbe,0xaf,
+0xd4,0x00,0xb7,0xaf,0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf,0xc4,0x00,0xb3,0xaf,
+0xc0,0x00,0xb2,0xaf,0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf,0x21,0xa8,0x00,0x00,
+0x40,0x11,0x15,0x00,0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00,0x07,0x00,0x16,0x24,
+0xff,0xff,0xd6,0x26,0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06,0x04,0x00,0x42,0x24,
+0x01,0x00,0xb5,0x26,0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14,0x40,0x11,0x15,0x00,
+0x25,0xb0,0x10,0x3c,0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac,0x04,0x00,0x03,0x36,
+0x00,0x00,0x62,0x8c,0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c,0x08,0x0c,0x04,0x36,
+0x0f,0x00,0x11,0x3c,0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c,0x24,0x10,0x51,0x00,
+0x02,0xf4,0x02,0x00,0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,
+0xff,0xff,0x25,0x36,0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
+0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x74,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0xe0,0x0e,0x02,0x36,0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c,0xdc,0x0e,0x12,0x36,
+0x70,0x0e,0x13,0x36,0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e,0x74,0x0e,0x14,0x36,
+0x78,0x0e,0x15,0x36,0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e,0x7c,0x0e,0x16,0x36,
+0x80,0x0e,0x17,0x36,0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e,0xd4,0x0e,0x10,0x36,
+0xed,0x3f,0x11,0x3c,0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e,0xfb,0x92,0x25,0x36,
+0x88,0x00,0xa3,0xaf,0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x8c,0x00,0xa2,0xaf,
+0x00,0x00,0xe3,0x8e,0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34,0x90,0x00,0xa3,0xaf,
+0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34,0x94,0x00,0xa2,0xaf,
+0x00,0x00,0x63,0x8c,0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34,0x98,0x00,0xa3,0xaf,
+0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34,0x9c,0x00,0xa2,0xaf,
+0x00,0x00,0x63,0x8c,0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf,0x00,0x00,0x02,0x8e,
+0x25,0xb0,0x03,0x3c,0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,
+0x68,0x52,0x00,0x0c,0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02,0x68,0x52,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x21,0x20,0x60,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x21,0x20,0x80,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xa0,0x02,
+0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02,0x68,0x52,0x00,0x0c,
+0xfb,0x92,0x25,0x36,0x21,0x20,0xe0,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x02,0x80,0x02,0x3c,0x18,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,
+0x68,0x52,0x00,0x0c,0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c,0x1c,0xb0,0x63,0x24,
+0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x68,0x52,0x00,0x0c,0x21,0xb0,0x00,0x00,
+0x02,0x80,0x02,0x3c,0x20,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,
+0x68,0x52,0x00,0x0c,0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c,0x24,0xb0,0x63,0x24,
+0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x68,0x52,0x00,0x0c,0x10,0x00,0xb7,0x27,
+0x21,0x20,0x00,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c,
+0x28,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,
+0x54,0x53,0x00,0x08,0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13,0x02,0x80,0x02,0x3c,
+0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,
+0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,
+0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,
+0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,
+0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,
+0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10,0x02,0x3c,0x07,0x00,
+0xe6,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,
+0xe2,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,0x08,0x00,0x83,0x10,
+0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,0xe0,0x03,0x03,0x24,
+0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10,0x01,0x00,0x04,0x24,
+0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11,0x00,0x00,0x00,0x00,
+0xd7,0x00,0x80,0x14,0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26,0x0a,0x00,0xa2,0x2e,
+0x01,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17,0x01,0x00,0x02,0x24,
+0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0x68,0x52,0x00,0x0c,0x04,0x0c,0x64,0x36,
+0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c,0x08,0x0c,0x64,0x36,
+0x28,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c,0x80,0x80,0x05,0x3c,0x14,0x02,0x02,0x3c,
+0x48,0x01,0x45,0x34,0x68,0x52,0x00,0x0c,0x40,0x0e,0x64,0x36,0x16,0x68,0x05,0x3c,
+0xa2,0x04,0xa5,0x34,0x68,0x52,0x00,0x0c,0x44,0x0e,0x64,0x36,0x4c,0x0e,0x64,0x36,
+0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c,0x4d,0x01,0x65,0x34,
+0x68,0x52,0x00,0x0c,0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c,0xba,0x08,0xa5,0x34,
+0x68,0x52,0x00,0x0c,0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c,
+0xd1,0x28,0x05,0x24,0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c,
+0x48,0x0e,0x64,0x36,0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c,
+0x48,0x0e,0x64,0x36,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xa0,0x00,0x02,0x3c,
+0x33,0x54,0x45,0x34,0x68,0x52,0x00,0x0c,0x04,0x0c,0x64,0x36,0x08,0x0c,0x64,0x36,
+0x68,0x52,0x00,0x0c,0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c,
+0x21,0x28,0x00,0x00,0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17,0xac,0x0e,0x62,0x36,
+0x02,0x80,0x02,0x3c,0x2c,0xb0,0x42,0x24,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0x8c,
+0x20,0x08,0x63,0x34,0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c,0x00,0x01,0x65,0x34,
+0x68,0x52,0x00,0x0c,0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c,0x00,0x01,0x45,0x34,
+0x68,0x52,0x00,0x0c,0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,
+0x68,0x52,0x00,0x0c,0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,
+0x68,0x52,0x00,0x0c,0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,
+0x80,0x80,0x05,0x3c,0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34,0x68,0x52,0x00,0x0c,
+0x30,0x0e,0x44,0x36,0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34,0x68,0x52,0x00,0x0c,
+0x34,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34,0x68,0x52,0x00,0x0c,
+0x38,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34,0x68,0x52,0x00,0x0c,
+0x3c,0x0e,0x44,0x36,0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34,0x68,0x52,0x00,0x0c,
+0x40,0x0e,0x44,0x36,0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34,0x68,0x52,0x00,0x0c,
+0x44,0x0e,0x44,0x36,0x4c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24,
+0x6c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0x01,0x03,0x3c,
+0x00,0x7c,0x65,0x34,0x68,0x52,0x00,0x0c,0x50,0x0e,0x44,0x36,0x00,0x01,0x02,0x3c,
+0x00,0x48,0x45,0x34,0x68,0x52,0x00,0x0c,0x54,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,
+0x23,0xdc,0x65,0x34,0x68,0x52,0x00,0x0c,0x58,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,
+0x23,0x8c,0x45,0x34,0x68,0x52,0x00,0x0c,0x5c,0x0e,0x44,0x36,0x14,0x02,0x03,0x3c,
+0x02,0x01,0x65,0x34,0x68,0x52,0x00,0x0c,0x60,0x0e,0x44,0x36,0x16,0x28,0x05,0x3c,
+0x07,0x0d,0xa5,0x34,0x68,0x52,0x00,0x0c,0x64,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,
+0x68,0x52,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x68,0x52,0x00,0x0c,
+0x48,0x0e,0x44,0x36,0x00,0x02,0x10,0x3c,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,
+0x4c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x36,0xd1,0x28,0x05,0x36,
+0x68,0x52,0x00,0x0c,0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,
+0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x68,0x52,0x00,0x0c,0x48,0x0e,0x44,0x36,
+0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f,0x04,0x0c,0x44,0x36,
+0x68,0x52,0x00,0x0c,0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f,0x08,0x0c,0x44,0x36,
+0x68,0x52,0x00,0x0c,0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,
+0x21,0x28,0x00,0x00,0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c,
+0x2c,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0x68,0x52,0x00,0x0c,0x00,0x01,0x05,0x3c,
+0x28,0x08,0x44,0x36,0x68,0x52,0x00,0x0c,0x00,0x01,0x05,0x3c,0xac,0x0e,0x62,0x36,
+0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36,
+0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c,
+0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c,
+0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00,
+0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,
+0x02,0x34,0x06,0x00,0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24,
+0x20,0xff,0x83,0x14,0x21,0x40,0x00,0x00,0x4a,0x53,0x00,0x08,0x21,0x20,0x00,0x00,
+0x00,0x00,0x62,0x8c,0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c,0xac,0x0e,0x67,0x36,
+0xb4,0x0e,0x65,0x36,0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00,0x04,0x00,0xe4,0xae,
+0x00,0x00,0xc3,0x8c,0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,
+0x08,0x00,0xe3,0xae,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,
+0xbc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,
+0xcc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,
+0x02,0x14,0x02,0x00,0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26,0x03,0x00,0xc2,0x2e,
+0xc7,0xfe,0x40,0x14,0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f,0x00,0x00,0x00,0x00,
+0x49,0x01,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f,0x00,0x00,0x00,0x00,
+0x06,0x00,0x20,0x16,0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,
+0x29,0x00,0x40,0x10,0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02,0x71,0x52,0x00,0x0c,
+0x21,0x28,0x20,0x02,0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
+0x34,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x2c,0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x50,0x00,0xb2,0x8f,
+0x21,0x20,0x00,0x02,0x71,0x52,0x00,0x0c,0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c,
+0x09,0x00,0x40,0x10,0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,
+0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x0e,0x00,0x40,0x14,
+0x21,0x28,0x00,0x00,0x21,0x20,0x20,0x02,0x71,0x52,0x00,0x0c,0x21,0x28,0x40,0x02,
+0x03,0x00,0x42,0x2c,0xe0,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x54,0x00,0xa5,0x8f,
+0x34,0x00,0xa4,0x8f,0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,
+0xd9,0x00,0x40,0x10,0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24,0xdb,0x00,0xa2,0x10,
+0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00,0x02,0x80,0x0f,0x3c,
+0x21,0x28,0xa2,0x00,0x78,0x1b,0xec,0x25,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xa7,0x8c,
+0x0c,0x00,0x83,0x8d,0x10,0x00,0x84,0x8d,0x04,0x00,0xa8,0x8c,0x10,0x00,0xa9,0x8c,
+0x00,0xfc,0x02,0x24,0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c,0x24,0x20,0x82,0x00,
+0xff,0x03,0xc6,0x30,0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30,0xf0,0xff,0x02,0x3c,
+0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00,0xff,0x03,0x08,0x31,
+0xff,0x03,0x29,0x31,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x80,0x42,0x08,0x00,
+0x80,0x4a,0x09,0x00,0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c,0x18,0x00,0xa7,0x8c,
+0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00,0xff,0x03,0x4a,0x31,
+0xff,0x03,0x6b,0x31,0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00,0x24,0x18,0x62,0x00,
+0x00,0x5d,0x0b,0x00,0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x16,0x00,0x86,0xa5,
+0x0c,0x00,0x83,0xad,0x10,0x00,0x84,0xad,0x14,0x00,0x87,0xa5,0x78,0x1b,0xf1,0x25,
+0x10,0x00,0x22,0x8e,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x4d,0x00,0x43,0x10,
+0x25,0xb0,0x12,0x3c,0x0c,0x00,0x23,0x8e,0x80,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,
+0x00,0x02,0x62,0x30,0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00,0x03,0x00,0x40,0x10,
+0xff,0x03,0x65,0x30,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,
+0x82,0x62,0x03,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,
+0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,
+0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36,0x24,0x28,0x14,0x01,
+0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,
+0x25,0x28,0xa2,0x00,0x68,0x52,0x00,0x0c,0x25,0x28,0xa6,0x00,0x94,0x0c,0x44,0x36,
+0x00,0x00,0x85,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34,0xc0,0x03,0x10,0x32,
+0x24,0x28,0xb5,0x00,0x80,0x85,0x10,0x00,0x68,0x52,0x00,0x0c,0x25,0x28,0xb0,0x00,
+0x10,0x00,0x2c,0x8e,0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,0x82,0x2a,0x0c,0x00,
+0xff,0x03,0xa5,0x30,0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30,0x03,0x00,0x60,0x10,
+0x82,0x6d,0x02,0x00,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,
+0x02,0x65,0x0c,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,
+0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,
+0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00,
+0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,
+0x68,0x52,0x00,0x0c,0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c,
+0xc0,0x03,0x10,0x32,0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00,0x68,0x52,0x00,0x0c,
+0x25,0x28,0xb0,0x00,0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c,0x68,0x52,0x00,0x0c,
+0xe0,0x0e,0x04,0x36,0x7c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0xdc,0x0e,0x04,0x36,
+0x80,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x70,0x0e,0x04,0x36,0x84,0x00,0xa5,0x8f,
+0x68,0x52,0x00,0x0c,0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,
+0x78,0x0e,0x04,0x36,0x8c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x7c,0x0e,0x04,0x36,
+0x90,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x80,0x0e,0x04,0x36,0x94,0x00,0xa5,0x8f,
+0x68,0x52,0x00,0x0c,0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,
+0x88,0x0e,0x04,0x36,0x9c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x8c,0x0e,0x04,0x36,
+0xa0,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0xd0,0x0e,0x04,0x36,0xa4,0x00,0xa5,0x8f,
+0x68,0x52,0x00,0x0c,0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f,0x88,0x0e,0x04,0x36,
+0x68,0x52,0x00,0x0c,0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,
+0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,
+0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xff,0xff,0x05,0x36,0xe3,0x44,0x00,0x0c,
+0x1e,0x00,0x04,0x24,0x21,0x88,0x40,0x00,0xfd,0xff,0x06,0x24,0x01,0x00,0x42,0x34,
+0x24,0x30,0x46,0x00,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,
+0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x03,0x00,0x26,0x36,
+0xb8,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0xdc,0x00,0xbf,0x8f,0xd8,0x00,0xbe,0x8f,
+0xd4,0x00,0xb7,0x8f,0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f,0xc8,0x00,0xb4,0x8f,
+0xc4,0x00,0xb3,0x8f,0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f,0xb8,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24,0xff,0x00,0x02,0x24,
+0x29,0xff,0xa2,0x14,0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c,0x94,0x0e,0x62,0x34,
+0x9c,0x0e,0x64,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x02,0x80,0x0f,0x3c,
+0x00,0x00,0x49,0x8c,0x78,0x1b,0xed,0x25,0x00,0x00,0x8c,0x8c,0x00,0x00,0xae,0x8c,
+0x00,0x00,0xc7,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x00,0xa4,0x8d,0x10,0x00,0xa5,0x8d,
+0x00,0x00,0x4a,0x8c,0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,
+0x24,0x48,0x26,0x01,0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c,0x24,0x28,0xa8,0x00,
+0x24,0x20,0x88,0x00,0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34,0x02,0x4c,0x09,0x00,
+0xc4,0x0e,0x63,0x34,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x28,0xa7,0x00,
+0x25,0x20,0x89,0x00,0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01,0x00,0x00,0x03,0x8d,
+0x24,0x50,0x46,0x01,0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0x82,0x61,0x0c,0x00,
+0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8c,0x00,
+0x25,0x28,0xaa,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x28,0xa2,0x00,
+0x24,0x18,0x66,0x00,0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00,
+0x24,0x38,0xe6,0x00,0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00,0x02,0x3c,0x07,0x00,
+0x02,0x1c,0x03,0x00,0x16,0x00,0xa3,0xa5,0x0c,0x00,0xa4,0xad,0x10,0x00,0xa5,0xad,
+0xbd,0x54,0x00,0x08,0x14,0x00,0xa7,0xa5,0x30,0x00,0xb1,0x8f,0x65,0x54,0x00,0x08,
+0x21,0x20,0x00,0x02,0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,
+0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x1c,0xb6,0xe7,0x24,
+0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xb0,0x59,0xc6,0x24,
+0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x20,0x00,0xb4,0xaf,
+0x1c,0x00,0xb3,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
+0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x03,0x0d,0x64,0x34,
+0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30,0x70,0x00,0x93,0x32,
+0x63,0x00,0x60,0x12,0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32,0x00,0x00,0x82,0xa0,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24,
+0xcb,0x12,0x00,0x0c,0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36,0x95,0x42,0x00,0x0c,
+0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00,
+0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,
+0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
+0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
+0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
+0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,
+0xb8,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,
+0x27,0x00,0x60,0x16,0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
+0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x42,0x00,0x42,0x34,
+0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xff,0xff,0x02,0x24,0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
+0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,
+0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,
+0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12,0x25,0xb0,0x02,0x3c,
+0x03,0x0d,0x42,0x34,0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,
+0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,
+0x0f,0x00,0x10,0x3c,0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,
+0x01,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02,0xb8,0x44,0x00,0x0c,
+0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f,
+0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
+0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00,
+0x95,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,
+0x02,0x80,0x14,0x3c,0x78,0x1b,0x85,0x26,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,
+0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,
+0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0xc8,0x02,0xa3,0x90,0x25,0xb0,0x02,0x3c,
+0x9a,0x0c,0x42,0x34,0x01,0x00,0x63,0x24,0xff,0x00,0x64,0x30,0x00,0x00,0x44,0xa0,
+0xc8,0x02,0xa3,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x85,0x26,
+0x0c,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,0x01,0x00,0x42,0x30,
+0x08,0x00,0x40,0x14,0x06,0x00,0x16,0x24,0x08,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,
+0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0x4e,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c,
+0x78,0x1b,0x85,0x26,0x0c,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,
+0x01,0x00,0x44,0x30,0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f,
+0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x00,0xa2,0x8c,
+0x00,0x00,0x00,0x00,0x42,0x17,0x02,0x00,0x03,0x00,0x43,0x30,0xef,0xff,0x64,0x14,
+0x00,0x00,0x00,0x00,0x10,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,
+0x60,0x02,0x43,0x10,0x0f,0x00,0x10,0x3c,0xc7,0x02,0xb3,0x90,0x25,0xb0,0x02,0x3c,
+0x62,0x0c,0x42,0x34,0xff,0x00,0x63,0x32,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x90,0x26,0xc6,0x02,0x02,0x92,0x00,0x00,0x00,0x00,
+0x6f,0x01,0x40,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36,
+0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,0x95,0x01,0x40,0x14,
+0xcc,0x00,0x02,0x24,0xc4,0x02,0x02,0x96,0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00,
+0x2b,0x18,0x53,0x00,0x23,0x10,0x62,0x02,0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c,
+0x62,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x02,0x03,0x92,0x63,0x0c,0x22,0x36,
+0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,
+0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x78,0x1b,0x83,0x26,
+0xc3,0x02,0x62,0x90,0x08,0x00,0x66,0x8c,0xc2,0x02,0x73,0xa0,0x23,0x20,0x53,0x00,
+0x2b,0x38,0x62,0x02,0x23,0x90,0x62,0x02,0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00,
+0x3f,0x00,0xa5,0x30,0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,
+0x23,0x10,0x44,0x00,0x7d,0x01,0x40,0x16,0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00,
+0x21,0xa8,0xa0,0x00,0x02,0x80,0x17,0x3c,0x2b,0x28,0xc8,0x02,0xf3,0x01,0xa0,0x10,
+0x78,0x1b,0x82,0x26,0x80,0x10,0x08,0x00,0x78,0x1b,0x83,0x26,0x21,0x10,0x43,0x00,
+0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x78,0x1b,0x86,0x26,
+0x0c,0x00,0xc3,0x8c,0x00,0x00,0x00,0x00,0xff,0x03,0x67,0x30,0x7b,0x01,0xe0,0x10,
+0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,
+0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32,
+0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,
+0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,
+0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36,
+0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,
+0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c,
+0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,
+0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,0x10,0x00,0xa3,0xaf,0x68,0x52,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x78,0x1b,0x83,0x26,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x59,0x01,0x40,0x04,0xc0,0x28,0x15,0x00,0x21,0x10,0xa3,0x00,0xac,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xad,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xae,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xaf,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb0,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb1,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb2,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb3,0x00,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x56,0x43,0xe3,0x92,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,
+0x92,0x00,0x02,0x24,0x0d,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x82,0x26,
+0x08,0x00,0x43,0x8c,0x01,0x00,0x44,0x3a,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,
+0x3f,0x00,0x63,0x30,0x01,0x00,0x84,0x30,0x71,0x01,0x80,0x10,0x23,0x28,0x43,0x00,
+0x42,0x18,0x12,0x00,0x40,0x10,0x03,0x00,0x21,0x90,0x43,0x00,0x78,0x1b,0x83,0x26,
+0xc3,0x02,0x62,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x62,0x02,0x46,0x01,0x40,0x10,
+0x2b,0x10,0x45,0x02,0x06,0x00,0x40,0x10,0x24,0x00,0x06,0x24,0x08,0x00,0x62,0x8c,
+0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00,
+0x2b,0x28,0xc6,0x02,0x46,0x01,0xa0,0x10,0x78,0x1b,0x82,0x26,0x80,0x10,0x06,0x00,
+0x78,0x1b,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x25,0x04,0x00,0x78,0x1b,0x83,0x26,0x10,0x00,0x70,0x8c,0x00,0x00,0x00,0x00,
+0x82,0x3a,0x10,0x00,0xff,0x03,0xe7,0x30,0x3c,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30,
+0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,
+0x18,0x00,0xe4,0x00,0x02,0x85,0x10,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,
+0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,
+0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,
+0x25,0xb0,0x11,0x3c,0x88,0x0c,0x24,0x36,0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,
+0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,
+0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c,0x10,0x00,0xa3,0xaf,
+0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32,
+0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,
+0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x99,0x56,0x00,0x08,
+0x00,0x00,0x00,0x00,0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00,
+0xc0,0xff,0x02,0x3c,0x24,0x20,0x62,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,
+0xec,0x57,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,
+0x0d,0x00,0x40,0x10,0x02,0x80,0x17,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,
+0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,
+0x08,0x00,0xc2,0xac,0x02,0x80,0x17,0x3c,0x56,0x43,0xe3,0x92,0x22,0x00,0x02,0x24,
+0x3a,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x39,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
+0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,
+0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0x26,0x1c,0x53,0x24,0x2e,0x1d,0x72,0x24,0x21,0x88,0x00,0x00,0x13,0x58,0x00,0x08,
+0x10,0x00,0xa4,0xaf,0x7b,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x43,0x00,0x40,0x10,
+0x78,0x1b,0x85,0x26,0x01,0x00,0x31,0x26,0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,
+0x78,0x1b,0x82,0x26,0xc0,0x80,0x11,0x00,0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,
+0x7b,0x46,0x00,0x0c,0x04,0x00,0x06,0x24,0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,
+0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,0x78,0x1b,0x85,0x26,0x08,0x00,0xa3,0x8c,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,
+0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x08,0x00,0xa3,0xac,0x78,0x1b,0x82,0x26,0x0c,0x00,0x43,0x8c,
+0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x92,0x56,0x00,0x08,0x0c,0x00,0x43,0xac,
+0xc6,0x02,0x02,0xa2,0xc0,0x56,0x00,0x08,0xc4,0x02,0x13,0xa6,0xbf,0x55,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xd0,0x56,0x00,0x08,0xc4,0x02,0x13,0xa6,0x25,0xb0,0x02,0x3c,
+0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x78,0x1b,0x66,0x24,
+0xc0,0xff,0x02,0x3c,0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,
+0x44,0x58,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,
+0xbc,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,
+0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,
+0x25,0x10,0x43,0x00,0xfe,0x57,0x00,0x08,0x08,0x00,0xc2,0xac,0x08,0x00,0xa3,0x8c,
+0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,
+0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0x27,0x58,0x00,0x08,
+0x25,0x18,0x62,0x00,0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0xda,0x56,0x00,0x08,0x78,0x1b,0x83,0x26,0x98,0x00,0xe0,0x10,
+0x21,0x40,0x00,0x00,0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38,
+0x24,0x00,0x08,0x24,0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x7d,0xfe,0x60,0x10,
+0x20,0x00,0x15,0x24,0x78,0x1b,0x83,0x26,0x0a,0x00,0x62,0x94,0x02,0x80,0x17,0x3c,
+0x3f,0x00,0x42,0x30,0xec,0x56,0x00,0x08,0x21,0xa8,0x52,0x00,0x96,0x00,0xa0,0x10,
+0x80,0x10,0x08,0x00,0x21,0x10,0x46,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c,
+0x68,0x52,0x00,0x0c,0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34,
+0x21,0x57,0x00,0x08,0x21,0x28,0x00,0x00,0x21,0x10,0xa3,0x00,0xb4,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x01,0x44,0x90,
+0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,
+0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x42,0x24,0x87,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x00,0x43,0x8c,
+0xf5,0x56,0x00,0x08,0x82,0x25,0x03,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,
+0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xbc,0xfe,0x60,0x14,
+0x23,0x30,0x52,0x00,0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x78,0x1b,0x82,0x26,
+0x30,0x00,0x43,0x8c,0xaf,0x57,0x00,0x08,0x82,0x25,0x03,0x00,0x32,0x00,0xa0,0x10,
+0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c,
+0x68,0x52,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x9c,0x0c,0x84,0x34,
+0x68,0x52,0x00,0x0c,0x21,0x28,0x00,0x00,0x99,0x56,0x00,0x08,0x00,0x00,0x00,0x00,
+0x23,0x10,0x92,0x00,0x2b,0x18,0x44,0x02,0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00,
+0xe8,0xfd,0x80,0x14,0x23,0xa8,0xb2,0x00,0xeb,0x56,0x00,0x08,0x21,0xa8,0x00,0x00,
+0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
+0x99,0x57,0x00,0x08,0x01,0x00,0x52,0x24,0x30,0x00,0xc5,0x8c,0x7a,0x58,0x00,0x08,
+0x25,0xb0,0x04,0x3c,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,0xb8,0x44,0x00,0x0c,
+0x24,0x00,0x04,0x24,0x9c,0x12,0x00,0x0c,0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,
+0xe3,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30,0x00,0x60,0x01,0x40,
+0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,
+0xb2,0x56,0x00,0x08,0x25,0xb0,0x02,0x3c,0x30,0x00,0x65,0x8c,0xf6,0x58,0x00,0x08,
+0x25,0xb0,0x04,0x3c,0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10,
+0x02,0x80,0x02,0x3c,0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24,
+0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x62,0x1e,0x43,0xa0,0x02,0x80,0x02,0x3c,
+0x08,0x00,0xe0,0x03,0x62,0x1e,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,
+0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
+0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x78,0x1b,0x63,0x24,0x20,0x00,0x84,0x2c,
+0x09,0x00,0x80,0x10,0x21,0x10,0x43,0x00,0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,
+0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x6c,0x3f,0x43,0x8c,
+0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,
+0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30,
+0xd2,0xff,0xa3,0x24,0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c,
+0x08,0x00,0x84,0x2c,0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24,
+0xfc,0xff,0xa3,0x24,0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10,
+0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0xe0,0xff,0xbd,0x27,
+0x02,0x80,0x08,0x3c,0x78,0x1b,0x08,0x25,0x18,0x00,0xbf,0xaf,0xe8,0x02,0x07,0x8d,
+0x02,0x80,0x02,0x3c,0x56,0x43,0x49,0x90,0x00,0x03,0x02,0x3c,0x25,0x38,0xe2,0x00,
+0xff,0xf3,0x02,0x3c,0x02,0x80,0x03,0x3c,0xff,0xff,0x42,0x34,0xe4,0xb5,0x6a,0x24,
+0x24,0x38,0xe2,0x00,0xff,0xff,0x03,0x34,0x01,0x80,0x06,0x3c,0x22,0x00,0x02,0x24,
+0x21,0x20,0x40,0x01,0x44,0x66,0xc6,0x24,0x10,0x00,0xa5,0x27,0xe8,0x02,0x07,0xad,
+0x00,0x24,0x03,0xad,0x05,0x00,0x22,0x11,0xfc,0x23,0x03,0xad,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x44,0x00,0x02,0x24,
+0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x11,0x00,0xa3,0xa3,
+0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,0x13,0x00,0xa0,0xa3,
+0x0c,0x00,0x43,0xad,0xa8,0x14,0x00,0x0c,0x14,0x00,0x42,0xa1,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
+0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,
+0x78,0x1b,0x04,0x26,0xd8,0x02,0x82,0x8c,0x01,0x00,0x03,0x24,0x02,0x15,0x02,0x00,
+0x0f,0x00,0x42,0x30,0x07,0x00,0x43,0x10,0x25,0xb0,0x06,0x3c,0x18,0x00,0xbf,0x8f,
+0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0x4c,0x00,0xc3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x03,0x00,0x42,0x30,0x45,0x00,0x40,0x10,0xff,0xf3,0x02,0x3c,0xe8,0x02,0x85,0x8c,
+0x00,0x00,0x00,0x00,0x82,0x16,0x05,0x00,0x03,0x00,0x42,0x30,0x17,0x00,0x40,0x14,
+0x78,0x1b,0x11,0x26,0x0c,0x09,0xc3,0x34,0x00,0x00,0x63,0x8c,0x12,0x01,0x02,0x3c,
+0x13,0x13,0x42,0x34,0x6b,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x22,0x02,0x02,0x3c,
+0x23,0x13,0x42,0x34,0x52,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x00,0x03,0x02,0x3c,
+0x25,0x10,0xa2,0x00,0xe8,0x02,0x82,0xac,0x78,0x1b,0x05,0x26,0xe8,0x02,0xa3,0x8c,
+0xff,0xf3,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x04,0x04,0x3c,
+0x25,0x18,0x64,0x00,0xe8,0x02,0xa3,0xac,0x78,0x1b,0x11,0x26,0xfc,0x23,0x24,0x8e,
+0xff,0xff,0x02,0x34,0xd5,0xff,0x82,0x10,0x00,0x00,0x00,0x00,0x80,0x11,0x22,0x8e,
+0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x3f,0x00,0x43,0x2c,
+0x28,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0x00,0x24,0x22,0x8e,0x02,0x19,0x04,0x00,
+0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x3a,0x00,0x60,0x18,0x01,0x00,0x03,0x24,
+0xeb,0x02,0x22,0x92,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x0e,0x00,0x43,0x10,
+0x78,0x1b,0x02,0x26,0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,0x0c,0x09,0x84,0x34,
+0x68,0x52,0x00,0x0c,0x13,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,0xff,0xfc,0x02,0x3c,
+0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x01,0x04,0x3c,0x25,0x18,0x64,0x00,
+0xe8,0x02,0x23,0xae,0x78,0x1b,0x02,0x26,0xe8,0x02,0x43,0x8c,0x00,0x20,0x04,0x3c,
+0x25,0x18,0x64,0x00,0x9d,0x59,0x00,0x08,0xe8,0x02,0x43,0xac,0xe8,0x02,0x83,0x8c,
+0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0x42,0x34,
+0x24,0x18,0x62,0x00,0x20,0x00,0xbd,0x27,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
+0xe8,0x02,0x83,0xac,0xa5,0xff,0x40,0x10,0x03,0x00,0x03,0x24,0xeb,0x02,0x22,0x92,
+0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0xa0,0xff,0x43,0x10,0x32,0x03,0x05,0x3c,
+0x25,0xb0,0x04,0x3c,0x0c,0x09,0x84,0x34,0x68,0x52,0x00,0x0c,0x33,0x13,0xa5,0x34,
+0xe8,0x02,0x23,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
+0x00,0x03,0x04,0x3c,0x25,0x18,0x64,0x00,0x9d,0x59,0x00,0x08,0xe8,0x02,0x23,0xae,
+0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x02,0x03,0x3c,0xbb,0x59,0x00,0x08,
+0x25,0x10,0x43,0x00,0xeb,0x02,0x22,0x92,0x02,0x00,0x03,0x24,0x03,0x00,0x42,0x30,
+0xd5,0xff,0x43,0x10,0x78,0x1b,0x02,0x26,0x25,0xb0,0x04,0x3c,0x22,0x02,0x05,0x3c,
+0x0c,0x09,0x84,0x34,0x68,0x52,0x00,0x0c,0x23,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,
+0xff,0xfc,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xe5,0x59,0x00,0x08,
+0x00,0x02,0x04,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x01,0x03,0x3c,
+0xbb,0x59,0x00,0x08,0x25,0x10,0x43,0x00,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34,
+0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x08,0x00,0x42,0x34,
+0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,
+0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34,
+0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,
+0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,
+0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,
+0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,
+0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,
+0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,
+0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,
+0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,0x02,0x3c,0x02,0x00,
+0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x02,0x32,0x04,0x00,
+0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xda,0x0c,0xa2,0xa0,0xc8,0x0c,0xa0,0xac,
+0xcc,0x0c,0xa0,0xac,0xd0,0x0c,0xa0,0xac,0x06,0x00,0x80,0x14,0xd4,0x0c,0xa0,0xac,
+0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xd8,0x0c,0xa2,0xa0,0x08,0x00,0xe0,0x03,
+0xd9,0x0c,0xa3,0xa0,0xd9,0x0c,0xa7,0xa0,0x08,0x00,0xe0,0x03,0xd8,0x0c,0xa6,0xa0,
+0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xd9,0x0c,0x66,0x90,0xd8,0x0c,0x65,0x90,
+0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,0x00,0x00,0x45,0xa0,
+0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xda,0x0c,0x60,0xa0,0x02,0x80,0x08,0x3c,
+0x78,0x1b,0x04,0x25,0xda,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10,
+0x21,0x18,0x00,0x00,0xcc,0x0c,0x82,0x8c,0xc8,0x0c,0x85,0x8c,0x25,0xb0,0x03,0x3c,
+0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,0x0f,0x00,0x40,0x10,
+0x81,0x01,0x66,0x34,0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30,
+0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,0x78,0x1b,0x02,0x25,
+0x01,0x00,0x03,0x24,0xd4,0x0c,0x40,0xac,0xc8,0x0c,0x40,0xac,0xcc,0x0c,0x40,0xac,
+0xd0,0x0c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd0,0x0c,0x82,0x8c,
+0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,
+0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xd4,0x0c,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa0,
+0x00,0x00,0x23,0xa1,0x8e,0x5a,0x00,0x08,0x78,0x1b,0x02,0x25,0xd9,0x0c,0x83,0x90,
+0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,
+0x00,0x00,0x23,0xa1,0x8e,0x5a,0x00,0x08,0x78,0x1b,0x02,0x25,0x00,0x00,0x85,0xac,
+0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,
+0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0,
+0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10,
+0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf,
+0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90,
+0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10,
+0x78,0x1b,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
+0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x52,0x24,0x43,0x96,
+0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0xba,0x5a,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0xba,0x5a,0x00,0x0c,0x21,0x80,0x40,0x00,
+0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32,
+0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00,
+0x00,0x00,0xa2,0x94,0x50,0x24,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34,
+0x01,0x00,0x63,0x24,0x50,0x24,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4,
+0xd7,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
+0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,0x78,0x1b,0x50,0x24,
+0x04,0x24,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,0x01,0x00,0x63,0x30,
+0x10,0x00,0xa4,0x27,0x80,0x3f,0x25,0x26,0x07,0x00,0x62,0x10,0x0a,0x00,0x06,0x24,
+0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x52,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
+0x21,0x28,0x00,0x00,0x80,0x3f,0x24,0x26,0x3e,0x46,0x00,0x0c,0x0a,0x00,0x06,0x24,
+0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0x09,0x24,0x03,0xa2,0x08,0x24,0x02,0xa2,
+0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x39,0x15,0x00,0x0c,
+0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,0xe4,0xff,0x40,0x10,
+0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,0x14,0x00,0x02,0xae,
+0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,0x0c,0x00,0x03,0xae,
+0x52,0x46,0x00,0x0c,0x20,0x00,0x84,0x24,0x59,0x0a,0x00,0x0c,0x21,0x20,0x00,0x02,
+0x0a,0x5b,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x21,0x20,0x82,0x00,
+0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,
+0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0xe8,0xff,0xbd,0x27,0xff,0x00,0xa5,0x30,0x10,0x00,0xb0,0xaf,
+0x14,0x00,0xbf,0xaf,0x18,0x00,0xa0,0x14,0xff,0x00,0x90,0x30,0x2c,0x00,0x00,0x12,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x01,0x00,0x07,0x24,0xb0,0x44,0x67,0xa0,
+0x02,0x80,0x08,0x3c,0xb2,0x44,0x02,0x91,0x02,0x00,0x04,0x24,0x21,0x28,0x00,0x00,
+0x02,0x00,0x42,0x34,0x00,0x03,0x06,0x24,0xb2,0x44,0x02,0xa1,0x71,0x14,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x42,0xb0,0x02,0x3c,
+0x44,0x00,0x03,0x24,0x03,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,
+0xb0,0x44,0x43,0xa0,0x02,0x80,0x02,0x3c,0xb3,0x44,0x43,0x90,0x0f,0x00,0x02,0x24,
+0x02,0x80,0x05,0x3c,0x0f,0x00,0x63,0x30,0x07,0x00,0x62,0x10,0x01,0x00,0x04,0x24,
+0xb2,0x44,0xa2,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0,
+0x1c,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0xdb,0xff,0x00,0x16,0x02,0x80,0x03,0x3c,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27,
+0xe8,0xff,0xbd,0x27,0x10,0x00,0xb2,0xaf,0x0c,0x00,0xb1,0xaf,0x08,0x00,0xb0,0xaf,
+0x21,0x40,0xe0,0x00,0x21,0x90,0xa0,0x03,0x21,0x60,0xc0,0x00,0x21,0x78,0x80,0x00,
+0x45,0x00,0xe0,0x14,0x21,0x50,0xa0,0x00,0x2b,0x10,0xa6,0x00,0x78,0x00,0x40,0x10,
+0xff,0xff,0x02,0x34,0x2b,0x10,0x46,0x00,0x8f,0x01,0x40,0x10,0x21,0x28,0xc0,0x00,
+0xff,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x24,0x2b,0x10,0x46,0x00,
+0x18,0x00,0x04,0x24,0x21,0x30,0x60,0x00,0x0b,0x30,0x82,0x00,0x02,0x80,0x03,0x3c,
+0x06,0x10,0xc5,0x00,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,
+0x20,0x00,0x02,0x24,0x21,0x20,0x86,0x00,0x23,0x30,0x44,0x00,0x08,0x00,0xc0,0x10,
+0x02,0x4c,0x0c,0x00,0x23,0x10,0x46,0x00,0x06,0x10,0x4f,0x00,0x04,0x18,0xca,0x00,
+0x25,0x50,0x62,0x00,0x04,0x60,0xcc,0x00,0x04,0x78,0xcf,0x00,0x02,0x4c,0x0c,0x00,
+0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0xff,0xff,0x87,0x31,0x02,0x24,0x0f,0x00,0x12,0x18,0x00,0x00,0x10,0x28,0x00,0x00,
+0x00,0x14,0x05,0x00,0x25,0x28,0x44,0x00,0x18,0x00,0x67,0x00,0x12,0x58,0x00,0x00,
+0x2b,0x18,0xab,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,
+0x21,0x28,0xac,0x00,0x2b,0x10,0xac,0x00,0x04,0x00,0x40,0x14,0x2b,0x10,0xab,0x00,
+0x00,0x00,0x42,0x38,0x21,0x18,0xac,0x00,0x0b,0x28,0x62,0x00,0x23,0x28,0xab,0x00,
+0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0xff,0xff,0xe4,0x31,0x12,0x18,0x00,0x00,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+0x42,0x5c,0x00,0x08,0x18,0x00,0x67,0x00,0x2b,0x10,0xa7,0x00,0x0a,0x00,0x40,0x10,
+0xff,0xff,0x02,0x34,0x10,0x00,0xb2,0x8f,0x0c,0x00,0xb1,0x8f,0x08,0x00,0xb0,0x8f,
+0x21,0x10,0x80,0x00,0x21,0x18,0xa0,0x00,0x00,0x00,0xa4,0xaf,0x04,0x00,0xa5,0xaf,
+0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x2b,0x10,0x47,0x00,0xd2,0x00,0x40,0x10,
+0x00,0x01,0xe3,0x2c,0xff,0x00,0x02,0x3c,0x10,0x00,0x03,0x24,0xff,0xff,0x42,0x34,
+0x2b,0x10,0x47,0x00,0x18,0x00,0x04,0x24,0x21,0x28,0x60,0x00,0x0b,0x28,0x82,0x00,
+0x06,0x10,0xa8,0x00,0x02,0x80,0x03,0x3c,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00,
+0xce,0x00,0xc0,0x14,0x23,0x38,0x46,0x00,0x2b,0x10,0x0a,0x01,0x04,0x00,0x40,0x14,
+0x23,0x20,0xec,0x01,0x2b,0x10,0xec,0x01,0x05,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x2b,0x10,0xe4,0x01,0x23,0x18,0x48,0x01,0x23,0x50,0x62,0x00,0x21,0x78,0x80,0x00,
+0x04,0x00,0x40,0x12,0x21,0xc0,0xe0,0x01,0x21,0xc8,0x40,0x01,0x00,0x00,0x58,0xae,
+0x04,0x00,0x59,0xae,0x00,0x00,0xa2,0x8f,0x04,0x00,0xa3,0x8f,0x10,0x00,0xb2,0x8f,
+0x0c,0x00,0xb1,0x8f,0x08,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0x53,0x00,0xc0,0x10,0x01,0x00,0x02,0x24,0xff,0xff,0x02,0x34,0x2b,0x10,0x4c,0x00,
+0x59,0x00,0x40,0x14,0xff,0x00,0x02,0x3c,0x00,0x01,0x83,0x2d,0x08,0x00,0x02,0x24,
+0x21,0x28,0x00,0x00,0x0a,0x28,0x43,0x00,0x06,0x10,0xac,0x00,0x02,0x80,0x03,0x3c,
+0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,
+0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00,0x5b,0x00,0xc0,0x14,0x00,0x00,0x00,0x00,
+0x23,0x50,0x4c,0x01,0x02,0x4c,0x0c,0x00,0xff,0xff,0x8d,0x31,0x1b,0x00,0x49,0x01,
+0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x02,0x24,0x0f,0x00,
+0x12,0x18,0x00,0x00,0x10,0x28,0x00,0x00,0x00,0x14,0x05,0x00,0x25,0x28,0x44,0x00,
+0x18,0x00,0x6d,0x00,0x12,0x58,0x00,0x00,0x2b,0x18,0xab,0x00,0x00,0x00,0x00,0x00,
+0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x28,0xac,0x00,0x2b,0x10,0xac,0x00,
+0x04,0x00,0x40,0x14,0x2b,0x10,0xab,0x00,0x00,0x00,0x42,0x38,0x21,0x18,0xac,0x00,
+0x0b,0x28,0x62,0x00,0x23,0x28,0xab,0x00,0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0xe4,0x31,0x12,0x18,0x00,0x00,
+0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x6d,0x00,
+0x00,0x14,0x08,0x00,0x12,0x58,0x00,0x00,0x25,0x40,0x44,0x00,0x2b,0x18,0x0b,0x01,
+0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x40,0x0c,0x01,0x2b,0x10,0x0c,0x01,
+0x04,0x00,0x40,0x14,0x2b,0x10,0x0b,0x01,0x21,0x18,0x0c,0x01,0x00,0x00,0x42,0x38,
+0x0b,0x40,0x62,0x00,0xab,0xff,0x40,0x12,0x23,0x78,0x0b,0x01,0x06,0xc0,0xcf,0x00,
+0x21,0xc8,0x00,0x00,0x00,0x00,0x58,0xae,0xff,0x5b,0x00,0x08,0x04,0x00,0x59,0xae,
+0x1b,0x00,0x47,0x00,0x02,0x00,0xe0,0x14,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0xff,0xff,0x02,0x34,0x12,0x60,0x00,0x00,0x2b,0x10,0x4c,0x00,0xab,0xff,0x40,0x10,
+0x00,0x01,0x83,0x2d,0xff,0x00,0x02,0x3c,0x10,0x00,0x03,0x24,0xff,0xff,0x42,0x34,
+0x2b,0x10,0x4c,0x00,0x18,0x00,0x04,0x24,0x21,0x28,0x60,0x00,0x0b,0x28,0x82,0x00,
+0x02,0x80,0x03,0x3c,0x06,0x10,0xac,0x00,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,
+0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00,
+0xa7,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x23,0x38,0x46,0x00,0x04,0x60,0xcc,0x00,
+0x06,0x58,0xea,0x00,0x02,0x4c,0x0c,0x00,0x1b,0x00,0x69,0x01,0x02,0x00,0x20,0x15,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0x8d,0x31,0x06,0x18,0xef,0x00,
+0x04,0x10,0xca,0x00,0x25,0x50,0x43,0x00,0x02,0x24,0x0a,0x00,0x12,0x28,0x00,0x00,
+0x10,0x40,0x00,0x00,0x00,0x14,0x08,0x00,0x25,0x40,0x44,0x00,0x18,0x00,0xad,0x00,
+0x12,0x28,0x00,0x00,0x2b,0x18,0x05,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x69,0x01,
+0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x05,0x00,0x60,0x10,
+0x04,0x78,0xcf,0x00,0x21,0x40,0x0c,0x01,0x2b,0x10,0x0c,0x01,0x93,0x00,0x40,0x10,
+0x2b,0x10,0x05,0x01,0x23,0x40,0x05,0x01,0x1b,0x00,0x09,0x01,0x02,0x00,0x20,0x15,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0x44,0x31,0x12,0x18,0x00,0x00,
+0x10,0x58,0x00,0x00,0x00,0x14,0x0b,0x00,0x25,0x58,0x44,0x00,0x18,0x00,0x6d,0x00,
+0x12,0x28,0x00,0x00,0x2b,0x18,0x65,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x09,0x01,
+0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x77,0xff,0x60,0x10,
+0x23,0x50,0x65,0x01,0x21,0x58,0x6c,0x01,0x2b,0x10,0x6c,0x01,0x04,0x00,0x40,0x14,
+0x2b,0x10,0x65,0x01,0x00,0x00,0x42,0x38,0x21,0x18,0x6c,0x01,0x0b,0x58,0x62,0x00,
+0x1d,0x5c,0x00,0x08,0x23,0x50,0x65,0x01,0x08,0x00,0x02,0x24,0x21,0x28,0x00,0x00,
+0x0a,0x28,0x43,0x00,0x02,0x80,0x03,0x3c,0x06,0x10,0xa8,0x00,0xfc,0xb2,0x63,0x24,
+0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00,
+0x23,0x30,0x44,0x00,0x34,0xff,0xc0,0x10,0x23,0x38,0x46,0x00,0x06,0x10,0xec,0x00,
+0x04,0x18,0xc8,0x00,0x25,0x40,0x62,0x00,0x06,0x58,0xea,0x00,0x02,0x6c,0x08,0x00,
+0x1b,0x00,0x6d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,
+0xff,0xff,0x11,0x31,0x06,0x10,0xef,0x00,0x04,0x18,0xca,0x00,0x25,0x50,0x62,0x00,
+0x02,0x24,0x0a,0x00,0x04,0x60,0xcc,0x00,0x12,0x80,0x00,0x00,0x10,0x48,0x00,0x00,
+0x00,0x14,0x09,0x00,0x25,0x48,0x44,0x00,0x12,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x18,0x00,0x11,0x02,0x12,0x70,0x00,0x00,0x2b,0x18,0x2e,0x01,
+0x00,0x00,0x00,0x00,0x1b,0x00,0x6d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00,
+0x0d,0x00,0x07,0x00,0x0a,0x00,0x60,0x10,0x04,0x78,0xcf,0x00,0x21,0x48,0x28,0x01,
+0x2b,0x10,0x28,0x01,0x06,0x00,0x40,0x14,0xff,0xff,0xb0,0x24,0x2b,0x10,0x2e,0x01,
+0x03,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x10,0x26,0x21,0x48,0x28,0x01,
+0x23,0x48,0x2e,0x01,0x1b,0x00,0x2d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00,
+0x0d,0x00,0x07,0x00,0xff,0xff,0x44,0x31,0x12,0x28,0x00,0x00,0x10,0x58,0x00,0x00,
+0x00,0x14,0x0b,0x00,0x25,0x58,0x44,0x00,0x18,0x00,0xb1,0x00,0x12,0x70,0x00,0x00,
+0x2b,0x18,0x6e,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x2d,0x01,0x02,0x00,0xa0,0x15,
+0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x0b,0x00,0x60,0x10,0x00,0x14,0x10,0x00,
+0x21,0x58,0x68,0x01,0x2b,0x10,0x68,0x01,0x06,0x00,0x40,0x14,0xff,0xff,0xa5,0x24,
+0x2b,0x10,0x6e,0x01,0x04,0x00,0x40,0x10,0x00,0x14,0x10,0x00,0xff,0xff,0xa5,0x24,
+0x21,0x58,0x68,0x01,0x00,0x14,0x10,0x00,0x25,0x10,0x45,0x00,0x23,0x58,0x6e,0x01,
+0x19,0x00,0x4c,0x00,0x10,0x28,0x00,0x00,0x2b,0x18,0x65,0x01,0x12,0x48,0x00,0x00,
+0x05,0x00,0x60,0x14,0x23,0x20,0x2c,0x01,0x07,0x00,0xab,0x14,0x2b,0x10,0xe9,0x01,
+0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x24,0x01,0x23,0x18,0xa8,0x00,
+0x23,0x28,0x62,0x00,0x21,0x48,0x80,0x00,0xea,0xfe,0x40,0x12,0x23,0x18,0xe9,0x01,
+0x23,0x20,0x65,0x01,0x2b,0x10,0xe3,0x01,0x23,0x50,0x82,0x00,0x04,0x28,0xea,0x00,
+0x06,0x18,0xc3,0x00,0x25,0xc0,0xa3,0x00,0x06,0xc8,0xca,0x00,0x00,0x00,0x58,0xae,
+0xff,0x5b,0x00,0x08,0x04,0x00,0x59,0xae,0x00,0x01,0xc3,0x2c,0x08,0x00,0x02,0x24,
+0x21,0x30,0x00,0x00,0x99,0x5b,0x00,0x08,0x0a,0x30,0x43,0x00,0x00,0x00,0x42,0x38,
+0x21,0x18,0x0c,0x01,0x93,0x5c,0x00,0x08,0x0b,0x40,0x62,0x00,0x25,0xb0,0x02,0x3c,
+0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
+0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0xc4,0x74,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0x0d,0xb8,0x46,0x34,
+0x80,0x00,0x03,0x3c,0x25,0x30,0xc3,0x00,0x00,0x04,0x02,0x3c,0x25,0x30,0xc2,0x00,
+0x00,0x08,0x03,0x3c,0x25,0x30,0xc3,0x00,0x02,0x80,0x04,0x3c,0x01,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x78,0x1b,0x84,0x24,0x41,0xb0,0x05,0x3c,0xe0,0x74,0x63,0x24,
+0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xa6,0xac,0x10,0x0b,0x86,0xac,
+0x08,0x0b,0x86,0xac,0x08,0x00,0xa5,0x34,0x86,0x00,0x06,0x24,0x00,0x00,0xa6,0xa4,
+0x14,0x0b,0x86,0xa4,0x0c,0x0b,0x80,0xac,0x16,0x0b,0x80,0xa4,0x08,0x00,0xe0,0x03,
+0x18,0x0b,0x86,0xa4,0x53,0x5d,0x00,0x08,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,
+0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,0x21,0x20,0x00,0x00,
+0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,0x10,0x00,0xbf,0xaf,
+0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x03,0x00,0x04,0x24,
+0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0x71,0x14,0x00,0x08,0x18,0x00,0xbd,0x27,
+0x25,0xb0,0x03,0x3c,0x01,0x80,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x18,0x03,0x64,0x34,
+0x98,0x75,0x42,0x24,0x00,0x00,0x82,0xac,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
+0x18,0x00,0xbf,0xaf,0xb6,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x10,0x3c,
+0x78,0x1b,0x10,0x26,0xe3,0x0a,0x02,0xa2,0x34,0x61,0x00,0x0c,0xee,0x23,0x00,0xa2,
+0xff,0xff,0x02,0x34,0x21,0x88,0x00,0x02,0xf8,0x23,0x02,0xae,0xf0,0x23,0x00,0xa6,
+0xf2,0x23,0x00,0xa6,0xf4,0x23,0x02,0xae,0x21,0x28,0x00,0x00,0x21,0x20,0x00,0x02,
+0x04,0x00,0xa2,0x24,0x01,0x00,0xa5,0x24,0x20,0x00,0xa3,0x28,0xee,0x0c,0x82,0xa4,
+0xdc,0x0c,0x80,0xa4,0xde,0x0c,0x80,0xa4,0xe0,0x0c,0x80,0xa4,0xe2,0x0c,0x80,0xa4,
+0xe4,0x0c,0x80,0xa4,0xe6,0x0c,0x80,0xa4,0xe8,0x0c,0x80,0xa4,0xea,0x0c,0x80,0xa4,
+0xec,0x0c,0x80,0xa4,0xf0,0x0c,0x80,0xa0,0xf1,0xff,0x60,0x14,0x24,0x00,0x84,0x24,
+0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c,
+0xa0,0x1e,0x84,0x24,0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,0x3e,0x46,0x00,0x0c,
+0x04,0x00,0x06,0x24,0x11,0x62,0x00,0x0c,0x00,0x00,0x00,0x00,0x84,0x62,0x00,0x0c,
+0xec,0x25,0x20,0xae,0xe6,0x63,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,
+0x56,0x43,0x64,0x90,0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00,
+0x5c,0x64,0x00,0x0c,0x00,0x00,0x00,0x00,0x42,0x64,0x00,0x0c,0x00,0x00,0x00,0x00,
+0xbd,0x62,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x64,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x50,0x24,0x20,0xa6,0xaf,0x64,0x00,0x0c,0x52,0x24,0x20,0xa6,0xf3,0x64,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
+0x02,0x80,0x05,0x3c,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,0x68,0x41,0xa2,0x24,
+0x70,0x41,0xc3,0x24,0x78,0x41,0xe4,0x24,0x20,0x00,0xbd,0x27,0x04,0x00,0x42,0xac,
+0x68,0x41,0xa2,0xac,0x04,0x00,0x63,0xac,0x70,0x41,0xc3,0xac,0x78,0x41,0xe4,0xac,
+0x08,0x00,0xe0,0x03,0x04,0x00,0x84,0xac,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
+0xe8,0xff,0xbd,0x27,0x00,0x77,0x63,0x24,0x18,0x03,0x42,0x34,0x14,0x00,0xbf,0xaf,
+0x10,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x21,0x20,0x00,0x00,0x01,0x00,0x82,0x24,
+0xff,0xff,0x44,0x30,0x64,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x52,0x43,0x48,0x90,0x50,0x43,0x65,0x94,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x53,0x43,0x46,0x90,0x60,0x43,0x67,0x90,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x6b,0x43,0x49,0x90,0x6d,0x43,0x6a,0x90,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x70,0x43,0x4b,0x90,0x72,0x43,0x6c,0x90,
+0x02,0x80,0x02,0x3c,0x07,0x00,0x03,0x24,0x25,0xb0,0x04,0x3c,0x5d,0x43,0x43,0xa0,
+0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x85,0xac,0x5e,0x43,0x40,0xa0,
+0x02,0x80,0x02,0x3c,0x00,0x00,0x86,0xac,0x5f,0x43,0x40,0xa0,0x02,0x80,0x02,0x3c,
+0x00,0x00,0x87,0xac,0x02,0x80,0x03,0x3c,0x80,0x43,0x40,0xa0,0x02,0x80,0x10,0x3c,
+0x02,0x80,0x02,0x3c,0x78,0x1b,0x0d,0x26,0x7e,0x43,0x60,0xa4,0x7c,0x43,0x40,0xa4,
+0x01,0x00,0x03,0x24,0xfd,0xff,0x02,0x24,0xe0,0x0a,0xa3,0xa1,0xe2,0x0a,0xa2,0xa1,
+0xff,0x07,0x03,0x24,0x00,0x78,0x02,0x24,0xe6,0x0a,0xa3,0xa5,0xe4,0x0a,0xa2,0xa5,
+0xff,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x00,0x00,0x88,0xac,0x0f,0x00,0x0e,0x31,
+0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac,0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,
+0x91,0x43,0x43,0xa0,0x02,0x00,0x02,0x24,0xe8,0x0a,0xa0,0xa1,0x31,0x00,0xc2,0x11,
+0x82,0x0b,0xa0,0xa1,0x00,0x80,0x02,0x3c,0x15,0x15,0x03,0x3c,0x02,0xbc,0x42,0x34,
+0x07,0x07,0x63,0x34,0x74,0x0b,0xa2,0xad,0x6c,0x0b,0xa3,0xad,0x02,0x02,0x02,0x3c,
+0x70,0x0b,0xa2,0xad,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c,0x9c,0x43,0x40,0xa4,
+0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,
+0x12,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
+0x10,0x00,0x42,0x30,0x38,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x08,0x00,0x82,0x24,
+0xff,0xff,0x44,0x30,0x80,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x78,0x1b,0x03,0x26,
+0x01,0x00,0x02,0x24,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24,
+0x8b,0x0b,0x62,0xa0,0x93,0x12,0x00,0x08,0x18,0x00,0xbd,0x27,0x54,0x00,0x85,0x34,
+0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,
+0x00,0x00,0xa3,0xac,0x01,0x00,0x02,0x24,0x78,0x1b,0x03,0x26,0x14,0x00,0xbf,0x8f,
+0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24,0x8b,0x0b,0x62,0xa0,0x93,0x12,0x00,0x08,
+0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x57,0x43,0x44,0x90,0x06,0x00,0x03,0x24,
+0x25,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x10,0x00,0x82,0x10,0x00,0x80,0x02,0x3c,
+0x02,0x80,0x02,0x3c,0x6a,0x43,0x43,0x90,0x00,0x00,0x00,0x00,0x2c,0x00,0x60,0x10,
+0x00,0xe0,0x02,0x3c,0x04,0xe0,0x02,0x3c,0x78,0x1b,0x04,0x26,0x00,0x8e,0x42,0x34,
+0x00,0x15,0x03,0x3c,0x74,0x0b,0x82,0xac,0x00,0x15,0x63,0x34,0x00,0x42,0x02,0x24,
+0x6c,0x0b,0x83,0xac,0x0f,0x5e,0x00,0x08,0x70,0x0b,0x82,0xac,0x00,0xbc,0x42,0x34,
+0x15,0x15,0x03,0x3c,0x74,0x0b,0xa2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,
+0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad,0x02,0x80,0x06,0x3c,0x00,0xb4,0xc6,0x24,
+0xf5,0x13,0x00,0x0c,0x80,0x00,0x05,0x24,0x78,0x1b,0x03,0x26,0x01,0x00,0x02,0x24,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24,0x8b,0x0b,0x62,0xa0,
+0x93,0x12,0x00,0x08,0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x6a,0x43,0x43,0x90,
+0x00,0x00,0x00,0x00,0x13,0x00,0x60,0x10,0x1c,0x1c,0x03,0x3c,0x04,0xc0,0x02,0x3c,
+0x00,0xb8,0x42,0x34,0x74,0x0b,0xa2,0xad,0x00,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,
+0x00,0x07,0x63,0x34,0x00,0x22,0x42,0x34,0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad,
+0x78,0x1b,0x04,0x26,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x74,0x0b,0x82,0xac,
+0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x6c,0x0b,0x83,0xac,0x0f,0x5e,0x00,0x08,
+0x70,0x0b,0x82,0xac,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34,0x74,0x0b,0xa2,0xad,
+0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad,
+0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,0x25,0xb0,0x10,0x3c,
+0x18,0x03,0x03,0x36,0xf8,0x79,0x42,0x24,0x00,0x00,0x62,0xac,0x14,0x00,0xbf,0xaf,
+0xc0,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0xff,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x25,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,0x29,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x3a,0x41,0x00,0x0c,0x00,0x00,0x00,0x00,0x66,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x44,0x00,0x03,0x36,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,
+0x00,0x00,0x62,0xa4,0x31,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x55,0x5d,0x00,0x0c,
+0x00,0x00,0x00,0x00,0xf1,0x60,0x00,0x0c,0x00,0x00,0x00,0x00,0xaf,0x60,0x00,0x0c,
+0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0xac,0x37,0x84,0x24,0x0e,0x61,0x00,0x0c,
+0x01,0x00,0x05,0x24,0x00,0x80,0x04,0x3c,0xcc,0x41,0x84,0x24,0x0e,0x61,0x00,0x0c,
+0x02,0x00,0x05,0x24,0x01,0x80,0x04,0x3c,0xa4,0x20,0x84,0x24,0x0e,0x61,0x00,0x0c,
+0x04,0x00,0x05,0x24,0x04,0x50,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,
+0x08,0x53,0x84,0x24,0x0e,0x61,0x00,0x0c,0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,
+0x60,0x43,0x43,0x90,0x43,0x00,0x04,0x36,0x2a,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,
+0x07,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,0x43,0x00,0x85,0x34,
+0x10,0x02,0x86,0x34,0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,
+0xd8,0x00,0x84,0x34,0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,
+0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,0x32,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x42,0xb0,0x03,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34,
+0x00,0x00,0x62,0xa0,0x38,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,
+0x44,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,
+0xc0,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x53,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24,
+0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,0x32,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x42,0xb0,0x03,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34,
+0x00,0x00,0x62,0xa0,0x38,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,
+0x44,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,
+0xc0,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
+0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x53,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
+0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,
+0x18,0x00,0xbd,0x27,0xb0,0xff,0xbd,0x27,0x02,0x80,0x03,0x3c,0x4c,0x00,0xbf,0xaf,
+0x48,0x00,0xbe,0xaf,0x3c,0x00,0xb5,0xaf,0x38,0x00,0xb4,0xaf,0x34,0x00,0xb3,0xaf,
+0x30,0x00,0xb2,0xaf,0x2c,0x00,0xb1,0xaf,0x28,0x00,0xb0,0xaf,0x44,0x00,0xb7,0xaf,
+0x40,0x00,0xb6,0xaf,0x78,0x1b,0x62,0x24,0xe2,0x0a,0x43,0x90,0xe4,0x0a,0x45,0x94,
+0xe6,0x0a,0x46,0x94,0x1c,0x00,0xa3,0xa3,0x6c,0x0b,0x43,0x8c,0x24,0xb0,0x04,0x3c,
+0x21,0xb0,0x07,0x3c,0x10,0x00,0xa3,0xaf,0x70,0x0b,0x43,0x8c,0x25,0xb0,0x1e,0x3c,
+0x01,0x00,0x88,0x34,0x14,0x00,0xa3,0xaf,0x74,0x0b,0x42,0x8c,0x21,0x38,0xa7,0x00,
+0xff,0x1f,0x03,0x3c,0x18,0x00,0xa2,0xaf,0x20,0xb0,0x02,0x3c,0xff,0xff,0x42,0x34,
+0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,0xff,0xff,0x63,0x34,0x21,0x40,0xc8,0x00,
+0x58,0x00,0xc9,0x37,0x21,0x30,0xc4,0x00,0x00,0xe0,0x42,0x34,0x00,0x00,0x22,0xad,
+0xff,0xff,0x04,0x24,0x24,0x40,0x03,0x01,0x24,0x28,0xa3,0x00,0x24,0x38,0xe3,0x00,
+0x24,0x30,0xc3,0x00,0x5c,0x00,0xca,0x37,0x60,0x00,0xcb,0x37,0x64,0x00,0xcc,0x37,
+0x8a,0x00,0xcd,0x37,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24,0x00,0x00,0x43,0xad,
+0x89,0x00,0xce,0x37,0x00,0x00,0x64,0xad,0x8c,0x00,0xcf,0x37,0x00,0x00,0x84,0xad,
+0x09,0x00,0x03,0x24,0x00,0x00,0xa2,0xa5,0x0a,0x0a,0x02,0x24,0x00,0x00,0xc3,0xa1,
+0x00,0x00,0xe2,0xa5,0x25,0xb0,0x02,0x3c,0x0e,0x0e,0x03,0x24,0x8e,0x00,0x42,0x34,
+0x00,0x00,0x43,0xa4,0x90,0x00,0xd1,0x37,0x13,0x00,0x02,0x24,0x00,0x00,0x22,0xa2,
+0x40,0x00,0x03,0x24,0x3a,0x01,0x02,0x24,0x91,0x00,0xd2,0x37,0x92,0x00,0xd3,0x37,
+0x00,0x00,0x43,0xa2,0x00,0x00,0x62,0xa6,0x25,0xb0,0x02,0x3c,0x21,0x00,0x03,0x24,
+0xb5,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x10,0x00,0xa3,0x8f,0xa0,0x00,0xd5,0x37,
+0x25,0xb0,0x02,0x3c,0x00,0x00,0xa3,0xae,0x14,0x00,0xa3,0x8f,0xa4,0x00,0x42,0x34,
+0xb0,0x00,0xdf,0x37,0x00,0x00,0x43,0xac,0x18,0x00,0xa3,0x8f,0x25,0xb0,0x02,0x3c,
+0xa8,0x00,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,
+0xac,0x00,0x42,0x34,0xf8,0x00,0x63,0x34,0x00,0x00,0x45,0xac,0x00,0x00,0x67,0xac,
+0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x08,0x01,0x42,0x34,0xd8,0x00,0x63,0x34,
+0x00,0x00,0xe6,0xaf,0x00,0x00,0x48,0xac,0x00,0x00,0x60,0xa0,0x1c,0x00,0xa3,0x93,
+0x25,0xb0,0x02,0x3c,0xb4,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,
+0x04,0x00,0x03,0x24,0xb6,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,
+0xb9,0x00,0x42,0x34,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0xa0,0xba,0x00,0x63,0x34,
+0x0f,0x00,0x02,0x24,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c,0x1a,0x01,0x42,0x34,
+0x16,0x01,0xd4,0x37,0x18,0x01,0xd0,0x37,0x25,0xb0,0x03,0x3c,0x00,0x00,0x80,0xa6,
+0xdc,0x00,0x63,0x34,0x00,0x00,0x00,0xa6,0x00,0x00,0x40,0xa4,0xff,0xcf,0x02,0x24,
+0x00,0x00,0x62,0xac,0x02,0x80,0x02,0x3c,0x56,0x43,0x42,0x90,0xd0,0x01,0xc4,0x37,
+0x5e,0x00,0x03,0x3c,0x20,0x00,0xa2,0xaf,0x2f,0x00,0x02,0x3c,0x32,0x32,0x42,0x34,
+0x00,0x00,0x82,0xac,0x08,0x00,0x02,0x3c,0x32,0x43,0x63,0x34,0x30,0xa5,0x42,0x34,
+0xd4,0x01,0xc5,0x37,0xd8,0x01,0xc6,0x37,0x00,0x00,0xa3,0xac,0xdc,0x01,0xc7,0x37,
+0x00,0x00,0xc2,0xac,0x49,0xa5,0x03,0x34,0x1a,0x06,0x02,0x24,0xe0,0x01,0xc8,0x37,
+0x00,0x00,0xe3,0xac,0xf4,0x01,0xc9,0x37,0x00,0x00,0x02,0xa5,0x07,0x07,0x03,0x24,
+0xc2,0x00,0x02,0x3c,0x00,0x00,0x23,0xa5,0x51,0x10,0x42,0x34,0x26,0x00,0x03,0x24,
+0xf8,0x01,0xca,0x37,0x00,0x02,0xcb,0x37,0x00,0x00,0x42,0xad,0x03,0x02,0xcc,0x37,
+0x00,0x00,0x63,0xa5,0x0c,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x36,0x02,0xcd,0x37,
+0x00,0x00,0x83,0xa1,0x34,0x02,0xce,0x37,0x00,0x00,0xa2,0xa1,0xc0,0x01,0x03,0x24,
+0x03,0x00,0x02,0x24,0x37,0x02,0xcf,0x37,0x00,0x00,0xc3,0xa5,0x00,0x00,0xe2,0xa1,
+0x20,0x00,0xa2,0x8f,0x22,0x00,0x03,0x24,0xd2,0x00,0x43,0x10,0x1b,0x1b,0x02,0x3c,
+0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37,
+0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37,
+0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac,
+0x02,0x80,0x03,0x3c,0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac,
+0x00,0x00,0x02,0xad,0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0x56,0x43,0x65,0x90,
+0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34,
+0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xb1,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c,
+0x92,0x00,0x02,0x24,0xae,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c,
+0x00,0xf0,0x4f,0x34,0xf7,0x01,0x91,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24,
+0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35,
+0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad,
+0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x6f,0xac,
+0x25,0xb0,0x05,0x3c,0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35,
+0xf0,0x0f,0x03,0x24,0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35,
+0x00,0x00,0x42,0xad,0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,
+0x00,0x00,0x6d,0xad,0x03,0x04,0x04,0x3c,0x00,0x00,0x8e,0xa1,0x07,0x08,0x03,0x3c,
+0x00,0x00,0x2e,0xa2,0x00,0x00,0xe2,0xa2,0x25,0xb0,0x02,0x3c,0x01,0x02,0x84,0x34,
+0x05,0x06,0x63,0x34,0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0xaf,0x34,
+0xb4,0x01,0xb1,0x34,0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,
+0x00,0x00,0xc9,0xae,0x00,0x00,0xe9,0xad,0x00,0x00,0x44,0xac,0x00,0x00,0x23,0xae,
+0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,0x25,0xb0,0x03,0x3c,0x0c,0x00,0x06,0x24,
+0xc0,0x01,0x63,0x34,0x25,0xb0,0x02,0x3c,0x00,0x00,0x66,0xa0,0xc1,0x01,0xb5,0x34,
+0xc2,0x01,0x42,0x34,0x25,0xb0,0x03,0x3c,0x00,0x00,0xa6,0xa2,0x0d,0x00,0x08,0x24,
+0x00,0x00,0x46,0xa0,0xc4,0x01,0xab,0x34,0xc5,0x01,0xac,0x34,0x0e,0x00,0x07,0x24,
+0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,0xc3,0x01,0x63,0x34,0x0f,0x00,0x02,0x24,
+0x00,0x00,0x68,0xa0,0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,
+0x00,0x00,0xa2,0xa1,0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,
+0x0e,0xe2,0x42,0x34,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf,
+0x4d,0x00,0xb9,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3,
+0x25,0xb0,0x02,0x3c,0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,
+0x25,0xb0,0x03,0x3c,0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,
+0x00,0x00,0x00,0xa3,0x00,0x00,0x62,0xa4,0x02,0x80,0x02,0x3c,0xd8,0x00,0xaa,0x34,
+0x78,0x1b,0x43,0x24,0xe2,0x0a,0x64,0x90,0x00,0x00,0x47,0x91,0x2a,0xb0,0x06,0x3c,
+0xa0,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,0x34,0x00,0xc9,0x34,0x01,0x00,0x83,0x24,
+0x00,0x00,0x47,0xa1,0x26,0xb0,0x08,0x3c,0x00,0x00,0x23,0xa1,0x30,0x00,0xce,0x34,
+0x20,0x20,0x02,0x24,0x38,0x00,0xc6,0x34,0x40,0x00,0x03,0x24,0x00,0x00,0xc2,0xa4,
+0x79,0x00,0x0b,0x35,0x00,0x00,0xc3,0xa1,0x94,0x00,0xac,0x34,0x16,0x00,0x02,0x24,
+0x64,0x00,0x03,0x24,0x00,0x00,0x62,0xa1,0x7c,0x00,0x15,0x35,0x00,0x00,0x83,0xa5,
+0x98,0x00,0xad,0x34,0x7a,0x00,0x08,0x35,0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24,
+0x00,0x00,0xa2,0xa5,0x9c,0x00,0xaf,0x34,0x00,0x00,0x03,0xa1,0x20,0x0c,0x02,0x24,
+0x0a,0x00,0x03,0x24,0x00,0x00,0xa2,0xa6,0x00,0x00,0xe3,0xa1,0x25,0xb0,0x03,0x3c,
+0xff,0x03,0x02,0x24,0x9a,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,0x96,0x00,0xb1,0x34,
+0x02,0x00,0x03,0x24,0x00,0x00,0x23,0xa6,0xb7,0x00,0xb2,0x34,0x89,0x00,0xb3,0x34,
+0x20,0x00,0x02,0x24,0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa2,0x44,0x00,0xa5,0x34,
+0x00,0x00,0x63,0xa2,0x00,0x00,0xa2,0x94,0xff,0xfd,0x03,0x24,0x04,0x02,0x06,0x24,
+0x24,0x10,0x43,0x00,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa3,0x94,0x29,0xb0,0x02,0x3c,
+0x40,0x00,0x42,0x34,0x00,0x02,0x63,0x34,0x00,0x00,0xa3,0xa4,0xff,0x00,0x84,0x30,
+0x00,0x00,0x46,0xa4,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x4c,0x00,0xbf,0x8f,
+0x48,0x00,0xbe,0x8f,0x44,0x00,0xb7,0x8f,0x40,0x00,0xb6,0x8f,0x3c,0x00,0xb5,0x8f,
+0x38,0x00,0xb4,0x8f,0x34,0x00,0xb3,0x8f,0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f,
+0x28,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x50,0x00,0xbd,0x27,
+0x00,0xf0,0x4f,0x34,0xf7,0x01,0x91,0x35,0x15,0xf0,0x4d,0x34,0xd2,0x5f,0x00,0x08,
+0xff,0xff,0x0e,0x24,0xb0,0x5f,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,
+0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c,
+0x00,0x00,0x62,0xa4,0x34,0x9b,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
+0x02,0x80,0x02,0x3c,0x2c,0x95,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,
+0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,
+0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
+0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,
+0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0xb0,0x83,0x42,0x24,
+0x02,0x80,0x03,0x3c,0xa4,0x43,0xa2,0xac,0x00,0x80,0x02,0x3c,0x44,0x44,0x60,0xac,
+0xa4,0x43,0xa4,0x24,0x02,0x80,0x03,0x3c,0x8c,0x0a,0x42,0x24,0x48,0x44,0x60,0xa4,
+0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x4a,0x44,0x60,0xa4,
+0x02,0x80,0x06,0x3c,0x24,0x10,0x42,0x24,0x00,0x80,0x03,0x3c,0x4c,0x44,0xc7,0x24,
+0x14,0x00,0x82,0xac,0x68,0x0c,0x63,0x24,0x02,0x80,0x02,0x3c,0x4c,0x44,0xc0,0xac,
+0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac,0x02,0x80,0x03,0x3c,0x54,0x44,0x40,0xa0,
+0x02,0x80,0x02,0x3c,0x58,0x44,0x60,0xac,0x5c,0x44,0x40,0xac,0x01,0x80,0x02,0x3c,
+0x00,0x80,0x03,0x3c,0xd8,0x87,0x42,0x24,0x40,0x10,0x63,0x24,0x7c,0x00,0x82,0xac,
+0x1c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0xd8,0x13,0x42,0x24,
+0xd0,0x17,0x63,0x24,0x20,0x00,0x82,0xac,0x24,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,
+0x00,0x80,0x03,0x3c,0xc4,0x1b,0x42,0x24,0xf8,0x29,0x63,0x24,0x28,0x00,0x82,0xac,
+0x2c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0x14,0x20,0x42,0x24,
+0x00,0x22,0x63,0x24,0x30,0x00,0x82,0xac,0x3c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,
+0x00,0x80,0x03,0x3c,0x68,0x04,0x42,0x24,0xb8,0x1f,0x63,0x24,0x50,0x00,0x82,0xac,
+0x08,0x00,0xe0,0x03,0x40,0x00,0x83,0xac,0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34,
+0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c,
+0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24,
+0x00,0x18,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24,
+0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac,
+0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24,
+0x21,0x18,0x6d,0x00,0x06,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac,
+0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac,
+0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad,
+0x06,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,
+0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00,
+0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00,
+0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
+0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac,
+0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x02,0x80,0x03,0x3c,
+0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x94,0x84,0x63,0x24,0xe8,0xff,0xbd,0x27,
+0x00,0x00,0x43,0xac,0x10,0x00,0xbf,0xaf,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
+0x10,0x00,0xbf,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x03,0x80,0x05,0x3c,0x00,0x80,0xa5,0x24,
+0x40,0x10,0x0c,0x3c,0xff,0xff,0xa5,0x30,0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,
+0x25,0xc8,0xac,0x00,0x00,0x25,0x99,0xac,0x80,0x00,0x39,0x27,0xe0,0xff,0xbd,0x27,
+0x0c,0x25,0x99,0xac,0x80,0x00,0x39,0x27,0x1c,0x00,0xb7,0xaf,0x18,0x00,0xb6,0xaf,
+0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,0x08,0x00,0xb2,0xaf,
+0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x18,0x25,0x99,0xac,0x80,0x00,0x39,0x27,
+0x24,0x25,0x99,0xac,0xe2,0x0a,0x86,0x90,0x80,0x00,0x39,0x27,0x30,0x25,0x99,0xac,
+0x80,0x00,0x39,0x27,0x3c,0x25,0x99,0xac,0x20,0xb0,0x02,0x3c,0x0c,0x25,0x87,0x8c,
+0x18,0x25,0x88,0x8c,0x24,0x25,0x89,0x8c,0x30,0x25,0x8a,0x8c,0x3c,0x25,0x8b,0x8c,
+0x00,0x01,0x42,0x34,0x00,0x32,0x06,0x00,0xff,0x1f,0x03,0x3c,0x80,0x00,0x39,0x27,
+0x21,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,0x24,0x30,0xc3,0x00,0x48,0x25,0x99,0xac,
+0x20,0x10,0x03,0x3c,0x21,0x68,0x20,0x03,0x25,0x28,0xac,0x00,0x25,0xb0,0x0e,0x3c,
+0x80,0x00,0x39,0x27,0xfc,0x24,0x85,0xac,0x08,0x25,0x87,0xac,0x14,0x25,0x88,0xac,
+0x20,0x25,0x89,0xac,0x2c,0x25,0x8a,0xac,0xcc,0x24,0x86,0xac,0x38,0x25,0x8b,0xac,
+0xac,0x00,0xc2,0x35,0x94,0x24,0x83,0xac,0x90,0x24,0x83,0xac,0xa0,0x24,0x83,0xac,
+0x9c,0x24,0x83,0xac,0xac,0x24,0x83,0xac,0xa8,0x24,0x83,0xac,0x54,0x25,0x99,0xac,
+0xd0,0x24,0x86,0xac,0x44,0x25,0x8d,0xac,0xb8,0x24,0x83,0xac,0xb4,0x24,0x83,0xac,
+0xc4,0x24,0x83,0xac,0xc0,0x24,0x83,0xac,0xdc,0x24,0x83,0xac,0xd8,0x24,0x83,0xac,
+0x00,0x02,0x39,0x27,0x00,0x00,0x48,0x8c,0xe4,0x0a,0x87,0x94,0x6c,0x25,0x99,0xac,
+0xb0,0x00,0xc2,0x35,0x00,0x00,0x56,0x8c,0x21,0x10,0x06,0x3c,0x54,0x25,0x92,0x8c,
+0x23,0x10,0x0b,0x3c,0x22,0x10,0x0f,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,
+0x02,0x80,0x17,0x3c,0x02,0x80,0x18,0x3c,0x00,0x80,0xc5,0x34,0x21,0x98,0x20,0x03,
+0x23,0x28,0xa7,0x00,0x00,0x02,0x39,0x27,0x24,0x10,0x07,0x3c,0x80,0x41,0x89,0x26,
+0x88,0x41,0xaa,0x26,0x90,0x41,0xec,0x26,0x98,0x41,0x0d,0x27,0x00,0x04,0x70,0x35,
+0x01,0x00,0x08,0x25,0x00,0x40,0xf1,0x35,0x00,0x01,0xce,0x35,0x01,0x00,0x02,0x24,
+0x50,0x25,0x92,0xac,0x59,0x25,0x82,0xa0,0x68,0x25,0x93,0xac,0xc4,0x25,0x90,0xac,
+0x88,0x25,0x88,0xac,0x94,0x25,0x85,0xac,0xb8,0x25,0x91,0xac,0xac,0x25,0x96,0xac,
+0x00,0x00,0xc7,0xad,0xa8,0x25,0x87,0xac,0xc8,0x25,0x83,0xac,0xe8,0x24,0x83,0xac,
+0xe4,0x24,0x83,0xac,0x72,0x25,0x80,0xa4,0x71,0x25,0x80,0xa0,0x70,0x25,0x80,0xa0,
+0xbc,0x25,0x8b,0xac,0xc0,0x25,0x8b,0xac,0x80,0x25,0x86,0xac,0x84,0x25,0x86,0xac,
+0x8c,0x25,0x86,0xac,0x90,0x25,0x86,0xac,0xb0,0x25,0x8f,0xac,0xb4,0x25,0x8f,0xac,
+0xa4,0x25,0x87,0xac,0xcc,0x25,0x83,0xac,0xd8,0x25,0x99,0xac,0xd4,0x25,0x99,0xac,
+0x04,0x00,0x4a,0xad,0x80,0x41,0x89,0xae,0x04,0x00,0x8c,0xad,0x88,0x41,0xaa,0xae,
+0x04,0x00,0xad,0xad,0x90,0x41,0xec,0xae,0x98,0x41,0x0d,0xaf,0x04,0x00,0x29,0xad,
+0x02,0x80,0x02,0x3c,0x00,0x18,0x43,0x24,0x21,0x20,0x20,0x01,0x03,0x00,0x06,0x24,
+0x21,0x10,0x80,0x00,0xff,0xff,0xc6,0x24,0x08,0x00,0x79,0xac,0x00,0x00,0x63,0xac,
+0x10,0x00,0x60,0xac,0x00,0x00,0x69,0xac,0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac,
+0x00,0x00,0x43,0xac,0x00,0x01,0x39,0x27,0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24,
+0x02,0x80,0x02,0x3c,0x88,0x41,0x48,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
+0x04,0x00,0x07,0x8d,0x60,0x18,0x4b,0x24,0x04,0x00,0x24,0xad,0x00,0x18,0x6a,0x24,
+0x01,0x00,0x09,0x24,0x21,0x28,0x00,0x00,0x0f,0x00,0x06,0x24,0x21,0x20,0xab,0x00,
+0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,0x68,0x00,0x59,0xac,0x70,0x00,0x49,0xac,
+0x18,0x00,0xa5,0x24,0x00,0x00,0x88,0xac,0x04,0x00,0x87,0xac,0x00,0x00,0xe4,0xac,
+0x00,0x01,0x39,0x27,0xf5,0xff,0xc1,0x04,0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c,
+0x90,0x41,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x25,0x8d,
+0xe0,0x19,0x4b,0x24,0x04,0x00,0x04,0xad,0x00,0x18,0x6a,0x24,0x02,0x00,0x07,0x24,
+0x21,0x20,0x00,0x00,0x0f,0x00,0x06,0x24,0x21,0x40,0x8b,0x00,0x21,0x10,0x8a,0x00,
+0xff,0xff,0xc6,0x24,0xe8,0x01,0x59,0xac,0xf0,0x01,0x47,0xac,0x18,0x00,0x84,0x24,
+0x00,0x00,0x09,0xad,0x04,0x00,0x05,0xad,0x00,0x00,0xa8,0xac,0x00,0x02,0x39,0x27,
+0xf5,0xff,0xc1,0x04,0x21,0x28,0x00,0x01,0x02,0x80,0x05,0x3c,0x98,0x41,0xa5,0x24,
+0x04,0x00,0xa6,0x8c,0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,
+0x10,0x00,0xb4,0x8f,0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,
+0x00,0x00,0xb0,0x8f,0x02,0x80,0x07,0x3c,0x02,0x80,0x03,0x3c,0x60,0x1b,0xe4,0x24,
+0x00,0x18,0x63,0x24,0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x68,0x03,0x79,0xac,
+0x04,0x00,0x28,0xad,0x04,0x00,0xa4,0xac,0x70,0x03,0x62,0xac,0x60,0x1b,0xe5,0xac,
+0x04,0x00,0x86,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc4,0xac,0xc8,0xff,0xbd,0x27,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,
+0xfc,0xad,0x73,0x24,0x70,0xae,0x52,0x24,0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c,
+0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
+0x30,0x00,0xbf,0xaf,0xff,0x1f,0x54,0x34,0x78,0x1b,0x70,0x24,0x21,0x88,0x00,0x00,
+0x02,0x80,0x15,0x3c,0x19,0x50,0x00,0x0c,0x21,0x20,0x20,0x02,0x90,0x11,0x05,0x8e,
+0x6c,0x00,0x66,0x8e,0x6c,0x00,0x43,0x8e,0xdc,0xad,0xa2,0x26,0x1b,0x00,0x44,0x90,
+0x21,0x18,0x66,0x00,0x24,0x28,0xb4,0x00,0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00,
+0x00,0x20,0xa5,0x34,0x5c,0x11,0x03,0xae,0x80,0x11,0x04,0xae,0x90,0x11,0x05,0xae,
+0x84,0x11,0x04,0xae,0x21,0x30,0x00,0x00,0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,
+0x1d,0x00,0xc3,0x28,0xb1,0x11,0x40,0xa0,0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,
+0xce,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae,
+0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
+0x78,0x1b,0x4b,0x24,0x02,0x80,0x02,0x3c,0x70,0xae,0x6f,0x24,0xfc,0xad,0x4d,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xdc,0xad,0x6e,0x24,0xbc,0xad,0x4c,0x24,
+0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,
+0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,
+0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,
+0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,0xf8,0x04,0x68,0xac,0xce,0x04,0x47,0xa0,
+0x6c,0x05,0x6a,0xac,0xef,0xff,0x80,0x14,0x94,0x04,0x49,0xa0,0x02,0x80,0x02,0x3c,
+0x78,0x1b,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x98,0xac,0x6b,0x24,
+0x38,0xab,0x4c,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
+0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
+0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
+0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2c,0x02,
+0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
+0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,
+0x05,0x00,0x29,0x25,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
+0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
+0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x29,0xb0,0x02,0x3c,0xf8,0xff,0xbd,0x27,
+0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34,
+0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34,
+0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34,
+0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,
+0x3c,0x00,0x51,0x34,0x38,0x00,0x50,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac,
+0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0x21,0x20,0x00,0x00,0x00,0x00,0xc0,0xac,
+0xff,0xff,0x05,0x24,0x00,0x00,0xe0,0xac,0x78,0x1b,0x46,0x24,0x00,0x00,0x00,0xad,
+0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,
+0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,
+0x00,0x00,0x20,0xae,0x21,0x18,0x86,0x00,0x01,0x00,0x84,0x24,0x08,0x00,0x82,0x28,
+0xfc,0xff,0x40,0x14,0xf0,0x04,0x65,0xa0,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,
+0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,0xf0,0x00,0x42,0x34,
+0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x04,0x00,0xb1,0x8f,
+0x00,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x08,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27,
+0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,0x02,0x80,0x13,0x3c,0x30,0xb0,0x46,0x24,
+0x78,0x1b,0x63,0x26,0xb0,0x02,0xb2,0xaf,0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf,
+0x03,0x00,0x60,0xa0,0x21,0x38,0xa0,0x03,0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c,
+0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24,
+0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac,
+0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c,
+0xc4,0xb0,0x58,0x24,0x00,0x00,0xe3,0xac,0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27,
+0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,
+0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,
+0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,
+0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,
+0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,
+0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,
+0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,
+0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,
+0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,
+0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,
+0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,
+0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,
+0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,
+0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,
+0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,
+0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,
+0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,
+0xcc,0xb1,0x58,0x24,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27,
+0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,
+0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,
+0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,
+0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,
+0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,
+0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,
+0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,
+0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,
+0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,
+0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,
+0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,
+0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,
+0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,
+0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,
+0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,
+0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,
+0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00,
+0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x78,0x1b,0x46,0x24,
+0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c,
+0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d,
+0xf8,0xff,0x40,0x14,0x18,0x00,0x85,0xac,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4b,0x24,
+0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00,
+0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90,
+0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c,
+0xb4,0x01,0x66,0xa0,0xf7,0xff,0x40,0x14,0xac,0x00,0x65,0xa0,0x01,0x00,0x42,0x25,
+0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00,
+0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
+0x20,0x00,0x63,0x30,0x4f,0x00,0x60,0x10,0x78,0x1b,0x64,0x26,0x33,0x00,0x02,0x24,
+0xc1,0x02,0x62,0xa1,0x1c,0x00,0x03,0x24,0x0f,0x00,0x02,0x24,0xbc,0x02,0x63,0xa1,
+0xbd,0x02,0x62,0xa1,0x78,0x1b,0x65,0x26,0x08,0x00,0xa4,0x8c,0xff,0x7f,0x09,0x3c,
+0xff,0xff,0x29,0x35,0xc0,0xff,0x02,0x24,0x24,0x20,0x89,0x00,0x24,0x20,0x82,0x00,
+0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,0xc8,0x02,0xa0,0xa0,0x24,0x20,0x82,0x00,
+0xc0,0xff,0x02,0x3c,0xc8,0x02,0xa6,0x8c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,
+0x24,0x20,0x82,0x00,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xbf,0xff,0x03,0x3c,
+0x24,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,
+0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34,
+0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0x7f,0x42,0x34,0xc8,0x02,0xa6,0xac,
+0x24,0x20,0x82,0x00,0xc9,0x02,0xa0,0xa0,0x0c,0x00,0xa6,0x8c,0xff,0x9f,0x02,0x3c,
+0xc8,0x02,0xa7,0x8c,0xff,0xff,0x42,0x34,0xff,0xbf,0x03,0x3c,0x10,0x00,0xa8,0x8c,
+0xff,0xff,0x63,0x34,0x24,0x20,0x82,0x00,0xff,0xf0,0x02,0x3c,0x24,0x30,0xc3,0x00,
+0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x38,0xe2,0x00,
+0xb4,0x02,0xb3,0x8f,0x1f,0x00,0x02,0x24,0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,
+0xa8,0x02,0xb0,0x8f,0x24,0x40,0x03,0x01,0xbe,0x02,0xa2,0xa0,0x01,0x00,0x03,0x24,
+0xff,0xff,0x02,0x24,0x24,0x30,0xc9,0x00,0xc0,0x02,0xa3,0xa0,0xc2,0x02,0xa2,0xa0,
+0xff,0x00,0x03,0x24,0x12,0x00,0x02,0x24,0xb8,0x02,0xbd,0x27,0xc8,0x02,0xa7,0xac,
+0x08,0x00,0xa4,0xac,0x10,0x00,0xa8,0xac,0x0c,0x00,0xa6,0xac,0xc4,0x02,0xa3,0xa4,
+0xc7,0x02,0xa2,0xa0,0xca,0x02,0xa0,0xa0,0xbf,0x02,0xa0,0xa0,0x08,0x00,0xe0,0x03,
+0xc6,0x02,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x02,0x82,0xa0,0x0d,0x00,0x03,0x24,
+0x03,0x00,0x02,0x24,0xbc,0x02,0x83,0xa0,0x97,0x63,0x00,0x08,0xbd,0x02,0x82,0xa0,
+0x02,0x80,0x19,0x3c,0x78,0x1b,0x22,0x27,0xe0,0xff,0xbd,0x27,0xff,0xff,0x03,0x34,
+0x18,0x00,0xbf,0xaf,0x21,0xc0,0x40,0x00,0xf4,0x23,0x43,0xac,0xea,0x02,0x40,0xa0,
+0x1f,0x00,0x0f,0x24,0xff,0xff,0xef,0x25,0x80,0x11,0x43,0xac,0x84,0x11,0x43,0xac,
+0xfc,0xff,0xe1,0x05,0x94,0x00,0x42,0x24,0x78,0x1b,0x24,0x8f,0xd8,0x02,0x05,0x8f,
+0xf0,0xff,0x02,0x3c,0xe8,0x02,0x07,0x8f,0xfd,0xff,0x03,0x24,0xff,0xff,0x42,0x34,
+0x24,0x20,0x83,0x00,0x24,0x28,0xa2,0x00,0x20,0x00,0x0f,0x24,0xff,0xff,0x0e,0x24,
+0xff,0xef,0x02,0x3c,0x78,0x1b,0x24,0xaf,0xff,0xff,0x42,0x34,0xd8,0x02,0x05,0xaf,
+0x02,0x00,0x0e,0xa3,0xdb,0x02,0x0f,0xa3,0xd8,0x02,0x00,0xa3,0xff,0xbf,0x03,0x3c,
+0x78,0x1b,0x28,0x8f,0xd8,0x02,0x09,0x8f,0x24,0x38,0xe2,0x00,0xff,0xff,0x63,0x34,
+0x24,0x38,0xe3,0x00,0xff,0x7f,0x02,0x3c,0x0f,0xff,0x03,0x3c,0xfe,0xff,0x04,0x24,
+0xff,0xff,0x42,0x34,0xff,0xff,0x63,0x34,0x24,0x40,0x04,0x01,0x24,0x38,0xe2,0x00,
+0x24,0x48,0x23,0x01,0xff,0xdf,0x02,0x3c,0xcf,0xff,0x03,0x24,0x24,0x40,0x03,0x01,
+0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x3c,0x24,0x38,0xe2,0x00,0x25,0x48,0x23,0x01,
+0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,0x78,0x1b,0x28,0xaf,0x02,0x80,0x0a,0x3c,
+0xd6,0x02,0x02,0xa3,0xd0,0x02,0x03,0xa7,0x00,0x01,0x02,0x24,0x49,0x00,0x03,0x24,
+0xe8,0x02,0x07,0xaf,0xd8,0x02,0x09,0xaf,0xac,0xb5,0x4a,0x25,0x3e,0x00,0x0c,0x24,
+0x1c,0x00,0x0d,0x24,0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xce,0x02,0x02,0xa7,
+0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3,
+0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xc8,0x66,0xc6,0x24,
+0xd4,0x02,0x0c,0xa3,0xd5,0x02,0x0d,0xa3,0xcc,0x02,0x0f,0xa7,0x01,0x00,0x0b,0xa3,
+0x0c,0x00,0x43,0xad,0x14,0x00,0x4b,0xa1,0x06,0x00,0x0e,0xa7,0xd2,0x02,0x0c,0xa3,
+0xd3,0x02,0x0d,0xa3,0x12,0x00,0xa2,0xa3,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,
+0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
+0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,
+0x52,0x28,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,
+0x54,0xb6,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,
+0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,
+0xe4,0x69,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,
+0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,
+0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x09,0x3c,0x78,0x1b,0x23,0x8d,
+0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,0xf3,0xff,0x02,0x24,0x24,0x18,0x62,0x00,
+0x3f,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0xd8,0xff,0xbd,0x27,0x78,0x1b,0x23,0xad,
+0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,0x02,0x80,0x08,0x3c,0x70,0xb6,0x08,0x25,
+0x18,0x00,0xb0,0xaf,0x10,0x00,0xa2,0xa3,0x78,0x1b,0x30,0x25,0x11,0x00,0xa3,0xa3,
+0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x00,0x07,0x3c,0x00,0x80,0x06,0x3c,
+0x08,0x03,0x0b,0xae,0x1c,0x00,0xb1,0xaf,0x56,0x30,0xea,0x34,0x43,0x00,0x11,0x24,
+0xf4,0x98,0xe7,0x34,0x10,0x00,0xa5,0x27,0x0c,0x00,0x02,0xad,0x14,0x00,0x03,0xa1,
+0x21,0x20,0x00,0x01,0xd8,0x73,0xc6,0x24,0x20,0x00,0xbf,0xaf,0x12,0x00,0xb1,0xa3,
+0x10,0x03,0x07,0xae,0x14,0x03,0x0a,0xae,0x13,0x00,0xa0,0xa3,0x0c,0x03,0x00,0xae,
+0x18,0x03,0x00,0xae,0xa8,0x14,0x00,0x0c,0x1c,0x03,0x00,0xae,0x1e,0x00,0x02,0x24,
+0x25,0x03,0x02,0xa2,0x4a,0x00,0x03,0x24,0x45,0x00,0x02,0x24,0x20,0x03,0x03,0xa2,
+0x21,0x03,0x02,0xa2,0x23,0x00,0x03,0x24,0x3e,0x00,0x02,0x24,0x22,0x03,0x11,0xa2,
+0x23,0x03,0x02,0xa2,0x24,0x03,0x03,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,
+0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
+0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,
+0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0x8c,0xb6,0xe7,0x24,
+0x12,0x00,0xa2,0xa3,0x4f,0x1e,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
+0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x04,0x78,0xc6,0x24,
+0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,
+0x10,0x00,0xa3,0xa3,0xc8,0x3f,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,
+0x02,0x80,0x07,0x3c,0xc4,0xb6,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,
+0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
+0x21,0x20,0xe0,0x00,0x28,0x6b,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
+0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
+0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,
+0xd8,0xff,0xbd,0x27,0x80,0x3f,0x84,0x24,0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf,
+0x3e,0x46,0x00,0x0c,0x0a,0x00,0x06,0x24,0x02,0x80,0x07,0x3c,0x78,0x1b,0xe7,0x24,
+0x04,0x24,0xe3,0x8c,0xfd,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00,
+0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x05,0x00,0x02,0x24,0x04,0x24,0xe3,0xac,
+0x08,0x24,0xe2,0xa0,0x28,0x00,0x03,0x24,0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,
+0x09,0x24,0xe3,0xa0,0x4b,0x00,0x02,0x24,0x42,0x00,0x03,0x24,0xe0,0xb6,0x08,0x25,
+0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,
+0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,0xf0,0x6b,0xc6,0x24,
+0x06,0x24,0xe0,0xa4,0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0xa8,0x14,0x00,0x0c,
+0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
+0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x03,0x3c,0x1c,0x00,0xbf,0xaf,
+0x18,0x00,0xb0,0xaf,0x44,0xaf,0x62,0x24,0x02,0x00,0x48,0x90,0x44,0xaf,0x67,0x94,
+0x02,0x80,0x02,0x3c,0x60,0x44,0x42,0x24,0x02,0x00,0x10,0x24,0x01,0x80,0x06,0x3c,
+0x21,0x20,0x40,0x00,0x10,0x00,0xa5,0x27,0x14,0x00,0x50,0xa0,0x34,0x83,0xc6,0x24,
+0x10,0x00,0xa7,0xa7,0x12,0x00,0xa8,0xa3,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,
+0x02,0x80,0x02,0x3c,0x7c,0x44,0x42,0x24,0x01,0x80,0x06,0x3c,0x21,0x20,0x40,0x00,
+0x10,0x00,0xa5,0x27,0x14,0x00,0x50,0xa0,0xa8,0x14,0x00,0x0c,0x68,0x82,0xc6,0x24,
+0x02,0x80,0x02,0x3c,0x98,0x44,0x40,0xa0,0x0c,0x00,0x04,0x24,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0x99,0x44,0x64,0xa0,0x9a,0x44,0x44,0xa0,0x02,0x80,0x03,0x3c,
+0x02,0x80,0x02,0x3c,0xb1,0x44,0x60,0xa0,0x01,0x00,0x06,0x24,0xb7,0x44,0x40,0xa0,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb8,0x44,0x60,0xa0,0x9c,0x44,0x46,0xa0,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb9,0x44,0x60,0xa0,0x08,0x00,0x04,0x24,
+0x9b,0x44,0x46,0xa0,0x02,0x80,0x02,0x3c,0x9d,0x44,0x44,0xa0,0x01,0x00,0x05,0x24,
+0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x9e,0x44,0x60,0xa0,0x64,0x00,0x04,0x24,
+0xa8,0x44,0x45,0xa4,0x02,0x80,0x03,0x3c,0x01,0x00,0x02,0x3c,0xa0,0x44,0x64,0xa4,
+0x00,0x90,0x42,0x34,0x02,0x80,0x03,0x3c,0xa4,0x44,0x62,0xac,0x02,0x80,0x04,0x3c,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xac,0x44,0x80,0xac,0x1c,0x00,0xbf,0x8f,
+0xb0,0x44,0x40,0xa0,0x18,0x00,0xb0,0x8f,0xb2,0x44,0x60,0xa0,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0xba,0x44,0x40,0xa0,0xb3,0x44,0x60,0xa0,0x02,0x80,0x02,0x3c,
+0x02,0x80,0x03,0x3c,0xb4,0x44,0x45,0xa0,0x20,0x00,0xbd,0x27,0xb5,0x44,0x65,0xa0,
+0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xb6,0x44,0x40,0xa0,0xbc,0x44,0x60,0xac,
+0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00,
+0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00,
+0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00,
+0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00,
+0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00,
+0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00,
+0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00,
+0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,
+0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00,
+0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00,
+0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00,
+0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00,
+0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00,
+0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00,
+0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00,
+0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00,
+0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,
+0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,
+0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00,
+0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00,
+0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00,
+0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00,
+0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00,
+0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00,
+0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00,
+0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00,
+0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00,
+0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00,
+0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00,
+0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00,
+0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00,
+0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00,
+0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00,
+0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00,
+0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00,
+0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00,
+0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00,
+0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00,
+0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00,
+0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
+0x64,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x6c,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x7c,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x84,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x8c,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x94,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x9c,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0xa4,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0xac,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
+0x9c,0x2d,0x00,0x80,0x10,0x00,0x00,0x00,0x94,0x2d,0x00,0x80,0x10,0x00,0x00,0x00,
+0xb4,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0xbc,0x05,0x01,0x80,0x34,0x01,0x00,0x00,
+0xc4,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xcc,0x05,0x01,0x80,0x34,0x01,0x00,0x00,
+0xc4,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xd4,0x05,0x01,0x80,0x30,0x00,0x00,0x00,
+0xdc,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xe4,0x05,0x01,0x80,0x13,0x00,0x00,0x00,
+0xec,0x05,0x01,0x80,0x17,0x00,0x00,0x00,0xf4,0x05,0x01,0x80,0x06,0x00,0x00,0x00,
+0xfc,0x05,0x01,0x80,0x06,0x00,0x00,0x00,0x04,0x06,0x01,0x80,0x08,0x00,0x00,0x00,
+0x0c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0x14,0x06,0x01,0x80,0x04,0x00,0x00,0x00,
+0x1c,0x06,0x01,0x80,0x1f,0x00,0x00,0x00,0x24,0x06,0x01,0x80,0x01,0x00,0x00,0x00,
+0x2c,0x06,0x01,0x80,0x38,0x00,0x00,0x00,0x34,0x06,0x01,0x80,0x04,0x00,0x00,0x00,
+0x3c,0x06,0x01,0x80,0x02,0x00,0x00,0x00,0x44,0x06,0x01,0x80,0x04,0x00,0x00,0x00,
+0x4c,0x06,0x01,0x80,0x01,0x00,0x00,0x00,0x54,0x06,0x01,0x80,0x01,0x00,0x00,0x00,
+0x5c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0x64,0x06,0x01,0x80,0x0e,0x00,0x00,0x00,
+0x6c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0xb8,0x08,0x01,0x80,0x78,0x00,0x00,0x00,
+0xf0,0x09,0x01,0x80,0x04,0x00,0x00,0x00,0xf8,0x09,0x01,0x80,0x04,0x00,0x00,0x00,
+0xa4,0x2d,0x00,0x80,0x04,0x00,0x00,0x00,0xac,0x2d,0x00,0x80,0x04,0x00,0x00,0x00,
+0xb4,0x2d,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x0a,0x01,0x80,0x08,0x00,0x00,0x00,
+0x08,0x0a,0x01,0x80,0x10,0x00,0x00,0x00,0x10,0x0a,0x01,0x80,0x01,0x00,0x00,0x00,
+0x18,0x0a,0x01,0x80,0x01,0x00,0x00,0x00,0x20,0x0a,0x01,0x80,0x10,0x00,0x00,0x00,
+0xc4,0x2d,0x00,0x80,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,
+0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,
+0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,
+0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,
+0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,
+0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,
+0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,
+0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,
+0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,
+0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,
+0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,
+0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,
+0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,
+0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,
+0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,
+0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,
+0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,
+0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,
+0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,
+0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,
+0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,
+0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,
+0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,
+0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,
+0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,
+0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,
+0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,
+0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,
+0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,
+0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,
+0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,
+0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,
+0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,
+0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,
+0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,
+0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,
+0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,
+0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,
+0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,
+0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,
+0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,
+0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,
+0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,
+0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,
+0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,
+0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,
+0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,
+0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,
+0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,
+0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,
+0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,
+0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,
+0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,
+0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,
+0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,
+0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,
+0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,
+0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,
+0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,
+0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,
+0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,
+0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,
+0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,
+0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,
+0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,
+0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,
+0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,
+0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,
+0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,
+0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,
+0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,
+0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,
+0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,
+0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,
+0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,
+0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,
+0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,
+0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,
+0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,
+0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,
+0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,
+0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,
+0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,
+0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,
+0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,
+0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,
+0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,
+0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,
+0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,
+0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,
+0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,
+0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,
+0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,
+0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,
+0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,
+0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,
+0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,
+0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,
+0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,
+0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,
+0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,
+0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,
+0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,
+0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,
+0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,
+0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,
+0xff,0xff,0xff,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,
+0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x4f,0x6e,0x52,0x65,
+0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,0x4f,0x6e,0x52,0x65,
+0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,0x4f,0x6e,0x50,0x72,
+0x6f,0x62,0x65,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,
+0x73,0x70,0x00,0x00,0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,0x00,0x00,0x00,0x00,
+0x4f,0x6e,0x41,0x54,0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,0x73,0x61,0x73,0x73,
+0x6f,0x63,0x00,0x00,0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,0x4f,0x6e,0x44,0x65,
+0x41,0x75,0x74,0x68,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,0x74,0x69,0x6f,0x6e,
+0x00,0x00,0x00,0x00,0x4f,0x6e,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6f,0x6e,0x00,
+0x00,0x00,0x00,0x00,0xfc,0xa7,0x01,0x80,0x24,0x2f,0x00,0x80,0x10,0x00,0x00,0x00,
+0x08,0xa8,0x01,0x80,0x2c,0x2f,0x00,0x80,0x20,0x00,0x00,0x00,0x14,0xa8,0x01,0x80,
+0x24,0x2f,0x00,0x80,0x30,0x00,0x00,0x00,0x24,0xa8,0x01,0x80,0x2c,0x2f,0x00,0x80,
+0x40,0x00,0x00,0x00,0x34,0xa8,0x01,0x80,0x34,0x2f,0x00,0x80,0x50,0x00,0x00,0x00,
+0x40,0xa8,0x01,0x80,0x54,0x2f,0x00,0x80,0x80,0x00,0x00,0x00,0x4c,0xa8,0x01,0x80,
+0x04,0x30,0x00,0x80,0x90,0x00,0x00,0x00,0x58,0xa8,0x01,0x80,0x5c,0x2f,0x00,0x80,
+0xa0,0x00,0x00,0x00,0x60,0xa8,0x01,0x80,0x6c,0x2f,0x00,0x80,0xb0,0x00,0x00,0x00,
+0x6c,0xa8,0x01,0x80,0x64,0x2f,0x00,0x80,0xc0,0x00,0x00,0x00,0x74,0xa8,0x01,0x80,
+0x74,0x2f,0x00,0x80,0xd0,0x00,0x00,0x00,0x80,0xa8,0x01,0x80,0x7c,0x2f,0x00,0x80,
+0x0c,0x00,0x00,0x00,0x8c,0xa8,0x01,0x80,0x98,0x2f,0x00,0x80,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,
+0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x04,0x05,0x06,0x07,0x08,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x01,0x80,0x00,0xaa,0x01,0x80,
+0x31,0x10,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00,
+0x31,0x28,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00,
+0x31,0x2f,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00,
+0x31,0x30,0x20,0x10,0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00,
+0x22,0x21,0x14,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00,
+0x22,0x21,0x20,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00,
+0x22,0x21,0x20,0x18,0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00,
+0x12,0x11,0x10,0x08,0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00,
+0x0a,0x09,0x08,0x02,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00,
+0x0a,0x09,0x08,0x06,0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00,
+0x06,0x05,0x04,0x02,0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00,
+0x05,0x04,0x03,0x02,0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,
+0x05,0x04,0x04,0x03,0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03,
+0x03,0x02,0x02,0x02,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,
+0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01,
+0x01,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,
+0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,
+0x30,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,
+0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,
+0x08,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,
+0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,
+0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
+0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,
+0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,
+0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,
+0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,
+0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,
+0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,
+0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,
+0x20,0x08,0x00,0x22,0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08,
+0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,
+0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,
+0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,
+0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,
+0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,
+0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,
+0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,
+0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,
+0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,
+0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,
+0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,
+0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04,
+0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,
+0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,
+0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,
+0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,
+0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08,
+0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
+0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,
+0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,
+0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,
+0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,
+0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,
+0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,
+0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,
+0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,
+0x10,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,
+0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48,
+0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x27,0x2c,
+0x19,0x1b,0x1e,0x20,0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,0x25,0x29,0x2b,0x2e,
+0x2e,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
+0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
+0xd8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,
+0xc8,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,
+0x30,0x02,0x00,0x00,0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,
+0xd0,0x02,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,
+0xa0,0x0f,0x00,0x00,0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
+0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,
+0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
+0x60,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,
+0x50,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,
+0xf0,0x00,0x00,0x00,0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,
+0xf0,0x00,0x00,0x00,0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,
+0x40,0x06,0x00,0x00,0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x30,0x7a,0x00,0x80,
+0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80,
+0xd8,0x83,0x00,0x80,0x38,0x7a,0x00,0x80,0x30,0x7a,0x00,0x80,0x30,0x7a,0x00,0x80,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x86,0x00,0x80,0xb8,0x86,0x00,0x80,
+0xb8,0x86,0x00,0x80,0xb8,0x86,0x00,0x80,0xfc,0x6c,0x01,0x80,0x1c,0x6d,0x01,0x80,
+0x04,0x6d,0x01,0x80,0x0c,0x6d,0x01,0x80,0x14,0x6d,0x01,0x80,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x08,0x02,0x02,0x01,0x01,0x50,0x53,0x00,0x00,
+0xf8,0x07,0x00,0x80,0xec,0x07,0x00,0x80,0xe0,0x07,0x00,0x80,0xd4,0x07,0x00,0x80,
+0xc8,0x07,0x00,0x80,0xbc,0x07,0x00,0x80,0xb0,0x07,0x00,0x80,0xa4,0x07,0x00,0x80,
+0x98,0x07,0x00,0x80,0x8c,0x07,0x00,0x80,0x44,0x07,0x00,0x80,0xb0,0x03,0x25,0xb0,
+0x2c,0x00,0x2a,0xb0,0x78,0x1b,0x02,0x80,0xb0,0x03,0x25,0xb0,0x44,0x44,0x33,0x33,
+0x06,0x00,0x2a,0xb0,0x3c,0x47,0x00,0x80,0x30,0x47,0x00,0x80,0x24,0x47,0x00,0x80,
+0x18,0x47,0x00,0x80,0x0c,0x47,0x00,0x80,0x00,0x47,0x00,0x80,0xf4,0x46,0x00,0x80,
+0xe8,0x46,0x00,0x80,0xdc,0x46,0x00,0x80,0xd0,0x46,0x00,0x80,0xc4,0x46,0x00,0x80,
+0xb8,0x46,0x00,0x80,0x60,0x3f,0x01,0x80,0x48,0x3f,0x01,0x80,0x30,0x3f,0x01,0x80,
+0x18,0x3f,0x01,0x80,0x00,0x3f,0x01,0x80,0xe8,0x3e,0x01,0x80,0xb4,0x3e,0x01,0x80,
+0x00,0x02,0x00,0x00,0x08,0x09,0x00,0x00,0x0c,0x58,0x00,0x80,0x18,0x58,0x00,0x80,
+0x24,0x58,0x00,0x80,0x30,0x58,0x00,0x80,0x0c,0x58,0x00,0x80,0x0c,0x58,0x00,0x80,
+0x0c,0x58,0x00,0x80,0x0c,0x58,0x00,0x80,0x3c,0x58,0x00,0x80,0x48,0x58,0x00,0x80,
+0x54,0x58,0x00,0x80,0x60,0x58,0x00,0x80,0x78,0x1b,0x02,0x80,0x78,0x1b,0x02,0x80,
+0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,0x8c,0x0e,0x25,0xb0,0xd0,0x0e,0x25,0xb0,
+0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,0xfe,0x01,0x80,0x7f,0xe2,0x01,0x80,0x78,
+0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,0x7f,0x01,0xc0,0x5f,
+0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,0x30,0x01,0x00,0x4c,
+0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,0xf2,0x00,0x80,0x3c,
+0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,0xc0,0x00,0x00,0x30,
+0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,0x98,0x00,0x00,0x26,
+0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,0x79,0x00,0x40,0x1e,
+0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,0x60,0x00,0x00,0x18,
+0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,0x4c,0x00,0x00,0x13,
+0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,0x36,0x35,0x2e,0x25,
+0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,0x30,0x2f,0x29,0x21,
+0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,0x2b,0x2a,0x25,0x1e,
+0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,0x26,0x25,0x21,0x1b,
+0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,0x22,0x21,0x1d,0x18,
+0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,0x1f,0x1e,0x1a,0x15,
+0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,0x1b,0x1a,0x17,0x13,
+0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,0x18,0x17,0x15,0x11,
+0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,0x16,0x15,0x12,0x0f,
+0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,0x13,0x13,0x10,0x0d,
+0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,0x11,0x11,0x0f,0x0c,
+0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,0x0f,0x0f,0x0d,0x0b,
+0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,0x0d,0x0d,0x0c,0x0a,
+0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,0x0c,0x0c,0x0a,0x09,
+0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,0x0b,0x0a,0x09,0x08,
+0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,0x0a,0x09,0x08,0x07,
+0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,0x09,0x08,0x07,0x06,
+0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,0x33,0x32,0x2b,0x19,
+0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,0x2d,0x2d,0x17,0x17,
+0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,0x28,0x28,0x24,0x14,
+0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,0x24,0x23,0x1f,0x12,
+0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,0x20,0x20,0x1b,0x10,
+0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,0x1d,0x1c,0x18,0x0e,
+0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,0x1a,0x19,0x16,0x0d,
+0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,0x17,0x16,0x13,0x0b,
+0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,0x14,0x14,0x11,0x0a,
+0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,0x12,0x12,0x0f,0x09,
+0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,0x10,0x10,0x0e,0x08,
+0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0c,0x07,
+0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0c,0x0b,0x06,
+0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06,
+0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05,
+0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x05,
+0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x2a,0xb0,
+0x05,0x00,0x2a,0xb0,0x34,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0x60,0x7b,0x00,0x80,
+0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,
+0x08,0x7b,0x00,0x80,0x00,0x01,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x36,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x45,0xc4,0xf0,0x00,0x45,0xc4,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x45,0xb5,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xc7,0x00,0xb8,0xff,0xff,0xff,0xff,
+};
+
+u8 Rtl8192SEFwMainArray[MainArrayLength] = {
+0x0, };
+
+u8 Rtl8192SEFwDataArray[DataArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = {
+0x01c,0x07000000,
+0x800,0x00040000,
+0x804,0x00008003,
+0x808,0x0000fc00,
+0x80c,0x0000000a,
+0x810,0x10005088,
+0x814,0x020c3d10,
+0x818,0x00200185,
+0x81c,0x00000000,
+0x820,0x01000000,
+0x824,0x00390004,
+0x828,0x01000000,
+0x82c,0x00390004,
+0x830,0x00000004,
+0x834,0x00690200,
+0x838,0x00000004,
+0x83c,0x00690200,
+0x840,0x00010000,
+0x844,0x00010000,
+0x848,0x00000000,
+0x84c,0x00000000,
+0x850,0x00000000,
+0x854,0x00000000,
+0x858,0x48484848,
+0x85c,0x65a965a9,
+0x860,0x0f7f0130,
+0x864,0x0f7f0130,
+0x868,0x0f7f0130,
+0x86c,0x0f7f0130,
+0x870,0x03000700,
+0x874,0x03000300,
+0x878,0x00020002,
+0x87c,0x004f0201,
+0x880,0xa8300ac1,
+0x884,0x00000058,
+0x888,0x00000008,
+0x88c,0x00000004,
+0x890,0x00000000,
+0x894,0xfffffffe,
+0x898,0x40302010,
+0x89c,0x00706050,
+0x8b0,0x00000000,
+0x8e0,0x00000000,
+0x8e4,0x00000000,
+0xe00,0x30333333,
+0xe04,0x2a2d2e2f,
+0xe08,0x00003232,
+0xe10,0x30333333,
+0xe14,0x2a2d2e2f,
+0xe18,0x30333333,
+0xe1c,0x2a2d2e2f,
+0xe30,0x01007c00,
+0xe34,0x01004800,
+0xe38,0x1000dc1f,
+0xe3c,0x10008c1f,
+0xe40,0x021400a0,
+0xe44,0x281600a0,
+0xe48,0xf8000001,
+0xe4c,0x00002910,
+0xe50,0x01007c00,
+0xe54,0x01004800,
+0xe58,0x1000dc1f,
+0xe5c,0x10008c1f,
+0xe60,0x021400a0,
+0xe64,0x281600a0,
+0xe6c,0x00002910,
+0xe70,0x31ed92fb,
+0xe74,0x361536fb,
+0xe78,0x361536fb,
+0xe7c,0x361536fb,
+0xe80,0x361536fb,
+0xe84,0x000d92fb,
+0xe88,0x000d92fb,
+0xe8c,0x31ed92fb,
+0xed0,0x31ed92fb,
+0xed4,0x31ed92fb,
+0xed8,0x000d92fb,
+0xedc,0x000d92fb,
+0xee0,0x000d92fb,
+0xee4,0x015e5448,
+0xee8,0x21555448,
+0x900,0x00000000,
+0x904,0x00000023,
+0x908,0x00000000,
+0x90c,0x01121313,
+0xa00,0x00d047c8,
+0xa04,0x80ff0008,
+0xa08,0x88cd8300,
+0xa0c,0x2e62120f,
+0xa10,0x9500bb78,
+0xa14,0x11144028,
+0xa18,0x00881117,
+0xa1c,0x89140f00,
+0xa20,0x1a1b0000,
+0xa24,0x090e1317,
+0xa28,0x00000204,
+0xa2c,0x10d30000,
+0xc00,0x40071d40,
+0xc04,0x00a05633,
+0xc08,0x000000e4,
+0xc0c,0x6c6c6c6c,
+0xc10,0x08800000,
+0xc14,0x40000100,
+0xc18,0x08000000,
+0xc1c,0x40000100,
+0xc20,0x08000000,
+0xc24,0x40000100,
+0xc28,0x08000000,
+0xc2c,0x40000100,
+0xc30,0x6de9ac44,
+0xc34,0x469652cf,
+0xc38,0x49795994,
+0xc3c,0x0a979764,
+0xc40,0x1f7c403f,
+0xc44,0x000100b7,
+0xc48,0xec020000,
+0xc4c,0x007f037f,
+0xc50,0x69543420,
+0xc54,0x433c0094,
+0xc58,0x69543420,
+0xc5c,0x433c0094,
+0xc60,0x69543420,
+0xc64,0x433c0094,
+0xc68,0x69543420,
+0xc6c,0x433c0094,
+0xc70,0x2c7f000d,
+0xc74,0x0186175b,
+0xc78,0x0000001f,
+0xc7c,0x00b91612,
+0xc80,0x40000100,
+0xc84,0x20f60000,
+0xc88,0x20000080,
+0xc8c,0x20200000,
+0xc90,0x40000100,
+0xc94,0x00000000,
+0xc98,0x40000100,
+0xc9c,0x00000000,
+0xca0,0x00492492,
+0xca4,0x00000000,
+0xca8,0x00000000,
+0xcac,0x00000000,
+0xcb0,0x00000000,
+0xcb4,0x00000000,
+0xcb8,0x00000000,
+0xcbc,0x28000000,
+0xcc0,0x00000000,
+0xcc4,0x00000000,
+0xcc8,0x00000000,
+0xccc,0x00000000,
+0xcd0,0x00000000,
+0xcd4,0x00000000,
+0xcd8,0x64b22427,
+0xcdc,0x00766932,
+0xce0,0x00222222,
+0xce4,0x00000000,
+0xce8,0x37644302,
+0xcec,0x2f97d40c,
+0xd00,0x00000750,
+0xd04,0x00000403,
+0xd08,0x0000907f,
+0xd0c,0x00000001,
+0xd10,0xa0633333,
+0xd14,0x33333c63,
+0xd18,0x6a8f5b6b,
+0xd1c,0x00000000,
+0xd20,0x00000000,
+0xd24,0x00000000,
+0xd28,0x00000000,
+0xd2c,0xcc979975,
+0xd30,0x00000000,
+0xd34,0x00000000,
+0xd38,0x00000000,
+0xd3c,0x00027293,
+0xd40,0x00000000,
+0xd44,0x00000000,
+0xd48,0x00000000,
+0xd50,0x6437140a,
+0xd54,0x024dbd02,
+0xd58,0x00000000,
+0xd5c,0x30032064,
+0xd60,0x4653de68,
+0xd64,0x00518a3c,
+0xd68,0x00002101,
+0xf14,0x00000003,
+0xf4c,0x00000000,
+0xf00,0x00000300,
+};
+
+u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = {
+0x0, };
+
+u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = {
+0x844,0xffffffff,0x00010000,
+0x804,0x0000000f,0x00000001,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00100002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000011,
+0xd04,0x0000000f,0x00000001,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300002,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000000,
+0x878,0x000f000f,0x00000002,
+0xe74,0x0f000000,0x00000002,
+0xe78,0x0f000000,0x00000002,
+0xe7c,0x0f000000,0x00000002,
+0xe80,0x0f000000,0x00000002,
+0x90c,0x000000ff,0x00000011,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x00007777,
+0x234,0xf8000000,0x0000000a,
+};
+
+u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = {
+0x804,0x0000000f,0x00000003,
+0x824,0x00f0000f,0x00300004,
+0x82c,0x00f0000f,0x00300004,
+0x870,0x04000000,0x00000001,
+0x864,0x00000400,0x00000001,
+0x878,0x000f000f,0x00020002,
+0xe74,0x0f000000,0x00000006,
+0xe78,0x0f000000,0x00000006,
+0xe7c,0x0f000000,0x00000006,
+0xe80,0x0f000000,0x00000006,
+0x90c,0x000000ff,0x00000033,
+0xc04,0x000000ff,0x00000033,
+0xd04,0x0000000f,0x00000003,
+0x1f4,0xffff0000,0x0000ffff,
+0x234,0xf8000000,0x00000013,
+};
+
+u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = {
+0xe00,0xffffffff,0x06090909,
+0xe04,0xffffffff,0x00030406,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x0a0c0d0e,
+0xe14,0xffffffff,0x03040508,
+0xe18,0xffffffff,0x0a0c0d0e,
+0xe1c,0xffffffff,0x03040508,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x04040404,
+0xe04,0xffffffff,0x00020204,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02040404,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02040404,
+0xe1c,0xffffffff,0x00000002,
+0xe00,0xffffffff,0x02020202,
+0xe04,0xffffffff,0x00020202,
+0xe08,0x0000ff00,0x00000000,
+0xe10,0xffffffff,0x02020202,
+0xe14,0xffffffff,0x00000002,
+0xe18,0xffffffff,0x02020202,
+0xe1c,0xffffffff,0x00000002,
+};
+
+u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x010,0x0002000f,
+0x011,0x00020101,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x0000f8f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x0009bd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x032,0x0000130d,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+0x013,0x00017cb0,
+0x013,0x00011cc0,
+0x013,0x0000dc60,
+0x013,0x00008c60,
+0x013,0x00004450,
+0x013,0x00000020,
+};
+
+u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00030250,
+0x002,0x00010000,
+0x010,0x0008000f,
+0x011,0x000231fc,
+0x010,0x000c000f,
+0x011,0x0003f9f8,
+0x014,0x0001093e,
+0x014,0x0009093e,
+0x015,0x000198f4,
+0x017,0x000f6500,
+0x01a,0x00013056,
+0x01b,0x00060000,
+0x01c,0x00000300,
+0x01e,0x00031059,
+0x021,0x00054000,
+0x022,0x0000083c,
+0x023,0x00001558,
+0x024,0x00000060,
+0x025,0x00022583,
+0x026,0x0000f200,
+0x027,0x000eacf1,
+0x028,0x000dbd54,
+0x029,0x00004582,
+0x02a,0x00000001,
+0x02b,0x00021334,
+0x02a,0x00000000,
+0x02b,0x0000000a,
+0x02a,0x00000001,
+0x02b,0x00000808,
+0x02b,0x00053333,
+0x02c,0x0000000c,
+0x02a,0x00000002,
+0x02b,0x00000808,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000003,
+0x02b,0x00000808,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000004,
+0x02b,0x00000808,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000005,
+0x02b,0x00000709,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x00000006,
+0x02b,0x00000709,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x00000007,
+0x02b,0x00000709,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x00000008,
+0x02b,0x00000709,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x00000009,
+0x02b,0x0000060a,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000a,
+0x02b,0x0000060a,
+0x02b,0x0005b333,
+0x02c,0x0000000d,
+0x02a,0x0000000b,
+0x02b,0x0000060a,
+0x02b,0x00063333,
+0x02c,0x0000000d,
+0x02a,0x0000000c,
+0x02b,0x0000060a,
+0x02b,0x0006b333,
+0x02c,0x0000000d,
+0x02a,0x0000000d,
+0x02b,0x0000050b,
+0x02b,0x00053333,
+0x02c,0x0000000d,
+0x02a,0x0000000e,
+0x02b,0x0000050b,
+0x02b,0x00066623,
+0x02c,0x0000001a,
+0x02a,0x000e4000,
+0x030,0x00020000,
+0x031,0x000b9631,
+0x033,0x00000187,
+0x013,0x00019e6c,
+0x013,0x00015e94,
+0x000,0x00010159,
+0x018,0x0000f401,
+0x0fe,0x00000000,
+0x01e,0x0003105b,
+0x0fe,0x00000000,
+0x000,0x00030159,
+0x010,0x0004000f,
+0x011,0x000203f9,
+};
+
+u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = {
+0x000,0x00030159,
+0x001,0x00001041,
+0x002,0x00011000,
+0x005,0x00080fc0,
+0x007,0x000fc803,
+};
+
+u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = {
+0x020,0x00000035,
+0x048,0x0000000e,
+0x049,0x000000f0,
+0x04a,0x00000077,
+0x04b,0x00000083,
+0x0b5,0x00000021,
+0x0dc,0x000000ff,
+0x0dd,0x000000ff,
+0x0de,0x000000ff,
+0x0df,0x000000ff,
+0x116,0x00000000,
+0x117,0x00000000,
+0x118,0x00000000,
+0x119,0x00000000,
+0x11a,0x00000000,
+0x11b,0x00000000,
+0x11c,0x00000000,
+0x11d,0x00000000,
+0x160,0x0000000b,
+0x161,0x0000000b,
+0x162,0x0000000b,
+0x163,0x0000000b,
+0x164,0x0000000b,
+0x165,0x0000000b,
+0x166,0x0000000b,
+0x167,0x0000000b,
+0x168,0x0000000b,
+0x169,0x0000000b,
+0x16a,0x0000000b,
+0x16b,0x0000000b,
+0x16c,0x0000000b,
+0x16d,0x0000000b,
+0x16e,0x0000000b,
+0x16f,0x0000000b,
+0x170,0x0000000b,
+0x171,0x0000000b,
+0x172,0x0000000b,
+0x173,0x0000000b,
+0x174,0x0000000b,
+0x175,0x0000000b,
+0x176,0x0000000b,
+0x177,0x0000000b,
+0x178,0x0000000b,
+0x179,0x0000000b,
+0x17a,0x0000000b,
+0x17b,0x0000000b,
+0x17c,0x0000000b,
+0x17d,0x0000000b,
+0x17e,0x0000000b,
+0x17f,0x0000000b,
+0x236,0x0000000c,
+0x503,0x00000022,
+0x560,0x00000000,
+};
+
+u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = {
+0x0, };
+
+u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = {
+0xc78,0x7f000001,
+0xc78,0x7f010001,
+0xc78,0x7e020001,
+0xc78,0x7d030001,
+0xc78,0x7c040001,
+0xc78,0x7b050001,
+0xc78,0x7a060001,
+0xc78,0x79070001,
+0xc78,0x78080001,
+0xc78,0x77090001,
+0xc78,0x760a0001,
+0xc78,0x750b0001,
+0xc78,0x740c0001,
+0xc78,0x730d0001,
+0xc78,0x720e0001,
+0xc78,0x710f0001,
+0xc78,0x70100001,
+0xc78,0x6f110001,
+0xc78,0x6f120001,
+0xc78,0x6e130001,
+0xc78,0x6d140001,
+0xc78,0x6d150001,
+0xc78,0x6c160001,
+0xc78,0x6b170001,
+0xc78,0x6a180001,
+0xc78,0x6a190001,
+0xc78,0x691a0001,
+0xc78,0x681b0001,
+0xc78,0x671c0001,
+0xc78,0x661d0001,
+0xc78,0x651e0001,
+0xc78,0x641f0001,
+0xc78,0x63200001,
+0xc78,0x4c210001,
+0xc78,0x4b220001,
+0xc78,0x4a230001,
+0xc78,0x49240001,
+0xc78,0x48250001,
+0xc78,0x47260001,
+0xc78,0x46270001,
+0xc78,0x45280001,
+0xc78,0x44290001,
+0xc78,0x2c2a0001,
+0xc78,0x2b2b0001,
+0xc78,0x2a2c0001,
+0xc78,0x292d0001,
+0xc78,0x282e0001,
+0xc78,0x272f0001,
+0xc78,0x26300001,
+0xc78,0x25310001,
+0xc78,0x24320001,
+0xc78,0x23330001,
+0xc78,0x22340001,
+0xc78,0x09350001,
+0xc78,0x08360001,
+0xc78,0x07370001,
+0xc78,0x06380001,
+0xc78,0x05390001,
+0xc78,0x043a0001,
+0xc78,0x033b0001,
+0xc78,0x023c0001,
+0xc78,0x013d0001,
+0xc78,0x003e0001,
+0xc78,0x003f0001,
+0xc78,0x7f400001,
+0xc78,0x7f410001,
+0xc78,0x7e420001,
+0xc78,0x7d430001,
+0xc78,0x7c440001,
+0xc78,0x7b450001,
+0xc78,0x7a460001,
+0xc78,0x79470001,
+0xc78,0x78480001,
+0xc78,0x77490001,
+0xc78,0x764a0001,
+0xc78,0x754b0001,
+0xc78,0x744c0001,
+0xc78,0x734d0001,
+0xc78,0x724e0001,
+0xc78,0x714f0001,
+0xc78,0x70500001,
+0xc78,0x6f510001,
+0xc78,0x6f520001,
+0xc78,0x6e530001,
+0xc78,0x6d540001,
+0xc78,0x6d550001,
+0xc78,0x6c560001,
+0xc78,0x6b570001,
+0xc78,0x6a580001,
+0xc78,0x6a590001,
+0xc78,0x695a0001,
+0xc78,0x685b0001,
+0xc78,0x675c0001,
+0xc78,0x665d0001,
+0xc78,0x655e0001,
+0xc78,0x645f0001,
+0xc78,0x63600001,
+0xc78,0x4c610001,
+0xc78,0x4b620001,
+0xc78,0x4a630001,
+0xc78,0x49640001,
+0xc78,0x48650001,
+0xc78,0x47660001,
+0xc78,0x46670001,
+0xc78,0x45680001,
+0xc78,0x44690001,
+0xc78,0x2c6a0001,
+0xc78,0x2b6b0001,
+0xc78,0x2a6c0001,
+0xc78,0x296d0001,
+0xc78,0x286e0001,
+0xc78,0x276f0001,
+0xc78,0x26700001,
+0xc78,0x25710001,
+0xc78,0x24720001,
+0xc78,0x23730001,
+0xc78,0x22740001,
+0xc78,0x09750001,
+0xc78,0x08760001,
+0xc78,0x07770001,
+0xc78,0x06780001,
+0xc78,0x05790001,
+0xc78,0x047a0001,
+0xc78,0x037b0001,
+0xc78,0x027c0001,
+0xc78,0x017d0001,
+0xc78,0x007e0001,
+0xc78,0x007f0001,
+0xc78,0x3000001e,
+0xc78,0x3001001e,
+0xc78,0x3002001e,
+0xc78,0x3003001e,
+0xc78,0x3004001e,
+0xc78,0x3405001e,
+0xc78,0x3806001e,
+0xc78,0x3e07001e,
+0xc78,0x3e08001e,
+0xc78,0x4409001e,
+0xc78,0x460a001e,
+0xc78,0x480b001e,
+0xc78,0x480c001e,
+0xc78,0x4e0d001e,
+0xc78,0x560e001e,
+0xc78,0x5a0f001e,
+0xc78,0x5e10001e,
+0xc78,0x6211001e,
+0xc78,0x6c12001e,
+0xc78,0x7213001e,
+0xc78,0x7214001e,
+0xc78,0x7215001e,
+0xc78,0x7216001e,
+0xc78,0x7217001e,
+0xc78,0x7218001e,
+0xc78,0x7219001e,
+0xc78,0x721a001e,
+0xc78,0x721b001e,
+0xc78,0x721c001e,
+0xc78,0x721d001e,
+0xc78,0x721e001e,
+0xc78,0x721f001e,
+};
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phyreg.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_phyreg.h
@@ -0,0 +1,954 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192SPHYREG_H
+#define __INC_HAL8192SPHYREG_H
+
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+
+
+#define		rPMAC_Reset					0x100
+#define		rPMAC_TxStart					0x104
+#define		rPMAC_TxLegacySIG				0x108
+#define		rPMAC_TxHTSIG1				0x10c
+#define		rPMAC_TxHTSIG2				0x110
+#define		rPMAC_PHYDebug				0x114
+#define		rPMAC_TxPacketNum				0x118
+#define		rPMAC_TxIdle					0x11c
+#define		rPMAC_TxMACHeader0			0x120
+#define		rPMAC_TxMACHeader1			0x124
+#define		rPMAC_TxMACHeader2			0x128
+#define		rPMAC_TxMACHeader3			0x12c
+#define		rPMAC_TxMACHeader4			0x130
+#define		rPMAC_TxMACHeader5			0x134
+#define		rPMAC_TxDataType				0x138
+#define		rPMAC_TxRandomSeed			0x13c
+#define		rPMAC_CCKPLCPPreamble			0x140
+#define		rPMAC_CCKPLCPHeader			0x144
+#define		rPMAC_CCKCRC16				0x148
+#define		rPMAC_OFDMRxCRC32OK			0x170
+#define		rPMAC_OFDMRxCRC32Er			0x174
+#define		rPMAC_OFDMRxParityEr			0x178
+#define		rPMAC_OFDMRxCRC8Er			0x17c
+#define		rPMAC_CCKCRxRC16Er			0x180
+#define		rPMAC_CCKCRxRC32Er			0x184
+#define		rPMAC_CCKCRxRC32OK			0x188
+#define		rPMAC_TxStatus					0x18c
+
+#define		RF_BB_CMD_ADDR				0x02c0	
+#define		RF_BB_CMD_DATA				0x02c4	
+
+#define		rFPGA0_RFMOD				0x800	
+
+#define		rFPGA0_TxInfo				0x804	
+#define		rFPGA0_PSDFunction			0x808
+
+#define		rFPGA0_TxGainStage			0x80c	
+
+#define		rFPGA0_RFTiming1			0x810	
+#define		rFPGA0_RFTiming2			0x814
+
+#define		rFPGA0_XA_HSSIParameter1		0x820	
+#define		rFPGA0_XA_HSSIParameter2		0x824
+#define		rFPGA0_XB_HSSIParameter1		0x828
+#define		rFPGA0_XB_HSSIParameter2		0x82c
+#define		rFPGA0_XC_HSSIParameter1		0x830
+#define		rFPGA0_XC_HSSIParameter2		0x834
+#define		rFPGA0_XD_HSSIParameter1		0x838
+#define		rFPGA0_XD_HSSIParameter2		0x83c
+#define		rFPGA0_XA_LSSIParameter		0x840
+#define		rFPGA0_XB_LSSIParameter		0x844
+#define		rFPGA0_XC_LSSIParameter		0x848
+#define		rFPGA0_XD_LSSIParameter		0x84c
+
+#define		rFPGA0_RFWakeUpParameter		0x850	
+#define		rFPGA0_RFSleepUpParameter		0x854
+
+#define		rFPGA0_XAB_SwitchControl		0x858	
+#define		rFPGA0_XCD_SwitchControl		0x85c
+
+#define		rFPGA0_XA_RFInterfaceOE		0x860	
+#define		rFPGA0_XB_RFInterfaceOE		0x864
+#define		rFPGA0_XC_RFInterfaceOE		0x868
+#define		rFPGA0_XD_RFInterfaceOE		0x86c
+
+#define		rFPGA0_XAB_RFInterfaceSW		0x870	
+#define		rFPGA0_XCD_RFInterfaceSW		0x874
+
+#define		rFPGA0_XAB_RFParameter		0x878	
+#define		rFPGA0_XCD_RFParameter		0x87c
+
+#define		rFPGA0_AnalogParameter1		0x880	
+#define		rFPGA0_AnalogParameter2		0x884
+#define		rFPGA0_AnalogParameter3		0x888	
+#define		rFPGA0_AnalogParameter4		0x88c
+
+#define		rFPGA0_XA_LSSIReadBack		0x8a0	
+#define		rFPGA0_XB_LSSIReadBack		0x8a4
+#define		rFPGA0_XC_LSSIReadBack		0x8a8
+#define		rFPGA0_XD_LSSIReadBack		0x8ac
+
+#define		rFPGA0_PSDReport				0x8b4	
+#define		TransceiverA_HSPI_Readback	0x8b8	
+#define		TransceiverB_HSPI_Readback	0x8bc	
+#define		rFPGA0_XAB_RFInterfaceRB		0x8e0	
+#define		rFPGA0_XCD_RFInterfaceRB		0x8e4	
+
+#define		rFPGA1_RFMOD				0x900	
+
+#define		rFPGA1_TxBlock				0x904	
+#define		rFPGA1_DebugSelect			0x908	
+#define		rFPGA1_TxInfo				0x90c	
+
+#define		rCCK0_System				0xa00
+
+#define		rCCK0_AFESetting			0xa04	
+#define		rCCK0_CCA					0xa08	
+
+#define		rCCK0_RxAGC1				0xa0c 	
+#define		rCCK0_RxAGC2				0xa10 	
+
+#define		rCCK0_RxHP					0xa14
+
+#define		rCCK0_DSPParameter1		0xa18	
+#define		rCCK0_DSPParameter2		0xa1c	
+
+#define		rCCK0_TxFilter1				0xa20
+#define		rCCK0_TxFilter2				0xa24
+#define		rCCK0_DebugPort			0xa28	
+#define		rCCK0_FalseAlarmReport		0xa2c	
+#define		rCCK0_TRSSIReport         		0xa50
+#define		rCCK0_RxReport            		0xa54  
+#define		rCCK0_FACounterLower      	0xa5c  
+#define		rCCK0_FACounterUpper      	0xa58  
+
+#define		rOFDM0_LSTF				0xc00
+
+#define		rOFDM0_TRxPathEnable		0xc04
+#define		rOFDM0_TRMuxPar			0xc08
+#define		rOFDM0_TRSWIsolation		0xc0c
+
+#define		rOFDM0_XARxAFE			0xc10  
+#define		rOFDM0_XARxIQImbalance    	0xc14  
+#define		rOFDM0_XBRxAFE            		0xc18
+#define		rOFDM0_XBRxIQImbalance    	0xc1c
+#define		rOFDM0_XCRxAFE            		0xc20
+#define		rOFDM0_XCRxIQImbalance    	0xc24
+#define		rOFDM0_XDRxAFE            		0xc28
+#define		rOFDM0_XDRxIQImbalance    	0xc2c
+
+#define		rOFDM0_RxDetector1			0xc30  
+#define		rOFDM0_RxDetector2			0xc34  
+#define		rOFDM0_RxDetector3			0xc38  
+#define		rOFDM0_RxDetector4			0xc3c  
+
+#define		rOFDM0_RxDSP				0xc40  
+#define		rOFDM0_CFOandDAGC		0xc44  
+#define		rOFDM0_CCADropThreshold	0xc48 
+#define		rOFDM0_ECCAThreshold		0xc4c 
+
+#define		rOFDM0_XAAGCCore1			0xc50	
+#define		rOFDM0_XAAGCCore2			0xc54
+#define		rOFDM0_XBAGCCore1			0xc58
+#define		rOFDM0_XBAGCCore2			0xc5c
+#define		rOFDM0_XCAGCCore1			0xc60
+#define		rOFDM0_XCAGCCore2			0xc64
+#define		rOFDM0_XDAGCCore1			0xc68
+#define		rOFDM0_XDAGCCore2			0xc6c
+
+#define		rOFDM0_AGCParameter1			0xc70
+#define		rOFDM0_AGCParameter2			0xc74
+#define		rOFDM0_AGCRSSITable			0xc78
+#define		rOFDM0_HTSTFAGC				0xc7c
+
+#define		rOFDM0_XATxIQImbalance		0xc80	
+#define		rOFDM0_XATxAFE				0xc84
+#define		rOFDM0_XBTxIQImbalance		0xc88
+#define		rOFDM0_XBTxAFE				0xc8c
+#define		rOFDM0_XCTxIQImbalance		0xc90
+#define		rOFDM0_XCTxAFE            			0xc94
+#define		rOFDM0_XDTxIQImbalance		0xc98
+#define		rOFDM0_XDTxAFE				0xc9c
+
+#define		rOFDM0_RxHPParameter			0xce0
+#define		rOFDM0_TxPseudoNoiseWgt		0xce4
+#define		rOFDM0_FrameSync				0xcf0
+#define		rOFDM0_DFSReport				0xcf4
+#define		rOFDM0_TxCoeff1				0xca4
+#define		rOFDM0_TxCoeff2				0xca8
+#define		rOFDM0_TxCoeff3				0xcac
+#define		rOFDM0_TxCoeff4				0xcb0
+#define		rOFDM0_TxCoeff5				0xcb4
+#define		rOFDM0_TxCoeff6				0xcb8
+
+
+#define		rOFDM1_LSTF					0xd00
+#define		rOFDM1_TRxPathEnable			0xd04
+
+#define		rOFDM1_CFO						0xd08	
+#define		rOFDM1_CSI1					0xd10
+#define		rOFDM1_SBD						0xd14
+#define		rOFDM1_CSI2					0xd18
+#define		rOFDM1_CFOTracking			0xd2c
+#define		rOFDM1_TRxMesaure1			0xd34
+#define		rOFDM1_IntfDet					0xd3c
+#define		rOFDM1_PseudoNoiseStateAB		0xd50
+#define		rOFDM1_PseudoNoiseStateCD		0xd54
+#define		rOFDM1_RxPseudoNoiseWgt		0xd58
+
+#define		rOFDM_PHYCounter1				0xda0  
+#define		rOFDM_PHYCounter2				0xda4  
+#define		rOFDM_PHYCounter3				0xda8  
+
+#define		rOFDM_ShortCFOAB				0xdac	
+#define		rOFDM_ShortCFOCD				0xdb0
+#define		rOFDM_LongCFOAB				0xdb4
+#define		rOFDM_LongCFOCD				0xdb8
+#define		rOFDM_TailCFOAB				0xdbc
+#define		rOFDM_TailCFOCD				0xdc0
+#define		rOFDM_PWMeasure1          		0xdc4
+#define		rOFDM_PWMeasure2          		0xdc8
+#define		rOFDM_BWReport				0xdcc
+#define		rOFDM_AGCReport				0xdd0
+#define		rOFDM_RxSNR					0xdd4
+#define		rOFDM_RxEVMCSI				0xdd8
+#define		rOFDM_SIGReport				0xddc
+
+
+#define		rTxAGC_Rate18_06				0xe00
+#define		rTxAGC_Rate54_24				0xe04
+#define		rTxAGC_CCK_Mcs32				0xe08
+#define		rTxAGC_Mcs03_Mcs00			0xe10
+#define		rTxAGC_Mcs07_Mcs04			0xe14
+#define		rTxAGC_Mcs11_Mcs08			0xe18
+#define		rTxAGC_Mcs15_Mcs12			0xe1c
+
+#define		rZebra1_HSSIEnable				0x0	
+#define		rZebra1_TRxEnable1				0x1
+#define		rZebra1_TRxEnable2				0x2
+#define		rZebra1_AGC					0x4
+#define		rZebra1_ChargePump			0x5
+#define		rZebra1_Channel				0x7	
+
+#define		rZebra1_TxGain					0x8	
+#define		rZebra1_TxLPF					0x9
+#define		rZebra1_RxLPF					0xb
+#define		rZebra1_RxHPFCorner			0xc
+
+#define		rGlobalCtrl						0	
+#define		rRTL8256_TxLPF					19
+#define		rRTL8256_RxLPF					11
+
+#define		rRTL8258_TxLPF					0x11	
+#define		rRTL8258_RxLPF					0x13
+#define		rRTL8258_RSSILPF				0xa
+
+#define		RF_AC						0x00	
+
+#define		RF_IQADJ_G1				0x01	
+#define		RF_IQADJ_G2				0x02	
+#define		RF_POW_TRSW				0x05	
+
+#define		RF_GAIN_RX					0x06	
+#define		RF_GAIN_TX					0x07	
+
+#define		RF_TXM_IDAC				0x08	
+#define		RF_BS_IQGEN				0x0F	
+
+#define		RF_MODE1					0x10	
+#define		RF_MODE2					0x11	
+
+#define		RF_RX_AGC_HP				0x12	
+#define		RF_TX_AGC					0x13	
+#define		RF_BIAS						0x14	
+#define		RF_IPA						0x15	
+#define		RF_POW_ABILITY			0x17	
+#define		RF_MODE_AG				0x18	
+#define		rRfChannel					0x18	
+#define		RF_CHNLBW					0x18	
+#define		RF_TOP						0x19	
+
+#define		RF_RX_G1					0x1A	
+#define		RF_RX_G2					0x1B	
+
+#define		RF_RX_BB2					0x1C	
+#define		RF_RX_BB1					0x1D	
+
+#define		RF_RCK1					0x1E	
+#define		RF_RCK2					0x1F	
+
+#define		RF_TX_G1					0x20	
+#define		RF_TX_G2					0x21	
+#define		RF_TX_G3					0x22	
+
+#define		RF_TX_BB1					0x23	
+
+#define		RF_T_METER					0x24	
+
+#define		RF_SYN_G1					0x25	
+#define		RF_SYN_G2					0x26	
+#define		RF_SYN_G3					0x27	
+#define		RF_SYN_G4					0x28	
+#define		RF_SYN_G5					0x29	
+#define		RF_SYN_G6					0x2A	
+#define		RF_SYN_G7					0x2B	
+#define		RF_SYN_G8					0x2C	
+
+#define		RF_RCK_OS					0x30	
+
+#define		RF_TXPA_G1					0x31	
+#define		RF_TXPA_G2					0x32	
+#define		RF_TXPA_G3					0x33	
+
+#define		bBBResetB						0x100	
+#define		bGlobalResetB					0x200
+#define		bOFDMTxStart					0x4
+#define		bCCKTxStart						0x8
+#define		bCRC32Debug					0x100
+#define		bPMACLoopback					0x10
+#define		bTxLSIG							0xffffff
+#define		bOFDMTxRate					0xf
+#define		bOFDMTxReserved				0x10
+#define		bOFDMTxLength					0x1ffe0
+#define		bOFDMTxParity					0x20000
+#define		bTxHTSIG1						0xffffff
+#define		bTxHTMCSRate					0x7f
+#define		bTxHTBW						0x80
+#define		bTxHTLength					0xffff00
+#define		bTxHTSIG2						0xffffff
+#define		bTxHTSmoothing					0x1
+#define		bTxHTSounding					0x2
+#define		bTxHTReserved					0x4
+#define		bTxHTAggreation				0x8
+#define		bTxHTSTBC						0x30
+#define		bTxHTAdvanceCoding			0x40
+#define		bTxHTShortGI					0x80
+#define		bTxHTNumberHT_LTF			0x300
+#define		bTxHTCRC8						0x3fc00
+#define		bCounterReset					0x10000
+#define		bNumOfOFDMTx					0xffff
+#define		bNumOfCCKTx					0xffff0000
+#define		bTxIdleInterval					0xffff
+#define		bOFDMService					0xffff0000
+#define		bTxMACHeader					0xffffffff
+#define		bTxDataInit						0xff
+#define		bTxHTMode						0x100
+#define		bTxDataType					0x30000
+#define		bTxRandomSeed					0xffffffff
+#define		bCCKTxPreamble					0x1
+#define		bCCKTxSFD						0xffff0000
+#define		bCCKTxSIG						0xff
+#define		bCCKTxService					0xff00
+#define		bCCKLengthExt					0x8000
+#define		bCCKTxLength					0xffff0000
+#define		bCCKTxCRC16					0xffff
+#define		bCCKTxStatus					0x1
+#define		bOFDMTxStatus					0x2
+
+#define 	IS_BB_REG_OFFSET_92S(_Offset)		((_Offset >= 0x800) && (_Offset <= 0xfff))
+
+#define		bRFMOD							0x1	
+#define		bJapanMode						0x2
+#define		bCCKTxSC						0x30
+#define		bCCKEn							0x1000000
+#define		bOFDMEn						0x2000000
+
+#define		bOFDMRxADCPhase           		0x10000	
+#define		bOFDMTxDACPhase           		0x40000
+#define		bXATxAGC                  			0x3f
+
+#define		bXBTxAGC                  			0xf00	
+#define		bXCTxAGC                  			0xf000
+#define		bXDTxAGC                  			0xf0000
+       		
+#define		bPAStart                  			0xf0000000	
+#define		bTRStart                  			0x00f00000
+#define		bRFStart                  			0x0000f000
+#define		bBBStart                  			0x000000f0
+#define		bBBCCKStart               		0x0000000f
+#define		bPAEnd                    			0xf          
+#define		bTREnd                    			0x0f000000
+#define		bRFEnd                    			0x000f0000
+#define		bCCAMask                  			0x000000f0   
+#define		bR2RCCAMask               		0x00000f00
+#define		bHSSI_R2TDelay            		0xf8000000
+#define		bHSSI_T2RDelay            		0xf80000
+#define		bContTxHSSI               		0x400     
+#define		bIGFromCCK                		0x200
+#define		bAGCAddress               		0x3f
+#define		bRxHPTx                   			0x7000
+#define		bRxHPT2R                  			0x38000
+#define		bRxHPCCKIni               		0xc0000
+#define		bAGCTxCode                		0xc00000
+#define		bAGCRxCode                		0x300000
+
+#define		b3WireDataLength          		0x800	
+#define		b3WireAddressLength       		0x400
+
+#define		b3WireRFPowerDown         		0x1	
+#define		b5GPAPEPolarity           		0x40000000
+#define		b2GPAPEPolarity           		0x80000000
+#define		bRFSW_TxDefaultAnt        		0x3
+#define		bRFSW_TxOptionAnt         		0x30
+#define		bRFSW_RxDefaultAnt        		0x300
+#define		bRFSW_RxOptionAnt         		0x3000
+#define		bRFSI_3WireData           		0x1
+#define		bRFSI_3WireClock          		0x2
+#define		bRFSI_3WireLoad           		0x4
+#define		bRFSI_3WireRW             		0x8
+#define		bRFSI_3Wire               			0xf
+
+#define		bRFSI_RFENV               		0x10	
+
+#define		bRFSI_TRSW                		0x20	
+#define		bRFSI_TRSWB               		0x40
+#define		bRFSI_ANTSW               		0x100
+#define		bRFSI_ANTSWB              		0x200
+#define		bRFSI_PAPE                			0x400
+#define		bRFSI_PAPE5G              		0x800 
+#define		bBandSelect               			0x1
+#define		bHTSIG2_GI                			0x80
+#define		bHTSIG2_Smoothing         		0x01
+#define		bHTSIG2_Sounding          		0x02
+#define		bHTSIG2_Aggreaton         		0x08
+#define		bHTSIG2_STBC              		0x30
+#define		bHTSIG2_AdvCoding         		0x40
+#define		bHTSIG2_NumOfHTLTF        	0x300
+#define		bHTSIG2_CRC8              		0x3fc
+#define		bHTSIG1_MCS               		0x7f
+#define		bHTSIG1_BandWidth         		0x80
+#define		bHTSIG1_HTLength          		0xffff
+#define		bLSIG_Rate                			0xf
+#define		bLSIG_Reserved            		0x10
+#define		bLSIG_Length              		0x1fffe
+#define		bLSIG_Parity              			0x20
+#define		bCCKRxPhase               		0x4
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define		bLSSIReadAddress          		0x3f000000   
+#else
+#define		bLSSIReadAddress          		0x7f800000   
+#endif
+#define		bLSSIReadEdge             		0x80000000   
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define		bLSSIReadBackData         		0xfff		
+#else
+#define		bLSSIReadBackData         		0xfffff		
+#endif
+#define		bLSSIReadOKFlag           		0x1000	
+#define		bCCKSampleRate            		0x8       
+#define		bRegulator0Standby        		0x1
+#define		bRegulatorPLLStandby      		0x2
+#define		bRegulator1Standby        		0x4
+#define		bPLLPowerUp               		0x8
+#define		bDPLLPowerUp              		0x10
+#define		bDA10PowerUp              		0x20
+#define		bAD7PowerUp               		0x200
+#define		bDA6PowerUp               		0x2000
+#define		bXtalPowerUp              		0x4000
+#define		b40MDClkPowerUP           		0x8000
+#define		bDA6DebugMode             		0x20000
+#define		bDA6Swing                 			0x380000
+
+#define		bADClkPhase               		0x4000000	
+
+#define		b80MClkDelay              		0x18000000	
+#define		bAFEWatchDogEnable        		0x20000000
+
+#define		bXtalCap01                			0xc0000000	
+#define		bXtalCap23                			0x3
+#define		bXtalCap92x					0x0f000000
+#define 		bXtalCap                			0x0f000000
+
+#define		bIntDifClkEnable          		0x400	
+#define		bExtSigClkEnable         	 	0x800
+#define		bBandgapMbiasPowerUp      	0x10000
+#define		bAD11SHGain               		0xc0000
+#define		bAD11InputRange           		0x700000
+#define		bAD11OPCurrent            		0x3800000
+#define		bIPathLoopback            		0x4000000
+#define		bQPathLoopback            		0x8000000
+#define		bAFELoopback              		0x10000000
+#define		bDA10Swing                		0x7e0
+#define		bDA10Reverse              		0x800
+#define		bDAClkSource              		0x1000
+#define		bAD7InputRange            		0x6000
+#define		bAD7Gain                  			0x38000
+#define		bAD7OutputCMMode          		0x40000
+#define		bAD7InputCMMode           		0x380000
+#define		bAD7Current               			0xc00000
+#define		bRegulatorAdjust          		0x7000000
+#define		bAD11PowerUpAtTx          		0x1
+#define		bDA10PSAtTx               		0x10
+#define		bAD11PowerUpAtRx          		0x100
+#define		bDA10PSAtRx               		0x1000       		
+#define		bCCKRxAGCFormat           		0x200       		
+#define		bPSDFFTSamplepPoint       		0xc000
+#define		bPSDAverageNum            		0x3000
+#define		bIQPathControl            		0xc00
+#define		bPSDFreq                  			0x3ff
+#define		bPSDAntennaPath           		0x30
+#define		bPSDIQSwitch              		0x40
+#define		bPSDRxTrigger             		0x400000
+#define		bPSDTxTrigger             		0x80000000
+#define		bPSDSineToneScale        		0x7f000000
+#define		bPSDReport                			0xffff
+
+#define		bOFDMTxSC                 		0x30000000	
+#define		bCCKTxOn                  			0x1
+#define		bOFDMTxOn                 		0x2
+#define		bDebugPage                		0xfff  
+#define		bDebugItem                		0xff   
+#define		bAntL              	       		0x10
+#define		bAntNonHT           	      			0x100
+#define		bAntHT1               			0x1000
+#define		bAntHT2                   			0x10000
+#define		bAntHT1S1                 			0x100000
+#define		bAntNonHTS1               		0x1000000
+
+#define		bCCKBBMode                		0x3	
+#define		bCCKTxPowerSaving         		0x80
+#define		bCCKRxPowerSaving         		0x40
+
+#define		bCCKSideBand              		0x10	
+
+#define		bCCKScramble              		0x8	
+#define		bCCKAntDiversity    		      	0x8000
+#define		bCCKCarrierRecovery   	    	0x4000
+#define		bCCKTxRate           		     	0x3000
+#define		bCCKDCCancel             	 	0x0800
+#define		bCCKISICancel             		0x0400
+#define		bCCKMatchFilter           		0x0200
+#define		bCCKEqualizer             		0x0100
+#define		bCCKPreambleDetect       	 	0x800000
+#define		bCCKFastFalseCCA          		0x400000
+#define		bCCKChEstStart            		0x300000
+#define		bCCKCCACount              		0x080000
+#define		bCCKcs_lim                			0x070000
+#define		bCCKBistMode              		0x80000000
+#define		bCCKCCAMask             	  	0x40000000
+#define		bCCKTxDACPhase         	   	0x4
+#define		bCCKRxADCPhase         	   	0x20000000   
+#define		bCCKr_cp_mode0         	   	0x0100
+#define		bCCKTxDCOffset           	 	0xf0
+#define		bCCKRxDCOffset           	 	0xf
+#define		bCCKCCAMode              	 	0xc000
+#define		bCCKFalseCS_lim           		0x3f00
+#define		bCCKCS_ratio              		0xc00000
+#define		bCCKCorgBit_sel           		0x300000
+#define		bCCKPD_lim                			0x0f0000
+#define		bCCKNewCCA                		0x80000000
+#define		bCCKRxHPofIG              		0x8000
+#define		bCCKRxIG                  			0x7f00
+#define		bCCKLNAPolarity           		0x800000
+#define		bCCKRx1stGain             		0x7f0000
+#define		bCCKRFExtend              		0x20000000 
+#define		bCCKRxAGCSatLevel        	 	0x1f000000
+#define		bCCKRxAGCSatCount       	  	0xe0
+#define		bCCKRxRFSettle            		0x1f       
+#define		bCCKFixedRxAGC           	 	0x8000
+#define		bCCKAntennaPolarity      	 	0x2000
+#define		bCCKTxFilterType          		0x0c00
+#define		bCCKRxAGCReportType   	   	0x0300
+#define		bCCKRxDAGCEn              		0x80000000
+#define		bCCKRxDAGCPeriod        	  	0x20000000
+#define		bCCKRxDAGCSatLevel     	   	0x1f000000
+#define		bCCKTimingRecovery       	 	0x800000
+#define		bCCKTxC0                  			0x3f0000
+#define		bCCKTxC1                  			0x3f000000
+#define		bCCKTxC2                  			0x3f
+#define		bCCKTxC3                  			0x3f00
+#define		bCCKTxC4                  			0x3f0000
+#define		bCCKTxC5                  			0x3f000000
+#define		bCCKTxC6                  			0x3f
+#define		bCCKTxC7                  			0x3f00
+#define		bCCKDebugPort             		0xff0000
+#define		bCCKDACDebug              		0x0f000000
+#define		bCCKFalseAlarmEnable      		0x8000
+#define		bCCKFalseAlarmRead        		0x4000
+#define		bCCKTRSSI                 			0x7f
+#define		bCCKRxAGCReport           		0xfe
+#define		bCCKRxReport_AntSel       		0x80000000
+#define		bCCKRxReport_MFOff        		0x40000000
+#define		bCCKRxRxReport_SQLoss     	0x20000000
+#define		bCCKRxReport_Pktloss      		0x10000000
+#define		bCCKRxReport_Lockedbit    	0x08000000
+#define		bCCKRxReport_RateError    	0x04000000
+#define		bCCKRxReport_RxRate       		0x03000000
+#define		bCCKRxFACounterLower      	0xff
+#define		bCCKRxFACounterUpper      	0xff000000
+#define		bCCKRxHPAGCStart          		0xe000
+#define		bCCKRxHPAGCFinal          		0x1c00       		
+#define		bCCKRxFalseAlarmEnable    	0x8000
+#define		bCCKFACounterFreeze       		0x4000       		
+#define		bCCKTxPathSel             		0x10000000
+#define		bCCKDefaultRxPath         		0xc000000
+#define		bCCKOptionRxPath          		0x3000000
+
+#define		bNumOfSTF                			0x3	
+#define		bShift_L                 			0xc0
+#define		bGI_TH                   			0xc
+#define		bRxPathA                 			0x1
+#define		bRxPathB                 			0x2
+#define		bRxPathC                 			0x4
+#define		bRxPathD                 			0x8
+#define		bTxPathA                 			0x1
+#define		bTxPathB                 			0x2
+#define		bTxPathC                 			0x4
+#define		bTxPathD                 			0x8
+#define		bTRSSIFreq               			0x200
+#define		bADCBackoff              			0x3000
+#define		bDFIRBackoff             			0xc000
+#define		bTRSSILatchPhase         		0x10000
+#define		bRxIDCOffset             			0xff
+#define		bRxQDCOffset             			0xff00
+#define		bRxDFIRMode              		0x1800000
+#define		bRxDCNFType              		0xe000000
+#define		bRXIQImb_A               			0x3ff
+#define		bRXIQImb_B               			0xfc00
+#define		bRXIQImb_C               			0x3f0000
+#define		bRXIQImb_D               			0xffc00000
+#define		bDC_dc_Notch             		0x60000
+#define		bRxNBINotch              			0x1f000000
+#define		bPD_TH                   			0xf
+#define		bPD_TH_Opt2              		0xc000
+#define		bPWED_TH                 			0x700
+#define		bIfMF_Win_L              			0x800
+#define		bPD_Option               			0x1000
+#define		bMF_Win_L                			0xe000
+#define		bBW_Search_L             		0x30000
+#define		bwin_enh_L               			0xc0000
+#define		bBW_TH                   			0x700000
+#define		bED_TH2                  			0x3800000
+#define		bBW_option               			0x4000000
+#define		bRatio_TH                			0x18000000
+#define		bWindow_L                			0xe0000000
+#define		bSBD_Option              			0x1
+#define		bFrame_TH                			0x1c
+#define		bFS_Option               			0x60
+#define		bDC_Slope_check          		0x80
+#define		bFGuard_Counter_DC_L     		0xe00
+#define		bFrame_Weight_Short      		0x7000
+#define		bSub_Tune                			0xe00000
+#define		bFrame_DC_Length         		0xe000000
+#define		bSBD_start_offset        		0x30000000
+#define		bFrame_TH_2              		0x7
+#define		bFrame_GI2_TH            		0x38
+#define		bGI2_Sync_en             		0x40
+#define		bSarch_Short_Early       		0x300
+#define		bSarch_Short_Late        		0xc00
+#define		bSarch_GI2_Late          		0x70000
+#define		bCFOAntSum               		0x1
+#define		bCFOAcc                  			0x2
+#define		bCFOStartOffset          		0xc
+#define		bCFOLookBack             		0x70
+#define		bCFOSumWeight            		0x80
+#define		bDAGCEnable              			0x10000
+#define		bTXIQImb_A               			0x3ff
+#define		bTXIQImb_B               			0xfc00
+#define		bTXIQImb_C               			0x3f0000
+#define		bTXIQImb_D               			0xffc00000
+#define		bTxIDCOffset             			0xff
+#define		bTxQDCOffset             			0xff00
+#define		bTxDFIRMode              		0x10000
+#define		bTxPesudoNoiseOn         		0x4000000
+#define		bTxPesudoNoise_A         		0xff
+#define		bTxPesudoNoise_B         		0xff00
+#define		bTxPesudoNoise_C         		0xff0000
+#define		bTxPesudoNoise_D         		0xff000000
+#define		bCCADropOption           		0x20000
+#define		bCCADropThres            		0xfff00000
+#define		bEDCCA_H                 			0xf
+#define		bEDCCA_L                 			0xf0
+#define		bLambda_ED               0x300
+#define		bRxInitialGain           0x7f
+#define		bRxAntDivEn              0x80
+#define		bRxAGCAddressForLNA      0x7f00
+#define		bRxHighPowerFlow         0x8000
+#define		bRxAGCFreezeThres        0xc0000
+#define		bRxFreezeStep_AGC1       0x300000
+#define		bRxFreezeStep_AGC2       0xc00000
+#define		bRxFreezeStep_AGC3       0x3000000
+#define		bRxFreezeStep_AGC0       0xc000000
+#define		bRxRssi_Cmp_En           0x10000000
+#define		bRxQuickAGCEn            0x20000000
+#define		bRxAGCFreezeThresMode    0x40000000
+#define		bRxOverFlowCheckType     0x80000000
+#define		bRxAGCShift              0x7f
+#define		bTRSW_Tri_Only           0x80
+#define		bPowerThres              0x300
+#define		bRxAGCEn                 0x1
+#define		bRxAGCTogetherEn         0x2
+#define		bRxAGCMin                0x4
+#define		bRxHP_Ini                0x7
+#define		bRxHP_TRLNA              0x70
+#define		bRxHP_RSSI               0x700
+#define		bRxHP_BBP1               0x7000
+#define		bRxHP_BBP2               0x70000
+#define		bRxHP_BBP3               0x700000
+#define		bRSSI_H                  0x7f0000     
+#define		bRSSI_Gen                0x7f000000   
+#define		bRxSettle_TRSW           0x7
+#define		bRxSettle_LNA            0x38
+#define		bRxSettle_RSSI           0x1c0
+#define		bRxSettle_BBP            0xe00
+#define		bRxSettle_RxHP           0x7000
+#define		bRxSettle_AntSW_RSSI     0x38000
+#define		bRxSettle_AntSW          0xc0000
+#define		bRxProcessTime_DAGC      0x300000
+#define		bRxSettle_HSSI           0x400000
+#define		bRxProcessTime_BBPPW     0x800000
+#define		bRxAntennaPowerShift     0x3000000
+#define		bRSSITableSelect         0xc000000
+#define		bRxHP_Final              0x7000000
+#define		bRxHTSettle_BBP          0x7
+#define		bRxHTSettle_HSSI         0x8
+#define		bRxHTSettle_RxHP         0x70
+#define		bRxHTSettle_BBPPW        0x80
+#define		bRxHTSettle_Idle         0x300
+#define		bRxHTSettle_Reserved     0x1c00
+#define		bRxHTRxHPEn              0x8000
+#define		bRxHTAGCFreezeThres      0x30000
+#define		bRxHTAGCTogetherEn       0x40000
+#define		bRxHTAGCMin              0x80000
+#define		bRxHTAGCEn               0x100000
+#define		bRxHTDAGCEn              0x200000
+#define		bRxHTRxHP_BBP            0x1c00000
+#define		bRxHTRxHP_Final          0xe0000000
+#define		bRxPWRatioTH             0x3
+#define		bRxPWRatioEn             0x4
+#define		bRxMFHold                0x3800
+#define		bRxPD_Delay_TH1          0x38
+#define		bRxPD_Delay_TH2          0x1c0
+#define		bRxPD_DC_COUNT_MAX       0x600
+#define		bRxPD_Delay_TH           0x8000
+#define		bRxProcess_Delay         0xf0000
+#define		bRxSearchrange_GI2_Early 0x700000
+#define		bRxFrame_Guard_Counter_L 0x3800000
+#define		bRxSGI_Guard_L           0xc000000
+#define		bRxSGI_Search_L          0x30000000
+#define		bRxSGI_TH                0xc0000000
+#define		bDFSCnt0                 0xff
+#define		bDFSCnt1                 0xff00
+#define		bDFSFlag                 0xf0000       		
+#define		bMFWeightSum             0x300000
+#define		bMinIdxTH                0x7f000000       		
+#define		bDAFormat                0x40000       		
+#define		bTxChEmuEnable           0x01000000       		
+#define		bTRSWIsolation_A         0x7f
+#define		bTRSWIsolation_B         0x7f00
+#define		bTRSWIsolation_C         0x7f0000
+#define		bTRSWIsolation_D         0x7f000000       		
+#define		bExtLNAGain              0x7c00          
+
+#define		bSTBCEn                  0x4	
+#define		bAntennaMapping          0x10
+#define		bNss                     0x20
+#define		bCFOAntSumD              0x200
+#define		bPHYCounterReset         0x8000000
+#define		bCFOReportGet            0x4000000
+#define		bOFDMContinueTx          0x10000000
+#define		bOFDMSingleCarrier       0x20000000
+#define		bOFDMSingleTone          0x40000000
+#define		bHTDetect                0x100
+#define		bCFOEn                   0x10000
+#define		bCFOValue                0xfff00000
+#define		bSigTone_Re              0x3f
+#define		bSigTone_Im              0x7f00
+#define		bCounter_CCA             0xffff
+#define		bCounter_ParityFail      0xffff0000
+#define		bCounter_RateIllegal     0xffff
+#define		bCounter_CRC8Fail        0xffff0000
+#define		bCounter_MCSNoSupport    0xffff
+#define		bCounter_FastSync        0xffff
+#define		bShortCFO                0xfff
+#define		bShortCFOTLength         12   
+#define		bShortCFOFLength         11   
+#define		bLongCFO                 0x7ff
+#define		bLongCFOTLength          11
+#define		bLongCFOFLength          11
+#define		bTailCFO                 0x1fff
+#define		bTailCFOTLength          13
+#define		bTailCFOFLength          12       		
+#define		bmax_en_pwdB             0xffff
+#define		bCC_power_dB             0xffff0000
+#define		bnoise_pwdB              0xffff
+#define		bPowerMeasTLength        10
+#define		bPowerMeasFLength        3
+#define		bRx_HT_BW                0x1
+#define		bRxSC                    0x6
+#define		bRx_HT                   0x8       		
+#define		bNB_intf_det_on          0x1
+#define		bIntf_win_len_cfg        0x30
+#define		bNB_Intf_TH_cfg          0x1c0       		
+#define		bRFGain                  0x3f
+#define		bTableSel                0x40
+#define		bTRSW                    0x80       		
+#define		bRxSNR_A                 0xff
+#define		bRxSNR_B                 0xff00
+#define		bRxSNR_C                 0xff0000
+#define		bRxSNR_D                 0xff000000
+#define		bSNREVMTLength           8
+#define		bSNREVMFLength           1       		
+#define		bCSI1st                  0xff
+#define		bCSI2nd                  0xff00
+#define		bRxEVM1st                0xff0000
+#define		bRxEVM2nd                0xff000000       		
+#define		bSIGEVM                  0xff
+#define		bPWDB                    0xff00
+#define		bSGIEN                   0x10000
+       		
+#define		bSFactorQAM1             0xf	
+#define		bSFactorQAM2             0xf0
+#define		bSFactorQAM3             0xf00
+#define		bSFactorQAM4             0xf000
+#define		bSFactorQAM5             0xf0000
+#define		bSFactorQAM6             0xf0000
+#define		bSFactorQAM7             0xf00000
+#define		bSFactorQAM8             0xf000000
+#define		bSFactorQAM9             0xf0000000
+#define		bCSIScheme               0x100000
+       		
+#define		bNoiseLvlTopSet          0x3	
+#define		bChSmooth                0x4
+#define		bChSmoothCfg1            0x38
+#define		bChSmoothCfg2            0x1c0
+#define		bChSmoothCfg3            0xe00
+#define		bChSmoothCfg4            0x7000
+#define		bMRCMode                 0x800000
+#define		bTHEVMCfg                0x7000000
+       		
+#define		bLoopFitType             0x1	
+#define		bUpdCFO                  0x40
+#define		bUpdCFOOffData           0x80
+#define		bAdvUpdCFO               0x100
+#define		bAdvTimeCtrl             0x800
+#define		bUpdClko                 0x1000
+#define		bFC                      0x6000
+#define		bTrackingMode            0x8000
+#define		bPhCmpEnable             0x10000
+#define		bUpdClkoLTF              0x20000
+#define		bComChCFO                0x40000
+#define		bCSIEstiMode             0x80000
+#define		bAdvUpdEqz               0x100000
+#define		bUChCfg                  0x7000000
+#define		bUpdEqz                  0x8000000
+
+#define		bTxAGCRate18_06			0x7f7f7f7f	
+#define		bTxAGCRate54_24			0x7f7f7f7f
+#define		bTxAGCRateMCS32			0x7f
+#define		bTxAGCRateCCK			0x7f00
+#define		bTxAGCRateMCS3_MCS0		0x7f7f7f7f
+#define		bTxAGCRateMCS7_MCS4		0x7f7f7f7f
+#define		bTxAGCRateMCS11_MCS8	0x7f7f7f7f
+#define		bTxAGCRateMCS15_MCS12	0x7f7f7f7f
+
+#define		bRxPesudoNoiseOn         0x20000000	
+#define		bRxPesudoNoise_A         0xff
+#define		bRxPesudoNoise_B         0xff00
+#define		bRxPesudoNoise_C         0xff0000
+#define		bRxPesudoNoise_D         0xff000000
+#define		bPesudoNoiseState_A      0xffff
+#define		bPesudoNoiseState_B      0xffff0000
+#define		bPesudoNoiseState_C      0xffff
+#define		bPesudoNoiseState_D      0xffff0000
+
+#define		bZebra1_HSSIEnable        0x8		
+#define		bZebra1_TRxControl        0xc00
+#define		bZebra1_TRxGainSetting    0x07f
+#define		bZebra1_RxCorner          0xc00
+#define		bZebra1_TxChargePump      0x38
+#define		bZebra1_RxChargePump      0x7
+#define		bZebra1_ChannelNum        0xf80
+#define		bZebra1_TxLPFBW           0x400
+#define		bZebra1_RxLPFBW           0x600
+
+#define		bRTL8256RegModeCtrl1      0x100	
+#define		bRTL8256RegModeCtrl0      0x40
+#define		bRTL8256_TxLPFBW          0x18
+#define		bRTL8256_RxLPFBW          0x600
+
+#define		bRTL8258_TxLPFBW          0xc	
+#define		bRTL8258_RxLPFBW          0xc00
+#define		bRTL8258_RSSILPFBW        0xc0
+
+
+
+#define		bByte0                    0x1	
+#define		bByte1                    0x2
+#define		bByte2                    0x4
+#define		bByte3                    0x8
+#define		bWord0                    0x3
+#define		bWord1                    0xc
+#define		bDWord                    0xf
+
+#define		bMaskByte0                0xff	
+#define		bMaskByte1                0xff00
+#define		bMaskByte2                0xff0000
+#define		bMaskByte3                0xff000000
+#define		bMaskHWord                0xffff0000
+#define		bMaskLWord                0x0000ffff
+#define		bMaskDWord                0xffffffff
+
+#if (RTL92SE_FPGA_VERIFY == 1)
+#define		bMask12Bits               0xfff	
+#define		bMask20Bits               0xfff	
+#define 		bRFRegOffsetMask	0xfff		
+#else
+#define		bMask12Bits               0xfffff	
+#define		bMask20Bits               0xfffff	
+#define 		bRFRegOffsetMask	0xfffff		
+#endif       		
+#define		bEnable                   0x1	
+#define		bDisable                  0x0
+       		
+#define		LeftAntenna               0x0	
+#define		RightAntenna              0x1
+       		
+#define		tCheckTxStatus            500   
+#define		tUpdateRxCounter          100   
+       		
+#define		rateCCK     0	
+#define		rateOFDM    1
+#define		rateHT      2
+
+#define		bPMAC_End                 0x1ff	
+#define		bFPGAPHY0_End             0x8ff
+#define		bFPGAPHY1_End             0x9ff
+#define		bCCKPHY0_End              0xaff
+#define		bOFDMPHY0_End             0xcff
+#define		bOFDMPHY1_End             0xdff
+
+
+#define		bPMACControl              0x0		
+#define		bWMACControl              0x1
+#define		bWNICControl              0x2
+       		
+#define		PathA                     0x0	
+#define		PathB                     0x1
+#define		PathC                     0x2
+#define		PathD                     0x3
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+#endif	
+
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_led.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_led.c
@@ -0,0 +1,1356 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "../rtl_core.h"
+#ifdef RTL8192SE
+#define LED_BLINK_NORMAL_INTERVAL	100
+#define LED_BLINK_SLOWLY_INTERVAL		200
+
+#define LED_BLINK_NORMAL_INTERVAL_NETTRONIX  100
+#define LED_BLINK_SLOWLY_INTERVAL_NETTRONIX  2000
+
+#define LED_BLINK_SLOWLY_INTERVAL_PORNET 1000
+#define LED_BLINK_NORMAL_INTERVAL_PORNET 100
+
+
+#define LED_CM2_BLINK_ON_INTERVAL			250
+#define LED_CM2_BLINK_OFF_INTERVAL		4750
+
+#define LED_CM8_BLINK_OFF_INTERVAL		3750	
+
+#define LED_RunTop_BLINK_INTERVAL 			300
+
+#define LED_CM3_BLINK_INTERVAL			1500
+
+
+
+static void BlinkTimerCallback(unsigned long data);
+
+
+void InitLed8190Pci(struct net_device *dev, PLED_8190 	pLed,LED_PIN_8190 LedPin)
+{
+	pLed->dev = dev;
+	pLed->LedPin = LedPin;
+
+	pLed->CurrLedState = LED_OFF;
+	pLed->bLedOn = false;
+	pLed->bLedBlinkInProgress = false;
+	pLed->BlinkTimes = 0;
+	pLed->BlinkingLedState = LED_OFF;
+
+	setup_timer(&pLed->BlinkTimer,
+		    BlinkTimerCallback,
+		    (unsigned long) pLed);
+}
+
+void DeInitLed8190Pci(PLED_8190 pLed)
+{
+	del_timer_sync(&(pLed->BlinkTimer));
+	pLed->bLedBlinkInProgress = false;
+}
+
+void SwLedOn(	struct net_device *dev , PLED_8190 pLed)
+{
+	u8	LedCfg;
+
+	LedCfg = read_nic_byte(dev, LEDCFG);
+	
+	switch(pLed->LedPin)
+	{
+	case LED_PIN_GPIO0:
+		break;
+
+	case LED_PIN_LED0:
+		write_nic_byte(dev, LEDCFG, LedCfg&0xf0); 
+		break;
+
+	case LED_PIN_LED1:
+		write_nic_byte(dev, LEDCFG, LedCfg&0x0f); 
+		break;
+
+	default:
+		break;
+	}
+
+	pLed->bLedOn = true;
+}
+
+void SwLedOff(struct net_device *dev, PLED_8190 pLed)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	u8	LedCfg;
+	
+	LedCfg = read_nic_byte(dev, LEDCFG);
+	
+	switch(pLed->LedPin)
+	{
+	case LED_PIN_GPIO0:
+		break;
+
+	case LED_PIN_LED0:
+		LedCfg &= 0xf0; 
+
+		if(priv->bLedOpenDrain == true) 
+			write_nic_byte(dev, LEDCFG, (LedCfg|BIT1));
+		else
+			write_nic_byte(dev, LEDCFG, (LedCfg|BIT3));
+		break;
+
+	case LED_PIN_LED1:
+		LedCfg &= 0x0f; 
+		write_nic_byte(dev, LEDCFG, (LedCfg|BIT7));
+		break;
+
+	default:
+		break;
+	}
+
+	pLed->bLedOn = false;
+}
+
+
+void InitSwLeds(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	InitLed8190Pci(
+		dev,
+		&(priv->SwLed0), 
+		LED_PIN_LED0);
+
+	InitLed8190Pci(
+		dev,
+		&(priv->SwLed1), 
+		LED_PIN_LED1);
+}
+
+
+void DeInitSwLeds(struct net_device *dev)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	DeInitLed8190Pci( &(priv->SwLed0) );
+	DeInitLed8190Pci( &(priv->SwLed1) );
+}
+
+void HwLedBlink(struct net_device *dev, PLED_8190 pLed)
+{
+
+	
+	switch(pLed->LedPin)
+	{
+	case LED_PIN_GPIO0:
+		break;
+
+	case LED_PIN_LED0:
+		break;
+
+	case LED_PIN_LED1:
+		break;
+
+	default:
+		break;
+	}
+
+	pLed->bLedOn = true;
+}
+
+
+
+void SwLedBlink(PLED_8190 pLed)
+{
+	struct net_device *dev = (struct net_device *)pLed->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool bStopBlinking = false;
+	
+	if( pLed->BlinkingLedState == LED_ON ) 
+	{
+		SwLedOn(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes);
+	}	
+	else 
+	{
+		SwLedOff(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes);
+	}
+
+	pLed->BlinkTimes--;
+	switch(pLed->CurrLedState)
+	{
+	case LED_BLINK_NORMAL: 
+	case LED_BLINK_TXRX:
+	case LED_BLINK_RUNTOP:
+		if(pLed->BlinkTimes == 0)
+		{
+			bStopBlinking = true;
+		}
+		break;
+
+	case LED_SCAN_BLINK:
+		if( (priv->rtllib->state == RTLLIB_LINKED) &&  
+			(!rtllib_act_scanning(priv->rtllib,true))&& 
+			(pLed->BlinkTimes % 2 == 0)) 
+		{
+			bStopBlinking = true;
+		}
+		break;
+
+	case LED_NO_LINK_BLINK:
+	case LED_BLINK_StartToBlink:	
+		if( (priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_INFRA)) 
+		{
+			bStopBlinking = true;
+		}
+		else if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC))
+		{
+			bStopBlinking = true;
+		}
+		else if(pLed->BlinkTimes == 0)
+		{
+			bStopBlinking = true;
+		}
+		break;
+		
+	case LED_BLINK_CAMEO:
+		if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_INFRA)) 
+		{
+			bStopBlinking = true;
+		}
+		else if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC) )
+		{
+			bStopBlinking = true;
+		}
+		break;
+		
+	default:
+		bStopBlinking = true;
+		break;
+	}
+
+	if(bStopBlinking)
+	{
+		if( priv->rtllib->eRFPowerState != eRfOn )
+		{
+			SwLedOff(dev, pLed);
+		}
+		else if(pLed->CurrLedState == LED_BLINK_TXRX)
+		{
+			SwLedOff(dev, pLed);
+		}
+		else if(pLed->CurrLedState == LED_BLINK_RUNTOP)
+		{
+			SwLedOff(dev, pLed);
+		}
+		else if( (priv->rtllib->state == RTLLIB_LINKED) && (pLed->bLedOn == false))
+		{
+			SwLedOn(dev, pLed);
+		}
+		else if( (priv->rtllib->state != RTLLIB_LINKED) &&  pLed->bLedOn == true)
+		{
+			SwLedOff(dev, pLed);
+		}
+
+		pLed->BlinkTimes = 0;
+		pLed->bLedBlinkInProgress = false;	
+	}
+	else
+	{
+		if( pLed->BlinkingLedState == LED_ON ) 
+			pLed->BlinkingLedState = LED_OFF;
+		else 
+			pLed->BlinkingLedState = LED_ON;
+
+		switch( pLed->CurrLedState )
+		{
+		case LED_BLINK_NORMAL:
+		case LED_BLINK_TXRX:
+		case LED_BLINK_StartToBlink:
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL));
+			break;
+
+		case LED_BLINK_SLOWLY:
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL));
+			break;
+
+		case LED_SCAN_BLINK:
+		case LED_NO_LINK_BLINK:
+			if( pLed->bLedOn )
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+			else
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL));
+			break;
+			
+		case LED_BLINK_RUNTOP:
+			mod_timer(&(pLed->BlinkTimer),jiffies + MSECS(LED_RunTop_BLINK_INTERVAL));
+			break;
+			
+		case LED_BLINK_CAMEO:
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+			break;
+			
+		default:
+			RT_TRACE(COMP_ERR, "SwLedCm2Blink(): unexpected state!\n");
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL));
+			break;
+		}		
+	}
+}
+
+void SwLedBlink5(PLED_8190 pLed)
+{
+	struct net_device *dev = (struct net_device *)pLed->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool bStopBlinking = false;
+
+	if( pLed->BlinkingLedState == LED_ON ) 
+	{
+		SwLedOn(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes);
+	}	
+	else 
+	{
+		SwLedOff(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes);
+	}
+
+	switch(pLed->CurrLedState)
+	{
+		case LED_OFF:
+			SwLedOff(dev, pLed);
+			break;
+
+		case LED_BLINK_SLOWLY:
+			if( pLed->bLedOn )
+				pLed->BlinkingLedState = LED_OFF; 
+			else
+				pLed->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX));
+			break;
+
+		case LED_BLINK_NORMAL:
+			pLed->BlinkTimes--;
+			if( pLed->BlinkTimes == 0 )
+			{
+				bStopBlinking = true;
+			}
+			if(bStopBlinking)
+			{
+				if( priv->rtllib->eRFPowerState != eRfOn )
+				{
+					SwLedOff(dev, pLed);
+				}
+				else 
+				{
+					pLed->bLedSlowBlinkInProgress = true;
+					pLed->CurrLedState = LED_BLINK_SLOWLY;
+					if( pLed->bLedOn )
+						pLed->BlinkingLedState = LED_OFF; 
+					else
+						pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX));
+				}
+				pLed->BlinkTimes = 0;
+				pLed->bLedBlinkInProgress = false;	
+			}
+			else
+			{
+				if( priv->rtllib->eRFPowerState != eRfOn )
+				{
+					SwLedOff(dev, pLed);
+				}
+				else
+				{
+					if( pLed->bLedOn )
+						pLed->BlinkingLedState = LED_OFF; 
+					else
+						pLed->BlinkingLedState = LED_ON; 
+
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_NETTRONIX));
+				}
+			}
+			break;
+			
+		default:
+			break;	
+		}
+
+}
+
+
+void SwLedBlink6(PLED_8190 pLed)
+{
+	struct net_device *dev = (struct net_device *)pLed->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+	bool bStopBlinking = false;
+
+	if( pLed->BlinkingLedState == LED_ON ) 
+	{
+		SwLedOn(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes);
+	}	
+	else 
+	{
+		SwLedOff(dev, pLed);
+		RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes);
+	}
+	
+	switch(pLed->CurrLedState)
+	{
+		case LED_OFF:
+			SwLedOff(dev, pLed);
+			break;
+
+		case LED_BLINK_SLOWLY:
+			if( pLed->bLedOn )
+				pLed->BlinkingLedState = LED_OFF; 
+			else
+				pLed->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+			break;
+
+		case LED_BLINK_NORMAL:
+			pLed->BlinkTimes--;
+			if( pLed->BlinkTimes == 0 )
+			{
+				bStopBlinking = true;
+			}
+			if(bStopBlinking)
+			{
+				if( priv->rtllib->eRFPowerState != eRfOn )
+				{
+					SwLedOff(dev, pLed);
+				}
+				else 
+				{
+					pLed->bLedSlowBlinkInProgress = true;
+					pLed->CurrLedState = LED_BLINK_SLOWLY;
+					if( pLed->bLedOn )
+						pLed->BlinkingLedState = LED_OFF; 
+					else
+						pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+				}
+				pLed->BlinkTimes = 0;
+				pLed->bLedBlinkInProgress = false;	
+			}
+			else
+			{
+				if( priv->rtllib->eRFPowerState != eRfOn )
+				{
+					SwLedOff(dev, pLed);
+				}
+				else
+				{
+					if( pLed->bLedOn )
+						pLed->BlinkingLedState = LED_OFF; 
+					else
+						pLed->BlinkingLedState = LED_ON; 
+
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_PORNET));
+				}
+			}
+			break;
+			
+		default:
+			break;	
+		}
+	
+}
+
+void SwLedBlink7(	PLED_8190 pLed)
+{
+	struct net_device *dev = (struct net_device *)pLed->dev;
+
+	SwLedOn(dev, pLed);
+	RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes);	
+}
+
+void BlinkTimerCallback(unsigned long data)
+{	
+	PLED_8190 	pLed = (PLED_8190)data;
+	struct net_device *dev = (struct net_device *)pLed->dev;
+	struct r8192_priv *priv = rtllib_priv(dev);
+		
+	switch(priv->LedStrategy)
+	{
+	case SW_LED_MODE1:
+		break;
+	case SW_LED_MODE2:
+		break;
+	case SW_LED_MODE3:
+		break;
+	case SW_LED_MODE5:
+		break;
+	case SW_LED_MODE6:
+		break;
+
+	case SW_LED_MODE7:
+		SwLedBlink7(pLed);
+		break;
+
+	default:
+		break;
+	}	
+}
+
+void SwLedControlMode0(struct net_device *dev,LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+
+	switch(LedAction)
+	{
+	case LED_CTL_TX:
+	case LED_CTL_RX:	
+		break;
+
+	case LED_CTL_LINK:
+		pLed0->CurrLedState = LED_ON;
+		SwLedOn(dev, pLed0);
+
+		pLed1->CurrLedState = LED_BLINK_NORMAL;
+		HwLedBlink(dev, pLed1);
+		break;
+
+	case LED_CTL_POWER_ON:
+		pLed0->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed0);
+
+		pLed1->CurrLedState = LED_BLINK_NORMAL;
+		HwLedBlink(dev, pLed1);
+
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed0->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed0);
+
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+		break;
+
+	case LED_CTL_SITE_SURVEY:
+		break;
+
+	case LED_CTL_NO_LINK:
+		pLed0->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed0);
+
+		pLed1->CurrLedState = LED_BLINK_NORMAL;
+		HwLedBlink(dev, pLed1);
+		break;	
+
+	default:
+		break;
+	}
+
+	RT_TRACE(COMP_LED, "Led0 %d Led1 %d\n", pLed0->CurrLedState, pLed1->CurrLedState);
+}
+
+
+void SwLedControlMode1(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190	pLed = &(priv->SwLed1);
+	
+	switch(LedAction)
+	{
+	case LED_CTL_TX:
+	case LED_CTL_RX:
+		if( pLed->bLedBlinkInProgress == false )
+		{
+			pLed->bLedBlinkInProgress = true;
+
+			pLed->CurrLedState = LED_BLINK_NORMAL;
+			pLed->BlinkTimes = 2;
+
+			if( pLed->bLedOn )
+				pLed->BlinkingLedState = LED_OFF; 
+			else
+				pLed->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL));
+		}
+		break;
+
+	case LED_CTL_SITE_SURVEY:
+		if( pLed->bLedBlinkInProgress == false )
+		{
+			pLed->bLedBlinkInProgress = true;
+
+			if(priv->rtllib->state == RTLLIB_LINKED)
+			{
+				pLed->CurrLedState = LED_SCAN_BLINK;
+				pLed->BlinkTimes = 4;
+			}
+			else
+			{
+				pLed->CurrLedState = LED_NO_LINK_BLINK;
+				pLed->BlinkTimes = 24;
+			}
+
+			if( pLed->bLedOn )
+			{
+				pLed->BlinkingLedState = LED_OFF; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+			}
+			else
+			{
+				pLed->BlinkingLedState = LED_ON; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL));
+			}
+		}
+		else
+		{
+			if(pLed->CurrLedState != LED_NO_LINK_BLINK)
+			{
+				if(priv->rtllib->state == RTLLIB_LINKED)
+				{
+					pLed->CurrLedState = LED_SCAN_BLINK;
+				}
+				else
+				{
+					pLed->CurrLedState = LED_NO_LINK_BLINK;
+				}
+			}
+		}
+		break;
+
+	case LED_CTL_NO_LINK:
+		if( pLed->bLedBlinkInProgress == false )
+		{
+			pLed->bLedBlinkInProgress = true;
+
+			pLed->CurrLedState = LED_NO_LINK_BLINK;
+			pLed->BlinkTimes = 24;
+
+			if( pLed->bLedOn )
+			{
+				pLed->BlinkingLedState = LED_OFF; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+			}
+			else
+			{
+				pLed->BlinkingLedState = LED_ON; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL));
+			}
+		}
+		else
+		{
+			pLed->CurrLedState = LED_NO_LINK_BLINK;
+		}
+		break;
+
+	case LED_CTL_LINK:
+		pLed->CurrLedState = LED_ON;
+		if( pLed->bLedBlinkInProgress == false )
+		{
+			SwLedOn(dev, pLed);
+		}
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed->CurrLedState = LED_OFF;
+		if(pLed->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed->BlinkTimer));
+			pLed->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed);
+		break;
+
+	default:
+		break;
+	}
+	
+	RT_TRACE(COMP_LED, "Led %d \n", pLed->CurrLedState);
+}
+
+void SwLedControlMode2(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+	
+	switch(LedAction)
+	{
+	case LED_CTL_POWER_ON:
+		pLed0->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed0);
+		
+		pLed1->CurrLedState = LED_BLINK_CAMEO;
+		if( pLed1->bLedBlinkInProgress == false )
+		{
+			pLed1->bLedBlinkInProgress = true;
+
+			pLed1->BlinkTimes = 6;
+		
+			if( pLed1->bLedOn )
+				pLed1->BlinkingLedState = LED_OFF; 
+			else
+				pLed1->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+		}
+		break;
+
+	case LED_CTL_TX:
+	case LED_CTL_RX:
+		if( pLed0->bLedBlinkInProgress == false )
+		{
+			pLed0->bLedBlinkInProgress = true;
+
+			pLed0->CurrLedState = LED_BLINK_TXRX;
+			pLed0->BlinkTimes = 2;
+
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL));
+		}
+		break;
+
+	case LED_CTL_NO_LINK:
+		pLed1->CurrLedState = LED_BLINK_CAMEO;
+		if( pLed1->bLedBlinkInProgress == false )
+		{
+			pLed1->bLedBlinkInProgress = true;
+			
+			pLed1->BlinkTimes = 6;
+
+			if( pLed1->bLedOn )
+				pLed1->BlinkingLedState = LED_OFF; 
+			else
+				pLed1->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+		}
+		break;
+
+	case LED_CTL_LINK:
+		pLed1->CurrLedState = LED_ON;
+		if( pLed1->bLedBlinkInProgress == false )
+		{
+			SwLedOn(dev, pLed1);
+		}
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed0->CurrLedState = LED_OFF;
+		pLed1->CurrLedState = LED_OFF;
+		if(pLed0->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedBlinkInProgress = false;
+		}
+		if(pLed1->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed1->BlinkTimer));
+			pLed1->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed0);
+		SwLedOff(dev, pLed1);
+		break;
+
+	default:
+		break;
+	}
+	
+	RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState);
+}
+
+
+
+void SwLedControlMode3(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+	
+	switch(LedAction)
+	{
+	case LED_CTL_POWER_ON:
+		pLed0->CurrLedState = LED_ON;
+		SwLedOn(dev, pLed0);
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+		break;
+		
+	case LED_CTL_TX:
+	case LED_CTL_RX:
+		if( pLed1->bLedBlinkInProgress == false )
+		{
+			pLed1->bLedBlinkInProgress = true;
+
+			pLed1->CurrLedState = LED_BLINK_RUNTOP;
+			pLed1->BlinkTimes = 2;
+		
+			if( pLed1->bLedOn )
+				pLed1->BlinkingLedState = LED_OFF; 
+			else
+				pLed1->BlinkingLedState = LED_ON; 
+			
+			mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_RunTop_BLINK_INTERVAL));
+		}
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed0->CurrLedState = LED_OFF;
+		pLed1->CurrLedState = LED_OFF;
+		if(pLed0->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedBlinkInProgress = false;
+		}
+		if(pLed1->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed1->BlinkTimer));
+			pLed1->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed0);
+		SwLedOff(dev, pLed1);
+		break;
+
+	default:
+		break;
+	}
+	
+	RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState);
+}
+
+
+void SwLedControlMode4(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+	
+	switch(LedAction)
+	{
+	case LED_CTL_POWER_ON:
+		pLed1->CurrLedState = LED_ON;
+		SwLedOn(dev, pLed1);
+		pLed0->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed0);
+		break;
+		
+	case LED_CTL_TX:
+	case LED_CTL_RX:
+		if( pLed0->bLedBlinkInProgress == false )
+		{
+			pLed0->bLedBlinkInProgress = true;
+
+			pLed0->CurrLedState = LED_BLINK_RUNTOP;
+			pLed0->BlinkTimes = 2;
+		
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_RunTop_BLINK_INTERVAL));
+		}
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed0->CurrLedState = LED_OFF;
+		pLed1->CurrLedState = LED_OFF;
+		if(pLed0->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedBlinkInProgress = false;
+		}
+		if(pLed1->bLedBlinkInProgress)
+		{
+			del_timer_sync(&(pLed1->BlinkTimer));
+			pLed1->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed0);
+		SwLedOff(dev, pLed1);
+		break;
+
+	default:
+		break;
+	}
+	
+	RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState);
+}
+
+void SwLedControlMode5(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+	switch(LedAction)
+	{
+	case LED_CTL_POWER_ON:
+	case LED_CTL_START_TO_LINK:
+	case LED_CTL_NO_LINK:
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+
+
+		if( pLed0->bLedSlowBlinkInProgress == false )
+		{
+			pLed0->bLedSlowBlinkInProgress = true;
+			pLed0->CurrLedState = LED_BLINK_SLOWLY;
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX));
+		}
+		
+		break;
+	
+	case LED_CTL_TX:
+	case LED_CTL_RX:	
+		pLed1->CurrLedState = LED_ON;
+		SwLedOn(dev, pLed1);
+
+		if( pLed0->bLedBlinkInProgress == false )
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedSlowBlinkInProgress = false;
+			pLed0->bLedBlinkInProgress = true;
+			pLed0->CurrLedState = LED_BLINK_NORMAL;
+			pLed0->BlinkTimes = 2;
+
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+				mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_NETTRONIX));
+		}		
+		break;
+
+	case LED_CTL_LINK:
+		pLed1->CurrLedState = LED_ON;
+		SwLedOn(dev, pLed1);
+
+		if( pLed0->bLedSlowBlinkInProgress == false )
+		{
+			pLed0->bLedSlowBlinkInProgress = true;
+			pLed0->CurrLedState = LED_BLINK_SLOWLY;
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX));
+		}
+		break;
+
+
+	case LED_CTL_POWER_OFF:
+		pLed0->CurrLedState = LED_OFF;
+		pLed1->CurrLedState = LED_OFF;
+		if( pLed0->bLedSlowBlinkInProgress == true )
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedSlowBlinkInProgress = false;
+		}
+		if(pLed0->bLedBlinkInProgress == true)
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed0);
+		SwLedOff(dev, pLed1);
+		break;
+
+	default:
+		break;
+		}
+
+	
+}
+
+void SwLedControlMode6(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);
+	PLED_8190 pLed1 = &(priv->SwLed1);
+	
+
+	switch(LedAction)
+	{
+	case LED_CTL_POWER_ON:
+	case LED_CTL_START_TO_LINK:
+	case LED_CTL_NO_LINK:
+	case LED_CTL_LINK:
+	case LED_CTL_SITE_SURVEY:
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+		
+		if( pLed0->bLedSlowBlinkInProgress == false )
+		{
+			pLed0->bLedSlowBlinkInProgress = true;
+			pLed0->CurrLedState = LED_BLINK_SLOWLY;
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET));
+		}
+		break;
+
+	case LED_CTL_TX:
+	case LED_CTL_RX:
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+		if( pLed0->bLedBlinkInProgress == false )
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedSlowBlinkInProgress = false;
+			pLed0->bLedBlinkInProgress = true;
+			pLed0->CurrLedState = LED_BLINK_NORMAL;
+			pLed0->BlinkTimes = 2;
+			if( pLed0->bLedOn )
+				pLed0->BlinkingLedState = LED_OFF; 
+			else
+				pLed0->BlinkingLedState = LED_ON; 
+			mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_PORNET));
+		}		
+		break;
+
+	case LED_CTL_POWER_OFF:
+		pLed1->CurrLedState = LED_OFF;
+		SwLedOff(dev, pLed1);
+		
+		pLed0->CurrLedState = LED_OFF;
+		if( pLed0->bLedSlowBlinkInProgress == true )
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedSlowBlinkInProgress = false;
+		}
+		if(pLed0->bLedBlinkInProgress == true)
+		{
+			del_timer_sync(&(pLed0->BlinkTimer));
+			pLed0->bLedBlinkInProgress = false;
+		}
+		SwLedOff(dev, pLed0);
+		break;
+
+	default:
+		break;
+		
+		}
+}
+
+
+void SwLedControlMode7(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed0 = &(priv->SwLed0);	
+
+	switch(LedAction)
+	{
+		case LED_CTL_POWER_ON:
+		case LED_CTL_LINK:
+		case LED_CTL_NO_LINK:			
+			SwLedOn(dev, pLed0);
+			break;
+
+		case LED_CTL_POWER_OFF:
+				SwLedOff(dev, pLed0);
+			break;
+
+		default:
+			break;
+			
+		}
+}
+
+void
+SwLedControlMode8(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed = &(priv->SwLed0);	
+
+	switch(LedAction)
+	{
+		case LED_CTL_TX:
+		case LED_CTL_RX:
+			if( pLed->bLedBlinkInProgress == false && priv->rtllib->state == RTLLIB_LINKED)
+			{
+				pLed->bLedBlinkInProgress = true;
+
+				pLed->CurrLedState = LED_BLINK_NORMAL;
+				pLed->BlinkTimes = 2;
+
+				if( pLed->bLedOn )
+					pLed->BlinkingLedState = LED_OFF; 
+				else
+					pLed->BlinkingLedState = LED_ON; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL));
+			}
+			break;
+
+		case LED_CTL_SITE_SURVEY:
+			if( pLed->bLedBlinkInProgress == false )
+			{
+				pLed->bLedBlinkInProgress = true;
+				pLed->CurrLedState = LED_SCAN_BLINK;
+				pLed->BlinkTimes = 2;
+			
+				if( pLed->bLedOn )
+				{
+					pLed->BlinkingLedState = LED_OFF; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+				}
+				else
+				{
+					pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL));
+				}				
+			}
+			else if(pLed->CurrLedState != LED_SCAN_BLINK)
+			{
+				del_timer_sync(&(pLed->BlinkTimer));
+				pLed->CurrLedState = LED_SCAN_BLINK;
+				pLed->BlinkTimes = 2;
+
+				if( pLed->bLedOn )
+				{
+					pLed->BlinkingLedState = LED_OFF; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+				}
+				else
+				{
+					pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL));
+				}				
+			}			
+			break;
+
+		case LED_CTL_POWER_ON:
+		case LED_CTL_NO_LINK:
+			if( pLed->bLedBlinkInProgress == false )
+			{
+				pLed->bLedBlinkInProgress = true;
+
+				pLed->CurrLedState = LED_NO_LINK_BLINK;
+				pLed->BlinkTimes = 24;
+
+				if( pLed->bLedOn )
+				{
+					pLed->BlinkingLedState = LED_OFF; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+				}
+				else
+				{
+					pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL));
+				}
+			}
+			else if(pLed->CurrLedState != LED_SCAN_BLINK && pLed->CurrLedState != LED_NO_LINK_BLINK)
+			{
+				pLed->CurrLedState = LED_NO_LINK_BLINK;
+				pLed->BlinkTimes = 24;
+
+				if( pLed->bLedOn )
+				{
+					pLed->BlinkingLedState = LED_OFF; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL));
+				}
+				else
+				{
+					pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL));
+				}
+			}
+			break;
+
+		case LED_CTL_LINK:
+			pLed->CurrLedState = LED_ON;
+			if(pLed->bLedBlinkInProgress)
+			{
+				del_timer_sync(&(pLed->BlinkTimer));
+				pLed->bLedBlinkInProgress = false;
+			}
+			SwLedOn(dev, pLed);
+			break;
+
+		case LED_CTL_POWER_OFF:
+			pLed->CurrLedState = LED_OFF;
+			if(pLed->bLedBlinkInProgress)
+			{
+				del_timer_sync(&(pLed->BlinkTimer));
+				pLed->bLedBlinkInProgress = false;
+			}
+			SwLedOff(dev, pLed);
+			break;
+
+		default:
+			break;
+		}
+}
+
+void
+SwLedControlMode9(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+	PLED_8190 pLed = &(priv->SwLed0);	
+	
+		switch(LedAction)
+		{
+		case LED_CTL_TX:
+		case LED_CTL_RX:
+			if( pLed->bLedBlinkInProgress == false )
+			{
+				pLed->bLedBlinkInProgress = true;
+	
+				pLed->CurrLedState = LED_BLINK_NORMAL;
+				pLed->BlinkTimes = 2;
+	
+				if( pLed->bLedOn )
+					pLed->BlinkingLedState = LED_OFF; 
+				else
+					pLed->BlinkingLedState = LED_ON; 
+				mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL));
+			}
+			break;
+	
+		case LED_CTL_SITE_SURVEY:
+		 	if(priv->rtllib->LinkDetectInfo.bBusyTraffic && priv->rtllib->state == RTLLIB_LINKED)
+			 	;			
+			else 
+			{
+				if( pLed->bLedBlinkInProgress == true )			
+					del_timer_sync(&(pLed->BlinkTimer));
+				else		
+					pLed->bLedBlinkInProgress = true;
+	
+				pLed->CurrLedState = LED_SCAN_BLINK;
+				pLed->BlinkTimes = 24;
+	
+				if( pLed->bLedOn )
+				{
+					pLed->BlinkingLedState = LED_OFF; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL));
+				}
+				else
+				{
+					pLed->BlinkingLedState = LED_ON; 
+					mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL));
+				}
+			}	
+			break;
+	
+		case LED_CTL_POWER_ON:
+		case LED_CTL_NO_LINK:
+		case LED_CTL_LINK:
+			if( pLed->bLedBlinkInProgress == false )
+			{
+				pLed->CurrLedState = LED_ON;		
+				SwLedOn(dev, pLed);
+			}
+			break;
+	
+		case LED_CTL_POWER_OFF:
+			pLed->CurrLedState = LED_OFF;
+			if(pLed->bLedBlinkInProgress)
+			{
+				del_timer_sync(&(pLed->BlinkTimer));
+				pLed->bLedBlinkInProgress = false;
+			}
+			SwLedOff(dev, pLed);
+			break;
+	
+		default:
+			break;
+		}
+	
+		RT_TRACE(COMP_LED, "LED9 CurrLedState %d\n", pLed->CurrLedState);
+		
+}
+
+
+
+void LedControl8192SE(struct net_device *dev, LED_CTL_MODE LedAction)
+{
+	struct r8192_priv *priv = rtllib_priv(dev);
+
+	if(IS_NIC_DOWN(priv))
+		return;
+
+#ifdef TO_DO_LIST
+	if(Adapter->bInHctTest)
+		return;
+#endif
+
+	if(	priv->rtllib->eRFPowerState != eRfOn && 
+		(LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || 
+		 LedAction == LED_CTL_SITE_SURVEY || 
+		 LedAction == LED_CTL_LINK || 
+		 LedAction == LED_CTL_NO_LINK||
+		 LedAction == LED_CTL_START_TO_LINK ||
+		 LedAction == LED_CTL_POWER_ON) )
+	{
+		return;
+	}
+
+	RT_TRACE(COMP_LED, "LedAction %d, \n", LedAction);
+
+	switch(priv->LedStrategy)
+	{
+	case SW_LED_MODE0:
+		break;
+	case SW_LED_MODE1:
+		break;
+	case SW_LED_MODE2:
+		break;
+	case SW_LED_MODE3:
+		break;
+	case SW_LED_MODE4:
+		break;
+	case SW_LED_MODE5: 
+		break;
+		
+	case SW_LED_MODE6: 
+		break;
+
+	case SW_LED_MODE7:
+		SwLedControlMode7(dev, LedAction);
+		break;
+	case SW_LED_MODE8:
+		SwLedControlMode8(dev, LedAction);
+		break;
+
+	case SW_LED_MODE9:
+		SwLedControlMode9(dev, LedAction);
+		break;
+
+	default:
+		break;
+	}	
+}
+
+#ifdef TO_DO_LIST
+#ifdef NDIS50_MINIPORT
+void LedBlinkTimerStallCheck(struct net_device *dev)
+{	
+}
+
+
+void DoLedTimerStallCheck(PLED_8190 pLed)
+{	
+}
+#endif 
+#endif
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192SE_FW_IMG_H
+#define __INC_HAL8192SE_FW_IMG_H
+
+/*Created on  2009/ 7/23,  5: 4*/
+
+#include <linux/types.h>
+#define ImgArrayLength 75984
+extern u8 Rtl8192SEFwImgArray[ImgArrayLength];
+#define MainArrayLength 1
+extern u8 Rtl8192SEFwMainArray[MainArrayLength];
+#define DataArrayLength 1
+extern u8 Rtl8192SEFwDataArray[DataArrayLength];
+#define PHY_REG_2T2RArrayLength 372
+extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength];
+#define PHY_REG_1T2RArrayLength 1
+extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength];
+#define PHY_ChangeTo_1T1RArrayLength 48
+extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength];
+#define PHY_ChangeTo_1T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength];
+#define PHY_ChangeTo_2T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength];
+#define PHY_REG_Array_PGLength 84
+extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength];
+#define RadioA_1T_ArrayLength 202
+extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength];
+#define RadioB_ArrayLength 22
+extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength];
+#define RadioA_to1T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength];
+#define RadioA_to2T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength];
+#define RadioB_GM_ArrayLength 10
+extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength];
+#define MAC_2T_ArrayLength 106
+extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength];
+#define MACPHY_Array_PGLength 1
+extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength];
+#define AGCTAB_ArrayLength 320
+extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength];
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.c
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.c
@@ -0,0 +1,856 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#if defined(RTL8192SE)
+#include "../rtl_core.h"
+#include "../rtl_endianfree.h"
+#include "r8192S_hwimg.h"
+#include "r8192S_dev.h"
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE)
+#include <linux/firmware.h>
+#endif
+#define   byte(x,n)  ( (x >> (8 * n)) & 0xff  )
+
+static void fw_SetRQPN(struct net_device *dev)
+{	
+
+	write_nic_dword(dev,  RQPN, 0xffffffff);
+	write_nic_dword(dev,  RQPN+4, 0xffffffff);
+	write_nic_byte(dev,  RQPN+8, 0xff);
+	write_nic_byte(dev,  RQPN+0xB, 0x80);
+
+
+}	/* fw_SetRQPN */
+
+bool FirmwareDownloadCode(struct net_device *dev, u8 *	code_virtual_address,u32 buffer_len)
+{
+	struct r8192_priv   *priv = rtllib_priv(dev);
+	bool 		    rt_status = true;
+	u16		    frag_threshold = MAX_FIRMWARE_CODE_SIZE; 
+	u16		    frag_length, frag_offset = 0;
+	struct sk_buff	    *skb;
+	unsigned char	    *seg_ptr;
+	cb_desc		    *tcb_desc;	
+	u8                  	    bLastIniPkt = 0;
+	u16 			    ExtraDescOffset = 0;
+	
+#ifdef RTL8192SE
+	fw_SetRQPN(dev);	
+#endif
+
+	RT_TRACE(COMP_FIRMWARE, "--->FirmwareDownloadCode()\n" );	
+
+	if(buffer_len >= MAX_FIRMWARE_CODE_SIZE)
+	{
+		RT_TRACE(COMP_ERR, "Size over FIRMWARE_CODE_SIZE! \n");
+		goto cmdsend_downloadcode_fail;
+	}
+	
+	ExtraDescOffset = 0;
+	
+	do {
+		if((buffer_len-frag_offset) > frag_threshold)
+		{
+			frag_length = frag_threshold + ExtraDescOffset;
+		}
+		else
+		{
+			frag_length = (u16)(buffer_len - frag_offset + ExtraDescOffset);
+			bLastIniPkt = 1;
+		}
+
+		skb  = dev_alloc_skb(frag_length); 
+		memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+		
+		tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
+		tcb_desc->queue_index = TXCMD_QUEUE;
+		tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
+		tcb_desc->bLastIniPkt = bLastIniPkt;
+		
+		skb_reserve(skb, ExtraDescOffset);
+		seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length-ExtraDescOffset));
+		memcpy(seg_ptr, code_virtual_address+frag_offset, (u32)(frag_length-ExtraDescOffset));
+		
+		tcb_desc->txbuf_size= frag_length;
+
+		if(!priv->rtllib->check_nic_enough_desc(dev,tcb_desc->queue_index)||
+			(!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index]))||\
+			(priv->rtllib->queue_stop) ) 
+		{
+			RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
+			skb_queue_tail(&priv->rtllib->skb_waitQ[tcb_desc->queue_index], skb);
+		} 
+		else 
+		{
+			priv->rtllib->softmac_hard_start_xmit(skb,dev);
+		}
+		
+		frag_offset += (frag_length - ExtraDescOffset);
+
+	}while(frag_offset < buffer_len);
+	write_nic_byte(dev, TPPoll, TPPoll_CQ);
+	return rt_status ;
+
+
+cmdsend_downloadcode_fail:	
+	rt_status = false;
+	RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n");
+	return rt_status;
+
+}
+
+
+
+bool
+FirmwareEnableCPU(struct net_device *dev)
+{
+
+	bool rtStatus = true;
+	u8		tmpU1b, CPUStatus = 0;
+	u16		tmpU2b;	
+	u32		iCheckTime = 200;	
+
+	RT_TRACE(COMP_FIRMWARE, "-->FirmwareEnableCPU()\n" );
+
+	fw_SetRQPN(dev);	
+	
+	tmpU1b = read_nic_byte(dev, SYS_CLKR);
+	write_nic_byte(dev,  SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); 
+
+	tmpU2b = read_nic_word(dev, SYS_FUNC_EN);	
+	write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN));
+
+	do
+	{
+		CPUStatus = read_nic_byte(dev, TCR);
+		if(CPUStatus& IMEM_RDY)
+		{
+			RT_TRACE(COMP_FIRMWARE, "IMEM Ready after CPU has refilled.\n");	
+			break;		
+		}
+
+		udelay(100);
+	}while(iCheckTime--);
+
+	if(!(CPUStatus & IMEM_RDY))
+		return false;
+
+	RT_TRACE(COMP_FIRMWARE, "<--FirmwareEnableCPU(): rtStatus(%#x)\n", rtStatus);
+	return rtStatus;			
+}
+
+FIRMWARE_8192S_STATUS
+FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus)
+{
+	FIRMWARE_8192S_STATUS	NextFWStatus = 0;
+	
+	switch(FWCurrentStatus)
+	{
+		case FW_STATUS_INIT:
+			NextFWStatus = FW_STATUS_LOAD_IMEM;
+			break;
+
+		case FW_STATUS_LOAD_IMEM:
+			NextFWStatus = FW_STATUS_LOAD_EMEM;
+			break;
+		
+		case FW_STATUS_LOAD_EMEM:
+			NextFWStatus = FW_STATUS_LOAD_DMEM;
+			break;
+
+		case FW_STATUS_LOAD_DMEM:
+			NextFWStatus = FW_STATUS_READY;
+			break;
+
+		default:
+			RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus);			
+			break;
+	}	
+	return	NextFWStatus;
+}
+
+bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus)
+{
+	struct r8192_priv  *priv = rtllib_priv(dev);
+	bool rtStatus = true;
+	rt_firmware  *pFirmware = priv->pFirmware;
+	short  PollingCnt = 1000;
+	u8   CPUStatus = 0;
+	u32  tmpU4b;
+
+	RT_TRACE(COMP_FIRMWARE, "--->%s(): LoadStaus(%d),", __FUNCTION__, LoadFWStatus);
+
+	pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus;	
+
+	switch (LoadFWStatus) {
+	case FW_STATUS_LOAD_IMEM:
+		do {
+			CPUStatus = read_nic_byte(dev, TCR);
+			if(CPUStatus& IMEM_CODE_DONE)
+				break;	
+			udelay(5);
+		} while (PollingCnt--);		
+		if (!(CPUStatus & IMEM_CHK_RPT) || (PollingCnt <= 0)) {
+			RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus);
+			goto status_check_fail;			
+		}
+		break;
+
+	case FW_STATUS_LOAD_EMEM:
+		do {
+			CPUStatus = read_nic_byte(dev, TCR);
+			if(CPUStatus& EMEM_CODE_DONE)
+				break;
+			udelay(5);
+		} while(PollingCnt--);		
+		if (!(CPUStatus & EMEM_CHK_RPT) || (PollingCnt <= 0)) {
+			RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus);
+			goto status_check_fail;
+		}
+
+		rtStatus = FirmwareEnableCPU(dev);
+		if (rtStatus != true) {
+			RT_TRACE(COMP_ERR, "Enable CPU fail ! \n" );
+			goto status_check_fail;
+		}		
+		break;
+
+	case FW_STATUS_LOAD_DMEM:
+		do {
+			CPUStatus = read_nic_byte(dev, TCR);
+			if (CPUStatus& DMEM_CODE_DONE)
+				break;		
+			udelay(5);
+		} while(PollingCnt--);
+
+		if (!(CPUStatus & DMEM_CODE_DONE) || (PollingCnt <= 0)) {
+			RT_TRACE(COMP_ERR, "Polling  DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus);
+			goto status_check_fail;
+		}
+
+		RT_TRACE(COMP_FIRMWARE, "DMEM code download success, CPUStatus(%#x)\n", CPUStatus);		
+		PollingCnt = 2000; 
+		do {
+			CPUStatus = read_nic_byte(dev, TCR);
+			if(CPUStatus & FWRDY)
+				break;		
+			udelay(40);
+		} while(PollingCnt--);	
+
+		RT_TRACE(COMP_FIRMWARE, "Polling Load Firmware ready, CPUStatus(%x)\n", CPUStatus);		
+		if (((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY) || (PollingCnt <= 0)) {
+			RT_TRACE(COMP_ERR, "Polling Load Firmware ready fail ! CPUStatus(%x)\n", CPUStatus);
+			goto status_check_fail;
+		}
+
+#ifdef RTL8192SE
+#endif 
+
+		tmpU4b = read_nic_dword(dev,TCR);
+		write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV)));
+
+		tmpU4b = read_nic_dword(dev, RCR);
+		write_nic_dword(dev, RCR, 
+				(tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC));
+
+		RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current RCR settings(%#x)\n", tmpU4b);
+
+#if 0
+		priv->TransmitConfig = read_nic_dword_E(dev, TCR);
+		RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current TCR settings(%#x)\n", priv->TransmitConfig);
+#endif
+
+		write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL);		
+		break;	
+	default :
+		RT_TRACE(COMP_FIRMWARE, "Unknown status check!\n");
+		rtStatus = false;
+		break;
+	}
+
+status_check_fail:
+	RT_TRACE(COMP_FIRMWARE, "<---%s: LoadFWStatus(%d), rtStatus(%x)\n", __FUNCTION__,
+			LoadFWStatus, rtStatus);
+	return rtStatus;
+}
+u8 FirmwareHeaderMapRfType(struct net_device *dev)
+{	
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	switch(priv->rf_type)
+	{
+		case RF_1T1R: 	return 0x11;
+		case RF_1T2R: 	return 0x12;
+		case RF_2T2R: 	return 0x22;
+		case RF_2T2R_GREEN: 	return 0x92;
+		default:
+			RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type);
+			break;
+	}
+	return 0x22;
+}
+
+
+void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV 	pFwPriv)
+{
+	pFwPriv->rf_config = FirmwareHeaderMapRfType(dev);
+}
+
+
+
+bool FirmwareDownload92S(struct net_device *dev)
+{	
+	struct r8192_priv 	*priv = rtllib_priv(dev);
+	bool			rtStatus = true;
+	u8			*pucMappedFile = NULL;
+	u32			ulFileLength = 0;	
+	u8			FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;	
+	rt_firmware		*pFirmware = priv->pFirmware;
+	u8			FwStatus = FW_STATUS_INIT;
+	PRT_8192S_FIRMWARE_HDR	pFwHdr = NULL;
+	PRT_8192S_FIRMWARE_PRIV	pFwPriv = NULL;
+	
+	pFirmware->FWStatus = FW_STATUS_INIT;
+
+	RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n");
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE)
+	priv->firmware_source = FW_SOURCE_IMG_FILE;
+#else
+	priv->firmware_source = FW_SOURCE_HEADER_FILE;
+#endif
+
+	switch( priv->firmware_source )
+	{
+		case FW_SOURCE_IMG_FILE:		
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE)			
+			if(pFirmware->szFwTmpBufferLen == 0)
+			{
+#ifdef _RTL8192_EXT_PATCH_
+				const char 		*pFwImageFileName[1] = {"RTL8191SE_MESH/rtl8192sfw.bin"};
+#else
+				const char 		*pFwImageFileName[1] = {"RTL8192SE/rtl8192sfw.bin"};
+#endif
+				const struct firmware 	*fw_entry = NULL;
+				u32 ulInitStep = 0;
+				int 			rc = 0;
+				u32			file_length = 0;
+				rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->pdev->dev);
+				if(rc < 0 ) {
+					RT_TRACE(COMP_ERR, "request firmware fail!\n");
+					goto DownloadFirmware_Fail;
+				} 
+
+				if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) {
+					RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
+					release_firmware(fw_entry);
+					goto DownloadFirmware_Fail;
+				}
+
+				memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
+				pFirmware->szFwTmpBufferLen = fw_entry->size;
+				release_firmware(fw_entry);
+
+				pucMappedFile = pFirmware->szFwTmpBuffer;
+				file_length = pFirmware->szFwTmpBufferLen;
+
+				pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;				
+				pFwHdr = pFirmware->pFwHeader;
+				RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
+						pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
+						pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
+				pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);			
+				if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
+				{
+					RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
+							__FUNCTION__);
+					goto DownloadFirmware_Fail;
+				} else {				
+					pucMappedFile+=FwHdrSize;
+
+					memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
+					pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;				
+				}
+
+				if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
+				{
+					RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
+							__FUNCTION__);	
+					goto DownloadFirmware_Fail;
+				}
+				else
+				{	
+					pucMappedFile += pFirmware->FwIMEMLen;
+
+					memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
+					pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;		
+				}	
+			}
+#endif
+			break;	
+
+		case FW_SOURCE_HEADER_FILE:	
+#if 1
+#define Rtl819XFwImageArray Rtl8192SEFwImgArray
+			pucMappedFile = Rtl819XFwImageArray;
+			ulFileLength = ImgArrayLength;
+
+			RT_TRACE(COMP_INIT,"Fw download from header.\n");
+			pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;				
+			pFwHdr = pFirmware->pFwHeader;
+			RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
+					pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
+					pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
+			pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);			
+
+			if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
+			{
+				printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n");					
+				goto DownloadFirmware_Fail;
+			}
+			else
+			{				
+				pucMappedFile+=FwHdrSize;
+
+				memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
+				pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;				
+			}
+
+			if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
+			{
+				printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n");					
+				goto DownloadFirmware_Fail;
+			} else {	
+				pucMappedFile+= pFirmware->FwIMEMLen;
+
+				memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
+				pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;		
+			}
+#endif
+			break;
+		default:
+			break;
+	}			
+
+	FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
+	while(FwStatus!= FW_STATUS_READY)
+	{
+		switch(FwStatus)
+		{
+			case FW_STATUS_LOAD_IMEM:				
+				pucMappedFile = pFirmware->FwIMEM;
+				ulFileLength = pFirmware->FwIMEMLen;					
+				break;
+
+			case FW_STATUS_LOAD_EMEM:				
+				pucMappedFile = pFirmware->FwEMEM;
+				ulFileLength = pFirmware->FwEMEMLen;					
+				break;
+
+			case FW_STATUS_LOAD_DMEM:			
+				pFwHdr = pFirmware->pFwHeader;
+				pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv;
+				FirmwareHeaderPriveUpdate(dev, pFwPriv);
+				pucMappedFile = (u8*)(pFirmware->pFwHeader)+RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
+				ulFileLength = FwHdrSize-RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;				
+				break;
+					
+			default:
+				RT_TRACE(COMP_ERR, "Unexpected Download step!!\n");
+				goto DownloadFirmware_Fail;
+				break;
+		}		
+		
+		rtStatus = FirmwareDownloadCode(dev, pucMappedFile, ulFileLength);	
+		
+		if(rtStatus != true)
+		{
+			RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n" );
+			goto DownloadFirmware_Fail;
+		}	
+		
+		rtStatus = FirmwareCheckReady(dev, FwStatus);
+
+		if(rtStatus != true)
+		{
+			RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n");
+			goto DownloadFirmware_Fail;
+		}
+		
+		FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
+	}
+
+	RT_TRACE(COMP_FIRMWARE, "Firmware Download Success!!\n");	
+	return rtStatus;	
+	
+	DownloadFirmware_Fail:	
+	RT_TRACE(COMP_ERR, "Firmware Download Fail!!%x\n",read_nic_word(dev, TCR));	
+	rtStatus = false;
+	return rtStatus;	
+}
+void rtl8192se_dump_skb_data(struct sk_buff *skb)
+{
+	u8 i = 0;
+	u8 *arry = skb->data;
+
+	printk("\nSCAN_CMD/PROBE_REQ==============>\n");
+	for(i = 0; i < skb->len; i ++){
+		if((i % 4 == 0)&&(i != 0))
+			printk("\n");
+		printk("%2.2x ", arry[i]);
+	}
+	printk("\nSCAN_CMD/PROBE_REQ<==============\n");
+}
+
+void rtl8192se_dump_cmd_para(u8*SiteSurveyPara)
+{
+	u8 i = 0;
+	u8 desc_size = sizeof(tx_desc_fw);
+	u8 para_size = 8+desc_size;
+	u8 *arry = SiteSurveyPara;
+
+	printk("\nSCAN_CMD_PARA==============>\n");
+	for(i = 0; i < para_size; i ++){
+		if((i % 4 == 0)&&(i != 0))
+			printk("\n");
+		printk("%2.2x ", arry[i]);
+	}
+	printk("\nSCAN_CMD_PARA<==============\n");
+}
+#if 1 
+RT_STATUS
+CmdSendPacket(
+	struct net_device	*dev,
+	cb_desc			*pTcb,
+	struct sk_buff	    	*skb,
+	u32				BufferLen,
+	u32				PacketType,
+	bool				bLastInitPacket 
+	)
+{
+	struct r8192_priv   	*priv = rtllib_priv(dev);
+
+	RT_STATUS		rtStatus = RT_STATUS_SUCCESS;
+	
+	pTcb->queue_index 	= TXCMD_QUEUE;
+	pTcb->bCmdOrInit 	= PacketType;
+	pTcb->bLastIniPkt	= bLastInitPacket;
+	pTcb->txbuf_size	= BufferLen;
+
+
+	if(!priv->rtllib->check_nic_enough_desc(dev,pTcb->queue_index)||
+		(!skb_queue_empty(&priv->rtllib->skb_waitQ[pTcb->queue_index]))||\
+		(priv->rtllib->queue_stop) ) 	{
+		RT_TRACE(COMP_CMD,"=========================> tx full!\n");
+		skb_queue_tail(&priv->rtllib->skb_waitQ[pTcb->queue_index], skb);
+	} else {
+		priv->rtllib->softmac_hard_start_xmit(skb,dev);
+	}
+		
+	return rtStatus;
+}
+
+u32
+FillH2CCmd(
+	struct sk_buff 	*skb,
+	u32			H2CBufferLen,
+	u32			CmdNum,
+	u32*		pElementID,
+	u32*		pCmdLen,
+	u8**		pCmbBuffer,
+	u8*			CmdStartSeq
+	)
+{
+	u8	i = 0;
+	u32	TotalLen = 0, Len = 0, TxDescLen = 0;
+	u32	preContinueOffset = 0;
+
+	u8*	pH2CBuffer;
+	
+	do
+	{
+		Len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pCmdLen[i], 8);
+
+		if(H2CBufferLen < TotalLen + Len + TxDescLen)
+			break;
+		
+		pH2CBuffer = (u8 *) skb_put(skb, (u32)Len);
+		memset((pH2CBuffer + TotalLen + TxDescLen),0,Len);
+
+		SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 0, 16, pCmdLen[i]);
+
+		SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 16, 8, pElementID[i]);
+
+		*CmdStartSeq = *CmdStartSeq % 0x80;
+		SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 24, 7, *CmdStartSeq);
+		++ *CmdStartSeq;
+		
+		memcpy((pH2CBuffer + TotalLen + TxDescLen + H2C_TX_CMD_HDR_LEN), pCmbBuffer[i], pCmdLen[i]);
+
+		if(i < CmdNum - 1) 
+			SET_BITS_TO_LE_4BYTE((pH2CBuffer + preContinueOffset), 31, 1, 1);
+
+		preContinueOffset = TotalLen;
+
+		TotalLen += Len;
+	}while(++ i < CmdNum);
+
+	return TotalLen;
+}
+
+u32
+GetH2CCmdLen(
+	u32		H2CBufferLen,
+	u32		CmdNum,
+	u32*	pCmdLen
+	)
+{
+	u8	i = 0;
+	u32	TotalLen = 0, Len = 0, TxDescLen = 0;
+
+	do
+	{
+		Len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pCmdLen[i], 8);
+
+		if(H2CBufferLen < TotalLen + Len + TxDescLen)
+			break;
+
+		TotalLen += Len;
+	}while(++ i < CmdNum);
+
+	return TotalLen + TxDescLen;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	FirmwareSetH2CCmd()
+ *
+ * Overview:	Set FW H2C command (Decide ElementID, cmd content length, and get FW buffer)
+ *
+ * Input:		H2CCmd: H2C command type. 
+ *			pCmdBuffer: Pointer of the H2C command content.
+ *
+ * Output:		NONE
+ *
+ * Return:		RT_STATUS
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	2009/1/12	tynli		Create the version 0.
+ *
+ *---------------------------------------------------------------------------*/
+RT_STATUS
+FirmwareSetH2CCmd( 
+	struct net_device 	*dev, 
+	u8				H2CCmd,
+	u8*				pCmdBuffer
+	)
+{	
+	struct r8192_priv   *priv = rtllib_priv(dev);
+	u32				ElementID;
+	u32				Cmd_Len;
+	cb_desc			*pTcb;
+	struct sk_buff	    	*skb;
+	u32				Len;
+
+	RT_STATUS		rtStatus;
+
+	switch(H2CCmd){
+	case FW_H2C_SETPWRMODE:
+		{
+			ElementID = H2C_SetPwrMode_CMD ;
+			Cmd_Len = sizeof(H2C_SETPWRMODE_PARM);
+		}
+		break;
+	case FW_H2C_JOINBSSRPT:
+		{
+			ElementID = H2C_JoinbssRpt_CMD;
+			Cmd_Len = sizeof(H2C_JOINBSSRPT_PARM);
+		}
+		break;
+	case FW_H2C_WoWLAN_UPDATE_GTK:
+		{
+			ElementID = H2C_WoWLAN_UPDATE_GTK_CMD;
+			Cmd_Len = sizeof(H2C_WPA_TWO_WAY_PARA);
+		}
+		break;	
+	case FW_H2C_WoWLAN_UPDATE_IV:
+		{
+			ElementID = H2C_WoWLAN_UPDATE_IV_CMD;
+			Cmd_Len = sizeof(unsigned long long);
+		}
+		break;
+
+	case FW_H2C_WoWLAN_OFFLOAD:
+		{
+			ElementID = H2C_WoWLAN_FW_OFFLOAD;
+			Cmd_Len = sizeof(u8);
+		}
+		break;
+	case FW_H2C_SITESURVEY:
+		{
+			ElementID = H2C_SiteSurvey_CMD;
+			Cmd_Len = sizeof(H2C_SITESURVEY_PARA) + ((PH2C_SITESURVEY_PARA)pCmdBuffer)->probe_req_len - sizeof(tx_desc_fw);
+		}
+		break;
+	default:
+		break;
+	}
+
+	RT_TRACE(COMP_CMD, "FirmwareSetH2CCmd() HW_VAR_SET_TX_CMD: ElementID = %d, %d+%d=Cmd_Len = %d\n", ElementID, sizeof(H2C_SITESURVEY_PARA),((PH2C_SITESURVEY_PARA)pCmdBuffer)->probe_req_len, Cmd_Len);
+
+	{
+		Len = GetH2CCmdLen(MAX_TRANSMIT_BUFFER_SIZE, 1, &Cmd_Len);
+
+		RT_TRACE(COMP_CMD, "---------->%s(), cmdlen:%d,len:%d\n", __func__,Cmd_Len,Len);
+		skb  = dev_alloc_skb(Len); 
+		memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+
+		pTcb = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
+		
+		FillH2CCmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &ElementID, &Cmd_Len, &pCmdBuffer, &priv->H2CTxCmdSeq);
+		
+
+		rtStatus = CmdSendPacket(dev, pTcb, skb, Len, DESC_PACKET_TYPE_NORMAL, false);
+		
+	}
+	
+	write_nic_byte(dev, TPPoll, TPPoll_CQ);
+
+	return RT_STATUS_SUCCESS;
+}
+
+
+void
+rtl8192se_set_scan_cmd(struct net_device *dev, u32 start_flag)
+{
+	struct r8192_priv   			*priv = rtllib_priv(dev);
+	H2C_SITESURVEY_PARA			*SiteSurveyPara;
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(H2C_SITESURVEY_PARA) +
+				RTL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			printk("----------->%s() Error!!!\n", __func__);
+			return;
+		}
+	}
+
+	SiteSurveyPara = priv->scan_cmd;
+	memset(SiteSurveyPara, 0, sizeof(struct _H2C_SITESURVEY_PARA) + RTL_MAX_SCAN_SIZE);
+
+	if(start_flag){
+		struct sk_buff *skb = rtllib_probe_req(priv->rtllib);	
+		cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
+
+
+		tcb_desc->queue_index = MGNT_QUEUE;
+		tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(priv->rtllib);	
+		tcb_desc->RATRIndex = 7;
+		tcb_desc->bTxDisableRateFallBack = 1;
+		tcb_desc->bTxUseDriverAssingedRate = 1;
+	
+		
+		SiteSurveyPara->start_flag 	= start_flag;
+		SiteSurveyPara->probe_req_len 	= skb->len + sizeof(tx_desc_fw);
+	
+		SiteSurveyPara->desc.MacID 	= 0;
+		SiteSurveyPara->desc.TXHT		= (tcb_desc->data_rate&0x80)?1:0;	
+		SiteSurveyPara->desc.TxRate	= MRateToHwRate8192SE(dev,tcb_desc->data_rate);
+		SiteSurveyPara->desc.TxShort	= rtl8192se_QueryIsShort(((tcb_desc->data_rate&0x80)?1:0), MRateToHwRate8192SE(dev,tcb_desc->data_rate), tcb_desc);
+
+		SiteSurveyPara->desc.AggEn 	= 0;
+		SiteSurveyPara->desc.Seq 		= 0; 
+		SiteSurveyPara->desc.RTSEn	= (tcb_desc->bRTSEnable && tcb_desc->bCTSEnable==false)?1:0;				
+		SiteSurveyPara->desc.CTS2Self	= (tcb_desc->bCTSEnable)?1:0;		
+		SiteSurveyPara->desc.RTSSTBC	= (tcb_desc->bRTSSTBC)?1:0;
+		SiteSurveyPara->desc.RTSHT	= (tcb_desc->rts_rate&0x80)?1:0;
+		SiteSurveyPara->desc.RTSRate	= MRateToHwRate8192SE(dev,tcb_desc->rts_rate);
+		SiteSurveyPara->desc.RTSRate	= MRateToHwRate8192SE(dev,MGN_24M);
+		SiteSurveyPara->desc.RTSBW	= 0;
+		SiteSurveyPara->desc.RTSSC	= tcb_desc->RTSSC;
+		SiteSurveyPara->desc.RTSShort	= (SiteSurveyPara->desc.RTSHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):(tcb_desc->bRTSUseShortGI?1:0);
+
+		if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40){
+			if(tcb_desc->bPacketBW)	{
+				SiteSurveyPara->desc.TxBw = 1;
+				SiteSurveyPara->desc.TXSC	 = 0;
+			} else {				
+				SiteSurveyPara->desc.TxBw = 0;
+				SiteSurveyPara->desc.TXSC	 = priv->nCur40MhzPrimeSC;
+			}
+		} else {
+			SiteSurveyPara->desc.TxBw	= 0;
+			SiteSurveyPara->desc.TXSC		= 0;
+		}
+	
+		SiteSurveyPara->desc.LINIP 		= 0;
+		SiteSurveyPara->desc.Offset 		= 32;
+		SiteSurveyPara->desc.PktSize 		= (u16)skb->len;		
+	
+		SiteSurveyPara->desc.RaBRSRID 	= tcb_desc->RATRIndex;
+	
+		SiteSurveyPara->desc.PktID		= 0x0;		
+		SiteSurveyPara->desc.QueueSel		= rtl8192se_MapHwQueueToFirmwareQueue(tcb_desc->queue_index, tcb_desc->priority); 
+	
+		SiteSurveyPara->desc.DataRateFBLmt= 0x1F;		
+		SiteSurveyPara->desc.DISFB		= tcb_desc->bTxDisableRateFallBack;
+		SiteSurveyPara->desc.UserRate		= tcb_desc->bTxUseDriverAssingedRate;
+
+	
+		SiteSurveyPara->desc.FirstSeg		= 1;
+		SiteSurveyPara->desc.LastSeg		= 1;
+	
+		SiteSurveyPara->desc.TxBufferSize	= (u16)skb->len;	
+	
+		SiteSurveyPara->desc.OWN			= 1;
+
+
+		memcpy(&SiteSurveyPara->probe_req[0], skb->data, (u16)skb->len);
+
+		dev_kfree_skb_any(skb);
+	} else {
+		SiteSurveyPara->start_flag 	= start_flag;
+		SiteSurveyPara->probe_req_len 	= 0;
+	}
+	
+	FirmwareSetH2CCmd( dev ,FW_H2C_SITESURVEY, (u8*)SiteSurveyPara);
+}
+
+int rtl8192se_send_scan_cmd(struct net_device 	*dev, bool start)
+{
+	struct r8192_priv   *priv = rtllib_priv(dev);
+	
+	if(start){
+		priv->rtllib->scan_watch_dog =0;
+#if 0
+		queue_delayed_work_rsl(priv->priv_wq,&priv->hw_scan_simu_wq,0);
+#else
+		rtl8192se_set_scan_cmd(dev, start);
+#endif
+	} else {
+#if 0
+		rtl8192se_rx_surveydone_cmd(dev);
+#else
+		rtl8192se_set_scan_cmd(dev, start);
+#endif
+	}
+	return true;
+}
+#endif
+
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.h
@@ -0,0 +1,116 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ * 
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ * 
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ * 
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+
+/*--------------------------Define Parameters-------------------------------*/
+
+#define	RF6052_MAX_TX_PWR	0x3F
+#define	RF6052_MAX_REG		0x3F
+#define	RF6052_MAX_PATH		4
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/ 
+
+/*------------------------------Define structure----------------------------*/ 
+
+
+/*------------------------Export global variable----------------------------*/
+/*------------------------Export global variable----------------------------*/
+
+/*------------------------Export Marco Definition---------------------------*/
+
+/*------------------------Export Marco Definition---------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+#if 1
+extern void PHY_SetRF0222DBandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth);	
+extern void PHY_SetRF8225Bandwidth(	struct net_device* dev ,	HT_CHANNEL_WIDTH Bandwidth);
+extern bool PHY_RF8225_Config(struct net_device* dev );
+extern void phy_RF8225_Config_HardCode(struct net_device*	dev);
+extern bool phy_RF8225_Config_ParaFile(struct net_device* dev);
+extern void PHY_SetRF8225CckTxPower(struct net_device* dev ,u8 powerlevel);
+extern void PHY_SetRF8225OfdmTxPower(struct net_device* dev ,u8        powerlevel);
+extern void PHY_SetRF0222DOfdmTxPower(struct net_device* dev ,u8 powerlevel);
+extern void PHY_SetRF0222DCckTxPower(struct net_device* dev ,u8        powerlevel);
+
+extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth);
+extern void PHY_RF8256_Config(struct net_device* dev);
+extern void phy_RF8256_Config_ParaFile(struct net_device* dev);
+extern void PHY_SetRF8256CCKTxPower(struct net_device*	dev, u8	powerlevel);
+extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel);
+#endif
+
+extern	void		RF_ChangeTxPath(struct net_device  * dev, u16 DataRate);
+extern	void		PHY_RF6052SetBandwidth(struct net_device  * dev,HT_CHANNEL_WIDTH	Bandwidth);	
+extern	void		PHY_RF6052SetCckTxPower(struct net_device  * dev, u8	powerlevel);
+extern	void		PHY_RF6052SetOFDMTxPower(struct net_device  * dev, u8* pPowerLevel, u8 Channel);
+extern	bool PHY_RF6052_Config(struct net_device  * dev);
+extern void PHY_RFShadowRefresh( struct net_device  		* dev);
+extern void PHY_RFShadowWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+
+extern bool
+PHY_RFShadowCompare(
+	struct net_device  		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset);
+extern void
+PHY_RFShadowRecorver(
+	struct net_device  		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset);
+extern void
+PHY_RFShadowCompareFlagSet(
+	struct net_device  		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset,
+	u8					Type);
+extern void
+PHY_RFShadowRecorverFlagSet(
+	struct net_device  		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset,
+	u8					Type);
+#if 0
+extern	u32
+PHY_RFShadowRead(
+	struct net_device  		* dev,
+	RF90_RADIO_PATH_E	eRFPath,
+	u32					Offset);
+extern void
+PHY_RFShadowCompareAll(
+	struct net_device  		* dev);
+extern void
+PHY_RFShadowRecorverAll(
+	struct net_device  		* dev);
+extern void
+PHY_RFShadowCompareFlagSetAll(
+	struct net_device  		* dev);
+extern void
+PHY_RFShadowRecorverFlagSetAll(
+	struct net_device  		* dev);
+extern void
+PHY_RFShadowRefresh(
+	struct net_device  		* dev);
+#endif
+/*--------------------------Exported Function prototype---------------------*/
+
+
+/* End of HalRf.h */
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_mp.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_mp.h
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef __INC_HAL8192S_MP_H
+#define __INC_HAL8192S_MP_H
+
+/*--------------------------Define Parameters-------------------------------*/
+
+#define MPT_NOOP				0
+#define MPT_READ_MAC_1BYTE			1
+#define MPT_READ_MAC_2BYTE			2
+#define MPT_READ_MAC_4BYTE			3
+#define MPT_WRITE_MAC_1BYTE			4
+#define MPT_WRITE_MAC_2BYTE			5
+#define MPT_WRITE_MAC_4BYTE			6
+#define MPT_READ_BB_CCK				7
+#define MPT_WRITE_BB_CCK				8
+#define MPT_READ_BB_OFDM				9
+#define MPT_WRITE_BB_OFDM				10
+#define MPT_READ_RF					11
+#define MPT_WRITE_RF					12
+#define MPT_READ_EEPROM_1BYTE			13
+#define MPT_WRITE_EEPROM_1BYTE		14
+#define MPT_READ_EEPROM_2BYTE			15
+#define MPT_WRITE_EEPROM_2BYTE		16
+#define MPT_SET_CSTHRESHOLD			21
+#define MPT_SET_INITGAIN				22
+#define MPT_SWITCH_BAND				23
+#define MPT_SWITCH_CHANNEL			24
+#define MPT_SET_DATARATE				25
+#define MPT_SWITCH_ANTENNA			26
+#define MPT_SET_TX_POWER				27
+#define MPT_SET_CONT_TX				28
+#define MPT_SET_SINGLE_CARRIER		29
+#define MPT_SET_CARRIER_SUPPRESSION	30
+
+#define MPT_SET_ANTENNA_GAIN_OFFSET	40
+#define MPT_SET_CRYSTAL_CAP			41
+#define MPT_TRIGGER_RF_THERMAL_METER	42		
+#define MPT_SET_SINGLE_TONE			43		
+#define MPT_READ_RF_THERMAL_METER	44		
+#define MPT_SWITCH_BAND_WIDTH		45		
+#define MPT_QUERY_TSSI_VALUE     		46          
+#define MPT_SET_TX_POWER_ADJUST          47
+#define MPT_DO_TX_POWER_TRACK		48
+#define MPT_QUERY_NIC_TYPE				49
+#define MPT_QUERY_WPS_PUSHED			50
+#define MPT_SET_LED_CONTROL			51
+#define MPT_TX_POWER_TRACK_CONTROL	52		
+
+#define MPT_WRITE_EFUSE_1BYTE  		53
+#define MPT_READ_EFUSE_1BYTE			54
+#define MPT_READ_EFUSE_2BYTE			55
+#define MPT_READ_EFUSE_4BYTE			56
+#define MPT_UPDATE_EFUSE				57
+#define MPT_UPDATE_EFUSE_UTILIZE		58
+#define MPT_UPDATE_AUTOLOAD_STS		59
+
+#define MAX_TX_PWR_INDEX_N_MODE 		64
+/*--------------------------Define Parameters-------------------------------*/
+
+/*------------------------------Define structure----------------------------*/ 
+/* MP set force data rate base on the definition. */
+typedef enum _MPT_RATE_INDEX{
+	/* CCK rate. */
+	MPT_RATE_1M = 1, 
+	MPT_RATE_2M,
+	MPT_RATE_55M,
+	MPT_RATE_11M,
+
+	/* OFDM rate. */
+	MPT_RATE_6M,
+	MPT_RATE_9M,
+	MPT_RATE_12M,
+	MPT_RATE_18M,
+	MPT_RATE_24M,
+	MPT_RATE_36M,
+	MPT_RATE_48M,
+	MPT_RATE_54M,
+	
+	/* HT rate. */
+	MPT_RATE_MCS0,
+	MPT_RATE_MCS1,
+	MPT_RATE_MCS2,
+	MPT_RATE_MCS3,
+	MPT_RATE_MCS4,
+	MPT_RATE_MCS5,
+	MPT_RATE_MCS6,
+	MPT_RATE_MCS7,
+	MPT_RATE_MCS8,
+	MPT_RATE_MCS9,
+	MPT_RATE_MCS10,
+	MPT_RATE_MCS11,
+	MPT_RATE_MCS12,
+	MPT_RATE_MCS13,
+	MPT_RATE_MCS14,
+	MPT_RATE_MCS15,
+	MPT_RATE_LAST
+	 
+}MPT_RATE_E, *PMPT_RATE_E;
+
+typedef enum _MPT_Bandwidth_Switch_Mode{
+	BAND_20MHZ_MODE = 0,
+	BAND_40MHZ_DUPLICATE_MODE = 1,
+	BAND_40MHZ_LOWER_MODE = 2,
+	BAND_40MHZ_UPPER_MODE = 3,
+	BAND_40MHZ_DONTCARE_MODE = 4
+}MPT_BANDWIDTH_MODE_E, *PMPT_BANDWIDTH_MODE_E;
+
+typedef enum _TxAGC_Offset{
+        TxAGC_Offset_0 	= 0x00,
+        TxAGC_Offset_1,
+        TxAGC_Offset_2,
+        TxAGC_Offset_3,
+        TxAGC_Offset_4,
+        TxAGC_Offset_5,
+        TxAGC_Offset_6,
+        TxAGC_Offset_7,
+        TxAGC_Offset_neg8,
+        TxAGC_Offset_neg7,
+        TxAGC_Offset_neg6,
+        TxAGC_Offset_neg5,
+        TxAGC_Offset_neg4,
+        TxAGC_Offset_neg3,
+        TxAGC_Offset_neg2,
+        TxAGC_Offset_neg1
+} TxAGC_Offset;
+/*------------------------------Define structure----------------------------*/ 
+void rtl8192_init_mp(struct net_device* dev);
+int r8192_wx_mp_set_chan(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_set_txrate(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_set_txpower(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_set_bw(struct net_device *dev,struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_set_txstart(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_set_singlecarrier(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_write_rf(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+int r8192_wx_mp_write_mac(struct net_device *dev, struct iw_request_info *info, 
+		union iwreq_data *wrqu, char *extra);
+
+void mpt_StartCckContTx(struct net_device *dev,bool bScrambleOn);
+void mpt_StartOfdmContTx(struct net_device *dev);
+void mpt_StopCckCoNtTx(struct net_device *dev);
+void mpt_StopOfdmContTx(struct net_device *dev);
+void mpt_SwitchRfSetting92S(struct net_device *dev);
+bool mpt_ProSetTxPower(	struct net_device *dev,	u32 ulTxPower);
+bool mpt_ProSetTxAGCOffset(struct net_device *dev,	u32	ulTxAGCOffset);
+bool mpt_ProSetRxFilter(struct net_device *dev, u32	RCRMode);
+bool mpt_ProSetRxFilter(struct net_device *dev, u32	RCRMode);
+bool mpt_ProSetModulation(struct net_device *dev, u32 ulWirelessMode);
+void mpt_Pro819xIoCallback(struct net_device *dev);
+void MPT_ProSetSingleCarrier(struct net_device *dev, bool ulMode);
+void MPT_ProSetBandWidth819x(struct net_device *dev);
+void MPT_ProSwChannel(struct net_device *dev);
+void MPT_ProSetDataRate819x(struct net_device *dev);
+void MPT_ProSetTxAGCOffset(struct net_device *dev);
+#endif
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phy.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_phy.h
@@ -0,0 +1,202 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+/* Check to see if the file has been included already.  */
+#ifndef _R8192S_PHY_H
+#define _R8192S_PHY_H
+
+
+/*--------------------------Define Parameters-------------------------------*/
+#define LOOP_LIMIT				5
+#define MAX_STALL_TIME			50		
+#define AntennaDiversityValue		0x80	
+#define MAX_TXPWR_IDX_NMODE_92S	63
+#define Reset_Cnt_Limit			3
+
+
+#define MAX_PRECMD_CNT 			16
+#define MAX_RFDEPENDCMD_CNT 	16
+#define MAX_POSTCMD_CNT 		16
+#ifdef RTL8192SE
+#define	SET_RTL8192SE_RF_SLEEP(dev)							\
+{																	\
+	u8		u1bTmp;												\
+	u1bTmp = read_nic_byte (dev, LDOV12D_CTRL);		\
+	u1bTmp |= BIT0;													\
+	write_nic_byte(dev, LDOV12D_CTRL, u1bTmp);		\
+	write_nic_byte(dev, SPS1_CTRL, 0x0);				\
+	write_nic_byte(dev, TXPAUSE, 0xFF);				\
+	write_nic_word(dev, CMDR, 0x57FC);				\
+	udelay(100);													\
+	write_nic_word(dev, CMDR, 0x77FC);				\
+	write_nic_byte(dev, PHY_CCA, 0x0);				\
+	udelay(10);													\
+	write_nic_word(dev, CMDR, 0x37FC);				\
+	udelay(10);													\
+	write_nic_word(dev, CMDR, 0x77FC);				\
+	udelay(10);													\
+	write_nic_word(dev, CMDR, 0x57FC);				\
+}
+
+
+#endif
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/ 
+typedef enum _SwChnlCmdID{
+	CmdID_End,
+	CmdID_SetTxPowerLevel,
+	CmdID_BBRegWrite10,
+	CmdID_WritePortUlong,
+	CmdID_WritePortUshort,
+	CmdID_WritePortUchar,
+	CmdID_RF_WriteReg,
+}SwChnlCmdID;
+
+
+typedef struct _SwChnlCmd{
+	SwChnlCmdID	CmdID;
+	u32			Para1;
+	u32			Para2;
+	u32			msDelay;
+}__attribute__ ((packed)) SwChnlCmd;
+
+extern u32 rtl819XMACPHY_Array_PG[];
+extern u32 rtl819XPHY_REG_1T2RArray[];
+extern u32 rtl819XAGCTAB_Array[];
+extern u32 rtl819XRadioA_Array[];
+extern u32 rtl819XRadioB_Array[];
+extern u32 rtl819XRadioC_Array[];
+extern u32 rtl819XRadioD_Array[];
+
+typedef enum _HW90_BLOCK{
+	HW90_BLOCK_MAC = 0,
+	HW90_BLOCK_PHY0 = 1,
+	HW90_BLOCK_PHY1 = 2,
+	HW90_BLOCK_RF = 3,
+	HW90_BLOCK_MAXIMUM = 4, 
+}HW90_BLOCK_E, *PHW90_BLOCK_E;
+
+typedef enum _RF90_RADIO_PATH{
+	RF90_PATH_A = 0,			
+	RF90_PATH_B = 1,			
+	RF90_PATH_C = 2,			
+	RF90_PATH_D = 3,			
+#ifndef _RTL8192_EXT_PATCH_
+	RF90_PATH_MAX	= 4,			
+#endif
+}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
+#ifdef _RTL8192_EXT_PATCH_
+#define	RF90_PATH_MAX			2
+#endif
+
+#define bMaskByte0                0xff
+#define bMaskByte1                0xff00
+#define bMaskByte2                0xff0000
+#define bMaskByte3                0xff000000
+#define bMaskHWord                0xffff0000
+#define bMaskLWord                0x0000ffff
+#define bMaskDWord                0xffffffff
+
+typedef enum _BaseBand_Config_Type{
+	BaseBand_Config_PHY_REG = 0,			
+	BaseBand_Config_AGC_TAB = 1,			
+}BaseBand_Config_Type, *PBaseBand_Config_Type;
+
+typedef enum _VERSION_8190{
+	VERSION_8190_BD=0x3,
+	VERSION_8190_BE
+}VERSION_8190,*PVERSION_8190;
+
+
+typedef enum _VERSION_8192S{
+	VERSION_8192S_ACUT,
+	VERSION_8192S_BCUT,
+	VERSION_8192S_CCUT
+}VERSION_8192S,*PVERSION_8192S;
+
+typedef enum _PHY_Rate_Tx_Power_Offset_Area{
+	RA_OFFSET_LEGACY_OFDM1,
+	RA_OFFSET_LEGACY_OFDM2,
+	RA_OFFSET_HT_OFDM1,
+	RA_OFFSET_HT_OFDM2,
+	RA_OFFSET_HT_OFDM3,
+	RA_OFFSET_HT_OFDM4,
+	RA_OFFSET_HT_CCK,
+}RA_OFFSET_AREA,*PRA_OFFSET_AREA;
+#if 0
+typedef enum _RATR_TABLE_MODE_8192S{
+	RATR_INX_WIRELESS_NGB = 0,
+	RATR_INX_WIRELESS_NG = 1,
+	RATR_INX_WIRELESS_NB = 2,
+	RATR_INX_WIRELESS_N = 3,
+	RATR_INX_WIRELESS_GB = 4,
+	RATR_INX_WIRELESS_G = 5,
+	RATR_INX_WIRELESS_B = 6,
+	RATR_INX_WIRELESS_MC = 7,
+	RATR_INX_WIRELESS_A = 8,
+}RATR_TABLE_MODE_8192S, *PRATR_TABLE_MODE_8192S;
+#endif
+/*------------------------------Define structure----------------------------*/ 
+
+
+/*------------------------Export global variable----------------------------*/
+/*------------------------Export global variable----------------------------*/
+
+
+/*------------------------Export Marco Definition---------------------------*/
+/*------------------------Export Marco Definition---------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+
+extern	u32	rtl8192_QueryBBReg(struct net_device* dev,u32 RegAddr, u32 BitMask);
+extern	void	rtl8192_setBBreg(struct net_device* dev,u32 RegAddr, u32 BitMask,u32 Data);
+extern	u32	rtl8192_phy_QueryRFReg(struct net_device* dev,RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
+extern	void	rtl8192_phy_SetRFReg(struct net_device* dev,RF90_RADIO_PATH_E eRFPath, u32 RegAddr,u32 BitMask,u32 Data);
+
+bool rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
+
+
+extern	bool 	PHY_MACConfig8192S(struct net_device* dev);
+extern	bool 	PHY_BBConfig8192S(struct net_device* dev);
+extern	bool 	PHY_RFConfig8192S(struct net_device* dev);
+
+extern	u8	rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev,RF90_RADIO_PATH_E eRFPath);
+extern	void	rtl8192_SetBWMode(struct net_device* dev,HT_CHANNEL_WIDTH ChnlWidth,HT_EXTCHNL_OFFSET Offset	);
+extern	u8	rtl8192_phy_SwChnl(struct net_device* dev,u8 channel);	
+extern	u8	rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev,u32 eRFPath	);
+extern	void    rtl8192_BBConfig(struct net_device* dev);
+extern	void 	PHY_IQCalibrateBcut(struct net_device* dev);
+extern	void 	PHY_IQCalibrate(struct net_device* dev);
+extern	void 	PHY_GetHWRegOriginalValue(struct net_device* dev);
+
+extern void 	InitialGainOperateWorkItemCallBack(void *data);
+void rtl8192_phy_setTxPower(struct net_device* dev, u8  channel);
+
+/*--------------------------Exported Function prototype---------------------*/
+bool rtl8192se_set_fw_cmd(struct net_device* dev, FW_CMD_IO_TYPE                FwCmdIO);
+extern void PHY_SetBeaconHwReg( struct net_device* dev, u16 BeaconInterval);
+void ChkFwCmdIoDone(struct net_device* dev);
+void PHY_SwitchEphyParameter(struct net_device* dev);
+bool PHY_SetRFPowerState(struct net_device* dev, RT_RF_POWER_STATE eRFPowerState);
+
+#endif	
+
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_led.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_led.h
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192SELED_H
+#define __INC_HAL8192SELED_H
+
+
+
+typedef	enum _LED_STATE_8190{
+	LED_UNKNOWN = 0,
+	LED_ON = 1,
+	LED_OFF = 2,
+	LED_BLINK_NORMAL = 3,
+	LED_BLINK_SLOWLY = 4,
+	LED_POWER_ON_BLINK = 5,
+	LED_SCAN_BLINK = 6, 
+	LED_NO_LINK_BLINK = 7, 
+	LED_BLINK_StartToBlink = 8, 
+	LED_BLINK_TXRX = 9,
+	LED_BLINK_RUNTOP = 10, 
+	LED_BLINK_CAMEO = 11,
+}LED_STATE_8190;
+
+typedef enum _LED_PIN_8190{
+	LED_PIN_GPIO0,
+	LED_PIN_LED0,
+	LED_PIN_LED1
+}LED_PIN_8190;
+
+typedef struct _LED_8190{
+	void *			dev;
+
+	LED_PIN_8190	LedPin;	
+
+	LED_STATE_8190	CurrLedState; 
+	bool				bLedOn; 
+
+	bool				bLedBlinkInProgress; 
+
+	bool				bLedSlowBlinkInProgress;
+	u32				BlinkTimes; 
+	LED_STATE_8190	BlinkingLedState; 
+
+	struct timer_list 	BlinkTimer; 
+} LED_8190, *PLED_8190;
+
+
+
+
+typedef	enum _LED_STRATEGY_8190{
+	SW_LED_MODE0, 
+	SW_LED_MODE1, 
+	SW_LED_MODE2, 
+	SW_LED_MODE3, 
+	SW_LED_MODE4, 
+	SW_LED_MODE5, 
+	SW_LED_MODE6, 
+	SW_LED_MODE7, 
+	SW_LED_MODE8,
+	SW_LED_MODE9, 
+	HW_LED, 
+}LED_STRATEGY_8190, *PLED_STRATEGY_8190;
+
+
+void InitSwLeds(struct net_device *dev);
+void DeInitSwLeds(struct net_device *dev);
+void LedControl8192SE(struct net_device *dev, LED_CTL_MODE LedAction);
+
+#endif	/*__INC_HAL8190PCILED_H*/
--- linux-ec2-2.6.32.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.h
+++ linux-ec2-2.6.32/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192SE_FW_IMG_H
+#define __INC_HAL8192SE_FW_IMG_H
+
+/*Created on  2009/11/17, 16:15*/
+
+#include <linux/types.h>
+#define ImgArrayLength 88592
+extern u8 Rtl8192SEFwImgArray[ImgArrayLength];
+#define MainArrayLength 1
+extern u8 Rtl8192SEFwMainArray[MainArrayLength];
+#define DataArrayLength 1
+extern u8 Rtl8192SEFwDataArray[DataArrayLength];
+#define PHY_REG_2T2RArrayLength 372
+extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength];
+#define PHY_REG_1T2RArrayLength 1
+extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength];
+#define PHY_ChangeTo_1T1RArrayLength 48
+extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength];
+#define PHY_ChangeTo_1T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength];
+#define PHY_ChangeTo_2T2RArrayLength 45
+extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength];
+#define PHY_REG_Array_PGLength 84
+extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength];
+#define RadioA_1T_ArrayLength 202
+extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength];
+#define RadioB_ArrayLength 22
+extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength];
+#define RadioA_to1T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength];
+#define RadioA_to2T_ArrayLength 196
+extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength];
+#define RadioB_GM_ArrayLength 10
+extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength];
+#define MAC_2T_ArrayLength 106
+extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength];
+#define MACPHY_Array_PGLength 1
+extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength];
+#define AGCTAB_ArrayLength 320
+extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength];
+
+#endif 
--- linux-ec2-2.6.32.orig/ubuntu/rfkill/Makefile
+++ linux-ec2-2.6.32/ubuntu/rfkill/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Ubuntu additional drivers
+#
+
+obj-$(CONFIG_AVERATEC_5100P)	+= av5100.o
+obj-$(CONFIG_PACKARDBELL_E5)	+= pbe5.o
--- linux-ec2-2.6.32.orig/ubuntu/rfkill/av5100.c
+++ linux-ec2-2.6.32/ubuntu/rfkill/av5100.c
@@ -0,0 +1,174 @@
+/*******************************************************************************
+  
+  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of version 2 of the GNU General Public License as 
+  published by the Free Software Foundation.
+  
+  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.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Contact Information:
+  James P. Ketrenos <ipw2100-admin@linux.intel.com>
+  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+
+#define DRV_NAME		"av5100"
+#define DRV_VERSION		"1.3"
+#define DRV_DESCRIPTION		"SW RF kill switch for Averatec 5100P"
+#define DRV_COPYRIGHT		"Copyright(c) 2003-2004 Intel Corporation"
+
+static int radio = 1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+MODULE_PARM(radio, "i");
+
+#else /* LINUX_VERSION_CODE < 2.6.0 */
+
+#include <linux/moduleparam.h>
+module_param(radio, int, 1);
+
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
+
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+#define AV5100_RADIO_ON (0xe0)
+#define AV5100_RADIO_OFF (0xe1)
+
+static int av5100_radio = AV5100_RADIO_OFF;
+
+static void av5100_set_radio(int state)
+{
+	printk(KERN_INFO DRV_NAME ": Radio being turned %s\n",
+	       (state  == AV5100_RADIO_ON) ? "ON" : "OFF");
+	outl(0x80020800, 0xcf8);
+	outb(0x6f, 0x0072);
+	outl(0x1800ffff, 0x1184); 
+	outb(state, 0x00b2);
+	av5100_radio = state;
+}
+
+
+/*
+ * proc stuff
+ */
+static struct proc_dir_entry *dir_base = NULL;
+
+static int proc_set_radio(struct file *file, const char *buffer, 
+			  unsigned long count, void *data)
+{
+	av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON);
+	
+	return count;
+}
+
+static int proc_get_radio(char *page, char **start, off_t offset,
+			  int count, int *eof, void *data)
+{
+	int len = 0;
+	
+	len += snprintf(page, count, DRV_NAME ": %d\n", 
+			av5100_radio == AV5100_RADIO_OFF ? 0 : 1);
+	
+	*eof = 1;
+	return len;
+}
+
+
+static void av5100_proc_cleanup(void)
+{
+	if (dir_base) {
+		remove_proc_entry("radio", dir_base);
+		remove_proc_entry(DRV_NAME, NULL);
+		dir_base = NULL;
+	}
+}
+
+
+static int av5100_proc_init(void)
+{
+	struct proc_dir_entry *ent;
+	int err = 0;
+
+	dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
+	if (dir_base == NULL) {
+		printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/" 
+		       DRV_NAME "\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+
+	ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR, 
+				dir_base);
+	if (ent) {
+		ent->read_proc = proc_get_radio;
+		ent->write_proc = proc_set_radio;
+	} else {
+		printk(KERN_ERR
+		       "Unable to initialize /proc/" DRV_NAME "/radio\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	av5100_proc_cleanup();
+	return err;
+}
+
+/*
+ * module stuff
+ */
+static int __init av5100_init(void)
+{
+	av5100_proc_init();
+
+	av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF);
+	
+	return 0;
+}
+
+static void __exit av5100_exit(void)
+{
+	av5100_set_radio(AV5100_RADIO_OFF);
+
+	av5100_proc_cleanup();
+}
+
+module_init(av5100_init);
+module_exit(av5100_exit);
+
+/*
+         1         2         3         4         5         6         7
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
--- linux-ec2-2.6.32.orig/ubuntu/rfkill/Kconfig
+++ linux-ec2-2.6.32/ubuntu/rfkill/Kconfig
@@ -0,0 +1,9 @@
+config AVERATEC_5100P
+	tristate "Software kill switch for Averatec 5100P"
+	depends on X86
+	default m
+
+config PACKARDBELL_E5
+	tristate "Software kill switch for Packard Bell EasyNote E5"
+	depends on X86
+	default m
--- linux-ec2-2.6.32.orig/ubuntu/rfkill/pbe5.c
+++ linux-ec2-2.6.32/ubuntu/rfkill/pbe5.c
@@ -0,0 +1,205 @@
+/*******************************************************************************
+  
+  This program is free software; you can redistribute it and/or modify it 
+  under the terms of version 2 of the GNU General Public License as 
+  published by the Free Software Foundation.
+  
+  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.
+  
+  The full GNU General Public License is included in this distribution in the
+  file called LICENSE.
+  
+  Author:
+  Pedro Ramalhais <pmr09313@students.fct.unl.pt>
+  
+  Based on:
+  av5100.c from http://ipw2100.sourceforge.net/
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define DRV_NAME		"pbe5"
+#define DRV_VERSION		"1.3"
+#define DRV_DESCRIPTION		"SW RF kill switch for Packard Bell EasyNote E5"
+#define DRV_AUTHOR		"Pedro Ramalhais"
+#define DRV_LICENSE		"GPL"
+
+static int radio = 1;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+
+MODULE_PARM(radio, "i");
+
+#else /* LINUX_VERSION_CODE < 2.6.0 */
+
+#include <linux/moduleparam.h>
+module_param(radio, int, 1);
+
+#endif /* LINUX_VERSION_CODE < 2.6.0 */
+
+MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)");
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_LICENSE(DRV_LICENSE);
+
+/*
+ * NOTE: These values were obtained from disassembling the Icon.exe program
+ * installed in the Packard Bell EasyNote E5 laptop. The names were guessed,
+ * so don't rely on them.
+ */
+#define PBE5_PORT_TOGGLE	0x0b3
+#define PBE5_VALUE_TOGGLE_ON	0x01
+#define PBE5_VALUE_TOGGLE_OFF	0x00
+#define PBE5_PORT_APPLY		0x0b2
+#define PBE5_VALUE_APPLY	0xef
+
+// Some "booleans" =;-)
+#define PBE5_RADIO_OFF	0
+#define PBE5_RADIO_ON	1
+
+static int pbe5_radio_status = PBE5_RADIO_ON;
+
+unsigned char pbe5_get_radio(void)
+{
+	unsigned char val = 0x00;
+
+	val = inb(PBE5_PORT_TOGGLE);
+
+	return val;
+}
+
+static void pbe5_set_radio(int state_set)
+{
+	pbe5_radio_status = pbe5_get_radio();
+
+	if (pbe5_radio_status != state_set) {
+		// Set the radio toggle register
+		outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE);
+		// Commit the radio toggle register value
+		outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY);
+		// Update the radio status
+		pbe5_radio_status = pbe5_get_radio();
+
+		printk(KERN_INFO DRV_NAME ": Radio turned %s\n",
+			(state_set  == PBE5_RADIO_ON) ? "ON" : "OFF");
+	} else {
+		printk(KERN_INFO DRV_NAME ": Radio already %s\n",
+			(state_set  == PBE5_RADIO_ON) ? "ON" : "OFF");
+	}
+}
+
+
+/*
+ * proc stuff
+ */
+static struct proc_dir_entry *dir_base = NULL;
+
+static int proc_set_radio(struct file *file, const char *buffer, 
+			  unsigned long count, void *data)
+{
+	pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON);
+
+	return count;
+}
+
+static int proc_get_radio(char *page, char **start, off_t offset,
+			  int count, int *eof, void *data)
+{
+	int len = 0;
+
+	len += snprintf(page, count, DRV_NAME ": %d\n", 
+			pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1);
+
+	*eof = 1;
+	return len;
+}
+
+
+static void pbe5_proc_cleanup(void)
+{
+	if (dir_base) {
+		remove_proc_entry("radio", dir_base);
+		remove_proc_entry(DRV_NAME, NULL);
+		dir_base = NULL;
+	}
+}
+
+
+static int pbe5_proc_init(void)
+{
+	struct proc_dir_entry *ent;
+	int err = 0;
+
+	dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL);
+	if (dir_base == NULL) {
+		printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/"
+		       DRV_NAME "\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+
+	ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR,
+				dir_base);
+	if (ent) {
+		ent->read_proc = proc_get_radio;
+		ent->write_proc = proc_set_radio;
+	} else {
+		printk(KERN_ERR
+		       "Unable to initialize /proc/" DRV_NAME "/radio\n");
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	return 0;
+
+ fail:
+	pbe5_proc_cleanup();
+	return err;
+}
+
+/*
+ * module stuff
+ */
+static int __init pbe5_init(void)
+{
+	pbe5_proc_init();
+
+	pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF);
+
+	return 0;
+}
+
+static void __exit pbe5_exit(void)
+{
+	pbe5_set_radio(PBE5_RADIO_OFF);
+
+	pbe5_proc_cleanup();
+}
+
+module_init(pbe5_init);
+module_exit(pbe5_exit);
+
+/*
+         1         2         3         4         5         6         7
+12345678901234567890123456789012345678901234567890123456789012345678901234567890
+*/
--- linux-ec2-2.6.32.orig/ubuntu/rfkill/BOM
+++ linux-ec2-2.6.32/ubuntu/rfkill/BOM
@@ -0,0 +1,6 @@
+Downloaded from:	http://sourceforge.net/project/showfiles.php?group_id=108766
+Current Version:	1.3
+Comments:
+
+Had to change &proc_root to NULL due to changes in create/remove proc
+entry usage.
--- linux-ec2-2.6.32.orig/arch/Kconfig
+++ linux-ec2-2.6.32/arch/Kconfig
@@ -6,8 +6,6 @@
 	tristate "OProfile system profiling (EXPERIMENTAL)"
 	depends on PROFILING
 	depends on HAVE_OPROFILE
-	depends on TRACING_SUPPORT
-	select TRACING
 	select RING_BUFFER
 	select RING_BUFFER_ALLOW_SWAP
 	help
@@ -20,7 +18,7 @@
 config OPROFILE_IBS
 	bool "OProfile AMD IBS support (EXPERIMENTAL)"
 	default n
-	depends on OPROFILE && SMP && X86
+	depends on OPROFILE && SMP && X86 && !XEN
 	help
           Instruction-Based Sampling (IBS) is a new profiling
           technique that provides rich, precise program performance
--- linux-ec2-2.6.32.orig/arch/alpha/kernel/err_marvel.c
+++ linux-ec2-2.6.32/arch/alpha/kernel/err_marvel.c
@@ -109,7 +109,7 @@
 #define IO7__ERR_CYC__CYCLE__M	(0x7)
 
 	printk("%s        Packet In Error: %s\n"
-	       "%s        Error in %s, cycle %ld%s%s\n",
+	       "%s        Error in %s, cycle %lld%s%s\n",
 	       err_print_prefix, 
 	       packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)],
 	       err_print_prefix,
@@ -313,7 +313,7 @@
 	}
 
 	printk("%s      Up Hose Garbage Symptom:\n"
-	       "%s        Source Port: %ld - Dest PID: %ld - OpCode: %s\n", 
+	       "%s        Source Port: %lld - Dest PID: %lld - OpCode: %s\n",
 	       err_print_prefix,
 	       err_print_prefix, 
 	       EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT),
@@ -552,7 +552,7 @@
 #define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M	(0xfff)
 
 	printk("%s      Split Completion Error:\n"	
-	       "%s         Source (Bus:Dev:Func): %ld:%ld:%ld\n",
+	       "%s         Source (Bus:Dev:Func): %lld:%lld:%lld\n",
 	       err_print_prefix,
 	       err_print_prefix,
 	       EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS),
--- linux-ec2-2.6.32.orig/arch/alpha/kernel/osf_sys.c
+++ linux-ec2-2.6.32/arch/alpha/kernel/osf_sys.c
@@ -178,25 +178,18 @@
 		unsigned long, prot, unsigned long, flags, unsigned long, fd,
 		unsigned long, off)
 {
-	struct file *file = NULL;
-	unsigned long ret = -EBADF;
+	unsigned long ret = -EINVAL;
 
 #if 0
 	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", 
 			current->comm, flags);
 #endif
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	down_write(&current->mm->mmap_sem);
-	ret = do_mmap(file, addr, len, prot, flags, off);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
+	if ((off + PAGE_ALIGN(len)) < off)
+		goto out;
+	if (off & ~PAGE_MASK)
+		goto out;
+	ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
  out:
 	return ret;
 }
--- linux-ec2-2.6.32.orig/arch/mips/kernel/linux32.c
+++ linux-ec2-2.6.32/arch/mips/kernel/linux32.c
@@ -67,28 +67,13 @@
 	unsigned long, prot, unsigned long, flags, unsigned long, fd,
 	unsigned long, pgoff)
 {
-	struct file * file = NULL;
 	unsigned long error;
 
 	error = -EINVAL;
 	if (pgoff & (~PAGE_MASK >> 12))
 		goto out;
-	pgoff >>= PAGE_SHIFT-12;
-
-	if (!(flags & MAP_ANONYMOUS)) {
-		error = -EBADF;
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
-
+	error = sys_mmap_pgoff(addr, len, prot, flags, fd,
+			       pgoff >> (PAGE_SHIFT-12));
 out:
 	return error;
 }
--- linux-ec2-2.6.32.orig/arch/mips/kernel/syscall.c
+++ linux-ec2-2.6.32/arch/mips/kernel/syscall.c
@@ -93,7 +93,8 @@
 		 * We do not accept a shared mapping if it would violate
 		 * cache aliasing constraints.
 		 */
-		if ((flags & MAP_SHARED) && (addr & shm_align_mask))
+		if ((flags & MAP_SHARED) &&
+		    ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
 			return -EINVAL;
 		return addr;
 	}
@@ -129,31 +130,6 @@
 	}
 }
 
-/* common code for old and new mmaps */
-static inline unsigned long
-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-        unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
-	unsigned long error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
 	unsigned long, prot, unsigned long, flags, unsigned long,
 	fd, off_t, offset)
@@ -164,7 +140,7 @@
 	if (offset & ~PAGE_MASK)
 		goto out;
 
-	result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 
 out:
 	return result;
@@ -177,7 +153,7 @@
 	if (pgoff & (~PAGE_MASK >> 12))
 		return -EINVAL;
 
-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
 }
 
 save_static_function(sys_fork);
--- linux-ec2-2.6.32.orig/arch/mips/pci/ops-pmcmsp.c
+++ linux-ec2-2.6.32/arch/mips/pci/ops-pmcmsp.c
@@ -944,6 +944,7 @@
 	.pci_ops	= &msp_pci_ops,
 	.mem_resource	= &pci_mem_resource,
 	.mem_offset	= 0,
+	.io_map_base	= MSP_PCI_IOSPACE_BASE,
 	.io_resource	= &pci_io_resource,
 	.io_offset	= 0
 };
--- linux-ec2-2.6.32.orig/arch/mips/pci/pci-yosemite.c
+++ linux-ec2-2.6.32/arch/mips/pci/pci-yosemite.c
@@ -54,6 +54,7 @@
 		panic(ioremap_failed);
 
 	set_io_port_base(io_v_base);
+	py_controller.io_map_base = io_v_base;
 	TITAN_WRITE(RM9000x2_OCD_LKM7, TITAN_READ(RM9000x2_OCD_LKM7) | 1);
 
 	ioport_resource.end = TITAN_IO_SIZE - 1;
--- linux-ec2-2.6.32.orig/arch/mips/math-emu/cp1emu.c
+++ linux-ec2-2.6.32/arch/mips/math-emu/cp1emu.c
@@ -75,6 +75,9 @@
 #define FPCREG_RID	0	/* $0  = revision id */
 #define FPCREG_CSR	31	/* $31 = csr */
 
+/* Determine rounding mode from the RM bits of the FCSR */
+#define modeindex(v) ((v) & FPU_CSR_RM)
+
 /* Convert Mips rounding mode (0..3) to IEEE library modes. */
 static const unsigned char ieee_rm[4] = {
 	[FPU_CSR_RN] = IEEE754_RN,
@@ -381,10 +384,14 @@
 					(void *) (xcp->cp0_epc),
 					MIPSInst_RT(ir), value);
 #endif
-				value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
-				ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
-				/* convert to ieee library modes */
-				ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
+
+				/*
+				 * Don't write reserved bits,
+				 * and convert to ieee library modes
+				 */
+				ctx->fcr31 = (value &
+						~(FPU_CSR_RSVD | FPU_CSR_RM)) |
+						ieee_rm[modeindex(value)];
 			}
 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
 				return SIGFPE;
--- linux-ec2-2.6.32.orig/arch/mips/alchemy/mtx-1/platform.c
+++ linux-ec2-2.6.32/arch/mips/alchemy/mtx-1/platform.c
@@ -28,6 +28,8 @@
 #include <linux/mtd/physmap.h>
 #include <mtd/mtd-abi.h>
 
+#include <asm/mach-au1x00/au1xxx_eth.h>
+
 static struct gpio_keys_button mtx1_gpio_button[] = {
 	{
 		.gpio = 207,
@@ -140,10 +142,17 @@
 	&mtx1_mtd,
 };
 
+static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = {
+	.phy_search_highest_addr	= 1,
+	.phy1_search_mac0 		= 1,
+};
+
 static int __init mtx1_register_devices(void)
 {
 	int rc;
 
+	au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata);
+
 	rc = gpio_request(mtx1_gpio_button[0].gpio,
 					mtx1_gpio_button[0].desc);
 	if (rc < 0) {
--- linux-ec2-2.6.32.orig/arch/mips/nxp/pnx8550/common/setup.c
+++ linux-ec2-2.6.32/arch/mips/nxp/pnx8550/common/setup.c
@@ -113,7 +113,7 @@
 	PNX8550_GLB2_ENAB_INTA_O = 0;
 
 	/* IO/MEM resources. */
-	set_io_port_base(KSEG1);
+	set_io_port_base(PNX8550_PORT_BASE);
 	ioport_resource.start = 0;
 	ioport_resource.end = ~0;
 	iomem_resource.start = 0;
--- linux-ec2-2.6.32.orig/arch/mips/nxp/pnx8550/common/pci.c
+++ linux-ec2-2.6.32/arch/mips/nxp/pnx8550/common/pci.c
@@ -44,6 +44,7 @@
 
 static struct pci_controller pnx8550_controller = {
 	.pci_ops	= &pnx8550_pci_ops,
+	.io_map_base	= PNX8550_PORT_BASE,
 	.io_resource	= &pci_io_resource,
 	.mem_resource	= &pci_mem_resource,
 };
--- linux-ec2-2.6.32.orig/arch/mips/sibyte/sb1250/setup.c
+++ linux-ec2-2.6.32/arch/mips/sibyte/sb1250/setup.c
@@ -87,6 +87,21 @@
 	return ret;
 }
 
+int sb1250_m3_workaround_needed(void)
+{
+	switch (soc_type) {
+	case K_SYS_SOC_TYPE_BCM1250:
+	case K_SYS_SOC_TYPE_BCM1250_ALT:
+	case K_SYS_SOC_TYPE_BCM1250_ALT2:
+	case K_SYS_SOC_TYPE_BCM1125:
+	case K_SYS_SOC_TYPE_BCM1125H:
+		return soc_pass < K_SYS_REVISION_BCM1250_C0;
+
+	default:
+		return 0;
+	}
+}
+
 static int __init setup_bcm112x(void)
 {
 	int ret = 0;
--- linux-ec2-2.6.32.orig/arch/mips/mm/tlbex.c
+++ linux-ec2-2.6.32/arch/mips/mm/tlbex.c
@@ -73,9 +73,6 @@
 enum label_id {
 	label_second_part = 1,
 	label_leave,
-#ifdef MODULE_START
-	label_module_alloc,
-#endif
 	label_vmalloc,
 	label_vmalloc_done,
 	label_tlbw_hazard,
@@ -92,9 +89,6 @@
 
 UASM_L_LA(_second_part)
 UASM_L_LA(_leave)
-#ifdef MODULE_START
-UASM_L_LA(_module_alloc)
-#endif
 UASM_L_LA(_vmalloc)
 UASM_L_LA(_vmalloc_done)
 UASM_L_LA(_tlbw_hazard)
@@ -731,10 +725,15 @@
 	 * create the plain linear handler
 	 */
 	if (bcm1250_m3_war()) {
-		UASM_i_MFC0(&p, K0, C0_BADVADDR);
-		UASM_i_MFC0(&p, K1, C0_ENTRYHI);
+		unsigned int segbits = 44;
+
+		uasm_i_dmfc0(&p, K0, C0_BADVADDR);
+		uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
 		uasm_i_xor(&p, K0, K0, K1);
-		UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+		uasm_i_dsrl32(&p, K1, K0, 62 - 32);
+		uasm_i_dsrl(&p, K0, K0, 12 + 1);
+		uasm_i_dsll32(&p, K0, K0, 64 + 12 + 1 - segbits - 32);
+		uasm_i_or(&p, K0, K0, K1);
 		uasm_il_bnez(&p, &r, K0, label_leave);
 		/* No need for uasm_i_nop */
 	}
@@ -802,8 +801,6 @@
 	} else {
 #if defined(CONFIG_HUGETLB_PAGE)
 		const enum label_id ls = label_tlb_huge_update;
-#elif defined(MODULE_START)
-		const enum label_id ls = label_module_alloc;
 #else
 		const enum label_id ls = label_vmalloc;
 #endif
@@ -1250,10 +1247,15 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	if (bcm1250_m3_war()) {
-		UASM_i_MFC0(&p, K0, C0_BADVADDR);
-		UASM_i_MFC0(&p, K1, C0_ENTRYHI);
+		unsigned int segbits = 44;
+
+		uasm_i_dmfc0(&p, K0, C0_BADVADDR);
+		uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
 		uasm_i_xor(&p, K0, K0, K1);
-		UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1);
+		uasm_i_dsrl32(&p, K1, K0, 62 - 32);
+		uasm_i_dsrl(&p, K0, K0, 12 + 1);
+		uasm_i_dsll32(&p, K0, K0, 64 + 12 + 1 - segbits - 32);
+		uasm_i_or(&p, K0, K0, K1);
 		uasm_il_bnez(&p, &r, K0, label_leave);
 		/* No need for uasm_i_nop */
 	}
--- linux-ec2-2.6.32.orig/arch/mips/mm/uasm.h
+++ linux-ec2-2.6.32/arch/mips/mm/uasm.h
@@ -78,6 +78,7 @@
 Ip_u1u2u3(_mfc0);
 Ip_u1u2u3(_mtc0);
 Ip_u2u1u3(_ori);
+Ip_u3u1u2(_or);
 Ip_u2s3u1(_pref);
 Ip_0(_rfe);
 Ip_u2s3u1(_sc);
--- linux-ec2-2.6.32.orig/arch/mips/mm/dma-default.c
+++ linux-ec2-2.6.32/arch/mips/mm/dma-default.c
@@ -43,27 +43,39 @@
 
 static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
 {
+	gfp_t dma_flag;
+
 	/* ignore region specifiers */
 	gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
 
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ISA
 	if (dev == NULL)
-		gfp |= __GFP_DMA;
-	else if (dev->coherent_dma_mask < DMA_BIT_MASK(24))
-		gfp |= __GFP_DMA;
+		dma_flag = __GFP_DMA;
 	else
 #endif
-#ifdef CONFIG_ZONE_DMA32
+#if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
 	     if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
-		gfp |= __GFP_DMA32;
+			dma_flag = __GFP_DMA;
+	else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+			dma_flag = __GFP_DMA32;
+	else
+#endif
+#if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
+	     if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+		dma_flag = __GFP_DMA32;
+	else
+#endif
+#if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
+	     if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+		dma_flag = __GFP_DMA;
 	else
 #endif
-		;
+		dma_flag = 0;
 
 	/* Don't invoke OOM killer */
 	gfp |= __GFP_NORETRY;
 
-	return gfp;
+	return gfp | dma_flag;
 }
 
 void *dma_alloc_noncoherent(struct device *dev, size_t size,
--- linux-ec2-2.6.32.orig/arch/mips/mm/uasm.c
+++ linux-ec2-2.6.32/arch/mips/mm/uasm.c
@@ -62,7 +62,7 @@
 	insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
 	insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr,
 	insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
-	insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
+	insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
 	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
 	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori
 };
@@ -116,6 +116,7 @@
 	{ insn_lw,  M(lw_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_mfc0,  M(cop0_op, mfc_op, 0, 0, 0, 0),  RT | RD | SET},
 	{ insn_mtc0,  M(cop0_op, mtc_op, 0, 0, 0, 0),  RT | RD | SET},
+	{ insn_or,  M(spec_op, 0, 0, 0, 0, or_op),  RS | RT | RD },
 	{ insn_ori,  M(ori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
 	{ insn_pref,  M(pref_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 	{ insn_rfe,  M(cop0_op, cop_op, 0, 0, 0, rfe_op),  0 },
@@ -362,6 +363,7 @@
 I_u1u2u3(_mfc0)
 I_u1u2u3(_mtc0)
 I_u2u1u3(_ori)
+I_u3u1u2(_or)
 I_u2s3u1(_pref)
 I_0(_rfe)
 I_u2s3u1(_sc)
--- linux-ec2-2.6.32.orig/arch/mips/mti-malta/malta-pci.c
+++ linux-ec2-2.6.32/arch/mips/mti-malta/malta-pci.c
@@ -247,6 +247,8 @@
 	iomem_resource.end &= 0xfffffffffULL;			/* 64 GB */
 	ioport_resource.end = controller->io_resource->end;
 
+	controller->io_map_base = mips_io_port_base;
+
 	register_pci_controller(controller);
 }
 
--- linux-ec2-2.6.32.orig/arch/mips/include/asm/mipsregs.h
+++ linux-ec2-2.6.32/arch/mips/include/asm/mipsregs.h
@@ -135,6 +135,12 @@
 #define FPU_CSR_COND7   0x80000000      /* $fcc7 */
 
 /*
+ * Bits 18 - 20 of the FPU Status Register will be read as 0,
+ * and should be written as zero.
+ */
+#define FPU_CSR_RSVD	0x001c0000
+
+/*
  * X the exception cause indicator
  * E the exception enable
  * S the sticky/flag bit
@@ -161,7 +167,8 @@
 #define FPU_CSR_UDF_S   0x00000008
 #define FPU_CSR_INE_S   0x00000004
 
-/* rounding mode */
+/* Bits 0 and 1 of FPU Status Register specify the rounding mode */
+#define FPU_CSR_RM	0x00000003
 #define FPU_CSR_RN      0x0     /* nearest */
 #define FPU_CSR_RZ      0x1     /* towards zero */
 #define FPU_CSR_RU      0x2     /* towards +Infinity */
--- linux-ec2-2.6.32.orig/arch/mips/include/asm/atomic.h
+++ linux-ec2-2.6.32/arch/mips/include/asm/atomic.h
@@ -434,7 +434,7 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_add		\n"
-		"	addu	%0, %2					\n"
+		"	daddu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
@@ -446,7 +446,7 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_add		\n"
-		"	addu	%0, %2					\n"
+		"	daddu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqz	%0, 2f					\n"
 		"	.subsection 2					\n"
@@ -479,7 +479,7 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_sub		\n"
-		"	subu	%0, %2					\n"
+		"	dsubu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqzl	%0, 1b					\n"
 		"	.set	mips0					\n"
@@ -491,7 +491,7 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%0, %1		# atomic64_sub		\n"
-		"	subu	%0, %2					\n"
+		"	dsubu	%0, %2					\n"
 		"	scd	%0, %1					\n"
 		"	beqz	%0, 2f					\n"
 		"	.subsection 2					\n"
@@ -524,10 +524,10 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_add_return	\n"
-		"	addu	%0, %1, %3				\n"
+		"	daddu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
-		"	addu	%0, %1, %3				\n"
+		"	daddu	%0, %1, %3				\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -538,10 +538,10 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_add_return	\n"
-		"	addu	%0, %1, %3				\n"
+		"	daddu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 2f					\n"
-		"	addu	%0, %1, %3				\n"
+		"	daddu	%0, %1, %3				\n"
 		"	.subsection 2					\n"
 		"2:	b	1b					\n"
 		"	.previous					\n"
@@ -576,10 +576,10 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
-		"	subu	%0, %1, %3				\n"
+		"	dsubu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqzl	%0, 1b					\n"
-		"	subu	%0, %1, %3				\n"
+		"	dsubu	%0, %1, %3				\n"
 		"	.set	mips0					\n"
 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
 		: "Ir" (i), "m" (v->counter)
@@ -590,10 +590,10 @@
 		__asm__ __volatile__(
 		"	.set	mips3					\n"
 		"1:	lld	%1, %2		# atomic64_sub_return	\n"
-		"	subu	%0, %1, %3				\n"
+		"	dsubu	%0, %1, %3				\n"
 		"	scd	%0, %2					\n"
 		"	beqz	%0, 2f					\n"
-		"	subu	%0, %1, %3				\n"
+		"	dsubu	%0, %1, %3				\n"
 		"	.subsection 2					\n"
 		"2:	b	1b					\n"
 		"	.previous					\n"
--- linux-ec2-2.6.32.orig/arch/mips/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/mips/include/asm/compat.h
@@ -144,7 +144,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = (struct pt_regs *)
 		((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
--- linux-ec2-2.6.32.orig/arch/mips/include/asm/mach-sibyte/war.h
+++ linux-ec2-2.6.32/arch/mips/include/asm/mach-sibyte/war.h
@@ -16,7 +16,11 @@
 #if defined(CONFIG_SB1_PASS_1_WORKAROUNDS) || \
     defined(CONFIG_SB1_PASS_2_WORKAROUNDS)
 
-#define BCM1250_M3_WAR	1
+#ifndef __ASSEMBLY__
+extern int sb1250_m3_workaround_needed(void);
+#endif
+
+#define BCM1250_M3_WAR	sb1250_m3_workaround_needed()
 #define SIBYTE_1956_WAR	1
 
 #else
--- linux-ec2-2.6.32.orig/arch/xtensa/kernel/syscall.c
+++ linux-ec2-2.6.32/arch/xtensa/kernel/syscall.c
@@ -57,31 +57,6 @@
 	return error;
 }
 
-
-asmlinkage long xtensa_mmap2(unsigned long addr, unsigned long len,
-   			     unsigned long prot, unsigned long flags,
-			     unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
 {
 	unsigned long ret;
--- linux-ec2-2.6.32.orig/arch/xtensa/include/asm/unistd.h
+++ linux-ec2-2.6.32/arch/xtensa/include/asm/unistd.h
@@ -189,7 +189,7 @@
 /* File Map / Shared Memory Operations */
 
 #define __NR_mmap2 				 80
-__SYSCALL( 80, xtensa_mmap2, 6)
+__SYSCALL( 80, sys_mmap_pgoff, 6)
 #define __NR_munmap 				 81
 __SYSCALL( 81, sys_munmap, 2)
 #define __NR_mprotect 				 82
--- linux-ec2-2.6.32.orig/arch/xtensa/include/asm/cache.h
+++ linux-ec2-2.6.32/arch/xtensa/include/asm/cache.h
@@ -29,5 +29,6 @@
 # define CACHE_WAY_SIZE ICACHE_WAY_SIZE
 #endif
 
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
 
 #endif	/* _XTENSA_CACHE_H */
--- linux-ec2-2.6.32.orig/arch/xtensa/include/asm/syscall.h
+++ linux-ec2-2.6.32/arch/xtensa/include/asm/syscall.h
@@ -13,8 +13,6 @@
 asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_pipe(int __user *);
-asmlinkage long xtensa_mmap2(unsigned long, unsigned long, unsigned long,
-    			     unsigned long, unsigned long, unsigned long);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
--- linux-ec2-2.6.32.orig/arch/parisc/kernel/irq.c
+++ linux-ec2-2.6.32/arch/parisc/kernel/irq.c
@@ -117,7 +117,7 @@
 	int cpu_dest;
 
 	/* timer and ipi have to always be received on all CPUs */
-	if (CHECK_IRQ_PER_CPU(irq)) {
+	if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) {
 		/* Bad linux design decision.  The mask has already
 		 * been set; we must reset it */
 		cpumask_setall(irq_desc[irq].affinity);
--- linux-ec2-2.6.32.orig/arch/parisc/kernel/sys_parisc.c
+++ linux-ec2-2.6.32/arch/parisc/kernel/sys_parisc.c
@@ -110,37 +110,14 @@
 	return addr;
 }
 
-static unsigned long do_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags, unsigned long fd,
-	unsigned long pgoff)
-{
-	struct file * file = NULL;
-	unsigned long error = -EBADF;
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file != NULL)
-		fput(file);
-out:
-	return error;
-}
-
 asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
 	unsigned long pgoff)
 {
 	/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
 	   we have. */
-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      pgoff >> (PAGE_SHIFT - 12));
 }
 
 asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
@@ -148,7 +125,8 @@
 		unsigned long offset)
 {
 	if (!(offset & ~PAGE_MASK)) {
-		return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+		return sys_mmap_pgoff(addr, len, prot, flags, fd,
+					offset >> PAGE_SHIFT);
 	} else {
 		return -EINVAL;
 	}
--- linux-ec2-2.6.32.orig/arch/parisc/kernel/firmware.c
+++ linux-ec2-2.6.32/arch/parisc/kernel/firmware.c
@@ -1123,42 +1123,23 @@
  */
 int pdc_iodc_print(const unsigned char *str, unsigned count)
 {
-	static int posx;        /* for simple TAB-Simulation... */
 	unsigned int i;
 	unsigned long flags;
 
-	for (i = 0; i < count && i < 79;) {
+	for (i = 0; i < count;) {
 		switch(str[i]) {
 		case '\n':
 			iodc_dbuf[i+0] = '\r';
 			iodc_dbuf[i+1] = '\n';
 			i += 2;
-			posx = 0;
 			goto print;
-		case '\t':
-			while (posx & 7) {
-				iodc_dbuf[i] = ' ';
-				i++, posx++;
-			}
-			break;
-		case '\b':	/* BS */
-			posx -= 2;
 		default:
 			iodc_dbuf[i] = str[i];
-			i++, posx++;
+			i++;
 			break;
 		}
 	}
 
-	/* if we're at the end of line, and not already inserting a newline,
-	 * insert one anyway. iodc console doesn't claim to support >79 char
-	 * lines. don't account for this in the return value.
-	 */
-	if (i == 79 && iodc_dbuf[i-1] != '\n') {
-		iodc_dbuf[i+0] = '\r';
-		iodc_dbuf[i+1] = '\n';
-	}
-
 print:
         spin_lock_irqsave(&pdc_lock, flags);
         real32_call(PAGE0->mem_cons.iodc_io,
--- linux-ec2-2.6.32.orig/arch/parisc/math-emu/decode_exc.c
+++ linux-ec2-2.6.32/arch/parisc/math-emu/decode_exc.c
@@ -342,6 +342,7 @@
 		return SIGNALCODE(SIGFPE, FPE_FLTINV);
 	  case DIVISIONBYZEROEXCEPTION:
 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+		Clear_excp_register(exception_index);
 	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);
 	  case INEXACTEXCEPTION:
 		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
--- linux-ec2-2.6.32.orig/arch/parisc/mm/init.c
+++ linux-ec2-2.6.32/arch/parisc/mm/init.c
@@ -265,8 +265,10 @@
 	}
 	memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
-	for (i = 0; i < npmem_ranges; i++)
+	for (i = 0; i < npmem_ranges; i++) {
+		node_set_state(i, N_NORMAL_MEMORY);
 		node_set_online(i);
+	}
 #endif
 
 	/*
--- linux-ec2-2.6.32.orig/arch/parisc/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/parisc/include/asm/compat.h
@@ -146,7 +146,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static __inline__ void __user *compat_alloc_user_space(long len)
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = &current->thread.regs;
 	return (void __user *)regs->gr[30];
--- linux-ec2-2.6.32.orig/arch/x86/Kconfig.debug
+++ linux-ec2-2.6.32/arch/x86/Kconfig.debug
@@ -25,6 +25,7 @@
 config X86_VERBOSE_BOOTUP
 	bool "Enable verbose x86 bootup info messages"
 	default y
+	depends on !XEN
 	---help---
 	  Enables the informational output from the decompression stage
 	  (e.g. bzImage) of the boot. If you disable this you will still
@@ -136,7 +137,7 @@
 config DOUBLEFAULT
 	default y
 	bool "Enable doublefault exception handler" if EMBEDDED
-	depends on X86_32
+	depends on X86_32 && !X86_NO_TSS
 	---help---
 	  This option allows trapping of rare doublefault exceptions that
 	  would otherwise cause a system to silently reboot. Disabling this
@@ -185,6 +186,7 @@
 
 config HAVE_MMIOTRACE_SUPPORT
 	def_bool y
+	depends on !XEN
 
 #
 # IO delay types:
@@ -264,6 +266,7 @@
 	bool "Debug boot parameters"
 	depends on DEBUG_KERNEL
 	depends on DEBUG_FS
+	depends on !XEN
 	---help---
 	  This option will cause struct boot_params to be exported via debugfs.
 
--- linux-ec2-2.6.32.orig/arch/x86/Makefile
+++ linux-ec2-2.6.32/arch/x86/Makefile
@@ -146,8 +146,27 @@
 
 BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage
 
-PHONY += bzImage $(BOOT_TARGETS)
+PHONY += bzImage vmlinuz $(BOOT_TARGETS)
 
+ifdef CONFIG_XEN
+LINUXINCLUDE := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \
+	-I$(srctree)/arch/x86/include/mach-xen $(LINUXINCLUDE)
+
+ifdef CONFIG_X86_64
+LDFLAGS_vmlinux := -e startup_64
+endif
+
+# Default kernel to build
+all: vmlinuz
+
+# KBUILD_IMAGE specifies the target image being built
+KBUILD_IMAGE := $(boot)/vmlinuz
+
+vmlinuz: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
+	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
+	$(Q)ln -fsn ../../x86/boot/$@ $(objtree)/arch/$(UTS_MACHINE)/boot/$@
+else
 # Default kernel to build
 all: bzImage
 
@@ -158,6 +177,7 @@
 	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
 	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
 	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/$@
+endif
 
 $(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
--- linux-ec2-2.6.32.orig/arch/x86/Kconfig
+++ linux-ec2-2.6.32/arch/x86/Kconfig
@@ -24,7 +24,7 @@
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_IDE
 	select HAVE_OPROFILE
-	select HAVE_PERF_EVENTS if (!M386 && !M486)
+	select HAVE_PERF_EVENTS if (!M386 && !M486 && !XEN)
 	select HAVE_IOREMAP_PROT
 	select HAVE_KPROBES
 	select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -39,16 +39,16 @@
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
 	select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 	select HAVE_SYSCALL_TRACEPOINTS
-	select HAVE_KVM
-	select HAVE_ARCH_KGDB
+	select HAVE_KVM if !XEN
+	select HAVE_ARCH_KGDB if !XEN
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_GENERIC_DMA_COHERENT if X86_32
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select USER_STACKTRACE_SUPPORT
 	select HAVE_DMA_API_DEBUG
 	select HAVE_KERNEL_GZIP
-	select HAVE_KERNEL_BZIP2
-	select HAVE_KERNEL_LZMA
+	select HAVE_KERNEL_BZIP2 if !XEN
+	select HAVE_KERNEL_LZMA if !XEN
 	select HAVE_ARCH_KMEMCHECK
 
 config OUTPUT_FORMAT
@@ -69,13 +69,16 @@
 
 config CLOCKSOURCE_WATCHDOG
 	def_bool y
+	depends on !XEN
 
 config GENERIC_CLOCKEVENTS
 	def_bool y
+	depends on !XEN
 
 config GENERIC_CLOCKEVENTS_BROADCAST
 	def_bool y
 	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
+	depends on !XEN
 
 config LOCKDEP_SUPPORT
 	def_bool y
@@ -157,6 +160,7 @@
 
 config ARCH_HIBERNATION_POSSIBLE
 	def_bool y
+	depends on !XEN
 
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
@@ -213,20 +217,34 @@
 
 config X86_HT
 	bool
-	depends on SMP
+	depends on SMP && !XEN
 	default y
 
 config X86_TRAMPOLINE
 	bool
 	depends on SMP || (64BIT && ACPI_SLEEP)
+	depends on !XEN
 	default y
 
+config X86_NO_TSS
+	def_bool y
+	depends on XEN
+
+config X86_NO_IDT
+	def_bool y
+	depends on XEN
+
 config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
 
 config KTIME_SCALAR
 	def_bool X86_32
+
+config ARCH_CPU_PROBE_RELEASE
+	def_bool y
+	depends on HOTPLUG_CPU && !XEN
+
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
@@ -298,13 +316,25 @@
 	  For old smp systems that do not have proper acpi support. Newer systems
 	  (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
 
+config X86_XEN
+	bool "Xen-compatible"
+	depends on X86_32
+	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
+	help
+	  Choose this option if you plan to run this kernel on top of the
+	  Xen Hypervisor.
+
 config X86_BIGSMP
 	bool "Support for big SMP systems with more than 8 CPUs"
-	depends on X86_32 && SMP
+	depends on X86_32 && SMP && !XEN
 	---help---
 	  This option is needed for the systems that have more than 8 CPUs
 
-if X86_32
+if X86_32 && !XEN
 config X86_EXTENDED_PLATFORM
 	bool "Support for extended (non-PC) x86 platforms"
 	default y
@@ -327,7 +357,15 @@
 	  generic distribution kernel, say Y here - otherwise say N.
 endif
 
-if X86_64
+config X86_64_XEN
+	bool "Enable Xen compatible kernel"
+	depends on X86_64
+	select XEN
+	select SWIOTLB
+	help
+	  This option will compile a kernel compatible with Xen hypervisor
+
+if X86_64 && !XEN
 config X86_EXTENDED_PLATFORM
 	bool "Support for extended (non-PC) x86 platforms"
 	default y
@@ -370,6 +408,12 @@
 # Following is an alphabetically sorted list of 32 bit extended platforms
 # Please maintain the alphabetic order if and when there are additions
 
+config X86_LPIA
+	bool "LPIA-compatible"
+	depends on X86_32 && X86_PC
+	help
+	  Choose this option if your computer is an LPIA platform.
+
 config X86_ELAN
 	bool "AMD Elan"
 	depends on X86_32
@@ -480,6 +524,7 @@
 
 menuconfig PARAVIRT_GUEST
 	bool "Paravirtualized guest support"
+	depends on !XEN
 	---help---
 	  Say Y here to get to see options related to running Linux under
 	  various hypervisors.  This option alone does not add any kernel code.
@@ -565,6 +610,7 @@
 
 config MEMTEST
 	bool "Memtest"
+	depends on !XEN
 	---help---
 	  This option adds a kernel parameter 'memtest', which allows memtest
 	  to be set.
@@ -587,6 +633,7 @@
 config HPET_TIMER
 	def_bool X86_64
 	prompt "HPET Timer Support" if X86_32
+	depends on !XEN
 	---help---
 	  Use the IA-PC HPET (High Precision Event Timer) to manage
 	  time in preference to the PIT and RTC, if a HPET is
@@ -612,6 +659,7 @@
 config DMI
 	default y
 	bool "Enable DMI scanning" if EMBEDDED
+	depends on !XEN_UNPRIVILEGED_GUEST
 	---help---
 	  Enabled scanning of DMI to identify machine quirks. Say Y
 	  here unless you have verified that your setup is not
@@ -622,7 +670,7 @@
 	bool "GART IOMMU support" if EMBEDDED
 	default y
 	select SWIOTLB
-	depends on X86_64 && PCI
+	depends on X86_64 && PCI && K8_NB && !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,
@@ -637,7 +685,7 @@
 config CALGARY_IOMMU
 	bool "IBM Calgary IOMMU support"
 	select SWIOTLB
-	depends on X86_64 && PCI && EXPERIMENTAL
+	depends on X86_64 && 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
@@ -667,7 +715,7 @@
 	bool "AMD IOMMU support"
 	select SWIOTLB
 	select PCI_MSI
-	depends on X86_64 && PCI && ACPI
+	depends on X86_64 && PCI && ACPI && !XEN
 	---help---
 	  With this option you can enable support for AMD IOMMU hardware in
 	  your system. An IOMMU is a hardware component which provides
@@ -716,11 +764,12 @@
 
 config NR_CPUS
 	int "Maximum number of CPUs" if SMP && !MAXSMP
-	range 2 8 if SMP && X86_32 && !X86_BIGSMP
+	range 2 8 if SMP && X86_32 && !X86_BIGSMP && !X86_XEN
 	range 2 512 if SMP && !MAXSMP
 	default "1" if !SMP
 	default "4096" if MAXSMP
 	default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
+	default "16" if X86_64_XEN
 	default "8" if SMP
 	---help---
 	  This allows you to specify the maximum number of CPUs which this
@@ -748,11 +797,22 @@
 	  making when dealing with multi-core CPU chips at a cost of slightly
 	  increased overhead in some places. If unsure say N here.
 
+config IRQ_TIME_ACCOUNTING
+	bool "Fine granularity task level IRQ time accounting"
+	default n
+	---help---
+	  Select this option to enable fine granularity task irq time
+	  accounting. This is done by reading a timestamp on each
+	  transitions between softirq and hardirq state, so there can be a
+	  small performance impact.
+
+	  If in doubt, say N here.
+
 source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
 	bool "Local APIC support on uniprocessors"
-	depends on X86_32 && !SMP && !X86_32_NON_STANDARD
+	depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !XEN_UNPRIVILEGED_GUEST
 	---help---
 	  A local APIC (Advanced Programmable Interrupt Controller) is an
 	  integrated interrupt controller in the CPU. If you have a single-CPU
@@ -778,10 +838,12 @@
 config X86_LOCAL_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+	depends on !XEN_UNPRIVILEGED_GUEST
 
 config X86_IO_APIC
 	def_bool y
 	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+	depends on !XEN_UNPRIVILEGED_GUEST
 
 config X86_VISWS_APIC
 	def_bool y
@@ -790,7 +852,7 @@
 config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 	bool "Reroute for broken boot IRQs"
 	default n
-	depends on X86_IO_APIC
+	depends on X86_IO_APIC && !XEN
 	---help---
 	  This option enables a workaround that fixes a source of
 	  spurious interrupts. This is recommended when threaded
@@ -813,6 +875,7 @@
 
 config X86_MCE
 	bool "Machine Check / overheating reporting"
+	depends on !XEN_UNPRIVILEGED_GUEST
 	---help---
 	  Machine Check support allows the processor to notify the
 	  kernel if it detects a problem (e.g. overheating, data corruption).
@@ -822,22 +885,30 @@
 config X86_MCE_INTEL
 	def_bool y
 	prompt "Intel MCE features"
-	depends on X86_MCE && X86_LOCAL_APIC
+	depends on X86_MCE && X86_LOCAL_APIC && !XEN
 	---help---
 	   Additional support for intel specific MCE features such as
 	   the thermal monitor.
 
+config X86_MCE_XEON75XX
+	tristate "Intel Xeon 7500 series corrected memory error driver"
+	depends on X86_MCE_INTEL && PCI
+	---help---
+	   Add support for a Intel Xeon 7500 series specific memory error driver.
+	   This allows to report the DIMM and physical address on a corrected
+	   memory error machine check event.
+
 config X86_MCE_AMD
 	def_bool y
 	prompt "AMD MCE features"
-	depends on X86_MCE && X86_LOCAL_APIC
+	depends on X86_MCE && X86_LOCAL_APIC && !XEN
 	---help---
 	   Additional support for AMD specific MCE features such as
 	   the DRAM Error Threshold.
 
 config X86_ANCIENT_MCE
 	def_bool n
-	depends on X86_32 && X86_MCE
+	depends on X86_32 && X86_MCE && !XEN
 	prompt "Support for old Pentium 5 / WinChip machine checks"
 	---help---
 	  Include support for machine check handling on old Pentium 5 or WinChip
@@ -857,6 +928,10 @@
 	  If you don't know what a machine check is and you don't do kernel
 	  QA it is safe to say n.
 
+config X86_XEN_MCE
+	def_bool y
+	depends on XEN && X86_MCE
+
 config X86_THERMAL_VECTOR
 	def_bool y
 	depends on X86_MCE_INTEL
@@ -909,7 +984,7 @@
 
 config X86_REBOOTFIXUPS
 	bool "Enable X86 board specific fixups for reboot"
-	depends on X86_32
+	depends on X86_32 && !XEN
 	---help---
 	  This enables chipset and/or board specific fixups to be done
 	  in order to get reboot to work correctly. This is only needed on
@@ -926,6 +1001,7 @@
 
 config MICROCODE
 	tristate "/dev/cpu/microcode - microcode support"
+	depends on !XEN_UNPRIVILEGED_GUEST
 	select FW_LOADER
 	---help---
 	  If you say Y here, you will be able to update the microcode on
@@ -944,7 +1020,7 @@
 
 config MICROCODE_INTEL
 	bool "Intel microcode patch loading support"
-	depends on MICROCODE
+	depends on MICROCODE && !XEN
 	default MICROCODE
 	select FW_LOADER
 	---help---
@@ -957,7 +1033,7 @@
 
 config MICROCODE_AMD
 	bool "AMD microcode patch loading support"
-	depends on MICROCODE
+	depends on MICROCODE && !XEN
 	select FW_LOADER
 	---help---
 	  If you select this option, microcode patch loading support for AMD
@@ -984,12 +1060,6 @@
 	  with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
 	  /dev/cpu/31/cpuid.
 
-config X86_CPU_DEBUG
-	tristate "/sys/kernel/debug/x86/cpu/* - CPU Debug support"
-	---help---
-	  If you select this option, this will provide various x86 CPUs
-	  information through debugfs.
-
 choice
 	prompt "High Memory Support"
 	default HIGHMEM4G if !X86_NUMAQ
@@ -1113,7 +1183,7 @@
 config DIRECT_GBPAGES
 	bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
 	default y
-	depends on X86_64
+	depends on X86_64 && !XEN
 	---help---
 	  Allow the kernel linear mapping to use 1GB pages on CPUs that
 	  support it. This can improve the kernel's performance a tiny bit by
@@ -1122,7 +1192,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"
-	depends on SMP
+	depends on SMP && !XEN
 	depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
 	default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
 	---help---
@@ -1226,11 +1296,12 @@
 
 config ARCH_SPARSEMEM_DEFAULT
 	def_bool y
-	depends on X86_64
+	depends on X86_64 && !X86_64_XEN
 
 config ARCH_SPARSEMEM_ENABLE
 	def_bool y
 	depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD
+	depends on !XEN
 	select SPARSEMEM_STATIC if X86_32
 	select SPARSEMEM_VMEMMAP_ENABLE if X86_64
 
@@ -1242,6 +1313,11 @@
 	def_bool X86_64
 	depends on MEMORY_HOTPLUG
 
+config ILLEGAL_POINTER_VALUE
+       hex
+       default 0 if X86_32
+       default 0xdead000000000000 if X86_64
+
 source "mm/Kconfig"
 
 config HIGHPTE
@@ -1255,6 +1331,7 @@
 
 config X86_CHECK_BIOS_CORRUPTION
 	bool "Check for low memory corruption"
+	depends on !XEN
 	---help---
 	  Periodically check for memory corruption in low memory, which
 	  is suspected to be caused by BIOS.  Even when enabled in the
@@ -1285,6 +1362,7 @@
 
 config X86_RESERVE_LOW_64K
 	bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
+	depends on !XEN
 	default y
 	---help---
 	  Reserve the first 64K of physical RAM on BIOSes that are known
@@ -1306,6 +1384,7 @@
 config MATH_EMULATION
 	bool
 	prompt "Math emulation" if X86_32
+	depends on !XEN
 	---help---
 	  Linux can emulate a math coprocessor (used for floating point
 	  operations) if you don't have one. 486DX and Pentium processors have
@@ -1331,6 +1410,7 @@
 
 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
@@ -1366,7 +1446,7 @@
 config MTRR_SANITIZER
 	def_bool y
 	prompt "MTRR cleanup support"
-	depends on MTRR
+	depends on MTRR && !XEN
 	---help---
 	  Convert MTRR layout from continuous to discrete, so X drivers can
 	  add writeback entries.
@@ -1415,7 +1495,7 @@
 
 config EFI
 	bool "EFI runtime service support"
-	depends on ACPI
+	depends on ACPI && !XEN
 	---help---
 	  This enables the kernel to use EFI runtime services that are
 	  available (such as the EFI variable services).
@@ -1463,6 +1543,7 @@
 
 config KEXEC
 	bool "kexec system call"
+	depends on !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
@@ -1480,6 +1561,7 @@
 config CRASH_DUMP
 	bool "kernel crash dumps"
 	depends on X86_64 || (X86_32 && HIGHMEM)
+	depends on !XEN
 	---help---
 	  Generate crash dump after being started by kexec.
 	  This should be normally only set in special crash dump kernels
@@ -1500,7 +1582,8 @@
 	  code in physical address mode via KEXEC
 
 config PHYSICAL_START
-	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP || XEN)
+	default 0x100000 if XEN
 	default "0x1000000"
 	---help---
 	  This gives the physical address where the kernel is loaded.
@@ -1542,6 +1625,7 @@
 
 config RELOCATABLE
 	bool "Build a relocatable kernel"
+	depends on !XEN
 	default y
 	---help---
 	  This builds a kernel image that retains relocation information
@@ -1564,7 +1648,8 @@
 
 config PHYSICAL_ALIGN
 	hex
-	prompt "Alignment value to which kernel should be aligned" if X86_32
+	prompt "Alignment value to which kernel should be aligned" if X86_32 && !XEN
+	default 0x2000 if XEN
 	default "0x1000000"
 	range 0x2000 0x1000000
 	---help---
@@ -1659,6 +1744,7 @@
 config ARCH_ENABLE_MEMORY_HOTPLUG
 	def_bool y
 	depends on X86_64 || (X86_32 && HIGHMEM)
+	depends on !XEN
 
 config ARCH_ENABLE_MEMORY_HOTREMOVE
 	def_bool y
@@ -1669,6 +1755,7 @@
 	depends on NUMA
 
 menu "Power management and ACPI options"
+	depends on !XEN_UNPRIVILEGED_GUEST
 
 config ARCH_HIBERNATION_HEADER
 	def_bool y
@@ -1687,7 +1774,7 @@
 
 menuconfig APM
 	tristate "APM (Advanced Power Management) BIOS support"
-	depends on X86_32 && PM_SLEEP
+	depends on X86_32 && PM_SLEEP && !XEN
 	---help---
 	  APM is a BIOS specification for saving power using several different
 	  techniques. This is mostly useful for battery powered laptops with
@@ -1821,6 +1908,7 @@
 	bool "PCI support"
 	default y
 	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
+	select ARCH_SUPPORTS_MSI if (XEN_UNPRIVILEGED_GUEST && XEN_PCIDEV_FRONTEND)
 	---help---
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1848,6 +1936,7 @@
 
 config PCI_GOBIOS
 	bool "BIOS"
+	depends on !XEN
 
 config PCI_GOMMCONFIG
 	bool "MMConfig"
@@ -1859,6 +1948,13 @@
 	bool "OLPC"
 	depends on OLPC
 
+config PCI_GOXEN_FE
+	bool "Xen PCI Frontend"
+	depends on X86_XEN
+	help
+	  The PCI device frontend driver allows the kernel to import arbitrary
+	  PCI devices from a PCI backend to support PCI driver domains.
+
 config PCI_GOANY
 	bool "Any"
 
@@ -1866,7 +1962,7 @@
 
 config PCI_BIOS
 	def_bool y
-	depends on X86_32 && PCI && (PCI_GOBIOS || PCI_GOANY)
+	depends on X86_32 && PCI && !XEN && (PCI_GOBIOS || PCI_GOANY)
 
 # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
@@ -1889,9 +1985,24 @@
 	bool "Support mmconfig PCI config space access"
 	depends on X86_64 && PCI && ACPI
 
+config XEN_PCIDEV_FRONTEND
+	def_bool y
+	prompt "Xen PCI Frontend" if X86_64
+	depends on PCI && XEN && (PCI_GOXEN_FE || PCI_GOANY || X86_64)
+ 	select HOTPLUG
+	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
+	help
+	  Enables some debug statements within the PCI Frontend.
+
 config DMAR
 	bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
-	depends on PCI_MSI && ACPI && EXPERIMENTAL
+	depends on PCI_MSI && ACPI && !XEN && EXPERIMENTAL
 	help
 	  DMA remapping (DMAR) devices support enables independent address
 	  translations for Direct Memory Access (DMA) from devices.
@@ -1933,7 +2044,7 @@
 
 config INTR_REMAP
 	bool "Support for Interrupt Remapping (EXPERIMENTAL)"
-	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+	depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && !XEN && EXPERIMENTAL
 	---help---
 	  Supports Interrupt remapping for IO-APIC and MSI devices.
 	  To use x2apic mode in the CPU's which support x2APIC enhancements or
@@ -1951,6 +2062,7 @@
 
 config ISA
 	bool "ISA support"
+	depends on !XEN
 	---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
@@ -1978,6 +2090,7 @@
 
 config MCA
 	bool "MCA support"
+	depends on !XEN
 	---help---
 	  MicroChannel Architecture is found in some IBM PS/2 machines and
 	  laptops.  It is a bus system similar to PCI or ISA. See
@@ -2028,7 +2141,7 @@
 
 config K8_NB
 	def_bool y
-	depends on AGP_AMD64 || (X86_64 && (GART_IOMMU || (PCI && NUMA)))
+	depends on CPU_SUP_AMD && PCI
 
 source "drivers/pcmcia/Kconfig"
 
@@ -2079,7 +2192,11 @@
 
 source "drivers/Kconfig"
 
+source "ubuntu/Kconfig"
+
+if !XEN_UNPRIVILEGED_GUEST
 source "drivers/firmware/Kconfig"
+endif
 
 source "fs/Kconfig"
 
--- linux-ec2-2.6.32.orig/arch/x86/Kbuild
+++ linux-ec2-2.6.32/arch/x86/Kbuild
@@ -2,7 +2,7 @@
 obj-$(CONFIG_KVM) += kvm/
 
 # Xen paravirtualization support
-obj-$(CONFIG_XEN) += xen/
+obj-$(CONFIG_PARAVIRT_XEN) += xen/
 
 # lguest paravirtualization support
 obj-$(CONFIG_LGUEST_GUEST) += lguest/
--- linux-ec2-2.6.32.orig/arch/x86/Kconfig.cpu
+++ linux-ec2-2.6.32/arch/x86/Kconfig.cpu
@@ -323,7 +323,7 @@
 
 config X86_XADD
 	def_bool y
-	depends on X86_32 && !M386
+	depends on X86_64 || !M386
 
 config X86_PPRO_FENCE
 	bool "PentiumPro memory ordering errata workaround"
@@ -340,7 +340,7 @@
 
 config X86_F00F_BUG
 	def_bool y
-	depends on M586MMX || M586TSC || M586 || M486 || M386
+	depends on (M586MMX || M586TSC || M586 || M486 || M386) && !X86_NO_IDT
 
 config X86_WP_WORKS_OK
 	def_bool y
@@ -397,10 +397,11 @@
 config X86_TSC
 	def_bool y
 	depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) && !X86_NUMAQ) || X86_64
+	depends on !XEN
 
 config X86_CMPXCHG64
 	def_bool y
-	depends on !M386 && !M486
+	depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM
 
 # this should be set for all -march=.. options where the compiler
 # generates cmov.
@@ -496,7 +497,7 @@
 config CPU_SUP_UMC_32
 	default y
 	bool "Support UMC processors" if PROCESSOR_SELECT
-	depends on !64BIT
+	depends on !64BIT && !XEN
 	---help---
 	  This enables detection, tunings and quirks for UMC processors
 
@@ -509,13 +510,13 @@
 
 config X86_DS
 	def_bool X86_PTRACE_BTS
-	depends on X86_DEBUGCTLMSR
+	depends on X86_DEBUGCTLMSR && !XEN
 	select HAVE_HW_BRANCH_TRACER
 
 config X86_PTRACE_BTS
 	bool "Branch Trace Store"
 	default y
-	depends on X86_DEBUGCTLMSR
+	depends on X86_DEBUGCTLMSR && !XEN
 	depends on BROKEN
 	---help---
 	  This adds a ptrace interface to the hardware's branch trace store.
--- linux-ec2-2.6.32.orig/arch/x86/Makefile_32.cpu
+++ linux-ec2-2.6.32/arch/x86/Makefile_32.cpu
@@ -46,6 +46,13 @@
 # cpu entries
 cflags-$(CONFIG_X86_GENERIC) 	+= $(call tune,generic,$(call tune,i686))
 
+# Work around the pentium-mmx code generator madness of gcc4.4.x which
+# does stack alignment by generating horrible code _before_ the mcount
+# prologue (push %ebp, mov %esp, %ebp) which breaks the function graph
+# tracer assumptions. For i686, generic, core2 this is set by the
+# compiler anyway
+cflags-$(CONFIG_FUNCTION_GRAPH_TRACER) += $(call cc-option,-maccumulate-outgoing-args)
+
 # Bug fix for binutils: this option is required in order to keep
 # binutils from generating NOPL instructions against our will.
 ifneq ($(CONFIG_X86_P6_NOP),y)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/syscall_table_32.S
+++ linux-ec2-2.6.32/arch/x86/kernel/syscall_table_32.S
@@ -191,7 +191,7 @@
 	.long sys_ni_syscall	/* reserved for streams2 */
 	.long ptregs_vfork	/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap2
+	.long sys_mmap_pgoff
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64	/* 195 */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/msr.c
+++ linux-ec2-2.6.32/arch/x86/kernel/msr.c
@@ -251,7 +251,7 @@
 	int i, err = 0;
 	i = 0;
 
-	if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
+	if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) {
 		printk(KERN_ERR "msr: unable to get major %d for msr\n",
 		       MSR_MAJOR);
 		err = -EBUSY;
@@ -279,7 +279,7 @@
 		msr_device_destroy(i);
 	class_destroy(msr_class);
 out_chrdev:
-	unregister_chrdev(MSR_MAJOR, "cpu/msr");
+	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
 out:
 	return err;
 }
@@ -290,7 +290,7 @@
 	for_each_online_cpu(cpu)
 		msr_device_destroy(cpu);
 	class_destroy(msr_class);
-	unregister_chrdev(MSR_MAJOR, "cpu/msr");
+	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
 	unregister_hotcpu_notifier(&msr_class_cpu_notifier);
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/e820.c
+++ linux-ec2-2.6.32/arch/x86/kernel/e820.c
@@ -79,7 +79,7 @@
  * Note: this function only works correct if the e820 table is sorted and
  * not-overlapping, which is the case
  */
-int __init e820_all_mapped(u64 start, u64 end, unsigned type)
+int e820_all_mapped(u64 start, u64 end, unsigned type)
 {
 	int i;
 
@@ -106,6 +106,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(e820_all_mapped);
 
 /*
  * Add a memory region to the kernel e820 map.
@@ -1236,15 +1237,21 @@
 	if (!p)
 		return -EINVAL;
 
-#ifdef CONFIG_X86_32
 	if (!strcmp(p, "nopentium")) {
+#ifdef CONFIG_X86_32
 		setup_clear_cpu_cap(X86_FEATURE_PSE);
 		return 0;
-	}
+#else
+		printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+		return -EINVAL;
 #endif
+	}
 
 	userdef = 1;
 	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" param */
+	if (mem_size == 0)
+		return -EINVAL;
 	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head_64-xen.S
+++ linux-ec2-2.6.32/arch/x86/kernel/head_64-xen.S
@@ -0,0 +1,151 @@
+/*
+ *  linux/arch/x86_64/kernel/head.S -- start in 32bit and switch to 64bit
+ *
+ *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+ *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
+ *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
+ *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
+ *  Copyright (C) 2005 Eric Biederman <ebiederm@xmission.com>
+ *  Jun Nakajima <jun.nakajima@intel.com>
+ *    Modified for Xen                                
+ */
+
+
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <linux/init.h>
+#include <linux/elfnote.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/msr.h>
+#include <asm/cache.h>
+#include <asm/dwarf2.h>
+#include <asm/percpu.h>
+#include <xen/interface/elfnote.h>
+
+	__HEAD
+	.code64
+	.globl startup_64
+startup_64:
+	movq $(init_thread_union+THREAD_SIZE-8),%rsp
+
+	/* rsi is pointer to startup info structure.
+	   pass it to C */
+	movq %rsi,%rdi
+
+	/* Set up %gs.
+	 *
+	 * The base of %gs always points to the bottom of the irqstack
+	 * union.  If the stack protector canary is enabled, it is
+	 * located at %gs:40.  Note that, on SMP, the boot cpu uses
+	 * init data section till per cpu areas are set up.
+	 */
+	movl	$MSR_GS_BASE,%ecx
+	movq	$INIT_PER_CPU_VAR(irq_stack_union),%rax
+	movq    %rax,%rdx
+	shrq	$32,%rdx
+	wrmsr
+
+	pushq $0		# fake return address
+	jmp x86_64_start_kernel
+
+#define NEXT_PAGE(name) \
+	.balign	PAGE_SIZE; \
+	phys_##name = . - .head.text; \
+ENTRY(name)
+
+NEXT_PAGE(init_level4_pgt)
+	.fill	512,8,0
+
+NEXT_PAGE(level3_kernel_pgt)
+	.fill	512,8,0
+
+        /*
+         * This is used for vsyscall area mapping as we have a different
+         * level4 page table for user.
+         */
+NEXT_PAGE(level3_user_pgt)
+        .fill	512,8,0
+
+NEXT_PAGE(level2_fixmap_pgt)
+	.fill	512,8,0
+
+NEXT_PAGE(level1_fixmap_pgt)
+	.fill	512,8,0
+
+NEXT_PAGE(hypercall_page)
+	CFI_STARTPROC
+	.rept 0x1000 / 0x20
+	.skip 1 /* push %rcx */
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rcx,0
+	.skip 2 /* push %r11 */
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rcx,0
+	.skip 5 /* mov $#,%eax */
+	.skip 2 /* syscall */
+	.skip 2 /* pop %r11 */
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE r11
+	.skip 1 /* pop %rcx */
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE rcx
+	.align 0x20,0 /* ret */
+	.endr
+	CFI_ENDPROC
+
+#undef NEXT_PAGE
+
+	__PAGE_ALIGNED_BSS
+	.align PAGE_SIZE
+ENTRY(empty_zero_page)
+	.skip PAGE_SIZE
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+/*
+ * __xen_guest information
+ */
+.macro utoh value
+ i = 64
+ .rept 16
+  i = i - 4
+  .byte '0' + ((((\value) >> i) & 0xf) > 9) * ('0' - 'A' + 10) + (((\value) >> i) & 0xf)
+ .endr
+.endm
+
+.section __xen_guest
+	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
+	.ascii	",XEN_VER=xen-3.0"
+	.ascii	",VIRT_BASE=0x"
+		utoh __START_KERNEL_map
+	.ascii	",ELF_PADDR_OFFSET=0x"
+		utoh __START_KERNEL_map
+	.ascii	",VIRT_ENTRY=0x"
+		utoh (__START_KERNEL_map + __PHYSICAL_START)
+	.ascii	",HYPERCALL_PAGE=0x"
+		utoh (phys_hypercall_page >> PAGE_SHIFT)
+	.ascii  ",FEATURES=writable_page_tables"
+	.ascii		 "|writable_descriptor_tables"
+	.ascii		 "|auto_translated_physmap"
+	.ascii	         "|supervisor_mode_kernel"
+	.ascii	",LOADER=generic"
+	.byte	0
+#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
+	
+	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
+	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
+	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
+	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad __START_KERNEL_map)
+#if CONFIG_XEN_COMPAT <= 0x030002
+	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad __START_KERNEL_map)
+#else
+	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad 0)
+#endif
+	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad startup_64)
+	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad hypercall_page)
+	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad _PAGE_PRESENT, _PAGE_PRESENT)
+	ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M,       .quad VMEMMAP_START)
+	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)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pvclock.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pvclock.c
@@ -74,7 +74,8 @@
 static u64 pvclock_get_nsec_offset(struct pvclock_shadow_time *shadow)
 {
 	u64 delta = native_read_tsc() - shadow->tsc_timestamp;
-	return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
+	return pvclock_scale_delta(delta, shadow->tsc_to_nsec_mul,
+				   shadow->tsc_shift);
 }
 
 /*
@@ -109,11 +110,19 @@
 	return pv_tsc_khz;
 }
 
+static atomic64_t last_value = ATOMIC64_INIT(0);
+
+void pvclock_resume(void)
+{
+	atomic64_set(&last_value, 0);
+}
+
 cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
 	struct pvclock_shadow_time shadow;
 	unsigned version;
 	cycle_t ret, offset;
+	u64 last;
 
 	do {
 		version = pvclock_get_time_values(&shadow, src);
@@ -123,6 +132,27 @@
 		barrier();
 	} while (version != src->version);
 
+	/*
+	 * Assumption here is that last_value, a global accumulator, always goes
+	 * forward. If we are less than that, we should not be much smaller.
+	 * We assume there is an error marging we're inside, and then the correction
+	 * does not sacrifice accuracy.
+	 *
+	 * For reads: global may have changed between test and return,
+	 * but this means someone else updated poked the clock at a later time.
+	 * We just need to make sure we are not seeing a backwards event.
+	 *
+	 * For updates: last_value = ret is not enough, since two vcpus could be
+	 * updating at the same time, and one of them could be slightly behind,
+	 * making the assumption that last_value always go forward fail to hold.
+	 */
+	last = atomic64_read(&last_value);
+	do {
+		if (ret < last)
+			return last;
+		last = atomic64_cmpxchg(&last_value, last, ret);
+	} while (unlikely(last != ret));
+
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/irq-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/irq-xen.c
@@ -0,0 +1,290 @@
+/*
+ * Common interrupt code for 32 and 64 bit
+ */
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
+#include <linux/smp.h>
+#include <linux/ftrace.h>
+
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/irq.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/hw_irq.h>
+
+#ifndef CONFIG_XEN
+atomic_t irq_err_count;
+#endif
+
+/* Function pointer for generic interrupt vector handling */
+void (*generic_interrupt_extension)(void) = NULL;
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+	if (printk_ratelimit())
+		pr_err("unexpected IRQ trap at vector %02x\n", irq);
+
+#ifndef CONFIG_XEN
+	/*
+	 * Currently unexpected vectors happen only on SMP and APIC.
+	 * We _must_ ack these because every local APIC has only N
+	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+	 * holds up an irq slot - in excessive cases (when multiple
+	 * unexpected vectors occur) that might lock up the APIC
+	 * completely.
+	 * But only ack when the APIC is enabled -AK
+	 */
+	ack_APIC_irq();
+#endif
+}
+
+#define irq_stats(x)		(&per_cpu(irq_stat, x))
+/*
+ * /proc/interrupts printing:
+ */
+static int show_other_interrupts(struct seq_file *p, int prec)
+{
+	int j;
+
+	seq_printf(p, "%*s: ", prec, "NMI");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
+	seq_printf(p, "  Non-maskable interrupts\n");
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+	seq_printf(p, "%*s: ", prec, "LOC");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
+	seq_printf(p, "  Local timer interrupts\n");
+
+	seq_printf(p, "%*s: ", prec, "SPU");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
+	seq_printf(p, "  Spurious interrupts\n");
+	seq_printf(p, "%*s: ", prec, "PMI");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
+	seq_printf(p, "  Performance monitoring interrupts\n");
+	seq_printf(p, "%*s: ", prec, "PND");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
+	seq_printf(p, "  Performance pending work\n");
+#endif
+	if (generic_interrupt_extension) {
+		seq_printf(p, "%*s: ", prec, "PLT");
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
+		seq_printf(p, "  Platform interrupts\n");
+	}
+#ifdef CONFIG_SMP
+	seq_printf(p, "%*s: ", prec, "RES");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
+	seq_printf(p, "  Rescheduling interrupts\n");
+	seq_printf(p, "%*s: ", prec, "CAL");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
+	seq_printf(p, "  Function call interrupts\n");
+#ifndef CONFIG_XEN
+	seq_printf(p, "%*s: ", prec, "TLB");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
+	seq_printf(p, "  TLB shootdowns\n");
+#endif
+#endif
+#ifdef CONFIG_X86_THERMAL_VECTOR
+	seq_printf(p, "%*s: ", prec, "TRM");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
+	seq_printf(p, "  Thermal event interrupts\n");
+#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
+	seq_printf(p, "%*s: ", prec, "THR");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
+	seq_printf(p, "  Threshold APIC interrupts\n");
+#endif
+#ifdef CONFIG_X86_MCE
+	seq_printf(p, "%*s: ", prec, "MCE");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
+	seq_printf(p, "  Machine check exceptions\n");
+	seq_printf(p, "%*s: ", prec, "MCP");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
+	seq_printf(p, "  Machine check polls\n");
+#endif
+#ifndef CONFIG_XEN
+	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+#if defined(CONFIG_X86_IO_APIC)
+	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
+#endif
+#endif
+	return 0;
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	unsigned long flags, any_count = 0;
+	int i = *(loff_t *) v, j, prec;
+	struct irqaction *action;
+	struct irq_desc *desc;
+
+	if (i > nr_irqs)
+		return 0;
+
+	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
+		j *= 10;
+
+	if (i == nr_irqs)
+		return show_other_interrupts(p, prec);
+
+	/* print header */
+	if (i == 0) {
+		seq_printf(p, "%*s", prec + 8, "");
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%-8d", j);
+		seq_putc(p, '\n');
+	}
+
+	desc = irq_to_desc(i);
+	if (!desc)
+		return 0;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	for_each_online_cpu(j)
+		any_count |= kstat_irqs_cpu(i, j);
+	action = desc->action;
+	if (!action && !any_count)
+		goto out;
+
+	seq_printf(p, "%*d: ", prec, i);
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+	seq_printf(p, " %8s", desc->chip->name);
+	seq_printf(p, "-%-8s", desc->name);
+
+	if (action) {
+		seq_printf(p, "  %s", action->name);
+		while ((action = action->next) != NULL)
+			seq_printf(p, ", %s", action->name);
+	}
+
+	seq_putc(p, '\n');
+out:
+	spin_unlock_irqrestore(&desc->lock, flags);
+	return 0;
+}
+
+/*
+ * /proc/stat helpers
+ */
+u64 arch_irq_stat_cpu(unsigned int cpu)
+{
+	u64 sum = irq_stats(cpu)->__nmi_count;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	sum += irq_stats(cpu)->apic_timer_irqs;
+	sum += irq_stats(cpu)->irq_spurious_count;
+	sum += irq_stats(cpu)->apic_perf_irqs;
+	sum += irq_stats(cpu)->apic_pending_irqs;
+#endif
+	if (generic_interrupt_extension)
+		sum += irq_stats(cpu)->generic_irqs;
+#ifdef CONFIG_SMP
+	sum += irq_stats(cpu)->irq_resched_count;
+	sum += irq_stats(cpu)->irq_call_count;
+#ifndef CONFIG_XEN
+	sum += irq_stats(cpu)->irq_tlb_count;
+#endif
+#endif
+#ifdef CONFIG_X86_THERMAL_VECTOR
+	sum += irq_stats(cpu)->irq_thermal_count;
+#endif
+#ifdef CONFIG_X86_MCE_THRESHOLD
+	sum += irq_stats(cpu)->irq_threshold_count;
+#endif
+#ifdef CONFIG_X86_MCE
+	sum += per_cpu(mce_exception_count, cpu);
+	sum += per_cpu(mce_poll_count, cpu);
+#endif
+	return sum;
+}
+
+u64 arch_irq_stat(void)
+{
+#ifndef CONFIG_XEN
+	u64 sum = atomic_read(&irq_err_count);
+
+#ifdef CONFIG_X86_IO_APIC
+	sum += atomic_read(&irq_mis_count);
+#endif
+	return sum;
+#else
+	return 0;
+#endif
+}
+
+
+#ifndef CONFIG_XEN
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	/* high bit used in ret_from_ code  */
+	unsigned vector = ~regs->orig_ax;
+	unsigned irq;
+
+	exit_idle();
+	irq_enter();
+
+	irq = __get_cpu_var(vector_irq)[vector];
+
+	if (!handle_irq(irq, regs)) {
+		ack_APIC_irq();
+
+		if (printk_ratelimit())
+			pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
+				__func__, smp_processor_id(), vector, irq);
+	}
+
+	irq_exit();
+
+	set_irq_regs(old_regs);
+	return 1;
+}
+
+/*
+ * Handler for GENERIC_INTERRUPT_VECTOR.
+ */
+void smp_generic_interrupt(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	ack_APIC_irq();
+
+	exit_idle();
+
+	irq_enter();
+
+	inc_irq_stat(generic_irqs);
+
+	if (generic_interrupt_extension)
+		generic_interrupt_extension();
+
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pci-calgary_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pci-calgary_64.c
@@ -102,11 +102,16 @@
 #define PMR_SOFTSTOPFAULT	0x40000000
 #define PMR_HARDSTOP		0x20000000
 
-#define MAX_NUM_OF_PHBS		8 /* how many PHBs in total? */
-#define MAX_NUM_CHASSIS		8 /* max number of chassis */
-/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
-#define MAX_PHB_BUS_NUM		(MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
-#define PHBS_PER_CALGARY	4
+/*
+ * The maximum PHB bus number.
+ * x3950M2 (rare): 8 chassis, 48 PHBs per chassis = 384
+ * x3950M2: 4 chassis, 48 PHBs per chassis        = 192
+ * x3950 (PCIE): 8 chassis, 32 PHBs per chassis   = 256
+ * x3950 (PCIX): 8 chassis, 16 PHBs per chassis   = 128
+ */
+#define MAX_PHB_BUS_NUM		256
+
+#define PHBS_PER_CALGARY	  4
 
 /* register offsets in Calgary's internal register space */
 static const unsigned long tar_offsets[] = {
@@ -318,13 +323,15 @@
 
 	pdev = to_pci_dev(dev);
 
+	/* search up the device tree for an iommu */
 	pbus = pdev->bus;
-
-	/* is the device behind a bridge? Look for the root bus */
-	while (pbus->parent)
+	do {
+		tbl = pci_iommu(pbus);
+		if (tbl && tbl->it_busno == pbus->number)
+			break;
+		tbl = NULL;
 		pbus = pbus->parent;
-
-	tbl = pci_iommu(pbus);
+	} while (pbus);
 
 	BUG_ON(tbl && (tbl->it_busno != pbus->number));
 
@@ -1051,8 +1058,6 @@
 	struct iommu_table *tbl;
 	int ret;
 
-	BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM);
-
 	bbar = busno_to_bbar(dev->bus->number);
 	ret = calgary_setup_tar(dev, bbar);
 	if (ret)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/asm-offsets_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/asm-offsets_64.c
@@ -115,8 +115,10 @@
 	ENTRY(cr8);
 	BLANK();
 #undef ENTRY
+#ifndef CONFIG_X86_NO_TSS
 	DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
 	BLANK();
+#endif
 	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
 	BLANK();
 	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
@@ -130,7 +132,7 @@
 
 	BLANK();
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 	BLANK();
 	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
 	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process_64.c
@@ -295,11 +295,10 @@
 
 	set_tsk_thread_flag(p, TIF_FORK);
 
-	p->thread.fs = me->thread.fs;
-	p->thread.gs = me->thread.gs;
-
 	savesegment(gs, p->thread.gsindex);
+	p->thread.gs = p->thread.gsindex ? 0 : me->thread.gs;
 	savesegment(fs, p->thread.fsindex);
+	p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
 	savesegment(es, p->thread.es);
 	savesegment(ds, p->thread.ds);
 
@@ -540,6 +539,18 @@
 	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
+void set_personality_ia32(void)
+{
+	/* inherit personality from parent */
+
+	/* Make sure to be in 32bit mode */
+	set_thread_flag(TIF_IA32);
+	current->personality |= force_personality32;
+
+	/* Prepare the first "return" to user space */
+	current_thread_info()->status |= TS_COMPAT;
+}
+
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long stack;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/hpet.c
+++ linux-ec2-2.6.32/arch/x86/kernel/hpet.c
@@ -33,6 +33,8 @@
  * HPET address is set in acpi/boot.c, when an ACPI entry exists
  */
 unsigned long				hpet_address;
+u8					hpet_msi_disable;
+
 #ifdef CONFIG_PCI_MSI
 static unsigned long			hpet_num_timers;
 #endif
@@ -383,11 +385,28 @@
 	hpet_writel(cnt, HPET_Tn_CMP(timer));
 
 	/*
-	 * We need to read back the CMP register to make sure that
-	 * what we wrote hit the chip before we compare it to the
-	 * counter.
+	 * We need to read back the CMP register on certain HPET
+	 * implementations (ATI chipsets) which seem to delay the
+	 * transfer of the compare register into the internal compare
+	 * logic. With small deltas this might actually be too late as
+	 * the counter could already be higher than the compare value
+	 * at that point and we would wait for the next hpet interrupt
+	 * forever. We found out that reading the CMP register back
+	 * forces the transfer so we can rely on the comparison with
+	 * the counter register below. If the read back from the
+	 * compare register does not match the value we programmed
+	 * then we might have a real hardware problem. We can not do
+	 * much about it here, but at least alert the user/admin with
+	 * a prominent warning.
+	 * An erratum on some chipsets (ICH9,..), results in comparator read
+	 * immediately following a write returning old value. Workaround
+	 * for this is to read this value second time, when first
+	 * read returns old value.
 	 */
-	WARN_ON_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt);
+	if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {
+		WARN_ONCE((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt,
+		  KERN_WARNING "hpet: compare register read back failed.\n");
+	}
 
 	return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
 }
@@ -478,7 +497,7 @@
 {
 	unsigned int irq;
 
-	irq = create_irq();
+	irq = create_irq_nr(0, -1);
 	if (!irq)
 		return -EINVAL;
 
@@ -584,6 +603,11 @@
 	unsigned int num_timers_used = 0;
 	int i;
 
+	if (hpet_msi_disable)
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_ARAT))
+		return;
 	id = hpet_readl(HPET_ID);
 
 	num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
@@ -872,10 +896,8 @@
 
 	if (id & HPET_ID_LEGSUP) {
 		hpet_legacy_clockevent_register();
-		hpet_msi_capability_lookup(2);
 		return 1;
 	}
-	hpet_msi_capability_lookup(0);
 	return 0;
 
 out_nohpet:
@@ -908,9 +930,20 @@
 	if (!hpet_virt_address)
 		return -ENODEV;
 
+	if (hpet_readl(HPET_ID) & HPET_ID_LEGSUP)
+		hpet_msi_capability_lookup(2);
+	else
+		hpet_msi_capability_lookup(0);
+
 	hpet_reserve_platform_timers(hpet_readl(HPET_ID));
 	hpet_print_config();
 
+	if (hpet_msi_disable)
+		return 0;
+
+	if (boot_cpu_has(X86_FEATURE_ARAT))
+		return 0;
+
 	for_each_online_cpu(cpu) {
 		hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu);
 	}
@@ -924,7 +957,7 @@
 
 void hpet_disable(void)
 {
-	if (is_hpet_capable()) {
+	if (is_hpet_capable() && hpet_virt_address) {
 		unsigned long cfg = hpet_readl(HPET_CFG);
 
 		if (hpet_legacy_int_enabled) {
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pci-nommu-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pci-nommu-xen.c
@@ -0,0 +1,117 @@
+#include <linux/dma-mapping.h>
+#include <linux/dmar.h>
+#include <linux/bootmem.h>
+#include <linux/pci.h>
+
+#include <xen/gnttab.h>
+
+#include <asm/iommu.h>
+#include <asm/proto.h>
+#include <asm/dma.h>
+#include <asm/swiotlb.h>
+#include <asm/tlbflush.h>
+#include <asm/gnttab_dma.h>
+#include <asm/bug.h>
+
+#define IOMMU_BUG_ON(test)				\
+do {							\
+	if (unlikely(test)) {				\
+		printk(KERN_ALERT "Fatal DMA error! "	\
+		       "Please use 'swiotlb=force'\n");	\
+		BUG();					\
+	}						\
+} while (0)
+
+static int
+gnttab_map_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+	      enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+
+	WARN_ON(nents == 0 || sgl->length == 0);
+
+	for_each_sg(sgl, sg, nents, i) {
+		BUG_ON(!sg_page(sg));
+		sg->dma_address =
+			gnttab_dma_map_page(sg_page(sg)) + sg->offset;
+		sg->dma_length  = sg->length;
+		IOMMU_BUG_ON(!dma_capable(
+			hwdev, sg->dma_address, sg->length));
+		IOMMU_BUG_ON(range_straddles_page_boundary(
+			page_to_pseudophys(sg_page(sg)) + sg->offset,
+			sg->length));
+	}
+
+	return nents;
+}
+
+static void
+gnttab_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nents,
+		enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	unsigned int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, nents, i)
+		gnttab_dma_unmap_page(sg->dma_address);
+}
+
+static dma_addr_t
+gnttab_map_page(struct device *dev, struct page *page, unsigned long offset,
+		size_t size, enum dma_data_direction dir,
+		struct dma_attrs *attrs)
+{
+	dma_addr_t dma;
+
+	WARN_ON(size == 0);
+
+	dma = gnttab_dma_map_page(page) + offset;
+	IOMMU_BUG_ON(range_straddles_page_boundary(offset, size));
+	IOMMU_BUG_ON(!dma_capable(dev, dma, size));
+
+	return dma;
+}
+
+static void
+gnttab_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+		  enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	gnttab_dma_unmap_page(dma_addr);
+}
+
+static void nommu_sync_single_for_device(struct device *dev,
+			dma_addr_t addr, size_t size,
+			enum dma_data_direction dir)
+{
+	flush_write_buffers();
+}
+
+
+static void nommu_sync_sg_for_device(struct device *dev,
+			struct scatterlist *sg, int nelems,
+			enum dma_data_direction dir)
+{
+	flush_write_buffers();
+}
+
+struct dma_map_ops nommu_dma_ops = {
+	.alloc_coherent		= dma_generic_alloc_coherent,
+	.free_coherent		= dma_generic_free_coherent,
+	.map_page		= gnttab_map_page,
+	.unmap_page		= gnttab_unmap_page,
+	.map_sg			= gnttab_map_sg,
+	.unmap_sg		= gnttab_unmap_sg,
+	.sync_single_for_device = nommu_sync_single_for_device,
+	.sync_sg_for_device	= nommu_sync_sg_for_device,
+	.dma_supported		= swiotlb_dma_supported,
+};
+
+void __init no_iommu_init(void)
+{
+	if (dma_ops)
+		return;
+
+	force_iommu = 0; /* no HW IOMMU */
+	dma_ops = &nommu_dma_ops;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/microcode_core-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/microcode_core-xen.c
@@ -0,0 +1,224 @@
+/*
+ *	Intel CPU Microcode Update Driver for Linux
+ *
+ *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ *		      2006	Shaohua Li <shaohua.li@intel.com>
+ *
+ *	This driver allows to upgrade microcode on Intel processors
+ *	belonging to IA-32 family - PentiumPro, Pentium II,
+ *	Pentium III, Xeon, Pentium 4, etc.
+ *
+ *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ *	Software Developer's Manual
+ *	Order Number 253668 or free download from:
+ *
+ *	http://developer.intel.com/design/pentium4/manuals/253668.htm
+ *
+ *	For more information, go to http://www.urbanmyth.org/microcode
+ *
+ *	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.
+ */
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/capability.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/firmware.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+#include <asm/microcode.h>
+#include <asm/processor.h>
+
+MODULE_DESCRIPTION("Microcode Update Driver");
+MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+MODULE_LICENSE("GPL");
+
+static int verbose;
+module_param(verbose, int, 0644);
+
+#define MICROCODE_VERSION	"2.00-xen"
+
+/*
+ * Synchronization.
+ *
+ * All non cpu-hotplug-callback call sites use:
+ *
+ * - microcode_mutex to synchronize with each other;
+ * - get/put_online_cpus() to synchronize with
+ *   the cpu-hotplug-callback call sites.
+ *
+ * We guarantee that only a single cpu is being
+ * updated at any particular moment of time.
+ */
+static DEFINE_MUTEX(microcode_mutex);
+
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+static int do_microcode_update(const void __user *ubuf, size_t len)
+{
+	int err;
+	void *kbuf;
+
+	kbuf = vmalloc(len);
+	if (!kbuf)
+		return -ENOMEM;
+
+	if (copy_from_user(kbuf, ubuf, len) == 0) {
+		struct xen_platform_op op;
+
+		op.cmd = XENPF_microcode_update;
+		set_xen_guest_handle(op.u.microcode.data, kbuf);
+		op.u.microcode.length = len;
+		err = HYPERVISOR_platform_op(&op);
+	} else
+		err = -EFAULT;
+
+	vfree(kbuf);
+
+	return err;
+}
+
+static int microcode_open(struct inode *unused1, struct file *unused2)
+{
+	cycle_kernel_lock();
+	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+static ssize_t microcode_write(struct file *file, const char __user *buf,
+			       size_t len, loff_t *ppos)
+{
+	ssize_t ret = -EINVAL;
+
+	if ((len >> PAGE_SHIFT) > totalram_pages) {
+		pr_err("microcode: too much data (max %ld pages)\n", totalram_pages);
+		return ret;
+ 	}
+
+	mutex_lock(&microcode_mutex);
+
+	if (do_microcode_update(buf, len) == 0)
+		ret = (ssize_t)len;
+
+	mutex_unlock(&microcode_mutex);
+
+	return ret;
+}
+
+static const struct file_operations microcode_fops = {
+	.owner			= THIS_MODULE,
+	.write			= microcode_write,
+	.open			= microcode_open,
+};
+
+static struct miscdevice microcode_dev = {
+	.minor			= MICROCODE_MINOR,
+	.name			= "microcode",
+	.nodename		= "cpu/microcode",
+	.fops			= &microcode_fops,
+};
+
+static int __init microcode_dev_init(void)
+{
+	int error;
+
+	error = misc_register(&microcode_dev);
+	if (error) {
+		pr_err("microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR);
+		return error;
+	}
+
+	return 0;
+}
+
+static void microcode_dev_exit(void)
+{
+	misc_deregister(&microcode_dev);
+}
+
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+#else
+#define microcode_dev_init()	0
+#define microcode_dev_exit()	do { } while (0)
+#endif
+
+/* fake device for request_firmware */
+static struct platform_device	*microcode_pdev;
+
+static int request_microcode(const char *name)
+{
+	const struct firmware *firmware;
+	int error;
+	struct xen_platform_op op;
+
+	error = request_firmware(&firmware, name, &microcode_pdev->dev);
+	if (error) {
+		pr_debug("microcode: data file %s load failed\n", name);
+		return error;
+	}
+
+	op.cmd = XENPF_microcode_update;
+	set_xen_guest_handle(op.u.microcode.data, firmware->data);
+	op.u.microcode.length = firmware->size;
+	error = HYPERVISOR_platform_op(&op);
+
+	release_firmware(firmware);
+
+	if (error)
+		pr_debug("ucode load failed\n");
+
+	return error;
+}
+
+static int __init microcode_init(void)
+{
+	const struct cpuinfo_x86 *c = &boot_cpu_data;
+	char buf[32];
+	const char *fw_name = buf;
+	int error;
+
+	if (c->x86_vendor == X86_VENDOR_INTEL)
+		sprintf(buf, "intel-ucode/%02x-%02x-%02x",
+			c->x86, c->x86_model, c->x86_mask);
+	else if (c->x86_vendor == X86_VENDOR_AMD)
+		fw_name = "amd-ucode/microcode_amd.bin";
+	else {
+		pr_err("microcode: no support for this CPU vendor\n");
+		return -ENODEV;
+	}
+
+	microcode_pdev = platform_device_register_simple("microcode", -1,
+							 NULL, 0);
+	if (IS_ERR(microcode_pdev)) {
+		return PTR_ERR(microcode_pdev);
+	}
+
+	error = microcode_dev_init();
+	if (error)
+		return error;
+
+	request_microcode(fw_name);
+
+	pr_info("Microcode Update Driver: v" MICROCODE_VERSION
+	       " <tigran@aivazian.fsnet.co.uk>,"
+	       " Peter Oruba\n");
+
+	return 0;
+}
+module_init(microcode_init);
+
+static void __exit microcode_exit(void)
+{
+	microcode_dev_exit();
+	platform_device_unregister(microcode_pdev);
+
+	pr_info("Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
+}
+module_exit(microcode_exit);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/sfi.c
+++ linux-ec2-2.6.32/arch/x86/kernel/sfi.c
@@ -31,7 +31,7 @@
 #include <asm/setup.h>
 #include <asm/apic.h>
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 
 void __init mp_sfi_register_lapic_address(unsigned long address)
@@ -99,9 +99,12 @@
 		pentry++;
 	}
 
+#ifndef CONFIG_XEN
 	WARN(pic_mode, KERN_WARNING
 		"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n");
 	pic_mode = 0;
+#endif
+
 	return 0;
 }
 #endif /* CONFIG_X86_IO_APIC */
@@ -111,7 +114,7 @@
  */
 int __init sfi_platform_init(void)
 {
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 	mp_sfi_register_lapic_address(sfi_lapic_addr);
 	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus);
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/reboot.c
+++ linux-ec2-2.6.32/arch/x86/kernel/reboot.c
@@ -203,6 +203,15 @@
 			DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G*/
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 760",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
+			DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
+		},
+	},
 	{	/* Handle problems with rebooting on Dell 2400's */
 		.callback = set_bios_reboot,
 		.ident = "Dell PowerEdge 2400",
@@ -259,6 +268,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
 		},
 	},
+	{       /* Handle problems with rebooting on ASUS P4S800 */
+		.callback = set_bios_reboot,
+		.ident = "ASUS P4S800",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
+		},
+	},
 	{ }
 };
 
@@ -444,6 +461,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
 		},
 	},
+	{	/* Handle problems with rebooting on the iMac9,1. */
+		.callback = set_pci_reboot,
+		.ident = "Apple iMac9,1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
+		},
+	},
 	{ }
 };
 
@@ -608,7 +633,7 @@
 	/* O.K Now that I'm on the appropriate processor,
 	 * stop all of the others.
 	 */
-	smp_send_stop();
+	stop_other_cpus();
 #endif
 
 	lapic_shutdown();
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pci-dma.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pci-dma.c
@@ -214,7 +214,7 @@
 		if (!strncmp(p, "allowdac", 8))
 			forbid_dac = 0;
 		if (!strncmp(p, "nodac", 5))
-			forbid_dac = -1;
+			forbid_dac = 1;
 		if (!strncmp(p, "usedac", 6)) {
 			forbid_dac = -1;
 			return 1;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/sys_x86_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/sys_x86_64.c
@@ -23,26 +23,11 @@
 		unsigned long, fd, unsigned long, off)
 {
 	long error;
-	struct file *file;
-
 	error = -EINVAL;
 	if (off & ~PAGE_MASK)
 		goto out;
 
-	error = -EBADF;
-	file = NULL;
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
+	error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 out:
 	return error;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/setup-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/setup-xen.c
@@ -0,0 +1,1384 @@
+/*
+ *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *
+ *  Memory region support
+ *	David Parsons <orc@pell.chi.il.us>, July-August 1999
+ *
+ *  Added E820 sanitization routine (removes overlapping memory regions);
+ *  Brian Moyle <bmoyle@mvista.com>, February 2001
+ *
+ * Moved CPU detection code to cpu/${cpu}.c
+ *    Patrick Mochel <mochel@osdl.org>, March 2002
+ *
+ *  Provisions for empty E820 memory regions (reported by certain BIOSes).
+ *  Alex Achenbach <xela@slit.de>, December 2002.
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/screen_info.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
+#include <linux/sfi.h>
+#include <linux/apm_bios.h>
+#include <linux/initrd.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/console.h>
+#include <linux/mca.h>
+#include <linux/root_dev.h>
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/edd.h>
+#include <linux/iscsi_ibft.h>
+#include <linux/nodemask.h>
+#include <linux/kexec.h>
+#include <linux/dmi.h>
+#include <linux/pfn.h>
+#include <linux/pci.h>
+#include <asm/pci-direct.h>
+#include <linux/init_ohci1394_dma.h>
+#include <linux/kvm_para.h>
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/delay.h>
+
+#include <linux/kallsyms.h>
+#include <linux/cpufreq.h>
+#include <linux/dma-mapping.h>
+#include <linux/ctype.h>
+#include <linux/uaccess.h>
+
+#include <linux/percpu.h>
+#include <linux/crash_dump.h>
+#include <linux/tboot.h>
+
+#include <video/edid.h>
+
+#include <asm/mtrr.h>
+#include <asm/apic.h>
+#include <asm/e820.h>
+#include <asm/mpspec.h>
+#include <asm/setup.h>
+#include <asm/efi.h>
+#include <asm/timer.h>
+#include <asm/i8259.h>
+#include <asm/sections.h>
+#include <asm/dmi.h>
+#include <asm/io_apic.h>
+#include <asm/ist.h>
+#include <asm/vmi.h>
+#include <asm/setup_arch.h>
+#include <asm/bios_ebda.h>
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/bugs.h>
+
+#include <asm/system.h>
+#include <asm/vsyscall.h>
+#include <asm/cpu.h>
+#include <asm/desc.h>
+#include <asm/dma.h>
+#include <asm/iommu.h>
+#include <asm/gart.h>
+#include <asm/mmu_context.h>
+#include <asm/proto.h>
+
+#include <asm/paravirt.h>
+#include <asm/hypervisor.h>
+
+#include <asm/percpu.h>
+#include <asm/topology.h>
+#include <asm/apicdef.h>
+#ifdef CONFIG_X86_64
+#include <asm/numa_64.h>
+#endif
+
+#ifdef CONFIG_XEN
+#include <asm/hypervisor.h>
+#include <xen/interface/kexec.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/nmi.h>
+#include <xen/interface/physdev.h>
+#include <xen/features.h>
+#include <xen/firmware.h>
+#include <xen/xencons.h>
+
+static int xen_panic_event(struct notifier_block *, unsigned long, void *);
+static struct notifier_block xen_panic_block = {
+	xen_panic_event, NULL, 0 /* try to go last */
+};
+
+unsigned long *phys_to_machine_mapping;
+EXPORT_SYMBOL(phys_to_machine_mapping);
+
+unsigned long *pfn_to_mfn_frame_list_list, **pfn_to_mfn_frame_list;
+
+/* Raw start-of-day parameters from the hypervisor. */
+start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
+#endif
+
+/*
+ * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
+ * The direct mapping extends to max_pfn_mapped, so that we can directly access
+ * apertures, ACPI and other tables without having to play with fixmaps.
+ */
+unsigned long max_low_pfn_mapped;
+unsigned long max_pfn_mapped;
+
+RESERVE_BRK(dmi_alloc, 65536);
+
+unsigned int boot_cpu_id __read_mostly;
+
+static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
+unsigned long _brk_end = (unsigned long)__brk_base;
+
+#ifndef CONFIG_XEN
+#ifdef CONFIG_X86_64
+int default_cpu_present_to_apicid(int mps_cpu)
+{
+	return __default_cpu_present_to_apicid(mps_cpu);
+}
+
+int default_check_phys_apicid_present(int phys_apicid)
+{
+	return __default_check_phys_apicid_present(phys_apicid);
+}
+#endif
+
+#ifndef CONFIG_DEBUG_BOOT_PARAMS
+struct boot_params __initdata boot_params;
+#else
+struct boot_params boot_params;
+#endif
+#endif
+
+/*
+ * Machine setup..
+ */
+static struct resource data_resource = {
+	.name	= "Kernel data",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+	.name	= "Kernel code",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource bss_resource = {
+	.name	= "Kernel bss",
+	.start	= 0,
+	.end	= 0,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+
+#ifdef CONFIG_X86_32
+/* cpu data as detected by the assembly code in head.S */
+struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};
+/* common cpu data for all cpus */
+struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1};
+EXPORT_SYMBOL(boot_cpu_data);
+#ifndef CONFIG_XEN
+static void set_mca_bus(int x)
+{
+#ifdef CONFIG_MCA
+	MCA_bus = x;
+#endif
+}
+
+unsigned int def_to_bigsmp;
+
+/* for MCA, but anyone else can use it if they want */
+unsigned int machine_id;
+unsigned int machine_submodel_id;
+unsigned int BIOS_revision;
+
+struct apm_info apm_info;
+EXPORT_SYMBOL(apm_info);
+#endif
+
+#if defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+struct ist_info ist_info;
+EXPORT_SYMBOL(ist_info);
+#elif defined(CONFIG_X86_SPEEDSTEP_SMI)
+struct ist_info ist_info;
+#endif
+
+#else
+struct cpuinfo_x86 boot_cpu_data __read_mostly = {
+	.x86_phys_bits = MAX_PHYSMEM_BITS,
+};
+EXPORT_SYMBOL(boot_cpu_data);
+#endif
+
+
+#if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
+unsigned long mmu_cr4_features;
+#else
+unsigned long mmu_cr4_features = X86_CR4_PAE;
+#endif
+
+/* Boot loader ID and version as integers, for the benefit of proc_dointvec */
+int bootloader_type, bootloader_version;
+
+/*
+ * Setup options
+ */
+struct screen_info screen_info;
+EXPORT_SYMBOL(screen_info);
+struct edid_info edid_info;
+EXPORT_SYMBOL_GPL(edid_info);
+
+extern int root_mountflags;
+
+unsigned long saved_video_mode;
+
+#define RAMDISK_IMAGE_START_MASK	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000
+
+static char __initdata command_line[COMMAND_LINE_SIZE];
+#ifdef CONFIG_CMDLINE_BOOL
+static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+#endif
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+struct edd edd;
+#ifdef CONFIG_EDD_MODULE
+EXPORT_SYMBOL(edd);
+#endif
+#ifndef CONFIG_XEN
+/**
+ * copy_edd() - Copy the BIOS EDD information
+ *              from boot_params into a safe place.
+ *
+ */
+static inline void copy_edd(void)
+{
+     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,
+	    sizeof(edd.mbr_signature));
+     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));
+     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;
+     edd.edd_info_nr = boot_params.eddbuf_entries;
+}
+#endif
+#else
+static inline void copy_edd(void)
+{
+}
+#endif
+
+void * __init extend_brk(size_t size, size_t align)
+{
+	size_t mask = align - 1;
+	void *ret;
+
+	BUG_ON(_brk_start == 0);
+	BUG_ON(align & mask);
+
+	_brk_end = (_brk_end + mask) & ~mask;
+	BUG_ON((char *)(_brk_end + size) > __brk_limit);
+
+	ret = (void *)_brk_end;
+	_brk_end += size;
+
+	memset(ret, 0, size);
+
+	return ret;
+}
+
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+static void __init init_gbpages(void)
+{
+	if (direct_gbpages && cpu_has_gbpages)
+		printk(KERN_INFO "Using GB pages for direct mapping\n");
+	else
+		direct_gbpages = 0;
+}
+#else
+static inline void init_gbpages(void)
+{
+}
+#endif
+
+static void __init reserve_brk(void)
+{
+	if (_brk_end > _brk_start)
+		reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
+
+	/* Mark brk area as locked down and no longer taking any
+	   new allocations */
+	_brk_start = 0;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+#define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
+static void __init relocate_initrd(void)
+{
+#ifndef CONFIG_XEN
+	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
+	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+	u64 ramdisk_here;
+	unsigned long slop, clen, mapaddr;
+	char *p, *q;
+
+	/* We need to move the initrd down into lowmem */
+	ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size,
+					 PAGE_SIZE);
+
+	if (ramdisk_here == -1ULL)
+		panic("Cannot find place for new RAMDISK of size %lld\n",
+			 ramdisk_size);
+
+	/* Note: this includes all the lowmem currently occupied by
+	   the initrd, we rely on that fact to keep the data intact. */
+	reserve_early(ramdisk_here, ramdisk_here + ramdisk_size,
+			 "NEW RAMDISK");
+	initrd_start = ramdisk_here + PAGE_OFFSET;
+	initrd_end   = initrd_start + ramdisk_size;
+	printk(KERN_INFO "Allocated new RAMDISK: %08llx - %08llx\n",
+			 ramdisk_here, ramdisk_here + ramdisk_size);
+
+	q = (char *)initrd_start;
+
+	/* Copy any lowmem portion of the initrd */
+	if (ramdisk_image < end_of_lowmem) {
+		clen = end_of_lowmem - ramdisk_image;
+		p = (char *)__va(ramdisk_image);
+		memcpy(q, p, clen);
+		q += clen;
+		ramdisk_image += clen;
+		ramdisk_size  -= clen;
+	}
+
+	/* Copy the highmem portion of the initrd */
+	while (ramdisk_size) {
+		slop = ramdisk_image & ~PAGE_MASK;
+		clen = ramdisk_size;
+		if (clen > MAX_MAP_CHUNK-slop)
+			clen = MAX_MAP_CHUNK-slop;
+		mapaddr = ramdisk_image & PAGE_MASK;
+		p = early_memremap(mapaddr, clen+slop);
+		memcpy(q, p+slop, clen);
+		early_iounmap(p, clen+slop);
+		q += clen;
+		ramdisk_image += clen;
+		ramdisk_size  -= clen;
+	}
+	/* high pages is not converted by early_res_to_bootmem */
+	ramdisk_image = boot_params.hdr.ramdisk_image;
+	ramdisk_size  = boot_params.hdr.ramdisk_size;
+	printk(KERN_INFO "Move RAMDISK from %016llx - %016llx to"
+		" %08llx - %08llx\n",
+		ramdisk_image, ramdisk_image + ramdisk_size - 1,
+		ramdisk_here, ramdisk_here + ramdisk_size - 1);
+#else
+	printk(KERN_ERR "initrd extends beyond end of memory "
+	       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+	       __pa(xen_start_info->mod_start) + xen_start_info->mod_len,
+	       max_low_pfn_mapped << PAGE_SHIFT);
+	initrd_start = 0;
+#endif
+}
+
+static void __init reserve_initrd(void)
+{
+#ifndef CONFIG_XEN
+	u64 ramdisk_image = boot_params.hdr.ramdisk_image;
+	u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+	u64 ramdisk_end   = ramdisk_image + ramdisk_size;
+	u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+
+	if (!boot_params.hdr.type_of_loader ||
+	    !ramdisk_image || !ramdisk_size)
+		return;		/* No initrd provided by bootloader */
+#else
+	unsigned long ramdisk_image = __pa(xen_start_info->mod_start);
+	unsigned long ramdisk_size  = xen_start_info->mod_len;
+	unsigned long ramdisk_end   = ramdisk_image + ramdisk_size;
+	unsigned long end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
+
+	if (!xen_start_info->mod_start || !ramdisk_size)
+		return;		/* No initrd provided by bootloader */
+#endif
+
+	initrd_start = 0;
+
+	if (ramdisk_size >= (end_of_lowmem>>1)) {
+		free_early(ramdisk_image, ramdisk_end);
+		printk(KERN_ERR "initrd too large to handle, "
+		       "disabling initrd\n");
+		return;
+	}
+
+	printk(KERN_INFO "RAMDISK: %08lx - %08lx\n", ramdisk_image,
+			ramdisk_end);
+
+
+	if (ramdisk_end <= end_of_lowmem) {
+		/* All in lowmem, easy case */
+		/*
+		 * don't need to reserve again, already reserved early
+		 * in i386_start_kernel
+		 */
+		initrd_start = ramdisk_image + PAGE_OFFSET;
+		initrd_end = initrd_start + ramdisk_size;
+#ifdef CONFIG_X86_64_XEN
+		initrd_below_start_ok = 1;
+#endif
+		return;
+	}
+
+	relocate_initrd();
+
+	free_early(ramdisk_image, ramdisk_end);
+}
+#else
+static void __init reserve_initrd(void)
+{
+}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+static void __init parse_setup_data(void)
+{
+#ifndef CONFIG_XEN
+	struct setup_data *data;
+	u64 pa_data;
+
+	if (boot_params.hdr.version < 0x0209)
+		return;
+	pa_data = boot_params.hdr.setup_data;
+	while (pa_data) {
+		data = early_memremap(pa_data, PAGE_SIZE);
+		switch (data->type) {
+		case SETUP_E820_EXT:
+			parse_e820_ext(data, pa_data);
+			break;
+		default:
+			break;
+		}
+		pa_data = data->next;
+		early_iounmap(data, PAGE_SIZE);
+	}
+#endif
+}
+
+static void __init e820_reserve_setup_data(void)
+{
+#ifndef CONFIG_XEN
+	struct setup_data *data;
+	u64 pa_data;
+	int found = 0;
+
+	if (boot_params.hdr.version < 0x0209)
+		return;
+	pa_data = boot_params.hdr.setup_data;
+	while (pa_data) {
+		data = early_memremap(pa_data, sizeof(*data));
+		e820_update_range(pa_data, sizeof(*data)+data->len,
+			 E820_RAM, E820_RESERVED_KERN);
+		found = 1;
+		pa_data = data->next;
+		early_iounmap(data, sizeof(*data));
+	}
+	if (!found)
+		return;
+
+	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+	memcpy(&e820_saved, &e820, sizeof(struct e820map));
+	printk(KERN_INFO "extended physical RAM map:\n");
+	e820_print_map("reserve setup_data");
+#endif
+}
+
+static void __init reserve_early_setup_data(void)
+{
+#ifndef CONFIG_XEN
+	struct setup_data *data;
+	u64 pa_data;
+	char buf[32];
+
+	if (boot_params.hdr.version < 0x0209)
+		return;
+	pa_data = boot_params.hdr.setup_data;
+	while (pa_data) {
+		data = early_memremap(pa_data, sizeof(*data));
+		sprintf(buf, "setup data %x", data->type);
+		reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf);
+		pa_data = data->next;
+		early_iounmap(data, sizeof(*data));
+	}
+#endif
+}
+
+/*
+ * --------- Crashkernel reservation ------------------------------
+ */
+
+#ifdef CONFIG_KEXEC
+
+#ifndef CONFIG_XEN
+/**
+ * Reserve @size bytes of crashkernel memory at any suitable offset.
+ *
+ * @size: Size of the crashkernel memory to reserve.
+ * Returns the base address on success, and -1ULL on failure.
+ */
+static
+unsigned long long __init find_and_reserve_crashkernel(unsigned long long size)
+{
+	const unsigned long long alignment = 16<<20; 	/* 16M */
+	unsigned long long start = 0LL;
+
+	while (1) {
+		int ret;
+
+		start = find_e820_area(start, ULONG_MAX, size, alignment);
+		if (start == -1ULL)
+			return start;
+
+		/* try to reserve it */
+		ret = reserve_bootmem_generic(start, size, BOOTMEM_EXCLUSIVE);
+		if (ret >= 0)
+			return start;
+
+		start += alignment;
+	}
+}
+
+static inline unsigned long long get_total_mem(void)
+{
+	unsigned long long total;
+
+	total = max_low_pfn - min_low_pfn;
+#ifdef CONFIG_HIGHMEM
+	total += highend_pfn - highstart_pfn;
+#endif
+
+	return total << PAGE_SHIFT;
+}
+
+static void __init reserve_crashkernel(void)
+{
+	unsigned long long total_mem;
+	unsigned long long crash_size, crash_base;
+	int ret;
+
+	total_mem = get_total_mem();
+
+	ret = parse_crashkernel(boot_command_line, total_mem,
+			&crash_size, &crash_base);
+	if (ret != 0 || crash_size <= 0)
+		return;
+
+	/* 0 means: find the address automatically */
+	if (crash_base <= 0) {
+		crash_base = find_and_reserve_crashkernel(crash_size);
+		if (crash_base == -1ULL) {
+			pr_info("crashkernel reservation failed. "
+				"No suitable area found.\n");
+			return;
+		}
+	} else {
+		ret = reserve_bootmem_generic(crash_base, crash_size,
+					BOOTMEM_EXCLUSIVE);
+		if (ret < 0) {
+			pr_info("crashkernel reservation failed - "
+				"memory is in use\n");
+			return;
+		}
+	}
+
+	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+			"for crashkernel (System RAM: %ldMB)\n",
+			(unsigned long)(crash_size >> 20),
+			(unsigned long)(crash_base >> 20),
+			(unsigned long)(total_mem >> 20));
+
+	crashk_res.start = crash_base;
+	crashk_res.end   = crash_base + crash_size - 1;
+	insert_resource(&iomem_resource, &crashk_res);
+}
+#else
+#define reserve_crashkernel xen_machine_kexec_setup_resources
+#endif
+#else
+static void __init reserve_crashkernel(void)
+{
+}
+#endif
+
+static struct resource standard_io_resources[] = {
+	{ .name = "dma1", .start = 0x00, .end = 0x1f,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .name = "pic1", .start = 0x20, .end = 0x21,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .name = "timer0", .start = 0x40, .end = 0x43,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .name = "timer1", .start = 0x50, .end = 0x53,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .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 },
+	{ .name = "pic2", .start = 0xa0, .end = 0xa1,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .name = "dma2", .start = 0xc0, .end = 0xdf,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO },
+	{ .name = "fpu", .start = 0xf0, .end = 0xff,
+		.flags = IORESOURCE_BUSY | IORESOURCE_IO }
+};
+
+void __init reserve_standard_io_resources(void)
+{
+	int i;
+
+	/* Nothing to do if not running in dom0. */
+	if (!is_initial_xendomain())
+		return;
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+		request_resource(&ioport_resource, &standard_io_resources[i]);
+
+}
+
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+
+#ifdef CONFIG_CRASH_DUMP
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel. This option will be passed
+ * by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
+{
+	char *end;
+	if (!arg)
+		return -EINVAL;
+	elfcorehdr_addr = memparse(arg, &end);
+	return end > arg ? 0 : -EINVAL;
+}
+early_param("elfcorehdr", setup_elfcorehdr);
+#endif
+
+#ifdef CONFIG_X86_RESERVE_LOW_64K
+static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE
+		"%s detected: BIOS may corrupt low RAM, working around it.\n",
+		d->ident);
+
+	e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED);
+	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+
+	return 0;
+}
+#endif
+
+/* List of systems that have known low memory corruption BIOS problems */
+static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
+#ifdef CONFIG_X86_RESERVE_LOW_64K
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
+		},
+	},
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "Phoenix BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
+		},
+	},
+	/*
+	 * AMI BIOS with low memory corruption was found on Intel DG45ID and
+	 * DG45FC boards.
+	 * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+	 * match only DMI_BOARD_NAME and see if there is more bad products
+	 * with this vendor.
+	 */
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
+		},
+	},
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
+		},
+	},
+	/*
+	 * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
+	 * match on the product name.
+	 */
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "Phoenix BIOS",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
+		},
+	},
+#endif
+	{}
+};
+
+/*
+ * Determine if we were loaded by an EFI loader.  If so, then we have also been
+ * passed the efi memmap, systab, etc., so we should use these data structures
+ * for initialization.  Note, the efi init code path is determined by the
+ * global efi_enabled. This allows the same kernel image to be used on existing
+ * systems (with a traditional BIOS) as well as on EFI systems.
+ */
+/*
+ * setup_arch - architecture-specific boot-time initializations
+ *
+ * Note: On x86_64, fixmaps are ready for use even before this is called.
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+#ifdef CONFIG_XEN
+	unsigned int i;
+	unsigned long p2m_pages;
+	struct physdev_set_iopl set_iopl;
+
+	if (!is_initial_xendomain()) {
+#ifdef CONFIG_X86_32
+		/* Force a quick death if the kernel panics (not domain 0). */
+		extern int panic_timeout;
+		if (!panic_timeout)
+			panic_timeout = 1;
+#endif
+
+		/* Register a call for panic conditions. */
+		atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+	}
+#endif /* CONFIG_XEN */
+
+#ifdef CONFIG_X86_32
+	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
+	visws_early_detect();
+#else
+	printk(KERN_INFO "Command line: %s\n", boot_command_line);
+#endif
+
+	/* VMI may relocate the fixmap; do this before touching ioremap area */
+	vmi_init();
+
+	early_cpu_init();
+	early_ioremap_init();
+
+#ifndef CONFIG_XEN
+	ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
+	screen_info = boot_params.screen_info;
+	edid_info = boot_params.edid_info;
+#ifdef CONFIG_X86_32
+	apm_info.bios = boot_params.apm_bios_info;
+	ist_info = boot_params.ist_info;
+	if (boot_params.sys_desc_table.length != 0) {
+		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
+		machine_id = boot_params.sys_desc_table.table[0];
+		machine_submodel_id = boot_params.sys_desc_table.table[1];
+		BIOS_revision = boot_params.sys_desc_table.table[2];
+	}
+#endif
+	saved_video_mode = boot_params.hdr.vid_mode;
+	bootloader_type = boot_params.hdr.type_of_loader;
+	if ((bootloader_type >> 4) == 0xe) {
+		bootloader_type &= 0xf;
+		bootloader_type |= (boot_params.hdr.ext_loader_type+0x10) << 4;
+	}
+	bootloader_version  = bootloader_type & 0xf;
+	bootloader_version |= boot_params.hdr.ext_loader_ver << 4;
+
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
+#endif
+#ifdef CONFIG_EFI
+	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
+#ifdef CONFIG_X86_32
+		     "EL32",
+#else
+		     "EL64",
+#endif
+	 4)) {
+		efi_enabled = 1;
+		efi_reserve_early();
+	}
+#endif
+#else /* CONFIG_XEN */
+#ifdef CONFIG_X86_32
+	/* This must be initialized to UNNAMED_MAJOR for ipconfig to work
+	   properly.  Setting ROOT_DEV to default to /dev/ram0 breaks initrd.
+	*/
+	ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
+#else
+ 	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+	if (is_initial_xendomain()) {
+		const struct dom0_vga_console_info *info =
+			(void *)((char *)xen_start_info +
+			         xen_start_info->console.dom0.info_off);
+
+		dom0_init_screen_info(info,
+		                      xen_start_info->console.dom0.info_size);
+		xen_start_info->console.domU.mfn = 0;
+		xen_start_info->console.domU.evtchn = 0;
+	} else
+		screen_info.orig_video_isVGA = 0;
+	copy_edid();
+#endif /* CONFIG_XEN */
+
+	x86_init.oem.arch_setup();
+
+	setup_memory_map();
+	parse_setup_data();
+	/* update the e820_saved too */
+	e820_reserve_setup_data();
+
+	copy_edd();
+
+#ifndef CONFIG_XEN
+	if (!boot_params.hdr.root_flags)
+		root_mountflags &= ~MS_RDONLY;
+#endif
+	init_mm.start_code = (unsigned long) _text;
+	init_mm.end_code = (unsigned long) _etext;
+	init_mm.end_data = (unsigned long) _edata;
+	init_mm.brk = _brk_end;
+
+	code_resource.start = virt_to_phys(_text);
+	code_resource.end = virt_to_phys(_etext)-1;
+	data_resource.start = virt_to_phys(_etext);
+	data_resource.end = virt_to_phys(_edata)-1;
+	bss_resource.start = virt_to_phys(&__bss_start);
+	bss_resource.end = virt_to_phys(&__bss_stop)-1;
+
+#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERRIDE
+	strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+#else
+	if (builtin_cmdline[0]) {
+		/* append boot loader cmdline to builtin */
+		strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
+		strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+		strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+	}
+#endif
+#endif
+
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = command_line;
+
+#ifdef CONFIG_X86_64
+	/*
+	 * Must call this twice: Once just to detect whether hardware doesn't
+	 * support NX (so that the early EHCI debug console setup can safely
+	 * call set_fixmap(), and then again after parsing early parameters to
+	 * honor the respective command line option.
+	 */
+	check_efer();
+#endif
+
+	parse_early_param();
+
+#ifdef CONFIG_X86_64
+	check_efer();
+#endif
+
+	/* Must be before kernel pagetables are setup */
+	vmi_activate();
+
+	/* after early param, so could get panic from serial */
+	reserve_early_setup_data();
+
+	if (acpi_mps_check()) {
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+		disable_apic = 1;
+#endif
+		setup_clear_cpu_cap(X86_FEATURE_APIC);
+	}
+
+#ifdef CONFIG_PCI
+	if (pci_early_dump_regs)
+		early_dump_pci_devices();
+#endif
+
+	finish_e820_parsing();
+
+	if (efi_enabled)
+		efi_init();
+
+	if (is_initial_xendomain()) {
+		dmi_scan_machine();
+
+		dmi_check_system(bad_bios_dmi_table);
+	}
+
+	/*
+	 * VMware detection requires dmi to be available, so this
+	 * needs to be done after dmi_scan_machine, for the BP.
+	 */
+	init_hypervisor_platform();
+
+	x86_init.resources.probe_roms();
+
+#ifndef CONFIG_XEN
+	/* after parse_early_param, so could debug it */
+	insert_resource(&iomem_resource, &code_resource);
+	insert_resource(&iomem_resource, &data_resource);
+	insert_resource(&iomem_resource, &bss_resource);
+
+
+#ifdef CONFIG_X86_32
+	if (ppro_with_ram_bug()) {
+		e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
+				  E820_RESERVED);
+		sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+		printk(KERN_INFO "fixed physical RAM map:\n");
+		e820_print_map("bad_ppro");
+	}
+#else
+	early_gart_iommu_check();
+#endif
+#endif /* CONFIG_XEN */
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	max_pfn = e820_end_of_ram_pfn();
+
+	/* preallocate 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
+	/* update e820 for memory not covered by WB MTRRs */
+	mtrr_bp_init();
+#ifndef CONFIG_XEN
+	if (mtrr_trim_uncached_memory(max_pfn))
+		max_pfn = e820_end_of_ram_pfn();
+#endif
+
+#ifdef CONFIG_X86_32
+	/* max_low_pfn get updated here */
+	find_low_pfn_range();
+#else
+	num_physpages = max_pfn;
+	max_mapnr = max_pfn;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	check_x2apic();
+#endif
+
+	/* How many end-of-memory variables you have, grandma! */
+	/* need this before calling reserve_initrd */
+	if (max_pfn > (1UL<<(32 - PAGE_SHIFT)))
+		max_low_pfn = e820_end_of_low_ram_pfn();
+	else
+		max_low_pfn = max_pfn;
+
+	high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+#ifndef CONFIG_XEN
+	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
+#endif
+#endif
+
+#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
+	setup_bios_corruption_check();
+#endif
+
+	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
+			max_pfn_mapped<<PAGE_SHIFT);
+
+	reserve_brk();
+
+	init_gbpages();
+
+	/* max_pfn_mapped is updated here */
+	max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
+	max_pfn_mapped = max_low_pfn_mapped;
+
+#ifdef CONFIG_X86_64
+	if (max_pfn > max_low_pfn) {
+		max_pfn_mapped = init_memory_mapping(1UL<<32,
+						     max_pfn<<PAGE_SHIFT);
+		/* can we preseve max_low_pfn ?*/
+		max_low_pfn = max_pfn;
+	}
+#endif
+
+	/*
+	 * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
+	 */
+
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+	if (init_ohci1394_dma_early)
+		init_ohci1394_dma_on_all_controllers();
+#endif
+
+	reserve_initrd();
+
+#ifndef CONFIG_XEN
+	vsmp_init();
+#endif
+
+	io_delay_init();
+
+#ifdef CONFIG_ACPI
+	if (!is_initial_xendomain()) {
+		printk(KERN_INFO "ACPI in unprivileged domain disabled\n");
+		disable_acpi();
+	}
+#endif
+
+	/*
+	 * Parse the ACPI tables for possible boot-time SMP configuration.
+	 */
+	acpi_boot_table_init();
+
+	early_acpi_boot_init();
+
+#ifdef CONFIG_ACPI_NUMA
+	/*
+	 * Parse SRAT to discover nodes.
+	 */
+	acpi_numa_init();
+#endif
+
+	initmem_init(0, max_pfn);
+
+#ifdef CONFIG_ACPI_SLEEP
+	/*
+	 * Reserve low memory region for sleep support.
+	 */
+	acpi_reserve_bootmem();
+#endif
+	/*
+	 * Find and reserve possible boot-time SMP configuration:
+	 */
+	find_smp_config();
+
+	reserve_crashkernel();
+
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+	/*
+	 * dma32_reserve_bootmem() allocates bootmem which may conflict
+	 * with the crashkernel command line, so do that after
+	 * reserve_crashkernel()
+	 */
+	dma32_reserve_bootmem();
+#endif
+
+	reserve_ibft_region();
+
+#ifdef CONFIG_KVM_CLOCK
+	kvmclock_init();
+#endif
+
+	x86_init.paging.pagetable_setup_start(swapper_pg_dir);
+	paging_init();
+	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
+
+	tboot_probe();
+
+#ifdef CONFIG_X86_64
+	map_vsyscall();
+#endif
+
+#ifdef CONFIG_XEN
+	p2m_pages = max_pfn;
+	if (xen_start_info->nr_pages > max_pfn) {
+		/*
+		 * the max_pfn was shrunk (probably by mem= or highmem=
+		 * kernel parameter); shrink reservation with the HV
+		 */
+		struct xen_memory_reservation reservation = {
+			.address_bits = 0,
+			.extent_order = 0,
+			.domid = DOMID_SELF
+		};
+		unsigned int difference;
+		int ret;
+
+		difference = xen_start_info->nr_pages - max_pfn;
+
+		set_xen_guest_handle(reservation.extent_start,
+				     phys_to_machine_mapping + max_pfn);
+		reservation.nr_extents = difference;
+		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					   &reservation);
+		BUG_ON(ret != difference);
+	}
+	else if (max_pfn > xen_start_info->nr_pages)
+		p2m_pages = xen_start_info->nr_pages;
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+		unsigned long i, j, size;
+		unsigned int k, fpp;
+
+		/* Make sure we have a large enough P->M table. */
+		phys_to_machine_mapping = alloc_bootmem_pages(
+			max_pfn * sizeof(unsigned long));
+		memcpy(phys_to_machine_mapping,
+		       __va(__pa(xen_start_info->mfn_list)),
+		       p2m_pages * sizeof(unsigned long));
+		memset(phys_to_machine_mapping + p2m_pages, ~0,
+		       (max_pfn - p2m_pages) * sizeof(unsigned long));
+
+#ifdef CONFIG_X86_64
+		if (xen_start_info->mfn_list == VMEMMAP_START) {
+			/*
+			 * Since it is well isolated we can (and since it is
+			 * perhaps large we should) also free the page tables
+			 * mapping the initial P->M table.
+			 */
+			unsigned long va = VMEMMAP_START, pa;
+			pgd_t *pgd = pgd_offset_k(va);
+			pud_t *pud_page = pud_offset(pgd, 0);
+
+			BUILD_BUG_ON(VMEMMAP_START & ~PGDIR_MASK);
+			xen_l4_entry_update(pgd, __pgd(0));
+			for(;;) {
+				pud_t *pud = pud_page + pud_index(va);
+
+				if (pud_none(*pud))
+					va += PUD_SIZE;
+				else if (pud_large(*pud)) {
+					pa = pud_val(*pud) & PHYSICAL_PAGE_MASK;
+					make_pages_writable(__va(pa),
+						PUD_SIZE >> PAGE_SHIFT,
+						XENFEAT_writable_page_tables);
+					free_bootmem(pa, PUD_SIZE);
+					va += PUD_SIZE;
+				} else {
+					pmd_t *pmd = pmd_offset(pud, va);
+
+					if (pmd_large(*pmd)) {
+						pa = pmd_val(*pmd) & PHYSICAL_PAGE_MASK;
+						make_pages_writable(__va(pa),
+							PMD_SIZE >> PAGE_SHIFT,
+							XENFEAT_writable_page_tables);
+						free_bootmem(pa, PMD_SIZE);
+					} else if (!pmd_none(*pmd)) {
+						pte_t *pte = pte_offset_kernel(pmd, va);
+
+						for (i = 0; i < PTRS_PER_PTE; ++i) {
+							if (pte_none(pte[i]))
+								break;
+							pa = pte_pfn(pte[i]) << PAGE_SHIFT;
+							make_page_writable(__va(pa),
+								XENFEAT_writable_page_tables);
+							free_bootmem(pa, PAGE_SIZE);
+						}
+						ClearPagePinned(virt_to_page(pte));
+						make_page_writable(pte,
+							XENFEAT_writable_page_tables);
+						free_bootmem(__pa(pte), PAGE_SIZE);
+					}
+					va += PMD_SIZE;
+					if (pmd_index(va))
+						continue;
+					ClearPagePinned(virt_to_page(pmd));
+					make_page_writable(pmd,
+						XENFEAT_writable_page_tables);
+					free_bootmem(__pa((unsigned long)pmd
+							  & PAGE_MASK),
+						PAGE_SIZE);
+				}
+				if (!pud_index(va))
+					break;
+			}
+			ClearPagePinned(virt_to_page(pud_page));
+			make_page_writable(pud_page,
+				XENFEAT_writable_page_tables);
+			free_bootmem(__pa((unsigned long)pud_page & PAGE_MASK),
+				PAGE_SIZE);
+		} else if (!WARN_ON(xen_start_info->mfn_list
+				    < __START_KERNEL_map))
+#endif
+			free_bootmem(__pa(xen_start_info->mfn_list),
+				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+						sizeof(unsigned long))));
+
+
+		/*
+		 * Initialise the list of the frames that specify the list of
+		 * frames that make up the p2m table. Used by save/restore.
+		 */
+		fpp = PAGE_SIZE/sizeof(unsigned long);
+		size = (max_pfn + fpp - 1) / fpp;
+		size = (size + fpp - 1) / fpp;
+		++size; /* include a zero terminator for crash tools */
+		size *= sizeof(unsigned long);
+		pfn_to_mfn_frame_list_list = alloc_bootmem_pages(size);
+		if (size > PAGE_SIZE
+		    && xen_create_contiguous_region((unsigned long)
+						    pfn_to_mfn_frame_list_list,
+						    get_order(size), 0))
+			BUG();
+		size -= sizeof(unsigned long);
+		pfn_to_mfn_frame_list = alloc_bootmem(size);
+
+		for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) {
+			if (j == fpp)
+				j = 0;
+			if (j == 0) {
+				k++;
+				BUG_ON(k * sizeof(unsigned long) >= size);
+				pfn_to_mfn_frame_list[k] =
+					alloc_bootmem_pages(PAGE_SIZE);
+				pfn_to_mfn_frame_list_list[k] =
+					virt_to_mfn(pfn_to_mfn_frame_list[k]);
+			}
+			pfn_to_mfn_frame_list[k][j] =
+				virt_to_mfn(&phys_to_machine_mapping[i]);
+		}
+		HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+			virt_to_mfn(pfn_to_mfn_frame_list_list);
+	}
+
+	/* Mark all ISA DMA channels in-use - using them wouldn't work. */
+	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
+		if (i != 4 && request_dma(i, "xen") != 0)
+			BUG();
+#else /* CONFIG_XEN */
+	generic_apic_probe();
+
+	early_quirks();
+#endif
+
+	/*
+	 * Read APIC and some other early information from ACPI tables.
+	 */
+	acpi_boot_init();
+
+	sfi_init();
+
+	/*
+	 * get boot-time SMP configuration:
+	 */
+	if (smp_found_config)
+		get_smp_config();
+
+	prefill_possible_map();
+
+#ifdef CONFIG_X86_64
+	init_cpu_to_node();
+#endif
+
+#ifndef CONFIG_XEN
+	init_apic_mappings();
+	ioapic_init_mappings();
+
+	/* need to wait for io_apic is mapped */
+	probe_nr_irqs_gsi();
+
+	kvm_guest_init();
+
+	e820_reserve_resources();
+	e820_mark_nosave_regions(max_low_pfn);
+#else
+	if (is_initial_xendomain())
+		e820_reserve_resources();
+#endif
+
+	x86_init.resources.reserve_resources();
+
+#ifndef CONFIG_XEN
+	e820_setup_gap();
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+		conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+#else /* CONFIG_XEN */
+	if (is_initial_xendomain())
+		e820_setup_gap();
+
+	set_iopl.iopl = 1;
+	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_VGA_CONSOLE
+	if (is_initial_xendomain())
+		conswitchp = &vga_con;
+#endif
+#endif
+    xencons_early_setup();
+#endif /* CONFIG_XEN */
+	x86_init.oem.banner();
+}
+
+#ifdef CONFIG_X86_32
+
+static struct resource video_ram_resource = {
+	.name	= "Video RAM area",
+	.start	= 0xa0000,
+	.end	= 0xbffff,
+	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+void __init i386_reserve_resources(void)
+{
+	if (is_initial_xendomain())
+		request_resource(&iomem_resource, &video_ram_resource);
+	reserve_standard_io_resources();
+}
+
+#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_XEN
+static int
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	HYPERVISOR_shutdown(SHUTDOWN_crash);
+	/* we're never actually going to get here... */
+	return NOTIFY_DONE;
+}
+#endif /* !CONFIG_XEN */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/mpparse.c
+++ linux-ec2-2.6.32/arch/x86/kernel/mpparse.c
@@ -359,13 +359,6 @@
 		x86_init.mpparse.mpc_record(1);
 	}
 
-#ifdef CONFIG_X86_BIGSMP
-	generic_bigsmp_probe();
-#endif
-
-	if (apic->setup_apic_routing)
-		apic->setup_apic_routing();
-
 	if (!num_processors)
 		printk(KERN_ERR "MPTABLE: no processors registered!\n");
 	return num_processors;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpuid.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpuid.c
@@ -192,7 +192,8 @@
 	int i, err = 0;
 	i = 0;
 
-	if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) {
+	if (__register_chrdev(CPUID_MAJOR, 0, NR_CPUS,
+			      "cpu/cpuid", &cpuid_fops)) {
 		printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
 		       CPUID_MAJOR);
 		err = -EBUSY;
@@ -221,7 +222,7 @@
 	}
 	class_destroy(cpuid_class);
 out_chrdev:
-	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
+	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
 out:
 	return err;
 }
@@ -233,7 +234,7 @@
 	for_each_online_cpu(cpu)
 		cpuid_device_destroy(cpu);
 	class_destroy(cpuid_class);
-	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
+	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
 	unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/amd_iommu_init.c
+++ linux-ec2-2.6.32/arch/x86/kernel/amd_iommu_init.c
@@ -136,6 +136,11 @@
 					   system */
 
 /*
+ * Set to true if ACPI table parsing and hardware intialization went properly
+ */
+static bool amd_iommu_initialized;
+
+/*
  * Pointer to the device table which is shared by all AMD IOMMUs
  * it is indexed by the PCI device id or the HT unit id and contains
  * information about the domain the device belongs to as well as the
@@ -617,6 +622,13 @@
 	iommu->last_device = calc_devid(MMIO_GET_BUS(range),
 					MMIO_GET_LD(range));
 	iommu->evt_msi_num = MMIO_MSI_NUM(misc);
+
+	if (is_rd890_iommu(iommu->dev)) {
+		pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]);
+		pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]);
+		pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]);
+		pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]);
+	}
 }
 
 /*
@@ -634,29 +646,9 @@
 	struct ivhd_entry *e;
 
 	/*
-	 * First set the recommended feature enable bits from ACPI
-	 * into the IOMMU control registers
+	 * First save the recommended feature enable bits from ACPI
 	 */
-	h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
-		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
-
-	h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
-
-	h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
-		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
-
-	h->flags & IVHD_FLAG_ISOC_EN_MASK ?
-		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
-		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
-
-	/*
-	 * make IOMMU memory accesses cache coherent
-	 */
-	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+	iommu->acpi_flags = h->flags;
 
 	/*
 	 * Done. Now parse the device entries
@@ -913,6 +905,8 @@
 	}
 	WARN_ON(p != end);
 
+	amd_iommu_initialized = true;
+
 	return 0;
 }
 
@@ -925,7 +919,7 @@
  *
  ****************************************************************************/
 
-static int __init iommu_setup_msi(struct amd_iommu *iommu)
+static int iommu_setup_msi(struct amd_iommu *iommu)
 {
 	int r;
 
@@ -1082,6 +1076,40 @@
 	}
 }
 
+static void iommu_init_flags(struct amd_iommu *iommu)
+{
+	iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
+		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
+		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
+
+	iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
+		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
+		iommu_feature_disable(iommu, CONTROL_ISOC_EN);
+
+	/*
+	 * make IOMMU memory accesses cache coherent
+	 */
+	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
+}
+
+static void iommu_apply_quirks(struct amd_iommu *iommu)
+{
+	if (is_rd890_iommu(iommu->dev)) {
+		pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]);
+		pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]);
+		pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]);
+		pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]);
+	}
+}
+
 /*
  * This function finally enables all IOMMUs found in the system after
  * they have been initialized
@@ -1092,6 +1120,8 @@
 
 	for_each_iommu(iommu) {
 		iommu_disable(iommu);
+		iommu_apply_quirks(iommu);
+		iommu_init_flags(iommu);
 		iommu_set_device_table(iommu);
 		iommu_enable_command_buffer(iommu);
 		iommu_enable_event_buffer(iommu);
@@ -1263,6 +1293,9 @@
 	if (acpi_table_parse("IVRS", init_iommu_all) != 0)
 		goto free;
 
+	if (!amd_iommu_initialized)
+		goto free;
+
 	if (acpi_table_parse("IVRS", init_memory_definitions) != 0)
 		goto free;
 
@@ -1274,14 +1307,17 @@
 	if (ret)
 		goto free;
 
+	enable_iommus();
+
 	if (iommu_pass_through)
 		ret = amd_iommu_init_passthrough();
 	else
 		ret = amd_iommu_init_dma_ops();
+
 	if (ret)
 		goto free;
 
-	enable_iommus();
+	amd_iommu_init_api();
 
 	if (iommu_pass_through)
 		goto out;
@@ -1301,6 +1337,8 @@
 	return ret;
 
 free:
+	disable_iommus();
+
 	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
 		   get_order(MAX_DOMAIN_ID/8));
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/vsyscall_64-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/vsyscall_64-xen.c
@@ -0,0 +1,315 @@
+/*
+ *  Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
+ *  Copyright 2003 Andi Kleen, SuSE Labs.
+ *
+ *  Thanks to hpa@transmeta.com for some useful hint.
+ *  Special thanks to Ingo Molnar for his early experience with
+ *  a different vsyscall implementation for Linux/IA32 and for the name.
+ *
+ *  vsyscall 1 is located at -10Mbyte, vsyscall 2 is located
+ *  at virtual address -10Mbyte+1024bytes etc... There are at max 4
+ *  vsyscalls. One vsyscall can reserve more than 1 slot to avoid
+ *  jumping out of line if necessary. We cannot add more with this
+ *  mechanism because older kernels won't return -ENOSYS.
+ *  If we want more than four we need a vDSO.
+ *
+ *  Note: the concept clashes with user mode linux. If you use UML and
+ *  want per guest time just set the kernel.vsyscall64 sysctl to 0.
+ */
+
+/* Disable profiling for userspace code: */
+#define DISABLE_BRANCH_PROFILING
+
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/seqlock.h>
+#include <linux/jiffies.h>
+#include <linux/sysctl.h>
+#include <linux/clocksource.h>
+#include <linux/getcpu.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/notifier.h>
+
+#include <asm/vsyscall.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
+#include <asm/fixmap.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/desc.h>
+#include <asm/topology.h>
+#include <asm/vgtod.h>
+
+#define __vsyscall(nr) \
+		__attribute__ ((unused, __section__(".vsyscall_" #nr))) notrace
+#define __syscall_clobber "r11","cx","memory"
+
+/*
+ * vsyscall_gtod_data contains data that is :
+ * - readonly from vsyscalls
+ * - written by timer interrupt or systcl (/proc/sys/kernel/vsyscall64)
+ * Try to keep this structure as small as possible to avoid cache line ping pongs
+ */
+int __vgetcpu_mode __section_vgetcpu_mode;
+
+struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data =
+{
+	.lock = SEQLOCK_UNLOCKED,
+	.sysctl_enabled = 1,
+};
+
+void update_vsyscall_tz(void)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+	/* sys_tz has changed */
+	vsyscall_gtod_data.sys_tz = sys_tz;
+	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+}
+
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
+		     u32 mult)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+	/* copy vsyscall data */
+	vsyscall_gtod_data.clock.vread = clock->vread;
+	vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
+	vsyscall_gtod_data.clock.mask = clock->mask;
+	vsyscall_gtod_data.clock.mult = mult;
+	vsyscall_gtod_data.clock.shift = clock->shift;
+	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
+	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
+	vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;
+	vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
+	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+}
+
+/* RED-PEN may want to readd seq locking, but then the variable should be
+ * write-once.
+ */
+static __always_inline void do_get_tz(struct timezone * tz)
+{
+	*tz = __vsyscall_gtod_data.sys_tz;
+}
+
+static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	int ret;
+	asm volatile("syscall"
+		: "=a" (ret)
+		: "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
+		: __syscall_clobber );
+	return ret;
+}
+
+static __always_inline long time_syscall(long *t)
+{
+	long secs;
+	asm volatile("syscall"
+		: "=a" (secs)
+		: "0" (__NR_time),"D" (t) : __syscall_clobber);
+	return secs;
+}
+
+static __always_inline void do_vgettimeofday(struct timeval * tv)
+{
+	cycle_t now, base, mask, cycle_delta;
+	unsigned seq;
+	unsigned long mult, shift, nsec;
+	cycle_t (*vread)(void);
+	do {
+		seq = read_seqbegin(&__vsyscall_gtod_data.lock);
+
+		vread = __vsyscall_gtod_data.clock.vread;
+		if (unlikely(!__vsyscall_gtod_data.sysctl_enabled || !vread)) {
+			gettimeofday(tv,NULL);
+			return;
+		}
+
+		now = vread();
+		base = __vsyscall_gtod_data.clock.cycle_last;
+		mask = __vsyscall_gtod_data.clock.mask;
+		mult = __vsyscall_gtod_data.clock.mult;
+		shift = __vsyscall_gtod_data.clock.shift;
+
+		tv->tv_sec = __vsyscall_gtod_data.wall_time_sec;
+		nsec = __vsyscall_gtod_data.wall_time_nsec;
+	} while (read_seqretry(&__vsyscall_gtod_data.lock, seq));
+
+	/* calculate interval: */
+	cycle_delta = (now - base) & mask;
+	/* convert to nsecs: */
+	nsec += (cycle_delta * mult) >> shift;
+
+	while (nsec >= NSEC_PER_SEC) {
+		tv->tv_sec += 1;
+		nsec -= NSEC_PER_SEC;
+	}
+	tv->tv_usec = nsec / NSEC_PER_USEC;
+}
+
+int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+{
+	if (tv)
+		do_vgettimeofday(tv);
+	if (tz)
+		do_get_tz(tz);
+	return 0;
+}
+
+/* This will break when the xtime seconds get inaccurate, but that is
+ * unlikely */
+time_t __vsyscall(1) vtime(time_t *t)
+{
+	struct timeval tv;
+	time_t result;
+	if (unlikely(!__vsyscall_gtod_data.sysctl_enabled))
+		return time_syscall(t);
+
+	vgettimeofday(&tv, NULL);
+	result = tv.tv_sec;
+	if (t)
+		*t = result;
+	return result;
+}
+
+/* Fast way to get current CPU and node.
+   This helps to do per node and per CPU caches in user space.
+   The result is not guaranteed without CPU affinity, but usually
+   works out because the scheduler tries to keep a thread on the same
+   CPU.
+
+   tcache must point to a two element sized long array.
+   All arguments can be NULL. */
+long __vsyscall(2)
+vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
+{
+	unsigned int p;
+	unsigned long j = 0;
+
+	/* Fast cache - only recompute value once per jiffies and avoid
+	   relatively costly rdtscp/cpuid otherwise.
+	   This works because the scheduler usually keeps the process
+	   on the same CPU and this syscall doesn't guarantee its
+	   results anyways.
+	   We do this here because otherwise user space would do it on
+	   its own in a likely inferior way (no access to jiffies).
+	   If you don't like it pass NULL. */
+	if (tcache && tcache->blob[0] == (j = __jiffies)) {
+		p = tcache->blob[1];
+	} else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+		/* Load per CPU data from RDTSCP */
+		native_read_tscp(&p);
+	} else {
+		/* Load per CPU data from GDT */
+		asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+	}
+	if (tcache) {
+		tcache->blob[0] = j;
+		tcache->blob[1] = p;
+	}
+	if (cpu)
+		*cpu = p & 0xfff;
+	if (node)
+		*node = p >> 12;
+	return 0;
+}
+
+static long __vsyscall(3) venosys_1(void)
+{
+	return -ENOSYS;
+}
+
+#ifdef CONFIG_SYSCTL
+static ctl_table kernel_table2[] = {
+	{ .procname = "vsyscall64",
+	  .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
+	  .mode = 0644,
+	  .proc_handler = proc_dointvec },
+	{}
+};
+
+static ctl_table kernel_root_table2[] = {
+	{ .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
+	  .child = kernel_table2 },
+	{}
+};
+#endif
+
+/* Assume __initcall executes before all user space. Hopefully kmod
+   doesn't violate that. We'll find out if it does. */
+static void __cpuinit vsyscall_set_cpu(int cpu)
+{
+	unsigned long d;
+	unsigned long node = 0;
+#ifdef CONFIG_NUMA
+	node = cpu_to_node(cpu);
+#endif
+	if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
+		write_rdtscp_aux((node << 12) | cpu);
+
+	/* Store cpu number in limit so that it can be loaded quickly
+	   in user space in vgetcpu.
+	   12 bits for the CPU and 8 bits for the node. */
+	d = 0x0f40000000000ULL;
+	d |= cpu;
+	d |= (node & 0xf) << 12;
+	d |= (node >> 4) << 48;
+	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S);
+}
+
+static void __cpuinit cpu_vsyscall_init(void *arg)
+{
+	/* preemption should be already off */
+	vsyscall_set_cpu(raw_smp_processor_id());
+}
+
+static int __cpuinit
+cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg)
+{
+	long cpu = (long)arg;
+	if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
+		smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 1);
+	return NOTIFY_DONE;
+}
+
+void __init map_vsyscall(void)
+{
+	extern char __vsyscall_0;
+	unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
+
+	/* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */
+	__set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
+}
+
+static int __init vsyscall_init(void)
+{
+	BUG_ON(((unsigned long) &vgettimeofday !=
+			VSYSCALL_ADDR(__NR_vgettimeofday)));
+	BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
+	BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
+	BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
+#ifdef CONFIG_XEN
+	vsyscall_gtod_data.sysctl_enabled = 0; /* disable vgettimeofay() */
+ 	if (boot_cpu_has(X86_FEATURE_RDTSCP))
+		vgetcpu_mode = VGETCPU_RDTSCP;
+	else
+		vgetcpu_mode = VGETCPU_LSL;
+#endif
+#ifdef CONFIG_SYSCTL
+	register_sysctl_table(kernel_root_table2);
+#endif
+	on_each_cpu(cpu_vsyscall_init, NULL, 1);
+	hotcpu_notifier(cpu_vsyscall_notifier, 0);
+	return 0;
+}
+
+__initcall(vsyscall_init);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/vm86_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/vm86_32.c
@@ -125,7 +125,9 @@
 
 struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
 {
+#ifndef CONFIG_X86_NO_TSS
 	struct tss_struct *tss;
+#endif
 	struct pt_regs *ret;
 	unsigned long tmp;
 
@@ -148,12 +150,16 @@
 		do_exit(SIGSEGV);
 	}
 
+#ifndef CONFIG_X86_NO_TSS
 	tss = &per_cpu(init_tss, get_cpu());
+#endif
 	current->thread.sp0 = current->thread.saved_sp0;
 	current->thread.sysenter_cs = __KERNEL_CS;
 	load_sp0(tss, &current->thread);
 	current->thread.saved_sp0 = 0;
+#ifndef CONFIG_X86_NO_TSS
 	put_cpu();
+#endif
 
 	ret = KVM86->regs32;
 
@@ -280,7 +286,9 @@
 
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk)
 {
+#ifndef CONFIG_X86_NO_TSS
 	struct tss_struct *tss;
+#endif
 /*
  * make sure the vm86() system call doesn't try to do anything silly
  */
@@ -324,12 +332,16 @@
 	tsk->thread.saved_fs = info->regs32->fs;
 	tsk->thread.saved_gs = get_user_gs(info->regs32);
 
+#ifndef CONFIG_X86_NO_TSS
 	tss = &per_cpu(init_tss, get_cpu());
+#endif
 	tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0;
 	if (cpu_has_sep)
 		tsk->thread.sysenter_cs = 0;
 	load_sp0(tss, &tsk->thread);
+#ifndef CONFIG_X86_NO_TSS
 	put_cpu();
+#endif
 
 	tsk->thread.screen_bitmap = info->screen_bitmap;
 	if (info->flags & VM86_SCREEN_BITMAP)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/Makefile
@@ -11,6 +11,8 @@
 CFLAGS_REMOVE_tsc.o = -pg
 CFLAGS_REMOVE_rtc.o = -pg
 CFLAGS_REMOVE_paravirt-spinlocks.o = -pg
+CFLAGS_REMOVE_pvclock.o = -pg
+CFLAGS_REMOVE_kvmclock.o = -pg
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
@@ -117,6 +119,8 @@
 
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 
+obj-$(CONFIG_X86_XEN)		+= fixup.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
@@ -131,3 +135,8 @@
 	obj-$(CONFIG_PCI_MMCONFIG)	+= mmconf-fam10h_64.o
 	obj-y				+= vsmp_64.o
 endif
+
+disabled-obj-$(CONFIG_XEN) := %_uv.o crash.o early-quirks.o hpet.o i8253.o \
+	i8259.o irqinit.o pci-swiotlb.o reboot.o smpboot.o tsc.o tsc_sync.o \
+	uv_%.o vsmp_64.o
+disabled-obj-$(CONFIG_XEN_UNPRIVILEGED_GUEST) += probe_roms_32.o
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process.c
@@ -91,18 +91,6 @@
 {
 	struct task_struct *tsk = current;
 
-#ifdef CONFIG_X86_64
-	if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
-		clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
-		if (test_tsk_thread_flag(tsk, TIF_IA32)) {
-			clear_tsk_thread_flag(tsk, TIF_IA32);
-		} else {
-			set_tsk_thread_flag(tsk, TIF_IA32);
-			current_thread_info()->status |= TS_COMPAT;
-		}
-	}
-#endif
-
 	clear_tsk_thread_flag(tsk, TIF_DEBUG);
 
 	tsk->thread.debugreg0 = 0;
@@ -450,24 +438,6 @@
 	return (edx & MWAIT_EDX_C1);
 }
 
-/*
- * Check for AMD CPUs, which have potentially C1E support
- */
-static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c)
-{
-	if (c->x86_vendor != X86_VENDOR_AMD)
-		return 0;
-
-	if (c->x86 < 0x0F)
-		return 0;
-
-	/* Family 0x0f models < rev F do not have C1E */
-	if (c->x86 == 0x0f && c->x86_model < 0x40)
-		return 0;
-
-	return 1;
-}
-
 static cpumask_var_t c1e_mask;
 static int c1e_detected;
 
@@ -545,7 +515,8 @@
 		 */
 		printk(KERN_INFO "using mwait in idle threads.\n");
 		pm_idle = mwait_idle;
-	} else if (check_c1e_idle(c)) {
+	} else if (cpu_has_amd_erratum(amd_erratum_400)) {
+		/* E400: APIC timer interrupt does not wake up CPU from C1e */
 		printk(KERN_INFO "using C1E aware idle routine\n");
 		pm_idle = c1e_idle;
 	} else
@@ -607,6 +578,16 @@
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
 	unsigned long range_end = mm->brk + 0x02000000;
-	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+	unsigned long bump = 0;
+#ifdef CONFIG_X86_32
+	/* in the case of NX emulation, shove the brk segment way out of the
+           way of the exec randomization area, since it can collide with
+	   future allocations if not. */
+	if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) &&
+	     (mm->brk < 0x08000000) ) {
+		bump = (TASK_SIZE/6);
+	}
+#endif
+	return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk);
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/vmlinux.lds.S
+++ linux-ec2-2.6.32/arch/x86/kernel/vmlinux.lds.S
@@ -16,8 +16,10 @@
 
 #ifdef CONFIG_X86_32
 #define LOAD_OFFSET __PAGE_OFFSET
-#else
+#elif !defined(CONFIG_XEN) || CONFIG_XEN_COMPAT > 0x030002
 #define LOAD_OFFSET __START_KERNEL_map
+#else
+#define LOAD_OFFSET 0
 #endif
 
 #include <asm-generic/vmlinux.lds.h>
@@ -58,6 +60,10 @@
 {
 #ifdef CONFIG_X86_32
         . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR;
+#if defined(CONFIG_XEN) && CONFIG_XEN_COMPAT <= 0x030002
+#undef LOAD_OFFSET
+#define LOAD_OFFSET 0
+#endif
         phys_startup_32 = startup_32 - LOAD_OFFSET;
 #else
         . = __START_KERNEL;
@@ -308,8 +314,10 @@
 /*
  * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
  */
+#if !defined(CONFIG_XEN) || CONFIG_XEN_COMPAT > 0x030002
 . = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
 	   "kernel image bigger than KERNEL_IMAGE_SIZE");
+#endif
 #else
 /*
  * Per-cpu symbols which need to be offset from __per_cpu_load
--- linux-ec2-2.6.32.orig/arch/x86/kernel/microcode_amd.c
+++ linux-ec2-2.6.32/arch/x86/kernel/microcode_amd.c
@@ -63,7 +63,6 @@
 	unsigned int			mpb[0];
 };
 
-#define UCODE_MAX_SIZE			2048
 #define UCODE_CONTAINER_SECTION_HDR	8
 #define UCODE_CONTAINER_HEADER_SIZE	12
 
@@ -109,12 +108,8 @@
 		return 0;
 	}
 
-	if (mc_header->processor_rev_id != equiv_cpu_id) {
-		printk(KERN_ERR	"microcode: CPU%d: patch mismatch "
-		       "(processor_rev_id: %x, equiv_cpu_id: %x)\n",
-		       cpu, mc_header->processor_rev_id, equiv_cpu_id);
+	if (mc_header->processor_rev_id != equiv_cpu_id)
 		return 0;
-	}
 
 	/* ucode might be chipset specific -- currently we don't support this */
 	if (mc_header->nb_dev_id || mc_header->sb_dev_id) {
@@ -129,6 +124,37 @@
 	return 1;
 }
 
+static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	unsigned int max_size, actual_size;
+
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
+
+	switch (c->x86) {
+	case 0x14:
+		max_size = F14H_MPB_MAX_SIZE;
+		break;
+	case 0x15:
+		max_size = F15H_MPB_MAX_SIZE;
+		break;
+	default:
+		max_size = F1XH_MPB_MAX_SIZE;
+		break;
+	}
+
+	actual_size = buf[4] + (buf[5] << 8);
+
+	if (actual_size > size || actual_size > max_size) {
+		pr_err("section size mismatch\n");
+		return 0;
+	}
+
+	return actual_size;
+}
+
 static int apply_microcode_amd(int cpu)
 {
 	u32 rev, dummy;
@@ -168,11 +194,11 @@
 }
 
 static void *
-get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
+get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
 {
-	unsigned int total_size;
+	unsigned int actual_size = 0;
 	u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
-	void *mc;
+	void *mc = NULL;
 
 	if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR))
 		return NULL;
@@ -183,26 +209,18 @@
 		return NULL;
 	}
 
-	total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
-
-	printk(KERN_DEBUG "microcode: size %u, total_size %u\n",
-	       size, total_size);
+	actual_size = verify_ucode_size(cpu, buf, size);
+	if (!actual_size)
+		return NULL;
 
-	if (total_size > size || total_size > UCODE_MAX_SIZE) {
-		printk(KERN_ERR "microcode: error: size mismatch\n");
+	mc = vmalloc(actual_size);
+	if (!mc)
 		return NULL;
-	}
 
-	mc = vmalloc(UCODE_MAX_SIZE);
-	if (mc) {
-		memset(mc, 0, UCODE_MAX_SIZE);
-		if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR,
-				   total_size)) {
-			vfree(mc);
-			mc = NULL;
-		} else
-			*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
-	}
+	memset(mc, 0, actual_size);
+	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
+	*mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
+
 	return mc;
 }
 
@@ -271,7 +289,7 @@
 		unsigned int uninitialized_var(mc_size);
 		struct microcode_header_amd *mc_header;
 
-		mc = get_next_ucode(ucode_ptr, leftover, &mc_size);
+		mc = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
 		if (!mc)
 			break;
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/crash_dump_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/crash_dump_64.c
@@ -34,7 +34,7 @@
 	if (!csize)
 		return 0;
 
-	vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+	vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
 	if (!vaddr)
 		return -ENOMEM;
 
@@ -46,6 +46,7 @@
 	} else
 		memcpy(buf, vaddr + offset, csize);
 
+	set_iounmap_nonlazy();
 	iounmap(vaddr);
 	return csize;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head_32-xen.S
+++ linux-ec2-2.6.32/arch/x86/kernel/head_32-xen.S
@@ -0,0 +1,198 @@
+
+
+.text
+#include <linux/elfnote.h>
+#include <linux/threads.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/page_types.h>
+#include <asm/pgtable_types.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/boot.h>
+#include <asm/dwarf2.h>
+#include <asm/percpu.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/elfnote.h>
+
+/*
+ * References to members of the new_cpu_data structure.
+ */
+
+#define X86		new_cpu_data+CPUINFO_x86
+#define X86_VENDOR	new_cpu_data+CPUINFO_x86_vendor
+#define X86_MODEL	new_cpu_data+CPUINFO_x86_model
+#define X86_MASK	new_cpu_data+CPUINFO_x86_mask
+#define X86_HARD_MATH	new_cpu_data+CPUINFO_hard_math
+#define X86_CPUID	new_cpu_data+CPUINFO_cpuid_level
+#define X86_CAPABILITY	new_cpu_data+CPUINFO_x86_capability
+#define X86_VENDOR_ID	new_cpu_data+CPUINFO_x86_vendor_id
+
+__HEAD
+#define VIRT_ENTRY_OFFSET 0x0
+.org VIRT_ENTRY_OFFSET
+ENTRY(startup_32)
+	movl %esi,xen_start_info
+	cld
+
+	/* Set up the stack pointer */
+	movl $(init_thread_union+THREAD_SIZE),%esp
+
+	/* get vendor info */
+	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
+	XEN_CPUID
+	movl %eax,X86_CPUID		# save CPUID level
+	movl %ebx,X86_VENDOR_ID		# lo 4 chars
+	movl %edx,X86_VENDOR_ID+4	# next 4 chars
+	movl %ecx,X86_VENDOR_ID+8	# last 4 chars
+
+	movl $1,%eax		# Use the CPUID instruction to get CPU type
+	XEN_CPUID
+	movb %al,%cl		# save reg for future use
+	andb $0x0f,%ah		# mask processor family
+	movb %ah,X86
+	andb $0xf0,%al		# mask model
+	shrb $4,%al
+	movb %al,X86_MODEL
+	andb $0x0f,%cl		# mask mask revision
+	movb %cl,X86_MASK
+	movl %edx,X86_CAPABILITY
+
+	movb $1,X86_HARD_MATH
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+	/*
+	 * The linker can't handle this by relocation.  Manually set
+	 * base address in stack canary segment descriptor.
+	 */
+	movl $per_cpu__gdt_page,%eax
+	movl $per_cpu__stack_canary,%ecx
+	movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
+	shrl $16, %ecx
+	movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
+	movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax)
+#endif
+
+	# %esi still points to start_info, and no registers
+	# need to be preserved.
+
+	movl XEN_START_mfn_list(%esi), %ebx
+	movl $(per_cpu__gdt_page - __PAGE_OFFSET), %eax
+	shrl $PAGE_SHIFT, %eax
+	movl (%ebx,%eax,4), %ecx
+	pushl %ecx			# frame number for set_gdt below
+
+	xorl %esi, %esi
+	xorl %edx, %edx
+	shldl $PAGE_SHIFT, %ecx, %edx
+	shll $PAGE_SHIFT, %ecx
+	orl $_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY, %ecx
+	movl $per_cpu__gdt_page, %ebx
+	movl $__HYPERVISOR_update_va_mapping, %eax
+	int $0x82
+
+	movl $(PAGE_SIZE_asm / 8), %ecx
+	movl %esp, %ebx
+	movl $__HYPERVISOR_set_gdt, %eax
+	int $0x82
+
+	popl %ecx
+
+	movl $(__KERNEL_PERCPU), %eax
+	movl %eax,%fs			# set this cpu's percpu
+
+	movl $(__KERNEL_STACK_CANARY),%eax
+	movl %eax,%gs
+
+	cld			# gcc2 wants the direction flag cleared at all times
+
+	pushl $0		# fake return address for unwinder
+	jmp i386_start_kernel
+
+#define HYPERCALL_PAGE_OFFSET 0x1000
+.org HYPERCALL_PAGE_OFFSET
+ENTRY(hypercall_page)
+	CFI_STARTPROC
+.skip 0x1000
+	CFI_ENDPROC
+
+/*
+ * BSS section
+ */
+__PAGE_ALIGNED_BSS
+	.align PAGE_SIZE_asm
+ENTRY(swapper_pg_fixmap)
+	.fill 1024,4,0
+ENTRY(empty_zero_page)
+	.fill 4096,1,0
+
+/*
+ * This starts the data section.
+ */
+.data
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+/*
+ * __xen_guest information
+ */
+.macro utoa value
+ .if (\value) < 0 || (\value) >= 0x10
+	utoa (((\value)>>4)&0x0fffffff)
+ .endif
+ .if ((\value) & 0xf) < 10
+  .byte '0' + ((\value) & 0xf)
+ .else
+  .byte 'A' + ((\value) & 0xf) - 10
+ .endif
+.endm
+
+.section __xen_guest
+	.ascii	"GUEST_OS=linux,GUEST_VER=2.6"
+	.ascii	",XEN_VER=xen-3.0"
+	.ascii	",VIRT_BASE=0x"
+		utoa __PAGE_OFFSET
+	.ascii	",ELF_PADDR_OFFSET=0x"
+		utoa __PAGE_OFFSET
+	.ascii	",VIRT_ENTRY=0x"
+		utoa (__PAGE_OFFSET + LOAD_PHYSICAL_ADDR + VIRT_ENTRY_OFFSET)
+	.ascii	",HYPERCALL_PAGE=0x"
+		utoa ((LOAD_PHYSICAL_ADDR+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT)
+	.ascii  ",FEATURES=writable_page_tables"
+	.ascii	         "|writable_descriptor_tables"
+	.ascii	         "|auto_translated_physmap"
+	.ascii	         "|pae_pgdir_above_4gb"
+	.ascii	         "|supervisor_mode_kernel"
+#ifdef CONFIG_X86_PAE
+	.ascii	",PAE=yes[extended-cr3]"
+#else
+	.ascii	",PAE=no"
+#endif
+	.ascii	",LOADER=generic"
+	.byte	0
+#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
+
+
+	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
+	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
+	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
+	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long __PAGE_OFFSET)
+#if CONFIG_XEN_COMPAT <= 0x030002
+	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long __PAGE_OFFSET)
+#else
+	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long 0)
+#endif
+	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long startup_32)
+	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long hypercall_page)
+	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long HYPERVISOR_VIRT_START)
+	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
+#ifdef CONFIG_X86_PAE
+	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
+	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad _PAGE_PRESENT, _PAGE_PRESENT)
+#else
+	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "no")
+	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .long _PAGE_PRESENT, _PAGE_PRESENT)
+#endif
+	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
+	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/entry_64-xen.S
+++ linux-ec2-2.6.32/arch/x86/kernel/entry_64-xen.S
@@ -0,0 +1,1440 @@
+/*
+ *  linux/arch/x86_64/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
+ *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
+ *  Jun Nakajima <jun.nakajima@intel.com>
+ *  Asit Mallick <asit.k.mallick@intel.com>
+ *      Modified for Xen
+ */
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after an interrupt and after each system call.
+ *
+ * Normal syscalls and interrupts don't save a full stack frame, this is
+ * only done for syscall tracing, signals or fork/exec et.al.
+ *
+ * A note on terminology:
+ * - top of stack: Architecture defined interrupt frame from SS to RIP
+ * at the top of the kernel process stack.
+ * - partial stack frame: partially saved registers upto R11.
+ * - full stack frame: Like partial stack frame, but all register saved.
+ *
+ * Some macro usage:
+ * - CFI macros are used to generate dwarf2 unwind information for better
+ * backtraces. They don't change any code.
+ * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
+ * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
+ * There are unfortunately lots of special cases where some registers
+ * not touched. The macro is a big mess that should be cleaned up.
+ * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
+ * Gives a full stack frame.
+ * - ENTRY/END Define functions in the symbol table.
+ * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
+ * frame that is otherwise undefined after a SYSCALL
+ * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
+ * - errorentry/paranoidentry/zeroentry - Define exception entry points.
+ */
+
+#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <asm/segment.h>
+#include <asm/cache.h>
+#include <asm/errno.h>
+#include <asm/dwarf2.h>
+#include <asm/calling.h>
+#include <asm/asm-offsets.h>
+#include <asm/msr.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/hw_irq.h>
+#include <asm/page_types.h>
+#include <asm/irqflags.h>
+#include <asm/processor-flags.h>
+#include <asm/ftrace.h>
+#include <asm/percpu.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/features.h>
+
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_64BIT 0x80000000
+#define __AUDIT_ARCH_LE	   0x40000000
+
+	.code64
+#ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+ENTRY(mcount)
+	retq
+END(mcount)
+
+ENTRY(ftrace_caller)
+	cmpl $0, function_trace_stop
+	jne  ftrace_stub
+
+	MCOUNT_SAVE_FRAME
+
+	movq 0x38(%rsp), %rdi
+	movq 8(%rbp), %rsi
+	subq $MCOUNT_INSN_SIZE, %rdi
+
+GLOBAL(ftrace_call)
+	call ftrace_stub
+
+	MCOUNT_RESTORE_FRAME
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+GLOBAL(ftrace_graph_call)
+	jmp ftrace_stub
+#endif
+
+GLOBAL(ftrace_stub)
+	retq
+END(ftrace_caller)
+
+#else /* ! CONFIG_DYNAMIC_FTRACE */
+ENTRY(mcount)
+	cmpl $0, function_trace_stop
+	jne  ftrace_stub
+
+	cmpq $ftrace_stub, ftrace_trace_function
+	jnz trace
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	cmpq $ftrace_stub, ftrace_graph_return
+	jnz ftrace_graph_caller
+
+	cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
+	jnz ftrace_graph_caller
+#endif
+
+GLOBAL(ftrace_stub)
+	retq
+
+trace:
+	MCOUNT_SAVE_FRAME
+
+	movq 0x38(%rsp), %rdi
+	movq 8(%rbp), %rsi
+	subq $MCOUNT_INSN_SIZE, %rdi
+
+	call   *ftrace_trace_function
+
+	MCOUNT_RESTORE_FRAME
+
+	jmp ftrace_stub
+END(mcount)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+	cmpl $0, function_trace_stop
+	jne ftrace_stub
+
+	MCOUNT_SAVE_FRAME
+
+	leaq 8(%rbp), %rdi
+	movq 0x38(%rsp), %rsi
+	movq (%rbp), %rdx
+	subq $MCOUNT_INSN_SIZE, %rsi
+
+	call	prepare_ftrace_return
+
+	MCOUNT_RESTORE_FRAME
+
+	retq
+END(ftrace_graph_caller)
+
+GLOBAL(return_to_handler)
+	subq  $24, %rsp
+
+	/* Save the return values */
+	movq %rax, (%rsp)
+	movq %rdx, 8(%rsp)
+	movq %rbp, %rdi
+
+	call ftrace_return_to_handler
+
+	movq %rax, 16(%rsp)
+	movq 8(%rsp), %rdx
+	movq (%rsp), %rax
+	addq $16, %rsp
+	retq
+#endif
+
+
+#ifndef CONFIG_PREEMPT
+#define retint_kernel retint_restore_args
+#endif
+
+#ifdef CONFIG_PARAVIRT
+ENTRY(native_usergs_sysret64)
+	swapgs
+	sysretq
+ENDPROC(native_usergs_sysret64)
+#endif /* CONFIG_PARAVIRT */
+
+
+.macro TRACE_IRQS_IRETQ offset=ARGOFFSET
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bt   $9,EFLAGS-\offset(%rsp)	/* interrupts off? */
+	jnc  1f
+	TRACE_IRQS_ON
+1:
+#endif
+.endm
+
+NMI_MASK = 0x80000000
+	
+/*
+ * C code is not supposed to know about undefined top of stack. Every time
+ * a C function with an pt_regs argument is called from the SYSCALL based
+ * fast path FIXUP_TOP_OF_STACK is needed.
+ * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
+ * manipulation.
+ */
+
+	/* %rsp:at FRAMEEND */
+	.macro FIXUP_TOP_OF_STACK tmp offset=0
+	movq $__USER_CS,CS+\offset(%rsp)
+	movq $-1,RCX+\offset(%rsp)
+	.endm
+
+	.macro RESTORE_TOP_OF_STACK tmp offset=0
+	.endm
+
+	.macro FAKE_STACK_FRAME child_rip
+	/* push in order ss, rsp, eflags, cs, rip */
+	xorl %eax, %eax
+	pushq $__KERNEL_DS /* ss */
+	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	ss,0*/
+	pushq %rax /* rsp */
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rsp,0
+	pushq $X86_EFLAGS_IF /* eflags - interrupts on */
+	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	rflags,0*/
+	pushq $__KERNEL_CS /* cs */
+	CFI_ADJUST_CFA_OFFSET	8
+	/*CFI_REL_OFFSET	cs,0*/
+	pushq \child_rip /* rip */
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rip,0
+	pushq	%rax /* orig rax */
+	CFI_ADJUST_CFA_OFFSET	8
+	.endm
+
+	.macro UNFAKE_STACK_FRAME
+	addq $8*6, %rsp
+	CFI_ADJUST_CFA_OFFSET	-(6*8)
+	.endm
+
+/*
+ * initial frame state for interrupts (and exceptions without error code)
+ */
+	.macro EMPTY_FRAME offset=0
+	CFI_STARTPROC simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA rsp,\offset
+	.endm
+
+/*
+ * initial frame state for syscall
+ */
+	.macro BASIC_FRAME start=1 offset=0
+	.if \start
+	EMPTY_FRAME __stringify(SS+8+\offset-RIP)
+	.else
+	CFI_DEF_CFA_OFFSET SS+8+\offset-RIP
+	.endif
+	/*CFI_REL_OFFSET ss, SS+\offset-RIP*/
+	CFI_REL_OFFSET rsp, RSP+\offset-RIP
+	/*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/
+	/*CFI_REL_OFFSET cs, CS+\offset-RIP*/
+	CFI_REL_OFFSET rip, RIP+\offset-RIP
+	.endm
+
+/*
+ * initial frame state for interrupts (and exceptions without error code)
+ */
+	.macro INTR_FRAME start=1 offset=0
+	.if \start == 1
+	BASIC_FRAME 1, \offset+2*8
+	CFI_REL_OFFSET rcx, 0+\offset
+	CFI_REL_OFFSET r11, 8+\offset
+	.else
+	BASIC_FRAME \start, \offset
+	.endif
+	.endm
+
+/*
+ * initial frame state for exceptions with error code (and interrupts
+ * with vector already pushed)
+ */
+	.macro XCPT_FRAME start=1 offset=0
+	INTR_FRAME \start, __stringify(RIP+\offset-ORIG_RAX)
+	.endm
+
+/*
+ * frame that enables calling into C.
+ */
+	.macro PARTIAL_FRAME start=1 offset=0
+	.if \start >= 0
+	XCPT_FRAME 2*\start, __stringify(ORIG_RAX+\offset-ARGOFFSET)
+	.endif
+	CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
+	CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
+	CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
+	CFI_REL_OFFSET rcx, RCX+\offset-ARGOFFSET
+	CFI_REL_OFFSET rax, RAX+\offset-ARGOFFSET
+	CFI_REL_OFFSET r8, R8+\offset-ARGOFFSET
+	CFI_REL_OFFSET r9, R9+\offset-ARGOFFSET
+	CFI_REL_OFFSET r10, R10+\offset-ARGOFFSET
+	CFI_REL_OFFSET r11, R11+\offset-ARGOFFSET
+	.endm
+
+/*
+ * frame that enables passing a complete pt_regs to a C function.
+ */
+	.macro DEFAULT_FRAME start=1 offset=0
+	.if \start >= -1
+	PARTIAL_FRAME \start, __stringify(R11+\offset-R15)
+	.endif
+	CFI_REL_OFFSET rbx, RBX+\offset
+	CFI_REL_OFFSET rbp, RBP+\offset
+	CFI_REL_OFFSET r12, R12+\offset
+	CFI_REL_OFFSET r13, R13+\offset
+	CFI_REL_OFFSET r14, R14+\offset
+	CFI_REL_OFFSET r15, R15+\offset
+	.endm
+
+        /*
+         * Must be consistent with the definition in arch-x86/xen-x86_64.h:
+         *     struct iret_context {
+         *        u64 rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+         *     };
+         * with rax, r11, and rcx being taken care of in the hypercall stub.
+         */
+	.macro HYPERVISOR_IRET flag
+	testb $3,1*8(%rsp)
+	jnz   2f
+	testl $NMI_MASK,2*8(%rsp)
+	jnz   2f
+
+	cmpb  $0,(xen_features+XENFEAT_supervisor_mode_kernel)(%rip)
+	jne   1f
+
+	/* Direct iret to kernel space. Correct CS and SS. */
+	orl   $3,1*8(%rsp)
+	orl   $3,4*8(%rsp)
+1:	iretq
+
+2:	/* Slow iret via hypervisor. */
+	andl  $~NMI_MASK, 2*8(%rsp)
+	pushq $\flag
+	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+	.endm
+
+#ifndef CONFIG_XEN
+/* save partial stack frame */
+ENTRY(save_args)
+	XCPT_FRAME offset=__stringify(ORIG_RAX-ARGOFFSET+16)
+	cld
+	movq %rdi, RDI+16-ARGOFFSET(%rsp)
+	movq %rsi, RSI+16-ARGOFFSET(%rsp)
+	movq %rdx, RDX+16-ARGOFFSET(%rsp)
+	movq %rcx, RCX+16-ARGOFFSET(%rsp)
+	movq_cfi rax, __stringify(RAX+16-ARGOFFSET)
+	movq  %r8,  R8+16-ARGOFFSET(%rsp)
+	movq  %r9,  R9+16-ARGOFFSET(%rsp)
+	movq %r10, R10+16-ARGOFFSET(%rsp)
+	movq_cfi r11, __stringify(R11+16-ARGOFFSET)
+
+	leaq -ARGOFFSET+16(%rsp),%rdi	/* arg1 for handler */
+	movq_cfi rbp, 8		/* push %rbp */
+	leaq 8(%rsp), %rbp		/* mov %rsp, %ebp */
+	CFI_DEF_CFA_REGISTER rbp
+	CFI_ADJUST_CFA_OFFSET -8
+	testl $3, CS(%rdi)
+	je 1f
+	SWAPGS
+	/*
+	 * irq_count is used to check if a CPU is already on an interrupt stack
+	 * or not. While this is essentially redundant with preempt_count it is
+	 * a little cheaper to use a separate counter in the PDA (short of
+	 * moving irq_enter into assembly, which would be too much work)
+	 */
+1:	incl PER_CPU_VAR(irq_count)
+	jne 2f
+	popq %rax			/* move return address... */
+	mov PER_CPU_VAR(irq_stack_ptr),%rsp
+	pushq %rbp			/* backlink for unwinder */
+	pushq %rax			/* ... to the new stack */
+	/*
+	 * We entered an interrupt context - irqs are off:
+	 */
+2:	TRACE_IRQS_OFF
+	ret
+	CFI_ENDPROC
+END(save_args)
+#endif
+
+ENTRY(save_rest)
+	CFI_STARTPROC
+	movq 5*8+16(%rsp), %r11	/* save return address */
+	movq %rbx, RBX+16(%rsp)
+	movq %rbp, RBP+16(%rsp)
+	movq %r12, R12+16(%rsp)
+	movq %r13, R13+16(%rsp)
+	movq %r14, R14+16(%rsp)
+	movq %r15, R15+16(%rsp)
+	movq %r11, 8(%rsp)	/* return address */
+	FIXUP_TOP_OF_STACK %r11, 16
+	ret
+	CFI_ENDPROC
+END(save_rest)
+
+#ifndef CONFIG_XEN
+/* save complete stack frame */
+	.pushsection .kprobes.text, "ax"
+ENTRY(save_paranoid)
+	XCPT_FRAME offset=__stringify(ORIG_RAX-R15+8)
+	cld
+	movq %rdi, RDI+8(%rsp)
+	movq %rsi, RSI+8(%rsp)
+	movq_cfi rdx, __stringify(RDX+8)
+	movq_cfi rcx, __stringify(RCX+8)
+	movq_cfi rax, __stringify(RAX+8)
+	movq %r8, R8+8(%rsp)
+	movq %r9, R9+8(%rsp)
+	movq %r10, R10+8(%rsp)
+	movq %r11, R11+8(%rsp)
+	movq_cfi rbx, __stringify(RBX+8)
+	movq %rbp, RBP+8(%rsp)
+	movq %r12, R12+8(%rsp)
+	movq %r13, R13+8(%rsp)
+	movq %r14, R14+8(%rsp)
+	movq %r15, R15+8(%rsp)
+	movl $1,%ebx
+	movl $MSR_GS_BASE,%ecx
+	rdmsr
+	testl %edx,%edx
+	js 1f	/* negative -> in kernel */
+	SWAPGS
+	xorl %ebx,%ebx
+1:	ret
+	CFI_ENDPROC
+END(save_paranoid)
+	.popsection
+#endif
+
+/*
+ * A newly forked process directly context switches into this address.
+ *
+ * rdi: prev task we switched from
+ */
+ENTRY(ret_from_fork)
+	DEFAULT_FRAME
+
+	LOCK ; btr $TIF_FORK,TI_flags(%r8)
+
+	push kernel_eflags(%rip)
+	CFI_ADJUST_CFA_OFFSET 8
+	popf					# reset kernel eflags
+	CFI_ADJUST_CFA_OFFSET -8
+
+	call schedule_tail			# rdi: 'prev' task parameter
+
+	GET_THREAD_INFO(%rcx)
+
+	RESTORE_REST
+
+	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
+	je   int_ret_from_sys_call
+
+	testl $_TIF_IA32, TI_flags(%rcx)	# 32-bit compat task needs IRET
+	jnz  int_ret_from_sys_call
+
+	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
+	jmp ret_from_sys_call			# go to the SYSRET fastpath
+
+	CFI_ENDPROC
+END(ret_from_fork)
+
+/*
+ * System call entry. Upto 6 arguments in registers are supported.
+ *
+ * SYSCALL does not save anything on the stack and does not change the
+ * stack pointer.
+ */
+
+/*
+ * Register setup:
+ * rax  system call number
+ * rdi  arg0
+ * rcx  return address for syscall/sysret, C arg3
+ * rsi  arg1
+ * rdx  arg2
+ * r10  arg3 	(--> moved to rcx for C)
+ * r8   arg4
+ * r9   arg5
+ * r11  eflags for syscall/sysret, temporary for C
+ * r12-r15,rbp,rbx saved by C code, not touched.
+ *
+ * Interrupts are enabled on entry.
+ * Only called from user space.
+ *
+ * XXX	if we had a free scratch register we could save the RSP into the stack frame
+ *      and report it properly in ps. Unfortunately we haven't.
+ *
+ * When user can change the frames always force IRET. That is because
+ * it deals with uncanonical addresses better. SYSRET has trouble
+ * with them due to bugs in both AMD and Intel CPUs.
+ */
+
+ENTRY(system_call)
+	INTR_FRAME start=2 offset=2*8
+	SAVE_ARGS -8,0
+	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
+	GET_THREAD_INFO(%rcx)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+	jnz tracesys
+system_call_fastpath:
+	cmpq $__NR_syscall_max,%rax
+	ja badsys
+	movq %r10,%rcx
+	call *sys_call_table(,%rax,8)  # XXX:	 rip relative
+	movq %rax,RAX-ARGOFFSET(%rsp)
+/*
+ * Syscall return path ending with SYSRET (fast path)
+ * Has incomplete stack frame and undefined top of stack.
+ */
+ret_from_sys_call:
+	movl $_TIF_ALLWORK_MASK,%edi
+	/* edi:	flagmask */
+sysret_check:
+	LOCKDEP_SYS_EXIT
+	GET_THREAD_INFO(%rcx)
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	movl TI_flags(%rcx),%edx
+	andl %edi,%edx
+	jnz  sysret_careful
+	CFI_REMEMBER_STATE
+	/*
+	 * sysretq will re-enable interrupts:
+	 */
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	RESTORE_ARGS 0,8,0
+        HYPERVISOR_IRET VGCF_IN_SYSCALL
+
+	CFI_RESTORE_STATE
+	/* Handle reschedules */
+	/* edx:	work, edi: workmask */
+sysret_careful:
+	bt $TIF_NEED_RESCHED,%edx
+	jnc sysret_signal
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
+	call schedule
+	popq  %rdi
+	CFI_ADJUST_CFA_OFFSET -8
+	jmp sysret_check
+
+	/* Handle a signal */
+sysret_signal:
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+#ifdef CONFIG_AUDITSYSCALL
+	bt $TIF_SYSCALL_AUDIT,%edx
+	jc sysret_audit
+#endif
+	/*
+	 * We have a signal, or exit tracing or single-step.
+	 * These all wind up with the iret return path anyway,
+	 * so just join that path right now.
+	 */
+	FIXUP_TOP_OF_STACK %r11, -ARGOFFSET
+	jmp int_check_syscall_exit_work
+
+badsys:
+	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+	jmp ret_from_sys_call
+
+#ifdef CONFIG_AUDITSYSCALL
+	/*
+	 * Fast path for syscall audit without full syscall trace.
+	 * We just call audit_syscall_entry() directly, and then
+	 * jump back to the normal fast path.
+	 */
+auditsys:
+	movq %r10,%r9			/* 6th arg: 4th syscall arg */
+	movq %rdx,%r8			/* 5th arg: 3rd syscall arg */
+	movq %rsi,%rcx			/* 4th arg: 2nd syscall arg */
+	movq %rdi,%rdx			/* 3rd arg: 1st syscall arg */
+	movq %rax,%rsi			/* 2nd arg: syscall number */
+	movl $AUDIT_ARCH_X86_64,%edi	/* 1st arg: audit arch */
+	call audit_syscall_entry
+	LOAD_ARGS 0		/* reload call-clobbered registers */
+	jmp system_call_fastpath
+
+	/*
+	 * Return fast path for syscall audit.  Call audit_syscall_exit()
+	 * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
+	 * masked off.
+	 */
+sysret_audit:
+	movq %rax,%rsi		/* second arg, syscall return value */
+	cmpq $0,%rax		/* is it < 0? */
+	setl %al		/* 1 if so, 0 if not */
+	movzbl %al,%edi		/* zero-extend that into %edi */
+	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+	call audit_syscall_exit
+	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+	jmp sysret_check
+#endif	/* CONFIG_AUDITSYSCALL */
+
+	/* Do syscall tracing */
+tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+	jz auditsys
+#endif
+	SAVE_REST
+	movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
+	FIXUP_TOP_OF_STACK %rdi
+	movq %rsp,%rdi
+	call syscall_trace_enter
+	/*
+	 * Reload arg registers from stack in case ptrace changed them.
+	 * We don't reload %rax because syscall_trace_enter() returned
+	 * the value it wants us to use in the table lookup.
+	 */
+	LOAD_ARGS ARGOFFSET, 1
+	RESTORE_REST
+	cmpq $__NR_syscall_max,%rax
+	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
+	movq %r10,%rcx	/* fixup for C */
+	call *sys_call_table(,%rax,8)
+	movq %rax,RAX-ARGOFFSET(%rsp)
+	/* Use IRET because user could have changed frame */
+
+/*
+ * Syscall return path ending with IRET.
+ * Has correct top of stack, but partial stack frame.
+ */
+GLOBAL(int_ret_from_sys_call)
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	testb $3,CS-ARGOFFSET(%rsp)
+        jnz 1f
+        /* Need to set the proper %ss (not NULL) for ring 3 iretq */
+        movl $__KERNEL_DS,SS-ARGOFFSET(%rsp)
+        jmp retint_restore_args   # retrun from ring3 kernel
+1:              
+	movl $_TIF_ALLWORK_MASK,%edi
+	/* edi:	mask to check */
+GLOBAL(int_with_check)
+	LOCKDEP_SYS_EXIT_IRQ
+	GET_THREAD_INFO(%rcx)
+	movl TI_flags(%rcx),%edx
+	andl %edi,%edx
+	jnz   int_careful
+	andl    $~TS_COMPAT,TI_status(%rcx)
+	jmp   retint_restore_args
+
+	/* Either reschedule or signal or syscall exit tracking needed. */
+	/* First do a reschedule test. */
+	/* edx:	work, edi: workmask */
+int_careful:
+	bt $TIF_NEED_RESCHED,%edx
+	jnc  int_very_careful
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
+	call schedule
+	popq %rdi
+	CFI_ADJUST_CFA_OFFSET -8
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	jmp int_with_check
+
+	/* handle signals and tracing -- both require a full stack frame */
+int_very_careful:
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+int_check_syscall_exit_work:
+	SAVE_REST
+	/* Check for syscall exit trace */
+	testl $_TIF_WORK_SYSCALL_EXIT,%edx
+	jz int_signal
+	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET 8
+	leaq 8(%rsp),%rdi	# &ptregs -> arg1
+	call syscall_trace_leave
+	popq %rdi
+	CFI_ADJUST_CFA_OFFSET -8
+	andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
+	jmp int_restore_rest
+
+int_signal:
+	testl $_TIF_DO_NOTIFY_MASK,%edx
+	jz 1f
+	movq %rsp,%rdi		# &ptregs -> arg1
+	xorl %esi,%esi		# oldset -> arg2
+	call do_notify_resume
+1:	movl $_TIF_WORK_MASK,%edi
+int_restore_rest:
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	jmp int_with_check
+	CFI_ENDPROC
+END(system_call)
+
+/*
+ * Certain special system calls that need to save a complete full stack frame.
+ */
+	.macro PTREGSCALL label,func,arg
+ENTRY(\label)
+	PARTIAL_FRAME 1 8		/* offset 8: return address */
+	subq $REST_SKIP, %rsp
+	CFI_ADJUST_CFA_OFFSET REST_SKIP
+	call save_rest
+	DEFAULT_FRAME -2 8		/* offset 8: return address */
+	leaq 8(%rsp), \arg	/* pt_regs pointer */
+	call \func
+	jmp ptregscall_common
+	CFI_ENDPROC
+END(\label)
+	.endm
+
+	PTREGSCALL stub_clone, sys_clone, %r8
+	PTREGSCALL stub_fork, sys_fork, %rdi
+	PTREGSCALL stub_vfork, sys_vfork, %rdi
+	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
+	PTREGSCALL stub_iopl, sys_iopl, %rsi
+
+ENTRY(ptregscall_common)
+	DEFAULT_FRAME 1 8	/* offset 8: return address */
+	RESTORE_TOP_OF_STACK %r11, 8
+	movq_cfi_restore __stringify(R15+8), r15
+	movq_cfi_restore __stringify(R14+8), r14
+	movq_cfi_restore __stringify(R13+8), r13
+	movq_cfi_restore __stringify(R12+8), r12
+	movq_cfi_restore __stringify(RBP+8), rbp
+	movq_cfi_restore __stringify(RBX+8), rbx
+	ret $REST_SKIP		/* pop extended registers */
+	CFI_ENDPROC
+END(ptregscall_common)
+
+ENTRY(stub_execve)
+	CFI_STARTPROC
+	popq %r11
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_REGISTER rip, r11
+	SAVE_REST
+	FIXUP_TOP_OF_STACK %r11
+	movq %rsp, %rcx
+	call sys_execve
+	RESTORE_TOP_OF_STACK %r11
+	movq %rax,RAX(%rsp)
+	RESTORE_REST
+	jmp int_ret_from_sys_call
+	CFI_ENDPROC
+END(stub_execve)
+
+/*
+ * sigreturn is special because it needs to restore all registers on return.
+ * This cannot be done with SYSRET, so use the IRET return path instead.
+ */
+ENTRY(stub_rt_sigreturn)
+	CFI_STARTPROC
+	addq $8, %rsp
+	CFI_ADJUST_CFA_OFFSET	-8
+	SAVE_REST
+	movq %rsp,%rdi
+	FIXUP_TOP_OF_STACK %r11
+	call sys_rt_sigreturn
+	movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
+	RESTORE_REST
+	jmp int_ret_from_sys_call
+	CFI_ENDPROC
+END(stub_rt_sigreturn)
+
+/*
+ * Interrupt exit.
+ */ 
+
+retint_with_reschedule:
+	PARTIAL_FRAME
+	movl $_TIF_WORK_MASK,%edi
+retint_check:
+	LOCKDEP_SYS_EXIT_IRQ
+	movl TI_flags(%rcx),%edx
+	andl %edi,%edx
+	CFI_REMEMBER_STATE
+	jnz  retint_careful
+retint_restore_args:	/* return to kernel space */
+	movl EFLAGS-REST_SKIP(%rsp), %eax
+	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
+	GET_VCPU_INFO
+	andb evtchn_upcall_mask(%rsi),%al
+	andb $1,%al			# EAX[0] == IRET_EFLAGS.IF & event_mask
+	jnz restore_all_enable_events	#        != 0 => enable event delivery
+		
+	RESTORE_ARGS 0,8,0
+	HYPERVISOR_IRET 0
+	
+	/* edi: workmask, edx: work */
+retint_careful:
+	CFI_RESTORE_STATE
+	bt    $TIF_NEED_RESCHED,%edx
+	jnc   retint_signal
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	pushq %rdi
+	CFI_ADJUST_CFA_OFFSET	8
+	call  schedule
+	popq %rdi
+	CFI_ADJUST_CFA_OFFSET	-8
+	GET_THREAD_INFO(%rcx)
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	jmp retint_check
+
+retint_signal:
+	testl $_TIF_DO_NOTIFY_MASK,%edx
+	jz    retint_restore_args
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	SAVE_REST
+	movq $-1,ORIG_RAX(%rsp)
+	xorl %esi,%esi		# oldset
+	movq %rsp,%rdi		# &pt_regs
+	call do_notify_resume
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	jmp retint_with_reschedule
+
+#ifdef CONFIG_PREEMPT
+	/* Returning to kernel space. Check if we need preemption */
+	/* rcx:	 threadinfo. interrupts off. */
+ENTRY(retint_kernel)
+	cmpl $0,TI_preempt_count(%rcx)
+	jnz  retint_restore_args
+	bt  $TIF_NEED_RESCHED,TI_flags(%rcx)
+	jnc  retint_restore_args
+	bt   $9,EFLAGS-ARGOFFSET(%rsp)	/* interrupts off? */
+	jnc  retint_restore_args
+	call preempt_schedule_irq
+	jmp retint_kernel       /* check again */
+#endif
+
+	CFI_ENDPROC
+END(retint_check)
+
+#ifndef CONFIG_XEN
+/*
+ * APIC interrupts.
+ */
+.macro apicinterrupt num sym do_sym
+ENTRY(\sym)
+	INTR_FRAME
+	pushq $~(\num)
+	CFI_ADJUST_CFA_OFFSET 8
+	interrupt \do_sym
+	jmp error_entry
+	CFI_ENDPROC
+END(\sym)
+.endm
+
+#ifdef CONFIG_SMP
+apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
+	irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
+apicinterrupt REBOOT_VECTOR \
+	reboot_interrupt smp_reboot_interrupt
+#endif
+
+#ifdef CONFIG_X86_UV
+apicinterrupt UV_BAU_MESSAGE \
+	uv_bau_message_intr1 uv_bau_message_interrupt
+#endif
+apicinterrupt LOCAL_TIMER_VECTOR \
+	apic_timer_interrupt smp_apic_timer_interrupt
+apicinterrupt GENERIC_INTERRUPT_VECTOR \
+	generic_interrupt smp_generic_interrupt
+
+#ifdef CONFIG_SMP
+apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
+	invalidate_interrupt0 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+1 \
+	invalidate_interrupt1 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+2 \
+	invalidate_interrupt2 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+3 \
+	invalidate_interrupt3 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+4 \
+	invalidate_interrupt4 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+5 \
+	invalidate_interrupt5 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+6 \
+	invalidate_interrupt6 smp_invalidate_interrupt
+apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
+	invalidate_interrupt7 smp_invalidate_interrupt
+#endif
+
+apicinterrupt THRESHOLD_APIC_VECTOR \
+	threshold_interrupt smp_threshold_interrupt
+apicinterrupt THERMAL_APIC_VECTOR \
+	thermal_interrupt smp_thermal_interrupt
+
+#ifdef CONFIG_X86_MCE
+apicinterrupt MCE_SELF_VECTOR \
+	mce_self_interrupt smp_mce_self_interrupt
+#endif
+
+#ifdef CONFIG_SMP
+apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
+	call_function_single_interrupt smp_call_function_single_interrupt
+apicinterrupt CALL_FUNCTION_VECTOR \
+	call_function_interrupt smp_call_function_interrupt
+apicinterrupt RESCHEDULE_VECTOR \
+	reschedule_interrupt smp_reschedule_interrupt
+#endif
+
+apicinterrupt ERROR_APIC_VECTOR \
+	error_interrupt smp_error_interrupt
+apicinterrupt SPURIOUS_APIC_VECTOR \
+	spurious_interrupt smp_spurious_interrupt
+
+#ifdef CONFIG_PERF_EVENTS
+apicinterrupt LOCAL_PENDING_VECTOR \
+	perf_pending_interrupt smp_perf_pending_interrupt
+#endif
+#endif /* !CONFIG_XEN */
+
+/*
+ * Exception entry points.
+ */
+.macro zeroentry sym do_sym
+ENTRY(\sym)
+	INTR_FRAME
+        movq (%rsp),%rcx
+	CFI_RESTORE rcx
+        movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	movq $-1,8(%rsp)	/* ORIG_RAX: no syscall to restart */
+	subq $ORIG_RAX-R15-8, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15-8
+	call error_entry
+	DEFAULT_FRAME -1
+	movq %rsp,%rdi		/* pt_regs pointer */
+	xorl %esi,%esi		/* no error code */
+	call \do_sym
+	jmp error_exit		/* %ebx: no swapgs flag */
+	CFI_ENDPROC
+END(\sym)
+.endm
+
+.macro paranoidzeroentry sym do_sym
+	zeroentry \sym \do_sym
+.endm
+
+.macro paranoidzeroentry_ist sym do_sym ist
+	zeroentry \sym \do_sym
+.endm
+
+.macro errorentry sym do_sym
+ENTRY(\sym)
+	XCPT_FRAME
+        movq (%rsp),%rcx
+	CFI_RESTORE rcx
+        movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	subq $ORIG_RAX-R15-2*8, %rsp
+	CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15-2*8
+	call error_entry
+	DEFAULT_FRAME -1
+	movq %rsp,%rdi			/* pt_regs pointer */
+	movq ORIG_RAX(%rsp),%rsi	/* get error code */
+	movq $-1,ORIG_RAX(%rsp)		/* no syscall to restart */
+	call \do_sym
+	jmp error_exit			/* %ebx: no swapgs flag */
+	CFI_ENDPROC
+END(\sym)
+.endm
+
+	/* error code is on the stack already */
+.macro paranoiderrorentry sym do_sym
+	errorentry \sym \do_sym
+.endm
+
+/*
+ * Copied from arch/xen/i386/kernel/entry.S
+ */               
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
+# until we've done all processing. HOWEVER, we must enable events before
+# popping the stack frame (can't be done atomically) and so it would still
+# be possible to get enough handler activations to overflow the stack.
+# Although unlikely, bugs of that kind are hard to track down, so we'd
+# like to avoid the possibility.
+# So, on entry to the handler we detect whether we interrupted an
+# existing activation in its critical region -- if so, we pop the current
+# activation and restart the handler using the previous one.
+ENTRY(do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
+	CFI_STARTPROC
+# Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
+# see the correct pointer to the pt_regs
+	movq %rdi, %rsp            # we don't return, adjust the stack frame
+	CFI_ENDPROC
+	DEFAULT_FRAME
+11:	incl PER_CPU_VAR(irq_count)
+	movq %rsp,%rbp
+	CFI_DEF_CFA_REGISTER rbp
+	cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp
+	pushq %rbp			# backlink for old unwinder
+	call evtchn_do_upcall
+	popq %rsp
+	CFI_DEF_CFA_REGISTER rsp
+	decl PER_CPU_VAR(irq_count)
+	jmp  error_exit
+	CFI_ENDPROC
+END(do_hypervisor_callback)
+
+        ALIGN
+restore_all_enable_events:  
+	PARTIAL_FRAME
+	TRACE_IRQS_ON
+	__ENABLE_INTERRUPTS
+
+scrit:	/**** START OF CRITICAL REGION ****/
+	__TEST_PENDING
+	CFI_REMEMBER_STATE
+	jnz  14f			# process more events if necessary...
+        RESTORE_ARGS 0,8,0
+        HYPERVISOR_IRET 0
+        
+	CFI_RESTORE_STATE
+14:	__DISABLE_INTERRUPTS
+	SAVE_REST
+        movq %rsp,%rdi                  # set the argument again
+	jmp  11b
+	CFI_ENDPROC
+ecrit:  /**** END OF CRITICAL REGION ****/
+# At this point, unlike on x86-32, we don't do the fixup to simplify the 
+# code and the stack frame is more complex on x86-64.
+# When the kernel is interrupted in the critical section, the kernel 
+# will do IRET in that case, and everything will be restored at that point, 
+# i.e. it just resumes from the next instruction interrupted with the same context. 
+
+# Hypervisor uses this for application faults while it executes.
+# We get here for two reasons:
+#  1. Fault while reloading DS, ES, FS or GS
+#  2. Fault while executing IRET
+# Category 1 we do not need to fix up as Xen has already reloaded all segment
+# registers that could be reloaded and zeroed the others.
+# Category 2 we fix up by killing the current process. We cannot use the
+# normal Linux return path in this case because if we use the IRET hypercall
+# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
+# We distinguish between categories by comparing each saved segment register
+# with its current contents: any discrepancy means we in category 1.
+ENTRY(failsafe_callback)
+	INTR_FRAME offset=4*8
+	movw %ds,%cx
+	cmpw %cx,0x10(%rsp)
+	CFI_REMEMBER_STATE
+	jne 1f
+	movw %es,%cx
+	cmpw %cx,0x18(%rsp)
+	jne 1f
+	movw %fs,%cx
+	cmpw %cx,0x20(%rsp)
+	jne 1f
+	movw %gs,%cx
+	cmpw %cx,0x28(%rsp)
+	jne 1f
+	/* All segments match their saved values => Category 2 (Bad IRET). */
+	movq (%rsp),%rcx
+	CFI_RESTORE rcx
+	movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	addq $0x30,%rsp
+	CFI_ADJUST_CFA_OFFSET -0x30
+	movq $11,%rdi	/* SIGSEGV */
+	jmp do_exit			
+	CFI_RESTORE_STATE
+1:	/* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
+	movq (%rsp),%rcx
+	CFI_RESTORE rcx
+	movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	addq $0x30,%rsp
+	CFI_ADJUST_CFA_OFFSET -0x30
+	pushq $0
+	CFI_ADJUST_CFA_OFFSET 8
+	SAVE_ALL
+	jmp error_exit
+	CFI_ENDPROC
+
+zeroentry divide_error do_divide_error
+zeroentry overflow do_overflow
+zeroentry bounds do_bounds
+zeroentry invalid_op do_invalid_op
+zeroentry device_not_available do_device_not_available
+zeroentry hypervisor_callback do_hypervisor_callback
+zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun
+errorentry invalid_TSS do_invalid_TSS
+errorentry segment_not_present do_segment_not_present
+zeroentry coprocessor_error do_coprocessor_error
+errorentry alignment_check do_alignment_check
+zeroentry simd_coprocessor_error do_simd_coprocessor_error
+	
+/*
+ * Create a kernel thread.
+ *
+ * C extern interface:
+ *	extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+ *
+ * asm input arguments:
+ *	rdi: fn, rsi: arg, rdx: flags
+ */
+ENTRY(kernel_thread)
+	CFI_STARTPROC
+	FAKE_STACK_FRAME $child_rip
+	SAVE_ALL
+
+	# rdi: flags, rsi: usp, rdx: will be &pt_regs
+	movq %rdx,%rdi
+	orq  kernel_thread_flags(%rip),%rdi
+	movq $-1, %rsi
+	movq %rsp, %rdx
+
+	xorl %r8d,%r8d
+	xorl %r9d,%r9d
+
+	# clone now
+	call do_fork
+	movq %rax,RAX(%rsp)
+	xorl %edi,%edi
+
+	/*
+	 * It isn't worth to check for reschedule here,
+	 * so internally to the x86_64 port you can rely on kernel_thread()
+	 * not to reschedule the child before returning, this avoids the need
+	 * of hacks for example to fork off the per-CPU idle tasks.
+	 * [Hopefully no generic code relies on the reschedule -AK]
+	 */
+	RESTORE_ALL
+	UNFAKE_STACK_FRAME
+	ret
+	CFI_ENDPROC
+END(kernel_thread)
+
+ENTRY(child_rip)
+	pushq $0		# fake return address
+	CFI_STARTPROC
+	/*
+	 * Here we are in the child and the registers are set as they were
+	 * at kernel_thread() invocation in the parent.
+	 */
+	movq %rdi, %rax
+	movq %rsi, %rdi
+	call *%rax
+	# exit
+	mov %eax, %edi
+	call do_exit
+	ud2			# padding for call trace
+	CFI_ENDPROC
+END(child_rip)
+
+/*
+ * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
+ *
+ * C extern interface:
+ *	 extern long execve(char *name, char **argv, char **envp)
+ *
+ * asm input arguments:
+ *	rdi: name, rsi: argv, rdx: envp
+ *
+ * We want to fallback into:
+ *	extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs)
+ *
+ * do_sys_execve asm fallback arguments:
+ *	rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
+ */
+ENTRY(kernel_execve)
+	CFI_STARTPROC
+	FAKE_STACK_FRAME $0
+	SAVE_ALL
+	movq %rsp,%rcx
+	call sys_execve
+	movq %rax, RAX(%rsp)
+	RESTORE_REST
+	testq %rax,%rax
+	jne 1f
+        jmp int_ret_from_sys_call
+1:      RESTORE_ARGS
+	UNFAKE_STACK_FRAME
+	ret
+	CFI_ENDPROC
+END(kernel_execve)
+
+/* Call softirq on interrupt stack. Interrupts are off. */
+ENTRY(call_softirq)
+	CFI_STARTPROC
+	push %rbp
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET rbp,0
+	mov  %rsp,%rbp
+	CFI_DEF_CFA_REGISTER rbp
+	incl PER_CPU_VAR(irq_count)
+	cmove PER_CPU_VAR(irq_stack_ptr),%rsp
+	push  %rbp			# backlink for old unwinder
+	call __do_softirq
+	leaveq
+	CFI_DEF_CFA_REGISTER	rsp
+	CFI_ADJUST_CFA_OFFSET   -8
+	decl PER_CPU_VAR(irq_count)
+	ret
+	CFI_ENDPROC
+END(call_softirq)
+
+#ifdef CONFIG_STACK_UNWIND
+ENTRY(arch_unwind_init_running)
+	CFI_STARTPROC
+	movq	%r15, R15(%rdi)
+	movq	%r14, R14(%rdi)
+	xchgq	%rsi, %rdx
+	movq	%r13, R13(%rdi)
+	movq	%r12, R12(%rdi)
+	xorl	%eax, %eax
+	movq	%rbp, RBP(%rdi)
+	movq	%rbx, RBX(%rdi)
+	movq	(%rsp), %r9
+	xchgq	%rdx, %rcx
+	movq	%rax, R11(%rdi)
+	movq	%rax, R10(%rdi)
+	movq	%rax, R9(%rdi)
+	movq	%rax, R8(%rdi)
+	movq	%rax, RAX(%rdi)
+	movq	%rax, RCX(%rdi)
+	movq	%rax, RDX(%rdi)
+	movq	%rax, RSI(%rdi)
+	movq	%rax, RDI(%rdi)
+	movq	%rax, ORIG_RAX(%rdi)
+	movq	%r9, RIP(%rdi)
+	leaq	8(%rsp), %r9
+	movq	$__KERNEL_CS, CS(%rdi)
+	movq	%rax, EFLAGS(%rdi)
+	movq	%r9, RSP(%rdi)
+	movq	$__KERNEL_DS, SS(%rdi)
+	jmpq	*%rcx
+	CFI_ENDPROC
+END(arch_unwind_init_running)
+#endif
+
+/*
+ * Some functions should be protected against kprobes
+ */
+	.pushsection .kprobes.text, "ax"
+
+paranoidzeroentry_ist debug do_debug DEBUG_STACK
+zeroentry nmi do_nmi_callback
+paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
+paranoiderrorentry stack_segment do_stack_segment
+errorentry general_protection do_general_protection
+errorentry page_fault do_page_fault
+#ifdef CONFIG_X86_MCE
+paranoidzeroentry machine_check *machine_check_vector(%rip)
+#endif
+
+#ifndef CONFIG_XEN
+	/*
+	 * "Paranoid" exit path from exception stack.
+	 * Paranoid because this is used by NMIs and cannot take
+	 * any kernel state for granted.
+	 * We don't do kernel preemption checks here, because only
+	 * NMI should be common and it does not enable IRQs and
+	 * cannot get reschedule ticks.
+	 *
+	 * "trace" is 0 for the NMI handler only, because irq-tracing
+	 * is fundamentally NMI-unsafe. (we cannot change the soft and
+	 * hard flags at once, atomically)
+	 */
+
+	/* ebx:	no swapgs flag */
+ENTRY(paranoid_exit)
+	DEFAULT_FRAME
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	testl %ebx,%ebx				/* swapgs needed? */
+	jnz paranoid_restore
+	testl $3,CS(%rsp)
+	jnz   paranoid_userspace
+paranoid_swapgs:
+	TRACE_IRQS_IRETQ 0
+	SWAPGS_UNSAFE_STACK
+	RESTORE_ALL 8
+	jmp irq_return
+paranoid_restore:
+	TRACE_IRQS_IRETQ 0
+	RESTORE_ALL 8
+	jmp irq_return
+paranoid_userspace:
+	GET_THREAD_INFO(%rcx)
+	movl TI_flags(%rcx),%ebx
+	andl $_TIF_WORK_MASK,%ebx
+	jz paranoid_swapgs
+	movq %rsp,%rdi			/* &pt_regs */
+	call sync_regs
+	movq %rax,%rsp			/* switch stack for scheduling */
+	testl $_TIF_NEED_RESCHED,%ebx
+	jnz paranoid_schedule
+	movl %ebx,%edx			/* arg3: thread flags */
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	xorl %esi,%esi 			/* arg2: oldset */
+	movq %rsp,%rdi 			/* arg1: &pt_regs */
+	call do_notify_resume
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	jmp paranoid_userspace
+paranoid_schedule:
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_ANY)
+	call schedule
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	TRACE_IRQS_OFF
+	jmp paranoid_userspace
+	CFI_ENDPROC
+END(paranoid_exit)
+#endif
+
+/*
+ * Exception entry point. This expects an error code/orig_rax on the stack.
+ * returns in "no swapgs flag" in %ebx.
+ */
+ENTRY(error_entry)
+	XCPT_FRAME start=2 offset=__stringify(ORIG_RAX-R15+8)
+	/* oldrax contains error code */
+	cld
+	movq %rdi, RDI+8(%rsp)
+	movq %rsi, RSI+8(%rsp)
+	movq %rdx, RDX+8(%rsp)
+	movq %rcx, RCX+8(%rsp)
+	movq %rax, RAX+8(%rsp)
+	movq  %r8,  R8+8(%rsp)
+	movq  %r9,  R9+8(%rsp)
+	movq %r10, R10+8(%rsp)
+	movq %r11, R11+8(%rsp)
+	movq_cfi rbx, __stringify(RBX+8)
+	movq %rbp, RBP+8(%rsp)
+	movq %r12, R12+8(%rsp)
+	movq %r13, R13+8(%rsp)
+	movq %r14, R14+8(%rsp)
+	movq %r15, R15+8(%rsp)
+#ifndef CONFIG_XEN
+	xorl %ebx,%ebx
+	testl $3,CS+8(%rsp)
+	je error_kernelspace
+error_swapgs:
+	SWAPGS
+error_sti:
+#endif
+	TRACE_IRQS_OFF
+	ret
+
+#ifndef CONFIG_XEN
+/*
+ * There are two places in the kernel that can potentially fault with
+ * usergs. Handle them here. The exception handlers after iret run with
+ * kernel gs again, so don't set the user space flag. B stepping K8s
+ * sometimes report an truncated RIP for IRET exceptions returning to
+ * compat mode. Check for these here too.
+ */
+error_kernelspace:
+	CFI_REL_OFFSET rcx, RCX+8
+	incl %ebx
+	leaq irq_return(%rip),%rcx
+	cmpq %rcx,RIP+8(%rsp)
+	je error_swapgs
+	movl %ecx,%ecx	/* zero extend */
+	cmpq %rcx,RIP+8(%rsp)
+	je error_swapgs
+	cmpq $gs_change,RIP+8(%rsp)
+	je error_swapgs
+	jmp error_sti
+#endif
+	CFI_ENDPROC
+END(error_entry)
+
+
+ENTRY(error_exit)
+	DEFAULT_FRAME
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	testb $3,CS-ARGOFFSET(%rsp)
+	jz retint_kernel
+	LOCKDEP_SYS_EXIT_IRQ
+	movl TI_flags(%rcx),%edx
+	movl $_TIF_WORK_MASK,%edi
+	andl %edi,%edx
+	jnz retint_careful
+	jmp retint_restore_args
+	CFI_ENDPROC
+END(error_exit)
+
+
+do_nmi_callback:
+	CFI_STARTPROC
+	addq $8, %rsp
+	CFI_ENDPROC
+	DEFAULT_FRAME
+	call do_nmi
+	orl  $NMI_MASK,EFLAGS(%rsp)
+	RESTORE_REST
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	GET_THREAD_INFO(%rcx)
+	jmp  retint_restore_args
+	CFI_ENDPROC
+END(do_nmi_callback)
+
+
+#ifndef CONFIG_IA32_EMULATION
+ENTRY(ignore_sysret)
+	INTR_FRAME
+	popq %rcx
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE rcx
+	popq %r11
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE r11
+	mov $-ENOSYS,%eax
+	HYPERVISOR_IRET 0
+	CFI_ENDPROC
+END(ignore_sysret)
+#endif
+
+/*
+ * End of kprobes section
+ */
+	.popsection
--- linux-ec2-2.6.32.orig/arch/x86/kernel/machine_kexec_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/machine_kexec_64.c
@@ -19,6 +19,112 @@
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
+#ifdef CONFIG_XEN
+
+/* In the case of Xen, override hypervisor functions to be able to create
+ * a regular identity mapping page table...
+ */
+
+#include <xen/interface/kexec.h>
+#include <xen/interface/memory.h>
+
+#define x__pmd(x) ((pmd_t) { (x) } )
+#define x__pud(x) ((pud_t) { (x) } )
+#define x__pgd(x) ((pgd_t) { (x) } )
+
+#define x_pmd_val(x)   ((x).pmd)
+#define x_pud_val(x)   ((x).pud)
+#define x_pgd_val(x)   ((x).pgd)
+
+static inline void x_set_pmd(pmd_t *dst, pmd_t val)
+{
+	x_pmd_val(*dst) = x_pmd_val(val);
+}
+
+static inline void x_set_pud(pud_t *dst, pud_t val)
+{
+	x_pud_val(*dst) = phys_to_machine(x_pud_val(val));
+}
+
+static inline void x_pud_clear (pud_t *pud)
+{
+	x_pud_val(*pud) = 0;
+}
+
+static inline void x_set_pgd(pgd_t *dst, pgd_t val)
+{
+	x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val));
+}
+
+static inline void x_pgd_clear (pgd_t * pgd)
+{
+	x_pgd_val(*pgd) = 0;
+}
+
+#define X__PAGE_KERNEL_LARGE_EXEC \
+         _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE
+#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY
+
+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
+
+#if PAGES_NR > KEXEC_XEN_NO_PAGES
+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
+#endif
+
+#if PA_CONTROL_PAGE != 0
+#error PA_CONTROL_PAGE is non zero - Xen support will break
+#endif
+
+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+{
+	void *control_page;
+	void *table_page;
+
+	memset(xki->page_list, 0, sizeof(xki->page_list));
+
+	control_page = page_address(image->control_code_page) + PAGE_SIZE;
+	memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+	table_page = page_address(image->control_code_page);
+
+	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
+	xki->page_list[PA_TABLE_PAGE] = __ma(table_page);
+
+	if (image->type == KEXEC_TYPE_DEFAULT)
+		xki->page_list[PA_SWAP_PAGE] = page_to_phys(image->swap_page);
+}
+
+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;
+}
+
+#else /* CONFIG_XEN */
+
+#define x__pmd(x) __pmd(x)
+#define x__pud(x) __pud(x)
+#define x__pgd(x) __pgd(x)
+
+#define x_set_pmd(x, y) set_pmd(x, y)
+#define x_set_pud(x, y) set_pud(x, y)
+#define x_set_pgd(x, y) set_pgd(x, y)
+
+#define x_pud_clear(x) pud_clear(x)
+#define x_pgd_clear(x) pgd_clear(x)
+
+#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC
+#define X_KERNPG_TABLE _KERNPG_TABLE
+
+#endif /* CONFIG_XEN */
+
 static int init_one_level2_page(struct kimage *image, pgd_t *pgd,
 				unsigned long addr)
 {
@@ -48,7 +154,7 @@
 	}
 	pmd = pmd_offset(pud, addr);
 	if (!pmd_present(*pmd))
-		set_pmd(pmd, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
+		x_set_pmd(pmd, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
 	result = 0;
 out:
 	return result;
@@ -61,7 +167,7 @@
 	addr &= PAGE_MASK;
 	end_addr = addr + PUD_SIZE;
 	while (addr < end_addr) {
-		set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
+		x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
 		addr += PMD_SIZE;
 	}
 }
@@ -86,12 +192,12 @@
 		}
 		level2p = (pmd_t *)page_address(page);
 		init_level2_page(level2p, addr);
-		set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE));
+		x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE));
 		addr += PUD_SIZE;
 	}
 	/* clear the unused entries */
 	while (addr < end_addr) {
-		pud_clear(level3p++);
+		x_pud_clear(level3p++);
 		addr += PUD_SIZE;
 	}
 out:
@@ -121,12 +227,12 @@
 		result = init_level3_page(image, level3p, addr, last_addr);
 		if (result)
 			goto out;
-		set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE));
+		x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE));
 		addr += PGDIR_SIZE;
 	}
 	/* clear the unused entries */
 	while (addr < end_addr) {
-		pgd_clear(level4p++);
+		x_pgd_clear(level4p++);
 		addr += PGDIR_SIZE;
 	}
 out:
@@ -187,8 +293,14 @@
 {
 	pgd_t *level4p;
 	int result;
+	unsigned long x_max_pfn = max_pfn;
+
+#ifdef CONFIG_XEN
+	x_max_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
+#endif
+
 	level4p = (pgd_t *)__va(start_pgtable);
-	result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
+	result = init_level4_page(image, level4p, 0, x_max_pfn << PAGE_SHIFT);
 	if (result)
 		return result;
 	/*
@@ -201,47 +313,6 @@
 	return init_transition_pgtable(image, level4p);
 }
 
-static void set_idt(void *newidt, u16 limit)
-{
-	struct desc_ptr curidt;
-
-	/* x86-64 supports unaliged loads & stores */
-	curidt.size    = limit;
-	curidt.address = (unsigned long)newidt;
-
-	__asm__ __volatile__ (
-		"lidtq %0\n"
-		: : "m" (curidt)
-		);
-};
-
-
-static void set_gdt(void *newgdt, u16 limit)
-{
-	struct desc_ptr curgdt;
-
-	/* x86-64 supports unaligned loads & stores */
-	curgdt.size    = limit;
-	curgdt.address = (unsigned long)newgdt;
-
-	__asm__ __volatile__ (
-		"lgdtq %0\n"
-		: : "m" (curgdt)
-		);
-};
-
-static void load_segments(void)
-{
-	__asm__ __volatile__ (
-		"\tmovl %0,%%ds\n"
-		"\tmovl %0,%%es\n"
-		"\tmovl %0,%%ss\n"
-		"\tmovl %0,%%fs\n"
-		"\tmovl %0,%%gs\n"
-		: : "a" (__KERNEL_DS) : "memory"
-		);
-}
-
 int machine_kexec_prepare(struct kimage *image)
 {
 	unsigned long start_pgtable;
@@ -263,6 +334,7 @@
 	free_transition_pgtable(image);
 }
 
+#ifndef CONFIG_XEN
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
@@ -308,24 +380,6 @@
 		page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
 						<< PAGE_SHIFT);
 
-	/*
-	 * The segment registers are funny things, they have both a
-	 * visible and an invisible part.  Whenever the visible part is
-	 * set to a specific selector, the invisible part is loaded
-	 * with from a table in memory.  At no other time is the
-	 * descriptor table in memory accessed.
-	 *
-	 * I take advantage of this here by force loading the
-	 * segments, before I zap the gdt with an invalid value.
-	 */
-	load_segments();
-	/*
-	 * The gdt & idt are now invalid.
-	 * If you want to load them you must set up your own idt & gdt.
-	 */
-	set_gdt(phys_to_virt(0), 0);
-	set_idt(phys_to_virt(0), 0);
-
 	/* now call it */
 	image->start = relocate_kernel((unsigned long)image->head,
 				       (unsigned long)page_list,
@@ -339,10 +393,13 @@
 
 	__ftrace_enabled_restore(save_ftrace_enabled);
 }
+#endif
 
 void arch_crash_save_vmcoreinfo(void)
 {
+#ifndef CONFIG_XEN /* could really be CONFIG_RELOCATABLE */
 	VMCOREINFO_SYMBOL(phys_base);
+#endif
 	VMCOREINFO_SYMBOL(init_level4_pgt);
 
 #ifdef CONFIG_NUMA
--- linux-ec2-2.6.32.orig/arch/x86/kernel/quirks-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/quirks-xen.c
@@ -0,0 +1,553 @@
+/*
+ * This file contains work-arounds for x86 and x86_64 platform bugs.
+ */
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI)
+
+static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+{
+	u8 config, rev;
+	u16 word;
+
+	/* BIOS may enable hardware IRQ balancing for
+	 * E7520/E7320/E7525(revision ID 0x9 and below)
+	 * based platforms.
+	 * Disable SW irqbalance/affinity on those platforms.
+	 */
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+	if (rev > 0x9)
+		return;
+
+	/* enable access to config space*/
+	pci_read_config_byte(dev, 0xf4, &config);
+	pci_write_config_byte(dev, 0xf4, config|0x2);
+
+	/*
+	 * read xTPR register.  We may not have a pci_dev for device 8
+	 * because it might be hidden until the above write.
+	 */
+	pci_bus_read_config_word(dev->bus, PCI_DEVFN(8, 0), 0x4c, &word);
+
+	if (!(word & (1 << 13))) {
+		struct xen_platform_op op;
+
+		dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
+			"disabling irq balancing and affinity\n");
+		op.cmd = XENPF_platform_quirk;
+		op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
+		WARN_ON(HYPERVISOR_platform_op(&op));
+	}
+
+	/* put back the original value for config space*/
+	if (!(config & 0x2))
+		pci_write_config_byte(dev, 0xf4, config);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH,
+			quirk_intel_irqbalance);
+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
+
+#if defined(CONFIG_HPET_TIMER)
+#include <asm/hpet.h>
+
+unsigned long force_hpet_address;
+
+static enum {
+	NONE_FORCE_HPET_RESUME,
+	OLD_ICH_FORCE_HPET_RESUME,
+	ICH_FORCE_HPET_RESUME,
+	VT8237_FORCE_HPET_RESUME,
+	NVIDIA_FORCE_HPET_RESUME,
+	ATI_FORCE_HPET_RESUME,
+} force_hpet_resume_type;
+
+static void __iomem *rcba_base;
+
+static void ich_force_hpet_resume(void)
+{
+	u32 val;
+
+	if (!force_hpet_address)
+		return;
+
+	BUG_ON(rcba_base == NULL);
+
+	/* read the Function Disable register, dword mode only */
+	val = readl(rcba_base + 0x3404);
+	if (!(val & 0x80)) {
+		/* HPET disabled in HPTC. Trying to enable */
+		writel(val | 0x80, rcba_base + 0x3404);
+	}
+
+	val = readl(rcba_base + 0x3404);
+	if (!(val & 0x80))
+		BUG();
+	else
+		printk(KERN_DEBUG "Force enabled HPET at resume\n");
+
+	return;
+}
+
+static void ich_force_enable_hpet(struct pci_dev *dev)
+{
+	u32 val;
+	u32 uninitialized_var(rcba);
+	int err = 0;
+
+	if (hpet_address || force_hpet_address)
+		return;
+
+	pci_read_config_dword(dev, 0xF0, &rcba);
+	rcba &= 0xFFFFC000;
+	if (rcba == 0) {
+		dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
+			"cannot force enable HPET\n");
+		return;
+	}
+
+	/* use bits 31:14, 16 kB aligned */
+	rcba_base = ioremap_nocache(rcba, 0x4000);
+	if (rcba_base == NULL) {
+		dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
+			"cannot force enable HPET\n");
+		return;
+	}
+
+	/* read the Function Disable register, dword mode only */
+	val = readl(rcba_base + 0x3404);
+
+	if (val & 0x80) {
+		/* HPET is enabled in HPTC. Just not reported by BIOS */
+		val = val & 0x3;
+		force_hpet_address = 0xFED00000 | (val << 12);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
+		iounmap(rcba_base);
+		return;
+	}
+
+	/* HPET disabled in HPTC. Trying to enable */
+	writel(val | 0x80, rcba_base + 0x3404);
+
+	val = readl(rcba_base + 0x3404);
+	if (!(val & 0x80)) {
+		err = 1;
+	} else {
+		val = val & 0x3;
+		force_hpet_address = 0xFED00000 | (val << 12);
+	}
+
+	if (err) {
+		force_hpet_address = 0;
+		iounmap(rcba_base);
+		dev_printk(KERN_DEBUG, &dev->dev,
+			"Failed to force enable HPET\n");
+	} else {
+		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
+			 ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x3a16,	/* ICH10 */
+			 ich_force_enable_hpet);
+
+static struct pci_dev *cached_dev;
+
+static void hpet_print_force_info(void)
+{
+	printk(KERN_INFO "HPET not enabled in BIOS. "
+	       "You might try hpet=force boot option\n");
+}
+
+static void old_ich_force_hpet_resume(void)
+{
+	u32 val;
+	u32 uninitialized_var(gen_cntl);
+
+	if (!force_hpet_address || !cached_dev)
+		return;
+
+	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
+	gen_cntl &= (~(0x7 << 15));
+	gen_cntl |= (0x4 << 15);
+
+	pci_write_config_dword(cached_dev, 0xD0, gen_cntl);
+	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
+	val = gen_cntl >> 15;
+	val &= 0x7;
+	if (val == 0x4)
+		printk(KERN_DEBUG "Force enabled HPET at resume\n");
+	else
+		BUG();
+}
+
+static void old_ich_force_enable_hpet(struct pci_dev *dev)
+{
+	u32 val;
+	u32 uninitialized_var(gen_cntl);
+
+	if (hpet_address || force_hpet_address)
+		return;
+
+	pci_read_config_dword(dev, 0xD0, &gen_cntl);
+	/*
+	 * Bit 17 is HPET enable bit.
+	 * Bit 16:15 control the HPET base address.
+	 */
+	val = gen_cntl >> 15;
+	val &= 0x7;
+	if (val & 0x4) {
+		val &= 0x3;
+		force_hpet_address = 0xFED00000 | (val << 12);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
+		return;
+	}
+
+	/*
+	 * HPET is disabled. Trying enabling at FED00000 and check
+	 * whether it sticks
+	 */
+	gen_cntl &= (~(0x7 << 15));
+	gen_cntl |= (0x4 << 15);
+	pci_write_config_dword(dev, 0xD0, gen_cntl);
+
+	pci_read_config_dword(dev, 0xD0, &gen_cntl);
+
+	val = gen_cntl >> 15;
+	val &= 0x7;
+	if (val & 0x4) {
+		/* HPET is enabled in HPTC. Just not reported by BIOS */
+		val &= 0x3;
+		force_hpet_address = 0xFED00000 | (val << 12);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
+		cached_dev = dev;
+		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
+		return;
+	}
+
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
+}
+
+/*
+ * Undocumented chipset features. Make sure that the user enforced
+ * this.
+ */
+static void old_ich_force_enable_hpet_user(struct pci_dev *dev)
+{
+	if (hpet_force_user)
+		old_ich_force_enable_hpet(dev);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
+			 old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+			 old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
+			 old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+			 old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
+			 old_ich_force_enable_hpet_user);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
+			 old_ich_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12,
+			 old_ich_force_enable_hpet);
+
+
+static void vt8237_force_hpet_resume(void)
+{
+	u32 val;
+
+	if (!force_hpet_address || !cached_dev)
+		return;
+
+	val = 0xfed00000 | 0x80;
+	pci_write_config_dword(cached_dev, 0x68, val);
+
+	pci_read_config_dword(cached_dev, 0x68, &val);
+	if (val & 0x80)
+		printk(KERN_DEBUG "Force enabled HPET at resume\n");
+	else
+		BUG();
+}
+
+static void vt8237_force_enable_hpet(struct pci_dev *dev)
+{
+	u32 uninitialized_var(val);
+
+	if (hpet_address || force_hpet_address)
+		return;
+
+	if (!hpet_force_user) {
+		hpet_print_force_info();
+		return;
+	}
+
+	pci_read_config_dword(dev, 0x68, &val);
+	/*
+	 * Bit 7 is HPET enable bit.
+	 * Bit 31:10 is HPET base address (contrary to what datasheet claims)
+	 */
+	if (val & 0x80) {
+		force_hpet_address = (val & ~0x3ff);
+		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+			force_hpet_address);
+		return;
+	}
+
+	/*
+	 * HPET is disabled. Trying enabling at FED00000 and check
+	 * whether it sticks
+	 */
+	val = 0xfed00000 | 0x80;
+	pci_write_config_dword(dev, 0x68, val);
+
+	pci_read_config_dword(dev, 0x68, &val);
+	if (val & 0x80) {
+		force_hpet_address = (val & ~0x3ff);
+		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+			"0x%lx\n", force_hpet_address);
+		cached_dev = dev;
+		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
+		return;
+	}
+
+	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
+			 vt8237_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
+			 vt8237_force_enable_hpet);
+
+static void ati_force_hpet_resume(void)
+{
+	pci_write_config_dword(cached_dev, 0x14, 0xfed00000);
+	printk(KERN_DEBUG "Force enabled HPET at resume\n");
+}
+
+static u32 ati_ixp4x0_rev(struct pci_dev *dev)
+{
+	u32 d;
+	u8  b;
+
+	pci_read_config_byte(dev, 0xac, &b);
+	b &= ~(1<<5);
+	pci_write_config_byte(dev, 0xac, b);
+	pci_read_config_dword(dev, 0x70, &d);
+	d |= 1<<8;
+	pci_write_config_dword(dev, 0x70, d);
+	pci_read_config_dword(dev, 0x8, &d);
+	d &= 0xff;
+	dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d);
+	return d;
+}
+
+static void ati_force_enable_hpet(struct pci_dev *dev)
+{
+	u32 d, val;
+	u8  b;
+
+	if (hpet_address || force_hpet_address)
+		return;
+
+	if (!hpet_force_user) {
+		hpet_print_force_info();
+		return;
+	}
+
+	d = ati_ixp4x0_rev(dev);
+	if (d  < 0x82)
+		return;
+
+	/* base address */
+	pci_write_config_dword(dev, 0x14, 0xfed00000);
+	pci_read_config_dword(dev, 0x14, &val);
+
+	/* enable interrupt */
+	outb(0x72, 0xcd6); b = inb(0xcd7);
+	b |= 0x1;
+	outb(0x72, 0xcd6); outb(b, 0xcd7);
+	outb(0x72, 0xcd6); b = inb(0xcd7);
+	if (!(b & 0x1))
+		return;
+	pci_read_config_dword(dev, 0x64, &d);
+	d |= (1<<10);
+	pci_write_config_dword(dev, 0x64, d);
+	pci_read_config_dword(dev, 0x64, &d);
+	if (!(d & (1<<10)))
+		return;
+
+	force_hpet_address = val;
+	force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
+	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
+		   force_hpet_address);
+	cached_dev = dev;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
+			 ati_force_enable_hpet);
+
+/*
+ * Undocumented chipset feature taken from LinuxBIOS.
+ */
+static void nvidia_force_hpet_resume(void)
+{
+	pci_write_config_dword(cached_dev, 0x44, 0xfed00001);
+	printk(KERN_DEBUG "Force enabled HPET at resume\n");
+}
+
+static void nvidia_force_enable_hpet(struct pci_dev *dev)
+{
+	u32 uninitialized_var(val);
+
+	if (hpet_address || force_hpet_address)
+		return;
+
+	if (!hpet_force_user) {
+		hpet_print_force_info();
+		return;
+	}
+
+	pci_write_config_dword(dev, 0x44, 0xfed00001);
+	pci_read_config_dword(dev, 0x44, &val);
+	force_hpet_address = val & 0xfffffffe;
+	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
+	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
+		force_hpet_address);
+	cached_dev = dev;
+	return;
+}
+
+/* ISA Bridges */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0050,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0051,
+			nvidia_force_enable_hpet);
+
+/* LPC bridges */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0260,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0360,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0361,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0362,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0363,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0364,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0365,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0366,
+			nvidia_force_enable_hpet);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0367,
+			nvidia_force_enable_hpet);
+
+void force_hpet_resume(void)
+{
+	switch (force_hpet_resume_type) {
+	case ICH_FORCE_HPET_RESUME:
+		ich_force_hpet_resume();
+		return;
+	case OLD_ICH_FORCE_HPET_RESUME:
+		old_ich_force_hpet_resume();
+		return;
+	case VT8237_FORCE_HPET_RESUME:
+		vt8237_force_hpet_resume();
+		return;
+	case NVIDIA_FORCE_HPET_RESUME:
+		nvidia_force_hpet_resume();
+		return;
+	case ATI_FORCE_HPET_RESUME:
+		ati_force_hpet_resume();
+		return;
+	default:
+		break;
+	}
+}
+
+/*
+ * HPET MSI on some boards (ATI SB700/SB800) has side effect on
+ * floppy DMA. Disable HPET MSI on such platforms.
+ */
+static void force_disable_hpet_msi(struct pci_dev *unused)
+{
+	hpet_msi_disable = 1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+			 force_disable_hpet_msi);
+
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
+/* Set correct numa_node information for AMD NB functions */
+static void __init quirk_amd_nb_node(struct pci_dev *dev)
+{
+	struct pci_dev *nb_ht;
+	unsigned int devfn;
+	u32 node;
+	u32 val;
+
+	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
+	nb_ht = pci_get_slot(dev->bus, devfn);
+	if (!nb_ht)
+		return;
+
+	pci_read_config_dword(nb_ht, 0x60, &val);
+	node = val & 7;
+	/*
+	 * Some hardware may return an invalid node ID,
+	 * so check it first:
+	 */
+	if (node_online(node))
+		set_dev_node(&dev->dev, node);
+	pci_dev_put(nb_ht);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_HT,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MAP,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,
+			quirk_amd_nb_node);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
+			quirk_amd_nb_node);
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process_32-xen.c
@@ -0,0 +1,568 @@
+/*
+ *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  Pentium III FXSR, SSE support
+ *	Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/stackprotector.h>
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/elfcore.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/user.h>
+#include <linux/interrupt.h>
+#include <linux/utsname.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+#include <linux/ptrace.h>
+#include <linux/personality.h>
+#include <linux/tick.h>
+#include <linux/percpu.h>
+#include <linux/prctl.h>
+#include <linux/dmi.h>
+#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/kdebug.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/ldt.h>
+#include <asm/processor.h>
+#include <asm/i387.h>
+#include <asm/desc.h>
+#ifdef CONFIG_MATH_EMULATION
+#include <asm/math_emu.h>
+#endif
+
+#include <xen/interface/physdev.h>
+#include <xen/interface/vcpu.h>
+#include <xen/cpu_hotplug.h>
+
+#include <linux/err.h>
+
+#include <asm/tlbflush.h>
+#include <asm/cpu.h>
+#include <asm/idle.h>
+#include <asm/syscalls.h>
+#include <asm/ds.h>
+
+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void cstar_ret_from_fork(void) __asm__("cstar_ret_from_fork");
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	return ((unsigned long *)tsk->thread.sp)[3];
+}
+
+#ifndef CONFIG_SMP
+static inline void play_dead(void)
+{
+	BUG();
+}
+#endif
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * If we're the non-boot CPU, nothing set the stack canary up
+	 * for us.  CPU0 already has it initialized but no harm in
+	 * doing it again.  This is a good place for updating it, as
+	 * we wont ever return from this function (so the invalid
+	 * canaries already on the stack wont ever trigger).
+	 */
+	boot_init_stack_canary();
+
+	current_thread_info()->status |= TS_POLLING;
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		while (!need_resched()) {
+
+			check_pgt_cache();
+			rmb();
+
+			if (cpu_is_offline(cpu))
+				play_dead();
+
+			local_irq_disable();
+			/* Don't trace irqs off for idle */
+			stop_critical_timings();
+			xen_idle();
+			start_critical_timings();
+		}
+		tick_nohz_restart_sched_tick();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+void __show_regs(struct pt_regs *regs, int all)
+{
+	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+	unsigned long d0, d1, d2, d3, d6, d7;
+	unsigned long sp;
+	unsigned short ss, gs;
+	const char *board;
+
+	if (user_mode_vm(regs)) {
+		sp = regs->sp;
+		ss = regs->ss & 0xffff;
+		gs = get_user_gs(regs);
+	} else {
+		sp = (unsigned long) (&regs->sp);
+		savesegment(ss, ss);
+		savesegment(gs, gs);
+	}
+
+	printk("\n");
+
+	board = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!board)
+		board = "";
+	printk("Pid: %d, comm: %s %s (%s %.*s) %s\n",
+			task_pid_nr(current), current->comm,
+			print_tainted(), init_utsname()->release,
+			(int)strcspn(init_utsname()->version, " "),
+			init_utsname()->version, board);
+
+	printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
+			(u16)regs->cs, regs->ip, regs->flags,
+			smp_processor_id());
+	print_symbol("EIP is at %s\n", regs->ip);
+
+	printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+		regs->ax, regs->bx, regs->cx, regs->dx);
+	printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
+		regs->si, regs->di, regs->bp, sp);
+	printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
+	       (u16)regs->ds, (u16)regs->es, (u16)regs->fs, gs, ss);
+
+	if (!all)
+		return;
+
+	cr0 = read_cr0();
+	cr2 = read_cr2();
+	cr3 = read_cr3();
+	cr4 = read_cr4_safe();
+	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n",
+			cr0, cr2, cr3, cr4);
+
+	get_debugreg(d0, 0);
+	get_debugreg(d1, 1);
+	get_debugreg(d2, 2);
+	get_debugreg(d3, 3);
+	printk("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n",
+			d0, d1, d2, d3);
+
+	get_debugreg(d6, 6);
+	get_debugreg(d7, 7);
+	printk("DR6: %08lx DR7: %08lx\n",
+			d6, d7);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	__show_regs(regs, 1);
+	show_trace(NULL, regs, &regs->sp, regs->bp);
+}
+
+/*
+ * This gets run with %bx containing the
+ * function to call, and %dx containing
+ * the "args".
+ */
+extern void kernel_thread_helper(void);
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.bx = (unsigned long) fn;
+	regs.dx = (unsigned long) arg;
+
+	regs.ds = __USER_DS;
+	regs.es = __USER_DS;
+	regs.fs = __KERNEL_PERCPU;
+	regs.gs = __KERNEL_STACK_CANARY;
+	regs.orig_ax = -1;
+	regs.ip = (unsigned long) kernel_thread_helper;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
+
+	/* Ok, create the new process.. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+void release_thread(struct task_struct *dead_task)
+{
+	BUG_ON(dead_task->mm);
+	release_vm86_irqs(dead_task);
+}
+
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	unlazy_fpu(tsk);
+}
+
+int copy_thread(unsigned long clone_flags, unsigned long sp,
+	unsigned long unused,
+	struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs *childregs;
+	struct task_struct *tsk;
+	int err;
+
+	childregs = task_pt_regs(p);
+	*childregs = *regs;
+	childregs->ax = 0;
+	childregs->sp = sp;
+
+	p->thread.sp = (unsigned long) childregs;
+	p->thread.sp0 = (unsigned long) (childregs+1);
+
+	p->thread.ip = (unsigned long) ret_from_fork;
+
+	task_user_gs(p) = get_user_gs(regs);
+
+	tsk = current;
+	if (test_tsk_thread_flag(tsk, TIF_CSTAR))
+		p->thread.ip = (unsigned long) cstar_ret_from_fork;
+	if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+		p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
+						IO_BITMAP_BYTES, GFP_KERNEL);
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
+			return -ENOMEM;
+		}
+		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+	}
+
+	err = 0;
+
+	/*
+	 * Set a new TLS for the child thread?
+	 */
+	if (clone_flags & CLONE_SETTLS)
+		err = do_set_thread_area(p, -1,
+			(struct user_desc __user *)childregs->si, 0);
+
+	p->thread.iopl = current->thread.iopl;
+
+	if (err && p->thread.io_bitmap_ptr) {
+		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
+
+	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+	p->thread.ds_ctx = NULL;
+
+	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
+	p->thread.debugctlmsr = 0;
+
+	return err;
+}
+
+void
+start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+{
+	set_user_gs(regs, 0);
+	regs->fs		= 0;
+	set_fs(USER_DS);
+	regs->ds		= __USER_DS;
+	regs->es		= __USER_DS;
+	regs->ss		= __USER_DS;
+	regs->cs		= __USER_CS;
+	regs->ip		= new_ip;
+	regs->sp		= new_sp;
+	/*
+	 * Free the old FP and other extended state
+	 */
+	free_thread_xstate(current);
+}
+EXPORT_SYMBOL_GPL(start_thread);
+
+/*
+ *	switch_to(x,yn) should switch tasks from x to y.
+ *
+ * We fsave/fwait so that an exception goes off at the right time
+ * (as a call from the fsave or fwait in effect) rather than to
+ * the wrong process. Lazy FP saving no longer makes any sense
+ * with modern CPU's, and this simplifies a lot of things (SMP
+ * and UP become the same).
+ *
+ * NOTE! We used to use the x86 hardware context switching. The
+ * reason for not using it any more becomes apparent when you
+ * try to recover gracefully from saved state that is no longer
+ * valid (stale segment register values in particular). With the
+ * hardware task-switch, there is no way to fix up bad state in
+ * a reasonable manner.
+ *
+ * The fact that Intel documents the hardware task-switching to
+ * be slow is a fairly red herring - this code is not noticeably
+ * faster. However, there _is_ some room for improvement here,
+ * so the performance issues may eventually be a valid point.
+ * More important, however, is the fact that this allows us much
+ * more flexibility.
+ *
+ * The return value (in %ax) will be the "prev" task after
+ * the task-switch, and shows up in ret_from_fork in entry.S,
+ * for example.
+ */
+__notrace_funcgraph struct task_struct *
+__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+{
+	struct thread_struct *prev = &prev_p->thread,
+				 *next = &next_p->thread;
+	int cpu = smp_processor_id();
+#ifndef CONFIG_X86_NO_TSS
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+#endif
+	bool preload_fpu;
+#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. */
+
+	/*
+	 * If the task has used fpu the last 5 timeslices, just do a full
+	 * restore of the math state immediately to avoid the trap; the
+	 * chances of needing FPU soon are obviously high now
+	 */
+	preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
+
+	/*
+	 * This is basically '__unlazy_fpu', except that we queue a
+	 * multicall to indicate FPU task switch, rather than
+	 * synchronously trapping to Xen.
+	 */
+	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+		if (!preload_fpu) {
+			mcl->op      = __HYPERVISOR_fpu_taskswitch;
+			mcl->args[0] = 1;
+			mcl++;
+		}
+	}
+#if 0 /* lazy fpu sanity check */
+	else BUG_ON(!(read_cr0() & 8));
+#endif
+
+	/*
+	 * Reload sp0.
+	 * This is load_sp0(tss, next) with a multicall.
+	 */
+	mcl->op      = __HYPERVISOR_stack_switch;
+	mcl->args[0] = __KERNEL_DS;
+	mcl->args[1] = next->sp0;
+	mcl++;
+
+	/*
+	 * Load the per-thread Thread-Local Storage descriptor.
+	 * This is load_TLS(next, cpu) with multicalls.
+	 */
+#define C(i) do {							\
+	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
+		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
+		mcl->op = __HYPERVISOR_update_descriptor;		\
+		*(u64 *)&mcl->args[0] =	arbitrary_virt_to_machine(	\
+			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
+		*(u64 *)&mcl->args[2] = *(u64 *)&next->tls_array[i];	\
+		mcl++;							\
+	}								\
+} while (0)
+	C(0); C(1); C(2);
+#undef C
+
+	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++;
+	}
+
+	/* If we're going to preload the fpu context, make sure clts
+	   is run while we're batching the cpu state updates. */
+	if (preload_fpu) {
+		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+		mcl->args[0] = 0;
+		mcl++;
+	}
+
+	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
+		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();
+
+	/* we're going to use this soon, after a few expensive things */
+	if (preload_fpu)
+		prefetch(next->xstate);
+
+	/*
+	 * Now maybe handle debug registers
+	 */
+	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
+		     task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
+		__switch_to_xtra(prev_p, next_p);
+
+	/*
+	 * Leave lazy mode, flushing any hypercalls made here.
+	 * This must be done before restoring TLS segments so
+	 * the GDT and LDT are properly updated, and must be
+	 * done before math_state_restore, so the TS bit is up
+	 * to date.
+	 */
+	arch_end_context_switch(next_p);
+
+	if (preload_fpu)
+		__math_state_restore();
+
+	/*
+	 * Restore %gs if needed (which is common)
+	 */
+	if (prev->gs | next->gs)
+		lazy_load_gs(next->gs);
+
+	percpu_write(current_task, next_p);
+
+	return prev_p;
+}
+
+int sys_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+	int __user *parent_tidptr, *child_tidptr;
+
+	clone_flags = regs->bx;
+	newsp = regs->cx;
+	parent_tidptr = (int __user *)regs->dx;
+	child_tidptr = (int __user *)regs->di;
+	if (!newsp)
+		newsp = regs->sp;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+int sys_execve(struct pt_regs *regs)
+{
+	int error;
+	char *filename;
+
+	filename = getname((char __user *) regs->bx);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename,
+			(char __user * __user *) regs->cx,
+			(char __user * __user *) regs->dx,
+			regs);
+	if (error == 0) {
+		/* Make sure we don't return using sysenter.. */
+		set_thread_flag(TIF_IRET);
+	}
+	putname(filename);
+out:
+	return error;
+}
+
+#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
+#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long bp, sp, ip;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	stack_page = (unsigned long)task_stack_page(p);
+	sp = p->thread.sp;
+	if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
+		return 0;
+	/* include/asm-i386/system.h:switch_to() pushes bp last. */
+	bp = *(unsigned long *) sp;
+	do {
+		if (bp < stack_page || bp > top_ebp+stack_page)
+			return 0;
+		ip = *(unsigned long *) (bp+4);
+		if (!in_sched_functions(ip))
+			return ip;
+		bp = *(unsigned long *) bp;
+	} while (count++ < 16);
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/arch/x86/kernel/relocate_kernel_32.S
+++ linux-ec2-2.6.32/arch/x86/kernel/relocate_kernel_32.S
@@ -87,14 +87,32 @@
 	movl	PTR(PA_PGD)(%ebp), %eax
 	movl	%eax, %cr3
 
+	/* setup idt */
+	lidtl	idt_48 - relocate_kernel(%edi)
+
+	/* setup gdt */
+	leal	gdt - relocate_kernel(%edi), %eax
+	movl	%eax, (gdt_48 - relocate_kernel) + 2(%edi)
+	lgdtl	gdt_48 - relocate_kernel(%edi)
+
+	/* setup data segment registers */
+	mov	$(gdt_ds - gdt), %eax
+	mov	%eax, %ds
+	mov	%eax, %es
+	mov	%eax, %fs
+	mov	%eax, %gs
+	mov	%eax, %ss
+
 	/* setup a new stack at the end of the physical control page */
 	lea	PAGE_SIZE(%edi), %esp
 
-	/* jump to identity mapped page */
+	/* load new code segment and jump to identity mapped page */
+	pushl	$0
+	pushl	$(gdt_cs - gdt)
 	movl    %edi, %eax
 	addl    $(identity_mapped - relocate_kernel), %eax
 	pushl   %eax
-	ret
+	iretl
 
 identity_mapped:
 	/* store the start address on the stack */
@@ -271,5 +289,22 @@
 	popl	%ebp
 	ret
 
+	.align	16
+gdt:
+	.quad	0x0000000000000000	/* NULL descriptor */
+gdt_cs:
+	.quad	0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
+gdt_ds:
+	.quad	0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */
+gdt_end:
+
+gdt_48:
+	.word	gdt_end - gdt - 1	/* limit */
+	.long	0			/* base - filled in by code above */
+
+idt_48:
+	.word	0			/* limit */
+	.long	0			/* base */
+
 	.globl kexec_control_code_size
 .set kexec_control_code_size, . - relocate_kernel
--- linux-ec2-2.6.32.orig/arch/x86/kernel/tlb_uv.c
+++ linux-ec2-2.6.32/arch/x86/kernel/tlb_uv.c
@@ -817,10 +817,8 @@
 	 */
 	apicid = blade_to_first_apicid(blade);
 	pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG);
-	if ((pa & 0xff) != UV_BAU_MESSAGE) {
-		uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
+	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
 				      ((apicid << 32) | UV_BAU_MESSAGE));
-	}
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/entry_32-xen.S
+++ linux-ec2-2.6.32/arch/x86/kernel/entry_32-xen.S
@@ -0,0 +1,1739 @@
+/*
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * I changed all the .align's to 4 (16 byte alignment), as that's faster
+ * on a 486.
+ *
+ * Stack layout in 'syscall_exit':
+ * 	ptrace needs to have all regs on the stack.
+ *	if the order here is changed, it needs to be
+ *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	ptrace.c and ptrace.h
+ *
+ *	 0(%esp) - %ebx
+ *	 4(%esp) - %ecx
+ *	 8(%esp) - %edx
+ *       C(%esp) - %esi
+ *	10(%esp) - %edi
+ *	14(%esp) - %ebp
+ *	18(%esp) - %eax
+ *	1C(%esp) - %ds
+ *	20(%esp) - %es
+ *	24(%esp) - %fs
+ *	28(%esp) - %gs		saved iff !CONFIG_X86_32_LAZY_GS
+ *	2C(%esp) - orig_eax
+ *	30(%esp) - %eip
+ *	34(%esp) - %cs
+ *	38(%esp) - %eflags
+ *	3C(%esp) - %oldesp
+ *	40(%esp) - %oldss
+ *
+ * "current" is in register %ebx during any slow entries.
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/irqflags.h>
+#include <asm/errno.h>
+#include <asm/segment.h>
+#include <asm/smp.h>
+#include <asm/page_types.h>
+#include <asm/percpu.h>
+#include <asm/dwarf2.h>
+#include <asm/processor-flags.h>
+#include <asm/ftrace.h>
+#include <asm/irq_vectors.h>
+#include <xen/interface/xen.h>
+
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_LE	   0x40000000
+
+#ifndef CONFIG_AUDITSYSCALL
+#define sysenter_audit	syscall_trace_entry
+#define sysexit_audit	syscall_exit_work
+#endif
+
+/*
+ * We use macros for low-level operations which need to be overridden
+ * for paravirtualization.  The following will never clobber any registers:
+ *   INTERRUPT_RETURN (aka. "iret")
+ *   GET_CR0_INTO_EAX (aka. "movl %cr0, %eax")
+ *   ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit").
+ *
+ * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must
+ * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY).
+ * Allowing a register to be clobbered can shrink the paravirt replacement
+ * enough to patch inline, increasing performance.
+ */
+
+#define nr_syscalls ((syscall_table_size)/4)
+
+/* Pseudo-eflags. */
+NMI_MASK	= 0x80000000
+
+#ifdef CONFIG_PREEMPT
+#define preempt_stop(clobbers)	DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF
+#else
+#define preempt_stop(clobbers)
+#define resume_kernel		restore_all
+#endif
+
+.macro TRACE_IRQS_IRET
+#ifdef CONFIG_TRACE_IRQFLAGS
+	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)     # interrupts off?
+	jz 1f
+	TRACE_IRQS_ON
+1:
+#endif
+.endm
+
+#ifdef CONFIG_VM86
+#define resume_userspace_sig	check_userspace
+#else
+#define resume_userspace_sig	resume_userspace
+#endif
+
+/*
+ * User gs save/restore
+ *
+ * %gs is used for userland TLS and kernel only uses it for stack
+ * canary which is required to be at %gs:20 by gcc.  Read the comment
+ * at the top of stackprotector.h for more info.
+ *
+ * Local labels 98 and 99 are used.
+ */
+#ifdef CONFIG_X86_32_LAZY_GS
+
+ /* unfortunately push/pop can't be no-op */
+.macro PUSH_GS
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+.endm
+.macro POP_GS pop=0
+	addl $(4 + \pop), %esp
+	CFI_ADJUST_CFA_OFFSET -(4 + \pop)
+.endm
+.macro POP_GS_EX
+.endm
+
+ /* all the rest are no-op */
+.macro PTGS_TO_GS
+.endm
+.macro PTGS_TO_GS_EX
+.endm
+.macro GS_TO_REG reg
+.endm
+.macro REG_TO_PTGS reg
+.endm
+.macro SET_KERNEL_GS reg
+.endm
+
+#else	/* CONFIG_X86_32_LAZY_GS */
+
+.macro PUSH_GS
+	pushl %gs
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET gs, 0*/
+.endm
+
+.macro POP_GS pop=0
+98:	popl %gs
+	CFI_ADJUST_CFA_OFFSET -4
+	/*CFI_RESTORE gs*/
+  .if \pop <> 0
+	add $\pop, %esp
+	CFI_ADJUST_CFA_OFFSET -\pop
+  .endif
+.endm
+.macro POP_GS_EX
+.pushsection .fixup, "ax"
+99:	movl $0, (%esp)
+	jmp 98b
+.section __ex_table, "a"
+	.align 4
+	.long 98b, 99b
+.popsection
+.endm
+
+.macro PTGS_TO_GS
+98:	mov PT_GS(%esp), %gs
+.endm
+.macro PTGS_TO_GS_EX
+.pushsection .fixup, "ax"
+99:	movl $0, PT_GS(%esp)
+	jmp 98b
+.section __ex_table, "a"
+	.align 4
+	.long 98b, 99b
+.popsection
+.endm
+
+.macro GS_TO_REG reg
+	movl %gs, \reg
+	/*CFI_REGISTER gs, \reg*/
+.endm
+.macro REG_TO_PTGS reg
+	movl \reg, PT_GS(%esp)
+	/*CFI_REL_OFFSET gs, PT_GS*/
+.endm
+.macro SET_KERNEL_GS reg
+	movl $(__KERNEL_STACK_CANARY), \reg
+	movl \reg, %gs
+.endm
+
+#endif	/* CONFIG_X86_32_LAZY_GS */
+
+.macro SAVE_ALL
+	cld
+	PUSH_GS
+	pushl %fs
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET fs, 0;*/
+	pushl %es
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET es, 0;*/
+	pushl %ds
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET ds, 0;*/
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eax, 0
+	pushl %ebp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebp, 0
+	pushl %edi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edi, 0
+	pushl %esi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET esi, 0
+	pushl %edx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edx, 0
+	pushl %ecx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ecx, 0
+	pushl %ebx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebx, 0
+	movl $(__USER_DS), %edx
+	movl %edx, %ds
+	movl %edx, %es
+	movl $(__KERNEL_PERCPU), %edx
+	movl %edx, %fs
+	SET_KERNEL_GS %edx
+.endm
+
+.macro RESTORE_INT_REGS
+	popl %ebx
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE ebx
+	popl %ecx
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE ecx
+	popl %edx
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE edx
+	popl %esi
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE esi
+	popl %edi
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE edi
+	popl %ebp
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE ebp
+	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
+	CFI_RESTORE eax
+.endm
+
+.macro RESTORE_REGS pop=0
+	RESTORE_INT_REGS
+1:	popl %ds
+	CFI_ADJUST_CFA_OFFSET -4
+	/*CFI_RESTORE ds;*/
+2:	popl %es
+	CFI_ADJUST_CFA_OFFSET -4
+	/*CFI_RESTORE es;*/
+3:	popl %fs
+	CFI_ADJUST_CFA_OFFSET -4
+	/*CFI_RESTORE fs;*/
+	POP_GS \pop
+.pushsection .fixup, "ax"
+4:	movl $0, (%esp)
+	jmp 1b
+5:	movl $0, (%esp)
+	jmp 2b
+6:	movl $0, (%esp)
+	jmp 3b
+.section __ex_table, "a"
+	.align 4
+	.long 1b, 4b
+	.long 2b, 5b
+	.long 3b, 6b
+.popsection
+	POP_GS_EX
+.endm
+
+.macro RING0_INT_FRAME
+	CFI_STARTPROC simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA esp, 3*4
+	/*CFI_OFFSET cs, -2*4;*/
+	CFI_OFFSET eip, -3*4
+.endm
+
+.macro RING0_EC_FRAME
+	CFI_STARTPROC simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA esp, 4*4
+	/*CFI_OFFSET cs, -2*4;*/
+	CFI_OFFSET eip, -3*4
+.endm
+
+.macro RING0_PTREGS_FRAME
+	CFI_STARTPROC simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA esp, PT_OLDESP-PT_EBX
+	/*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/
+	CFI_OFFSET eip, PT_EIP-PT_OLDESP
+	/*CFI_OFFSET es, PT_ES-PT_OLDESP;*/
+	/*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/
+	CFI_OFFSET eax, PT_EAX-PT_OLDESP
+	CFI_OFFSET ebp, PT_EBP-PT_OLDESP
+	CFI_OFFSET edi, PT_EDI-PT_OLDESP
+	CFI_OFFSET esi, PT_ESI-PT_OLDESP
+	CFI_OFFSET edx, PT_EDX-PT_OLDESP
+	CFI_OFFSET ecx, PT_ECX-PT_OLDESP
+	CFI_OFFSET ebx, PT_EBX-PT_OLDESP
+.endm
+
+ENTRY(ret_from_fork)
+	CFI_STARTPROC
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	call schedule_tail
+	GET_THREAD_INFO(%ebp)
+	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
+	pushl $0x0202			# Reset kernel eflags
+	CFI_ADJUST_CFA_OFFSET 4
+	popfl
+	CFI_ADJUST_CFA_OFFSET -4
+	jmp syscall_exit
+	CFI_ENDPROC
+END(ret_from_fork)
+
+/*
+ * Return to user mode is not as complex as all this looks,
+ * but we want the default path for a system call return to
+ * go as quickly as possible which is why some of this is
+ * less clear than it otherwise should be.
+ */
+
+	# userspace resumption stub bypassing syscall exit tracing
+	ALIGN
+	RING0_PTREGS_FRAME
+ret_from_exception:
+	preempt_stop(CLBR_ANY)
+ret_from_intr:
+	GET_THREAD_INFO(%ebp)
+check_userspace:
+	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS and CS
+	movb PT_CS(%esp), %al
+	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+	cmpl $USER_RPL, %eax
+	jb resume_kernel		# not returning to v8086 or userspace
+
+ENTRY(resume_userspace)
+	LOCKDEP_SYS_EXIT
+ 	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+					# setting need_resched or sigpending
+					# between sampling and the iret
+	TRACE_IRQS_OFF
+	movl TI_flags(%ebp), %ecx
+	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done on
+					# int/exception return?
+	jne work_pending
+	jmp restore_all
+END(ret_from_exception)
+
+#ifdef CONFIG_PREEMPT
+ENTRY(resume_kernel)
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
+	jnz restore_all
+need_resched:
+	movl TI_flags(%ebp), %ecx	# need_resched set ?
+	testb $_TIF_NEED_RESCHED, %cl
+	jz restore_all
+	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
+	jz restore_all
+	call preempt_schedule_irq
+	jmp need_resched
+END(resume_kernel)
+#endif
+	CFI_ENDPROC
+
+/* SYSENTER_RETURN points to after the "sysenter" instruction in
+   the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
+
+	# sysenter call handler stub
+ENTRY(ia32_sysenter_target)
+	CFI_STARTPROC simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA esp, 0
+	CFI_REGISTER esp, ebp
+	movl SYSENTER_stack_sp0(%esp),%esp
+sysenter_past_esp:
+	/*
+	 * Interrupts are disabled here, but we can't trace it until
+	 * enough kernel state to call TRACE_IRQS_OFF can be called - but
+	 * we immediately enable interrupts at that point anyway.
+	 */
+	pushl $(__USER_DS)
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET ss, 0*/
+	pushl %ebp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET esp, 0
+	pushfl
+	orl $X86_EFLAGS_IF, (%esp)
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $(__USER_CS)
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET cs, 0*/
+	/*
+	 * Push current_thread_info()->sysenter_return to the stack.
+	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+	 */
+	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eip, 0
+
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	ENABLE_INTERRUPTS(CLBR_NONE)
+
+/*
+ * Load the potential sixth argument from user stack.
+ * Careful about security.
+ */
+	cmpl $__PAGE_OFFSET-3,%ebp
+	jae syscall_fault
+1:	movl (%ebp),%ebp
+	movl %ebp,PT_EBP(%esp)
+.section __ex_table,"a"
+	.align 4
+	.long 1b,syscall_fault
+.previous
+
+	GET_THREAD_INFO(%ebp)
+
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+	jnz sysenter_audit
+sysenter_do_call:
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
+	call *sys_call_table(,%eax,4)
+	movl %eax,PT_EAX(%esp)
+	LOCKDEP_SYS_EXIT
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	TRACE_IRQS_OFF
+	movl TI_flags(%ebp), %ecx
+	testl $_TIF_ALLWORK_MASK, %ecx
+	jne sysexit_audit
+sysenter_exit:
+/* if something modifies registers it must also disable sysexit */
+	movl PT_EIP(%esp), %edx
+	movl PT_OLDESP(%esp), %ecx
+	xorl %ebp,%ebp
+#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
+	GET_VCPU_INFO
+#endif
+	TRACE_IRQS_ON
+1:	mov  PT_FS(%esp), %fs
+	PTGS_TO_GS
+	ENABLE_INTERRUPTS_SYSEXIT
+
+#ifdef CONFIG_AUDITSYSCALL
+sysenter_audit:
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	jnz syscall_trace_entry
+	addl $4,%esp
+	CFI_ADJUST_CFA_OFFSET -4
+	/* %esi already in 8(%esp)	   6th arg: 4th syscall arg */
+	/* %edx already in 4(%esp)	   5th arg: 3rd syscall arg */
+	/* %ecx already in 0(%esp)	   4th arg: 2nd syscall arg */
+	movl %ebx,%ecx			/* 3rd arg: 1st syscall arg */
+	movl %eax,%edx			/* 2nd arg: syscall number */
+	movl $AUDIT_ARCH_I386,%eax	/* 1st arg: audit arch */
+	call audit_syscall_entry
+	pushl %ebx
+	CFI_ADJUST_CFA_OFFSET 4
+	movl PT_EAX(%esp),%eax		/* reload syscall number */
+	jmp sysenter_do_call
+
+sysexit_audit:
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
+	jne syscall_exit_work
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_ANY)
+	movl %eax,%edx		/* second arg, syscall return value */
+	cmpl $0,%eax		/* is it < 0? */
+	setl %al		/* 1 if so, 0 if not */
+	movzbl %al,%eax		/* zero-extend that */
+	inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+	call audit_syscall_exit
+	DISABLE_INTERRUPTS(CLBR_ANY)
+	TRACE_IRQS_OFF
+	movl TI_flags(%ebp), %ecx
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %ecx
+	jne syscall_exit_work
+	movl PT_EAX(%esp),%eax	/* reload syscall return value */
+	jmp sysenter_exit
+#endif
+
+	CFI_ENDPROC
+.pushsection .fixup,"ax"
+2:	movl $0,PT_FS(%esp)
+	jmp 1b
+.section __ex_table,"a"
+	.align 4
+	.long 1b,2b
+.popsection
+	PTGS_TO_GS_EX
+ENDPROC(ia32_sysenter_target)
+
+	# pv sysenter call handler stub
+ENTRY(ia32pv_sysenter_target)
+	RING0_INT_FRAME
+	movl $__USER_DS,16(%esp)
+	movl %ebp,12(%esp)
+	movl $__USER_CS,4(%esp)
+	addl $4,%esp
+	CFI_ADJUST_CFA_OFFSET -4
+	/* +5*4 is SS:ESP,EFLAGS,CS:EIP. +8 is esp0 setting. */
+	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+	CFI_ADJUST_CFA_OFFSET 4
+/*
+ * Load the potential sixth argument from user stack.
+ * Careful about security.
+ */
+	cmpl $__PAGE_OFFSET-3,%ebp
+	jae syscall_fault
+1:	movl (%ebp),%ebp
+.section __ex_table,"a"
+	.align 4
+	.long 1b,syscall_fault
+.previous
+	/* fall through */
+	CFI_ENDPROC
+ENDPROC(ia32pv_sysenter_target)
+
+	# system call handler stub
+ENTRY(system_call)
+	RING0_INT_FRAME			# can't unwind into user space anyway
+	pushl %eax			# save orig_eax
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	GET_THREAD_INFO(%ebp)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+	jnz syscall_trace_entry
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
+syscall_call:
+	call *sys_call_table(,%eax,4)
+	movl %eax,PT_EAX(%esp)		# store the return value
+syscall_exit:
+	LOCKDEP_SYS_EXIT
+	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+					# setting need_resched or sigpending
+					# between sampling and the iret
+	TRACE_IRQS_OFF
+	movl TI_flags(%ebp), %ecx
+	testl $_TIF_ALLWORK_MASK, %ecx	# current->work
+	jne syscall_exit_work
+
+restore_all:
+	TRACE_IRQS_IRET
+restore_all_notrace:
+#ifndef CONFIG_XEN
+	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
+	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
+	# are returning to the kernel.
+	# See comments in process.c:copy_thread() for details.
+	movb PT_OLDSS(%esp), %ah
+	movb PT_CS(%esp), %al
+	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
+	CFI_REMEMBER_STATE
+	je ldt_ss			# returning to user-space with LDT SS
+restore_nocheck:
+#else
+restore_nocheck:
+	movl PT_EFLAGS(%esp), %eax
+	testl $(X86_EFLAGS_VM|NMI_MASK), %eax
+	CFI_REMEMBER_STATE
+	jnz hypervisor_iret
+	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
+	GET_VCPU_INFO
+	andb evtchn_upcall_mask(%esi),%al
+	andb $1,%al			# EAX[0] == IRET_EFLAGS.IF & event_mask
+	CFI_REMEMBER_STATE
+	jnz restore_all_enable_events	#        != 0 => enable event delivery
+#endif
+	RESTORE_REGS 4			# skip orig_eax/error_code
+	CFI_ADJUST_CFA_OFFSET -4
+irq_return:
+	INTERRUPT_RETURN
+.section .fixup,"ax"
+ENTRY(iret_exc)
+	pushl $0			# no error code
+	pushl $do_iret_error
+	jmp error_code
+.previous
+.section __ex_table,"a"
+	.align 4
+	.long irq_return,iret_exc
+.previous
+
+	CFI_RESTORE_STATE
+#ifndef CONFIG_XEN
+ldt_ss:
+	larl PT_OLDSS(%esp), %eax
+	jnz restore_nocheck
+	testl $0x00400000, %eax		# returning to 32bit stack?
+	jnz restore_nocheck		# allright, normal return
+
+#ifdef CONFIG_PARAVIRT
+	/*
+	 * The kernel can't run on a non-flat stack if paravirt mode
+	 * is active.  Rather than try to fixup the high bits of
+	 * ESP, bypass this code entirely.  This may break DOSemu
+	 * and/or Wine support in a paravirt VM, although the option
+	 * is still available to implement the setting of the high
+	 * 16-bits in the INTERRUPT_RETURN paravirt-op.
+	 */
+	cmpl $0, pv_info+PARAVIRT_enabled
+	jne restore_nocheck
+#endif
+
+/*
+ * Setup and switch to ESPFIX stack
+ *
+ * We're returning to userspace with a 16 bit stack. The CPU will not
+ * restore the high word of ESP for us on executing iret... This is an
+ * "official" bug of all the x86-compatible CPUs, which we can work
+ * around to make dosemu and wine happy. We do this by preloading the
+ * high word of ESP with the high word of the userspace ESP while
+ * compensating for the offset by changing to the ESPFIX segment with
+ * a base address that matches for the difference.
+ */
+	mov %esp, %edx			/* load kernel esp */
+	mov PT_OLDESP(%esp), %eax	/* load userspace esp */
+	mov %dx, %ax			/* eax: new kernel esp */
+	sub %eax, %edx			/* offset (low word is 0) */
+	PER_CPU(gdt_page, %ebx)
+	shr $16, %edx
+	mov %dl, GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx) /* bits 16..23 */
+	mov %dh, GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx) /* bits 24..31 */
+	pushl $__ESPFIX_SS
+	CFI_ADJUST_CFA_OFFSET 4
+	push %eax			/* new kernel esp */
+	CFI_ADJUST_CFA_OFFSET 4
+	/* Disable interrupts, but do not irqtrace this section: we
+	 * will soon execute iret and the tracer was already set to
+	 * the irqstate after the iret */
+	DISABLE_INTERRUPTS(CLBR_EAX)
+	lss (%esp), %esp		/* switch to espfix segment */
+	CFI_ADJUST_CFA_OFFSET -8
+	jmp restore_nocheck
+#else
+        ALIGN
+restore_all_enable_events:
+	TRACE_IRQS_ON
+	__ENABLE_INTERRUPTS
+scrit:	/**** START OF CRITICAL REGION ****/
+	__TEST_PENDING
+	jnz  14f			# process more events if necessary...
+	RESTORE_REGS 4
+1:	INTERRUPT_RETURN
+.section __ex_table,"a"
+	.align 4
+	.long 1b,iret_exc
+.previous
+14:	__DISABLE_INTERRUPTS
+	TRACE_IRQS_OFF
+ecrit:  /**** END OF CRITICAL REGION ****/
+	jmp  .Ldo_upcall
+
+	CFI_RESTORE_STATE
+hypervisor_iret:
+	andl $~NMI_MASK, PT_EFLAGS(%esp)
+	RESTORE_REGS 4
+	jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+#endif
+	CFI_ENDPROC
+ENDPROC(system_call)
+
+	# perform work that needs to be done immediately before resumption
+	ALIGN
+	RING0_PTREGS_FRAME		# can't unwind into user space anyway
+work_pending:
+	testb $_TIF_NEED_RESCHED, %cl
+	jz work_notifysig
+work_resched:
+	call schedule
+	LOCKDEP_SYS_EXIT
+	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
+					# setting need_resched or sigpending
+					# between sampling and the iret
+	TRACE_IRQS_OFF
+	movl TI_flags(%ebp), %ecx
+	andl $_TIF_WORK_MASK, %ecx	# is there any work to be done other
+					# than syscall tracing?
+	jz restore_all
+	testb $_TIF_NEED_RESCHED, %cl
+	jnz work_resched
+
+work_notifysig:				# deal with pending signals and
+					# notify-resume requests
+#ifdef CONFIG_VM86
+	testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
+	movl %esp, %eax
+	jne work_notifysig_v86		# returning to kernel-space or
+					# vm86-space
+	xorl %edx, %edx
+	call do_notify_resume
+	jmp resume_userspace_sig
+
+	ALIGN
+work_notifysig_v86:
+	pushl %ecx			# save ti_flags for do_notify_resume
+	CFI_ADJUST_CFA_OFFSET 4
+	call save_v86_state		# %eax contains pt_regs pointer
+	popl %ecx
+	CFI_ADJUST_CFA_OFFSET -4
+	movl %eax, %esp
+#else
+	movl %esp, %eax
+#endif
+	xorl %edx, %edx
+	call do_notify_resume
+	jmp resume_userspace_sig
+END(work_pending)
+
+	# perform syscall exit tracing
+	ALIGN
+syscall_trace_entry:
+	movl $-ENOSYS,PT_EAX(%esp)
+	movl %esp, %eax
+	call syscall_trace_enter
+	/* What it returned is what we'll actually use.  */
+	cmpl $(nr_syscalls), %eax
+	jnae syscall_call
+	jmp syscall_exit
+END(syscall_trace_entry)
+
+	# perform syscall exit tracing
+	ALIGN
+syscall_exit_work:
+	testl $_TIF_WORK_SYSCALL_EXIT, %ecx
+	jz work_pending
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
+					# schedule() instead
+	movl %esp, %eax
+	call syscall_trace_leave
+	jmp resume_userspace
+END(syscall_exit_work)
+	CFI_ENDPROC
+
+	RING0_INT_FRAME			# can't unwind into user space anyway
+syscall_fault:
+	GET_THREAD_INFO(%ebp)
+	movl $-EFAULT,PT_EAX(%esp)
+	jmp resume_userspace
+END(syscall_fault)
+
+syscall_badsys:
+	movl $-ENOSYS,PT_EAX(%esp)
+	jmp resume_userspace
+END(syscall_badsys)
+	CFI_ENDPROC
+
+/*
+ * System calls that need a pt_regs pointer.
+ */
+#define PTREGSCALL(name) \
+	ALIGN; \
+ptregs_##name: \
+	leal 4(%esp),%eax; \
+	jmp sys_##name;
+
+PTREGSCALL(iopl)
+PTREGSCALL(fork)
+PTREGSCALL(clone)
+PTREGSCALL(vfork)
+PTREGSCALL(execve)
+PTREGSCALL(sigaltstack)
+PTREGSCALL(sigreturn)
+PTREGSCALL(rt_sigreturn)
+PTREGSCALL(vm86)
+PTREGSCALL(vm86old)
+
+#ifndef CONFIG_XEN
+.macro FIXUP_ESPFIX_STACK
+/*
+ * Switch back for ESPFIX stack to the normal zerobased stack
+ *
+ * We can't call C functions using the ESPFIX stack. This code reads
+ * the high word of the segment base from the GDT and swiches to the
+ * normal stack and adjusts ESP with the matching offset.
+ */
+	/* fixup the stack */
+	PER_CPU(gdt_page, %ebx)
+	mov GDT_ENTRY_ESPFIX_SS * 8 + 4(%ebx), %al /* bits 16..23 */
+	mov GDT_ENTRY_ESPFIX_SS * 8 + 7(%ebx), %ah /* bits 24..31 */
+	shl $16, %eax
+	addl %esp, %eax			/* the adjusted stack pointer */
+	pushl $__KERNEL_DS
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	lss (%esp), %esp		/* switch to the normal stack segment */
+	CFI_ADJUST_CFA_OFFSET -8
+.endm
+.macro UNWIND_ESPFIX_STACK
+	movl %ss, %eax
+	/* see if on espfix stack */
+	cmpw $__ESPFIX_SS, %ax
+	jne 27f
+	movl $__KERNEL_DS, %eax
+	movl %eax, %ds
+	movl %eax, %es
+	/* switch to normal stack */
+	FIXUP_ESPFIX_STACK
+27:
+.endm
+
+/*
+ * Build the entry stubs and pointer table with some assembler magic.
+ * We pack 7 stubs into a single 32-byte chunk, which will fit in a
+ * single cache line on all modern x86 implementations.
+ */
+.section .init.rodata,"a"
+ENTRY(interrupt)
+.text
+	.p2align 5
+	.p2align CONFIG_X86_L1_CACHE_SHIFT
+ENTRY(irq_entries_start)
+	RING0_INT_FRAME
+vector=FIRST_EXTERNAL_VECTOR
+.rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7
+	.balign 32
+  .rept	7
+    .if vector < NR_VECTORS
+      .if vector <> FIRST_EXTERNAL_VECTOR
+	CFI_ADJUST_CFA_OFFSET -4
+      .endif
+1:	pushl $(~vector+0x80)	/* Note: always in signed byte range */
+	CFI_ADJUST_CFA_OFFSET 4
+      .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 6
+	jmp 2f
+      .endif
+      .previous
+	.long 1b
+      .text
+vector=vector+1
+    .endif
+  .endr
+2:	jmp common_interrupt
+.endr
+END(irq_entries_start)
+
+.previous
+END(interrupt)
+.previous
+
+/*
+ * the CPU automatically disables interrupts when executing an IRQ vector,
+ * so IRQ-flags tracing has to follow that:
+ */
+	.p2align CONFIG_X86_L1_CACHE_SHIFT
+common_interrupt:
+	addl $-0x80,(%esp)	/* Adjust vector into the [-256,-1] range */
+	SAVE_ALL
+	TRACE_IRQS_OFF
+	movl %esp,%eax
+	call do_IRQ
+	jmp ret_from_intr
+ENDPROC(common_interrupt)
+	CFI_ENDPROC
+
+#define BUILD_INTERRUPT3(name, nr, fn)	\
+ENTRY(name)				\
+	RING0_INT_FRAME;		\
+	pushl $~(nr);			\
+	CFI_ADJUST_CFA_OFFSET 4;	\
+	SAVE_ALL;			\
+	TRACE_IRQS_OFF			\
+	movl %esp,%eax;			\
+	call fn;			\
+	jmp ret_from_intr;		\
+	CFI_ENDPROC;			\
+ENDPROC(name)
+
+#define BUILD_INTERRUPT(name, nr)	BUILD_INTERRUPT3(name, nr, smp_##name)
+
+/* The include is where all of the SMP etc. interrupts come from */
+#include <asm/entry_arch.h>
+
+#else
+#define UNWIND_ESPFIX_STACK
+
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
+# until we've done all processing. HOWEVER, we must enable events before
+# popping the stack frame (can't be done atomically) and so it would still
+# be possible to get enough handler activations to overflow the stack.
+# Although unlikely, bugs of that kind are hard to track down, so we'd
+# like to avoid the possibility.
+# So, on entry to the handler we detect whether we interrupted an
+# existing activation in its critical region -- if so, we pop the current
+# activation and restart the handler using the previous one.
+#
+# The sysexit critical region is slightly different. sysexit
+# atomically removes the entire stack frame. If we interrupt in the
+# critical region we know that the entire frame is present and correct
+# so we can simply throw away the new one.
+ENTRY(hypervisor_callback)
+	RING0_INT_FRAME
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	movl PT_CS(%esp),%ecx
+	movl PT_EIP(%esp),%eax
+	andl $SEGMENT_RPL_MASK,%ecx
+	cmpl $USER_RPL,%ecx
+	jae  .Ldo_upcall
+	cmpl $scrit,%eax
+	jb   0f
+	cmpl $ecrit,%eax
+	jb   critical_region_fixup
+0:
+#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL
+	cmpl $sysexit_scrit,%eax
+	jb   .Ldo_upcall
+	cmpl $sysexit_ecrit,%eax
+	ja   .Ldo_upcall
+	addl $PT_OLDESP,%esp		# Remove eflags...ebx from stack frame.
+#endif
+.Ldo_upcall:
+	push %esp
+	CFI_ADJUST_CFA_OFFSET 4
+	call evtchn_do_upcall
+	add  $4,%esp
+	CFI_ADJUST_CFA_OFFSET -4
+	jmp  ret_from_intr
+	CFI_ENDPROC
+
+# [How we do the fixup]. We want to merge the current stack frame with the
+# just-interrupted frame. How we do this depends on where in the critical
+# region the interrupted handler was executing, and so how many saved
+# registers are in each frame. We do this quickly using the lookup table
+# 'critical_fixup_table'. For each byte offset in the critical region, it
+# provides the number of bytes which have already been popped from the
+# interrupted stack frame.
+critical_region_fixup:
+	movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped
+	testl %ecx,%ecx
+	leal (%esp,%ecx,4),%esi		# %esi points at end of src region
+	leal PT_OLDESP(%esp),%edi	# %edi points at end of dst region
+	jle   17f			# skip loop if nothing to copy
+16:	subl $4,%esi			# pre-decrementing copy loop
+	subl $4,%edi
+	movl (%esi),%eax
+	movl %eax,(%edi)
+	loop 16b
+17:	movl %edi,%esp			# final %edi is top of merged stack
+	jmp  .Ldo_upcall
+
+.section .rodata,"a"
+critical_fixup_table:
+	.rept __SIZEOF_TEST_PENDING
+	.byte -1
+	.endr
+	.byte -1,-1			# jnz  14f
+	.byte 0				# pop  %ebx
+	.byte 1				# pop  %ecx
+	.byte 2				# pop  %edx
+	.byte 3				# pop  %esi
+	.byte 4				# pop  %edi
+	.byte 5				# pop  %ebp
+	.byte 6				# pop  %eax
+	.byte 7				# pop  %ds
+	.byte 8				# pop  %es
+	.byte 9,9			# pop  %fs
+#ifndef CONFIG_X86_32_LAZY_GS
+	.byte 10,10			# pop  %gs
+	.byte 11,11,11			# add  $4,%esp
+#else
+	.byte 10,10,10			# add  $8,%esp
+#endif
+	.byte 12			# iret
+	.rept __SIZEOF_DISABLE_INTERRUPTS
+	.byte -1
+	.endr
+.previous
+
+# Hypervisor uses this for application faults while it executes.
+# We get here for two reasons:
+#  1. Fault while reloading DS, ES, FS or GS
+#  2. Fault while executing IRET
+# Category 1 we fix up by reattempting the load, and zeroing the segment
+# register if the load fails.
+# Category 2 we fix up by jumping to do_iret_error. We cannot use the
+# normal Linux return path in this case because if we use the IRET hypercall
+# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
+# We distinguish between categories by maintaining a status value in EAX.
+ENTRY(failsafe_callback)
+	pushl %eax
+	movl $1,%eax
+1:	mov 4(%esp),%ds
+2:	mov 8(%esp),%es
+3:	mov 12(%esp),%fs
+4:	mov 16(%esp),%gs
+	testl %eax,%eax
+	popl %eax
+	jz 5f
+	addl $16,%esp		# EAX != 0 => Category 2 (Bad IRET)
+	jmp iret_exc
+5:	addl $16,%esp		# EAX == 0 => Category 1 (Bad segment)
+	RING0_INT_FRAME
+	pushl $0
+	SAVE_ALL
+	jmp ret_from_exception
+.section .fixup,"ax";		\
+6:	xorl %eax,%eax;		\
+	movl %eax,4(%esp);	\
+	jmp 1b;			\
+7:	xorl %eax,%eax;		\
+	movl %eax,8(%esp);	\
+	jmp 2b;			\
+8:	xorl %eax,%eax;		\
+	movl %eax,12(%esp);	\
+	jmp 3b;			\
+9:	xorl %eax,%eax;		\
+	movl %eax,16(%esp);	\
+	jmp 4b;			\
+.previous;			\
+.section __ex_table,"a";	\
+	.align 4;		\
+	.long 1b,6b;		\
+	.long 2b,7b;		\
+	.long 3b,8b;		\
+	.long 4b,9b;		\
+.previous
+#endif
+	CFI_ENDPROC
+
+ENTRY(coprocessor_error)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_coprocessor_error
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(coprocessor_error)
+
+ENTRY(simd_coprocessor_error)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_simd_coprocessor_error
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(simd_coprocessor_error)
+
+ENTRY(device_not_available)
+	RING0_INT_FRAME
+	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_device_not_available
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(device_not_available)
+
+#ifdef CONFIG_PARAVIRT
+ENTRY(native_iret)
+	iret
+.section __ex_table,"a"
+	.align 4
+	.long native_iret, iret_exc
+.previous
+END(native_iret)
+
+ENTRY(native_irq_enable_sysexit)
+	sti
+	sysexit
+END(native_irq_enable_sysexit)
+#endif
+
+ENTRY(overflow)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_overflow
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(overflow)
+
+ENTRY(bounds)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_bounds
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(bounds)
+
+ENTRY(invalid_op)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_invalid_op
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(invalid_op)
+
+ENTRY(coprocessor_segment_overrun)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_coprocessor_segment_overrun
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(coprocessor_segment_overrun)
+
+ENTRY(invalid_TSS)
+	RING0_EC_FRAME
+	pushl $do_invalid_TSS
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(invalid_TSS)
+
+ENTRY(segment_not_present)
+	RING0_EC_FRAME
+	pushl $do_segment_not_present
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(segment_not_present)
+
+ENTRY(stack_segment)
+	RING0_EC_FRAME
+	pushl $do_stack_segment
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(stack_segment)
+
+ENTRY(alignment_check)
+	RING0_EC_FRAME
+	pushl $do_alignment_check
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(alignment_check)
+
+ENTRY(divide_error)
+	RING0_INT_FRAME
+	pushl $0			# no error code
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_divide_error
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(divide_error)
+
+#ifdef CONFIG_X86_MCE
+ENTRY(machine_check)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl machine_check_vector
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(machine_check)
+#endif
+
+#ifndef CONFIG_XEN
+ENTRY(spurious_interrupt_bug)
+	RING0_INT_FRAME
+	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $do_spurious_interrupt_bug
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+#endif /* !CONFIG_XEN */
+
+ENTRY(fixup_4gb_segment)
+	RING0_EC_FRAME
+	pushl $do_fixup_4gb_segment
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(spurious_interrupt_bug)
+
+#ifdef CONFIG_STACK_UNWIND
+ENTRY(arch_unwind_init_running)
+	CFI_STARTPROC
+	movl	4(%esp), %edx
+	movl	(%esp), %ecx
+	leal	4(%esp), %eax
+	movl	%ebx, PT_EBX(%edx)
+	xorl	%ebx, %ebx
+	movl	%ebx, PT_ECX(%edx)
+	movl	%ebx, PT_EDX(%edx)
+	movl	%esi, PT_ESI(%edx)
+	movl	%edi, PT_EDI(%edx)
+	movl	%ebp, PT_EBP(%edx)
+	movl	%ebx, PT_EAX(%edx)
+	movl	$__USER_DS, PT_DS(%edx)
+	movl	$__USER_DS, PT_ES(%edx)
+	movl	$__KERNEL_PERCPU, PT_FS(%edx)
+	movl	$__KERNEL_STACK_CANARY, PT_GS(%edx)
+	movl	%eax, PT_OLDESP(%edx)
+	movl	16(%esp), %eax
+	movl	%ebx, PT_ORIG_EAX(%edx)
+	movl	%ecx, PT_EIP(%edx)
+	movl	12(%esp), %ecx
+	movl	$__KERNEL_CS, PT_CS(%edx)
+	movl	%eax, 12(%esp)
+	movl	8(%esp), %eax
+	movl	%ecx, 8(%esp)
+	movl	%ebx, PT_EFLAGS(%edx)
+	movl	PT_EBX(%edx), %ebx
+	movl	$__KERNEL_DS, PT_OLDSS(%edx)
+	jmpl	*%eax
+	CFI_ENDPROC
+ENDPROC(arch_unwind_init_running)
+#endif
+
+ENTRY(kernel_thread_helper)
+	pushl $0		# fake return address for unwinder
+	CFI_STARTPROC
+	movl %edx,%eax
+	push %edx
+	CFI_ADJUST_CFA_OFFSET 4
+	call *%ebx
+	push %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	call do_exit
+	ud2			# padding for call trace
+	CFI_ENDPROC
+ENDPROC(kernel_thread_helper)
+
+#ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+ENTRY(mcount)
+	ret
+END(mcount)
+
+ENTRY(ftrace_caller)
+	cmpl $0, function_trace_stop
+	jne  ftrace_stub
+
+	pushl %eax
+	pushl %ecx
+	pushl %edx
+	movl 0xc(%esp), %eax
+	movl 0x4(%ebp), %edx
+	subl $MCOUNT_INSN_SIZE, %eax
+
+.globl ftrace_call
+ftrace_call:
+	call ftrace_stub
+
+	popl %edx
+	popl %ecx
+	popl %eax
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+.globl ftrace_graph_call
+ftrace_graph_call:
+	jmp ftrace_stub
+#endif
+
+.globl ftrace_stub
+ftrace_stub:
+	ret
+END(ftrace_caller)
+
+#else /* ! CONFIG_DYNAMIC_FTRACE */
+
+ENTRY(mcount)
+	cmpl $0, function_trace_stop
+	jne  ftrace_stub
+
+	cmpl $ftrace_stub, ftrace_trace_function
+	jnz trace
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	cmpl $ftrace_stub, ftrace_graph_return
+	jnz ftrace_graph_caller
+
+	cmpl $ftrace_graph_entry_stub, ftrace_graph_entry
+	jnz ftrace_graph_caller
+#endif
+.globl ftrace_stub
+ftrace_stub:
+	ret
+
+	/* taken from glibc */
+trace:
+	pushl %eax
+	pushl %ecx
+	pushl %edx
+	movl 0xc(%esp), %eax
+	movl 0x4(%ebp), %edx
+	subl $MCOUNT_INSN_SIZE, %eax
+
+	call *ftrace_trace_function
+
+	popl %edx
+	popl %ecx
+	popl %eax
+	jmp ftrace_stub
+END(mcount)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+	cmpl $0, function_trace_stop
+	jne ftrace_stub
+
+	pushl %eax
+	pushl %ecx
+	pushl %edx
+	movl 0xc(%esp), %edx
+	lea 0x4(%ebp), %eax
+	movl (%ebp), %ecx
+	subl $MCOUNT_INSN_SIZE, %edx
+	call prepare_ftrace_return
+	popl %edx
+	popl %ecx
+	popl %eax
+	ret
+END(ftrace_graph_caller)
+
+.globl return_to_handler
+return_to_handler:
+	pushl $0
+	pushl %eax
+	pushl %ecx
+	pushl %edx
+	movl %ebp, %eax
+	call ftrace_return_to_handler
+	movl %eax, 0xc(%esp)
+	popl %edx
+	popl %ecx
+	popl %eax
+	ret
+#endif
+
+#include <asm/alternative-asm.h>
+
+	# pv syscall call handler stub
+ENTRY(ia32pv_cstar_target)
+	RING0_INT_FRAME
+	movl $__USER_DS,16(%esp)
+	movl %ebp,%ecx
+	movl $__USER_CS,4(%esp)
+	movl 12(%esp),%ebp
+	pushl %eax			# save orig_eax
+	CFI_ADJUST_CFA_OFFSET 4
+/*
+ * Load the potential sixth argument from user stack.
+ * Careful about security.
+ */
+	cmpl $__PAGE_OFFSET-4,%ebp
+	CFI_REMEMBER_STATE
+	ja cstar_fault
+1:	movl (%ebp),%ebp
+.section __ex_table,"a"
+	.align 4
+	.long 1b,cstar_fault
+.previous
+	SAVE_ALL
+	GET_THREAD_INFO(%ebp)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
+	jnz cstar_trace_entry
+	cmpl $nr_syscalls,%eax
+	jae cstar_badsys
+.Lcstar_call:
+	btl %eax,cstar_special
+	jc .Lcstar_special
+	call *cstar_call_table(,%eax,4)
+	movl %eax,PT_EAX(%esp)		# store the return value
+.Lcstar_exit:
+	movl PT_ECX(%esp),%ecx
+	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+	jmp syscall_exit
+.Lcstar_special:
+	movl PT_ECX(%esp),%ecx
+	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+	jmp syscall_call
+cstar_set_tif:
+	movl $cstar_clear_tif,(%esp)	# replace return address
+	LOCK_PREFIX
+	orl $_TIF_CSTAR,TI_flags(%ebp)
+	jmp *sys_call_table(,%eax,4)
+cstar_clear_tif:
+	movl %eax,PT_EAX(%esp)		# store the return value
+	LOCK_PREFIX
+	andl $~_TIF_CSTAR,TI_flags(%ebp)
+	jmp .Lcstar_exit
+cstar_trace_entry:
+	movl $-ENOSYS,PT_EAX(%esp)
+	cmpl $nr_syscalls,%eax
+	jae 1f
+	btl %eax,cstar_special
+	jc .Lcstar_trace_special
+1:	movl %esp,%eax
+	LOCK_PREFIX
+	orl $_TIF_CSTAR,TI_flags(%ebp)
+	call syscall_trace_enter
+	LOCK_PREFIX
+	andl $~_TIF_CSTAR,TI_flags(%ebp)
+	/* What it returned is what we'll actually use.  */
+	cmpl $nr_syscalls,%eax
+	jb .Lcstar_call
+	jmp .Lcstar_exit
+.Lcstar_trace_special:
+	movl PT_ECX(%esp),%ecx
+	movl %esp,%eax
+	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+	call syscall_trace_enter
+	/* What it returned is what we'll actually use.  */
+	cmpl $nr_syscalls,%eax
+	jb syscall_call
+	jmp syscall_exit
+cstar_badsys:
+	movl $-ENOSYS,PT_EAX(%esp)
+.Lcstar_resume:
+	movl PT_ECX(%esp),%ecx
+	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+	jmp resume_userspace
+	CFI_RESTORE_STATE
+cstar_fault:
+	movl $-EFAULT,%eax
+	SAVE_ALL
+	GET_THREAD_INFO(%ebp)
+	jmp .Lcstar_resume
+	CFI_ENDPROC
+ENDPROC(ia32pv_cstar_target)
+
+ENTRY(cstar_ret_from_fork)
+	CFI_STARTPROC
+	movl PT_ECX(%esp),%ecx
+	GET_THREAD_INFO(%ebp)
+	movl %ecx,PT_EBP(%esp)		# put user EBP back in place
+	LOCK_PREFIX
+	andl $~_TIF_CSTAR,TI_flags(%ebp)
+	jmp ret_from_fork
+	CFI_ENDPROC
+END(ret_from_fork)
+
+.section .rodata,"a"
+#include "syscall_table_32.S"
+
+syscall_table_size=(.-sys_call_table)
+
+#include <asm/unistd.h>
+cstar_special:
+nr=0
+mask=0
+.rept nr_syscalls+31
+ .irp n, __NR_sigreturn, __NR_rt_sigreturn
+  .if nr == \n
+   mask = mask | (1 << (\n & 31))
+  .endif
+ .endr
+ nr = nr + 1
+ .if (nr & 31) == 0
+  .long mask
+  mask = 0
+ .endif
+.endr
+#define	sys_call_table cstar_call_table
+#define	sys_fork cstar_set_tif
+#define	sys_clone cstar_set_tif
+#define	sys_vfork cstar_set_tif
+#include "syscall_table_32.S"
+#undef	sys_call_table
+#undef	sys_fork
+#undef	sys_clone
+#undef	sys_vfork
+
+/*
+ * Some functions should be protected against kprobes
+ */
+	.pushsection .kprobes.text, "ax"
+
+ENTRY(page_fault)
+	RING0_EC_FRAME
+	pushl $do_page_fault
+	CFI_ADJUST_CFA_OFFSET 4
+	ALIGN
+error_code:
+	/* the function address is in %gs's slot on the stack */
+	pushl %fs
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET fs, 0*/
+	pushl %es
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET es, 0*/
+	pushl %ds
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET ds, 0*/
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eax, 0
+	pushl %ebp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebp, 0
+	pushl %edi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edi, 0
+	pushl %esi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET esi, 0
+	pushl %edx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edx, 0
+	pushl %ecx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ecx, 0
+	pushl %ebx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebx, 0
+	cld
+	movl $(__KERNEL_PERCPU), %ecx
+	movl %ecx, %fs
+	UNWIND_ESPFIX_STACK
+	GS_TO_REG %ecx
+	movl PT_GS(%esp), %edi		# get the function address
+	movl PT_ORIG_EAX(%esp), %edx	# get the error code
+	movl $-1, PT_ORIG_EAX(%esp)	# no syscall to restart
+	REG_TO_PTGS %ecx
+	SET_KERNEL_GS %ecx
+	movl $(__USER_DS), %ecx
+	movl %ecx, %ds
+	movl %ecx, %es
+	TRACE_IRQS_OFF
+	movl %esp,%eax			# pt_regs pointer
+	call *%edi
+	jmp ret_from_exception
+	CFI_ENDPROC
+END(page_fault)
+
+#ifndef CONFIG_XEN
+/*
+ * Debug traps and NMI can happen at the one SYSENTER instruction
+ * that sets up the real kernel stack. Check here, since we can't
+ * allow the wrong stack to be used.
+ *
+ * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
+ * already pushed 3 words if it hits on the sysenter instruction:
+ * eflags, cs and eip.
+ *
+ * We just load the right stack, and push the three (known) values
+ * by hand onto the new stack - while updating the return eip past
+ * the instruction that would have done it for sysenter.
+ */
+.macro FIX_STACK offset ok label
+	cmpw $__KERNEL_CS, 4(%esp)
+	jne \ok
+\label:
+	movl TSS_sysenter_sp0 + \offset(%esp), %esp
+	CFI_DEF_CFA esp, 0
+	CFI_UNDEFINED eip
+	pushfl
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $__KERNEL_CS
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl $sysenter_past_esp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eip, 0
+.endm
+#endif /* CONFIG_XEN */
+
+ENTRY(debug)
+	RING0_INT_FRAME
+#ifndef CONFIG_XEN
+	cmpl $ia32_sysenter_target,(%esp)
+	jne debug_stack_correct
+	FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
+debug_stack_correct:
+#endif /* !CONFIG_XEN */
+	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	TRACE_IRQS_OFF
+	xorl %edx,%edx			# error code 0
+	movl %esp,%eax			# pt_regs pointer
+	call do_debug
+	jmp ret_from_exception
+	CFI_ENDPROC
+END(debug)
+
+/*
+ * NMI is doubly nasty. It can happen _while_ we're handling
+ * a debug fault, and the debug fault hasn't yet been able to
+ * clear up the stack. So we first check whether we got  an
+ * NMI on the sysenter entry path, but after that we need to
+ * check whether we got an NMI on the debug path where the debug
+ * fault happened on the sysenter path.
+ */
+ENTRY(nmi)
+	RING0_INT_FRAME
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+#ifndef CONFIG_XEN
+	movl %ss, %eax
+	cmpw $__ESPFIX_SS, %ax
+	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
+	je nmi_espfix_stack
+	cmpl $ia32_sysenter_target,(%esp)
+	je nmi_stack_fixup
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	movl %esp,%eax
+	/* Do not access memory above the end of our stack page,
+	 * it might not exist.
+	 */
+	andl $(THREAD_SIZE-1),%eax
+	cmpl $(THREAD_SIZE-20),%eax
+	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
+	jae nmi_stack_correct
+	cmpl $ia32_sysenter_target,12(%esp)
+	je nmi_debug_stack_check
+nmi_stack_correct:
+	/* We have a RING0_INT_FRAME here */
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	xorl %edx,%edx		# zero error code
+	movl %esp,%eax		# pt_regs pointer
+	call do_nmi
+	jmp restore_all_notrace
+	CFI_ENDPROC
+
+nmi_stack_fixup:
+	RING0_INT_FRAME
+	FIX_STACK 12, nmi_stack_correct, 1
+	jmp nmi_stack_correct
+
+nmi_debug_stack_check:
+	/* We have a RING0_INT_FRAME here */
+	cmpw $__KERNEL_CS,16(%esp)
+	jne nmi_stack_correct
+	cmpl $debug,(%esp)
+	jb nmi_stack_correct
+	cmpl $debug_esp_fix_insn,(%esp)
+	ja nmi_stack_correct
+	FIX_STACK 24, nmi_stack_correct, 1
+	jmp nmi_stack_correct
+
+nmi_espfix_stack:
+	/* We have a RING0_INT_FRAME here.
+	 *
+	 * create the pointer to lss back
+	 */
+	pushl %ss
+	CFI_ADJUST_CFA_OFFSET 4
+	pushl %esp
+	CFI_ADJUST_CFA_OFFSET 4
+	addl $4, (%esp)
+	/* copy the iret frame of 12 bytes */
+	.rept 3
+	pushl 16(%esp)
+	CFI_ADJUST_CFA_OFFSET 4
+	.endr
+	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	FIXUP_ESPFIX_STACK		# %eax == %esp
+	xorl %edx,%edx			# zero error code
+	call do_nmi
+	RESTORE_REGS
+	lss 12+4(%esp), %esp		# back to espfix stack
+	CFI_ADJUST_CFA_OFFSET -24
+	jmp irq_return
+#else
+	SAVE_ALL
+	xorl %edx,%edx		# zero error code
+	movl %esp,%eax		# pt_regs pointer
+	call do_nmi
+	orl  $NMI_MASK, PT_EFLAGS(%esp)
+	jmp restore_all
+#endif
+	CFI_ENDPROC
+END(nmi)
+
+ENTRY(int3)
+	RING0_INT_FRAME
+	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
+	SAVE_ALL
+	TRACE_IRQS_OFF
+	xorl %edx,%edx		# zero error code
+	movl %esp,%eax		# pt_regs pointer
+	call do_int3
+	jmp ret_from_exception
+	CFI_ENDPROC
+END(int3)
+
+ENTRY(general_protection)
+	RING0_EC_FRAME
+	pushl $do_general_protection
+	CFI_ADJUST_CFA_OFFSET 4
+	jmp error_code
+	CFI_ENDPROC
+END(general_protection)
+
+/*
+ * End of kprobes section
+ */
+	.popsection
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pci-gart_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pci-gart_64.c
@@ -553,6 +553,9 @@
 
 		enable_gart_translation(dev, __pa(agp_gatt_table));
 	}
+
+	/* Flush the GART-TLB to remove stale entries */
+	k8_flush_garts();
 }
 
 /*
@@ -717,7 +720,7 @@
 	unsigned long scratch;
 	long i;
 
-	if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0)
+	if (num_k8_northbridges == 0)
 		return;
 
 #ifndef CONFIG_AGP_AMD64
@@ -856,7 +859,7 @@
 #endif
 	if (isdigit(*p) && get_option(&p, &arg))
 		iommu_size = arg;
-	if (!strncmp(p, "fullflush", 8))
+	if (!strncmp(p, "fullflush", 9))
 		iommu_fullflush = 1;
 	if (!strncmp(p, "nofullflush", 11))
 		iommu_fullflush = 0;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/relocate_kernel_64.S
+++ linux-ec2-2.6.32/arch/x86/kernel/relocate_kernel_64.S
@@ -91,13 +91,30 @@
 	/* Switch to the identity mapped page tables */
 	movq	%r9, %cr3
 
+	/* setup idt */
+	lidtq	idt_80 - relocate_kernel(%r8)
+
+	/* setup gdt */
+	leaq	gdt - relocate_kernel(%r8), %rax
+	movq	%rax, (gdt_80 - relocate_kernel) + 2(%r8)
+	lgdtq	gdt_80 - relocate_kernel(%r8)
+
+	/* setup data segment registers */
+	xorl	%eax, %eax
+	movl	%eax, %ds
+	movl	%eax, %es
+	movl	%eax, %fs
+	movl	%eax, %gs
+	movl	%eax, %ss
+
 	/* setup a new stack at the end of the physical control page */
 	lea	PAGE_SIZE(%r8), %rsp
 
-	/* jump to identity mapped page */
+	/* load new code segment and jump to identity mapped page */
 	addq	$(identity_mapped - relocate_kernel), %r8
+	pushq	$(gdt_cs - gdt)
 	pushq	%r8
-	ret
+	lretq
 
 identity_mapped:
 	/* store the start address on the stack */
@@ -262,5 +279,20 @@
 3:
 	ret
 
+	.align  16
+gdt:
+	.quad	0x0000000000000000	/* NULL descriptor */
+gdt_cs:
+	.quad   0x00af9a000000ffff
+gdt_end:
+
+gdt_80:
+	.word	gdt_end - gdt - 1	/* limit */
+	.quad	0			/* base - filled in by code above */
+
+idt_80:
+	.word	0			/* limit */
+	.quad	0			/* base */
+
 	.globl kexec_control_code_size
 .set kexec_control_code_size, . - relocate_kernel
--- linux-ec2-2.6.32.orig/arch/x86/kernel/smp.c
+++ linux-ec2-2.6.32/arch/x86/kernel/smp.c
@@ -158,10 +158,10 @@
 	irq_exit();
 }
 
-static void native_smp_send_stop(void)
+static void native_stop_other_cpus(int wait)
 {
 	unsigned long flags;
-	unsigned long wait;
+	unsigned long timeout;
 
 	if (reboot_force)
 		return;
@@ -178,9 +178,12 @@
 	if (num_online_cpus() > 1) {
 		apic->send_IPI_allbutself(REBOOT_VECTOR);
 
-		/* Don't wait longer than a second */
-		wait = USEC_PER_SEC;
-		while (num_online_cpus() > 1 && wait--)
+		/*
+		 * Don't wait longer than a second if the caller
+		 * didn't ask us to wait.
+		 */
+		timeout = USEC_PER_SEC;
+		while (num_online_cpus() > 1 && (wait || timeout--))
 			udelay(1);
 	}
 
@@ -226,7 +229,7 @@
 	.smp_prepare_cpus	= native_smp_prepare_cpus,
 	.smp_cpus_done		= native_smp_cpus_done,
 
-	.smp_send_stop		= native_smp_send_stop,
+	.stop_other_cpus	= native_stop_other_cpus,
 	.smp_send_reschedule	= native_smp_send_reschedule,
 
 	.cpu_up			= native_cpu_up,
--- linux-ec2-2.6.32.orig/arch/x86/kernel/quirks.c
+++ linux-ec2-2.6.32/arch/x86/kernel/quirks.c
@@ -491,6 +491,19 @@
 		break;
 	}
 }
+
+/*
+ * HPET MSI on some boards (ATI SB700/SB800) has side effect on
+ * floppy DMA. Disable HPET MSI on such platforms.
+ */
+static void force_disable_hpet_msi(struct pci_dev *unused)
+{
+	hpet_msi_disable = 1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+			 force_disable_hpet_msi);
+
 #endif
 
 #if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
@@ -499,6 +512,7 @@
 {
 	struct pci_dev *nb_ht;
 	unsigned int devfn;
+	u32 node;
 	u32 val;
 
 	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
@@ -507,7 +521,13 @@
 		return;
 
 	pci_read_config_dword(nb_ht, 0x60, &val);
-	set_dev_node(&dev->dev, val & 7);
+	node = val & 7;
+	/*
+	 * Some hardware may return an invalid node ID,
+	 * so check it first:
+	 */
+	if (node_online(node))
+		set_dev_node(&dev->dev, node);
 	pci_dev_put(nb_ht);
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/olpc.c
+++ linux-ec2-2.6.32/arch/x86/kernel/olpc.c
@@ -115,6 +115,7 @@
 	unsigned long flags;
 	int ret = -EIO;
 	int i;
+	int restarts = 0;
 
 	spin_lock_irqsave(&ec_lock, flags);
 
@@ -171,7 +172,9 @@
 			if (wait_on_obf(0x6c, 1)) {
 				printk(KERN_ERR "olpc-ec:  timeout waiting for"
 						" EC to provide data!\n");
-				goto restart;
+				if (restarts++ < 10)
+					goto restart;
+				goto err;
 			}
 			outbuf[i] = inb(0x68);
 			printk(KERN_DEBUG "olpc-ec:  received 0x%x\n",
--- linux-ec2-2.6.32.orig/arch/x86/kernel/traps.c
+++ linux-ec2-2.6.32/arch/x86/kernel/traps.c
@@ -115,6 +115,67 @@
 	if (!user_mode_vm(regs))
 		die(str, regs, err);
 }
+
+static inline int
+__compare_user_cs_desc(const struct desc_struct *desc1,
+	const struct desc_struct *desc2)
+{
+	return ((desc1->limit0 != desc2->limit0) ||
+		(desc1->limit != desc2->limit) ||
+		(desc1->base0 != desc2->base0) ||
+		(desc1->base1 != desc2->base1) ||
+		(desc1->base2 != desc2->base2));
+}
+
+/*
+ * lazy-check for CS validity on exec-shield binaries:
+ *
+ * the original non-exec stack patch was written by
+ * Solar Designer <solar at openwall.com>. Thanks!
+ */
+static int
+check_lazy_exec_limit(int cpu, struct pt_regs *regs, long error_code)
+{
+	struct desc_struct *desc1, *desc2;
+	struct vm_area_struct *vma;
+	unsigned long limit;
+
+	if (current->mm == NULL)
+		return 0;
+
+	limit = -1UL;
+	if (current->mm->context.exec_limit != -1UL) {
+		limit = PAGE_SIZE;
+		spin_lock(&current->mm->page_table_lock);
+		for (vma = current->mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+		vma = get_gate_vma(current);
+		if (vma && (vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+			limit = vma->vm_end;
+		spin_unlock(&current->mm->page_table_lock);
+		if (limit >= TASK_SIZE)
+			limit = -1UL;
+		current->mm->context.exec_limit = limit;
+	}
+	set_user_cs(&current->mm->context.user_cs, limit);
+
+	desc1 = &current->mm->context.user_cs;
+	desc2 = get_cpu_gdt_table(cpu) + GDT_ENTRY_DEFAULT_USER_CS;
+
+	if (__compare_user_cs_desc(desc1, desc2)) {
+		/*
+		 * The CS was not in sync - reload it and retry the
+		 * instruction. If the instruction still faults then
+		 * we won't hit this branch next time around.
+		 */
+		load_user_cs_desc(cpu, current->mm);
+
+		return 1;
+	}
+
+	return 0;
+}
 #endif
 
 static void __kprobes
@@ -273,6 +334,20 @@
 	if (!user_mode(regs))
 		goto gp_in_kernel;
 
+#ifdef CONFIG_X86_32
+{
+	int cpu;
+	int ok;
+
+	cpu = get_cpu();
+	ok = check_lazy_exec_limit(cpu, regs, error_code);
+	put_cpu();
+
+	if (ok)
+		return;
+}
+#endif
+
 	tsk->thread.error_code = error_code;
 	tsk->thread.trap_no = 13;
 
@@ -881,11 +956,29 @@
 }
 
 #ifdef CONFIG_X86_32
+/*
+ * The fixup code for errors in iret jumps to here (iret_exc). It loses
+ * the original trap number and erorr code. The bogus trap 32 and error
+ * code 0 are what the vanilla kernel delivers via:
+ * DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1)
+ *
+ * NOTE: Because of the final "1" in the macro we need to enable interrupts.
+ *
+ * In case of a general protection fault in the iret instruction, we
+ * need to check for a lazy CS update for exec-shield.
+ */
 dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
 {
 	siginfo_t info;
+	int ok;
+	int cpu;
 	local_irq_enable();
 
+	cpu = get_cpu();
+	ok = check_lazy_exec_limit(cpu, regs, error_code);
+	put_cpu();
+	if (ok) return;
+
 	info.si_signo = SIGILL;
 	info.si_errno = 0;
 	info.si_code = ILL_BADSTK;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pci-dma-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pci-dma-xen.c
@@ -0,0 +1,408 @@
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/dmar.h>
+#include <linux/bootmem.h>
+#include <linux/pci.h>
+#include <linux/kmemleak.h>
+
+#include <asm/proto.h>
+#include <asm/dma.h>
+#include <asm/iommu.h>
+#include <asm/gart.h>
+#include <asm/calgary.h>
+#include <asm/amd_iommu.h>
+
+static int forbid_dac __read_mostly;
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+static int iommu_sac_force __read_mostly;
+
+#ifdef CONFIG_IOMMU_DEBUG
+int panic_on_overflow __read_mostly = 1;
+int force_iommu __read_mostly = 1;
+#else
+int panic_on_overflow __read_mostly = 0;
+int force_iommu __read_mostly = 0;
+#endif
+
+int iommu_merge __read_mostly = 0;
+
+int no_iommu __read_mostly;
+/* Set this to 1 if there is a HW IOMMU in the system */
+int iommu_detected __read_mostly = 0;
+
+/*
+ * This variable becomes 1 if iommu=pt is passed on the kernel command line.
+ * If this variable is 1, IOMMU implementations do no DMA translation for
+ * devices and allow every device to access to whole physical memory. This is
+ * useful if a user want to use an IOMMU only for KVM device assignment to
+ * guests and not for driver dma translation.
+ */
+int iommu_pass_through __read_mostly;
+
+dma_addr_t bad_dma_address __read_mostly = 0;
+EXPORT_SYMBOL(bad_dma_address);
+
+/* Dummy device used for NULL arguments (normally ISA). Better would
+   be probably a smaller DMA mask, but this is bug-to-bug compatible
+   to older i386. */
+struct device x86_dma_fallback_dev = {
+	.init_name = "fallback device",
+	.coherent_dma_mask = DMA_BIT_MASK(32),
+	.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
+};
+EXPORT_SYMBOL(x86_dma_fallback_dev);
+
+/* Number of entries preallocated for DMA-API debugging */
+#define PREALLOC_DMA_DEBUG_ENTRIES       32768
+
+int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+static __initdata void *dma32_bootmem_ptr;
+static unsigned long dma32_bootmem_size __initdata = (128ULL<<20);
+
+static int __init parse_dma32_size_opt(char *p)
+{
+	if (!p)
+		return -EINVAL;
+	dma32_bootmem_size = memparse(p, &p);
+	return 0;
+}
+early_param("dma32_size", parse_dma32_size_opt);
+
+void __init dma32_reserve_bootmem(void)
+{
+	unsigned long size, align;
+	if (max_pfn <= MAX_DMA32_PFN)
+		return;
+
+	/*
+	 * check aperture_64.c allocate_aperture() for reason about
+	 * using 512M as goal
+	 */
+	align = 64ULL<<20;
+	size = roundup(dma32_bootmem_size, align);
+	dma32_bootmem_ptr = __alloc_bootmem_nopanic(size, align,
+				 512ULL<<20);
+	/*
+	 * Kmemleak should not scan this block as it may not be mapped via the
+	 * kernel direct mapping.
+	 */
+	kmemleak_ignore(dma32_bootmem_ptr);
+	if (dma32_bootmem_ptr)
+		dma32_bootmem_size = size;
+	else
+		dma32_bootmem_size = 0;
+}
+static void __init dma32_free_bootmem(void)
+{
+
+	if (max_pfn <= MAX_DMA32_PFN)
+		return;
+
+	if (!dma32_bootmem_ptr)
+		return;
+
+	free_bootmem(__pa(dma32_bootmem_ptr), dma32_bootmem_size);
+
+	dma32_bootmem_ptr = NULL;
+	dma32_bootmem_size = 0;
+}
+#endif
+
+static struct dma_map_ops swiotlb_dma_ops = {
+	.alloc_coherent = dma_generic_alloc_coherent,
+	.free_coherent = dma_generic_free_coherent,
+	.mapping_error = swiotlb_dma_mapping_error,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = swiotlb_sync_single_for_device,
+	.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+	.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.dma_supported = swiotlb_dma_supported
+};
+
+void __init pci_iommu_alloc(void)
+{
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+	/* free the range so iommu could get some range less than 4G */
+	dma32_free_bootmem();
+#endif
+
+	/*
+	 * The order of these functions is important for
+	 * fall-back/fail-over reasons
+	 */
+	gart_iommu_hole_init();
+
+	detect_calgary();
+
+	detect_intel_iommu();
+
+	amd_iommu_detect();
+
+	swiotlb_init();
+	if (swiotlb) {
+		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
+		dma_ops = &swiotlb_dma_ops;
+	}
+}
+
+void *dma_generic_alloc_coherent(struct device *dev, size_t size,
+				 dma_addr_t *dma_addr, gfp_t flag)
+{
+	unsigned long dma_mask;
+	struct page *page;
+#ifndef CONFIG_XEN
+	dma_addr_t addr;
+#else
+	void *memory;
+#endif
+	unsigned int order = get_order(size);
+
+	dma_mask = dma_alloc_coherent_mask(dev, flag);
+
+#ifndef CONFIG_XEN
+	flag |= __GFP_ZERO;
+again:
+#else
+	flag &= ~(__GFP_DMA | __GFP_DMA32);
+#endif
+	page = alloc_pages_node(dev_to_node(dev), flag, order);
+	if (!page)
+		return NULL;
+
+#ifndef CONFIG_XEN
+	addr = page_to_phys(page);
+	if (addr + size > dma_mask) {
+		__free_pages(page, order);
+
+		if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
+			flag = (flag & ~GFP_DMA32) | GFP_DMA;
+			goto again;
+		}
+
+		return NULL;
+	}
+
+	*dma_addr = addr;
+	return page_address(page);
+#else
+	memory = page_address(page);
+	if (xen_create_contiguous_region((unsigned long)memory, order,
+					 fls64(dma_mask))) {
+		__free_pages(page, order);
+		return NULL;
+	}
+
+	*dma_addr = virt_to_bus(memory);
+	return memset(memory, 0, size);
+#endif
+}
+
+#ifdef CONFIG_XEN
+void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
+			       dma_addr_t dma_addr)
+{
+	unsigned int order = get_order(size);
+	unsigned long va = (unsigned long)vaddr;
+
+	xen_destroy_contiguous_region(va, order);
+	free_pages(va, order);
+}
+#endif
+
+/*
+ * See <Documentation/x86_64/boot-options.txt> for the iommu kernel parameter
+ * documentation.
+ */
+static __init int iommu_setup(char *p)
+{
+	iommu_merge = 1;
+
+	if (!p)
+		return -EINVAL;
+
+	while (*p) {
+		if (!strncmp(p, "off", 3))
+			no_iommu = 1;
+		/* gart_parse_options has more force support */
+		if (!strncmp(p, "force", 5))
+			force_iommu = 1;
+		if (!strncmp(p, "noforce", 7)) {
+			iommu_merge = 0;
+			force_iommu = 0;
+		}
+
+		if (!strncmp(p, "biomerge", 8)) {
+			iommu_merge = 1;
+			force_iommu = 1;
+		}
+		if (!strncmp(p, "panic", 5))
+			panic_on_overflow = 1;
+		if (!strncmp(p, "nopanic", 7))
+			panic_on_overflow = 0;
+		if (!strncmp(p, "merge", 5)) {
+			iommu_merge = 1;
+			force_iommu = 1;
+		}
+		if (!strncmp(p, "nomerge", 7))
+			iommu_merge = 0;
+		if (!strncmp(p, "forcesac", 8))
+			iommu_sac_force = 1;
+		if (!strncmp(p, "allowdac", 8))
+			forbid_dac = 0;
+		if (!strncmp(p, "nodac", 5))
+			forbid_dac = -1;
+		if (!strncmp(p, "usedac", 6)) {
+			forbid_dac = -1;
+			return 1;
+		}
+#ifdef CONFIG_SWIOTLB
+		if (!strncmp(p, "soft", 4))
+			swiotlb = 1;
+#endif
+		if (!strncmp(p, "pt", 2))
+			iommu_pass_through = 1;
+
+		gart_parse_options(p);
+
+#ifdef CONFIG_CALGARY_IOMMU
+		if (!strncmp(p, "calgary", 7))
+			use_calgary = 1;
+#endif /* CONFIG_CALGARY_IOMMU */
+
+		p += strcspn(p, ",");
+		if (*p == ',')
+			++p;
+	}
+	return 0;
+}
+early_param("iommu", iommu_setup);
+
+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)
+{
+	unsigned long pfn = p >> PAGE_SHIFT;
+	unsigned int offset = p & ~PAGE_MASK;
+
+	return ((offset + size > PAGE_SIZE) &&
+		!check_pages_physically_contiguous(pfn, offset, size));
+}
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+#ifdef CONFIG_PCI
+	if (mask > 0xffffffff && forbid_dac > 0) {
+		dev_info(dev, "PCI: Disallowing DAC for device\n");
+		return 0;
+	}
+#endif
+
+	if (ops->dma_supported)
+		return ops->dma_supported(dev, mask);
+
+	/* Copied from i386. Doesn't make much sense, because it will
+	   only work for pci_alloc_coherent.
+	   The caller just has to use GFP_DMA in this case. */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	/* Tell the device to use SAC when IOMMU force is on.  This
+	   allows the driver to use cheaper accesses in some cases.
+
+	   Problem with this is that if we overflow the IOMMU area and
+	   return DAC as fallback address the device may not handle it
+	   correctly.
+
+	   As a special case some controllers have a 39bit address
+	   mode that is as efficient as 32bit (aic79xx). Don't force
+	   SAC for these.  Assume all masks <= 40 bits are of this
+	   type. Normally this doesn't make any difference, but gives
+	   more gentle handling of IOMMU overflow. */
+	if (iommu_sac_force && (mask >= DMA_BIT_MASK(40))) {
+		dev_info(dev, "Force SAC with mask %Lx\n", mask);
+		return 0;
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(dma_supported);
+
+static int __init pci_iommu_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+#ifdef CONFIG_PCI
+	dma_debug_add_bus(&pci_bus_type);
+#endif
+
+	calgary_iommu_init();
+
+	intel_iommu_init();
+
+	amd_iommu_init();
+
+	gart_iommu_init();
+
+	no_iommu_init();
+	return 0;
+}
+
+void pci_iommu_shutdown(void)
+{
+	gart_iommu_shutdown();
+
+	amd_iommu_shutdown();
+}
+/* Must execute after PCI subsystem */
+rootfs_initcall(pci_iommu_init);
+
+#ifdef CONFIG_PCI
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+		dev_info(&dev->dev, "disabling DAC on VIA PCI bridge\n");
+		forbid_dac = 1;
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/probe_roms_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/probe_roms_32.c
@@ -131,7 +131,7 @@
 	upper = system_rom_resource.start;
 
 	/* check for extension rom (ignore length byte!) */
-	rom = isa_bus_to_virt(extension_rom_resource.start);
+	rom = isa_bus_to_virt((unsigned long)extension_rom_resource.start);
 	if (romsignature(rom)) {
 		length = extension_rom_resource.end - extension_rom_resource.start + 1;
 		if (romchecksum(rom, length)) {
--- linux-ec2-2.6.32.orig/arch/x86/kernel/ptrace.c
+++ linux-ec2-2.6.32/arch/x86/kernel/ptrace.c
@@ -408,14 +408,14 @@
 {
 	if (kbuf) {
 		unsigned long *k = kbuf;
-		while (count > 0) {
+		while (count >= sizeof(*k)) {
 			*k++ = getreg(target, pos);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		unsigned long __user *u = ubuf;
-		while (count > 0) {
+		while (count >= sizeof(*u)) {
 			if (__put_user(getreg(target, pos), u++))
 				return -EFAULT;
 			count -= sizeof(*u);
@@ -434,14 +434,14 @@
 	int ret = 0;
 	if (kbuf) {
 		const unsigned long *k = kbuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*k) && !ret) {
 			ret = putreg(target, pos, *k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		const unsigned long  __user *u = ubuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*u) && !ret) {
 			unsigned long word;
 			ret = __get_user(word, u++);
 			if (ret)
@@ -1219,14 +1219,14 @@
 {
 	if (kbuf) {
 		compat_ulong_t *k = kbuf;
-		while (count > 0) {
+		while (count >= sizeof(*k)) {
 			getreg32(target, pos, k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		compat_ulong_t __user *u = ubuf;
-		while (count > 0) {
+		while (count >= sizeof(*u)) {
 			compat_ulong_t word;
 			getreg32(target, pos, &word);
 			if (__put_user(word, u++))
@@ -1247,14 +1247,14 @@
 	int ret = 0;
 	if (kbuf) {
 		const compat_ulong_t *k = kbuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*k) && !ret) {
 			ret = putreg32(target, pos, *k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		const compat_ulong_t __user *u = ubuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*u) && !ret) {
 			compat_ulong_t word;
 			ret = __get_user(word, u++);
 			if (ret)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process_64-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process_64-xen.c
@@ -0,0 +1,754 @@
+/*
+ *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  Pentium III FXSR, SSE support
+ *	Gareth Hughes <gareth@valinux.com>, May 2000
+ *
+ *  X86-64 port
+ *	Andi Kleen.
+ *
+ *	CPU hotplug support - ashok.raj@intel.com
+ * 
+ *  Jun Nakajima <jun.nakajima@intel.com> 
+ *     Modified for Xen
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/stackprotector.h>
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/elfcore.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/interrupt.h>
+#include <linux/utsname.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/tick.h>
+#include <linux/prctl.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/ftrace.h>
+#include <linux/dmi.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/i387.h>
+#include <asm/mmu_context.h>
+#include <asm/prctl.h>
+#include <xen/interface/platform.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/vcpu.h>
+#include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/hardirq.h>
+#include <asm/ia32.h>
+#include <asm/idle.h>
+#include <asm/syscalls.h>
+#include <asm/ds.h>
+
+#include <xen/cpu_hotplug.h>
+
+asmlinkage extern void ret_from_fork(void);
+
+DEFINE_PER_CPU(unsigned long, old_rsp);
+static DEFINE_PER_CPU(unsigned char, is_idle);
+
+unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
+
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+	atomic_notifier_chain_register(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+	atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+
+void enter_idle(void)
+{
+	percpu_write(is_idle, 1);
+	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+}
+
+static void __exit_idle(void)
+{
+	if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
+		return;
+	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+}
+
+/* Called from interrupts to signify idle end */
+void exit_idle(void)
+{
+	/* idle loop has pid 0 */
+	if (current->pid)
+		return;
+	__exit_idle();
+}
+
+#ifndef CONFIG_SMP
+static inline void play_dead(void)
+{
+	BUG();
+}
+#endif
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+	current_thread_info()->status |= TS_POLLING;
+
+	/*
+	 * If we're the non-boot CPU, nothing set the stack canary up
+	 * for us.  CPU0 already has it initialized but no harm in
+	 * doing it again.  This is a good place for updating it, as
+	 * we wont ever return from this function (so the invalid
+	 * canaries already on the stack wont ever trigger).
+	 */
+	boot_init_stack_canary();
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		while (!need_resched()) {
+
+			rmb();
+
+			if (cpu_is_offline(smp_processor_id()))
+				play_dead();
+			/*
+			 * Idle routines should keep interrupts disabled
+			 * from here on, until they go to idle.
+			 * Otherwise, idle callbacks can misfire.
+			 */
+			local_irq_disable();
+			enter_idle();
+			/* Don't trace irqs off for idle */
+			stop_critical_timings();
+			xen_idle();
+			start_critical_timings();
+			/* In many cases the interrupt that ended idle
+			   has already called exit_idle. But some idle
+			   loops can be woken up without interrupt. */
+			__exit_idle();
+		}
+
+		tick_nohz_restart_sched_tick();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+/* Prints also some state that isn't saved in the pt_regs */
+void __show_regs(struct pt_regs *regs, int all)
+{
+	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs;
+	unsigned long d0, d1, d2, d3, d6, d7;
+	unsigned int fsindex, gsindex;
+	unsigned int ds, cs, es;
+	const char *board;
+
+	printk("\n");
+	print_modules();
+	board = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!board)
+		board = "";
+	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n",
+		current->pid, current->comm, print_tainted(),
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version, board);
+	printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
+	printk_address(regs->ip, 1);
+	printk(KERN_INFO "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
+			regs->sp, regs->flags);
+	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+	       regs->ax, regs->bx, regs->cx);
+	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+	       regs->dx, regs->si, regs->di);
+	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+	       regs->bp, regs->r8, regs->r9);
+	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+	       regs->r10, regs->r11, regs->r12);
+	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+	       regs->r13, regs->r14, regs->r15);
+
+	asm("movl %%ds,%0" : "=r" (ds));
+	asm("movl %%cs,%0" : "=r" (cs));
+	asm("movl %%es,%0" : "=r" (es));
+	asm("mov %%fs,%0" : "=r" (fsindex));
+	asm("mov %%gs,%0" : "=r" (gsindex));
+
+	rdmsrl(MSR_FS_BASE, fs);
+	rdmsrl(MSR_GS_BASE, gs);
+	rdmsrl(MSR_KERNEL_GS_BASE, shadowgs);
+
+	if (!all)
+		return;
+
+	cr0 = read_cr0();
+	cr2 = read_cr2();
+	cr3 = read_cr3();
+	cr4 = read_cr4();
+
+	printk(KERN_INFO "FS:  %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
+	       fs, fsindex, gs, gsindex, shadowgs);
+	printk(KERN_INFO "CS:  %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds,
+			es, cr0);
+	printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3,
+			cr4);
+
+	get_debugreg(d0, 0);
+	get_debugreg(d1, 1);
+	get_debugreg(d2, 2);
+	printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2);
+	get_debugreg(d3, 3);
+	get_debugreg(d6, 6);
+	get_debugreg(d7, 7);
+	printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_INFO "CPU %d:", smp_processor_id());
+	__show_regs(regs, 1);
+	show_trace(NULL, regs, (void *)(regs + 1), regs->bp);
+}
+
+void xen_load_gs_index(unsigned gs)
+{
+	WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, gs));
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+	if (dead_task->mm) {
+		if (dead_task->mm->context.size) {
+			printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
+					dead_task->comm,
+					dead_task->mm->context.ldt,
+					dead_task->mm->context.size);
+			BUG();
+		}
+	}
+}
+
+static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
+{
+	struct user_desc ud = {
+		.base_addr = addr,
+		.limit = 0xfffff,
+		.seg_32bit = 1,
+		.limit_in_pages = 1,
+		.useable = 1,
+	};
+	struct desc_struct *desc = t->thread.tls_array;
+	desc += tls;
+	fill_ldt(desc, &ud);
+}
+
+static inline u32 read_32bit_tls(struct task_struct *t, int tls)
+{
+	return get_desc_base(&t->thread.tls_array[tls]);
+}
+
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+	unlazy_fpu(tsk);
+}
+
+int copy_thread(unsigned long clone_flags, unsigned long sp,
+		unsigned long unused,
+	struct task_struct *p, struct pt_regs *regs)
+{
+	int err;
+	struct pt_regs *childregs;
+	struct task_struct *me = current;
+
+	childregs = ((struct pt_regs *)
+			(THREAD_SIZE + task_stack_page(p))) - 1;
+	*childregs = *regs;
+
+	childregs->ax = 0;
+	childregs->sp = sp;
+	if (sp == ~0UL)
+		childregs->sp = (unsigned long)childregs;
+
+	p->thread.sp = (unsigned long) childregs;
+	p->thread.sp0 = (unsigned long) (childregs+1);
+	p->thread.usersp = me->thread.usersp;
+
+	set_tsk_thread_flag(p, TIF_FORK);
+
+	savesegment(gs, p->thread.gsindex);
+	p->thread.gs = p->thread.gsindex ? 0 : me->thread.gs;
+	savesegment(fs, p->thread.fsindex);
+	p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
+	savesegment(es, p->thread.es);
+	savesegment(ds, p->thread.ds);
+
+	if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
+		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
+			return -ENOMEM;
+		}
+		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
+				IO_BITMAP_BYTES);
+		set_tsk_thread_flag(p, TIF_IO_BITMAP);
+	}
+
+	/*
+	 * Set a new TLS for the child thread?
+	 */
+	if (clone_flags & CLONE_SETTLS) {
+#ifdef CONFIG_IA32_EMULATION
+		if (test_thread_flag(TIF_IA32))
+			err = do_set_thread_area(p, -1,
+				(struct user_desc __user *)childregs->si, 0);
+		else
+#endif
+			err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8);
+		if (err)
+			goto out;
+	}
+        p->thread.iopl = current->thread.iopl;
+
+	clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
+	p->thread.ds_ctx = NULL;
+
+	clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
+	p->thread.debugctlmsr = 0;
+
+	err = 0;
+out:
+	if (err && p->thread.io_bitmap_ptr) {
+		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
+	return err;
+}
+
+void
+start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+{
+	loadsegment(fs, 0);
+	loadsegment(es, 0);
+	loadsegment(ds, 0);
+	load_gs_index(0);
+	regs->ip		= new_ip;
+	regs->sp		= new_sp;
+	percpu_write(old_rsp, new_sp);
+	regs->cs		= __USER_CS;
+	regs->ss		= __USER_DS;
+	regs->flags		= 0x200;
+	set_fs(USER_DS);
+	/*
+	 * Free the old FP and other extended state
+	 */
+	free_thread_xstate(current);
+}
+EXPORT_SYMBOL_GPL(start_thread);
+
+/*
+ *	switch_to(x,y) should switch tasks from x to y.
+ *
+ * This could still be optimized:
+ * - fold all the options into a flag word and test it with a single test.
+ * - could test fs/gs bitsliced
+ *
+ * Kprobes not supported here. Set the probe on schedule instead.
+ * Function graph tracer not supported too.
+ */
+__notrace_funcgraph struct task_struct *
+__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+{
+	struct thread_struct *prev = &prev_p->thread;
+	struct thread_struct *next = &next_p->thread;
+	int cpu = smp_processor_id();
+#ifndef CONFIG_X86_NO_TSS
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+#endif
+	bool preload_fpu;
+#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;
+
+	/*
+	 * If the task has used fpu the last 5 timeslices, just do a full
+	 * restore of the math state immediately to avoid the trap; the
+	 * chances of needing FPU soon are obviously high now
+	 */
+	preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
+
+	/* we're going to use this soon, after a few expensive things */
+	if (preload_fpu)
+		prefetch(next->xstate);
+
+	/*
+	 * This is basically '__unlazy_fpu', except that we queue a
+	 * multicall to indicate FPU task switch, rather than
+	 * synchronously trapping to Xen.
+	 * The AMD workaround requires it to be after DS reload, or
+	 * after DS has been cleared, which we do in __prepare_arch_switch.
+	 */
+	if (task_thread_info(prev_p)->status & TS_USEDFPU) {
+		__save_init_fpu(prev_p); /* _not_ save_init_fpu() */
+		if (!preload_fpu) {
+			mcl->op      = __HYPERVISOR_fpu_taskswitch;
+			mcl->args[0] = 1;
+			mcl++;
+		}
+	} else
+		prev_p->fpu_counter = 0;
+
+	/* Make sure cpu is ready for new context */
+	if (preload_fpu) {
+		mcl->op      = __HYPERVISOR_fpu_taskswitch;
+		mcl->args[0] = 0;
+		mcl++;
+	}
+
+	/*
+	 * Reload sp0.
+	 * This is load_sp0(tss, next) with a multicall.
+	 */
+	mcl->op      = __HYPERVISOR_stack_switch;
+	mcl->args[0] = __KERNEL_DS;
+	mcl->args[1] = next->sp0;
+	mcl++;
+
+	/*
+	 * Load the per-thread Thread-Local Storage descriptor.
+	 * This is load_TLS(next, cpu) with multicalls.
+	 */
+#define C(i) do {							\
+	if (unlikely(next->tls_array[i].a != prev->tls_array[i].a ||	\
+		     next->tls_array[i].b != prev->tls_array[i].b)) {	\
+		mcl->op      = __HYPERVISOR_update_descriptor;		\
+		mcl->args[0] = arbitrary_virt_to_machine(		\
+			&get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\
+		mcl->args[1] = *(u64 *)&next->tls_array[i];		\
+		mcl++;							\
+	}								\
+} while (0)
+	C(0); C(1); C(2);
+#undef C
+
+	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++;
+	}
+
+	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
+		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();
+
+	/*
+	 * Switch DS and ES.
+	 * This won't pick up thread selector changes, but I guess that is ok.
+	 */
+	if (unlikely(next->es))
+		loadsegment(es, next->es);
+
+	if (unlikely(next->ds))
+		loadsegment(ds, next->ds);
+
+	/*
+	 * Leave lazy mode, flushing any hypercalls made here.
+	 * This must be done before restoring TLS segments so
+	 * the GDT and LDT are properly updated, and must be
+	 * done before math_state_restore, so the TS bit is up
+	 * to date.
+	 */
+	arch_end_context_switch(next_p);
+
+	/*
+	 * Switch FS and GS.
+	 *
+	 * Segment register != 0 always requires a reload.  Also
+	 * reload when it has changed.  When prev process used 64bit
+	 * base always reload to avoid an information leak.
+	 */
+	if (unlikely(next->fsindex))
+		loadsegment(fs, next->fsindex);
+
+	if (next->fs)
+		WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_FS, next->fs));
+	
+	if (unlikely(next->gsindex))
+		load_gs_index(next->gsindex);
+
+	if (next->gs)
+		WARN_ON(HYPERVISOR_set_segment_base(SEGBASE_GS_USER, next->gs));
+
+	/*
+	 * Switch the PDA context.
+	 */
+	prev->usersp = percpu_read(old_rsp);
+	percpu_write(old_rsp, next->usersp);
+	percpu_write(current_task, next_p);
+
+	percpu_write(kernel_stack,
+		  (unsigned long)task_stack_page(next_p) +
+		  THREAD_SIZE - KERNEL_STACK_OFFSET);
+
+	/*
+	 * Now maybe reload the debug registers
+	 */
+	if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
+		     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
+		__switch_to_xtra(prev_p, next_p);
+
+	/*
+	 * Preload the FPU context, now that we've determined that the
+	 * task is likely to be using it.
+	 */
+	if (preload_fpu)
+		__math_state_restore();
+	return prev_p;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage
+long sys_execve(char __user *name, char __user * __user *argv,
+		char __user * __user *envp, struct pt_regs *regs)
+{
+	long error;
+	char *filename;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return error;
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+	return error;
+}
+
+void set_personality_64bit(void)
+{
+	/* inherit personality from parent */
+
+	/* Make sure to be in 64bit mode */
+	clear_thread_flag(TIF_IA32);
+
+	/* TBD: overwrites user setup. Should have two bits.
+	   But 64bit processes have always behaved this way,
+	   so it's not too bad. The main problem is just that
+	   32bit childs are affected again. */
+	current->personality &= ~READ_IMPLIES_EXEC;
+}
+
+asmlinkage long
+sys_clone(unsigned long clone_flags, unsigned long newsp,
+	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->sp;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+}
+
+void set_personality_ia32(void)
+{
+	/* inherit personality from parent */
+
+	/* Make sure to be in 32bit mode */
+	set_thread_flag(TIF_IA32);
+	current->personality |= force_personality32;
+
+	/* Prepare the first "return" to user space */
+	current_thread_info()->status |= TS_COMPAT;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long stack;
+	u64 fp, ip;
+	int count = 0;
+
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	stack = (unsigned long)task_stack_page(p);
+	if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
+		return 0;
+	fp = *(u64 *)(p->thread.sp);
+	do {
+		if (fp < (unsigned long)stack ||
+		    fp >= (unsigned long)stack+THREAD_SIZE)
+			return 0;
+		ip = *(u64 *)(fp+8);
+		if (!in_sched_functions(ip))
+			return ip;
+		fp = *(u64 *)fp;
+	} while (count++ < 16);
+	return 0;
+}
+
+long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
+{
+	int ret = 0;
+	int doit = task == current;
+	int cpu;
+
+	switch (code) {
+	case ARCH_SET_GS:
+		if (addr >= TASK_SIZE_OF(task))
+			return -EPERM;
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to
+		   switch. */
+		if (addr <= 0xffffffff) {
+			set_32bit_tls(task, GS_TLS, addr);
+			if (doit) {
+				load_TLS(&task->thread, cpu);
+				load_gs_index(GS_TLS_SEL);
+			}
+			task->thread.gsindex = GS_TLS_SEL;
+			task->thread.gs = 0;
+		} else {
+			task->thread.gsindex = 0;
+			task->thread.gs = addr;
+			if (doit) {
+				load_gs_index(0);
+				ret = HYPERVISOR_set_segment_base(
+					SEGBASE_GS_USER, addr);
+			}
+		}
+		put_cpu();
+		break;
+	case ARCH_SET_FS:
+		/* Not strictly needed for fs, but do it for symmetry
+		   with gs */
+		if (addr >= TASK_SIZE_OF(task))
+			return -EPERM;
+		cpu = get_cpu();
+		/* handle small bases via the GDT because that's faster to
+		   switch. */
+		if (addr <= 0xffffffff) {
+			set_32bit_tls(task, FS_TLS, addr);
+			if (doit) {
+				load_TLS(&task->thread, cpu);
+				loadsegment(fs, FS_TLS_SEL);
+			}
+			task->thread.fsindex = FS_TLS_SEL;
+			task->thread.fs = 0;
+		} else {
+			task->thread.fsindex = 0;
+			task->thread.fs = addr;
+			if (doit) {
+				/* set the selector to 0 to not confuse
+				   __switch_to */
+				loadsegment(fs, 0);
+                                ret = HYPERVISOR_set_segment_base(SEGBASE_FS,
+								  addr);
+			}
+		}
+		put_cpu();
+		break;
+	case ARCH_GET_FS: {
+		unsigned long base;
+		if (task->thread.fsindex == FS_TLS_SEL)
+			base = read_32bit_tls(task, FS_TLS);
+		else if (doit)
+			rdmsrl(MSR_FS_BASE, base);
+		else
+			base = task->thread.fs;
+		ret = put_user(base, (unsigned long __user *)addr);
+		break;
+	}
+	case ARCH_GET_GS: {
+		unsigned long base;
+		unsigned gsindex;
+		if (task->thread.gsindex == GS_TLS_SEL)
+			base = read_32bit_tls(task, GS_TLS);
+		else if (doit) {
+			savesegment(gs, gsindex);
+			if (gsindex)
+				rdmsrl(MSR_KERNEL_GS_BASE, base);
+			else
+				base = task->thread.gs;
+		} else
+			base = task->thread.gs;
+		ret = put_user(base, (unsigned long __user *)addr);
+		break;
+	}
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+long sys_arch_prctl(int code, unsigned long addr)
+{
+	return do_arch_prctl(current, code, addr);
+}
+
--- linux-ec2-2.6.32.orig/arch/x86/kernel/smp-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/smp-xen.c
@@ -0,0 +1,207 @@
+/*
+ *	Intel SMP support routines.
+ *
+ *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+ *	(c) 1998-99, 2000, 2009 Ingo Molnar <mingo@redhat.com>
+ *      (c) 2002,2003 Andi Kleen, SuSE Labs.
+ *
+ *	i386 and x86_64 integration by Glauber Costa <gcosta@redhat.com>
+ *
+ *	This code is released under the GNU General Public License version 2 or
+ *	later.
+ */
+
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/cache.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+
+#include <asm/mtrr.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/proto.h>
+#include <asm/ipi.h>
+#include <xen/evtchn.h>
+/*
+ *	Some notes on x86 processor bugs affecting SMP operation:
+ *
+ *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
+ *	The Linux implications for SMP are handled as follows:
+ *
+ *	Pentium III / [Xeon]
+ *		None of the E1AP-E3AP errata are visible to the user.
+ *
+ *	E1AP.	see PII A1AP
+ *	E2AP.	see PII A2AP
+ *	E3AP.	see PII A3AP
+ *
+ *	Pentium II / [Xeon]
+ *		None of the A1AP-A3AP errata are visible to the user.
+ *
+ *	A1AP.	see PPro 1AP
+ *	A2AP.	see PPro 2AP
+ *	A3AP.	see PPro 7AP
+ *
+ *	Pentium Pro
+ *		None of 1AP-9AP errata are visible to the normal user,
+ *	except occasional delivery of 'spurious interrupt' as trap #15.
+ *	This is very rare and a non-problem.
+ *
+ *	1AP.	Linux maps APIC as non-cacheable
+ *	2AP.	worked around in hardware
+ *	3AP.	fixed in C0 and above steppings microcode update.
+ *		Linux does not use excessive STARTUP_IPIs.
+ *	4AP.	worked around in hardware
+ *	5AP.	symmetric IO mode (normal Linux operation) not affected.
+ *		'noapic' mode has vector 0xf filled out properly.
+ *	6AP.	'noapic' mode might be affected - fixed in later steppings
+ *	7AP.	We do not assume writes to the LVT deassering IRQs
+ *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
+ *	9AP.	We do not use mixed mode
+ *
+ *	Pentium
+ *		There is a marginal case where REP MOVS on 100MHz SMP
+ *	machines with B stepping processors can fail. XXX should provide
+ *	an L1cache=Writethrough or L1cache=off option.
+ *
+ *		B stepping CPUs may hang. There are hardware work arounds
+ *	for this. We warn about it in case your board doesn't have the work
+ *	arounds. Basically that's so I can tell anyone with a B stepping
+ *	CPU and SMP problems "tough".
+ *
+ *	Specific items [From Pentium Processor Specification Update]
+ *
+ *	1AP.	Linux doesn't use remote read
+ *	2AP.	Linux doesn't trust APIC errors
+ *	3AP.	We work around this
+ *	4AP.	Linux never generated 3 interrupts of the same priority
+ *		to cause a lost local interrupt.
+ *	5AP.	Remote read is never used
+ *	6AP.	not affected - worked around in hardware
+ *	7AP.	not affected - worked around in hardware
+ *	8AP.	worked around in hardware - we get explicit CS errors if not
+ *	9AP.	only 'noapic' mode affected. Might generate spurious
+ *		interrupts, we log only the first one and count the
+ *		rest silently.
+ *	10AP.	not affected - worked around in hardware
+ *	11AP.	Linux reads the APIC between writes to avoid this, as per
+ *		the documentation. Make sure you preserve this as it affects
+ *		the C stepping chips too.
+ *	12AP.	not affected - worked around in hardware
+ *	13AP.	not affected - worked around in hardware
+ *	14AP.	we always deassert INIT during bootup
+ *	15AP.	not affected - worked around in hardware
+ *	16AP.	not affected - worked around in hardware
+ *	17AP.	not affected - worked around in hardware
+ *	18AP.	not affected - worked around in hardware
+ *	19AP.	not affected - worked around in BIOS
+ *
+ *	If this sounds worrying believe me these bugs are either ___RARE___,
+ *	or are signal timing bugs worked around in hardware and there's
+ *	about nothing of note with C stepping upwards.
+ */
+
+/*
+ * this function sends a 'reschedule' IPI to another CPU.
+ * it goes straight through and wastes no time serializing
+ * anything. Worst case is that we lose a reschedule ...
+ */
+void xen_smp_send_reschedule(int cpu)
+{
+	if (unlikely(cpu_is_offline(cpu))) {
+		WARN_ON(1);
+		return;
+	}
+	xen_send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
+}
+
+void xen_send_call_func_single_ipi(int cpu)
+{
+	xen_send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_VECTOR);
+}
+
+void xen_send_call_func_ipi(const struct cpumask *mask)
+{
+	xen_send_IPI_mask_allbutself(mask, CALL_FUNCTION_VECTOR);
+}
+
+/*
+ * this function calls the 'stop' function on all other CPUs in the system.
+ */
+
+irqreturn_t smp_reboot_interrupt(int irq, void *dev_id)
+{
+	irq_enter();
+	stop_this_cpu(NULL);
+	irq_exit();
+
+	return IRQ_HANDLED;
+}
+
+void xen_stop_other_cpus(int wait)
+{
+	unsigned long flags;
+	unsigned long timeout;
+
+	/*
+	 * Use an own vector here because smp_call_function
+	 * does lots of things not suitable in a panic situation.
+	 * On most systems we could also use an NMI here,
+	 * but there are a few systems around where NMI
+	 * is problematic so stay with an non NMI for now
+	 * (this implies we cannot stop CPUs spinning with irq off
+	 * currently)
+	 */
+	if (num_online_cpus() > 1) {
+		xen_send_IPI_allbutself(REBOOT_VECTOR);
+
+		/*
+		 * Don't wait longer than a second if the caller
+		 * didn't ask us to wait.
+		 */
+		timeout = USEC_PER_SEC;
+		while (num_online_cpus() > 1 && (wait || timeout--))
+			udelay(1);
+	}
+
+	local_irq_save(flags);
+	disable_all_local_evtchn();
+	local_irq_restore(flags);
+}
+
+/*
+ * Reschedule call back. Nothing to do,
+ * all the work is done automatically when
+ * we return from the interrupt.
+ */
+irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
+{
+	inc_irq_stat(irq_resched_count);
+	return IRQ_HANDLED;
+}
+
+irqreturn_t smp_call_function_interrupt(int irq, void *dev_id)
+{
+	irq_enter();
+	generic_smp_call_function_interrupt();
+	inc_irq_stat(irq_call_count);
+	irq_exit();
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t smp_call_function_single_interrupt(int irq, void *dev_id)
+{
+	irq_enter();
+	generic_smp_call_function_single_interrupt();
+	inc_irq_stat(irq_call_count);
+	irq_exit();
+
+	return IRQ_HANDLED;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/amd_iommu.c
+++ linux-ec2-2.6.32/arch/x86/kernel/amd_iommu.c
@@ -540,11 +540,11 @@
 static void flush_devices_by_domain(struct protection_domain *domain)
 {
 	struct amd_iommu *iommu;
-	int i;
+	unsigned long i;
 
 	for (i = 0; i <= amd_iommu_last_bdf; ++i) {
 		if ((domain == NULL && amd_iommu_pd_table[i] == NULL) ||
-		    (amd_iommu_pd_table[i] != domain))
+		    (domain != NULL && amd_iommu_pd_table[i] != domain))
 			continue;
 
 		iommu = amd_iommu_rlookup_table[i];
@@ -1230,9 +1230,10 @@
 
 	/*
 	 * If we run in passthrough mode the device must be assigned to the
-	 * passthrough domain if it is detached from any other domain
+	 * passthrough domain if it is detached from any other domain.
+	 * Make sure we can deassign from the pt_domain itself.
 	 */
-	if (iommu_pass_through) {
+	if (iommu_pass_through && domain != pt_domain) {
 		struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
 		__attach_device(iommu, pt_domain, devid);
 	}
@@ -1687,6 +1688,7 @@
 			   size_t size,
 			   int dir)
 {
+	dma_addr_t flush_addr;
 	dma_addr_t i, start;
 	unsigned int pages;
 
@@ -1694,6 +1696,7 @@
 	    (dma_addr + size > dma_dom->aperture_size))
 		return;
 
+	flush_addr = dma_addr;
 	pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
 	dma_addr &= PAGE_MASK;
 	start = dma_addr;
@@ -1708,7 +1711,7 @@
 	dma_ops_free_addresses(dma_dom, dma_addr, pages);
 
 	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
-		iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size);
+		iommu_flush_pages(iommu, dma_dom->domain.id, flush_addr, size);
 		dma_dom->need_flush = false;
 	}
 }
@@ -2047,10 +2050,10 @@
 	struct pci_dev *dev = NULL;
 	struct dma_ops_domain *dma_dom;
 	struct amd_iommu *iommu;
-	u16 devid;
+	u16 devid, __devid;
 
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		devid = calc_devid(dev->bus->number, dev->devfn);
+		__devid = devid = calc_devid(dev->bus->number, dev->devfn);
 		if (devid > amd_iommu_last_bdf)
 			continue;
 		devid = amd_iommu_alias_table[devid];
@@ -2065,6 +2068,10 @@
 		init_unity_mappings_for_device(dma_dom, devid);
 		dma_dom->target_dev = devid;
 
+		attach_device(iommu, &dma_dom->domain, devid);
+		if (__devid != devid)
+			attach_device(iommu, &dma_dom->domain, __devid);
+
 		list_add_tail(&dma_dom->list, &iommu_pd_list);
 	}
 }
@@ -2079,6 +2086,11 @@
 	.dma_supported = amd_iommu_dma_supported,
 };
 
+void __init amd_iommu_init_api(void)
+{
+	register_iommu(&amd_iommu_ops);
+}
+
 /*
  * The function which clues the AMD IOMMU driver into dma_ops.
  */
@@ -2120,8 +2132,6 @@
 	/* Make the driver finally visible to the drivers */
 	dma_ops = &amd_iommu_dma_ops;
 
-	register_iommu(&amd_iommu_ops);
-
 	bus_register_notifier(&pci_bus_type, &device_nb);
 
 	amd_iommu_stats_init();
@@ -2231,9 +2241,7 @@
 
 	free_pagetable(domain);
 
-	domain_id_free(domain->id);
-
-	kfree(domain);
+	protection_domain_free(domain);
 
 	dom->priv = NULL;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/sys_i386_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/sys_i386_32.c
@@ -24,31 +24,6 @@
 
 #include <asm/syscalls.h>
 
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-			  unsigned long prot, unsigned long flags,
-			  unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file *file = NULL;
-	struct mm_struct *mm = current->mm;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls. Linux/i386 didn't use to be able to handle more than
@@ -77,7 +52,7 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	err = sys_mmap2(a.addr, a.len, a.prot, a.flags,
+	err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags,
 			a.fd, a.offset >> PAGE_SHIFT);
 out:
 	return err;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process-xen.c
@@ -0,0 +1,576 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/prctl.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/clockchips.h>
+#include <linux/random.h>
+#include <trace/events/power.h>
+#include <asm/system.h>
+#include <asm/apic.h>
+#include <asm/syscalls.h>
+#include <asm/idle.h>
+#include <asm/uaccess.h>
+#include <asm/i387.h>
+#include <asm/ds.h>
+#include <xen/evtchn.h>
+
+unsigned long idle_halt;
+EXPORT_SYMBOL(idle_halt);
+unsigned long idle_nomwait;
+EXPORT_SYMBOL(idle_nomwait);
+
+struct kmem_cache *task_xstate_cachep;
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+	*dst = *src;
+	if (src->thread.xstate) {
+		dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+						      GFP_KERNEL);
+		if (!dst->thread.xstate)
+			return -ENOMEM;
+		WARN_ON((unsigned long)dst->thread.xstate & 15);
+		memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
+	}
+	return 0;
+}
+
+void free_thread_xstate(struct task_struct *tsk)
+{
+	if (tsk->thread.xstate) {
+		kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
+		tsk->thread.xstate = NULL;
+	}
+
+	WARN(tsk->thread.ds_ctx, "leaking DS context\n");
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+	free_thread_xstate(ti->task);
+	free_pages((unsigned long)ti, get_order(THREAD_SIZE));
+}
+
+void arch_task_cache_init(void)
+{
+        task_xstate_cachep =
+        	kmem_cache_create("task_xstate", xstate_size,
+				  __alignof__(union thread_xstate),
+				  SLAB_PANIC | SLAB_NOTRACK, NULL);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+	struct task_struct *me = current;
+	struct thread_struct *t = &me->thread;
+	unsigned long *bp = t->io_bitmap_ptr;
+
+	if (bp) {
+		struct physdev_set_iobitmap set_iobitmap;
+
+		t->io_bitmap_ptr = NULL;
+		clear_thread_flag(TIF_IO_BITMAP);
+		/*
+		 * Careful, clear this in the TSS too:
+		 */
+		memset(&set_iobitmap, 0, sizeof(set_iobitmap));
+		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+					      &set_iobitmap));
+		t->io_bitmap_max = 0;
+		kfree(bp);
+	}
+}
+
+void flush_thread(void)
+{
+	struct task_struct *tsk = current;
+
+	clear_tsk_thread_flag(tsk, TIF_DEBUG);
+
+	tsk->thread.debugreg0 = 0;
+	tsk->thread.debugreg1 = 0;
+	tsk->thread.debugreg2 = 0;
+	tsk->thread.debugreg3 = 0;
+	tsk->thread.debugreg6 = 0;
+	tsk->thread.debugreg7 = 0;
+	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+	/*
+	 * Forget coprocessor state..
+	 */
+	tsk->fpu_counter = 0;
+	clear_fpu(tsk);
+	clear_used_math();
+}
+
+static void hard_disable_TSC(void)
+{
+	write_cr4(read_cr4() | X86_CR4_TSD);
+}
+
+void disable_TSC(void)
+{
+#ifdef CONFIG_SECCOMP_DISABLE_TSC
+	preempt_disable();
+	if (!test_and_set_thread_flag(TIF_NOTSC))
+		/*
+		 * Must flip the CPU state synchronously with
+		 * TIF_NOTSC in the current running context.
+		 */
+		hard_disable_TSC();
+	preempt_enable();
+#endif
+}
+
+static void hard_enable_TSC(void)
+{
+	write_cr4(read_cr4() & ~X86_CR4_TSD);
+}
+
+static void enable_TSC(void)
+{
+	preempt_disable();
+	if (test_and_clear_thread_flag(TIF_NOTSC))
+		/*
+		 * Must flip the CPU state synchronously with
+		 * TIF_NOTSC in the current running context.
+		 */
+		hard_enable_TSC();
+	preempt_enable();
+}
+
+int get_tsc_mode(unsigned long adr)
+{
+	unsigned int val;
+
+	if (test_thread_flag(TIF_NOTSC))
+		val = PR_TSC_SIGSEGV;
+	else
+		val = PR_TSC_ENABLE;
+
+	return put_user(val, (unsigned int __user *)adr);
+}
+
+int set_tsc_mode(unsigned int val)
+{
+	if (val == PR_TSC_SIGSEGV)
+		disable_TSC();
+	else if (val == PR_TSC_ENABLE)
+		enable_TSC();
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
+{
+	struct thread_struct *prev, *next;
+
+	prev = &prev_p->thread;
+	next = &next_p->thread;
+
+	if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
+	    test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
+		ds_switch_to(prev_p, next_p);
+	else if (next->debugctlmsr != prev->debugctlmsr)
+		update_debugctlmsr(next->debugctlmsr);
+
+	if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+		set_debugreg(next->debugreg0, 0);
+		set_debugreg(next->debugreg1, 1);
+		set_debugreg(next->debugreg2, 2);
+		set_debugreg(next->debugreg3, 3);
+		/* no 4 and 5 */
+		set_debugreg(next->debugreg6, 6);
+		set_debugreg(next->debugreg7, 7);
+	}
+
+	if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
+	    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
+		/* prev and next are different */
+		if (test_tsk_thread_flag(next_p, TIF_NOTSC))
+			hard_disable_TSC();
+		else
+			hard_enable_TSC();
+	}
+}
+
+int sys_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+int sys_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
+		       NULL, NULL);
+}
+
+
+/*
+ * Idle related variables and functions
+ */
+unsigned long boot_option_idle_override = 0;
+EXPORT_SYMBOL(boot_option_idle_override);
+
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
+
+#ifdef CONFIG_X86_32
+/*
+ * This halt magic was a workaround for ancient floppy DMA
+ * wreckage. It should be safe to remove.
+ */
+static int hlt_counter;
+void disable_hlt(void)
+{
+	hlt_counter++;
+}
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+	hlt_counter--;
+}
+EXPORT_SYMBOL(enable_hlt);
+
+static inline int hlt_use_halt(void)
+{
+	return (!hlt_counter && boot_cpu_data.hlt_works_ok);
+}
+#else
+static inline int hlt_use_halt(void)
+{
+	return 1;
+}
+#endif
+
+/*
+ * We use this if we don't have any better
+ * idle routine..
+ */
+void xen_idle(void)
+{
+	trace_power_start(POWER_CSTATE, 1);
+	current_thread_info()->status &= ~TS_POLLING;
+	/*
+	 * TS_POLLING-cleared state must be visible before we
+	 * test NEED_RESCHED:
+	 */
+	smp_mb();
+
+	if (!need_resched())
+		safe_halt();	/* enables interrupts racelessly */
+	else
+		local_irq_enable();
+	current_thread_info()->status |= TS_POLLING;
+}
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(default_idle);
+#endif
+
+void stop_this_cpu(void *dummy)
+{
+	local_irq_disable();
+	/*
+	 * Remove this CPU:
+	 */
+	set_cpu_online(smp_processor_id(), false);
+	disable_all_local_evtchn();
+
+	for (;;) {
+		if (hlt_works(smp_processor_id()))
+			halt();
+	}
+}
+
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+	smp_mb();
+	/* kick all the CPUs so that they exit out of pm_idle */
+	smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
+#ifndef CONFIG_XEN
+/*
+ * This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
+ * which can obviate IPI to trigger checking of need_resched.
+ * We execute MONITOR against need_resched and enter optimized wait state
+ * through MWAIT. Whenever someone changes need_resched, we would be woken
+ * up from MWAIT (without an IPI).
+ *
+ * New with Core Duo processors, MWAIT can take some hints based on CPU
+ * capability.
+ */
+void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
+{
+	trace_power_start(POWER_CSTATE, (ax>>4)+1);
+	if (!need_resched()) {
+		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+			clflush((void *)&current_thread_info()->flags);
+
+		__monitor((void *)&current_thread_info()->flags, 0, 0);
+		smp_mb();
+		if (!need_resched())
+			__mwait(ax, cx);
+	}
+}
+
+/* Default MONITOR/MWAIT with no hints, used for default C1 state */
+static void mwait_idle(void)
+{
+	if (!need_resched()) {
+		trace_power_start(POWER_CSTATE, 1);
+		if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
+			clflush((void *)&current_thread_info()->flags);
+
+		__monitor((void *)&current_thread_info()->flags, 0, 0);
+		smp_mb();
+		if (!need_resched())
+			__sti_mwait(0, 0);
+		else
+			local_irq_enable();
+	} else
+		local_irq_enable();
+}
+#endif
+
+/*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->work.need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle(void)
+{
+	trace_power_start(POWER_CSTATE, 0);
+	local_irq_enable();
+	while (!need_resched())
+		cpu_relax();
+	trace_power_end(0);
+}
+
+#ifndef CONFIG_XEN
+/*
+ * mwait selection logic:
+ *
+ * It depends on the CPU. For AMD CPUs that support MWAIT this is
+ * wrong. Family 0x10 and 0x11 CPUs will enter C1 on HLT. Powersavings
+ * then depend on a clock divisor and current Pstate of the core. If
+ * all cores of a processor are in halt state (C1) the processor can
+ * enter the C1E (C1 enhanced) state. If mwait is used this will never
+ * happen.
+ *
+ * idle=mwait overrides this decision and forces the usage of mwait.
+ */
+static int __cpuinitdata force_mwait;
+
+#define MWAIT_INFO			0x05
+#define MWAIT_ECX_EXTENDED_INFO		0x01
+#define MWAIT_EDX_C1			0xf0
+
+static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c)
+{
+	u32 eax, ebx, ecx, edx;
+
+	if (force_mwait)
+		return 1;
+
+	if (c->cpuid_level < MWAIT_INFO)
+		return 0;
+
+	cpuid(MWAIT_INFO, &eax, &ebx, &ecx, &edx);
+	/* Check, whether EDX has extended info about MWAIT */
+	if (!(ecx & MWAIT_ECX_EXTENDED_INFO))
+		return 1;
+
+	/*
+	 * edx enumeratios MONITOR/MWAIT extensions. Check, whether
+	 * C1  supports MWAIT
+	 */
+	return (edx & MWAIT_EDX_C1);
+}
+
+static cpumask_var_t c1e_mask;
+static int c1e_detected;
+
+void c1e_remove_cpu(int cpu)
+{
+	if (c1e_mask != NULL)
+		cpumask_clear_cpu(cpu, c1e_mask);
+}
+
+/*
+ * C1E aware idle routine. We check for C1E active in the interrupt
+ * pending message MSR. If we detect C1E, then we handle it the same
+ * way as C3 power states (local apic timer and TSC stop)
+ */
+static void c1e_idle(void)
+{
+	if (need_resched())
+		return;
+
+	if (!c1e_detected) {
+		u32 lo, hi;
+
+		rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
+		if (lo & K8_INTP_C1E_ACTIVE_MASK) {
+			c1e_detected = 1;
+			if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+				mark_tsc_unstable("TSC halt in AMD C1E");
+			printk(KERN_INFO "System has AMD C1E enabled\n");
+			set_cpu_cap(&boot_cpu_data, X86_FEATURE_AMDC1E);
+		}
+	}
+
+	if (c1e_detected) {
+		int cpu = smp_processor_id();
+
+		if (!cpumask_test_cpu(cpu, c1e_mask)) {
+			cpumask_set_cpu(cpu, c1e_mask);
+			/*
+			 * Force broadcast so ACPI can not interfere.
+			 */
+			clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
+					   &cpu);
+			printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
+			       cpu);
+		}
+		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+
+		default_idle();
+
+		/*
+		 * The switch back from broadcast mode needs to be
+		 * called with interrupts disabled.
+		 */
+		 local_irq_disable();
+		 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+		 local_irq_enable();
+	} else
+		default_idle();
+}
+#endif
+
+void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
+{
+#ifndef CONFIG_XEN
+#ifdef CONFIG_SMP
+	if (pm_idle == poll_idle && smp_num_siblings > 1) {
+		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+			" performance may degrade.\n");
+	}
+#endif
+	if (pm_idle)
+		return;
+
+	if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
+		/*
+		 * One CPU supports mwait => All CPUs supports mwait
+		 */
+		printk(KERN_INFO "using mwait in idle threads.\n");
+		pm_idle = mwait_idle;
+	} else if (cpu_has_amd_erratum(amd_erratum_400)) {
+		/* E400: APIC timer interrupt does not wake up CPU from C1e */
+		printk(KERN_INFO "using C1E aware idle routine\n");
+		pm_idle = c1e_idle;
+	} else
+		pm_idle = default_idle;
+#endif
+}
+
+void __init init_c1e_mask(void)
+{
+#ifndef CONFIG_XEN
+	/* If we're using c1e_idle, we need to allocate c1e_mask. */
+	if (pm_idle == c1e_idle)
+		zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
+#endif
+}
+
+static int __init idle_setup(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "poll")) {
+		printk("using polling idle threads.\n");
+		pm_idle = poll_idle;
+#ifndef CONFIG_XEN
+	} else if (!strcmp(str, "mwait"))
+		force_mwait = 1;
+	else if (!strcmp(str, "halt")) {
+		/*
+		 * When the boot option of idle=halt is added, halt is
+		 * forced to be used for CPU idle. In such case CPU C2/C3
+		 * won't be used again.
+		 * To continue to load the CPU idle driver, don't touch
+		 * the boot_option_idle_override.
+		 */
+		pm_idle = default_idle;
+		idle_halt = 1;
+		return 0;
+	} else if (!strcmp(str, "nomwait")) {
+		/*
+		 * If the boot option of "idle=nomwait" is added,
+		 * it means that mwait will be disabled for CPU C2/C3
+		 * states. In such case it won't touch the variable
+		 * of boot_option_idle_override.
+		 */
+		idle_nomwait = 1;
+		return 0;
+#endif
+	} else
+		return -1;
+
+	boot_option_idle_override = 1;
+	return 0;
+}
+early_param("idle", idle_setup);
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	unsigned long range_end = mm->brk + 0x02000000;
+	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
--- linux-ec2-2.6.32.orig/arch/x86/kernel/process_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/process_32.c
@@ -296,6 +296,8 @@
 void
 start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 {
+	int cpu;
+
 	set_user_gs(regs, 0);
 	regs->fs		= 0;
 	set_fs(USER_DS);
@@ -305,6 +307,11 @@
 	regs->cs		= __USER_CS;
 	regs->ip		= new_ip;
 	regs->sp		= new_sp;
+
+	cpu = get_cpu();
+	load_user_cs_desc(cpu, current->mm);
+	put_cpu();
+
 	/*
 	 * Free the old FP and other extended state
 	 */
@@ -359,6 +366,8 @@
 	preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
 
 	__unlazy_fpu(prev_p);
+	if (next_p->mm)
+		load_user_cs_desc(cpu, next_p->mm);
 
 	/* we're going to use this soon, after a few expensive things */
 	if (preload_fpu)
@@ -497,3 +506,40 @@
 	return 0;
 }
 
+static void modify_cs(struct mm_struct *mm, unsigned long limit)
+{
+	mm->context.exec_limit = limit;
+	set_user_cs(&mm->context.user_cs, limit);
+	if (mm == current->mm) {
+		int cpu;
+
+		cpu = get_cpu();
+		load_user_cs_desc(cpu, mm);
+		put_cpu();
+	}
+}
+
+void arch_add_exec_range(struct mm_struct *mm, unsigned long limit)
+{
+	if (limit > mm->context.exec_limit)
+		modify_cs(mm, limit);
+}
+
+void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end)
+{
+	struct vm_area_struct *vma;
+	unsigned long limit = PAGE_SIZE;
+
+	if (old_end == mm->context.exec_limit) {
+		for (vma = mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+		modify_cs(mm, limit);
+	}
+}
+
+void arch_flush_exec_range(struct mm_struct *mm)
+{
+	mm->context.exec_limit = 0;
+	set_user_cs(&mm->context.user_cs, 0);
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/irq_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/irq_32-xen.c
@@ -0,0 +1,260 @@
+/*
+ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * This file contains the lowest level x86-specific interrupt
+ * entry, irq-stacks and irq statistics code. All the remaining
+ * irq logic is done by the generic kernel/irq/ code and
+ * by the x86-specific irq controller code. (e.g. i8259.c and
+ * io_apic.c.)
+ */
+
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/percpu.h>
+
+#include <asm/apic.h>
+
+DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+EXPORT_PER_CPU_SYMBOL(irq_stat);
+
+DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+EXPORT_PER_CPU_SYMBOL(irq_regs);
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+/* Debugging check for stack overflow: is there less than 1KB free? */
+static int check_stack_overflow(void)
+{
+	long sp;
+
+	__asm__ __volatile__("andl %%esp,%0" :
+			     "=r" (sp) : "0" (THREAD_SIZE - 1));
+
+	return sp < (sizeof(struct thread_info) + STACK_WARN);
+}
+
+static void print_stack_overflow(void)
+{
+	printk(KERN_WARNING "low stack detected by irq handler\n");
+	dump_stack();
+}
+
+#else
+static inline int check_stack_overflow(void) { return 0; }
+static inline void print_stack_overflow(void) { }
+#endif
+
+#ifdef CONFIG_4KSTACKS
+/*
+ * per-CPU IRQ handling contexts (thread information and stack)
+ */
+union irq_ctx {
+	struct thread_info      tinfo;
+	u32                     stack[THREAD_SIZE/sizeof(u32)];
+} __attribute__((aligned(PAGE_SIZE)));
+
+static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
+static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
+
+static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
+static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+
+static void call_on_stack(void *func, void *stack)
+{
+	asm volatile("xchgl	%%ebx,%%esp	\n"
+		     "call	*%%edi		\n"
+		     "movl	%%ebx,%%esp	\n"
+		     : "=b" (stack)
+		     : "0" (stack),
+		       "D"(func)
+		     : "memory", "cc", "edx", "ecx", "eax");
+}
+
+static inline int
+execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
+{
+	union irq_ctx *curctx, *irqctx;
+	u32 *isp, arg1, arg2;
+
+	curctx = (union irq_ctx *) current_thread_info();
+	irqctx = __get_cpu_var(hardirq_ctx);
+
+	/*
+	 * this is where we switch to the IRQ stack. However, if we are
+	 * already using the IRQ stack (because we interrupted a hardirq
+	 * handler) we can't do that and just have to keep using the
+	 * current stack (which is the irq stack already after all)
+	 */
+	if (unlikely(curctx == irqctx))
+		return 0;
+
+	/* build the stack frame on the IRQ stack */
+	isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+	irqctx->tinfo.task = curctx->tinfo.task;
+	irqctx->tinfo.previous_esp = current_stack_pointer;
+
+	/*
+	 * Copy the softirq bits in preempt_count so that the
+	 * softirq checks work in the hardirq context.
+	 */
+	irqctx->tinfo.preempt_count =
+		(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+		(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+
+	if (unlikely(overflow))
+		call_on_stack(print_stack_overflow, isp);
+
+	asm volatile("xchgl	%%ebx,%%esp	\n"
+		     "call	*%%edi		\n"
+		     "movl	%%ebx,%%esp	\n"
+		     : "=a" (arg1), "=d" (arg2), "=b" (isp)
+		     :  "0" (irq),   "1" (desc),  "2" (isp),
+			"D" (desc->handle_irq)
+		     : "memory", "cc", "ecx");
+	return 1;
+}
+
+/*
+ * allocate per-cpu stacks for hardirq and for softirq processing
+ */
+void __cpuinit irq_ctx_init(int cpu)
+{
+	union irq_ctx *irqctx;
+
+	if (per_cpu(hardirq_ctx, cpu))
+		return;
+
+	irqctx = &per_cpu(hardirq_stack, cpu);
+	irqctx->tinfo.task		= NULL;
+	irqctx->tinfo.exec_domain	= NULL;
+	irqctx->tinfo.cpu		= cpu;
+	irqctx->tinfo.preempt_count	= HARDIRQ_OFFSET;
+	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+
+	per_cpu(hardirq_ctx, cpu) = irqctx;
+
+	irqctx = &per_cpu(softirq_stack, cpu);
+	irqctx->tinfo.task		= NULL;
+	irqctx->tinfo.exec_domain	= NULL;
+	irqctx->tinfo.cpu		= cpu;
+	irqctx->tinfo.preempt_count	= 0;
+	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
+
+	per_cpu(softirq_ctx, cpu) = irqctx;
+
+	printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
+	       cpu, per_cpu(hardirq_ctx, cpu),  per_cpu(softirq_ctx, cpu));
+}
+
+void irq_ctx_exit(int cpu)
+{
+	per_cpu(hardirq_ctx, cpu) = NULL;
+}
+
+asmlinkage void do_softirq(void)
+{
+	unsigned long flags;
+	struct thread_info *curctx;
+	union irq_ctx *irqctx;
+	u32 *isp;
+
+	if (in_interrupt())
+		return;
+
+	local_irq_save(flags);
+
+	if (local_softirq_pending()) {
+		curctx = current_thread_info();
+		irqctx = __get_cpu_var(softirq_ctx);
+		irqctx->tinfo.task = curctx->task;
+		irqctx->tinfo.previous_esp = current_stack_pointer;
+
+		/* build the stack frame on the softirq stack */
+		isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
+
+		call_on_stack(__do_softirq, isp);
+		/*
+		 * Shouldnt happen, we returned above if in_interrupt():
+		 */
+		WARN_ON_ONCE(softirq_count());
+	}
+
+	local_irq_restore(flags);
+}
+
+#else
+static inline int
+execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
+#endif
+
+bool handle_irq(unsigned irq, struct pt_regs *regs)
+{
+	struct irq_desc *desc;
+	int overflow;
+
+	overflow = check_stack_overflow();
+
+	desc = irq_to_desc(irq);
+	if (unlikely(!desc))
+		return false;
+
+	if (!execute_on_irq_stack(overflow, desc, irq)) {
+		if (unlikely(overflow))
+			print_stack_overflow();
+		desc->handle_irq(irq, desc);
+	}
+
+	return true;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
+void fixup_irqs(void)
+{
+	unsigned int irq;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(irq, desc) {
+		const struct cpumask *affinity;
+
+		if (!desc)
+			continue;
+		if (irq == 2)
+			continue;
+		if (desc->status & IRQ_PER_CPU)
+			continue;
+
+		affinity = desc->affinity;
+		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+			/*printk("Breaking affinity for irq %i\n", irq);*/
+			affinity = cpu_all_mask;
+		}
+		if (desc->chip->set_affinity)
+			desc->chip->set_affinity(irq, affinity);
+		else if (desc->action)
+			printk_once("Cannot set affinity for irq %i\n", irq);
+	}
+
+#if 0
+	barrier();
+	/* Ingo Molnar says: "after the IO-APIC masks have been redirected
+	   [note the nop - the interrupt-enable boundary on x86 is two
+	   instructions from sti] - to flush out pending hardirqs and
+	   IPIs. After this point nothing is supposed to reach this CPU." */
+	__asm__ __volatile__("sti; nop; cli");
+	barrier();
+#else
+	/* That doesn't seem sufficient.  Give it 1ms. */
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+#endif
+}
+#endif
+
--- linux-ec2-2.6.32.orig/arch/x86/kernel/smpboot.c
+++ linux-ec2-2.6.32/arch/x86/kernel/smpboot.c
@@ -70,7 +70,6 @@
 
 #ifdef CONFIG_X86_32
 u8 apicid_2_node[MAX_APICID];
-static int low_mappings;
 #endif
 
 /* State of each CPU */
@@ -88,6 +87,25 @@
 static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
 #define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
 #define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+
+/*
+ * We need this for trampoline_base protection from concurrent accesses when
+ * off- and onlining cores wildly.
+ */
+static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
+
+void cpu_hotplug_driver_lock()
+{
+        mutex_lock(&x86_cpu_hotplug_driver_mutex);
+}
+
+void cpu_hotplug_driver_unlock()
+{
+        mutex_unlock(&x86_cpu_hotplug_driver_mutex);
+}
+
+ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; }
+ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; }
 #else
 static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
 #define get_idle_for_cpu(x)      (idle_thread_array[(x)])
@@ -273,6 +291,18 @@
 	 * fragile that we want to limit the things done here to the
 	 * most necessary things.
 	 */
+
+#ifdef CONFIG_X86_32
+	/*
+	 * Switch away from the trampoline page-table
+	 *
+	 * Do this before cpu_init() because it needs to access per-cpu
+	 * data which may not be mapped in the trampoline page-table.
+	 */
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
+#endif
+
 	vmi_bringup();
 	cpu_init();
 	preempt_disable();
@@ -291,12 +321,6 @@
 		enable_8259A_irq(0);
 	}
 
-#ifdef CONFIG_X86_32
-	while (low_mappings)
-		cpu_relax();
-	__flush_tlb_all();
-#endif
-
 	/* This must be done before setting cpu_online_mask */
 	set_cpu_sibling_map(raw_smp_processor_id());
 	wmb();
@@ -722,6 +746,7 @@
 #ifdef CONFIG_X86_32
 	/* Stack for startup_32 can be just as for start_secondary onwards */
 	irq_ctx_init(cpu);
+	initial_page_table = __pa(&trampoline_pg_dir);
 #else
 	clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
 	initial_gs = per_cpu_offset(cpu);
@@ -866,20 +891,8 @@
 
 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 
-#ifdef CONFIG_X86_32
-	/* init low mem mapping */
-	clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-		min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
-	flush_tlb_all();
-	low_mappings = 1;
-
 	err = do_boot_cpu(apicid, cpu);
 
-	zap_low_mappings(false);
-	low_mappings = 0;
-#else
-	err = do_boot_cpu(apicid, cpu);
-#endif
 	if (err) {
 		pr_debug("do_boot_cpu failed %d\n", err);
 		return -EIO;
@@ -1066,9 +1079,7 @@
 	set_cpu_sibling_map(0);
 
 	enable_IR_x2apic();
-#ifdef CONFIG_X86_64
 	default_setup_apic_routing();
-#endif
 
 	if (smp_sanity_check(max_cpus) < 0) {
 		printk(KERN_INFO "SMP disabled\n");
@@ -1327,11 +1338,94 @@
 	local_irq_disable();
 }
 
+#define MWAIT_SUBSTATE_MASK		0xf
+#define MWAIT_SUBSTATE_SIZE		4
+
+#define CPUID_MWAIT_LEAF		5
+#define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
+
+/*
+ * We need to flush the caches before going to sleep, lest we have
+ * dirty data in our caches when we come back up.
+ */
+static inline void mwait_play_dead(void)
+{
+	unsigned int eax, ebx, ecx, edx;
+	unsigned int highest_cstate = 0;
+	unsigned int highest_subcstate = 0;
+	int i;
+	void *mwait_ptr;
+
+	if (!cpu_has(&current_cpu_data, X86_FEATURE_MWAIT))
+		return;
+	if (!cpu_has(&current_cpu_data, X86_FEATURE_CLFLSH))
+		return;
+	if (current_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+		return;
+
+	eax = CPUID_MWAIT_LEAF;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+
+	/*
+	 * eax will be 0 if EDX enumeration is not valid.
+	 * Initialized below to cstate, sub_cstate value when EDX is valid.
+	 */
+	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
+		eax = 0;
+	} else {
+		edx >>= MWAIT_SUBSTATE_SIZE;
+		for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
+			if (edx & MWAIT_SUBSTATE_MASK) {
+				highest_cstate = i;
+				highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
+			}
+		}
+		eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
+			(highest_subcstate - 1);
+	}
+
+	/*
+	 * This should be a memory location in a cache line which is
+	 * unlikely to be touched by other processors.  The actual
+	 * content is immaterial as it is not actually modified in any way.
+	 */
+	mwait_ptr = &current_thread_info()->flags;
+
+	wbinvd();
+
+	while (1) {
+		/*
+		 * The CLFLUSH is a workaround for erratum AAI65 for
+		 * the Xeon 7400 series.  It's not clear it is actually
+		 * needed, but it should be harmless in either case.
+		 * The WBINVD is insufficient due to the spurious-wakeup
+		 * case where we return around the loop.
+		 */
+		clflush(mwait_ptr);
+		__monitor(mwait_ptr, 0, 0);
+		mb();
+		__mwait(eax, 0);
+	}
+}
+
+static inline void hlt_play_dead(void)
+{
+	if (current_cpu_data.x86 >= 4)
+		wbinvd();
+
+	while (1) {
+		native_halt();
+	}
+}
+
 void native_play_dead(void)
 {
 	play_dead_common();
 	tboot_shutdown(TB_SHUTDOWN_WFS);
-	wbinvd_halt();
+
+	mwait_play_dead();	/* Only returns on failure */
+	hlt_play_dead();
 }
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/tboot.c
+++ linux-ec2-2.6.32/arch/x86/kernel/tboot.c
@@ -46,6 +46,7 @@
 
 /* Global pointer to shared data; NULL means no measured launch. */
 struct tboot *tboot __read_mostly;
+EXPORT_SYMBOL(tboot);
 
 /* timeout for APs (in secs) to enter wait-for-SIPI state during shutdown */
 #define AP_WAIT_TIMEOUT		1
--- linux-ec2-2.6.32.orig/arch/x86/kernel/setup_percpu.c
+++ linux-ec2-2.6.32/arch/x86/kernel/setup_percpu.c
@@ -224,7 +224,7 @@
 		 * are zeroed indicating that the static arrays are
 		 * gone.
 		 */
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 		per_cpu(x86_cpu_to_apicid, cpu) =
 			early_per_cpu_map(x86_cpu_to_apicid, cpu);
 		per_cpu(x86_bios_cpu_apicid, cpu) =
@@ -248,7 +248,7 @@
 	}
 
 	/* indicate the early static arrays will soon be gone */
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 	early_per_cpu_ptr(x86_cpu_to_apicid) = NULL;
 	early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL;
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/rtc.c
+++ linux-ec2-2.6.32/arch/x86/kernel/rtc.c
@@ -171,6 +171,11 @@
 	unsigned long flags;
 	int retval;
 
+#ifdef CONFIG_XEN
+	if (xen_update_persistent_clock() < 0 || xen_independent_wallclock())
+		return 0;
+#endif
+
 	spin_lock_irqsave(&rtc_lock, flags);
 	retval = x86_platform.set_wallclock(now.tv_sec);
 	spin_unlock_irqrestore(&rtc_lock, flags);
@@ -183,6 +188,12 @@
 {
 	unsigned long retval, flags;
 
+#ifdef CONFIG_XEN
+	if (!is_initial_xendomain()) {
+		xen_read_persistent_clock(ts);
+		return;
+	}
+#endif
 	spin_lock_irqsave(&rtc_lock, flags);
 	retval = x86_platform.get_wallclock();
 	spin_unlock_irqrestore(&rtc_lock, flags);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/mmconf-fam10h_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/mmconf-fam10h_64.c
@@ -218,6 +218,16 @@
 	val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
 	       FAM10H_MMIO_CONF_ENABLE;
 	wrmsrl(address, val);
+
+#ifdef CONFIG_XEN
+	{
+		u64 val2;
+
+		rdmsrl(address, val2);
+		if (val2 != val)
+			pci_probe &= ~PCI_CHECK_ENABLE_AMD_MMCONF;
+	}
+#endif
 }
 
 static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/time-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/time-xen.c
@@ -0,0 +1,932 @@
+/*
+ *  Copyright (c) 1991,1992,1995  Linus Torvalds
+ *  Copyright (c) 1994  Alan Modra
+ *  Copyright (c) 1995  Markus Kuhn
+ *  Copyright (c) 1996  Ingo Molnar
+ *  Copyright (c) 1998  Andrea Arcangeli
+ *  Copyright (c) 2002,2006  Vojtech Pavlik
+ *  Copyright (c) 2003  Andi Kleen
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/mca.h>
+#include <linux/sysctl.h>
+#include <linux/percpu.h>
+#include <linux/kernel_stat.h>
+#include <linux/posix-timers.h>
+#include <linux/cpufreq.h>
+#include <linux/clocksource.h>
+#include <linux/sysdev.h>
+
+#include <asm/vsyscall.h>
+#include <asm/delay.h>
+#include <asm/time.h>
+#include <asm/timer.h>
+
+#include <xen/evtchn.h>
+#include <xen/sysctl.h>
+#include <xen/interface/vcpu.h>
+
+#include <asm/i8253.h>
+DEFINE_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
+
+#ifdef CONFIG_X86_64
+volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
+#endif
+
+#define XEN_SHIFT 22
+
+unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
+EXPORT_SYMBOL(cpu_khz);
+
+/* These are peridically updated in shared_info, and then copied here. */
+struct shadow_time_info {
+	u64 tsc_timestamp;     /* TSC at last update of time vals.  */
+	u64 system_timestamp;  /* Time, in nanosecs, since boot.    */
+	u32 tsc_to_nsec_mul;
+	u32 tsc_to_usec_mul;
+	int tsc_shift;
+	u32 version;
+};
+static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
+static struct timespec shadow_tv;
+static u32 shadow_tv_version;
+
+/* Keep track of last time we did processing/updating of jiffies and xtime. */
+static u64 processed_system_time;   /* System time (ns) at last processing. */
+static DEFINE_PER_CPU(u64, processed_system_time);
+
+/* How much CPU time was spent blocked and how much was 'stolen'? */
+static DEFINE_PER_CPU(u64, processed_stolen_time);
+static DEFINE_PER_CPU(u64, processed_blocked_time);
+
+/* Current runstate of each CPU (updated automatically by the hypervisor). */
+static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+
+/* Must be signed, as it's compared with s64 quantities which can be -ve. */
+#define NS_PER_TICK (1000000000LL/HZ)
+
+static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
+	.period_ns = NS_PER_TICK
+};
+
+static void __clock_was_set(struct work_struct *unused)
+{
+	clock_was_set();
+}
+static DECLARE_WORK(clock_was_set_work, __clock_was_set);
+
+/*
+ * 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)--;
+	}
+}
+
+/* Does this guest OS track Xen time, or set its wall clock independently? */
+static int independent_wallclock = 0;
+static int __init __independent_wallclock(char *str)
+{
+	independent_wallclock = 1;
+	return 1;
+}
+__setup("independent_wallclock", __independent_wallclock);
+
+int xen_independent_wallclock(void)
+{
+	return independent_wallclock;
+}
+
+/* Permitted clock jitter, in nsecs, beyond which a warning will be printed. */
+static unsigned long permitted_clock_jitter = 10000000UL; /* 10ms */
+static int __init __permitted_clock_jitter(char *str)
+{
+	permitted_clock_jitter = simple_strtoul(str, NULL, 0);
+	return 1;
+}
+__setup("permitted_clock_jitter=", __permitted_clock_jitter);
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
+{
+	u64 product;
+#ifdef __i386__
+	u32 tmp1, tmp2;
+#endif
+
+	if (shift < 0)
+		delta >>= -shift;
+	else
+		delta <<= shift;
+
+#ifdef __i386__
+	__asm__ (
+		"mul  %5       ; "
+		"mov  %4,%%eax ; "
+		"mov  %%edx,%4 ; "
+		"mul  %5       ; "
+		"xor  %5,%5    ; "
+		"add  %4,%%eax ; "
+		"adc  %5,%%edx ; "
+		: "=A" (product), "=r" (tmp1), "=r" (tmp2)
+		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
+#else
+	__asm__ (
+		"mul %%rdx ; shrd $32,%%rdx,%%rax"
+		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
+#endif
+
+	return product;
+}
+
+static inline u64 get64(volatile u64 *ptr)
+{
+#ifndef CONFIG_64BIT
+	return cmpxchg64(ptr, 0, 0);
+#else
+	return *ptr;
+#endif
+}
+
+static inline u64 get64_local(volatile u64 *ptr)
+{
+#ifndef CONFIG_64BIT
+	return cmpxchg64_local(ptr, 0, 0);
+#else
+	return *ptr;
+#endif
+}
+
+static void init_cpu_khz(void)
+{
+	u64 __cpu_khz = 1000000ULL << 32;
+	struct vcpu_time_info *info = &vcpu_info(0)->time;
+	do_div(__cpu_khz, info->tsc_to_system_mul);
+	if (info->tsc_shift < 0)
+		cpu_khz = __cpu_khz << -info->tsc_shift;
+	else
+		cpu_khz = __cpu_khz >> info->tsc_shift;
+}
+
+static u64 get_nsec_offset(struct shadow_time_info *shadow)
+{
+	u64 now, delta;
+	rdtscll(now);
+	delta = now - shadow->tsc_timestamp;
+	return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
+}
+
+static void __update_wallclock(time_t sec, long nsec)
+{
+	long wtm_nsec, xtime_nsec;
+	time_t wtm_sec, xtime_sec;
+	u64 tmp, wc_nsec;
+
+	/* Adjust wall-clock time base. */
+	wc_nsec = processed_system_time;
+	wc_nsec += sec * (u64)NSEC_PER_SEC;
+	wc_nsec += nsec;
+
+	/* Split wallclock base into seconds and nanoseconds. */
+	tmp = wc_nsec;
+	xtime_nsec = do_div(tmp, 1000000000);
+	xtime_sec  = (time_t)tmp;
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
+
+	set_normalized_timespec(&xtime, xtime_sec, xtime_nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+}
+
+static void update_wallclock(void)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+
+	do {
+		shadow_tv_version = s->wc_version;
+		rmb();
+		shadow_tv.tv_sec  = s->wc_sec;
+		shadow_tv.tv_nsec = s->wc_nsec;
+		rmb();
+	} while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
+
+	if (!independent_wallclock)
+		__update_wallclock(shadow_tv.tv_sec, shadow_tv.tv_nsec);
+}
+
+/*
+ * Reads a consistent set of time-base values from Xen, into a shadow data
+ * area.
+ */
+static void get_time_values_from_xen(unsigned int cpu)
+{
+	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 {
+		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();
+		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(void)
+{
+	rmb();
+	return percpu_read(shadow_time.version) == vcpu_info_read(time.version);
+}
+
+static void sync_xen_wallclock(unsigned long dummy);
+static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
+static void sync_xen_wallclock(unsigned long dummy)
+{
+	time_t sec;
+	s64 nsec;
+	struct xen_platform_op op;
+
+	BUG_ON(!is_initial_xendomain());
+	if (!ntp_synced() || independent_wallclock)
+		return;
+
+	write_seqlock_irq(&xtime_lock);
+
+	sec  = xtime.tv_sec;
+	nsec = xtime.tv_nsec;
+	__normalize_time(&sec, &nsec);
+
+	op.cmd = XENPF_settime;
+	op.u.settime.secs        = sec;
+	op.u.settime.nsecs       = nsec;
+	op.u.settime.system_time = processed_system_time;
+	WARN_ON(HYPERVISOR_platform_op(&op));
+
+	update_wallclock();
+
+	write_sequnlock_irq(&xtime_lock);
+
+	/* Once per minute. */
+	mod_timer(&sync_xen_wallclock_timer, jiffies + 60*HZ);
+}
+
+static unsigned long long local_clock(void)
+{
+	unsigned int cpu = get_cpu();
+	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+	u64 time;
+	u32 local_time_version;
+
+	do {
+		local_time_version = shadow->version;
+		rdtsc_barrier();
+		time = shadow->system_timestamp + get_nsec_offset(shadow);
+		if (!time_values_up_to_date())
+			get_time_values_from_xen(cpu);
+		barrier();
+	} while (local_time_version != shadow->version);
+
+	put_cpu();
+
+	return time;
+}
+
+/*
+ * Runstate accounting
+ */
+static void get_runstate_snapshot(struct vcpu_runstate_info *res)
+{
+	u64 state_time;
+	struct vcpu_runstate_info *state;
+
+	BUG_ON(preemptible());
+
+	state = &__get_cpu_var(runstate);
+
+	do {
+		state_time = get64_local(&state->state_entry_time);
+		*res = *state;
+	} while (get64_local(&state->state_entry_time) != state_time);
+
+	WARN_ON_ONCE(res->state != RUNSTATE_running);
+}
+
+/*
+ * Xen sched_clock implementation.  Returns the number of unstolen
+ * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED
+ * states.
+ */
+unsigned long long sched_clock(void)
+{
+	struct vcpu_runstate_info runstate;
+	cycle_t now;
+	u64 ret;
+	s64 offset;
+
+	/*
+	 * Ideally sched_clock should be called on a per-cpu basis
+	 * anyway, so preempt should already be disabled, but that's
+	 * not current practice at the moment.
+	 */
+	preempt_disable();
+
+	now = local_clock();
+
+	get_runstate_snapshot(&runstate);
+
+	offset = now - runstate.state_entry_time;
+	if (offset < 0)
+		offset = 0;
+
+	ret = offset + runstate.time[RUNSTATE_running]
+	      + runstate.time[RUNSTATE_blocked];
+
+	preempt_enable();
+
+	return ret;
+}
+
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (!user_mode_vm(regs) && in_lock_functions(pc)) {
+#ifdef CONFIG_FRAME_POINTER
+		return *(unsigned long *)(regs->bp + sizeof(long));
+#else
+		unsigned long *sp =
+			(unsigned long *)kernel_stack_pointer(regs);
+
+		/*
+		 * Return address is either directly at stack pointer
+		 * or above a saved flags. Eflags has bits 22-31 zero,
+		 * kernel addresses don't.
+		 */
+		if (sp[0] >> 22)
+			return sp[0];
+		if (sp[1] >> 22)
+			return sp[1];
+#endif
+	}
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+
+/*
+ * Default timer interrupt handler
+ */
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	s64 delta, delta_cpu, stolen, blocked;
+	unsigned int i, cpu = smp_processor_id();
+	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+	struct vcpu_runstate_info runstate;
+
+	/* Keep nmi watchdog up to date */
+	inc_irq_stat(irq0_irqs);
+
+	/*
+	 * Here we are in the timer irq handler. We just have irqs locally
+	 * disabled but we don't know if the timer_bh is running on the other
+	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+	 * the irq version of write_lock because as just said we have irq
+	 * locally disabled. -arca
+	 */
+	write_seqlock(&xtime_lock);
+
+	do {
+		get_time_values_from_xen(cpu);
+
+		/* Obtain a consistent snapshot of elapsed wallclock cycles. */
+		delta = delta_cpu =
+			shadow->system_timestamp + get_nsec_offset(shadow);
+		delta     -= processed_system_time;
+		delta_cpu -= per_cpu(processed_system_time, cpu);
+
+		get_runstate_snapshot(&runstate);
+	} while (!time_values_up_to_date());
+
+	if ((unlikely(delta < -(s64)permitted_clock_jitter) ||
+	     unlikely(delta_cpu < -(s64)permitted_clock_jitter))
+	    && printk_ratelimit()) {
+		printk("Timer ISR/%u: Time went backwards: "
+		       "delta=%lld delta_cpu=%lld shadow=%lld "
+		       "off=%lld processed=%lld cpu_processed=%lld\n",
+		       cpu, delta, delta_cpu, shadow->system_timestamp,
+		       (s64)get_nsec_offset(shadow),
+		       processed_system_time,
+		       per_cpu(processed_system_time, cpu));
+		for (i = 0; i < num_online_cpus(); i++)
+			printk(" %d: %lld\n", i,
+			       per_cpu(processed_system_time, i));
+	}
+
+	/* System-wide jiffy work. */
+	if (delta >= NS_PER_TICK) {
+		do_div(delta, NS_PER_TICK);
+		processed_system_time += delta * NS_PER_TICK;
+		while (delta > HZ) {
+			clobber_induction_variable(delta);
+			do_timer(HZ);
+			delta -= HZ;
+		}
+		do_timer(delta);
+	}
+
+	if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
+		update_wallclock();
+		if (keventd_up())
+			schedule_work(&clock_was_set_work);
+	}
+
+	write_sequnlock(&xtime_lock);
+
+	/*
+	 * Account stolen ticks.
+	 * ensures that the ticks are accounted as stolen.
+	 */
+	stolen = runstate.time[RUNSTATE_runnable]
+		 + runstate.time[RUNSTATE_offline]
+		 - per_cpu(processed_stolen_time, cpu);
+	if ((stolen > 0) && (delta_cpu > 0)) {
+		delta_cpu -= stolen;
+		if (unlikely(delta_cpu < 0))
+			stolen += delta_cpu; /* clamp local-time progress */
+		do_div(stolen, NS_PER_TICK);
+		per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK;
+		per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK;
+		account_steal_time((cputime_t)stolen);
+	}
+
+	/*
+	 * Account blocked ticks.
+	 * ensures that the ticks are accounted as idle/wait.
+	 */
+	blocked = runstate.time[RUNSTATE_blocked]
+		  - per_cpu(processed_blocked_time, cpu);
+	if ((blocked > 0) && (delta_cpu > 0)) {
+		delta_cpu -= blocked;
+		if (unlikely(delta_cpu < 0))
+			blocked += delta_cpu; /* clamp local-time progress */
+		do_div(blocked, NS_PER_TICK);
+		per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK;
+		per_cpu(processed_system_time, cpu)  += blocked * NS_PER_TICK;
+		account_idle_time((cputime_t)blocked);
+	}
+
+	/* Account user/system ticks. */
+	if (delta_cpu > 0) {
+		do_div(delta_cpu, NS_PER_TICK);
+		per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK;
+		if (user_mode_vm(get_irq_regs()))
+			account_user_time(current, (cputime_t)delta_cpu,
+					  (cputime_t)delta_cpu);
+		else if (current != idle_task(cpu))
+			account_system_time(current, HARDIRQ_OFFSET,
+					    (cputime_t)delta_cpu,
+					    (cputime_t)delta_cpu);
+		else
+			account_idle_time((cputime_t)delta_cpu);
+	}
+
+	/* Offlined for more than a few seconds? Avoid lockup warnings. */
+	if (stolen > 5*HZ)
+		touch_softlockup_watchdog();
+
+	/* Local timer processing (see update_process_times()). */
+	run_local_timers();
+	rcu_check_callbacks(cpu, user_mode_vm(get_irq_regs()));
+	printk_tick();
+	scheduler_tick();
+	run_posix_cpu_timers(current);
+	profile_tick(CPU_PROFILING);
+
+	return IRQ_HANDLED;
+}
+
+void mark_tsc_unstable(char *reason)
+{
+#ifndef CONFIG_XEN /* XXX Should tell the hypervisor about this fact. */
+	tsc_unstable = 1;
+#endif
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
+static void init_missing_ticks_accounting(unsigned int cpu)
+{
+	struct vcpu_register_runstate_memory_area area;
+	struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
+	int rc;
+
+	memset(runstate, 0, sizeof(*runstate));
+
+	area.addr.v = runstate;
+	rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, &area);
+	WARN_ON(rc && rc != -ENOSYS);
+
+	per_cpu(processed_blocked_time, cpu) =
+		runstate->time[RUNSTATE_blocked];
+	per_cpu(processed_stolen_time, cpu) =
+		runstate->time[RUNSTATE_runnable] +
+		runstate->time[RUNSTATE_offline];
+}
+
+static cycle_t cs_last;
+
+static cycle_t xen_clocksource_read(struct clocksource *cs)
+{
+#ifdef CONFIG_SMP
+	cycle_t last = get64(&cs_last);
+	cycle_t ret = local_clock();
+
+	if (unlikely((s64)(ret - last) < 0)) {
+		if (last - ret > permitted_clock_jitter
+		    && printk_ratelimit()) {
+			unsigned int cpu = get_cpu();
+			struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
+
+			printk(KERN_WARNING "clocksource/%u: "
+			       "Time went backwards: "
+			       "ret=%Lx delta=%Ld shadow=%Lx offset=%Lx\n",
+			       cpu, ret, ret - last, shadow->system_timestamp,
+			       get_nsec_offset(shadow));
+			put_cpu();
+		}
+		return last;
+	}
+
+	for (;;) {
+		cycle_t cur = cmpxchg64(&cs_last, last, ret);
+
+		if (cur == last || (s64)(ret - cur) < 0)
+			return ret;
+		last = cur;
+	}
+#else
+	return local_clock();
+#endif
+}
+
+/* No locking required. Interrupts are disabled on all CPUs. */
+static void xen_clocksource_resume(void)
+{
+	unsigned int cpu;
+
+	init_cpu_khz();
+
+	for_each_online_cpu(cpu) {
+		switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+					   &xen_set_periodic_tick)) {
+		case 0:
+#if CONFIG_XEN_COMPAT <= 0x030004
+		case -ENOSYS:
+#endif
+			break;
+		default:
+			BUG();
+		}
+		get_time_values_from_xen(cpu);
+		per_cpu(processed_system_time, cpu) =
+			per_cpu(shadow_time, 0).system_timestamp;
+		init_missing_ticks_accounting(cpu);
+	}
+
+	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
+
+	cs_last = local_clock();
+}
+
+static struct clocksource clocksource_xen = {
+	.name			= "xen",
+	.rating			= 400,
+	.read			= xen_clocksource_read,
+	.mask			= CLOCKSOURCE_MASK(64),
+	.mult			= 1 << XEN_SHIFT,		/* time directly in nanoseconds */
+	.shift			= XEN_SHIFT,
+	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume			= xen_clocksource_resume,
+};
+
+void xen_read_persistent_clock(struct timespec *ts)
+{
+	const shared_info_t *s = HYPERVISOR_shared_info;
+	u32 version, sec, nsec;
+	u64 delta;
+
+	do {
+		version = s->wc_version;
+		rmb();
+		sec     = s->wc_sec;
+		nsec    = s->wc_nsec;
+		rmb();
+	} while ((s->wc_version & 1) | (version ^ s->wc_version));
+
+	delta = local_clock() + (u64)sec * NSEC_PER_SEC + nsec;
+	do_div(delta, NSEC_PER_SEC);
+
+	ts->tv_sec = delta;
+	ts->tv_nsec = 0;
+}
+
+int xen_update_persistent_clock(void)
+{
+	if (!is_initial_xendomain())
+		return -1;
+	mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
+	return 0;
+}
+
+/* Dynamically-mapped IRQ. */
+static int __read_mostly timer_irq = -1;
+static struct irqaction timer_action = {
+	.handler = timer_interrupt,
+	.flags   = IRQF_DISABLED|IRQF_TIMER,
+	.name    = "timer"
+};
+
+static void __init setup_cpu0_timer_irq(void)
+{
+	timer_irq = bind_virq_to_irqaction(VIRQ_TIMER, 0, &timer_action);
+	BUG_ON(timer_irq < 0);
+}
+
+void __init time_init(void)
+{
+	init_cpu_khz();
+	printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n",
+	       cpu_khz / 1000, cpu_khz % 1000);
+
+	switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
+				   &xen_set_periodic_tick)) {
+	case 0:
+#if CONFIG_XEN_COMPAT <= 0x030004
+	case -ENOSYS:
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	get_time_values_from_xen(0);
+
+	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
+	per_cpu(processed_system_time, 0) = processed_system_time;
+	init_missing_ticks_accounting(0);
+
+	clocksource_register(&clocksource_xen);
+
+	update_wallclock();
+
+	use_tsc_delay();
+
+	/* Cannot request_irq() until kmem is initialised. */
+	late_time_init = setup_cpu0_timer_irq;
+}
+
+/* Convert jiffies to system time. */
+u64 jiffies_to_st(unsigned long j)
+{
+	unsigned long seq;
+	long delta;
+	u64 st;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		delta = j - jiffies;
+		if (delta < 1) {
+			/* Triggers in some wrap-around cases, but that's okay:
+			 * we just end up with a shorter timeout. */
+			st = processed_system_time + NS_PER_TICK;
+		} else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
+			/* Very long timeout means there is no pending timer.
+			 * We indicate this to Xen by passing zero timeout. */
+			st = 0;
+		} else {
+			st = processed_system_time + delta * (u64)NS_PER_TICK;
+		}
+	} while (read_seqretry(&xtime_lock, seq));
+
+	return st;
+}
+EXPORT_SYMBOL(jiffies_to_st);
+
+/*
+ * stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
+ * These functions are based on implementations from arch/s390/kernel/time.c
+ */
+static void stop_hz_timer(void)
+{
+	struct vcpu_set_singleshot_timer singleshot;
+	unsigned int cpu = smp_processor_id();
+	unsigned long j;
+	int rc;
+
+	cpumask_set_cpu(cpu, nohz_cpu_mask);
+
+	/* See matching smp_mb in rcu_start_batch in rcupdate.c.  These mbs  */
+	/* ensure that if __rcu_pending (nested in rcu_needs_cpu) fetches a  */
+	/* value of rcp->cur that matches rdp->quiescbatch and allows us to  */
+	/* stop the hz timer then the cpumasks created for subsequent values */
+	/* of cur in rcu_start_batch are guaranteed to pick up the updated   */
+	/* nohz_cpu_mask and so will not depend on this cpu.                 */
+
+	smp_mb();
+
+	/* Leave ourselves in tick mode if rcu or softirq or timer pending. */
+	if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) ||
+	    local_softirq_pending() ||
+	    (j = get_next_timer_interrupt(jiffies),
+	     time_before_eq(j, jiffies))) {
+		cpumask_clear_cpu(cpu, nohz_cpu_mask);
+		j = jiffies + 1;
+	}
+
+	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
+	if (rc) {
+		BUG_ON(rc != -ENOSYS);
+		rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
+	}
+#endif
+	BUG_ON(rc);
+}
+
+static void start_hz_timer(void)
+{
+	cpumask_clear_cpu(smp_processor_id(), nohz_cpu_mask);
+}
+
+void xen_safe_halt(void)
+{
+	stop_hz_timer();
+	/* Blocking includes an implicit local_irq_enable(). */
+	HYPERVISOR_block();
+	start_hz_timer();
+}
+EXPORT_SYMBOL(xen_safe_halt);
+
+void xen_halt(void)
+{
+	if (irqs_disabled())
+		VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL));
+}
+EXPORT_SYMBOL(xen_halt);
+
+#ifdef CONFIG_SMP
+int __cpuinit local_setup_timer(unsigned int cpu)
+{
+	int seq, irq;
+
+	BUG_ON(cpu == 0);
+
+	switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+			   &xen_set_periodic_tick)) {
+	case 0:
+#if CONFIG_XEN_COMPAT <= 0x030004
+	case -ENOSYS:
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		/* Use cpu0 timestamp: cpu's shadow is not initialised yet. */
+		per_cpu(processed_system_time, cpu) =
+			per_cpu(shadow_time, 0).system_timestamp;
+		init_missing_ticks_accounting(cpu);
+	} while (read_seqretry(&xtime_lock, seq));
+
+	irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action);
+	if (irq < 0)
+		return irq;
+	BUG_ON(timer_irq != irq);
+
+	return 0;
+}
+
+void __cpuinit local_teardown_timer(unsigned int cpu)
+{
+	BUG_ON(cpu == 0);
+	unbind_from_per_cpu_irq(timer_irq, cpu, &timer_action);
+}
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 
+				void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	struct xen_platform_op op;
+
+	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
+		return 0;
+
+	if (val == CPUFREQ_PRECHANGE)
+		return 0;
+
+	op.cmd = XENPF_change_freq;
+	op.u.change_freq.flags = 0;
+	op.u.change_freq.cpu = freq->cpu;
+	op.u.change_freq.freq = (u64)freq->new * 1000;
+	WARN_ON(HYPERVISOR_platform_op(&op));
+
+	return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+	.notifier_call = time_cpufreq_notifier
+};
+
+static int __init cpufreq_time_setup(void)
+{
+	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+			CPUFREQ_TRANSITION_NOTIFIER)) {
+		printk(KERN_ERR "failed to set up cpufreq notifier\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+core_initcall(cpufreq_time_setup);
+#endif
+
+/*
+ * /proc/sys/xen: This really belongs in another file. It can stay here for
+ * now however.
+ */
+static ctl_table xen_subtable[] = {
+	{
+		.ctl_name	= CTL_XEN_INDEPENDENT_WALLCLOCK,
+		.procname	= "independent_wallclock",
+		.data		= &independent_wallclock,
+		.maxlen		= sizeof(independent_wallclock),
+		.mode		= 0644,
+		.strategy	= sysctl_data,
+		.proc_handler	= proc_dointvec
+	},
+	{
+		.ctl_name	= CTL_XEN_PERMITTED_CLOCK_JITTER,
+		.procname	= "permitted_clock_jitter",
+		.data		= &permitted_clock_jitter,
+		.maxlen		= sizeof(permitted_clock_jitter),
+		.mode		= 0644,
+		.strategy	= sysctl_data,
+		.proc_handler	= proc_doulongvec_minmax
+	},
+	{ }
+};
+static ctl_table xen_table[] = {
+	{
+		.ctl_name	= CTL_XEN,
+		.procname	= "xen",
+		.mode		= 0555,
+		.child		= xen_subtable
+	},
+	{ }
+};
+static int __init xen_sysctl_init(void)
+{
+	(void)register_sysctl_table(xen_table);
+	return 0;
+}
+__initcall(xen_sysctl_init);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/setup.c
+++ linux-ec2-2.6.32/arch/x86/kernel/setup.c
@@ -109,6 +109,8 @@
 #ifdef CONFIG_X86_64
 #include <asm/numa_64.h>
 #endif
+#include <asm/mce.h>
+#include <asm/trampoline.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -666,19 +668,38 @@
 			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"),
 		},
 	},
-	{
 	/*
-	 * AMI BIOS with low memory corruption was found on Intel DG45ID board.
-	 * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+	 * AMI BIOS with low memory corruption was found on Intel DG45ID and
+	 * DG45FC boards.
+	 * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
 	 * match only DMI_BOARD_NAME and see if there is more bad products
 	 * with this vendor.
 	 */
+	{
 		.callback = dmi_low_memory_corruption,
 		.ident = "AMI BIOS",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
 		},
 	},
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "DG45FC"),
+		},
+	},
+	/*
+	 * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so
+	 * match on the product name.
+	 */
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "Phoenix BIOS",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
+		},
+	},
 #endif
 	{}
 };
@@ -978,6 +999,8 @@
 	paging_init();
 	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
 
+	setup_trampoline_page_table();
+
 	tboot_probe();
 
 #ifdef CONFIG_X86_64
@@ -1031,6 +1054,8 @@
 #endif
 #endif
 	x86_init.oem.banner();
+
+	mcheck_intel_therm_init();
 }
 
 #ifdef CONFIG_X86_32
--- linux-ec2-2.6.32.orig/arch/x86/kernel/k8.c
+++ linux-ec2-2.6.32/arch/x86/kernel/k8.c
@@ -121,3 +121,17 @@
 }
 EXPORT_SYMBOL_GPL(k8_flush_garts);
 
+static __init int init_k8_nbs(void)
+{
+	int err = 0;
+
+	err = cache_k8_northbridges();
+
+	if (err < 0)
+		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");
+
+	return err;
+}
+
+/* This has to go after the PCI subsystem */
+fs_initcall(init_k8_nbs);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/early-quirks.c
+++ linux-ec2-2.6.32/arch/x86/kernel/early-quirks.c
@@ -145,15 +145,10 @@
 
 static u32 __init ati_sbx00_rev(int num, int slot, int func)
 {
-	u32 old, d;
+	u32 d;
 
-	d = read_pci_config(num, slot, func, 0x70);
-	old = d;
-	d &= ~(1<<8);
-	write_pci_config(num, slot, func, 0x70, d);
 	d = read_pci_config(num, slot, func, 0x8);
 	d &= 0xff;
-	write_pci_config(num, slot, func, 0x70, old);
 
 	return d;
 }
@@ -162,11 +157,19 @@
 {
 	u32 d, rev;
 
-	if (acpi_use_timer_override)
+	rev = ati_sbx00_rev(num, slot, func);
+	if (rev >= 0x40)
+		acpi_fix_pin2_polarity = 1;
+
+	/*
+	 * SB600: revisions 0x11, 0x12, 0x13, 0x14, ...
+	 * SB700: revisions 0x39, 0x3a, ...
+	 * SB800: revisions 0x40, 0x41, ...
+	 */
+	if (rev >= 0x39)
 		return;
 
-	rev = ati_sbx00_rev(num, slot, func);
-	if (rev > 0x13)
+	if (acpi_use_timer_override)
 		return;
 
 	/* check for IRQ0 interrupt swap */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/init_task.c
+++ linux-ec2-2.6.32/arch/x86/kernel/init_task.c
@@ -31,6 +31,7 @@
 struct task_struct init_task = INIT_TASK(init_task);
 EXPORT_SYMBOL(init_task);
 
+#ifndef CONFIG_X86_NO_TSS
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's. The TSS size is kept cacheline-aligned
@@ -39,4 +40,4 @@
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */
 DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS;
-
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/pcspeaker.c
+++ linux-ec2-2.6.32/arch/x86/kernel/pcspeaker.c
@@ -6,6 +6,11 @@
 {
 	struct platform_device *pd;
 
+#ifdef CONFIG_XEN
+	if (!is_initial_xendomain())
+		return 0;
+#endif
+
 	pd = platform_device_register_simple("pcspkr", -1, NULL, 0);
 
 	return IS_ERR(pd) ? PTR_ERR(pd) : 0;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/ioport-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/ioport-xen.c
@@ -0,0 +1,112 @@
+/*
+ * This contains the io-permission bitmap code - written by obz, with changes
+ * by Linus. 32/64 bits code unification by Miguel Botón.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/slab.h>
+#include <linux/thread_info.h>
+#include <linux/syscalls.h>
+#include <asm/syscalls.h>
+#include <xen/interface/physdev.h>
+
+/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
+static void set_bitmap(unsigned long *bitmap, unsigned int base,
+		       unsigned int extent, int new_value)
+{
+	unsigned int i;
+
+	for (i = base; i < base + extent; i++) {
+		if (new_value)
+			__set_bit(i, bitmap);
+		else
+			__clear_bit(i, bitmap);
+	}
+}
+
+/*
+ * this changes the io permissions bitmap in the current task.
+ */
+asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+{
+	struct thread_struct *t = &current->thread;
+	struct physdev_set_iobitmap set_iobitmap;
+
+	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
+		return -EINVAL;
+	if (turn_on && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/*
+	 * If it's the first ioperm() call in this thread's lifetime, set the
+	 * IO bitmap up. ioperm() is much less timing critical than clone(),
+	 * this is why we delay this operation until now:
+	 */
+	if (!t->io_bitmap_ptr) {
+		unsigned long *bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+
+		if (!bitmap)
+			return -ENOMEM;
+
+		memset(bitmap, 0xff, IO_BITMAP_BYTES);
+		t->io_bitmap_ptr = bitmap;
+		set_thread_flag(TIF_IO_BITMAP);
+
+		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
+		set_iobitmap.nr_ports = IO_BITMAP_BITS;
+		WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap,
+					      &set_iobitmap));
+	}
+
+	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+
+	return 0;
+}
+
+/*
+ * sys_iopl has to be used when you want to access the IO ports
+ * beyond the 0x3ff range: to get the full 65536 ports bitmapped
+ * you'd need 8kB of bitmaps/process, which is a bit excessive.
+ */
+static int do_iopl(unsigned int level, struct thread_struct *t)
+{
+	unsigned int old = t->iopl >> 12;
+
+	if (level > 3)
+		return -EINVAL;
+	/* Trying to gain more privileges? */
+	if (level > old) {
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_32
+long sys_iopl(struct pt_regs *regs)
+{
+	unsigned int level = regs->bx;
+#else
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
+{
+#endif
+	struct thread_struct *t = &current->thread;
+	int rc;
+
+	rc = do_iopl(level, t);
+	if (rc < 0)
+		goto out;
+
+	t->iopl = level << 12;
+	set_iopl_mask(t->iopl);
+out:
+	return rc;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/early_printk-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/early_printk-xen.c
@@ -0,0 +1,271 @@
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/screen_info.h>
+#include <linux/usb/ch9.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fcntl.h>
+#include <asm/setup.h>
+#include <asm/pci-direct.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <linux/usb/ehci_def.h>
+
+#ifndef CONFIG_XEN
+/* Simple VGA output */
+#define VGABASE		(__ISA_IO_base + 0xb8000)
+
+static int max_ypos = 25, max_xpos = 80;
+static int current_ypos = 25, current_xpos;
+
+static void early_vga_write(struct console *con, const char *str, unsigned n)
+{
+	char c;
+	int  i, k, j;
+
+	while ((c = *str++) != '\0' && n-- > 0) {
+		if (current_ypos >= max_ypos) {
+			/* scroll 1 line up */
+			for (k = 1, j = 0; k < max_ypos; k++, j++) {
+				for (i = 0; i < max_xpos; i++) {
+					writew(readw(VGABASE+2*(max_xpos*k+i)),
+					       VGABASE + 2*(max_xpos*j + i));
+				}
+			}
+			for (i = 0; i < max_xpos; i++)
+				writew(0x720, VGABASE + 2*(max_xpos*j + i));
+			current_ypos = max_ypos-1;
+		}
+		if (c == '\n') {
+			current_xpos = 0;
+			current_ypos++;
+		} else if (c != '\r')  {
+			writew(((0x7 << 8) | (unsigned short) c),
+			       VGABASE + 2*(max_xpos*current_ypos +
+						current_xpos++));
+			if (current_xpos >= max_xpos) {
+				current_xpos = 0;
+				current_ypos++;
+			}
+		}
+	}
+}
+
+static struct console early_vga_console = {
+	.name =		"earlyvga",
+	.write =	early_vga_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/* Serial functions loosely based on a similar package from Klaus P. Gerlicher */
+
+static int early_serial_base = 0x3f8;  /* ttyS0 */
+
+#define XMTRDY          0x20
+
+#define DLAB		0x80
+
+#define TXR             0       /*  Transmit register (WRITE) */
+#define RXR             0       /*  Receive register  (READ)  */
+#define IER             1       /*  Interrupt Enable          */
+#define IIR             2       /*  Interrupt ID              */
+#define FCR             2       /*  FIFO control              */
+#define LCR             3       /*  Line control              */
+#define MCR             4       /*  Modem control             */
+#define LSR             5       /*  Line Status               */
+#define MSR             6       /*  Modem Status              */
+#define DLL             0       /*  Divisor Latch Low         */
+#define DLH             1       /*  Divisor latch High        */
+
+static int early_serial_putc(unsigned char ch)
+{
+	unsigned timeout = 0xffff;
+
+	while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
+		cpu_relax();
+	outb(ch, early_serial_base + TXR);
+	return timeout ? 0 : -1;
+}
+
+static void early_serial_write(struct console *con, const char *s, unsigned n)
+{
+	while (*s && n-- > 0) {
+		if (*s == '\n')
+			early_serial_putc('\r');
+		early_serial_putc(*s);
+		s++;
+	}
+}
+
+#define DEFAULT_BAUD 9600
+
+static __init void early_serial_init(char *s)
+{
+	unsigned char c;
+	unsigned divisor;
+	unsigned baud = DEFAULT_BAUD;
+	char *e;
+
+	if (*s == ',')
+		++s;
+
+	if (*s) {
+		unsigned port;
+		if (!strncmp(s, "0x", 2)) {
+			early_serial_base = simple_strtoul(s, &e, 16);
+		} else {
+			static const int __initconst bases[] = { 0x3f8, 0x2f8 };
+
+			if (!strncmp(s, "ttyS", 4))
+				s += 4;
+			port = simple_strtoul(s, &e, 10);
+			if (port > 1 || s == e)
+				port = 0;
+			early_serial_base = bases[port];
+		}
+		s += strcspn(s, ",");
+		if (*s == ',')
+			s++;
+	}
+
+	outb(0x3, early_serial_base + LCR);	/* 8n1 */
+	outb(0, early_serial_base + IER);	/* no interrupt */
+	outb(0, early_serial_base + FCR);	/* no fifo */
+	outb(0x3, early_serial_base + MCR);	/* DTR + RTS */
+
+	if (*s) {
+		baud = simple_strtoul(s, &e, 0);
+		if (baud == 0 || s == e)
+			baud = DEFAULT_BAUD;
+	}
+
+	divisor = 115200 / baud;
+	c = inb(early_serial_base + LCR);
+	outb(c | DLAB, early_serial_base + LCR);
+	outb(divisor & 0xff, early_serial_base + DLL);
+	outb((divisor >> 8) & 0xff, early_serial_base + DLH);
+	outb(c & ~DLAB, early_serial_base + LCR);
+}
+
+#else /* CONFIG_XEN */
+
+static void
+early_serial_write(struct console *con, const char *s, unsigned count)
+{
+	int n;
+
+	while (count > 0) {
+		n = HYPERVISOR_console_io(CONSOLEIO_write, count, (char *)s);
+		if (n <= 0)
+			break;
+		count -= n;
+		s += n;
+	}
+} 
+
+static __init void early_serial_init(char *s)
+{
+}
+
+/*
+ * No early VGA console on Xen, as we do not have convenient ISA-space
+ * mappings. Someone should fix this for domain 0. For now, use fake serial.
+ */
+#define early_vga_console early_serial_console
+
+#endif
+
+static struct console early_serial_console = {
+	.name =		"earlyser",
+	.write =	early_serial_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/* Direct interface for emergencies */
+static struct console *early_console = &early_vga_console;
+static int __initdata early_console_initialized;
+
+asmlinkage void early_printk(const char *fmt, ...)
+{
+	char buf[512];
+	int n;
+	va_list ap;
+
+	va_start(ap, fmt);
+	n = vscnprintf(buf, sizeof(buf), fmt, ap);
+	early_console->write(early_console, buf, n);
+	va_end(ap);
+}
+
+static inline void early_console_register(struct console *con, int keep_early)
+{
+	if (early_console->index != -1) {
+		printk(KERN_CRIT "ERROR: earlyprintk= %s already used\n",
+		       con->name);
+		return;
+	}
+	early_console = con;
+	if (keep_early)
+		early_console->flags &= ~CON_BOOT;
+	else
+		early_console->flags |= CON_BOOT;
+	register_console(early_console);
+}
+
+static int __init setup_early_printk(char *buf)
+{
+	int keep;
+
+	if (!buf)
+		return 0;
+
+	if (early_console_initialized)
+		return 0;
+	early_console_initialized = 1;
+
+	keep = (strstr(buf, "keep") != NULL);
+
+	while (*buf != '\0') {
+		if (!strncmp(buf, "serial", 6)) {
+			buf += 6;
+			early_serial_init(buf);
+			early_console_register(&early_serial_console, keep);
+			if (!strncmp(buf, ",ttyS", 5))
+				buf += 5;
+		}
+		if (!strncmp(buf, "ttyS", 4)) {
+			early_serial_init(buf + 4);
+			early_console_register(&early_serial_console, keep);
+		}
+#ifndef CONFIG_XEN
+		if (!strncmp(buf, "vga", 3) &&
+		    boot_params.screen_info.orig_video_isVGA == 1) {
+			max_xpos = boot_params.screen_info.orig_video_cols;
+			max_ypos = boot_params.screen_info.orig_video_lines;
+			current_ypos = boot_params.screen_info.orig_y;
+#else
+		if (!strncmp(buf, "vga", 3) || !strncmp(buf, "xen", 3)) {
+#endif
+			early_console_register(&early_vga_console, keep);
+		}
+#ifdef CONFIG_EARLY_PRINTK_DBGP
+		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
+			early_console_register(&early_dbgp_console, keep);
+#endif
+#ifdef CONFIG_HVC_XEN
+		if (!strncmp(buf, "xen", 3))
+			early_console_register(&xenboot_console, keep);
+#endif
+		buf++;
+	}
+	return 0;
+}
+
+early_param("earlyprintk", setup_early_printk);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/x86_init-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/x86_init-xen.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Thomas Gleixner <tglx@linutronix.de>
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+#include <linux/bitmap.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+
+#include <asm/mpspec.h>
+#include <asm/setup.h>
+#include <asm/apic.h>
+#include <asm/e820.h>
+#include <asm/time.h>
+#include <asm/irq.h>
+
+void __cpuinit x86_init_noop(void) { }
+void __init x86_init_uint_noop(unsigned int unused) { }
+void __init x86_init_pgd_noop(pgd_t *unused) { }
+
+/*
+ * The platform setup functions are preset with the default functions
+ * for standard PC hardware.
+ */
+struct x86_init_ops x86_init __initdata = {
+
+	.resources = {
+		.probe_roms		= x86_init_noop,
+		.reserve_resources	= reserve_standard_io_resources,
+		.memory_setup		= default_machine_specific_memory_setup,
+	},
+
+	.mpparse = {
+		.mpc_record		= x86_init_uint_noop,
+		.setup_ioapic_ids	= x86_init_noop,
+		.mpc_apic_id		= NULL,
+		.smp_read_mpc_oem	= default_smp_read_mpc_oem,
+		.mpc_oem_bus_info	= default_mpc_oem_bus_info,
+		.find_smp_config	= default_find_smp_config,
+		.get_smp_config		= default_get_smp_config,
+	},
+
+	.irqs = {
+		.pre_vector_init	= NULL,
+		.intr_init		= NULL,
+		.trap_init		= x86_init_noop,
+	},
+
+	.oem = {
+		.arch_setup		= xen_arch_setup,
+		.banner			= x86_init_noop,
+	},
+
+	.paging = {
+		.pagetable_setup_start	= x86_init_pgd_noop,
+		.pagetable_setup_done	= x86_init_pgd_noop,
+	},
+
+	.timers = {
+		.setup_percpu_clockev	= NULL,
+		.tsc_pre_init		= x86_init_noop,
+		.timer_init		= x86_init_noop,
+	},
+};
+
+struct x86_platform_ops x86_platform = {
+	.calibrate_tsc			= NULL,
+	.get_wallclock			= mach_get_cmos_time,
+	.set_wallclock			= mach_set_rtc_mmss,
+};
--- linux-ec2-2.6.32.orig/arch/x86/kernel/e820-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/e820-xen.c
@@ -0,0 +1,1649 @@
+/*
+ * Handle the memory map.
+ * The functions here do the job until bootmem takes over.
+ *
+ *  Getting sanitize_e820_map() in sync with i386 version by applying change:
+ *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
+ *     Alex Achenbach <xela@slit.de>, December 2002.
+ *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pfn.h>
+#include <linux/suspend.h>
+#include <linux/firmware-map.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/e820.h>
+#include <asm/proto.h>
+#include <asm/setup.h>
+#include <xen/interface/memory.h>
+
+/*
+ * The e820 map is the map that gets modified e.g. with command line parameters
+ * and that is also registered with modifications in the kernel resource tree
+ * with the iomem_resource as parent.
+ *
+ * The e820_saved is directly saved after the BIOS-provided memory map is
+ * copied. It doesn't get modified afterwards. It's registered for the
+ * /sys/firmware/memmap interface.
+ *
+ * That memory map is not modified and is used as base for kexec. The kexec'd
+ * kernel should get the same memory map as the firmware provides. Then the
+ * user can e.g. boot the original kernel with mem=1G while still booting the
+ * next kernel with full memory.
+ */
+struct e820map e820;
+#ifndef CONFIG_XEN
+struct e820map e820_saved;
+#else
+static struct e820map machine_e820;
+#define e820_saved machine_e820
+#endif
+
+/* For PCI or other memory-mapped resources */
+unsigned long pci_mem_start = 0xaeedbabe;
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_mem_start);
+#endif
+
+/*
+ * 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;
+
+#ifndef CONFIG_XEN
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+#else
+	if (!is_initial_xendomain())
+		return 0;
+	for (i = 0; i < machine_e820.nr_map; ++i) {
+		const struct e820entry *ei = &machine_e820.map[i];
+#endif
+
+		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.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init e820_all_mapped(u64 start, u64 end, unsigned type)
+{
+	int i;
+
+#ifndef CONFIG_XEN
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+#else
+	if (!is_initial_xendomain())
+		return 0;
+	for (i = 0; i < machine_e820.nr_map; ++i) {
+		const struct e820entry *ei = &machine_e820.map[i];
+#endif
+
+		if (type && ei->type != type)
+			continue;
+		/* is the region (part) in overlap with the current region ?*/
+		if (ei->addr >= end || ei->addr + ei->size <= start)
+			continue;
+
+		/* if the region is at the beginning of <start,end> we move
+		 * start to the end of the region since it's ok until there
+		 */
+		if (ei->addr <= start)
+			start = ei->addr + ei->size;
+		/*
+		 * if start is now at or beyond end, we're done, full
+		 * coverage
+		 */
+		if (start >= end)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Add a memory region to the kernel e820 map.
+ */
+static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
+					 int type)
+{
+	int x = e820x->nr_map;
+
+	if (x >= ARRAY_SIZE(e820x->map)) {
+		printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+		return;
+	}
+
+	e820x->map[x].addr = start;
+	e820x->map[x].size = size;
+	e820x->map[x].type = type;
+	e820x->nr_map++;
+}
+
+void __init e820_add_region(u64 start, u64 size, int type)
+{
+	__e820_add_region(&e820, start, size, type);
+}
+
+static void __init e820_print_type(u32 type)
+{
+	switch (type) {
+	case E820_RAM:
+	case E820_RESERVED_KERN:
+		printk(KERN_CONT "(usable)");
+		break;
+	case E820_RESERVED:
+		printk(KERN_CONT "(reserved)");
+		break;
+	case E820_ACPI:
+		printk(KERN_CONT "(ACPI data)");
+		break;
+	case E820_NVS:
+		printk(KERN_CONT "(ACPI NVS)");
+		break;
+	case E820_UNUSABLE:
+		printk(KERN_CONT "(unusable)");
+		break;
+	default:
+		printk(KERN_CONT "type %u", type);
+		break;
+	}
+}
+
+static void __init _e820_print_map(const struct e820map *e820, const char *who)
+{
+	int i;
+
+	for (i = 0; i < e820->nr_map; i++) {
+		printk(KERN_INFO " %s: %016Lx - %016Lx ", who,
+		       (unsigned long long) e820->map[i].addr,
+		       (unsigned long long)
+		       (e820->map[i].addr + e820->map[i].size));
+		e820_print_type(e820->map[i].type);
+		printk(KERN_CONT "\n");
+	}
+}
+
+/*
+ * Sanitize the BIOS e820 map.
+ *
+ * Some e820 responses include overlapping entries. The following
+ * replaces the original e820 map with a new one, removing overlaps,
+ * and resolving conflicting memory types in favor of highest
+ * numbered type.
+ *
+ * The input parameter biosmap points to an array of 'struct
+ * e820entry' which on entry has elements in the range [0, *pnr_map)
+ * valid, and which has space for up to max_nr_map entries.
+ * On return, the resulting sanitized e820 map entries will be in
+ * overwritten in the same location, starting at biosmap.
+ *
+ * The integer pointed to by pnr_map must be valid on entry (the
+ * current number of valid entries located at biosmap) and will
+ * be updated on return, with the new number of valid entries
+ * (something no more than max_nr_map.)
+ *
+ * The return value from sanitize_e820_map() is zero if it
+ * successfully 'sanitized' the map entries passed in, and is -1
+ * if it did nothing, which can happen if either of (1) it was
+ * only passed one map entry, or (2) any of the input map entries
+ * were invalid (start + size < start, meaning that the size was
+ * so big the described memory range wrapped around through zero.)
+ *
+ *	Visually we're performing the following
+ *	(1,2,3,4 = memory types)...
+ *
+ *	Sample memory map (w/overlaps):
+ *	   ____22__________________
+ *	   ______________________4_
+ *	   ____1111________________
+ *	   _44_____________________
+ *	   11111111________________
+ *	   ____________________33__
+ *	   ___________44___________
+ *	   __________33333_________
+ *	   ______________22________
+ *	   ___________________2222_
+ *	   _________111111111______
+ *	   _____________________11_
+ *	   _________________4______
+ *
+ *	Sanitized equivalent (no overlap):
+ *	   1_______________________
+ *	   _44_____________________
+ *	   ___1____________________
+ *	   ____22__________________
+ *	   ______11________________
+ *	   _________1______________
+ *	   __________3_____________
+ *	   ___________44___________
+ *	   _____________33_________
+ *	   _______________2________
+ *	   ________________1_______
+ *	   _________________4______
+ *	   ___________________2____
+ *	   ____________________33__
+ *	   ______________________4_
+ */
+
+int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
+			     u32 *pnr_map)
+{
+	struct change_member {
+		struct e820entry *pbios; /* pointer to original bios entry */
+		unsigned long long addr; /* address for this change point */
+	};
+	static struct change_member change_point_list[2*E820_X_MAX] __initdata;
+	static struct change_member *change_point[2*E820_X_MAX] __initdata;
+	static struct e820entry *overlap_list[E820_X_MAX] __initdata;
+	static struct e820entry new_bios[E820_X_MAX] __initdata;
+	struct change_member *change_tmp;
+	unsigned long current_type, last_type;
+	unsigned long long last_addr;
+	int chgidx, still_changing;
+	int overlap_entries;
+	int new_bios_entry;
+	int old_nr, new_nr, chg_nr;
+	int i;
+
+	/* if there's only one memory region, don't bother */
+#ifdef CONFIG_XEN
+	if (*pnr_map == 1)
+		return 0;
+#endif
+	if (*pnr_map < 2)
+		return -1;
+
+	old_nr = *pnr_map;
+	BUG_ON(old_nr > max_nr_map);
+
+	/* bail out if we find any unreasonable addresses in bios map */
+	for (i = 0; i < old_nr; i++)
+		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
+			return -1;
+
+	/* create pointers for initial change-point information (for sorting) */
+	for (i = 0; i < 2 * old_nr; i++)
+		change_point[i] = &change_point_list[i];
+
+	/* record all known change-points (starting and ending addresses),
+	   omitting those that are for empty memory regions */
+	chgidx = 0;
+	for (i = 0; i < old_nr; i++)	{
+		if (biosmap[i].size != 0) {
+			change_point[chgidx]->addr = biosmap[i].addr;
+			change_point[chgidx++]->pbios = &biosmap[i];
+			change_point[chgidx]->addr = biosmap[i].addr +
+				biosmap[i].size;
+			change_point[chgidx++]->pbios = &biosmap[i];
+		}
+	}
+	chg_nr = chgidx;
+
+	/* sort change-point list by memory addresses (low -> high) */
+	still_changing = 1;
+	while (still_changing)	{
+		still_changing = 0;
+		for (i = 1; i < chg_nr; i++)  {
+			unsigned long long curaddr, lastaddr;
+			unsigned long long curpbaddr, lastpbaddr;
+
+			curaddr = change_point[i]->addr;
+			lastaddr = change_point[i - 1]->addr;
+			curpbaddr = change_point[i]->pbios->addr;
+			lastpbaddr = change_point[i - 1]->pbios->addr;
+
+			/*
+			 * swap entries, when:
+			 *
+			 * curaddr > lastaddr or
+			 * curaddr == lastaddr and curaddr == curpbaddr and
+			 * lastaddr != lastpbaddr
+			 */
+			if (curaddr < lastaddr ||
+			    (curaddr == lastaddr && curaddr == curpbaddr &&
+			     lastaddr != lastpbaddr)) {
+				change_tmp = change_point[i];
+				change_point[i] = change_point[i-1];
+				change_point[i-1] = change_tmp;
+				still_changing = 1;
+			}
+		}
+	}
+
+	/* create a new bios memory map, removing overlaps */
+	overlap_entries = 0;	 /* number of entries in the overlap table */
+	new_bios_entry = 0;	 /* index for creating new bios map entries */
+	last_type = 0;		 /* start with undefined memory type */
+	last_addr = 0;		 /* start with 0 as last starting address */
+
+	/* loop through change-points, determining affect on the new bios map */
+	for (chgidx = 0; chgidx < chg_nr; chgidx++) {
+		/* keep track of all overlapping bios entries */
+		if (change_point[chgidx]->addr ==
+		    change_point[chgidx]->pbios->addr) {
+			/*
+			 * add map entry to overlap list (> 1 entry
+			 * implies an overlap)
+			 */
+			overlap_list[overlap_entries++] =
+				change_point[chgidx]->pbios;
+		} else {
+			/*
+			 * remove entry from list (order independent,
+			 * so swap with last)
+			 */
+			for (i = 0; i < overlap_entries; i++) {
+				if (overlap_list[i] ==
+				    change_point[chgidx]->pbios)
+					overlap_list[i] =
+						overlap_list[overlap_entries-1];
+			}
+			overlap_entries--;
+		}
+		/*
+		 * if there are overlapping entries, decide which
+		 * "type" to use (larger value takes precedence --
+		 * 1=usable, 2,3,4,4+=unusable)
+		 */
+		current_type = 0;
+		for (i = 0; i < overlap_entries; i++)
+			if (overlap_list[i]->type > current_type)
+				current_type = overlap_list[i]->type;
+		/*
+		 * continue building up new bios map based on this
+		 * information
+		 */
+		if (current_type != last_type)	{
+			if (last_type != 0)	 {
+				new_bios[new_bios_entry].size =
+					change_point[chgidx]->addr - last_addr;
+				/*
+				 * move forward only if the new size
+				 * was non-zero
+				 */
+				if (new_bios[new_bios_entry].size != 0)
+					/*
+					 * no more space left for new
+					 * bios entries ?
+					 */
+					if (++new_bios_entry >= max_nr_map)
+						break;
+			}
+			if (current_type != 0)	{
+				new_bios[new_bios_entry].addr =
+					change_point[chgidx]->addr;
+				new_bios[new_bios_entry].type = current_type;
+				last_addr = change_point[chgidx]->addr;
+			}
+			last_type = current_type;
+		}
+	}
+	/* retain count for new bios entries */
+	new_nr = new_bios_entry;
+
+	/* copy new bios mapping into original location */
+	memcpy(biosmap, new_bios, new_nr * sizeof(struct e820entry));
+	*pnr_map = new_nr;
+
+	return 0;
+}
+
+static int __init __append_e820_map(struct e820entry *biosmap, int nr_map)
+{
+	while (nr_map) {
+		u64 start = biosmap->addr;
+		u64 size = biosmap->size;
+		u64 end = start + size;
+		u32 type = biosmap->type;
+
+		/* Overflow in 64 bits? Ignore the memory map. */
+		if (start > end)
+			return -1;
+
+		e820_add_region(start, size, type);
+
+		biosmap++;
+		nr_map--;
+	}
+	return 0;
+}
+
+/*
+ * Copy the BIOS e820 map into a safe place.
+ *
+ * Sanity-check it while we're at it..
+ *
+ * If we're lucky and live on a modern system, the setup code
+ * will have given us a memory map that we can use to properly
+ * set up memory.  If we aren't, we'll fake a memory map.
+ */
+static int __init append_e820_map(struct e820entry *biosmap, int nr_map)
+{
+#ifndef CONFIG_XEN
+	/* Only one memory region (or negative)? Ignore it */
+	if (nr_map < 2)
+		return -1;
+#else
+	BUG_ON(nr_map < 1);
+#endif
+
+	return __append_e820_map(biosmap, nr_map);
+}
+
+static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
+					u64 size, unsigned old_type,
+					unsigned new_type)
+{
+	u64 end;
+	unsigned int i;
+	u64 real_updated_size = 0;
+
+	BUG_ON(old_type == new_type);
+
+	if (size > (ULLONG_MAX - start))
+		size = ULLONG_MAX - start;
+
+	end = start + size;
+	printk(KERN_DEBUG "e820 update range: %016Lx - %016Lx ",
+		       (unsigned long long) start,
+		       (unsigned long long) end);
+	e820_print_type(old_type);
+	printk(KERN_CONT " ==> ");
+	e820_print_type(new_type);
+	printk(KERN_CONT "\n");
+
+	for (i = 0; i < e820x->nr_map; i++) {
+		struct e820entry *ei = &e820x->map[i];
+		u64 final_start, final_end;
+		u64 ei_end;
+
+		if (ei->type != old_type)
+			continue;
+
+		ei_end = ei->addr + ei->size;
+		/* totally covered by new range? */
+		if (ei->addr >= start && ei_end <= end) {
+			ei->type = new_type;
+			real_updated_size += ei->size;
+			continue;
+		}
+
+		/* new range is totally covered? */
+		if (ei->addr < start && ei_end > end) {
+			__e820_add_region(e820x, start, size, new_type);
+			__e820_add_region(e820x, end, ei_end - end, ei->type);
+			ei->size = start - ei->addr;
+			real_updated_size += size;
+			continue;
+		}
+
+		/* partially covered */
+		final_start = max(start, ei->addr);
+		final_end = min(end, ei_end);
+		if (final_start >= final_end)
+			continue;
+
+		__e820_add_region(e820x, final_start, final_end - final_start,
+				  new_type);
+
+		real_updated_size += final_end - final_start;
+
+		/*
+		 * left range could be head or tail, so need to update
+		 * size at first.
+		 */
+		ei->size -= final_end - final_start;
+		if (ei->addr < final_start)
+			continue;
+		ei->addr = final_end;
+	}
+	return real_updated_size;
+}
+
+u64 __init e820_update_range(u64 start, u64 size, unsigned old_type,
+			     unsigned new_type)
+{
+	return __e820_update_range(&e820, start, size, old_type, new_type);
+}
+
+static u64 __init e820_update_range_saved(u64 start, u64 size,
+					  unsigned old_type, unsigned new_type)
+{
+#ifdef CONFIG_XEN
+	if (is_initial_xendomain())
+		return __e820_update_range(&machine_e820,
+					   phys_to_machine(start), size,
+					   old_type, new_type);
+#endif
+	return __e820_update_range(&e820_saved, start, size, old_type,
+				     new_type);
+}
+
+/* make e820 not cover the range */
+u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
+			     int checktype)
+{
+	int i;
+	u64 real_removed_size = 0;
+
+	if (size > (ULLONG_MAX - start))
+		size = ULLONG_MAX - start;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		u64 final_start, final_end;
+
+		if (checktype && ei->type != old_type)
+			continue;
+		/* totally covered? */
+		if (ei->addr >= start &&
+		    (ei->addr + ei->size) <= (start + size)) {
+			real_removed_size += ei->size;
+			memset(ei, 0, sizeof(struct e820entry));
+			continue;
+		}
+		/* partially covered */
+		final_start = max(start, ei->addr);
+		final_end = min(start + size, ei->addr + ei->size);
+		if (final_start >= final_end)
+			continue;
+		real_removed_size += final_end - final_start;
+
+		ei->size -= final_end - final_start;
+		if (ei->addr < final_start)
+			continue;
+		ei->addr = final_end;
+	}
+	return real_removed_size;
+}
+
+void __init update_e820(void)
+{
+	u32 nr_map;
+
+	nr_map = e820.nr_map;
+	if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
+		return;
+	e820.nr_map = nr_map;
+	printk(KERN_INFO "modified physical RAM map:\n");
+	_e820_print_map(&e820, "modified");
+}
+static void __init update_e820_saved(void)
+{
+	u32 nr_map;
+
+	nr_map = e820_saved.nr_map;
+	if (sanitize_e820_map(e820_saved.map, ARRAY_SIZE(e820_saved.map), &nr_map))
+		return;
+	e820_saved.nr_map = nr_map;
+}
+
+#ifdef CONFIG_XEN
+#define e820 machine_e820
+#endif
+
+#define MAX_GAP_END 0x100000000ull
+/*
+ * Search for a gap in the e820 memory space from start_addr to end_addr.
+ */
+__init int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
+		unsigned long start_addr, unsigned long long end_addr)
+{
+	unsigned long long last;
+	int i = e820.nr_map;
+	int found = 0;
+
+	last = (end_addr && end_addr < MAX_GAP_END) ? end_addr : MAX_GAP_END;
+#ifdef CONFIG_X86_64
+	if (start_addr >= MAX_GAP_END)
+		last = end_addr ?: (1UL << boot_cpu_data.x86_phys_bits);
+#endif
+
+	while (--i >= 0) {
+		unsigned long long start = e820.map[i].addr;
+		unsigned long long end = start + e820.map[i].size;
+
+		if (end < start_addr)
+			continue;
+
+		/*
+		 * Since "last" is at most 4GB, we know we'll
+		 * fit in 32 bits if this condition is true
+		 */
+		if (last > end) {
+			unsigned long gap = last - end;
+
+			if (gap >= *gapsize) {
+				*gapsize = gap;
+				*gapstart = end;
+				found = 1;
+			}
+		}
+		if (start < last)
+			last = start;
+	}
+	return found;
+}
+
+/*
+ * Search for the biggest gap in the low 32 bits of the e820
+ * memory space.  We pass this space to PCI to assign MMIO resources
+ * for hotplug or unconfigured devices in.
+ * Hopefully the BIOS let enough space left.
+ */
+__init void e820_setup_gap(void)
+{
+	unsigned long gapstart, gapsize;
+	int found;
+
+	gapstart = 0x10000000;
+	gapsize = 0x400000;
+	found  = e820_search_gap(&gapstart, &gapsize, 0, MAX_GAP_END);
+
+#ifdef CONFIG_X86_64
+	if (!found) {
+		printk(KERN_ERR
+	"PCI: Warning: Cannot find a gap in the 32bit address range\n"
+	"PCI: Unassigned devices with 32bit resource registers may break!\n");
+		found = e820_search_gap(&gapstart, &gapsize, MAX_GAP_END, 0);
+		WARN_ON(!found);
+	}
+#endif
+
+	/*
+	 * e820_reserve_resources_late protect stolen RAM already
+	 */
+	pci_mem_start = gapstart;
+
+	printk(KERN_INFO
+	       "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
+	       pci_mem_start, gapstart, gapsize);
+}
+
+#undef e820
+
+#ifndef CONFIG_XEN
+/**
+ * Because of the size limitation of struct boot_params, only first
+ * 128 E820 memory entries are passed to kernel via
+ * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
+ * linked list of struct setup_data, which is parsed here.
+ */
+void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+{
+	u32 map_len;
+	int entries;
+	struct e820entry *extmap;
+
+	entries = sdata->len / sizeof(struct e820entry);
+	map_len = sdata->len + sizeof(struct setup_data);
+	if (map_len > PAGE_SIZE)
+		sdata = early_ioremap(pa_data, map_len);
+	extmap = (struct e820entry *)(sdata->data);
+	__append_e820_map(extmap, entries);
+	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
+	if (map_len > PAGE_SIZE)
+		early_iounmap(sdata, map_len);
+	printk(KERN_INFO "extended physical RAM map:\n");
+	_e820_print_map(&e820, "extended");
+}
+
+#if defined(CONFIG_X86_64) || \
+	(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
+/**
+ * Find the ranges of physical addresses that do not correspond to
+ * e820 RAM areas and mark the corresponding pages as nosave for
+ * hibernation (32 bit) or software suspend and suspend to RAM (64 bit).
+ *
+ * This function requires the e820 map to be sorted and without any
+ * overlapping entries and assumes the first e820 area to be RAM.
+ */
+void __init e820_mark_nosave_regions(unsigned long limit_pfn)
+{
+	int i;
+	unsigned long pfn;
+
+	pfn = PFN_DOWN(e820.map[0].addr + e820.map[0].size);
+	for (i = 1; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		if (pfn < PFN_UP(ei->addr))
+			register_nosave_region(pfn, PFN_UP(ei->addr));
+
+		pfn = PFN_DOWN(ei->addr + ei->size);
+		if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
+			register_nosave_region(PFN_UP(ei->addr), pfn);
+
+		if (pfn >= limit_pfn)
+			break;
+	}
+}
+#endif
+
+#ifdef CONFIG_HIBERNATION
+/**
+ * Mark ACPI NVS memory region, so that we can save/restore it during
+ * hibernation and the subsequent resume.
+ */
+static int __init e820_mark_nvs_memory(void)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		if (ei->type == E820_NVS)
+			hibernate_nvs_register(ei->addr, ei->size);
+	}
+
+	return 0;
+}
+core_initcall(e820_mark_nvs_memory);
+#endif
+#endif
+
+/*
+ * Early reserved memory areas.
+ */
+#define MAX_EARLY_RES 20
+
+struct early_res {
+	u64 start, end;
+	char name[16];
+	char overlap_ok;
+};
+static struct early_res early_res[MAX_EARLY_RES] __initdata = {
+#ifndef CONFIG_XEN
+	{ 0, PAGE_SIZE, "BIOS data page" },	/* BIOS data page */
+#endif
+	{}
+};
+
+static int __init find_overlapped_early(u64 start, u64 end)
+{
+	int i;
+	struct early_res *r;
+
+	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+		r = &early_res[i];
+		if (end > r->start && start < r->end)
+			break;
+	}
+
+	return i;
+}
+
+/*
+ * Drop the i-th range from the early reservation map,
+ * by copying any higher ranges down one over it, and
+ * clearing what had been the last slot.
+ */
+static void __init drop_range(int i)
+{
+	int j;
+
+	for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
+		;
+
+	memmove(&early_res[i], &early_res[i + 1],
+	       (j - 1 - i) * sizeof(struct early_res));
+
+	early_res[j - 1].end = 0;
+}
+
+/*
+ * Split any existing ranges that:
+ *  1) are marked 'overlap_ok', and
+ *  2) overlap with the stated range [start, end)
+ * into whatever portion (if any) of the existing range is entirely
+ * below or entirely above the stated range.  Drop the portion
+ * of the existing range that overlaps with the stated range,
+ * which will allow the caller of this routine to then add that
+ * stated range without conflicting with any existing range.
+ */
+static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
+{
+	int i;
+	struct early_res *r;
+	u64 lower_start, lower_end;
+	u64 upper_start, upper_end;
+	char name[16];
+
+	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+		r = &early_res[i];
+
+		/* Continue past non-overlapping ranges */
+		if (end <= r->start || start >= r->end)
+			continue;
+
+		/*
+		 * Leave non-ok overlaps as is; let caller
+		 * panic "Overlapping early reservations"
+		 * when it hits this overlap.
+		 */
+		if (!r->overlap_ok)
+			return;
+
+		/*
+		 * We have an ok overlap.  We will drop it from the early
+		 * reservation map, and add back in any non-overlapping
+		 * portions (lower or upper) as separate, overlap_ok,
+		 * non-overlapping ranges.
+		 */
+
+		/* 1. Note any non-overlapping (lower or upper) ranges. */
+		strncpy(name, r->name, sizeof(name) - 1);
+
+		lower_start = lower_end = 0;
+		upper_start = upper_end = 0;
+		if (r->start < start) {
+		 	lower_start = r->start;
+			lower_end = start;
+		}
+		if (r->end > end) {
+			upper_start = end;
+			upper_end = r->end;
+		}
+
+		/* 2. Drop the original ok overlapping range */
+		drop_range(i);
+
+		i--;		/* resume for-loop on copied down entry */
+
+		/* 3. Add back in any non-overlapping ranges. */
+		if (lower_end)
+			reserve_early_overlap_ok(lower_start, lower_end, name);
+		if (upper_end)
+			reserve_early_overlap_ok(upper_start, upper_end, name);
+	}
+}
+
+static void __init __reserve_early(u64 start, u64 end, char *name,
+						int overlap_ok)
+{
+	int i;
+	struct early_res *r;
+
+	i = find_overlapped_early(start, end);
+	if (i >= MAX_EARLY_RES)
+		panic("Too many early reservations");
+	r = &early_res[i];
+	if (r->end)
+		panic("Overlapping early reservations "
+		      "%llx-%llx %s to %llx-%llx %s\n",
+		      start, end - 1, name?name:"", r->start,
+		      r->end - 1, r->name);
+	r->start = start;
+	r->end = end;
+	r->overlap_ok = overlap_ok;
+	if (name)
+		strncpy(r->name, name, sizeof(r->name) - 1);
+}
+
+/*
+ * A few early reservtations come here.
+ *
+ * The 'overlap_ok' in the name of this routine does -not- mean it
+ * is ok for these reservations to overlap an earlier reservation.
+ * Rather it means that it is ok for subsequent reservations to
+ * overlap this one.
+ *
+ * Use this entry point to reserve early ranges when you are doing
+ * so out of "Paranoia", reserving perhaps more memory than you need,
+ * just in case, and don't mind a subsequent overlapping reservation
+ * that is known to be needed.
+ *
+ * The drop_overlaps_that_are_ok() call here isn't really needed.
+ * It would be needed if we had two colliding 'overlap_ok'
+ * reservations, so that the second such would not panic on the
+ * overlap with the first.  We don't have any such as of this
+ * writing, but might as well tolerate such if it happens in
+ * the future.
+ */
+void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
+{
+	drop_overlaps_that_are_ok(start, end);
+	__reserve_early(start, end, name, 1);
+}
+
+/*
+ * Most early reservations come here.
+ *
+ * We first have drop_overlaps_that_are_ok() drop any pre-existing
+ * 'overlap_ok' ranges, so that we can then reserve this memory
+ * range without risk of panic'ing on an overlapping overlap_ok
+ * early reservation.
+ */
+void __init reserve_early(u64 start, u64 end, char *name)
+{
+	if (start >= end)
+		return;
+
+	drop_overlaps_that_are_ok(start, end);
+	__reserve_early(start, end, name, 0);
+}
+
+void __init free_early(u64 start, u64 end)
+{
+	struct early_res *r;
+	int i;
+
+	i = find_overlapped_early(start, end);
+	r = &early_res[i];
+	if (i >= MAX_EARLY_RES || r->end != end || r->start != start)
+		panic("free_early on not reserved area: %llx-%llx!",
+			 start, end - 1);
+
+	drop_range(i);
+}
+
+void __init early_res_to_bootmem(u64 start, u64 end)
+{
+	int i, count;
+	u64 final_start, final_end;
+
+	count  = 0;
+	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++)
+		count++;
+
+	printk(KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n",
+			 count, start, end);
+	for (i = 0; i < count; i++) {
+		struct early_res *r = &early_res[i];
+		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
+			r->start, r->end, r->name);
+		final_start = max(start, r->start);
+		final_end = min(end, r->end);
+		if (final_start >= final_end) {
+			printk(KERN_CONT "\n");
+			continue;
+		}
+		printk(KERN_CONT " ==> [%010llx - %010llx]\n",
+			final_start, final_end);
+		reserve_bootmem_generic(final_start, final_end - final_start,
+				BOOTMEM_DEFAULT);
+	}
+}
+
+/* Check for already reserved areas */
+static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
+{
+	int i;
+	u64 addr = *addrp;
+	int changed = 0;
+	struct early_res *r;
+again:
+	i = find_overlapped_early(addr, addr + size);
+	r = &early_res[i];
+	if (i < MAX_EARLY_RES && r->end) {
+		*addrp = addr = round_up(r->end, align);
+		changed = 1;
+		goto again;
+	}
+	return changed;
+}
+
+/* Check for already reserved areas */
+static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
+{
+	int i;
+	u64 addr = *addrp, last;
+	u64 size = *sizep;
+	int changed = 0;
+again:
+	last = addr + size;
+	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
+		struct early_res *r = &early_res[i];
+		if (last > r->start && addr < r->start) {
+			size = r->start - addr;
+			changed = 1;
+			goto again;
+		}
+		if (last > r->end && addr < r->end) {
+			addr = round_up(r->end, align);
+			size = last - addr;
+			changed = 1;
+			goto again;
+		}
+		if (last <= r->end && addr >= r->start) {
+			(*sizep)++;
+			return 0;
+		}
+	}
+	if (changed) {
+		*addrp = addr;
+		*sizep = size;
+	}
+	return changed;
+}
+
+/*
+ * Find a free area with specified alignment in a specific range.
+ */
+u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		u64 addr, last;
+		u64 ei_last;
+
+		if (ei->type != E820_RAM)
+			continue;
+		addr = round_up(ei->addr, align);
+		ei_last = ei->addr + ei->size;
+		if (addr < start)
+			addr = round_up(start, align);
+		if (addr >= ei_last)
+			continue;
+		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+			;
+		last = addr + size;
+		if (last > ei_last)
+			continue;
+		if (last > end)
+			continue;
+		return addr;
+	}
+	return -1ULL;
+}
+
+/*
+ * Find next free range after *start
+ */
+u64 __init find_e820_area_size(u64 start, u64 *sizep, u64 align)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		u64 addr, last;
+		u64 ei_last;
+
+		if (ei->type != E820_RAM)
+			continue;
+		addr = round_up(ei->addr, align);
+		ei_last = ei->addr + ei->size;
+		if (addr < start)
+			addr = round_up(start, align);
+		if (addr >= ei_last)
+			continue;
+		*sizep = ei_last - addr;
+		while (bad_addr_size(&addr, sizep, align) &&
+			addr + *sizep <= ei_last)
+			;
+		last = addr + *sizep;
+		if (last > ei_last)
+			continue;
+		return addr;
+	}
+
+	return -1ULL;
+}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+{
+	u64 size = 0;
+	u64 addr;
+	u64 start;
+#ifdef CONFIG_XEN
+	unsigned int order = get_order(sizet);
+
+	if (is_initial_xendomain()) {
+		sizet = PAGE_SIZE << order;
+		if (align < PAGE_SIZE)
+			align = PAGE_SIZE;
+	}
+#endif
+	for (start = startt; ; start += size) {
+		start = find_e820_area_size(start, &size, align);
+		if (!(start + 1))
+			return 0;
+		if (size >= sizet)
+			break;
+	}
+
+#ifdef CONFIG_X86_32
+	if (start >= MAXMEM)
+		return 0;
+	if (start + size > MAXMEM)
+		size = MAXMEM - start;
+#endif
+#ifdef CONFIG_XEN
+	if ((start >> PAGE_SHIFT) >= xen_start_info->nr_pages)
+		return 0;
+	if (PFN_UP(start + size) > xen_start_info->nr_pages)
+		size = ((u64)xen_start_info->nr_pages << PAGE_SHIFT) - start;
+#endif
+
+	addr = round_down(start + size - sizet, align);
+	if (addr < start)
+		return 0;
+#ifdef CONFIG_XEN
+	if (is_initial_xendomain()) {
+		int rc;
+		unsigned long max_initmap_pfn;
+
+		max_initmap_pfn = ALIGN(PFN_UP(__pa(xen_start_info->pt_base))
+					       + xen_start_info->nr_pt_frames
+					       + 1 + (1 << (19 - PAGE_SHIFT)),
+					1UL << (22 - PAGE_SHIFT));
+#ifdef CONFIG_X86_32
+		if ((addr >> PAGE_SHIFT)
+		    < max(max_initmap_pfn, max_pfn_mapped))
+			rc = xen_create_contiguous_region((unsigned long)
+							  __va(addr),
+							  order, 32);
+#else
+		if ((addr >> PAGE_SHIFT) < max_pfn_mapped)
+			rc = xen_create_contiguous_region((unsigned long)
+							  __va(addr),
+							  order, 32);
+		else if ((addr >> PAGE_SHIFT) < max_initmap_pfn)
+			rc = xen_create_contiguous_region(__START_KERNEL_map
+							  + addr,
+							  order, 32);
+#endif
+		else
+			rc = early_create_contiguous_region(addr >> PAGE_SHIFT,
+							    order, 32);
+		if (rc)
+			return 0;
+	}
+#endif
+	e820_update_range(addr, sizet, E820_RAM, E820_RESERVED);
+	e820_update_range_saved(addr, sizet, E820_RAM, E820_RESERVED);
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+	update_e820_saved();
+
+	return addr;
+}
+
+#ifdef CONFIG_X86_32
+# ifdef CONFIG_X86_PAE
+#  define MAX_ARCH_PFN		(1ULL<<(40-PAGE_SHIFT))
+# else
+#  define MAX_ARCH_PFN		(1ULL<<(32-PAGE_SHIFT))
+# endif
+#else /* CONFIG_X86_32 */
+# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT
+#endif
+
+/*
+ * Find the highest page frame number we have available
+ */
+static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
+{
+	int i;
+	unsigned long last_pfn = 0;
+	unsigned long max_arch_pfn = MAX_ARCH_PFN;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long start_pfn;
+		unsigned long end_pfn;
+
+		if (ei->type != type)
+			continue;
+
+		start_pfn = ei->addr >> PAGE_SHIFT;
+		end_pfn = (ei->addr + ei->size) >> PAGE_SHIFT;
+
+		if (start_pfn >= limit_pfn)
+			continue;
+		if (end_pfn > limit_pfn) {
+			last_pfn = limit_pfn;
+			break;
+		}
+		if (end_pfn > last_pfn)
+			last_pfn = end_pfn;
+	}
+
+	if (last_pfn > max_arch_pfn)
+		last_pfn = max_arch_pfn;
+
+	printk(KERN_INFO "last_pfn = %#lx max_arch_pfn = %#lx\n",
+			 last_pfn, max_arch_pfn);
+	return last_pfn;
+}
+unsigned long __init e820_end_of_ram_pfn(void)
+{
+	return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
+}
+
+unsigned long __init e820_end_of_low_ram_pfn(void)
+{
+	return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
+}
+/*
+ * Finds an active region in the address range from start_pfn to last_pfn and
+ * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
+ */
+int __init e820_find_active_region(const struct e820entry *ei,
+				  unsigned long start_pfn,
+				  unsigned long last_pfn,
+				  unsigned long *ei_startpfn,
+				  unsigned long *ei_endpfn)
+{
+	u64 align = PAGE_SIZE;
+
+#ifdef CONFIG_XEN
+	if (last_pfn > xen_start_info->nr_pages)
+		last_pfn = xen_start_info->nr_pages;
+#endif
+
+	*ei_startpfn = round_up(ei->addr, align) >> PAGE_SHIFT;
+	*ei_endpfn = round_down(ei->addr + ei->size, align) >> PAGE_SHIFT;
+
+	/* Skip map entries smaller than a page */
+	if (*ei_startpfn >= *ei_endpfn)
+		return 0;
+
+	/* Skip if map is outside the node */
+	if (ei->type != E820_RAM || *ei_endpfn <= start_pfn ||
+				    *ei_startpfn >= last_pfn)
+		return 0;
+
+	/* Check for overlaps */
+	if (*ei_startpfn < start_pfn)
+		*ei_startpfn = start_pfn;
+	if (*ei_endpfn > last_pfn)
+		*ei_endpfn = last_pfn;
+
+	return 1;
+}
+
+/* Walk the e820 map and register active regions within a node */
+void __init e820_register_active_regions(int nid, unsigned long start_pfn,
+					 unsigned long last_pfn)
+{
+	unsigned long ei_startpfn;
+	unsigned long ei_endpfn;
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++)
+		if (e820_find_active_region(&e820.map[i],
+					    start_pfn, last_pfn,
+					    &ei_startpfn, &ei_endpfn))
+			add_active_range(nid, ei_startpfn, ei_endpfn);
+#ifdef CONFIG_XEN
+	BUG_ON(nid);
+	add_active_range(nid, last_pfn, last_pfn);
+#endif
+}
+
+/*
+ * Find the hole size (in bytes) in the memory range.
+ * @start: starting address of the memory range to scan
+ * @end: ending address of the memory range to scan
+ */
+u64 __init e820_hole_size(u64 start, u64 end)
+{
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long last_pfn = end >> PAGE_SHIFT;
+	unsigned long ei_startpfn, ei_endpfn, ram = 0;
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		if (e820_find_active_region(&e820.map[i],
+					    start_pfn, last_pfn,
+					    &ei_startpfn, &ei_endpfn))
+			ram += ei_endpfn - ei_startpfn;
+	}
+	return end - start - ((u64)ram << PAGE_SHIFT);
+}
+
+static void early_panic(char *msg)
+{
+	early_printk(msg);
+	panic(msg);
+}
+
+static int userdef __initdata;
+
+/* "mem=nopentium" disables the 4MB page tables. */
+static int __init parse_memopt(char *p)
+{
+	u64 mem_size, current_end;
+	unsigned int i;
+
+	if (!p)
+		return -EINVAL;
+
+	if (!strcmp(p, "nopentium")) {
+#ifdef CONFIG_X86_32
+		setup_clear_cpu_cap(X86_FEATURE_PSE);
+		return 0;
+#else
+		printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+		return -EINVAL;
+
+#endif
+	}
+
+	userdef = 1;
+	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" param */
+	if (mem_size == 0)
+		return -EINVAL;
+#ifdef CONFIG_XEN
+	/*
+	 * A little less than 2% of available memory are needed for page
+	 * tables, p2m map, and mem_map. Hence the maximum amount of memory
+	 * we can potentially balloon up to can in no case exceed about 50
+	 * times of what we've been given initially. Since even with that we
+	 * won't be able to boot (due to various calculations done based on
+	 * the total number of pages) we further restrict this to factor 32.
+	 */
+	if ((mem_size >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
+		u64 size = (u64)xen_start_info->nr_pages << 5;
+
+		printk(KERN_WARNING "mem=%Luk is invalid for an initial"
+				    " allocation of %luk, using %Luk\n",
+		       (unsigned long long)mem_size >> 10,
+		       xen_start_info->nr_pages << (PAGE_SHIFT - 10),
+		       (unsigned long long)size << (PAGE_SHIFT - 10));
+		mem_size = size << PAGE_SHIFT;
+	}
+#endif
+	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
+
+	i = e820.nr_map - 1;
+	current_end = e820.map[i].addr + e820.map[i].size;
+	if (current_end < mem_size) {
+		/*
+		 * The e820 map ends before our requested size so
+		 * extend the final entry to the requested address.
+		 */
+		if (e820.map[i].type == E820_RAM)
+			e820.map[i].size = mem_size - e820.map[i].addr;
+		else
+			e820_add_region(current_end, mem_size - current_end, E820_RAM);
+	}
+
+	return 0;
+}
+early_param("mem", parse_memopt);
+
+#ifndef CONFIG_XEN
+static int __init parse_memmap_opt(char *p)
+{
+	char *oldp;
+	u64 start_at, mem_size;
+
+	if (!p)
+		return -EINVAL;
+
+	if (!strncmp(p, "exactmap", 8)) {
+#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 = e820_end_of_ram_pfn();
+#endif
+		e820.nr_map = 0;
+		userdef = 1;
+		return 0;
+	}
+
+	oldp = p;
+	mem_size = memparse(p, &p);
+	if (p == oldp)
+		return -EINVAL;
+
+	userdef = 1;
+	if (*p == '@') {
+		start_at = memparse(p+1, &p);
+		e820_add_region(start_at, mem_size, E820_RAM);
+	} else if (*p == '#') {
+		start_at = memparse(p+1, &p);
+		e820_add_region(start_at, mem_size, E820_ACPI);
+	} else if (*p == '$') {
+		start_at = memparse(p+1, &p);
+		e820_add_region(start_at, mem_size, E820_RESERVED);
+	} else
+		e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
+
+	return *p == '\0' ? 0 : -EINVAL;
+}
+early_param("memmap", parse_memmap_opt);
+#endif
+
+void __init finish_e820_parsing(void)
+{
+	if (userdef) {
+		u32 nr = e820.nr_map;
+
+		if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr) < 0)
+			early_panic("Invalid user supplied memory map");
+		e820.nr_map = nr;
+
+		printk(KERN_INFO "user-defined physical RAM map:\n");
+		_e820_print_map(&e820, "user");
+	}
+}
+
+static inline const char *e820_type_to_string(int e820_type)
+{
+	switch (e820_type) {
+	case E820_RESERVED_KERN:
+	case E820_RAM:	return "System RAM";
+	case E820_ACPI:	return "ACPI Tables";
+	case E820_NVS:	return "ACPI Non-volatile Storage";
+	case E820_UNUSABLE:	return "Unusable memory";
+	default:	return "reserved";
+	}
+}
+
+#ifdef CONFIG_XEN
+#define e820 machine_e820
+#endif
+
+/*
+ * Mark e820 reserved areas as busy for the resource manager.
+ */
+static struct resource __initdata *e820_res;
+void __init e820_reserve_resources(void)
+{
+	int i;
+	struct resource *res;
+	u64 end;
+
+	res = alloc_bootmem(sizeof(struct resource) * e820.nr_map);
+	e820_res = res;
+	for (i = 0; i < e820.nr_map; i++) {
+		end = e820.map[i].addr + e820.map[i].size - 1;
+		if (end != (resource_size_t)end) {
+			res++;
+			continue;
+		}
+		res->name = e820_type_to_string(e820.map[i].type);
+		res->start = e820.map[i].addr;
+		res->end = end;
+
+		res->flags = IORESOURCE_MEM;
+
+		/*
+		 * don't register the region that could be conflicted with
+		 * pci device BAR resource and insert them later in
+		 * pcibios_resource_survey()
+		 */
+		if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) {
+			res->flags |= IORESOURCE_BUSY;
+			insert_resource(&iomem_resource, res);
+		}
+		res++;
+	}
+
+	for (i = 0; i < e820_saved.nr_map; i++) {
+		struct e820entry *entry = &e820_saved.map[i];
+		firmware_map_add_early(entry->addr,
+			entry->addr + entry->size - 1,
+			e820_type_to_string(entry->type));
+	}
+}
+
+/* How much should we pad RAM ending depending on where it is? */
+static unsigned long ram_alignment(resource_size_t pos)
+{
+	unsigned long mb = pos >> 20;
+
+	/* To 64kB in the first megabyte */
+	if (!mb)
+		return 64*1024;
+
+	/* To 1MB in the first 16MB */
+	if (mb < 16)
+		return 1024*1024;
+
+	/* To 64MB for anything above that */
+	return 64*1024*1024;
+}
+
+#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
+
+void __init e820_reserve_resources_late(void)
+{
+	int i;
+	struct resource *res;
+
+	res = e820_res;
+	for (i = 0; i < e820.nr_map; i++) {
+		if (!res->parent && res->end)
+			insert_resource_expand_to_fit(&iomem_resource, res);
+		res++;
+	}
+
+	/*
+	 * Try to bump up RAM regions to reasonable boundaries to
+	 * avoid stolen RAM:
+	 */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *entry = &e820.map[i];
+		u64 start, end;
+
+		if (entry->type != E820_RAM)
+			continue;
+		start = entry->addr + entry->size;
+		end = round_up(start, ram_alignment(start)) - 1;
+		if (end > MAX_RESOURCE_SIZE)
+			end = MAX_RESOURCE_SIZE;
+		if (start >= end)
+			continue;
+		reserve_region_with_split(&iomem_resource, start, end,
+					  "RAM buffer");
+	}
+}
+
+#undef e820
+
+char *__init default_machine_specific_memory_setup(void)
+{
+	int rc, nr_map;
+	unsigned long long maxmem;
+	struct xen_memory_map memmap;
+	/*
+	 * This is rather large for a stack variable but this early in
+	 * the boot process we know we have plenty slack space.
+	 */
+	struct e820entry map[E820MAX];
+
+	memmap.nr_entries = E820MAX;
+	set_xen_guest_handle(memmap.buffer, map);
+
+	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+	if (rc == -ENOSYS) {
+		memmap.nr_entries = 1;
+		map[0].addr = 0ULL;
+		map[0].size = PFN_PHYS((unsigned long long)xen_start_info->nr_pages);
+		/* 8MB slack (to balance backend allocations). */
+		map[0].size += 8ULL << 20;
+		map[0].type = E820_RAM;
+		rc = 0;
+	}
+	BUG_ON(rc);
+
+	nr_map = memmap.nr_entries;
+	sanitize_e820_map(map, ARRAY_SIZE(map), &nr_map);
+
+	if (append_e820_map(map, nr_map) < 0)
+		BUG();
+
+#ifdef CONFIG_XEN
+	/* See the comment in parse_memopt(). */
+	for (maxmem = rc = 0; rc < e820.nr_map; ++rc)
+		if (e820.map[rc].type == E820_RAM)
+			maxmem += e820.map[rc].size;
+	if ((maxmem >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
+		unsigned long long size = (u64)xen_start_info->nr_pages << 5;
+
+		printk(KERN_WARNING "maxmem of %LuM is invalid for an initial"
+				    " allocation of %luM, using %LuM\n",
+		       maxmem >> 20,
+		       xen_start_info->nr_pages >> (20 - PAGE_SHIFT),
+		       size >> (20 - PAGE_SHIFT));
+		size <<= PAGE_SHIFT;
+		e820_remove_range(size, ULLONG_MAX - size, E820_RAM, 1);
+	}
+
+	if (is_initial_xendomain()) {
+		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;
+	}
+#endif
+
+	return "Xen";
+}
+
+void __init setup_memory_map(void)
+{
+	char *who;
+
+	who = x86_init.resources.memory_setup();
+#ifdef CONFIG_XEN
+	if (is_initial_xendomain()) {
+		printk(KERN_INFO "Xen-provided machine memory map:\n");
+		_e820_print_map(&machine_e820, "BIOS");
+	} else
+#endif
+		memcpy(&e820_saved, &e820, sizeof(struct e820map));
+	printk(KERN_INFO "Xen-provided physical RAM map:\n");
+	_e820_print_map(&e820, who);
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/ldt-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/ldt-xen.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ * Copyright (C) 2002 Andi Kleen
+ *
+ * This handles calls from both 32bit and 64bit mode.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+
+#include <asm/system.h>
+#include <asm/ldt.h>
+#include <asm/desc.h>
+#include <asm/mmu_context.h>
+#include <asm/syscalls.h>
+
+#ifdef CONFIG_SMP
+static void flush_ldt(void *current_mm)
+{
+	if (current->active_mm == current_mm)
+		load_LDT(&current->active_mm->context);
+}
+#endif
+
+static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+{
+	void *oldldt, *newldt;
+	int oldsize;
+
+	if (mincount <= pc->size)
+		return 0;
+	oldsize = pc->size;
+	mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
+			(~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
+	if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
+		newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
+	else
+		newldt = (void *)__get_free_page(GFP_KERNEL);
+
+	if (!newldt)
+		return -ENOMEM;
+
+	if (oldsize)
+		memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
+	oldldt = pc->ldt;
+	memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
+	       (mincount - oldsize) * LDT_ENTRY_SIZE);
+
+#ifdef CONFIG_X86_64
+	/* CHECKME: Do we really need this ? */
+	wmb();
+#endif
+	pc->ldt = newldt;
+	wmb();
+	pc->size = mincount;
+	wmb();
+
+	if (reload) {
+#ifdef CONFIG_SMP
+		preempt_disable();
+#endif
+		make_pages_readonly(newldt,
+				    (mincount * LDT_ENTRY_SIZE) / PAGE_SIZE,
+				    XENFEAT_writable_descriptor_tables);
+		load_LDT(pc);
+#ifdef CONFIG_SMP
+		if (!cpumask_equal(mm_cpumask(current->mm),
+				   cpumask_of(smp_processor_id())))
+			smp_call_function(flush_ldt, current->mm, 1);
+		preempt_enable();
+#endif
+	}
+	if (oldsize) {
+		make_pages_writable(oldldt,
+				    (oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE,
+				    XENFEAT_writable_descriptor_tables);
+		if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
+			vfree(oldldt);
+		else
+			put_page(virt_to_page(oldldt));
+	}
+	return 0;
+}
+
+static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+{
+	int err = alloc_ldt(new, old->size, 0);
+
+	if (err < 0)
+		return err;
+	memcpy(new->ldt, old->ldt, old->size * LDT_ENTRY_SIZE);
+	make_pages_readonly(new->ldt,
+			    (new->size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+			    XENFEAT_writable_descriptor_tables);
+	return 0;
+}
+
+/*
+ * we do not have to muck with descriptors here, that is
+ * done in switch_mm() as needed.
+ */
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	struct mm_struct *old_mm;
+	int retval = 0;
+
+	memset(&mm->context, 0, sizeof(mm->context));
+	mutex_init(&mm->context.lock);
+	old_mm = current->mm;
+	if (old_mm)
+		mm->context.vdso = old_mm->context.vdso;
+	if (old_mm && old_mm->context.size > 0) {
+		mutex_lock(&old_mm->context.lock);
+		retval = copy_ldt(&mm->context, &old_mm->context);
+		mutex_unlock(&old_mm->context.lock);
+	}
+	return retval;
+}
+
+/*
+ * No need to lock the MM as we are the last user
+ *
+ * 64bit: Don't touch the LDT register - we're already in the next thread.
+ */
+void destroy_context(struct mm_struct *mm)
+{
+	if (mm->context.size) {
+		/* CHECKME: Can this ever happen ? */
+		if (mm == current->active_mm)
+			clear_LDT();
+		make_pages_writable(mm->context.ldt,
+				    (mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE,
+				    XENFEAT_writable_descriptor_tables);
+		if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
+			vfree(mm->context.ldt);
+		else
+			put_page(virt_to_page(mm->context.ldt));
+		mm->context.size = 0;
+	}
+}
+
+static int read_ldt(void __user *ptr, unsigned long bytecount)
+{
+	int err;
+	unsigned long size;
+	struct mm_struct *mm = current->mm;
+
+	if (!mm->context.size)
+		return 0;
+	if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
+		bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
+
+	mutex_lock(&mm->context.lock);
+	size = mm->context.size * LDT_ENTRY_SIZE;
+	if (size > bytecount)
+		size = bytecount;
+
+	err = 0;
+	if (copy_to_user(ptr, mm->context.ldt, size))
+		err = -EFAULT;
+	mutex_unlock(&mm->context.lock);
+	if (err < 0)
+		goto error_return;
+	if (size != bytecount) {
+		/* zero-fill the rest */
+		if (clear_user(ptr + size, bytecount - size) != 0) {
+			err = -EFAULT;
+			goto error_return;
+		}
+	}
+	return bytecount;
+error_return:
+	return err;
+}
+
+static int read_default_ldt(void __user *ptr, unsigned long bytecount)
+{
+	/* CHECKME: Can we use _one_ random number ? */
+#ifdef CONFIG_X86_32
+	unsigned long size = 5 * sizeof(struct desc_struct);
+#else
+	unsigned long size = 128;
+#endif
+	if (bytecount > size)
+		bytecount = size;
+	if (clear_user(ptr, bytecount))
+		return -EFAULT;
+	return bytecount;
+}
+
+static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
+{
+	struct mm_struct *mm = current->mm;
+	struct desc_struct ldt;
+	int error;
+	struct user_desc ldt_info;
+
+	error = -EINVAL;
+	if (bytecount != sizeof(ldt_info))
+		goto out;
+	error = -EFAULT;
+	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+		goto out;
+
+	error = -EINVAL;
+	if (ldt_info.entry_number >= LDT_ENTRIES)
+		goto out;
+	if (ldt_info.contents == 3) {
+		if (oldmode)
+			goto out;
+		if (ldt_info.seg_not_present == 0)
+			goto out;
+	}
+
+	mutex_lock(&mm->context.lock);
+	if (ldt_info.entry_number >= mm->context.size) {
+		error = alloc_ldt(&current->mm->context,
+				  ldt_info.entry_number + 1, 1);
+		if (error < 0)
+			goto out_unlock;
+	}
+
+	/* Allow LDTs to be cleared by the user. */
+	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+		if (oldmode || LDT_empty(&ldt_info)) {
+			memset(&ldt, 0, sizeof(ldt));
+			goto install;
+		}
+	}
+
+	fill_ldt(&ldt, &ldt_info);
+	if (oldmode)
+		ldt.avl = 0;
+
+	/* Install the new entry ...  */
+install:
+	error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
+
+out_unlock:
+	mutex_unlock(&mm->context.lock);
+out:
+	return error;
+}
+
+asmlinkage int sys_modify_ldt(int func, void __user *ptr,
+			      unsigned long bytecount)
+{
+	int ret = -ENOSYS;
+
+	switch (func) {
+	case 0:
+		ret = read_ldt(ptr, bytecount);
+		break;
+	case 1:
+		ret = write_ldt(ptr, bytecount, 1);
+		break;
+	case 2:
+		ret = read_default_ldt(ptr, bytecount);
+		break;
+	case 0x11:
+		ret = write_ldt(ptr, bytecount, 0);
+		break;
+	}
+	return ret;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/aperture_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/aperture_64.c
@@ -389,6 +389,7 @@
 	for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) {
 		int bus;
 		int dev_base, dev_limit;
+		u32 ctl;
 
 		bus = bus_dev_ranges[i].bus;
 		dev_base = bus_dev_ranges[i].dev_base;
@@ -401,7 +402,19 @@
 			iommu_detected = 1;
 			gart_iommu_aperture = 1;
 
-			aper_order = (read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL) >> 1) & 7;
+			ctl = read_pci_config(bus, slot, 3,
+					      AMD64_GARTAPERTURECTL);
+
+			/*
+			 * Before we do anything else disable the GART. It may
+			 * still be enabled if we boot into a crash-kernel here.
+			 * Reconfiguring the GART while it is enabled could have
+			 * unknown side-effects.
+			 */
+			ctl &= ~GARTEN;
+			write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl);
+
+			aper_order = (ctl >> 1) & 7;
 			aper_size = (32 * 1024 * 1024) << aper_order;
 			aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff;
 			aper_base <<= 25;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/asm-offsets_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/asm-offsets_32.c
@@ -20,10 +20,14 @@
 #include <asm/elf.h>
 #include <asm/suspend.h>
 
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
 #include <xen/interface/xen.h>
+#endif
 
+#ifdef CONFIG_LGUEST_GUEST
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
+#endif
 
 /* workaround for a warning with -Wmissing-prototypes */
 void foo(void);
@@ -55,6 +59,7 @@
 	OFFSET(TI_exec_domain, thread_info, exec_domain);
 	OFFSET(TI_flags, thread_info, flags);
 	OFFSET(TI_status, thread_info, status);
+	OFFSET(TI_cpu, thread_info, cpu);
 	OFFSET(TI_preempt_count, thread_info, preempt_count);
 	OFFSET(TI_addr_limit, thread_info, addr_limit);
 	OFFSET(TI_restart_block, thread_info, restart_block);
@@ -93,9 +98,14 @@
 	OFFSET(pbe_orig_address, pbe, orig_address);
 	OFFSET(pbe_next, pbe, next);
 
+#ifndef CONFIG_X86_NO_TSS
 	/* Offset from the sysenter stack to tss.sp0 */
-	DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
+	DEFINE(SYSENTER_stack_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
 		 sizeof(struct tss_struct));
+#else
+	/* sysenter stack points directly to sp0 */
+	DEFINE(SYSENTER_stack_sp0, 0);
+#endif
 
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
 	DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
@@ -105,6 +115,11 @@
 
 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
 
+#ifdef CONFIG_XEN
+	BLANK();
+	OFFSET(XEN_START_mfn_list, start_info, mfn_list);
+#endif
+
 #ifdef CONFIG_PARAVIRT
 	BLANK();
 	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
@@ -117,7 +132,7 @@
 	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
 #endif
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 	BLANK();
 	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
 	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/dumpstack_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/dumpstack_64.c
@@ -19,6 +19,7 @@
 #include "dumpstack.h"
 
 
+#ifndef CONFIG_X86_NO_TSS
 static char x86_stack_ids[][8] = {
 		[DEBUG_STACK - 1] = "#DB",
 		[NMI_STACK - 1] = "NMI",
@@ -30,15 +31,21 @@
 			N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
 #endif
 	};
+#endif
 
 int x86_is_stack_id(int id, char *name)
 {
+#ifndef CONFIG_X86_NO_TSS
 	return x86_stack_ids[id - 1] == name;
+#else
+	return 0;
+#endif
 }
 
 static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
 					unsigned *usedp, char **idp)
 {
+#ifndef CONFIG_X86_NO_TSS
 	unsigned k;
 
 	/*
@@ -98,6 +105,7 @@
 		}
 #endif
 	}
+#endif /* CONFIG_X86_NO_TSS */
 	return NULL;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/fixup.c
+++ linux-ec2-2.6.32/arch/x86/kernel/fixup.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * fixup.c
+ * 
+ * Binary-rewriting of certain IA32 instructions, on notification by Xen.
+ * Used to avoid repeated slow emulation of common instructions used by the
+ * user-space TLS (Thread-Local Storage) libraries.
+ * 
+ * **** NOTE ****
+ *  Issues with the binary rewriting have caused it to be removed. Instead
+ *  we rely on Xen's emulator to boot the kernel, and then print a banner
+ *  message recommending that the user disables /lib/tls.
+ * 
+ * Copyright (c) 2004, K A Fraser
+ * 
+ * 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/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <asm/traps.h>
+
+#define DP(_f, _args...) printk(KERN_ALERT "  " _f "\n" , ## _args )
+
+dotraplinkage void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
+{
+	static unsigned long printed = 0;
+	char info[100];
+	int i;
+
+	/* Ignore statically-linked init. */
+	if (current->tgid == 1)
+		return;
+            
+	VOID(HYPERVISOR_vm_assist(VMASST_CMD_disable,
+				  VMASST_TYPE_4gb_segments_notify));
+
+	if (test_and_set_bit(0, &printed))
+		return;
+
+	sprintf(info, "%s (pid=%d)", current->comm, current->tgid);
+
+	DP("");
+	DP("***************************************************************");
+	DP("***************************************************************");
+	DP("** WARNING: Currently emulating unsupported memory accesses  **");
+	DP("**          in /lib/tls glibc libraries. The emulation is    **");
+	DP("**          slow. To ensure full performance you should      **");
+	DP("**          install a 'xen-friendly' (nosegneg) version of   **");
+	DP("**          the library, or disable tls support by executing **");
+	DP("**          the following as root:                           **");
+	DP("**          mv /lib/tls /lib/tls.disabled                    **");
+	DP("** Offending process: %-38.38s **", info);
+	DP("***************************************************************");
+	DP("***************************************************************");
+	DP("");
+
+	for (i = 5; i > 0; i--) {
+		touch_softlockup_watchdog();
+		printk("Pausing... %d", i);
+		mdelay(1000);
+		printk("\b\b\b\b\b\b\b\b\b\b\b\b");
+	}
+
+	printk("Continuing...\n\n");
+}
+
+static int __init fixup_init(void)
+{
+	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+				     VMASST_TYPE_4gb_segments_notify));
+	return 0;
+}
+__initcall(fixup_init);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/tsc.c
+++ linux-ec2-2.6.32/arch/x86/kernel/tsc.c
@@ -104,10 +104,14 @@
 
 __setup("notsc", notsc_setup);
 
+static int no_sched_irq_time;
+
 static int __init tsc_setup(char *str)
 {
 	if (!strcmp(str, "reliable"))
 		tsc_clocksource_reliable = 1;
+	if (!strncmp(str, "noirqtime", 9))
+		no_sched_irq_time = 1;
 	return 1;
 }
 
@@ -626,6 +630,44 @@
 	local_irq_restore(flags);
 }
 
+static unsigned long long cyc2ns_suspend;
+
+void save_sched_clock_state(void)
+{
+	if (!sched_clock_stable)
+		return;
+
+	cyc2ns_suspend = sched_clock();
+}
+
+/*
+ * Even on processors with invariant TSC, TSC gets reset in some the
+ * ACPI system sleep states. And in some systems BIOS seem to reinit TSC to
+ * arbitrary value (still sync'd across cpu's) during resume from such sleep
+ * states. To cope up with this, recompute the cyc2ns_offset for each cpu so
+ * that sched_clock() continues from the point where it was left off during
+ * suspend.
+ */
+void restore_sched_clock_state(void)
+{
+	unsigned long long offset;
+	unsigned long flags;
+	int cpu;
+
+	if (!sched_clock_stable)
+		return;
+
+	local_irq_save(flags);
+
+	__get_cpu_var(cyc2ns_offset) = 0;
+	offset = cyc2ns_suspend - sched_clock();
+
+	for_each_possible_cpu(cpu)
+		per_cpu(cyc2ns_offset, cpu) = offset;
+
+	local_irq_restore(flags);
+}
+
 #ifdef CONFIG_CPU_FREQ
 
 /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
@@ -763,6 +805,8 @@
 {
 	if (!tsc_unstable) {
 		tsc_unstable = 1;
+		sched_clock_stable = 0;
+		disable_sched_clock_irqtime();
 		printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
 		/* Change only the rating, when not registered */
 		if (clocksource_tsc.mult)
@@ -951,6 +995,9 @@
 	/* now allow native_sched_clock() to use rdtsc */
 	tsc_disabled = 0;
 
+	if (!no_sched_irq_time)
+		enable_sched_clock_irqtime();
+
 	lpj = ((u64)tsc_khz * 1000);
 	do_div(lpj, HZ);
 	lpj_fine = lpj;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/entry_32.S
+++ linux-ec2-2.6.32/arch/x86/kernel/entry_32.S
@@ -393,7 +393,7 @@
 	CFI_SIGNAL_FRAME
 	CFI_DEF_CFA esp, 0
 	CFI_REGISTER esp, ebp
-	movl TSS_sysenter_sp0(%esp),%esp
+	movl SYSENTER_stack_sp0(%esp),%esp
 sysenter_past_esp:
 	/*
 	 * Interrupts are disabled here, but we can't trace it until
@@ -995,7 +995,7 @@
 	CFI_ENDPROC
 ENDPROC(kernel_thread_helper)
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 /* Xen doesn't set %esp to be precisely what the normal sysenter
    entrypoint expects, so fix it up before using the normal path. */
 ENTRY(xen_sysenter_target)
@@ -1088,7 +1088,7 @@
 .previous
 ENDPROC(xen_failsafe_callback)
 
-#endif	/* CONFIG_XEN */
+#endif	/* CONFIG_PARAVIRT_XEN */
 
 #ifdef CONFIG_FUNCTION_TRACER
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -1270,7 +1270,7 @@
  * that sets up the real kernel stack. Check here, since we can't
  * allow the wrong stack to be used.
  *
- * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
+ * "SYSENTER_stack_sp0+12" is because the NMI/debug handler will have
  * already pushed 3 words if it hits on the sysenter instruction:
  * eflags, cs and eip.
  *
@@ -1282,7 +1282,7 @@
 	cmpw $__KERNEL_CS, 4(%esp)
 	jne \ok
 \label:
-	movl TSS_sysenter_sp0 + \offset(%esp), %esp
+	movl SYSENTER_stack_sp0 + \offset(%esp), %esp
 	CFI_DEF_CFA esp, 0
 	CFI_UNDEFINED eip
 	pushfl
--- linux-ec2-2.6.32.orig/arch/x86/kernel/irq_64-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/irq_64-xen.c
@@ -0,0 +1,143 @@
+/*
+ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * This file contains the lowest level x86_64-specific interrupt
+ * entry and irq statistics code. All the remaining irq logic is
+ * done by the generic kernel/irq/ code and in the
+ * x86_64-specific irq controller code. (e.g. i8259.c and
+ * io_apic.c.)
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <linux/smp.h>
+#include <asm/io_apic.h>
+#include <asm/idle.h>
+#include <asm/apic.h>
+
+DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+EXPORT_PER_CPU_SYMBOL(irq_stat);
+
+DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+EXPORT_PER_CPU_SYMBOL(irq_regs);
+
+/*
+ * Probabilistic stack overflow check:
+ *
+ * Only check the stack in process context, because everything else
+ * runs on the big interrupt stacks. Checking reliably is too expensive,
+ * so we just check from interrupts.
+ */
+static inline void stack_overflow_check(struct pt_regs *regs)
+{
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	u64 curbase = (u64)task_stack_page(current);
+
+	WARN_ONCE(regs->sp >= curbase &&
+		  regs->sp <= curbase + THREAD_SIZE &&
+		  regs->sp <  curbase + sizeof(struct thread_info) +
+					sizeof(struct pt_regs) + 128,
+
+		  "do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
+			current->comm, curbase, regs->sp);
+#endif
+}
+
+bool handle_irq(unsigned irq, struct pt_regs *regs)
+{
+	struct irq_desc *desc;
+
+	stack_overflow_check(regs);
+
+	desc = irq_to_desc(irq);
+	if (unlikely(!desc))
+		return false;
+
+	generic_handle_irq_desc(irq, desc);
+	return true;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
+void fixup_irqs(void)
+{
+	unsigned int irq;
+	static int warned;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(irq, desc) {
+		int break_affinity = 0;
+		int set_affinity = 1;
+		const struct cpumask *affinity;
+
+		if (!desc)
+			continue;
+		if (irq == 2)
+			continue;
+
+		/* interrupt's are disabled at this point */
+		spin_lock(&desc->lock);
+
+		affinity = desc->affinity;
+		if (!irq_has_action(irq) ||
+		    (desc->status & IRQ_PER_CPU) ||
+		    cpumask_equal(affinity, cpu_online_mask)) {
+			spin_unlock(&desc->lock);
+			continue;
+		}
+
+		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+			break_affinity = 1;
+			affinity = cpu_all_mask;
+		}
+
+		if (desc->chip->mask)
+			desc->chip->mask(irq);
+
+		if (desc->chip->set_affinity)
+			desc->chip->set_affinity(irq, affinity);
+		else if (!(warned++))
+			set_affinity = 0;
+
+		if (desc->chip->unmask)
+			desc->chip->unmask(irq);
+
+		spin_unlock(&desc->lock);
+
+		if (break_affinity && set_affinity)
+			/*printk("Broke affinity for irq %i\n", irq)*/;
+		else if (!set_affinity)
+			printk("Cannot set affinity for irq %i\n", irq);
+	}
+
+	/* That doesn't seem sufficient.  Give it 1ms. */
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+}
+#endif
+
+extern void call_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+	__u32 pending;
+	unsigned long flags;
+
+	if (in_interrupt())
+		return;
+
+	local_irq_save(flags);
+	pending = local_softirq_pending();
+	/* Switch to interrupt stack */
+	if (pending) {
+		call_softirq();
+		WARN_ON_ONCE(softirq_count());
+	}
+	local_irq_restore(flags);
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/crash.c
+++ linux-ec2-2.6.32/arch/x86/kernel/crash.c
@@ -27,7 +27,6 @@
 #include <asm/cpu.h>
 #include <asm/reboot.h>
 #include <asm/virtext.h>
-#include <asm/iommu.h>
 
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
@@ -104,10 +103,5 @@
 #ifdef CONFIG_HPET_TIMER
 	hpet_disable();
 #endif
-
-#ifdef CONFIG_X86_64
-	pci_iommu_shutdown();
-#endif
-
 	crash_save_cpu(regs, safe_smp_processor_id());
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/vsyscall_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/vsyscall_64.c
@@ -73,7 +73,8 @@
 	write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
 }
 
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
+		     u32 mult)
 {
 	unsigned long flags;
 
@@ -82,7 +83,7 @@
 	vsyscall_gtod_data.clock.vread = clock->vread;
 	vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
 	vsyscall_gtod_data.clock.mask = clock->mask;
-	vsyscall_gtod_data.clock.mult = clock->mult;
+	vsyscall_gtod_data.clock.mult = mult;
 	vsyscall_gtod_data.clock.shift = clock->shift;
 	vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
 	vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/paravirt.c
+++ linux-ec2-2.6.32/arch/x86/kernel/paravirt.c
@@ -345,6 +345,9 @@
 	.read_tscp = native_read_tscp,
 	.load_tr_desc = native_load_tr_desc,
 	.set_ldt = native_set_ldt,
+#ifdef CONFIG_X86_32
+	.load_user_cs_desc = native_load_user_cs_desc,
+#endif /*CONFIG_X86_32*/
 	.load_gdt = native_load_gdt,
 	.load_idt = native_load_idt,
 	.store_gdt = native_store_gdt,
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/head-xen.c
@@ -0,0 +1,222 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#ifndef CONFIG_XEN
+#include <asm/bios_ebda.h>
+
+#define BIOS_LOWMEM_KILOBYTES 0x413
+
+/*
+ * The BIOS places the EBDA/XBDA at the top of conventional
+ * memory, and usually decreases the reported amount of
+ * conventional memory (int 0x12) too. This also contains a
+ * workaround for Dell systems that neglect to reserve EBDA.
+ * The same workaround also avoids a problem with the AMD768MPX
+ * chipset: reserve a page before VGA to prevent PCI prefetch
+ * into it (errata #56). Usually the page is reserved anyways,
+ * unless you have no PS/2 mouse plugged in.
+ */
+void __init reserve_ebda_region(void)
+{
+	unsigned int lowmem, ebda_addr;
+
+	/* To determine the position of the EBDA and the */
+	/* end of conventional memory, we need to look at */
+	/* the BIOS data area. In a paravirtual environment */
+	/* that area is absent. We'll just have to assume */
+	/* that the paravirt case can handle memory setup */
+	/* correctly, without our help. */
+	if (paravirt_enabled())
+		return;
+
+	/* end of low (conventional) memory */
+	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
+	lowmem <<= 10;
+
+	/* start of EBDA area */
+	ebda_addr = get_bios_ebda();
+
+	/* Fixup: bios puts an EBDA in the top 64K segment */
+	/* of conventional memory, but does not adjust lowmem. */
+	if ((lowmem - ebda_addr) <= 0x10000)
+		lowmem = ebda_addr;
+
+	/* Fixup: bios does not report an EBDA at all. */
+	/* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
+	if ((ebda_addr == 0) && (lowmem >= 0x9f000))
+		lowmem = 0x9f000;
+
+	/* Paranoia: should never happen, but... */
+	if ((lowmem == 0) || (lowmem >= 0x100000))
+		lowmem = 0x9f000;
+
+	/* reserve all memory between lowmem and the 1MB mark */
+	reserve_early_overlap_ok(lowmem, 0x100000, "BIOS reserved");
+}
+#else /* CONFIG_XEN */
+#include <linux/module.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <xen/interface/callback.h>
+#include <xen/interface/memory.h>
+
+extern void hypervisor_callback(void);
+extern void failsafe_callback(void);
+extern void nmi(void);
+
+#ifdef CONFIG_X86_64
+#include <asm/proto.h>
+#define CALLBACK_ADDR(fn) ((unsigned long)(fn))
+#else
+#define CALLBACK_ADDR(fn) { __KERNEL_CS, (unsigned long)(fn) }
+#endif
+
+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 xen_start_kernel(void)
+{
+	unsigned int i;
+	struct xen_machphys_mapping mapping;
+	unsigned long machine_to_phys_nr_ents;
+#ifdef CONFIG_X86_32
+	struct xen_platform_parameters pp;
+	extern pte_t swapper_pg_fixmap[PTRS_PER_PTE];
+	unsigned long addr;
+#endif
+
+	xen_setup_features();
+
+	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;
+	while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
+		machine_to_phys_order++;
+
+	if (!xen_feature(XENFEAT_auto_translated_physmap))
+		phys_to_machine_mapping =
+			(unsigned long *)xen_start_info->mfn_list;
+
+	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+				     VMASST_TYPE_writable_pagetables));
+
+	reserve_early(ALIGN(__pa_symbol(&_end), PAGE_SIZE),
+		      __pa(xen_start_info->pt_base)
+		      + (xen_start_info->nr_pt_frames << PAGE_SHIFT),
+		      "Xen provided");
+
+#ifdef CONFIG_X86_32
+	WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable,
+				     VMASST_TYPE_4gb_segments));
+
+	init_mm.pgd = swapper_pg_dir = (pgd_t *)xen_start_info->pt_base;
+
+	if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) {
+		hypervisor_virt_start = pp.virt_start;
+		reserve_top_address(0UL - pp.virt_start);
+	}
+
+	BUG_ON(pte_index(hypervisor_virt_start));
+
+	/* Do an early initialization of the fixmap area */
+	make_lowmem_page_readonly(swapper_pg_fixmap, XENFEAT_writable_page_tables);
+	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+	set_pmd(pmd_offset(pud_offset(swapper_pg_dir + pgd_index(addr),
+				      addr),
+			   addr),
+		__pmd(__pa_symbol(swapper_pg_fixmap) | _PAGE_TABLE));
+#else
+	check_efer();
+	xen_init_pt();
+#endif
+
+#define __FIXADDR_TOP (-PAGE_SIZE)
+#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+#define FIX_BUG_ON(fix) BUILD_BUG_ON(pmd_index(__fix_to_virt(FIX_##fix)) \
+			!= pmd_index(__fix_to_virt(FIX_EARLYCON_MEM_BASE)))
+	FIX_BUG_ON(SHARED_INFO);
+	FIX_BUG_ON(ISAMAP_BEGIN);
+	FIX_BUG_ON(ISAMAP_END);
+#undef pmd_index
+#undef __FIXADDR_TOP
+
+	/* Switch to the real shared_info page, and clear the dummy page. */
+	set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
+	HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+	memset(empty_zero_page, 0, sizeof(empty_zero_page));
+
+	setup_vcpu_info(0);
+
+	/* Set up mapping of lowest 1MB of physical memory. */
+	for (i = 0; i < NR_FIX_ISAMAPS; i++)
+		if (is_initial_xendomain())
+			set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE);
+		else
+			__set_fixmap(FIX_ISAMAP_BEGIN - i,
+				     virt_to_machine(empty_zero_page),
+				     PAGE_KERNEL_RO);
+
+}
+
+void __init xen_arch_setup(void)
+{
+	int ret;
+	static const struct callback_register __initconst event = {
+		.type = CALLBACKTYPE_event,
+		.address = CALLBACK_ADDR(hypervisor_callback)
+	};
+	static const struct callback_register __initconst failsafe = {
+		.type = CALLBACKTYPE_failsafe,
+		.address = CALLBACK_ADDR(failsafe_callback)
+	};
+#ifdef CONFIG_X86_64
+	static const struct callback_register __initconst syscall = {
+		.type = CALLBACKTYPE_syscall,
+		.address = CALLBACK_ADDR(system_call)
+	};
+#endif
+	static const struct callback_register __initconst nmi_cb = {
+		.type = CALLBACKTYPE_nmi,
+		.address = CALLBACK_ADDR(nmi)
+	};
+
+	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
+	if (ret == 0)
+		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
+#ifdef CONFIG_X86_64
+	if (ret == 0)
+		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
+#endif
+#if CONFIG_XEN_COMPAT <= 0x030002
+#ifdef CONFIG_X86_32
+	if (ret == -ENOSYS)
+		ret = HYPERVISOR_set_callbacks(
+			event.address.cs, event.address.eip,
+			failsafe.address.cs, failsafe.address.eip);
+#else
+		ret = HYPERVISOR_set_callbacks(
+			event.address,
+			failsafe.address,
+			syscall.address);
+#endif
+#endif
+	BUG_ON(ret);
+
+	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (ret == -ENOSYS) {
+		static struct xennmi_callback __initdata cb = {
+			.handler_address = (unsigned long)nmi
+		};
+
+		HYPERVISOR_nmi_op(XENNMI_register_callback, &cb);
+	}
+#endif
+}
+#endif /* CONFIG_XEN */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head_32.S
+++ linux-ec2-2.6.32/arch/x86/kernel/head_32.S
@@ -324,7 +324,7 @@
 /*
  * Enable paging
  */
-	movl $pa(swapper_pg_dir),%eax
+	movl pa(initial_page_table), %eax
 	movl %eax,%cr3		/* set the page table pointer.. */
 	movl %cr0,%eax
 	orl  $X86_CR0_PG,%eax
@@ -604,6 +604,8 @@
 .align 4
 ENTRY(initial_code)
 	.long i386_start_kernel
+ENTRY(initial_page_table)
+	.long pa(swapper_pg_dir)
 
 /*
  * BSS section
@@ -619,6 +621,10 @@
 #endif
 swapper_pg_fixmap:
 	.fill 1024,4,0
+#ifdef CONFIG_X86_TRAMPOLINE
+ENTRY(trampoline_pg_dir)
+	.fill 1024,4,0
+#endif
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head32-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/head32-xen.c
@@ -0,0 +1,80 @@
+/*
+ *  linux/arch/i386/kernel/head32.c -- prepare to run common code
+ *
+ *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
+ *  Copyright (C) 2007 Eric Biederman <ebiederm@xmission.com>
+ */
+
+#include <linux/init.h>
+#include <linux/start_kernel.h>
+
+#include <asm/setup.h>
+#include <asm/sections.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+#include <asm/trampoline.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/bios_ebda.h>
+
+static void __init i386_default_early_setup(void)
+{
+	/* Initialize 32bit specific setup functions */
+	if (is_initial_xendomain())
+		x86_init.resources.probe_roms = probe_roms;
+	x86_init.resources.reserve_resources = i386_reserve_resources;
+#ifndef CONFIG_XEN
+	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
+
+	reserve_ebda_region();
+#endif
+}
+
+void __init i386_start_kernel(void)
+{
+	reserve_trampoline_memory();
+
+	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+
+#ifndef CONFIG_XEN
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* Reserve INITRD */
+	if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
+		u64 ramdisk_image = boot_params.hdr.ramdisk_image;
+		u64 ramdisk_size  = boot_params.hdr.ramdisk_size;
+		u64 ramdisk_end   = ramdisk_image + ramdisk_size;
+		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
+	}
+#endif
+
+	/* Call the subarch specific early setup function */
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_MRST:
+		x86_mrst_early_setup();
+		break;
+	default:
+		i386_default_early_setup();
+		break;
+	}
+#else
+	{
+		int max_cmdline;
+
+		if ((max_cmdline = MAX_GUEST_CMDLINE) > COMMAND_LINE_SIZE)
+			max_cmdline = COMMAND_LINE_SIZE;
+		memcpy(boot_command_line, xen_start_info->cmd_line, max_cmdline);
+		boot_command_line[max_cmdline-1] = '\0';
+	}
+
+	i386_default_early_setup();
+	xen_start_kernel();
+#endif
+
+	/*
+	 * At this point everything still needed from the boot loader
+	 * or BIOS or kernel text should be early reserved or marked not
+	 * RAM in e820. All other memory is free game.
+	 */
+
+	start_kernel();
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/entry_64.S
+++ linux-ec2-2.6.32/arch/x86/kernel/entry_64.S
@@ -1267,7 +1267,7 @@
 	CFI_ENDPROC
 END(call_softirq)
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
 
 /*
@@ -1303,7 +1303,7 @@
 	decl PER_CPU_VAR(irq_count)
 	jmp  error_exit
 	CFI_ENDPROC
-END(do_hypervisor_callback)
+END(xen_do_hypervisor_callback)
 
 /*
  * Hypervisor uses this for application faults while it executes.
@@ -1364,7 +1364,7 @@
 	CFI_ENDPROC
 END(xen_failsafe_callback)
 
-#endif /* CONFIG_XEN */
+#endif /* CONFIG_PARAVIRT_XEN */
 
 /*
  * Some functions should be protected against kprobes
@@ -1374,7 +1374,7 @@
 paranoidzeroentry_ist debug do_debug DEBUG_STACK
 paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
 paranoiderrorentry stack_segment do_stack_segment
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 zeroentry xen_debug do_debug
 zeroentry xen_int3 do_int3
 errorentry xen_stack_segment do_stack_segment
--- linux-ec2-2.6.32.orig/arch/x86/kernel/head64-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/head64-xen.c
@@ -0,0 +1,141 @@
+/*
+ *  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/start_kernel.h>
+#include <linux/io.h>
+
+#include <asm/processor.h>
+#include <asm/proto.h>
+#include <asm/smp.h>
+#include <asm/setup.h>
+#include <asm/desc.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/sections.h>
+#include <asm/kdebug.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
+#include <asm/bios_ebda.h>
+
+#ifndef CONFIG_XEN
+static void __init zap_identity_mappings(void)
+{
+	pgd_t *pgd = pgd_offset_k(0UL);
+	pgd_clear(pgd);
+	__flush_tlb_all();
+}
+
+/* Don't add a printk in there. printk relies on the PDA which is not initialized 
+   yet. */
+static void __init clear_bss(void)
+{
+	memset(__bss_start, 0,
+	       (unsigned long) __bss_stop - (unsigned long) __bss_start);
+}
+#endif
+
+static void __init copy_bootdata(char *real_mode_data)
+{
+#ifndef CONFIG_XEN
+	char * command_line;
+
+	memcpy(&boot_params, real_mode_data, sizeof boot_params);
+	if (boot_params.hdr.cmd_line_ptr) {
+		command_line = __va(boot_params.hdr.cmd_line_ptr);
+		memcpy(boot_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(boot_command_line, xen_start_info->cmd_line, max_cmdline);
+	boot_command_line[max_cmdline-1] = '\0';
+#endif
+}
+
+#include <xen/interface/memory.h>
+
+void __init x86_64_start_kernel(char * real_mode_data)
+{
+	/*
+	 * Build-time sanity checks on the kernel image and module
+	 * area mappings. (these are purely build-time and produce no code)
+	 */
+	BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START);
+	BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE);
+	BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE);
+	BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0);
+	BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0);
+	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
+	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
+				(__START_KERNEL & PGDIR_MASK)));
+	BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END);
+
+	xen_start_info = (struct start_info *)real_mode_data;
+	xen_start_kernel();
+
+#ifndef CONFIG_XEN
+	/* clear bss before set_intr_gate with early_idt_handler */
+	clear_bss();
+
+	/* Make NULL pointers segfault */
+	zap_identity_mappings();
+
+	/* Cleanup the over mapped high alias */
+	cleanup_highmap();
+
+	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
+#ifdef CONFIG_EARLY_PRINTK
+		set_intr_gate(i, &early_idt_handlers[i]);
+#else
+		set_intr_gate(i, early_idt_handler);
+#endif
+	}
+	load_idt((const struct desc_ptr *)&idt_descr);
+#endif
+
+	if (console_loglevel == 10)
+		early_printk("Kernel alive\n");
+
+	xen_switch_pt();
+
+	x86_64_start_reservations(real_mode_data);
+}
+
+void __init x86_64_start_reservations(char *real_mode_data)
+{
+	copy_bootdata(__va(real_mode_data));
+
+	reserve_trampoline_memory();
+
+	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		xen_start_info->mfn_list = ~0UL;
+	else if (xen_start_info->mfn_list < __START_KERNEL_map)
+		reserve_early(xen_start_info->first_p2m_pfn << PAGE_SHIFT,
+			      (xen_start_info->first_p2m_pfn
+			       + xen_start_info->nr_p2m_frames) << PAGE_SHIFT,
+			      "INITP2M");
+
+	/*
+	 * At this point everything still needed from the boot loader
+	 * or BIOS or kernel text should be early reserved or marked not
+	 * RAM in e820. All other memory is free game.
+	 */
+
+	start_kernel();
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/trampoline.c
+++ linux-ec2-2.6.32/arch/x86/kernel/trampoline.c
@@ -1,6 +1,7 @@
 #include <linux/io.h>
 
 #include <asm/trampoline.h>
+#include <asm/pgtable.h>
 #include <asm/e820.h>
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
@@ -39,3 +40,19 @@
 	memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
 	return virt_to_phys(trampoline_base);
 }
+
+void __init setup_trampoline_page_table(void)
+{
+#ifdef CONFIG_X86_32
+	/* Copy kernel address range */
+	clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
+			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
+
+	/* Initialize low mappings */
+	clone_pgd_range(trampoline_pg_dir,
+			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+			min_t(unsigned long, KERNEL_PGD_PTRS,
+			      KERNEL_PGD_BOUNDARY));
+#endif
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/machine_kexec_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/machine_kexec_32.c
@@ -26,47 +26,9 @@
 #include <asm/system.h>
 #include <asm/cacheflush.h>
 
-static void set_idt(void *newidt, __u16 limit)
-{
-	struct desc_ptr curidt;
-
-	/* ia32 supports unaliged loads & stores */
-	curidt.size    = limit;
-	curidt.address = (unsigned long)newidt;
-
-	load_idt(&curidt);
-}
-
-
-static void set_gdt(void *newgdt, __u16 limit)
-{
-	struct desc_ptr curgdt;
-
-	/* ia32 supports unaligned loads & stores */
-	curgdt.size    = limit;
-	curgdt.address = (unsigned long)newgdt;
-
-	load_gdt(&curgdt);
-}
-
-static void load_segments(void)
-{
-#define __STR(X) #X
-#define STR(X) __STR(X)
-
-	__asm__ __volatile__ (
-		"\tljmp $"STR(__KERNEL_CS)",$1f\n"
-		"\t1:\n"
-		"\tmovl $"STR(__KERNEL_DS)",%%eax\n"
-		"\tmovl %%eax,%%ds\n"
-		"\tmovl %%eax,%%es\n"
-		"\tmovl %%eax,%%fs\n"
-		"\tmovl %%eax,%%gs\n"
-		"\tmovl %%eax,%%ss\n"
-		: : : "eax", "memory");
-#undef STR
-#undef __STR
-}
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
 
 static void machine_kexec_free_page_tables(struct kimage *image)
 {
@@ -138,6 +100,51 @@
 		__pa(control_page), __pa(control_page));
 }
 
+#ifdef CONFIG_XEN
+
+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
+
+#if PAGES_NR > KEXEC_XEN_NO_PAGES
+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
+#endif
+
+#if PA_CONTROL_PAGE != 0
+#error PA_CONTROL_PAGE is non zero - Xen support will break
+#endif
+
+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+{
+	void *control_page;
+
+	memset(xki->page_list, 0, sizeof(xki->page_list));
+
+	control_page = page_address(image->control_code_page);
+	memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
+	xki->page_list[PA_PGD] = __ma(image->arch.pgd);
+
+	if (image->type == KEXEC_TYPE_DEFAULT)
+		xki->page_list[PA_SWAP_PAGE] = page_to_phys(image->swap_page);
+}
+
+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) { ; }
+
+#endif /* CONFIG_XEN */
+
 /*
  * A architecture hook called to validate the
  * proposed image and prepare the control pages
@@ -177,6 +184,7 @@
 	machine_kexec_free_page_tables(image);
 }
 
+#ifndef CONFIG_XEN
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
@@ -228,24 +236,6 @@
 		page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page)
 						<< PAGE_SHIFT);
 
-	/*
-	 * The segment registers are funny things, they have both a
-	 * visible and an invisible part.  Whenever the visible part is
-	 * set to a specific selector, the invisible part is loaded
-	 * with from a table in memory.  At no other time is the
-	 * descriptor table in memory accessed.
-	 *
-	 * I take advantage of this here by force loading the
-	 * segments, before I zap the gdt with an invalid value.
-	 */
-	load_segments();
-	/*
-	 * The gdt & idt are now invalid.
-	 * If you want to load them you must set up your own idt & gdt.
-	 */
-	set_gdt(phys_to_virt(0), 0);
-	set_idt(phys_to_virt(0), 0);
-
 	/* now call it */
 	image->start = relocate_kernel_ptr((unsigned long)image->head,
 					   (unsigned long)page_list,
@@ -259,6 +249,7 @@
 
 	__ftrace_enabled_restore(save_ftrace_enabled);
 }
+#endif
 
 void arch_crash_save_vmcoreinfo(void)
 {
--- linux-ec2-2.6.32.orig/arch/x86/kernel/mpparse-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/mpparse-xen.c
@@ -0,0 +1,1081 @@
+/*
+ *	Intel Multiprocessor Specification 1.1 and 1.4
+ *	compliant MP-table parsing routines.
+ *
+ *	(c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
+ *	(c) 1998, 1999, 2000, 2009 Ingo Molnar <mingo@redhat.com>
+ *      (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bitops.h>
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+#include <asm/pgalloc.h>
+#include <asm/io_apic.h>
+#include <asm/proto.h>
+#include <asm/bios_ebda.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
+#include <asm/setup.h>
+#include <asm/smp.h>
+
+#include <asm/apic.h>
+
+static void *_bus_to_virt(unsigned long ma)
+{
+	return is_ISA_range(ma, ma) ? isa_bus_to_virt(ma) : bus_to_virt(ma);
+}
+
+/*
+ * Checksum an MP configuration block.
+ */
+
+static int __init mpf_checksum(unsigned char *mp, int len)
+{
+	int sum = 0;
+
+	while (len--)
+		sum += *mp++;
+
+	return sum & 0xFF;
+}
+
+#ifndef CONFIG_XEN
+int __init default_mpc_apic_id(struct mpc_cpu *m)
+{
+	return m->apicid;
+}
+#endif
+
+static void __init MP_processor_info(struct mpc_cpu *m)
+{
+#ifndef CONFIG_XEN
+	int apicid;
+	char *bootup_cpu = "";
+
+	if (!(m->cpuflag & CPU_ENABLED)) {
+		disabled_cpus++;
+		return;
+	}
+
+	apicid = x86_init.mpparse.mpc_apic_id(m);
+
+	if (m->cpuflag & CPU_BOOTPROCESSOR) {
+		bootup_cpu = " (Bootup-CPU)";
+		boot_cpu_physical_apicid = m->apicid;
+	}
+
+	printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+	generic_processor_info(apicid, m->apicver);
+#else /* CONFIG_XEN */
+	num_processors++;
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+void __init default_mpc_oem_bus_info(struct mpc_bus *m, char *str)
+{
+	memcpy(str, m->bustype, 6);
+	str[6] = 0;
+	apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
+}
+
+static void __init MP_bus_info(struct mpc_bus *m)
+{
+	char str[7];
+
+	x86_init.mpparse.mpc_oem_bus_info(m, str);
+
+#if MAX_MP_BUSSES < 256
+	if (m->busid >= MAX_MP_BUSSES) {
+		printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+		       " is too large, max. supported is %d\n",
+		       m->busid, str, MAX_MP_BUSSES - 1);
+		return;
+	}
+#endif
+
+	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
+		set_bit(m->busid, mp_bus_not_pci);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
+#endif
+	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
+		if (x86_init.mpparse.mpc_oem_pci_bus)
+			x86_init.mpparse.mpc_oem_pci_bus(m);
+
+		clear_bit(m->busid, mp_bus_not_pci);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+		mp_bus_id_to_type[m->busid] = MP_BUS_PCI;
+	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
+		mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
+	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
+		mp_bus_id_to_type[m->busid] = MP_BUS_MCA;
+#endif
+	} else
+		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
+}
+
+static int bad_ioapic(unsigned long address)
+{
+	if (nr_ioapics >= MAX_IO_APICS) {
+		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+		       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+	}
+	if (!address) {
+		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+		       " found in table, skipping!\n");
+		return 1;
+	}
+	return 0;
+}
+
+static void __init MP_ioapic_info(struct mpc_ioapic *m)
+{
+	if (!(m->flags & MPC_APIC_USABLE))
+		return;
+
+	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
+	       m->apicid, m->apicver, m->apicaddr);
+
+	if (bad_ioapic(m->apicaddr))
+		return;
+
+	mp_ioapics[nr_ioapics].apicaddr = m->apicaddr;
+	mp_ioapics[nr_ioapics].apicid = m->apicid;
+	mp_ioapics[nr_ioapics].type = m->type;
+	mp_ioapics[nr_ioapics].apicver = m->apicver;
+	mp_ioapics[nr_ioapics].flags = m->flags;
+	nr_ioapics++;
+}
+
+static void print_MP_intsrc_info(struct mpc_intsrc *m)
+{
+	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
+		m->srcbusirq, m->dstapic, m->dstirq);
+}
+
+static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
+{
+	apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		mp_irq->irqtype, mp_irq->irqflag & 3,
+		(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
+		mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_intsrc *m,
+				    struct mpc_intsrc *mp_irq)
+{
+	mp_irq->dstapic = m->dstapic;
+	mp_irq->type = m->type;
+	mp_irq->irqtype = m->irqtype;
+	mp_irq->irqflag = m->irqflag;
+	mp_irq->srcbus = m->srcbus;
+	mp_irq->srcbusirq = m->srcbusirq;
+	mp_irq->dstirq = m->dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mpc_intsrc *mp_irq,
+					struct mpc_intsrc *m)
+{
+	m->dstapic = mp_irq->dstapic;
+	m->type = mp_irq->type;
+	m->irqtype = mp_irq->irqtype;
+	m->irqflag = mp_irq->irqflag;
+	m->srcbus = mp_irq->srcbus;
+	m->srcbusirq = mp_irq->srcbusirq;
+	m->dstirq = mp_irq->dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mpc_intsrc *mp_irq,
+					struct mpc_intsrc *m)
+{
+	if (mp_irq->dstapic != m->dstapic)
+		return 1;
+	if (mp_irq->type != m->type)
+		return 2;
+	if (mp_irq->irqtype != m->irqtype)
+		return 3;
+	if (mp_irq->irqflag != m->irqflag)
+		return 4;
+	if (mp_irq->srcbus != m->srcbus)
+		return 5;
+	if (mp_irq->srcbusirq != m->srcbusirq)
+		return 6;
+	if (mp_irq->dstirq != m->dstirq)
+		return 7;
+
+	return 0;
+}
+
+static void __init MP_intsrc_info(struct mpc_intsrc *m)
+{
+	int i;
+
+	print_MP_intsrc_info(m);
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+			return;
+	}
+
+	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!!\n");
+}
+#else /* CONFIG_X86_IO_APIC */
+static inline void __init MP_bus_info(struct mpc_bus *m) {}
+static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
+static inline void __init MP_intsrc_info(struct mpc_intsrc *m) {}
+#endif /* CONFIG_X86_IO_APIC */
+
+
+static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
+{
+	apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
+		m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
+		m->srcbusirq, m->destapic, m->destapiclint);
+}
+
+/*
+ * Read/parse the MPC
+ */
+
+static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
+{
+
+	if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
+		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
+		       mpc->signature[0], mpc->signature[1],
+		       mpc->signature[2], mpc->signature[3]);
+		return 0;
+	}
+	if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
+		printk(KERN_ERR "MPTABLE: checksum error!\n");
+		return 0;
+	}
+	if (mpc->spec != 0x01 && mpc->spec != 0x04) {
+		printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
+		       mpc->spec);
+		return 0;
+	}
+	if (!mpc->lapic) {
+		printk(KERN_ERR "MPTABLE: null local APIC address!\n");
+		return 0;
+	}
+	memcpy(oem, mpc->oem, 8);
+	oem[8] = 0;
+	printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
+
+	memcpy(str, mpc->productid, 12);
+	str[12] = 0;
+
+	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
+
+#ifndef CONFIG_XEN
+	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
+#endif
+
+	return 1;
+}
+
+static void skip_entry(unsigned char **ptr, int *count, int size)
+{
+	*ptr += size;
+	*count += size;
+}
+
+static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
+{
+	printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
+		"type %x\n", *mpt);
+	print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+			1, mpc, mpc->length, 1);
+}
+
+void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { }
+
+static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+{
+	char str[16];
+	char oem[10];
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+#ifndef CONFIG_XEN
+#ifdef CONFIG_X86_32
+	generic_mps_oem_check(mpc, oem, str);
+#endif
+	/* save the local APIC address, it might be non-default */
+	if (!acpi_lapic)
+		mp_lapic_addr = mpc->lapic;
+#endif
+
+	if (early)
+		return 1;
+
+	if (mpc->oemptr)
+		x86_init.mpparse.smp_read_mpc_oem(mpc);
+
+	/*
+	 *      Now process the configuration blocks.
+	 */
+	x86_init.mpparse.mpc_record(0);
+
+	while (count < mpc->length) {
+		switch (*mpt) {
+		case MP_PROCESSOR:
+			/* ACPI may have already provided this data */
+			if (!acpi_lapic)
+				MP_processor_info((struct mpc_cpu *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
+			break;
+		case MP_BUS:
+			MP_bus_info((struct mpc_bus *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
+			break;
+		case MP_IOAPIC:
+			MP_ioapic_info((struct mpc_ioapic *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
+			break;
+		case MP_INTSRC:
+			MP_intsrc_info((struct mpc_intsrc *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
+			break;
+		case MP_LINTSRC:
+			MP_lintsrc_info((struct mpc_lintsrc *)mpt);
+			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
+			break;
+		default:
+			/* wrong mptable */
+			smp_dump_mptable(mpc, mpt);
+			count = mpc->length;
+			break;
+		}
+		x86_init.mpparse.mpc_record(1);
+	}
+
+	if (!num_processors)
+		printk(KERN_ERR "MPTABLE: no processors registered!\n");
+	return num_processors;
+}
+
+#ifdef CONFIG_X86_IO_APIC
+
+static int __init ELCR_trigger(unsigned int irq)
+{
+	unsigned int port;
+
+	port = 0x4d0 + (irq >> 3);
+	return (inb(port) >> (irq & 7)) & 1;
+}
+
+static void __init construct_default_ioirq_mptable(int mpc_default_type)
+{
+	struct mpc_intsrc intsrc;
+	int i;
+	int ELCR_fallback = 0;
+
+	intsrc.type = MP_INTSRC;
+	intsrc.irqflag = 0;	/* conforming */
+	intsrc.srcbus = 0;
+	intsrc.dstapic = mp_ioapics[0].apicid;
+
+	intsrc.irqtype = mp_INT;
+
+	/*
+	 *  If true, we have an ISA/PCI system with no IRQ entries
+	 *  in the MP table. To prevent the PCI interrupts from being set up
+	 *  incorrectly, we try to use the ELCR. The sanity check to see if
+	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
+	 *  never be level sensitive, so we simply see if the ELCR agrees.
+	 *  If it does, we assume it's valid.
+	 */
+	if (mpc_default_type == 5) {
+		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
+		       "falling back to ELCR\n");
+
+		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
+		    ELCR_trigger(13))
+			printk(KERN_ERR "ELCR contains invalid data... "
+			       "not using ELCR\n");
+		else {
+			printk(KERN_INFO
+			       "Using ELCR to identify PCI interrupts\n");
+			ELCR_fallback = 1;
+		}
+	}
+
+	for (i = 0; i < 16; i++) {
+		switch (mpc_default_type) {
+		case 2:
+			if (i == 0 || i == 13)
+				continue;	/* IRQ0 & IRQ13 not connected */
+			/* fall through */
+		default:
+			if (i == 2)
+				continue;	/* IRQ2 is never connected */
+		}
+
+		if (ELCR_fallback) {
+			/*
+			 *  If the ELCR indicates a level-sensitive interrupt, we
+			 *  copy that information over to the MP table in the
+			 *  irqflag field (level sensitive, active high polarity).
+			 */
+			if (ELCR_trigger(i))
+				intsrc.irqflag = 13;
+			else
+				intsrc.irqflag = 0;
+		}
+
+		intsrc.srcbusirq = i;
+		intsrc.dstirq = i ? i : 2;	/* IRQ0 to INTIN2 */
+		MP_intsrc_info(&intsrc);
+	}
+
+	intsrc.irqtype = mp_ExtINT;
+	intsrc.srcbusirq = 0;
+	intsrc.dstirq = 0;	/* 8259A to INTIN0 */
+	MP_intsrc_info(&intsrc);
+}
+
+
+static void __init construct_ioapic_table(int mpc_default_type)
+{
+	struct mpc_ioapic ioapic;
+	struct mpc_bus bus;
+
+	bus.type = MP_BUS;
+	bus.busid = 0;
+	switch (mpc_default_type) {
+	default:
+		printk(KERN_ERR "???\nUnknown standard configuration %d\n",
+		       mpc_default_type);
+		/* fall through */
+	case 1:
+	case 5:
+		memcpy(bus.bustype, "ISA   ", 6);
+		break;
+	case 2:
+	case 6:
+	case 3:
+		memcpy(bus.bustype, "EISA  ", 6);
+		break;
+	case 4:
+	case 7:
+		memcpy(bus.bustype, "MCA   ", 6);
+	}
+	MP_bus_info(&bus);
+	if (mpc_default_type > 4) {
+		bus.busid = 1;
+		memcpy(bus.bustype, "PCI   ", 6);
+		MP_bus_info(&bus);
+	}
+
+	ioapic.type	= MP_IOAPIC;
+	ioapic.apicid	= 2;
+	ioapic.apicver	= mpc_default_type > 4 ? 0x10 : 0x01;
+	ioapic.flags	= MPC_APIC_USABLE;
+	ioapic.apicaddr	= IO_APIC_DEFAULT_PHYS_BASE;
+	MP_ioapic_info(&ioapic);
+
+	/*
+	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
+	 */
+	construct_default_ioirq_mptable(mpc_default_type);
+}
+#else
+static inline void __init construct_ioapic_table(int mpc_default_type) { }
+#endif
+
+static inline void __init construct_default_ISA_mptable(int mpc_default_type)
+{
+	struct mpc_cpu processor;
+	struct mpc_lintsrc lintsrc;
+	int linttypes[2] = { mp_ExtINT, mp_NMI };
+	int i;
+
+#ifndef CONFIG_XEN
+	/*
+	 * local APIC has default address
+	 */
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+#endif
+
+	/*
+	 * 2 CPUs, numbered 0 & 1.
+	 */
+	processor.type = MP_PROCESSOR;
+	/* Either an integrated APIC or a discrete 82489DX. */
+	processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+	processor.cpuflag = CPU_ENABLED;
+	processor.cpufeature = (boot_cpu_data.x86 << 8) |
+	    (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+	processor.featureflag = boot_cpu_data.x86_capability[0];
+	processor.reserved[0] = 0;
+	processor.reserved[1] = 0;
+	for (i = 0; i < 2; i++) {
+		processor.apicid = i;
+		MP_processor_info(&processor);
+	}
+
+	construct_ioapic_table(mpc_default_type);
+
+	lintsrc.type = MP_LINTSRC;
+	lintsrc.irqflag = 0;		/* conforming */
+	lintsrc.srcbusid = 0;
+	lintsrc.srcbusirq = 0;
+	lintsrc.destapic = MP_APIC_ALL;
+	for (i = 0; i < 2; i++) {
+		lintsrc.irqtype = linttypes[i];
+		lintsrc.destapiclint = i;
+		MP_lintsrc_info(&lintsrc);
+	}
+}
+
+static struct mpf_intel *mpf_found;
+
+static unsigned long __init get_mpc_size(unsigned long physptr)
+{
+	struct mpc_table *mpc;
+	unsigned long size;
+
+	mpc = early_ioremap(physptr, PAGE_SIZE);
+	size = mpc->length;
+	early_iounmap(mpc, PAGE_SIZE);
+	apic_printk(APIC_VERBOSE, "  mpc: %lx-%lx\n", physptr, physptr + size);
+
+	return size;
+}
+
+static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
+{
+	struct mpc_table *mpc;
+	unsigned long size;
+
+	size = get_mpc_size(mpf->physptr);
+	mpc = early_ioremap(mpf->physptr, size);
+	/*
+	 * Read the physical hardware table.  Anything here will
+	 * override the defaults.
+	 */
+	if (!smp_read_mpc(mpc, early)) {
+#ifdef CONFIG_X86_LOCAL_APIC
+		smp_found_config = 0;
+#endif
+		printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
+			"... disabling SMP support. (tell your hw vendor)\n");
+		early_iounmap(mpc, size);
+		return -1;
+	}
+	early_iounmap(mpc, size);
+
+	if (early)
+		return -1;
+
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * If there are no explicit MP IRQ entries, then we are
+	 * broken.  We set up most of the low 16 IO-APIC pins to
+	 * ISA defaults and hope it will work.
+	 */
+	if (!mp_irq_entries) {
+		struct mpc_bus bus;
+
+		printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
+		       "using default mptable. (tell your hw vendor)\n");
+
+		bus.type = MP_BUS;
+		bus.busid = 0;
+		memcpy(bus.bustype, "ISA   ", 6);
+		MP_bus_info(&bus);
+
+		construct_default_ioirq_mptable(0);
+	}
+#endif
+
+	return 0;
+}
+
+/*
+ * Scan the memory blocks for an SMP configuration block.
+ */
+void __init default_get_smp_config(unsigned int early)
+{
+	struct mpf_intel *mpf = mpf_found;
+
+	if (!mpf)
+		return;
+
+	if (acpi_lapic && early)
+		return;
+
+	/*
+	 * MPS doesn't support hyperthreading, aka only have
+	 * thread 0 apic id in MPS table
+	 */
+	if (acpi_lapic && acpi_ioapic)
+		return;
+
+	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
+	       mpf->specification);
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+	if (mpf->feature2 & (1 << 7)) {
+		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
+		pic_mode = 1;
+	} else {
+		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
+		pic_mode = 0;
+	}
+#endif
+	/*
+	 * Now see if we need to read further.
+	 */
+	if (mpf->feature1 != 0) {
+		if (early) {
+#ifndef CONFIG_XEN
+			/*
+			 * local APIC has default address
+			 */
+			mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+#endif
+			return;
+		}
+
+		printk(KERN_INFO "Default MP configuration #%d\n",
+		       mpf->feature1);
+		construct_default_ISA_mptable(mpf->feature1);
+
+	} else if (mpf->physptr) {
+		if (check_physptr(mpf, early))
+			return;
+	} else
+		BUG();
+
+	if (!early)
+		printk(KERN_INFO "Processors: %d\n", num_processors);
+	/*
+	 * Only use the first configuration found.
+	 */
+}
+
+#ifndef CONFIG_XEN
+static void __init smp_reserve_bootmem(struct mpf_intel *mpf)
+{
+	unsigned long size = get_mpc_size(mpf->physptr);
+#ifdef CONFIG_X86_32
+	/*
+	 * We cannot access to MPC table to compute table size yet,
+	 * as only few megabytes from the bottom is mapped now.
+	 * PC-9800's MPC table places on the very last of physical
+	 * memory; so that simply reserving PAGE_SIZE from mpf->physptr
+	 * yields BUG() in reserve_bootmem.
+	 * also need to make sure physptr is below than max_low_pfn
+	 * we don't need reserve the area above max_low_pfn
+	 */
+	unsigned long end = max_low_pfn * PAGE_SIZE;
+
+	if (mpf->physptr < end) {
+		if (mpf->physptr + size > end)
+			size = end - mpf->physptr;
+		reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
+	}
+#else
+	reserve_bootmem_generic(mpf->physptr, size, BOOTMEM_DEFAULT);
+#endif
+}
+#endif
+
+static int __init smp_scan_config(unsigned long base, unsigned long length,
+				  unsigned reserve)
+{
+	unsigned int *bp = _bus_to_virt(base);
+	struct mpf_intel *mpf;
+
+	apic_printk(APIC_VERBOSE, "Scan SMP from %p for %ld bytes.\n",
+			bp, length);
+	BUILD_BUG_ON(sizeof(*mpf) != 16);
+
+	while (length > 0) {
+		mpf = (struct mpf_intel *)bp;
+		if ((*bp == SMP_MAGIC_IDENT) &&
+		    (mpf->length == 1) &&
+		    !mpf_checksum((unsigned char *)bp, 16) &&
+		    ((mpf->specification == 1)
+		     || (mpf->specification == 4))) {
+#ifdef CONFIG_X86_LOCAL_APIC
+			smp_found_config = 1;
+#endif
+			mpf_found = mpf;
+
+#ifndef CONFIG_XEN
+			printk(KERN_INFO "found SMP MP-table at [%p] %llx\n",
+			       mpf, (u64)virt_to_phys(mpf));
+
+			if (!reserve)
+				return 1;
+			reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf),
+						BOOTMEM_DEFAULT);
+			if (mpf->physptr)
+				smp_reserve_bootmem(mpf);
+#else
+			printk(KERN_INFO "found SMP MP-table at [%p] %08lx\n",
+			       mpf, ((void *)bp - _bus_to_virt(base)) + base);
+#endif
+			return 1;
+		}
+		bp += 4;
+		length -= 16;
+	}
+	return 0;
+}
+
+void __init default_find_smp_config(unsigned int reserve)
+{
+#ifndef CONFIG_XEN
+	unsigned int address;
+#endif
+
+	/*
+	 * FIXME: Linux assumes you have 640K of base ram..
+	 * this continues the error...
+	 *
+	 * 1) Scan the bottom 1K for a signature
+	 * 2) Scan the top 1K of base RAM
+	 * 3) Scan the 64K of bios
+	 */
+	if (smp_scan_config(0x0, 0x400, reserve) ||
+	    smp_scan_config(639 * 0x400, 0x400, reserve) ||
+	    smp_scan_config(0xF0000, 0x10000, reserve))
+		return;
+	/*
+	 * If it is an SMP machine we should know now, unless the
+	 * configuration is in an EISA/MCA bus machine with an
+	 * extended bios data area.
+	 *
+	 * there is a real-mode segmented pointer pointing to the
+	 * 4K EBDA area at 0x40E, calculate and scan it here.
+	 *
+	 * NOTE! There are Linux loaders that will corrupt the EBDA
+	 * area, and as such this kind of SMP config may be less
+	 * trustworthy, simply because the SMP table may have been
+	 * stomped on during early boot. These loaders are buggy and
+	 * should be fixed.
+	 *
+	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
+	 */
+
+#ifndef CONFIG_XEN
+	address = get_bios_ebda();
+	if (address)
+		smp_scan_config(address, 0x400, reserve);
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int  __init get_MP_intsrc_index(struct mpc_intsrc *m)
+{
+	int i;
+
+	if (m->irqtype != mp_INT)
+		return 0;
+
+	if (m->irqflag != 0x0f)
+		return 0;
+
+	/* not legacy */
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (mp_irqs[i].irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].irqflag != 0x0f)
+			continue;
+
+		if (mp_irqs[i].srcbus != m->srcbus)
+			continue;
+		if (mp_irqs[i].srcbusirq != m->srcbusirq)
+			continue;
+		if (irq_used[i]) {
+			/* already claimed */
+			return -2;
+		}
+		irq_used[i] = 1;
+		return i;
+	}
+
+	/* not found */
+	return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+
+static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
+{
+	int i;
+
+	apic_printk(APIC_VERBOSE, "OLD ");
+	print_MP_intsrc_info(m);
+
+	i = get_MP_intsrc_index(m);
+	if (i > 0) {
+		assign_to_mpc_intsrc(&mp_irqs[i], m);
+		apic_printk(APIC_VERBOSE, "NEW ");
+		print_mp_irq_info(&mp_irqs[i]);
+		return;
+	}
+	if (!i) {
+		/* legacy, do nothing */
+		return;
+	}
+	if (*nr_m_spare < SPARE_SLOT_NUM) {
+		/*
+		 * not found (-1), or duplicated (-2) are invalid entries,
+		 * we need to use the slot later
+		 */
+		m_spare[*nr_m_spare] = m;
+		*nr_m_spare += 1;
+	}
+}
+#else /* CONFIG_X86_IO_APIC */
+static
+inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
+#endif /* CONFIG_X86_IO_APIC */
+
+static int
+check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
+{
+	int ret = 0;
+
+	if (!mpc_new_phys || count <= mpc_new_length) {
+		WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
+		return -1;
+	}
+
+	return ret;
+}
+
+static int  __init replace_intsrc_all(struct mpc_table *mpc,
+					unsigned long mpc_new_phys,
+					unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+	int i;
+#endif
+	int count = sizeof(*mpc);
+	int nr_m_spare = 0;
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	printk(KERN_INFO "mpc_length %x\n", mpc->length);
+	while (count < mpc->length) {
+		switch (*mpt) {
+		case MP_PROCESSOR:
+			skip_entry(&mpt, &count, sizeof(struct mpc_cpu));
+			break;
+		case MP_BUS:
+			skip_entry(&mpt, &count, sizeof(struct mpc_bus));
+			break;
+		case MP_IOAPIC:
+			skip_entry(&mpt, &count, sizeof(struct mpc_ioapic));
+			break;
+		case MP_INTSRC:
+			check_irq_src((struct mpc_intsrc *)mpt, &nr_m_spare);
+			skip_entry(&mpt, &count, sizeof(struct mpc_intsrc));
+			break;
+		case MP_LINTSRC:
+			skip_entry(&mpt, &count, sizeof(struct mpc_lintsrc));
+			break;
+		default:
+			/* wrong mptable */
+			smp_dump_mptable(mpc, mpt);
+			goto out;
+		}
+	}
+
+#ifdef CONFIG_X86_IO_APIC
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (irq_used[i])
+			continue;
+
+		if (mp_irqs[i].irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].irqflag != 0x0f)
+			continue;
+
+		if (nr_m_spare > 0) {
+			apic_printk(APIC_VERBOSE, "*NEW* found\n");
+			nr_m_spare--;
+			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+			m_spare[nr_m_spare] = NULL;
+		} else {
+			struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+			count += sizeof(struct mpc_intsrc);
+			if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
+				goto out;
+			assign_to_mpc_intsrc(&mp_irqs[i], m);
+			mpc->length = count;
+			mpt += sizeof(struct mpc_intsrc);
+		}
+		print_mp_irq_info(&mp_irqs[i]);
+	}
+#endif
+out:
+	/* update checksum */
+	mpc->checksum = 0;
+	mpc->checksum -= mpf_checksum((unsigned char *)mpc, mpc->length);
+
+	return 0;
+}
+
+int enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
+	return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+	enable_update_mptable = 1;
+#ifdef CONFIG_PCI
+	pci_routeirq = 1;
+#endif
+	alloc_mptable = 1;
+	if (!p)
+		return 0;
+	mpc_new_length = memparse(p, &p);
+	return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+	if (enable_update_mptable && alloc_mptable) {
+		u64 startt = 0;
+#ifdef CONFIG_X86_TRAMPOLINE
+		startt = TRAMPOLINE_BASE;
+#endif
+		mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+	}
+}
+
+static int __init update_mp_table(void)
+{
+	char str[16];
+	char oem[10];
+	struct mpf_intel *mpf;
+	struct mpc_table *mpc, *mpc_new;
+
+	if (!enable_update_mptable)
+		return 0;
+
+	mpf = mpf_found;
+	if (!mpf)
+		return 0;
+
+	/*
+	 * Now see if we need to go further.
+	 */
+	if (mpf->feature1 != 0)
+		return 0;
+
+	if (!mpf->physptr)
+		return 0;
+
+	mpc = _bus_to_virt(mpf->physptr);
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+	printk(KERN_INFO "mpf: %llx\n", (u64)arbitrary_virt_to_machine(mpf));
+	printk(KERN_INFO "physptr: %x\n", mpf->physptr);
+
+	if (mpc_new_phys && mpc->length > mpc_new_length) {
+		mpc_new_phys = 0;
+		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+			 mpc_new_length);
+	}
+
+	if (!mpc_new_phys) {
+		unsigned char old, new;
+		/* check if we can change the postion */
+		mpc->checksum = 0;
+		old = mpf_checksum((unsigned char *)mpc, mpc->length);
+		mpc->checksum = 0xff;
+		new = mpf_checksum((unsigned char *)mpc, mpc->length);
+		if (old == new) {
+			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+			return 0;
+		}
+		printk(KERN_INFO "use in-positon replacing\n");
+	} else {
+		maddr_t mpc_new_bus;
+
+		mpc_new_bus = phys_to_machine(mpc_new_phys);
+		mpf->physptr = mpc_new_bus;
+		mpc_new = phys_to_virt(mpc_new_phys);
+		memcpy(mpc_new, mpc, mpc->length);
+		mpc = mpc_new;
+		/* check if we can modify that */
+		if (mpc_new_bus - mpf->physptr) {
+			struct mpf_intel *mpf_new;
+			/* steal 16 bytes from [0, 1k) */
+			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+			mpf_new = isa_bus_to_virt(0x400 - 16);
+			memcpy(mpf_new, mpf, 16);
+			mpf = mpf_new;
+			mpf->physptr = mpc_new_bus;
+		}
+		mpf->checksum = 0;
+		mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
+		printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
+	}
+
+	/*
+	 * only replace the one with mp_INT and
+	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+	 * may need pci=routeirq for all coverage
+	 */
+	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+	return 0;
+}
+
+late_initcall(update_mp_table);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/traps-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/traps-xen.c
@@ -0,0 +1,974 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
+ *
+ *  Pentium III FXSR, SSE support
+ *	Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+/*
+ * Handle hardware traps and faults.
+ */
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/spinlock.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/kdebug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kexec.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/bug.h>
+#include <linux/nmi.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_EISA
+#include <linux/ioport.h>
+#include <linux/eisa.h>
+#endif
+
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
+
+#if defined(CONFIG_EDAC)
+#include <linux/edac.h>
+#endif
+
+#include <asm/kmemcheck.h>
+#include <asm/stacktrace.h>
+#include <asm/processor.h>
+#include <asm/debugreg.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/nmi.h>
+#include <asm/desc.h>
+#include <asm/i387.h>
+#include <asm/mce.h>
+
+#include <asm/mach_traps.h>
+
+#ifdef CONFIG_X86_64
+#include <asm/x86_init.h>
+#include <asm/pgalloc.h>
+#include <asm/proto.h>
+#else
+#include <asm/processor-flags.h>
+#include <asm/setup.h>
+
+asmlinkage int system_call(void);
+
+/* Do we ignore FPU interrupts ? */
+char ignore_fpu_irq;
+
+#ifndef CONFIG_X86_NO_IDT
+/*
+ * The IDT has to be page-aligned to simplify the Pentium
+ * F0 0F bug workaround.
+ */
+gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
+#endif
+#endif
+
+#ifndef CONFIG_XEN
+DECLARE_BITMAP(used_vectors, NR_VECTORS);
+EXPORT_SYMBOL_GPL(used_vectors);
+#endif
+
+static int ignore_nmis;
+
+static inline void conditional_sti(struct pt_regs *regs)
+{
+	if (regs->flags & X86_EFLAGS_IF)
+		local_irq_enable();
+}
+
+static inline void preempt_conditional_sti(struct pt_regs *regs)
+{
+	inc_preempt_count();
+	if (regs->flags & X86_EFLAGS_IF)
+		local_irq_enable();
+}
+
+static inline void conditional_cli(struct pt_regs *regs)
+{
+	if (regs->flags & X86_EFLAGS_IF)
+		local_irq_disable();
+}
+
+static inline void preempt_conditional_cli(struct pt_regs *regs)
+{
+	if (regs->flags & X86_EFLAGS_IF)
+		local_irq_disable();
+	dec_preempt_count();
+}
+
+#ifdef CONFIG_X86_32
+static inline void
+die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode_vm(regs))
+		die(str, regs, err);
+}
+#endif
+
+static void __kprobes
+do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
+	long error_code, siginfo_t *info)
+{
+	struct task_struct *tsk = current;
+
+#ifdef CONFIG_X86_32
+	if (regs->flags & X86_VM_MASK) {
+		/*
+		 * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
+		 * On nmi (interrupt 2), do_trap should not be called.
+		 */
+		if (trapnr < 6)
+			goto vm86_trap;
+		goto trap_signal;
+	}
+#endif
+
+	if (!user_mode(regs))
+		goto kernel_trap;
+
+#ifdef CONFIG_X86_32
+trap_signal:
+#endif
+	/*
+	 * We want error_code and trap_no set for userspace faults and
+	 * kernelspace faults which result in die(), but not
+	 * kernelspace faults which are fixed up.  die() gives the
+	 * process no chance to handle the signal and notice the
+	 * kernel fault information, so that won't result in polluting
+	 * the information about previously queued, but not yet
+	 * delivered, faults.  See also do_general_protection below.
+	 */
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = trapnr;
+
+#ifdef CONFIG_X86_64
+	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
+	    printk_ratelimit()) {
+		printk(KERN_INFO
+		       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+		       tsk->comm, tsk->pid, str,
+		       regs->ip, regs->sp, error_code);
+		print_vma_addr(" in ", regs->ip);
+		printk("\n");
+	}
+#endif
+
+	if (info)
+		force_sig_info(signr, info, tsk);
+	else
+		force_sig(signr, tsk);
+	return;
+
+kernel_trap:
+	if (!fixup_exception(regs)) {
+		tsk->thread.error_code = error_code;
+		tsk->thread.trap_no = trapnr;
+		die(str, regs, error_code);
+	}
+	return;
+
+#ifdef CONFIG_X86_32
+vm86_trap:
+	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
+						error_code, trapnr))
+		goto trap_signal;
+	return;
+#endif
+}
+
+#define DO_ERROR(trapnr, signr, str, name)				\
+dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
+{									\
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+							== NOTIFY_STOP)	\
+		return;							\
+	conditional_sti(regs);						\
+	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
+}
+
+#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
+dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
+{									\
+	siginfo_t info;							\
+	info.si_signo = signr;						\
+	info.si_errno = 0;						\
+	info.si_code = sicode;						\
+	info.si_addr = (void __user *)siaddr;				\
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
+							== NOTIFY_STOP)	\
+		return;							\
+	conditional_sti(regs);						\
+	do_trap(trapnr, signr, str, regs, error_code, &info);		\
+}
+
+DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+DO_ERROR(4, SIGSEGV, "overflow", overflow)
+DO_ERROR(5, SIGSEGV, "bounds", bounds)
+DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
+DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+#ifdef CONFIG_X86_32
+DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+#endif
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+
+#ifdef CONFIG_X86_64
+/* Runs on IST stack */
+dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
+{
+	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
+			12, SIGBUS) == NOTIFY_STOP)
+		return;
+	preempt_conditional_sti(regs);
+	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL);
+	preempt_conditional_cli(regs);
+}
+
+dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
+{
+	static const char str[] = "double fault";
+	struct task_struct *tsk = current;
+
+	/* Return not checked because double check cannot be ignored */
+	notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
+
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = 8;
+
+	/*
+	 * This is always a kernel trap and never fixable (and thus must
+	 * never return).
+	 */
+	for (;;)
+		die(str, regs, error_code);
+}
+#endif
+
+dotraplinkage void __kprobes
+do_general_protection(struct pt_regs *regs, long error_code)
+{
+	struct task_struct *tsk;
+
+	conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+	if (regs->flags & X86_VM_MASK)
+		goto gp_in_vm86;
+#endif
+
+	tsk = current;
+	if (!user_mode(regs))
+		goto gp_in_kernel;
+
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = 13;
+
+	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+			printk_ratelimit()) {
+		printk(KERN_INFO
+			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
+			tsk->comm, task_pid_nr(tsk),
+			regs->ip, regs->sp, error_code);
+		print_vma_addr(" in ", regs->ip);
+		printk("\n");
+	}
+
+	force_sig(SIGSEGV, tsk);
+	return;
+
+#ifdef CONFIG_X86_32
+gp_in_vm86:
+	local_irq_enable();
+	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
+	return;
+#endif
+
+gp_in_kernel:
+	if (fixup_exception(regs))
+		return;
+
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = 13;
+	if (notify_die(DIE_GPF, "general protection fault", regs,
+				error_code, 13, SIGSEGV) == NOTIFY_STOP)
+		return;
+	die("general protection fault", regs, error_code);
+}
+
+static notrace __kprobes void
+mem_parity_error(unsigned char reason, struct pt_regs *regs)
+{
+	printk(KERN_EMERG
+		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+			reason, smp_processor_id());
+
+	printk(KERN_EMERG
+		"You have some hardware problem, likely on the PCI bus.\n");
+
+#if defined(CONFIG_EDAC)
+	if (edac_handler_set()) {
+		edac_atomic_assert_error();
+		return;
+	}
+#endif
+
+	if (panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+
+	/* Clear and disable the memory parity error line. */
+	clear_mem_error(reason);
+}
+
+static notrace __kprobes void
+io_check_error(unsigned char reason, struct pt_regs *regs)
+{
+	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+	show_registers(regs);
+
+	if (panic_on_io_nmi)
+		panic("NMI IOCK error: Not continuing");
+
+	/* Re-enable the IOCK line, wait for a few seconds */
+	clear_io_check_error(reason);
+}
+
+static notrace __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs *regs)
+{
+	if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) ==
+			NOTIFY_STOP)
+		return;
+#ifdef CONFIG_MCA
+	/*
+	 * Might actually be able to figure out what the guilty party
+	 * is:
+	 */
+	if (MCA_bus) {
+		mca_handle_nmi();
+		return;
+	}
+#endif
+	printk(KERN_EMERG
+		"Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+			reason, smp_processor_id());
+
+	printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+	if (panic_on_unrecovered_nmi)
+		panic("NMI: Not continuing");
+
+	printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
+}
+
+static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
+{
+	unsigned char reason = 0;
+	int cpu;
+
+	cpu = smp_processor_id();
+
+	/* Only the BSP gets external NMIs from the system. */
+	if (!cpu)
+		reason = get_nmi_reason();
+
+	if (!(reason & 0xc0)) {
+		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
+								== NOTIFY_STOP)
+			return;
+#ifdef CONFIG_X86_LOCAL_APIC
+#ifdef ARCH_HAS_NMI_WATCHDOG
+		/*
+		 * Ok, so this is none of the documented NMI sources,
+		 * so it must be the NMI watchdog.
+		 */
+		if (nmi_watchdog_tick(regs, reason))
+			return;
+#endif
+		if (!do_nmi_callback(regs, cpu))
+			unknown_nmi_error(reason, regs);
+#else
+		unknown_nmi_error(reason, regs);
+#endif
+
+		return;
+	}
+	if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
+		return;
+
+	/* AK: following checks seem to be broken on modern chipsets. FIXME */
+	if (reason & 0x80)
+		mem_parity_error(reason, regs);
+	if (reason & 0x40)
+		io_check_error(reason, regs);
+#ifdef CONFIG_X86_32
+	/*
+	 * Reassert NMI in case it became active meanwhile
+	 * as it's edge-triggered:
+	 */
+	reassert_nmi();
+#endif
+}
+
+dotraplinkage notrace __kprobes void
+do_nmi(struct pt_regs *regs, long error_code)
+{
+	nmi_enter();
+
+	inc_irq_stat(__nmi_count);
+
+	if (!ignore_nmis)
+		default_do_nmi(regs);
+
+	nmi_exit();
+}
+
+void stop_nmi(void)
+{
+	acpi_nmi_disable();
+	ignore_nmis++;
+}
+
+void restart_nmi(void)
+{
+	ignore_nmis--;
+	acpi_nmi_enable();
+}
+
+/* May run on IST stack. */
+dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
+{
+#ifdef CONFIG_KPROBES
+	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+			== NOTIFY_STOP)
+		return;
+#else
+	if (notify_die(DIE_TRAP, "int3", regs, error_code, 3, SIGTRAP)
+			== NOTIFY_STOP)
+		return;
+#endif
+
+	preempt_conditional_sti(regs);
+	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
+	preempt_conditional_cli(regs);
+}
+
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+/*
+ * Help handler running on IST stack to switch back to user stack
+ * for scheduling or signal handling. The actual stack switch is done in
+ * entry.S
+ */
+asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
+{
+	struct pt_regs *regs = eregs;
+	/* Did already sync */
+	if (eregs == (struct pt_regs *)eregs->sp)
+		;
+	/* Exception from user space */
+	else if (user_mode(eregs))
+		regs = task_pt_regs(current);
+	/*
+	 * Exception from kernel and interrupts are enabled. Move to
+	 * kernel process stack.
+	 */
+	else if (eregs->flags & X86_EFLAGS_IF)
+		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
+	if (eregs != regs)
+		*regs = *eregs;
+	return regs;
+}
+#endif
+
+/*
+ * Our handling of the processor debug registers is non-trivial.
+ * We do not clear them on entry and exit from the kernel. Therefore
+ * it is possible to get a watchpoint trap here from inside the kernel.
+ * However, the code in ./ptrace.c has ensured that the user can
+ * only set watchpoints on userspace addresses. Therefore the in-kernel
+ * watchpoint trap can only occur in code which is reading/writing
+ * from user space. Such code must not hold kernel locks (since it
+ * can equally take a page fault), therefore it is safe to call
+ * force_sig_info even though that claims and releases locks.
+ *
+ * Code in ./signal.c ensures that the debug control register
+ * is restored before we deliver any signal, and therefore that
+ * user code runs with the correct debug control register even though
+ * we clear it here.
+ *
+ * Being careful here means that we don't have to be as careful in a
+ * lot of more complicated places (task switching can be a bit lazy
+ * about restoring all the debug state, and ptrace doesn't have to
+ * find every occurrence of the TF bit that could be saved away even
+ * by user code)
+ *
+ * May run on IST stack.
+ */
+dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
+{
+	struct task_struct *tsk = current;
+	unsigned long condition;
+	int si_code;
+
+	get_debugreg(condition, 6);
+
+	/* Catch kmemcheck conditions first of all! */
+	if (condition & DR_STEP && kmemcheck_trap(regs))
+		return;
+
+	/*
+	 * The processor cleared BTF, so don't mark that we need it set.
+	 */
+	clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
+	tsk->thread.debugctlmsr = 0;
+
+	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+						SIGTRAP) == NOTIFY_STOP)
+		return;
+
+	/* It's safe to allow irq's after DR6 has been saved */
+	preempt_conditional_sti(regs);
+
+	/* Mask out spurious debug traps due to lazy DR7 setting */
+	if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+		if (!tsk->thread.debugreg7)
+			goto clear_dr7;
+	}
+
+#ifdef CONFIG_X86_32
+	if (regs->flags & X86_VM_MASK)
+		goto debug_vm86;
+#endif
+
+	/* Save debug status register where ptrace can see it */
+	tsk->thread.debugreg6 = condition;
+
+	/*
+	 * Single-stepping through TF: make sure we ignore any events in
+	 * kernel space (but re-enable TF when returning to user mode).
+	 */
+	if (condition & DR_STEP) {
+		if (!user_mode(regs))
+			goto clear_TF_reenable;
+	}
+
+	si_code = get_si_code(condition);
+	/* Ok, finally something we can handle */
+	send_sigtrap(tsk, regs, error_code, si_code);
+
+	/*
+	 * Disable additional traps. They'll be re-enabled when
+	 * the signal is delivered.
+	 */
+clear_dr7:
+	set_debugreg(0, 7);
+	preempt_conditional_cli(regs);
+	return;
+
+#ifdef CONFIG_X86_32
+debug_vm86:
+	/* reenable preemption: handle_vm86_trap() might sleep */
+	dec_preempt_count();
+	handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+	conditional_cli(regs);
+	return;
+#endif
+
+clear_TF_reenable:
+	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+	regs->flags &= ~X86_EFLAGS_TF;
+	preempt_conditional_cli(regs);
+	return;
+}
+
+#ifdef CONFIG_X86_64
+static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
+{
+	if (fixup_exception(regs))
+		return 1;
+
+	notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
+	/* Illegal floating point operation in the kernel */
+	current->thread.trap_no = trapnr;
+	die(str, regs, 0);
+	return 0;
+}
+#endif
+
+/*
+ * Note that we play around with the 'TS' bit in an attempt to get
+ * the correct behaviour even in the presence of the asynchronous
+ * IRQ13 behaviour
+ */
+void math_error(void __user *ip)
+{
+	struct task_struct *task;
+	siginfo_t info;
+	unsigned short cwd, swd, err;
+
+	/*
+	 * Save the info for the exception handler and clear the error.
+	 */
+	task = current;
+	save_init_fpu(task);
+	task->thread.trap_no = 16;
+	task->thread.error_code = 0;
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_addr = ip;
+	/*
+	 * (~cwd & swd) will mask out exceptions that are not set to unmasked
+	 * status.  0x3f is the exception bits in these regs, 0x200 is the
+	 * C1 reg you need in case of a stack fault, 0x040 is the stack
+	 * fault bit.  We should only be taking one exception at a time,
+	 * so if this combination doesn't produce any single exception,
+	 * then we have a bad program that isn't synchronizing its FPU usage
+	 * and it will suffer the consequences since we won't be able to
+	 * fully reproduce the context of the exception
+	 */
+	cwd = get_fpu_cwd(task);
+	swd = get_fpu_swd(task);
+
+	err = swd & ~cwd;
+
+	if (err & 0x001) {	/* Invalid op */
+		/*
+		 * swd & 0x240 == 0x040: Stack Underflow
+		 * swd & 0x240 == 0x240: Stack Overflow
+		 * User must clear the SF bit (0x40) if set
+		 */
+		info.si_code = FPE_FLTINV;
+	} else if (err & 0x004) { /* Divide by Zero */
+		info.si_code = FPE_FLTDIV;
+	} else if (err & 0x008) { /* Overflow */
+		info.si_code = FPE_FLTOVF;
+	} else if (err & 0x012) { /* Denormal, Underflow */
+		info.si_code = FPE_FLTUND;
+	} else if (err & 0x020) { /* Precision */
+		info.si_code = FPE_FLTRES;
+	} else {
+		/*
+		 * If we're using IRQ 13, or supposedly even some trap 16
+		 * implementations, it's possible we get a spurious trap...
+		 */
+		return;		/* Spurious trap, no error */
+	}
+	force_sig_info(SIGFPE, &info, task);
+}
+
+dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
+{
+	conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+	ignore_fpu_irq = 1;
+#else
+	if (!user_mode(regs) &&
+	    kernel_math_error(regs, "kernel x87 math error", 16))
+		return;
+#endif
+
+	math_error((void __user *)regs->ip);
+}
+
+static void simd_math_error(void __user *ip)
+{
+	struct task_struct *task;
+	siginfo_t info;
+	unsigned short mxcsr;
+
+	/*
+	 * Save the info for the exception handler and clear the error.
+	 */
+	task = current;
+	save_init_fpu(task);
+	task->thread.trap_no = 19;
+	task->thread.error_code = 0;
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_code = __SI_FAULT;
+	info.si_addr = ip;
+	/*
+	 * The SIMD FPU exceptions are handled a little differently, as there
+	 * is only a single status/control register.  Thus, to determine which
+	 * unmasked exception was caught we must mask the exception mask bits
+	 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+	 */
+	mxcsr = get_fpu_mxcsr(task);
+	switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+	case 0x000:
+	default:
+		break;
+	case 0x001: /* Invalid Op */
+		info.si_code = FPE_FLTINV;
+		break;
+	case 0x002: /* Denormalize */
+	case 0x010: /* Underflow */
+		info.si_code = FPE_FLTUND;
+		break;
+	case 0x004: /* Zero Divide */
+		info.si_code = FPE_FLTDIV;
+		break;
+	case 0x008: /* Overflow */
+		info.si_code = FPE_FLTOVF;
+		break;
+	case 0x020: /* Precision */
+		info.si_code = FPE_FLTRES;
+		break;
+	}
+	force_sig_info(SIGFPE, &info, task);
+}
+
+dotraplinkage void
+do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
+{
+	conditional_sti(regs);
+
+#ifdef CONFIG_X86_32
+	if (cpu_has_xmm) {
+		/* Handle SIMD FPU exceptions on PIII+ processors. */
+		ignore_fpu_irq = 1;
+		simd_math_error((void __user *)regs->ip);
+		return;
+	}
+	/*
+	 * Handle strange cache flush from user space exception
+	 * in all other cases.  This is undocumented behaviour.
+	 */
+	if (regs->flags & X86_VM_MASK) {
+		handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
+		return;
+	}
+	current->thread.trap_no = 19;
+	current->thread.error_code = error_code;
+	die_if_kernel("cache flush denied", regs, error_code);
+	force_sig(SIGSEGV, current);
+#else
+	if (!user_mode(regs) &&
+			kernel_math_error(regs, "kernel simd math error", 19))
+		return;
+	simd_math_error((void __user *)regs->ip);
+#endif
+}
+
+#ifndef CONFIG_XEN
+dotraplinkage void
+do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
+{
+	conditional_sti(regs);
+#if 0
+	/* No need to warn about this any longer. */
+	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+#endif
+}
+
+asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+{
+}
+
+asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
+{
+}
+#endif /* CONFIG_XEN */
+
+/*
+ * __math_state_restore assumes that cr0.TS is already clear and the
+ * fpu state is all ready for use.  Used during context switch.
+ */
+void __math_state_restore(void)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = thread->task;
+
+	/*
+	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
+	 */
+	if (unlikely(restore_fpu_checking(tsk))) {
+		stts();
+		force_sig(SIGSEGV, tsk);
+		return;
+	}
+
+	thread->status |= TS_USEDFPU;	/* So we fnsave on switch_to() */
+	tsk->fpu_counter++;
+}
+
+/*
+ * 'math_state_restore()' saves the current math information in the
+ * old math state array, and gets the new ones from the current task
+ *
+ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+ * Don't touch unless you *really* know how it works.
+ *
+ * Must be called with kernel preemption disabled (in this case,
+ * local interrupts are disabled at the call-site in entry.S).
+ */
+asmlinkage void math_state_restore(void)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = thread->task;
+
+	if (!tsk_used_math(tsk)) {
+		local_irq_enable();
+		/*
+		 * does a slab alloc which can sleep
+		 */
+		if (init_fpu(tsk)) {
+			/*
+			 * ran out of memory!
+			 */
+			do_group_exit(SIGKILL);
+			return;
+		}
+		local_irq_disable();
+	}
+
+	/* NB. 'clts' is done for us by Xen during virtual trap. */
+	__math_state_restore();
+}
+EXPORT_SYMBOL_GPL(math_state_restore);
+
+#ifndef CONFIG_MATH_EMULATION
+void math_emulate(struct math_emu_info *info)
+{
+	printk(KERN_EMERG
+		"math-emulation not enabled and no coprocessor found.\n");
+	printk(KERN_EMERG "killing %s.\n", current->comm);
+	force_sig(SIGFPE, current);
+	schedule();
+}
+#endif /* CONFIG_MATH_EMULATION */
+
+dotraplinkage void __kprobes
+do_device_not_available(struct pt_regs *regs, long error_code)
+{
+#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+	if (read_cr0() & X86_CR0_EM) {
+		struct math_emu_info info = { };
+
+		conditional_sti(regs);
+
+		info.regs = regs;
+		math_emulate(&info);
+	} else {
+		math_state_restore(); /* interrupts still off */
+		conditional_sti(regs);
+	}
+#else
+	math_state_restore();
+#endif
+}
+
+#ifdef CONFIG_X86_32
+dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
+{
+	siginfo_t info;
+	local_irq_enable();
+
+	info.si_signo = SIGILL;
+	info.si_errno = 0;
+	info.si_code = ILL_BADSTK;
+	info.si_addr = NULL;
+	if (notify_die(DIE_TRAP, "iret exception",
+			regs, error_code, 32, SIGILL) == NOTIFY_STOP)
+		return;
+	do_trap(32, SIGILL, "iret exception", regs, error_code, &info);
+}
+#endif
+
+/*
+ * 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 const trap_info_t __cpuinitconst trap_table[] = {
+#ifdef CONFIG_X86_32
+#define X 0
+#else
+#define X 4
+#endif
+	{  0, 0|X, __KERNEL_CS, (unsigned long)divide_error		},
+	{  1, 0|4, __KERNEL_CS, (unsigned long)debug			},
+	{  3, 3|4, __KERNEL_CS, (unsigned long)int3			},
+	{  4, 3|X, __KERNEL_CS, (unsigned long)overflow			},
+	{  5, 0|X, __KERNEL_CS, (unsigned long)bounds			},
+	{  6, 0|X, __KERNEL_CS, (unsigned long)invalid_op		},
+	{  7, 0|4, __KERNEL_CS, (unsigned long)device_not_available	},
+	{  9, 0|X, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+	{ 10, 0|X, __KERNEL_CS, (unsigned long)invalid_TSS		},
+	{ 11, 0|X, __KERNEL_CS, (unsigned long)segment_not_present	},
+	{ 12, 0|X, __KERNEL_CS, (unsigned long)stack_segment		},
+	{ 13, 0|X, __KERNEL_CS, (unsigned long)general_protection	},
+	{ 14, 0|4, __KERNEL_CS, (unsigned long)page_fault		},
+	{ 16, 0|X, __KERNEL_CS, (unsigned long)coprocessor_error	},
+	{ 17, 0|X, __KERNEL_CS, (unsigned long)alignment_check		},
+#ifdef CONFIG_X86_MCE
+	{ 18, 0|X, __KERNEL_CS, (unsigned long)machine_check		},
+#endif
+	{ 19, 0|X, __KERNEL_CS, (unsigned long)simd_coprocessor_error	},
+#ifdef CONFIG_X86_32
+	{ 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment		},
+	{ SYSCALL_VECTOR,  3, __KERNEL_CS, (unsigned long)system_call	},
+#elif defined(CONFIG_IA32_EMULATION)
+	{ IA32_SYSCALL_VECTOR, 3, __KERNEL_CS, (unsigned long)ia32_syscall },
+#endif
+	{  0, 0,	   0, 0						}
+};
+
+void __init trap_init(void)
+{
+	int ret;
+
+	ret = HYPERVISOR_set_trap_table(trap_table);
+	if (ret)
+		printk("HYPERVISOR_set_trap_table failed (%d)\n", ret);
+
+#ifdef CONFIG_X86_32
+	if (cpu_has_fxsr) {
+		printk(KERN_INFO "Enabling fast FPU save and restore... ");
+		set_in_cr4(X86_CR4_OSFXSR);
+		printk("done.\n");
+	}
+	if (cpu_has_xmm) {
+		printk(KERN_INFO
+			"Enabling unmasked SIMD FPU exception support... ");
+		set_in_cr4(X86_CR4_OSXMMEXCPT);
+		printk("done.\n");
+	}
+
+#endif
+	/*
+	 * Should be a barrier for any external CPU state:
+	 */
+	cpu_init();
+
+	x86_init.irqs.trap_init();
+}
+
+void __cpuinit smp_trap_init(trap_info_t *trap_ctxt)
+{
+	const trap_info_t *t = trap_table;
+
+	for (t = trap_table; t->address; t++) {
+		trap_ctxt[t->vector].flags = t->flags;
+		trap_ctxt[t->vector].cs = t->cs;
+		trap_ctxt[t->vector].address = t->address;
+	}
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/Makefile
@@ -18,8 +18,6 @@
 obj-$(CONFIG_X86_32)	+= bugs.o cmpxchg.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
 
-obj-$(CONFIG_X86_CPU_DEBUG)		+= cpu_debug.o
-
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
 obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o
 obj-$(CONFIG_CPU_SUP_CYRIX_32)		+= cyrix.o
@@ -35,6 +33,8 @@
 
 obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o
 
+disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o perfctr-watchdog.o
+
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -18,6 +18,7 @@
 #include <asm/processor.h>
 #include <linux/smp.h>
 #include <asm/k8.h>
+#include <asm/smp.h>
 
 #define LVL_1_INST	1
 #define LVL_1_DATA	2
@@ -94,7 +95,7 @@
 	{ 0xd1, LVL_3,    1024 },	/* 4-way set assoc, 64 byte line size */
 	{ 0xd2, LVL_3,    2048 },	/* 4-way set assoc, 64 byte line size */
 	{ 0xd6, LVL_3,    1024 },	/* 8-way set assoc, 64 byte line size */
-	{ 0xd7, LVL_3,    2038 },	/* 8-way set assoc, 64 byte line size */
+	{ 0xd7, LVL_3,    2048 },	/* 8-way set assoc, 64 byte line size */
 	{ 0xd8, LVL_3,    4096 },	/* 12-way set assoc, 64 byte line size */
 	{ 0xdc, LVL_3,    2048 },	/* 12-way set assoc, 64 byte line size */
 	{ 0xdd, LVL_3,    4096 },	/* 12-way set assoc, 64 byte line size */
@@ -102,6 +103,9 @@
 	{ 0xe2, LVL_3,    2048 },	/* 16-way set assoc, 64 byte line size */
 	{ 0xe3, LVL_3,    4096 },	/* 16-way set assoc, 64 byte line size */
 	{ 0xe4, LVL_3,    8192 },	/* 16-way set assoc, 64 byte line size */
+	{ 0xea, LVL_3,    12288 },	/* 24-way set assoc, 64 byte line size */
+	{ 0xeb, LVL_3,    18432 },	/* 24-way set assoc, 64 byte line size */
+	{ 0xec, LVL_3,    24576 },	/* 24-way set assoc, 64 byte line size */
 	{ 0x00, 0, 0}
 };
 
@@ -147,7 +151,8 @@
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	unsigned long can_disable;
+	bool can_disable;
+	unsigned int l3_indices;
 	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
 };
 
@@ -157,7 +162,8 @@
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	unsigned long can_disable;
+	bool can_disable;
+	unsigned int l3_indices;
 };
 
 unsigned short			num_cache_leaves;
@@ -287,6 +293,36 @@
 		(ebx->split.ways_of_associativity + 1) - 1;
 }
 
+struct _cache_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct _cpuid4_info *, char *);
+	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+};
+
+#if defined(CONFIG_CPU_SUP_AMD) && !defined(CONFIG_XEN)
+static unsigned int __cpuinit amd_calc_l3_indices(void)
+{
+	/*
+	 * We're called over smp_call_function_single() and therefore
+	 * are on the correct cpu.
+	 */
+	int cpu = smp_processor_id();
+	int node = cpu_to_node(cpu);
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	unsigned int sc0, sc1, sc2, sc3;
+	u32 val = 0;
+
+	pci_read_config_dword(dev, 0x1C4, &val);
+
+	/* calculate subcache sizes */
+	sc0 = !(val & BIT(0));
+	sc1 = !(val & BIT(4));
+	sc2 = !(val & BIT(8))  + !(val & BIT(9));
+	sc3 = !(val & BIT(12)) + !(val & BIT(13));
+
+	return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+}
+
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
@@ -296,13 +332,108 @@
 	if (boot_cpu_data.x86 == 0x11)
 		return;
 
-	/* see erratum #382 */
-	if ((boot_cpu_data.x86 == 0x10) && (boot_cpu_data.x86_model < 0x8))
+	/* see errata #382 and #388 */
+	if ((boot_cpu_data.x86 == 0x10) &&
+	    ((boot_cpu_data.x86_model < 0x8) ||
+	     (boot_cpu_data.x86_mask  < 0x1)))
 		return;
 
-	this_leaf->can_disable = 1;
+	/* not in virtualized environments */
+	if (num_k8_northbridges == 0)
+		return;
+
+	this_leaf->can_disable = true;
+	this_leaf->l3_indices  = amd_calc_l3_indices();
+}
+
+static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
+				  unsigned int index)
+{
+	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+	int node = amd_get_nb_id(cpu);
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	unsigned int reg = 0;
+
+	if (!this_leaf->can_disable)
+		return -EINVAL;
+
+	if (!dev)
+		return -EINVAL;
+
+	pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
+	return sprintf(buf, "0x%08x\n", reg);
+}
+
+#define SHOW_CACHE_DISABLE(index)					\
+static ssize_t								\
+show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf)	\
+{									\
+	return show_cache_disable(this_leaf, buf, index);		\
+}
+SHOW_CACHE_DISABLE(0)
+SHOW_CACHE_DISABLE(1)
+
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
+	const char *buf, size_t count, unsigned int index)
+{
+	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
+	int node = amd_get_nb_id(cpu);
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	unsigned long val = 0;
+
+#define SUBCACHE_MASK	(3UL << 20)
+#define SUBCACHE_INDEX	0xfff
+
+	if (!this_leaf->can_disable)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	/* do not allow writes outside of allowed bits */
+	if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
+	    ((val & SUBCACHE_INDEX) > this_leaf->l3_indices))
+		return -EINVAL;
+
+	val |= BIT(30);
+	pci_write_config_dword(dev, 0x1BC + index * 4, val);
+	/*
+	 * We need to WBINVD on a core on the node containing the L3 cache which
+	 * indices we disable therefore a simple wbinvd() is not sufficient.
+	 */
+	wbinvd_on_cpu(cpu);
+	pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31));
+	return count;
 }
 
+#define STORE_CACHE_DISABLE(index)					\
+static ssize_t								\
+store_cache_disable_##index(struct _cpuid4_info *this_leaf,		\
+			    const char *buf, size_t count)		\
+{									\
+	return store_cache_disable(this_leaf, buf, count, index);	\
+}
+STORE_CACHE_DISABLE(0)
+STORE_CACHE_DISABLE(1)
+
+static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
+		show_cache_disable_0, store_cache_disable_0);
+static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
+		show_cache_disable_1, store_cache_disable_1);
+
+#else	/* CONFIG_CPU_SUP_AMD */
+static void __cpuinit
+amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
+{
+};
+#endif /* CONFIG_CPU_SUP_AMD */
+
 static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
 				   struct _cpuid4_info_regs *this_leaf)
@@ -515,23 +646,24 @@
 static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
 #define CPUID4_INFO_IDX(x, y)	(&((per_cpu(cpuid4_info, x))[y]))
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
 {
 	struct _cpuid4_info	*this_leaf, *sibling_leaf;
 	unsigned long num_threads_sharing;
-	int index_msb, i;
+	int index_msb, i, sibling;
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
-		struct cpuinfo_x86 *d;
-		for_each_online_cpu(i) {
+		for_each_cpu(i, c->llc_shared_map) {
 			if (!per_cpu(cpuid4_info, i))
 				continue;
-			d = &cpu_data(i);
 			this_leaf = CPUID4_INFO_IDX(i, index);
-			cpumask_copy(to_cpumask(this_leaf->shared_cpu_map),
-				     d->llc_shared_map);
+			for_each_cpu(sibling, c->llc_shared_map) {
+				if (!cpu_online(sibling))
+					continue;
+				set_bit(sibling, this_leaf->shared_cpu_map);
+			}
 		}
 		return;
 	}
@@ -723,82 +855,6 @@
 #define to_object(k)	container_of(k, struct _index_kobject, kobj)
 #define to_attr(a)	container_of(a, struct _cache_attr, attr)
 
-static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
-				  unsigned int index)
-{
-	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = cpu_to_node(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
-	unsigned int reg = 0;
-
-	if (!this_leaf->can_disable)
-		return -EINVAL;
-
-	if (!dev)
-		return -EINVAL;
-
-	pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
-	return sprintf(buf, "%x\n", reg);
-}
-
-#define SHOW_CACHE_DISABLE(index)					\
-static ssize_t								\
-show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf)  	\
-{									\
-	return show_cache_disable(this_leaf, buf, index);		\
-}
-SHOW_CACHE_DISABLE(0)
-SHOW_CACHE_DISABLE(1)
-
-static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
-	const char *buf, size_t count, unsigned int index)
-{
-	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = cpu_to_node(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
-	unsigned long val = 0;
-	unsigned int scrubber = 0;
-
-	if (!this_leaf->can_disable)
-		return -EINVAL;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (!dev)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &val) < 0)
-		return -EINVAL;
-
-	val |= 0xc0000000;
-
-	pci_read_config_dword(dev, 0x58, &scrubber);
-	scrubber &= ~0x1f000000;
-	pci_write_config_dword(dev, 0x58, scrubber);
-
-	pci_write_config_dword(dev, 0x1BC + index * 4, val & ~0x40000000);
-	wbinvd();
-	pci_write_config_dword(dev, 0x1BC + index * 4, val);
-	return count;
-}
-
-#define STORE_CACHE_DISABLE(index)					\
-static ssize_t								\
-store_cache_disable_##index(struct _cpuid4_info *this_leaf,	     	\
-			    const char *buf, size_t count)		\
-{									\
-	return store_cache_disable(this_leaf, buf, count, index);	\
-}
-STORE_CACHE_DISABLE(0)
-STORE_CACHE_DISABLE(1)
-
-struct _cache_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct _cpuid4_info *, char *);
-	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
-};
-
 #define define_one_ro(_name) \
 static struct _cache_attr _name = \
 	__ATTR(_name, 0444, show_##_name, NULL)
@@ -813,23 +869,28 @@
 define_one_ro(shared_cpu_map);
 define_one_ro(shared_cpu_list);
 
-static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
-		show_cache_disable_0, store_cache_disable_0);
-static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
-		show_cache_disable_1, store_cache_disable_1);
+#define DEFAULT_SYSFS_CACHE_ATTRS	\
+	&type.attr,			\
+	&level.attr,			\
+	&coherency_line_size.attr,	\
+	&physical_line_partition.attr,	\
+	&ways_of_associativity.attr,	\
+	&number_of_sets.attr,		\
+	&size.attr,			\
+	&shared_cpu_map.attr,		\
+	&shared_cpu_list.attr
 
 static struct attribute *default_attrs[] = {
-	&type.attr,
-	&level.attr,
-	&coherency_line_size.attr,
-	&physical_line_partition.attr,
-	&ways_of_associativity.attr,
-	&number_of_sets.attr,
-	&size.attr,
-	&shared_cpu_map.attr,
-	&shared_cpu_list.attr,
+	DEFAULT_SYSFS_CACHE_ATTRS,
+	NULL
+};
+
+static struct attribute *default_l3_attrs[] = {
+	DEFAULT_SYSFS_CACHE_ATTRS,
+#if defined(CONFIG_CPU_SUP_AMD) && !defined(CONFIG_XEN)
 	&cache_disable_0.attr,
 	&cache_disable_1.attr,
+#endif
 	NULL
 };
 
@@ -920,6 +981,7 @@
 	unsigned int cpu = sys_dev->id;
 	unsigned long i, j;
 	struct _index_kobject *this_object;
+	struct _cpuid4_info   *this_leaf;
 	int retval;
 
 	retval = cpuid4_cache_sysfs_init(cpu);
@@ -938,6 +1000,14 @@
 		this_object = INDEX_KOBJECT_PTR(cpu, i);
 		this_object->cpu = cpu;
 		this_object->index = i;
+
+		this_leaf = CPUID4_INFO_IDX(cpu, i);
+
+		if (this_leaf->can_disable)
+			ktype_cache.default_attrs = default_l3_attrs;
+		else
+			ktype_cache.default_attrs = default_attrs;
+
 		retval = kobject_init_and_add(&(this_object->kobj),
 					      &ktype_cache,
 					      per_cpu(cache_kobject, cpu),
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/common-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/common-xen.c
@@ -0,0 +1,1346 @@
+#include <linux/bootmem.h>
+#include <linux/linkage.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/stackprotector.h>
+#include <asm/perf_event.h>
+#include <asm/mmu_context.h>
+#include <asm/hypervisor.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <linux/topology.h>
+#include <linux/cpumask.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/proto.h>
+#include <asm/setup.h>
+#include <asm/apic.h>
+#include <asm/desc.h>
+#include <asm/i387.h>
+#include <asm/mtrr.h>
+#include <linux/numa.h>
+#include <asm/asm.h>
+#include <asm/cpu.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+#include <asm/pat.h>
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/uv/uv.h>
+#endif
+
+#ifdef CONFIG_XEN
+#include <xen/interface/callback.h>
+#endif
+
+#include "cpu.h"
+
+/* all of these masks are initialized in setup_cpu_local_masks() */
+cpumask_var_t cpu_initialized_mask;
+#ifndef CONFIG_XEN
+cpumask_var_t cpu_callout_mask;
+cpumask_var_t cpu_callin_mask;
+#endif
+
+/* representing cpus for which sibling maps can be computed */
+cpumask_var_t cpu_sibling_setup_mask;
+
+/* correctly size the local cpu masks */
+void __init setup_cpu_local_masks(void)
+{
+	alloc_bootmem_cpumask_var(&cpu_initialized_mask);
+#ifndef CONFIG_XEN
+	alloc_bootmem_cpumask_var(&cpu_callin_mask);
+	alloc_bootmem_cpumask_var(&cpu_callout_mask);
+#endif
+	alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
+}
+
+static void __cpuinit default_init(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+	display_cacheinfo(c);
+#else
+	/* Not much we can do here... */
+	/* Check if at least it has cpuid */
+	if (c->cpuid_level == -1) {
+		/* No cpuid. It must be an ancient CPU */
+		if (c->x86 == 4)
+			strcpy(c->x86_model_id, "486");
+		else if (c->x86 == 3)
+			strcpy(c->x86_model_id, "386");
+	}
+#endif
+}
+
+static const struct cpu_dev __cpuinitconst default_cpu = {
+	.c_init		= default_init,
+	.c_vendor	= "Unknown",
+	.c_x86_vendor	= X86_VENDOR_UNKNOWN,
+};
+
+static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
+
+DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
+#ifdef CONFIG_X86_64
+	/*
+	 * We need valid kernel segments for data and code in long mode too
+	 * IRET will check the segment types  kkeil 2000/10/28
+	 * Also sysret mandates a special GDT layout
+	 *
+	 * TLS descriptors are currently at a different place compared to i386.
+	 * Hopefully nobody expects them at a fixed place (Wine?)
+	 */
+	[GDT_ENTRY_KERNEL32_CS]		= GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
+	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
+	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
+	[GDT_ENTRY_DEFAULT_USER32_CS]	= GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff),
+	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff),
+	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff),
+#else
+	[GDT_ENTRY_KERNEL_CS]		= GDT_ENTRY_INIT(0xc09a, 0, 0xfffff),
+	[GDT_ENTRY_KERNEL_DS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+	[GDT_ENTRY_DEFAULT_USER_CS]	= GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff),
+	[GDT_ENTRY_DEFAULT_USER_DS]	= GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),
+#ifndef CONFIG_XEN
+	/*
+	 * Segments used for calling PnP BIOS have byte granularity.
+	 * They code segments and data segments have fixed 64k limits,
+	 * the transfer segment sizes are set at run time.
+	 */
+	/* 32-bit code */
+	[GDT_ENTRY_PNPBIOS_CS32]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+	/* 16-bit code */
+	[GDT_ENTRY_PNPBIOS_CS16]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_DS]		= GDT_ENTRY_INIT(0x0092, 0, 0xffff),
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_TS1]		= GDT_ENTRY_INIT(0x0092, 0, 0),
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_TS2]		= GDT_ENTRY_INIT(0x0092, 0, 0),
+	/*
+	 * The APM segments have byte granularity and their bases
+	 * are set at run time.  All have 64k limits.
+	 */
+	/* 32-bit code */
+	[GDT_ENTRY_APMBIOS_BASE]	= GDT_ENTRY_INIT(0x409a, 0, 0xffff),
+	/* 16-bit code */
+	[GDT_ENTRY_APMBIOS_BASE+1]	= GDT_ENTRY_INIT(0x009a, 0, 0xffff),
+	/* data */
+	[GDT_ENTRY_APMBIOS_BASE+2]	= GDT_ENTRY_INIT(0x4092, 0, 0xffff),
+
+	[GDT_ENTRY_ESPFIX_SS]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+#endif
+	[GDT_ENTRY_PERCPU]		= GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
+	GDT_STACK_CANARY_INIT
+#endif
+} };
+EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
+
+static int __init x86_xsave_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_XSAVE);
+	return 1;
+}
+__setup("noxsave", x86_xsave_setup);
+
+#ifdef CONFIG_X86_32
+static int cachesize_override __cpuinitdata = -1;
+static int disable_x86_serial_nr __cpuinitdata = 1;
+
+static int __init cachesize_setup(char *str)
+{
+	get_option(&str, &cachesize_override);
+	return 1;
+}
+__setup("cachesize=", cachesize_setup);
+
+static int __init x86_fxsr_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_FXSR);
+	setup_clear_cpu_cap(X86_FEATURE_XMM);
+	return 1;
+}
+__setup("nofxsr", x86_fxsr_setup);
+
+static int __init x86_sep_setup(char *s)
+{
+	setup_clear_cpu_cap(X86_FEATURE_SEP);
+	return 1;
+}
+__setup("nosep", x86_sep_setup);
+
+/* Standard macro to see if a specific flag is changeable */
+static inline int flag_is_changeable_p(u32 flag)
+{
+	u32 f1, f2;
+
+	/*
+	 * Cyrix and IDT cpus allow disabling of CPUID
+	 * so the code below may return different results
+	 * when it is executed before and after enabling
+	 * the CPUID. Add "volatile" to not allow gcc to
+	 * optimize the subsequent calls to this function.
+	 */
+	asm volatile ("pushfl		\n\t"
+		      "pushfl		\n\t"
+		      "popl %0		\n\t"
+		      "movl %0, %1	\n\t"
+		      "xorl %2, %0	\n\t"
+		      "pushl %0		\n\t"
+		      "popfl		\n\t"
+		      "pushfl		\n\t"
+		      "popl %0		\n\t"
+		      "popfl		\n\t"
+
+		      : "=&r" (f1), "=&r" (f2)
+		      : "ir" (flag));
+
+	return ((f1^f2) & flag) != 0;
+}
+
+/* Probe for the CPUID instruction */
+static int __cpuinit have_cpuid_p(void)
+{
+	return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+{
+	unsigned long lo, hi;
+
+	if (!cpu_has(c, X86_FEATURE_PN) || !disable_x86_serial_nr)
+		return;
+
+	/* Disable processor serial number: */
+
+	rdmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+	lo |= 0x200000;
+	wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
+
+	printk(KERN_NOTICE "CPU serial number disabled.\n");
+	clear_cpu_cap(c, X86_FEATURE_PN);
+
+	/* Disabling the serial number may affect the cpuid level */
+	c->cpuid_level = cpuid_eax(0);
+}
+
+static int __init x86_serial_nr_setup(char *s)
+{
+	disable_x86_serial_nr = 0;
+	return 1;
+}
+__setup("serialnumber", x86_serial_nr_setup);
+#else
+static inline int flag_is_changeable_p(u32 flag)
+{
+	return 1;
+}
+/* Probe for the CPUID instruction */
+static inline int have_cpuid_p(void)
+{
+	return 1;
+}
+static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+{
+}
+#endif
+
+/*
+ * Some CPU features depend on higher CPUID levels, which may not always
+ * be available due to CPUID level capping or broken virtualization
+ * software.  Add those features to this table to auto-disable them.
+ */
+struct cpuid_dependent_feature {
+	u32 feature;
+	u32 level;
+};
+
+static const struct cpuid_dependent_feature __cpuinitconst
+cpuid_dependent_features[] = {
+	{ X86_FEATURE_MWAIT,		0x00000005 },
+	{ X86_FEATURE_DCA,		0x00000009 },
+	{ X86_FEATURE_XSAVE,		0x0000000d },
+	{ 0, 0 }
+};
+
+static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
+{
+	const struct cpuid_dependent_feature *df;
+
+	for (df = cpuid_dependent_features; df->feature; df++) {
+
+		if (!cpu_has(c, df->feature))
+			continue;
+		/*
+		 * Note: cpuid_level is set to -1 if unavailable, but
+		 * extended_extended_level is set to 0 if unavailable
+		 * and the legitimate extended levels are all negative
+		 * when signed; hence the weird messing around with
+		 * signs here...
+		 */
+		if (!((s32)df->level < 0 ?
+		     (u32)df->level > (u32)c->extended_cpuid_level :
+		     (s32)df->level > (s32)c->cpuid_level))
+			continue;
+
+		clear_cpu_cap(c, df->feature);
+		if (!warn)
+			continue;
+
+		printk(KERN_WARNING
+		       "CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
+				x86_cap_flags[df->feature], df->level);
+	}
+}
+
+/*
+ * Naming convention should be: <Name> [(<Codename>)]
+ * This table only is used unless init_<vendor>() below doesn't set it;
+ * in particular, if CPUID levels 0x80000002..4 are supported, this
+ * isn't used
+ */
+
+/* Look up CPU names by table lookup. */
+static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c)
+{
+	const struct cpu_model_info *info;
+
+	if (c->x86_model >= 16)
+		return NULL;	/* Range check */
+
+	if (!this_cpu)
+		return NULL;
+
+	info = this_cpu->c_models;
+
+	while (info && info->family) {
+		if (info->family == c->x86)
+			return info->model_names[c->x86_model];
+		info++;
+	}
+	return NULL;		/* Not found */
+}
+
+__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
+__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
+
+void __ref load_percpu_segment(int cpu)
+{
+#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
+	static bool done;
+
+	if (!done) {
+		done = true;
+		adjust_boot_vcpu_info();
+	}
+#endif
+#ifdef CONFIG_X86_32
+	loadsegment(fs, __KERNEL_PERCPU);
+#else
+	loadsegment(gs, 0);
+#ifndef CONFIG_XEN
+	wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));
+#else
+	if (HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL,
+			(unsigned long)per_cpu(irq_stack_union.gs_base, cpu)))
+		BUG();
+#endif
+#endif
+	load_stack_canary_segment();
+}
+
+/*
+ * Current gdt points %fs at the "master" per-cpu area: after this,
+ * it's on the real one.
+ */
+void switch_to_new_gdt(int cpu)
+{
+	struct desc_ptr gdt_descr;
+	unsigned long va, frames[16];
+	int f;
+
+	gdt_descr.address = (long)get_cpu_gdt_table(cpu);
+	gdt_descr.size = GDT_SIZE - 1;
+
+	for (va = gdt_descr.address, f = 0;
+	     va < gdt_descr.address + gdt_descr.size;
+	     va += PAGE_SIZE, f++) {
+		frames[f] = arbitrary_virt_to_mfn(va);
+		make_page_readonly((void *)va,
+				   XENFEAT_writable_descriptor_tables);
+	}
+	if (HYPERVISOR_set_gdt(frames, (gdt_descr.size + 1) / 8))
+		BUG();
+
+	/* Reload the per-cpu base */
+
+	load_percpu_segment(cpu);
+}
+
+static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
+
+static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
+{
+	unsigned int *v;
+	char *p, *q;
+
+	if (c->extended_cpuid_level < 0x80000004)
+		return;
+
+	v = (unsigned int *)c->x86_model_id;
+	cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+	cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+	cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+	c->x86_model_id[48] = 0;
+
+	/*
+	 * Intel chips right-justify this string for some dumb reason;
+	 * undo that brain damage:
+	 */
+	p = q = &c->x86_model_id[0];
+	while (*p == ' ')
+		p++;
+	if (p != q) {
+		while (*p)
+			*q++ = *p++;
+		while (q <= &c->x86_model_id[48])
+			*q++ = '\0';	/* Zero-pad the rest */
+	}
+}
+
+void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
+{
+	unsigned int n, dummy, ebx, ecx, edx, l2size;
+
+	n = c->extended_cpuid_level;
+
+	if (n >= 0x80000005) {
+		cpuid(0x80000005, &dummy, &ebx, &ecx, &edx);
+		printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+				edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+		c->x86_cache_size = (ecx>>24) + (edx>>24);
+#ifdef CONFIG_X86_64
+		/* On K8 L1 TLB is inclusive, so don't count it */
+		c->x86_tlbsize = 0;
+#endif
+	}
+
+	if (n < 0x80000006)	/* Some chips just has a large L1. */
+		return;
+
+	cpuid(0x80000006, &dummy, &ebx, &ecx, &edx);
+	l2size = ecx >> 16;
+
+#ifdef CONFIG_X86_64
+	c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
+#else
+	/* do processor-specific cache resizing */
+	if (this_cpu->c_size_cache)
+		l2size = this_cpu->c_size_cache(c, l2size);
+
+	/* Allow user to override all this if necessary. */
+	if (cachesize_override != -1)
+		l2size = cachesize_override;
+
+	if (l2size == 0)
+		return;		/* Again, no L2 cache is possible */
+#endif
+
+	c->x86_cache_size = l2size;
+
+	printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+			l2size, ecx & 0xFF);
+}
+
+void __cpuinit detect_ht(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_HT
+	u32 eax, ebx, ecx, edx;
+	int index_msb, core_bits;
+
+	if (!cpu_has(c, X86_FEATURE_HT))
+		return;
+
+	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+		goto out;
+
+	if (cpu_has(c, X86_FEATURE_XTOPOLOGY))
+		return;
+
+	cpuid(1, &eax, &ebx, &ecx, &edx);
+
+	smp_num_siblings = (ebx & 0xff0000) >> 16;
+
+	if (smp_num_siblings == 1) {
+		printk(KERN_INFO  "CPU: Hyper-Threading is disabled\n");
+		goto out;
+	}
+
+	if (smp_num_siblings <= 1)
+		goto out;
+
+	if (smp_num_siblings > nr_cpu_ids) {
+		pr_warning("CPU: Unsupported number of siblings %d",
+			   smp_num_siblings);
+		smp_num_siblings = 1;
+		return;
+	}
+
+	index_msb = get_count_order(smp_num_siblings);
+	c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
+
+	smp_num_siblings = smp_num_siblings / c->x86_max_cores;
+
+	index_msb = get_count_order(smp_num_siblings);
+
+	core_bits = get_count_order(c->x86_max_cores);
+
+	c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
+				       ((1 << core_bits) - 1);
+
+out:
+	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+		       c->phys_proc_id);
+		printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+		       c->cpu_core_id);
+	}
+#endif
+}
+
+static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+{
+	char *v = c->x86_vendor_id;
+	int i;
+
+	for (i = 0; i < X86_VENDOR_NUM; i++) {
+		if (!cpu_devs[i])
+			break;
+
+		if (!strcmp(v, cpu_devs[i]->c_ident[0]) ||
+		    (cpu_devs[i]->c_ident[1] &&
+		     !strcmp(v, cpu_devs[i]->c_ident[1]))) {
+
+			this_cpu = cpu_devs[i];
+			c->x86_vendor = this_cpu->c_x86_vendor;
+			return;
+		}
+	}
+
+	printk_once(KERN_ERR
+			"CPU: vendor_id '%s' unknown, using generic init.\n" \
+			"CPU: Your system may be unstable.\n", v);
+
+	c->x86_vendor = X86_VENDOR_UNKNOWN;
+	this_cpu = &default_cpu;
+}
+
+void __cpuinit cpu_detect(struct cpuinfo_x86 *c)
+{
+	/* Get vendor name */
+	cpuid(0x00000000, (unsigned int *)&c->cpuid_level,
+	      (unsigned int *)&c->x86_vendor_id[0],
+	      (unsigned int *)&c->x86_vendor_id[8],
+	      (unsigned int *)&c->x86_vendor_id[4]);
+
+	c->x86 = 4;
+	/* Intel-defined flags: level 0x00000001 */
+	if (c->cpuid_level >= 0x00000001) {
+		u32 junk, tfms, cap0, misc;
+
+		cpuid(0x00000001, &tfms, &misc, &junk, &cap0);
+		c->x86 = (tfms >> 8) & 0xf;
+		c->x86_model = (tfms >> 4) & 0xf;
+		c->x86_mask = tfms & 0xf;
+
+		if (c->x86 == 0xf)
+			c->x86 += (tfms >> 20) & 0xff;
+		if (c->x86 >= 0x6)
+			c->x86_model += ((tfms >> 16) & 0xf) << 4;
+
+		if (cap0 & (1<<19)) {
+			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+			c->x86_cache_alignment = c->x86_clflush_size;
+		}
+	}
+}
+
+void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+{
+	u32 tfms, xlvl;
+	u32 ebx;
+
+	/* Intel-defined flags: level 0x00000001 */
+	if (c->cpuid_level >= 0x00000001) {
+		u32 capability, excap;
+
+		cpuid(0x00000001, &tfms, &ebx, &excap, &capability);
+		c->x86_capability[0] = capability;
+		c->x86_capability[4] = excap;
+	}
+
+	/* AMD-defined flags: level 0x80000001 */
+	xlvl = cpuid_eax(0x80000000);
+	c->extended_cpuid_level = xlvl;
+
+	if ((xlvl & 0xffff0000) == 0x80000000) {
+		if (xlvl >= 0x80000001) {
+			c->x86_capability[1] = cpuid_edx(0x80000001);
+			c->x86_capability[6] = cpuid_ecx(0x80000001);
+		}
+	}
+
+	if (c->extended_cpuid_level >= 0x80000008) {
+		u32 eax = cpuid_eax(0x80000008);
+
+		c->x86_virt_bits = (eax >> 8) & 0xff;
+		c->x86_phys_bits = eax & 0xff;
+	}
+#ifdef CONFIG_X86_32
+	else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
+		c->x86_phys_bits = 36;
+#endif
+
+	if (c->extended_cpuid_level >= 0x80000007)
+		c->x86_power = cpuid_edx(0x80000007);
+
+	init_scattered_cpuid_features(c);
+}
+
+static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_32
+	int i;
+
+	/*
+	 * First of all, decide if this is a 486 or higher
+	 * It's a 486 if we can modify the AC flag
+	 */
+	if (flag_is_changeable_p(X86_EFLAGS_AC))
+		c->x86 = 4;
+	else
+		c->x86 = 3;
+
+	for (i = 0; i < X86_VENDOR_NUM; i++)
+		if (cpu_devs[i] && cpu_devs[i]->c_identify) {
+			c->x86_vendor_id[0] = 0;
+			cpu_devs[i]->c_identify(c);
+			if (c->x86_vendor_id[0]) {
+				get_cpu_vendor(c);
+				break;
+			}
+		}
+#endif
+}
+
+/*
+ * Do minimum CPU detection early.
+ * Fields really needed: vendor, cpuid_level, family, model, mask,
+ * cache alignment.
+ * The others are not touched to avoid unwanted side effects.
+ *
+ * WARNING: this function is only called on the BP.  Don't add code here
+ * that is supposed to run on all CPUs.
+ */
+static void __init early_identify_cpu(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+	c->x86_clflush_size = 64;
+	c->x86_phys_bits = 36;
+	c->x86_virt_bits = 48;
+#else
+	c->x86_clflush_size = 32;
+	c->x86_phys_bits = 32;
+	c->x86_virt_bits = 32;
+#endif
+	c->x86_cache_alignment = c->x86_clflush_size;
+
+	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+	c->extended_cpuid_level = 0;
+
+	if (!have_cpuid_p())
+		identify_cpu_without_cpuid(c);
+
+	/* cyrix could have cpuid enabled via c_identify()*/
+	if (!have_cpuid_p())
+		return;
+
+	cpu_detect(c);
+
+	get_cpu_vendor(c);
+
+	get_cpu_cap(c);
+
+	if (this_cpu->c_early_init)
+		this_cpu->c_early_init(c);
+
+#ifdef CONFIG_SMP
+	c->cpu_index = boot_cpu_id;
+#endif
+	filter_cpuid_features(c, false);
+}
+
+void __init early_cpu_init(void)
+{
+	const struct cpu_dev *const *cdev;
+	int count = 0;
+
+	printk(KERN_INFO "KERNEL supported cpus:\n");
+	for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
+		const struct cpu_dev *cpudev = *cdev;
+		unsigned int j;
+
+		if (count >= X86_VENDOR_NUM)
+			break;
+		cpu_devs[count] = cpudev;
+		count++;
+
+		for (j = 0; j < 2; j++) {
+			if (!cpudev->c_ident[j])
+				continue;
+			printk(KERN_INFO "  %s %s\n", cpudev->c_vendor,
+				cpudev->c_ident[j]);
+		}
+	}
+
+	early_identify_cpu(&boot_cpu_data);
+}
+
+/*
+ * The NOPL instruction is supposed to exist on all CPUs with
+ * family >= 6; unfortunately, that's not true in practice because
+ * of early VIA chips and (more importantly) broken virtualizers that
+ * are not easy to detect.  In the latter case it doesn't even *fail*
+ * reliably, so probing for it doesn't even work.  Disable it completely
+ * unless we can find a reliable way to detect all the broken cases.
+ */
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
+{
+	clear_cpu_cap(c, X86_FEATURE_NOPL);
+}
+
+static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
+{
+	c->extended_cpuid_level = 0;
+
+	if (!have_cpuid_p())
+		identify_cpu_without_cpuid(c);
+
+	/* cyrix could have cpuid enabled via c_identify()*/
+	if (!have_cpuid_p())
+		return;
+
+	cpu_detect(c);
+
+	get_cpu_vendor(c);
+
+	get_cpu_cap(c);
+
+	if (c->cpuid_level >= 0x00000001) {
+		c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
+#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
+# ifdef CONFIG_X86_HT
+		c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+# else
+		c->apicid = c->initial_apicid;
+# endif
+#endif
+
+#ifdef CONFIG_X86_HT
+		c->phys_proc_id = c->initial_apicid;
+#endif
+	}
+
+	get_model_name(c); /* Default name */
+
+	detect_nopl(c);
+}
+
+/*
+ * This does the hard work of actually picking apart the CPU stuff...
+ */
+static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+{
+	int i;
+
+	c->loops_per_jiffy = loops_per_jiffy;
+	c->x86_cache_size = -1;
+	c->x86_vendor = X86_VENDOR_UNKNOWN;
+	c->x86_model = c->x86_mask = 0;	/* So far unknown... */
+	c->x86_vendor_id[0] = '\0'; /* Unset */
+	c->x86_model_id[0] = '\0';  /* Unset */
+	c->x86_max_cores = 1;
+	c->x86_coreid_bits = 0;
+#ifdef CONFIG_X86_64
+	c->x86_clflush_size = 64;
+	c->x86_phys_bits = 36;
+	c->x86_virt_bits = 48;
+#else
+	c->cpuid_level = -1;	/* CPUID not detected */
+	c->x86_clflush_size = 32;
+	c->x86_phys_bits = 32;
+	c->x86_virt_bits = 32;
+#endif
+	c->x86_cache_alignment = c->x86_clflush_size;
+	memset(&c->x86_capability, 0, sizeof c->x86_capability);
+	if (boot_cpu_has(X86_FEATURE_SYSCALL32))
+		set_cpu_cap(c, X86_FEATURE_SYSCALL32);
+
+	generic_identify(c);
+
+	if (this_cpu->c_identify)
+		this_cpu->c_identify(c);
+
+	/* Clear/Set all flags overriden by options, after probe */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
+	c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
+#endif
+
+	/*
+	 * Vendor-specific initialization.  In this section we
+	 * canonicalize the feature flags, meaning if there are
+	 * features a certain CPU supports which CPUID doesn't
+	 * tell us, CPUID claiming incorrect flags, or other bugs,
+	 * we handle them here.
+	 *
+	 * At the end of this section, c->x86_capability better
+	 * indicate the features this CPU genuinely supports!
+	 */
+	if (this_cpu->c_init)
+		this_cpu->c_init(c);
+
+	/* Disable the PN if appropriate */
+	squash_the_stupid_serial_number(c);
+
+	/*
+	 * The vendor-specific functions might have changed features.
+	 * Now we do "generic changes."
+	 */
+
+	/* Filter out anything that depends on CPUID levels we don't have */
+	filter_cpuid_features(c, true);
+
+	/* If the model name is still unset, do table lookup. */
+	if (!c->x86_model_id[0]) {
+		const char *p;
+		p = table_lookup_model(c);
+		if (p)
+			strcpy(c->x86_model_id, p);
+		else
+			/* Last resort... */
+			sprintf(c->x86_model_id, "%02x/%02x",
+				c->x86, c->x86_model);
+	}
+
+#ifdef CONFIG_X86_64
+	detect_ht(c);
+#endif
+
+	init_hypervisor(c);
+
+	/*
+	 * Clear/Set all flags overriden by options, need do it
+	 * before following smp all cpus cap AND.
+	 */
+	for (i = 0; i < NCAPINTS; i++) {
+		c->x86_capability[i] &= ~cpu_caps_cleared[i];
+		c->x86_capability[i] |= cpu_caps_set[i];
+	}
+
+	/*
+	 * On SMP, boot_cpu_data holds the common feature set between
+	 * all CPUs; so make sure that we indicate which features are
+	 * common between the CPUs.  The first time this routine gets
+	 * executed, c == &boot_cpu_data.
+	 */
+	if (c != &boot_cpu_data) {
+		/* AND the already accumulated flags with these */
+		for (i = 0; i < NCAPINTS; i++)
+			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+	}
+
+#ifdef CONFIG_X86_MCE
+	/* Init Machine Check Exception if available. */
+	mcheck_init(c);
+#endif
+
+	select_idle_routine(c);
+
+#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+	numa_add_cpu(smp_processor_id());
+#endif
+}
+
+#ifdef CONFIG_X86_64
+static void vgetcpu_set_mode(void)
+{
+	if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
+		vgetcpu_mode = VGETCPU_RDTSCP;
+	else
+		vgetcpu_mode = VGETCPU_LSL;
+}
+#endif
+
+void __init identify_boot_cpu(void)
+{
+	identify_cpu(&boot_cpu_data);
+	init_c1e_mask();
+#ifdef CONFIG_X86_32
+	sysenter_setup();
+	enable_sep_cpu();
+#else
+	vgetcpu_set_mode();
+#endif
+	init_hw_perf_events();
+}
+
+void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
+{
+	BUG_ON(c == &boot_cpu_data);
+	identify_cpu(c);
+#ifdef CONFIG_X86_32
+	enable_sep_cpu();
+#endif
+	mtrr_ap_init();
+}
+
+struct msr_range {
+	unsigned	min;
+	unsigned	max;
+};
+
+static const struct msr_range msr_range_array[] __cpuinitconst = {
+	{ 0x00000000, 0x00000418},
+	{ 0xc0000000, 0xc000040b},
+	{ 0xc0010000, 0xc0010142},
+	{ 0xc0011000, 0xc001103b},
+};
+
+static void __cpuinit print_cpu_msr(void)
+{
+	unsigned index_min, index_max;
+	unsigned index;
+	u64 val;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
+		index_min = msr_range_array[i].min;
+		index_max = msr_range_array[i].max;
+
+		for (index = index_min; index < index_max; index++) {
+			if (rdmsrl_amd_safe(index, &val))
+				continue;
+			printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
+		}
+	}
+}
+
+static int show_msr __cpuinitdata;
+
+static __init int setup_show_msr(char *arg)
+{
+	int num;
+
+	get_option(&arg, &num);
+
+	if (num > 0)
+		show_msr = num;
+	return 1;
+}
+__setup("show_msr=", setup_show_msr);
+
+static __init int setup_noclflush(char *arg)
+{
+	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
+	return 1;
+}
+__setup("noclflush", setup_noclflush);
+
+void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+{
+	const char *vendor = NULL;
+
+	if (c->x86_vendor < X86_VENDOR_NUM) {
+		vendor = this_cpu->c_vendor;
+	} else {
+		if (c->cpuid_level >= 0)
+			vendor = c->x86_vendor_id;
+	}
+
+	if (vendor && !strstr(c->x86_model_id, vendor))
+		printk(KERN_CONT "%s ", vendor);
+
+	if (c->x86_model_id[0])
+		printk(KERN_CONT "%s", c->x86_model_id);
+	else
+		printk(KERN_CONT "%d86", c->x86);
+
+	if (c->x86_mask || c->cpuid_level >= 0)
+		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
+	else
+		printk(KERN_CONT "\n");
+
+#ifdef CONFIG_SMP
+	if (c->cpu_index < show_msr)
+		print_cpu_msr();
+#else
+	if (show_msr)
+		print_cpu_msr();
+#endif
+}
+
+static __init int setup_disablecpuid(char *arg)
+{
+	int bit;
+
+	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+		setup_clear_cpu_cap(bit);
+	else
+		return 0;
+
+	return 1;
+}
+__setup("clearcpuid=", setup_disablecpuid);
+
+#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_NO_IDT
+struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
+#endif
+
+DEFINE_PER_CPU_FIRST(union irq_stack_union,
+		     irq_stack_union) __aligned(PAGE_SIZE);
+
+void xen_switch_pt(void)
+{
+#ifdef CONFIG_XEN
+	xen_pt_switch(init_level4_pgt);
+#endif
+}
+
+/*
+ * The following four percpu variables are hot.  Align current_task to
+ * cacheline size such that all four fall in the same cacheline.
+ */
+DEFINE_PER_CPU(struct task_struct *, current_task) ____cacheline_aligned =
+	&init_task;
+EXPORT_PER_CPU_SYMBOL(current_task);
+
+DEFINE_PER_CPU(unsigned long, kernel_stack) =
+	(unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+EXPORT_PER_CPU_SYMBOL(kernel_stack);
+
+DEFINE_PER_CPU(char *, irq_stack_ptr) =
+	init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
+
+DEFINE_PER_CPU(unsigned int, irq_count) = -1;
+
+#ifndef CONFIG_X86_NO_TSS
+/*
+ * Special IST stacks which the CPU switches to when it calls
+ * an IST-marked descriptor entry. Up to 7 stacks (hardware
+ * limit), all of them are 4K, except the debug stack which
+ * is 8K.
+ */
+static const unsigned int exception_stack_sizes[N_EXCEPTION_STACKS] = {
+	  [0 ... N_EXCEPTION_STACKS - 1]	= EXCEPTION_STKSZ,
+	  [DEBUG_STACK - 1]			= DEBUG_STKSZ
+};
+
+static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
+	[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
+#endif
+
+void __cpuinit 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);
+	wrmsrl(MSR_CSTAR, ignore_sysret);
+#endif
+
+#ifdef CONFIG_IA32_EMULATION
+	syscall32_cpu_init();
+#elif defined(CONFIG_XEN)
+	static const struct callback_register __cpuinitconst cstar = {
+		.type = CALLBACKTYPE_syscall32,
+		.address = (unsigned long)ignore_sysret
+	};
+
+	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar))
+		printk(KERN_WARNING "Unable to register CSTAR callback\n");
+#endif
+
+#ifndef CONFIG_XEN
+	/* Flags to clear on syscall */
+	wrmsrl(MSR_SYSCALL_MASK,
+	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
+#endif
+}
+
+unsigned long kernel_eflags;
+
+#ifndef CONFIG_X86_NO_TSS
+/*
+ * Copies of the original ist values from the tss are only accessed during
+ * debugging, no special alignment required.
+ */
+DEFINE_PER_CPU(struct orig_ist, orig_ist);
+#endif
+
+#else	/* CONFIG_X86_64 */
+
+DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
+EXPORT_PER_CPU_SYMBOL(current_task);
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+#endif
+
+/* Make sure %fs and %gs are initialized properly in idle threads */
+struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
+{
+	memset(regs, 0, sizeof(struct pt_regs));
+	regs->fs = __KERNEL_PERCPU;
+	regs->gs = __KERNEL_STACK_CANARY;
+
+	return regs;
+}
+#endif	/* CONFIG_X86_64 */
+
+/*
+ * Clear all 6 debug registers:
+ */
+static void clear_all_debug_regs(void)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		/* Ignore db4, db5 */
+		if ((i == 4) || (i == 5))
+			continue;
+
+		set_debugreg(0, i);
+	}
+}
+
+/*
+ * 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 for 64 bit
+ */
+#ifdef CONFIG_X86_64
+
+void __cpuinit cpu_init(void)
+{
+#ifndef CONFIG_X86_NO_TSS
+	struct orig_ist *orig_ist;
+	struct tss_struct *t;
+	unsigned long v;
+	int i;
+#endif
+	struct task_struct *me;
+	int cpu;
+
+	cpu = stack_smp_processor_id();
+	/* CPU 0 is initialised in head64.c */
+	if (cpu != 0)
+		xen_switch_pt();
+#ifndef CONFIG_X86_NO_TSS
+	t = &per_cpu(init_tss, cpu);
+	orig_ist = &per_cpu(orig_ist, cpu);
+#endif
+
+#ifdef CONFIG_NUMA
+	if (cpu != 0 && percpu_read(node_number) == 0 &&
+	    cpu_to_node(cpu) != NUMA_NO_NODE)
+		percpu_write(node_number, cpu_to_node(cpu));
+#endif
+
+	me = current;
+
+	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask))
+		panic("CPU#%d already initialized!\n", cpu);
+
+	printk(KERN_INFO "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:
+	 */
+
+	switch_to_new_gdt(cpu);
+	loadsegment(fs, 0);
+
+#ifndef CONFIG_X86_NO_IDT
+	load_idt((const struct desc_ptr *)&idt_descr);
+#endif
+
+	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();
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (cpu != 0)
+		enable_x2apic();
+#endif
+
+#ifndef CONFIG_X86_NO_TSS
+	/*
+	 * set up and load the per-CPU TSS
+	 */
+	if (!orig_ist->ist[0]) {
+		char *estacks = per_cpu(exception_stacks, cpu);
+
+		for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+			estacks += exception_stack_sizes[v];
+			orig_ist->ist[v] = t->x86_tss.ist[v] =
+					(unsigned long)estacks;
+		}
+	}
+
+	t->x86_tss.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;
+	BUG_ON(me->mm);
+	enter_lazy_tlb(&init_mm, me);
+
+	load_sp0(t, &current->thread);
+#ifndef CONFIG_X86_NO_TSS
+	set_tss_desc(cpu, t);
+	load_TR_desc();
+#endif
+	load_LDT(&init_mm.context);
+
+#ifdef CONFIG_KGDB
+	/*
+	 * If the kgdb is connected no debug regs should be altered.  This
+	 * is only applicable when KGDB and a KGDB I/O module are built
+	 * into the kernel and you are using early debugging with
+	 * kgdbwait. KGDB will control the kernel HW breakpoint registers.
+	 */
+	if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
+		arch_kgdb_ops.correct_hw_break();
+	else
+#endif
+		clear_all_debug_regs();
+
+	fpu_init();
+
+#ifndef CONFIG_XEN
+	raw_local_save_flags(kernel_eflags);
+#else
+	asm ("pushfq; popq %0" : "=rm" (kernel_eflags));
+	if (raw_irqs_disabled())
+		kernel_eflags &= ~X86_EFLAGS_IF;
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (is_uv_system())
+		uv_cpu_init();
+#endif
+}
+
+#else
+
+void __cpuinit cpu_init(void)
+{
+	int cpu = smp_processor_id();
+	struct task_struct *curr = current;
+#ifndef CONFIG_X86_NO_TSS
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
+#endif
+	struct thread_struct *thread = &curr->thread;
+
+	if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
+		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
+		for (;;)
+			local_irq_enable();
+	}
+
+	printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+
+	if (cpu_has_vme || cpu_has_de)
+		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
+
+	switch_to_new_gdt(cpu);
+
+	/*
+	 * Set up and load the per-CPU TSS and LDT
+	 */
+	atomic_inc(&init_mm.mm_count);
+	curr->active_mm = &init_mm;
+	BUG_ON(curr->mm);
+	enter_lazy_tlb(&init_mm, curr);
+
+	load_sp0(t, thread);
+
+	load_LDT(&init_mm.context);
+
+#ifndef CONFIG_X86_NO_TSS
+	t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
+#endif
+
+#ifdef CONFIG_DOUBLEFAULT
+	/* Set up doublefault TSS pointer in the GDT */
+	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+#endif
+
+	clear_all_debug_regs();
+
+	/*
+	 * Force FPU initialization:
+	 */
+	if (cpu_has_xsave)
+		current_thread_info()->status = TS_XSAVE;
+	else
+		current_thread_info()->status = 0;
+	clear_used_math();
+	mxcsr_feature_mask_init();
+
+	/*
+	 * Boot processor to setup the FP and extended state context info.
+	 */
+	if (smp_processor_id() == boot_cpu_id)
+		init_thread_xstate();
+
+	xsave_init();
+}
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/intel.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/intel.c
@@ -40,6 +40,7 @@
 			misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
 			wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
 			c->cpuid_level = cpuid_eax(0);
+			get_cpu_cap(c);
 		}
 	}
 
@@ -47,6 +48,30 @@
 		(c->x86 == 0x6 && c->x86_model >= 0x0e))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
+	/*
+	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
+	 *
+	 * A race condition between speculative fetches and invalidating
+	 * a large page.  This is worked around in microcode, but we
+	 * need the microcode to have already been loaded... so if it is
+	 * not, recommend a BIOS update and disable large pages.
+	 */
+#ifdef CONFIG_XEN
+	if (cpu_has(c, X86_FEATURE_PSE))
+#endif
+	if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2) {
+		u32 ucode, junk;
+
+		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+		sync_core();
+		rdmsr(MSR_IA32_UCODE_REV, junk, ucode);
+
+		if (ucode < 0x20e) {
+			printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
+			clear_cpu_cap(c, X86_FEATURE_PSE);
+		}
+	}
+
 #ifdef CONFIG_X86_64
 	set_cpu_cap(c, X86_FEATURE_SYSENTER32);
 #else
@@ -70,8 +95,10 @@
 	if (c->x86_power & (1 << 8)) {
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 		set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
-		set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
-		sched_clock_stable = 1;
+#ifndef CONFIG_XEN
+		if (!check_tsc_unstable())
+			sched_clock_stable = 1;
+#endif
 	}
 
 	/*
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -712,7 +712,7 @@
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
 		if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15 &&
-		    boot_cpu_data.x86 != 16)
+		    boot_cpu_data.x86 != 16 && boot_cpu_data.x86 != 17)
 			return;
 		wd_ops = &k7_wd_ops;
 		break;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/common.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/common.c
@@ -540,7 +540,7 @@
 	}
 }
 
-static void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
 {
 	u32 tfms, xlvl;
 	u32 ebx;
@@ -579,6 +579,7 @@
 	if (c->extended_cpuid_level >= 0x80000007)
 		c->x86_power = cpuid_edx(0x80000007);
 
+	init_scattered_cpuid_features(c);
 }
 
 static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
@@ -727,7 +728,6 @@
 
 	get_model_name(c); /* Default name */
 
-	init_scattered_cpuid_features(c);
 	detect_nopl(c);
 }
 
@@ -798,6 +798,19 @@
 	/* Filter out anything that depends on CPUID levels we don't have */
 	filter_cpuid_features(c, true);
 
+#ifdef CONFIG_X86_32
+	/*
+	 *  emulation of NX with segment limits unfortunately means
+	 *  we have to disable the fast system calls, due to the way that
+	 *  sysexit clears the segment limits on return.
+	 *  If we have NX, then we don't need to do this.
+	 */
+#ifdef CONFIG_X86_PAE
+		if (!test_cpu_cap(c, X86_FEATURE_NX))
+#endif
+			clear_cpu_cap(c, X86_FEATURE_SEP);
+#endif /*CONFIG_X86_32*/
+
 	/* If the model name is still unset, do table lookup. */
 	if (!c->x86_model_id[0]) {
 		const char *p;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/cpu.h
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/cpu.h
@@ -33,5 +33,6 @@
 			    *const __x86_cpu_dev_end[];
 
 extern void display_cacheinfo(struct cpuinfo_x86 *c);
+extern void get_cpu_cap(struct cpuinfo_x86 *c);
 
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/amd.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/amd.c
@@ -254,59 +254,36 @@
 
 /*
  * Fixup core topology information for AMD multi-node processors.
- * Assumption 1: Number of cores in each internal node is the same.
- * Assumption 2: Mixed systems with both single-node and dual-node
- *               processors are not supported.
+ * Assumption: Number of cores in each internal node is the same.
  */
 #ifdef CONFIG_X86_HT
 static void __cpuinit amd_fixup_dcm(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_PCI
-	u32 t, cpn;
-	u8 n, n_id;
+	unsigned long long value;
+	u32 nodes, cores_per_node;
 	int cpu = smp_processor_id();
 
+	if (!cpu_has(c, X86_FEATURE_NODEID_MSR))
+		return;
+
 	/* fixup topology information only once for a core */
 	if (cpu_has(c, X86_FEATURE_AMD_DCM))
 		return;
 
-	/* check for multi-node processor on boot cpu */
-	t = read_pci_config(0, 24, 3, 0xe8);
-	if (!(t & (1 << 29)))
+	rdmsrl(MSR_FAM10H_NODE_ID, value);
+
+	nodes = ((value >> 3) & 7) + 1;
+	if (nodes == 1)
 		return;
 
 	set_cpu_cap(c, X86_FEATURE_AMD_DCM);
+	cores_per_node = c->x86_max_cores / nodes;
 
-	/* cores per node: each internal node has half the number of cores */
-	cpn = c->x86_max_cores >> 1;
-
-	/* even-numbered NB_id of this dual-node processor */
-	n = c->phys_proc_id << 1;
-
-	/*
-	 * determine internal node id and assign cores fifty-fifty to
-	 * each node of the dual-node processor
-	 */
-	t = read_pci_config(0, 24 + n, 3, 0xe8);
-	n = (t>>30) & 0x3;
-	if (n == 0) {
-		if (c->cpu_core_id < cpn)
-			n_id = 0;
-		else
-			n_id = 1;
-	} else {
-		if (c->cpu_core_id < cpn)
-			n_id = 1;
-		else
-			n_id = 0;
-	}
+	/* store NodeID, use llc_shared_map to store sibling info */
+	per_cpu(cpu_llc_id, cpu) = value & 7;
 
-	/* compute entire NodeID, use llc_shared_map to store sibling info */
-	per_cpu(cpu_llc_id, cpu) = (c->phys_proc_id << 1) + n_id;
-
-	/* fixup core id to be in range from 0 to cpn */
-	c->cpu_core_id = c->cpu_core_id % cpn;
-#endif
+	/* fixup core id to be in range from 0 to (cores_per_node - 1) */
+	c->cpu_core_id = c->cpu_core_id % cores_per_node;
 }
 #endif
 
@@ -328,15 +305,14 @@
 	/* use socket ID also for last level cache */
 	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
 	/* fixup topology information on multi-node processors */
-	if ((c->x86 == 0x10) && (c->x86_model == 9))
-		amd_fixup_dcm(c);
+	amd_fixup_dcm(c);
 #endif
 }
 
 int amd_get_nb_id(int cpu)
 {
 	int id = 0;
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
 	id = per_cpu(cpu_llc_id, cpu);
 #endif
 	return id;
@@ -428,7 +404,7 @@
 		    (c->x86_model == 8 && c->x86_mask >= 8))
 			set_cpu_cap(c, X86_FEATURE_K6_MTRR);
 #endif
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) && !defined(CONFIG_XEN)
 	/* check CPU config space for extended APIC ID */
 	if (cpu_has_apic && c->x86 >= 0xf) {
 		unsigned int val;
@@ -494,8 +470,10 @@
 	if (c->x86 == 0x10 || c->x86 == 0x11)
 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
 
+#ifndef CONFIG_XEN
 	/* get apicid instead of initial apic id from cpuid */
 	c->apicid = hard_smp_processor_id();
+#endif
 #else
 
 	/*
@@ -571,6 +549,7 @@
 		fam10h_check_enable_mmcfg();
 	}
 
+#ifndef CONFIG_XEN
 	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
 		unsigned long long tseg;
 
@@ -590,6 +569,30 @@
 		}
 	}
 #endif
+#endif
+
+	/* As a rule processors have APIC timer running in deep C states */
+	if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400))
+		set_cpu_cap(c, X86_FEATURE_ARAT);
+
+	/*
+	 * Disable GART TLB Walk Errors on Fam10h. We do this here
+	 * because this is always needed when GART is enabled, even in a
+	 * kernel which has no MCE support built in.
+	 */
+	if (c->x86 == 0x10) {
+		/*
+		 * BIOS should disable GartTlbWlk Errors themself. If
+		 * it doesn't do it here as suggested by the BKDG.
+		 *
+		 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
+		 */
+		u64 mask;
+
+		rdmsrl(MSR_AMD64_MCx_MASK(4), mask);
+		mask |= (1 << 10);
+		wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+	}
 }
 
 #ifdef CONFIG_X86_32
@@ -634,3 +637,68 @@
 };
 
 cpu_dev_register(amd_cpu_dev);
+
+/*
+ * AMD errata checking
+ *
+ * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
+ * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
+ * have an OSVW id assigned, which it takes as first argument. Both take a
+ * variable number of family-specific model-stepping ranges created by
+ * AMD_MODEL_RANGE(). Each erratum also has to be declared as extern const
+ * int[] in arch/x86/include/asm/processor.h.
+ *
+ * Example:
+ *
+ * const int amd_erratum_319[] =
+ *	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
+ *			   AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
+ *			   AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
+ */
+
+const int amd_erratum_400[] =
+	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
+			    AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
+
+
+bool cpu_has_amd_erratum(const int *erratum)
+{
+	struct cpuinfo_x86 *cpu = &current_cpu_data;
+	int osvw_id = *erratum++;
+	u32 range;
+	u32 ms;
+
+	/*
+	 * If called early enough that current_cpu_data hasn't been initialized
+	 * yet, fall back to boot_cpu_data.
+	 */
+	if (cpu->x86 == 0)
+		cpu = &boot_cpu_data;
+
+	if (cpu->x86_vendor != X86_VENDOR_AMD)
+		return false;
+
+	if (osvw_id >= 0 && osvw_id < 65536 &&
+	    cpu_has(cpu, X86_FEATURE_OSVW)) {
+		u64 osvw_len;
+
+		rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
+		if (osvw_id < osvw_len) {
+			u64 osvw_bits;
+
+			rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
+			    osvw_bits);
+			return osvw_bits & (1ULL << (osvw_id & 0x3f));
+		}
+	}
+
+	/* OSVW unavailable or ID unknown, match family-model-stepping range */
+	ms = (cpu->x86_model << 4) | cpu->x86_mask;
+	while ((range = *erratum++))
+		if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
+		    (ms >= AMD_MODEL_RANGE_START(range)) &&
+		    (ms <= AMD_MODEL_RANGE_END(range)))
+			return true;
+
+	return false;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/bugs_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/bugs_64.c
@@ -20,6 +20,7 @@
 #endif
 	alternative_instructions();
 
+#ifndef CONFIG_XEN
 	/*
 	 * Make sure the first 2MB area is not mapped by huge pages
 	 * There are typically fixed size MTRRs in there and overlapping
@@ -30,4 +31,5 @@
 	 */
 	if (!direct_gbpages)
 		set_memory_4k((unsigned long)__va(0), 1);
+#endif
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/vmware.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/vmware.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/dmi.h>
+#include <linux/jiffies.h>
 #include <asm/div64.h>
 #include <asm/vmware.h>
 #include <asm/x86_init.h>
@@ -50,7 +51,7 @@
 
 static unsigned long vmware_get_tsc_khz(void)
 {
-	uint64_t tsc_hz;
+	uint64_t tsc_hz, lpj;
 	uint32_t eax, ebx, ecx, edx;
 
 	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
@@ -61,6 +62,13 @@
 	printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n",
 			 (unsigned long) tsc_hz / 1000,
 			 (unsigned long) tsc_hz % 1000);
+
+	if (!preset_lpj) {
+		lpj = ((u64)tsc_hz * 1000);
+		do_div(lpj, HZ);
+		preset_lpj = lpj;
+	}
+
 	return tsc_hz;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/addon_cpuid_features.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -70,7 +70,7 @@
  */
 void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
 	unsigned int eax, ebx, ecx, edx, sub_index;
 	unsigned int ht_mask_width, core_plus_mask_width;
 	unsigned int core_select_mask, core_level_siblings;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/perf_event.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/perf_event.c
@@ -190,6 +190,97 @@
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
+static const u64 westmere_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+		[ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+		[ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
+		[ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
+		[ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
+		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
+		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
+		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+		[ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+		[ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
+		[ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.ANY              */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+		[ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
 static const u64 nehalem_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -914,8 +1005,11 @@
 		if (atomic_read(&active_events) == 0) {
 			if (!reserve_pmc_hardware())
 				err = -EBUSY;
-			else
+			else {
 				err = reserve_bts_hardware();
+				if (err)
+					release_pmc_hardware();
+			}
 		}
 		if (!err)
 			atomic_inc(&active_events);
@@ -1999,6 +2093,7 @@
 	 * Install the hw-cache-events table:
 	 */
 	switch (boot_cpu_data.x86_model) {
+
 	case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
 	case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
 	case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
@@ -2009,7 +2104,9 @@
 		pr_cont("Core2 events, ");
 		break;
 	default:
-	case 26:
+	case 26: /* 45 nm nehalem, "Bloomfield" */
+	case 30: /* 45 nm nehalem, "Lynnfield" */
+	case 46: /* 45 nm nehalem-ex, "Beckton" */
 		memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
 
@@ -2021,6 +2118,14 @@
 
 		pr_cont("Atom events, ");
 		break;
+
+	case 37: /* 32 nm nehalem, "Clarkdale" */
+	case 44: /* 32 nm nehalem, "Gulftown" */
+		memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		pr_cont("Westmere events, ");
+		break;
 	}
 	return 0;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/bugs.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/bugs.c
@@ -151,6 +151,20 @@
 #endif
 }
 
+static void __init check_atom(void)
+{	
+
+	/* 
+	 *  Disable 4MB page tables to work around Intel errata AAE44 for
+	 *  Atom. We cannot guarantee stopping undefined processor behaviour
+	 *  when two pageing structure translations differ with respect to
+	 *  page frame sizes.  Hence, for Atoms we disable the PSE.
+	 */
+	if (boot_cpu_data.x86_model == 0x1c) {
+		clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+		printk(KERN_INFO "Disabling 4MB page tables to avoid TLB bug\n");
+	}
+}
 
 void __init check_bugs(void)
 {
@@ -163,6 +177,7 @@
 	check_fpu();
 	check_hlt();
 	check_popad();
+	check_atom();
 	init_utsname()->machine[1] =
 		'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
 	alternative_instructions();
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mtrr/main-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mtrr/main-xen.c
@@ -0,0 +1,324 @@
+#define DEBUG
+
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/init.h>
+
+#include <asm/mtrr.h>
+#include "mtrr.h"
+
+static DEFINE_MUTEX(mtrr_mutex);
+
+void generic_get_mtrr(unsigned int reg, unsigned long *base,
+		      unsigned long *size, mtrr_type * type)
+{
+	struct xen_platform_op op;
+
+	op.cmd = XENPF_read_memtype;
+	op.u.read_memtype.reg = reg;
+	if (unlikely(HYPERVISOR_platform_op(&op)))
+		memset(&op.u.read_memtype, 0, sizeof(op.u.read_memtype));
+
+	*size = op.u.read_memtype.nr_mfns;
+	*base = op.u.read_memtype.mfn;
+	*type = op.u.read_memtype.type;
+}
+
+struct mtrr_ops generic_mtrr_ops = {
+	.use_intel_if      = 1,
+	.get               = generic_get_mtrr,
+};
+
+struct mtrr_ops *mtrr_if = &generic_mtrr_ops;
+unsigned int num_var_ranges;
+unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
+
+static u64 tom2;
+
+static void __init set_num_var_ranges(void)
+{
+	struct xen_platform_op op;
+
+	for (num_var_ranges = 0; ; num_var_ranges++) {
+		op.cmd = XENPF_read_memtype;
+		op.u.read_memtype.reg = num_var_ranges;
+		if (HYPERVISOR_platform_op(&op) != 0)
+			break;
+	}
+}
+
+static void __init init_table(void)
+{
+	int i, max;
+
+	max = num_var_ranges;
+	for (i = 0; i < max; i++)
+		mtrr_usage_table[i] = 0;
+}
+
+int mtrr_add_page(unsigned long base, unsigned long size,
+		  unsigned int type, bool increment)
+{
+	int error;
+	struct xen_platform_op op;
+
+	mutex_lock(&mtrr_mutex);
+
+	op.cmd = XENPF_add_memtype;
+	op.u.add_memtype.mfn     = base;
+	op.u.add_memtype.nr_mfns = size;
+	op.u.add_memtype.type    = type;
+	error = HYPERVISOR_platform_op(&op);
+	if (error) {
+		mutex_unlock(&mtrr_mutex);
+		BUG_ON(error > 0);
+		return error;
+	}
+
+	if (increment)
+		++mtrr_usage_table[op.u.add_memtype.reg];
+
+	mutex_unlock(&mtrr_mutex);
+
+	return op.u.add_memtype.reg;
+}
+
+static int mtrr_check(unsigned long base, unsigned long size)
+{
+	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
+		pr_warning("mtrr: size and base must be multiples of 4 kiB\n");
+		pr_debug("mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+		dump_stack();
+		return -1;
+	}
+	return 0;
+}
+
+int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
+	     bool increment)
+{
+	if (mtrr_check(base, size))
+		return -EINVAL;
+	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
+			     increment);
+}
+EXPORT_SYMBOL(mtrr_add);
+
+int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+{
+	unsigned i;
+	mtrr_type ltype;
+	unsigned long lbase, lsize;
+	int error = -EINVAL;
+	struct xen_platform_op op;
+
+	mutex_lock(&mtrr_mutex);
+
+	if (reg < 0) {
+		/*  Search for existing MTRR  */
+		for (i = 0; i < num_var_ranges; ++i) {
+			mtrr_if->get(i, &lbase, &lsize, &ltype);
+			if (lbase == base && lsize == size) {
+				reg = i;
+				break;
+			}
+		}
+		if (reg < 0) {
+			pr_debug("mtrr: no MTRR for %lx000,%lx000 found\n",
+				 base, size);
+			goto out;
+		}
+	}
+	if (mtrr_usage_table[reg] < 1) {
+		pr_warning("mtrr: reg: %d has count=0\n", reg);
+		goto out;
+	}
+	if (--mtrr_usage_table[reg] < 1) {
+		op.cmd = XENPF_del_memtype;
+		op.u.del_memtype.handle = 0;
+		op.u.del_memtype.reg    = reg;
+		error = HYPERVISOR_platform_op(&op);
+		if (error) {
+			BUG_ON(error > 0);
+			goto out;
+		}
+	}
+	error = reg;
+ out:
+	mutex_unlock(&mtrr_mutex);
+	return error;
+}
+
+int mtrr_del(int reg, unsigned long base, unsigned long size)
+{
+	if (mtrr_check(base, size))
+		return -EINVAL;
+	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(mtrr_del);
+
+/*
+ * Returns the effective MTRR type for the region
+ * Error returns:
+ * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
+ * - 0xFF - when MTRR is not enabled
+ */
+u8 mtrr_type_lookup(u64 start, u64 end)
+{
+	int i, error;
+	u64 start_mfn, end_mfn, base_mfn, top_mfn;
+	u8 prev_match, curr_match;
+	struct xen_platform_op op;
+
+	if (!is_initial_xendomain())
+		return MTRR_TYPE_WRBACK;
+
+	if (!num_var_ranges)
+		return 0xFF;
+
+	start_mfn = start >> PAGE_SHIFT;
+	/* Make end inclusive end, instead of exclusive */
+	end_mfn = --end >> PAGE_SHIFT;
+
+	/* Look in fixed ranges. Just return the type as per start */
+	if (start_mfn < 0x100) {
+#if 0//todo
+		op.cmd = XENPF_read_memtype;
+		op.u.read_memtype.reg = ???;
+		error = HYPERVISOR_platform_op(&op);
+		if (!error)
+			return op.u.read_memtype.type;
+#endif
+		return MTRR_TYPE_UNCACHABLE;
+	}
+
+	/*
+	 * Look in variable ranges
+	 * Look of multiple ranges matching this address and pick type
+	 * as per MTRR precedence
+	 */
+	prev_match = 0xFF;
+	for (i = 0; i < num_var_ranges; ++i) {
+		op.cmd = XENPF_read_memtype;
+		op.u.read_memtype.reg = i;
+		error = HYPERVISOR_platform_op(&op);
+
+		if (error || !op.u.read_memtype.nr_mfns)
+			continue;
+
+		base_mfn = op.u.read_memtype.mfn;
+		top_mfn = base_mfn + op.u.read_memtype.nr_mfns - 1;
+
+		if (base_mfn > end_mfn || start_mfn > top_mfn) {
+			continue;
+		}
+
+		if (base_mfn > start_mfn || end_mfn > top_mfn) {
+			return 0xFE;
+		}
+
+		curr_match = op.u.read_memtype.type;
+		if (prev_match == 0xFF) {
+			prev_match = curr_match;
+			continue;
+		}
+
+		if (prev_match == MTRR_TYPE_UNCACHABLE ||
+		    curr_match == MTRR_TYPE_UNCACHABLE) {
+			return MTRR_TYPE_UNCACHABLE;
+		}
+
+		if ((prev_match == MTRR_TYPE_WRBACK &&
+		     curr_match == MTRR_TYPE_WRTHROUGH) ||
+		    (prev_match == MTRR_TYPE_WRTHROUGH &&
+		     curr_match == MTRR_TYPE_WRBACK)) {
+			prev_match = MTRR_TYPE_WRTHROUGH;
+			curr_match = MTRR_TYPE_WRTHROUGH;
+		}
+
+		if (prev_match != curr_match) {
+			return MTRR_TYPE_UNCACHABLE;
+		}
+	}
+
+	if (tom2) {
+		if (start >= (1ULL<<32) && (end < tom2))
+			return MTRR_TYPE_WRBACK;
+	}
+
+	if (prev_match != 0xFF)
+		return prev_match;
+
+#if 0//todo
+	op.cmd = XENPF_read_def_memtype;
+	error = HYPERVISOR_platform_op(&op);
+	if (!error)
+		return op.u.read_def_memtype.type;
+#endif
+	return MTRR_TYPE_UNCACHABLE;
+}
+
+/*
+ * Newer AMD K8s and later CPUs have a special magic MSR way to force WB
+ * for memory >4GB. Check for that here.
+ * Note this won't check if the MTRRs < 4GB where the magic bit doesn't
+ * apply to are wrong, but so far we don't know of any such case in the wild.
+ */
+#define Tom2Enabled (1U << 21)
+#define Tom2ForceMemTypeWB (1U << 22)
+
+int __init amd_special_default_mtrr(void)
+{
+	u32 l, h;
+
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return 0;
+	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+		return 0;
+	/* In case some hypervisor doesn't pass SYSCFG through */
+	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
+		return 0;
+	/*
+	 * Memory between 4GB and top of mem is forced WB by this magic bit.
+	 * Reserved before K8RevF, but should be zero there.
+	 */
+	if ((l & (Tom2Enabled | Tom2ForceMemTypeWB)) ==
+		 (Tom2Enabled | Tom2ForceMemTypeWB))
+		return 1;
+	return 0;
+}
+
+void __init mtrr_bp_init(void)
+{
+	if (amd_special_default_mtrr()) {
+		/* TOP_MEM2 */
+		rdmsrl(MSR_K8_TOP_MEM2, tom2);
+		tom2 &= 0xffffff8000000ULL;
+	}
+}
+
+void mtrr_ap_init(void)
+{
+}
+
+static int __init mtrr_init(void)
+{
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	if (!is_initial_xendomain())
+		return -ENODEV;
+
+	if ((!cpu_has(c, X86_FEATURE_MTRR)) &&
+	    (!cpu_has(c, X86_FEATURE_K6_MTRR)) &&
+	    (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) &&
+	    (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
+		return -ENODEV;
+
+	set_num_var_ranges();
+	init_table();
+
+	return 0;
+}
+
+subsys_initcall(mtrr_init);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mtrr/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mtrr/Makefile
@@ -1,3 +1,4 @@
 obj-y		:= main.o if.o generic.o state.o cleanup.o
 obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o
 
+obj-$(CONFIG_XEN) := main.o if.o
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mtrr/cleanup.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -948,7 +948,7 @@
 
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 		return 0;
-	if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11)
+	if (boot_cpu_data.x86 < 0xf)
 		return 0;
 	/* In case some hypervisor doesn't pass SYSCFG through: */
 	if (rdmsr_safe(MSR_K8_SYSCFG, &l, &h) < 0)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mtrr/main.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mtrr/main.c
@@ -262,14 +262,24 @@
 
 	/*
 	 * HACK!
-	 * We use this same function to initialize the mtrrs on boot.
-	 * The state of the boot cpu's mtrrs has been saved, and we want
-	 * to replicate across all the APs.
-	 * If we're doing that @reg is set to something special...
+	 *
+	 * We use this same function to initialize the mtrrs during boot,
+	 * resume, runtime cpu online and on an explicit request to set a
+	 * specific MTRR.
+	 *
+	 * During boot or suspend, the state of the boot cpu's mtrrs has been
+	 * saved, and we want to replicate that across all the cpus that come
+	 * online (either at the end of boot or resume or during a runtime cpu
+	 * online). If we're doing that, @reg is set to something special and on
+	 * this cpu we still do mtrr_if->set_all(). During boot/resume, this
+	 * is unnecessary if at this point we are still on the cpu that started
+	 * the boot/resume sequence. But there is no guarantee that we are still
+	 * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
+	 * sure that we are in sync with everyone else.
 	 */
 	if (reg != ~0U)
 		mtrr_if->set(reg, base, size, type);
-	else if (!mtrr_aps_delayed_init)
+	else
 		mtrr_if->set_all();
 
 	/* Wait for the others */
@@ -762,13 +772,21 @@
 }
 
 /*
- * MTRR initialization for all AP's
+ * Delayed MTRR initialization for all AP's
  */
 void mtrr_aps_init(void)
 {
 	if (!use_intel())
 		return;
 
+	/*
+	 * Check if someone has requested the delay of AP MTRR initialization,
+	 * by doing set_mtrr_aps_delayed_init(), prior to this point. If not,
+	 * then we are done.
+	 */
+	if (!mtrr_aps_delayed_init)
+		return;
+
 	set_mtrr(~0U, 0, 0, 0);
 	mtrr_aps_delayed_init = false;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce_dom0.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce_dom0.c
@@ -0,0 +1,186 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <xen/interface/xen.h>
+#include <xen/evtchn.h>
+#include <xen/interface/vcpu.h>
+#include <asm/hypercall.h>
+#include <asm/mce.h>
+
+static xen_mc_logical_cpu_t *g_physinfo;
+static unsigned int ncpus;
+
+static int convert_log(struct mc_info *mi)
+{
+	struct mcinfo_common *mic = NULL;
+	struct mcinfo_global *mc_global;
+	struct mcinfo_bank *mc_bank;
+	struct mce m;
+	unsigned int i;
+	bool found = false;
+
+	x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL);
+	if (mic == NULL)
+	{
+		printk(KERN_ERR "DOM0_MCE_LOG: global data is NULL\n");
+		return -1;
+	}
+
+	mce_setup(&m);
+	mc_global = (struct mcinfo_global*)mic;
+	m.mcgstatus = mc_global->mc_gstatus;
+	m.apicid = mc_global->mc_apicid;
+
+	for (i = 0; i < ncpus; i++)
+		if (g_physinfo[i].mc_apicid == m.apicid) {
+			found = true;
+			break;
+		}
+	WARN_ON_ONCE(!found);
+	m.socketid = g_physinfo[i].mc_chipid;
+	m.cpu = m.extcpu = g_physinfo[i].mc_cpunr;
+	m.cpuvendor = (__u8)g_physinfo[i].mc_vendor;
+
+	x86_mcinfo_lookup(mic, mi, MC_TYPE_BANK);
+	do
+	{
+		if (mic == NULL || mic->size == 0)
+			break;
+		if (mic->type == MC_TYPE_BANK)
+		{
+			mc_bank = (struct mcinfo_bank*)mic;
+			m.misc = mc_bank->mc_misc;
+			m.status = mc_bank->mc_status;
+			m.addr = mc_bank->mc_addr;
+			m.tsc = mc_bank->mc_tsc;
+			m.bank = mc_bank->mc_bank;
+			printk(KERN_DEBUG "[CPU%d, BANK%d, addr %llx, state %llx]\n", 
+						m.bank, m.cpu, m.addr, m.status);
+			/*log this record*/
+			mce_log(&m);
+		}
+		mic = x86_mcinfo_next(mic);
+	}while (1);
+
+	return 0;
+}
+
+static struct mc_info *g_mi;
+
+/*dom0 mce virq handler, logging physical mce error info*/
+
+static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id)
+{
+	xen_mc_t mc_op;
+	int result = 0;
+
+	printk(KERN_DEBUG "MCE_DOM0_LOG: enter dom0 mce vIRQ handler\n");
+	mc_op.cmd = XEN_MC_fetch;
+	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
+	set_xen_guest_handle(mc_op.u.mc_fetch.data, g_mi);
+urgent:
+	mc_op.u.mc_fetch.flags = XEN_MC_URGENT;
+	result = HYPERVISOR_mca(&mc_op);
+	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
+			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
+	{
+		printk(KERN_DEBUG "MCE_DOM0_LOG: No more urgent data\n");
+		goto nonurgent;
+	}
+	else
+	{
+		result = convert_log(g_mi);
+		if (result) {
+			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
+			goto end;
+		}
+		/* After fetching the telem from DOM0, we need to dec the telem's
+		 * refcnt and release the entry. The telem is reserved and inc
+		 * refcnt when filling the telem.
+		 */
+		mc_op.u.mc_fetch.flags = XEN_MC_URGENT | XEN_MC_ACK;
+		result = HYPERVISOR_mca(&mc_op);
+
+		goto urgent;
+	}
+nonurgent:
+	mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT;
+	result = HYPERVISOR_mca(&mc_op);
+	if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA ||
+			mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED)
+	{
+		printk(KERN_DEBUG "MCE_DOM0_LOG: No more nonurgent data\n");
+		goto end;
+	}
+	else
+	{
+		result = convert_log(g_mi);
+		if (result) {
+			printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n");
+			goto end;
+		}
+		/* After fetching the telem from DOM0, we need to dec the telem's
+		 * refcnt and release the entry. The telem is reserved and inc
+		 * refcnt when filling the telem.
+		 */
+		mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT | XEN_MC_ACK;
+		result = HYPERVISOR_mca(&mc_op);
+
+		goto nonurgent;
+	}
+end:
+	return IRQ_HANDLED;
+}
+
+int __init bind_virq_for_mce(void)
+{
+	int ret;
+	xen_mc_t mc_op;
+
+	g_mi = kmalloc(sizeof(*g_mi), GFP_KERNEL);
+	if (!g_mi)
+		return -ENOMEM;
+
+	/* fetch physical CPU count */
+	mc_op.cmd = XEN_MC_physcpuinfo;
+	mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
+	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, NULL);
+	ret = HYPERVISOR_mca(&mc_op);
+	if (ret) {
+		printk(KERN_ERR "MCE: Failed to get physical CPU count\n");
+		kfree(g_mi);
+		return ret;
+	}
+
+	/* fetch CPU physical info for later reference */
+	ncpus = mc_op.u.mc_physcpuinfo.ncpus;
+	g_physinfo = kmalloc(sizeof(*g_physinfo) * ncpus, GFP_KERNEL);
+	if (!g_physinfo) {
+		kfree(g_mi);
+		return -ENOMEM;
+	}
+	set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
+	ret = HYPERVISOR_mca(&mc_op);
+	if (ret) {
+		printk(KERN_ERR "MCE: Failed to get physical CPUs' info\n");
+		kfree(g_mi);
+		kfree(g_physinfo);
+		return ret;
+	}
+
+	ret  = bind_virq_to_irqhandler(VIRQ_MCA, 0, 
+		mce_dom0_interrupt, 0, "mce", NULL);
+
+	if (ret < 0) {
+		printk(KERN_ERR "MCE: Failed to bind vIRQ for Dom0\n");
+		kfree(g_mi);
+		kfree(g_physinfo);
+		return ret;
+	}
+
+	/* Log the machine checks left over from the previous reset. */
+	mce_dom0_interrupt(VIRQ_MCA, NULL);
+
+	return 0;
+}
+
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/Makefile
@@ -2,7 +2,9 @@
 
 obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip.o p5.o
 obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
+obj-$(CONFIG_X86_MCE_XEON75XX)	+= mce-xeon75xx.o
 obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd.o
+obj-$(CONFIG_X86_XEN_MCE)	+= mce_dom0.o
 obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
 obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -143,7 +143,7 @@
 	if (context == MCJ_CTX_RANDOM)
 		return;
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 	if (m->inject_flags & MCJ_NMI_BROADCAST) {
 		unsigned long start;
 		int cpu;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce.c
@@ -91,6 +91,9 @@
 	pr_emerg("Run the message through 'mcelog --ascii' to decode.\n");
 }
 
+void				(*mce_cpu_specific_poll)(struct mce *);
+EXPORT_SYMBOL_GPL(mce_cpu_specific_poll);
+
 /*
  * CPU/chipset specific EDAC code can register a callback here to print
  * MCE errors in a human-readable form:
@@ -350,6 +353,11 @@
 	wrmsrl(msr, v);
 }
 
+static int under_injection(void)
+{
+	return __get_cpu_var(injectm).finished;
+}
+
 /*
  * Simple lockless ring to communicate PFNs from the exception handler with the
  * process context work function. This is vastly simplified because there's
@@ -447,7 +455,9 @@
  */
 asmlinkage void smp_mce_self_interrupt(struct pt_regs *regs)
 {
+#ifndef CONFIG_XEN
 	ack_APIC_irq();
+#endif
 	exit_idle();
 	irq_enter();
 	mce_notify_irq();
@@ -470,7 +480,7 @@
 		return;
 	}
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 	/*
 	 * Without APIC do not notify. The event will be picked
 	 * up eventually.
@@ -553,6 +563,10 @@
 
 		if (!(flags & MCP_TIMESTAMP))
 			m.tsc = 0;
+
+		if (mce_cpu_specific_poll && !under_injection() && !mce_dont_log_ce)
+			mce_cpu_specific_poll(&m);
+
 		/*
 		 * Don't get the IP here because it's unlikely to
 		 * have anything to do with the actual error location.
@@ -1116,8 +1130,15 @@
  * Periodic polling timer for "silent" machine check errors.  If the
  * poller finds an MCE, poll 2x faster.  When the poller finds no more
  * errors, poll 2x slower (up to check_interval seconds).
+ *
+ * We will disable polling in DOM0 since all CMCI/Polling
+ * mechanism will be done in XEN for Intel CPUs
  */
+#if defined (CONFIG_X86_XEN_MCE)
+static int check_interval = 0; /* disable polling */
+#else
 static int check_interval = 5 * 60; /* 5 minutes */
+#endif
 
 static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */
 static DEFINE_PER_CPU(struct timer_list, mce_timer);
@@ -1282,6 +1303,7 @@
 
 	/* This should be disabled by the BIOS, but isn't always */
 	if (c->x86_vendor == X86_VENDOR_AMD) {
+#ifndef CONFIG_XEN
 		if (c->x86 == 15 && banks > 4) {
 			/*
 			 * disable GART TBL walk error reporting, which
@@ -1290,6 +1312,7 @@
 			 */
 			clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
 		}
+#endif
 		if (c->x86 <= 17 && mce_bootlog < 0) {
 			/*
 			 * Lots of broken BIOS around that don't clear them
@@ -1357,6 +1380,7 @@
 
 static void mce_cpu_features(struct cpuinfo_x86 *c)
 {
+#ifndef CONFIG_X86_64_XEN
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
 		mce_intel_feature_init(c);
@@ -1367,6 +1391,7 @@
 	default:
 		break;
 	}
+#endif
 }
 
 static void mce_init_timer(void)
@@ -1374,13 +1399,14 @@
 	struct timer_list *t = &__get_cpu_var(mce_timer);
 	int *n = &__get_cpu_var(mce_next_interval);
 
+	setup_timer(t, mcheck_timer, smp_processor_id());
+
 	if (mce_ignore_ce)
 		return;
 
 	*n = check_interval * HZ;
 	if (!*n)
 		return;
-	setup_timer(t, mcheck_timer, smp_processor_id());
 	t->expires = round_jiffies(jiffies + *n);
 	add_timer_on(t, smp_processor_id());
 }
@@ -1991,9 +2017,11 @@
 		break;
 	case CPU_DOWN_FAILED:
 	case CPU_DOWN_FAILED_FROZEN:
-		t->expires = round_jiffies(jiffies +
+		if (!mce_ignore_ce && check_interval) {
+			t->expires = round_jiffies(jiffies +
 					   __get_cpu_var(mce_next_interval));
-		add_timer_on(t, cpu);
+			add_timer_on(t, cpu);
+		}
 		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
 		break;
 	case CPU_POST_DEAD:
@@ -2050,6 +2078,16 @@
 	register_hotcpu_notifier(&mce_cpu_notifier);
 	misc_register(&mce_log_device);
 
+#ifdef CONFIG_X86_XEN_MCE
+	if (is_initial_xendomain()) {
+		/* Register vIRQ handler for MCE LOG processing */
+		extern int bind_virq_for_mce(void);
+
+		printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n");
+		bind_virq_for_mce();
+	}
+#endif
+
 	return err;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -140,6 +140,7 @@
 				address = (low & MASK_BLKPTR_LO) >> 21;
 				if (!address)
 					break;
+
 				address += MCG_XBLK_ADDR;
 			} else
 				++address;
@@ -147,12 +148,8 @@
 			if (rdmsr_safe(address, &low, &high))
 				break;
 
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
+			if (!(high & MASK_VALID_HI))
+				continue;
 
 			if (!(high & MASK_CNTP_HI)  ||
 			     (high & MASK_LOCKED_HI))
@@ -471,6 +468,7 @@
 out_free:
 	if (b) {
 		kobject_put(&b->kobj);
+		list_del(&b->miscj);
 		kfree(b);
 	}
 	return err;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -28,3 +28,4 @@
 
 extern struct mce_bank *mce_banks;
 
+extern void (*mce_cpu_specific_poll)(struct mce *);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -49,6 +49,8 @@
 
 static atomic_t therm_throt_en	= ATOMIC_INIT(0);
 
+static u32 lvtthmr_init __read_mostly;
+
 #ifdef CONFIG_SYSFS
 #define define_therm_throt_sysdev_one_ro(_name)				\
 	static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
@@ -254,14 +256,27 @@
 	ack_APIC_irq();
 }
 
+void __init mcheck_intel_therm_init(void)
+{
+	/*
+	 * This function is only called on boot CPU. Save the init thermal
+	 * LVT value on BSP and use that value to restore APs' thermal LVT
+	 * entry BIOS programmed later
+	 */
+	if (cpu_has(&boot_cpu_data, X86_FEATURE_ACPI) &&
+		cpu_has(&boot_cpu_data, X86_FEATURE_ACC))
+		lvtthmr_init = apic_read(APIC_LVTTHMR);
+}
+
 void intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	unsigned int cpu = smp_processor_id();
 	int tm2 = 0;
 	u32 l, h;
 
-	/* Thermal monitoring depends on ACPI and clock modulation*/
-	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
+	/* Thermal monitoring depends on APIC, ACPI and clock modulation */
+	if (!cpu_has_apic || !cpu_has(c, X86_FEATURE_ACPI) ||
+		!cpu_has(c, X86_FEATURE_ACC))
 		return;
 
 	/*
@@ -270,7 +285,22 @@
 	 * since it might be delivered via SMI already:
 	 */
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	h = apic_read(APIC_LVTTHMR);
+
+	h = lvtthmr_init;
+	/*
+	 * The initial value of thermal LVT entries on all APs always reads
+	 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
+	 * sequence to them and LVT registers are reset to 0s except for
+	 * the mask bits which are set to 1s when APs receive INIT IPI.
+	 * If BIOS takes over the thermal interrupt and sets its interrupt
+	 * delivery mode to SMI (not fixed), it restores the value that the
+	 * BIOS has programmed on AP based on BSP's info we saved since BIOS
+	 * is always setting the same value for all threads/cores.
+	 */
+	if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
+		apic_write(APIC_LVTTHMR, lvtthmr_init);
+
+
 	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
 		printk(KERN_DEBUG
 		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c
@@ -0,0 +1,427 @@
+/*
+ * Xeon 7500 series specific machine check support code.
+ * Copyright 2009, 2010 Intel Corporation
+ * Author: Andi Kleen
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Implement Xeon 7500 series specific code to retrieve the physical address
+ * and DIMM information for corrected memory errors.
+ *
+ * Interface: mce->aux0/aux1 is mapped to a struct pfa_dimm with pad
+ * redefined to DIMM valid bits. Consumers check CPUID and bank and
+ * then interpret aux0/aux1
+ */
+
+/* #define DEBUG 1 */	/* disable for production */
+#define pr_fmt(x) "MCE: " x
+
+#include <linux/moduleparam.h>
+#include <linux/pci_ids.h>
+#include <linux/hrtimer.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/processor.h>
+#include <asm/e820.h>
+#include <asm/mce.h>
+#include <asm/io.h>
+
+#include "mce-internal.h"
+
+#define PFA_SIG "$PFA"
+#define PFA_SIG_LEN 4
+
+/* DIMM description */
+struct aux_pfa_dimm {
+	u8  fbd_channel_id;
+	u8  ddr_channel_id;
+	u8  ddr_dimm_id;
+	u8  ddr_rank_id;
+	u8  ddr_dimm_bank_id;
+	u8  ddr_dimm_row_id;
+	u8  ddr_dimm_column_id;
+	u8  valid;
+} __attribute__((packed));
+
+struct pfa_dimm {
+	u8  fbd_channel_id;
+	u8  ddr_channel_id;
+	u8  ddr_dimm_id;
+	u8  ddr_rank_id;
+	u8  ddr_dimm_bank_id;
+	u32 ddr_dimm_row_id;
+	u32 ddr_dimm_column_id;
+} __attribute__((packed));
+
+/* Memory translation table in memory. */
+struct pfa_table {
+	u8  sig[PFA_SIG_LEN];	/* Signature: '$PFA' */
+	u16 len;		/* total length */
+	u16 revision;		/* 0x11 */
+	u8  checksum;		/* 8bit sum to zero */
+	u8  db_value;		/* mailbox port command value */
+	u8  db_port;		/* mailbox port */
+	/* end of header; end of checksum */
+	u8  command;		/* input command */
+	u32 valid;		/* valid input/output bits */
+	u16 status;		/* output status */
+	u8  socket_id;		/* input socket id*/
+	u8  bank_id;		/* input MCE bank id */
+	u32 pad1;
+	u64 mbox_address;
+	u64 physical_addr;	/* physical address */
+	struct pfa_dimm dimm[2];
+	/*
+	 * topology information follows: not used for now.
+	 */
+} __attribute__((packed));
+
+/* DIMM valid bits in valid: DIMM0: 8..12; DIMM1 16..20 */
+#define DIMM_VALID_BITS(val, num) (((val) >> (4 + (num) * 8)) & DIMM_VALID_ALL)
+#define DIMM_SET_VALID(val, num)  ((val) << (4 + (num) * 8))
+
+enum {
+	MCE_BANK_MBOX0		= 8,
+	MCE_BANK_MBOX1		= 9,
+
+	PFA_REVISION		= 0x11,		/* v1.1 */
+
+	/* Status bits for valid field */
+	PFA_VALID_MA            = (1 << 0),
+	PFA_VALID_SOCKETID      = (1 << 1),
+	PFA_VALID_BANKID        = (1 << 2),
+	PFA_VALID_PA            = (1 << 3),
+
+	/* DIMM valid bits in valid */
+	/* use with DIMM_VALID_BITS/DIMM_SET_VALID for pfa->valid */
+	DIMM_VALID_FBD_CHAN      = (1 << 0),
+	DIMM_VALID_DDR_CHAN      = (1 << 1),
+	DIMM_VALID_DDR_DIMM      = (1 << 2),
+	DIMM_VALID_DDR_RANK      = (1 << 3),
+	DIMM_VALID_DIMM_BANK     = (1 << 4),
+	DIMM_VALID_DIMM_ROW      = (1 << 5),
+	DIMM_VALID_DIMM_COLUMN   = (1 << 6),
+	DIMM_VALID_ALL		 = 0x7f,
+
+	PFA_DIMM_VALID_MASK	 = DIMM_SET_VALID(DIMM_VALID_ALL, 0)
+				 | DIMM_SET_VALID(DIMM_VALID_ALL, 1),
+
+	/* Values for status field */
+	PFA_STATUS_SUCCESS      = 0,
+	PFA_STATUS_SOCKET_INVALID  = (1 << 1),
+	PFA_STATUS_MBOX_INVALID = (1 << 2),
+	PFA_STATUS_MA_INVALID   = (1 << 3),
+	PFA_STATUS_PA_INVALID   = (1 << 4),
+
+	/* Values for command field */
+	PFA_CMD_GET_MEM_CORR_ERR_PA = 0,
+	PFA_CMD_PA_TO_DIMM_ADDR     = 1,
+	PFA_CMD_DIMM_TO_PA	    = 2,
+	PFA_CMD_GET_TOPOLOGY	    = 3,
+
+	/* PCI device IDs and the base register */
+	ICH_PFA_CFG             = 0x8c, /* SCRATCH4 */
+	PCI_DEVICE_ID_BXB_ICH_LEGACY0 = 0x3422,
+};
+
+static struct pfa_table *pfa_table __read_mostly;
+static int memerr_max_conv_rate __read_mostly = 100;
+static int memerr_min_interval __read_mostly = 500;
+static int pfa_lost;	/* for diagnosis */
+
+enum {
+	RATE_LIMIT_PERIOD = USEC_PER_SEC, /* in us; period of rate limit */
+};
+
+module_param(memerr_max_conv_rate, int, 0644);
+MODULE_PARM_DESC(memerr_max_conv_rate,
+	"Maximum number of memory error conversions each second; 0 to disable");
+module_param(memerr_min_interval, int, 0644);
+MODULE_PARM_DESC(memerr_min_interval,
+	"Minimum time delta between two memory conversions; in us; default 500");
+
+static int notest;
+static int nocsum;
+module_param(notest, int, 0);
+module_param(nocsum, int, 0);
+
+static u64 encode_dimm(struct pfa_dimm *d, u8 valid)
+{
+	union {
+		struct aux_pfa_dimm d;
+		u64 v;
+	} p;
+
+	BUILD_BUG_ON(sizeof(struct aux_pfa_dimm) != sizeof(u64));
+	p.d.fbd_channel_id = d->fbd_channel_id;
+	p.d.ddr_channel_id = d->ddr_channel_id;
+	p.d.ddr_dimm_id = d->ddr_dimm_id;
+	p.d.ddr_rank_id = d->ddr_rank_id;
+	p.d.ddr_dimm_bank_id = d->ddr_dimm_bank_id;
+	p.d.ddr_dimm_row_id = d->ddr_dimm_row_id;
+	if (p.d.ddr_dimm_row_id != d->ddr_dimm_row_id) /* truncated? */
+		valid &= ~DIMM_VALID_DIMM_ROW;
+	p.d.ddr_dimm_column_id = d->ddr_dimm_column_id;
+	if (p.d.ddr_dimm_column_id != d->ddr_dimm_column_id)
+		valid &= ~DIMM_VALID_DIMM_COLUMN;
+	p.d.valid = valid;
+	pr_debug("PFA fbd_ch %u ddr_ch %u dimm %u rank %u bank %u valid %x\n",
+		 d->fbd_channel_id,
+		 d->ddr_channel_id,
+		 d->ddr_dimm_id,
+		 d->ddr_rank_id,
+		 d->ddr_dimm_bank_id,
+		 valid);
+	return p.v;
+}
+
+static u8 csum(u8 *table, u16 len)
+{
+	u8 sum = 0;
+	int i;
+	for (i = 0; i < len; i++)
+		sum += *table++;
+	return sum;
+}
+
+/*
+ * Execute a command through the mailbox interface.
+ */
+static int
+pfa_command(unsigned bank, unsigned socketid, unsigned command, unsigned valid)
+{
+	pfa_table->bank_id = bank;
+	pfa_table->socket_id = socketid;
+	pfa_table->valid = valid | PFA_VALID_SOCKETID;
+	pfa_table->command = command;
+
+	outb(pfa_table->db_value, pfa_table->db_port);
+
+	mb();	/* Reread fields after they got changed */
+
+	if (pfa_table->status != PFA_STATUS_SUCCESS) {
+		pr_debug("Memory PFA command %d failed: socket:%d bank:%d status:%x\n",
+			command, socketid, bank, pfa_table->status);
+		return -pfa_table->status;
+	}
+	return 0;
+}
+
+/*
+ * Retrieve physical address and DIMMs.
+ */
+static int translate_memory_error(struct mce *m)
+{
+	struct pfa_table *pfa = pfa_table;
+	u64 status;
+	int ret;
+	u32 valid;
+	int cpu = smp_processor_id();
+
+	/* Make sure our structures match the specification */
+	BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20);
+	BUILD_BUG_ON(offsetof(struct pfa_table, status) != 0x10);
+	BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20);
+	BUILD_BUG_ON(offsetof(struct pfa_table, dimm[1].ddr_dimm_column_id) !=
+			0x3e);
+
+	/* Ask for PA/DIMMs of last error */
+	if (pfa_command(m->bank, m->socketid,
+			PFA_CMD_GET_MEM_CORR_ERR_PA, PFA_VALID_BANKID) < 0)
+		return -1;
+
+	/*
+	 * Recheck machine check bank. If the overflow bit was set
+	 * there was a race. Don't use the information in this case.
+	 */
+	rdmsrl(MSR_IA32_MCx_STATUS(m->bank), status);
+	if (status & MCI_STATUS_OVER) {
+		pr_debug("%d: overflow race on bank %d\n", cpu, m->bank);
+		return -1;
+	}
+
+	ret = -1;
+	valid = pfa->valid;
+	if (valid & PFA_VALID_PA) {
+		m->status |= MCI_STATUS_ADDRV;
+		m->addr = pfa_table->physical_addr;
+		pr_debug("%d: got physical address %llx valid %x\n",
+			cpu, m->addr, valid);
+		ret = 0;
+	}
+
+	/* When DIMM information was supplied pass it out */
+	if (valid & PFA_DIMM_VALID_MASK) {
+		m->aux0 = encode_dimm(&pfa->dimm[0], DIMM_VALID_BITS(valid, 0));
+		m->aux1 = encode_dimm(&pfa->dimm[1], DIMM_VALID_BITS(valid, 1));
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * Xeon 75xx specific mce poll method to retrieve the physical address
+ * and DIMM information.
+ */
+static void xeon75xx_mce_poll(struct mce *m)
+{
+	static DEFINE_SPINLOCK(convert_lock); /* Protect table and static */
+	static unsigned long cperm;
+	static ktime_t last, last_int;
+	unsigned long flags;
+	ktime_t now;
+	s64 delta;
+
+	/* Memory error? */
+	if (m->bank != MCE_BANK_MBOX0 && m->bank != MCE_BANK_MBOX1)
+		return;
+	if (m->status & MCI_STATUS_OVER)
+		return;
+	if (memerr_max_conv_rate == 0)
+		return;
+
+	spin_lock_irqsave(&convert_lock, flags);
+	/*
+	 * Rate limit conversions. The conversion takes some time,
+	 * but it's not good to use all the CPU time during a error
+	 * flood.
+	 * Enforce maximum number per second and minimum interval.
+	 * The ktime call should use TSC on this machine and be fast.
+	 */
+	now = ktime_get();
+	delta = ktime_us_delta(now, last);
+	if (delta >= RATE_LIMIT_PERIOD) {
+		cperm = 0;
+		last = now;
+	}
+	if (ktime_us_delta(now, last_int) >= memerr_min_interval &&
+	   ++cperm <= memerr_max_conv_rate) {
+		if (translate_memory_error(m) < 0) {
+			/* On error stop converting for the next second */
+			cperm = memerr_max_conv_rate;
+			pr_debug("PFA translation failed\n");
+		}
+	} else
+		pfa_lost++;
+	last_int = now;
+	spin_unlock_irqrestore(&convert_lock, flags);
+}
+
+static struct pci_device_id bxb_mce_pciids[] = {
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_BXB_ICH_LEGACY0) },
+	{}
+};
+
+static int __init xeon75xx_mce_init(void)
+{
+	u32 addr = 0;
+	struct pci_dev *dev;
+
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+	    boot_cpu_data.x86 != 6 ||
+	    boot_cpu_data.x86_model != 0x2e)
+		return -ENODEV;
+
+	/*
+	 * Get table address from register in IOH.
+	 * This just looks up the device, because we don't want to "own" it.
+	 */
+	dev = NULL;
+	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, dev))
+			!= NULL) {
+		if (!pci_match_id(bxb_mce_pciids, dev))
+			continue;
+		pci_read_config_dword(dev, ICH_PFA_CFG, &addr);
+		if (addr)
+			break;
+	}
+	pci_dev_put(dev);
+	if (!addr)
+		return -ENODEV;
+
+	if (!e820_all_mapped(addr, addr + PAGE_SIZE, E820_RESERVED)) {
+		pr_info("PFA table at %x not e820 reserved\n", addr);
+		return -ENODEV;
+	}
+
+	pfa_table = (__force struct pfa_table *)ioremap_cache(addr, PAGE_SIZE);
+	if (!pfa_table) {
+		pr_err("Cannot map PFA table at %x\n", addr);
+		return -EIO;
+	}
+
+	if (memcmp(&pfa_table->sig, PFA_SIG, PFA_SIG_LEN) ||
+	    pfa_table->len < sizeof(struct pfa_table) ||
+	    /* assume newer versions are compatible */
+	    pfa_table->revision < PFA_REVISION) {
+		pr_info("PFA table at %x invalid\n", addr);
+		goto error_unmap;
+	}
+
+	if (!nocsum && csum((u8 *)pfa_table,
+				offsetof(struct pfa_table, command))) {
+		pr_info("PFA table at %x length %u has invalid checksum\n",
+			addr, pfa_table->len);
+		goto error_unmap;
+	}
+
+	/* Not strictly needed today */
+	if (pfa_table->len > PAGE_SIZE) {
+		unsigned len = roundup(pfa_table->len, PAGE_SIZE);
+		iounmap(pfa_table);
+		pfa_table = (__force void *)ioremap_cache(addr, len);
+		if (!pfa_table) {
+			pr_err("Cannot remap %u bytes PFA table at %x\n",
+				len, addr);
+			return -EIO;
+		}
+	}
+
+	if (!notest) {
+		int status = pfa_command(0, 0, PFA_CMD_GET_TOPOLOGY, 0);
+		if (status < 0) {
+			pr_err("Test of PFA table failed: %x\n", -status);
+			goto error_unmap;
+		}
+	}
+
+	pr_info("Found Xeon75xx PFA memory error translation table at %x\n",
+		addr);
+	mb();
+	mce_cpu_specific_poll = xeon75xx_mce_poll;
+	return 0;
+
+error_unmap:
+	iounmap(pfa_table);
+	return -ENODEV;
+}
+
+MODULE_DEVICE_TABLE(pci, bxb_mce_pciids);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Andi Kleen");
+MODULE_DESCRIPTION("Intel Xeon 75xx specific DIMM error reporting");
+
+#ifdef CONFIG_MODULE
+static void __exit xeon75xx_mce_exit(void)
+{
+	mce_cpu_specific_poll = NULL;
+	wmb();
+	/* Wait for all machine checks to finish before really unloading */
+	synchronize_rcu();
+	iounmap(pfa_table);
+}
+
+module_init(xeon75xx_mce_init);
+module_exit(xeon75xx_mce_exit);
+#else
+/* When built-in run as soon as the PCI subsystem is up */
+fs_initcall(xeon75xx_mce_init);
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -45,6 +45,7 @@
 	CPU_DOTHAN_A1,
 	CPU_DOTHAN_A2,
 	CPU_DOTHAN_B0,
+	CPU_DOTHAN_C0,
 	CPU_MP4HT_D0,
 	CPU_MP4HT_E0,
 };
@@ -54,6 +55,7 @@
 	[CPU_DOTHAN_A1]	= { 6, 13, 1 },
 	[CPU_DOTHAN_A2]	= { 6, 13, 2 },
 	[CPU_DOTHAN_B0]	= { 6, 13, 6 },
+	[CPU_DOTHAN_C0]	= { 6, 13, 8 },
 	[CPU_MP4HT_D0]	= {15,  3, 4 },
 	[CPU_MP4HT_E0]	= {15,  4, 1 },
 };
@@ -196,6 +198,88 @@
 };
 #undef OP
 
+
+#define OPEX(mhz, base, mva, mvb, mvc, mvd)                     \
+{                                                               \
+        .frequency = (mhz) * 1000,                              \
+        .index = (((mhz)/(base)) << 8) | ((mva - 700) / 16)     \
+}
+
+/* Intel Pentium M processor 730 / 1.60 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_1596[] =
+{
+        OPEX( 798, 133,  988,  988,  988,  988),
+        OPEX(1064, 133, 1116, 1111, 1084, 1079),
+        OPEX(1330, 133, 1244, 1233, 1180, 1169),
+        OPEX(1596, 133, 1356, 1356, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+
+/* Intel Pentium M processor 740 / 1.73 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_1729[] =
+{
+        OPEX( 798, 133,  988,  988,  988,  988),
+        OPEX(1064, 133, 1100, 1093, 1068, 1066),
+        OPEX(1330, 133, 1212, 1198, 1148, 1143),
+        OPEX(1729, 133, 1356, 1356, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+
+/* Intel Pentium M processor 750 / 1.86 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_1862[] =
+{
+        OPEX( 798, 133,  988,  988,  988,  988),
+        OPEX(1064, 133, 1084, 1080, 1068, 1056),
+        OPEX(1330, 133, 1180, 1172, 1132, 1124),
+        OPEX(1596, 133, 1276, 1264, 1196, 1192),
+        OPEX(1862, 133, 1356, 1356, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+
+/* Intel Pentium M processor 760 / 2.00 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_1995[] =
+{
+        OPEX( 798, 133, 988, 988, 988, 988),
+        OPEX(1064, 133, 1084, 1070, 1052, 1048),
+        OPEX(1330, 133, 1164, 1152, 1116, 1109),
+        OPEX(1596, 133, 1244, 1233, 1180, 1169),
+        OPEX(1995, 133, 1356, 1356, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+/* Intel Pentium M processor 770 / 2.13 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_2128[] =
+{
+        OPEX( 798, 133, 988, 988, 988, 988),
+        OPEX(1064, 133, 1068, 1065, 1052, 1042),
+        OPEX(1330, 133, 1148, 1142, 1100, 1097),
+        OPEX(1596, 133, 1228, 1218, 1164, 1151),
+        OPEX(1862, 133, 1308, 1295, 1212, 1206),
+        OPEX(2128, 133, 1372, 1372, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+
+/* Intel Pentium M processor 780 / 2.26 GHz (Sonoma) */
+static struct cpufreq_frequency_table sonoma_2261[] =
+{
+        OPEX( 798, 133, 988, 988, 988, 988),
+        OPEX(1064, 133, 1068, 1064, 1052, 1037),
+        OPEX(1330, 133, 1148, 1139, 1100, 1087),
+        OPEX(1596, 133, 1228, 1215, 1148, 1136),
+        OPEX(1862, 133, 1292, 1291, 1196, 1186),
+        OPEX(2261, 133, 1404, 1404, 1260, 1260),
+        { .frequency = CPUFREQ_TABLE_END }
+};
+
+#undef OPEX
+
+#define SONOMA(cpuid, max, base, name)  \
+{       .cpu_id         = cpuid,        \
+        .model_name     = "Intel(R) Pentium(R) M processor " name "GHz", \
+        .max_freq       = (max)*1000,   \
+        .op_points      = sonoma_##max, \
+}
+
+
 #define _BANIAS(cpuid, max, name)	\
 {	.cpu_id		= cpuid,	\
 	.model_name	= "Intel(R) Pentium(R) M processor " name "MHz", \
@@ -218,6 +302,15 @@
 	BANIAS(1600),
 	BANIAS(1700),
 
+        /* Builtin tables for Dothan C0 CPUs, a.k.a Sonoma */
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1596, 133, "1.60"),
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1729, 133, "1.73"),
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1862, 133, "1.86"),
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 1995, 133, "2.00"),
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2128, 133, "2.13"),
+        SONOMA(&cpu_ids[CPU_DOTHAN_C0], 2261, 133, "2.26"),
+
+
 	/* NULL model_name is a wildcard */
 	{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
 	{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -929,7 +929,8 @@
 		powernow_table[i].index = index;
 
 		/* Frequency may be rounded for these */
-		if (boot_cpu_data.x86 == 0x10 || boot_cpu_data.x86 == 0x11) {
+		if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
+				 || boot_cpu_data.x86 == 0x11) {
 			powernow_table[i].frequency =
 				freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
 		} else
@@ -1351,6 +1352,7 @@
 
 	kfree(data->powernow_table);
 	kfree(data);
+	per_cpu(powernow_data, pol->cpu) = NULL;
 
 	return 0;
 }
@@ -1370,7 +1372,7 @@
 	int err;
 
 	if (!data)
-		return -EINVAL;
+		return 0;
 
 	smp_call_function_single(cpu, query_values_on_cpu, &err, true);
 	if (err)
--- linux-ec2-2.6.32.orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ linux-ec2-2.6.32/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -741,6 +741,7 @@
 		per_cpu(drv_data, policy->cpu) = NULL;
 		acpi_processor_unregister_performance(data->acpi_data,
 						      policy->cpu);
+		kfree(data->freq_table);
 		kfree(data);
 	}
 
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/Makefile
@@ -17,3 +17,8 @@
 obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 obj-$(CONFIG_X86_ES7000)	+= es7000_32.o
 obj-$(CONFIG_X86_SUMMIT)	+= summit_32.o
+
+probe_64-$(CONFIG_XEN)		:= probe_32.o
+
+disabled-obj-$(CONFIG_XEN)	:= apic_flat_$(BITS).o
+disabled-obj-$(filter-out $(CONFIG_SMP),$(CONFIG_XEN)) += ipi.o
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/apic_flat_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/apic_flat_64.c
@@ -240,6 +240,11 @@
 		printk(KERN_DEBUG "system APIC only can use physical flat");
 		return 1;
 	}
+
+	if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
+		printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
+		return 1;
+	}
 #endif
 
 	return 0;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/ipi-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/ipi-xen.c
@@ -0,0 +1,86 @@
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/cache.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/apic.h>
+#include <asm/proto.h>
+#include <asm/ipi.h>
+
+#include <xen/evtchn.h>
+
+static void __send_IPI_shortcut(unsigned int shortcut, int vector)
+{
+	unsigned int cpu;
+
+	switch (shortcut) {
+	case APIC_DEST_SELF:
+		notify_remote_via_ipi(vector, smp_processor_id());
+		break;
+	case APIC_DEST_ALLBUT:
+		for_each_online_cpu(cpu)
+			if (cpu != smp_processor_id())
+				notify_remote_via_ipi(vector, cpu);
+		break;
+	case APIC_DEST_ALLINC:
+		for_each_online_cpu(cpu)
+			notify_remote_via_ipi(vector, cpu);
+		break;
+	default:
+		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
+		       vector);
+		break;
+	}
+}
+
+void xen_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
+{
+	unsigned int cpu;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
+	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
+		if (cpu != smp_processor_id())
+			notify_remote_via_ipi(vector, cpu);
+	local_irq_restore(flags);
+}
+
+void xen_send_IPI_mask(const struct cpumask *cpumask, int vector)
+{
+	unsigned int cpu;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	WARN_ON(!cpumask_subset(cpumask, cpu_online_mask));
+	for_each_cpu_and(cpu, cpumask, cpu_online_mask)
+		notify_remote_via_ipi(vector, cpu);
+	local_irq_restore(flags);
+}
+
+void xen_send_IPI_allbutself(int vector)
+{
+	__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+}
+
+void xen_send_IPI_all(int vector)
+{
+	__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+}
+
+void xen_send_IPI_self(int vector)
+{
+	__send_IPI_shortcut(APIC_DEST_SELF, vector);
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/io_apic.c
@@ -332,14 +332,19 @@
 
 	old_cfg = old_desc->chip_data;
 
-	memcpy(cfg, old_cfg, sizeof(struct irq_cfg));
+	cfg->vector = old_cfg->vector;
+	cfg->move_in_progress = old_cfg->move_in_progress;
+	cpumask_copy(cfg->domain, old_cfg->domain);
+	cpumask_copy(cfg->old_domain, old_cfg->old_domain);
 
 	init_copy_irq_2_pin(old_cfg, cfg, node);
 }
 
-static void free_irq_cfg(struct irq_cfg *old_cfg)
+static void free_irq_cfg(struct irq_cfg *cfg)
 {
-	kfree(old_cfg);
+	free_cpumask_var(cfg->domain);
+	free_cpumask_var(cfg->old_domain);
+	kfree(cfg);
 }
 
 void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
@@ -1405,6 +1410,7 @@
 		irte.dlvry_mode = apic->irq_delivery_mode;
 		irte.vector = vector;
 		irte.dest_id = IRTE_DEST(destination);
+		irte.redir_hint = 1;
 
 		/* Set source-id of interrupt request */
 		set_ioapic_sid(&irte, apic_id);
@@ -1484,7 +1490,7 @@
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int apic_id, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1492,14 +1498,7 @@
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1521,6 +1520,9 @@
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -1550,6 +1552,56 @@
 }
 
 /*
+ * for the gsit that is not in first ioapic
+ * but could not use acpi_register_gsi()
+ * like some special sci in IBM x3330
+ */
+void setup_IO_APIC_irq_extra(u32 gsi)
+{
+	int apic_id = 0, pin, idx, irq;
+	int node = cpu_to_node(boot_cpu_id);
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+
+	/*
+	 * Convert 'gsi' to 'ioapic.pin'.
+	 */
+	apic_id = mp_find_ioapic(gsi);
+	if (apic_id < 0)
+		return;
+
+	pin = mp_find_ioapic_pin(apic_id, gsi);
+	idx = find_irq_entry(apic_id, pin, mp_INT);
+	if (idx == -1)
+		return;
+
+	irq = pin_2_irq(idx, apic_id, pin);
+#ifdef CONFIG_SPARSE_IRQ
+	desc = irq_to_desc(irq);
+	if (desc)
+		return;
+#endif
+	desc = irq_to_desc_alloc_node(irq, node);
+	if (!desc) {
+		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+		return;
+	}
+
+	cfg = desc->chip_data;
+	add_pin_to_irq_node(cfg, node, apic_id, pin);
+
+	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[apic_id].apicid, pin);
+		return;
+	}
+	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+
+	setup_IO_APIC_irq(apic_id, pin, irq, desc,
+			irq_trigger(idx), irq_polarity(idx));
+}
+
+/*
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
 static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
@@ -1690,6 +1742,8 @@
 		struct irq_pin_list *entry;
 
 		cfg = desc->chip_data;
+		if (!cfg)
+			continue;
 		entry = cfg->irq_2_pin;
 		if (!entry)
 			continue;
@@ -3157,6 +3211,7 @@
 			continue;
 
 		desc_new = move_irq_desc(desc_new, node);
+		cfg_new = desc_new->chip_data;
 
 		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
 			irq = new;
@@ -3164,12 +3219,9 @@
 	}
 	spin_unlock_irqrestore(&vector_lock, flags);
 
-	if (irq > 0) {
-		dynamic_irq_init(irq);
-		/* restore it, in case dynamic_irq_init clear it */
-		if (desc_new)
-			desc_new->chip_data = cfg_new;
-	}
+	if (irq > 0)
+		dynamic_irq_init_keep_chip_data(irq);
+
 	return irq;
 }
 
@@ -3192,17 +3244,12 @@
 {
 	unsigned long flags;
 	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 
-	/* store it, in case dynamic_irq_cleanup clear it */
-	desc = irq_to_desc(irq);
-	cfg = desc->chip_data;
-	dynamic_irq_cleanup(irq);
-	/* connect back irq_cfg */
-	desc->chip_data = cfg;
+	dynamic_irq_cleanup_keep_chip_data(irq);
 
 	free_irte(irq);
 	spin_lock_irqsave(&vector_lock, flags);
+	cfg = irq_to_desc(irq)->chip_data;
 	__clear_irq_vector(irq, cfg);
 	spin_unlock_irqrestore(&vector_lock, flags);
 }
@@ -3243,6 +3290,7 @@
 		irte.dlvry_mode = apic->irq_delivery_mode;
 		irte.vector = cfg->vector;
 		irte.dest_id = IRTE_DEST(dest);
+		irte.redir_hint = 1;
 
 		/* Set source-id of interrupt request */
 		set_msi_sid(&irte, pdev);
@@ -3297,7 +3345,7 @@
 
 	cfg = desc->chip_data;
 
-	read_msi_msg_desc(desc, &msg);
+	get_cached_msi_msg_desc(desc, &msg);
 
 	msg.data &= ~MSI_DATA_VECTOR_MASK;
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
@@ -3519,6 +3567,7 @@
 	msg.data |= MSI_DATA_VECTOR(cfg->vector);
 	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
 	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
 
 	dmar_msi_write(irq, &msg);
 
@@ -4040,27 +4089,23 @@
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
-
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
 		desc = irq_to_desc(irq);
 
 		/*
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/apic.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/apic.c
@@ -51,6 +51,7 @@
 #include <asm/smp.h>
 #include <asm/mce.h>
 #include <asm/kvm_para.h>
+#include <asm/tsc.h>
 
 unsigned int num_processors;
 
@@ -246,7 +247,7 @@
  */
 static void native_apic_write_dummy(u32 reg, u32 v)
 {
-	WARN_ON_ONCE((cpu_has_apic || !disable_apic));
+	WARN_ON_ONCE(cpu_has_apic && !disable_apic);
 }
 
 static u32 native_apic_read_dummy(u32 reg)
@@ -941,7 +942,7 @@
 	unsigned int value;
 
 	/* APIC hasn't been mapped yet */
-	if (!apic_phys)
+	if (!x2apic_mode && !apic_phys)
 		return;
 
 	clear_local_APIC();
@@ -1172,8 +1173,13 @@
  */
 void __cpuinit setup_local_APIC(void)
 {
-	unsigned int value;
-	int i, j;
+	unsigned int value, queued;
+	int i, j, acked = 0;
+	unsigned long long tsc = 0, ntsc;
+	long long max_loops = cpu_khz;
+
+	if (cpu_has_tsc)
+		rdtscll(tsc);
 
 	if (disable_apic) {
 		arch_disable_smp_support();
@@ -1225,13 +1231,32 @@
 	 * the interrupt. Hence a vector might get locked. It was noticed
 	 * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
 	 */
-	for (i = APIC_ISR_NR - 1; i >= 0; i--) {
-		value = apic_read(APIC_ISR + i*0x10);
-		for (j = 31; j >= 0; j--) {
-			if (value & (1<<j))
-				ack_APIC_irq();
+	do {
+		queued = 0;
+		for (i = APIC_ISR_NR - 1; i >= 0; i--)
+			queued |= apic_read(APIC_IRR + i*0x10);
+
+		for (i = APIC_ISR_NR - 1; i >= 0; i--) {
+			value = apic_read(APIC_ISR + i*0x10);
+			for (j = 31; j >= 0; j--) {
+				if (value & (1<<j)) {
+					ack_APIC_irq();
+					acked++;
+				}
+			}
 		}
-	}
+		if (acked > 256) {
+			printk(KERN_ERR "LAPIC pending interrupts after %d EOI\n",
+			       acked);
+			break;
+		}
+		if (cpu_has_tsc) {
+			rdtscll(ntsc);
+			max_loops = (cpu_khz << 10) - (ntsc - tsc);
+		} else
+			max_loops--;
+	} while (queued && max_loops > 0);
+	WARN_ON(max_loops <= 0);
 
 	/*
 	 * Now that we are all set up, enable the APIC
@@ -1336,6 +1361,14 @@
 
 	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
+
+	/*
+	 * Now that local APIC setup is completed for BP, configure the fault
+	 * handling for interrupt remapping.
+	 */
+	if (!smp_processor_id() && intr_remapping_enabled)
+		enable_drhd_fault_handling();
+
 }
 
 #ifdef CONFIG_X86_X2APIC
@@ -1664,8 +1697,8 @@
 	}
 #endif
 
+#ifndef CONFIG_SMP
 	enable_IR_x2apic();
-#ifdef CONFIG_X86_64
 	default_setup_apic_routing();
 #endif
 
@@ -1915,18 +1948,6 @@
 	if (apicid > max_physical_apicid)
 		max_physical_apicid = apicid;
 
-#ifdef CONFIG_X86_32
-	switch (boot_cpu_data.x86_vendor) {
-	case X86_VENDOR_INTEL:
-		if (num_processors > 8)
-			def_to_bigsmp = 1;
-		break;
-	case X86_VENDOR_AMD:
-		if (max_physical_apicid >= 8)
-			def_to_bigsmp = 1;
-	}
-#endif
-
 #if defined(CONFIG_SMP) || defined(CONFIG_X86_64)
 	early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
 	early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/io_apic-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/io_apic-xen.c
@@ -0,0 +1,4428 @@
+/*
+ *	Intel IO-APIC support for multi-Pentium hosts.
+ *
+ *	Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
+ *
+ *	Many thanks to Stig Venaas for trying out countless experimental
+ *	patches and reporting/debugging problems patiently!
+ *
+ *	(c) 1999, Multiple IO-APIC support, developed by
+ *	Ken-ichi Yaku <yaku@css1.kbnes.nec.co.jp> and
+ *      Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
+ *	further tested and cleaned up by Zach Brown <zab@redhat.com>
+ *	and Ingo Molnar <mingo@redhat.com>
+ *
+ *	Fixes
+ *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs;
+ *					thanks to Eric Gilmore
+ *					and Rolf G. Tews
+ *					for testing these extensively
+ *	Paul Diefenbaugh	:	Added full ACPI support
+ */
+
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/mc146818rtc.h>
+#include <linux/compiler.h>
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/sysdev.h>
+#include <linux/msi.h>
+#include <linux/htirq.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/jiffies.h>	/* time_after() */
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+#endif
+#include <linux/bootmem.h>
+#include <linux/dmar.h>
+#include <linux/hpet.h>
+
+#include <asm/idle.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/cpu.h>
+#include <asm/desc.h>
+#include <asm/proto.h>
+#include <asm/acpi.h>
+#include <asm/dma.h>
+#include <asm/timer.h>
+#include <asm/i8259.h>
+#include <asm/nmi.h>
+#include <asm/msidef.h>
+#include <asm/hypertransport.h>
+#include <asm/setup.h>
+#include <asm/irq_remapping.h>
+#include <asm/hpet.h>
+#include <asm/hw_irq.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/uv_irq.h>
+
+#include <asm/apic.h>
+
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#include <xen/interface/physdev.h>
+#include <xen/evtchn.h>
+
+/* Fake i8259 */
+#define make_8259A_irq(_irq)     (io_apic_irqs &= ~(1UL<<(_irq)))
+#define disable_8259A_irq(_irq)  ((void)0)
+#define i8259A_irq_pending(_irq) (0)
+
+unsigned long io_apic_irqs;
+#endif /* CONFIG_XEN */
+
+#define __apicdebuginit(type) static type __init
+#define for_each_irq_pin(entry, head) \
+	for (entry = head; entry; entry = entry->next)
+
+/*
+ *      Is the SiS APIC rmw bug present ?
+ *      -1 = don't know, 0 = no, 1 = yes
+ */
+int sis_apic_bug = -1;
+
+static DEFINE_SPINLOCK(ioapic_lock);
+#ifndef CONFIG_XEN
+static DEFINE_SPINLOCK(vector_lock);
+#endif
+
+/*
+ * # of IRQ routing registers
+ */
+int nr_ioapic_registers[MAX_IO_APICS];
+
+/* I/O APIC entries */
+struct mpc_ioapic mp_ioapics[MAX_IO_APICS];
+int nr_ioapics;
+
+/* IO APIC gsi routing info */
+struct mp_ioapic_gsi  mp_gsi_routing[MAX_IO_APICS];
+
+/* MP IRQ source entries */
+struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
+
+/* # of MP IRQ source entries */
+int mp_irq_entries;
+
+#ifndef CONFIG_XEN
+/* Number of legacy interrupts */
+static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
+/* GSI interrupts */
+static int nr_irqs_gsi = NR_IRQS_LEGACY;
+#else
+#define nr_legacy_irqs NR_IRQS_LEGACY
+#endif
+
+#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
+int mp_bus_id_to_type[MAX_MP_BUSSES];
+#endif
+
+DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
+
+int skip_ioapic_setup;
+
+void arch_disable_smp_support(void)
+{
+#ifdef CONFIG_PCI
+	noioapicquirk = 1;
+	noioapicreroute = -1;
+#endif
+	skip_ioapic_setup = 1;
+}
+
+static int __init parse_noapic(char *str)
+{
+	/* disable IO-APIC */
+	arch_disable_smp_support();
+	return 0;
+}
+early_param("noapic", parse_noapic);
+
+#ifndef CONFIG_XEN
+struct irq_pin_list {
+	int apic, pin;
+	struct irq_pin_list *next;
+};
+
+static struct irq_pin_list *get_one_free_irq_2_pin(int node)
+{
+	struct irq_pin_list *pin;
+
+	pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
+
+	return pin;
+}
+
+/*
+ * This is performance-critical, we want to do it O(1)
+ *
+ * Most irqs are mapped 1:1 with pins.
+ */
+struct irq_cfg {
+	struct irq_pin_list *irq_2_pin;
+	cpumask_var_t domain;
+	cpumask_var_t old_domain;
+	unsigned move_cleanup_count;
+	u8 vector;
+	u8 move_in_progress : 1;
+};
+
+/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+#ifdef CONFIG_SPARSE_IRQ
+static struct irq_cfg irq_cfgx[] = {
+#else
+static struct irq_cfg irq_cfgx[NR_IRQS] = {
+#endif
+	[0]  = { .vector = IRQ0_VECTOR,  },
+	[1]  = { .vector = IRQ1_VECTOR,  },
+	[2]  = { .vector = IRQ2_VECTOR,  },
+	[3]  = { .vector = IRQ3_VECTOR,  },
+	[4]  = { .vector = IRQ4_VECTOR,  },
+	[5]  = { .vector = IRQ5_VECTOR,  },
+	[6]  = { .vector = IRQ6_VECTOR,  },
+	[7]  = { .vector = IRQ7_VECTOR,  },
+	[8]  = { .vector = IRQ8_VECTOR,  },
+	[9]  = { .vector = IRQ9_VECTOR,  },
+	[10] = { .vector = IRQ10_VECTOR, },
+	[11] = { .vector = IRQ11_VECTOR, },
+	[12] = { .vector = IRQ12_VECTOR, },
+	[13] = { .vector = IRQ13_VECTOR, },
+	[14] = { .vector = IRQ14_VECTOR, },
+	[15] = { .vector = IRQ15_VECTOR, },
+};
+
+void __init io_apic_disable_legacy(void)
+{
+	nr_legacy_irqs = 0;
+	nr_irqs_gsi = 0;
+}
+
+int __init arch_early_irq_init(void)
+{
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+	int count;
+	int node;
+	int i;
+
+	cfg = irq_cfgx;
+	count = ARRAY_SIZE(irq_cfgx);
+	node= cpu_to_node(boot_cpu_id);
+
+	for (i = 0; i < count; i++) {
+		desc = irq_to_desc(i);
+		desc->chip_data = &cfg[i];
+		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
+		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
+		if (i < nr_legacy_irqs)
+			cpumask_setall(cfg[i].domain);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SPARSE_IRQ
+static struct irq_cfg *irq_cfg(unsigned int irq)
+{
+	struct irq_cfg *cfg = NULL;
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+	if (desc)
+		cfg = desc->chip_data;
+
+	return cfg;
+}
+
+static struct irq_cfg *get_one_free_irq_cfg(int node)
+{
+	struct irq_cfg *cfg;
+
+	cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
+	if (cfg) {
+		if (!zalloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
+			kfree(cfg);
+			cfg = NULL;
+		} else if (!zalloc_cpumask_var_node(&cfg->old_domain,
+							  GFP_ATOMIC, node)) {
+			free_cpumask_var(cfg->domain);
+			kfree(cfg);
+			cfg = NULL;
+		}
+	}
+
+	return cfg;
+}
+
+int arch_init_chip_data(struct irq_desc *desc, int node)
+{
+	struct irq_cfg *cfg;
+
+	cfg = desc->chip_data;
+	if (!cfg) {
+		desc->chip_data = get_one_free_irq_cfg(node);
+		if (!desc->chip_data) {
+			printk(KERN_ERR "can not alloc irq_cfg\n");
+			BUG_ON(1);
+		}
+	}
+
+	return 0;
+}
+
+/* for move_irq_desc */
+static void
+init_copy_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg, int node)
+{
+	struct irq_pin_list *old_entry, *head, *tail, *entry;
+
+	cfg->irq_2_pin = NULL;
+	old_entry = old_cfg->irq_2_pin;
+	if (!old_entry)
+		return;
+
+	entry = get_one_free_irq_2_pin(node);
+	if (!entry)
+		return;
+
+	entry->apic	= old_entry->apic;
+	entry->pin	= old_entry->pin;
+	head		= entry;
+	tail		= entry;
+	old_entry	= old_entry->next;
+	while (old_entry) {
+		entry = get_one_free_irq_2_pin(node);
+		if (!entry) {
+			entry = head;
+			while (entry) {
+				head = entry->next;
+				kfree(entry);
+				entry = head;
+			}
+			/* still use the old one */
+			return;
+		}
+		entry->apic	= old_entry->apic;
+		entry->pin	= old_entry->pin;
+		tail->next	= entry;
+		tail		= entry;
+		old_entry	= old_entry->next;
+	}
+
+	tail->next = NULL;
+	cfg->irq_2_pin = head;
+}
+
+static void free_irq_2_pin(struct irq_cfg *old_cfg, struct irq_cfg *cfg)
+{
+	struct irq_pin_list *entry, *next;
+
+	if (old_cfg->irq_2_pin == cfg->irq_2_pin)
+		return;
+
+	entry = old_cfg->irq_2_pin;
+
+	while (entry) {
+		next = entry->next;
+		kfree(entry);
+		entry = next;
+	}
+	old_cfg->irq_2_pin = NULL;
+}
+
+void arch_init_copy_chip_data(struct irq_desc *old_desc,
+				 struct irq_desc *desc, int node)
+{
+	struct irq_cfg *cfg;
+	struct irq_cfg *old_cfg;
+
+	cfg = get_one_free_irq_cfg(node);
+
+	if (!cfg)
+		return;
+
+	desc->chip_data = cfg;
+
+	old_cfg = old_desc->chip_data;
+
+	cfg->vector = old_cfg->vector;
+	cfg->move_in_progress = old_cfg->move_in_progress;
+	cpumask_copy(cfg->domain, old_cfg->domain);
+	cpumask_copy(cfg->old_domain, old_cfg->old_domain);
+
+	init_copy_irq_2_pin(old_cfg, cfg, node);
+}
+
+static void free_irq_cfg(struct irq_cfg *cfg)
+{
+	free_cpumask_var(cfg->domain);
+	free_cpumask_var(cfg->old_domain);
+	kfree(cfg);
+}
+
+void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
+{
+	struct irq_cfg *old_cfg, *cfg;
+
+	old_cfg = old_desc->chip_data;
+	cfg = desc->chip_data;
+
+	if (old_cfg == cfg)
+		return;
+
+	if (old_cfg) {
+		free_irq_2_pin(old_cfg, cfg);
+		free_irq_cfg(old_cfg);
+		old_desc->chip_data = NULL;
+	}
+}
+/* end for move_irq_desc */
+
+#else
+static struct irq_cfg *irq_cfg(unsigned int irq)
+{
+	return irq < nr_irqs ? irq_cfgx + irq : NULL;
+}
+
+#endif
+
+struct io_apic {
+	unsigned int index;
+	unsigned int unused[3];
+	unsigned int data;
+	unsigned int unused2[11];
+	unsigned int eoi;
+};
+
+static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
+{
+	return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
+		+ (mp_ioapics[idx].apicaddr & ~PAGE_MASK);
+}
+
+static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(vector, &io_apic->eoi);
+}
+#endif /* CONFIG_XEN */
+
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+#ifndef CONFIG_XEN
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(reg, &io_apic->index);
+	return readl(&io_apic->data);
+#else
+	struct physdev_apic apic_op;
+	int ret;
+
+	apic_op.apic_physbase = mp_ioapics[apic].apicaddr;
+	apic_op.reg = reg;
+	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+	if (ret)
+		return ret;
+	return apic_op.value;
+#endif
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+#ifndef CONFIG_XEN
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+	writel(reg, &io_apic->index);
+	writel(value, &io_apic->data);
+#else
+	struct physdev_apic apic_op;
+
+	apic_op.apic_physbase = mp_ioapics[apic].apicaddr;
+	apic_op.reg = reg;
+	apic_op.value = value;
+	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op));
+#endif
+}
+
+#ifdef CONFIG_XEN
+#define io_apic_modify io_apic_write
+#else
+/*
+ * Re-write a value: to be used for read-modify-write
+ * cycles where the read already set up the index register.
+ *
+ * Older SiS APIC requires we rewrite the index register
+ */
+static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
+{
+	struct io_apic __iomem *io_apic = io_apic_base(apic);
+
+	if (sis_apic_bug)
+		writel(reg, &io_apic->index);
+	writel(value, &io_apic->data);
+}
+
+static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
+{
+	struct irq_pin_list *entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	for_each_irq_pin(entry, cfg->irq_2_pin) {
+		unsigned int reg;
+		int pin;
+
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin*2);
+		/* Is the remote IRR bit set? */
+		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
+			spin_unlock_irqrestore(&ioapic_lock, flags);
+			return true;
+		}
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return false;
+}
+#endif /* CONFIG_XEN */
+
+union entry_union {
+	struct { u32 w1, w2; };
+	struct IO_APIC_route_entry entry;
+};
+
+#ifndef CONFIG_XEN
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+	union entry_union eu;
+	unsigned long flags;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+	return eu.entry;
+}
+#endif
+
+/*
+ * When we write a new IO APIC routing entry, we need to write the high
+ * word first! If the mask bit in the low word is clear, we will enable
+ * the interrupt, and we need to make sure the entry is fully populated
+ * before that happens.
+ */
+static void
+__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+	union entry_union eu = {{0, 0}};
+
+	eu.entry = e;
+	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+}
+
+void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__ioapic_write_entry(apic, pin, e);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+#ifndef CONFIG_XEN
+/*
+ * When we mask an IO APIC routing entry, we need to write the low
+ * word first, in order to set the mask bit before we change the
+ * high bits!
+ */
+static void ioapic_mask_entry(int apic, int pin)
+{
+	unsigned long flags;
+	union entry_union eu = { .entry.mask = 1 };
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+/*
+ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+ * shared ISA-space IRQs, so we have to support them. We are super
+ * fast in the common case, and fast for shared ISA-space IRQs.
+ */
+static int
+add_pin_to_irq_node_nopanic(struct irq_cfg *cfg, int node, int apic, int pin)
+{
+	struct irq_pin_list **last, *entry;
+
+	/* don't allow duplicates */
+	last = &cfg->irq_2_pin;
+	for_each_irq_pin(entry, cfg->irq_2_pin) {
+		if (entry->apic == apic && entry->pin == pin)
+			return 0;
+		last = &entry->next;
+	}
+
+	entry = get_one_free_irq_2_pin(node);
+	if (!entry) {
+		printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
+				node, apic, pin);
+		return -ENOMEM;
+	}
+	entry->apic = apic;
+	entry->pin = pin;
+
+	*last = entry;
+	return 0;
+}
+
+static void add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin)
+{
+	if (add_pin_to_irq_node_nopanic(cfg, node, apic, pin))
+		panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
+}
+
+/*
+ * Reroute an IRQ to a different pin.
+ */
+static void __init replace_pin_at_irq_node(struct irq_cfg *cfg, int node,
+					   int oldapic, int oldpin,
+					   int newapic, int newpin)
+{
+	struct irq_pin_list *entry;
+
+	for_each_irq_pin(entry, cfg->irq_2_pin) {
+		if (entry->apic == oldapic && entry->pin == oldpin) {
+			entry->apic = newapic;
+			entry->pin = newpin;
+			/* every one is different, right? */
+			return;
+		}
+	}
+
+	/* old apic/pin didn't exist, so just add new ones */
+	add_pin_to_irq_node(cfg, node, newapic, newpin);
+}
+
+static void io_apic_modify_irq(struct irq_cfg *cfg,
+			       int mask_and, int mask_or,
+			       void (*final)(struct irq_pin_list *entry))
+{
+	int pin;
+	struct irq_pin_list *entry;
+
+	for_each_irq_pin(entry, cfg->irq_2_pin) {
+		unsigned int reg;
+		pin = entry->pin;
+		reg = io_apic_read(entry->apic, 0x10 + pin * 2);
+		reg &= mask_and;
+		reg |= mask_or;
+		io_apic_modify(entry->apic, 0x10 + pin * 2, reg);
+		if (final)
+			final(entry);
+	}
+}
+
+static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
+{
+	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
+}
+
+static void io_apic_sync(struct irq_pin_list *entry)
+{
+	/*
+	 * Synchronize the IO-APIC and the CPU by doing
+	 * a dummy read from the IO-APIC
+	 */
+	struct io_apic __iomem *io_apic;
+	io_apic = io_apic_base(entry->apic);
+	readl(&io_apic->data);
+}
+
+static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
+{
+	io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+}
+
+static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg)
+{
+	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER,
+			IO_APIC_REDIR_MASKED, NULL);
+}
+
+static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg)
+{
+	io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED,
+			IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
+}
+
+static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
+{
+	struct irq_cfg *cfg = desc->chip_data;
+	unsigned long flags;
+
+	BUG_ON(!cfg);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__mask_IO_APIC_irq(cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
+{
+	struct irq_cfg *cfg = desc->chip_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__unmask_IO_APIC_irq(cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void mask_IO_APIC_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	mask_IO_APIC_irq_desc(desc);
+}
+static void unmask_IO_APIC_irq(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	unmask_IO_APIC_irq_desc(desc);
+}
+
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+{
+	struct IO_APIC_route_entry entry;
+
+	/* Check delivery_mode to be sure we're not clearing an SMI pin */
+	entry = ioapic_read_entry(apic, pin);
+	if (entry.delivery_mode == dest_SMI)
+		return;
+	/*
+	 * Disable it in the IO-APIC irq-routing table:
+	 */
+	ioapic_mask_entry(apic, pin);
+}
+
+static void clear_IO_APIC (void)
+{
+	int apic, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			clear_IO_APIC_pin(apic, pin);
+}
+#else
+#define add_pin_to_irq_node(cfg, node, apic, pin)
+#define add_pin_to_irq_node_nopanic(cfg, node, apic, pin) 0
+#endif /* CONFIG_XEN */
+
+#ifdef CONFIG_X86_32
+/*
+ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
+ * specific CPU-side IRQs.
+ */
+
+#define MAX_PIRQS 8
+static int pirq_entries[MAX_PIRQS] = {
+	[0 ... MAX_PIRQS - 1] = -1
+};
+
+static int __init ioapic_pirq_setup(char *str)
+{
+	int i, max;
+	int ints[MAX_PIRQS+1];
+
+	get_options(str, ARRAY_SIZE(ints), ints);
+
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"PIRQ redirection, working around broken MP-BIOS.\n");
+	max = MAX_PIRQS;
+	if (ints[0] < MAX_PIRQS)
+		max = ints[0];
+
+	for (i = 0; i < max; i++) {
+		apic_printk(APIC_VERBOSE, KERN_DEBUG
+				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		/*
+		 * PIRQs are mapped upside down, usually.
+		 */
+		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
+	}
+	return 1;
+}
+
+__setup("pirq=", ioapic_pirq_setup);
+#endif /* CONFIG_X86_32 */
+
+#ifndef CONFIG_XEN
+struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+{
+	int apic;
+	struct IO_APIC_route_entry **ioapic_entries;
+
+	ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
+				GFP_ATOMIC);
+	if (!ioapic_entries)
+		return 0;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		ioapic_entries[apic] =
+			kzalloc(sizeof(struct IO_APIC_route_entry) *
+				nr_ioapic_registers[apic], GFP_ATOMIC);
+		if (!ioapic_entries[apic])
+			goto nomem;
+	}
+
+	return ioapic_entries;
+
+nomem:
+	while (--apic >= 0)
+		kfree(ioapic_entries[apic]);
+	kfree(ioapic_entries);
+
+	return 0;
+}
+
+/*
+ * Saves all the IO-APIC RTE's
+ */
+int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+{
+	int apic, pin;
+
+	if (!ioapic_entries)
+		return -ENOMEM;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		if (!ioapic_entries[apic])
+			return -ENOMEM;
+
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			ioapic_entries[apic][pin] =
+				ioapic_read_entry(apic, pin);
+	}
+
+	return 0;
+}
+
+/*
+ * Mask all IO APIC entries.
+ */
+void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+{
+	int apic, pin;
+
+	if (!ioapic_entries)
+		return;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		if (!ioapic_entries[apic])
+			break;
+
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+
+			entry = ioapic_entries[apic][pin];
+			if (!entry.mask) {
+				entry.mask = 1;
+				ioapic_write_entry(apic, pin, entry);
+			}
+		}
+	}
+}
+
+/*
+ * Restore IO APIC entries which was saved in ioapic_entries.
+ */
+int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+{
+	int apic, pin;
+
+	if (!ioapic_entries)
+		return -ENOMEM;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		if (!ioapic_entries[apic])
+			return -ENOMEM;
+
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+			ioapic_write_entry(apic, pin,
+					ioapic_entries[apic][pin]);
+	}
+	return 0;
+}
+
+void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
+{
+	int apic;
+
+	for (apic = 0; apic < nr_ioapics; apic++)
+		kfree(ioapic_entries[apic]);
+
+	kfree(ioapic_entries);
+}
+#endif /* CONFIG_XEN */
+
+/*
+ * Find the IRQ entry number of a certain pin.
+ */
+static int find_irq_entry(int apic, int pin, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++)
+		if (mp_irqs[i].irqtype == type &&
+		    (mp_irqs[i].dstapic == mp_ioapics[apic].apicid ||
+		     mp_irqs[i].dstapic == MP_APIC_ALL) &&
+		    mp_irqs[i].dstirq == pin)
+			return i;
+
+	return -1;
+}
+
+#ifndef CONFIG_XEN
+/*
+ * Find the pin to which IRQ[irq] (ISA) is connected
+ */
+static int __init find_isa_irq_pin(int irq, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].srcbus;
+
+		if (test_bit(lbus, mp_bus_not_pci) &&
+		    (mp_irqs[i].irqtype == type) &&
+		    (mp_irqs[i].srcbusirq == irq))
+
+			return mp_irqs[i].dstirq;
+	}
+	return -1;
+}
+
+static int __init find_isa_irq_apic(int irq, int type)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].srcbus;
+
+		if (test_bit(lbus, mp_bus_not_pci) &&
+		    (mp_irqs[i].irqtype == type) &&
+		    (mp_irqs[i].srcbusirq == irq))
+			break;
+	}
+	if (i < mp_irq_entries) {
+		int apic;
+		for(apic = 0; apic < nr_ioapics; apic++) {
+			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic)
+				return apic;
+		}
+	}
+
+	return -1;
+}
+#endif
+
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+/*
+ * EISA Edge/Level control register, ELCR
+ */
+static int EISA_ELCR(unsigned int irq)
+{
+	if (irq < nr_legacy_irqs) {
+		unsigned int port = 0x4d0 + (irq >> 3);
+		return (inb(port) >> (irq & 7)) & 1;
+	}
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"Broken MPtable reports ISA irq %d\n", irq);
+	return 0;
+}
+
+#endif
+
+/* ISA interrupts are always polarity zero edge triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_ISA_trigger(idx)	(0)
+#define default_ISA_polarity(idx)	(0)
+
+/* EISA interrupts are always polarity zero and can be edge or level
+ * trigger depending on the ELCR value.  If an interrupt is listed as
+ * EISA conforming in the MP table, that means its trigger type must
+ * be read in from the ELCR */
+
+#define default_EISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].srcbusirq))
+#define default_EISA_polarity(idx)	default_ISA_polarity(idx)
+
+/* PCI interrupts are always polarity one level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_PCI_trigger(idx)	(1)
+#define default_PCI_polarity(idx)	(1)
+
+/* MCA interrupts are always polarity zero level triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_MCA_trigger(idx)	(1)
+#define default_MCA_polarity(idx)	default_ISA_polarity(idx)
+
+static int MPBIOS_polarity(int idx)
+{
+	int bus = mp_irqs[idx].srcbus;
+	int polarity;
+
+	/*
+	 * Determine IRQ line polarity (high active or low active):
+	 */
+	switch (mp_irqs[idx].irqflag & 3)
+	{
+		case 0: /* conforms, ie. bus-type dependent polarity */
+			if (test_bit(bus, mp_bus_not_pci))
+				polarity = default_ISA_polarity(idx);
+			else
+				polarity = default_PCI_polarity(idx);
+			break;
+		case 1: /* high active */
+		{
+			polarity = 0;
+			break;
+		}
+		case 2: /* reserved */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
+		case 3: /* low active */
+		{
+			polarity = 1;
+			break;
+		}
+		default: /* invalid */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			polarity = 1;
+			break;
+		}
+	}
+	return polarity;
+}
+
+static int MPBIOS_trigger(int idx)
+{
+	int bus = mp_irqs[idx].srcbus;
+	int trigger;
+
+	/*
+	 * Determine IRQ trigger mode (edge or level sensitive):
+	 */
+	switch ((mp_irqs[idx].irqflag>>2) & 3)
+	{
+		case 0: /* conforms, ie. bus-type dependent */
+			if (test_bit(bus, mp_bus_not_pci))
+				trigger = default_ISA_trigger(idx);
+			else
+				trigger = default_PCI_trigger(idx);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+			switch (mp_bus_id_to_type[bus]) {
+				case MP_BUS_ISA: /* ISA pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_EISA: /* EISA pin */
+				{
+					trigger = default_EISA_trigger(idx);
+					break;
+				}
+				case MP_BUS_PCI: /* PCI pin */
+				{
+					/* set before the switch */
+					break;
+				}
+				case MP_BUS_MCA: /* MCA pin */
+				{
+					trigger = default_MCA_trigger(idx);
+					break;
+				}
+				default:
+				{
+					printk(KERN_WARNING "broken BIOS!!\n");
+					trigger = 1;
+					break;
+				}
+			}
+#endif
+			break;
+		case 1: /* edge */
+		{
+			trigger = 0;
+			break;
+		}
+		case 2: /* reserved */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			trigger = 1;
+			break;
+		}
+		case 3: /* level */
+		{
+			trigger = 1;
+			break;
+		}
+		default: /* invalid */
+		{
+			printk(KERN_WARNING "broken BIOS!!\n");
+			trigger = 0;
+			break;
+		}
+	}
+	return trigger;
+}
+
+static inline int irq_polarity(int idx)
+{
+	return MPBIOS_polarity(idx);
+}
+
+static inline int irq_trigger(int idx)
+{
+	return MPBIOS_trigger(idx);
+}
+
+#ifndef CONFIG_XEN
+int (*ioapic_renumber_irq)(int ioapic, int irq);
+#endif
+static int pin_2_irq(int idx, int apic, int pin)
+{
+	int irq, i;
+	int bus = mp_irqs[idx].srcbus;
+
+	/*
+	 * Debugging check, we are in big trouble if this message pops up!
+	 */
+	if (mp_irqs[idx].dstirq != pin)
+		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+
+	if (test_bit(bus, mp_bus_not_pci)) {
+		irq = mp_irqs[idx].srcbusirq;
+	} else {
+		/*
+		 * PCI IRQs are mapped in order
+		 */
+		i = irq = 0;
+		while (i < apic)
+			irq += nr_ioapic_registers[i++];
+		irq += pin;
+#ifndef CONFIG_XEN
+		/*
+                 * For MPS mode, so far only needed by ES7000 platform
+                 */
+		if (ioapic_renumber_irq)
+			irq = ioapic_renumber_irq(apic, irq);
+#endif
+	}
+
+#ifdef CONFIG_X86_32
+	/*
+	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
+	 */
+	if ((pin >= 16) && (pin <= 23)) {
+		if (pirq_entries[pin-16] != -1) {
+			if (!pirq_entries[pin-16]) {
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"disabling PIRQ%d\n", pin-16);
+			} else {
+				irq = pirq_entries[pin-16];
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"using PIRQ%d -> IRQ %d\n",
+						pin-16, irq);
+			}
+		}
+	}
+#endif
+
+	return irq;
+}
+
+/*
+ * Find a specific PCI IRQ entry.
+ * Not an __init, possibly needed by modules
+ */
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
+				struct io_apic_irq_attr *irq_attr)
+{
+	int apic, i, best_guess = -1;
+
+	apic_printk(APIC_DEBUG,
+		    "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+		    bus, slot, pin);
+	if (test_bit(bus, mp_bus_not_pci)) {
+		apic_printk(APIC_VERBOSE,
+			    "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		return -1;
+	}
+	for (i = 0; i < mp_irq_entries; i++) {
+		int lbus = mp_irqs[i].srcbus;
+
+		for (apic = 0; apic < nr_ioapics; apic++)
+			if (mp_ioapics[apic].apicid == mp_irqs[i].dstapic ||
+			    mp_irqs[i].dstapic == MP_APIC_ALL)
+				break;
+
+		if (!test_bit(lbus, mp_bus_not_pci) &&
+		    !mp_irqs[i].irqtype &&
+		    (bus == lbus) &&
+		    (slot == ((mp_irqs[i].srcbusirq >> 2) & 0x1f))) {
+			int irq = pin_2_irq(i, apic, mp_irqs[i].dstirq);
+
+			if (!(apic || IO_APIC_IRQ(irq)))
+				continue;
+
+			if (pin == (mp_irqs[i].srcbusirq & 3)) {
+				set_io_apic_irq_attr(irq_attr, apic,
+						     mp_irqs[i].dstirq,
+						     irq_trigger(i),
+						     irq_polarity(i));
+				return irq;
+			}
+			/*
+			 * Use the first all-but-pin matching entry as a
+			 * best-guess fuzzy result for broken mptables.
+			 */
+			if (best_guess < 0) {
+				set_io_apic_irq_attr(irq_attr, apic,
+						     mp_irqs[i].dstirq,
+						     irq_trigger(i),
+						     irq_polarity(i));
+				best_guess = irq;
+			}
+		}
+	}
+	return best_guess;
+}
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
+
+#ifndef CONFIG_XEN
+void lock_vector_lock(void)
+{
+	/* Used to the online set of cpus does not change
+	 * during assign_irq_vector.
+	 */
+	spin_lock(&vector_lock);
+}
+
+void unlock_vector_lock(void)
+{
+	spin_unlock(&vector_lock);
+}
+
+static int
+__assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
+{
+	/*
+	 * NOTE! The local APIC isn't very good at handling
+	 * multiple interrupts at the same interrupt level.
+	 * As the interrupt level is determined by taking the
+	 * vector number and shifting that right by 4, we
+	 * want to spread these out a bit so that they don't
+	 * all fall in the same interrupt level.
+	 *
+	 * Also, we've got to be careful not to trash gate
+	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+	 */
+	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	unsigned int old_vector;
+	int cpu, err;
+	cpumask_var_t tmp_mask;
+
+	if ((cfg->move_in_progress) || cfg->move_cleanup_count)
+		return -EBUSY;
+
+	if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
+		return -ENOMEM;
+
+	old_vector = cfg->vector;
+	if (old_vector) {
+		cpumask_and(tmp_mask, mask, cpu_online_mask);
+		cpumask_and(tmp_mask, cfg->domain, tmp_mask);
+		if (!cpumask_empty(tmp_mask)) {
+			free_cpumask_var(tmp_mask);
+			return 0;
+		}
+	}
+
+	/* Only try and allocate irqs on cpus that are present */
+	err = -ENOSPC;
+	for_each_cpu_and(cpu, mask, cpu_online_mask) {
+		int new_cpu;
+		int vector, offset;
+
+		apic->vector_allocation_domain(cpu, tmp_mask);
+
+		vector = current_vector;
+		offset = current_offset;
+next:
+		vector += 8;
+		if (vector >= first_system_vector) {
+			/* If out of vectors on large boxen, must share them. */
+			offset = (offset + 1) % 8;
+			vector = FIRST_DEVICE_VECTOR + offset;
+		}
+		if (unlikely(current_vector == vector))
+			continue;
+
+		if (test_bit(vector, used_vectors))
+			goto next;
+
+#ifdef CONFIG_KDB
+		if (vector == KDBENTER_VECTOR)
+			goto next;
+#endif	/* CONFIG_KDB */
+		for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
+			if (per_cpu(vector_irq, new_cpu)[vector] != -1)
+				goto next;
+		/* Found one! */
+		current_vector = vector;
+		current_offset = offset;
+		if (old_vector) {
+			cfg->move_in_progress = 1;
+			cpumask_copy(cfg->old_domain, cfg->domain);
+		}
+		for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
+			per_cpu(vector_irq, new_cpu)[vector] = irq;
+		cfg->vector = vector;
+		cpumask_copy(cfg->domain, tmp_mask);
+		err = 0;
+		break;
+	}
+	free_cpumask_var(tmp_mask);
+	return err;
+}
+
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
+{
+	int err;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	err = __assign_irq_vector(irq, cfg, mask);
+	spin_unlock_irqrestore(&vector_lock, flags);
+	return err;
+}
+
+static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
+{
+	int cpu, vector;
+
+	BUG_ON(!cfg->vector);
+
+	vector = cfg->vector;
+	for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
+		per_cpu(vector_irq, cpu)[vector] = -1;
+
+	cfg->vector = 0;
+	cpumask_clear(cfg->domain);
+
+	if (likely(!cfg->move_in_progress))
+		return;
+	for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
+		for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
+								vector++) {
+			if (per_cpu(vector_irq, cpu)[vector] != irq)
+				continue;
+			per_cpu(vector_irq, cpu)[vector] = -1;
+			break;
+		}
+	}
+	cfg->move_in_progress = 0;
+}
+
+void __setup_vector_irq(int cpu)
+{
+	/* Initialize vector_irq on a new cpu */
+	/* This function must be called with vector_lock held */
+	int irq, vector;
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+
+	/* Mark the inuse vectors */
+	for_each_irq_desc(irq, desc) {
+		cfg = desc->chip_data;
+		if (!cpumask_test_cpu(cpu, cfg->domain))
+			continue;
+		vector = cfg->vector;
+		per_cpu(vector_irq, cpu)[vector] = irq;
+	}
+	/* Mark the free vectors */
+	for (vector = 0; vector < NR_VECTORS; ++vector) {
+		irq = per_cpu(vector_irq, cpu)[vector];
+		if (irq < 0)
+			continue;
+
+		cfg = irq_cfg(irq);
+		if (!cpumask_test_cpu(cpu, cfg->domain))
+			per_cpu(vector_irq, cpu)[vector] = -1;
+	}
+}
+
+static struct irq_chip ioapic_chip;
+static struct irq_chip ir_ioapic_chip;
+
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
+
+#ifdef CONFIG_X86_32
+static inline int IO_APIC_irq_trigger(int irq)
+{
+	int apic, idx, pin;
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			idx = find_irq_entry(apic, pin, mp_INT);
+			if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+				return irq_trigger(idx);
+		}
+	}
+	/*
+         * nonexistent IRQs are edge default
+         */
+	return 0;
+}
+#else
+static inline int IO_APIC_irq_trigger(int irq)
+{
+	return 1;
+}
+#endif
+
+static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
+{
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
+		desc->status |= IRQ_LEVEL;
+	else
+		desc->status &= ~IRQ_LEVEL;
+
+	if (irq_remapped(irq)) {
+		desc->status |= IRQ_MOVE_PCNTXT;
+		if (trigger)
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_fasteoi_irq,
+						     "fasteoi");
+		else
+			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
+						      handle_edge_irq, "edge");
+		return;
+	}
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+	    trigger == IOAPIC_LEVEL)
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_fasteoi_irq,
+					      "fasteoi");
+	else
+		set_irq_chip_and_handler_name(irq, &ioapic_chip,
+					      handle_edge_irq, "edge");
+}
+#else /* !CONFIG_XEN */
+#define __clear_irq_vector(irq, cfg) ((void)0)
+#define ioapic_register_intr(irq, desc, trigger) evtchn_register_pirq(irq)
+#endif
+
+int setup_ioapic_entry(int apic_id, int irq,
+		       struct IO_APIC_route_entry *entry,
+		       unsigned int destination, int trigger,
+		       int polarity, int vector, int pin)
+{
+	/*
+	 * add it to the IO-APIC irq-routing table:
+	 */
+	memset(entry,0,sizeof(*entry));
+
+	if (intr_remapping_enabled) {
+#ifndef CONFIG_XEN
+		struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
+		struct irte irte;
+		struct IR_IO_APIC_route_entry *ir_entry =
+			(struct IR_IO_APIC_route_entry *) entry;
+		int index;
+
+		if (!iommu)
+			panic("No mapping iommu for ioapic %d\n", apic_id);
+
+		index = alloc_irte(iommu, irq, 1);
+		if (index < 0)
+			panic("Failed to allocate IRTE for ioapic %d\n", apic_id);
+
+		memset(&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = apic->irq_dest_mode;
+		/*
+		 * Trigger mode in the IRTE will always be edge, and the
+		 * actual level or edge trigger will be setup in the IO-APIC
+		 * RTE. This will help simplify level triggered irq migration.
+		 * For more details, see the comments above explainig IO-APIC
+		 * irq migration in the presence of interrupt-remapping.
+		 */
+		irte.trigger_mode = 0;
+		irte.dlvry_mode = apic->irq_delivery_mode;
+		irte.vector = vector;
+		irte.dest_id = IRTE_DEST(destination);
+
+		/* Set source-id of interrupt request */
+		set_ioapic_sid(&irte, apic_id);
+
+		modify_irte(irq, &irte);
+
+		ir_entry->index2 = (index >> 15) & 0x1;
+		ir_entry->zero = 0;
+		ir_entry->format = 1;
+		ir_entry->index = (index & 0x7fff);
+		/*
+		 * IO-APIC RTE will be configured with virtual vector.
+		 * irq handler will do the explicit EOI to the io-apic.
+		 */
+		ir_entry->vector = pin;
+#endif
+	} else {
+		entry->delivery_mode = apic->irq_delivery_mode;
+		entry->dest_mode = apic->irq_dest_mode;
+		entry->dest = destination;
+		entry->vector = vector;
+	}
+
+	entry->mask = 0;				/* enable IRQ */
+	entry->trigger = trigger;
+	entry->polarity = polarity;
+
+	/* Mask level triggered irqs.
+	 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
+	 */
+	if (trigger)
+		entry->mask = 1;
+	return 0;
+}
+
+static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq_desc *desc,
+			      int trigger, int polarity)
+{
+	struct irq_cfg *cfg;
+	struct IO_APIC_route_entry entry;
+	unsigned int dest;
+
+	if (!IO_APIC_IRQ(irq))
+		return;
+
+	cfg = desc->chip_data;
+
+	if (assign_irq_vector(irq, cfg, apic->target_cpus()))
+		return;
+
+#ifndef CONFIG_XEN
+	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+#else
+	dest = 0; /* meaningless */
+#endif
+
+	apic_printk(APIC_VERBOSE,KERN_DEBUG
+		    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
+		    "IRQ %d Mode:%i Active:%i)\n",
+		    apic_id, mp_ioapics[apic_id].apicid, pin, cfg->vector,
+		    irq, trigger, polarity);
+
+
+	if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry,
+			       dest, trigger, polarity, cfg->vector, pin)) {
+		printk("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+		       mp_ioapics[apic_id].apicid, pin);
+		__clear_irq_vector(irq, cfg);
+		return;
+	}
+
+	ioapic_register_intr(irq, desc, trigger);
+	if (irq < nr_legacy_irqs)
+		disable_8259A_irq(irq);
+
+	ioapic_write_entry(apic_id, pin, entry);
+}
+
+static struct {
+	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
+} mp_ioapic_routing[MAX_IO_APICS];
+
+static void __init setup_IO_APIC_irqs(void)
+{
+	int apic_id, pin, idx, irq;
+	int notcon = 0;
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+	int node = cpu_to_node(boot_cpu_id);
+
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
+	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
+		idx = find_irq_entry(apic_id, pin, mp_INT);
+		if (idx == -1) {
+			if (!notcon) {
+				notcon = 1;
+				apic_printk(APIC_VERBOSE,
+					KERN_DEBUG " %d-%d",
+					mp_ioapics[apic_id].apicid, pin);
+			} else
+				apic_printk(APIC_VERBOSE, " %d-%d",
+					mp_ioapics[apic_id].apicid, pin);
+			continue;
+		}
+		if (notcon) {
+			apic_printk(APIC_VERBOSE,
+				" (apicid-pin) not connected\n");
+			notcon = 0;
+		}
+
+		irq = pin_2_irq(idx, apic_id, pin);
+
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
+#if defined(CONFIG_XEN)
+		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+			continue;
+#else
+		/*
+		 * Skip the timer IRQ if there's a quirk handler
+		 * installed and if it returns 1:
+		 */
+		if (apic->multi_timer_check &&
+				apic->multi_timer_check(apic_id, irq))
+			continue;
+#endif
+
+		desc = irq_to_desc_alloc_node(irq, node);
+		if (!desc) {
+			printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+			continue;
+		}
+		cfg = desc->chip_data;
+		add_pin_to_irq_node(cfg, node, apic_id, pin);
+		/*
+		 * don't mark it in pin_programmed, so later acpi could
+		 * set it correctly when irq < 16
+		 */
+		setup_IO_APIC_irq(apic_id, pin, irq, desc,
+				irq_trigger(idx), irq_polarity(idx));
+	}
+
+	if (notcon)
+		apic_printk(APIC_VERBOSE,
+			" (apicid-pin) not connected\n");
+}
+
+/*
+ * for the gsit that is not in first ioapic
+ * but could not use acpi_register_gsi()
+ * like some special sci in IBM x3330
+ */
+void setup_IO_APIC_irq_extra(u32 gsi)
+{
+	int apic_id = 0, pin, idx, irq;
+	int node = cpu_to_node(boot_cpu_id);
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+
+	/*
+	 * Convert 'gsi' to 'ioapic.pin'.
+	 */
+	apic_id = mp_find_ioapic(gsi);
+	if (apic_id < 0)
+		return;
+
+	pin = mp_find_ioapic_pin(apic_id, gsi);
+	idx = find_irq_entry(apic_id, pin, mp_INT);
+	if (idx == -1)
+		return;
+
+	irq = pin_2_irq(idx, apic_id, pin);
+#ifdef CONFIG_XEN
+	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+		return;
+#endif
+#ifdef CONFIG_SPARSE_IRQ
+	desc = irq_to_desc(irq);
+	if (desc)
+		return;
+#endif
+	desc = irq_to_desc_alloc_node(irq, node);
+	if (!desc) {
+		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+		return;
+	}
+
+	cfg = desc->chip_data;
+	add_pin_to_irq_node(cfg, node, apic_id, pin);
+
+	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[apic_id].apicid, pin);
+		return;
+	}
+	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+
+	setup_IO_APIC_irq(apic_id, pin, irq, desc,
+			irq_trigger(idx), irq_polarity(idx));
+}
+
+#ifndef CONFIG_XEN
+/*
+ * Set up the timer pin, possibly with the 8259A-master behind.
+ */
+static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
+					int vector)
+{
+	struct IO_APIC_route_entry entry;
+
+	if (intr_remapping_enabled)
+		return;
+
+	memset(&entry, 0, sizeof(entry));
+
+	/*
+	 * We use logical delivery to get the timer IRQ
+	 * to the first CPU.
+	 */
+	entry.dest_mode = apic->irq_dest_mode;
+	entry.mask = 0;			/* don't mask IRQ for edge */
+	entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus());
+	entry.delivery_mode = apic->irq_delivery_mode;
+	entry.polarity = 0;
+	entry.trigger = 0;
+	entry.vector = vector;
+
+	/*
+	 * The timer IRQ doesn't have to know that behind the
+	 * scene we may have a 8259A-master in AEOI mode ...
+	 */
+	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+
+	/*
+	 * Add it to the IO-APIC irq-routing table:
+	 */
+	ioapic_write_entry(apic_id, pin, entry);
+}
+
+
+__apicdebuginit(void) print_IO_APIC(void)
+{
+	int apic, i;
+	union IO_APIC_reg_00 reg_00;
+	union IO_APIC_reg_01 reg_01;
+	union IO_APIC_reg_02 reg_02;
+	union IO_APIC_reg_03 reg_03;
+	unsigned long flags;
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+	unsigned int irq;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	for (i = 0; i < nr_ioapics; i++)
+		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
+		       mp_ioapics[i].apicid, nr_ioapic_registers[i]);
+
+	/*
+	 * We are a bit conservative about what we expect.  We have to
+	 * know about every hardware change ASAP.
+	 */
+	printk(KERN_INFO "testing the IO APIC.......................\n");
+
+	for (apic = 0; apic < nr_ioapics; apic++) {
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(apic, 0);
+	reg_01.raw = io_apic_read(apic, 1);
+	if (reg_01.bits.version >= 0x10)
+		reg_02.raw = io_apic_read(apic, 2);
+	if (reg_01.bits.version >= 0x20)
+		reg_03.raw = io_apic_read(apic, 3);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	printk("\n");
+	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid);
+	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
+	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);
+	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);
+
+	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
+	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);
+
+	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);
+	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);
+
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+	 * but the value of reg_02 is read as the previous read register
+	 * value, so ignore it if reg_02 == reg_01.
+	 */
+	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);
+	}
+
+	/*
+	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
+	 * or reg_03, but the value of reg_0[23] is read as the previous read
+	 * register value, so ignore it if reg_03 == reg_0[12].
+	 */
+	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+	    reg_03.raw != reg_01.raw) {
+		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);
+	}
+
+	printk(KERN_DEBUG ".... IRQ redirection table:\n");
+
+	printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
+			  " Stat Dmod Deli Vect:   \n");
+
+	for (i = 0; i <= reg_01.bits.entries; i++) {
+		struct IO_APIC_route_entry entry;
+
+		entry = ioapic_read_entry(apic, i);
+
+		printk(KERN_DEBUG " %02x %03X ",
+			i,
+			entry.dest
+		);
+
+		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",
+			entry.mask,
+			entry.trigger,
+			entry.irr,
+			entry.polarity,
+			entry.delivery_status,
+			entry.dest_mode,
+			entry.delivery_mode,
+			entry.vector
+		);
+	}
+	}
+	printk(KERN_DEBUG "IRQ to pin mappings:\n");
+	for_each_irq_desc(irq, desc) {
+		struct irq_pin_list *entry;
+
+		cfg = desc->chip_data;
+		if (!cfg)
+			continue;
+		entry = cfg->irq_2_pin;
+		if (!entry)
+			continue;
+		printk(KERN_DEBUG "IRQ%d ", irq);
+		for_each_irq_pin(entry, cfg->irq_2_pin)
+			printk("-> %d:%d", entry->apic, entry->pin);
+		printk("\n");
+	}
+
+	printk(KERN_INFO ".................................... done.\n");
+
+	return;
+}
+
+__apicdebuginit(void) print_APIC_field(int base)
+{
+	int i;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG);
+
+	for (i = 0; i < 8; i++)
+		printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+
+	printk(KERN_CONT "\n");
+}
+
+__apicdebuginit(void) print_local_APIC(void *dummy)
+{
+	unsigned int i, v, ver, maxlvt;
+	u64 icr;
+
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+		smp_processor_id(), hard_smp_processor_id());
+	v = apic_read(APIC_ID);
+	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
+	v = apic_read(APIC_LVR);
+	printk(KERN_INFO "... APIC VERSION: %08x\n", v);
+	ver = GET_APIC_VERSION(v);
+	maxlvt = lapic_get_maxlvt();
+
+	v = apic_read(APIC_TASKPRI);
+	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
+
+	if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
+		if (!APIC_XAPIC(ver)) {
+			v = apic_read(APIC_ARBPRI);
+			printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+			       v & APIC_ARBPRI_MASK);
+		}
+		v = apic_read(APIC_PROCPRI);
+		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
+	}
+
+	/*
+	 * Remote read supported only in the 82489DX and local APIC for
+	 * Pentium processors.
+	 */
+	if (!APIC_INTEGRATED(ver) || maxlvt == 3) {
+		v = apic_read(APIC_RRR);
+		printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+	}
+
+	v = apic_read(APIC_LDR);
+	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
+	if (!x2apic_enabled()) {
+		v = apic_read(APIC_DFR);
+		printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+	}
+	v = apic_read(APIC_SPIV);
+	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
+
+	printk(KERN_DEBUG "... APIC ISR field:\n");
+	print_APIC_field(APIC_ISR);
+	printk(KERN_DEBUG "... APIC TMR field:\n");
+	print_APIC_field(APIC_TMR);
+	printk(KERN_DEBUG "... APIC IRR field:\n");
+	print_APIC_field(APIC_IRR);
+
+	if (APIC_INTEGRATED(ver)) {             /* !82489DX */
+		if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
+			apic_write(APIC_ESR, 0);
+
+		v = apic_read(APIC_ESR);
+		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
+	}
+
+	icr = apic_icr_read();
+	printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr);
+	printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32));
+
+	v = apic_read(APIC_LVTT);
+	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
+
+	if (maxlvt > 3) {                       /* PC is LVT#4. */
+		v = apic_read(APIC_LVTPC);
+		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);
+	}
+	v = apic_read(APIC_LVT0);
+	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);
+	v = apic_read(APIC_LVT1);
+	printk(KERN_DEBUG "... APIC LVT1: %08x\n", v);
+
+	if (maxlvt > 2) {			/* ERR is LVT#3. */
+		v = apic_read(APIC_LVTERR);
+		printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v);
+	}
+
+	v = apic_read(APIC_TMICT);
+	printk(KERN_DEBUG "... APIC TMICT: %08x\n", v);
+	v = apic_read(APIC_TMCCT);
+	printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v);
+	v = apic_read(APIC_TDCR);
+	printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
+
+	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+		v = apic_read(APIC_EFEAT);
+		maxlvt = (v >> 16) & 0xff;
+		printk(KERN_DEBUG "... APIC EFEAT: %08x\n", v);
+		v = apic_read(APIC_ECTRL);
+		printk(KERN_DEBUG "... APIC ECTRL: %08x\n", v);
+		for (i = 0; i < maxlvt; i++) {
+			v = apic_read(APIC_EILVTn(i));
+			printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
+		}
+	}
+	printk("\n");
+}
+
+__apicdebuginit(void) print_all_local_APICs(void)
+{
+	int cpu;
+
+	preempt_disable();
+	for_each_online_cpu(cpu)
+		smp_call_function_single(cpu, print_local_APIC, NULL, 1);
+	preempt_enable();
+}
+
+__apicdebuginit(void) print_PIC(void)
+{
+	unsigned int v;
+	unsigned long flags;
+
+	if (apic_verbosity == APIC_QUIET || !nr_legacy_irqs)
+		return;
+
+	printk(KERN_DEBUG "\nprinting PIC contents\n");
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+
+	v = inb(0xa1) << 8 | inb(0x21);
+	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
+
+	v = inb(0xa0) << 8 | inb(0x20);
+	printk(KERN_DEBUG "... PIC  IRR: %04x\n", v);
+
+	outb(0x0b,0xa0);
+	outb(0x0b,0x20);
+	v = inb(0xa0) << 8 | inb(0x20);
+	outb(0x0a,0xa0);
+	outb(0x0a,0x20);
+
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+
+	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
+
+	v = inb(0x4d1) << 8 | inb(0x4d0);
+	printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
+}
+
+__apicdebuginit(int) print_all_ICs(void)
+{
+	print_PIC();
+
+	/* don't print out if apic is not there */
+	if (!cpu_has_apic && !apic_from_smp_config())
+		return 0;
+
+	print_all_local_APICs();
+	print_IO_APIC();
+
+	return 0;
+}
+
+fs_initcall(print_all_ICs);
+
+
+/* Where if anywhere is the i8259 connect in external int mode */
+static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+#endif /* CONFIG_XEN */
+
+void __init enable_IO_APIC(void)
+{
+	union IO_APIC_reg_01 reg_01;
+#ifndef CONFIG_XEN
+	int i8259_apic, i8259_pin;
+#endif
+	int apic;
+	unsigned long flags;
+
+	/*
+	 * The number of IO-APIC IRQ registers (== #pins):
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_01.raw = io_apic_read(apic, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+	}
+
+	if (!nr_legacy_irqs)
+		return;
+
+#ifndef CONFIG_XEN
+	for(apic = 0; apic < nr_ioapics; apic++) {
+		int pin;
+		/* See if any of the pins is in ExtINT mode */
+		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+			struct IO_APIC_route_entry entry;
+			entry = ioapic_read_entry(apic, pin);
+
+			/* If the interrupt line is enabled and in ExtInt mode
+			 * I have found the pin where the i8259 is connected.
+			 */
+			if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+				ioapic_i8259.apic = apic;
+				ioapic_i8259.pin  = pin;
+				goto found_i8259;
+			}
+		}
+	}
+ found_i8259:
+	/* Look to see what if the MP table has reported the ExtINT */
+	/* If we could not find the appropriate pin by looking at the ioapic
+	 * the i8259 probably is not connected the ioapic but give the
+	 * mptable a chance anyway.
+	 */
+	i8259_pin  = find_isa_irq_pin(0, mp_ExtINT);
+	i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+	/* Trust the MP table if nothing is setup in the hardware */
+	if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+		printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+		ioapic_i8259.pin  = i8259_pin;
+		ioapic_i8259.apic = i8259_apic;
+	}
+	/* Complain if the MP table and the hardware disagree */
+	if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+		(i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+	{
+		printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
+	}
+
+	/*
+	 * Do not trust the IO-APIC being empty at bootup
+	 */
+	clear_IO_APIC();
+#endif
+}
+
+#ifdef CONFIG_XEN
+#define disable_IO_APIC() ((void)0)
+#else
+/*
+ * Not an __init, needed by the reboot code
+ */
+void disable_IO_APIC(void)
+{
+	/*
+	 * Clear the IO-APIC before rebooting:
+	 */
+	clear_IO_APIC();
+
+	if (!nr_legacy_irqs)
+		return;
+
+	/*
+	 * If the i8259 is routed through an IOAPIC
+	 * Put that IOAPIC in virtual wire mode
+	 * so legacy interrupts can be delivered.
+	 *
+	 * With interrupt-remapping, for now we will use virtual wire A mode,
+	 * as virtual wire B is little complex (need to configure both
+	 * IOAPIC RTE aswell as interrupt-remapping table entry).
+	 * As this gets called during crash dump, keep this simple for now.
+	 */
+	if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
+		struct IO_APIC_route_entry entry;
+
+		memset(&entry, 0, sizeof(entry));
+		entry.mask            = 0; /* Enabled */
+		entry.trigger         = 0; /* Edge */
+		entry.irr             = 0;
+		entry.polarity        = 0; /* High */
+		entry.delivery_status = 0;
+		entry.dest_mode       = 0; /* Physical */
+		entry.delivery_mode   = dest_ExtINT; /* ExtInt */
+		entry.vector          = 0;
+		entry.dest            = read_apic_id();
+
+		/*
+		 * Add it to the IO-APIC irq-routing table:
+		 */
+		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
+	}
+
+	/*
+	 * Use virtual wire A mode when interrupt remapping is enabled.
+	 */
+	if (cpu_has_apic || apic_from_smp_config())
+		disconnect_bsp_APIC(!intr_remapping_enabled &&
+				ioapic_i8259.pin != -1);
+}
+
+#ifdef CONFIG_X86_32
+/*
+ * function to set the IO-APIC physical IDs based on the
+ * values stored in the MPC table.
+ *
+ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+ */
+
+void __init setup_ioapic_ids_from_mpc(void)
+{
+	union IO_APIC_reg_00 reg_00;
+	physid_mask_t phys_id_present_map;
+	int apic_id;
+	int i;
+	unsigned char old_id;
+	unsigned long flags;
+
+	if (acpi_ioapic)
+		return;
+	/*
+	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+	 * no meaning without the serial APIC bus.
+	 */
+	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+		|| APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return;
+	/*
+	 * This is broken; anything with a real cpu count has to
+	 * circumvent this idiocy regardless.
+	 */
+	phys_id_present_map = apic->ioapic_phys_id_map(phys_cpu_present_map);
+
+	/*
+	 * Set the IOAPIC ID to the value stored in the MPC table.
+	 */
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
+
+		/* Read the register 0 value */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic_id, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		old_id = mp_ioapics[apic_id].apicid;
+
+		if (mp_ioapics[apic_id].apicid >= get_physical_broadcast()) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+				apic_id, mp_ioapics[apic_id].apicid);
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				reg_00.bits.ID);
+			mp_ioapics[apic_id].apicid = reg_00.bits.ID;
+		}
+
+		/*
+		 * Sanity check, is the ID really free? Every APIC in a
+		 * system must have a unique ID or we get lots of nice
+		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+		 */
+		if (apic->check_apicid_used(phys_id_present_map,
+					mp_ioapics[apic_id].apicid)) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+				apic_id, mp_ioapics[apic_id].apicid);
+			for (i = 0; i < get_physical_broadcast(); i++)
+				if (!physid_isset(i, phys_id_present_map))
+					break;
+			if (i >= get_physical_broadcast())
+				panic("Max APIC ID exceeded!\n");
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				i);
+			physid_set(i, phys_id_present_map);
+			mp_ioapics[apic_id].apicid = i;
+		} else {
+			physid_mask_t tmp;
+			tmp = apic->apicid_to_cpu_present(mp_ioapics[apic_id].apicid);
+			apic_printk(APIC_VERBOSE, "Setting %d in the "
+					"phys_id_present_map\n",
+					mp_ioapics[apic_id].apicid);
+			physids_or(phys_id_present_map, phys_id_present_map, tmp);
+		}
+
+
+		/*
+		 * We need to adjust the IRQ routing table
+		 * if the ID changed.
+		 */
+		if (old_id != mp_ioapics[apic_id].apicid)
+			for (i = 0; i < mp_irq_entries; i++)
+				if (mp_irqs[i].dstapic == old_id)
+					mp_irqs[i].dstapic
+						= mp_ioapics[apic_id].apicid;
+
+		/*
+		 * Read the right value from the MPC table and
+		 * write it into the ID register.
+		 */
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"...changing IO-APIC physical APIC ID to %d ...",
+			mp_ioapics[apic_id].apicid);
+
+		reg_00.bits.ID = mp_ioapics[apic_id].apicid;
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(apic_id, 0, reg_00.raw);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		/*
+		 * Sanity check
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		reg_00.raw = io_apic_read(apic_id, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+		if (reg_00.bits.ID != mp_ioapics[apic_id].apicid)
+			printk("could not set ID!\n");
+		else
+			apic_printk(APIC_VERBOSE, " ok.\n");
+	}
+}
+#endif
+
+int no_timer_check __initdata;
+
+static int __init notimercheck(char *s)
+{
+	no_timer_check = 1;
+	return 1;
+}
+__setup("no_timer_check", notimercheck);
+
+/*
+ * There is a nasty bug in some older SMP boards, their mptable lies
+ * about the timer IRQ. We do the following to work around the situation:
+ *
+ *	- timer IRQ defaults to IO-APIC IRQ
+ *	- if this function detects that timer IRQs are defunct, then we fall
+ *	  back to ISA timer IRQs
+ */
+static int __init timer_irq_works(void)
+{
+	unsigned long t1 = jiffies;
+	unsigned long flags;
+
+	if (no_timer_check)
+		return 1;
+
+	local_save_flags(flags);
+	local_irq_enable();
+	/* Let ten ticks pass... */
+	mdelay((10 * 1000) / HZ);
+	local_irq_restore(flags);
+
+	/*
+	 * Expect a few ticks at least, to be sure some possible
+	 * glue logic does not lock up after one or two first
+	 * ticks in a non-ExtINT mode.  Also the local APIC
+	 * might have cached one ExtINT interrupt.  Finally, at
+	 * least one tick may be lost due to delays.
+	 */
+
+	/* jiffies wrap? */
+	if (time_after(jiffies, t1 + 4))
+		return 1;
+	return 0;
+}
+
+/*
+ * In the SMP+IOAPIC case it might happen that there are an unspecified
+ * number of pending IRQ events unhandled. These cases are very rare,
+ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much
+ * better to do it this way as thus we do not have to be aware of
+ * 'pending' interrupts in the IRQ path, except at this point.
+ */
+/*
+ * Edge triggered needs to resend any interrupt
+ * that was delayed but this is now handled in the device
+ * independent code.
+ */
+
+/*
+ * Starting up a edge-triggered IO-APIC interrupt is
+ * nasty - we need to make sure that we get the edge.
+ * If it is already asserted for some reason, we need
+ * return 1 to indicate that is was pending.
+ *
+ * This is not complete - we should be able to fake
+ * an edge even if it isn't on the 8259A...
+ */
+
+static unsigned int startup_ioapic_irq(unsigned int irq)
+{
+	int was_pending = 0;
+	unsigned long flags;
+	struct irq_cfg *cfg;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	if (irq < nr_legacy_irqs) {
+		disable_8259A_irq(irq);
+		if (i8259A_irq_pending(irq))
+			was_pending = 1;
+	}
+	cfg = irq_cfg(irq);
+	__unmask_IO_APIC_irq(cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return was_pending;
+}
+
+static int ioapic_retrigger_irq(unsigned int irq)
+{
+
+	struct irq_cfg *cfg = irq_cfg(irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	return 1;
+}
+
+/*
+ * Level and edge triggered IO-APIC interrupts need different handling,
+ * so we use two separate IRQ descriptors. Edge triggered IRQs can be
+ * handled with the level-triggered descriptor, but that one has slightly
+ * more overhead. Level-triggered interrupts cannot be handled with the
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
+ */
+
+#ifdef CONFIG_SMP
+static void send_cleanup_vector(struct irq_cfg *cfg)
+{
+	cpumask_var_t cleanup_mask;
+
+	if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+		unsigned int i;
+		cfg->move_cleanup_count = 0;
+		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+			cfg->move_cleanup_count++;
+		for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+			apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+	} else {
+		cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+		cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+		apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+		free_cpumask_var(cleanup_mask);
+	}
+	cfg->move_in_progress = 0;
+}
+
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+	int apic, pin;
+	struct irq_pin_list *entry;
+	u8 vector = cfg->vector;
+
+	for_each_irq_pin(entry, cfg->irq_2_pin) {
+		unsigned int reg;
+
+		apic = entry->apic;
+		pin = entry->pin;
+		/*
+		 * With interrupt-remapping, destination information comes
+		 * from interrupt-remapping table entry.
+		 */
+		if (!irq_remapped(irq))
+			io_apic_write(apic, 0x11 + pin*2, dest);
+		reg = io_apic_read(apic, 0x10 + pin*2);
+		reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+		reg |= vector;
+		io_apic_modify(apic, 0x10 + pin*2, reg);
+	}
+}
+
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
+
+/*
+ * Either sets desc->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+ * leaves desc->affinity untouched.
+ */
+static unsigned int
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+{
+	struct irq_cfg *cfg;
+	unsigned int irq;
+
+	if (!cpumask_intersects(mask, cpu_online_mask))
+		return BAD_APICID;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+	if (assign_irq_vector(irq, cfg, mask))
+		return BAD_APICID;
+
+	cpumask_copy(desc->affinity, mask);
+
+	return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+}
+
+static int
+set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int dest;
+	unsigned int irq;
+	int ret = -1;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	dest = set_desc_affinity(desc, mask);
+	if (dest != BAD_APICID) {
+		/* Only the high 8 bits are valid. */
+		dest = SET_APIC_LOGICAL_ID(dest);
+		__target_IO_APIC_irq(irq, dest, cfg);
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return ret;
+}
+
+static int
+set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+
+	return set_ioapic_affinity_irq_desc(desc, mask);
+}
+
+#ifdef CONFIG_INTR_REMAP
+
+/*
+ * Migrate the IO-APIC irq in the presence of intr-remapping.
+ *
+ * For both level and edge triggered, irq migration is a simple atomic
+ * update(of vector and cpu destination) of IRTE and flush the hardware cache.
+ *
+ * For level triggered, we eliminate the io-apic RTE modification (with the
+ * updated vector information), by using a virtual vector (io-apic pin number).
+ * Real vector that is used for interrupting cpu will be coming from
+ * the interrupt-remapping table entry.
+ */
+static int
+migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+	struct irq_cfg *cfg;
+	struct irte irte;
+	unsigned int dest;
+	unsigned int irq;
+	int ret = -1;
+
+	if (!cpumask_intersects(mask, cpu_online_mask))
+		return ret;
+
+	irq = desc->irq;
+	if (get_irte(irq, &irte))
+		return ret;
+
+	cfg = desc->chip_data;
+	if (assign_irq_vector(irq, cfg, mask))
+		return ret;
+
+	dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * Modified the IRTE and flushes the Interrupt entry cache.
+	 */
+	modify_irte(irq, &irte);
+
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	cpumask_copy(desc->affinity, mask);
+
+	return 0;
+}
+
+/*
+ * Migrates the IRQ destination in the process context.
+ */
+static int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+					    const struct cpumask *mask)
+{
+	return migrate_ioapic_irq_desc(desc, mask);
+}
+static int set_ir_ioapic_affinity_irq(unsigned int irq,
+				       const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	return set_ir_ioapic_affinity_irq_desc(desc, mask);
+}
+#else
+static inline int set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+						   const struct cpumask *mask)
+{
+	return 0;
+}
+#endif
+
+asmlinkage void smp_irq_move_cleanup_interrupt(void)
+{
+	unsigned vector, me;
+
+	ack_APIC_irq();
+	exit_idle();
+	irq_enter();
+
+	me = smp_processor_id();
+	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+		unsigned int irq;
+		unsigned int irr;
+		struct irq_desc *desc;
+		struct irq_cfg *cfg;
+		irq = __get_cpu_var(vector_irq)[vector];
+
+		if (irq == -1)
+			continue;
+
+		desc = irq_to_desc(irq);
+		if (!desc)
+			continue;
+
+		cfg = irq_cfg(irq);
+		spin_lock(&desc->lock);
+		if (!cfg->move_cleanup_count)
+			goto unlock;
+
+		if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
+			goto unlock;
+
+		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
+		/*
+		 * Check if the vector that needs to be cleanedup is
+		 * registered at the cpu's IRR. If so, then this is not
+		 * the best time to clean it up. Lets clean it up in the
+		 * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
+		 * to myself.
+		 */
+		if (irr  & (1 << (vector % 32))) {
+			apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
+			goto unlock;
+		}
+		__get_cpu_var(vector_irq)[vector] = -1;
+		cfg->move_cleanup_count--;
+unlock:
+		spin_unlock(&desc->lock);
+	}
+
+	irq_exit();
+}
+
+static void irq_complete_move(struct irq_desc **descp)
+{
+	struct irq_desc *desc = *descp;
+	struct irq_cfg *cfg = desc->chip_data;
+	unsigned vector, me;
+
+	if (likely(!cfg->move_in_progress))
+		return;
+
+	vector = ~get_irq_regs()->orig_ax;
+	me = smp_processor_id();
+
+	if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
+		send_cleanup_vector(cfg);
+}
+#else
+static inline void irq_complete_move(struct irq_desc **descp) {}
+#endif
+
+static void ack_apic_edge(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	irq_complete_move(&desc);
+	move_native_irq(irq);
+	ack_APIC_irq();
+}
+
+atomic_t irq_mis_count;
+
+static void ack_apic_level(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	unsigned long v;
+	int i;
+	struct irq_cfg *cfg;
+	int do_unmask_irq = 0;
+
+	irq_complete_move(&desc);
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+	/* If we are moving the irq we need to mask it */
+	if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+		do_unmask_irq = 1;
+		mask_IO_APIC_irq_desc(desc);
+	}
+#endif
+
+	/*
+	 * It appears there is an erratum which affects at least version 0x11
+	 * of I/O APIC (that's the 82093AA and cores integrated into various
+	 * chipsets).  Under certain conditions a level-triggered interrupt is
+	 * erroneously delivered as edge-triggered one but the respective IRR
+	 * bit gets set nevertheless.  As a result the I/O unit expects an EOI
+	 * message but it will never arrive and further interrupts are blocked
+	 * from the source.  The exact reason is so far unknown, but the
+	 * phenomenon was observed when two consecutive interrupt requests
+	 * from a given source get delivered to the same CPU and the source is
+	 * temporarily disabled in between.
+	 *
+	 * A workaround is to simulate an EOI message manually.  We achieve it
+	 * by setting the trigger mode to edge and then to level when the edge
+	 * trigger mode gets detected in the TMR of a local APIC for a
+	 * level-triggered interrupt.  We mask the source for the time of the
+	 * operation to prevent an edge-triggered interrupt escaping meanwhile.
+	 * The idea is from Manfred Spraul.  --macro
+	 */
+	cfg = desc->chip_data;
+	i = cfg->vector;
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+	/*
+	 * We must acknowledge the irq before we move it or the acknowledge will
+	 * not propagate properly.
+	 */
+	ack_APIC_irq();
+
+	/* Now we can move and renable the irq */
+	if (unlikely(do_unmask_irq)) {
+		/* Only migrate the irq if the ack has been received.
+		 *
+		 * On rare occasions the broadcast level triggered ack gets
+		 * delayed going to ioapics, and if we reprogram the
+		 * vector while Remote IRR is still set the irq will never
+		 * fire again.
+		 *
+		 * To prevent this scenario we read the Remote IRR bit
+		 * of the ioapic.  This has two effects.
+		 * - On any sane system the read of the ioapic will
+		 *   flush writes (and acks) going to the ioapic from
+		 *   this cpu.
+		 * - We get to see if the ACK has actually been delivered.
+		 *
+		 * Based on failed experiments of reprogramming the
+		 * ioapic entry from outside of irq context starting
+		 * with masking the ioapic entry and then polling until
+		 * Remote IRR was clear before reprogramming the
+		 * ioapic I don't trust the Remote IRR bit to be
+		 * completey accurate.
+		 *
+		 * However there appears to be no other way to plug
+		 * this race, so if the Remote IRR bit is not
+		 * accurate and is causing problems then it is a hardware bug
+		 * and you can go talk to the chipset vendor about it.
+		 */
+		cfg = desc->chip_data;
+		if (!io_apic_level_ack_pending(cfg))
+			move_masked_irq(irq);
+		unmask_IO_APIC_irq_desc(desc);
+	}
+
+	/* Tail end of version 0x11 I/O APIC bug workaround */
+	if (!(v & (1 << (i & 0x1f)))) {
+		atomic_inc(&irq_mis_count);
+		spin_lock(&ioapic_lock);
+		__mask_and_edge_IO_APIC_irq(cfg);
+		__unmask_and_level_IO_APIC_irq(cfg);
+		spin_unlock(&ioapic_lock);
+	}
+}
+
+#ifdef CONFIG_INTR_REMAP
+static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
+{
+	struct irq_pin_list *entry;
+
+	for_each_irq_pin(entry, cfg->irq_2_pin)
+		io_apic_eoi(entry->apic, entry->pin);
+}
+
+static void
+eoi_ioapic_irq(struct irq_desc *desc)
+{
+	struct irq_cfg *cfg;
+	unsigned long flags;
+	unsigned int irq;
+
+	irq = desc->irq;
+	cfg = desc->chip_data;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	__eoi_ioapic_irq(irq, cfg);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
+static void ir_ack_apic_edge(unsigned int irq)
+{
+	ack_APIC_irq();
+}
+
+static void ir_ack_apic_level(unsigned int irq)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	ack_APIC_irq();
+	eoi_ioapic_irq(desc);
+}
+#endif /* CONFIG_INTR_REMAP */
+
+static struct irq_chip ioapic_chip __read_mostly = {
+	.name		= "IO-APIC",
+	.startup	= startup_ioapic_irq,
+	.mask		= mask_IO_APIC_irq,
+	.unmask		= unmask_IO_APIC_irq,
+	.ack		= ack_apic_edge,
+	.eoi		= ack_apic_level,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_ioapic_affinity_irq,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+static struct irq_chip ir_ioapic_chip __read_mostly = {
+	.name		= "IR-IO-APIC",
+	.startup	= startup_ioapic_irq,
+	.mask		= mask_IO_APIC_irq,
+	.unmask		= unmask_IO_APIC_irq,
+#ifdef CONFIG_INTR_REMAP
+	.ack		= ir_ack_apic_edge,
+	.eoi		= ir_ack_apic_level,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_ir_ioapic_affinity_irq,
+#endif
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+#endif /* CONFIG_XEN */
+
+static inline void init_IO_APIC_traps(void)
+{
+	int irq;
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+
+	/*
+	 * NOTE! The local APIC isn't very good at handling
+	 * multiple interrupts at the same interrupt level.
+	 * As the interrupt level is determined by taking the
+	 * vector number and shifting that right by 4, we
+	 * want to spread these out a bit so that they don't
+	 * all fall in the same interrupt level.
+	 *
+	 * Also, we've got to be careful not to trash gate
+	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
+	 */
+	for_each_irq_desc(irq, desc) {
+#ifdef CONFIG_XEN
+		if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs)
+			continue;
+#endif
+		cfg = desc->chip_data;
+		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
+			/*
+			 * Hmm.. We don't have an entry for this,
+			 * so default to an old-fashioned 8259
+			 * interrupt if we can..
+			 */
+			if (irq < nr_legacy_irqs)
+				make_8259A_irq(irq);
+			else
+				/* Strange. Oh, well.. */
+				desc->chip = &no_irq_chip;
+		}
+	}
+}
+
+#ifndef CONFIG_XEN
+/*
+ * The local APIC irq-chip implementation:
+ */
+
+static void mask_lapic_irq(unsigned int irq)
+{
+	unsigned long v;
+
+	v = apic_read(APIC_LVT0);
+	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
+}
+
+static void unmask_lapic_irq(unsigned int irq)
+{
+	unsigned long v;
+
+	v = apic_read(APIC_LVT0);
+	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
+}
+
+static void ack_lapic_irq(unsigned int irq)
+{
+	ack_APIC_irq();
+}
+
+static struct irq_chip lapic_chip __read_mostly = {
+	.name		= "local-APIC",
+	.mask		= mask_lapic_irq,
+	.unmask		= unmask_lapic_irq,
+	.ack		= ack_lapic_irq,
+};
+
+static void lapic_register_intr(int irq, struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_LEVEL;
+	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+				      "edge");
+}
+
+static void __init setup_nmi(void)
+{
+	/*
+	 * Dirty trick to enable the NMI watchdog ...
+	 * We put the 8259A master into AEOI mode and
+	 * unmask on all local APICs LVT0 as NMI.
+	 *
+	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
+	 * is from Maciej W. Rozycki - so we do not have to EOI from
+	 * the NMI handler or the timer interrupt.
+	 */
+	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
+
+	enable_NMI_through_LVT0();
+
+	apic_printk(APIC_VERBOSE, " done.\n");
+}
+
+/*
+ * This looks a bit hackish but it's about the only one way of sending
+ * a few INTA cycles to 8259As and any associated glue logic.  ICR does
+ * not support the ExtINT mode, unfortunately.  We need to send these
+ * cycles as some i82489DX-based boards have glue logic that keeps the
+ * 8259A interrupt line asserted until INTA.  --macro
+ */
+static inline void __init unlock_ExtINT_logic(void)
+{
+	int apic, pin, i;
+	struct IO_APIC_route_entry entry0, entry1;
+	unsigned char save_control, save_freq_select;
+
+	pin  = find_isa_irq_pin(8, mp_INT);
+	if (pin == -1) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+	apic = find_isa_irq_apic(8, mp_INT);
+	if (apic == -1) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	entry0 = ioapic_read_entry(apic, pin);
+	clear_IO_APIC_pin(apic, pin);
+
+	memset(&entry1, 0, sizeof(entry1));
+
+	entry1.dest_mode = 0;			/* physical delivery */
+	entry1.mask = 0;			/* unmask IRQ now */
+	entry1.dest = hard_smp_processor_id();
+	entry1.delivery_mode = dest_ExtINT;
+	entry1.polarity = entry0.polarity;
+	entry1.trigger = 0;
+	entry1.vector = 0;
+
+	ioapic_write_entry(apic, pin, entry1);
+
+	save_control = CMOS_READ(RTC_CONTROL);
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+	CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6,
+		   RTC_FREQ_SELECT);
+	CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL);
+
+	i = 100;
+	while (i-- > 0) {
+		mdelay(10);
+		if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF)
+			i -= 10;
+	}
+
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	clear_IO_APIC_pin(apic, pin);
+
+	ioapic_write_entry(apic, pin, entry0);
+}
+
+static int disable_timer_pin_1 __initdata;
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+static int __init disable_timer_pin_setup(char *arg)
+{
+	disable_timer_pin_1 = 1;
+	return 0;
+}
+early_param("disable_timer_pin_1", disable_timer_pin_setup);
+
+int timer_through_8259 __initdata;
+
+/*
+ * This code may look a bit paranoid, but it's supposed to cooperate with
+ * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
+ * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
+ * fanatically on his truly buggy board.
+ *
+ * FIXME: really need to revamp this for all platforms.
+ */
+static inline void __init check_timer(void)
+{
+	struct irq_desc *desc = irq_to_desc(0);
+	struct irq_cfg *cfg = desc->chip_data;
+	int node = cpu_to_node(boot_cpu_id);
+	int apic1, pin1, apic2, pin2;
+	unsigned long flags;
+	int no_pin1 = 0;
+
+	local_irq_save(flags);
+
+	/*
+	 * get/set the timer IRQ vector:
+	 */
+	disable_8259A_irq(0);
+	assign_irq_vector(0, cfg, apic->target_cpus());
+
+	/*
+	 * As IRQ0 is to be enabled in the 8259A, the virtual
+	 * wire has to be disabled in the local APIC.  Also
+	 * timer interrupts need to be acknowledged manually in
+	 * the 8259A for the i82489DX when using the NMI
+	 * watchdog as that APIC treats NMIs as level-triggered.
+	 * The AEOI mode will finish them in the 8259A
+	 * automatically.
+	 */
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+	init_8259A(1);
+#ifdef CONFIG_X86_32
+	{
+		unsigned int ver;
+
+		ver = apic_read(APIC_LVR);
+		ver = GET_APIC_VERSION(ver);
+		timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
+	}
+#endif
+
+	pin1  = find_isa_irq_pin(0, mp_INT);
+	apic1 = find_isa_irq_apic(0, mp_INT);
+	pin2  = ioapic_i8259.pin;
+	apic2 = ioapic_i8259.apic;
+
+	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+		    cfg->vector, apic1, pin1, apic2, pin2);
+
+	/*
+	 * Some BIOS writers are clueless and report the ExtINTA
+	 * I/O APIC input from the cascaded 8259A as the timer
+	 * interrupt input.  So just in case, if only one pin
+	 * was found above, try it both directly and through the
+	 * 8259A.
+	 */
+	if (pin1 == -1) {
+		if (intr_remapping_enabled)
+			panic("BIOS bug: timer not connected to IO-APIC");
+		pin1 = pin2;
+		apic1 = apic2;
+		no_pin1 = 1;
+	} else if (pin2 == -1) {
+		pin2 = pin1;
+		apic2 = apic1;
+	}
+
+	if (pin1 != -1) {
+		/*
+		 * Ok, does IRQ0 through the IOAPIC work?
+		 */
+		if (no_pin1) {
+			add_pin_to_irq_node(cfg, node, apic1, pin1);
+			setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
+		} else {
+			/* for edge trigger, setup_IO_APIC_irq already
+			 * leave it unmasked.
+			 * so only need to unmask if it is level-trigger
+			 * do we really have level trigger timer?
+			 */
+			int idx;
+			idx = find_irq_entry(apic1, pin1, mp_INT);
+			if (idx != -1 && irq_trigger(idx))
+				unmask_IO_APIC_irq_desc(desc);
+		}
+		if (timer_irq_works()) {
+			if (nmi_watchdog == NMI_IO_APIC) {
+				setup_nmi();
+				enable_8259A_irq(0);
+			}
+			if (disable_timer_pin_1 > 0)
+				clear_IO_APIC_pin(0, pin1);
+			goto out;
+		}
+		if (intr_remapping_enabled)
+			panic("timer doesn't work through Interrupt-remapped IO-APIC");
+		local_irq_disable();
+		clear_IO_APIC_pin(apic1, pin1);
+		if (!no_pin1)
+			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+				    "8254 timer not connected to IO-APIC\n");
+
+		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+			    "(IRQ0) through the 8259A ...\n");
+		apic_printk(APIC_QUIET, KERN_INFO
+			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
+		/*
+		 * legacy devices should be connected to IO APIC #0
+		 */
+		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
+		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
+		enable_8259A_irq(0);
+		if (timer_irq_works()) {
+			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
+			timer_through_8259 = 1;
+			if (nmi_watchdog == NMI_IO_APIC) {
+				disable_8259A_irq(0);
+				setup_nmi();
+				enable_8259A_irq(0);
+			}
+			goto out;
+		}
+		/*
+		 * Cleanup, just in case ...
+		 */
+		local_irq_disable();
+		disable_8259A_irq(0);
+		clear_IO_APIC_pin(apic2, pin2);
+		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
+	}
+
+	if (nmi_watchdog == NMI_IO_APIC) {
+		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+			    "through the IO-APIC - disabling NMI Watchdog!\n");
+		nmi_watchdog = NMI_NONE;
+	}
+#ifdef CONFIG_X86_32
+	timer_ack = 0;
+#endif
+
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as Virtual Wire IRQ...\n");
+
+	lapic_register_intr(0, desc);
+	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
+	enable_8259A_irq(0);
+
+	if (timer_irq_works()) {
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+		goto out;
+	}
+	local_irq_disable();
+	disable_8259A_irq(0);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
+
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as ExtINT IRQ...\n");
+
+	init_8259A(0);
+	make_8259A_irq(0);
+	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+
+	unlock_ExtINT_logic();
+
+	if (timer_irq_works()) {
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
+		goto out;
+	}
+	local_irq_disable();
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+		"report.  Then try booting with the 'noapic' option.\n");
+out:
+	local_irq_restore(flags);
+}
+#else
+#define check_timer() ((void)0)
+#endif
+
+/*
+ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
+ * to devices.  However there may be an I/O APIC pin available for
+ * this interrupt regardless.  The pin may be left unconnected, but
+ * typically it will be reused as an ExtINT cascade interrupt for
+ * the master 8259A.  In the MPS case such a pin will normally be
+ * reported as an ExtINT interrupt in the MP table.  With ACPI
+ * there is no provision for ExtINT interrupts, and in the absence
+ * of an override it would be treated as an ordinary ISA I/O APIC
+ * interrupt, that is edge-triggered and unmasked by default.  We
+ * used to do this, but it caused problems on some systems because
+ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
+ * the same ExtINT cascade interrupt to drive the local APIC of the
+ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
+ * the I/O APIC in all cases now.  No actual device should request
+ * it anyway.  --macro
+ */
+#define PIC_IRQS	(1UL << PIC_CASCADE_IR)
+
+void __init setup_IO_APIC(void)
+{
+
+#ifdef CONFIG_XEN
+	enable_IO_APIC();
+#else
+	/*
+	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
+	 */
+#endif
+	io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+
+	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+	/*
+         * Set up IO-APIC IRQ routing.
+         */
+#ifndef CONFIG_XEN
+	x86_init.mpparse.setup_ioapic_ids();
+
+	sync_Arb_IDs();
+#endif
+	setup_IO_APIC_irqs();
+	init_IO_APIC_traps();
+	if (nr_legacy_irqs)
+		check_timer();
+}
+
+/*
+ *      Called after all the initialization is done. If we didnt find any
+ *      APIC bugs then we can allow the modify fast path
+ */
+
+static int __init io_apic_bug_finalize(void)
+{
+	if (sis_apic_bug == -1)
+		sis_apic_bug = 0;
+#ifdef CONFIG_XEN
+	if (is_initial_xendomain()) {
+		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
+		op.u.platform_quirk.quirk_id = sis_apic_bug ?
+			QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
+		VOID(HYPERVISOR_platform_op(&op));
+	}
+#endif
+	return 0;
+}
+
+late_initcall(io_apic_bug_finalize);
+
+#ifndef CONFIG_XEN
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+		*entry = ioapic_read_entry(dev->id, i);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+		ioapic_write_entry(dev->id, i, entry[i]);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	.name = "ioapic",
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i;
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
+/*
+ * Dynamic irq allocate and deallocation
+ */
+unsigned int create_irq_nr(unsigned int irq_want, int node)
+{
+	/* Allocate an unused irq */
+	unsigned int irq;
+	unsigned int new;
+	unsigned long flags;
+	struct irq_cfg *cfg_new = NULL;
+	struct irq_desc *desc_new = NULL;
+
+	irq = 0;
+	if (irq_want < nr_irqs_gsi)
+		irq_want = nr_irqs_gsi;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	for (new = irq_want; new < nr_irqs; new++) {
+		desc_new = irq_to_desc_alloc_node(new, node);
+		if (!desc_new) {
+			printk(KERN_INFO "can not get irq_desc for %d\n", new);
+			continue;
+		}
+		cfg_new = desc_new->chip_data;
+
+		if (cfg_new->vector != 0)
+			continue;
+
+		desc_new = move_irq_desc(desc_new, node);
+		cfg_new = desc_new->chip_data;
+
+		if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
+			irq = new;
+		break;
+	}
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	if (irq > 0)
+		dynamic_irq_init_keep_chip_data(irq);
+
+	return irq;
+}
+
+int create_irq(void)
+{
+	int node = cpu_to_node(boot_cpu_id);
+	unsigned int irq_want;
+	int irq;
+
+	irq_want = nr_irqs_gsi;
+	irq = create_irq_nr(irq_want, node);
+
+	if (irq == 0)
+		irq = -1;
+
+	return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+	unsigned long flags;
+	struct irq_cfg *cfg;
+
+	dynamic_irq_cleanup_keep_chip_data(irq);
+
+	free_irte(irq);
+	spin_lock_irqsave(&vector_lock, flags);
+	cfg = irq_to_desc(irq)->chip_data;
+	__clear_irq_vector(irq, cfg);
+	spin_unlock_irqrestore(&vector_lock, flags);
+}
+#endif /* CONFIG_XEN */
+
+/*
+ * MSI message composition
+ */
+#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+{
+	struct irq_cfg *cfg;
+	int err;
+	unsigned dest;
+
+	if (disable_apic)
+		return -ENXIO;
+
+	cfg = irq_cfg(irq);
+	err = assign_irq_vector(irq, cfg, apic->target_cpus());
+	if (err)
+		return err;
+
+	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+
+	if (irq_remapped(irq)) {
+		struct irte irte;
+		int ir_index;
+		u16 sub_handle;
+
+		ir_index = map_irq_to_irte_handle(irq, &sub_handle);
+		BUG_ON(ir_index == -1);
+
+		memset (&irte, 0, sizeof(irte));
+
+		irte.present = 1;
+		irte.dst_mode = apic->irq_dest_mode;
+		irte.trigger_mode = 0; /* edge */
+		irte.dlvry_mode = apic->irq_delivery_mode;
+		irte.vector = cfg->vector;
+		irte.dest_id = IRTE_DEST(dest);
+
+		/* Set source-id of interrupt request */
+		set_msi_sid(&irte, pdev);
+
+		modify_irte(irq, &irte);
+
+		msg->address_hi = MSI_ADDR_BASE_HI;
+		msg->data = sub_handle;
+		msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
+				  MSI_ADDR_IR_SHV |
+				  MSI_ADDR_IR_INDEX1(ir_index) |
+				  MSI_ADDR_IR_INDEX2(ir_index);
+	} else {
+		if (x2apic_enabled())
+			msg->address_hi = MSI_ADDR_BASE_HI |
+					  MSI_ADDR_EXT_DEST_ID(dest);
+		else
+			msg->address_hi = MSI_ADDR_BASE_HI;
+
+		msg->address_lo =
+			MSI_ADDR_BASE_LO |
+			((apic->irq_dest_mode == 0) ?
+				MSI_ADDR_DEST_MODE_PHYSICAL:
+				MSI_ADDR_DEST_MODE_LOGICAL) |
+			((apic->irq_delivery_mode != dest_LowestPrio) ?
+				MSI_ADDR_REDIRECTION_CPU:
+				MSI_ADDR_REDIRECTION_LOWPRI) |
+			MSI_ADDR_DEST_ID(dest);
+
+		msg->data =
+			MSI_DATA_TRIGGER_EDGE |
+			MSI_DATA_LEVEL_ASSERT |
+			((apic->irq_delivery_mode != dest_LowestPrio) ?
+				MSI_DATA_DELIVERY_FIXED:
+				MSI_DATA_DELIVERY_LOWPRI) |
+			MSI_DATA_VECTOR(cfg->vector);
+	}
+	return err;
+}
+
+#ifdef CONFIG_SMP
+static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+
+	dest = set_desc_affinity(desc, mask);
+	if (dest == BAD_APICID)
+		return -1;
+
+	cfg = desc->chip_data;
+
+	get_cached_msi_msg_desc(desc, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+	write_msi_msg_desc(desc, &msg);
+
+	return 0;
+}
+#ifdef CONFIG_INTR_REMAP
+/*
+ * Migrate the MSI irq to another cpumask. This migration is
+ * done in the process context using interrupt-remapping hardware.
+ */
+static int
+ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_cfg *cfg = desc->chip_data;
+	unsigned int dest;
+	struct irte irte;
+
+	if (get_irte(irq, &irte))
+		return -1;
+
+	dest = set_desc_affinity(desc, mask);
+	if (dest == BAD_APICID)
+		return -1;
+
+	irte.vector = cfg->vector;
+	irte.dest_id = IRTE_DEST(dest);
+
+	/*
+	 * atomically update the IRTE with the new destination and vector.
+	 */
+	modify_irte(irq, &irte);
+
+	/*
+	 * After this point, all the interrupts will start arriving
+	 * at the new destination. So, time to cleanup the previous
+	 * vector allocation.
+	 */
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return 0;
+}
+
+#endif
+#endif /* CONFIG_SMP */
+
+/*
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
+ */
+static struct irq_chip msi_chip = {
+	.name		= "PCI-MSI",
+	.unmask		= unmask_msi_irq,
+	.mask		= mask_msi_irq,
+	.ack		= ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_msi_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+static struct irq_chip msi_ir_chip = {
+	.name		= "IR-PCI-MSI",
+	.unmask		= unmask_msi_irq,
+	.mask		= mask_msi_irq,
+#ifdef CONFIG_INTR_REMAP
+	.ack		= ir_ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= ir_set_msi_irq_affinity,
+#endif
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+/*
+ * Map the PCI dev to the corresponding remapping hardware unit
+ * and allocate 'nvec' consecutive interrupt-remapping table entries
+ * in it.
+ */
+static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
+{
+	struct intel_iommu *iommu;
+	int index;
+
+	iommu = map_dev_to_ir(dev);
+	if (!iommu) {
+		printk(KERN_ERR
+		       "Unable to map PCI %s to iommu\n", pci_name(dev));
+		return -ENOENT;
+	}
+
+	index = alloc_irte(iommu, irq, nvec);
+	if (index < 0) {
+		printk(KERN_ERR
+		       "Unable to allocate %d IRTE for PCI %s\n", nvec,
+		       pci_name(dev));
+		return -ENOSPC;
+	}
+	return index;
+}
+
+static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(dev, irq, &msg);
+	if (ret < 0)
+		return ret;
+
+	set_irq_msi(irq, msidesc);
+	write_msi_msg(irq, &msg);
+
+	if (irq_remapped(irq)) {
+		struct irq_desc *desc = irq_to_desc(irq);
+		/*
+		 * irq migration in process context
+		 */
+		desc->status |= IRQ_MOVE_PCNTXT;
+		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
+	} else
+		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+
+	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
+
+	return 0;
+}
+
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+	unsigned int irq;
+	int ret, sub_handle;
+	struct msi_desc *msidesc;
+	unsigned int irq_want;
+	struct intel_iommu *iommu = NULL;
+	int index = 0;
+	int node;
+
+	/* x86 doesn't support multiple MSI yet */
+	if (type == PCI_CAP_ID_MSI && nvec > 1)
+		return 1;
+
+	node = dev_to_node(&dev->dev);
+	irq_want = nr_irqs_gsi;
+	sub_handle = 0;
+	list_for_each_entry(msidesc, &dev->msi_list, list) {
+		irq = create_irq_nr(irq_want, node);
+		if (irq == 0)
+			return -1;
+		irq_want = irq + 1;
+		if (!intr_remapping_enabled)
+			goto no_ir;
+
+		if (!sub_handle) {
+			/*
+			 * allocate the consecutive block of IRTE's
+			 * for 'nvec'
+			 */
+			index = msi_alloc_irte(dev, irq, nvec);
+			if (index < 0) {
+				ret = index;
+				goto error;
+			}
+		} else {
+			iommu = map_dev_to_ir(dev);
+			if (!iommu) {
+				ret = -ENOENT;
+				goto error;
+			}
+			/*
+			 * setup the mapping between the irq and the IRTE
+			 * base index, the sub_handle pointing to the
+			 * appropriate interrupt remap table entry.
+			 */
+			set_irte_irq(irq, iommu, index, sub_handle);
+		}
+no_ir:
+		ret = setup_msi_irq(dev, msidesc, irq);
+		if (ret < 0)
+			goto error;
+		sub_handle++;
+	}
+	return 0;
+
+error:
+	destroy_irq(irq);
+	return ret;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	destroy_irq(irq);
+}
+
+#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
+#ifdef CONFIG_SMP
+static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+
+	dest = set_desc_affinity(desc, mask);
+	if (dest == BAD_APICID)
+		return -1;
+
+	cfg = desc->chip_data;
+
+	dmar_msi_read(irq, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+	msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
+
+	dmar_msi_write(irq, &msg);
+
+	return 0;
+}
+
+#endif /* CONFIG_SMP */
+
+static struct irq_chip dmar_msi_type = {
+	.name = "DMAR_MSI",
+	.unmask = dmar_msi_unmask,
+	.mask = dmar_msi_mask,
+	.ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity = dmar_msi_set_affinity,
+#endif
+	.retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_dmar_msi(unsigned int irq)
+{
+	int ret;
+	struct msi_msg msg;
+
+	ret = msi_compose_msg(NULL, irq, &msg);
+	if (ret < 0)
+		return ret;
+	dmar_msi_write(irq, &msg);
+	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+		"edge");
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_HPET_TIMER
+
+#ifdef CONFIG_SMP
+static int hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_cfg *cfg;
+	struct msi_msg msg;
+	unsigned int dest;
+
+	dest = set_desc_affinity(desc, mask);
+	if (dest == BAD_APICID)
+		return -1;
+
+	cfg = desc->chip_data;
+
+	hpet_msi_read(irq, &msg);
+
+	msg.data &= ~MSI_DATA_VECTOR_MASK;
+	msg.data |= MSI_DATA_VECTOR(cfg->vector);
+	msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+	msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+	hpet_msi_write(irq, &msg);
+
+	return 0;
+}
+
+#endif /* CONFIG_SMP */
+
+static struct irq_chip hpet_msi_type = {
+	.name = "HPET_MSI",
+	.unmask = hpet_msi_unmask,
+	.mask = hpet_msi_mask,
+	.ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity = hpet_msi_set_affinity,
+#endif
+	.retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_hpet_msi(unsigned int irq)
+{
+	int ret;
+	struct msi_msg msg;
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	ret = msi_compose_msg(NULL, irq, &msg);
+	if (ret < 0)
+		return ret;
+
+	hpet_msi_write(irq, &msg);
+	desc->status |= IRQ_MOVE_PCNTXT;
+	set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq,
+		"edge");
+
+	return 0;
+}
+#endif
+
+#endif /* CONFIG_PCI_MSI */
+/*
+ * Hypertransport interrupt support
+ */
+#ifdef CONFIG_HT_IRQ
+
+#ifdef CONFIG_SMP
+
+static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
+{
+	struct ht_irq_msg msg;
+	fetch_ht_irq_msg(irq, &msg);
+
+	msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK);
+	msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK);
+
+	msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest);
+	msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest);
+
+	write_ht_irq_msg(irq, &msg);
+}
+
+static int set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_cfg *cfg;
+	unsigned int dest;
+
+	dest = set_desc_affinity(desc, mask);
+	if (dest == BAD_APICID)
+		return -1;
+
+	cfg = desc->chip_data;
+
+	target_ht_irq(irq, dest, cfg->vector);
+
+	return 0;
+}
+
+#endif
+
+static struct irq_chip ht_irq_chip = {
+	.name		= "PCI-HT",
+	.mask		= mask_ht_irq,
+	.unmask		= unmask_ht_irq,
+	.ack		= ack_apic_edge,
+#ifdef CONFIG_SMP
+	.set_affinity	= set_ht_irq_affinity,
+#endif
+	.retrigger	= ioapic_retrigger_irq,
+};
+
+int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
+{
+	struct irq_cfg *cfg;
+	int err;
+
+	if (disable_apic)
+		return -ENXIO;
+
+	cfg = irq_cfg(irq);
+	err = assign_irq_vector(irq, cfg, apic->target_cpus());
+	if (!err) {
+		struct ht_irq_msg msg;
+		unsigned dest;
+
+		dest = apic->cpu_mask_to_apicid_and(cfg->domain,
+						    apic->target_cpus());
+
+		msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+
+		msg.address_lo =
+			HT_IRQ_LOW_BASE |
+			HT_IRQ_LOW_DEST_ID(dest) |
+			HT_IRQ_LOW_VECTOR(cfg->vector) |
+			((apic->irq_dest_mode == 0) ?
+				HT_IRQ_LOW_DM_PHYSICAL :
+				HT_IRQ_LOW_DM_LOGICAL) |
+			HT_IRQ_LOW_RQEOI_EDGE |
+			((apic->irq_delivery_mode != dest_LowestPrio) ?
+				HT_IRQ_LOW_MT_FIXED :
+				HT_IRQ_LOW_MT_ARBITRATED) |
+			HT_IRQ_LOW_IRQ_MASKED;
+
+		write_ht_irq_msg(irq, &msg);
+
+		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+					      handle_edge_irq, "edge");
+
+		dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
+	}
+	return err;
+}
+#endif /* CONFIG_HT_IRQ */
+
+#ifdef CONFIG_X86_UV
+/*
+ * Re-target the irq to the specified CPU and enable the specified MMR located
+ * on the specified blade to allow the sending of MSIs to the specified CPU.
+ */
+int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
+		       unsigned long mmr_offset)
+{
+	const struct cpumask *eligible_cpu = cpumask_of(cpu);
+	struct irq_cfg *cfg;
+	int mmr_pnode;
+	unsigned long mmr_value;
+	struct uv_IO_APIC_route_entry *entry;
+	unsigned long flags;
+	int err;
+
+	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
+	cfg = irq_cfg(irq);
+
+	err = assign_irq_vector(irq, cfg, eligible_cpu);
+	if (err != 0)
+		return err;
+
+	spin_lock_irqsave(&vector_lock, flags);
+	set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
+				      irq_name);
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	mmr_value = 0;
+	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+	entry->vector		= cfg->vector;
+	entry->delivery_mode	= apic->irq_delivery_mode;
+	entry->dest_mode	= apic->irq_dest_mode;
+	entry->polarity		= 0;
+	entry->trigger		= 0;
+	entry->mask		= 0;
+	entry->dest		= apic->cpu_mask_to_apicid(eligible_cpu);
+
+	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+
+	if (cfg->move_in_progress)
+		send_cleanup_vector(cfg);
+
+	return irq;
+}
+
+/*
+ * Disable the specified MMR located on the specified blade so that MSIs are
+ * longer allowed to be sent.
+ */
+void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
+{
+	unsigned long mmr_value;
+	struct uv_IO_APIC_route_entry *entry;
+	int mmr_pnode;
+
+	BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
+	mmr_value = 0;
+	entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+	entry->mask = 1;
+
+	mmr_pnode = uv_blade_to_pnode(mmr_blade);
+	uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+}
+#endif /* CONFIG_X86_64 */
+
+int __init io_apic_get_redir_entries (int ioapic)
+{
+	union IO_APIC_reg_01	reg_01;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_01.raw = io_apic_read(ioapic, 1);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return reg_01.bits.entries;
+}
+
+#ifndef CONFIG_XEN
+void __init probe_nr_irqs_gsi(void)
+{
+	int nr = 0;
+
+	nr = acpi_probe_gsi();
+	if (nr > nr_irqs_gsi) {
+		nr_irqs_gsi = nr;
+	} else {
+		/* for acpi=off or acpi is not compiled in */
+		int idx;
+
+		nr = 0;
+		for (idx = 0; idx < nr_ioapics; idx++)
+			nr += io_apic_get_redir_entries(idx) + 1;
+
+		if (nr > nr_irqs_gsi)
+			nr_irqs_gsi = nr;
+	}
+
+	printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
+}
+
+#ifdef CONFIG_SPARSE_IRQ
+int __init arch_probe_nr_irqs(void)
+{
+	int nr;
+
+	if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
+		nr_irqs = NR_VECTORS * nr_cpu_ids;
+
+	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
+#if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
+	/*
+	 * for MSI and HT dyn irq
+	 */
+	nr += nr_irqs_gsi * 16;
+#endif
+	if (nr < nr_irqs)
+		nr_irqs = nr;
+
+	return 0;
+}
+#endif
+#endif /* CONFIG_XEN */
+
+static int __io_apic_set_pci_routing(struct device *dev, int irq,
+				struct io_apic_irq_attr *irq_attr)
+{
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+	int node;
+	int ioapic, pin;
+	int trigger, polarity;
+
+	ioapic = irq_attr->ioapic;
+#ifdef CONFIG_XEN
+	if (irq < PIRQ_BASE || irq >= PIRQ_BASE + nr_pirqs) {
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ %d\n",
+			    ioapic, irq);
+		return -EINVAL;
+	}
+#endif
+	if (!IO_APIC_IRQ(irq)) {
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+			ioapic);
+		return -EINVAL;
+	}
+
+	if (dev)
+		node = dev_to_node(dev);
+	else
+		node = cpu_to_node(boot_cpu_id);
+
+	desc = irq_to_desc_alloc_node(irq, node);
+	if (!desc) {
+		printk(KERN_INFO "can not get irq_desc %d\n", irq);
+		return 0;
+	}
+
+	pin = irq_attr->ioapic_pin;
+	trigger = irq_attr->trigger;
+	polarity = irq_attr->polarity;
+
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= nr_legacy_irqs) {
+		cfg = desc->chip_data;
+		if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
+			printk(KERN_INFO "can not add pin %d for irq %d\n",
+				pin, irq);
+			return 0;
+		}
+	}
+
+	setup_IO_APIC_irq(ioapic, pin, irq, desc, trigger, polarity);
+
+	return 0;
+}
+
+int io_apic_set_pci_routing(struct device *dev, int irq,
+				struct io_apic_irq_attr *irq_attr)
+{
+	int ioapic, pin;
+	/*
+	 * Avoid pin reprogramming.  PRTs typically include entries
+	 * with redundant pin->gsi mappings (but unique PCI devices);
+	 * we only program the IOAPIC on the first.
+	 */
+	ioapic = irq_attr->ioapic;
+	pin = irq_attr->ioapic_pin;
+	if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[ioapic].apicid, pin);
+		return 0;
+	}
+	set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
+
+	return __io_apic_set_pci_routing(dev, irq, irq_attr);
+}
+
+u8 __init io_apic_unique_id(u8 id)
+{
+#ifdef CONFIG_X86_32
+#ifndef CONFIG_XEN
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return io_apic_get_unique_id(nr_ioapics, id);
+	else
+#endif
+		return id;
+#else
+	int i;
+	DECLARE_BITMAP(used, 256);
+
+	bitmap_zero(used, 256);
+	for (i = 0; i < nr_ioapics; i++) {
+		struct mpc_ioapic *ia = &mp_ioapics[i];
+		__set_bit(ia->apicid, used);
+	}
+	if (!test_bit(id, used))
+		return id;
+	return find_first_zero_bit(used, 256);
+#endif
+}
+
+#ifdef CONFIG_X86_32
+int __init io_apic_get_unique_id(int ioapic, int apic_id)
+{
+#ifndef CONFIG_XEN
+	union IO_APIC_reg_00 reg_00;
+	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
+	physid_mask_t tmp;
+	unsigned long flags;
+	int i = 0;
+
+	/*
+	 * The P4 platform supports up to 256 APIC IDs on two separate APIC
+	 * buses (one for LAPICs, one for IOAPICs), where predecessors only
+	 * supports up to 16 on one shared APIC bus.
+	 *
+	 * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
+	 *      advantage of new APIC bus architecture.
+	 */
+
+	if (physids_empty(apic_id_map))
+		apic_id_map = apic->ioapic_phys_id_map(phys_cpu_present_map);
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(ioapic, 0);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	if (apic_id >= get_physical_broadcast()) {
+		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+			"%d\n", ioapic, apic_id, reg_00.bits.ID);
+		apic_id = reg_00.bits.ID;
+	}
+
+	/*
+	 * Every APIC in a system must have a unique ID or we get lots of nice
+	 * 'stuck on smp_invalidate_needed IPI wait' messages.
+	 */
+	if (apic->check_apicid_used(apic_id_map, apic_id)) {
+
+		for (i = 0; i < get_physical_broadcast(); i++) {
+			if (!apic->check_apicid_used(apic_id_map, i))
+				break;
+		}
+
+		if (i == get_physical_broadcast())
+			panic("Max apic_id exceeded!\n");
+
+		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+			"trying %d\n", ioapic, apic_id, i);
+
+		apic_id = i;
+	}
+
+	tmp = apic->apicid_to_cpu_present(apic_id);
+	physids_or(apic_id_map, apic_id_map, tmp);
+
+	if (reg_00.bits.ID != apic_id) {
+		reg_00.bits.ID = apic_id;
+
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(ioapic, 0, reg_00.raw);
+		reg_00.raw = io_apic_read(ioapic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+
+		/* Sanity check */
+		if (reg_00.bits.ID != apic_id) {
+			printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+			return -1;
+		}
+	}
+
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+#endif /* !CONFIG_XEN */
+
+	return apic_id;
+}
+#endif
+
+int __init io_apic_get_version(int ioapic)
+{
+	union IO_APIC_reg_01	reg_01;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_01.raw = io_apic_read(ioapic, 1);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return reg_01.bits.version;
+}
+
+int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+{
+	int i;
+
+	if (skip_ioapic_setup)
+		return -1;
+
+	for (i = 0; i < mp_irq_entries; i++)
+		if (mp_irqs[i].irqtype == mp_INT &&
+		    mp_irqs[i].srcbusirq == bus_irq)
+			break;
+	if (i >= mp_irq_entries)
+		return -1;
+
+	*trigger = irq_trigger(i);
+	*polarity = irq_polarity(i);
+	return 0;
+}
+
+#ifndef CONFIG_XEN
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be apic->target_cpus()
+ */
+#ifdef CONFIG_SMP
+void __init setup_ioapic_dest(void)
+{
+	int pin, ioapic, irq, irq_entry;
+	struct irq_desc *desc;
+	const struct cpumask *mask;
+
+	if (skip_ioapic_setup == 1)
+		return;
+
+
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
+	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+		if (irq_entry == -1)
+			continue;
+		irq = pin_2_irq(irq_entry, ioapic, pin);
+
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
+		desc = irq_to_desc(irq);
+
+		/*
+		 * Honour affinities which have been set in early boot
+		 */
+		if (desc->status &
+		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
+			mask = desc->affinity;
+		else
+			mask = apic->target_cpus();
+
+		if (intr_remapping_enabled)
+			set_ir_ioapic_affinity_irq_desc(desc, mask);
+		else
+			set_ioapic_affinity_irq_desc(desc, mask);
+	}
+
+}
+#endif
+
+#define IOAPIC_RESOURCE_NAME_SIZE 11
+
+static struct resource *ioapic_resources;
+
+static struct resource * __init ioapic_setup_resources(int nr_ioapics)
+{
+	unsigned long n;
+	struct resource *res;
+	char *mem;
+	int i;
+
+	if (nr_ioapics <= 0)
+		return NULL;
+
+	n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+	n *= nr_ioapics;
+
+	mem = alloc_bootmem(n);
+	res = (void *)mem;
+
+	mem += sizeof(struct resource) * nr_ioapics;
+
+	for (i = 0; i < nr_ioapics; i++) {
+		res[i].name = mem;
+		res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		sprintf(mem,  "IOAPIC %u", i);
+		mem += IOAPIC_RESOURCE_NAME_SIZE;
+	}
+
+	ioapic_resources = res;
+
+	return res;
+}
+
+void __init ioapic_init_mappings(void)
+{
+	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+	struct resource *ioapic_res;
+	int i;
+
+	ioapic_res = ioapic_setup_resources(nr_ioapics);
+	for (i = 0; i < nr_ioapics; i++) {
+		if (smp_found_config) {
+			ioapic_phys = mp_ioapics[i].apicaddr;
+#ifdef CONFIG_X86_32
+			if (!ioapic_phys) {
+				printk(KERN_ERR
+				       "WARNING: bogus zero IO-APIC "
+				       "address found in MPTABLE, "
+				       "disabling IO/APIC support!\n");
+				smp_found_config = 0;
+				skip_ioapic_setup = 1;
+				goto fake_ioapic_page;
+			}
+#endif
+		} else {
+#ifdef CONFIG_X86_32
+fake_ioapic_page:
+#endif
+			ioapic_phys = (unsigned long)
+				alloc_bootmem_pages(PAGE_SIZE);
+			ioapic_phys = __pa(ioapic_phys);
+		}
+		set_fixmap_nocache(idx, ioapic_phys);
+		apic_printk(APIC_VERBOSE,
+			    "mapped IOAPIC to %08lx (%08lx)\n",
+			    __fix_to_virt(idx), ioapic_phys);
+		idx++;
+
+		ioapic_res->start = ioapic_phys;
+		ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+		ioapic_res++;
+	}
+}
+
+void __init ioapic_insert_resources(void)
+{
+	int i;
+	struct resource *r = ioapic_resources;
+
+	if (!r) {
+		if (nr_ioapics > 0)
+			printk(KERN_ERR
+				"IO APIC resources couldn't be allocated.\n");
+		return;
+	}
+
+	for (i = 0; i < nr_ioapics; i++) {
+		insert_resource(&iomem_resource, r);
+		r++;
+	}
+}
+#endif /* !CONFIG_XEN */
+
+int mp_find_ioapic(int gsi)
+{
+	int i = 0;
+
+	/* Find the IOAPIC that manages this GSI. */
+	for (i = 0; i < nr_ioapics; i++) {
+		if ((gsi >= mp_gsi_routing[i].gsi_base)
+		    && (gsi <= mp_gsi_routing[i].gsi_end))
+			return i;
+	}
+
+	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
+	return -1;
+}
+
+int mp_find_ioapic_pin(int ioapic, int gsi)
+{
+	if (WARN_ON(ioapic == -1))
+		return -1;
+	if (WARN_ON(gsi > mp_gsi_routing[ioapic].gsi_end))
+		return -1;
+
+	return gsi - mp_gsi_routing[ioapic].gsi_base;
+}
+
+static int bad_ioapic(unsigned long address)
+{
+	if (nr_ioapics >= MAX_IO_APICS) {
+		printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
+		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
+		return 1;
+	}
+	if (!address) {
+		printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address"
+		       " found in table, skipping!\n");
+		return 1;
+	}
+	return 0;
+}
+
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+{
+	int idx = 0;
+
+	if (bad_ioapic(address))
+		return;
+
+	idx = nr_ioapics;
+
+	mp_ioapics[idx].type = MP_IOAPIC;
+	mp_ioapics[idx].flags = MPC_APIC_USABLE;
+	mp_ioapics[idx].apicaddr = address;
+
+#ifndef CONFIG_XEN
+	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
+#endif
+	mp_ioapics[idx].apicid = io_apic_unique_id(id);
+	mp_ioapics[idx].apicver = io_apic_get_version(idx);
+
+	/*
+	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+	 */
+	mp_gsi_routing[idx].gsi_base = gsi_base;
+	mp_gsi_routing[idx].gsi_end = gsi_base +
+	    io_apic_get_redir_entries(idx);
+
+	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+	       "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
+	       mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
+	       mp_gsi_routing[idx].gsi_base, mp_gsi_routing[idx].gsi_end);
+
+	nr_ioapics++;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/probe_32.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/probe_32.c
@@ -54,6 +54,31 @@
 
 void default_setup_apic_routing(void)
 {
+	int version = apic_version[boot_cpu_physical_apicid];
+
+	if (num_possible_cpus() > 8) {
+		switch (boot_cpu_data.x86_vendor) {
+		case X86_VENDOR_INTEL:
+			if (!APIC_XAPIC(version)) {
+				def_to_bigsmp = 0;
+				break;
+			}
+			/* If P4 and above fall through */
+		case X86_VENDOR_AMD:
+			def_to_bigsmp = 1;
+		}
+	}
+
+#ifdef CONFIG_X86_BIGSMP
+	generic_bigsmp_probe();
+#endif
+
+	if (apic->setup_apic_routing)
+		apic->setup_apic_routing();
+}
+
+void setup_apic_flat_routing(void)
+{
 #ifdef CONFIG_X86_IO_APIC
 	printk(KERN_INFO
 		"Enabling APIC mode:  Flat.  Using %d I/O APICs\n",
@@ -103,7 +128,7 @@
 	.init_apic_ldr			= default_init_apic_ldr,
 
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
-	.setup_apic_routing		= default_setup_apic_routing,
+	.setup_apic_routing		= setup_apic_flat_routing,
 	.multi_timer_check		= NULL,
 	.apicid_to_node			= default_apicid_to_node,
 	.cpu_to_logical_apicid		= default_cpu_to_logical_apicid,
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/apic-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/apic-xen.c
@@ -0,0 +1,70 @@
+/*
+ *	Local APIC handling stubs
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/smp.h>
+#include <asm/proto.h>
+#include <asm/apic.h>
+
+unsigned int num_processors;
+
+/*
+ * Map cpu index to physical APIC ID
+ */
+DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
+EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+
+/*
+ * Debug level, exported for io_apic.c
+ */
+unsigned int apic_verbosity;
+
+/* Have we found an MP table */
+int smp_found_config;
+
+static int __init apic_set_verbosity(char *arg)
+{
+	if (!arg)  {
+#ifdef CONFIG_X86_64
+		skip_ioapic_setup = 0;
+		return 0;
+#endif
+		return -EINVAL;
+	}
+
+	if (strcmp("debug", arg) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", arg) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	else {
+		pr_warning("APIC Verbosity level %s not recognised"
+			" use apic=verbose or apic=debug\n", arg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+early_param("apic", apic_set_verbosity);
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+int __init APIC_init_uniprocessor(void)
+{
+#ifdef CONFIG_X86_IO_APIC
+	if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
+		setup_IO_APIC();
+# ifdef CONFIG_X86_64
+	else
+		nr_ioapics = 0;
+# endif
+#endif
+
+	return 0;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/nmi.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/nmi.c
@@ -27,7 +27,11 @@
 #include <linux/kdebug.h>
 #include <linux/smp.h>
 
+#ifdef ARCH_HAS_NMI_WATCHDOG
 #include <asm/i8259.h>
+#else
+#include <asm/nmi.h>
+#endif
 #include <asm/io_apic.h>
 #include <asm/proto.h>
 #include <asm/timer.h>
@@ -37,6 +41,9 @@
 #include <asm/mach_traps.h>
 
 int unknown_nmi_panic;
+
+#ifdef ARCH_HAS_NMI_WATCHDOG
+
 int nmi_watchdog_enabled;
 
 static cpumask_t backtrace_mask __read_mostly;
@@ -468,8 +475,11 @@
 	return rc;
 }
 
+#endif /* ARCH_HAS_NMI_WATCHDOG */
+
 #ifdef CONFIG_SYSCTL
 
+#ifdef ARCH_HAS_NMI_WATCHDOG
 static void enable_ioapic_nmi_watchdog_single(void *unused)
 {
 	__get_cpu_var(wd_enabled) = 1;
@@ -487,6 +497,7 @@
 {
 	on_each_cpu(stop_apic_nmi_watchdog, NULL, 1);
 }
+#endif
 
 static int __init setup_unknown_nmi_panic(char *str)
 {
@@ -505,6 +516,7 @@
 	return 0;
 }
 
+#ifdef ARCH_HAS_NMI_WATCHDOG
 /*
  * proc handler for /proc/sys/kernel/nmi
  */
@@ -542,6 +554,7 @@
 	}
 	return 0;
 }
+#endif
 
 #endif /* CONFIG_SYSCTL */
 
@@ -554,6 +567,7 @@
 	return 0;
 }
 
+#ifdef ARCH_HAS_NMI_WATCHDOG
 void arch_trigger_all_cpu_backtrace(void)
 {
 	int i;
@@ -570,3 +584,4 @@
 		mdelay(1);
 	}
 }
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/probe_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/probe_32-xen.c
@@ -0,0 +1,58 @@
+/*
+ * Default generic APIC driver. This handles up to 8 CPUs.
+ *
+ * Copyright 2003 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic x86 APIC driver probe layer.
+ */
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
+#include <asm/apicdef.h>
+#include <asm/apic.h>
+#include <asm/setup.h>
+
+#include <linux/smp.h>
+#include <asm/ipi.h>
+
+#include <linux/interrupt.h>
+#include <asm/acpi.h>
+#include <asm/e820.h>
+
+static int xen_phys_pkg_id(int cpuid_apic, int index_msb)
+{
+	return cpuid_apic;
+}
+
+static struct apic apic_xen = {
+
+	.name				= "default",
+
+	.irq_delivery_mode		= dest_LowestPrio,
+	/* logical delivery broadcast to all CPUs: */
+	.irq_dest_mode			= 1,
+
+	.target_cpus			= default_target_cpus,
+
+	.phys_pkg_id			= xen_phys_pkg_id,
+	.mps_oem_check			= NULL,
+
+#ifdef CONFIG_SMP
+	.send_IPI_mask			= xen_send_IPI_mask,
+	.send_IPI_mask_allbutself	= xen_send_IPI_mask_allbutself,
+	.send_IPI_allbutself		= xen_send_IPI_allbutself,
+	.send_IPI_all			= xen_send_IPI_all,
+	.send_IPI_self			= xen_send_IPI_self,
+#endif
+};
+
+struct apic *apic = &apic_xen;
+EXPORT_SYMBOL_GPL(apic);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/probe_64.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/probe_64.c
@@ -67,17 +67,8 @@
 	}
 #endif
 
-	if (apic == &apic_flat) {
-		switch (boot_cpu_data.x86_vendor) {
-		case X86_VENDOR_INTEL:
-			if (num_processors > 8)
-				apic = &apic_physflat;
-			break;
-		case X86_VENDOR_AMD:
-			if (max_physical_apicid >= 8)
-				apic = &apic_physflat;
-		}
-	}
+	if (apic == &apic_flat && num_possible_cpus() > 8)
+		apic = &apic_physflat;
 
 	printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
 
@@ -85,13 +76,6 @@
 		/* need to update phys_pkg_id */
 		apic->phys_pkg_id = apicid_phys_pkg_id;
 	}
-
-	/*
-	 * Now that apic routing model is selected, configure the
-	 * fault handling for intr remapping.
-	 */
-	if (intr_remapping_enabled)
-		enable_drhd_fault_handling();
 }
 
 /* Same for both flat and physical. */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux-ec2-2.6.32/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -364,13 +364,13 @@
 
 enum map_type {map_wb, map_uc};
 
-static __init void map_high(char *id, unsigned long base, int shift,
-			    int max_pnode, enum map_type map_type)
+static __init void map_high(char *id, unsigned long base, int pshift,
+			int bshift, int max_pnode, enum map_type map_type)
 {
 	unsigned long bytes, paddr;
 
-	paddr = base << shift;
-	bytes = (1UL << shift) * (max_pnode + 1);
+	paddr = base << pshift;
+	bytes = (1UL << bshift) * (max_pnode + 1);
 	printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr,
 						paddr + bytes);
 	if (map_type == map_uc)
@@ -386,7 +386,7 @@
 
 	gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
 	if (gru.s.enable)
-		map_high("GRU", gru.s.base, shift, max_pnode, map_wb);
+		map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
 }
 
 static __init void map_mmr_high(int max_pnode)
@@ -396,7 +396,7 @@
 
 	mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR);
 	if (mmr.s.enable)
-		map_high("MMR", mmr.s.base, shift, max_pnode, map_uc);
+		map_high("MMR", mmr.s.base, shift, shift, max_pnode, map_uc);
 }
 
 static __init void map_mmioh_high(int max_pnode)
@@ -406,7 +406,8 @@
 
 	mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR);
 	if (mmioh.s.enable)
-		map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc);
+		map_high("MMIOH", mmioh.s.base, shift, mmioh.s.m_io,
+			max_pnode, map_uc);
 }
 
 static __init void uv_rtc_init(void)
@@ -594,9 +595,11 @@
 		for (j = 0; j < 64; j++) {
 			if (!test_bit(j, &present))
 				continue;
-			uv_blade_info[blade].pnode = (i * 64 + j);
+			pnode = (i * 64 + j);
+			uv_blade_info[blade].pnode = pnode;
 			uv_blade_info[blade].nr_possible_cpus = 0;
 			uv_blade_info[blade].nr_online_cpus = 0;
+			max_pnode = max(pnode, max_pnode);
 			blade++;
 		}
 	}
@@ -607,8 +610,10 @@
 	uv_rtc_init();
 
 	for_each_present_cpu(cpu) {
+		int apicid = per_cpu(x86_cpu_to_apicid, cpu);
+
 		nid = cpu_to_node(cpu);
-		pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu));
+		pnode = uv_apicid_to_pnode(apicid);
 		blade = boot_pnode_to_blade(pnode);
 		lcpu = uv_blade_info[blade].nr_possible_cpus;
 		uv_blade_info[blade].nr_possible_cpus++;
@@ -629,15 +634,9 @@
 		uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
 		uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
 		uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;
-		uv_cpu_hub_info(cpu)->scir.offset = SCIR_LOCAL_MMR_BASE + lcpu;
+		uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid);
 		uv_node_to_blade[nid] = blade;
 		uv_cpu_to_blade[cpu] = blade;
-		max_pnode = max(pnode, max_pnode);
-
-		printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, "
-			"lcpu %d, blade %d\n",
-			cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid,
-			lcpu, blade);
 	}
 
 	/* Add blade/pnode info for nodes without cpus */
@@ -649,7 +648,6 @@
 		pnode = (paddr >> m_val) & pnode_mask;
 		blade = boot_pnode_to_blade(pnode);
 		uv_node_to_blade[nid] = blade;
-		max_pnode = max(pnode, max_pnode);
 	}
 
 	map_gru_high(max_pnode);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/sleep-xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/sleep-xen.c
@@ -0,0 +1,180 @@
+/*
+ * sleep.c - x86-specific ACPI sleep support.
+ *
+ *  Copyright (C) 2001-2003 Patrick Mochel
+ *  Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
+ */
+
+#include <linux/acpi.h>
+#include <linux/bootmem.h>
+#include <linux/dmi.h>
+#include <linux/cpumask.h>
+#include <asm/segment.h>
+#include <asm/desc.h>
+
+#include "realmode/wakeup.h"
+#include "sleep.h"
+
+#ifndef CONFIG_ACPI_PV_SLEEP
+unsigned long acpi_wakeup_address;
+unsigned long acpi_realmode_flags;
+
+/* address in low memory of the wakeup routine. */
+static unsigned long acpi_realmode;
+
+#if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
+static char temp_stack[4096];
+#endif
+#endif
+
+/**
+ * acpi_save_state_mem - save kernel state
+ *
+ * Create an identity mapped page table and copy the wakeup routine to
+ * low memory.
+ *
+ * Note that this is too late to change acpi_wakeup_address.
+ */
+int acpi_save_state_mem(void)
+{
+#ifndef CONFIG_ACPI_PV_SLEEP
+	struct wakeup_header *header;
+
+	if (!acpi_realmode) {
+		printk(KERN_ERR "Could not allocate memory during boot, "
+		       "S3 disabled\n");
+		return -ENOMEM;
+	}
+	memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
+
+	header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
+	if (header->signature != 0x51ee1111) {
+		printk(KERN_ERR "wakeup header does not match\n");
+		return -EINVAL;
+	}
+
+	header->video_mode = saved_video_mode;
+
+	header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
+
+	/*
+	 * Set up the wakeup GDT.  We set these up as Big Real Mode,
+	 * that is, with limits set to 4 GB.  At least the Lenovo
+	 * Thinkpad X61 is known to need this for the video BIOS
+	 * initialization quirk to work; this is likely to also
+	 * be the case for other laptops or integrated video devices.
+	 */
+
+	/* GDT[0]: GDT self-pointer */
+	header->wakeup_gdt[0] =
+		(u64)(sizeof(header->wakeup_gdt) - 1) +
+		((u64)(acpi_wakeup_address +
+			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
+				<< 16);
+	/* GDT[1]: big real mode-like code segment */
+	header->wakeup_gdt[1] =
+		GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
+	/* GDT[2]: big real mode-like data segment */
+	header->wakeup_gdt[2] =
+		GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
+
+#ifndef CONFIG_64BIT
+	store_gdt((struct desc_ptr *)&header->pmode_gdt);
+
+	header->pmode_efer_low = nx_enabled;
+	if (header->pmode_efer_low & 1) {
+		/* This is strange, why not save efer, always? */
+		rdmsr(MSR_EFER, header->pmode_efer_low,
+			header->pmode_efer_high);
+	}
+#endif /* !CONFIG_64BIT */
+
+	header->pmode_cr0 = read_cr0();
+	header->pmode_cr4 = read_cr4_safe();
+	header->realmode_flags = acpi_realmode_flags;
+	header->real_magic = 0x12345678;
+
+#ifndef CONFIG_64BIT
+	header->pmode_entry = (u32)&wakeup_pmode_return;
+	header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
+	saved_magic = 0x12345678;
+#else /* CONFIG_64BIT */
+	header->trampoline_segment = setup_trampoline() >> 4;
+#ifdef CONFIG_SMP
+	stack_start.sp = temp_stack + sizeof(temp_stack);
+	early_gdt_descr.address =
+			(unsigned long)get_cpu_gdt_table(smp_processor_id());
+	initial_gs = per_cpu_offset(smp_processor_id());
+#endif
+	initial_code = (unsigned long)wakeup_long64;
+       saved_magic = 0x123456789abcdef0L;
+#endif /* CONFIG_64BIT */
+#endif
+
+	return 0;
+}
+
+/*
+ * acpi_restore_state - undo effects of acpi_save_state_mem
+ */
+void acpi_restore_state_mem(void)
+{
+}
+
+
+/**
+ * acpi_reserve_bootmem - do _very_ early ACPI initialisation
+ *
+ * We allocate a page from the first 1MB of memory for the wakeup
+ * routine for when we come back from a sleep state. The
+ * runtime allocator allows specification of <16MB pages, but not
+ * <1MB pages.
+ */
+void __init acpi_reserve_bootmem(void)
+{
+#ifndef CONFIG_ACPI_PV_SLEEP
+	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
+		printk(KERN_ERR
+		       "ACPI: Wakeup code way too big, S3 disabled.\n");
+		return;
+	}
+
+	acpi_realmode = (unsigned long)alloc_bootmem_low(WAKEUP_SIZE);
+
+	if (!acpi_realmode) {
+		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
+		return;
+	}
+
+	acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
+#endif
+}
+
+
+#ifndef CONFIG_ACPI_PV_SLEEP
+static int __init acpi_sleep_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "s3_bios", 7) == 0)
+			acpi_realmode_flags |= 1;
+		if (strncmp(str, "s3_mode", 7) == 0)
+			acpi_realmode_flags |= 2;
+		if (strncmp(str, "s3_beep", 7) == 0)
+			acpi_realmode_flags |= 4;
+#ifdef CONFIG_HIBERNATION
+		if (strncmp(str, "s4_nohwsig", 10) == 0)
+			acpi_no_s4_hw_signature();
+		if (strncmp(str, "s4_nonvs", 8) == 0)
+			acpi_s4_no_nvs();
+#endif
+		if (strncmp(str, "old_ordering", 12) == 0)
+			acpi_old_suspend_ordering();
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("acpi_sleep=", acpi_sleep_setup);
+#endif /* CONFIG_ACPI_PV_SLEEP */
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/processor.c
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/processor.c
@@ -76,7 +76,18 @@
 /* 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.
+	 */
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+#else
 	struct cpuinfo_x86 *c = &cpu_data(pr->id);
+#endif
 
 	pr->pdc = NULL;
 	if (c->x86_vendor == X86_VENDOR_INTEL ||
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/Makefile
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/Makefile
@@ -5,6 +5,9 @@
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
 obj-y				+= cstate.o processor.o
+ifneq ($(CONFIG_PROCESSOR_EXTERNAL_CONTROL),)
+obj-$(CONFIG_XEN)		+= processor_extcntl_xen.o
+endif
 endif
 
 $(obj)/wakeup_rm.o:    $(obj)/realmode/wakeup.bin
@@ -12,3 +15,4 @@
 $(obj)/realmode/wakeup.bin: FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/realmode
 
+disabled-obj-$(CONFIG_XEN)	:= cstate.o wakeup_%.o
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/processor_extcntl_xen.c
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/processor_extcntl_xen.c
@@ -0,0 +1,217 @@
+/*
+ * 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_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;
+
+	/* 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.access_size;
+		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.u.power.count = count;
+	op.u.set_pminfo.u.power.flags.bm_control = pr->flags.bm_control;
+	op.u.set_pminfo.u.power.flags.bm_check = pr->flags.bm_check;
+	op.u.set_pminfo.u.power.flags.has_cst = pr->flags.has_cst;
+	op.u.set_pminfo.u.power.flags.power_setup_done = pr->flags.power_setup_done;
+
+	set_xen_guest_handle(op.u.set_pminfo.u.power.states, buf);
+	ret = HYPERVISOR_platform_op(&op);
+	kfree(buf);
+	return ret;
+}
+
+static int xen_px_notifier(struct acpi_processor *pr, int action)
+{
+	int ret = -EINVAL;
+	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;
+
+	if (!pr)
+		return -EINVAL;
+
+	perf = &op.u.set_pminfo.u.perf;
+	px = pr->performance;
+
+	switch(action) {
+	case PROCESSOR_PM_CHANGE:
+		/* ppc dynamic handle */
+		perf->flags = XEN_PX_PPC;
+		perf->platform_limit = pr->performance_platform_limit;
+
+		ret = HYPERVISOR_platform_op(&op);
+		break;
+
+	case PROCESSOR_PM_INIT:
+		/* px normal init */
+		perf->flags = XEN_PX_PPC | 
+			      XEN_PX_PCT | 
+			      XEN_PX_PSS | 
+			      XEN_PX_PSD;
+
+		/* ppc */
+		perf->platform_limit = pr->performance_platform_limit;
+
+		/* pct */
+		xen_convert_pct_reg(&perf->control_register, &px->control_register);
+		xen_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;
+		xen_convert_pss_states(states, px->states, px->state_count);
+		set_xen_guest_handle(perf->states, states);
+
+		/* psd */
+		pdomain = &px->domain_info;
+		xen_convert_psd_pack(&perf->domain_info, pdomain);
+		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 {
+			ret = -ENODEV;
+			kfree(states);
+			break;
+		}
+
+		ret = HYPERVISOR_platform_op(&op);
+		kfree(states);
+		break;
+
+	default:
+		break;
+	}
+
+	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)
+{
+	unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8;
+
+	if (!pmbits)
+		return;
+	if (pmbits & XEN_PROCESSOR_PM_CX)
+		xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier;
+	if (pmbits & XEN_PROCESSOR_PM_PX)
+		xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier;
+	if (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);
+
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+	xen_platform_op_t op = {
+		.cmd			= XENPF_get_cpu_freq,
+		.interface_version	= XENPF_INTERFACE_VERSION,
+		.u.get_cpu_freq.vcpu	= cpu
+	};
+
+	return HYPERVISOR_platform_op(&op) == 0 ? op.u.get_cpu_freq.freq : 0;
+}
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/cstate.c
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/cstate.c
@@ -48,7 +48,7 @@
 	 * P4, Core and beyond CPUs
 	 */
 	if (c->x86_vendor == X86_VENDOR_INTEL &&
-	    (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 14)))
+	    (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
 			flags->bm_control = 0;
 }
 EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
@@ -145,6 +145,15 @@
 		percpu_entry->states[cx->index].eax = cx->address;
 		percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
 	}
+
+	/*
+	 * For _CST FFH on Intel, if GAS.access_size bit 1 is cleared,
+	 * then we should skip checking BM_STS for this C-state.
+	 * ref: "Intel Processor Vendor-Specific ACPI Interface Specification"
+	 */
+	if ((c->x86_vendor == X86_VENDOR_INTEL) && !(reg->access_size & 0x2))
+		cx->bm_sts_skip = 1;
+
 	return retval;
 }
 EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
--- linux-ec2-2.6.32.orig/arch/x86/kernel/acpi/boot.c
+++ linux-ec2-2.6.32/arch/x86/kernel/acpi/boot.c
@@ -68,12 +68,18 @@
 
 u8 acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
+#ifndef CONFIG_XEN
 int acpi_skip_timer_override __initdata;
 int acpi_use_timer_override __initdata;
+int acpi_fix_pin2_polarity __initdata;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
+#else
+#define acpi_skip_timer_override 0
+#define acpi_fix_pin2_polarity 0
+#endif
 
 #ifndef __HAVE_ARCH_CMPXCHG
 #warning ACPI uses CMPXCHG, i486 and later hardware
@@ -132,6 +138,7 @@
 		return -ENODEV;
 	}
 
+#ifndef CONFIG_XEN
 	if (madt->address) {
 		acpi_lapic_addr = (u64) madt->address;
 
@@ -141,12 +148,14 @@
 
 	default_acpi_madt_oem_check(madt->header.oem_id,
 				    madt->header.oem_table_id);
+#endif
 
 	return 0;
 }
 
 static void __cpuinit acpi_register_lapic(int id, u8 enabled)
 {
+#ifndef CONFIG_XEN
 	unsigned int ver = 0;
 
 	if (!enabled) {
@@ -158,6 +167,7 @@
 		ver = apic_version[boot_cpu_physical_apicid];
 
 	generic_processor_info(id, ver);
+#endif
 }
 
 static int __init
@@ -236,6 +246,7 @@
 acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
 			  const unsigned long end)
 {
+#ifndef CONFIG_XEN
 	struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
 
 	lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
@@ -244,6 +255,7 @@
 		return -EINVAL;
 
 	acpi_lapic_addr = lapic_addr_ovr->address;
+#endif
 
 	return 0;
 }
@@ -360,10 +372,15 @@
 		return 0;
 	}
 
-	if (acpi_skip_timer_override &&
-	    intsrc->source_irq == 0 && intsrc->global_irq == 2) {
-		printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
-		return 0;
+	if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
+		if (acpi_skip_timer_override) {
+			printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+			return 0;
+		}
+		if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
+			intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
+			printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
+		}
 	}
 
 	mp_override_legacy_irq(intsrc->source_irq,
@@ -446,6 +463,12 @@
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
 	*irq = gsi;
+
+#ifdef CONFIG_X86_IO_APIC
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		setup_IO_APIC_irq_extra(gsi);
+#endif
+
 	return 0;
 }
 
@@ -473,7 +496,8 @@
 		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
 	}
 #endif
-	acpi_gsi_to_irq(plat_gsi, &irq);
+	irq = plat_gsi;
+
 	return irq;
 }
 
@@ -731,6 +755,7 @@
  * returns 0 on success, < 0 on error
  */
 
+#ifndef CONFIG_XEN
 static void __init acpi_register_lapic_address(unsigned long address)
 {
 	mp_lapic_addr = address;
@@ -742,6 +767,9 @@
 			 GET_APIC_VERSION(apic_read(APIC_LVR));
 	}
 }
+#else
+#define acpi_register_lapic_address(address)
+#endif
 
 static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
 {
@@ -1042,7 +1070,7 @@
 
 	ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
 
-#ifdef CONFIG_X86_32
+#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN)
 	if (ioapic_renumber_irq)
 		gsi = ioapic_renumber_irq(ioapic, gsi);
 #endif
@@ -1184,9 +1212,6 @@
 		if (!error) {
 			acpi_lapic = 1;
 
-#ifdef CONFIG_X86_BIGSMP
-			generic_bigsmp_probe();
-#endif
 			/*
 			 * Parse MADT IO-APIC entries
 			 */
@@ -1196,8 +1221,6 @@
 				acpi_ioapic = 1;
 
 				smp_found_config = 1;
-				if (apic->setup_apic_routing)
-					apic->setup_apic_routing();
 			}
 		}
 		if (error == -EINVAL) {
@@ -1284,6 +1307,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_XEN
 /*
  * Force ignoring BIOS IRQ0 pin2 override
  */
@@ -1301,6 +1325,7 @@
 	}
 	return 0;
 }
+#endif
 
 /*
  * If your system is blacklisted here, but you find that acpi=force
@@ -1348,14 +1373,6 @@
 	 },
 	{
 	 .callback = force_acpi_ht,
-	 .ident = "ASUS P2B-DS",
-	 .matches = {
-		     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-		     DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
-		     },
-	 },
-	{
-	 .callback = force_acpi_ht,
 	 .ident = "ASUS CUR-DLS",
 	 .matches = {
 		     DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
@@ -1464,6 +1481,7 @@
 	{}
 };
 
+#ifndef CONFIG_XEN
 /* second table for DMI checks that should run after early-quirks */
 static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
 	/*
@@ -1510,6 +1528,7 @@
 	 },
 	{}
 };
+#endif
 
 /*
  * acpi_boot_table_init() and acpi_boot_init()
@@ -1594,8 +1613,10 @@
 
 int __init acpi_boot_init(void)
 {
+#ifndef CONFIG_XEN
 	/* those are executed after early-quirks are executed */
 	dmi_check_system(acpi_dmi_table_late);
+#endif
 
 	/*
 	 * If acpi_disabled, bail out
@@ -1684,7 +1705,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_X86_IO_APIC
+#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_XEN)
 static int __init parse_acpi_skip_timer_override(char *arg)
 {
 	acpi_skip_timer_override = 1;
--- linux-ec2-2.6.32.orig/arch/x86/power/Makefile
+++ linux-ec2-2.6.32/arch/x86/power/Makefile
@@ -5,3 +5,5 @@
 
 obj-$(CONFIG_PM_SLEEP)		+= cpu.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate_$(BITS).o hibernate_asm_$(BITS).o
+
+disabled-obj-$(CONFIG_XEN)	:= cpu.o
--- linux-ec2-2.6.32.orig/arch/x86/power/hibernate_asm_32.S
+++ linux-ec2-2.6.32/arch/x86/power/hibernate_asm_32.S
@@ -27,10 +27,17 @@
 	ret
 
 ENTRY(restore_image)
+	movl	mmu_cr4_features, %ecx
 	movl	resume_pg_dir, %eax
 	subl	$__PAGE_OFFSET, %eax
 	movl	%eax, %cr3
 
+	jecxz	1f	# cr4 Pentium and higher, skip if zero
+	andl	$~(X86_CR4_PGE), %ecx
+	movl	%ecx, %cr4;  # turn off PGE
+	movl	%cr3, %eax;  # flush TLB
+	movl	%eax, %cr3
+1:
 	movl	restore_pblist, %edx
 	.p2align 4,,7
 
@@ -54,16 +61,8 @@
 	movl	$swapper_pg_dir, %eax
 	subl	$__PAGE_OFFSET, %eax
 	movl	%eax, %cr3
-	/* Flush TLB, including "global" things (vmalloc) */
 	movl	mmu_cr4_features, %ecx
 	jecxz	1f	# cr4 Pentium and higher, skip if zero
-	movl	%ecx, %edx
-	andl	$~(X86_CR4_PGE), %edx
-	movl	%edx, %cr4;  # turn off PGE
-1:
-	movl	%cr3, %eax;  # flush TLB
-	movl	%eax, %cr3
-	jecxz	1f	# cr4 Pentium and higher, skip if zero
 	movl	%ecx, %cr4;  # turn PGE back on
 1:
 
--- linux-ec2-2.6.32.orig/arch/x86/power/cpu.c
+++ linux-ec2-2.6.32/arch/x86/power/cpu.c
@@ -104,12 +104,15 @@
 	ctxt->cr4 = read_cr4();
 	ctxt->cr8 = read_cr8();
 #endif
+	ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE,
+					       &ctxt->misc_enable);
 }
 
 /* Needed by apm.c */
 void save_processor_state(void)
 {
 	__save_processor_state(&saved_context);
+	save_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(save_processor_state);
@@ -176,6 +179,8 @@
  */
 static void __restore_processor_state(struct saved_context *ctxt)
 {
+	if (ctxt->misc_enable_saved)
+		wrmsrl(MSR_IA32_MISC_ENABLE, ctxt->misc_enable);
 	/*
 	 * control registers
 	 */
@@ -249,6 +254,7 @@
 void restore_processor_state(void)
 {
 	__restore_processor_state(&saved_context);
+	restore_sched_clock_state();
 }
 #ifdef CONFIG_X86_32
 EXPORT_SYMBOL(restore_processor_state);
--- linux-ec2-2.6.32.orig/arch/x86/lib/rwsem_64.S
+++ linux-ec2-2.6.32/arch/x86/lib/rwsem_64.S
@@ -0,0 +1,81 @@
+/*
+ * x86-64 rwsem wrappers
+ *
+ * This interfaces the inline asm code to the slow-path
+ * C routines. We need to save the call-clobbered regs
+ * that the asm does not mark as clobbered, and move the
+ * argument from %rax to %rdi.
+ *
+ * NOTE! We don't need to save %rax, because the functions
+ * will always return the semaphore pointer in %rax (which
+ * is also the input argument to these helpers)
+ *
+ * The following can clobber %rdx because the asm clobbers it:
+ *   call_rwsem_down_write_failed
+ *   call_rwsem_wake
+ * but %rdi, %rsi, %rcx, %r8-r11 always need saving.
+ */
+
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+#define save_common_regs \
+	pushq %rdi; \
+	pushq %rsi; \
+	pushq %rcx; \
+	pushq %r8; \
+	pushq %r9; \
+	pushq %r10; \
+	pushq %r11
+
+#define restore_common_regs \
+	popq %r11; \
+	popq %r10; \
+	popq %r9; \
+	popq %r8; \
+	popq %rcx; \
+	popq %rsi; \
+	popq %rdi
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_down_read_failed)
+	save_common_regs
+	pushq %rdx
+	movq %rax,%rdi
+	call rwsem_down_read_failed
+	popq %rdx
+	restore_common_regs
+	ret
+	ENDPROC(call_rwsem_down_read_failed)
+
+ENTRY(call_rwsem_down_write_failed)
+	save_common_regs
+	movq %rax,%rdi
+	call rwsem_down_write_failed
+	restore_common_regs
+	ret
+	ENDPROC(call_rwsem_down_write_failed)
+
+ENTRY(call_rwsem_wake)
+	decw %dx    /* do nothing if still outstanding active readers */
+	jnz 1f
+	save_common_regs
+	movq %rax,%rdi
+	call rwsem_wake
+	restore_common_regs
+1:	ret
+	ENDPROC(call_rwsem_wake)
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_downgrade_wake)
+	save_common_regs
+	pushq %rdx
+	movq %rax,%rdi
+	call rwsem_downgrade_wake
+	popq %rdx
+	restore_common_regs
+	ret
+	ENDPROC(call_rwsem_downgrade_wake)
--- linux-ec2-2.6.32.orig/arch/x86/lib/msr.c
+++ linux-ec2-2.6.32/arch/x86/lib/msr.c
@@ -1,226 +1,23 @@
 #include <linux/module.h>
 #include <linux/preempt.h>
-#include <linux/smp.h>
 #include <asm/msr.h>
 
-struct msr_info {
-	u32 msr_no;
-	struct msr reg;
-	struct msr *msrs;
-	int off;
-	int err;
-};
-
-static void __rdmsr_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-	struct msr *reg;
-	int this_cpu = raw_smp_processor_id();
-
-	if (rv->msrs)
-		reg = &rv->msrs[this_cpu - rv->off];
-	else
-		reg = &rv->reg;
-
-	rdmsr(rv->msr_no, reg->l, reg->h);
-}
-
-static void __wrmsr_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-	struct msr *reg;
-	int this_cpu = raw_smp_processor_id();
-
-	if (rv->msrs)
-		reg = &rv->msrs[this_cpu - rv->off];
-	else
-		reg = &rv->reg;
-
-	wrmsr(rv->msr_no, reg->l, reg->h);
-}
-
-int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
-{
-	int err;
-	struct msr_info rv;
-
-	memset(&rv, 0, sizeof(rv));
-
-	rv.msr_no = msr_no;
-	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
-	*l = rv.reg.l;
-	*h = rv.reg.h;
-
-	return err;
-}
-EXPORT_SYMBOL(rdmsr_on_cpu);
-
-int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
-{
-	int err;
-	struct msr_info rv;
-
-	memset(&rv, 0, sizeof(rv));
-
-	rv.msr_no = msr_no;
-	rv.reg.l = l;
-	rv.reg.h = h;
-	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
-
-	return err;
-}
-EXPORT_SYMBOL(wrmsr_on_cpu);
-
-/* rdmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
-{
-	struct msr_info rv;
-	int this_cpu;
-
-	memset(&rv, 0, sizeof(rv));
-
-	rv.off    = cpumask_first(mask);
-	rv.msrs	  = msrs;
-	rv.msr_no = msr_no;
-
-	this_cpu = get_cpu();
-
-	if (cpumask_test_cpu(this_cpu, mask))
-		__rdmsr_on_cpu(&rv);
-
-	smp_call_function_many(mask, __rdmsr_on_cpu, &rv, 1);
-	put_cpu();
-}
-EXPORT_SYMBOL(rdmsr_on_cpus);
-
-/*
- * wrmsr on a bunch of CPUs
- *
- * @mask:       which CPUs
- * @msr_no:     which MSR
- * @msrs:       array of MSR values
- *
- */
-void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
-{
-	struct msr_info rv;
-	int this_cpu;
-
-	memset(&rv, 0, sizeof(rv));
-
-	rv.off    = cpumask_first(mask);
-	rv.msrs   = msrs;
-	rv.msr_no = msr_no;
-
-	this_cpu = get_cpu();
-
-	if (cpumask_test_cpu(this_cpu, mask))
-		__wrmsr_on_cpu(&rv);
-
-	smp_call_function_many(mask, __wrmsr_on_cpu, &rv, 1);
-	put_cpu();
-}
-EXPORT_SYMBOL(wrmsr_on_cpus);
-
-/* These "safe" variants are slower and should be used when the target MSR
-   may not actually exist. */
-static void __rdmsr_safe_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
-}
-
-static void __wrmsr_safe_on_cpu(void *info)
-{
-	struct msr_info *rv = info;
-
-	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
-}
-
-int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+struct msr *msrs_alloc(void)
 {
-	int err;
-	struct msr_info rv;
+	struct msr *msrs = NULL;
 
-	memset(&rv, 0, sizeof(rv));
+	msrs = alloc_percpu(struct msr);
+	if (!msrs) {
+		pr_warning("%s: error allocating msrs\n", __func__);
+		return NULL;
+	}
 
-	rv.msr_no = msr_no;
-	err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
-	*l = rv.reg.l;
-	*h = rv.reg.h;
-
-	return err ? err : rv.err;
+	return msrs;
 }
-EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+EXPORT_SYMBOL(msrs_alloc);
 
-int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+void msrs_free(struct msr *msrs)
 {
-	int err;
-	struct msr_info rv;
-
-	memset(&rv, 0, sizeof(rv));
-
-	rv.msr_no = msr_no;
-	rv.reg.l = l;
-	rv.reg.h = h;
-	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
-
-	return err ? err : rv.err;
-}
-EXPORT_SYMBOL(wrmsr_safe_on_cpu);
-
-/*
- * These variants are significantly slower, but allows control over
- * the entire 32-bit GPR set.
- */
-struct msr_regs_info {
-	u32 *regs;
-	int err;
-};
-
-static void __rdmsr_safe_regs_on_cpu(void *info)
-{
-	struct msr_regs_info *rv = info;
-
-	rv->err = rdmsr_safe_regs(rv->regs);
-}
-
-static void __wrmsr_safe_regs_on_cpu(void *info)
-{
-	struct msr_regs_info *rv = info;
-
-	rv->err = wrmsr_safe_regs(rv->regs);
-}
-
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-	int err;
-	struct msr_regs_info rv;
-
-	rv.regs   = regs;
-	rv.err    = -EIO;
-	err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
-
-	return err ? err : rv.err;
-}
-EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
-
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
-{
-	int err;
-	struct msr_regs_info rv;
-
-	rv.regs = regs;
-	rv.err  = -EIO;
-	err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
-
-	return err ? err : rv.err;
+	free_percpu(msrs);
 }
-EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
+EXPORT_SYMBOL(msrs_free);
--- linux-ec2-2.6.32.orig/arch/x86/lib/scrub.c
+++ linux-ec2-2.6.32/arch/x86/lib/scrub.c
@@ -0,0 +1,21 @@
+#include <asm/cpufeature.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+void scrub_pages(void *v, unsigned int count)
+{
+	if (likely(cpu_has_xmm2)) {
+		unsigned long n = count * (PAGE_SIZE / sizeof(long) / 4);
+
+		for (; n--; v += sizeof(long) * 4)
+			asm("movnti %1,(%0)\n\t"
+			    "movnti %1,%c2(%0)\n\t"
+			    "movnti %1,2*%c2(%0)\n\t"
+			    "movnti %1,3*%c2(%0)\n\t"
+			    : : "r" (v), "r" (0L), "i" (sizeof(long))
+			    : "memory");
+		asm volatile("sfence" : : : "memory");
+	} else
+		for (; count--; v += PAGE_SIZE)
+			clear_page(v);
+}
--- linux-ec2-2.6.32.orig/arch/x86/lib/Makefile
+++ linux-ec2-2.6.32/arch/x86/lib/Makefile
@@ -2,14 +2,15 @@
 # Makefile for x86 specific library files.
 #
 
-obj-$(CONFIG_SMP) := msr.o
+obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
+obj-$(CONFIG_XEN) += cache-smp.o
 
 lib-y := delay.o
 lib-y += thunk_$(BITS).o
 lib-y += usercopy_$(BITS).o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
 
-obj-y += msr-reg.o msr-reg-export.o
+obj-y += msr.o msr-reg.o msr-reg-export.o
 
 ifeq ($(CONFIG_X86_32),y)
         obj-y += atomic64_32.o
@@ -26,4 +27,7 @@
         lib-y += thunk_64.o clear_page_64.o copy_page_64.o
         lib-y += memmove_64.o memset_64.o
         lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
+	lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o
 endif
+
+lib-$(CONFIG_XEN_SCRUB_PAGES) += scrub.o
--- linux-ec2-2.6.32.orig/arch/x86/lib/cache-smp.c
+++ linux-ec2-2.6.32/arch/x86/lib/cache-smp.c
@@ -0,0 +1,27 @@
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <asm/hypervisor.h>
+
+static void __wbinvd(void *dummy)
+{
+	wbinvd();
+}
+
+#ifndef CONFIG_XEN /* XXX Needs hypervisor support. */
+void wbinvd_on_cpu(int cpu)
+{
+	smp_call_function_single(cpu, __wbinvd, NULL, 1);
+}
+EXPORT_SYMBOL(wbinvd_on_cpu);
+#endif
+
+int wbinvd_on_all_cpus(void)
+{
+	struct mmuext_op op = { .cmd = MMUEXT_FLUSH_CACHE_GLOBAL };
+
+	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) == 0)
+		return 0;
+	/* Best effort as fallback. */
+	return on_each_cpu(__wbinvd, NULL, 1);
+}
+EXPORT_SYMBOL(wbinvd_on_all_cpus);
--- linux-ec2-2.6.32.orig/arch/x86/lib/semaphore_32.S
+++ linux-ec2-2.6.32/arch/x86/lib/semaphore_32.S
@@ -36,7 +36,7 @@
  */
 #ifdef CONFIG_SMP
 ENTRY(__write_lock_failed)
-	CFI_STARTPROC simple
+	CFI_STARTPROC
 	FRAME
 2: 	LOCK_PREFIX
 	addl	$ RW_LOCK_BIAS,(%eax)
--- linux-ec2-2.6.32.orig/arch/x86/lib/msr-smp.c
+++ linux-ec2-2.6.32/arch/x86/lib/msr-smp.c
@@ -0,0 +1,204 @@
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/smp.h>
+#include <asm/msr.h>
+
+static void __rdmsr_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+	struct msr *reg;
+	int this_cpu = raw_smp_processor_id();
+
+	if (rv->msrs)
+		reg = per_cpu_ptr(rv->msrs, this_cpu);
+	else
+		reg = &rv->reg;
+
+	rdmsr(rv->msr_no, reg->l, reg->h);
+}
+
+static void __wrmsr_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+	struct msr *reg;
+	int this_cpu = raw_smp_processor_id();
+
+	if (rv->msrs)
+		reg = per_cpu_ptr(rv->msrs, this_cpu);
+	else
+		reg = &rv->reg;
+
+	wrmsr(rv->msr_no, reg->l, reg->h);
+}
+
+int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+	*l = rv.reg.l;
+	*h = rv.reg.h;
+
+	return err;
+}
+EXPORT_SYMBOL(rdmsr_on_cpu);
+
+int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	rv.reg.l = l;
+	rv.reg.h = h;
+	err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+	return err;
+}
+EXPORT_SYMBOL(wrmsr_on_cpu);
+
+static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
+			    struct msr *msrs,
+			    void (*msr_func) (void *info))
+{
+	struct msr_info rv;
+	int this_cpu;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msrs	  = msrs;
+	rv.msr_no = msr_no;
+
+	this_cpu = get_cpu();
+
+	if (cpumask_test_cpu(this_cpu, mask))
+		msr_func(&rv);
+
+	smp_call_function_many(mask, msr_func, &rv, 1);
+	put_cpu();
+}
+
+/* rdmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+	__rwmsr_on_cpus(mask, msr_no, msrs, __rdmsr_on_cpu);
+}
+EXPORT_SYMBOL(rdmsr_on_cpus);
+
+/*
+ * wrmsr on a bunch of CPUs
+ *
+ * @mask:       which CPUs
+ * @msr_no:     which MSR
+ * @msrs:       array of MSR values
+ *
+ */
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
+{
+	__rwmsr_on_cpus(mask, msr_no, msrs, __wrmsr_on_cpu);
+}
+EXPORT_SYMBOL(wrmsr_on_cpus);
+
+/* These "safe" variants are slower and should be used when the target MSR
+   may not actually exist. */
+static void __rdmsr_safe_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+
+	rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h);
+}
+
+static void __wrmsr_safe_on_cpu(void *info)
+{
+	struct msr_info *rv = info;
+
+	rv->err = wrmsr_safe(rv->msr_no, rv->reg.l, rv->reg.h);
+}
+
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+	*l = rv.reg.l;
+	*h = rv.reg.h;
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_on_cpu);
+
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+{
+	int err;
+	struct msr_info rv;
+
+	memset(&rv, 0, sizeof(rv));
+
+	rv.msr_no = msr_no;
+	rv.reg.l = l;
+	rv.reg.h = h;
+	err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_on_cpu);
+
+/*
+ * These variants are significantly slower, but allows control over
+ * the entire 32-bit GPR set.
+ */
+static void __rdmsr_safe_regs_on_cpu(void *info)
+{
+	struct msr_regs_info *rv = info;
+
+	rv->err = rdmsr_safe_regs(rv->regs);
+}
+
+static void __wrmsr_safe_regs_on_cpu(void *info)
+{
+	struct msr_regs_info *rv = info;
+
+	rv->err = wrmsr_safe_regs(rv->regs);
+}
+
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+	int err;
+	struct msr_regs_info rv;
+
+	rv.regs   = regs;
+	rv.err    = -EIO;
+	err = smp_call_function_single(cpu, __rdmsr_safe_regs_on_cpu, &rv, 1);
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
+
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+{
+	int err;
+	struct msr_regs_info rv;
+
+	rv.regs = regs;
+	rv.err  = -EIO;
+	err = smp_call_function_single(cpu, __wrmsr_safe_regs_on_cpu, &rv, 1);
+
+	return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsr_safe_regs_on_cpu);
--- linux-ec2-2.6.32.orig/arch/x86/vdso/vdso32-setup.c
+++ linux-ec2-2.6.32/arch/x86/vdso/vdso32-setup.c
@@ -331,7 +331,7 @@
 	if (compat)
 		addr = VDSO_HIGH_BASE;
 	else {
-		addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+		addr = get_unmapped_area_prot(NULL, 0, PAGE_SIZE, 0, 0, 1);
 		if (IS_ERR_VALUE(addr)) {
 			ret = addr;
 			goto up_fail;
--- linux-ec2-2.6.32.orig/arch/x86/vdso/Makefile
+++ linux-ec2-2.6.32/arch/x86/vdso/Makefile
@@ -25,7 +25,7 @@
 
 export CPPFLAGS_vdso.lds += -P -C
 
-VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 		      	-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
@@ -65,11 +65,12 @@
 vdso32.so-$(VDSO32-y)		+= int80
 vdso32.so-$(CONFIG_COMPAT)	+= syscall
 vdso32.so-$(VDSO32-y)		+= sysenter
+vdso32.so-$(CONFIG_X86_XEN)	+= syscall
 
 vdso32-images			= $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
--- linux-ec2-2.6.32.orig/arch/x86/vdso/vdso32.S
+++ linux-ec2-2.6.32/arch/x86/vdso/vdso32.S
@@ -9,7 +9,7 @@
 
 	.globl vdso32_syscall_start, vdso32_syscall_end
 vdso32_syscall_start:
-#ifdef CONFIG_COMPAT
+#if defined(CONFIG_COMPAT) || defined(CONFIG_X86_XEN)
 	.incbin "arch/x86/vdso/vdso32-syscall.so"
 #endif
 vdso32_syscall_end:
--- linux-ec2-2.6.32.orig/arch/x86/vdso/vdso32-setup-xen.c
+++ linux-ec2-2.6.32/arch/x86/vdso/vdso32-setup-xen.c
@@ -0,0 +1,486 @@
+/*
+ * (C) Copyright 2002 Linus Torvalds
+ * Portions based on the vdso-randomization code from exec-shield:
+ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
+ *
+ * This file contains the needed initializations to support sysenter.
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/thread_info.h>
+#include <linux/sched.h>
+#include <linux/gfp.h>
+#include <linux/string.h>
+#include <linux/elf.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <asm/cpufeature.h>
+#include <asm/msr.h>
+#include <asm/pgtable.h>
+#include <asm/unistd.h>
+#include <asm/elf.h>
+#include <asm/tlbflush.h>
+#include <asm/vdso.h>
+#include <asm/proto.h>
+
+#include <xen/interface/callback.h>
+
+enum {
+	VDSO_DISABLED = 0,
+	VDSO_ENABLED = 1,
+	VDSO_COMPAT = 2,
+};
+
+#ifdef CONFIG_COMPAT_VDSO
+#define VDSO_DEFAULT	VDSO_COMPAT
+#else
+#define VDSO_DEFAULT	VDSO_ENABLED
+#endif
+
+#ifdef CONFIG_X86_64
+#define vdso_enabled			sysctl_vsyscall32
+#define arch_setup_additional_pages	syscall32_setup_pages
+#endif
+
+/*
+ * This is the difference between the prelinked addresses in the vDSO images
+ * and the VDSO_HIGH_BASE address where CONFIG_COMPAT_VDSO places the vDSO
+ * in the user address space.
+ */
+#define VDSO_ADDR_ADJUST	(VDSO_HIGH_BASE - (unsigned long)VDSO32_PRELINK)
+
+/*
+ * Should the kernel map a VDSO page into processes and pass its
+ * address down to glibc upon exec()?
+ */
+unsigned int __read_mostly vdso_enabled = VDSO_DEFAULT;
+
+static int __init vdso_setup(char *s)
+{
+	vdso_enabled = simple_strtoul(s, NULL, 0);
+
+	return 1;
+}
+
+/*
+ * For consistency, the argument vdso32=[012] affects the 32-bit vDSO
+ * behavior on both 64-bit and 32-bit kernels.
+ * On 32-bit kernels, vdso=[012] means the same thing.
+ */
+__setup("vdso32=", vdso_setup);
+
+#ifdef CONFIG_X86_32
+__setup_param("vdso=", vdso32_setup, vdso_setup, 0);
+
+EXPORT_SYMBOL_GPL(vdso_enabled);
+#endif
+
+static __init void reloc_symtab(Elf32_Ehdr *ehdr,
+				unsigned offset, unsigned size)
+{
+	Elf32_Sym *sym = (void *)ehdr + offset;
+	unsigned nsym = size / sizeof(*sym);
+	unsigned i;
+
+	for(i = 0; i < nsym; i++, sym++) {
+		if (sym->st_shndx == SHN_UNDEF ||
+		    sym->st_shndx == SHN_ABS)
+			continue;  /* skip */
+
+		if (sym->st_shndx > SHN_LORESERVE) {
+			printk(KERN_INFO "VDSO: unexpected st_shndx %x\n",
+			       sym->st_shndx);
+			continue;
+		}
+
+		switch(ELF_ST_TYPE(sym->st_info)) {
+		case STT_OBJECT:
+		case STT_FUNC:
+		case STT_SECTION:
+		case STT_FILE:
+			sym->st_value += VDSO_ADDR_ADJUST;
+		}
+	}
+}
+
+static __init void reloc_dyn(Elf32_Ehdr *ehdr, unsigned offset)
+{
+	Elf32_Dyn *dyn = (void *)ehdr + offset;
+
+	for(; dyn->d_tag != DT_NULL; dyn++)
+		switch(dyn->d_tag) {
+		case DT_PLTGOT:
+		case DT_HASH:
+		case DT_STRTAB:
+		case DT_SYMTAB:
+		case DT_RELA:
+		case DT_INIT:
+		case DT_FINI:
+		case DT_REL:
+		case DT_DEBUG:
+		case DT_JMPREL:
+		case DT_VERSYM:
+		case DT_VERDEF:
+		case DT_VERNEED:
+		case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+			/* definitely pointers needing relocation */
+			dyn->d_un.d_ptr += VDSO_ADDR_ADJUST;
+			break;
+
+		case DT_ENCODING ... OLD_DT_LOOS-1:
+		case DT_LOOS ... DT_HIOS-1:
+			/* Tags above DT_ENCODING are pointers if
+			   they're even */
+			if (dyn->d_tag >= DT_ENCODING &&
+			    (dyn->d_tag & 1) == 0)
+				dyn->d_un.d_ptr += VDSO_ADDR_ADJUST;
+			break;
+
+		case DT_VERDEFNUM:
+		case DT_VERNEEDNUM:
+		case DT_FLAGS_1:
+		case DT_RELACOUNT:
+		case DT_RELCOUNT:
+		case DT_VALRNGLO ... DT_VALRNGHI:
+			/* definitely not pointers */
+			break;
+
+		case OLD_DT_LOOS ... DT_LOOS-1:
+		case DT_HIOS ... DT_VALRNGLO-1:
+		default:
+			if (dyn->d_tag > DT_ENCODING)
+				printk(KERN_INFO "VDSO: unexpected DT_tag %x\n",
+				       dyn->d_tag);
+			break;
+		}
+}
+
+static __init void relocate_vdso(Elf32_Ehdr *ehdr)
+{
+	Elf32_Phdr *phdr;
+	Elf32_Shdr *shdr;
+	int i;
+
+	BUG_ON(memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 ||
+	       !elf_check_arch_ia32(ehdr) ||
+	       ehdr->e_type != ET_DYN);
+
+	ehdr->e_entry += VDSO_ADDR_ADJUST;
+
+	/* rebase phdrs */
+	phdr = (void *)ehdr + ehdr->e_phoff;
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		phdr[i].p_vaddr += VDSO_ADDR_ADJUST;
+
+		/* relocate dynamic stuff */
+		if (phdr[i].p_type == PT_DYNAMIC)
+			reloc_dyn(ehdr, phdr[i].p_offset);
+	}
+
+	/* rebase sections */
+	shdr = (void *)ehdr + ehdr->e_shoff;
+	for(i = 0; i < ehdr->e_shnum; i++) {
+		if (!(shdr[i].sh_flags & SHF_ALLOC))
+			continue;
+
+		shdr[i].sh_addr += VDSO_ADDR_ADJUST;
+
+		if (shdr[i].sh_type == SHT_SYMTAB ||
+		    shdr[i].sh_type == SHT_DYNSYM)
+			reloc_symtab(ehdr, shdr[i].sh_offset,
+				     shdr[i].sh_size);
+	}
+}
+
+static struct page *vdso32_pages[1];
+
+#ifdef CONFIG_X86_64
+
+#define	vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SYSENTER32))
+#define	vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
+
+void __cpuinit syscall32_cpu_init(void)
+{
+	static const struct callback_register __cpuinitconst cstar = {
+		.type = CALLBACKTYPE_syscall32,
+		.address = (unsigned long)ia32_cstar_target
+	};
+	static const struct callback_register __cpuinitconst sysenter = {
+		.type = CALLBACKTYPE_sysenter,
+		.address = (unsigned long)ia32_sysenter_target
+	};
+
+	if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) < 0)
+		setup_clear_cpu_cap(X86_FEATURE_SYSENTER32);
+	if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) < 0)
+		setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
+}
+
+#define compat_uses_vma		1
+
+static inline void map_compat_vdso(int map)
+{
+}
+
+#else  /* CONFIG_X86_32 */
+
+#define vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SEP))
+#define vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
+
+extern asmlinkage void ia32pv_cstar_target(void);
+static const struct callback_register __cpuinitconst cstar = {
+	.type = CALLBACKTYPE_syscall32,
+	.address = { __KERNEL_CS, (unsigned long)ia32pv_cstar_target },
+};
+
+void __cpuinit enable_sep_cpu(void)
+{
+	extern asmlinkage void ia32pv_sysenter_target(void);
+	static struct callback_register __cpuinitdata sysenter = {
+		.type = CALLBACKTYPE_sysenter,
+		.address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target },
+	};
+
+	if (vdso32_syscall()) {
+		if (HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) != 0)
+			BUG();
+		return;
+	}
+
+	if (!vdso32_sysenter())
+		return;
+
+	if (xen_feature(XENFEAT_supervisor_mode_kernel))
+		sysenter.address.eip = (unsigned long)ia32_sysenter_target;
+
+	switch (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter)) {
+	case 0:
+		break;
+#if CONFIG_XEN_COMPAT < 0x030200
+	case -ENOSYS:
+		sysenter.type = CALLBACKTYPE_sysenter_deprecated;
+		if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) == 0)
+			break;
+#endif
+	default:
+		setup_clear_cpu_cap(X86_FEATURE_SEP);
+		break;
+	}
+}
+
+static struct vm_area_struct gate_vma;
+
+static int __init gate_vma_init(void)
+{
+	gate_vma.vm_mm = NULL;
+	gate_vma.vm_start = FIXADDR_USER_START;
+	gate_vma.vm_end = FIXADDR_USER_END;
+	gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC;
+	gate_vma.vm_page_prot = __P101;
+	/*
+	 * 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.
+	 */
+	gate_vma.vm_flags |= VM_ALWAYSDUMP;
+	return 0;
+}
+
+#define compat_uses_vma		0
+
+static void map_compat_vdso(int map)
+{
+	static int vdso_mapped;
+
+	if (map == vdso_mapped)
+		return;
+
+	vdso_mapped = map;
+
+	__set_fixmap(FIX_VDSO, page_to_pfn(vdso32_pages[0]) << PAGE_SHIFT,
+		     map ? PAGE_READONLY_EXEC : PAGE_NONE);
+
+	/* flush stray tlbs */
+	flush_tlb_all();
+}
+
+#endif	/* CONFIG_X86_64 */
+
+int __init sysenter_setup(void)
+{
+	void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+	const void *vsyscall;
+	size_t vsyscall_len;
+
+	vdso32_pages[0] = virt_to_page(syscall_page);
+
+#ifdef CONFIG_X86_32
+	gate_vma_init();
+
+	if (boot_cpu_has(X86_FEATURE_SYSCALL)) {
+		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD
+		    && HYPERVISOR_callback_op(CALLBACKOP_register, &cstar) == 0)
+			setup_force_cpu_cap(X86_FEATURE_SYSCALL32);
+		else {
+			setup_clear_cpu_cap(X86_FEATURE_SYSCALL);
+			setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
+		}
+	}
+#endif
+	if (vdso32_syscall()) {
+		vsyscall = &vdso32_syscall_start;
+		vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
+	} else if (vdso32_sysenter()){
+		vsyscall = &vdso32_sysenter_start;
+		vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
+	} else {
+		vsyscall = &vdso32_int80_start;
+		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
+	}
+
+	memcpy(syscall_page, vsyscall, vsyscall_len);
+	relocate_vdso(syscall_page);
+
+	return 0;
+}
+
+/* Setup a VMA at program startup for the vsyscall page */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr;
+	int ret = 0;
+	bool compat;
+
+	if (vdso_enabled == VDSO_DISABLED)
+		return 0;
+
+	down_write(&mm->mmap_sem);
+
+	/* Test compat mode once here, in case someone
+	   changes it via sysctl */
+	compat = (vdso_enabled == VDSO_COMPAT);
+
+	map_compat_vdso(compat);
+
+	if (compat)
+		addr = VDSO_HIGH_BASE;
+	else {
+		addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+		if (IS_ERR_VALUE(addr)) {
+			ret = addr;
+			goto up_fail;
+		}
+	}
+
+	current->mm->context.vdso = (void *)addr;
+
+	if (compat_uses_vma || !compat) {
+		/*
+		 * MAYWRITE to allow gdb to COW and set breakpoints
+		 *
+		 * 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.
+		 */
+		ret = install_special_mapping(mm, addr, PAGE_SIZE,
+					      VM_READ|VM_EXEC|
+					      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
+					      VM_ALWAYSDUMP,
+					      vdso32_pages);
+
+		if (ret)
+			goto up_fail;
+	}
+
+	current_thread_info()->sysenter_return =
+		VDSO32_SYMBOL(addr, SYSENTER_RETURN);
+
+  up_fail:
+	if (ret)
+		current->mm->context.vdso = NULL;
+
+	up_write(&mm->mmap_sem);
+
+	return ret;
+}
+
+#ifdef CONFIG_X86_64
+
+/*
+ * This must be done early in case we have an initrd containing 32-bit
+ * binaries (e.g., hotplug). This could be pushed upstream.
+ */
+core_initcall(sysenter_setup);
+
+#ifdef CONFIG_SYSCTL
+/* Register vsyscall32 into the ABI table */
+#include <linux/sysctl.h>
+
+static ctl_table abi_table2[] = {
+	{
+		.procname	= "vsyscall32",
+		.data		= &sysctl_vsyscall32,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
+	{}
+};
+
+static ctl_table abi_root_table2[] = {
+	{
+		.ctl_name = CTL_ABI,
+		.procname = "abi",
+		.mode = 0555,
+		.child = abi_table2
+	},
+	{}
+};
+
+static __init int ia32_binfmt_init(void)
+{
+	register_sysctl_table(abi_root_table2);
+	return 0;
+}
+__initcall(ia32_binfmt_init);
+#endif
+
+#else  /* CONFIG_X86_32 */
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+{
+	struct mm_struct *mm = tsk->mm;
+
+	/* Check to see if this task was created in compat vdso mode */
+	if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE)
+		return &gate_vma;
+	return NULL;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long addr)
+{
+	const struct vm_area_struct *vma = get_gate_vma(task);
+
+	return vma && addr >= vma->vm_start && addr < vma->vm_end;
+}
+
+int in_gate_area_no_task(unsigned long addr)
+{
+	return 0;
+}
+
+#endif	/* CONFIG_X86_64 */
--- linux-ec2-2.6.32.orig/arch/x86/vdso/vdso32/syscall.S
+++ linux-ec2-2.6.32/arch/x86/vdso/vdso32/syscall.S
@@ -19,8 +19,10 @@
 .Lpush_ebp:
 	movl	%ecx, %ebp
 	syscall
+#ifndef CONFIG_XEN
 	movl	$__USER32_DS, %ecx
 	movl	%ecx, %ss
+#endif
 	movl	%ebp, %ecx
 	popl	%ebp
 .Lpop_ebp:
--- linux-ec2-2.6.32.orig/arch/x86/vdso/vdso32/note.S
+++ linux-ec2-2.6.32/arch/x86/vdso/vdso32/note.S
@@ -13,7 +13,7 @@
 	.long LINUX_VERSION_CODE
 ELFNOTE_END
 
-#ifdef CONFIG_XEN
+#if defined(CONFIG_X86_XEN) || defined(CONFIG_PARAVIRT_XEN)
 /*
  * Add a special note telling glibc's dynamic linker a fake hardware
  * flavor that it will use to choose the search path for libraries in the
@@ -37,8 +37,12 @@
 
 ELFNOTE_START(GNU, 2, "a")
 	.long 1			/* ncaps */
+#ifdef CONFIG_PARAVIRT_XEN
 VDSO32_NOTE_MASK:		/* Symbol used by arch/x86/xen/setup.c */
 	.long 0			/* mask */
+#else
+	.long 1 << VDSO_NOTE_NONEGSEG_BIT /* mask */
+#endif
 	.byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg"	/* bit, name */
 ELFNOTE_END
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/xenoprof.c
+++ linux-ec2-2.6.32/arch/x86/oprofile/xenoprof.c
@@ -0,0 +1,179 @@
+/**
+ * @file xenoprof.c
+ *
+ * @remark Copyright 2002 OProfile authors
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@movementarian.org>
+ *
+ * Modified by Aravind Menon and Jose Renato Santos for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
+ *
+ * x86-specific part
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ */
+
+#include <linux/init.h>
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+#include <asm/pgtable.h>
+
+#include <xen/driver_util.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/xenoprof.h>
+#include <xen/xenoprof.h>
+#include "op_counter.h"
+
+static unsigned int num_events = 0;
+
+void __init xenoprof_arch_init_counter(struct xenoprof_init *init)
+{
+	num_events = init->num_events;
+	/* just in case - make sure we do not overflow event list 
+	   (i.e. counter_config list) */
+	if (num_events > OP_MAX_COUNTER) {
+		num_events = OP_MAX_COUNTER;
+		init->num_events = num_events;
+	}
+}
+
+void xenoprof_arch_counter(void)
+{
+	int i;
+	struct xenoprof_counter counter;
+
+	for (i=0; i<num_events; i++) {
+		counter.ind       = i;
+		counter.count     = (uint64_t)counter_config[i].count;
+		counter.enabled   = (uint32_t)counter_config[i].enabled;
+		counter.event     = (uint32_t)counter_config[i].event;
+		counter.kernel    = (uint32_t)counter_config[i].kernel;
+		counter.user      = (uint32_t)counter_config[i].user;
+		counter.unit_mask = (uint64_t)counter_config[i].unit_mask;
+		WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_counter,
+					       &counter));
+	}
+}
+
+void xenoprof_arch_start(void) 
+{
+	/* nothing */
+}
+
+void xenoprof_arch_stop(void)
+{
+	/* nothing */
+}
+
+void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf)
+{
+	if (sbuf->buffer) {
+		vunmap(sbuf->buffer);
+		sbuf->buffer = NULL;
+	}
+}
+
+int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer,
+				    struct xenoprof_shared_buffer * sbuf)
+{
+	int npages, ret;
+	struct vm_struct *area;
+
+	sbuf->buffer = NULL;
+	if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) )
+		return ret;
+
+	npages = (get_buffer->bufsize * get_buffer->nbuf - 1) / PAGE_SIZE + 1;
+
+	area = alloc_vm_area(npages * PAGE_SIZE);
+	if (area == NULL)
+		return -ENOMEM;
+
+	if ( (ret = direct_kernel_remap_pfn_range(
+		      (unsigned long)area->addr,
+		      get_buffer->buf_gmaddr >> PAGE_SHIFT,
+		      npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE),
+		      DOMID_SELF)) ) {
+		vunmap(area->addr);
+		return ret;
+	}
+
+	sbuf->buffer = area->addr;
+	return ret;
+}
+
+int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain,
+			      struct xenoprof_shared_buffer * sbuf)
+{
+	int ret;
+	int npages;
+	struct vm_struct *area;
+	pgprot_t prot = __pgprot(_KERNPG_TABLE);
+
+	sbuf->buffer = NULL;
+	ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain);
+	if (ret)
+		goto out;
+
+	npages = (pdomain->bufsize * pdomain->nbuf - 1) / PAGE_SIZE + 1;
+
+	area = alloc_vm_area(npages * PAGE_SIZE);
+	if (area == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = direct_kernel_remap_pfn_range(
+		(unsigned long)area->addr,
+		pdomain->buf_gmaddr >> PAGE_SHIFT,
+		npages * PAGE_SIZE, prot, DOMID_SELF);
+	if (ret) {
+		vunmap(area->addr);
+		goto out;
+	}
+	sbuf->buffer = area->addr;
+
+out:
+	return ret;
+}
+
+struct op_counter_config counter_config[OP_MAX_COUNTER];
+
+int xenoprof_create_files(struct super_block * sb, struct dentry * root)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_events; ++i) {
+		struct dentry * dir;
+		char buf[2];
+ 
+		snprintf(buf, 2, "%d", i);
+		dir = oprofilefs_mkdir(sb, root, buf);
+		oprofilefs_create_ulong(sb, dir, "enabled",
+					&counter_config[i].enabled);
+		oprofilefs_create_ulong(sb, dir, "event",
+					&counter_config[i].event);
+		oprofilefs_create_ulong(sb, dir, "count",
+					&counter_config[i].count);
+		oprofilefs_create_ulong(sb, dir, "unit_mask",
+					&counter_config[i].unit_mask);
+		oprofilefs_create_ulong(sb, dir, "kernel",
+					&counter_config[i].kernel);
+		oprofilefs_create_ulong(sb, dir, "user",
+					&counter_config[i].user);
+	}
+
+	return 0;
+}
+
+int __init oprofile_arch_init(struct oprofile_operations * ops)
+{
+	return xenoprofile_init(ops);
+}
+
+void oprofile_arch_exit(void)
+{
+	xenoprofile_exit();
+}
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/Makefile
+++ linux-ec2-2.6.32/arch/x86/oprofile/Makefile
@@ -6,7 +6,14 @@
 		oprofilefs.o oprofile_stats.o  \
 		timer_int.o )
 
+ifdef CONFIG_XEN
+XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
+			 xenoprofile.o)
+oprofile-y				:= $(DRIVER_OBJS) \
+					   $(XENOPROF_COMMON_OBJS) xenoprof.o
+else
 oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
 oprofile-$(CONFIG_X86_LOCAL_APIC) 	+= nmi_int.o op_model_amd.o \
 					   op_model_ppro.o op_model_p4.o
 oprofile-$(CONFIG_X86_IO_APIC)		+= nmi_timer_int.o
+endif
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/op_model_amd.c
+++ linux-ec2-2.6.32/arch/x86/oprofile/op_model_amd.c
@@ -76,19 +76,6 @@
 
 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
 
-static void op_mux_fill_in_addresses(struct op_msrs * const msrs)
-{
-	int i;
-
-	for (i = 0; i < NUM_VIRT_COUNTERS; i++) {
-		int hw_counter = op_x86_virt_to_phys(i);
-		if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
-			msrs->multiplex[i].addr = MSR_K7_PERFCTR0 + hw_counter;
-		else
-			msrs->multiplex[i].addr = 0;
-	}
-}
-
 static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
 			       struct op_msrs const * const msrs)
 {
@@ -98,7 +85,7 @@
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
 		int virt = op_x86_phys_to_virt(i);
-		if (!counter_config[virt].enabled)
+		if (!reset_value[virt])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
 		val &= model->reserved;
@@ -107,10 +94,6 @@
 	}
 }
 
-#else
-
-static inline void op_mux_fill_in_addresses(struct op_msrs * const msrs) { }
-
 #endif
 
 /* functions for op_amd_spec */
@@ -122,18 +105,12 @@
 	for (i = 0; i < NUM_COUNTERS; i++) {
 		if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
 			msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
-		else
-			msrs->counters[i].addr = 0;
 	}
 
 	for (i = 0; i < NUM_CONTROLS; i++) {
 		if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
 			msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
-		else
-			msrs->controls[i].addr = 0;
 	}
-
-	op_mux_fill_in_addresses(msrs);
 }
 
 static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
@@ -144,7 +121,8 @@
 
 	/* setup reset_value */
 	for (i = 0; i < NUM_VIRT_COUNTERS; ++i) {
-		if (counter_config[i].enabled)
+		if (counter_config[i].enabled
+		    && msrs->counters[op_x86_virt_to_phys(i)].addr)
 			reset_value[i] = counter_config[i].count;
 		else
 			reset_value[i] = 0;
@@ -169,9 +147,7 @@
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
 		int virt = op_x86_phys_to_virt(i);
-		if (!counter_config[virt].enabled)
-			continue;
-		if (!msrs->counters[i].addr)
+		if (!reset_value[virt])
 			continue;
 
 		/* setup counter registers */
@@ -405,16 +381,6 @@
 		return 1;
 	}
 
-#ifdef CONFIG_NUMA
-	/* Sanity check */
-	/* Works only for 64bit with proper numa implementation. */
-	if (nodes != num_possible_nodes()) {
-		printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, "
-			"found: %d, expected %d",
-			nodes, num_possible_nodes());
-		return 1;
-	}
-#endif
 	return 0;
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/op_model_ppro.c
+++ linux-ec2-2.6.32/arch/x86/oprofile/op_model_ppro.c
@@ -37,15 +37,11 @@
 	for (i = 0; i < num_counters; i++) {
 		if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
 			msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
-		else
-			msrs->counters[i].addr = 0;
 	}
 
 	for (i = 0; i < num_counters; i++) {
 		if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
 			msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
-		else
-			msrs->controls[i].addr = 0;
 	}
 }
 
@@ -57,7 +53,7 @@
 	int i;
 
 	if (!reset_value) {
-		reset_value = kmalloc(sizeof(reset_value[0]) * num_counters,
+		reset_value = kzalloc(sizeof(reset_value[0]) * num_counters,
 					GFP_ATOMIC);
 		if (!reset_value)
 			return;
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/op_model_p4.c
+++ linux-ec2-2.6.32/arch/x86/oprofile/op_model_p4.c
@@ -394,12 +394,6 @@
 	setup_num_counters();
 	stag = get_stagger();
 
-	/* initialize some registers */
-	for (i = 0; i < num_counters; ++i)
-		msrs->counters[i].addr = 0;
-	for (i = 0; i < num_controls; ++i)
-		msrs->controls[i].addr = 0;
-
 	/* the counter & cccr registers we pay attention to */
 	for (i = 0; i < num_counters; ++i) {
 		addr = p4_counters[VIRT_CTR(stag, i)].counter_address;
--- linux-ec2-2.6.32.orig/arch/x86/oprofile/nmi_int.c
+++ linux-ec2-2.6.32/arch/x86/oprofile/nmi_int.c
@@ -95,7 +95,10 @@
 static void nmi_cpu_start(void *dummy)
 {
 	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-	model->start(msrs);
+	if (!msrs->controls)
+		WARN_ON_ONCE(1);
+	else
+		model->start(msrs);
 }
 
 static int nmi_start(void)
@@ -107,7 +110,10 @@
 static void nmi_cpu_stop(void *dummy)
 {
 	struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
-	model->stop(msrs);
+	if (!msrs->controls)
+		WARN_ON_ONCE(1);
+	else
+		model->stop(msrs);
 }
 
 static void nmi_stop(void)
@@ -159,7 +165,7 @@
 
 	for_each_possible_cpu(i) {
 		per_cpu(cpu_msrs, i).multiplex =
-			kmalloc(multiplex_size, GFP_KERNEL);
+			kzalloc(multiplex_size, GFP_KERNEL);
 		if (!per_cpu(cpu_msrs, i).multiplex)
 			return 0;
 	}
@@ -179,7 +185,6 @@
 		if (counter_config[i].enabled) {
 			multiplex[i].saved = -(u64)counter_config[i].count;
 		} else {
-			multiplex[i].addr  = 0;
 			multiplex[i].saved = 0;
 		}
 	}
@@ -189,25 +194,27 @@
 
 static void nmi_cpu_save_mpx_registers(struct op_msrs *msrs)
 {
+	struct op_msr *counters = msrs->counters;
 	struct op_msr *multiplex = msrs->multiplex;
 	int i;
 
 	for (i = 0; i < model->num_counters; ++i) {
 		int virt = op_x86_phys_to_virt(i);
-		if (multiplex[virt].addr)
-			rdmsrl(multiplex[virt].addr, multiplex[virt].saved);
+		if (counters[i].addr)
+			rdmsrl(counters[i].addr, multiplex[virt].saved);
 	}
 }
 
 static void nmi_cpu_restore_mpx_registers(struct op_msrs *msrs)
 {
+	struct op_msr *counters = msrs->counters;
 	struct op_msr *multiplex = msrs->multiplex;
 	int i;
 
 	for (i = 0; i < model->num_counters; ++i) {
 		int virt = op_x86_phys_to_virt(i);
-		if (multiplex[virt].addr)
-			wrmsrl(multiplex[virt].addr, multiplex[virt].saved);
+		if (counters[i].addr)
+			wrmsrl(counters[i].addr, multiplex[virt].saved);
 	}
 }
 
@@ -222,7 +229,7 @@
 
 	/* move to next set */
 	si += model->num_counters;
-	if ((si > model->num_virt_counters) || (counter_config[si].count == 0))
+	if ((si >= model->num_virt_counters) || (counter_config[si].count == 0))
 		per_cpu(switch_index, cpu) = 0;
 	else
 		per_cpu(switch_index, cpu) = si;
@@ -303,11 +310,11 @@
 
 	int i;
 	for_each_possible_cpu(i) {
-		per_cpu(cpu_msrs, i).counters = kmalloc(counters_size,
+		per_cpu(cpu_msrs, i).counters = kzalloc(counters_size,
 							GFP_KERNEL);
 		if (!per_cpu(cpu_msrs, i).counters)
 			return 0;
-		per_cpu(cpu_msrs, i).controls = kmalloc(controls_size,
+		per_cpu(cpu_msrs, i).controls = kzalloc(controls_size,
 							GFP_KERNEL);
 		if (!per_cpu(cpu_msrs, i).controls)
 			return 0;
@@ -511,8 +518,13 @@
 	int error;
 
 	error = sysdev_class_register(&oprofile_sysclass);
-	if (!error)
-		error = sysdev_register(&device_oprofile);
+	if (error)
+		return error;
+
+	error = sysdev_register(&device_oprofile);
+	if (error)
+		sysdev_class_unregister(&oprofile_sysclass);
+
 	return error;
 }
 
@@ -523,8 +535,10 @@
 }
 
 #else
-#define init_sysfs() do { } while (0)
-#define exit_sysfs() do { } while (0)
+
+static inline int  init_sysfs(void) { return 0; }
+static inline void exit_sysfs(void) { }
+
 #endif /* CONFIG_PM */
 
 static int __init p4_init(char **cpu_type)
@@ -577,6 +591,18 @@
 	if (force_arch_perfmon && cpu_has_arch_perfmon)
 		return 0;
 
+	/*
+	 * Documentation on identifying Intel processors by CPU family
+	 * and model can be found in the Intel Software Developer's
+	 * Manuals (SDM):
+	 *
+	 *  http://www.intel.com/products/processor/manuals/
+	 *
+	 * As of May 2010 the documentation for this was in the:
+	 * "Intel 64 and IA-32 Architectures Software Developer's
+	 * Manual Volume 3B: System Programming Guide", "Table B-1
+	 * CPUID Signature Values of DisplayFamily_DisplayModel".
+	 */
 	switch (cpu_model) {
 	case 0 ... 2:
 		*cpu_type = "i386/ppro";
@@ -595,14 +621,19 @@
 	case 14:
 		*cpu_type = "i386/core";
 		break;
-	case 15: case 23:
+	case 0x0f:
+	case 0x16:
+	case 0x17:
+	case 0x1d:
 		*cpu_type = "i386/core_2";
 		break;
-	case 26:
+	case 0x1a:
+	case 0x1e:
+	case 0x2e:
 		spec = &op_arch_perfmon_spec;
 		*cpu_type = "i386/core_i7";
 		break;
-	case 28:
+	case 0x1c:
 		*cpu_type = "i386/atom";
 		break;
 	default:
@@ -624,6 +655,8 @@
 	char *cpu_type = NULL;
 	int ret = 0;
 
+	using_nmi = 0;
+
 	if (!cpu_has_apic)
 		return -ENODEV;
 
@@ -706,7 +739,10 @@
 
 	mux_init(ops);
 
-	init_sysfs();
+	ret = init_sysfs();
+	if (ret)
+		return ret;
+
 	using_nmi = 1;
 	printk(KERN_INFO "oprofile: using NMI interrupt.\n");
 	return 0;
--- linux-ec2-2.6.32.orig/arch/x86/boot/Makefile
+++ linux-ec2-2.6.32/arch/x86/boot/Makefile
@@ -23,6 +23,7 @@
 SVGA_MODE	:= -DSVGA_MODE=NORMAL_VGA
 
 targets		:= vmlinux.bin setup.bin setup.elf bzImage
+targets		+= vmlinuz vmlinux-stripped
 targets		+= fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-		:= compressed
 
@@ -195,6 +196,20 @@
 	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)
+
+ifndef CONFIG_XEN
+bzImage := bzImage
+else
+bzImage := vmlinuz
+endif
+
 install:
-	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
+	sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/$(bzImage) \
 		System.map "$(INSTALL_PATH)"
--- linux-ec2-2.6.32.orig/arch/x86/pci/irq-xen.c
+++ linux-ec2-2.6.32/arch/x86/pci/irq-xen.c
@@ -0,0 +1,1265 @@
+/*
+ *	Low-Level PCI Support for PC -- Routing of Interrupts
+ *
+ *	(c) 1999--2000 Martin Mares <mj@ucw.cz>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+#include <asm/io_apic.h>
+#include <linux/irq.h>
+#include <linux/acpi.h>
+#include <asm/pci_x86.h>
+
+#define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
+#define PIRQ_VERSION 0x0100
+
+static int broken_hp_bios_irq9;
+static int acer_tm360_irqrouting;
+
+static struct irq_routing_table *pirq_table;
+
+static int pirq_enable_irq(struct pci_dev *dev);
+
+/*
+ * Never use: 0, 1, 2 (timer, keyboard, and cascade)
+ * Avoid using: 13, 14 and 15 (FP error and IDE).
+ * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
+ */
+unsigned int pcibios_irq_mask = 0xfff8;
+
+static int pirq_penalty[16] = {
+	1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
+	0, 0, 0, 0, 1000, 100000, 100000, 100000
+};
+
+struct irq_router {
+	char *name;
+	u16 vendor, device;
+	int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
+	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq,
+		int new);
+};
+
+struct irq_router_handler {
+	u16 vendor;
+	int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
+};
+
+int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
+
+/*
+ *  Check passed address for the PCI IRQ Routing Table signature
+ *  and perform checksum verification.
+ */
+
+static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
+{
+	struct irq_routing_table *rt;
+	int i;
+	u8 sum;
+
+	rt = (struct irq_routing_table *) addr;
+	if (rt->signature != PIRQ_SIGNATURE ||
+	    rt->version != PIRQ_VERSION ||
+	    rt->size % 16 ||
+	    rt->size < sizeof(struct irq_routing_table))
+		return NULL;
+	sum = 0;
+	for (i = 0; i < rt->size; i++)
+		sum += addr[i];
+	if (!sum) {
+		DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n",
+			rt);
+		return rt;
+	}
+	return NULL;
+}
+
+
+
+/*
+ *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
+ */
+
+static struct irq_routing_table * __init pirq_find_routing_table(void)
+{
+	u8 *addr;
+	struct irq_routing_table *rt;
+
+#ifdef CONFIG_XEN
+	if (!is_initial_xendomain())
+		return NULL;
+#endif
+	if (pirq_table_addr) {
+		rt = pirq_check_routing_table((u8 *) isa_bus_to_virt(pirq_table_addr));
+		if (rt)
+			return rt;
+		printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
+	}
+	for (addr = (u8 *) isa_bus_to_virt(0xf0000);
+	     addr < (u8 *) isa_bus_to_virt(0x100000);
+	     addr += 16) {
+		rt = pirq_check_routing_table(addr);
+		if (rt)
+			return rt;
+	}
+	return NULL;
+}
+
+/*
+ *  If we have a IRQ routing table, use it to search for peer host
+ *  bridges.  It's a gross hack, but since there are no other known
+ *  ways how to get a list of buses, we have to go this way.
+ */
+
+static void __init pirq_peer_trick(void)
+{
+	struct irq_routing_table *rt = pirq_table;
+	u8 busmap[256];
+	int i;
+	struct irq_info *e;
+
+	memset(busmap, 0, sizeof(busmap));
+	for (i = 0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
+		e = &rt->slots[i];
+#ifdef DEBUG
+		{
+			int j;
+			DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
+			for (j = 0; j < 4; j++)
+				DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
+			DBG("\n");
+		}
+#endif
+		busmap[e->bus] = 1;
+	}
+	for (i = 1; i < 256; i++) {
+		int node;
+		if (!busmap[i] || pci_find_bus(0, i))
+			continue;
+		node = get_mp_bus_to_node(i);
+		if (pci_scan_bus_on_node(i, &pci_root_ops, node))
+			printk(KERN_INFO "PCI: Discovered primary peer "
+			       "bus %02x [IRQ]\n", i);
+	}
+	pcibios_last_bus = -1;
+}
+
+/*
+ *  Code for querying and setting of IRQ routes on various interrupt routers.
+ */
+
+void eisa_set_level_irq(unsigned int irq)
+{
+	unsigned char mask = 1 << (irq & 7);
+	unsigned int port = 0x4d0 + (irq >> 3);
+	unsigned char val;
+	static u16 eisa_irq_mask;
+
+	if (irq >= 16 || (1 << irq) & eisa_irq_mask)
+		return;
+
+	eisa_irq_mask |= (1 << irq);
+	printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq);
+	val = inb(port);
+	if (!(val & mask)) {
+		DBG(KERN_DEBUG " -> edge");
+		outb(val | mask, port);
+	}
+}
+
+/*
+ * Common IRQ routing practice: nibbles in config space,
+ * offset by some magic constant.
+ */
+static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
+{
+	u8 x;
+	unsigned reg = offset + (nr >> 1);
+
+	pci_read_config_byte(router, reg, &x);
+	return (nr & 1) ? (x >> 4) : (x & 0xf);
+}
+
+static void write_config_nybble(struct pci_dev *router, unsigned offset,
+	unsigned nr, unsigned int val)
+{
+	u8 x;
+	unsigned reg = offset + (nr >> 1);
+
+	pci_read_config_byte(router, reg, &x);
+	x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
+	pci_write_config_byte(router, reg, x);
+}
+
+/*
+ * ALI pirq entries are damn ugly, and completely undocumented.
+ * This has been figured out from pirq tables, and it's not a pretty
+ * picture.
+ */
+static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+
+	WARN_ON_ONCE(pirq > 16);
+	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
+}
+
+static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+	unsigned int val = irqmap[irq];
+
+	WARN_ON_ONCE(pirq > 16);
+	if (val) {
+		write_config_nybble(router, 0x48, pirq-1, val);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
+ * just a pointer to the config space.
+ */
+static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	u8 x;
+
+	pci_read_config_byte(router, pirq, &x);
+	return (x < 16) ? x : 0;
+}
+
+static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	pci_write_config_byte(router, pirq, irq);
+	return 1;
+}
+
+/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, PIRQD is in the upper instead of lower 4 bits.
+ */
+static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
+}
+
+static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
+	return 1;
+}
+
+/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, for 82C586, nibble map is different .
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 };
+
+	WARN_ON_ONCE(pirq > 5);
+	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[5] = { 3, 2, 5, 1, 1 };
+
+	WARN_ON_ONCE(pirq > 5);
+	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+	return 1;
+}
+
+/*
+ * ITE 8330G pirq rules are nibble-based
+ * FIXME: pirqmap may be { 1, 0, 3, 2 },
+ * 	  2+3 are both mapped to irq 9 on my system
+ */
+static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+
+	WARN_ON_ONCE(pirq > 4);
+	return read_config_nybble(router, 0x43, pirqmap[pirq-1]);
+}
+
+static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+
+	WARN_ON_ONCE(pirq > 4);
+	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+	return 1;
+}
+
+/*
+ * OPTI: high four bits are nibble pointer..
+ * I wonder what the low bits do?
+ */
+static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	return read_config_nybble(router, 0xb8, pirq >> 4);
+}
+
+static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	write_config_nybble(router, 0xb8, pirq >> 4, irq);
+	return 1;
+}
+
+/*
+ * Cyrix: nibble offset 0x5C
+ * 0x5C bits 7:4 is INTB bits 3:0 is INTA
+ * 0x5D bits 7:4 is INTD bits 3:0 is INTC
+ */
+static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	return read_config_nybble(router, 0x5C, (pirq-1)^1);
+}
+
+static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
+	return 1;
+}
+
+/*
+ *	PIRQ routing for SiS 85C503 router used in several SiS chipsets.
+ *	We have to deal with the following issues here:
+ *	- vendors have different ideas about the meaning of link values
+ *	- some onboard devices (integrated in the chipset) have special
+ *	  links and are thus routed differently (i.e. not via PCI INTA-INTD)
+ *	- different revision of the router have a different layout for
+ *	  the routing registers, particularly for the onchip devices
+ *
+ *	For all routing registers the common thing is we have one byte
+ *	per routeable link which is defined as:
+ *		 bit 7      IRQ mapping enabled (0) or disabled (1)
+ *		 bits [6:4] reserved (sometimes used for onchip devices)
+ *		 bits [3:0] IRQ to map to
+ *		     allowed: 3-7, 9-12, 14-15
+ *		     reserved: 0, 1, 2, 8, 13
+ *
+ *	The config-space registers located at 0x41/0x42/0x43/0x44 are
+ *	always used to route the normal PCI INT A/B/C/D respectively.
+ *	Apparently there are systems implementing PCI routing table using
+ *	link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D.
+ *	We try our best to handle both link mappings.
+ *
+ *	Currently (2003-05-21) it appears most SiS chipsets follow the
+ *	definition of routing registers from the SiS-5595 southbridge.
+ *	According to the SiS 5595 datasheets the revision id's of the
+ *	router (ISA-bridge) should be 0x01 or 0xb0.
+ *
+ *	Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1.
+ *	Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets.
+ *	They seem to work with the current routing code. However there is
+ *	some concern because of the two USB-OHCI HCs (original SiS 5595
+ *	had only one). YMMV.
+ *
+ *	Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1:
+ *
+ *	0x61:	IDEIRQ:
+ *		bits [6:5] must be written 01
+ *		bit 4 channel-select primary (0), secondary (1)
+ *
+ *	0x62:	USBIRQ:
+ *		bit 6 OHCI function disabled (0), enabled (1)
+ *
+ *	0x6a:	ACPI/SCI IRQ: bits 4-6 reserved
+ *
+ *	0x7e:	Data Acq. Module IRQ - bits 4-6 reserved
+ *
+ *	We support USBIRQ (in addition to INTA-INTD) and keep the
+ *	IDE, ACPI and DAQ routing untouched as set by the BIOS.
+ *
+ *	Currently the only reported exception is the new SiS 65x chipset
+ *	which includes the SiS 69x southbridge. Here we have the 85C503
+ *	router revision 0x04 and there are changes in the register layout
+ *	mostly related to the different USB HCs with USB 2.0 support.
+ *
+ *	Onchip routing for router rev-id 0x04 (try-and-error observation)
+ *
+ *	0x60/0x61/0x62/0x63:	1xEHCI and 3xOHCI (companion) USB-HCs
+ *				bit 6-4 are probably unused, not like 5595
+ */
+
+#define PIRQ_SIS_IRQ_MASK	0x0f
+#define PIRQ_SIS_IRQ_DISABLE	0x80
+#define PIRQ_SIS_USB_ENABLE	0x40
+
+static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	u8 x;
+	int reg;
+
+	reg = pirq;
+	if (reg >= 0x01 && reg <= 0x04)
+		reg += 0x40;
+	pci_read_config_byte(router, reg, &x);
+	return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK);
+}
+
+static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	u8 x;
+	int reg;
+
+	reg = pirq;
+	if (reg >= 0x01 && reg <= 0x04)
+		reg += 0x40;
+	pci_read_config_byte(router, reg, &x);
+	x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE);
+	x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE;
+	pci_write_config_byte(router, reg, x);
+	return 1;
+}
+
+
+/*
+ * VLSI: nibble offset 0x74 - educated guess due to routing table and
+ *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
+ *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
+ *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
+ *       for the busbridge to the docking station.
+ */
+
+static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	WARN_ON_ONCE(pirq >= 9);
+	if (pirq > 8) {
+		dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
+		return 0;
+	}
+	return read_config_nybble(router, 0x74, pirq-1);
+}
+
+static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	WARN_ON_ONCE(pirq >= 9);
+	if (pirq > 8) {
+		dev_info(&dev->dev, "VLSI router PIRQ escape (%d)\n", pirq);
+		return 0;
+	}
+	write_config_nybble(router, 0x74, pirq-1, irq);
+	return 1;
+}
+
+/*
+ * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
+ * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
+ * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
+ * register is a straight binary coding of desired PIC IRQ (low nibble).
+ *
+ * The 'link' value in the PIRQ table is already in the correct format
+ * for the Index register.  There are some special index values:
+ * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
+ * and 0x03 for SMBus.
+ */
+static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	outb(pirq, 0xc00);
+	return inb(0xc01) & 0xf;
+}
+
+static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev,
+	int pirq, int irq)
+{
+	outb(pirq, 0xc00);
+	outb(irq, 0xc01);
+	return 1;
+}
+
+/* Support for AMD756 PCI IRQ Routing
+ * Jhon H. Caicedo <jhcaiced@osso.org.co>
+ * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
+ * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
+ * The AMD756 pirq rules are nibble-based
+ * offset 0x56 0-3 PIRQA  4-7  PIRQB
+ * offset 0x57 0-3 PIRQC  4-7  PIRQD
+ */
+static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	u8 irq;
+	irq = 0;
+	if (pirq <= 4)
+		irq = read_config_nybble(router, 0x56, pirq - 1);
+	dev_info(&dev->dev,
+		 "AMD756: dev [%04x:%04x], router PIRQ %d get IRQ %d\n",
+		 dev->vendor, dev->device, pirq, irq);
+	return irq;
+}
+
+static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	dev_info(&dev->dev,
+		 "AMD756: dev [%04x:%04x], router PIRQ %d set IRQ %d\n",
+		 dev->vendor, dev->device, pirq, irq);
+	if (pirq <= 4)
+		write_config_nybble(router, 0x56, pirq - 1, irq);
+	return 1;
+}
+
+/*
+ * PicoPower PT86C523
+ */
+static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	outb(0x10 + ((pirq - 1) >> 1), 0x24);
+	return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf);
+}
+
+static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
+			int irq)
+{
+	unsigned int x;
+	outb(0x10 + ((pirq - 1) >> 1), 0x24);
+	x = inb(0x26);
+	x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq));
+	outb(x, 0x26);
+	return 1;
+}
+
+#ifdef CONFIG_PCI_BIOS
+
+static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	struct pci_dev *bridge;
+	int pin = pci_get_interrupt_pin(dev, &bridge);
+	return pcibios_set_irq_routing(bridge, pin - 1, irq);
+}
+
+#endif
+
+static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	static struct pci_device_id __initdata pirq_440gx[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
+		{ },
+	};
+
+	/* 440GX has a proprietary PIRQ router -- don't use it */
+	if (pci_dev_present(pirq_440gx))
+		return 0;
+
+	switch (device) {
+	case PCI_DEVICE_ID_INTEL_82371FB_0:
+	case PCI_DEVICE_ID_INTEL_82371SB_0:
+	case PCI_DEVICE_ID_INTEL_82371AB_0:
+	case PCI_DEVICE_ID_INTEL_82371MX:
+	case PCI_DEVICE_ID_INTEL_82443MX_0:
+	case PCI_DEVICE_ID_INTEL_82801AA_0:
+	case PCI_DEVICE_ID_INTEL_82801AB_0:
+	case PCI_DEVICE_ID_INTEL_82801BA_0:
+	case PCI_DEVICE_ID_INTEL_82801BA_10:
+	case PCI_DEVICE_ID_INTEL_82801CA_0:
+	case PCI_DEVICE_ID_INTEL_82801CA_12:
+	case PCI_DEVICE_ID_INTEL_82801DB_0:
+	case PCI_DEVICE_ID_INTEL_82801E_0:
+	case PCI_DEVICE_ID_INTEL_82801EB_0:
+	case PCI_DEVICE_ID_INTEL_ESB_1:
+	case PCI_DEVICE_ID_INTEL_ICH6_0:
+	case PCI_DEVICE_ID_INTEL_ICH6_1:
+	case PCI_DEVICE_ID_INTEL_ICH7_0:
+	case PCI_DEVICE_ID_INTEL_ICH7_1:
+	case PCI_DEVICE_ID_INTEL_ICH7_30:
+	case PCI_DEVICE_ID_INTEL_ICH7_31:
+	case PCI_DEVICE_ID_INTEL_TGP_LPC:
+	case PCI_DEVICE_ID_INTEL_ESB2_0:
+	case PCI_DEVICE_ID_INTEL_ICH8_0:
+	case PCI_DEVICE_ID_INTEL_ICH8_1:
+	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_TOLAPAI_0:
+	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:
+	case PCI_DEVICE_ID_INTEL_CPT_LPC1:
+	case PCI_DEVICE_ID_INTEL_CPT_LPC2:
+		r->name = "PIIX/ICH";
+		r->get = pirq_piix_get;
+		r->set = pirq_piix_set;
+		return 1;
+	}
+
+	if ((device >= PCI_DEVICE_ID_INTEL_PCH_LPC_MIN) &&
+		(device <= PCI_DEVICE_ID_INTEL_PCH_LPC_MAX)) {
+		r->name = "PIIX/ICH";
+		r->get = pirq_piix_get;
+		r->set = pirq_piix_set;
+		return 1;
+	}
+
+	return 0;
+}
+
+static __init int via_router_probe(struct irq_router *r,
+				struct pci_dev *router, u16 device)
+{
+	/* FIXME: We should move some of the quirk fixup stuff here */
+
+	/*
+	 * workarounds for some buggy BIOSes
+	 */
+	if (device == PCI_DEVICE_ID_VIA_82C586_0) {
+		switch (router->device) {
+		case PCI_DEVICE_ID_VIA_82C686:
+			/*
+			 * Asus k7m bios wrongly reports 82C686A
+			 * as 586-compatible
+			 */
+			device = PCI_DEVICE_ID_VIA_82C686;
+			break;
+		case PCI_DEVICE_ID_VIA_8235:
+			/**
+			 * Asus a7v-x bios wrongly reports 8235
+			 * as 586-compatible
+			 */
+			device = PCI_DEVICE_ID_VIA_8235;
+			break;
+		case PCI_DEVICE_ID_VIA_8237:
+			/**
+			 * Asus a7v600 bios wrongly reports 8237
+			 * as 586-compatible
+			 */
+			device = PCI_DEVICE_ID_VIA_8237;
+			break;
+		}
+	}
+
+	switch (device) {
+	case PCI_DEVICE_ID_VIA_82C586_0:
+		r->name = "VIA";
+		r->get = pirq_via586_get;
+		r->set = pirq_via586_set;
+		return 1;
+	case PCI_DEVICE_ID_VIA_82C596:
+	case PCI_DEVICE_ID_VIA_82C686:
+	case PCI_DEVICE_ID_VIA_8231:
+	case PCI_DEVICE_ID_VIA_8233A:
+	case PCI_DEVICE_ID_VIA_8235:
+	case PCI_DEVICE_ID_VIA_8237:
+		/* FIXME: add new ones for 8233/5 */
+		r->name = "VIA";
+		r->get = pirq_via_get;
+		r->set = pirq_via_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_VLSI_82C534:
+		r->name = "VLSI 82C534";
+		r->get = pirq_vlsi_get;
+		r->set = pirq_vlsi_set;
+		return 1;
+	}
+	return 0;
+}
+
+
+static __init int serverworks_router_probe(struct irq_router *r,
+		struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_SERVERWORKS_OSB4:
+	case PCI_DEVICE_ID_SERVERWORKS_CSB5:
+		r->name = "ServerWorks";
+		r->get = pirq_serverworks_get;
+		r->set = pirq_serverworks_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	if (device != PCI_DEVICE_ID_SI_503)
+		return 0;
+
+	r->name = "SIS";
+	r->get = pirq_sis_get;
+	r->set = pirq_sis_set;
+	return 1;
+}
+
+static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_CYRIX_5520:
+		r->name = "NatSemi";
+		r->get = pirq_cyrix_get;
+		r->set = pirq_cyrix_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_OPTI_82C700:
+		r->name = "OPTI";
+		r->get = pirq_opti_get;
+		r->set = pirq_opti_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_ITE_IT8330G_0:
+		r->name = "ITE";
+		r->get = pirq_ite_get;
+		r->set = pirq_ite_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_AL_M1533:
+	case PCI_DEVICE_ID_AL_M1563:
+		r->name = "ALI";
+		r->get = pirq_ali_get;
+		r->set = pirq_ali_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_AMD_VIPER_740B:
+		r->name = "AMD756";
+		break;
+	case PCI_DEVICE_ID_AMD_VIPER_7413:
+		r->name = "AMD766";
+		break;
+	case PCI_DEVICE_ID_AMD_VIPER_7443:
+		r->name = "AMD768";
+		break;
+	default:
+		return 0;
+	}
+	r->get = pirq_amd756_get;
+	r->set = pirq_amd756_set;
+	return 1;
+}
+
+static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
+{
+	switch (device) {
+	case PCI_DEVICE_ID_PICOPOWER_PT86C523:
+		r->name = "PicoPower PT86C523";
+		r->get = pirq_pico_get;
+		r->set = pirq_pico_set;
+		return 1;
+
+	case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP:
+		r->name = "PicoPower PT86C523 rev. BB+";
+		r->get = pirq_pico_get;
+		r->set = pirq_pico_set;
+		return 1;
+	}
+	return 0;
+}
+
+static __initdata struct irq_router_handler pirq_routers[] = {
+	{ PCI_VENDOR_ID_INTEL, intel_router_probe },
+	{ PCI_VENDOR_ID_AL, ali_router_probe },
+	{ PCI_VENDOR_ID_ITE, ite_router_probe },
+	{ PCI_VENDOR_ID_VIA, via_router_probe },
+	{ PCI_VENDOR_ID_OPTI, opti_router_probe },
+	{ PCI_VENDOR_ID_SI, sis_router_probe },
+	{ PCI_VENDOR_ID_CYRIX, cyrix_router_probe },
+	{ PCI_VENDOR_ID_VLSI, vlsi_router_probe },
+	{ PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
+	{ PCI_VENDOR_ID_AMD, amd_router_probe },
+	{ PCI_VENDOR_ID_PICOPOWER, pico_router_probe },
+	/* Someone with docs needs to add the ATI Radeon IGP */
+	{ 0, NULL }
+};
+static struct irq_router pirq_router;
+static struct pci_dev *pirq_router_dev;
+
+
+/*
+ *	FIXME: should we have an option to say "generic for
+ *	chipset" ?
+ */
+
+static void __init pirq_find_router(struct irq_router *r)
+{
+	struct irq_routing_table *rt = pirq_table;
+	struct irq_router_handler *h;
+
+#ifdef CONFIG_PCI_BIOS
+	if (!rt->signature) {
+		printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n");
+		r->set = pirq_bios_set;
+		r->name = "BIOS";
+		return;
+	}
+#endif
+
+	/* Default unless a driver reloads it */
+	r->name = "default";
+	r->get = NULL;
+	r->set = NULL;
+
+	DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for [%04x:%04x]\n",
+	    rt->rtr_vendor, rt->rtr_device);
+
+	pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn);
+	if (!pirq_router_dev) {
+		DBG(KERN_DEBUG "PCI: Interrupt router not found at "
+			"%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+		return;
+	}
+
+	for (h = pirq_routers; h->vendor; h++) {
+		/* First look for a router match */
+		if (rt->rtr_vendor == h->vendor &&
+			h->probe(r, pirq_router_dev, rt->rtr_device))
+			break;
+		/* Fall back to a device match */
+		if (pirq_router_dev->vendor == h->vendor &&
+			h->probe(r, pirq_router_dev, pirq_router_dev->device))
+			break;
+	}
+	dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n",
+		 pirq_router.name,
+		 pirq_router_dev->vendor, pirq_router_dev->device);
+
+	/* The device remains referenced for the kernel lifetime */
+}
+
+static struct irq_info *pirq_get_info(struct pci_dev *dev)
+{
+	struct irq_routing_table *rt = pirq_table;
+	int entries = (rt->size - sizeof(struct irq_routing_table)) /
+		sizeof(struct irq_info);
+	struct irq_info *info;
+
+	for (info = rt->slots; entries--; info++)
+		if (info->bus == dev->bus->number &&
+			PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
+			return info;
+	return NULL;
+}
+
+static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
+{
+	u8 pin;
+	struct irq_info *info;
+	int i, pirq, newirq;
+	int irq = 0;
+	u32 mask;
+	struct irq_router *r = &pirq_router;
+	struct pci_dev *dev2 = NULL;
+	char *msg = NULL;
+
+	/* Find IRQ pin */
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (!pin) {
+		dev_dbg(&dev->dev, "no interrupt pin\n");
+		return 0;
+	}
+
+	if (io_apic_assign_pci_irqs)
+		return 0;
+
+	/* Find IRQ routing entry */
+
+	if (!pirq_table)
+		return 0;
+
+	info = pirq_get_info(dev);
+	if (!info) {
+		dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
+			'A' + pin - 1);
+		return 0;
+	}
+	pirq = info->irq[pin - 1].link;
+	mask = info->irq[pin - 1].bitmap;
+	if (!pirq) {
+		dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1);
+		return 0;
+	}
+	dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
+		'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs);
+	mask &= pcibios_irq_mask;
+
+	/* Work around broken HP Pavilion Notebooks which assign USB to
+	   IRQ 9 even though it is actually wired to IRQ 11 */
+
+	if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		r->set(pirq_router_dev, dev, pirq, 11);
+	}
+
+	/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
+	if (acer_tm360_irqrouting && dev->irq == 11 &&
+		dev->vendor == PCI_VENDOR_ID_O2) {
+		pirq = 0x68;
+		mask = 0x400;
+		dev->irq = r->get(pirq_router_dev, dev, pirq);
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+
+	/*
+	 * Find the best IRQ to assign: use the one
+	 * reported by the device if possible.
+	 */
+	newirq = dev->irq;
+	if (newirq && !((1 << newirq) & mask)) {
+		if (pci_probe & PCI_USE_PIRQ_MASK)
+			newirq = 0;
+		else
+			dev_warn(&dev->dev, "IRQ %d doesn't match PIRQ mask "
+				 "%#x; try pci=usepirqmask\n", newirq, mask);
+	}
+	if (!newirq && assign) {
+		for (i = 0; i < 16; i++) {
+			if (!(mask & (1 << i)))
+				continue;
+			if (pirq_penalty[i] < pirq_penalty[newirq] &&
+				can_request_irq(i, IRQF_SHARED))
+				newirq = i;
+		}
+	}
+	dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq);
+
+	/* Check if it is hardcoded */
+	if ((pirq & 0xf0) == 0xf0) {
+		irq = pirq & 0xf;
+		msg = "hardcoded";
+	} else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
+	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask))) {
+		msg = "found";
+		eisa_set_level_irq(irq);
+	} else if (newirq && r->set &&
+		(dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
+			eisa_set_level_irq(newirq);
+			msg = "assigned";
+			irq = newirq;
+		}
+	}
+
+	if (!irq) {
+		if (newirq && mask == (1 << newirq)) {
+			msg = "guessed";
+			irq = newirq;
+		} else {
+			dev_dbg(&dev->dev, "can't route interrupt\n");
+			return 0;
+		}
+	}
+	dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
+
+	/* Update IRQ for all devices with the same pirq value */
+	while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
+		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
+		if (!pin)
+			continue;
+
+		info = pirq_get_info(dev2);
+		if (!info)
+			continue;
+		if (info->irq[pin - 1].link == pirq) {
+			/*
+			 * We refuse to override the dev->irq
+			 * information. Give a warning!
+			 */
+			if (dev2->irq && dev2->irq != irq && \
+			(!(pci_probe & PCI_USE_PIRQ_MASK) || \
+			((1 << dev2->irq) & mask))) {
+#ifndef CONFIG_PCI_MSI
+				dev_info(&dev2->dev, "IRQ routing conflict: "
+					 "have IRQ %d, want IRQ %d\n",
+					 dev2->irq, irq);
+#endif
+				continue;
+			}
+			dev2->irq = irq;
+			pirq_penalty[irq]++;
+			if (dev != dev2)
+				dev_info(&dev->dev, "sharing IRQ %d with %s\n",
+					 irq, pci_name(dev2));
+		}
+	}
+	return 1;
+}
+
+static void __init pcibios_fixup_irqs(void)
+{
+	struct pci_dev *dev = NULL;
+	u8 pin;
+
+	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		/*
+		 * If the BIOS has set an out of range IRQ number, just
+		 * ignore it.  Also keep track of which IRQ's are
+		 * already in use.
+		 */
+		if (dev->irq >= 16) {
+			dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
+			dev->irq = 0;
+		}
+		/*
+		 * If the IRQ is already assigned to a PCI device,
+		 * ignore its ISA use penalty
+		 */
+		if (pirq_penalty[dev->irq] >= 100 &&
+				pirq_penalty[dev->irq] < 100000)
+			pirq_penalty[dev->irq] = 0;
+		pirq_penalty[dev->irq]++;
+	}
+
+	if (io_apic_assign_pci_irqs)
+		return;
+
+	dev = NULL;
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (!pin)
+			continue;
+
+		/*
+		 * Still no IRQ? Try to lookup one...
+		 */
+		if (!dev->irq)
+			pcibios_lookup_irq(dev, 0);
+	}
+}
+
+/*
+ * Work around broken HP Pavilion Notebooks which assign USB to
+ * IRQ 9 even though it is actually wired to IRQ 11
+ */
+static int __init fix_broken_hp_bios_irq9(const struct dmi_system_id *d)
+{
+	if (!broken_hp_bios_irq9) {
+		broken_hp_bios_irq9 = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
+			d->ident);
+	}
+	return 0;
+}
+
+/*
+ * Work around broken Acer TravelMate 360 Notebooks which assign
+ * Cardbus to IRQ 11 even though it is actually wired to IRQ 10
+ */
+static int __init fix_acer_tm360_irqrouting(const struct dmi_system_id *d)
+{
+	if (!acer_tm360_irqrouting) {
+		acer_tm360_irqrouting = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n",
+			d->ident);
+	}
+	return 0;
+}
+
+static struct dmi_system_id __initdata pciirq_dmi_table[] = {
+	{
+		.callback = fix_broken_hp_bios_irq9,
+		.ident = "HP Pavilion N5400 Series Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+			DMI_MATCH(DMI_PRODUCT_VERSION,
+				"HP Pavilion Notebook Model GE"),
+			DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+		},
+	},
+	{
+		.callback = fix_acer_tm360_irqrouting,
+		.ident = "Acer TravelMate 36x Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+		},
+	},
+	{ }
+};
+
+int __init pcibios_irq_init(void)
+{
+	DBG(KERN_DEBUG "PCI: IRQ init\n");
+
+	if (pcibios_enable_irq || raw_pci_ops == NULL)
+		return 0;
+
+	dmi_check_system(pciirq_dmi_table);
+
+	pirq_table = pirq_find_routing_table();
+
+#ifdef CONFIG_PCI_BIOS
+	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
+		pirq_table = pcibios_get_irq_routing_table();
+#endif
+	if (pirq_table) {
+		pirq_peer_trick();
+		pirq_find_router(&pirq_router);
+		if (pirq_table->exclusive_irqs) {
+			int i;
+			for (i = 0; i < 16; i++)
+				if (!(pirq_table->exclusive_irqs & (1 << i)))
+					pirq_penalty[i] += 100;
+		}
+		/*
+		 * If we're using the I/O APIC, avoid using the PCI IRQ
+		 * routing table
+		 */
+		if (io_apic_assign_pci_irqs)
+			pirq_table = NULL;
+	}
+
+	pcibios_enable_irq = pirq_enable_irq;
+
+	pcibios_fixup_irqs();
+
+	if (io_apic_assign_pci_irqs && pci_routeirq) {
+		struct pci_dev *dev = NULL;
+		/*
+		 * PCI IRQ routing is set up by pci_enable_device(), but we
+		 * also do it here in case there are still broken drivers that
+		 * don't use pci_enable_device().
+		 */
+		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+		for_each_pci_dev(dev)
+			pirq_enable_irq(dev);
+	}
+
+	return 0;
+}
+
+static void pirq_penalize_isa_irq(int irq, int active)
+{
+	/*
+	 *  If any ISAPnP device reports an IRQ in its list of possible
+	 *  IRQ's, we try to avoid assigning it to PCI devices.
+	 */
+	if (irq < 16) {
+		if (active)
+			pirq_penalty[irq] += 1000;
+		else
+			pirq_penalty[irq] += 100;
+	}
+}
+
+void pcibios_penalize_isa_irq(int irq, int active)
+{
+#ifdef CONFIG_ACPI
+	if (!acpi_noirq)
+		acpi_penalize_isa_irq(irq, active);
+	else
+#endif
+		pirq_penalize_isa_irq(irq, active);
+}
+
+static int pirq_enable_irq(struct pci_dev *dev)
+{
+	u8 pin;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (pin && !pcibios_lookup_irq(dev, 1)) {
+		char *msg = "";
+
+		if (!io_apic_assign_pci_irqs && dev->irq)
+			return 0;
+
+		if (io_apic_assign_pci_irqs) {
+#ifdef CONFIG_X86_IO_APIC
+			struct pci_dev *temp_dev;
+			int irq;
+			struct io_apic_irq_attr irq_attr;
+
+			irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
+						PCI_SLOT(dev->devfn),
+						pin - 1, &irq_attr);
+			/*
+			 * Busses behind bridges are typically not listed in the MP-table.
+			 * In this case we have to look up the IRQ based on the parent bus,
+			 * parent slot, and pin number. The SMP code detects such bridged
+			 * busses itself so we should get into this branch reliably.
+			 */
+			temp_dev = dev;
+			while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+				struct pci_dev *bridge = dev->bus->self;
+
+				pin = pci_swizzle_interrupt_pin(dev, pin);
+				irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+						PCI_SLOT(bridge->devfn),
+						pin - 1, &irq_attr);
+				if (irq >= 0)
+					dev_warn(&dev->dev, "using bridge %s "
+						 "INT %c to get IRQ %d\n",
+						 pci_name(bridge), 'A' + pin - 1,
+						 irq);
+				dev = bridge;
+			}
+			dev = temp_dev;
+			if (irq >= 0) {
+				io_apic_set_pci_routing(&dev->dev, irq,
+							 &irq_attr);
+				dev->irq = irq;
+				dev_info(&dev->dev, "PCI->APIC IRQ transform: "
+					 "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
+				return 0;
+			} else
+				msg = "; probably buggy MP table";
+#endif
+		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+			msg = "";
+		else
+			msg = "; please try using pci=biosirq";
+
+		/*
+		 * With IDE legacy devices the IRQ lookup failure is not
+		 * a problem..
+		 */
+		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
+				!(dev->class & 0x5))
+			return 0;
+
+		dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
+			 'A' + pin - 1, msg);
+	}
+	return 0;
+}
--- linux-ec2-2.6.32.orig/arch/x86/pci/pcifront.c
+++ linux-ec2-2.6.32/arch/x86/pci/pcifront.c
@@ -0,0 +1,59 @@
+/*
+ * PCI Frontend Stub - puts some "dummy" functions in to the Linux x86 PCI core
+ *                     to support the Xen PCI Frontend's operation
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <asm/acpi.h>
+#include <asm/pci_x86.h>
+#include <xen/evtchn.h>
+
+static int pcifront_enable_irq(struct pci_dev *dev)
+{
+	u8 irq;
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+	irq_to_desc_alloc_node(irq, numa_node_id());
+	evtchn_register_pirq(irq);
+	dev->irq = irq;
+
+	return 0;
+}
+
+extern u8 pci_cache_line_size;
+
+static int __init pcifront_x86_stub_init(void)
+{
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	/* Only install our method if we haven't found real hardware already */
+	if (raw_pci_ops)
+		return 0;
+
+	printk(KERN_INFO "PCI: setting up Xen PCI frontend stub\n");
+
+	/* Copied from arch/i386/pci/common.c */
+	pci_cache_line_size = 32 >> 2;
+	if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD)
+		pci_cache_line_size = 64 >> 2;	/* K7 & K8 */
+	else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL)
+		pci_cache_line_size = 128 >> 2;	/* P4 */
+
+	/* On x86, we need to disable the normal IRQ routing table and
+	 * just ask the backend
+	 */
+	pcibios_enable_irq = pcifront_enable_irq;
+	pcibios_disable_irq = NULL;
+
+#ifdef CONFIG_ACPI
+	/* Keep ACPI out of the picture */
+	acpi_noirq = 1;
+#endif
+
+	return 0;
+}
+
+arch_initcall(pcifront_x86_stub_init);
--- linux-ec2-2.6.32.orig/arch/x86/pci/Makefile
+++ linux-ec2-2.6.32/arch/x86/pci/Makefile
@@ -4,6 +4,9 @@
 obj-$(CONFIG_PCI_MMCONFIG)	+= mmconfig_$(BITS).o direct.o mmconfig-shared.o
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 obj-$(CONFIG_PCI_OLPC)		+= olpc.o
+# pcifront should be after 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
 
 obj-y				+= fixup.o
 obj-$(CONFIG_ACPI)		+= acpi.o
--- linux-ec2-2.6.32.orig/arch/x86/pci/irq.c
+++ linux-ec2-2.6.32/arch/x86/pci/irq.c
@@ -590,6 +590,8 @@
 	case PCI_DEVICE_ID_INTEL_ICH10_1:
 	case PCI_DEVICE_ID_INTEL_ICH10_2:
 	case PCI_DEVICE_ID_INTEL_ICH10_3:
+	case PCI_DEVICE_ID_INTEL_CPT_LPC1:
+	case PCI_DEVICE_ID_INTEL_CPT_LPC2:
 		r->name = "PIIX/ICH";
 		r->get = pirq_piix_get;
 		r->set = pirq_piix_set;
--- linux-ec2-2.6.32.orig/arch/x86/pci/amd_bus.c
+++ linux-ec2-2.6.32/arch/x86/pci/amd_bus.c
@@ -553,6 +553,14 @@
 	for_each_online_cpu(cpu)
 		amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
 			       (void *)(long)cpu);
+#ifdef CONFIG_XEN
+	{
+		u64 reg;
+		rdmsrl(MSR_AMD64_NB_CFG, reg);
+		if (!(reg & ENABLE_CF8_EXT_CFG))
+			return 0;
+	}
+#endif
 	pci_probe |= PCI_HAS_IO_ECS;
 
 	return 0;
@@ -560,6 +568,10 @@
 
 static int __init amd_postcore_init(void)
 {
+#ifdef CONFIG_XEN
+	if (!is_initial_xendomain())
+		return 0;
+#endif
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 		return 0;
 
--- linux-ec2-2.6.32.orig/arch/x86/pci/i386.c
+++ linux-ec2-2.6.32/arch/x86/pci/i386.c
@@ -228,12 +228,14 @@
 	pcibios_allocate_resources(1);
 
 	e820_reserve_resources_late();
+#ifndef CONFIG_XEN
 	/*
 	 * Insert the IO APIC resources after PCI initialization has
 	 * occured to handle IO APICS that are mapped in on a BAR in
 	 * PCI space, but before trying to assign unassigned pci res.
 	 */
 	ioapic_insert_resources();
+#endif
 }
 
 /**
@@ -282,6 +284,15 @@
 		return -EINVAL;
 
 	prot = pgprot_val(vma->vm_page_prot);
+
+	/*
+ 	 * Return error if pat is not enabled and write_combine is requested.
+ 	 * Caller can followup with UC MINUS request and add a WC mtrr if there
+ 	 * is a free mtrr slot.
+ 	 */
+	if (!pat_enabled && write_combine)
+		return -EINVAL;
+
 	if (pat_enabled && write_combine)
 		prot |= _PAGE_CACHE_WC;
 	else if (pat_enabled || boot_cpu_data.x86 > 3)
--- linux-ec2-2.6.32.orig/arch/x86/kvm/lapic.c
+++ linux-ec2-2.6.32/arch/x86/kvm/lapic.c
@@ -374,6 +374,12 @@
 		if (unlikely(!apic_enabled(apic)))
 			break;
 
+		if (trig_mode) {
+			apic_debug("level trig mode for vector %d", vector);
+			apic_set_vector(vector, apic->regs + APIC_TMR);
+		} else
+			apic_clear_vector(vector, apic->regs + APIC_TMR);
+
 		result = !apic_test_and_set_irr(vector, apic);
 		trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
 					  trig_mode, vector, !result);
@@ -384,11 +390,6 @@
 			break;
 		}
 
-		if (trig_mode) {
-			apic_debug("level trig mode for vector %d", vector);
-			apic_set_vector(vector, apic->regs + APIC_TMR);
-		} else
-			apic_clear_vector(vector, apic->regs + APIC_TMR);
 		kvm_vcpu_kick(vcpu);
 		break;
 
@@ -1156,6 +1157,7 @@
 	hrtimer_cancel(&apic->lapic_timer.timer);
 	update_divide_count(apic);
 	start_apic_timer(apic);
+	apic->irr_pending = true;
 }
 
 void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
--- linux-ec2-2.6.32.orig/arch/x86/kvm/vmx.c
+++ linux-ec2-2.6.32/arch/x86/kvm/vmx.c
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
 #include <linux/ftrace_event.h>
+#include <linux/tboot.h>
 #include "kvm_cache_regs.h"
 #include "x86.h"
 
@@ -61,6 +62,27 @@
 static int __read_mostly emulate_invalid_guest_state = 0;
 module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
+/*
+ * These 2 parameters are used to config the controls for Pause-Loop Exiting:
+ * ple_gap:    upper bound on the amount of time between two successive
+ *             executions of PAUSE in a loop. Also indicate if ple enabled.
+ *             According to test, this time is usually small than 41 cycles.
+ * ple_window: upper bound on the amount of time a guest is allowed to execute
+ *             in a PAUSE loop. Tests indicate that most spinlocks are held for
+ *             less than 2^12 cycles
+ * Time is measured based on a counter that runs at the same rate as the TSC,
+ * refer SDM volume 3b section 21.6.13 & 22.1.3.
+ */
+#define KVM_VMX_DEFAULT_PLE_GAP    41
+#define KVM_VMX_DEFAULT_PLE_WINDOW 4096
+static int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
+module_param(ple_gap, int, S_IRUGO);
+
+static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
+module_param(ple_window, int, S_IRUGO);
+
+#define RMODE_GUEST_OWNED_EFLAGS_BITS (~(X86_EFLAGS_IOPL | X86_EFLAGS_VM))
+
 struct vmcs {
 	u32 revision_id;
 	u32 abort;
@@ -92,7 +114,7 @@
 	} host_state;
 	struct {
 		int vm86_active;
-		u8 save_iopl;
+		ulong save_rflags;
 		struct kvm_save_segment {
 			u16 selector;
 			unsigned long base;
@@ -127,6 +149,7 @@
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
 static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
+static DEFINE_PER_CPU(struct desc_ptr, host_gdt);
 
 static unsigned long *vmx_io_bitmap_a;
 static unsigned long *vmx_io_bitmap_b;
@@ -320,6 +343,12 @@
 		SECONDARY_EXEC_UNRESTRICTED_GUEST;
 }
 
+static inline int cpu_has_vmx_ple(void)
+{
+	return vmcs_config.cpu_based_2nd_exec_ctrl &
+		SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+}
+
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
 {
 	return flexpriority_enabled &&
@@ -625,7 +654,7 @@
 	 */
 	vmx->host_state.ldt_sel = kvm_read_ldt();
 	vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
-	vmx->host_state.fs_sel = kvm_read_fs();
+	savesegment(fs, vmx->host_state.fs_sel);
 	if (!(vmx->host_state.fs_sel & 7)) {
 		vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
 		vmx->host_state.fs_reload_needed = 0;
@@ -633,7 +662,7 @@
 		vmcs_write16(HOST_FS_SELECTOR, 0);
 		vmx->host_state.fs_reload_needed = 1;
 	}
-	vmx->host_state.gs_sel = kvm_read_gs();
+	savesegment(gs, vmx->host_state.gs_sel);
 	if (!(vmx->host_state.gs_sel & 7))
 		vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
 	else {
@@ -650,10 +679,7 @@
 #endif
 
 #ifdef CONFIG_X86_64
-	if (is_long_mode(&vmx->vcpu))
-		save_msrs(vmx->host_msrs +
-			  vmx->msr_offset_kernel_gs_base, 1);
-
+	save_msrs(vmx->host_msrs + vmx->msr_offset_kernel_gs_base, 1);
 #endif
 	load_msrs(vmx->guest_msrs, vmx->save_nmsrs);
 	load_transition_efer(vmx);
@@ -661,32 +687,36 @@
 
 static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 {
-	unsigned long flags;
-
 	if (!vmx->host_state.loaded)
 		return;
 
 	++vmx->vcpu.stat.host_state_reload;
 	vmx->host_state.loaded = 0;
-	if (vmx->host_state.fs_reload_needed)
-		kvm_load_fs(vmx->host_state.fs_sel);
+#ifdef CONFIG_X86_64
+	if (is_long_mode(&vmx->vcpu))
+		save_msrs(vmx->guest_msrs + vmx->msr_offset_kernel_gs_base, 1);
+#endif
 	if (vmx->host_state.gs_ldt_reload_needed) {
 		kvm_load_ldt(vmx->host_state.ldt_sel);
-		/*
-		 * If we have to reload gs, we must take care to
-		 * preserve our gs base.
-		 */
-		local_irq_save(flags);
-		kvm_load_gs(vmx->host_state.gs_sel);
 #ifdef CONFIG_X86_64
-		wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
+		load_gs_index(vmx->host_state.gs_sel);
+#else
+		loadsegment(gs, vmx->host_state.gs_sel);
 #endif
-		local_irq_restore(flags);
 	}
+	if (vmx->host_state.fs_reload_needed)
+		loadsegment(fs, vmx->host_state.fs_sel);
 	reload_tss();
+#ifdef CONFIG_X86_64
+	save_msrs(vmx->guest_msrs, vmx->msr_offset_kernel_gs_base);
+	save_msrs(vmx->guest_msrs + vmx->msr_offset_kernel_gs_base + 1,
+		  vmx->save_nmsrs - vmx->msr_offset_kernel_gs_base - 1);
+#else
 	save_msrs(vmx->guest_msrs, vmx->save_nmsrs);
+#endif
 	load_msrs(vmx->host_msrs, vmx->save_nmsrs);
 	reload_host_efer(vmx);
+	load_gdt(&__get_cpu_var(host_gdt));
 }
 
 static void vmx_load_host_state(struct vcpu_vmx *vmx)
@@ -783,18 +813,23 @@
 
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
 {
-	unsigned long rflags;
+	unsigned long rflags, save_rflags;
 
 	rflags = vmcs_readl(GUEST_RFLAGS);
-	if (to_vmx(vcpu)->rmode.vm86_active)
-		rflags &= ~(unsigned long)(X86_EFLAGS_IOPL | X86_EFLAGS_VM);
+	if (to_vmx(vcpu)->rmode.vm86_active) {
+		rflags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
+		save_rflags = to_vmx(vcpu)->rmode.save_rflags;
+		rflags |= save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
+	}
 	return rflags;
 }
 
 static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
-	if (to_vmx(vcpu)->rmode.vm86_active)
+	if (to_vmx(vcpu)->rmode.vm86_active) {
+		to_vmx(vcpu)->rmode.save_rflags = rflags;
 		rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
+	}
 	vmcs_writel(GUEST_RFLAGS, rflags);
 }
 
@@ -1133,9 +1168,16 @@
 	u64 msr;
 
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
-	return (msr & (FEATURE_CONTROL_LOCKED |
-		       FEATURE_CONTROL_VMXON_ENABLED))
-	    == FEATURE_CONTROL_LOCKED;
+	if (msr & FEATURE_CONTROL_LOCKED) {
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
+			&& tboot_enabled())
+			return 1;
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& !tboot_enabled())
+			return 1;
+	}
+
+	return 0;
 	/* locked but not enabled */
 }
 
@@ -1143,22 +1185,26 @@
 {
 	int cpu = raw_smp_processor_id();
 	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
-	u64 old;
+	u64 old, test_bits;
 
 	INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu));
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
-	if ((old & (FEATURE_CONTROL_LOCKED |
-		    FEATURE_CONTROL_VMXON_ENABLED))
-	    != (FEATURE_CONTROL_LOCKED |
-		FEATURE_CONTROL_VMXON_ENABLED))
+
+	test_bits = FEATURE_CONTROL_LOCKED;
+	test_bits |= FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+	if (tboot_enabled())
+		test_bits |= FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX;
+
+	if ((old & test_bits) != test_bits) {
 		/* enable and lock */
-		wrmsrl(MSR_IA32_FEATURE_CONTROL, old |
-		       FEATURE_CONTROL_LOCKED |
-		       FEATURE_CONTROL_VMXON_ENABLED);
+		wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits);
+	}
 	write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug safe */
 	asm volatile (ASM_VMX_VMXON_RAX
 		      : : "a"(&phys_addr), "m"(phys_addr)
 		      : "memory", "cc");
+
+	store_gdt(&__get_cpu_var(host_gdt));
 }
 
 static void vmclear_local_vcpus(void)
@@ -1250,7 +1296,8 @@
 			SECONDARY_EXEC_WBINVD_EXITING |
 			SECONDARY_EXEC_ENABLE_VPID |
 			SECONDARY_EXEC_ENABLE_EPT |
-			SECONDARY_EXEC_UNRESTRICTED_GUEST;
+			SECONDARY_EXEC_UNRESTRICTED_GUEST |
+			SECONDARY_EXEC_PAUSE_LOOP_EXITING;
 		if (adjust_vmx_controls(min2, opt2,
 					MSR_IA32_VMX_PROCBASED_CTLS2,
 					&_cpu_based_2nd_exec_control) < 0)
@@ -1394,6 +1441,9 @@
 	if (enable_ept && !cpu_has_vmx_ept_2m_page())
 		kvm_disable_largepages();
 
+	if (!cpu_has_vmx_ple())
+		ple_gap = 0;
+
 	return alloc_kvm_area();
 }
 
@@ -1431,8 +1481,8 @@
 	vmcs_write32(GUEST_TR_AR_BYTES, vmx->rmode.tr.ar);
 
 	flags = vmcs_readl(GUEST_RFLAGS);
-	flags &= ~(X86_EFLAGS_IOPL | X86_EFLAGS_VM);
-	flags |= (vmx->rmode.save_iopl << IOPL_SHIFT);
+	flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
+	flags |= vmx->rmode.save_rflags & ~RMODE_GUEST_OWNED_EFLAGS_BITS;
 	vmcs_writel(GUEST_RFLAGS, flags);
 
 	vmcs_writel(GUEST_CR4, (vmcs_readl(GUEST_CR4) & ~X86_CR4_VME) |
@@ -1501,8 +1551,7 @@
 	vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
 
 	flags = vmcs_readl(GUEST_RFLAGS);
-	vmx->rmode.save_iopl
-		= (flags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+	vmx->rmode.save_rflags = flags;
 
 	flags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
 
@@ -2302,13 +2351,22 @@
 				~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
 		if (vmx->vpid == 0)
 			exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
-		if (!enable_ept)
+		if (!enable_ept) {
 			exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+			enable_unrestricted_guest = 0;
+		}
 		if (!enable_unrestricted_guest)
 			exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+		if (!ple_gap)
+			exec_control &= ~SECONDARY_EXEC_PAUSE_LOOP_EXITING;
 		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
 	}
 
+	if (ple_gap) {
+		vmcs_write32(PLE_GAP, ple_gap);
+		vmcs_write32(PLE_WINDOW, ple_window);
+	}
+
 	vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf);
 	vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
 	vmcs_write32(CR3_TARGET_COUNT, 0);           /* 22.2.1 */
@@ -2320,8 +2378,8 @@
 	vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);  /* 22.2.4 */
 	vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 	vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
-	vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs());    /* 22.2.4 */
-	vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs());    /* 22.2.4 */
+	vmcs_write16(HOST_FS_SELECTOR, 0);            /* 22.2.4 */
+	vmcs_write16(HOST_GS_SELECTOR, 0);            /* 22.2.4 */
 	vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS);  /* 22.2.4 */
 #ifdef CONFIG_X86_64
 	rdmsrl(MSR_FS_BASE, a);
@@ -2510,7 +2568,7 @@
 	if (vmx->vpid != 0)
 		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
-	vmx->vcpu.arch.cr0 = 0x60000010;
+	vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
 	vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
 	vmx_set_cr4(&vmx->vcpu, 0);
 	vmx_set_efer(&vmx->vcpu, 0);
@@ -2674,6 +2732,12 @@
 		kvm_queue_exception(vcpu, vec);
 		return 1;
 	case BP_VECTOR:
+		/*
+		 * Update instruction length as we may reinject the exception
+		 * from user space while in guest debugging mode.
+		 */
+		to_vmx(vcpu)->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
 			return 0;
 		/* fall through */
@@ -2790,6 +2854,13 @@
 		kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
 		/* fall through */
 	case BP_VECTOR:
+		/*
+		 * Update instruction length as we may reinject #BP from
+		 * user space while in guest debugging mode. Reading it for
+		 * #DB as well causes no harm, it is not used in that case.
+		 */
+		vmx->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
 		kvm_run->exit_reason = KVM_EXIT_DEBUG;
 		kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
 		kvm_run->debug.arch.exception = ex_no;
@@ -3358,6 +3429,18 @@
 }
 
 /*
+ * Indicate a busy-waiting vcpu in spinlock. We do not enable the PAUSE
+ * exiting, so only get here on cpu with PAUSE-Loop-Exiting.
+ */
+static int handle_pause(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	skip_emulated_instruction(vcpu);
+	kvm_vcpu_on_spin(vcpu);
+
+	return 1;
+}
+
+/*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
  * to be done to userspace and return 0.
@@ -3394,6 +3477,7 @@
 	[EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
 	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
 	[EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
+	[EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
 };
 
 static const int kvm_vmx_max_exit_handlers =
--- linux-ec2-2.6.32.orig/arch/x86/kvm/paging_tmpl.h
+++ linux-ec2-2.6.32/arch/x86/kvm/paging_tmpl.h
@@ -150,7 +150,9 @@
 		walker->table_gfn[walker->level - 1] = table_gfn;
 		walker->pte_gpa[walker->level - 1] = pte_gpa;
 
-		kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
+		if (kvm_read_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte)))
+			goto not_present;
+
 		trace_kvm_mmu_paging_element(pte, walker->level);
 
 		if (!is_present_gpte(pte))
@@ -316,8 +318,32 @@
 			break;
 		}
 
-		if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
-			continue;
+		if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) {
+			struct kvm_mmu_page *child;
+			unsigned direct_access;
+
+			if (level != gw->level)
+				continue;
+
+			/*
+			 * For the direct sp, if the guest pte's dirty bit
+			 * changed form clean to dirty, it will corrupt the
+			 * sp's access: allow writable in the read-only sp,
+			 * so we should update the spte at this point to get
+			 * a new sp with the correct access.
+			 */
+			direct_access = gw->pt_access & gw->pte_access;
+			if (!is_dirty_gpte(gw->ptes[gw->level - 1]))
+				direct_access &= ~ACC_WRITE_MASK;
+
+			child = page_header(*sptep & PT64_BASE_ADDR_MASK);
+			if (child->role.access == direct_access)
+				continue;
+
+			mmu_page_remove_parent_pte(child, sptep);
+			__set_spte(sptep, shadow_trap_nonpresent_pte);
+			kvm_flush_remote_tlbs(vcpu->kvm);
+		}
 
 		if (is_large_pte(*sptep)) {
 			rmap_remove(vcpu->kvm, sptep);
@@ -334,6 +360,7 @@
 			/* advance table_gfn when emulating 1gb pages with 4k */
 			if (delta == 0)
 				table_gfn += PT_INDEX(addr, level);
+			access &= gw->pte_access;
 		} else {
 			direct = 0;
 			table_gfn = gw->table_gfn[level - 2];
@@ -455,8 +482,6 @@
 static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
 {
 	struct kvm_shadow_walk_iterator iterator;
-	pt_element_t gpte;
-	gpa_t pte_gpa = -1;
 	int level;
 	u64 *sptep;
 	int need_flush = 0;
@@ -471,10 +496,6 @@
 		if (level == PT_PAGE_TABLE_LEVEL  ||
 		    ((level == PT_DIRECTORY_LEVEL && is_large_pte(*sptep))) ||
 		    ((level == PT_PDPE_LEVEL && is_large_pte(*sptep)))) {
-			struct kvm_mmu_page *sp = page_header(__pa(sptep));
-
-			pte_gpa = (sp->gfn << PAGE_SHIFT);
-			pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
 
 			if (is_shadow_present_pte(*sptep)) {
 				rmap_remove(vcpu->kvm, sptep);
@@ -493,32 +514,25 @@
 	if (need_flush)
 		kvm_flush_remote_tlbs(vcpu->kvm);
 	spin_unlock(&vcpu->kvm->mmu_lock);
-
-	if (pte_gpa == -1)
-		return;
-	if (kvm_read_guest_atomic(vcpu->kvm, pte_gpa, &gpte,
-				  sizeof(pt_element_t)))
-		return;
-	if (is_present_gpte(gpte) && (gpte & PT_ACCESSED_MASK)) {
-		if (mmu_topup_memory_caches(vcpu))
-			return;
-		kvm_mmu_pte_write(vcpu, pte_gpa, (const u8 *)&gpte,
-				  sizeof(pt_element_t), 0);
-	}
 }
 
-static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
+static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
+			       u32 *error)
 {
 	struct guest_walker walker;
 	gpa_t gpa = UNMAPPED_GVA;
 	int r;
 
-	r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
+	r = FNAME(walk_addr)(&walker, vcpu, vaddr,
+			     !!(access & PFERR_WRITE_MASK),
+			     !!(access & PFERR_USER_MASK),
+			     !!(access & PFERR_FETCH_MASK));
 
 	if (r) {
 		gpa = gfn_to_gpa(walker.gfn);
 		gpa |= vaddr & ~PAGE_MASK;
-	}
+	} else if (error)
+		*error = walker.error_code;
 
 	return gpa;
 }
--- linux-ec2-2.6.32.orig/arch/x86/kvm/Kconfig
+++ linux-ec2-2.6.32/arch/x86/kvm/Kconfig
@@ -7,6 +7,7 @@
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
 	depends on HAVE_KVM || X86
+	depends on !XEN
 	default y
 	---help---
 	  Say Y here to get to see options for using your Linux host to run other
--- linux-ec2-2.6.32.orig/arch/x86/kvm/mmu.h
+++ linux-ec2-2.6.32/arch/x86/kvm/mmu.h
@@ -37,6 +37,12 @@
 #define PT32_ROOT_LEVEL 2
 #define PT32E_ROOT_LEVEL 3
 
+#define PFERR_PRESENT_MASK (1U << 0)
+#define PFERR_WRITE_MASK (1U << 1)
+#define PFERR_USER_MASK (1U << 2)
+#define PFERR_RSVD_MASK (1U << 3)
+#define PFERR_FETCH_MASK (1U << 4)
+
 int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
 
 static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
--- linux-ec2-2.6.32.orig/arch/x86/kvm/x86.c
+++ linux-ec2-2.6.32/arch/x86/kvm/x86.c
@@ -47,6 +47,7 @@
 #include <asm/desc.h>
 #include <asm/mtrr.h>
 #include <asm/mce.h>
+#include <asm/pvclock.h>
 
 #define MAX_IO_MSRS 256
 #define CR0_RESERVED_BITS						\
@@ -297,21 +298,16 @@
 void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
 	if (cr0 & CR0_RESERVED_BITS) {
-		printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
-		       cr0, vcpu->arch.cr0);
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
 
 	if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) {
-		printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
 
 	if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) {
-		printk(KERN_DEBUG "set_cr0: #GP, set PG flag "
-		       "and a clear PE flag\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
@@ -322,15 +318,11 @@
 			int cs_db, cs_l;
 
 			if (!is_pae(vcpu)) {
-				printk(KERN_DEBUG "set_cr0: #GP, start paging "
-				       "in long mode while PAE is disabled\n");
 				kvm_inject_gp(vcpu, 0);
 				return;
 			}
 			kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 			if (cs_l) {
-				printk(KERN_DEBUG "set_cr0: #GP, start paging "
-				       "in long mode while CS.L == 1\n");
 				kvm_inject_gp(vcpu, 0);
 				return;
 
@@ -338,8 +330,6 @@
 		} else
 #endif
 		if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.cr3)) {
-			printk(KERN_DEBUG "set_cr0: #GP, pdptrs "
-			       "reserved bits\n");
 			kvm_inject_gp(vcpu, 0);
 			return;
 		}
@@ -356,7 +346,7 @@
 
 void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
-	kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
+	kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0eul) | (msw & 0x0f));
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
@@ -366,28 +356,23 @@
 	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
 
 	if (cr4 & CR4_RESERVED_BITS) {
-		printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
 
 	if (is_long_mode(vcpu)) {
 		if (!(cr4 & X86_CR4_PAE)) {
-			printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while "
-			       "in long mode\n");
 			kvm_inject_gp(vcpu, 0);
 			return;
 		}
 	} else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE)
 		   && ((cr4 ^ old_cr4) & pdptr_bits)
 		   && !load_pdptrs(vcpu, vcpu->arch.cr3)) {
-		printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
 
 	if (cr4 & X86_CR4_VMXE) {
-		printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
@@ -408,21 +393,16 @@
 
 	if (is_long_mode(vcpu)) {
 		if (cr3 & CR3_L_MODE_RESERVED_BITS) {
-			printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
 			kvm_inject_gp(vcpu, 0);
 			return;
 		}
 	} else {
 		if (is_pae(vcpu)) {
 			if (cr3 & CR3_PAE_RESERVED_BITS) {
-				printk(KERN_DEBUG
-				       "set_cr3: #GP, reserved bits\n");
 				kvm_inject_gp(vcpu, 0);
 				return;
 			}
 			if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3)) {
-				printk(KERN_DEBUG "set_cr3: #GP, pdptrs "
-				       "reserved bits\n");
 				kvm_inject_gp(vcpu, 0);
 				return;
 			}
@@ -454,7 +434,6 @@
 void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	if (cr8 & CR8_RESERVED_BITS) {
-		printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
@@ -484,16 +463,19 @@
  * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
  *
  * This list is modified at module load time to reflect the
- * capabilities of the host cpu.
+ * capabilities of the host cpu. This capabilities test skips MSRs that are
+ * kvm-specific. Those are put in the beginning of the list.
  */
+
+#define KVM_SAVE_MSRS_BEGIN	2
 static u32 msrs_to_save[] = {
+	MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
 	MSR_K6_STAR,
 #ifdef CONFIG_X86_64
 	MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
 #endif
-	MSR_IA32_TSC, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
-	MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA
+	MSR_IA32_TSC, MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA
 };
 
 static unsigned num_msrs_to_save;
@@ -502,53 +484,42 @@
 	MSR_IA32_MISC_ENABLE,
 };
 
-static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
+static int set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
-	if (efer & efer_reserved_bits) {
-		printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
-		       efer);
-		kvm_inject_gp(vcpu, 0);
-		return;
-	}
+	if (efer & efer_reserved_bits)
+		return 1;
 
 	if (is_paging(vcpu)
-	    && (vcpu->arch.shadow_efer & EFER_LME) != (efer & EFER_LME)) {
-		printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n");
-		kvm_inject_gp(vcpu, 0);
-		return;
-	}
+	    && (vcpu->arch.shadow_efer & EFER_LME) != (efer & EFER_LME))
+		return 1;
 
 	if (efer & EFER_FFXSR) {
 		struct kvm_cpuid_entry2 *feat;
 
 		feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
-		if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT))) {
-			printk(KERN_DEBUG "set_efer: #GP, enable FFXSR w/o CPUID capability\n");
-			kvm_inject_gp(vcpu, 0);
-			return;
-		}
+		if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT)))
+			return 1;
 	}
 
 	if (efer & EFER_SVME) {
 		struct kvm_cpuid_entry2 *feat;
 
 		feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
-		if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM))) {
-			printk(KERN_DEBUG "set_efer: #GP, enable SVM w/o SVM\n");
-			kvm_inject_gp(vcpu, 0);
-			return;
-		}
+		if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM)))
+			return 1;
 	}
 
-	kvm_x86_ops->set_efer(vcpu, efer);
-
 	efer &= ~EFER_LMA;
 	efer |= vcpu->arch.shadow_efer & EFER_LMA;
 
+	kvm_x86_ops->set_efer(vcpu, efer);
+
 	vcpu->arch.shadow_efer = efer;
 
 	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
 	kvm_mmu_reset_context(vcpu);
+
+	return 0;
 }
 
 void kvm_enable_efer_bits(u64 mask)
@@ -578,14 +549,22 @@
 
 static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 {
-	static int version;
+	int version;
+	int r;
 	struct pvclock_wall_clock wc;
-	struct timespec now, sys, boot;
+	struct timespec boot;
 
 	if (!wall_clock)
 		return;
 
-	version++;
+	r = kvm_read_guest(kvm, wall_clock, &version, sizeof(version));
+	if (r)
+		return;
+
+	if (version & 1)
+		++version;  /* first time write, random junk */
+
+	++version;
 
 	kvm_write_guest(kvm, wall_clock, &version, sizeof(version));
 
@@ -595,9 +574,7 @@
 	 * wall clock specified here.  guest system time equals host
 	 * system time for us, thus we must fill in host boot time here.
 	 */
-	now = current_kernel_time();
-	ktime_get_ts(&sys);
-	boot = ns_to_timespec(timespec_to_ns(&now) - timespec_to_ns(&sys));
+	getboottime(&boot);
 
 	wc.sec = boot.tv_sec;
 	wc.nsec = boot.tv_nsec;
@@ -657,6 +634,8 @@
 	struct kvm_vcpu_arch *vcpu = &v->arch;
 	void *shared_kaddr;
 	unsigned long this_tsc_khz;
+	s64 kernel_ns, max_kernel_ns;
+	u64 tsc_timestamp;
 
 	if ((!vcpu->time_page))
 		return;
@@ -670,14 +649,53 @@
 
 	/* Keep irq disabled to prevent changes to the clock */
 	local_irq_save(flags);
-	kvm_get_msr(v, MSR_IA32_TSC, &vcpu->hv_clock.tsc_timestamp);
+	kvm_get_msr(v, MSR_IA32_TSC, &tsc_timestamp);
 	ktime_get_ts(&ts);
+	monotonic_to_bootbased(&ts);
+	kernel_ns = timespec_to_ns(&ts);
 	local_irq_restore(flags);
 
+	/*
+	 * Time as measured by the TSC may go backwards when resetting the base
+	 * tsc_timestamp.  The reason for this is that the TSC resolution is
+	 * higher than the resolution of the other clock scales.  Thus, many
+	 * possible measurments of the TSC correspond to one measurement of any
+	 * other clock, and so a spread of values is possible.  This is not a
+	 * problem for the computation of the nanosecond clock; with TSC rates
+	 * around 1GHZ, there can only be a few cycles which correspond to one
+	 * nanosecond value, and any path through this code will inevitably
+	 * take longer than that.  However, with the kernel_ns value itself,
+	 * the precision may be much lower, down to HZ granularity.  If the
+	 * first sampling of TSC against kernel_ns ends in the low part of the
+	 * range, and the second in the high end of the range, we can get:
+	 *
+	 * (TSC - offset_low) * S + kns_old > (TSC - offset_high) * S + kns_new
+	 *
+	 * As the sampling errors potentially range in the thousands of cycles,
+	 * it is possible such a time value has already been observed by the
+	 * guest.  To protect against this, we must compute the system time as
+	 * observed by the guest and ensure the new system time is greater.
+	 */
+	max_kernel_ns = 0;
+	if (vcpu->hv_clock.tsc_timestamp && vcpu->last_guest_tsc) {
+		max_kernel_ns = vcpu->last_guest_tsc -
+			vcpu->hv_clock.tsc_timestamp;
+		max_kernel_ns = pvclock_scale_delta(max_kernel_ns,
+				vcpu->hv_clock.tsc_to_system_mul,
+				vcpu->hv_clock.tsc_shift);
+		max_kernel_ns += vcpu->last_kernel_ns;
+	}
+
+	if (max_kernel_ns > kernel_ns)
+		kernel_ns = max_kernel_ns;
+
 	/* With all the info we got, fill in the values */
 
-	vcpu->hv_clock.system_time = ts.tv_nsec +
-				     (NSEC_PER_SEC * (u64)ts.tv_sec);
+	vcpu->hv_clock.tsc_timestamp = tsc_timestamp;
+	vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
+	vcpu->last_kernel_ns = kernel_ns;
+	vcpu->last_guest_tsc = tsc_timestamp;
+
 	/*
 	 * The interface expects us to write an even number signaling that the
 	 * update is finished. Since the guest won't see the intermediate
@@ -823,9 +841,13 @@
 		if (msr >= MSR_IA32_MC0_CTL &&
 		    msr < MSR_IA32_MC0_CTL + 4 * bank_num) {
 			u32 offset = msr - MSR_IA32_MC0_CTL;
-			/* only 0 or all 1s can be written to IA32_MCi_CTL */
+			/* only 0 or all 1s can be written to IA32_MCi_CTL
+			 * some Linux kernels though clear bit 10 in bank 4 to
+			 * workaround a BIOS/GART TBL issue on AMD K8s, ignore
+			 * this to avoid an uncatched #GP in the guest
+			 */
 			if ((offset & 0x3) == 0 &&
-			    data != 0 && data != ~(u64)0)
+			    data != 0 && (data | (1 << 10)) != ~(u64)0)
 				return -1;
 			vcpu->arch.mce_banks[offset] = data;
 			break;
@@ -839,8 +861,7 @@
 {
 	switch (msr) {
 	case MSR_EFER:
-		set_efer(vcpu, data);
-		break;
+		return set_efer(vcpu, data);
 	case MSR_K7_HWCR:
 		data &= ~(u64)0x40;	/* ignore flush filter disable */
 		if (data != 0) {
@@ -1224,6 +1245,7 @@
 	case KVM_CAP_PIT2:
 	case KVM_CAP_PIT_STATE2:
 	case KVM_CAP_SET_IDENTITY_MAP_ADDR:
+	case KVM_CAP_ADJUST_CLOCK:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -1238,8 +1260,8 @@
 	case KVM_CAP_NR_MEMSLOTS:
 		r = KVM_MEMORY_SLOTS;
 		break;
-	case KVM_CAP_PV_MMU:
-		r = !tdp_enabled;
+	case KVM_CAP_PV_MMU:	/* obsolete */
+		r = 0;
 		break;
 	case KVM_CAP_IOMMU:
 		r = iommu_found();
@@ -1431,6 +1453,7 @@
 {
 	int r;
 
+	vcpu_load(vcpu);
 	r = -E2BIG;
 	if (cpuid->nent < vcpu->arch.cpuid_nent)
 		goto out;
@@ -1442,6 +1465,7 @@
 
 out:
 	cpuid->nent = vcpu->arch.cpuid_nent;
+	vcpu_put(vcpu);
 	return r;
 }
 
@@ -1501,7 +1525,7 @@
 	const u32 kvm_supported_word6_x86_features =
 		F(LAHF_LM) | F(CMP_LEGACY) | F(SVM) | 0 /* ExtApicSpace */ |
 		F(CR8_LEGACY) | F(ABM) | F(SSE4A) | F(MISALIGNSSE) |
-		F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(SSE5) |
+		F(3DNOWPREFETCH) | 0 /* OSVW */ | 0 /* IBS */ | F(XOP) |
 		0 /* SKINIT */ | 0 /* WDT */;
 
 	/* all calls to cpuid_count() should be made on the same cpu */
@@ -1691,6 +1715,7 @@
 	int r;
 	unsigned bank_num = mcg_cap & 0xff, bank;
 
+	vcpu_load(vcpu);
 	r = -EINVAL;
 	if (!bank_num || bank_num >= KVM_MAX_MCE_BANKS)
 		goto out;
@@ -1705,6 +1730,7 @@
 	for (bank = 0; bank < bank_num; bank++)
 		vcpu->arch.mce_banks[bank*4] = ~(u64)0;
 out:
+	vcpu_put(vcpu);
 	return r;
 }
 
@@ -1907,7 +1933,9 @@
 		r = -EFAULT;
 		if (copy_from_user(&mce, argp, sizeof mce))
 			goto out;
+		vcpu_load(vcpu);
 		r = kvm_vcpu_ioctl_x86_set_mce(vcpu, &mce);
+		vcpu_put(vcpu);
 		break;
 	}
 	default:
@@ -2114,6 +2142,7 @@
 		sizeof(ps->channels));
 	ps->flags = kvm->arch.vpit->pit_state.flags;
 	mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+	memset(&ps->reserved, 0, sizeof(ps->reserved));
 	return r;
 }
 
@@ -2152,7 +2181,7 @@
 				      struct kvm_dirty_log *log)
 {
 	int r;
-	int n;
+	unsigned long n;
 	struct kvm_memory_slot *memslot;
 	int is_dirty = 0;
 
@@ -2168,7 +2197,7 @@
 		kvm_mmu_slot_remove_write_access(kvm, log->slot);
 		spin_unlock(&kvm->mmu_lock);
 		memslot = &kvm->memslots[log->slot];
-		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+		n = kvm_dirty_bitmap_bytes(memslot);
 		memset(memslot->dirty_bitmap, 0, n);
 	}
 	r = 0;
@@ -2421,6 +2450,45 @@
 		r = 0;
 		break;
 	}
+	case KVM_SET_CLOCK: {
+		struct timespec now;
+		struct kvm_clock_data user_ns;
+		u64 now_ns;
+		s64 delta;
+
+		r = -EFAULT;
+		if (copy_from_user(&user_ns, argp, sizeof(user_ns)))
+			goto out;
+
+		r = -EINVAL;
+		if (user_ns.flags)
+			goto out;
+
+		r = 0;
+		ktime_get_ts(&now);
+		now_ns = timespec_to_ns(&now);
+		delta = user_ns.clock - now_ns;
+		kvm->arch.kvmclock_offset = delta;
+		break;
+	}
+	case KVM_GET_CLOCK: {
+		struct timespec now;
+		struct kvm_clock_data user_ns;
+		u64 now_ns;
+
+		ktime_get_ts(&now);
+		now_ns = timespec_to_ns(&now);
+		user_ns.clock = kvm->arch.kvmclock_offset + now_ns;
+		user_ns.flags = 0;
+		memset(&user_ns.pad, 0, sizeof(user_ns.pad));
+
+		r = -EFAULT;
+		if (copy_to_user(argp, &user_ns, sizeof(user_ns)))
+			goto out;
+		r = 0;
+		break;
+	}
+
 	default:
 		;
 	}
@@ -2433,7 +2501,8 @@
 	u32 dummy[2];
 	unsigned i, j;
 
-	for (i = j = 0; i < ARRAY_SIZE(msrs_to_save); i++) {
+	/* skip the first msrs in the list. KVM-specific */
+	for (i = j = KVM_SAVE_MSRS_BEGIN; i < ARRAY_SIZE(msrs_to_save); i++) {
 		if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
 			continue;
 		if (j < i)
@@ -2462,14 +2531,41 @@
 	return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v);
 }
 
-static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
-			       struct kvm_vcpu *vcpu)
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+ gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	access |= PFERR_FETCH_MASK;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	access |= PFERR_WRITE_MASK;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+/* uses this to access any guest's mapped memory without checking CPL */
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, 0, error);
+}
+
+static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
+				      struct kvm_vcpu *vcpu, u32 access,
+				      u32 *error)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
 
 	while (bytes) {
-		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, access, error);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
@@ -2492,14 +2588,37 @@
 	return r;
 }
 
+/* used for instruction fetching */
+static int kvm_fetch_guest_virt(gva_t addr, void *val, unsigned int bytes,
+				struct kvm_vcpu *vcpu, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
+					  access | PFERR_FETCH_MASK, error);
+}
+
+static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
+			       struct kvm_vcpu *vcpu, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
+					  error);
+}
+
+static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes,
+			       struct kvm_vcpu *vcpu, u32 *error)
+{
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
+}
+
 static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
-				struct kvm_vcpu *vcpu)
+				struct kvm_vcpu *vcpu, u32 *error)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
 
 	while (bytes) {
-		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa_t gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
@@ -2529,6 +2648,7 @@
 				  struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
+	u32 error_code;
 
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
@@ -2538,17 +2658,20 @@
 		return X86EMUL_CONTINUE;
 	}
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+	gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, &error_code);
+
+	if (gpa == UNMAPPED_GVA) {
+		kvm_inject_page_fault(vcpu, addr, error_code);
+		return X86EMUL_PROPAGATE_FAULT;
+	}
 
 	/* For APIC access vmexit */
 	if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
 		goto mmio;
 
-	if (kvm_read_guest_virt(addr, val, bytes, vcpu)
+	if (kvm_read_guest_virt(addr, val, bytes, vcpu, NULL)
 				== X86EMUL_CONTINUE)
 		return X86EMUL_CONTINUE;
-	if (gpa == UNMAPPED_GVA)
-		return X86EMUL_PROPAGATE_FAULT;
 
 mmio:
 	/*
@@ -2587,11 +2710,12 @@
 					   struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
+	u32 error_code;
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, &error_code);
 
 	if (gpa == UNMAPPED_GVA) {
-		kvm_inject_page_fault(vcpu, addr, 2);
+		kvm_inject_page_fault(vcpu, addr, error_code);
 		return X86EMUL_PROPAGATE_FAULT;
 	}
 
@@ -2655,7 +2779,7 @@
 		char *kaddr;
 		u64 val;
 
-		gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL);
 
 		if (gpa == UNMAPPED_GVA ||
 		   (gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
@@ -2700,6 +2824,9 @@
 {
 	struct kvm_vcpu *vcpu = ctxt->vcpu;
 
+	if (!kvm_x86_ops->get_dr)
+		return X86EMUL_UNHANDLEABLE;
+
 	switch (dr) {
 	case 0 ... 3:
 		*dest = kvm_x86_ops->get_dr(vcpu, dr);
@@ -2715,6 +2842,9 @@
 	unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
 	int exception;
 
+	if (!kvm_x86_ops->set_dr)
+		return X86EMUL_UNHANDLEABLE;
+
 	kvm_x86_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception);
 	if (exception) {
 		/* FIXME: better handling */
@@ -2734,7 +2864,7 @@
 
 	rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS);
 
-	kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu);
+	kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu, NULL);
 
 	printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n",
 	       context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
@@ -2742,7 +2872,8 @@
 EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
 
 static struct x86_emulate_ops emulate_ops = {
-	.read_std            = kvm_read_guest_virt,
+	.read_std            = kvm_read_guest_virt_system,
+	.fetch               = kvm_fetch_guest_virt,
 	.read_emulated       = emulator_read_emulated,
 	.write_emulated      = emulator_write_emulated,
 	.cmpxchg_emulated    = emulator_cmpxchg_emulated,
@@ -2785,8 +2916,9 @@
 		vcpu->arch.emulate_ctxt.vcpu = vcpu;
 		vcpu->arch.emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
 		vcpu->arch.emulate_ctxt.mode =
+			(!(vcpu->arch.cr0 & X86_CR0_PE)) ? X86EMUL_MODE_REAL :
 			(vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
-			? X86EMUL_MODE_REAL : cs_l
+			? X86EMUL_MODE_VM86 : cs_l
 			? X86EMUL_MODE_PROT64 :	cs_db
 			? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
 
@@ -2878,12 +3010,17 @@
 	gva_t q = vcpu->arch.pio.guest_gva;
 	unsigned bytes;
 	int ret;
+	u32 error_code;
 
 	bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count;
 	if (vcpu->arch.pio.in)
-		ret = kvm_write_guest_virt(q, p, bytes, vcpu);
+		ret = kvm_write_guest_virt(q, p, bytes, vcpu, &error_code);
 	else
-		ret = kvm_read_guest_virt(q, p, bytes, vcpu);
+		ret = kvm_read_guest_virt(q, p, bytes, vcpu, &error_code);
+
+	if (ret == X86EMUL_PROPAGATE_FAULT)
+		kvm_inject_page_fault(vcpu, q, error_code);
+
 	return ret;
 }
 
@@ -2904,7 +3041,7 @@
 		if (io->in) {
 			r = pio_copy_data(vcpu);
 			if (r)
-				return r;
+				goto out;
 		}
 
 		delta = 1;
@@ -2931,7 +3068,7 @@
 			kvm_register_write(vcpu, VCPU_REGS_RSI, val);
 		}
 	}
-
+out:
 	io->count -= io->cur_count;
 	io->cur_count = 0;
 
@@ -2974,6 +3111,8 @@
 {
 	unsigned long val;
 
+	trace_kvm_pio(!in, port, size, 1);
+
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = vcpu->arch.pio.size = size;
@@ -2985,9 +3124,6 @@
 	vcpu->arch.pio.down = 0;
 	vcpu->arch.pio.rep = 0;
 
-	trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
-		      size, 1);
-
 	val = kvm_register_read(vcpu, VCPU_REGS_RAX);
 	memcpy(vcpu->arch.pio_data, &val, 4);
 
@@ -3006,6 +3142,8 @@
 	unsigned now, in_page;
 	int ret = 0;
 
+	trace_kvm_pio(!in, port, size, count);
+
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = vcpu->arch.pio.size = size;
@@ -3017,9 +3155,6 @@
 	vcpu->arch.pio.down = down;
 	vcpu->arch.pio.rep = rep;
 
-	trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
-		      size, count);
-
 	if (!count) {
 		kvm_x86_ops->skip_emulated_instruction(vcpu);
 		return 1;
@@ -3051,10 +3186,8 @@
 	if (!vcpu->arch.pio.in) {
 		/* string PIO write */
 		ret = pio_copy_data(vcpu);
-		if (ret == X86EMUL_PROPAGATE_FAULT) {
-			kvm_inject_gp(vcpu, 0);
+		if (ret == X86EMUL_PROPAGATE_FAULT)
 			return 1;
-		}
 		if (ret == 0 && !pio_string_write(vcpu)) {
 			complete_pio(vcpu);
 			if (vcpu->arch.pio.count == 0)
@@ -3602,6 +3735,8 @@
 	kvm_x86_ops->prepare_guest_switch(vcpu);
 	kvm_load_guest_fpu(vcpu);
 
+	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
+
 	local_irq_disable();
 
 	clear_bit(KVM_REQ_KICK, &vcpu->requests);
@@ -4034,7 +4169,9 @@
 		kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
 		return 1;
 	}
-	return kvm_read_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
+	return kvm_read_guest_virt_system(dtable.base + index*8,
+					  seg_desc, sizeof(*seg_desc),
+					  vcpu, NULL);
 }
 
 /* allowed just for 8 bytes segments */
@@ -4048,15 +4185,23 @@
 
 	if (dtable.limit < index * 8 + 7)
 		return 1;
-	return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
+	return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu, NULL);
+}
+
+static gpa_t get_tss_base_addr_write(struct kvm_vcpu *vcpu,
+			       struct desc_struct *seg_desc)
+{
+	u32 base_addr = get_desc_base(seg_desc);
+
+	return kvm_mmu_gva_to_gpa_write(vcpu, base_addr, NULL);
 }
 
-static gpa_t get_tss_base_addr(struct kvm_vcpu *vcpu,
+static gpa_t get_tss_base_addr_read(struct kvm_vcpu *vcpu,
 			     struct desc_struct *seg_desc)
 {
 	u32 base_addr = get_desc_base(seg_desc);
 
-	return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr);
+	return kvm_mmu_gva_to_gpa_read(vcpu, base_addr, NULL);
 }
 
 static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
@@ -4067,18 +4212,6 @@
 	return kvm_seg.selector;
 }
 
-static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu,
-						u16 selector,
-						struct kvm_segment *kvm_seg)
-{
-	struct desc_struct seg_desc;
-
-	if (load_guest_segment_descriptor(vcpu, selector, &seg_desc))
-		return 1;
-	seg_desct_to_kvm_desct(&seg_desc, selector, kvm_seg);
-	return 0;
-}
-
 static int kvm_load_realmode_segment(struct kvm_vcpu *vcpu, u16 selector, int seg)
 {
 	struct kvm_segment segvar = {
@@ -4096,7 +4229,7 @@
 		.unusable = 0,
 	};
 	kvm_x86_ops->set_segment(vcpu, &segvar, seg);
-	return 0;
+	return X86EMUL_CONTINUE;
 }
 
 static int is_vm86_segment(struct kvm_vcpu *vcpu, int seg)
@@ -4106,24 +4239,113 @@
 		(kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_VM);
 }
 
-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
-				int type_bits, int seg)
+int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg)
 {
 	struct kvm_segment kvm_seg;
+	struct desc_struct seg_desc;
+	u8 dpl, rpl, cpl;
+	unsigned err_vec = GP_VECTOR;
+	u32 err_code = 0;
+	bool null_selector = !(selector & ~0x3); /* 0000-0003 are null */
+	int ret;
 
 	if (is_vm86_segment(vcpu, seg) || !(vcpu->arch.cr0 & X86_CR0_PE))
 		return kvm_load_realmode_segment(vcpu, selector, seg);
-	if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
-		return 1;
-	kvm_seg.type |= type_bits;
 
-	if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
-	    seg != VCPU_SREG_LDTR)
-		if (!kvm_seg.s)
-			kvm_seg.unusable = 1;
 
+	/* NULL selector is not valid for TR, CS and SS */
+	if ((seg == VCPU_SREG_CS || seg == VCPU_SREG_SS || seg == VCPU_SREG_TR)
+	    && null_selector)
+		goto exception;
+
+	/* TR should be in GDT only */
+	if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
+		goto exception;
+
+	ret = load_guest_segment_descriptor(vcpu, selector, &seg_desc);
+	if (ret)
+		return ret;
+
+	seg_desct_to_kvm_desct(&seg_desc, selector, &kvm_seg);
+
+	if (null_selector) { /* for NULL selector skip all following checks */
+		kvm_seg.unusable = 1;
+		goto load;
+	}
+
+	err_code = selector & 0xfffc;
+	err_vec = GP_VECTOR;
+
+	/* can't load system descriptor into segment selecor */
+	if (seg <= VCPU_SREG_GS && !kvm_seg.s)
+		goto exception;
+
+	if (!kvm_seg.present) {
+		err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
+		goto exception;
+	}
+
+	rpl = selector & 3;
+	dpl = kvm_seg.dpl;
+	cpl = kvm_x86_ops->get_cpl(vcpu);
+
+	switch (seg) {
+	case VCPU_SREG_SS:
+		/*
+		 * segment is not a writable data segment or segment
+		 * selector's RPL != CPL or segment selector's RPL != CPL
+		 */
+		if (rpl != cpl || (kvm_seg.type & 0xa) != 0x2 || dpl != cpl)
+			goto exception;
+		break;
+	case VCPU_SREG_CS:
+		if (!(kvm_seg.type & 8))
+			goto exception;
+
+		if (kvm_seg.type & 4) {
+			/* conforming */
+			if (dpl > cpl)
+				goto exception;
+		} else {
+			/* nonconforming */
+			if (rpl > cpl || dpl != cpl)
+				goto exception;
+		}
+		/* CS(RPL) <- CPL */
+		selector = (selector & 0xfffc) | cpl;
+		break;
+	case VCPU_SREG_TR:
+		if (kvm_seg.s || (kvm_seg.type != 1 && kvm_seg.type != 9))
+			goto exception;
+		break;
+	case VCPU_SREG_LDTR:
+		if (kvm_seg.s || kvm_seg.type != 2)
+			goto exception;
+		break;
+	default: /*  DS, ES, FS, or GS */
+		/*
+		 * segment is not a data or readable code segment or
+		 * ((segment is a data or nonconforming code segment)
+		 * and (both RPL and CPL > DPL))
+		 */
+		if ((kvm_seg.type & 0xa) == 0x8 ||
+		    (((kvm_seg.type & 0xc) != 0xc) && (rpl > dpl && cpl > dpl)))
+			goto exception;
+		break;
+	}
+
+	if (!kvm_seg.unusable && kvm_seg.s) {
+		/* mark segment as accessed */
+		kvm_seg.type |= 1;
+		seg_desc.type |= 1;
+		save_guest_segment_descriptor(vcpu, selector, &seg_desc);
+	}
+load:
 	kvm_set_segment(vcpu, &kvm_seg, seg);
-	return 0;
+	return X86EMUL_CONTINUE;
+exception:
+	kvm_queue_exception_e(vcpu, err_vec, err_code);
+	return X86EMUL_PROPAGATE_FAULT;
 }
 
 static void save_state_to_tss32(struct kvm_vcpu *vcpu,
@@ -4149,6 +4371,14 @@
 	tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
 }
 
+static void kvm_load_segment_selector(struct kvm_vcpu *vcpu, u16 sel, int seg)
+{
+	struct kvm_segment kvm_seg;
+	kvm_get_segment(vcpu, &kvm_seg, seg);
+	kvm_seg.selector = sel;
+	kvm_set_segment(vcpu, &kvm_seg, seg);
+}
+
 static int load_state_from_tss32(struct kvm_vcpu *vcpu,
 				  struct tss_segment_32 *tss)
 {
@@ -4166,25 +4396,41 @@
 	kvm_register_write(vcpu, VCPU_REGS_RSI, tss->esi);
 	kvm_register_write(vcpu, VCPU_REGS_RDI, tss->edi);
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
+	/*
+	 * SDM says that segment selectors are loaded before segment
+	 * descriptors
+	 */
+	kvm_load_segment_selector(vcpu, tss->ldt_selector, VCPU_SREG_LDTR);
+	kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
+	kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
+	kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
+	kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
+	kvm_load_segment_selector(vcpu, tss->fs, VCPU_SREG_FS);
+	kvm_load_segment_selector(vcpu, tss->gs, VCPU_SREG_GS);
+
+	/*
+	 * Now load segment descriptors. If fault happenes at this stage
+	 * it is handled in a context of new task
+	 */
+	if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, VCPU_SREG_LDTR))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+	if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+	if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS))
+	if (kvm_load_segment_descriptor(vcpu, tss->fs, VCPU_SREG_FS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS))
+	if (kvm_load_segment_descriptor(vcpu, tss->gs, VCPU_SREG_GS))
 		return 1;
 	return 0;
 }
@@ -4225,19 +4471,33 @@
 	kvm_register_write(vcpu, VCPU_REGS_RSI, tss->si);
 	kvm_register_write(vcpu, VCPU_REGS_RDI, tss->di);
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
+	/*
+	 * SDM says that segment selectors are loaded before segment
+	 * descriptors
+	 */
+	kvm_load_segment_selector(vcpu, tss->ldt, VCPU_SREG_LDTR);
+	kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
+	kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
+	kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
+	kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
+
+	/*
+	 * Now load segment descriptors. If fault happenes at this stage
+	 * it is handled in a context of new task
+	 */
+	if (kvm_load_segment_descriptor(vcpu, tss->ldt, VCPU_SREG_LDTR))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+	if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+	if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
 		return 1;
 	return 0;
 }
@@ -4259,7 +4519,7 @@
 			    sizeof tss_segment_16))
 		goto out;
 
-	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
 			   &tss_segment_16, sizeof tss_segment_16))
 		goto out;
 
@@ -4267,7 +4527,7 @@
 		tss_segment_16.prev_task_link = old_tss_sel;
 
 		if (kvm_write_guest(vcpu->kvm,
-				    get_tss_base_addr(vcpu, nseg_desc),
+				    get_tss_base_addr_write(vcpu, nseg_desc),
 				    &tss_segment_16.prev_task_link,
 				    sizeof tss_segment_16.prev_task_link))
 			goto out;
@@ -4298,7 +4558,7 @@
 			    sizeof tss_segment_32))
 		goto out;
 
-	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
 			   &tss_segment_32, sizeof tss_segment_32))
 		goto out;
 
@@ -4306,7 +4566,7 @@
 		tss_segment_32.prev_task_link = old_tss_sel;
 
 		if (kvm_write_guest(vcpu->kvm,
-				    get_tss_base_addr(vcpu, nseg_desc),
+				    get_tss_base_addr_write(vcpu, nseg_desc),
 				    &tss_segment_32.prev_task_link,
 				    sizeof tss_segment_32.prev_task_link))
 			goto out;
@@ -4328,8 +4588,9 @@
 	int ret = 0;
 	u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR);
 	u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR);
+	u32 desc_limit;
 
-	old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base);
+	old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL);
 
 	/* FIXME: Handle errors. Failure to read either TSS or their
 	 * descriptors should generate a pagefault.
@@ -4350,7 +4611,10 @@
 		}
 	}
 
-	if (!nseg_desc.p || get_desc_limit(&nseg_desc) < 0x67) {
+	desc_limit = get_desc_limit(&nseg_desc);
+	if (!nseg_desc.p ||
+	    ((desc_limit < 0x67 && (nseg_desc.type & 8)) ||
+	     desc_limit < 0x2b)) {
 		kvm_queue_exception_e(vcpu, TS_VECTOR, tss_selector & 0xfffc);
 		return 1;
 	}
@@ -4538,7 +4802,7 @@
 
 	vcpu_load(vcpu);
 	down_read(&vcpu->kvm->slots_lock);
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr);
+	gpa = kvm_mmu_gva_to_gpa_system(vcpu, vaddr, NULL);
 	up_read(&vcpu->kvm->slots_lock);
 	tr->physical_address = gpa;
 	tr->valid = gpa != UNMAPPED_GVA;
@@ -4762,12 +5026,13 @@
 				       GFP_KERNEL);
 	if (!vcpu->arch.mce_banks) {
 		r = -ENOMEM;
-		goto fail_mmu_destroy;
+		goto fail_free_lapic;
 	}
 	vcpu->arch.mcg_cap = KVM_MAX_MCE_BANKS;
 
 	return 0;
-
+fail_free_lapic:
+	kvm_free_lapic(vcpu);
 fail_mmu_destroy:
 	kvm_mmu_destroy(vcpu);
 fail_free_pio_data:
@@ -4778,6 +5043,7 @@
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
+	kfree(vcpu->arch.mce_banks);
 	kvm_free_lapic(vcpu);
 	down_read(&vcpu->kvm->slots_lock);
 	kvm_mmu_destroy(vcpu);
--- linux-ec2-2.6.32.orig/arch/x86/kvm/emulate.c
+++ linux-ec2-2.6.32/arch/x86/kvm/emulate.c
@@ -75,6 +75,7 @@
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
 #define GroupMask   0xff        /* Group number stored in bits 0:7 */
+#define Priv        (1<<27) /* instruction generates #GP if current CPL != 0 */
 /* Source 2 operand type */
 #define Src2None    (0<<29)
 #define Src2CL      (1<<29)
@@ -86,6 +87,7 @@
 enum {
 	Group1_80, Group1_81, Group1_82, Group1_83,
 	Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
+	Group8, Group9,
 };
 
 static u32 opcode_table[256] = {
@@ -203,7 +205,7 @@
 	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
 	/* 0xF0 - 0xF7 */
 	0, 0, 0, 0,
-	ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3,
+	ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3,
 	/* 0xF8 - 0xFF */
 	ImplicitOps, 0, ImplicitOps, ImplicitOps,
 	ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
@@ -211,16 +213,20 @@
 
 static u32 twobyte_table[256] = {
 	/* 0x00 - 0x0F */
-	0, Group | GroupDual | Group7, 0, 0, 0, ImplicitOps, ImplicitOps, 0,
-	ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+	0, Group | GroupDual | Group7, 0, 0,
+	0, ImplicitOps, ImplicitOps | Priv, 0,
+	ImplicitOps | Priv, ImplicitOps | Priv, 0, 0,
+	0, ImplicitOps | ModRM, 0, 0,
 	/* 0x10 - 0x1F */
 	0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x20 - 0x2F */
-	ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
+	ModRM | ImplicitOps | Priv, ModRM | Priv,
+	ModRM | ImplicitOps | Priv, ModRM | Priv,
+	0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x30 - 0x3F */
-	ImplicitOps, 0, ImplicitOps, 0,
-	ImplicitOps, ImplicitOps, 0, 0,
+	ImplicitOps | Priv, 0, ImplicitOps | Priv, 0,
+	ImplicitOps, ImplicitOps | Priv, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x40 - 0x47 */
 	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -258,11 +264,12 @@
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xB8 - 0xBF */
-	0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,
+	0, 0, Group | Group8, DstMem | SrcReg | ModRM | BitOp,
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xC0 - 0xCF */
-	0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,
+	0, 0, 0, DstMem | SrcReg | ModRM | Mov,
+	0, 0, 0, Group | GroupDual | Group9,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xD0 - 0xDF */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -311,24 +318,39 @@
 	SrcMem | ModRM | Stack, 0,
 	SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, 0,
 	[Group7*8] =
-	0, 0, ModRM | SrcMem, ModRM | SrcMem,
+	0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
 	SrcNone | ModRM | DstMem | Mov, 0,
-	SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
+	SrcMem16 | ModRM | Mov | Priv, SrcMem | ModRM | ByteOp | Priv,
+	[Group8*8] =
+	0, 0, 0, 0,
+	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+	[Group9*8] =
+	0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0,
 };
 
 static u32 group2_table[] = {
 	[Group7*8] =
-	SrcNone | ModRM, 0, 0, SrcNone | ModRM,
+	SrcNone | ModRM | Priv, 0, 0, SrcNone | ModRM,
 	SrcNone | ModRM | DstMem | Mov, 0,
 	SrcMem16 | ModRM | Mov, 0,
+	[Group9*8] =
+	0, 0, 0, 0, 0, 0, 0, 0,
 };
 
 /* EFLAGS bit definitions. */
+#define EFLG_ID (1<<21)
+#define EFLG_VIP (1<<20)
+#define EFLG_VIF (1<<19)
+#define EFLG_AC (1<<18)
 #define EFLG_VM (1<<17)
 #define EFLG_RF (1<<16)
+#define EFLG_IOPL (3<<12)
+#define EFLG_NT (1<<14)
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
 #define EFLG_IF (1<<9)
+#define EFLG_TF (1<<8)
 #define EFLG_SF (1<<7)
 #define EFLG_ZF (1<<6)
 #define EFLG_AF (1<<4)
@@ -597,7 +619,7 @@
 
 	if (linear < fc->start || linear >= fc->end) {
 		size = min(15UL, PAGE_SIZE - offset_in_page(linear));
-		rc = ops->read_std(linear, fc->data, size, ctxt->vcpu);
+		rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL);
 		if (rc)
 			return rc;
 		fc->start = linear;
@@ -613,6 +635,9 @@
 {
 	int rc = 0;
 
+	/* x86 instructions are limited to 15 bytes. */
+	if (eip + size - ctxt->decode.eip_orig > 15)
+		return X86EMUL_UNHANDLEABLE;
 	eip += ctxt->cs_base;
 	while (size--) {
 		rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
@@ -649,11 +674,11 @@
 		op_bytes = 3;
 	*address = 0;
 	rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2,
-			   ctxt->vcpu);
+			   ctxt->vcpu, NULL);
 	if (rc)
 		return rc;
 	rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes,
-			   ctxt->vcpu);
+			   ctxt->vcpu, NULL);
 	return rc;
 }
 
@@ -871,12 +896,13 @@
 	/* Shadow copy of register state. Committed on successful emulation. */
 
 	memset(c, 0, sizeof(struct decode_cache));
-	c->eip = kvm_rip_read(ctxt->vcpu);
+	c->eip = c->eip_orig = kvm_rip_read(ctxt->vcpu);
 	ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS);
 	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
+	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
 		def_op_bytes = def_ad_bytes = 2;
 		break;
@@ -1186,6 +1212,49 @@
 	return rc;
 }
 
+static int emulate_popf(struct x86_emulate_ctxt *ctxt,
+		       struct x86_emulate_ops *ops,
+		       void *dest, int len)
+{
+	int rc;
+	unsigned long val, change_mask;
+	int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+	int cpl = kvm_x86_ops->get_cpl(ctxt->vcpu);
+
+	rc = emulate_pop(ctxt, ops, &val, len);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
+		| EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
+
+	switch(ctxt->mode) {
+	case X86EMUL_MODE_PROT64:
+	case X86EMUL_MODE_PROT32:
+	case X86EMUL_MODE_PROT16:
+		if (cpl == 0)
+			change_mask |= EFLG_IOPL;
+		if (cpl <= iopl)
+			change_mask |= EFLG_IF;
+		break;
+	case X86EMUL_MODE_VM86:
+		if (iopl < 3) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			return X86EMUL_PROPAGATE_FAULT;
+		}
+		change_mask |= EFLG_IF;
+		break;
+	default: /* real mode */
+		change_mask |= (EFLG_IOPL | EFLG_IF);
+		break;
+	}
+
+	*(unsigned long *)dest =
+		(ctxt->eflags & ~change_mask) | (val & change_mask);
+
+	return rc;
+}
+
 static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
 				struct x86_emulate_ops *ops)
 {
@@ -1327,7 +1396,7 @@
 	rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
 	if (rc)
 		return rc;
-	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS);
+	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, VCPU_SREG_CS);
 	return rc;
 }
 
@@ -1435,7 +1504,7 @@
 
 	/* syscall is not available in real mode */
 	if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL
-		|| !(ctxt->vcpu->arch.cr0 & X86_CR0_PE))
+	    || ctxt->mode == X86EMUL_MODE_VM86)
 		return -1;
 
 	setup_syscalls_segments(ctxt, &cs, &ss);
@@ -1487,9 +1556,8 @@
 	if (c->lock_prefix)
 		return -1;
 
-	/* inject #GP if in real mode or paging is disabled */
-	if (ctxt->mode == X86EMUL_MODE_REAL ||
-		!(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
+	/* inject #GP if in real mode */
+	if (ctxt->mode == X86EMUL_MODE_REAL) {
 		kvm_inject_gp(ctxt->vcpu, 0);
 		return -1;
 	}
@@ -1553,15 +1621,9 @@
 	if (c->lock_prefix)
 		return -1;
 
-	/* inject #GP if in real mode or paging is disabled */
-	if (ctxt->mode == X86EMUL_MODE_REAL
-		|| !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
-		kvm_inject_gp(ctxt->vcpu, 0);
-		return -1;
-	}
-
-	/* sysexit must be called from CPL 0 */
-	if (kvm_x86_ops->get_cpl(ctxt->vcpu) != 0) {
+	/* inject #GP if in real mode or Virtual 8086 mode */
+	if (ctxt->mode == X86EMUL_MODE_REAL ||
+	    ctxt->mode == X86EMUL_MODE_VM86) {
 		kvm_inject_gp(ctxt->vcpu, 0);
 		return -1;
 	}
@@ -1608,6 +1670,57 @@
 	return 0;
 }
 
+static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
+{
+	int iopl;
+	if (ctxt->mode == X86EMUL_MODE_REAL)
+		return false;
+	if (ctxt->mode == X86EMUL_MODE_VM86)
+		return true;
+	iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+	return kvm_x86_ops->get_cpl(ctxt->vcpu) > iopl;
+}
+
+static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
+					    struct x86_emulate_ops *ops,
+					    u16 port, u16 len)
+{
+	struct kvm_segment tr_seg;
+	int r;
+	u16 io_bitmap_ptr;
+	u8 perm, bit_idx = port & 0x7;
+	unsigned mask = (1 << len) - 1;
+
+	kvm_get_segment(ctxt->vcpu, &tr_seg, VCPU_SREG_TR);
+	if (tr_seg.unusable)
+		return false;
+	if (tr_seg.limit < 103)
+		return false;
+	r = ops->read_std(tr_seg.base + 102, &io_bitmap_ptr, 2, ctxt->vcpu,
+			  NULL);
+	if (r != X86EMUL_CONTINUE)
+		return false;
+	if (io_bitmap_ptr + port/8 > tr_seg.limit)
+		return false;
+	r = ops->read_std(tr_seg.base + io_bitmap_ptr + port/8, &perm, 1,
+			  ctxt->vcpu, NULL);
+	if (r != X86EMUL_CONTINUE)
+		return false;
+	if ((perm >> bit_idx) & mask)
+		return false;
+	return true;
+}
+
+static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
+				 struct x86_emulate_ops *ops,
+				 u16 port, u16 len)
+{
+	if (emulator_bad_iopl(ctxt))
+		if (!emulator_io_port_access_allowed(ctxt, ops, port, len))
+			return false;
+	return true;
+}
+
 int
 x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 {
@@ -1629,6 +1742,12 @@
 	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
 	saved_eip = c->eip;
 
+	/* Privileged instruction can be executed only in CPL=0 */
+	if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+		kvm_inject_gp(ctxt->vcpu, 0);
+		goto done;
+	}
+
 	if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
 		memop = c->modrm_ea;
 
@@ -1761,7 +1880,12 @@
 		break;
 	case 0x6c:		/* insb */
 	case 0x6d:		/* insw/insd */
-		 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
+		if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+		if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
 				1,
 				(c->d & ByteOp) ? 1 : c->op_bytes,
 				c->rep_prefix ?
@@ -1777,6 +1901,11 @@
 		return 0;
 	case 0x6e:		/* outsb */
 	case 0x6f:		/* outsw/outsd */
+		if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
 		if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
 				0,
 				(c->d & ByteOp) ? 1 : c->op_bytes,
@@ -1863,25 +1992,19 @@
 		break;
 	case 0x8e: { /* mov seg, r/m16 */
 		uint16_t sel;
-		int type_bits;
-		int err;
 
 		sel = c->src.val;
-		if (c->modrm_reg == VCPU_SREG_SS)
-			toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
 
-		if (c->modrm_reg <= 5) {
-			type_bits = (c->modrm_reg == 1) ? 9 : 1;
-			err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
-							  type_bits, c->modrm_reg);
-		} else {
-			printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n",
-					c->modrm);
-			goto cannot_emulate;
+		if (c->modrm_reg == VCPU_SREG_CS ||
+		    c->modrm_reg > VCPU_SREG_GS) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
 		}
 
-		if (err < 0)
-			goto cannot_emulate;
+		if (c->modrm_reg == VCPU_SREG_SS)
+			toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
+
+		rc = kvm_load_segment_descriptor(ctxt->vcpu, sel, c->modrm_reg);
 
 		c->dst.type = OP_NONE;  /* Disable writeback. */
 		break;
@@ -1910,7 +2033,10 @@
 		c->dst.type = OP_REG;
 		c->dst.ptr = (unsigned long *) &ctxt->eflags;
 		c->dst.bytes = c->op_bytes;
-		goto pop_instruction;
+		rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
+		break;
 	case 0xa0 ... 0xa1:	/* mov */
 		c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
 		c->dst.val = c->src.val;
@@ -2048,11 +2174,9 @@
 	case 0xe9: /* jmp rel */
 		goto jmp;
 	case 0xea: /* jmp far */
-		if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
-					VCPU_SREG_CS) < 0) {
-			DPRINTF("jmp far: Failed to load CS descriptor\n");
-			goto cannot_emulate;
-		}
+		if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val,
+						VCPU_SREG_CS))
+			goto done;
 
 		c->eip = c->src.val;
 		break;
@@ -2070,7 +2194,13 @@
 	case 0xef: /* out (e/r)ax,dx */
 		port = c->regs[VCPU_REGS_RDX];
 		io_dir_in = 0;
-	do_io:	if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in,
+	do_io:
+		if (!emulator_io_permited(ctxt, ops, port,
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+		if (kvm_emulate_pio(ctxt->vcpu, NULL, io_dir_in,
 				   (c->d & ByteOp) ? 1 : c->op_bytes,
 				   port) != 0) {
 			c->eip = saved_eip;
@@ -2095,13 +2225,21 @@
 		c->dst.type = OP_NONE;	/* Disable writeback. */
 		break;
 	case 0xfa: /* cli */
-		ctxt->eflags &= ~X86_EFLAGS_IF;
-		c->dst.type = OP_NONE;	/* Disable writeback. */
+		if (emulator_bad_iopl(ctxt))
+			kvm_inject_gp(ctxt->vcpu, 0);
+		else {
+			ctxt->eflags &= ~X86_EFLAGS_IF;
+			c->dst.type = OP_NONE;	/* Disable writeback. */
+		}
 		break;
 	case 0xfb: /* sti */
-		toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
-		ctxt->eflags |= X86_EFLAGS_IF;
-		c->dst.type = OP_NONE;	/* Disable writeback. */
+		if (emulator_bad_iopl(ctxt))
+			kvm_inject_gp(ctxt->vcpu, 0);
+		else {
+			toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
+			ctxt->eflags |= X86_EFLAGS_IF;
+			c->dst.type = OP_NONE;	/* Disable writeback. */
+		}
 		break;
 	case 0xfc: /* cld */
 		ctxt->eflags &= ~EFLG_DF;
--- linux-ec2-2.6.32.orig/arch/x86/kvm/mmu.c
+++ linux-ec2-2.6.32/arch/x86/kvm/mmu.c
@@ -136,12 +136,6 @@
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \
 			| PT64_NX_MASK)
 
-#define PFERR_PRESENT_MASK (1U << 0)
-#define PFERR_WRITE_MASK (1U << 1)
-#define PFERR_USER_MASK (1U << 2)
-#define PFERR_RSVD_MASK (1U << 3)
-#define PFERR_FETCH_MASK (1U << 4)
-
 #define PT_PDPE_LEVEL 3
 #define PT_DIRECTORY_LEVEL 2
 #define PT_PAGE_TABLE_LEVEL 1
@@ -227,7 +221,7 @@
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
-static int is_write_protection(struct kvm_vcpu *vcpu)
+static bool is_write_protection(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.cr0 & X86_CR0_WP;
 }
@@ -477,7 +471,7 @@
 
 	addr = gfn_to_hva(kvm, gfn);
 	if (kvm_is_error_hva(addr))
-		return page_size;
+		return PT_PAGE_TABLE_LEVEL;
 
 	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, addr);
@@ -515,11 +509,9 @@
 	if (host_level == PT_PAGE_TABLE_LEVEL)
 		return host_level;
 
-	for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) {
-
+	for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level)
 		if (has_wrprotected_page(vcpu->kvm, large_gfn, level))
 			break;
-	}
 
 	return level - 1;
 }
@@ -1504,8 +1496,8 @@
 		for_each_sp(pages, sp, parents, i) {
 			kvm_mmu_zap_page(kvm, sp);
 			mmu_pages_clear_parents(&parents);
+			zapped++;
 		}
-		zapped += pages.nr;
 		kvm_mmu_pages_init(parent, &parents, &pages);
 	}
 
@@ -1556,14 +1548,16 @@
 	 */
 
 	if (used_pages > kvm_nr_mmu_pages) {
-		while (used_pages > kvm_nr_mmu_pages) {
+		while (used_pages > kvm_nr_mmu_pages &&
+			!list_empty(&kvm->arch.active_mmu_pages)) {
 			struct kvm_mmu_page *page;
 
 			page = container_of(kvm->arch.active_mmu_pages.prev,
 					    struct kvm_mmu_page, link);
-			kvm_mmu_zap_page(kvm, page);
+			used_pages -= kvm_mmu_zap_page(kvm, page);
 			used_pages--;
 		}
+		kvm_nr_mmu_pages = used_pages;
 		kvm->arch.n_free_mmu_pages = 0;
 	}
 	else
@@ -1610,7 +1604,8 @@
 		    && !sp->role.invalid) {
 			pgprintk("%s: zap %lx %x\n",
 				 __func__, gfn, sp->role.word);
-			kvm_mmu_zap_page(kvm, sp);
+			if (kvm_mmu_zap_page(kvm, sp))
+				nn = bucket->first;
 		}
 	}
 }
@@ -1641,7 +1636,7 @@
 {
 	struct page *page;
 
-	gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
+	gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
 
 	if (gpa == UNMAPPED_GVA)
 		return NULL;
@@ -1848,6 +1843,9 @@
 
 		spte |= PT_WRITABLE_MASK;
 
+		if (!tdp_enabled && !(pte_access & ACC_WRITE_MASK))
+			spte &= ~PT_USER_MASK;
+
 		/*
 		 * Optimization: for pte sync, if spte was writable the hash
 		 * lookup is unnecessary (and expensive). Write protection
@@ -1903,6 +1901,8 @@
 
 			child = page_header(pte & PT64_BASE_ADDR_MASK);
 			mmu_page_remove_parent_pte(child, sptep);
+			__set_spte(sptep, shadow_trap_nonpresent_pte);
+			kvm_flush_remote_tlbs(vcpu->kvm);
 		} else if (pfn != spte_to_pfn(*sptep)) {
 			pgprintk("hfn old %lx new %lx\n",
 				 spte_to_pfn(*sptep), pfn);
@@ -2096,11 +2096,13 @@
 			direct = 1;
 		if (mmu_check_root(vcpu, root_gfn))
 			return 1;
+		spin_lock(&vcpu->kvm->mmu_lock);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
 				      PT64_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
 		root = __pa(sp->spt);
 		++sp->root_count;
+		spin_unlock(&vcpu->kvm->mmu_lock);
 		vcpu->arch.mmu.root_hpa = root;
 		return 0;
 	}
@@ -2122,11 +2124,14 @@
 			root_gfn = 0;
 		if (mmu_check_root(vcpu, root_gfn))
 			return 1;
+		spin_lock(&vcpu->kvm->mmu_lock);
 		sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
 				      PT32_ROOT_LEVEL, direct,
 				      ACC_ALL, NULL);
 		root = __pa(sp->spt);
 		++sp->root_count;
+		spin_unlock(&vcpu->kvm->mmu_lock);
+
 		vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
 	}
 	vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
@@ -2164,8 +2169,11 @@
 	spin_unlock(&vcpu->kvm->mmu_lock);
 }
 
-static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
+static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr,
+				  u32 access, u32 *error)
 {
+	if (error)
+		*error = 0;
 	return vaddr;
 }
 
@@ -2447,6 +2455,7 @@
 		r = paging32_init_context(vcpu);
 
 	vcpu->arch.mmu.base_role.glevels = vcpu->arch.mmu.root_level;
+	vcpu->arch.mmu.base_role.cr0_wp = is_write_protection(vcpu);
 
 	return r;
 }
@@ -2486,7 +2495,9 @@
 		goto out;
 	spin_lock(&vcpu->kvm->mmu_lock);
 	kvm_mmu_free_some_pages(vcpu);
+	spin_unlock(&vcpu->kvm->mmu_lock);
 	r = mmu_alloc_roots(vcpu);
+	spin_lock(&vcpu->kvm->mmu_lock);
 	mmu_sync_roots(vcpu);
 	spin_unlock(&vcpu->kvm->mmu_lock);
 	if (r)
@@ -2749,7 +2760,7 @@
 	if (tdp_enabled)
 		return 0;
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
+	gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
 
 	spin_lock(&vcpu->kvm->mmu_lock);
 	r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
@@ -3247,7 +3258,7 @@
 		if (is_shadow_present_pte(ent) && !is_last_spte(ent, level))
 			audit_mappings_page(vcpu, ent, va, level - 1);
 		else {
-			gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
+			gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL);
 			gfn_t gfn = gpa >> PAGE_SHIFT;
 			pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn);
 			hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT;
--- linux-ec2-2.6.32.orig/arch/x86/kvm/svm.c
+++ linux-ec2-2.6.32/arch/x86/kvm/svm.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/ftrace_event.h>
 
+#include <asm/tlbflush.h>
 #include <asm/desc.h>
 
 #include <asm/virtext.h>
@@ -62,6 +63,8 @@
 #define nsvm_printk(fmt, args...) do {} while(0)
 #endif
 
+static bool erratum_383_found __read_mostly;
+
 static const u32 host_save_user_msrs[] = {
 #ifdef CONFIG_X86_64
 	MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_SYSCALL_MASK, MSR_KERNEL_GS_BASE,
@@ -299,6 +302,31 @@
 	svm_set_interrupt_shadow(vcpu, 0);
 }
 
+static void svm_init_erratum_383(void)
+{
+	u32 low, high;
+	int err;
+	u64 val;
+
+	/* Only Fam10h is affected */
+	if (boot_cpu_data.x86 != 0x10)
+		return;
+
+	/* Use _safe variants to not break nested virtualization */
+	val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
+	if (err)
+		return;
+
+	val |= (1ULL << 47);
+
+	low  = lower_32_bits(val);
+	high = upper_32_bits(val);
+
+	native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
+
+	erratum_383_found = true;
+}
+
 static int has_svm(void)
 {
 	const char *msg;
@@ -318,7 +346,6 @@
 
 static void svm_hardware_enable(void *garbage)
 {
-
 	struct svm_cpu_data *svm_data;
 	uint64_t efer;
 	struct descriptor_table gdt_descr;
@@ -350,6 +377,10 @@
 
 	wrmsrl(MSR_VM_HSAVE_PA,
 	       page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
+
+	svm_init_erratum_383();
+
+	return;
 }
 
 static void svm_cpu_uninit(int cpu)
@@ -590,7 +621,6 @@
 
 	control->iopm_base_pa = iopm_base;
 	control->msrpm_base_pa = __pa(svm->msrpm);
-	control->tsc_offset = 0;
 	control->int_ctl = V_INTR_MASKING_MASK;
 
 	init_seg(&save->es);
@@ -625,11 +655,12 @@
 	save->rip = 0x0000fff0;
 	svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip;
 
-	/*
-	 * cr0 val on cpu init should be 0x60000010, we enable cpu
-	 * cache by default. the orderly way is to enable cache in bios.
+	/* This is the guest-visible cr0 value.
+	 * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
 	 */
-	save->cr0 = 0x00000010 | X86_CR0_PG | X86_CR0_WP;
+	svm->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
+	kvm_set_cr0(&svm->vcpu, svm->vcpu.arch.cr0);
+
 	save->cr4 = X86_CR4_PAE;
 	/* rdx = ?? */
 
@@ -693,29 +724,28 @@
 	if (err)
 		goto free_svm;
 
+	err = -ENOMEM;
 	page = alloc_page(GFP_KERNEL);
-	if (!page) {
-		err = -ENOMEM;
+	if (!page)
 		goto uninit;
-	}
 
-	err = -ENOMEM;
 	msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
 	if (!msrpm_pages)
-		goto uninit;
+		goto free_page1;
 
 	nested_msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER);
 	if (!nested_msrpm_pages)
-		goto uninit;
-
-	svm->msrpm = page_address(msrpm_pages);
-	svm_vcpu_init_msrpm(svm->msrpm);
+		goto free_page2;
 
 	hsave_page = alloc_page(GFP_KERNEL);
 	if (!hsave_page)
-		goto uninit;
+		goto free_page3;
+
 	svm->nested.hsave = page_address(hsave_page);
 
+	svm->msrpm = page_address(msrpm_pages);
+	svm_vcpu_init_msrpm(svm->msrpm);
+
 	svm->nested.msrpm = page_address(nested_msrpm_pages);
 
 	svm->vmcb = page_address(page);
@@ -723,6 +753,7 @@
 	svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT;
 	svm->asid_generation = 0;
 	init_vmcb(svm);
+	svm->vmcb->control.tsc_offset = 0-native_read_tsc();
 
 	fx_init(&svm->vcpu);
 	svm->vcpu.fpu_active = 1;
@@ -732,6 +763,12 @@
 
 	return &svm->vcpu;
 
+free_page3:
+	__free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
+free_page2:
+	__free_pages(msrpm_pages, MSRPM_ALLOC_ORDER);
+free_page1:
+	__free_page(page);
 uninit:
 	kvm_vcpu_uninit(&svm->vcpu);
 free_svm:
@@ -758,17 +795,18 @@
 	int i;
 
 	if (unlikely(cpu != vcpu->cpu)) {
-		u64 tsc_this, delta;
+		u64 delta;
 
-		/*
-		 * Make sure that the guest sees a monotonically
-		 * increasing TSC.
-		 */
-		rdtscll(tsc_this);
-		delta = vcpu->arch.host_tsc - tsc_this;
-		svm->vmcb->control.tsc_offset += delta;
-		if (is_nested(svm))
-			svm->nested.hsave->control.tsc_offset += delta;
+		if (check_tsc_unstable()) {
+			/*
+			 * Make sure that the guest sees a monotonically
+			 * increasing TSC.
+			 */
+			delta = vcpu->arch.host_tsc - native_read_tsc();
+			svm->vmcb->control.tsc_offset += delta;
+			if (is_nested(svm))
+				svm->nested.hsave->control.tsc_offset += delta;
+		}
 		vcpu->cpu = cpu;
 		kvm_migrate_timers(vcpu);
 		svm->asid_generation = 0;
@@ -1251,8 +1289,59 @@
 	return 1;
 }
 
-static int mc_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+static bool is_erratum_383(void)
 {
+	int err, i;
+	u64 value;
+
+	if (!erratum_383_found)
+		return false;
+
+	value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
+	if (err)
+		return false;
+
+	/* Bit 62 may or may not be set for this mce */
+	value &= ~(1ULL << 62);
+
+	if (value != 0xb600000000010015ULL)
+		return false;
+
+	/* Clear MCi_STATUS registers */
+	for (i = 0; i < 6; ++i)
+		native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
+
+	value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
+	if (!err) {
+		u32 low, high;
+
+		value &= ~(1ULL << 2);
+		low    = lower_32_bits(value);
+		high   = upper_32_bits(value);
+
+		native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
+	}
+
+	/* Flush tlb to evict multi-match entries */
+	__flush_tlb_all();
+
+	return true;
+}
+
+static void svm_handle_mce(struct vcpu_svm *svm)
+{
+	if (is_erratum_383()) {
+		/*
+		 * Erratum 383 triggered. Guest state is corrupt so kill the
+		 * guest.
+		 */
+		pr_err("KVM: Guest triggered AMD Erratum 383\n");
+
+		set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests);
+
+		return;
+	}
+
 	/*
 	 * On an #MC intercept the MCE handler is not called automatically in
 	 * the host. So do it by hand here.
@@ -1261,6 +1350,11 @@
 		"int $0x12\n");
 	/* not sure if we ever come back to this point */
 
+	return;
+}
+
+static int mc_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
 	return 1;
 }
 
@@ -2018,7 +2112,7 @@
 static int iret_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
 {
 	++svm->vcpu.stat.nmi_window_exits;
-	svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+	svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
 	return 1;
 }
@@ -2413,7 +2507,7 @@
 
 	svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
 	vcpu->arch.hflags |= HF_NMI_MASK;
-	svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+	svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET);
 	++vcpu->stat.nmi_injections;
 }
 
@@ -2604,8 +2698,8 @@
 	sync_lapic_to_cr8(vcpu);
 
 	save_host_msrs(vcpu);
-	fs_selector = kvm_read_fs();
-	gs_selector = kvm_read_gs();
+	savesegment(fs, fs_selector);
+	savesegment(gs, gs_selector);
 	ldt_selector = kvm_read_ldt();
 	svm->vmcb->save.cr2 = vcpu->arch.cr2;
 	/* required for live migration with NPT */
@@ -2692,10 +2786,15 @@
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
-	kvm_load_fs(fs_selector);
-	kvm_load_gs(gs_selector);
-	kvm_load_ldt(ldt_selector);
 	load_host_msrs(vcpu);
+	kvm_load_ldt(ldt_selector);
+	loadsegment(fs, fs_selector);
+#ifdef CONFIG_X86_64
+	load_gs_index(gs_selector);
+	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+#else
+	loadsegment(gs, gs_selector);
+#endif
 
 	reload_tss(vcpu);
 
@@ -2711,6 +2810,14 @@
 		vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
 		vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
 	}
+
+	/*
+	 * We need to handle MC intercepts here before the vcpu has a chance to
+	 * change the physical cpu
+	 */
+	if (unlikely(svm->vmcb->control.exit_code ==
+		     SVM_EXIT_EXCP_BASE + MC_VECTOR))
+		svm_handle_mce(svm);
 }
 
 #undef R
--- linux-ec2-2.6.32.orig/arch/x86/kvm/i8254.c
+++ linux-ec2-2.6.32/arch/x86/kvm/i8254.c
@@ -465,6 +465,9 @@
 		return -EOPNOTSUPP;
 
 	addr &= KVM_PIT_CHANNEL_MASK;
+	if (addr == 3)
+		return 0;
+
 	s = &pit_state->channels[addr];
 
 	mutex_lock(&pit_state->lock);
--- linux-ec2-2.6.32.orig/arch/x86/xen/time.c
+++ linux-ec2-2.6.32/arch/x86/xen/time.c
@@ -100,7 +100,7 @@
 	return per_cpu(runstate, vcpu).state == RUNSTATE_runnable;
 }
 
-static void setup_runstate_info(int cpu)
+void xen_setup_runstate_info(int cpu)
 {
 	struct vcpu_register_runstate_memory_area area;
 
@@ -154,45 +154,6 @@
 	account_idle_ticks(ticks);
 }
 
-/*
- * Xen sched_clock implementation.  Returns the number of unstolen
- * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED
- * states.
- */
-unsigned long long xen_sched_clock(void)
-{
-	struct vcpu_runstate_info state;
-	cycle_t now;
-	u64 ret;
-	s64 offset;
-
-	/*
-	 * Ideally sched_clock should be called on a per-cpu basis
-	 * anyway, so preempt should already be disabled, but that's
-	 * not current practice at the moment.
-	 */
-	preempt_disable();
-
-	now = xen_clocksource_read();
-
-	get_runstate_snapshot(&state);
-
-	WARN_ON(state.state != RUNSTATE_running);
-
-	offset = now - state.state_entry_time;
-	if (offset < 0)
-		offset = 0;
-
-	ret = state.time[RUNSTATE_blocked] +
-		state.time[RUNSTATE_running] +
-		offset;
-
-	preempt_enable();
-
-	return ret;
-}
-
-
 /* Get the TSC speed from Xen */
 unsigned long xen_tsc_khz(void)
 {
@@ -434,7 +395,7 @@
 		name = "<timer kasprintf failed>";
 
 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
-				      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
+				      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER,
 				      name, NULL);
 
 	evt = &per_cpu(xen_clock_events, cpu);
@@ -442,8 +403,6 @@
 
 	evt->cpumask = cpumask_of(cpu);
 	evt->irq = irq;
-
-	setup_runstate_info(cpu);
 }
 
 void xen_teardown_timer(int cpu)
@@ -465,6 +424,8 @@
 {
 	int cpu;
 
+	pvclock_resume();
+
 	if (xen_clockevent != &xen_vcpuop_clockevent)
 		return;
 
@@ -494,6 +455,7 @@
 
 	setup_force_cpu_cap(X86_FEATURE_TSC);
 
+	xen_setup_runstate_info(cpu);
 	xen_setup_timer(cpu);
 	xen_setup_cpu_clockevents();
 }
--- linux-ec2-2.6.32.orig/arch/x86/xen/xen-ops.h
+++ linux-ec2-2.6.32/arch/x86/xen/xen-ops.h
@@ -25,6 +25,7 @@
 
 void xen_setup_mfn_list_list(void);
 void xen_setup_shared_info(void);
+void xen_build_mfn_list_list(void);
 void xen_setup_machphys_mapping(void);
 pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
 void xen_ident_map_ISA(void);
@@ -41,6 +42,7 @@
 
 void xen_init_irq_ops(void);
 void xen_setup_timer(int cpu);
+void xen_setup_runstate_info(int cpu);
 void xen_teardown_timer(int cpu);
 cycle_t xen_clocksource_read(void);
 void xen_setup_cpu_clockevents(void);
--- linux-ec2-2.6.32.orig/arch/x86/xen/xen-asm_64.S
+++ linux-ec2-2.6.32/arch/x86/xen/xen-asm_64.S
@@ -96,7 +96,7 @@
 	pushq $__USER32_CS
 	pushq %rcx
 
-	pushq $VGCF_in_syscall
+	pushq $0
 1:	jmp hypercall_iret
 ENDPATCH(xen_sysret32)
 RELOC(xen_sysret32, 1b+1)
@@ -151,7 +151,7 @@
 ENTRY(xen_sysenter_target)
 	lea 16(%rsp), %rsp	/* strip %rcx, %r11 */
 	mov $-ENOSYS, %rax
-	pushq $VGCF_in_syscall
+	pushq $0
 	jmp hypercall_iret
 ENDPROC(xen_syscall32_target)
 ENDPROC(xen_sysenter_target)
--- linux-ec2-2.6.32.orig/arch/x86/xen/smp.c
+++ linux-ec2-2.6.32/arch/x86/xen/smp.c
@@ -295,6 +295,7 @@
 		(unsigned long)task_stack_page(idle) -
 		KERNEL_STACK_OFFSET + THREAD_SIZE;
 #endif
+	xen_setup_runstate_info(cpu);
 	xen_setup_timer(cpu);
 	xen_init_lock_cpu(cpu);
 
@@ -395,9 +396,9 @@
 	BUG();
 }
 
-static void xen_smp_send_stop(void)
+static void xen_stop_other_cpus(int wait)
 {
-	smp_call_function(stop_self, NULL, 0);
+	smp_call_function(stop_self, NULL, wait);
 }
 
 static void xen_smp_send_reschedule(int cpu)
@@ -465,7 +466,7 @@
 	.cpu_disable = xen_cpu_disable,
 	.play_dead = xen_play_dead,
 
-	.smp_send_stop = xen_smp_send_stop,
+	.stop_other_cpus = xen_stop_other_cpus,
 	.smp_send_reschedule = xen_smp_send_reschedule,
 
 	.send_call_func_ipi = xen_smp_send_call_function_ipi,
--- linux-ec2-2.6.32.orig/arch/x86/xen/Kconfig
+++ linux-ec2-2.6.32/arch/x86/xen/Kconfig
@@ -2,7 +2,7 @@
 # This Kconfig describes xen options
 #
 
-config XEN
+config PARAVIRT_XEN
 	bool "Xen guest support"
 	select PARAVIRT
 	select PARAVIRT_CLOCK
@@ -17,7 +17,7 @@
        int "Maximum allowed size of a domain in gigabytes"
        default 8 if X86_32
        default 32 if X86_64
-       depends on XEN
+       depends on PARAVIRT_XEN
        help
          The pseudo-physical to machine address array is sized
          according to the maximum possible memory size of a Xen
@@ -26,12 +26,12 @@
 
 config XEN_SAVE_RESTORE
        bool
-       depends on XEN && PM
+       depends on PARAVIRT_XEN && PM
        default y
 
 config XEN_DEBUG_FS
 	bool "Enable Xen debug and tuning parameters in debugfs"
-	depends on XEN && DEBUG_FS
+	depends on PARAVIRT_XEN && DEBUG_FS
 	default n
 	help
 	  Enable statistics output and various tuning options in debugfs.
--- linux-ec2-2.6.32.orig/arch/x86/xen/mmu.c
+++ linux-ec2-2.6.32/arch/x86/xen/mmu.c
@@ -185,7 +185,7 @@
 }
 
 /* Build the parallel p2m_top_mfn structures */
-static void __init xen_build_mfn_list_list(void)
+void xen_build_mfn_list_list(void)
 {
 	unsigned pfn, idx;
 
@@ -1432,14 +1432,15 @@
 {
 	pgprot_t prot = PAGE_KERNEL;
 
+	/*
+	 * We disable highmem allocations for page tables so we should never
+	 * see any calls to kmap_atomic_pte on a highmem page.
+	 */
+	BUG_ON(PageHighMem(page));
+
 	if (PagePinned(page))
 		prot = PAGE_KERNEL_RO;
 
-	if (0 && PageHighMem(page))
-		printk("mapping highpte %lx type %d prot %s\n",
-		       page_to_pfn(page), type,
-		       (unsigned long)pgprot_val(prot) & _PAGE_RW ? "WRITE" : "READ");
-
 	return kmap_atomic_prot(page, type, prot);
 }
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/xen/enlighten.c
+++ linux-ec2-2.6.32/arch/x86/xen/enlighten.c
@@ -48,6 +48,7 @@
 #include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/reboot.h>
@@ -138,24 +139,23 @@
  */
 void xen_vcpu_restore(void)
 {
-	if (have_vcpu_info_placement) {
-		int cpu;
+	int cpu;
 
-		for_each_online_cpu(cpu) {
-			bool other_cpu = (cpu != smp_processor_id());
+	for_each_online_cpu(cpu) {
+		bool other_cpu = (cpu != smp_processor_id());
 
-			if (other_cpu &&
-			    HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL))
-				BUG();
+		if (other_cpu &&
+		    HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL))
+			BUG();
 
-			xen_vcpu_setup(cpu);
+		xen_setup_runstate_info(cpu);
 
-			if (other_cpu &&
-			    HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL))
-				BUG();
-		}
+		if (have_vcpu_info_placement)
+			xen_vcpu_setup(cpu);
 
-		BUG_ON(!have_vcpu_info_placement);
+		if (other_cpu &&
+		    HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL))
+			BUG();
 	}
 }
 
@@ -332,6 +332,24 @@
 	xen_mc_issue(PARAVIRT_LAZY_CPU);
 }
 
+#ifdef CONFIG_X86_32
+static void xen_load_user_cs_desc(int cpu, struct mm_struct *mm)
+{
+	void *gdt;
+	xmaddr_t mgdt;
+	u64 descriptor;
+	struct desc_struct user_cs;
+
+	gdt = &get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS];
+	mgdt = virt_to_machine(gdt);
+
+	user_cs = mm->context.user_cs;
+	descriptor = (u64) user_cs.a | ((u64) user_cs.b) << 32;
+
+	HYPERVISOR_update_descriptor(mgdt.maddr, descriptor);
+}
+#endif /*CONFIG_X86_32*/
+
 static void xen_load_gdt(const struct desc_ptr *dtr)
 {
 	unsigned long va = dtr->address;
@@ -924,7 +942,7 @@
 };
 
 static const struct pv_time_ops xen_time_ops __initdata = {
-	.sched_clock = xen_sched_clock,
+	.sched_clock = xen_clocksource_read,
 };
 
 static const struct pv_cpu_ops xen_cpu_ops __initdata = {
@@ -958,6 +976,9 @@
 
 	.load_tr_desc = paravirt_nop,
 	.set_ldt = xen_set_ldt,
+#ifdef CONFIG_X86_32
+	.load_user_cs_desc = xen_load_user_cs_desc,
+#endif /*CONFIG_X86_32*/
 	.load_gdt = xen_load_gdt,
 	.load_idt = xen_load_idt,
 	.load_tls = xen_load_tls,
@@ -997,10 +1018,6 @@
 {
 	struct sched_shutdown r = { .reason = reason };
 
-#ifdef CONFIG_SMP
-	smp_send_stop();
-#endif
-
 	if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
 		BUG();
 }
@@ -1093,6 +1110,12 @@
 
 	__supported_pte_mask |= _PAGE_IOMAP;
 
+	/*
+	 * Prevent page tables from being allocated in highmem, even
+	 * if CONFIG_HIGHPTE is enabled.
+	 */
+	__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+
 #ifdef CONFIG_X86_64
 	/* Work out if we support NX */
 	check_efer();
@@ -1182,6 +1205,8 @@
 
 	xen_raw_console_write("about to get started...\n");
 
+	xen_setup_runstate_info(0);
+
 	/* Start the world */
 #ifdef CONFIG_X86_32
 	i386_start_kernel();
--- linux-ec2-2.6.32.orig/arch/x86/xen/xen-head.S
+++ linux-ec2-2.6.32/arch/x86/xen/xen-head.S
@@ -1,7 +1,7 @@
 /* Xen-specific pieces of head.S, intended to be included in the right
 	place in head.S */
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 
 #include <linux/elfnote.h>
 #include <linux/init.h>
@@ -52,4 +52,4 @@
 	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   _ASM_PTR __HYPERVISOR_VIRT_START)
 	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
 
-#endif /*CONFIG_XEN */
+#endif /* CONFIG_PARAVIRT_XEN */
--- linux-ec2-2.6.32.orig/arch/x86/xen/suspend.c
+++ linux-ec2-2.6.32/arch/x86/xen/suspend.c
@@ -1,4 +1,5 @@
 #include <linux/types.h>
+#include <linux/clockchips.h>
 
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
@@ -27,6 +28,8 @@
 
 void xen_post_suspend(int suspend_cancelled)
 {
+	xen_build_mfn_list_list();
+
 	xen_setup_shared_info();
 
 	if (suspend_cancelled) {
@@ -44,7 +47,19 @@
 
 }
 
+static void xen_vcpu_notify_restore(void *data)
+{
+	unsigned long reason = (unsigned long)data;
+
+	/* Boot processor notified via generic timekeeping_resume() */
+	if ( smp_processor_id() == 0)
+		return;
+
+	clockevents_notify(reason, NULL);
+}
+
 void xen_arch_resume(void)
 {
-	/* nothing */
+	on_each_cpu(xen_vcpu_notify_restore,
+		    (void *)CLOCK_EVT_NOTIFY_RESUME, 1);
 }
--- linux-ec2-2.6.32.orig/arch/x86/mm/init_64-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/init_64-xen.c
@@ -0,0 +1,1300 @@
+/*
+ *  linux/arch/x86_64/mm/init.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
+ *  Copyright (C) 2002,2003 Andi Kleen <ak@suse.de>
+ *
+ *  Jun Nakajima <jun.nakajima@intel.com>
+ *	Modified for Xen.
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/pfn.h>
+#include <linux/poison.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/memory_hotplug.h>
+#include <linux/nmi.h>
+
+#include <asm/processor.h>
+#include <asm/bios_ebda.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/dma.h>
+#include <asm/fixmap.h>
+#include <asm/e820.h>
+#include <asm/apic.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/proto.h>
+#include <asm/smp.h>
+#include <asm/sections.h>
+#include <asm/kdebug.h>
+#include <asm/numa.h>
+#include <asm/cacheflush.h>
+#include <asm/init.h>
+#include <asm/setup.h>
+
+#include <xen/features.h>
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+unsigned int __kernel_page_user;
+EXPORT_SYMBOL(__kernel_page_user);
+#endif
+
+extern pmd_t level2_fixmap_pgt[PTRS_PER_PMD];
+extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
+
+/*
+ * Use this until direct mapping is established, i.e. before __va() is 
+ * available in init_memory_mapping().
+ */
+
+#define addr_to_page(addr, page)				\
+	(addr) &= PHYSICAL_PAGE_MASK;				\
+	(page) = ((unsigned long *) ((unsigned long)		\
+	(((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) +	\
+	__START_KERNEL_map)))
+
+pmd_t *__init early_get_pmd(unsigned long va)
+{
+	unsigned long addr;
+	unsigned long *page = (unsigned long *)init_level4_pgt;
+
+	addr = page[pgd_index(va)];
+	addr_to_page(addr, page);
+
+	addr = page[pud_index(va)];
+	addr_to_page(addr, page);
+
+	return (pmd_t *)&page[pmd_index(va)];
+}
+
+void __meminit early_make_page_readonly(void *va, unsigned int feature)
+{
+	unsigned long addr, _va = (unsigned long)va;
+	pte_t pte, *ptep;
+	unsigned long *page = (unsigned long *) init_level4_pgt;
+
+	BUG_ON(after_bootmem);
+
+	if (xen_feature(feature))
+		return;
+
+	addr = (unsigned long) page[pgd_index(_va)];
+	addr_to_page(addr, page);
+
+	addr = page[pud_index(_va)];
+	addr_to_page(addr, page);
+
+	addr = page[pmd_index(_va)];
+	addr_to_page(addr, page);
+
+	ptep = (pte_t *) &page[pte_index(_va)];
+
+	pte.pte = ptep->pte & ~_PAGE_RW;
+	if (HYPERVISOR_update_va_mapping(_va, pte, 0))
+		BUG();
+}
+
+unsigned long __init early_arbitrary_virt_to_mfn(void *v)
+{
+	unsigned long va = (unsigned long)v, addr, *page;
+
+	BUG_ON(va < __START_KERNEL_map);
+
+	page = (void *)(xen_read_cr3() + __START_KERNEL_map);
+
+	addr = page[pgd_index(va)];
+	addr_to_page(addr, page);
+
+	addr = page[pud_index(va)];
+	addr_to_page(addr, page);
+
+	addr = page[pmd_index(va)];
+	addr_to_page(addr, page);
+
+	return (page[pte_index(va)] & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT;
+}
+
+#ifndef CONFIG_XEN
+static int __init parse_direct_gbpages_off(char *arg)
+{
+	direct_gbpages = 0;
+	return 0;
+}
+early_param("nogbpages", parse_direct_gbpages_off);
+
+static int __init parse_direct_gbpages_on(char *arg)
+{
+	direct_gbpages = 1;
+	return 0;
+}
+early_param("gbpages", parse_direct_gbpages_on);
+#endif
+
+/*
+ * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+ * physical space so we can cache the place of the first one and move
+ * around without checking the pgd every time.
+ */
+
+pteval_t __supported_pte_mask __read_mostly = ~0UL;
+EXPORT_SYMBOL_GPL(__supported_pte_mask);
+
+int force_personality32;
+
+/*
+ * 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 32-bit processes (default)
+ * off	PROT_READ implies PROT_EXEC
+ */
+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);
+
+static __init unsigned long get_table_end(void)
+{
+	BUG_ON(!e820_table_end);
+	if (xen_start_info->mfn_list < __START_KERNEL_map
+	    && e820_table_end == xen_start_info->first_p2m_pfn) {
+		e820_table_end += xen_start_info->nr_p2m_frames;
+		e820_table_top += xen_start_info->nr_p2m_frames;
+	}
+	return e820_table_end++;
+}
+
+/*
+ * NOTE: This function is marked __ref because it calls __init function
+ * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0.
+ */
+static __ref void *spp_getpage(void)
+{
+	void *ptr;
+
+	if (after_bootmem)
+		ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
+	else if (e820_table_end < e820_table_top) {
+		ptr = __va(get_table_end() << PAGE_SHIFT);
+		memset(ptr, 0, PAGE_SIZE);
+	} else
+		ptr = alloc_bootmem_pages(PAGE_SIZE);
+
+	if (!ptr || ((unsigned long)ptr & ~PAGE_MASK)) {
+		panic("set_pte_phys: cannot allocate page data %s\n",
+			after_bootmem ? "after bootmem" : "");
+	}
+
+	pr_debug("spp_getpage %p\n", ptr);
+
+	return ptr;
+}
+
+static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr)
+{
+	if (pgd_none(*pgd)) {
+		pud_t *pud = (pud_t *)spp_getpage();
+		make_page_readonly(pud, XENFEAT_writable_page_tables);
+		if (!after_bootmem)
+			xen_l4_entry_update(pgd, __pgd(__pa(pud) | _PAGE_TABLE));
+		else
+			pgd_populate(&init_mm, pgd, pud);
+		if (pud != pud_offset(pgd, 0))
+			printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n",
+			       pud, pud_offset(pgd, 0));
+	}
+	return pud_offset(pgd, vaddr);
+}
+
+static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr)
+{
+	if (pud_none(*pud)) {
+		pmd_t *pmd = (pmd_t *) spp_getpage();
+		make_page_readonly(pmd, XENFEAT_writable_page_tables);
+		if (!after_bootmem)
+			xen_l3_entry_update(pud, __pud(__pa(pmd) | _PAGE_TABLE));
+		else
+			pud_populate(&init_mm, pud, pmd);
+		if (pmd != pmd_offset(pud, 0))
+			printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n",
+			       pmd, pmd_offset(pud, 0));
+	}
+	return pmd_offset(pud, vaddr);
+}
+
+static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr)
+{
+	if (pmd_none(*pmd)) {
+		pte_t *pte = (pte_t *) spp_getpage();
+		make_page_readonly(pte, XENFEAT_writable_page_tables);
+		pmd_populate_kernel(&init_mm, pmd, pte);
+		if (pte != pte_offset_kernel(pmd, 0))
+			printk(KERN_ERR "PAGETABLE BUG #02!\n");
+	}
+	return pte_offset_kernel(pmd, vaddr);
+}
+
+void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte)
+{
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pud = pud_page + pud_index(vaddr);
+	pmd = fill_pmd(pud, vaddr);
+	pte = fill_pte(pmd, vaddr);
+
+	set_pte(pte, new_pte);
+
+	/*
+	 * It's enough to flush this one mapping.
+	 * (PGE mappings get flushed as well)
+	 */
+	__flush_tlb_one(vaddr);
+}
+
+void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
+{
+	pgd_t *pgd;
+	pud_t *pud_page;
+
+	pr_debug("set_pte_vaddr %lx to %lx\n", vaddr, __pte_val(pteval));
+
+	pgd = pgd_offset_k(vaddr);
+	if (pgd_none(*pgd)) {
+		printk(KERN_ERR
+			"PGD FIXMAP MISSING, it should be setup in head.S!\n");
+		return;
+	}
+	pud_page = (pud_t*)pgd_page_vaddr(*pgd);
+	set_pte_vaddr_pud(pud_page, vaddr, pteval);
+}
+
+pmd_t * __init populate_extra_pmd(unsigned long vaddr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+
+	pgd = pgd_offset_k(vaddr);
+	pud = fill_pud(pgd, vaddr);
+	return fill_pmd(pud, vaddr);
+}
+
+pte_t * __init populate_extra_pte(unsigned long vaddr)
+{
+	pmd_t *pmd;
+
+	pmd = populate_extra_pmd(vaddr);
+	return fill_pte(pmd, vaddr);
+}
+
+#ifndef CONFIG_XEN
+/*
+ * Create large page table mappings for a range of physical addresses.
+ */
+static void __init __init_extra_mapping(unsigned long phys, unsigned long size,
+						pgprot_t prot)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	BUG_ON((phys & ~PMD_MASK) || (size & ~PMD_MASK));
+	for (; size; phys += PMD_SIZE, size -= PMD_SIZE) {
+		pgd = pgd_offset_k((unsigned long)__va(phys));
+		if (pgd_none(*pgd)) {
+			pud = (pud_t *) spp_getpage();
+			set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE |
+						_PAGE_USER));
+		}
+		pud = pud_offset(pgd, (unsigned long)__va(phys));
+		if (pud_none(*pud)) {
+			pmd = (pmd_t *) spp_getpage();
+			set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE |
+						_PAGE_USER));
+		}
+		pmd = pmd_offset(pud, phys);
+		BUG_ON(!pmd_none(*pmd));
+		set_pmd(pmd, __pmd(phys | pgprot_val(prot)));
+	}
+}
+
+void __init init_extra_mapping_wb(unsigned long phys, unsigned long size)
+{
+	__init_extra_mapping(phys, size, PAGE_KERNEL_LARGE);
+}
+
+void __init init_extra_mapping_uc(unsigned long phys, unsigned long size)
+{
+	__init_extra_mapping(phys, size, PAGE_KERNEL_LARGE_NOCACHE);
+}
+
+/*
+ * The head.S code sets up the kernel high mapping:
+ *
+ *   from __START_KERNEL_map to __START_KERNEL_map + size (== _end-_text)
+ *
+ * phys_addr holds the negative offset to the kernel, which is added
+ * to the compile time generated pmds. This results in invalid pmds up
+ * to the point where we hit the physaddr 0 mapping.
+ *
+ * We limit the mappings to the region from _text to _end.  _end is
+ * rounded up to the 2MB boundary. This catches the invalid pmds as
+ * well, as they are located before _text:
+ */
+void __init cleanup_highmap(void)
+{
+	unsigned long vaddr = __START_KERNEL_map;
+	unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
+	pmd_t *pmd = level2_kernel_pgt;
+	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
+
+	for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
+		if (pmd_none(*pmd))
+			continue;
+		if (vaddr < (unsigned long) _text || vaddr > end)
+			set_pmd(pmd, __pmd(0));
+	}
+}
+#endif
+
+static __ref void *alloc_low_page(unsigned long *phys)
+{
+	unsigned long pfn;
+	void *adr;
+
+	if (after_bootmem) {
+		adr = (void *)get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK);
+		*phys = __pa(adr);
+
+		return adr;
+	}
+
+	pfn = get_table_end();
+	if (pfn >= e820_table_top)
+		panic("alloc_low_page: ran out of memory");
+
+	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
+	memset(adr, 0, PAGE_SIZE);
+	*phys  = pfn * PAGE_SIZE;
+	return adr;
+}
+
+static __ref void unmap_low_page(void *adr)
+{
+	if (after_bootmem)
+		return;
+
+	early_iounmap(adr, PAGE_SIZE);
+}
+
+static inline int __meminit make_readonly(unsigned long paddr)
+{
+	extern char __vsyscall_0;
+	int readonly = 0;
+
+	/* Make new page tables read-only on the first pass. */
+	if (!xen_feature(XENFEAT_writable_page_tables)
+	    && !max_pfn_mapped
+	    && (paddr >= (e820_table_start << PAGE_SHIFT))) {
+		unsigned long top = e820_table_top;
+
+		/* Account for the range get_table_end() skips. */
+		if (xen_start_info->mfn_list < __START_KERNEL_map
+		    && e820_table_end <= xen_start_info->first_p2m_pfn
+		    && top > xen_start_info->first_p2m_pfn)
+			top += xen_start_info->nr_p2m_frames;
+		if (paddr < (top << PAGE_SHIFT))
+			readonly = 1;
+	}
+	/* Make old page tables read-only. */
+	if (!xen_feature(XENFEAT_writable_page_tables)
+	    && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
+	    && (paddr < (e820_table_end << PAGE_SHIFT)))
+		readonly = 1;
+	/* Make P->M table (and its page tables) read-only. */
+	if (!xen_feature(XENFEAT_writable_page_tables)
+	    && xen_start_info->mfn_list < __START_KERNEL_map
+	    && paddr >= (xen_start_info->first_p2m_pfn << PAGE_SHIFT)
+	    && paddr < (xen_start_info->first_p2m_pfn
+			+ xen_start_info->nr_p2m_frames) << PAGE_SHIFT)
+		readonly = 1;
+
+	/*
+	 * No need for writable mapping of kernel image. This also ensures that
+	 * page and descriptor tables embedded inside don't have writable
+	 * mappings. Exclude the vsyscall area here, allowing alternative
+	 * instruction patching to work.
+	 */
+	if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa(_brk_end))
+	    && !(paddr >= __pa_symbol(&__vsyscall_0)
+	         && paddr < __pa_symbol(&__vsyscall_0) + PAGE_SIZE))
+		readonly = 1;
+
+	return readonly;
+}
+
+static unsigned long __meminit
+phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
+	      pgprot_t prot)
+{
+	unsigned pages = 0;
+	unsigned long last_map_addr = end;
+	int i;
+
+	pte_t *pte = pte_page + pte_index(addr);
+
+	for(i = pte_index(addr); i < PTRS_PER_PTE; i++, addr += PAGE_SIZE, pte++) {
+		unsigned long pteval = addr | pgprot_val(prot);
+
+		if (addr >= end ||
+		    (!after_bootmem &&
+		     (addr >> PAGE_SHIFT) >= xen_start_info->nr_pages))
+			break;
+
+		/*
+		 * We will re-use the existing mapping.
+		 * Xen for example has some special requirements, like mapping
+		 * pagetable pages as RO. So assume someone who pre-setup
+		 * these mappings are more intelligent.
+		 */
+		if (__pte_val(*pte)) {
+			pages++;
+			continue;
+		}
+
+		if (make_readonly(addr))
+			pteval &= ~_PAGE_RW;
+		if (0)
+			printk("   pte=%p addr=%lx pte=%016lx\n",
+			       pte, addr, pteval);
+		pages++;
+		if (!after_bootmem)
+			*pte = __pte(pteval & __supported_pte_mask);
+		else
+			set_pte(pte, __pte(pteval & __supported_pte_mask));
+		last_map_addr = (addr & PAGE_MASK) + PAGE_SIZE;
+	}
+
+	update_page_count(PG_LEVEL_4K, pages);
+
+	return last_map_addr;
+}
+
+static unsigned long __meminit
+phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end,
+		pgprot_t prot)
+{
+	pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
+
+	BUG_ON(!max_pfn_mapped);
+	return phys_pte_init(pte, address, end, prot);
+}
+
+static unsigned long __meminit
+phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
+	      unsigned long page_size_mask, pgprot_t prot)
+{
+	unsigned long pages = 0;
+	unsigned long last_map_addr = end;
+
+	int i = pmd_index(address);
+
+	for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
+		unsigned long pte_phys;
+		pmd_t *pmd = pmd_page + pmd_index(address);
+		pte_t *pte;
+		pgprot_t new_prot = prot;
+
+		if (address >= end)
+			break;
+
+		if (__pmd_val(*pmd)) {
+			if (!pmd_large(*pmd)) {
+				spin_lock(&init_mm.page_table_lock);
+				last_map_addr = phys_pte_update(pmd, address,
+								end, prot);
+				spin_unlock(&init_mm.page_table_lock);
+				continue;
+			}
+			/*
+			 * If we are ok with PG_LEVEL_2M mapping, then we will
+			 * use the existing mapping,
+			 *
+			 * Otherwise, we will split the large page mapping but
+			 * use the same existing protection bits except for
+			 * large page, so that we don't violate Intel's TLB
+			 * Application note (317080) which says, while changing
+			 * the page sizes, new and old translations should
+			 * not differ with respect to page frame and
+			 * attributes.
+			 */
+			if (page_size_mask & (1 << PG_LEVEL_2M)) {
+				pages++;
+				continue;
+			}
+			new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd));
+		}
+
+		if (page_size_mask & (1<<PG_LEVEL_2M)) {
+			pages++;
+			spin_lock(&init_mm.page_table_lock);
+			set_pte((pte_t *)pmd,
+				pfn_pte(address >> PAGE_SHIFT,
+					__pgprot(pgprot_val(prot) | _PAGE_PSE)));
+			spin_unlock(&init_mm.page_table_lock);
+			last_map_addr = (address & PMD_MASK) + PMD_SIZE;
+			continue;
+		}
+
+		pte = alloc_low_page(&pte_phys);
+		last_map_addr = phys_pte_init(pte, address, end, new_prot);
+		unmap_low_page(pte);
+
+		if (!after_bootmem) {
+			if (max_pfn_mapped)
+				make_page_readonly(__va(pte_phys),
+						   XENFEAT_writable_page_tables);
+			*pmd = __pmd(pte_phys | _PAGE_TABLE);
+		} else {
+			spin_lock(&init_mm.page_table_lock);
+			pmd_populate_kernel(&init_mm, pmd, __va(pte_phys));
+			spin_unlock(&init_mm.page_table_lock);
+		}
+	}
+	update_page_count(PG_LEVEL_2M, pages);
+	return last_map_addr;
+}
+
+static unsigned long __meminit
+phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
+		unsigned long page_size_mask, pgprot_t prot)
+{
+	pmd_t *pmd = pmd_offset(pud, 0);
+	unsigned long last_map_addr;
+
+	BUG_ON(!max_pfn_mapped);
+	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot);
+	__flush_tlb_all();
+	return last_map_addr;
+}
+
+static unsigned long __meminit
+phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
+			 unsigned long page_size_mask)
+{
+	unsigned long pages = 0;
+	unsigned long last_map_addr = end;
+	int i = pud_index(addr);
+
+	for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
+		unsigned long pmd_phys;
+		pud_t *pud = pud_page + pud_index(addr);
+		pmd_t *pmd;
+		pgprot_t prot = PAGE_KERNEL;
+
+		if (addr >= end)
+			break;
+
+		if (__pud_val(*pud)) {
+			if (!pud_large(*pud)) {
+				last_map_addr = phys_pmd_update(pud, addr, end,
+							 page_size_mask, prot);
+				continue;
+			}
+			/*
+			 * If we are ok with PG_LEVEL_1G mapping, then we will
+			 * use the existing mapping.
+			 *
+			 * Otherwise, we will split the gbpage mapping but use
+			 * the same existing protection  bits except for large
+			 * page, so that we don't violate Intel's TLB
+			 * Application note (317080) which says, while changing
+			 * the page sizes, new and old translations should
+			 * not differ with respect to page frame and
+			 * attributes.
+			 */
+			if (page_size_mask & (1 << PG_LEVEL_1G)) {
+				pages++;
+				continue;
+			}
+			prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud));
+		}
+
+		if (page_size_mask & (1<<PG_LEVEL_1G)) {
+			pages++;
+			spin_lock(&init_mm.page_table_lock);
+			set_pte((pte_t *)pud,
+				pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
+			spin_unlock(&init_mm.page_table_lock);
+			last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
+			continue;
+		}
+
+		pmd = alloc_low_page(&pmd_phys);
+		last_map_addr = phys_pmd_init(pmd, addr, end, page_size_mask,
+					      prot);
+		unmap_low_page(pmd);
+
+		if (!after_bootmem) {
+			if (max_pfn_mapped)
+				make_page_readonly(__va(pmd_phys),
+						   XENFEAT_writable_page_tables);
+			if (page_size_mask & (1 << PG_LEVEL_NUM))
+				xen_l3_entry_update(pud, __pud(pmd_phys | _PAGE_TABLE));
+			else
+				*pud = __pud(pmd_phys | _PAGE_TABLE);
+		} else {
+			spin_lock(&init_mm.page_table_lock);
+			pud_populate(&init_mm, pud, __va(pmd_phys));
+			spin_unlock(&init_mm.page_table_lock);
+		}
+	}
+	__flush_tlb_all();
+
+	update_page_count(PG_LEVEL_1G, pages);
+
+	return last_map_addr;
+}
+
+static unsigned long __meminit
+phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
+		 unsigned long page_size_mask)
+{
+	pud_t *pud;
+
+	pud = (pud_t *)pgd_page_vaddr(*pgd);
+
+	return phys_pud_init(pud, addr, end, page_size_mask | (1 << PG_LEVEL_NUM));
+}
+
+void __init xen_init_pt(void)
+{
+	unsigned long addr, *page;
+
+	/* Find the initial pte page that was built for us. */
+	page = (unsigned long *)xen_start_info->pt_base;
+	addr = page[pgd_index(__START_KERNEL_map)];
+	addr_to_page(addr, page);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	/* On Xen 3.0.2 and older we may need to explicitly specify _PAGE_USER
+	   in kernel PTEs. We check that here. */
+	if (HYPERVISOR_xen_version(XENVER_version, NULL) <= 0x30000) {
+		unsigned long *pg;
+		pte_t pte;
+
+		/* Mess with the initial mapping of page 0. It's not needed. */
+		BUILD_BUG_ON(__START_KERNEL <= __START_KERNEL_map);
+		addr = page[pud_index(__START_KERNEL_map)];
+		addr_to_page(addr, pg);
+		addr = pg[pmd_index(__START_KERNEL_map)];
+		addr_to_page(addr, pg);
+		pte.pte = pg[pte_index(__START_KERNEL_map)];
+		BUG_ON(!(pte.pte & _PAGE_PRESENT));
+
+		/* If _PAGE_USER isn't set, we obviously do not need it. */
+		if (pte.pte & _PAGE_USER) {
+			/* _PAGE_USER is needed, but is it set implicitly? */
+			pte.pte &= ~_PAGE_USER;
+			if ((HYPERVISOR_update_va_mapping(__START_KERNEL_map,
+							  pte, 0) != 0) ||
+			    !(pg[pte_index(__START_KERNEL_map)] & _PAGE_USER))
+				/* We need to explicitly specify _PAGE_USER. */
+				__kernel_page_user = _PAGE_USER;
+		}
+	}
+#endif
+
+	/* Construct mapping of initial pte page in our own directories. */
+	init_level4_pgt[pgd_index(__START_KERNEL_map)] = 
+		__pgd(__pa_symbol(level3_kernel_pgt) | _PAGE_TABLE);
+	memcpy(level3_kernel_pgt + pud_index(__START_KERNEL_map),
+	       page + pud_index(__START_KERNEL_map),
+	       (PTRS_PER_PUD - pud_index(__START_KERNEL_map))
+	       * sizeof(*level3_kernel_pgt));
+
+	/* Copy the initial P->M table mappings if necessary. */
+	addr = pgd_index(xen_start_info->mfn_list);
+	if (addr < pgd_index(__START_KERNEL_map))
+		init_level4_pgt[addr] =
+			((pgd_t *)xen_start_info->pt_base)[addr];
+
+	/* Do an early initialization of the fixmap area. */
+	addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE);
+	if (pud_present(level3_kernel_pgt[pud_index(addr)])) {
+		unsigned long adr = page[pud_index(addr)];
+
+		addr_to_page(adr, page);
+		memcpy(level2_fixmap_pgt, page, PAGE_SIZE);
+	}
+	level3_kernel_pgt[pud_index(addr)] =
+		__pud(__pa_symbol(level2_fixmap_pgt) | _PAGE_TABLE);
+	level2_fixmap_pgt[pmd_index(addr)] =
+		__pmd(__pa_symbol(level1_fixmap_pgt) | _PAGE_TABLE);
+
+	early_make_page_readonly(init_level4_pgt,
+				 XENFEAT_writable_page_tables);
+	early_make_page_readonly(level3_kernel_pgt,
+				 XENFEAT_writable_page_tables);
+	early_make_page_readonly(level3_user_pgt,
+				 XENFEAT_writable_page_tables);
+	early_make_page_readonly(level2_fixmap_pgt,
+				 XENFEAT_writable_page_tables);
+	early_make_page_readonly(level1_fixmap_pgt,
+				 XENFEAT_writable_page_tables);
+
+	if (!xen_feature(XENFEAT_writable_page_tables))
+		xen_pgd_pin(init_level4_pgt);
+}
+
+void __init xen_finish_init_mapping(void)
+{
+	unsigned long start, end;
+	struct mmuext_op mmuext;
+
+	/* Re-vector virtual addresses pointing into the initial
+	   mapping to the just-established permanent ones. */
+	xen_start_info = __va(__pa(xen_start_info));
+	xen_start_info->pt_base = (unsigned long)
+		__va(__pa(xen_start_info->pt_base));
+	if (!xen_feature(XENFEAT_auto_translated_physmap)
+	    && xen_start_info->mfn_list >= __START_KERNEL_map)
+		phys_to_machine_mapping =
+			__va(__pa(xen_start_info->mfn_list));
+	if (xen_start_info->mod_start)
+		xen_start_info->mod_start = (unsigned long)
+			__va(__pa(xen_start_info->mod_start));
+
+	/* Unpin the no longer used Xen provided page tables. */
+	mmuext.cmd = MMUEXT_UNPIN_TABLE;
+	mmuext.arg1.mfn = virt_to_mfn(xen_start_info->pt_base);
+	if (HYPERVISOR_mmuext_op(&mmuext, 1, NULL, DOMID_SELF))
+		BUG();
+
+	/* Destroy the Xen-created mappings beyond the kernel image. */
+	start = PAGE_ALIGN(_brk_end);
+	end   = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT);
+	for (; start < end; start += PAGE_SIZE)
+		if (HYPERVISOR_update_va_mapping(start, __pte_ma(0), 0))
+			BUG();
+
+	WARN(e820_table_end != e820_table_top, "start=%lx cur=%lx top=%lx\n",
+	     e820_table_start, e820_table_end, e820_table_top);
+	if (e820_table_end > e820_table_top)
+		e820_table_top = e820_table_end;
+}
+
+unsigned long __meminit
+kernel_physical_mapping_init(unsigned long start,
+			     unsigned long end,
+			     unsigned long page_size_mask)
+{
+
+	unsigned long next, last_map_addr = end;
+
+	start = (unsigned long)__va(start);
+	end = (unsigned long)__va(end);
+
+	for (; start < end; start = next) {
+		pgd_t *pgd = pgd_offset_k(start);
+		unsigned long pud_phys;
+		pud_t *pud;
+
+		next = (start + PGDIR_SIZE) & PGDIR_MASK;
+		if (next > end)
+			next = end;
+
+		if (__pgd_val(*pgd)) {
+			last_map_addr = phys_pud_update(pgd, __pa(start),
+						 __pa(end), page_size_mask);
+			continue;
+		}
+
+		pud = alloc_low_page(&pud_phys);
+		last_map_addr = phys_pud_init(pud, __pa(start), __pa(next),
+						 page_size_mask);
+		unmap_low_page(pud);
+
+		if(!after_bootmem) {
+			if (max_pfn_mapped)
+				make_page_readonly(__va(pud_phys),
+						   XENFEAT_writable_page_tables);
+			xen_l4_entry_update(pgd, __pgd(pud_phys | _PAGE_TABLE));
+		} else {
+			spin_lock(&init_mm.page_table_lock);
+			pgd_populate(&init_mm, pgd, __va(pud_phys));
+			spin_unlock(&init_mm.page_table_lock);
+		}
+	}
+
+	return last_map_addr;
+}
+
+#ifndef CONFIG_NUMA
+void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+{
+	unsigned long bootmap_size, bootmap;
+
+	e820_register_active_regions(0, start_pfn, end_pfn);
+#ifdef CONFIG_XEN
+	if (end_pfn > xen_start_info->nr_pages)
+		end_pfn = xen_start_info->nr_pages;
+#endif
+	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size,
+				 PAGE_SIZE);
+	if (bootmap == -1L)
+		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+	/* don't touch min_low_pfn */
+	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
+					 0, end_pfn);
+	free_bootmem_with_active_regions(0, end_pfn);
+	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
+	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+}
+#endif
+
+void __init paging_init(void)
+{
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
+	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
+	max_zone_pfns[ZONE_NORMAL] = max_pfn;
+
+	sparse_memory_present_with_active_regions(MAX_NUMNODES);
+	sparse_init();
+
+	/*
+	 * clear the default setting with node 0
+	 * note: don't use nodes_clear here, that is really clearing when
+	 *	 numa support is not compiled in, and later node_set_state
+	 *	 will not set it back.
+	 */
+	node_clear_state(0, N_NORMAL_MEMORY);
+
+	free_area_init_nodes(max_zone_pfns);
+
+	xen_init_pgd_pin();
+}
+
+/*
+ * Memory hotplug specific functions
+ */
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void  update_end_of_memory_vars(u64 start, u64 size)
+{
+	unsigned long end_pfn = PFN_UP(start + size);
+
+	if (end_pfn > max_pfn) {
+		max_pfn = end_pfn;
+		max_low_pfn = end_pfn;
+		high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+	}
+}
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+	struct pglist_data *pgdat = NODE_DATA(nid);
+	struct zone *zone = pgdat->node_zones + ZONE_NORMAL;
+	unsigned long last_mapped_pfn, start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+	int ret;
+
+	last_mapped_pfn = init_memory_mapping(start, start + size);
+	if (last_mapped_pfn > max_pfn_mapped)
+		max_pfn_mapped = last_mapped_pfn;
+
+	ret = __add_pages(nid, zone, start_pfn, nr_pages);
+	WARN_ON_ONCE(ret);
+
+	/* update max_pfn, max_low_pfn and high_memory */
+	update_end_of_memory_vars(start, size);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(arch_add_memory);
+
+#if !defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA)
+int memory_add_physaddr_to_nid(u64 start)
+{
+	return 0;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+#endif
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
+static struct kcore_list kcore_vsyscall;
+
+void __init mem_init(void)
+{
+	long codesize, reservedpages, datasize, initsize;
+	unsigned long absent_pages;
+	unsigned long pfn;
+
+	pci_iommu_alloc();
+
+	/* clear_bss() already clear the empty_zero_page */
+
+	reservedpages = 0;
+
+	/* this will put all low memory onto the freelists */
+#ifdef CONFIG_NUMA
+	totalram_pages = numa_free_all_bootmem();
+#else
+	totalram_pages = free_all_bootmem();
+#endif
+
+	/* XEN: init pages outside initial allocation. */
+	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
+		ClearPageReserved(pfn_to_page(pfn));
+		init_page_count(pfn_to_page(pfn));
+	}
+
+	absent_pages = absent_pages_in_range(0, max_pfn);
+	reservedpages = max_pfn - totalram_pages - absent_pages;
+	after_bootmem = 1;
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	/* Register memory areas for /proc/kcore */
+	kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START,
+			 VSYSCALL_END - VSYSCALL_START, KCORE_OTHER);
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
+			 "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n",
+		nr_free_pages() << (PAGE_SHIFT-10),
+		max_pfn << (PAGE_SHIFT-10),
+		codesize >> 10,
+		absent_pages << (PAGE_SHIFT-10),
+		reservedpages << (PAGE_SHIFT-10),
+		datasize >> 10,
+		initsize >> 10);
+}
+
+#ifdef CONFIG_DEBUG_RODATA
+const int rodata_test_data = 0xC3;
+EXPORT_SYMBOL_GPL(rodata_test_data);
+
+static int kernel_set_to_readonly;
+
+void set_kernel_text_rw(void)
+{
+	unsigned long start = PFN_ALIGN(_stext);
+	unsigned long end = PFN_ALIGN(__start_rodata);
+
+	if (!kernel_set_to_readonly)
+		return;
+
+	pr_debug("Set kernel text: %lx - %lx for read write\n",
+		 start, end);
+
+	set_memory_rw(start, (end - start) >> PAGE_SHIFT);
+}
+
+void set_kernel_text_ro(void)
+{
+	unsigned long start = PFN_ALIGN(_stext);
+	unsigned long end = PFN_ALIGN(__start_rodata);
+
+	if (!kernel_set_to_readonly)
+		return;
+
+	pr_debug("Set kernel text: %lx - %lx for read only\n",
+		 start, end);
+
+	set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+}
+
+void mark_rodata_ro(void)
+{
+	unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata);
+	unsigned long rodata_start =
+		((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK;
+
+	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+	       (end - start) >> 10);
+	set_memory_ro(start, (end - start) >> PAGE_SHIFT);
+
+	kernel_set_to_readonly = 1;
+
+	/*
+	 * The rodata section (but not the kernel text!) should also be
+	 * not-executable.
+	 */
+	set_memory_nx(rodata_start, (end - rodata_start) >> PAGE_SHIFT);
+
+	rodata_test();
+
+#ifdef CONFIG_CPA_DEBUG
+	printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, end);
+	set_memory_rw(start, (end-start) >> PAGE_SHIFT);
+
+	printk(KERN_INFO "Testing CPA: again\n");
+	set_memory_ro(start, (end-start) >> PAGE_SHIFT);
+#endif
+}
+
+#endif
+
+int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+				   int flags)
+{
+#ifdef CONFIG_NUMA
+	int nid, next_nid;
+	int ret;
+#endif
+	unsigned long pfn = phys >> PAGE_SHIFT;
+
+	if (pfn >= max_pfn) {
+		/*
+		 * This can happen with kdump kernels when accessing
+		 * firmware tables:
+		 */
+		if (pfn < max_pfn_mapped)
+			return -EFAULT;
+
+		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %lu\n",
+				phys, len);
+		return -EFAULT;
+	}
+
+	/* Should check here against the e820 map to avoid double free */
+#ifdef CONFIG_NUMA
+	nid = phys_to_nid(phys);
+	next_nid = phys_to_nid(phys + len - 1);
+	if (nid == next_nid)
+		ret = reserve_bootmem_node(NODE_DATA(nid), phys, len, flags);
+	else
+		ret = reserve_bootmem(phys, len, flags);
+
+	if (ret != 0)
+		return ret;
+
+#else
+	reserve_bootmem(phys, len, flags);
+#endif
+
+#ifndef CONFIG_XEN
+	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
+		dma_reserve += len / PAGE_SIZE;
+		set_dma_reserve(dma_reserve);
+	}
+#endif
+
+	return 0;
+}
+
+int kern_addr_valid(unsigned long addr)
+{
+	unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (above != 0 && above != -1UL)
+		return 0;
+
+	pgd = pgd_offset_k(addr);
+	if (pgd_none(*pgd))
+		return 0;
+
+	pud = pud_offset(pgd, addr);
+	if (pud_none(*pud))
+		return 0;
+
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none(*pmd))
+		return 0;
+
+	if (pmd_large(*pmd))
+		return pfn_valid(pmd_pfn(*pmd));
+
+	pte = pte_offset_kernel(pmd, addr);
+	if (pte_none(*pte))
+		return 0;
+
+	return pfn_valid(pte_pfn(*pte));
+}
+
+/*
+ * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
+ * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+ * not need special handling anymore:
+ */
+static struct vm_area_struct gate_vma = {
+	.vm_start	= VSYSCALL_START,
+	.vm_end		= VSYSCALL_START + (VSYSCALL_MAPPED_PAGES * PAGE_SIZE),
+	.vm_page_prot	= PAGE_READONLY_EXEC,
+	.vm_flags	= VM_READ | VM_EXEC
+};
+
+struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+{
+#ifdef CONFIG_IA32_EMULATION
+	if (test_tsk_thread_flag(tsk, TIF_IA32))
+		return NULL;
+#endif
+	return &gate_vma;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long addr)
+{
+	struct vm_area_struct *vma = get_gate_vma(task);
+
+	if (!vma)
+		return 0;
+
+	return (addr >= vma->vm_start) && (addr < vma->vm_end);
+}
+
+/*
+ * Use this when you have no reliable task/vma, typically from interrupt
+ * context. It is less reliable than using the task's vma and may give
+ * false positives:
+ */
+int in_gate_area_no_task(unsigned long addr)
+{
+	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	if (vma == &gate_vma)
+		return "[vsyscall]";
+	return NULL;
+}
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+/*
+ * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
+ */
+static long __meminitdata addr_start, addr_end;
+static void __meminitdata *p_start, *p_end;
+static int __meminitdata node_start;
+
+int __meminit
+vmemmap_populate(struct page *start_page, unsigned long size, int node)
+{
+	unsigned long addr = (unsigned long)start_page;
+	unsigned long end = (unsigned long)(start_page + size);
+	unsigned long next;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	for (; addr < end; addr = next) {
+		void *p = NULL;
+
+		pgd = vmemmap_pgd_populate(addr, node);
+		if (!pgd)
+			return -ENOMEM;
+
+		pud = vmemmap_pud_populate(pgd, addr, node);
+		if (!pud)
+			return -ENOMEM;
+
+		if (!cpu_has_pse) {
+			next = (addr + PAGE_SIZE) & PAGE_MASK;
+			pmd = vmemmap_pmd_populate(pud, addr, node);
+
+			if (!pmd)
+				return -ENOMEM;
+
+			p = vmemmap_pte_populate(pmd, addr, node);
+
+			if (!p)
+				return -ENOMEM;
+
+			addr_end = addr + PAGE_SIZE;
+			p_end = p + PAGE_SIZE;
+		} else {
+			next = pmd_addr_end(addr, end);
+
+			pmd = pmd_offset(pud, addr);
+			if (pmd_none(*pmd)) {
+				pte_t entry;
+
+				p = vmemmap_alloc_block(PMD_SIZE, node);
+				if (!p)
+					return -ENOMEM;
+
+				entry = pfn_pte(__pa(p) >> PAGE_SHIFT,
+						PAGE_KERNEL_LARGE);
+				set_pmd(pmd, __pmd_ma(__pte_val(entry)));
+
+				/* check to see if we have contiguous blocks */
+				if (p_end != p || node_start != node) {
+					if (p_start)
+						printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
+						       addr_start, addr_end-1, p_start, p_end-1, node_start);
+					addr_start = addr;
+					node_start = node;
+					p_start = p;
+				}
+
+				addr_end = addr + PMD_SIZE;
+				p_end = p + PMD_SIZE;
+			} else
+				vmemmap_verify((pte_t *)pmd, node, addr, next);
+		}
+
+	}
+	return 0;
+}
+
+void __meminit vmemmap_populate_print_last(void)
+{
+	if (p_start) {
+		printk(KERN_DEBUG " [%lx-%lx] PMD -> [%p-%p] on node %d\n",
+			addr_start, addr_end-1, p_start, p_end-1, node_start);
+		p_start = NULL;
+		p_end = NULL;
+		node_start = 0;
+	}
+}
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/mm/pat-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/pat-xen.c
@@ -0,0 +1,1028 @@
+/*
+ * Handle caching attributes in page tables (PAT)
+ *
+ * Authors: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ *          Suresh B Siddha <suresh.b.siddha@intel.com>
+ *
+ * Loosely based on earlier PAT patchset from Eric Biederman and Andi Kleen.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/bootmem.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/rbtree.h>
+
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/fcntl.h>
+#include <asm/e820.h>
+#include <asm/mtrr.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/pat.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_X86_PAT
+int __read_mostly pat_enabled = 1;
+
+static inline void pat_disable(const char *reason)
+{
+	pat_enabled = 0;
+	printk(KERN_INFO "%s\n", reason);
+}
+
+static int __init nopat(char *str)
+{
+	pat_disable("PAT support disabled.");
+	return 0;
+}
+early_param("nopat", nopat);
+#else
+static inline void pat_disable(const char *reason)
+{
+	(void)reason;
+}
+#endif
+
+
+static int debug_enable;
+
+static int __init pat_debug_setup(char *str)
+{
+	debug_enable = 1;
+	return 0;
+}
+__setup("debugpat", pat_debug_setup);
+
+#define dprintk(fmt, arg...) \
+	do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
+
+
+static u64 __read_mostly boot_pat_state;
+
+enum {
+	PAT_UC = 0,		/* uncached */
+	PAT_WC = 1,		/* Write combining */
+	PAT_WT = 4,		/* Write Through */
+	PAT_WP = 5,		/* Write Protected */
+	PAT_WB = 6,		/* Write Back (default) */
+	PAT_UC_MINUS = 7,	/* UC, but can be overriden by MTRR */
+};
+
+#define PAT(x, y)	((u64)PAT_ ## y << ((x)*8))
+
+void pat_init(void)
+{
+	u64 pat;
+	bool boot_cpu = !boot_pat_state;
+
+	if (!pat_enabled)
+		return;
+
+	if (!cpu_has_pat) {
+		if (!boot_pat_state) {
+			pat_disable("PAT not supported by CPU.");
+			return;
+		} else {
+			/*
+			 * If this happens we are on a secondary CPU, but
+			 * switched to PAT on the boot CPU. We have no way to
+			 * undo PAT.
+			 */
+			printk(KERN_ERR "PAT enabled, "
+			       "but not supported by secondary CPU\n");
+			BUG();
+		}
+	}
+
+#ifndef CONFIG_XEN
+	/* Set PWT to Write-Combining. All other bits stay the same */
+	/*
+	 * PTE encoding used in Linux:
+	 *      PAT
+	 *      |PCD
+	 *      ||PWT
+	 *      |||
+	 *      000 WB		_PAGE_CACHE_WB
+	 *      001 WC		_PAGE_CACHE_WC
+	 *      010 UC-		_PAGE_CACHE_UC_MINUS
+	 *      011 UC		_PAGE_CACHE_UC
+	 * PAT bit unused
+	 */
+	pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
+	      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
+
+	/* Boot CPU check */
+	if (!boot_pat_state)
+		rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
+
+	wrmsrl(MSR_IA32_CR_PAT, pat);
+#else
+	/*
+	 * PAT settings are part of the hypervisor interface, and their
+	 * assignment cannot be changed.
+	 */
+	rdmsrl(MSR_IA32_CR_PAT, pat);
+	if (!boot_pat_state)
+		boot_pat_state = pat;
+#endif
+
+	if (boot_cpu)
+		printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
+		       smp_processor_id(), boot_pat_state, pat);
+}
+
+#undef PAT
+
+static char *cattr_name(unsigned long flags)
+{
+	switch (flags & _PAGE_CACHE_MASK) {
+	case _PAGE_CACHE_UC:		return "uncached";
+	case _PAGE_CACHE_UC_MINUS:	return "uncached-minus";
+	case _PAGE_CACHE_WB:		return "write-back";
+	case _PAGE_CACHE_WC:		return "write-combining";
+	case _PAGE_CACHE_WP:		return "write-protected";
+	case _PAGE_CACHE_WT:		return "write-through";
+	default:			return "broken";
+	}
+}
+
+/*
+ * The global memtype list keeps track of memory type for specific
+ * physical memory areas. Conflicting memory types in different
+ * mappings can cause CPU cache corruption. To avoid this we keep track.
+ *
+ * The list is sorted based on starting address and can contain multiple
+ * entries for each address (this allows reference counting for overlapping
+ * areas). All the aliases have the same cache attributes of course.
+ * Zero attributes are represented as holes.
+ *
+ * The data structure is a list that is also organized as an rbtree
+ * sorted on the start address of memtype range.
+ *
+ * memtype_lock protects both the linear list and rbtree.
+ */
+
+struct memtype {
+	u64			start;
+	u64			end;
+	unsigned long		type;
+	struct list_head	nd;
+	struct rb_node		rb;
+};
+
+static struct rb_root memtype_rbroot = RB_ROOT;
+static LIST_HEAD(memtype_list);
+static DEFINE_SPINLOCK(memtype_lock);	/* protects memtype list */
+
+static struct memtype *memtype_rb_search(struct rb_root *root, u64 start)
+{
+	struct rb_node *node = root->rb_node;
+	struct memtype *last_lower = NULL;
+
+	while (node) {
+		struct memtype *data = container_of(node, struct memtype, rb);
+
+		if (data->start < start) {
+			last_lower = data;
+			node = node->rb_right;
+		} else if (data->start > start) {
+			node = node->rb_left;
+		} else
+			return data;
+	}
+
+	/* Will return NULL if there is no entry with its start <= start */
+	return last_lower;
+}
+
+static void memtype_rb_insert(struct rb_root *root, struct memtype *data)
+{
+	struct rb_node **new = &(root->rb_node);
+	struct rb_node *parent = NULL;
+
+	while (*new) {
+		struct memtype *this = container_of(*new, struct memtype, rb);
+
+		parent = *new;
+		if (data->start <= this->start)
+			new = &((*new)->rb_left);
+		else if (data->start > this->start)
+			new = &((*new)->rb_right);
+	}
+
+	rb_link_node(&data->rb, parent, new);
+	rb_insert_color(&data->rb, root);
+}
+
+/*
+ * Does intersection of PAT memory type and MTRR memory type and returns
+ * the resulting memory type as PAT understands it.
+ * (Type in pat and mtrr will not have same value)
+ * The intersection is based on "Effective Memory Type" tables in IA-32
+ * SDM vol 3a
+ */
+static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type)
+{
+	/*
+	 * Look for MTRR hint to get the effective type in case where PAT
+	 * request is for WB.
+	 */
+	if (req_type == _PAGE_CACHE_WB) {
+		u8 mtrr_type;
+
+		mtrr_type = mtrr_type_lookup(start, end);
+		if (mtrr_type != MTRR_TYPE_WRBACK)
+			return _PAGE_CACHE_UC_MINUS;
+
+		return _PAGE_CACHE_WB;
+	}
+
+	return req_type;
+}
+
+static int
+chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type)
+{
+	if (new->type != entry->type) {
+		if (type) {
+			new->type = entry->type;
+			*type = entry->type;
+		} else
+			goto conflict;
+	}
+
+	 /* check overlaps with more than one entry in the list */
+	list_for_each_entry_continue(entry, &memtype_list, nd) {
+		if (new->end <= entry->start)
+			break;
+		else if (new->type != entry->type)
+			goto conflict;
+	}
+	return 0;
+
+ conflict:
+	printk(KERN_INFO "%s:%d conflicting memory types "
+	       "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start,
+	       new->end, cattr_name(new->type), cattr_name(entry->type));
+	return -EBUSY;
+}
+
+static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
+{
+	int ram_page = 0, not_rampage = 0;
+	unsigned long page_nr;
+
+	for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
+	     ++page_nr) {
+		/*
+		 * For legacy reasons, physical address range in the legacy ISA
+		 * region is tracked as non-RAM. This will allow users of
+		 * /dev/mem to map portions of legacy ISA region, even when
+		 * some of those portions are listed(or not even listed) with
+		 * different e820 types(RAM/reserved/..)
+		 */
+		if (page_nr >= (ISA_END_ADDRESS >> PAGE_SHIFT) &&
+		    page_is_ram(mfn_to_local_pfn(page_nr)))
+			ram_page = 1;
+		else
+			not_rampage = 1;
+
+		if (ram_page == not_rampage)
+			return -1;
+	}
+
+	return ram_page;
+}
+
+/*
+ * For RAM pages, we use page flags to mark the pages with appropriate type.
+ * Here we do two pass:
+ * - Find the memtype of all the pages in the range, look for any conflicts
+ * - In case of no conflicts, set the new memtype for pages in the range
+ *
+ * Caller must hold memtype_lock for atomicity.
+ */
+static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
+				  unsigned long *new_type)
+{
+	struct page *page;
+	u64 pfn;
+
+	if (req_type == _PAGE_CACHE_UC) {
+		/* We do not support strong UC */
+		WARN_ON_ONCE(1);
+		req_type = _PAGE_CACHE_UC_MINUS;
+	}
+
+	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+		unsigned long type;
+
+		page = pfn_to_page(pfn);
+		type = get_page_memtype(page);
+		if (type != -1) {
+			printk(KERN_INFO "reserve_ram_pages_type failed "
+				"0x%Lx-0x%Lx, track 0x%lx, req 0x%lx\n",
+				start, end, type, req_type);
+			if (new_type)
+				*new_type = type;
+
+			return -EBUSY;
+		}
+	}
+
+	if (new_type)
+		*new_type = req_type;
+
+	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+		page = pfn_to_page(pfn);
+		set_page_memtype(page, req_type);
+	}
+	return 0;
+}
+
+static int free_ram_pages_type(u64 start, u64 end)
+{
+	struct page *page;
+	u64 pfn;
+
+	for (pfn = (start >> PAGE_SHIFT); pfn < (end >> PAGE_SHIFT); ++pfn) {
+		page = pfn_to_page(pfn);
+		set_page_memtype(page, -1);
+	}
+	return 0;
+}
+
+/*
+ * req_type typically has one of the:
+ * - _PAGE_CACHE_WB
+ * - _PAGE_CACHE_WC
+ * - _PAGE_CACHE_UC_MINUS
+ * - _PAGE_CACHE_UC
+ *
+ * req_type will have a special case value '-1', when requester want to inherit
+ * the memory type from mtrr (if WB), existing PAT, defaulting to UC_MINUS.
+ *
+ * If new_type is NULL, function will return an error if it cannot reserve the
+ * region with req_type. If new_type is non-NULL, function will return
+ * available type in new_type in case of no error. In case of any error
+ * it will return a negative return value.
+ */
+int reserve_memtype(u64 start, u64 end, unsigned long req_type,
+		    unsigned long *new_type)
+{
+	struct memtype *new, *entry;
+	unsigned long actual_type;
+	struct list_head *where;
+	int is_range_ram;
+	int err = 0;
+
+	BUG_ON(start >= end); /* end is exclusive */
+
+	if (!pat_enabled) {
+		/* This is identical to page table setting without PAT */
+		if (new_type) {
+			if (req_type == -1)
+				*new_type = _PAGE_CACHE_WB;
+			else if (req_type == _PAGE_CACHE_WC)
+				*new_type = _PAGE_CACHE_UC_MINUS;
+			else
+				*new_type = req_type & _PAGE_CACHE_MASK;
+		}
+		return 0;
+	}
+
+	/* Low ISA region is always mapped WB in page table. No need to track */
+	if (is_ISA_range(start, end - 1)) {
+		if (new_type)
+			*new_type = _PAGE_CACHE_WB;
+		return 0;
+	}
+
+	/*
+	 * Call mtrr_lookup to get the type hint. This is an
+	 * optimization for /dev/mem mmap'ers into WB memory (BIOS
+	 * tools and ACPI tools). Use WB request for WB memory and use
+	 * UC_MINUS otherwise.
+	 */
+	actual_type = pat_x_mtrr_type(start, end, req_type & _PAGE_CACHE_MASK);
+
+	if (new_type)
+		*new_type = actual_type;
+
+	is_range_ram = pat_pagerange_is_ram(start, end);
+	if (is_range_ram == 1) {
+
+		spin_lock(&memtype_lock);
+		err = reserve_ram_pages_type(start, end, req_type, new_type);
+		spin_unlock(&memtype_lock);
+
+		return err;
+	} else if (is_range_ram < 0) {
+		return -EINVAL;
+	}
+
+	new  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	new->start	= start;
+	new->end	= end;
+	new->type	= actual_type;
+
+	spin_lock(&memtype_lock);
+
+	/* Search for existing mapping that overlaps the current range */
+	where = NULL;
+	list_for_each_entry(entry, &memtype_list, nd) {
+		if (end <= entry->start) {
+			where = entry->nd.prev;
+			break;
+		} else if (start <= entry->start) { /* end > entry->start */
+			err = chk_conflict(new, entry, new_type);
+			if (!err) {
+				dprintk("Overlap at 0x%Lx-0x%Lx\n",
+					entry->start, entry->end);
+				where = entry->nd.prev;
+			}
+			break;
+		} else if (start < entry->end) { /* start > entry->start */
+			err = chk_conflict(new, entry, new_type);
+			if (!err) {
+				dprintk("Overlap at 0x%Lx-0x%Lx\n",
+					entry->start, entry->end);
+
+				/*
+				 * Move to right position in the linked
+				 * list to add this new entry
+				 */
+				list_for_each_entry_continue(entry,
+							&memtype_list, nd) {
+					if (start <= entry->start) {
+						where = entry->nd.prev;
+						break;
+					}
+				}
+			}
+			break;
+		}
+	}
+
+	if (err) {
+		printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
+		       "track %s, req %s\n",
+		       start, end, cattr_name(new->type), cattr_name(req_type));
+		kfree(new);
+		spin_unlock(&memtype_lock);
+
+		return err;
+	}
+
+	if (where)
+		list_add(&new->nd, where);
+	else
+		list_add_tail(&new->nd, &memtype_list);
+
+	memtype_rb_insert(&memtype_rbroot, new);
+
+	spin_unlock(&memtype_lock);
+
+	dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
+		start, end, cattr_name(new->type), cattr_name(req_type),
+		new_type ? cattr_name(*new_type) : "-");
+
+	return err;
+}
+
+int free_memtype(u64 start, u64 end)
+{
+	struct memtype *entry, *saved_entry;
+	int err = -EINVAL;
+	int is_range_ram;
+
+	if (!pat_enabled)
+		return 0;
+
+	/* Low ISA region is always mapped WB. No need to track */
+	if (is_ISA_range(start, end - 1))
+		return 0;
+
+	is_range_ram = pat_pagerange_is_ram(start, end);
+	if (is_range_ram == 1) {
+
+		spin_lock(&memtype_lock);
+		err = free_ram_pages_type(start, end);
+		spin_unlock(&memtype_lock);
+
+		return err;
+	} else if (is_range_ram < 0) {
+		return -EINVAL;
+	}
+
+	spin_lock(&memtype_lock);
+
+	entry = memtype_rb_search(&memtype_rbroot, start);
+	if (unlikely(entry == NULL))
+		goto unlock_ret;
+
+	/*
+	 * Saved entry points to an entry with start same or less than what
+	 * we searched for. Now go through the list in both directions to look
+	 * for the entry that matches with both start and end, with list stored
+	 * in sorted start address
+	 */
+	saved_entry = entry;
+	list_for_each_entry_from(entry, &memtype_list, nd) {
+		if (entry->start == start && entry->end == end) {
+			rb_erase(&entry->rb, &memtype_rbroot);
+			list_del(&entry->nd);
+			kfree(entry);
+			err = 0;
+			break;
+		} else if (entry->start > start) {
+			break;
+		}
+	}
+
+	if (!err)
+		goto unlock_ret;
+
+	entry = saved_entry;
+	list_for_each_entry_reverse(entry, &memtype_list, nd) {
+		if (entry->start == start && entry->end == end) {
+			rb_erase(&entry->rb, &memtype_rbroot);
+			list_del(&entry->nd);
+			kfree(entry);
+			err = 0;
+			break;
+		} else if (entry->start < start) {
+			break;
+		}
+	}
+unlock_ret:
+	spin_unlock(&memtype_lock);
+
+	if (err) {
+		printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n",
+			current->comm, current->pid, start, end);
+	}
+
+	dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
+
+	return err;
+}
+
+
+#ifndef CONFIG_XEN
+/**
+ * lookup_memtype - Looksup the memory type for a physical address
+ * @paddr: physical address of which memory type needs to be looked up
+ *
+ * Only to be called when PAT is enabled
+ *
+ * Returns _PAGE_CACHE_WB, _PAGE_CACHE_WC, _PAGE_CACHE_UC_MINUS or
+ * _PAGE_CACHE_UC
+ */
+static unsigned long lookup_memtype(u64 paddr)
+{
+	int rettype = _PAGE_CACHE_WB;
+	struct memtype *entry;
+
+	if (is_ISA_range(paddr, paddr + PAGE_SIZE - 1))
+		return rettype;
+
+	if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) {
+		struct page *page;
+		spin_lock(&memtype_lock);
+		page = pfn_to_page(paddr >> PAGE_SHIFT);
+		rettype = get_page_memtype(page);
+		spin_unlock(&memtype_lock);
+		/*
+		 * -1 from get_page_memtype() implies RAM page is in its
+		 * default state and not reserved, and hence of type WB
+		 */
+		if (rettype == -1)
+			rettype = _PAGE_CACHE_WB;
+
+		return rettype;
+	}
+
+	spin_lock(&memtype_lock);
+
+	entry = memtype_rb_search(&memtype_rbroot, paddr);
+	if (entry != NULL)
+		rettype = entry->type;
+	else
+		rettype = _PAGE_CACHE_UC_MINUS;
+
+	spin_unlock(&memtype_lock);
+	return rettype;
+}
+#endif
+
+/**
+ * io_reserve_memtype - Request a memory type mapping for a region of memory
+ * @start: start (physical address) of the region
+ * @end: end (physical address) of the region
+ * @type: A pointer to memtype, with requested type. On success, requested
+ * or any other compatible type that was available for the region is returned
+ *
+ * On success, returns 0
+ * On failure, returns non-zero
+ */
+int io_reserve_memtype(resource_size_t start, resource_size_t end,
+			unsigned long *type)
+{
+	resource_size_t size = end - start;
+	unsigned long req_type = *type;
+	unsigned long new_type;
+	int ret;
+
+	WARN_ON_ONCE(iomem_map_sanity_check(start, size));
+
+	ret = reserve_memtype(start, end, req_type, &new_type);
+	if (ret)
+		goto out_err;
+
+	if (!is_new_memtype_allowed(start, size, req_type, new_type))
+		goto out_free;
+
+	if (kernel_map_sync_memtype(start, size, new_type) < 0)
+		goto out_free;
+
+	*type = new_type;
+	return 0;
+
+out_free:
+	free_memtype(start, end);
+	ret = -EBUSY;
+out_err:
+	return ret;
+}
+
+/**
+ * io_free_memtype - Release a memory type mapping for a region of memory
+ * @start: start (physical address) of the region
+ * @end: end (physical address) of the region
+ */
+void io_free_memtype(resource_size_t start, resource_size_t end)
+{
+	free_memtype(start, end);
+}
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long mfn,
+				unsigned long size, pgprot_t vma_prot)
+{
+	return vma_prot;
+}
+
+#ifdef CONFIG_STRICT_DEVMEM
+/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/
+static inline int range_is_allowed(unsigned long mfn, unsigned long size)
+{
+	return 1;
+}
+#else
+/* This check is needed to avoid cache aliasing when PAT is enabled */
+static inline int range_is_allowed(unsigned long mfn, unsigned long size)
+{
+	u64 from = ((u64)mfn) << PAGE_SHIFT;
+	u64 to = from + size;
+	u64 cursor = from;
+
+	if (!pat_enabled)
+		return 1;
+
+	while (cursor < to) {
+		if (!devmem_is_allowed(mfn)) {
+			printk(KERN_INFO
+		"Program %s tried to access /dev/mem between %Lx->%Lx.\n",
+				current->comm, from, to);
+			return 0;
+		}
+		cursor += PAGE_SIZE;
+		mfn++;
+	}
+	return 1;
+}
+#endif /* CONFIG_STRICT_DEVMEM */
+
+int phys_mem_access_prot_allowed(struct file *file, unsigned long mfn,
+				unsigned long size, pgprot_t *vma_prot)
+{
+	unsigned long flags = _PAGE_CACHE_WB;
+
+	if (!range_is_allowed(mfn, size))
+		return 0;
+
+	if (file->f_flags & O_SYNC) {
+		flags = _PAGE_CACHE_UC_MINUS;
+	}
+
+#ifndef CONFIG_X86_32
+#ifndef CONFIG_XEN /* Xen sets correct MTRR type on non-RAM for us. */
+	/*
+	 * On the PPro and successors, the MTRRs are used to set
+	 * memory types for physical addresses outside main memory,
+	 * so blindly setting UC or PWT on those pages is wrong.
+	 * For Pentiums and earlier, the surround logic should disable
+	 * caching for the high addresses through the KEN pin, but
+	 * we maintain the tradition of paranoia in this code.
+	 */
+	if (!pat_enabled &&
+	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
+	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
+	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
+	      boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
+	    (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
+		flags = _PAGE_CACHE_UC;
+	}
+#endif
+#endif
+
+	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
+			     flags);
+	return 1;
+}
+
+/*
+ * Change the memory type for the physial address range in kernel identity
+ * mapping space if that range is a part of identity map.
+ */
+int kernel_map_sync_memtype(u64 ma, unsigned long size, unsigned long flags)
+{
+	return ioremap_check_change_attr(ma >> PAGE_SHIFT, size, flags);
+}
+
+#ifndef CONFIG_XEN
+/*
+ * Internal interface to reserve a range of physical memory with prot.
+ * Reserved non RAM regions only and after successful reserve_memtype,
+ * this func also keeps identity mapping (if any) in sync with this new prot.
+ */
+static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
+				int strict_prot)
+{
+	int is_ram = 0;
+	int ret;
+	unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
+	unsigned long flags = want_flags;
+
+	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
+
+	/*
+	 * reserve_pfn_range() for RAM pages. We do not refcount to keep
+	 * track of number of mappings of RAM pages. We can assert that
+	 * the type requested matches the type of first page in the range.
+	 */
+	if (is_ram) {
+		if (!pat_enabled)
+			return 0;
+
+		flags = lookup_memtype(paddr);
+		if (want_flags != flags) {
+			printk(KERN_WARNING
+			"%s:%d map pfn RAM range req %s for %Lx-%Lx, got %s\n",
+				current->comm, current->pid,
+				cattr_name(want_flags),
+				(unsigned long long)paddr,
+				(unsigned long long)(paddr + size),
+				cattr_name(flags));
+			*vma_prot = __pgprot((pgprot_val(*vma_prot) &
+					      (~_PAGE_CACHE_MASK)) |
+					     flags);
+		}
+		return 0;
+	}
+
+	ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
+	if (ret)
+		return ret;
+
+	if (flags != want_flags) {
+		if (strict_prot ||
+		    !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
+			free_memtype(paddr, paddr + size);
+			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
+				" for %Lx-%Lx, got %s\n",
+				current->comm, current->pid,
+				cattr_name(want_flags),
+				(unsigned long long)paddr,
+				(unsigned long long)(paddr + size),
+				cattr_name(flags));
+			return -EINVAL;
+		}
+		/*
+		 * We allow returning different type than the one requested in
+		 * non strict case.
+		 */
+		*vma_prot = __pgprot((pgprot_val(*vma_prot) &
+				      (~_PAGE_CACHE_MASK)) |
+				     flags);
+	}
+
+	if (kernel_map_sync_memtype(paddr, size, flags) < 0) {
+		free_memtype(paddr, paddr + size);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Internal interface to free a range of physical memory.
+ * Frees non RAM regions only.
+ */
+static void free_pfn_range(u64 paddr, unsigned long size)
+{
+	int is_ram;
+
+	is_ram = pat_pagerange_is_ram(paddr, paddr + size);
+	if (is_ram == 0)
+		free_memtype(paddr, paddr + size);
+}
+
+/*
+ * track_pfn_vma_copy is called when vma that is covering the pfnmap gets
+ * copied through copy_page_range().
+ *
+ * If the vma has a linear pfn mapping for the entire range, we get the prot
+ * from pte and reserve the entire vma range with single reserve_pfn_range call.
+ */
+int track_pfn_vma_copy(struct vm_area_struct *vma)
+{
+	resource_size_t paddr;
+	unsigned long prot;
+	unsigned long vma_size = vma->vm_end - vma->vm_start;
+	pgprot_t pgprot;
+
+	if (is_linear_pfn_mapping(vma)) {
+		/*
+		 * reserve the whole chunk covered by vma. We need the
+		 * starting address and protection from pte.
+		 */
+		if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
+			WARN_ON_ONCE(1);
+			return -EINVAL;
+		}
+		pgprot = __pgprot(prot);
+		return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
+	}
+
+	return 0;
+}
+
+/*
+ * track_pfn_vma_new is called when a _new_ pfn mapping is being established
+ * for physical range indicated by pfn and size.
+ *
+ * prot is passed in as a parameter for the new mapping. If the vma has a
+ * linear pfn mapping for the entire range reserve the entire vma range with
+ * single reserve_pfn_range call.
+ */
+int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
+			unsigned long pfn, unsigned long size)
+{
+	unsigned long flags;
+	resource_size_t paddr;
+	unsigned long vma_size = vma->vm_end - vma->vm_start;
+
+	if (is_linear_pfn_mapping(vma)) {
+		/* reserve the whole chunk starting from vm_pgoff */
+		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+		return reserve_pfn_range(paddr, vma_size, prot, 0);
+	}
+
+	if (!pat_enabled)
+		return 0;
+
+	/* for vm_insert_pfn and friends, we set prot based on lookup */
+	flags = lookup_memtype(pfn << PAGE_SHIFT);
+	*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
+			 flags);
+
+	return 0;
+}
+
+/*
+ * untrack_pfn_vma is called while unmapping a pfnmap for a region.
+ * untrack can be called for a specific region indicated by pfn and size or
+ * can be for the entire vma (in which case size can be zero).
+ */
+void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
+			unsigned long size)
+{
+	resource_size_t paddr;
+	unsigned long vma_size = vma->vm_end - vma->vm_start;
+
+	if (is_linear_pfn_mapping(vma)) {
+		/* free the whole chunk starting from vm_pgoff */
+		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+		free_pfn_range(paddr, vma_size);
+		return;
+	}
+}
+#endif /* CONFIG_XEN */
+
+pgprot_t pgprot_writecombine(pgprot_t prot)
+{
+	if (pat_enabled)
+		return __pgprot(pgprot_val(prot) | _PAGE_CACHE_WC);
+	else
+		return pgprot_noncached(prot);
+}
+EXPORT_SYMBOL_GPL(pgprot_writecombine);
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
+
+/* get Nth element of the linked list */
+static struct memtype *memtype_get_idx(loff_t pos)
+{
+	struct memtype *list_node, *print_entry;
+	int i = 1;
+
+	print_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+	if (!print_entry)
+		return NULL;
+
+	spin_lock(&memtype_lock);
+	list_for_each_entry(list_node, &memtype_list, nd) {
+		if (pos == i) {
+			*print_entry = *list_node;
+			spin_unlock(&memtype_lock);
+			return print_entry;
+		}
+		++i;
+	}
+	spin_unlock(&memtype_lock);
+	kfree(print_entry);
+
+	return NULL;
+}
+
+static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos == 0) {
+		++*pos;
+		seq_printf(seq, "PAT memtype list:\n");
+	}
+
+	return memtype_get_idx(*pos);
+}
+
+static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return memtype_get_idx(*pos);
+}
+
+static void memtype_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int memtype_seq_show(struct seq_file *seq, void *v)
+{
+	struct memtype *print_entry = (struct memtype *)v;
+
+	seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type),
+			print_entry->start, print_entry->end);
+	kfree(print_entry);
+
+	return 0;
+}
+
+static const struct seq_operations memtype_seq_ops = {
+	.start = memtype_seq_start,
+	.next  = memtype_seq_next,
+	.stop  = memtype_seq_stop,
+	.show  = memtype_seq_show,
+};
+
+static int memtype_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &memtype_seq_ops);
+}
+
+static const struct file_operations memtype_fops = {
+	.open    = memtype_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+static int __init pat_memtype_list_init(void)
+{
+	debugfs_create_file("pat_memtype_list", S_IRUSR, arch_debugfs_dir,
+				NULL, &memtype_fops);
+	return 0;
+}
+
+late_initcall(pat_memtype_list_init);
+
+#endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */
--- linux-ec2-2.6.32.orig/arch/x86/mm/setup_nx.c
+++ linux-ec2-2.6.32/arch/x86/mm/setup_nx.c
@@ -53,6 +53,7 @@
 #else
 void set_nx(void)
 {
+	nx_enabled = _PAGE_NX && ((__supported_pte_mask & _PAGE_NX) == _PAGE_NX);
 }
 #endif
 
--- linux-ec2-2.6.32.orig/arch/x86/mm/srat_64.c
+++ linux-ec2-2.6.32/arch/x86/mm/srat_64.c
@@ -229,9 +229,11 @@
 			printk(KERN_ERR "SRAT: Hotplug zone not continuous. Partly ignored\n");
 	}
 
-	if (changed)
+	if (changed) {
+		node_set(node, cpu_nodes_parsed);
 		printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
 				 nd->start, nd->end);
+	}
 }
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
--- linux-ec2-2.6.32.orig/arch/x86/mm/Makefile
+++ linux-ec2-2.6.32/arch/x86/mm/Makefile
@@ -25,4 +25,7 @@
 obj-$(CONFIG_K8_NUMA)		+= k8topology_64.o
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
 
+obj-$(CONFIG_XEN)		+= hypervisor.o
+disabled-obj-$(CONFIG_XEN)	:= tlb.o
+
 obj-$(CONFIG_MEMTEST)		+= memtest.o
--- linux-ec2-2.6.32.orig/arch/x86/mm/init-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/init-xen.c
@@ -0,0 +1,456 @@
+#include <linux/initrd.h>
+#include <linux/ioport.h>
+#include <linux/swap.h>
+#include <linux/bootmem.h>
+
+#include <asm/cacheflush.h>
+#include <asm/e820.h>
+#include <asm/init.h>
+#include <asm/page.h>
+#include <asm/page_types.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+#include <asm/proto.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+unsigned long __meminitdata e820_table_start;
+unsigned long __meminitdata e820_table_end;
+unsigned long __meminitdata e820_table_top;
+
+int after_bootmem;
+
+#if !defined(CONFIG_XEN)
+int direct_gbpages
+#ifdef CONFIG_DIRECT_GBPAGES
+				= 1
+#endif
+;
+#elif defined(CONFIG_X86_32)
+#define direct_gbpages 0
+extern unsigned long extend_init_mapping(unsigned long tables_space);
+#else
+extern void xen_finish_init_mapping(void);
+#endif
+
+static void __init find_early_table_space(unsigned long end, int use_pse,
+					  int use_gbpages)
+{
+	unsigned long puds, pmds, ptes, tables;
+
+	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
+	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+
+	if (use_gbpages) {
+		unsigned long extra;
+
+		extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
+		pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+	} else
+		pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+
+	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+
+	if (use_pse) {
+		unsigned long extra;
+
+		extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+#ifdef CONFIG_X86_32
+		extra += PMD_SIZE;
+#endif
+		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	} else
+		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
+
+#ifdef CONFIG_X86_32
+	/* for fixmap */
+	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
+#endif
+
+	/*
+	 * RED-PEN putting page tables only on node 0 could
+	 * cause a hotspot and fill up ZONE_DMA. The page tables
+	 * need roughly 0.5KB per GB.
+	 */
+#ifdef CONFIG_X86_32
+	e820_table_start = extend_init_mapping(tables);
+	e820_table_end = e820_table_start;
+#else /* CONFIG_X86_64 */
+	if (!e820_table_top) {
+		e820_table_start = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
+			xen_start_info->nr_pt_frames;
+		e820_table_end = e820_table_start;
+	} else {
+		/*
+		 * [table_start, table_top) gets passed to reserve_early(),
+		 * so we must not use table_end here, despite continuing
+		 * to allocate from there. table_end possibly being below
+		 * table_start is otoh not a problem.
+		 */
+		e820_table_start = e820_table_top;
+	}
+#endif
+	if (e820_table_start == -1UL)
+		panic("Cannot find space for the kernel page tables");
+
+	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
+
+	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
+		end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
+}
+
+struct map_range {
+	unsigned long start;
+	unsigned long end;
+	unsigned page_size_mask;
+};
+
+#ifdef CONFIG_X86_32
+#define NR_RANGE_MR 3
+#else /* CONFIG_X86_64 */
+#define NR_RANGE_MR 5
+#endif
+
+static int __meminit save_mr(struct map_range *mr, int nr_range,
+			     unsigned long start_pfn, unsigned long end_pfn,
+			     unsigned long page_size_mask)
+{
+	if (start_pfn < end_pfn) {
+		if (nr_range >= NR_RANGE_MR)
+			panic("run out of range for init_memory_mapping\n");
+		mr[nr_range].start = start_pfn<<PAGE_SHIFT;
+		mr[nr_range].end   = end_pfn<<PAGE_SHIFT;
+		mr[nr_range].page_size_mask = page_size_mask;
+		nr_range++;
+	}
+
+	return nr_range;
+}
+
+/*
+ * Setup the direct mapping of the physical memory at PAGE_OFFSET.
+ * This runs before bootmem is initialized and gets pages directly from
+ * the physical memory. To access them they are temporarily mapped.
+ */
+unsigned long __init_refok init_memory_mapping(unsigned long start,
+					       unsigned long end)
+{
+	unsigned long page_size_mask = 0;
+	unsigned long start_pfn, end_pfn;
+	unsigned long ret = 0;
+	unsigned long pos;
+
+	struct map_range mr[NR_RANGE_MR];
+	int nr_range, i;
+	int use_pse, use_gbpages;
+
+	printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
+
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
+	/*
+	 * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+	 * This will simplify cpa(), which otherwise needs to support splitting
+	 * large pages into small in interrupt context, etc.
+	 */
+	use_pse = use_gbpages = 0;
+#else
+	use_pse = cpu_has_pse;
+	use_gbpages = direct_gbpages;
+#endif
+
+	set_nx();
+	if (nx_enabled)
+		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+
+	/* Enable PSE if available */
+	if (cpu_has_pse)
+		set_in_cr4(X86_CR4_PSE);
+
+	/* Enable PGE if available */
+	if (cpu_has_pge) {
+		set_in_cr4(X86_CR4_PGE);
+		__supported_pte_mask |= _PAGE_GLOBAL;
+	}
+
+	if (use_gbpages)
+		page_size_mask |= 1 << PG_LEVEL_1G;
+	if (use_pse)
+		page_size_mask |= 1 << PG_LEVEL_2M;
+
+	memset(mr, 0, sizeof(mr));
+	nr_range = 0;
+
+	/* head if not big page alignment ? */
+	start_pfn = start >> PAGE_SHIFT;
+	pos = start_pfn << PAGE_SHIFT;
+#ifdef CONFIG_X86_32
+	/*
+	 * Don't use a large page for the first 2/4MB of memory
+	 * because there are often fixed size MTRRs in there
+	 * and overlapping MTRRs into large pages can cause
+	 * slowdowns.
+	 */
+	if (pos == 0)
+		end_pfn = 1<<(PMD_SHIFT - PAGE_SHIFT);
+	else
+		end_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+				 << (PMD_SHIFT - PAGE_SHIFT);
+#else /* CONFIG_X86_64 */
+	end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
+			<< (PMD_SHIFT - PAGE_SHIFT);
+#endif
+	if (end_pfn > (end >> PAGE_SHIFT))
+		end_pfn = end >> PAGE_SHIFT;
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+	/* big page (2M) range */
+	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+			 << (PMD_SHIFT - PAGE_SHIFT);
+#ifdef CONFIG_X86_32
+	end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+#else /* CONFIG_X86_64 */
+	end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+			 << (PUD_SHIFT - PAGE_SHIFT);
+	if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
+		end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
+#endif
+
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask & (1<<PG_LEVEL_2M));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+#ifdef CONFIG_X86_64
+	/* big page (1G) range */
+	start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
+			 << (PUD_SHIFT - PAGE_SHIFT);
+	end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask &
+				 ((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+
+	/* tail is not big page (1G) alignment */
+	start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
+			 << (PMD_SHIFT - PAGE_SHIFT);
+	end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
+	if (start_pfn < end_pfn) {
+		nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
+				page_size_mask & (1<<PG_LEVEL_2M));
+		pos = end_pfn << PAGE_SHIFT;
+	}
+#endif
+
+	/* tail is not big page (2M) alignment */
+	start_pfn = pos>>PAGE_SHIFT;
+	end_pfn = end>>PAGE_SHIFT;
+	nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
+
+	/* try to merge same page size and continuous */
+	for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
+		unsigned long old_start;
+		if (mr[i].end != mr[i+1].start ||
+		    mr[i].page_size_mask != mr[i+1].page_size_mask)
+			continue;
+		/* move it */
+		old_start = mr[i].start;
+		memmove(&mr[i], &mr[i+1],
+			(nr_range - 1 - i) * sizeof(struct map_range));
+		mr[i--].start = old_start;
+		nr_range--;
+	}
+
+	for (i = 0; i < nr_range; i++)
+		printk(KERN_DEBUG " %010lx - %010lx page %s\n",
+				mr[i].start, mr[i].end,
+			(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
+			 (mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
+
+	/*
+	 * Find space for the kernel direct mapping tables.
+	 *
+	 * Later we should allocate these tables in the local node of the
+	 * memory mapped. Unfortunately this is done currently before the
+	 * nodes are discovered.
+	 */
+	if (!after_bootmem)
+		find_early_table_space(end, use_pse, use_gbpages);
+
+#ifdef CONFIG_X86_32
+	for (i = 0; i < nr_range; i++)
+		kernel_physical_mapping_init(mr[i].start, mr[i].end,
+					     mr[i].page_size_mask);
+	ret = end;
+#else /* CONFIG_X86_64 */
+#define addr_to_page(addr)						\
+	((unsigned long *)						\
+	 ((mfn_to_pfn(((addr) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)	\
+	   << PAGE_SHIFT) + __START_KERNEL_map))
+
+	if (!start) {
+		unsigned long addr, va = __START_KERNEL_map;
+		unsigned long *page = (unsigned long *)init_level4_pgt;
+
+		/* Kill mapping of memory below _text. */
+		while (va < (unsigned long)&_text) {
+			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+				BUG();
+			va += PAGE_SIZE;
+		}
+
+		/* Blow away any spurious initial mappings. */
+		va = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT);
+
+		addr = page[pgd_index(va)];
+		page = addr_to_page(addr);
+		addr = page[pud_index(va)];
+		page = addr_to_page(addr);
+		while (pmd_index(va) | pte_index(va)) {
+			if (pmd_none(*(pmd_t *)&page[pmd_index(va)]))
+				break;
+			if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+				BUG();
+			va += PAGE_SIZE;
+		}
+	}
+
+	for (i = 0; i < nr_range; i++)
+		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
+						   mr[i].page_size_mask);
+#undef addr_to_page
+#endif
+
+#ifdef CONFIG_X86_32
+	early_ioremap_page_table_range_init();
+#endif
+
+#ifdef CONFIG_X86_64
+	BUG_ON(e820_table_end > e820_table_top);
+	if (!start)
+		xen_finish_init_mapping();
+	else
+#endif
+	if (e820_table_end < e820_table_top)
+		/* Disable the 'table_end' allocator. */
+		e820_table_top = e820_table_end;
+
+	__flush_tlb_all();
+
+	if (!after_bootmem && e820_table_top > e820_table_start) {
+#ifdef CONFIG_X86_64
+		if (xen_start_info->mfn_list < __START_KERNEL_map
+		    && e820_table_start <= xen_start_info->first_p2m_pfn
+		    && e820_table_top > xen_start_info->first_p2m_pfn) {
+			reserve_early(e820_table_start << PAGE_SHIFT,
+				      xen_start_info->first_p2m_pfn
+				      << PAGE_SHIFT,
+				      "PGTABLE");
+			e820_table_start = xen_start_info->first_p2m_pfn
+					 + xen_start_info->nr_p2m_frames;
+		}
+#endif
+		reserve_early(e820_table_start << PAGE_SHIFT,
+			      e820_table_top << PAGE_SHIFT, "PGTABLE");
+	}
+
+	if (!after_bootmem)
+		early_memtest(start, end);
+
+	return ret >> PAGE_SHIFT;
+}
+
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+ * is valid. The argument is a physical page number.
+ *
+ *
+ * On x86, access has to be given to the first megabyte of ram because that area
+ * contains bios code and data regions used by X and dosemu and similar apps.
+ * Access has to be given to non-kernel-ram areas as well, these contain the PCI
+ * mmio resources as well as potential bios/acpi data regions.
+ */
+int devmem_is_allowed(unsigned long pagenr)
+{
+	if (pagenr <= 256)
+		return 1;
+	if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+		return 0;
+	if (mfn_to_local_pfn(pagenr) >= max_pfn)
+		return 1;
+	return 0;
+}
+
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+	unsigned long addr = begin;
+
+	if (addr >= end)
+		return;
+
+	/*
+	 * If debugging page accesses then do not free this memory but
+	 * mark them not present - any buggy init-section access will
+	 * create a kernel page fault:
+	 */
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
+		begin, PAGE_ALIGN(end));
+	set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
+#else
+	/*
+	 * We just marked the kernel text read only above, now that
+	 * we are going to free part of that, we need to make that
+	 * writeable first.
+	 */
+	set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
+
+	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
+
+	for (; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		memset((void *)(addr & ~(PAGE_SIZE-1)),
+			POISON_FREE_INITMEM, PAGE_SIZE);
+#ifdef CONFIG_X86_64
+		if (addr >= __START_KERNEL_map) {
+			/* make_readonly() reports all kernel addresses. */
+			if (HYPERVISOR_update_va_mapping((unsigned long)__va(__pa(addr)),
+							 pfn_pte(__pa(addr) >> PAGE_SHIFT,
+								 PAGE_KERNEL),
+							 0))
+				BUG();
+			if (HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
+				BUG();
+		}
+#endif
+		free_page(addr);
+		totalram_pages++;
+	}
+#endif
+}
+
+void free_initmem(void)
+{
+	free_init_pages("unused kernel memory",
+			(unsigned long)(&__init_begin),
+			(unsigned long)(&__init_end));
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	free_init_pages("initrd memory", start, end);
+}
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/mm/init_64.c
+++ linux-ec2-2.6.32/arch/x86/mm/init_64.c
@@ -49,6 +49,7 @@
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
 #include <asm/init.h>
+#include <linux/bootmem.h>
 
 static unsigned long dma_reserve __initdata;
 
@@ -615,6 +616,21 @@
  */
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
+ * After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
+ * updating.
+ */
+static void  update_end_of_memory_vars(u64 start, u64 size)
+{
+	unsigned long end_pfn = PFN_UP(start + size);
+
+	if (end_pfn > max_pfn) {
+		max_pfn = end_pfn;
+		max_low_pfn = end_pfn;
+		high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
+	}
+}
+
+/*
  * Memory is added always to NORMAL zone. This means you will never get
  * additional DMA/DMA32 memory.
  */
@@ -633,6 +649,9 @@
 	ret = __add_pages(nid, zone, start_pfn, nr_pages);
 	WARN_ON_ONCE(ret);
 
+	/* update max_pfn, max_low_pfn and high_memory */
+	update_end_of_memory_vars(start, size);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(arch_add_memory);
--- linux-ec2-2.6.32.orig/arch/x86/mm/fault-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/fault-xen.c
@@ -0,0 +1,1177 @@
+/*
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
+ *  Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
+ */
+#include <linux/magic.h>		/* STACK_END_MAGIC		*/
+#include <linux/sched.h>		/* test_thread_flag(), ...	*/
+#include <linux/kdebug.h>		/* oops_begin/end, ...		*/
+#include <linux/module.h>		/* search_exception_table	*/
+#include <linux/bootmem.h>		/* max_low_pfn			*/
+#include <linux/kprobes.h>		/* __kprobes, ...		*/
+#include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/
+#include <linux/perf_event.h>		/* perf_sw_event		*/
+
+#include <asm/traps.h>			/* dotraplinkage, ...		*/
+#include <asm/pgalloc.h>		/* pgd_*(), ...			*/
+#include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/
+
+/*
+ * Page fault error code bits:
+ *
+ *   bit 0 ==	 0: no page found	1: protection fault
+ *   bit 1 ==	 0: read access		1: write access
+ *   bit 2 ==	 0: kernel-mode access	1: user-mode access
+ *   bit 3 ==				1: use of reserved bit detected
+ *   bit 4 ==				1: fault was an instruction fetch
+ */
+enum x86_pf_error_code {
+
+	PF_PROT		=		1 << 0,
+	PF_WRITE	=		1 << 1,
+	PF_USER		=		1 << 2,
+	PF_RSVD		=		1 << 3,
+	PF_INSTR	=		1 << 4,
+};
+
+/*
+ * Returns 0 if mmiotrace is disabled, or if the fault is not
+ * handled by mmiotrace:
+ */
+static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
+{
+	if (unlikely(is_kmmio_active()))
+		if (kmmio_handler(regs, addr) == 1)
+			return -1;
+	return 0;
+}
+
+static inline int notify_page_fault(struct pt_regs *regs)
+{
+	int ret = 0;
+
+	/* kprobe_running() needs smp_processor_id() */
+	if (kprobes_built_in() && !user_mode_vm(regs)) {
+		preempt_disable();
+		if (kprobe_running() && kprobe_fault_handler(regs, 14))
+			ret = 1;
+		preempt_enable();
+	}
+
+	return ret;
+}
+
+/*
+ * Prefetch quirks:
+ *
+ * 32-bit mode:
+ *
+ *   Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
+ *   Check that here and ignore it.
+ *
+ * 64-bit mode:
+ *
+ *   Sometimes the CPU reports invalid exceptions on prefetch.
+ *   Check that here and ignore it.
+ *
+ * Opcode checker based on code by Richard Brunner.
+ */
+static inline int
+check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
+		      unsigned char opcode, int *prefetch)
+{
+	unsigned char instr_hi = opcode & 0xf0;
+	unsigned char instr_lo = opcode & 0x0f;
+
+	switch (instr_hi) {
+	case 0x20:
+	case 0x30:
+		/*
+		 * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
+		 * In X86_64 long mode, the CPU will signal invalid
+		 * opcode if some of these prefixes are present so
+		 * X86_64 will never get here anyway
+		 */
+		return ((instr_lo & 7) == 0x6);
+#ifdef CONFIG_X86_64
+	case 0x40:
+		/*
+		 * In AMD64 long mode 0x40..0x4F are valid REX prefixes
+		 * Need to figure out under what instruction mode the
+		 * instruction was issued. Could check the LDT for lm,
+		 * but for now it's good enough to assume that long
+		 * mode only uses well known segments or kernel.
+		 */
+		return (!user_mode(regs)) || (regs->cs == __USER_CS);
+#endif
+	case 0x60:
+		/* 0x64 thru 0x67 are valid prefixes in all modes. */
+		return (instr_lo & 0xC) == 0x4;
+	case 0xF0:
+		/* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
+		return !instr_lo || (instr_lo>>1) == 1;
+	case 0x00:
+		/* Prefetch instruction is 0x0F0D or 0x0F18 */
+		if (probe_kernel_address(instr, opcode))
+			return 0;
+
+		*prefetch = (instr_lo == 0xF) &&
+			(opcode == 0x0D || opcode == 0x18);
+		return 0;
+	default:
+		return 0;
+	}
+}
+
+static int
+is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
+{
+	unsigned char *max_instr;
+	unsigned char *instr;
+	int prefetch = 0;
+
+	/*
+	 * If it was a exec (instruction fetch) fault on NX page, then
+	 * do not ignore the fault:
+	 */
+	if (error_code & PF_INSTR)
+		return 0;
+
+	instr = (void *)convert_ip_to_linear(current, regs);
+	max_instr = instr + 15;
+
+	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+		return 0;
+
+	while (instr < max_instr) {
+		unsigned char opcode;
+
+		if (probe_kernel_address(instr, opcode))
+			break;
+
+		instr++;
+
+		if (!check_prefetch_opcode(regs, instr, opcode, &prefetch))
+			break;
+	}
+	return prefetch;
+}
+
+static void
+force_sig_info_fault(int si_signo, int si_code, unsigned long address,
+		     struct task_struct *tsk)
+{
+	siginfo_t info;
+
+	info.si_signo	= si_signo;
+	info.si_errno	= 0;
+	info.si_code	= si_code;
+	info.si_addr	= (void __user *)address;
+	info.si_addr_lsb = si_code == BUS_MCEERR_AR ? PAGE_SHIFT : 0;
+
+	force_sig_info(si_signo, &info, tsk);
+}
+
+DEFINE_SPINLOCK(pgd_lock);
+LIST_HEAD(pgd_list);
+
+#ifdef CONFIG_X86_32
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
+{
+	unsigned index = pgd_index(address);
+	pgd_t *pgd_k;
+	pud_t *pud, *pud_k;
+	pmd_t *pmd, *pmd_k;
+
+	pgd += index;
+	pgd_k = init_mm.pgd + index;
+
+	if (!pgd_present(*pgd_k))
+		return NULL;
+
+	/*
+	 * set_pgd(pgd, *pgd_k); here would be useless on PAE
+	 * and redundant with the set_pmd() on non-PAE. As would
+	 * set_pud.
+	 */
+	pud = pud_offset(pgd, address);
+	pud_k = pud_offset(pgd_k, address);
+	if (!pud_present(*pud_k))
+		return NULL;
+
+	pmd = pmd_offset(pud, address);
+	pmd_k = pmd_offset(pud_k, address);
+	if (!pmd_present(*pmd_k))
+		return NULL;
+
+	if (!pmd_present(*pmd))
+#if CONFIG_XEN_COMPAT > 0x030002
+		set_pmd(pmd, *pmd_k);
+#else
+		/*
+		 * When running on older Xen we must launder *pmd_k through
+		 * pmd_val() to ensure that _PAGE_PRESENT is correctly set.
+		 */
+		set_pmd(pmd, __pmd(pmd_val(*pmd_k)));
+#endif
+	else
+		BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+
+	return pmd_k;
+}
+
+void vmalloc_sync_all(void)
+{
+	unsigned long address;
+
+	if (SHARED_KERNEL_PMD)
+		return;
+
+	for (address = VMALLOC_START & PMD_MASK;
+	     address >= TASK_SIZE && address < FIXADDR_TOP;
+	     address += PMD_SIZE) {
+
+		unsigned long flags;
+		struct page *page;
+
+		spin_lock_irqsave(&pgd_lock, flags);
+		list_for_each_entry(page, &pgd_list, lru) {
+			if (!vmalloc_sync_one(page_address(page), address))
+				break;
+		}
+		spin_unlock_irqrestore(&pgd_lock, flags);
+	}
+}
+
+/*
+ * 32-bit:
+ *
+ *   Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+	unsigned long pgd_paddr;
+	pmd_t *pmd_k;
+	pte_t *pte_k;
+
+	/* Make sure we are in vmalloc area: */
+	if (!(address >= VMALLOC_START && address < VMALLOC_END))
+		return -1;
+
+	/*
+	 * Synchronize this task's top level page-table
+	 * with the 'reference' page table.
+	 *
+	 * Do _not_ use "current" here. We might be inside
+	 * an interrupt in the middle of a task switch..
+	 */
+	pgd_paddr = read_cr3();
+	pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
+	if (!pmd_k)
+		return -1;
+
+	pte_k = pte_offset_kernel(pmd_k, address);
+	if (!pte_present(*pte_k))
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Did it hit the DOS screen memory VA from vm86 mode?
+ */
+static inline void
+check_v8086_mode(struct pt_regs *regs, unsigned long address,
+		 struct task_struct *tsk)
+{
+	unsigned long bit;
+
+	if (!v8086_mode(regs))
+		return;
+
+	bit = (address - 0xA0000) >> PAGE_SHIFT;
+	if (bit < 32)
+		tsk->thread.screen_bitmap |= 1 << bit;
+}
+
+static bool low_pfn(unsigned long pfn)
+{
+	return pfn < max_low_pfn;
+}
+
+static void dump_pagetable(unsigned long address)
+{
+	pgd_t *base = __va(read_cr3());
+	pgd_t *pgd = &base[pgd_index(address)];
+	pmd_t *pmd;
+	pte_t *pte;
+
+#ifdef CONFIG_X86_PAE
+	printk("*pdpt = %016Lx ", __pgd_val(*pgd));
+	if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd))
+		goto out;
+#endif
+	pmd = pmd_offset(pud_offset(pgd, address), address);
+	printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)__pmd_val(*pmd));
+
+	/*
+	 * We must not directly access the pte in the highpte
+	 * case if the page table is located in highmem.
+	 * And let's rather not kmap-atomic the pte, just in case
+	 * it's allocated already:
+	 */
+	if (!low_pfn(pmd_pfn(*pmd)) || !pmd_present(*pmd) || pmd_large(*pmd))
+		goto out;
+
+	pte = pte_offset_kernel(pmd, address);
+	printk(KERN_CONT "*pte = %0*Lx ", sizeof(*pte) * 2, (u64)__pte_val(*pte));
+out:
+	printk(KERN_CONT "\n");
+}
+#define dump_pagetable(addr, krnl) dump_pagetable(addr)
+
+#else /* CONFIG_X86_64: */
+
+void vmalloc_sync_all(void)
+{
+	unsigned long address;
+
+	for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
+	     address += PGDIR_SIZE) {
+
+		const pgd_t *pgd_ref = pgd_offset_k(address);
+		unsigned long flags;
+		struct page *page;
+
+		if (pgd_none(*pgd_ref))
+			continue;
+
+		spin_lock_irqsave(&pgd_lock, flags);
+		list_for_each_entry(page, &pgd_list, lru) {
+			pgd_t *pgd;
+			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+			if (pgd_none(*pgd))
+				set_pgd(pgd, *pgd_ref);
+			else
+				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+		}
+		spin_unlock_irqrestore(&pgd_lock, flags);
+	}
+}
+
+/*
+ * 64-bit:
+ *
+ *   Handle a fault on the vmalloc area
+ *
+ * This assumes no large pages in there.
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+	pgd_t *pgd, *pgd_ref;
+	pud_t *pud, *pud_ref;
+	pmd_t *pmd, *pmd_ref;
+	pte_t *pte, *pte_ref;
+
+	/* Make sure we are in vmalloc area: */
+	if (!(address >= VMALLOC_START && address < VMALLOC_END))
+		return -1;
+
+	/*
+	 * Copy kernel mappings over when needed. This can also
+	 * happen within a race in page table update. In the later
+	 * case just flush:
+	 */
+	pgd = pgd_offset(current->active_mm, address);
+	pgd_ref = pgd_offset_k(address);
+	if (pgd_none(*pgd_ref))
+		return -1;
+
+	if (pgd_none(*pgd))
+		set_pgd(pgd, *pgd_ref);
+	else
+		BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+
+	/*
+	 * Below here mismatches are bugs because these lower tables
+	 * are shared:
+	 */
+
+	pud = pud_offset(pgd, address);
+	pud_ref = pud_offset(pgd_ref, address);
+	if (pud_none(*pud_ref))
+		return -1;
+
+	if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+		BUG();
+
+	pmd = pmd_offset(pud, address);
+	pmd_ref = pmd_offset(pud_ref, address);
+	if (pmd_none(*pmd_ref))
+		return -1;
+
+	if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
+		BUG();
+
+	pte_ref = pte_offset_kernel(pmd_ref, address);
+	if (!pte_present(*pte_ref))
+		return -1;
+
+	pte = pte_offset_kernel(pmd, address);
+
+	/*
+	 * Don't use pte_page here, because the mappings can point
+	 * outside mem_map, and the NUMA hash lookup cannot handle
+	 * that:
+	 */
+	if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
+		BUG();
+
+	return 0;
+}
+
+static const char errata93_warning[] =
+KERN_ERR
+"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+"******* Working around it, but it may cause SEGVs or burn power.\n"
+"******* Please consider a BIOS update.\n"
+"******* Disabling USB legacy in the BIOS may also help.\n";
+
+/*
+ * No vm86 mode in 64-bit mode:
+ */
+static inline void
+check_v8086_mode(struct pt_regs *regs, unsigned long address,
+		 struct task_struct *tsk)
+{
+}
+
+static int bad_address(void *p)
+{
+	unsigned long dummy;
+
+	return probe_kernel_address((unsigned long *)p, dummy);
+}
+
+static void dump_pagetable(unsigned long address, bool kernel)
+{
+	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+	pgd_t *pgd = base + pgd_index(address);
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (!kernel)
+		pgd = __user_pgd(base) + pgd_index(address);
+
+	if (bad_address(pgd))
+		goto bad;
+
+	printk("PGD %lx ", pgd_val(*pgd));
+
+	if (!pgd_present(*pgd))
+		goto out;
+
+	pud = pud_offset(pgd, address);
+	if (bad_address(pud))
+		goto bad;
+
+	printk(KERN_CONT "PUD %lx ", pud_val(*pud));
+	if (!pud_present(*pud) || pud_large(*pud))
+		goto out;
+
+	pmd = pmd_offset(pud, address);
+	if (bad_address(pmd))
+		goto bad;
+
+	printk(KERN_CONT "PMD %lx ", pmd_val(*pmd));
+	if (!pmd_present(*pmd) || pmd_large(*pmd))
+		goto out;
+
+	pte = pte_offset_kernel(pmd, address);
+	if (bad_address(pte))
+		goto bad;
+
+	printk(KERN_CONT "PTE %lx", pte_val(*pte));
+out:
+	printk(KERN_CONT "\n");
+	return;
+bad:
+	printk("BAD\n");
+}
+
+#endif /* CONFIG_X86_64 */
+
+/*
+ * Workaround for K8 erratum #93 & buggy BIOS.
+ *
+ * BIOS SMM functions are required to use a specific workaround
+ * to avoid corruption of the 64bit RIP register on C stepping K8.
+ *
+ * A lot of BIOS that didn't get tested properly miss this.
+ *
+ * The OS sees this as a page fault with the upper 32bits of RIP cleared.
+ * Try to work around it here.
+ *
+ * Note we only handle faults in kernel here.
+ * Does nothing on 32-bit.
+ */
+static int is_errata93(struct pt_regs *regs, unsigned long address)
+{
+#ifdef CONFIG_X86_64
+	if (address != regs->ip)
+		return 0;
+
+	if ((address >> 32) != 0)
+		return 0;
+
+	address |= 0xffffffffUL << 32;
+	if ((address >= (u64)_stext && address <= (u64)_etext) ||
+	    (address >= MODULES_VADDR && address <= MODULES_END)) {
+		printk_once(errata93_warning);
+		regs->ip = address;
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Work around K8 erratum #100 K8 in compat mode occasionally jumps
+ * to illegal addresses >4GB.
+ *
+ * We catch this in the page fault handler because these addresses
+ * are not reachable. Just detect this case and return.  Any code
+ * segment in LDT is compatibility mode.
+ */
+static int is_errata100(struct pt_regs *regs, unsigned long address)
+{
+#ifdef CONFIG_X86_64
+	if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32))
+		return 1;
+#endif
+	return 0;
+}
+
+static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
+{
+#ifdef CONFIG_X86_F00F_BUG
+	unsigned long nr;
+
+	/*
+	 * Pentium F0 0F C7 C8 bug workaround:
+	 */
+	if (boot_cpu_data.f00f_bug) {
+		nr = (address - idt_descr.address) >> 3;
+
+		if (nr == 6) {
+			do_invalid_op(regs, 0);
+			return 1;
+		}
+	}
+#endif
+	return 0;
+}
+
+static const char nx_warning[] = KERN_CRIT
+"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
+
+static void
+show_fault_oops(struct pt_regs *regs, unsigned long error_code,
+		unsigned long address)
+{
+	if (!oops_may_print())
+		return;
+
+	if (error_code & PF_INSTR) {
+		unsigned int level;
+
+		pte_t *pte = lookup_address(address, &level);
+
+		if (pte && pte_present(*pte) && !pte_exec(*pte))
+			printk(nx_warning, current_uid());
+	}
+
+	printk(KERN_ALERT "BUG: unable to handle kernel ");
+	if (address < PAGE_SIZE)
+		printk(KERN_CONT "NULL pointer dereference");
+	else
+		printk(KERN_CONT "paging request");
+
+	printk(KERN_CONT " at %p\n", (void *) address);
+	printk(KERN_ALERT "IP:");
+	printk_address(regs->ip, 1);
+
+	dump_pagetable(address, !(error_code & PF_USER));
+}
+
+static noinline void
+pgtable_bad(struct pt_regs *regs, unsigned long error_code,
+	    unsigned long address)
+{
+	struct task_struct *tsk;
+	unsigned long flags;
+	int sig;
+
+	flags = oops_begin();
+	tsk = current;
+	sig = SIGKILL;
+
+	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+	       tsk->comm, address);
+	dump_pagetable(address, !(error_code & PF_USER));
+
+	tsk->thread.cr2		= address;
+	tsk->thread.trap_no	= 14;
+	tsk->thread.error_code	= error_code;
+
+	if (__die("Bad pagetable", regs, error_code))
+		sig = 0;
+
+	oops_end(flags, regs, sig);
+}
+
+static noinline void
+no_context(struct pt_regs *regs, unsigned long error_code,
+	   unsigned long address)
+{
+	struct task_struct *tsk = current;
+	unsigned long *stackend;
+	unsigned long flags;
+	int sig;
+
+	/* Are we prepared to handle this kernel fault? */
+	if (fixup_exception(regs))
+		return;
+
+	/*
+	 * 32-bit:
+	 *
+	 *   Valid to do another page fault here, because if this fault
+	 *   had been triggered by is_prefetch fixup_exception would have
+	 *   handled it.
+	 *
+	 * 64-bit:
+	 *
+	 *   Hall of shame of CPU/BIOS bugs.
+	 */
+	if (is_prefetch(regs, error_code, address))
+		return;
+
+	if (is_errata93(regs, address))
+		return;
+
+	/*
+	 * Oops. The kernel tried to access some bad page. We'll have to
+	 * terminate things with extreme prejudice:
+	 */
+	flags = oops_begin();
+
+	show_fault_oops(regs, error_code, address);
+
+	stackend = end_of_stack(tsk);
+	if (*stackend != STACK_END_MAGIC)
+		printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+
+	tsk->thread.cr2		= address;
+	tsk->thread.trap_no	= 14;
+	tsk->thread.error_code	= error_code;
+
+	sig = SIGKILL;
+	if (__die("Oops", regs, error_code))
+		sig = 0;
+
+	/* Executive summary in case the body of the oops scrolled away */
+	printk(KERN_EMERG "CR2: %016lx\n", address);
+
+	oops_end(flags, regs, sig);
+}
+
+/*
+ * Print out info about fatal segfaults, if the show_unhandled_signals
+ * sysctl is set:
+ */
+static inline void
+show_signal_msg(struct pt_regs *regs, unsigned long error_code,
+		unsigned long address, struct task_struct *tsk)
+{
+	if (!unhandled_signal(tsk, SIGSEGV))
+		return;
+
+	if (!printk_ratelimit())
+		return;
+
+	printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+		task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+		tsk->comm, task_pid_nr(tsk), address,
+		(void *)regs->ip, (void *)regs->sp, error_code);
+
+	print_vma_addr(KERN_CONT " in ", regs->ip);
+
+	printk(KERN_CONT "\n");
+}
+
+static void
+__bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+		       unsigned long address, int si_code)
+{
+	struct task_struct *tsk = current;
+
+	/* User mode accesses just cause a SIGSEGV */
+	if (error_code & PF_USER) {
+		/*
+		 * It's possible to have interrupts off here:
+		 */
+		local_irq_enable();
+
+		/*
+		 * Valid to do another page fault here because this one came
+		 * from user space:
+		 */
+		if (is_prefetch(regs, error_code, address))
+			return;
+
+		if (is_errata100(regs, address))
+			return;
+
+		if (unlikely(show_unhandled_signals))
+			show_signal_msg(regs, error_code, address, tsk);
+
+		/* Kernel addresses are always protection faults: */
+		tsk->thread.cr2		= address;
+		tsk->thread.error_code	= error_code | (address >= TASK_SIZE);
+		tsk->thread.trap_no	= 14;
+
+		force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+
+		return;
+	}
+
+	if (is_f00f_bug(regs, address))
+		return;
+
+	no_context(regs, error_code, address);
+}
+
+static noinline void
+bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+		     unsigned long address)
+{
+	__bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR);
+}
+
+static void
+__bad_area(struct pt_regs *regs, unsigned long error_code,
+	   unsigned long address, int si_code)
+{
+	struct mm_struct *mm = current->mm;
+
+	/*
+	 * Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
+	up_read(&mm->mmap_sem);
+
+	__bad_area_nosemaphore(regs, error_code, address, si_code);
+}
+
+static noinline void
+bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address)
+{
+	__bad_area(regs, error_code, address, SEGV_MAPERR);
+}
+
+static noinline void
+bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
+		      unsigned long address)
+{
+	__bad_area(regs, error_code, address, SEGV_ACCERR);
+}
+
+/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
+static void
+out_of_memory(struct pt_regs *regs, unsigned long error_code,
+	      unsigned long address)
+{
+	/*
+	 * We ran out of memory, call the OOM killer, and return the userspace
+	 * (which will retry the fault, or kill us if we got oom-killed):
+	 */
+	up_read(&current->mm->mmap_sem);
+
+	pagefault_out_of_memory();
+}
+
+static void
+do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
+	  unsigned int fault)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->mm;
+	int code = BUS_ADRERR;
+
+	up_read(&mm->mmap_sem);
+
+	/* Kernel mode? Handle exceptions or die: */
+	if (!(error_code & PF_USER)) {
+		no_context(regs, error_code, address);
+		return;
+	}
+
+	/* User-space => ok to do another page fault: */
+	if (is_prefetch(regs, error_code, address))
+		return;
+
+	tsk->thread.cr2		= address;
+	tsk->thread.error_code	= error_code;
+	tsk->thread.trap_no	= 14;
+
+#ifdef CONFIG_MEMORY_FAILURE
+	if (fault & VM_FAULT_HWPOISON) {
+		printk(KERN_ERR
+	"MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
+			tsk->comm, tsk->pid, address);
+		code = BUS_MCEERR_AR;
+	}
+#endif
+	force_sig_info_fault(SIGBUS, code, address, tsk);
+}
+
+static noinline void
+mm_fault_error(struct pt_regs *regs, unsigned long error_code,
+	       unsigned long address, unsigned int fault)
+{
+	if (fault & VM_FAULT_OOM) {
+		/* Kernel mode? Handle exceptions or die: */
+		if (!(error_code & PF_USER)) {
+			up_read(&current->mm->mmap_sem);
+			no_context(regs, error_code, address);
+			return;
+		}
+
+		out_of_memory(regs, error_code, address);
+	} else {
+		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON))
+			do_sigbus(regs, error_code, address, fault);
+		else
+			BUG();
+	}
+}
+
+static int spurious_fault_check(unsigned long error_code, pte_t *pte)
+{
+	if ((error_code & PF_WRITE) && !pte_write(*pte))
+		return 0;
+
+	if ((error_code & PF_INSTR) && !pte_exec(*pte))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Handle a spurious fault caused by a stale TLB entry.
+ *
+ * This allows us to lazily refresh the TLB when increasing the
+ * permissions of a kernel page (RO -> RW or NX -> X).  Doing it
+ * eagerly is very expensive since that implies doing a full
+ * cross-processor TLB flush, even if no stale TLB entries exist
+ * on other processors.
+ *
+ * There are no security implications to leaving a stale TLB when
+ * increasing the permissions on a page.
+ */
+static noinline int
+spurious_fault(unsigned long error_code, unsigned long address)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	int ret;
+
+	/* Reserved-bit violation or user access to kernel space? */
+	if (error_code & (PF_USER | PF_RSVD))
+		return 0;
+
+	pgd = init_mm.pgd + pgd_index(address);
+	if (!pgd_present(*pgd))
+		return 0;
+
+	pud = pud_offset(pgd, address);
+	if (!pud_present(*pud))
+		return 0;
+
+	if (pud_large(*pud))
+		return spurious_fault_check(error_code, (pte_t *) pud);
+
+	pmd = pmd_offset(pud, address);
+	if (!pmd_present(*pmd))
+		return 0;
+
+	if (pmd_large(*pmd))
+		return spurious_fault_check(error_code, (pte_t *) pmd);
+
+	pte = pte_offset_kernel(pmd, address);
+	if (!pte_present(*pte))
+		return 0;
+
+	ret = spurious_fault_check(error_code, pte);
+	if (!ret)
+		return 0;
+
+	/*
+	 * Make sure we have permissions in PMD.
+	 * If not, then there's a bug in the page tables:
+	 */
+	ret = spurious_fault_check(error_code, (pte_t *) pmd);
+	WARN_ONCE(!ret, "PMD has incorrect permission bits\n");
+
+	return ret;
+}
+
+int show_unhandled_signals = 1;
+
+static inline int
+access_error(unsigned long error_code, int write, struct vm_area_struct *vma)
+{
+	if (write) {
+		/* write, present and write, not present: */
+		if (unlikely(!(vma->vm_flags & VM_WRITE)))
+			return 1;
+		return 0;
+	}
+
+	/* read, present: */
+	if (unlikely(error_code & PF_PROT))
+		return 1;
+
+	/* read, not present: */
+	if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
+		return 1;
+
+	return 0;
+}
+
+static int fault_in_kernel_space(unsigned long address)
+{
+	return address >= TASK_SIZE_MAX;
+}
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+dotraplinkage void __kprobes
+do_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+	struct vm_area_struct *vma;
+	struct task_struct *tsk;
+	unsigned long address;
+	struct mm_struct *mm;
+	int write;
+	int fault;
+
+	/* Set the "privileged fault" bit to something sane. */
+	if (user_mode_vm(regs))
+		error_code |= PF_USER;
+	else
+		error_code &= ~PF_USER;
+
+	tsk = current;
+	mm = tsk->mm;
+
+	/* Get the faulting address: */
+	address = read_cr2();
+
+	/*
+	 * Detect and handle instructions that would cause a page fault for
+	 * both a tracked kernel page and a userspace page.
+	 */
+	if (kmemcheck_active(regs))
+		kmemcheck_hide(regs);
+	prefetchw(&mm->mmap_sem);
+
+	if (unlikely(kmmio_fault(regs, address)))
+		return;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * (error_code & 4) == 0, and that the fault was not a
+	 * protection error (error_code & 9) == 0.
+	 */
+	if (unlikely(fault_in_kernel_space(address))) {
+		/* Faults in hypervisor area can never be patched up. */
+#if defined(CONFIG_X86_XEN)
+		if (address >= hypervisor_virt_start) {
+#elif defined(CONFIG_X86_64_XEN)
+		if (address >= HYPERVISOR_VIRT_START
+		    && address < HYPERVISOR_VIRT_END) {
+#endif
+			bad_area_nosemaphore(regs, error_code, address);
+			return;
+		}
+
+		if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
+			if (vmalloc_fault(address) >= 0)
+				return;
+
+			if (kmemcheck_fault(regs, address, error_code))
+				return;
+		}
+
+		/* Can handle a stale RO->RW TLB: */
+		if (spurious_fault(error_code, address))
+			return;
+
+		/* kprobes don't want to hook the spurious faults: */
+		if (notify_page_fault(regs))
+			return;
+		/*
+		 * Don't take the mm semaphore here. If we fixup a prefetch
+		 * fault we could otherwise deadlock:
+		 */
+		bad_area_nosemaphore(regs, error_code, address);
+
+		return;
+	}
+
+	/* kprobes don't want to hook the spurious faults: */
+	if (unlikely(notify_page_fault(regs)))
+		return;
+	/*
+	 * It's safe to allow irq's after cr2 has been saved and the
+	 * vmalloc fault has been handled.
+	 *
+	 * User-mode registers count as a user access even for any
+	 * potential system fault or CPU buglet:
+	 */
+	if (user_mode_vm(regs)) {
+		local_irq_enable();
+		error_code |= PF_USER;
+	} else {
+		if (regs->flags & X86_EFLAGS_IF)
+			local_irq_enable();
+	}
+
+	if (unlikely(error_code & PF_RSVD))
+		pgtable_bad(regs, error_code, address);
+
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
+	/*
+	 * If we're in an interrupt, have no user context or are running
+	 * in an atomic region then we must not take the fault:
+	 */
+	if (unlikely(in_atomic() || !mm)) {
+		bad_area_nosemaphore(regs, error_code, address);
+		return;
+	}
+
+	/*
+	 * When running in the kernel we expect faults to occur only to
+	 * addresses in user space.  All other faults represent errors in
+	 * the kernel and should generate an OOPS.  Unfortunately, in the
+	 * case of an erroneous fault occurring in a code path which already
+	 * holds mmap_sem we will deadlock attempting to validate the fault
+	 * against the address space.  Luckily the kernel only validly
+	 * references user space from well defined areas of code, which are
+	 * listed in the exceptions table.
+	 *
+	 * As the vast majority of faults will be valid we will only perform
+	 * the source reference check when there is a possibility of a
+	 * deadlock. Attempt to lock the address space, if we cannot we then
+	 * validate the source. If this is invalid we can skip the address
+	 * space check, thus avoiding the deadlock:
+	 */
+	if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
+		if ((error_code & PF_USER) == 0 &&
+		    !search_exception_tables(regs->ip)) {
+			bad_area_nosemaphore(regs, error_code, address);
+			return;
+		}
+		down_read(&mm->mmap_sem);
+	} else {
+		/*
+		 * The above down_read_trylock() might have succeeded in
+		 * which case we'll have missed the might_sleep() from
+		 * down_read():
+		 */
+		might_sleep();
+	}
+
+	vma = find_vma(mm, address);
+	if (unlikely(!vma)) {
+		bad_area(regs, error_code, address);
+		return;
+	}
+	if (likely(vma->vm_start <= address))
+		goto good_area;
+	if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
+		bad_area(regs, error_code, address);
+		return;
+	}
+	if (error_code & PF_USER) {
+		/*
+		 * Accessing the stack below %sp is always a bug.
+		 * The large cushion allows instructions like enter
+		 * and pusha to work. ("enter $65535, $31" pushes
+		 * 32 pointers and then decrements %sp by 65535.)
+		 */
+		if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
+			bad_area(regs, error_code, address);
+			return;
+		}
+	}
+	if (unlikely(expand_stack(vma, address))) {
+		bad_area(regs, error_code, address);
+		return;
+	}
+
+	/*
+	 * Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
+good_area:
+	write = error_code & PF_WRITE;
+
+	if (unlikely(access_error(error_code, write, vma))) {
+		bad_area_access_error(regs, error_code, address);
+		return;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault:
+	 */
+	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+
+	if (unlikely(fault & VM_FAULT_ERROR)) {
+		mm_fault_error(regs, error_code, address, fault);
+		return;
+	}
+
+	if (fault & VM_FAULT_MAJOR) {
+		tsk->maj_flt++;
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+				     regs, address);
+	} else {
+		tsk->min_flt++;
+		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+				     regs, address);
+	}
+
+	check_v8086_mode(regs, address, tsk);
+
+	up_read(&mm->mmap_sem);
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/iomap_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/iomap_32-xen.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2008 Ingo Molnar
+ *
+ * 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 <asm/iomap.h>
+#include <asm/pat.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+
+static int is_io_mapping_possible(resource_size_t base, unsigned long size)
+{
+#if !defined(CONFIG_X86_PAE) && defined(CONFIG_PHYS_ADDR_T_64BIT)
+	/* There is no way to map greater than 1 << 32 address without PAE */
+	if (base + size > 0x100000000ULL)
+		return 0;
+#endif
+	return 1;
+}
+
+int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot)
+{
+	unsigned long flag = _PAGE_CACHE_WC;
+	int ret;
+
+	if (!is_io_mapping_possible(base, size))
+		return -EINVAL;
+
+	ret = io_reserve_memtype(base, base + size, &flag);
+	if (ret)
+		return ret;
+
+	*prot = __pgprot(__PAGE_KERNEL | flag);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iomap_create_wc);
+
+void
+iomap_free(resource_size_t base, unsigned long size)
+{
+	io_free_memtype(base, base + size);
+}
+EXPORT_SYMBOL_GPL(iomap_free);
+
+void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	pagefault_disable();
+
+	debug_kmap_atomic(type);
+	idx = type + KM_TYPE_NR * smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte_at(&init_mm, vaddr, kmap_pte - idx, pfn_pte(pfn, prot));
+	/*arch_flush_lazy_mmu_mode();*/
+
+	return (void *)vaddr;
+}
+
+/*
+ * Map 'mfn' using fixed map 'type' and protections 'prot'
+ */
+void *
+iomap_atomic_prot_pfn(unsigned long mfn, enum km_type type, pgprot_t prot)
+{
+	/*
+	 * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
+	 * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
+	 * MTRR is UC or WC.  UC_MINUS gets the real intention, of the
+	 * user, which is "WC if the MTRR is WC, UC if you can't do that."
+	 */
+	if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
+		prot = PAGE_KERNEL_UC_MINUS;
+
+	pgprot_val(prot) |= _PAGE_IOMAP;
+	return kmap_atomic_prot_pfn(mfn, type, prot);
+}
+EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
+
+void
+iounmap_atomic(void *kvaddr, enum km_type type)
+{
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	/*
+	 * Force other mappings to Oops if they'll try to access this pte
+	 * without first remap it.  Keeping stale mappings around is a bad idea
+	 * also, in case the page changes cacheability attributes or becomes
+	 * a protected page in a hypervisor.
+	 */
+	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+		kpte_clear_flush(kmap_pte-idx, vaddr);
+
+	pagefault_enable();
+}
+EXPORT_SYMBOL_GPL(iounmap_atomic);
--- linux-ec2-2.6.32.orig/arch/x86/mm/fault.c
+++ linux-ec2-2.6.32/arch/x86/mm/fault.c
@@ -801,8 +801,10 @@
 	up_read(&mm->mmap_sem);
 
 	/* Kernel mode? Handle exceptions or die: */
-	if (!(error_code & PF_USER))
+	if (!(error_code & PF_USER)) {
 		no_context(regs, error_code, address);
+		return;
+	}
 
 	/* User-space => ok to do another page fault: */
 	if (is_prefetch(regs, error_code, address))
@@ -828,6 +830,13 @@
 	       unsigned long address, unsigned int fault)
 {
 	if (fault & VM_FAULT_OOM) {
+		/* Kernel mode? Handle exceptions or die: */
+		if (!(error_code & PF_USER)) {
+			up_read(&current->mm->mmap_sem);
+			no_context(regs, error_code, address);
+			return;
+		}
+
 		out_of_memory(regs, error_code, address);
 	} else {
 		if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON))
--- linux-ec2-2.6.32.orig/arch/x86/mm/init_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/init_32-xen.c
@@ -0,0 +1,1136 @@
+/*
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/pci.h>
+#include <linux/pfn.h>
+#include <linux/poison.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/memory_hotplug.h>
+#include <linux/initrd.h>
+#include <linux/cpumask.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+
+#include <asm/asm.h>
+#include <asm/bios_ebda.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/fixmap.h>
+#include <asm/e820.h>
+#include <asm/apic.h>
+#include <asm/bugs.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <asm/hypervisor.h>
+#include <asm/swiotlb.h>
+#include <asm/setup.h>
+#include <asm/cacheflush.h>
+#include <asm/page_types.h>
+#include <asm/init.h>
+
+unsigned long highstart_pfn, highend_pfn;
+
+static noinline int do_test_wp_bit(void);
+
+bool __read_mostly __vmalloc_start_set = false;
+
+static __init void *alloc_low_page(void)
+{
+	unsigned long pfn = e820_table_end++;
+	void *adr;
+
+	if (pfn >= e820_table_top)
+		panic("alloc_low_page: ran out of memory");
+
+	adr = __va(pfn * PAGE_SIZE);
+	memset(adr, 0, PAGE_SIZE);
+	return adr;
+}
+
+/*
+ * Creates a middle page table and puts a pointer to it in the
+ * given global directory entry. This only returns the gd entry
+ * in non-PAE compilation mode, since the middle layer is folded.
+ */
+static pmd_t * __init one_md_table_init(pgd_t *pgd)
+{
+	pud_t *pud;
+	pmd_t *pmd_table;
+
+#ifdef CONFIG_X86_PAE
+	if (!(__pgd_val(*pgd) & _PAGE_PRESENT)) {
+		if (after_bootmem)
+			pmd_table = (pmd_t *)alloc_bootmem_pages(PAGE_SIZE);
+		else
+			pmd_table = (pmd_t *)alloc_low_page();
+		paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT);
+		make_lowmem_page_readonly(pmd_table, XENFEAT_writable_page_tables);
+		set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+		pud = pud_offset(pgd, 0);
+		BUG_ON(pmd_table != pmd_offset(pud, 0));
+
+		return pmd_table;
+	}
+#endif
+	pud = pud_offset(pgd, 0);
+	pmd_table = pmd_offset(pud, 0);
+
+	return pmd_table;
+}
+
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry:
+ */
+static pte_t * __init one_page_table_init(pmd_t *pmd)
+{
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (pmd_none(*pmd)) {
+#else
+	if (!(__pmd_val(*pmd) & _PAGE_PRESENT)) {
+#endif
+		pte_t *page_table = NULL;
+
+		if (after_bootmem) {
+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
+			page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+#endif
+			if (!page_table)
+				page_table =
+				(pte_t *)alloc_bootmem_pages(PAGE_SIZE);
+		} else
+			page_table = (pte_t *)alloc_low_page();
+
+		paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT);
+		make_lowmem_page_readonly(page_table,
+					  XENFEAT_writable_page_tables);
+		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+	}
+
+	return pte_offset_kernel(pmd, 0);
+}
+
+pmd_t * __init populate_extra_pmd(unsigned long vaddr)
+{
+	int pgd_idx = pgd_index(vaddr);
+	int pmd_idx = pmd_index(vaddr);
+
+	return one_md_table_init(swapper_pg_dir + pgd_idx) + pmd_idx;
+}
+
+pte_t * __init populate_extra_pte(unsigned long vaddr)
+{
+	int pte_idx = pte_index(vaddr);
+	pmd_t *pmd;
+
+	pmd = populate_extra_pmd(vaddr);
+	return one_page_table_init(pmd) + pte_idx;
+}
+
+static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
+					   unsigned long vaddr, pte_t *lastpte)
+{
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * Something (early fixmap) may already have put a pte
+	 * page here, which causes the page table allocation
+	 * to become nonlinear. Attempt to fix it, and if it
+	 * is still nonlinear then we have to bug.
+	 */
+	int pmd_idx_kmap_begin = fix_to_virt(FIX_KMAP_END) >> PMD_SHIFT;
+	int pmd_idx_kmap_end = fix_to_virt(FIX_KMAP_BEGIN) >> PMD_SHIFT;
+
+	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
+	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
+	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
+	    && ((__pa(pte) >> PAGE_SHIFT) < e820_table_start
+		|| (__pa(pte) >> PAGE_SHIFT) >= e820_table_end)) {
+		pte_t *newpte;
+		int i;
+
+		BUG_ON(after_bootmem);
+		newpte = alloc_low_page();
+		for (i = 0; i < PTRS_PER_PTE; i++)
+			set_pte(newpte + i, pte[i]);
+
+		paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT);
+		make_lowmem_page_readonly(newpte,
+					  XENFEAT_writable_page_tables);
+		set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE));
+		BUG_ON(newpte != pte_offset_kernel(pmd, 0));
+		__flush_tlb_all();
+
+		paravirt_release_pte(__pa(pte) >> PAGE_SHIFT);
+		make_lowmem_page_writable(pte,
+					  XENFEAT_writable_page_tables);
+		pte = newpte;
+	}
+	BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1)
+	       && vaddr > fix_to_virt(FIX_KMAP_END)
+	       && lastpte && lastpte + PTRS_PER_PTE != pte);
+#endif
+	return pte;
+}
+
+/*
+ * This function initializes a certain range of kernel virtual memory
+ * with new bootmem page tables, everywhere page tables are missing in
+ * the given range.
+ *
+ * NOTE: The pagetables are allocated contiguous on the physical space
+ * so we can cache the place of the first one and move around without
+ * checking the pgd every time.
+ */
+static void __init
+page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
+{
+	int pgd_idx, pmd_idx;
+	unsigned long vaddr;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte = NULL;
+
+	vaddr = start;
+	pgd_idx = pgd_index(vaddr);
+	pmd_idx = pmd_index(vaddr);
+	pgd = pgd_base + pgd_idx;
+
+	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+		pmd = one_md_table_init(pgd);
+		pmd = pmd + pmd_index(vaddr);
+		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
+							pmd++, pmd_idx++) {
+			if (vaddr >= hypervisor_virt_start)
+				break;
+			pte = page_table_kmap_check(one_page_table_init(pmd),
+			                            pmd, vaddr, pte);
+
+			vaddr += PMD_SIZE;
+		}
+		pmd_idx = 0;
+	}
+}
+
+static inline int is_kernel_text(unsigned long addr)
+{
+	if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
+		return 1;
+	return 0;
+}
+
+/*
+ * This maps the physical memory to kernel virtual address space, a total
+ * of max_low_pfn pages, by creating page tables starting from address
+ * PAGE_OFFSET:
+ */
+unsigned long __init
+kernel_physical_mapping_init(unsigned long start,
+			     unsigned long end,
+			     unsigned long page_size_mask)
+{
+	int use_pse = page_size_mask == (1<<PG_LEVEL_2M);
+	unsigned long start_pfn, end_pfn;
+	pgd_t *pgd_base = swapper_pg_dir;
+	int pgd_idx, pmd_idx, pte_ofs;
+	unsigned long pfn;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned pages_2m, pages_4k;
+	int mapping_iter;
+
+	start_pfn = start >> PAGE_SHIFT;
+	end_pfn = end >> PAGE_SHIFT;
+
+	/*
+	 * First iteration will setup identity mapping using large/small pages
+	 * based on use_pse, with other attributes same as set by
+	 * the early code in head_32.S
+	 *
+	 * Second iteration will setup the appropriate attributes (NX, GLOBAL..)
+	 * as desired for the kernel identity mapping.
+	 *
+	 * This two pass mechanism conforms to the TLB app note which says:
+	 *
+	 *     "Software should not write to a paging-structure entry in a way
+	 *      that would change, for any linear address, both the page size
+	 *      and either the page frame or attributes."
+	 */
+	mapping_iter = 1;
+
+	if (!cpu_has_pse) {
+		use_pse = 0;
+		mapping_iter = 0;
+	}
+
+repeat:
+	pages_2m = pages_4k = 0;
+	pfn = start_pfn;
+	pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+	pgd = pgd_base + pgd_idx;
+	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+#ifdef CONFIG_XEN
+		/*
+		 * Native linux hasn't PAE-paging enabled yet at this
+		 * point.  When running as xen domain we are in PAE
+		 * mode already, thus we can't simply hook a empty
+		 * pmd.  That would kill the mappings we are currently
+		 * using ...
+		 */
+		pmd = pmd_offset(pud_offset(pgd, PAGE_OFFSET), PAGE_OFFSET);
+#else
+		pmd = one_md_table_init(pgd);
+#endif
+
+		if (pfn >= end_pfn)
+			continue;
+#ifdef CONFIG_X86_PAE
+		pmd_idx = pmd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+		pmd += pmd_idx;
+#else
+		pmd_idx = 0;
+#endif
+		for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn;
+		     pmd++, pmd_idx++) {
+			unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET;
+
+			if (addr >= hypervisor_virt_start)
+				continue;
+
+			/*
+			 * Map with big pages if possible, otherwise
+			 * create normal page tables:
+			 */
+			if (use_pse) {
+				unsigned int addr2;
+				pgprot_t prot = PAGE_KERNEL_LARGE;
+				/*
+				 * first pass will use the same initial
+				 * identity mapping attribute + _PAGE_PSE.
+				 */
+				pgprot_t init_prot =
+					__pgprot(PTE_IDENT_ATTR |
+						 _PAGE_PSE);
+
+				addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE +
+					PAGE_OFFSET + PAGE_SIZE-1;
+
+				if (is_kernel_text(addr) ||
+				    is_kernel_text(addr2))
+					prot = PAGE_KERNEL_LARGE_EXEC;
+
+				pages_2m++;
+				if (mapping_iter == 1)
+					set_pmd(pmd, pfn_pmd(pfn, init_prot));
+				else
+					set_pmd(pmd, pfn_pmd(pfn, prot));
+
+				pfn += PTRS_PER_PTE;
+				continue;
+			}
+			pte = one_page_table_init(pmd);
+
+			pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET);
+			pte += pte_ofs;
+			for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn;
+			     pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) {
+				pgprot_t prot = PAGE_KERNEL;
+				/*
+				 * first pass will use the same initial
+				 * identity mapping attribute.
+				 */
+				pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR);
+
+				/* XEN: Only map initial RAM allocation. */
+				if (pfn >= xen_start_info->nr_pages || pte_present(*pte))
+					continue;
+				if (is_kernel_text(addr))
+					prot = PAGE_KERNEL_EXEC;
+
+				pages_4k++;
+				if (mapping_iter == 1)
+					set_pte(pte, pfn_pte(pfn, init_prot));
+				else
+					set_pte(pte, pfn_pte(pfn, prot));
+			}
+		}
+	}
+	if (mapping_iter <= 1) {
+		/*
+		 * update direct mapping page count only in the first
+		 * iteration.
+		 */
+		update_page_count(PG_LEVEL_2M, pages_2m);
+		update_page_count(PG_LEVEL_4K, pages_4k);
+	}
+	if (mapping_iter == 1) {
+		/*
+		 * local global flush tlb, which will flush the previous
+		 * mappings present in both small and large page TLB's.
+		 */
+		__flush_tlb_all();
+
+		/*
+		 * Second iteration will set the actual desired PTE attributes.
+		 */
+		mapping_iter = 2;
+		goto repeat;
+	}
+	return 0;
+}
+
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr)
+{
+	return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
+			vaddr), vaddr), vaddr);
+}
+
+static void __init kmap_init(void)
+{
+	unsigned long kmap_vstart;
+
+	/*
+	 * Cache the first kmap pte:
+	 */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+	kmap_prot = PAGE_KERNEL;
+}
+
+#ifdef CONFIG_HIGHMEM
+static void __init permanent_kmaps_init(pgd_t *pgd_base)
+{
+	unsigned long vaddr;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	vaddr = PKMAP_BASE;
+	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
+	pte = pte_offset_kernel(pmd, vaddr);
+	pkmap_page_table = pte;
+}
+
+static void __init add_one_highpage_init(struct page *page, int pfn)
+{
+	ClearPageReserved(page);
+	init_page_count(page);
+	__free_page(page);
+	totalhigh_pages++;
+}
+
+struct add_highpages_data {
+	unsigned long start_pfn;
+	unsigned long end_pfn;
+};
+
+static int __init add_highpages_work_fn(unsigned long start_pfn,
+					 unsigned long end_pfn, void *datax)
+{
+	int node_pfn;
+	struct page *page;
+	unsigned long final_start_pfn, final_end_pfn;
+	struct add_highpages_data *data;
+
+	data = (struct add_highpages_data *)datax;
+
+	final_start_pfn = max(start_pfn, data->start_pfn);
+	final_end_pfn = min(end_pfn, data->end_pfn);
+	if (final_start_pfn >= final_end_pfn)
+		return 0;
+
+	for (node_pfn = final_start_pfn; node_pfn < final_end_pfn;
+	     node_pfn++) {
+		if (!pfn_valid(node_pfn))
+			continue;
+		page = pfn_to_page(node_pfn);
+		add_one_highpage_init(page, node_pfn);
+	}
+
+	return 0;
+
+}
+
+void __init add_highpages_with_active_regions(int nid, unsigned long start_pfn,
+					      unsigned long end_pfn)
+{
+	struct add_highpages_data data;
+
+	data.start_pfn = start_pfn;
+	data.end_pfn = end_pfn;
+
+	work_with_active_regions(nid, add_highpages_work_fn, &data);
+}
+
+#else
+static inline void permanent_kmaps_init(pgd_t *pgd_base)
+{
+}
+#endif /* CONFIG_HIGHMEM */
+
+pgd_t *swapper_pg_dir;
+
+/*
+ * Build a proper pagetable for the kernel mappings.  Up until this
+ * point, we've been running on some set of pagetables constructed by
+ * the boot process.
+ *
+ * If we're booting on native hardware, this will be a pagetable
+ * constructed in arch/x86/kernel/head_32.S.  The root of the
+ * pagetable will be swapper_pg_dir.
+ *
+ * If we're booting paravirtualized under a hypervisor, then there are
+ * more options: we may already be running PAE, and the pagetable may
+ * or may not be based in swapper_pg_dir.  In any case,
+ * paravirt_pagetable_setup_start() will set up swapper_pg_dir
+ * appropriately for the rest of the initialization to work.
+ *
+ * In general, pagetable_init() assumes that the pagetable may already
+ * be partially populated, and so it avoids stomping on any existing
+ * mappings.
+ */
+void __init early_ioremap_page_table_range_init(void)
+{
+	pgd_t *pgd_base = swapper_pg_dir;
+	unsigned long vaddr, end;
+
+	/*
+	 * Fixed mappings, only the page table structure has to be
+	 * created - mappings will be set by set_fixmap():
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+	end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
+	page_table_range_init(vaddr, end, pgd_base);
+	early_ioremap_reset();
+}
+
+static void __init pagetable_init(void)
+{
+	pgd_t *pgd_base = (pgd_t *)xen_start_info->pt_base;
+
+	permanent_kmaps_init(pgd_base);
+}
+
+#if defined(CONFIG_ACPI_SLEEP) && !defined(CONFIG_XEN)
+/*
+ * ACPI suspend needs this for resume, because things like the intel-agp
+ * driver might have split up a kernel 4MB mapping.
+ */
+char swsusp_pg_dir[PAGE_SIZE]
+	__attribute__ ((aligned(PAGE_SIZE)));
+
+static inline void save_pg_dir(void)
+{
+	memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE);
+}
+#else /* !CONFIG_ACPI_SLEEP */
+static inline void save_pg_dir(void)
+{
+}
+#endif /* !CONFIG_ACPI_SLEEP */
+
+void zap_low_mappings(bool early)
+{
+	int i;
+
+	/*
+	 * Zap initial low-memory mappings.
+	 *
+	 * Note that "pgd_clear()" doesn't do it for
+	 * us, because pgd_clear() is a no-op on i386.
+	 */
+	for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
+#if defined(CONFIG_X86_PAE) && !defined(CONFIG_XEN)
+		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
+#else
+		set_pgd(swapper_pg_dir+i, __pgd(0));
+#endif
+	}
+
+	if (early)
+		__flush_tlb();
+	else
+		flush_tlb_all();
+}
+
+pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
+EXPORT_SYMBOL_GPL(__supported_pte_mask);
+
+/* user-defined highmem size */
+static unsigned int highmem_pages = -1;
+
+/*
+ * highmem=size forces highmem to be exactly 'size' bytes.
+ * This works even on boxes that have no highmem otherwise.
+ * This also works to reduce highmem size on bigger boxes.
+ */
+static int __init parse_highmem(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
+	return 0;
+}
+early_param("highmem", parse_highmem);
+
+#define MSG_HIGHMEM_TOO_BIG \
+	"highmem size (%luMB) is bigger than pages available (%luMB)!\n"
+
+#define MSG_LOWMEM_TOO_SMALL \
+	"highmem size (%luMB) results in <64MB lowmem, ignoring it!\n"
+/*
+ * All of RAM fits into lowmem - but if user wants highmem
+ * artificially via the highmem=x boot parameter then create
+ * it:
+ */
+void __init lowmem_pfn_init(void)
+{
+	/* max_low_pfn is 0, we already have early_res support */
+	max_low_pfn = max_pfn;
+
+	if (highmem_pages == -1)
+		highmem_pages = 0;
+#ifdef CONFIG_HIGHMEM
+	if (highmem_pages >= max_pfn) {
+		printk(KERN_ERR MSG_HIGHMEM_TOO_BIG,
+			pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
+		highmem_pages = 0;
+	}
+	if (highmem_pages) {
+		if (max_low_pfn - highmem_pages < 64*1024*1024/PAGE_SIZE) {
+			printk(KERN_ERR MSG_LOWMEM_TOO_SMALL,
+				pages_to_mb(highmem_pages));
+			highmem_pages = 0;
+		}
+		max_low_pfn -= highmem_pages;
+	}
+#else
+	if (highmem_pages)
+		printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
+#endif
+}
+
+#define MSG_HIGHMEM_TOO_SMALL \
+	"only %luMB highmem pages available, ignoring highmem size of %luMB!\n"
+
+#define MSG_HIGHMEM_TRIMMED \
+	"Warning: only 4GB will be used. Use a HIGHMEM64G enabled kernel!\n"
+/*
+ * We have more RAM than fits into lowmem - we try to put it into
+ * highmem, also taking the highmem=x boot parameter into account:
+ */
+void __init highmem_pfn_init(void)
+{
+	max_low_pfn = MAXMEM_PFN;
+
+	if (highmem_pages == -1)
+		highmem_pages = max_pfn - MAXMEM_PFN;
+
+	if (highmem_pages + MAXMEM_PFN < max_pfn)
+		max_pfn = MAXMEM_PFN + highmem_pages;
+
+	if (highmem_pages + MAXMEM_PFN > max_pfn) {
+		printk(KERN_WARNING MSG_HIGHMEM_TOO_SMALL,
+			pages_to_mb(max_pfn - MAXMEM_PFN),
+			pages_to_mb(highmem_pages));
+		highmem_pages = 0;
+	}
+#ifndef CONFIG_HIGHMEM
+	/* Maximum memory usable is what is directly addressable */
+	printk(KERN_WARNING "Warning only %ldMB will be used.\n", MAXMEM>>20);
+	if (max_pfn > MAX_NONPAE_PFN)
+		printk(KERN_WARNING "Use a HIGHMEM64G enabled kernel.\n");
+	else
+		printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+	max_pfn = MAXMEM_PFN;
+#else /* !CONFIG_HIGHMEM */
+#ifndef CONFIG_HIGHMEM64G
+	if (max_pfn > MAX_NONPAE_PFN) {
+		max_pfn = MAX_NONPAE_PFN;
+		printk(KERN_WARNING MSG_HIGHMEM_TRIMMED);
+	}
+#endif /* !CONFIG_HIGHMEM64G */
+#endif /* !CONFIG_HIGHMEM */
+}
+
+/*
+ * Determine low and high memory ranges:
+ */
+void __init find_low_pfn_range(void)
+{
+	/* it could update max_pfn */
+
+	if (max_pfn <= MAXMEM_PFN)
+		lowmem_pfn_init();
+	else
+		highmem_pfn_init();
+}
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+void __init initmem_init(unsigned long start_pfn,
+				  unsigned long end_pfn)
+{
+#ifdef CONFIG_HIGHMEM
+	highstart_pfn = highend_pfn = max_pfn;
+	if (max_pfn > max_low_pfn)
+		highstart_pfn = max_low_pfn;
+	e820_register_active_regions(0, 0, highend_pfn);
+	sparse_memory_present_with_active_regions(0);
+	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+		pages_to_mb(highend_pfn - highstart_pfn));
+	num_physpages = highend_pfn;
+	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+	e820_register_active_regions(0, 0, max_low_pfn);
+	sparse_memory_present_with_active_regions(0);
+	num_physpages = max_low_pfn;
+	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+#endif
+#ifdef CONFIG_FLATMEM
+	max_mapnr = num_physpages;
+#endif
+	__vmalloc_start_set = true;
+
+	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+			pages_to_mb(max_low_pfn));
+
+	setup_bootmem_allocator();
+}
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+
+static void __init zone_sizes_init(void)
+{
+	unsigned long max_zone_pfns[MAX_NR_ZONES];
+	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+	max_zone_pfns[ZONE_DMA] =
+		virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
+#ifdef CONFIG_HIGHMEM
+	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
+#endif
+
+	free_area_init_nodes(max_zone_pfns);
+
+	xen_init_pgd_pin();
+}
+
+static unsigned long __init setup_node_bootmem(int nodeid,
+				 unsigned long start_pfn,
+				 unsigned long end_pfn,
+				 unsigned long bootmap)
+{
+	unsigned long bootmap_size;
+
+	/* don't touch min_low_pfn */
+	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
+					 bootmap >> PAGE_SHIFT,
+					 start_pfn, end_pfn);
+	printk(KERN_INFO "  node %d low ram: %08lx - %08lx\n",
+		nodeid, start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+	printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
+		 nodeid, bootmap, bootmap + bootmap_size);
+	free_bootmem_with_active_regions(nodeid, end_pfn);
+	early_res_to_bootmem(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
+
+	return bootmap + bootmap_size;
+}
+
+void __init setup_bootmem_allocator(void)
+{
+	int nodeid;
+	unsigned long bootmap_size, bootmap;
+	unsigned long end_xen_pfn = min(max_low_pfn, xen_start_info->nr_pages);
+
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = bootmem_bootmap_pages(end_xen_pfn)<<PAGE_SHIFT;
+	bootmap = find_e820_area(0, min(max_pfn_mapped,
+				        xen_start_info->nr_pages)<<PAGE_SHIFT,
+				 bootmap_size, PAGE_SIZE);
+	if (bootmap == -1L)
+		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
+
+	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
+		 max_pfn_mapped<<PAGE_SHIFT);
+	printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
+
+	for_each_online_node(nodeid) {
+		 unsigned long start_pfn, end_pfn;
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+		start_pfn = node_start_pfn[nodeid];
+		end_pfn = node_end_pfn[nodeid];
+		if (start_pfn > end_xen_pfn)
+			continue;
+		if (end_pfn > end_xen_pfn)
+			end_pfn = end_xen_pfn;
+#else
+		start_pfn = 0;
+		end_pfn = end_xen_pfn;
+#endif
+		bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
+						 bootmap);
+	}
+
+	after_bootmem = 1;
+}
+
+unsigned long __init extend_init_mapping(unsigned long tables_space)
+{
+	unsigned long start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT)
+				  + xen_start_info->nr_pt_frames;
+	unsigned long start = start_pfn, va = (unsigned long)&_text;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	/* Ensure init mappings cover kernel text/data and initial tables. */
+	while (va < PAGE_OFFSET + (start_pfn << PAGE_SHIFT) + tables_space) {
+		pgd = pgd_offset_k(va);
+		pud = pud_offset(pgd, va);
+		pmd = pmd_offset(pud, va);
+		if (pmd_none(*pmd)) {
+			unsigned long pa = start_pfn++ << PAGE_SHIFT;
+
+			memset(__va(pa), 0, PAGE_SIZE);
+			make_lowmem_page_readonly(__va(pa),
+						  XENFEAT_writable_page_tables);
+			xen_l2_entry_update(pmd, __pmd(pa | _KERNPG_TABLE));
+		}
+		pte = pte_offset_kernel(pmd, va);
+		if (pte_none(*pte)) {
+			pte_t new_pte = __pte(__pa(va) | _KERNPG_TABLE);
+
+			if (HYPERVISOR_update_va_mapping(va, new_pte, 0))
+				BUG();
+		}
+		va += PAGE_SIZE;
+	}
+
+	/* Finally, blow away any spurious initial mappings. */
+	while (1) {
+		pgd = pgd_offset_k(va);
+		pud = pud_offset(pgd, va);
+		pmd = pmd_offset(pud, va);
+		if (pmd_none(*pmd))
+			break;
+		if (HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0))
+			BUG();
+		va += PAGE_SIZE;
+	}
+
+	if (start_pfn > start)
+		reserve_early(start << PAGE_SHIFT,
+			      start_pfn << PAGE_SHIFT, "INITMAP");
+
+	return start_pfn;
+}
+
+/*
+ * paging_init() sets up the page tables - note that the first 8MB are
+ * already mapped by head.S.
+ *
+ * This routines also unmaps the page at virtual kernel address 0, so
+ * that we can trap those pesky NULL-reference errors in the kernel.
+ */
+void __init paging_init(void)
+{
+	pagetable_init();
+
+	__flush_tlb_all();
+
+	kmap_init();
+
+	/*
+	 * NOTE: at this point the bootmem allocator is fully available.
+	 */
+	sparse_init();
+	zone_sizes_init();
+}
+
+/*
+ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+ * and also on some strange 486's. All 586+'s are OK. This used to involve
+ * black magic jumps to work around some nasty CPU bugs, but fortunately the
+ * switch to using exceptions got rid of all that.
+ */
+static void __init test_wp_bit(void)
+{
+	printk(KERN_INFO
+  "Checking if this processor honours the WP bit even in supervisor mode...");
+
+	/* Any page-aligned address will do, the test is non-destructive */
+	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
+	boot_cpu_data.wp_works_ok = do_test_wp_bit();
+	clear_fixmap(FIX_WP_TEST);
+
+	if (!boot_cpu_data.wp_works_ok) {
+		printk(KERN_CONT "No.\n");
+#ifdef CONFIG_X86_WP_WORKS_OK
+		panic(
+  "This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
+#endif
+	} else {
+		printk(KERN_CONT "Ok.\n");
+	}
+}
+
+void __init mem_init(void)
+{
+	int codesize, reservedpages, datasize, initsize;
+	int tmp;
+	unsigned long pfn;
+
+	pci_iommu_alloc();
+
+#ifdef CONFIG_FLATMEM
+	BUG_ON(!mem_map);
+#endif
+	/* this will put all low memory onto the freelists */
+	totalram_pages += free_all_bootmem();
+	/* XEN: init low-mem pages outside initial allocation. */
+	for (pfn = xen_start_info->nr_pages; pfn < max_low_pfn; pfn++) {
+		ClearPageReserved(pfn_to_page(pfn));
+		init_page_count(pfn_to_page(pfn));
+	}
+
+	reservedpages = 0;
+	for (tmp = 0; tmp < max_low_pfn; tmp++)
+		/*
+		 * Only count reserved RAM pages:
+		 */
+		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
+			reservedpages++;
+
+	set_highmem_pages_init();
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+			"%dk reserved, %dk data, %dk init, %ldk highmem)\n",
+		nr_free_pages() << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
+		codesize >> 10,
+		reservedpages << (PAGE_SHIFT-10),
+		datasize >> 10,
+		initsize >> 10,
+		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
+	       );
+
+	printk(KERN_INFO "virtual kernel memory layout:\n"
+		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#ifdef CONFIG_HIGHMEM
+		"    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#endif
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
+		FIXADDR_START, FIXADDR_TOP,
+		(FIXADDR_TOP - FIXADDR_START) >> 10,
+
+#ifdef CONFIG_HIGHMEM
+		PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
+		(LAST_PKMAP*PAGE_SIZE) >> 10,
+#endif
+
+		VMALLOC_START, VMALLOC_END,
+		(VMALLOC_END - VMALLOC_START) >> 20,
+
+		(unsigned long)__va(0), (unsigned long)high_memory,
+		((unsigned long)high_memory - (unsigned long)__va(0)) >> 20,
+
+		(unsigned long)&__init_begin, (unsigned long)&__init_end,
+		((unsigned long)&__init_end -
+		 (unsigned long)&__init_begin) >> 10,
+
+		(unsigned long)&_etext, (unsigned long)&_edata,
+		((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+
+		(unsigned long)&_text, (unsigned long)&_etext,
+		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+
+	/*
+	 * Check boundaries twice: Some fundamental inconsistencies can
+	 * be detected at build time already.
+	 */
+#define __FIXADDR_TOP (-PAGE_SIZE)
+#ifdef CONFIG_HIGHMEM
+	BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
+	BUILD_BUG_ON(VMALLOC_END			> PKMAP_BASE);
+#endif
+#define high_memory (-128UL << 20)
+	BUILD_BUG_ON(VMALLOC_START			>= VMALLOC_END);
+#undef high_memory
+#undef __FIXADDR_TOP
+
+#ifdef CONFIG_HIGHMEM
+	BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
+	BUG_ON(VMALLOC_END				> PKMAP_BASE);
+#endif
+	BUG_ON(VMALLOC_START				>= VMALLOC_END);
+	BUG_ON((unsigned long)high_memory		> VMALLOC_START);
+
+	if (boot_cpu_data.wp_works_ok < 0)
+		test_wp_bit();
+
+	save_pg_dir();
+	zap_low_mappings(true);
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+	struct pglist_data *pgdata = NODE_DATA(nid);
+	struct zone *zone = pgdata->node_zones + ZONE_HIGHMEM;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+
+	return __add_pages(nid, zone, start_pfn, nr_pages);
+}
+#endif
+
+/*
+ * This function cannot be __init, since exceptions don't work in that
+ * section.  Put this after the callers, so that it cannot be inlined.
+ */
+static noinline int do_test_wp_bit(void)
+{
+	char tmp_reg;
+	int flag;
+
+	__asm__ __volatile__(
+		"	movb %0, %1	\n"
+		"1:	movb %1, %0	\n"
+		"	xorl %2, %2	\n"
+		"2:			\n"
+		_ASM_EXTABLE(1b,2b)
+		:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
+		 "=q" (tmp_reg),
+		 "=r" (flag)
+		:"2" (1)
+		:"memory");
+
+	return flag;
+}
+
+#ifdef CONFIG_DEBUG_RODATA
+const int rodata_test_data = 0xC3;
+EXPORT_SYMBOL_GPL(rodata_test_data);
+
+static int kernel_set_to_readonly;
+
+void set_kernel_text_rw(void)
+{
+	unsigned long start = PFN_ALIGN(_text);
+	unsigned long size = PFN_ALIGN(_etext) - start;
+
+	if (!kernel_set_to_readonly)
+		return;
+
+	pr_debug("Set kernel text: %lx - %lx for read write\n",
+		 start, start+size);
+
+	set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
+}
+
+void set_kernel_text_ro(void)
+{
+	unsigned long start = PFN_ALIGN(_text);
+	unsigned long size = PFN_ALIGN(_etext) - start;
+
+	if (!kernel_set_to_readonly)
+		return;
+
+	pr_debug("Set kernel text: %lx - %lx for read only\n",
+		 start, start+size);
+
+	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+}
+
+void mark_rodata_ro(void)
+{
+	unsigned long start = PFN_ALIGN(_text);
+	unsigned long size = PFN_ALIGN(_etext) - start;
+
+	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+	printk(KERN_INFO "Write protecting the kernel text: %luk\n",
+		size >> 10);
+
+	kernel_set_to_readonly = 1;
+
+#ifdef CONFIG_CPA_DEBUG
+	printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n",
+		start, start+size);
+	set_pages_rw(virt_to_page(start), size>>PAGE_SHIFT);
+
+	printk(KERN_INFO "Testing CPA: write protecting again\n");
+	set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT);
+#endif
+
+	start += size;
+	size = (unsigned long)__end_rodata - start;
+	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+	printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
+		size >> 10);
+	rodata_test();
+
+#ifdef CONFIG_CPA_DEBUG
+	printk(KERN_INFO "Testing CPA: undo %lx-%lx\n", start, start + size);
+	set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
+
+	printk(KERN_INFO "Testing CPA: write protecting again\n");
+	set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
+#endif
+}
+#endif
+
+int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
+				   int flags)
+{
+	return reserve_bootmem(phys, len, flags);
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/mmap.c
+++ linux-ec2-2.6.32/arch/x86/mm/mmap.c
@@ -131,6 +131,11 @@
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+#ifdef CONFIG_X86_32
+		if (!nx_enabled && !(current->personality & READ_IMPLIES_EXEC)
+		    && mmap_is_ia32())
+			mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
+#endif
 		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
--- linux-ec2-2.6.32.orig/arch/x86/mm/hypervisor.c
+++ linux-ec2-2.6.32/arch/x86/mm/hypervisor.c
@@ -0,0 +1,1214 @@
+/******************************************************************************
+ * mm/hypervisor.c
+ * 
+ * Update page tables via the hypervisor.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * 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/sched.h>
+#include <linux/hardirq.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/hypervisor.h>
+#include <xen/balloon.h>
+#include <xen/features.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/vcpu.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <asm/tlbflush.h>
+#include <linux/highmem.h>
+
+EXPORT_SYMBOL(hypercall_page);
+
+shared_info_t *__read_mostly HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+#ifndef CONFIG_XEN_VCPU_INFO_PLACEMENT
+EXPORT_SYMBOL(HYPERVISOR_shared_info);
+#else
+DEFINE_PER_CPU(struct vcpu_info, vcpu_info) __aligned(sizeof(struct vcpu_info));
+EXPORT_PER_CPU_SYMBOL(vcpu_info);
+
+void __ref setup_vcpu_info(unsigned int cpu)
+{
+	struct vcpu_info *v = &per_cpu(vcpu_info, cpu);
+	struct vcpu_register_vcpu_info info;
+#ifdef CONFIG_X86_64
+	static bool first = true;
+
+	if (first) {
+		first = false;
+		info.mfn = early_arbitrary_virt_to_mfn(v);
+	} else
+#endif
+		info.mfn = arbitrary_virt_to_mfn(v);
+	info.offset = offset_in_page(v);
+
+	if (HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info,
+			       cpu, &info))
+		BUG();
+}
+
+void __init adjust_boot_vcpu_info(void)
+{
+	unsigned long lpfn, rpfn, lmfn, rmfn;
+	pte_t *lpte, *rpte;
+	unsigned int level;
+	mmu_update_t mmu[2];
+
+	/*
+	 * setup_vcpu_info() cannot be used more than once for a given (v)CPU,
+	 * hence we must swap the underlying MFNs of the two pages holding old
+	 * and new vcpu_info of the boot CPU.
+	 *
+	 * Do *not* use __get_cpu_var() or percpu_{write,...}() here, as the per-
+	 * CPU segment didn't get reloaded yet. Using percpu_read(), as in
+	 * arch_use_lazy_mmu_mode(), though undesirable, is safe except for the
+	 * accesses to variables that were updated in setup_percpu_areas().
+	 */
+	lpte = lookup_address((unsigned long)&per_cpu_var(vcpu_info)
+			      + (__per_cpu_load - __per_cpu_start),
+			      &level);
+	rpte = lookup_address((unsigned long)&per_cpu(vcpu_info, 0), &level);
+	BUG_ON(!lpte || !(pte_flags(*lpte) & _PAGE_PRESENT));
+	BUG_ON(!rpte || !(pte_flags(*rpte) & _PAGE_PRESENT));
+	lmfn = __pte_mfn(*lpte);
+	rmfn = __pte_mfn(*rpte);
+
+	if (lmfn == rmfn)
+		return;
+
+	lpfn = mfn_to_local_pfn(lmfn);
+	rpfn = mfn_to_local_pfn(rmfn);
+
+	printk(KERN_INFO
+	       "Swapping MFNs for PFN %lx and %lx (MFN %lx and %lx)\n",
+	       lpfn, rpfn, lmfn, rmfn);
+
+	xen_l1_entry_update(lpte, pfn_pte_ma(rmfn, pte_pgprot(*lpte)));
+	xen_l1_entry_update(rpte, pfn_pte_ma(lmfn, pte_pgprot(*rpte)));
+#ifdef CONFIG_X86_64
+	if (HYPERVISOR_update_va_mapping((unsigned long)__va(lpfn<<PAGE_SHIFT),
+					 pfn_pte_ma(rmfn, PAGE_KERNEL_RO), 0))
+		BUG();
+#endif
+	if (HYPERVISOR_update_va_mapping((unsigned long)__va(rpfn<<PAGE_SHIFT),
+					 pfn_pte_ma(lmfn, PAGE_KERNEL),
+					 UVMF_TLB_FLUSH))
+		BUG();
+
+	set_phys_to_machine(lpfn, rmfn);
+	set_phys_to_machine(rpfn, lmfn);
+
+	mmu[0].ptr = ((uint64_t)lmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+	mmu[0].val = rpfn;
+	mmu[1].ptr = ((uint64_t)rmfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+	mmu[1].val = lpfn;
+	if (HYPERVISOR_mmu_update(mmu, 2, NULL, DOMID_SELF))
+		BUG();
+}
+#endif
+
+#define NR_MC     BITS_PER_LONG
+#define NR_MMU    BITS_PER_LONG
+#define NR_MMUEXT (BITS_PER_LONG / 4)
+
+DEFINE_PER_CPU(bool, xen_lazy_mmu);
+EXPORT_PER_CPU_SYMBOL(xen_lazy_mmu);
+struct lazy_mmu {
+	unsigned int nr_mc, nr_mmu, nr_mmuext;
+	multicall_entry_t mc[NR_MC];
+	mmu_update_t mmu[NR_MMU];
+	struct mmuext_op mmuext[NR_MMUEXT];
+};
+static DEFINE_PER_CPU(struct lazy_mmu, lazy_mmu);
+
+static inline bool use_lazy_mmu_mode(void)
+{
+#ifdef CONFIG_PREEMPT
+	if (!preempt_count())
+		return false;
+#endif
+	return !irq_count();
+}
+
+static void multicall_failed(const multicall_entry_t *mc, int rc)
+{
+	printk(KERN_EMERG "hypercall#%lu(%lx, %lx, %lx, %lx)"
+			  " failed: %d (caller %lx)\n",
+	       mc->op, mc->args[0], mc->args[1], mc->args[2], mc->args[3],
+	       rc, mc->args[5]);
+	BUG();
+}
+
+static int _xen_multicall_flush(bool ret_last) {
+	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
+	multicall_entry_t *mc = lazy->mc;
+	unsigned int count = lazy->nr_mc;
+
+	if (!count)
+		return 0;
+
+	lazy->nr_mc = 0;
+	lazy->nr_mmu = 0;
+	lazy->nr_mmuext = 0;
+
+	if (count == 1) {
+		int rc = _hypercall(int, mc->op, mc->args[0], mc->args[1],
+				    mc->args[2], mc->args[3], mc->args[4]);
+
+		if (unlikely(rc)) {
+			if (ret_last)
+				return rc;
+			multicall_failed(mc, rc);
+		}
+	} else {
+		if (HYPERVISOR_multicall(mc, count))
+			BUG();
+		while (count-- > ret_last)
+			if (unlikely(mc++->result))
+				multicall_failed(mc - 1, mc[-1].result);
+		if (ret_last)
+			return mc->result;
+	}
+
+	return 0;
+}
+
+void xen_multicall_flush(bool force) {
+	if (force || use_lazy_mmu_mode())
+		_xen_multicall_flush(false);
+}
+EXPORT_SYMBOL(xen_multicall_flush);
+
+int xen_multi_update_va_mapping(unsigned long va, pte_t pte,
+				unsigned long uvmf)
+{
+	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
+	multicall_entry_t *mc;
+
+	if (unlikely(!use_lazy_mmu_mode()))
+#ifdef CONFIG_X86_PAE
+		return _hypercall4(int, update_va_mapping, va,
+				   pte.pte_low, pte.pte_high, uvmf);
+#else
+		return _hypercall3(int, update_va_mapping, va,
+				   pte.pte, uvmf);
+#endif
+
+	if (unlikely(lazy->nr_mc == NR_MC))
+		_xen_multicall_flush(false);
+
+	mc = lazy->mc + lazy->nr_mc++;
+	mc->op = __HYPERVISOR_update_va_mapping;
+	mc->args[0] = va;
+#ifndef CONFIG_X86_PAE
+	mc->args[1] = pte.pte;
+#else
+	mc->args[1] = pte.pte_low;
+	mc->args[2] = pte.pte_high;
+#endif
+	mc->args[MULTI_UVMFLAGS_INDEX] = uvmf;
+	mc->args[5] = (long)__builtin_return_address(0);
+
+	return 0;
+}
+
+static inline bool mmu_may_merge(const multicall_entry_t *mc,
+				 unsigned int op, domid_t domid)
+{
+	return mc->op == op && !mc->args[2] && mc->args[3] == domid;
+}
+
+int xen_multi_mmu_update(mmu_update_t *src, unsigned int count,
+			 unsigned int *success_count, domid_t domid)
+{
+	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
+	multicall_entry_t *mc = lazy->mc + lazy->nr_mc;
+	mmu_update_t *dst;
+	bool commit, merge;
+
+	if (unlikely(!use_lazy_mmu_mode()))
+		return _hypercall4(int, mmu_update, src, count,
+				   success_count, domid);
+
+	commit = (lazy->nr_mmu + count) > NR_MMU || success_count;
+	merge = lazy->nr_mc && !commit
+		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmu_update, domid);
+	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
+		_xen_multicall_flush(false);
+		mc = lazy->mc;
+		commit = count > NR_MMU || success_count;
+	}
+
+	if (!lazy->nr_mc && unlikely(commit))
+		return _hypercall4(int, mmu_update, src, count,
+				   success_count, domid);
+
+	dst = lazy->mmu + lazy->nr_mmu;
+	lazy->nr_mmu += count;
+	if (merge) {
+		mc[-1].args[1] += count;
+		memcpy(dst, src, count * sizeof(*src));
+	} else {
+		++lazy->nr_mc;
+		mc->op = __HYPERVISOR_mmu_update;
+		if (!commit) {
+			mc->args[0] = (unsigned long)dst;
+			memcpy(dst, src, count * sizeof(*src));
+		} else
+			mc->args[0] = (unsigned long)src;
+		mc->args[1] = count;
+		mc->args[2] = (unsigned long)success_count;
+		mc->args[3] = domid;
+		mc->args[5] = (long)__builtin_return_address(0);
+	}
+
+	while (!commit && count--)
+		switch (src++->ptr & (sizeof(pteval_t) - 1)) {
+		case MMU_NORMAL_PT_UPDATE:
+		case MMU_PT_UPDATE_PRESERVE_AD:
+			break;
+		default:
+			commit = true;
+			break;
+		}
+
+	return commit ? _xen_multicall_flush(true) : 0;
+}
+
+int xen_multi_mmuext_op(struct mmuext_op *src, unsigned int count,
+			unsigned int *success_count, domid_t domid)
+{
+	struct lazy_mmu *lazy = &__get_cpu_var(lazy_mmu);
+	multicall_entry_t *mc;
+	struct mmuext_op *dst;
+	bool commit, merge;
+
+	if (unlikely(!use_lazy_mmu_mode()))
+		return _hypercall4(int, mmuext_op, src, count,
+				   success_count, domid);
+
+	/*
+	 * While it could be useful in theory, I've never seen the body of
+	 * this conditional to be reached, hence it seems more reasonable
+	 * to disable it for the time being.
+	 */
+	if (0 && likely(count)
+	    && likely(!success_count)
+	    && likely(domid == DOMID_SELF)
+	    && likely(lazy->nr_mc)
+	    && lazy->mc[lazy->nr_mc - 1].op == __HYPERVISOR_update_va_mapping) {
+		unsigned long oldf, newf = UVMF_NONE;
+
+		switch (src->cmd) {
+		case MMUEXT_TLB_FLUSH_ALL:
+			newf = UVMF_TLB_FLUSH | UVMF_ALL;
+			break;
+		case MMUEXT_INVLPG_ALL:
+			newf = UVMF_INVLPG | UVMF_ALL;
+			break;
+		case MMUEXT_TLB_FLUSH_MULTI:
+			newf = UVMF_TLB_FLUSH | UVMF_MULTI
+			       | (unsigned long)src->arg2.vcpumask.p;
+			break;
+		case MMUEXT_INVLPG_MULTI:
+			newf = UVMF_INVLPG | UVMF_MULTI
+			       | (unsigned long)src->arg2.vcpumask.p;
+			break;
+		case MMUEXT_TLB_FLUSH_LOCAL:
+			newf = UVMF_TLB_FLUSH | UVMF_LOCAL;
+			break;
+		case MMUEXT_INVLPG_LOCAL:
+			newf = UVMF_INVLPG | UVMF_LOCAL;
+			break;
+		}
+		mc = lazy->mc + lazy->nr_mc - 1;
+		oldf = mc->args[MULTI_UVMFLAGS_INDEX];
+		if (newf == UVMF_NONE || oldf == UVMF_NONE
+		    || newf == (UVMF_TLB_FLUSH | UVMF_ALL))
+			;
+		else if (oldf == (UVMF_TLB_FLUSH | UVMF_ALL))
+			newf = UVMF_TLB_FLUSH | UVMF_ALL;
+		else if ((newf & UVMF_FLUSHTYPE_MASK) == UVMF_INVLPG
+			 && (oldf & UVMF_FLUSHTYPE_MASK) == UVMF_INVLPG
+			 && ((src->arg1.linear_addr ^ mc->args[0])
+			     >> PAGE_SHIFT))
+			newf = UVMF_NONE;
+		else if (((oldf | newf) & UVMF_ALL)
+			 && !((oldf ^ newf) & UVMF_FLUSHTYPE_MASK))
+			newf |= UVMF_ALL;
+		else if ((oldf ^ newf) & ~UVMF_FLUSHTYPE_MASK)
+			newf = UVMF_NONE;
+		else if ((oldf & UVMF_FLUSHTYPE_MASK) == UVMF_TLB_FLUSH)
+			newf = (newf & ~UVMF_FLUSHTYPE_MASK) | UVMF_TLB_FLUSH;
+		else if ((newf & UVMF_FLUSHTYPE_MASK) != UVMF_TLB_FLUSH
+			 && ((newf ^ oldf) & UVMF_FLUSHTYPE_MASK))
+			newf = UVMF_NONE;
+		if (newf != UVMF_NONE) {
+			mc->args[MULTI_UVMFLAGS_INDEX] = newf;
+			++src;
+			if (!--count)
+				return 0;
+		}
+	}
+
+	mc = lazy->mc + lazy->nr_mc;
+	commit = (lazy->nr_mmuext + count) > NR_MMUEXT || success_count;
+	merge = lazy->nr_mc && !commit
+		&& mmu_may_merge(mc - 1, __HYPERVISOR_mmuext_op, domid);
+	if (unlikely(lazy->nr_mc == NR_MC) && !merge) {
+		_xen_multicall_flush(false);
+		mc = lazy->mc;
+		commit = count > NR_MMUEXT || success_count;
+	}
+
+	if (!lazy->nr_mc && unlikely(commit))
+		return _hypercall4(int, mmuext_op, src, count,
+				   success_count, domid);
+
+	dst = lazy->mmuext + lazy->nr_mmuext;
+	lazy->nr_mmuext += count;
+	if (merge) {
+		mc[-1].args[1] += count;
+		memcpy(dst, src, count * sizeof(*src));
+	} else {
+		++lazy->nr_mc;
+		mc->op = __HYPERVISOR_mmuext_op;
+		if (!commit) {
+			mc->args[0] = (unsigned long)dst;
+			memcpy(dst, src, count * sizeof(*src));
+		} else
+			mc->args[0] = (unsigned long)src;
+		mc->args[1] = count;
+		mc->args[2] = (unsigned long)success_count;
+		mc->args[3] = domid;
+		mc->args[5] = (long)__builtin_return_address(0);
+	}
+
+	while (!commit && count--)
+		switch (src++->cmd) {
+		case MMUEXT_PIN_L1_TABLE:
+		case MMUEXT_PIN_L2_TABLE:
+		case MMUEXT_PIN_L3_TABLE:
+		case MMUEXT_PIN_L4_TABLE:
+		case MMUEXT_UNPIN_TABLE:
+		case MMUEXT_TLB_FLUSH_LOCAL:
+		case MMUEXT_INVLPG_LOCAL:
+		case MMUEXT_TLB_FLUSH_MULTI:
+		case MMUEXT_INVLPG_MULTI:
+		case MMUEXT_TLB_FLUSH_ALL:
+		case MMUEXT_INVLPG_ALL:
+			break;
+		default:
+			commit = true;
+			break;
+		}
+
+	return commit ? _xen_multicall_flush(true) : 0;
+}
+
+void xen_l1_entry_update(pte_t *ptr, pte_t val)
+{
+	mmu_update_t u;
+	u.ptr = ptep_to_machine(ptr);
+	u.val = __pte_val(val);
+	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL_GPL(xen_l1_entry_update);
+
+static void do_lN_entry_update(mmu_update_t *mmu, unsigned int mmu_count,
+                               struct page *page)
+{
+	if (likely(page)) {
+		multicall_entry_t mcl[2];
+		unsigned long pfn = page_to_pfn(page);
+
+		MULTI_update_va_mapping(mcl,
+					(unsigned long)__va(pfn << PAGE_SHIFT),
+					pfn_pte(pfn, PAGE_KERNEL_RO), 0);
+		SetPagePinned(page);
+		MULTI_mmu_update(mcl + 1, mmu, mmu_count, NULL, DOMID_SELF);
+		if (unlikely(HYPERVISOR_multicall_check(mcl, 2, NULL)))
+			BUG();
+	} else if (unlikely(HYPERVISOR_mmu_update(mmu, mmu_count,
+						  NULL, DOMID_SELF) < 0))
+		BUG();
+}
+
+void xen_l2_entry_update(pmd_t *ptr, pmd_t val)
+{
+	mmu_update_t u;
+	struct page *page = NULL;
+
+	if (likely(pmd_present(val)) && likely(!pmd_large(val))
+	    && likely(mem_map)
+	    && likely(PagePinned(virt_to_page(ptr)))) {
+		page = pmd_page(val);
+		if (unlikely(PagePinned(page)))
+			page = NULL;
+		else if (PageHighMem(page)) {
+#ifdef CONFIG_HIGHPTE
+			BUG();
+#endif
+			kmap_flush_unused();
+			page = NULL;
+		}
+	}
+	u.ptr = virt_to_machine(ptr);
+	u.val = __pmd_val(val);
+	do_lN_entry_update(&u, 1, page);
+}
+
+#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
+void xen_l3_entry_update(pud_t *ptr, pud_t val)
+{
+	mmu_update_t u;
+	struct page *page = NULL;
+
+	if (likely(pud_present(val))
+#ifdef CONFIG_X86_64
+	    && likely(!pud_large(val))
+#endif
+	    && likely(mem_map)
+	    && likely(PagePinned(virt_to_page(ptr)))) {
+		page = pud_page(val);
+		if (unlikely(PagePinned(page)))
+			page = NULL;
+	}
+	u.ptr = virt_to_machine(ptr);
+	u.val = __pud_val(val);
+	do_lN_entry_update(&u, 1, page);
+}
+#endif
+
+#ifdef CONFIG_X86_64
+void xen_l4_entry_update(pgd_t *ptr, pgd_t val)
+{
+	mmu_update_t u[2];
+	struct page *page = NULL;
+
+	if (likely(pgd_present(val)) && likely(mem_map)
+	    && likely(PagePinned(virt_to_page(ptr)))) {
+		page = pgd_page(val);
+		if (unlikely(PagePinned(page)))
+			page = NULL;
+	}
+	u[0].ptr = virt_to_machine(ptr);
+	u[0].val = __pgd_val(val);
+	if (((unsigned long)ptr & ~PAGE_MASK)
+	    <= pgd_index(TASK_SIZE_MAX) * sizeof(*ptr)) {
+		ptr = __user_pgd(ptr);
+		BUG_ON(!ptr);
+		u[1].ptr = virt_to_machine(ptr);
+		u[1].val = __pgd_val(val);
+		do_lN_entry_update(u, 2, page);
+	} else
+		do_lN_entry_update(u, 1, page);
+}
+#endif /* CONFIG_X86_64 */
+
+#ifdef CONFIG_X86_64
+void xen_pt_switch(pgd_t *pgd)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_NEW_BASEPTR;
+	op.arg1.mfn = virt_to_mfn(pgd);
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+void xen_new_user_pt(pgd_t *pgd)
+{
+	struct mmuext_op op;
+
+	pgd = __user_pgd(pgd);
+	op.cmd = MMUEXT_NEW_USER_BASEPTR;
+	op.arg1.mfn = pgd ? virt_to_mfn(pgd) : 0;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+#endif
+
+void xen_tlb_flush(void)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_TLB_FLUSH_LOCAL;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL(xen_tlb_flush);
+
+void xen_invlpg(unsigned long ptr)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_INVLPG_LOCAL;
+	op.arg1.linear_addr = ptr & PAGE_MASK;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL(xen_invlpg);
+
+#ifdef CONFIG_SMP
+
+void xen_tlb_flush_all(void)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_TLB_FLUSH_ALL;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL_GPL(xen_tlb_flush_all);
+
+void xen_tlb_flush_mask(const cpumask_t *mask)
+{
+	struct mmuext_op op;
+	if ( cpus_empty(*mask) )
+		return;
+	op.cmd = MMUEXT_TLB_FLUSH_MULTI;
+	set_xen_guest_handle(op.arg2.vcpumask, cpus_addr(*mask));
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL_GPL(xen_tlb_flush_mask);
+
+void xen_invlpg_all(unsigned long ptr)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_INVLPG_ALL;
+	op.arg1.linear_addr = ptr & PAGE_MASK;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL_GPL(xen_invlpg_all);
+
+void xen_invlpg_mask(const cpumask_t *mask, unsigned long ptr)
+{
+	struct mmuext_op op;
+	if ( cpus_empty(*mask) )
+		return;
+	op.cmd = MMUEXT_INVLPG_MULTI;
+	op.arg1.linear_addr = ptr & PAGE_MASK;
+	set_xen_guest_handle(op.arg2.vcpumask, cpus_addr(*mask));
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+EXPORT_SYMBOL_GPL(xen_invlpg_mask);
+
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_X86_64
+#define NR_PGD_PIN_OPS 2
+#else
+#define NR_PGD_PIN_OPS 1
+#endif
+
+void xen_pgd_pin(pgd_t *pgd)
+{
+	struct mmuext_op op[NR_PGD_PIN_OPS];
+	unsigned int nr = NR_PGD_PIN_OPS;
+
+	op[0].cmd = MMUEXT_PIN_L3_TABLE;
+	op[0].arg1.mfn = virt_to_mfn(pgd);
+#ifdef CONFIG_X86_64
+	op[1].cmd = op[0].cmd = MMUEXT_PIN_L4_TABLE;
+	pgd = __user_pgd(pgd);
+	if (pgd)
+		op[1].arg1.mfn = virt_to_mfn(pgd);
+	else
+		nr = 1;
+#endif
+	if (HYPERVISOR_mmuext_op(op, nr, NULL, DOMID_SELF) < 0)
+		BUG();
+}
+
+void xen_pgd_unpin(pgd_t *pgd)
+{
+	struct mmuext_op op[NR_PGD_PIN_OPS];
+	unsigned int nr = NR_PGD_PIN_OPS;
+
+	op[0].cmd = MMUEXT_UNPIN_TABLE;
+	op[0].arg1.mfn = virt_to_mfn(pgd);
+#ifdef CONFIG_X86_64
+	pgd = __user_pgd(pgd);
+	if (pgd) {
+		op[1].cmd = MMUEXT_UNPIN_TABLE;
+		op[1].arg1.mfn = virt_to_mfn(pgd);
+	} else
+		nr = 1;
+#endif
+	if (HYPERVISOR_mmuext_op(op, nr, NULL, DOMID_SELF) < 0)
+		BUG();
+}
+
+void xen_set_ldt(const void *ptr, unsigned int ents)
+{
+	struct mmuext_op op;
+	op.cmd = MMUEXT_SET_LDT;
+	op.arg1.linear_addr = (unsigned long)ptr;
+	op.arg2.nr_ents     = ents;
+	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+}
+
+/* Protected by balloon_lock. */
+#define MAX_CONTIG_ORDER 9 /* 2MB */
+static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
+static unsigned long limited_frames[1<<MAX_CONTIG_ORDER];
+static multicall_entry_t cr_mcl[1<<MAX_CONTIG_ORDER];
+
+/* Ensure multi-page extents are contiguous in machine memory. */
+int xen_create_contiguous_region(
+	unsigned long vstart, unsigned int order, unsigned int address_bits)
+{
+	unsigned long *in_frames = discontig_frames, out_frame;
+	unsigned long  frame, flags;
+	unsigned int   i;
+	int            rc, success;
+#ifdef CONFIG_64BIT
+	pte_t         *ptep = NULL;
+#endif
+	struct xen_memory_exchange exchange = {
+		.in = {
+			.nr_extents   = 1UL << order,
+			.extent_order = 0,
+			.domid        = DOMID_SELF
+		},
+		.out = {
+			.nr_extents   = 1,
+			.extent_order = order,
+			.address_bits = address_bits,
+			.domid        = DOMID_SELF
+		}
+	};
+
+	/*
+	 * Currently an auto-translated guest will not perform I/O, nor will
+	 * it require PAE page directories below 4GB. Therefore any calls to
+	 * this function are redundant and can be ignored.
+	 */
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return 0;
+
+	if (unlikely(order > MAX_CONTIG_ORDER))
+		return -ENOMEM;
+
+#ifdef CONFIG_64BIT
+	if (unlikely(vstart > PAGE_OFFSET + MAXMEM)) {
+		unsigned int level;
+
+		if (vstart < __START_KERNEL_map
+		    || vstart + (PAGE_SIZE << order) > _brk_end)
+			return -EINVAL;
+		ptep = lookup_address((unsigned long)__va(__pa(vstart)),
+				      &level);
+		if (ptep && pte_none(*ptep))
+			ptep = NULL;
+		if (vstart < __START_KERNEL && ptep)
+			return -EINVAL;
+		if (order > MAX_CONTIG_ORDER - 1)
+			return -ENOMEM;
+	}
+#else
+	if (unlikely(vstart + (PAGE_SIZE << order) > (unsigned long)high_memory))
+		return -EINVAL;
+#endif
+
+	set_xen_guest_handle(exchange.in.extent_start, in_frames);
+	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
+
+	scrub_pages((void *)vstart, 1 << order);
+
+	balloon_lock(flags);
+
+	/* 1. Zap current PTEs, remembering MFNs. */
+	for (i = 0; i < (1U<<order); i++) {
+		in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
+		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+					__pte_ma(0), 0);
+#ifdef CONFIG_64BIT
+		if (ptep)
+			MULTI_update_va_mapping(cr_mcl + i + (1U << order),
+				(unsigned long)__va(__pa(vstart)) + (i*PAGE_SIZE),
+				__pte_ma(0), 0);
+#endif
+		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
+			INVALID_P2M_ENTRY);
+	}
+#ifdef CONFIG_64BIT
+	if (ptep)
+		i += i;
+#endif
+	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
+		BUG();
+
+	/* 2. Get a new contiguous memory extent. */
+	out_frame = __pa(vstart) >> PAGE_SHIFT;
+	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+	success = (exchange.nr_exchanged == (1UL << order));
+	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
+	BUG_ON(success && (rc != 0));
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		/* Compatibility when XENMEM_exchange is unsupported. */
+		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					 &exchange.in) != (1UL << order))
+			BUG();
+		success = (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+						&exchange.out) == 1);
+		if (!success) {
+			/* Couldn't get special memory: fall back to normal. */
+			for (i = 0; i < (1U<<order); i++)
+				in_frames[i] = (__pa(vstart)>>PAGE_SHIFT) + i;
+			if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+						 &exchange.in) != (1UL<<order))
+				BUG();
+		}
+	}
+#endif
+
+	/* 3. Map the new extent in place of old pages. */
+	for (i = 0; i < (1U<<order); i++) {
+		frame = success ? (out_frame + i) : in_frames[i];
+		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+					pfn_pte_ma(frame, PAGE_KERNEL), 0);
+#ifdef CONFIG_64BIT
+		if (ptep)
+			MULTI_update_va_mapping(cr_mcl + i + (1U << order),
+				(unsigned long)__va(__pa(vstart)) + (i*PAGE_SIZE),
+				pfn_pte_ma(frame, PAGE_KERNEL_RO), 0);
+#endif
+		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
+	}
+#ifdef CONFIG_64BIT
+	if (ptep)
+		i += i;
+#endif
+	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+						   ? UVMF_TLB_FLUSH|UVMF_ALL
+						   : UVMF_INVLPG|UVMF_ALL;
+	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
+		BUG();
+
+	balloon_unlock(flags);
+
+	return success ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(xen_create_contiguous_region);
+
+void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+	unsigned long *out_frames = discontig_frames, in_frame;
+	unsigned long  frame, flags;
+	unsigned int   i;
+	int            rc, success;
+	struct xen_memory_exchange exchange = {
+		.in = {
+			.nr_extents   = 1,
+			.extent_order = order,
+			.domid        = DOMID_SELF
+		},
+		.out = {
+			.nr_extents   = 1UL << order,
+			.extent_order = 0,
+			.domid        = DOMID_SELF
+		}
+	};
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
+	if (unlikely(order > MAX_CONTIG_ORDER))
+		return;
+
+	set_xen_guest_handle(exchange.in.extent_start, &in_frame);
+	set_xen_guest_handle(exchange.out.extent_start, out_frames);
+
+	scrub_pages((void *)vstart, 1 << order);
+
+	balloon_lock(flags);
+
+	/* 1. Find start MFN of contiguous extent. */
+	in_frame = pfn_to_mfn(__pa(vstart) >> PAGE_SHIFT);
+
+	/* 2. Zap current PTEs. */
+	for (i = 0; i < (1U<<order); i++) {
+		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+					__pte_ma(0), 0);
+		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
+			INVALID_P2M_ENTRY);
+		out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
+	}
+	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
+		BUG();
+
+	/* 3. Do the exchange for non-contiguous MFNs. */
+	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+	success = (exchange.nr_exchanged == 1);
+	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
+	BUG_ON(success && (rc != 0));
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		/* Compatibility when XENMEM_exchange is unsupported. */
+		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					 &exchange.in) != 1)
+			BUG();
+		if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+					 &exchange.out) != (1UL << order))
+			BUG();
+		success = 1;
+	}
+#endif
+
+	/* 4. Map new pages in place of old pages. */
+	for (i = 0; i < (1U<<order); i++) {
+		frame = success ? out_frames[i] : (in_frame + i);
+		MULTI_update_va_mapping(cr_mcl + i, vstart + (i*PAGE_SIZE),
+					pfn_pte_ma(frame, PAGE_KERNEL), 0);
+		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
+	}
+
+	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
+						   ? UVMF_TLB_FLUSH|UVMF_ALL
+						   : UVMF_INVLPG|UVMF_ALL;
+	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
+		BUG();
+
+	balloon_unlock(flags);
+
+	if (unlikely(!success)) {
+		/* Try hard to get the special memory back to Xen. */
+		exchange.in.extent_order = 0;
+		set_xen_guest_handle(exchange.in.extent_start, &in_frame);
+
+		for (i = 0; i < (1U<<order); i++) {
+			struct page *page = alloc_page(__GFP_HIGHMEM|__GFP_COLD);
+			unsigned long pfn;
+			mmu_update_t mmu;
+			unsigned int j = 0;
+
+			if (!page) {
+				printk(KERN_WARNING "Xen and kernel out of memory "
+				       "while trying to release an order %u "
+				       "contiguous region\n", order);
+				break;
+			}
+			pfn = page_to_pfn(page);
+
+			balloon_lock(flags);
+
+			if (!PageHighMem(page)) {
+				void *v = __va(pfn << PAGE_SHIFT);
+
+				scrub_pages(v, 1);
+				MULTI_update_va_mapping(cr_mcl + j, (unsigned long)v,
+							__pte_ma(0), UVMF_INVLPG|UVMF_ALL);
+				++j;
+			}
+#ifdef CONFIG_XEN_SCRUB_PAGES
+			else {
+				scrub_pages(kmap(page), 1);
+				kunmap(page);
+				kmap_flush_unused();
+			}
+#endif
+
+			frame = pfn_to_mfn(pfn);
+			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+
+			MULTI_update_va_mapping(cr_mcl + j, vstart,
+						pfn_pte_ma(frame, PAGE_KERNEL),
+						UVMF_INVLPG|UVMF_ALL);
+			++j;
+
+			pfn = __pa(vstart) >> PAGE_SHIFT;
+			set_phys_to_machine(pfn, frame);
+			if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+				mmu.ptr = ((uint64_t)frame << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
+				mmu.val = pfn;
+				cr_mcl[j].op = __HYPERVISOR_mmu_update;
+				cr_mcl[j].args[0] = (unsigned long)&mmu;
+				cr_mcl[j].args[1] = 1;
+				cr_mcl[j].args[2] = 0;
+				cr_mcl[j].args[3] = DOMID_SELF;
+				++j;
+			}
+
+			cr_mcl[j].op = __HYPERVISOR_memory_op;
+			cr_mcl[j].args[0] = XENMEM_decrease_reservation;
+			cr_mcl[j].args[1] = (unsigned long)&exchange.in;
+
+			if (HYPERVISOR_multicall(cr_mcl, j + 1))
+				BUG();
+			BUG_ON(cr_mcl[j].result != 1);
+			while (j--)
+				BUG_ON(cr_mcl[j].result != 0);
+
+			balloon_unlock(flags);
+
+			free_empty_pages(&page, 1);
+
+			in_frame++;
+			vstart += PAGE_SIZE;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
+
+int __init early_create_contiguous_region(unsigned long pfn,
+					  unsigned int order,
+					  unsigned int address_bits)
+{
+	unsigned long *in_frames = discontig_frames, out_frame = pfn;
+	unsigned int i;
+	int rc, success;
+	struct xen_memory_exchange exchange = {
+		.in = {
+			.nr_extents   = 1UL << order,
+			.extent_order = 0,
+			.domid        = DOMID_SELF
+		},
+		.out = {
+			.nr_extents   = 1,
+			.extent_order = order,
+			.address_bits = address_bits,
+			.domid        = DOMID_SELF
+		}
+	};
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return 0;
+
+	if (unlikely(order > MAX_CONTIG_ORDER))
+		return -ENOMEM;
+
+	for (i = 0; i < (1U << order); ++i) {
+		in_frames[i] = pfn_to_mfn(pfn + i);
+		set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY);
+	}
+
+	set_xen_guest_handle(exchange.in.extent_start, in_frames);
+	set_xen_guest_handle(exchange.out.extent_start, &out_frame);
+
+	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+	success = (exchange.nr_exchanged == (1UL << order));
+	BUG_ON(!success && (exchange.nr_exchanged || !rc));
+	BUG_ON(success && rc);
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		/* Compatibility when XENMEM_exchange is unavailable. */
+		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					 &exchange.in) != (1UL << order))
+			BUG();
+		success = (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+						&exchange.out) == 1);
+		if (!success) {
+			for (i = 0; i < (1U << order); ++i)
+				in_frames[i] = pfn + i;
+			if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+						 &exchange.in) != (1UL << order))
+				BUG();
+		}
+	}
+#endif
+
+	for (i = 0; i < (1U << order); ++i, ++out_frame) {
+		if (!success)
+			out_frame = in_frames[i];
+		set_phys_to_machine(pfn + i, out_frame);
+	}
+
+	return success ? 0 : -ENOMEM;
+}
+
+static void undo_limit_pages(struct page *pages, unsigned int order)
+{
+	BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+	BUG_ON(order > MAX_CONTIG_ORDER);
+	xen_limit_pages_to_max_mfn(pages, order, 0);
+	ClearPageForeign(pages);
+	__free_pages(pages, order);
+}
+
+int xen_limit_pages_to_max_mfn(
+	struct page *pages, unsigned int order, unsigned int address_bits)
+{
+	unsigned long flags, frame;
+	unsigned long *in_frames = discontig_frames, *out_frames = limited_frames;
+	struct page *page;
+	unsigned int i, n, nr_mcl;
+	int rc, success;
+	DECLARE_BITMAP(limit_map, 1 << MAX_CONTIG_ORDER);
+
+	struct xen_memory_exchange exchange = {
+		.in = {
+			.extent_order = 0,
+			.domid        = DOMID_SELF
+		},
+		.out = {
+			.extent_order = 0,
+			.address_bits = address_bits,
+			.domid        = DOMID_SELF
+		}
+	};
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return 0;
+
+	if (unlikely(order > MAX_CONTIG_ORDER))
+		return -ENOMEM;
+
+	if (address_bits) {
+		if (address_bits < PAGE_SHIFT)
+			return -EINVAL;
+		bitmap_zero(limit_map, 1U << order);
+	} else if (order) {
+		BUILD_BUG_ON(sizeof(pages->index) != sizeof(*limit_map));
+		for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+			limit_map[i] = pages[i + 1].index;
+	} else
+		__set_bit(0, limit_map);
+
+	set_xen_guest_handle(exchange.in.extent_start, in_frames);
+	set_xen_guest_handle(exchange.out.extent_start, out_frames);
+
+	/* 0. Scrub the pages. */
+	for (i = 0, n = 0; i < 1U<<order ; i++) {
+		page = &pages[i];
+		if (address_bits) {
+			if (!(pfn_to_mfn(page_to_pfn(page)) >> (address_bits - PAGE_SHIFT)))
+				continue;
+			__set_bit(i, limit_map);
+		}
+
+		if (!PageHighMem(page))
+			scrub_pages(page_address(page), 1);
+#ifdef CONFIG_XEN_SCRUB_PAGES
+		else {
+			scrub_pages(kmap(page), 1);
+			kunmap(page);
+			++n;
+		}
+#endif
+	}
+	if (bitmap_empty(limit_map, 1U << order))
+		return 0;
+
+	if (n)
+		kmap_flush_unused();
+
+	balloon_lock(flags);
+
+	/* 1. Zap current PTEs (if any), remembering MFNs. */
+	for (i = 0, n = 0, nr_mcl = 0; i < (1U<<order); i++) {
+		if(!test_bit(i, limit_map))
+			continue;
+		page = &pages[i];
+
+		out_frames[n] = page_to_pfn(page);
+		in_frames[n] = pfn_to_mfn(out_frames[n]);
+
+		if (!PageHighMem(page))
+			MULTI_update_va_mapping(cr_mcl + nr_mcl++,
+						(unsigned long)page_address(page),
+						__pte_ma(0), 0);
+
+		set_phys_to_machine(out_frames[n], INVALID_P2M_ENTRY);
+		++n;
+	}
+	if (nr_mcl && HYPERVISOR_multicall_check(cr_mcl, nr_mcl, NULL))
+		BUG();
+
+	/* 2. Get new memory below the required limit. */
+	exchange.in.nr_extents = n;
+	exchange.out.nr_extents = n;
+	rc = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+	success = (exchange.nr_exchanged == n);
+	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
+	BUG_ON(success && (rc != 0));
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		/* Compatibility when XENMEM_exchange is unsupported. */
+		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					 &exchange.in) != n)
+			BUG();
+		if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
+					 &exchange.out) != n)
+			BUG();
+		success = 1;
+	}
+#endif
+
+	/* 3. Map the new pages in place of old pages. */
+	for (i = 0, n = 0, nr_mcl = 0; i < (1U<<order); i++) {
+		if(!test_bit(i, limit_map))
+			continue;
+		page = &pages[i];
+
+		frame = success ? out_frames[n] : in_frames[n];
+
+		if (!PageHighMem(page))
+			MULTI_update_va_mapping(cr_mcl + nr_mcl++,
+						(unsigned long)page_address(page),
+						pfn_pte_ma(frame, PAGE_KERNEL), 0);
+
+		set_phys_to_machine(page_to_pfn(page), frame);
+		++n;
+	}
+	if (nr_mcl) {
+		cr_mcl[nr_mcl - 1].args[MULTI_UVMFLAGS_INDEX] = order
+							        ? UVMF_TLB_FLUSH|UVMF_ALL
+							        : UVMF_INVLPG|UVMF_ALL;
+		if (HYPERVISOR_multicall_check(cr_mcl, nr_mcl, NULL))
+			BUG();
+	}
+
+	balloon_unlock(flags);
+
+	if (!success)
+		return -ENOMEM;
+
+	if (address_bits) {
+		if (order) {
+			BUILD_BUG_ON(sizeof(*limit_map) != sizeof(pages->index));
+			for (i = 0; i < BITS_TO_LONGS(1U << order); ++i)
+				pages[i + 1].index = limit_map[i];
+		}
+		SetPageForeign(pages, undo_limit_pages);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xen_limit_pages_to_max_mfn);
+
+int write_ldt_entry(struct desc_struct *ldt, int entry, const void *desc)
+{
+	maddr_t mach_lp = arbitrary_virt_to_machine(ldt + entry);
+	return HYPERVISOR_update_descriptor(mach_lp, *(const u64*)desc);
+}
+
+int write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc,
+		    int type)
+{
+	maddr_t mach_gp = arbitrary_virt_to_machine(gdt + entry);
+	return HYPERVISOR_update_descriptor(mach_gp, *(const u64*)desc);
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/highmem_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/highmem_32-xen.c
@@ -0,0 +1,186 @@
+#include <linux/highmem.h>
+#include <linux/module.h>
+#include <linux/swap.h> /* for totalram_pages */
+
+void *kmap(struct page *page)
+{
+	might_sleep();
+	if (!PageHighMem(page))
+		return page_address(page);
+	return kmap_high(page);
+}
+
+void kunmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (!PageHighMem(page))
+		return;
+	kunmap_high(page);
+}
+
+/*
+ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+ * no global lock is needed and because the kmap code must perform a global TLB
+ * invalidation when the kmap pool wraps.
+ *
+ * However when holding an atomic kmap it is not legal to sleep, so atomic
+ * kmaps are appropriate for short, tight code paths only.
+ */
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+	pagefault_disable();
+
+	if (!PageHighMem(page))
+		return page_address(page);
+
+	debug_kmap_atomic(type);
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	BUG_ON(!pte_none(*(kmap_pte-idx)));
+	set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
+
+	return (void *)vaddr;
+}
+
+void *kmap_atomic(struct page *page, enum km_type type)
+{
+	return kmap_atomic_prot(page, type, kmap_prot);
+}
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	/*
+	 * Force other mappings to Oops if they'll try to access this pte
+	 * without first remap it.  Keeping stale mappings around is a bad idea
+	 * also, in case the page changes cacheability attributes or becomes
+	 * a protected page in a hypervisor.
+	 */
+	if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+		kpte_clear_flush(kmap_pte-idx, vaddr);
+	else {
+#ifdef CONFIG_DEBUG_HIGHMEM
+		BUG_ON(vaddr < PAGE_OFFSET);
+		BUG_ON(vaddr >= (unsigned long)high_memory);
+#endif
+	}
+
+	pagefault_enable();
+}
+
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+	return kmap_atomic_prot_pfn(pfn, type, kmap_prot);
+}
+EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+	unsigned long idx, vaddr = (unsigned long)ptr;
+	pte_t *pte;
+
+	if (vaddr < FIXADDR_START)
+		return virt_to_page(ptr);
+
+	idx = virt_to_fix(vaddr);
+	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+	return pte_page(*pte);
+}
+
+void clear_highpage(struct page *page)
+{
+	void *kaddr;
+
+	if (likely(xen_feature(XENFEAT_highmem_assist))
+	    && PageHighMem(page)) {
+		struct mmuext_op meo;
+
+		meo.cmd = MMUEXT_CLEAR_PAGE;
+		meo.arg1.mfn = pfn_to_mfn(page_to_pfn(page));
+		if (HYPERVISOR_mmuext_op(&meo, 1, NULL, DOMID_SELF) == 0)
+			return;
+	}
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	clear_page(kaddr);
+	kunmap_atomic(kaddr, KM_USER0);
+}
+
+void copy_highpage(struct page *to, struct page *from)
+{
+	void *vfrom, *vto;
+
+	if (likely(xen_feature(XENFEAT_highmem_assist))
+	    && (PageHighMem(from) || PageHighMem(to))) {
+		unsigned long from_pfn = page_to_pfn(from);
+		unsigned long to_pfn = page_to_pfn(to);
+		struct mmuext_op meo;
+
+		meo.cmd = MMUEXT_COPY_PAGE;
+		meo.arg1.mfn = pfn_to_mfn(to_pfn);
+		meo.arg2.src_mfn = pfn_to_mfn(from_pfn);
+		if (mfn_to_pfn(meo.arg2.src_mfn) == from_pfn
+		    && mfn_to_pfn(meo.arg1.mfn) == to_pfn
+		    && HYPERVISOR_mmuext_op(&meo, 1, NULL, DOMID_SELF) == 0)
+			return;
+	}
+
+	vfrom = kmap_atomic(from, KM_USER0);
+	vto = kmap_atomic(to, KM_USER1);
+	copy_page(vto, vfrom);
+	kunmap_atomic(vfrom, KM_USER0);
+	kunmap_atomic(vto, KM_USER1);
+}
+
+EXPORT_SYMBOL(kmap);
+EXPORT_SYMBOL(kunmap);
+EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_prot);
+EXPORT_SYMBOL(kmap_atomic_to_page);
+EXPORT_SYMBOL(clear_highpage);
+EXPORT_SYMBOL(copy_highpage);
+
+void __init set_highmem_pages_init(void)
+{
+	struct zone *zone;
+	int nid;
+
+	for_each_zone(zone) {
+		unsigned long zone_start_pfn, zone_end_pfn;
+
+		if (!is_highmem(zone))
+			continue;
+
+		zone_start_pfn = zone->zone_start_pfn;
+		zone_end_pfn = zone_start_pfn + zone->spanned_pages;
+
+		nid = zone_to_nid(zone);
+		printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",
+				zone->name, nid, zone_start_pfn, zone_end_pfn);
+
+		add_highpages_with_active_regions(nid, zone_start_pfn,
+				 zone_end_pfn);
+
+		/* XEN: init high-mem pages outside initial allocation. */
+		if (zone_start_pfn < xen_start_info->nr_pages)
+			zone_start_pfn = xen_start_info->nr_pages;
+		for (; zone_start_pfn < zone_end_pfn; zone_start_pfn++) {
+			ClearPageReserved(pfn_to_page(zone_start_pfn));
+			init_page_count(pfn_to_page(zone_start_pfn));
+		}
+	}
+	totalram_pages += totalhigh_pages;
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/ioremap-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/ioremap-xen.c
@@ -0,0 +1,871 @@
+/*
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ */
+
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mmiotrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/e820.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+#include <asm/pat.h>
+
+#include "physaddr.h"
+
+static int direct_remap_area_pte_fn(pte_t *pte,
+				    struct page *pmd_page,
+				    unsigned long address,
+				    void *data)
+{
+	mmu_update_t **v = (mmu_update_t **)data;
+
+	BUG_ON(!pte_none(*pte));
+
+	(*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+		     PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+	(*v)++;
+
+	return 0;
+}
+
+static int __direct_remap_pfn_range(struct mm_struct *mm,
+				    unsigned long address,
+				    unsigned long mfn,
+				    unsigned long size,
+				    pgprot_t prot,
+				    domid_t  domid)
+{
+	int rc;
+	unsigned long i, start_address;
+	mmu_update_t *u, *v, *w;
+
+	u = v = w = (mmu_update_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	if (u == NULL)
+		return -ENOMEM;
+
+	start_address = address;
+
+	flush_cache_all();
+
+	for (i = 0; i < size; i += PAGE_SIZE) {
+		if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) {
+			/* Flush a full batch after filling in the PTE ptrs. */
+			rc = apply_to_page_range(mm, start_address,
+						 address - start_address,
+						 direct_remap_area_pte_fn, &w);
+			if (rc)
+				goto out;
+			rc = -EFAULT;
+			if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)
+				goto out;
+			v = w = u;
+			start_address = address;
+		}
+
+		/*
+		 * Fill in the machine address: PTE ptr is done later by
+		 * apply_to_page_range().
+		 */
+		pgprot_val(prot) |= _PAGE_IOMAP;
+		v->val = __pte_val(pte_mkspecial(pfn_pte_ma(mfn, prot)));
+
+		mfn++;
+		address += PAGE_SIZE;
+		v++;
+	}
+
+	if (v != u) {
+		/* Final batch. */
+		rc = apply_to_page_range(mm, start_address,
+					 address - start_address,
+					 direct_remap_area_pte_fn, &w);
+		if (rc)
+			goto out;
+		rc = -EFAULT;
+		if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0))
+			goto out;
+	}
+
+	rc = 0;
+
+ out:
+	flush_tlb_all();
+
+	free_page((unsigned long)u);
+
+	return rc;
+}
+
+int direct_remap_pfn_range(struct vm_area_struct *vma,
+			   unsigned long address,
+			   unsigned long mfn,
+			   unsigned long size,
+			   pgprot_t prot,
+			   domid_t  domid)
+{
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return remap_pfn_range(vma, address, mfn, size, prot);
+
+	if (domid == DOMID_SELF)
+		return -EINVAL;
+
+	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+
+	vma->vm_mm->context.has_foreign_mappings = 1;
+
+	return __direct_remap_pfn_range(
+		vma->vm_mm, address, mfn, size, prot, domid);
+}
+EXPORT_SYMBOL(direct_remap_pfn_range);
+
+int direct_kernel_remap_pfn_range(unsigned long address,
+				  unsigned long mfn,
+				  unsigned long size,
+				  pgprot_t prot,
+				  domid_t  domid)
+{
+	return __direct_remap_pfn_range(
+		&init_mm, address, mfn, size, prot, domid);
+}
+EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
+
+static int lookup_pte_fn(
+	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+	uint64_t *ptep = (uint64_t *)data;
+	if (ptep)
+		*ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+			 PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+	return 0;
+}
+
+int create_lookup_pte_addr(struct mm_struct *mm,
+			   unsigned long address,
+			   uint64_t *ptep)
+{
+	return apply_to_page_range(mm, address, PAGE_SIZE,
+				   lookup_pte_fn, ptep);
+}
+
+EXPORT_SYMBOL(create_lookup_pte_addr);
+
+static int noop_fn(
+	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
+{
+	return 0;
+}
+
+int touch_pte_range(struct mm_struct *mm,
+		    unsigned long address,
+		    unsigned long size)
+{
+	return apply_to_page_range(mm, address, size, noop_fn, NULL);
+}
+
+EXPORT_SYMBOL(touch_pte_range);
+
+int page_is_ram(unsigned long pagenr)
+{
+	resource_size_t addr, end;
+	int i;
+
+#ifndef CONFIG_XEN
+	/*
+	 * A special case is the first 4Kb of memory;
+	 * This is a BIOS owned area, not kernel ram, but generally
+	 * not listed as such in the E820 table.
+	 */
+	if (pagenr == 0)
+		return 0;
+
+	/*
+	 * Second special case: Some BIOSen report the PC BIOS
+	 * area (640->1Mb) as ram even though it is not.
+	 */
+	if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) &&
+		    pagenr < (BIOS_END >> PAGE_SHIFT))
+		return 0;
+#endif
+
+	for (i = 0; i < e820.nr_map; i++) {
+		/*
+		 * Not usable memory:
+		 */
+		if (e820.map[i].type != E820_RAM)
+			continue;
+		addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT;
+		end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
+
+
+		if ((pagenr >= addr) && (pagenr < end))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Fix up the linear direct mapping of the kernel to avoid cache attribute
+ * conflicts.
+ */
+static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
+			       unsigned long prot_val)
+{
+	unsigned long nrpages = size >> PAGE_SHIFT;
+	int err;
+
+	switch (prot_val) {
+	case _PAGE_CACHE_UC:
+	default:
+		err = _set_memory_uc(vaddr, nrpages);
+		break;
+	case _PAGE_CACHE_WC:
+		err = _set_memory_wc(vaddr, nrpages);
+		break;
+	case _PAGE_CACHE_WB:
+		err = _set_memory_wb(vaddr, nrpages);
+		break;
+	}
+
+	return err;
+}
+
+int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
+			      unsigned long prot_val)
+{
+	unsigned long sz;
+	int rc;
+
+	for (sz = rc = 0; sz < size && !rc; ++mfn, sz += PAGE_SIZE) {
+		unsigned long pfn = mfn_to_local_pfn(mfn);
+
+		if (pfn >= max_low_pfn_mapped &&
+		    (pfn < (1UL<<(32 - PAGE_SHIFT)) || pfn >= max_pfn_mapped))
+			continue;
+		rc = ioremap_change_attr((unsigned long)__va(pfn << PAGE_SHIFT),
+					 PAGE_SIZE, prot_val);
+	}
+
+	return rc;
+}
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+static void __iomem *__ioremap_caller(resource_size_t phys_addr,
+		unsigned long size, unsigned long prot_val, void *caller)
+{
+	unsigned long mfn, offset, vaddr;
+	resource_size_t last_addr;
+	const resource_size_t unaligned_phys_addr = phys_addr;
+	const unsigned long unaligned_size = size;
+	struct vm_struct *area;
+	unsigned long new_prot_val;
+	pgprot_t prot;
+	int retval;
+	domid_t domid = DOMID_IO;
+	void __iomem *ret_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	if (!phys_addr_valid(phys_addr)) {
+		printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
+		       (unsigned long long)phys_addr);
+		WARN_ON_ONCE(1);
+		return NULL;
+	}
+
+	/*
+	 * Don't remap the low PCI/ISA area, it's always mapped..
+	 */
+	if (is_initial_xendomain() && is_ISA_range(phys_addr, last_addr))
+		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
+
+	/*
+	 * Check if the request spans more than any BAR in the iomem resource
+	 * tree.
+	 */
+	WARN_ONCE(iomem_map_sanity_check(phys_addr, size),
+		  KERN_INFO "Info: mapping multiple BARs. Your kernel is fine.");
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using..
+	 */
+	for (mfn = PFN_DOWN(phys_addr); mfn < PFN_UP(last_addr); mfn++) {
+		unsigned long pfn = mfn_to_local_pfn(mfn);
+
+		if (pfn_valid(pfn)) {
+			if (!PageReserved(pfn_to_page(pfn)))
+				return NULL;
+			domid = DOMID_SELF;
+		}
+	}
+	WARN_ON_ONCE(domid == DOMID_SELF);
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr+1) - phys_addr;
+
+	retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
+						prot_val, &new_prot_val);
+	if (retval) {
+		printk(KERN_ERR "ioremap reserve_memtype failed %d\n", retval);
+		return NULL;
+	}
+
+	if (prot_val != new_prot_val) {
+		if (!is_new_memtype_allowed(phys_addr, size,
+					    prot_val, new_prot_val)) {
+			printk(KERN_ERR
+		"ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
+				(unsigned long long)phys_addr,
+				(unsigned long long)(phys_addr + size),
+				prot_val, new_prot_val);
+			free_memtype(phys_addr, phys_addr + size);
+			return NULL;
+		}
+		prot_val = new_prot_val;
+	}
+
+	switch (prot_val) {
+	case _PAGE_CACHE_UC:
+	default:
+		prot = PAGE_KERNEL_IO_NOCACHE;
+		break;
+	case _PAGE_CACHE_UC_MINUS:
+		prot = PAGE_KERNEL_IO_UC_MINUS;
+		break;
+	case _PAGE_CACHE_WC:
+		prot = PAGE_KERNEL_IO_WC;
+		break;
+	case _PAGE_CACHE_WB:
+		prot = PAGE_KERNEL_IO;
+		break;
+	}
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+	if (!area)
+		return NULL;
+	area->phys_addr = phys_addr;
+	vaddr = (unsigned long) area->addr;
+
+	if (kernel_map_sync_memtype(phys_addr, size, prot_val)) {
+		free_memtype(phys_addr, phys_addr + size);
+		free_vm_area(area);
+		return NULL;
+	}
+
+	if (__direct_remap_pfn_range(&init_mm, vaddr, PFN_DOWN(phys_addr),
+				     size, prot, domid)) {
+		free_memtype(phys_addr, phys_addr + size);
+		free_vm_area(area);
+		return NULL;
+	}
+
+	ret_addr = (void __iomem *) (vaddr + offset);
+	mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
+
+	return ret_addr;
+}
+
+/**
+ * ioremap_nocache     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_nocache performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * This version of ioremap ensures that the memory is marked uncachable
+ * on the CPU as well as honouring existing caching rules from things like
+ * the PCI bus. Note that there are other caches and buffers on many
+ * busses. In particular driver authors should read up on PCI writes
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
+{
+	/*
+	 * Ideally, this should be:
+	 *	pat_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
+	 *
+	 * Till we fix all X drivers to use ioremap_wc(), we will use
+	 * UC MINUS.
+	 */
+	unsigned long val = _PAGE_CACHE_UC_MINUS;
+
+	return __ioremap_caller(phys_addr, size, val,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_nocache);
+
+/**
+ * ioremap_wc	-	map memory into CPU space write combined
+ * @offset:	bus address of the memory
+ * @size:	size of the resource to map
+ *
+ * This version of ioremap ensures that the memory is marked write combining.
+ * Write combining allows faster writes to some hardware devices.
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size)
+{
+	if (pat_enabled)
+		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
+					__builtin_return_address(0));
+	else
+		return ioremap_nocache(phys_addr, size);
+}
+EXPORT_SYMBOL(ioremap_wc);
+
+void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
+{
+	return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WB,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_cache);
+
+#ifndef CONFIG_XEN
+static void __iomem *ioremap_default(resource_size_t phys_addr,
+					unsigned long size)
+{
+	unsigned long flags;
+	void __iomem *ret;
+	int err;
+
+	/*
+	 * - WB for WB-able memory and no other conflicting mappings
+	 * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+	 * - Inherit from confliting mappings otherwise
+	 */
+	err = reserve_memtype(phys_addr, phys_addr + size,
+				_PAGE_CACHE_WB, &flags);
+	if (err < 0)
+		return NULL;
+
+	ret = __ioremap_caller(phys_addr, size, flags,
+			       __builtin_return_address(0));
+
+	free_memtype(phys_addr, phys_addr + size);
+	return ret;
+}
+#endif
+
+void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
+				unsigned long prot_val)
+{
+	return __ioremap_caller(phys_addr, size, (prot_val & _PAGE_CACHE_MASK),
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_prot);
+
+/**
+ * iounmap - Free a IO remapping
+ * @addr: virtual address from ioremap_*
+ *
+ * Caller must ensure there is only one unmapping for the same pointer.
+ */
+void iounmap(volatile void __iomem *addr)
+{
+	struct vm_struct *p, *o;
+
+	if ((void __force *)addr <= high_memory)
+		return;
+
+	/*
+	 * __ioremap special-cases the PCI/ISA range by not instantiating a
+	 * vm_area and by simply returning an address into the kernel mapping
+	 * of ISA space.   So handle that here.
+	 */
+	if ((unsigned long)addr >= fix_to_virt(FIX_ISAMAP_BEGIN))
+		return;
+
+	addr = (volatile void __iomem *)
+		(PAGE_MASK & (unsigned long __force)addr);
+
+	mmiotrace_iounmap(addr);
+
+	/* Use the vm area unlocked, assuming the caller
+	   ensures there isn't another iounmap for the same address
+	   in parallel. Reuse of the virtual address is prevented by
+	   leaving it in the global lists until we're done with it.
+	   cpa takes care of the direct mappings. */
+	read_lock(&vmlist_lock);
+	for (p = vmlist; p; p = p->next) {
+		if (p->addr == (void __force *)addr)
+			break;
+	}
+	read_unlock(&vmlist_lock);
+
+	if (!p) {
+		printk(KERN_ERR "iounmap: bad address %p\n", addr);
+		dump_stack();
+		return;
+	}
+
+	free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));
+
+	/* Finally remove it */
+	o = remove_vm_area((void __force *)addr);
+	BUG_ON(p != o || o == NULL);
+	kfree(p);
+}
+EXPORT_SYMBOL(iounmap);
+
+#ifndef CONFIG_XEN
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+void *xlate_dev_mem_ptr(unsigned long phys)
+{
+	void *addr;
+	unsigned long start = phys & PAGE_MASK;
+
+	/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
+	if (page_is_ram(start >> PAGE_SHIFT))
+		return __va(phys);
+
+	addr = (void __force *)ioremap_default(start, PAGE_SIZE);
+	if (addr)
+		addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+
+	return addr;
+}
+
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+{
+	if (page_is_ram(phys >> PAGE_SHIFT))
+		return;
+
+	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
+	return;
+}
+#endif
+
+static int __initdata early_ioremap_debug;
+
+static int __init early_ioremap_debug_setup(char *str)
+{
+	early_ioremap_debug = 1;
+
+	return 0;
+}
+early_param("early_ioremap_debug", early_ioremap_debug_setup);
+
+static __initdata int after_paging_init;
+static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
+
+#ifdef CONFIG_X86_32
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
+{
+	/* Don't assume we're using swapper_pg_dir at this point */
+	pgd_t *base = __va(read_cr3());
+	pgd_t *pgd = &base[pgd_index(addr)];
+	pud_t *pud = pud_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
+
+	return pmd;
+}
+#else
+#define early_ioremap_pmd early_get_pmd
+#undef make_lowmem_page_readonly
+#define make_lowmem_page_readonly early_make_page_readonly
+#endif
+
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
+{
+	return &bm_pte[pte_index(addr)];
+}
+
+static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata;
+
+void __init early_ioremap_init(void)
+{
+	pmd_t *pmd;
+	int i;
+
+	if (early_ioremap_debug)
+		printk(KERN_INFO "early_ioremap_init()\n");
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+		slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
+
+	pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+	memset(bm_pte, 0, sizeof(bm_pte));
+	make_lowmem_page_readonly(bm_pte, XENFEAT_writable_page_tables);
+	pmd_populate_kernel(&init_mm, pmd, bm_pte);
+
+	/*
+	 * The boot-ioremap range spans multiple pmds, for which
+	 * we are not prepared:
+	 */
+	if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+		WARN_ON(1);
+		printk(KERN_WARNING "pmd %p != %p\n",
+		       pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
+		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+			fix_to_virt(FIX_BTMAP_BEGIN));
+		printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+			fix_to_virt(FIX_BTMAP_END));
+
+		printk(KERN_WARNING "FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
+		printk(KERN_WARNING "FIX_BTMAP_BEGIN:     %d\n",
+		       FIX_BTMAP_BEGIN);
+	}
+}
+
+void __init early_ioremap_reset(void)
+{
+	after_paging_init = 1;
+}
+
+static void __init __early_set_fixmap(enum fixed_addresses idx,
+				      phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long addr = __fix_to_virt(idx);
+	pte_t *pte;
+
+	if (idx >= __end_of_fixed_addresses) {
+		BUG();
+		return;
+	}
+	pte = early_ioremap_pte(addr);
+
+	if (pgprot_val(flags))
+		set_pte(pte, pfn_pte_ma(phys >> PAGE_SHIFT, flags));
+	else
+		pte_clear(&init_mm, addr, pte);
+	__flush_tlb_one(addr);
+}
+
+static inline void __init early_set_fixmap(enum fixed_addresses idx,
+					   phys_addr_t phys, pgprot_t prot)
+{
+	if (after_paging_init)
+		__set_fixmap(idx, phys, prot);
+	else
+		__early_set_fixmap(idx, phys, prot);
+}
+
+static inline void __init early_clear_fixmap(enum fixed_addresses idx)
+{
+	if (after_paging_init)
+		clear_fixmap(idx);
+	else
+		__early_set_fixmap(idx, 0, __pgprot(0));
+}
+
+static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
+static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
+
+static int __init check_early_ioremap_leak(void)
+{
+	int count = 0;
+	int i;
+
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
+		if (prev_map[i])
+			count++;
+
+	if (!count)
+		return 0;
+	WARN(1, KERN_WARNING
+	       "Debug warning: early ioremap leak of %d areas detected.\n",
+		count);
+	printk(KERN_WARNING
+		"please boot with early_ioremap_debug and report the dmesg.\n");
+
+	return 1;
+}
+late_initcall(check_early_ioremap_leak);
+
+static void __init __iomem *
+__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	unsigned long offset;
+	resource_size_t last_addr;
+	unsigned int nrpages;
+	enum fixed_addresses idx0, idx;
+	int i, slot;
+
+	WARN_ON(system_state != SYSTEM_BOOTING);
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (!prev_map[i]) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		printk(KERN_INFO "early_iomap(%08llx, %08lx) not found slot\n",
+			 (u64)phys_addr, size);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	if (early_ioremap_debug) {
+		printk(KERN_INFO "early_ioremap(%08llx, %08lx) [%d] => ",
+		       (u64)phys_addr, size, slot);
+		dump_stack();
+	}
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	prev_size[slot] = size;
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Mappings have to fit in the FIX_BTMAP area.
+	 */
+	nrpages = size >> PAGE_SHIFT;
+	if (nrpages > NR_FIX_BTMAPS) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/*
+	 * Ok, go for it..
+	 */
+	idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+	idx = idx0;
+	while (nrpages > 0) {
+		early_set_fixmap(idx, phys_addr, prot);
+		phys_addr += PAGE_SIZE;
+		--idx;
+		--nrpages;
+	}
+	if (early_ioremap_debug)
+		printk(KERN_CONT "%08lx + %08lx\n", offset, slot_virt[slot]);
+
+	prev_map[slot] = (void __iomem *)(offset + slot_virt[slot]);
+	return prev_map[slot];
+}
+
+/* Remap an IO device */
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
+{
+	/*
+	 * Don't remap the low PCI/ISA area, it's always mapped.
+	 */
+	if (is_initial_xendomain() && is_ISA_range(phys_addr, phys_addr + size - 1))
+		return (__force void __iomem *)isa_bus_to_virt((unsigned long)phys_addr);
+
+	return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
+}
+
+/* Remap memory */
+void __init __iomem *
+early_memremap(resource_size_t phys_addr, unsigned long size)
+{
+	return __early_ioremap(phys_to_machine(phys_addr), size, PAGE_KERNEL);
+}
+
+void __init early_iounmap(void __iomem *addr, unsigned long size)
+{
+	unsigned long virt_addr;
+	unsigned long offset;
+	unsigned int nrpages;
+	enum fixed_addresses idx;
+	int i, slot;
+
+	/*
+	 * early_ioremap special-cases the PCI/ISA range by not instantiating a
+	 * vm_area and by simply returning an address into the kernel mapping
+	 * of ISA space.   So handle that here.
+	 */
+	if ((unsigned long)addr >= fix_to_virt(FIX_ISAMAP_BEGIN)
+	    && (unsigned long)addr < fix_to_virt(FIX_ISAMAP_END - 1))
+		return;
+
+	slot = -1;
+	for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+		if (prev_map[i] == addr) {
+			slot = i;
+			break;
+		}
+	}
+
+	if (slot < 0) {
+		printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n",
+			 addr, size);
+		WARN_ON(1);
+		return;
+	}
+
+	if (prev_size[slot] != size) {
+		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n",
+			 addr, size, slot, prev_size[slot]);
+		WARN_ON(1);
+		return;
+	}
+
+	if (early_ioremap_debug) {
+		printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr,
+		       size, slot);
+		dump_stack();
+	}
+
+	virt_addr = (unsigned long)addr;
+	if (virt_addr < fix_to_virt(FIX_BTMAP_BEGIN)) {
+		WARN_ON(1);
+		return;
+	}
+	offset = virt_addr & ~PAGE_MASK;
+	nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT;
+
+	idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot;
+	while (nrpages > 0) {
+		early_clear_fixmap(idx);
+		--idx;
+		--nrpages;
+	}
+	prev_map[slot] = NULL;
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/physaddr.c
+++ linux-ec2-2.6.32/arch/x86/mm/physaddr.c
@@ -8,6 +8,10 @@
 
 #ifdef CONFIG_X86_64
 
+#ifdef CONFIG_XEN
+#define phys_base 0
+#endif
+
 unsigned long __phys_addr(unsigned long x)
 {
 	if (x >= __START_KERNEL_map) {
--- linux-ec2-2.6.32.orig/arch/x86/mm/tlb.c
+++ linux-ec2-2.6.32/arch/x86/mm/tlb.c
@@ -6,6 +6,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 
+#include <asm/desc.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 #include <asm/apic.h>
@@ -130,6 +131,10 @@
 	union smp_flush_state *f;
 
 	cpu = smp_processor_id();
+#ifdef CONFIG_X86_32
+	if (current->active_mm)
+                load_user_cs_desc(cpu, current->active_mm);
+#endif
 	/*
 	 * orig_rax contains the negated interrupt vector.
 	 * Use that to determine where the sender put the data.
--- linux-ec2-2.6.32.orig/arch/x86/mm/pgtable_32-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/pgtable_32-xen.c
@@ -0,0 +1,180 @@
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/nmi.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/quicklist.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/fixmap.h>
+#include <asm/e820.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+
+#include <xen/features.h>
+#include <asm/hypervisor.h>
+
+unsigned int __VMALLOC_RESERVE = 128 << 20;
+
+/*
+ * Associate a virtual page frame with a given physical page frame
+ * and protection flags for that frame.
+ */
+void set_pte_vaddr(unsigned long vaddr, pte_t pteval)
+{
+#ifndef CONFIG_XEN
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	if (pgd_none(*pgd)) {
+		BUG();
+		return;
+	}
+	pud = pud_offset(pgd, vaddr);
+	if (pud_none(*pud)) {
+		BUG();
+		return;
+	}
+	pmd = pmd_offset(pud, vaddr);
+	if (pmd_none(*pmd)) {
+		BUG();
+		return;
+	}
+	pte = pte_offset_kernel(pmd, vaddr);
+	if (pte_val(pteval))
+		set_pte_at(&init_mm, vaddr, pte, pteval);
+	else
+		pte_clear(&init_mm, vaddr, pte);
+
+	/*
+	 * It's enough to flush this one mapping.
+	 * (PGE mappings get flushed as well)
+	 */
+	__flush_tlb_one(vaddr);
+#else
+	if (HYPERVISOR_update_va_mapping(vaddr, pteval,
+					 UVMF_INVLPG|UVMF_ALL))
+		BUG();
+#endif
+}
+
+/*
+ * Associate a large virtual page frame with a given physical page frame 
+ * and protection flags for that frame. pfn is for the base of the page,
+ * vaddr is what the page gets mapped to - both must be properly aligned. 
+ * The pmd must already be instantiated. Assumes PAE mode.
+ */ 
+void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	if (vaddr & (PMD_SIZE-1)) {		/* vaddr is misaligned */
+		printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n");
+		return; /* BUG(); */
+	}
+	if (pfn & (PTRS_PER_PTE-1)) {		/* pfn is misaligned */
+		printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n");
+		return; /* BUG(); */
+	}
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	if (pgd_none(*pgd)) {
+		printk(KERN_WARNING "set_pmd_pfn: pgd_none\n");
+		return; /* BUG(); */
+	}
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
+	set_pmd(pmd, pfn_pmd(pfn, flags));
+	/*
+	 * It's enough to flush this one mapping.
+	 * (PGE mappings get flushed as well)
+	 */
+	__flush_tlb_one(vaddr);
+}
+
+unsigned long hypervisor_virt_start = HYPERVISOR_VIRT_START;
+unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - PAGE_SIZE);
+EXPORT_SYMBOL(__FIXADDR_TOP);
+
+/*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the
+ * vmalloc area - the default is 128m.
+ */
+static int __init parse_vmalloc(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	/* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/
+	__VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET;
+	return 0;
+}
+early_param("vmalloc", parse_vmalloc);
+
+#ifndef CONFIG_XEN
+/*
+ * reservetop=size reserves a hole at the top of the kernel address space which
+ * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
+ * so relocating the fixmap can be done before paging initialization.
+ */
+static int __init parse_reservetop(char *arg)
+{
+	unsigned long address;
+
+	if (!arg)
+		return -EINVAL;
+
+	address = memparse(arg, &arg);
+	reserve_top_address(address);
+	return 0;
+}
+early_param("reservetop", parse_reservetop);
+#endif
+
+void make_lowmem_page_readonly(void *va, unsigned int feature)
+{
+	pte_t *pte;
+	unsigned int level;
+	int rc;
+
+	if (xen_feature(feature))
+		return;
+
+	pte = lookup_address((unsigned long)va, &level);
+	BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte));
+	rc = HYPERVISOR_update_va_mapping(
+		(unsigned long)va, pte_wrprotect(*pte), 0);
+	BUG_ON(rc);
+}
+
+void make_lowmem_page_writable(void *va, unsigned int feature)
+{
+	pte_t *pte;
+	unsigned int level;
+	int rc;
+
+	if (xen_feature(feature))
+		return;
+
+	pte = lookup_address((unsigned long)va, &level);
+	BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte));
+	rc = HYPERVISOR_update_va_mapping(
+		(unsigned long)va, pte_mkwrite(*pte), UVMF_INVLPG);
+	BUG_ON(rc);
+}
--- linux-ec2-2.6.32.orig/arch/x86/mm/pgtable.c
+++ linux-ec2-2.6.32/arch/x86/mm/pgtable.c
@@ -6,6 +6,14 @@
 
 #define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
 
+#ifdef CONFIG_HIGHPTE
+#define PGALLOC_USER_GFP __GFP_HIGHMEM
+#else
+#define PGALLOC_USER_GFP 0
+#endif
+
+gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP;
+
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
 	return (pte_t *)__get_free_page(PGALLOC_GFP);
@@ -15,16 +23,29 @@
 {
 	struct page *pte;
 
-#ifdef CONFIG_HIGHPTE
-	pte = alloc_pages(PGALLOC_GFP | __GFP_HIGHMEM, 0);
-#else
-	pte = alloc_pages(PGALLOC_GFP, 0);
-#endif
+	pte = alloc_pages(__userpte_alloc_gfp, 0);
 	if (pte)
 		pgtable_page_ctor(pte);
 	return pte;
 }
 
+static int __init setup_userpte(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	/*
+	 * "userpte=nohigh" disables allocation of user pagetables in
+	 * high memory.
+	 */
+	if (strcmp(arg, "nohigh") == 0)
+		__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+	else
+		return -EINVAL;
+	return 0;
+}
+early_param("userpte", setup_userpte);
+
 void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 {
 	pgtable_page_dtor(pte);
--- linux-ec2-2.6.32.orig/arch/x86/mm/pageattr-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/pageattr-xen.c
@@ -0,0 +1,1451 @@
+/*
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ * Thanks to Ben LaHaise for precious feedback.
+ */
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/pfn.h>
+#include <linux/percpu.h>
+
+#include <asm/e820.h>
+#include <asm/processor.h>
+#include <asm/tlbflush.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/proto.h>
+#include <asm/pat.h>
+
+/*
+ * The current flushing context - we pass it instead of 5 arguments:
+ */
+struct cpa_data {
+	unsigned long	*vaddr;
+	pgprot_t	mask_set;
+	pgprot_t	mask_clr;
+	int		numpages;
+	int		flags;
+	unsigned long	pfn;
+	unsigned	force_split : 1;
+	int		curpage;
+	struct page	**pages;
+};
+
+/*
+ * Serialize cpa() (for !DEBUG_PAGEALLOC which uses large identity mappings)
+ * using cpa_lock. So that we don't allow any other cpu, with stale large tlb
+ * entries change the page attribute in parallel to some other cpu
+ * splitting a large page entry along with changing the attribute.
+ */
+static DEFINE_SPINLOCK(cpa_lock);
+
+#define CPA_FLUSHTLB 1
+#define CPA_ARRAY 2
+#define CPA_PAGES_ARRAY 4
+
+#ifdef CONFIG_PROC_FS
+static unsigned long direct_pages_count[PG_LEVEL_NUM];
+
+void update_page_count(int level, unsigned long pages)
+{
+	unsigned long flags;
+
+	/* Protect against CPA */
+	spin_lock_irqsave(&pgd_lock, flags);
+	direct_pages_count[level] += pages;
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+static void split_page_count(int level)
+{
+	direct_pages_count[level]--;
+	direct_pages_count[level - 1] += PTRS_PER_PTE;
+}
+
+void arch_report_meminfo(struct seq_file *m)
+{
+	seq_printf(m, "DirectMap4k:    %8lu kB\n",
+			direct_pages_count[PG_LEVEL_4K] << 2);
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+	seq_printf(m, "DirectMap2M:    %8lu kB\n",
+			direct_pages_count[PG_LEVEL_2M] << 11);
+#else
+	seq_printf(m, "DirectMap4M:    %8lu kB\n",
+			direct_pages_count[PG_LEVEL_2M] << 12);
+#endif
+#ifdef CONFIG_X86_64
+	if (direct_gbpages)
+		seq_printf(m, "DirectMap1G:    %8lu kB\n",
+			direct_pages_count[PG_LEVEL_1G] << 20);
+#endif
+}
+#else
+static inline void split_page_count(int level) { }
+#endif
+
+#ifdef CONFIG_X86_64
+
+static inline unsigned long highmap_start_pfn(void)
+{
+	return __pa(_text) >> PAGE_SHIFT;
+}
+
+static inline unsigned long highmap_end_pfn(void)
+{
+	return __pa(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT;
+}
+
+#endif
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+# define debug_pagealloc 1
+#else
+# define debug_pagealloc 0
+#endif
+
+static inline int
+within(unsigned long addr, unsigned long start, unsigned long end)
+{
+	return addr >= start && addr < end;
+}
+
+/*
+ * Flushing functions
+ */
+
+/**
+ * clflush_cache_range - flush a cache range with clflush
+ * @addr:	virtual start address
+ * @size:	number of bytes to flush
+ *
+ * clflush is an unordered instruction which needs fencing with mfence
+ * to avoid ordering issues.
+ */
+void clflush_cache_range(void *vaddr, unsigned int size)
+{
+	void *vend = vaddr + size - 1;
+
+	mb();
+
+	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
+		clflush(vaddr);
+	/*
+	 * Flush any possible final partial cacheline:
+	 */
+	clflush(vend);
+
+	mb();
+}
+EXPORT_SYMBOL_GPL(clflush_cache_range);
+
+static void __cpa_flush_all(void *arg)
+{
+	unsigned long cache = (unsigned long)arg;
+
+	/*
+	 * Flush all to work around Errata in early athlons regarding
+	 * large page flushing.
+	 */
+	__flush_tlb_all();
+
+	if (cache && boot_cpu_data.x86 >= 4)
+		wbinvd();
+}
+
+static void cpa_flush_all(unsigned long cache)
+{
+	BUG_ON(irqs_disabled());
+
+	on_each_cpu(__cpa_flush_all, (void *) cache, 1);
+}
+
+static void __cpa_flush_range(void *arg)
+{
+	/*
+	 * We could optimize that further and do individual per page
+	 * tlb invalidates for a low number of pages. Caveat: we must
+	 * flush the high aliases on 64bit as well.
+	 */
+	__flush_tlb_all();
+}
+
+static void cpa_flush_range(unsigned long start, int numpages, int cache)
+{
+	unsigned int i, level;
+	unsigned long addr;
+
+	BUG_ON(irqs_disabled());
+	WARN_ON(PAGE_ALIGN(start) != start);
+
+	on_each_cpu(__cpa_flush_range, NULL, 1);
+
+	if (!cache)
+		return;
+
+	/*
+	 * We only need to flush on one CPU,
+	 * clflush is a MESI-coherent instruction that
+	 * will cause all other CPUs to flush the same
+	 * cachelines:
+	 */
+	for (i = 0, addr = start; i < numpages; i++, addr += PAGE_SIZE) {
+		pte_t *pte = lookup_address(addr, &level);
+
+		/*
+		 * Only flush present addresses:
+		 */
+		if (pte && (__pte_val(*pte) & _PAGE_PRESENT))
+			clflush_cache_range((void *) addr, PAGE_SIZE);
+	}
+}
+
+static void cpa_flush_array(unsigned long *start, int numpages, int cache,
+			    int in_flags, struct page **pages)
+{
+	unsigned int i, level;
+	unsigned long do_wbinvd = cache && numpages >= 1024; /* 4M threshold */
+
+	BUG_ON(irqs_disabled());
+
+	on_each_cpu(__cpa_flush_all, (void *) do_wbinvd, 1);
+
+	if (!cache || do_wbinvd)
+		return;
+
+	/*
+	 * We only need to flush on one CPU,
+	 * clflush is a MESI-coherent instruction that
+	 * will cause all other CPUs to flush the same
+	 * cachelines:
+	 */
+	for (i = 0; i < numpages; i++) {
+		unsigned long addr;
+		pte_t *pte;
+
+		if (in_flags & CPA_PAGES_ARRAY)
+			addr = (unsigned long)page_address(pages[i]);
+		else
+			addr = start[i];
+
+		pte = lookup_address(addr, &level);
+
+		/*
+		 * Only flush present addresses:
+		 */
+		if (pte && (__pte_val(*pte) & _PAGE_PRESENT))
+			clflush_cache_range((void *)addr, PAGE_SIZE);
+	}
+}
+
+/*
+ * Certain areas of memory on x86 require very specific protection flags,
+ * for example the BIOS area or kernel text. Callers don't always get this
+ * right (again, ioremap() on BIOS memory is not uncommon) so this function
+ * checks and fixes these known static required protection bits.
+ */
+static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
+				   unsigned long pfn)
+{
+	pgprot_t forbidden = __pgprot(0);
+
+#ifndef CONFIG_XEN
+	/*
+	 * The BIOS area between 640k and 1Mb needs to be executable for
+	 * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
+	 */
+	if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
+		pgprot_val(forbidden) |= _PAGE_NX;
+#endif
+
+	/*
+	 * The kernel text needs to be executable for obvious reasons
+	 * Does not cover __inittext since that is gone later on. On
+	 * 64bit we do not enforce !NX on the low mapping
+	 */
+	if (within(address, (unsigned long)_text, (unsigned long)_etext))
+		pgprot_val(forbidden) |= _PAGE_NX;
+
+	/*
+	 * The .rodata section needs to be read-only. Using the pfn
+	 * catches all aliases.
+	 */
+	if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
+		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
+		pgprot_val(forbidden) |= _PAGE_RW;
+
+	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+
+	return prot;
+}
+
+/*
+ * Lookup the page table entry for a virtual address. Return a pointer
+ * to the entry and the level of the mapping.
+ *
+ * Note: We return pud and pmd either when the entry is marked large
+ * or when the present bit is not set. Otherwise we would return a
+ * pointer to a nonexisting mapping.
+ */
+pte_t *lookup_address(unsigned long address, unsigned int *level)
+{
+	pgd_t *pgd = pgd_offset_k(address);
+	pud_t *pud;
+	pmd_t *pmd;
+
+	*level = PG_LEVEL_NONE;
+
+	if (pgd_none(*pgd))
+		return NULL;
+
+	pud = pud_offset(pgd, address);
+	if (pud_none(*pud))
+		return NULL;
+
+	*level = PG_LEVEL_1G;
+	if (pud_large(*pud) || !pud_present(*pud))
+		return (pte_t *)pud;
+
+	pmd = pmd_offset(pud, address);
+	if (pmd_none(*pmd))
+		return NULL;
+
+	*level = PG_LEVEL_2M;
+	if (pmd_large(*pmd) || !pmd_present(*pmd))
+		return (pte_t *)pmd;
+
+	*level = PG_LEVEL_4K;
+
+	return pte_offset_kernel(pmd, address);
+}
+EXPORT_SYMBOL_GPL(lookup_address);
+
+/*
+ * Set the new pmd in all the pgds we know about:
+ */
+static void __set_pmd_pte(pte_t *kpte, unsigned long address,
+			  unsigned int level, pte_t pte)
+{
+	/* change init_mm */
+	switch(level) {
+	case PG_LEVEL_2M:
+		xen_l2_entry_update((pmd_t *)kpte, __pmd_ma(__pte_val(pte)));
+		break;
+#ifdef CONFIG_X86_64
+	case PG_LEVEL_1G:
+		xen_l3_entry_update((pud_t *)kpte, __pud_ma(__pte_val(pte)));
+		break;
+#endif
+	default:
+		BUG();
+	}
+#ifdef CONFIG_X86_32
+	if (!SHARED_KERNEL_PMD) {
+		struct page *page;
+
+		list_for_each_entry(page, &pgd_list, lru) {
+			pgd_t *pgd;
+			pud_t *pud;
+			pmd_t *pmd;
+
+			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+			pud = pud_offset(pgd, address);
+			pmd = pmd_offset(pud, address);
+			xen_l2_entry_update(pmd, __pmd_ma(__pte_val(pte)));
+		}
+	}
+#endif
+}
+
+static int
+try_preserve_large_page(pte_t *kpte, unsigned long address,
+			struct cpa_data *cpa)
+{
+	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
+	pte_t new_pte, old_pte, *tmp;
+	pgprot_t old_prot, new_prot;
+	int i, do_split = 1;
+	unsigned int level;
+
+	if (cpa->force_split)
+		return 1;
+
+	spin_lock_irqsave(&pgd_lock, flags);
+	/*
+	 * Check for races, another CPU might have split this page
+	 * up already:
+	 */
+	tmp = lookup_address(address, &level);
+	if (tmp != kpte)
+		goto out_unlock;
+
+	switch (level) {
+	case PG_LEVEL_2M:
+		psize = PMD_PAGE_SIZE;
+		pmask = PMD_PAGE_MASK;
+		break;
+#ifdef CONFIG_X86_64
+	case PG_LEVEL_1G:
+		psize = PUD_PAGE_SIZE;
+		pmask = PUD_PAGE_MASK;
+		break;
+#endif
+	default:
+		do_split = -EINVAL;
+		goto out_unlock;
+	}
+
+	/*
+	 * Calculate the number of pages, which fit into this large
+	 * page starting at address:
+	 */
+	nextpage_addr = (address + psize) & pmask;
+	numpages = (nextpage_addr - address) >> PAGE_SHIFT;
+	if (numpages < cpa->numpages)
+		cpa->numpages = numpages;
+
+	/*
+	 * We are safe now. Check whether the new pgprot is the same:
+	 */
+	old_pte = *kpte;
+	old_prot = new_prot = pte_pgprot(old_pte);
+
+	pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
+	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
+
+	/*
+	 * old_pte points to the large page base address. So we need
+	 * to add the offset of the virtual address:
+	 */
+	pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT);
+	cpa->pfn = pfn;
+
+	new_prot = static_protections(new_prot, address, pfn);
+
+	/*
+	 * We need to check the full range, whether
+	 * static_protection() requires a different pgprot for one of
+	 * the pages in the range we try to preserve:
+	 */
+	if (pfn < max_mapnr) {
+		addr = address + PAGE_SIZE;
+		for (i = 1; i < cpa->numpages && ++pfn < max_mapnr;
+		     i++, addr += PAGE_SIZE) {
+			pgprot_t chk_prot = static_protections(new_prot, addr, pfn);
+
+			if (pgprot_val(chk_prot) != pgprot_val(new_prot))
+				goto out_unlock;
+		}
+	}
+
+	/*
+	 * If there are no changes, return. maxpages has been updated
+	 * above:
+	 */
+	if (pgprot_val(new_prot) == pgprot_val(old_prot)) {
+		do_split = 0;
+		goto out_unlock;
+	}
+
+	/*
+	 * We need to change the attributes. Check, whether we can
+	 * change the large page in one go. We request a split, when
+	 * the address is not aligned and the number of pages is
+	 * smaller than the number of pages in the large page. Note
+	 * that we limited the number of possible pages already to
+	 * the number of pages in the large page.
+	 */
+	if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
+		/*
+		 * The address is aligned and the number of pages
+		 * covers the full page.
+		 */
+		new_pte = pfn_pte_ma(__pte_mfn(old_pte), canon_pgprot(new_prot));
+		__set_pmd_pte(kpte, address, level, new_pte);
+		cpa->flags |= CPA_FLUSHTLB;
+		do_split = 0;
+	}
+
+out_unlock:
+	spin_unlock_irqrestore(&pgd_lock, flags);
+
+	return do_split;
+}
+
+static int split_large_page(pte_t *kpte, unsigned long address)
+{
+	unsigned long flags, mfn, mfninc = 1;
+	unsigned int i, level;
+	pte_t *pbase, *tmp;
+	pgprot_t ref_prot;
+	struct page *base;
+
+	if (!debug_pagealloc)
+		spin_unlock(&cpa_lock);
+	base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
+	if (!debug_pagealloc)
+		spin_lock(&cpa_lock);
+	if (!base)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&pgd_lock, flags);
+	/*
+	 * Check for races, another CPU might have split this page
+	 * up for us already:
+	 */
+	tmp = lookup_address(address, &level);
+	if (tmp != kpte)
+		goto out_unlock;
+
+	pbase = (pte_t *)page_address(base);
+	paravirt_alloc_pte(&init_mm, page_to_pfn(base));
+	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
+	/*
+	 * If we ever want to utilize the PAT bit, we need to
+	 * update this function to make sure it's converted from
+	 * bit 12 to bit 7 when we cross from the 2MB level to
+	 * the 4K level:
+	 */
+	WARN_ON_ONCE(pgprot_val(ref_prot) & _PAGE_PAT_LARGE);
+
+#ifdef CONFIG_X86_64
+	if (level == PG_LEVEL_1G) {
+		mfninc = PMD_PAGE_SIZE >> PAGE_SHIFT;
+		pgprot_val(ref_prot) |= _PAGE_PSE;
+	}
+#endif
+
+	if (address >= (unsigned long)__va(0) &&
+		address < (unsigned long)__va(max_low_pfn_mapped << PAGE_SHIFT))
+		split_page_count(level);
+
+#ifdef CONFIG_X86_64
+	if (address >= (unsigned long)__va(1UL<<32) &&
+		address < (unsigned long)__va(max_pfn_mapped << PAGE_SHIFT))
+		split_page_count(level);
+#endif
+
+	/*
+	 * Get the target mfn from the original entry:
+	 */
+	mfn = __pte_mfn(*kpte);
+	for (i = 0; i < PTRS_PER_PTE; i++, mfn += mfninc)
+		set_pte(&pbase[i], pfn_pte_ma(mfn, ref_prot));
+
+	/*
+	 * Install the new, split up pagetable.
+	 *
+	 * We use the standard kernel pagetable protections for the new
+	 * pagetable protections, the actual ptes set above control the
+	 * primary protection behavior:
+	 */
+	if (!xen_feature(XENFEAT_writable_page_tables) &&
+	    HYPERVISOR_update_va_mapping((unsigned long)pbase,
+					 mk_pte(base, PAGE_KERNEL_RO), 0))
+		BUG();
+	__set_pmd_pte(kpte, address, level, mk_pte(base, __pgprot(_KERNPG_TABLE)));
+
+	/*
+	 * Intel Atom errata AAH41 workaround.
+	 *
+	 * The real fix should be in hw or in a microcode update, but
+	 * we also probabilistically try to reduce the window of having
+	 * a large TLB mixed with 4K TLBs while instruction fetches are
+	 * going on.
+	 */
+	__flush_tlb_all();
+
+	base = NULL;
+
+out_unlock:
+	/*
+	 * If we dropped out via the lookup_address check under
+	 * pgd_lock then stick the page back into the pool:
+	 */
+	if (base)
+		__free_page(base);
+	spin_unlock_irqrestore(&pgd_lock, flags);
+
+	return 0;
+}
+
+static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
+			       int primary)
+{
+	/*
+	 * Ignore all non primary paths.
+	 */
+	if (!primary)
+		return 0;
+
+	/*
+	 * Ignore the NULL PTE for kernel identity mapping, as it is expected
+	 * to have holes.
+	 * Also set numpages to '1' indicating that we processed cpa req for
+	 * one virtual address page and its pfn. TBD: numpages can be set based
+	 * on the initial value and the level returned by lookup_address().
+	 */
+	if (within(vaddr, PAGE_OFFSET,
+		   PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
+		cpa->numpages = 1;
+		cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
+		return 0;
+	} else {
+		WARN(1, KERN_WARNING "CPA: called for zero pte. "
+			"vaddr = %lx cpa->vaddr = %lx\n", vaddr,
+			*cpa->vaddr);
+
+		return -EFAULT;
+	}
+}
+
+static int __change_page_attr(struct cpa_data *cpa, int primary)
+{
+	unsigned long address;
+	int do_split, err;
+	unsigned int level;
+	pte_t *kpte, old_pte;
+
+	if (cpa->flags & CPA_PAGES_ARRAY) {
+		struct page *page = cpa->pages[cpa->curpage];
+		if (unlikely(PageHighMem(page)))
+			return 0;
+		address = (unsigned long)page_address(page);
+	} else if (cpa->flags & CPA_ARRAY)
+		address = cpa->vaddr[cpa->curpage];
+	else
+		address = *cpa->vaddr;
+repeat:
+	kpte = lookup_address(address, &level);
+	if (!kpte)
+		return __cpa_process_fault(cpa, address, primary);
+
+	old_pte = *kpte;
+	if (!__pte_val(old_pte))
+		return __cpa_process_fault(cpa, address, primary);
+
+	if (level == PG_LEVEL_4K) {
+		pte_t new_pte;
+		pgprot_t new_prot = pte_pgprot(old_pte);
+		unsigned long mfn = __pte_mfn(old_pte);
+
+		pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
+		pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
+
+		new_prot = static_protections(new_prot, address,
+					      mfn_to_local_pfn(mfn));
+
+		/*
+		 * We need to keep the mfn from the existing PTE,
+		 * after all we're only going to change it's attributes
+		 * not the memory it points to
+		 */
+		new_pte = pfn_pte_ma(mfn, canon_pgprot(new_prot));
+		cpa->pfn = mfn_to_local_pfn(mfn);
+		/*
+		 * Do we really change anything ?
+		 */
+		if (__pte_val(old_pte) != __pte_val(new_pte)) {
+			set_pte_atomic(kpte, new_pte);
+			cpa->flags |= CPA_FLUSHTLB;
+		}
+		cpa->numpages = 1;
+		return 0;
+	}
+
+	/*
+	 * Check, whether we can keep the large page intact
+	 * and just change the pte:
+	 */
+	do_split = try_preserve_large_page(kpte, address, cpa);
+	/*
+	 * When the range fits into the existing large page,
+	 * return. cp->numpages and cpa->tlbflush have been updated in
+	 * try_large_page:
+	 */
+	if (do_split <= 0)
+		return do_split;
+
+	/*
+	 * We have to split the large page:
+	 */
+	err = split_large_page(kpte, address);
+	if (!err) {
+		/*
+	 	 * Do a global flush tlb after splitting the large page
+	 	 * and before we do the actual change page attribute in the PTE.
+	 	 *
+	 	 * With out this, we violate the TLB application note, that says
+	 	 * "The TLBs may contain both ordinary and large-page
+		 *  translations for a 4-KByte range of linear addresses. This
+		 *  may occur if software modifies the paging structures so that
+		 *  the page size used for the address range changes. If the two
+		 *  translations differ with respect to page frame or attributes
+		 *  (e.g., permissions), processor behavior is undefined and may
+		 *  be implementation-specific."
+	 	 *
+	 	 * We do this global tlb flush inside the cpa_lock, so that we
+		 * don't allow any other cpu, with stale tlb entries change the
+		 * page attribute in parallel, that also falls into the
+		 * just split large page entry.
+	 	 */
+		flush_tlb_all();
+		goto repeat;
+	}
+
+	return err;
+}
+
+static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias);
+
+static int cpa_process_alias(struct cpa_data *cpa)
+{
+	struct cpa_data alias_cpa;
+	unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
+	unsigned long vaddr;
+	int ret;
+
+	if (cpa->pfn >= max_pfn_mapped)
+		return 0;
+
+#ifdef CONFIG_X86_64
+	if (cpa->pfn >= max_low_pfn_mapped && cpa->pfn < (1UL<<(32-PAGE_SHIFT)))
+		return 0;
+#endif
+	/*
+	 * No need to redo, when the primary call touched the direct
+	 * mapping already:
+	 */
+	if (cpa->flags & CPA_PAGES_ARRAY) {
+		struct page *page = cpa->pages[cpa->curpage];
+		if (unlikely(PageHighMem(page)))
+			return 0;
+		vaddr = (unsigned long)page_address(page);
+	} else if (cpa->flags & CPA_ARRAY)
+		vaddr = cpa->vaddr[cpa->curpage];
+	else
+		vaddr = *cpa->vaddr;
+
+	if (!(within(vaddr, PAGE_OFFSET,
+		    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
+
+		alias_cpa = *cpa;
+		alias_cpa.vaddr = &laddr;
+		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+
+		ret = __change_page_attr_set_clr(&alias_cpa, 0);
+		if (ret)
+			return ret;
+	}
+
+#ifdef CONFIG_X86_64
+	/*
+	 * If the primary call didn't touch the high mapping already
+	 * and the physical address is inside the kernel map, we need
+	 * to touch the high mapped kernel as well:
+	 */
+	if (!within(vaddr, (unsigned long)_text, _brk_end) &&
+	    within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
+		unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
+					       __START_KERNEL_map;
+		alias_cpa = *cpa;
+		alias_cpa.vaddr = &temp_cpa_vaddr;
+		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+
+		/*
+		 * The high mapping range is imprecise, so ignore the
+		 * return value.
+		 */
+		__change_page_attr_set_clr(&alias_cpa, 0);
+	}
+#endif
+
+	return 0;
+}
+
+static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
+{
+	int ret, numpages = cpa->numpages;
+
+	while (numpages) {
+		/*
+		 * Store the remaining nr of pages for the large page
+		 * preservation check.
+		 */
+		cpa->numpages = numpages;
+		/* for array changes, we can't use large page */
+		if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
+			cpa->numpages = 1;
+
+		if (!debug_pagealloc)
+			spin_lock(&cpa_lock);
+		ret = __change_page_attr(cpa, checkalias);
+		if (!debug_pagealloc)
+			spin_unlock(&cpa_lock);
+		if (ret)
+			return ret;
+
+		if (checkalias) {
+			ret = cpa_process_alias(cpa);
+			if (ret)
+				return ret;
+		}
+
+		/*
+		 * Adjust the number of pages with the result of the
+		 * CPA operation. Either a large page has been
+		 * preserved or a single page update happened.
+		 */
+		BUG_ON(cpa->numpages > numpages);
+		numpages -= cpa->numpages;
+		if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
+			cpa->curpage++;
+		else
+			*cpa->vaddr += cpa->numpages * PAGE_SIZE;
+
+	}
+	return 0;
+}
+
+static inline int cache_attr(pgprot_t attr)
+{
+	return pgprot_val(attr) &
+		(_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
+}
+
+static int change_page_attr_set_clr(unsigned long *addr, int numpages,
+				    pgprot_t mask_set, pgprot_t mask_clr,
+				    int force_split, int in_flag,
+				    struct page **pages)
+{
+	struct cpa_data cpa;
+	int ret, cache, checkalias;
+	unsigned long baddr = 0;
+
+	/*
+	 * Check, if we are requested to change a not supported
+	 * feature:
+	 */
+	mask_set = canon_pgprot(mask_set);
+	mask_clr = canon_pgprot(mask_clr);
+	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr) && !force_split)
+		return 0;
+
+	/* Ensure we are PAGE_SIZE aligned */
+	if (in_flag & CPA_ARRAY) {
+		int i;
+		for (i = 0; i < numpages; i++) {
+			if (addr[i] & ~PAGE_MASK) {
+				addr[i] &= PAGE_MASK;
+				WARN_ON_ONCE(1);
+			}
+		}
+	} else if (!(in_flag & CPA_PAGES_ARRAY)) {
+		/*
+		 * in_flag of CPA_PAGES_ARRAY implies it is aligned.
+		 * No need to cehck in that case
+		 */
+		if (*addr & ~PAGE_MASK) {
+			*addr &= PAGE_MASK;
+			/*
+			 * People should not be passing in unaligned addresses:
+			 */
+			WARN_ON_ONCE(1);
+		}
+		/*
+		 * Save address for cache flush. *addr is modified in the call
+		 * to __change_page_attr_set_clr() below.
+		 */
+		baddr = *addr;
+	}
+
+	/* Must avoid aliasing mappings in the highmem code */
+	kmap_flush_unused();
+
+	vm_unmap_aliases();
+
+	cpa.vaddr = addr;
+	cpa.pages = pages;
+	cpa.numpages = numpages;
+	cpa.mask_set = mask_set;
+	cpa.mask_clr = mask_clr;
+	cpa.flags = 0;
+	cpa.curpage = 0;
+	cpa.force_split = force_split;
+
+	if (in_flag & (CPA_ARRAY | CPA_PAGES_ARRAY))
+		cpa.flags |= in_flag;
+
+	/* No alias checking for _NX bit modifications */
+	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
+
+	ret = __change_page_attr_set_clr(&cpa, checkalias);
+
+	/*
+	 * Check whether we really changed something:
+	 */
+	if (!(cpa.flags & CPA_FLUSHTLB))
+		goto out;
+
+	/*
+	 * No need to flush, when we did not set any of the caching
+	 * attributes:
+	 */
+	cache = cache_attr(mask_set);
+
+	/*
+	 * On success we use clflush, when the CPU supports it to
+	 * avoid the wbindv. If the CPU does not support it and in the
+	 * error case we fall back to cpa_flush_all (which uses
+	 * wbindv):
+	 */
+	if (!ret && cpu_has_clflush) {
+		if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
+			cpa_flush_array(addr, numpages, cache,
+					cpa.flags, pages);
+		} else
+			cpa_flush_range(baddr, numpages, cache);
+	} else
+		cpa_flush_all(cache);
+
+out:
+	return ret;
+}
+
+static inline int change_page_attr_set(unsigned long *addr, int numpages,
+				       pgprot_t mask, int array)
+{
+	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0,
+		(array ? CPA_ARRAY : 0), NULL);
+}
+
+static inline int change_page_attr_clear(unsigned long *addr, int numpages,
+					 pgprot_t mask, int array)
+{
+	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0,
+		(array ? CPA_ARRAY : 0), NULL);
+}
+
+static inline int cpa_set_pages_array(struct page **pages, int numpages,
+				       pgprot_t mask)
+{
+	return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0,
+		CPA_PAGES_ARRAY, pages);
+}
+
+static inline int cpa_clear_pages_array(struct page **pages, int numpages,
+					 pgprot_t mask)
+{
+	return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0,
+		CPA_PAGES_ARRAY, pages);
+}
+
+#ifdef CONFIG_XEN
+static void _free_memtype(u64 pstart, u64 pend)
+{
+	u64 pa = pstart &= __PHYSICAL_MASK;
+	u64 ma = phys_to_machine(pa);
+
+	while ((pa += PAGE_SIZE) < pend) {
+		if (phys_to_machine(pa) != ma + (pa - pstart)) {
+			free_memtype(ma, ma + (pa - pstart));
+			pstart = pa;
+			ma = phys_to_machine(pa);
+		}
+	}
+	free_memtype(ma, ma + (pend - pstart));
+}
+#define free_memtype _free_memtype
+
+static int _reserve_memtype(u64 pstart, u64 pend, unsigned long req_type)
+{
+	u64 pcur = pstart &= __PHYSICAL_MASK, pa = pcur;
+	u64 ma = phys_to_machine(pa);
+	int rc = 0;
+
+	while ((pa += PAGE_SIZE) < pend) {
+		if (phys_to_machine(pa) != ma + (pa - pcur)) {
+			rc = reserve_memtype(ma, ma + (pa - pcur),
+					     req_type, NULL);
+			if (rc)
+				break;
+			pcur = pa;
+			ma = phys_to_machine(pa);
+		}
+	}
+	if (likely(!rc))
+		rc = reserve_memtype(ma, ma + (pend - pcur), req_type, NULL);
+
+	if (unlikely(!rc) && pstart < pcur)
+		_free_memtype(pstart, pcur);
+
+	return rc;
+}
+#define reserve_memtype(s, e, r, n) \
+	_reserve_memtype(s, e, BUILD_BUG_ON_ZERO(n) ?: (r))
+#endif
+
+int _set_memory_uc(unsigned long addr, int numpages)
+{
+	/*
+	 * for now UC MINUS. see comments in ioremap_nocache()
+	 */
+	return change_page_attr_set(&addr, numpages,
+				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
+}
+
+int set_memory_uc(unsigned long addr, int numpages)
+{
+	int ret;
+
+	/*
+	 * for now UC MINUS. see comments in ioremap_nocache()
+	 */
+	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+			    _PAGE_CACHE_UC_MINUS, NULL);
+	if (ret)
+		goto out_err;
+
+	ret = _set_memory_uc(addr, numpages);
+	if (ret)
+		goto out_free;
+
+	return 0;
+
+out_free:
+	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+out_err:
+	return ret;
+}
+EXPORT_SYMBOL(set_memory_uc);
+
+int set_memory_array_uc(unsigned long *addr, int addrinarray)
+{
+	int i, j;
+	int ret;
+
+	/*
+	 * for now UC MINUS. see comments in ioremap_nocache()
+	 */
+	for (i = 0; i < addrinarray; i++) {
+		ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE,
+					_PAGE_CACHE_UC_MINUS, NULL);
+		if (ret)
+			goto out_free;
+	}
+
+	ret = change_page_attr_set(addr, addrinarray,
+				    __pgprot(_PAGE_CACHE_UC_MINUS), 1);
+	if (ret)
+		goto out_free;
+
+	return 0;
+
+out_free:
+	for (j = 0; j < i; j++)
+		free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE);
+
+	return ret;
+}
+EXPORT_SYMBOL(set_memory_array_uc);
+
+int _set_memory_wc(unsigned long addr, int numpages)
+{
+	int ret;
+	unsigned long addr_copy = addr;
+
+	ret = change_page_attr_set(&addr, numpages,
+				    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
+	if (!ret) {
+		ret = change_page_attr_set_clr(&addr_copy, numpages,
+					       __pgprot(_PAGE_CACHE_WC),
+					       __pgprot(_PAGE_CACHE_MASK),
+					       0, 0, NULL);
+	}
+	return ret;
+}
+
+int set_memory_wc(unsigned long addr, int numpages)
+{
+	int ret;
+
+	if (!pat_enabled)
+		return set_memory_uc(addr, numpages);
+
+	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
+		_PAGE_CACHE_WC, NULL);
+	if (ret)
+		goto out_err;
+
+	ret = _set_memory_wc(addr, numpages);
+	if (ret)
+		goto out_free;
+
+	return 0;
+
+out_free:
+	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+out_err:
+	return ret;
+}
+EXPORT_SYMBOL(set_memory_wc);
+
+int _set_memory_wb(unsigned long addr, int numpages)
+{
+	return change_page_attr_clear(&addr, numpages,
+				      __pgprot(_PAGE_CACHE_MASK), 0);
+}
+
+int set_memory_wb(unsigned long addr, int numpages)
+{
+	int ret;
+
+	ret = _set_memory_wb(addr, numpages);
+	if (ret)
+		return ret;
+
+	free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
+	return 0;
+}
+EXPORT_SYMBOL(set_memory_wb);
+
+int set_memory_array_wb(unsigned long *addr, int addrinarray)
+{
+	int i;
+	int ret;
+
+	ret = change_page_attr_clear(addr, addrinarray,
+				      __pgprot(_PAGE_CACHE_MASK), 1);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < addrinarray; i++)
+		free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE);
+
+	return 0;
+}
+EXPORT_SYMBOL(set_memory_array_wb);
+
+int set_memory_x(unsigned long addr, int numpages)
+{
+	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0);
+}
+EXPORT_SYMBOL(set_memory_x);
+
+int set_memory_nx(unsigned long addr, int numpages)
+{
+	return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0);
+}
+EXPORT_SYMBOL(set_memory_nx);
+
+int set_memory_ro(unsigned long addr, int numpages)
+{
+	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0);
+}
+EXPORT_SYMBOL_GPL(set_memory_ro);
+
+int set_memory_rw(unsigned long addr, int numpages)
+{
+	return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0);
+}
+EXPORT_SYMBOL_GPL(set_memory_rw);
+
+int set_memory_np(unsigned long addr, int numpages)
+{
+	return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0);
+}
+
+int set_memory_4k(unsigned long addr, int numpages)
+{
+	return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
+					__pgprot(0), 1, 0, NULL);
+}
+
+int set_pages_uc(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_uc(addr, numpages);
+}
+EXPORT_SYMBOL(set_pages_uc);
+
+int set_pages_array_uc(struct page **pages, int addrinarray)
+{
+	unsigned long start;
+	unsigned long end;
+	int i;
+	int free_idx;
+
+	for (i = 0; i < addrinarray; i++) {
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+		end = start + PAGE_SIZE;
+		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
+			goto err_out;
+	}
+
+	if (cpa_set_pages_array(pages, addrinarray,
+			__pgprot(_PAGE_CACHE_UC_MINUS)) == 0) {
+		return 0; /* Success */
+	}
+err_out:
+	free_idx = i;
+	for (i = 0; i < free_idx; i++) {
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+		end = start + PAGE_SIZE;
+		free_memtype(start, end);
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(set_pages_array_uc);
+
+int set_pages_wb(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_wb(addr, numpages);
+}
+EXPORT_SYMBOL(set_pages_wb);
+
+int set_pages_array_wb(struct page **pages, int addrinarray)
+{
+	int retval;
+	unsigned long start;
+	unsigned long end;
+	int i;
+
+	retval = cpa_clear_pages_array(pages, addrinarray,
+			__pgprot(_PAGE_CACHE_MASK));
+	if (retval)
+		return retval;
+
+	for (i = 0; i < addrinarray; i++) {
+		if (PageHighMem(pages[i]))
+			continue;
+		start = page_to_pfn(pages[i]) << PAGE_SHIFT;
+		end = start + PAGE_SIZE;
+		free_memtype(start, end);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(set_pages_array_wb);
+
+int set_pages_x(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_x(addr, numpages);
+}
+EXPORT_SYMBOL(set_pages_x);
+
+int set_pages_nx(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_nx(addr, numpages);
+}
+EXPORT_SYMBOL(set_pages_nx);
+
+int set_pages_ro(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_ro(addr, numpages);
+}
+
+int set_pages_rw(struct page *page, int numpages)
+{
+	unsigned long addr = (unsigned long)page_address(page);
+
+	return set_memory_rw(addr, numpages);
+}
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+
+static int __set_pages_p(struct page *page, int numpages)
+{
+	unsigned long tempaddr = (unsigned long) page_address(page);
+	struct cpa_data cpa = { .vaddr = &tempaddr,
+				.numpages = numpages,
+				.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
+				.mask_clr = __pgprot(0),
+				.flags = 0};
+
+	/*
+	 * No alias checking needed for setting present flag. otherwise,
+	 * we may need to break large pages for 64-bit kernel text
+	 * mappings (this adds to complexity if we want to do this from
+	 * atomic context especially). Let's keep it simple!
+	 */
+	return __change_page_attr_set_clr(&cpa, 0);
+}
+
+static int __set_pages_np(struct page *page, int numpages)
+{
+	unsigned long tempaddr = (unsigned long) page_address(page);
+	struct cpa_data cpa = { .vaddr = &tempaddr,
+				.numpages = numpages,
+				.mask_set = __pgprot(0),
+				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
+				.flags = 0};
+
+	/*
+	 * No alias checking needed for setting not present flag. otherwise,
+	 * we may need to break large pages for 64-bit kernel text
+	 * mappings (this adds to complexity if we want to do this from
+	 * atomic context especially). Let's keep it simple!
+	 */
+	return __change_page_attr_set_clr(&cpa, 0);
+}
+
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+	if (PageHighMem(page))
+		return;
+	if (!enable) {
+		debug_check_no_locks_freed(page_address(page),
+					   numpages * PAGE_SIZE);
+	}
+
+	/*
+	 * If page allocator is not up yet then do not call c_p_a():
+	 */
+	if (!debug_pagealloc_enabled)
+		return;
+
+	/*
+	 * The return value is ignored as the calls cannot fail.
+	 * Large pages for identity mappings are not used at boot time
+	 * and hence no memory allocations during large page split.
+	 */
+	if (enable)
+		__set_pages_p(page, numpages);
+	else
+		__set_pages_np(page, numpages);
+
+	/*
+	 * We should perform an IPI and flush all tlbs,
+	 * but that can deadlock->flush only current cpu:
+	 */
+	__flush_tlb_all();
+}
+
+#ifdef CONFIG_HIBERNATION
+
+bool kernel_page_present(struct page *page)
+{
+	unsigned int level;
+	pte_t *pte;
+
+	if (PageHighMem(page))
+		return false;
+
+	pte = lookup_address((unsigned long)page_address(page), &level);
+	return (__pte_val(*pte) & _PAGE_PRESENT);
+}
+
+#endif /* CONFIG_HIBERNATION */
+
+#endif /* CONFIG_DEBUG_PAGEALLOC */
+
+static inline int in_secondary_range(unsigned long va)
+{
+#ifdef CONFIG_X86_64
+	return va >= VMALLOC_START && va < VMALLOC_END;
+#else
+	return va >= (unsigned long)high_memory;
+#endif
+}
+
+static void __make_page_readonly(unsigned long va)
+{
+	pte_t *pte;
+	unsigned int level;
+
+	pte = lookup_address(va, &level);
+	BUG_ON(!pte || level != PG_LEVEL_4K);
+	if (HYPERVISOR_update_va_mapping(va, pte_wrprotect(*pte), 0))
+		BUG();
+	if (in_secondary_range(va)) {
+		unsigned long pfn = pte_pfn(*pte);
+
+#ifdef CONFIG_HIGHMEM
+		if (pfn >= highstart_pfn)
+			kmap_flush_unused(); /* flush stale writable kmaps */
+		else
+#endif
+			__make_page_readonly((unsigned long)__va(pfn << PAGE_SHIFT));
+	}
+}
+
+static void __make_page_writable(unsigned long va)
+{
+	pte_t *pte;
+	unsigned int level;
+
+	pte = lookup_address(va, &level);
+	BUG_ON(!pte || level != PG_LEVEL_4K);
+	if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), UVMF_INVLPG))
+		BUG();
+	if (in_secondary_range(va)) {
+		unsigned long pfn = pte_pfn(*pte);
+
+#ifdef CONFIG_HIGHMEM
+		if (pfn < highstart_pfn)
+#endif
+			__make_page_writable((unsigned long)__va(pfn << PAGE_SHIFT));
+	}
+}
+
+void make_page_readonly(void *va, unsigned int feature)
+{
+	if (!xen_feature(feature))
+		__make_page_readonly((unsigned long)va);
+}
+
+void make_page_writable(void *va, unsigned int feature)
+{
+	if (!xen_feature(feature))
+		__make_page_writable((unsigned long)va);
+}
+
+void make_pages_readonly(void *va, unsigned int nr, unsigned int feature)
+{
+	unsigned long addr;
+
+	if (xen_feature(feature))
+		return;
+
+	for (addr = (unsigned long)va; nr--; addr += PAGE_SIZE)
+		__make_page_readonly(addr);
+}
+
+void make_pages_writable(void *va, unsigned int nr, unsigned int feature)
+{
+	unsigned long addr;
+
+	if (xen_feature(feature))
+		return;
+
+	for (addr = (unsigned long)va; nr--; addr += PAGE_SIZE)
+		__make_page_writable(addr);
+}
+
+/*
+ * The testcases use internal knowledge of the implementation that shouldn't
+ * be exposed to the rest of the kernel. Include these directly here.
+ */
+#ifdef CONFIG_CPA_DEBUG
+#include "pageattr-test.c"
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/mm/init.c
+++ linux-ec2-2.6.32/arch/x86/mm/init.c
@@ -149,6 +149,14 @@
 	set_nx();
 	if (nx_enabled)
 		printk(KERN_INFO "NX (Execute Disable) protection: active\n");
+	else
+#ifdef CONFIG_X86_32
+		printk(KERN_INFO "Using x86 segment limits to approximate "
+			"NX protection\n");
+#else
+		printk(KERN_WARNING "Warning: NX (Execute Disable) protection "
+			"missing in CPU or disabled in BIOS!\n");
+#endif
 
 	/* Enable PSE if available */
 	if (cpu_has_pse)
--- linux-ec2-2.6.32.orig/arch/x86/mm/pgtable-xen.c
+++ linux-ec2-2.6.32/arch/x86/mm/pgtable-xen.c
@@ -0,0 +1,895 @@
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <xen/features.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/tlb.h>
+#include <asm/fixmap.h>
+#include <asm/hypervisor.h>
+#include <asm/mmu_context.h>
+
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+
+#ifdef CONFIG_HIGHPTE
+#define PGALLOC_USER_GFP __GFP_HIGHMEM
+#else
+#define PGALLOC_USER_GFP 0
+#endif
+
+gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP;
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte = (pte_t *)__get_free_page(PGALLOC_GFP);
+	if (pte)
+		make_lowmem_page_readonly(pte, XENFEAT_writable_page_tables);
+	return pte;
+}
+
+static void _pte_free(struct page *page, unsigned int order)
+{
+	BUG_ON(order);
+	__pte_free(page);
+}
+
+pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *pte;
+
+	pte = alloc_pages(__userpte_alloc_gfp, 0);
+	if (pte) {
+		pgtable_page_ctor(pte);
+		SetPageForeign(pte, _pte_free);
+		init_page_count(pte);
+	}
+	return pte;
+}
+
+static int __init setup_userpte(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	/*
+	 * "userpte=nohigh" disables allocation of user pagetables in
+	 * high memory.
+	 */
+	if (strcmp(arg, "nohigh") == 0)
+		__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+	else
+		return -EINVAL;
+	return 0;
+}
+early_param("userpte", setup_userpte);
+
+void __pte_free(pgtable_t pte)
+{
+	if (!PageHighMem(pte)) {
+		if (PagePinned(pte)) {
+			unsigned long pfn = page_to_pfn(pte);
+
+			if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT),
+							 pfn_pte(pfn,
+								 PAGE_KERNEL),
+							 0))
+				BUG();
+			ClearPagePinned(pte);
+		}
+	} else
+#ifdef CONFIG_HIGHPTE
+		ClearPagePinned(pte);
+#else
+		BUG();
+#endif
+
+	ClearPageForeign(pte);
+	init_page_count(pte);
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+{
+	pgtable_page_dtor(pte);
+	paravirt_release_pte(page_to_pfn(pte));
+	tlb_remove_page(tlb, pte);
+}
+
+#if PAGETABLE_LEVELS > 2
+static void _pmd_free(struct page *page, unsigned int order)
+{
+	BUG_ON(order);
+	__pmd_free(page);
+}
+
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *pmd;
+
+	pmd = alloc_pages(PGALLOC_GFP, 0);
+	if (!pmd)
+		return NULL;
+	SetPageForeign(pmd, _pmd_free);
+	init_page_count(pmd);
+	return page_address(pmd);
+}
+
+void __pmd_free(pgtable_t pmd)
+{
+	if (PagePinned(pmd)) {
+		unsigned long pfn = page_to_pfn(pmd);
+
+		if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT),
+						 pfn_pte(pfn, PAGE_KERNEL),
+						 0))
+			BUG();
+		ClearPagePinned(pmd);
+	}
+
+	ClearPageForeign(pmd);
+	init_page_count(pmd);
+	__free_page(pmd);
+}
+
+void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+{
+	paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+	tlb_remove_page(tlb, virt_to_page(pmd));
+}
+
+#if PAGETABLE_LEVELS > 3
+void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+{
+	paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
+	tlb_remove_page(tlb, virt_to_page(pud));
+}
+#endif	/* PAGETABLE_LEVELS > 3 */
+#endif	/* PAGETABLE_LEVELS > 2 */
+
+static void _pin_lock(struct mm_struct *mm, int lock) {
+	if (lock)
+		spin_lock(&mm->page_table_lock);
+#if USE_SPLIT_PTLOCKS
+	/* While mm->page_table_lock protects us against insertions and
+	 * removals of higher level page table pages, it doesn't protect
+	 * against updates of pte-s. Such updates, however, require the
+	 * pte pages to be in consistent state (unpinned+writable or
+	 * pinned+readonly). The pinning and attribute changes, however
+	 * cannot be done atomically, which is why such updates must be
+	 * prevented from happening concurrently.
+	 * Note that no pte lock can ever elsewhere be acquired nesting
+	 * with an already acquired one in the same mm, or with the mm's
+	 * page_table_lock already acquired, as that would break in the
+	 * non-split case (where all these are actually resolving to the
+	 * one page_table_lock). Thus acquiring all of them here is not
+	 * going to result in dead locks, and the order of acquires
+	 * doesn't matter.
+	 */
+	{
+		pgd_t *pgd = mm->pgd;
+		unsigned g;
+
+		for (g = 0; g <= ((TASK_SIZE_MAX-1) / PGDIR_SIZE); g++, pgd++) {
+			pud_t *pud;
+			unsigned u;
+
+			if (pgd_none(*pgd))
+				continue;
+			pud = pud_offset(pgd, 0);
+			for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+				pmd_t *pmd;
+				unsigned m;
+
+				if (pud_none(*pud))
+					continue;
+				pmd = pmd_offset(pud, 0);
+				for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+					spinlock_t *ptl;
+
+					if (pmd_none(*pmd))
+						continue;
+					ptl = pte_lockptr(0, pmd);
+					if (lock)
+						spin_lock(ptl);
+					else
+						spin_unlock(ptl);
+				}
+			}
+		}
+	}
+#endif
+	if (!lock)
+		spin_unlock(&mm->page_table_lock);
+}
+#define pin_lock(mm) _pin_lock(mm, 1)
+#define pin_unlock(mm) _pin_lock(mm, 0)
+
+#define PIN_BATCH sizeof(void *)
+static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+
+static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
+					     unsigned int cpu, unsigned int seq)
+{
+	unsigned long pfn = page_to_pfn(page);
+
+	if (pgprot_val(flags) & _PAGE_RW)
+		ClearPagePinned(page);
+	else
+		SetPagePinned(page);
+	if (PageHighMem(page))
+		return seq;
+	MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+				(unsigned long)__va(pfn << PAGE_SHIFT),
+				pfn_pte(pfn, flags), 0);
+	if (unlikely(++seq == PIN_BATCH)) {
+		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+							PIN_BATCH, NULL)))
+			BUG();
+		seq = 0;
+	}
+
+	return seq;
+}
+
+static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
+{
+	pgd_t       *pgd = pgd_base;
+	pud_t       *pud;
+	pmd_t       *pmd;
+	int          g,u,m;
+	unsigned int cpu, seq;
+	multicall_entry_t *mcl;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
+	cpu = get_cpu();
+
+	/*
+	 * Cannot iterate up to USER_PTRS_PER_PGD on x86-64 as these pagetables
+	 * may not be the 'current' task's pagetables (e.g., current may be
+	 * 32-bit, but the pagetables may be for a 64-bit task).
+	 * Subtracting 1 from TASK_SIZE_MAX means the loop limit is correct
+	 * regardless of whether TASK_SIZE_MAX is a multiple of PGDIR_SIZE.
+	 */
+	for (g = 0, seq = 0; g <= ((TASK_SIZE_MAX-1) / PGDIR_SIZE); g++, pgd++) {
+		if (pgd_none(*pgd))
+			continue;
+		pud = pud_offset(pgd, 0);
+		if (PTRS_PER_PUD > 1) /* not folded */
+			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
+		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+			if (pud_none(*pud))
+				continue;
+			pmd = pmd_offset(pud, 0);
+			if (PTRS_PER_PMD > 1) /* not folded */
+				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
+			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+				if (pmd_none(*pmd))
+					continue;
+				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
+			}
+		}
+	}
+
+#ifdef CONFIG_X86_PAE
+	for (; g < PTRS_PER_PGD; g++, pgd++) {
+		BUG_ON(pgd_none(*pgd));
+		pud = pud_offset(pgd, 0);
+		BUG_ON(pud_none(*pud));
+		pmd = pmd_offset(pud, 0);
+		seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
+	}
+#endif
+
+	mcl = per_cpu(pb_mcl, cpu);
+#ifdef CONFIG_X86_64
+	if (unlikely(seq > PIN_BATCH - 2)) {
+		if (unlikely(HYPERVISOR_multicall_check(mcl, seq, NULL)))
+			BUG();
+		seq = 0;
+	}
+	pgd = __user_pgd(pgd_base);
+	BUG_ON(!pgd);
+	MULTI_update_va_mapping(mcl + seq,
+	       (unsigned long)pgd,
+	       pfn_pte(virt_to_phys(pgd)>>PAGE_SHIFT, flags),
+	       0);
+	MULTI_update_va_mapping(mcl + seq + 1,
+	       (unsigned long)pgd_base,
+	       pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+	       UVMF_TLB_FLUSH);
+	if (unlikely(HYPERVISOR_multicall_check(mcl, seq + 2, NULL)))
+		BUG();
+#else
+	if (likely(seq != 0)) {
+		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+			(unsigned long)pgd_base,
+			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+			UVMF_TLB_FLUSH);
+		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+		                                        seq + 1, NULL)))
+			BUG();
+	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
+			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+			UVMF_TLB_FLUSH))
+		BUG();
+#endif
+
+	put_cpu();
+}
+
+void __init xen_init_pgd_pin(void)
+{
+	pgd_t       *pgd = init_mm.pgd;
+	pud_t       *pud;
+	pmd_t       *pmd;
+	unsigned int g, u, m;
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return;
+
+	SetPagePinned(virt_to_page(pgd));
+	for (g = 0; g < PTRS_PER_PGD; g++, pgd++) {
+#ifndef CONFIG_X86_PAE
+		if (g >= pgd_index(HYPERVISOR_VIRT_START)
+		    && g <= pgd_index(HYPERVISOR_VIRT_END - 1))
+			continue;
+#endif
+		if (!pgd_present(*pgd))
+			continue;
+		pud = pud_offset(pgd, 0);
+		if (PTRS_PER_PUD > 1) /* not folded */
+			SetPagePinned(virt_to_page(pud));
+		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
+			if (!pud_present(*pud) || pud_large(*pud))
+				continue;
+			pmd = pmd_offset(pud, 0);
+			if (PTRS_PER_PMD > 1) /* not folded */
+				SetPagePinned(virt_to_page(pmd));
+			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
+#ifdef CONFIG_X86_PAE
+				if (g == pgd_index(HYPERVISOR_VIRT_START)
+				    && m >= pmd_index(HYPERVISOR_VIRT_START))
+					continue;
+#endif
+				if (!pmd_present(*pmd) || pmd_large(*pmd))
+					continue;
+				SetPagePinned(pmd_page(*pmd));
+			}
+		}
+	}
+#ifdef CONFIG_X86_64
+	SetPagePinned(virt_to_page(level3_user_pgt));
+#endif
+}
+
+static void __pgd_pin(pgd_t *pgd)
+{
+	pgd_walk(pgd, PAGE_KERNEL_RO);
+	kmap_flush_unused();
+	xen_pgd_pin(pgd);
+	SetPagePinned(virt_to_page(pgd));
+}
+
+static void __pgd_unpin(pgd_t *pgd)
+{
+	xen_pgd_unpin(pgd);
+	pgd_walk(pgd, PAGE_KERNEL);
+	ClearPagePinned(virt_to_page(pgd));
+}
+
+static void pgd_test_and_unpin(pgd_t *pgd)
+{
+	if (PagePinned(virt_to_page(pgd)))
+		__pgd_unpin(pgd);
+}
+
+void mm_pin(struct mm_struct *mm)
+{
+	if (xen_feature(XENFEAT_writable_page_tables))
+		return;
+
+	pin_lock(mm);
+	__pgd_pin(mm->pgd);
+	pin_unlock(mm);
+}
+
+void mm_unpin(struct mm_struct *mm)
+{
+	if (xen_feature(XENFEAT_writable_page_tables))
+		return;
+
+	pin_lock(mm);
+	__pgd_unpin(mm->pgd);
+	pin_unlock(mm);
+}
+
+void mm_pin_all(void)
+{
+	struct page *page;
+	unsigned long flags;
+
+	if (xen_feature(XENFEAT_writable_page_tables))
+		return;
+
+	/*
+	 * Allow uninterrupted access to the pgd_list. Also protects
+	 * __pgd_pin() by disabling preemption.
+	 * All other CPUs must be at a safe point (e.g., in stop_machine
+	 * or offlined entirely).
+	 */
+	spin_lock_irqsave(&pgd_lock, flags);
+	list_for_each_entry(page, &pgd_list, lru) {
+		if (!PagePinned(page))
+			__pgd_pin((pgd_t *)page_address(page));
+	}
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
+void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+{
+	if (!PagePinned(virt_to_page(mm->pgd)))
+		mm_pin(mm);
+}
+
+/*
+ * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() *much*
+ * faster this way, as no hypercalls are needed for the page table updates.
+ */
+static void leave_active_mm(struct task_struct *tsk, struct mm_struct *mm)
+	__releases(tsk->alloc_lock)
+{
+	if (tsk->active_mm == mm) {
+		tsk->active_mm = &init_mm;
+		atomic_inc(&init_mm.mm_count);
+
+		switch_mm(mm, &init_mm, tsk);
+
+		if (atomic_dec_and_test(&mm->mm_count))
+			BUG();
+	}
+
+	task_unlock(tsk);
+}
+
+static void _leave_active_mm(void *mm)
+{
+	struct task_struct *tsk = current;
+
+	if (spin_trylock(&tsk->alloc_lock))
+		leave_active_mm(tsk, mm);
+}
+
+void arch_exit_mmap(struct mm_struct *mm)
+{
+	struct task_struct *tsk = current;
+
+	task_lock(tsk);
+	leave_active_mm(tsk, mm);
+
+	preempt_disable();
+	smp_call_function_many(mm_cpumask(mm), _leave_active_mm, mm, 1);
+	preempt_enable();
+
+	if (PagePinned(virt_to_page(mm->pgd))
+	    && atomic_read(&mm->mm_count) == 1
+	    && !mm->context.has_foreign_mappings)
+		mm_unpin(mm);
+}
+
+static inline void pgd_list_add(pgd_t *pgd)
+{
+	struct page *page = virt_to_page(pgd);
+
+	list_add(&page->lru, &pgd_list);
+}
+
+static inline void pgd_list_del(pgd_t *pgd)
+{
+	struct page *page = virt_to_page(pgd);
+
+	list_del(&page->lru);
+}
+
+#define UNSHARED_PTRS_PER_PGD				\
+	(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
+
+static void pgd_ctor(pgd_t *pgd)
+{
+	pgd_test_and_unpin(pgd);
+
+	/* If the pgd points to a shared pagetable level (either the
+	   ptes in non-PAE, or shared PMD in PAE), then just copy the
+	   references from swapper_pg_dir. */
+	if (PAGETABLE_LEVELS == 2 ||
+	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
+	    PAGETABLE_LEVELS == 4) {
+		clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
+				swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+				KERNEL_PGD_PTRS);
+		paravirt_alloc_pmd_clone(__pa(pgd) >> PAGE_SHIFT,
+					 __pa(swapper_pg_dir) >> PAGE_SHIFT,
+					 KERNEL_PGD_BOUNDARY,
+					 KERNEL_PGD_PTRS);
+	}
+
+#ifdef CONFIG_X86_64
+	/* set level3_user_pgt for vsyscall area */
+	__user_pgd(pgd)[pgd_index(VSYSCALL_START)] =
+		__pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE);
+#endif
+
+	/* list required to sync kernel mapping updates */
+	if (!SHARED_KERNEL_PMD)
+		pgd_list_add(pgd);
+}
+
+static void pgd_dtor(pgd_t *pgd)
+{
+	unsigned long flags; /* can be called from interrupt context */
+
+	if (!SHARED_KERNEL_PMD) {
+		spin_lock_irqsave(&pgd_lock, flags);
+		pgd_list_del(pgd);
+		spin_unlock_irqrestore(&pgd_lock, flags);
+	}
+
+	pgd_test_and_unpin(pgd);
+}
+
+/*
+ * List of all pgd's needed for non-PAE so it can invalidate entries
+ * in both cached and uncached pgd's; not needed for PAE since the
+ * kernel pmd is shared. If PAE were not to share the pmd a similar
+ * tactic would be needed. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+ * -- wli
+ */
+
+#ifdef CONFIG_X86_PAE
+/*
+ * In PAE mode, we need to do a cr3 reload (=tlb flush) when
+ * updating the top-level pagetable entries to guarantee the
+ * processor notices the update.  Since this is expensive, and
+ * all 4 top-level entries are used almost immediately in a
+ * new process's life, we just pre-populate them here.
+ *
+ * Also, if we're in a paravirt environment where the kernel pmd is
+ * not shared between pagetables (!SHARED_KERNEL_PMDS), we allocate
+ * and initialize the kernel pmds here.
+ */
+#define PREALLOCATED_PMDS	UNSHARED_PTRS_PER_PGD
+
+void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
+{
+	/* Note: almost everything apart from _PAGE_PRESENT is
+	   reserved at the pmd (PDPT) level. */
+	pud_t pud = __pud(__pa(pmd) | _PAGE_PRESENT);
+
+	paravirt_alloc_pmd(mm, page_to_pfn(virt_to_page(pmd)));
+
+	if (likely(!PagePinned(virt_to_page(pudp)))) {
+		*pudp = pud;
+		return;
+	}
+
+	set_pud(pudp, pud);
+
+	/*
+	 * According to Intel App note "TLBs, Paging-Structure Caches,
+	 * and Their Invalidation", April 2007, document 317080-001,
+	 * section 8.1: in PAE mode we explicitly have to flush the
+	 * TLB via cr3 if the top-level pgd is changed...
+	 */
+	if (mm == current->active_mm)
+		xen_tlb_flush();
+}
+#else  /* !CONFIG_X86_PAE */
+
+/* No need to prepopulate any pagetable entries in non-PAE modes. */
+#define PREALLOCATED_PMDS	0
+
+#endif	/* CONFIG_X86_PAE */
+
+static void free_pmds(pmd_t *pmds[], struct mm_struct *mm, bool contig)
+{
+	int i;
+
+#ifdef CONFIG_X86_PAE
+	if (contig)
+		xen_destroy_contiguous_region((unsigned long)mm->pgd, 0);
+#endif
+
+	for(i = 0; i < PREALLOCATED_PMDS; i++)
+		if (pmds[i])
+			pmd_free(mm, pmds[i]);
+}
+
+static int preallocate_pmds(pmd_t *pmds[], struct mm_struct *mm)
+{
+	int i;
+	bool failed = false;
+
+	for(i = 0; i < PREALLOCATED_PMDS; i++) {
+		pmd_t *pmd = pmd_alloc_one(mm, i << PUD_SHIFT);
+		if (pmd == NULL)
+			failed = true;
+		pmds[i] = pmd;
+	}
+
+	if (failed) {
+		free_pmds(pmds, mm, false);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * Mop up any pmd pages which may still be attached to the pgd.
+ * Normally they will be freed by munmap/exit_mmap, but any pmd we
+ * preallocate which never got a corresponding vma will need to be
+ * freed manually.
+ */
+static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
+{
+	int i;
+
+	for(i = 0; i < PREALLOCATED_PMDS; i++) {
+		pgd_t pgd = pgdp[i];
+
+		if (__pgd_val(pgd) != 0) {
+			pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd);
+
+			pgdp[i] = xen_make_pgd(0);
+
+			paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT);
+			pmd_free(mm, pmd);
+		}
+	}
+
+#ifdef CONFIG_X86_PAE
+	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb))
+		xen_destroy_contiguous_region((unsigned long)pgdp, 0);
+#endif
+}
+
+static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
+{
+	pud_t *pud;
+	unsigned long addr;
+	int i;
+
+	if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */
+		return;
+
+	pud = pud_offset(pgd, 0);
+ 	for (addr = i = 0; i < PREALLOCATED_PMDS;
+	     i++, pud++, addr += PUD_SIZE) {
+		pmd_t *pmd = pmds[i];
+
+		if (i >= KERNEL_PGD_BOUNDARY)
+			memcpy(pmd,
+			       (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
+			       sizeof(pmd_t) * PTRS_PER_PMD);
+
+		/* It is safe to poke machine addresses of pmds under the pgd_lock. */
+		pud_populate(mm, pud, pmd);
+	}
+}
+
+static inline pgd_t *user_pgd_alloc(pgd_t *pgd)
+{
+#ifdef CONFIG_X86_64
+	if (pgd) {
+		pgd_t *upgd = (void *)__get_free_page(PGALLOC_GFP);
+
+		if (upgd)
+			virt_to_page(pgd)->index = (long)upgd;
+		else {
+			free_page((unsigned long)pgd);
+			pgd = NULL;
+		}
+	}
+#endif
+	return pgd;
+}
+
+static inline void user_pgd_free(pgd_t *pgd)
+{
+#ifdef CONFIG_X86_64
+	free_page(virt_to_page(pgd)->index);
+#endif
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd;
+	pmd_t *pmds[PREALLOCATED_PMDS];
+	unsigned long flags;
+
+	pgd = user_pgd_alloc((void *)__get_free_page(PGALLOC_GFP));
+
+	if (pgd == NULL)
+		goto out;
+
+	mm->pgd = pgd;
+
+	if (preallocate_pmds(pmds, mm) != 0)
+		goto out_free_pgd;
+
+	if (paravirt_pgd_alloc(mm) != 0)
+		goto out_free_pmds;
+
+	/*
+	 * Make sure that pre-populating the pmds is atomic with
+	 * respect to anything walking the pgd_list, so that they
+	 * never see a partially populated pgd.
+	 */
+	spin_lock_irqsave(&pgd_lock, flags);
+
+#ifdef CONFIG_X86_PAE
+	/* Protect against save/restore: move below 4GB under pgd_lock. */
+	if (!xen_feature(XENFEAT_pae_pgdir_above_4gb)
+	    && xen_create_contiguous_region((unsigned long)pgd, 0, 32)) {
+		spin_unlock_irqrestore(&pgd_lock, flags);
+		goto out_free_pmds;
+	}
+#endif
+
+	pgd_ctor(pgd);
+	pgd_prepopulate_pmd(mm, pgd, pmds);
+
+	spin_unlock_irqrestore(&pgd_lock, flags);
+
+	return pgd;
+
+out_free_pmds:
+	free_pmds(pmds, mm, !xen_feature(XENFEAT_pae_pgdir_above_4gb));
+out_free_pgd:
+	user_pgd_free(pgd);
+	free_page((unsigned long)pgd);
+out:
+	return NULL;
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	/*
+	 * After this the pgd should not be pinned for the duration of this
+	 * function's execution. We should never sleep and thus never race:
+	 *  1. User pmds will not become write-protected under our feet due
+	 *     to a concurrent mm_pin_all().
+	 *  2. The machine addresses in PGD entries will not become invalid
+	 *     due to a concurrent save/restore.
+	 */
+	pgd_dtor(pgd);
+
+	pgd_mop_up_pmds(mm, pgd);
+	paravirt_pgd_free(mm, pgd);
+	user_pgd_free(pgd);
+	free_page((unsigned long)pgd);
+}
+
+/* blktap and gntdev need this, as otherwise they would implicitly (and
+ * needlessly, as they never use it) reference init_mm. */
+pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *vma,
+				  unsigned long addr, pte_t *ptep, int full)
+{
+	return ptep_get_and_clear_full(vma ? vma->vm_mm : &init_mm,
+				       addr, ptep, full);
+}
+EXPORT_SYMBOL_GPL(xen_ptep_get_and_clear_full);
+
+int ptep_set_access_flags(struct vm_area_struct *vma,
+			  unsigned long address, pte_t *ptep,
+			  pte_t entry, int dirty)
+{
+	int changed = !pte_same(*ptep, entry);
+
+	if (changed && dirty) {
+		if (likely(vma->vm_mm == current->mm)) {
+			if (HYPERVISOR_update_va_mapping(address,
+				entry,
+				uvm_multi(mm_cpumask(vma->vm_mm))|UVMF_INVLPG))
+				BUG();
+		} else {
+			xen_l1_entry_update(ptep, entry);
+			flush_tlb_page(vma, address);
+		}
+	}
+
+	return changed;
+}
+
+int ptep_test_and_clear_young(struct vm_area_struct *vma,
+			      unsigned long addr, pte_t *ptep)
+{
+	int ret = 0;
+
+	if (pte_young(*ptep))
+		ret = test_and_clear_bit(_PAGE_BIT_ACCESSED,
+					 (unsigned long *) &ptep->pte);
+
+	if (ret)
+		pte_update(vma->vm_mm, addr, ptep);
+
+	return ret;
+}
+
+int ptep_clear_flush_young(struct vm_area_struct *vma,
+			   unsigned long address, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	int young = pte_young(pte);
+
+	pte = pte_mkold(pte);
+	if (PagePinned(virt_to_page(vma->vm_mm->pgd)))
+		ptep_set_access_flags(vma, address, ptep, pte, young);
+	else if (young)
+		ptep->pte_low = pte.pte_low;
+
+	return young;
+}
+
+/**
+ * reserve_top_address - reserves a hole in the top of kernel address space
+ * @reserve - size of hole to reserve
+ *
+ * Can be used to relocate the fixmap area and poke a hole in the top
+ * of kernel address space to make room for a hypervisor.
+ */
+void __init reserve_top_address(unsigned long reserve)
+{
+#ifdef CONFIG_X86_32
+	BUG_ON(fixmaps_set > 0);
+	printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
+	       (int)-reserve);
+	__FIXADDR_TOP = -reserve - PAGE_SIZE;
+#endif
+}
+
+int fixmaps_set;
+
+void xen_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
+{
+	unsigned long address = __fix_to_virt(idx);
+	pte_t pte;
+
+	if (idx >= __end_of_fixed_addresses) {
+		BUG();
+		return;
+	}
+
+	switch (idx) {
+#ifdef CONFIG_X86_64
+	extern pte_t level1_fixmap_pgt[PTRS_PER_PTE];
+
+	case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
+		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
+		set_pte_vaddr_pud(level3_user_pgt, address, pte);
+		break;
+	case FIX_EARLYCON_MEM_BASE:
+	case FIX_SHARED_INFO:
+	case FIX_ISAMAP_END ... FIX_ISAMAP_BEGIN:
+		xen_l1_entry_update(level1_fixmap_pgt + pte_index(address),
+				    pfn_pte_ma(phys >> PAGE_SHIFT, flags));
+		fixmaps_set++;
+		return;
+#else
+	case FIX_WP_TEST:
+	case FIX_VDSO:
+		pte = pfn_pte(phys >> PAGE_SHIFT, flags);
+		break;
+#endif
+	default:
+		pte = pfn_pte_ma(phys >> PAGE_SHIFT, flags);
+		break;
+	}
+	set_pte_vaddr(address, pte);
+	fixmaps_set++;
+}
--- linux-ec2-2.6.32.orig/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ linux-ec2-2.6.32/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -0,0 +1,333 @@
+/*
+ * Accelerated GHASH implementation with Intel PCLMULQDQ-NI
+ * instructions. This file contains glue code.
+ *
+ * Copyright (c) 2009 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/cryptd.h>
+#include <crypto/gf128mul.h>
+#include <crypto/internal/hash.h>
+#include <asm/i387.h>
+
+#define GHASH_BLOCK_SIZE	16
+#define GHASH_DIGEST_SIZE	16
+
+void clmul_ghash_mul(char *dst, const be128 *shash);
+
+void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
+			const be128 *shash);
+
+void clmul_ghash_setkey(be128 *shash, const u8 *key);
+
+struct ghash_async_ctx {
+	struct cryptd_ahash *cryptd_tfm;
+};
+
+struct ghash_ctx {
+	be128 shash;
+};
+
+struct ghash_desc_ctx {
+	u8 buffer[GHASH_BLOCK_SIZE];
+	u32 bytes;
+};
+
+static int ghash_init(struct shash_desc *desc)
+{
+	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+
+	memset(dctx, 0, sizeof(*dctx));
+
+	return 0;
+}
+
+static int ghash_setkey(struct crypto_shash *tfm,
+			const u8 *key, unsigned int keylen)
+{
+	struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
+
+	if (keylen != GHASH_BLOCK_SIZE) {
+		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	clmul_ghash_setkey(&ctx->shash, key);
+
+	return 0;
+}
+
+static int ghash_update(struct shash_desc *desc,
+			 const u8 *src, unsigned int srclen)
+{
+	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+	u8 *dst = dctx->buffer;
+
+	kernel_fpu_begin();
+	if (dctx->bytes) {
+		int n = min(srclen, dctx->bytes);
+		u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
+
+		dctx->bytes -= n;
+		srclen -= n;
+
+		while (n--)
+			*pos++ ^= *src++;
+
+		if (!dctx->bytes)
+			clmul_ghash_mul(dst, &ctx->shash);
+	}
+
+	clmul_ghash_update(dst, src, srclen, &ctx->shash);
+	kernel_fpu_end();
+
+	if (srclen & 0xf) {
+		src += srclen - (srclen & 0xf);
+		srclen &= 0xf;
+		dctx->bytes = GHASH_BLOCK_SIZE - srclen;
+		while (srclen--)
+			*dst++ ^= *src++;
+	}
+
+	return 0;
+}
+
+static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
+{
+	u8 *dst = dctx->buffer;
+
+	if (dctx->bytes) {
+		u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
+
+		while (dctx->bytes--)
+			*tmp++ ^= 0;
+
+		kernel_fpu_begin();
+		clmul_ghash_mul(dst, &ctx->shash);
+		kernel_fpu_end();
+	}
+
+	dctx->bytes = 0;
+}
+
+static int ghash_final(struct shash_desc *desc, u8 *dst)
+{
+	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
+	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
+	u8 *buf = dctx->buffer;
+
+	ghash_flush(ctx, dctx);
+	memcpy(dst, buf, GHASH_BLOCK_SIZE);
+
+	return 0;
+}
+
+static struct shash_alg ghash_alg = {
+	.digestsize	= GHASH_DIGEST_SIZE,
+	.init		= ghash_init,
+	.update		= ghash_update,
+	.final		= ghash_final,
+	.setkey		= ghash_setkey,
+	.descsize	= sizeof(struct ghash_desc_ctx),
+	.base		= {
+		.cra_name		= "__ghash",
+		.cra_driver_name	= "__ghash-pclmulqdqni",
+		.cra_priority		= 0,
+		.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize		= GHASH_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct ghash_ctx),
+		.cra_module		= THIS_MODULE,
+		.cra_list		= LIST_HEAD_INIT(ghash_alg.base.cra_list),
+	},
+};
+
+static int ghash_async_init(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm;
+
+	if (irq_fpu_usable()) {
+		memcpy(cryptd_req, req, sizeof(*req));
+		ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base);
+		return crypto_ahash_init(cryptd_req);
+	} else {
+		struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+		struct crypto_shash *child = cryptd_ahash_child(cryptd_tfm);
+
+		desc->tfm = child;
+		desc->flags = req->base.flags;
+		return crypto_shash_init(desc);
+	}
+}
+
+static int ghash_async_update(struct ahash_request *req)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+
+	if (irq_fpu_usable()) {
+		struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+		struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+		struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm;
+
+		memcpy(cryptd_req, req, sizeof(*req));
+		ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base);
+		return crypto_ahash_update(cryptd_req);
+	} else {
+		struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+		return shash_ahash_update(req, desc);
+	}
+}
+
+static int ghash_async_final(struct ahash_request *req)
+{
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+
+	if (irq_fpu_usable()) {
+		struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+		struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+		struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm;
+
+		memcpy(cryptd_req, req, sizeof(*req));
+		ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base);
+		return crypto_ahash_final(cryptd_req);
+	} else {
+		struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+		return crypto_shash_final(desc, req->result);
+	}
+}
+
+static int ghash_async_digest(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct ahash_request *cryptd_req = ahash_request_ctx(req);
+	struct cryptd_ahash *cryptd_tfm = ctx->cryptd_tfm;
+
+	if (irq_fpu_usable()) {
+		memcpy(cryptd_req, req, sizeof(*req));
+		ahash_request_set_tfm(cryptd_req, &cryptd_tfm->base);
+		return crypto_ahash_digest(cryptd_req);
+	} else {
+		struct shash_desc *desc = cryptd_shash_desc(cryptd_req);
+		struct crypto_shash *child = cryptd_ahash_child(cryptd_tfm);
+
+		desc->tfm = child;
+		desc->flags = req->base.flags;
+		return shash_ahash_digest(req, desc);
+	}
+}
+
+static int ghash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
+			      unsigned int keylen)
+{
+	struct ghash_async_ctx *ctx = crypto_ahash_ctx(tfm);
+	struct crypto_ahash *child = &ctx->cryptd_tfm->base;
+	int err;
+
+	crypto_ahash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_ahash_set_flags(child, crypto_ahash_get_flags(tfm)
+			       & CRYPTO_TFM_REQ_MASK);
+	err = crypto_ahash_setkey(child, key, keylen);
+	crypto_ahash_set_flags(tfm, crypto_ahash_get_flags(child)
+			       & CRYPTO_TFM_RES_MASK);
+
+	return 0;
+}
+
+static int ghash_async_init_tfm(struct crypto_tfm *tfm)
+{
+	struct cryptd_ahash *cryptd_tfm;
+	struct ghash_async_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	cryptd_tfm = cryptd_alloc_ahash("__ghash-pclmulqdqni", 0, 0);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+	ctx->cryptd_tfm = cryptd_tfm;
+	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+				 sizeof(struct ahash_request) +
+				 crypto_ahash_reqsize(&cryptd_tfm->base));
+
+	return 0;
+}
+
+static void ghash_async_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct ghash_async_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	cryptd_free_ahash(ctx->cryptd_tfm);
+}
+
+static struct ahash_alg ghash_async_alg = {
+	.init		= ghash_async_init,
+	.update		= ghash_async_update,
+	.final		= ghash_async_final,
+	.setkey		= ghash_async_setkey,
+	.digest		= ghash_async_digest,
+	.halg = {
+		.digestsize	= GHASH_DIGEST_SIZE,
+		.base = {
+			.cra_name		= "ghash",
+			.cra_driver_name	= "ghash-clmulni",
+			.cra_priority		= 400,
+			.cra_flags		= CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+			.cra_blocksize		= GHASH_BLOCK_SIZE,
+			.cra_type		= &crypto_ahash_type,
+			.cra_module		= THIS_MODULE,
+			.cra_list		= LIST_HEAD_INIT(ghash_async_alg.halg.base.cra_list),
+			.cra_init		= ghash_async_init_tfm,
+			.cra_exit		= ghash_async_exit_tfm,
+		},
+	},
+};
+
+static int __init ghash_pclmulqdqni_mod_init(void)
+{
+	int err;
+
+	if (!cpu_has_pclmulqdq) {
+		printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not"
+		       " detected.\n");
+		return -ENODEV;
+	}
+
+	err = crypto_register_shash(&ghash_alg);
+	if (err)
+		goto err_out;
+	err = crypto_register_ahash(&ghash_async_alg);
+	if (err)
+		goto err_shash;
+
+	return 0;
+
+err_shash:
+	crypto_unregister_shash(&ghash_alg);
+err_out:
+	return err;
+}
+
+static void __exit ghash_pclmulqdqni_mod_exit(void)
+{
+	crypto_unregister_ahash(&ghash_async_alg);
+	crypto_unregister_shash(&ghash_alg);
+}
+
+module_init(ghash_pclmulqdqni_mod_init);
+module_exit(ghash_pclmulqdqni_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GHASH Message Digest Algorithm, "
+		   "acclerated by PCLMULQDQ-NI");
+MODULE_ALIAS("ghash");
--- linux-ec2-2.6.32.orig/arch/x86/crypto/Makefile
+++ linux-ec2-2.6.32/arch/x86/crypto/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
 obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
 obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
+obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
 
@@ -24,3 +25,5 @@
 salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o
+
+ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
--- linux-ec2-2.6.32.orig/arch/x86/crypto/ghash-clmulni-intel_asm.S
+++ linux-ec2-2.6.32/arch/x86/crypto/ghash-clmulni-intel_asm.S
@@ -0,0 +1,157 @@
+/*
+ * Accelerated GHASH implementation with Intel PCLMULQDQ-NI
+ * instructions. This file contains accelerated part of ghash
+ * implementation. More information about PCLMULQDQ can be found at:
+ *
+ * http://software.intel.com/en-us/articles/carry-less-multiplication-and-its-usage-for-computing-the-gcm-mode/
+ *
+ * Copyright (c) 2009 Intel Corp.
+ *   Author: Huang Ying <ying.huang@intel.com>
+ *	     Vinodh Gopal
+ *	     Erdinc Ozturk
+ *	     Deniz Karakoyunlu
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+
+.align 16
+.Lbswap_mask:
+	.octa 0x000102030405060708090a0b0c0d0e0f
+.Lpoly:
+	.octa 0xc2000000000000000000000000000001
+.Ltwo_one:
+	.octa 0x00000001000000000000000000000001
+
+#define DATA	%xmm0
+#define SHASH	%xmm1
+#define T1	%xmm2
+#define T2	%xmm3
+#define T3	%xmm4
+#define BSWAP	%xmm5
+#define IN1	%xmm6
+
+.text
+
+/*
+ * __clmul_gf128mul_ble:	internal ABI
+ * input:
+ *	DATA:			operand1
+ *	SHASH:			operand2, hash_key << 1 mod poly
+ * output:
+ *	DATA:			operand1 * operand2 mod poly
+ * changed:
+ *	T1
+ *	T2
+ *	T3
+ */
+__clmul_gf128mul_ble:
+	movaps DATA, T1
+	pshufd $0b01001110, DATA, T2
+	pshufd $0b01001110, SHASH, T3
+	pxor DATA, T2
+	pxor SHASH, T3
+
+	# pclmulqdq $0x00, SHASH, DATA	# DATA = a0 * b0
+	.byte 0x66, 0x0f, 0x3a, 0x44, 0xc1, 0x00
+	# pclmulqdq $0x11, SHASH, T1	# T1 = a1 * b1
+	.byte 0x66, 0x0f, 0x3a, 0x44, 0xd1, 0x11
+	# pclmulqdq $0x00, T3, T2	# T2 = (a1 + a0) * (b1 + b0)
+	.byte 0x66, 0x0f, 0x3a, 0x44, 0xdc, 0x00
+	pxor DATA, T2
+	pxor T1, T2			# T2 = a0 * b1 + a1 * b0
+
+	movaps T2, T3
+	pslldq $8, T3
+	psrldq $8, T2
+	pxor T3, DATA
+	pxor T2, T1			# <T1:DATA> is result of
+					# carry-less multiplication
+
+	# first phase of the reduction
+	movaps DATA, T3
+	psllq $1, T3
+	pxor DATA, T3
+	psllq $5, T3
+	pxor DATA, T3
+	psllq $57, T3
+	movaps T3, T2
+	pslldq $8, T2
+	psrldq $8, T3
+	pxor T2, DATA
+	pxor T3, T1
+
+	# second phase of the reduction
+	movaps DATA, T2
+	psrlq $5, T2
+	pxor DATA, T2
+	psrlq $1, T2
+	pxor DATA, T2
+	psrlq $1, T2
+	pxor T2, T1
+	pxor T1, DATA
+	ret
+
+/* void clmul_ghash_mul(char *dst, const be128 *shash) */
+ENTRY(clmul_ghash_mul)
+	movups (%rdi), DATA
+	movups (%rsi), SHASH
+	movaps .Lbswap_mask, BSWAP
+	pshufb BSWAP, DATA
+	call __clmul_gf128mul_ble
+	pshufb BSWAP, DATA
+	movups DATA, (%rdi)
+	ret
+
+/*
+ * void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
+ *			   const be128 *shash);
+ */
+ENTRY(clmul_ghash_update)
+	cmp $16, %rdx
+	jb .Lupdate_just_ret	# check length
+	movaps .Lbswap_mask, BSWAP
+	movups (%rdi), DATA
+	movups (%rcx), SHASH
+	pshufb BSWAP, DATA
+.align 4
+.Lupdate_loop:
+	movups (%rsi), IN1
+	pshufb BSWAP, IN1
+	pxor IN1, DATA
+	call __clmul_gf128mul_ble
+	sub $16, %rdx
+	add $16, %rsi
+	cmp $16, %rdx
+	jge .Lupdate_loop
+	pshufb BSWAP, DATA
+	movups DATA, (%rdi)
+.Lupdate_just_ret:
+	ret
+
+/*
+ * void clmul_ghash_setkey(be128 *shash, const u8 *key);
+ *
+ * Calculate hash_key << 1 mod poly
+ */
+ENTRY(clmul_ghash_setkey)
+	movaps .Lbswap_mask, BSWAP
+	movups (%rsi), %xmm0
+	pshufb BSWAP, %xmm0
+	movaps %xmm0, %xmm1
+	psllq $1, %xmm0
+	psrlq $63, %xmm1
+	movaps %xmm1, %xmm2
+	pslldq $8, %xmm1
+	psrldq $8, %xmm2
+	por %xmm1, %xmm0
+	# reduction
+	pshufd $0b00100100, %xmm2, %xmm1
+	pcmpeqd .Ltwo_one, %xmm1
+	pand .Lpoly, %xmm1
+	pxor %xmm1, %xmm0
+	movups %xmm0, (%rdi)
+	ret
--- linux-ec2-2.6.32.orig/arch/x86/ia32/sys_ia32.c
+++ linux-ec2-2.6.32/arch/x86/ia32/sys_ia32.c
@@ -155,9 +155,6 @@
 asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
 {
 	struct mmap_arg_struct a;
-	struct file *file = NULL;
-	unsigned long retval;
-	struct mm_struct *mm ;
 
 	if (copy_from_user(&a, arg, sizeof(a)))
 		return -EFAULT;
@@ -165,22 +162,8 @@
 	if (a.offset & ~PAGE_MASK)
 		return -EINVAL;
 
-	if (!(a.flags & MAP_ANONYMOUS)) {
-		file = fget(a.fd);
-		if (!file)
-			return -EBADF;
-	}
-
-	mm = current->mm;
-	down_write(&mm->mmap_sem);
-	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags,
+	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
 			       a.offset>>PAGE_SHIFT);
-	if (file)
-		fput(file);
-
-	up_write(&mm->mmap_sem);
-
-	return retval;
 }
 
 asmlinkage long sys32_mprotect(unsigned long start, size_t len,
@@ -539,30 +522,6 @@
 	return ret;
 }
 
-asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
-			    unsigned long prot, unsigned long flags,
-			    unsigned long fd, unsigned long pgoff)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long error;
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			return -EBADF;
-	}
-
-	down_write(&mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&mm->mmap_sem);
-
-	if (file)
-		fput(file);
-	return error;
-}
-
 asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
 {
 	char *arch = "x86_64";
--- linux-ec2-2.6.32.orig/arch/x86/ia32/ia32_aout.c
+++ linux-ec2-2.6.32/arch/x86/ia32/ia32_aout.c
@@ -308,14 +308,15 @@
 	if (retval)
 		return retval;
 
-	regs->cs = __USER32_CS;
-	regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
-		regs->r13 = regs->r14 = regs->r15 = 0;
-
 	/* OK, This is the point of no return */
 	set_personality(PER_LINUX);
 	set_thread_flag(TIF_IA32);
-	clear_thread_flag(TIF_ABI_PENDING);
+
+	setup_new_exec(bprm);
+
+	regs->cs = __USER32_CS;
+	regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
+		regs->r13 = regs->r14 = regs->r15 = 0;
 
 	current->mm->end_code = ex.a_text +
 		(current->mm->start_code = N_TXTADDR(ex));
@@ -326,7 +327,6 @@
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 	current->mm->cached_hole_size = 0;
 
-	current->mm->mmap = NULL;
 	install_exec_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 
--- linux-ec2-2.6.32.orig/arch/x86/ia32/ia32entry-xen.S
+++ linux-ec2-2.6.32/arch/x86/ia32/ia32entry-xen.S
@@ -0,0 +1,788 @@
+/*
+ * Compatibility mode system call entry point for x86-64. 
+ * 		
+ * Copyright 2000-2002 Andi Kleen, SuSE Labs.
+ */		 
+
+#include <asm/dwarf2.h>
+#include <asm/calling.h>
+#include <asm/asm-offsets.h>
+#include <asm/current.h>
+#include <asm/errno.h>
+#include <asm/ia32_unistd.h>	
+#include <asm/thread_info.h>	
+#include <asm/segment.h>
+#include <asm/irqflags.h>
+#include <linux/linkage.h>
+
+/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
+#include <linux/elf-em.h>
+#define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
+#define __AUDIT_ARCH_LE	   0x40000000
+
+#ifndef CONFIG_AUDITSYSCALL
+#define sysexit_audit ia32_ret_from_sys_call
+#define sysretl_audit ia32_ret_from_sys_call
+#endif
+
+#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
+
+	.macro IA32_ARG_FIXUP noebp=0
+	movl	%edi,%r8d
+	.if \noebp
+	.else
+	movl	%ebp,%r9d
+	.endif
+	xchg	%ecx,%esi
+	movl	%ebx,%edi
+	movl	%edx,%edx	/* zero extension */
+	.endm 
+
+	/* clobbers %eax */	
+	.macro  CLEAR_RREGS offset=0, _r9=rax
+	xorl 	%eax,%eax
+	movq	%rax,\offset+R11(%rsp)
+	movq	%rax,\offset+R10(%rsp)
+	movq	%\_r9,\offset+R9(%rsp)
+	movq	%rax,\offset+R8(%rsp)
+	.endm
+
+	/*
+	 * Reload arg registers from stack in case ptrace changed them.
+	 * We don't reload %eax because syscall_trace_enter() returned
+	 * the %rax value we should see.  Instead, we just truncate that
+	 * value to 32 bits again as we did on entry from user mode.
+	 * If it's a new value set by user_regset during entry tracing,
+	 * this matches the normal truncation of the user-mode value.
+	 * If it's -1 to make us punt the syscall, then (u32)-1 is still
+	 * an appropriately invalid value.
+	 */
+	.macro LOAD_ARGS32 offset, _r9=0
+	.if \_r9
+	movl \offset+16(%rsp),%r9d
+	.endif
+	movl \offset+40(%rsp),%ecx
+	movl \offset+48(%rsp),%edx
+	movl \offset+56(%rsp),%esi
+	movl \offset+64(%rsp),%edi
+	movl %eax,%eax			/* zero extension */
+	.endm
+
+	.macro CFI_STARTPROC32 simple
+	CFI_STARTPROC	\simple
+	CFI_UNDEFINED	r8
+	CFI_UNDEFINED	r9
+	CFI_UNDEFINED	r10
+	CFI_UNDEFINED	r11
+	CFI_UNDEFINED	r12
+	CFI_UNDEFINED	r13
+	CFI_UNDEFINED	r14
+	CFI_UNDEFINED	r15
+	.endm
+
+#ifdef CONFIG_PARAVIRT
+ENTRY(native_usergs_sysret32)
+	swapgs
+	sysretl
+ENDPROC(native_usergs_sysret32)
+
+ENTRY(native_irq_enable_sysexit)
+	swapgs
+	sti
+	sysexit
+ENDPROC(native_irq_enable_sysexit)
+#endif
+
+/*
+ * 32bit SYSENTER instruction entry.
+ *
+ * Arguments:
+ * %eax	System call number.
+ * %ebx Arg1
+ * %ecx Arg2
+ * %edx Arg3
+ * %esi Arg4
+ * %edi Arg5
+ * %ebp user stack
+ * 0(%ebp) Arg6	
+ * 	
+ * Interrupts on.
+ *	
+ * This is purely a fast path. For anything complicated we use the int 0x80
+ * path below.	Set up a complete hardware stack frame to share code
+ * with the int 0x80 path.
+ */ 	
+ENTRY(ia32_sysenter_target)
+	CFI_STARTPROC32	simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA	rsp,SS+8-RIP+16
+	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+	CFI_REL_OFFSET	rsp,RSP-RIP+16
+	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
+	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
+	CFI_REL_OFFSET	rip,RIP-RIP+16
+	CFI_REL_OFFSET	r11,8
+	CFI_REL_OFFSET	rcx,0
+	movq	8(%rsp),%r11
+	CFI_RESTORE	r11
+	popq	%rcx
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE	rcx
+ 	movl	%ebp,%ebp		/* zero extension */
+	movl	%eax,%eax
+	movl	48-THREAD_SIZE+TI_sysenter_return(%rsp),%r10d
+	movl	$__USER32_DS,40(%rsp)
+	movq	%rbp,32(%rsp)
+	movl	$__USER32_CS,16(%rsp)
+	movq	%r10,8(%rsp)
+	movq	%rax,(%rsp)
+	cld
+	SAVE_ARGS 0,0,1
+ 	/* no need to do an access_ok check here because rbp has been
+ 	   32bit zero extended */ 
+1:	movl	(%rbp),%ebp
+ 	.section __ex_table,"a"
+ 	.quad 1b,ia32_badarg
+ 	.previous	
+	GET_THREAD_INFO(%r10)
+	orl    $TS_COMPAT,TI_status(%r10)
+	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+	jnz  sysenter_tracesys
+	cmpq	$(IA32_NR_syscalls-1),%rax
+	ja	ia32_badsys
+sysenter_do_call:
+	IA32_ARG_FIXUP
+sysenter_dispatch:
+	call	*ia32_sys_call_table(,%rax,8)
+	movq	%rax,RAX-ARGOFFSET(%rsp)
+	GET_THREAD_INFO(%r10)
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	testl	$_TIF_ALLWORK_MASK,TI_flags(%r10)
+	jnz	sysexit_audit
+	jmp	ia32_ret_from_sys_call
+
+#ifdef CONFIG_AUDITSYSCALL
+	.macro auditsys_entry_common
+	movl %esi,%r9d			/* 6th arg: 4th syscall arg */
+	movl %edx,%r8d			/* 5th arg: 3rd syscall arg */
+	/* (already in %ecx)		   4th arg: 2nd syscall arg */
+	movl %ebx,%edx			/* 3rd arg: 1st syscall arg */
+	movl %eax,%esi			/* 2nd arg: syscall number */
+	movl $AUDIT_ARCH_I386,%edi	/* 1st arg: audit arch */
+	call audit_syscall_entry
+	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall number */
+	cmpq $(IA32_NR_syscalls-1),%rax
+	ja ia32_badsys
+	movl %ebx,%edi			/* reload 1st syscall arg */
+	movl RCX-ARGOFFSET(%rsp),%esi	/* reload 2nd syscall arg */
+	movl RDX-ARGOFFSET(%rsp),%edx	/* reload 3rd syscall arg */
+	movl RSI-ARGOFFSET(%rsp),%ecx	/* reload 4th syscall arg */
+	movl RDI-ARGOFFSET(%rsp),%r8d	/* reload 5th syscall arg */
+	.endm
+
+	.macro auditsys_exit exit
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+	jnz ia32_ret_from_sys_call
+	TRACE_IRQS_ON
+	ENABLE_INTERRUPTS(CLBR_NONE)
+	movl %eax,%esi		/* second arg, syscall return value */
+	cmpl $0,%eax		/* is it < 0? */
+	setl %al		/* 1 if so, 0 if not */
+	movzbl %al,%edi		/* zero-extend that into %edi */
+	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
+	call audit_syscall_exit
+	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
+	CLEAR_RREGS -ARGOFFSET
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	TRACE_IRQS_OFF
+	jmp int_with_check
+	.endm
+
+sysenter_auditsys:
+	auditsys_entry_common
+	movl %ebp,%r9d			/* reload 6th syscall arg */
+	jmp sysenter_dispatch
+
+sysexit_audit:
+	auditsys_exit sysexit_from_sys_call
+#endif
+
+sysenter_tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+	jz	sysenter_auditsys
+#endif
+	SAVE_REST
+	CLEAR_RREGS
+	movq	$-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
+	movq	%rsp,%rdi        /* &pt_regs -> arg1 */
+	call	syscall_trace_enter
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	RESTORE_REST
+	cmpq	$(IA32_NR_syscalls-1),%rax
+	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
+	jmp	sysenter_do_call
+	CFI_ENDPROC
+ENDPROC(ia32_sysenter_target)
+
+/*
+ * 32bit SYSCALL instruction entry.
+ *
+ * Arguments:
+ * %eax	System call number.
+ * %ebx Arg1
+ * %ecx return EIP 
+ * %edx Arg3
+ * %esi Arg4
+ * %edi Arg5
+ * %ebp Arg2    [note: not saved in the stack frame, should not be touched]
+ * %esp user stack 
+ * 0(%esp) Arg6
+ * 	
+ * Interrupts on.
+ *	
+ * This is purely a fast path. For anything complicated we use the int 0x80
+ * path below.	Set up a complete hardware stack frame to share code
+ * with the int 0x80 path.	
+ */ 	
+ENTRY(ia32_cstar_target)
+	CFI_STARTPROC32	simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA	rsp,SS+8-RIP+16
+	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+	CFI_REL_OFFSET	rsp,RSP-RIP+16
+	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
+	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
+	CFI_REL_OFFSET	rip,RIP-RIP+16
+	movl 	%eax,%eax	/* zero extension */
+	movl	RSP-RIP+16(%rsp),%r8d
+	SAVE_ARGS -8,1,1
+	movq	%rax,ORIG_RAX-ARGOFFSET(%rsp)
+	movq	%rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
+	movl	%ebp,%ecx
+	movl	$__USER32_CS,CS-ARGOFFSET(%rsp)
+	movl	$__USER32_DS,SS-ARGOFFSET(%rsp)
+	/* no need to do an access_ok check here because r8 has been
+	   32bit zero extended */ 
+	/* hardware stack frame is complete now */	
+1:	movl	(%r8),%r9d
+	.section __ex_table,"a"
+	.quad 1b,ia32_badarg
+	.previous	
+	GET_THREAD_INFO(%r10)
+	orl   $TS_COMPAT,TI_status(%r10)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+	jnz   cstar_tracesys
+	cmpq $IA32_NR_syscalls-1,%rax
+	ja  ia32_badsys
+cstar_do_call:
+	IA32_ARG_FIXUP 1
+cstar_dispatch:
+	call *ia32_sys_call_table(,%rax,8)
+	movq %rax,RAX-ARGOFFSET(%rsp)
+	GET_THREAD_INFO(%r10)
+	DISABLE_INTERRUPTS(CLBR_NONE)
+	testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
+	jnz sysretl_audit
+	jmp ia32_ret_from_sys_call
+	
+#ifdef CONFIG_AUDITSYSCALL
+cstar_auditsys:
+	movl %r9d,R9-ARGOFFSET(%rsp)	/* register to be clobbered by call */
+	auditsys_entry_common
+	movl R9-ARGOFFSET(%rsp),%r9d	/* reload 6th syscall arg */
+	jmp cstar_dispatch
+
+sysretl_audit:
+	auditsys_exit sysretl_from_sys_call
+#endif
+
+cstar_tracesys:
+#ifdef CONFIG_AUDITSYSCALL
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10)
+	jz cstar_auditsys
+#endif
+	xchgl %r9d,%ebp
+	SAVE_REST
+	CLEAR_RREGS 0, r9
+	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+	call syscall_trace_enter
+	LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
+	RESTORE_REST
+	xchgl %ebp,%r9d
+	cmpq $(IA32_NR_syscalls-1),%rax
+	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
+	jmp cstar_do_call
+END(ia32_cstar_target)
+				
+ia32_badarg:
+	movq $-EFAULT,%rax
+	jmp ia32_sysret
+	CFI_ENDPROC
+
+/* 
+ * Emulated IA32 system calls via int 0x80. 
+ *
+ * Arguments:	 
+ * %eax	System call number.
+ * %ebx Arg1
+ * %ecx Arg2
+ * %edx Arg3
+ * %esi Arg4
+ * %edi Arg5
+ * %ebp Arg6    [note: not saved in the stack frame, should not be touched]
+ *
+ * Notes:
+ * Uses the same stack frame as the x86-64 version.	
+ * All registers except %eax must be saved (but ptrace may violate that)
+ * Arguments are zero extended. For system calls that want sign extension and
+ * take long arguments a wrapper is needed. Most calls can just be called
+ * directly.
+ * Assumes it is only called from user space and entered with interrupts on.
+ */ 				
+
+ENTRY(ia32_syscall)
+	CFI_STARTPROC32	simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA	rsp,SS+8-RIP+16
+	/*CFI_REL_OFFSET	ss,SS-RIP+16*/
+	CFI_REL_OFFSET	rsp,RSP-RIP+16
+	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP+16*/
+	/*CFI_REL_OFFSET	cs,CS-RIP+16*/
+	CFI_REL_OFFSET	rip,RIP-RIP+16
+	CFI_REL_OFFSET	r11,8
+	CFI_REL_OFFSET	rcx,0
+	movq 8(%rsp),%r11
+	CFI_RESTORE	r11
+	popq %rcx
+	CFI_ADJUST_CFA_OFFSET -8
+	CFI_RESTORE	rcx
+	movl %eax,%eax
+	movq %rax,(%rsp)
+	cld
+	/* note the registers are not zero extended to the sf.
+	   this could be a problem. */
+	SAVE_ARGS 0,0,1
+	GET_THREAD_INFO(%r10)
+	orl   $TS_COMPAT,TI_status(%r10)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
+	jnz ia32_tracesys
+	cmpq $(IA32_NR_syscalls-1),%rax
+	ja ia32_badsys
+ia32_do_call:
+	IA32_ARG_FIXUP
+	call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
+ia32_sysret:
+	movq %rax,RAX-ARGOFFSET(%rsp)
+ia32_ret_from_sys_call:
+	CLEAR_RREGS -ARGOFFSET
+	jmp int_ret_from_sys_call 
+
+ia32_tracesys:			 
+	SAVE_REST
+	CLEAR_RREGS
+	movq $-ENOSYS,RAX(%rsp)	/* ptrace can change this for a bad syscall */
+	movq %rsp,%rdi        /* &pt_regs -> arg1 */
+	call syscall_trace_enter
+	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	RESTORE_REST
+	cmpq $(IA32_NR_syscalls-1),%rax
+	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
+	jmp ia32_do_call
+END(ia32_syscall)
+
+ia32_badsys:
+	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
+	movq $-ENOSYS,%rax
+	jmp ia32_sysret
+
+quiet_ni_syscall:
+	movq $-ENOSYS,%rax
+	ret
+	CFI_ENDPROC
+	
+	.macro PTREGSCALL label, func, arg
+	.globl \label
+\label:
+	leaq \func(%rip),%rax
+	leaq -ARGOFFSET+8(%rsp),\arg	/* 8 for return address */
+	jmp  ia32_ptregs_common	
+	.endm
+
+	CFI_STARTPROC32
+
+	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
+	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
+	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
+	PTREGSCALL stub32_execve, sys32_execve, %rcx
+	PTREGSCALL stub32_fork, sys_fork, %rdi
+	PTREGSCALL stub32_clone, sys32_clone, %rdx
+	PTREGSCALL stub32_vfork, sys_vfork, %rdi
+	PTREGSCALL stub32_iopl, sys_iopl, %rsi
+
+ENTRY(ia32_ptregs_common)
+	popq %r11
+	CFI_ENDPROC
+	CFI_STARTPROC32	simple
+	CFI_SIGNAL_FRAME
+	CFI_DEF_CFA	rsp,SS+8-ARGOFFSET
+	CFI_REL_OFFSET	rax,RAX-ARGOFFSET
+	CFI_REL_OFFSET	rcx,RCX-ARGOFFSET
+	CFI_REL_OFFSET	rdx,RDX-ARGOFFSET
+	CFI_REL_OFFSET	rsi,RSI-ARGOFFSET
+	CFI_REL_OFFSET	rdi,RDI-ARGOFFSET
+	CFI_REL_OFFSET	rip,RIP-ARGOFFSET
+/*	CFI_REL_OFFSET	cs,CS-ARGOFFSET*/
+/*	CFI_REL_OFFSET	rflags,EFLAGS-ARGOFFSET*/
+	CFI_REL_OFFSET	rsp,RSP-ARGOFFSET
+/*	CFI_REL_OFFSET	ss,SS-ARGOFFSET*/
+	SAVE_REST
+	call *%rax
+	RESTORE_REST
+	jmp  ia32_sysret	/* misbalances the return cache */
+	CFI_ENDPROC
+END(ia32_ptregs_common)
+
+	.section .rodata,"a"
+	.align 8
+ia32_sys_call_table:
+	.quad sys_restart_syscall
+	.quad sys_exit
+	.quad stub32_fork
+	.quad sys_read
+	.quad sys_write
+	.quad compat_sys_open		/* 5 */
+	.quad sys_close
+	.quad sys32_waitpid
+	.quad sys_creat
+	.quad sys_link
+	.quad sys_unlink		/* 10 */
+	.quad stub32_execve
+	.quad sys_chdir
+	.quad compat_sys_time
+	.quad sys_mknod
+	.quad sys_chmod		/* 15 */
+	.quad sys_lchown16
+	.quad quiet_ni_syscall			/* old break syscall holder */
+	.quad sys_stat
+	.quad sys32_lseek
+	.quad sys_getpid		/* 20 */
+	.quad compat_sys_mount	/* mount  */
+	.quad sys_oldumount	/* old_umount  */
+	.quad sys_setuid16
+	.quad sys_getuid16
+	.quad compat_sys_stime	/* stime */		/* 25 */
+	.quad compat_sys_ptrace	/* ptrace */
+	.quad sys_alarm
+	.quad sys_fstat	/* (old)fstat */
+	.quad sys_pause
+	.quad compat_sys_utime	/* 30 */
+	.quad quiet_ni_syscall	/* old stty syscall holder */
+	.quad quiet_ni_syscall	/* old gtty syscall holder */
+	.quad sys_access
+	.quad sys_nice	
+	.quad quiet_ni_syscall	/* 35 */	/* old ftime syscall holder */
+	.quad sys_sync
+	.quad sys32_kill
+	.quad sys_rename
+	.quad sys_mkdir
+	.quad sys_rmdir		/* 40 */
+	.quad sys_dup
+	.quad sys_pipe
+	.quad compat_sys_times
+	.quad quiet_ni_syscall			/* old prof syscall holder */
+	.quad sys_brk		/* 45 */
+	.quad sys_setgid16
+	.quad sys_getgid16
+	.quad sys_signal
+	.quad sys_geteuid16
+	.quad sys_getegid16	/* 50 */
+	.quad sys_acct
+	.quad sys_umount			/* new_umount */
+	.quad quiet_ni_syscall			/* old lock syscall holder */
+	.quad compat_sys_ioctl
+	.quad compat_sys_fcntl64		/* 55 */
+	.quad quiet_ni_syscall			/* old mpx syscall holder */
+	.quad sys_setpgid
+	.quad quiet_ni_syscall			/* old ulimit syscall holder */
+	.quad sys32_olduname
+	.quad sys_umask		/* 60 */
+	.quad sys_chroot
+	.quad compat_sys_ustat
+	.quad sys_dup2
+	.quad sys_getppid
+	.quad sys_getpgrp		/* 65 */
+	.quad sys_setsid
+	.quad sys32_sigaction
+	.quad sys_sgetmask
+	.quad sys_ssetmask
+	.quad sys_setreuid16	/* 70 */
+	.quad sys_setregid16
+	.quad sys32_sigsuspend
+	.quad compat_sys_sigpending
+	.quad sys_sethostname
+	.quad compat_sys_setrlimit	/* 75 */
+	.quad compat_sys_old_getrlimit	/* old_getrlimit */
+	.quad compat_sys_getrusage
+	.quad compat_sys_gettimeofday
+	.quad compat_sys_settimeofday
+	.quad sys_getgroups16	/* 80 */
+	.quad sys_setgroups16
+	.quad sys32_old_select
+	.quad sys_symlink
+	.quad sys_lstat
+	.quad sys_readlink		/* 85 */
+	.quad sys_uselib
+	.quad sys_swapon
+	.quad sys_reboot
+	.quad compat_sys_old_readdir
+	.quad sys32_mmap		/* 90 */
+	.quad sys_munmap
+	.quad sys_truncate
+	.quad sys_ftruncate
+	.quad sys_fchmod
+	.quad sys_fchown16		/* 95 */
+	.quad sys_getpriority
+	.quad sys_setpriority
+	.quad quiet_ni_syscall			/* old profil syscall holder */
+	.quad compat_sys_statfs
+	.quad compat_sys_fstatfs		/* 100 */
+	.quad sys_ioperm
+	.quad compat_sys_socketcall
+	.quad sys_syslog
+	.quad compat_sys_setitimer
+	.quad compat_sys_getitimer	/* 105 */
+	.quad compat_sys_newstat
+	.quad compat_sys_newlstat
+	.quad compat_sys_newfstat
+	.quad sys32_uname
+	.quad stub32_iopl		/* 110 */
+	.quad sys_vhangup
+	.quad quiet_ni_syscall	/* old "idle" system call */
+	.quad sys32_vm86_warning	/* vm86old */ 
+	.quad compat_sys_wait4
+	.quad sys_swapoff		/* 115 */
+	.quad compat_sys_sysinfo
+	.quad sys32_ipc
+	.quad sys_fsync
+	.quad stub32_sigreturn
+	.quad stub32_clone		/* 120 */
+	.quad sys_setdomainname
+	.quad sys_uname
+	.quad sys_modify_ldt
+	.quad compat_sys_adjtimex
+	.quad sys32_mprotect		/* 125 */
+	.quad compat_sys_sigprocmask
+	.quad quiet_ni_syscall		/* create_module */
+	.quad sys_init_module
+	.quad sys_delete_module
+	.quad quiet_ni_syscall		/* 130  get_kernel_syms */
+	.quad sys32_quotactl
+	.quad sys_getpgid
+	.quad sys_fchdir
+	.quad quiet_ni_syscall	/* bdflush */
+	.quad sys_sysfs		/* 135 */
+	.quad sys_personality
+	.quad quiet_ni_syscall	/* for afs_syscall */
+	.quad sys_setfsuid16
+	.quad sys_setfsgid16
+	.quad sys_llseek		/* 140 */
+	.quad compat_sys_getdents
+	.quad compat_sys_select
+	.quad sys_flock
+	.quad sys_msync
+	.quad compat_sys_readv		/* 145 */
+	.quad compat_sys_writev
+	.quad sys_getsid
+	.quad sys_fdatasync
+	.quad sys32_sysctl	/* sysctl */
+	.quad sys_mlock		/* 150 */
+	.quad sys_munlock
+	.quad sys_mlockall
+	.quad sys_munlockall
+	.quad sys_sched_setparam
+	.quad sys_sched_getparam   /* 155 */
+	.quad sys_sched_setscheduler
+	.quad sys_sched_getscheduler
+	.quad sys_sched_yield
+	.quad sys_sched_get_priority_max
+	.quad sys_sched_get_priority_min  /* 160 */
+	.quad sys32_sched_rr_get_interval
+	.quad compat_sys_nanosleep
+	.quad sys_mremap
+	.quad sys_setresuid16
+	.quad sys_getresuid16	/* 165 */
+	.quad sys32_vm86_warning	/* vm86 */ 
+	.quad quiet_ni_syscall	/* query_module */
+	.quad sys_poll
+	.quad compat_sys_nfsservctl
+	.quad sys_setresgid16	/* 170 */
+	.quad sys_getresgid16
+	.quad sys_prctl
+	.quad stub32_rt_sigreturn
+	.quad sys32_rt_sigaction
+	.quad sys32_rt_sigprocmask	/* 175 */
+	.quad sys32_rt_sigpending
+	.quad compat_sys_rt_sigtimedwait
+	.quad sys32_rt_sigqueueinfo
+	.quad sys_rt_sigsuspend
+	.quad sys32_pread		/* 180 */
+	.quad sys32_pwrite
+	.quad sys_chown16
+	.quad sys_getcwd
+	.quad sys_capget
+	.quad sys_capset
+	.quad stub32_sigaltstack
+	.quad sys32_sendfile
+	.quad quiet_ni_syscall		/* streams1 */
+	.quad quiet_ni_syscall		/* streams2 */
+	.quad stub32_vfork            /* 190 */
+	.quad compat_sys_getrlimit
+	.quad sys_mmap_pgoff
+	.quad sys32_truncate64
+	.quad sys32_ftruncate64
+	.quad sys32_stat64		/* 195 */
+	.quad sys32_lstat64
+	.quad sys32_fstat64
+	.quad sys_lchown
+	.quad sys_getuid
+	.quad sys_getgid		/* 200 */
+	.quad sys_geteuid
+	.quad sys_getegid
+	.quad sys_setreuid
+	.quad sys_setregid
+	.quad sys_getgroups	/* 205 */
+	.quad sys_setgroups
+	.quad sys_fchown
+	.quad sys_setresuid
+	.quad sys_getresuid
+	.quad sys_setresgid	/* 210 */
+	.quad sys_getresgid
+	.quad sys_chown
+	.quad sys_setuid
+	.quad sys_setgid
+	.quad sys_setfsuid		/* 215 */
+	.quad sys_setfsgid
+	.quad sys_pivot_root
+	.quad sys_mincore
+	.quad sys_madvise
+	.quad compat_sys_getdents64	/* 220 getdents64 */
+	.quad compat_sys_fcntl64	
+	.quad quiet_ni_syscall		/* tux */
+	.quad quiet_ni_syscall    	/* security */
+	.quad sys_gettid	
+	.quad sys32_readahead	/* 225 */
+	.quad sys_setxattr
+	.quad sys_lsetxattr
+	.quad sys_fsetxattr
+	.quad sys_getxattr
+	.quad sys_lgetxattr	/* 230 */
+	.quad sys_fgetxattr
+	.quad sys_listxattr
+	.quad sys_llistxattr
+	.quad sys_flistxattr
+	.quad sys_removexattr	/* 235 */
+	.quad sys_lremovexattr
+	.quad sys_fremovexattr
+	.quad sys_tkill
+	.quad sys_sendfile64 
+	.quad compat_sys_futex		/* 240 */
+	.quad compat_sys_sched_setaffinity
+	.quad compat_sys_sched_getaffinity
+	.quad sys_set_thread_area
+	.quad sys_get_thread_area
+	.quad compat_sys_io_setup	/* 245 */
+	.quad sys_io_destroy
+	.quad compat_sys_io_getevents
+	.quad compat_sys_io_submit
+	.quad sys_io_cancel
+	.quad sys32_fadvise64		/* 250 */
+	.quad quiet_ni_syscall 	/* free_huge_pages */
+	.quad sys_exit_group
+	.quad sys32_lookup_dcookie
+	.quad sys_epoll_create
+	.quad sys_epoll_ctl		/* 255 */
+	.quad sys_epoll_wait
+	.quad sys_remap_file_pages
+	.quad sys_set_tid_address
+	.quad compat_sys_timer_create
+	.quad compat_sys_timer_settime	/* 260 */
+	.quad compat_sys_timer_gettime
+	.quad sys_timer_getoverrun
+	.quad sys_timer_delete
+	.quad compat_sys_clock_settime
+	.quad compat_sys_clock_gettime	/* 265 */
+	.quad compat_sys_clock_getres
+	.quad compat_sys_clock_nanosleep
+	.quad compat_sys_statfs64
+	.quad compat_sys_fstatfs64
+	.quad sys_tgkill		/* 270 */
+	.quad compat_sys_utimes
+	.quad sys32_fadvise64_64
+	.quad quiet_ni_syscall	/* sys_vserver */
+	.quad sys_mbind
+	.quad compat_sys_get_mempolicy	/* 275 */
+	.quad sys_set_mempolicy
+	.quad compat_sys_mq_open
+	.quad sys_mq_unlink
+	.quad compat_sys_mq_timedsend
+	.quad compat_sys_mq_timedreceive	/* 280 */
+	.quad compat_sys_mq_notify
+	.quad compat_sys_mq_getsetattr
+	.quad compat_sys_kexec_load	/* reserved for kexec */
+	.quad compat_sys_waitid
+	.quad quiet_ni_syscall		/* 285: sys_altroot */
+	.quad sys_add_key
+	.quad sys_request_key
+	.quad sys_keyctl
+	.quad sys_ioprio_set
+	.quad sys_ioprio_get		/* 290 */
+	.quad sys_inotify_init
+	.quad sys_inotify_add_watch
+	.quad sys_inotify_rm_watch
+	.quad sys_migrate_pages
+	.quad compat_sys_openat		/* 295 */
+	.quad sys_mkdirat
+	.quad sys_mknodat
+	.quad sys_fchownat
+	.quad compat_sys_futimesat
+	.quad sys32_fstatat		/* 300 */
+	.quad sys_unlinkat
+	.quad sys_renameat
+	.quad sys_linkat
+	.quad sys_symlinkat
+	.quad sys_readlinkat		/* 305 */
+	.quad sys_fchmodat
+	.quad sys_faccessat
+	.quad compat_sys_pselect6
+	.quad compat_sys_ppoll
+	.quad sys_unshare		/* 310 */
+	.quad compat_sys_set_robust_list
+	.quad compat_sys_get_robust_list
+	.quad sys_splice
+	.quad sys32_sync_file_range
+	.quad sys_tee			/* 315 */
+	.quad compat_sys_vmsplice
+	.quad compat_sys_move_pages
+	.quad sys_getcpu
+	.quad sys_epoll_pwait
+	.quad compat_sys_utimensat	/* 320 */
+	.quad compat_sys_signalfd
+	.quad sys_timerfd_create
+	.quad sys_eventfd
+	.quad sys32_fallocate
+	.quad compat_sys_timerfd_settime	/* 325 */
+	.quad compat_sys_timerfd_gettime
+	.quad compat_sys_signalfd4
+	.quad sys_eventfd2
+	.quad sys_epoll_create1
+	.quad sys_dup3				/* 330 */
+	.quad sys_pipe2
+	.quad sys_inotify_init1
+	.quad compat_sys_preadv
+	.quad compat_sys_pwritev
+	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */
+	.quad sys_perf_event_open
+ia32_syscall_end:
--- linux-ec2-2.6.32.orig/arch/x86/ia32/ia32entry.S
+++ linux-ec2-2.6.32/arch/x86/ia32/ia32entry.S
@@ -50,7 +50,12 @@
 	/*
 	 * Reload arg registers from stack in case ptrace changed them.
 	 * We don't reload %eax because syscall_trace_enter() returned
-	 * the value it wants us to use in the table lookup.
+	 * the %rax value we should see.  Instead, we just truncate that
+	 * value to 32 bits again as we did on entry from user mode.
+	 * If it's a new value set by user_regset during entry tracing,
+	 * this matches the normal truncation of the user-mode value.
+	 * If it's -1 to make us punt the syscall, then (u32)-1 is still
+	 * an appropriately invalid value.
 	 */
 	.macro LOAD_ARGS32 offset, _r9=0
 	.if \_r9
@@ -60,6 +65,7 @@
 	movl \offset+48(%rsp),%edx
 	movl \offset+56(%rsp),%esi
 	movl \offset+64(%rsp),%edi
+	movl %eax,%eax			/* zero extension */
 	.endm
 	
 	.macro CFI_STARTPROC32 simple
@@ -153,7 +159,7 @@
 	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	CFI_REMEMBER_STATE
 	jnz  sysenter_tracesys
-	cmpl	$(IA32_NR_syscalls-1),%eax
+	cmpq	$(IA32_NR_syscalls-1),%rax
 	ja	ia32_badsys
 sysenter_do_call:
 	IA32_ARG_FIXUP
@@ -195,7 +201,7 @@
 	movl $AUDIT_ARCH_I386,%edi	/* 1st arg: audit arch */
 	call audit_syscall_entry
 	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall number */
-	cmpl $(IA32_NR_syscalls-1),%eax
+	cmpq $(IA32_NR_syscalls-1),%rax
 	ja ia32_badsys
 	movl %ebx,%edi			/* reload 1st syscall arg */
 	movl RCX-ARGOFFSET(%rsp),%esi	/* reload 2nd syscall arg */
@@ -248,7 +254,7 @@
 	call	syscall_trace_enter
 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
-	cmpl	$(IA32_NR_syscalls-1),%eax
+	cmpq	$(IA32_NR_syscalls-1),%rax
 	ja	int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
 	jmp	sysenter_do_call
 	CFI_ENDPROC
@@ -314,7 +320,7 @@
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	CFI_REMEMBER_STATE
 	jnz   cstar_tracesys
-	cmpl $IA32_NR_syscalls-1,%eax
+	cmpq $IA32_NR_syscalls-1,%rax
 	ja  ia32_badsys
 cstar_do_call:
 	IA32_ARG_FIXUP 1
@@ -367,7 +373,7 @@
 	LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	xchgl %ebp,%r9d
-	cmpl $(IA32_NR_syscalls-1),%eax
+	cmpq $(IA32_NR_syscalls-1),%rax
 	ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
 	jmp cstar_do_call
 END(ia32_cstar_target)
@@ -425,7 +431,7 @@
 	orl   $TS_COMPAT,TI_status(%r10)
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	jnz ia32_tracesys
-	cmpl $(IA32_NR_syscalls-1),%eax
+	cmpq $(IA32_NR_syscalls-1),%rax
 	ja ia32_badsys
 ia32_do_call:
 	IA32_ARG_FIXUP
@@ -444,7 +450,7 @@
 	call syscall_trace_enter
 	LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
-	cmpl $(IA32_NR_syscalls-1),%eax
+	cmpq $(IA32_NR_syscalls-1),%rax
 	ja  int_ret_from_sys_call	/* ia32_tracesys has set RAX(%rsp) */
 	jmp ia32_do_call
 END(ia32_syscall)
@@ -696,7 +702,7 @@
 	.quad quiet_ni_syscall		/* streams2 */
 	.quad stub32_vfork            /* 190 */
 	.quad compat_sys_getrlimit
-	.quad sys32_mmap2
+	.quad sys_mmap_pgoff
 	.quad sys32_truncate64
 	.quad sys32_ftruncate64
 	.quad sys32_stat64		/* 195 */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/pgtable_32.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/pgtable_32.h
@@ -27,6 +27,7 @@
 struct vm_area_struct;
 
 extern pgd_t swapper_pg_dir[1024];
+extern pgd_t trampoline_pg_dir[1024];
 
 static inline void pgtable_cache_init(void) { }
 static inline void check_pgt_cache(void) { }
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/cmpxchg_64.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/cmpxchg_64.h
@@ -8,13 +8,11 @@
 
 #define __xg(x) ((volatile long *)(x))
 
-static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile u64 *ptr, u64 val)
 {
 	*ptr = val;
 }
 
-#define _set_64bit set_64bit
-
 /*
  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
@@ -26,26 +24,26 @@
 	switch (size) {
 	case 1:
 		asm volatile("xchgb %b0,%1"
-			     : "=q" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=q" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 2:
 		asm volatile("xchgw %w0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 4:
 		asm volatile("xchgl %k0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 8:
 		asm volatile("xchgq %0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	}
@@ -66,27 +64,27 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile(LOCK_PREFIX "cmpxchgl %k1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgl %k2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 8:
-		asm volatile(LOCK_PREFIX "cmpxchgq %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgq %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -105,21 +103,27 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("lock; cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("lock; cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("lock; cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgl %k2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
+			     : "memory");
+		return prev;
+	case 8:
+		asm volatile("lock; cmpxchgq %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -133,27 +137,27 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("cmpxchgl %k1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgl %k2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 8:
-		asm volatile("cmpxchgq %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgq %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/acpi.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/acpi.h
@@ -30,6 +30,10 @@
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
 
+#ifdef CONFIG_XEN
+#include <xen/interface/platform.h>
+#endif
+
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
 
@@ -89,6 +93,7 @@
 extern int acpi_pci_disabled;
 extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
+extern int acpi_fix_pin2_polarity;
 
 extern u8 acpi_sci_flags;
 extern int acpi_sci_override_gsi;
@@ -120,6 +125,27 @@
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+#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 */
+
 /*
  * Check if the CPU can handle C2 and deeper
  */
@@ -152,7 +178,9 @@
 
 #endif /* !CONFIG_ACPI */
 
+#ifndef CONFIG_XEN
 #define ARCH_HAS_POWER_INIT	1
+#endif
 
 struct bootnode;
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/desc.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/desc.h
@@ -5,6 +5,7 @@
 #include <asm/ldt.h>
 #include <asm/mmu.h>
 #include <linux/smp.h>
+#include <linux/mm_types.h>
 
 static inline void fill_ldt(struct desc_struct *desc,
 			    const struct user_desc *info)
@@ -93,6 +94,9 @@
 
 #define load_TLS(t, cpu) native_load_tls(t, cpu)
 #define set_ldt native_set_ldt
+#ifdef CONFIG_X86_32
+#define load_user_cs_desc native_load_user_cs_desc
+#endif /*CONFIG_X86_32*/
 
 #define write_ldt_entry(dt, entry, desc)	\
 	native_write_ldt_entry(dt, entry, desc)
@@ -392,4 +396,25 @@
 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
 }
 
+#ifdef CONFIG_X86_32
+static inline void set_user_cs(struct desc_struct *desc, unsigned long limit)
+{
+	limit = (limit - 1) / PAGE_SIZE;
+	desc->a = limit & 0xffff;
+	desc->b = (limit & 0xf0000) | 0x00c0fb00;
+}
+
+static inline void native_load_user_cs_desc(int cpu, struct mm_struct *mm)
+{
+	get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs;
+}
+
+#define arch_add_exec_range arch_add_exec_range
+#define arch_remove_exec_range arch_remove_exec_range
+#define arch_flush_exec_range arch_flush_exec_range
+extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_flush_exec_range(struct mm_struct *mm);
+#endif /* CONFIG_X86_32 */
+
 #endif /* _ASM_X86_DESC_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/dma-mapping.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/dma-mapping.h
@@ -151,8 +151,6 @@
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
-	WARN_ON(irqs_disabled());       /* for portability */
-
 	if (dma_release_from_coherent(dev, get_order(size), vaddr))
 		return;
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/elf.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/elf.h
@@ -197,14 +197,8 @@
 	set_fs(USER_DS);				\
 } while (0)
 
-#define COMPAT_SET_PERSONALITY(ex)			\
-do {							\
-	if (test_thread_flag(TIF_IA32))			\
-		clear_thread_flag(TIF_ABI_PENDING);	\
-	else						\
-		set_thread_flag(TIF_ABI_PENDING);	\
-	current->personality |= force_personality32;	\
-} while (0)
+void set_personality_ia32(void);
+#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32()
 
 #define COMPAT_ELF_PLATFORM			("i686")
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/segment.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/segment.h
@@ -186,7 +186,9 @@
 #define __KERNEL_DS	(GDT_ENTRY_KERNEL_DS * 8)
 #define __USER_DS     (GDT_ENTRY_DEFAULT_USER_DS* 8 + 3)
 #define __USER_CS     (GDT_ENTRY_DEFAULT_USER_CS* 8 + 3)
-#ifndef CONFIG_PARAVIRT
+#if defined(CONFIG_X86_XEN)
+#define get_kernel_rpl()  (xen_feature(XENFEAT_supervisor_mode_kernel)?0:1)
+#elif !defined(CONFIG_PARAVIRT)
 #define get_kernel_rpl()  0
 #endif
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/sys_ia32.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/sys_ia32.h
@@ -62,9 +62,6 @@
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long,
-			    unsigned long, unsigned long, unsigned long);
-
 struct oldold_utsname;
 struct old_utsname;
 asmlinkage long sys32_olduname(struct oldold_utsname __user *);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/time.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/time.h
@@ -7,4 +7,11 @@
 
 extern void time_init(void);
 
+#ifdef CONFIG_XEN
+struct timespec;
+extern int xen_independent_wallclock(void);
+extern void xen_read_persistent_clock(struct timespec *);
+extern int xen_update_persistent_clock(void);
+#endif
+
 #endif /* _ASM_X86_TIME_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/mce.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/mce.h
@@ -67,6 +67,8 @@
 	__u32 socketid;	/* CPU socket ID */
 	__u32 apicid;	/* CPU initial apic ID */
 	__u64 mcgcap;	/* MCGCAP MSR: machine check capabilities of CPU */
+	__u64 aux0;	/* model specific */
+	__u64 aux1;	/* model specific */
 };
 
 /*
@@ -214,5 +216,11 @@
 
 void mce_log_therm_throt_event(__u64 status);
 
+#ifdef CONFIG_X86_THERMAL_VECTOR
+extern void mcheck_intel_therm_init(void);
+#else
+static inline void mcheck_intel_therm_init(void) { }
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/pvclock.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/pvclock.h
@@ -10,5 +10,44 @@
 void pvclock_read_wallclock(struct pvclock_wall_clock *wall,
 			    struct pvclock_vcpu_time_info *vcpu,
 			    struct timespec *ts);
+void pvclock_resume(void);
+
+/*
+ * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
+ * yielding a 64-bit result.
+ */
+static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
+{
+	u64 product;
+#ifdef __i386__
+	u32 tmp1, tmp2;
+#endif
+
+	if (shift < 0)
+		delta >>= -shift;
+	else
+		delta <<= shift;
+
+#ifdef __i386__
+	__asm__ (
+		"mul  %5       ; "
+		"mov  %4,%%eax ; "
+		"mov  %%edx,%4 ; "
+		"mul  %5       ; "
+		"xor  %5,%5    ; "
+		"add  %4,%%eax ; "
+		"adc  %5,%%edx ; "
+		: "=A" (product), "=r" (tmp1), "=r" (tmp2)
+		: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
+#elif defined(__x86_64__)
+	__asm__ (
+		"mul %%rdx ; shrd $32,%%rdx,%%rax"
+		: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
+#else
+#error implement me!
+#endif
+
+	return product;
+}
 
 #endif /* _ASM_X86_PVCLOCK_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/cmpxchg_32.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/cmpxchg_32.h
@@ -17,60 +17,33 @@
 #define __xg(x) ((struct __xchg_dummy *)(x))
 
 /*
- * The semantics of XCHGCMP8B are a bit strange, this is why
- * there is a loop and the loading of %%eax and %%edx has to
- * be inside. This inlines well in most cases, the cached
- * cost is around ~38 cycles. (in the future we might want
- * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
- * might have an implicit FPU-save as a cost, so it's not
- * clear which path to go.)
+ * CMPXCHG8B only writes to the target if we had the previous
+ * value in registers, otherwise it acts as a read and gives us the
+ * "new previous" value.  That is why there is a loop.  Preloading
+ * EDX:EAX is a performance optimization: in the common case it means
+ * we need only one locked operation.
  *
- * cmpxchg8b must be used with the lock prefix here to allow
- * the instruction to be executed atomically, see page 3-102
- * of the instruction set reference 24319102.pdf. We need
- * the reader side to see the coherent 64bit value.
+ * A SIMD/3DNOW!/MMX/FPU 64-bit store here would require at the very
+ * least an FPU save and/or %cr0.ts manipulation.
+ *
+ * cmpxchg8b must be used with the lock prefix here to allow the
+ * instruction to be executed atomically.  We need to have the reader
+ * side to see the coherent 64bit value.
  */
-static inline void __set_64bit(unsigned long long *ptr,
-			       unsigned int low, unsigned int high)
+static inline void set_64bit(volatile u64 *ptr, u64 value)
 {
+	u32 low  = value;
+	u32 high = value >> 32;
+	u64 prev = *ptr;
+
 	asm volatile("\n1:\t"
-		     "movl (%0), %%eax\n\t"
-		     "movl 4(%0), %%edx\n\t"
-		     LOCK_PREFIX "cmpxchg8b (%0)\n\t"
+		     LOCK_PREFIX "cmpxchg8b %0\n\t"
 		     "jnz 1b"
-		     : /* no outputs */
-		     : "D"(ptr),
-		       "b"(low),
-		       "c"(high)
-		     : "ax", "dx", "memory");
-}
-
-static inline void __set_64bit_constant(unsigned long long *ptr,
-					unsigned long long value)
-{
-	__set_64bit(ptr, (unsigned int)value, (unsigned int)(value >> 32));
-}
-
-#define ll_low(x)	*(((unsigned int *)&(x)) + 0)
-#define ll_high(x)	*(((unsigned int *)&(x)) + 1)
-
-static inline void __set_64bit_var(unsigned long long *ptr,
-				   unsigned long long value)
-{
-	__set_64bit(ptr, ll_low(value), ll_high(value));
+		     : "=m" (*ptr), "+A" (prev)
+		     : "b" (low), "c" (high)
+		     : "memory");
 }
 
-#define set_64bit(ptr, value)			\
-	(__builtin_constant_p((value))		\
-	 ? __set_64bit_constant((ptr), (value))	\
-	 : __set_64bit_var((ptr), (value)))
-
-#define _set_64bit(ptr, value)						\
-	(__builtin_constant_p(value)					\
-	 ? __set_64bit(ptr, (unsigned int)(value),			\
-		       (unsigned int)((value) >> 32))			\
-	 : __set_64bit(ptr, ll_low((value)), ll_high((value))))
-
 /*
  * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
@@ -82,20 +55,20 @@
 	switch (size) {
 	case 1:
 		asm volatile("xchgb %b0,%1"
-			     : "=q" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=q" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 2:
 		asm volatile("xchgw %w0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	case 4:
 		asm volatile("xchgl %0,%1"
-			     : "=r" (x)
-			     : "m" (*__xg(ptr)), "0" (x)
+			     : "=r" (x), "+m" (*__xg(ptr))
+			     : "0" (x)
 			     : "memory");
 		break;
 	}
@@ -139,21 +112,21 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile(LOCK_PREFIX "cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile(LOCK_PREFIX "cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile(LOCK_PREFIX "cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile(LOCK_PREFIX "cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -172,21 +145,21 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("lock; cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("lock; cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("lock; cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("lock; cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -200,21 +173,21 @@
 	unsigned long prev;
 	switch (size) {
 	case 1:
-		asm volatile("cmpxchgb %b1,%2"
-			     : "=a"(prev)
-			     : "q"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgb %b2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "q"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 2:
-		asm volatile("cmpxchgw %w1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgw %w2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	case 4:
-		asm volatile("cmpxchgl %1,%2"
-			     : "=a"(prev)
-			     : "r"(new), "m"(*__xg(ptr)), "0"(old)
+		asm volatile("cmpxchgl %2,%1"
+			     : "=a"(prev), "+m"(*__xg(ptr))
+			     : "r"(new), "0"(old)
 			     : "memory");
 		return prev;
 	}
@@ -226,11 +199,10 @@
 					     unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile(LOCK_PREFIX "cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile(LOCK_PREFIX "cmpxchg8b %1"
+		     : "=A"(prev), "+m" (*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
@@ -241,11 +213,10 @@
 						   unsigned long long new)
 {
 	unsigned long long prev;
-	asm volatile("cmpxchg8b %3"
-		     : "=A"(prev)
+	asm volatile("cmpxchg8b %1"
+		     : "=A"(prev), "+m"(*__xg(ptr))
 		     : "b"((unsigned long)new),
 		       "c"((unsigned long)(new >> 32)),
-		       "m"(*__xg(ptr)),
 		       "0"(old)
 		     : "memory");
 	return prev;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/syscalls.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/syscalls.h
@@ -55,8 +55,6 @@
 struct oldold_utsname;
 struct old_utsname;
 
-asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
-			  unsigned long, unsigned long, unsigned long);
 asmlinkage int old_mmap(struct mmap_arg_struct __user *);
 asmlinkage int old_select(struct sel_arg_struct __user *);
 asmlinkage int sys_ipc(uint, int, int, int, void __user *, long);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/k8.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/k8.h
@@ -13,11 +13,16 @@
 extern int k8_scan_nodes(unsigned long start, unsigned long end);
 
 #ifdef CONFIG_K8_NB
+extern int num_k8_northbridges;
+
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
 	return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
 }
+
 #else
+#define num_k8_northbridges 0
+
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
 	return NULL;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/msr.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/msr.h
@@ -27,6 +27,18 @@
 	};
 };
 
+struct msr_info {
+	u32 msr_no;
+	struct msr reg;
+	struct msr *msrs;
+	int err;
+};
+
+struct msr_regs_info {
+	u32 *regs;
+	int err;
+};
+
 static inline unsigned long long native_read_tscp(unsigned int *aux)
 {
 	unsigned long low, high;
@@ -244,11 +256,14 @@
 
 #define write_rdtscp_aux(val) wrmsr(0xc0000103, (val), 0)
 
+struct msr *msrs_alloc(void);
+void msrs_free(struct msr *msrs);
+
 #ifdef CONFIG_SMP
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
-void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs);
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
 int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
 int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/amd_iommu.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/amd_iommu.h
@@ -32,6 +32,7 @@
 extern void amd_iommu_flush_all_devices(void);
 extern void amd_iommu_shutdown(void);
 extern void amd_iommu_apply_erratum_63(u16 devid);
+extern void amd_iommu_init_api(void);
 #else
 static inline int amd_iommu_init(void) { return -ENODEV; }
 static inline void amd_iommu_detect(void) { }
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/nmi.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/nmi.h
@@ -5,8 +5,6 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#ifdef ARCH_HAS_NMI_WATCHDOG
-
 /**
  * do_nmi_callback
  *
@@ -16,6 +14,11 @@
 int do_nmi_callback(struct pt_regs *regs, int cpu);
 
 extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
+
+extern int unknown_nmi_panic;
+
+#ifdef ARCH_HAS_NMI_WATCHDOG
+
 extern int check_nmi_watchdog(void);
 extern int nmi_watchdog_enabled;
 extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
@@ -42,7 +45,6 @@
 struct ctl_table;
 extern int proc_nmi_enabled(struct ctl_table *, int ,
 			void __user *, size_t *, loff_t *);
-extern int unknown_nmi_panic;
 
 void arch_trigger_all_cpu_backtrace(void);
 #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
@@ -65,7 +67,6 @@
 	 */
 	return nmi_watchdog & (NMI_LOCAL_APIC | NMI_IO_APIC);
 }
-#endif
 
 void lapic_watchdog_stop(void);
 int lapic_watchdog_init(unsigned nmi_hz);
@@ -73,6 +74,9 @@
 unsigned lapic_adjust_nmi_hz(unsigned hz);
 void disable_lapic_nmi_watchdog(void);
 void enable_lapic_nmi_watchdog(void);
+
+#endif
+
 void stop_nmi(void);
 void restart_nmi(void);
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/system.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/system.h
@@ -449,7 +449,7 @@
  *
  * (Could use an alternative three way for this if there was one.)
  */
-static inline void rdtsc_barrier(void)
+static __always_inline void rdtsc_barrier(void)
 {
 	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
 	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/paravirt_types.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/paravirt_types.h
@@ -118,6 +118,9 @@
 	void (*store_gdt)(struct desc_ptr *);
 	void (*store_idt)(struct desc_ptr *);
 	void (*set_ldt)(const void *desc, unsigned entries);
+#ifdef CONFIG_X86_32
+	void (*load_user_cs_desc)(int cpu, struct mm_struct *mm);
+#endif /*CONFIG_X86_32*/
 	unsigned long (*store_tr)(void);
 	void (*load_tls)(struct thread_struct *t, unsigned int cpu);
 #ifdef CONFIG_X86_64
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/mmu_context.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/mmu_context.h
@@ -36,8 +36,6 @@
 	unsigned cpu = smp_processor_id();
 
 	if (likely(prev != next)) {
-		/* stop flush ipis for the previous mm */
-		cpumask_clear_cpu(cpu, mm_cpumask(prev));
 #ifdef CONFIG_SMP
 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
 		percpu_write(cpu_tlbstate.active_mm, next);
@@ -47,6 +45,9 @@
 		/* Re-load page tables */
 		load_cr3(next->pgd);
 
+		/* stop flush ipis for the previous mm */
+		cpumask_clear_cpu(cpu, mm_cpumask(prev));
+
 		/*
 		 * load the LDT, if the LDT is different:
 		 */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/page_64_types.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/page_64_types.h
@@ -69,7 +69,15 @@
 #endif	/* !__ASSEMBLY__ */
 
 #ifdef CONFIG_FLATMEM
+/*
+ * While max_pfn is not exported, max_mapnr never gets initialized for non-Xen
+ * other than for hotplugged memory.
+ */
+#ifndef CONFIG_XEN
 #define pfn_valid(pfn)          ((pfn) < max_pfn)
+#else
+#define pfn_valid(pfn)          ((pfn) < max_mapnr)
+#endif
 #endif
 
 #endif /* _ASM_X86_PAGE_64_DEFS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/tsc.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/tsc.h
@@ -59,5 +59,7 @@
 extern void check_tsc_sync_target(void);
 
 extern int notsc_setup(char *);
+extern void save_sched_clock_state(void);
+extern void restore_sched_clock_state(void);
 
 #endif /* _ASM_X86_TSC_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/ptrace.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/ptrace.h
@@ -224,7 +224,9 @@
 extern void user_disable_single_step(struct task_struct *);
 
 extern void user_enable_block_step(struct task_struct *);
-#ifdef CONFIG_X86_DEBUGCTLMSR
+#if defined(CONFIG_XEN)
+#define arch_has_block_step()	(0)
+#elif defined(CONFIG_X86_DEBUGCTLMSR)
 #define arch_has_block_step()	(1)
 #else
 #define arch_has_block_step()	(boot_cpu_data.x86 >= 6)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/vmx.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/vmx.h
@@ -56,6 +56,7 @@
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING		0x00000040
 #define SECONDARY_EXEC_UNRESTRICTED_GUEST	0x00000080
+#define SECONDARY_EXEC_PAUSE_LOOP_EXITING	0x00000400
 
 
 #define PIN_BASED_EXT_INTR_MASK                 0x00000001
@@ -144,6 +145,8 @@
 	VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
 	TPR_THRESHOLD                   = 0x0000401c,
 	SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
+	PLE_GAP                         = 0x00004020,
+	PLE_WINDOW                      = 0x00004022,
 	VM_INSTRUCTION_ERROR            = 0x00004400,
 	VM_EXIT_REASON                  = 0x00004402,
 	VM_EXIT_INTR_INFO               = 0x00004404,
@@ -248,6 +251,7 @@
 #define EXIT_REASON_MSR_READ            31
 #define EXIT_REASON_MSR_WRITE           32
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_PAUSE_INSTRUCTION   40
 #define EXIT_REASON_MCE_DURING_VMENTRY	 41
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
 #define EXIT_REASON_APIC_ACCESS         44
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/hpet.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/hpet.h
@@ -66,6 +66,7 @@
 extern unsigned long hpet_address;
 extern unsigned long force_hpet_address;
 extern int hpet_force_user;
+extern u8 hpet_msi_disable;
 extern int is_hpet_enabled(void);
 extern int hpet_enable(void);
 extern void hpet_disable(void);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/processor.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/processor.h
@@ -180,7 +180,7 @@
 				unsigned int *ecx, unsigned int *edx)
 {
 	/* ecx is often an input as well as an output. */
-	asm("cpuid"
+	asm volatile("cpuid"
 	    : "=a" (*eax),
 	      "=b" (*ebx),
 	      "=c" (*ecx),
@@ -765,29 +765,6 @@
 extern unsigned long		idle_halt;
 extern unsigned long		idle_nomwait;
 
-/*
- * on systems with caches, caches must be flashed as the absolute
- * last instruction before going into a suspended halt.  Otherwise,
- * dirty data can linger in the cache and become stale on resume,
- * leading to strange errors.
- *
- * perform a variety of operations to guarantee that the compiler
- * will not reorder instructions.  wbinvd itself is serializing
- * so the processor will not reorder.
- *
- * Systems without cache can just go into halt.
- */
-static inline void wbinvd_halt(void)
-{
-	mb();
-	/* check for clflush to determine if wbinvd is legal */
-	if (cpu_has_clflush)
-		asm volatile("cli; wbinvd; 1: hlt; jmp 1b" : : : "memory");
-	else
-		while (1)
-			halt();
-}
-
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
@@ -1052,4 +1029,23 @@
 	return ratio;
 }
 
+/*
+ * AMD errata checking
+ */
+#ifdef CONFIG_CPU_SUP_AMD
+extern const int amd_erratum_400[];
+extern bool cpu_has_amd_erratum(const int *);
+
+#define AMD_LEGACY_ERRATUM(...)		{ -1, __VA_ARGS__, 0 }
+#define AMD_OSVW_ERRATUM(osvw_id, ...)	{ osvw_id, __VA_ARGS__, 0 }
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
+	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
+#define AMD_MODEL_RANGE_FAMILY(range)	(((range) >> 24) & 0xff)
+#define AMD_MODEL_RANGE_START(range)	(((range) >> 12) & 0xfff)
+#define AMD_MODEL_RANGE_END(range)	((range) & 0xfff)
+
+#else
+#define cpu_has_amd_erratum(x)	(false)
+#endif /* CONFIG_CPU_SUP_AMD */
+
 #endif /* _ASM_X86_PROCESSOR_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/cpufeature.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/cpufeature.h
@@ -150,9 +150,10 @@
 #define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
 #define X86_FEATURE_OSVW	(6*32+ 9) /* OS Visible Workaround */
 #define X86_FEATURE_IBS		(6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_SSE5	(6*32+11) /* SSE-5 */
+#define X86_FEATURE_XOP		(6*32+11) /* extended AVX instructions */
 #define X86_FEATURE_SKINIT	(6*32+12) /* SKINIT/STGI instructions */
 #define X86_FEATURE_WDT		(6*32+13) /* Watchdog timer */
+#define X86_FEATURE_NODEID_MSR	(6*32+19) /* NodeId MSR */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -246,8 +247,13 @@
 #define cpu_has_xmm4_1		boot_cpu_has(X86_FEATURE_XMM4_1)
 #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
+#ifndef CONFIG_XEN
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
+#else
+#define cpu_has_xsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
+#endif
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
+#define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/i8253.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/i8253.h
@@ -8,10 +8,14 @@
 
 extern spinlock_t i8253_lock;
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS
+
 extern struct clock_event_device *global_clock_event;
 
 extern void setup_pit_timer(void);
 
+#endif
+
 #define inb_pit		inb_p
 #define outb_pit	outb_p
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/msr-index.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/msr-index.h
@@ -81,11 +81,15 @@
 #define MSR_IA32_MC0_ADDR		0x00000402
 #define MSR_IA32_MC0_MISC		0x00000403
 
+#define MSR_AMD64_MC0_MASK		0xc0010044
+
 #define MSR_IA32_MCx_CTL(x)		(MSR_IA32_MC0_CTL + 4*(x))
 #define MSR_IA32_MCx_STATUS(x)		(MSR_IA32_MC0_STATUS + 4*(x))
 #define MSR_IA32_MCx_ADDR(x)		(MSR_IA32_MC0_ADDR + 4*(x))
 #define MSR_IA32_MCx_MISC(x)		(MSR_IA32_MC0_MISC + 4*(x))
 
+#define MSR_AMD64_MCx_MASK(x)		(MSR_AMD64_MC0_MASK + (x))
+
 /* These are consecutive and not in the normal 4er MCE bank block */
 #define MSR_IA32_MC0_CTL2		0x00000280
 #define MSR_IA32_MCx_CTL2(x)		(MSR_IA32_MC0_CTL2 + (x))
@@ -104,6 +108,9 @@
 #define MSR_AMD64_PATCH_LEVEL		0x0000008b
 #define MSR_AMD64_NB_CFG		0xc001001f
 #define MSR_AMD64_PATCH_LOADER		0xc0010020
+#define MSR_AMD64_OSVW_ID_LENGTH	0xc0010140
+#define MSR_AMD64_OSVW_STATUS		0xc0010141
+#define MSR_AMD64_DC_CFG		0xc0011022
 #define MSR_AMD64_IBSFETCHCTL		0xc0011030
 #define MSR_AMD64_IBSFETCHLINAD		0xc0011031
 #define MSR_AMD64_IBSFETCHPHYSAD	0xc0011032
@@ -123,6 +130,7 @@
 #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
 #define FAM10H_MMIO_CONF_BASE_MASK	0xfffffff
 #define FAM10H_MMIO_CONF_BASE_SHIFT	20
+#define MSR_FAM10H_NODE_ID		0xc001100c
 
 /* K8 MSRs */
 #define MSR_K8_TOP_MEM1			0xc001001a
@@ -195,8 +203,9 @@
 #define MSR_IA32_EBL_CR_POWERON		0x0000002a
 #define MSR_IA32_FEATURE_CONTROL        0x0000003a
 
-#define FEATURE_CONTROL_LOCKED		(1<<0)
-#define FEATURE_CONTROL_VMXON_ENABLED	(1<<2)
+#define FEATURE_CONTROL_LOCKED				(1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX	(1<<1)
+#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX	(1<<2)
 
 #define MSR_IA32_APICBASE		0x0000001b
 #define MSR_IA32_APICBASE_BSP		(1<<8)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/io_apic.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/io_apic.h
@@ -160,6 +160,7 @@
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
+void setup_IO_APIC_irq_extra(u32 gsi);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/mmu.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/mmu.h
@@ -7,15 +7,25 @@
 /*
  * The x86 doesn't have a mmu context, but
  * we put the segment information here.
+ *
+ * exec_limit is used to track the range PROT_EXEC
+ * mappings span.
  */
 typedef struct {
 	void *ldt;
 	int size;
+#ifdef CONFIG_XEN
+	unsigned has_foreign_mappings:1;
+#endif
 	struct mutex lock;
 	void *vdso;
+#ifdef CONFIG_X86_32
+	struct desc_struct user_cs;
+	unsigned long exec_limit;
+#endif
 } mm_context_t;
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
 void leave_mm(int cpu);
 #else
 static inline void leave_mm(int cpu)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/fixmap.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/fixmap.h
@@ -82,6 +82,9 @@
 #endif
 	FIX_DBGP_BASE,
 	FIX_EARLYCON_MEM_BASE,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+	FIX_OHCI1394_BASE,
+#endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
@@ -126,9 +129,6 @@
 	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
 			(__end_of_permanent_fixed_addresses & 255),
 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
-	FIX_OHCI1394_BASE,
-#endif
 #ifdef CONFIG_X86_32
 	FIX_WP_TEST,
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/irq_vectors.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/irq_vectors.h
@@ -113,7 +113,7 @@
  */
 #define LOCAL_PENDING_VECTOR		0xec
 
-#define UV_BAU_MESSAGE			0xec
+#define UV_BAU_MESSAGE			0xea
 
 /*
  * Self IPI vector for machine checks
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/hypervisor.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/hypervisor.h
@@ -24,3 +24,7 @@
 extern void init_hypervisor_platform(void);
 
 #endif
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include_next <asm/hypervisor.h>
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/thread_info.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/thread_info.h
@@ -86,7 +86,6 @@
 #define TIF_NOTSC		16	/* TSC is not accessible in userland */
 #define TIF_IA32		17	/* 32bit process */
 #define TIF_FORK		18	/* ret_from_fork */
-#define TIF_ABI_PENDING		19
 #define TIF_MEMDIE		20
 #define TIF_DEBUG		21	/* uses debug registers */
 #define TIF_IO_BITMAP		22	/* uses I/O bitmap */
@@ -96,6 +95,9 @@
 #define TIF_DS_AREA_MSR		26      /* uses thread_struct.ds_area_msr */
 #define TIF_LAZY_MMU_UPDATES	27	/* task is updating the mmu lazily */
 #define TIF_SYSCALL_TRACEPOINT	28	/* syscall tracepoint instrumentation */
+#ifdef CONFIG_X86_XEN
+#define TIF_CSTAR		31      /* cstar-based syscall (special handling) */
+#endif
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
@@ -110,7 +112,6 @@
 #define _TIF_NOTSC		(1 << TIF_NOTSC)
 #define _TIF_IA32		(1 << TIF_IA32)
 #define _TIF_FORK		(1 << TIF_FORK)
-#define _TIF_ABI_PENDING	(1 << TIF_ABI_PENDING)
 #define _TIF_DEBUG		(1 << TIF_DEBUG)
 #define _TIF_IO_BITMAP		(1 << TIF_IO_BITMAP)
 #define _TIF_FREEZE		(1 << TIF_FREEZE)
@@ -119,6 +120,7 @@
 #define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
 #define _TIF_LAZY_MMU_UPDATES	(1 << TIF_LAZY_MMU_UPDATES)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_CSTAR		(1 << TIF_CSTAR)
 
 /* work to do in syscall_trace_enter() */
 #define _TIF_WORK_SYSCALL_ENTRY	\
@@ -145,9 +147,14 @@
 	(_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
 
 /* flags to check in __switch_to() */
+#ifndef CONFIG_XEN
 #define _TIF_WORK_CTXSW							\
 	(_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_NOTSC)
 
+#else
+#define _TIF_WORK_CTXSW (_TIF_NOTSC \
+     /*todo | _TIF_DEBUGCTLMSR | _TIF_DS_AREA_MSR | _TIF_BTS_TRACE_TS*/)
+#endif
 #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/apicdef.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/apicdef.h
@@ -11,6 +11,8 @@
 #define IO_APIC_DEFAULT_PHYS_BASE	0xfec00000
 #define	APIC_DEFAULT_PHYS_BASE		0xfee00000
 
+#ifndef CONFIG_XEN
+
 #define	APIC_ID		0x20
 
 #define	APIC_LVR	0x30
@@ -72,6 +74,7 @@
 #define		APIC_DEST_LOGICAL	0x00800
 #define		APIC_DEST_PHYSICAL	0x00000
 #define		APIC_DM_FIXED		0x00000
+#define		APIC_DM_FIXED_MASK	0x00700
 #define		APIC_DM_LOWEST		0x00100
 #define		APIC_DM_SMI		0x00200
 #define		APIC_DM_REMRD		0x00300
@@ -136,6 +139,16 @@
 #define APIC_BASE_MSR	0x800
 #define X2APIC_ENABLE	(1UL << 10)
 
+#else /* CONFIG_XEN */
+
+enum {
+	APIC_DEST_ALLBUT = 0x1,
+	APIC_DEST_SELF,
+	APIC_DEST_ALLINC
+};
+
+#endif /* CONFIG_XEN */
+
 #ifdef CONFIG_X86_32
 # define MAX_IO_APICS 64
 #else
@@ -143,6 +156,8 @@
 # define MAX_LOCAL_APIC 32768
 #endif
 
+#ifndef CONFIG_XEN
+
 /*
  * All x86-64 systems are xAPIC compatible.
  * In the following, "apicid" is a physical APIC ID.
@@ -413,6 +428,8 @@
 
 #undef u32
 
+#endif /* CONFIG_XEN */
+
 #ifdef CONFIG_X86_32
  #define BAD_APICID 0xFFu
 #else
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/topology.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/topology.h
@@ -30,7 +30,7 @@
 #  define ENABLE_TOPO_DEFINES
 # endif
 #else
-# ifdef CONFIG_SMP
+# if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
 #  define ENABLE_TOPO_DEFINES
 # endif
 #endif
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/smp.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/smp.h
@@ -50,7 +50,7 @@
 	void (*smp_prepare_cpus)(unsigned max_cpus);
 	void (*smp_cpus_done)(unsigned max_cpus);
 
-	void (*smp_send_stop)(void);
+	void (*stop_other_cpus)(int wait);
 	void (*smp_send_reschedule)(int cpu);
 
 	int (*cpu_up)(unsigned cpu);
@@ -73,7 +73,12 @@
 
 static inline void smp_send_stop(void)
 {
-	smp_ops.smp_send_stop();
+	smp_ops.stop_other_cpus(0);
+}
+
+static inline void stop_other_cpus(void)
+{
+	smp_ops.stop_other_cpus(1);
 }
 
 static inline void smp_prepare_boot_cpu(void)
@@ -135,6 +140,8 @@
 void native_cpu_die(unsigned int cpu);
 void native_play_dead(void);
 void play_dead_common(void);
+void wbinvd_on_cpu(int cpu);
+int wbinvd_on_all_cpus(void);
 
 void native_send_call_func_ipi(const struct cpumask *mask);
 void native_send_call_func_single_ipi(int cpu);
@@ -147,6 +154,13 @@
 {
 	return cpumask_weight(cpu_callout_mask);
 }
+#else /* !CONFIG_SMP */
+#define wbinvd_on_cpu(cpu)     wbinvd()
+static inline int wbinvd_on_all_cpus(void)
+{
+	wbinvd();
+	return 0;
+}
 #endif /* CONFIG_SMP */
 
 extern unsigned disabled_cpus __cpuinitdata;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/boot.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/boot.h
@@ -16,7 +16,7 @@
 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
 
 /* Minimum kernel alignment, as a power of two */
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && !defined(CONFIG_XEN)
 #define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
 #else
 #define MIN_KERNEL_ALIGN_LG2	(PAGE_SHIFT + THREAD_ORDER)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/traps.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/traps.h
@@ -37,6 +37,9 @@
 asmlinkage void machine_check(void);
 #endif /* CONFIG_X86_MCE */
 asmlinkage void simd_coprocessor_error(void);
+#ifdef CONFIG_X86_XEN
+asmlinkage void fixup_4gb_segment(void);
+#endif
 
 dotraplinkage void do_divide_error(struct pt_regs *, long);
 dotraplinkage void do_debug(struct pt_regs *, long);
@@ -65,6 +68,9 @@
 dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
 #ifdef CONFIG_X86_32
 dotraplinkage void do_iret_error(struct pt_regs *, long);
+#ifdef CONFIG_XEN
+void do_fixup_4gb_segment(struct pt_regs *, long);
+#endif
 #endif
 
 static inline int get_si_code(unsigned long condition)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/scatterlist.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/scatterlist.h
@@ -3,6 +3,10 @@
 
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
+#ifdef CONFIG_X86_XEN
+# define sg_dma_len(sg)		((sg)->dma_length)
+#endif
+
 #include <asm-generic/scatterlist.h>
 
 #endif /* _ASM_X86_SCATTERLIST_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/paravirt.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/paravirt.h
@@ -289,6 +289,12 @@
 {
 	PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
 }
+#ifdef CONFIG_X86_32
+static inline void load_user_cs_desc(unsigned int cpu, struct mm_struct *mm)
+{
+	PVOP_VCALL2(pv_cpu_ops.load_user_cs_desc, cpu, mm);
+}
+#endif /*CONFIG_X86_32*/
 static inline void store_gdt(struct desc_ptr *dtr)
 {
 	PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/io.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/io.h
@@ -172,6 +172,7 @@
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void set_iounmap_nonlazy(void);
 
 #ifdef CONFIG_X86_32
 # include "io_32.h"
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/trampoline.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/trampoline.h
@@ -13,15 +13,18 @@
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
+extern unsigned long initial_page_table;
 extern unsigned long initial_gs;
 
 #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
 #define TRAMPOLINE_BASE 0x6000
 
 extern unsigned long setup_trampoline(void);
+extern void __init setup_trampoline_page_table(void);
 extern void __init reserve_trampoline_memory(void);
 #else
-static inline void reserve_trampoline_memory(void) {};
+static inline void setup_trampoline_page_table(void) {}
+static inline void reserve_trampoline_memory(void) {}
 #endif /* CONFIG_X86_TRAMPOLINE */
 
 #endif /* __ASSEMBLY__ */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/e820.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/e820.h
@@ -129,7 +129,11 @@
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 
+#ifndef CONFIG_XEN
 #define ISA_START_ADDRESS	0xa0000
+#else
+#define ISA_START_ADDRESS	0
+#endif
 #define ISA_END_ADDRESS		0x100000
 #define is_ISA_range(s, e) ((s) >= ISA_START_ADDRESS && (e) < ISA_END_ADDRESS)
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/pgalloc.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/pgalloc.h
@@ -23,6 +23,11 @@
 #endif
 
 /*
+ * Flags to use when allocating a user page table page.
+ */
+extern gfp_t __userpte_alloc_gfp;
+
+/*
  * Allocate and free page tables.
  */
 extern pgd_t *pgd_alloc(struct mm_struct *);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/amd_iommu_types.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/amd_iommu_types.h
@@ -305,6 +305,9 @@
 	/* capabilities of that IOMMU read from ACPI */
 	u32 cap;
 
+	/* flags read from acpi table */
+	u8 acpi_flags;
+
 	/*
 	 * Capability pointer. There could be more than one IOMMU per PCI
 	 * device function if there are more than one AMD IOMMU capability
@@ -348,6 +351,15 @@
 
 	/* default dma_ops domain for that IOMMU */
 	struct dma_ops_domain *default_dom;
+
+	/*
+	 * This array is required to work around a potential BIOS bug.
+	 * The BIOS may miss to restore parts of the PCI configuration
+	 * space when the system resumes from S3. The result is that the
+	 * IOMMU does not execute commands anymore which leads to system
+	 * failure.
+	 */
+	u32 cache_cfg[4];
 };
 
 /*
@@ -469,4 +481,10 @@
 /* some function prototypes */
 extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
 
+static inline bool is_rd890_iommu(struct pci_dev *pdev)
+{
+	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
+	       (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
+}
+
 #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/compat.h
@@ -204,7 +204,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = task_pt_regs(current);
 	return (void __user *)regs->sp - len;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/hw_irq.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/hw_irq.h
@@ -107,6 +107,7 @@
 extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
 #endif
 #ifdef CONFIG_SMP
+#ifndef CONFIG_XEN
 extern void smp_reschedule_interrupt(struct pt_regs *);
 extern void smp_call_function_interrupt(struct pt_regs *);
 extern void smp_call_function_single_interrupt(struct pt_regs *);
@@ -115,9 +116,18 @@
 #else
 extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *);
 #endif
+#else
+#include <linux/irqreturn.h>
+extern irqreturn_t smp_reschedule_interrupt(int, void *);
+extern irqreturn_t smp_call_function_interrupt(int, void *);
+extern irqreturn_t smp_call_function_single_interrupt(int, void *);
+extern irqreturn_t smp_reboot_interrupt(int, void *);
+#endif
 #endif
 
+#ifndef CONFIG_XEN
 extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void);
+#endif
 
 typedef int vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/required-features.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/required-features.h
@@ -48,7 +48,7 @@
 #endif
 
 #ifdef CONFIG_X86_64
-#ifdef CONFIG_PARAVIRT
+#if defined(CONFIG_PARAVIRT) || defined(CONFIG_XEN)
 /* Paravirtualized systems may not have PSE or PGE available */
 #define NEED_PSE	0
 #define NEED_PGE	0
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/kvm_host.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/kvm_host.h
@@ -193,6 +193,7 @@
 		unsigned invalid:1;
 		unsigned cr4_pge:1;
 		unsigned nxe:1;
+		unsigned cr0_wp:1;
 	};
 };
 
@@ -256,7 +257,8 @@
 	void (*new_cr3)(struct kvm_vcpu *vcpu);
 	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
 	void (*free)(struct kvm_vcpu *vcpu);
-	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
+	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
+			    u32 *error);
 	void (*prefetch_page)(struct kvm_vcpu *vcpu,
 			      struct kvm_mmu_page *page);
 	int (*sync_page)(struct kvm_vcpu *vcpu,
@@ -355,6 +357,9 @@
 	struct page *time_page;
 
 	bool singlestep; /* guest is single stepped by KVM */
+	u64 last_guest_tsc;
+	u64 last_kernel_ns;
+
 	bool nmi_pending;
 	bool nmi_injected;
 
@@ -412,6 +417,7 @@
 	unsigned long irq_sources_bitmap;
 	unsigned long irq_states[KVM_IOAPIC_NUM_PINS];
 	u64 vm_init_tsc;
+	s64 kvmclock_offset;
 };
 
 struct kvm_vm_stat {
@@ -600,8 +606,7 @@
 		    unsigned long value);
 
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
-				int type_bits, int seg);
+int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
 
 int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason);
 
@@ -644,6 +649,10 @@
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
@@ -657,6 +666,7 @@
 
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int complete_pio(struct kvm_vcpu *vcpu);
+bool kvm_check_iopl(struct kvm_vcpu *vcpu);
 
 struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn);
 
@@ -667,20 +677,6 @@
 	return (struct kvm_mmu_page *)page_private(page);
 }
 
-static inline u16 kvm_read_fs(void)
-{
-	u16 seg;
-	asm("mov %%fs, %0" : "=g"(seg));
-	return seg;
-}
-
-static inline u16 kvm_read_gs(void)
-{
-	u16 seg;
-	asm("mov %%gs, %0" : "=g"(seg));
-	return seg;
-}
-
 static inline u16 kvm_read_ldt(void)
 {
 	u16 ldt;
@@ -688,16 +684,6 @@
 	return ldt;
 }
 
-static inline void kvm_load_fs(u16 sel)
-{
-	asm("mov %0, %%fs" : : "rm"(sel));
-}
-
-static inline void kvm_load_gs(u16 sel)
-{
-	asm("mov %0, %%gs" : : "rm"(sel));
-}
-
 static inline void kvm_load_ldt(u16 sel)
 {
 	asm("lldt %0" : : "rm"(sel));
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/apic.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/apic.h
@@ -10,12 +10,16 @@
 #include <asm/processor.h>
 #include <asm/apicdef.h>
 #include <asm/atomic.h>
+#ifndef CONFIG_XEN
 #include <asm/fixmap.h>
+#endif
 #include <asm/mpspec.h>
 #include <asm/system.h>
 #include <asm/msr.h>
 
+#ifndef CONFIG_XEN
 #define ARCH_APICTIMER_STOPS_ON_C3	1
+#endif
 
 /*
  * Debugging macros
@@ -47,6 +51,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 
 extern unsigned int apic_verbosity;
+#ifndef CONFIG_XEN
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
@@ -119,6 +124,8 @@
 
 extern int x2apic_mode;
 
+#endif /* CONFIG_XEN */
+
 #ifdef CONFIG_X86_X2APIC
 /*
  * Make previous memory operations globally visible before
@@ -365,6 +372,8 @@
  */
 extern struct apic *apic;
 
+#ifndef CONFIG_XEN
+
 /*
  * APIC functionality to boot other CPUs - only used on SMP:
  */
@@ -458,6 +467,8 @@
 
 extern void generic_bigsmp_probe(void);
 
+#endif /* CONFIG_XEN */
+
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
@@ -477,6 +488,8 @@
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
 
 
+#ifndef CONFIG_XEN
+
 static inline unsigned int read_apic_id(void)
 {
 	unsigned int reg;
@@ -588,6 +601,8 @@
 	return physid_mask_of_physid(phys_apicid);
 }
 
+#endif /* CONFIG_XEN */
+
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_32
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/irq.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/irq.h
@@ -15,7 +15,7 @@
 	return ((irq == 2) ? 9 : irq);
 }
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
 # define ARCH_HAS_NMI_WATCHDOG
 #endif
 
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/suspend_64.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/suspend_64.h
@@ -27,6 +27,8 @@
 	u16 ds, es, fs, gs, ss;
 	unsigned long gs_base, gs_kernel_base, fs_base;
 	unsigned long cr0, cr2, cr3, cr4, cr8;
+	u64 misc_enable;
+	bool misc_enable_saved;
 	unsigned long efer;
 	u16 gdt_pad;
 	u16 gdt_limit;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/smpboot_hooks.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/smpboot_hooks.h
@@ -34,7 +34,7 @@
 	 */
 	CMOS_WRITE(0, 0xf);
 
-	*((volatile long *)phys_to_virt(apic->trampoline_phys_low)) = 0;
+	*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
 }
 
 static inline void __init smpboot_setup_io_apic(void)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/percpu.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/percpu.h
@@ -133,6 +133,38 @@
 	ret__;						\
 })
 
+#define percpu_xchg_op(op, var, val)			\
+({							\
+	typedef typeof(var) T__;			\
+	T__ ret__;					\
+	if (0)						\
+		ret__ = (val);				\
+	switch (sizeof(var)) {				\
+	case 1:						\
+		asm(op "b %0,"__percpu_arg(1)		\
+		    : "=q" (ret__), "+m" (var)		\
+		    : "0" ((T__)(val)));		\
+		break;					\
+	case 2:						\
+		asm(op "w %0,"__percpu_arg(1)		\
+		    : "=r" (ret__), "+m" (var)		\
+		    : "0" ((T__)(val)));		\
+		break;					\
+	case 4:						\
+		asm(op "l %0,"__percpu_arg(1)		\
+		    : "=r" (ret__), "+m" (var)		\
+		    : "0" ((T__)(val)));		\
+		break;					\
+	case 8:						\
+		asm(op "q %0,"__percpu_arg(1)		\
+		    : "=r" (ret__), "+m" (var)		\
+		    : "0" ((T__)(val)));		\
+		break;					\
+	default: __bad_percpu_size();			\
+	}						\
+	ret__;						\
+})
+
 /*
  * percpu_read() makes gcc load the percpu variable every time it is
  * accessed while percpu_read_stable() allows the value to be cached.
@@ -152,6 +184,10 @@
 #define percpu_and(var, val)	percpu_to_op("and", per_cpu__##var, val)
 #define percpu_or(var, val)	percpu_to_op("or", per_cpu__##var, val)
 #define percpu_xor(var, val)	percpu_to_op("xor", per_cpu__##var, val)
+#define percpu_xchg(var, val)   percpu_xchg_op("xchg", per_cpu__##var, val)
+#if defined(CONFIG_X86_XADD) || defined(CONFIG_X86_64)
+#define percpu_xadd(var, val)   percpu_xchg_op("xadd", per_cpu__##var, val)
+#endif
 
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
 #define x86_test_and_clear_bit_percpu(bit, var)				\
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/kvm_emulate.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/kvm_emulate.h
@@ -54,13 +54,23 @@
 struct x86_emulate_ops {
 	/*
 	 * read_std: Read bytes of standard (non-emulated/special) memory.
-	 *           Used for instruction fetch, stack operations, and others.
+	 *           Used for descriptor reading.
 	 *  @addr:  [IN ] Linear address from which to read.
 	 *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
 	 *  @bytes: [IN ] Number of bytes to read from memory.
 	 */
 	int (*read_std)(unsigned long addr, void *val,
-			unsigned int bytes, struct kvm_vcpu *vcpu);
+			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+
+	/*
+	 * fetch: Read bytes of standard (non-emulated/special) memory.
+	 *        Used for instruction fetch.
+	 *  @addr:  [IN ] Linear address from which to read.
+	 *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+	 *  @bytes: [IN ] Number of bytes to read from memory.
+	 */
+	int (*fetch)(unsigned long addr, void *val,
+			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
 
 	/*
 	 * read_emulated: Read bytes from emulated/special memory area.
@@ -129,7 +139,7 @@
 	u8 seg_override;
 	unsigned int d;
 	unsigned long regs[NR_VCPU_REGS];
-	unsigned long eip;
+	unsigned long eip, eip_orig;
 	/* modrm */
 	u8 modrm;
 	u8 modrm_mod;
@@ -168,6 +178,7 @@
 
 /* Execution mode, passed to the emulator. */
 #define X86EMUL_MODE_REAL     0	/* Real mode.             */
+#define X86EMUL_MODE_VM86     1	/* Virtual 8086 mode.     */
 #define X86EMUL_MODE_PROT16   2	/* 16-bit protected mode. */
 #define X86EMUL_MODE_PROT32   4	/* 32-bit protected mode. */
 #define X86EMUL_MODE_PROT64   8	/* 64-bit (long) mode.    */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/suspend_32.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/suspend_32.h
@@ -15,6 +15,8 @@
 struct saved_context {
 	u16 es, fs, gs, ss;
 	unsigned long cr0, cr2, cr3, cr4;
+	u64 misc_enable;
+	bool misc_enable_saved;
 	struct desc_ptr gdt;
 	struct desc_ptr idt;
 	u16 ldt;
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/rwsem.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/rwsem.h
@@ -41,6 +41,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/lockdep.h>
+#include <asm/asm.h>
 
 struct rwsem_waiter;
 
@@ -55,17 +56,28 @@
 
 /*
  * the semaphore definition
+ *
+ * The bias values and the counter type limits the number of
+ * potential readers/writers to 32767 for 32 bits and 2147483647
+ * for 64 bits.
  */
 
-#define RWSEM_UNLOCKED_VALUE		0x00000000
-#define RWSEM_ACTIVE_BIAS		0x00000001
-#define RWSEM_ACTIVE_MASK		0x0000ffff
-#define RWSEM_WAITING_BIAS		(-0x00010000)
+#ifdef CONFIG_X86_64
+# define RWSEM_ACTIVE_MASK		0xffffffffL
+#else
+# define RWSEM_ACTIVE_MASK		0x0000ffffL
+#endif
+
+#define RWSEM_UNLOCKED_VALUE		0x00000000L
+#define RWSEM_ACTIVE_BIAS		0x00000001L
+#define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
+typedef signed long rwsem_count_t;
+
 struct rw_semaphore {
-	signed long		count;
+	rwsem_count_t		count;
 	spinlock_t		wait_lock;
 	struct list_head	wait_list;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -105,7 +117,7 @@
 static inline void __down_read(struct rw_semaphore *sem)
 {
 	asm volatile("# beginning down_read\n\t"
-		     LOCK_PREFIX "  incl      (%%eax)\n\t"
+		     LOCK_PREFIX _ASM_INC "(%1)\n\t"
 		     /* adds 0x00000001, returns the old value */
 		     "  jns        1f\n"
 		     "  call call_rwsem_down_read_failed\n"
@@ -121,14 +133,14 @@
  */
 static inline int __down_read_trylock(struct rw_semaphore *sem)
 {
-	__s32 result, tmp;
+	rwsem_count_t result, tmp;
 	asm volatile("# beginning __down_read_trylock\n\t"
-		     "  movl      %0,%1\n\t"
+		     "  mov          %0,%1\n\t"
 		     "1:\n\t"
-		     "  movl	     %1,%2\n\t"
-		     "  addl      %3,%2\n\t"
+		     "  mov          %1,%2\n\t"
+		     "  add          %3,%2\n\t"
 		     "  jle	     2f\n\t"
-		     LOCK_PREFIX "  cmpxchgl  %2,%0\n\t"
+		     LOCK_PREFIX "  cmpxchg  %2,%0\n\t"
 		     "  jnz	     1b\n\t"
 		     "2:\n\t"
 		     "# ending __down_read_trylock\n\t"
@@ -143,13 +155,13 @@
  */
 static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
-	int tmp;
+	rwsem_count_t tmp;
 
 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
 	asm volatile("# beginning down_write\n\t"
-		     LOCK_PREFIX "  xadd      %%edx,(%%eax)\n\t"
+		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtract 0x0000ffff, returns the old value */
-		     "  testl     %%edx,%%edx\n\t"
+		     "  test      %1,%1\n\t"
 		     /* was the count 0 before? */
 		     "  jz        1f\n"
 		     "  call call_rwsem_down_write_failed\n"
@@ -170,9 +182,9 @@
  */
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
-	signed long ret = cmpxchg(&sem->count,
-				  RWSEM_UNLOCKED_VALUE,
-				  RWSEM_ACTIVE_WRITE_BIAS);
+	rwsem_count_t ret = cmpxchg(&sem->count,
+				    RWSEM_UNLOCKED_VALUE,
+				    RWSEM_ACTIVE_WRITE_BIAS);
 	if (ret == RWSEM_UNLOCKED_VALUE)
 		return 1;
 	return 0;
@@ -183,9 +195,9 @@
  */
 static inline void __up_read(struct rw_semaphore *sem)
 {
-	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
+	rwsem_count_t tmp = -RWSEM_ACTIVE_READ_BIAS;
 	asm volatile("# beginning __up_read\n\t"
-		     LOCK_PREFIX "  xadd      %%edx,(%%eax)\n\t"
+		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtracts 1, returns the old value */
 		     "  jns        1f\n\t"
 		     "  call call_rwsem_wake\n"
@@ -201,18 +213,18 @@
  */
 static inline void __up_write(struct rw_semaphore *sem)
 {
+	rwsem_count_t tmp;
 	asm volatile("# beginning __up_write\n\t"
-		     "  movl      %2,%%edx\n\t"
-		     LOCK_PREFIX "  xaddl     %%edx,(%%eax)\n\t"
+		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* tries to transition
 			0xffff0001 -> 0x00000000 */
 		     "  jz       1f\n"
 		     "  call call_rwsem_wake\n"
 		     "1:\n\t"
 		     "# ending __up_write\n"
-		     : "+m" (sem->count)
-		     : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
-		     : "memory", "cc", "edx");
+		     : "+m" (sem->count), "=d" (tmp)
+		     : "a" (sem), "1" (-RWSEM_ACTIVE_WRITE_BIAS)
+		     : "memory", "cc");
 }
 
 /*
@@ -221,33 +233,38 @@
 static inline void __downgrade_write(struct rw_semaphore *sem)
 {
 	asm volatile("# beginning __downgrade_write\n\t"
-		     LOCK_PREFIX "  addl      %2,(%%eax)\n\t"
-		     /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
+		     LOCK_PREFIX _ASM_ADD "%2,(%1)\n\t"
+		     /*
+		      * transitions 0xZZZZ0001 -> 0xYYYY0001 (i386)
+		      *     0xZZZZZZZZ00000001 -> 0xYYYYYYYY00000001 (x86_64)
+		      */
 		     "  jns       1f\n\t"
 		     "  call call_rwsem_downgrade_wake\n"
 		     "1:\n\t"
 		     "# ending __downgrade_write\n"
 		     : "+m" (sem->count)
-		     : "a" (sem), "i" (-RWSEM_WAITING_BIAS)
+		     : "a" (sem), "er" (-RWSEM_WAITING_BIAS)
 		     : "memory", "cc");
 }
 
 /*
  * implement atomic add functionality
  */
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+static inline void rwsem_atomic_add(rwsem_count_t delta,
+				    struct rw_semaphore *sem)
 {
-	asm volatile(LOCK_PREFIX "addl %1,%0"
+	asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0"
 		     : "+m" (sem->count)
-		     : "ir" (delta));
+		     : "er" (delta));
 }
 
 /*
  * implement exchange and add functionality
  */
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+static inline rwsem_count_t rwsem_atomic_update(rwsem_count_t delta,
+						struct rw_semaphore *sem)
 {
-	int tmp = delta;
+	rwsem_count_t tmp = delta;
 
 	asm volatile(LOCK_PREFIX "xadd %0,%1"
 		     : "+r" (tmp), "+m" (sem->count)
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/kexec.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/kexec.h
@@ -5,14 +5,30 @@
 # define PA_CONTROL_PAGE	0
 # define VA_CONTROL_PAGE	1
 # define PA_PGD			2
+# ifndef CONFIG_XEN
 # define PA_SWAP_PAGE		3
 # define PAGES_NR		4
+# else /* CONFIG_XEN */
+/*
+ * The hypervisor interface implicitly requires that all entries (except
+ * for possibly the final one) are arranged in matching PA_/VA_ pairs.
+#  define VA_PGD		3
+ */
+#  define PA_SWAP_PAGE		4
+#  define PAGES_NR		5
+# endif /* CONFIG_XEN */
 #else
 # define PA_CONTROL_PAGE	0
 # define VA_CONTROL_PAGE	1
 # define PA_TABLE_PAGE		2
+# ifndef CONFIG_XEN
 # define PA_SWAP_PAGE		3
 # define PAGES_NR		4
+# else /* CONFIG_XEN, see comment above
+#  define VA_TABLE_PAGE		3 */
+#  define PA_SWAP_PAGE		4
+#  define PAGES_NR		5
+# endif /* CONFIG_XEN */
 #endif
 
 # define KEXEC_CONTROL_CODE_MAX_SIZE	2048
@@ -163,6 +179,19 @@
 };
 #endif
 
+/* Under Xen we need to work with machine addresses. These macros give the
+ * machine address of a certain page to the generic kexec code instead of
+ * the pseudo physical address which would be given by the default macros.
+ */
+
+#ifdef CONFIG_XEN
+#define KEXEC_ARCH_HAS_PAGE_MACROS
+#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
+#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
+#define kexec_virt_to_phys(addr) virt_to_machine(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_KEXEC_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/xen/hypervisor.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/xen/hypervisor.h
@@ -43,7 +43,7 @@
 	XEN_HVM_DOMAIN,		/* running in a Xen hvm domain */
 };
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 extern enum xen_domain_type xen_domain_type;
 #else
 #define xen_domain_type		XEN_NATIVE
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/xen/interface.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/xen/interface.h
@@ -10,17 +10,20 @@
 #define _ASM_X86_XEN_INTERFACE_H
 
 #ifdef __XEN__
-#define __DEFINE_GUEST_HANDLE(name, type) \
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
     typedef struct { type *p; } __guest_handle_ ## name
 #else
-#define __DEFINE_GUEST_HANDLE(name, type) \
+#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_GUEST_HANDLE_STRUCT(name) \
-	__DEFINE_GUEST_HANDLE(name, struct name)
-#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
-#define GUEST_HANDLE(name)        __guest_handle_ ## name
+	__DEFINE_XEN_GUEST_HANDLE(name, struct name)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
 
 #ifdef __XEN__
 #if defined(__i386__)
@@ -47,14 +50,8 @@
 #endif
 
 #ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
-DEFINE_GUEST_HANDLE(char);
-DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
-DEFINE_GUEST_HANDLE(void);
+typedef unsigned long xen_pfn_t;
+typedef unsigned long xen_ulong_t;
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
--- linux-ec2-2.6.32.orig/arch/x86/include/asm/uv/uv_hub.h
+++ linux-ec2-2.6.32/arch/x86/include/asm/uv/uv_hub.h
@@ -11,7 +11,7 @@
 #ifndef _ASM_X86_UV_UV_HUB_H
 #define _ASM_X86_UV_UV_HUB_H
 
-#ifdef CONFIG_X86_64
+#ifdef CONFIG_X86_UV
 #include <linux/numa.h>
 #include <linux/percpu.h>
 #include <linux/timer.h>
@@ -31,20 +31,20 @@
  *		  contiguous (although various IO spaces may punch holes in
  *		  it)..
  *
- * 	N	- Number of bits in the node portion of a socket physical
- * 		  address.
+ *	N	- Number of bits in the node portion of a socket physical
+ *		  address.
  *
- * 	NASID   - network ID of a router, Mbrick or Cbrick. Nasid values of
- * 	 	  routers always have low bit of 1, C/MBricks have low bit
- * 		  equal to 0. Most addressing macros that target UV hub chips
- * 		  right shift the NASID by 1 to exclude the always-zero bit.
- * 		  NASIDs contain up to 15 bits.
+ *	NASID   - network ID of a router, Mbrick or Cbrick. Nasid values of
+ *		  routers always have low bit of 1, C/MBricks have low bit
+ *		  equal to 0. Most addressing macros that target UV hub chips
+ *		  right shift the NASID by 1 to exclude the always-zero bit.
+ *		  NASIDs contain up to 15 bits.
  *
  *	GNODE   - NASID right shifted by 1 bit. Most mmrs contain gnodes instead
  *		  of nasids.
  *
- * 	PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
- * 		  of the nasid for socket usage.
+ *	PNODE   - the low N bits of the GNODE. The PNODE is the most useful variant
+ *		  of the nasid for socket usage.
  *
  *
  *  NumaLink Global Physical Address Format:
@@ -71,12 +71,12 @@
  *
  *
  * APICID format
- * 	NOTE!!!!!! This is the current format of the APICID. However, code
- * 	should assume that this will change in the future. Use functions
- * 	in this file for all APICID bit manipulations and conversion.
+ *	NOTE!!!!!! This is the current format of the APICID. However, code
+ *	should assume that this will change in the future. Use functions
+ *	in this file for all APICID bit manipulations and conversion.
  *
- * 		1111110000000000
- * 		5432109876543210
+ *		1111110000000000
+ *		5432109876543210
  *		pppppppppplc0cch
  *		sssssssssss
  *
@@ -89,9 +89,9 @@
  *	Note: Processor only supports 12 bits in the APICID register. The ACPI
  *	      tables hold all 16 bits. Software needs to be aware of this.
  *
- * 	      Unless otherwise specified, all references to APICID refer to
- * 	      the FULL value contained in ACPI tables, not the subset in the
- * 	      processor APICID register.
+ *	      Unless otherwise specified, all references to APICID refer to
+ *	      the FULL value contained in ACPI tables, not the subset in the
+ *	      processor APICID register.
  */
 
 
@@ -151,16 +151,16 @@
 };
 
 DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-#define uv_hub_info 		(&__get_cpu_var(__uv_hub_info))
+#define uv_hub_info		(&__get_cpu_var(__uv_hub_info))
 #define uv_cpu_hub_info(cpu)	(&per_cpu(__uv_hub_info, cpu))
 
 /*
  * Local & Global MMR space macros.
- * 	Note: macros are intended to be used ONLY by inline functions
- * 	in this file - not by other kernel code.
- * 		n -  NASID (full 15-bit global nasid)
- * 		g -  GNODE (full 15-bit global nasid, right shifted 1)
- * 		p -  PNODE (local part of nsids, right shifted 1)
+ *	Note: macros are intended to be used ONLY by inline functions
+ *	in this file - not by other kernel code.
+ *		n -  NASID (full 15-bit global nasid)
+ *		g -  GNODE (full 15-bit global nasid, right shifted 1)
+ *		p -  PNODE (local part of nsids, right shifted 1)
  */
 #define UV_NASID_TO_PNODE(n)		(((n) >> 1) & uv_hub_info->pnode_mask)
 #define UV_PNODE_TO_GNODE(p)		((p) |uv_hub_info->gnode_extra)
@@ -213,8 +213,8 @@
 /*
  * Macros for converting between kernel virtual addresses, socket local physical
  * addresses, and UV global physical addresses.
- * 	Note: use the standard __pa() & __va() macros for converting
- * 	      between socket virtual and socket physical addresses.
+ *	Note: use the standard __pa() & __va() macros for converting
+ *	      between socket virtual and socket physical addresses.
  */
 
 /* socket phys RAM --> UV global physical address */
@@ -265,21 +265,18 @@
  * Access global MMRs using the low memory MMR32 space. This region supports
  * faster MMR access but not all MMRs are accessible in this space.
  */
-static inline unsigned long *uv_global_mmr32_address(int pnode,
-				unsigned long offset)
+static inline unsigned long *uv_global_mmr32_address(int pnode, unsigned long offset)
 {
 	return __va(UV_GLOBAL_MMR32_BASE |
 		       UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset);
 }
 
-static inline void uv_write_global_mmr32(int pnode, unsigned long offset,
-				 unsigned long val)
+static inline void uv_write_global_mmr32(int pnode, unsigned long offset, unsigned long val)
 {
 	writeq(val, uv_global_mmr32_address(pnode, offset));
 }
 
-static inline unsigned long uv_read_global_mmr32(int pnode,
-						 unsigned long offset)
+static inline unsigned long uv_read_global_mmr32(int pnode, unsigned long offset)
 {
 	return readq(uv_global_mmr32_address(pnode, offset));
 }
@@ -288,25 +285,32 @@
  * Access Global MMR space using the MMR space located at the top of physical
  * memory.
  */
-static inline unsigned long *uv_global_mmr64_address(int pnode,
-				unsigned long offset)
+static inline unsigned long *uv_global_mmr64_address(int pnode, unsigned long offset)
 {
 	return __va(UV_GLOBAL_MMR64_BASE |
 		    UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset);
 }
 
-static inline void uv_write_global_mmr64(int pnode, unsigned long offset,
-				unsigned long val)
+static inline void uv_write_global_mmr64(int pnode, unsigned long offset, unsigned long val)
 {
 	writeq(val, uv_global_mmr64_address(pnode, offset));
 }
 
-static inline unsigned long uv_read_global_mmr64(int pnode,
-						 unsigned long offset)
+static inline unsigned long uv_read_global_mmr64(int pnode, unsigned long offset)
 {
 	return readq(uv_global_mmr64_address(pnode, offset));
 }
 
+static inline void uv_write_global_mmr8(int pnode, unsigned long offset, unsigned char val)
+{
+	writeb(val, uv_global_mmr64_address(pnode, offset));
+}
+
+static inline unsigned char uv_read_global_mmr8(int pnode, unsigned long offset)
+{
+	return readb(uv_global_mmr64_address(pnode, offset));
+}
+
 /*
  * Access hub local MMRs. Faster than using global space but only local MMRs
  * are accessible.
@@ -426,11 +430,17 @@
 	}
 }
 
+static inline unsigned long uv_scir_offset(int apicid)
+{
+	return SCIR_LOCAL_MMR_BASE | (apicid & 0x3f);
+}
+
 static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
 {
 	if (uv_cpu_hub_info(cpu)->scir.state != value) {
+		uv_write_global_mmr8(uv_cpu_to_pnode(cpu),
+				uv_cpu_hub_info(cpu)->scir.offset, value);
 		uv_cpu_hub_info(cpu)->scir.state = value;
-		uv_write_local_mmr8(uv_cpu_hub_info(cpu)->scir.offset, value);
 	}
 }
 
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable_32.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable_32.h
@@ -0,0 +1,99 @@
+#ifndef _ASM_X86_PGTABLE_32_H
+#define _ASM_X86_PGTABLE_32_H
+
+#include <asm/pgtable_32_types.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * the i386, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * i386 mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the i386 page table tree.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <asm/fixmap.h>
+#include <linux/threads.h>
+
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+
+struct vm_area_struct;
+
+extern pgd_t *swapper_pg_dir;
+
+static inline void pgtable_cache_init(void) { }
+static inline void check_pgt_cache(void) { }
+void paging_init(void);
+
+extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t);
+
+
+/*
+ * Define this if things work differently on an i386 and an i486:
+ * it will (on an i486) warn about kernel memory accesses that are
+ * done without a 'access_ok(VERIFY_WRITE,..)'
+ */
+#undef TEST_ACCESS_OK
+
+#ifdef CONFIG_X86_PAE
+# include <asm/pgtable-3level.h>
+#else
+# include <asm/pgtable-2level.h>
+#endif
+
+#if defined(CONFIG_HIGHPTE)
+#define __KM_PTE			\
+	(in_nmi() ? KM_NMI_PTE : 	\
+	 in_irq() ? KM_IRQ_PTE :	\
+	 KM_PTE0)
+#define pte_offset_map(dir, address)					\
+	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) +		\
+	 pte_index((address)))
+#define pte_offset_map_nested(dir, address)				\
+	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
+	 pte_index((address)))
+#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
+#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+#else
+#define pte_offset_map(dir, address)					\
+	((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
+#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+#endif
+
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr)					\
+do {									\
+	if (HYPERVISOR_update_va_mapping(vaddr, __pte(0), UVMF_INVLPG)) \
+		BUG(); \
+} while (0)
+
+/*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+#define update_mmu_cache(vma, address, pte) do { } while (0)
+
+void make_lowmem_page_readonly(void *va, unsigned int feature);
+void make_lowmem_page_writable(void *va, unsigned int feature);
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * kern_addr_valid() is (1) for FLATMEM and (0) for
+ * SPARSEMEM and DISCONTIGMEM
+ */
+#ifdef CONFIG_FLATMEM
+#define kern_addr_valid(addr)	(1)
+#else
+#define kern_addr_valid(kaddr)	(0)
+#endif
+
+#endif /* _ASM_X86_PGTABLE_32_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/desc.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/desc.h
@@ -0,0 +1,421 @@
+#ifndef _ASM_X86_DESC_H
+#define _ASM_X86_DESC_H
+
+#include <asm/desc_defs.h>
+#include <asm/ldt.h>
+#include <asm/mmu.h>
+#include <linux/smp.h>
+
+static inline void fill_ldt(struct desc_struct *desc,
+			    const struct user_desc *info)
+{
+	desc->limit0 = info->limit & 0x0ffff;
+	desc->base0 = info->base_addr & 0x0000ffff;
+
+	desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
+	desc->type = (info->read_exec_only ^ 1) << 1;
+	desc->type |= info->contents << 2;
+	desc->s = 1;
+	desc->dpl = 0x3;
+	desc->p = info->seg_not_present ^ 1;
+	desc->limit = (info->limit & 0xf0000) >> 16;
+	desc->avl = info->useable;
+	desc->d = info->seg_32bit;
+	desc->g = info->limit_in_pages;
+	desc->base2 = (info->base_addr & 0xff000000) >> 24;
+	/*
+	 * Don't allow setting of the lm bit. It is useless anyway
+	 * because 64bit system calls require __USER_CS:
+	 */
+	desc->l = 0;
+}
+
+#ifndef CONFIG_X86_NO_IDT
+extern struct desc_ptr idt_descr;
+extern gate_desc idt_table[];
+#endif
+
+struct gdt_page {
+	struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
+
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+	return per_cpu(gdt_page, cpu).gdt;
+}
+
+#ifdef CONFIG_X86_64
+
+static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+			     unsigned dpl, unsigned ist, unsigned seg)
+{
+	gate->offset_low = PTR_LOW(func);
+	gate->segment = __KERNEL_CS;
+	gate->ist = ist;
+	gate->p = 1;
+	gate->dpl = dpl;
+	gate->zero0 = 0;
+	gate->zero1 = 0;
+	gate->type = type;
+	gate->offset_middle = PTR_MIDDLE(func);
+	gate->offset_high = PTR_HIGH(func);
+}
+
+#else
+static inline void pack_gate(gate_desc *gate, unsigned char type,
+			     unsigned long base, unsigned dpl, unsigned flags,
+			     unsigned short seg)
+{
+	gate->a = (seg << 16) | (base & 0xffff);
+	gate->b = (base & 0xffff0000) |
+		  (((0x80 | type | (dpl << 5)) & 0xff) << 8);
+}
+
+#endif
+
+static inline int desc_empty(const void *ptr)
+{
+	const u32 *desc = ptr;
+	return !(desc[0] | desc[1]);
+}
+
+#ifndef CONFIG_XEN
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
+#define load_tr(tr) asm volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) asm volatile("lldt %0"::"m" (ldt))
+
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
+
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
+
+#define write_ldt_entry(dt, entry, desc)	\
+	native_write_ldt_entry(dt, entry, desc)
+#define write_gdt_entry(dt, entry, desc, type)		\
+	native_write_gdt_entry(dt, entry, desc, type)
+#define write_idt_entry(dt, entry, g)		\
+	native_write_idt_entry(dt, entry, g)
+
+static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
+{
+}
+
+static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
+{
+}
+
+#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
+
+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+					  const gate_desc *gate)
+{
+	memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+					  const void *desc)
+{
+	memcpy(&ldt[entry], desc, 8);
+}
+
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+					  const void *desc, int type)
+{
+	unsigned int size;
+	switch (type) {
+	case DESC_TSS:
+		size = sizeof(tss_desc);
+		break;
+	case DESC_LDT:
+		size = sizeof(ldt_desc);
+		break;
+	default:
+		size = sizeof(struct desc_struct);
+		break;
+	}
+	memcpy(&gdt[entry], desc, size);
+}
+#endif
+
+static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+				   unsigned long limit, unsigned char type,
+				   unsigned char flags)
+{
+	desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+	desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+		(limit & 0x000f0000) | ((type & 0xff) << 8) |
+		((flags & 0xf) << 20);
+	desc->p = 1;
+}
+
+
+#ifndef CONFIG_XEN
+static inline void set_tssldt_descriptor(void *d, unsigned long addr,
+					 unsigned type, unsigned size)
+{
+#ifdef CONFIG_X86_64
+	struct ldttss_desc64 *desc = d;
+	memset(desc, 0, sizeof(*desc));
+	desc->limit0 = size & 0xFFFF;
+	desc->base0 = PTR_LOW(addr);
+	desc->base1 = PTR_MIDDLE(addr) & 0xFF;
+	desc->type = type;
+	desc->p = 1;
+	desc->limit1 = (size >> 16) & 0xF;
+	desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
+	desc->base3 = PTR_HIGH(addr);
+#else
+	pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+#endif
+}
+
+static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+{
+	struct desc_struct *d = get_cpu_gdt_table(cpu);
+	tss_desc tss;
+
+	/*
+	 * sizeof(unsigned long) coming from an extra "long" at the end
+	 * of the iobitmap. See tss_struct definition in processor.h
+	 *
+	 * -1? seg base+limit should be pointing to the address of the
+	 * last valid byte
+	 */
+	set_tssldt_descriptor(&tss, (unsigned long)addr, DESC_TSS,
+			      IO_BITMAP_OFFSET + IO_BITMAP_BYTES +
+			      sizeof(unsigned long) - 1);
+	write_gdt_entry(d, entry, &tss, DESC_TSS);
+}
+
+#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
+static inline void native_set_ldt(const void *addr, unsigned int entries)
+{
+	if (likely(entries == 0))
+		asm volatile("lldt %w0"::"q" (0));
+	else {
+		unsigned cpu = smp_processor_id();
+		ldt_desc ldt;
+
+		set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,
+				      entries * LDT_ENTRY_SIZE - 1);
+		write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+				&ldt, DESC_LDT);
+		asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+	}
+}
+
+static inline void native_load_tr_desc(void)
+{
+	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct desc_ptr *dtr)
+{
+	asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct desc_ptr *dtr)
+{
+	asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct desc_ptr *dtr)
+{
+	asm volatile("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct desc_ptr *dtr)
+{
+	asm volatile("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+	unsigned long tr;
+	asm volatile("str %0":"=r" (tr));
+	return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+	unsigned int i;
+	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+#else
+#include <asm/pgtable.h>
+
+#define load_TLS(t, cpu) xen_load_tls(t, cpu)
+#define set_ldt xen_set_ldt
+
+extern int write_ldt_entry(struct desc_struct *ldt, int entry,
+			   const void *desc);
+extern int write_gdt_entry(struct desc_struct *gdt, int entry,
+			   const void *desc, int type);
+
+static inline void xen_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+	unsigned int i;
+	struct desc_struct *gdt = get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN;
+
+	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+		if (HYPERVISOR_update_descriptor(
+				arbitrary_virt_to_machine(&gdt[i]),
+				*(u64 *)&t->tls_array[i]))
+			BUG();
+}
+#endif
+
+#define _LDT_empty(info)				\
+	((info)->base_addr		== 0	&&	\
+	 (info)->limit			== 0	&&	\
+	 (info)->contents		== 0	&&	\
+	 (info)->read_exec_only		== 1	&&	\
+	 (info)->seg_32bit		== 0	&&	\
+	 (info)->limit_in_pages		== 0	&&	\
+	 (info)->seg_not_present	== 1	&&	\
+	 (info)->useable		== 0)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+static inline void clear_LDT(void)
+{
+	set_ldt(NULL, 0);
+}
+
+/*
+ * load one particular LDT into the current CPU
+ */
+static inline void load_LDT_nolock(mm_context_t *pc)
+{
+	set_ldt(pc->ldt, pc->size);
+}
+
+static inline void load_LDT(mm_context_t *pc)
+{
+	preempt_disable();
+	load_LDT_nolock(pc);
+	preempt_enable();
+}
+
+static inline unsigned long get_desc_base(const struct desc_struct *desc)
+{
+	return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
+}
+
+static inline void set_desc_base(struct desc_struct *desc, unsigned long base)
+{
+	desc->base0 = base & 0xffff;
+	desc->base1 = (base >> 16) & 0xff;
+	desc->base2 = (base >> 24) & 0xff;
+}
+
+static inline unsigned long get_desc_limit(const struct desc_struct *desc)
+{
+	return desc->limit0 | (desc->limit << 16);
+}
+
+static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
+{
+	desc->limit0 = limit & 0xffff;
+	desc->limit = (limit >> 16) & 0xf;
+}
+
+#ifndef CONFIG_X86_NO_IDT
+static inline void _set_gate(int gate, unsigned type, void *addr,
+			     unsigned dpl, unsigned ist, unsigned seg)
+{
+	gate_desc s;
+	pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+	/*
+	 * does not need to be atomic because it is only done once at
+	 * setup time
+	 */
+	write_idt_entry(idt_table, gate, &s);
+}
+
+/*
+ * This needs to use 'idt_table' rather than 'idt', and
+ * thus use the _nonmapped_ version of the IDT, as the
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+static inline void set_intr_gate(unsigned int n, void *addr)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
+
+extern int first_system_vector;
+/* used_vectors is BITMAP for irq is not managed by percpu vector_irq */
+extern unsigned long used_vectors[];
+
+static inline void alloc_system_vector(int vector)
+{
+	if (!test_bit(vector, used_vectors)) {
+		set_bit(vector, used_vectors);
+		if (first_system_vector > vector)
+			first_system_vector = vector;
+	} else
+		BUG();
+}
+
+static inline void alloc_intr_gate(unsigned int n, void *addr)
+{
+	alloc_system_vector(n);
+	set_intr_gate(n, addr);
+}
+
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_system_trap_gate(unsigned int n, void *addr)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_trap_gate(unsigned int n, void *addr)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+}
+
+static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
+}
+
+static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+}
+
+static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+	BUG_ON((unsigned)n > 0xFF);
+	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+}
+#endif
+
+#endif /* _ASM_X86_DESC_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/dma-mapping.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/dma-mapping.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_X86_DMA_MAPPING_H_
+#define _ASM_X86_DMA_MAPPING_H_
+
+#define phys_to_dma _phys_to_dma_
+#define dma_to_phys _dma_to_phys_
+
+#include_next <asm/dma-mapping.h>
+
+#undef phys_to_dma
+#undef dma_to_phys
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return phys_to_machine(paddr);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return machine_to_phys(daddr);
+}
+
+void dma_generic_free_coherent(struct device *, size_t, void *, dma_addr_t);
+
+extern int range_straddles_page_boundary(paddr_t p, size_t size);
+
+#endif /* _ASM_X86_DMA_MAPPING_H_ */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/agp.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/agp.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_X86_AGP_H
+#define _ASM_X86_AGP_H
+
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+
+/*
+ * Functions to keep the agpgart mappings coherent with the MMU. The
+ * GART gives the CPU a physical alias of pages in memory. The alias
+ * region is mapped uncacheable. Make sure there are no conflicting
+ * mappings with different cachability attributes for the same
+ * page. This avoids data corruption on some CPUs.
+ */
+
+#define map_page_into_agp(page) ( \
+	xen_create_contiguous_region((unsigned long)page_address(page), 0, 32) \
+	?: set_pages_uc(page, 1))
+#define unmap_page_from_agp(page) ( \
+	xen_destroy_contiguous_region((unsigned long)page_address(page), 0), \
+	/* only a fallback: xen_destroy_contiguous_region uses PAGE_KERNEL */ \
+	set_pages_wb(page, 1))
+
+/*
+ * Could use CLFLUSH here if the cpu supports it. But then it would
+ * need to be called for each cacheline of the whole page so it may
+ * not be worth it. Would need a page for it.
+ */
+#define flush_agp_cache() wbinvd()
+
+#define virt_to_gart virt_to_machine
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)	({                                          \
+	char *_t; dma_addr_t _d;                                            \
+	_t = dma_alloc_coherent(NULL,PAGE_SIZE<<(order),&_d,GFP_KERNEL);    \
+	_t; })
+#define free_gatt_pages(table, order)	\
+	dma_free_coherent(NULL,PAGE_SIZE<<(order),(table),virt_to_bus(table))
+
+#endif /* _ASM_X86_AGP_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable_types.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable_types.h
@@ -0,0 +1,385 @@
+#ifndef _ASM_X86_PGTABLE_DEFS_H
+#define _ASM_X86_PGTABLE_DEFS_H
+
+#include <linux/const.h>
+#include <asm/page_types.h>
+
+#define FIRST_USER_ADDRESS	0
+
+#define _PAGE_BIT_PRESENT	0	/* is present */
+#define _PAGE_BIT_RW		1	/* writeable */
+#define _PAGE_BIT_USER		2	/* userspace addressable */
+#define _PAGE_BIT_PWT		3	/* page write through */
+#define _PAGE_BIT_PCD		4	/* page cache disabled */
+#define _PAGE_BIT_ACCESSED	5	/* was accessed (raised by CPU) */
+#define _PAGE_BIT_DIRTY		6	/* was written to (raised by CPU) */
+#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
+#define _PAGE_BIT_PAT		7	/* on 4KB pages */
+#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
+#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
+#define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
+#define _PAGE_BIT_HIDDEN	11	/* hidden by kmemcheck */
+#define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
+#define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
+#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
+#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
+
+/* If _PAGE_BIT_PRESENT is clear, we use these: */
+/* - if the user mapped it with PROT_NONE; pte_present gives true */
+#define _PAGE_BIT_PROTNONE	_PAGE_BIT_GLOBAL
+/* - set: nonlinear file mapping, saved PTE; unset:swap */
+#define _PAGE_BIT_FILE		_PAGE_BIT_DIRTY
+
+#define _PAGE_PRESENT	(_AT(pteval_t, 1) << _PAGE_BIT_PRESENT)
+#define _PAGE_RW	(_AT(pteval_t, 1) << _PAGE_BIT_RW)
+#define _PAGE_USER	(_AT(pteval_t, 1) << _PAGE_BIT_USER)
+#define _PAGE_PWT	(_AT(pteval_t, 1) << _PAGE_BIT_PWT)
+#define _PAGE_PCD	(_AT(pteval_t, 1) << _PAGE_BIT_PCD)
+#define _PAGE_ACCESSED	(_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED)
+#define _PAGE_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
+#define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
+#define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
+#define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
+#define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
+#define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
+#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
+#define _PAGE_SPECIAL	(_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
+#define _PAGE_CPA_TEST	(_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST)
+#define __HAVE_ARCH_PTE_SPECIAL
+
+#ifdef CONFIG_KMEMCHECK
+#define _PAGE_HIDDEN	(_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
+#else
+#define _PAGE_HIDDEN	(_AT(pteval_t, 0))
+#endif
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
+#define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
+#else
+#define _PAGE_NX	(_AT(pteval_t, 0))
+#endif
+
+#define _PAGE_FILE	(_AT(pteval_t, 1) << _PAGE_BIT_FILE)
+#define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
+
+#ifndef __ASSEMBLY__
+#if defined(CONFIG_X86_64) && CONFIG_XEN_COMPAT <= 0x030002
+extern unsigned int __kernel_page_user;
+#else
+#define __kernel_page_user 0
+#endif
+#endif
+
+#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)
+
+/* Set of bits not changed in pte_modify */
+#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_CACHE_MASK | _PAGE_IOMAP | \
+			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+/*
+ * PAT settings are part of the hypervisor interface, which sets the
+ * MSR to 0x050100070406 (i.e. WB, WT, UC-, UC, WC, WP [, UC, UC]).
+ */
+#define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT | _PAGE_PAT)
+#define _PAGE_CACHE_WB		(0)
+#define _PAGE_CACHE_WT		(_PAGE_PWT)
+#define _PAGE_CACHE_WC		(_PAGE_PAT)
+#define _PAGE_CACHE_WP		(_PAGE_PAT | _PAGE_PWT)
+#define _PAGE_CACHE_UC_MINUS	(_PAGE_PCD)
+#define _PAGE_CACHE_UC		(_PAGE_PCD | _PAGE_PWT)
+
+#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
+				 _PAGE_ACCESSED | _PAGE_NX)
+
+#define PAGE_SHARED_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW |	\
+					 _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+					 _PAGE_ACCESSED | _PAGE_NX)
+#define PAGE_COPY_EXEC		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+					 _PAGE_ACCESSED)
+#define PAGE_COPY		PAGE_COPY_NOEXEC
+#define PAGE_READONLY		__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+					 _PAGE_ACCESSED | _PAGE_NX)
+#define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
+					 _PAGE_ACCESSED)
+
+#define __PAGE_KERNEL_EXEC						\
+	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | __kernel_page_user)
+#define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
+
+#define __PAGE_KERNEL_RO		(__PAGE_KERNEL & ~_PAGE_RW)
+#define __PAGE_KERNEL_RX		(__PAGE_KERNEL_EXEC & ~_PAGE_RW)
+#define __PAGE_KERNEL_EXEC_NOCACHE	(__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
+#define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_UC_MINUS		(__PAGE_KERNEL | _PAGE_PCD)
+#define __PAGE_KERNEL_VSYSCALL		(__PAGE_KERNEL_RX | _PAGE_USER)
+#define __PAGE_KERNEL_VSYSCALL_NOCACHE	(__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT)
+#define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
+#define __PAGE_KERNEL_LARGE_NOCACHE	(__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
+#define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+
+#define __PAGE_KERNEL_IO		(__PAGE_KERNEL | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_UC_MINUS	(__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP)
+#define __PAGE_KERNEL_IO_WC		(__PAGE_KERNEL_WC | _PAGE_IOMAP)
+
+#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
+#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
+#define PAGE_KERNEL_WC			__pgprot(__PAGE_KERNEL_WC)
+#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
+#define PAGE_KERNEL_UC_MINUS		__pgprot(__PAGE_KERNEL_UC_MINUS)
+#define PAGE_KERNEL_EXEC_NOCACHE	__pgprot(__PAGE_KERNEL_EXEC_NOCACHE)
+#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
+#define PAGE_KERNEL_LARGE_NOCACHE	__pgprot(__PAGE_KERNEL_LARGE_NOCACHE)
+#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
+#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
+#define PAGE_KERNEL_VSYSCALL_NOCACHE	__pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE)
+
+#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#define PAGE_KERNEL_IO_UC_MINUS		__pgprot(__PAGE_KERNEL_IO_UC_MINUS)
+#define PAGE_KERNEL_IO_WC		__pgprot(__PAGE_KERNEL_IO_WC)
+
+/*         xwr */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY_EXEC
+#define __P101	PAGE_READONLY_EXEC
+#define __P110	PAGE_COPY_EXEC
+#define __P111	PAGE_COPY_EXEC
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY_EXEC
+#define __S101	PAGE_READONLY_EXEC
+#define __S110	PAGE_SHARED_EXEC
+#define __S111	PAGE_SHARED_EXEC
+
+/*
+ * early identity mapping  pte attrib macros.
+ */
+#ifdef CONFIG_X86_64
+#define __PAGE_KERNEL_IDENT_LARGE_EXEC	__PAGE_KERNEL_LARGE_EXEC
+#else
+/*
+ * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection
+ * bits are combined, this will alow user to access the high address mapped
+ * VDSO in the presence of CONFIG_COMPAT_VDSO
+ */
+#define PTE_IDENT_ATTR	 0x003		/* PRESENT+RW */
+#define PDE_IDENT_ATTR	 0x067		/* PRESENT+RW+USER+DIRTY+ACCESSED */
+#define PGD_IDENT_ATTR	 0x001		/* PRESENT (no other attributes) */
+#endif
+
+#ifdef CONFIG_X86_32
+# include <asm/pgtable_32_types.h>
+#else
+# include "pgtable_64_types.h"
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
+#define PTE_PFN_MASK		((pteval_t)PHYSICAL_PAGE_MASK)
+
+/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
+#define PTE_FLAGS_MASK		(~PTE_PFN_MASK)
+
+typedef struct pgprot { pgprotval_t pgprot; } pgprot_t;
+
+#include <asm/maddr.h>
+
+typedef struct { pgdval_t pgd; } pgd_t;
+
+#define __pgd_ma(x) ((pgd_t) { (x) } )
+static inline pgd_t xen_make_pgd(pgdval_t val)
+{
+	if (likely(val & _PAGE_PRESENT))
+		val = pte_phys_to_machine(val);
+	return (pgd_t) { val };
+}
+
+#define __pgd_val(x) ((x).pgd)
+static inline pgdval_t xen_pgd_val(pgd_t pgd)
+{
+	pgdval_t ret = __pgd_val(pgd);
+#if PAGETABLE_LEVELS == 2 && CONFIG_XEN_COMPAT <= 0x030002
+	if (likely(ret))
+		ret = machine_to_phys(ret) | _PAGE_PRESENT;
+#else
+	if (likely(ret & _PAGE_PRESENT))
+		ret = pte_machine_to_phys(ret);
+#endif
+	return ret;
+}
+
+static inline pgdval_t pgd_flags(pgd_t pgd)
+{
+	return __pgd_val(pgd) & PTE_FLAGS_MASK;
+}
+
+#if PAGETABLE_LEVELS > 3
+typedef struct { pudval_t pud; } pud_t;
+
+#define __pud_ma(x) ((pud_t) { (x) } )
+static inline pud_t xen_make_pud(pudval_t val)
+{
+	if (likely(val & _PAGE_PRESENT))
+		val = pte_phys_to_machine(val);
+	return (pud_t) { val };
+}
+
+#define __pud_val(x) ((x).pud)
+static inline pudval_t xen_pud_val(pud_t pud)
+{
+	pudval_t ret = __pud_val(pud);
+	if (likely(ret & _PAGE_PRESENT))
+		ret = pte_machine_to_phys(ret);
+	return ret;
+}
+#else
+#include <asm-generic/pgtable-nopud.h>
+
+#define __pud_val(x) __pgd_val((x).pgd)
+static inline pudval_t xen_pud_val(pud_t pud)
+{
+	return xen_pgd_val(pud.pgd);
+}
+#endif
+
+#if PAGETABLE_LEVELS > 2
+typedef struct { pmdval_t pmd; } pmd_t;
+
+#define __pmd_ma(x)	((pmd_t) { (x) } )
+static inline pmd_t xen_make_pmd(pmdval_t val)
+{
+	if (likely(val & _PAGE_PRESENT))
+		val = pte_phys_to_machine(val);
+	return (pmd_t) { val };
+}
+
+#define __pmd_val(x) ((x).pmd)
+static inline pmdval_t xen_pmd_val(pmd_t pmd)
+{
+	pmdval_t ret = __pmd_val(pmd);
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (likely(ret))
+		ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
+#else
+	if (likely(ret & _PAGE_PRESENT))
+		ret = pte_machine_to_phys(ret);
+#endif
+	return ret;
+}
+#else
+#include <asm-generic/pgtable-nopmd.h>
+
+#define __pmd_ma(x) ((pmd_t) { .pud.pgd = __pgd_ma(x) } )
+#define __pmd_val(x) __pgd_val((x).pud.pgd)
+static inline pmdval_t xen_pmd_val(pmd_t pmd)
+{
+	return xen_pgd_val(pmd.pud.pgd);
+}
+#endif
+
+static inline pudval_t pud_flags(pud_t pud)
+{
+	return __pud_val(pud) & PTE_FLAGS_MASK;
+}
+
+static inline pmdval_t pmd_flags(pmd_t pmd)
+{
+	return __pmd_val(pmd) & PTE_FLAGS_MASK;
+}
+
+#define __pte_ma(x) ((pte_t) { .pte = (x) } )
+static inline pte_t xen_make_pte(pteval_t val)
+{
+	if (likely((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT))
+		val = pte_phys_to_machine(val);
+	return (pte_t) { .pte = val };
+}
+
+#define __pte_val(x) ((x).pte)
+static inline pteval_t xen_pte_val(pte_t pte)
+{
+	pteval_t ret = __pte_val(pte);
+	if (likely((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT))
+		ret = pte_machine_to_phys(ret);
+	return ret;
+}
+
+static inline pteval_t pte_flags(pte_t pte)
+{
+	return __pte_val(pte) & PTE_FLAGS_MASK;
+}
+
+#define pgprot_val(x)	((x).pgprot)
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+
+typedef struct page *pgtable_t;
+
+extern pteval_t __supported_pte_mask;
+extern void set_nx(void);
+extern int nx_enabled;
+
+#define pgprot_writecombine	pgprot_writecombine
+extern pgprot_t pgprot_writecombine(pgprot_t prot);
+
+#ifndef CONFIG_XEN
+/* Indicate that x86 has its own track and untrack pfn vma functions */
+#define __HAVE_PFNMAP_TRACKING
+#endif
+
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                              unsigned long size, pgprot_t vma_prot);
+int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+                              unsigned long size, pgprot_t *vma_prot);
+
+/* Install a pte for a particular vaddr in kernel space. */
+void set_pte_vaddr(unsigned long vaddr, pte_t pte);
+
+struct seq_file;
+extern void arch_report_meminfo(struct seq_file *m);
+
+enum {
+	PG_LEVEL_NONE,
+	PG_LEVEL_4K,
+	PG_LEVEL_2M,
+	PG_LEVEL_1G,
+	PG_LEVEL_NUM
+};
+
+#ifdef CONFIG_PROC_FS
+extern void update_page_count(int level, unsigned long pages);
+#else
+static inline void update_page_count(int level, unsigned long pages) { }
+#endif
+
+/*
+ * Helper function that returns the kernel pagetable entry controlling
+ * the virtual address 'address'. NULL means no pagetable entry present.
+ * NOTE: the return type is pte_t but if the pmd is PSE then we return it
+ * as a pte too.
+ */
+extern pte_t *lookup_address(unsigned long address, unsigned int *level);
+
+#endif	/* !__ASSEMBLY__ */
+
+#endif /* _ASM_X86_PGTABLE_DEFS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/hypercall_32.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/hypercall_32.h
@@ -0,0 +1,62 @@
+#define HYPERCALL_arg1 "ebx"
+#define HYPERCALL_arg2 "ecx"
+#define HYPERCALL_arg3 "edx"
+#define HYPERCALL_arg4 "esi"
+#define HYPERCALL_arg5 "edi"
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+static inline int __must_check
+HYPERVISOR_set_callbacks(
+	unsigned long event_selector, unsigned long event_address,
+	unsigned long failsafe_selector, unsigned long failsafe_address)
+{
+	return _hypercall4(int, set_callbacks,
+			   event_selector, event_address,
+			   failsafe_selector, failsafe_address);
+}
+#endif
+
+static inline long __must_check
+HYPERVISOR_set_timer_op(
+	u64 timeout)
+{
+	return _hypercall2(long, set_timer_op,
+			   (unsigned long)timeout,
+			   (unsigned long)(timeout>>32));
+}
+
+static inline int __must_check
+HYPERVISOR_update_descriptor(
+	u64 ma, u64 desc)
+{
+	return _hypercall4(int, update_descriptor,
+			   (unsigned long)ma, (unsigned long)(ma>>32),
+			   (unsigned long)desc, (unsigned long)(desc>>32));
+}
+
+static inline int __must_check
+HYPERVISOR_update_va_mapping(
+	unsigned long va, pte_t new_val, unsigned long flags)
+{
+	unsigned long pte_hi = 0;
+
+	if (arch_use_lazy_mmu_mode())
+		return xen_multi_update_va_mapping(va, new_val, flags);
+#ifdef CONFIG_X86_PAE
+	pte_hi = new_val.pte_high;
+#endif
+	return _hypercall4(int, update_va_mapping, va,
+			   new_val.pte_low, pte_hi, flags);
+}
+
+static inline int __must_check
+HYPERVISOR_update_va_mapping_otherdomain(
+	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+	unsigned long pte_hi = 0;
+#ifdef CONFIG_X86_PAE
+	pte_hi = new_val.pte_high;
+#endif
+	return _hypercall5(int, update_va_mapping_otherdomain, va,
+			   new_val.pte_low, pte_hi, flags, domid);
+}
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/hypercall_64.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/hypercall_64.h
@@ -0,0 +1,54 @@
+#define HYPERCALL_arg1 "rdi"
+#define HYPERCALL_arg2 "rsi"
+#define HYPERCALL_arg3 "rdx"
+#define HYPERCALL_arg4 "r10"
+#define HYPERCALL_arg5 "r8"
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+static inline int __must_check
+HYPERVISOR_set_callbacks(
+	unsigned long event_address, unsigned long failsafe_address, 
+	unsigned long syscall_address)
+{
+	return _hypercall3(int, set_callbacks,
+			   event_address, failsafe_address, syscall_address);
+}
+#endif
+
+static inline long __must_check
+HYPERVISOR_set_timer_op(
+	u64 timeout)
+{
+	return _hypercall1(long, set_timer_op, timeout);
+}
+
+static inline int __must_check
+HYPERVISOR_update_descriptor(
+	unsigned long ma, unsigned long word)
+{
+	return _hypercall2(int, update_descriptor, ma, word);
+}
+
+static inline int __must_check
+HYPERVISOR_update_va_mapping(
+	unsigned long va, pte_t new_val, unsigned long flags)
+{
+	if (arch_use_lazy_mmu_mode())
+		return xen_multi_update_va_mapping(va, new_val, flags);
+	return _hypercall3(int, update_va_mapping, va, new_val.pte, flags);
+}
+
+static inline int __must_check
+HYPERVISOR_update_va_mapping_otherdomain(
+	unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+	return _hypercall4(int, update_va_mapping_otherdomain, va,
+			   new_val.pte, flags, domid);
+}
+
+static inline int __must_check
+HYPERVISOR_set_segment_base(
+	int reg, unsigned long value)
+{
+	return _hypercall2(int, set_segment_base, reg, value);
+}
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/synch_bitops.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/synch_bitops.h
@@ -0,0 +1,126 @@
+#ifndef __XEN_SYNCH_BITOPS_H__
+#define __XEN_SYNCH_BITOPS_H__
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ * Heavily modified to provide guaranteed strong synchronisation
+ * when communicating with Xen or other guest OSes running on other CPUs.
+ */
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#define ADDR (*(volatile long *) addr)
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+    __asm__ __volatile__ ( 
+        "lock btsl %1,%0"
+        : "+m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+    __asm__ __volatile__ (
+        "lock btrl %1,%0"
+        : "+m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ void synch_change_bit(int nr, volatile void * addr)
+{
+    __asm__ __volatile__ (
+        "lock btcl %1,%0"
+        : "+m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+    int oldbit;
+    __asm__ __volatile__ (
+        "lock btsl %2,%1\n\tsbbl %0,%0"
+        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
+    return oldbit;
+}
+
+static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr)
+{
+    int oldbit;
+    __asm__ __volatile__ (
+        "lock btrl %2,%1\n\tsbbl %0,%0"
+        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
+    return oldbit;
+}
+
+static __inline__ int synch_test_and_change_bit(int nr, volatile void * addr)
+{
+    int oldbit;
+
+    __asm__ __volatile__ (
+        "lock btcl %2,%1\n\tsbbl %0,%0"
+        : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory");
+    return oldbit;
+}
+
+struct __synch_xchg_dummy { unsigned long a[100]; };
+#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
+
+#define synch_cmpxchg(ptr, old, new) \
+((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
+                                     (unsigned long)(old), \
+                                     (unsigned long)(new), \
+                                     sizeof(*(ptr))))
+
+static inline unsigned long __synch_cmpxchg(volatile void *ptr,
+					    unsigned long old,
+					    unsigned long new, int size)
+{
+	unsigned long prev;
+	switch (size) {
+	case 1:
+		__asm__ __volatile__("lock; cmpxchgb %b1,%2"
+				     : "=a"(prev)
+				     : "q"(new), "m"(*__synch_xg(ptr)),
+				       "0"(old)
+				     : "memory");
+		return prev;
+	case 2:
+		__asm__ __volatile__("lock; cmpxchgw %w1,%2"
+				     : "=a"(prev)
+				     : "r"(new), "m"(*__synch_xg(ptr)),
+				       "0"(old)
+				     : "memory");
+		return prev;
+#ifdef CONFIG_X86_64
+	case 4:
+		__asm__ __volatile__("lock; cmpxchgl %k1,%2"
+				     : "=a"(prev)
+				     : "r"(new), "m"(*__synch_xg(ptr)),
+				       "0"(old)
+				     : "memory");
+		return prev;
+	case 8:
+		__asm__ __volatile__("lock; cmpxchgq %1,%2"
+				     : "=a"(prev)
+				     : "r"(new), "m"(*__synch_xg(ptr)),
+				       "0"(old)
+				     : "memory");
+		return prev;
+#else
+	case 4:
+		__asm__ __volatile__("lock; cmpxchgl %1,%2"
+				     : "=a"(prev)
+				     : "r"(new), "m"(*__synch_xg(ptr)),
+				       "0"(old)
+				     : "memory");
+		return prev;
+#endif
+	}
+	return old;
+}
+
+#define synch_test_bit test_bit
+
+#define synch_cmpxchg_subword synch_cmpxchg
+
+#endif /* __XEN_SYNCH_BITOPS_H__ */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/maddr_32.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/maddr_32.h
@@ -0,0 +1,182 @@
+#ifndef _I386_MADDR_H
+#define _I386_MADDR_H
+
+#include <asm/bug.h>
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+#define INVALID_P2M_ENTRY	(~0UL)
+#define FOREIGN_FRAME_BIT	(1UL<<31)
+#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
+
+/* Definitions for machine and pseudophysical addresses. */
+#ifdef CONFIG_X86_PAE
+typedef unsigned long long paddr_t;
+typedef unsigned long long maddr_t;
+#else
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+#endif
+
+#ifdef CONFIG_XEN
+
+extern unsigned long *phys_to_machine_mapping;
+extern unsigned long  max_mapnr;
+
+#undef machine_to_phys_mapping
+extern unsigned long *machine_to_phys_mapping;
+extern unsigned int   machine_to_phys_order;
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return pfn;
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return 1;
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+	unsigned long pfn;
+
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return mfn;
+
+	if (unlikely((mfn >> machine_to_phys_order) != 0))
+		return max_mapnr;
+
+	/* The array access can fail (e.g., device space beyond end of RAM). */
+	asm (
+		"1:	movl %1,%0\n"
+		"2:\n"
+		".section .fixup,\"ax\"\n"
+		"3:	movl %2,%0\n"
+		"	jmp  2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b,3b\n"
+		".previous"
+		: "=r" (pfn)
+		: "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
+
+	return pfn;
+}
+
+/*
+ * We detect special mappings in one of two ways:
+ *  1. If the MFN is an I/O page then Xen will set the m2p entry
+ *     to be outside our maximum possible pseudophys range.
+ *  2. If the MFN belongs to a different domain then we will certainly
+ *     not have MFN in our p2m table. Conversely, if the page is ours,
+ *     then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+	unsigned long pfn = mfn_to_pfn(mfn);
+	if (likely(pfn < max_mapnr)
+	    && likely(!xen_feature(XENFEAT_auto_translated_physmap))
+	    && unlikely(phys_to_machine_mapping[pfn] != mfn))
+		return max_mapnr; /* force !pfn_valid() */
+	return pfn;
+}
+
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+		return;
+	}
+	phys_to_machine_mapping[pfn] = mfn;
+}
+
+static inline maddr_t phys_to_machine(paddr_t phys)
+{
+	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+	return machine;
+}
+
+static inline paddr_t machine_to_phys(maddr_t machine)
+{
+	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+	return phys;
+}
+
+#ifdef CONFIG_X86_PAE
+static inline paddr_t pte_phys_to_machine(paddr_t phys)
+{
+	/*
+	 * In PAE mode, the NX bit needs to be dealt with in the value
+	 * passed to pfn_to_mfn(). On x86_64, we need to mask it off,
+	 * but for i386 the conversion to ulong for the argument will
+	 * clip it off.
+	 */
+	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+	machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
+	return machine;
+}
+
+static inline paddr_t pte_machine_to_phys(maddr_t machine)
+{
+	/*
+	 * In PAE mode, the NX bit needs to be dealt with in the value
+	 * passed to mfn_to_pfn(). On x86_64, we need to mask it off,
+	 * but for i386 the conversion to ulong for the argument will
+	 * clip it off.
+	 */
+	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+	phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
+	return phys;
+}
+#else
+#define pte_phys_to_machine phys_to_machine
+#define pte_machine_to_phys machine_to_phys
+#endif
+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn(pfn) (pfn)
+#define mfn_to_pfn(mfn) (mfn)
+#define mfn_to_local_pfn(mfn) (mfn)
+#define set_phys_to_machine(pfn, mfn) ((void)0)
+#define phys_to_machine_mapping_valid(pfn) (1)
+#define phys_to_machine(phys) ((maddr_t)(phys))
+#define machine_to_phys(mach) ((paddr_t)(mach))
+#define pfn_pte_ma(pfn, prot) pfn_pte(pfn, prot)
+#define __pte_ma(x) __pte(x)
+
+#endif /* !CONFIG_XEN */
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)	(phys_to_machine(__pa(v)))
+#define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
+#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#endif /* _I386_MADDR_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/tlbflush.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/tlbflush.h
@@ -0,0 +1,116 @@
+#ifndef _ASM_X86_TLBFLUSH_H
+#define _ASM_X86_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+
+#define __flush_tlb() xen_tlb_flush()
+#define __flush_tlb_global() xen_tlb_flush()
+#define __flush_tlb_single(addr) xen_invlpg(addr)
+#define __flush_tlb_all() xen_tlb_flush()
+#define __flush_tlb_one(addr) xen_invlpg(addr)
+
+#ifdef CONFIG_X86_32
+# define TLB_FLUSH_ALL	0xffffffff
+#else
+# define TLB_FLUSH_ALL	-1ULL
+#endif
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ *
+ * ..but the i386 has somewhat limited tlb flushing capabilities,
+ * and page-granular flushes are available only on i486 and up.
+ *
+ * x86-64 can only flush individual pages or full VMs. For a range flush
+ * we always do the full VM. Might be worth trying if for a small
+ * range a few INVLPGs in a row are a win.
+ */
+
+#ifndef CONFIG_SMP
+
+#define flush_tlb() __flush_tlb()
+#define flush_tlb_all() __flush_tlb_all()
+#define local_flush_tlb() __flush_tlb()
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	if (mm == current->active_mm)
+		__flush_tlb();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long addr)
+{
+	if (vma->vm_mm == current->active_mm)
+		__flush_tlb_one(addr);
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	if (vma->vm_mm == current->active_mm)
+		__flush_tlb();
+}
+
+static inline void reset_lazy_tlbstate(void)
+{
+}
+
+#else  /* SMP */
+
+#include <asm/smp.h>
+
+#define local_flush_tlb() __flush_tlb()
+
+#define flush_tlb_all xen_tlb_flush_all
+#define flush_tlb_current_task() xen_tlb_flush_mask(mm_cpumask(current->mm))
+#define flush_tlb_mm(mm) xen_tlb_flush_mask(mm_cpumask(mm))
+#define flush_tlb_page(vma, va) xen_invlpg_mask(mm_cpumask((vma)->vm_mm), va)
+
+#define flush_tlb()	flush_tlb_current_task()
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	flush_tlb_mm(vma->vm_mm);
+}
+
+#ifndef CONFIG_XEN
+#define TLBSTATE_OK	1
+#define TLBSTATE_LAZY	2
+
+struct tlb_state {
+	struct mm_struct *active_mm;
+	int state;
+};
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
+
+static inline void reset_lazy_tlbstate(void)
+{
+	percpu_write(cpu_tlbstate.state, 0);
+	percpu_write(cpu_tlbstate.active_mm, &init_mm);
+}
+#endif
+
+#endif	/* SMP */
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	flush_tlb_all();
+}
+
+extern void zap_low_mappings(bool early);
+
+#endif /* _ASM_X86_TLBFLUSH_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/spinlock.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/spinlock.h
@@ -0,0 +1,377 @@
+#ifndef _ASM_X86_SPINLOCK_H
+#define _ASM_X86_SPINLOCK_H
+
+#include <asm/atomic.h>
+#include <asm/rwlock.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <linux/compiler.h>
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ *
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * These are fair FIFO ticket locks, which are currently limited to 256
+ * CPUs.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
+ */
+
+#ifdef CONFIG_X86_32
+# define LOCK_PTR_REG "a"
+# define REG_PTR_MODE "k"
+#else
+# define LOCK_PTR_REG "D"
+# define REG_PTR_MODE "q"
+#endif
+
+#if defined(CONFIG_X86_32) && \
+	(defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE))
+/*
+ * On PPro SMP or if we are using OOSTORE, we use a locked operation to unlock
+ * (PPro errata 66, 92)
+ */
+# define UNLOCK_LOCK_PREFIX LOCK_PREFIX
+#else
+# define UNLOCK_LOCK_PREFIX
+#endif
+
+int xen_spinlock_init(unsigned int cpu);
+void xen_spinlock_cleanup(unsigned int cpu);
+extern int xen_spin_wait(raw_spinlock_t *, unsigned int token);
+extern int xen_spin_wait_flags(raw_spinlock_t *, unsigned int *token,
+			       unsigned int flags);
+extern unsigned int xen_spin_adjust(raw_spinlock_t *, unsigned int token);
+extern void xen_spin_kick(raw_spinlock_t *, unsigned int token);
+
+/*
+ * Ticket locks are conceptually two parts, one indicating the current head of
+ * the queue, and the other indicating the current tail. The lock is acquired
+ * by atomically noting the tail and incrementing it by one (thus adding
+ * ourself to the queue and noting our position), then waiting until the head
+ * becomes equal to the the initial value of the tail.
+ *
+ * We use an xadd covering *both* parts of the lock, to increment the tail and
+ * also load the position of the head, which takes care of memory ordering
+ * issues and should be optimal for the uncontended case. Note the tail must be
+ * in the high part, because a wide xadd increment of the low part would carry
+ * up and contaminate the high part.
+ *
+ * With fewer than 2^8 possible CPUs, we can use x86's partial registers to
+ * save some instructions and make the code more elegant. There really isn't
+ * much between them in performance though, especially as locks are out of line.
+ */
+#if (NR_CPUS < 256)
+#define TICKET_SHIFT 8
+#define __ticket_spin_lock_preamble \
+	asm(LOCK_PREFIX "xaddw %w0, %2\n\t" \
+	    "cmpb %h0, %b0\n\t" \
+	    "sete %1" \
+	    : "=&Q" (token), "=qm" (free), "+m" (lock->slock) \
+	    : "0" (0x0100) \
+	    : "memory", "cc")
+#define __ticket_spin_lock_body \
+	asm("1:\t" \
+	    "cmpb %h0, %b0\n\t" \
+	    "je 2f\n\t" \
+	    "decl %1\n\t" \
+	    "jz 2f\n\t" \
+	    "rep ; nop\n\t" \
+	    "movb %2, %b0\n\t" \
+	    /* don't need lfence here, because loads are in-order */ \
+	    "jmp 1b\n" \
+	    "2:" \
+	    : "+Q" (token), "+g" (count) \
+	    : "m" (lock->slock) \
+	    : "memory", "cc")
+
+
+static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
+{
+	int tmp, new;
+
+	asm("movzwl %2, %0\n\t"
+	    "cmpb %h0, %b0\n\t"
+	    "leal 0x100(%" REG_PTR_MODE "0), %1\n\t"
+	    "jne 1f\n\t"
+	    LOCK_PREFIX "cmpxchgw %w1, %2\n\t"
+	    "1:\t"
+	    "sete %b1\n\t"
+	    "movzbl %b1, %0\n\t"
+	    : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
+	    :
+	    : "memory", "cc");
+
+	return tmp;
+}
+
+static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
+{
+	unsigned int token;
+	unsigned char kick;
+
+	asm(UNLOCK_LOCK_PREFIX "incb %2\n\t"
+	    "movzwl %2, %0\n\t"
+	    "cmpb %h0, %b0\n\t"
+	    "setne %1"
+	    : "=&Q" (token), "=qm" (kick), "+m" (lock->slock)
+	    :
+	    : "memory", "cc");
+	if (kick)
+		xen_spin_kick(lock, token);
+}
+#else
+#define TICKET_SHIFT 16
+#define __ticket_spin_lock_preamble \
+	do { \
+		unsigned int tmp; \
+		asm(LOCK_PREFIX "xaddl %0, %2\n\t" \
+		    "shldl $16, %0, %3\n\t" \
+		    "cmpw %w3, %w0\n\t" \
+		    "sete %1" \
+		    : "=&r" (token), "=qm" (free), "+m" (lock->slock), \
+		      "=&g" (tmp) \
+		    : "0" (0x00010000) \
+		    : "memory", "cc"); \
+	} while (0)
+#define __ticket_spin_lock_body \
+	do { \
+		unsigned int tmp; \
+		asm("shldl $16, %0, %2\n" \
+		    "1:\t" \
+		    "cmpw %w2, %w0\n\t" \
+		    "je 2f\n\t" \
+		    "decl %1\n\t" \
+		    "jz 2f\n\t" \
+		    "rep ; nop\n\t" \
+		    "movw %3, %w0\n\t" \
+		    /* don't need lfence here, because loads are in-order */ \
+		    "jmp 1b\n" \
+		    "2:" \
+		    : "+r" (token), "+g" (count), "=&g" (tmp) \
+		    : "m" (lock->slock) \
+		    : "memory", "cc"); \
+	} while (0)
+
+static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
+{
+	int tmp;
+	int new;
+
+	asm("movl %2, %0\n\t"
+	    "movl %0, %1\n\t"
+	    "roll $16, %0\n\t"
+	    "cmpl %0, %1\n\t"
+	    "leal 0x00010000(%" REG_PTR_MODE "0), %1\n\t"
+	    "jne 1f\n\t"
+	    LOCK_PREFIX "cmpxchgl %1, %2\n"
+	    "1:\t"
+	    "sete %b1\n\t"
+	    "movzbl %b1, %0\n\t"
+	    : "=&a" (tmp), "=&q" (new), "+m" (lock->slock)
+	    :
+	    : "memory", "cc");
+
+	return tmp;
+}
+
+static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
+{
+	unsigned int token, tmp;
+	bool kick;
+
+	asm(UNLOCK_LOCK_PREFIX "incw %2\n\t"
+	    "movl %2, %0\n\t"
+	    "shldl $16, %0, %3\n\t"
+	    "cmpw %w3, %w0\n\t"
+	    "setne %1"
+	    : "=&r" (token), "=qm" (kick), "+m" (lock->slock), "=&r" (tmp)
+	    :
+	    : "memory", "cc");
+	if (kick)
+		xen_spin_kick(lock, token);
+}
+#endif
+
+static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
+{
+	int tmp = ACCESS_ONCE(lock->slock);
+
+	return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1 << TICKET_SHIFT) - 1));
+}
+
+static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
+{
+	int tmp = ACCESS_ONCE(lock->slock);
+
+	return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1;
+}
+
+static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
+{
+	unsigned int token, count;
+	bool free;
+
+	__ticket_spin_lock_preamble;
+	if (likely(free))
+		return;
+	token = xen_spin_adjust(lock, token);
+	do {
+		count = 1 << 10;
+		__ticket_spin_lock_body;
+	} while (unlikely(!count) && !xen_spin_wait(lock, token));
+}
+
+static __always_inline void __ticket_spin_lock_flags(raw_spinlock_t *lock,
+						     unsigned long flags)
+{
+	unsigned int token, count;
+	bool free;
+
+	__ticket_spin_lock_preamble;
+	if (likely(free))
+		return;
+	token = xen_spin_adjust(lock, token);
+	do {
+		count = 1 << 10;
+		__ticket_spin_lock_body;
+	} while (unlikely(!count) && !xen_spin_wait_flags(lock, &token, flags));
+}
+
+#ifndef CONFIG_PARAVIRT_SPINLOCKS
+
+static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+{
+	return __ticket_spin_is_locked(lock);
+}
+
+static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+{
+	return __ticket_spin_is_contended(lock);
+}
+#define __raw_spin_is_contended	__raw_spin_is_contended
+
+static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+	__ticket_spin_lock(lock);
+}
+
+static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+	return __ticket_spin_trylock(lock);
+}
+
+static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+	__ticket_spin_unlock(lock);
+}
+
+static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
+						  unsigned long flags)
+{
+	__ticket_spin_lock_flags(lock, flags);
+}
+
+#endif	/* CONFIG_PARAVIRT_SPINLOCKS */
+
+static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+{
+	while (__raw_spin_is_locked(lock))
+		cpu_relax();
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ *
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ */
+
+/**
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static inline int __raw_read_can_lock(raw_rwlock_t *lock)
+{
+	return (int)(lock)->lock > 0;
+}
+
+/**
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static inline int __raw_write_can_lock(raw_rwlock_t *lock)
+{
+	return (lock)->lock == RW_LOCK_BIAS;
+}
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
+{
+	asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
+		     "jns 1f\n"
+		     "call __read_lock_failed\n\t"
+		     "1:\n"
+		     ::LOCK_PTR_REG (rw) : "memory");
+}
+
+static inline void __raw_write_lock(raw_rwlock_t *rw)
+{
+	asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t"
+		     "jz 1f\n"
+		     "call __write_lock_failed\n\t"
+		     "1:\n"
+		     ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory");
+}
+
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
+{
+	atomic_t *count = (atomic_t *)lock;
+
+	if (atomic_dec_return(count) >= 0)
+		return 1;
+	atomic_inc(count);
+	return 0;
+}
+
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
+{
+	atomic_t *count = (atomic_t *)lock;
+
+	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
+		return 1;
+	atomic_add(RW_LOCK_BIAS, count);
+	return 0;
+}
+
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+	asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory");
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+	asm volatile(LOCK_PREFIX "addl %1, %0"
+		     : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory");
+}
+
+#define __raw_read_lock_flags(lock, flags) __raw_read_lock(lock)
+#define __raw_write_lock_flags(lock, flags) __raw_write_lock(lock)
+
+#define _raw_spin_relax(lock)	cpu_relax()
+#define _raw_read_relax(lock)	cpu_relax()
+#define _raw_write_relax(lock)	cpu_relax()
+
+/* The {read|write|spin}_lock() on x86 are full memory barriers. */
+static inline void smp_mb__after_lock(void) { }
+#define ARCH_HAS_SMP_MB_AFTER_LOCK
+
+#endif /* _ASM_X86_SPINLOCK_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable.h
@@ -0,0 +1,742 @@
+#ifndef _ASM_X86_PGTABLE_H
+#define _ASM_X86_PGTABLE_H
+
+#include <asm/page.h>
+#include <asm/e820.h>
+
+#include <asm/pgtable_types.h>
+
+/*
+ * Macro to mark a page protection value as UC-
+ */
+#define pgprot_noncached(prot)					\
+	((boot_cpu_data.x86 > 3)				\
+	 ? (__pgprot(pgprot_val(prot) | _PAGE_CACHE_UC_MINUS))	\
+	 : (prot))
+
+#ifndef __ASSEMBLY__
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern spinlock_t pgd_lock;
+extern struct list_head pgd_list;
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else  /* !CONFIG_PARAVIRT */
+#define set_pte(ptep, pte)		xen_set_pte(ptep, pte)
+#define set_pte_at(mm, addr, ptep, pte)	xen_set_pte_at(mm, addr, ptep, pte)
+
+#define set_pte_atomic(ptep, pte)					\
+	xen_set_pte_atomic(ptep, pte)
+
+#define set_pmd(pmdp, pmd)		xen_set_pmd(pmdp, pmd)
+
+#ifndef __PAGETABLE_PUD_FOLDED
+#define set_pgd(pgdp, pgd)		xen_set_pgd(pgdp, pgd)
+#define pgd_clear(pgd)			xen_pgd_clear(pgd)
+#endif
+
+#ifndef set_pud
+# define set_pud(pudp, pud)		xen_set_pud(pudp, pud)
+#endif
+
+#ifndef __PAGETABLE_PMD_FOLDED
+#define pud_clear(pud)			xen_pud_clear(pud)
+#endif
+
+#define pte_clear(mm, addr, ptep)	xen_pte_clear(mm, addr, ptep)
+#define pmd_clear(pmd)			xen_pmd_clear(pmd)
+
+#define pte_update(mm, addr, ptep)              do { } while (0)
+#define pte_update_defer(mm, addr, ptep)        do { } while (0)
+
+#define pgd_val(x)	xen_pgd_val(x)
+#define __pgd(x)	xen_make_pgd(x)
+
+#ifndef __PAGETABLE_PUD_FOLDED
+#define pud_val(x)	xen_pud_val(x)
+#define __pud(x)	xen_make_pud(x)
+#endif
+
+#ifndef __PAGETABLE_PMD_FOLDED
+#define pmd_val(x)	xen_pmd_val(x)
+#define __pmd(x)	xen_make_pmd(x)
+#endif
+
+#define pte_val(x)	xen_pte_val(x)
+#define __pte(x)	xen_make_pte(x)
+
+#define arch_end_context_switch(prev)	do {} while(0)
+
+#endif	/* CONFIG_PARAVIRT */
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_dirty(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_DIRTY;
+}
+
+static inline int pte_young(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_ACCESSED;
+}
+
+static inline int pte_write(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_RW;
+}
+
+static inline int pte_file(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_FILE;
+}
+
+static inline int pte_huge(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_PSE;
+}
+
+static inline int pte_global(pte_t pte)
+{
+	return 0;
+}
+
+static inline int pte_exec(pte_t pte)
+{
+	return !(pte_flags(pte) & _PAGE_NX);
+}
+
+static inline int pte_special(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_SPECIAL;
+}
+
+#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_IOMAP ? 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))
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+	return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT;
+}
+
+static inline int pmd_large(pmd_t pte)
+{
+	return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+		(_PAGE_PSE | _PAGE_PRESENT);
+}
+
+static inline pte_t pte_set_flags(pte_t pte, pteval_t set)
+{
+	pteval_t v = __pte_val(pte);
+
+	return __pte_ma(v | set);
+}
+
+static inline pte_t pte_clear_flags(pte_t pte, pteval_t clear)
+{
+	pteval_t v = __pte_val(pte);
+
+	return __pte_ma(v & ~clear);
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_DIRTY);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_ACCESSED);
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_RW);
+}
+
+static inline pte_t pte_mkexec(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_NX);
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_DIRTY);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_ACCESSED);
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_RW);
+}
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_PSE);
+}
+
+static inline pte_t pte_clrhuge(pte_t pte)
+{
+	return pte_clear_flags(pte, _PAGE_PSE);
+}
+
+static inline pte_t pte_mkglobal(pte_t pte)
+{
+	return pte;
+}
+
+static inline pte_t pte_clrglobal(pte_t pte)
+{
+	return pte;
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+	return pte_set_flags(pte, _PAGE_SPECIAL);
+}
+
+/*
+ * Mask out unsupported bits in a present pgprot.  Non-present pgprots
+ * can use those bits for other purposes, so leave them be.
+ */
+static inline pgprotval_t massage_pgprot(pgprot_t pgprot)
+{
+	pgprotval_t protval = pgprot_val(pgprot);
+
+	if (protval & _PAGE_PRESENT)
+		protval &= __supported_pte_mask;
+
+	return protval;
+}
+
+static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
+{
+	return __pte(((phys_addr_t)page_nr << PAGE_SHIFT) |
+		     massage_pgprot(pgprot));
+}
+
+static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+{
+	return __pte_ma(((phys_addr_t)page_nr << PAGE_SHIFT) |
+			massage_pgprot(pgprot));
+}
+
+static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+{
+	return __pmd(((phys_addr_t)page_nr << PAGE_SHIFT) |
+		     massage_pgprot(pgprot));
+}
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pteval_t val = pte_val(pte) & _PAGE_CHG_MASK;
+
+	val |= massage_pgprot(newprot) & ~_PAGE_CHG_MASK;
+
+	return __pte(val);
+}
+
+/* mprotect needs to preserve PAT bits when updating vm_page_prot */
+#define pgprot_modify pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+	pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK;
+	pgprotval_t addbits = pgprot_val(newprot);
+	return __pgprot(preservebits | addbits);
+}
+
+#define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
+
+#define canon_pgprot(p) __pgprot(massage_pgprot(p))
+
+static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
+					 unsigned long flags,
+					 unsigned long new_flags)
+{
+	/*
+	 * PAT type is always WB for ISA. So no need to check.
+	 */
+	if (is_ISA_range(paddr, paddr + size - 1))
+		return 1;
+
+	/*
+	 * Certain new memtypes are not allowed with certain
+	 * requested memtype:
+	 * - request is uncached, return cannot be write-back
+	 * - request is write-combine, return cannot be write-back
+	 */
+	if ((flags == _PAGE_CACHE_UC_MINUS &&
+	     new_flags == _PAGE_CACHE_WB) ||
+	    (flags == _PAGE_CACHE_WC &&
+	     new_flags == _PAGE_CACHE_WB)) {
+		return 0;
+	}
+
+	return 1;
+}
+
+pmd_t *populate_extra_pmd(unsigned long vaddr);
+pte_t *populate_extra_pte(unsigned long vaddr);
+#endif	/* __ASSEMBLY__ */
+
+#ifdef CONFIG_X86_32
+# include "pgtable_32.h"
+#else
+# include "pgtable_64.h"
+#endif
+
+#ifndef __ASSEMBLY__
+#include <linux/mm_types.h>
+
+static inline int pte_none(pte_t pte)
+{
+	return !pte.pte;
+}
+
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t a, pte_t b)
+{
+	return a.pte == b.pte;
+}
+
+static inline int pte_present(pte_t a)
+{
+	return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
+}
+
+static inline int pte_hidden(pte_t pte)
+{
+	return pte_flags(pte) & _PAGE_HIDDEN;
+}
+
+static inline int pmd_present(pmd_t pmd)
+{
+#if CONFIG_XEN_COMPAT <= 0x030002
+/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
+   can temporarily clear it. */
+	return __pmd_val(pmd) != 0;
+#else
+	return pmd_flags(pmd) & _PAGE_PRESENT;
+#endif
+}
+
+static inline int pmd_none(pmd_t pmd)
+{
+	/* Only check low word on 32-bit platforms, since it might be
+	   out of sync with upper half. */
+	return (unsigned long)__pmd_val(pmd) == 0;
+}
+
+static inline unsigned long pmd_page_vaddr(pmd_t pmd)
+{
+	return (unsigned long)__va(pmd_val(pmd) & PTE_PFN_MASK);
+}
+
+/*
+ * Currently stuck as a macro due to indirect forward reference to
+ * linux/mmzone.h's __section_mem_map_addr() definition:
+ */
+#define pmd_page(pmd)	pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)
+
+/*
+ * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+ *
+ * this macro returns the index of the entry in the pmd page which would
+ * control the given virtual address
+ */
+static inline unsigned long pmd_index(unsigned long address)
+{
+	return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ *
+ * (Currently stuck as a macro because of indirect forward reference
+ * to linux/mm.h:page_to_nid())
+ */
+#define mk_pte(page, pgprot)   pfn_pte(page_to_pfn(page), (pgprot))
+
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this function returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
+static inline unsigned long pte_index(unsigned long address)
+{
+	return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+}
+
+static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
+{
+	return (pte_t *)pmd_page_vaddr(*pmd) + pte_index(address);
+}
+
+static inline int pmd_bad(pmd_t pmd)
+{
+#if CONFIG_XEN_COMPAT <= 0x030002
+	return (pmd_flags(pmd) & ~_PAGE_USER & ~_PAGE_PRESENT)
+	       != (_KERNPG_TABLE & ~_PAGE_PRESENT);
+#else
+	return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE;
+#endif
+}
+
+static inline unsigned long pages_to_mb(unsigned long npg)
+{
+	return npg >> (20 - PAGE_SHIFT);
+}
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)	\
+	direct_remap_pfn_range(vma, vaddr, pfn, size, prot, DOMID_IO)
+
+#if PAGETABLE_LEVELS > 2
+static inline int pud_none(pud_t pud)
+{
+	return __pud_val(pud) == 0;
+}
+
+static inline int pud_present(pud_t pud)
+{
+	return pud_flags(pud) & _PAGE_PRESENT;
+}
+
+static inline unsigned long pud_page_vaddr(pud_t pud)
+{
+	return (unsigned long)__va((unsigned long)pud_val(pud) & PTE_PFN_MASK);
+}
+
+/*
+ * Currently stuck as a macro due to indirect forward reference to
+ * linux/mmzone.h's __section_mem_map_addr() definition:
+ */
+#define pud_page(pud)		pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
+
+/* Find an entry in the second-level page table.. */
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
+{
+	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
+}
+
+static inline int pud_large(pud_t pud)
+{
+	return (__pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) ==
+		(_PAGE_PSE | _PAGE_PRESENT);
+}
+
+static inline int pud_bad(pud_t pud)
+{
+	return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0;
+}
+#else
+static inline int pud_large(pud_t pud)
+{
+	return 0;
+}
+#endif	/* PAGETABLE_LEVELS > 2 */
+
+#if PAGETABLE_LEVELS > 3
+static inline int pgd_present(pgd_t pgd)
+{
+	return pgd_flags(pgd) & _PAGE_PRESENT;
+}
+
+static inline unsigned long pgd_page_vaddr(pgd_t pgd)
+{
+	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
+}
+
+/*
+ * Currently stuck as a macro due to indirect forward reference to
+ * linux/mmzone.h's __section_mem_map_addr() definition:
+ */
+#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+
+/* to find an entry in a page-table-directory. */
+static inline unsigned long pud_index(unsigned long address)
+{
+	return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
+}
+
+static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
+{
+	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address);
+}
+
+static inline int pgd_bad(pgd_t pgd)
+{
+	return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE;
+}
+
+static inline int pgd_none(pgd_t pgd)
+{
+	return !__pgd_val(pgd);
+}
+#endif	/* PAGETABLE_LEVELS > 3 */
+
+#endif	/* __ASSEMBLY__ */
+
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
+#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
+#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
+#define pgd_offset_k(address) pgd_offset(&init_mm, (address))
+
+
+#define KERNEL_PGD_BOUNDARY	pgd_index(PAGE_OFFSET)
+#define KERNEL_PGD_PTRS		(PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
+
+#ifndef __ASSEMBLY__
+
+#define direct_gbpages 0
+
+/* local pte updates need not use xchg for locking */
+static inline pte_t xen_local_ptep_get_and_clear(pte_t *ptep, pte_t res)
+{
+	xen_set_pte(ptep, __pte(0));
+	return res;
+}
+
+static inline void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
+				  pte_t *ptep , pte_t pte)
+{
+	if ((mm != current->mm && mm != &init_mm) ||
+	    HYPERVISOR_update_va_mapping(addr, pte, 0))
+		xen_set_pte(ptep, pte);
+}
+
+static inline void xen_pte_clear(struct mm_struct *mm, unsigned long addr,
+				 pte_t *ptep)
+{
+	if ((mm != current->mm && mm != &init_mm)
+	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))
+		__xen_pte_clear(ptep);
+}
+
+#ifndef CONFIG_PARAVIRT
+/*
+ * Rules for using pte_update - it must be called after any PTE update which
+ * has not been done using the set_pte / clear_pte interfaces.  It is used by
+ * shadow mode hypervisors to resynchronize the shadow page tables.  Kernel PTE
+ * updates should either be sets, clears, or set_pte_atomic for P->P
+ * transitions, which means this hook should only be called for user PTEs.
+ * This hook implies a P->P protection or access change has taken place, which
+ * requires a subsequent TLB flush.  The notification can optionally be delayed
+ * until the TLB flush event by using the pte_update_defer form of the
+ * interface, but care must be taken to assure that the flush happens while
+ * still holding the same page table lock so that the shadow and primary pages
+ * do not become out of sync on SMP.
+ */
+#define pte_update(mm, addr, ptep)		do { } while (0)
+#define pte_update_defer(mm, addr, ptep)	do { } while (0)
+#endif
+
+/*
+ * We only update the dirty/accessed state if we set
+ * the dirty bit by hand in the kernel, since the hardware
+ * will do the accessed bit for us, and we don't want to
+ * race with other CPU's that might be updating the dirty
+ * bit at the same time.
+ */
+struct vm_area_struct;
+
+#define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma,
+				 unsigned long address, pte_t *ptep,
+				 pte_t entry, int dirty);
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+extern int ptep_test_and_clear_young(struct vm_area_struct *vma,
+				     unsigned long addr, pte_t *ptep);
+
+#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
+extern int ptep_clear_flush_young(struct vm_area_struct *vma,
+				  unsigned long address, pte_t *ptep);
+
+#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+#define ptep_clear_flush(vma, addr, ptep)			\
+({								\
+	pte_t *__ptep = (ptep);					\
+	pte_t __res = *__ptep;					\
+	if (!pte_none(__res) &&					\
+	    ((vma)->vm_mm != current->mm ||			\
+	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
+			uvm_multi(mm_cpumask((vma)->vm_mm)) |	\
+				UVMF_INVLPG))) {		\
+		__xen_pte_clear(__ptep);			\
+		flush_tlb_page(vma, addr);			\
+	}							\
+	__res;							\
+})
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+				       pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!pte_none(pte)
+	    && (mm != &init_mm
+	        || HYPERVISOR_update_va_mapping(addr, __pte(0), 0))) {
+		pte = xen_ptep_get_and_clear(ptep, pte);
+		pte_update(mm, addr, ptep);
+	}
+	return pte;
+}
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+#define ptep_get_and_clear_full(mm, addr, ptep, full)		\
+	((full) ? ({						\
+		pte_t *__ptep = (ptep);				\
+		pte_t __res = *__ptep;				\
+		if (!PagePinned(virt_to_page((mm)->pgd)))	\
+			__xen_pte_clear(__ptep);		\
+		else if (!pte_none(__res))			\
+			xen_l1_entry_update(__ptep, __pte(0));	\
+		__res;						\
+	 }) :							\
+	 ptep_get_and_clear(mm, addr, ptep))
+
+pte_t xen_ptep_get_and_clear_full(struct vm_area_struct *, unsigned long, pte_t *, int);
+
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm,
+				      unsigned long addr, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (pte_write(pte))
+		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
+}
+
+/*
+ * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
+ *
+ *  dst - pointer to pgd range anwhere on a pgd page
+ *  src - ""
+ *  count - the number of pgds to copy.
+ *
+ * dst and src can be on the same page, but the range must not overlap,
+ * and must not cross a page boundary.
+ */
+static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+{
+       memcpy(dst, src, count * sizeof(pgd_t));
+}
+
+#define arbitrary_virt_to_mfn(va)					\
+({									\
+	unsigned int __lvl;						\
+	pte_t *__ptep = lookup_address((unsigned long)(va), &__lvl);	\
+	BUG_ON(!__ptep || __lvl != PG_LEVEL_4K || !pte_present(*__ptep));\
+	pte_mfn(*__ptep);						\
+})
+
+#define arbitrary_virt_to_machine(va)					\
+	(((maddr_t)arbitrary_virt_to_mfn(va) << PAGE_SHIFT)		\
+	 | ((unsigned long)(va) & (PAGE_SIZE - 1)))
+
+#ifdef CONFIG_HIGHPTE
+#include <asm/io.h>
+struct page *kmap_atomic_to_page(void *);
+#define ptep_to_machine(ptep)						\
+({									\
+	pte_t *__ptep = (ptep);						\
+	page_to_phys(kmap_atomic_to_page(__ptep))			\
+		| ((unsigned long)__ptep & (PAGE_SIZE - 1));		\
+})
+#else
+#define ptep_to_machine(ptep)	virt_to_machine(ptep)
+#endif
+
+#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
+static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
+					   pte_t *ptep)
+{
+#if CONFIG_XEN_COMPAT < 0x030300
+	if (unlikely(!xen_feature(XENFEAT_mmu_pt_update_preserve_ad)))
+		return ptep_get_and_clear(mm, addr, ptep);
+#endif
+	return *ptep;
+}
+
+static inline void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
+					   pte_t *ptep, pte_t pte)
+{
+	mmu_update_t u;
+
+#if CONFIG_XEN_COMPAT < 0x030300
+	if (unlikely(!xen_feature(XENFEAT_mmu_pt_update_preserve_ad))) {
+		set_pte_at(mm, addr, ptep, pte);
+		return;
+	}
+#endif
+	u.ptr = ptep_to_machine(ptep) | MMU_PT_UPDATE_PRESERVE_AD;
+	u.val = __pte_val(pte);
+	if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF))
+		BUG();
+}
+
+#include <asm-generic/pgtable.h>
+
+#include <xen/features.h>
+void make_page_readonly(void *va, unsigned int feature);
+void make_page_writable(void *va, unsigned int feature);
+void make_pages_readonly(void *va, unsigned int nr, unsigned int feature);
+void make_pages_writable(void *va, unsigned int nr, unsigned int feature);
+
+struct vm_area_struct;
+
+int direct_remap_pfn_range(struct vm_area_struct *vma,
+                           unsigned long address,
+                           unsigned long mfn,
+                           unsigned long size,
+                           pgprot_t prot,
+                           domid_t  domid);
+int direct_kernel_remap_pfn_range(unsigned long address,
+				  unsigned long mfn,
+				  unsigned long size,
+				  pgprot_t prot,
+				  domid_t  domid);
+int create_lookup_pte_addr(struct mm_struct *mm,
+                           unsigned long address,
+                           uint64_t *ptep);
+int touch_pte_range(struct mm_struct *mm,
+                    unsigned long address,
+                    unsigned long size);
+
+#endif	/* __ASSEMBLY__ */
+
+#endif /* _ASM_X86_PGTABLE_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pci.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pci.h
@@ -0,0 +1,162 @@
+#ifndef _ASM_X86_PCI_H
+#define _ASM_X86_PCI_H
+
+#include <linux/mm.h> /* for struct page */
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+
+#ifdef __KERNEL__
+
+struct pci_sysdata {
+	int		domain;		/* PCI domain */
+	int		node;		/* NUMA node */
+#ifdef CONFIG_X86_64
+	void		*iommu;		/* IOMMU private data */
+#endif
+#ifdef CONFIG_XEN_PCIDEV_FRONTEND
+	struct pcifront_device *pdev;
+#endif
+};
+
+extern int pci_routeirq;
+extern int noioapicquirk;
+extern int noioapicreroute;
+
+/* scan a bus after allocating a pci_sysdata for it */
+extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
+					    int node);
+extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
+
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+	struct pci_sysdata *sd = bus->sysdata;
+	return sd->domain;
+}
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+	return pci_domain_nr(bus);
+}
+
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+   already-configured bus numbers - to be used for buggy BIOSes
+   or architectures with incomplete PCI setup by the loader */
+
+#ifdef CONFIG_PCI
+extern unsigned int pcibios_assign_all_busses(void);
+#else
+#define pcibios_assign_all_busses()	0
+#endif
+
+#include <asm/hypervisor.h>
+#define pcibios_scan_all_fns(a, b)	(!is_initial_xendomain())
+
+extern unsigned long pci_mem_start;
+#define PCIBIOS_MIN_IO		0x1000
+#define PCIBIOS_MIN_MEM		(pci_mem_start)
+
+#define PCIBIOS_MIN_CARDBUS_IO	0x4000
+
+void pcibios_config_init(void);
+struct pci_bus *pcibios_scan_root(int bus);
+
+void pcibios_set_master(struct pci_dev *dev);
+void pcibios_penalize_isa_irq(int irq, int active);
+struct irq_routing_table *pcibios_get_irq_routing_table(void);
+int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+
+
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state,
+			       int write_combine);
+
+
+#ifdef CONFIG_PCI
+extern void early_quirks(void);
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+					enum pci_dma_burst_strategy *strat,
+					unsigned long *strategy_parameter)
+{
+	*strat = PCI_DMA_BURST_INFINITY;
+	*strategy_parameter = ~0UL;
+}
+#else
+static inline void early_quirks(void) { }
+#endif
+
+extern void pci_iommu_alloc(void);
+
+/* MSI arch hooks */
+#define arch_setup_msi_irqs arch_setup_msi_irqs
+#define arch_teardown_msi_irqs arch_teardown_msi_irqs
+
+#define PCI_DMA_BUS_IS_PHYS 0
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG) \
+	|| defined(CONFIG_SWIOTLB)
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
+	        dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)         \
+	        __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)                  \
+	        ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)         \
+	        (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)                    \
+	        ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)           \
+	        (((PTR)->LEN_NAME) = (VAL))
+
+#else
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       dma_addr_t ADDR_NAME[0];
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0];
+#define pci_unmap_addr(PTR, ADDR_NAME)  sizeof((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
+	        do { break; } while (pci_unmap_addr(PTR, ADDR_NAME))
+#define pci_unmap_len(PTR, LEN_NAME)            sizeof((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
+	        do { break; } while (pci_unmap_len(PTR, LEN_NAME))
+
+#endif
+
+#endif  /* __KERNEL__ */
+
+#ifdef CONFIG_X86_64
+#include "../../asm/pci_64.h"
+#endif
+
+/* implement the pci_ DMA API in terms of the generic device dma_ one */
+#include <asm-generic/pci-dma-compat.h>
+
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+#define PCIBIOS_MAX_MEM_32 0xffffffff
+
+#ifdef CONFIG_NUMA
+/* Returns the node based on pci bus */
+static inline int __pcibus_to_node(const struct pci_bus *bus)
+{
+	const struct pci_sysdata *sd = bus->sysdata;
+
+	return sd->node;
+}
+
+static inline const struct cpumask *
+cpumask_of_pcibus(const struct pci_bus *bus)
+{
+	int node;
+
+	node = __pcibus_to_node(bus);
+	return (node == -1) ? cpu_online_mask :
+			      cpumask_of_node(node);
+}
+#endif
+
+#endif /* _ASM_X86_PCI_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable-3level_types.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable-3level_types.h
@@ -0,0 +1,44 @@
+#ifndef _ASM_X86_PGTABLE_3LEVEL_DEFS_H
+#define _ASM_X86_PGTABLE_3LEVEL_DEFS_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+typedef u64	pteval_t;
+typedef u64	pmdval_t;
+typedef u64	pudval_t;
+typedef u64	pgdval_t;
+typedef u64	pgprotval_t;
+
+typedef union {
+	struct {
+		unsigned long pte_low, pte_high;
+	};
+	pteval_t pte;
+} pte_t;
+#endif	/* !__ASSEMBLY__ */
+
+#define SHARED_KERNEL_PMD	0
+
+#define PAGETABLE_LEVELS	3
+
+/*
+ * PGDIR_SHIFT determines what a top-level page table entry can map
+ */
+#define PGDIR_SHIFT	30
+#define PTRS_PER_PGD	4
+
+/*
+ * PMD_SHIFT determines the size of the area a middle-level
+ * page table can map
+ */
+#define PMD_SHIFT	21
+#define PTRS_PER_PMD	512
+
+/*
+ * entries per page directory level
+ */
+#define PTRS_PER_PTE	512
+
+
+#endif /* _ASM_X86_PGTABLE_3LEVEL_DEFS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/system.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/system.h
@@ -0,0 +1,440 @@
+#ifndef _ASM_X86_SYSTEM_H
+#define _ASM_X86_SYSTEM_H
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+#include <asm/hypervisor.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/* entries in ARCH_DLINFO: */
+#ifdef CONFIG_IA32_EMULATION
+# define AT_VECTOR_SIZE_ARCH 2
+#else
+# define AT_VECTOR_SIZE_ARCH 1
+#endif
+
+struct task_struct; /* one of the stranger aspects of C forward declarations */
+struct task_struct *__switch_to(struct task_struct *prev,
+				struct task_struct *next);
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
+
+#ifdef CONFIG_X86_32
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary							\
+	"movl %P[task_canary](%[next]), %%ebx\n\t"			\
+	"movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
+#define __switch_canary_oparam						\
+	, [stack_canary] "=m" (per_cpu_var(stack_canary.canary))
+#define __switch_canary_iparam						\
+	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else	/* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif	/* CC_STACKPROTECTOR */
+
+/*
+ * Saving eflags is important. It switches not only IOPL between tasks,
+ * it also protects other tasks from NT leaking through sysenter etc.
+ */
+#define switch_to(prev, next, last)					\
+do {									\
+	/*								\
+	 * Context-switching clobbers all registers, so we clobber	\
+	 * them explicitly, via unused output variables.		\
+	 * (EAX and EBP is not listed because EBP is saved/restored	\
+	 * explicitly for wchan access and EAX is the return value of	\
+	 * __switch_to())						\
+	 */								\
+	unsigned long ebx, ecx, edx, esi, edi;				\
+									\
+	asm volatile("pushfl\n\t"		/* save    flags */	\
+		     "pushl %%ebp\n\t"		/* save    EBP   */	\
+		     "movl %%esp,%[prev_sp]\n\t"	/* save    ESP   */ \
+		     "movl %[next_sp],%%esp\n\t"	/* restore ESP   */ \
+		     "movl $1f,%[prev_ip]\n\t"	/* save    EIP   */	\
+		     "pushl %[next_ip]\n\t"	/* restore EIP   */	\
+		     __switch_canary					\
+		     "jmp __switch_to\n"	/* regparm call  */	\
+		     "1:\t"						\
+		     "popl %%ebp\n\t"		/* restore EBP   */	\
+		     "popfl\n"			/* restore flags */	\
+									\
+		     /* output parameters */				\
+		     : [prev_sp] "=m" (prev->thread.sp),		\
+		       [prev_ip] "=m" (prev->thread.ip),		\
+		       "=a" (last),					\
+									\
+		       /* clobbered output registers: */		\
+		       "=b" (ebx), "=c" (ecx), "=d" (edx),		\
+		       "=S" (esi), "=D" (edi)				\
+		       							\
+		       __switch_canary_oparam				\
+									\
+		       /* input parameters: */				\
+		     : [next_sp]  "m" (next->thread.sp),		\
+		       [next_ip]  "m" (next->thread.ip),		\
+		       							\
+		       /* regparm parameters for __switch_to(): */	\
+		       [prev]     "a" (prev),				\
+		       [next]     "d" (next)				\
+									\
+		       __switch_canary_iparam				\
+									\
+		     : /* reloaded segment registers */			\
+			"memory");					\
+} while (0)
+
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+#else
+#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
+#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
+
+/* frame pointer must be last for get_wchan */
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
+
+#define __EXTRA_CLOBBER  \
+	, "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
+	  "r12", "r13", "r14", "r15"
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+#define __switch_canary							  \
+	"movq %P[task_canary](%%rsi),%%r8\n\t"				  \
+	"movq %%r8,"__percpu_arg([gs_canary])"\n\t"
+#define __switch_canary_oparam						  \
+	, [gs_canary] "=m" (per_cpu_var(irq_stack_union.stack_canary))
+#define __switch_canary_iparam						  \
+	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
+#else	/* CC_STACKPROTECTOR */
+#define __switch_canary
+#define __switch_canary_oparam
+#define __switch_canary_iparam
+#endif	/* CC_STACKPROTECTOR */
+
+/* Save restore flags to clear handle leaking NT */
+#define switch_to(prev, next, last) \
+	asm volatile(SAVE_CONTEXT					  \
+	     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */	  \
+	     "movq %P[threadrsp](%[next]),%%rsp\n\t" /* restore RSP */	  \
+	     "call __switch_to\n\t"					  \
+	     ".globl thread_return\n"					  \
+	     "thread_return:\n\t"					  \
+	     "movq "__percpu_arg([current_task])",%%rsi\n\t"		  \
+	     __switch_canary						  \
+	     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
+	     "movq %%rax,%%rdi\n\t" 					  \
+	     "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"	  \
+	     "jnz   ret_from_fork\n\t"					  \
+	     RESTORE_CONTEXT						  \
+	     : "=a" (last)					  	  \
+	       __switch_canary_oparam					  \
+	     : [next] "S" (next), [prev] "D" (prev),			  \
+	       [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
+	       [ti_flags] "i" (offsetof(struct thread_info, flags)),	  \
+	       [_tif_fork] "i" (_TIF_FORK),			  	  \
+	       [thread_info] "i" (offsetof(struct task_struct, stack)),   \
+	       [current_task] "m" (per_cpu_var(current_task))		  \
+	       __switch_canary_iparam					  \
+	     : "memory", "cc" __EXTRA_CLOBBER)
+#endif
+
+#ifdef __KERNEL__
+
+extern void xen_load_gs_index(unsigned);
+
+/*
+ * Load a segment. Fall back on loading the zero
+ * segment if something goes wrong..
+ */
+#define loadsegment(seg, value)			\
+	asm volatile("\n"			\
+		     "1:\t"			\
+		     "movl %k0,%%" #seg "\n"	\
+		     "2:\n"			\
+		     ".section .fixup,\"ax\"\n"	\
+		     "3:\t"			\
+		     "movl %k1, %%" #seg "\n\t"	\
+		     "jmp 2b\n"			\
+		     ".previous\n"		\
+		     _ASM_EXTABLE(1b,3b)	\
+		     : :"r" (value), "r" (0) : "memory")
+
+
+/*
+ * Save a segment register away
+ */
+#define savesegment(seg, value)				\
+	asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
+
+/*
+ * x86_32 user gs accessors.
+ */
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_32_LAZY_GS
+#define get_user_gs(regs)	(u16)({unsigned long v; savesegment(gs, v); v;})
+#define set_user_gs(regs, v)	loadsegment(gs, (unsigned long)(v))
+#define task_user_gs(tsk)	((tsk)->thread.gs)
+#define lazy_save_gs(v)		savesegment(gs, (v))
+#define lazy_load_gs(v)		loadsegment(gs, (v))
+#else	/* X86_32_LAZY_GS */
+#define get_user_gs(regs)	(u16)((regs)->gs)
+#define set_user_gs(regs, v)	do { (regs)->gs = (v); } while (0)
+#define task_user_gs(tsk)	(task_pt_regs(tsk)->gs)
+#define lazy_save_gs(v)		do { } while (0)
+#define lazy_load_gs(v)		do { } while (0)
+#endif	/* X86_32_LAZY_GS */
+#endif	/* X86_32 */
+
+static inline unsigned long get_limit(unsigned long segment)
+{
+	unsigned long __limit;
+	asm("lsll %1,%0" : "=r" (__limit) : "r" (segment));
+	return __limit + 1;
+}
+
+static inline void xen_clts(void)
+{
+	HYPERVISOR_fpu_taskswitch(0);
+}
+
+static inline void xen_stts(void)
+{
+	HYPERVISOR_fpu_taskswitch(1);
+}
+
+/*
+ * Volatile isn't enough to prevent the compiler from reordering the
+ * read/write functions for the control registers and messing everything up.
+ * A memory clobber would solve the problem, but would prevent reordering of
+ * all loads stores around it, which can hurt performance. Solution is to
+ * use a variable and mimic reads and writes to it to enforce serialization
+ */
+static unsigned long __force_order;
+
+static inline unsigned long xen_read_cr0(void)
+{
+	unsigned long val;
+	asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+	return val;
+}
+
+static inline void xen_write_cr0(unsigned long val)
+{
+	asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order));
+}
+
+#define xen_read_cr2() vcpu_info_read(arch.cr2)
+#define xen_write_cr2(val) vcpu_info_write(arch.cr2, val)
+
+static inline unsigned long xen_read_cr3(void)
+{
+	unsigned long val;
+	asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+#ifdef CONFIG_X86_32
+	return mfn_to_pfn(xen_cr3_to_pfn(val)) << PAGE_SHIFT;
+#else
+	return machine_to_phys(val);
+#endif
+}
+
+static inline void xen_write_cr3(unsigned long val)
+{
+#ifdef CONFIG_X86_32
+	val = xen_pfn_to_cr3(pfn_to_mfn(val >> PAGE_SHIFT));
+#else
+	val = phys_to_machine(val);
+#endif
+	asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+}
+
+static inline unsigned long xen_read_cr4(void)
+{
+	unsigned long val;
+	asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+	return val;
+}
+
+#define xen_read_cr4_safe() xen_read_cr4()
+
+static inline void xen_write_cr4(unsigned long val)
+{
+	asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));
+}
+
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+	return 0;
+}
+
+static inline void xen_write_cr8(unsigned long val)
+{
+	BUG_ON(val);
+}
+#endif
+
+static inline void xen_wbinvd(void)
+{
+	asm volatile("wbinvd": : :"memory");
+}
+
+#define read_cr0()	(xen_read_cr0())
+#define write_cr0(x)	(xen_write_cr0(x))
+#define read_cr2()	(xen_read_cr2())
+#define write_cr2(x)	(xen_write_cr2(x))
+#define read_cr3()	(xen_read_cr3())
+#define write_cr3(x)	(xen_write_cr3(x))
+#define read_cr4()	(xen_read_cr4())
+#define read_cr4_safe()	(xen_read_cr4_safe())
+#define write_cr4(x)	(xen_write_cr4(x))
+#define wbinvd()	(xen_wbinvd())
+#ifdef CONFIG_X86_64
+#define read_cr8()	(xen_read_cr8())
+#define write_cr8(x)	(xen_write_cr8(x))
+#define load_gs_index   xen_load_gs_index
+#endif
+
+/* Clear the 'TS' bit */
+#define clts()		(xen_clts())
+#define stts()		(xen_stts())
+
+#endif /* __KERNEL__ */
+
+static inline void clflush(volatile void *__p)
+{
+	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
+}
+
+#define nop() asm volatile ("nop")
+
+void disable_hlt(void);
+void enable_hlt(void);
+
+void cpu_idle_wait(void);
+
+extern unsigned long arch_align_stack(unsigned long sp);
+extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
+
+void xen_idle(void);
+
+void stop_this_cpu(void *dummy);
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+/*
+ * Some non-Intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#else
+#define mb() 	asm volatile("mfence":::"memory")
+#define rmb()	asm volatile("lfence":::"memory")
+#define wmb()	asm volatile("sfence" ::: "memory")
+#endif
+
+/**
+ * read_barrier_depends - Flush all pending reads that subsequents reads
+ * depend on.
+ *
+ * No data-dependent reads from memory-like regions are ever reordered
+ * over this barrier.  All reads preceding this primitive are guaranteed
+ * to access memory (but not necessarily other CPUs' caches) before any
+ * reads following this primitive that depend on the data return by
+ * any of the preceding reads.  This primitive is much lighter weight than
+ * rmb() on most CPUs, and is never heavier weight than is
+ * rmb().
+ *
+ * These ordering constraints are respected by both the local CPU
+ * and the compiler.
+ *
+ * Ordering is not guaranteed by anything other than these primitives,
+ * not even by data dependencies.  See the documentation for
+ * memory_barrier() for examples and URLs to more information.
+ *
+ * For example, the following code would force ordering (the initial
+ * value of "a" is zero, "b" is one, and "p" is "&a"):
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	b = 2;
+ *	memory_barrier();
+ *	p = &b;				q = p;
+ *					read_barrier_depends();
+ *					d = *q;
+ * </programlisting>
+ *
+ * because the read of "*q" depends on the read of "p" and these
+ * two reads are separated by a read_barrier_depends().  However,
+ * the following code, with the same initial values for "a" and "b":
+ *
+ * <programlisting>
+ *	CPU 0				CPU 1
+ *
+ *	a = 2;
+ *	memory_barrier();
+ *	b = 3;				y = b;
+ *					read_barrier_depends();
+ *					x = a;
+ * </programlisting>
+ *
+ * does not enforce ordering, since there is no data dependency between
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
+ * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
+ * in cases like this where there are no data dependencies.
+ **/
+
+#define read_barrier_depends()	do { } while (0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+# define smp_rmb()	rmb()
+#else
+# define smp_rmb()	barrier()
+#endif
+#ifdef CONFIG_X86_OOSTORE
+# define smp_wmb() 	wmb()
+#else
+# define smp_wmb()	barrier()
+#endif
+#define smp_read_barrier_depends()	read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define smp_read_barrier_depends()	do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+#endif
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static __always_inline void rdtsc_barrier(void)
+{
+	alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+	alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+#endif /* _ASM_X86_SYSTEM_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/mmu_context.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/mmu_context.h
@@ -0,0 +1,164 @@
+#ifndef _ASM_X86_MMU_CONTEXT_H
+#define _ASM_X86_MMU_CONTEXT_H
+
+#include <asm/desc.h>
+#include <asm/atomic.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+void arch_exit_mmap(struct mm_struct *mm);
+void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
+
+void mm_pin(struct mm_struct *mm);
+void mm_unpin(struct mm_struct *mm);
+void mm_pin_all(void);
+
+static inline void xen_activate_mm(struct mm_struct *prev,
+				   struct mm_struct *next)
+{
+	if (!PagePinned(virt_to_page(next->pgd)))
+		mm_pin(next);
+}
+
+/*
+ * Used for LDT copy/destruction.
+ */
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+void destroy_context(struct mm_struct *mm);
+
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+		percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
+#endif
+}
+
+#define prepare_arch_switch(next)	__prepare_arch_switch()
+
+static inline void __prepare_arch_switch(void)
+{
+#ifdef CONFIG_X86_32
+	/*
+	 * Save away %gs. No need to save %fs, as it was saved on the
+	 * stack on entry.  No need to save %es and %ds, as those are
+	 * always kernel segments while inside the kernel.
+	 */
+	lazy_save_gs(current->thread.gs);
+	lazy_load_gs(__KERNEL_STACK_CANARY);
+#else
+	/*
+	 * Save away %es, %ds, %fs and %gs. Must happen before reload
+	 * of cr3/ldt (i.e., not in __switch_to).
+	 */
+	__asm__ __volatile__ (
+		"mov %%es,%0 ; mov %%ds,%1 ; mov %%fs,%2 ; mov %%gs,%3"
+		: "=m" (current->thread.es),
+		  "=m" (current->thread.ds),
+		  "=m" (current->thread.fsindex),
+		  "=m" (current->thread.gsindex) );
+
+	if (current->thread.ds)
+		__asm__ __volatile__ ( "movl %0,%%ds" : : "r" (0) );
+
+	if (current->thread.es)
+		__asm__ __volatile__ ( "movl %0,%%es" : : "r" (0) );
+
+	if (current->thread.fsindex) {
+		__asm__ __volatile__ ( "movl %0,%%fs" : : "r" (0) );
+		current->thread.fs = 0;
+	}
+
+	if (current->thread.gsindex) {
+		load_gs_index(0);
+		current->thread.gs = 0;
+	}
+#endif
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	unsigned cpu = smp_processor_id();
+	struct mmuext_op _op[2 + (sizeof(long) > 4)], *op = _op;
+#ifdef CONFIG_X86_64
+	pgd_t *upgd;
+#endif
+
+	if (likely(prev != next)) {
+		BUG_ON(!xen_feature(XENFEAT_writable_page_tables) &&
+		       !PagePinned(virt_to_page(next->pgd)));
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+		percpu_write(cpu_tlbstate.active_mm, next);
+#endif
+		cpumask_set_cpu(cpu, mm_cpumask(next));
+
+		/* Re-load page tables: load_cr3(next->pgd) */
+		op->cmd = MMUEXT_NEW_BASEPTR;
+		op->arg1.mfn = virt_to_mfn(next->pgd);
+		op++;
+
+		/* xen_new_user_pt(next->pgd) */
+#ifdef CONFIG_X86_64
+		op->cmd = MMUEXT_NEW_USER_BASEPTR;
+		upgd = __user_pgd(next->pgd);
+		op->arg1.mfn = likely(upgd) ? virt_to_mfn(upgd) : 0;
+		op++;
+#endif
+		/* stop flush ipis for the previous mm */
+		cpumask_clear_cpu(cpu, mm_cpumask(prev));
+
+		/*
+		 * load the LDT, if the LDT is different:
+		 */
+		if (unlikely(prev->context.ldt != next->context.ldt)) {
+			/* load_LDT_nolock(&next->context) */
+			op->cmd = MMUEXT_SET_LDT;
+			op->arg1.linear_addr = (unsigned long)next->context.ldt;
+			op->arg2.nr_ents     = next->context.size;
+			op++;
+		}
+
+		BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
+	}
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN) /* XEN: no lazy tlb */
+	else {
+		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+		BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
+
+		if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) {
+			/* We were in lazy tlb mode and leave_mm disabled
+			 * tlb flush IPI delivery. We must reload CR3
+			 * to make sure to use no freed page tables.
+			 */
+			load_cr3(next->pgd);
+			xen_new_user_pt(next->pgd);
+			load_LDT_nolock(&next->context);
+		}
+	}
+#endif
+}
+
+#define activate_mm(prev, next)			\
+do {						\
+	xen_activate_mm(prev, next);		\
+	switch_mm((prev), (next), NULL);	\
+} while (0);
+
+#ifdef CONFIG_X86_32
+#define deactivate_mm(tsk, mm)			\
+do {						\
+	lazy_load_gs(0);			\
+} while (0)
+#else
+#define deactivate_mm(tsk, mm)			\
+do {						\
+	load_gs_index(0);			\
+	loadsegment(fs, 0);			\
+} while (0)
+#endif
+
+#endif /* _ASM_X86_MMU_CONTEXT_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/mach_traps.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/mach_traps.h
@@ -0,0 +1,33 @@
+/*
+ *  include/asm-xen/asm-i386/mach-xen/mach_traps.h
+ *
+ *  Machine specific NMI handling for Xen
+ */
+#ifndef _MACH_TRAPS_H
+#define _MACH_TRAPS_H
+
+#include <linux/bitops.h>
+#include <xen/interface/nmi.h>
+
+static inline void clear_mem_error(unsigned char reason) {}
+static inline void clear_io_check_error(unsigned char reason) {}
+
+static inline unsigned char get_nmi_reason(void)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	unsigned char reason = 0;
+
+	/* construct a value which looks like it came from
+	 * port 0x61.
+	 */
+	if (test_bit(_XEN_NMIREASON_io_error, &s->arch.nmi_reason))
+		reason |= 0x40;
+	if (test_bit(_XEN_NMIREASON_parity_error, &s->arch.nmi_reason))
+		reason |= 0x80;
+
+        return reason;
+}
+
+static inline void reassert_nmi(void) {}
+
+#endif /* !_MACH_TRAPS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/system_64.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/system_64.h
@@ -0,0 +1,20 @@
+#ifndef _ASM_X86_SYSTEM_64_H
+#define _ASM_X86_SYSTEM_64_H
+
+#include <asm/segment.h>
+#include <asm/cmpxchg.h>
+
+
+static inline unsigned long read_cr8(void)
+{
+	return 0;
+}
+
+static inline void write_cr8(unsigned long val)
+{
+	BUG_ON(val);
+}
+
+#include <linux/irqflags.h>
+
+#endif /* _ASM_X86_SYSTEM_64_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/processor.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/processor.h
@@ -0,0 +1,996 @@
+#ifndef _ASM_X86_PROCESSOR_H
+#define _ASM_X86_PROCESSOR_H
+
+#include <asm/processor-flags.h>
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+struct mm_struct;
+
+#include <asm/vm86.h>
+#include <asm/math_emu.h>
+#include <asm/segment.h>
+#include <asm/types.h>
+#include <asm/sigcontext.h>
+#include <asm/current.h>
+#include <asm/cpufeature.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable_types.h>
+#include <asm/percpu.h>
+#include <asm/msr.h>
+#include <asm/desc_defs.h>
+#include <asm/nops.h>
+#include <asm/ds.h>
+
+#include <linux/personality.h>
+#include <linux/cpumask.h>
+#include <linux/cache.h>
+#include <linux/threads.h>
+#include <linux/math64.h>
+#include <linux/init.h>
+#include <xen/interface/physdev.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+static inline void *current_text_addr(void)
+{
+	void *pc;
+
+	asm volatile("mov $1f, %0; 1:":"=r" (pc));
+
+	return pc;
+}
+
+#ifdef CONFIG_X86_VSMP
+# define ARCH_MIN_TASKALIGN		(1 << INTERNODE_CACHE_SHIFT)
+# define ARCH_MIN_MMSTRUCT_ALIGN	(1 << INTERNODE_CACHE_SHIFT)
+#else
+# define ARCH_MIN_TASKALIGN		16
+# define ARCH_MIN_MMSTRUCT_ALIGN	0
+#endif
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ *  Members of this structure are referenced in head.S, so think twice
+ *  before touching them. [mj]
+ */
+
+struct cpuinfo_x86 {
+	__u8			x86;		/* CPU family */
+	__u8			x86_vendor;	/* CPU vendor */
+	__u8			x86_model;
+	__u8			x86_mask;
+#ifdef CONFIG_X86_32
+	char			wp_works_ok;	/* It doesn't on 386's */
+
+	/* Problems on some 486Dx4's and old 386's: */
+	char			hlt_works_ok;
+	char			hard_math;
+	char			rfu;
+	char			fdiv_bug;
+	char			f00f_bug;
+	char			coma_bug;
+	char			pad0;
+#else
+	/* Number of 4K pages in DTLB/ITLB combined(in pages): */
+	int			x86_tlbsize;
+#endif
+	__u8			x86_virt_bits;
+	__u8			x86_phys_bits;
+	/* CPUID returned core id bits: */
+	__u8			x86_coreid_bits;
+	/* Max extended CPUID function supported: */
+	__u32			extended_cpuid_level;
+	/* Maximum supported CPUID level, -1=no CPUID: */
+	int			cpuid_level;
+	__u32			x86_capability[NCAPINTS];
+	char			x86_vendor_id[16];
+	char			x86_model_id[64];
+	/* in KB - valid for CPUS which support this call: */
+	int			x86_cache_size;
+	int			x86_cache_alignment;	/* In bytes */
+	int			x86_power;
+	unsigned long		loops_per_jiffy;
+#if defined(CONFIG_SMP) && !defined(CONFIG_XEN)
+	/* cpus sharing the last level cache: */
+	cpumask_var_t		llc_shared_map;
+#endif
+	/* cpuid returned max cores value: */
+	u16			 x86_max_cores;
+	u16			apicid;
+	u16			initial_apicid;
+	u16			x86_clflush_size;
+#ifdef CONFIG_SMP
+	/* number of cores as seen by the OS: */
+	u16			booted_cores;
+	/* Physical processor id: */
+	u16			phys_proc_id;
+	/* Core id: */
+	u16			cpu_core_id;
+	/* Index into per_cpu list: */
+	u16			cpu_index;
+#endif
+	unsigned int		x86_hyper_vendor;
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+#define X86_VENDOR_INTEL	0
+#define X86_VENDOR_CYRIX	1
+#define X86_VENDOR_AMD		2
+#define X86_VENDOR_UMC		3
+#define X86_VENDOR_CENTAUR	5
+#define X86_VENDOR_TRANSMETA	7
+#define X86_VENDOR_NSC		8
+#define X86_VENDOR_NUM		9
+
+#define X86_VENDOR_UNKNOWN	0xff
+
+#define X86_HYPER_VENDOR_NONE  0
+#define X86_HYPER_VENDOR_VMWARE 1
+#define X86_HYPER_VENDOR_XEN   'X'
+
+/*
+ * capabilities of CPUs
+ */
+extern struct cpuinfo_x86	boot_cpu_data;
+extern struct cpuinfo_x86	new_cpu_data;
+
+extern __u32			cpu_caps_cleared[NCAPINTS];
+extern __u32			cpu_caps_set[NCAPINTS];
+
+#ifdef CONFIG_SMP
+DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+#define current_cpu_data	__get_cpu_var(cpu_info)
+#else
+#define cpu_data(cpu)		boot_cpu_data
+#define current_cpu_data	boot_cpu_data
+#endif
+
+extern const struct seq_operations cpuinfo_op;
+
+static inline int hlt_works(int cpu)
+{
+#ifdef CONFIG_X86_32
+	return cpu_data(cpu).hlt_works_ok;
+#else
+	return 1;
+#endif
+}
+
+#define cache_line_size()	(boot_cpu_data.x86_cache_alignment)
+
+extern void cpu_detect(struct cpuinfo_x86 *c);
+
+extern struct pt_regs *idle_regs(struct pt_regs *);
+
+extern void early_cpu_init(void);
+extern void identify_boot_cpu(void);
+extern void identify_secondary_cpu(struct cpuinfo_x86 *);
+extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern unsigned short num_cache_leaves;
+
+extern void detect_extended_topology(struct cpuinfo_x86 *c);
+extern void detect_ht(struct cpuinfo_x86 *c);
+
+static inline void xen_cpuid(unsigned int *eax, unsigned int *ebx,
+			     unsigned int *ecx, unsigned int *edx)
+{
+	/* ecx is often an input as well as an output. */
+	asm(XEN_CPUID
+	    : "=a" (*eax),
+	      "=b" (*ebx),
+	      "=c" (*ecx),
+	      "=d" (*edx)
+	    : "0" (*eax), "2" (*ecx));
+}
+
+static inline void load_cr3(pgd_t *pgdir)
+{
+	write_cr3(__pa(pgdir));
+}
+
+#ifndef CONFIG_X86_NO_TSS
+#ifdef CONFIG_X86_32
+/* This is the TSS defined by the hardware. */
+struct x86_hw_tss {
+	unsigned short		back_link, __blh;
+	unsigned long		sp0;
+	unsigned short		ss0, __ss0h;
+	unsigned long		sp1;
+	/* ss1 caches MSR_IA32_SYSENTER_CS: */
+	unsigned short		ss1, __ss1h;
+	unsigned long		sp2;
+	unsigned short		ss2, __ss2h;
+	unsigned long		__cr3;
+	unsigned long		ip;
+	unsigned long		flags;
+	unsigned long		ax;
+	unsigned long		cx;
+	unsigned long		dx;
+	unsigned long		bx;
+	unsigned long		sp;
+	unsigned long		bp;
+	unsigned long		si;
+	unsigned long		di;
+	unsigned short		es, __esh;
+	unsigned short		cs, __csh;
+	unsigned short		ss, __ssh;
+	unsigned short		ds, __dsh;
+	unsigned short		fs, __fsh;
+	unsigned short		gs, __gsh;
+	unsigned short		ldt, __ldth;
+	unsigned short		trace;
+	unsigned short		io_bitmap_base;
+
+} __attribute__((packed));
+extern struct tss_struct doublefault_tss;
+#else
+struct x86_hw_tss {
+	u32			reserved1;
+	u64			sp0;
+	u64			sp1;
+	u64			sp2;
+	u64			reserved2;
+	u64			ist[7];
+	u32			reserved3;
+	u32			reserved4;
+	u16			reserved5;
+	u16			io_bitmap_base;
+
+} __attribute__((packed)) ____cacheline_aligned;
+#endif
+#endif /* CONFIG_X86_NO_TSS */
+
+/*
+ * IO-bitmap sizes:
+ */
+#define IO_BITMAP_BITS			65536
+#define IO_BITMAP_BYTES			(IO_BITMAP_BITS/8)
+#define IO_BITMAP_LONGS			(IO_BITMAP_BYTES/sizeof(long))
+#define IO_BITMAP_OFFSET		offsetof(struct tss_struct, io_bitmap)
+#define INVALID_IO_BITMAP_OFFSET	0x8000
+
+#ifndef CONFIG_X86_NO_TSS
+struct tss_struct {
+	/*
+	 * The hardware state:
+	 */
+	struct x86_hw_tss	x86_tss;
+
+	/*
+	 * The extra 1 is there because the CPU will access an
+	 * additional byte beyond the end of the IO permission
+	 * bitmap. The extra byte must be all 1 bits, and must
+	 * be within the limit.
+	 */
+	unsigned long		io_bitmap[IO_BITMAP_LONGS + 1];
+
+	/*
+	 * .. and then another 0x100 bytes for the emergency kernel stack:
+	 */
+	unsigned long		stack[64];
+
+} ____cacheline_aligned;
+
+DECLARE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss);
+
+/*
+ * Save the original ist values for checking stack pointers during debugging
+ */
+struct orig_ist {
+	unsigned long		ist[7];
+};
+#endif /* CONFIG_X86_NO_TSS */
+
+#define	MXCSR_DEFAULT		0x1f80
+
+struct i387_fsave_struct {
+	u32			cwd;	/* FPU Control Word		*/
+	u32			swd;	/* FPU Status Word		*/
+	u32			twd;	/* FPU Tag Word			*/
+	u32			fip;	/* FPU IP Offset		*/
+	u32			fcs;	/* FPU IP Selector		*/
+	u32			foo;	/* FPU Operand Pointer Offset	*/
+	u32			fos;	/* FPU Operand Pointer Selector	*/
+
+	/* 8*10 bytes for each FP-reg = 80 bytes:			*/
+	u32			st_space[20];
+
+	/* Software status information [not touched by FSAVE ]:		*/
+	u32			status;
+};
+
+struct i387_fxsave_struct {
+	u16			cwd; /* Control Word			*/
+	u16			swd; /* Status Word			*/
+	u16			twd; /* Tag Word			*/
+	u16			fop; /* Last Instruction Opcode		*/
+	union {
+		struct {
+			u64	rip; /* Instruction Pointer		*/
+			u64	rdp; /* Data Pointer			*/
+		};
+		struct {
+			u32	fip; /* FPU IP Offset			*/
+			u32	fcs; /* FPU IP Selector			*/
+			u32	foo; /* FPU Operand Offset		*/
+			u32	fos; /* FPU Operand Selector		*/
+		};
+	};
+	u32			mxcsr;		/* MXCSR Register State */
+	u32			mxcsr_mask;	/* MXCSR Mask		*/
+
+	/* 8*16 bytes for each FP-reg = 128 bytes:			*/
+	u32			st_space[32];
+
+	/* 16*16 bytes for each XMM-reg = 256 bytes:			*/
+	u32			xmm_space[64];
+
+	u32			padding[12];
+
+	union {
+		u32		padding1[12];
+		u32		sw_reserved[12];
+	};
+
+} __attribute__((aligned(16)));
+
+struct i387_soft_struct {
+	u32			cwd;
+	u32			swd;
+	u32			twd;
+	u32			fip;
+	u32			fcs;
+	u32			foo;
+	u32			fos;
+	/* 8*10 bytes for each FP-reg = 80 bytes: */
+	u32			st_space[20];
+	u8			ftop;
+	u8			changed;
+	u8			lookahead;
+	u8			no_update;
+	u8			rm;
+	u8			alimit;
+	struct math_emu_info	*info;
+	u32			entry_eip;
+};
+
+struct ymmh_struct {
+	/* 16 * 16 bytes for each YMMH-reg = 256 bytes */
+	u32 ymmh_space[64];
+};
+
+struct xsave_hdr_struct {
+	u64 xstate_bv;
+	u64 reserved1[2];
+	u64 reserved2[5];
+} __attribute__((packed));
+
+struct xsave_struct {
+	struct i387_fxsave_struct i387;
+	struct xsave_hdr_struct xsave_hdr;
+	struct ymmh_struct ymmh;
+	/* new processor state extensions will go here */
+} __attribute__ ((packed, aligned (64)));
+
+union thread_xstate {
+	struct i387_fsave_struct	fsave;
+	struct i387_fxsave_struct	fxsave;
+	struct i387_soft_struct		soft;
+	struct xsave_struct		xsave;
+};
+
+#ifdef CONFIG_X86_64
+#ifndef CONFIG_X86_NO_TSS
+DECLARE_PER_CPU(struct orig_ist, orig_ist);
+#endif
+
+union irq_stack_union {
+	char irq_stack[IRQ_STACK_SIZE];
+	/*
+	 * GCC hardcodes the stack canary as %gs:40.  Since the
+	 * irq_stack is the object at %gs:0, we reserve the bottom
+	 * 48 bytes of the irq stack for the canary.
+	 */
+	struct {
+		char gs_base[40];
+		unsigned long stack_canary;
+	};
+};
+
+DECLARE_PER_CPU_FIRST(union irq_stack_union, irq_stack_union);
+DECLARE_INIT_PER_CPU(irq_stack_union);
+
+DECLARE_PER_CPU(char *, irq_stack_ptr);
+DECLARE_PER_CPU(unsigned int, irq_count);
+extern unsigned long kernel_eflags;
+extern asmlinkage void ignore_sysret(void);
+#else	/* X86_64 */
+#ifdef CONFIG_CC_STACKPROTECTOR
+/*
+ * Make sure stack canary segment base is cached-aligned:
+ *   "For Intel Atom processors, avoid non zero segment base address
+ *    that is not aligned to cache line boundary at all cost."
+ * (Optim Ref Manual Assembly/Compiler Coding Rule 15.)
+ */
+struct stack_canary {
+	char __pad[20];		/* canary at %gs:20 */
+	unsigned long canary;
+};
+DECLARE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
+#endif
+#endif	/* X86_64 */
+
+extern unsigned int xstate_size;
+extern void free_thread_xstate(struct task_struct *);
+extern struct kmem_cache *task_xstate_cachep;
+
+struct thread_struct {
+	/* Cached TLS descriptors: */
+	struct desc_struct	tls_array[GDT_ENTRY_TLS_ENTRIES];
+	unsigned long		sp0;
+	unsigned long		sp;
+#ifdef CONFIG_X86_32
+	unsigned long		sysenter_cs;
+#else
+	unsigned long		usersp;	/* Copy from PDA */
+	unsigned short		es;
+	unsigned short		ds;
+	unsigned short		fsindex;
+	unsigned short		gsindex;
+#endif
+#ifdef CONFIG_X86_32
+	unsigned long		ip;
+#endif
+#ifdef CONFIG_X86_64
+	unsigned long		fs;
+#endif
+	unsigned long		gs;
+	/* Hardware debugging registers: */
+	unsigned long		debugreg0;
+	unsigned long		debugreg1;
+	unsigned long		debugreg2;
+	unsigned long		debugreg3;
+	unsigned long		debugreg6;
+	unsigned long		debugreg7;
+	/* Fault info: */
+	unsigned long		cr2;
+	unsigned long		trap_no;
+	unsigned long		error_code;
+	/* floating point and extended processor state */
+	union thread_xstate	*xstate;
+#ifdef CONFIG_X86_32
+	/* Virtual 86 mode info */
+	struct vm86_struct __user *vm86_info;
+	unsigned long		screen_bitmap;
+	unsigned long		v86flags, v86mask, saved_sp0;
+	unsigned int		saved_fs, saved_gs;
+#endif
+	/* IO permissions: */
+	unsigned long		*io_bitmap_ptr;
+	unsigned long		iopl;
+	/* Max allowed port in the bitmap, in bytes: */
+	unsigned		io_bitmap_max;
+/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set.  */
+	unsigned long	debugctlmsr;
+	/* Debug Store context; see asm/ds.h */
+	struct ds_context	*ds_ctx;
+};
+
+static inline unsigned long xen_get_debugreg(int regno)
+{
+	return HYPERVISOR_get_debugreg(regno);
+}
+
+static inline void xen_set_debugreg(int regno, unsigned long value)
+{
+	WARN_ON(HYPERVISOR_set_debugreg(regno, value));
+}
+
+/*
+ * Set IOPL bits in EFLAGS from given mask
+ */
+static inline void xen_set_iopl_mask(unsigned mask)
+{
+	struct physdev_set_iopl set_iopl;
+
+	/* Force the change at ring 0. */
+	set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3;
+	WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl));
+}
+
+#ifndef CONFIG_X86_NO_TSS
+static inline void
+native_load_sp0(struct tss_struct *tss, struct thread_struct *thread)
+{
+	tss->x86_tss.sp0 = thread->sp0;
+#ifdef CONFIG_X86_32
+	/* Only happens when SEP is enabled, no need to test "SEP"arately: */
+	if (unlikely(tss->x86_tss.ss1 != thread->sysenter_cs)) {
+		tss->x86_tss.ss1 = thread->sysenter_cs;
+		wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0);
+	}
+#endif
+}
+#else
+#define xen_load_sp0(tss, thread) do { \
+	if (HYPERVISOR_stack_switch(__KERNEL_DS, (thread)->sp0)) \
+		BUG(); \
+} while (0)
+#endif
+
+#define __cpuid			xen_cpuid
+#define paravirt_enabled()	0
+
+/*
+ * These special macros can be used to get or set a debugging register
+ */
+#define get_debugreg(var, register)				\
+	(var) = xen_get_debugreg(register)
+#define set_debugreg(value, register)				\
+	xen_set_debugreg(register, value)
+
+#define load_sp0 xen_load_sp0
+
+#define set_iopl_mask xen_set_iopl_mask
+
+/*
+ * Save the cr4 feature set we're using (ie
+ * Pentium 4MB enable and PPro Global page
+ * enable), so that any CPU's that boot up
+ * after us can get the correct flags.
+ */
+extern unsigned long		mmu_cr4_features;
+
+static inline void set_in_cr4(unsigned long mask)
+{
+	unsigned cr4;
+
+	mmu_cr4_features |= mask;
+	cr4 = read_cr4();
+	cr4 |= mask;
+	write_cr4(cr4);
+}
+
+static inline void clear_in_cr4(unsigned long mask)
+{
+	unsigned cr4;
+
+	mmu_cr4_features &= ~mask;
+	cr4 = read_cr4();
+	cr4 &= ~mask;
+	write_cr4(cr4);
+}
+
+typedef struct {
+	unsigned long		seg;
+} mm_segment_t;
+
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy state */
+extern void prepare_to_copy(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+/*
+ * Generic CPUID function
+ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ * resulting in stale register contents being returned.
+ */
+static inline void cpuid(unsigned int op,
+			 unsigned int *eax, unsigned int *ebx,
+			 unsigned int *ecx, unsigned int *edx)
+{
+	*eax = op;
+	*ecx = 0;
+	__cpuid(eax, ebx, ecx, edx);
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(unsigned int op, int count,
+			       unsigned int *eax, unsigned int *ebx,
+			       unsigned int *ecx, unsigned int *edx)
+{
+	*eax = op;
+	*ecx = count;
+	__cpuid(eax, ebx, ecx, edx);
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+	unsigned int eax, ebx, ecx, edx;
+
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return eax;
+}
+
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+	unsigned int eax, ebx, ecx, edx;
+
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return ebx;
+}
+
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+	unsigned int eax, ebx, ecx, edx;
+
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return ecx;
+}
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+	unsigned int eax, ebx, ecx, edx;
+
+	cpuid(op, &eax, &ebx, &ecx, &edx);
+
+	return edx;
+}
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+	asm volatile("rep; nop" ::: "memory");
+}
+
+static inline void cpu_relax(void)
+{
+	rep_nop();
+}
+
+/* Stop speculative execution and prefetching of modified code. */
+static inline void sync_core(void)
+{
+	int tmp;
+
+#if defined(CONFIG_M386) || defined(CONFIG_M486)
+	if (boot_cpu_data.x86 < 5)
+		/* There is no speculative execution.
+		 * jmp is a barrier to prefetching. */
+		asm volatile("jmp 1f\n1:\n" ::: "memory");
+	else
+#endif
+		/* cpuid is a barrier to speculative execution.
+		 * Prefetched instructions are automatically
+		 * invalidated when modified. */
+		asm volatile("cpuid" : "=a" (tmp) : "0" (1)
+			     : "ebx", "ecx", "edx", "memory");
+}
+
+static inline void __monitor(const void *eax, unsigned long ecx,
+			     unsigned long edx)
+{
+	/* "monitor %eax, %ecx, %edx;" */
+	asm volatile(".byte 0x0f, 0x01, 0xc8;"
+		     :: "a" (eax), "c" (ecx), "d"(edx));
+}
+
+static inline void __mwait(unsigned long eax, unsigned long ecx)
+{
+	/* "mwait %eax, %ecx;" */
+	asm volatile(".byte 0x0f, 0x01, 0xc9;"
+		     :: "a" (eax), "c" (ecx));
+}
+
+static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
+{
+	trace_hardirqs_on();
+	/* "mwait %eax, %ecx;" */
+	asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
+		     :: "a" (eax), "c" (ecx));
+}
+
+extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
+
+extern void select_idle_routine(const struct cpuinfo_x86 *c);
+extern void init_c1e_mask(void);
+
+extern unsigned long		boot_option_idle_override;
+extern unsigned long		idle_halt;
+extern unsigned long		idle_nomwait;
+
+extern void enable_sep_cpu(void);
+extern int sysenter_setup(void);
+
+/* Defined in head.S */
+extern struct desc_ptr		early_gdt_descr;
+
+extern void cpu_set_gdt(int);
+extern void switch_to_new_gdt(int);
+extern void load_percpu_segment(int);
+extern void cpu_init(void);
+
+static inline unsigned long get_debugctlmsr(void)
+{
+    unsigned long debugctlmsr = 0;
+
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return 0;
+#endif
+	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
+
+    return debugctlmsr;
+}
+
+static inline unsigned long get_debugctlmsr_on_cpu(int cpu)
+{
+	u64 debugctlmsr = 0;
+	u32 val1, val2;
+
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return 0;
+#endif
+	rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2);
+	debugctlmsr = val1 | ((u64)val2 << 32);
+
+	return debugctlmsr;
+}
+
+static inline void update_debugctlmsr(unsigned long debugctlmsr)
+{
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return;
+#endif
+	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
+}
+
+static inline void update_debugctlmsr_on_cpu(int cpu,
+					     unsigned long debugctlmsr)
+{
+#ifndef CONFIG_X86_DEBUGCTLMSR
+	if (boot_cpu_data.x86 < 6)
+		return;
+#endif
+	wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR,
+		     (u32)((u64)debugctlmsr),
+		     (u32)((u64)debugctlmsr >> 32));
+}
+
+/*
+ * from system description table in BIOS. Mostly for MCA use, but
+ * others may find it useful:
+ */
+extern unsigned int		machine_id;
+extern unsigned int		machine_submodel_id;
+extern unsigned int		BIOS_revision;
+
+/* Boot loader type from the setup header: */
+extern int			bootloader_type;
+extern int			bootloader_version;
+
+extern char			ignore_fpu_irq;
+
+#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_SPINLOCK_PREFETCH
+
+#ifdef CONFIG_X86_32
+# define BASE_PREFETCH		ASM_NOP4
+# define ARCH_HAS_PREFETCH
+#else
+# define BASE_PREFETCH		"prefetcht0 (%1)"
+#endif
+
+/*
+ * Prefetch instructions for Pentium III (+) and AMD Athlon (+)
+ *
+ * It's not worth to care about 3dnow prefetches for the K6
+ * because they are microcoded there and very slow.
+ */
+static inline void prefetch(const void *x)
+{
+	alternative_input(BASE_PREFETCH,
+			  "prefetchnta (%1)",
+			  X86_FEATURE_XMM,
+			  "r" (x));
+}
+
+/*
+ * 3dnow prefetch to get an exclusive cache line.
+ * Useful for spinlocks to avoid one state transition in the
+ * cache coherency protocol:
+ */
+static inline void prefetchw(const void *x)
+{
+	alternative_input(BASE_PREFETCH,
+			  "prefetchw (%1)",
+			  X86_FEATURE_3DNOW,
+			  "r" (x));
+}
+
+static inline void spin_lock_prefetch(const void *x)
+{
+	prefetchw(x);
+}
+
+#ifdef CONFIG_X86_32
+/*
+ * User space process size: 3GB (default).
+ */
+#define TASK_SIZE		PAGE_OFFSET
+#define TASK_SIZE_MAX		TASK_SIZE
+#define STACK_TOP		TASK_SIZE
+#define STACK_TOP_MAX		STACK_TOP
+
+#define INIT_THREAD  {							  \
+	.sp0			= sizeof(init_stack) + (long)&init_stack, \
+	.vm86_info		= NULL,					  \
+	.sysenter_cs		= __KERNEL_CS,				  \
+	.io_bitmap_ptr		= NULL,					  \
+}
+
+/*
+ * Note that the .io_bitmap member must be extra-big. This is because
+ * the CPU will access an additional byte beyond the end of the IO
+ * permission bitmap. The extra byte must be all 1 bits, and must
+ * be within the limit.
+ */
+#define INIT_TSS  {							  \
+	.x86_tss = {							  \
+		.sp0		= sizeof(init_stack) + (long)&init_stack, \
+		.ss0		= __KERNEL_DS,				  \
+		.ss1		= __KERNEL_CS,				  \
+		.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,		  \
+	 },								  \
+	.io_bitmap		= { [0 ... IO_BITMAP_LONGS] = ~0 },	  \
+}
+
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+#define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
+#define KSTK_TOP(info)                                                 \
+({                                                                     \
+       unsigned long *__ptr = (unsigned long *)(info);                 \
+       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
+})
+
+/*
+ * The below -8 is to reserve 8 bytes on top of the ring0 stack.
+ * This is necessary to guarantee that the entire "struct pt_regs"
+ * is accessable even if the CPU haven't stored the SS/ESP registers
+ * on the stack (interrupt gate does not save these registers
+ * when switching to the same priv ring).
+ * Therefore beware: accessing the ss/esp fields of the
+ * "struct pt_regs" is possible, but they may contain the
+ * completely wrong values.
+ */
+#define task_pt_regs(task)                                             \
+({                                                                     \
+       struct pt_regs *__regs__;                                       \
+       __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
+       __regs__ - 1;                                                   \
+})
+
+#define KSTK_ESP(task)		(task_pt_regs(task)->sp)
+
+#else
+/*
+ * User space process size. 47bits minus one guard page.
+ */
+#define TASK_SIZE_MAX	((1UL << 47) - PAGE_SIZE)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define IA32_PAGE_OFFSET	((current->personality & ADDR_LIMIT_3GB) ? \
+					0xc0000000 : 0xFFFFe000)
+
+#define TASK_SIZE		(test_thread_flag(TIF_IA32) ? \
+					IA32_PAGE_OFFSET : TASK_SIZE_MAX)
+#define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_IA32)) ? \
+					IA32_PAGE_OFFSET : TASK_SIZE_MAX)
+
+#define STACK_TOP		TASK_SIZE
+#define STACK_TOP_MAX		TASK_SIZE_MAX
+
+#define INIT_THREAD  { \
+	.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+#define INIT_TSS  { \
+	.x86_tss.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ * What is this good for? it will be always the scheduler or ret_from_fork.
+ */
+#define thread_saved_pc(t)	(*(unsigned long *)((t)->thread.sp - 8))
+
+#define task_pt_regs(tsk)	((struct pt_regs *)(tsk)->thread.sp0 - 1)
+#define KSTK_ESP(tsk)		-1 /* sorry. doesn't work for syscall. */
+#endif /* CONFIG_X86_64 */
+
+extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
+					       unsigned long new_sp);
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+
+#define KSTK_EIP(task)		(task_pt_regs(task)->ip)
+
+/* Get/set a process' ability to use the timestamp counter instruction */
+#define GET_TSC_CTL(adr)	get_tsc_mode((adr))
+#define SET_TSC_CTL(val)	set_tsc_mode((val))
+
+extern int get_tsc_mode(unsigned long adr);
+extern int set_tsc_mode(unsigned int val);
+
+extern int amd_get_nb_id(int cpu);
+
+struct aperfmperf {
+	u64 aperf, mperf;
+};
+
+static inline void get_aperfmperf(struct aperfmperf *am)
+{
+	WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF));
+
+	rdmsrl(MSR_IA32_APERF, am->aperf);
+	rdmsrl(MSR_IA32_MPERF, am->mperf);
+}
+
+#define APERFMPERF_SHIFT 10
+
+static inline
+unsigned long calc_aperfmperf_ratio(struct aperfmperf *old,
+				    struct aperfmperf *new)
+{
+	u64 aperf = new->aperf - old->aperf;
+	u64 mperf = new->mperf - old->mperf;
+	unsigned long ratio = aperf;
+
+	mperf >>= APERFMPERF_SHIFT;
+	if (mperf)
+		ratio = div64_u64(aperf, mperf);
+
+	return ratio;
+}
+
+/*
+ * AMD errata checking
+ */
+#ifdef CONFIG_CPU_SUP_AMD
+extern const int amd_erratum_400[];
+extern bool cpu_has_amd_erratum(const int *);
+
+#define AMD_LEGACY_ERRATUM(...)		{ -1, __VA_ARGS__, 0 }
+#define AMD_OSVW_ERRATUM(osvw_id, ...)	{ osvw_id, __VA_ARGS__, 0 }
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
+	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
+#define AMD_MODEL_RANGE_FAMILY(range)	(((range) >> 24) & 0xff)
+#define AMD_MODEL_RANGE_START(range)	(((range) >> 12) & 0xfff)
+#define AMD_MODEL_RANGE_END(range)	((range) & 0xfff)
+
+#else
+#define cpu_has_amd_erratum(x)	(false)
+#endif /* CONFIG_CPU_SUP_AMD */
+
+#endif /* _ASM_X86_PROCESSOR_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable-3level.h
@@ -0,0 +1,137 @@
+#ifndef _ASM_X86_PGTABLE_3LEVEL_H
+#define _ASM_X86_PGTABLE_3LEVEL_H
+
+/*
+ * Intel Physical Address Extension (PAE) Mode - three-level page
+ * tables on PPro+ CPUs.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#define pte_ERROR(e)							\
+	printk("%s:%d: bad pte %p(%016Lx pfn %08lx).\n",		\
+	        __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
+#define pmd_ERROR(e)							\
+	printk("%s:%d: bad pmd %p(%016Lx pfn %08Lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pmd_val(e),			\
+	       (pmd_val(e) & PTE_PFN_MASK) >> PAGE_SHIFT)
+#define pgd_ERROR(e)							\
+	printk("%s:%d: bad pgd %p(%016Lx pfn %08Lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+	       (pgd_val(e) & PTE_PFN_MASK) >> PAGE_SHIFT)
+
+/* Rules for using set_pte: the pte being assigned *must* be
+ * either not present or in a state where the hardware will
+ * not attempt to update the pte.  In places where this is
+ * not possible, use pte_get_and_clear to obtain the old pte
+ * value and then use set_pte to update it.  -ben
+ */
+
+static inline void xen_set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = pte.pte_high;
+	smp_wmb();
+	ptep->pte_low = pte.pte_low;
+}
+
+static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+	set_64bit((unsigned long long *)(ptep), __pte_val(pte));
+}
+
+static inline void xen_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+	xen_l2_entry_update(pmdp, pmd);
+}
+
+static inline void xen_set_pud(pud_t *pudp, pud_t pud)
+{
+	xen_l3_entry_update(pudp, pud);
+}
+
+/*
+ * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
+ * entry, so clear the bottom half first and enforce ordering with a compiler
+ * barrier.
+ */
+static inline void __xen_pte_clear(pte_t *ptep)
+{
+	ptep->pte_low = 0;
+	smp_wmb();
+	ptep->pte_high = 0;
+}
+
+#define xen_pmd_clear(pmd)			\
+({						\
+	pmd_t *__pmdp = (pmd);			\
+	PagePinned(virt_to_page(__pmdp))	\
+	? set_pmd(__pmdp, __pmd(0))		\
+	: (void)(*__pmdp = __pmd(0));		\
+})
+
+static inline void __xen_pud_clear(pud_t *pudp)
+{
+	pgdval_t pgd;
+
+	set_pud(pudp, __pud(0));
+
+	/*
+	 * According to Intel App note "TLBs, Paging-Structure Caches,
+	 * and Their Invalidation", April 2007, document 317080-001,
+	 * section 8.1: in PAE mode we explicitly have to flush the
+	 * TLB via cr3 if the top-level pgd is changed...
+	 *
+	 * Make sure the pud entry we're updating is within the
+	 * current pgd to avoid unnecessary TLB flushes.
+	 */
+	pgd = read_cr3();
+	if (__pa(pudp) >= pgd && __pa(pudp) <
+	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
+		xen_tlb_flush();
+}
+
+#define xen_pud_clear(pudp)			\
+({						\
+	pud_t *__pudp = (pudp);			\
+	PagePinned(virt_to_page(__pudp))	\
+	? __xen_pud_clear(__pudp)		\
+	: (void)(*__pudp = __pud(0));		\
+})
+
+#ifdef CONFIG_SMP
+static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res)
+{
+	uint64_t val = __pte_val(res);
+	if (__cmpxchg64(ptep, val, 0) != val) {
+		/* xchg acts as a barrier before the setting of the high bits */
+		res.pte_low = xchg(&ptep->pte_low, 0);
+		res.pte_high = ptep->pte_high;
+		ptep->pte_high = 0;
+	}
+	return res;
+}
+#else
+#define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
+#endif
+
+#define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
+			 ((_pte).pte_high << (32-PAGE_SHIFT)))
+
+/*
+ * Bits 0, 6 and 7 are taken in the low part of the pte,
+ * put the 32 bits of offset into the high part.
+ */
+#define pte_to_pgoff(pte) ((pte).pte_high)
+#define pgoff_to_pte(off)						\
+	((pte_t) { { .pte_low = _PAGE_FILE, .pte_high = (off) } })
+#define PTE_FILE_MAX_BITS       32
+
+/* Encode and de-code a swap entry */
+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > 5)
+#define __swp_type(x)			(((x).val) & 0x1f)
+#define __swp_offset(x)			((x).val >> 5)
+#define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
+#define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+#define __swp_entry_to_pte(x)		((pte_t){ { .pte_high = (x).val } })
+
+#endif /* _ASM_X86_PGTABLE_3LEVEL_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable_64.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable_64.h
@@ -0,0 +1,197 @@
+#ifndef _ASM_X86_PGTABLE_64_H
+#define _ASM_X86_PGTABLE_64_H
+
+#include <linux/const.h>
+#include <asm/pgtable_64_types.h>
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This file contains the functions and defines necessary to modify and use
+ * the x86-64 page table tree.
+ */
+#include <asm/processor.h>
+#include <linux/bitops.h>
+#include <linux/threads.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_XEN
+extern pud_t level3_user_pgt[512];
+
+extern void xen_init_pt(void);
+extern void xen_switch_pt(void);
+#endif
+
+extern pud_t level3_kernel_pgt[512];
+extern pud_t level3_ident_pgt[512];
+extern pmd_t level2_kernel_pgt[512];
+extern pmd_t level2_fixmap_pgt[512];
+extern pmd_t level2_ident_pgt[512];
+extern pgd_t init_level4_pgt[];
+
+#define swapper_pg_dir init_level4_pgt
+
+extern void paging_init(void);
+
+#define pte_ERROR(e)							\
+	printk("%s:%d: bad pte %p(%016lx pfn %010lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pte_val(e), pte_pfn(e))
+#define pmd_ERROR(e)							\
+	printk("%s:%d: bad pmd %p(%016lx pfn %010lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pmd_val(e), pmd_pfn(e))
+#define pud_ERROR(e)							\
+	printk("%s:%d: bad pud %p(%016lx pfn %010Lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pud_val(e),			\
+	       (pud_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+#define pgd_ERROR(e)							\
+	printk("%s:%d: bad pgd %p(%016lx pfn %010Lx).\n",		\
+	       __FILE__, __LINE__, &(e), __pgd_val(e),			\
+	       (pgd_val(e) & __PHYSICAL_MASK) >> PAGE_SHIFT)
+
+struct mm_struct;
+
+void set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte);
+
+
+#define __xen_pte_clear(ptep) xen_set_pte(ptep, __pte(0))
+
+static inline void xen_set_pte(pte_t *ptep, pte_t pte)
+{
+	*ptep = pte;
+}
+
+static inline void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+	xen_set_pte(ptep, pte);
+}
+
+#ifdef CONFIG_SMP
+static inline pte_t xen_ptep_get_and_clear(pte_t *xp, pte_t ret)
+{
+	return __pte_ma(xchg(&xp->pte, 0));
+}
+#else
+#define xen_ptep_get_and_clear(xp, pte) xen_local_ptep_get_and_clear(xp, pte)
+#endif
+
+static inline void xen_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+	xen_l2_entry_update(pmdp, pmd);
+}
+
+#define xen_pmd_clear(pmd)			\
+({						\
+	pmd_t *__pmdp = (pmd);			\
+	PagePinned(virt_to_page(__pmdp))	\
+	? set_pmd(__pmdp, xen_make_pmd(0))	\
+	: (void)(*__pmdp = xen_make_pmd(0));	\
+})
+
+static inline void xen_set_pud(pud_t *pudp, pud_t pud)
+{
+	xen_l3_entry_update(pudp, pud);
+}
+
+#define xen_pud_clear(pud)			\
+({						\
+	pud_t *__pudp = (pud);			\
+	PagePinned(virt_to_page(__pudp))	\
+	? set_pud(__pudp, xen_make_pud(0))	\
+	: (void)(*__pudp = xen_make_pud(0));	\
+})
+
+static inline pgd_t *__user_pgd(pgd_t *pgd)
+{
+	if (unlikely(((unsigned long)pgd & PAGE_MASK)
+		     == (unsigned long)init_level4_pgt))
+		return NULL;
+	return (pgd_t *)(virt_to_page(pgd)->index
+			 + ((unsigned long)pgd & ~PAGE_MASK));
+}
+
+static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd)
+{
+	xen_l4_entry_update(pgdp, pgd);
+}
+
+#define xen_pgd_clear(pgd)			\
+({						\
+	pgd_t *__pgdp = (pgd);			\
+	PagePinned(virt_to_page(__pgdp))	\
+	? xen_l4_entry_update(__pgdp, xen_make_pgd(0)) \
+	: (void)(*__user_pgd(__pgdp) = *__pgdp = xen_make_pgd(0)); \
+})
+
+#define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT)
+
+extern unsigned long early_arbitrary_virt_to_mfn(void *va);
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+/*
+ * Level 4 access.
+ */
+static inline int pgd_large(pgd_t pgd) { return 0; }
+#define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE)
+
+/* PUD - Level3 access */
+
+/* PMD  - Level 2 access */
+#define pte_to_pgoff(pte) ((__pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
+#define pgoff_to_pte(off) ((pte_t) { .pte = ((off) << PAGE_SHIFT) |	\
+					    _PAGE_FILE })
+#define PTE_FILE_MAX_BITS __PHYSICAL_MASK_SHIFT
+
+/* PTE - Level 1 access. */
+
+/* x86-64 always has all page tables mapped. */
+#define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
+#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
+#define pte_unmap(pte) /* NOP */
+#define pte_unmap_nested(pte) /* NOP */
+
+#define update_mmu_cache(vma, address, pte) do { } while (0)
+
+/* Encode and de-code a swap entry */
+#if _PAGE_BIT_FILE < _PAGE_BIT_PROTNONE
+#define SWP_TYPE_BITS (_PAGE_BIT_FILE - _PAGE_BIT_PRESENT - 1)
+#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1)
+#else
+#define SWP_TYPE_BITS (_PAGE_BIT_PROTNONE - _PAGE_BIT_PRESENT - 1)
+#define SWP_OFFSET_SHIFT (_PAGE_BIT_FILE + 1)
+#endif
+
+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
+
+#define __swp_type(x)			(((x).val >> (_PAGE_BIT_PRESENT + 1)) \
+					 & ((1U << SWP_TYPE_BITS) - 1))
+#define __swp_offset(x)			((x).val >> SWP_OFFSET_SHIFT)
+#define __swp_entry(type, offset)	((swp_entry_t) { \
+					 ((type) << (_PAGE_BIT_PRESENT + 1)) \
+					 | ((offset) << SWP_OFFSET_SHIFT) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { __pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { .pte = (x).val })
+
+extern int kern_addr_valid(unsigned long addr);
+extern void cleanup_highmap(void);
+
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
+#define pgtable_cache_init()   do { } while (0)
+#define check_pgt_cache()      do { } while (0)
+
+#define PAGE_AGP    PAGE_KERNEL_NOCACHE
+#define HAVE_PAGE_AGP 1
+
+/* fs/proc/kcore.c */
+#define	kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+#define	kc_offset_to_vaddr(o) ((o) | ~__VIRTUAL_MASK)
+
+#define __HAVE_ARCH_PTE_SAME
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_X86_PGTABLE_64_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/fixmap.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/fixmap.h
@@ -0,0 +1,214 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ * x86_32 and x86_64 integration by Gustavo F. Padovan, February 2009
+ */
+
+#ifndef _ASM_X86_FIXMAP_H
+#define _ASM_X86_FIXMAP_H
+
+#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
+#include <asm/acpi.h>
+#include <asm/page.h>
+#ifdef CONFIG_X86_32
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#else
+#include <asm/vsyscall.h>
+#endif
+
+/*
+ * We can't declare FIXADDR_TOP as variable for x86_64 because vsyscall
+ * uses fixmaps that relies on FIXADDR_TOP for proper address calculation.
+ * Because of this, FIXADDR_TOP x86 integration was left as later work.
+ */
+#ifdef CONFIG_X86_32
+/* used by vmalloc.c, vsyscall.lds.S.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
+ */
+extern unsigned long __FIXADDR_TOP;
+#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+
+#define FIXADDR_USER_START     __fix_to_virt(FIX_VDSO)
+#define FIXADDR_USER_END       __fix_to_virt(FIX_VDSO - 1)
+#else
+#define FIXADDR_TOP	(VSYSCALL_END-PAGE_SIZE)
+
+/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
+#define FIXADDR_USER_START	((unsigned long)VSYSCALL32_VSYSCALL)
+#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+#endif
+
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process.
+ * for x86_32: We allocate these special addresses
+ * from the end of virtual memory (0xfffff000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * These 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages (or larger if used with an increment
+ * higher than 1). Use set_fixmap(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+enum fixed_addresses {
+#ifdef CONFIG_X86_32
+	FIX_HOLE,
+	FIX_VDSO,
+#else
+	VSYSCALL_LAST_PAGE,
+	VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE
+			    + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
+	VSYSCALL_HPET,
+#endif
+	FIX_DBGP_BASE,
+	FIX_EARLYCON_MEM_BASE,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+	FIX_OHCI1394_BASE,
+#endif
+#ifndef CONFIG_XEN
+#ifdef CONFIG_X86_LOCAL_APIC
+	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+#endif
+#ifdef CONFIG_X86_IO_APIC
+	FIX_IO_APIC_BASE_0,
+	FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1,
+#endif
+#else
+	FIX_SHARED_INFO,
+#define NR_FIX_ISAMAPS	256
+	FIX_ISAMAP_END,
+	FIX_ISAMAP_BEGIN = FIX_ISAMAP_END + NR_FIX_ISAMAPS - 1,
+#endif
+#ifdef CONFIG_X86_VISWS_APIC
+	FIX_CO_CPU,	/* Cobalt timer */
+	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */
+	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
+	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
+#endif
+#ifdef CONFIG_X86_F00F_BUG
+	FIX_F00F_IDT,	/* Virtual mapping for IDT */
+#endif
+#ifdef CONFIG_X86_CYCLONE_TIMER
+	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+#endif
+#ifdef CONFIG_X86_32
+	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+#ifdef CONFIG_PCI_MMCONFIG
+	FIX_PCIE_MCFG,
+#endif
+#endif
+#ifdef CONFIG_PARAVIRT
+	FIX_PARAVIRT_BOOTMAP,
+#endif
+	FIX_TEXT_POKE1,	/* reserve 2 pages for text_poke() */
+	FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
+	__end_of_permanent_fixed_addresses,
+	/*
+	 * 256 temporary boot-time mappings, used by early_ioremap(),
+	 * before ioremap() is functional.
+	 *
+	 * We round it up to the next 256 pages boundary so that we
+	 * can have a single pgd entry and a single pte table:
+	 */
+#define NR_FIX_BTMAPS		64
+#define FIX_BTMAPS_SLOTS	4
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+			(__end_of_permanent_fixed_addresses & 255),
+	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+#ifdef CONFIG_X86_32
+	FIX_WP_TEST,
+#endif
+#ifdef CONFIG_INTEL_TXT
+	FIX_TBOOT_BASE,
+#endif
+	__end_of_fixed_addresses
+};
+
+
+extern void reserve_top_address(unsigned long reserve);
+
+#define FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_BOOT_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START		(FIXADDR_TOP - FIXADDR_SIZE)
+#define FIXADDR_BOOT_START	(FIXADDR_TOP - FIXADDR_BOOT_SIZE)
+
+extern int fixmaps_set;
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
+void xen_set_fixmap(enum fixed_addresses, phys_addr_t, pgprot_t);
+
+static inline void __set_fixmap(enum fixed_addresses idx,
+				phys_addr_t phys, pgprot_t flags)
+{
+	xen_set_fixmap(idx, phys, flags);
+}
+
+#define set_fixmap(idx, phys)				\
+	__set_fixmap(idx, phys, PAGE_KERNEL)
+
+/*
+ * Some hardware wants to get fixmapped without caching.
+ */
+#define set_fixmap_nocache(idx, phys)			\
+	__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+
+#define clear_fixmap(idx)			\
+	__set_fixmap(idx, 0, __pgprot(0))
+
+#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
+extern void __this_fixmap_does_not_exist(void);
+
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without translation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+	/*
+	 * this branch gets completely eliminated after inlining,
+	 * except when someone tries to use fixaddr indices in an
+	 * illegal way. (such as mixing up address types or using
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
+	 */
+	if (idx >= __end_of_fixed_addresses)
+		__this_fixmap_does_not_exist();
+
+	return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+	BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+	return __virt_to_fix(vaddr);
+}
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_X86_FIXMAP_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/irq_vectors.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/irq_vectors.h
@@ -0,0 +1,94 @@
+#ifndef _ASM_X86_IRQ_VECTORS_H
+#define _ASM_X86_IRQ_VECTORS_H
+
+#define MCE_VECTOR			0x12
+
+#ifdef CONFIG_X86_32
+# define SYSCALL_VECTOR			0x80
+# define IA32_SYSCALL_VECTOR		0x80
+#else
+# define IA32_SYSCALL_VECTOR		0x80
+#endif
+
+#define RESCHEDULE_VECTOR		0
+#define CALL_FUNCTION_VECTOR		1
+#define CALL_FUNC_SINGLE_VECTOR		2
+#define SPIN_UNLOCK_VECTOR		3
+#define REBOOT_VECTOR			4
+#define NR_IPIS				5
+
+/*
+ * The maximum number of vectors supported by i386 processors
+ * is limited to 256. For processors other than i386, NR_VECTORS
+ * should be changed accordingly.
+ */
+#define NR_VECTORS			 256
+
+#define	FIRST_VM86_IRQ			   3
+#define LAST_VM86_IRQ			  15
+
+#ifndef __ASSEMBLY__
+static inline int invalid_vm86_irq(int irq)
+{
+	return irq < FIRST_VM86_IRQ || irq > LAST_VM86_IRQ;
+}
+#endif
+
+/*
+ * Size the maximum number of interrupts.
+ *
+ * If the irq_desc[] array has a sparse layout, we can size things
+ * generously - it scales up linearly with the maximum number of CPUs,
+ * and the maximum number of IO-APICs, whichever is higher.
+ *
+ * In other cases we size more conservatively, to not create too large
+ * static arrays.
+ */
+
+#define NR_IRQS_LEGACY			  16
+
+/*
+ * The flat IRQ space is divided into two regions:
+ *  1. A one-to-one mapping of real physical IRQs. This space is only used
+ *     if we have physical device-access privilege. This region is at the
+ *     start of the IRQ space so that existing device drivers do not need
+ *     to be modified to translate physical IRQ numbers into our IRQ space.
+ *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+ *     are bound using the provided bind/unbind functions.
+ */
+#define PIRQ_BASE			0
+
+#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
+#define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
+
+#ifdef CONFIG_X86_IO_APIC
+# if !defined(NR_CPUS) || !defined(MAX_IO_APICS)
+/* nothing */
+# elif defined(CONFIG_SPARSE_IRQ)
+#  define NR_PIRQS					\
+	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
+		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
+		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
+# elif NR_CPUS < MAX_IO_APICS
+#  define NR_PIRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
+# else
+#  define NR_PIRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
+# endif
+#else /* !CONFIG_X86_IO_APIC: */
+# define NR_PIRQS			NR_IRQS_LEGACY
+#endif
+
+#ifndef __ASSEMBLY__
+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SPARSE_IRQ)
+extern int nr_pirqs;
+#else
+# define nr_pirqs			NR_PIRQS
+#endif
+#endif
+
+#define DYNIRQ_BASE			(PIRQ_BASE + nr_pirqs)
+#define NR_DYNIRQS			(64 + CONFIG_XEN_NR_GUEST_DEVICES)
+
+#define NR_IRQS				(NR_PIRQS + NR_DYNIRQS)
+
+#endif /* _ASM_X86_IRQ_VECTORS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/setup.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/setup.h
@@ -0,0 +1,8 @@
+#ifndef __ASSEMBLY__
+
+void xen_start_kernel(void);
+void xen_arch_setup(void);
+
+#endif
+
+#include_next <asm/setup.h>
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/hypervisor.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/hypervisor.h
@@ -0,0 +1,388 @@
+/******************************************************************************
+ * hypervisor.h
+ * 
+ * Linux-specific hypervisor handling.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * 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 __HYPERVISOR_H__
+#define __HYPERVISOR_H__
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/platform.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/nmi.h>
+#include <xen/interface/tmem.h>
+#include <xen/interface/arch-x86/xen-mca.h>
+#include <asm/percpu.h>
+#include <asm/ptrace.h>
+#include <asm/pgtable_types.h>
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
+DECLARE_PER_CPU(struct vcpu_info, vcpu_info);
+#define vcpu_info(cpu) (&per_cpu(vcpu_info, cpu))
+#define current_vcpu_info() (&__get_cpu_var(vcpu_info))
+#define vcpu_info_read(fld) percpu_read(vcpu_info.fld)
+#define vcpu_info_write(fld, val) percpu_write(vcpu_info.fld, val)
+#define vcpu_info_xchg(fld, val) percpu_xchg(vcpu_info.fld, val)
+void setup_vcpu_info(unsigned int cpu);
+void adjust_boot_vcpu_info(void);
+#else
+#define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu))
+#ifdef CONFIG_SMP
+#define current_vcpu_info() vcpu_info(smp_processor_id())
+#else
+#define current_vcpu_info() vcpu_info(0)
+#endif
+#define vcpu_info_read(fld) (current_vcpu_info()->fld)
+#define vcpu_info_write(fld, val) (current_vcpu_info()->fld = (val))
+static inline void setup_vcpu_info(unsigned int cpu) {}
+#endif
+
+#ifdef CONFIG_X86_32
+extern unsigned long hypervisor_virt_start;
+#endif
+
+/* arch/xen/i386/kernel/setup.c */
+extern start_info_t *xen_start_info;
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN)
+#else
+#define is_initial_xendomain() 0
+#endif
+
+#define init_hypervisor(c) ((void)((c)->x86_hyper_vendor = X86_HYPER_VENDOR_XEN))
+#define init_hypervisor_platform() init_hypervisor(&boot_cpu_data)
+
+/* arch/xen/kernel/evtchn.c */
+/* Force a proper event-channel callback from Xen. */
+void force_evtchn_callback(void);
+
+/* arch/xen/kernel/process.c */
+void xen_cpu_idle (void);
+
+/* arch/xen/i386/kernel/hypervisor.c */
+void do_hypervisor_callback(struct pt_regs *regs);
+
+/* arch/xen/i386/mm/hypervisor.c */
+/*
+ * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
+ * be MACHINE addresses.
+ */
+
+void xen_pt_switch(pgd_t *);
+void xen_new_user_pt(pgd_t *); /* x86_64 only */
+void xen_load_gs(unsigned int selector); /* x86_64 only */
+void xen_tlb_flush(void);
+void xen_invlpg(unsigned long ptr);
+
+void xen_l1_entry_update(pte_t *ptr, pte_t val);
+void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
+void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
+void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
+void xen_pgd_pin(pgd_t *);
+void xen_pgd_unpin(pgd_t *);
+
+void xen_init_pgd_pin(void);
+
+void xen_set_ldt(const void *ptr, unsigned int ents);
+
+#ifdef CONFIG_SMP
+#include <linux/cpumask.h>
+void xen_tlb_flush_all(void);
+void xen_invlpg_all(unsigned long ptr);
+void xen_tlb_flush_mask(const cpumask_t *mask);
+void xen_invlpg_mask(const cpumask_t *mask, unsigned long ptr);
+#else
+#define xen_tlb_flush_all xen_tlb_flush
+#define xen_invlpg_all xen_invlpg
+#endif
+
+/* Returns zero on success else negative errno. */
+int xen_create_contiguous_region(
+    unsigned long vstart, unsigned int order, unsigned int address_bits);
+void xen_destroy_contiguous_region(
+    unsigned long vstart, unsigned int order);
+int early_create_contiguous_region(unsigned long pfn, unsigned int order,
+				   unsigned int address_bits);
+
+struct page;
+
+int xen_limit_pages_to_max_mfn(
+	struct page *pages, unsigned int order, unsigned int address_bits);
+
+/* Turn jiffies into Xen system time. */
+u64 jiffies_to_st(unsigned long jiffies);
+
+#ifdef CONFIG_XEN_SCRUB_PAGES
+void scrub_pages(void *, unsigned int);
+#else
+#define scrub_pages(_p,_n) ((void)0)
+#endif
+
+#if defined(CONFIG_XEN) && !defined(MODULE)
+
+DECLARE_PER_CPU(bool, xen_lazy_mmu);
+
+void xen_multicall_flush(bool);
+
+int __must_check xen_multi_update_va_mapping(unsigned long va, pte_t,
+					     unsigned long flags);
+int __must_check xen_multi_mmu_update(mmu_update_t *, unsigned int count,
+				      unsigned int *success_count, domid_t);
+int __must_check xen_multi_mmuext_op(struct mmuext_op *, unsigned int count,
+				     unsigned int *success_count, domid_t);
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+static inline void arch_enter_lazy_mmu_mode(void)
+{
+	percpu_write(xen_lazy_mmu, true);
+}
+
+static inline void arch_leave_lazy_mmu_mode(void)
+{
+	percpu_write(xen_lazy_mmu, false);
+	xen_multicall_flush(false);
+}
+
+#define arch_use_lazy_mmu_mode() unlikely(percpu_read(xen_lazy_mmu))
+
+#if 0 /* All uses are in places potentially called asynchronously, but
+       * asynchronous code should rather not make use of lazy mode at all.
+       * Therefore, all uses of this function get commented out, proper
+       * detection of asynchronous invocations is added whereever needed,
+       * and this function is disabled to catch any new (improper) uses.
+       */
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+	if (arch_use_lazy_mmu_mode())
+		xen_multicall_flush(false);
+}
+#endif
+
+#else /* !CONFIG_XEN || MODULE */
+
+static inline void xen_multicall_flush(bool ignore) {}
+#define arch_use_lazy_mmu_mode() false
+#define xen_multi_update_va_mapping(...) ({ BUG(); -ENOSYS; })
+#define xen_multi_mmu_update(...) ({ BUG(); -ENOSYS; })
+#define xen_multi_mmuext_op(...) ({ BUG(); -ENOSYS; })
+
+#endif /* CONFIG_XEN && !MODULE */
+
+#ifdef CONFIG_XEN
+
+struct gnttab_map_grant_ref;
+bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *,
+			   unsigned int count);
+#if CONFIG_XEN_COMPAT < 0x030400
+int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *, unsigned int);
+#else
+static inline int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *m,
+					 unsigned int count)
+{
+	BUG();
+	return -ENOSYS;
+}
+#endif
+
+#else /* !CONFIG_XEN */
+
+#define gnttab_pre_map_adjust(...) false
+#define gnttab_post_map_adjust(...) ({ BUG(); -ENOSYS; })
+
+#endif /* CONFIG_XEN */
+
+#if defined(CONFIG_X86_64)
+#define MULTI_UVMFLAGS_INDEX 2
+#define MULTI_UVMDOMID_INDEX 3
+#else
+#define MULTI_UVMFLAGS_INDEX 3
+#define MULTI_UVMDOMID_INDEX 4
+#endif
+
+#ifdef CONFIG_XEN
+#define is_running_on_xen() 1
+extern char hypercall_page[PAGE_SIZE];
+#else
+extern char *hypercall_stubs;
+#define is_running_on_xen() (!!hypercall_stubs)
+#endif
+
+#include <xen/hypercall.h>
+
+static inline int
+HYPERVISOR_yield(
+	void)
+{
+	int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (rc == -ENOSYS)
+		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
+#endif
+
+	return rc;
+}
+
+static inline int
+HYPERVISOR_block(
+	void)
+{
+	int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (rc == -ENOSYS)
+		rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
+#endif
+
+	return rc;
+}
+
+static inline void __noreturn
+HYPERVISOR_shutdown(
+	unsigned int reason)
+{
+	struct sched_shutdown sched_shutdown = {
+		.reason = reason
+	};
+
+	VOID(HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown));
+#if CONFIG_XEN_COMPAT <= 0x030002
+	VOID(HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason));
+#endif
+	/* Don't recurse needlessly. */
+	BUG_ON(reason != SHUTDOWN_crash);
+	for(;;);
+}
+
+static inline int __must_check
+HYPERVISOR_poll(
+	evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+	int rc;
+	struct sched_poll sched_poll = {
+		.nr_ports = nr_ports,
+		.timeout = jiffies_to_st(timeout)
+	};
+	set_xen_guest_handle(sched_poll.ports, ports);
+
+	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (rc == -ENOSYS)
+		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
+#endif
+
+	return rc;
+}
+
+static inline int __must_check
+HYPERVISOR_poll_no_timeout(
+	evtchn_port_t *ports, unsigned int nr_ports)
+{
+	int rc;
+	struct sched_poll sched_poll = {
+		.nr_ports = nr_ports
+	};
+	set_xen_guest_handle(sched_poll.ports, ports);
+
+	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (rc == -ENOSYS)
+		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
+#endif
+
+	return rc;
+}
+
+#ifdef CONFIG_XEN
+
+static inline void
+MULTI_update_va_mapping(
+    multicall_entry_t *mcl, unsigned long va,
+    pte_t new_val, unsigned long flags)
+{
+    mcl->op = __HYPERVISOR_update_va_mapping;
+    mcl->args[0] = va;
+#if defined(CONFIG_X86_64)
+    mcl->args[1] = new_val.pte;
+#elif defined(CONFIG_X86_PAE)
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = new_val.pte_high;
+#else
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = 0;
+#endif
+    mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
+}
+
+static inline void
+MULTI_mmu_update(multicall_entry_t *mcl, mmu_update_t *req,
+		 unsigned int count, unsigned int *success_count,
+		 domid_t domid)
+{
+    mcl->op = __HYPERVISOR_mmu_update;
+    mcl->args[0] = (unsigned long)req;
+    mcl->args[1] = count;
+    mcl->args[2] = (unsigned long)success_count;
+    mcl->args[3] = domid;
+}
+
+static inline void
+MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd,
+		     void *uop, unsigned int count)
+{
+    mcl->op = __HYPERVISOR_grant_table_op;
+    mcl->args[0] = cmd;
+    mcl->args[1] = (unsigned long)uop;
+    mcl->args[2] = count;
+}
+
+#else /* !defined(CONFIG_XEN) */
+
+/* Multicalls not supported for HVM guests. */
+#define MULTI_update_va_mapping(a,b,c,d) ((void)0)
+#define MULTI_grant_table_op(a,b,c,d) ((void)0)
+
+#endif
+
+#define uvm_multi(cpumask) ((unsigned long)cpumask_bits(cpumask) | UVMF_MULTI)
+
+#ifdef LINUX
+/* drivers/staging/ use Windows-style types, including VOID */
+#undef VOID
+#endif
+
+#endif /* __HYPERVISOR_H__ */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/maddr_64.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/maddr_64.h
@@ -0,0 +1,163 @@
+#ifndef _X86_64_MADDR_H
+#define _X86_64_MADDR_H
+
+#include <asm/bug.h>
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
+#define INVALID_P2M_ENTRY	(~0UL)
+#define FOREIGN_FRAME_BIT	(1UL<<63)
+#define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
+
+/* Definitions for machine and pseudophysical addresses. */
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+
+#ifdef CONFIG_XEN
+
+extern unsigned long *phys_to_machine_mapping;
+extern unsigned long  max_mapnr;
+
+#undef machine_to_phys_mapping
+extern unsigned long *machine_to_phys_mapping;
+extern unsigned int   machine_to_phys_order;
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return pfn;
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return 1;
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+	unsigned long pfn;
+
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return mfn;
+
+	if (unlikely((mfn >> machine_to_phys_order) != 0))
+		return max_mapnr;
+
+	/* The array access can fail (e.g., device space beyond end of RAM). */
+	asm (
+		"1:	movq %1,%0\n"
+		"2:\n"
+		".section .fixup,\"ax\"\n"
+		"3:	movq %2,%0\n"
+		"	jmp  2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 8\n"
+		"	.quad 1b,3b\n"
+		".previous"
+		: "=r" (pfn)
+		: "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) );
+
+	return pfn;
+}
+
+/*
+ * We detect special mappings in one of two ways:
+ *  1. If the MFN is an I/O page then Xen will set the m2p entry
+ *     to be outside our maximum possible pseudophys range.
+ *  2. If the MFN belongs to a different domain then we will certainly
+ *     not have MFN in our p2m table. Conversely, if the page is ours,
+ *     then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ *      use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ *      require. In all the cases we care about, the FOREIGN_FRAME bit is
+ *      masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+	unsigned long pfn = mfn_to_pfn(mfn);
+	if (likely(pfn < max_mapnr)
+	    && likely(!xen_feature(XENFEAT_auto_translated_physmap))
+	    && unlikely(phys_to_machine_mapping[pfn] != mfn))
+		return max_mapnr; /* force !pfn_valid() */
+	return pfn;
+}
+
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+	if (likely(max_mapnr))
+		BUG_ON(pfn >= max_mapnr);
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+		return;
+	}
+	phys_to_machine_mapping[pfn] = mfn;
+}
+
+static inline maddr_t phys_to_machine(paddr_t phys)
+{
+	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+	return machine;
+}
+
+static inline paddr_t machine_to_phys(maddr_t machine)
+{
+	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+	return phys;
+}
+
+static inline paddr_t pte_phys_to_machine(paddr_t phys)
+{
+	maddr_t machine;
+	machine = pfn_to_mfn((phys & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT);
+	machine = (machine << PAGE_SHIFT) | (phys & ~PHYSICAL_PAGE_MASK);
+	return machine;
+}
+
+static inline paddr_t pte_machine_to_phys(maddr_t machine)
+{
+	paddr_t phys;
+	phys = mfn_to_pfn((machine & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT);
+	phys = (phys << PAGE_SHIFT) | (machine & ~PHYSICAL_PAGE_MASK);
+	return phys;
+}
+
+#else /* !CONFIG_XEN */
+
+#define pfn_to_mfn(pfn) (pfn)
+#define mfn_to_pfn(mfn) (mfn)
+#define mfn_to_local_pfn(mfn) (mfn)
+#define set_phys_to_machine(pfn, mfn) ((void)0)
+#define phys_to_machine_mapping_valid(pfn) (1)
+#define phys_to_machine(phys) ((maddr_t)(phys))
+#define machine_to_phys(mach) ((paddr_t)(mach))
+#define pfn_pte_ma(pfn, prot) pfn_pte(pfn, prot)
+#define __pte_ma(x) __pte(x)
+
+#endif /* !CONFIG_XEN */
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)	(phys_to_machine(__pa(v)))
+#define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
+#define mfn_to_virt(m)		(__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+#endif /* _X86_64_MADDR_H */
+
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/smp.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/smp.h
@@ -0,0 +1,221 @@
+#ifndef _ASM_X86_SMP_H
+#define _ASM_X86_SMP_H
+#ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <asm/percpu.h>
+
+/*
+ * We need the APIC definitions automatically as part of 'smp.h'
+ */
+#ifdef CONFIG_X86_LOCAL_APIC
+# include <asm/mpspec.h>
+# include <asm/apic.h>
+# ifdef CONFIG_X86_IO_APIC
+#  include <asm/io_apic.h>
+# endif
+#endif
+#include <linux/thread_info.h>
+#include <asm/cpumask.h>
+
+extern int smp_num_siblings;
+extern unsigned int num_processors;
+
+DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
+DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
+DECLARE_PER_CPU(u16, cpu_llc_id);
+DECLARE_PER_CPU(int, cpu_number);
+
+static inline struct cpumask *cpu_sibling_mask(int cpu)
+{
+	return per_cpu(cpu_sibling_map, cpu);
+}
+
+static inline struct cpumask *cpu_core_mask(int cpu)
+{
+	return per_cpu(cpu_core_map, cpu);
+}
+
+DECLARE_PER_CPU(u16, x86_cpu_to_apicid);
+DECLARE_PER_CPU(u16, x86_bios_cpu_apicid);
+
+#ifdef CONFIG_SMP
+
+#ifndef CONFIG_XEN
+
+/* Static state in head.S used to set up a CPU */
+extern struct {
+	void *sp;
+	unsigned short ss;
+} stack_start;
+
+struct smp_ops {
+	void (*smp_prepare_boot_cpu)(void);
+	void (*smp_prepare_cpus)(unsigned max_cpus);
+	void (*smp_cpus_done)(unsigned max_cpus);
+
+	void (*stop_other_cpus)(int wait);
+	void (*smp_send_reschedule)(int cpu);
+
+	int (*cpu_up)(unsigned cpu);
+	int (*cpu_disable)(void);
+	void (*cpu_die)(unsigned int cpu);
+	void (*play_dead)(void);
+
+	void (*send_call_func_ipi)(const struct cpumask *mask);
+	void (*send_call_func_single_ipi)(int cpu);
+};
+
+/* Globals due to paravirt */
+extern void set_cpu_sibling_map(int cpu);
+
+#ifndef CONFIG_PARAVIRT
+#define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0)
+#endif
+extern struct smp_ops smp_ops;
+
+static inline void smp_send_stop(void)
+{
+	smp_ops.stop_other_cpus(0);
+}
+
+static inline void stop_other_cpus(void)
+{
+	smp_ops.stop_other_cpus(1);
+}
+
+static inline void smp_prepare_boot_cpu(void)
+{
+	smp_ops.smp_prepare_boot_cpu();
+}
+
+static inline void smp_prepare_cpus(unsigned int max_cpus)
+{
+	smp_ops.smp_prepare_cpus(max_cpus);
+}
+
+static inline void smp_cpus_done(unsigned int max_cpus)
+{
+	smp_ops.smp_cpus_done(max_cpus);
+}
+
+static inline int __cpu_up(unsigned int cpu)
+{
+	return smp_ops.cpu_up(cpu);
+}
+
+static inline int __cpu_disable(void)
+{
+	return smp_ops.cpu_disable();
+}
+
+static inline void __cpu_die(unsigned int cpu)
+{
+	smp_ops.cpu_die(cpu);
+}
+
+static inline void play_dead(void)
+{
+	smp_ops.play_dead();
+}
+
+static inline void smp_send_reschedule(int cpu)
+{
+	smp_ops.smp_send_reschedule(cpu);
+}
+
+static inline void arch_send_call_function_single_ipi(int cpu)
+{
+	smp_ops.send_call_func_single_ipi(cpu);
+}
+
+static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	smp_ops.send_call_func_ipi(mask);
+}
+
+void cpu_disable_common(void);
+void native_smp_prepare_boot_cpu(void);
+void native_smp_prepare_cpus(unsigned int max_cpus);
+void native_smp_cpus_done(unsigned int max_cpus);
+int native_cpu_up(unsigned int cpunum);
+int native_cpu_disable(void);
+void native_cpu_die(unsigned int cpu);
+void native_play_dead(void);
+void play_dead_common(void);
+void wbinvd_on_cpu(int cpu);
+int wbinvd_on_all_cpus(void);
+
+#else /* CONFIG_XEN */
+
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+void xen_stop_other_cpus(int wait);
+void xen_smp_send_reschedule(int cpu);
+void xen_send_call_func_ipi(const struct cpumask *mask);
+void xen_send_call_func_single_ipi(int cpu);
+
+static inline void smp_send_stop(void)
+{
+	xen_stop_other_cpus(0);
+}
+
+#define smp_send_reschedule	xen_smp_send_reschedule
+#define arch_send_call_function_single_ipi	xen_send_call_func_single_ipi
+#define arch_send_call_function_ipi_mask	xen_send_call_func_ipi
+
+void play_dead(void);
+
+#endif /* CONFIG_XEN */
+
+void wbinvd_on_cpu(int cpu);
+int wbinvd_on_all_cpus(void);
+
+void smp_store_cpu_info(int id);
+#define cpu_physical_id(cpu)	per_cpu(x86_cpu_to_apicid, cpu)
+
+/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+static inline int num_booting_cpus(void)
+{
+	return cpumask_weight(cpu_callout_mask);
+}
+#elif /* !CONFIG_SMP */ !defined(CONFIG_XEN)
+#define wbinvd_on_cpu(cpu)     wbinvd()
+static inline int wbinvd_on_all_cpus(void)
+{
+	wbinvd();
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_XEN
+int wbinvd_on_all_cpus(void);
+#endif
+
+extern unsigned disabled_cpus __cpuinitdata;
+
+#include <asm/smp-processor-id.h>
+
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN)
+
+#ifndef CONFIG_X86_64
+static inline int logical_smp_processor_id(void)
+{
+	/* we don't want to mark this access volatile - bad code generation */
+	return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
+}
+
+#endif
+
+extern int hard_smp_processor_id(void);
+
+#else /* CONFIG_X86_LOCAL_APIC */
+
+# ifndef CONFIG_SMP
+#  define hard_smp_processor_id()	0
+# endif
+
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_X86_SMP_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/vga.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/vga.h
@@ -0,0 +1,20 @@
+/*
+ *	Access to VGA videoram
+ *
+ *	(c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _ASM_X86_VGA_H
+#define _ASM_X86_VGA_H
+
+/*
+ *	On the PC, we can just recalculate addresses and then
+ *	access the videoram directly without any black magic.
+ */
+
+#define VGA_MAP_MEM(x, s) (unsigned long)isa_bus_to_virt(x)
+
+#define vga_readb(x) (*(x))
+#define vga_writeb(x, y) (*(y) = (x))
+
+#endif /* _ASM_X86_VGA_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgtable_64_types.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgtable_64_types.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_X86_PGTABLE_64_DEFS_H
+#define _ASM_X86_PGTABLE_64_DEFS_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef unsigned long	pteval_t;
+typedef unsigned long	pmdval_t;
+typedef unsigned long	pudval_t;
+typedef unsigned long	pgdval_t;
+typedef unsigned long	pgprotval_t;
+
+typedef union { pteval_t pte; unsigned int pte_low; } pte_t;
+
+#endif	/* !__ASSEMBLY__ */
+
+#define SHARED_KERNEL_PMD	0
+#define PAGETABLE_LEVELS	4
+
+/*
+ * PGDIR_SHIFT determines what a top-level page table entry can map
+ */
+#define PGDIR_SHIFT	39
+#define PTRS_PER_PGD	512
+
+/*
+ * 3rd level page
+ */
+#define PUD_SHIFT	30
+#define PTRS_PER_PUD	512
+
+/*
+ * PMD_SHIFT determines the size of the area a middle-level
+ * page table can map
+ */
+#define PMD_SHIFT	21
+#define PTRS_PER_PMD	512
+
+/*
+ * entries per page directory level
+ */
+#define PTRS_PER_PTE	512
+
+#define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE - 1))
+#define PUD_SIZE	(_AC(1, UL) << PUD_SHIFT)
+#define PUD_MASK	(~(PUD_SIZE - 1))
+#define PGDIR_SIZE	(_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE - 1))
+
+/* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
+#define MAX_PHYSMEM_BITS 43
+#define MAXMEM		 _AC(__AC(1, UL) << MAX_PHYSMEM_BITS, UL)
+#define VMALLOC_START    _AC(0xffffc90000000000, UL)
+#define VMALLOC_END      _AC(0xffffe8ffffffffff, UL)
+#define VMEMMAP_START	 _AC(0xffffea0000000000, UL)
+#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+#define MODULES_END      _AC(0xffffffffff000000, UL)
+#define MODULES_LEN   (MODULES_END - MODULES_VADDR)
+
+#endif /* _ASM_X86_PGTABLE_64_DEFS_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/io.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/io.h
@@ -0,0 +1,230 @@
+#ifndef _ASM_X86_IO_H
+#define _ASM_X86_IO_H
+
+#define ARCH_HAS_IOREMAP_WC
+
+#include <linux/compiler.h>
+#include <asm-generic/int-ll64.h>
+#include <asm/page.h>
+#ifdef __KERNEL__
+#include <asm/fixmap.h>
+#endif
+
+#define build_mmio_read(name, size, type, reg, barrier) \
+static inline type name(const volatile void __iomem *addr) \
+{ type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+:"m" (*(volatile type __force *)addr) barrier); return ret; }
+
+#define build_mmio_write(name, size, type, reg, barrier) \
+static inline void name(type val, volatile void __iomem *addr) \
+{ asm volatile("mov" size " %0,%1": :reg (val), \
+"m" (*(volatile type __force *)addr) barrier); }
+
+build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
+build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
+build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
+
+build_mmio_read(__readb, "b", unsigned char, "=q", )
+build_mmio_read(__readw, "w", unsigned short, "=r", )
+build_mmio_read(__readl, "l", unsigned int, "=r", )
+
+build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
+build_mmio_write(writew, "w", unsigned short, "r", :"memory")
+build_mmio_write(writel, "l", unsigned int, "r", :"memory")
+
+build_mmio_write(__writeb, "b", unsigned char, "q", )
+build_mmio_write(__writew, "w", unsigned short, "r", )
+build_mmio_write(__writel, "l", unsigned int, "r", )
+
+#define readb_relaxed(a) __readb(a)
+#define readw_relaxed(a) __readw(a)
+#define readl_relaxed(a) __readl(a)
+#define __raw_readb __readb
+#define __raw_readw __readw
+#define __raw_readl __readl
+
+#define __raw_writeb __writeb
+#define __raw_writew __writew
+#define __raw_writel __writel
+
+#define mmiowb() barrier()
+
+#ifdef CONFIG_X86_64
+
+build_mmio_read(readq, "q", unsigned long, "=r", :"memory")
+build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
+
+#else
+
+static inline __u64 readq(const volatile void __iomem *addr)
+{
+	const volatile u32 __iomem *p = addr;
+	u32 low, high;
+
+	low = readl(p);
+	high = readl(p + 1);
+
+	return low + ((u64)high << 32);
+}
+
+static inline void writeq(__u64 val, volatile void __iomem *addr)
+{
+	writel(val, addr);
+	writel(val >> 32, addr+4);
+}
+
+#endif
+
+#define readq_relaxed(a)	readq(a)
+
+#define __raw_readq(a)		readq(a)
+#define __raw_writeq(val, addr)	writeq(val, addr)
+
+/* Let people know that we have them */
+#define readq			readq
+#define writeq			writeq
+
+#define native_io_delay xen_io_delay
+
+/**
+ *	virt_to_phys	-	map virtual addresses to physical
+ *	@address: address to remap
+ *
+ *	The returned physical address is the physical (CPU) mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses directly mapped or allocated via kmalloc.
+ *
+ *	This function does not give bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
+ */
+
+static inline phys_addr_t virt_to_phys(volatile void *address)
+{
+	return __pa(address);
+}
+
+/**
+ *	phys_to_virt	-	map physical address to virtual
+ *	@address: address to remap
+ *
+ *	The returned virtual address is a current CPU mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses that have a kernel mapping
+ *
+ *	This function does not handle bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
+ */
+
+static inline void *phys_to_virt(phys_addr_t address)
+{
+	return __va(address);
+}
+
+/*
+ * Change "struct page" to physical address.
+ */
+#define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
+#undef page_to_phys
+#define page_to_phys(page)	 (phys_to_machine(page_to_pseudophys(page)))
+#define page_to_bus(page)	 (phys_to_machine(page_to_pseudophys(page)))
+
+/*
+ * ISA I/O bus memory addresses are 1:1 with the physical address.
+ * However, we truncate the address to unsigned int to avoid undesirable
+ * promitions in legacy drivers.
+ */
+#define isa_virt_to_bus(_x) ({ \
+	unsigned long _va_ = (unsigned long)(_x); \
+	_va_ - fix_to_virt(FIX_ISAMAP_BEGIN) < (NR_FIX_ISAMAPS << PAGE_SHIFT) \
+	? _va_ - fix_to_virt(FIX_ISAMAP_BEGIN) \
+	: ({ BUG(); (unsigned long)virt_to_bus(_va_); }); })
+#define isa_bus_to_virt(_x) ((void *)fix_to_virt(FIX_ISAMAP_BEGIN) + (_x))
+
+/*
+ * However PCI ones are not necessarily 1:1 and therefore these interfaces
+ * are forbidden in portable PCI drivers.
+ *
+ * Allow them on x86 for legacy drivers, though.
+ */
+#define virt_to_bus(_x) phys_to_machine(__pa(_x))
+#define bus_to_virt(_x) __va(machine_to_phys(_x))
+
+/**
+ * ioremap     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * If the area you are trying to map is a PCI BAR you should have a
+ * look at pci_iomap().
+ */
+extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
+				unsigned long prot_val);
+
+/*
+ * The default ioremap() behavior is non-cached:
+ */
+static inline void __iomem *ioremap(resource_size_t offset, unsigned long size)
+{
+	return ioremap_nocache(offset, size);
+}
+
+extern void iounmap(volatile void __iomem *addr);
+
+extern void set_iounmap_nonlazy(void);
+
+#ifdef CONFIG_X86_32
+# include "../../asm/io_32.h"
+#else
+# include "../../asm/io_64.h"
+#endif
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+
+/* We will be supplying our own /dev/mem implementation */
+#define ARCH_HAS_DEV_MEM
+
+#define bvec_to_pseudophys(bv)	 (page_to_pseudophys((bv)->bv_page) + \
+				  (unsigned long) (bv)->bv_offset)
+
+#define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \
+	(bvec_to_phys(vec1) + (vec1)->bv_len == bvec_to_phys(vec2) \
+	 && bvec_to_pseudophys(vec1) + (vec1)->bv_len \
+	    == bvec_to_pseudophys(vec2))
+
+#undef __ISA_IO_base
+
+#endif
+
+extern void *xlate_dev_mem_ptr(unsigned long phys);
+extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+
+extern int ioremap_check_change_attr(unsigned long mfn, unsigned long size,
+				     unsigned long prot_val);
+extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size);
+
+/*
+ * early_ioremap() and early_iounmap() are for temporary early boot-time
+ * mappings, before the real ioremap() is functional.
+ * A boot-time mapping is currently limited to at most 16 pages.
+ */
+extern void early_ioremap_init(void);
+extern void early_ioremap_reset(void);
+extern void __iomem *early_ioremap(resource_size_t phys_addr,
+				   unsigned long size);
+extern void __iomem *early_memremap(resource_size_t phys_addr,
+				    unsigned long size);
+extern void early_iounmap(void __iomem *addr, unsigned long size);
+
+#define IO_SPACE_LIMIT 0xffff
+
+#endif /* _ASM_X86_IO_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/maddr.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/maddr.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_32
+# include "maddr_32.h"
+#else
+# include "maddr_64.h"
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/pgalloc.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/pgalloc.h
@@ -0,0 +1,159 @@
+#ifndef _ASM_X86_PGALLOC_H
+#define _ASM_X86_PGALLOC_H
+
+#include <linux/threads.h>
+#include <linux/mm.h>		/* for struct page */
+#include <linux/pagemap.h>
+
+#include <asm/io.h>		/* for phys_to_virt and page_to_pseudophys */
+
+static inline int paravirt_pgd_alloc(struct mm_struct *mm) { return 0; }
+static inline void paravirt_pgd_free(struct mm_struct *mm, pgd_t *pgd) {}
+
+static inline void paravirt_alloc_pte(struct mm_struct *mm, unsigned long pfn)	{}
+static inline void paravirt_alloc_pmd(struct mm_struct *mm, unsigned long pfn)	{}
+static inline void paravirt_alloc_pmd_clone(unsigned long pfn, unsigned long clonepfn,
+					    unsigned long start, unsigned long count) {}
+static inline void paravirt_alloc_pud(struct mm_struct *mm, unsigned long pfn)	{}
+static inline void paravirt_release_pte(unsigned long pfn) {}
+static inline void paravirt_release_pmd(unsigned long pfn) {}
+static inline void paravirt_release_pud(unsigned long pfn) {}
+
+#ifdef CONFIG_X86_64
+void early_make_page_readonly(void *va, unsigned int feature);
+pmd_t *early_get_pmd(unsigned long va);
+#define make_lowmem_page_readonly make_page_readonly
+#define make_lowmem_page_writable make_page_writable
+#endif
+
+/*
+ * Flags to use when allocating a user page table page.
+ */
+extern gfp_t __userpte_alloc_gfp;
+
+/*
+ * Allocate and free page tables.
+ */
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
+
+/* Should really implement gc for free page table pages. This could be
+   done with a reference count in struct page. */
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+	make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
+	free_page((unsigned long)pte);
+}
+
+extern void __pte_free(pgtable_t);
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+	__pte_free(pte);
+}
+
+extern void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
+				  unsigned long address)
+{
+	___pte_free_tlb(tlb, pte);
+}
+
+static inline void pmd_populate_kernel(struct mm_struct *mm,
+				       pmd_t *pmd, pte_t *pte)
+{
+	paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
+	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				struct page *pte)
+{
+	unsigned long pfn = page_to_pfn(pte);
+	pmd_t ent = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE);
+
+	paravirt_alloc_pte(mm, pfn);
+	if (PagePinned(virt_to_page(pmd))) {
+#ifndef CONFIG_HIGHPTE
+		BUG_ON(PageHighMem(pte));
+#endif
+		set_pmd(pmd, ent);
+	} else
+		*pmd = ent;
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#if PAGETABLE_LEVELS > 2
+extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr);
+extern void __pmd_free(pgtable_t);
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+	__pmd_free(virt_to_page(pmd));
+}
+
+extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+				  unsigned long adddress)
+{
+	___pmd_free_tlb(tlb, pmd);
+}
+
+#ifdef CONFIG_X86_PAE
+extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
+#else	/* !CONFIG_X86_PAE */
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	pud_t ent = __pud(_PAGE_TABLE | __pa(pmd));
+
+	paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT);
+	if (PagePinned(virt_to_page(pud)))
+		set_pud(pud, ent);
+	else
+		*pud = ent;
+}
+#endif	/* CONFIG_X86_PAE */
+
+#if PAGETABLE_LEVELS > 3
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+	pgd_t ent = __pgd(_PAGE_TABLE | __pa(pud));
+
+	paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT);
+	if (unlikely(PagePinned(virt_to_page(pgd))))
+		xen_l4_entry_update(pgd, ent);
+	else
+		*__user_pgd(pgd) = *pgd = ent;
+}
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return (pud_t *)pmd_alloc_one(mm, addr);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+	__pmd_free(virt_to_page(pud));
+}
+
+extern void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+				  unsigned long address)
+{
+	___pud_free_tlb(tlb, pud);
+}
+
+#endif	/* PAGETABLE_LEVELS > 3 */
+#endif	/* PAGETABLE_LEVELS > 2 */
+
+#endif /* _ASM_X86_PGALLOC_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/gnttab_dma.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/gnttab_dma.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 _ASM_I386_GNTTAB_DMA_H
+#define _ASM_I386_GNTTAB_DMA_H
+
+static inline int gnttab_dma_local_pfn(struct page *page)
+{
+	/* Has it become a local MFN? */
+	return pfn_valid(mfn_to_local_pfn(pfn_to_mfn(page_to_pfn(page))));
+}
+
+static inline maddr_t gnttab_dma_map_page(struct page *page)
+{
+	__gnttab_dma_map_page(page);
+	return ((maddr_t)pfn_to_mfn(page_to_pfn(page)) << PAGE_SHIFT);
+}
+
+static inline void gnttab_dma_unmap_page(maddr_t maddr)
+{
+	__gnttab_dma_unmap_page(virt_to_page(bus_to_virt(maddr)));
+}
+
+#endif /* _ASM_I386_GNTTAB_DMA_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/highmem.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/highmem.h
@@ -0,0 +1,98 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *		      Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_X86_HIGHMEM_H
+#define _ASM_X86_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/interrupt.h>
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+/*
+ * Ordering is:
+ *
+ * FIXADDR_TOP
+ * 			fixed_addresses
+ * FIXADDR_START
+ * 			temp fixed addresses
+ * FIXADDR_BOOT_START
+ * 			Persistent kmap area
+ * PKMAP_BASE
+ * VMALLOC_END
+ * 			Vmalloc area
+ * VMALLOC_START
+ * high_memory
+ */
+#define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+extern void *kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+void *kmap(struct page *page);
+void kunmap(struct page *page);
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
+void *kmap_atomic(struct page *page, enum km_type type);
+void *kmap_atomic_pte(struct page *page, enum km_type type);
+void kunmap_atomic(void *kvaddr, enum km_type type);
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+struct page *kmap_atomic_to_page(void *ptr);
+
+#define kmap_atomic_pte(page, type) \
+	kmap_atomic_prot(page, type, \
+	                 PagePinned(page) ? PAGE_KERNEL_RO : kmap_prot)
+
+#define flush_cache_kmaps()	do { } while (0)
+
+extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn,
+					unsigned long end_pfn);
+
+void clear_highpage(struct page *);
+static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+	clear_highpage(page);
+}
+#define __HAVE_ARCH_CLEAR_HIGHPAGE
+#define clear_user_highpage clear_user_highpage
+#define __HAVE_ARCH_CLEAR_USER_HIGHPAGE
+
+void copy_highpage(struct page *to, struct page *from);
+static inline void copy_user_highpage(struct page *to, struct page *from,
+	unsigned long vaddr, struct vm_area_struct *vma)
+{
+	copy_highpage(to, from);
+}
+#define __HAVE_ARCH_COPY_HIGHPAGE
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_X86_HIGHMEM_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/ipi.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/ipi.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_X86_IPI_H
+#define _ASM_X86_IPI_H
+
+#include <asm/hw_irq.h>
+#include <asm/smp.h>
+
+void xen_send_IPI_mask(const struct cpumask *, int vector);
+void xen_send_IPI_mask_allbutself(const struct cpumask *, int vector);
+void xen_send_IPI_allbutself(int vector);
+void xen_send_IPI_all(int vector);
+void xen_send_IPI_self(int vector);
+
+#endif /* _ASM_X86_IPI_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/xor_64.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/xor_64.h
@@ -0,0 +1,337 @@
+#ifndef _ASM_X86_XOR_64_H
+#define _ASM_X86_XOR_64_H
+
+/*
+ * x86-64 changes / gcc fixes from Andi Kleen.
+ * Copyright 2002 Andi Kleen, SuSE Labs.
+ *
+ * This hasn't been optimized for the hammer yet, but there are likely
+ * no advantages to be gotten from x86-64 here anyways.
+ */
+
+typedef struct {
+	unsigned long a, b;
+} __attribute__((aligned(16))) xmm_store_t;
+
+/* Doesn't use gcc to save the XMM registers, because there is no easy way to
+   tell it to do a clts before the register saving. */
+#define XMMS_SAVE				\
+do {						\
+	preempt_disable();			\
+	if (!(current_thread_info()->status & TS_USEDFPU))	\
+		clts();				\
+	asm volatile(				\
+		"movups %%xmm0,(%1)	;\n\t"	\
+		"movups %%xmm1,0x10(%1)	;\n\t"	\
+		"movups %%xmm2,0x20(%1)	;\n\t"	\
+		"movups %%xmm3,0x30(%1)	;\n\t"	\
+		: "=&r" (cr0)			\
+		: "r" (xmm_save) 		\
+		: "memory");			\
+} while (0)
+
+#define XMMS_RESTORE				\
+do {						\
+	asm volatile(				\
+		"sfence			;\n\t"	\
+		"movups (%1),%%xmm0	;\n\t"	\
+		"movups 0x10(%1),%%xmm1	;\n\t"	\
+		"movups 0x20(%1),%%xmm2	;\n\t"	\
+		"movups 0x30(%1),%%xmm3	;\n\t"	\
+		:				\
+		: "r" (cr0), "r" (xmm_save)	\
+		: "memory");			\
+	if (!(current_thread_info()->status & TS_USEDFPU))	\
+		stts();				\
+	preempt_enable();			\
+} while (0)
+
+#define OFFS(x)		"16*("#x")"
+#define PF_OFFS(x)	"256+16*("#x")"
+#define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%[p1])		;\n"
+#define LD(x, y)	"       movaps   "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
+#define ST(x, y)	"       movaps %%xmm"#y",   "OFFS(x)"(%[p1])	;\n"
+#define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%[p2])		;\n"
+#define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%[p3])		;\n"
+#define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%[p4])		;\n"
+#define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%[p5])		;\n"
+#define PF5(x)		"	prefetchnta "PF_OFFS(x)"(%[p6])		;\n"
+#define XO1(x, y)	"       xorps   "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
+#define XO2(x, y)	"       xorps   "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
+#define XO3(x, y)	"       xorps   "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
+#define XO4(x, y)	"       xorps   "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
+#define XO5(x, y)	"       xorps   "OFFS(x)"(%[p6]), %%xmm"#y"	;\n"
+
+
+static void
+xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+	unsigned int lines = bytes >> 8;
+	unsigned long cr0;
+	xmm_store_t xmm_save[4];
+
+	XMMS_SAVE;
+
+	asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+		LD(i, 0)				\
+			LD(i + 1, 1)			\
+		PF1(i)					\
+				PF1(i + 2)		\
+				LD(i + 2, 2)		\
+					LD(i + 3, 3)	\
+		PF0(i + 4)				\
+				PF0(i + 6)		\
+		XO1(i, 0)				\
+			XO1(i + 1, 1)			\
+				XO1(i + 2, 2)		\
+					XO1(i + 3, 3)	\
+		ST(i, 0)				\
+			ST(i + 1, 1)			\
+				ST(i + 2, 2)		\
+					ST(i + 3, 3)	\
+
+
+		PF0(0)
+				PF0(2)
+
+	" .align 32			;\n"
+	" 1:                            ;\n"
+
+		BLOCK(0)
+		BLOCK(4)
+		BLOCK(8)
+		BLOCK(12)
+
+	"       addq %[inc], %[p1]           ;\n"
+	"       addq %[inc], %[p2]           ;\n"
+		"		decl %[cnt] ; jnz 1b"
+	: [p1] "+r" (p1), [p2] "+r" (p2), [cnt] "+r" (lines)
+	: [inc] "r" (256UL)
+	: "memory");
+
+	XMMS_RESTORE;
+}
+
+static void
+xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	  unsigned long *p3)
+{
+	unsigned int lines = bytes >> 8;
+	xmm_store_t xmm_save[4];
+	unsigned long cr0;
+
+	XMMS_SAVE;
+
+	asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+		PF1(i)					\
+				PF1(i + 2)		\
+		LD(i, 0)					\
+			LD(i + 1, 1)			\
+				LD(i + 2, 2)		\
+					LD(i + 3, 3)	\
+		PF2(i)					\
+				PF2(i + 2)		\
+		PF0(i + 4)				\
+				PF0(i + 6)		\
+		XO1(i, 0)				\
+			XO1(i + 1, 1)			\
+				XO1(i + 2, 2)		\
+					XO1(i + 3, 3)	\
+		XO2(i, 0)				\
+			XO2(i + 1, 1)			\
+				XO2(i + 2, 2)		\
+					XO2(i + 3, 3)	\
+		ST(i, 0)				\
+			ST(i + 1, 1)			\
+				ST(i + 2, 2)		\
+					ST(i + 3, 3)	\
+
+
+		PF0(0)
+				PF0(2)
+
+	" .align 32			;\n"
+	" 1:                            ;\n"
+
+		BLOCK(0)
+		BLOCK(4)
+		BLOCK(8)
+		BLOCK(12)
+
+	"       addq %[inc], %[p1]           ;\n"
+	"       addq %[inc], %[p2]          ;\n"
+	"       addq %[inc], %[p3]           ;\n"
+		"		decl %[cnt] ; jnz 1b"
+	: [cnt] "+r" (lines),
+	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
+	: [inc] "r" (256UL)
+	: "memory");
+	XMMS_RESTORE;
+}
+
+static void
+xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	  unsigned long *p3, unsigned long *p4)
+{
+	unsigned int lines = bytes >> 8;
+	xmm_store_t xmm_save[4];
+	unsigned long cr0;
+
+	XMMS_SAVE;
+
+	asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+		PF1(i)					\
+				PF1(i + 2)		\
+		LD(i, 0)				\
+			LD(i + 1, 1)			\
+				LD(i + 2, 2)		\
+					LD(i + 3, 3)	\
+		PF2(i)					\
+				PF2(i + 2)		\
+		XO1(i, 0)				\
+			XO1(i + 1, 1)			\
+				XO1(i + 2, 2)		\
+					XO1(i + 3, 3)	\
+		PF3(i)					\
+				PF3(i + 2)		\
+		PF0(i + 4)				\
+				PF0(i + 6)		\
+		XO2(i, 0)				\
+			XO2(i + 1, 1)			\
+				XO2(i + 2, 2)		\
+					XO2(i + 3, 3)	\
+		XO3(i, 0)				\
+			XO3(i + 1, 1)			\
+				XO3(i + 2, 2)		\
+					XO3(i + 3, 3)	\
+		ST(i, 0)				\
+			ST(i + 1, 1)			\
+				ST(i + 2, 2)		\
+					ST(i + 3, 3)	\
+
+
+		PF0(0)
+				PF0(2)
+
+	" .align 32			;\n"
+	" 1:                            ;\n"
+
+		BLOCK(0)
+		BLOCK(4)
+		BLOCK(8)
+		BLOCK(12)
+
+	"       addq %[inc], %[p1]           ;\n"
+	"       addq %[inc], %[p2]           ;\n"
+	"       addq %[inc], %[p3]           ;\n"
+	"       addq %[inc], %[p4]           ;\n"
+	"	decl %[cnt] ; jnz 1b"
+	: [cnt] "+c" (lines),
+	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
+	: [inc] "r" (256UL)
+	: "memory" );
+
+	XMMS_RESTORE;
+}
+
+static void
+xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+	unsigned int lines = bytes >> 8;
+	xmm_store_t xmm_save[4];
+	unsigned long cr0;
+
+	XMMS_SAVE;
+
+	asm volatile(
+#undef BLOCK
+#define BLOCK(i) \
+		PF1(i)					\
+				PF1(i + 2)		\
+		LD(i, 0)				\
+			LD(i + 1, 1)			\
+				LD(i + 2, 2)		\
+					LD(i + 3, 3)	\
+		PF2(i)					\
+				PF2(i + 2)		\
+		XO1(i, 0)				\
+			XO1(i + 1, 1)			\
+				XO1(i + 2, 2)		\
+					XO1(i + 3, 3)	\
+		PF3(i)					\
+				PF3(i + 2)		\
+		XO2(i, 0)				\
+			XO2(i + 1, 1)			\
+				XO2(i + 2, 2)		\
+					XO2(i + 3, 3)	\
+		PF4(i)					\
+				PF4(i + 2)		\
+		PF0(i + 4)				\
+				PF0(i + 6)		\
+		XO3(i, 0)				\
+			XO3(i + 1, 1)			\
+				XO3(i + 2, 2)		\
+					XO3(i + 3, 3)	\
+		XO4(i, 0)				\
+			XO4(i + 1, 1)			\
+				XO4(i + 2, 2)		\
+					XO4(i + 3, 3)	\
+		ST(i, 0)				\
+			ST(i + 1, 1)			\
+				ST(i + 2, 2)		\
+					ST(i + 3, 3)	\
+
+
+		PF0(0)
+				PF0(2)
+
+	" .align 32			;\n"
+	" 1:                            ;\n"
+
+		BLOCK(0)
+		BLOCK(4)
+		BLOCK(8)
+		BLOCK(12)
+
+	"       addq %[inc], %[p1]           ;\n"
+	"       addq %[inc], %[p2]           ;\n"
+	"       addq %[inc], %[p3]           ;\n"
+	"       addq %[inc], %[p4]           ;\n"
+	"       addq %[inc], %[p5]           ;\n"
+	"	decl %[cnt] ; jnz 1b"
+	: [cnt] "+c" (lines),
+	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4),
+	  [p5] "+r" (p5)
+	: [inc] "r" (256UL)
+	: "memory");
+
+	XMMS_RESTORE;
+}
+
+static struct xor_block_template xor_block_sse = {
+	.name = "generic_sse",
+	.do_2 = xor_sse_2,
+	.do_3 = xor_sse_3,
+	.do_4 = xor_sse_4,
+	.do_5 = xor_sse_5,
+};
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES			\
+do {						\
+	xor_speed(&xor_block_sse);		\
+} while (0)
+
+/* We force the use of the SSE xor block because it can write around L2.
+   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)
+
+#endif /* _ASM_X86_XOR_64_H */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/xor.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/xor.h
@@ -0,0 +1,8 @@
+#ifdef CONFIG_KMEMCHECK
+/* kmemcheck doesn't handle MMX/SSE/SSE2 instructions */
+# include <asm-generic/xor.h>
+#elif defined(CONFIG_X86_32)
+# include "../../asm/xor_32.h"
+#else
+# include "xor_64.h"
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/swiotlb.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/swiotlb.h
@@ -0,0 +1,4 @@
+#include_next <asm/swiotlb.h>
+
+dma_addr_t swiotlb_map_single_phys(struct device *, phys_addr_t, size_t size,
+				   int dir);
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/hypercall.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/hypercall.h
@@ -0,0 +1,430 @@
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * 64-bit updates:
+ *   Benjamin Liu <benjamin.liu@intel.com>
+ *   Jun Nakajima <jun.nakajima@intel.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; 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 __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#ifndef __HYPERVISOR_H__
+# error "please don't include this file directly"
+#endif
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+# include <linux/string.h> /* memcpy() */
+#endif
+
+#ifdef CONFIG_XEN
+#define HYPERCALL_ASM_OPERAND "%c"
+#define HYPERCALL_LOCATION(op) (hypercall_page + (op) * 32)
+#define HYPERCALL_C_OPERAND(name) "i" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
+#else
+#define HYPERCALL_ASM_OPERAND "*%"
+#define HYPERCALL_LOCATION(op) (hypercall_stubs + (op) * 32)
+#define HYPERCALL_C_OPERAND(name) "g" (HYPERCALL_LOCATION(__HYPERVISOR_##name))
+#endif
+
+#define HYPERCALL_ARG(arg, n) \
+	register typeof((arg)+0) __arg##n asm(HYPERCALL_arg##n) = (arg)
+
+#define _hypercall0(type, name)					\
+({								\
+	type __res;						\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "1"		\
+		: "=a" (__res)					\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall1(type, name, arg)				\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(arg, 1);					\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "2"		\
+		: "=a" (__res), "+r" (__arg1)			\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall2(type, name, a1, a2)				\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(a1, 1);					\
+	HYPERCALL_ARG(a2, 2);					\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "3"		\
+		: "=a" (__res), "+r" (__arg1), "+r" (__arg2)	\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall3(type, name, a1, a2, a3)			\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(a1, 1);					\
+	HYPERCALL_ARG(a2, 2);					\
+	HYPERCALL_ARG(a3, 3);					\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "4"		\
+		: "=a" (__res), "+r" (__arg1),			\
+		  "+r" (__arg2), "+r" (__arg3)			\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4)			\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(a1, 1);					\
+	HYPERCALL_ARG(a2, 2);					\
+	HYPERCALL_ARG(a3, 3);					\
+	HYPERCALL_ARG(a4, 4);					\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "5"		\
+		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
+		  "+r" (__arg3), "+r" (__arg4)			\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5)		\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(a1, 1);					\
+	HYPERCALL_ARG(a2, 2);					\
+	HYPERCALL_ARG(a3, 3);					\
+	HYPERCALL_ARG(a4, 4);					\
+	HYPERCALL_ARG(a5, 5);					\
+	asm volatile (						\
+		"call " HYPERCALL_ASM_OPERAND "6"		\
+		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
+		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
+		: HYPERCALL_C_OPERAND(name)			\
+		: "memory" );					\
+	__res;							\
+})
+
+#define _hypercall(type, op, a1, a2, a3, a4, a5)		\
+({								\
+	type __res;						\
+	HYPERCALL_ARG(a1, 1);					\
+	HYPERCALL_ARG(a2, 2);					\
+	HYPERCALL_ARG(a3, 3);					\
+	HYPERCALL_ARG(a4, 4);					\
+	HYPERCALL_ARG(a5, 5);					\
+	asm volatile (						\
+		"call *%6"					\
+		: "=a" (__res), "+r" (__arg1), "+r" (__arg2),	\
+		  "+r" (__arg3), "+r" (__arg4), "+r" (__arg5)	\
+		: "g" (HYPERCALL_LOCATION(op))			\
+		: "memory" );					\
+	__res;							\
+})
+
+#ifdef CONFIG_X86_32
+# include "hypercall_32.h"
+#else
+# include "hypercall_64.h"
+#endif
+
+static inline int __must_check
+HYPERVISOR_set_trap_table(
+	const trap_info_t *table)
+{
+	return _hypercall1(int, set_trap_table, table);
+}
+
+static inline int __must_check
+HYPERVISOR_mmu_update(
+	mmu_update_t *req, unsigned int count, unsigned int *success_count,
+	domid_t domid)
+{
+	if (arch_use_lazy_mmu_mode())
+		return xen_multi_mmu_update(req, count, success_count, domid);
+	return _hypercall4(int, mmu_update, req, count, success_count, domid);
+}
+
+static inline int __must_check
+HYPERVISOR_mmuext_op(
+	struct mmuext_op *op, unsigned int count, unsigned int *success_count,
+	domid_t domid)
+{
+	if (arch_use_lazy_mmu_mode())
+		return xen_multi_mmuext_op(op, count, success_count, domid);
+	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
+}
+
+static inline int __must_check
+HYPERVISOR_set_gdt(
+	unsigned long *frame_list, unsigned int entries)
+{
+	return _hypercall2(int, set_gdt, frame_list, entries);
+}
+
+static inline int __must_check
+HYPERVISOR_stack_switch(
+	unsigned long ss, unsigned long esp)
+{
+	return _hypercall2(int, stack_switch, ss, esp);
+}
+
+static inline int
+HYPERVISOR_fpu_taskswitch(
+	int set)
+{
+	return _hypercall1(int, fpu_taskswitch, set);
+}
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+static inline int __must_check
+HYPERVISOR_sched_op_compat(
+	int cmd, unsigned long arg)
+{
+	return _hypercall2(int, sched_op_compat, cmd, arg);
+}
+#endif
+
+static inline int __must_check
+HYPERVISOR_sched_op(
+	int cmd, void *arg)
+{
+	return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline int __must_check
+HYPERVISOR_platform_op(
+	struct xen_platform_op *platform_op)
+{
+	platform_op->interface_version = XENPF_INTERFACE_VERSION;
+	return _hypercall1(int, platform_op, platform_op);
+}
+
+struct xen_mc;
+static inline int __must_check
+HYPERVISOR_mca(
+	struct xen_mc *mc_op)
+{
+	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
+	return _hypercall1(int, mca, mc_op);
+}
+
+static inline int __must_check
+HYPERVISOR_set_debugreg(
+	unsigned int reg, unsigned long value)
+{
+	return _hypercall2(int, set_debugreg, reg, value);
+}
+
+static inline unsigned long __must_check
+HYPERVISOR_get_debugreg(
+	unsigned int reg)
+{
+	return _hypercall1(unsigned long, get_debugreg, reg);
+}
+
+static inline int __must_check
+HYPERVISOR_memory_op(
+	unsigned int cmd, void *arg)
+{
+	if (arch_use_lazy_mmu_mode())
+		xen_multicall_flush(false);
+	return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int __must_check
+HYPERVISOR_multicall(
+	multicall_entry_t *call_list, unsigned int nr_calls)
+{
+	return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int __must_check
+HYPERVISOR_event_channel_op(
+	int cmd, void *arg)
+{
+	int rc = _hypercall2(int, event_channel_op, cmd, arg);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		struct evtchn_op op;
+		op.cmd = cmd;
+		memcpy(&op.u, arg, sizeof(op.u));
+		rc = _hypercall1(int, event_channel_op_compat, &op);
+		memcpy(arg, &op.u, sizeof(op.u));
+	}
+#endif
+
+	return rc;
+}
+
+static inline int __must_check
+HYPERVISOR_xen_version(
+	int cmd, void *arg)
+{
+	return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int __must_check
+HYPERVISOR_console_io(
+	int cmd, unsigned int count, char *str)
+{
+	return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int __must_check
+HYPERVISOR_physdev_op(
+	int cmd, void *arg)
+{
+	int rc = _hypercall2(int, physdev_op, cmd, arg);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (unlikely(rc == -ENOSYS)) {
+		struct physdev_op op;
+		op.cmd = cmd;
+		memcpy(&op.u, arg, sizeof(op.u));
+		rc = _hypercall1(int, physdev_op_compat, &op);
+		memcpy(arg, &op.u, sizeof(op.u));
+	}
+#endif
+
+	return rc;
+}
+
+static inline int __must_check
+HYPERVISOR_grant_table_op(
+	unsigned int cmd, void *uop, unsigned int count)
+{
+	bool fixup = false;
+	int rc;
+
+	if (arch_use_lazy_mmu_mode())
+		xen_multicall_flush(false);
+#ifdef GNTTABOP_map_grant_ref
+	if (cmd == GNTTABOP_map_grant_ref)
+#endif
+		fixup = gnttab_pre_map_adjust(cmd, uop, count);
+	rc = _hypercall3(int, grant_table_op, cmd, uop, count);
+	if (rc == 0 && fixup)
+		rc = gnttab_post_map_adjust(uop, count);
+	return rc;
+}
+
+static inline int __must_check
+HYPERVISOR_vm_assist(
+	unsigned int cmd, unsigned int type)
+{
+	return _hypercall2(int, vm_assist, cmd, type);
+}
+
+static inline int __must_check
+HYPERVISOR_vcpu_op(
+	int cmd, unsigned int vcpuid, void *extra_args)
+{
+	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+}
+
+static inline int __must_check
+HYPERVISOR_suspend(
+	unsigned long srec)
+{
+	struct sched_shutdown sched_shutdown = {
+		.reason = SHUTDOWN_suspend
+	};
+
+	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
+			     &sched_shutdown, srec);
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+	if (rc == -ENOSYS)
+		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
+				 SHUTDOWN_suspend, srec);
+#endif
+
+	return rc;
+}
+
+#if CONFIG_XEN_COMPAT <= 0x030002
+static inline int
+HYPERVISOR_nmi_op(
+	unsigned long op, void *arg)
+{
+	return _hypercall2(int, nmi_op, op, arg);
+}
+#endif
+
+#ifndef CONFIG_XEN
+static inline unsigned long __must_check
+HYPERVISOR_hvm_op(
+    int op, void *arg)
+{
+    return _hypercall2(unsigned long, hvm_op, op, arg);
+}
+#endif
+
+static inline int __must_check
+HYPERVISOR_callback_op(
+	int cmd, const void *arg)
+{
+	return _hypercall2(int, callback_op, cmd, arg);
+}
+
+static inline int __must_check
+HYPERVISOR_xenoprof_op(
+	int op, void *arg)
+{
+	return _hypercall2(int, xenoprof_op, op, arg);
+}
+
+static inline int __must_check
+HYPERVISOR_kexec_op(
+	unsigned long op, void *args)
+{
+	return _hypercall2(int, kexec_op, op, args);
+}
+
+static inline int __must_check
+HYPERVISOR_tmem_op(
+	struct tmem_op *op)
+{
+	return _hypercall1(int, tmem_op, op);
+}
+
+#endif /* __HYPERCALL_H__ */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/irqflags.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/irqflags.h
@@ -0,0 +1,223 @@
+#ifndef _X86_IRQFLAGS_H_
+#define _X86_IRQFLAGS_H_
+
+#include <asm/smp-processor-id.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operations must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+#define xen_save_fl(void) vcpu_info_read(evtchn_upcall_mask)
+
+#define xen_restore_fl(f)					\
+do {								\
+	vcpu_info_t *_vcpu;					\
+	barrier();						\
+	_vcpu = current_vcpu_info();				\
+	if ((_vcpu->evtchn_upcall_mask = (f)) == 0) {		\
+		barrier(); /* unmask then check (avoid races) */\
+		if (unlikely(_vcpu->evtchn_upcall_pending))	\
+			force_evtchn_callback();		\
+	}							\
+} while (0)
+
+#define xen_irq_disable()					\
+do {								\
+	vcpu_info_write(evtchn_upcall_mask, 1);			\
+	barrier();						\
+} while (0)
+
+#define xen_irq_enable()					\
+do {								\
+	vcpu_info_t *_vcpu;					\
+	barrier();						\
+	_vcpu = current_vcpu_info();				\
+	_vcpu->evtchn_upcall_mask = 0;				\
+	barrier(); /* unmask then check (avoid races) */	\
+	if (unlikely(_vcpu->evtchn_upcall_pending))		\
+		force_evtchn_callback();			\
+} while (0)
+
+void xen_safe_halt(void);
+
+void xen_halt(void);
+
+#define __raw_local_save_flags() xen_save_fl()
+
+#define raw_local_irq_restore(flags) xen_restore_fl(flags)
+
+#define raw_local_irq_disable()	xen_irq_disable()
+
+#define raw_local_irq_enable() xen_irq_enable()
+
+/*
+ * Used in the idle loop; sti takes one instruction cycle
+ * to complete:
+ */
+static inline void raw_safe_halt(void)
+{
+	xen_safe_halt();
+}
+
+/*
+ * Used when interrupts are already enabled or to
+ * shutdown the processor:
+ */
+static inline void halt(void)
+{
+	xen_halt();
+}
+
+/*
+ * For spinlocks, etc:
+ */
+#define __raw_local_irq_save()						\
+({									\
+	unsigned long flags = __raw_local_save_flags();			\
+									\
+	raw_local_irq_disable();					\
+									\
+	flags;								\
+})
+#else
+
+/* Offsets into shared_info_t. */
+#define evtchn_upcall_pending		/* 0 */
+#define evtchn_upcall_mask		1
+
+#ifdef CONFIG_X86_64
+# define __REG_si %rsi
+# define __CPU_num PER_CPU_VAR(cpu_number)
+#else
+# define __REG_si %esi
+# define __CPU_num TI_cpu(%ebp)
+#endif
+
+#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT
+
+#define GET_VCPU_INFO		PER_CPU(vcpu_info, __REG_si)
+#define __DISABLE_INTERRUPTS	movb $1,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
+#define __ENABLE_INTERRUPTS	movb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask)
+#define __TEST_PENDING		cmpb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_pending+0)
+#define DISABLE_INTERRUPTS(clb)	__DISABLE_INTERRUPTS
+#define ENABLE_INTERRUPTS(clb)	__ENABLE_INTERRUPTS
+
+#define __SIZEOF_DISABLE_INTERRUPTS 8
+#define __SIZEOF_TEST_PENDING	8
+
+#else /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
+
+#define sizeof_vcpu_shift	6
+
+#ifdef CONFIG_SMP
+#define GET_VCPU_INFO		movl __CPU_num,%esi			; \
+				shl $sizeof_vcpu_shift,%esi		; \
+				add HYPERVISOR_shared_info,__REG_si
+#else
+#define GET_VCPU_INFO		mov HYPERVISOR_shared_info,__REG_si
+#endif
+
+#define __DISABLE_INTERRUPTS	movb $1,evtchn_upcall_mask(__REG_si)
+#define __ENABLE_INTERRUPTS	movb $0,evtchn_upcall_mask(__REG_si)
+#define __TEST_PENDING		testb $0xFF,evtchn_upcall_pending(__REG_si)
+#define DISABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
+				__DISABLE_INTERRUPTS
+#define ENABLE_INTERRUPTS(clb)	GET_VCPU_INFO				; \
+				__ENABLE_INTERRUPTS
+
+#define __SIZEOF_DISABLE_INTERRUPTS 4
+#define __SIZEOF_TEST_PENDING	3
+
+#endif /* CONFIG_XEN_VCPU_INFO_PLACEMENT */
+
+#ifndef CONFIG_X86_64
+#define INTERRUPT_RETURN		iret
+#define ENABLE_INTERRUPTS_SYSEXIT					  \
+	movb $0,evtchn_upcall_mask(%esi) /* __ENABLE_INTERRUPTS */	; \
+sysexit_scrit:	/**** START OF SYSEXIT CRITICAL REGION ****/		; \
+	cmpb $0,evtchn_upcall_pending(%esi) /* __TEST_PENDING */	; \
+	jnz  14f	/* process more events if necessary... */	; \
+	movl PT_ESI(%esp), %esi						; \
+	sysexit								; \
+14:	movb $1,evtchn_upcall_mask(%esi) /* __DISABLE_INTERRUPTS */	; \
+	TRACE_IRQS_OFF							; \
+sysexit_ecrit:	/**** END OF SYSEXIT CRITICAL REGION ****/		; \
+	mov  $__KERNEL_PERCPU, %ecx					; \
+	push %esp							; \
+	mov  %ecx, %fs							; \
+	SET_KERNEL_GS %ecx						; \
+	call evtchn_do_upcall						; \
+	add  $4,%esp							; \
+	jmp  ret_from_intr
+#endif
+
+
+#endif /* __ASSEMBLY__ */
+
+#ifndef __ASSEMBLY__
+#define raw_local_save_flags(flags)				\
+	do { (flags) = __raw_local_save_flags(); } while (0)
+
+#define raw_local_irq_save(flags)				\
+	do { (flags) = __raw_local_irq_save(); } while (0)
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags != 0);
+}
+
+#define raw_irqs_disabled()						\
+({									\
+	unsigned long flags = __raw_local_save_flags();			\
+									\
+	raw_irqs_disabled_flags(flags);					\
+})
+
+#else
+
+#ifdef CONFIG_X86_64
+#define ARCH_LOCKDEP_SYS_EXIT		call lockdep_sys_exit_thunk
+#define ARCH_LOCKDEP_SYS_EXIT_IRQ	\
+	TRACE_IRQS_ON; \
+	ENABLE_INTERRUPTS(CLBR_NONE); \
+	SAVE_REST; \
+	LOCKDEP_SYS_EXIT; \
+	RESTORE_REST; \
+	__DISABLE_INTERRUPTS; \
+	TRACE_IRQS_OFF;
+
+#else
+#define ARCH_LOCKDEP_SYS_EXIT			\
+	pushl %eax;				\
+	pushl %ecx;				\
+	pushl %edx;				\
+	call lockdep_sys_exit;			\
+	popl %edx;				\
+	popl %ecx;				\
+	popl %eax;
+
+#define ARCH_LOCKDEP_SYS_EXIT_IRQ
+#endif
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+#  define TRACE_IRQS_ON		call trace_hardirqs_on_thunk;
+#  define TRACE_IRQS_OFF	call trace_hardirqs_off_thunk;
+#else
+#  define TRACE_IRQS_ON
+#  define TRACE_IRQS_OFF
+#endif
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#  define LOCKDEP_SYS_EXIT	ARCH_LOCKDEP_SYS_EXIT
+#  define LOCKDEP_SYS_EXIT_IRQ	ARCH_LOCKDEP_SYS_EXIT_IRQ
+# else
+#  define LOCKDEP_SYS_EXIT
+#  define LOCKDEP_SYS_EXIT_IRQ
+# endif
+
+#endif /* __ASSEMBLY__ */
+#endif
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/xenoprof.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/xenoprof.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ * asm-i386/mach-xen/asm/xenoprof.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 __ASM_XENOPROF_H__
+#define __ASM_XENOPROF_H__
+#ifdef CONFIG_XEN
+
+struct super_block;
+struct dentry;
+int xenoprof_create_files(struct super_block * sb, struct dentry * root);
+#define HAVE_XENOPROF_CREATE_FILES
+
+struct xenoprof_init;
+void xenoprof_arch_init_counter(struct xenoprof_init *init);
+void xenoprof_arch_counter(void);
+void xenoprof_arch_start(void);
+void xenoprof_arch_stop(void);
+
+struct xenoprof_arch_shared_buffer {
+	/* nothing */
+};
+struct xenoprof_shared_buffer;
+void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf);
+struct xenoprof_get_buffer;
+int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf);
+struct xenoprof_passive;
+int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf);
+
+#endif /* CONFIG_XEN */
+#endif /* __ASM_XENOPROF_H__ */
--- linux-ec2-2.6.32.orig/arch/x86/include/mach-xen/asm/smp-processor-id.h
+++ linux-ec2-2.6.32/arch/x86/include/mach-xen/asm/smp-processor-id.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_X86_SMP_PROCESSOR_ID_H
+#define _ASM_X86_SMP_PROCESSOR_ID_H
+
+#if defined(CONFIG_SMP) && !defined(__ASSEMBLY__)
+
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU(int, cpu_number);
+
+/*
+ * This function is needed by all SMP systems. It must _always_ be valid
+ * from the initial startup. We map APIC_BASE very early in page_setup(),
+ * so this is correct in the x86 case.
+ */
+#define raw_smp_processor_id() percpu_read(cpu_number)
+#define safe_smp_processor_id() smp_processor_id()
+
+#ifdef CONFIG_X86_64_SMP
+#define stack_smp_processor_id()					\
+({									\
+	struct thread_info *ti;						\
+	__asm__("andq %%rsp,%0; ":"=r" (ti) : "0" (CURRENT_MASK));	\
+	ti->cpu;							\
+})
+#endif
+
+#ifdef CONFIG_DEBUG_PREEMPT
+extern unsigned int debug_smp_processor_id(void);
+# define smp_processor_id() debug_smp_processor_id()
+#else
+# define smp_processor_id() raw_smp_processor_id()
+#endif
+
+#endif /* SMP && !__ASSEMBLY__ */
+
+#endif /* _ASM_X86_SMP_PROCESSOR_ID_H */
--- linux-ec2-2.6.32.orig/arch/h8300/kernel/syscalls.S
+++ linux-ec2-2.6.32/arch/h8300/kernel/syscalls.S
@@ -206,7 +206,7 @@
 	.long SYMBOL_NAME(sys_ni_syscall)	/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
 	.long SYMBOL_NAME(sys_getrlimit)
-	.long SYMBOL_NAME(sys_mmap2)
+	.long SYMBOL_NAME(sys_mmap_pgoff)
 	.long SYMBOL_NAME(sys_truncate64)
 	.long SYMBOL_NAME(sys_ftruncate64)
 	.long SYMBOL_NAME(sys_stat64)		/* 195 */
--- linux-ec2-2.6.32.orig/arch/h8300/kernel/sys_h8300.c
+++ linux-ec2-2.6.32/arch/h8300/kernel/sys_h8300.c
@@ -26,39 +26,6 @@
 #include <asm/traps.h>
 #include <asm/unistd.h>
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
@@ -87,58 +54,12 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+			       a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
 
-#if 0 /* DAVIDM - do we want this */
-struct mmap_arg_struct64 {
-	__u32 addr;
-	__u32 len;
-	__u32 prot;
-	__u32 flags;
-	__u64 offset; /* 64 bits */
-	__u32 fd;
-};
-
-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
-{
-	int error = -EFAULT;
-	struct file * file = NULL;
-	struct mmap_arg_struct64 a;
-	unsigned long pgoff;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-
-	if ((long)a.offset & ~PAGE_MASK)
-		return -EINVAL;
-
-	pgoff = a.offset >> PAGE_SHIFT;
-	if ((a.offset >> PAGE_SHIFT) != pgoff)
-		return -EINVAL;
-
-	if (!(a.flags & MAP_ANONYMOUS)) {
-		error = -EBADF;
-		file = fget(a.fd);
-		if (!file)
-			goto out;
-	}
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-#endif
-
 struct sel_arg_struct {
 	unsigned long n;
 	fd_set *inp, *outp, *exp;
--- linux-ec2-2.6.32.orig/arch/arm/Kconfig
+++ linux-ec2-2.6.32/arch/arm/Kconfig
@@ -887,6 +887,18 @@
 	  ACTLR register. Note that setting specific bits in the ACTLR register
 	  may not be available in non-secure mode.
 
+config ARM_ERRATA_720789
+	bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 720789 Cortex-A9 (prior to
+	  r2p0) erratum. A faulty ASID can be sent to the other CPUs for the
+	  broadcasted CP15 TLB maintenance operations TLBIASIDIS and TLBIMVAIS.
+	  As a consequence of this erratum, some TLB entries which should be
+	  invalidated are not, resulting in an incoherency in the system page
+	  tables. The workaround changes the TLB flushing routines to invalidate
+	  entries regardless of the ASID.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1508,6 +1520,8 @@
 
 source "drivers/Kconfig"
 
+source "ubuntu/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/arm/Kconfig.debug"
--- linux-ec2-2.6.32.orig/arch/arm/kernel/sys_arm.c
+++ linux-ec2-2.6.32/arch/arm/kernel/sys_arm.c
@@ -28,41 +28,6 @@
 #include <linux/ipc.h>
 #include <linux/uaccess.h>
 
-extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
-			       unsigned long new_len, unsigned long flags,
-			       unsigned long new_addr);
-
-/* common code for old and new mmaps */
-inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	int error = -EINVAL;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS)
-		goto out;
-
-	error = -EBADF;
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 struct mmap_arg_struct {
 	unsigned long addr;
 	unsigned long len;
@@ -84,29 +49,11 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
 
-asmlinkage unsigned long
-sys_arm_mremap(unsigned long addr, unsigned long old_len,
-	       unsigned long new_len, unsigned long flags,
-	       unsigned long new_addr)
-{
-	unsigned long ret = -EINVAL;
-
-	if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS)
-		goto out;
-
-	down_write(&current->mm->mmap_sem);
-	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
-	up_write(&current->mm->mmap_sem);
-
-out:
-	return ret;
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls.
--- linux-ec2-2.6.32.orig/arch/arm/kernel/signal.c
+++ linux-ec2-2.6.32/arch/arm/kernel/signal.c
@@ -389,7 +389,9 @@
 	unsigned long handler = (unsigned long)ka->sa.sa_handler;
 	unsigned long retcode;
 	int thumb = 0;
-	unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;
+	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
+
+	cpsr |= PSR_ENDSTATE;
 
 	/*
 	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
--- linux-ec2-2.6.32.orig/arch/arm/kernel/kprobes-decode.c
+++ linux-ec2-2.6.32/arch/arm/kernel/kprobes-decode.c
@@ -583,13 +583,14 @@
 {
 	insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
+	long ppc = (long)p->addr + 8;
 	union reg_pair fnr;
 	int rd = (insn >> 12) & 0xf;
 	int rn = (insn >> 16) & 0xf;
 	int rm = insn & 0xf;
 	long rdv;
-	long rnv  = regs->uregs[rn];
-	long rmv  = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
+	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
 	long cpsr = regs->ARM_cpsr;
 
 	fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
--- linux-ec2-2.6.32.orig/arch/arm/kernel/calls.S
+++ linux-ec2-2.6.32/arch/arm/kernel/calls.S
@@ -172,7 +172,7 @@
 /* 160 */	CALL(sys_sched_get_priority_min)
 		CALL(sys_sched_rr_get_interval)
 		CALL(sys_nanosleep)
-		CALL(sys_arm_mremap)
+		CALL(sys_mremap)
 		CALL(sys_setresuid16)
 /* 165 */	CALL(sys_getresuid16)
 		CALL(sys_ni_syscall)		/* vm86 */
--- linux-ec2-2.6.32.orig/arch/arm/kernel/sys_oabi-compat.c
+++ linux-ec2-2.6.32/arch/arm/kernel/sys_oabi-compat.c
@@ -311,7 +311,7 @@
 	long err;
 	int i;
 
-	if (nsops < 1)
+	if (nsops < 1 || nsops > SEMOPM)
 		return -EINVAL;
 	sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
 	if (!sops)
--- linux-ec2-2.6.32.orig/arch/arm/kernel/entry-common.S
+++ linux-ec2-2.6.32/arch/arm/kernel/entry-common.S
@@ -382,11 +382,13 @@
 
 sys_sigreturn_wrapper:
 		add	r0, sp, #S_OFF
+		mov	why, #0		@ prevent syscall restart handling
 		b	sys_sigreturn
 ENDPROC(sys_sigreturn_wrapper)
 
 sys_rt_sigreturn_wrapper:
 		add	r0, sp, #S_OFF
+		mov	why, #0		@ prevent syscall restart handling
 		b	sys_rt_sigreturn
 ENDPROC(sys_rt_sigreturn_wrapper)
 
@@ -416,12 +418,12 @@
 		tst	r5, #PGOFF_MASK
 		moveq	r5, r5, lsr #PAGE_SHIFT - 12
 		streq	r5, [sp, #4]
-		beq	do_mmap2
+		beq	sys_mmap_pgoff
 		mov	r0, #-EINVAL
 		mov	pc, lr
 #else
 		str	r5, [sp, #4]
-		b	do_mmap2
+		b	sys_mmap_pgoff
 #endif
 ENDPROC(sys_mmap2)
 
--- linux-ec2-2.6.32.orig/arch/arm/mach-davinci/dm646x.c
+++ linux-ec2-2.6.32/arch/arm/mach-davinci/dm646x.c
@@ -789,7 +789,14 @@
 		.part_no	= 0xb770,
 		.manufacturer	= 0x017,
 		.cpu_id		= DAVINCI_CPU_ID_DM6467,
-		.name		= "dm6467",
+		.name		= "dm6467_rev1.x",
+	},
+	{
+		.variant	= 0x1,
+		.part_no	= 0xb770,
+		.manufacturer	= 0x017,
+		.cpu_id		= DAVINCI_CPU_ID_DM6467,
+		.name		= "dm6467_rev3.x",
 	},
 };
 
--- linux-ec2-2.6.32.orig/arch/arm/lib/findbit.S
+++ linux-ec2-2.6.32/arch/arm/lib/findbit.S
@@ -174,8 +174,8 @@
  */
 .L_found:
 #if __LINUX_ARM_ARCH__ >= 5
-		rsb	r1, r3, #0
-		and	r3, r3, r1
+		rsb	r0, r3, #0
+		and	r3, r3, r0
 		clz	r3, r3
 		rsb	r3, r3, #31
 		add	r0, r2, r3
@@ -190,5 +190,7 @@
 		addeq	r2, r2, #1
 		mov	r0, r2
 #endif
+		cmp	r1, r0			@ Clamp to maxbit
+		movlo	r0, r1
 		mov	pc, lr
 
--- linux-ec2-2.6.32.orig/arch/arm/boot/compressed/vmlinux.lds.in
+++ linux-ec2-2.6.32/arch/arm/boot/compressed/vmlinux.lds.in
@@ -36,6 +36,9 @@
 
   _etext = .;
 
+  /* Assume size of decompressed image is 4x the compressed image */
+  _image_size = (_etext - _text) * 4;
+
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
--- linux-ec2-2.6.32.orig/arch/arm/boot/compressed/head.S
+++ linux-ec2-2.6.32/arch/arm/boot/compressed/head.S
@@ -162,9 +162,9 @@
 
 		.text
 		adr	r0, LC0
- ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip, sp}	)
- THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip}	)
- THUMB(		ldr	sp, [r0, #28]				)
+ ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
+ THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip}	)
+ THUMB(		ldr	sp, [r0, #32]				)
 		subs	r0, r0, r1		@ calculate the delta offset
 
 						@ if delta is zero, we are
@@ -174,12 +174,13 @@
 		/*
 		 * We're running at a different address.  We need to fix
 		 * up various pointers:
-		 *   r5 - zImage base address
-		 *   r6 - GOT start
+		 *   r5 - zImage base address (_start)
+		 *   r6 - size of decompressed image
+		 *   r11 - GOT start
 		 *   ip - GOT end
 		 */
 		add	r5, r5, r0
-		add	r6, r6, r0
+		add	r11, r11, r0
 		add	ip, ip, r0
 
 #ifndef CONFIG_ZBOOT_ROM
@@ -197,10 +198,10 @@
 		/*
 		 * Relocate all entries in the GOT table.
 		 */
-1:		ldr	r1, [r6, #0]		@ relocate entries in the GOT
+1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		add	r1, r1, r0		@ table.  This fixes up the
-		str	r1, [r6], #4		@ C references.
-		cmp	r6, ip
+		str	r1, [r11], #4		@ C references.
+		cmp	r11, ip
 		blo	1b
 #else
 
@@ -208,12 +209,12 @@
 		 * Relocate entries in the GOT table.  We only relocate
 		 * the entries that are outside the (relocated) BSS region.
 		 */
-1:		ldr	r1, [r6, #0]		@ relocate entries in the GOT
+1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		cmp	r1, r2			@ entry < bss_start ||
 		cmphs	r3, r1			@ _end < entry
 		addlo	r1, r1, r0		@ table.  This fixes up the
-		str	r1, [r6], #4		@ C references.
-		cmp	r6, ip
+		str	r1, [r11], #4		@ C references.
+		cmp	r11, ip
 		blo	1b
 #endif
 
@@ -239,6 +240,7 @@
  * Check to see if we will overwrite ourselves.
  *   r4 = final kernel address
  *   r5 = start of this image
+ *   r6 = size of decompressed image
  *   r2 = end of malloc space (and therefore this image)
  * We basically want:
  *   r4 >= r2 -> OK
@@ -246,8 +248,7 @@
  */
 		cmp	r4, r2
 		bhs	wont_overwrite
-		sub	r3, sp, r5		@ > compressed kernel size
-		add	r0, r4, r3, lsl #2	@ allow for 4x expansion
+		add	r0, r4, r6
 		cmp	r0, r5
 		bls	wont_overwrite
 
@@ -263,7 +264,6 @@
  * r1-r3  = unused
  * r4     = kernel execution address
  * r5     = decompressed kernel start
- * r6     = processor ID
  * r7     = architecture ID
  * r8     = atags pointer
  * r9-r12,r14 = corrupted
@@ -304,7 +304,8 @@
 		.word	_end			@ r3
 		.word	zreladdr		@ r4
 		.word	_start			@ r5
-		.word	_got_start		@ r6
+		.word	_image_size		@ r6
+		.word	_got_start		@ r11
 		.word	_got_end		@ ip
 		.word	user_stack+4096		@ sp
 LC1:		.word	reloc_end - reloc_start
@@ -328,7 +329,6 @@
  *
  * On entry,
  *  r4 = kernel execution address
- *  r6 = processor ID
  *  r7 = architecture number
  *  r8 = atags pointer
  *  r9 = run-time address of "start"  (???)
@@ -534,7 +534,6 @@
  * r1-r3  = unused
  * r4     = kernel execution address
  * r5     = decompressed kernel start
- * r6     = processor ID
  * r7     = architecture ID
  * r8     = atags pointer
  * r9-r12,r14 = corrupted
@@ -573,19 +572,19 @@
  *  r1  = corrupted
  *  r2  = corrupted
  *  r3  = block offset
- *  r6  = corrupted
+ *  r9  = corrupted
  *  r12 = corrupted
  */
 
 call_cache_fn:	adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
-		mrc	p15, 0, r6, c0, c0	@ get processor ID
+		mrc	p15, 0, r9, c0, c0	@ get processor ID
 #else
-		ldr	r6, =CONFIG_PROCESSOR_ID
+		ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 1:		ldr	r1, [r12, #0]		@ get value
 		ldr	r2, [r12, #4]		@ get mask
-		eor	r1, r1, r6		@ (real ^ match)
+		eor	r1, r1, r9		@ (real ^ match)
 		tst	r1, r2			@       & mask
  ARM(		addeq	pc, r12, r3		) @ call cache function
  THUMB(		addeq	r12, r3			)
@@ -764,8 +763,7 @@
  * Turn off the Cache and MMU.  ARMv3 does not support
  * reading the control register, but ARMv4 does.
  *
- * On entry,  r6 = processor ID
- * On exit,   r0, r1, r2, r3, r12 corrupted
+ * On exit, r0, r1, r2, r3, r9, r12 corrupted
  * This routine must preserve: r4, r6, r7
  */
 		.align	5
@@ -838,10 +836,8 @@
 /*
  * Clean and flush the cache to maintain consistency.
  *
- * On entry,
- *  r6 = processor ID
  * On exit,
- *  r1, r2, r3, r11, r12 corrupted
+ *  r1, r2, r3, r9, r11, r12 corrupted
  * This routine must preserve:
  *  r0, r4, r5, r6, r7
  */
@@ -953,7 +949,7 @@
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
 		mov	r11, #32		@ default: 32 byte line size
 		mrc	p15, 0, r3, c0, c0, 1	@ read cache type
-		teq	r3, r6			@ cache ID register present?
+		teq	r3, r9			@ cache ID register present?
 		beq	no_cache_id
 		mov	r1, r3, lsr #18
 		and	r1, r1, #7
--- linux-ec2-2.6.32.orig/arch/arm/mach-pxa/em-x270.c
+++ linux-ec2-2.6.32/arch/arm/mach-pxa/em-x270.c
@@ -497,16 +497,15 @@
 		goto err_free_vbus_gpio;
 
 	/* USB Hub power-on and reset */
-	gpio_direction_output(usb_hub_reset, 0);
+	gpio_direction_output(usb_hub_reset, 1);
+	gpio_direction_output(GPIO9_USB_VBUS_EN, 0);
 	regulator_enable(em_x270_usb_ldo);
-	gpio_set_value(usb_hub_reset, 1);
 	gpio_set_value(usb_hub_reset, 0);
+	gpio_set_value(usb_hub_reset, 1);
 	regulator_disable(em_x270_usb_ldo);
 	regulator_enable(em_x270_usb_ldo);
-	gpio_set_value(usb_hub_reset, 1);
-
-	/* enable VBUS */
-	gpio_direction_output(GPIO9_USB_VBUS_EN, 1);
+	gpio_set_value(usb_hub_reset, 0);
+	gpio_set_value(GPIO9_USB_VBUS_EN, 1);
 
 	return 0;
 
--- linux-ec2-2.6.32.orig/arch/arm/mach-pxa/include/mach/colibri.h
+++ linux-ec2-2.6.32/arch/arm/mach-pxa/include/mach/colibri.h
@@ -2,6 +2,7 @@
 #define _COLIBRI_H_
 
 #include <net/ax88796.h>
+#include <mach/mfp.h>
 
 /*
  * common settings for all modules
--- linux-ec2-2.6.32.orig/arch/arm/common/sa1111.c
+++ linux-ec2-2.6.32/arch/arm/common/sa1111.c
@@ -887,8 +887,6 @@
 	if (!save)
 		return 0;
 
-	spin_lock_irqsave(&sachip->lock, flags);
-
 	/*
 	 * Ensure that the SA1111 is still here.
 	 * FIXME: shouldn't do this here.
@@ -905,6 +903,13 @@
 	 * First of all, wake up the chip.
 	 */
 	sa1111_wake(sachip);
+
+	/*
+	 * Only lock for write ops. Also, sa1111_wake must be called with
+	 * released spinlock!
+	 */
+	spin_lock_irqsave(&sachip->lock, flags);
+
 	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
 	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
 
--- linux-ec2-2.6.32.orig/arch/arm/mach-realview/Kconfig
+++ linux-ec2-2.6.32/arch/arm/mach-realview/Kconfig
@@ -18,6 +18,7 @@
 	bool "Support ARM11MPCore tile"
 	depends on MACH_REALVIEW_EB
 	select CPU_V6
+	select ARCH_HAS_BARRIERS if SMP
 	help
 	  Enable support for the ARM11MPCore tile on the Realview platform.
 
@@ -35,6 +36,7 @@
 	select CPU_V6
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
+	select ARCH_HAS_BARRIERS if SMP
 	help
 	  Include support for the ARM(R) RealView MPCore Platform Baseboard.
 	  PB11MPCore is a platform with an on-board ARM11MPCore and has
--- linux-ec2-2.6.32.orig/arch/arm/mach-realview/include/mach/barriers.h
+++ linux-ec2-2.6.32/arch/arm/mach-realview/include/mach/barriers.h
@@ -0,0 +1,8 @@
+/*
+ * Barriers redefined for RealView ARM11MPCore platforms with L220 cache
+ * controller to work around hardware errata causing the outer_sync()
+ * operation to deadlock the system.
+ */
+#define mb()		dsb()
+#define rmb()		dmb()
+#define wmb()		mb()
--- linux-ec2-2.6.32.orig/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ linux-ec2-2.6.32/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -37,6 +37,10 @@
 #define SYSTEM_REV_S_USES_VAUX3 0x8
 
 static int board_keymap[] = {
+	/*
+	 * Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
+	 * connected to the ground" matrix state.
+	 */
 	KEY(0, 0, KEY_Q),
 	KEY(0, 1, KEY_O),
 	KEY(0, 2, KEY_P),
@@ -44,6 +48,7 @@
 	KEY(0, 4, KEY_BACKSPACE),
 	KEY(0, 6, KEY_A),
 	KEY(0, 7, KEY_S),
+
 	KEY(1, 0, KEY_W),
 	KEY(1, 1, KEY_D),
 	KEY(1, 2, KEY_F),
@@ -52,6 +57,7 @@
 	KEY(1, 5, KEY_J),
 	KEY(1, 6, KEY_K),
 	KEY(1, 7, KEY_L),
+
 	KEY(2, 0, KEY_E),
 	KEY(2, 1, KEY_DOT),
 	KEY(2, 2, KEY_UP),
@@ -59,6 +65,8 @@
 	KEY(2, 5, KEY_Z),
 	KEY(2, 6, KEY_X),
 	KEY(2, 7, KEY_C),
+	KEY(2, 8, KEY_F9),
+
 	KEY(3, 0, KEY_R),
 	KEY(3, 1, KEY_V),
 	KEY(3, 2, KEY_B),
@@ -67,20 +75,23 @@
 	KEY(3, 5, KEY_SPACE),
 	KEY(3, 6, KEY_SPACE),
 	KEY(3, 7, KEY_LEFT),
+
 	KEY(4, 0, KEY_T),
 	KEY(4, 1, KEY_DOWN),
 	KEY(4, 2, KEY_RIGHT),
 	KEY(4, 4, KEY_LEFTCTRL),
 	KEY(4, 5, KEY_RIGHTALT),
 	KEY(4, 6, KEY_LEFTSHIFT),
+	KEY(4, 8, KEY_F10),
+
 	KEY(5, 0, KEY_Y),
+	KEY(5, 8, KEY_F11),
+
 	KEY(6, 0, KEY_U),
+
 	KEY(7, 0, KEY_I),
 	KEY(7, 1, KEY_F7),
 	KEY(7, 2, KEY_F8),
-	KEY(0xff, 2, KEY_F9),
-	KEY(0xff, 4, KEY_F10),
-	KEY(0xff, 5, KEY_F11),
 };
 
 static struct matrix_keymap_data board_map_data = {
--- linux-ec2-2.6.32.orig/arch/arm/plat-mxc/gpio.c
+++ linux-ec2-2.6.32/arch/arm/plat-mxc/gpio.c
@@ -223,13 +223,16 @@
 	struct mxc_gpio_port *port =
 		container_of(chip, struct mxc_gpio_port, chip);
 	u32 l;
+	unsigned long flags;
 
+	spin_lock_irqsave(&port->lock, flags);
 	l = __raw_readl(port->base + GPIO_GDIR);
 	if (dir)
 		l |= 1 << offset;
 	else
 		l &= ~(1 << offset);
 	__raw_writel(l, port->base + GPIO_GDIR);
+	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -238,9 +241,12 @@
 		container_of(chip, struct mxc_gpio_port, chip);
 	void __iomem *reg = port->base + GPIO_DR;
 	u32 l;
+	unsigned long flags;
 
+	spin_lock_irqsave(&port->lock, flags);
 	l = (__raw_readl(reg) & (~(1 << offset))) | (value << offset);
 	__raw_writel(l, reg);
+	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -294,6 +300,8 @@
 		port[i].chip.base = i * 32;
 		port[i].chip.ngpio = 32;
 
+		spin_lock_init(&port[i].lock);
+
 		/* its a serious configuration bug when it fails */
 		BUG_ON( gpiochip_add(&port[i].chip) < 0 );
 
--- linux-ec2-2.6.32.orig/arch/arm/plat-mxc/include/mach/gpio.h
+++ linux-ec2-2.6.32/arch/arm/plat-mxc/include/mach/gpio.h
@@ -19,6 +19,7 @@
 #ifndef __ASM_ARCH_MXC_GPIO_H__
 #define __ASM_ARCH_MXC_GPIO_H__
 
+#include <linux/spinlock.h>
 #include <mach/hardware.h>
 #include <asm-generic/gpio.h>
 
@@ -36,6 +37,7 @@
 	int virtual_irq_start;
 	struct gpio_chip chip;
 	u32 both_edges;
+	spinlock_t lock;
 };
 
 int mxc_gpio_init(struct mxc_gpio_port*, int);
--- linux-ec2-2.6.32.orig/arch/arm/mm/copypage-v4wb.c
+++ linux-ec2-2.6.32/arch/arm/mm/copypage-v4wb.c
@@ -27,7 +27,7 @@
 {
 	asm("\
 	stmfd	sp!, {r4, lr}			@ 2\n\
-	mov	r2, %0				@ 1\n\
+	mov	r2, %2				@ 1\n\
 	ldmia	r1!, {r3, r4, ip, lr}		@ 4\n\
 1:	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line\n\
 	stmia	r0!, {r3, r4, ip, lr}		@ 4\n\
@@ -44,7 +44,7 @@
 	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB\n\
 	ldmfd	 sp!, {r4, pc}			@ 3"
 	:
-	: "I" (PAGE_SIZE / 64));
+	: "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
 }
 
 void v4wb_copy_user_highpage(struct page *to, struct page *from,
--- linux-ec2-2.6.32.orig/arch/arm/mm/copypage-v4wt.c
+++ linux-ec2-2.6.32/arch/arm/mm/copypage-v4wt.c
@@ -25,7 +25,7 @@
 {
 	asm("\
 	stmfd	sp!, {r4, lr}			@ 2\n\
-	mov	r2, %0				@ 1\n\
+	mov	r2, %2				@ 1\n\
 	ldmia	r1!, {r3, r4, ip, lr}		@ 4\n\
 1:	stmia	r0!, {r3, r4, ip, lr}		@ 4\n\
 	ldmia	r1!, {r3, r4, ip, lr}		@ 4+1\n\
@@ -40,7 +40,7 @@
 	mcr	p15, 0, r2, c7, c7, 0		@ flush ID cache\n\
 	ldmfd	sp!, {r4, pc}			@ 3"
 	:
-	: "I" (PAGE_SIZE / 64));
+	: "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64));
 }
 
 void v4wt_copy_user_highpage(struct page *to, struct page *from,
--- linux-ec2-2.6.32.orig/arch/arm/mm/fault.c
+++ linux-ec2-2.6.32/arch/arm/mm/fault.c
@@ -386,6 +386,9 @@
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*
--- linux-ec2-2.6.32.orig/arch/arm/mm/mmap.c
+++ linux-ec2-2.6.32/arch/arm/mm/mmap.c
@@ -54,7 +54,8 @@
 	 * We enforce the MAP_FIXED case.
 	 */
 	if (flags & MAP_FIXED) {
-		if (aliasing && flags & MAP_SHARED && addr & (SHMLBA - 1))
+		if (aliasing && flags & MAP_SHARED &&
+		    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
 			return -EINVAL;
 		return addr;
 	}
--- linux-ec2-2.6.32.orig/arch/arm/mm/copypage-feroceon.c
+++ linux-ec2-2.6.32/arch/arm/mm/copypage-feroceon.c
@@ -18,7 +18,7 @@
 {
 	asm("\
 	stmfd	sp!, {r4-r9, lr}		\n\
-	mov	ip, %0				\n\
+	mov	ip, %2				\n\
 1:	mov	lr, r1				\n\
 	ldmia	r1!, {r2 - r9}			\n\
 	pld	[lr, #32]			\n\
@@ -64,7 +64,7 @@
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB\n\
 	ldmfd	sp!, {r4-r9, pc}"
 	:
-	: "I" (PAGE_SIZE));
+	: "r" (kto), "r" (kfrom), "I" (PAGE_SIZE));
 }
 
 void feroceon_copy_user_highpage(struct page *to, struct page *from,
--- linux-ec2-2.6.32.orig/arch/arm/mm/copypage-xsc3.c
+++ linux-ec2-2.6.32/arch/arm/mm/copypage-xsc3.c
@@ -34,7 +34,7 @@
 {
 	asm("\
 	stmfd	sp!, {r4, r5, lr}		\n\
-	mov	lr, %0				\n\
+	mov	lr, %2				\n\
 						\n\
 	pld	[r1, #0]			\n\
 	pld	[r1, #32]			\n\
@@ -67,7 +67,7 @@
 						\n\
 	ldmfd	sp!, {r4, r5, pc}"
 	:
-	: "I" (PAGE_SIZE / 64 - 1));
+	: "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1));
 }
 
 void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
--- linux-ec2-2.6.32.orig/arch/arm/mm/init.c
+++ linux-ec2-2.6.32/arch/arm/mm/init.c
@@ -632,10 +632,10 @@
 void free_initmem(void)
 {
 #ifdef CONFIG_HAVE_TCM
-	extern char *__tcm_start, *__tcm_end;
+	extern char __tcm_start, __tcm_end;
 
-	totalram_pages += free_area(__phys_to_pfn(__pa(__tcm_start)),
-				    __phys_to_pfn(__pa(__tcm_end)),
+	totalram_pages += free_area(__phys_to_pfn(__pa(&__tcm_start)),
+				    __phys_to_pfn(__pa(&__tcm_end)),
 				    "TCM link");
 #endif
 
--- linux-ec2-2.6.32.orig/arch/arm/vfp/vfphw.S
+++ linux-ec2-2.6.32/arch/arm/vfp/vfphw.S
@@ -277,7 +277,7 @@
 #ifdef CONFIG_VFPv3
 	@ d16 - d31 registers
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	mcrr	p11, 3, r1, r2, c\dr	@ fmdrr	r1, r2, d\dr
+1:	mcrr	p11, 3, r0, r1, c\dr	@ fmdrr	r0, r1, d\dr
 	mov	pc, lr
 	.org	1b + 8
 	.endr
--- linux-ec2-2.6.32.orig/arch/arm/include/asm/assembler.h
+++ linux-ec2-2.6.32/arch/arm/include/asm/assembler.h
@@ -215,7 +215,7 @@
 	@ Slightly optimised to avoid incrementing the pointer twice
 	usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort
 	.if	\rept == 2
-	usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort
+	usraccoff \instr, \reg, \ptr, \inc, \inc, \cond, \abort
 	.endif
 
 	add\cond \ptr, #\rept * \inc
--- linux-ec2-2.6.32.orig/arch/arm/include/asm/tlbflush.h
+++ linux-ec2-2.6.32/arch/arm/include/asm/tlbflush.h
@@ -369,7 +369,11 @@
 	if (tlb_flag(TLB_V6_I_ASID))
 		asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
 	if (tlb_flag(TLB_V7_UIS_ASID))
+#ifdef CONFIG_ARM_ERRATA_720789
+		asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+#else
 		asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
+#endif
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
@@ -409,7 +413,11 @@
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
 	if (tlb_flag(TLB_V7_UIS_PAGE))
+#ifdef CONFIG_ARM_ERRATA_720789
+		asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
+#else
 		asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
+#endif
 
 	if (tlb_flag(TLB_BTB)) {
 		/* flush the branch target cache */
--- linux-ec2-2.6.32.orig/arch/arm/include/asm/ptrace.h
+++ linux-ec2-2.6.32/arch/arm/include/asm/ptrace.h
@@ -150,15 +150,24 @@
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
-	if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
-		regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
-		return 1;
+	unsigned long mode = regs->ARM_cpsr & MODE_MASK;
+
+	/*
+	 * Always clear the F (FIQ) and A (delayed abort) bits
+	 */
+	regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
+
+	if ((regs->ARM_cpsr & PSR_I_BIT) == 0) {
+		if (mode == USR_MODE)
+			return 1;
+		if (elf_hwcap & HWCAP_26BIT && mode == USR26_MODE)
+			return 1;
 	}
 
 	/*
 	 * Force CPSR to something logical...
 	 */
-	regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+	regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
 	if (!(elf_hwcap & HWCAP_26BIT))
 		regs->ARM_cpsr |= USR_MODE;
 
--- linux-ec2-2.6.32.orig/arch/arm/include/asm/mman.h
+++ linux-ec2-2.6.32/arch/arm/include/asm/mman.h
@@ -1 +1,4 @@
 #include <asm-generic/mman.h>
+
+#define arch_mmap_check(addr, len, flags) \
+	(((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0)
--- linux-ec2-2.6.32.orig/arch/arm/mach-versatile/Kconfig
+++ linux-ec2-2.6.32/arch/arm/mach-versatile/Kconfig
@@ -3,14 +3,14 @@
 
 config ARCH_VERSATILE_PB
 	bool "Support Versatile/PB platform"
-	select CPU_ARM926T
+	select CPU_V7
 	default y
 	help
 	  Include support for the ARM(R) Versatile/PB platform.
 
 config MACH_VERSATILE_AB
 	bool "Support Versatile/AB platform"
-	select CPU_ARM926T
+	select CPU_V7
 	help
 	  Include support for the ARM(R) Versatile/AP platform.
 
--- linux-ec2-2.6.32.orig/arch/arm/mach-at91/at91sam9g45_devices.c
+++ linux-ec2-2.6.32/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -46,7 +46,7 @@
 		.end	= AT91_BASE_SYS + AT91_DMA + SZ_512 - 1,
 		.flags	= IORESOURCE_MEM,
 	},
-	[2] = {
+	[1] = {
 		.start	= AT91SAM9G45_ID_DMA,
 		.end	= AT91SAM9G45_ID_DMA,
 		.flags	= IORESOURCE_IRQ,
--- linux-ec2-2.6.32.orig/arch/powerpc/Makefile
+++ linux-ec2-2.6.32/arch/powerpc/Makefile
@@ -158,9 +158,11 @@
 # Default to zImage, override when needed
 all: zImage
 
-BOOT_TARGETS = zImage zImage.initrd uImage zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
+# With make 3.82 we cannot mix normal and wildcard targets
+BOOT_TARGETS1 := zImage zImage.initrd uImage
+BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
 
-PHONY += $(BOOT_TARGETS)
+PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
 
 boot := arch/$(ARCH)/boot
 
@@ -175,10 +177,16 @@
 zImage: relocs_check
 endif
 
-$(BOOT_TARGETS): vmlinux
+$(BOOT_TARGETS1): vmlinux
+	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+$(BOOT_TARGETS2): vmlinux
+	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+
+
+bootwrapper_install:
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
-bootwrapper_install %.dtb:
+%.dtb:
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
 define archhelp
--- linux-ec2-2.6.32.orig/arch/powerpc/Kconfig
+++ linux-ec2-2.6.32/arch/powerpc/Kconfig
@@ -935,6 +935,8 @@
 
 source "drivers/Kconfig"
 
+source "ubuntu/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/powerpc/sysdev/qe_lib/Kconfig"
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/cpu_setup_6xx.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -18,7 +18,7 @@
 #include <asm/mmu.h>
 
 _GLOBAL(__setup_cpu_603)
-	mflr	r4
+	mflr	r5
 BEGIN_MMU_FTR_SECTION
 	li	r10,0
 	mtspr	SPRN_SPRG_603_LRU,r10		/* init SW LRU tracking */
@@ -27,60 +27,60 @@
 	bl	__init_fpu_registers
 END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE)
 	bl	setup_common_caches
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_604)
-	mflr	r4
+	mflr	r5
 	bl	setup_common_caches
 	bl	setup_604_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750cx)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750cx
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_750fx)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	bl	setup_750fx
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_7400)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_7400_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_7410)
-	mflr	r4
+	mflr	r5
 	bl	__init_fpu_registers
 	bl	setup_7410_workarounds
 	bl	setup_common_caches
 	bl	setup_750_7400_hid0
 	li	r3,0
 	mtspr	SPRN_L2CR2,r3
-	mtlr	r4
+	mtlr	r5
 	blr
 _GLOBAL(__setup_cpu_745x)
-	mflr	r4
+	mflr	r5
 	bl	setup_common_caches
 	bl	setup_745x_specifics
-	mtlr	r4
+	mtlr	r5
 	blr
 
 /* Enable caches for 603's, 604, 750 & 7400 */
@@ -194,10 +194,10 @@
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bnelr
-	lwz	r6,CPU_SPEC_FEATURES(r5)
+	lwz	r6,CPU_SPEC_FEATURES(r4)
 	li	r7,CPU_FTR_CAN_NAP
 	andc	r6,r6,r7
-	stw	r6,CPU_SPEC_FEATURES(r5)
+	stw	r6,CPU_SPEC_FEATURES(r4)
 	blr
 
 /* 750fx specific
@@ -225,12 +225,12 @@
 	andis.	r11,r11,L3CR_L3E@h
 	beq	1f
 END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
-	lwz	r6,CPU_SPEC_FEATURES(r5)
+	lwz	r6,CPU_SPEC_FEATURES(r4)
 	andi.	r0,r6,CPU_FTR_L3_DISABLE_NAP
 	beq	1f
 	li	r7,CPU_FTR_CAN_NAP
 	andc	r6,r6,r7
-	stw	r6,CPU_SPEC_FEATURES(r5)
+	stw	r6,CPU_SPEC_FEATURES(r4)
 1:
 	mfspr	r11,SPRN_HID0
 
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/time.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/time.c
@@ -530,25 +530,60 @@
 }
 #endif /* CONFIG_PPC_ISERIES */
 
-#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32)
-DEFINE_PER_CPU(u8, perf_event_pending);
+#ifdef CONFIG_PERF_EVENTS
 
-void set_perf_event_pending(void)
+/*
+ * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
+ */
+#ifdef CONFIG_PPC64
+static inline unsigned long test_perf_event_pending(void)
 {
-	get_cpu_var(perf_event_pending) = 1;
-	set_dec(1);
-	put_cpu_var(perf_event_pending);
+	unsigned long x;
+
+	asm volatile("lbz %0,%1(13)"
+		: "=r" (x)
+		: "i" (offsetof(struct paca_struct, perf_event_pending)));
+	return x;
 }
 
+static inline void set_perf_event_pending_flag(void)
+{
+	asm volatile("stb %0,%1(13)" : :
+		"r" (1),
+		"i" (offsetof(struct paca_struct, perf_event_pending)));
+}
+
+static inline void clear_perf_event_pending(void)
+{
+	asm volatile("stb %0,%1(13)" : :
+		"r" (0),
+		"i" (offsetof(struct paca_struct, perf_event_pending)));
+}
+
+#else /* 32-bit */
+
+DEFINE_PER_CPU(u8, perf_event_pending);
+
+#define set_perf_event_pending_flag()	__get_cpu_var(perf_event_pending) = 1
 #define test_perf_event_pending()	__get_cpu_var(perf_event_pending)
 #define clear_perf_event_pending()	__get_cpu_var(perf_event_pending) = 0
 
-#else  /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
+#endif /* 32 vs 64 bit */
+
+void set_perf_event_pending(void)
+{
+	preempt_disable();
+	set_perf_event_pending_flag();
+	set_dec(1);
+	preempt_enable();
+}
+
+#else  /* CONFIG_PERF_EVENTS */
 
 #define test_perf_event_pending()	0
 #define clear_perf_event_pending()
 
-#endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
+#endif /* CONFIG_PERF_EVENTS */
 
 /*
  * For iSeries shared processors, we have to let the hypervisor
@@ -576,10 +611,6 @@
 	set_dec(DECREMENTER_MAX);
 
 #ifdef CONFIG_PPC32
-	if (test_perf_event_pending()) {
-		clear_perf_event_pending();
-		perf_event_do_pending();
-	}
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
 #endif
@@ -597,6 +628,11 @@
 
 	calculate_steal_time();
 
+	if (test_perf_event_pending()) {
+		clear_perf_event_pending();
+		perf_event_do_pending();
+	}
+
 #ifdef CONFIG_PPC_ISERIES
 	if (firmware_has_feature(FW_FEATURE_ISERIES))
 		get_lppaca()->int_dword.fields.decr_int = 0;
@@ -828,7 +864,8 @@
 	return (cycle_t)get_tb();
 }
 
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
+		     u32 mult)
 {
 	u64 t2x, stamp_xsec;
 
@@ -841,7 +878,7 @@
 
 	/* XXX this assumes clock->shift == 22 */
 	/* 4611686018 ~= 2^(20+64-22) / 1e9 */
-	t2x = (u64) clock->mult * 4611686018ULL;
+	t2x = (u64) mult * 4611686018ULL;
 	stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
 	do_div(stamp_xsec, 1000000000);
 	stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/syscalls.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/syscalls.c
@@ -140,7 +140,6 @@
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, unsigned long off, int shift)
 {
-	struct file * file = NULL;
 	unsigned long ret = -EINVAL;
 
 	if (!arch_validate_prot(prot))
@@ -151,20 +150,8 @@
 			goto out;
 		off >>= shift;
 	}
-		
-	ret = -EBADF;
-	if (!(flags & MAP_ANONYMOUS)) {
-		if (!(file = fget(fd)))
-			goto out;
-	}
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
-	down_write(&current->mm->mmap_sem);
-	ret = do_mmap_pgoff(file, addr, len, prot, flags, off);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
+	ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off);
 out:
 	return ret;
 }
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/paca.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/paca.c
@@ -14,6 +14,7 @@
 #include <asm/paca.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
+#include <asm/kexec.h>
 
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
@@ -97,6 +98,7 @@
 		new_paca->kernelbase = (unsigned long) _stext;
 		new_paca->kernel_msr = MSR_KERNEL;
 		new_paca->hw_cpu_id = 0xffff;
+		new_paca->kexec_state = KEXEC_STATE_NONE;
 		new_paca->__current = &init_task;
 #ifdef CONFIG_PPC_STD_MMU_64
 		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/process.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/process.c
@@ -554,18 +554,6 @@
 
 void flush_thread(void)
 {
-#ifdef CONFIG_PPC64
-	struct thread_info *t = current_thread_info();
-
-	if (test_ti_thread_flag(t, TIF_ABI_PENDING)) {
-		clear_ti_thread_flag(t, TIF_ABI_PENDING);
-		if (test_ti_thread_flag(t, TIF_32BIT))
-			clear_ti_thread_flag(t, TIF_32BIT);
-		else
-			set_ti_thread_flag(t, TIF_32BIT);
-	}
-#endif
-
 	discard_lazy_cpu_state();
 
 	if (current->thread.dabr) {
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/vmlinux.lds.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/vmlinux.lds.S
@@ -38,6 +38,9 @@
 #endif
 SECTIONS
 {
+	. = 0;
+	reloc_start = .;
+
 	. = KERNELBASE;
 
 /*
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/irq.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/irq.c
@@ -53,7 +53,6 @@
 #include <linux/bootmem.h>
 #include <linux/pci.h>
 #include <linux/debugfs.h>
-#include <linux/perf_event.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -138,11 +137,6 @@
 	}
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
-	if (test_perf_event_pending()) {
-		clear_perf_event_pending();
-		perf_event_do_pending();
-	}
-
 	/*
 	 * if (get_paca()->hard_enabled) return;
 	 * But again we need to take care that gcc gets hard_enabled directly
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/machine_kexec_64.c
@@ -15,6 +15,7 @@
 #include <linux/thread_info.h>
 #include <linux/init_task.h>
 #include <linux/errno.h>
+#include <linux/cpu.h>
 
 #include <asm/page.h>
 #include <asm/current.h>
@@ -155,33 +156,62 @@
 
 #ifdef CONFIG_SMP
 
-/* FIXME: we should schedule this function to be called on all cpus based
- * on calling the interrupts, but we would like to call it off irq level
- * so that the interrupt controller is clean.
- */
+static int kexec_all_irq_disabled;
+
 static void kexec_smp_down(void *arg)
 {
+	local_irq_disable();
+	mb(); /* make sure our irqs are disabled before we say they are */
+	get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
+	while (kexec_all_irq_disabled == 0)
+		cpu_relax();
+	mb(); /* make sure all irqs are disabled before this */
+	/*
+	 * Now every CPU has IRQs off, we can clear out any pending
+	 * IPIs and be sure that no more will come in after this.
+	 */
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(0, 1);
 
-	local_irq_disable();
 	kexec_smp_wait();
 	/* NOTREACHED */
 }
 
-static void kexec_prepare_cpus(void)
+/*
+ * We need to make sure each present CPU is online.  The next kernel will scan
+ * the device tree and assume primary threads are online and query secondary
+ * threads via RTAS to online them if required.  If we don't online primary
+ * threads, they will be stuck.  However, we also online secondary threads as we
+ * may be using 'cede offline'.  In this case RTAS doesn't see the secondary
+ * threads as offline -- and again, these CPUs will be stuck.
+ *
+ * So, we online all CPUs that should be running, including secondary threads.
+ */
+static void wake_offline_cpus(void)
+{
+	int cpu = 0;
+
+	for_each_present_cpu(cpu) {
+		if (!cpu_online(cpu)) {
+			printk(KERN_INFO "kexec: Waking offline cpu %d.\n",
+					cpu);
+			cpu_up(cpu);
+		}
+	}
+}
+
+static void kexec_prepare_cpus_wait(int wait_state)
 {
 	int my_cpu, i, notified=-1;
 
-	smp_call_function(kexec_smp_down, NULL, /* wait */0);
+	wake_offline_cpus();
 	my_cpu = get_cpu();
-
-	/* check the others cpus are now down (via paca hw cpu id == -1) */
+	/* Make sure each CPU has atleast made it to the state we need */
 	for (i=0; i < NR_CPUS; i++) {
 		if (i == my_cpu)
 			continue;
 
-		while (paca[i].hw_cpu_id != -1) {
+		while (paca[i].kexec_state < wait_state) {
 			barrier();
 			if (!cpu_possible(i)) {
 				printk("kexec: cpu %d hw_cpu_id %d is not"
@@ -201,20 +231,35 @@
 			}
 			if (i != notified) {
 				printk( "kexec: waiting for cpu %d (physical"
-						" %d) to go down\n",
-						i, paca[i].hw_cpu_id);
+						" %d) to enter %i state\n",
+					i, paca[i].hw_cpu_id, wait_state);
 				notified = i;
 			}
 		}
 	}
+	mb();
+}
+
+static void kexec_prepare_cpus(void)
+{
+
+	smp_call_function(kexec_smp_down, NULL, /* wait */0);
+	local_irq_disable();
+	mb(); /* make sure IRQs are disabled before we say they are */
+	get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF;
+
+	kexec_prepare_cpus_wait(KEXEC_STATE_IRQS_OFF);
+	/* we are sure every CPU has IRQs off at this point */
+	kexec_all_irq_disabled = 1;
 
 	/* after we tell the others to go down */
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(0, 0);
 
-	put_cpu();
+/* Before removing MMU mapings make sure all CPUs have entered real mode */
+	kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE);
 
-	local_irq_disable();
+	put_cpu();
 }
 
 #else /* ! SMP */
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/head_64.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/head_64.S
@@ -563,15 +563,21 @@
 	/* Set thread priority to MEDIUM */
 	HMT_MEDIUM
 
-	/* Do early setup for that CPU (stab, slb, hash table pointer) */
-	bl	.early_setup_secondary
-
 	/* Initialize the kernel stack.  Just a repeat for iSeries.	 */
 	LOAD_REG_ADDR(r3, current_set)
 	sldi	r28,r24,3		/* get current_set[cpu#]	 */
-	ldx	r1,r3,r28
-	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
-	std	r1,PACAKSAVE(r13)
+	ldx	r14,r3,r28
+	addi	r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD
+	std	r14,PACAKSAVE(r13)
+
+	/* Do early setup for that CPU (stab, slb, hash table pointer) */
+	bl	.early_setup_secondary
+
+	/*
+	 * setup the new stack pointer, but *don't* use this until
+	 * translation is on.
+	 */
+	mr	r1, r14
 
 	/* Clear backchain so we get nice backtraces */
 	li	r7,0
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/setup_64.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/setup_64.c
@@ -432,9 +432,18 @@
 	DBG(" <- setup_system()\n");
 }
 
+static u64 slb0_limit(void)
+{
+	if (cpu_has_feature(CPU_FTR_1T_SEGMENT)) {
+		return 1UL << SID_SHIFT_1T;
+	}
+	return 1UL << SID_SHIFT;
+}
+
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
+	u64 limit = slb0_limit();
 	unsigned int i;
 
 	/*
@@ -444,10 +453,10 @@
 	for_each_possible_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)
 			__va(lmb_alloc_base(THREAD_SIZE,
-					    THREAD_SIZE, 0x10000000));
+					    THREAD_SIZE, limit));
 		hardirq_ctx[i] = (struct thread_info *)
 			__va(lmb_alloc_base(THREAD_SIZE,
-					    THREAD_SIZE, 0x10000000));
+					    THREAD_SIZE, limit));
 	}
 }
 #else
@@ -478,7 +487,7 @@
  */
 static void __init emergency_stack_init(void)
 {
-	unsigned long limit;
+	u64 limit;
 	unsigned int i;
 
 	/*
@@ -490,7 +499,7 @@
 	 * bringup, we need to get at them in real mode. This means they
 	 * must also be within the RMO region.
 	 */
-	limit = min(0x10000000ULL, lmb.rmo_size);
+	limit = min(slb0_limit(), lmb.rmo_size);
 
 	for_each_possible_cpu(i) {
 		unsigned long sp;
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/align.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/align.c
@@ -642,10 +642,14 @@
  */
 static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
 		       unsigned int areg, struct pt_regs *regs,
-		       unsigned int flags, unsigned int length)
+		       unsigned int flags, unsigned int length,
+		       unsigned int elsize)
 {
 	char *ptr;
+	unsigned long *lptr;
 	int ret = 0;
+	int sw = 0;
+	int i, j;
 
 	flush_vsx_to_thread(current);
 
@@ -654,19 +658,35 @@
 	else
 		ptr = (char *) &current->thread.vr[reg - 32];
 
-	if (flags & ST)
-		ret = __copy_to_user(addr, ptr, length);
-        else {
-		if (flags & SPLT){
-			ret = __copy_from_user(ptr, addr, length);
-			ptr += length;
+	lptr = (unsigned long *) ptr;
+
+	if (flags & SW)
+		sw = elsize-1;
+
+	for (j = 0; j < length; j += elsize) {
+		for (i = 0; i < elsize; ++i) {
+			if (flags & ST)
+				ret |= __put_user(ptr[i^sw], addr + i);
+			else
+				ret |= __get_user(ptr[i^sw], addr + i);
 		}
-		ret |= __copy_from_user(ptr, addr, length);
+		ptr  += elsize;
+		addr += elsize;
 	}
-	if (flags & U)
-		regs->gpr[areg] = regs->dar;
-	if (ret)
+
+	if (!ret) {
+		if (flags & U)
+			regs->gpr[areg] = regs->dar;
+
+		/* Splat load copies the same data to top and bottom 8 bytes */
+		if (flags & SPLT)
+			lptr[1] = lptr[0];
+		/* For 8 byte loads, zero the top 8 bytes */
+		else if (!(flags & ST) && (8 == length))
+			lptr[1] = 0;
+	} else
 		return -EFAULT;
+
 	return 1;
 }
 #endif
@@ -767,16 +787,25 @@
 
 #ifdef CONFIG_VSX
 	if ((instruction & 0xfc00003e) == 0x7c000018) {
-		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR */
+		unsigned int elsize;
+
+		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */
 		reg |= (instruction & 0x1) << 5;
 		/* Simple inline decoder instead of a table */
+		/* VSX has only 8 and 16 byte memory accesses */
+		nb = 8;
 		if (instruction & 0x200)
 			nb = 16;
-		else if (instruction & 0x080)
-			nb = 8;
-		else
-			nb = 4;
+
+		/* Vector stores in little-endian mode swap individual
+		   elements, so process them separately */
+		elsize = 4;
+		if (instruction & 0x80)
+			elsize = 8;
+
 		flags = 0;
+		if (regs->msr & MSR_LE)
+			flags |= SW;
 		if (instruction & 0x100)
 			flags |= ST;
 		if (instruction & 0x040)
@@ -787,7 +816,7 @@
 			nb = 8;
 		}
 		PPC_WARN_EMULATED(vsx);
-		return emulate_vsx(addr, reg, areg, regs, flags, nb);
+		return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
 	}
 #endif
 	/* A size of 0 indicates an instruction we don't support, with
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/asm-offsets.c
@@ -133,7 +133,6 @@
 	DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
 	DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
 	DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
-	DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_event_pending));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
 #ifdef CONFIG_PPC_MM_SLICES
 	DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
@@ -184,6 +183,7 @@
 #endif /* CONFIG_PPC_STD_MMU_64 */
 	DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
 	DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
+	DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
 	DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
 	DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr));
 	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/perf_event.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/perf_event.c
@@ -1220,6 +1220,28 @@
 	return ip;
 }
 
+static bool pmc_overflow(unsigned long val)
+{
+	if ((int)val < 0)
+		return true;
+
+	/*
+	 * Events on POWER7 can roll back if a speculative event doesn't
+	 * eventually complete. Unfortunately in some rare cases they will
+	 * raise a performance monitor exception. We need to catch this to
+	 * ensure we reset the PMC. In all cases the PMC will be 256 or less
+	 * cycles from overflow.
+	 *
+	 * We only do this if the first pass fails to find any overflowing
+	 * PMCs because a user might set a period of less than 256 and we
+	 * don't want to mistakenly reset them.
+	 */
+	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+		return true;
+
+	return false;
+}
+
 /*
  * Performance monitor interrupt stuff
  */
@@ -1267,7 +1289,7 @@
 			if (is_limited_pmc(i + 1))
 				continue;
 			val = read_pmc(i + 1);
-			if ((int)val < 0)
+			if (pmc_overflow(val))
 				write_pmc(i + 1, 0);
 		}
 	}
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/misc_64.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/misc_64.S
@@ -24,6 +24,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
+#include <asm/kexec.h>
 
 	.text
 
@@ -471,6 +472,10 @@
 1:	mflr	r5
 	addi	r5,r5,kexec_flag-1b
 
+	li      r4,KEXEC_STATE_REAL_MODE
+	stb     r4,PACAKEXECSTATE(r13)
+	SYNC
+
 99:	HMT_LOW
 #ifdef CONFIG_KEXEC		/* use no memory without kexec */
 	lwz	r4,0(r5)
@@ -494,14 +499,11 @@
  * note: this is a terminal routine, it does not save lr
  *
  * get phys id from paca
- * set paca id to -1 to say we got here
  * switch to real mode
  * join other cpus in kexec_wait(phys_id)
  */
 _GLOBAL(kexec_smp_wait)
 	lhz	r3,PACAHWCPUID(r13)
-	li	r4,-1
-	sth	r4,PACAHWCPUID(r13)	/* let others know we left */
 	bl	real_mode
 	b	.kexec_wait
 
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/crash.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/crash.c
@@ -162,6 +162,34 @@
 	/* Leave the IPI callback set */
 }
 
+/* wait for all the CPUs to hit real mode but timeout if they don't come in */
+#ifdef CONFIG_PPC_STD_MMU_64
+static void crash_kexec_wait_realmode(int cpu)
+{
+	unsigned int msecs;
+	int i;
+
+	msecs = 10000;
+	for (i=0; i < NR_CPUS && msecs > 0; i++) {
+		if (i == cpu)
+			continue;
+
+		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
+			barrier();
+			if (!cpu_possible(i)) {
+				break;
+			}
+			if (!cpu_online(i)) {
+				break;
+			}
+			msecs--;
+			mdelay(1);
+		}
+	}
+	mb();
+}
+#endif
+
 /*
  * This function will be called by secondary cpus or by kexec cpu
  * if soft-reset is activated to stop some CPUs.
@@ -347,10 +375,12 @@
 EXPORT_SYMBOL(crash_shutdown_unregister);
 
 static unsigned long crash_shutdown_buf[JMP_BUF_LEN];
+static int crash_shutdown_cpu = -1;
 
 static int handle_fault(struct pt_regs *regs)
 {
-	longjmp(crash_shutdown_buf, 1);
+	if (crash_shutdown_cpu == smp_processor_id())
+		longjmp(crash_shutdown_buf, 1);
 	return 0;
 }
 
@@ -375,11 +405,14 @@
 	for_each_irq(i) {
 		struct irq_desc *desc = irq_desc + i;
 
+		if (!desc || !desc->chip || !desc->chip->eoi)
+			continue;
+
 		if (desc->status & IRQ_INPROGRESS)
 			desc->chip->eoi(i);
 
 		if (!(desc->status & IRQ_DISABLED))
-			desc->chip->disable(i);
+			desc->chip->shutdown(i);
 	}
 
 	/*
@@ -388,6 +421,7 @@
 	 */
 	old_handler = __debugger_fault_handler;
 	__debugger_fault_handler = handle_fault;
+	crash_shutdown_cpu = smp_processor_id();
 	for (i = 0; crash_shutdown_handles[i]; i++) {
 		if (setjmp(crash_shutdown_buf) == 0) {
 			/*
@@ -401,6 +435,7 @@
 			asm volatile("sync; isync");
 		}
 	}
+	crash_shutdown_cpu = -1;
 	__debugger_fault_handler = old_handler;
 
 	/*
@@ -412,6 +447,9 @@
 	crash_kexec_prepare_cpus(crashing_cpu);
 	cpu_set(crashing_cpu, cpus_in_crash);
 	crash_kexec_stop_spus();
+#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
+	crash_kexec_wait_realmode(crashing_cpu);
+#endif
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 0);
 }
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/ppc970-pmu.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/ppc970-pmu.c
@@ -173,9 +173,11 @@
 	switch (unit) {
 	case PM_VPU:
 		mask = 0x4c;		/* byte 0 bits 2,3,6 */
+		break;
 	case PM_LSU0:
 		/* byte 2 bits 0,2,3,4,6; all of byte 1 */
 		mask = 0x085dff00;
+		break;
 	case PM_LSU1L:
 		mask = 0x50 << 24;	/* byte 3 bits 4,6 */
 		break;
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/entry_64.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/entry_64.S
@@ -556,15 +556,6 @@
 2:
 	TRACE_AND_RESTORE_IRQ(r5);
 
-#ifdef CONFIG_PERF_EVENTS
-	/* check paca->perf_event_pending if we're enabling ints */
-	lbz	r3,PACAPERFPEND(r13)
-	and.	r3,r3,r5
-	beq	27f
-	bl	.perf_event_do_pending
-27:
-#endif /* CONFIG_PERF_EVENTS */
-
 	/* extract EE bit and use it to restore paca->hard_enabled */
 	ld	r3,_MSR(r1)
 	rldicl	r4,r3,49,63		/* r0 = (r3 >> 15) & 1 */
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/pci-common.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/pci-common.c
@@ -1107,6 +1107,12 @@
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct dev_archdata *sd = &dev->dev.archdata;
 
+		/* Cardbus can call us to add new devices to a bus, so ignore
+		 * those who are already fully discovered
+		 */
+		if (dev->is_added)
+			continue;
+
 		/* Setup OF node pointer in archdata */
 		sd->of_node = pci_device_to_OF_node(dev);
 
@@ -1147,6 +1153,13 @@
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
+void __devinit pci_fixup_cardbus(struct pci_bus *bus)
+{
+	/* Now fixup devices on that bus */
+	pcibios_setup_bus_devices(bus);
+}
+
+
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
 	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/rtas_flash.c
+++ linux-ec2-2.6.32/arch/powerpc/kernel/rtas_flash.c
@@ -93,12 +93,8 @@
 	struct flash_block_list *next;
 	struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
 };
-struct flash_block_list_header { /* just the header of flash_block_list */
-	unsigned long num_blocks;
-	struct flash_block_list *next;
-};
 
-static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
+static struct flash_block_list *rtas_firmware_flash_list;
 
 /* Use slab cache to guarantee 4k alignment */
 static struct kmem_cache *flash_block_cache = NULL;
@@ -107,13 +103,14 @@
 
 /* Local copy of the flash block list.
  * We only allow one open of the flash proc file and create this
- * list as we go.  This list will be put in the
- * rtas_firmware_flash_list var once it is fully read.
+ * list as we go.  The rtas_firmware_flash_list varable will be
+ * set once the data is fully read.
  *
  * For convenience as we build the list we use virtual addrs,
  * we do not fill in the version number, and the length field
  * is treated as the number of entries currently in the block
- * (i.e. not a byte count).  This is all fixed on release.
+ * (i.e. not a byte count).  This is all fixed when calling
+ * the flash routine.
  */
 
 /* Status int must be first member of struct */
@@ -200,16 +197,16 @@
 	if (uf->flist) {    
 		/* File was opened in write mode for a new flash attempt */
 		/* Clear saved list */
-		if (rtas_firmware_flash_list.next) {
-			free_flash_list(rtas_firmware_flash_list.next);
-			rtas_firmware_flash_list.next = NULL;
+		if (rtas_firmware_flash_list) {
+			free_flash_list(rtas_firmware_flash_list);
+			rtas_firmware_flash_list = NULL;
 		}
 
 		if (uf->status != FLASH_AUTH)  
 			uf->status = flash_list_valid(uf->flist);
 
 		if (uf->status == FLASH_IMG_READY) 
-			rtas_firmware_flash_list.next = uf->flist;
+			rtas_firmware_flash_list = uf->flist;
 		else
 			free_flash_list(uf->flist);
 
@@ -592,7 +589,7 @@
 	unsigned long rtas_block_list;
 	int i, status, update_token;
 
-	if (rtas_firmware_flash_list.next == NULL)
+	if (rtas_firmware_flash_list == NULL)
 		return;		/* nothing to do */
 
 	if (reboot_type != SYS_RESTART) {
@@ -609,20 +606,25 @@
 		return;
 	}
 
-	/* NOTE: the "first" block list is a global var with no data
-	 * blocks in the kernel data segment.  We do this because
-	 * we want to ensure this block_list addr is under 4GB.
+	/*
+	 * NOTE: the "first" block must be under 4GB, so we create
+	 * an entry with no data blocks in the reserved buffer in
+	 * the kernel data segment.
 	 */
-	rtas_firmware_flash_list.num_blocks = 0;
-	flist = (struct flash_block_list *)&rtas_firmware_flash_list;
+	spin_lock(&rtas_data_buf_lock);
+	flist = (struct flash_block_list *)&rtas_data_buf[0];
+	flist->num_blocks = 0;
+	flist->next = rtas_firmware_flash_list;
 	rtas_block_list = virt_to_abs(flist);
 	if (rtas_block_list >= 4UL*1024*1024*1024) {
 		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
+		spin_unlock(&rtas_data_buf_lock);
 		return;
 	}
 
 	printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
 	/* Update the block_list in place. */
+	rtas_firmware_flash_list = NULL; /* too hard to backout on error */
 	image_size = 0;
 	for (f = flist; f; f = next) {
 		/* Translate data addrs to absolute */
@@ -663,6 +665,7 @@
 		printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
 		break;
 	}
+	spin_unlock(&rtas_data_buf_lock);
 }
 
 static void remove_flash_pde(struct proc_dir_entry *dp)
--- linux-ec2-2.6.32.orig/arch/powerpc/kernel/vector.S
+++ linux-ec2-2.6.32/arch/powerpc/kernel/vector.S
@@ -58,7 +58,7 @@
 	 * all 1's
 	 */
 	mfspr	r4,SPRN_VRSAVE
-	cmpdi	0,r4,0
+	cmpwi	0,r4,0
 	bne+	1f
 	li	r4,-1
 	mtspr	SPRN_VRSAVE,r4
--- linux-ec2-2.6.32.orig/arch/powerpc/lib/string.S
+++ linux-ec2-2.6.32/arch/powerpc/lib/string.S
@@ -71,7 +71,7 @@
 
 _GLOBAL(strncmp)
 	PPC_LCMPI r5,0
-	beqlr
+	ble-	2f
 	mtctr	r5
 	addi	r5,r3,-1
 	addi	r4,r4,-1
@@ -82,6 +82,8 @@
 	beqlr	1
 	bdnzt	eq,1b
 	blr
+2:	li	r3,0
+	blr
 
 _GLOBAL(strlen)
 	addi	r4,r3,-1
--- linux-ec2-2.6.32.orig/arch/powerpc/oprofile/op_model_cell.c
+++ linux-ec2-2.6.32/arch/powerpc/oprofile/op_model_cell.c
@@ -1077,7 +1077,7 @@
 		index = ENTRIES-1;
 
 	/* make sure index is valid */
-	if ((index > ENTRIES) || (index < 0))
+	if ((index >= ENTRIES) || (index < 0))
 		index = ENTRIES-1;
 
 	return initial_lfsr[index];
--- linux-ec2-2.6.32.orig/arch/powerpc/boot/Makefile
+++ linux-ec2-2.6.32/arch/powerpc/boot/Makefile
@@ -364,7 +364,7 @@
 extra-installed		:= $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y))
 hostprogs-installed	:= $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y))
 wrapper-installed	:= $(DESTDIR)$(WRAPPER_BINDIR)/wrapper
-dts-installed		:= $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts))
+dts-installed		:= $(patsubst $(dtstree)/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(dtstree)/*.dts))
 
 all-installed		:= $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed)
 
--- linux-ec2-2.6.32.orig/arch/powerpc/kvm/powerpc.c
+++ linux-ec2-2.6.32/arch/powerpc/kvm/powerpc.c
@@ -176,7 +176,8 @@
 {
 	struct kvm_vcpu *vcpu;
 	vcpu = kvmppc_core_vcpu_create(kvm, id);
-	kvmppc_create_vcpu_debugfs(vcpu, id);
+	if (!IS_ERR(vcpu))
+		kvmppc_create_vcpu_debugfs(vcpu, id);
 	return vcpu;
 }
 
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -66,30 +66,6 @@
 	for(;;);
 }
 
-static int qcss_tok;	/* query-cpu-stopped-state token */
-
-/* Get state of physical CPU.
- * Return codes:
- *	0	- The processor is in the RTAS stopped state
- *	1	- stop-self is in progress
- *	2	- The processor is not in the RTAS stopped state
- *	-1	- Hardware Error
- *	-2	- Hardware Busy, Try again later.
- */
-static int query_cpu_stopped(unsigned int pcpu)
-{
-	int cpu_status, status;
-
-	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-	if (status != 0) {
-		printk(KERN_ERR
-		       "RTAS query-cpu-stopped-state failed: %i\n", status);
-		return status;
-	}
-
-	return cpu_status;
-}
-
 static int pseries_cpu_disable(void)
 {
 	int cpu = smp_processor_id();
@@ -113,8 +89,9 @@
 	unsigned int pcpu = get_hard_smp_processor_id(cpu);
 
 	for (tries = 0; tries < 25; tries++) {
-		cpu_status = query_cpu_stopped(pcpu);
-		if (cpu_status == 0 || cpu_status == -1)
+		cpu_status = smp_query_cpu_stopped(pcpu);
+		if (cpu_status == QCSS_STOPPED ||
+		    cpu_status == QCSS_HARDWARE_ERROR)
 			break;
 		cpu_relax();
 	}
@@ -256,6 +233,7 @@
 {
 	struct device_node *np;
 	const char *typep;
+	int qcss_tok;
 
 	for_each_node_by_name(np, "interrupt-controller") {
 		typep = of_get_property(np, "compatible", NULL);
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/lpar.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/lpar.c
@@ -366,21 +366,28 @@
 {
 	unsigned long size_bytes = 1UL << ppc64_pft_size;
 	unsigned long hpte_count = size_bytes >> 4;
-	unsigned long dummy1, dummy2, dword0;
+	struct {
+		unsigned long pteh;
+		unsigned long ptel;
+	} ptes[4];
 	long lpar_rc;
-	int i;
+	int i, j;
 
-	/* TODO: Use bulk call */
-	for (i = 0; i < hpte_count; i++) {
-		/* dont remove HPTEs with VRMA mappings */
-		lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG,
-						&dummy1, &dummy2);
-		if (lpar_rc == H_NOT_FOUND) {
-			lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1);
-			if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK)
-				!= HPTE_V_VRMA_MASK))
-				/* Can be hpte for 1TB Seg. So remove it */
-				plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
+	/* Read in batches of 4,
+	 * invalidate only valid entries not in the VRMA
+	 * hpte_count will be a multiple of 4
+         */
+	for (i = 0; i < hpte_count; i += 4) {
+		lpar_rc = plpar_pte_read_4_raw(0, i, (void *)ptes);
+		if (lpar_rc != H_SUCCESS)
+			continue;
+		for (j = 0; j < 4; j++){
+			if ((ptes[j].pteh & HPTE_V_VRMA_MASK) ==
+				HPTE_V_VRMA_MASK)
+				continue;
+			if (ptes[j].pteh & HPTE_V_VALID)
+				plpar_pte_remove_raw(0, i + j, 0,
+					&(ptes[j].pteh), &(ptes[j].ptel));
 		}
 	}
 }
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/eeh_driver.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -353,7 +353,7 @@
 		location = location ? location : "unknown";
 		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
 		                "for location=%s pci addr=%s\n",
-		        location, pci_name(event->dev));
+		        location, eeh_pci_name(event->dev));
 		return NULL;
 	}
 
@@ -384,7 +384,7 @@
 		pci_str = pci_name (frozen_pdn->pcidev);
 		drv_str = pcid_name (frozen_pdn->pcidev);
 	} else {
-		pci_str = pci_name (event->dev);
+		pci_str = eeh_pci_name(event->dev);
 		drv_str = pcid_name (event->dev);
 	}
 	
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/smp.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/smp.c
@@ -56,6 +56,28 @@
  */
 static cpumask_t of_spin_map;
 
+/* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */
+int smp_query_cpu_stopped(unsigned int pcpu)
+{
+	int cpu_status, status;
+	int qcss_tok = rtas_token("query-cpu-stopped-state");
+
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_INFO "Firmware doesn't support "
+				"query-cpu-stopped-state\n");
+		return QCSS_HARDWARE_ERROR;
+	}
+
+	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "RTAS query-cpu-stopped-state failed: %i\n", status);
+		return status;
+	}
+
+	return cpu_status;
+}
+
 /**
  * smp_startup_cpu() - start the given cpu
  *
@@ -81,6 +103,12 @@
 
 	pcpu = get_hard_smp_processor_id(lcpu);
 
+	/* Check to see if the CPU out of FW already for kexec */
+	if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){
+		cpu_set(lcpu, of_spin_map);
+		return 1;
+	}
+
 	/* Fixup atomic count: it exited inside IRQ handler. */
 	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
 
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/hvCall.S
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/hvCall.S
@@ -202,3 +202,41 @@
 	mtcrf	0xff,r0
 
 	blr				/* return r3 = status */
+
+/* See plpar_hcall_raw to see why this is needed */
+_GLOBAL(plpar_hcall9_raw)
+	HMT_MEDIUM
+
+	mfcr	r0
+	stw	r0,8(r1)
+
+	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+
+	mr	r4,r5
+	mr	r5,r6
+	mr	r6,r7
+	mr	r7,r8
+	mr	r8,r9
+	mr	r9,r10
+	ld	r10,STK_PARM(r11)(r1)	 /* put arg7 in R10 */
+	ld	r11,STK_PARM(r12)(r1)	 /* put arg8 in R11 */
+	ld	r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
+
+	HVSC				/* invoke the hypervisor */
+
+	mr	r0,r12
+	ld	r12,STK_PARM(r4)(r1)
+	std	r4,  0(r12)
+	std	r5,  8(r12)
+	std	r6, 16(r12)
+	std	r7, 24(r12)
+	std	r8, 32(r12)
+	std	r9, 40(r12)
+	std	r10,48(r12)
+	std	r11,56(r12)
+	std	r0, 64(r12)
+
+	lwz	r0,8(r1)
+	mtcrf	0xff,r0
+
+	blr				/* return r3 = status */
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/eeh.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/eeh.c
@@ -491,7 +491,7 @@
 	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
 		ignored_check++;
 		pr_debug("EEH: Ignored check (%x) for %s %s\n",
-			 pdn->eeh_mode, pci_name (dev), dn->full_name);
+			 pdn->eeh_mode, eeh_pci_name(dev), dn->full_name);
 		return 0;
 	}
 
@@ -515,7 +515,7 @@
 			printk (KERN_ERR "EEH: %d reads ignored for recovering device at "
 				"location=%s driver=%s pci addr=%s\n",
 				pdn->eeh_check_count, location,
-				dev->driver->name, pci_name(dev));
+				dev->driver->name, eeh_pci_name(dev));
 			printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",
 				dev->driver->name);
 			dump_stack();
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -4,6 +4,14 @@
 #include <asm/hvcall.h>
 #include <asm/page.h>
 
+/* Get state of physical CPU from query_cpu_stopped */
+int smp_query_cpu_stopped(unsigned int pcpu);
+#define QCSS_STOPPED 0
+#define QCSS_STOPPING 1
+#define QCSS_NOT_STOPPED 2
+#define QCSS_HARDWARE_ERROR -1
+#define QCSS_HARDWARE_BUSY -2
+
 static inline long poll_pending(void)
 {
 	return plpar_hcall_norets(H_POLL_PENDING);
@@ -161,6 +169,24 @@
 	return rc;
 }
 
+/*
+ * plpar_pte_read_4_raw can be called in real mode.
+ * ptes must be 8*sizeof(unsigned long)
+ */
+static inline long plpar_pte_read_4_raw(unsigned long flags, unsigned long ptex,
+					unsigned long *ptes)
+
+{
+	long rc;
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+
+	rc = plpar_hcall9_raw(H_READ, retbuf, flags | H_READ_4, ptex);
+
+	memcpy(ptes, retbuf, 8*sizeof(unsigned long));
+
+	return rc;
+}
+
 static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
 		unsigned long avpn)
 {
--- linux-ec2-2.6.32.orig/arch/powerpc/platforms/pseries/eeh_event.c
+++ linux-ec2-2.6.32/arch/powerpc/platforms/pseries/eeh_event.c
@@ -80,7 +80,7 @@
 	eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
 
 	printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-	       pci_name(event->dev));
+	       eeh_pci_name(event->dev));
 
 	pdn = handle_eeh_events(event);
 
--- linux-ec2-2.6.32.orig/arch/powerpc/sysdev/fsl_pci.c
+++ linux-ec2-2.6.32/arch/powerpc/sysdev/fsl_pci.c
@@ -392,8 +392,22 @@
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1011, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1013, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P1022, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header);
 #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
--- linux-ec2-2.6.32.orig/arch/powerpc/sysdev/fsl_rio.c
+++ linux-ec2-2.6.32/arch/powerpc/sysdev/fsl_rio.c
@@ -832,7 +832,6 @@
 	if (dsr & DOORBELL_DSR_QFI) {
 		pr_info("RIO: doorbell queue full\n");
 		out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI);
-		goto out;
 	}
 
 	/* XXX Need to check/dispatch until queue empty */
--- linux-ec2-2.6.32.orig/arch/powerpc/mm/fsl_booke_mmu.c
+++ linux-ec2-2.6.32/arch/powerpc/mm/fsl_booke_mmu.c
@@ -131,15 +131,10 @@
 	TLBCAM[index].MAS3 = (phys & PAGE_MASK) | MAS3_SX | MAS3_SR;
 	TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
 
-#ifndef CONFIG_KGDB /* want user access for breakpoints */
 	if (flags & _PAGE_USER) {
 	   TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
 	   TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
 	}
-#else
-	TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
-	TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
-#endif
 
 	tlbcam_addrs[index].start = virt;
 	tlbcam_addrs[index].limit = virt + size - 1;
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/elf.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/elf.h
@@ -236,14 +236,10 @@
 #ifdef __powerpc64__
 # define SET_PERSONALITY(ex)					\
 do {								\
-	unsigned long new_flags = 0;				\
 	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)		\
-		new_flags = _TIF_32BIT;				\
-	if ((current_thread_info()->flags & _TIF_32BIT)		\
-	    != new_flags)					\
-		set_thread_flag(TIF_ABI_PENDING);		\
+		set_thread_flag(TIF_32BIT);			\
 	else							\
-		clear_thread_flag(TIF_ABI_PENDING);		\
+		clear_thread_flag(TIF_32BIT);			\
 	if (personality(current->personality) != PER_LINUX32)	\
 		set_personality(PER_LINUX |			\
 			(current->personality & (~PER_MASK)));	\
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/hvcall.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/hvcall.h
@@ -268,6 +268,7 @@
  */
 #define PLPAR_HCALL9_BUFSIZE 9
 long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
+long plpar_hcall9_raw(unsigned long opcode, unsigned long *retbuf, ...);
 
 /* For hcall instrumentation.  One structure per-hcall, per-CPU */
 struct hcall_stats {
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/paca.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/paca.h
@@ -56,7 +56,7 @@
 	struct lppaca *lppaca_ptr;	/* Pointer to LpPaca for PLIC */
 #endif /* CONFIG_PPC_BOOK3S */
 	/*
-	 * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c 
+	 * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c
 	 * load lock_token and paca_index with a single lwz
 	 * instruction.  They must travel together and be properly
 	 * aligned.
@@ -76,6 +76,7 @@
 	s16 hw_cpu_id;			/* Physical processor number */
 	u8 cpu_start;			/* At startup, processor spins until */
 					/* this becomes non-zero. */
+	u8 kexec_state;         /* set when kexec down has irqs off */
 #ifdef CONFIG_PPC_STD_MMU_64
 	struct slb_shadow *slb_shadow_ptr;
 
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/system.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/system.h
@@ -540,10 +540,6 @@
 
 #define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 extern struct dentry *powerpc_debugfs_root;
 
 #endif /* __KERNEL__ */
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/reg.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/reg.h
@@ -858,6 +858,7 @@
 #define PV_970		0x0039
 #define PV_POWER5	0x003A
 #define PV_POWER5p	0x003B
+#define PV_POWER7	0x003F
 #define PV_970FX	0x003C
 #define PV_630		0x0040
 #define PV_630p	0x0041
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/thread_info.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/thread_info.h
@@ -111,7 +111,6 @@
 #define TIF_NOTIFY_RESUME	13	/* callback before returning to user */
 #define TIF_FREEZE		14	/* Freezing for suspend */
 #define TIF_RUNLATCH		15	/* Is the runlatch enabled? */
-#define TIF_ABI_PENDING		16	/* 32/64 bit switch needed */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -129,7 +128,6 @@
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/ppc-pci.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/ppc-pci.h
@@ -137,6 +137,11 @@
 void eeh_sysfs_add_device(struct pci_dev *pdev);
 void eeh_sysfs_remove_device(struct pci_dev *pdev);
 
+static inline const char *eeh_pci_name(struct pci_dev *pdev)
+{
+	return pdev ? pci_name(pdev) : "<null>";
+}
+
 #endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/compat.h
@@ -133,7 +133,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = current->thread.regs;
 	unsigned long usp = regs->gpr[1];
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/hw_irq.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/hw_irq.h
@@ -135,43 +135,5 @@
  */
 struct irq_chip;
 
-#ifdef CONFIG_PERF_EVENTS
-
-#ifdef CONFIG_PPC64
-static inline unsigned long test_perf_event_pending(void)
-{
-	unsigned long x;
-
-	asm volatile("lbz %0,%1(13)"
-		: "=r" (x)
-		: "i" (offsetof(struct paca_struct, perf_event_pending)));
-	return x;
-}
-
-static inline void set_perf_event_pending(void)
-{
-	asm volatile("stb %0,%1(13)" : :
-		"r" (1),
-		"i" (offsetof(struct paca_struct, perf_event_pending)));
-}
-
-static inline void clear_perf_event_pending(void)
-{
-	asm volatile("stb %0,%1(13)" : :
-		"r" (0),
-		"i" (offsetof(struct paca_struct, perf_event_pending)));
-}
-#endif /* CONFIG_PPC64 */
-
-#else  /* CONFIG_PERF_EVENTS */
-
-static inline unsigned long test_perf_event_pending(void)
-{
-	return 0;
-}
-
-static inline void clear_perf_event_pending(void) {}
-#endif /* CONFIG_PERF_EVENTS */
-
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_HW_IRQ_H */
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/module.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/module.h
@@ -87,5 +87,10 @@
 void sort_ex_table(struct exception_table_entry *start,
 		   struct exception_table_entry *finish);
 
+#ifdef CONFIG_MODVERSIONS
+#define ARCH_RELOCATES_KCRCTAB
+
+extern const unsigned long reloc_start[];
+#endif
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_MODULE_H */
--- linux-ec2-2.6.32.orig/arch/powerpc/include/asm/kexec.h
+++ linux-ec2-2.6.32/arch/powerpc/include/asm/kexec.h
@@ -31,6 +31,10 @@
 #define KEXEC_ARCH KEXEC_ARCH_PPC
 #endif
 
+#define KEXEC_STATE_NONE 0
+#define KEXEC_STATE_IRQS_OFF 1
+#define KEXEC_STATE_REAL_MODE 2
+
 #ifndef __ASSEMBLY__
 #include <linux/cpumask.h>
 #include <asm/reg.h>
--- linux-ec2-2.6.32.orig/arch/m68k/kernel/sys_m68k.c
+++ linux-ec2-2.6.32/arch/m68k/kernel/sys_m68k.c
@@ -29,37 +29,16 @@
 #include <asm/page.h>
 #include <asm/unistd.h>
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
 {
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+	/*
+	 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
+	 * so we need to shift the argument down by 1; m68k mmap64(3)
+	 * (in libc) expects the last argument of mmap2 in 4Kb units.
+	 */
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
 /*
@@ -90,57 +69,11 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
-#if 0
-struct mmap_arg_struct64 {
-	__u32 addr;
-	__u32 len;
-	__u32 prot;
-	__u32 flags;
-	__u64 offset; /* 64 bits */
-	__u32 fd;
-};
-
-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
-{
-	int error = -EFAULT;
-	struct file * file = NULL;
-	struct mmap_arg_struct64 a;
-	unsigned long pgoff;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-
-	if ((long)a.offset & ~PAGE_MASK)
-		return -EINVAL;
-
-	pgoff = a.offset >> PAGE_SHIFT;
-	if ((a.offset >> PAGE_SHIFT) != pgoff)
-		return -EINVAL;
-
-	if (!(a.flags & MAP_ANONYMOUS)) {
-		error = -EBADF;
-		file = fget(a.fd);
-		if (!file)
-			goto out;
-	}
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+			       a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
-#endif
 
 struct sel_arg_struct {
 	unsigned long n;
--- linux-ec2-2.6.32.orig/arch/m68k/mm/motorola.c
+++ linux-ec2-2.6.32/arch/m68k/mm/motorola.c
@@ -299,6 +299,8 @@
 		zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
 		free_area_init_node(i, zones_size,
 				    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+		if (node_present_pages(i))
+			node_set_state(i, N_NORMAL_MEMORY);
 	}
 }
 
--- linux-ec2-2.6.32.orig/arch/m68k/include/asm/cache.h
+++ linux-ec2-2.6.32/arch/m68k/include/asm/cache.h
@@ -8,4 +8,6 @@
 #define        L1_CACHE_SHIFT  4
 #define        L1_CACHE_BYTES  (1<< L1_CACHE_SHIFT)
 
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+
 #endif
--- linux-ec2-2.6.32.orig/arch/cris/kernel/sys_cris.c
+++ linux-ec2-2.6.32/arch/cris/kernel/sys_cris.c
@@ -26,31 +26,6 @@
 #include <asm/uaccess.h>
 #include <asm/segment.h>
 
-/* common code for old and new mmaps */
-static inline long
-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-        unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
-        int error = -EBADF;
-        struct file * file = NULL;
-
-        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-        if (!(flags & MAP_ANONYMOUS)) {
-                file = fget(fd);
-                if (!file)
-                        goto out;
-        }
-
-        down_write(&current->mm->mmap_sem);
-        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-        up_write(&current->mm->mmap_sem);
-
-        if (file)
-                fput(file);
-out:
-        return error;
-}
-
 asmlinkage unsigned long old_mmap(unsigned long __user *args)
 {        
 	unsigned long buffer[6];
@@ -63,7 +38,7 @@
 	if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
 		goto out;
 
-	err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
+	err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3],
                        buffer[4], buffer[5] >> PAGE_SHIFT);
 out:
 	return err;
@@ -73,7 +48,8 @@
 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
           unsigned long flags, unsigned long fd, unsigned long pgoff)
 {
-        return do_mmap2(addr, len, prot, flags, fd, pgoff);
+	/* bug(?): 8Kb pages here */
+        return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
 /*
--- linux-ec2-2.6.32.orig/arch/avr32/kernel/syscall-stubs.S
+++ linux-ec2-2.6.32/arch/avr32/kernel/syscall-stubs.S
@@ -61,7 +61,7 @@
 __sys_mmap2:
 	pushm	lr
 	st.w	--sp, ARG6
-	call	sys_mmap2
+	call	sys_mmap_pgoff
 	sub	sp, -4
 	popm	pc
 
--- linux-ec2-2.6.32.orig/arch/avr32/kernel/sys_avr32.c
+++ linux-ec2-2.6.32/arch/avr32/kernel/sys_avr32.c
@@ -5,39 +5,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mm.h>
 #include <linux/unistd.h>
 
-#include <asm/mman.h>
-#include <asm/uaccess.h>
-#include <asm/syscalls.h>
-
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-			  unsigned long prot, unsigned long flags,
-			  unsigned long fd, off_t offset)
-{
-	int error = -EBADF;
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			return error;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, offset);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-	return error;
-}
-
 int kernel_execve(const char *file, char **argv, char **envp)
 {
 	register long scno asm("r8") = __NR_execve;
--- linux-ec2-2.6.32.orig/arch/avr32/include/asm/syscalls.h
+++ linux-ec2-2.6.32/arch/avr32/include/asm/syscalls.h
@@ -29,10 +29,6 @@
 			       struct pt_regs *);
 asmlinkage int sys_rt_sigreturn(struct pt_regs *);
 
-/* kernel/sys_avr32.c */
-asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
-			  unsigned long, unsigned long, off_t);
-
 /* mm/cache.c */
 asmlinkage int sys_cacheflush(int, void __user *, size_t);
 
--- linux-ec2-2.6.32.orig/arch/mn10300/kernel/sys_mn10300.c
+++ linux-ec2-2.6.32/arch/mn10300/kernel/sys_mn10300.c
@@ -23,47 +23,13 @@
 
 #include <asm/uaccess.h>
 
-#define MIN_MAP_ADDR	PAGE_SIZE	/* minimum fixed mmap address */
-
-/*
- * memory mapping syscall
- */
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-			  unsigned long prot, unsigned long flags,
-			  unsigned long fd, unsigned long pgoff)
-{
-	struct file *file = NULL;
-	long error = -EINVAL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	if (flags & MAP_FIXED && addr < MIN_MAP_ADDR)
-		goto out;
-
-	error = -EBADF;
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 asmlinkage long old_mmap(unsigned long addr, unsigned long len,
 			 unsigned long prot, unsigned long flags,
 			 unsigned long fd, unsigned long offset)
 {
 	if (offset & ~PAGE_MASK)
 		return -EINVAL;
-	return sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 }
 
 struct sel_arg_struct {
--- linux-ec2-2.6.32.orig/arch/mn10300/kernel/entry.S
+++ linux-ec2-2.6.32/arch/mn10300/kernel/entry.S
@@ -578,7 +578,7 @@
 	.long sys_ni_syscall	/* reserved for streams2 */
 	.long sys_vfork		/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap2
+	.long sys_mmap_pgoff
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64	/* 195 */
--- linux-ec2-2.6.32.orig/arch/mn10300/include/asm/cache.h
+++ linux-ec2-2.6.32/arch/mn10300/include/asm/cache.h
@@ -21,6 +21,8 @@
 #define L1_CACHE_DISPARITY	L1_CACHE_NENTRIES * L1_CACHE_BYTES
 #endif
 
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+
 /* data cache purge registers
  * - read from the register to unconditionally purge that cache line
  * - write address & 0xffffff00 to conditionally purge that cache line
--- linux-ec2-2.6.32.orig/arch/mn10300/include/asm/mman.h
+++ linux-ec2-2.6.32/arch/mn10300/include/asm/mman.h
@@ -1 +1,6 @@
 #include <asm-generic/mman.h>
+
+#define MIN_MAP_ADDR	PAGE_SIZE	/* minimum fixed mmap address */
+
+#define arch_mmap_check(addr, len, flags) \
+	(((flags) & MAP_FIXED && (addr) < MIN_MAP_ADDR) ? -EINVAL : 0)
--- linux-ec2-2.6.32.orig/arch/sparc/Makefile
+++ linux-ec2-2.6.32/arch/sparc/Makefile
@@ -27,6 +27,7 @@
 LDFLAGS        := -m elf32_sparc
 CHECKFLAGS     += -D__sparc__
 export BITS    := 32
+UTS_MACHINE    := sparc
 
 #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
 KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
@@ -46,6 +47,7 @@
 
 LDFLAGS              := -m elf64_sparc
 export BITS          := 64
+UTS_MACHINE          := sparc64
 
 KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow   \
                  -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/process_64.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/process_64.c
@@ -365,14 +365,6 @@
 	struct thread_info *t = current_thread_info();
 	struct mm_struct *mm;
 
-	if (test_ti_thread_flag(t, TIF_ABI_PENDING)) {
-		clear_ti_thread_flag(t, TIF_ABI_PENDING);
-		if (test_ti_thread_flag(t, TIF_32BIT))
-			clear_ti_thread_flag(t, TIF_32BIT);
-		else
-			set_ti_thread_flag(t, TIF_32BIT);
-	}
-
 	mm = t->task->mm;
 	if (mm)
 		tsb_context_switch(mm);
@@ -406,11 +398,11 @@
 	} else
 		__get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
 
-	/* Now 8-byte align the stack as this is mandatory in the
-	 * Sparc ABI due to how register windows work.  This hides
-	 * the restriction from thread libraries etc.  -DaveM
+	/* Now align the stack as this is mandatory in the Sparc ABI
+	 * due to how register windows work.  This hides the
+	 * restriction from thread libraries etc.
 	 */
-	csp &= ~7UL;
+	csp &= ~15UL;
 
 	distance = fp - psp;
 	rval = (csp - distance);
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/systbls.h
+++ linux-ec2-2.6.32/arch/sparc/kernel/systbls.h
@@ -9,7 +9,6 @@
 struct new_utsname;
 
 extern asmlinkage unsigned long sys_getpagesize(void);
-extern asmlinkage unsigned long sparc_brk(unsigned long brk);
 extern asmlinkage long sparc_pipe(struct pt_regs *regs);
 extern asmlinkage long sys_ipc(unsigned int call, int first,
 			       unsigned long second,
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/sys_sparc_64.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/sys_sparc_64.c
@@ -317,10 +317,14 @@
 unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	unsigned long align_goal, addr = -ENOMEM;
+	unsigned long (*get_area)(struct file *, unsigned long,
+				  unsigned long, unsigned long, unsigned long);
+
+	get_area = current->mm->get_unmapped_area;
 
 	if (flags & MAP_FIXED) {
 		/* Ok, don't mess with it. */
-		return get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
+		return get_area(NULL, orig_addr, len, pgoff, flags);
 	}
 	flags &= ~MAP_SHARED;
 
@@ -333,7 +337,7 @@
 		align_goal = (64UL * 1024);
 
 	do {
-		addr = get_unmapped_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
+		addr = get_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
 		if (!(addr & ~PAGE_MASK)) {
 			addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL);
 			break;
@@ -351,7 +355,7 @@
 	 * be obtained.
 	 */
 	if (addr & ~PAGE_MASK)
-		addr = get_unmapped_area(NULL, orig_addr, len, pgoff, flags);
+		addr = get_area(NULL, orig_addr, len, pgoff, flags);
 
 	return addr;
 }
@@ -399,18 +403,6 @@
 	}
 }
 
-SYSCALL_DEFINE1(sparc_brk, unsigned long, brk)
-{
-	/* People could try to be nasty and use ta 0x6d in 32bit programs */
-	if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32)
-		return current->mm->brk;
-
-	if (unlikely(straddles_64bit_va_hole(current->mm->brk, brk)))
-		return current->mm->brk;
-
-	return sys_brk(brk);
-}
-                                                                
 /*
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way unix traditionally does this, though.
@@ -568,23 +560,13 @@
 		unsigned long, prot, unsigned long, flags, unsigned long, fd,
 		unsigned long, off)
 {
-	struct file * file = NULL;
-	unsigned long retval = -EBADF;
-
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	len = PAGE_ALIGN(len);
+	unsigned long retval = -EINVAL;
 
-	down_write(&current->mm->mmap_sem);
-	retval = do_mmap(file, addr, len, prot, flags, off);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
+	if ((off + PAGE_ALIGN(len)) < off)
+		goto out;
+	if (off & ~PAGE_MASK)
+		goto out;
+	retval = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 out:
 	return retval;
 }
@@ -614,12 +596,6 @@
 
 	if (test_thread_flag(TIF_32BIT))
 		goto out;
-	if (unlikely(new_len >= VA_EXCLUDE_START))
-		goto out;
-	if (unlikely(sparc_mmap_check(addr, old_len)))
-		goto out;
-	if (unlikely(sparc_mmap_check(new_addr, new_len)))
-		goto out;
 
 	down_write(&current->mm->mmap_sem);
 	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/sys_sparc_32.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/sys_sparc_32.c
@@ -45,7 +45,8 @@
 		/* We do not accept a shared mapping if it would violate
 		 * cache aliasing constraints.
 		 */
-		if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+		if ((flags & MAP_SHARED) &&
+		    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
 			return -EINVAL;
 		return addr;
 	}
@@ -79,15 +80,6 @@
 	}
 }
 
-asmlinkage unsigned long sparc_brk(unsigned long brk)
-{
-	if(ARCH_SUN4C) {
-		if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000))
-			return current->mm->brk;
-	}
-	return sys_brk(brk);
-}
-
 /*
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way unix traditionally does this, though.
@@ -234,31 +226,6 @@
 }
 
 /* Linux version of mmap */
-static unsigned long do_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags, unsigned long fd,
-	unsigned long pgoff)
-{
-	struct file * file = NULL;
-	unsigned long retval = -EBADF;
-
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	len = PAGE_ALIGN(len);
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	down_write(&current->mm->mmap_sem);
-	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return retval;
-}
 
 asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
@@ -266,14 +233,16 @@
 {
 	/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
 	   we have. */
-	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      pgoff >> (PAGE_SHIFT - 12));
 }
 
 asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
 	unsigned long off)
 {
-	return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+	/* no alignment check? */
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 }
 
 long sparc_remap_file_pages(unsigned long start, unsigned long size,
@@ -287,27 +256,6 @@
 				    (pgoff >> (PAGE_SHIFT - 12)), flags);
 }
 
-extern unsigned long do_mremap(unsigned long addr,
-	unsigned long old_len, unsigned long new_len,
-	unsigned long flags, unsigned long new_addr);
-                
-asmlinkage unsigned long sparc_mremap(unsigned long addr,
-	unsigned long old_len, unsigned long new_len,
-	unsigned long flags, unsigned long new_addr)
-{
-	unsigned long ret = -EINVAL;
-
-	if (unlikely(sparc_mmap_check(addr, old_len)))
-		goto out;
-	if (unlikely(sparc_mmap_check(new_addr, new_len)))
-		goto out;
-	down_write(&current->mm->mmap_sem);
-	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
-	up_write(&current->mm->mmap_sem);
-out:
-	return ret;       
-}
-
 /* we come to here via sys_nis_syscall so it can setup the regs argument */
 asmlinkage unsigned long
 c_sys_nis_syscall (struct pt_regs *regs)
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/systbls_32.S
+++ linux-ec2-2.6.32/arch/sparc/kernel/systbls_32.S
@@ -19,7 +19,7 @@
 /*0*/	.long sys_restart_syscall, sys_exit, sys_fork, sys_read, sys_write
 /*5*/	.long sys_open, sys_close, sys_wait4, sys_creat, sys_link
 /*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
-/*15*/	.long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
+/*15*/	.long sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys_lseek
 /*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
 /*25*/	.long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
 /*30*/	.long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
@@ -67,7 +67,7 @@
 /*235*/	.long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/	.long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 /*255*/	.long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/process_32.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/process_32.c
@@ -526,7 +526,7 @@
 			 * Set some valid stack frames to give to the child.
 			 */
 			childstack = (struct sparc_stackf __user *)
-				(sp & ~0x7UL);
+				(sp & ~0xfUL);
 			parentstack = (struct sparc_stackf __user *)
 				regs->u_regs[UREG_FP];
 
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/of_device_64.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/of_device_64.c
@@ -104,9 +104,19 @@
 	int i;
 
 	/* Check address type match */
-	if ((addr[0] ^ range[0]) & 0x03000000)
-		return -EINVAL;
+	if (!((addr[0] ^ range[0]) & 0x03000000))
+		goto type_match;
+
+	/* Special exception, we can map a 64-bit address into
+	 * a 32-bit range.
+	 */
+	if ((addr[0] & 0x03000000) == 0x03000000 &&
+	    (range[0] & 0x03000000) == 0x02000000)
+		goto type_match;
+
+	return -EINVAL;
 
+type_match:
 	if (of_out_of_range(addr + 1, range + 1, range + na + pna,
 			    na - 1, ns))
 		return -EINVAL;
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/central.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/central.c
@@ -99,7 +99,7 @@
 
 	p->leds_resource.start = (unsigned long)
 		(p->clock_regs + CLOCK_CTRL);
-	p->leds_resource.end = p->leds_resource.end;
+	p->leds_resource.end = p->leds_resource.start;
 	p->leds_resource.name = "leds";
 
 	p->leds_pdev.name = "sunfire-clockboard-leds";
@@ -194,7 +194,7 @@
 	if (!p->central) {
 		p->leds_resource.start = (unsigned long)
 			(p->pregs + FHC_PREGS_CTRL);
-		p->leds_resource.end = p->leds_resource.end;
+		p->leds_resource.end = p->leds_resource.start;
 		p->leds_resource.name = "leds";
 
 		p->leds_pdev.name = "sunfire-fhc-leds";
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/ldc.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/ldc.c
@@ -1242,13 +1242,13 @@
 	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
 
 	err = request_irq(lp->cfg.rx_irq, ldc_rx,
-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
+			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
 			  lp->rx_irq_name, lp);
 	if (err)
 		return err;
 
 	err = request_irq(lp->cfg.tx_irq, ldc_tx,
-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED | IRQF_SHARED,
+			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
 			  lp->tx_irq_name, lp);
 	if (err) {
 		free_irq(lp->cfg.rx_irq, lp);
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/systbls_64.S
+++ linux-ec2-2.6.32/arch/sparc/kernel/systbls_64.S
@@ -21,7 +21,7 @@
 /*0*/	.word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod
-/*15*/	.word sys_chmod, sys_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek
+/*15*/	.word sys_chmod, sys_lchown16, sys_brk, sys32_perfctr, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
 /*25*/	.word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause
 /*30*/	.word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
@@ -96,7 +96,7 @@
 /*0*/	.word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys_open, sys_close, sys_wait4, sys_creat, sys_link
 /*10*/  .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
-/*15*/	.word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek
+/*15*/	.word sys_chmod, sys_lchown, sys_brk, sys_perfctr, sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
 /*25*/	.word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
 /*30*/	.word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/nmi.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/nmi.c
@@ -96,7 +96,6 @@
 	int cpu = smp_processor_id();
 
 	clear_softint(1 << irq);
-	pcr_ops->write(PCR_PIC_PRIV);
 
 	local_cpu_data().__nmi_count++;
 
@@ -105,6 +104,8 @@
 	if (notify_die(DIE_NMI, "nmi", regs, 0,
 		       pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
 		touched = 1;
+	else
+		pcr_ops->write(PCR_PIC_PRIV);
 
 	sum = kstat_irqs_cpu(0, cpu);
 	if (__get_cpu_var(nmi_touch)) {
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/signal_64.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/signal_64.c
@@ -353,7 +353,7 @@
 /* Checks if the fp is valid */
 static int invalid_frame_pointer(void __user *fp, int fplen)
 {
-	if (((unsigned long) fp) & 7)
+	if (((unsigned long) fp) & 15)
 		return 1;
 	return 0;
 }
@@ -396,18 +396,20 @@
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
+	sp -= framesize;
+
 	/* Always align the stack frame.  This handles two cases.  First,
 	 * sigaltstack need not be mindful of platform specific stack
 	 * alignment.  Second, if we took this signal because the stack
 	 * is not aligned properly, we'd like to take the signal cleanly
 	 * and report that.
 	 */
-	sp &= ~7UL;
+	sp &= ~15UL;
 
-	return (void __user *)(sp - framesize);
+	return (void __user *) sp;
 }
 
-static inline void
+static inline int
 setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	       int signo, sigset_t *oldset, siginfo_t *info)
 {
@@ -481,26 +483,37 @@
 	}
 	/* 4. return to kernel instructions */
 	regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
-	return;
+	return 0;
 
 sigill:
 	do_exit(SIGILL);
+	return -EINVAL;
+
 sigsegv:
 	force_sigsegv(signo, current);
+	return -EFAULT;
 }
 
-static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
-				 siginfo_t *info,
-				 sigset_t *oldset, struct pt_regs *regs)
+static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
+				siginfo_t *info,
+				sigset_t *oldset, struct pt_regs *regs)
 {
-	setup_rt_frame(ka, regs, signr, oldset,
-		       (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
+	int err;
+
+	err = setup_rt_frame(ka, regs, signr, oldset,
+			     (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
+	if (err)
+		return err;
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 	if (!(ka->sa.sa_flags & SA_NOMASK))
 		sigaddset(&current->blocked,signr);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	tracehook_signal_handler(signr, info, ka, regs, 0);
+
+	return 0;
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -569,16 +582,14 @@
 	if (signr > 0) {
 		if (restart_syscall)
 			syscall_restart(orig_i0, regs, &ka.sa);
-		handle_signal(signr, &ka, &info, oldset, regs);
-
-		/* A signal was successfully delivered; the saved
-		 * sigmask will have been stored in the signal frame,
-		 * and will be restored by sigreturn, so we can simply
-		 * clear the TS_RESTORE_SIGMASK flag.
-		 */
-		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-		tracehook_signal_handler(signr, &info, &ka, regs, 0);
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+			/* A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TS_RESTORE_SIGMASK flag.
+			 */
+			current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+		}
 		return;
 	}
 	if (restart_syscall &&
@@ -589,12 +600,14 @@
 		regs->u_regs[UREG_I0] = orig_i0;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 	if (restart_syscall &&
 	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
 		regs->u_regs[UREG_G1] = __NR_restart_syscall;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 
 	/* If there's no signal to deliver, we just put the saved sigmask
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/tsb.S
+++ linux-ec2-2.6.32/arch/sparc/kernel/tsb.S
@@ -191,10 +191,12 @@
 
 tsb_itlb_load:
 	/* Executable bit must be set.  */
-661:	andcc		%g5, _PAGE_EXEC_4U, %g0
-	.section	.sun4v_1insn_patch, "ax"
+661:	sethi		%hi(_PAGE_EXEC_4U), %g4
+	andcc		%g5, %g4, %g0
+	.section	.sun4v_2insn_patch, "ax"
 	.word		661b
 	andcc		%g5, _PAGE_EXEC_4V, %g0
+	nop
 	.previous
 
 	be,pn		%xcc, tsb_do_fault
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/perf_event.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/perf_event.c
@@ -986,6 +986,17 @@
 	data.addr = 0;
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
+
+	/* If the PMU has the TOE IRQ enable bits, we need to do a
+	 * dummy write to the %pcr to clear the overflow bits and thus
+	 * the interrupt.
+	 *
+	 * Do this before we peek at the counters to determine
+	 * overflow so we don't lose any events.
+	 */
+	if (sparc_pmu->irq_bit)
+		pcr_ops->write(cpuc->pcr);
+
 	for (idx = 0; idx < MAX_HWEVENTS; idx++) {
 		struct perf_event *event = cpuc->events[idx];
 		struct hw_perf_event *hwc;
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/signal_32.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/signal_32.c
@@ -267,15 +267,17 @@
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
+	sp -= framesize;
+
 	/* Always align the stack frame.  This handles two cases.  First,
 	 * sigaltstack need not be mindful of platform specific stack
 	 * alignment.  Second, if we took this signal because the stack
 	 * is not aligned properly, we'd like to take the signal cleanly
 	 * and report that.
 	 */
-	sp &= ~7UL;
+	sp &= ~15UL;
 
-	return (void __user *)(sp - framesize);
+	return (void __user *) sp;
 }
 
 static inline int
@@ -313,8 +315,8 @@
 	return err;
 }
 
-static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
-			int signo, sigset_t *oldset)
+static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
+		       int signo, sigset_t *oldset)
 {
 	struct signal_frame __user *sf;
 	int sigframe_size, err;
@@ -382,16 +384,19 @@
 		/* Flush instruction space. */
 		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
 	}
-	return;
+	return 0;
 
 sigill_and_return:
 	do_exit(SIGILL);
+	return -EINVAL;
+
 sigsegv:
 	force_sigsegv(signo, current);
+	return -EFAULT;
 }
 
-static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
-			   int signo, sigset_t *oldset, siginfo_t *info)
+static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
+			  int signo, sigset_t *oldset, siginfo_t *info)
 {
 	struct rt_signal_frame __user *sf;
 	int sigframe_size;
@@ -464,22 +469,30 @@
 		/* Flush instruction space. */
 		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
 	}
-	return;
+	return 0;
 
 sigill:
 	do_exit(SIGILL);
+	return -EINVAL;
+
 sigsegv:
 	force_sigsegv(signo, current);
+	return -EFAULT;
 }
 
-static inline void
+static inline int
 handle_signal(unsigned long signr, struct k_sigaction *ka,
 	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
+	int err;
+
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(ka, regs, signr, oldset, info);
+		err = setup_rt_frame(ka, regs, signr, oldset, info);
 	else
-		setup_frame(ka, regs, signr, oldset);
+		err = setup_frame(ka, regs, signr, oldset);
+
+	if (err)
+		return err;
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -487,6 +500,10 @@
 		sigaddset(&current->blocked, signr);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	tracehook_signal_handler(signr, info, ka, regs, 0);
+
+	return 0;
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -544,17 +561,15 @@
 	if (signr > 0) {
 		if (restart_syscall)
 			syscall_restart(orig_i0, regs, &ka.sa);
-		handle_signal(signr, &ka, &info, oldset, regs);
-
-		/* a signal was successfully delivered; the saved
-		 * sigmask will have been stored in the signal frame,
-		 * and will be restored by sigreturn, so we can simply
-		 * clear the TIF_RESTORE_SIGMASK flag.
-		 */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK))
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-		tracehook_signal_handler(signr, &info, &ka, regs, 0);
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
 		return;
 	}
 	if (restart_syscall &&
@@ -565,12 +580,14 @@
 		regs->u_regs[UREG_I0] = orig_i0;
 		regs->pc -= 4;
 		regs->npc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 	if (restart_syscall &&
 	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
 		regs->u_regs[UREG_G1] = __NR_restart_syscall;
 		regs->pc -= 4;
 		regs->npc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 
 	/* if there's no signal to deliver, we just put the saved sigmask
--- linux-ec2-2.6.32.orig/arch/sparc/kernel/signal32.c
+++ linux-ec2-2.6.32/arch/sparc/kernel/signal32.c
@@ -120,8 +120,8 @@
 };
 
 /* Align macros */
-#define SF_ALIGNEDSZ  (((sizeof(struct signal_frame32) + 7) & (~7)))
-#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
+#define SF_ALIGNEDSZ  (((sizeof(struct signal_frame32) + 15) & (~15)))
+#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 15) & (~15)))
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
@@ -420,15 +420,17 @@
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
+	sp -= framesize;
+
 	/* Always align the stack frame.  This handles two cases.  First,
 	 * sigaltstack need not be mindful of platform specific stack
 	 * alignment.  Second, if we took this signal because the stack
 	 * is not aligned properly, we'd like to take the signal cleanly
 	 * and report that.
 	 */
-	sp &= ~7UL;
+	sp &= ~15UL;
 
-	return (void __user *)(sp - framesize);
+	return (void __user *) sp;
 }
 
 static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
@@ -451,8 +453,66 @@
 	return err;
 }
 
-static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
-			  int signo, sigset_t *oldset)
+/* The I-cache flush instruction only works in the primary ASI, which
+ * right now is the nucleus, aka. kernel space.
+ *
+ * Therefore we have to kick the instructions out using the kernel
+ * side linear mapping of the physical address backing the user
+ * instructions.
+ */
+static void flush_signal_insns(unsigned long address)
+{
+	unsigned long pstate, paddr;
+	pte_t *ptep, pte;
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+
+	/* Commit all stores of the instructions we are about to flush.  */
+	wmb();
+
+	/* Disable cross-call reception.  In this way even a very wide
+	 * munmap() on another cpu can't tear down the page table
+	 * hierarchy from underneath us, since that can't complete
+	 * until the IPI tlb flush returns.
+	 */
+
+	__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
+	__asm__ __volatile__("wrpr %0, %1, %%pstate"
+				: : "r" (pstate), "i" (PSTATE_IE));
+
+	pgdp = pgd_offset(current->mm, address);
+	if (pgd_none(*pgdp))
+		goto out_irqs_on;
+	pudp = pud_offset(pgdp, address);
+	if (pud_none(*pudp))
+		goto out_irqs_on;
+	pmdp = pmd_offset(pudp, address);
+	if (pmd_none(*pmdp))
+		goto out_irqs_on;
+
+	ptep = pte_offset_map(pmdp, address);
+	pte = *ptep;
+	if (!pte_present(pte))
+		goto out_unmap;
+
+	paddr = (unsigned long) page_address(pte_page(pte));
+
+	__asm__ __volatile__("flush	%0 + %1"
+			     : /* no outputs */
+			     : "r" (paddr),
+			       "r" (address & (PAGE_SIZE - 1))
+			     : "memory");
+
+out_unmap:
+	pte_unmap(ptep);
+out_irqs_on:
+	__asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
+
+}
+
+static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+			 int signo, sigset_t *oldset)
 {
 	struct signal_frame32 __user *sf;
 	int sigframe_size;
@@ -545,13 +605,7 @@
 	if (ka->ka_restorer) {
 		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
 	} else {
-		/* Flush instruction space. */
 		unsigned long address = ((unsigned long)&(sf->insns[0]));
-		pgd_t *pgdp = pgd_offset(current->mm, address);
-		pud_t *pudp = pud_offset(pgdp, address);
-		pmd_t *pmdp = pmd_offset(pudp, address);
-		pte_t *ptep;
-		pte_t pte;
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 	
@@ -560,34 +614,22 @@
 		if (err)
 			goto sigsegv;
 
-		preempt_disable();
-		ptep = pte_offset_map(pmdp, address);
-		pte = *ptep;
-		if (pte_present(pte)) {
-			unsigned long page = (unsigned long)
-				page_address(pte_page(pte));
-
-			wmb();
-			__asm__ __volatile__("flush	%0 + %1"
-					     : /* no outputs */
-					     : "r" (page),
-					       "r" (address & (PAGE_SIZE - 1))
-					     : "memory");
-		}
-		pte_unmap(ptep);
-		preempt_enable();
+		flush_signal_insns(address);
 	}
-	return;
+	return 0;
 
 sigill:
 	do_exit(SIGILL);
+	return -EINVAL;
+
 sigsegv:
 	force_sigsegv(signo, current);
+	return -EFAULT;
 }
 
-static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
-			     unsigned long signr, sigset_t *oldset,
-			     siginfo_t *info)
+static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
+			    unsigned long signr, sigset_t *oldset,
+			    siginfo_t *info)
 {
 	struct rt_signal_frame32 __user *sf;
 	int sigframe_size;
@@ -685,12 +727,7 @@
 	if (ka->ka_restorer)
 		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
 	else {
-		/* Flush instruction space. */
 		unsigned long address = ((unsigned long)&(sf->insns[0]));
-		pgd_t *pgdp = pgd_offset(current->mm, address);
-		pud_t *pudp = pud_offset(pgdp, address);
-		pmd_t *pmdp = pmd_offset(pudp, address);
-		pte_t *ptep;
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 	
@@ -702,38 +739,32 @@
 		if (err)
 			goto sigsegv;
 
-		preempt_disable();
-		ptep = pte_offset_map(pmdp, address);
-		if (pte_present(*ptep)) {
-			unsigned long page = (unsigned long)
-				page_address(pte_page(*ptep));
-
-			wmb();
-			__asm__ __volatile__("flush	%0 + %1"
-					     : /* no outputs */
-					     : "r" (page),
-					       "r" (address & (PAGE_SIZE - 1))
-					     : "memory");
-		}
-		pte_unmap(ptep);
-		preempt_enable();
+		flush_signal_insns(address);
 	}
-	return;
+	return 0;
 
 sigill:
 	do_exit(SIGILL);
+	return -EINVAL;
+
 sigsegv:
 	force_sigsegv(signr, current);
+	return -EFAULT;
 }
 
-static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
-				   siginfo_t *info,
-				   sigset_t *oldset, struct pt_regs *regs)
+static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
+				  siginfo_t *info,
+				  sigset_t *oldset, struct pt_regs *regs)
 {
+	int err;
+
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame32(ka, regs, signr, oldset, info);
+		err = setup_rt_frame32(ka, regs, signr, oldset, info);
 	else
-		setup_frame32(ka, regs, signr, oldset);
+		err = setup_frame32(ka, regs, signr, oldset);
+
+	if (err)
+		return err;
 
 	spin_lock_irq(&current->sighand->siglock);
 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -741,6 +772,10 @@
 		sigaddset(&current->blocked,signr);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
+
+	tracehook_signal_handler(signr, info, ka, regs, 0);
+
+	return 0;
 }
 
 static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
@@ -787,16 +822,14 @@
 	if (signr > 0) {
 		if (restart_syscall)
 			syscall_restart32(orig_i0, regs, &ka.sa);
-		handle_signal32(signr, &ka, &info, oldset, regs);
-
-		/* A signal was successfully delivered; the saved
-		 * sigmask will have been stored in the signal frame,
-		 * and will be restored by sigreturn, so we can simply
-		 * clear the TS_RESTORE_SIGMASK flag.
-		 */
-		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-		tracehook_signal_handler(signr, &info, &ka, regs, 0);
+		if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) {
+			/* A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TS_RESTORE_SIGMASK flag.
+			 */
+			current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+		}
 		return;
 	}
 	if (restart_syscall &&
@@ -807,12 +840,14 @@
 		regs->u_regs[UREG_I0] = orig_i0;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 	if (restart_syscall &&
 	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
 		regs->u_regs[UREG_G1] = __NR_restart_syscall;
 		regs->tpc -= 4;
 		regs->tnpc -= 4;
+		pt_regs_clear_syscall(regs);
 	}
 
 	/* If there's no signal to deliver, we just put the saved sigmask
--- linux-ec2-2.6.32.orig/arch/sparc/lib/mcount.S
+++ linux-ec2-2.6.32/arch/sparc/lib/mcount.S
@@ -64,8 +64,9 @@
 2:	 sethi		%hi(softirq_stack), %g3
 	or		%g3, %lo(softirq_stack), %g3
 	ldx		[%g3 + %g1], %g7
+	sub		%g7, STACK_BIAS, %g7
 	cmp		%sp, %g7
-	bleu,pt		%xcc, 2f
+	bleu,pt		%xcc, 3f
 	 sethi		%hi(THREAD_SIZE), %g3
 	add		%g7, %g3, %g7
 	cmp		%sp, %g7
@@ -75,7 +76,7 @@
 	 * again, we are already trying to output the stack overflow
 	 * message.
 	 */
-	sethi		%hi(ovstack), %g7		! cant move to panic stack fast enough
+3:	sethi		%hi(ovstack), %g7		! cant move to panic stack fast enough
 	 or		%g7, %lo(ovstack), %g7
 	add		%g7, OVSTACKSIZE, %g3
 	sub		%g3, STACK_BIAS + 192, %g3
--- linux-ec2-2.6.32.orig/arch/sparc/prom/devops_64.c
+++ linux-ec2-2.6.32/arch/sparc/prom/devops_64.c
@@ -18,16 +18,32 @@
 int
 prom_devopen(const char *dstr)
 {
-	return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
-				  P1275_INOUT(1,1),
-				  dstr);
+	unsigned long args[5];
+
+	args[0] = (unsigned long) "open";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned long) dstr;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[4];
 }
 
 /* Close the device described by device handle 'dhandle'. */
 int
 prom_devclose(int dhandle)
 {
-	p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
+	unsigned long args[4];
+
+	args[0] = (unsigned long) "close";
+	args[1] = 1;
+	args[2] = 0;
+	args[3] = (unsigned int) dhandle;
+
+	p1275_cmd_direct(args);
+
 	return 0;
 }
 
@@ -37,5 +53,15 @@
 void
 prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
 {
-	p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
+	unsigned long args[7];
+
+	args[0] = (unsigned long) "seek";
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) dhandle;
+	args[4] = seekhi;
+	args[5] = seeklo;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
 }
--- linux-ec2-2.6.32.orig/arch/sparc/prom/console_64.c
+++ linux-ec2-2.6.32/arch/sparc/prom/console_64.c
@@ -21,14 +21,22 @@
 inline int
 prom_nbgetchar(void)
 {
+	unsigned long args[7];
 	char inc;
 
-	if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
-			      P1275_INOUT(3,1),
-			      prom_stdin, &inc, P1275_SIZE(1)) == 1)
+	args[0] = (unsigned long) "read";
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) prom_stdin;
+	args[4] = (unsigned long) &inc;
+	args[5] = 1;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	if (args[6] == 1)
 		return inc;
-	else
-		return -1;
+	return -1;
 }
 
 /* Non blocking put character to console device, returns -1 if
@@ -37,12 +45,22 @@
 inline int
 prom_nbputchar(char c)
 {
+	unsigned long args[7];
 	char outc;
 	
 	outc = c;
-	if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
-			       P1275_INOUT(3,1),
-			       prom_stdout, &outc, P1275_SIZE(1)) == 1)
+
+	args[0] = (unsigned long) "write";
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) prom_stdout;
+	args[4] = (unsigned long) &outc;
+	args[5] = 1;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	if (args[6] == 1)
 		return 0;
 	else
 		return -1;
@@ -68,7 +86,15 @@
 void
 prom_puts(const char *s, int len)
 {
-	p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
-			   P1275_INOUT(3,1),
-			   prom_stdout, s, P1275_SIZE(len));
+	unsigned long args[7];
+
+	args[0] = (unsigned long) "write";
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) prom_stdout;
+	args[4] = (unsigned long) s;
+	args[5] = len;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
 }
--- linux-ec2-2.6.32.orig/arch/sparc/prom/tree_64.c
+++ linux-ec2-2.6.32/arch/sparc/prom/tree_64.c
@@ -16,22 +16,39 @@
 #include <asm/oplib.h>
 #include <asm/ldc.h>
 
+static int prom_node_to_node(const char *type, int node)
+{
+	unsigned long args[5];
+
+	args[0] = (unsigned long) type;
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[4];
+}
+
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
 inline int __prom_getchild(int node)
 {
-	return p1275_cmd ("child", P1275_INOUT(1, 1), node);
+	return prom_node_to_node("child", node);
 }
 
 inline int prom_getchild(int node)
 {
 	int cnode;
 
-	if(node == -1) return 0;
+	if (node == -1)
+		return 0;
 	cnode = __prom_getchild(node);
-	if(cnode == -1) return 0;
-	return (int)cnode;
+	if (cnode == -1)
+		return 0;
+	return cnode;
 }
 EXPORT_SYMBOL(prom_getchild);
 
@@ -39,10 +56,12 @@
 {
 	int cnode;
 
-	if(node == -1) return 0;
-	cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
-	if(cnode == -1) return 0;
-	return (int)cnode;
+	if (node == -1)
+		return 0;
+	cnode = prom_node_to_node("parent", node);
+	if (cnode == -1)
+		return 0;
+	return cnode;
 }
 
 /* Return the next sibling of node 'node' or zero if no more siblings
@@ -50,7 +69,7 @@
  */
 inline int __prom_getsibling(int node)
 {
-	return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
+	return prom_node_to_node(prom_peer_name, node);
 }
 
 inline int prom_getsibling(int node)
@@ -72,11 +91,21 @@
  */
 inline int prom_getproplen(int node, const char *prop)
 {
-	if((!node) || (!prop)) return -1;
-	return p1275_cmd ("getproplen", 
-			  P1275_ARG(1,P1275_ARG_IN_STRING)|
-			  P1275_INOUT(2, 1), 
-			  node, prop);
+	unsigned long args[6];
+
+	if (!node || !prop)
+		return -1;
+
+	args[0] = (unsigned long) "getproplen";
+	args[1] = 2;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = (unsigned long) prop;
+	args[5] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[5];
 }
 EXPORT_SYMBOL(prom_getproplen);
 
@@ -87,19 +116,25 @@
 inline int prom_getproperty(int node, const char *prop,
 			    char *buffer, int bufsize)
 {
+	unsigned long args[8];
 	int plen;
 
 	plen = prom_getproplen(node, prop);
-	if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
+	if ((plen > bufsize) || (plen == 0) || (plen == -1))
 		return -1;
-	} else {
-		/* Ok, things seem all right. */
-		return p1275_cmd(prom_getprop_name, 
-				 P1275_ARG(1,P1275_ARG_IN_STRING)|
-				 P1275_ARG(2,P1275_ARG_OUT_BUF)|
-				 P1275_INOUT(4, 1), 
-				 node, prop, buffer, P1275_SIZE(plen));
-	}
+
+	args[0] = (unsigned long) prom_getprop_name;
+	args[1] = 4;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = (unsigned long) prop;
+	args[5] = (unsigned long) buffer;
+	args[6] = bufsize;
+	args[7] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[7];
 }
 EXPORT_SYMBOL(prom_getproperty);
 
@@ -110,7 +145,7 @@
 {
 	int intprop;
 
-	if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
+	if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
 		return intprop;
 
 	return -1;
@@ -126,7 +161,8 @@
 	int retval;
 
 	retval = prom_getint(node, property);
-	if(retval == -1) return deflt;
+	if (retval == -1)
+		return deflt;
 
 	return retval;
 }
@@ -138,7 +174,8 @@
 	int retval;
 
 	retval = prom_getproplen(node, prop);
-	if(retval == -1) return 0;
+	if (retval == -1)
+		return 0;
 	return 1;
 }
 EXPORT_SYMBOL(prom_getbool);
@@ -152,7 +189,8 @@
 	int len;
 
 	len = prom_getproperty(node, prop, user_buf, ubuf_size);
-	if(len != -1) return;
+	if (len != -1)
+		return;
 	user_buf[0] = 0;
 	return;
 }
@@ -165,7 +203,8 @@
 {
 	char namebuf[128];
 	prom_getproperty(node, "name", namebuf, sizeof(namebuf));
-	if(strcmp(namebuf, name) == 0) return 1;
+	if (strcmp(namebuf, name) == 0)
+		return 1;
 	return 0;
 }
 
@@ -191,16 +230,29 @@
 }
 EXPORT_SYMBOL(prom_searchsiblings);
 
+static const char *prom_nextprop_name = "nextprop";
+
 /* Return the first property type for node 'node'.
  * buffer should be at least 32B in length
  */
 inline char *prom_firstprop(int node, char *buffer)
 {
+	unsigned long args[7];
+
 	*buffer = 0;
-	if(node == -1) return buffer;
-	p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
-			       P1275_INOUT(3, 0), 
-			       node, (char *) 0x0, buffer);
+	if (node == -1)
+		return buffer;
+
+	args[0] = (unsigned long) prom_nextprop_name;
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = 0;
+	args[5] = (unsigned long) buffer;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
 	return buffer;
 }
 EXPORT_SYMBOL(prom_firstprop);
@@ -211,9 +263,10 @@
  */
 inline char *prom_nextprop(int node, const char *oprop, char *buffer)
 {
+	unsigned long args[7];
 	char buf[32];
 
-	if(node == -1) {
+	if (node == -1) {
 		*buffer = 0;
 		return buffer;
 	}
@@ -221,10 +274,17 @@
 		strcpy (buf, oprop);
 		oprop = buf;
 	}
-	p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
-				    P1275_ARG(2,P1275_ARG_OUT_32B)|
-				    P1275_INOUT(3, 0), 
-				    node, oprop, buffer); 
+
+	args[0] = (unsigned long) prom_nextprop_name;
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = (unsigned long) oprop;
+	args[5] = (unsigned long) buffer;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
 	return buffer;
 }
 EXPORT_SYMBOL(prom_nextprop);
@@ -232,12 +292,19 @@
 int
 prom_finddevice(const char *name)
 {
+	unsigned long args[5];
+
 	if (!name)
 		return 0;
-	return p1275_cmd(prom_finddev_name,
-			 P1275_ARG(0,P1275_ARG_IN_STRING)|
-			 P1275_INOUT(1, 1), 
-			 name);
+	args[0] = (unsigned long) "finddevice";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned long) name;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[4];
 }
 EXPORT_SYMBOL(prom_finddevice);
 
@@ -248,7 +315,7 @@
 	*buf = 0;
 	do {
 		prom_nextprop(node, buf, buf);
-		if(!strcmp(buf, prop))
+		if (!strcmp(buf, prop))
 			return 1;
 	} while (*buf);
 	return 0;
@@ -261,6 +328,8 @@
 int
 prom_setprop(int node, const char *pname, char *value, int size)
 {
+	unsigned long args[8];
+
 	if (size == 0)
 		return 0;
 	if ((pname == 0) || (value == 0))
@@ -272,19 +341,37 @@
 		return 0;
 	}
 #endif
-	return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
-					  P1275_ARG(2,P1275_ARG_IN_BUF)|
-					  P1275_INOUT(4, 1), 
-					  node, pname, value, P1275_SIZE(size));
+	args[0] = (unsigned long) "setprop";
+	args[1] = 4;
+	args[2] = 1;
+	args[3] = (unsigned int) node;
+	args[4] = (unsigned long) pname;
+	args[5] = (unsigned long) value;
+	args[6] = size;
+	args[7] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[7];
 }
 EXPORT_SYMBOL(prom_setprop);
 
 inline int prom_inst2pkg(int inst)
 {
+	unsigned long args[5];
 	int node;
 	
-	node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
-	if (node == -1) return 0;
+	args[0] = (unsigned long) "instance-to-package";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned int) inst;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	node = (int) args[4];
+	if (node == -1)
+		return 0;
 	return node;
 }
 
@@ -297,17 +384,28 @@
 	int node, inst;
 
 	inst = prom_devopen (path);
-	if (inst == 0) return 0;
-	node = prom_inst2pkg (inst);
-	prom_devclose (inst);
-	if (node == -1) return 0;
+	if (inst == 0)
+		return 0;
+	node = prom_inst2pkg(inst);
+	prom_devclose(inst);
+	if (node == -1)
+		return 0;
 	return node;
 }
 
 int prom_ihandle2path(int handle, char *buffer, int bufsize)
 {
-	return p1275_cmd("instance-to-path",
-			 P1275_ARG(1,P1275_ARG_OUT_BUF)|
-			 P1275_INOUT(3, 1),
-			 handle, buffer, P1275_SIZE(bufsize));
+	unsigned long args[7];
+
+	args[0] = (unsigned long) "instance-to-path";
+	args[1] = 3;
+	args[2] = 1;
+	args[3] = (unsigned int) handle;
+	args[4] = (unsigned long) buffer;
+	args[5] = bufsize;
+	args[6] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[6];
 }
--- linux-ec2-2.6.32.orig/arch/sparc/prom/p1275.c
+++ linux-ec2-2.6.32/arch/sparc/prom/p1275.c
@@ -22,126 +22,32 @@
 	long prom_callback;			/* 0x00 */
 	void (*prom_cif_handler)(long *);	/* 0x08 */
 	unsigned long prom_cif_stack;		/* 0x10 */
-	unsigned long prom_args [23];		/* 0x18 */
-	char prom_buffer [3000];
 } p1275buf;
 
 extern void prom_world(int);
 
-extern void prom_cif_interface(void);
+extern void prom_cif_direct(unsigned long *args);
 extern void prom_cif_callback(void);
 
 /*
- * This provides SMP safety on the p1275buf. prom_callback() drops this lock
- * to allow recursuve acquisition.
+ * This provides SMP safety on the p1275buf.
  */
 DEFINE_SPINLOCK(prom_entry_lock);
 
-long p1275_cmd(const char *service, long fmt, ...)
+void p1275_cmd_direct(unsigned long *args)
 {
-	char *p, *q;
 	unsigned long flags;
-	int nargs, nrets, i;
-	va_list list;
-	long attrs, x;
-	
-	p = p1275buf.prom_buffer;
-
-	spin_lock_irqsave(&prom_entry_lock, flags);
-
-	p1275buf.prom_args[0] = (unsigned long)p;		/* service */
-	strcpy (p, service);
-	p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
-	p1275buf.prom_args[1] = nargs = (fmt & 0x0f);		/* nargs */
-	p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); 	/* nrets */
-	attrs = fmt >> 8;
-	va_start(list, fmt);
-	for (i = 0; i < nargs; i++, attrs >>= 3) {
-		switch (attrs & 0x7) {
-		case P1275_ARG_NUMBER:
-			p1275buf.prom_args[i + 3] =
-						(unsigned)va_arg(list, long);
-			break;
-		case P1275_ARG_IN_64B:
-			p1275buf.prom_args[i + 3] =
-				va_arg(list, unsigned long);
-			break;
-		case P1275_ARG_IN_STRING:
-			strcpy (p, va_arg(list, char *));
-			p1275buf.prom_args[i + 3] = (unsigned long)p;
-			p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
-			break;
-		case P1275_ARG_OUT_BUF:
-			(void) va_arg(list, char *);
-			p1275buf.prom_args[i + 3] = (unsigned long)p;
-			x = va_arg(list, long);
-			i++; attrs >>= 3;
-			p = (char *)(((long)(p + (int)x + 7)) & ~7);
-			p1275buf.prom_args[i + 3] = x;
-			break;
-		case P1275_ARG_IN_BUF:
-			q = va_arg(list, char *);
-			p1275buf.prom_args[i + 3] = (unsigned long)p;
-			x = va_arg(list, long);
-			i++; attrs >>= 3;
-			memcpy (p, q, (int)x);
-			p = (char *)(((long)(p + (int)x + 7)) & ~7);
-			p1275buf.prom_args[i + 3] = x;
-			break;
-		case P1275_ARG_OUT_32B:
-			(void) va_arg(list, char *);
-			p1275buf.prom_args[i + 3] = (unsigned long)p;
-			p += 32;
-			break;
-		case P1275_ARG_IN_FUNCTION:
-			p1275buf.prom_args[i + 3] =
-					(unsigned long)prom_cif_callback;
-			p1275buf.prom_callback = va_arg(list, long);
-			break;
-		}
-	}
-	va_end(list);
+
+	raw_local_save_flags(flags);
+	raw_local_irq_restore(PIL_NMI);
+	spin_lock(&prom_entry_lock);
 
 	prom_world(1);
-	prom_cif_interface();
+	prom_cif_direct(args);
 	prom_world(0);
 
-	attrs = fmt >> 8;
-	va_start(list, fmt);
-	for (i = 0; i < nargs; i++, attrs >>= 3) {
-		switch (attrs & 0x7) {
-		case P1275_ARG_NUMBER:
-			(void) va_arg(list, long);
-			break;
-		case P1275_ARG_IN_STRING:
-			(void) va_arg(list, char *);
-			break;
-		case P1275_ARG_IN_FUNCTION:
-			(void) va_arg(list, long);
-			break;
-		case P1275_ARG_IN_BUF:
-			(void) va_arg(list, char *);
-			(void) va_arg(list, long);
-			i++; attrs >>= 3;
-			break;
-		case P1275_ARG_OUT_BUF:
-			p = va_arg(list, char *);
-			x = va_arg(list, long);
-			memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
-			i++; attrs >>= 3;
-			break;
-		case P1275_ARG_OUT_32B:
-			p = va_arg(list, char *);
-			memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
-			break;
-		}
-	}
-	va_end(list);
-	x = p1275buf.prom_args [nargs + 3];
-
-	spin_unlock_irqrestore(&prom_entry_lock, flags);
-
-	return x;
+	spin_unlock(&prom_entry_lock);
+	raw_local_irq_restore(flags);
 }
 
 void prom_cif_init(void *cif_handler, void *cif_stack)
--- linux-ec2-2.6.32.orig/arch/sparc/prom/cif.S
+++ linux-ec2-2.6.32/arch/sparc/prom/cif.S
@@ -9,18 +9,18 @@
 #include <asm/thread_info.h>
 
 	.text
-	.globl	prom_cif_interface
-prom_cif_interface:
-	sethi	%hi(p1275buf), %o0
-	or	%o0, %lo(p1275buf), %o0
-	ldx	[%o0 + 0x010], %o1	! prom_cif_stack
-	save	%o1, -192, %sp
-	ldx	[%i0 + 0x008], %l2	! prom_cif_handler
+	.globl	prom_cif_direct
+prom_cif_direct:
+	sethi	%hi(p1275buf), %o1
+	or	%o1, %lo(p1275buf), %o1
+	ldx	[%o1 + 0x0010], %o2	! prom_cif_stack
+	save	%o2, -192, %sp
+	ldx	[%i1 + 0x0008], %l2	! prom_cif_handler
 	mov	%g4, %l0
 	mov	%g5, %l1
 	mov	%g6, %l3
 	call	%l2
-	 add	%i0, 0x018, %o0		! prom_args
+	 mov	%i0, %o0		! prom_args
 	mov	%l0, %g4
 	mov	%l1, %g5
 	mov	%l3, %g6
--- linux-ec2-2.6.32.orig/arch/sparc/prom/misc_64.c
+++ linux-ec2-2.6.32/arch/sparc/prom/misc_64.c
@@ -20,10 +20,17 @@
 
 int prom_service_exists(const char *service_name)
 {
-	int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
-			    P1275_INOUT(1, 1), service_name);
+	unsigned long args[5];
 
-	if (err)
+	args[0] = (unsigned long) "test";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned long) service_name;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	if (args[4])
 		return 0;
 	return 1;
 }
@@ -31,30 +38,47 @@
 void prom_sun4v_guest_soft_state(void)
 {
 	const char *svc = "SUNW,soft-state-supported";
+	unsigned long args[3];
 
 	if (!prom_service_exists(svc))
 		return;
-	p1275_cmd(svc, P1275_INOUT(0, 0));
+	args[0] = (unsigned long) svc;
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 }
 
 /* Reset and reboot the machine with the command 'bcommand'. */
 void prom_reboot(const char *bcommand)
 {
+	unsigned long args[4];
+
 #ifdef CONFIG_SUN_LDOMS
 	if (ldom_domaining_enabled)
 		ldom_reboot(bcommand);
 #endif
-	p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
-		  P1275_INOUT(1, 0), bcommand);
+	args[0] = (unsigned long) "boot";
+	args[1] = 1;
+	args[2] = 0;
+	args[3] = (unsigned long) bcommand;
+
+	p1275_cmd_direct(args);
 }
 
 /* Forth evaluate the expression contained in 'fstring'. */
 void prom_feval(const char *fstring)
 {
+	unsigned long args[5];
+
 	if (!fstring || fstring[0] == 0)
 		return;
-	p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
-		  P1275_INOUT(1, 1), fstring);
+	args[0] = (unsigned long) "interpret";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned long) fstring;
+	args[4] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
 }
 EXPORT_SYMBOL(prom_feval);
 
@@ -68,6 +92,7 @@
  */
 void prom_cmdline(void)
 {
+	unsigned long args[3];
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -76,7 +101,11 @@
 	smp_capture();
 #endif
 
-	p1275_cmd("enter", P1275_INOUT(0, 0));
+	args[0] = (unsigned long) "enter";
+	args[1] = 0;
+	args[2] = 0;
+
+	p1275_cmd_direct(args);
 
 #ifdef CONFIG_SMP
 	smp_release();
@@ -90,22 +119,32 @@
  */
 void notrace prom_halt(void)
 {
+	unsigned long args[3];
+
 #ifdef CONFIG_SUN_LDOMS
 	if (ldom_domaining_enabled)
 		ldom_power_off();
 #endif
 again:
-	p1275_cmd("exit", P1275_INOUT(0, 0));
+	args[0] = (unsigned long) "exit";
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 	goto again; /* PROM is out to get me -DaveM */
 }
 
 void prom_halt_power_off(void)
 {
+	unsigned long args[3];
+
 #ifdef CONFIG_SUN_LDOMS
 	if (ldom_domaining_enabled)
 		ldom_power_off();
 #endif
-	p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
+	args[0] = (unsigned long) "SUNW,power-off";
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 
 	/* if nothing else helps, we just halt */
 	prom_halt();
@@ -114,10 +153,15 @@
 /* Set prom sync handler to call function 'funcp'. */
 void prom_setcallback(callback_func_t funcp)
 {
+	unsigned long args[5];
 	if (!funcp)
 		return;
-	p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
-		  P1275_INOUT(1, 1), funcp);
+	args[0] = (unsigned long) "set-callback";
+	args[1] = 1;
+	args[2] = 1;
+	args[3] = (unsigned long) funcp;
+	args[4] = (unsigned long) -1;
+	p1275_cmd_direct(args);
 }
 
 /* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
@@ -173,57 +217,61 @@
 }
 
 /* Load explicit I/D TLB entries. */
+static long tlb_load(const char *type, unsigned long index,
+		     unsigned long tte_data, unsigned long vaddr)
+{
+	unsigned long args[9];
+
+	args[0] = (unsigned long) prom_callmethod_name;
+	args[1] = 5;
+	args[2] = 1;
+	args[3] = (unsigned long) type;
+	args[4] = (unsigned int) prom_get_mmu_ihandle();
+	args[5] = vaddr;
+	args[6] = tte_data;
+	args[7] = index;
+	args[8] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (long) args[8];
+}
+
 long prom_itlb_load(unsigned long index,
 		    unsigned long tte_data,
 		    unsigned long vaddr)
 {
-	return p1275_cmd(prom_callmethod_name,
-			 (P1275_ARG(0, P1275_ARG_IN_STRING) |
-			  P1275_ARG(2, P1275_ARG_IN_64B) |
-			  P1275_ARG(3, P1275_ARG_IN_64B) |
-			  P1275_INOUT(5, 1)),
-			 "SUNW,itlb-load",
-			 prom_get_mmu_ihandle(),
-			 /* And then our actual args are pushed backwards. */
-			 vaddr,
-			 tte_data,
-			 index);
+	return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
 }
 
 long prom_dtlb_load(unsigned long index,
 		    unsigned long tte_data,
 		    unsigned long vaddr)
 {
-	return p1275_cmd(prom_callmethod_name,
-			 (P1275_ARG(0, P1275_ARG_IN_STRING) |
-			  P1275_ARG(2, P1275_ARG_IN_64B) |
-			  P1275_ARG(3, P1275_ARG_IN_64B) |
-			  P1275_INOUT(5, 1)),
-			 "SUNW,dtlb-load",
-			 prom_get_mmu_ihandle(),
-			 /* And then our actual args are pushed backwards. */
-			 vaddr,
-			 tte_data,
-			 index);
+	return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
 }
 
 int prom_map(int mode, unsigned long size,
 	     unsigned long vaddr, unsigned long paddr)
 {
-	int ret = p1275_cmd(prom_callmethod_name,
-			    (P1275_ARG(0, P1275_ARG_IN_STRING) |
-			     P1275_ARG(3, P1275_ARG_IN_64B) |
-			     P1275_ARG(4, P1275_ARG_IN_64B) |
-			     P1275_ARG(6, P1275_ARG_IN_64B) |
-			     P1275_INOUT(7, 1)),
-			    prom_map_name,
-			    prom_get_mmu_ihandle(),
-			    mode,
-			    size,
-			    vaddr,
-			    0,
-			    paddr);
+	unsigned long args[11];
+	int ret;
 
+	args[0] = (unsigned long) prom_callmethod_name;
+	args[1] = 7;
+	args[2] = 1;
+	args[3] = (unsigned long) prom_map_name;
+	args[4] = (unsigned int) prom_get_mmu_ihandle();
+	args[5] = (unsigned int) mode;
+	args[6] = size;
+	args[7] = vaddr;
+	args[8] = 0;
+	args[9] = paddr;
+	args[10] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	ret = (int) args[10];
 	if (ret == 0)
 		ret = -1;
 	return ret;
@@ -231,40 +279,51 @@
 
 void prom_unmap(unsigned long size, unsigned long vaddr)
 {
-	p1275_cmd(prom_callmethod_name,
-		  (P1275_ARG(0, P1275_ARG_IN_STRING) |
-		   P1275_ARG(2, P1275_ARG_IN_64B) |
-		   P1275_ARG(3, P1275_ARG_IN_64B) |
-		   P1275_INOUT(4, 0)),
-		  prom_unmap_name,
-		  prom_get_mmu_ihandle(),
-		  size,
-		  vaddr);
+	unsigned long args[7];
+
+	args[0] = (unsigned long) prom_callmethod_name;
+	args[1] = 4;
+	args[2] = 0;
+	args[3] = (unsigned long) prom_unmap_name;
+	args[4] = (unsigned int) prom_get_mmu_ihandle();
+	args[5] = size;
+	args[6] = vaddr;
+
+	p1275_cmd_direct(args);
 }
 
 /* Set aside physical memory which is not touched or modified
  * across soft resets.
  */
-unsigned long prom_retain(const char *name,
-			  unsigned long pa_low, unsigned long pa_high,
-			  long size, long align)
-{
-	/* XXX I don't think we return multiple values correctly.
-	 * XXX OBP supposedly returns pa_low/pa_high here, how does
-	 * XXX it work?
-	 */
+int prom_retain(const char *name, unsigned long size,
+		unsigned long align, unsigned long *paddr)
+{
+	unsigned long args[11];
 
-	/* If align is zero, the pa_low/pa_high args are passed,
-	 * else they are not.
+	args[0] = (unsigned long) prom_callmethod_name;
+	args[1] = 5;
+	args[2] = 3;
+	args[3] = (unsigned long) "SUNW,retain";
+	args[4] = (unsigned int) prom_get_memory_ihandle();
+	args[5] = align;
+	args[6] = size;
+	args[7] = (unsigned long) name;
+	args[8] = (unsigned long) -1;
+	args[9] = (unsigned long) -1;
+	args[10] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	if (args[8])
+		return (int) args[8];
+
+	/* Next we get "phys_high" then "phys_low".  On 64-bit
+	 * the phys_high cell is don't care since the phys_low
+	 * cell has the full value.
 	 */
-	if (align == 0)
-		return p1275_cmd("SUNW,retain",
-				 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
-				 name, pa_low, pa_high, size, align);
-	else
-		return p1275_cmd("SUNW,retain",
-				 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
-				 name, size, align);
+	*paddr = args[10];
+
+	return 0;
 }
 
 /* Get "Unumber" string for the SIMM at the given
@@ -277,62 +336,129 @@
 		    unsigned long phys_addr,
 		    char *buf, int buflen)
 {
-	return p1275_cmd(prom_callmethod_name,
-			 (P1275_ARG(0, P1275_ARG_IN_STRING)	|
-			  P1275_ARG(3, P1275_ARG_OUT_BUF)	|
-			  P1275_ARG(6, P1275_ARG_IN_64B)	|
-			  P1275_INOUT(8, 2)),
-			 "SUNW,get-unumber", prom_get_memory_ihandle(),
-			 buflen, buf, P1275_SIZE(buflen),
-			 0, phys_addr, syndrome_code);
+	unsigned long args[12];
+
+	args[0] = (unsigned long) prom_callmethod_name;
+	args[1] = 7;
+	args[2] = 2;
+	args[3] = (unsigned long) "SUNW,get-unumber";
+	args[4] = (unsigned int) prom_get_memory_ihandle();
+	args[5] = buflen;
+	args[6] = (unsigned long) buf;
+	args[7] = 0;
+	args[8] = phys_addr;
+	args[9] = (unsigned int) syndrome_code;
+	args[10] = (unsigned long) -1;
+	args[11] = (unsigned long) -1;
+
+	p1275_cmd_direct(args);
+
+	return (int) args[10];
 }
 
 /* Power management extensions. */
 void prom_sleepself(void)
 {
-	p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
+	unsigned long args[3];
+
+	args[0] = (unsigned long) "SUNW,sleep-self";
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 }
 
 int prom_sleepsystem(void)
 {
-	return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
+	unsigned long args[4];
+
+	args[0] = (unsigned long) "SUNW,sleep-system";
+	args[1] = 0;
+	args[2] = 1;
+	args[3] = (unsigned long) -1;
+	p1275_cmd_direct(args);
+
+	return (int) args[3];
 }
 
 int prom_wakeupsystem(void)
 {
-	return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
+	unsigned long args[4];
+
+	args[0] = (unsigned long) "SUNW,wakeup-system";
+	args[1] = 0;
+	args[2] = 1;
+	args[3] = (unsigned long) -1;
+	p1275_cmd_direct(args);
+
+	return (int) args[3];
 }
 
 #ifdef CONFIG_SMP
 void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
 {
-	p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
+	unsigned long args[6];
+
+	args[0] = (unsigned long) "SUNW,start-cpu";
+	args[1] = 3;
+	args[2] = 0;
+	args[3] = (unsigned int) cpunode;
+	args[4] = pc;
+	args[5] = arg;
+	p1275_cmd_direct(args);
 }
 
 void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
 {
-	p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
-		  cpuid, pc, arg);
+	unsigned long args[6];
+
+	args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
+	args[1] = 3;
+	args[2] = 0;
+	args[3] = (unsigned int) cpuid;
+	args[4] = pc;
+	args[5] = arg;
+	p1275_cmd_direct(args);
 }
 
 void prom_stopcpu_cpuid(int cpuid)
 {
-	p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
-		  cpuid);
+	unsigned long args[4];
+
+	args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
+	args[1] = 1;
+	args[2] = 0;
+	args[3] = (unsigned int) cpuid;
+	p1275_cmd_direct(args);
 }
 
 void prom_stopself(void)
 {
-	p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
+	unsigned long args[3];
+
+	args[0] = (unsigned long) "SUNW,stop-self";
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 }
 
 void prom_idleself(void)
 {
-	p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
+	unsigned long args[3];
+
+	args[0] = (unsigned long) "SUNW,idle-self";
+	args[1] = 0;
+	args[2] = 0;
+	p1275_cmd_direct(args);
 }
 
 void prom_resumecpu(int cpunode)
 {
-	p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
+	unsigned long args[4];
+
+	args[0] = (unsigned long) "SUNW,resume-cpu";
+	args[1] = 1;
+	args[2] = 0;
+	args[3] = (unsigned int) cpunode;
+	p1275_cmd_direct(args);
 }
 #endif
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/page_32.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/page_32.h
@@ -143,7 +143,7 @@
 #define phys_to_virt		__va
 
 #define ARCH_PFN_OFFSET		(pfn_base)
-#define virt_to_page(kaddr)	(mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 
 #define pfn_valid(pfn)		(((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
 #define virt_addr_valid(kaddr)	((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/stat.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/stat.h
@@ -53,8 +53,8 @@
 	ino_t		st_ino;
 	mode_t		st_mode;
 	short		st_nlink;
-	uid_t		st_uid;
-	gid_t		st_gid;
+	unsigned short	st_uid;
+	unsigned short	st_gid;
 	unsigned short	st_rdev;
 	off_t		st_size;
 	time_t		st_atime;
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/oplib_64.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/oplib_64.h
@@ -185,9 +185,8 @@
 			   char *buf, int buflen);
 
 /* Retain physical memory to the caller across soft resets. */
-extern unsigned long prom_retain(const char *name,
-				 unsigned long pa_low, unsigned long pa_high,
-				 long size, long align);
+extern int prom_retain(const char *name, unsigned long size,
+		       unsigned long align, unsigned long *paddr);
 
 /* Load explicit I/D TLB entries into the calling processor. */
 extern long prom_itlb_load(unsigned long index,
@@ -287,26 +286,6 @@
 extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
 
 /* Client interface level routines. */
-extern long p1275_cmd(const char *, long, ...);
-
-#if 0
-#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
-#else
-#define P1275_SIZE(x) x
-#endif
-
-/* We support at most 16 input and 1 output argument */
-#define P1275_ARG_NUMBER		0
-#define P1275_ARG_IN_STRING		1
-#define P1275_ARG_OUT_BUF		2
-#define P1275_ARG_OUT_32B		3
-#define P1275_ARG_IN_FUNCTION		4
-#define P1275_ARG_IN_BUF		5
-#define P1275_ARG_IN_64B		6
-
-#define P1275_IN(x) ((x) & 0xf)
-#define P1275_OUT(x) (((x) << 4) & 0xf0)
-#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
-#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
+extern void p1275_cmd_direct(unsigned long *);
 
 #endif /* !(__SPARC64_OPLIB_H) */
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/thread_info_64.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/thread_info_64.h
@@ -227,12 +227,11 @@
 /* flag bit 8 is available */
 #define TIF_SECCOMP		9	/* secure computing */
 #define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
-/* flag bit 11 is available */
 /* NOTE: Thread flags >= 12 should be ones we have no interest
  *       in using in assembly, else we can't use the mask as
  *       an immediate value in instructions such as andcc.
  */
-#define TIF_ABI_PENDING		12
+/* flag bit 12 is available */
 #define TIF_MEMDIE		13
 #define TIF_POLLING_NRFLAG	14
 #define TIF_FREEZE		15	/* is freezing for suspend */
@@ -246,7 +245,6 @@
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/parport.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/parport.h
@@ -228,6 +228,10 @@
 		.name = "parallel",
 		.compatible = "ns87317-ecpp",
 	},
+	{
+		.name = "parallel",
+		.compatible = "pnpALI,1533,3",
+	},
 	{},
 };
 
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/atomic_64.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/atomic_64.h
@@ -20,14 +20,14 @@
 #define atomic64_set(v, i)	(((v)->counter) = i)
 
 extern void atomic_add(int, atomic_t *);
-extern void atomic64_add(int, atomic64_t *);
+extern void atomic64_add(long, atomic64_t *);
 extern void atomic_sub(int, atomic_t *);
-extern void atomic64_sub(int, atomic64_t *);
+extern void atomic64_sub(long, atomic64_t *);
 
 extern int atomic_add_ret(int, atomic_t *);
-extern int atomic64_add_ret(int, atomic64_t *);
+extern long atomic64_add_ret(long, atomic64_t *);
 extern int atomic_sub_ret(int, atomic_t *);
-extern int atomic64_sub_ret(int, atomic64_t *);
+extern long atomic64_sub_ret(long, atomic64_t *);
 
 #define atomic_dec_return(v) atomic_sub_ret(1, v)
 #define atomic64_dec_return(v) atomic64_sub_ret(1, v)
@@ -91,7 +91,7 @@
 	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 {
 	long c, old;
 	c = atomic64_read(v);
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/elf_64.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/elf_64.h
@@ -196,17 +196,10 @@
 #define ELF_PLATFORM	(NULL)
 
 #define SET_PERSONALITY(ex)				\
-do {	unsigned long new_flags = current_thread_info()->flags; \
-	new_flags &= _TIF_32BIT;			\
-	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
-		new_flags |= _TIF_32BIT;		\
+do {	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
+		set_thread_flag(TIF_32BIT);		\
 	else						\
-		new_flags &= ~_TIF_32BIT;		\
-	if ((current_thread_info()->flags & _TIF_32BIT) \
-	    != new_flags)				\
-		set_thread_flag(TIF_ABI_PENDING);	\
-	else						\
-		clear_thread_flag(TIF_ABI_PENDING);	\
+		clear_thread_flag(TIF_32BIT);		\
 	/* flush_thread will update pgd cache */	\
 	if (personality(current->personality) != PER_LINUX32)	\
 		set_personality(PER_LINUX |		\
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/rwsem-const.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/rwsem-const.h
@@ -5,7 +5,7 @@
 #define RWSEM_UNLOCKED_VALUE		0x00000000
 #define RWSEM_ACTIVE_BIAS		0x00000001
 #define RWSEM_ACTIVE_MASK		0x0000ffff
-#define RWSEM_WAITING_BIAS		0xffff0000
+#define RWSEM_WAITING_BIAS		(-0x00010000)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/io_64.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/io_64.h
@@ -468,10 +468,14 @@
 
 #define ioread8(X)			readb(X)
 #define ioread16(X)			readw(X)
+#define ioread16be(X)			__raw_readw(X)
 #define ioread32(X)			readl(X)
+#define ioread32be(X)			__raw_readl(X)
 #define iowrite8(val,X)			writeb(val,X)
 #define iowrite16(val,X)		writew(val,X)
+#define iowrite16be(val,X)		__raw_writew(val,X)
 #define iowrite32(val,X)		writel(val,X)
+#define iowrite32be(val,X)		__raw_writel(val,X)
 
 /* Create a virtual mapping cookie for an IO port range */
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/compat.h
@@ -166,7 +166,7 @@
 	return (u32)(unsigned long)uptr;
 }
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = current_thread_info()->kregs;
 	unsigned long usp = regs->u_regs[UREG_I6];
--- linux-ec2-2.6.32.orig/arch/sparc/include/asm/io_32.h
+++ linux-ec2-2.6.32/arch/sparc/include/asm/io_32.h
@@ -8,7 +8,7 @@
 #include <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 static inline u32 flip_dword (u32 l)
 {
@@ -249,10 +249,14 @@
 
 #define ioread8(X)			readb(X)
 #define ioread16(X)			readw(X)
+#define ioread16be(X)			__raw_readw(X)
 #define ioread32(X)			readl(X)
+#define ioread32be(X)			__raw_readl(X)
 #define iowrite8(val,X)			writeb(val,X)
 #define iowrite16(val,X)		writew(val,X)
+#define iowrite16be(val,X)		__raw_writew(val,X)
 #define iowrite32(val,X)		writel(val,X)
+#define iowrite32be(val,X)		__raw_writel(val,X)
 
 static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
 {
--- linux-ec2-2.6.32.orig/arch/sh/kernel/process_64.c
+++ linux-ec2-2.6.32/arch/sh/kernel/process_64.c
@@ -367,7 +367,7 @@
 void flush_thread(void)
 {
 
-	/* Called by fs/exec.c (flush_old_exec) to remove traces of a
+	/* Called by fs/exec.c (setup_new_exec) to remove traces of a
 	 * previously running executable. */
 #ifdef CONFIG_SH_FPU
 	if (last_task_used_math == current) {
--- linux-ec2-2.6.32.orig/arch/sh/kernel/smp.c
+++ linux-ec2-2.6.32/arch/sh/kernel/smp.c
@@ -69,6 +69,7 @@
 	unsigned int cpu;
 	struct mm_struct *mm = &init_mm;
 
+	enable_mmu();
 	atomic_inc(&mm->mm_count);
 	atomic_inc(&mm->mm_users);
 	current->active_mm = mm;
--- linux-ec2-2.6.32.orig/arch/sh/kernel/sys_sh.c
+++ linux-ec2-2.6.32/arch/sh/kernel/sys_sh.c
@@ -28,37 +28,13 @@
 #include <asm/cacheflush.h>
 #include <asm/cachectl.h>
 
-static inline long
-do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-	 unsigned long flags, int fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 asmlinkage int old_mmap(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags,
 	int fd, unsigned long off)
 {
 	if (off & ~PAGE_MASK)
 		return -EINVAL;
-	return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
 }
 
 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
@@ -74,7 +50,7 @@
 
 	pgoff >>= PAGE_SHIFT - 12;
 
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
 /*
--- linux-ec2-2.6.32.orig/arch/sh/boot/compressed/misc.c
+++ linux-ec2-2.6.32/arch/sh/boot/compressed/misc.c
@@ -132,7 +132,7 @@
 	output_addr = (CONFIG_MEMORY_START + 0x2000);
 #else
 	output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
-#ifdef CONFIG_29BIT
+#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED)
 	output_addr |= P2SEG;
 #endif
 #endif
--- linux-ec2-2.6.32.orig/arch/sh/mm/mmap.c
+++ linux-ec2-2.6.32/arch/sh/mm/mmap.c
@@ -54,7 +54,8 @@
 		/* We do not accept a shared mapping if it would violate
 		 * cache aliasing constraints.
 		 */
-		if ((flags & MAP_SHARED) && (addr & shm_align_mask))
+		if ((flags & MAP_SHARED) &&
+		    ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
 			return -EINVAL;
 		return addr;
 	}
--- linux-ec2-2.6.32.orig/arch/sh/include/asm/pgtable_32.h
+++ linux-ec2-2.6.32/arch/sh/include/asm/pgtable_32.h
@@ -344,7 +344,8 @@
 #define pte_special(pte)	((pte).pte_low & _PAGE_SPECIAL)
 
 #ifdef CONFIG_X2TLB
-#define pte_write(pte)		((pte).pte_high & _PAGE_EXT_USER_WRITE)
+#define pte_write(pte) \
+	((pte).pte_high & (_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE))
 #else
 #define pte_write(pte)		((pte).pte_low & _PAGE_RW)
 #endif
@@ -358,7 +359,7 @@
  * individually toggled (and user permissions are entirely decoupled from
  * kernel permissions), we attempt to couple them a bit more sanely here.
  */
-PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
+PTE_BIT_FUNC(high, wrprotect, &= ~(_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE));
 PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
 PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
 #else
--- linux-ec2-2.6.32.orig/arch/sh/include/asm/elf.h
+++ linux-ec2-2.6.32/arch/sh/include/asm/elf.h
@@ -212,7 +212,9 @@
 
 #define VSYSCALL_AUX_ENT					\
 	if (vdso_enabled)					\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);	\
+	else							\
+		NEW_AUX_ENT(AT_IGNORE, 0);
 #else
 #define VSYSCALL_AUX_ENT
 #endif /* CONFIG_VSYSCALL */
@@ -220,7 +222,7 @@
 #ifdef CONFIG_SH_FPU
 #define FPU_AUX_ENT	NEW_AUX_ENT(AT_FPUCW, FPSCR_INIT)
 #else
-#define FPU_AUX_ENT
+#define FPU_AUX_ENT	NEW_AUX_ENT(AT_IGNORE, 0)
 #endif
 
 extern int l1i_cache_shape, l1d_cache_shape, l2_cache_shape;
--- linux-ec2-2.6.32.orig/arch/microblaze/Makefile
+++ linux-ec2-2.6.32/arch/microblaze/Makefile
@@ -69,12 +69,16 @@
 
 all: linux.bin
 
-BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.%
+# With make 3.82 we cannot mix normal and wildcard targets
+BOOT_TARGETS1 = linux.bin linux.bin.gz
+BOOT_TARGETS2 = simpleImage.%
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
-$(BOOT_TARGETS): vmlinux
+$(BOOT_TARGETS1): vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+$(BOOT_TARGETS2): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
--- linux-ec2-2.6.32.orig/arch/microblaze/kernel/sys_microblaze.c
+++ linux-ec2-2.6.32/arch/microblaze/kernel/sys_microblaze.c
@@ -62,46 +62,14 @@
 	return error;
 }
 
-asmlinkage long
-sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	struct file *file = NULL;
-	int ret = -EBADF;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file) {
-			printk(KERN_INFO "no fd in mmap\r\n");
-			goto out;
-		}
-	}
-
-	down_write(&current->mm->mmap_sem);
-	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
-out:
-	return ret;
-}
-
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, off_t pgoff)
 {
-	int err = -EINVAL;
-
-	if (pgoff & ~PAGE_MASK) {
-		printk(KERN_INFO "no pagemask in mmap\r\n");
-		goto out;
-	}
+	if (pgoff & ~PAGE_MASK)
+		return -EINVAL;
 
-	err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
-out:
-	return err;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 }
 
 /*
--- linux-ec2-2.6.32.orig/arch/microblaze/kernel/syscall_table.S
+++ linux-ec2-2.6.32/arch/microblaze/kernel/syscall_table.S
@@ -196,7 +196,7 @@
 	.long sys_ni_syscall		/* reserved for streams2 */
 	.long sys_vfork		/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap2			/* mmap2 */
+	.long sys_mmap_pgoff		/* mmap2 */
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64		/* 195 */
--- linux-ec2-2.6.32.orig/arch/score/kernel/sys_score.c
+++ linux-ec2-2.6.32/arch/score/kernel/sys_score.c
@@ -36,34 +36,16 @@
 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
 	  unsigned long flags, unsigned long fd, unsigned long pgoff)
 {
-	int error = -EBADF;
-	struct file *file = NULL;
-
-	if (pgoff & (~PAGE_MASK >> 12))
-		return -EINVAL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			return error;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-
-	return error;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
 asmlinkage long
 sys_mmap(unsigned long addr, unsigned long len, unsigned long prot,
-	unsigned long flags, unsigned long fd, off_t pgoff)
+	unsigned long flags, unsigned long fd, off_t offset)
 {
-	return sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
+	if (unlikely(offset & ~PAGE_MASK))
+		return -EINVAL;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 }
 
 asmlinkage long
--- linux-ec2-2.6.32.orig/arch/frv/kernel/sys_frv.c
+++ linux-ec2-2.6.32/arch/frv/kernel/sys_frv.c
@@ -31,9 +31,6 @@
 			  unsigned long prot, unsigned long flags,
 			  unsigned long fd, unsigned long pgoff)
 {
-	int error = -EBADF;
-	struct file * file = NULL;
-
 	/* As with sparc32, make sure the shift for mmap2 is constant
 	   (12), no matter what PAGE_SIZE we have.... */
 
@@ -41,69 +38,10 @@
 	   trying to map something we can't */
 	if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
 		return -EINVAL;
-	pgoff >>= PAGE_SHIFT - 12;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
-#if 0 /* DAVIDM - do we want this */
-struct mmap_arg_struct64 {
-	__u32 addr;
-	__u32 len;
-	__u32 prot;
-	__u32 flags;
-	__u64 offset; /* 64 bits */
-	__u32 fd;
-};
-
-asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg)
-{
-	int error = -EFAULT;
-	struct file * file = NULL;
-	struct mmap_arg_struct64 a;
-	unsigned long pgoff;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-
-	if ((long)a.offset & ~PAGE_MASK)
-		return -EINVAL;
-
-	pgoff = a.offset >> PAGE_SHIFT;
-	if ((a.offset >> PAGE_SHIFT) != pgoff)
-		return -EINVAL;
-
-	if (!(a.flags & MAP_ANONYMOUS)) {
-		error = -EBADF;
-		file = fget(a.fd);
-		if (!file)
-			goto out;
-	}
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-	if (file)
-		fput(file);
-out:
-	return error;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      pgoff >> (PAGE_SHIFT - 12));
 }
-#endif
 
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
--- linux-ec2-2.6.32.orig/arch/frv/include/asm/page.h
+++ linux-ec2-2.6.32/arch/frv/include/asm/page.h
@@ -63,12 +63,10 @@
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
 
-#ifdef CONFIG_MMU
 #define VM_DATA_DEFAULT_FLAGS \
 	(VM_READ | VM_WRITE | \
 	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
 		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#endif
 
 #endif /* __ASSEMBLY__ */
 
--- linux-ec2-2.6.32.orig/arch/frv/include/asm/cache.h
+++ linux-ec2-2.6.32/arch/frv/include/asm/cache.h
@@ -17,6 +17,8 @@
 #define L1_CACHE_SHIFT		(CONFIG_FRV_L1_CACHE_SHIFT)
 #define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
 
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+
 #define __cacheline_aligned	__attribute__((aligned(L1_CACHE_BYTES)))
 #define ____cacheline_aligned	__attribute__((aligned(L1_CACHE_BYTES)))
 
--- linux-ec2-2.6.32.orig/arch/ia64/Makefile
+++ linux-ec2-2.6.32/arch/ia64/Makefile
@@ -56,7 +56,7 @@
 core-$(CONFIG_IA64_SGI_SN2)	+= arch/ia64/sn/
 core-$(CONFIG_IA64_SGI_UV)	+= arch/ia64/uv/
 core-$(CONFIG_KVM) 		+= arch/ia64/kvm/
-core-$(CONFIG_XEN)		+= arch/ia64/xen/
+core-$(CONFIG_PARAVIRT_XEN)	+= arch/ia64/xen/
 
 drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)	+= arch/ia64/hp/sim/
--- linux-ec2-2.6.32.orig/arch/ia64/Kconfig
+++ linux-ec2-2.6.32/arch/ia64/Kconfig
@@ -231,7 +231,7 @@
 config IA64_XEN_GUEST
 	bool "Xen guest"
 	select SWIOTLB
-	depends on XEN
+	depends on PARAVIRT_XEN
 	help
 	  Build a kernel that runs on Xen guest domain. At this moment only
 	  16KB page size in supported.
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/time.c
+++ linux-ec2-2.6.32/arch/ia64/kernel/time.c
@@ -473,7 +473,7 @@
 {
 }
 
-void update_vsyscall(struct timespec *wall, struct clocksource *c)
+void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult)
 {
         unsigned long flags;
 
@@ -481,7 +481,7 @@
 
         /* copy fsyscall clock data */
         fsyscall_gtod_data.clk_mask = c->mask;
-        fsyscall_gtod_data.clk_mult = c->mult;
+        fsyscall_gtod_data.clk_mult = mult;
         fsyscall_gtod_data.clk_shift = c->shift;
         fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
         fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/vmlinux.lds.S
+++ linux-ec2-2.6.32/arch/ia64/kernel/vmlinux.lds.S
@@ -176,7 +176,7 @@
 	  __start_gate_section = .;
 	  *(.data.gate)
 	  __stop_gate_section = .;
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 	  . = ALIGN(PAGE_SIZE);
 	  __xen_start_gate_section = .;
 	  *(.data.gate.xen)
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/mca.c
+++ linux-ec2-2.6.32/arch/ia64/kernel/mca.c
@@ -1850,7 +1850,8 @@
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = __get_free_pages(GFP_KERNEL, get_order(sz));
+			data = (void *)__get_free_pages(GFP_KERNEL,
+							get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
 					cpu);
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/asm-offsets.c
+++ linux-ec2-2.6.32/arch/ia64/kernel/asm-offsets.c
@@ -290,7 +290,7 @@
 	DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
 		offsetof (struct itc_jitter_data_t, itc_lastcycle));
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 	BLANK();
 
 	DEFINE(XEN_NATIVE_ASM, XEN_NATIVE);
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/sys_ia64.c
+++ linux-ec2-2.6.32/arch/ia64/kernel/sys_ia64.c
@@ -100,51 +100,7 @@
 asmlinkage unsigned long
 ia64_brk (unsigned long brk)
 {
-	unsigned long rlim, retval, newbrk, oldbrk;
-	struct mm_struct *mm = current->mm;
-
-	/*
-	 * Most of this replicates the code in sys_brk() except for an additional safety
-	 * check and the clearing of r8.  However, we can't call sys_brk() because we need
-	 * to acquire the mmap_sem before we can do the test...
-	 */
-	down_write(&mm->mmap_sem);
-
-	if (brk < mm->end_code)
-		goto out;
-	newbrk = PAGE_ALIGN(brk);
-	oldbrk = PAGE_ALIGN(mm->brk);
-	if (oldbrk == newbrk)
-		goto set_brk;
-
-	/* Always allow shrinking brk. */
-	if (brk <= mm->brk) {
-		if (!do_munmap(mm, newbrk, oldbrk-newbrk))
-			goto set_brk;
-		goto out;
-	}
-
-	/* Check against unimplemented/unmapped addresses: */
-	if ((newbrk - oldbrk) > RGN_MAP_LIMIT || REGION_OFFSET(newbrk) > RGN_MAP_LIMIT)
-		goto out;
-
-	/* Check against rlimit.. */
-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
-	if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
-		goto out;
-
-	/* Check against existing mmap mappings. */
-	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
-		goto out;
-
-	/* Ok, looks good - let it rip. */
-	if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
-		goto out;
-set_brk:
-	mm->brk = brk;
-out:
-	retval = mm->brk;
-	up_write(&mm->mmap_sem);
+	unsigned long retval = sys_brk(brk);
 	force_successful_syscall_return();
 	return retval;
 }
@@ -185,39 +141,6 @@
 	return 0;
 }
 
-static inline unsigned long
-do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
-{
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			return -EBADF;
-
-		if (!file->f_op || !file->f_op->mmap) {
-			addr = -ENODEV;
-			goto out;
-		}
-	}
-
-	/* Careful about overflows.. */
-	len = PAGE_ALIGN(len);
-	if (!len || len > TASK_SIZE) {
-		addr = -EINVAL;
-		goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-out:	if (file)
-		fput(file);
-	return addr;
-}
-
 /*
  * mmap2() is like mmap() except that the offset is expressed in units
  * of PAGE_SIZE (instead of bytes).  This allows to mmap2() (pieces
@@ -226,7 +149,7 @@
 asmlinkage unsigned long
 sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff)
 {
-	addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
+	addr = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 	if (!IS_ERR((void *) addr))
 		force_successful_syscall_return();
 	return addr;
@@ -238,7 +161,7 @@
 	if (offset_in_page(off) != 0)
 		return -EINVAL;
 
-	addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+	addr = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 	if (!IS_ERR((void *) addr))
 		force_successful_syscall_return();
 	return addr;
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/fsys.S
+++ linux-ec2-2.6.32/arch/ia64/kernel/fsys.S
@@ -420,22 +420,31 @@
 	;;
 
 	RSM_PSR_I(p0, r18, r19)			// mask interrupt delivery
-	mov ar.ccv=0
 	andcm r14=r14,r17			// filter out SIGKILL & SIGSTOP
+	mov r8=EINVAL			// default to EINVAL
 
 #ifdef CONFIG_SMP
-	mov r17=1
-	;;
-	cmpxchg4.acq r18=[r31],r17,ar.ccv	// try to acquire the lock
-	mov r8=EINVAL			// default to EINVAL
+	// __ticket_spin_trylock(r31)
+	ld4 r17=[r31]
 	;;
+	mov.m ar.ccv=r17
+	extr.u r9=r17,17,15
+	adds r19=1,r17
+	extr.u r18=r17,0,15
+	;;
+	cmp.eq p6,p7=r9,r18
+	;;
+(p6)	cmpxchg4.acq r9=[r31],r19,ar.ccv
+(p6)	dep.z r20=r19,1,15		// next serving ticket for unlock
+(p7)	br.cond.spnt.many .lock_contention
+	;;
+	cmp4.eq p0,p7=r9,r17
+	adds r31=2,r31
+(p7)	br.cond.spnt.many .lock_contention
 	ld8 r3=[r2]			// re-read current->blocked now that we hold the lock
-	cmp4.ne p6,p0=r18,r0
-(p6)	br.cond.spnt.many .lock_contention
 	;;
 #else
 	ld8 r3=[r2]			// re-read current->blocked now that we hold the lock
-	mov r8=EINVAL			// default to EINVAL
 #endif
 	add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16
 	add r19=IA64_TASK_SIGNAL_OFFSET,r16
@@ -490,7 +499,9 @@
 (p6)	br.cond.spnt.few 1b			// yes -> retry
 
 #ifdef CONFIG_SMP
-	st4.rel [r31]=r0			// release the lock
+	// __ticket_spin_unlock(r31)
+	st2.rel [r31]=r20
+	mov r20=0					// i must not leak kernel bits...
 #endif
 	SSM_PSR_I(p0, p9, r31)
 	;;
@@ -512,7 +523,8 @@
 
 .sig_pending:
 #ifdef CONFIG_SMP
-	st4.rel [r31]=r0			// release the lock
+	// __ticket_spin_unlock(r31)
+	st2.rel [r31]=r20			// release the lock
 #endif
 	SSM_PSR_I(p0, p9, r17)
 	;;
--- linux-ec2-2.6.32.orig/arch/ia64/kernel/msi_ia64.c
+++ linux-ec2-2.6.32/arch/ia64/kernel/msi_ia64.c
@@ -25,7 +25,7 @@
 	if (irq_prepare_move(irq, cpu))
 		return -1;
 
-	read_msi_msg(irq, &msg);
+	get_cached_msi_msg(irq, &msg);
 
 	addr = msg.address_lo;
 	addr &= MSI_ADDR_DEST_ID_MASK;
--- linux-ec2-2.6.32.orig/arch/ia64/kvm/kvm-ia64.c
+++ linux-ec2-2.6.32/arch/ia64/kvm/kvm-ia64.c
@@ -1797,7 +1797,8 @@
 {
 	struct kvm_memory_slot *memslot;
 	int r, i;
-	long n, base;
+	long base;
+	unsigned long n;
 	unsigned long *dirty_bitmap = (unsigned long *)(kvm->arch.vm_base +
 			offsetof(struct kvm_vm_data, kvm_mem_dirty_log));
 
@@ -1810,7 +1811,7 @@
 	if (!memslot->dirty_bitmap)
 		goto out;
 
-	n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+	n = kvm_dirty_bitmap_bytes(memslot);
 	base = memslot->base_gfn / BITS_PER_LONG;
 
 	for (i = 0; i < n/sizeof(long); ++i) {
@@ -1826,7 +1827,7 @@
 		struct kvm_dirty_log *log)
 {
 	int r;
-	int n;
+	unsigned long n;
 	struct kvm_memory_slot *memslot;
 	int is_dirty = 0;
 
@@ -1844,7 +1845,7 @@
 	if (is_dirty) {
 		kvm_flush_remote_tlbs(kvm);
 		memslot = &kvm->memslots[log->slot];
-		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+		n = kvm_dirty_bitmap_bytes(memslot);
 		memset(memslot->dirty_bitmap, 0, n);
 	}
 	r = 0;
--- linux-ec2-2.6.32.orig/arch/ia64/xen/Kconfig
+++ linux-ec2-2.6.32/arch/ia64/xen/Kconfig
@@ -2,7 +2,7 @@
 # This Kconfig describes xen/ia64 options
 #
 
-config XEN
+config PARAVIRT_XEN
 	bool "Xen hypervisor support"
 	default y
 	depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
@@ -17,9 +17,9 @@
 	  both as a guest OS on Xen and natively on hardware.
 
 config XEN_XENCOMM
-	depends on XEN
+	depends on PARAVIRT_XEN
 	bool
 
 config NO_IDLE_HZ
-	depends on XEN
+	depends on PARAVIRT_XEN
 	bool
--- linux-ec2-2.6.32.orig/arch/ia64/xen/xcom_hcall.c
+++ linux-ec2-2.6.32/arch/ia64/xen/xcom_hcall.c
@@ -343,7 +343,7 @@
 int
 xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
 {
-	GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
+	XEN_GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
 	struct xen_memory_reservation *xmr = NULL;
 	int rc;
 	struct xencomm_handle *desc;
--- linux-ec2-2.6.32.orig/arch/ia64/sn/kernel/msi_sn.c
+++ linux-ec2-2.6.32/arch/ia64/sn/kernel/msi_sn.c
@@ -174,7 +174,7 @@
 	 * Release XIO resources for the old MSI PCI address
 	 */
 
-	read_msi_msg(irq, &msg);
+	get_cached_msi_msg(irq, &msg);
         sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
 	pdev = sn_pdev->pdi_linux_pcidev;
 	provider = SN_PCIDEV_BUSPROVIDER(pdev);
--- linux-ec2-2.6.32.orig/arch/ia64/sn/pci/tioca_provider.c
+++ linux-ec2-2.6.32/arch/ia64/sn/pci/tioca_provider.c
@@ -517,7 +517,7 @@
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
--- linux-ec2-2.6.32.orig/arch/ia64/mm/ioremap.c
+++ linux-ec2-2.6.32/arch/ia64/mm/ioremap.c
@@ -22,6 +22,12 @@
 }
 
 void __iomem *
+early_ioremap (unsigned long phys_addr, unsigned long size)
+{
+	return __ioremap(phys_addr);
+}
+
+void __iomem *
 ioremap (unsigned long phys_addr, unsigned long size)
 {
 	void __iomem *addr;
@@ -102,6 +108,11 @@
 EXPORT_SYMBOL(ioremap_nocache);
 
 void
+early_iounmap (volatile void __iomem *addr, unsigned long size)
+{
+}
+
+void
 iounmap (volatile void __iomem *addr)
 {
 	if (REGION_NUMBER(addr) == RGN_GATE)
--- linux-ec2-2.6.32.orig/arch/ia64/mm/tlb.c
+++ linux-ec2-2.6.32/arch/ia64/mm/tlb.c
@@ -120,7 +120,7 @@
 	ia64_invala();
 
 	for (;;) {
-		asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+		asm volatile ("ld8.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
 		if (time_before(t, serve))
 			return;
 		cpu_relax();
--- linux-ec2-2.6.32.orig/arch/ia64/hp/common/sba_iommu.c
+++ linux-ec2-2.6.32/arch/ia64/hp/common/sba_iommu.c
@@ -677,12 +677,19 @@
 			spin_unlock_irqrestore(&ioc->saved_lock, flags);
 
 			pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
-			if (unlikely(pide >= (ioc->res_size << 3)))
-				panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
-				      ioc->ioc_hpa);
+			if (unlikely(pide >= (ioc->res_size << 3))) {
+				printk(KERN_WARNING "%s: I/O MMU @ %p is"
+				       "out of mapping resources, %u %u %lx\n",
+				       __func__, ioc->ioc_hpa, ioc->res_size,
+				       pages_needed, dma_get_seg_boundary(dev));
+				return -1;
+			}
 #else
-			panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
-			      ioc->ioc_hpa);
+			printk(KERN_WARNING "%s: I/O MMU @ %p is"
+			       "out of mapping resources, %u %u %lx\n",
+			       __func__, ioc->ioc_hpa, ioc->res_size,
+			       pages_needed, dma_get_seg_boundary(dev));
+			return -1;
 #endif
 		}
 	}
@@ -965,6 +972,8 @@
 #endif
 
 	pide = sba_alloc_range(ioc, dev, size);
+	if (pide < 0)
+		return 0;
 
 	iovp = (dma_addr_t) pide << iovp_shift;
 
@@ -1320,6 +1329,7 @@
 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	int n_mappings = 0;
 	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+	int idx;
 
 	while (nents > 0) {
 		unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1418,16 +1428,22 @@
 		vcontig_sg->dma_length = vcontig_len;
 		dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
 		ASSERT(dma_len <= DMA_CHUNK_SIZE);
-		dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
-			| (sba_alloc_range(ioc, dev, dma_len) << iovp_shift)
-			| dma_offset);
+		idx = sba_alloc_range(ioc, dev, dma_len);
+		if (idx < 0) {
+			dma_sg->dma_length = 0;
+			return -1;
+		}
+		dma_sg->dma_address = (dma_addr_t)(PIDE_FLAG | (idx << iovp_shift)
+						   | dma_offset);
 		n_mappings++;
 	}
 
 	return n_mappings;
 }
 
-
+static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
+			       int nents, enum dma_data_direction dir,
+			       struct dma_attrs *attrs);
 /**
  * sba_map_sg - map Scatter/Gather list
  * @dev: instance of PCI owned by the driver that's asking.
@@ -1493,6 +1509,10 @@
 	** Access to the virtual address is what forces a two pass algorithm.
 	*/
 	coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
+	if (coalesced < 0) {
+		sba_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
+		return 0;
+	}
 
 	/*
 	** Program the I/O Pdir
--- linux-ec2-2.6.32.orig/arch/ia64/ia32/sys_ia32.c
+++ linux-ec2-2.6.32/arch/ia64/ia32/sys_ia32.c
@@ -858,6 +858,9 @@
 
 	prot = get_prot32(prot);
 
+	if (flags & MAP_HUGETLB)
+		return -ENOMEM;
+
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
 	mutex_lock(&ia32_mmap_mutex);
 	{
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/acpi.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/acpi.h
@@ -94,6 +94,7 @@
 #define acpi_noirq 0	/* ACPI always enabled on IA64 */
 #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
 #define acpi_strict 1	/* no ACPI spec workarounds on IA64 */
+#define acpi_ht 0	/* no HT-only mode on IA64 */
 #endif
 #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
 static inline void disable_acpi(void) { }
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/system.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/system.h
@@ -281,10 +281,6 @@
 
 void default_idle(void);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_system_vtime(struct task_struct *);
-#endif
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/io.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/io.h
@@ -424,6 +424,8 @@
 extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
+extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
+extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 
 /*
  * String version of IO memory access ops:
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/compat.h
@@ -198,7 +198,7 @@
 }
 
 static __inline__ void __user *
-compat_alloc_user_space (long len)
+arch_compat_alloc_user_space (long len)
 {
 	struct pt_regs *regs = task_pt_regs(current);
 	return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/xen/hypervisor.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/xen/hypervisor.h
@@ -34,10 +34,12 @@
 #define _ASM_IA64_XEN_HYPERVISOR_H
 
 #include <linux/err.h>
+#ifdef CONFIG_PARAVIRT_XEN
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>	/* to compile feature.c */
 #include <xen/features.h>		/* to comiple xen-netfront.c */
 #include <asm/xen/hypercall.h>
+#endif
 
 /* xen_domain_type is set before executing any C code by early_xen_setup */
 enum xen_domain_type {
@@ -46,7 +48,7 @@
 	XEN_HVM_DOMAIN,	/* running in a Xen hvm domain*/
 };
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 extern enum xen_domain_type xen_domain_type;
 #else
 #define xen_domain_type		XEN_NATIVE
@@ -66,7 +68,7 @@
 #endif
 
 
-#ifdef CONFIG_XEN
+#ifdef CONFIG_PARAVIRT_XEN
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
--- linux-ec2-2.6.32.orig/arch/ia64/include/asm/xen/interface.h
+++ linux-ec2-2.6.32/arch/ia64/include/asm/xen/interface.h
@@ -56,29 +56,21 @@
 #ifndef _ASM_IA64_XEN_INTERFACE_H
 #define _ASM_IA64_XEN_INTERFACE_H
 
-#define __DEFINE_GUEST_HANDLE(name, type)	\
+#define __DEFINE_XEN_GUEST_HANDLE(name, type)	\
 	typedef struct { type *p; } __guest_handle_ ## name
 
 #define DEFINE_GUEST_HANDLE_STRUCT(name)	\
-	__DEFINE_GUEST_HANDLE(name, struct name)
-#define DEFINE_GUEST_HANDLE(name)	__DEFINE_GUEST_HANDLE(name, name)
-#define GUEST_HANDLE(name)		__guest_handle_ ## name
-#define GUEST_HANDLE_64(name)		GUEST_HANDLE(name)
+	__DEFINE_XEN_GUEST_HANDLE(name, struct name)
+#define DEFINE_XEN_GUEST_HANDLE(name)	__DEFINE_XEN_GUEST_HANDLE(name, name)
+#define XEN_GUEST_HANDLE(name)		__guest_handle_ ## name
+#define XEN_GUEST_HANDLE_64(name)	XEN_GUEST_HANDLE(name)
 #define set_xen_guest_handle(hnd, val)	do { (hnd).p = val; } while (0)
 
 #ifndef __ASSEMBLY__
-/* Guest handles for primitive C types. */
-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_GUEST_HANDLE(uint, unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
-__DEFINE_GUEST_HANDLE(u64, unsigned long);
-DEFINE_GUEST_HANDLE(char);
-DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
-DEFINE_GUEST_HANDLE(void);
+__DEFINE_XEN_GUEST_HANDLE(u64, unsigned long);
 
+typedef unsigned long xen_ulong_t;
 typedef unsigned long xen_pfn_t;
-DEFINE_GUEST_HANDLE(xen_pfn_t);
 #define PRI_xen_pfn	"lx"
 #endif
 
--- linux-ec2-2.6.32.orig/arch/s390/kernel/time.c
+++ linux-ec2-2.6.32/arch/s390/kernel/time.c
@@ -214,7 +214,8 @@
 	return &clocksource_tod;
 }
 
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
+		     u32 mult)
 {
 	if (clock != &clocksource_tod)
 		return;
--- linux-ec2-2.6.32.orig/arch/s390/kernel/head64.S
+++ linux-ec2-2.6.32/arch/s390/kernel/head64.S
@@ -83,6 +83,8 @@
 	slr	%r0,%r0 		# set cpuid to zero
 	sigp	%r1,%r0,0x12		# switch to esame mode
 	sam64				# switch to 64 bit mode
+	llgfr	%r13,%r13		# clear high-order half of base reg
+	lmh	%r0,%r15,.Lzero64-.LPG1(%r13)	# clear high-order half
 	lctlg	%c0,%c15,.Lctl-.LPG1(%r13)	# load control registers
 	lg	%r12,.Lparmaddr-.LPG1(%r13)	# pointer to parameter area
 					# move IPL device to lowcore
@@ -127,6 +129,7 @@
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad	0x80000000 + 0x20000 - 8	# 2GB + 128K - 8
 .Lnop:	.long	0x07000700
+.Lzero64:.fill	16,4,0x0
 #ifdef CONFIG_ZFCPDUMP
 .Lcurrent_cpu:
 	.long 0x0
--- linux-ec2-2.6.32.orig/arch/s390/kernel/s390_ext.c
+++ linux-ec2-2.6.32/arch/s390/kernel/s390_ext.c
@@ -126,6 +126,8 @@
 		/* Serve timer interrupts first. */
 		clock_comparator_work();
 	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+	if (code != 0x1004)
+		__get_cpu_var(s390_idle).nohz_delay = 1;
         index = ext_hash(code);
 	for (p = ext_int_hash[index]; p; p = p->next) {
 		if (likely(p->code == code))
--- linux-ec2-2.6.32.orig/arch/s390/kernel/compat_linux.c
+++ linux-ec2-2.6.32/arch/s390/kernel/compat_linux.c
@@ -683,38 +683,6 @@
 	u32	offset;
 };
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	struct file * file = NULL;
-	unsigned long error = -EBADF;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
-		/* Result is out of bounds.  */
-		do_munmap(current->mm, addr, len);
-		error = -ENOMEM;
-	}
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:    
-	return error;
-}
-
-
 asmlinkage unsigned long
 old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
 {
@@ -728,7 +696,8 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+			       a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
@@ -741,7 +710,7 @@
 
 	if (copy_from_user(&a, arg, sizeof(a)))
 		goto out;
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 out:
 	return error;
 }
--- linux-ec2-2.6.32.orig/arch/s390/kernel/traps.c
+++ linux-ec2-2.6.32/arch/s390/kernel/traps.c
@@ -243,43 +243,6 @@
 	show_last_breaking_event(regs);
 }
 
-/* This is called from fs/proc/array.c */
-void task_show_regs(struct seq_file *m, struct task_struct *task)
-{
-	struct pt_regs *regs;
-
-	regs = task_pt_regs(task);
-	seq_printf(m, "task: %p, ksp: %p\n",
-		       task, (void *)task->thread.ksp);
-	seq_printf(m, "User PSW : %p %p\n",
-		       (void *) regs->psw.mask, (void *)regs->psw.addr);
-
-	seq_printf(m, "User GPRS: " FOURLONG,
-			  regs->gprs[0], regs->gprs[1],
-			  regs->gprs[2], regs->gprs[3]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[4], regs->gprs[5],
-			  regs->gprs[6], regs->gprs[7]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[8], regs->gprs[9],
-			  regs->gprs[10], regs->gprs[11]);
-	seq_printf(m, "           " FOURLONG,
-			  regs->gprs[12], regs->gprs[13],
-			  regs->gprs[14], regs->gprs[15]);
-	seq_printf(m, "User ACRS: %08x %08x %08x %08x\n",
-			  task->thread.acrs[0], task->thread.acrs[1],
-			  task->thread.acrs[2], task->thread.acrs[3]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[4], task->thread.acrs[5],
-			  task->thread.acrs[6], task->thread.acrs[7]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[8], task->thread.acrs[9],
-			  task->thread.acrs[10], task->thread.acrs[11]);
-	seq_printf(m, "           %08x %08x %08x %08x\n",
-			  task->thread.acrs[12], task->thread.acrs[13],
-			  task->thread.acrs[14], task->thread.acrs[15]);
-}
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
--- linux-ec2-2.6.32.orig/arch/s390/kernel/ptrace.c
+++ linux-ec2-2.6.32/arch/s390/kernel/ptrace.c
@@ -632,7 +632,7 @@
 
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
-	long ret;
+	long ret = 0;
 
 	/* Do the secure computing check first. */
 	secure_computing(regs->gprs[2]);
@@ -641,7 +641,6 @@
 	 * The sysc_tracesys code in entry.S stored the system
 	 * call number to gprs[2].
 	 */
-	ret = regs->gprs[2];
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    (tracehook_report_syscall_entry(regs) ||
 	     regs->gprs[2] >= NR_syscalls)) {
@@ -663,7 +662,7 @@
 				    regs->gprs[2], regs->orig_gpr2,
 				    regs->gprs[3], regs->gprs[4],
 				    regs->gprs[5]);
-	return ret;
+	return ret ?: regs->gprs[2];
 }
 
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
--- linux-ec2-2.6.32.orig/arch/s390/kernel/entry64.S
+++ linux-ec2-2.6.32/arch/s390/kernel/entry64.S
@@ -549,6 +549,7 @@
 	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
 	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
 	TRACE_IRQS_ON
+	lmg	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	j	sysc_do_svc
 
--- linux-ec2-2.6.32.orig/arch/s390/kernel/sys_s390.c
+++ linux-ec2-2.6.32/arch/s390/kernel/sys_s390.c
@@ -32,32 +32,6 @@
 #include <asm/uaccess.h>
 #include "entry.h"
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	long error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls. Linux for S/390 isn't able to handle more than 5
@@ -81,7 +55,7 @@
 
 	if (copy_from_user(&a, arg, sizeof(a)))
 		goto out;
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
 out:
 	return error;
 }
@@ -98,7 +72,7 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
--- linux-ec2-2.6.32.orig/arch/s390/kernel/vtime.c
+++ linux-ec2-2.6.32/arch/s390/kernel/vtime.c
@@ -167,6 +167,8 @@
 	/* Wait for external, I/O or machine check interrupt. */
 	psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
 
+	idle->nohz_delay = 0;
+
 	/* Check if the CPU timer needs to be reprogrammed. */
 	if (vq->do_spt) {
 		__u64 vmax = VTIMER_MAX_SLICE;
--- linux-ec2-2.6.32.orig/arch/s390/kernel/entry.S
+++ linux-ec2-2.6.32/arch/s390/kernel/entry.S
@@ -571,6 +571,7 @@
 	mvc	__THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
 	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
 	TRACE_IRQS_ON
+	lm	%r2,%r6,SP_R2(%r15)	# load svc arguments
 	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	b	BASED(sysc_do_svc)
 
--- linux-ec2-2.6.32.orig/arch/s390/kernel/nmi.c
+++ linux-ec2-2.6.32/arch/s390/kernel/nmi.c
@@ -95,7 +95,6 @@
 static int notrace s390_revalidate_registers(struct mci *mci)
 {
 	int kill_task;
-	u64 tmpclock;
 	u64 zero;
 	void *fpt_save_area, *fpt_creg_save_area;
 
@@ -214,11 +213,10 @@
 			: "0", "cc");
 #endif
 	/* Revalidate clock comparator register */
-	asm volatile(
-		"	stck	0(%1)\n"
-		"	sckc	0(%1)"
-		: "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
-
+	if (S390_lowcore.clock_comparator == -1)
+		set_clock_comparator(get_clock());
+	else
+		set_clock_comparator(S390_lowcore.clock_comparator);
 	/* Check if old PSW is valid */
 	if (!mci->wp)
 		/*
--- linux-ec2-2.6.32.orig/arch/s390/lib/delay.c
+++ linux-ec2-2.6.32/arch/s390/lib/delay.c
@@ -29,17 +29,21 @@
 {
 	unsigned long mask, cr0, cr0_saved;
 	u64 clock_saved;
+	u64 end;
 
+	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+	end = get_clock() + (usecs << 12);
 	clock_saved = local_tick_disable();
-	set_clock_comparator(get_clock() + (usecs << 12));
 	__ctl_store(cr0_saved, 0, 0);
 	cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
 	__ctl_load(cr0 , 0, 0);
-	mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
 	lockdep_off();
-	trace_hardirqs_on();
-	__load_psw_mask(mask);
-	local_irq_disable();
+	do {
+		set_clock_comparator(end);
+		trace_hardirqs_on();
+		__load_psw_mask(mask);
+		local_irq_disable();
+	} while (get_clock() < end);
 	lockdep_on();
 	__ctl_load(cr0_saved, 0, 0);
 	local_tick_enable(clock_saved);
--- linux-ec2-2.6.32.orig/arch/s390/kvm/intercept.c
+++ linux-ec2-2.6.32/arch/s390/kvm/intercept.c
@@ -213,7 +213,7 @@
 	return rc2;
 }
 
-static const intercept_handler_t intercept_funcs[0x48 >> 2] = {
+static const intercept_handler_t intercept_funcs[] = {
 	[0x00 >> 2] = handle_noop,
 	[0x04 >> 2] = handle_instruction,
 	[0x08 >> 2] = handle_prog,
@@ -230,7 +230,7 @@
 	intercept_handler_t func;
 	u8 code = vcpu->arch.sie_block->icptcode;
 
-	if (code & 3 || code > 0x48)
+	if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs))
 		return -ENOTSUPP;
 	func = intercept_funcs[code >> 2];
 	if (func)
--- linux-ec2-2.6.32.orig/arch/s390/kvm/sigp.c
+++ linux-ec2-2.6.32/arch/s390/kvm/sigp.c
@@ -188,9 +188,9 @@
 
 	/* make sure that the new value is valid memory */
 	address = address & 0x7fffe000u;
-	if ((copy_from_guest(vcpu, &tmp,
-		(u64) (address + vcpu->arch.sie_block->gmsor) , 1)) ||
-	   (copy_from_guest(vcpu, &tmp, (u64) (address +
+	if ((copy_from_user(&tmp, (void __user *)
+		(address + vcpu->arch.sie_block->gmsor) , 1)) ||
+	   (copy_from_user(&tmp, (void __user *)(address +
 			vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
 		*reg |= SIGP_STAT_INVALID_PARAMETER;
 		return 1; /* invalid parameter */
--- linux-ec2-2.6.32.orig/arch/s390/kvm/kvm-s390.c
+++ linux-ec2-2.6.32/arch/s390/kvm/kvm-s390.c
@@ -116,10 +116,16 @@
 
 int kvm_dev_ioctl_check_extension(long ext)
 {
+	int r;
+
 	switch (ext) {
+	case KVM_CAP_S390_PSW:
+		r = 1;
+		break;
 	default:
-		return 0;
+		r = 0;
 	}
+	return r;
 }
 
 /* Section: vm related */
@@ -332,11 +338,13 @@
 
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
-		goto out_free_cpu;
+		goto out_free_sie_block;
 	VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
 		 vcpu->arch.sie_block);
 
 	return vcpu;
+out_free_sie_block:
+	free_page((unsigned long)(vcpu->arch.sie_block));
 out_free_cpu:
 	kfree(vcpu);
 out_nomem:
@@ -419,8 +427,10 @@
 	vcpu_load(vcpu);
 	if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
 		rc = -EBUSY;
-	else
-		vcpu->arch.sie_block->gpsw = psw;
+	else {
+		vcpu->run->psw_mask = psw.mask;
+		vcpu->run->psw_addr = psw.addr;
+	}
 	vcpu_put(vcpu);
 	return rc;
 }
@@ -508,9 +518,6 @@
 
 	switch (kvm_run->exit_reason) {
 	case KVM_EXIT_S390_SIEIC:
-		vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
-		vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
-		break;
 	case KVM_EXIT_UNKNOWN:
 	case KVM_EXIT_INTR:
 	case KVM_EXIT_S390_RESET:
@@ -519,6 +526,9 @@
 		BUG();
 	}
 
+	vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
+	vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
+
 	might_fault();
 
 	do {
@@ -538,8 +548,6 @@
 		/* intercept cannot be handled in-kernel, prepare kvm-run */
 		kvm_run->exit_reason         = KVM_EXIT_S390_SIEIC;
 		kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
-		kvm_run->s390_sieic.mask     = vcpu->arch.sie_block->gpsw.mask;
-		kvm_run->s390_sieic.addr     = vcpu->arch.sie_block->gpsw.addr;
 		kvm_run->s390_sieic.ipa      = vcpu->arch.sie_block->ipa;
 		kvm_run->s390_sieic.ipb      = vcpu->arch.sie_block->ipb;
 		rc = 0;
@@ -551,6 +559,9 @@
 		rc = 0;
 	}
 
+	kvm_run->psw_mask     = vcpu->arch.sie_block->gpsw.mask;
+	kvm_run->psw_addr     = vcpu->arch.sie_block->gpsw.addr;
+
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
 
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/cputime.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/cputime.h
@@ -183,6 +183,7 @@
 	unsigned long long idle_count;
 	unsigned long long idle_enter;
 	unsigned long long idle_time;
+	int nohz_delay;
 };
 
 DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
@@ -198,4 +199,11 @@
 		vtime_start_cpu();
 }
 
+static inline int s390_nohz_delay(int cpu)
+{
+	return per_cpu(s390_idle, cpu).nohz_delay != 0;
+}
+
+#define arch_needs_cpu(cpu) s390_nohz_delay(cpu)
+
 #endif /* _S390_CPUTIME_H */
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/vdso.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/vdso.h
@@ -7,7 +7,7 @@
 #define VDSO32_LBASE	0
 #define VDSO64_LBASE	0
 
-#define VDSO_VERSION_STRING	LINUX_2.6.26
+#define VDSO_VERSION_STRING	LINUX_2.6.29
 
 #ifndef __ASSEMBLY__
 
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/system.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/system.h
@@ -97,7 +97,6 @@
 
 extern void account_vtime(struct task_struct *, struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
-extern void account_system_vtime(struct task_struct *);
 
 #ifdef CONFIG_PFAULT
 extern void pfault_irq_init(void);
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/processor.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/processor.h
@@ -150,11 +150,6 @@
  */
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
-/*
- * Print register of task into buffer. Used in fs/proc/array.c.
- */
-extern void task_show_regs(struct seq_file *m, struct task_struct *task);
-
 extern void show_code(struct pt_regs *regs);
 
 unsigned long get_wchan(struct task_struct *p);
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/kvm.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/kvm.h
@@ -1,6 +1,5 @@
 #ifndef __LINUX_KVM_S390_H
 #define __LINUX_KVM_S390_H
-
 /*
  * asm-s390/kvm.h - KVM s390 specific structures and definitions
  *
@@ -15,6 +14,8 @@
  */
 #include <linux/types.h>
 
+#define __KVM_S390
+
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
 	/* general purpose regs for s390 */
--- linux-ec2-2.6.32.orig/arch/s390/include/asm/compat.h
+++ linux-ec2-2.6.32/arch/s390/include/asm/compat.h
@@ -180,7 +180,7 @@
 
 #endif
 
-static inline void __user *compat_alloc_user_space(long len)
+static inline void __user *arch_compat_alloc_user_space(long len)
 {
 	unsigned long stack;
 
--- linux-ec2-2.6.32.orig/arch/um/kernel/uml.lds.S
+++ linux-ec2-2.6.32/arch/um/kernel/uml.lds.S
@@ -22,7 +22,7 @@
   _text = .;
   _stext = .;
   __init_begin = .;
-  INIT_TEXT_SECTION(PAGE_SIZE)
+  INIT_TEXT_SECTION(0)
   . = ALIGN(PAGE_SIZE);
 
   .text      :
--- linux-ec2-2.6.32.orig/arch/um/kernel/syscall.c
+++ linux-ec2-2.6.32/arch/um/kernel/syscall.c
@@ -8,6 +8,7 @@
 #include "linux/mm.h"
 #include "linux/sched.h"
 #include "linux/utsname.h"
+#include "linux/syscalls.h"
 #include "asm/current.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
@@ -37,31 +38,6 @@
 	return ret;
 }
 
-/* common code for old and new mmaps */
-long sys_mmap2(unsigned long addr, unsigned long len,
-	       unsigned long prot, unsigned long flags,
-	       unsigned long fd, unsigned long pgoff)
-{
-	long error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
- out:
-	return error;
-}
-
 long old_mmap(unsigned long addr, unsigned long len,
 	      unsigned long prot, unsigned long flags,
 	      unsigned long fd, unsigned long offset)
@@ -70,7 +46,7 @@
 	if (offset & ~PAGE_MASK)
 		goto out;
 
-	err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	err = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  out:
 	return err;
 }
--- linux-ec2-2.6.32.orig/arch/um/os-Linux/time.c
+++ linux-ec2-2.6.32/arch/um/os-Linux/time.c
@@ -60,7 +60,7 @@
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
-	int remain, max = UM_NSEC_PER_SEC / UM_HZ;
+	long long remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
 	if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
 		printk(UM_KERN_ERR "disable_timer - setitimer failed, "
--- linux-ec2-2.6.32.orig/arch/um/drivers/line.c
+++ linux-ec2-2.6.32/arch/um/drivers/line.c
@@ -727,6 +727,9 @@
 
 static void free_winch(struct winch *winch, int free_irq_ok)
 {
+	if (free_irq_ok)
+		free_irq(WINCH_IRQ, winch);
+
 	list_del(&winch->list);
 
 	if (winch->pid != -1)
@@ -735,8 +738,6 @@
 		os_close_file(winch->fd);
 	if (winch->stack != 0)
 		free_stack(winch->stack, 0);
-	if (free_irq_ok)
-		free_irq(WINCH_IRQ, winch);
 	kfree(winch);
 }
 
--- linux-ec2-2.6.32.orig/arch/um/drivers/ubd_kern.c
+++ linux-ec2-2.6.32/arch/um/drivers/ubd_kern.c
@@ -160,6 +160,7 @@
 	struct scatterlist sg[MAX_SG];
 	struct request *request;
 	int start_sg, end_sg;
+	sector_t rq_pos;
 };
 
 #define DEFAULT_COW { \
@@ -184,6 +185,7 @@
 	.request =		NULL, \
 	.start_sg =		0, \
 	.end_sg =		0, \
+	.rq_pos =		0, \
 }
 
 /* Protected by ubd_lock */
@@ -1222,7 +1224,6 @@
 {
 	struct io_thread_req *io_req;
 	struct request *req;
-	sector_t sector;
 	int n;
 
 	while(1){
@@ -1233,12 +1234,12 @@
 				return;
 
 			dev->request = req;
+			dev->rq_pos = blk_rq_pos(req);
 			dev->start_sg = 0;
 			dev->end_sg = blk_rq_map_sg(q, req, dev->sg);
 		}
 
 		req = dev->request;
-		sector = blk_rq_pos(req);
 		while(dev->start_sg < dev->end_sg){
 			struct scatterlist *sg = &dev->sg[dev->start_sg];
 
@@ -1250,10 +1251,9 @@
 				return;
 			}
 			prepare_request(req, io_req,
-					(unsigned long long)sector << 9,
+					(unsigned long long)dev->rq_pos << 9,
 					sg->offset, sg->length, sg_page(sg));
 
-			sector += sg->length >> 9;
 			n = os_write_file(thread_fd, &io_req,
 					  sizeof(struct io_thread_req *));
 			if(n != sizeof(struct io_thread_req *)){
@@ -1266,6 +1266,7 @@
 				return;
 			}
 
+			dev->rq_pos += sg->length >> 9;
 			dev->start_sg++;
 		}
 		dev->end_sg = 0;
--- linux-ec2-2.6.32.orig/arch/um/sys-x86_64/Makefile
+++ linux-ec2-2.6.32/arch/um/sys-x86_64/Makefile
@@ -8,7 +8,8 @@
 	setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
 	sysrq.o ksyms.o tls.o
 
-subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
+subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
+		lib/rwsem_64.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
 ldt-y = ../sys-i386/ldt.o
--- linux-ec2-2.6.32.orig/arch/um/sys-i386/shared/sysdep/syscalls.h
+++ linux-ec2-2.6.32/arch/um/sys-i386/shared/sysdep/syscalls.h
@@ -20,7 +20,3 @@
 #define EXECUTE_SYSCALL(syscall, regs) \
 	((long (*)(struct syscall_args)) \
 	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
-
-extern long sys_mmap2(unsigned long addr, unsigned long len,
-		      unsigned long prot, unsigned long flags,
-		      unsigned long fd, unsigned long pgoff);
--- linux-ec2-2.6.32.orig/arch/m68knommu/kernel/syscalltable.S
+++ linux-ec2-2.6.32/arch/m68knommu/kernel/syscalltable.S
@@ -210,7 +210,7 @@
 	.long sys_ni_syscall	/* streams2 */
 	.long sys_vfork		/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap2
+	.long sys_mmap_pgoff
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64	/* 195 */
--- linux-ec2-2.6.32.orig/arch/m68knommu/kernel/sys_m68k.c
+++ linux-ec2-2.6.32/arch/m68knommu/kernel/sys_m68k.c
@@ -27,39 +27,6 @@
 #include <asm/cacheflush.h>
 #include <asm/unistd.h>
 
-/* common code for old and new mmaps */
-static inline long do_mmap2(
-	unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file * file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
  * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
@@ -88,9 +55,8 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+				a.offset >> PAGE_SHIFT);
 out:
 	return error;
 }
--- linux-ec2-2.6.32.orig/arch/m32r/kernel/syscall_table.S
+++ linux-ec2-2.6.32/arch/m32r/kernel/syscall_table.S
@@ -191,7 +191,7 @@
 	.long sys_ni_syscall		/* streams2 */
 	.long sys_vfork			/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap2
+	.long sys_mmap_pgoff
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64		/* 195 */
--- linux-ec2-2.6.32.orig/arch/m32r/kernel/sys_m32r.c
+++ linux-ec2-2.6.32/arch/m32r/kernel/sys_m32r.c
@@ -76,30 +76,6 @@
 	return oldval;
 }
 
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
-out:
-	return error;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
--- linux-ec2-2.6.32.orig/arch/blackfin/kernel/sys_bfin.c
+++ linux-ec2-2.6.32/arch/blackfin/kernel/sys_bfin.c
@@ -22,39 +22,6 @@
 #include <asm/cacheflush.h>
 #include <asm/dma.h>
 
-/* common code for old and new mmaps */
-static inline long
-do_mmap2(unsigned long addr, unsigned long len,
-	 unsigned long prot, unsigned long flags,
-	 unsigned long fd, unsigned long pgoff)
-{
-	int error = -EBADF;
-	struct file *file = NULL;
-
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	if (!(flags & MAP_ANONYMOUS)) {
-		file = fget(fd);
-		if (!file)
-			goto out;
-	}
-
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
-
-	if (file)
-		fput(file);
- out:
-	return error;
-}
-
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-			  unsigned long prot, unsigned long flags,
-			  unsigned long fd, unsigned long pgoff)
-{
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
 asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
 {
 	return sram_alloc_with_lsl(size, flags);
--- linux-ec2-2.6.32.orig/arch/blackfin/mach-common/entry.S
+++ linux-ec2-2.6.32/arch/blackfin/mach-common/entry.S
@@ -1422,7 +1422,7 @@
 	.long _sys_ni_syscall	/* streams2 */
 	.long _sys_vfork		/* 190 */
 	.long _sys_getrlimit
-	.long _sys_mmap2
+	.long _sys_mmap_pgoff
 	.long _sys_truncate64
 	.long _sys_ftruncate64
 	.long _sys_stat64	/* 195 */
--- linux-ec2-2.6.32.orig/arch/blackfin/include/asm/page.h
+++ linux-ec2-2.6.32/arch/blackfin/include/asm/page.h
@@ -10,4 +10,9 @@
 #include <asm-generic/page.h>
 #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
 
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | \
+	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
 #endif
--- linux-ec2-2.6.32.orig/arch/blackfin/include/asm/cache.h
+++ linux-ec2-2.6.32/arch/blackfin/include/asm/cache.h
@@ -15,6 +15,8 @@
 #define L1_CACHE_BYTES	(1 << L1_CACHE_SHIFT)
 #define SMP_CACHE_BYTES	L1_CACHE_BYTES
 
+#define ARCH_KMALLOC_MINALIGN	L1_CACHE_BYTES
+
 #ifdef CONFIG_SMP
 #define __cacheline_aligned
 #else
--- linux-ec2-2.6.32.orig/mm/shmem.c
+++ linux-ec2-2.6.32/mm/shmem.c
@@ -2691,5 +2691,6 @@
 		fput(vma->vm_file);
 	vma->vm_file = file;
 	vma->vm_ops = &shmem_vm_ops;
+	vma->vm_flags |= VM_CAN_NONLINEAR;
 	return 0;
 }
--- linux-ec2-2.6.32.orig/mm/backing-dev.c
+++ linux-ec2-2.6.32/mm/backing-dev.c
@@ -98,15 +98,13 @@
 		   "b_more_io:        %8lu\n"
 		   "bdi_list:         %8u\n"
 		   "state:            %8lx\n"
-		   "wb_mask:          %8lx\n"
-		   "wb_list:          %8u\n"
-		   "wb_cnt:           %8u\n",
+		   "wb_list:          %8u\n",
 		   (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
 		   (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
 		   K(bdi_thresh), K(dirty_thresh),
 		   K(background_thresh), nr_wb, nr_dirty, nr_io, nr_more_io,
-		   !list_empty(&bdi->bdi_list), bdi->state, bdi->wb_mask,
-		   !list_empty(&bdi->wb_list), bdi->wb_cnt);
+		   !list_empty(&bdi->bdi_list), bdi->state,
+		   !list_empty(&bdi->wb_list));
 #undef K
 
 	return 0;
@@ -331,14 +329,13 @@
 static void bdi_flush_io(struct backing_dev_info *bdi)
 {
 	struct writeback_control wbc = {
-		.bdi			= bdi,
 		.sync_mode		= WB_SYNC_NONE,
 		.older_than_this	= NULL,
 		.range_cyclic		= 1,
 		.nr_to_write		= 1024,
 	};
 
-	writeback_inodes_wbc(&wbc);
+	writeback_inodes_wb(&bdi->wb, &wbc);
 }
 
 /*
@@ -660,12 +657,6 @@
 
 	bdi_wb_init(&bdi->wb, bdi);
 
-	/*
-	 * Just one thread support for now, hard code mask and count
-	 */
-	bdi->wb_mask = 1;
-	bdi->wb_cnt = 1;
-
 	for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
 		err = percpu_counter_init(&bdi->bdi_stat[i], 0);
 		if (err)
--- linux-ec2-2.6.32.orig/mm/tmem.h
+++ linux-ec2-2.6.32/mm/tmem.h
@@ -0,0 +1,84 @@
+/*
+ * linux/mm/tmem.h
+ *
+ * Interface to transcendent memory, used by mm/precache.c and mm/preswap.c
+ * Currently implemented on XEN, but may be implemented elsewhere in future.
+ *
+ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
+ */
+
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+
+/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
+#define TMEM_POOL_MIN_PAGESHIFT   12
+#define TMEM_POOL_PAGEORDER       (PAGE_SHIFT - TMEM_POOL_MIN_PAGESHIFT)
+
+extern int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
+	unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len);
+extern int xen_tmem_new_pool(u32 tmem_cmd, u64 uuid_lo, u64 uuid_hi, u32 flags);
+
+static inline int tmem_put_page(u32 pool_id, u64 object, u32 index,
+	unsigned long gmfn)
+{
+	return xen_tmem_op(TMEM_PUT_PAGE, pool_id, object, index,
+		gmfn, 0, 0, 0);
+}
+
+static inline int tmem_get_page(u32 pool_id, u64 object, u32 index,
+	unsigned long gmfn)
+{
+	return xen_tmem_op(TMEM_GET_PAGE, pool_id, object, index,
+		gmfn, 0, 0, 0);
+}
+
+static inline int tmem_flush_page(u32 pool_id, u64 object, u32 index)
+{
+	return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, object, index,
+		0, 0, 0, 0);
+}
+
+static inline int tmem_flush_object(u32 pool_id, u64 object)
+{
+	return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, object, 0, 0, 0, 0, 0);
+}
+
+static inline int tmem_new_pool(u64 uuid_lo, u64 uuid_hi, u32 flags)
+{
+	BUILD_BUG_ON((TMEM_POOL_PAGEORDER < 0) ||
+		(TMEM_POOL_PAGEORDER >= TMEM_POOL_PAGESIZE_MASK));
+	flags |= TMEM_POOL_PAGEORDER << TMEM_POOL_PAGESIZE_SHIFT;
+	return xen_tmem_new_pool(TMEM_NEW_POOL, uuid_lo, uuid_hi, flags);
+}
+
+static inline int tmem_destroy_pool(u32 pool_id)
+{
+	return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, 0, 0, 0, 0, 0, 0);
+}
+#else
+struct tmem_op {
+	u32 cmd;
+	s32 pool_id; /* private > 0; shared < 0; 0 is invalid */
+	union {
+		struct {  /* for cmd == TMEM_NEW_POOL */
+			u64 uuid[2];
+			u32 flags;
+		} new;
+		struct {  /* for cmd == TMEM_CONTROL */
+			u32 subop;
+			u32 cli_id;
+			u32 arg1;
+			u32 arg2;
+			void *buf;
+		} ctrl;
+		struct {
+			u64 object;
+			u32 index;
+			u32 tmem_offset;
+			u32 pfn_offset;
+			u32 len;
+			unsigned long pfn;  /* page frame */
+		} gen;
+	} u;
+};
+#endif
--- linux-ec2-2.6.32.orig/mm/hugetlb.c
+++ linux-ec2-2.6.32/mm/hugetlb.c
@@ -401,7 +401,7 @@
 {
 	int i;
 
-	if (unlikely(sz > MAX_ORDER_NR_PAGES)) {
+	if (unlikely(sz/PAGE_SIZE > MAX_ORDER_NR_PAGES)) {
 		clear_gigantic_page(page, addr, sz);
 		return;
 	}
@@ -545,6 +545,7 @@
 
 	mapping = (struct address_space *) page_private(page);
 	set_page_private(page, 0);
+	page->mapping = NULL;
 	BUG_ON(page_count(page));
 	INIT_LIST_HEAD(&page->lru);
 
@@ -1007,7 +1008,7 @@
 		page = alloc_buddy_huge_page(h, vma, addr);
 		if (!page) {
 			hugetlb_put_quota(inode->i_mapping, chg);
-			return ERR_PTR(-VM_FAULT_OOM);
+			return ERR_PTR(-VM_FAULT_SIGBUS);
 		}
 	}
 
@@ -2095,8 +2096,10 @@
 			spin_lock(&inode->i_lock);
 			inode->i_blocks += blocks_per_huge_page(h);
 			spin_unlock(&inode->i_lock);
-		} else
+		} else {
 			lock_page(page);
+			page->mapping = HUGETLB_POISON;
+		}
 	}
 
 	/*
--- linux-ec2-2.6.32.orig/mm/internal.h
+++ linux-ec2-2.6.32/mm/internal.h
@@ -59,7 +59,7 @@
  */
 static inline unsigned long page_order(struct page *page)
 {
-	VM_BUG_ON(!PageBuddy(page));
+	/* PageBuddy() must be checked by the caller */
 	return page_private(page);
 }
 
@@ -107,9 +107,10 @@
 }
 
 /*
- * must be called with vma's mmap_sem held for read, and page locked.
+ * must be called with vma's mmap_sem held for read or write, and page locked.
  */
 extern void mlock_vma_page(struct page *page);
+extern void munlock_vma_page(struct page *page);
 
 /*
  * Clear the page's PageMlocked().  This can be useful in a situation where
--- linux-ec2-2.6.32.orig/mm/ksm.c
+++ linux-ec2-2.6.32/mm/ksm.c
@@ -34,6 +34,7 @@
 #include <linux/ksm.h>
 
 #include <asm/tlbflush.h>
+#include "internal.h"
 
 /*
  * A few notes about the KSM scanning process,
@@ -767,15 +768,14 @@
 	 * ptes are necessarily already write-protected.  But in either
 	 * case, we need to lock and check page_count is not raised.
 	 */
-	if (write_protect_page(vma, oldpage, &orig_pte)) {
-		unlock_page(oldpage);
-		goto out_putpage;
-	}
-	unlock_page(oldpage);
-
-	if (pages_identical(oldpage, newpage))
+	if (write_protect_page(vma, oldpage, &orig_pte) == 0 &&
+	    pages_identical(oldpage, newpage))
 		err = replace_page(vma, oldpage, newpage, orig_pte);
 
+	if ((vma->vm_flags & VM_LOCKED) && !err)
+		munlock_vma_page(oldpage);
+
+	unlock_page(oldpage);
 out_putpage:
 	put_page(oldpage);
 	put_page(newpage);
--- linux-ec2-2.6.32.orig/mm/Makefile
+++ linux-ec2-2.6.32/mm/Makefile
@@ -17,6 +17,9 @@
 
 obj-$(CONFIG_BOUNCE)	+= bounce.o
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
+obj-$(CONFIG_TMEM)	+= tmem.o
+obj-$(CONFIG_PRESWAP)	+= preswap.o
+obj-$(CONFIG_PRECACHE)	+= precache.o
 obj-$(CONFIG_HAS_DMA)	+= dmapool.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
--- linux-ec2-2.6.32.orig/mm/slab.c
+++ linux-ec2-2.6.32/mm/slab.c
@@ -971,13 +971,11 @@
 
 	if (limit > 1)
 		limit = 12;
-	ac_ptr = kmalloc_node(memsize, gfp, node);
+	ac_ptr = kzalloc_node(memsize, gfp, node);
 	if (ac_ptr) {
 		for_each_node(i) {
-			if (i == node || !node_online(i)) {
-				ac_ptr[i] = NULL;
+			if (i == node || !node_online(i))
 				continue;
-			}
 			ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d, gfp);
 			if (!ac_ptr[i]) {
 				for (i--; i >= 0; i--)
@@ -2251,8 +2249,8 @@
 	}
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
 	if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
-	    && cachep->obj_size > cache_line_size() && size < PAGE_SIZE) {
-		cachep->obj_offset += PAGE_SIZE - size;
+	    && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) {
+		cachep->obj_offset += PAGE_SIZE - ALIGN(size, align);
 		size = PAGE_SIZE;
 	}
 #endif
--- linux-ec2-2.6.32.orig/mm/vmscan.c
+++ linux-ec2-2.6.32/mm/vmscan.c
@@ -1083,6 +1083,48 @@
 }
 
 /*
+ * Returns true if the caller should wait to clean dirty/writeback pages.
+ *
+ * If we are direct reclaiming for contiguous pages and we do not reclaim
+ * everything in the list, try again and wait for writeback IO to complete.
+ * This will stall high-order allocations noticeably. Only do that when really
+ * need to free the pages under high memory pressure.
+ */
+static inline bool should_reclaim_stall(unsigned long nr_taken,
+					unsigned long nr_freed,
+					int priority,
+					int lumpy_reclaim,
+					struct scan_control *sc)
+{
+	int lumpy_stall_priority;
+
+	/* kswapd should not stall on sync IO */
+	if (current_is_kswapd())
+		return false;
+
+	/* Only stall on lumpy reclaim */
+	if (!lumpy_reclaim)
+		return false;
+
+	/* If we have relaimed everything on the isolated list, no stall */
+	if (nr_freed == nr_taken)
+		return false;
+
+	/*
+	 * For high-order allocations, there are two stall thresholds.
+	 * High-cost allocations stall immediately where as lower
+	 * order allocations such as stacks require the scanning
+	 * priority to be much higher before stalling.
+	 */
+	if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+		lumpy_stall_priority = DEF_PRIORITY;
+	else
+		lumpy_stall_priority = DEF_PRIORITY / 3;
+
+	return priority <= lumpy_stall_priority;
+}
+
+/*
  * shrink_inactive_list() is a helper for shrink_zone().  It returns the number
  * of reclaimed pages
  */
@@ -1176,14 +1218,9 @@
 		nr_scanned += nr_scan;
 		nr_freed = shrink_page_list(&page_list, sc, PAGEOUT_IO_ASYNC);
 
-		/*
-		 * If we are direct reclaiming for contiguous pages and we do
-		 * not reclaim everything in the list, try again and wait
-		 * for IO to complete. This will stall high-order allocations
-		 * but that should be acceptable to the caller
-		 */
-		if (nr_freed < nr_taken && !current_is_kswapd() &&
-		    lumpy_reclaim) {
+		/* Check if we should syncronously wait for writeback */
+		if (should_reclaim_stall(nr_taken, nr_freed, priority,
+					lumpy_reclaim, sc)) {
 			congestion_wait(BLK_RW_ASYNC, HZ/10);
 
 			/*
@@ -1464,20 +1501,26 @@
 	return low;
 }
 
+static int inactive_list_is_low(struct zone *zone, struct scan_control *sc,
+				int file)
+{
+	if (file)
+		return inactive_file_is_low(zone, sc);
+	else
+		return inactive_anon_is_low(zone, sc);
+}
+
 static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
 	struct zone *zone, struct scan_control *sc, int priority)
 {
 	int file = is_file_lru(lru);
 
-	if (lru == LRU_ACTIVE_FILE && inactive_file_is_low(zone, sc)) {
-		shrink_active_list(nr_to_scan, zone, sc, priority, file);
+	if (is_active_lru(lru)) {
+		if (inactive_list_is_low(zone, sc, file))
+		    shrink_active_list(nr_to_scan, zone, sc, priority, file);
 		return 0;
 	}
 
-	if (lru == LRU_ACTIVE_ANON && inactive_anon_is_low(zone, sc)) {
-		shrink_active_list(nr_to_scan, zone, sc, priority, file);
-		return 0;
-	}
 	return shrink_inactive_list(nr_to_scan, zone, sc, priority, file);
 }
 
--- linux-ec2-2.6.32.orig/mm/mmzone.c
+++ linux-ec2-2.6.32/mm/mmzone.c
@@ -87,3 +87,24 @@
 	return 1;
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
+
+#ifdef CONFIG_SMP
+/* Called when a more accurate view of NR_FREE_PAGES is needed */
+unsigned long zone_nr_free_pages(struct zone *zone)
+{
+	unsigned long nr_free_pages = zone_page_state(zone, NR_FREE_PAGES);
+
+	/*
+	 * While kswapd is awake, it is considered the zone is under some
+	 * memory pressure. Under pressure, there is a risk that
+	 * per-cpu-counter-drift will allow the min watermark to be breached
+	 * potentially causing a live-lock. While kswapd is awake and
+	 * free pages are low, get a better estimate for free pages
+	 */
+	if (nr_free_pages < zone->percpu_drift_mark &&
+			!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
+		return zone_page_state_snapshot(zone, NR_FREE_PAGES);
+
+	return nr_free_pages;
+}
+#endif /* CONFIG_SMP */
--- linux-ec2-2.6.32.orig/mm/mlock.c
+++ linux-ec2-2.6.32/mm/mlock.c
@@ -99,14 +99,14 @@
  * not get another chance to clear PageMlocked.  If we successfully
  * isolate the page and try_to_munlock() detects other VM_LOCKED vmas
  * mapping the page, it will restore the PageMlocked state, unless the page
- * is mapped in a non-linear vma.  So, we go ahead and SetPageMlocked(),
+ * is mapped in a non-linear vma.  So, we go ahead and ClearPageMlocked(),
  * perhaps redundantly.
  * If we lose the isolation race, and the page is mapped by other VM_LOCKED
  * vmas, we'll detect this in vmscan--via try_to_munlock() or try_to_unmap()
  * either of which will restore the PageMlocked state by calling
  * mlock_vma_page() above, if it can grab the vma's mmap sem.
  */
-static void munlock_vma_page(struct page *page)
+void munlock_vma_page(struct page *page)
 {
 	BUG_ON(!PageLocked(page));
 
@@ -138,6 +138,13 @@
 	}
 }
 
+static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	return (vma->vm_flags & VM_GROWSDOWN) &&
+		(vma->vm_start == addr) &&
+		!vma_stack_continue(vma->vm_prev, addr);
+}
+
 /**
  * __mlock_vma_pages_range() -  mlock a range of pages in the vma.
  * @vma:   target vma
@@ -170,6 +177,12 @@
 	if (vma->vm_flags & VM_WRITE)
 		gup_flags |= FOLL_WRITE;
 
+	/* We don't try to access the guard page of a stack vma */
+	if (stack_guard_page(vma, start)) {
+		addr += PAGE_SIZE;
+		nr_pages--;
+	}
+
 	while (nr_pages > 0) {
 		int i;
 
--- linux-ec2-2.6.32.orig/mm/tmem-xen.c
+++ linux-ec2-2.6.32/mm/tmem-xen.c
@@ -0,0 +1,41 @@
+/*
+ * Xen implementation for transcendent memory (tmem)
+ *
+ * Dan Magenheimer <dan.magenheimer@oracle.com> 2009
+ */
+
+#include <linux/types.h>
+#include <xen/interface/xen.h>
+#include <asm/hypervisor.h>
+
+int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
+	unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len)
+{
+	struct tmem_op op;
+	int rc = 0;
+
+	op.cmd = tmem_cmd;
+	op.pool_id = tmem_pool;
+	op.u.gen.object = object;
+	op.u.gen.index = index;
+	op.u.gen.tmem_offset = tmem_offset;
+	op.u.gen.pfn_offset = pfn_offset;
+	op.u.gen.len = len;
+	op.u.gen.cmfn = gmfn;
+	rc = HYPERVISOR_tmem_op(&op);
+	return rc;
+}
+
+int xen_tmem_new_pool(uint32_t tmem_cmd, uint64_t uuid_lo,
+	uint64_t uuid_hi, uint32_t flags)
+{
+	struct tmem_op op;
+	int rc = 0;
+
+	op.cmd = tmem_cmd;
+	op.u.new.uuid[0] = uuid_lo;
+	op.u.new.uuid[1] = uuid_hi;
+	op.u.new.flags = flags;
+	rc = HYPERVISOR_tmem_op(&op);
+	return rc;
+}
--- linux-ec2-2.6.32.orig/mm/init-mm.c
+++ linux-ec2-2.6.32/mm/init-mm.c
@@ -8,6 +8,10 @@
 #include <asm/atomic.h>
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_X86_XEN
+#define swapper_pg_dir ((pgd_t *)NULL)
+#endif
+
 struct mm_struct init_mm = {
 	.mm_rb		= RB_ROOT,
 	.pgd		= swapper_pg_dir,
--- linux-ec2-2.6.32.orig/mm/pagewalk.c
+++ linux-ec2-2.6.32/mm/pagewalk.c
@@ -1,6 +1,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sched.h>
+#include <linux/hugetlb.h>
 
 static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 			  struct mm_walk *walk)
@@ -107,6 +108,7 @@
 	pgd_t *pgd;
 	unsigned long next;
 	int err = 0;
+	struct vm_area_struct *vma;
 
 	if (addr >= end)
 		return err;
@@ -117,11 +119,22 @@
 	pgd = pgd_offset(walk->mm, addr);
 	do {
 		next = pgd_addr_end(addr, end);
+
+		/* skip hugetlb vma to avoid hugepage PMD being cleared
+		 * in pmd_none_or_clear_bad(). */
+		vma = find_vma(walk->mm, addr);
+		if (vma && is_vm_hugetlb_page(vma)) {
+			if (vma->vm_end < next)
+				next = vma->vm_end;
+			continue;
+		}
+
 		if (pgd_none_or_clear_bad(pgd)) {
 			if (walk->pte_hole)
 				err = walk->pte_hole(addr, next, walk);
 			if (err)
 				break;
+			pgd++;
 			continue;
 		}
 		if (walk->pgd_entry)
@@ -131,7 +144,8 @@
 			err = walk_pud_range(pgd, addr, next, walk);
 		if (err)
 			break;
-	} while (pgd++, addr = next, addr != end);
+		pgd++;
+	} while (addr = next, addr != end);
 
 	return err;
 }
--- linux-ec2-2.6.32.orig/mm/mmap.c
+++ linux-ec2-2.6.32/mm/mmap.c
@@ -29,6 +29,7 @@
 #include <linux/rmap.h>
 #include <linux/mmu_notifier.h>
 #include <linux/perf_event.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -45,6 +46,18 @@
 #define arch_rebalance_pgtables(addr, len)		(addr)
 #endif
 
+/* No sane architecture will #define these to anything else */
+#ifndef arch_add_exec_range
+#define arch_add_exec_range(mm, limit)	do { ; } while (0)
+#endif
+#ifndef arch_flush_exec_range
+#define arch_flush_exec_range(mm)	do { ; } while (0)
+#endif
+#ifndef arch_remove_exec_range
+#define arch_remove_exec_range(mm, limit)	do { ; } while (0)
+#endif
+
+
 static void unmap_region(struct mm_struct *mm,
 		struct vm_area_struct *vma, struct vm_area_struct *prev,
 		unsigned long start, unsigned long end);
@@ -389,17 +402,23 @@
 __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct vm_area_struct *prev, struct rb_node *rb_parent)
 {
-	if (prev) {
-		vma->vm_next = prev->vm_next;
-		prev->vm_next = vma;
-	} else {
-		mm->mmap = vma;
-		if (rb_parent)
-			vma->vm_next = rb_entry(rb_parent,
-					struct vm_area_struct, vm_rb);
-		else
-			vma->vm_next = NULL;
-	}
+	struct vm_area_struct *next;
+
+	vma->vm_prev = prev;
+ 	if (prev) {
+		next = prev->vm_next;
+ 		prev->vm_next = vma;
+ 	} else {
+ 		mm->mmap = vma;
+ 		if (rb_parent)
+			next = rb_entry(rb_parent,
+ 					struct vm_area_struct, vm_rb);
+ 		else
+			next = NULL;
+ 	}
+	vma->vm_next = next;
+	if (next)
+		next->vm_prev = vma;
 }
 
 void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -487,10 +506,16 @@
 __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct vm_area_struct *prev)
 {
-	prev->vm_next = vma->vm_next;
+	struct vm_area_struct *next = vma->vm_next;
+
+	prev->vm_next = next;
+	if (next)
+		next->vm_prev = prev;
 	rb_erase(&vma->vm_rb, &mm->mm_rb);
 	if (mm->mmap_cache == vma)
 		mm->mmap_cache = prev;
+	if (vma->vm_flags & VM_EXEC)
+		arch_remove_exec_range(mm, vma->vm_end);
 }
 
 /*
@@ -798,6 +823,8 @@
 		} else					/* cases 2, 5, 7 */
 			vma_adjust(prev, prev->vm_start,
 				end, prev->vm_pgoff, NULL);
+		if (prev->vm_flags & VM_EXEC)
+			arch_add_exec_range(mm, prev->vm_end);
 		return prev;
 	}
 
@@ -932,13 +959,9 @@
 	if (!(flags & MAP_FIXED))
 		addr = round_hint_to_min(addr);
 
-	error = arch_mmap_check(addr, len, flags);
-	if (error)
-		return error;
-
 	/* Careful about overflows.. */
 	len = PAGE_ALIGN(len);
-	if (!len || len > TASK_SIZE)
+	if (!len)
 		return -ENOMEM;
 
 	/* offset overflow? */
@@ -949,28 +972,11 @@
 	if (mm->map_count > sysctl_max_map_count)
 		return -ENOMEM;
 
-	if (flags & MAP_HUGETLB) {
-		struct user_struct *user = NULL;
-		if (file)
-			return -EINVAL;
-
-		/*
-		 * VM_NORESERVE is used because the reservations will be
-		 * taken when vm_ops->mmap() is called
-		 * A dummy user value is used because we are not locking
-		 * memory so no accounting is necessary
-		 */
-		len = ALIGN(len, huge_page_size(&default_hstate));
-		file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
-						&user, HUGETLB_ANONHUGE_INODE);
-		if (IS_ERR(file))
-			return PTR_ERR(file);
-	}
-
 	/* Obtain the address to map to. we verify (or select) it and ensure
 	 * that it represents a valid section of the address space.
 	 */
-	addr = get_unmapped_area(file, addr, len, pgoff, flags);
+	addr = get_unmapped_area_prot(file, addr, len, pgoff, flags,
+		prot & PROT_EXEC);
 	if (addr & ~PAGE_MASK)
 		return addr;
 
@@ -1453,13 +1459,23 @@
 }
 
 unsigned long
-get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
-		unsigned long pgoff, unsigned long flags)
+get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags, int exec)
 {
 	unsigned long (*get_area)(struct file *, unsigned long,
 				  unsigned long, unsigned long, unsigned long);
+	unsigned long error = arch_mmap_check(addr, len, flags);
+	if (error)
+		return error;
 
-	get_area = current->mm->get_unmapped_area;
+	/* Careful about overflows.. */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (exec && current->mm->get_unmapped_exec_area)
+		get_area = current->mm->get_unmapped_exec_area;
+	else
+		get_area = current->mm->get_unmapped_area;
 	if (file && file->f_op && file->f_op->get_unmapped_area)
 		get_area = file->f_op->get_unmapped_area;
 	addr = get_area(file, addr, len, pgoff, flags);
@@ -1473,8 +1489,81 @@
 
 	return arch_rebalance_pgtables(addr, len);
 }
+EXPORT_SYMBOL(get_unmapped_area_prot);
+
+#define SHLIB_BASE	0x00110000
+
+unsigned long
+arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0,
+		unsigned long len0, unsigned long pgoff, unsigned long flags)
+{
+	unsigned long addr = addr0, len = len0;
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long tmp;
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED)
+		return addr;
+
+	if (!addr) {
+		addr = SHLIB_BASE;
+		if ((current->flags & PF_RANDOMIZE) && randomize_va_space)
+			addr = randomize_range(addr, 0x01000000, len);
+	}
+
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	addr = SHLIB_BASE;
+	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (TASK_SIZE - len < addr)
+			return -ENOMEM;
+
+		if (!vma || addr + len <= vma->vm_start) {
+			/*
+			 * Must not let a PROT_EXEC mapping get into the
+			 * brk area:
+			 */
+			if (addr + len > mm->brk)
+				goto failed;
+
+			/*
+			 * Up until the brk area we randomize addresses
+			 * as much as possible:
+			 */
+			if ((current->flags & PF_RANDOMIZE) &&
+                            randomize_va_space &&
+                            addr >= 0x01000000) {
+				tmp = randomize_range(0x01000000,
+					PAGE_ALIGN(max(mm->start_brk,
+					(unsigned long)0x08000000)), len);
+				vma = find_vma(mm, tmp);
+				if (TASK_SIZE - len >= tmp &&
+				    (!vma || tmp + len <= vma->vm_start))
+					return tmp;
+			}
+			/*
+			 * Ok, randomization didnt work out - return
+			 * the result of the linear search:
+			 */
+			return addr;
+		}
+		addr = vma->vm_end;
+	}
+
+failed:
+	return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags);
+}
 
-EXPORT_SYMBOL(get_unmapped_area);
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
 struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
@@ -1549,6 +1638,14 @@
 	return prev ? prev->vm_next : vma;
 }
 
+static int over_stack_limit(unsigned long sz)
+{
+	if (sz < EXEC_STACK_BIAS)
+		return 0;
+	return (sz - EXEC_STACK_BIAS) >
+			current->signal->rlim[RLIMIT_STACK].rlim_cur;
+}
+
 /*
  * Verify that the stack growth is acceptable and
  * update accounting. This is shared with both the
@@ -1565,7 +1662,7 @@
 		return -ENOMEM;
 
 	/* Stack limit test */
-	if (size > rlim[RLIMIT_STACK].rlim_cur)
+	if (over_stack_limit(size))
 		return -ENOMEM;
 
 	/* mlock limit tests */
@@ -1604,9 +1701,6 @@
  * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
  * vma is the last one with address > vma->vm_end.  Have to extend vma.
  */
-#ifndef CONFIG_IA64
-static
-#endif
 int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
 	int error;
@@ -1799,6 +1893,14 @@
 	tlb_finish_mmu(tlb, start, end);
 }
 
+static inline void unmap_vma(struct vm_area_struct *vma)
+{
+#ifdef CONFIG_XEN
+	if (unlikely(vma->vm_ops && vma->vm_ops->unmap))
+		vma->vm_ops->unmap(vma);
+#endif
+}
+
 /*
  * Create a list of vma's touched by the unmap, removing them from the mm's
  * vma list as we go..
@@ -1812,13 +1914,17 @@
 	unsigned long addr;
 
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
+	vma->vm_prev = NULL;
 	do {
 		rb_erase(&vma->vm_rb, &mm->mm_rb);
+		unmap_vma(vma);
 		mm->map_count--;
 		tail_vma = vma;
 		vma = vma->vm_next;
 	} while (vma && vma->vm_start < end);
 	*insertion_point = vma;
+	if (vma)
+		vma->vm_prev = prev;
 	tail_vma->vm_next = NULL;
 	if (mm->unmap_area == arch_unmap_area)
 		addr = prev ? prev->vm_end : mm->mmap_base;
@@ -1875,10 +1981,14 @@
 	if (new->vm_ops && new->vm_ops->open)
 		new->vm_ops->open(new);
 
-	if (new_below)
+	if (new_below) {
+		unsigned long old_end = vma->vm_end;
+
 		vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
 			((addr - new->vm_start) >> PAGE_SHIFT), new);
-	else
+		if (vma->vm_flags & VM_EXEC)
+			arch_remove_exec_range(mm, old_end);
+	} else
 		vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
 
 	return 0;
@@ -2003,20 +2113,14 @@
 	if (!len)
 		return addr;
 
-	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
-		return -EINVAL;
-
-	if (is_hugepage_only_range(mm, addr, len))
-		return -EINVAL;
-
 	error = security_file_mmap(NULL, 0, 0, 0, addr, 1);
 	if (error)
 		return error;
 
 	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
 
-	error = arch_mmap_check(addr, len, flags);
-	if (error)
+	error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
+	if (error & ~PAGE_MASK)
 		return error;
 
 	/*
@@ -2114,6 +2218,11 @@
 
 	arch_exit_mmap(mm);
 
+#ifdef CONFIG_XEN
+	for (vma = mm->mmap; vma; vma = vma->vm_next)
+		unmap_vma(vma);
+#endif
+
 	vma = mm->mmap;
 	if (!vma)	/* Can happen if dup_mmap() received an OOM */
 		return;
@@ -2128,6 +2237,7 @@
 
 	free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0);
 	tlb_finish_mmu(tlb, 0, end);
+	arch_flush_exec_range(mm);
 
 	/*
 	 * Walk the list again, actually closing and freeing it,
@@ -2300,6 +2410,7 @@
 			    unsigned long addr, unsigned long len,
 			    unsigned long vm_flags, struct page **pages)
 {
+	int ret;
 	struct vm_area_struct *vma;
 
 	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
@@ -2316,16 +2427,23 @@
 	vma->vm_ops = &special_mapping_vmops;
 	vma->vm_private_data = pages;
 
-	if (unlikely(insert_vm_struct(mm, vma))) {
-		kmem_cache_free(vm_area_cachep, vma);
-		return -ENOMEM;
-	}
+	ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
+	if (ret)
+		goto out;
+
+	ret = insert_vm_struct(mm, vma);
+	if (ret)
+		goto out;
 
 	mm->total_vm += len >> PAGE_SHIFT;
 
 	perf_event_mmap(vma);
 
 	return 0;
+
+out:
+	kmem_cache_free(vm_area_cachep, vma);
+	return ret;
 }
 
 static DEFINE_MUTEX(mm_all_locks_mutex);
--- linux-ec2-2.6.32.orig/mm/bounce.c
+++ linux-ec2-2.6.32/mm/bounce.c
@@ -115,8 +115,8 @@
 		 */
 		vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
 
-		flush_dcache_page(tovec->bv_page);
 		bounce_copy_vec(tovec, vfrom);
+		flush_dcache_page(tovec->bv_page);
 	}
 }
 
--- linux-ec2-2.6.32.orig/mm/memory-failure.c
+++ linux-ec2-2.6.32/mm/memory-failure.c
@@ -589,7 +589,6 @@
 
 	{ lru|dirty,	lru|dirty,	"LRU",		me_pagecache_dirty },
 	{ lru|dirty,	lru,		"clean LRU",	me_pagecache_clean },
-	{ swapbacked,	swapbacked,	"anonymous",	me_pagecache_clean },
 
 	/*
 	 * Catchall entry: must be at end.
@@ -638,7 +637,7 @@
  * Do all that is necessary to remove user space mappings. Unmap
  * the pages and send SIGBUS to the processes if the data was dirty.
  */
-static void hwpoison_user_mappings(struct page *p, unsigned long pfn,
+static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
 				  int trapno)
 {
 	enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
@@ -648,15 +647,18 @@
 	int i;
 	int kill = 1;
 
-	if (PageReserved(p) || PageCompound(p) || PageSlab(p) || PageKsm(p))
-		return;
+	if (PageReserved(p) || PageSlab(p))
+		return SWAP_SUCCESS;
 
 	/*
 	 * This check implies we don't kill processes if their pages
 	 * are in the swap cache early. Those are always late kills.
 	 */
 	if (!page_mapped(p))
-		return;
+		return SWAP_SUCCESS;
+
+	if (PageCompound(p) || PageKsm(p))
+		return SWAP_FAIL;
 
 	if (PageSwapCache(p)) {
 		printk(KERN_ERR
@@ -718,6 +720,8 @@
 	 */
 	kill_procs_ao(&tokill, !!PageDirty(p), trapno,
 		      ret != SWAP_SUCCESS, pfn);
+
+	return ret;
 }
 
 int __memory_failure(unsigned long pfn, int trapno, int ref)
@@ -787,8 +791,13 @@
 
 	/*
 	 * Now take care of user space mappings.
+	 * Abort on fail: __remove_from_page_cache() assumes unmapped page.
 	 */
-	hwpoison_user_mappings(p, pfn, trapno);
+	if (hwpoison_user_mappings(p, pfn, trapno) != SWAP_SUCCESS) {
+		printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn);
+		res = -EBUSY;
+		goto out;
+	}
 
 	/*
 	 * Torn down by someone else?
--- linux-ec2-2.6.32.orig/mm/vmstat.c
+++ linux-ec2-2.6.32/mm/vmstat.c
@@ -136,10 +136,23 @@
 	int threshold;
 
 	for_each_populated_zone(zone) {
+		unsigned long max_drift, tolerate_drift;
+
 		threshold = calculate_threshold(zone);
 
 		for_each_online_cpu(cpu)
 			zone_pcp(zone, cpu)->stat_threshold = threshold;
+
+		/*
+		 * Only set percpu_drift_mark if there is a danger that
+		 * NR_FREE_PAGES reports the low watermark is ok when in fact
+		 * the min watermark could be breached by an allocation
+		 */
+		tolerate_drift = low_wmark_pages(zone) - min_wmark_pages(zone);
+		max_drift = num_online_cpus() * threshold;
+		if (max_drift > tolerate_drift)
+			zone->percpu_drift_mark = high_wmark_pages(zone) +
+					max_drift;
 	}
 }
 
@@ -715,7 +728,7 @@
 		   "\n        scanned  %lu"
 		   "\n        spanned  %lu"
 		   "\n        present  %lu",
-		   zone_page_state(zone, NR_FREE_PAGES),
+		   zone_nr_free_pages(zone),
 		   min_wmark_pages(zone),
 		   low_wmark_pages(zone),
 		   high_wmark_pages(zone),
--- linux-ec2-2.6.32.orig/mm/Kconfig
+++ linux-ec2-2.6.32/mm/Kconfig
@@ -227,6 +227,7 @@
 
 config DEFAULT_MMAP_MIN_ADDR
         int "Low address space to protect from user allocation"
+	depends on MMU
         default 4096
         help
 	  This is the portion of low virtual memory which should be protected
@@ -287,3 +288,31 @@
 	  of 1 says that all excess pages should be trimmed.
 
 	  See Documentation/nommu-mmap.txt for more information.
+
+#
+# support for transcendent memory
+#
+config TMEM
+	bool
+	help
+	  In a virtualized environment, allows unused and underutilized
+	  system physical memory to be made accessible through a narrow
+	  well-defined page-copy-based API.  If unsure, say Y.
+
+config PRECACHE
+	bool "Cache clean pages in transcendent memory"
+	depends on XEN
+	select TMEM
+	help
+	  Allows the transcendent memory pool to be used to store clean
+	  page-cache pages which, under some circumstances, will greatly
+	  reduce paging and thus improve performance.  If unsure, say Y.
+
+config PRESWAP
+	bool "Swap pages to transcendent memory"
+	depends on XEN
+	select TMEM
+	help
+	  Allows the transcendent memory pool to be used as a pseudo-swap
+	  device which, under some circumstances, will greatly reduce
+	  swapping and thus improve performance.  If unsure, say Y.
--- linux-ec2-2.6.32.orig/mm/memory_hotplug.c
+++ linux-ec2-2.6.32/mm/memory_hotplug.c
@@ -551,19 +551,19 @@
 /* Return the start of the next active pageblock after a given page */
 static struct page *next_active_pageblock(struct page *page)
 {
-	int pageblocks_stride;
-
 	/* Ensure the starting page is pageblock-aligned */
 	BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1));
 
-	/* Move forward by at least 1 * pageblock_nr_pages */
-	pageblocks_stride = 1;
-
 	/* If the entire pageblock is free, move to the end of free page */
-	if (pageblock_free(page))
-		pageblocks_stride += page_order(page) - pageblock_order;
+	if (pageblock_free(page)) {
+		int order;
+		/* be careful. we don't have locks, page_order can be changed.*/
+		order = page_order(page);
+		if ((order < MAX_ORDER) && (order >= pageblock_order))
+			return page + (1 << order);
+	}
 
-	return page + (pageblocks_stride * pageblock_nr_pages);
+	return page + pageblock_nr_pages;
 }
 
 /* Checks if this range of memory is likely to be hot-removable. */
@@ -626,7 +626,7 @@
  * Scanning pfn is much easier than scanning lru list.
  * Scan pfn from start to end and Find LRU page.
  */
-int scan_lru_pages(unsigned long start, unsigned long end)
+unsigned long scan_lru_pages(unsigned long start, unsigned long end)
 {
 	unsigned long pfn;
 	struct page *page;
--- linux-ec2-2.6.32.orig/mm/mincore.c
+++ linux-ec2-2.6.32/mm/mincore.c
@@ -14,6 +14,7 @@
 #include <linux/syscalls.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
+#include <linux/hugetlb.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -72,6 +73,42 @@
 	if (!vma || addr < vma->vm_start)
 		return -ENOMEM;
 
+#ifdef CONFIG_HUGETLB_PAGE
+	if (is_vm_hugetlb_page(vma)) {
+		struct hstate *h;
+		unsigned long nr_huge;
+		unsigned char present;
+
+		i = 0;
+		nr = min(pages, (vma->vm_end - addr) >> PAGE_SHIFT);
+		h = hstate_vma(vma);
+		nr_huge = ((addr + pages * PAGE_SIZE - 1) >> huge_page_shift(h))
+			  - (addr >> huge_page_shift(h)) + 1;
+		nr_huge = min(nr_huge,
+			      (vma->vm_end - addr) >> huge_page_shift(h));
+		while (1) {
+			/* hugepage always in RAM for now,
+			 * but generally it needs to be check */
+			ptep = huge_pte_offset(current->mm,
+					       addr & huge_page_mask(h));
+			present = !!(ptep &&
+				     !huge_pte_none(huge_ptep_get(ptep)));
+			while (1) {
+				vec[i++] = present;
+				addr += PAGE_SIZE;
+				/* reach buffer limit */
+				if (i == nr)
+					return nr;
+				/* check hugepage border */
+				if (!((addr & ~huge_page_mask(h))
+				      >> PAGE_SHIFT))
+					break;
+			}
+		}
+		return nr;
+	}
+#endif
+
 	/*
 	 * Calculate how many pages there are left in the last level of the
 	 * PTE array for our address.
--- linux-ec2-2.6.32.orig/mm/precache.c
+++ linux-ec2-2.6.32/mm/precache.c
@@ -0,0 +1,140 @@
+/*
+ * linux/mm/precache.c
+ *
+ * Implements "precache" for filesystems/pagecache on top of transcendent
+ * memory ("tmem") API.  A filesystem creates an "ephemeral tmem pool"
+ * and retains the returned pool_id in its superblock.  Clean pages evicted
+ * from pagecache may be "put" into the pool and associated with a "handle"
+ * consisting of the pool_id, an object (inode) id, and an index (page offset).
+ * Note that the page is copied to tmem; no kernel mappings are changed.
+ * If the page is later needed, the filesystem (or VFS) issues a "get", passing
+ * the same handle and an empty pageframe.  If successful, the page is copied
+ * into the pageframe and a disk read is avoided.  But since the tmem pool
+ * is of indeterminate size, a "put" page has indeterminate longevity
+ * ("ephemeral"), and the "get" may fail, in which case the filesystem must
+ * read the page from disk as before.  Note that the filesystem/pagecache are
+ * responsible for maintaining coherency between the pagecache, precache,
+ * and the disk, for which "flush page" and "flush object" actions are
+ * provided.  And when a filesystem is unmounted, it must "destroy" the pool.
+ *
+ * Two types of pools may be created for a precache: "private" or "shared".
+ * For a private pool, a successful "get" always flushes, implementing
+ * exclusive semantics; for a "shared" pool (which is intended for use by
+ * co-resident nodes of a cluster filesystem), the "flush" is not guaranteed.
+ * In either case, a failed "duplicate" put (overwrite) always guarantee
+ * the old data is flushed.
+ *
+ * Note also that multiple accesses to a tmem pool may be concurrent and any
+ * ordering must be guaranteed by the caller.
+ *
+ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
+ */
+
+#include <linux/precache.h>
+#include <linux/module.h>
+#include "tmem.h"
+
+static int precache_auto_allocate; /* set to 1 to auto_allocate */
+
+int precache_put(struct address_space *mapping, unsigned long index,
+ struct page *page)
+{
+	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
+	u64 obj = (unsigned long) mapping->host->i_ino;
+	u32 ind = (u32) index;
+	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
+	int ret;
+
+	if ((s32)tmem_pool < 0) {
+		if (!precache_auto_allocate)
+			return 0;
+		/* a put on a non-existent precache may auto-allocate one */
+		ret = tmem_new_pool(0, 0, 0);
+		if (ret < 0)
+			return 0;
+		printk(KERN_INFO
+			"Mapping superblock for s_id=%s to precache_id=%d\n",
+			mapping->host->i_sb->s_id, tmem_pool);
+		mapping->host->i_sb->precache_poolid = tmem_pool;
+	}
+	if (ind != index)
+		return 0;
+	mb(); /* ensure page is quiescent; tmem may address it with an alias */
+	return tmem_put_page(tmem_pool, obj, ind, mfn);
+}
+
+int precache_get(struct address_space *mapping, unsigned long index,
+ struct page *empty_page)
+{
+	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
+	u64 obj = (unsigned long) mapping->host->i_ino;
+	u32 ind = (u32) index;
+	unsigned long mfn = pfn_to_mfn(page_to_pfn(empty_page));
+
+	if ((s32)tmem_pool < 0)
+		return 0;
+	if (ind != index)
+		return 0;
+
+	return tmem_get_page(tmem_pool, obj, ind, mfn);
+}
+EXPORT_SYMBOL(precache_get);
+
+int precache_flush(struct address_space *mapping, unsigned long index)
+{
+	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
+	u64 obj = (unsigned long) mapping->host->i_ino;
+	u32 ind = (u32) index;
+
+	if ((s32)tmem_pool < 0)
+		return 0;
+	if (ind != index)
+		return 0;
+
+	return tmem_flush_page(tmem_pool, obj, ind);
+}
+EXPORT_SYMBOL(precache_flush);
+
+int precache_flush_inode(struct address_space *mapping)
+{
+	u32 tmem_pool = mapping->host->i_sb->precache_poolid;
+	u64 obj = (unsigned long) mapping->host->i_ino;
+
+	if ((s32)tmem_pool < 0)
+		return 0;
+
+	return tmem_flush_object(tmem_pool, obj);
+}
+EXPORT_SYMBOL(precache_flush_inode);
+
+int precache_flush_filesystem(struct super_block *sb)
+{
+	u32 tmem_pool = sb->precache_poolid;
+	int ret;
+
+	if ((s32)tmem_pool < 0)
+		return 0;
+	ret = tmem_destroy_pool(tmem_pool);
+	if (!ret)
+		return 0;
+	printk(KERN_INFO
+		"Unmapping superblock for s_id=%s from precache_id=%d\n",
+		sb->s_id, ret);
+	sb->precache_poolid = 0;
+	return 1;
+}
+EXPORT_SYMBOL(precache_flush_filesystem);
+
+void precache_init(struct super_block *sb)
+{
+	sb->precache_poolid = tmem_new_pool(0, 0, 0);
+}
+EXPORT_SYMBOL(precache_init);
+
+void shared_precache_init(struct super_block *sb, char *uuid)
+{
+	u64 uuid_lo = *(u64 *)uuid;
+	u64 uuid_hi = *(u64 *)(&uuid[8]);
+	sb->precache_poolid = tmem_new_pool(uuid_lo, uuid_hi, TMEM_POOL_SHARED);
+}
+EXPORT_SYMBOL(shared_precache_init);
--- linux-ec2-2.6.32.orig/mm/mprotect.c
+++ linux-ec2-2.6.32/mm/mprotect.c
@@ -26,9 +26,14 @@
 #include <linux/perf_event.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#ifndef arch_remove_exec_range
+#define arch_remove_exec_range(mm, limit)      do { ; } while (0)
+#endif
+
 #ifndef pgprot_modify
 static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
 {
@@ -139,7 +144,7 @@
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long oldflags = vma->vm_flags;
 	long nrpages = (end - start) >> PAGE_SHIFT;
-	unsigned long charged = 0;
+	unsigned long charged = 0, old_end = vma->vm_end;
 	pgoff_t pgoff;
 	int error;
 	int dirty_accountable = 0;
@@ -204,6 +209,9 @@
 		dirty_accountable = 1;
 	}
 
+	if (oldflags & VM_EXEC)
+		arch_remove_exec_range(current->mm, old_end);
+
 	mmu_notifier_invalidate_range_start(mm, start, end);
 	if (is_vm_hugetlb_page(vma))
 		hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
@@ -212,6 +220,7 @@
 	mmu_notifier_invalidate_range_end(mm, start, end);
 	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
+	perf_event_mmap(vma);
 	return 0;
 
 fail:
@@ -300,7 +309,6 @@
 		error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
 		if (error)
 			goto out;
-		perf_event_mmap(vma);
 		nstart = tmp;
 
 		if (nstart < prev->vm_end)
--- linux-ec2-2.6.32.orig/mm/vmalloc.c
+++ linux-ec2-2.6.32/mm/vmalloc.c
@@ -479,6 +479,8 @@
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	vunmap_page_range(start, end);
 	flush_tlb_kernel_range(start, end);
+#elif defined(CONFIG_XEN) && defined(CONFIG_X86)
+	vunmap_page_range(start, end);
 #endif
 }
 
@@ -509,6 +511,18 @@
 
 static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
 
+/* for per-CPU blocks */
+static void purge_fragmented_blocks_allcpus(void);
+
+/*
+ * called before a call to iounmap() if the caller wants vm_area_struct's
+ * immediately freed.
+ */
+void set_iounmap_nonlazy(void)
+{
+	atomic_set(&vmap_lazy_nr, lazy_max_pages()+1);
+}
+
 /*
  * Purges all lazily-freed vmap areas.
  *
@@ -539,6 +553,9 @@
 	} else
 		spin_lock(&purge_lock);
 
+	if (sync)
+		purge_fragmented_blocks_allcpus();
+
 	rcu_read_lock();
 	list_for_each_entry_rcu(va, &vmap_area_list, list) {
 		if (va->flags & VM_LAZY_FREE) {
@@ -555,10 +572,8 @@
 	}
 	rcu_read_unlock();
 
-	if (nr) {
-		BUG_ON(nr > atomic_read(&vmap_lazy_nr));
+	if (nr)
 		atomic_sub(nr, &vmap_lazy_nr);
-	}
 
 	if (nr || force_flush)
 		flush_tlb_kernel_range(*start, *end);
@@ -669,8 +684,6 @@
 struct vmap_block_queue {
 	spinlock_t lock;
 	struct list_head free;
-	struct list_head dirty;
-	unsigned int nr_dirty;
 };
 
 struct vmap_block {
@@ -680,10 +693,9 @@
 	unsigned long free, dirty;
 	DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS);
 	DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS);
-	union {
-		struct list_head free_list;
-		struct rcu_head rcu_head;
-	};
+	struct list_head free_list;
+	struct rcu_head rcu_head;
+	struct list_head purge;
 };
 
 /* Queue of free and dirty vmap blocks, for allocation and flushing purposes */
@@ -759,7 +771,7 @@
 	vbq = &get_cpu_var(vmap_block_queue);
 	vb->vbq = vbq;
 	spin_lock(&vbq->lock);
-	list_add(&vb->free_list, &vbq->free);
+	list_add_rcu(&vb->free_list, &vbq->free);
 	spin_unlock(&vbq->lock);
 	put_cpu_var(vmap_cpu_blocks);
 
@@ -778,8 +790,6 @@
 	struct vmap_block *tmp;
 	unsigned long vb_idx;
 
-	BUG_ON(!list_empty(&vb->free_list));
-
 	vb_idx = addr_to_vb_idx(vb->va->va_start);
 	spin_lock(&vmap_block_tree_lock);
 	tmp = radix_tree_delete(&vmap_block_tree, vb_idx);
@@ -790,12 +800,61 @@
 	call_rcu(&vb->rcu_head, rcu_free_vb);
 }
 
+static void purge_fragmented_blocks(int cpu)
+{
+	LIST_HEAD(purge);
+	struct vmap_block *vb;
+	struct vmap_block *n_vb;
+	struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu);
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(vb, &vbq->free, free_list) {
+
+		if (!(vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS))
+			continue;
+
+		spin_lock(&vb->lock);
+		if (vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS) {
+			vb->free = 0; /* prevent further allocs after releasing lock */
+			vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */
+			bitmap_fill(vb->alloc_map, VMAP_BBMAP_BITS);
+			bitmap_fill(vb->dirty_map, VMAP_BBMAP_BITS);
+			spin_lock(&vbq->lock);
+			list_del_rcu(&vb->free_list);
+			spin_unlock(&vbq->lock);
+			spin_unlock(&vb->lock);
+			list_add_tail(&vb->purge, &purge);
+		} else
+			spin_unlock(&vb->lock);
+	}
+	rcu_read_unlock();
+
+	list_for_each_entry_safe(vb, n_vb, &purge, purge) {
+		list_del(&vb->purge);
+		free_vmap_block(vb);
+	}
+}
+
+static void purge_fragmented_blocks_thiscpu(void)
+{
+	purge_fragmented_blocks(smp_processor_id());
+}
+
+static void purge_fragmented_blocks_allcpus(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		purge_fragmented_blocks(cpu);
+}
+
 static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
 {
 	struct vmap_block_queue *vbq;
 	struct vmap_block *vb;
 	unsigned long addr = 0;
 	unsigned int order;
+	int purge = 0;
 
 	BUG_ON(size & ~PAGE_MASK);
 	BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC);
@@ -808,24 +867,37 @@
 		int i;
 
 		spin_lock(&vb->lock);
+		if (vb->free < 1UL << order)
+			goto next;
 		i = bitmap_find_free_region(vb->alloc_map,
 						VMAP_BBMAP_BITS, order);
 
-		if (i >= 0) {
-			addr = vb->va->va_start + (i << PAGE_SHIFT);
-			BUG_ON(addr_to_vb_idx(addr) !=
-					addr_to_vb_idx(vb->va->va_start));
-			vb->free -= 1UL << order;
-			if (vb->free == 0) {
-				spin_lock(&vbq->lock);
-				list_del_init(&vb->free_list);
-				spin_unlock(&vbq->lock);
+		if (i < 0) {
+			if (vb->free + vb->dirty == VMAP_BBMAP_BITS) {
+				/* fragmented and no outstanding allocations */
+				BUG_ON(vb->dirty != VMAP_BBMAP_BITS);
+				purge = 1;
 			}
-			spin_unlock(&vb->lock);
-			break;
+			goto next;
 		}
+		addr = vb->va->va_start + (i << PAGE_SHIFT);
+		BUG_ON(addr_to_vb_idx(addr) !=
+				addr_to_vb_idx(vb->va->va_start));
+		vb->free -= 1UL << order;
+		if (vb->free == 0) {
+			spin_lock(&vbq->lock);
+			list_del_rcu(&vb->free_list);
+			spin_unlock(&vbq->lock);
+		}
+		spin_unlock(&vb->lock);
+		break;
+next:
 		spin_unlock(&vb->lock);
 	}
+
+	if (purge)
+		purge_fragmented_blocks_thiscpu();
+
 	put_cpu_var(vmap_cpu_blocks);
 	rcu_read_unlock();
 
@@ -862,11 +934,11 @@
 	BUG_ON(!vb);
 
 	spin_lock(&vb->lock);
-	bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order);
+	BUG_ON(bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order));
 
 	vb->dirty += 1UL << order;
 	if (vb->dirty == VMAP_BBMAP_BITS) {
-		BUG_ON(vb->free || !list_empty(&vb->free_list));
+		BUG_ON(vb->free);
 		spin_unlock(&vb->lock);
 		free_vmap_block(vb);
 	} else
@@ -1035,8 +1107,6 @@
 		vbq = &per_cpu(vmap_block_queue, i);
 		spin_lock_init(&vbq->lock);
 		INIT_LIST_HEAD(&vbq->free);
-		INIT_LIST_HEAD(&vbq->dirty);
-		vbq->nr_dirty = 0;
 	}
 
 	/* Import existing vmlist entries. */
@@ -1993,6 +2063,7 @@
 }
 EXPORT_SYMBOL_GPL(free_vm_area);
 
+#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
 static struct vmap_area *node_to_va(struct rb_node *n)
 {
 	return n ? rb_entry(n, struct vmap_area, rb_node) : NULL;
@@ -2257,6 +2328,7 @@
 	kfree(vms);
 	return NULL;
 }
+#endif
 
 /**
  * pcpu_free_vm_areas - free vmalloc areas for percpu allocator
--- linux-ec2-2.6.32.orig/mm/percpu.c
+++ linux-ec2-2.6.32/mm/percpu.c
@@ -1702,9 +1702,9 @@
 
 			if (pcpu_first_unit_cpu == NR_CPUS)
 				pcpu_first_unit_cpu = cpu;
+			pcpu_last_unit_cpu = cpu;
 		}
 	}
-	pcpu_last_unit_cpu = cpu;
 	pcpu_nr_units = unit;
 
 	for_each_possible_cpu(cpu)
--- linux-ec2-2.6.32.orig/mm/oom_kill.c
+++ linux-ec2-2.6.32/mm/oom_kill.c
@@ -404,7 +404,7 @@
 		cpuset_print_task_mems_allowed(current);
 		task_unlock(current);
 		dump_stack();
-		mem_cgroup_print_oom_info(mem, current);
+		mem_cgroup_print_oom_info(mem, p);
 		show_mem();
 		if (sysctl_oom_dump_tasks)
 			dump_tasks(mem);
@@ -426,6 +426,8 @@
 	list_for_each_entry(c, &p->children, sibling) {
 		if (c->mm == p->mm)
 			continue;
+		if (mem && !task_in_mem_cgroup(c, mem))
+			continue;
 		if (!oom_kill_task(c))
 			return 0;
 	}
--- linux-ec2-2.6.32.orig/mm/page-writeback.c
+++ linux-ec2-2.6.32/mm/page-writeback.c
@@ -495,7 +495,6 @@
 
 	for (;;) {
 		struct writeback_control wbc = {
-			.bdi		= bdi,
 			.sync_mode	= WB_SYNC_NONE,
 			.older_than_this = NULL,
 			.nr_to_write	= write_chunk,
@@ -537,7 +536,7 @@
 		 * up.
 		 */
 		if (bdi_nr_reclaimable > bdi_thresh) {
-			writeback_inodes_wbc(&wbc);
+			writeback_inodes_wb(&bdi->wb, &wbc);
 			pages_written += write_chunk - wbc.nr_to_write;
 			get_dirty_limits(&background_thresh, &dirty_thresh,
 				       &bdi_thresh, bdi);
@@ -597,7 +596,7 @@
 	    (!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
 			       + global_page_state(NR_UNSTABLE_NFS))
 					  > background_thresh)))
-		bdi_start_writeback(bdi, NULL, 0);
+		bdi_start_background_writeback(bdi);
 }
 
 void set_page_dirty_balance(struct page *page, int page_mkwrite)
@@ -821,7 +820,6 @@
 		      struct writeback_control *wbc, writepage_t writepage,
 		      void *data)
 {
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	int ret = 0;
 	int done = 0;
 	struct pagevec pvec;
@@ -834,11 +832,6 @@
 	int range_whole = 0;
 	long nr_to_write = wbc->nr_to_write;
 
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		return 0;
-	}
-
 	pagevec_init(&pvec, 0);
 	if (wbc->range_cyclic) {
 		writeback_index = mapping->writeback_index; /* prev offset */
@@ -957,12 +950,6 @@
 					break;
 				}
 			}
-
-			if (wbc->nonblocking && bdi_write_congested(bdi)) {
-				wbc->encountered_congestion = 1;
-				done = 1;
-				break;
-			}
 		}
 		pagevec_release(&pvec);
 		cond_resched();
--- linux-ec2-2.6.32.orig/mm/mremap.c
+++ linux-ec2-2.6.32/mm/mremap.c
@@ -92,9 +92,7 @@
 		 */
 		mapping = vma->vm_file->f_mapping;
 		spin_lock(&mapping->i_mmap_lock);
-		if (new_vma->vm_truncate_count &&
-		    new_vma->vm_truncate_count != vma->vm_truncate_count)
-			new_vma->vm_truncate_count = 0;
+		new_vma->vm_truncate_count = 0;
 	}
 
 	/*
@@ -261,6 +259,144 @@
 	return new_addr;
 }
 
+static struct vm_area_struct *vma_to_resize(unsigned long addr,
+	unsigned long old_len, unsigned long new_len, unsigned long *p)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma = find_vma(mm, addr);
+
+	if (!vma || vma->vm_start > addr)
+		goto Efault;
+
+	if (is_vm_hugetlb_page(vma))
+		goto Einval;
+
+	/* We can't remap across vm area boundaries */
+	if (old_len > vma->vm_end - addr)
+		goto Efault;
+
+	/* Need to be careful about a growing mapping */
+	if (new_len > old_len) {
+		unsigned long pgoff;
+
+		if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
+			goto Efault;
+		pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+		pgoff += vma->vm_pgoff;
+		if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
+			goto Einval;
+	}
+
+	if (vma->vm_flags & VM_LOCKED) {
+		unsigned long locked, lock_limit;
+		locked = mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+		locked += new_len - old_len;
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+			goto Eagain;
+	}
+
+	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT))
+		goto Enomem;
+
+	if (vma->vm_flags & VM_ACCOUNT) {
+		unsigned long charged = (new_len - old_len) >> PAGE_SHIFT;
+		if (security_vm_enough_memory(charged))
+			goto Efault;
+		*p = charged;
+	}
+
+	return vma;
+
+Efault:	/* very odd choice for most of the cases, but... */
+	return ERR_PTR(-EFAULT);
+Einval:
+	return ERR_PTR(-EINVAL);
+Enomem:
+	return ERR_PTR(-ENOMEM);
+Eagain:
+	return ERR_PTR(-EAGAIN);
+}
+
+static unsigned long mremap_to(unsigned long addr,
+	unsigned long old_len, unsigned long new_addr,
+	unsigned long new_len)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long ret = -EINVAL;
+	unsigned long charged = 0;
+	unsigned long map_flags;
+
+	if (new_addr & ~PAGE_MASK)
+		goto out;
+
+	if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
+		goto out;
+
+	/* Check if the location we're moving into overlaps the
+	 * old location at all, and fail if it does.
+	 */
+	if ((new_addr <= addr) && (new_addr+new_len) > addr)
+		goto out;
+
+	if ((addr <= new_addr) && (addr+old_len) > new_addr)
+		goto out;
+
+	ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+	if (ret)
+		goto out;
+
+	ret = do_munmap(mm, new_addr, new_len);
+	if (ret)
+		goto out;
+
+	if (old_len >= new_len) {
+		ret = do_munmap(mm, addr+new_len, old_len - new_len);
+		if (ret && old_len != new_len)
+			goto out;
+		old_len = new_len;
+	}
+
+	vma = vma_to_resize(addr, old_len, new_len, &charged);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto out;
+	}
+
+	map_flags = MAP_FIXED;
+	if (vma->vm_flags & VM_MAYSHARE)
+		map_flags |= MAP_SHARED;
+
+	ret = get_unmapped_area(vma->vm_file, new_addr, new_len, vma->vm_pgoff +
+				((addr - vma->vm_start) >> PAGE_SHIFT),
+				map_flags);
+	if (ret & ~PAGE_MASK)
+		goto out1;
+
+	ret = move_vma(vma, addr, old_len, new_len, new_addr);
+	if (!(ret & ~PAGE_MASK))
+		goto out;
+out1:
+	vm_unacct_memory(charged);
+
+out:
+	return ret;
+}
+
+static int vma_expandable(struct vm_area_struct *vma, unsigned long delta)
+{
+	unsigned long end = vma->vm_end + delta;
+	if (end < vma->vm_end) /* overflow */
+		return 0;
+	if (vma->vm_next && vma->vm_next->vm_start < end) /* intersection */
+		return 0;
+	if (get_unmapped_area(NULL, vma->vm_start, end - vma->vm_start,
+			      0, MAP_FIXED) & ~PAGE_MASK)
+		return 0;
+	return 1;
+}
+
 /*
  * Expand (or shrink) an existing mapping, potentially moving it at the
  * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
@@ -294,32 +430,10 @@
 	if (!new_len)
 		goto out;
 
-	/* new_addr is only valid if MREMAP_FIXED is specified */
 	if (flags & MREMAP_FIXED) {
-		if (new_addr & ~PAGE_MASK)
-			goto out;
-		if (!(flags & MREMAP_MAYMOVE))
-			goto out;
-
-		if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
-			goto out;
-
-		/* Check if the location we're moving into overlaps the
-		 * old location at all, and fail if it does.
-		 */
-		if ((new_addr <= addr) && (new_addr+new_len) > addr)
-			goto out;
-
-		if ((addr <= new_addr) && (addr+old_len) > new_addr)
-			goto out;
-
-		ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
-		if (ret)
-			goto out;
-
-		ret = do_munmap(mm, new_addr, new_len);
-		if (ret)
-			goto out;
+		if (flags & MREMAP_MAYMOVE)
+			ret = mremap_to(addr, old_len, new_addr, new_len);
+		goto out;
 	}
 
 	/*
@@ -332,60 +446,23 @@
 		if (ret && old_len != new_len)
 			goto out;
 		ret = addr;
-		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
-			goto out;
-		old_len = new_len;
+		goto out;
 	}
 
 	/*
-	 * Ok, we need to grow..  or relocate.
+	 * Ok, we need to grow..
 	 */
-	ret = -EFAULT;
-	vma = find_vma(mm, addr);
-	if (!vma || vma->vm_start > addr)
-		goto out;
-	if (is_vm_hugetlb_page(vma)) {
-		ret = -EINVAL;
-		goto out;
-	}
-	/* We can't remap across vm area boundaries */
-	if (old_len > vma->vm_end - addr)
+	vma = vma_to_resize(addr, old_len, new_len, &charged);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
 		goto out;
-	if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
-		if (new_len > old_len)
-			goto out;
-	}
-	if (vma->vm_flags & VM_LOCKED) {
-		unsigned long locked, lock_limit;
-		locked = mm->locked_vm << PAGE_SHIFT;
-		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
-		locked += new_len - old_len;
-		ret = -EAGAIN;
-		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
-			goto out;
-	}
-	if (!may_expand_vm(mm, (new_len - old_len) >> PAGE_SHIFT)) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (vma->vm_flags & VM_ACCOUNT) {
-		charged = (new_len - old_len) >> PAGE_SHIFT;
-		if (security_vm_enough_memory(charged))
-			goto out_nc;
 	}
 
 	/* old_len exactly to the end of the area..
-	 * And we're not relocating the area.
 	 */
-	if (old_len == vma->vm_end - addr &&
-	    !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
-	    (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
-		unsigned long max_addr = TASK_SIZE;
-		if (vma->vm_next)
-			max_addr = vma->vm_next->vm_start;
+	if (old_len == vma->vm_end - addr) {
 		/* can we just expand the current mapping? */
-		if (max_addr - addr >= new_len) {
+		if (vma_expandable(vma, new_len - old_len)) {
 			int pages = (new_len - old_len) >> PAGE_SHIFT;
 
 			vma_adjust(vma, vma->vm_start,
@@ -409,28 +486,27 @@
 	 */
 	ret = -ENOMEM;
 	if (flags & MREMAP_MAYMOVE) {
-		if (!(flags & MREMAP_FIXED)) {
-			unsigned long map_flags = 0;
-			if (vma->vm_flags & VM_MAYSHARE)
-				map_flags |= MAP_SHARED;
-
-			new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
-						vma->vm_pgoff, map_flags);
-			if (new_addr & ~PAGE_MASK) {
-				ret = new_addr;
-				goto out;
-			}
-
-			ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
-			if (ret)
-				goto out;
+		unsigned long map_flags = 0;
+		if (vma->vm_flags & VM_MAYSHARE)
+			map_flags |= MAP_SHARED;
+
+		new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len,
+					vma->vm_pgoff +
+					((addr - vma->vm_start) >> PAGE_SHIFT),
+					map_flags, vma->vm_flags & VM_EXEC);
+		if (new_addr & ~PAGE_MASK) {
+			ret = new_addr;
+			goto out;
 		}
+
+		ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1);
+		if (ret)
+			goto out;
 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
 	}
 out:
 	if (ret & ~PAGE_MASK)
 		vm_unacct_memory(charged);
-out_nc:
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/mm/swapfile.c
+++ linux-ec2-2.6.32/mm/swapfile.c
@@ -330,8 +330,10 @@
 	if (offset > si->highest_bit)
 		scan_base = offset = si->lowest_bit;
 
-	/* reuse swap entry of cache-only swap if not busy. */
-	if (vm_swap_full() && si->swap_map[offset] == SWAP_HAS_CACHE) {
+	/* reuse swap entry of cache-only swap if not hibernation. */
+	if (vm_swap_full()
+		&& cache == SWAP_CACHE
+		&& si->swap_map[offset] == SWAP_HAS_CACHE) {
 		int swap_was_freed;
 		spin_unlock(&swap_lock);
 		swap_was_freed = __try_to_reclaim_swap(si, offset);
@@ -585,9 +587,14 @@
 			swap_list.next = p - swap_info;
 		nr_swap_pages++;
 		p->inuse_pages--;
+		preswap_flush(p - swap_info, offset);
 	}
-	if (!swap_count(count))
+	if (!swap_count(count)) {
 		mem_cgroup_uncharge_swap(ent);
+			if (p->notify_swap_entry_free_fn)
+				p->notify_swap_entry_free_fn(offset);
+	}
+
 	return count;
 }
 
@@ -984,7 +991,7 @@
  * Recycle to start on reaching the end, returning 0 when empty.
  */
 static unsigned int find_next_to_unuse(struct swap_info_struct *si,
-					unsigned int prev)
+				unsigned int prev, unsigned int preswap)
 {
 	unsigned int max = si->max;
 	unsigned int i = prev;
@@ -1010,6 +1017,12 @@
 			prev = 0;
 			i = 1;
 		}
+		if (preswap) {
+			if (preswap_test(si, i))
+				break;
+			else
+				continue;
+		}
 		count = si->swap_map[i];
 		if (count && swap_count(count) != SWAP_MAP_BAD)
 			break;
@@ -1021,8 +1034,12 @@
  * We completely avoid races by reading each swap page in advance,
  * and then search for the process using it.  All the necessary
  * page table adjustments can then be made atomically.
+ *
+ * if the boolean preswap is true, only unuse pages_to_unuse pages;
+ * pages_to_unuse==0 means all pages
  */
-static int try_to_unuse(unsigned int type)
+static int try_to_unuse(unsigned int type, unsigned int preswap,
+		unsigned long pages_to_unuse)
 {
 	struct swap_info_struct * si = &swap_info[type];
 	struct mm_struct *start_mm;
@@ -1058,7 +1075,7 @@
 	 * one pass through swap_map is enough, but not necessarily:
 	 * there are races when an instance of an entry might be missed.
 	 */
-	while ((i = find_next_to_unuse(si, i)) != 0) {
+	while ((i = find_next_to_unuse(si, i, preswap)) != 0) {
 		if (signal_pending(current)) {
 			retval = -EINTR;
 			break;
@@ -1251,6 +1268,8 @@
 		 * interactive performance.
 		 */
 		cond_resched();
+		if (preswap && pages_to_unuse && !--pages_to_unuse)
+			break;
 	}
 
 	mmput(start_mm);
@@ -1575,7 +1594,7 @@
 	spin_unlock(&swap_lock);
 
 	current->flags |= PF_OOM_ORIGIN;
-	err = try_to_unuse(type);
+	err = try_to_unuse(type, 0, 0);
 	current->flags &= ~PF_OOM_ORIGIN;
 
 	if (err) {
@@ -1624,9 +1643,14 @@
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
 	p->flags = 0;
+	preswap_flush_area(p - swap_info);
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	vfree(swap_map);
+#ifdef CONFIG_PRESWAP
+	if (p->preswap_map)
+		vfree(p->preswap_map);
+#endif
 	/* Destroy swap account informatin */
 	swap_cgroup_swapoff(type);
 
@@ -1780,6 +1804,7 @@
 	unsigned long maxpages = 1;
 	unsigned long swapfilepages;
 	unsigned short *swap_map = NULL;
+	unsigned long *preswap_map = NULL;
 	struct page *page = NULL;
 	struct inode *inode = NULL;
 	int did_down = 0;
@@ -1948,6 +1973,12 @@
 		swap_map[page_nr] = SWAP_MAP_BAD;
 	}
 
+#ifdef CONFIG_PRESWAP
+	preswap_map = vmalloc(maxpages / sizeof(long));
+	if (preswap_map)
+		memset(preswap_map, 0, maxpages / sizeof(long));
+#endif
+
 	error = swap_cgroup_swapon(type, maxpages);
 	if (error)
 		goto bad_swap;
@@ -1990,6 +2021,9 @@
 	else
 		p->prio = --least_priority;
 	p->swap_map = swap_map;
+#ifdef CONFIG_PRESWAP
+	p->preswap_map = preswap_map;
+#endif
 	p->flags |= SWP_WRITEOK;
 	nr_swap_pages += nr_good_pages;
 	total_swap_pages += nr_good_pages;
@@ -2015,6 +2049,7 @@
 	} else {
 		swap_info[prev].next = p - swap_info;
 	}
+	preswap_init(p - swap_info);
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	error = 0;
@@ -2031,6 +2066,7 @@
 	p->swap_file = NULL;
 	p->flags = 0;
 	spin_unlock(&swap_lock);
+	vfree(preswap_map);
 	vfree(swap_map);
 	if (swap_file)
 		filp_close(swap_file, NULL);
@@ -2167,6 +2203,23 @@
 }
 
 /*
+ * Sets callback for event when swap_map[offset] == 0
+ * i.e. page at this swap offset is not longer used.
+ *
+ * type: identifies swap file
+ * fn: callback function
+ */
+void set_notify_swap_entry_free(unsigned type, void (*fn) (unsigned long))
+{
+	struct swap_info_struct *sis;
+	sis = get_swap_info_struct(type);
+	BUG_ON(!sis);
+	sis->notify_swap_entry_free_fn = fn;
+	return;
+}
+EXPORT_SYMBOL(set_notify_swap_entry_free);
+
+/*
  * swap_lock prevents swap_map being freed. Don't grab an extra
  * reference on the swaphandle, it doesn't matter if it becomes unused.
  */
@@ -2189,6 +2242,10 @@
 		base++;
 
 	spin_lock(&swap_lock);
+	if (preswap_test(si, target)) {
+		spin_unlock(&swap_lock);
+		return 0;
+	}
 	if (end > si->max)	/* don't go beyond end of map */
 		end = si->max;
 
@@ -2199,6 +2256,9 @@
 			break;
 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
 			break;
+		/* Don't read in preswap pages */
+		if (preswap_test(si, toff))
+			break;
 	}
 	/* Count contiguous allocated slots below our target */
 	for (toff = target; --toff >= base; nr_pages++) {
@@ -2207,6 +2267,9 @@
 			break;
 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
 			break;
+		/* Don't read in preswap pages */
+		if (preswap_test(si, toff))
+			break;
 	}
 	spin_unlock(&swap_lock);
 
@@ -2217,3 +2280,92 @@
 	*offset = ++toff;
 	return nr_pages? ++nr_pages: 0;
 }
+
+#ifdef CONFIG_PRESWAP
+/*
+ * preswap infrastructure functions
+ */
+
+/* code structure leveraged from sys_swapoff */
+void preswap_shrink(unsigned long target_pages)
+{
+	struct swap_info_struct *si = NULL;
+	unsigned long total_pages = 0, total_pages_to_unuse;
+	unsigned long pages = 0, unuse_pages = 0;
+	int type;
+	int wrapped = 0;
+
+	do {
+		/*
+		 * we don't want to hold swap_lock while doing a very
+		 * lengthy try_to_unuse, but swap_list may change
+		 * so restart scan from swap_list.head each time
+		 */
+		spin_lock(&swap_lock);
+		total_pages = 0;
+		for (type = swap_list.head; type >= 0; type = si->next) {
+			si = get_swap_info_struct(type);
+			total_pages += si->preswap_pages;
+		}
+		if (total_pages <= target_pages) {
+			spin_unlock(&swap_lock);
+			return;
+		}
+		total_pages_to_unuse = total_pages - target_pages;
+		for (type = swap_list.head; type >= 0; type = si->next) {
+			si = get_swap_info_struct(type);
+			if (total_pages_to_unuse < si->preswap_pages)
+				pages = unuse_pages = total_pages_to_unuse;
+			else {
+				pages = si->preswap_pages;
+				unuse_pages = 0; /* unuse all */
+			}
+			if (security_vm_enough_memory(pages))
+				continue;
+			vm_unacct_memory(pages);
+			break;
+		}
+		spin_unlock(&swap_lock);
+		if (type < 0)
+			return;
+		current->flags |= PF_OOM_ORIGIN;
+		(void)try_to_unuse(type, 1, unuse_pages);
+		current->flags &= ~PF_OOM_ORIGIN;
+		wrapped++;
+	} while (wrapped <= 3);
+}
+
+
+#ifdef CONFIG_SYSCTL
+/* cat /sys/proc/vm/preswap provides total number of pages in preswap
+ * across all swaptypes.  echo N > /sys/proc/vm/preswap attempts to shrink
+ * preswap page usage to N (usually 0) */
+int preswap_sysctl_handler(ctl_table *table, int write,
+	void __user *buffer, size_t *length, loff_t *ppos)
+{
+	unsigned long npages;
+	int type;
+	unsigned long totalpages = 0;
+	struct swap_info_struct *si = NULL;
+
+	/* modeled after hugetlb_sysctl_handler in mm/hugetlb.c */
+	if (!write) {
+		spin_lock(&swap_lock);
+		for (type = swap_list.head; type >= 0; type = si->next) {
+			si = get_swap_info_struct(type);
+			totalpages += si->preswap_pages;
+		}
+		spin_unlock(&swap_lock);
+		npages = totalpages;
+	}
+	table->data = &npages;
+	table->maxlen = sizeof(unsigned long);
+	proc_doulongvec_minmax(table, write, buffer, length, ppos);
+
+	if (write)
+		preswap_shrink(npages);
+
+	return 0;
+}
+#endif
+#endif /* CONFIG_PRESWAP */
--- linux-ec2-2.6.32.orig/mm/page_io.c
+++ linux-ec2-2.6.32/mm/page_io.c
@@ -110,10 +110,23 @@
 		ret = -ENOMEM;
 		goto out;
 	}
+
+#ifdef CONFIG_PRECACHE
+	set_page_writeback(page);
+	if (preswap_put(page) == 1) {
+		unlock_page(page);
+		end_page_writeback(page);
+		bio_put(bio);
+		goto out;
+	}
+#endif
+
 	if (wbc->sync_mode == WB_SYNC_ALL)
 		rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
 	count_vm_event(PSWPOUT);
+#ifndef CONFIG_PRECACHE
 	set_page_writeback(page);
+#endif
 	unlock_page(page);
 	submit_bio(rw, bio);
 out:
@@ -127,6 +140,13 @@
 
 	VM_BUG_ON(!PageLocked(page));
 	VM_BUG_ON(PageUptodate(page));
+
+	if (preswap_get(page) == 1) {
+		SetPageUptodate(page);
+		unlock_page(page);
+		goto out;
+	}
+
 	bio = get_swap_bio(GFP_KERNEL, page_private(page), page,
 				end_swap_bio_read);
 	if (bio == NULL) {
--- linux-ec2-2.6.32.orig/mm/preswap.c
+++ linux-ec2-2.6.32/mm/preswap.c
@@ -0,0 +1,184 @@
+/*
+ * linux/mm/preswap.c
+ *
+ * Implements a fast "preswap" on top of the transcendent memory ("tmem") API.
+ * When a swapdisk is enabled (with swapon), a "private persistent tmem pool"
+ * is created along with a bit-per-page preswap_map.  When swapping occurs
+ * and a page is about to be written to disk, a "put" into the pool may first
+ * be attempted by passing the pageframe to be swapped, along with a "handle"
+ * consisting of a pool_id, an object id, and an index.  Since the pool is of
+ * indeterminate size, the "put" may be rejected, in which case the page
+ * is swapped to disk as normal.  If the "put" is successful, the page is
+ * copied to tmem and the preswap_map records the success.  Later, when
+ * the page needs to be swapped in, the preswap_map is checked and, if set,
+ * the page may be obtained with a "get" operation.  Note that the swap
+ * subsystem is responsible for: maintaining coherency between the swapcache,
+ * preswap, and the swapdisk; for evicting stale pages from preswap; and for
+ * emptying preswap when swapoff is performed. The "flush page" and "flush
+ * object" actions are provided for this.
+ *
+ * Note that if a "duplicate put" is performed to overwrite a page and
+ * the "put" operation fails, the page (and old data) is flushed and lost.
+ * Also note that multiple accesses to a tmem pool may be concurrent and
+ * any ordering must be guaranteed by the caller.
+ *
+ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
+ */
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sysctl.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include <linux/capability.h>
+#include <linux/uaccess.h>
+#include "tmem.h"
+
+static u32 preswap_poolid = -1; /* if negative, preswap will never call tmem */
+
+const unsigned long preswap_zero = 0, preswap_infinity = ~0UL; /* for sysctl */
+
+/*
+ * Swizzling increases objects per swaptype, increasing tmem concurrency
+ * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
+ */
+#define SWIZ_BITS		4
+#define SWIZ_MASK		((1 << SWIZ_BITS) - 1)
+#define oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define iswiz(_ind)		(_ind >> SWIZ_BITS)
+
+/*
+ * preswap_map test/set/clear operations (must be atomic)
+ */
+
+int preswap_test(struct swap_info_struct *sis, unsigned long offset)
+{
+	if (!sis->preswap_map)
+		return 0;
+	return test_bit(offset % BITS_PER_LONG,
+		&sis->preswap_map[offset/BITS_PER_LONG]);
+}
+
+static inline void preswap_set(struct swap_info_struct *sis,
+				unsigned long offset)
+{
+	if (!sis->preswap_map)
+		return;
+	set_bit(offset % BITS_PER_LONG,
+		&sis->preswap_map[offset/BITS_PER_LONG]);
+}
+
+static inline void preswap_clear(struct swap_info_struct *sis,
+				unsigned long offset)
+{
+	if (!sis->preswap_map)
+		return;
+	clear_bit(offset % BITS_PER_LONG,
+		&sis->preswap_map[offset/BITS_PER_LONG]);
+}
+
+/*
+ * preswap tmem operations
+ */
+
+/* returns 1 if the page was successfully put into preswap, 0 if the page
+ * was declined, and -ERRNO for a specific error */
+int preswap_put(struct page *page)
+{
+	swp_entry_t entry = { .val = page_private(page), };
+	unsigned type = swp_type(entry);
+	pgoff_t offset = swp_offset(entry);
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
+	struct swap_info_struct *sis = get_swap_info_struct(type);
+	int dup = 0, ret;
+
+	if ((s32)preswap_poolid < 0)
+		return 0;
+	if (ind64 != ind)
+		return 0;
+	if (preswap_test(sis, offset))
+		dup = 1;
+	mb(); /* ensure page is quiescent; tmem may address it with an alias */
+	ret = tmem_put_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn);
+	if (ret == 1) {
+		preswap_set(sis, offset);
+		if (!dup)
+			sis->preswap_pages++;
+	} else if (dup) {
+		/* failed dup put always results in an automatic flush of
+		 * the (older) page from preswap */
+		preswap_clear(sis, offset);
+		sis->preswap_pages--;
+	}
+	return ret;
+}
+
+/* returns 1 if the page was successfully gotten from preswap, 0 if the page
+ * was not present (should never happen!), and -ERRNO for a specific error */
+int preswap_get(struct page *page)
+{
+	swp_entry_t entry = { .val = page_private(page), };
+	unsigned type = swp_type(entry);
+	pgoff_t offset = swp_offset(entry);
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
+	struct swap_info_struct *sis = get_swap_info_struct(type);
+	int ret;
+
+	if ((s32)preswap_poolid < 0)
+		return 0;
+	if (ind64 != ind)
+		return 0;
+	if (!preswap_test(sis, offset))
+		return 0;
+	ret = tmem_get_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn);
+	return ret;
+}
+
+/* flush a single page from preswap */
+void preswap_flush(unsigned type, unsigned long offset)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	struct swap_info_struct *sis = get_swap_info_struct(type);
+	int ret = 1;
+
+	if ((s32)preswap_poolid < 0)
+		return;
+	if (ind64 != ind)
+		return;
+	if (preswap_test(sis, offset)) {
+		ret = tmem_flush_page(preswap_poolid,
+					oswiz(type, ind), iswiz(ind));
+		sis->preswap_pages--;
+		preswap_clear(sis, offset);
+	}
+}
+
+/* flush all pages from the passed swaptype */
+void preswap_flush_area(unsigned type)
+{
+	struct swap_info_struct *sis = get_swap_info_struct(type);
+	int ind;
+
+	if ((s32)preswap_poolid < 0)
+		return;
+	for (ind = SWIZ_MASK; ind >= 0; ind--)
+		(void)tmem_flush_object(preswap_poolid, oswiz(type, ind));
+	sis->preswap_pages = 0;
+}
+
+void preswap_init(unsigned type)
+{
+	/* only need one tmem pool for all swap types */
+	if ((s32)preswap_poolid >= 0)
+		return;
+	preswap_poolid = tmem_new_pool(0, 0, TMEM_POOL_PERSIST);
+	if (preswap_poolid < 0)
+		return;
+}
--- linux-ec2-2.6.32.orig/mm/nommu.c
+++ linux-ec2-2.6.32/mm/nommu.c
@@ -608,7 +608,7 @@
  */
 static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma)
 {
-	struct vm_area_struct *pvma, **pp;
+	struct vm_area_struct *pvma, **pp, *next;
 	struct address_space *mapping;
 	struct rb_node **p, *parent;
 
@@ -668,8 +668,11 @@
 			break;
 	}
 
-	vma->vm_next = *pp;
+	next = *pp;
 	*pp = vma;
+	vma->vm_next = next;
+	if (next)
+		next->vm_prev = vma;
 }
 
 /*
@@ -1612,6 +1615,7 @@
 		mm->mmap = vma->vm_next;
 		delete_vma_from_mm(vma);
 		delete_vma(mm, vma);
+		cond_resched();
 	}
 
 	kleave("");
--- linux-ec2-2.6.32.orig/mm/truncate.c
+++ linux-ec2-2.6.32/mm/truncate.c
@@ -15,6 +15,7 @@
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/pagevec.h>
+#include <linux/precache.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/buffer_head.h>	/* grr. try_to_release_page,
 				   do_invalidatepage */
@@ -50,6 +51,7 @@
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
 	zero_user_segment(page, partial, PAGE_CACHE_SIZE);
+	precache_flush(page->mapping, page->index);
 	if (page_has_private(page))
 		do_invalidatepage(page, partial);
 }
@@ -107,6 +109,10 @@
 	clear_page_mlock(page);
 	remove_from_page_cache(page);
 	ClearPageMappedToDisk(page);
+	/* this must be after the remove_from_page_cache which
+	 * calls precache_put
+	 */
+	precache_flush(mapping, page->index);
 	page_cache_release(page);	/* pagecache ref */
 	return 0;
 }
@@ -214,6 +220,7 @@
 	pgoff_t next;
 	int i;
 
+	precache_flush_inode(mapping);
 	if (mapping->nrpages == 0)
 		return;
 
@@ -287,6 +294,7 @@
 		}
 		pagevec_release(&pvec);
 	}
+	precache_flush_inode(mapping);
 }
 EXPORT_SYMBOL(truncate_inode_pages_range);
 
@@ -423,6 +431,7 @@
 	int did_range_unmap = 0;
 	int wrapped = 0;
 
+	precache_flush_inode(mapping);
 	pagevec_init(&pvec, 0);
 	next = start;
 	while (next <= end && !wrapped &&
@@ -479,6 +488,7 @@
 		pagevec_release(&pvec);
 		cond_resched();
 	}
+	precache_flush_inode(mapping);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
@@ -516,22 +526,20 @@
  */
 void truncate_pagecache(struct inode *inode, loff_t old, loff_t new)
 {
-	if (new < old) {
-		struct address_space *mapping = inode->i_mapping;
+	struct address_space *mapping = inode->i_mapping;
 
-		/*
-		 * unmap_mapping_range is called twice, first simply for
-		 * efficiency so that truncate_inode_pages does fewer
-		 * single-page unmaps.  However after this first call, and
-		 * before truncate_inode_pages finishes, it is possible for
-		 * private pages to be COWed, which remain after
-		 * truncate_inode_pages finishes, hence the second
-		 * unmap_mapping_range call must be made for correctness.
-		 */
-		unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
-		truncate_inode_pages(mapping, new);
-		unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
-	}
+	/*
+	 * unmap_mapping_range is called twice, first simply for
+	 * efficiency so that truncate_inode_pages does fewer
+	 * single-page unmaps.  However after this first call, and
+	 * before truncate_inode_pages finishes, it is possible for
+	 * private pages to be COWed, which remain after
+	 * truncate_inode_pages finishes, hence the second
+	 * unmap_mapping_range call must be made for correctness.
+	 */
+	unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
+	truncate_inode_pages(mapping, new);
+	unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
 }
 EXPORT_SYMBOL(truncate_pagecache);
 
--- linux-ec2-2.6.32.orig/mm/migrate.c
+++ linux-ec2-2.6.32/mm/migrate.c
@@ -953,6 +953,9 @@
 				goto out_pm;
 
 			err = -ENODEV;
+			if (node < 0 || node >= MAX_NUMNODES)
+				goto out_pm;
+
 			if (!node_state(node, N_HIGH_MEMORY))
 				goto out_pm;
 
--- linux-ec2-2.6.32.orig/mm/util.c
+++ linux-ec2-2.6.32/mm/util.c
@@ -4,6 +4,10 @@
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/sched.h>
+#include <linux/hugetlb.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
 #include <asm/uaccess.h>
 
 #define CREATE_TRACE_POINTS
@@ -268,6 +272,46 @@
 }
 EXPORT_SYMBOL_GPL(get_user_pages_fast);
 
+SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+		unsigned long, prot, unsigned long, flags,
+		unsigned long, fd, unsigned long, pgoff)
+{
+	struct file * file = NULL;
+	unsigned long retval = -EBADF;
+
+	if (!(flags & MAP_ANONYMOUS)) {
+		if (unlikely(flags & MAP_HUGETLB))
+			return -EINVAL;
+		file = fget(fd);
+		if (!file)
+			goto out;
+	} else if (flags & MAP_HUGETLB) {
+		struct user_struct *user = NULL;
+		/*
+		 * VM_NORESERVE is used because the reservations will be
+		 * taken when vm_ops->mmap() is called
+		 * A dummy user value is used because we are not locking
+		 * memory so no accounting is necessary
+		 */
+		len = ALIGN(len, huge_page_size(&default_hstate));
+		file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
+						&user, HUGETLB_ANONHUGE_INODE);
+		if (IS_ERR(file))
+			return PTR_ERR(file);
+	}
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	down_write(&current->mm->mmap_sem);
+	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:
+	return retval;
+}
+
 /* Tracepoints definitions. */
 EXPORT_TRACEPOINT_SYMBOL(kmalloc);
 EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);
--- linux-ec2-2.6.32.orig/mm/memory.c
+++ linux-ec2-2.6.32/mm/memory.c
@@ -523,6 +523,12 @@
 {
 	unsigned long pfn = pte_pfn(pte);
 
+#if defined(CONFIG_XEN) && defined(CONFIG_X86)
+	/* XEN: Covers user-space grant mappings (even of local pages). */
+	if (unlikely(vma->vm_flags & VM_FOREIGN))
+		return NULL;
+#endif
+
 	if (HAVE_PTE_SPECIAL) {
 		if (likely(!pte_special(pte)))
 			goto check_pfn;
@@ -554,6 +560,9 @@
 		return NULL;
 check_pfn:
 	if (unlikely(pfn > highest_memmap_pfn)) {
+#ifdef CONFIG_XEN
+		if (!(vma->vm_flags & VM_RESERVED))
+#endif
 		print_bad_pte(vma, addr, pte, NULL);
 		return NULL;
 	}
@@ -839,8 +848,14 @@
 				     page->index > details->last_index))
 					continue;
 			}
-			ptent = ptep_get_and_clear_full(mm, addr, pte,
-							tlb->fullmm);
+#ifdef CONFIG_XEN
+			if (unlikely(vma->vm_ops && vma->vm_ops->zap_pte))
+				ptent = vma->vm_ops->zap_pte(vma, addr, pte,
+							     tlb->fullmm);
+			else
+#endif
+				ptent = ptep_get_and_clear_full(mm, addr, pte,
+								tlb->fullmm);
 			tlb_remove_tlb_entry(tlb, pte, addr);
 			if (unlikely(!page))
 				continue;
@@ -1100,6 +1115,7 @@
 		tlb_finish_mmu(tlb, address, end);
 	return end;
 }
+EXPORT_SYMBOL(zap_page_range);
 
 /**
  * zap_vma_ptes - remove ptes mapping the vma
@@ -1282,10 +1298,20 @@
 				return i ? : -EFAULT;
 			}
 			if (pages) {
-				struct page *page = vm_normal_page(gate_vma, start, *pte);
+				struct page *page;
+
+				page = vm_normal_page(gate_vma, start, *pte);
+				if (!page) {
+					if (!(gup_flags & FOLL_DUMP) &&
+					     is_zero_pfn(pte_pfn(*pte)))
+						page = pte_page(*pte);
+					else {
+						pte_unmap(pte);
+						return i ? : -EFAULT;
+					}
+				}
 				pages[i] = page;
-				if (page)
-					get_page(page);
+				get_page(page);
 			}
 			pte_unmap(pte);
 			if (vmas)
@@ -1296,6 +1322,28 @@
 			continue;
 		}
 
+#ifdef CONFIG_XEN
+		if (vma && (vma->vm_flags & VM_FOREIGN)) {
+			struct vm_foreign_map *foreign_map =
+				vma->vm_private_data;
+			struct page **map = foreign_map->map;
+			int offset = (start - vma->vm_start) >> PAGE_SHIFT;
+			if (map[offset] != NULL) {
+			        if (pages) {
+			                struct page *page = map[offset];
+
+					pages[i] = page;
+					get_page(page);
+				}
+				if (vmas)
+					vmas[i] = vma;
+				i++;
+				start += PAGE_SIZE;
+				nr_pages--;
+				continue;
+			}
+		}
+#endif
 		if (!vma ||
 		    (vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
 		    !(vm_flags & vma->vm_flags))
@@ -1889,6 +1937,10 @@
 	unsigned long start = addr, end = addr + size;
 	int err;
 
+#ifdef CONFIG_XEN
+	if (!mm)
+		mm = &init_mm;
+#endif
 	BUG_ON(addr >= end);
 	mmu_notifier_invalidate_range_start(mm, start, end);
 	pgd = pgd_offset(mm, addr);
@@ -2514,7 +2566,7 @@
 			ret = VM_FAULT_HWPOISON;
 		} else {
 			print_bad_pte(vma, address, orig_pte, NULL);
-			ret = VM_FAULT_OOM;
+			ret = VM_FAULT_SIGBUS;
 		}
 		goto out;
 	}
@@ -2620,6 +2672,40 @@
 }
 
 /*
+ * This is like a special single-page "expand_{down|up}wards()",
+ * except we must first make sure that 'address{-|+}PAGE_SIZE'
+ * doesn't hit another vma.
+ */
+static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
+{
+	address &= PAGE_MASK;
+	if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
+		struct vm_area_struct *prev = vma->vm_prev;
+
+		/*
+		 * Is there a mapping abutting this one below?
+		 *
+		 * That's only ok if it's the same stack mapping
+		 * that has gotten split..
+		 */
+		if (prev && prev->vm_end == address)
+			return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
+
+		expand_stack(vma, address - PAGE_SIZE);
+	}
+	if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
+		struct vm_area_struct *next = vma->vm_next;
+
+		/* As VM_GROWSDOWN but s/below/above/ */
+		if (next && next->vm_start == address + PAGE_SIZE)
+			return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
+
+		expand_upwards(vma, address + PAGE_SIZE);
+	}
+	return 0;
+}
+
+/*
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
  * but allow concurrent faults), and pte mapped but not yet locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
@@ -2632,19 +2718,23 @@
 	spinlock_t *ptl;
 	pte_t entry;
 
+	pte_unmap(page_table);
+
+	/* Check if we need to add a guard page to the stack */
+	if (check_stack_guard_page(vma, address) < 0)
+		return VM_FAULT_SIGBUS;
+
+	/* Use the zero-page for reads */
 	if (!(flags & FAULT_FLAG_WRITE)) {
 		entry = pte_mkspecial(pfn_pte(my_zero_pfn(address),
 						vma->vm_page_prot));
-		ptl = pte_lockptr(mm, pmd);
-		spin_lock(ptl);
+		page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 		if (!pte_none(*page_table))
 			goto unlock;
 		goto setpte;
 	}
 
 	/* Allocate our own private page. */
-	pte_unmap(page_table);
-
 	if (unlikely(anon_vma_prepare(vma)))
 		goto oom;
 	page = alloc_zeroed_user_highpage_movable(vma, address);
@@ -2910,7 +3000,7 @@
 		 * Page table corrupted: show pte and kill process.
 		 */
 		print_bad_pte(vma, address, orig_pte, NULL);
-		return VM_FAULT_OOM;
+		return VM_FAULT_SIGBUS;
 	}
 
 	pgoff = pte_to_pgoff(orig_pte);
--- linux-ec2-2.6.32.orig/mm/readahead.c
+++ linux-ec2-2.6.32/mm/readahead.c
@@ -501,6 +501,12 @@
 	if (!ra->ra_pages)
 		return;
 
+	/* be dumb */
+	if (filp && (filp->f_mode & FMODE_RANDOM)) {
+		force_page_cache_readahead(mapping, filp, offset, req_size);
+		return;
+	}
+
 	/* do read-ahead */
 	ondemand_readahead(mapping, ra, filp, false, offset, req_size);
 }
@@ -547,5 +553,17 @@
 
 	/* do read-ahead */
 	ondemand_readahead(mapping, ra, filp, true, offset, req_size);
+
+#ifdef CONFIG_BLOCK
+	/*
+	 * Normally the current page is !uptodate and lock_page() will be
+	 * immediately called to implicitly unplug the device. However this
+	 * is not always true for RAID conifgurations, where data arrives
+	 * not strictly in their submission order. In this case we need to
+	 * explicitly kick off the IO.
+	 */
+	if (PageUptodate(page))
+		blk_run_backing_dev(mapping->backing_dev_info, NULL);
+#endif
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
--- linux-ec2-2.6.32.orig/mm/page_alloc.c
+++ linux-ec2-2.6.32/mm/page_alloc.c
@@ -531,13 +531,13 @@
 {
 	int migratetype = 0;
 	int batch_free = 0;
+	int to_free = count;
 
 	spin_lock(&zone->lock);
 	zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
 	zone->pages_scanned = 0;
 
-	__mod_zone_page_state(zone, NR_FREE_PAGES, count);
-	while (count) {
+	while (to_free) {
 		struct page *page;
 		struct list_head *list;
 
@@ -559,10 +559,12 @@
 			page = list_entry(list->prev, struct page, lru);
 			/* must delete as __free_one_page list manipulates */
 			list_del(&page->lru);
-			__free_one_page(page, zone, 0, migratetype);
-			trace_mm_page_pcpu_drain(page, 0, migratetype);
-		} while (--count && --batch_free && !list_empty(list));
+			/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
+			__free_one_page(page, zone, 0, page_private(page));
+			trace_mm_page_pcpu_drain(page, 0, page_private(page));
+		} while (--to_free && --batch_free && !list_empty(list));
 	}
+	__mod_zone_page_state(zone, NR_FREE_PAGES, count);
 	spin_unlock(&zone->lock);
 }
 
@@ -573,8 +575,8 @@
 	zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
 	zone->pages_scanned = 0;
 
-	__mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
 	__free_one_page(page, zone, order, migratetype);
+	__mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
 	spin_unlock(&zone->lock);
 }
 
@@ -585,6 +587,14 @@
 	int bad = 0;
 	int wasMlocked = __TestClearPageMlocked(page);
 
+#ifdef CONFIG_XEN
+	if (PageForeign(page)) {
+		WARN_ON(wasMlocked);
+		PageForeignDestructor(page, order);
+		return;
+	}
+#endif
+
 	kmemcheck_free_shadow(page, order);
 
 	for (i = 0 ; i < (1 << order) ; ++i)
@@ -1084,6 +1094,14 @@
 	int migratetype;
 	int wasMlocked = __TestClearPageMlocked(page);
 
+#ifdef CONFIG_XEN
+	if (PageForeign(page)) {
+		WARN_ON(wasMlocked);
+		PageForeignDestructor(page, 0);
+		return;
+	}
+#endif
+
 	kmemcheck_free_shadow(page, 0);
 
 	if (PageAnon(page))
@@ -1225,10 +1243,10 @@
 		}
 		spin_lock_irqsave(&zone->lock, flags);
 		page = __rmqueue(zone, order, migratetype);
-		__mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order));
 		spin_unlock(&zone->lock);
 		if (!page)
 			goto failed;
+		__mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << order));
 	}
 
 	__count_zone_vm_events(PGALLOC, zone, 1 << order);
@@ -1364,7 +1382,7 @@
 {
 	/* free_pages my go negative - that's OK */
 	long min = mark;
-	long free_pages = zone_page_state(z, NR_FREE_PAGES) - (1 << order) + 1;
+	long free_pages = zone_nr_free_pages(z) - (1 << order) + 1;
 	int o;
 
 	if (alloc_flags & ALLOC_HIGH)
@@ -1680,6 +1698,7 @@
 	struct page *page = NULL;
 	struct reclaim_state reclaim_state;
 	struct task_struct *p = current;
+	bool drained = false;
 
 	cond_resched();
 
@@ -1698,14 +1717,25 @@
 
 	cond_resched();
 
-	if (order != 0)
-		drain_all_pages();
+	if (unlikely(!(*did_some_progress)))
+		return NULL;
 
-	if (likely(*did_some_progress))
-		page = get_page_from_freelist(gfp_mask, nodemask, order,
+retry:
+	page = get_page_from_freelist(gfp_mask, nodemask, order,
 					zonelist, high_zoneidx,
 					alloc_flags, preferred_zone,
 					migratetype);
+
+	/*
+	 * If an allocation failed after direct reclaim, it could be because
+	 * pages are pinned on the per-cpu lists. Drain them and try again
+	 */
+	if (!page && !drained) {
+		drain_all_pages();
+		drained = true;
+		goto retry;
+	}
+
 	return page;
 }
 
@@ -2237,7 +2267,7 @@
 			" all_unreclaimable? %s"
 			"\n",
 			zone->name,
-			K(zone_page_state(zone, NR_FREE_PAGES)),
+			K(zone_nr_free_pages(zone)),
 			K(min_wmark_pages(zone)),
 			K(low_wmark_pages(zone)),
 			K(high_wmark_pages(zone)),
@@ -4628,6 +4658,21 @@
 		spin_unlock_irqrestore(&zone->lock, flags);
 	}
 
+#ifdef CONFIG_XEN
+	for_each_populated_zone(zone) {
+		unsigned int cpu;
+
+		for_each_online_cpu(cpu) {
+			unsigned long high;
+
+			high = percpu_pagelist_fraction
+			       ? zone->present_pages / percpu_pagelist_fraction
+			       : 5 * zone_batchsize(zone);
+			setup_pagelist_highmark(zone_pcp(zone, cpu), high);
+		}
+	}
+#endif
+
 	/* update totalreserve_pages */
 	calculate_totalreserve_pages();
 }
--- linux-ec2-2.6.32.orig/mm/filemap.c
+++ linux-ec2-2.6.32/mm/filemap.c
@@ -33,6 +33,7 @@
 #include <linux/cpuset.h>
 #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
 #include <linux/memcontrol.h>
+#include <linux/precache.h>
 #include <linux/mm_inline.h> /* for page_is_file_cache() */
 #include "internal.h"
 
@@ -119,6 +120,16 @@
 {
 	struct address_space *mapping = page->mapping;
 
+	/*
+	 * if we're uptodate, flush out into the precache, otherwise
+	 * invalidate any existing precache entries.  We can't leave
+	 * stale data around in the precache once our page is gone
+	 */
+	if (PageUptodate(page))
+		precache_put(page->mapping, page->index, page);
+	else
+		precache_flush(page->mapping, page->index);
+
 	radix_tree_delete(&mapping->page_tree, page->index);
 	page->mapping = NULL;
 	mapping->nrpages--;
@@ -462,7 +473,7 @@
 	/*
 	 * Splice_read and readahead add shmem/tmpfs pages into the page cache
 	 * before shmem_readpage has a chance to mark them as SwapBacked: they
-	 * need to go on the active_anon lru below, and mem_cgroup_cache_charge
+	 * need to go on the anon lru below, and mem_cgroup_cache_charge
 	 * (called in add_to_page_cache) needs to know where they're going too.
 	 */
 	if (mapping_cap_swap_backed(mapping))
@@ -473,7 +484,7 @@
 		if (page_is_file_cache(page))
 			lru_cache_add_file(page);
 		else
-			lru_cache_add_active_anon(page);
+			lru_cache_add_anon(page);
 	}
 	return ret;
 }
@@ -1030,6 +1041,9 @@
 				goto page_not_up_to_date;
 			if (!trylock_page(page))
 				goto page_not_up_to_date;
+			/* Did it get truncated before we got the lock? */
+			if (!page->mapping)
+				goto page_not_up_to_date_locked;
 			if (!mapping->a_ops->is_partially_uptodate(page,
 								desc, offset))
 				goto page_not_up_to_date_locked;
@@ -1120,6 +1134,12 @@
 		}
 
 readpage:
+		/*
+		 * A previous I/O error may have been due to temporary
+		 * failures, eg. multipath errors.
+		 * PG_error will be set again if readpage fails.
+		 */
+		ClearPageError(page);
 		/* Start the actual read. The read will unlock the page. */
 		error = mapping->a_ops->readpage(filp, page);
 
@@ -1655,14 +1675,15 @@
 static struct page *__read_cache_page(struct address_space *mapping,
 				pgoff_t index,
 				int (*filler)(void *,struct page*),
-				void *data)
+				void *data,
+				gfp_t gfp)
 {
 	struct page *page;
 	int err;
 repeat:
 	page = find_get_page(mapping, index);
 	if (!page) {
-		page = page_cache_alloc_cold(mapping);
+		page = __page_cache_alloc(gfp | __GFP_COLD);
 		if (!page)
 			return ERR_PTR(-ENOMEM);
 		err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
@@ -1682,31 +1703,18 @@
 	return page;
 }
 
-/**
- * read_cache_page_async - read into page cache, fill it if needed
- * @mapping:	the page's address_space
- * @index:	the page index
- * @filler:	function to perform the read
- * @data:	destination for read data
- *
- * Same as read_cache_page, but don't wait for page to become unlocked
- * after submitting it to the filler.
- *
- * Read into the page cache. If a page already exists, and PageUptodate() is
- * not set, try to fill the page but don't wait for it to become unlocked.
- *
- * If the page does not get brought uptodate, return -EIO.
- */
-struct page *read_cache_page_async(struct address_space *mapping,
+static struct page *do_read_cache_page(struct address_space *mapping,
 				pgoff_t index,
 				int (*filler)(void *,struct page*),
-				void *data)
+				void *data,
+				gfp_t gfp)
+
 {
 	struct page *page;
 	int err;
 
 retry:
-	page = __read_cache_page(mapping, index, filler, data);
+	page = __read_cache_page(mapping, index, filler, data, gfp);
 	if (IS_ERR(page))
 		return page;
 	if (PageUptodate(page))
@@ -1731,8 +1739,67 @@
 	mark_page_accessed(page);
 	return page;
 }
+
+/**
+ * read_cache_page_async - read into page cache, fill it if needed
+ * @mapping:	the page's address_space
+ * @index:	the page index
+ * @filler:	function to perform the read
+ * @data:	destination for read data
+ *
+ * Same as read_cache_page, but don't wait for page to become unlocked
+ * after submitting it to the filler.
+ *
+ * Read into the page cache. If a page already exists, and PageUptodate() is
+ * not set, try to fill the page but don't wait for it to become unlocked.
+ *
+ * If the page does not get brought uptodate, return -EIO.
+ */
+struct page *read_cache_page_async(struct address_space *mapping,
+				pgoff_t index,
+				int (*filler)(void *,struct page*),
+				void *data)
+{
+	return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping));
+}
 EXPORT_SYMBOL(read_cache_page_async);
 
+static struct page *wait_on_page_read(struct page *page)
+{
+	if (!IS_ERR(page)) {
+		wait_on_page_locked(page);
+		if (!PageUptodate(page)) {
+			page_cache_release(page);
+			page = ERR_PTR(-EIO);
+		}
+	}
+	return page;
+}
+
+/**
+ * read_cache_page_gfp - read into page cache, using specified page allocation flags.
+ * @mapping:	the page's address_space
+ * @index:	the page index
+ * @gfp:	the page allocator flags to use if allocating
+ *
+ * This is the same as "read_mapping_page(mapping, index, NULL)", but with
+ * any new page allocations done using the specified allocation flags. Note
+ * that the Radix tree operations will still use GFP_KERNEL, so you can't
+ * expect to do this atomically or anything like that - but you can pass in
+ * other page requirements.
+ *
+ * If the page does not get brought uptodate, return -EIO.
+ */
+struct page *read_cache_page_gfp(struct address_space *mapping,
+				pgoff_t index,
+				gfp_t gfp)
+{
+	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+
+	return wait_on_page_read(do_read_cache_page(mapping, index, filler, NULL, gfp));
+}
+EXPORT_SYMBOL(read_cache_page_gfp);
+
 /**
  * read_cache_page - read into page cache, fill it if needed
  * @mapping:	the page's address_space
@@ -1750,18 +1817,7 @@
 				int (*filler)(void *,struct page*),
 				void *data)
 {
-	struct page *page;
-
-	page = read_cache_page_async(mapping, index, filler, data);
-	if (IS_ERR(page))
-		goto out;
-	wait_on_page_locked(page);
-	if (!PageUptodate(page)) {
-		page_cache_release(page);
-		page = ERR_PTR(-EIO);
-	}
- out:
-	return page;
+	return wait_on_page_read(read_cache_page_async(mapping, index, filler, data));
 }
 EXPORT_SYMBOL(read_cache_page);
 
@@ -2217,6 +2273,9 @@
 		if (unlikely(status))
 			break;
 
+		if (mapping_writably_mapped(mapping))
+			flush_dcache_page(page);
+
 		pagefault_disable();
 		copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
 		pagefault_enable();
--- linux-ec2-2.6.32.orig/mm/mempolicy.c
+++ linux-ec2-2.6.32/mm/mempolicy.c
@@ -1482,7 +1482,7 @@
 		(void)first_zones_zonelist(zonelist, highest_zoneidx,
 							&policy->v.nodes,
 							&zone);
-		return zone->node;
+		return zone ? zone->node : numa_node_id();
 	}
 
 	default:
@@ -2122,8 +2122,8 @@
 			char *rest = nodelist;
 			while (isdigit(*rest))
 				rest++;
-			if (!*rest)
-				err = 0;
+			if (*rest)
+				goto out;
 		}
 		break;
 	case MPOL_INTERLEAVE:
@@ -2132,7 +2132,6 @@
 		 */
 		if (!nodelist)
 			nodes = node_states[N_HIGH_MEMORY];
-		err = 0;
 		break;
 	case MPOL_LOCAL:
 		/*
@@ -2142,11 +2141,19 @@
 			goto out;
 		mode = MPOL_PREFERRED;
 		break;
-
-	/*
-	 * case MPOL_BIND:    mpol_new() enforces non-empty nodemask.
-	 * case MPOL_DEFAULT: mpol_new() enforces empty nodemask, ignores flags.
-	 */
+	case MPOL_DEFAULT:
+		/*
+		 * Insist on a empty nodelist
+		 */
+		if (!nodelist)
+			err = 0;
+		goto out;
+	case MPOL_BIND:
+		/*
+		 * Insist on a nodelist
+		 */
+		if (!nodelist)
+			goto out;
 	}
 
 	mode_flags = 0;
@@ -2160,13 +2167,14 @@
 		else if (!strcmp(flags, "relative"))
 			mode_flags |= MPOL_F_RELATIVE_NODES;
 		else
-			err = 1;
+			goto out;
 	}
 
 	new = mpol_new(mode, mode_flags, &nodes);
 	if (IS_ERR(new))
-		err = 1;
-	else {
+		goto out;
+
+	{
 		int ret;
 		NODEMASK_SCRATCH(scratch);
 		if (scratch) {
@@ -2177,13 +2185,15 @@
 			ret = -ENOMEM;
 		NODEMASK_SCRATCH_FREE(scratch);
 		if (ret) {
-			err = 1;
 			mpol_put(new);
-		} else if (no_context) {
-			/* save for contextualization */
-			new->w.user_nodemask = nodes;
+			goto out;
 		}
 	}
+	err = 0;
+	if (no_context) {
+		/* save for contextualization */
+		new->w.user_nodemask = nodes;
+	}
 
 out:
 	/* Restore string for error message */
--- linux-ec2-2.6.32.orig/mm/memcontrol.c
+++ linux-ec2-2.6.32/mm/memcontrol.c
@@ -758,7 +758,13 @@
 	task_unlock(task);
 	if (!curr)
 		return 0;
-	if (curr->use_hierarchy)
+	/*
+	 * We should check use_hierarchy of "mem" not "curr". Because checking
+	 * use_hierarchy of "curr" here make this function true if hierarchy is
+	 * enabled in "curr" and "curr" is a child of "mem" in *cgroup*
+	 * hierarchy(even if use_hierarchy is disabled in "mem").
+	 */
+	if (mem->use_hierarchy)
 		ret = css_is_ancestor(&curr->css, &mem->css);
 	else
 		ret = (curr == mem);
@@ -2002,12 +2008,12 @@
 	}
 	unlock_page_cgroup(pc);
 
+	*ptr = mem;
 	if (mem) {
-		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false,
+		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, ptr, false,
 						page);
 		css_put(&mem->css);
 	}
-	*ptr = mem;
 	return ret;
 }
 
@@ -2375,7 +2381,7 @@
 	if (free_all)
 		goto try_to_free;
 move_account:
-	while (mem->res.usage > 0) {
+	do {
 		ret = -EBUSY;
 		if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))
 			goto out;
@@ -2402,8 +2408,8 @@
 		if (ret == -ENOMEM)
 			goto try_to_free;
 		cond_resched();
-	}
-	ret = 0;
+	/* "ret" should also be checked to ensure all lists are empty. */
+	} while (mem->res.usage > 0 || ret);
 out:
 	css_put(&mem->css);
 	return ret;
@@ -2436,10 +2442,7 @@
 	}
 	lru_add_drain();
 	/* try move_account...there may be some *locked* pages. */
-	if (mem->res.usage)
-		goto move_account;
-	ret = 0;
-	goto out;
+	goto move_account;
 }
 
 int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
@@ -2541,6 +2544,7 @@
 			val += idx_val;
 			mem_cgroup_get_recursive_idx_stat(mem,
 				MEM_CGROUP_STAT_SWAPOUT, &idx_val);
+			val += idx_val;
 			val <<= PAGE_SHIFT;
 		} else
 			val = res_counter_read_u64(&mem->memsw, name);
--- linux-ec2-2.6.32.orig/mm/fadvise.c
+++ linux-ec2-2.6.32/mm/fadvise.c
@@ -77,12 +77,20 @@
 	switch (advice) {
 	case POSIX_FADV_NORMAL:
 		file->f_ra.ra_pages = bdi->ra_pages;
+		spin_lock(&file->f_lock);
+		file->f_mode &= ~FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_RANDOM:
-		file->f_ra.ra_pages = 0;
+		spin_lock(&file->f_lock);
+		file->f_mode |= FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_SEQUENTIAL:
 		file->f_ra.ra_pages = bdi->ra_pages * 2;
+		spin_lock(&file->f_lock);
+		file->f_mode &= ~FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_WILLNEED:
 		if (!mapping->a_ops->readpage) {
--- linux-ec2-2.6.32.orig/crypto/authenc.c
+++ linux-ec2-2.6.32/crypto/authenc.c
@@ -46,6 +46,12 @@
 	char tail[];
 };
 
+static void authenc_request_complete(struct aead_request *req, int err)
+{
+	if (err != -EINPROGRESS)
+		aead_request_complete(req, err);
+}
+
 static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
 				 unsigned int keylen)
 {
@@ -142,7 +148,7 @@
 				 crypto_aead_authsize(authenc), 1);
 
 out:
-	aead_request_complete(req, err);
+	authenc_request_complete(req, err);
 }
 
 static void authenc_geniv_ahash_done(struct crypto_async_request *areq, int err)
@@ -208,7 +214,7 @@
 	err = crypto_ablkcipher_decrypt(abreq);
 
 out:
-	aead_request_complete(req, err);
+	authenc_request_complete(req, err);
 }
 
 static void authenc_verify_ahash_done(struct crypto_async_request *areq,
@@ -245,7 +251,7 @@
 	err = crypto_ablkcipher_decrypt(abreq);
 
 out:
-	aead_request_complete(req, err);
+	authenc_request_complete(req, err);
 }
 
 static u8 *crypto_authenc_ahash_fb(struct aead_request *req, unsigned int flags)
@@ -379,7 +385,7 @@
 		err = crypto_authenc_genicv(areq, iv, 0);
 	}
 
-	aead_request_complete(areq, err);
+	authenc_request_complete(areq, err);
 }
 
 static int crypto_authenc_encrypt(struct aead_request *req)
@@ -418,7 +424,7 @@
 		err = crypto_authenc_genicv(areq, greq->giv, 0);
 	}
 
-	aead_request_complete(areq, err);
+	authenc_request_complete(areq, err);
 }
 
 static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
--- linux-ec2-2.6.32.orig/crypto/Kconfig
+++ linux-ec2-2.6.32/crypto/Kconfig
@@ -440,6 +440,15 @@
 	  See also:
 	  <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
 
+config CRYPTO_GHASH_CLMUL_NI_INTEL
+	tristate "GHASH digest algorithm (CLMUL-NI accelerated)"
+	depends on (X86 || UML_X86) && 64BIT
+	select CRYPTO_SHASH
+	select CRYPTO_CRYPTD
+	help
+	  GHASH is message digest algorithm for GCM (Galois/Counter Mode).
+	  The implementation is accelerated by CLMUL-NI of Intel.
+
 comment "Ciphers"
 
 config CRYPTO_AES
--- linux-ec2-2.6.32.orig/crypto/testmgr.c
+++ linux-ec2-2.6.32/crypto/testmgr.c
@@ -1477,9 +1477,54 @@
 	return err;
 }
 
+static int alg_test_null(const struct alg_test_desc *desc,
+			     const char *driver, u32 type, u32 mask)
+{
+	return 0;
+}
+
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
+		.alg = "__driver-cbc-aes-aesni",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "__driver-ecb-aes-aesni",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "__ghash-pclmulqdqni",
+		.test = alg_test_null,
+		.suite = {
+			.hash = {
+				.vecs = NULL,
+				.count = 0
+			}
+		}
+	}, {
 		.alg = "ansi_cprng",
 		.test = alg_test_cprng,
 		.fips_allowed = 1,
@@ -1623,6 +1668,30 @@
 			}
 		}
 	}, {
+		.alg = "cryptd(__driver-ecb-aes-aesni)",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "cryptd(__ghash-pclmulqdqni)",
+		.test = alg_test_null,
+		.suite = {
+			.hash = {
+				.vecs = NULL,
+				.count = 0
+			}
+		}
+	}, {
 		.alg = "ctr(aes)",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
@@ -1669,6 +1738,21 @@
 			}
 		}
 	}, {
+		.alg = "ecb(__aes-aesni)",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "ecb(aes)",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
--- linux-ec2-2.6.32.orig/crypto/cryptd.c
+++ linux-ec2-2.6.32/crypto/cryptd.c
@@ -711,6 +711,13 @@
 }
 EXPORT_SYMBOL_GPL(cryptd_ahash_child);
 
+struct shash_desc *cryptd_shash_desc(struct ahash_request *req)
+{
+	struct cryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
+	return &rctx->desc;
+}
+EXPORT_SYMBOL_GPL(cryptd_shash_desc);
+
 void cryptd_free_ahash(struct cryptd_ahash *tfm)
 {
 	crypto_free_ahash(&tfm->base);
--- linux-ec2-2.6.32.orig/crypto/async_tx/async_raid6_recov.c
+++ linux-ec2-2.6.32/crypto/async_tx/async_raid6_recov.c
@@ -324,6 +324,7 @@
 async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
 			struct page **blocks, struct async_submit_ctl *submit)
 {
+	void *scribble = submit->scribble;
 	int non_zero_srcs, i;
 
 	BUG_ON(faila == failb);
@@ -332,11 +333,13 @@
 
 	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
 
-	/* we need to preserve the contents of 'blocks' for the async
-	 * case, so punt to synchronous if a scribble buffer is not available
+	/* if a dma resource is not available or a scribble buffer is not
+	 * available punt to the synchronous path.  In the 'dma not
+	 * available' case be sure to use the scribble buffer to
+	 * preserve the content of 'blocks' as the caller intended.
 	 */
-	if (!submit->scribble) {
-		void **ptrs = (void **) blocks;
+	if (!async_dma_find_channel(DMA_PQ) || !scribble) {
+		void **ptrs = scribble ? scribble : (void **) blocks;
 
 		async_tx_quiesce(&submit->depend_tx);
 		for (i = 0; i < disks; i++)
@@ -406,11 +409,13 @@
 
 	pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
 
-	/* we need to preserve the contents of 'blocks' for the async
-	 * case, so punt to synchronous if a scribble buffer is not available
+	/* if a dma resource is not available or a scribble buffer is not
+	 * available punt to the synchronous path.  In the 'dma not
+	 * available' case be sure to use the scribble buffer to
+	 * preserve the content of 'blocks' as the caller intended.
 	 */
-	if (!scribble) {
-		void **ptrs = (void **) blocks;
+	if (!async_dma_find_channel(DMA_PQ) || !scribble) {
+		void **ptrs = scribble ? scribble : (void **) blocks;
 
 		async_tx_quiesce(&submit->depend_tx);
 		for (i = 0; i < disks; i++)
--- linux-ec2-2.6.32.orig/include/Kbuild
+++ linux-ec2-2.6.32/include/Kbuild
@@ -9,4 +9,3 @@
 header-y += video/
 header-y += drm/
 header-y += xen/
-header-y += scsi/
--- linux-ec2-2.6.32.orig/include/asm-generic/vmlinux.lds.h
+++ linux-ec2-2.6.32/include/asm-generic/vmlinux.lds.h
@@ -585,6 +585,7 @@
   	*(.initcall0s.init)						\
   	*(.initcall1.init)						\
   	*(.initcall1s.init)						\
+	*(.initcallearlyrootfs.init)					\
   	*(.initcall2.init)						\
   	*(.initcall2s.init)						\
   	*(.initcall3.init)						\
--- linux-ec2-2.6.32.orig/include/asm-generic/dma-mapping-common.h
+++ linux-ec2-2.6.32/include/asm-generic/dma-mapping-common.h
@@ -131,7 +131,7 @@
 		debug_dma_sync_single_range_for_cpu(dev, addr, offset, size, dir);
 
 	} else
-		dma_sync_single_for_cpu(dev, addr, size, dir);
+		dma_sync_single_for_cpu(dev, addr + offset, size, dir);
 }
 
 static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -148,7 +148,7 @@
 		debug_dma_sync_single_range_for_device(dev, addr, offset, size, dir);
 
 	} else
-		dma_sync_single_for_device(dev, addr, size, dir);
+		dma_sync_single_for_device(dev, addr + offset, size, dir);
 }
 
 static inline void
--- linux-ec2-2.6.32.orig/include/sound/soc-dapm.h
+++ linux-ec2-2.6.32/include/sound/soc-dapm.h
@@ -46,25 +46,25 @@
 /* platform domain */
 #define SND_SOC_DAPM_INPUT(wname) \
 {	.id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0}
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_OUTPUT(wname) \
 {	.id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0}
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_MIC(wname, wevent) \
 {	.id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
 #define SND_SOC_DAPM_HP(wname, wevent) \
 {	.id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_SPK(wname, wevent) \
 {	.id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_LINE(wname, wevent) \
 {	.id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
 
 /* path domain */
@@ -129,11 +129,11 @@
 /* events that are pre and post DAPM */
 #define SND_SOC_DAPM_PRE(wname, wevent) \
 {	.id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
 #define SND_SOC_DAPM_POST(wname, wevent) \
 {	.id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
-	.num_kcontrols = 0, .event = wevent, \
+	.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
 	.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
 
 /* stream domain */
--- linux-ec2-2.6.32.orig/include/sound/emu10k1.h
+++ linux-ec2-2.6.32/include/sound/emu10k1.h
@@ -1707,6 +1707,7 @@
 	unsigned int card_type;			/* EMU10K1_CARD_* */
 	unsigned int ecard_ctrl;		/* ecard control bits */
 	unsigned long dma_mask;			/* PCI DMA mask */
+	unsigned int delay_pcm_irq;		/* in samples */
 	int max_cache_pages;			/* max memory size / PAGE_SIZE */
 	struct snd_dma_buffer silent_page;	/* silent page */
 	struct snd_dma_buffer ptb_pages;	/* page table pages */
--- linux-ec2-2.6.32.orig/include/acpi/processor.h
+++ linux-ec2-2.6.32/include/acpi/processor.h
@@ -17,6 +17,12 @@
 #define ACPI_PROCESSOR_MAX_THROTTLE	250	/* 25% */
 #define ACPI_PROCESSOR_MAX_DUTY_WIDTH	4
 
+#ifdef CONFIG_XEN
+#define NR_ACPI_CPUS			(NR_CPUS < 256 ? 256 : NR_CPUS)
+#else
+#define NR_ACPI_CPUS			NR_CPUS
+#endif /* CONFIG_XEN */
+
 #define ACPI_PDC_REVISION_ID		0x1
 
 #define ACPI_PSD_REV0_REVISION		0	/* Support for _PSD as in ACPI 3.0 */
@@ -42,13 +48,24 @@
 
 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;
 	u8 space_id;
 	u8 bit_width;
 	u8 bit_offset;
-	u8 reserved;
+	u8 access_size;
 	u64 address;
 } __attribute__ ((packed));
 
@@ -74,6 +91,13 @@
 	u32 power;
 	u32 usage;
 	u64 time;
+	u8 bm_sts_skip;
+#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;
 	char desc[ACPI_CX_DESC_LEN];
@@ -304,6 +328,9 @@
 {
 	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;
@@ -316,6 +343,7 @@
 	}
 	return 0;
 }
+#endif				/* CONFIG_PROCESSOR_EXTERNAL_CONTROL */
 #endif				/* CONFIG_CPU_FREQ */
 
 /* in processor_throttling.c */
@@ -353,4 +381,127 @@
 }
 #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 type);
+};
+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 **);
+
+/*
+ * Declarations for objects and functions removed in native 2.6.29, and
+ * thus moved to drivers/acpi/processor_extcntl.c.
+ */
+extern struct notifier_block acpi_processor_latency_notifier;
+int acpi_processor_set_power_policy(struct acpi_processor *);
+#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 */
+
+#ifdef CONFIG_XEN
+static inline void xen_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 inline void xen_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 inline void xen_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;
+}
+
+#endif /* CONFIG_XEN */
+
 #endif
--- linux-ec2-2.6.32.orig/include/acpi/platform/aclinux.h
+++ linux-ec2-2.6.32/include/acpi/platform/aclinux.h
@@ -152,7 +152,7 @@
 #include <linux/hardirq.h>
 #define ACPI_PREEMPTION_POINT() \
 	do { \
-		if (!in_atomic_preempt_off()) \
+		if (!in_atomic_preempt_off() && !irqs_disabled()) \
 			cond_resched(); \
 	} while (0)
 
--- linux-ec2-2.6.32.orig/include/scsi/scsi_bsg_fc.h
+++ linux-ec2-2.6.32/include/scsi/scsi_bsg_fc.h
@@ -292,7 +292,7 @@
 		struct fc_bsg_rport_els		r_els;
 		struct fc_bsg_rport_ct		r_ct;
 	} rqst_data;
-};
+} __attribute__((packed));
 
 
 /* response (request sense data) structure of the sg_io_v4 */
--- linux-ec2-2.6.32.orig/include/scsi/fc_frame.h
+++ linux-ec2-2.6.32/include/scsi/fc_frame.h
@@ -37,6 +37,9 @@
 #define	FC_FRAME_HEADROOM	32	/* headroom for VLAN + FCoE headers */
 #define	FC_FRAME_TAILROOM	8	/* trailer space for FCoE */
 
+/* Max number of skb frags allowed, reserving one for fcoe_crc_eof page */
+#define FC_FRAME_SG_LEN		(MAX_SKB_FRAGS - 1)
+
 #define fp_skb(fp)	(&((fp)->skb))
 #define fr_hdr(fp)	((fp)->skb.data)
 #define fr_len(fp)	((fp)->skb.len)
--- linux-ec2-2.6.32.orig/include/scsi/osd_protocol.h
+++ linux-ec2-2.6.32/include/scsi/osd_protocol.h
@@ -17,6 +17,7 @@
 #define __OSD_PROTOCOL_H__
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 
--- linux-ec2-2.6.32.orig/include/scsi/scsi_device.h
+++ linux-ec2-2.6.32/include/scsi/scsi_device.h
@@ -446,7 +446,7 @@
 }
 static inline int scsi_device_enclosure(struct scsi_device *sdev)
 {
-	return sdev->inquiry[6] & (1<<6);
+	return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1;
 }
 
 static inline int scsi_device_protection(struct scsi_device *sdev)
--- linux-ec2-2.6.32.orig/include/scsi/libfc.h
+++ linux-ec2-2.6.32/include/scsi/libfc.h
@@ -145,6 +145,7 @@
 	RPORT_ST_LOGO,		/* port logout sent */
 	RPORT_ST_ADISC,		/* Discover Address sent */
 	RPORT_ST_DELETE,	/* port being deleted */
+	RPORT_ST_RESTART,       /* remote port being deleted and will restart */
 };
 
 /**
--- linux-ec2-2.6.32.orig/include/scsi/scsi_host.h
+++ linux-ec2-2.6.32/include/scsi/scsi_host.h
@@ -677,6 +677,12 @@
 	void *shost_data;
 
 	/*
+	 * Points to the physical bus device we'd use to do DMA
+	 * Needed just in case we have virtual hosts.
+	 */
+	struct device *dma_dev;
+
+	/*
 	 * We should ensure that this is aligned, both for better performance
 	 * and also because some compilers (m68k) don't automatically force
 	 * alignment to a long boundary.
@@ -720,7 +726,9 @@
 extern void scsi_flush_work(struct Scsi_Host *);
 
 extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
-extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
+extern int __must_check scsi_add_host_with_dma(struct Scsi_Host *,
+					       struct device *,
+					       struct device *);
 extern void scsi_scan_host(struct Scsi_Host *);
 extern void scsi_rescan_device(struct device *);
 extern void scsi_remove_host(struct Scsi_Host *);
@@ -731,6 +739,12 @@
 
 extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
 
+static inline int __must_check scsi_add_host(struct Scsi_Host *host,
+					     struct device *dev)
+{
+	return scsi_add_host_with_dma(host, dev, dev);
+}
+
 static inline struct device *scsi_get_device(struct Scsi_Host *shost)
 {
         return shost->shost_gendev.parent;
--- linux-ec2-2.6.32.orig/include/math-emu/op-common.h
+++ linux-ec2-2.6.32/include/math-emu/op-common.h
@@ -799,7 +799,7 @@
 		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
 	X##_e = rsize - X##_e - 1;					\
 									\
-	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)	\
+	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e)	\
 	  __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
 	_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);			\
 	if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)			\
--- linux-ec2-2.6.32.orig/include/linux/inetdevice.h
+++ linux-ec2-2.6.32/include/linux/inetdevice.h
@@ -83,6 +83,7 @@
 #define IN_DEV_FORWARD(in_dev)		IN_DEV_CONF_GET((in_dev), FORWARDING)
 #define IN_DEV_MFORWARD(in_dev)		IN_DEV_ANDCONF((in_dev), MC_FORWARDING)
 #define IN_DEV_RPFILTER(in_dev)		IN_DEV_MAXCONF((in_dev), RP_FILTER)
+#define IN_DEV_SRC_VMARK(in_dev)    	IN_DEV_ORCONF((in_dev), SRC_VMARK)
 #define IN_DEV_SOURCE_ROUTE(in_dev)	IN_DEV_ANDCONF((in_dev), \
 						       ACCEPT_SOURCE_ROUTE)
 #define IN_DEV_BOOTP_RELAY(in_dev)	IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
--- linux-ec2-2.6.32.orig/include/linux/libata.h
+++ linux-ec2-2.6.32/include/linux/libata.h
@@ -339,6 +339,7 @@
 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
 	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
 	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
+	ATA_EHI_NO_RECOVERY	= (1 << 4),  /* no recovery */
 
 	ATA_EHI_DID_SOFTRESET	= (1 << 16), /* already soft-reset this port */
 	ATA_EHI_DID_HARDRESET	= (1 << 17), /* already soft-reset this port */
@@ -354,6 +355,9 @@
 	/* max tries if error condition is still set after ->error_handler */
 	ATA_EH_MAX_TRIES	= 5,
 
+	/* sometimes resuming a link requires several retries */
+	ATA_LINK_RESUME_TRIES	= 5,
+
 	/* how hard are we gonna try to probe/recover devices */
 	ATA_PROBE_MAX_TRIES	= 3,
 	ATA_EH_DEV_TRIES	= 3,
--- linux-ec2-2.6.32.orig/include/linux/fb.h
+++ linux-ec2-2.6.32/include/linux/fb.h
@@ -784,8 +784,6 @@
 #define FBINFO_MISC_USEREVENT          0x10000 /* event request
 						  from userspace */
 #define FBINFO_MISC_TILEBLITTING       0x20000 /* use tile blitting */
-#define FBINFO_MISC_FIRMWARE           0x40000 /* a replaceable firmware
-						  inited framebuffer */
 
 /* A driver may set this flag to indicate that it does want a set_par to be
  * called every time when fbcon_switch is executed. The advantage is that with
@@ -799,6 +797,8 @@
  */
 #define FBINFO_MISC_ALWAYS_SETPAR   0x40000
 
+/* where the fb is a firmware driver, and can be replaced with a proper one */
+#define FBINFO_MISC_FIRMWARE        0x80000
 /*
  * Host and GPU endianness differ.
  */
--- linux-ec2-2.6.32.orig/include/linux/elfnote.h
+++ linux-ec2-2.6.32/include/linux/elfnote.h
@@ -52,7 +52,7 @@
 4484:.balign 4				;	\
 .popsection				;
 
-#define ELFNOTE(name, type, desc)		\
+#define ELFNOTE(name, type, desc...)		\
 	ELFNOTE_START(name, type, "")		\
 		desc			;	\
 	ELFNOTE_END
--- linux-ec2-2.6.32.orig/include/linux/acpi.h
+++ linux-ec2-2.6.32/include/linux/acpi.h
@@ -247,12 +247,21 @@
 int acpi_check_mem_region(resource_size_t start, resource_size_t n,
 		      const char *name);
 
+int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn);
+
 #ifdef CONFIG_PM_SLEEP
 void __init acpi_no_s4_hw_signature(void);
 void __init acpi_old_suspend_ordering(void);
 void __init acpi_s4_no_nvs(void);
 #endif /* CONFIG_PM_SLEEP */
 
+struct acpi_osc_context {
+	char *uuid_str; /* uuid string */
+	int rev;
+	struct acpi_buffer cap; /* arg2/arg3 */
+	struct acpi_buffer ret; /* free by caller if success */
+};
+
 #define OSC_QUERY_TYPE			0
 #define OSC_SUPPORT_TYPE 		1
 #define OSC_CONTROL_TYPE		2
@@ -265,6 +274,15 @@
 #define OSC_INVALID_REVISION_ERROR	8
 #define OSC_CAPABILITIES_MASK_ERROR	16
 
+acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
+
+/* platform-wide _OSC bits */
+#define OSC_SB_PAD_SUPPORT		1
+#define OSC_SB_PPC_OST_SUPPORT		2
+#define OSC_SB_PR3_SUPPORT		4
+#define OSC_SB_CPUHP_OST_SUPPORT	8
+#define OSC_SB_APEI_SUPPORT		16
+
 /* _OSC DW1 Definition (OS Support Fields) */
 #define OSC_EXT_PCI_CONFIG_SUPPORT		1
 #define OSC_ACTIVE_STATE_PWR_SUPPORT 		2
--- linux-ec2-2.6.32.orig/include/linux/mmzone.h
+++ linux-ec2-2.6.32/include/linux/mmzone.h
@@ -290,6 +290,13 @@
 	unsigned long watermark[NR_WMARK];
 
 	/*
+	 * When free pages are below this point, additional steps are taken
+	 * when reading the number of free pages to avoid per-cpu counter
+	 * drift allowing watermarks to be breached
+	 */
+	unsigned long percpu_drift_mark;
+
+	/*
 	 * We don't know if the memory that we're going to allocate will be freeable
 	 * or/and it will be released eventually, so to avoid totally wasting several
 	 * GB of ram we must reserve some of the lower zone memory (otherwise we risk
@@ -460,6 +467,12 @@
 	return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 }
 
+#ifdef CONFIG_SMP
+unsigned long zone_nr_free_pages(struct zone *zone);
+#else
+#define zone_nr_free_pages(zone) zone_page_state(zone, NR_FREE_PAGES)
+#endif /* CONFIG_SMP */
+
 /*
  * The "priority" of VM scanning is how much of the queues we will scan in one
  * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
--- linux-ec2-2.6.32.orig/include/linux/init.h
+++ linux-ec2-2.6.32/include/linux/init.h
@@ -186,6 +186,7 @@
 
 #define core_initcall(fn)		__define_initcall("1",fn,1)
 #define core_initcall_sync(fn)		__define_initcall("1s",fn,1s)
+#define earlyrootfs_initcall(fn)	__define_initcall("earlyrootfs",fn,rootfs)
 #define postcore_initcall(fn)		__define_initcall("2",fn,2)
 #define postcore_initcall_sync(fn)	__define_initcall("2s",fn,2s)
 #define arch_initcall(fn)		__define_initcall("3",fn,3)
@@ -213,6 +214,8 @@
 	static initcall_t __initcall_##fn \
 	__used __section(.security_initcall.init) = fn
 
+extern struct list_head  populate_rootfs_domain;
+
 struct obs_kernel_param {
 	const char *str;
 	int (*setup_func)(char *);
--- linux-ec2-2.6.32.orig/include/linux/vermagic.h
+++ linux-ec2-2.6.32/include/linux/vermagic.h
@@ -22,6 +22,11 @@
 #else
 #define MODULE_VERMAGIC_MODVERSIONS ""
 #endif
+#ifdef CONFIG_XEN
+#define MODULE_VERMAGIC_XEN "Xen "
+#else
+#define MODULE_VERMAGIC_XEN
+#endif
 #ifndef MODULE_ARCH_VERMAGIC
 #define MODULE_ARCH_VERMAGIC ""
 #endif
@@ -30,5 +35,5 @@
 	UTS_RELEASE " "							\
 	MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT 			\
 	MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS	\
-	MODULE_ARCH_VERMAGIC
+	MODULE_VERMAGIC_XEN MODULE_ARCH_VERMAGIC
 
--- linux-ec2-2.6.32.orig/include/linux/time.h
+++ linux-ec2-2.6.32/include/linux/time.h
@@ -148,6 +148,7 @@
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_valid_for_hres(void);
+extern u64 timekeeping_max_deferment(void);
 extern void update_wall_time(void);
 extern void update_xtime_cache(u64 nsec);
 extern void timekeeping_leap_insert(int leapsecond);
--- linux-ec2-2.6.32.orig/include/linux/oprofile.h
+++ linux-ec2-2.6.32/include/linux/oprofile.h
@@ -16,6 +16,9 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/xenoprof.h>
+#endif
  
 /* Each escaped entry is prefixed by ESCAPE_CODE
  * then one of the following codes, then the
@@ -28,14 +31,18 @@
 #define CPU_SWITCH_CODE			2
 #define COOKIE_SWITCH_CODE		3
 #define KERNEL_ENTER_SWITCH_CODE	4
-#define KERNEL_EXIT_SWITCH_CODE		5
+#define USER_ENTER_SWITCH_CODE		5
 #define MODULE_LOADED_CODE		6
 #define CTX_TGID_CODE			7
 #define TRACE_BEGIN_CODE		8
 #define TRACE_END_CODE			9
 #define XEN_ENTER_SWITCH_CODE		10
+#ifndef CONFIG_XEN
 #define SPU_PROFILING_CODE		11
 #define SPU_CTX_SWITCH_CODE		12
+#else
+#define DOMAIN_SWITCH_CODE		11
+#endif
 #define IBS_FETCH_CODE			13
 #define IBS_OP_CODE			14
 
@@ -49,6 +56,12 @@
 	/* create any necessary configuration files in the oprofile fs.
 	 * Optional. */
 	int (*create_files)(struct super_block * sb, struct dentry * root);
+#ifdef CONFIG_XEN
+	/* setup active domains with Xen */
+	int (*set_active)(int *active_domains, unsigned int adomains);
+	/* setup passive domains with Xen */
+	int (*set_passive)(int *passive_domains, unsigned int pdomains);
+#endif
 	/* Do any necessary interrupt setup. Optional. */
 	int (*setup)(void);
 	/* Do any necessary interrupt shutdown. Optional. */
@@ -107,9 +120,14 @@
  * backtrace. */
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
 
+void oprofile_add_mode(int cpu_mode);
+
 /* add a backtrace entry, to be called from the ->backtrace callback */
 void oprofile_add_trace(unsigned long eip);
 
+/* add a domain switch entry */
+int oprofile_add_domain_switch(int32_t domain_id);
+
 
 /**
  * Create a file of the given name as a child of the given root, with
--- linux-ec2-2.6.32.orig/include/linux/tboot.h
+++ linux-ec2-2.6.32/include/linux/tboot.h
@@ -150,6 +150,7 @@
 
 #else
 
+#define tboot_enabled()			0
 #define tboot_probe()			do { } while (0)
 #define tboot_shutdown(shutdown_type)	do { } while (0)
 #define tboot_sleep(sleep_state, pm1a_control, pm1b_control)	\
--- linux-ec2-2.6.32.orig/include/linux/resource.h
+++ linux-ec2-2.6.32/include/linux/resource.h
@@ -3,8 +3,6 @@
 
 #include <linux/time.h>
 
-struct task_struct;
-
 /*
  * Resource control/accounting header file for linux
  */
@@ -55,8 +53,11 @@
 /*
  * Limit the stack by to some sane default: root can always
  * increase this limit if needed..  8MB seems reasonable.
+ *
+ * (2MB more to cover randomization effects.)
  */
-#define _STK_LIM	(8*1024*1024)
+#define _STK_LIM	(10*1024*1024)
+#define EXEC_STACK_BIAS	(2*1024*1024)
 
 /*
  * GPG2 wants 64kB of mlocked memory, to make sure pass phrases
@@ -70,6 +71,12 @@
  */
 #include <asm/resource.h>
 
+#ifdef __KERNEL__
+
+struct task_struct;
+
 int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
 
+#endif /* __KERNEL__ */
+
 #endif
--- linux-ec2-2.6.32.orig/include/linux/ftrace.h
+++ linux-ec2-2.6.32/include/linux/ftrace.h
@@ -412,6 +412,7 @@
 
 extern void ftrace_graph_init_task(struct task_struct *t);
 extern void ftrace_graph_exit_task(struct task_struct *t);
+extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu);
 
 static inline int task_curr_ret_stack(struct task_struct *t)
 {
@@ -435,6 +436,7 @@
 
 static inline void ftrace_graph_init_task(struct task_struct *t) { }
 static inline void ftrace_graph_exit_task(struct task_struct *t) { }
+static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { }
 
 static inline int task_curr_ret_stack(struct task_struct *tsk)
 {
--- linux-ec2-2.6.32.orig/include/linux/quotaops.h
+++ linux-ec2-2.6.32/include/linux/quotaops.h
@@ -26,6 +26,10 @@
 		sb->s_qcop->quota_sync(sb, type);
 }
 
+void inode_add_rsv_space(struct inode *inode, qsize_t number);
+void inode_claim_rsv_space(struct inode *inode, qsize_t number);
+void inode_sub_rsv_space(struct inode *inode, qsize_t number);
+
 int dquot_initialize(struct inode *inode, int type);
 int dquot_drop(struct inode *inode);
 struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
@@ -42,7 +46,6 @@
 int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
 int dquot_claim_space(struct inode *inode, qsize_t number);
 void dquot_release_reserved_space(struct inode *inode, qsize_t number);
-qsize_t dquot_get_reserved_space(struct inode *inode);
 
 int dquot_free_space(struct inode *inode, qsize_t number);
 int dquot_free_inode(const struct inode *inode, qsize_t number);
@@ -199,6 +202,8 @@
 		if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA)
 			return 1;
 	}
+	else
+		inode_add_rsv_space(inode, nr);
 	return 0;
 }
 
@@ -221,7 +226,7 @@
 		if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
 			return 1;
 	} else
-		inode_add_bytes(inode, nr);
+		inode_claim_rsv_space(inode, nr);
 
 	mark_inode_dirty(inode);
 	return 0;
@@ -235,6 +240,8 @@
 {
 	if (sb_any_quota_active(inode->i_sb))
 		inode->i_sb->dq_op->release_rsv(inode, nr);
+	else
+		inode_sub_rsv_space(inode, nr);
 }
 
 static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
--- linux-ec2-2.6.32.orig/include/linux/vmstat.h
+++ linux-ec2-2.6.32/include/linux/vmstat.h
@@ -166,6 +166,28 @@
 	return x;
 }
 
+/*
+ * More accurate version that also considers the currently pending
+ * deltas. For that we need to loop over all cpus to find the current
+ * deltas. There is no synchronization so the result cannot be
+ * exactly accurate either.
+ */
+static inline unsigned long zone_page_state_snapshot(struct zone *zone,
+					enum zone_stat_item item)
+{
+	long x = atomic_long_read(&zone->vm_stat[item]);
+
+#ifdef CONFIG_SMP
+	int cpu;
+	for_each_online_cpu(cpu)
+		x += zone_pcp(zone, cpu)->vm_stat_diff[item];
+
+	if (x < 0)
+		x = 0;
+#endif
+	return x;
+}
+
 extern unsigned long global_reclaimable_pages(void);
 extern unsigned long zone_reclaimable_pages(struct zone *zone);
 
--- linux-ec2-2.6.32.orig/include/linux/pagemap.h
+++ linux-ec2-2.6.32/include/linux/pagemap.h
@@ -253,6 +253,8 @@
 extern struct page * read_cache_page(struct address_space *mapping,
 				pgoff_t index, filler_t *filler,
 				void *data);
+extern struct page * read_cache_page_gfp(struct address_space *mapping,
+				pgoff_t index, gfp_t gfp_mask);
 extern int read_cache_pages(struct address_space *mapping,
 		struct list_head *pages, filler_t *filler, void *data);
 
--- linux-ec2-2.6.32.orig/include/linux/perf_event.h
+++ linux-ec2-2.6.32/include/linux/perf_event.h
@@ -219,7 +219,7 @@
 #define PERF_EVENT_IOC_DISABLE		_IO ('$', 1)
 #define PERF_EVENT_IOC_REFRESH		_IO ('$', 2)
 #define PERF_EVENT_IOC_RESET		_IO ('$', 3)
-#define PERF_EVENT_IOC_PERIOD		_IOW('$', 4, u64)
+#define PERF_EVENT_IOC_PERIOD		_IOW('$', 4, __u64)
 #define PERF_EVENT_IOC_SET_OUTPUT	_IO ('$', 5)
 
 enum perf_event_ioc_flags {
--- linux-ec2-2.6.32.orig/include/linux/backing-dev.h
+++ linux-ec2-2.6.32/include/linux/backing-dev.h
@@ -81,8 +81,6 @@
 	struct bdi_writeback wb;  /* default writeback info for this bdi */
 	spinlock_t wb_lock;	  /* protects update side of wb_list */
 	struct list_head wb_list; /* the flusher threads hanging off this bdi */
-	unsigned long wb_mask;	  /* bitmask of registered tasks */
-	unsigned int wb_cnt;	  /* number of registered tasks */
 
 	struct list_head work_list;
 
@@ -101,8 +99,8 @@
 		const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
 void bdi_unregister(struct backing_dev_info *bdi);
-void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
-				long nr_pages);
+void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages);
+void bdi_start_background_writeback(struct backing_dev_info *bdi);
 int bdi_writeback_task(struct bdi_writeback *wb);
 int bdi_has_dirty_io(struct backing_dev_info *bdi);
 
--- linux-ec2-2.6.32.orig/include/linux/namei.h
+++ linux-ec2-2.6.32/include/linux/namei.h
@@ -75,6 +75,9 @@
 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
 extern void release_open_intent(struct nameidata *);
 
+extern struct dentry *lookup_hash(struct nameidata *nd);
+extern int __lookup_one_len(const char *name, struct qstr *this,
+			    struct dentry *base, int len);
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
 extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
 
--- linux-ec2-2.6.32.orig/include/linux/if_tunnel.h
+++ linux-ec2-2.6.32/include/linux/if_tunnel.h
@@ -2,6 +2,7 @@
 #define _IF_TUNNEL_H_
 
 #include <linux/types.h>
+#include <asm/byteorder.h>
 
 #ifdef __KERNEL__
 #include <linux/ip.h>
--- linux-ec2-2.6.32.orig/include/linux/pci_ids.h
+++ linux-ec2-2.6.32/include/linux/pci_ids.h
@@ -393,6 +393,9 @@
 #define PCI_DEVICE_ID_VLSI_82C147	0x0105
 #define PCI_DEVICE_ID_VLSI_VAS96011	0x0702
 
+/* AMD RD890 Chipset */
+#define PCI_DEVICE_ID_RD890_IOMMU	0x5a23
+
 #define PCI_VENDOR_ID_ADL		0x1005
 #define PCI_DEVICE_ID_ADL_2301		0x2301
 
@@ -1262,6 +1265,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS     0x07D8
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS     0x0AA2
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA	    0x0D85
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_TT128		0x9128
@@ -2030,6 +2034,7 @@
 #define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
 #define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
 
+#define PCI_VENDOR_ID_BCM_GVC          0x14a4
 #define PCI_VENDOR_ID_BROADCOM		0x14e4
 #define PCI_DEVICE_ID_TIGON3_5752	0x1600
 #define PCI_DEVICE_ID_TIGON3_5752M	0x1601
@@ -2290,6 +2295,20 @@
 #define PCI_DEVICE_ID_MPC8536		0x0051
 #define PCI_DEVICE_ID_P2020E		0x0070
 #define PCI_DEVICE_ID_P2020		0x0071
+#define PCI_DEVICE_ID_P2010E		0x0078
+#define PCI_DEVICE_ID_P2010		0x0079
+#define PCI_DEVICE_ID_P1020E		0x0100
+#define PCI_DEVICE_ID_P1020		0x0101
+#define PCI_DEVICE_ID_P1011E		0x0108
+#define PCI_DEVICE_ID_P1011		0x0109
+#define PCI_DEVICE_ID_P1022E		0x0110
+#define PCI_DEVICE_ID_P1022		0x0111
+#define PCI_DEVICE_ID_P1013E		0x0118
+#define PCI_DEVICE_ID_P1013		0x0119
+#define PCI_DEVICE_ID_P4080E		0x0400
+#define PCI_DEVICE_ID_P4080		0x0401
+#define PCI_DEVICE_ID_P4040E		0x0408
+#define PCI_DEVICE_ID_P4040		0x0409
 #define PCI_DEVICE_ID_MPC8641		0x7010
 #define PCI_DEVICE_ID_MPC8641D		0x7011
 #define PCI_DEVICE_ID_MPC8610		0x7018
@@ -2303,6 +2322,7 @@
 #define PCI_VENDOR_ID_JMICRON		0x197B
 #define PCI_DEVICE_ID_JMICRON_JMB360	0x2360
 #define PCI_DEVICE_ID_JMICRON_JMB361	0x2361
+#define PCI_DEVICE_ID_JMICRON_JMB362	0x2362
 #define PCI_DEVICE_ID_JMICRON_JMB363	0x2363
 #define PCI_DEVICE_ID_JMICRON_JMB365	0x2365
 #define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
@@ -2398,6 +2418,9 @@
 #define PCI_DEVICE_ID_INTEL_82840_HB	0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
 #define PCI_DEVICE_ID_INTEL_IOAT	0x1a38
+#define PCI_DEVICE_ID_INTEL_CPT_SMBUS	0x1c22
+#define PCI_DEVICE_ID_INTEL_CPT_LPC1	0x1c42
+#define PCI_DEVICE_ID_INTEL_CPT_LPC2	0x1c43
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
--- linux-ec2-2.6.32.orig/include/linux/cpumask.h
+++ linux-ec2-2.6.32/include/linux/cpumask.h
@@ -84,6 +84,7 @@
 #define num_online_cpus()	cpumask_weight(cpu_online_mask)
 #define num_possible_cpus()	cpumask_weight(cpu_possible_mask)
 #define num_present_cpus()	cpumask_weight(cpu_present_mask)
+#define num_active_cpus()	cpumask_weight(cpu_active_mask)
 #define cpu_online(cpu)		cpumask_test_cpu((cpu), cpu_online_mask)
 #define cpu_possible(cpu)	cpumask_test_cpu((cpu), cpu_possible_mask)
 #define cpu_present(cpu)	cpumask_test_cpu((cpu), cpu_present_mask)
@@ -92,6 +93,7 @@
 #define num_online_cpus()	1
 #define num_possible_cpus()	1
 #define num_present_cpus()	1
+#define num_active_cpus()	1
 #define cpu_online(cpu)		((cpu) == 0)
 #define cpu_possible(cpu)	((cpu) == 0)
 #define cpu_present(cpu)	((cpu) == 0)
--- linux-ec2-2.6.32.orig/include/linux/syscalls.h
+++ linux-ec2-2.6.32/include/linux/syscalls.h
@@ -153,7 +153,8 @@
 #define __SC_STR_TDECL6(t, a, ...)	#t, __SC_STR_TDECL5(__VA_ARGS__)
 
 #define SYSCALL_TRACE_ENTER_EVENT(sname)				\
-	static struct ftrace_event_call event_enter_##sname;		\
+	static struct ftrace_event_call					\
+	__attribute__((__aligned__(4))) event_enter_##sname;		\
 	struct trace_event enter_syscall_print_##sname = {		\
 		.trace                  = print_syscall_enter,		\
 	};								\
@@ -189,7 +190,8 @@
 	}
 
 #define SYSCALL_TRACE_EXIT_EVENT(sname)					\
-	static struct ftrace_event_call event_exit_##sname;		\
+	static struct ftrace_event_call					\
+	__attribute__((__aligned__(4))) event_exit_##sname;		\
 	struct trace_event exit_syscall_print_##sname = {		\
 		.trace                  = print_syscall_exit,		\
 	};								\
@@ -879,4 +881,8 @@
 asmlinkage long sys_perf_event_open(
 		struct perf_event_attr __user *attr_uptr,
 		pid_t pid, int cpu, int group_fd, unsigned long flags);
+
+asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff);
 #endif
--- linux-ec2-2.6.32.orig/include/linux/binfmts.h
+++ linux-ec2-2.6.32/include/linux/binfmts.h
@@ -29,6 +29,7 @@
 	char buf[BINPRM_BUF_SIZE];
 #ifdef CONFIG_MMU
 	struct vm_area_struct *vma;
+	unsigned long vma_pages;
 #else
 # define MAX_ARG_PAGES	32
 	struct page *page[MAX_ARG_PAGES];
@@ -59,6 +60,10 @@
 	unsigned long loader, exec;
 };
 
+extern void acct_arg_size(struct linux_binprm *bprm, unsigned long pages);
+extern struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
+					int write);
+
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
 #define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
 
@@ -101,6 +106,7 @@
 extern int __must_check remove_arg_zero(struct linux_binprm *);
 extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
 extern int flush_old_exec(struct linux_binprm * bprm);
+extern void setup_new_exec(struct linux_binprm * bprm);
 
 extern int suid_dumpable;
 #define SUID_DUMP_DISABLE	0	/* No setuid dumping */
--- linux-ec2-2.6.32.orig/include/linux/security.h
+++ linux-ec2-2.6.32/include/linux/security.h
@@ -76,7 +76,7 @@
 extern int cap_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
-extern int cap_syslog(int type);
+extern int cap_syslog(int type, bool from_file);
 extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
 
 struct msghdr;
@@ -95,8 +95,13 @@
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+#ifdef CONFIG_MMU
 extern unsigned long mmap_min_addr;
 extern unsigned long dac_mmap_min_addr;
+#else
+#define dac_mmap_min_addr	0UL
+#endif
+
 /*
  * Values used in the task_security_ops calls
  */
@@ -121,6 +126,7 @@
 #define LSM_UNSAFE_PTRACE	2
 #define LSM_UNSAFE_PTRACE_CAP	4
 
+#ifdef CONFIG_MMU
 /*
  * If a hint addr is less than mmap_min_addr change hint to be as
  * low as possible but still greater than mmap_min_addr
@@ -135,6 +141,7 @@
 }
 extern int mmap_min_addr_handler(struct ctl_table *table, int write,
 				 void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
 
 #ifdef CONFIG_SECURITY
 
@@ -447,6 +454,22 @@
  *	@new_dir contains the path structure for parent of the new link.
  *	@new_dentry contains the dentry structure of the new link.
  *	Return 0 if permission is granted.
+ * @path_chmod:
+ *	Check for permission to change DAC's permission of a file or directory.
+ *	@dentry contains the dentry structure.
+ *	@mnt contains the vfsmnt structure.
+ *	@mode contains DAC's mode.
+ *	Return 0 if permission is granted.
+ * @path_chown:
+ *	Check for permission to change owner/group of a file or directory.
+ *	@path contains the path structure.
+ *	@uid contains new owner's ID.
+ *	@gid contains new group's ID.
+ *	Return 0 if permission is granted.
+ * @path_chroot:
+ *	Check for permission to change root directory.
+ *	@path contains the path structure.
+ *	Return 0 if permission is granted.
  * @inode_readlink:
  *	Check the permission to read the symbolic link.
  *	@dentry contains the dentry structure for the file link.
@@ -1324,6 +1347,7 @@
  *	logging to the console.
  *	See the syslog(2) manual page for an explanation of the @type values.
  *	@type contains the type of action.
+ *	@from_file indicates the context of action (if it came from /proc).
  *	Return 0 if permission is granted.
  * @settime:
  *	Check permission to change the system time.
@@ -1438,7 +1462,7 @@
 	int (*sysctl) (struct ctl_table *table, int op);
 	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
 	int (*quota_on) (struct dentry *dentry);
-	int (*syslog) (int type);
+	int (*syslog) (int type, bool from_file);
 	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 
@@ -1488,6 +1512,10 @@
 			  struct dentry *new_dentry);
 	int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
 			    struct path *new_dir, struct dentry *new_dentry);
+	int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt,
+			   mode_t mode);
+	int (*path_chown) (struct path *path, uid_t uid, gid_t gid);
+	int (*path_chroot) (struct path *path);
 #endif
 
 	int (*inode_alloc_security) (struct inode *inode);
@@ -1733,7 +1761,7 @@
 int security_sysctl(struct ctl_table *table, int op);
 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
 int security_quota_on(struct dentry *dentry);
-int security_syslog(int type);
+int security_syslog(int type, bool from_file);
 int security_settime(struct timespec *ts, struct timezone *tz);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
@@ -1979,9 +2007,9 @@
 	return 0;
 }
 
-static inline int security_syslog(int type)
+static inline int security_syslog(int type, bool from_file)
 {
-	return cap_syslog(type);
+	return cap_syslog(type, from_file);
 }
 
 static inline int security_settime(struct timespec *ts, struct timezone *tz)
@@ -2952,6 +2980,10 @@
 		       struct dentry *new_dentry);
 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
 			 struct path *new_dir, struct dentry *new_dentry);
+int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+			mode_t mode);
+int security_path_chown(struct path *path, uid_t uid, gid_t gid);
+int security_path_chroot(struct path *path);
 #else	/* CONFIG_SECURITY_PATH */
 static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
@@ -3001,6 +3033,23 @@
 {
 	return 0;
 }
+
+static inline int security_path_chmod(struct dentry *dentry,
+				      struct vfsmount *mnt,
+				      mode_t mode)
+{
+	return 0;
+}
+
+static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+	return 0;
+}
+
+static inline int security_path_chroot(struct path *path)
+{
+	return 0;
+}
 #endif	/* CONFIG_SECURITY_PATH */
 
 #ifdef CONFIG_KEYS
--- linux-ec2-2.6.32.orig/include/linux/pci.h
+++ linux-ec2-2.6.32/include/linux/pci.h
@@ -289,7 +289,7 @@
 	int rom_attr_enabled;		/* has display of the rom attribute been enabled? */
 	struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
 	struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
-#ifdef CONFIG_PCI_MSI
+#if defined(CONFIG_PCI_MSI) && !defined(CONFIG_XEN)
 	struct list_head msi_list;
 #endif
 	struct pci_vpd *vpd;
@@ -564,6 +564,9 @@
 				resource_size_t);
 void pcibios_update_irq(struct pci_dev *, int irq);
 
+/* Weak but can be overriden by arch */
+void pci_fixup_cardbus(struct pci_bus *);
+
 /* Generic PCI functions used internally */
 
 extern struct pci_bus *pci_find_bus(int domain, int busnr);
@@ -721,6 +724,9 @@
 void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+#ifdef CONFIG_XEN
+void pci_restore_bars(struct pci_dev *);
+#endif
 
 /* ROM control related routines */
 int pci_enable_rom(struct pci_dev *pdev);
@@ -877,6 +883,11 @@
 {
 	return 0;
 }
+
+#ifdef CONFIG_XEN
+#define register_msi_get_owner(func) 0
+#define unregister_msi_get_owner(func) 0
+#endif
 #else
 extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
 extern void pci_msi_shutdown(struct pci_dev *dev);
@@ -889,6 +900,10 @@
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 extern void pci_restore_msi_state(struct pci_dev *dev);
 extern int pci_msi_enabled(void);
+#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
 
 #ifndef CONFIG_PCIEASPM
@@ -942,6 +957,11 @@
 }
 #endif /* CONFIG_PCI_DOMAINS */
 
+/* some architectures require additional setup to direct VGA traffic */
+typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
+		      unsigned int command_bits, bool change_bridge);
+extern void pci_register_set_vga_state(arch_set_vga_state_t func);
+
 #else /* CONFIG_PCI is not enabled */
 
 /*
@@ -1290,5 +1310,11 @@
 extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
 #endif
 
+#ifdef CONFIG_PCI_GUESTDEV
+int pci_is_guestdev(struct pci_dev *dev);
+#else
+#define pci_is_guestdev(dev)	0
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
--- linux-ec2-2.6.32.orig/include/linux/page-flags.h
+++ linux-ec2-2.6.32/include/linux/page-flags.h
@@ -108,6 +108,11 @@
 #ifdef CONFIG_MEMORY_FAILURE
 	PG_hwpoison,		/* hardware poisoned page. Don't touch */
 #endif
+#ifdef CONFIG_XEN
+	PG_foreign,		/* Page is owned by foreign allocator. */
+	/* PG_netback,		   Page is owned by netback */
+	PG_blkback,		/* Page is owned by blkback */
+#endif
 	__NR_PAGEFLAGS,
 
 	/* Filesystems */
@@ -120,8 +125,15 @@
 	PG_fscache = PG_private_2,	/* page backed by cache */
 
 	/* XEN */
+#if defined(CONFIG_XEN)
+	PG_pinned = PG_locked,	/* Cannot alias with PG_owner_priv_1 since
+				 * bad_page() checks should include this bit.
+				 * Should not use PG_arch_1 as that may have
+				 * a different purpose elsewhere. */
+#elif defined(CONFIG_PARAVIRT_XEN)
 	PG_pinned = PG_owner_priv_1,
 	PG_savepinned = PG_dirty,
+#endif
 
 	/* SLOB */
 	PG_slob_free = PG_private,
@@ -207,8 +219,12 @@
 	TESTCLEARFLAG(Active, active)
 __PAGEFLAG(Slab, slab)
 PAGEFLAG(Checked, checked)		/* Used by some filesystems */
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
 PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned)	/* Xen */
+#endif
+#ifdef CONFIG_PARAVIRT_XEN
 PAGEFLAG(SavePinned, savepinned);			/* Xen */
+#endif
 PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
 PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
 
@@ -329,6 +345,28 @@
 
 CLEARPAGEFLAG(Uptodate, uptodate)
 
+#ifdef CONFIG_XEN
+TESTPAGEFLAG(Foreign, foreign)
+static inline void SetPageForeign(struct page *page,
+				  void (*dtor)(struct page *, unsigned int))
+{
+	BUG_ON(!dtor);
+	set_bit(PG_foreign, &page->flags);
+	page->index = (long)dtor;
+}
+static inline void ClearPageForeign(struct page *page)
+{
+	clear_bit(PG_foreign, &page->flags);
+	page->index = 0;
+}
+static inline void PageForeignDestructor(struct page *page, unsigned int order)
+{
+	((void (*)(struct page *, unsigned int))page->index)(page, order);
+}
+/*PAGEFLAG(Netback, netback)*/
+PAGEFLAG(Blkback, blkback)
+#endif
+
 extern void cancel_dirty_page(struct page *page, unsigned int account_size);
 
 int test_clear_page_writeback(struct page *page);
@@ -399,6 +437,12 @@
 #define __PG_MLOCKED		0
 #endif
 
+#ifndef CONFIG_XEN
+# define __PG_XEN		0
+#else
+# define __PG_XEN		(1 << PG_foreign)
+#endif
+
 /*
  * Flags checked when a page is freed.  Pages being freed should not have
  * these flags set.  It they are, there is a problem.
@@ -408,7 +452,7 @@
 	 1 << PG_private | 1 << PG_private_2 | \
 	 1 << PG_buddy	 | 1 << PG_writeback | 1 << PG_reserved | \
 	 1 << PG_slab	 | 1 << PG_swapcache | 1 << PG_active | \
-	 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON)
+	 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | __PG_XEN)
 
 /*
  * Flags checked when a page is prepped for return by the page allocator.
--- linux-ec2-2.6.32.orig/include/linux/klist.h
+++ linux-ec2-2.6.32/include/linux/klist.h
@@ -22,7 +22,7 @@
 	struct list_head	k_list;
 	void			(*get)(struct klist_node *);
 	void			(*put)(struct klist_node *);
-} __attribute__ ((aligned (4)));
+} __attribute__ ((aligned (sizeof(void *))));
 
 #define KLIST_INIT(_name, _get, _put)					\
 	{ .k_lock	= __SPIN_LOCK_UNLOCKED(_name.k_lock),		\
--- linux-ec2-2.6.32.orig/include/linux/swap.h
+++ linux-ec2-2.6.32/include/linux/swap.h
@@ -177,8 +177,60 @@
 	unsigned int max;
 	unsigned int inuse_pages;
 	unsigned int old_block_size;
+#ifdef CONFIG_PRESWAP
+	unsigned long *preswap_map;
+	unsigned int preswap_pages;
+#endif
+	void (*notify_swap_entry_free_fn) (unsigned long);
 };
 
+#ifdef CONFIG_PRESWAP
+
+#include <linux/sysctl.h>
+extern int preswap_sysctl_handler(struct ctl_table *, int, void __user *,
+				   size_t *, loff_t *);
+extern const unsigned long preswap_zero, preswap_infinity;
+
+extern void preswap_shrink(unsigned long);
+extern int preswap_test(struct swap_info_struct *, unsigned long);
+extern void preswap_init(unsigned);
+extern int preswap_put(struct page *);
+extern int preswap_get(struct page *);
+extern void preswap_flush(unsigned, unsigned long);
+extern void preswap_flush_area(unsigned);
+#else
+static inline void preswap_shrink(unsigned long target_pages)
+{
+}
+
+static inline int preswap_test(struct swap_info_struct *sis, unsigned long offset)
+{
+	return 0;
+}
+
+static inline void preswap_init(unsigned type)
+{
+}
+
+static inline int preswap_put(struct page *page)
+{
+	return 0;
+}
+
+static inline int preswap_get(struct page *get)
+{
+	return 0;
+}
+
+static inline void preswap_flush(unsigned type, unsigned long offset)
+{
+}
+
+static inline void preswap_flush_area(unsigned type)
+{
+}
+#endif /* CONFIG_PRESWAP */
+
 struct swap_list_t {
 	int head;	/* head of priority-ordered swapfile list */
 	int next;	/* swapfile to be used next */
@@ -218,21 +270,11 @@
 	__lru_cache_add(page, LRU_INACTIVE_ANON);
 }
 
-static inline void lru_cache_add_active_anon(struct page *page)
-{
-	__lru_cache_add(page, LRU_ACTIVE_ANON);
-}
-
 static inline void lru_cache_add_file(struct page *page)
 {
 	__lru_cache_add(page, LRU_INACTIVE_FILE);
 }
 
-static inline void lru_cache_add_active_file(struct page *page)
-{
-	__lru_cache_add(page, LRU_ACTIVE_FILE);
-}
-
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 					gfp_t gfp_mask, nodemask_t *mask);
@@ -323,6 +365,7 @@
 extern int reuse_swap_page(struct page *);
 extern int try_to_free_swap(struct page *);
 struct backing_dev_info;
+extern void set_notify_swap_entry_free(unsigned, void (*) (unsigned long));
 
 /* linux/mm/thrash.c */
 extern struct mm_struct *swap_token_mm;
--- linux-ec2-2.6.32.orig/include/linux/vmalloc.h
+++ linux-ec2-2.6.32/include/linux/vmalloc.h
@@ -115,9 +115,11 @@
 extern struct vm_struct *vmlist;
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 
+#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
 struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
 				     const size_t *sizes, int nr_vms,
 				     size_t align, gfp_t gfp_mask);
+#endif
 
 void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
 
--- linux-ec2-2.6.32.orig/include/linux/tty.h
+++ linux-ec2-2.6.32/include/linux/tty.h
@@ -68,6 +68,17 @@
 	unsigned long data[0];
 };
 
+/*
+ * We default to dicing tty buffer allocations to this many characters
+ * in order to avoid multiple page allocations. We know the size of
+ * tty_buffer itself but it must also be taken into account that the
+ * the buffer is 256 byte aligned. See tty_buffer_find for the allocation
+ * logic this must match
+ */
+
+#define TTY_BUFFER_PAGE	(((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
+
+
 struct tty_bufhead {
 	struct delayed_work work;
 	spinlock_t lock;
--- linux-ec2-2.6.32.orig/include/linux/interrupt.h
+++ linux-ec2-2.6.32/include/linux/interrupt.h
@@ -52,16 +52,21 @@
  * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
  *                Used by threaded interrupts which need to keep the
  *                irq line disabled until the threaded handler has been run.
+ * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
+ *
  */
 #define IRQF_DISABLED		0x00000020
 #define IRQF_SAMPLE_RANDOM	0x00000040
 #define IRQF_SHARED		0x00000080
 #define IRQF_PROBE_SHARED	0x00000100
-#define IRQF_TIMER		0x00000200
+#define __IRQF_TIMER		0x00000200
 #define IRQF_PERCPU		0x00000400
 #define IRQF_NOBALANCING	0x00000800
 #define IRQF_IRQPOLL		0x00001000
 #define IRQF_ONESHOT		0x00002000
+#define IRQF_NO_SUSPEND		0x00004000
+
+#define IRQF_TIMER		(__IRQF_TIMER | IRQF_NO_SUSPEND)
 
 /*
  * Bits used by threaded handlers:
@@ -317,6 +322,12 @@
 }
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
+#ifdef CONFIG_HAVE_IRQ_IGNORE_UNHANDLED
+int irq_ignore_unhandled(unsigned int irq);
+#else
+#define irq_ignore_unhandled(irq) 0
+#endif
+
 #ifndef __ARCH_SET_SOFTIRQ_PENDING
 #define set_softirq_pending(x) (local_softirq_pending() = (x))
 #define or_softirq_pending(x)  (local_softirq_pending() |= (x))
--- linux-ec2-2.6.32.orig/include/linux/blkdev.h
+++ linux-ec2-2.6.32/include/linux/blkdev.h
@@ -318,7 +318,7 @@
 	unsigned short		max_phys_segments;
 
 	unsigned char		misaligned;
-	unsigned char		no_cluster;
+	unsigned char		cluster;
 };
 
 struct request_queue
@@ -440,7 +440,6 @@
 #endif
 };
 
-#define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED	2	/* queue is stopped */
 #define	QUEUE_FLAG_SYNCFULL	3	/* read queue has been filled */
@@ -461,7 +460,6 @@
 #define QUEUE_FLAG_DISCARD     17	/* supports DISCARD */
 
 #define QUEUE_FLAG_DEFAULT	((1 << QUEUE_FLAG_IO_STAT) |		\
-				 (1 << QUEUE_FLAG_CLUSTER) |		\
 				 (1 << QUEUE_FLAG_STACKABLE)	|	\
 				 (1 << QUEUE_FLAG_SAME_COMP))
 
@@ -627,6 +625,11 @@
 
 #define rq_data_dir(rq)		((rq)->cmd_flags & 1)
 
+static inline unsigned int blk_queue_cluster(struct request_queue *q)
+{
+	return q->limits.cluster;
+}
+
 /*
  * We regard a request as sync, if either a read or a sync write
  */
@@ -932,7 +935,7 @@
 extern void blk_queue_max_discard_sectors(struct request_queue *q,
 		unsigned int max_discard_sectors);
 extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
-extern void blk_queue_physical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
 				       unsigned int alignment);
 extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
@@ -942,6 +945,8 @@
 extern void blk_set_default_limits(struct queue_limits *lim);
 extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 			    sector_t offset);
+extern int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
+			    sector_t offset);
 extern void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
 			      sector_t offset);
 extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
@@ -1081,7 +1086,7 @@
 	return q->limits.physical_block_size;
 }
 
-static inline int bdev_physical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_physical_block_size(struct block_device *bdev)
 {
 	return queue_physical_block_size(bdev_get_queue(bdev));
 }
@@ -1114,11 +1119,18 @@
 	return q->limits.alignment_offset;
 }
 
+static inline int queue_limit_alignment_offset(struct queue_limits *lim, sector_t offset)
+{
+	unsigned int granularity = max(lim->physical_block_size, lim->io_min);
+
+	offset &= granularity - 1;
+	return (granularity + lim->alignment_offset - offset) & (granularity - 1);
+}
+
 static inline int queue_sector_alignment_offset(struct request_queue *q,
 						sector_t sector)
 {
-	return ((sector << 9) - q->limits.alignment_offset)
-		& (q->limits.io_min - 1);
+	return queue_limit_alignment_offset(&q->limits, sector << 9);
 }
 
 static inline int bdev_alignment_offset(struct block_device *bdev)
--- linux-ec2-2.6.32.orig/include/linux/firmware.h
+++ linux-ec2-2.6.32/include/linux/firmware.h
@@ -11,6 +11,7 @@
 struct firmware {
 	size_t size;
 	const u8 *data;
+	struct page **pages;
 };
 
 struct device;
--- linux-ec2-2.6.32.orig/include/linux/clocksource.h
+++ linux-ec2-2.6.32/include/linux/clocksource.h
@@ -151,6 +151,7 @@
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
+ * @max_idle_ns:	max idle time permitted by the clocksource (nsecs)
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @resume:		resume function for the clocksource, if necessary
@@ -168,6 +169,7 @@
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
+	u64 max_idle_ns;
 	unsigned long flags;
 	cycle_t (*vread)(void);
 	void (*resume)(void);
@@ -280,10 +282,12 @@
 extern void clocksource_mark_unstable(struct clocksource *cs);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
-extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
+extern void
+update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult);
 extern void update_vsyscall_tz(void);
 #else
-static inline void update_vsyscall(struct timespec *ts, struct clocksource *c)
+static inline void
+update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult)
 {
 }
 
--- linux-ec2-2.6.32.orig/include/linux/sched.h
+++ linux-ec2-2.6.32/include/linux/sched.h
@@ -145,7 +145,6 @@
 
 
 extern void calc_global_load(void);
-extern u64 cpu_nr_migrations(int cpu);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
@@ -379,6 +378,9 @@
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
 		       unsigned long, unsigned long);
 extern unsigned long
+arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long,
+		       unsigned long, unsigned long);
+extern unsigned long
 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
 			  unsigned long len, unsigned long pgoff,
 			  unsigned long flags);
@@ -628,6 +630,9 @@
 	cputime_t utime, stime, cutime, cstime;
 	cputime_t gtime;
 	cputime_t cgtime;
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+	cputime_t prev_utime, prev_stime;
+#endif
 	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
 	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
 	unsigned long inblock, oublock, cinblock, coublock;
@@ -726,14 +731,6 @@
 	uid_t uid;
 	struct user_namespace *user_ns;
 
-#ifdef CONFIG_USER_SCHED
-	struct task_group *tg;
-#ifdef CONFIG_SYSFS
-	struct kobject kobj;
-	struct delayed_work work;
-#endif
-#endif
-
 #ifdef CONFIG_PERF_EVENTS
 	atomic_long_t locked_vm;
 #endif
@@ -864,7 +861,10 @@
 	if (sched_smt_power_savings)
 		return SD_POWERSAVINGS_BALANCE;
 
-	return SD_PREFER_SIBLING;
+	if (!sched_mc_power_savings)
+		return SD_PREFER_SIBLING;
+
+	return 0;
 }
 
 static inline int sd_balance_for_package_power(void)
@@ -897,6 +897,7 @@
 	 * single CPU.
 	 */
 	unsigned int cpu_power;
+	unsigned int group_weight;
 
 	/*
 	 * The CPUs this group covers.
@@ -995,6 +996,7 @@
 	char *name;
 #endif
 
+	unsigned int span_weight;
 	/*
 	 * Span of all CPUs in this domain.
 	 *
@@ -1066,7 +1068,8 @@
 struct sched_class {
 	const struct sched_class *next;
 
-	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup);
+	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup,
+			      bool head);
 	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep);
 	void (*yield_task) (struct rq *rq);
 
@@ -1076,7 +1079,8 @@
 	void (*put_prev_task) (struct rq *rq, struct task_struct *p);
 
 #ifdef CONFIG_SMP
-	int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
+	int  (*select_task_rq)(struct rq *rq, struct task_struct *p,
+			       int sd_flag, int flags);
 
 	unsigned long (*load_balance) (struct rq *this_rq, int this_cpu,
 			struct rq *busiest, unsigned long max_load_move,
@@ -1088,7 +1092,8 @@
 			      enum cpu_idle_type idle);
 	void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
 	void (*post_schedule) (struct rq *this_rq);
-	void (*task_wake_up) (struct rq *this_rq, struct task_struct *task);
+	void (*task_waking) (struct rq *this_rq, struct task_struct *task);
+	void (*task_woken) (struct rq *this_rq, struct task_struct *task);
 
 	void (*set_cpus_allowed)(struct task_struct *p,
 				 const struct cpumask *newmask);
@@ -1099,7 +1104,7 @@
 
 	void (*set_curr_task) (struct rq *rq);
 	void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
-	void (*task_new) (struct rq *rq, struct task_struct *p);
+	void (*task_fork) (struct task_struct *p);
 
 	void (*switched_from) (struct rq *this_rq, struct task_struct *task,
 			       int running);
@@ -1108,10 +1113,11 @@
 	void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
 			     int oldprio, int running);
 
-	unsigned int (*get_rr_interval) (struct task_struct *task);
+	unsigned int (*get_rr_interval) (struct rq *rq,
+					 struct task_struct *task);
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-	void (*moved_group) (struct task_struct *p);
+	void (*task_move_group) (struct task_struct *p, int on_rq);
 #endif
 };
 
@@ -1172,7 +1178,6 @@
 	u64			nr_failed_migrations_running;
 	u64			nr_failed_migrations_hot;
 	u64			nr_forced_migrations;
-	u64			nr_forced2_migrations;
 
 	u64			nr_wakeups;
 	u64			nr_wakeups_sync;
@@ -1354,7 +1359,7 @@
 	char comm[TASK_COMM_LEN]; /* executable name excluding path
 				     - access with [gs]et_task_comm (which lock
 				       it with task_lock())
-				     - initialized normally by flush_old_exec */
+				     - initialized normally by setup_new_exec */
 /* file system info */
 	int link_count, total_link_count;
 #ifdef CONFIG_SYSVIPC
@@ -1538,7 +1543,6 @@
 	/* bitmask of trace recursion */
 	unsigned long trace_recursion;
 #endif /* CONFIG_TRACING */
-	unsigned long stack_start;
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -1723,12 +1727,12 @@
 extern cputime_t task_utime(struct task_struct *p);
 extern cputime_t task_stime(struct task_struct *p);
 extern cputime_t task_gtime(struct task_struct *p);
+extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st);
 
 /*
  * Per process flags
  */
-#define PF_ALIGNWARN	0x00000001	/* Print alignment warning msgs */
-					/* Not implemented yet, only for 486*/
+#define PF_KSOFTIRQD	0x00000001	/* I am ksoftirqd */
 #define PF_STARTING	0x00000002	/* being created */
 #define PF_EXITING	0x00000004	/* getting shut down */
 #define PF_EXITPIDONE	0x00000008	/* pi exit done on shut down */
@@ -1865,6 +1869,19 @@
  */
 extern unsigned long long cpu_clock(int cpu);
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+/*
+ * An i/f to runtime opt-in for irq time accounting based off of sched_clock.
+ * The reason for this explicit opt-in is not to have perf penalty with
+ * slow sched_clocks.
+ */
+extern void enable_sched_clock_irqtime(void);
+extern void disable_sched_clock_irqtime(void);
+#else
+static inline void enable_sched_clock_irqtime(void) {}
+static inline void disable_sched_clock_irqtime(void) {}
+#endif
+
 extern unsigned long long
 task_sched_runtime(struct task_struct *task);
 extern unsigned long long thread_group_sched_runtime(struct task_struct *task);
@@ -1880,6 +1897,7 @@
 extern void sched_clock_idle_wakeup_event(u64 delta_ns);
 
 #ifdef CONFIG_HOTPLUG_CPU
+extern void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p);
 extern void idle_task_exit(void);
 #else
 static inline void idle_task_exit(void) {}
@@ -2086,11 +2104,18 @@
 	return info <= SEND_SIG_FORCED;
 }
 
-/* True if we are on the alternate signal stack.  */
-
+/*
+ * True if we are on the alternate signal stack.
+ */
 static inline int on_sig_stack(unsigned long sp)
 {
-	return (sp - current->sas_ss_sp < current->sas_ss_size);
+#ifdef CONFIG_STACK_GROWSUP
+	return sp >= current->sas_ss_sp &&
+		sp - current->sas_ss_sp < current->sas_ss_size;
+#else
+	return sp > current->sas_ss_sp &&
+		sp - current->sas_ss_sp <= current->sas_ss_size;
+#endif
 }
 
 static inline int sas_ss_flags(unsigned long sp)
@@ -2392,9 +2417,9 @@
 
 extern int __cond_resched_softirq(void);
 
-#define cond_resched_softirq() ({				\
-	__might_sleep(__FILE__, __LINE__, SOFTIRQ_OFFSET);	\
-	__cond_resched_softirq();				\
+#define cond_resched_softirq() ({					\
+	__might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET);	\
+	__cond_resched_softirq();					\
 })
 
 /*
@@ -2483,13 +2508,9 @@
 
 extern void normalize_rt_tasks(void);
 
-#ifdef CONFIG_GROUP_SCHED
+#ifdef CONFIG_CGROUP_SCHED
 
 extern struct task_group init_task_group;
-#ifdef CONFIG_USER_SCHED
-extern struct task_group root_task_group;
-extern void set_tg_uid(struct user_struct *user);
-#endif
 
 extern struct task_group *sched_create_group(struct task_group *parent);
 extern void sched_destroy_group(struct task_group *tg);
@@ -2576,6 +2597,28 @@
 
 #define TASK_STATE_TO_CHAR_STR "RSDTtZX"
 
+static inline unsigned long task_rlimit(const struct task_struct *tsk,
+		unsigned int limit)
+{
+	return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_cur);
+}
+
+static inline unsigned long task_rlimit_max(const struct task_struct *tsk,
+		unsigned int limit)
+{
+	return ACCESS_ONCE(tsk->signal->rlim[limit].rlim_max);
+}
+
+static inline unsigned long rlimit(unsigned int limit)
+{
+	return task_rlimit(current, limit);
+}
+
+static inline unsigned long rlimit_max(unsigned int limit)
+{
+	return task_rlimit_max(current, limit);
+}
+
 #endif /* __KERNEL__ */
 
 #endif
--- linux-ec2-2.6.32.orig/include/linux/tty_driver.h
+++ linux-ec2-2.6.32/include/linux/tty_driver.h
@@ -224,6 +224,12 @@
  *	unless the tty also has a valid tty->termiox pointer.
  *
  *	Optional: Called under the termios lock
+ *
+ * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
+ *
+ *	Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
+ *	structure to complete. This method is optional and will only be called
+ *	if provided (otherwise EINVAL will be returned).
  */
 
 #include <linux/fs.h>
@@ -232,6 +238,7 @@
 
 struct tty_struct;
 struct tty_driver;
+struct serial_icounter_struct;
 
 struct tty_operations {
 	struct tty_struct * (*lookup)(struct tty_driver *driver,
@@ -268,6 +275,8 @@
 			unsigned int set, unsigned int clear);
 	int (*resize)(struct tty_struct *tty, struct winsize *ws);
 	int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
+	int (*get_icount)(struct tty_struct *tty,
+				struct serial_icounter_struct *icount);
 #ifdef CONFIG_CONSOLE_POLL
 	int (*poll_init)(struct tty_driver *driver, int line, char *options);
 	int (*poll_get_char)(struct tty_driver *driver, int line);
--- linux-ec2-2.6.32.orig/include/linux/enclosure.h
+++ linux-ec2-2.6.32/include/linux/enclosure.h
@@ -42,6 +42,8 @@
 	ENCLOSURE_STATUS_NOT_INSTALLED,
 	ENCLOSURE_STATUS_UNKNOWN,
 	ENCLOSURE_STATUS_UNAVAILABLE,
+	/* last element for counting purposes */
+	ENCLOSURE_STATUS_MAX
 };
 
 /* SFF-8485 activity light settings */
--- linux-ec2-2.6.32.orig/include/linux/writeback.h
+++ linux-ec2-2.6.32/include/linux/writeback.h
@@ -27,13 +27,12 @@
  * in a manner such that unspecified fields are set to zero.
  */
 struct writeback_control {
-	struct backing_dev_info *bdi;	/* If !NULL, only write back this
-					   queue */
-	struct super_block *sb;		/* if !NULL, only write inodes from
-					   this super_block */
 	enum writeback_sync_modes sync_mode;
 	unsigned long *older_than_this;	/* If !NULL, only write back inodes
 					   older than this */
+	unsigned long wb_start;         /* Time writeback_inodes_wb was
+					   called. This is needed to avoid
+					   extra jobs and livelock */
 	long nr_to_write;		/* Write this many pages, and decrement
 					   this for each page written */
 	long pages_skipped;		/* Pages which were not written */
@@ -69,8 +68,10 @@
 struct bdi_writeback;
 int inode_wait(void *);
 void writeback_inodes_sb(struct super_block *);
+int writeback_inodes_sb_if_idle(struct super_block *);
 void sync_inodes_sb(struct super_block *);
-void writeback_inodes_wbc(struct writeback_control *wbc);
+void writeback_inodes_wb(struct bdi_writeback *wb,
+		struct writeback_control *wbc);
 long wb_do_writeback(struct bdi_writeback *wb, int force_wait);
 void wakeup_flusher_threads(long nr_pages);
 
--- linux-ec2-2.6.32.orig/include/linux/syslog.h
+++ linux-ec2-2.6.32/include/linux/syslog.h
@@ -0,0 +1,29 @@
+/*  Syslog internals
+ *
+ *  Copyright 2010 Canonical, Ltd.
+ *  Author: Kees Cook <kees.cook@canonical.com>
+ *
+ *  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, 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; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_SYSLOG_H
+#define _LINUX_SYSLOG_H
+
+#define SYSLOG_FROM_CALL 0
+#define SYSLOG_FROM_FILE 1
+
+int do_syslog(int type, char __user *buf, int count, bool from_file);
+
+#endif /* _LINUX_SYSLOG_H */
--- linux-ec2-2.6.32.orig/include/linux/usb_usual.h
+++ linux-ec2-2.6.32/include/linux/usb_usual.h
@@ -56,7 +56,9 @@
 	US_FLAG(SANE_SENSE,     0x00008000)			\
 		/* Sane Sense (> 18 bytes) */			\
 	US_FLAG(CAPACITY_OK,	0x00010000)			\
-		/* READ CAPACITY response is correct */
+		/* READ CAPACITY response is correct */		\
+	US_FLAG(BAD_SENSE,	0x00020000)			\
+		/* Bad Sense (never more than 18 bytes) */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
--- linux-ec2-2.6.32.orig/include/linux/ieee80211.h
+++ linux-ec2-2.6.32/include/linux/ieee80211.h
@@ -872,7 +872,7 @@
 /* block-ack parameters */
 #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
 #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
-#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
+#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0
 #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
 #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
 
@@ -1098,6 +1098,8 @@
 	WLAN_CATEGORY_SA_QUERY = 8,
 	WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9,
 	WLAN_CATEGORY_WMM = 17,
+	WLAN_CATEGORY_MESH_PLINK = 30,		/* Pending ANA approval */
+	WLAN_CATEGORY_MESH_PATH_SEL = 32,	/* Pending ANA approval */
 	WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
 	WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
 };
--- linux-ec2-2.6.32.orig/include/linux/skbuff.h
+++ linux-ec2-2.6.32/include/linux/skbuff.h
@@ -278,6 +278,8 @@
  *	@local_df: allow local fragmentation
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
+ *	@proto_data_valid: Protocol data validated since arriving at localhost
+ *	@proto_csum_blank: Protocol csum must be added before leaving localhost
  *	@pkt_type: Packet class
  *	@fclone: skbuff clone status
  *	@ip_summed: Driver fed us an IP checksum
@@ -379,9 +381,13 @@
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
 	__u8			ndisc_nodetype:2;
 #endif
+#ifdef CONFIG_XEN
+	__u8			proto_data_valid:1,
+				proto_csum_blank:1;
+#endif
 	kmemcheck_bitfield_end(flags2);
 
-	/* 0/14 bit hole */
+	/* 0/12/14 bit hole */
 
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
@@ -2085,5 +2091,12 @@
 }
 
 bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
+
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+int skb_checksum_setup(struct sk_buff *skb);
+#else
+static inline int skb_checksum_setup(struct sk_buff *skb) { return 0; }
+#endif
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
--- linux-ec2-2.6.32.orig/include/linux/pid.h
+++ linux-ec2-2.6.32/include/linux/pid.h
@@ -117,7 +117,7 @@
  */
 extern struct pid *find_get_pid(int nr);
 extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
-int next_pidmap(struct pid_namespace *pid_ns, int last);
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last);
 
 extern struct pid *alloc_pid(struct pid_namespace *ns);
 extern void free_pid(struct pid *pid);
--- linux-ec2-2.6.32.orig/include/linux/quota.h
+++ linux-ec2-2.6.32/include/linux/quota.h
@@ -313,8 +313,9 @@
 	int (*claim_space) (struct inode *, qsize_t);
 	/* release rsved quota for delayed alloc */
 	void (*release_rsv) (struct inode *, qsize_t);
-	/* get reserved quota for delayed alloc */
-	qsize_t (*get_reserved_space) (struct inode *);
+	/* get reserved quota for delayed alloc, value returned is managed by
+	 * quota code only */
+	qsize_t *(*get_reserved_space) (struct inode *);
 };
 
 /* Operations handling requests from userspace */
--- linux-ec2-2.6.32.orig/include/linux/msi.h
+++ linux-ec2-2.6.32/include/linux/msi.h
@@ -14,8 +14,10 @@
 extern void mask_msi_irq(unsigned int irq);
 extern void unmask_msi_irq(unsigned int irq);
 extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
+extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
 extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
 extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
+extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
 extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
 
 struct msi_desc {
--- linux-ec2-2.6.32.orig/include/linux/topology.h
+++ linux-ec2-2.6.32/include/linux/topology.h
@@ -99,7 +99,7 @@
 				| 1*SD_WAKE_AFFINE			\
 				| 1*SD_SHARE_CPUPOWER			\
 				| 0*SD_POWERSAVINGS_BALANCE		\
-				| 0*SD_SHARE_PKG_RESOURCES		\
+				| 1*SD_SHARE_PKG_RESOURCES		\
 				| 0*SD_SERIALIZE			\
 				| 0*SD_PREFER_SIBLING			\
 				,					\
--- linux-ec2-2.6.32.orig/include/linux/lcm.h
+++ linux-ec2-2.6.32/include/linux/lcm.h
@@ -0,0 +1,8 @@
+#ifndef _LCM_H
+#define _LCM_H
+
+#include <linux/compiler.h>
+
+unsigned long lcm(unsigned long a, unsigned long b) __attribute_const__;
+
+#endif /* _LCM_H */
--- linux-ec2-2.6.32.orig/include/linux/kvm.h
+++ linux-ec2-2.6.32/include/linux/kvm.h
@@ -116,6 +116,11 @@
 	__u64 cr8;
 	__u64 apic_base;
 
+#ifdef __KVM_S390
+	/* the processor status word for s390 */
+	__u64 psw_mask; /* psw upper half */
+	__u64 psw_addr; /* psw lower half */
+#endif
 	union {
 		/* KVM_EXIT_UNKNOWN */
 		struct {
@@ -167,8 +172,6 @@
 		/* KVM_EXIT_S390_SIEIC */
 		struct {
 			__u8 icptcode;
-			__u64 mask; /* psw upper half */
-			__u64 addr; /* psw lower half */
 			__u16 ipa;
 			__u32 ipb;
 		} s390_sieic;
@@ -436,6 +439,7 @@
 #endif
 #define KVM_CAP_IOEVENTFD 36
 #define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
+#define KVM_CAP_ADJUST_CLOCK 39
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -474,6 +478,7 @@
 };
 
 #endif
+#define KVM_CAP_S390_PSW 42
 
 #ifdef KVM_CAP_MCE
 /* x86 MCE */
@@ -497,6 +502,12 @@
 	__u8  pad[20];
 };
 
+struct kvm_clock_data {
+	__u64 clock;
+	__u32 flags;
+	__u32 pad[9];
+};
+
 /*
  * ioctls for VM fds
  */
@@ -546,6 +557,8 @@
 #define KVM_CREATE_PIT2		   _IOW(KVMIO, 0x77, struct kvm_pit_config)
 #define KVM_SET_BOOT_CPU_ID        _IO(KVMIO, 0x78)
 #define KVM_IOEVENTFD             _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+#define KVM_SET_CLOCK             _IOW(KVMIO, 0x7b, struct kvm_clock_data)
+#define KVM_GET_CLOCK             _IOR(KVMIO, 0x7c, struct kvm_clock_data)
 
 /*
  * ioctls for vcpu fds
--- linux-ec2-2.6.32.orig/include/linux/mm_types.h
+++ linux-ec2-2.6.32/include/linux/mm_types.h
@@ -138,7 +138,7 @@
 					   within vm_mm. */
 
 	/* linked list of VM areas per task, sorted by address */
-	struct vm_area_struct *vm_next;
+	struct vm_area_struct *vm_next, *vm_prev;
 
 	pgprot_t vm_page_prot;		/* Access permissions of this VMA. */
 	unsigned long vm_flags;		/* Flags, see mm.h. */
@@ -206,6 +206,9 @@
 	unsigned long (*get_unmapped_area) (struct file *filp,
 				unsigned long addr, unsigned long len,
 				unsigned long pgoff, unsigned long flags);
+       unsigned long (*get_unmapped_exec_area) (struct file *filp,
+				unsigned long addr, unsigned long len,
+				unsigned long pgoff, unsigned long flags);
 	void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
 	unsigned long mmap_base;		/* base of mmap area */
 	unsigned long task_size;		/* size of task vm space */
--- linux-ec2-2.6.32.orig/include/linux/ata.h
+++ linux-ec2-2.6.32/include/linux/ata.h
@@ -1000,8 +1000,8 @@
 
 static inline int lba_28_ok(u64 block, u32 n_block)
 {
-	/* check the ending block number */
-	return ((block + n_block) < ((u64)1 << 28)) && (n_block <= 256);
+	/* check the ending block number: must be LESS THAN 0x0fffffff */
+	return ((block + n_block) < ((1 << 28) - 1)) && (n_block <= 256);
 }
 
 static inline int lba_48_ok(u64 block, u32 n_block)
--- linux-ec2-2.6.32.orig/include/linux/splice.h
+++ linux-ec2-2.6.32/include/linux/splice.h
@@ -82,4 +82,10 @@
 extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
 				      splice_direct_actor *);
 
+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+			   loff_t *ppos, size_t len, unsigned int flags);
+extern long do_splice_to(struct file *in, loff_t *ppos,
+			 struct pipe_inode_info *pipe, size_t len,
+			 unsigned int flags);
+
 #endif
--- linux-ec2-2.6.32.orig/include/linux/poison.h
+++ linux-ec2-2.6.32/include/linux/poison.h
@@ -2,13 +2,25 @@
 #define _LINUX_POISON_H
 
 /********** include/linux/list.h **********/
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
 /*
  * These are non-NULL pointers that will result in page faults
  * under normal circumstances, used to verify that nobody uses
  * non-initialized list entries.
  */
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
+#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
 
 /********** include/linux/timer.h **********/
 /*
@@ -36,6 +48,15 @@
 #define POISON_FREE	0x6b	/* for use-after-free poisoning */
 #define	POISON_END	0xa5	/* end-byte of poisoning */
 
+/********** mm/hugetlb.c **********/
+/*
+ * Private mappings of hugetlb pages use this poisoned value for
+ * page->mapping. The core VM should not be doing anything with this mapping
+ * but futex requires the existence of some page->mapping value even though it
+ * is unused if PAGE_MAPPING_ANON is set.
+ */
+#define HUGETLB_POISON	((void *)(0x00300300 + POISON_POINTER_DELTA + PAGE_MAPPING_ANON))
+
 /********** arch/$ARCH/mm/init.c **********/
 #define POISON_FREE_INITMEM	0xcc
 
--- linux-ec2-2.6.32.orig/include/linux/fs.h
+++ linux-ec2-2.6.32/include/linux/fs.h
@@ -87,6 +87,9 @@
  */
 #define FMODE_NOCMTIME		((__force fmode_t)2048)
 
+/* Expect random access pattern */
+#define FMODE_RANDOM		((__force fmode_t)4096)
+
 /*
  * The below are the various read and write types that we support. Some of
  * them include behavioral modifiers that send information down to the
@@ -142,11 +145,11 @@
  *
  */
 #define RW_MASK		1
-#define RWA_MASK	2
+#define RWA_MASK		16
 #define READ 0
 #define WRITE 1
-#define READA 2		/* read-ahead  - don't block if no resources */
-#define SWRITE 3	/* for ll_rw_block() - wait for buffer lock */
+#define READA			16 /* readahead - don't block if no resources */
+#define SWRITE			17 /* for ll_rw_block(), wait for buffer lock */
 #define READ_SYNC	(READ | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
 #define READ_META	(READ | (1 << BIO_RW_META))
 #define WRITE_SYNC_PLUG	(WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE))
@@ -1307,6 +1310,8 @@
 #define MNT_FORCE	0x00000001	/* Attempt to forcibily umount */
 #define MNT_DETACH	0x00000002	/* Just detach from the tree */
 #define MNT_EXPIRE	0x00000004	/* Mark for expiry */
+#define UMOUNT_NOFOLLOW	0x00000008	/* Don't follow symlink on umount */
+#define UMOUNT_UNUSED	0x80000000	/* Flag guaranteed to be unused */
 
 extern struct list_head super_blocks;
 extern spinlock_t sb_lock;
@@ -1368,6 +1373,9 @@
 	/* Granularity of c/m/atime in ns.
 	   Cannot be worse than a second */
 	u32		   s_time_gran;
+#ifdef CONFIG_PRECACHE
+	u32                precache_poolid;
+#endif
 
 	/*
 	 * Filesystem subtype.  If non-empty the filesystem type field
@@ -2222,6 +2230,7 @@
 /* fs/block_dev.c */
 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos);
+extern int block_fsync(struct file *filp, struct dentry *dentry, int datasync);
 
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
@@ -2314,6 +2323,7 @@
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+void __inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_add_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
@@ -2371,7 +2381,7 @@
 extern const struct inode_operations simple_dir_inode_operations;
 struct tree_descr { char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
+extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *);
 extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
 
--- linux-ec2-2.6.32.orig/include/linux/mm.h
+++ linux-ec2-2.6.32/include/linux/mm.h
@@ -77,7 +77,11 @@
 #define VM_MAYSHARE	0x00000080
 
 #define VM_GROWSDOWN	0x00000100	/* general info on the segment */
+#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64)
 #define VM_GROWSUP	0x00000200
+#else
+#define VM_GROWSUP	0x00000000
+#endif
 #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
 #define VM_DENYWRITE	0x00000800	/* ETXTBSY on write attempts.. */
 
@@ -102,7 +106,12 @@
 
 #define VM_CAN_NONLINEAR 0x08000000	/* Has ->fault & does nonlinear pages */
 #define VM_MIXEDMAP	0x10000000	/* Can contain "struct page" and pure PFN pages */
+#ifndef CONFIG_XEN
 #define VM_SAO		0x20000000	/* Strong Access Ordering (powerpc) */
+#else
+#define VM_SAO		0
+#define VM_FOREIGN	0x20000000	/* Has pages belonging to another VM */
+#endif
 #define VM_PFN_AT_MMAP	0x40000000	/* PFNMAP vma that is fully mapped at mmap time */
 #define VM_MERGEABLE	0x80000000	/* KSM may merge identical pages */
 
@@ -127,6 +136,12 @@
  */
 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
 
+#ifdef CONFIG_XEN
+struct vm_foreign_map {
+	struct page **map;
+};
+#endif
+
 /*
  * mapping from the currently active vm_flags protection bits (the
  * low four bits) to a page protection mask..
@@ -195,6 +210,17 @@
 	 */
 	int (*access)(struct vm_area_struct *vma, unsigned long addr,
 		      void *buf, int len, int write);
+
+#ifdef CONFIG_XEN
+	/* Area-specific function for clearing the PTE at @ptep. Returns the
+	 * original value of @ptep. */
+	pte_t (*zap_pte)(struct vm_area_struct *vma,
+			 unsigned long addr, pte_t *ptep, int is_fullmm);
+
+	/* called before close() to indicate no more pages should be mapped */
+	void (*unmap)(struct vm_area_struct *area);
+#endif
+
 #ifdef CONFIG_NUMA
 	/*
 	 * set_policy() op must add a reference to any non-NULL @new mempolicy
@@ -837,6 +863,12 @@
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
 
+/* Is the vma a continuation of the stack vma above it? */
+static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr)
+{
+	return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
+}
+
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
 		unsigned long old_addr, struct vm_area_struct *new_vma,
 		unsigned long new_addr, unsigned long len);
@@ -1129,7 +1161,15 @@
 				   unsigned long addr, unsigned long len,
 				   unsigned long flags, struct page **pages);
 
-extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+extern unsigned long get_unmapped_area_prot(struct file *, unsigned long,
+		unsigned long, unsigned long, unsigned long, int);
+
+static inline unsigned long get_unmapped_area(struct file *file,
+		unsigned long addr, unsigned long len, unsigned long pgoff,
+		unsigned long flags)
+{
+	return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0);
+}
 
 extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
@@ -1195,8 +1235,10 @@
 
 /* Do stack extension */
 extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
-#ifdef CONFIG_IA64
+#if VM_GROWSUP
 extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
+#else
+  #define expand_upwards(vma, address) do { } while (0)
 #endif
 extern int expand_stack_downwards(struct vm_area_struct *vma,
 				  unsigned long address);
--- linux-ec2-2.6.32.orig/include/linux/tick.h
+++ linux-ec2-2.6.32/include/linux/tick.h
@@ -98,6 +98,9 @@
 extern struct tick_sched *tick_get_tick_sched(int cpu);
 extern void tick_check_idle(int cpu);
 extern int tick_oneshot_mode_active(void);
+#  ifndef arch_needs_cpu
+#   define arch_needs_cpu(cpu) (0)
+#  endif
 # else
 static inline void tick_clock_notify(void) { }
 static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
--- linux-ec2-2.6.32.orig/include/linux/aio.h
+++ linux-ec2-2.6.32/include/linux/aio.h
@@ -201,6 +201,12 @@
 
 	struct delayed_work	wq;
 
+#ifdef CONFIG_EPOLL
+	/* poll integration */
+	wait_queue_head_t       poll_wait;
+	struct file		*file;
+#endif
+
 	struct rcu_head		rcu_head;
 };
 
--- linux-ec2-2.6.32.orig/include/linux/ethtool.h
+++ linux-ec2-2.6.32/include/linux/ethtool.h
@@ -357,6 +357,8 @@
 	__u32				flow_type;
 	/* The rx flow hash value or the rule DB size */
 	__u64				data;
+	/* The following fields are not valid and must not be used for
+	 * the ETHTOOL_{G,X}RXFH commands. */
 	struct ethtool_rx_flow_spec	fs;
 	__u32				rule_cnt;
 	__u32				rule_locs[0];
@@ -502,6 +504,7 @@
 	int	(*get_rxnfc)(struct net_device *, struct ethtool_rxnfc *, void *);
 	int	(*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
 	int     (*flash_device)(struct net_device *, struct ethtool_flash *);
+	int	(*reset)(struct net_device *, u32 *);
 };
 #endif /* __KERNEL__ */
 
@@ -559,6 +562,7 @@
 #define	ETHTOOL_SRXCLSRLDEL	0x00000031 /* Delete RX classification rule */
 #define	ETHTOOL_SRXCLSRLINS	0x00000032 /* Insert RX classification rule */
 #define	ETHTOOL_FLASHDEV	0x00000033 /* Flash firmware to device */
+#define	ETHTOOL_RESET		0x00000034 /* Reset hardware */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
@@ -689,4 +693,34 @@
 
 #define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
 
+/* Reset flags */
+/* The reset() operation must clear the flags for the components which
+ * were actually reset.  On successful return, the flags indicate the
+ * components which were not reset, either because they do not exist
+ * in the hardware or because they cannot be reset independently.  The
+ * driver must never reset any components that were not requested.
+ */
+enum ethtool_reset_flags {
+	/* These flags represent components dedicated to the interface
+	 * the command is addressed to.  Shift any flag left by
+	 * ETH_RESET_SHARED_SHIFT to reset a shared component of the
+	 * same type.
+	 */
+	ETH_RESET_MGMT		= 1 << 0,	/* Management processor */
+	ETH_RESET_IRQ		= 1 << 1,	/* Interrupt requester */
+	ETH_RESET_DMA		= 1 << 2,	/* DMA engine */
+	ETH_RESET_FILTER	= 1 << 3,	/* Filtering/flow direction */
+	ETH_RESET_OFFLOAD	= 1 << 4,	/* Protocol offload */
+	ETH_RESET_MAC		= 1 << 5,	/* Media access controller */
+	ETH_RESET_PHY		= 1 << 6,	/* Transceiver/PHY */
+	ETH_RESET_RAM		= 1 << 7,	/* RAM shared between
+						 * multiple components */
+
+	ETH_RESET_DEDICATED	= 0x0000ffff,	/* All components dedicated to
+						 * this interface */
+	ETH_RESET_ALL		= 0xffffffff,	/* All components used by this
+						 * interface, even if shared */
+};
+#define ETH_RESET_SHARED_SHIFT	16
+
 #endif /* _LINUX_ETHTOOL_H */
--- linux-ec2-2.6.32.orig/include/linux/netdevice.h
+++ linux-ec2-2.6.32/include/linux/netdevice.h
@@ -348,13 +348,14 @@
 	NAPI_STATE_NPSVC,	/* Netpoll - don't dequeue from poll_list */
 };
 
-enum {
+enum gro_result {
 	GRO_MERGED,
 	GRO_MERGED_FREE,
 	GRO_HELD,
 	GRO_NORMAL,
 	GRO_DROP,
 };
+typedef enum gro_result gro_result_t;
 
 extern void __napi_schedule(struct napi_struct *n);
 
@@ -1467,18 +1468,19 @@
 #define HAVE_NETIF_RECEIVE_SKB 1
 extern int		netif_receive_skb(struct sk_buff *skb);
 extern void		napi_gro_flush(struct napi_struct *napi);
-extern int		dev_gro_receive(struct napi_struct *napi,
+extern gro_result_t	dev_gro_receive(struct napi_struct *napi,
 					struct sk_buff *skb);
-extern int		napi_skb_finish(int ret, struct sk_buff *skb);
-extern int		napi_gro_receive(struct napi_struct *napi,
+extern gro_result_t	napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
+extern gro_result_t	napi_gro_receive(struct napi_struct *napi,
 					 struct sk_buff *skb);
 extern void		napi_reuse_skb(struct napi_struct *napi,
 				       struct sk_buff *skb);
 extern struct sk_buff *	napi_get_frags(struct napi_struct *napi);
-extern int		napi_frags_finish(struct napi_struct *napi,
-					  struct sk_buff *skb, int ret);
+extern gro_result_t	napi_frags_finish(struct napi_struct *napi,
+					  struct sk_buff *skb,
+					  gro_result_t ret);
 extern struct sk_buff *	napi_frags_skb(struct napi_struct *napi);
-extern int		napi_gro_frags(struct napi_struct *napi);
+extern gro_result_t	napi_gro_frags(struct napi_struct *napi);
 
 static inline void napi_free_frags(struct napi_struct *napi)
 {
@@ -1560,6 +1562,8 @@
 
 extern void netif_carrier_off(struct net_device *dev);
 
+extern void netif_notify_peers(struct net_device *dev);
+
 /**
  *	netif_dormant_on - mark device as dormant.
  *	@dev: network device
@@ -2013,6 +2017,10 @@
 		return 0;
 	return dev->ethtool_ops->get_flags(dev);
 }
+
+#define MODULE_ALIAS_NETDEV(device) \
+	MODULE_ALIAS("netdev-" device)
+
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_NETDEVICE_H */
--- linux-ec2-2.6.32.orig/include/linux/cpuset.h
+++ linux-ec2-2.6.32/include/linux/cpuset.h
@@ -21,8 +21,7 @@
 extern int cpuset_init(void);
 extern void cpuset_init_smp(void);
 extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
-extern void cpuset_cpus_allowed_locked(struct task_struct *p,
-				       struct cpumask *mask);
+extern int cpuset_cpus_allowed_fallback(struct task_struct *p);
 extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
 #define cpuset_current_mems_allowed (current->mems_allowed)
 void cpuset_init_current_mems_allowed(void);
@@ -69,9 +68,6 @@
 extern void cpuset_task_status_allowed(struct seq_file *m,
 					struct task_struct *task);
 
-extern void cpuset_lock(void);
-extern void cpuset_unlock(void);
-
 extern int cpuset_mem_spread_node(void);
 
 static inline int cpuset_do_page_mem_spread(void)
@@ -105,10 +101,11 @@
 {
 	cpumask_copy(mask, cpu_possible_mask);
 }
-static inline void cpuset_cpus_allowed_locked(struct task_struct *p,
-					      struct cpumask *mask)
+
+static inline int cpuset_cpus_allowed_fallback(struct task_struct *p)
 {
-	cpumask_copy(mask, cpu_possible_mask);
+	cpumask_copy(&p->cpus_allowed, cpu_possible_mask);
+	return cpumask_any(cpu_active_mask);
 }
 
 static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
@@ -157,9 +154,6 @@
 {
 }
 
-static inline void cpuset_lock(void) {}
-static inline void cpuset_unlock(void) {}
-
 static inline int cpuset_mem_spread_node(void)
 {
 	return 0;
--- linux-ec2-2.6.32.orig/include/linux/reiserfs_xattr.h
+++ linux-ec2-2.6.32/include/linux/reiserfs_xattr.h
@@ -70,6 +70,11 @@
 void reiserfs_security_free(struct reiserfs_security_handle *sec);
 #endif
 
+static inline int reiserfs_xattrs_initialized(struct super_block *sb)
+{
+	return REISERFS_SB(sb)->priv_root != NULL;
+}
+
 #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
 static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
 {
--- linux-ec2-2.6.32.orig/include/linux/cred.h
+++ linux-ec2-2.6.32/include/linux/cred.h
@@ -153,6 +153,7 @@
 extern void __put_cred(struct cred *);
 extern void exit_creds(struct task_struct *);
 extern int copy_creds(struct task_struct *, unsigned long);
+extern const struct cred *get_task_cred(struct task_struct *);
 extern struct cred *cred_alloc_blank(void);
 extern struct cred *prepare_creds(void);
 extern struct cred *prepare_exec_creds(void);
@@ -283,26 +284,6 @@
 	((const struct cred *)(rcu_dereference((task)->real_cred)))
 
 /**
- * get_task_cred - Get another task's objective credentials
- * @task: The task to query
- *
- * Get the objective credentials of a task, pinning them so that they can't go
- * away.  Accessing a task's credentials directly is not permitted.
- *
- * The caller must make sure task doesn't go away, either by holding a ref on
- * task or by holding tasklist_lock to prevent it from being unlinked.
- */
-#define get_task_cred(task)				\
-({							\
-	struct cred *__cred;				\
-	rcu_read_lock();				\
-	__cred = (struct cred *) __task_cred((task));	\
-	get_cred(__cred);				\
-	rcu_read_unlock();				\
-	__cred;						\
-})
-
-/**
  * get_current_cred - Get the current task's subjective credentials
  *
  * Get the subjective credentials of the current task, pinning them so that
--- linux-ec2-2.6.32.orig/include/linux/if_vlan.h
+++ linux-ec2-2.6.32/include/linux/if_vlan.h
@@ -115,10 +115,12 @@
 extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
 			     u16 vlan_tci, int polling);
 extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
-extern int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
-			    unsigned int vlan_tci, struct sk_buff *skb);
-extern int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
-			  unsigned int vlan_tci);
+extern gro_result_t
+vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
+		 unsigned int vlan_tci, struct sk_buff *skb);
+extern gro_result_t
+vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
+	       unsigned int vlan_tci);
 
 #else
 static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
@@ -145,17 +147,18 @@
 	return 0;
 }
 
-static inline int vlan_gro_receive(struct napi_struct *napi,
-				   struct vlan_group *grp,
-				   unsigned int vlan_tci, struct sk_buff *skb)
+static inline gro_result_t
+vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
+		 unsigned int vlan_tci, struct sk_buff *skb)
 {
-	return NET_RX_DROP;
+	return GRO_DROP;
 }
 
-static inline int vlan_gro_frags(struct napi_struct *napi,
-				 struct vlan_group *grp, unsigned int vlan_tci)
+static inline gro_result_t
+vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
+	       unsigned int vlan_tci)
 {
-	return NET_RX_DROP;
+	return GRO_DROP;
 }
 #endif
 
--- linux-ec2-2.6.32.orig/include/linux/compat.h
+++ linux-ec2-2.6.32/include/linux/compat.h
@@ -309,5 +309,7 @@
 asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
 				  int flags, int mode);
 
+extern void __user *compat_alloc_user_space(unsigned long len);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
--- linux-ec2-2.6.32.orig/include/linux/nfs_fs_sb.h
+++ linux-ec2-2.6.32/include/linux/nfs_fs_sb.h
@@ -176,6 +176,7 @@
 #define NFS_CAP_ATIME		(1U << 11)
 #define NFS_CAP_CTIME		(1U << 12)
 #define NFS_CAP_MTIME		(1U << 13)
+#define NFS_CAP_POSIX_LOCK	(1U << 14)
 
 
 /* maximum number of slots to use */
--- linux-ec2-2.6.32.orig/include/linux/cpufreq.h
+++ linux-ec2-2.6.32/include/linux/cpufreq.h
@@ -302,7 +302,7 @@
 #endif
 
 /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
 unsigned int cpufreq_quick_get(unsigned int cpu);
 #else
 static inline unsigned int cpufreq_quick_get(unsigned int cpu)
--- linux-ec2-2.6.32.orig/include/linux/list_sort.h
+++ linux-ec2-2.6.32/include/linux/list_sort.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_LIST_SORT_H
+#define _LINUX_LIST_SORT_H
+
+#include <linux/types.h>
+
+struct list_head;
+
+void list_sort(void *priv, struct list_head *head,
+	       int (*cmp)(void *priv, struct list_head *a,
+			  struct list_head *b));
+#endif
--- linux-ec2-2.6.32.orig/include/linux/precache.h
+++ linux-ec2-2.6.32/include/linux/precache.h
@@ -0,0 +1,55 @@
+#ifndef _LINUX_PRECACHE_H
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#ifdef CONFIG_PRECACHE
+extern void precache_init(struct super_block *sb);
+extern void shared_precache_init(struct super_block *sb, char *uuid);
+extern int precache_get(struct address_space *mapping, unsigned long index,
+	       struct page *empty_page);
+extern int precache_put(struct address_space *mapping, unsigned long index,
+		struct page *page);
+extern int precache_flush(struct address_space *mapping, unsigned long index);
+extern int precache_flush_inode(struct address_space *mapping);
+extern int precache_flush_filesystem(struct super_block *s);
+#else
+static inline void precache_init(struct super_block *sb)
+{
+}
+
+static inline void shared_precache_init(struct super_block *sb, char *uuid)
+{
+}
+
+static inline int precache_get(struct address_space *mapping,
+		unsigned long index, struct page *empty_page)
+{
+	return 0;
+}
+
+static inline int precache_put(struct address_space *mapping,
+		unsigned long index, struct page *page)
+{
+	return 0;
+}
+
+static inline int precache_flush(struct address_space *mapping,
+		unsigned long index)
+{
+	return 0;
+}
+
+static inline int precache_flush_inode(struct address_space *mapping)
+{
+	return 0;
+}
+
+static inline int precache_flush_filesystem(struct super_block *s)
+{
+	return 0;
+}
+#endif
+
+#define _LINUX_PRECACHE_H
+#endif /* _LINUX_PRECACHE_H */
--- linux-ec2-2.6.32.orig/include/linux/audit.h
+++ linux-ec2-2.6.32/include/linux/audit.h
@@ -33,7 +33,7 @@
  * 1200 - 1299 messages internal to the audit daemon
  * 1300 - 1399 audit event messages
  * 1400 - 1499 SE Linux use
- * 1500 - 1599 kernel LSPP events
+ * 1500 - 1599 AppArmor use
  * 1600 - 1699 kernel crypto events
  * 1700 - 1799 kernel anomaly records
  * 1800 - 1899 kernel integrity events
@@ -122,6 +122,14 @@
 #define AUDIT_MAC_UNLBL_STCADD	1416	/* NetLabel: add a static label */
 #define AUDIT_MAC_UNLBL_STCDEL	1417	/* NetLabel: del a static label */
 
+#define AUDIT_APPARMOR_AUDIT	1501	/* AppArmor audited grants */
+#define AUDIT_APPARMOR_ALLOWED	1502	/* Allowed Access for learning */
+#define AUDIT_APPARMOR_DENIED	1503
+#define AUDIT_APPARMOR_HINT	1504	/* Process Tracking information */
+#define AUDIT_APPARMOR_STATUS	1505	/* Changes in config */
+#define AUDIT_APPARMOR_ERROR	1506	/* Internal AppArmor Errors */
+#define AUDIT_APPARMOR_KILL	1507	/* AppArmor killing processes */
+
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
--- linux-ec2-2.6.32.orig/include/linux/highmem.h
+++ linux-ec2-2.6.32/include/linux/highmem.h
@@ -130,12 +130,14 @@
 	return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
 }
 
+#ifndef __HAVE_ARCH_CLEAR_HIGHPAGE
 static inline void clear_highpage(struct page *page)
 {
 	void *kaddr = kmap_atomic(page, KM_USER0);
 	clear_page(kaddr);
 	kunmap_atomic(kaddr, KM_USER0);
 }
+#endif
 
 static inline void zero_user_segments(struct page *page,
 	unsigned start1, unsigned end1,
@@ -189,6 +191,8 @@
 
 #endif
 
+#ifndef __HAVE_ARCH_COPY_HIGHPAGE
+
 static inline void copy_highpage(struct page *to, struct page *from)
 {
 	char *vfrom, *vto;
@@ -200,4 +204,6 @@
 	kunmap_atomic(vto, KM_USER1);
 }
 
+#endif
+
 #endif /* _LINUX_HIGHMEM_H */
--- linux-ec2-2.6.32.orig/include/linux/kvm_host.h
+++ linux-ec2-2.6.32/include/linux/kvm_host.h
@@ -53,7 +53,7 @@
  */
 struct kvm_io_bus {
 	int                   dev_count;
-#define NR_IOBUS_DEVS 6
+#define NR_IOBUS_DEVS 200
 	struct kvm_io_device *devs[NR_IOBUS_DEVS];
 };
 
@@ -116,6 +116,11 @@
 	int user_alloc;
 };
 
+static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot)
+{
+	return ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+}
+
 struct kvm_kernel_irq_routing_entry {
 	u32 gsi;
 	u32 type;
@@ -266,6 +271,7 @@
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
 
 void kvm_vcpu_block(struct kvm_vcpu *vcpu);
+void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu);
 void kvm_resched(struct kvm_vcpu *vcpu);
 void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
 void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
--- linux-ec2-2.6.32.orig/include/linux/hardirq.h
+++ linux-ec2-2.6.32/include/linux/hardirq.h
@@ -64,6 +64,8 @@
 #define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
 #define NMI_OFFSET	(1UL << NMI_SHIFT)
 
+#define SOFTIRQ_DISABLE_OFFSET	(2 * SOFTIRQ_OFFSET)
+
 #ifndef PREEMPT_ACTIVE
 #define PREEMPT_ACTIVE_BITS	1
 #define PREEMPT_ACTIVE_SHIFT	(NMI_SHIFT + NMI_BITS)
@@ -82,10 +84,13 @@
 /*
  * Are we doing bottom half or hardware interrupt processing?
  * Are we in a softirq context? Interrupt context?
+ * in_softirq - Are we currently processing softirq or have bh disabled?
+ * in_serving_softirq - Are we currently processing softirq?
  */
 #define in_irq()		(hardirq_count())
 #define in_softirq()		(softirq_count())
 #define in_interrupt()		(irq_count())
+#define in_serving_softirq()	(softirq_count() & SOFTIRQ_OFFSET)
 
 /*
  * Are we in NMI context?
@@ -132,10 +137,12 @@
 
 struct task_struct;
 
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+#if !defined(CONFIG_VIRT_CPU_ACCOUNTING) && !defined(CONFIG_IRQ_TIME_ACCOUNTING)
 static inline void account_system_vtime(struct task_struct *tsk)
 {
 }
+#else
+extern void account_system_vtime(struct task_struct *tsk);
 #endif
 
 #if defined(CONFIG_NO_HZ)
--- linux-ec2-2.6.32.orig/include/linux/irq.h
+++ linux-ec2-2.6.32/include/linux/irq.h
@@ -400,7 +400,9 @@
 
 /* Dynamic irq helper functions */
 extern void dynamic_irq_init(unsigned int irq);
+void dynamic_irq_init_keep_chip_data(unsigned int irq);
 extern void dynamic_irq_cleanup(unsigned int irq);
+void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
 
 /* Set/get chip/data for an IRQ: */
 extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
--- linux-ec2-2.6.32.orig/include/linux/jbd2.h
+++ linux-ec2-2.6.32/include/linux/jbd2.h
@@ -653,6 +653,7 @@
 	 * waiting for it to finish.
 	 */
 	unsigned int t_synchronous_commit:1;
+	unsigned int t_flushed_data_blocks:1;
 
 	/*
 	 * For use by the filesystem to store fs-specific data
--- linux-ec2-2.6.32.orig/include/linux/hrtimer.h
+++ linux-ec2-2.6.32/include/linux/hrtimer.h
@@ -162,10 +162,11 @@
  * @expires_next:	absolute time of the next event which was scheduled
  *			via clock_set_next_event()
  * @hres_active:	State of high resolution mode
- * @check_clocks:	Indictator, when set evaluate time source and clock
- *			event devices whether high resolution mode can be
- *			activated.
- * @nr_events:		Total number of timer interrupt events
+ * @hang_detected:	The last hrtimer interrupt detected a hang
+ * @nr_events:		Total number of hrtimer interrupt events
+ * @nr_retries:		Total number of hrtimer interrupt retries
+ * @nr_hangs:		Total number of hrtimer interrupt hangs
+ * @max_hang_time:	Maximum time spent in hrtimer_interrupt
  */
 struct hrtimer_cpu_base {
 	spinlock_t			lock;
@@ -173,7 +174,11 @@
 #ifdef CONFIG_HIGH_RES_TIMERS
 	ktime_t				expires_next;
 	int				hres_active;
+	int				hang_detected;
 	unsigned long			nr_events;
+	unsigned long			nr_retries;
+	unsigned long			nr_hangs;
+	ktime_t				max_hang_time;
 #endif
 };
 
@@ -446,7 +451,7 @@
 
 static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
 {
-	if (likely(!timer->start_site))
+	if (likely(!timer_stats_active))
 		return;
 	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
 				 timer->function, timer->start_comm, 0);
@@ -457,8 +462,6 @@
 
 static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
 {
-	if (likely(!timer_stats_active))
-		return;
 	__timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0));
 }
 
--- linux-ec2-2.6.32.orig/include/linux/freezer.h
+++ linux-ec2-2.6.32/include/linux/freezer.h
@@ -64,9 +64,12 @@
 extern void cancel_freezing(struct task_struct *p);
 
 #ifdef CONFIG_CGROUP_FREEZER
-extern int cgroup_frozen(struct task_struct *task);
+extern int cgroup_freezing_or_frozen(struct task_struct *task);
 #else /* !CONFIG_CGROUP_FREEZER */
-static inline int cgroup_frozen(struct task_struct *task) { return 0; }
+static inline int cgroup_freezing_or_frozen(struct task_struct *task)
+{
+	return 0;
+}
 #endif /* !CONFIG_CGROUP_FREEZER */
 
 /*
--- linux-ec2-2.6.32.orig/include/linux/notifier.h
+++ linux-ec2-2.6.32/include/linux/notifier.h
@@ -201,6 +201,7 @@
 #define NETDEV_PRE_UP		0x000D
 #define NETDEV_BONDING_OLDTYPE  0x000E
 #define NETDEV_BONDING_NEWTYPE  0x000F
+#define NETDEV_NOTIFY_PEERS	0x0013
 
 #define SYS_DOWN	0x0001	/* Notify of system down */
 #define SYS_RESTART	SYS_DOWN
--- linux-ec2-2.6.32.orig/include/linux/hid.h
+++ linux-ec2-2.6.32/include/linux/hid.h
@@ -312,6 +312,7 @@
 #define HID_QUIRK_MULTI_INPUT			0x00000040
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
 #define HID_QUIRK_FULLSPEED_INTERVAL		0x10000000
+#define HID_QUIRK_NO_INIT_REPORTS		0x20000000
 
 /*
  * This is the global environment of the parser. This information is
--- linux-ec2-2.6.32.orig/include/linux/console.h
+++ linux-ec2-2.6.32/include/linux/console.h
@@ -63,6 +63,7 @@
 extern const struct consw vga_con;	/* VGA text console */
 extern const struct consw newport_con;	/* SGI Newport console  */
 extern const struct consw prom_con;	/* SPARC PROM console */
+extern int console_use_vt;
 
 int con_is_bound(const struct consw *csw);
 int register_con_driver(const struct consw *csw, int first, int last);
--- linux-ec2-2.6.32.orig/include/linux/module.h
+++ linux-ec2-2.6.32/include/linux/module.h
@@ -724,4 +724,13 @@
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif	/* CONFIG_GENERIC_BUG */
 
+/*
+ * Establish a symbolic link between 2 modules so that depmod
+ * and modprobe do the heavy lifting of loading the modules in the
+ * correct dependency order.
+ */
+#define MODULE_EXPORT(mod_name) int sym_link_##mod_name; EXPORT_SYMBOL(sym_link_##mod_name);
+#define MODULE_IMPORT(mod_name) extern int sym_link_##mod_name; int func_sym_link_##mod_name(void) {sym_link_##mod_name=1;}; EXPORT_SYMBOL(func_sym_link_##mod_name);
+
+
 #endif /* _LINUX_MODULE_H */
--- linux-ec2-2.6.32.orig/include/linux/kexec.h
+++ linux-ec2-2.6.32/include/linux/kexec.h
@@ -46,6 +46,13 @@
 			    KEXEC_CORE_NOTE_NAME_BYTES +		\
 			    KEXEC_CORE_NOTE_DESC_BYTES )
 
+#ifndef KEXEC_ARCH_HAS_PAGE_MACROS
+#define kexec_page_to_pfn(page)  page_to_pfn(page)
+#define kexec_pfn_to_page(pfn)   pfn_to_page(pfn)
+#define kexec_virt_to_phys(addr) virt_to_phys(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(addr)
+#endif
+
 /*
  * This structure is used to hold the arguments that are used when loading
  * kernel binaries.
@@ -112,6 +119,12 @@
 extern void machine_kexec(struct kimage *image);
 extern int machine_kexec_prepare(struct kimage *image);
 extern void machine_kexec_cleanup(struct kimage *image);
+#ifdef CONFIG_XEN
+extern int xen_machine_kexec_load(struct kimage *image);
+extern void xen_machine_kexec_unload(struct kimage *image);
+extern void xen_machine_kexec_setup_resources(void);
+extern void xen_machine_kexec_register_resources(struct resource *res);
+#endif
 extern asmlinkage long sys_kexec_load(unsigned long entry,
 					unsigned long nr_segments,
 					struct kexec_segment __user *segments,
@@ -192,8 +205,15 @@
 #define VMCOREINFO_BYTES           (4096)
 #define VMCOREINFO_NOTE_NAME       "VMCOREINFO"
 #define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#if !defined(CONFIG_XEN) || !defined(CONFIG_X86)
 #define VMCOREINFO_NOTE_SIZE       (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
 				    + VMCOREINFO_NOTE_NAME_BYTES)
+#else
+#define VMCOREINFO_NOTE_SIZE       ALIGN(KEXEC_NOTE_HEAD_BYTES*2 \
+					 + VMCOREINFO_BYTES \
+					 + VMCOREINFO_NOTE_NAME_BYTES, \
+					 PAGE_SIZE)
+#endif
 
 /* Location of a reserved region to hold the crash kernel.
  */
--- linux-ec2-2.6.32.orig/include/linux/connector.h
+++ linux-ec2-2.6.32/include/linux/connector.h
@@ -24,9 +24,6 @@
 
 #include <linux/types.h>
 
-#define CN_IDX_CONNECTOR		0xffffffff
-#define CN_VAL_CONNECTOR		0xffffffff
-
 /*
  * Process Events connector unique ids -- used for message routing
  */
@@ -73,30 +70,6 @@
 	__u8 data[0];
 };
 
-/*
- * Notify structure - requests notification about
- * registering/unregistering idx/val in range [first, first+range].
- */
-struct cn_notify_req {
-	__u32 first;
-	__u32 range;
-};
-
-/*
- * Main notification control message
- * *_notify_num 	- number of appropriate cn_notify_req structures after 
- *				this struct.
- * group 		- notification receiver's idx.
- * len 			- total length of the attached data.
- */
-struct cn_ctl_msg {
-	__u32 idx_notify_num;
-	__u32 val_notify_num;
-	__u32 group;
-	__u32 len;
-	__u8 data[0];
-};
-
 #ifdef __KERNEL__
 
 #include <asm/atomic.h>
@@ -149,11 +122,6 @@
 	u32 seq, group;
 };
 
-struct cn_ctl_entry {
-	struct list_head notify_entry;
-	struct cn_ctl_msg *msg;
-};
-
 struct cn_dev {
 	struct cb_id id;
 
--- linux-ec2-2.6.32.orig/include/linux/input.h
+++ linux-ec2-2.6.32/include/linux/input.h
@@ -595,6 +595,48 @@
 #define KEY_NUMERIC_STAR	0x20a
 #define KEY_NUMERIC_POUND	0x20b
 
+#define BTN_TRIGGER_HAPPY		0x2c0
+#define BTN_TRIGGER_HAPPY1		0x2c0
+#define BTN_TRIGGER_HAPPY2		0x2c1
+#define BTN_TRIGGER_HAPPY3		0x2c2
+#define BTN_TRIGGER_HAPPY4		0x2c3
+#define BTN_TRIGGER_HAPPY5		0x2c4
+#define BTN_TRIGGER_HAPPY6		0x2c5
+#define BTN_TRIGGER_HAPPY7		0x2c6
+#define BTN_TRIGGER_HAPPY8		0x2c7
+#define BTN_TRIGGER_HAPPY9		0x2c8
+#define BTN_TRIGGER_HAPPY10		0x2c9
+#define BTN_TRIGGER_HAPPY11		0x2ca
+#define BTN_TRIGGER_HAPPY12		0x2cb
+#define BTN_TRIGGER_HAPPY13		0x2cc
+#define BTN_TRIGGER_HAPPY14		0x2cd
+#define BTN_TRIGGER_HAPPY15		0x2ce
+#define BTN_TRIGGER_HAPPY16		0x2cf
+#define BTN_TRIGGER_HAPPY17		0x2d0
+#define BTN_TRIGGER_HAPPY18		0x2d1
+#define BTN_TRIGGER_HAPPY19		0x2d2
+#define BTN_TRIGGER_HAPPY20		0x2d3
+#define BTN_TRIGGER_HAPPY21		0x2d4
+#define BTN_TRIGGER_HAPPY22		0x2d5
+#define BTN_TRIGGER_HAPPY23		0x2d6
+#define BTN_TRIGGER_HAPPY24		0x2d7
+#define BTN_TRIGGER_HAPPY25		0x2d8
+#define BTN_TRIGGER_HAPPY26		0x2d9
+#define BTN_TRIGGER_HAPPY27		0x2da
+#define BTN_TRIGGER_HAPPY28		0x2db
+#define BTN_TRIGGER_HAPPY29		0x2dc
+#define BTN_TRIGGER_HAPPY30		0x2dd
+#define BTN_TRIGGER_HAPPY31		0x2de
+#define BTN_TRIGGER_HAPPY32		0x2df
+#define BTN_TRIGGER_HAPPY33		0x2e0
+#define BTN_TRIGGER_HAPPY34		0x2e1
+#define BTN_TRIGGER_HAPPY35		0x2e2
+#define BTN_TRIGGER_HAPPY36		0x2e3
+#define BTN_TRIGGER_HAPPY37		0x2e4
+#define BTN_TRIGGER_HAPPY38		0x2e5
+#define BTN_TRIGGER_HAPPY39		0x2e6
+#define BTN_TRIGGER_HAPPY40		0x2e7
+
 /* We avoid low common keys in module aliases so they don't get huge. */
 #define KEY_MIN_INTERESTING	KEY_MUTE
 #define KEY_MAX			0x2ff
@@ -658,6 +700,7 @@
 #define ABS_MT_TOOL_TYPE	0x37	/* Type of touching device */
 #define ABS_MT_BLOB_ID		0x38	/* Group a set of packets as a blob */
 #define ABS_MT_TRACKING_ID	0x39	/* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE		0x3a	/* Pressure on contact area */
 
 #define ABS_MAX			0x3f
 #define ABS_CNT			(ABS_MAX+1)
@@ -1118,6 +1161,7 @@
 	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 
 	struct input_handle *grab;
+	struct input_handle *filter;
 
 	spinlock_t event_lock;
 	struct mutex mutex;
@@ -1218,6 +1262,7 @@
 	void *private;
 
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
+	bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
 	void (*start)(struct input_handle *handle);
@@ -1295,6 +1340,9 @@
 int input_grab_device(struct input_handle *);
 void input_release_device(struct input_handle *);
 
+int input_filter_device(struct input_handle *);
+void input_unfilter_device(struct input_handle *);
+
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
--- linux-ec2-2.6.32.orig/include/linux/sysctl.h
+++ linux-ec2-2.6.32/include/linux/sysctl.h
@@ -68,6 +68,7 @@
 	CTL_BUS=8,		/* Busses */
 	CTL_ABI=9,		/* Binary emulation */
 	CTL_CPU=10,		/* CPU stuff (speed scaling, etc) */
+	CTL_XEN=123,		/* Xen info and control */
 	CTL_ARLAN=254,		/* arlan wireless driver */
 	CTL_S390DBF=5677,	/* s390 debug */
 	CTL_SUNRPC=7249,	/* sunrpc debug */
@@ -490,6 +491,7 @@
 	NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
 	NET_IPV4_CONF_ARP_ACCEPT=21,
 	NET_IPV4_CONF_ARP_NOTIFY=22,
+	NET_IPV4_CONF_SRC_VMARK=24,
 	__NET_IPV4_CONF_MAX
 };
 
--- linux-ec2-2.6.32.orig/include/linux/nfsd/xdr4.h
+++ linux-ec2-2.6.32/include/linux/nfsd/xdr4.h
@@ -480,18 +480,17 @@
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-	BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-	cinfo->atomic = 1;
+	BUG_ON(!fhp->fh_pre_saved);
+	cinfo->atomic = fhp->fh_post_saved;
 	cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
-	if (cinfo->change_supported) {
-		cinfo->before_change = fhp->fh_pre_change;
-		cinfo->after_change = fhp->fh_post_change;
-	} else {
-		cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
-		cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
-		cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
-		cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
-	}
+
+	cinfo->before_change = fhp->fh_pre_change;
+	cinfo->after_change = fhp->fh_post_change;
+	cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+	cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+	cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+	cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
--- linux-ec2-2.6.32.orig/include/linux/ssb/ssb_driver_chipcommon.h
+++ linux-ec2-2.6.32/include/linux/ssb/ssb_driver_chipcommon.h
@@ -53,6 +53,7 @@
 #define  SSB_CHIPCO_CAP_64BIT		0x08000000	/* 64-bit Backplane */
 #define  SSB_CHIPCO_CAP_PMU		0x10000000	/* PMU available (rev >= 20) */
 #define  SSB_CHIPCO_CAP_ECI		0x20000000	/* ECI available (rev >= 20) */
+#define  SSB_CHIPCO_CAP_SPROM		0x40000000	/* SPROM present */
 #define SSB_CHIPCO_CORECTL		0x0008
 #define  SSB_CHIPCO_CORECTL_UARTCLK0	0x00000001	/* Drive UART with internal clock */
 #define	 SSB_CHIPCO_CORECTL_SE		0x00000002	/* sync clk out enable (corerev >= 3) */
@@ -385,6 +386,7 @@
 
 
 /** Chip specific Chip-Status register contents. */
+#define SSB_CHIPCO_CHST_4322_SPROM_EXISTS	0x00000040 /* SPROM present */
 #define SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL	0x00000003
 #define SSB_CHIPCO_CHST_4325_DEFCIS_SEL		0 /* OTP is powered up, use def. CIS, no SPROM */
 #define SSB_CHIPCO_CHST_4325_SPROM_SEL		1 /* OTP is powered up, SPROM is present */
@@ -398,6 +400,18 @@
 #define SSB_CHIPCO_CHST_4325_RCAL_VALUE_SHIFT	4
 #define SSB_CHIPCO_CHST_4325_PMUTOP_2B 		0x00000200 /* 1 for 2b, 0 for to 2a */
 
+/** Macros to determine SPROM presence based on Chip-Status register. */
+#define SSB_CHIPCO_CHST_4312_SPROM_PRESENT(status) \
+	((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
+		SSB_CHIPCO_CHST_4325_OTP_SEL)
+#define SSB_CHIPCO_CHST_4322_SPROM_PRESENT(status) \
+	(status & SSB_CHIPCO_CHST_4322_SPROM_EXISTS)
+#define SSB_CHIPCO_CHST_4325_SPROM_PRESENT(status) \
+	(((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
+		SSB_CHIPCO_CHST_4325_DEFCIS_SEL) && \
+	 ((status & SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL) != \
+		SSB_CHIPCO_CHST_4325_OTP_SEL))
+
 
 
 /** Clockcontrol masks and values **/
@@ -564,6 +578,7 @@
 struct ssb_chipcommon {
 	struct ssb_device *dev;
 	u32 capabilities;
+	u32 status;
 	/* Fast Powerup Delay constant */
 	u16 fast_pwrup_delay;
 	struct ssb_chipcommon_pmu pmu;
--- linux-ec2-2.6.32.orig/include/linux/ssb/ssb.h
+++ linux-ec2-2.6.32/include/linux/ssb/ssb.h
@@ -301,6 +301,7 @@
 	/* ID information about the Chip. */
 	u16 chip_id;
 	u16 chip_rev;
+	u16 sprom_offset;
 	u16 sprom_size;		/* number of words in sprom */
 	u8 chip_package;
 
@@ -390,6 +391,9 @@
 
 extern void ssb_bus_unregister(struct ssb_bus *bus);
 
+/* Does the device have an SPROM? */
+extern bool ssb_is_sprom_available(struct ssb_bus *bus);
+
 /* Set a fallback SPROM.
  * See kdoc at the function definition for complete documentation. */
 extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
--- linux-ec2-2.6.32.orig/include/linux/ssb/ssb_regs.h
+++ linux-ec2-2.6.32/include/linux/ssb/ssb_regs.h
@@ -170,7 +170,8 @@
 #define SSB_SPROMSIZE_WORDS_R4		220
 #define SSB_SPROMSIZE_BYTES_R123	(SSB_SPROMSIZE_WORDS_R123 * sizeof(u16))
 #define SSB_SPROMSIZE_BYTES_R4		(SSB_SPROMSIZE_WORDS_R4 * sizeof(u16))
-#define SSB_SPROM_BASE			0x1000
+#define SSB_SPROM_BASE1			0x1000
+#define SSB_SPROM_BASE31		0x0800
 #define SSB_SPROM_REVISION		0x107E
 #define  SSB_SPROM_REVISION_REV		0x00FF	/* SPROM Revision number */
 #define  SSB_SPROM_REVISION_CRC		0xFF00	/* SPROM CRC8 value */
--- linux-ec2-2.6.32.orig/include/linux/mfd/wm8350/pmic.h
+++ linux-ec2-2.6.32/include/linux/mfd/wm8350/pmic.h
@@ -666,20 +666,20 @@
 #define WM8350_ISINK_FLASH_DUR_64MS		(1 << 8)
 #define WM8350_ISINK_FLASH_DUR_96MS		(2 << 8)
 #define WM8350_ISINK_FLASH_DUR_1024MS		(3 << 8)
-#define WM8350_ISINK_FLASH_ON_INSTANT		(0 << 4)
-#define WM8350_ISINK_FLASH_ON_0_25S		(1 << 4)
-#define WM8350_ISINK_FLASH_ON_0_50S		(2 << 4)
-#define WM8350_ISINK_FLASH_ON_1_00S		(3 << 4)
-#define WM8350_ISINK_FLASH_ON_1_95S		(1 << 4)
-#define WM8350_ISINK_FLASH_ON_3_91S		(2 << 4)
-#define WM8350_ISINK_FLASH_ON_7_80S		(3 << 4)
-#define WM8350_ISINK_FLASH_OFF_INSTANT		(0 << 0)
-#define WM8350_ISINK_FLASH_OFF_0_25S		(1 << 0)
-#define WM8350_ISINK_FLASH_OFF_0_50S		(2 << 0)
-#define WM8350_ISINK_FLASH_OFF_1_00S		(3 << 0)
-#define WM8350_ISINK_FLASH_OFF_1_95S		(1 << 0)
-#define WM8350_ISINK_FLASH_OFF_3_91S		(2 << 0)
-#define WM8350_ISINK_FLASH_OFF_7_80S		(3 << 0)
+#define WM8350_ISINK_FLASH_ON_INSTANT		(0 << 0)
+#define WM8350_ISINK_FLASH_ON_0_25S		(1 << 0)
+#define WM8350_ISINK_FLASH_ON_0_50S		(2 << 0)
+#define WM8350_ISINK_FLASH_ON_1_00S		(3 << 0)
+#define WM8350_ISINK_FLASH_ON_1_95S		(1 << 0)
+#define WM8350_ISINK_FLASH_ON_3_91S		(2 << 0)
+#define WM8350_ISINK_FLASH_ON_7_80S		(3 << 0)
+#define WM8350_ISINK_FLASH_OFF_INSTANT		(0 << 4)
+#define WM8350_ISINK_FLASH_OFF_0_25S		(1 << 4)
+#define WM8350_ISINK_FLASH_OFF_0_50S		(2 << 4)
+#define WM8350_ISINK_FLASH_OFF_1_00S		(3 << 4)
+#define WM8350_ISINK_FLASH_OFF_1_95S		(1 << 4)
+#define WM8350_ISINK_FLASH_OFF_3_91S		(2 << 4)
+#define WM8350_ISINK_FLASH_OFF_7_80S		(3 << 4)
 
 /*
  * Regulator Interrupts.
--- linux-ec2-2.6.32.orig/include/linux/netfilter/Kbuild
+++ linux-ec2-2.6.32/include/linux/netfilter/Kbuild
@@ -38,6 +38,8 @@
 header-y += xt_pkttype.h
 header-y += xt_quota.h
 header-y += xt_rateest.h
+header-y += xt_policy.h
+header-y += xt_quota.h
 header-y += xt_realm.h
 header-y += xt_recent.h
 header-y += xt_sctp.h
--- linux-ec2-2.6.32.orig/include/linux/netfilter/xt_recent.h
+++ linux-ec2-2.6.32/include/linux/netfilter/xt_recent.h
@@ -9,6 +9,7 @@
 	XT_RECENT_UPDATE   = 1 << 2,
 	XT_RECENT_REMOVE   = 1 << 3,
 	XT_RECENT_TTL      = 1 << 4,
+	XT_RECENT_REAP     = 1 << 5,
 
 	XT_RECENT_SOURCE   = 0,
 	XT_RECENT_DEST     = 1,
@@ -16,6 +17,9 @@
 	XT_RECENT_NAME_LEN = 200,
 };
 
+/* Only allowed with --rcheck and --update */
+#define XT_RECENT_MODIFIERS (XT_RECENT_TTL|XT_RECENT_REAP)
+
 struct xt_recent_mtinfo {
 	__u32 seconds;
 	__u32 hit_count;
--- linux-ec2-2.6.32.orig/include/linux/usb/serial.h
+++ linux-ec2-2.6.32/include/linux/usb/serial.h
@@ -259,6 +259,8 @@
 	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
 	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
+	int  (*get_icount)(struct tty_struct *tty,
+			struct serial_icounter_struct *icount);
 	/* Called by the tty layer for port level work. There may or may not
 	   be an attached tty at this point */
 	void (*dtr_rts)(struct usb_serial_port *port, int on);
@@ -326,6 +328,9 @@
 					struct usb_serial_port *port,
 					unsigned int ch);
 extern int usb_serial_handle_break(struct usb_serial_port *port);
+extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
+					 struct tty_struct *tty,
+					 unsigned int status);
 
 
 extern int usb_serial_bus_register(struct usb_serial_driver *device);
--- linux-ec2-2.6.32.orig/include/linux/usb/quirks.h
+++ linux-ec2-2.6.32/include/linux/usb/quirks.h
@@ -19,4 +19,8 @@
 /* device can't handle its Configuration or Interface strings */
 #define USB_QUIRK_CONFIG_INTF_STRINGS	0x00000008
 
+/* device needs a pause during initialization, after we read the device
+   descriptor */
+#define USB_QUIRK_DELAY_INIT		0x00000040
+
 #endif /* __LINUX_USB_QUIRKS_H */
--- linux-ec2-2.6.32.orig/include/linux/decompress/mm.h
+++ linux-ec2-2.6.32/include/linux/decompress/mm.h
@@ -14,11 +14,21 @@
 
 /* Code active when included from pre-boot environment: */
 
+/*
+ * Some architectures want to ensure there is no local data in their
+ * pre-boot environment, so that data can arbitarily relocated (via
+ * GOT references).  This is achieved by defining STATIC_RW_DATA to
+ * be null.
+ */
+#ifndef STATIC_RW_DATA
+#define STATIC_RW_DATA static
+#endif
+
 /* A trivial malloc implementation, adapted from
  *  malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  */
-static unsigned long malloc_ptr;
-static int malloc_count;
+STATIC_RW_DATA unsigned long malloc_ptr;
+STATIC_RW_DATA int malloc_count;
 
 static void *malloc(int size)
 {
--- linux-ec2-2.6.32.orig/include/linux/mmc/host.h
+++ linux-ec2-2.6.32/include/linux/mmc/host.h
@@ -120,6 +120,7 @@
 	unsigned int		f_min;
 	unsigned int		f_max;
 	u32			ocr_avail;
+	struct notifier_block	pm_notify;
 
 #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
@@ -177,6 +178,7 @@
 
 	/* Only used with MMC_CAP_DISABLE */
 	int			enabled;	/* host is enabled */
+	int			rescan_disable;	/* disable card detection */
 	int			nesting_cnt;	/* "enable" nesting count */
 	int			en_dis_recurs;	/* detect recursion */
 	unsigned int		disable_delay;	/* disable delay in msecs */
@@ -249,6 +251,7 @@
 int mmc_host_enable(struct mmc_host *host);
 int mmc_host_disable(struct mmc_host *host);
 int mmc_host_lazy_disable(struct mmc_host *host);
+int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
 
 static inline void mmc_set_disable_delay(struct mmc_host *host,
 					 unsigned int disable_delay)
--- linux-ec2-2.6.32.orig/include/linux/mmc/sdio.h
+++ linux-ec2-2.6.32/include/linux/mmc/sdio.h
@@ -94,6 +94,8 @@
 
 #define  SDIO_BUS_WIDTH_1BIT	0x00
 #define  SDIO_BUS_WIDTH_4BIT	0x02
+#define  SDIO_BUS_ECSI		0x20	/* Enable continuous SPI interrupt */
+#define  SDIO_BUS_SCSI		0x40	/* Support continuous SPI interrupt */
 
 #define  SDIO_BUS_CD_DISABLE     0x80	/* disable pull-up on DAT3 (pin 1) */
 
--- linux-ec2-2.6.32.orig/include/xen/compat_ioctl.h
+++ linux-ec2-2.6.32/include/xen/compat_ioctl.h
@@ -0,0 +1,45 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Jimi Xenidis <jimix@watson.ibm.com>
+ *          Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __LINUX_XEN_COMPAT_H__ 
+#define __LINUX_XEN_COMPAT_H__ 
+
+#include <linux/compat.h>
+
+extern int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg);
+struct privcmd_mmap_32 {
+	int num;
+	domid_t dom;
+	compat_uptr_t entry;
+};
+
+struct privcmd_mmapbatch_32 {
+	int num;     /* number of pages to populate */
+	domid_t dom; /* target domain */
+	__u64 addr;  /* virtual address */
+	compat_uptr_t arr; /* array of mfns - top nibble set on err */
+};
+#define IOCTL_PRIVCMD_MMAP_32                   \
+	_IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap_32))
+#define IOCTL_PRIVCMD_MMAPBATCH_32                  \
+	_IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch_32))
+
+#endif /* __LINUX_XEN_COMPAT_H__ */
--- linux-ec2-2.6.32.orig/include/xen/pcifront.h
+++ linux-ec2-2.6.32/include/xen/pcifront.h
@@ -0,0 +1,69 @@
+/*
+ * PCI Frontend - arch-dependendent declarations
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#ifndef __XEN_ASM_PCIFRONT_H__
+#define __XEN_ASM_PCIFRONT_H__
+
+#include <linux/spinlock.h>
+
+#ifdef __KERNEL__
+
+#ifndef __ia64__
+
+#include <asm/pci.h>
+
+struct pcifront_device;
+struct pci_bus;
+#define pcifront_sd pci_sysdata
+
+static inline struct pcifront_device *
+pcifront_get_pdev(struct pcifront_sd *sd)
+{
+	return sd->pdev;
+}
+
+static inline void pcifront_init_sd(struct pcifront_sd *sd,
+				    unsigned int domain, unsigned int bus,
+				    struct pcifront_device *pdev)
+{
+	sd->domain = domain;
+	sd->pdev = pdev;
+}
+
+static inline void pcifront_setup_root_resources(struct pci_bus *bus,
+						 struct pcifront_sd *sd)
+{
+}
+
+#else /* __ia64__ */
+
+#include <linux/acpi.h>
+#include <asm/pci.h>
+#define pcifront_sd pci_controller
+
+extern void xen_add_resource(struct pci_controller *, unsigned int,
+			     unsigned int, struct acpi_resource *);
+extern void xen_pcibios_setup_root_windows(struct pci_bus *,
+					   struct pci_controller *);
+
+static inline struct pcifront_device *
+pcifront_get_pdev(struct pcifront_sd *sd)
+{
+	return (struct pcifront_device *)sd->platform_data;
+}
+
+static inline void pcifront_setup_root_resources(struct pci_bus *bus,
+						 struct pcifront_sd *sd)
+{
+	xen_pcibios_setup_root_windows(bus, sd);
+}
+
+#endif /* __ia64__ */
+
+extern struct rw_semaphore pci_bus_sem;
+
+#endif /* __KERNEL__ */
+
+#endif /* __XEN_ASM_PCIFRONT_H__ */
--- linux-ec2-2.6.32.orig/include/xen/blkif.h
+++ linux-ec2-2.6.32/include/xen/blkif.h
@@ -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__
+
+#include <xen/interface/io/ring.h>
+#include <xen/interface/io/blkif.h>
+#include <xen/interface/io/protocols.h>
+
+/* Not a real protocol.  Used to generate ring structs which contain
+ * the elements common to all protocols only.  This way we get a
+ * compiler-checkable way to use common struct elements, so we can
+ * avoid using switch(protocol) in a number of places.  */
+struct blkif_common_request {
+	char dummy;
+};
+struct blkif_common_response {
+	char dummy;
+};
+
+/* i386 protocol version */
+#pragma pack(push, 4)
+struct blkif_x86_32_request {
+	uint8_t        operation;    /* BLKIF_OP_???                         */
+	uint8_t        nr_segments;  /* number of segments                   */
+	blkif_vdev_t   handle;       /* only for read/write requests         */
+	uint64_t       id;           /* private guest value, echoed in resp  */
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+struct blkif_x86_32_response {
+	uint64_t        id;              /* copied from request */
+	uint8_t         operation;       /* copied from request */
+	int16_t         status;          /* BLKIF_RSP_???       */
+};
+typedef struct blkif_x86_32_request blkif_x86_32_request_t;
+typedef struct blkif_x86_32_response blkif_x86_32_response_t;
+#pragma pack(pop)
+
+/* x86_64 protocol version */
+struct blkif_x86_64_request {
+	uint8_t        operation;    /* BLKIF_OP_???                         */
+	uint8_t        nr_segments;  /* number of segments                   */
+	blkif_vdev_t   handle;       /* only for read/write requests         */
+	uint64_t       __attribute__((__aligned__(8))) id;
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+struct blkif_x86_64_response {
+	uint64_t       __attribute__((__aligned__(8))) id;
+	uint8_t         operation;       /* copied from request */
+	int16_t         status;          /* BLKIF_RSP_???       */
+};
+typedef struct blkif_x86_64_request blkif_x86_64_request_t;
+typedef struct blkif_x86_64_response blkif_x86_64_response_t;
+
+DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
+DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
+DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
+
+union blkif_back_rings {
+	blkif_back_ring_t        native;
+	blkif_common_back_ring_t common;
+	blkif_x86_32_back_ring_t x86_32;
+	blkif_x86_64_back_ring_t x86_64;
+};
+typedef union blkif_back_rings blkif_back_rings_t;
+
+enum blkif_protocol {
+	BLKIF_PROTOCOL_NATIVE = 1,
+	BLKIF_PROTOCOL_X86_32 = 2,
+	BLKIF_PROTOCOL_X86_64 = 3,
+};
+
+static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
+{
+	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+	dst->operation = src->operation;
+	dst->nr_segments = src->nr_segments;
+	dst->handle = src->handle;
+	dst->id = src->id;
+	dst->sector_number = src->sector_number;
+	barrier();
+	if (n > dst->nr_segments)
+		n = dst->nr_segments;
+	for (i = 0; i < n; i++)
+		dst->seg[i] = src->seg[i];
+}
+
+static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
+{
+	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+	dst->operation = src->operation;
+	dst->nr_segments = src->nr_segments;
+	dst->handle = src->handle;
+	dst->id = src->id;
+	dst->sector_number = src->sector_number;
+	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__ */
--- linux-ec2-2.6.32.orig/include/xen/gnttab.h
+++ linux-ec2-2.6.32/include/xen/gnttab.h
@@ -0,0 +1,165 @@
+/******************************************************************************
+ * gnttab.h
+ * 
+ * Two sets of functionality:
+ * 1. Granting foreign access to our memory reservation.
+ * 2. Accessing others' memory reservations via grant references.
+ * (i.e., mechanisms for both sender and recipient of grant references)
+ * 
+ * Copyright (c) 2004-2005, K A Fraser
+ * Copyright (c) 2005, Christopher Clark
+ * 
+ * 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 __ASM_GNTTAB_H__
+#define __ASM_GNTTAB_H__
+
+#include <asm/hypervisor.h>
+#include <asm/maddr.h> /* maddr_t */
+#include <linux/mm.h>
+#include <xen/interface/grant_table.h>
+#include <xen/features.h>
+
+struct gnttab_free_callback {
+	struct gnttab_free_callback *next;
+	void (*fn)(void *);
+	void *arg;
+	u16 count;
+	u8 queued;
+};
+
+int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
+				int flags);
+
+/*
+ * End access through the given grant reference, iff the grant entry is no
+ * longer in use.  Return 1 if the grant entry was freed, 0 if it is still in
+ * use.
+ */
+int gnttab_end_foreign_access_ref(grant_ref_t ref);
+
+/*
+ * Eventually end access through the given grant reference, and once that
+ * access has been ended, free the given page too.  Access will be ended
+ * immediately iff the grant entry is not in use, otherwise it will happen
+ * some time later.  page may be 0, in which case no freeing will occur.
+ */
+void gnttab_end_foreign_access(grant_ref_t ref, unsigned long page);
+
+int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
+
+unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
+unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
+
+int gnttab_query_foreign_access(grant_ref_t ref);
+
+/*
+ * operations on reserved batches of grant references
+ */
+int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head);
+
+void gnttab_free_grant_reference(grant_ref_t ref);
+
+void gnttab_free_grant_references(grant_ref_t head);
+
+int gnttab_empty_grant_references(const grant_ref_t *pprivate_head);
+
+int gnttab_claim_grant_reference(grant_ref_t *pprivate_head);
+
+void gnttab_release_grant_reference(grant_ref_t *private_head,
+				    grant_ref_t release);
+
+void gnttab_request_free_callback(struct gnttab_free_callback *callback,
+				  void (*fn)(void *), void *arg, u16 count);
+void gnttab_cancel_free_callback(struct gnttab_free_callback *callback);
+
+void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+				     unsigned long frame, int flags);
+
+void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+				       unsigned long pfn);
+
+int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep);
+void __gnttab_dma_map_page(struct page *page);
+static inline void __gnttab_dma_unmap_page(struct page *page)
+{
+}
+
+void gnttab_reset_grant_page(struct page *page);
+
+#ifndef CONFIG_XEN
+int gnttab_resume(void);
+#endif
+
+void *arch_gnttab_alloc_shared(unsigned long *frames);
+
+static inline void
+gnttab_set_map_op(struct gnttab_map_grant_ref *map, maddr_t addr,
+		  uint32_t flags, grant_ref_t ref, domid_t domid)
+{
+	if (flags & GNTMAP_contains_pte)
+		map->host_addr = addr;
+	else if (xen_feature(XENFEAT_auto_translated_physmap))
+		map->host_addr = __pa(addr);
+	else
+		map->host_addr = addr;
+
+	map->flags = flags;
+	map->ref = ref;
+	map->dom = domid;
+}
+
+static inline void
+gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, maddr_t addr,
+		    uint32_t flags, grant_handle_t handle)
+{
+	if (flags & GNTMAP_contains_pte)
+		unmap->host_addr = addr;
+	else if (xen_feature(XENFEAT_auto_translated_physmap))
+		unmap->host_addr = __pa(addr);
+	else
+		unmap->host_addr = addr;
+
+	unmap->handle = handle;
+	unmap->dev_bus_addr = 0;
+}
+
+static inline void
+gnttab_set_replace_op(struct gnttab_unmap_and_replace *unmap, maddr_t addr,
+		      maddr_t new_addr, grant_handle_t handle)
+{
+	if (xen_feature(XENFEAT_auto_translated_physmap)) {
+		unmap->host_addr = __pa(addr);
+		unmap->new_addr = __pa(new_addr);
+	} else {
+		unmap->host_addr = addr;
+		unmap->new_addr = new_addr;
+	}
+
+	unmap->handle = handle;
+}
+
+#endif /* __ASM_GNTTAB_H__ */
--- linux-ec2-2.6.32.orig/include/xen/driver_util.h
+++ linux-ec2-2.6.32/include/xen/driver_util.h
@@ -0,0 +1,10 @@
+
+#ifndef __ASM_XEN_DRIVER_UTIL_H__
+#define __ASM_XEN_DRIVER_UTIL_H__
+
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+
+extern struct class *get_xen_class(void);
+
+#endif /* __ASM_XEN_DRIVER_UTIL_H__ */
--- linux-ec2-2.6.32.orig/include/xen/evtchn.h
+++ linux-ec2-2.6.32/include/xen/evtchn.h
@@ -1,7 +1,8 @@
 /******************************************************************************
  * evtchn.h
  *
- * Interface to /dev/xen/evtchn.
+ * Communication via Xen event channels.
+ * Also definitions for the device that demuxes notifications to userspace.
  *
  * Copyright (c) 2003-2005, K A Fraser
  *
@@ -30,6 +31,207 @@
  * IN THE SOFTWARE.
  */
 
+#if !defined(__ASM_EVTCHN_H__) && defined(__KERNEL__) && !defined(CONFIG_PARAVIRT_XEN)
+#define __ASM_EVTCHN_H__
+
+#include <linux/interrupt.h>
+#include <asm/hypervisor.h>
+#include <asm/ptrace.h>
+#include <asm/synch_bitops.h>
+#include <xen/interface/event_channel.h>
+#include <linux/smp.h>
+
+/*
+ * LOW-LEVEL DEFINITIONS
+ */
+struct irq_cfg {
+	u32 info;
+	union {
+		int bindcount; /* for dynamic IRQs */
+#ifdef CONFIG_X86_IO_APIC
+		u8 vector; /* for physical IRQs */
+#endif
+	};
+};
+
+int assign_irq_vector(int irq, struct irq_cfg *, const struct cpumask *);
+
+/*
+ * Dynamically bind an event source to an IRQ-like callback handler.
+ * On some platforms this may not be implemented via the Linux IRQ subsystem.
+ * The IRQ argument passed to the callback handler is the same as returned
+ * from the bind call. It may not correspond to a Linux IRQ number.
+ * Returns IRQ or negative errno.
+ */
+int bind_caller_port_to_irqhandler(
+	unsigned int caller_port,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id);
+int bind_listening_port_to_irqhandler(
+	unsigned int remote_domain,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id);
+int bind_interdomain_evtchn_to_irqhandler(
+	unsigned int remote_domain,
+	unsigned int remote_port,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id);
+int bind_virq_to_irqhandler(
+	unsigned int virq,
+	unsigned int cpu,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id);
+#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86)
+int bind_virq_to_irqaction(
+	unsigned int virq,
+	unsigned int cpu,
+	struct irqaction *action);
+#else
+#define bind_virq_to_irqaction(virq, cpu, action) \
+	bind_virq_to_irqhandler(virq, cpu, (action)->handler, \
+			 	(action)->flags | IRQF_NOBALANCING, \
+				(action)->name, action)
+#endif
+#if defined(CONFIG_SMP) && !defined(MODULE)
+#ifndef CONFIG_X86
+int bind_ipi_to_irqhandler(
+	unsigned int ipi,
+	unsigned int cpu,
+	irq_handler_t handler,
+	unsigned long irqflags,
+	const char *devname,
+	void *dev_id);
+#else
+int bind_ipi_to_irqaction(
+	unsigned int ipi,
+	unsigned int cpu,
+	struct irqaction *action);
+#endif
+#endif
+
+/*
+ * Common unbind function for all event sources. Takes IRQ to unbind from.
+ * Automatically closes the underlying event channel (except for bindings
+ * made with bind_caller_port_to_irqhandler()).
+ */
+void unbind_from_irqhandler(unsigned int irq, void *dev_id);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86)
+/* Specialized unbind function for per-CPU IRQs. */
+void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu,
+			     struct irqaction *);
+#else
+#define unbind_from_per_cpu_irq(irq, cpu, action) \
+	unbind_from_irqhandler(irq, action)
+#endif
+
+#ifndef CONFIG_XEN
+void irq_resume(void);
+#endif
+
+/* Entry point for notifications into Linux subsystems. */
+asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
+
+/* Entry point for notifications into the userland character device. */
+void evtchn_device_upcall(int port);
+
+/* Mark a PIRQ as unavailable for dynamic allocation. */
+void evtchn_register_pirq(int irq);
+/* Map a Xen-supplied PIRQ to a dynamically allocated one. */
+int evtchn_map_pirq(int irq, int xen_pirq);
+/* Look up a Xen-supplied PIRQ for a dynamically allocated one. */
+int evtchn_get_xen_pirq(int irq);
+
+void mask_evtchn(int port);
+void disable_all_local_evtchn(void);
+void unmask_evtchn(int port);
+
+#ifdef CONFIG_SMP
+void rebind_evtchn_to_cpu(int port, unsigned int cpu);
+#else
+#define rebind_evtchn_to_cpu(port, cpu)	((void)0)
+#endif
+
+static inline int test_and_set_evtchn_mask(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	return synch_test_and_set_bit(port, s->evtchn_mask);
+}
+
+static inline void clear_evtchn(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	synch_clear_bit(port, s->evtchn_pending);
+}
+
+static inline void set_evtchn(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	synch_set_bit(port, s->evtchn_pending);
+}
+
+static inline int test_evtchn(int port)
+{
+	shared_info_t *s = HYPERVISOR_shared_info;
+	return synch_test_bit(port, s->evtchn_pending);
+}
+
+static inline void notify_remote_via_evtchn(int port)
+{
+	struct evtchn_send send = { .port = port };
+	VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send));
+}
+
+static inline void
+multi_notify_remote_via_evtchn(multicall_entry_t *mcl, int port)
+{
+	struct evtchn_send *send = (void *)(mcl->args + 2);
+
+	BUILD_BUG_ON(sizeof(*send) > sizeof(mcl->args) - 2 * sizeof(*mcl->args));
+	send->port = port;
+	mcl->op = __HYPERVISOR_event_channel_op;
+	mcl->args[0] = EVTCHNOP_send;
+	mcl->args[1] = (unsigned long)send;
+}
+
+/* Clear an irq's pending state, in preparation for polling on it. */
+void xen_clear_irq_pending(int irq);
+
+/* Set an irq's pending state, to avoid blocking on it. */
+void xen_set_irq_pending(int irq);
+
+/* Test an irq's pending state. */
+int xen_test_irq_pending(int irq);
+
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq);
+
+/*
+ * Use these to access the event channel underlying the IRQ handle returned
+ * by bind_*_to_irqhandler().
+ */
+void notify_remote_via_irq(int irq);
+int multi_notify_remote_via_irq(multicall_entry_t *, int irq);
+int irq_to_evtchn_port(int irq);
+
+#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86)
+void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu);
+#endif
+
+#endif /* __ASM_EVTCHN_H__ */
+
+/*
+ * Interface to /dev/xen/evtchn.
+ */
 #ifndef __LINUX_PUBLIC_EVTCHN_H__
 #define __LINUX_PUBLIC_EVTCHN_H__
 
--- linux-ec2-2.6.32.orig/include/xen/firmware.h
+++ linux-ec2-2.6.32/include/xen/firmware.h
@@ -0,0 +1,14 @@
+#ifndef __XEN_FIRMWARE_H__
+#define __XEN_FIRMWARE_H__
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+void copy_edd(void);
+#endif
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+void copy_edid(void);
+#else
+static inline void copy_edid(void) {}
+#endif
+
+#endif /* __XEN_FIRMWARE_H__ */
--- linux-ec2-2.6.32.orig/include/xen/hvm.h
+++ linux-ec2-2.6.32/include/xen/hvm.h
@@ -0,0 +1,23 @@
+/* Simple wrappers around HVM functions */
+#ifndef XEN_HVM_H__
+#define XEN_HVM_H__
+
+#include <xen/interface/hvm/params.h>
+
+static inline unsigned long hvm_get_parameter(int idx)
+{
+	struct xen_hvm_param xhv;
+	int r;
+
+	xhv.domid = DOMID_SELF;
+	xhv.index = idx;
+	r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+	if (r < 0) {
+		printk(KERN_ERR "cannot get hvm parameter %d: %d.\n",
+		       idx, r);
+		return 0;
+	}
+	return xhv.value;
+}
+
+#endif /* XEN_HVM_H__ */
--- linux-ec2-2.6.32.orig/include/xen/xencons.h
+++ linux-ec2-2.6.32/include/xen/xencons.h
@@ -0,0 +1,19 @@
+#ifndef __ASM_XENCONS_H__
+#define __ASM_XENCONS_H__
+
+struct dom0_vga_console_info;
+void dom0_init_screen_info(const struct dom0_vga_console_info *, size_t);
+
+void xencons_force_flush(void);
+void xencons_resume(void);
+
+/* Interrupt work hooks. Receive data, or kick data out. */
+void xencons_rx(char *buf, unsigned len);
+void xencons_tx(void);
+
+int xencons_ring_init(void);
+int xencons_ring_send(const char *data, unsigned len);
+
+void xencons_early_setup(void);
+
+#endif /* __ASM_XENCONS_H__ */
--- linux-ec2-2.6.32.orig/include/xen/hypervisor_sysfs.h
+++ linux-ec2-2.6.32/include/xen/hypervisor_sysfs.h
@@ -0,0 +1,30 @@
+/*
+ *  copyright (c) 2006 IBM Corporation
+ *  Authored by: Mike D. Day <ncmike@us.ibm.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.
+ */
+
+#ifndef _HYP_SYSFS_H_
+#define _HYP_SYSFS_H_
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+#define HYPERVISOR_ATTR_RO(_name) \
+static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
+
+#define HYPERVISOR_ATTR_RW(_name) \
+static struct hyp_sysfs_attr _name##_attr = \
+	__ATTR(_name, 0644, _name##_show, _name##_store)
+
+struct hyp_sysfs_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct hyp_sysfs_attr *, char *);
+	ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
+	void *hyp_attr_data;
+};
+
+#endif /* _HYP_SYSFS_H_ */
--- linux-ec2-2.6.32.orig/include/xen/xen_proc.h
+++ linux-ec2-2.6.32/include/xen/xen_proc.h
@@ -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__ */
--- linux-ec2-2.6.32.orig/include/xen/xenbus.h
+++ linux-ec2-2.6.32/include/xen/xenbus.h
@@ -39,6 +39,7 @@
 #include <linux/mutex.h>
 #include <linux/completion.h>
 #include <linux/init.h>
+#include <linux/err.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/grant_table.h>
 #include <xen/interface/io/xenbus.h>
@@ -55,8 +56,21 @@
 	/* Callback (executed in a process context with no locks held). */
 	void (*callback)(struct xenbus_watch *,
 			 const char **vec, unsigned int len);
+
+#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+	/* See XBWF_ definitions below. */
+	unsigned long flags;
+#endif
 };
 
+#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+/*
+ * Execute callback in its own kthread. Useful if the callback is long
+ * running or heavily serialised, to avoid taking out the main xenwatch thread
+ * for a long period of time (or even unwittingly causing a deadlock).
+ */
+#define XBWF_new_thread	1
+#endif
 
 /* A xenbus device. */
 struct xenbus_device {
@@ -83,17 +97,21 @@
 
 /* A xenbus driver. */
 struct xenbus_driver {
-	char *name;
-	struct module *owner;
+	const char *name;
 	const struct xenbus_device_id *ids;
 	int (*probe)(struct xenbus_device *dev,
 		     const struct xenbus_device_id *id);
 	void (*otherend_changed)(struct xenbus_device *dev,
 				 enum xenbus_state backend_state);
 	int (*remove)(struct xenbus_device *dev);
+#if !defined(CONFIG_XEN) && !defined(MODULE)
 	int (*suspend)(struct xenbus_device *dev, pm_message_t state);
+#else
+	int (*suspend)(struct xenbus_device *dev);
+	int (*suspend_cancel)(struct xenbus_device *dev);
+#endif
 	int (*resume)(struct xenbus_device *dev);
-	int (*uevent)(struct xenbus_device *, char **, int, char *, int);
+	int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
 	struct device_driver driver;
 	int (*read_otherend_details)(struct xenbus_device *dev);
 	int (*is_ready)(struct xenbus_device *dev);
@@ -111,7 +129,6 @@
 static inline int __must_check
 xenbus_register_frontend(struct xenbus_driver *drv)
 {
-	WARN_ON(drv->owner != THIS_MODULE);
 	return __xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME);
 }
 
@@ -121,7 +138,6 @@
 static inline int __must_check
 xenbus_register_backend(struct xenbus_driver *drv)
 {
-	WARN_ON(drv->owner != THIS_MODULE);
 	return __xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME);
 }
 
@@ -164,7 +180,6 @@
 int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
 
 /* notifer routines for when the xenstore comes up */
-extern int xenstored_ready;
 int register_xenstore_notifier(struct notifier_block *nb);
 void unregister_xenstore_notifier(struct notifier_block *nb);
 
@@ -177,12 +192,9 @@
 /* Used by xenbus_dev to borrow kernel's store connection. */
 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
 
-struct work_struct;
-
 /* Prepare for domain suspend: then resume or cancel the suspend. */
 void xenbus_suspend(void);
 void xenbus_resume(void);
-void xenbus_probe(struct work_struct *);
 void xenbus_suspend_cancel(void);
 
 #define XENBUS_IS_ERR_READ(str) ({			\
@@ -195,38 +207,134 @@
 
 #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
 
+
+/**
+ * Register a watch on the given path, using the given xenbus_watch structure
+ * for storage, and the given callback function as the callback.  Return 0 on
+ * success, or -errno on error.  On success, the given path will be saved as
+ * watch->node, and remains the caller's to free.  On error, watch->node will
+ * be NULL, the device will switch to XenbusStateClosing, and the error will
+ * be saved in the store.
+ */
 int xenbus_watch_path(struct xenbus_device *dev, const char *path,
 		      struct xenbus_watch *watch,
 		      void (*callback)(struct xenbus_watch *,
 				       const char **, unsigned int));
+
+
+#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+/**
+ * Register a watch on the given path/path2, using the given xenbus_watch
+ * structure for storage, and the given callback function as the callback.
+ * Return 0 on success, or -errno on error.  On success, the watched path
+ * (path/path2) will be saved as watch->node, and becomes the caller's to
+ * kfree().  On error, watch->node will be NULL, so the caller has nothing to
+ * free, the device will switch to XenbusStateClosing, and the error will be
+ * saved in the store.
+ */
+int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+		       const char *path2, struct xenbus_watch *watch,
+		       void (*callback)(struct xenbus_watch *,
+					const char **, unsigned int));
+#else
 int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
 			 void (*callback)(struct xenbus_watch *,
 					  const char **, unsigned int),
 			 const char *pathfmt, ...)
 	__attribute__ ((format (printf, 4, 5)));
+#endif
 
+/**
+ * Advertise in the store a change of the given driver to the given new_state.
+ * Return 0 on success, or -errno on error.  On error, the device will switch
+ * to XenbusStateClosing, and the error will be saved in the store.
+ */
 int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state new_state);
+
+
+/**
+ * Grant access to the given ring_mfn to the peer of the given device.  Return
+ * 0 on success, or -errno on error.  On error, the device will switch to
+ * XenbusStateClosing, and the error will be saved in the store.
+ */
 int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn);
-int xenbus_map_ring_valloc(struct xenbus_device *dev,
-			   int gnt_ref, void **vaddr);
+
+
+/**
+ * Map a page of memory into this domain from another domain's grant table.
+ * xenbus_map_ring_valloc allocates a page of virtual address space, maps the
+ * page to that address, and sets *vaddr to that address.
+ * xenbus_map_ring does not allocate the virtual address space (you must do
+ * this yourself!). It only maps in the page to the specified address.
+ * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h)
+ * or -ENOMEM on error. If an error is returned, device will switch to
+ * XenbusStateClosing and the error message will be saved in XenStore.
+ */
+struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev,
+					 int gnt_ref);
 int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
 			   grant_handle_t *handle, void *vaddr);
 
-int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
+
+/**
+ * Unmap a page of memory in this domain that was imported from another domain.
+ * Use xenbus_unmap_ring_vfree if you mapped in your memory with
+ * xenbus_map_ring_valloc (it will free the virtual address space).
+ * Returns 0 on success and returns GNTST_* on error
+ * (see xen/include/interface/grant_table.h).
+ */
+int xenbus_unmap_ring_vfree(struct xenbus_device *dev, struct vm_struct *);
 int xenbus_unmap_ring(struct xenbus_device *dev,
 		      grant_handle_t handle, void *vaddr);
 
+
+/**
+ * Allocate an event channel for the given xenbus_device, assigning the newly
+ * created local port to *port.  Return 0 on success, or -errno on error.  On
+ * error, the device will switch to XenbusStateClosing, and the error will be
+ * saved in the store.
+ */
 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
-int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port);
+
+
+/**
+ * Free an existing event channel. Returns 0 on success or -errno on error.
+ */
 int xenbus_free_evtchn(struct xenbus_device *dev, int port);
 
+
+/**
+ * Return the state of the driver rooted at the given store path, or
+ * XenbusStateUnknown if no state can be read.
+ */
 enum xenbus_state xenbus_read_driver_state(const char *path);
 
-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...);
+
+/***
+ * Report the given negative errno into the store, along with the given
+ * formatted message.
+ */
+void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
+		      ...);
+
+
+/***
+ * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
+ * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
+ * closedown of this driver and its peer.
+ */
+void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+		      ...);
+
+#if defined(CONFIG_XEN) || defined(MODULE)
+int xenbus_dev_init(void);
+#endif
 
 const char *xenbus_strstate(enum xenbus_state state);
 int xenbus_dev_is_online(struct xenbus_device *dev);
 int xenbus_frontend_closed(struct xenbus_device *dev);
 
+int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *));
+int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *));
+
 #endif /* _XEN_XENBUS_H */
--- linux-ec2-2.6.32.orig/include/xen/hypercall.h
+++ linux-ec2-2.6.32/include/xen/hypercall.h
@@ -0,0 +1,30 @@
+#ifndef __XEN_HYPERCALL_H__
+#define __XEN_HYPERCALL_H__
+
+#include <asm/hypercall.h>
+
+static inline int __must_check
+HYPERVISOR_multicall_check(
+	multicall_entry_t *call_list, unsigned int nr_calls,
+	const unsigned long *rc_list)
+{
+	int rc = HYPERVISOR_multicall(call_list, nr_calls);
+
+	if (unlikely(rc < 0))
+		return rc;
+	BUG_ON(rc);
+	BUG_ON((int)nr_calls < 0);
+
+	for ( ; nr_calls > 0; --nr_calls, ++call_list)
+		if (unlikely(call_list->result != (rc_list ? *rc_list++ : 0)))
+			return nr_calls;
+
+	return 0;
+}
+
+/* A construct to ignore the return value of hypercall wrappers in a few
+ * exceptional cases (simply casting the function result to void doesn't
+ * avoid the compiler warning): */
+#define VOID(expr) ((void)((expr)?:0))
+
+#endif /* __XEN_HYPERCALL_H__ */
--- linux-ec2-2.6.32.orig/include/xen/cpu_hotplug.h
+++ linux-ec2-2.6.32/include/xen/cpu_hotplug.h
@@ -0,0 +1,39 @@
+#ifndef __XEN_CPU_HOTPLUG_H__
+#define __XEN_CPU_HOTPLUG_H__
+
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+
+#if defined(CONFIG_X86) && defined(CONFIG_SMP)
+extern cpumask_var_t vcpu_initialized_mask;
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU)
+
+int cpu_up_check(unsigned int cpu);
+void init_xenbus_allowed_cpumask(void);
+int smp_suspend(void);
+void smp_resume(void);
+
+#else /* !defined(CONFIG_HOTPLUG_CPU) */
+
+#define cpu_up_check(cpu)		(0)
+#define init_xenbus_allowed_cpumask()	((void)0)
+
+static inline int smp_suspend(void)
+{
+	if (num_online_cpus() > 1) {
+		printk(KERN_WARNING "Can't suspend SMP guests "
+		       "without CONFIG_HOTPLUG_CPU\n");
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
+static inline void smp_resume(void)
+{
+}
+
+#endif /* !defined(CONFIG_HOTPLUG_CPU) */
+
+#endif /* __XEN_CPU_HOTPLUG_H__ */
--- linux-ec2-2.6.32.orig/include/xen/balloon.h
+++ linux-ec2-2.6.32/include/xen/balloon.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ * balloon.h
+ *
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * 
+ * 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_BALLOON_H__
+#define __XEN_BALLOON_H__
+
+#include <linux/spinlock.h>
+
+#if !defined(CONFIG_PARAVIRT_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+/*
+ * Inform the balloon driver that it should allow some slop for device-driver
+ * memory activities.
+ */
+void balloon_update_driver_allowance(long delta);
+
+/* Allocate/free a set of empty pages in low memory (i.e., no RAM mapped). */
+struct page **alloc_empty_pages_and_pagevec(int nr_pages);
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages);
+
+/* Free an empty page range (not allocated through
+   alloc_empty_pages_and_pagevec), adding to the balloon. */
+void free_empty_pages(struct page **pagevec, int nr_pages);
+
+void balloon_release_driver_page(struct page *page);
+
+/*
+ * Prevent the balloon driver from changing the memory reservation during
+ * a driver critical region.
+ */
+extern spinlock_t balloon_lock;
+#define balloon_lock(__flags)   spin_lock_irqsave(&balloon_lock, __flags)
+#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags)
+#endif
+
+#endif /* __XEN_BALLOON_H__ */
--- linux-ec2-2.6.32.orig/include/xen/features.h
+++ linux-ec2-2.6.32/include/xen/features.h
@@ -10,6 +10,7 @@
 #define __XEN_FEATURES_H__
 
 #include <xen/interface/features.h>
+#include <xen/interface/version.h>
 
 void xen_setup_features(void);
 
@@ -20,4 +21,4 @@
 	return xen_features[flag];
 }
 
-#endif /* __ASM_XEN_FEATURES_H__ */
+#endif /* __XEN_FEATURES_H__ */
--- linux-ec2-2.6.32.orig/include/xen/xenoprof.h
+++ linux-ec2-2.6.32/include/xen/xenoprof.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ * xen/xenoprof.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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_XENOPROF_H__
+#define __XEN_XENOPROF_H__
+#ifdef CONFIG_XEN
+
+#include <asm/xenoprof.h>
+
+struct oprofile_operations;
+int xenoprofile_init(struct oprofile_operations * ops);
+void xenoprofile_exit(void);
+
+struct xenoprof_shared_buffer {
+	char					*buffer;
+	struct xenoprof_arch_shared_buffer	arch;
+};
+#else
+#define xenoprofile_init(ops)	(-ENOSYS)
+#define xenoprofile_exit()	do { } while (0)
+
+#endif /* CONFIG_XEN */
+#endif /* __XEN_XENOPROF_H__ */
--- linux-ec2-2.6.32.orig/include/xen/sysctl.h
+++ linux-ec2-2.6.32/include/xen/sysctl.h
@@ -0,0 +1,11 @@
+#ifndef _XEN_SYSCTL_H
+#define _XEN_SYSCTL_H
+
+/* CTL_XEN names: */
+enum
+{
+	CTL_XEN_INDEPENDENT_WALLCLOCK=1,
+	CTL_XEN_PERMITTED_CLOCK_JITTER=2,
+};
+
+#endif /* _XEN_SYSCTL_H */
--- linux-ec2-2.6.32.orig/include/xen/public/gntdev.h
+++ linux-ec2-2.6.32/include/xen/public/gntdev.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * gntdev.h
+ * 
+ * Interface to /dev/xen/gntdev.
+ * 
+ * Copyright (c) 2007, D G Murray
+ * 
+ * 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 __LINUX_PUBLIC_GNTDEV_H__
+#define __LINUX_PUBLIC_GNTDEV_H__
+
+struct ioctl_gntdev_grant_ref {
+	/* The domain ID of the grant to be mapped. */
+	uint32_t domid;
+	/* The grant reference of the grant to be mapped. */
+	uint32_t ref;
+};
+
+/*
+ * Inserts the grant references into the mapping table of an instance
+ * of gntdev. N.B. This does not perform the mapping, which is deferred
+ * until mmap() is called with @index as the offset.
+ */
+#define IOCTL_GNTDEV_MAP_GRANT_REF \
+_IOC(_IOC_NONE, 'G', 0, sizeof(struct ioctl_gntdev_map_grant_ref))
+struct ioctl_gntdev_map_grant_ref {
+	/* IN parameters */
+	/* The number of grants to be mapped. */
+	uint32_t count;
+	uint32_t pad;
+	/* OUT parameters */
+	/* The offset to be used on a subsequent call to mmap(). */
+	uint64_t index;
+	/* Variable IN parameter. */
+	/* Array of grant references, of size @count. */
+	struct ioctl_gntdev_grant_ref refs[1];
+};
+
+/*
+ * Removes the grant references from the mapping table of an instance of
+ * of gntdev. N.B. munmap() must be called on the relevant virtual address(es)
+ * before this ioctl is called, or an error will result.
+ */
+#define IOCTL_GNTDEV_UNMAP_GRANT_REF \
+_IOC(_IOC_NONE, 'G', 1, sizeof(struct ioctl_gntdev_unmap_grant_ref))       
+struct ioctl_gntdev_unmap_grant_ref {
+	/* IN parameters */
+	/* The offset was returned by the corresponding map operation. */
+	uint64_t index;
+	/* The number of pages to be unmapped. */
+	uint32_t count;
+	uint32_t pad;
+};
+
+/*
+ * Returns the offset in the driver's address space that corresponds
+ * to @vaddr. This can be used to perform a munmap(), followed by an
+ * UNMAP_GRANT_REF ioctl, where no state about the offset is retained by
+ * the caller. The number of pages that were allocated at the same time as
+ * @vaddr is returned in @count.
+ *
+ * N.B. Where more than one page has been mapped into a contiguous range, the
+ *      supplied @vaddr must correspond to the start of the range; otherwise
+ *      an error will result. It is only possible to munmap() the entire
+ *      contiguously-allocated range at once, and not any subrange thereof.
+ */
+#define IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR \
+_IOC(_IOC_NONE, 'G', 2, sizeof(struct ioctl_gntdev_get_offset_for_vaddr))
+struct ioctl_gntdev_get_offset_for_vaddr {
+	/* IN parameters */
+	/* The virtual address of the first mapped page in a range. */
+	uint64_t vaddr;
+	/* OUT parameters */
+	/* The offset that was used in the initial mmap() operation. */
+	uint64_t offset;
+	/* The number of pages mapped in the VM area that begins at @vaddr. */
+	uint32_t count;
+	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__ */
--- linux-ec2-2.6.32.orig/include/xen/public/evtchn.h
+++ linux-ec2-2.6.32/include/xen/public/evtchn.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * evtchn.h
+ * 
+ * Interface to /dev/xen/evtchn.
+ * 
+ * Copyright (c) 2003-2005, K A Fraser
+ * 
+ * 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 __LINUX_PUBLIC_EVTCHN_H__
+#define __LINUX_PUBLIC_EVTCHN_H__
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ				\
+	_IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
+struct ioctl_evtchn_bind_virq {
+	unsigned int virq;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN			\
+	_IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
+struct ioctl_evtchn_bind_interdomain {
+	unsigned int remote_domain, remote_port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT			\
+	_IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
+struct ioctl_evtchn_bind_unbound_port {
+	unsigned int remote_domain;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND				\
+	_IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
+struct ioctl_evtchn_unbind {
+	unsigned int port;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY				\
+	_IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify))
+struct ioctl_evtchn_notify {
+	unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET				\
+	_IOC(_IOC_NONE, 'E', 5, 0)
+
+#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
--- linux-ec2-2.6.32.orig/include/xen/public/privcmd.h
+++ linux-ec2-2.6.32/include/xen/public/privcmd.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * privcmd.h
+ * 
+ * Interface to /proc/xen/privcmd.
+ * 
+ * Copyright (c) 2003-2005, K A Fraser
+ * 
+ * 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 __LINUX_PUBLIC_PRIVCMD_H__
+#define __LINUX_PUBLIC_PRIVCMD_H__
+
+#include <linux/types.h>
+
+#ifndef __user
+#define __user
+#endif
+
+typedef struct privcmd_hypercall
+{
+	__u64 op;
+	__u64 arg[5];
+} privcmd_hypercall_t;
+
+typedef struct privcmd_mmap_entry {
+	__u64 va;
+	__u64 mfn;
+	__u64 npages;
+} privcmd_mmap_entry_t; 
+
+typedef struct privcmd_mmap {
+	int num;
+	domid_t dom; /* target domain */
+	privcmd_mmap_entry_t __user *entry;
+} privcmd_mmap_t; 
+
+typedef struct privcmd_mmapbatch {
+	int num;     /* number of pages to populate */
+	domid_t dom; /* target domain */
+	__u64 addr;  /* virtual address */
+	xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */
+} privcmd_mmapbatch_t; 
+
+/*
+ * @cmd: IOCTL_PRIVCMD_HYPERCALL
+ * @arg: &privcmd_hypercall_t
+ * Return: Value returned from execution of the specified hypercall.
+ */
+#define IOCTL_PRIVCMD_HYPERCALL					\
+	_IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
+#define IOCTL_PRIVCMD_MMAP					\
+	_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
+#define IOCTL_PRIVCMD_MMAPBATCH					\
+	_IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+
+#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
--- linux-ec2-2.6.32.orig/include/xen/public/xenbus.h
+++ linux-ec2-2.6.32/include/xen/public/xenbus.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ * xenbus.h
+ * 
+ * Interface to /proc/xen/xenbus.
+ * 
+ * Copyright (c) 2008, Diego Ongaro <diego.ongaro@citrix.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; 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 __LINUX_PUBLIC_XENBUS_H__
+#define __LINUX_PUBLIC_XENBUS_H__
+
+#include <linux/types.h>
+
+#ifndef __user
+#define __user
+#endif
+
+typedef struct xenbus_alloc {
+	domid_t dom;
+	__u32 port;
+	__u32 grant_ref;
+} xenbus_alloc_t;
+
+/*
+ * @cmd: IOCTL_XENBUS_ALLOC
+ * @arg: &xenbus_alloc_t
+ * Return: 0, or -1 for error
+ */
+#define IOCTL_XENBUS_ALLOC					\
+	_IOC(_IOC_NONE, 'X', 0, sizeof(xenbus_alloc_t))
+
+#endif /* __LINUX_PUBLIC_XENBUS_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/grant_table.h
+++ linux-ec2-2.6.32/include/xen/interface/grant_table.h
@@ -28,6 +28,7 @@
 #ifndef __XEN_PUBLIC_GRANT_TABLE_H__
 #define __XEN_PUBLIC_GRANT_TABLE_H__
 
+#include "xen.h"
 
 /***********************************
  * GRANT TABLE REPRESENTATION
@@ -100,6 +101,7 @@
      */
     uint32_t frame;
 };
+typedef struct grant_entry grant_entry_t;
 
 /*
  * Type of grant entry.
@@ -118,6 +120,7 @@
  *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
  *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
  *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
+ *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
  */
 #define _GTF_readonly       (2)
 #define GTF_readonly        (1U<<_GTF_readonly)
@@ -125,6 +128,12 @@
 #define GTF_reading         (1U<<_GTF_reading)
 #define _GTF_writing        (4)
 #define GTF_writing         (1U<<_GTF_writing)
+#define _GTF_PWT            (5)
+#define GTF_PWT             (1U<<_GTF_PWT)
+#define _GTF_PCD            (6)
+#define GTF_PCD             (1U<<_GTF_PCD)
+#define _GTF_PAT            (7)
+#define GTF_PAT             (1U<<_GTF_PAT)
 
 /*
  * Subflags for GTF_accept_transfer:
@@ -186,6 +195,8 @@
     uint64_t dev_bus_addr;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);
+typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
 
 /*
  * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
@@ -208,6 +219,8 @@
     int16_t  status;              /* GNTST_* */
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref);
+typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
 
 /*
  * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
@@ -225,9 +238,11 @@
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    GUEST_HANDLE(ulong) frame_list;
+    XEN_GUEST_HANDLE(ulong) frame_list;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
+typedef struct gnttab_setup_table gnttab_setup_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
 
 /*
  * GNTTABOP_dump_table: Dump the contents of the grant table to the
@@ -241,6 +256,8 @@
     int16_t status;               /* GNTST_* */
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);
+typedef struct gnttab_dump_table gnttab_dump_table_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
 
 /*
  * GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
@@ -253,13 +270,16 @@
 #define GNTTABOP_transfer                4
 struct gnttab_transfer {
     /* IN parameters. */
-    unsigned long mfn;
+    xen_pfn_t     mfn;
     domid_t       domid;
     grant_ref_t   ref;
     /* OUT parameters. */
     int16_t       status;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);
+typedef struct gnttab_transfer gnttab_transfer_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
+
 
 /*
  * GNTTABOP_copy: Hypervisor based copy
@@ -285,22 +305,23 @@
 #define GNTCOPY_dest_gref         (1<<_GNTCOPY_dest_gref)
 
 #define GNTTABOP_copy                 5
-struct gnttab_copy {
-	/* IN parameters. */
-	struct {
-		union {
-			grant_ref_t ref;
-			unsigned long   gmfn;
-		} u;
-		domid_t  domid;
-		uint16_t offset;
-	} source, dest;
-	uint16_t      len;
-	uint16_t      flags;          /* GNTCOPY_* */
-	/* OUT parameters. */
-	int16_t       status;
-};
+typedef struct gnttab_copy {
+    /* IN parameters. */
+    struct {
+        union {
+            grant_ref_t ref;
+            xen_pfn_t   gmfn;
+        } u;
+        domid_t  domid;
+        uint16_t offset;
+    } source, dest;
+    uint16_t      len;
+    uint16_t      flags;          /* GNTCOPY_* */
+    /* OUT parameters. */
+    int16_t       status;
+} gnttab_copy_t;
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);
+DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
 
 /*
  * GNTTABOP_query_size: Query the current and maximum sizes of the shared
@@ -319,9 +340,35 @@
     int16_t  status;              /* GNTST_* */
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
+typedef struct gnttab_query_size gnttab_query_size_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
+
+/*
+ * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
+ * tracked by <handle> but atomically replace the page table entry with one
+ * pointing to the machine address under <new_addr>.  <new_addr> will be
+ * redirected to the null entry.
+ * NOTES:
+ *  1. The call may fail in an undefined manner if either mapping is not
+ *     tracked by <handle>.
+ *  2. After executing a batch of unmaps, it is guaranteed that no stale
+ *     mappings will remain in the device or host TLBs.
+ */
+#define GNTTABOP_unmap_and_replace    7
+struct gnttab_unmap_and_replace {
+    /* IN parameters. */
+    uint64_t host_addr;
+    uint64_t new_addr;
+    grant_handle_t handle;
+    /* OUT parameters. */
+    int16_t  status;              /* GNTST_* */
+};
+typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
+
 
 /*
- * Bitfield values for update_pin_status.flags.
+ * Bitfield values for gnttab_map_grant_ref.flags.
  */
  /* Map the grant entry for access by I/O devices. */
 #define _GNTMAP_device_map      (0)
@@ -349,6 +396,13 @@
 #define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
 
 /*
+ * Bits to be placed in guest kernel available PTE bits (architecture
+ * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
+ */
+#define _GNTMAP_guest_avail0    (16)
+#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
+
+/*
  * Values for error status returns. All errors are -ve.
  */
 #define GNTST_okay             (0)  /* Normal return.                        */
@@ -361,7 +415,8 @@
 #define GNTST_no_device_space  (-7) /* Out of space in I/O MMU.              */
 #define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
 #define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
-#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary */
+#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary.   */
+#define GNTST_address_too_big (-11) /* transfer page address too large.      */
 
 #define GNTTABOP_error_msgs {                   \
     "okay",                                     \
@@ -374,7 +429,8 @@
     "no spare translation slot in the I/O MMU", \
     "permission denied",                        \
     "bad page",                                 \
-    "copy arguments cross page boundary"        \
+    "copy arguments cross page boundary",       \
+    "page address size too large"               \
 }
 
 #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86_64.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86_64.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * arch-x86_64.h
+ * 
+ * Guest OS interface to x86 64-bit 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 "arch-x86/xen.h"
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86_32.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86_32.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * arch-x86_32.h
+ * 
+ * Guest OS interface to x86 32-bit 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 "arch-x86/xen.h"
--- linux-ec2-2.6.32.orig/include/xen/interface/elfnote.h
+++ linux-ec2-2.6.32/include/xen/interface/elfnote.h
@@ -3,6 +3,24 @@
  *
  * Definitions used for the Xen ELF notes.
  *
+ * 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) 2006, Ian Campbell, XenSource Ltd.
  */
 
@@ -10,7 +28,7 @@
 #define __XEN_PUBLIC_ELFNOTE_H__
 
 /*
- * The notes should live in a SHT_NOTE segment and have "Xen" in the
+ * The notes should live in a PT_NOTE segment and have "Xen" in the
  * name field.
  *
  * Numeric types are either 4 or 8 bytes depending on the content of
@@ -22,8 +40,6 @@
 
 /*
  * NAME=VALUE pair (string).
- *
- * LEGACY: FEATURES and PAE
  */
 #define XEN_ELFNOTE_INFO           0
 
@@ -90,7 +106,12 @@
 #define XEN_ELFNOTE_LOADER         8
 
 /*
- * The kernel supports PAE (x86/32 only, string = "yes" or "no").
+ * The kernel supports PAE (x86/32 only, string = "yes", "no" or
+ * "bimodal").
+ *
+ * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting
+ * may be given as "yes,bimodal" which will cause older Xen to treat
+ * this kernel as PAE.
  *
  * LEGACY: PAE (n.b. The legacy interface included a provision to
  * indicate 'extended-cr3' support allowing L3 page tables to be
@@ -140,6 +161,76 @@
  */
 #define XEN_ELFNOTE_SUSPEND_CANCEL 14
 
+/*
+ * The (non-default) location the initial phys-to-machine map should be
+ * placed at by the hypervisor (Dom0) or the tools (DomU).
+ * The kernel must be prepared for this mapping to be established using
+ * large pages, despite such otherwise not being available to guests.
+ * The kernel must also be able to handle the page table pages used for
+ * this mapping not being accessible through the initial mapping.
+ * (Only x86-64 supports this at present.)
+ */
+#define XEN_ELFNOTE_INIT_P2M      15
+
+/*
+ * The number of the highest elfnote defined.
+ */
+#define XEN_ELFNOTE_MAX XEN_ELFNOTE_INIT_P2M
+
+/*
+ * System information exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO
+ * note in case of a system crash. This note will contain various
+ * information about the system, see xen/include/xen/elfcore.h.
+ */
+#define XEN_ELFNOTE_CRASH_INFO 0x1000001
+
+/*
+ * System registers exported through crash notes.
+ *
+ * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS
+ * note per cpu in case of a system crash. This note is architecture
+ * specific and will contain registers not saved in the "CORE" note.
+ * See xen/include/xen/elfcore.h for more information.
+ */
+#define XEN_ELFNOTE_CRASH_REGS 0x1000002
+
+
+/*
+ * xen dump-core none note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE
+ * in its dump file to indicate that the file is xen dump-core
+ * file. This note doesn't have any other information.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_NONE               0x2000000
+
+/*
+ * xen dump-core header note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER
+ * in its dump file.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_HEADER             0x2000001
+
+/*
+ * xen dump-core xen version note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION
+ * in its dump file. It contains the xen version obtained via the
+ * XENVER hypercall.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION        0x2000002
+
+/*
+ * xen dump-core format version note.
+ * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION
+ * in its dump file. It contains a format version identifier.
+ * See tools/libxc/xc_core.h for more information.
+ */
+#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION     0x2000003
+
 #endif /* __XEN_PUBLIC_ELFNOTE_H__ */
 
 /*
--- linux-ec2-2.6.32.orig/include/xen/interface/tmem.h
+++ linux-ec2-2.6.32/include/xen/interface/tmem.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ * tmem.h
+ * 
+ * Guest OS interface to Xen Transcendent Memory.
+ * 
+ * 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, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_TMEM_H__
+#define __XEN_PUBLIC_TMEM_H__
+
+#include "xen.h"
+
+/* Commands to HYPERVISOR_tmem_op() */
+#define TMEM_CONTROL               0
+#define TMEM_NEW_POOL              1
+#define TMEM_DESTROY_POOL          2
+#define TMEM_NEW_PAGE              3
+#define TMEM_PUT_PAGE              4
+#define TMEM_GET_PAGE              5
+#define TMEM_FLUSH_PAGE            6
+#define TMEM_FLUSH_OBJECT          7
+#define TMEM_READ                  8
+#define TMEM_WRITE                 9
+#define TMEM_XCHG                 10
+
+/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
+#define TMEMC_THAW                 0
+#define TMEMC_FREEZE               1
+#define TMEMC_FLUSH                2
+#define TMEMC_DESTROY              3
+#define TMEMC_LIST                 4
+#define TMEMC_SET_WEIGHT           5
+#define TMEMC_SET_CAP              6
+#define TMEMC_SET_COMPRESS         7
+
+/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
+#define TMEM_POOL_PERSIST          1
+#define TMEM_POOL_SHARED           2
+#define TMEM_POOL_PAGESIZE_SHIFT   4
+#define TMEM_POOL_PAGESIZE_MASK  0xf
+#define TMEM_POOL_VERSION_SHIFT   24
+#define TMEM_POOL_VERSION_MASK  0xff
+
+/* Special errno values */
+#define EFROZEN                 1000
+#define EEMPTY                  1001
+
+
+#ifndef __ASSEMBLY__
+typedef xen_pfn_t tmem_cli_mfn_t;
+typedef XEN_GUEST_HANDLE(char) tmem_cli_va_t;
+struct tmem_op {
+    uint32_t cmd;
+    int32_t pool_id; /* private > 0; shared < 0; 0 is invalid */
+    union {
+        struct {  /* for cmd == TMEM_NEW_POOL */
+            uint64_t uuid[2];
+            uint32_t flags;
+        } new;
+        struct {  /* for cmd == TMEM_CONTROL */
+            uint32_t subop;
+            uint32_t cli_id;
+            uint32_t arg1;
+            uint32_t arg2;
+            tmem_cli_va_t buf;
+        } ctrl;
+        struct {
+            uint64_t object;
+            uint32_t index;
+            uint32_t tmem_offset;
+            uint32_t pfn_offset;
+            uint32_t len;
+            tmem_cli_mfn_t cmfn; /* client machine page frame */
+        } gen;
+    } u;
+};
+typedef struct tmem_op tmem_op_t;
+DEFINE_XEN_GUEST_HANDLE(tmem_op_t);
+
+#endif
+
+#endif /* __XEN_PUBLIC_TMEM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/version.h
+++ linux-ec2-2.6.32/include/xen/interface/version.h
@@ -3,6 +3,24 @@
  *
  * Xen version, type, and compile information.
  *
+ * 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) 2005, Nguyen Anh Quynh <aquynh@gmail.com>
  * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
  */
@@ -10,17 +28,18 @@
 #ifndef __XEN_PUBLIC_VERSION_H__
 #define __XEN_PUBLIC_VERSION_H__
 
-/* NB. All ops return zero on success, except XENVER_version. */
+/* NB. All ops return zero on success, except XENVER_{version,pagesize} */
 
 /* arg == NULL; returns major:minor (16:16). */
 #define XENVER_version      0
 
 /* arg == xen_extraversion_t. */
 #define XENVER_extraversion 1
+typedef char xen_extraversion_t[16];
 struct xen_extraversion {
-    char extraversion[16];
+    xen_extraversion_t extraversion;
 };
-#define XEN_EXTRAVERSION_LEN (sizeof(struct xen_extraversion))
+#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t))
 
 /* arg == xen_compile_info_t. */
 #define XENVER_compile_info 2
@@ -30,29 +49,34 @@
     char compile_domain[32];
     char compile_date[32];
 };
+typedef struct xen_compile_info xen_compile_info_t;
 
 #define XENVER_capabilities 3
+typedef char xen_capabilities_info_t[1024];
 struct xen_capabilities_info {
-    char info[1024];
+    xen_capabilities_info_t info;
 };
-#define XEN_CAPABILITIES_INFO_LEN (sizeof(struct xen_capabilities_info))
+#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t))
 
 #define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
 struct xen_changeset_info {
-    char info[64];
+    xen_changeset_info_t info;
 };
-#define XEN_CHANGESET_INFO_LEN (sizeof(struct xen_changeset_info))
+#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t))
 
 #define XENVER_platform_parameters 5
 struct xen_platform_parameters {
     unsigned long virt_start;
 };
+typedef struct xen_platform_parameters xen_platform_parameters_t;
 
 #define XENVER_get_features 6
 struct xen_feature_info {
     unsigned int submap_idx;    /* IN: which 32-bit submap to return */
     uint32_t     submap;        /* OUT: 32-bit submap */
 };
+typedef struct xen_feature_info xen_feature_info_t;
 
 /* Declares the features reported by XENVER_get_features. */
 #include "features.h"
@@ -60,4 +84,10 @@
 /* arg == NULL; returns host memory page size. */
 #define XENVER_pagesize 7
 
+/* arg == xen_domain_handle_t. */
+#define XENVER_guest_handle 8
+
+#define XENVER_commandline 9
+typedef char xen_commandline_t[1024];
+
 #endif /* __XEN_PUBLIC_VERSION_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/callback.h
+++ linux-ec2-2.6.32/include/xen/interface/callback.h
@@ -86,6 +86,8 @@
 	uint16_t flags;
 	xen_callback_t address;
 };
+typedef struct callback_register callback_register_t;
+DEFINE_XEN_GUEST_HANDLE(callback_register_t);
 
 /*
  * Unregister a callback.
@@ -98,5 +100,12 @@
     uint16_t type;
     uint16_t _unused;
 };
+typedef struct callback_unregister callback_unregister_t;
+DEFINE_XEN_GUEST_HANDLE(callback_unregister_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030207
+#undef CALLBACKTYPE_sysenter
+#define CALLBACKTYPE_sysenter CALLBACKTYPE_sysenter_deprecated
+#endif
 
 #endif /* __XEN_PUBLIC_CALLBACK_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/nmi.h
+++ linux-ec2-2.6.32/include/xen/interface/nmi.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ * nmi.h
+ * 
+ * NMI callback registration and reason codes.
+ * 
+ * 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) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_NMI_H__
+#define __XEN_PUBLIC_NMI_H__
+
+#include "xen.h"
+
+/*
+ * NMI reason codes:
+ * Currently these are x86-specific, stored in arch_shared_info.nmi_reason.
+ */
+ /* I/O-check error reported via ISA port 0x61, bit 6. */
+#define _XEN_NMIREASON_io_error     0
+#define XEN_NMIREASON_io_error      (1UL << _XEN_NMIREASON_io_error)
+ /* Parity error reported via ISA port 0x61, bit 7. */
+#define _XEN_NMIREASON_parity_error 1
+#define XEN_NMIREASON_parity_error  (1UL << _XEN_NMIREASON_parity_error)
+ /* Unknown hardware-generated NMI. */
+#define _XEN_NMIREASON_unknown      2
+#define XEN_NMIREASON_unknown       (1UL << _XEN_NMIREASON_unknown)
+
+/*
+ * long nmi_op(unsigned int cmd, void *arg)
+ * NB. All ops return zero on success, else a negative error code.
+ */
+
+/*
+ * Register NMI callback for this (calling) VCPU. Currently this only makes
+ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL.
+ * arg == pointer to xennmi_callback structure.
+ */
+#define XENNMI_register_callback   0
+struct xennmi_callback {
+    unsigned long handler_address;
+    unsigned long pad;
+};
+typedef struct xennmi_callback xennmi_callback_t;
+DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t);
+
+/*
+ * Deregister NMI callback for this (calling) VCPU.
+ * arg == NULL.
+ */
+#define XENNMI_unregister_callback 1
+
+#endif /* __XEN_PUBLIC_NMI_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/memory.h
+++ linux-ec2-2.6.32/include/xen/interface/memory.h
@@ -3,20 +3,57 @@
  *
  * Memory reservation and information.
  *
+ * 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) 2005, Keir Fraser <keir@xensource.com>
  */
 
 #ifndef __XEN_PUBLIC_MEMORY_H__
 #define __XEN_PUBLIC_MEMORY_H__
 
+#include "xen.h"
+
 /*
- * Increase or decrease the specified domain's memory reservation. Returns a
- * -ve errcode on failure, or the # extents successfully allocated or freed.
+ * Increase or decrease the specified domain's memory reservation. Returns the
+ * number of extents successfully allocated or freed.
  * arg == addr of struct xen_memory_reservation.
  */
 #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)
+/* Flag to populate physmap with populate-on-demand entries */
+#define XENMEMF_populate_on_demand (1<<16)
+#endif
+
 struct xen_memory_reservation {
 
     /*
@@ -29,28 +66,71 @@
      *   OUT: GMFN bases of extents that were allocated
      *   (NB. This command also updates the mach_to_phys translation table)
      */
-    GUEST_HANDLE(ulong) extent_start;
+    XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
 
     /* Number of extents, and size/alignment of each (2^extent_order pages). */
-    unsigned long  nr_extents;
+    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.
      * Unprivileged domains can specify only DOMID_SELF.
      */
     domid_t        domid;
-
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_memory_reservation);
+typedef struct xen_memory_reservation xen_memory_reservation_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t);
+
+/*
+ * An atomic exchange of memory pages. If return code is zero then
+ * @out.extent_list provides GMFNs of the newly-allocated memory.
+ * Returns zero on complete success, otherwise a negative error code.
+ * On complete success then always @nr_exchanged == @in.nr_extents.
+ * On partial success @nr_exchanged indicates how much work was done.
+ */
+#define XENMEM_exchange             11
+struct xen_memory_exchange {
+    /*
+     * [IN] Details of memory extents to be exchanged (GMFN bases).
+     * Note that @in.address_bits is ignored and unused.
+     */
+    struct xen_memory_reservation in;
+
+    /*
+     * [IN/OUT] Details of new memory extents.
+     * We require that:
+     *  1. @in.domid == @out.domid
+     *  2. @in.nr_extents  << @in.extent_order ==
+     *     @out.nr_extents << @out.extent_order
+     *  3. @in.extent_start and @out.extent_start lists must not overlap
+     *  4. @out.extent_start lists GPFN bases to be populated
+     *  5. @out.extent_start is overwritten with allocated GMFN bases
+     */
+    struct xen_memory_reservation out;
+
+    /*
+     * [OUT] Number of input extents that were successfully exchanged:
+     *  1. The first @nr_exchanged input extents were successfully
+     *     deallocated.
+     *  2. The corresponding first entries in the output extent list correctly
+     *     indicate the GMFNs that were successfully exchanged.
+     *  3. All other input and output extents are untouched.
+     *  4. If not all input exents are exchanged then the return code of this
+     *     command will be non-zero.
+     *  5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER!
+     */
+    xen_ulong_t nr_exchanged;
+};
+typedef struct xen_memory_exchange xen_memory_exchange_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t);
 
 /*
  * Returns the maximum machine frame number of mapped RAM in this system.
@@ -68,6 +148,11 @@
 #define XENMEM_maximum_reservation  4
 
 /*
+ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
+ */
+#define XENMEM_maximum_gpfn         14
+
+/*
  * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
  * mapping table. Architectures which do not have a m2p table do not implement
  * this command.
@@ -86,7 +171,7 @@
      * any large discontiguities in the machine address space, 2MB gaps in
      * the machphys table will be represented by an MFN base of zero.
      */
-    GUEST_HANDLE(ulong) extent_start;
+    XEN_GUEST_HANDLE(xen_pfn_t) extent_start;
 
     /*
      * Number of extents written to the above array. This will be smaller
@@ -95,6 +180,22 @@
     unsigned int nr_extents;
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);
+typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
+
+/*
+ * Returns the location in virtual address space of the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table, or which do not
+ * map it by default into guest address space, do not implement this command.
+ * arg == addr of xen_machphys_mapping_t.
+ */
+#define XENMEM_machphys_mapping     12
+struct xen_machphys_mapping {
+    xen_ulong_t v_start, v_end; /* Start and end virtual addresses.   */
+    xen_ulong_t max_mfn;        /* Maximum MFN that can be looked up. */
+};
+typedef struct xen_machphys_mapping xen_machphys_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
 
 /*
  * Sets the GPFN at which a particular page appears in the specified guest's
@@ -109,37 +210,76 @@
     /* Source mapping space. */
 #define XENMAPSPACE_shared_info 0 /* shared info page */
 #define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_gmfn        2 /* GMFN */
     unsigned int space;
 
     /* Index into source mapping space. */
-    unsigned long idx;
+    xen_ulong_t idx;
 
     /* GPFN where the source mapping page should appear. */
-    unsigned long gpfn;
+    xen_pfn_t     gpfn;
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
+typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list  8*/
 
 /*
- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
- * code on failure. This call only works for auto-translated guests.
+ * Returns the pseudo-physical memory map as it was when the domain
+ * was started (specified by XENMEM_set_memory_map).
+ * arg == addr of xen_memory_map_t.
  */
-#define XENMEM_translate_gpfn_list  8
-struct xen_translate_gpfn_list {
-    /* Which domain to translate for? */
-    domid_t domid;
-
-    /* Length of list. */
-    unsigned long nr_gpfns;
-
-    /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
+#define XENMEM_memory_map           9
+struct xen_memory_map {
+    /*
+     * On call the number of entries which can be stored in buffer. On
+     * return the number of entries which have been stored in
+     * buffer.
+     */
+    unsigned int nr_entries;
 
     /*
-     * Output list to contain MFN translations. May be the same as the input
-     * list (in which case each input GPFN is overwritten with the output MFN).
+     * Entries in the buffer are in the same format as returned by the
+     * BIOS INT 0x15 EAX=0xE820 call.
      */
-    GUEST_HANDLE(ulong) mfn_list;
+    XEN_GUEST_HANDLE(void) buffer;
 };
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+typedef struct xen_memory_map xen_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t);
+
+/*
+ * Returns the real physical memory map. Passes the same structure as
+ * XENMEM_memory_map.
+ * arg == addr of xen_memory_map_t.
+ */
+#define XENMEM_machine_memory_map   10
 
+/*
+ * Set the pseudo-physical memory map of a domain, as returned by
+ * XENMEM_memory_map.
+ * arg == addr of xen_foreign_memory_map_t.
+ */
+#define XENMEM_set_memory_map       13
+struct xen_foreign_memory_map {
+    domid_t domid;
+    struct xen_memory_map map;
+};
+typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
+
+#define XENMEM_set_pod_target       16
+#define XENMEM_get_pod_target       17
+struct xen_pod_target {
+    /* IN */
+    uint64_t target_pages;
+    /* OUT */
+    uint64_t tot_pages;
+    uint64_t pod_cache_pages;
+    uint64_t pod_entries;
+    /* IN */
+    domid_t domid;
+};
+typedef struct xen_pod_target xen_pod_target_t;
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/xen-compat.h
+++ linux-ec2-2.6.32/include/xen/interface/xen-compat.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * xen-compat.h
+ * 
+ * Guest OS interface to Xen.  Compatibility layer.
+ * 
+ * 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) 2006, Christian Limpach
+ */
+
+#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
+#define __XEN_PUBLIC_XEN_COMPAT_H__
+
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030209
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Xen is built with matching headers and implements the latest interface. */
+#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
+#elif !defined(__XEN_INTERFACE_VERSION__)
+/* Guests which do not specify a version get the legacy interface. */
+#define __XEN_INTERFACE_VERSION__ 0x00000000
+#endif
+
+#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
+#error "These header files do not support the requested interface version."
+#endif
+
+#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/sched.h
+++ linux-ec2-2.6.32/include/xen/interface/sched.h
@@ -3,6 +3,24 @@
  *
  * Scheduler state interactions
  *
+ * 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) 2005, Keir Fraser <keir@xensource.com>
  */
 
@@ -13,17 +31,17 @@
 
 /*
  * The prototype for this hypercall is:
- *  long sched_op_new(int cmd, void *arg)
+ *  long sched_op(int cmd, void *arg)
  * @cmd == SCHEDOP_??? (scheduler operation).
  * @arg == Operation-specific extra argument(s), as described below.
  *
- * **NOTE**:
- * Versions of Xen prior to 3.0.2 provide only the following legacy version
+ * Versions of Xen prior to 3.0.2 provided only the following legacy version
  * of this hypercall, supporting only the commands yield, block and shutdown:
  *  long sched_op(int cmd, unsigned long arg)
  * @cmd == SCHEDOP_??? (scheduler operation).
  * @arg == 0               (SCHEDOP_yield and SCHEDOP_block)
  *      == SHUTDOWN_* code (SCHEDOP_shutdown)
+ * This legacy version is available to new guests as sched_op_compat().
  */
 
 /*
@@ -50,6 +68,8 @@
     unsigned int reason; /* SHUTDOWN_* */
 };
 DEFINE_GUEST_HANDLE_STRUCT(sched_shutdown);
+typedef struct sched_shutdown sched_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
 
 /*
  * Poll a set of event-channel ports. Return when one or more are pending. An
@@ -58,11 +78,27 @@
  */
 #define SCHEDOP_poll        3
 struct sched_poll {
-    GUEST_HANDLE(evtchn_port_t) ports;
+    XEN_GUEST_HANDLE(evtchn_port_t) ports;
     unsigned int nr_ports;
     uint64_t timeout;
 };
 DEFINE_GUEST_HANDLE_STRUCT(sched_poll);
+typedef struct sched_poll sched_poll_t;
+DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
+
+/*
+ * Declare a shutdown for another domain. The main use of this function is
+ * in interpreting shutdown requests and reasons for fully-virtualized
+ * domains.  A para-virtualized domain may use SCHEDOP_shutdown directly.
+ * @arg == pointer to sched_remote_shutdown structure.
+ */
+#define SCHEDOP_remote_shutdown        4
+struct sched_remote_shutdown {
+    domid_t domain_id;         /* Remote domain ID */
+    unsigned int reason;       /* SHUTDOWN_xxx reason */
+};
+typedef struct sched_remote_shutdown sched_remote_shutdown_t;
+DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
 
 /*
  * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
--- linux-ec2-2.6.32.orig/include/xen/interface/xen.h
+++ linux-ec2-2.6.32/include/xen/interface/xen.h
@@ -3,35 +3,70 @@
  *
  * Guest OS interface to 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, K A Fraser
  */
 
 #ifndef __XEN_PUBLIC_XEN_H__
 #define __XEN_PUBLIC_XEN_H__
 
-#include <asm/xen/interface.h>
+#include "xen-compat.h"
+#ifdef CONFIG_PARAVIRT_XEN
 #include <asm/pvclock-abi.h>
+#endif
 
-/*
- * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS).
- */
+#if defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H)
+#include <asm/xen/interface.h>
+#elif defined(__i386__) || defined(__x86_64__)
+#include "arch-x86/xen.h"
+#elif defined(__ia64__)
+#include "arch-ia64.h"
+#else
+#error "Unsupported architecture"
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+DEFINE_XEN_GUEST_HANDLE(char);
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+DEFINE_XEN_GUEST_HANDLE(int);
+__DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
+DEFINE_XEN_GUEST_HANDLE(long);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+DEFINE_XEN_GUEST_HANDLE(void);
+
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+#endif
 
 /*
- * x86_32: EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5.
- *         EAX = return value
- *         (argument registers may be clobbered on return)
- * x86_64: RAX = vector; RDI, RSI, RDX, R10, R8, R9 = args 1, 2, 3, 4, 5, 6.
- *         RAX = return value
- *         (argument registers not clobbered on return; RCX, R11 are)
+ * HYPERCALLS
  */
+
 #define __HYPERVISOR_set_trap_table        0
 #define __HYPERVISOR_mmu_update            1
 #define __HYPERVISOR_set_gdt               2
 #define __HYPERVISOR_stack_switch          3
 #define __HYPERVISOR_set_callbacks         4
 #define __HYPERVISOR_fpu_taskswitch        5
-#define __HYPERVISOR_sched_op              6
-#define __HYPERVISOR_dom0_op               7
+#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op           7
 #define __HYPERVISOR_set_debugreg          8
 #define __HYPERVISOR_get_debugreg          9
 #define __HYPERVISOR_update_descriptor    10
@@ -39,10 +74,10 @@
 #define __HYPERVISOR_multicall            13
 #define __HYPERVISOR_update_va_mapping    14
 #define __HYPERVISOR_set_timer_op         15
-#define __HYPERVISOR_event_channel_op_compat 16
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
 #define __HYPERVISOR_xen_version          17
 #define __HYPERVISOR_console_io           18
-#define __HYPERVISOR_physdev_op_compat    19
+#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
 #define __HYPERVISOR_grant_table_op       20
 #define __HYPERVISOR_vm_assist            21
 #define __HYPERVISOR_update_va_mapping_otherdomain 22
@@ -50,7 +85,7 @@
 #define __HYPERVISOR_vcpu_op              24
 #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
 #define __HYPERVISOR_mmuext_op            26
-#define __HYPERVISOR_acm_op               27
+#define __HYPERVISOR_xsm_op               27
 #define __HYPERVISOR_nmi_op               28
 #define __HYPERVISOR_sched_op_new         29
 #define __HYPERVISOR_callback_op          30
@@ -58,6 +93,10 @@
 #define __HYPERVISOR_event_channel_op     32
 #define __HYPERVISOR_physdev_op           33
 #define __HYPERVISOR_hvm_op               34
+#define __HYPERVISOR_sysctl               35
+#define __HYPERVISOR_domctl               36
+#define __HYPERVISOR_kexec_op             37
+#define __HYPERVISOR_tmem_op              38
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
@@ -70,15 +109,48 @@
 #define __HYPERVISOR_arch_7               55
 
 /*
+ * HYPERCALL COMPATIBILITY.
+ */
+
+/* New sched_op hypercall introduced in 0x00030101. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030101 || (defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H))
+#undef __HYPERVISOR_sched_op
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+#else
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_new
+#endif
+
+/* New event-channel and physdev hypercalls introduced in 0x00030202. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030202
+#undef __HYPERVISOR_event_channel_op
+#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
+#undef __HYPERVISOR_physdev_op
+#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
+#endif
+
+/* New platform_op hypercall introduced in 0x00030204. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030204 || (defined(CONFIG_PARAVIRT_XEN) && !defined(HAVE_XEN_PLATFORM_COMPAT_H))
+#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+#endif
+
+/*
  * VIRTUAL INTERRUPTS
  *
  * Virtual interrupts that a guest OS may receive from Xen.
- */
-#define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
-#define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
-#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
-#define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
-#define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+ *
+ * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
+ * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
+ * The latter can be allocated only once per guest: they must initially be
+ * allocated to VCPU0 but can subsequently be re-bound.
+ */
+#define VIRQ_TIMER      0  /* V. Timebase update, and/or requested timeout.  */
+#define VIRQ_DEBUG      1  /* V. Request guest to dump debug info.           */
+#define VIRQ_CONSOLE    2  /* G. (DOM0) Bytes received on emergency console. */
+#define VIRQ_DOM_EXC    3  /* G. (DOM0) Exceptional event for some domain.   */
+#define VIRQ_TBUF       4  /* G. (DOM0) Trace buffer has records available.  */
+#define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
+#define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
+#define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16
@@ -91,6 +163,7 @@
 #define VIRQ_ARCH_7    23
 
 #define NR_VIRQS       24
+
 /*
  * MMU-UPDATE REQUESTS
  *
@@ -119,8 +192,8 @@
  * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
  * with those in @val.
  */
-#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.       */
-#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for  */
+#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.      */
+#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for */
 #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
 
 /*
@@ -163,9 +236,20 @@
  * cmd: MMUEXT_FLUSH_CACHE
  * No additional arguments. Writes back and flushes cache contents.
  *
+ * cmd: MMUEXT_FLUSH_CACHE_GLOBAL
+ * No additional arguments. Writes back and flushes cache contents
+ * on all CPUs in the system.
+ *
  * cmd: MMUEXT_SET_LDT
  * linear_addr: Linear address of LDT base (NB. must be page-aligned).
  * nr_ents: Number of entries in LDT.
+ *
+ * cmd: MMUEXT_CLEAR_PAGE
+ * mfn: Machine frame number to be cleared.
+ *
+ * cmd: MMUEXT_COPY_PAGE
+ * mfn: Machine frame number of the destination page.
+ * src_mfn: Machine frame number of the source page.
  */
 #define MMUEXT_PIN_L1_TABLE      0
 #define MMUEXT_PIN_L2_TABLE      1
@@ -182,24 +266,36 @@
 #define MMUEXT_FLUSH_CACHE      12
 #define MMUEXT_SET_LDT          13
 #define MMUEXT_NEW_USER_BASEPTR 15
+#define MMUEXT_CLEAR_PAGE       16
+#define MMUEXT_COPY_PAGE        17
+#define MMUEXT_FLUSH_CACHE_GLOBAL 18
 
 #ifndef __ASSEMBLY__
 struct mmuext_op {
-	unsigned int cmd;
-	union {
-		/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */
-		unsigned long mfn;
-		/* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
-		unsigned long linear_addr;
-	} arg1;
-	union {
-		/* SET_LDT */
-		unsigned int nr_ents;
-		/* TLB_FLUSH_MULTI, INVLPG_MULTI */
-		void *vcpumask;
-	} arg2;
+    unsigned int cmd;
+    union {
+        /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
+         * CLEAR_PAGE, COPY_PAGE */
+        xen_pfn_t     mfn;
+        /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
+        unsigned long linear_addr;
+    } arg1;
+    union {
+        /* SET_LDT */
+        unsigned int nr_ents;
+        /* TLB_FLUSH_MULTI, INVLPG_MULTI */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030205
+        XEN_GUEST_HANDLE(const_void) vcpumask;
+#else
+        const void *vcpumask;
+#endif
+        /* COPY_PAGE */
+        xen_pfn_t src_mfn;
+    } arg2;
 };
 DEFINE_GUEST_HANDLE_STRUCT(mmuext_op);
+typedef struct mmuext_op mmuext_op_t;
+DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
 #endif
 
 /* These are passed as 'flags' to update_va_mapping. They can be ORed. */
@@ -224,11 +320,24 @@
  */
 #define VMASST_CMD_enable                0
 #define VMASST_CMD_disable               1
+
+/* x86/32 guests: simulate full 4GB segment limits. */
 #define VMASST_TYPE_4gb_segments         0
+
+/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
 #define VMASST_TYPE_4gb_segments_notify  1
+
+/*
+ * x86 guests: support writes to bottom-level PTEs.
+ * NB1. Page-directory entries cannot be written.
+ * NB2. Guest must continue to remove all writable mappings of PTEs.
+ */
 #define VMASST_TYPE_writable_pagetables  2
+
+/* x86/PAE guests: support PDPTs above 4GB. */
 #define VMASST_TYPE_pae_extended_cr3     3
-#define MAX_VMASST_TYPE 3
+
+#define MAX_VMASST_TYPE                  3
 
 #ifndef __ASSEMBLY__
 
@@ -259,6 +368,9 @@
  */
 #define DOMID_XEN  (0x7FF2U)
 
+/* DOMID_INVALID is used to identity invalid domid */
+#define DOMID_INVALID (0x7FFFU)
+
 /*
  * Send an array of these to HYPERVISOR_mmu_update().
  * NB. The fields are natural pointer/address size for this architecture.
@@ -268,6 +380,8 @@
     uint64_t val;       /* New contents of PTE.    */
 };
 DEFINE_GUEST_HANDLE_STRUCT(mmu_update);
+typedef struct mmu_update mmu_update_t;
+DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
 
 /*
  * Send an array of these to HYPERVISOR_multicall().
@@ -275,10 +389,16 @@
  */
 struct multicall_entry {
     unsigned long op;
+#if !defined(CONFIG_PARAVIRT_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+    unsigned long result;
+#else
     long result;
+#endif
     unsigned long args[6];
 };
 DEFINE_GUEST_HANDLE_STRUCT(multicall_entry);
+typedef struct multicall_entry multicall_entry_t;
+DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
 
 /*
  * Event channel endpoints per domain:
@@ -287,173 +407,244 @@
 #define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
 
 struct vcpu_time_info {
-	/*
-	 * Updates to the following values are preceded and followed
-	 * by an increment of 'version'. The guest can therefore
-	 * detect updates by looking for changes to 'version'. If the
-	 * least-significant bit of the version number is set then an
-	 * update is in progress and the guest must wait to read a
-	 * consistent set of values.  The correct way to interact with
-	 * the version number is similar to Linux's seqlock: see the
-	 * implementations of read_seqbegin/read_seqretry.
-	 */
-	uint32_t version;
-	uint32_t pad0;
-	uint64_t tsc_timestamp;   /* TSC at last update of time vals.  */
-	uint64_t system_time;     /* Time, in nanosecs, since boot.    */
-	/*
-	 * Current system time:
-	 *   system_time + ((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul
-	 * CPU frequency (Hz):
-	 *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
-	 */
-	uint32_t tsc_to_system_mul;
-	int8_t   tsc_shift;
-	int8_t   pad1[3];
+    /*
+     * Updates to the following values are preceded and followed by an
+     * increment of 'version'. The guest can therefore detect updates by
+     * looking for changes to 'version'. If the least-significant bit of
+     * the version number is set then an update is in progress and the guest
+     * must wait to read a consistent set of values.
+     * The correct way to interact with the version number is similar to
+     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
+     */
+    uint32_t version;
+    uint32_t pad0;
+    uint64_t tsc_timestamp;   /* TSC at last update of time vals.  */
+    uint64_t system_time;     /* Time, in nanosecs, since boot.    */
+    /*
+     * Current system time:
+     *   system_time +
+     *   ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
+     * CPU frequency (Hz):
+     *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
+     */
+    uint32_t tsc_to_system_mul;
+    int8_t   tsc_shift;
+    int8_t   pad1[3];
 }; /* 32 bytes */
+typedef struct vcpu_time_info vcpu_time_info_t;
 
 struct vcpu_info {
-	/*
-	 * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
-	 * a pending notification for a particular VCPU. It is then cleared
-	 * by the guest OS /before/ checking for pending work, thus avoiding
-	 * a set-and-check race. Note that the mask is only accessed by Xen
-	 * on the CPU that is currently hosting the VCPU. This means that the
-	 * pending and mask flags can be updated by the guest without special
-	 * synchronisation (i.e., no need for the x86 LOCK prefix).
-	 * This may seem suboptimal because if the pending flag is set by
-	 * a different CPU then an IPI may be scheduled even when the mask
-	 * is set. However, note:
-	 *  1. The task of 'interrupt holdoff' is covered by the per-event-
-	 *     channel mask bits. A 'noisy' event that is continually being
-	 *     triggered can be masked at source at this very precise
-	 *     granularity.
-	 *  2. The main purpose of the per-VCPU mask is therefore to restrict
-	 *     reentrant execution: whether for concurrency control, or to
-	 *     prevent unbounded stack usage. Whatever the purpose, we expect
-	 *     that the mask will be asserted only for short periods at a time,
-	 *     and so the likelihood of a 'spurious' IPI is suitably small.
-	 * The mask is read before making an event upcall to the guest: a
-	 * non-zero mask therefore guarantees that the VCPU will not receive
-	 * an upcall activation. The mask is cleared when the VCPU requests
-	 * to block: this avoids wakeup-waiting races.
-	 */
-	uint8_t evtchn_upcall_pending;
-	uint8_t evtchn_upcall_mask;
-	unsigned long evtchn_pending_sel;
-	struct arch_vcpu_info arch;
-	struct pvclock_vcpu_time_info time;
+    /*
+     * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
+     * a pending notification for a particular VCPU. It is then cleared
+     * by the guest OS /before/ checking for pending work, thus avoiding
+     * a set-and-check race. Note that the mask is only accessed by Xen
+     * on the CPU that is currently hosting the VCPU. This means that the
+     * pending and mask flags can be updated by the guest without special
+     * synchronisation (i.e., no need for the x86 LOCK prefix).
+     * This may seem suboptimal because if the pending flag is set by
+     * a different CPU then an IPI may be scheduled even when the mask
+     * is set. However, note:
+     *  1. The task of 'interrupt holdoff' is covered by the per-event-
+     *     channel mask bits. A 'noisy' event that is continually being
+     *     triggered can be masked at source at this very precise
+     *     granularity.
+     *  2. The main purpose of the per-VCPU mask is therefore to restrict
+     *     reentrant execution: whether for concurrency control, or to
+     *     prevent unbounded stack usage. Whatever the purpose, we expect
+     *     that the mask will be asserted only for short periods at a time,
+     *     and so the likelihood of a 'spurious' IPI is suitably small.
+     * The mask is read before making an event upcall to the guest: a
+     * non-zero mask therefore guarantees that the VCPU will not receive
+     * an upcall activation. The mask is cleared when the VCPU requests
+     * to block: this avoids wakeup-waiting races.
+     */
+    uint8_t evtchn_upcall_pending;
+    uint8_t evtchn_upcall_mask;
+    unsigned long evtchn_pending_sel;
+    struct arch_vcpu_info arch;
+#ifdef CONFIG_PARAVIRT_XEN
+    struct pvclock_vcpu_time_info time;
+#else
+    struct vcpu_time_info time;
+#endif
 }; /* 64 bytes (x86) */
+#ifndef __XEN__
+typedef struct vcpu_info vcpu_info_t;
+#endif
 
 /*
  * Xen/kernel shared data -- pointer provided in start_info.
- * NB. We expect that this struct is smaller than a page.
+ *
+ * This structure is defined to be both smaller than a page, and the
+ * only data on the shared page, but may vary in actual size even within
+ * compatible Xen versions; guests should not rely on the size
+ * of this structure remaining constant.
  */
 struct shared_info {
-	struct vcpu_info vcpu_info[MAX_VIRT_CPUS];
+    struct vcpu_info vcpu_info[MAX_VIRT_CPUS];
 
-	/*
-	 * A domain can create "event channels" on which it can send and receive
-	 * asynchronous event notifications. There are three classes of event that
-	 * are delivered by this mechanism:
-	 *  1. Bi-directional inter- and intra-domain connections. Domains must
-	 *     arrange out-of-band to set up a connection (usually by allocating
-	 *     an unbound 'listener' port and avertising that via a storage service
-	 *     such as xenstore).
-	 *  2. Physical interrupts. A domain with suitable hardware-access
-	 *     privileges can bind an event-channel port to a physical interrupt
-	 *     source.
-	 *  3. Virtual interrupts ('events'). A domain can bind an event-channel
-	 *     port to a virtual interrupt source, such as the virtual-timer
-	 *     device or the emergency console.
-	 *
-	 * Event channels are addressed by a "port index". Each channel is
-	 * associated with two bits of information:
-	 *  1. PENDING -- notifies the domain that there is a pending notification
-	 *     to be processed. This bit is cleared by the guest.
-	 *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
-	 *     will cause an asynchronous upcall to be scheduled. This bit is only
-	 *     updated by the guest. It is read-only within Xen. If a channel
-	 *     becomes pending while the channel is masked then the 'edge' is lost
-	 *     (i.e., when the channel is unmasked, the guest must manually handle
-	 *     pending notifications as no upcall will be scheduled by Xen).
-	 *
-	 * To expedite scanning of pending notifications, any 0->1 pending
-	 * transition on an unmasked channel causes a corresponding bit in a
-	 * per-vcpu selector word to be set. Each bit in the selector covers a
-	 * 'C long' in the PENDING bitfield array.
-	 */
-	unsigned long evtchn_pending[sizeof(unsigned long) * 8];
-	unsigned long evtchn_mask[sizeof(unsigned long) * 8];
-
-	/*
-	 * Wallclock time: updated only by control software. Guests should base
-	 * their gettimeofday() syscall on this wallclock-base value.
-	 */
-	struct pvclock_wall_clock wc;
+    /*
+     * A domain can create "event channels" on which it can send and receive
+     * asynchronous event notifications. There are three classes of event that
+     * are delivered by this mechanism:
+     *  1. Bi-directional inter- and intra-domain connections. Domains must
+     *     arrange out-of-band to set up a connection (usually by allocating
+     *     an unbound 'listener' port and avertising that via a storage service
+     *     such as xenstore).
+     *  2. Physical interrupts. A domain with suitable hardware-access
+     *     privileges can bind an event-channel port to a physical interrupt
+     *     source.
+     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
+     *     port to a virtual interrupt source, such as the virtual-timer
+     *     device or the emergency console.
+     *
+     * Event channels are addressed by a "port index". Each channel is
+     * associated with two bits of information:
+     *  1. PENDING -- notifies the domain that there is a pending notification
+     *     to be processed. This bit is cleared by the guest.
+     *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
+     *     will cause an asynchronous upcall to be scheduled. This bit is only
+     *     updated by the guest. It is read-only within Xen. If a channel
+     *     becomes pending while the channel is masked then the 'edge' is lost
+     *     (i.e., when the channel is unmasked, the guest must manually handle
+     *     pending notifications as no upcall will be scheduled by Xen).
+     *
+     * To expedite scanning of pending notifications, any 0->1 pending
+     * transition on an unmasked channel causes a corresponding bit in a
+     * per-vcpu selector word to be set. Each bit in the selector covers a
+     * 'C long' in the PENDING bitfield array.
+     */
+    unsigned long evtchn_pending[sizeof(unsigned long) * 8];
+    unsigned long evtchn_mask[sizeof(unsigned long) * 8];
+
+    /*
+     * Wallclock time: updated only by control software. Guests should base
+     * their gettimeofday() syscall on this wallclock-base value.
+     */
+#ifdef CONFIG_PARAVIRT_XEN
+    struct pvclock_wall_clock wc;
+#else
+    uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */
+    uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
+    uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
+#endif
 
-	struct arch_shared_info arch;
+    struct arch_shared_info arch;
 
 };
+#ifndef __XEN__
+typedef struct shared_info shared_info_t;
+#endif
 
 /*
- * Start-of-day memory layout for the initial domain (DOM0):
+ * Start-of-day memory layout:
  *  1. The domain is started within contiguous virtual-memory region.
- *  2. The contiguous region begins and ends on an aligned 4MB boundary.
- *  3. The region start corresponds to the load address of the OS image.
- *     If the load address is not 4MB aligned then the address is rounded down.
- *  4. This the order of bootstrap elements in the initial virtual region:
+ *  2. The contiguous region ends on an aligned 4MB boundary.
+ *  3. This the order of bootstrap elements in the initial virtual region:
  *      a. relocated kernel image
  *      b. initial ram disk              [mod_start, mod_len]
  *      c. list of allocated page frames [mfn_list, nr_pages]
+ *         (unless relocated due to XEN_ELFNOTE_INIT_P2M)
  *      d. start_info_t structure        [register ESI (x86)]
  *      e. bootstrap page tables         [pt_base, CR3 (x86)]
  *      f. bootstrap stack               [register ESP (x86)]
- *  5. Bootstrap elements are packed together, but each is 4kB-aligned.
- *  6. The initial ram disk may be omitted.
- *  7. The list of page frames forms a contiguous 'pseudo-physical' memory
+ *  4. Bootstrap elements are packed together, but each is 4kB-aligned.
+ *  5. The initial ram disk may be omitted.
+ *  6. The list of page frames forms a contiguous 'pseudo-physical' memory
  *     layout for the domain. In particular, the bootstrap virtual-memory
  *     region is a 1:1 mapping to the first section of the pseudo-physical map.
- *  8. All bootstrap elements are mapped read-writable for the guest OS. The
+ *  7. All bootstrap elements are mapped read-writable for the guest OS. The
  *     only exception is the bootstrap page table, which is mapped read-only.
- *  9. There is guaranteed to be at least 512kB padding after the final
+ *  8. There is guaranteed to be at least 512kB padding after the final
  *     bootstrap element. If necessary, the bootstrap virtual region is
  *     extended by an extra 4MB to ensure this.
  */
 
 #define MAX_GUEST_CMDLINE 1024
 struct start_info {
-	/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
-	char magic[32];             /* "xen-<version>-<platform>".            */
-	unsigned long nr_pages;     /* Total pages allocated to this domain.  */
-	unsigned long shared_info;  /* MACHINE address of shared info struct. */
-	uint32_t flags;             /* SIF_xxx flags.                         */
-	unsigned long store_mfn;    /* MACHINE page number of shared page.    */
-	uint32_t store_evtchn;      /* Event channel for store communication. */
-	union {
-		struct {
-			unsigned long mfn;  /* MACHINE page number of console page.   */
-			uint32_t  evtchn;   /* Event channel for console page.        */
-		} domU;
-		struct {
-			uint32_t info_off;  /* Offset of console_info struct.         */
-			uint32_t info_size; /* Size of console_info struct from start.*/
-		} dom0;
-	} console;
-	/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
-	unsigned long pt_base;      /* VIRTUAL address of page directory.     */
-	unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
-	unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
-	unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
-	unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
-	int8_t cmd_line[MAX_GUEST_CMDLINE];
+    /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
+    char magic[32];             /* "xen-<version>-<platform>".            */
+    unsigned long nr_pages;     /* Total pages allocated to this domain.  */
+    unsigned long shared_info;  /* MACHINE address of shared info struct. */
+    uint32_t flags;             /* SIF_xxx flags.                         */
+    xen_pfn_t store_mfn;        /* MACHINE page number of shared page.    */
+    uint32_t store_evtchn;      /* Event channel for store communication. */
+    union {
+        struct {
+            xen_pfn_t mfn;      /* MACHINE page number of console page.   */
+            uint32_t  evtchn;   /* Event channel for console page.        */
+        } domU;
+        struct {
+            uint32_t info_off;  /* Offset of console_info struct.         */
+            uint32_t info_size; /* Size of console_info struct from start.*/
+        } dom0;
+    } console;
+    /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
+    unsigned long pt_base;      /* VIRTUAL address of page directory.     */
+    unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
+    unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
+    unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
+    unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
+    int8_t cmd_line[MAX_GUEST_CMDLINE];
+    /* The pfn range here covers both page table and p->m table frames.   */
+    unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table.    */
+    unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table.  */
 };
+typedef struct start_info start_info_t;
+
+/* New console union for dom0 introduced in 0x00030203. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030203
+#define console_mfn    console.domU.mfn
+#define console_evtchn console.domU.evtchn
+#endif
 
 /* 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 uint64_t cpumap_t;
+typedef struct dom0_vga_console_info {
+    uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
+#define XEN_VGATYPE_VESA_LFB    0x23
+
+    union {
+        struct {
+            /* Font height, in pixels. */
+            uint16_t font_height;
+            /* Cursor location (column, row). */
+            uint16_t cursor_x, cursor_y;
+            /* Number of rows and columns (dimensions in characters). */
+            uint16_t rows, columns;
+        } text_mode_3;
+
+        struct {
+            /* Width and height, in pixels. */
+            uint16_t width, height;
+            /* Bytes per scan line. */
+            uint16_t bytes_per_line;
+            /* Bits per pixel. */
+            uint16_t bits_per_pixel;
+            /* LFB physical address, and size (in units of 64kB). */
+            uint32_t lfb_base;
+            uint32_t lfb_size;
+            /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
+            uint8_t  red_pos, red_size;
+            uint8_t  green_pos, green_size;
+            uint8_t  blue_pos, blue_size;
+            uint8_t  rsvd_pos, rsvd_size;
+#if __XEN_INTERFACE_VERSION__ >= 0x00030206
+            /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
+            uint32_t gbl_caps;
+            /* Mode attributes (offset 0x0, VESA command 0x4f01). */
+            uint16_t mode_attrs;
+#endif
+        } vesa_lfb;
+    } u;
+} dom0_vga_console_info_t;
+#define xen_vga_console_info dom0_vga_console_info
+#define xen_vga_console_info_t dom0_vga_console_info_t
 
 typedef uint8_t xen_domain_handle_t[16];
 
@@ -461,6 +652,11 @@
 #define __mk_unsigned_long(x) x ## UL
 #define mk_unsigned_long(x) __mk_unsigned_long(x)
 
+__DEFINE_XEN_GUEST_HANDLE(uint8,  uint8_t);
+__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
+__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
+__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
+
 #else /* __ASSEMBLY__ */
 
 /* In assembly code we cannot use C numeric constant suffixes. */
@@ -468,4 +664,14 @@
 
 #endif /* !__ASSEMBLY__ */
 
+/* Default definitions for macros used by domctl/sysctl. */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#ifndef uint64_aligned_t
+#define uint64_aligned_t uint64_t
+#endif
+#ifndef XEN_GUEST_HANDLE_64
+#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
+#endif
+#endif
+
 #endif /* __XEN_PUBLIC_XEN_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/physdev.h
+++ linux-ec2-2.6.32/include/xen/interface/physdev.h
@@ -21,10 +21,12 @@
 #ifndef __XEN_PUBLIC_PHYSDEV_H__
 #define __XEN_PUBLIC_PHYSDEV_H__
 
+#include "xen.h"
+
 /*
  * Prototype for this hypercall is:
  *  int physdev_op(int cmd, void *args)
- * @cmd	 == PHYSDEVOP_??? (physdev operation).
+ * @cmd  == PHYSDEVOP_??? (physdev operation).
  * @args == Operation-specific extra arguments (NULL if none).
  */
 
@@ -32,114 +34,218 @@
  * Notify end-of-interrupt (EOI) for the specified IRQ.
  * @arg == pointer to physdev_eoi structure.
  */
-#define PHYSDEVOP_eoi			12
+#define PHYSDEVOP_eoi                   12
 struct physdev_eoi {
-	/* IN */
-	uint32_t irq;
+    /* IN */
+    uint32_t irq;
 };
+typedef struct physdev_eoi physdev_eoi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t);
+
+/*
+ * Register a shared page for the hypervisor to indicate whether the guest
+ * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly
+ * once the guest used this function in that the associated event channel
+ * will automatically get unmasked. The page registered is used as a bit
+ * array indexed by Xen's PIRQ value.
+ */
+#define PHYSDEVOP_pirq_eoi_gmfn         17
+struct physdev_pirq_eoi_gmfn {
+    /* IN */
+    xen_pfn_t gmfn;
+};
+typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t);
 
 /*
  * Query the status of an IRQ line.
  * @arg == pointer to physdev_irq_status_query structure.
  */
-#define PHYSDEVOP_irq_status_query	 5
+#define PHYSDEVOP_irq_status_query       5
 struct physdev_irq_status_query {
-	/* IN */
-	uint32_t irq;
-	/* OUT */
-	uint32_t flags; /* XENIRQSTAT_* */
+    /* IN */
+    uint32_t irq;
+    /* OUT */
+    uint32_t flags; /* XENIRQSTAT_* */
 };
+typedef struct physdev_irq_status_query physdev_irq_status_query_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t);
 
 /* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */
-#define _XENIRQSTAT_needs_eoi	(0)
-#define	 XENIRQSTAT_needs_eoi	(1U<<_XENIRQSTAT_needs_eoi)
+#define _XENIRQSTAT_needs_eoi   (0)
+#define  XENIRQSTAT_needs_eoi   (1U<<_XENIRQSTAT_needs_eoi)
 
 /* IRQ shared by multiple guests? */
-#define _XENIRQSTAT_shared	(1)
-#define	 XENIRQSTAT_shared	(1U<<_XENIRQSTAT_shared)
+#define _XENIRQSTAT_shared      (1)
+#define  XENIRQSTAT_shared      (1U<<_XENIRQSTAT_shared)
 
 /*
  * Set the current VCPU's I/O privilege level.
  * @arg == pointer to physdev_set_iopl structure.
  */
-#define PHYSDEVOP_set_iopl		 6
+#define PHYSDEVOP_set_iopl               6
 struct physdev_set_iopl {
-	/* IN */
-	uint32_t iopl;
+    /* IN */
+    uint32_t iopl;
 };
+typedef struct physdev_set_iopl physdev_set_iopl_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t);
 
 /*
  * Set the current VCPU's I/O-port permissions bitmap.
  * @arg == pointer to physdev_set_iobitmap structure.
  */
-#define PHYSDEVOP_set_iobitmap		 7
+#define PHYSDEVOP_set_iobitmap           7
 struct physdev_set_iobitmap {
-	/* IN */
-	uint8_t * bitmap;
-	uint32_t nr_ports;
+    /* IN */
+#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;
+DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t);
 
 /*
  * Read or write an IO-APIC register.
  * @arg == pointer to physdev_apic structure.
  */
-#define PHYSDEVOP_apic_read		 8
-#define PHYSDEVOP_apic_write		 9
+#define PHYSDEVOP_apic_read              8
+#define PHYSDEVOP_apic_write             9
 struct physdev_apic {
-	/* IN */
-	unsigned long apic_physbase;
-	uint32_t reg;
-	/* IN or OUT */
-	uint32_t value;
+    /* IN */
+    unsigned long apic_physbase;
+    uint32_t reg;
+    /* IN or OUT */
+    uint32_t value;
 };
+typedef struct physdev_apic physdev_apic_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_apic_t);
 
 /*
  * Allocate or free a physical upcall vector for the specified IRQ line.
  * @arg == pointer to physdev_irq structure.
  */
-#define PHYSDEVOP_alloc_irq_vector	10
-#define PHYSDEVOP_free_irq_vector	11
+#define PHYSDEVOP_alloc_irq_vector      10
+#define PHYSDEVOP_free_irq_vector       11
 struct physdev_irq {
-	/* IN */
-	uint32_t irq;
-	/* IN or OUT */
-	uint32_t vector;
+    /* IN */
+    uint32_t irq;
+    /* IN or OUT */
+    uint32_t vector;
+};
+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);
+
+#define PHYSDEVOP_restore_msi            19
+struct physdev_restore_msi {
+    /* IN */
+    uint8_t bus;
+    uint8_t devfn;
+};
+typedef struct physdev_restore_msi physdev_restore_msi_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
+
+#define PHYSDEVOP_manage_pci_add_ext     20
+struct physdev_manage_pci_ext {
+    /* IN */
+    uint8_t bus;
+    uint8_t devfn;
+    unsigned is_extfn;
+    unsigned is_virtfn;
+    struct {
+        uint8_t bus;
+        uint8_t devfn;
+    } physfn;
 };
 
+typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
+
 /*
  * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
  * hypercall since 0x00030202.
  */
 struct physdev_op {
-	uint32_t cmd;
-	union {
-		struct physdev_irq_status_query	     irq_status_query;
-		struct physdev_set_iopl		     set_iopl;
-		struct physdev_set_iobitmap	     set_iobitmap;
-		struct physdev_apic		     apic_op;
-		struct physdev_irq		     irq_op;
-	} u;
+    uint32_t cmd;
+    union {
+        struct physdev_irq_status_query      irq_status_query;
+        struct physdev_set_iopl              set_iopl;
+        struct physdev_set_iobitmap          set_iobitmap;
+        struct physdev_apic                  apic_op;
+        struct physdev_irq                   irq_op;
+    } u;
 };
+typedef struct physdev_op physdev_op_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_op_t);
 
 /*
  * Notify that some PIRQ-bound event channels have been unmasked.
  * ** This command is obsolete since interface version 0x00030202 and is **
- * ** unsupported by newer versions of Xen.				 **
+ * ** unsupported by newer versions of Xen.                              **
  */
-#define PHYSDEVOP_IRQ_UNMASK_NOTIFY	 4
+#define PHYSDEVOP_IRQ_UNMASK_NOTIFY      4
 
 /*
  * These all-capitals physdev operation names are superceded by the new names
  * (defined above) since interface version 0x00030202.
  */
-#define PHYSDEVOP_IRQ_STATUS_QUERY	 PHYSDEVOP_irq_status_query
-#define PHYSDEVOP_SET_IOPL		 PHYSDEVOP_set_iopl
-#define PHYSDEVOP_SET_IOBITMAP		 PHYSDEVOP_set_iobitmap
-#define PHYSDEVOP_APIC_READ		 PHYSDEVOP_apic_read
-#define PHYSDEVOP_APIC_WRITE		 PHYSDEVOP_apic_write
-#define PHYSDEVOP_ASSIGN_VECTOR		 PHYSDEVOP_alloc_irq_vector
-#define PHYSDEVOP_FREE_VECTOR		 PHYSDEVOP_free_irq_vector
+#define PHYSDEVOP_IRQ_STATUS_QUERY       PHYSDEVOP_irq_status_query
+#define PHYSDEVOP_SET_IOPL               PHYSDEVOP_set_iopl
+#define PHYSDEVOP_SET_IOBITMAP           PHYSDEVOP_set_iobitmap
+#define PHYSDEVOP_APIC_READ              PHYSDEVOP_apic_read
+#define PHYSDEVOP_APIC_WRITE             PHYSDEVOP_apic_write
+#define PHYSDEVOP_ASSIGN_VECTOR          PHYSDEVOP_alloc_irq_vector
+#define PHYSDEVOP_FREE_VECTOR            PHYSDEVOP_free_irq_vector
 #define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi
-#define PHYSDEVOP_IRQ_SHARED		 XENIRQSTAT_shared
+#define PHYSDEVOP_IRQ_SHARED             XENIRQSTAT_shared
 
 #endif /* __XEN_PUBLIC_PHYSDEV_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/COPYING
+++ linux-ec2-2.6.32/include/xen/interface/COPYING
@@ -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.
--- linux-ec2-2.6.32.orig/include/xen/interface/event_channel.h
+++ linux-ec2-2.6.32/include/xen/interface/event_channel.h
@@ -3,6 +3,24 @@
  *
  * Event channels between domains.
  *
+ * 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) 2003-2004, K A Fraser.
  */
 
@@ -11,8 +29,15 @@
 
 #include <xen/interface/xen.h>
 
+/*
+ * Prototype for this hypercall is:
+ *  int event_channel_op(int cmd, void *args)
+ * @cmd  == EVTCHNOP_??? (event-channel operation).
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
 typedef uint32_t evtchn_port_t;
-DEFINE_GUEST_HANDLE(evtchn_port_t);
+DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
 
 /*
  * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
@@ -22,13 +47,14 @@
  *  1. If the caller is unprivileged then <dom> must be DOMID_SELF.
  *  2. <rdom> may be DOMID_SELF, allowing loopback connections.
  */
-#define EVTCHNOP_alloc_unbound	  6
+#define EVTCHNOP_alloc_unbound    6
 struct evtchn_alloc_unbound {
-	/* IN parameters */
-	domid_t dom, remote_dom;
-	/* OUT parameters */
-	evtchn_port_t port;
+    /* IN parameters */
+    domid_t dom, remote_dom;
+    /* OUT parameters */
+    evtchn_port_t port;
 };
+typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
 
 /*
  * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
@@ -41,29 +67,35 @@
  */
 #define EVTCHNOP_bind_interdomain 0
 struct evtchn_bind_interdomain {
-	/* IN parameters. */
-	domid_t remote_dom;
-	evtchn_port_t remote_port;
-	/* OUT parameters. */
-	evtchn_port_t local_port;
+    /* IN parameters. */
+    domid_t remote_dom;
+    evtchn_port_t remote_port;
+    /* OUT parameters. */
+    evtchn_port_t local_port;
 };
+typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
 
 /*
  * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
  * vcpu.
  * NOTES:
- *  1. A virtual IRQ may be bound to at most one event channel per vcpu.
- *  2. The allocated event channel is bound to the specified vcpu. The binding
- *     may not be changed.
+ *  1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
+ *     in xen.h for the classification of each VIRQ.
+ *  2. Global VIRQs must be allocated on VCPU0 but can subsequently be
+ *     re-bound via EVTCHNOP_bind_vcpu.
+ *  3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
+ *     The allocated event channel is bound to the specified vcpu and the
+ *     binding cannot be changed.
  */
-#define EVTCHNOP_bind_virq	  1
+#define EVTCHNOP_bind_virq        1
 struct evtchn_bind_virq {
-	/* IN parameters. */
-	uint32_t virq;
-	uint32_t vcpu;
-	/* OUT parameters. */
-	evtchn_port_t port;
+    /* IN parameters. */
+    uint32_t virq;
+    uint32_t vcpu;
+    /* OUT parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_bind_virq evtchn_bind_virq_t;
 
 /*
  * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ <irq>.
@@ -71,15 +103,16 @@
  *  1. A physical IRQ may be bound to at most one event channel per domain.
  *  2. Only a sufficiently-privileged domain may bind to a physical IRQ.
  */
-#define EVTCHNOP_bind_pirq	  2
+#define EVTCHNOP_bind_pirq        2
 struct evtchn_bind_pirq {
-	/* IN parameters. */
-	uint32_t pirq;
+    /* IN parameters. */
+    uint32_t pirq;
 #define BIND_PIRQ__WILL_SHARE 1
-	uint32_t flags; /* BIND_PIRQ__* */
-	/* OUT parameters. */
-	evtchn_port_t port;
+    uint32_t flags; /* BIND_PIRQ__* */
+    /* OUT parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
 
 /*
  * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
@@ -87,33 +120,36 @@
  *  1. The allocated event channel is bound to the specified vcpu. The binding
  *     may not be changed.
  */
-#define EVTCHNOP_bind_ipi	  7
+#define EVTCHNOP_bind_ipi         7
 struct evtchn_bind_ipi {
-	uint32_t vcpu;
-	/* OUT parameters. */
-	evtchn_port_t port;
+    uint32_t vcpu;
+    /* OUT parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
 
 /*
  * EVTCHNOP_close: Close a local event channel <port>. If the channel is
  * interdomain then the remote end is placed in the unbound state
  * (EVTCHNSTAT_unbound), awaiting a new connection.
  */
-#define EVTCHNOP_close		  3
+#define EVTCHNOP_close            3
 struct evtchn_close {
-	/* IN parameters. */
-	evtchn_port_t port;
+    /* IN parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_close evtchn_close_t;
 
 /*
  * EVTCHNOP_send: Send an event to the remote end of the channel whose local
  * endpoint is <port>.
  */
-#define EVTCHNOP_send		  4
+#define EVTCHNOP_send             4
 struct evtchn_send {
-	/* IN parameters. */
-	evtchn_port_t port;
+    /* IN parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_send evtchn_send_t;
 
 /*
  * EVTCHNOP_status: Get the current status of the communication channel which
@@ -123,75 +159,99 @@
  *  2. Only a sufficiently-privileged domain may obtain the status of an event
  *     channel for which <dom> is not DOMID_SELF.
  */
-#define EVTCHNOP_status		  5
+#define EVTCHNOP_status           5
 struct evtchn_status {
-	/* IN parameters */
-	domid_t  dom;
-	evtchn_port_t port;
-	/* OUT parameters */
-#define EVTCHNSTAT_closed	0  /* Channel is not in use.		     */
-#define EVTCHNSTAT_unbound	1  /* Channel is waiting interdom connection.*/
-#define EVTCHNSTAT_interdomain	2  /* Channel is connected to remote domain. */
-#define EVTCHNSTAT_pirq		3  /* Channel is bound to a phys IRQ line.   */
-#define EVTCHNSTAT_virq		4  /* Channel is bound to a virtual IRQ line */
-#define EVTCHNSTAT_ipi		5  /* Channel is bound to a virtual IPI line */
-	uint32_t status;
-	uint32_t vcpu;		   /* VCPU to which this channel is bound.   */
-	union {
-		struct {
-			domid_t dom;
-		} unbound; /* EVTCHNSTAT_unbound */
-		struct {
-			domid_t dom;
-			evtchn_port_t port;
-		} interdomain; /* EVTCHNSTAT_interdomain */
-		uint32_t pirq;	    /* EVTCHNSTAT_pirq	      */
-		uint32_t virq;	    /* EVTCHNSTAT_virq	      */
-	} u;
+    /* IN parameters */
+    domid_t  dom;
+    evtchn_port_t port;
+    /* OUT parameters */
+#define EVTCHNSTAT_closed       0  /* Channel is not in use.                 */
+#define EVTCHNSTAT_unbound      1  /* Channel is waiting interdom connection.*/
+#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
+#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
+#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
+#define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */
+    uint32_t status;
+    uint32_t vcpu;                 /* VCPU to which this channel is bound.   */
+    union {
+        struct {
+            domid_t dom;
+        } unbound; /* EVTCHNSTAT_unbound */
+        struct {
+            domid_t dom;
+            evtchn_port_t port;
+        } interdomain; /* EVTCHNSTAT_interdomain */
+        uint32_t pirq;      /* EVTCHNSTAT_pirq        */
+        uint32_t virq;      /* EVTCHNSTAT_virq        */
+    } u;
 };
+typedef struct evtchn_status evtchn_status_t;
 
 /*
  * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
  * event is pending.
  * NOTES:
- *  1. IPI- and VIRQ-bound channels always notify the vcpu that initialised
- *     the binding. This binding cannot be changed.
- *  2. All other channels notify vcpu0 by default. This default is set when
+ *  1. IPI-bound channels always notify the vcpu specified at bind time.
+ *     This binding cannot be changed.
+ *  2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
+ *     This binding cannot be changed.
+ *  3. All other channels notify vcpu0 by default. This default is set when
  *     the channel is allocated (a port that is freed and subsequently reused
  *     has its binding reset to vcpu0).
  */
-#define EVTCHNOP_bind_vcpu	  8
+#define EVTCHNOP_bind_vcpu        8
 struct evtchn_bind_vcpu {
-	/* IN parameters. */
-	evtchn_port_t port;
-	uint32_t vcpu;
+    /* IN parameters. */
+    evtchn_port_t port;
+    uint32_t vcpu;
 };
+typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
 
 /*
  * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
  * a notification to the appropriate VCPU if an event is pending.
  */
-#define EVTCHNOP_unmask		  9
+#define EVTCHNOP_unmask           9
 struct evtchn_unmask {
-	/* IN parameters. */
-	evtchn_port_t port;
+    /* IN parameters. */
+    evtchn_port_t port;
 };
+typedef struct evtchn_unmask evtchn_unmask_t;
 
+/*
+ * EVTCHNOP_reset: Close all event channels associated with specified domain.
+ * NOTES:
+ *  1. <dom> may be specified as DOMID_SELF.
+ *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ */
+#define EVTCHNOP_reset           10
+struct evtchn_reset {
+    /* IN parameters. */
+    domid_t dom;
+};
+typedef struct evtchn_reset evtchn_reset_t;
+
+/*
+ * Argument to event_channel_op_compat() hypercall. Superceded by new
+ * event_channel_op() hypercall since 0x00030202.
+ */
 struct evtchn_op {
-	uint32_t cmd; /* EVTCHNOP_* */
-	union {
-		struct evtchn_alloc_unbound    alloc_unbound;
-		struct evtchn_bind_interdomain bind_interdomain;
-		struct evtchn_bind_virq	       bind_virq;
-		struct evtchn_bind_pirq	       bind_pirq;
-		struct evtchn_bind_ipi	       bind_ipi;
-		struct evtchn_close	       close;
-		struct evtchn_send	       send;
-		struct evtchn_status	       status;
-		struct evtchn_bind_vcpu	       bind_vcpu;
-		struct evtchn_unmask	       unmask;
-	} u;
+    uint32_t cmd; /* EVTCHNOP_* */
+    union {
+        struct evtchn_alloc_unbound    alloc_unbound;
+        struct evtchn_bind_interdomain bind_interdomain;
+        struct evtchn_bind_virq        bind_virq;
+        struct evtchn_bind_pirq        bind_pirq;
+        struct evtchn_bind_ipi         bind_ipi;
+        struct evtchn_close            close;
+        struct evtchn_send             send;
+        struct evtchn_status           status;
+        struct evtchn_bind_vcpu        bind_vcpu;
+        struct evtchn_unmask           unmask;
+    } u;
 };
 DEFINE_GUEST_HANDLE_STRUCT(evtchn_op);
+typedef struct evtchn_op evtchn_op_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
 
 #endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/trace.h
+++ linux-ec2-2.6.32/include/xen/interface/trace.h
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * include/public/trace.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.
+ *
+ * Mark Williamson, (C) 2004 Intel Research Cambridge
+ * Copyright (C) 2005 Bin Ren
+ */
+
+#ifndef __XEN_PUBLIC_TRACE_H__
+#define __XEN_PUBLIC_TRACE_H__
+
+#define TRACE_EXTRA_MAX    7
+#define TRACE_EXTRA_SHIFT 28
+
+/* Trace classes */
+#define TRC_CLS_SHIFT 16
+#define TRC_GEN      0x0001f000    /* General trace            */
+#define TRC_SCHED    0x0002f000    /* Xen Scheduler trace      */
+#define TRC_DOM0OP   0x0004f000    /* Xen DOM0 operation trace */
+#define TRC_HVM      0x0008f000    /* Xen HVM trace            */
+#define TRC_MEM      0x0010f000    /* Xen memory trace         */
+#define TRC_PV       0x0020f000    /* Xen PV traces            */
+#define TRC_SHADOW   0x0040f000    /* Xen shadow tracing       */
+#define TRC_PM       0x0080f000    /* Xen power management trace */
+#define TRC_ALL      0x0ffff000
+#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff)
+#define TRC_HD_CYCLE_FLAG (1UL<<31)
+#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) )
+#define TRC_HD_EXTRA(x)    (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX)
+
+/* Trace subclasses */
+#define TRC_SUBCLS_SHIFT 12
+
+/* trace subclasses for SVM */
+#define TRC_HVM_ENTRYEXIT 0x00081000   /* VMENTRY and #VMEXIT       */
+#define TRC_HVM_HANDLER   0x00082000   /* various HVM handlers      */
+
+#define TRC_SCHED_MIN       0x00021000   /* Just runstate changes */
+#define TRC_SCHED_VERBOSE   0x00028000   /* More inclusive scheduling */
+
+/* Trace events per class */
+#define TRC_LOST_RECORDS        (TRC_GEN + 1)
+#define TRC_TRACE_WRAP_BUFFER  (TRC_GEN + 2)
+#define TRC_TRACE_CPU_CHANGE    (TRC_GEN + 3)
+#define TRC_TRACE_IRQ           (TRC_GEN + 4)
+
+#define TRC_SCHED_RUNSTATE_CHANGE   (TRC_SCHED_MIN + 1)
+#define TRC_SCHED_CONTINUE_RUNNING  (TRC_SCHED_MIN + 2)
+#define TRC_SCHED_DOM_ADD        (TRC_SCHED_VERBOSE +  1)
+#define TRC_SCHED_DOM_REM        (TRC_SCHED_VERBOSE +  2)
+#define TRC_SCHED_SLEEP          (TRC_SCHED_VERBOSE +  3)
+#define TRC_SCHED_WAKE           (TRC_SCHED_VERBOSE +  4)
+#define TRC_SCHED_YIELD          (TRC_SCHED_VERBOSE +  5)
+#define TRC_SCHED_BLOCK          (TRC_SCHED_VERBOSE +  6)
+#define TRC_SCHED_SHUTDOWN       (TRC_SCHED_VERBOSE +  7)
+#define TRC_SCHED_CTL            (TRC_SCHED_VERBOSE +  8)
+#define TRC_SCHED_ADJDOM         (TRC_SCHED_VERBOSE +  9)
+#define TRC_SCHED_SWITCH         (TRC_SCHED_VERBOSE + 10)
+#define TRC_SCHED_S_TIMER_FN     (TRC_SCHED_VERBOSE + 11)
+#define TRC_SCHED_T_TIMER_FN     (TRC_SCHED_VERBOSE + 12)
+#define TRC_SCHED_DOM_TIMER_FN   (TRC_SCHED_VERBOSE + 13)
+#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
+#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
+
+#define TRC_MEM_PAGE_GRANT_MAP      (TRC_MEM + 1)
+#define TRC_MEM_PAGE_GRANT_UNMAP    (TRC_MEM + 2)
+#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3)
+
+#define TRC_PV_HYPERCALL             (TRC_PV +  1)
+#define TRC_PV_TRAP                  (TRC_PV +  3)
+#define TRC_PV_PAGE_FAULT            (TRC_PV +  4)
+#define TRC_PV_FORCED_INVALID_OP     (TRC_PV +  5)
+#define TRC_PV_EMULATE_PRIVOP        (TRC_PV +  6)
+#define TRC_PV_EMULATE_4GB           (TRC_PV +  7)
+#define TRC_PV_MATH_STATE_RESTORE    (TRC_PV +  8)
+#define TRC_PV_PAGING_FIXUP          (TRC_PV +  9)
+#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV + 10)
+#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_64_FLAG               (0x100) 
+
+#define TRC_SHADOW_NOT_SHADOW                 (TRC_SHADOW +  1)
+#define TRC_SHADOW_FAST_PROPAGATE             (TRC_SHADOW +  2)
+#define TRC_SHADOW_FAST_MMIO                  (TRC_SHADOW +  3)
+#define TRC_SHADOW_FALSE_FAST_PATH            (TRC_SHADOW +  4)
+#define TRC_SHADOW_MMIO                       (TRC_SHADOW +  5)
+#define TRC_SHADOW_FIXUP                      (TRC_SHADOW +  6)
+#define TRC_SHADOW_DOMF_DYING                 (TRC_SHADOW +  7)
+#define TRC_SHADOW_EMULATE                    (TRC_SHADOW +  8)
+#define TRC_SHADOW_EMULATE_UNSHADOW_USER      (TRC_SHADOW +  9)
+#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ    (TRC_SHADOW + 10)
+#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11)
+#define TRC_SHADOW_WRMAP_BF                   (TRC_SHADOW + 12)
+#define TRC_SHADOW_PREALLOC_UNPIN             (TRC_SHADOW + 13)
+#define TRC_SHADOW_RESYNC_FULL                (TRC_SHADOW + 14)
+#define TRC_SHADOW_RESYNC_ONLY                (TRC_SHADOW + 15)
+
+/* 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 + 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)
+#define TRC_HVM_MSR_WRITE       (TRC_HVM_HANDLER + 0x0D)
+#define TRC_HVM_CPUID           (TRC_HVM_HANDLER + 0x0E)
+#define TRC_HVM_INTR            (TRC_HVM_HANDLER + 0x0F)
+#define TRC_HVM_NMI             (TRC_HVM_HANDLER + 0x10)
+#define TRC_HVM_SMI             (TRC_HVM_HANDLER + 0x11)
+#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_IOPORT_READ     (TRC_HVM_HANDLER + 0x16)
+#define TRC_HVM_IOMEM_READ      (TRC_HVM_HANDLER + 0x17)
+#define TRC_HVM_CLTS            (TRC_HVM_HANDLER + 0x18)
+#define TRC_HVM_LMSW            (TRC_HVM_HANDLER + 0x19)
+#define TRC_HVM_LMSW64          (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19)
+#define TRC_HVM_INTR_WINDOW     (TRC_HVM_HANDLER + 0x20)
+#define TRC_HVM_IOPORT_WRITE    (TRC_HVM_HANDLER + 0x216)
+#define TRC_HVM_IOMEM_WRITE     (TRC_HVM_HANDLER + 0x217)
+
+/* trace subclasses for power management */
+#define TRC_PM_FREQ     0x00801000      /* xen cpu freq events */
+#define TRC_PM_IDLE     0x00802000      /* xen cpu idle events */
+
+/* trace events for per class */
+#define TRC_PM_FREQ_CHANGE      (TRC_PM_FREQ + 0x01)
+#define TRC_PM_IDLE_ENTRY       (TRC_PM_IDLE + 0x01)
+#define TRC_PM_IDLE_EXIT        (TRC_PM_IDLE + 0x02)
+
+/* This structure represents a single trace buffer record. */
+struct t_rec {
+    uint32_t event:28;
+    uint32_t extra_u32:3;         /* # entries in trailing extra_u32[] array */
+    uint32_t cycles_included:1;   /* u.cycles or u.no_cycles? */
+    union {
+        struct {
+            uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
+            uint32_t extra_u32[7];         /* event data items */
+        } cycles;
+        struct {
+            uint32_t extra_u32[7];         /* event data items */
+        } nocycles;
+    } u;
+};
+
+/*
+ * This structure contains the metadata for a single trace buffer.  The head
+ * 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.    */
+};
+
+#endif /* __XEN_PUBLIC_TRACE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/domctl.h
+++ linux-ec2-2.6.32/include/xen/interface/domctl.h
@@ -0,0 +1,710 @@
+/******************************************************************************
+ * domctl.h
+ * 
+ * Domain management operations. For use by node control stack.
+ * 
+ * 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) 2002-2003, B Dragovic
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_DOMCTL_H__
+#define __XEN_PUBLIC_DOMCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "domctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+
+#define XEN_DOMCTL_INTERFACE_VERSION 0x00000005
+
+struct xenctl_cpumap {
+    XEN_GUEST_HANDLE_64(uint8) bitmap;
+    uint32_t nr_cpus;
+};
+
+/*
+ * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
+ * If it is specified as zero, an id is auto-allocated and returned.
+ */
+#define XEN_DOMCTL_createdomain       1
+struct xen_domctl_createdomain {
+    /* IN parameters */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+ /* 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)
+ /* Should domain memory integrity be verifed by tboot during Sx? */
+#define _XEN_DOMCTL_CDF_s3_integrity  2
+#define XEN_DOMCTL_CDF_s3_integrity   (1U<<_XEN_DOMCTL_CDF_s3_integrity)
+    uint32_t flags;
+};
+typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
+
+#define XEN_DOMCTL_destroydomain      2
+#define XEN_DOMCTL_pausedomain        3
+#define XEN_DOMCTL_unpausedomain      4
+#define XEN_DOMCTL_resumedomain      27
+
+#define XEN_DOMCTL_getdomaininfo      5
+struct xen_domctl_getdomaininfo {
+    /* OUT variables. */
+    domid_t  domain;              /* Also echoed in domctl.domain */
+ /* Domain is scheduled to die. */
+#define _XEN_DOMINF_dying     0
+#define XEN_DOMINF_dying      (1U<<_XEN_DOMINF_dying)
+ /* Domain is an HVM guest (as opposed to a PV guest). */
+#define _XEN_DOMINF_hvm_guest 1
+#define XEN_DOMINF_hvm_guest  (1U<<_XEN_DOMINF_hvm_guest)
+ /* The guest OS has shut down. */
+#define _XEN_DOMINF_shutdown  2
+#define XEN_DOMINF_shutdown   (1U<<_XEN_DOMINF_shutdown)
+ /* Currently paused by control software. */
+#define _XEN_DOMINF_paused    3
+#define XEN_DOMINF_paused     (1U<<_XEN_DOMINF_paused)
+ /* Currently blocked pending an event.     */
+#define _XEN_DOMINF_blocked   4
+#define XEN_DOMINF_blocked    (1U<<_XEN_DOMINF_blocked)
+ /* Domain is currently running.            */
+#define _XEN_DOMINF_running   5
+#define XEN_DOMINF_running    (1U<<_XEN_DOMINF_running)
+ /* Being debugged.  */
+#define _XEN_DOMINF_debugged  6
+#define XEN_DOMINF_debugged   (1U<<_XEN_DOMINF_debugged)
+ /* CPU to which this domain is bound.      */
+#define XEN_DOMINF_cpumask      255
+#define XEN_DOMINF_cpushift       8
+ /* XEN_DOMINF_shutdown guest-supplied code.  */
+#define XEN_DOMINF_shutdownmask 255
+#define XEN_DOMINF_shutdownshift 16
+    uint32_t flags;              /* XEN_DOMINF_* */
+    uint64_aligned_t tot_pages;
+    uint64_aligned_t max_pages;
+    uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
+    uint64_aligned_t cpu_time;
+    uint32_t nr_online_vcpus;    /* Number of VCPUs currently online. */
+    uint32_t max_vcpu_id;        /* Maximum VCPUID in use by this domain. */
+    uint32_t ssidref;
+    xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t);
+
+
+#define XEN_DOMCTL_getmemlist         6
+struct xen_domctl_getmemlist {
+    /* IN variables. */
+    /* Max entries to write to output buffer. */
+    uint64_aligned_t max_pfns;
+    /* Start index in guest's page list. */
+    uint64_aligned_t start_pfn;
+    XEN_GUEST_HANDLE_64(uint64) buffer;
+    /* OUT variables. */
+    uint64_aligned_t num_pfns;
+};
+typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t);
+
+
+#define XEN_DOMCTL_getpageframeinfo   7
+
+#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28
+#define XEN_DOMCTL_PFINFO_NOTAB   (0x0U<<28)
+#define XEN_DOMCTL_PFINFO_L1TAB   (0x1U<<28)
+#define XEN_DOMCTL_PFINFO_L2TAB   (0x2U<<28)
+#define XEN_DOMCTL_PFINFO_L3TAB   (0x3U<<28)
+#define XEN_DOMCTL_PFINFO_L4TAB   (0x4U<<28)
+#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28)
+#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31)
+#define XEN_DOMCTL_PFINFO_XTAB    (0xfU<<28) /* invalid page */
+#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28)
+
+struct xen_domctl_getpageframeinfo {
+    /* IN variables. */
+    uint64_aligned_t gmfn; /* GMFN to query */
+    /* OUT variables. */
+    /* Is the page PINNED to a type? */
+    uint32_t type;         /* see above type defs */
+};
+typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t);
+
+
+#define XEN_DOMCTL_getpageframeinfo2  8
+struct xen_domctl_getpageframeinfo2 {
+    /* IN variables. */
+    uint64_aligned_t num;
+    /* IN/OUT variables. */
+    XEN_GUEST_HANDLE_64(uint32) array;
+};
+typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t);
+
+
+/*
+ * Control shadow pagetables operation
+ */
+#define XEN_DOMCTL_shadow_op         10
+
+/* Disable shadow mode. */
+#define XEN_DOMCTL_SHADOW_OP_OFF         0
+
+/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE      32
+
+/* Log-dirty bitmap operations. */
+ /* Return the bitmap and clean internal copy for next round. */
+#define XEN_DOMCTL_SHADOW_OP_CLEAN       11
+ /* Return the bitmap but do not modify internal copy. */
+#define XEN_DOMCTL_SHADOW_OP_PEEK        12
+
+/* Memory allocation accessors. */
+#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION   30
+#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION   31
+
+/* Legacy enable operations. */
+ /* Equiv. to ENABLE with no mode flags. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST       1
+ /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY   2
+ /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */
+#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE  3
+
+/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */
+ /*
+  * Shadow pagetables are refcounted: guest does not use explicit mmu
+  * operations nor write-protect its pagetables.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT  (1 << 1)
+ /*
+  * Log pages in a bitmap as they are dirtied.
+  * Used for live relocation to determine which pages must be re-sent.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
+ /*
+  * Automatically translate GPFNs into MFNs.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
+ /*
+  * Xen does not steal virtual address space from the guest.
+  * Requires HVM support.
+  */
+#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL  (1 << 4)
+
+struct xen_domctl_shadow_op_stats {
+    uint32_t fault_count;
+    uint32_t dirty_count;
+};
+typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t);
+
+struct xen_domctl_shadow_op {
+    /* IN variables. */
+    uint32_t       op;       /* XEN_DOMCTL_SHADOW_OP_* */
+
+    /* OP_ENABLE */
+    uint32_t       mode;     /* XEN_DOMCTL_SHADOW_ENABLE_* */
+
+    /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */
+    uint32_t       mb;       /* Shadow memory allocation in MB */
+
+    /* OP_PEEK / OP_CLEAN */
+    XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
+    uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */
+    struct xen_domctl_shadow_op_stats stats;
+};
+typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t);
+
+
+#define XEN_DOMCTL_max_mem           11
+struct xen_domctl_max_mem {
+    /* IN variables. */
+    uint64_aligned_t max_memkb;
+};
+typedef struct xen_domctl_max_mem xen_domctl_max_mem_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t);
+
+
+#define XEN_DOMCTL_setvcpucontext    12
+#define XEN_DOMCTL_getvcpucontext    13
+struct xen_domctl_vcpucontext {
+    uint32_t              vcpu;                  /* IN */
+    XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t);
+
+
+#define XEN_DOMCTL_getvcpuinfo       14
+struct xen_domctl_getvcpuinfo {
+    /* IN variables. */
+    uint32_t vcpu;
+    /* OUT variables. */
+    uint8_t  online;                  /* currently online (not hotplugged)? */
+    uint8_t  blocked;                 /* blocked waiting for an event? */
+    uint8_t  running;                 /* currently scheduled on its CPU? */
+    uint64_aligned_t cpu_time;        /* total cpu time consumed (ns) */
+    uint32_t cpu;                     /* current mapping   */
+};
+typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t);
+
+
+/* Get/set which physical cpus a vcpu can execute on. */
+#define XEN_DOMCTL_setvcpuaffinity    9
+#define XEN_DOMCTL_getvcpuaffinity   25
+struct xen_domctl_vcpuaffinity {
+    uint32_t  vcpu;              /* IN */
+    struct xenctl_cpumap cpumap; /* IN/OUT */
+};
+typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t);
+
+
+#define XEN_DOMCTL_max_vcpus         15
+struct xen_domctl_max_vcpus {
+    uint32_t max;           /* maximum number of vcpus */
+};
+typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t);
+
+
+#define XEN_DOMCTL_scheduler_op      16
+/* Scheduler types. */
+#define XEN_SCHEDULER_SEDF     4
+#define XEN_SCHEDULER_CREDIT   5
+/* Set or get info? */
+#define XEN_DOMCTL_SCHEDOP_putinfo 0
+#define XEN_DOMCTL_SCHEDOP_getinfo 1
+struct xen_domctl_scheduler_op {
+    uint32_t sched_id;  /* XEN_SCHEDULER_* */
+    uint32_t cmd;       /* XEN_DOMCTL_SCHEDOP_* */
+    union {
+        struct xen_domctl_sched_sedf {
+            uint64_aligned_t period;
+            uint64_aligned_t slice;
+            uint64_aligned_t latency;
+            uint32_t extratime;
+            uint32_t weight;
+        } sedf;
+        struct xen_domctl_sched_credit {
+            uint16_t weight;
+            uint16_t cap;
+        } credit;
+    } u;
+};
+typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t);
+
+
+#define XEN_DOMCTL_setdomainhandle   17
+struct xen_domctl_setdomainhandle {
+    xen_domain_handle_t handle;
+};
+typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t);
+
+
+#define XEN_DOMCTL_setdebugging      18
+struct xen_domctl_setdebugging {
+    uint8_t enable;
+};
+typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t);
+
+
+#define XEN_DOMCTL_irq_permission    19
+struct xen_domctl_irq_permission {
+    uint8_t pirq;
+    uint8_t allow_access;    /* flag to specify enable/disable of IRQ access */
+};
+typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t);
+
+
+#define XEN_DOMCTL_iomem_permission  20
+struct xen_domctl_iomem_permission {
+    uint64_aligned_t first_mfn;/* first page (physical page number) in range */
+    uint64_aligned_t nr_mfns;  /* number of pages in range (>0) */
+    uint8_t  allow_access;     /* allow (!0) or deny (0) access to range? */
+};
+typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t);
+
+
+#define XEN_DOMCTL_ioport_permission 21
+struct xen_domctl_ioport_permission {
+    uint32_t first_port;              /* first port int range */
+    uint32_t nr_ports;                /* size of port range */
+    uint8_t  allow_access;            /* allow or deny access to range? */
+};
+typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t);
+
+
+#define XEN_DOMCTL_hypercall_init    22
+struct xen_domctl_hypercall_init {
+    uint64_aligned_t  gmfn;           /* GMFN to be initialised */
+};
+typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
+
+
+#define XEN_DOMCTL_arch_setup        23
+#define _XEN_DOMAINSETUP_hvm_guest 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__
+    uint64_aligned_t bp;     /* mpaddr of boot param area */
+    uint64_aligned_t maxmem; /* Highest memory address for MDT.  */
+    uint64_aligned_t xsi_va; /* Xen shared_info area virtual address.  */
+    uint32_t hypercall_imm;  /* Break imm for Xen hypercalls.  */
+    int8_t vhpt_size_log2;   /* Log2 of VHPT size. */
+#endif
+} xen_domctl_arch_setup_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t);
+
+
+#define XEN_DOMCTL_settimeoffset     24
+struct xen_domctl_settimeoffset {
+    int32_t  time_offset_seconds; /* applied to domain wallclock time */
+};
+typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
+
+ 
+#define XEN_DOMCTL_gethvmcontext     33
+#define XEN_DOMCTL_sethvmcontext     34
+typedef struct xen_domctl_hvmcontext {
+    uint32_t size; /* IN/OUT: size of buffer / bytes filled */
+    XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call
+                                        * gethvmcontext with NULL
+                                        * buffer to get size req'd */
+} xen_domctl_hvmcontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t);
+
+
+#define XEN_DOMCTL_set_address_size  35
+#define XEN_DOMCTL_get_address_size  36
+typedef struct xen_domctl_address_size {
+    uint32_t size;
+} xen_domctl_address_size_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t);
+
+
+#define XEN_DOMCTL_real_mode_area    26
+struct xen_domctl_real_mode_area {
+    uint32_t log; /* log2 of Real Mode Area size */
+};
+typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t);
+
+
+#define XEN_DOMCTL_sendtrigger       28
+#define XEN_DOMCTL_SENDTRIGGER_NMI    0
+#define XEN_DOMCTL_SENDTRIGGER_RESET  1
+#define XEN_DOMCTL_SENDTRIGGER_INIT   2
+#define XEN_DOMCTL_SENDTRIGGER_POWER  3
+struct xen_domctl_sendtrigger {
+    uint32_t  trigger;  /* IN */
+    uint32_t  vcpu;     /* IN */
+};
+typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t);
+
+
+/* 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_MSI,
+    PT_IRQ_TYPE_MSI_TRANSLATE,
+} pt_irq_type_t;
+struct xen_domctl_bind_pt_irq {
+    uint32_t machine_irq;
+    pt_irq_type_t irq_type;
+    uint32_t hvm_domid;
+
+    union {
+        struct {
+            uint8_t isa_irq;
+        } isa;
+        struct {
+            uint8_t bus;
+            uint8_t device;
+            uint8_t intx;
+        } pci;
+        struct {
+            uint8_t gvec;
+            uint32_t gflags;
+            uint64_aligned_t gtable;
+        } msi;
+    } u;
+};
+typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t);
+
+
+/* Bind machine I/O address range -> HVM address range. */
+#define XEN_DOMCTL_memory_mapping    39
+#define DPCI_ADD_MAPPING         1
+#define DPCI_REMOVE_MAPPING      0
+struct xen_domctl_memory_mapping {
+    uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */
+    uint64_aligned_t first_mfn; /* first page (machine page) in range */
+    uint64_aligned_t nr_mfns;   /* number of pages in range (>0) */
+    uint32_t add_mapping;       /* add or remove mapping */
+    uint32_t padding;           /* padding for 64-bit aligned structure */
+};
+typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t);
+
+
+/* Bind machine I/O port range -> HVM I/O port range. */
+#define XEN_DOMCTL_ioport_mapping    40
+struct xen_domctl_ioport_mapping {
+    uint32_t first_gport;     /* first guest IO port*/
+    uint32_t first_mport;     /* first machine IO port */
+    uint32_t nr_ports;        /* size of port range */
+    uint32_t add_mapping;     /* add or remove mapping */
+};
+typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t);
+
+
+/*
+ * Pin caching type of RAM space for x86 HVM domU.
+ */
+#define XEN_DOMCTL_pin_mem_cacheattr 41
+/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */
+#define XEN_DOMCTL_MEM_CACHEATTR_UC  0
+#define XEN_DOMCTL_MEM_CACHEATTR_WC  1
+#define XEN_DOMCTL_MEM_CACHEATTR_WT  4
+#define XEN_DOMCTL_MEM_CACHEATTR_WP  5
+#define XEN_DOMCTL_MEM_CACHEATTR_WB  6
+#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7
+struct xen_domctl_pin_mem_cacheattr {
+    uint64_aligned_t start, end;
+    unsigned int type; /* XEN_DOMCTL_MEM_CACHEATTR_* */
+};
+typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t);
+
+
+#define XEN_DOMCTL_set_ext_vcpucontext 42
+#define XEN_DOMCTL_get_ext_vcpucontext 43
+struct xen_domctl_ext_vcpucontext {
+    /* IN: VCPU that this call applies to. */
+    uint32_t         vcpu;
+    /*
+     * SET: Size of struct (IN)
+     * GET: Size of struct (OUT)
+     */
+    uint32_t         size;
+#if defined(__i386__) || defined(__x86_64__)
+    /* SYSCALL from 32-bit mode and SYSENTER callback information. */
+    /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */
+    uint64_aligned_t syscall32_callback_eip;
+    uint64_aligned_t sysenter_callback_eip;
+    uint16_t         syscall32_callback_cs;
+    uint16_t         sysenter_callback_cs;
+    uint8_t          syscall32_disables_events;
+    uint8_t          sysenter_disables_events;
+#endif
+};
+typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t);
+
+/*
+ * Set optimizaton features for a domain
+ */
+#define XEN_DOMCTL_set_opt_feature    44
+struct xen_domctl_set_opt_feature {
+#if defined(__ia64__)
+    struct xen_ia64_opt_feature optf;
+#else
+    /* Make struct non-empty: do not depend on this field name! */
+    uint64_t dummy;
+#endif
+};
+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
+
+/*
+ * Do not inject spurious page faults into this domain.
+ */
+#define XEN_DOMCTL_suppress_spurious_page_faults 53
+
+#define XEN_DOMCTL_debug_op    54
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF         0
+#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON          1
+struct xen_domctl_debug_op {
+    uint32_t op;   /* IN */
+    uint32_t vcpu; /* IN */
+};
+typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
+
+/*
+ * Request a particular record from the HVM context
+ */
+#define XEN_DOMCTL_gethvmcontext_partial   55
+typedef struct xen_domctl_hvmcontext_partial {
+    uint32_t type;                      /* IN: Type of record required */
+    uint32_t instance;                  /* IN: Instance of that type */
+    XEN_GUEST_HANDLE_64(uint8) buffer;  /* OUT: buffer to write record into */
+} xen_domctl_hvmcontext_partial_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
+
+
+struct xen_domctl {
+    uint32_t cmd;
+    uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
+    domid_t  domain;
+    union {
+        struct xen_domctl_createdomain      createdomain;
+        struct xen_domctl_getdomaininfo     getdomaininfo;
+        struct xen_domctl_getmemlist        getmemlist;
+        struct xen_domctl_getpageframeinfo  getpageframeinfo;
+        struct xen_domctl_getpageframeinfo2 getpageframeinfo2;
+        struct xen_domctl_vcpuaffinity      vcpuaffinity;
+        struct xen_domctl_shadow_op         shadow_op;
+        struct xen_domctl_max_mem           max_mem;
+        struct xen_domctl_vcpucontext       vcpucontext;
+        struct xen_domctl_getvcpuinfo       getvcpuinfo;
+        struct xen_domctl_max_vcpus         max_vcpus;
+        struct xen_domctl_scheduler_op      scheduler_op;
+        struct xen_domctl_setdomainhandle   setdomainhandle;
+        struct xen_domctl_setdebugging      setdebugging;
+        struct xen_domctl_irq_permission    irq_permission;
+        struct xen_domctl_iomem_permission  iomem_permission;
+        struct xen_domctl_ioport_permission ioport_permission;
+        struct xen_domctl_hypercall_init    hypercall_init;
+        struct xen_domctl_arch_setup        arch_setup;
+        struct xen_domctl_settimeoffset     settimeoffset;
+        struct xen_domctl_real_mode_area    real_mode_area;
+        struct xen_domctl_hvmcontext        hvmcontext;
+        struct xen_domctl_hvmcontext_partial hvmcontext_partial;
+        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;
+        struct xen_domctl_ioport_mapping    ioport_mapping;
+        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;
+        struct xen_domctl_debug_op          debug_op;
+#if defined(__i386__) || defined(__x86_64__)
+        struct xen_domctl_cpuid             cpuid;
+#endif
+        uint8_t                             pad[128];
+    } u;
+};
+typedef struct xen_domctl xen_domctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_t);
+
+#endif /* __XEN_PUBLIC_DOMCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/vcpu.h
+++ linux-ec2-2.6.32/include/xen/interface/vcpu.h
@@ -27,11 +27,13 @@
 #ifndef __XEN_PUBLIC_VCPU_H__
 #define __XEN_PUBLIC_VCPU_H__
 
+#include "xen.h"
+
 /*
  * Prototype for this hypercall is:
- *	int vcpu_op(int cmd, int vcpuid, void *extra_args)
- * @cmd		   == VCPUOP_??? (VCPU operation).
- * @vcpuid	   == VCPU to operate on.
+ *  int vcpu_op(int cmd, int vcpuid, void *extra_args)
+ * @cmd        == VCPUOP_??? (VCPU operation).
+ * @vcpuid     == VCPU to operate on.
  * @extra_args == Operation-specific extra arguments (NULL if none).
  */
 
@@ -40,52 +42,54 @@
  * newly-initialised VCPU will not run until it is brought up by VCPUOP_up.
  *
  * @extra_arg == pointer to vcpu_guest_context structure containing initial
- *				 state for the VCPU.
+ *               state for the VCPU.
  */
-#define VCPUOP_initialise			 0
+#define VCPUOP_initialise            0
 
 /*
  * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
  * if the VCPU has not been initialised (VCPUOP_initialise).
  */
-#define VCPUOP_up					 1
+#define VCPUOP_up                    1
 
 /*
  * Bring down a VCPU (i.e., make it non-runnable).
  * There are a few caveats that callers should observe:
- *	1. This operation may return, and VCPU_is_up may return false, before the
- *	   VCPU stops running (i.e., the command is asynchronous). It is a good
- *	   idea to ensure that the VCPU has entered a non-critical loop before
- *	   bringing it down. Alternatively, this operation is guaranteed
- *	   synchronous if invoked by the VCPU itself.
- *	2. After a VCPU is initialised, there is currently no way to drop all its
- *	   references to domain memory. Even a VCPU that is down still holds
- *	   memory references via its pagetable base pointer and GDT. It is good
- *	   practise to move a VCPU onto an 'idle' or default page table, LDT and
- *	   GDT before bringing it down.
+ *  1. This operation may return, and VCPU_is_up may return false, before the
+ *     VCPU stops running (i.e., the command is asynchronous). It is a good
+ *     idea to ensure that the VCPU has entered a non-critical loop before
+ *     bringing it down. Alternatively, this operation is guaranteed
+ *     synchronous if invoked by the VCPU itself.
+ *  2. After a VCPU is initialised, there is currently no way to drop all its
+ *     references to domain memory. Even a VCPU that is down still holds
+ *     memory references via its pagetable base pointer and GDT. It is good
+ *     practise to move a VCPU onto an 'idle' or default page table, LDT and
+ *     GDT before bringing it down.
  */
-#define VCPUOP_down					 2
+#define VCPUOP_down                  2
 
 /* Returns 1 if the given VCPU is up. */
-#define VCPUOP_is_up				 3
+#define VCPUOP_is_up                 3
 
 /*
  * Return information about the state and running time of a VCPU.
  * @extra_arg == pointer to vcpu_runstate_info structure.
  */
-#define VCPUOP_get_runstate_info	 4
+#define VCPUOP_get_runstate_info     4
 struct vcpu_runstate_info {
-		/* VCPU's current state (RUNSTATE_*). */
-		int		 state;
-		/* When was current state entered (system time, ns)? */
-		uint64_t state_entry_time;
-		/*
-		 * Time spent in each RUNSTATE_* (ns). The sum of these times is
-		 * guaranteed not to drift from system time.
-		 */
-		uint64_t time[4];
+    /* VCPU's current state (RUNSTATE_*). */
+    int      state;
+    /* When was current state entered (system time, ns)? */
+    uint64_t state_entry_time;
+    /*
+     * Time spent in each RUNSTATE_* (ns). The sum of these times is
+     * guaranteed not to drift from system time.
+     */
+    uint64_t time[4];
 };
 DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);
+typedef struct vcpu_runstate_info vcpu_runstate_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t);
 
 /* VCPU is currently running on a physical CPU. */
 #define RUNSTATE_running  0
@@ -108,47 +112,54 @@
  * Register a shared memory area from which the guest may obtain its own
  * runstate information without needing to execute a hypercall.
  * Notes:
- *	1. The registered address may be virtual or physical, depending on the
- *	   platform. The virtual address should be registered on x86 systems.
- *	2. Only one shared area may be registered per VCPU. The shared area is
- *	   updated by the hypervisor each time the VCPU is scheduled. Thus
- *	   runstate.state will always be RUNSTATE_running and
- *	   runstate.state_entry_time will indicate the system time at which the
- *	   VCPU was last scheduled to run.
+ *  1. The registered address may be virtual or physical or guest handle,
+ *     depending on the platform. Virtual address or guest handle should be
+ *     registered on x86 systems.
+ *  2. Only one shared area may be registered per VCPU. The shared area is
+ *     updated by the hypervisor each time the VCPU is scheduled. Thus
+ *     runstate.state will always be RUNSTATE_running and
+ *     runstate.state_entry_time will indicate the system time at which the
+ *     VCPU was last scheduled to run.
  * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
  */
 #define VCPUOP_register_runstate_memory_area 5
 struct vcpu_register_runstate_memory_area {
-		union {
-				GUEST_HANDLE(vcpu_runstate_info) h;
-				struct vcpu_runstate_info *v;
-				uint64_t p;
-		} addr;
+    union {
+        XEN_GUEST_HANDLE(vcpu_runstate_info_t) h;
+        struct vcpu_runstate_info *v;
+        uint64_t p;
+    } addr;
 };
+typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
 
 /*
  * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
  * which can be set via these commands. Periods smaller than one millisecond
  * may not be supported.
  */
-#define VCPUOP_set_periodic_timer	 6 /* arg == vcpu_set_periodic_timer_t */
-#define VCPUOP_stop_periodic_timer	 7 /* arg == NULL */
+#define VCPUOP_set_periodic_timer    6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer   7 /* arg == NULL */
 struct vcpu_set_periodic_timer {
-		uint64_t period_ns;
+    uint64_t period_ns;
 };
 DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_timer);
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
 
 /*
  * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
  * timer which can be set via these commands.
  */
-#define VCPUOP_set_singleshot_timer	 8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_set_singleshot_timer  8 /* arg == vcpu_set_singleshot_timer_t */
 #define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
 struct vcpu_set_singleshot_timer {
-		uint64_t timeout_abs_ns;
-		uint32_t flags;			   /* VCPU_SSHOTTMR_??? */
+    uint64_t timeout_abs_ns;   /* Absolute system time value in nanoseconds. */
+    uint32_t flags;            /* VCPU_SSHOTTMR_??? */
 };
 DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_timer);
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
 
 /* Flags to VCPUOP_set_singleshot_timer. */
  /* Require the timeout to be in the future (return -ETIME if it's passed). */
@@ -161,13 +172,38 @@
  * structure in a convenient place, such as in a per-cpu data area.
  * The pointer need not be page aligned, but the structure must not
  * cross a page boundary.
+ *
+ * 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 */
     uint32_t rsvd;   /* unused */
 };
 DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_info);
+typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t);
+
+/* 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__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/platform.h
+++ linux-ec2-2.6.32/include/xen/interface/platform.h
@@ -0,0 +1,357 @@
+/******************************************************************************
+ * platform.h
+ * 
+ * Hardware platform operations. Intended for use by domain-0 kernel.
+ * 
+ * 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) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_PLATFORM_H__
+#define __XEN_PUBLIC_PLATFORM_H__
+
+#include "xen.h"
+
+#define XENPF_INTERFACE_VERSION 0x03000001
+
+/*
+ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
+ * 1 January, 1970 if the current system time was <system_time>.
+ */
+#define XENPF_settime             17
+struct xenpf_settime {
+    /* IN variables. */
+    uint32_t secs;
+    uint32_t nsecs;
+    uint64_t system_time;
+};
+typedef struct xenpf_settime xenpf_settime_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
+
+/*
+ * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type.
+ * On x86, @type is an architecture-defined MTRR memory type.
+ * On success, returns the MTRR that was used (@reg) and a handle that can
+ * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting.
+ * (x86-specific).
+ */
+#define XENPF_add_memtype         31
+struct xenpf_add_memtype {
+    /* IN variables. */
+    xen_pfn_t mfn;
+    uint64_t nr_mfns;
+    uint32_t type;
+    /* OUT variables. */
+    uint32_t handle;
+    uint32_t reg;
+};
+typedef struct xenpf_add_memtype xenpf_add_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t);
+
+/*
+ * Tear down an existing memory-range type. If @handle is remembered then it
+ * should be passed in to accurately tear down the correct setting (in case
+ * of overlapping memory regions with differing types). If it is not known
+ * then @handle should be set to zero. In all cases @reg must be set.
+ * (x86-specific).
+ */
+#define XENPF_del_memtype         32
+struct xenpf_del_memtype {
+    /* IN variables. */
+    uint32_t handle;
+    uint32_t reg;
+};
+typedef struct xenpf_del_memtype xenpf_del_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t);
+
+/* Read current type of an MTRR (x86-specific). */
+#define XENPF_read_memtype        33
+struct xenpf_read_memtype {
+    /* IN variables. */
+    uint32_t reg;
+    /* OUT variables. */
+    xen_pfn_t mfn;
+    uint64_t nr_mfns;
+    uint32_t type;
+};
+typedef struct xenpf_read_memtype xenpf_read_memtype_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t);
+
+#define XENPF_microcode_update    35
+struct xenpf_microcode_update {
+    /* IN variables. */
+    XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */
+    uint32_t length;                  /* Length of microcode data. */
+};
+typedef struct xenpf_microcode_update xenpf_microcode_update_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t);
+
+#define XENPF_platform_quirk      39
+#define QUIRK_NOIRQBALANCING      1 /* Do not restrict IO-APIC RTE targets */
+#define QUIRK_IOAPIC_BAD_REGSEL   2 /* IO-APIC REGSEL forgets its value    */
+#define QUIRK_IOAPIC_GOOD_REGSEL  3 /* IO-APIC REGSEL behaves properly     */
+struct xenpf_platform_quirk {
+    /* IN variables. */
+    uint32_t quirk_id;
+};
+typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t);
+
+#define XENPF_firmware_info       50
+#define XEN_FW_DISK_INFO          1 /* from int 13 AH=08/41/48 */
+#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
+#define XEN_FW_VBEDDC_INFO        3 /* from int 10 AX=4f15 */
+struct xenpf_firmware_info {
+    /* IN variables. */
+    uint32_t type;
+    uint32_t index;
+    /* OUT variables. */
+    union {
+        struct {
+            /* Int13, Fn48: Check Extensions Present. */
+            uint8_t device;                   /* %dl: bios device number */
+            uint8_t version;                  /* %ah: major version      */
+            uint16_t interface_support;       /* %cx: support bitmap     */
+            /* Int13, Fn08: Legacy Get Device Parameters. */
+            uint16_t legacy_max_cylinder;     /* %cl[7:6]:%ch: max cyl # */
+            uint8_t legacy_max_head;          /* %dh: max head #         */
+            uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector #  */
+            /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */
+            /* NB. First uint16_t of buffer must be set to buffer size.      */
+            XEN_GUEST_HANDLE(void) edd_params;
+        } disk_info; /* XEN_FW_DISK_INFO */
+        struct {
+            uint8_t device;                   /* bios device number  */
+            uint32_t mbr_signature;           /* offset 0x1b8 in mbr */
+        } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */
+        struct {
+            /* Int10, AX=4F15: Get EDID info. */
+            uint8_t capabilities;
+            uint8_t edid_transfer_time;
+            /* must refer to 128-byte buffer */
+            XEN_GUEST_HANDLE(uint8) edid;
+        } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
+    } u;
+};
+typedef struct xenpf_firmware_info xenpf_firmware_info_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t);
+
+#define XENPF_enter_acpi_sleep    51
+struct xenpf_enter_acpi_sleep {
+    /* IN variables */
+    uint16_t pm1a_cnt_val;      /* PM1a control value. */
+    uint16_t pm1b_cnt_val;      /* PM1b control value. */
+    uint32_t sleep_state;       /* Which state to enter (Sn). */
+    uint32_t flags;             /* Must be zero. */
+};
+typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t);
+
+#define XENPF_change_freq         52
+struct xenpf_change_freq {
+    /* IN variables */
+    uint32_t flags; /* Must be zero. */
+    uint32_t cpu;   /* Physical cpu. */
+    uint64_t freq;  /* New frequency (Hz). */
+};
+typedef struct xenpf_change_freq xenpf_change_freq_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t);
+
+/*
+ * Get idle times (nanoseconds since boot) for physical CPUs specified in the
+ * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is
+ * indexed by CPU number; only entries with the corresponding @cpumap_bitmap
+ * bit set are written to. On return, @cpumap_bitmap is modified so that any
+ * non-existent CPUs are cleared. Such CPUs have their @idletime array entry
+ * cleared.
+ */
+#define XENPF_getidletime         53
+struct xenpf_getidletime {
+    /* IN/OUT variables */
+    /* IN: CPUs to interrogate; OUT: subset of IN which are present */
+    XEN_GUEST_HANDLE(uint8) cpumap_bitmap;
+    /* IN variables */
+    /* Size of cpumap bitmap. */
+    uint32_t cpumap_nr_cpus;
+    /* Must be indexable for every cpu in cpumap_bitmap. */
+    XEN_GUEST_HANDLE(uint64) idletime;
+    /* OUT variables */
+    /* System time when the idletime snapshots were taken. */
+    uint64_t now;
+};
+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 platform_limit;  /* 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 */
+    } u;
+};
+typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t);
+
+#define XENPF_get_cpu_freq        ('N' << 24)
+struct xenpf_get_cpu_freq {
+    /* IN variables */
+    uint32_t vcpu;
+    /* OUT variables */
+    uint32_t freq; /* in kHz */
+};
+typedef struct xenpf_get_cpu_freq xenpf_get_cpu_freq_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_get_cpu_freq_t);
+
+struct xen_platform_op {
+    uint32_t cmd;
+    uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
+    union {
+        struct xenpf_settime           settime;
+        struct xenpf_add_memtype       add_memtype;
+        struct xenpf_del_memtype       del_memtype;
+        struct xenpf_read_memtype      read_memtype;
+        struct xenpf_microcode_update  microcode;
+        struct xenpf_platform_quirk    platform_quirk;
+        struct xenpf_firmware_info     firmware_info;
+        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;
+        struct xenpf_get_cpu_freq      get_cpu_freq;
+        uint8_t                        pad[128];
+    } u;
+};
+typedef struct xen_platform_op xen_platform_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t);
+
+#endif /* __XEN_PUBLIC_PLATFORM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/dom0_ops.h
+++ linux-ec2-2.6.32/include/xen/interface/dom0_ops.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * dom0_ops.h
+ * 
+ * Process command requests from domain-0 guest OS.
+ * 
+ * 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) 2002-2003, B Dragovic
+ * Copyright (c) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_DOM0_OPS_H__
+#define __XEN_PUBLIC_DOM0_OPS_H__
+
+#include "xen.h"
+#include "platform.h"
+
+#if __XEN_INTERFACE_VERSION__ >= 0x00030204
+#error "dom0_ops.h is a compatibility interface only"
+#endif
+
+#define DOM0_INTERFACE_VERSION XENPF_INTERFACE_VERSION
+
+#define DOM0_SETTIME          XENPF_settime
+#define dom0_settime          xenpf_settime
+#define dom0_settime_t        xenpf_settime_t
+
+#define DOM0_ADD_MEMTYPE      XENPF_add_memtype
+#define dom0_add_memtype      xenpf_add_memtype
+#define dom0_add_memtype_t    xenpf_add_memtype_t
+
+#define DOM0_DEL_MEMTYPE      XENPF_del_memtype
+#define dom0_del_memtype      xenpf_del_memtype
+#define dom0_del_memtype_t    xenpf_del_memtype_t
+
+#define DOM0_READ_MEMTYPE     XENPF_read_memtype
+#define dom0_read_memtype     xenpf_read_memtype
+#define dom0_read_memtype_t   xenpf_read_memtype_t
+
+#define DOM0_MICROCODE        XENPF_microcode_update
+#define dom0_microcode        xenpf_microcode_update
+#define dom0_microcode_t      xenpf_microcode_update_t
+
+#define DOM0_PLATFORM_QUIRK   XENPF_platform_quirk
+#define dom0_platform_quirk   xenpf_platform_quirk
+#define dom0_platform_quirk_t xenpf_platform_quirk_t
+
+typedef uint64_t cpumap_t;
+
+/* Unsupported legacy operation -- defined for API compatibility. */
+#define DOM0_MSR                 15
+struct dom0_msr {
+    /* IN variables. */
+    uint32_t write;
+    cpumap_t cpu_mask;
+    uint32_t msr;
+    uint32_t in1;
+    uint32_t in2;
+    /* OUT variables. */
+    uint32_t out1;
+    uint32_t out2;
+};
+typedef struct dom0_msr dom0_msr_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_msr_t);
+
+/* Unsupported legacy operation -- defined for API compatibility. */
+#define DOM0_PHYSICAL_MEMORY_MAP 40
+struct dom0_memory_map_entry {
+    uint64_t start, end;
+    uint32_t flags; /* reserved */
+    uint8_t  is_ram;
+};
+typedef struct dom0_memory_map_entry dom0_memory_map_entry_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_memory_map_entry_t);
+
+struct dom0_op {
+    uint32_t cmd;
+    uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
+    union {
+        struct dom0_msr               msr;
+        struct dom0_settime           settime;
+        struct dom0_add_memtype       add_memtype;
+        struct dom0_del_memtype       del_memtype;
+        struct dom0_read_memtype      read_memtype;
+        struct dom0_microcode         microcode;
+        struct dom0_platform_quirk    platform_quirk;
+        struct dom0_memory_map_entry  physical_memory_map;
+        uint8_t                       pad[128];
+    } u;
+};
+typedef struct dom0_op dom0_op_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_op_t);
+
+#endif /* __XEN_PUBLIC_DOM0_OPS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/kexec.h
+++ linux-ec2-2.6.32/include/xen/interface/kexec.h
@@ -0,0 +1,168 @@
+/******************************************************************************
+ * 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>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+
+/* This file describes the Kexec / Kdump hypercall interface for Xen.
+ *
+ * Kexec under vanilla Linux allows a user to reboot the physical machine 
+ * into a new user-specified kernel. The Xen port extends this idea
+ * to allow rebooting of the machine from dom0. When kexec for dom0
+ * is used to reboot,  both the hypervisor and the domains get replaced
+ * with some other kernel. It is possible to kexec between vanilla
+ * Linux and Xen and back again. Xen to Xen works well too.
+ *
+ * The hypercall interface for kexec can be divided into three main
+ * types of hypercall operations:
+ *
+ * 1) Range information:
+ *    This is used by the dom0 kernel to ask the hypervisor about various 
+ *    address information. This information is needed to allow kexec-tools 
+ *    to fill in the ELF headers for /proc/vmcore properly.
+ *
+ * 2) Load and unload of images:
+ *    There are no big surprises here, the kexec binary from kexec-tools
+ *    runs in userspace in dom0. The tool loads/unloads data into the
+ *    dom0 kernel such as new kernel, initramfs and hypervisor. When
+ *    loaded the dom0 kernel performs a load hypercall operation, and
+ *    before releasing all page references the dom0 kernel calls unload.
+ *
+ * 3) Kexec operation:
+ *    This is used to start a previously loaded kernel.
+ */
+
+#include "xen.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#define KEXEC_XEN_NO_PAGES 17
+#endif
+
+/*
+ * Prototype for this hypercall is:
+ *  int kexec_op(int cmd, void *args)
+ * @cmd  == KEXEC_CMD_... 
+ *          KEXEC operation to perform
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+/*
+ * Kexec supports two types of operation:
+ * - kexec into a regular kernel, very similar to a standard reboot
+ *   - KEXEC_TYPE_DEFAULT is used to specify this type
+ * - kexec into a special "crash kernel", aka kexec-on-panic
+ *   - KEXEC_TYPE_CRASH is used to specify this type
+ *   - parts of our system may be broken at kexec-on-panic time
+ *     - the code should be kept as simple and self-contained as possible
+ */
+
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH   1
+
+
+/* The kexec implementation for Xen allows the user to load two
+ * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
+ * All data needed for a kexec reboot is kept in one xen_kexec_image_t
+ * per "instance". The data mainly consists of machine address lists to pages
+ * together with destination addresses. The data in xen_kexec_image_t
+ * is passed to the "code page" which is one page of code that performs
+ * the final relocations before jumping to the new kernel.
+ */
+ 
+typedef struct xen_kexec_image {
+#if defined(__i386__) || defined(__x86_64__)
+    unsigned long page_list[KEXEC_XEN_NO_PAGES];
+#endif
+#if defined(__ia64__)
+    unsigned long reboot_code_buffer;
+#endif
+    unsigned long indirection_page;
+    unsigned long start_address;
+} xen_kexec_image_t;
+
+/*
+ * Perform kexec having previously loaded a kexec or kdump kernel
+ * as appropriate.
+ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ */
+#define KEXEC_CMD_kexec                 0
+typedef struct xen_kexec_exec {
+    int type;
+} xen_kexec_exec_t;
+
+/*
+ * Load/Unload kernel image for kexec or kdump.
+ * type  == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
+ * image == relocation information for kexec (ignored for unload) [in]
+ */
+#define KEXEC_CMD_kexec_load            1
+#define KEXEC_CMD_kexec_unload          2
+typedef struct xen_kexec_load {
+    int type;
+    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_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
+ * range == KEXEC_RANGE_... [in]
+ * nr    == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
+ * size  == number of bytes reserved in window [out]
+ * start == address of the first byte in the window [out]
+ */
+#define KEXEC_CMD_kexec_get_range       3
+typedef struct xen_kexec_range {
+    int range;
+    int nr;
+    unsigned long size;
+    unsigned long start;
+} xen_kexec_range_t;
+
+#endif /* _XEN_PUBLIC_KEXEC_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/features.h
+++ linux-ec2-2.6.32/include/xen/interface/features.h
@@ -3,6 +3,24 @@
  *
  * Feature flags, reported by XENVER_get_features.
  *
+ * 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) 2006, Keir Fraser <keir@xensource.com>
  */
 
@@ -41,6 +59,15 @@
 /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */
 #define XENFEAT_mmu_pt_update_preserve_ad  5
 
+/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */
+#define XENFEAT_highmem_assist             6
+
+/*
+ * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel
+ * available pte bits.
+ */
+#define XENFEAT_gnttab_map_avail_bits      7
+
 #define XENFEAT_NR_SUBMAPS 1
 
 #endif /* __XEN_PUBLIC_FEATURES_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/xenoprof.h
+++ linux-ec2-2.6.32/include/xen/interface/xenoprof.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+ * xenoprof.h
+ * 
+ * Interface for enabling system wide profiling based on hardware performance
+ * counters
+ * 
+ * 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) 2005 Hewlett-Packard Co.
+ * Written by Aravind Menon & Jose Renato Santos
+ */
+
+#ifndef __XEN_PUBLIC_XENOPROF_H__
+#define __XEN_PUBLIC_XENOPROF_H__
+
+#include "xen.h"
+
+/*
+ * Commands to HYPERVISOR_xenoprof_op().
+ */
+#define XENOPROF_init                0
+#define XENOPROF_reset_active_list   1
+#define XENOPROF_reset_passive_list  2
+#define XENOPROF_set_active          3
+#define XENOPROF_set_passive         4
+#define XENOPROF_reserve_counters    5
+#define XENOPROF_counter             6
+#define XENOPROF_setup_events        7
+#define XENOPROF_enable_virq         8
+#define XENOPROF_start               9
+#define XENOPROF_stop               10
+#define XENOPROF_disable_virq       11
+#define XENOPROF_release_counters   12
+#define XENOPROF_shutdown           13
+#define XENOPROF_get_buffer         14
+#define XENOPROF_set_backtrace      15
+#define XENOPROF_last_op            15
+
+#define MAX_OPROF_EVENTS    32
+#define MAX_OPROF_DOMAINS   25
+#define XENOPROF_CPU_TYPE_SIZE 64
+
+/* Xenoprof performance events (not Xen events) */
+struct event_log {
+    uint64_t eip;
+    uint8_t mode;
+    uint8_t event;
+};
+
+/* PC value that indicates a special code */
+#define XENOPROF_ESCAPE_CODE ~0UL
+/* Transient events for the xenoprof->oprofile cpu buf */
+#define XENOPROF_TRACE_BEGIN 1
+
+/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */
+struct xenoprof_buf {
+    uint32_t event_head;
+    uint32_t event_tail;
+    uint32_t event_size;
+    uint32_t vcpu_id;
+    uint64_t xen_samples;
+    uint64_t kernel_samples;
+    uint64_t user_samples;
+    uint64_t lost_samples;
+    struct event_log event_log[1];
+};
+#ifndef __XEN__
+typedef struct xenoprof_buf xenoprof_buf_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t);
+#endif
+
+struct xenoprof_init {
+    int32_t  num_events;
+    int32_t  is_primary;
+    char cpu_type[XENOPROF_CPU_TYPE_SIZE];
+};
+typedef struct xenoprof_init xenoprof_init_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t);
+
+struct xenoprof_get_buffer {
+    int32_t  max_samples;
+    int32_t  nbuf;
+    int32_t  bufsize;
+    uint64_t buf_gmaddr;
+};
+typedef struct xenoprof_get_buffer xenoprof_get_buffer_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t);
+
+struct xenoprof_counter {
+    uint32_t ind;
+    uint64_t count;
+    uint32_t enabled;
+    uint32_t event;
+    uint32_t hypervisor;
+    uint32_t kernel;
+    uint32_t user;
+    uint64_t unit_mask;
+};
+typedef struct xenoprof_counter xenoprof_counter_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t);
+
+typedef struct xenoprof_passive {
+    uint16_t domain_id;
+    int32_t  max_samples;
+    int32_t  nbuf;
+    int32_t  bufsize;
+    uint64_t buf_gmaddr;
+} xenoprof_passive_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
+
+
+#endif /* __XEN_PUBLIC_XENOPROF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/sysctl.h
+++ linux-ec2-2.6.32/include/xen/interface/sysctl.h
@@ -0,0 +1,490 @@
+/******************************************************************************
+ * sysctl.h
+ * 
+ * System management operations. For use by node control stack.
+ * 
+ * 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) 2002-2006, K Fraser
+ */
+
+#ifndef __XEN_PUBLIC_SYSCTL_H__
+#define __XEN_PUBLIC_SYSCTL_H__
+
+#if !defined(__XEN__) && !defined(__XEN_TOOLS__)
+#error "sysctl operations are intended for use by node control tools only"
+#endif
+
+#include "xen.h"
+#include "domctl.h"
+
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000006
+
+/*
+ * Read console content from Xen buffer ring.
+ */
+#define XEN_SYSCTL_readconsole       1
+struct xen_sysctl_readconsole {
+    /* IN: Non-zero -> clear after reading. */
+    uint8_t clear;
+    /* IN: Non-zero -> start index specified by @index field. */
+    uint8_t incremental;
+    uint8_t pad0, pad1;
+    /*
+     * IN:  Start index for consuming from ring buffer (if @incremental);
+     * OUT: End index after consuming from ring buffer.
+     */
+    uint32_t index; 
+    /* IN: Virtual address to write console data. */
+    XEN_GUEST_HANDLE_64(char) buffer;
+    /* IN: Size of buffer; OUT: Bytes written to buffer. */
+    uint32_t count;
+};
+typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t);
+
+/* Get trace buffers machine base address */
+#define XEN_SYSCTL_tbuf_op           2
+struct xen_sysctl_tbuf_op {
+    /* IN variables */
+#define XEN_SYSCTL_TBUFOP_get_info     0
+#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1
+#define XEN_SYSCTL_TBUFOP_set_evt_mask 2
+#define XEN_SYSCTL_TBUFOP_set_size     3
+#define XEN_SYSCTL_TBUFOP_enable       4
+#define XEN_SYSCTL_TBUFOP_disable      5
+    uint32_t cmd;
+    /* IN/OUT variables */
+    struct xenctl_cpumap cpu_mask;
+    uint32_t             evt_mask;
+    /* OUT variables */
+    uint64_aligned_t buffer_mfn;
+    uint32_t size;
+};
+typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
+
+/*
+ * 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 {
+    uint32_t threads_per_core;
+    uint32_t cores_per_socket;
+    uint32_t nr_cpus;
+    uint32_t nr_nodes;
+    uint32_t cpu_khz;
+    uint64_aligned_t total_pages;
+    uint64_aligned_t free_pages;
+    uint64_aligned_t scrub_pages;
+    uint32_t hw_cap[8];
+
+    /*
+     * IN: maximum addressable entry in the caller-provided cpu_to_node array.
+     * OUT: largest cpu identifier in the system.
+     * If OUT is greater than IN then the cpu_to_node array is truncated!
+     */
+    uint32_t max_cpu_id;
+    /*
+     * If not NULL, this array is filled with node identifier for each cpu.
+     * If a cpu has no node information (e.g., cpu not present) then the
+     * sentinel value ~0u is written.
+     * The size of this array is specified by the caller in @max_cpu_id.
+     * If the actual @max_cpu_id is smaller than the array then the trailing
+     * 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);
+
+/*
+ * Get the ID of the current scheduler.
+ */
+#define XEN_SYSCTL_sched_id          4
+struct xen_sysctl_sched_id {
+    /* OUT variable */
+    uint32_t sched_id;
+};
+typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t);
+
+/* Interface for controlling Xen software performance counters. */
+#define XEN_SYSCTL_perfc_op          5
+/* Sub-operations: */
+#define XEN_SYSCTL_PERFCOP_reset 1   /* Reset all counters to zero. */
+#define XEN_SYSCTL_PERFCOP_query 2   /* Get perfctr information. */
+struct xen_sysctl_perfc_desc {
+    char         name[80];             /* name of perf counter */
+    uint32_t     nr_vals;              /* number of values for this counter */
+};
+typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t);
+typedef uint32_t xen_sysctl_perfc_val_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t);
+
+struct xen_sysctl_perfc_op {
+    /* IN variables. */
+    uint32_t       cmd;                /*  XEN_SYSCTL_PERFCOP_??? */
+    /* OUT variables. */
+    uint32_t       nr_counters;       /*  number of counters description  */
+    uint32_t       nr_vals;           /*  number of values  */
+    /* counter information (or NULL) */
+    XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc;
+    /* counter values (or NULL) */
+    XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val;
+};
+typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t);
+
+#define XEN_SYSCTL_getdomaininfolist 6
+struct xen_sysctl_getdomaininfolist {
+    /* IN variables. */
+    domid_t               first_domain;
+    uint32_t              max_domains;
+    XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
+    /* OUT variables. */
+    uint32_t              num_domains;
+};
+typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
+
+/* Inject debug keys into Xen. */
+#define XEN_SYSCTL_debug_keys        7
+struct xen_sysctl_debug_keys {
+    /* IN variables. */
+    XEN_GUEST_HANDLE_64(char) keys;
+    uint32_t nr_keys;
+};
+typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
+/* Get physical CPU information. */
+#define XEN_SYSCTL_getcpuinfo        8
+struct xen_sysctl_cpuinfo {
+    uint64_aligned_t idletime;
+};
+typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t); 
+struct xen_sysctl_getcpuinfo {
+    /* IN variables. */
+    uint32_t max_cpus;
+    XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info;
+    /* OUT variables. */
+    uint32_t nr_cpus;
+}; 
+typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); 
+
+#define XEN_SYSCTL_availheap         9
+struct xen_sysctl_availheap {
+    /* IN variables. */
+    uint32_t min_bitwidth;  /* Smallest address width (zero if don't care). */
+    uint32_t max_bitwidth;  /* Largest address width (zero if don't care). */
+    int32_t  node;          /* NUMA node of interest (-1 for all nodes). */
+    /* OUT variables. */
+    uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */
+};
+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);
+
+/*
+ * Status codes. Must be greater than 0 to avoid confusing
+ * sysctl callers that see 0 as a plain successful return.
+ */
+#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1
+#define XEN_CPU_HOTPLUG_STATUS_ONLINE  2
+#define XEN_CPU_HOTPLUG_STATUS_NEW     3
+
+#define XEN_SYSCTL_cpu_hotplug       11
+struct xen_sysctl_cpu_hotplug {
+    /* IN variables */
+    uint32_t cpu;   /* Physical cpu. */
+#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE  0
+#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1
+#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2
+    uint32_t op;    /* hotplug opcode */
+};
+typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t);
+
+/*
+ * Get/set xen power management, include 
+ * 1. cpufreq governors and related parameters
+ */
+#define XEN_SYSCTL_pm_op        12
+struct xen_userspace {
+    uint32_t scaling_setspeed;
+};
+typedef struct xen_userspace xen_userspace_t;
+
+struct xen_ondemand {
+    uint32_t sampling_rate_max;
+    uint32_t sampling_rate_min;
+
+    uint32_t sampling_rate;
+    uint32_t up_threshold;
+};
+typedef struct xen_ondemand xen_ondemand_t;
+
+/* 
+ * cpufreq para name of this structure named 
+ * same as sysfs file name of native linux
+ */
+#define CPUFREQ_NAME_LEN 16
+struct xen_get_cpufreq_para {
+    /* IN/OUT variable */
+    uint32_t cpu_num;
+    uint32_t freq_num;
+    uint32_t gov_num;
+
+    /* for all governors */
+    /* OUT variable */
+    XEN_GUEST_HANDLE_64(uint32) affected_cpus;
+    XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies;
+    XEN_GUEST_HANDLE_64(char)   scaling_available_governors;
+    char scaling_driver[CPUFREQ_NAME_LEN];
+
+    uint32_t cpuinfo_cur_freq;
+    uint32_t cpuinfo_max_freq;
+    uint32_t cpuinfo_min_freq;
+    uint32_t scaling_cur_freq;
+
+    char scaling_governor[CPUFREQ_NAME_LEN];
+    uint32_t scaling_max_freq;
+    uint32_t scaling_min_freq;
+
+    /* for specific governor */
+    union {
+        struct  xen_userspace userspace;
+        struct  xen_ondemand ondemand;
+    } u;
+};
+
+struct xen_set_cpufreq_gov {
+    char scaling_governor[CPUFREQ_NAME_LEN];
+};
+
+struct xen_set_cpufreq_para {
+    #define SCALING_MAX_FREQ           1
+    #define SCALING_MIN_FREQ           2
+    #define SCALING_SETSPEED           3
+    #define SAMPLING_RATE              4
+    #define UP_THRESHOLD               5
+
+    uint32_t ctrl_type;
+    uint32_t ctrl_value;
+};
+
+/* Get physical CPU topology information. */
+#define INVALID_TOPOLOGY_ID  (~0U)
+struct xen_get_cputopo {
+     /* IN: maximum addressable entry in
+      * the caller-provided cpu_to_core/socket.
+      */
+    uint32_t max_cpus;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_core;
+    XEN_GUEST_HANDLE_64(uint32) cpu_to_socket;
+
+    /* OUT: number of cpus returned
+     * If OUT is greater than IN then the cpu_to_core/socket is truncated!
+     */
+    uint32_t nr_cpus;
+};
+
+struct xen_sysctl_pm_op {
+    #define PM_PARA_CATEGORY_MASK      0xf0
+    #define CPUFREQ_PARA               0x10
+
+    /* cpufreq command type */
+    #define GET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x01)
+    #define SET_CPUFREQ_GOV            (CPUFREQ_PARA | 0x02)
+    #define SET_CPUFREQ_PARA           (CPUFREQ_PARA | 0x03)
+    #define GET_CPUFREQ_AVGFREQ        (CPUFREQ_PARA | 0x04)
+
+    /* get CPU topology */
+    #define XEN_SYSCTL_pm_op_get_cputopo  0x20
+
+    /* set/reset scheduler power saving option */
+    #define XEN_SYSCTL_pm_op_set_sched_opt_smt    0x21
+
+    /* cpuidle max_cstate access command */
+    #define XEN_SYSCTL_pm_op_get_max_cstate       0x22
+    #define XEN_SYSCTL_pm_op_set_max_cstate       0x23
+
+    /* set scheduler migration cost value */
+    #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay   0x24
+    #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay   0x25
+
+    uint32_t cmd;
+    uint32_t cpuid;
+    union {
+        struct xen_get_cpufreq_para get_para;
+        struct xen_set_cpufreq_gov  set_gov;
+        struct xen_set_cpufreq_para set_para;
+        uint64_t get_avgfreq;
+        struct xen_get_cputopo      get_topo;
+        uint32_t                    set_sched_opt_smt;
+        uint32_t                    get_max_cstate;
+        uint32_t                    set_max_cstate;
+        uint32_t                    get_vcpu_migration_delay;
+        uint32_t                    set_vcpu_migration_delay;
+    };
+};
+
+#define XEN_SYSCTL_page_offline_op        14
+struct xen_sysctl_page_offline_op {
+    /* IN: range of page to be offlined */
+#define sysctl_page_offline     1
+#define sysctl_page_online      2
+#define sysctl_query_page_offline  3
+    uint32_t cmd;
+    uint32_t start;
+    uint32_t end;
+    /* OUT: result of page offline request */
+    /*
+     * bit 0~15: result flags
+     * bit 16~31: owner
+     */
+    XEN_GUEST_HANDLE(uint32) status;
+};
+
+#define PG_OFFLINE_STATUS_MASK    (0xFFUL)
+
+/* The result is invalid, i.e. HV does not handle it */
+#define PG_OFFLINE_INVALID   (0x1UL << 0)
+
+#define PG_OFFLINE_OFFLINED  (0x1UL << 1)
+#define PG_OFFLINE_PENDING   (0x1UL << 2)
+#define PG_OFFLINE_FAILED    (0x1UL << 3)
+
+#define PG_ONLINE_FAILED     PG_OFFLINE_FAILED
+#define PG_ONLINE_ONLINED    PG_OFFLINE_OFFLINED
+
+#define PG_OFFLINE_STATUS_OFFLINED              (0x1UL << 1)
+#define PG_OFFLINE_STATUS_ONLINE                (0x1UL << 2)
+#define PG_OFFLINE_STATUS_OFFLINE_PENDING       (0x1UL << 3)
+#define PG_OFFLINE_STATUS_BROKEN                (0x1UL << 4)
+
+#define PG_OFFLINE_MISC_MASK    (0xFFUL << 4)
+
+/* only valid when PG_OFFLINE_FAILED */
+#define PG_OFFLINE_XENPAGE   (0x1UL << 8)
+#define PG_OFFLINE_DOM0PAGE  (0x1UL << 9)
+#define PG_OFFLINE_ANONYMOUS (0x1UL << 10)
+#define PG_OFFLINE_NOT_CONV_RAM   (0x1UL << 11)
+#define PG_OFFLINE_OWNED     (0x1UL << 12)
+
+#define PG_OFFLINE_BROKEN    (0x1UL << 13)
+#define PG_ONLINE_BROKEN     PG_OFFLINE_BROKEN
+
+#define PG_OFFLINE_OWNER_SHIFT 16
+
+struct xen_sysctl {
+    uint32_t cmd;
+    uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
+    union {
+        struct xen_sysctl_readconsole       readconsole;
+        struct xen_sysctl_tbuf_op           tbuf_op;
+        struct xen_sysctl_physinfo          physinfo;
+        struct xen_sysctl_sched_id          sched_id;
+        struct xen_sysctl_perfc_op          perfc_op;
+        struct xen_sysctl_getdomaininfolist getdomaininfolist;
+        struct xen_sysctl_debug_keys        debug_keys;
+        struct xen_sysctl_getcpuinfo        getcpuinfo;
+        struct xen_sysctl_availheap         availheap;
+        struct xen_sysctl_get_pmstat        get_pmstat;
+        struct xen_sysctl_cpu_hotplug       cpu_hotplug;
+        struct xen_sysctl_pm_op             pm_op;
+        struct xen_sysctl_page_offline_op   page_offline;
+        uint8_t                             pad[128];
+    } u;
+};
+typedef struct xen_sysctl xen_sysctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);
+
+#endif /* __XEN_PUBLIC_SYSCTL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/params.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/params.h
@@ -0,0 +1,111 @@
+/*
+ * 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_PUBLIC_HVM_PARAMS_H__
+#define __XEN_PUBLIC_HVM_PARAMS_H__
+
+#include "hvm_op.h"
+
+/*
+ * Parameter space for HVMOP_{set,get}_param.
+ */
+
+/*
+ * How should CPU0 event-channel notifications be delivered?
+ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
+ *                  Domain = val[47:32], Bus  = val[31:16],
+ *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
+ * If val == 0 then CPU0 event-channel notifications are not delivered.
+ */
+#define HVM_PARAM_CALLBACK_IRQ 0
+
+/*
+ * These are not used by Xen. They are here for convenience of HVM-guest
+ * xenbus implementations.
+ */
+#define HVM_PARAM_STORE_PFN    1
+#define HVM_PARAM_STORE_EVTCHN 2
+
+#define HVM_PARAM_PAE_ENABLED  4
+
+#define HVM_PARAM_IOREQ_PFN    5
+
+#define HVM_PARAM_BUFIOREQ_PFN 6
+
+#ifdef __ia64__
+
+#define HVM_PARAM_NVRAM_FD     7
+#define HVM_PARAM_VHPT_SIZE    8
+#define HVM_PARAM_BUFPIOREQ_PFN	9
+
+#elif defined(__i386__) || defined(__x86_64__)
+
+/* Expose Viridian interfaces to this HVM guest? */
+#define HVM_PARAM_VIRIDIAN     9
+
+#endif
+
+/*
+ * Set mode for virtual timers (currently x86 only):
+ *  delay_for_missed_ticks (default):
+ *   Do not advance a vcpu's time beyond the correct delivery time for
+ *   interrupts that have been missed due to preemption. Deliver missed
+ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
+ *   time stepwise for each one.
+ *  no_delay_for_missed_ticks:
+ *   As above, missed interrupts are delivered, but guest time always tracks
+ *   wallclock (i.e., real) time while doing so.
+ *  no_missed_ticks_pending:
+ *   No missed interrupts are held pending. Instead, to ensure ticks are
+ *   delivered at some non-zero rate, if we detect missed ticks then the
+ *   internal tick alarm is not disabled if the VCPU is preempted during the
+ *   next tick period.
+ *  one_missed_tick_pending:
+ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
+ *   Guest time always tracks wallclock (i.e., real) time.
+ */
+#define HVM_PARAM_TIMER_MODE   10
+#define HVMPTM_delay_for_missed_ticks    0
+#define HVMPTM_no_delay_for_missed_ticks 1
+#define HVMPTM_no_missed_ticks_pending   2
+#define HVMPTM_one_missed_tick_pending   3
+
+/* 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
+
+/* TSS used on Intel when CR0.PE=0. */
+#define HVM_PARAM_VM86_TSS     15
+
+/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
+#define HVM_PARAM_VPT_ALIGN    16
+
+#define HVM_NR_PARAMS          17
+
+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/e820.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/e820.h
@@ -0,0 +1,34 @@
+
+/*
+ * 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_PUBLIC_HVM_E820_H__
+#define __XEN_PUBLIC_HVM_E820_H__
+
+/* E820 location in HVM virtual address space. */
+#define HVM_E820_PAGE        0x00090000
+#define HVM_E820_NR_OFFSET   0x000001E8
+#define HVM_E820_OFFSET      0x000002D0
+
+#define HVM_BELOW_4G_RAM_END        0xF0000000
+#define HVM_BELOW_4G_MMIO_START     HVM_BELOW_4G_RAM_END
+#define HVM_BELOW_4G_MMIO_LENGTH    ((1ULL << 32) - HVM_BELOW_4G_MMIO_START)
+
+#endif /* __XEN_PUBLIC_HVM_E820_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/save.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/save.h
@@ -0,0 +1,88 @@
+/* 
+ * hvm/save.h
+ *
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ * 
+ * Copyright (c) 2007 XenSource Ltd.
+ *
+ * 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_PUBLIC_HVM_SAVE_H__
+#define __XEN_PUBLIC_HVM_SAVE_H__
+
+/*
+ * Structures in this header *must* have the same layout in 32bit 
+ * and 64bit environments: this means that all fields must be explicitly 
+ * sized types and aligned to their sizes, and the structs must be 
+ * a multiple of eight bytes long.
+ *
+ * Only the state necessary for saving and restoring (i.e. fields 
+ * that are analogous to actual hardware state) should go in this file. 
+ * 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
+ */
+struct hvm_save_descriptor {
+    uint16_t typecode;          /* Used to demux the various types below */
+    uint16_t instance;          /* Further demux within a type */
+    uint32_t length;            /* In bytes, *not* including this descriptor */
+};
+
+
+/* 
+ * Each entry has a datatype associated with it: for example, the CPU state 
+ * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU), 
+ * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU).
+ * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system
+ * ugliness.
+ */
+
+#define DECLARE_HVM_SAVE_TYPE(_x, _code, _type)                   \
+  struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; }
+
+#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t)
+#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x)))
+#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c))
+
+
+/* 
+ * The series of save records is teminated by a zero-type, zero-length 
+ * descriptor.
+ */
+
+struct hvm_save_end {};
+DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end);
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "../arch-x86/hvm/save.h"
+#elif defined(__ia64__)
+#include "../arch-ia64/hvm/save.h"
+#else
+#error "unsupported architecture"
+#endif
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/hvm_info_table.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/hvm_info_table.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * hvm/hvm_info_table.h
+ * 
+ * HVM parameter and information table, written into guest memory map.
+ *
+ * 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_PUBLIC_HVM_HVM_INFO_TABLE_H__
+#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
+
+#define HVM_INFO_PFN         0x09F
+#define HVM_INFO_OFFSET      0x800
+#define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
+
+struct hvm_info_table {
+    char        signature[8]; /* "HVM INFO" */
+    uint32_t    length;
+    uint8_t     checksum;
+
+    /* Should firmware build ACPI tables? */
+    uint8_t     acpi_enabled;
+
+    /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */
+    uint8_t     apic_mode;
+
+    /* How many CPUs does this domain have? */
+    uint32_t    nr_vcpus;
+
+    /*
+     * MEMORY MAP provided by HVM domain builder.
+     * Notes:
+     *  1. page_to_phys(x) = x << 12
+     *  2. If a field is zero, the corresponding range does not exist.
+     */
+    /*
+     *  0x0 to page_to_phys(low_mem_pgend)-1:
+     *    RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF)
+     */
+    uint32_t    low_mem_pgend;
+    /*
+     *  page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF:
+     *    Reserved for special memory mappings
+     */
+    uint32_t    reserved_mem_pgstart;
+    /*
+     *  0x100000000 to page_to_phys(high_mem_pgend)-1:
+     *    RAM above 4GB
+     */
+    uint32_t    high_mem_pgend;
+};
+
+#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/hvm_op.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/hvm_op.h
@@ -0,0 +1,133 @@
+/*
+ * 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_PUBLIC_HVM_HVM_OP_H__
+#define __XEN_PUBLIC_HVM_HVM_OP_H__
+
+#include "../xen.h"
+
+/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
+#define HVMOP_set_param           0
+#define HVMOP_get_param           1
+struct xen_hvm_param {
+    domid_t  domid;    /* IN */
+    uint32_t index;    /* IN */
+    uint64_t value;    /* IN/OUT */
+};
+typedef struct xen_hvm_param xen_hvm_param_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
+
+/* Set the logical level of one of a domain's PCI INTx wires. */
+#define HVMOP_set_pci_intx_level  2
+struct xen_hvm_set_pci_intx_level {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* PCI INTx identification in PCI topology (domain:bus:device:intx). */
+    uint8_t  domain, bus, device, intx;
+    /* Assertion level (0 = unasserted, 1 = asserted). */
+    uint8_t  level;
+};
+typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t);
+
+/* Set the logical level of one of a domain's ISA IRQ wires. */
+#define HVMOP_set_isa_irq_level   3
+struct xen_hvm_set_isa_irq_level {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* ISA device identification, by ISA IRQ (0-15). */
+    uint8_t  isa_irq;
+    /* Assertion level (0 = unasserted, 1 = asserted). */
+    uint8_t  level;
+};
+typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t);
+
+#define HVMOP_set_pci_link_route  4
+struct xen_hvm_set_pci_link_route {
+    /* Domain to be updated. */
+    domid_t  domid;
+    /* PCI link identifier (0-3). */
+    uint8_t  link;
+    /* ISA IRQ (1-15), or 0 (disable link). */
+    uint8_t  isa_irq;
+};
+typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
+
+/* 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__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/hvm/ioreq.h
+++ linux-ec2-2.6.32/include/xen/interface/hvm/ioreq.h
@@ -0,0 +1,127 @@
+/*
+ * ioreq.h: I/O request definitions for device models
+ * Copyright (c) 2004, Intel Corporation.
+ * 
+ * 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 _IOREQ_H_
+#define _IOREQ_H_
+
+#define IOREQ_READ      1
+#define IOREQ_WRITE     0
+
+#define STATE_IOREQ_NONE        0
+#define STATE_IOREQ_READY       1
+#define STATE_IOREQ_INPROCESS   2
+#define STATE_IORESP_READY      3
+
+#define IOREQ_TYPE_PIO          0 /* pio */
+#define IOREQ_TYPE_COPY         1 /* mmio ops */
+#define IOREQ_TYPE_TIMEOFFSET   7
+#define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
+
+/*
+ * VMExit dispatcher should cooperate with instruction decoder to
+ * prepare this structure and notify service OS and DM by sending
+ * virq
+ */
+struct ioreq {
+    uint64_t addr;          /*  physical address            */
+    uint64_t size;          /*  size in bytes               */
+    uint64_t count;         /*  for rep prefixes            */
+    uint64_t data;          /*  data (or paddr of data)     */
+    uint8_t state:4;
+    uint8_t data_is_ptr:1;  /*  if 1, data above is the guest paddr 
+                             *   of the real data to use.   */
+    uint8_t dir:1;          /*  1=read, 0=write             */
+    uint8_t df:1;
+    uint8_t pad:1;
+    uint8_t type;           /* I/O type                     */
+    uint8_t _pad0[6];
+    uint64_t io_count;      /* How many IO done on a vcpu   */
+};
+typedef struct ioreq ioreq_t;
+
+struct vcpu_iodata {
+    struct ioreq vp_ioreq;
+    /* Event channel port, used for notifications to/from the device model. */
+    uint32_t vp_eport;
+    uint32_t _pad0;
+};
+typedef struct vcpu_iodata vcpu_iodata_t;
+
+struct shared_iopage {
+    struct vcpu_iodata   vcpu_iodata[1];
+};
+typedef struct shared_iopage shared_iopage_t;
+
+struct buf_ioreq {
+    uint8_t  type;   /* I/O type                    */
+    uint8_t  pad:1;
+    uint8_t  dir:1;  /* 1=read, 0=write             */
+    uint8_t  size:2; /* 0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */
+    uint32_t addr:20;/* physical address            */
+    uint32_t data;   /* data                        */
+};
+typedef struct buf_ioreq buf_ioreq_t;
+
+#define IOREQ_BUFFER_SLOT_NUM     511 /* 8 bytes each, plus 2 4-byte indexes */
+struct buffered_iopage {
+    unsigned int read_pointer;
+    unsigned int write_pointer;
+    buf_ioreq_t buf_ioreq[IOREQ_BUFFER_SLOT_NUM];
+}; /* NB. Size of this structure must be no greater than one page. */
+typedef struct buffered_iopage buffered_iopage_t;
+
+#if defined(__ia64__)
+struct pio_buffer {
+    uint32_t page_offset;
+    uint32_t pointer;
+    uint32_t data_end;
+    uint32_t buf_size;
+    void *opaque;
+};
+
+#define PIO_BUFFER_IDE_PRIMARY   0 /* I/O port = 0x1F0 */
+#define PIO_BUFFER_IDE_SECONDARY 1 /* I/O port = 0x170 */
+#define PIO_BUFFER_ENTRY_NUM     2
+struct buffered_piopage {
+    struct pio_buffer pio[PIO_BUFFER_ENTRY_NUM];
+    uint8_t buffer[1];
+};
+#endif /* defined(__ia64__) */
+
+#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)
+#define ACPI_GPE0_BLK_ADDRESS               (ACPI_PM_TMR_BLK_ADDRESS + 0x20)
+#define ACPI_GPE0_BLK_LEN                   0x08
+
+#endif /* _IOREQ_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/xsm/acm_ops.h
+++ linux-ec2-2.6.32/include/xen/interface/xsm/acm_ops.h
@@ -0,0 +1,159 @@
+/*
+ * acm_ops.h: Xen access control module hypervisor commands
+ *
+ * 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.
+ *
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Copyright (c) 2005,2006 International Business Machines Corporation.
+ */
+
+#ifndef __XEN_PUBLIC_ACM_OPS_H__
+#define __XEN_PUBLIC_ACM_OPS_H__
+
+#include "../xen.h"
+#include "acm.h"
+
+/*
+ * Make sure you increment the interface version whenever you modify this file!
+ * This makes sure that old versions of acm tools will stop working in a
+ * well-defined way (rather than crashing the machine, for instance).
+ */
+#define ACM_INTERFACE_VERSION   0xAAAA000A
+
+/************************************************************************/
+
+/*
+ * Prototype for this hypercall is:
+ *  int acm_op(int cmd, void *args)
+ * @cmd  == ACMOP_??? (access control module operation).
+ * @args == Operation-specific extra arguments (NULL if none).
+ */
+
+
+#define ACMOP_setpolicy         1
+struct acm_setpolicy {
+    /* IN */
+    XEN_GUEST_HANDLE_64(void) pushcache;
+    uint32_t pushcache_size;
+};
+
+
+#define ACMOP_getpolicy         2
+struct acm_getpolicy {
+    /* IN */
+    XEN_GUEST_HANDLE_64(void) pullcache;
+    uint32_t pullcache_size;
+};
+
+
+#define ACMOP_dumpstats         3
+struct acm_dumpstats {
+    /* IN */
+    XEN_GUEST_HANDLE_64(void) pullcache;
+    uint32_t pullcache_size;
+};
+
+
+#define ACMOP_getssid           4
+#define ACM_GETBY_ssidref  1
+#define ACM_GETBY_domainid 2
+struct acm_getssid {
+    /* IN */
+    uint32_t get_ssid_by; /* ACM_GETBY_* */
+    union {
+        domaintype_t domainid;
+        ssidref_t    ssidref;
+    } id;
+    XEN_GUEST_HANDLE_64(void) ssidbuf;
+    uint32_t ssidbuf_size;
+};
+
+#define ACMOP_getdecision      5
+struct acm_getdecision {
+    /* IN */
+    uint32_t get_decision_by1; /* ACM_GETBY_* */
+    uint32_t get_decision_by2; /* ACM_GETBY_* */
+    union {
+        domaintype_t domainid;
+        ssidref_t    ssidref;
+    } id1;
+    union {
+        domaintype_t domainid;
+        ssidref_t    ssidref;
+    } id2;
+    uint32_t hook;
+    /* OUT */
+    uint32_t acm_decision;
+};
+
+
+#define ACMOP_chgpolicy        6
+struct acm_change_policy {
+    /* IN */
+    XEN_GUEST_HANDLE_64(void) policy_pushcache;
+    uint32_t policy_pushcache_size;
+    XEN_GUEST_HANDLE_64(void) del_array;
+    uint32_t delarray_size;
+    XEN_GUEST_HANDLE_64(void) chg_array;
+    uint32_t chgarray_size;
+    /* OUT */
+    /* array with error code */
+    XEN_GUEST_HANDLE_64(void) err_array;
+    uint32_t errarray_size;
+};
+
+#define ACMOP_relabeldoms       7
+struct acm_relabel_doms {
+    /* IN */
+    XEN_GUEST_HANDLE_64(void) relabel_map;
+    uint32_t relabel_map_size;
+    /* OUT */
+    XEN_GUEST_HANDLE_64(void) err_array;
+    uint32_t errarray_size;
+};
+
+/* future interface to Xen */
+struct xen_acmctl {
+    uint32_t cmd;
+    uint32_t interface_version;
+    union {
+        struct acm_setpolicy     setpolicy;
+        struct acm_getpolicy     getpolicy;
+        struct acm_dumpstats     dumpstats;
+        struct acm_getssid       getssid;
+        struct acm_getdecision   getdecision;
+        struct acm_change_policy change_policy;
+        struct acm_relabel_doms  relabel_doms;
+    } u;
+};
+
+typedef struct xen_acmctl xen_acmctl_t;
+DEFINE_XEN_GUEST_HANDLE(xen_acmctl_t);
+
+#endif /* __XEN_PUBLIC_ACM_OPS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/xsm/acm.h
+++ linux-ec2-2.6.32/include/xen/interface/xsm/acm.h
@@ -0,0 +1,235 @@
+/*
+ * acm.h: Xen access control module interface defintions
+ *
+ * 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.
+ *
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Copyright (c) 2005, International Business Machines Corporation.
+ */
+
+#ifndef _XEN_PUBLIC_ACM_H
+#define _XEN_PUBLIC_ACM_H
+
+#include "../xen.h"
+
+/* if ACM_DEBUG defined, all hooks should
+ * print a short trace message (comment it out
+ * when not in testing mode )
+ */
+/* #define ACM_DEBUG */
+
+#ifdef ACM_DEBUG
+#  define printkd(fmt, args...) printk(fmt,## args)
+#else
+#  define printkd(fmt, args...)
+#endif
+
+/* default ssid reference value if not supplied */
+#define ACM_DEFAULT_SSID  0x0
+#define ACM_DEFAULT_LOCAL_SSID  0x0
+
+/* Internal ACM ERROR types */
+#define ACM_OK     0
+#define ACM_UNDEF   -1
+#define ACM_INIT_SSID_ERROR  -2
+#define ACM_INIT_SOID_ERROR  -3
+#define ACM_ERROR          -4
+
+/* External ACCESS DECISIONS */
+#define ACM_ACCESS_PERMITTED        0
+#define ACM_ACCESS_DENIED           -111
+#define ACM_NULL_POINTER_ERROR      -200
+
+/*
+   Error codes reported in when trying to test for a new policy
+   These error codes are reported in an array of tuples where
+   each error code is followed by a parameter describing the error
+   more closely, such as a domain id.
+*/
+#define ACM_EVTCHN_SHARING_VIOLATION       0x100
+#define ACM_GNTTAB_SHARING_VIOLATION       0x101
+#define ACM_DOMAIN_LOOKUP                  0x102
+#define ACM_CHWALL_CONFLICT                0x103
+#define ACM_SSIDREF_IN_USE                 0x104
+
+
+/* primary policy in lower 4 bits */
+#define ACM_NULL_POLICY 0
+#define ACM_CHINESE_WALL_POLICY 1
+#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
+#define ACM_POLICY_UNDEFINED 15
+
+/* combinations have secondary policy component in higher 4bit */
+#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \
+    ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY)
+
+/* policy: */
+#define ACM_POLICY_NAME(X) \
+ ((X) == (ACM_NULL_POLICY)) ? "NULL" :                        \
+    ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL" :        \
+    ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT" : \
+    ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT" : \
+     "UNDEFINED"
+
+/* the following policy versions must be increased
+ * whenever the interpretation of the related
+ * policy's data structure changes
+ */
+#define ACM_POLICY_VERSION 4
+#define ACM_CHWALL_VERSION 1
+#define ACM_STE_VERSION  1
+
+/* defines a ssid reference used by xen */
+typedef uint32_t ssidref_t;
+
+/* hooks that are known to domains */
+#define ACMHOOK_none          0
+#define ACMHOOK_sharing       1
+#define ACMHOOK_authorization 2
+#define ACMHOOK_conflictset   3
+
+/* -------security policy relevant type definitions-------- */
+
+/* type identifier; compares to "equal" or "not equal" */
+typedef uint16_t domaintype_t;
+
+/* CHINESE WALL POLICY DATA STRUCTURES
+ *
+ * current accumulated conflict type set:
+ * When a domain is started and has a type that is in
+ * a conflict set, the conflicting types are incremented in
+ * the aggregate set. When a domain is destroyed, the 
+ * conflicting types to its type are decremented.
+ * If a domain has multiple types, this procedure works over
+ * all those types.
+ *
+ * conflict_aggregate_set[i] holds the number of
+ *   running domains that have a conflict with type i.
+ *
+ * running_types[i] holds the number of running domains
+ *        that include type i in their ssidref-referenced type set
+ *
+ * conflict_sets[i][j] is "0" if type j has no conflict
+ *    with type i and is "1" otherwise.
+ */
+/* 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 */
+
+/* V3 of the policy buffer aded a version structure */
+struct acm_policy_version
+{
+    uint32_t major;
+    uint32_t minor;
+};
+
+
+/* each buffer consists of all policy information for
+ * the respective policy given in the policy code
+ *
+ * acm_policy_buffer, acm_chwall_policy_buffer,
+ * and acm_ste_policy_buffer need to stay 32-bit aligned
+ * because we create binary policies also with external
+ * tools that assume packed representations (e.g. the java tool)
+ */
+struct acm_policy_buffer {
+    uint32_t magic;
+    uint32_t policy_version; /* ACM_POLICY_VERSION */
+    uint32_t len;
+    uint32_t policy_reference_offset;
+    uint32_t primary_policy_code;
+    uint32_t primary_buffer_offset;
+    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 */
+};
+
+
+struct acm_policy_reference_buffer {
+    uint32_t len;
+};
+
+struct acm_chwall_policy_buffer {
+    uint32_t policy_version; /* ACM_CHWALL_VERSION */
+    uint32_t policy_code;
+    uint32_t chwall_max_types;
+    uint32_t chwall_max_ssidrefs;
+    uint32_t chwall_max_conflictsets;
+    uint32_t chwall_ssid_offset;
+    uint32_t chwall_conflict_sets_offset;
+    uint32_t chwall_running_types_offset;
+    uint32_t chwall_conflict_aggregate_offset;
+};
+
+struct acm_ste_policy_buffer {
+    uint32_t policy_version; /* ACM_STE_VERSION */
+    uint32_t policy_code;
+    uint32_t ste_max_types;
+    uint32_t ste_max_ssidrefs;
+    uint32_t ste_ssid_offset;
+};
+
+struct acm_stats_buffer {
+    uint32_t magic;
+    uint32_t len;
+    uint32_t primary_policy_code;
+    uint32_t primary_stats_offset;
+    uint32_t secondary_policy_code;
+    uint32_t secondary_stats_offset;
+};
+
+struct acm_ste_stats_buffer {
+    uint32_t ec_eval_count;
+    uint32_t gt_eval_count;
+    uint32_t ec_denied_count;
+    uint32_t gt_denied_count;
+    uint32_t ec_cachehit_count;
+    uint32_t gt_cachehit_count;
+};
+
+struct acm_ssid_buffer {
+    uint32_t len;
+    ssidref_t ssidref;
+    uint32_t policy_reference_offset;
+    uint32_t primary_policy_code;
+    uint32_t primary_max_types;
+    uint32_t primary_types_offset;
+    uint32_t secondary_policy_code;
+    uint32_t secondary_max_types;
+    uint32_t secondary_types_offset;
+};
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/xsm/flask_op.h
+++ linux-ec2-2.6.32/include/xen/interface/xsm/flask_op.h
@@ -0,0 +1,45 @@
+/*
+ *  This file contains the flask_op hypercall commands and definitions.
+ *
+ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  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.
+ */
+
+#ifndef __FLASK_OP_H__
+#define __FLASK_OP_H__
+
+#define FLASK_LOAD              1
+#define FLASK_GETENFORCE        2
+#define FLASK_SETENFORCE        3
+#define FLASK_CONTEXT_TO_SID    4
+#define FLASK_SID_TO_CONTEXT    5
+#define FLASK_ACCESS            6
+#define FLASK_CREATE            7
+#define FLASK_RELABEL           8
+#define FLASK_USER              9
+#define FLASK_POLICYVERS        10
+#define FLASK_GETBOOL           11
+#define FLASK_SETBOOL           12
+#define FLASK_COMMITBOOLS       13
+#define FLASK_MLS               14
+#define FLASK_DISABLE           15
+#define FLASK_GETAVC_THRESHOLD  16
+#define FLASK_SETAVC_THRESHOLD  17
+#define FLASK_AVC_HASHSTATS     18
+#define FLASK_AVC_CACHESTATS    19
+#define FLASK_MEMBER            20
+
+#define FLASK_LAST              FLASK_MEMBER
+
+typedef struct flask_op {
+    uint32_t  cmd;
+    uint32_t  size;
+    char      *buf;
+} flask_op_t;
+
+DEFINE_XEN_GUEST_HANDLE(flask_op_t);
+
+#endif
--- linux-ec2-2.6.32.orig/include/xen/interface/io/blkif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/blkif.h
@@ -3,6 +3,24 @@
  *
  * Unified block-device I/O interface for Xen guest OSes.
  *
+ * 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) 2003-2004, Keir Fraser
  */
 
@@ -24,8 +42,10 @@
  * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
  */
 
-typedef uint16_t blkif_vdev_t;
-typedef uint64_t blkif_sector_t;
+#ifndef blkif_vdev_t
+#define blkif_vdev_t   uint16_t
+#endif
+#define blkif_sector_t uint64_t
 
 /*
  * REQUEST CODES.
@@ -34,7 +54,7 @@
 #define BLKIF_OP_WRITE             1
 /*
  * Recognised only if "feature-barrier" is present in backend xenbus info.
- * The "feature_barrier" node contains a boolean indicating whether barrier
+ * The "feature-barrier" node contains a boolean indicating whether barrier
  * requests are likely to succeed or fail. Either way, a barrier request
  * may fail at any time with BLKIF_RSP_EOPNOTSUPP if it is unsupported by
  * the underlying block-device hardware. The boolean simply indicates whether
@@ -43,33 +63,61 @@
  * create the "feature-barrier" node!
  */
 #define BLKIF_OP_WRITE_BARRIER     2
+/*
+ * Recognised if "feature-flush-cache" is present in backend xenbus
+ * info.  A flush will ask the underlying storage hardware to flush its
+ * non-volatile caches as appropriate.  The "feature-flush-cache" node
+ * contains a boolean indicating whether flush requests are likely to
+ * succeed or fail. Either way, a flush request may fail at any time
+ * with BLKIF_RSP_EOPNOTSUPP if it is unsupported by the underlying
+ * block-device hardware. The boolean simply indicates whether or not it
+ * is worthwhile for the frontend to attempt flushes.  If a backend does
+ * not recognise BLKIF_OP_WRITE_FLUSH_CACHE, it should *not* create the
+ * "feature-flush-cache" node!
+ */
+#define BLKIF_OP_FLUSH_DISKCACHE   3
+/*
+ * Device specific command packet contained within the request
+ */
+#define BLKIF_OP_PACKET            4
 
 /*
  * Maximum scatter/gather segments per request.
- * This is carefully chosen so that sizeof(struct blkif_ring) <= PAGE_SIZE.
+ * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
  * NB. This could be 12 if the ring indexes weren't stored in the same page.
  */
 #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
 
+/*
+ * NB. first_sect and last_sect in blkif_request_segment, as well as
+ * sector_number in blkif_request, are always expressed in 512-byte units.
+ * However they must be properly aligned to the real sector size of the
+ * physical disk, which is reported in the "sector-size" node in the backend
+ * xenbus info. Also the xenbus "sectors" node is expressed in 512-byte units.
+ */
+struct blkif_request_segment {
+    grant_ref_t gref;        /* reference to I/O buffer frame        */
+    /* @first_sect: first sector in frame to transfer (inclusive).   */
+    /* @last_sect: last sector in frame to transfer (inclusive).     */
+    uint8_t     first_sect, last_sect;
+};
+
 struct blkif_request {
-	uint8_t        operation;    /* BLKIF_OP_???                         */
-	uint8_t        nr_segments;  /* number of segments                   */
-	blkif_vdev_t   handle;       /* only for read/write requests         */
-	uint64_t       id;           /* private guest value, echoed in resp  */
-	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
-	struct blkif_request_segment {
-		grant_ref_t gref;        /* reference to I/O buffer frame        */
-		/* @first_sect: first sector in frame to transfer (inclusive).   */
-		/* @last_sect: last sector in frame to transfer (inclusive).     */
-		uint8_t     first_sect, last_sect;
-	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+    uint8_t        operation;    /* BLKIF_OP_???                         */
+    uint8_t        nr_segments;  /* number of segments                   */
+    blkif_vdev_t   handle;       /* only for read/write requests         */
+    uint64_t       id;           /* private guest value, echoed in resp  */
+    blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
+typedef struct blkif_request blkif_request_t;
 
 struct blkif_response {
-	uint64_t        id;              /* copied from request */
-	uint8_t         operation;       /* copied from request */
-	int16_t         status;          /* BLKIF_RSP_???       */
+    uint64_t        id;              /* copied from request */
+    uint8_t         operation;       /* copied from request */
+    int16_t         status;          /* BLKIF_RSP_???       */
 };
+typedef struct blkif_response blkif_response_t;
 
 /*
  * STATUS RETURN CODES.
--- linux-ec2-2.6.32.orig/include/xen/interface/io/pciif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/pciif.h
@@ -0,0 +1,124 @@
+/*
+ * PCI Backend/Frontend Common Data Structures & Macros
+ *
+ * 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.
+ *
+ *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
+ */
+#ifndef __XEN_PCI_COMMON_H__
+#define __XEN_PCI_COMMON_H__
+
+/* Be sure to bump this number if you change this file */
+#define XEN_PCI_MAGIC "7"
+
+/* xen_pci_sharedinfo flags */
+#define _XEN_PCIF_active     (0)
+#define XEN_PCIF_active      (1<<_XEN_PCIF_active)
+#define _XEN_PCIB_AERHANDLER (1)
+#define XEN_PCIB_AERHANDLER  (1<<_XEN_PCIB_AERHANDLER)
+#define _XEN_PCIB_active     (2)
+#define XEN_PCIB_active      (1<<_XEN_PCIB_active)
+
+/* 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)
+#define XEN_PCI_OP_aer_detected 	(6)
+#define XEN_PCI_OP_aer_resume		(7)
+#define XEN_PCI_OP_aer_mmio		(8)
+#define XEN_PCI_OP_aer_slotreset	(9)
+
+/* xen_pci_op error numbers */
+#define XEN_PCI_ERR_success          (0)
+#define XEN_PCI_ERR_dev_not_found   (-1)
+#define XEN_PCI_ERR_invalid_offset  (-2)
+#define XEN_PCI_ERR_access_denied   (-3)
+#define XEN_PCI_ERR_not_implemented (-4)
+/* 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;
+
+    /* OUT: will contain an error number (if any) from errno.h */
+    int32_t err;
+
+    /* IN: which device to touch */
+    uint32_t domain; /* PCI Domain/Segment */
+    uint32_t bus;
+    uint32_t devfn;
+
+    /* IN: which configuration registers to touch */
+    int32_t offset;
+    int32_t size;
+
+    /* 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];
+};
+
+/*used for pcie aer handling*/
+struct xen_pcie_aer_op
+{
+
+    /* IN: what action to perform: XEN_PCI_OP_* */
+    uint32_t cmd;
+    /*IN/OUT: return aer_op result or carry error_detected state as input*/
+    int32_t err;
+
+    /* IN: which device to touch */
+    uint32_t domain; /* PCI Domain/Segment*/
+    uint32_t bus;
+    uint32_t devfn;
+};
+struct xen_pci_sharedinfo {
+    /* flags - XEN_PCIF_* */
+    uint32_t flags;
+    struct xen_pci_op op;
+    struct xen_pcie_aer_op aer_op;
+};
+
+#endif /* __XEN_PCI_COMMON_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/xs_wire.h
+++ linux-ec2-2.6.32/include/xen/interface/io/xs_wire.h
@@ -1,6 +1,25 @@
 /*
  * Details of the "wire" protocol between Xen Store Daemon and client
  * library or guest kernel.
+ *
+ * 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) 2005 Rusty Russell IBM Corporation
  */
 
@@ -26,7 +45,9 @@
     XS_SET_PERMS,
     XS_WATCH_EVENT,
     XS_ERROR,
-    XS_IS_DOMAIN_INTRODUCED
+    XS_IS_DOMAIN_INTRODUCED,
+    XS_RESUME,
+    XS_SET_TARGET
 };
 
 #define XS_WRITE_NONE "NONE"
@@ -39,8 +60,14 @@
     int errnum;
     const char *errstring;
 };
+#ifdef EINVAL
 #define XSD_ERROR(x) { x, #x }
-static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
+/* LINTED: static unused */
+static struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+    = {
     XSD_ERROR(EINVAL),
     XSD_ERROR(EACCES),
     XSD_ERROR(EEXIST),
@@ -56,6 +83,7 @@
     XSD_ERROR(EAGAIN),
     XSD_ERROR(EISCONN)
 };
+#endif
 
 struct xsd_sockmsg
 {
@@ -84,4 +112,11 @@
     XENSTORE_RING_IDX rsp_cons, rsp_prod;
 };
 
+/* Violating this is very bad.  See docs/misc/xenstore.txt. */
+#define XENSTORE_PAYLOAD_MAX 4096
+
+/* Violating these just gets you an error back */
+#define XENSTORE_ABS_PATH_MAX 3072
+#define XENSTORE_REL_PATH_MAX 2048
+
 #endif /* _XS_WIRE_H */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/fsif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/fsif.h
@@ -0,0 +1,192 @@
+/******************************************************************************
+ * fsif.h
+ * 
+ * Interface to FS level split device drivers.
+ * 
+ * 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) 2007, Grzegorz Milos, <gm281@cam.ac.uk>.
+ */
+
+#ifndef __XEN_PUBLIC_IO_FSIF_H__
+#define __XEN_PUBLIC_IO_FSIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+#define REQ_FILE_OPEN        1
+#define REQ_FILE_CLOSE       2
+#define REQ_FILE_READ        3
+#define REQ_FILE_WRITE       4
+#define REQ_STAT             5
+#define REQ_FILE_TRUNCATE    6
+#define REQ_REMOVE           7
+#define REQ_RENAME           8
+#define REQ_CREATE           9
+#define REQ_DIR_LIST        10
+#define REQ_CHMOD           11
+#define REQ_FS_SPACE        12
+#define REQ_FILE_SYNC       13
+
+struct fsif_open_request {
+    grant_ref_t gref;
+};
+
+struct fsif_close_request {
+    uint32_t fd;
+};
+
+struct fsif_read_request {
+    uint32_t fd;
+    int32_t pad;
+    uint64_t len;
+    uint64_t offset;
+    grant_ref_t grefs[1];  /* Variable length */
+};
+
+struct fsif_write_request {
+    uint32_t fd;
+    int32_t pad;
+    uint64_t len;
+    uint64_t offset;
+    grant_ref_t grefs[1];  /* Variable length */
+};
+
+struct fsif_stat_request {
+    uint32_t fd;
+};
+
+/* 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  stat_ret;
+    int64_t  stat_size;
+    int64_t  stat_atime;
+    int64_t  stat_mtime;
+    int64_t  stat_ctime;
+};
+
+struct fsif_truncate_request {
+    uint32_t fd;
+    int32_t pad;
+    int64_t length;
+};
+
+struct fsif_remove_request {
+    grant_ref_t gref;
+};
+
+struct fsif_rename_request {
+    uint16_t old_name_offset;
+    uint16_t new_name_offset;
+    grant_ref_t gref;
+};
+
+struct fsif_create_request {
+    int8_t directory;
+    int8_t pad;
+    int16_t pad2;
+    int32_t mode;
+    grant_ref_t gref;
+};
+
+struct fsif_list_request {
+    uint32_t offset;
+    grant_ref_t gref;
+};
+
+#define NR_FILES_SHIFT  0
+#define NR_FILES_SIZE   16   /* 16 bits for the number of files mask */
+#define NR_FILES_MASK   (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT)
+#define ERROR_SIZE      32   /* 32 bits for the error mask */
+#define ERROR_SHIFT     (NR_FILES_SIZE + NR_FILES_SHIFT)
+#define ERROR_MASK      (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT)
+#define HAS_MORE_SHIFT  (ERROR_SHIFT + ERROR_SIZE)    
+#define HAS_MORE_FLAG   (1ULL << HAS_MORE_SHIFT)
+
+struct fsif_chmod_request {
+    uint32_t fd;
+    int32_t mode;
+};
+
+struct fsif_space_request {
+    grant_ref_t gref;
+};
+
+struct fsif_sync_request {
+    uint32_t fd;
+};
+
+
+/* FS operation request */
+struct fsif_request {
+    uint8_t type;                 /* Type of the request                  */
+    uint8_t pad;
+    uint16_t id;                  /* Request ID, copied to the response   */
+    uint32_t pad2;
+    union {
+        struct fsif_open_request     fopen;
+        struct fsif_close_request    fclose;
+        struct fsif_read_request     fread;
+        struct fsif_write_request    fwrite;
+        struct fsif_stat_request     fstat;
+        struct fsif_truncate_request ftruncate;
+        struct fsif_remove_request   fremove;
+        struct fsif_rename_request   frename;
+        struct fsif_create_request   fcreate;
+        struct fsif_list_request     flist;
+        struct fsif_chmod_request    fchmod;
+        struct fsif_space_request    fspace;
+        struct fsif_sync_request     fsync;
+    } u;
+};
+typedef struct fsif_request fsif_request_t;
+
+/* FS operation response */
+struct fsif_response {
+    uint16_t id;
+    uint16_t pad1;
+    uint32_t pad2;
+    union {
+        uint64_t ret_val;
+        struct fsif_stat_response fstat;
+    } u;
+};
+
+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);
+
+#define STATE_INITIALISED     "init"
+#define STATE_READY           "ready"
+#define STATE_CLOSING         "closing"
+#define STATE_CLOSED          "closed"
+
+
+#endif
--- linux-ec2-2.6.32.orig/include/xen/interface/io/tpmif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/tpmif.h
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * tpmif.h
+ *
+ * TPM I/O interface for Xen guest OSes.
+ *
+ * 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) 2005, IBM Corporation
+ *
+ * Author: Stefan Berger, stefanb@us.ibm.com
+ * Grant table support: Mahadevan Gomathisankaran
+ *
+ * This code has been derived from tools/libxc/xen/io/netif.h
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_TPMIF_H__
+#define __XEN_PUBLIC_IO_TPMIF_H__
+
+#include "../grant_table.h"
+
+struct tpmif_tx_request {
+    unsigned long addr;   /* Machine address of packet.   */
+    grant_ref_t ref;      /* grant table access reference */
+    uint16_t unused;
+    uint16_t size;        /* Packet size in bytes.        */
+};
+typedef struct tpmif_tx_request tpmif_tx_request_t;
+
+/*
+ * The TPMIF_TX_RING_SIZE defines the number of pages the
+ * front-end and backend can exchange (= size of array).
+ */
+typedef uint32_t TPMIF_RING_IDX;
+
+#define TPMIF_TX_RING_SIZE 1
+
+/* This structure must fit in a memory page. */
+
+struct tpmif_ring {
+    struct tpmif_tx_request req;
+};
+typedef struct tpmif_ring tpmif_ring_t;
+
+struct tpmif_tx_interface {
+    struct tpmif_ring ring[TPMIF_TX_RING_SIZE];
+};
+typedef struct tpmif_tx_interface tpmif_tx_interface_t;
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/cdromif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/cdromif.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * cdromif.h
+ *
+ * Shared definitions between backend driver and Xen guest Virtual CDROM
+ * block device.
+ *
+ * Copyright (c) 2008, Pat Campell  plc@novell.com
+ *
+ * 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_PUBLIC_IO_CDROMIF_H__
+#define __XEN_PUBLIC_IO_CDROMIF_H__
+
+/*
+ * Queries backend for CDROM support
+ */
+#define XEN_TYPE_CDROM_SUPPORT         _IO('c', 1)
+
+struct xen_cdrom_support
+{
+	uint32_t type;
+	int8_t ret;                  /* returned, 0 succeded, -1 error */
+	int8_t err;                  /* returned, backend errno */
+	int8_t supported;            /* returned, 1 supported */
+};
+
+/*
+ * Opens backend device, returns drive geometry or
+ * any encountered errors
+ */
+#define XEN_TYPE_CDROM_OPEN            _IO('c', 2)
+
+struct xen_cdrom_open
+{
+	uint32_t type;
+	int8_t ret;
+	int8_t err;
+	int8_t pad;
+	int8_t media_present;        /* returned */
+	uint32_t sectors;            /* returned */
+	uint32_t sector_size;        /* returned */
+	int32_t payload_offset;      /* offset to backend node name payload */
+};
+
+/*
+ * Queries backend for media changed status
+ */
+#define XEN_TYPE_CDROM_MEDIA_CHANGED   _IO('c', 3)
+
+struct xen_cdrom_media_changed
+{
+	uint32_t type;
+	int8_t ret;
+	int8_t err;
+	int8_t media_changed;        /* returned */
+};
+
+/*
+ * Sends vcd generic CDROM packet to backend, followed
+ * immediately by the vcd_generic_command payload
+ */
+#define XEN_TYPE_CDROM_PACKET          _IO('c', 4)
+
+struct xen_cdrom_packet
+{
+	uint32_t type;
+	int8_t ret;
+	int8_t err;
+	int8_t pad[2];
+	int32_t payload_offset;      /* offset to vcd_generic_command payload */
+};
+
+/* CDROM_PACKET_COMMAND, payload for XEN_TYPE_CDROM_PACKET */
+struct vcd_generic_command
+{
+	uint8_t  cmd[CDROM_PACKET_SIZE];
+	uint8_t  pad[4];
+	uint32_t buffer_offset;
+	uint32_t buflen;
+	int32_t  stat;
+	uint32_t sense_offset;
+	uint8_t  data_direction;
+	uint8_t  pad1[3];
+	int32_t  quiet;
+	int32_t  timeout;
+};
+
+union xen_block_packet
+{
+	uint32_t type;
+	struct xen_cdrom_support xcs;
+	struct xen_cdrom_open xco;
+	struct xen_cdrom_media_changed xcmc;
+	struct xen_cdrom_packet xcp;
+};
+
+#define PACKET_PAYLOAD_OFFSET (sizeof(struct xen_cdrom_packet))
+#define PACKET_SENSE_OFFSET (PACKET_PAYLOAD_OFFSET + sizeof(struct vcd_generic_command))
+#define PACKET_BUFFER_OFFSET (PACKET_SENSE_OFFSET + sizeof(struct request_sense))
+#define MAX_PACKET_DATA (PAGE_SIZE - sizeof(struct xen_cdrom_packet) - \
+            sizeof(struct vcd_generic_command) - sizeof(struct request_sense))
+
+#endif
--- linux-ec2-2.6.32.orig/include/xen/interface/io/netif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/netif.h
@@ -3,6 +3,24 @@
  *
  * Unified network-device I/O interface for Xen guest OSes.
  *
+ * 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) 2003-2004, Keir Fraser
  */
 
@@ -47,18 +65,21 @@
 #define _NETTXF_extra_info     (3)
 #define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
 
-struct xen_netif_tx_request {
+struct netif_tx_request {
     grant_ref_t gref;      /* Reference to buffer page */
     uint16_t offset;       /* Offset within buffer page */
     uint16_t flags;        /* NETTXF_* */
     uint16_t id;           /* Echoed in response message. */
     uint16_t size;         /* Packet size in bytes.       */
 };
+typedef struct netif_tx_request netif_tx_request_t;
 
 /* Types of netif_extra_info descriptors. */
-#define XEN_NETIF_EXTRA_TYPE_NONE  (0)  /* Never used - invalid */
-#define XEN_NETIF_EXTRA_TYPE_GSO   (1)  /* u.gso */
-#define XEN_NETIF_EXTRA_TYPE_MAX   (2)
+#define XEN_NETIF_EXTRA_TYPE_NONE      (0)  /* Never used - invalid */
+#define XEN_NETIF_EXTRA_TYPE_GSO       (1)  /* u.gso */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2)  /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3)  /* u.mcast */
+#define XEN_NETIF_EXTRA_TYPE_MAX       (4)
 
 /* netif_extra_info flags. */
 #define _XEN_NETIF_EXTRA_FLAG_MORE (0)
@@ -71,49 +92,68 @@
  * This structure needs to fit within both netif_tx_request and
  * netif_rx_response for compatibility.
  */
-struct xen_netif_extra_info {
-	uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
-	uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
-
-	union {
-		struct {
-			/*
-			 * Maximum payload size of each segment. For
-			 * example, for TCP this is just the path MSS.
-			 */
-			uint16_t size;
-
-			/*
-			 * GSO type. This determines the protocol of
-			 * the packet and any extra features required
-			 * to segment the packet properly.
-			 */
-			uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
-
-			/* Future expansion. */
-			uint8_t pad;
-
-			/*
-			 * GSO features. This specifies any extra GSO
-			 * features required to process this packet,
-			 * such as ECN support for TCPv4.
-			 */
-			uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
-		} gso;
+struct netif_extra_info {
+    uint8_t type;  /* XEN_NETIF_EXTRA_TYPE_* */
+    uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */
+
+    union {
+        /*
+         * XEN_NETIF_EXTRA_TYPE_GSO:
+         */
+        struct {
+            /*
+             * Maximum payload size of each segment. For example, for TCP this
+             * is just the path MSS.
+             */
+            uint16_t size;
+
+            /*
+             * GSO type. This determines the protocol of the packet and any
+             * extra features required to segment the packet properly.
+             */
+            uint8_t type; /* XEN_NETIF_GSO_TYPE_* */
+
+            /* Future expansion. */
+            uint8_t pad;
+
+            /*
+             * GSO features. This specifies any extra GSO features required
+             * to process this packet, such as ECN support for TCPv4.
+             */
+            uint16_t features; /* XEN_NETIF_GSO_FEAT_* */
+        } gso;
+
+        /*
+         * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}:
+         * Backend advertises availability via 'feature-multicast-control'
+         * xenbus node containing value '1'.
+         * Frontend requests this feature by advertising
+         * 'request-multicast-control' xenbus node containing value '1'.
+         * If multicast control is requested then multicast flooding is
+         * disabled and the frontend must explicitly register its interest
+         * in multicast groups using dummy transmit requests containing
+         * MCAST_{ADD,DEL} extra-info fragments.
+         */
+        struct {
+            uint8_t addr[6]; /* Address to add/remove. */
+        } mcast;
 
-		uint16_t pad[3];
-	} u;
+        uint16_t pad[3];
+    } u;
 };
+typedef struct netif_extra_info netif_extra_info_t;
 
-struct xen_netif_tx_response {
-	uint16_t id;
-	int16_t  status;       /* NETIF_RSP_* */
+struct netif_tx_response {
+    uint16_t id;
+    int16_t  status;       /* NETIF_RSP_* */
 };
+typedef struct netif_tx_response netif_tx_response_t;
 
-struct xen_netif_rx_request {
-	uint16_t    id;        /* Echoed in response message.        */
-	grant_ref_t gref;      /* Reference to incoming granted frame */
+struct netif_rx_request {
+    uint16_t    id;        /* Echoed in response message.        */
+    grant_ref_t gref;      /* Reference to incoming granted frame */
 };
+typedef struct netif_rx_request netif_rx_request_t;
 
 /* Packet data has been validated against protocol checksum. */
 #define _NETRXF_data_validated (0)
@@ -131,23 +171,34 @@
 #define _NETRXF_extra_info     (3)
 #define  NETRXF_extra_info     (1U<<_NETRXF_extra_info)
 
-struct xen_netif_rx_response {
+struct netif_rx_response {
     uint16_t id;
     uint16_t offset;       /* Offset in page of start of received packet  */
     uint16_t flags;        /* NETRXF_* */
     int16_t  status;       /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
 };
+typedef struct netif_rx_response netif_rx_response_t;
 
 /*
  * Generate netif ring structures and types.
  */
 
+#if defined(CONFIG_XEN) || defined(HAVE_XEN_PLATFORM_COMPAT_H)
+DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response);
+DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response);
+#else
+#define xen_netif_tx_request netif_tx_request
+#define xen_netif_rx_request netif_rx_request
+#define xen_netif_tx_response netif_tx_response
+#define xen_netif_rx_response netif_rx_response
 DEFINE_RING_TYPES(xen_netif_tx,
 		  struct xen_netif_tx_request,
 		  struct xen_netif_tx_response);
 DEFINE_RING_TYPES(xen_netif_rx,
 		  struct xen_netif_rx_request,
 		  struct xen_netif_rx_response);
+#define xen_netif_extra_info netif_extra_info
+#endif
 
 #define NETIF_RSP_DROPPED         -2
 #define NETIF_RSP_ERROR           -1
--- linux-ec2-2.6.32.orig/include/xen/interface/io/kbdif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/kbdif.h
@@ -45,34 +45,38 @@
  */
 #define XENKBD_TYPE_POS     4
 
-struct xenkbd_motion {
-	uint8_t type;		/* XENKBD_TYPE_MOTION */
-	int32_t rel_x;		/* relative X motion */
-	int32_t rel_y;		/* relative Y motion */
-	int32_t rel_z;		/* relative Z motion (wheel) */
-};
-
-struct xenkbd_key {
-	uint8_t type;		/* XENKBD_TYPE_KEY */
-	uint8_t pressed;	/* 1 if pressed; 0 otherwise */
-	uint32_t keycode;	/* KEY_* from linux/input.h */
-};
-
-struct xenkbd_position {
-	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 rel_z;		/* relative Z motion (wheel) */
+struct xenkbd_motion
+{
+    uint8_t type;        /* XENKBD_TYPE_MOTION */
+    int32_t rel_x;       /* relative X motion */
+    int32_t rel_y;       /* relative Y motion */
+    int32_t rel_z;       /* relative Z motion (wheel) */
+};
+
+struct xenkbd_key
+{
+    uint8_t type;         /* XENKBD_TYPE_KEY */
+    uint8_t pressed;      /* 1 if pressed; 0 otherwise */
+    uint32_t keycode;     /* KEY_* from linux/input.h */
+};
+
+struct xenkbd_position
+{
+    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 rel_z;       /* relative Z motion (wheel) */
 };
 
 #define XENKBD_IN_EVENT_SIZE 40
 
-union xenkbd_in_event {
-	uint8_t type;
-	struct xenkbd_motion motion;
-	struct xenkbd_key key;
-	struct xenkbd_position pos;
-	char pad[XENKBD_IN_EVENT_SIZE];
+union xenkbd_in_event
+{
+    uint8_t type;
+    struct xenkbd_motion motion;
+    struct xenkbd_key key;
+    struct xenkbd_position pos;
+    char pad[XENKBD_IN_EVENT_SIZE];
 };
 
 /* Out events (frontend -> backend) */
@@ -85,9 +89,10 @@
 
 #define XENKBD_OUT_EVENT_SIZE 40
 
-union xenkbd_out_event {
-	uint8_t type;
-	char pad[XENKBD_OUT_EVENT_SIZE];
+union xenkbd_out_event
+{
+    uint8_t type;
+    char pad[XENKBD_OUT_EVENT_SIZE];
 };
 
 /* shared page */
@@ -96,21 +101,22 @@
 #define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
 #define XENKBD_IN_RING_OFFS 1024
 #define XENKBD_IN_RING(page) \
-	((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+    ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
 #define XENKBD_IN_RING_REF(page, idx) \
-	(XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+    (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
 
 #define XENKBD_OUT_RING_SIZE 1024
 #define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
 #define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
 #define XENKBD_OUT_RING(page) \
-	((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+    ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
 #define XENKBD_OUT_RING_REF(page, idx) \
-	(XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+    (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
 
-struct xenkbd_page {
-	uint32_t in_cons, in_prod;
-	uint32_t out_cons, out_prod;
+struct xenkbd_page
+{
+    uint32_t in_cons, in_prod;
+    uint32_t out_cons, out_prod;
 };
 
 #endif
--- linux-ec2-2.6.32.orig/include/xen/interface/io/protocols.h
+++ linux-ec2-2.6.32/include/xen/interface/io/protocols.h
@@ -1,10 +1,31 @@
+/******************************************************************************
+ * 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
@@ -12,8 +33,6 @@
 # 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
--- linux-ec2-2.6.32.orig/include/xen/interface/io/xenbus.h
+++ linux-ec2-2.6.32/include/xen/interface/io/xenbus.h
@@ -3,42 +3,68 @@
  *
  * Xenbus protocol details.
  *
+ * 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) 2005 XenSource Ltd.
  */
 
 #ifndef _XEN_PUBLIC_IO_XENBUS_H
 #define _XEN_PUBLIC_IO_XENBUS_H
 
-/* The state of either end of the Xenbus, i.e. the current communication
-   status of initialisation across the bus.  States here imply nothing about
-   the state of the connection between the driver and the kernel's device
-   layers.  */
-enum xenbus_state
-{
-	XenbusStateUnknown      = 0,
-	XenbusStateInitialising = 1,
-	XenbusStateInitWait     = 2,  /* Finished early
-					 initialisation, but waiting
-					 for information from the peer
-					 or hotplug scripts. */
-	XenbusStateInitialised  = 3,  /* Initialised and waiting for a
-					 connection from the peer. */
-	XenbusStateConnected    = 4,
-	XenbusStateClosing      = 5,  /* The device is being closed
-					 due to an error or an unplug
-					 event. */
-	XenbusStateClosed       = 6
+/*
+ * The state of either end of the Xenbus, i.e. the current communication
+ * status of initialisation across the bus.  States here imply nothing about
+ * the state of the connection between the driver and the kernel's device
+ * layers.
+ */
+enum xenbus_state {
+    XenbusStateUnknown       = 0,
+
+    XenbusStateInitialising  = 1,
+
+    /*
+     * InitWait: Finished early initialisation but waiting for information
+     * from the peer or hotplug scripts.
+     */
+    XenbusStateInitWait      = 2,
+
+    /*
+     * Initialised: Waiting for a connection from the peer.
+     */
+    XenbusStateInitialised   = 3,
 
+    XenbusStateConnected     = 4,
+
+    /*
+     * Closing: The device is being closed due to an error or an unplug event.
+     */
+    XenbusStateClosing       = 5,
+
+    XenbusStateClosed        = 6,
+
+    /*
+     * Reconfiguring: The device is being reconfigured.
+     */
+    XenbusStateReconfiguring = 7,
+
+    XenbusStateReconfigured  = 8
 };
+typedef enum xenbus_state XenbusState;
 
 #endif /* _XEN_PUBLIC_IO_XENBUS_H */
-
-/*
- * Local variables:
- *  c-file-style: "linux"
- *  indent-tabs-mode: t
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/vscsiif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/vscsiif.h
@@ -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:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/usbif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/usbif.h
@@ -0,0 +1,151 @@
+/*
+ * usbif.h
+ *
+ * USB I/O interface for Xen guest OSes.
+ *
+ * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
+ * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
+ *
+ * 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_PUBLIC_IO_USBIF_H__
+#define __XEN_PUBLIC_IO_USBIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+enum usb_spec_version {
+	USB_VER_UNKNOWN = 0,
+	USB_VER_USB11,
+	USB_VER_USB20,
+	USB_VER_USB30,	/* not supported yet */
+};
+
+/*
+ *  USB pipe in usbif_request
+ *
+ *  bits 0-5 are specific bits for virtual USB driver.
+ *  bits 7-31 are standard urb pipe.
+ *
+ *  - port number(NEW):	bits 0-4
+ *  				(USB_MAXCHILDREN is 31)
+ *
+ *  - operation flag(NEW):	bit 5
+ *  				(0 = submit urb,
+ *  				 1 = unlink urb)
+ *
+ *  - direction:		bit 7
+ *  				(0 = Host-to-Device [Out]
+ *                           1 = Device-to-Host [In])
+ *
+ *  - device address:	bits 8-14
+ *
+ *  - endpoint:		bits 15-18
+ *
+ *  - pipe type:		bits 30-31
+ *  				(00 = isochronous, 01 = interrupt,
+ *                           10 = control, 11 = bulk)
+ */
+#define usbif_pipeportnum(pipe) ((pipe) & 0x1f)
+#define usbif_setportnum_pipe(pipe, portnum) \
+	((pipe)|(portnum))
+
+#define usbif_pipeunlink(pipe) ((pipe) & 0x20)
+#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe))
+#define usbif_setunlink_pipe(pipe) ((pipe)|(0x20))
+
+#define USBIF_BACK_MAX_PENDING_REQS (128)
+#define USBIF_MAX_SEGMENTS_PER_REQUEST (16)
+
+/*
+ * RING for transferring urbs.
+ */
+struct usbif_request_segment {
+	grant_ref_t gref;
+	uint16_t offset;
+	uint16_t length;
+};
+
+struct usbif_urb_request {
+	uint16_t id; /* request id */
+	uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */
+
+	/* basic urb parameter */
+	uint32_t pipe;
+	uint16_t transfer_flags;
+	uint16_t buffer_length;
+	union {
+		uint8_t ctrl[8]; /* setup_packet (Ctrl) */
+
+		struct {
+			uint16_t interval; /* maximum (1024*8) in usb core */
+			uint16_t start_frame; /* start frame */
+			uint16_t number_of_packets; /* number of ISO packet */
+			uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */
+		} isoc;
+
+		struct {
+			uint16_t interval; /* maximum (1024*8) in usb core */
+			uint16_t pad[3];
+		} intr;
+
+		struct {
+			uint16_t unlink_id; /* unlink request id */
+			uint16_t pad[3];
+		} unlink;
+
+	} u;
+
+	/* urb data segments */
+	struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct usbif_urb_request usbif_urb_request_t;
+
+struct usbif_urb_response {
+	uint16_t id; /* request id */
+	uint16_t start_frame;  /* start frame (ISO) */
+	int32_t status; /* status (non-ISO) */
+	int32_t actual_length; /* actual transfer length */
+	int32_t error_count; /* number of ISO errors */
+};
+typedef struct usbif_urb_response usbif_urb_response_t;
+
+DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response);
+#define USB_URB_RING_SIZE __RING_SIZE((struct usbif_urb_sring *)0, PAGE_SIZE)
+
+/*
+ * RING for notifying connect/disconnect events to frontend
+ */
+struct usbif_conn_request {
+	uint16_t id;
+};
+typedef struct usbif_conn_request usbif_conn_request_t;
+
+struct usbif_conn_response {
+	uint16_t id; /* request id */
+	uint8_t portnum; /* port number */
+	uint8_t speed; /* usb_device_speed */
+};
+typedef struct usbif_conn_response usbif_conn_response_t;
+
+DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response);
+#define USB_CONN_RING_SIZE __RING_SIZE((struct usbif_conn_sring *)0, PAGE_SIZE)
+
+#endif /* __XEN_PUBLIC_IO_USBIF_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/io/console.h
+++ linux-ec2-2.6.32/include/xen/interface/io/console.h
@@ -3,6 +3,24 @@
  *
  * Console I/O interface for Xen guest OSes.
  *
+ * 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) 2005, Keir Fraser
  */
 
--- linux-ec2-2.6.32.orig/include/xen/interface/io/fbif.h
+++ linux-ec2-2.6.32/include/xen/interface/io/fbif.h
@@ -41,12 +41,13 @@
  */
 #define XENFB_TYPE_UPDATE 2
 
-struct xenfb_update {
-	uint8_t type;		/* XENFB_TYPE_UPDATE */
-	int32_t x;		/* source x */
-	int32_t y;		/* source y */
-	int32_t width;		/* rect width */
-	int32_t height;		/* rect height */
+struct xenfb_update
+{
+    uint8_t type;    /* XENFB_TYPE_UPDATE */
+    int32_t x;      /* source x */
+    int32_t y;      /* source y */
+    int32_t width;  /* rect width */
+    int32_t height; /* rect height */
 };
 
 /*
@@ -55,36 +56,58 @@
  */
 #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;		/* start offset within framebuffer */
+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];
+union xenfb_out_event
+{
+    uint8_t type;
+    struct xenfb_update update;
+    struct xenfb_resize resize;
+    char pad[XENFB_OUT_EVENT_SIZE];
 };
 
 /* In events (backend -> frontend) */
 
 /*
  * 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;
-	char pad[XENFB_IN_EVENT_SIZE];
+union xenfb_in_event
+{
+    uint8_t type;
+    struct xenfb_refresh_period refresh_period;
+    char pad[XENFB_IN_EVENT_SIZE];
 };
 
 /* shared page */
@@ -93,41 +116,46 @@
 #define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
 #define XENFB_IN_RING_OFFS 1024
 #define XENFB_IN_RING(page) \
-	((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+    ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
 #define XENFB_IN_RING_REF(page, idx) \
-	(XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+    (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
 
 #define XENFB_OUT_RING_SIZE 2048
 #define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
 #define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
 #define XENFB_OUT_RING(page) \
-	((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+    ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
 #define XENFB_OUT_RING_REF(page, idx) \
-	(XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+    (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
 
-struct xenfb_page {
-	uint32_t in_cons, in_prod;
-	uint32_t out_cons, out_prod;
-
-	int32_t width;          /* width of the framebuffer (in pixels) */
-	int32_t height;         /* height of the framebuffer (in pixels) */
-	uint32_t line_length;   /* length of a row of pixels (in bytes) */
-	uint32_t mem_length;    /* length of the framebuffer (in bytes) */
-	uint8_t depth;          /* depth of a pixel (in bits) */
-
-	/*
-	 * Framebuffer page directory
-	 *
-	 * 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/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[256];
+struct xenfb_page
+{
+    uint32_t in_cons, in_prod;
+    uint32_t out_cons, out_prod;
+
+    int32_t width;          /* the width of the framebuffer (in pixels) */
+    int32_t height;         /* the height of the framebuffer (in pixels) */
+    uint32_t line_length;   /* the length of a row of pixels (in bytes) */
+    uint32_t mem_length;    /* the length of the framebuffer (in bytes) */
+    uint8_t depth;          /* the depth of a pixel (in bits) */
+
+    /*
+     * Framebuffer page directory
+     *
+     * 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/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.
+     */
+#ifndef CONFIG_PARAVIRT_XEN
+    unsigned long pd[256];
+#else
+	/* Two directory pages should be enough for a while. */
+	unsigned long pd[2];
+#endif
 };
 
 /*
--- linux-ec2-2.6.32.orig/include/xen/interface/io/ring.h
+++ linux-ec2-2.6.32/include/xen/interface/io/ring.h
@@ -3,16 +3,42 @@
  *
  * Shared producer-consumer ring macros.
  *
+ * 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.
+ *
  * Tim Deegan and Andrew Warfield November 2004.
  */
 
 #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. */
-#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2		       : ((_x) & 0x1))
+#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2                  : ((_x) & 0x1))
 #define __RD4(_x)  (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2    : __RD2(_x))
 #define __RD8(_x)  (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4    : __RD4(_x))
 #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8    : __RD8(_x))
@@ -25,73 +51,77 @@
  * power of two (so we can mask with (size-1) to loop around).
  */
 #define __RING_SIZE(_s, _sz) \
-    (__RD32(((_sz) - (long)&(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+    (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
 
 /*
  * Macros to make the correct C datatypes for a new kind of ring.
  *
  * To make a new ring datatype, you need to have two message structures,
- * let's say struct request, and struct response already defined.
+ * let's say request_t, and response_t already defined.
  *
  * In a header where you want the ring datatype declared, you then do:
  *
- *     DEFINE_RING_TYPES(mytag, struct request, struct response);
+ *     DEFINE_RING_TYPES(mytag, request_t, response_t);
  *
  * These expand out to give you a set of types, as you can see below.
  * The most important of these are:
  *
- *     struct mytag_sring      - The shared ring.
- *     struct mytag_front_ring - The 'front' half of the ring.
- *     struct mytag_back_ring  - The 'back' half of the ring.
+ *     mytag_sring_t      - The shared ring.
+ *     mytag_front_ring_t - The 'front' half of the ring.
+ *     mytag_back_ring_t  - The 'back' half of the ring.
  *
  * To initialize a ring in your code you need to know the location and size
  * of the shared memory area (PAGE_SIZE, for instance). To initialise
  * the front half:
  *
- *     struct mytag_front_ring front_ring;
- *     SHARED_RING_INIT((struct mytag_sring *)shared_page);
- *     FRONT_RING_INIT(&front_ring, (struct mytag_sring *)shared_page,
- *		       PAGE_SIZE);
+ *     mytag_front_ring_t front_ring;
+ *     SHARED_RING_INIT((mytag_sring_t *)shared_page);
+ *     FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
  *
  * Initializing the back follows similarly (note that only the front
  * initializes the shared ring):
  *
- *     struct mytag_back_ring back_ring;
- *     BACK_RING_INIT(&back_ring, (struct mytag_sring *)shared_page,
- *		      PAGE_SIZE);
+ *     mytag_back_ring_t back_ring;
+ *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
  */
 
-#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)			\
-									\
-/* Shared ring entry */							\
-union __name##_sring_entry {						\
-    __req_t req;							\
-    __rsp_t rsp;							\
-};									\
-									\
-/* Shared ring page */							\
-struct __name##_sring {							\
-    RING_IDX req_prod, req_event;					\
-    RING_IDX rsp_prod, rsp_event;					\
-    uint8_t  pad[48];							\
-    union __name##_sring_entry ring[1]; /* variable-length */		\
-};									\
-									\
-/* "Front" end's private variables */					\
-struct __name##_front_ring {						\
-    RING_IDX req_prod_pvt;						\
-    RING_IDX rsp_cons;							\
-    unsigned int nr_ents;						\
-    struct __name##_sring *sring;					\
-};									\
-									\
-/* "Back" end's private variables */					\
-struct __name##_back_ring {						\
-    RING_IDX rsp_prod_pvt;						\
-    RING_IDX req_cons;							\
-    unsigned int nr_ents;						\
-    struct __name##_sring *sring;					\
-};
+#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
+                                                                        \
+/* Shared ring entry */                                                 \
+union __name##_sring_entry {                                            \
+    __req_t req;                                                        \
+    __rsp_t rsp;                                                        \
+};                                                                      \
+                                                                        \
+/* Shared ring page */                                                  \
+struct __name##_sring {                                                 \
+    RING_IDX req_prod, req_event;                                       \
+    RING_IDX rsp_prod, rsp_event;                                       \
+    uint8_t  netfront_smartpoll_active;                                 \
+    uint8_t  pad[47];                                                   \
+    union __name##_sring_entry ring[1]; /* variable-length */           \
+};                                                                      \
+                                                                        \
+/* "Front" end's private variables */                                   \
+struct __name##_front_ring {                                            \
+    RING_IDX req_prod_pvt;                                              \
+    RING_IDX rsp_cons;                                                  \
+    unsigned int nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* "Back" end's private variables */                                    \
+struct __name##_back_ring {                                             \
+    RING_IDX rsp_prod_pvt;                                              \
+    RING_IDX req_cons;                                                  \
+    unsigned int nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* Syntactic sugar */                                                   \
+typedef struct __name##_sring __name##_sring_t;                         \
+typedef struct __name##_front_ring __name##_front_ring_t;               \
+typedef struct __name##_back_ring __name##_back_ring_t
 
 /*
  * Macros for manipulating rings.
@@ -109,86 +139,94 @@
  */
 
 /* Initialising empty rings */
-#define SHARED_RING_INIT(_s) do {					\
-    (_s)->req_prod  = (_s)->rsp_prod  = 0;				\
-    (_s)->req_event = (_s)->rsp_event = 1;				\
-    memset((_s)->pad, 0, sizeof((_s)->pad));				\
+#define SHARED_RING_INIT(_s) do {                                       \
+    (_s)->req_prod  = (_s)->rsp_prod  = 0;                              \
+    (_s)->req_event = (_s)->rsp_event = 1;                              \
+    (void)memset((_s)->pad, 0, sizeof((_s)->pad));                      \
 } while(0)
 
-#define FRONT_RING_INIT(_r, _s, __size) do {				\
-    (_r)->req_prod_pvt = 0;						\
-    (_r)->rsp_cons = 0;							\
-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
-    (_r)->sring = (_s);							\
+#define FRONT_RING_INIT(_r, _s, __size) do {                            \
+    (_r)->req_prod_pvt = 0;                                             \
+    (_r)->rsp_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
 } while (0)
 
-#define BACK_RING_INIT(_r, _s, __size) do {				\
-    (_r)->rsp_prod_pvt = 0;						\
-    (_r)->req_cons = 0;							\
-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
-    (_r)->sring = (_s);							\
+#define BACK_RING_INIT(_r, _s, __size) do {                             \
+    (_r)->rsp_prod_pvt = 0;                                             \
+    (_r)->req_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
 } while (0)
 
 /* Initialize to existing shared indexes -- for recovery */
-#define FRONT_RING_ATTACH(_r, _s, __size) do {				\
-    (_r)->sring = (_s);							\
-    (_r)->req_prod_pvt = (_s)->req_prod;				\
-    (_r)->rsp_cons = (_s)->rsp_prod;					\
-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
+#define FRONT_RING_ATTACH(_r, _s, __size) do {                          \
+    (_r)->sring = (_s);                                                 \
+    (_r)->req_prod_pvt = (_s)->req_prod;                                \
+    (_r)->rsp_cons = (_s)->rsp_prod;                                    \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
 } while (0)
 
-#define BACK_RING_ATTACH(_r, _s, __size) do {				\
-    (_r)->sring = (_s);							\
-    (_r)->rsp_prod_pvt = (_s)->rsp_prod;				\
-    (_r)->req_cons = (_s)->req_prod;					\
-    (_r)->nr_ents = __RING_SIZE(_s, __size);				\
+#define BACK_RING_ATTACH(_r, _s, __size) do {                           \
+    (_r)->sring = (_s);                                                 \
+    (_r)->rsp_prod_pvt = (_s)->rsp_prod;                                \
+    (_r)->req_cons = (_s)->req_prod;                                    \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
 } while (0)
 
 /* How big is this ring? */
-#define RING_SIZE(_r)							\
+#define RING_SIZE(_r)                                                   \
     ((_r)->nr_ents)
 
 /* Number of free requests (for use on front side only). */
-#define RING_FREE_REQUESTS(_r)						\
+#define RING_FREE_REQUESTS(_r)                                          \
     (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
 
 /* Test if there is an empty slot available on the front ring.
  * (This is only meaningful from the front. )
  */
-#define RING_FULL(_r)							\
+#define RING_FULL(_r)                                                   \
     (RING_FREE_REQUESTS(_r) == 0)
 
 /* Test if there are outstanding messages to be processed on a ring. */
-#define RING_HAS_UNCONSUMED_RESPONSES(_r)				\
+#define RING_HAS_UNCONSUMED_RESPONSES(_r)                               \
     ((_r)->sring->rsp_prod - (_r)->rsp_cons)
 
-#define RING_HAS_UNCONSUMED_REQUESTS(_r)				\
-    ({									\
-	unsigned int req = (_r)->sring->req_prod - (_r)->req_cons;	\
-	unsigned int rsp = RING_SIZE(_r) -				\
-			   ((_r)->req_cons - (_r)->rsp_prod_pvt);	\
-	req < rsp ? req : rsp;						\
-    })
+#ifdef __GNUC__
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({                             \
+    unsigned int req = (_r)->sring->req_prod - (_r)->req_cons;          \
+    unsigned int rsp = RING_SIZE(_r) -                                  \
+        ((_r)->req_cons - (_r)->rsp_prod_pvt);                          \
+    req < rsp ? req : rsp;                                              \
+})
+#else
+/* Same as above, but without the nice GCC ({ ... }) syntax. */
+#define RING_HAS_UNCONSUMED_REQUESTS(_r)                                \
+    ((((_r)->sring->req_prod - (_r)->req_cons) <                        \
+      (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ?        \
+     ((_r)->sring->req_prod - (_r)->req_cons) :                         \
+     (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
+#endif
 
 /* Direct access to individual ring elements, by index. */
-#define RING_GET_REQUEST(_r, _idx)					\
+#define RING_GET_REQUEST(_r, _idx)                                      \
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
 
-#define RING_GET_RESPONSE(_r, _idx)					\
+#define RING_GET_RESPONSE(_r, _idx)                                     \
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
 
 /* Loop termination condition: Would the specified index overflow the ring? */
-#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)				\
+#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)                           \
     (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
 
-#define RING_PUSH_REQUESTS(_r) do {					\
-    wmb(); /* back sees requests /before/ updated producer index */	\
-    (_r)->sring->req_prod = (_r)->req_prod_pvt;				\
+#define RING_PUSH_REQUESTS(_r) do {                                     \
+    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 */	\
-    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;				\
+#define RING_PUSH_RESPONSES(_r) do {                                    \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;                         \
 } while (0)
 
 /*
@@ -221,40 +259,40 @@
  *  field appropriately.
  */
 
-#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 */	\
-    (_r)->sring->req_prod = __new;					\
-    mb(); /* back sees new requests /before/ we check req_event */	\
-    (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) <		\
-		 (RING_IDX)(__new - __old));				\
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do {           \
+    RING_IDX __old = (_r)->sring->req_prod;                             \
+    RING_IDX __new = (_r)->req_prod_pvt;                                \
+    xen_wmb(); /* back sees requests /before/ updated producer index */ \
+    (_r)->sring->req_prod = __new;                                      \
+    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)
 
-#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 */	\
-    (_r)->sring->rsp_prod = __new;					\
-    mb(); /* front sees new responses /before/ we check rsp_event */	\
-    (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) <		\
-		 (RING_IDX)(__new - __old));				\
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do {          \
+    RING_IDX __old = (_r)->sring->rsp_prod;                             \
+    RING_IDX __new = (_r)->rsp_prod_pvt;                                \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = __new;                                      \
+    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)
 
-#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {		\
-    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);			\
-    if (_work_to_do) break;						\
-    (_r)->sring->req_event = (_r)->req_cons + 1;			\
-    mb();								\
-    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);			\
+#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {             \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->req_event = (_r)->req_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
 } while (0)
 
-#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {		\
-    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);			\
-    if (_work_to_do) break;						\
-    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;			\
-    mb();								\
-    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);			\
+#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {            \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
 } while (0)
 
 #endif /* __XEN_PUBLIC_IO_RING_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/xen-mca.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/xen-mca.h
@@ -0,0 +1,422 @@
+/******************************************************************************
+ * 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
+
+/*
+ * The xen-unstable repo has interface version 0x03000001; out interface
+ * is incompatible with that and any future minor revisions, so we
+ * choose a different version number range that is numerically less
+ * than that used in xen-unstable.
+ */
+#define XEN_MCA_INTERFACE_VERSION 0x01ecc003
+
+/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */
+#define XEN_MC_NONURGENT  0x0001
+/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */
+#define XEN_MC_URGENT     0x0002
+/* IN: Dom0 acknowledges previosly-fetched telemetry */
+#define XEN_MC_ACK        0x0004
+
+/* 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
+#define MC_TYPE_RECOVERY        3
+
+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)
+#define MC_FLAG_RECOVERABLE	(1 << 2)
+#define MC_FLAG_POLLED		(1 << 3)
+#define MC_FLAG_RESET		(1 << 4)
+#define MC_FLAG_CMCI		(1 << 5)
+#define MC_FLAG_MCE		(1 << 6)
+/* 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;
+    uint16_t mc_vcpuid; /* virtual cpu scheduled for 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 */
+    uint32_t mc_apicid;
+    uint32_t mc_flags;
+    uint64_t mc_gstatus; /* global status */
+};
+
+/* 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;
+    uint64_t mc_ctrl2;
+    uint64_t mc_tsc;
+};
+
+
+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. */
+    /*
+     * Currently Intel extended MSR (32/64) include all gp registers
+     * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be
+     * useful at present. So expand this array to 16/32 to leave room.
+     */
+    struct mcinfo_msr mc_msr[sizeof(void *) * 4];
+};
+
+/* Recovery Action flags. Giving recovery result information to DOM0 */
+
+/* Xen takes successful recovery action, the error is recovered */
+#define REC_ACTION_RECOVERED (0x1 << 0)
+/* No action is performed by XEN */
+#define REC_ACTION_NONE (0x1 << 1)
+/* It's possible DOM0 might take action ownership in some case */
+#define REC_ACTION_NEED_RESET (0x1 << 2)
+
+/* Different Recovery Action types, if the action is performed successfully,
+ * REC_ACTION_RECOVERED flag will be returned.
+ */
+
+/* Page Offline Action */
+#define MC_ACTION_PAGE_OFFLINE (0x1 << 0)
+/* CPU offline Action */
+#define MC_ACTION_CPU_OFFLINE (0x1 << 1)
+/* L3 cache disable Action */
+#define MC_ACTION_CACHE_SHRINK (0x1 << 2)
+
+/* Below interface used between XEN/DOM0 for passing XEN's recovery action 
+ * information to DOM0. 
+ * usage Senario: After offlining broken page, XEN might pass its page offline
+ * recovery action result to DOM0. DOM0 will save the information in 
+ * non-volatile memory for further proactive actions, such as offlining the
+ * easy broken page earlier when doing next reboot.
+*/
+struct page_offline_action
+{
+    /* Params for passing the offlined page number to DOM0 */
+    uint64_t mfn;
+    uint64_t status;
+};
+
+struct cpu_offline_action
+{
+    /* Params for passing the identity of the offlined CPU to DOM0 */
+    uint32_t mc_socketid;
+    uint16_t mc_coreid;
+    uint16_t mc_core_threadid;
+};
+
+#define MAX_UNION_SIZE 16
+struct mcinfo_recovery
+{
+    struct mcinfo_common common;
+    uint16_t mc_bank; /* bank nr */
+    uint8_t action_flags;
+    uint8_t action_types;
+    union {
+        struct page_offline_action page_retire;
+        struct cpu_offline_action cpu_offline;
+        uint8_t pad[MAX_UNION_SIZE];
+    } action_info;
+};
+
+
+#define MCINFO_HYPERCALLSIZE	1024
+#define MCINFO_MAXSIZE		768
+
+struct mc_info {
+    /* Number of mcinfo_* entries in mi_data */
+    uint32_t mi_nentries;
+    uint32_t _pad0;
+    uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8];
+};
+typedef struct mc_info mc_info_t;
+DEFINE_XEN_GUEST_HANDLE(mc_info_t);
+
+#define __MC_MSR_ARRAYSIZE 8
+#define __MC_NMSRS 1
+#define MC_NCAPS	7	/* 7 CPU feature flag words */
+#define MC_CAPS_STD_EDX	0	/* cpuid level 0x00000001 (%edx) */
+#define MC_CAPS_AMD_EDX	1	/* cpuid level 0x80000001 (%edx) */
+#define MC_CAPS_TM	2	/* cpuid level 0x80860001 (TransMeta) */
+#define MC_CAPS_LINUX	3	/* Linux-defined */
+#define MC_CAPS_STD_ECX	4	/* cpuid level 0x00000001 (%ecx) */
+#define MC_CAPS_VIA	5	/* cpuid level 0xc0000001 */
+#define MC_CAPS_AMD_ECX	6	/* cpuid level 0x80000001 (%ecx) */
+
+struct mcinfo_logical_cpu {
+    uint32_t mc_cpunr;          
+    uint32_t mc_chipid; 
+    uint16_t mc_coreid;
+    uint16_t mc_threadid;
+    uint32_t mc_apicid;
+    uint32_t mc_clusterid;
+    uint32_t mc_ncores;
+    uint32_t mc_ncores_active;
+    uint32_t mc_nthreads;
+    int32_t mc_cpuid_level;
+    uint32_t mc_family;
+    uint32_t mc_vendor;
+    uint32_t mc_model;
+    uint32_t mc_step;
+    char mc_vendorid[16];
+    char mc_brandid[64];
+    uint32_t mc_cpu_caps[MC_NCAPS];
+    uint32_t mc_cache_size;
+    uint32_t mc_cache_alignment;
+    int32_t mc_nmsrvals;
+    struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE];
+};
+typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_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_NONURGENT, XEN_MC_URGENT,
+                           XEN_MC_ACK if ack'ing an earlier fetch */
+			/* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED,
+			   XEN_MC_NODATA, XEN_MC_NOMATCH */
+    uint32_t _pad0;
+    uint64_t fetch_id;	/* OUT: id for ack, IN: id we are ack'ing */
+
+    /* OUT variables. */
+    XEN_GUEST_HANDLE(mc_info_t) data;
+};
+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. */
+
+    /* 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);
+
+#define XEN_MC_physcpuinfo 3
+struct xen_mc_physcpuinfo {
+	/* IN/OUT */
+	uint32_t ncpus;
+	uint32_t _pad0;
+	/* OUT */
+	XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info;
+};
+
+#define XEN_MC_msrinject    4
+#define MC_MSRINJ_MAXMSRS       8
+struct xen_mc_msrinject {
+       /* IN */
+	uint32_t mcinj_cpunr;           /* target processor id */
+	uint32_t mcinj_flags;           /* see MC_MSRINJ_F_* below */
+	uint32_t mcinj_count;           /* 0 .. count-1 in array are valid */
+	uint32_t _pad0;
+	struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS];
+};
+
+/* Flags for mcinj_flags above; bits 16-31 are reserved */
+#define MC_MSRINJ_F_INTERPOSE   0x1
+
+#define XEN_MC_mceinject    5
+struct xen_mc_mceinject {
+	unsigned int mceinj_cpunr;      /* target processor id */
+};
+
+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;
+        struct xen_mc_physcpuinfo  mc_physcpuinfo;
+        struct xen_mc_msrinject    mc_msrinject;
+        struct xen_mc_mceinject    mc_mceinject;
+    } u;
+};
+typedef struct xen_mc xen_mc_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mc_t);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/cpuid.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/cpuid.h
@@ -0,0 +1,68 @@
+/******************************************************************************
+ * arch-x86/cpuid.h
+ * 
+ * CPUID interface to 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) 2007 Citrix Systems, Inc.
+ * 
+ * Authors:
+ *    Keir Fraser <keir.fraser@citrix.com>
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__
+#define __XEN_PUBLIC_ARCH_X86_CPUID_H__
+
+/* Xen identification leaves start at 0x40000000. */
+#define XEN_CPUID_FIRST_LEAF 0x40000000
+#define XEN_CPUID_LEAF(i)    (XEN_CPUID_FIRST_LEAF + (i))
+
+/*
+ * Leaf 1 (0x40000000)
+ * EAX: Largest Xen-information leaf. All leaves up to an including @EAX
+ *      are supported by the Xen host.
+ * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification
+ *      of a Xen host.
+ */
+#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */
+#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */
+#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */
+
+/*
+ * Leaf 2 (0x40000001)
+ * EAX[31:16]: Xen major version.
+ * EAX[15: 0]: Xen minor version.
+ * EBX-EDX: Reserved (currently all zeroes).
+ */
+
+/*
+ * Leaf 3 (0x40000002)
+ * EAX: Number of hypercall transfer pages. This register is always guaranteed
+ *      to specify one hypercall page.
+ * EBX: Base address of Xen-specific MSRs.
+ * ECX: Features 1. Unused bits are set to zero.
+ * EDX: Features 2. Unused bits are set to zero.
+ */
+
+/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */
+#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0
+#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD  (1u<<0)
+
+#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/xen.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/xen.h
@@ -0,0 +1,203 @@
+/******************************************************************************
+ * 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
+
+/* Allow co-existing Linux 2.6.23+ Xen interface definitions. */
+#define DEFINE_GUEST_HANDLE_STRUCT(name) struct name
+
+#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:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/xen-x86_32.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/xen-x86_32.h
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * xen-x86_32.h
+ * 
+ * Guest OS interface to x86 32-bit 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-2007, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+
+/*
+ * Hypercall interface:
+ *  Input:  %ebx, %ecx, %edx, %esi, %edi (arguments 1-5)
+ *  Output: %eax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ *  call hypercall_page + hypercall-number * 32
+ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
+ */
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030203
+/*
+ * Legacy hypercall interface:
+ * As above, except the entry sequence to the hypervisor is:
+ *  mov $hypercall-number*32,%eax ; int $0x82
+ */
+#define TRAP_INSTR "int $0x82"
+#endif
+
+/*
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+#define FLAT_RING1_CS 0xe019    /* GDT index 259 */
+#define FLAT_RING1_DS 0xe021    /* GDT index 260 */
+#define FLAT_RING1_SS 0xe021    /* GDT index 260 */
+#define FLAT_RING3_CS 0xe02b    /* GDT index 261 */
+#define FLAT_RING3_DS 0xe033    /* GDT index 262 */
+#define FLAT_RING3_SS 0xe033    /* GDT index 262 */
+
+#define FLAT_KERNEL_CS FLAT_RING1_CS
+#define FLAT_KERNEL_DS FLAT_RING1_DS
+#define FLAT_KERNEL_SS FLAT_RING1_SS
+#define FLAT_USER_CS    FLAT_RING3_CS
+#define FLAT_USER_DS    FLAT_RING3_DS
+#define FLAT_USER_SS    FLAT_RING3_SS
+
+#define __HYPERVISOR_VIRT_START_PAE    0xF5800000
+#define __MACH2PHYS_VIRT_START_PAE     0xF5800000
+#define __MACH2PHYS_VIRT_END_PAE       0xF6800000
+#define HYPERVISOR_VIRT_START_PAE      \
+    mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
+#define MACH2PHYS_VIRT_START_PAE       \
+    mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
+#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
+#define HYPERVISOR_VIRT_START_NONPAE   \
+    mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_START_NONPAE    \
+    mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
+#define MACH2PHYS_VIRT_END_NONPAE      \
+    mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
+
+#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_START  __MACH2PHYS_VIRT_START_PAE
+#define __MACH2PHYS_VIRT_END    __MACH2PHYS_VIRT_END_PAE
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#endif
+
+#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
+#endif
+
+/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+#undef ___DEFINE_XEN_GUEST_HANDLE
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type)                  \
+    typedef struct { type *p; }                                 \
+        __guest_handle_ ## name;                                \
+    typedef struct { union { type *p; uint64_aligned_t q; }; }  \
+        __guest_handle_64_ ## name
+#undef set_xen_guest_handle
+#define set_xen_guest_handle(hnd, val)                      \
+    do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0;   \
+         (hnd).p = val;                                     \
+    } while ( 0 )
+#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
+#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
+#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
+#endif
+
+#ifndef __ASSEMBLY__
+
+struct cpu_user_regs {
+    uint32_t ebx;
+    uint32_t ecx;
+    uint32_t edx;
+    uint32_t esi;
+    uint32_t edi;
+    uint32_t ebp;
+    uint32_t eax;
+    uint16_t error_code;    /* private */
+    uint16_t entry_vector;  /* private */
+    uint32_t eip;
+    uint16_t cs;
+    uint8_t  saved_upcall_mask;
+    uint8_t  _pad0;
+    uint32_t eflags;        /* eflags.IF == !saved_upcall_mask */
+    uint32_t esp;
+    uint16_t ss, _pad1;
+    uint16_t es, _pad2;
+    uint16_t ds, _pad3;
+    uint16_t fs, _pad4;
+    uint16_t gs, _pad5;
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+/*
+ * Page-directory addresses above 4GB do not fit into architectural %cr3.
+ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
+ * must use the following accessor macros to pack/unpack valid MFNs.
+ */
+#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
+#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
+
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+struct xen_callback {
+    unsigned long cs;
+    unsigned long eip;
+};
+typedef struct xen_callback xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/xen-x86_64.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/xen-x86_64.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ * xen-x86_64.h
+ * 
+ * Guest OS interface to x86 64-bit 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_X86_64_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+
+/*
+ * Hypercall interface:
+ *  Input:  %rdi, %rsi, %rdx, %r10, %r8 (arguments 1-5)
+ *  Output: %rax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ *  call hypercall_page + hypercall-number * 32
+ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
+ */
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030203
+/*
+ * Legacy hypercall interface:
+ * As above, except the entry sequence to the hypervisor is:
+ *  mov $hypercall-number*32,%eax ; syscall
+ * Clobbered: %rcx, %r11, argument registers (as above)
+ */
+#define TRAP_INSTR "syscall"
+#endif
+
+/*
+ * 64-bit segment selectors
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+
+#define FLAT_RING3_CS32 0xe023  /* GDT index 260 */
+#define FLAT_RING3_CS64 0xe033  /* GDT index 261 */
+#define FLAT_RING3_DS32 0xe02b  /* GDT index 262 */
+#define FLAT_RING3_DS64 0x0000  /* NULL selector */
+#define FLAT_RING3_SS32 0xe02b  /* GDT index 262 */
+#define FLAT_RING3_SS64 0xe02b  /* GDT index 262 */
+
+#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
+#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
+#define FLAT_KERNEL_DS   FLAT_KERNEL_DS64
+#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
+#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
+#define FLAT_KERNEL_CS   FLAT_KERNEL_CS64
+#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
+#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
+#define FLAT_KERNEL_SS   FLAT_KERNEL_SS64
+
+#define FLAT_USER_DS64 FLAT_RING3_DS64
+#define FLAT_USER_DS32 FLAT_RING3_DS32
+#define FLAT_USER_DS   FLAT_USER_DS64
+#define FLAT_USER_CS64 FLAT_RING3_CS64
+#define FLAT_USER_CS32 FLAT_RING3_CS32
+#define FLAT_USER_CS   FLAT_USER_CS64
+#define FLAT_USER_SS64 FLAT_RING3_SS64
+#define FLAT_USER_SS32 FLAT_RING3_SS32
+#define FLAT_USER_SS   FLAT_USER_SS64
+
+#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
+#define __HYPERVISOR_VIRT_END   0xFFFF880000000000
+#define __MACH2PHYS_VIRT_START  0xFFFF800000000000
+#define __MACH2PHYS_VIRT_END    0xFFFF804000000000
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#define HYPERVISOR_VIRT_END   mk_unsigned_long(__HYPERVISOR_VIRT_END)
+#endif
+
+#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+/*
+ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
+ *  @which == SEGBASE_*  ;  @base == 64-bit base address
+ * Returns 0 on success.
+ */
+#define SEGBASE_FS          0
+#define SEGBASE_GS_USER     1
+#define SEGBASE_GS_KERNEL   2
+#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
+
+/*
+ * int HYPERVISOR_iret(void)
+ * All arguments are on the kernel stack, in the following format.
+ * Never returns if successful. Current kernel context is lost.
+ * The saved CS is mapped as follows:
+ *   RING0 -> RING3 kernel mode.
+ *   RING1 -> RING3 kernel mode.
+ *   RING2 -> RING3 kernel mode.
+ *   RING3 -> RING3 user mode.
+ * However RING0 indicates that the guest kernel should return to iteself
+ * directly with
+ *      orb   $3,1*8(%rsp)
+ *      iretq
+ * If flags contains VGCF_in_syscall:
+ *   Restore RAX, RIP, RFLAGS, RSP.
+ *   Discard R11, RCX, CS, SS.
+ * Otherwise:
+ *   Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
+ * All other registers are saved on hypercall entry and restored to user.
+ */
+/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
+#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. */
+};
+
+#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; \
+    uint32_t _e ## name; \
+}
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
+#define __DECL_REG(name) uint64_t r ## name
+#endif
+
+struct cpu_user_regs {
+    uint64_t r15;
+    uint64_t r14;
+    uint64_t r13;
+    uint64_t r12;
+    __DECL_REG(bp);
+    __DECL_REG(bx);
+    uint64_t r11;
+    uint64_t r10;
+    uint64_t r9;
+    uint64_t r8;
+    __DECL_REG(ax);
+    __DECL_REG(cx);
+    __DECL_REG(dx);
+    __DECL_REG(si);
+    __DECL_REG(di);
+    uint32_t error_code;    /* private */
+    uint32_t entry_vector;  /* private */
+    __DECL_REG(ip);
+    uint16_t cs, _pad0[1];
+    uint8_t  saved_upcall_mask;
+    uint8_t  _pad1[3];
+    __DECL_REG(flags);      /* rflags.IF == !saved_upcall_mask */
+    __DECL_REG(sp);
+    uint16_t ss, _pad2[3];
+    uint16_t es, _pad3[3];
+    uint16_t ds, _pad4[3];
+    uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base.     */
+    uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
+};
+typedef struct cpu_user_regs cpu_user_regs_t;
+DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
+
+#undef __DECL_REG
+
+#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
+#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
+
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+typedef unsigned long xen_callback_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- linux-ec2-2.6.32.orig/include/xen/interface/arch-x86/hvm/save.h
+++ linux-ec2-2.6.32/include/xen/interface/arch-x86/hvm/save.h
@@ -0,0 +1,438 @@
+/* 
+ * Structure definitions for HVM state that is held by Xen and must
+ * be saved along with the domain's memory and device-model state.
+ * 
+ * Copyright (c) 2007 XenSource Ltd.
+ *
+ * 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_PUBLIC_HVM_SAVE_X86_H__
+#define __XEN_PUBLIC_HVM_SAVE_X86_H__
+
+/* 
+ * Save/restore header: general info about the save file. 
+ */
+
+#define HVM_FILE_MAGIC   0x54381286
+#define HVM_FILE_VERSION 0x00000001
+
+struct hvm_save_header {
+    uint32_t magic;             /* Must be HVM_FILE_MAGIC */
+    uint32_t version;           /* File format version */
+    uint64_t changeset;         /* Version of Xen that saved this file */
+    uint32_t cpuid;             /* CPUID[0x01][%eax] on the saving machine */
+    uint32_t pad0;
+};
+
+DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
+
+
+/*
+ * Processor
+ */
+
+struct hvm_hw_cpu {
+    uint8_t  fpu_regs[512];
+
+    uint64_t rax;
+    uint64_t rbx;
+    uint64_t rcx;
+    uint64_t rdx;
+    uint64_t rbp;
+    uint64_t rsi;
+    uint64_t rdi;
+    uint64_t rsp;
+    uint64_t r8;
+    uint64_t r9;
+    uint64_t r10;
+    uint64_t r11;
+    uint64_t r12;
+    uint64_t r13;
+    uint64_t r14;
+    uint64_t r15;
+
+    uint64_t rip;
+    uint64_t rflags;
+
+    uint64_t cr0;
+    uint64_t cr2;
+    uint64_t cr3;
+    uint64_t cr4;
+
+    uint64_t dr0;
+    uint64_t dr1;
+    uint64_t dr2;
+    uint64_t dr3;
+    uint64_t dr6;
+    uint64_t dr7;    
+
+    uint32_t cs_sel;
+    uint32_t ds_sel;
+    uint32_t es_sel;
+    uint32_t fs_sel;
+    uint32_t gs_sel;
+    uint32_t ss_sel;
+    uint32_t tr_sel;
+    uint32_t ldtr_sel;
+
+    uint32_t cs_limit;
+    uint32_t ds_limit;
+    uint32_t es_limit;
+    uint32_t fs_limit;
+    uint32_t gs_limit;
+    uint32_t ss_limit;
+    uint32_t tr_limit;
+    uint32_t ldtr_limit;
+    uint32_t idtr_limit;
+    uint32_t gdtr_limit;
+
+    uint64_t cs_base;
+    uint64_t ds_base;
+    uint64_t es_base;
+    uint64_t fs_base;
+    uint64_t gs_base;
+    uint64_t ss_base;
+    uint64_t tr_base;
+    uint64_t ldtr_base;
+    uint64_t idtr_base;
+    uint64_t gdtr_base;
+
+    uint32_t cs_arbytes;
+    uint32_t ds_arbytes;
+    uint32_t es_arbytes;
+    uint32_t fs_arbytes;
+    uint32_t gs_arbytes;
+    uint32_t ss_arbytes;
+    uint32_t tr_arbytes;
+    uint32_t ldtr_arbytes;
+
+    uint64_t sysenter_cs;
+    uint64_t sysenter_esp;
+    uint64_t sysenter_eip;
+
+    /* msr for em64t */
+    uint64_t shadow_gs;
+
+    /* msr content saved/restored. */
+    uint64_t msr_flags;
+    uint64_t msr_lstar;
+    uint64_t msr_star;
+    uint64_t msr_cstar;
+    uint64_t msr_syscall_mask;
+    uint64_t msr_efer;
+
+    /* guest's idea of what rdtsc() would return */
+    uint64_t tsc;
+
+    /* pending event, if any */
+    union {
+        uint32_t pending_event;
+        struct {
+            uint8_t  pending_vector:8;
+            uint8_t  pending_type:3;
+            uint8_t  pending_error_valid:1;
+            uint32_t pending_reserved:19;
+            uint8_t  pending_valid:1;
+        };
+    };
+    /* error code for pending event */
+    uint32_t error_code;
+};
+
+DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu);
+
+
+/*
+ * PIC
+ */
+
+struct hvm_hw_vpic {
+    /* IR line bitmasks. */
+    uint8_t irr;
+    uint8_t imr;
+    uint8_t isr;
+
+    /* Line IRx maps to IRQ irq_base+x */
+    uint8_t irq_base;
+
+    /*
+     * Where are we in ICW2-4 initialisation (0 means no init in progress)?
+     * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
+     * Bit 2: ICW1.IC4  (1 == ICW4 included in init sequence)
+     * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
+     */
+    uint8_t init_state:4;
+
+    /* IR line with highest priority. */
+    uint8_t priority_add:4;
+
+    /* Reads from A=0 obtain ISR or IRR? */
+    uint8_t readsel_isr:1;
+
+    /* Reads perform a polling read? */
+    uint8_t poll:1;
+
+    /* Automatically clear IRQs from the ISR during INTA? */
+    uint8_t auto_eoi:1;
+
+    /* Automatically rotate IRQ priorities during AEOI? */
+    uint8_t rotate_on_auto_eoi:1;
+
+    /* Exclude slave inputs when considering in-service IRQs? */
+    uint8_t special_fully_nested_mode:1;
+
+    /* Special mask mode excludes masked IRs from AEOI and priority checks. */
+    uint8_t special_mask_mode:1;
+
+    /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
+    uint8_t is_master:1;
+
+    /* Edge/trigger selection. */
+    uint8_t elcr;
+
+    /* Virtual INT output. */
+    uint8_t int_output;
+};
+
+DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
+
+
+/*
+ * IO-APIC
+ */
+
+#ifdef __ia64__
+#define VIOAPIC_IS_IOSAPIC 1
+#define VIOAPIC_NUM_PINS  24
+#else
+#define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
+#endif
+
+struct hvm_hw_vioapic {
+    uint64_t base_address;
+    uint32_t ioregsel;
+    uint32_t id;
+    union vioapic_redir_entry
+    {
+        uint64_t bits;
+        struct {
+            uint8_t vector;
+            uint8_t delivery_mode:3;
+            uint8_t dest_mode:1;
+            uint8_t delivery_status:1;
+            uint8_t polarity:1;
+            uint8_t remote_irr:1;
+            uint8_t trig_mode:1;
+            uint8_t mask:1;
+            uint8_t reserve:7;
+#if !VIOAPIC_IS_IOSAPIC
+            uint8_t reserved[4];
+            uint8_t dest_id;
+#else
+            uint8_t reserved[3];
+            uint16_t dest_id;
+#endif
+        } fields;
+    } redirtbl[VIOAPIC_NUM_PINS];
+};
+
+DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
+
+
+/*
+ * LAPIC
+ */
+
+struct hvm_hw_lapic {
+    uint64_t             apic_base_msr;
+    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
+    uint32_t             timer_divisor;
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
+
+struct hvm_hw_lapic_regs {
+    uint8_t data[1024];
+};
+
+DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
+
+
+/*
+ * IRQs
+ */
+
+struct hvm_hw_pci_irqs {
+    /*
+     * Virtual interrupt wires for a single PCI bus.
+     * Indexed by: device*4 + INTx#.
+     */
+    union {
+        unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
+        uint64_t pad[2];
+    };
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
+
+struct hvm_hw_isa_irqs {
+    /*
+     * Virtual interrupt wires for ISA devices.
+     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
+     */
+    union {
+        unsigned long i[1];  /* DECLARE_BITMAP(i, 16); */
+        uint64_t pad[1];
+    };
+};
+
+DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
+
+struct hvm_hw_pci_link {
+    /*
+     * PCI-ISA interrupt router.
+     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
+     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
+     * The router provides a programmable mapping from each link to a GSI.
+     */
+    uint8_t route[4];
+    uint8_t pad0[4];
+};
+
+DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
+
+/* 
+ *  PIT
+ */
+
+struct hvm_hw_pit {
+    struct hvm_hw_pit_channel {
+        uint32_t count; /* can be 65536 */
+        uint16_t latched_count;
+        uint8_t count_latched;
+        uint8_t status_latched;
+        uint8_t status;
+        uint8_t read_state;
+        uint8_t write_state;
+        uint8_t write_latch;
+        uint8_t rw_mode;
+        uint8_t mode;
+        uint8_t bcd; /* not supported */
+        uint8_t gate; /* timer start */
+    } channels[3];  /* 3 x 16 bytes */
+    uint32_t speaker_data_on;
+    uint32_t pad0;
+};
+
+DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
+
+
+/* 
+ * RTC
+ */ 
+
+#define RTC_CMOS_SIZE 14
+struct hvm_hw_rtc {
+    /* CMOS bytes */
+    uint8_t cmos_data[RTC_CMOS_SIZE];
+    /* Index register for 2-part operations */
+    uint8_t cmos_index;
+    uint8_t pad0;
+};
+
+DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
+
+
+/*
+ * HPET
+ */
+
+#define HPET_TIMER_NUM     3    /* 3 timers supported now */
+struct hvm_hw_hpet {
+    /* Memory-mapped, software visible registers */
+    uint64_t capability;        /* capabilities */
+    uint64_t res0;              /* reserved */
+    uint64_t config;            /* configuration */
+    uint64_t res1;              /* reserved */
+    uint64_t isr;               /* interrupt status reg */
+    uint64_t res2[25];          /* reserved */
+    uint64_t mc64;              /* main counter */
+    uint64_t res3;              /* reserved */
+    struct {                    /* timers */
+        uint64_t config;        /* configuration/cap */
+        uint64_t cmp;           /* comparator */
+        uint64_t fsb;           /* FSB route, not supported now */
+        uint64_t res4;          /* reserved */
+    } timers[HPET_TIMER_NUM];
+    uint64_t res5[4*(24-HPET_TIMER_NUM)];  /* reserved, up to 0x3ff */
+
+    /* Hidden register state */
+    uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
+};
+
+DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
+
+
+/*
+ * PM timer
+ */
+
+struct hvm_hw_pmtimer {
+    uint32_t tmr_val;   /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
+    uint16_t pm1a_sts;  /* PM1a_EVT_BLK.PM1a_STS: status register */
+    uint16_t pm1a_en;   /* PM1a_EVT_BLK.PM1a_EN: enable register */
+};
+
+DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
+
+/*
+ * MTRR MSRs
+ */
+
+struct hvm_hw_mtrr {
+#define MTRR_VCNT 8
+#define NUM_FIXED_MSR 11
+    uint64_t msr_pat_cr;
+    /* mtrr physbase & physmask msr pair*/
+    uint64_t msr_mtrr_var[MTRR_VCNT*2];
+    uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
+    uint64_t msr_mtrr_cap;
+    uint64_t msr_mtrr_def_type;
+};
+
+DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
+
+/*
+ * Viridian hypervisor context.
+ */
+
+struct hvm_viridian_context {
+    uint64_t hypercall_gpa;
+    uint64_t guest_os_id;
+};
+
+DECLARE_HVM_SAVE_TYPE(VIRIDIAN, 15, struct hvm_viridian_context);
+
+/* 
+ * Largest type-code in use
+ */
+#define HVM_SAVE_CODE_MAX 15
+
+#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
--- linux-ec2-2.6.32.orig/include/crypto/cryptd.h
+++ linux-ec2-2.6.32/include/crypto/cryptd.h
@@ -39,6 +39,7 @@
 struct cryptd_ahash *cryptd_alloc_ahash(const char *alg_name,
 					u32 type, u32 mask);
 struct crypto_shash *cryptd_ahash_child(struct cryptd_ahash *tfm);
+struct shash_desc *cryptd_shash_desc(struct ahash_request *req);
 void cryptd_free_ahash(struct cryptd_ahash *tfm);
 
 #endif
--- linux-ec2-2.6.32.orig/include/trace/ftrace.h
+++ linux-ec2-2.6.32/include/trace/ftrace.h
@@ -43,7 +43,8 @@
 		tstruct						\
 		char			__data[0];		\
 	};							\
-	static struct ftrace_event_call event_##name
+	static struct ftrace_event_call			\
+	__attribute__((__aligned__(4))) event_##name
 
 #undef __cpparg
 #define __cpparg(arg...) arg
@@ -159,7 +160,7 @@
 #undef __get_str
 
 #undef TP_printk
-#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args)
+#define TP_printk(fmt, args...) "\"%s\", %s\n", fmt, __stringify(args)
 
 #undef TP_fast_assign
 #define TP_fast_assign(args...) args
--- linux-ec2-2.6.32.orig/include/trace/events/vfs.h
+++ linux-ec2-2.6.32/include/trace/events/vfs.h
@@ -0,0 +1,53 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM vfs
+
+#if !defined(_TRACE_VFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_VFS_H
+
+/*
+ * Tracepoint for dirtying an inode:
+ */
+TRACE_EVENT(dirty_inode,
+
+	TP_PROTO(struct inode *inode, struct task_struct *task),
+
+	TP_ARGS(inode, task),
+
+	TP_STRUCT__entry(
+		__array( char,	comm,	TASK_COMM_LEN	)
+		__field( pid_t,	pid			)
+		__array( char,  dev,    16		)
+		__array( char,  file,   32		)
+	),
+
+	TP_fast_assign(
+		if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
+			struct dentry *dentry;
+			const char *name = "?";
+
+			dentry = d_find_alias(inode);
+			if (dentry) {
+				spin_lock(&dentry->d_lock);
+				name = (const char *) dentry->d_name.name;
+			}
+
+			memcpy(__entry->comm, task->comm, TASK_COMM_LEN);
+			__entry->pid = task->pid;
+			strlcpy(__entry->file, name, 32);
+			strlcpy(__entry->dev, inode->i_sb->s_id, 16);
+
+			if (dentry) {
+				spin_unlock(&dentry->d_lock);
+				dput(dentry);
+			}
+		}
+	),
+
+	TP_printk("task=%i (%s) file=%s dev=%s",
+		__entry->pid, __entry->comm, __entry->file, __entry->dev)
+);
+
+#endif /* _TRACE_VFS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--- linux-ec2-2.6.32.orig/include/trace/events/fs.h
+++ linux-ec2-2.6.32/include/trace/events/fs.h
@@ -0,0 +1,53 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM fs
+
+#if !defined(_TRACE_FS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_FS_H
+
+#include <linux/fs.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(do_sys_open,
+
+	TP_PROTO(char *filename, int flags, int mode),
+
+	TP_ARGS(filename, flags, mode),
+
+	TP_STRUCT__entry(
+		__string(	filename, filename		)
+		__field(	int, flags			)
+		__field(	int, mode			)
+	),
+
+	TP_fast_assign(
+		__assign_str(filename, filename);
+		__entry->flags = flags;
+		__entry->mode = mode;
+	),
+
+	TP_printk("\"%s\" %x %o",
+		  __get_str(filename), __entry->flags, __entry->mode)
+);
+
+TRACE_EVENT(open_exec,
+
+	TP_PROTO(char *filename),
+
+	TP_ARGS(filename),
+
+	TP_STRUCT__entry(
+		__string(	filename, filename		)
+	),
+
+	TP_fast_assign(
+		__assign_str(filename, filename);
+	),
+
+	TP_printk("\"%s\"",
+		  __get_str(filename))
+);
+
+#endif /* _TRACE_FS_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--- linux-ec2-2.6.32.orig/include/keys/rxrpc-type.h
+++ linux-ec2-2.6.32/include/keys/rxrpc-type.h
@@ -99,7 +99,6 @@
  * structure of raw payloads passed to add_key() or instantiate key
  */
 struct rxrpc_key_data_v1 {
-	u32		kif_version;		/* 1 */
 	u16		security_index;
 	u16		ticket_length;
 	u32		expiry;			/* time_t */
--- linux-ec2-2.6.32.orig/include/net/ipv6.h
+++ linux-ec2-2.6.32/include/net/ipv6.h
@@ -354,8 +354,16 @@
 
 struct inet_frag_queue;
 
+enum ip6_defrag_users {
+	IP6_DEFRAG_LOCAL_DELIVER,
+	IP6_DEFRAG_CONNTRACK_IN,
+	IP6_DEFRAG_CONNTRACK_OUT,
+	IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+};
+
 struct ip6_create_arg {
 	__be32 id;
+	u32 user;
 	struct in6_addr *src;
 	struct in6_addr *dst;
 };
--- linux-ec2-2.6.32.orig/include/net/netlink.h
+++ linux-ec2-2.6.32/include/net/netlink.h
@@ -384,7 +384,7 @@
  *
  * Returns the first attribute which matches the specified type.
  */
-static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh,
+static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
 					     int hdrlen, int attrtype)
 {
 	return nla_find(nlmsg_attrdata(nlh, hdrlen),
--- linux-ec2-2.6.32.orig/include/net/netrom.h
+++ linux-ec2-2.6.32/include/net/netrom.h
@@ -132,6 +132,8 @@
 static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
 {
 	if (atomic_dec_and_test(&nr_neigh->refcount)) {
+		if (nr_neigh->ax25)
+			ax25_cb_put(nr_neigh->ax25);
 		kfree(nr_neigh->digipeat);
 		kfree(nr_neigh);
 	}
--- linux-ec2-2.6.32.orig/include/net/mac80211.h
+++ linux-ec2-2.6.32/include/net/mac80211.h
@@ -908,6 +908,9 @@
  * @IEEE80211_HW_BEACON_FILTER:
  *	Hardware supports dropping of irrelevant beacon frames to
  *	avoid waking up cpu.
+ * @IEEE80211_HW_REPORTS_TX_ACK_STATUS:
+ *	Hardware can provide ack status reports of Tx frames to
+ *	the stack.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_RX_INCLUDES_FCS			= 1<<1,
@@ -924,6 +927,7 @@
 	IEEE80211_HW_SUPPORTS_DYNAMIC_PS		= 1<<12,
 	IEEE80211_HW_MFP_CAPABLE			= 1<<13,
 	IEEE80211_HW_BEACON_FILTER			= 1<<14,
+	IEEE80211_HW_REPORTS_TX_ACK_STATUS		= 1<<15,
 };
 
 /**
@@ -1696,6 +1700,12 @@
  */
 void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
 
+/*
+ * The TX headroom reserved by mac80211 for its own tx_status functions.
+ * This is enough for the radiotap header.
+ */
+#define IEEE80211_TX_STATUS_HEADROOM	13
+
 /**
  * ieee80211_tx_status - transmit status callback
  *
--- linux-ec2-2.6.32.orig/include/net/x25.h
+++ linux-ec2-2.6.32/include/net/x25.h
@@ -182,6 +182,10 @@
 extern int  sysctl_x25_ack_holdback_timeout;
 extern int  sysctl_x25_forward;
 
+extern int x25_parse_address_block(struct sk_buff *skb,
+		struct x25_address *called_addr,
+		struct x25_address *calling_addr);
+
 extern int  x25_addr_ntoa(unsigned char *, struct x25_address *,
 			  struct x25_address *);
 extern int  x25_addr_aton(unsigned char *, struct x25_address *,
--- linux-ec2-2.6.32.orig/include/net/af_unix.h
+++ linux-ec2-2.6.32/include/net/af_unix.h
@@ -10,6 +10,7 @@
 extern void unix_notinflight(struct file *fp);
 extern void unix_gc(void);
 extern void wait_for_unix_gc(void);
+extern struct sock *unix_get_socket(struct file *filp);
 
 #define UNIX_HASH_SIZE	256
 
@@ -56,6 +57,7 @@
         spinlock_t		lock;
 	unsigned int		gc_candidate : 1;
 	unsigned int		gc_maybe_cycle : 1;
+	unsigned char		recursion_level;
         wait_queue_head_t       peer_wait;
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
--- linux-ec2-2.6.32.orig/include/net/ip.h
+++ linux-ec2-2.6.32/include/net/ip.h
@@ -342,6 +342,7 @@
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
 	IP_DEFRAG_CONNTRACK_OUT,
+	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
--- linux-ec2-2.6.32.orig/include/net/tcp.h
+++ linux-ec2-2.6.32/include/net/tcp.h
@@ -259,11 +259,21 @@
 	return seq3 - seq2 >= seq1 - seq2;
 }
 
-static inline int tcp_too_many_orphans(struct sock *sk, int num)
+static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
 {
-	return (num > sysctl_tcp_max_orphans) ||
-		(sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
-		 atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]);
+	struct percpu_counter *ocp = sk->sk_prot->orphan_count;
+	int orphans = percpu_counter_read_positive(ocp);
+
+	if (orphans << shift > sysctl_tcp_max_orphans) {
+		orphans = percpu_counter_sum_positive(ocp);
+		if (orphans << shift > sysctl_tcp_max_orphans)
+			return true;
+	}
+
+	if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+	    atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
+		return true;
+	return false;
 }
 
 /* syncookies: remember time of last synqueue overflow */
@@ -501,8 +511,22 @@
 /* Bound MSS / TSO packet size with the half of the window */
 static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
 {
-	if (tp->max_window && pktsize > (tp->max_window >> 1))
-		return max(tp->max_window >> 1, 68U - tp->tcp_header_len);
+	int cutoff;
+
+	/* When peer uses tiny windows, there is no use in packetizing
+	 * to sub-MSS pieces for the sake of SWS or making sure there
+	 * are enough packets in the pipe for fast recovery.
+	 *
+	 * On the other hand, for extremely large MSS devices, handling
+	 * smaller than MSS windows in this way does make sense.
+	 */
+	if (tp->max_window >= 512)
+		cutoff = (tp->max_window >> 1);
+	else
+		cutoff = tp->max_window;
+
+	if (cutoff && pktsize > cutoff)
+		return max_t(int, cutoff, 68U - tp->tcp_header_len);
 	else
 		return pktsize;
 }
@@ -1263,14 +1287,20 @@
  * TCP connection after "boundary" unsucessful, exponentially backed-off
  * retransmissions with an initial RTO of TCP_RTO_MIN.
  */
-static inline bool retransmits_timed_out(const struct sock *sk,
+static inline bool retransmits_timed_out(struct sock *sk,
 					 unsigned int boundary)
 {
 	unsigned int timeout, linear_backoff_thresh;
+	unsigned int start_ts;
 
 	if (!inet_csk(sk)->icsk_retransmits)
 		return false;
 
+	if (unlikely(!tcp_sk(sk)->retrans_stamp))
+		start_ts = TCP_SKB_CB(tcp_write_queue_head(sk))->when;
+	else
+		start_ts = tcp_sk(sk)->retrans_stamp;
+
 	linear_backoff_thresh = ilog2(TCP_RTO_MAX/TCP_RTO_MIN);
 
 	if (boundary <= linear_backoff_thresh)
@@ -1279,7 +1309,7 @@
 		timeout = ((2 << linear_backoff_thresh) - 1) * TCP_RTO_MIN +
 			  (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
 
-	return (tcp_time_stamp - tcp_sk(sk)->retrans_stamp) >= timeout;
+	return (tcp_time_stamp - start_ts) >= timeout;
 }
 
 static inline struct sk_buff *tcp_send_head(struct sock *sk)
--- linux-ec2-2.6.32.orig/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ linux-ec2-2.6.32/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -9,7 +9,7 @@
 
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
 extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
 			       struct net_device *in,
 			       struct net_device *out,
--- linux-ec2-2.6.32.orig/include/net/sctp/command.h
+++ linux-ec2-2.6.32/include/net/sctp/command.h
@@ -107,6 +107,7 @@
 	SCTP_CMD_T1_RETRAN,	 /* Mark for retransmission after T1 timeout  */
 	SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */
 	SCTP_CMD_SEND_MSG,	 /* Send the whole use message */
+	SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
--- linux-ec2-2.6.32.orig/include/net/sctp/sm.h
+++ linux-ec2-2.6.32/include/net/sctp/sm.h
@@ -278,6 +278,7 @@
 /* 2nd level prototypes */
 void sctp_generate_t3_rtx_event(unsigned long peer);
 void sctp_generate_heartbeat_event(unsigned long peer);
+void sctp_generate_proto_unreach_event(unsigned long peer);
 
 void sctp_ootb_pkt_free(struct sctp_packet *);
 
--- linux-ec2-2.6.32.orig/include/net/sctp/structs.h
+++ linux-ec2-2.6.32/include/net/sctp/structs.h
@@ -772,6 +772,7 @@
 			  struct iovec *data);
 void sctp_chunk_free(struct sctp_chunk *);
 void  *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
+void  *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
 struct sctp_chunk *sctp_chunkify(struct sk_buff *,
 				 const struct sctp_association *,
 				 struct sock *);
@@ -1007,6 +1008,9 @@
 	/* Heartbeat timer is per destination. */
 	struct timer_list hb_timer;
 
+	/* Timer to handle ICMP proto unreachable envets */
+	struct timer_list proto_unreach_timer;
+
 	/* Since we're using per-destination retransmission timers
 	 * (see above), we're also using per-destination "transmitted"
 	 * queues.  This probably ought to be a private struct
--- linux-ec2-2.6.32.orig/include/net/netns/ipv4.h
+++ linux-ec2-2.6.32/include/net/netns/ipv4.h
@@ -40,6 +40,7 @@
 	struct xt_table		*iptable_security;
 	struct xt_table		*nat_table;
 	struct hlist_head	*nat_bysource;
+	unsigned int		nat_htable_size;
 	int			nat_vmalloced;
 #endif
 
--- linux-ec2-2.6.32.orig/include/net/netns/conntrack.h
+++ linux-ec2-2.6.32/include/net/netns/conntrack.h
@@ -11,6 +11,8 @@
 struct netns_ct {
 	atomic_t		count;
 	unsigned int		expect_count;
+	unsigned int		htable_size;
+	struct kmem_cache	*nf_conntrack_cachep;
 	struct hlist_nulls_head	*hash;
 	struct hlist_head	*expect_hash;
 	struct hlist_nulls_head	unconfirmed;
@@ -28,5 +30,6 @@
 #endif
 	int			hash_vmalloc;
 	int			expect_vmalloc;
+	char			*slabname;
 };
 #endif
--- linux-ec2-2.6.32.orig/include/drm/via_drm.h
+++ linux-ec2-2.6.32/include/drm/via_drm.h
@@ -24,7 +24,7 @@
 #ifndef _VIA_DRM_H_
 #define _VIA_DRM_H_
 
-#include <linux/types.h>
+#include "drm.h"
 
 /* WARNING: These defines must be the same as what the Xserver uses.
  * if you change them, you must change the defines in the Xserver.
--- linux-ec2-2.6.32.orig/include/drm/drm.h
+++ linux-ec2-2.6.32/include/drm/drm.h
@@ -36,17 +36,27 @@
 #ifndef _DRM_H_
 #define _DRM_H_
 
+#if defined(__linux__)
+
 #include <linux/types.h>
-#include <asm/ioctl.h>		/* For _IO* macros */
-#define DRM_IOCTL_NR(n)		_IOC_NR(n)
-#define DRM_IOC_VOID		_IOC_NONE
-#define DRM_IOC_READ		_IOC_READ
-#define DRM_IOC_WRITE		_IOC_WRITE
-#define DRM_IOC_READWRITE	_IOC_READ|_IOC_WRITE
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#include <asm/ioctl.h>
+typedef unsigned int drm_handle_t;
+
+#else /* One of the BSDs */
 
-#define DRM_MAJOR       226
-#define DRM_MAX_MINOR   15
+#include <sys/ioccom.h>
+#include <sys/types.h>
+typedef int8_t   __s8;
+typedef uint8_t  __u8;
+typedef int16_t  __s16;
+typedef uint16_t __u16;
+typedef int32_t  __s32;
+typedef uint32_t __u32;
+typedef int64_t  __s64;
+typedef uint64_t __u64;
+typedef unsigned long drm_handle_t;
+
+#endif
 
 #define DRM_NAME	"drm"	  /**< Name in kernel, /dev, and /proc */
 #define DRM_MIN_ORDER	5	  /**< At least 2^5 bytes = 32 bytes */
@@ -59,7 +69,6 @@
 #define _DRM_LOCK_IS_CONT(lock)	   ((lock) & _DRM_LOCK_CONT)
 #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
 
-typedef unsigned int drm_handle_t;
 typedef unsigned int drm_context_t;
 typedef unsigned int drm_drawable_t;
 typedef unsigned int drm_magic_t;
@@ -454,6 +463,7 @@
 enum drm_vblank_seq_type {
 	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
 	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
+	_DRM_VBLANK_EVENT = 0x4000000,   /**< Send event instead of blocking */
 	_DRM_VBLANK_FLIP = 0x8000000,   /**< Scheduled buffer swap should flip */
 	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
 	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
@@ -461,8 +471,8 @@
 };
 
 #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
-#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
-				_DRM_VBLANK_NEXTONMISS)
+#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \
+				_DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)
 
 struct drm_wait_vblank_request {
 	enum drm_vblank_seq_type type;
@@ -686,6 +696,8 @@
 #define DRM_IOCTL_MODE_GETFB		DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
 #define DRM_IOCTL_MODE_ADDFB		DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
 #define DRM_IOCTL_MODE_RMFB		DRM_IOWR(0xAF, unsigned int)
+#define DRM_IOCTL_MODE_PAGE_FLIP	DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
+#define DRM_IOCTL_MODE_DIRTYFB		DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
 
 /**
  * Device specific ioctls should only be in their respective headers
@@ -698,6 +710,35 @@
 #define DRM_COMMAND_BASE                0x40
 #define DRM_COMMAND_END			0xA0
 
+/**
+ * Header for events written back to userspace on the drm fd.  The
+ * type defines the type of event, the length specifies the total
+ * length of the event (including the header), and user_data is
+ * typically a 64 bit value passed with the ioctl that triggered the
+ * event.  A read on the drm fd will always only return complete
+ * events, that is, if for example the read buffer is 100 bytes, and
+ * there are two 64 byte events pending, only one will be returned.
+ *
+ * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
+ * up are chipset specific.
+ */
+struct drm_event {
+	__u32 type;
+	__u32 length;
+};
+
+#define DRM_EVENT_VBLANK 0x01
+#define DRM_EVENT_FLIP_COMPLETE 0x02
+
+struct drm_event_vblank {
+	struct drm_event base;
+	__u64 user_data;
+	__u32 tv_sec;
+	__u32 tv_usec;
+	__u32 sequence;
+	__u32 reserved;
+};
+
 /* typedef area */
 #ifndef __KERNEL__
 typedef struct drm_clip_rect drm_clip_rect_t;
--- linux-ec2-2.6.32.orig/include/drm/drmP.h
+++ linux-ec2-2.6.32/include/drm/drmP.h
@@ -245,16 +245,6 @@
 
 #endif
 
-#define DRM_PROC_LIMIT (PAGE_SIZE-80)
-
-#define DRM_PROC_PRINT(fmt, arg...)					\
-   len += sprintf(&buf[len], fmt , ##arg);				\
-   if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
-
-#define DRM_PROC_PRINT_RET(ret, fmt, arg...)				\
-   len += sprintf(&buf[len], fmt , ##arg);				\
-   if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
-
 /*@}*/
 
 /***********************************************************************/
@@ -265,19 +255,8 @@
 
 #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
-#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
 
 #define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-/**
- * Get the private SAREA mapping.
- *
- * \param _dev DRM device.
- * \param _ctx context number.
- * \param _map output mapping.
- */
-#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {	\
-	(_map) = (_dev)->context_sareas[_ctx];		\
-} while(0)
 
 /**
  * Test that the hardware lock is held by the caller, returning otherwise.
@@ -297,18 +276,6 @@
 } while (0)
 
 /**
- * Copy and IOCTL return string to user space
- */
-#define DRM_COPY( name, value )						\
-	len = strlen( value );						\
-	if ( len > name##_len ) len = name##_len;			\
-	name##_len = strlen( value );					\
-	if ( len && name ) {						\
-		if ( copy_to_user( name, value, len ) )			\
-			return -EFAULT;					\
-	}
-
-/**
  * Ioctl function type.
  *
  * \param inode device inode.
@@ -322,10 +289,14 @@
 typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
 			       unsigned long arg);
 
+#define DRM_IOCTL_NR(n)                _IOC_NR(n)
+#define DRM_MAJOR       226
+
 #define DRM_AUTH	0x1
 #define	DRM_MASTER	0x2
 #define DRM_ROOT_ONLY	0x4
 #define DRM_CONTROL_ALLOW 0x8
+#define DRM_UNLOCKED	0x10
 
 struct drm_ioctl_desc {
 	unsigned int cmd;
@@ -426,6 +397,14 @@
 	struct drm_freelist freelist;
 };
 
+/* Event queued up for userspace to read */
+struct drm_pending_event {
+	struct drm_event *event;
+	struct list_head link;
+	struct drm_file *file_priv;
+	void (*destroy)(struct drm_pending_event *event);
+};
+
 /** File private data */
 struct drm_file {
 	int authenticated;
@@ -449,6 +428,10 @@
 	struct drm_master *master; /* master this node is currently associated with
 				      N.B. not always minor->master */
 	struct list_head fbs;
+
+	wait_queue_head_t event_wait;
+	struct list_head event_list;
+	int event_space;
 };
 
 /** Wait queue */
@@ -795,6 +778,15 @@
 	/* Master routines */
 	int (*master_create)(struct drm_device *dev, struct drm_master *master);
 	void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+	/**
+	 * master_set is called whenever the minor master is set.
+	 * master_drop is called whenever the minor master is dropped.
+	 */
+
+	int (*master_set)(struct drm_device *dev, struct drm_file *file_priv,
+			  bool from_open);
+	void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv,
+			    bool from_release);
 
 	int (*proc_init)(struct drm_minor *minor);
 	void (*proc_cleanup)(struct drm_minor *minor);
@@ -900,6 +892,12 @@
 	struct drm_mode_group mode_group;
 };
 
+struct drm_pending_vblank_event {
+	struct drm_pending_event base;
+	int pipe;
+	struct drm_event_vblank event;
+};
+
 /**
  * DRM device structure. This structure represent a complete card that
  * may contain multiple heads.
@@ -999,6 +997,12 @@
 
 	u32 max_vblank_count;           /**< size of vblank counter register */
 
+	/**
+	 * List of events
+	 */
+	struct list_head vblank_event_list;
+	spinlock_t event_lock;
+
 	/*@} */
 	cycles_t ctx_start;
 	cycles_t lck_start;
@@ -1016,7 +1020,7 @@
 	struct pci_controller *hose;
 #endif
 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
-	int num_crtcs;                  /**< Number of CRTCs on this device */
+	unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
 	void *dev_private;		/**< device private data */
 	void *mm_private;
 	struct address_space *dev_mapping;
@@ -1125,8 +1129,8 @@
 				/* Driver support (drm_drv.h) */
 extern int drm_init(struct drm_driver *driver);
 extern void drm_exit(struct drm_driver *driver);
-extern int drm_ioctl(struct inode *inode, struct file *filp,
-		     unsigned int cmd, unsigned long arg);
+extern long drm_ioctl(struct file *filp,
+		      unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern int drm_lastclose(struct drm_device *dev);
@@ -1135,6 +1139,8 @@
 extern int drm_open(struct inode *inode, struct file *filp);
 extern int drm_stub_open(struct inode *inode, struct file *filp);
 extern int drm_fasync(int fd, struct file *filp, int on);
+extern ssize_t drm_read(struct file *filp, char __user *buffer,
+			size_t count, loff_t *offset);
 extern int drm_release(struct inode *inode, struct file *filp);
 
 				/* Mapping support (drm_vm.h) */
@@ -1295,6 +1301,7 @@
 extern void drm_handle_vblank(struct drm_device *dev, int crtc);
 extern int drm_vblank_get(struct drm_device *dev, int crtc);
 extern void drm_vblank_put(struct drm_device *dev, int crtc);
+extern void drm_vblank_off(struct drm_device *dev, int crtc);
 extern void drm_vblank_cleanup(struct drm_device *dev);
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
@@ -1401,7 +1408,7 @@
 				   struct drm_ati_pcigart_info * gart_info);
 
 extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
-				       size_t align, dma_addr_t maxaddr);
+				       size_t align);
 extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
 
@@ -1519,14 +1526,27 @@
 
 static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
 {
+	if (size != 0 && nmemb > ULONG_MAX / size)
+		return NULL;
+
 	if (size * nmemb <= PAGE_SIZE)
 	    return kcalloc(nmemb, size, GFP_KERNEL);
 
+	return __vmalloc(size * nmemb,
+			 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+}
+
+/* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
+static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
+{
 	if (size != 0 && nmemb > ULONG_MAX / size)
 		return NULL;
 
+	if (size * nmemb <= PAGE_SIZE)
+	    return kmalloc(nmemb * size, GFP_KERNEL);
+
 	return __vmalloc(size * nmemb,
-			 GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+			 GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
 
 static __inline void drm_free_large(void *ptr)
--- linux-ec2-2.6.32.orig/include/drm/i915_drm.h
+++ linux-ec2-2.6.32/include/drm/i915_drm.h
@@ -27,11 +27,11 @@
 #ifndef _I915_DRM_H_
 #define _I915_DRM_H_
 
+#include "drm.h"
+
 /* Please note that modifications to all structs defined here are
  * subject to backwards-compatibility constraints.
  */
-#include <linux/types.h>
-#include "drm.h"
 
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
@@ -186,6 +186,9 @@
 #define DRM_I915_GEM_MMAP_GTT	0x24
 #define DRM_I915_GET_PIPE_FROM_CRTC_ID	0x25
 #define DRM_I915_GEM_MADVISE	0x26
+#define DRM_I915_OVERLAY_PUT_IMAGE	0x27
+#define DRM_I915_OVERLAY_ATTRS	0x28
+#define DRM_I915_GEM_EXECBUFFER2	0x29
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -205,6 +208,7 @@
 #define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
 #define DRM_IOCTL_I915_GEM_INIT		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
 #define DRM_IOCTL_I915_GEM_EXECBUFFER	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER2	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
 #define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
 #define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
 #define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
@@ -221,8 +225,10 @@
 #define DRM_IOCTL_I915_GEM_SET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
 #define DRM_IOCTL_I915_GEM_GET_TILING	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
 #define DRM_IOCTL_I915_GEM_GET_APERTURE	DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
-#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id)
+#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
 #define DRM_IOCTL_I915_GEM_MADVISE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
+#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE	DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
+#define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -266,6 +272,9 @@
 #define I915_PARAM_CHIPSET_ID            4
 #define I915_PARAM_HAS_GEM               5
 #define I915_PARAM_NUM_FENCES_AVAIL      6
+#define I915_PARAM_HAS_OVERLAY           7
+#define I915_PARAM_HAS_PAGEFLIPPING	 8
+#define I915_PARAM_HAS_EXECBUF2          9
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -561,6 +570,57 @@
 	__u64 cliprects_ptr;
 };
 
+struct drm_i915_gem_exec_object2 {
+	/**
+	 * User's handle for a buffer to be bound into the GTT for this
+	 * operation.
+	 */
+	__u32 handle;
+
+	/** Number of relocations to be performed on this buffer */
+	__u32 relocation_count;
+	/**
+	 * Pointer to array of struct drm_i915_gem_relocation_entry containing
+	 * the relocations to be performed in this buffer.
+	 */
+	__u64 relocs_ptr;
+
+	/** Required alignment in graphics aperture */
+	__u64 alignment;
+
+	/**
+	 * Returned value of the updated offset of the object, for future
+	 * presumed_offset writes.
+	 */
+	__u64 offset;
+
+#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
+	__u64 flags;
+	__u64 rsvd1;
+	__u64 rsvd2;
+};
+
+struct drm_i915_gem_execbuffer2 {
+	/**
+	 * List of gem_exec_object2 structs
+	 */
+	__u64 buffers_ptr;
+	__u32 buffer_count;
+
+	/** Offset in the batchbuffer to start execution from. */
+	__u32 batch_start_offset;
+	/** Bytes used in batchbuffer from batch_start_offset */
+	__u32 batch_len;
+	__u32 DR1;
+	__u32 DR4;
+	__u32 num_cliprects;
+	/** This is a struct drm_clip_rect *cliprects */
+	__u64 cliprects_ptr;
+	__u64 flags; /* currently unused */
+	__u64 rsvd1;
+	__u64 rsvd2;
+};
+
 struct drm_i915_gem_pin {
 	/** Handle of the buffer to be pinned. */
 	__u32 handle;
@@ -686,4 +746,70 @@
 	__u32 retained;
 };
 
+/* flags */
+#define I915_OVERLAY_TYPE_MASK 		0xff
+#define I915_OVERLAY_YUV_PLANAR 	0x01
+#define I915_OVERLAY_YUV_PACKED 	0x02
+#define I915_OVERLAY_RGB		0x03
+
+#define I915_OVERLAY_DEPTH_MASK		0xff00
+#define I915_OVERLAY_RGB24		0x1000
+#define I915_OVERLAY_RGB16		0x2000
+#define I915_OVERLAY_RGB15		0x3000
+#define I915_OVERLAY_YUV422		0x0100
+#define I915_OVERLAY_YUV411		0x0200
+#define I915_OVERLAY_YUV420		0x0300
+#define I915_OVERLAY_YUV410		0x0400
+
+#define I915_OVERLAY_SWAP_MASK		0xff0000
+#define I915_OVERLAY_NO_SWAP		0x000000
+#define I915_OVERLAY_UV_SWAP		0x010000
+#define I915_OVERLAY_Y_SWAP		0x020000
+#define I915_OVERLAY_Y_AND_UV_SWAP	0x030000
+
+#define I915_OVERLAY_FLAGS_MASK		0xff000000
+#define I915_OVERLAY_ENABLE		0x01000000
+
+struct drm_intel_overlay_put_image {
+	/* various flags and src format description */
+	__u32 flags;
+	/* source picture description */
+	__u32 bo_handle;
+	/* stride values and offsets are in bytes, buffer relative */
+	__u16 stride_Y; /* stride for packed formats */
+	__u16 stride_UV;
+	__u32 offset_Y; /* offset for packet formats */
+	__u32 offset_U;
+	__u32 offset_V;
+	/* in pixels */
+	__u16 src_width;
+	__u16 src_height;
+	/* to compensate the scaling factors for partially covered surfaces */
+	__u16 src_scan_width;
+	__u16 src_scan_height;
+	/* output crtc description */
+	__u32 crtc_id;
+	__u16 dst_x;
+	__u16 dst_y;
+	__u16 dst_width;
+	__u16 dst_height;
+};
+
+/* flags */
+#define I915_OVERLAY_UPDATE_ATTRS	(1<<0)
+#define I915_OVERLAY_UPDATE_GAMMA	(1<<1)
+struct drm_intel_overlay_attrs {
+	__u32 flags;
+	__u32 color_key;
+	__s32 brightness;
+	__u32 contrast;
+	__u32 saturation;
+	__u32 gamma0;
+	__u32 gamma1;
+	__u32 gamma2;
+	__u32 gamma3;
+	__u32 gamma4;
+	__u32 gamma5;
+};
+
 #endif				/* _I915_DRM_H_ */
--- linux-ec2-2.6.32.orig/include/drm/drm_crtc.h
+++ linux-ec2-2.6.32/include/drm/drm_crtc.h
@@ -123,7 +123,7 @@
 	int type;
 
 	/* Proposed mode values */
-	int clock;
+	int clock;		/* in kHz */
 	int hdisplay;
 	int hsync_start;
 	int hsync_end;
@@ -164,8 +164,8 @@
 	int *private;
 	int private_flags;
 
-	int vrefresh;
-	float hsync;
+	int vrefresh;		/* in Hz */
+	int hsync;		/* in kHz */
 };
 
 enum drm_connector_status {
@@ -242,6 +242,21 @@
 	int (*create_handle)(struct drm_framebuffer *fb,
 			     struct drm_file *file_priv,
 			     unsigned int *handle);
+	/**
+	 * Optinal callback for the dirty fb ioctl.
+	 *
+	 * Userspace can notify the driver via this callback
+	 * that a area of the framebuffer has changed and should
+	 * be flushed to the display hardware.
+	 *
+	 * See documentation in drm_mode.h for the struct
+	 * drm_mode_fb_dirty_cmd for more information as all
+	 * the semantics and arguments have a one to one mapping
+	 * on this function.
+	 */
+	int (*dirty)(struct drm_framebuffer *framebuffer, unsigned flags,
+		     unsigned color, struct drm_clip_rect *clips,
+		     unsigned num_clips);
 };
 
 struct drm_framebuffer {
@@ -256,7 +271,7 @@
 	unsigned int depth;
 	int bits_per_pixel;
 	int flags;
-	void *fbdev;
+	struct fb_info *fbdev;
 	u32 pseudo_palette[17];
 	struct list_head filp_head;
 	/* if you are using the helper */
@@ -290,6 +305,7 @@
 struct drm_crtc;
 struct drm_connector;
 struct drm_encoder;
+struct drm_pending_vblank_event;
 
 /**
  * drm_crtc_funcs - control CRTCs for a given device
@@ -333,6 +349,19 @@
 	void (*destroy)(struct drm_crtc *crtc);
 
 	int (*set_config)(struct drm_mode_set *set);
+
+	/*
+	 * Flip to the given framebuffer.  This implements the page
+	 * flip ioctl descibed in drm_mode.h, specifically, the
+	 * implementation must return immediately and block all
+	 * rendering to the current fb until the flip has completed.
+	 * If userspace set the event flag in the ioctl, the event
+	 * argument will point to an event to send back when the flip
+	 * completes, otherwise it will be NULL.
+	 */
+	int (*page_flip)(struct drm_crtc *crtc,
+			 struct drm_framebuffer *fb,
+			 struct drm_pending_vblank_event *event);
 };
 
 /**
@@ -596,6 +625,7 @@
 	/* Optional properties */
 	struct drm_property *scaling_mode_property;
 	struct drm_property *dithering_mode_property;
+	struct drm_property *dirty_info_property;
 };
 
 #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
@@ -667,6 +697,7 @@
 extern void drm_mode_prune_invalid(struct drm_device *dev,
 				   struct list_head *mode_list, bool verbose);
 extern void drm_mode_sort(struct list_head *mode_list);
+extern int drm_mode_hsync(struct drm_display_mode *mode);
 extern int drm_mode_vrefresh(struct drm_display_mode *mode);
 extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
 				  int adjust_flags);
@@ -703,6 +734,7 @@
 				     char *formats[]);
 extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 extern int drm_mode_create_dithering_property(struct drm_device *dev);
+extern int drm_mode_create_dirty_info_property(struct drm_device *dev);
 extern char *drm_get_encoder_name(struct drm_encoder *encoder);
 
 extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
@@ -711,7 +743,8 @@
 					   struct drm_encoder *encoder);
 extern bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
 					 int gamma_size);
-extern void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type);
+extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
+		uint32_t id, uint32_t type);
 /* IOCTLs */
 extern int drm_mode_getresources(struct drm_device *dev,
 				 void *data, struct drm_file *file_priv);
@@ -730,6 +763,8 @@
 			 void *data, struct drm_file *file_priv);
 extern int drm_mode_getfb(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
+extern int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+				  void *data, struct drm_file *file_priv);
 extern int drm_mode_addmode_ioctl(struct drm_device *dev,
 				  void *data, struct drm_file *file_priv);
 extern int drm_mode_rmmode_ioctl(struct drm_device *dev,
@@ -756,6 +791,8 @@
 extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 				    void *data, struct drm_file *file_priv);
 extern bool drm_detect_hdmi_monitor(struct edid *edid);
+extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
+				    void *data, struct drm_file *file_priv);
 extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
 				int hdisplay, int vdisplay, int vrefresh,
 				bool reduced, bool interlaced, bool margins);
--- linux-ec2-2.6.32.orig/include/drm/nouveau_drm.h
+++ linux-ec2-2.6.32/include/drm/nouveau_drm.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2005 Stephane Marchesin.
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 __NOUVEAU_DRM_H__
+#define __NOUVEAU_DRM_H__
+
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15
+
+struct drm_nouveau_channel_alloc {
+	uint32_t     fb_ctxdma_handle;
+	uint32_t     tt_ctxdma_handle;
+
+	int          channel;
+
+	/* Notifier memory */
+	uint32_t     notifier_handle;
+
+	/* DRM-enforced subchannel assignments */
+	struct {
+		uint32_t handle;
+		uint32_t grclass;
+	} subchan[8];
+	uint32_t nr_subchan;
+};
+
+struct drm_nouveau_channel_free {
+	int channel;
+};
+
+struct drm_nouveau_grobj_alloc {
+	int      channel;
+	uint32_t handle;
+	int      class;
+};
+
+struct drm_nouveau_notifierobj_alloc {
+	uint32_t channel;
+	uint32_t handle;
+	uint32_t size;
+	uint32_t offset;
+};
+
+struct drm_nouveau_gpuobj_free {
+	int      channel;
+	uint32_t handle;
+};
+
+/* FIXME : maybe unify {GET,SET}PARAMs */
+#define NOUVEAU_GETPARAM_PCI_VENDOR      3
+#define NOUVEAU_GETPARAM_PCI_DEVICE      4
+#define NOUVEAU_GETPARAM_BUS_TYPE        5
+#define NOUVEAU_GETPARAM_FB_PHYSICAL     6
+#define NOUVEAU_GETPARAM_AGP_PHYSICAL    7
+#define NOUVEAU_GETPARAM_FB_SIZE         8
+#define NOUVEAU_GETPARAM_AGP_SIZE        9
+#define NOUVEAU_GETPARAM_PCI_PHYSICAL    10
+#define NOUVEAU_GETPARAM_CHIPSET_ID      11
+#define NOUVEAU_GETPARAM_VM_VRAM_BASE    12
+#define NOUVEAU_GETPARAM_GRAPH_UNITS     13
+struct drm_nouveau_getparam {
+	uint64_t param;
+	uint64_t value;
+};
+
+struct drm_nouveau_setparam {
+	uint64_t param;
+	uint64_t value;
+};
+
+#define NOUVEAU_GEM_DOMAIN_CPU       (1 << 0)
+#define NOUVEAU_GEM_DOMAIN_VRAM      (1 << 1)
+#define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
+#define NOUVEAU_GEM_DOMAIN_MAPPABLE  (1 << 3)
+
+struct drm_nouveau_gem_info {
+	uint32_t handle;
+	uint32_t domain;
+	uint64_t size;
+	uint64_t offset;
+	uint64_t map_handle;
+	uint32_t tile_mode;
+	uint32_t tile_flags;
+};
+
+struct drm_nouveau_gem_new {
+	struct drm_nouveau_gem_info info;
+	uint32_t channel_hint;
+	uint32_t align;
+};
+
+struct drm_nouveau_gem_pushbuf_bo {
+	uint64_t user_priv;
+	uint32_t handle;
+	uint32_t read_domains;
+	uint32_t write_domains;
+	uint32_t valid_domains;
+	uint32_t presumed_ok;
+	uint32_t presumed_domain;
+	uint64_t presumed_offset;
+};
+
+#define NOUVEAU_GEM_RELOC_LOW  (1 << 0)
+#define NOUVEAU_GEM_RELOC_HIGH (1 << 1)
+#define NOUVEAU_GEM_RELOC_OR   (1 << 2)
+struct drm_nouveau_gem_pushbuf_reloc {
+	uint32_t bo_index;
+	uint32_t reloc_index;
+	uint32_t flags;
+	uint32_t data;
+	uint32_t vor;
+	uint32_t tor;
+};
+
+#define NOUVEAU_GEM_MAX_BUFFERS 1024
+#define NOUVEAU_GEM_MAX_RELOCS 1024
+
+struct drm_nouveau_gem_pushbuf {
+	uint32_t channel;
+	uint32_t nr_dwords;
+	uint32_t nr_buffers;
+	uint32_t nr_relocs;
+	uint64_t dwords;
+	uint64_t buffers;
+	uint64_t relocs;
+};
+
+struct drm_nouveau_gem_pushbuf_call {
+	uint32_t channel;
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t nr_buffers;
+	uint32_t nr_relocs;
+	uint32_t nr_dwords;
+	uint64_t buffers;
+	uint64_t relocs;
+	uint32_t suffix0;
+	uint32_t suffix1;
+	/* below only accessed for CALL2 */
+	uint64_t vram_available;
+	uint64_t gart_available;
+};
+
+struct drm_nouveau_gem_pin {
+	uint32_t handle;
+	uint32_t domain;
+	uint64_t offset;
+};
+
+struct drm_nouveau_gem_unpin {
+	uint32_t handle;
+};
+
+#define NOUVEAU_GEM_CPU_PREP_NOWAIT                                  0x00000001
+#define NOUVEAU_GEM_CPU_PREP_NOBLOCK                                 0x00000002
+#define NOUVEAU_GEM_CPU_PREP_WRITE                                   0x00000004
+struct drm_nouveau_gem_cpu_prep {
+	uint32_t handle;
+	uint32_t flags;
+};
+
+struct drm_nouveau_gem_cpu_fini {
+	uint32_t handle;
+};
+
+struct drm_nouveau_gem_tile {
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t size;
+	uint32_t tile_mode;
+	uint32_t tile_flags;
+};
+
+enum nouveau_bus_type {
+	NV_AGP     = 0,
+	NV_PCI     = 1,
+	NV_PCIE    = 2,
+};
+
+struct drm_nouveau_sarea {
+};
+
+#define DRM_NOUVEAU_CARD_INIT          0x00
+#define DRM_NOUVEAU_GETPARAM           0x01
+#define DRM_NOUVEAU_SETPARAM           0x02
+#define DRM_NOUVEAU_CHANNEL_ALLOC      0x03
+#define DRM_NOUVEAU_CHANNEL_FREE       0x04
+#define DRM_NOUVEAU_GROBJ_ALLOC        0x05
+#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC  0x06
+#define DRM_NOUVEAU_GPUOBJ_FREE        0x07
+#define DRM_NOUVEAU_GEM_NEW            0x40
+#define DRM_NOUVEAU_GEM_PUSHBUF        0x41
+#define DRM_NOUVEAU_GEM_PUSHBUF_CALL   0x42
+#define DRM_NOUVEAU_GEM_PIN            0x43 /* !KMS only */
+#define DRM_NOUVEAU_GEM_UNPIN          0x44 /* !KMS only */
+#define DRM_NOUVEAU_GEM_CPU_PREP       0x45
+#define DRM_NOUVEAU_GEM_CPU_FINI       0x46
+#define DRM_NOUVEAU_GEM_INFO           0x47
+#define DRM_NOUVEAU_GEM_PUSHBUF_CALL2  0x48
+
+#endif /* __NOUVEAU_DRM_H__ */
--- linux-ec2-2.6.32.orig/include/drm/radeon_drm.h
+++ linux-ec2-2.6.32/include/drm/radeon_drm.h
@@ -33,7 +33,7 @@
 #ifndef __RADEON_DRM_H__
 #define __RADEON_DRM_H__
 
-#include <linux/types.h>
+#include "drm.h"
 
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the X server file (radeon_sarea.h)
--- linux-ec2-2.6.32.orig/include/drm/mga_drm.h
+++ linux-ec2-2.6.32/include/drm/mga_drm.h
@@ -35,7 +35,7 @@
 #ifndef __MGA_DRM_H__
 #define __MGA_DRM_H__
 
-#include <linux/types.h>
+#include "drm.h"
 
 /* WARNING: If you change any of these defines, make sure to change the
  * defines in the Xserver file (mga_sarea.h)
--- linux-ec2-2.6.32.orig/include/drm/drm_mode.h
+++ linux-ec2-2.6.32/include/drm/drm_mode.h
@@ -27,9 +27,6 @@
 #ifndef _DRM_MODE_H
 #define _DRM_MODE_H
 
-#include <linux/kernel.h>
-#include <linux/types.h>
-
 #define DRM_DISPLAY_INFO_LEN	32
 #define DRM_CONNECTOR_NAME_LEN	32
 #define DRM_DISPLAY_MODE_LEN	32
@@ -78,12 +75,17 @@
 #define DRM_MODE_DITHERING_OFF	0
 #define DRM_MODE_DITHERING_ON	1
 
+/* Dirty info options */
+#define DRM_MODE_DIRTY_OFF      0
+#define DRM_MODE_DIRTY_ON       1
+#define DRM_MODE_DIRTY_ANNOTATE 2
+
 struct drm_mode_modeinfo {
 	__u32 clock;
 	__u16 hdisplay, hsync_start, hsync_end, htotal, hskew;
 	__u16 vdisplay, vsync_start, vsync_end, vtotal, vscan;
 
-	__u32 vrefresh; /* vertical refresh * 1000 */
+	__u32 vrefresh;
 
 	__u32 flags;
 	__u32 type;
@@ -158,6 +160,7 @@
 #define DRM_MODE_CONNECTOR_HDMIA	11
 #define DRM_MODE_CONNECTOR_HDMIB	12
 #define DRM_MODE_CONNECTOR_TV		13
+#define DRM_MODE_CONNECTOR_eDP		14
 
 struct drm_mode_get_connector {
 
@@ -225,6 +228,45 @@
 	__u32 handle;
 };
 
+#define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01
+#define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
+#define DRM_MODE_FB_DIRTY_FLAGS         0x03
+
+/*
+ * Mark a region of a framebuffer as dirty.
+ *
+ * Some hardware does not automatically update display contents
+ * as a hardware or software draw to a framebuffer. This ioctl
+ * allows userspace to tell the kernel and the hardware what
+ * regions of the framebuffer have changed.
+ *
+ * The kernel or hardware is free to update more then just the
+ * region specified by the clip rects. The kernel or hardware
+ * may also delay and/or coalesce several calls to dirty into a
+ * single update.
+ *
+ * Userspace may annotate the updates, the annotates are a
+ * promise made by the caller that the change is either a copy
+ * of pixels or a fill of a single color in the region specified.
+ *
+ * If the DRM_MODE_FB_DIRTY_ANNOTATE_COPY flag is given then
+ * the number of updated regions are half of num_clips given,
+ * where the clip rects are paired in src and dst. The width and
+ * height of each one of the pairs must match.
+ *
+ * If the DRM_MODE_FB_DIRTY_ANNOTATE_FILL flag is given the caller
+ * promises that the region specified of the clip rects is filled
+ * completely with a single color as given in the color argument.
+ */
+
+struct drm_mode_fb_dirty_cmd {
+	__u32 fb_id;
+	__u32 flags;
+	__u32 color;
+	__u32 num_clips;
+	__u64 clips_ptr;
+};
+
 struct drm_mode_mode_cmd {
 	__u32 connector_id;
 	struct drm_mode_modeinfo mode;
@@ -268,4 +310,37 @@
 	__u64 blue;
 };
 
+#define DRM_MODE_PAGE_FLIP_EVENT 0x01
+#define DRM_MODE_PAGE_FLIP_FLAGS DRM_MODE_PAGE_FLIP_EVENT
+
+/*
+ * Request a page flip on the specified crtc.
+ *
+ * This ioctl will ask KMS to schedule a page flip for the specified
+ * crtc.  Once any pending rendering targeting the specified fb (as of
+ * ioctl time) has completed, the crtc will be reprogrammed to display
+ * that fb after the next vertical refresh.  The ioctl returns
+ * immediately, but subsequent rendering to the current fb will block
+ * in the execbuffer ioctl until the page flip happens.  If a page
+ * flip is already pending as the ioctl is called, EBUSY will be
+ * returned.
+ *
+ * The ioctl supports one flag, DRM_MODE_PAGE_FLIP_EVENT, which will
+ * request that drm sends back a vblank event (see drm.h: struct
+ * drm_event_vblank) when the page flip is done.  The user_data field
+ * passed in with this ioctl will be returned as the user_data field
+ * in the vblank event struct.
+ *
+ * The reserved field must be zero until we figure out something
+ * clever to use it for.
+ */
+
+struct drm_mode_crtc_page_flip {
+	__u32 crtc_id;
+	__u32 fb_id;
+	__u32 flags;
+	__u32 reserved;
+	__u64 user_data;
+};
+
 #endif
--- linux-ec2-2.6.32.orig/include/drm/drm_os_linux.h
+++ linux-ec2-2.6.32/include/drm/drm_os_linux.h
@@ -123,5 +123,5 @@
 	remove_wait_queue(&(queue), &entry);			\
 } while (0)
 
-#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
+#define DRM_WAKEUP( queue ) wake_up( queue )
 #define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
--- linux-ec2-2.6.32.orig/include/drm/drm_pciids.h
+++ linux-ec2-2.6.32/include/drm/drm_pciids.h
@@ -6,6 +6,7 @@
 	{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x3155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
@@ -27,7 +28,6 @@
 	{0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
 	{0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
 	{0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-	{0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
 	{0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
@@ -84,7 +84,6 @@
 	{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-	{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R423|RADEON_NEW_MEMMAP}, \
@@ -102,6 +101,7 @@
 	{0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
 	{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
 	{0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
@@ -375,6 +375,7 @@
 	{0x1002, 0x9712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+	{0x1002, 0x9715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
 	{0, 0, 0}
 
 #define r128_PCI_IDS \
--- linux-ec2-2.6.32.orig/include/drm/Kbuild
+++ linux-ec2-2.6.32/include/drm/Kbuild
@@ -7,4 +7,6 @@
 unifdef-y += radeon_drm.h
 unifdef-y += sis_drm.h
 unifdef-y += savage_drm.h
+unifdef-y += vmwgfx_drm.h
 unifdef-y += via_drm.h
+unifdef-y += nouveau_drm.h
--- linux-ec2-2.6.32.orig/include/drm/drm_mm.h
+++ linux-ec2-2.6.32/include/drm/drm_mm.h
@@ -66,6 +66,13 @@
 						    unsigned long size,
 						    unsigned alignment,
 						    int atomic);
+extern struct drm_mm_node *drm_mm_get_block_range_generic(
+						struct drm_mm_node *node,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int atomic);
 static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
 						   unsigned long size,
 						   unsigned alignment)
@@ -78,11 +85,38 @@
 {
 	return drm_mm_get_block_generic(parent, size, alignment, 1);
 }
+static inline struct drm_mm_node *drm_mm_get_block_range(
+						struct drm_mm_node *parent,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end)
+{
+	return drm_mm_get_block_range_generic(parent, size, alignment,
+						start, end, 0);
+}
+static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
+						struct drm_mm_node *parent,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end)
+{
+	return drm_mm_get_block_range_generic(parent, size, alignment,
+						start, end, 1);
+}
 extern void drm_mm_put_block(struct drm_mm_node *cur);
 extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
 					      unsigned long size,
 					      unsigned alignment,
 					      int best_match);
+extern struct drm_mm_node *drm_mm_search_free_in_range(
+						const struct drm_mm *mm,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int best_match);
 extern int drm_mm_init(struct drm_mm *mm, unsigned long start,
 		       unsigned long size);
 extern void drm_mm_takedown(struct drm_mm *mm);
@@ -99,6 +133,7 @@
 	return block->mm;
 }
 
+extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
 #ifdef CONFIG_DEBUG_FS
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm);
 #endif
--- linux-ec2-2.6.32.orig/include/drm/vmwgfx_drm.h
+++ linux-ec2-2.6.32/include/drm/vmwgfx_drm.h
@@ -0,0 +1,588 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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 __VMWGFX_DRM_H__
+#define __VMWGFX_DRM_H__
+
+#define DRM_VMW_MAX_SURFACE_FACES 6
+#define DRM_VMW_MAX_MIP_LEVELS 24
+
+#define DRM_VMW_EXT_NAME_LEN 128
+
+#define DRM_VMW_GET_PARAM            0
+#define DRM_VMW_ALLOC_DMABUF         1
+#define DRM_VMW_UNREF_DMABUF         2
+#define DRM_VMW_CURSOR_BYPASS        3
+/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/
+#define DRM_VMW_CONTROL_STREAM       4
+#define DRM_VMW_CLAIM_STREAM         5
+#define DRM_VMW_UNREF_STREAM         6
+/* guarded by DRM_VMW_PARAM_3D == 1 */
+#define DRM_VMW_CREATE_CONTEXT       7
+#define DRM_VMW_UNREF_CONTEXT        8
+#define DRM_VMW_CREATE_SURFACE       9
+#define DRM_VMW_UNREF_SURFACE        10
+#define DRM_VMW_REF_SURFACE          11
+#define DRM_VMW_EXECBUF              12
+#define DRM_VMW_FIFO_DEBUG           13
+#define DRM_VMW_FENCE_WAIT           14
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GET_PARAM - get device information.
+ *
+ * DRM_VMW_PARAM_FIFO_OFFSET:
+ * Offset to use to map the first page of the FIFO read-only.
+ * The fifo is mapped using the mmap() system call on the drm device.
+ *
+ * DRM_VMW_PARAM_OVERLAY_IOCTL:
+ * Does the driver support the overlay ioctl.
+ */
+
+#define DRM_VMW_PARAM_NUM_STREAMS      0
+#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
+#define DRM_VMW_PARAM_3D               2
+#define DRM_VMW_PARAM_FIFO_OFFSET      3
+#define DRM_VMW_PARAM_HW_CAPS          4
+#define DRM_VMW_PARAM_FIFO_CAPS        5
+
+/**
+ * struct drm_vmw_getparam_arg
+ *
+ * @value: Returned value. //Out
+ * @param: Parameter to query. //In.
+ *
+ * Argument to the DRM_VMW_GET_PARAM Ioctl.
+ */
+
+struct drm_vmw_getparam_arg {
+	uint64_t value;
+	uint32_t param;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_EXTENSION - Query device extensions.
+ */
+
+/**
+ * struct drm_vmw_extension_rep
+ *
+ * @exists: The queried extension exists.
+ * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension.
+ * @driver_sarea_offset: Offset to any space in the DRI SAREA
+ * used by the extension.
+ * @major: Major version number of the extension.
+ * @minor: Minor version number of the extension.
+ * @pl: Patch level version number of the extension.
+ *
+ * Output argument to the DRM_VMW_EXTENSION Ioctl.
+ */
+
+struct drm_vmw_extension_rep {
+	int32_t exists;
+	uint32_t driver_ioctl_offset;
+	uint32_t driver_sarea_offset;
+	uint32_t major;
+	uint32_t minor;
+	uint32_t pl;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_extension_arg
+ *
+ * @extension - Ascii name of the extension to be queried. //In
+ * @rep - Reply as defined above. //Out
+ *
+ * Argument to the DRM_VMW_EXTENSION Ioctl.
+ */
+
+union drm_vmw_extension_arg {
+	char extension[DRM_VMW_EXT_NAME_LEN];
+	struct drm_vmw_extension_rep rep;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_CONTEXT - Create a host context.
+ *
+ * Allocates a device unique context id, and queues a create context command
+ * for the host. Does not wait for host completion.
+ */
+
+/**
+ * struct drm_vmw_context_arg
+ *
+ * @cid: Device unique context ID.
+ *
+ * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
+ * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
+ */
+
+struct drm_vmw_context_arg {
+	int32_t cid;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_CONTEXT - Create a host context.
+ *
+ * Frees a global context id, and queues a destroy host command for the host.
+ * Does not wait for host completion. The context ID can be used directly
+ * in the command stream and shows up as the same context ID on the host.
+ */
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_SURFACE - Create a host suface.
+ *
+ * Allocates a device unique surface id, and queues a create surface command
+ * for the host. Does not wait for host completion. The surface ID can be
+ * used directly in the command stream and shows up as the same surface
+ * ID on the host.
+ */
+
+/**
+ * struct drm_wmv_surface_create_req
+ *
+ * @flags: Surface flags as understood by the host.
+ * @format: Surface format as understood by the host.
+ * @mip_levels: Number of mip levels for each face.
+ * An unused face should have 0 encoded.
+ * @size_addr: Address of a user-space array of sruct drm_vmw_size
+ * cast to an uint64_t for 32-64 bit compatibility.
+ * The size of the array should equal the total number of mipmap levels.
+ * @shareable: Boolean whether other clients (as identified by file descriptors)
+ * may reference this surface.
+ * @scanout: Boolean whether the surface is intended to be used as a
+ * scanout.
+ *
+ * Input data to the DRM_VMW_CREATE_SURFACE Ioctl.
+ * Output data from the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+struct drm_vmw_surface_create_req {
+	uint32_t flags;
+	uint32_t format;
+	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
+	uint64_t size_addr;
+	int32_t shareable;
+	int32_t scanout;
+};
+
+/**
+ * struct drm_wmv_surface_arg
+ *
+ * @sid: Surface id of created surface or surface to destroy or reference.
+ *
+ * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
+ * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
+ * Input argument to the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+struct drm_vmw_surface_arg {
+	int32_t sid;
+	uint32_t pad64;
+};
+
+/**
+ * struct drm_vmw_size ioctl.
+ *
+ * @width - mip level width
+ * @height - mip level height
+ * @depth - mip level depth
+ *
+ * Description of a mip level.
+ * Input data to the DRM_WMW_CREATE_SURFACE Ioctl.
+ */
+
+struct drm_vmw_size {
+	uint32_t width;
+	uint32_t height;
+	uint32_t depth;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_surface_create_arg
+ *
+ * @rep: Output data as described above.
+ * @req: Input data as described above.
+ *
+ * Argument to the DRM_VMW_CREATE_SURFACE Ioctl.
+ */
+
+union drm_vmw_surface_create_arg {
+	struct drm_vmw_surface_arg rep;
+	struct drm_vmw_surface_create_req req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_REF_SURFACE - Reference a host surface.
+ *
+ * Puts a reference on a host surface with a give sid, as previously
+ * returned by the DRM_VMW_CREATE_SURFACE ioctl.
+ * A reference will make sure the surface isn't destroyed while we hold
+ * it and will allow the calling client to use the surface ID in the command
+ * stream.
+ *
+ * On successful return, the Ioctl returns the surface information given
+ * in the DRM_VMW_CREATE_SURFACE ioctl.
+ */
+
+/**
+ * union drm_vmw_surface_reference_arg
+ *
+ * @rep: Output data as described above.
+ * @req: Input data as described above.
+ *
+ * Argument to the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+union drm_vmw_surface_reference_arg {
+	struct drm_vmw_surface_create_req rep;
+	struct drm_vmw_surface_arg req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_SURFACE - Unreference a host surface.
+ *
+ * Clear a reference previously put on a host surface.
+ * When all references are gone, including the one implicitly placed
+ * on creation,
+ * a destroy surface command will be queued for the host.
+ * Does not wait for completion.
+ */
+
+/*************************************************************************/
+/**
+ * DRM_VMW_EXECBUF
+ *
+ * Submit a command buffer for execution on the host, and return a
+ * fence sequence that when signaled, indicates that the command buffer has
+ * executed.
+ */
+
+/**
+ * struct drm_vmw_execbuf_arg
+ *
+ * @commands: User-space address of a command buffer cast to an uint64_t.
+ * @command-size: Size in bytes of the command buffer.
+ * @throttle-us: Sleep until software is less than @throttle_us
+ * microseconds ahead of hardware. The driver may round this value
+ * to the nearest kernel tick.
+ * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an
+ * uint64_t.
+ * @version: Allows expanding the execbuf ioctl parameters without breaking
+ * backwards compatibility, since user-space will always tell the kernel
+ * which version it uses.
+ * @flags: Execbuf flags. None currently.
+ *
+ * Argument to the DRM_VMW_EXECBUF Ioctl.
+ */
+
+#define DRM_VMW_EXECBUF_VERSION 0
+
+struct drm_vmw_execbuf_arg {
+	uint64_t commands;
+	uint32_t command_size;
+	uint32_t throttle_us;
+	uint64_t fence_rep;
+	 uint32_t version;
+	 uint32_t flags;
+};
+
+/**
+ * struct drm_vmw_fence_rep
+ *
+ * @fence_seq: Fence sequence associated with a command submission.
+ * @error: This member should've been set to -EFAULT on submission.
+ * The following actions should be take on completion:
+ * error == -EFAULT: Fence communication failed. The host is synchronized.
+ * Use the last fence id read from the FIFO fence register.
+ * error != 0 && error != -EFAULT:
+ * Fence submission failed. The host is synchronized. Use the fence_seq member.
+ * error == 0: All is OK, The host may not be synchronized.
+ * Use the fence_seq member.
+ *
+ * Input / Output data to the DRM_VMW_EXECBUF Ioctl.
+ */
+
+struct drm_vmw_fence_rep {
+	uint64_t fence_seq;
+	int32_t error;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_ALLOC_DMABUF
+ *
+ * Allocate a DMA buffer that is visible also to the host.
+ * NOTE: The buffer is
+ * identified by a handle and an offset, which are private to the guest, but
+ * useable in the command stream. The guest kernel may translate these
+ * and patch up the command stream accordingly. In the future, the offset may
+ * be zero at all times, or it may disappear from the interface before it is
+ * fixed.
+ *
+ * The DMA buffer may stay user-space mapped in the guest at all times,
+ * and is thus suitable for sub-allocation.
+ *
+ * DMA buffers are mapped using the mmap() syscall on the drm device.
+ */
+
+/**
+ * struct drm_vmw_alloc_dmabuf_req
+ *
+ * @size: Required minimum size of the buffer.
+ *
+ * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+struct drm_vmw_alloc_dmabuf_req {
+	uint32_t size;
+	uint32_t pad64;
+};
+
+/**
+ * struct drm_vmw_dmabuf_rep
+ *
+ * @map_handle: Offset to use in the mmap() call used to map the buffer.
+ * @handle: Handle unique to this buffer. Used for unreferencing.
+ * @cur_gmr_id: GMR id to use in the command stream when this buffer is
+ * referenced. See not above.
+ * @cur_gmr_offset: Offset to use in the command stream when this buffer is
+ * referenced. See note above.
+ *
+ * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+struct drm_vmw_dmabuf_rep {
+	uint64_t map_handle;
+	uint32_t handle;
+	uint32_t cur_gmr_id;
+	uint32_t cur_gmr_offset;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_dmabuf_arg
+ *
+ * @req: Input data as described above.
+ * @rep: Output data as described above.
+ *
+ * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+union drm_vmw_alloc_dmabuf_arg {
+	struct drm_vmw_alloc_dmabuf_req req;
+	struct drm_vmw_dmabuf_rep rep;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_DMABUF - Free a DMA buffer.
+ *
+ */
+
+/**
+ * struct drm_vmw_unref_dmabuf_arg
+ *
+ * @handle: Handle indicating what buffer to free. Obtained from the
+ * DRM_VMW_ALLOC_DMABUF Ioctl.
+ *
+ * Argument to the DRM_VMW_UNREF_DMABUF Ioctl.
+ */
+
+struct drm_vmw_unref_dmabuf_arg {
+	uint32_t handle;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_FIFO_DEBUG - Get last FIFO submission.
+ *
+ * This IOCTL copies the last FIFO submission directly out of the FIFO buffer.
+ */
+
+/**
+ * struct drm_vmw_fifo_debug_arg
+ *
+ * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In
+ * @debug_buffer_size: Size in bytes of debug buffer //In
+ * @used_size: Number of bytes copied to the buffer // Out
+ * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out
+ *
+ * Argument to the DRM_VMW_FIFO_DEBUG Ioctl.
+ */
+
+struct drm_vmw_fifo_debug_arg {
+	uint64_t debug_buffer;
+	uint32_t debug_buffer_size;
+	uint32_t used_size;
+	int32_t did_not_fit;
+	uint32_t pad64;
+};
+
+struct drm_vmw_fence_wait_arg {
+	uint64_t sequence;
+	uint64_t kernel_cookie;
+	int32_t cookie_valid;
+	int32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams.
+ *
+ * This IOCTL controls the overlay units of the svga device.
+ * The SVGA overlay units does not work like regular hardware units in
+ * that they do not automaticaly read back the contents of the given dma
+ * buffer. But instead only read back for each call to this ioctl, and
+ * at any point between this call being made and a following call that
+ * either changes the buffer or disables the stream.
+ */
+
+/**
+ * struct drm_vmw_rect
+ *
+ * Defines a rectangle. Used in the overlay ioctl to define
+ * source and destination rectangle.
+ */
+
+struct drm_vmw_rect {
+	int32_t x;
+	int32_t y;
+	uint32_t w;
+	uint32_t h;
+};
+
+/**
+ * struct drm_vmw_control_stream_arg
+ *
+ * @stream_id: Stearm to control
+ * @enabled: If false all following arguments are ignored.
+ * @handle: Handle to buffer for getting data from.
+ * @format: Format of the overlay as understood by the host.
+ * @width: Width of the overlay.
+ * @height: Height of the overlay.
+ * @size: Size of the overlay in bytes.
+ * @pitch: Array of pitches, the two last are only used for YUV12 formats.
+ * @offset: Offset from start of dma buffer to overlay.
+ * @src: Source rect, must be within the defined area above.
+ * @dst: Destination rect, x and y may be negative.
+ *
+ * Argument to the DRM_VMW_CONTROL_STREAM Ioctl.
+ */
+
+struct drm_vmw_control_stream_arg {
+	uint32_t stream_id;
+	uint32_t enabled;
+
+	uint32_t flags;
+	uint32_t color_key;
+
+	uint32_t handle;
+	uint32_t offset;
+	int32_t format;
+	uint32_t size;
+	uint32_t width;
+	uint32_t height;
+	uint32_t pitch[3];
+
+	uint32_t pad64;
+	struct drm_vmw_rect src;
+	struct drm_vmw_rect dst;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass.
+ *
+ */
+
+#define DRM_VMW_CURSOR_BYPASS_ALL    (1 << 0)
+#define DRM_VMW_CURSOR_BYPASS_FLAGS       (1)
+
+/**
+ * struct drm_vmw_cursor_bypass_arg
+ *
+ * @flags: Flags.
+ * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed.
+ * @xpos: X position of cursor.
+ * @ypos: Y position of cursor.
+ * @xhot: X hotspot.
+ * @yhot: Y hotspot.
+ *
+ * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl.
+ */
+
+struct drm_vmw_cursor_bypass_arg {
+	uint32_t flags;
+	uint32_t crtc_id;
+	int32_t xpos;
+	int32_t ypos;
+	int32_t xhot;
+	int32_t yhot;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CLAIM_STREAM - Claim a single stream.
+ */
+
+/**
+ * struct drm_vmw_context_arg
+ *
+ * @stream_id: Device unique context ID.
+ *
+ * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
+ * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
+ */
+
+struct drm_vmw_stream_arg {
+	uint32_t stream_id;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_STREAM - Unclaim a stream.
+ *
+ * Return a single stream that was claimed by this process. Also makes
+ * sure that the stream has been stopped.
+ */
+
+#endif
--- linux-ec2-2.6.32.orig/include/drm/drm_dp_helper.h
+++ linux-ec2-2.6.32/include/drm/drm_dp_helper.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright © 2008 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _DRM_DP_HELPER_H_
+#define _DRM_DP_HELPER_H_
+
+/* From the VESA DisplayPort spec */
+
+#define AUX_NATIVE_WRITE	0x8
+#define AUX_NATIVE_READ		0x9
+#define AUX_I2C_WRITE		0x0
+#define AUX_I2C_READ		0x1
+#define AUX_I2C_STATUS		0x2
+#define AUX_I2C_MOT		0x4
+
+#define AUX_NATIVE_REPLY_ACK	(0x0 << 4)
+#define AUX_NATIVE_REPLY_NACK	(0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER	(0x2 << 4)
+#define AUX_NATIVE_REPLY_MASK	(0x3 << 4)
+
+#define AUX_I2C_REPLY_ACK	(0x0 << 6)
+#define AUX_I2C_REPLY_NACK	(0x1 << 6)
+#define AUX_I2C_REPLY_DEFER	(0x2 << 6)
+#define AUX_I2C_REPLY_MASK	(0x3 << 6)
+
+/* AUX CH addresses */
+/* DPCD */
+#define DP_DPCD_REV                         0x000
+
+#define DP_MAX_LINK_RATE                    0x001
+
+#define DP_MAX_LANE_COUNT                   0x002
+# define DP_MAX_LANE_COUNT_MASK		    0x1f
+# define DP_ENHANCED_FRAME_CAP		    (1 << 7)
+
+#define DP_MAX_DOWNSPREAD                   0x003
+# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING  (1 << 6)
+
+#define DP_NORP                             0x004
+
+#define DP_DOWNSTREAMPORT_PRESENT           0x005
+# define DP_DWN_STRM_PORT_PRESENT           (1 << 0)
+# define DP_DWN_STRM_PORT_TYPE_MASK         0x06
+/* 00b = DisplayPort */
+/* 01b = Analog */
+/* 10b = TMDS or HDMI */
+/* 11b = Other */
+# define DP_FORMAT_CONVERSION               (1 << 3)
+
+#define DP_MAIN_LINK_CHANNEL_CODING         0x006
+
+/* link configuration */
+#define	DP_LINK_BW_SET		            0x100
+# define DP_LINK_BW_1_62		    0x06
+# define DP_LINK_BW_2_7			    0x0a
+
+#define DP_LANE_COUNT_SET	            0x101
+# define DP_LANE_COUNT_MASK		    0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN    (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET	            0x102
+# define DP_TRAINING_PATTERN_DISABLE	    0
+# define DP_TRAINING_PATTERN_1		    1
+# define DP_TRAINING_PATTERN_2		    2
+# define DP_TRAINING_PATTERN_MASK	    0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE	    (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2	    (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE    (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7	    (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK	    (3 << 2)
+
+# define DP_RECOVERED_CLOCK_OUT_EN	    (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE	    (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH	    (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY    (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL	    (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK	    (3 << 6)
+
+#define DP_TRAINING_LANE0_SET		    0x103
+#define DP_TRAINING_LANE1_SET		    0x104
+#define DP_TRAINING_LANE2_SET		    0x105
+#define DP_TRAINING_LANE3_SET		    0x106
+
+# define DP_TRAIN_VOLTAGE_SWING_MASK	    0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT	    0
+# define DP_TRAIN_MAX_SWING_REACHED	    (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400	    (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600	    (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800	    (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200	    (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK	    (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0	    (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5	    (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6	    (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5	    (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT	    3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED  (1 << 5)
+
+#define DP_DOWNSPREAD_CTRL		    0x107
+# define DP_SPREAD_AMP_0_5		    (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET	    0x108
+# define DP_SET_ANSI_8B10B		    (1 << 0)
+
+#define DP_LANE0_1_STATUS		    0x202
+#define DP_LANE2_3_STATUS		    0x203
+# define DP_LANE_CR_DONE		    (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE	    (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED		    (1 << 2)
+
+#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE |		\
+			    DP_LANE_CHANNEL_EQ_DONE |	\
+			    DP_LANE_SYMBOL_LOCKED)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED	    0x204
+
+#define DP_INTERLANE_ALIGN_DONE		    (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED   (1 << 6)
+#define DP_LINK_STATUS_UPDATED		    (1 << 7)
+
+#define DP_SINK_STATUS			    0x205
+
+#define DP_RECEIVE_PORT_0_STATUS	    (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS	    (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1	    0x206
+#define DP_ADJUST_REQUEST_LANE2_3	    0x207
+# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK  0x03
+# define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+# define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK   0x0c
+# define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT  2
+# define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK  0x30
+# define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+# define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK   0xc0
+# define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT  6
+
+#define DP_SET_POWER                        0x600
+# define DP_SET_POWER_D0                    0x1
+# define DP_SET_POWER_D3                    0x2
+
+#define MODE_I2C_START	1
+#define MODE_I2C_WRITE	2
+#define MODE_I2C_READ	4
+#define MODE_I2C_STOP	8
+
+struct i2c_algo_dp_aux_data {
+	bool running;
+	u16 address;
+	int (*aux_ch) (struct i2c_adapter *adapter,
+		       int mode, uint8_t write_byte,
+		       uint8_t *read_byte);
+};
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
+
+#endif /* _DRM_DP_HELPER_H_ */
--- linux-ec2-2.6.32.orig/include/drm/drm_edid.h
+++ linux-ec2-2.6.32/include/drm/drm_edid.h
@@ -106,6 +106,10 @@
 	u8 wpindex2[3];
 } __attribute__((packed));
 
+struct cvt_timing {
+	u8 code[3];
+} __attribute__((packed));
+
 struct detailed_non_pixel {
 	u8 pad1;
 	u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
@@ -117,9 +121,13 @@
 		struct detailed_data_monitor_range range;
 		struct detailed_data_wpindex color;
 		struct std_timing timings[5];
+		struct cvt_timing cvt[4];
 	} data;
 } __attribute__((packed));
 
+#define EDID_DETAIL_EST_TIMINGS 0xf7
+#define EDID_DETAIL_CVT_3BYTE 0xf8
+#define EDID_DETAIL_COLOR_MGMT_DATA 0xf9
 #define EDID_DETAIL_STD_MODES 0xfa
 #define EDID_DETAIL_MONITOR_CPDATA 0xfb
 #define EDID_DETAIL_MONITOR_NAME 0xfc
--- linux-ec2-2.6.32.orig/include/drm/i2c/ch7006.h
+++ linux-ec2-2.6.32/include/drm/i2c/ch7006.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * 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 (including the
+ * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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 __DRM_I2C_CH7006_H__
+#define __DRM_I2C_CH7006_H__
+
+/**
+ * struct ch7006_encoder_params
+ *
+ * Describes how the ch7006 is wired up with the GPU. It should be
+ * used as the @params parameter of its @set_config method.
+ *
+ * See "http://www.chrontel.com/pdf/7006.pdf" for their precise
+ * meaning.
+ */
+struct ch7006_encoder_params {
+	enum {
+		CH7006_FORMAT_RGB16 = 0,
+		CH7006_FORMAT_YCrCb24m16,
+		CH7006_FORMAT_RGB24m16,
+		CH7006_FORMAT_RGB15,
+		CH7006_FORMAT_RGB24m12C,
+		CH7006_FORMAT_RGB24m12I,
+		CH7006_FORMAT_RGB24m8,
+		CH7006_FORMAT_RGB16m8,
+		CH7006_FORMAT_RGB15m8,
+		CH7006_FORMAT_YCrCb24m8,
+	} input_format;
+
+	enum {
+		CH7006_CLOCK_SLAVE = 0,
+		CH7006_CLOCK_MASTER,
+	} clock_mode;
+
+	enum {
+		CH7006_CLOCK_EDGE_NEG = 0,
+		CH7006_CLOCK_EDGE_POS,
+	} clock_edge;
+
+	int xcm, pcm;
+
+	enum {
+		CH7006_SYNC_SLAVE = 0,
+		CH7006_SYNC_MASTER,
+	} sync_direction;
+
+	enum {
+		CH7006_SYNC_SEPARATED = 0,
+		CH7006_SYNC_EMBEDDED,
+	} sync_encoding;
+
+	enum {
+		CH7006_POUT_1_8V = 0,
+		CH7006_POUT_3_3V,
+	} pout_level;
+
+	enum {
+		CH7006_ACTIVE_HSYNC = 0,
+		CH7006_ACTIVE_DSTART,
+	} active_detect;
+};
+
+#endif
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_bo_driver.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_bo_driver.h
@@ -242,12 +242,6 @@
 /**
  * struct ttm_bo_driver
  *
- * @mem_type_prio: Priority array of memory types to place a buffer object in
- * if it fits without evicting buffers from any of these memory types.
- * @mem_busy_prio: Priority array of memory types to place a buffer object in
- * if it needs to evict buffers to make room.
- * @num_mem_type_prio: Number of elements in the @mem_type_prio array.
- * @num_mem_busy_prio: Number of elements in the @num_mem_busy_prio array.
  * @create_ttm_backend_entry: Callback to create a struct ttm_backend.
  * @invalidate_caches: Callback to invalidate read caches when a buffer object
  * has been evicted.
@@ -265,11 +259,6 @@
  */
 
 struct ttm_bo_driver {
-	const uint32_t *mem_type_prio;
-	const uint32_t *mem_busy_prio;
-	uint32_t num_mem_type_prio;
-	uint32_t num_mem_busy_prio;
-
 	/**
 	 * struct ttm_bo_driver member create_ttm_backend_entry
 	 *
@@ -306,7 +295,8 @@
 	 * finished, they'll end up in bo->mem.flags
 	 */
 
-	 uint32_t(*evict_flags) (struct ttm_buffer_object *bo);
+	 void(*evict_flags) (struct ttm_buffer_object *bo,
+				struct ttm_placement *placement);
 	/**
 	 * struct ttm_bo_driver member move:
 	 *
@@ -363,6 +353,11 @@
 	/* notify the driver we are taking a fault on this BO
 	 * and have reserved it */
 	void (*fault_reserve_notify)(struct ttm_buffer_object *bo);
+
+	/**
+	 * notify the driver that we're about to swap out this bo
+	 */
+	void (*swap_notify) (struct ttm_buffer_object *bo);
 };
 
 /**
@@ -545,6 +540,15 @@
 extern int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem);
 
 /**
+ * ttm_tt_populate:
+ *
+ * @ttm: The struct ttm_tt to contain the backing pages.
+ *
+ * Add backing pages to all of @ttm
+ */
+extern int ttm_tt_populate(struct ttm_tt *ttm);
+
+/**
  * ttm_ttm_destroy:
  *
  * @ttm: The struct ttm_tt.
@@ -639,12 +643,12 @@
  * -EBUSY: No space available (only if no_wait == 1).
  * -ENOMEM: Could not allocate memory for the buffer object, either due to
  * fragmentation or concurrent allocators.
- * -ERESTART: An interruptible sleep was interrupted by a signal.
+ * -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
  */
 extern int ttm_bo_mem_space(struct ttm_buffer_object *bo,
-			    uint32_t proposed_placement,
-			    struct ttm_mem_reg *mem,
-			    bool interruptible, bool no_wait);
+				struct ttm_placement *placement,
+				struct ttm_mem_reg *mem,
+				bool interruptible, bool no_wait);
 /**
  * ttm_bo_wait_for_cpu
  *
@@ -654,7 +658,7 @@
  * Wait until a buffer object is no longer sync'ed for CPU access.
  * Returns:
  * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1).
- * -ERESTART: An interruptible sleep was interrupted by a signal.
+ * -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
  */
 
 extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait);
@@ -758,7 +762,7 @@
  * -EAGAIN: The reservation may cause a deadlock.
  * Release all buffer reservations, wait for @bo to become unreserved and
  * try again. (only if use_sequence == 1).
- * -ERESTART: A wait for the buffer to become unreserved was interrupted by
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
  * a signal. Release all buffer reservations and return to user-space.
  */
 extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
@@ -799,7 +803,7 @@
  *
  * Returns:
  * -EBUSY: If no_wait == 1 and the buffer is already reserved.
- * -ERESTART: If interruptible == 1 and the process received a signal
+ * -ERESTARTSYS: If interruptible == 1 and the process received a signal
  * while sleeping.
  */
 extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo,
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_execbuf_util.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_execbuf_util.h
@@ -0,0 +1,107 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+#ifndef _TTM_EXECBUF_UTIL_H_
+#define _TTM_EXECBUF_UTIL_H_
+
+#include "ttm/ttm_bo_api.h"
+#include <linux/list.h>
+
+/**
+ * struct ttm_validate_buffer
+ *
+ * @head:           list head for thread-private list.
+ * @bo:             refcounted buffer object pointer.
+ * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once
+ * adding a new sync object.
+ * @reservied:      Indicates whether @bo has been reserved for validation.
+ */
+
+struct ttm_validate_buffer {
+	struct list_head head;
+	struct ttm_buffer_object *bo;
+	void *new_sync_obj_arg;
+	bool reserved;
+};
+
+/**
+ * function ttm_eu_backoff_reservation
+ *
+ * @list:     thread private list of ttm_validate_buffer structs.
+ *
+ * Undoes all buffer validation reservations for bos pointed to by
+ * the list entries.
+ */
+
+extern void ttm_eu_backoff_reservation(struct list_head *list);
+
+/**
+ * function ttm_eu_reserve_buffers
+ *
+ * @list:    thread private list of ttm_validate_buffer structs.
+ * @val_seq: A unique sequence number.
+ *
+ * Tries to reserve bos pointed to by the list entries for validation.
+ * If the function returns 0, all buffers are marked as "unfenced",
+ * taken off the lru lists and are not synced for write CPU usage.
+ *
+ * If the function detects a deadlock due to multiple threads trying to
+ * reserve the same buffers in reverse order, all threads except one will
+ * back off and retry. This function may sleep while waiting for
+ * CPU write reservations to be cleared, and for other threads to
+ * unreserve their buffers.
+ *
+ * This function may return -ERESTART or -EAGAIN if the calling process
+ * receives a signal while waiting. In that case, no buffers on the list
+ * will be reserved upon return.
+ *
+ * Buffers reserved by this function should be unreserved by
+ * a call to either ttm_eu_backoff_reservation() or
+ * ttm_eu_fence_buffer_objects() when command submission is complete or
+ * has failed.
+ */
+
+extern int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq);
+
+/**
+ * function ttm_eu_fence_buffer_objects.
+ *
+ * @list:        thread private list of ttm_validate_buffer structs.
+ * @sync_obj:    The new sync object for the buffers.
+ *
+ * This function should be called when command submission is complete, and
+ * it will add a new sync object to bos pointed to by entries on @list.
+ * It also unreserves all buffers, putting them on lru lists.
+ *
+ */
+
+extern void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj);
+
+#endif
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_object.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_object.h
@@ -0,0 +1,271 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+/** @file ttm_object.h
+ *
+ * Base- and reference object implementation for the various
+ * ttm objects. Implements reference counting, minimal security checks
+ * and release on file close.
+ */
+
+#ifndef _TTM_OBJECT_H_
+#define _TTM_OBJECT_H_
+
+#include <linux/list.h>
+#include "drm_hashtab.h"
+#include <linux/kref.h>
+#include <ttm/ttm_memory.h>
+
+/**
+ * enum ttm_ref_type
+ *
+ * Describes what type of reference a ref object holds.
+ *
+ * TTM_REF_USAGE is a simple refcount on a base object.
+ *
+ * TTM_REF_SYNCCPU_READ is a SYNCCPU_READ reference on a
+ * buffer object.
+ *
+ * TTM_REF_SYNCCPU_WRITE is a SYNCCPU_WRITE reference on a
+ * buffer object.
+ *
+ */
+
+enum ttm_ref_type {
+	TTM_REF_USAGE,
+	TTM_REF_SYNCCPU_READ,
+	TTM_REF_SYNCCPU_WRITE,
+	TTM_REF_NUM
+};
+
+/**
+ * enum ttm_object_type
+ *
+ * One entry per ttm object type.
+ * Device-specific types should use the
+ * ttm_driver_typex types.
+ */
+
+enum ttm_object_type {
+	ttm_fence_type,
+	ttm_buffer_type,
+	ttm_lock_type,
+	ttm_driver_type0 = 256,
+	ttm_driver_type1,
+	ttm_driver_type2,
+	ttm_driver_type3,
+	ttm_driver_type4,
+	ttm_driver_type5
+};
+
+struct ttm_object_file;
+struct ttm_object_device;
+
+/**
+ * struct ttm_base_object
+ *
+ * @hash: hash entry for the per-device object hash.
+ * @type: derived type this object is base class for.
+ * @shareable: Other ttm_object_files can access this object.
+ *
+ * @tfile: Pointer to ttm_object_file of the creator.
+ * NULL if the object was not created by a user request.
+ * (kernel object).
+ *
+ * @refcount: Number of references to this object, not
+ * including the hash entry. A reference to a base object can
+ * only be held by a ref object.
+ *
+ * @refcount_release: A function to be called when there are
+ * no more references to this object. This function should
+ * destroy the object (or make sure destruction eventually happens),
+ * and when it is called, the object has
+ * already been taken out of the per-device hash. The parameter
+ * "base" should be set to NULL by the function.
+ *
+ * @ref_obj_release: A function to be called when a reference object
+ * with another ttm_ref_type than TTM_REF_USAGE is deleted.
+ * this function may, for example, release a lock held by a user-space
+ * process.
+ *
+ * This struct is intended to be used as a base struct for objects that
+ * are visible to user-space. It provides a global name, race-safe
+ * access and refcounting, minimal access contol and hooks for unref actions.
+ */
+
+struct ttm_base_object {
+	struct drm_hash_item hash;
+	enum ttm_object_type object_type;
+	bool shareable;
+	struct ttm_object_file *tfile;
+	struct kref refcount;
+	void (*refcount_release) (struct ttm_base_object **base);
+	void (*ref_obj_release) (struct ttm_base_object *base,
+				 enum ttm_ref_type ref_type);
+};
+
+/**
+ * ttm_base_object_init
+ *
+ * @tfile: Pointer to a struct ttm_object_file.
+ * @base: The struct ttm_base_object to initialize.
+ * @shareable: This object is shareable with other applcations.
+ * (different @tfile pointers.)
+ * @type: The object type.
+ * @refcount_release: See the struct ttm_base_object description.
+ * @ref_obj_release: See the struct ttm_base_object description.
+ *
+ * Initializes a struct ttm_base_object.
+ */
+
+extern int ttm_base_object_init(struct ttm_object_file *tfile,
+				struct ttm_base_object *base,
+				bool shareable,
+				enum ttm_object_type type,
+				void (*refcount_release) (struct ttm_base_object
+							  **),
+				void (*ref_obj_release) (struct ttm_base_object
+							 *,
+							 enum ttm_ref_type
+							 ref_type));
+
+/**
+ * ttm_base_object_lookup
+ *
+ * @tfile: Pointer to a struct ttm_object_file.
+ * @key: Hash key
+ *
+ * Looks up a struct ttm_base_object with the key @key.
+ * Also verifies that the object is visible to the application, by
+ * comparing the @tfile argument and checking the object shareable flag.
+ */
+
+extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
+						      *tfile, uint32_t key);
+
+/**
+ * ttm_base_object_unref
+ *
+ * @p_base: Pointer to a pointer referncing a struct ttm_base_object.
+ *
+ * Decrements the base object refcount and clears the pointer pointed to by
+ * p_base.
+ */
+
+extern void ttm_base_object_unref(struct ttm_base_object **p_base);
+
+/**
+ * ttm_ref_object_add.
+ *
+ * @tfile: A struct ttm_object_file representing the application owning the
+ * ref_object.
+ * @base: The base object to reference.
+ * @ref_type: The type of reference.
+ * @existed: Upon completion, indicates that an identical reference object
+ * already existed, and the refcount was upped on that object instead.
+ *
+ * Adding a ref object to a base object is basically like referencing the
+ * base object, but a user-space application holds the reference. When the
+ * file corresponding to @tfile is closed, all its reference objects are
+ * deleted. A reference object can have different types depending on what
+ * it's intended for. It can be refcounting to prevent object destruction,
+ * When user-space takes a lock, it can add a ref object to that lock to
+ * make sure the lock is released if the application dies. A ref object
+ * will hold a single reference on a base object.
+ */
+extern int ttm_ref_object_add(struct ttm_object_file *tfile,
+			      struct ttm_base_object *base,
+			      enum ttm_ref_type ref_type, bool *existed);
+/**
+ * ttm_ref_object_base_unref
+ *
+ * @key: Key representing the base object.
+ * @ref_type: Ref type of the ref object to be dereferenced.
+ *
+ * Unreference a ref object with type @ref_type
+ * on the base object identified by @key. If there are no duplicate
+ * references, the ref object will be destroyed and the base object
+ * will be unreferenced.
+ */
+extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+				     unsigned long key,
+				     enum ttm_ref_type ref_type);
+
+/**
+ * ttm_object_file_init - initialize a struct ttm_object file
+ *
+ * @tdev: A struct ttm_object device this file is initialized on.
+ * @hash_order: Order of the hash table used to hold the reference objects.
+ *
+ * This is typically called by the file_ops::open function.
+ */
+
+extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
+						    *tdev,
+						    unsigned int hash_order);
+
+/**
+ * ttm_object_file_release - release data held by a ttm_object_file
+ *
+ * @p_tfile: Pointer to pointer to the ttm_object_file object to release.
+ * *p_tfile will be set to NULL by this function.
+ *
+ * Releases all data associated by a ttm_object_file.
+ * Typically called from file_ops::release. The caller must
+ * ensure that there are no concurrent users of tfile.
+ */
+
+extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
+
+/**
+ * ttm_object device init - initialize a struct ttm_object_device
+ *
+ * @hash_order: Order of hash table used to hash the base objects.
+ *
+ * This function is typically called on device initialization to prepare
+ * data structures needed for ttm base and ref objects.
+ */
+
+extern struct ttm_object_device *ttm_object_device_init
+    (struct ttm_mem_global *mem_glob, unsigned int hash_order);
+
+/**
+ * ttm_object_device_release - release data held by a ttm_object_device
+ *
+ * @p_tdev: Pointer to pointer to the ttm_object_device object to release.
+ * *p_tdev will be set to NULL by this function.
+ *
+ * Releases all data associated by a ttm_object_device.
+ * Typically called from driver::unload before the destruction of the
+ * device private data structure.
+ */
+
+extern void ttm_object_device_release(struct ttm_object_device **p_tdev);
+
+#endif
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_lock.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_lock.h
@@ -0,0 +1,247 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+/** @file ttm_lock.h
+ * This file implements a simple replacement for the buffer manager use
+ * of the DRM heavyweight hardware lock.
+ * The lock is a read-write lock. Taking it in read mode and write mode
+ * is relatively fast, and intended for in-kernel use only.
+ *
+ * The vt mode is used only when there is a need to block all
+ * user-space processes from validating buffers.
+ * It's allowed to leave kernel space with the vt lock held.
+ * If a user-space process dies while having the vt-lock,
+ * it will be released during the file descriptor release. The vt lock
+ * excludes write lock and read lock.
+ *
+ * The suspend mode is used to lock out all TTM users when preparing for
+ * and executing suspend operations.
+ *
+ */
+
+#ifndef _TTM_LOCK_H_
+#define _TTM_LOCK_H_
+
+#include "ttm/ttm_object.h"
+#include <linux/wait.h>
+#include <asm/atomic.h>
+
+/**
+ * struct ttm_lock
+ *
+ * @base: ttm base object used solely to release the lock if the client
+ * holding the lock dies.
+ * @queue: Queue for processes waiting for lock change-of-status.
+ * @lock: Spinlock protecting some lock members.
+ * @rw: Read-write lock counter. Protected by @lock.
+ * @flags: Lock state. Protected by @lock.
+ * @kill_takers: Boolean whether to kill takers of the lock.
+ * @signal: Signal to send when kill_takers is true.
+ */
+
+struct ttm_lock {
+	struct ttm_base_object base;
+	wait_queue_head_t queue;
+	spinlock_t lock;
+	int32_t rw;
+	uint32_t flags;
+	bool kill_takers;
+	int signal;
+	struct ttm_object_file *vt_holder;
+};
+
+
+/**
+ * ttm_lock_init
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * Initializes the lock.
+ */
+extern void ttm_lock_init(struct ttm_lock *lock);
+
+/**
+ * ttm_read_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a read lock.
+ */
+extern void ttm_read_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_read_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in read mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_read_trylock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Tries to take the lock in read mode. If the lock is already held
+ * in write mode, the function will return -EBUSY. If the lock is held
+ * in vt or suspend mode, the function will sleep until these modes
+ * are unlocked.
+ *
+ * Returns:
+ * -EBUSY The lock was already held in write mode.
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_write_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a write lock.
+ */
+extern void ttm_write_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in write mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_lock_downgrade
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Downgrades a write lock to a read lock.
+ */
+extern void ttm_lock_downgrade(struct ttm_lock *lock);
+
+/**
+ * ttm_suspend_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Takes the lock in suspend mode. Excludes read and write mode.
+ */
+extern void ttm_suspend_lock(struct ttm_lock *lock);
+
+/**
+ * ttm_suspend_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a suspend lock
+ */
+extern void ttm_suspend_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_vt_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ * @tfile: Pointer to a struct ttm_object_file to register the lock with.
+ *
+ * Takes the lock in vt mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ * -ENOMEM: Out of memory when locking.
+ */
+extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible,
+		       struct ttm_object_file *tfile);
+
+/**
+ * ttm_vt_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a vt lock.
+ * Returns:
+ * -EINVAL If the lock was not held.
+ */
+extern int ttm_vt_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a write lock.
+ */
+extern void ttm_write_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in write mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_lock_set_kill
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @val: Boolean whether to kill processes taking the lock.
+ * @signal: Signal to send to the process taking the lock.
+ *
+ * The kill-when-taking-lock functionality is used to kill processes that keep
+ * on using the TTM functionality when its resources has been taken down, for
+ * example when the X server exits. A typical sequence would look like this:
+ * - X server takes lock in write mode.
+ * - ttm_lock_set_kill() is called with @val set to true.
+ * - As part of X server exit, TTM resources are taken down.
+ * - X server releases the lock on file release.
+ * - Another dri client wants to render, takes the lock and is killed.
+ *
+ */
+static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val,
+				     int signal)
+{
+	lock->kill_takers = val;
+	if (val)
+		lock->signal = signal;
+}
+
+#endif
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_bo_api.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_bo_api.h
@@ -44,6 +44,29 @@
 
 struct drm_mm_node;
 
+
+/**
+ * struct ttm_placement
+ *
+ * @fpfn:		first valid page frame number to put the object
+ * @lpfn:		last valid page frame number to put the object
+ * @num_placement:	number of prefered placements
+ * @placement:		prefered placements
+ * @num_busy_placement:	number of prefered placements when need to evict buffer
+ * @busy_placement:	prefered placements when need to evict buffer
+ *
+ * Structure indicating the placement you request for an object.
+ */
+struct ttm_placement {
+	unsigned	fpfn;
+	unsigned	lpfn;
+	unsigned	num_placement;
+	const uint32_t	*placement;
+	unsigned	num_busy_placement;
+	const uint32_t	*busy_placement;
+};
+
+
 /**
  * struct ttm_mem_reg
  *
@@ -109,10 +132,6 @@
  * the object is destroyed.
  * @event_queue: Queue for processes waiting on buffer object status change.
  * @lock: spinlock protecting mostly synchronization members.
- * @proposed_placement: Proposed placement for the buffer. Changed only by the
- * creator prior to validation as opposed to bo->mem.proposed_flags which is
- * changed by the implementation prior to a buffer move if it wants to outsmart
- * the buffer creator / user. This latter happens, for example, at eviction.
  * @mem: structure describing current placement.
  * @persistant_swap_storage: Usually the swap storage is deleted for buffers
  * pinned in physical memory. If this behaviour is not desired, this member
@@ -177,7 +196,6 @@
 	 * Members protected by the bo::reserved lock.
 	 */
 
-	uint32_t proposed_placement;
 	struct ttm_mem_reg mem;
 	struct file *persistant_swap_storage;
 	struct ttm_tt *ttm;
@@ -206,9 +224,11 @@
 
 	atomic_t reserved;
 
-
 	/**
 	 * Members protected by the bo::lock
+	 * In addition, setting sync_obj to anything else
+	 * than NULL requires bo::reserved to be held. This allows for
+	 * checking NULL while reserved but not holding bo::lock.
 	 */
 
 	void *sync_obj_arg;
@@ -285,29 +305,30 @@
  * Note: It might be necessary to block validations before the
  * wait by reserving the buffer.
  * Returns -EBUSY if no_wait is true and the buffer is busy.
- * Returns -ERESTART if interrupted by a signal.
+ * Returns -ERESTARTSYS if interrupted by a signal.
  */
 extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy,
 		       bool interruptible, bool no_wait);
 /**
- * ttm_buffer_object_validate
+ * ttm_bo_validate
  *
  * @bo: The buffer object.
- * @proposed_placement: Proposed_placement for the buffer object.
+ * @placement: Proposed placement for the buffer object.
  * @interruptible: Sleep interruptible if sleeping.
  * @no_wait: Return immediately if the buffer is busy.
  *
  * Changes placement and caching policy of the buffer object
- * according to bo::proposed_flags.
+ * according proposed placement.
  * Returns
- * -EINVAL on invalid proposed_flags.
+ * -EINVAL on invalid proposed placement.
  * -ENOMEM on out-of-memory condition.
  * -EBUSY if no_wait is true and buffer busy.
- * -ERESTART if interrupted by a signal.
+ * -ERESTARTSYS if interrupted by a signal.
  */
-extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo,
-				      uint32_t proposed_placement,
-				      bool interruptible, bool no_wait);
+extern int ttm_bo_validate(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement,
+				bool interruptible, bool no_wait);
+
 /**
  * ttm_bo_unref
  *
@@ -328,7 +349,7 @@
  * waiting for buffer idle. This lock is recursive.
  * Returns
  * -EBUSY if the buffer is busy and no_wait is true.
- * -ERESTART if interrupted by a signal.
+ * -ERESTARTSYS if interrupted by a signal.
  */
 
 extern int
@@ -343,7 +364,7 @@
 extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo);
 
 /**
- * ttm_buffer_object_init
+ * ttm_bo_init
  *
  * @bdev: Pointer to a ttm_bo_device struct.
  * @bo: Pointer to a ttm_buffer_object to be initialized.
@@ -371,20 +392,20 @@
  * Returns
  * -ENOMEM: Out of memory.
  * -EINVAL: Invalid placement flags.
- * -ERESTART: Interrupted by signal while sleeping waiting for resources.
+ * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources.
  */
 
-extern int ttm_buffer_object_init(struct ttm_bo_device *bdev,
-				  struct ttm_buffer_object *bo,
-				  unsigned long size,
-				  enum ttm_bo_type type,
-				  uint32_t flags,
-				  uint32_t page_alignment,
-				  unsigned long buffer_start,
-				  bool interrubtible,
-				  struct file *persistant_swap_storage,
-				  size_t acc_size,
-				  void (*destroy) (struct ttm_buffer_object *));
+extern int ttm_bo_init(struct ttm_bo_device *bdev,
+			struct ttm_buffer_object *bo,
+			unsigned long size,
+			enum ttm_bo_type type,
+			struct ttm_placement *placement,
+			uint32_t page_alignment,
+			unsigned long buffer_start,
+			bool interrubtible,
+			struct file *persistant_swap_storage,
+			size_t acc_size,
+			void (*destroy) (struct ttm_buffer_object *));
 /**
  * ttm_bo_synccpu_object_init
  *
@@ -405,47 +426,43 @@
  * GEM user interface.
  * @p_bo: On successful completion *p_bo points to the created object.
  *
- * This function allocates a ttm_buffer_object, and then calls
- * ttm_buffer_object_init on that object.
- * The destroy function is set to kfree().
+ * This function allocates a ttm_buffer_object, and then calls ttm_bo_init
+ * on that object. The destroy function is set to kfree().
  * Returns
  * -ENOMEM: Out of memory.
  * -EINVAL: Invalid placement flags.
- * -ERESTART: Interrupted by signal while waiting for resources.
+ * -ERESTARTSYS: Interrupted by signal while waiting for resources.
  */
 
-extern int ttm_buffer_object_create(struct ttm_bo_device *bdev,
-				    unsigned long size,
-				    enum ttm_bo_type type,
-				    uint32_t flags,
-				    uint32_t page_alignment,
-				    unsigned long buffer_start,
-				    bool interruptible,
-				    struct file *persistant_swap_storage,
-				    struct ttm_buffer_object **p_bo);
+extern int ttm_bo_create(struct ttm_bo_device *bdev,
+				unsigned long size,
+				enum ttm_bo_type type,
+				struct ttm_placement *placement,
+				uint32_t page_alignment,
+				unsigned long buffer_start,
+				bool interruptible,
+				struct file *persistant_swap_storage,
+				struct ttm_buffer_object **p_bo);
 
 /**
  * ttm_bo_check_placement
  *
- * @bo: the buffer object.
- * @set_flags: placement flags to set.
- * @clr_flags: placement flags to clear.
+ * @bo:		the buffer object.
+ * @placement:	placements
  *
  * Performs minimal validity checking on an intended change of
  * placement flags.
  * Returns
  * -EINVAL: Intended change is invalid or not allowed.
  */
-
 extern int ttm_bo_check_placement(struct ttm_buffer_object *bo,
-				  uint32_t set_flags, uint32_t clr_flags);
+					struct ttm_placement *placement);
 
 /**
  * ttm_bo_init_mm
  *
  * @bdev: Pointer to a ttm_bo_device struct.
  * @mem_type: The memory type.
- * @p_offset: offset for managed area in pages.
  * @p_size: size managed area in pages.
  *
  * Initialize a manager for a given memory type.
@@ -458,7 +475,7 @@
  */
 
 extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
-			  unsigned long p_offset, unsigned long p_size);
+				unsigned long p_size);
 /**
  * ttm_bo_clean_mm
  *
@@ -503,7 +520,7 @@
  *
  * Returns:
  * -EINVAL: Invalid or uninitialized memory type.
- * -ERESTART: The call was interrupted by a signal while waiting to
+ * -ERESTARTSYS: The call was interrupted by a signal while waiting to
  * evict a buffer.
  */
 
@@ -606,7 +623,7 @@
  * be called from the fops::read and fops::write method.
  * Returns:
  * See man (2) write, man(2) read. In particular,
- * the function may return -EINTR if
+ * the function may return -ERESTARTSYS if
  * interrupted by a signal.
  */
 
--- linux-ec2-2.6.32.orig/include/drm/ttm/ttm_memory.h
+++ linux-ec2-2.6.32/include/drm/ttm/ttm_memory.h
@@ -33,6 +33,7 @@
 #include <linux/wait.h>
 #include <linux/errno.h>
 #include <linux/kobject.h>
+#include <linux/mm.h>
 
 /**
  * struct ttm_mem_shrink - callback to shrink TTM memory usage.
--- linux-ec2-2.6.32.orig/net/socket.c
+++ linux-ec2-2.6.32/net/socket.c
@@ -1673,6 +1673,8 @@
 	struct iovec iov;
 	int fput_needed;
 
+	if (len > INT_MAX)
+		len = INT_MAX;
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
@@ -1730,6 +1732,8 @@
 	int err, err2;
 	int fput_needed;
 
+	if (size > INT_MAX)
+		size = INT_MAX;
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
--- linux-ec2-2.6.32.orig/net/compat.c
+++ linux-ec2-2.6.32/net/compat.c
@@ -40,10 +40,12 @@
 		compat_size_t len;
 
 		if (get_user(len, &uiov32->iov_len) ||
-		   get_user(buf, &uiov32->iov_base)) {
-			tot_len = -EFAULT;
-			break;
-		}
+		    get_user(buf, &uiov32->iov_base))
+			return -EFAULT;
+
+		if (len > INT_MAX - tot_len)
+			len = INT_MAX - tot_len;
+
 		tot_len += len;
 		kiov->iov_base = compat_ptr(buf);
 		kiov->iov_len = (__kernel_size_t) len;
--- linux-ec2-2.6.32.orig/net/netlink/af_netlink.c
+++ linux-ec2-2.6.32/net/netlink/af_netlink.c
@@ -1363,7 +1363,7 @@
 	struct netlink_sock *nlk = nlk_sk(sk);
 	int noblock = flags&MSG_DONTWAIT;
 	size_t copied;
-	struct sk_buff *skb, *frag __maybe_unused = NULL;
+	struct sk_buff *skb, *data_skb;
 	int err;
 
 	if (flags&MSG_OOB)
@@ -1375,45 +1375,35 @@
 	if (skb == NULL)
 		goto out;
 
+	data_skb = skb;
+
 #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
 	if (unlikely(skb_shinfo(skb)->frag_list)) {
-		bool need_compat = !!(flags & MSG_CMSG_COMPAT);
-
 		/*
-		 * If this skb has a frag_list, then here that means that
-		 * we will have to use the frag_list skb for compat tasks
-		 * and the regular skb for non-compat tasks.
+		 * If this skb has a frag_list, then here that means that we
+		 * will have to use the frag_list skb's data for compat tasks
+		 * and the regular skb's data for normal (non-compat) tasks.
 		 *
-		 * The skb might (and likely will) be cloned, so we can't
-		 * just reset frag_list and go on with things -- we need to
-		 * keep that. For the compat case that's easy -- simply get
-		 * a reference to the compat skb and free the regular one
-		 * including the frag. For the non-compat case, we need to
-		 * avoid sending the frag to the user -- so assign NULL but
-		 * restore it below before freeing the skb.
+		 * If we need to send the compat skb, assign it to the
+		 * 'data_skb' variable so that it will be used below for data
+		 * copying. We keep 'skb' for everything else, including
+		 * freeing both later.
 		 */
-		if (need_compat) {
-			struct sk_buff *compskb = skb_shinfo(skb)->frag_list;
-			skb_get(compskb);
-			kfree_skb(skb);
-			skb = compskb;
-		} else {
-			frag = skb_shinfo(skb)->frag_list;
-			skb_shinfo(skb)->frag_list = NULL;
-		}
+		if (flags & MSG_CMSG_COMPAT)
+			data_skb = skb_shinfo(skb)->frag_list;
 	}
 #endif
 
 	msg->msg_namelen = 0;
 
-	copied = skb->len;
+	copied = data_skb->len;
 	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
 
-	skb_reset_transport_header(skb);
-	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	skb_reset_transport_header(data_skb);
+	err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied);
 
 	if (msg->msg_name) {
 		struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name;
@@ -1433,11 +1423,7 @@
 	}
 	siocb->scm->creds = *NETLINK_CREDS(skb);
 	if (flags & MSG_TRUNC)
-		copied = skb->len;
-
-#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
-	skb_shinfo(skb)->frag_list = frag;
-#endif
+		copied = data_skb->len;
 
 	skb_free_datagram(sk, skb);
 
--- linux-ec2-2.6.32.orig/net/9p/trans_fd.c
+++ linux-ec2-2.6.32/net/9p/trans_fd.c
@@ -948,7 +948,7 @@
 
 	csocket = NULL;
 
-	if (strlen(addr) > UNIX_PATH_MAX) {
+	if (strlen(addr) >= UNIX_PATH_MAX) {
 		P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
 			addr);
 		err = -ENAMETOOLONG;
--- linux-ec2-2.6.32.orig/net/sched/act_gact.c
+++ linux-ec2-2.6.32/net/sched/act_gact.c
@@ -152,21 +152,24 @@
 static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
 	unsigned char *b = skb_tail_pointer(skb);
-	struct tc_gact opt;
 	struct tcf_gact *gact = a->priv;
+	struct tc_gact opt = {
+		.index   = gact->tcf_index,
+		.refcnt  = gact->tcf_refcnt - ref,
+		.bindcnt = gact->tcf_bindcnt - bind,
+		.action  = gact->tcf_action,
+	};
 	struct tcf_t t;
 
-	opt.index = gact->tcf_index;
-	opt.refcnt = gact->tcf_refcnt - ref;
-	opt.bindcnt = gact->tcf_bindcnt - bind;
-	opt.action = gact->tcf_action;
 	NLA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
 #ifdef CONFIG_GACT_PROB
 	if (gact->tcfg_ptype) {
-		struct tc_gact_p p_opt;
-		p_opt.paction = gact->tcfg_paction;
-		p_opt.pval = gact->tcfg_pval;
-		p_opt.ptype = gact->tcfg_ptype;
+		struct tc_gact_p p_opt = {
+			.paction = gact->tcfg_paction,
+			.pval    = gact->tcfg_pval,
+			.ptype   = gact->tcfg_ptype,
+		};
+
 		NLA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
 	}
 #endif
--- linux-ec2-2.6.32.orig/net/sched/cls_cgroup.c
+++ linux-ec2-2.6.32/net/sched/cls_cgroup.c
@@ -110,7 +110,7 @@
 	 * calls by looking at the number of nested bh disable calls because
 	 * softirqs always disables bh.
 	 */
-	if (softirq_count() != SOFTIRQ_OFFSET)
+	if (in_serving_softirq())
 		return -1;
 
 	rcu_read_lock();
--- linux-ec2-2.6.32.orig/net/sched/sch_generic.c
+++ linux-ec2-2.6.32/net/sched/sch_generic.c
@@ -330,6 +330,24 @@
 }
 EXPORT_SYMBOL(netif_carrier_off);
 
+/**
+ * 	netif_notify_peers - notify network peers about existence of @dev
+ * 	@dev: network device
+ *
+ * Generate traffic such that interested network peers are aware of
+ * @dev, such as by generating a gratuitous ARP. This may be used when
+ * a device wants to inform the rest of the network about some sort of
+ * reconfiguration such as a failover event or virtual machine
+ * migration.
+ */
+void netif_notify_peers(struct net_device *dev)
+{
+	rtnl_lock();
+	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
+	rtnl_unlock();
+}
+EXPORT_SYMBOL(netif_notify_peers);
+
 /* "NOOP" scheduler: the best scheduler, recommended for all interfaces
    under all circumstances. It is difficult to invent anything faster or
    cheaper.
--- linux-ec2-2.6.32.orig/net/sched/act_nat.c
+++ linux-ec2-2.6.32/net/sched/act_nat.c
@@ -240,7 +240,7 @@
 			iph->saddr = new_addr;
 
 		inet_proto_csum_replace4(&icmph->checksum, skb, addr, new_addr,
-					 1);
+					 0);
 		break;
 	}
 	default:
@@ -261,40 +261,29 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_nat *p = a->priv;
-	struct tc_nat *opt;
+	struct tc_nat opt = {
+		.old_addr = p->old_addr,
+		.new_addr = p->new_addr,
+		.mask     = p->mask,
+		.flags    = p->flags,
+
+		.index    = p->tcf_index,
+		.action   = p->tcf_action,
+		.refcnt   = p->tcf_refcnt - ref,
+		.bindcnt  = p->tcf_bindcnt - bind,
+	};
 	struct tcf_t t;
-	int s;
 
-	s = sizeof(*opt);
-
-	/* netlink spinlocks held above us - must use ATOMIC */
-	opt = kzalloc(s, GFP_ATOMIC);
-	if (unlikely(!opt))
-		return -ENOBUFS;
-
-	opt->old_addr = p->old_addr;
-	opt->new_addr = p->new_addr;
-	opt->mask = p->mask;
-	opt->flags = p->flags;
-
-	opt->index = p->tcf_index;
-	opt->action = p->tcf_action;
-	opt->refcnt = p->tcf_refcnt - ref;
-	opt->bindcnt = p->tcf_bindcnt - bind;
-
-	NLA_PUT(skb, TCA_NAT_PARMS, s, opt);
+	NLA_PUT(skb, TCA_NAT_PARMS, sizeof(opt), &opt);
 	t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
 	t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
 	t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
 	NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t);
 
-	kfree(opt);
-
 	return skb->len;
 
 nla_put_failure:
 	nlmsg_trim(skb, b);
-	kfree(opt);
 	return -1;
 }
 
--- linux-ec2-2.6.32.orig/net/sched/act_skbedit.c
+++ linux-ec2-2.6.32/net/sched/act_skbedit.c
@@ -147,13 +147,14 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_skbedit *d = a->priv;
-	struct tc_skbedit opt;
+	struct tc_skbedit opt = {
+		.index   = d->tcf_index,
+		.refcnt  = d->tcf_refcnt - ref,
+		.bindcnt = d->tcf_bindcnt - bind,
+		.action  = d->tcf_action,
+	};
 	struct tcf_t t;
 
-	opt.index = d->tcf_index;
-	opt.refcnt = d->tcf_refcnt - ref;
-	opt.bindcnt = d->tcf_bindcnt - bind;
-	opt.action = d->tcf_action;
 	NLA_PUT(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt);
 	if (d->flags & SKBEDIT_F_PRIORITY)
 		NLA_PUT(skb, TCA_SKBEDIT_PRIORITY, sizeof(d->priority),
--- linux-ec2-2.6.32.orig/net/sched/act_mirred.c
+++ linux-ec2-2.6.32/net/sched/act_mirred.c
@@ -205,15 +205,16 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_mirred *m = a->priv;
-	struct tc_mirred opt;
+	struct tc_mirred opt = {
+		.index   = m->tcf_index,
+		.action  = m->tcf_action,
+		.refcnt  = m->tcf_refcnt - ref,
+		.bindcnt = m->tcf_bindcnt - bind,
+		.eaction = m->tcfm_eaction,
+		.ifindex = m->tcfm_ifindex,
+	};
 	struct tcf_t t;
 
-	opt.index = m->tcf_index;
-	opt.action = m->tcf_action;
-	opt.refcnt = m->tcf_refcnt - ref;
-	opt.bindcnt = m->tcf_bindcnt - bind;
-	opt.eaction = m->tcfm_eaction;
-	opt.ifindex = m->tcfm_ifindex;
 	NLA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt);
 	t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install);
 	t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse);
--- linux-ec2-2.6.32.orig/net/sched/act_police.c
+++ linux-ec2-2.6.32/net/sched/act_police.c
@@ -340,22 +340,19 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_police *police = a->priv;
-	struct tc_police opt;
+	struct tc_police opt = {
+		.index = police->tcf_index,
+		.action = police->tcf_action,
+		.mtu = police->tcfp_mtu,
+		.burst = police->tcfp_burst,
+		.refcnt = police->tcf_refcnt - ref,
+		.bindcnt = police->tcf_bindcnt - bind,
+	};
 
-	opt.index = police->tcf_index;
-	opt.action = police->tcf_action;
-	opt.mtu = police->tcfp_mtu;
-	opt.burst = police->tcfp_burst;
-	opt.refcnt = police->tcf_refcnt - ref;
-	opt.bindcnt = police->tcf_bindcnt - bind;
 	if (police->tcfp_R_tab)
 		opt.rate = police->tcfp_R_tab->rate;
-	else
-		memset(&opt.rate, 0, sizeof(opt.rate));
 	if (police->tcfp_P_tab)
 		opt.peakrate = police->tcfp_P_tab->rate;
-	else
-		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
 	NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
 	if (police->tcfp_result)
 		NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
--- linux-ec2-2.6.32.orig/net/sched/act_simple.c
+++ linux-ec2-2.6.32/net/sched/act_simple.c
@@ -163,13 +163,14 @@
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_defact *d = a->priv;
-	struct tc_defact opt;
+	struct tc_defact opt = {
+		.index   = d->tcf_index,
+		.refcnt  = d->tcf_refcnt - ref,
+		.bindcnt = d->tcf_bindcnt - bind,
+		.action  = d->tcf_action,
+	};
 	struct tcf_t t;
 
-	opt.index = d->tcf_index;
-	opt.refcnt = d->tcf_refcnt - ref;
-	opt.bindcnt = d->tcf_bindcnt - bind;
-	opt.action = d->tcf_action;
 	NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
 	NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata);
 	t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
--- linux-ec2-2.6.32.orig/net/ipv6/reassembly.c
+++ linux-ec2-2.6.32/net/ipv6/reassembly.c
@@ -72,6 +72,7 @@
 	struct inet_frag_queue	q;
 
 	__be32			id;		/* fragment id		*/
+	u32			user;
 	struct in6_addr		saddr;
 	struct in6_addr		daddr;
 
@@ -141,7 +142,7 @@
 	struct ip6_create_arg *arg = a;
 
 	fq = container_of(q, struct frag_queue, q);
-	return (fq->id == arg->id &&
+	return (fq->id == arg->id && fq->user == arg->user &&
 			ipv6_addr_equal(&fq->saddr, arg->src) &&
 			ipv6_addr_equal(&fq->daddr, arg->dst));
 }
@@ -163,6 +164,7 @@
 	struct ip6_create_arg *arg = a;
 
 	fq->id = arg->id;
+	fq->user = arg->user;
 	ipv6_addr_copy(&fq->saddr, arg->src);
 	ipv6_addr_copy(&fq->daddr, arg->dst);
 }
@@ -244,6 +246,7 @@
 	unsigned int hash;
 
 	arg.id = id;
+	arg.user = IP6_DEFRAG_LOCAL_DELIVER;
 	arg.src = src;
 	arg.dst = dst;
 
--- linux-ec2-2.6.32.orig/net/ipv6/sit.c
+++ linux-ec2-2.6.32/net/ipv6/sit.c
@@ -1101,4 +1101,4 @@
 module_init(sit_init);
 module_exit(sit_cleanup);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("sit0");
+MODULE_ALIAS_NETDEV("sit0");
--- linux-ec2-2.6.32.orig/net/ipv6/ip6_tunnel.c
+++ linux-ec2-2.6.32/net/ipv6/ip6_tunnel.c
@@ -56,6 +56,7 @@
 MODULE_AUTHOR("Ville Nuorvala");
 MODULE_DESCRIPTION("IPv6 tunneling device");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETDEV("ip6tnl0");
 
 #define IPV6_TLV_TEL_DST_SIZE 8
 
--- linux-ec2-2.6.32.orig/net/ipv6/route.c
+++ linux-ec2-2.6.32/net/ipv6/route.c
@@ -1561,14 +1561,13 @@
  *	i.e. Path MTU discovery
  */
 
-void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
-			struct net_device *dev, u32 pmtu)
+static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
+			     struct net *net, u32 pmtu, int ifindex)
 {
 	struct rt6_info *rt, *nrt;
-	struct net *net = dev_net(dev);
 	int allfrag = 0;
 
-	rt = rt6_lookup(net, daddr, saddr, dev->ifindex, 0);
+	rt = rt6_lookup(net, daddr, saddr, ifindex, 0);
 	if (rt == NULL)
 		return;
 
@@ -1636,6 +1635,27 @@
 	dst_release(&rt->u.dst);
 }
 
+void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
+			struct net_device *dev, u32 pmtu)
+{
+	struct net *net = dev_net(dev);
+
+	/*
+	 * RFC 1981 states that a node "MUST reduce the size of the packets it
+	 * is sending along the path" that caused the Packet Too Big message.
+	 * Since it's not possible in the general case to determine which
+	 * interface was used to send the original packet, we update the MTU
+	 * on the interface that will be used to send future packets. We also
+	 * update the MTU on the interface that received the Packet Too Big in
+	 * case the original packet was forced out that interface with
+	 * SO_BINDTODEVICE or similar. This is the next best thing to the
+	 * correct behaviour, which would be to update the MTU on all
+	 * interfaces.
+	 */
+	rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0);
+	rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex);
+}
+
 /*
  *	Misc support functions
  */
--- linux-ec2-2.6.32.orig/net/ipv6/exthdrs.c
+++ linux-ec2-2.6.32/net/ipv6/exthdrs.c
@@ -559,6 +559,11 @@
 	return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev);
 }
 
+static inline struct net *ipv6_skb_net(struct sk_buff *skb)
+{
+	return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev);
+}
+
 /* Router Alert as of RFC 2711 */
 
 static int ipv6_hop_ra(struct sk_buff *skb, int optoff)
@@ -580,8 +585,8 @@
 static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
 {
 	const unsigned char *nh = skb_network_header(skb);
+	struct net *net = ipv6_skb_net(skb);
 	u32 pkt_len;
-	struct net *net = dev_net(skb_dst(skb)->dev);
 
 	if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
 		LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
--- linux-ec2-2.6.32.orig/net/ipv6/ip6_output.c
+++ linux-ec2-2.6.32/net/ipv6/ip6_output.c
@@ -643,7 +643,7 @@
 
 	if (skb_has_frags(skb)) {
 		int first_len = skb_pagelen(skb);
-		int truesizes = 0;
+		struct sk_buff *frag2;
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
@@ -655,18 +655,18 @@
 			if (frag->len > mtu ||
 			    ((frag->len & 7) && frag->next) ||
 			    skb_headroom(frag) < hlen)
-			    goto slow_path;
+				goto slow_path_clean;
 
 			/* Partially cloned skb? */
 			if (skb_shared(frag))
-				goto slow_path;
+				goto slow_path_clean;
 
 			BUG_ON(frag->sk);
 			if (skb->sk) {
 				frag->sk = skb->sk;
 				frag->destructor = sock_wfree;
-				truesizes += frag->truesize;
 			}
+			skb->truesize -= frag->truesize;
 		}
 
 		err = 0;
@@ -697,7 +697,6 @@
 
 		first_len = skb_pagelen(skb);
 		skb->data_len = first_len - skb_headlen(skb);
-		skb->truesize -= truesizes;
 		skb->len = first_len;
 		ipv6_hdr(skb)->payload_len = htons(first_len -
 						   sizeof(struct ipv6hdr));
@@ -760,6 +759,15 @@
 			      IPSTATS_MIB_FRAGFAILS);
 		dst_release(&rt->u.dst);
 		return err;
+
+slow_path_clean:
+		skb_walk_frags(skb, frag2) {
+			if (frag2 == frag)
+				break;
+			frag2->sk = NULL;
+			frag2->destructor = NULL;
+			skb->truesize += frag2->truesize;
+		}
 	}
 
 slow_path:
--- linux-ec2-2.6.32.orig/net/ipv6/addrconf.c
+++ linux-ec2-2.6.32/net/ipv6/addrconf.c
@@ -407,9 +407,6 @@
 	    dev->type == ARPHRD_TUNNEL6 ||
 	    dev->type == ARPHRD_SIT ||
 	    dev->type == ARPHRD_NONE) {
-		printk(KERN_INFO
-		       "%s: Disabled Privacy Extensions\n",
-		       dev->name);
 		ndev->cnf.use_tempaddr = -1;
 	} else {
 		in6_dev_hold(ndev);
@@ -504,8 +501,11 @@
 	if (p == &net->ipv6.devconf_dflt->forwarding)
 		return 0;
 
-	if (!rtnl_trylock())
+	if (!rtnl_trylock()) {
+		/* Restore the original values before restarting */
+		*p = old;
 		return restart_syscall();
+	}
 
 	if (p == &net->ipv6.devconf_all->forwarding) {
 		__s32 newf = net->ipv6.devconf_all->forwarding;
@@ -2796,6 +2796,7 @@
 	spin_lock_bh(&ifp->lock);
 
 	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
+	    !(dev->flags&IFF_MULTICAST) ||
 	    idev->cnf.accept_dad < 1 ||
 	    !(ifp->flags&IFA_F_TENTATIVE) ||
 	    ifp->flags & IFA_F_NODAD) {
@@ -2888,6 +2889,7 @@
 	if (ifp->idev->cnf.forwarding == 0 &&
 	    ifp->idev->cnf.rtr_solicits > 0 &&
 	    (dev->flags&IFF_LOOPBACK) == 0 &&
+	    (dev->flags & IFF_MULTICAST) &&
 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
 		/*
 		 *	If a host as already performed a random delay
@@ -3991,12 +3993,15 @@
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret;
 
 	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_fixup_forwarding(ctl, valp, val);
+	if (ret)
+		*ppos = pos;
 	return ret;
 }
 
@@ -4075,8 +4080,11 @@
 	if (p == &net->ipv6.devconf_dflt->disable_ipv6)
 		return 0;
 
-	if (!rtnl_trylock())
+	if (!rtnl_trylock()) {
+		/* Restore the original values before restarting */
+		*p = old;
 		return restart_syscall();
+	}
 
 	if (p == &net->ipv6.devconf_all->disable_ipv6) {
 		__s32 newf = net->ipv6.devconf_all->disable_ipv6;
@@ -4095,12 +4103,15 @@
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret;
 
 	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_disable_ipv6(ctl, valp, val);
+	if (ret)
+		*ppos = pos;
 	return ret;
 }
 
--- linux-ec2-2.6.32.orig/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ linux-ec2-2.6.32/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -63,6 +63,7 @@
 	struct inet_frag_queue	q;
 
 	__be32			id;		/* fragment id		*/
+	u32			user;
 	struct in6_addr		saddr;
 	struct in6_addr		daddr;
 
@@ -170,13 +171,14 @@
 /* Creation primitives. */
 
 static __inline__ struct nf_ct_frag6_queue *
-fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
+fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst)
 {
 	struct inet_frag_queue *q;
 	struct ip6_create_arg arg;
 	unsigned int hash;
 
 	arg.id = id;
+	arg.user = user;
 	arg.src = src;
 	arg.dst = dst;
 
@@ -561,7 +563,7 @@
 	return 0;
 }
 
-struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
+struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
 {
 	struct sk_buff *clone;
 	struct net_device *dev = skb->dev;
@@ -607,7 +609,7 @@
 	if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh)
 		nf_ct_frag6_evictor();
 
-	fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
+	fq = fq_find(fhdr->identification, user, &hdr->saddr, &hdr->daddr);
 	if (fq == NULL) {
 		pr_debug("Can't find and can't create new queue\n");
 		goto ret_orig;
--- linux-ec2-2.6.32.orig/net/ipv6/netfilter/ip6t_REJECT.c
+++ linux-ec2-2.6.32/net/ipv6/netfilter/ip6t_REJECT.c
@@ -95,9 +95,11 @@
 	fl.fl_ip_dport = otcph.source;
 	security_skb_classify_flow(oldskb, &fl);
 	dst = ip6_route_output(net, NULL, &fl);
-	if (dst == NULL)
+	if (dst == NULL || dst->error) {
+		dst_release(dst);
 		return;
-	if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0))
+	}
+	if (xfrm_lookup(net, &dst, &fl, NULL, 0))
 		return;
 
 	hh_len = (dst->dev->hard_header_len + 15)&~15;
--- linux-ec2-2.6.32.orig/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ linux-ec2-2.6.32/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -20,6 +20,7 @@
 #include <net/ipv6.h>
 #include <net/inet_frag.h>
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
@@ -187,6 +188,21 @@
 	return nf_conntrack_confirm(skb);
 }
 
+static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
+						struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP6_DEFRAG_CONNTRACK_IN;
+	else
+		return IP6_DEFRAG_CONNTRACK_OUT;
+
+}
+
 static unsigned int ipv6_defrag(unsigned int hooknum,
 				struct sk_buff *skb,
 				const struct net_device *in,
@@ -199,8 +215,7 @@
 	if (skb->nfct)
 		return NF_ACCEPT;
 
-	reasm = nf_ct_frag6_gather(skb);
-
+	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
 	/* queued */
 	if (reasm == NULL)
 		return NF_STOLEN;
--- linux-ec2-2.6.32.orig/net/ipv6/netfilter/ip6_tables.c
+++ linux-ec2-2.6.32/net/ipv6/netfilter/ip6_tables.c
@@ -1164,10 +1164,10 @@
 	if (t && !IS_ERR(t)) {
 		struct ip6t_getinfo info;
 		const struct xt_table_info *private = t->private;
-
 #ifdef CONFIG_COMPAT
+		struct xt_table_info tmp;
+
 		if (compat) {
-			struct xt_table_info tmp;
 			ret = compat_table_info(private, &tmp);
 			xt_compat_flush_offsets(AF_INET6);
 			private = &tmp;
@@ -1323,6 +1323,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1855,6 +1856,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2079,6 +2081,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IP6T_SO_GET_REVISION_TARGET)
 			target = 1;
--- linux-ec2-2.6.32.orig/net/can/bcm.c
+++ linux-ec2-2.6.32/net/can/bcm.c
@@ -59,6 +59,13 @@
 #include <net/sock.h>
 #include <net/net_namespace.h>
 
+/*
+ * To send multiple CAN frame content within TX_SETUP or to filter
+ * CAN messages with multiplex index within RX_SETUP, the number of
+ * different filters is limited to 256 due to the one byte index value.
+ */
+#define MAX_NFRAMES 256
+
 /* use of last_frames[index].can_dlc */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -88,16 +95,16 @@
 	struct list_head list;
 	int ifindex;
 	canid_t can_id;
-	int flags;
+	u32 flags;
 	unsigned long frames_abs, frames_filtered;
 	struct timeval ival1, ival2;
 	struct hrtimer timer, thrtimer;
 	struct tasklet_struct tsklet, thrtsklet;
 	ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
 	int rx_ifindex;
-	int count;
-	int nframes;
-	int currframe;
+	u32 count;
+	u32 nframes;
+	u32 currframe;
 	struct can_frame *frames;
 	struct can_frame *last_frames;
 	struct can_frame sframe;
@@ -117,7 +124,7 @@
 	struct list_head tx_ops;
 	unsigned long dropped_usr_msgs;
 	struct proc_dir_entry *bcm_proc_read;
-	char procname [9]; /* pointer printed in ASCII with \0 */
+	char procname [32]; /* inode number in decimal with \0 */
 };
 
 static inline struct bcm_sock *bcm_sk(const struct sock *sk)
@@ -174,7 +181,7 @@
 
 		seq_printf(m, "rx_op: %03X %-5s ",
 				op->can_id, bcm_proc_getifname(ifname, op->ifindex));
-		seq_printf(m, "[%d]%c ", op->nframes,
+		seq_printf(m, "[%u]%c ", op->nframes,
 				(op->flags & RX_CHECK_DLC)?'d':' ');
 		if (op->kt_ival1.tv64)
 			seq_printf(m, "timeo=%lld ",
@@ -197,7 +204,7 @@
 
 	list_for_each_entry(op, &bo->tx_ops, list) {
 
-		seq_printf(m, "tx_op: %03X %s [%d] ",
+		seq_printf(m, "tx_op: %03X %s [%u] ",
 				op->can_id,
 				bcm_proc_getifname(ifname, op->ifindex),
 				op->nframes);
@@ -282,7 +289,7 @@
 	struct can_frame *firstframe;
 	struct sockaddr_can *addr;
 	struct sock *sk = op->sk;
-	int datalen = head->nframes * CFSIZ;
+	unsigned int datalen = head->nframes * CFSIZ;
 	int err;
 
 	skb = alloc_skb(sizeof(*head) + datalen, gfp_any());
@@ -467,7 +474,7 @@
  * bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly
  *                       received data stored in op->last_frames[]
  */
-static void bcm_rx_cmp_to_index(struct bcm_op *op, int index,
+static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index,
 				const struct can_frame *rxdata)
 {
 	/*
@@ -553,7 +560,8 @@
 /*
  * bcm_rx_do_flush - helper for bcm_rx_thr_flush
  */
-static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index)
+static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
+				  unsigned int index)
 {
 	if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) {
 		if (update)
@@ -574,7 +582,7 @@
 	int updated = 0;
 
 	if (op->nframes > 1) {
-		int i;
+		unsigned int i;
 
 		/* for MUX filter we start at index 1 */
 		for (i = 1; i < op->nframes; i++)
@@ -623,7 +631,7 @@
 {
 	struct bcm_op *op = (struct bcm_op *)data;
 	const struct can_frame *rxframe = (struct can_frame *)skb->data;
-	int i;
+	unsigned int i;
 
 	/* disable timeout */
 	hrtimer_cancel(&op->timer);
@@ -823,14 +831,15 @@
 {
 	struct bcm_sock *bo = bcm_sk(sk);
 	struct bcm_op *op;
-	int i, err;
+	unsigned int i;
+	int err;
 
 	/* we need a real device to send frames */
 	if (!ifindex)
 		return -ENODEV;
 
-	/* we need at least one can_frame */
-	if (msg_head->nframes < 1)
+	/* check nframes boundaries - we need at least one can_frame */
+	if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
 		return -EINVAL;
 
 	/* check the given can_id */
@@ -994,6 +1003,10 @@
 		msg_head->nframes = 0;
 	}
 
+	/* the first element contains the mux-mask => MAX_NFRAMES + 1  */
+	if (msg_head->nframes > MAX_NFRAMES + 1)
+		return -EINVAL;
+
 	if ((msg_head->flags & RX_RTR_FRAME) &&
 	    ((msg_head->nframes != 1) ||
 	     (!(msg_head->can_id & CAN_RTR_FLAG))))
@@ -1412,9 +1425,14 @@
 static int bcm_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct bcm_sock *bo = bcm_sk(sk);
+	struct bcm_sock *bo;
 	struct bcm_op *op, *next;
 
+	if (sk == NULL)
+		return 0;
+
+	bo = bcm_sk(sk);
+
 	/* remove bcm_ops, timer, rx_unregister(), etc. */
 
 	unregister_netdevice_notifier(&bo->notifier);
@@ -1506,7 +1524,7 @@
 
 	if (proc_dir) {
 		/* unique socket address as filename */
-		sprintf(bo->procname, "%p", sock);
+		sprintf(bo->procname, "%lu", sock_i_ino(sk));
 		bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
 						     proc_dir,
 						     &bcm_proc_fops, sk);
--- linux-ec2-2.6.32.orig/net/can/raw.c
+++ linux-ec2-2.6.32/net/can/raw.c
@@ -280,7 +280,12 @@
 static int raw_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct raw_sock *ro = raw_sk(sk);
+	struct raw_sock *ro;
+
+	if (!sk)
+		return 0;
+
+	ro = raw_sk(sk);
 
 	unregister_netdevice_notifier(&ro->notifier);
 
--- linux-ec2-2.6.32.orig/net/dccp/probe.c
+++ linux-ec2-2.6.32/net/dccp/probe.c
@@ -164,7 +164,8 @@
 	if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops))
 		goto err0;
 
-	ret = register_jprobe(&dccp_send_probe);
+	ret = try_then_request_module((register_jprobe(&dccp_send_probe) == 0),
+					"dccp");
 	if (ret)
 		goto err1;
 
--- linux-ec2-2.6.32.orig/net/dccp/input.c
+++ linux-ec2-2.6.32/net/dccp/input.c
@@ -616,6 +616,9 @@
 		/* Caller (dccp_v4_do_rcv) will send Reset */
 		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
 		return 1;
+	} else if (sk->sk_state == DCCP_CLOSED) {
+		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
+		return 1;
 	}
 
 	if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) {
@@ -678,10 +681,6 @@
 	}
 
 	switch (sk->sk_state) {
-	case DCCP_CLOSED:
-		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
-		return 1;
-
 	case DCCP_REQUESTING:
 		queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
 		if (queued >= 0)
--- linux-ec2-2.6.32.orig/net/dccp/options.c
+++ linux-ec2-2.6.32/net/dccp/options.c
@@ -131,6 +131,8 @@
 		case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
 			if (pkt_type == DCCP_PKT_DATA)      /* RFC 4340, 6 */
 				break;
+			if (len == 0)
+				goto out_invalid_option;
 			rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
 						    *value, value + 1, len - 1);
 			if (rc)
--- linux-ec2-2.6.32.orig/net/phonet/af_phonet.c
+++ linux-ec2-2.6.32/net/phonet/af_phonet.c
@@ -67,6 +67,8 @@
 	struct phonet_protocol *pnp;
 	int err;
 
+	if (!net_eq(net, &init_net))
+		return -EAFNOSUPPORT;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
@@ -353,6 +355,8 @@
 	struct sockaddr_pn sa;
 	u16 len;
 
+	if (!net_eq(net, &init_net))
+		goto out;
 	/* check we have at least a full Phonet header */
 	if (!pskb_pull(skb, sizeof(struct phonethdr)))
 		goto out;
--- linux-ec2-2.6.32.orig/net/phonet/pep.c
+++ linux-ec2-2.6.32/net/phonet/pep.c
@@ -224,12 +224,13 @@
 static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
 {
 	struct pep_sock *pn = pep_sk(sk);
-	struct pnpipehdr *hdr = pnp_hdr(skb);
+	struct pnpipehdr *hdr;
 	int wake = 0;
 
 	if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
 		return -EINVAL;
 
+	hdr = pnp_hdr(skb);
 	if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
 		LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n",
 				(unsigned)hdr->data[0]);
--- linux-ec2-2.6.32.orig/net/phonet/pn_netlink.c
+++ linux-ec2-2.6.32/net/phonet/pn_netlink.c
@@ -68,6 +68,8 @@
 	int err;
 	u8 pnaddr;
 
+	if (!net_eq(net, &init_net))
+		return -EOPNOTSUPP;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
@@ -124,12 +126,16 @@
 
 static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
+	struct net *net = sock_net(skb->sk);
 	struct phonet_device_list *pndevs;
 	struct phonet_device *pnd;
 	int dev_idx = 0, dev_start_idx = cb->args[0];
 	int addr_idx = 0, addr_start_idx = cb->args[1];
 
-	pndevs = phonet_device_list(sock_net(skb->sk));
+	if (!net_eq(net, &init_net))
+		goto skip;
+
+	pndevs = phonet_device_list(net);
 	spin_lock_bh(&pndevs->lock);
 	list_for_each_entry(pnd, &pndevs->list, list) {
 		u8 addr;
@@ -154,6 +160,7 @@
 
 out:
 	spin_unlock_bh(&pndevs->lock);
+skip:
 	cb->args[0] = dev_idx;
 	cb->args[1] = addr_idx;
 
--- linux-ec2-2.6.32.orig/net/phonet/pn_dev.c
+++ linux-ec2-2.6.32/net/phonet/pn_dev.c
@@ -225,6 +225,9 @@
 {
 	struct net_device *dev = arg;
 
+	if (!net_eq(dev_net(dev), &init_net))
+		return 0;
+
 	switch (what) {
 	case NETDEV_REGISTER:
 		if (dev->type == ARPHRD_PHONET)
@@ -246,7 +249,11 @@
 /* Per-namespace Phonet devices handling */
 static int phonet_init_net(struct net *net)
 {
-	struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
+	struct phonet_net *pnn;
+
+	if (!net_eq(net, &init_net))
+		return 0;
+	pnn = kmalloc(sizeof(*pnn), GFP_KERNEL);
 	if (!pnn)
 		return -ENOMEM;
 
@@ -263,9 +270,13 @@
 
 static void phonet_exit_net(struct net *net)
 {
-	struct phonet_net *pnn = net_generic(net, phonet_net_id);
+	struct phonet_net *pnn;
 	struct net_device *dev;
 
+	if (!net_eq(net, &init_net))
+		return;
+	pnn = net_generic(net, phonet_net_id);
+
 	rtnl_lock();
 	for_each_netdev(net, dev)
 		phonet_device_destroy(dev);
--- linux-ec2-2.6.32.orig/net/bluetooth/l2cap.c
+++ linux-ec2-2.6.32/net/bluetooth/l2cap.c
@@ -2813,6 +2813,11 @@
 			int len = cmd->len - sizeof(*rsp);
 			char req[64];
 
+			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
+				l2cap_send_disconn_req(conn, sk);
+				goto done;
+			}
+
 			/* throw out any old stored conf requests */
 			result = L2CAP_CONF_SUCCESS;
 			len = l2cap_parse_conf_rsp(sk, rsp->data,
@@ -3885,16 +3890,24 @@
 	struct sock *sk;
 	struct hlist_node *node;
 	char *str = buf;
+	int size = PAGE_SIZE;
 
 	read_lock_bh(&l2cap_sk_list.lock);
 
 	sk_for_each(sk, node, &l2cap_sk_list.head) {
 		struct l2cap_pinfo *pi = l2cap_pi(sk);
+		int len;
 
-		str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
+		len = snprintf(str, size, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 				sk->sk_state, __le16_to_cpu(pi->psm), pi->scid,
 				pi->dcid, pi->imtu, pi->omtu, pi->sec_level);
+
+		size -= len;
+		if (size <= 0)
+			break;
+
+		str += len;
 	}
 
 	read_unlock_bh(&l2cap_sk_list.lock);
--- linux-ec2-2.6.32.orig/net/bluetooth/sco.c
+++ linux-ec2-2.6.32/net/bluetooth/sco.c
@@ -700,6 +700,7 @@
 			break;
 		}
 
+		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
 		memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
@@ -957,13 +958,22 @@
 	struct sock *sk;
 	struct hlist_node *node;
 	char *str = buf;
+	int size = PAGE_SIZE;
 
 	read_lock_bh(&sco_sk_list.lock);
 
 	sk_for_each(sk, node, &sco_sk_list.head) {
-		str += sprintf(str, "%s %s %d\n",
+		int len;
+
+		len = snprintf(str, size, "%s %s %d\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 				sk->sk_state);
+
+		size -= len;
+		if (size <= 0)
+			break;
+
+		str += len;
 	}
 
 	read_unlock_bh(&sco_sk_list.lock);
--- linux-ec2-2.6.32.orig/net/bluetooth/rfcomm/core.c
+++ linux-ec2-2.6.32/net/bluetooth/rfcomm/core.c
@@ -251,7 +251,6 @@
 	BT_DBG("session %p state %ld", s, s->state);
 
 	set_bit(RFCOMM_TIMED_OUT, &s->flags);
-	rfcomm_session_put(s);
 	rfcomm_schedule(RFCOMM_SCHED_TIMEO);
 }
 
@@ -1917,6 +1916,7 @@
 		if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
 			s->state = BT_DISCONN;
 			rfcomm_send_disc(s, 0);
+			rfcomm_session_put(s);
 			continue;
 		}
 
@@ -2096,6 +2096,7 @@
 	struct rfcomm_session *s;
 	struct list_head *pp, *p;
 	char *str = buf;
+	int size = PAGE_SIZE;
 
 	rfcomm_lock();
 
@@ -2104,11 +2105,21 @@
 		list_for_each(pp, &s->dlcs) {
 			struct sock *sk = s->sock->sk;
 			struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
+			int len;
 
-			str += sprintf(str, "%s %s %ld %d %d %d %d\n",
+			len = snprintf(str, size, "%s %s %ld %d %d %d %d\n",
 					batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 					d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits);
+
+			size -= len;
+			if (size <= 0)
+				break;
+
+			str += len;
 		}
+
+		if (size <= 0)
+			break;
 	}
 
 	rfcomm_unlock();
--- linux-ec2-2.6.32.orig/net/bluetooth/rfcomm/sock.c
+++ linux-ec2-2.6.32/net/bluetooth/rfcomm/sock.c
@@ -1065,13 +1065,22 @@
 	struct sock *sk;
 	struct hlist_node *node;
 	char *str = buf;
+	int size = PAGE_SIZE;
 
 	read_lock_bh(&rfcomm_sk_list.lock);
 
 	sk_for_each(sk, node, &rfcomm_sk_list.head) {
-		str += sprintf(str, "%s %s %d %d\n",
+		int len;
+
+		len = snprintf(str, size, "%s %s %d %d\n",
 				batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
 				sk->sk_state, rfcomm_pi(sk)->channel);
+
+		size -= len;
+		if (size <= 0)
+			break;
+
+		str += len;
 	}
 
 	read_unlock_bh(&rfcomm_sk_list.lock);
--- linux-ec2-2.6.32.orig/net/bluetooth/bnep/sock.c
+++ linux-ec2-2.6.32/net/bluetooth/bnep/sock.c
@@ -88,6 +88,7 @@
 			sockfd_put(nsock);
 			return -EBADFD;
 		}
+		ca.device[sizeof(ca.device)-1] = 0;
 
 		err = bnep_add_connection(&ca, nsock);
 		if (!err) {
--- linux-ec2-2.6.32.orig/net/core/filter.c
+++ linux-ec2-2.6.32/net/core/filter.c
@@ -111,39 +111,41 @@
  */
 unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
 {
-	struct sock_filter *fentry;	/* We walk down these */
 	void *ptr;
 	u32 A = 0;			/* Accumulator */
 	u32 X = 0;			/* Index Register */
 	u32 mem[BPF_MEMWORDS];		/* Scratch Memory Store */
+	unsigned long memvalid = 0;
 	u32 tmp;
 	int k;
 	int pc;
 
+	BUILD_BUG_ON(BPF_MEMWORDS > BITS_PER_LONG);
 	/*
 	 * Process array of filter instructions.
 	 */
 	for (pc = 0; pc < flen; pc++) {
-		fentry = &filter[pc];
+		const struct sock_filter *fentry = &filter[pc];
+		u32 f_k = fentry->k;
 
 		switch (fentry->code) {
 		case BPF_ALU|BPF_ADD|BPF_X:
 			A += X;
 			continue;
 		case BPF_ALU|BPF_ADD|BPF_K:
-			A += fentry->k;
+			A += f_k;
 			continue;
 		case BPF_ALU|BPF_SUB|BPF_X:
 			A -= X;
 			continue;
 		case BPF_ALU|BPF_SUB|BPF_K:
-			A -= fentry->k;
+			A -= f_k;
 			continue;
 		case BPF_ALU|BPF_MUL|BPF_X:
 			A *= X;
 			continue;
 		case BPF_ALU|BPF_MUL|BPF_K:
-			A *= fentry->k;
+			A *= f_k;
 			continue;
 		case BPF_ALU|BPF_DIV|BPF_X:
 			if (X == 0)
@@ -151,49 +153,49 @@
 			A /= X;
 			continue;
 		case BPF_ALU|BPF_DIV|BPF_K:
-			A /= fentry->k;
+			A /= f_k;
 			continue;
 		case BPF_ALU|BPF_AND|BPF_X:
 			A &= X;
 			continue;
 		case BPF_ALU|BPF_AND|BPF_K:
-			A &= fentry->k;
+			A &= f_k;
 			continue;
 		case BPF_ALU|BPF_OR|BPF_X:
 			A |= X;
 			continue;
 		case BPF_ALU|BPF_OR|BPF_K:
-			A |= fentry->k;
+			A |= f_k;
 			continue;
 		case BPF_ALU|BPF_LSH|BPF_X:
 			A <<= X;
 			continue;
 		case BPF_ALU|BPF_LSH|BPF_K:
-			A <<= fentry->k;
+			A <<= f_k;
 			continue;
 		case BPF_ALU|BPF_RSH|BPF_X:
 			A >>= X;
 			continue;
 		case BPF_ALU|BPF_RSH|BPF_K:
-			A >>= fentry->k;
+			A >>= f_k;
 			continue;
 		case BPF_ALU|BPF_NEG:
 			A = -A;
 			continue;
 		case BPF_JMP|BPF_JA:
-			pc += fentry->k;
+			pc += f_k;
 			continue;
 		case BPF_JMP|BPF_JGT|BPF_K:
-			pc += (A > fentry->k) ? fentry->jt : fentry->jf;
+			pc += (A > f_k) ? fentry->jt : fentry->jf;
 			continue;
 		case BPF_JMP|BPF_JGE|BPF_K:
-			pc += (A >= fentry->k) ? fentry->jt : fentry->jf;
+			pc += (A >= f_k) ? fentry->jt : fentry->jf;
 			continue;
 		case BPF_JMP|BPF_JEQ|BPF_K:
-			pc += (A == fentry->k) ? fentry->jt : fentry->jf;
+			pc += (A == f_k) ? fentry->jt : fentry->jf;
 			continue;
 		case BPF_JMP|BPF_JSET|BPF_K:
-			pc += (A & fentry->k) ? fentry->jt : fentry->jf;
+			pc += (A & f_k) ? fentry->jt : fentry->jf;
 			continue;
 		case BPF_JMP|BPF_JGT|BPF_X:
 			pc += (A > X) ? fentry->jt : fentry->jf;
@@ -208,7 +210,7 @@
 			pc += (A & X) ? fentry->jt : fentry->jf;
 			continue;
 		case BPF_LD|BPF_W|BPF_ABS:
-			k = fentry->k;
+			k = f_k;
 load_w:
 			ptr = load_pointer(skb, k, 4, &tmp);
 			if (ptr != NULL) {
@@ -217,7 +219,7 @@
 			}
 			break;
 		case BPF_LD|BPF_H|BPF_ABS:
-			k = fentry->k;
+			k = f_k;
 load_h:
 			ptr = load_pointer(skb, k, 2, &tmp);
 			if (ptr != NULL) {
@@ -226,7 +228,7 @@
 			}
 			break;
 		case BPF_LD|BPF_B|BPF_ABS:
-			k = fentry->k;
+			k = f_k;
 load_b:
 			ptr = load_pointer(skb, k, 1, &tmp);
 			if (ptr != NULL) {
@@ -241,32 +243,34 @@
 			X = skb->len;
 			continue;
 		case BPF_LD|BPF_W|BPF_IND:
-			k = X + fentry->k;
+			k = X + f_k;
 			goto load_w;
 		case BPF_LD|BPF_H|BPF_IND:
-			k = X + fentry->k;
+			k = X + f_k;
 			goto load_h;
 		case BPF_LD|BPF_B|BPF_IND:
-			k = X + fentry->k;
+			k = X + f_k;
 			goto load_b;
 		case BPF_LDX|BPF_B|BPF_MSH:
-			ptr = load_pointer(skb, fentry->k, 1, &tmp);
+			ptr = load_pointer(skb, f_k, 1, &tmp);
 			if (ptr != NULL) {
 				X = (*(u8 *)ptr & 0xf) << 2;
 				continue;
 			}
 			return 0;
 		case BPF_LD|BPF_IMM:
-			A = fentry->k;
+			A = f_k;
 			continue;
 		case BPF_LDX|BPF_IMM:
-			X = fentry->k;
+			X = f_k;
 			continue;
 		case BPF_LD|BPF_MEM:
-			A = mem[fentry->k];
+			A = (memvalid & (1UL << f_k)) ?
+				mem[f_k] : 0;
 			continue;
 		case BPF_LDX|BPF_MEM:
-			X = mem[fentry->k];
+			X = (memvalid & (1UL << f_k)) ?
+				mem[f_k] : 0;
 			continue;
 		case BPF_MISC|BPF_TAX:
 			X = A;
@@ -275,14 +279,16 @@
 			A = X;
 			continue;
 		case BPF_RET|BPF_K:
-			return fentry->k;
+			return f_k;
 		case BPF_RET|BPF_A:
 			return A;
 		case BPF_ST:
-			mem[fentry->k] = A;
+			memvalid |= 1UL << f_k;
+			mem[f_k] = A;
 			continue;
 		case BPF_STX:
-			mem[fentry->k] = X;
+			memvalid |= 1UL << f_k;
+			mem[f_k] = X;
 			continue;
 		default:
 			WARN_ON(1);
--- linux-ec2-2.6.32.orig/net/core/pktgen.c
+++ linux-ec2-2.6.32/net/core/pktgen.c
@@ -3516,6 +3516,7 @@
 			wait_event_interruptible_timeout(t->queue,
 							 t->control != 0,
 							 HZ/10);
+			try_to_freeze();
 			continue;
 		}
 
--- linux-ec2-2.6.32.orig/net/core/net-sysfs.c
+++ linux-ec2-2.6.32/net/core/net-sysfs.c
@@ -366,7 +366,8 @@
 	const struct iw_statistics *iw;
 	ssize_t ret = -EINVAL;
 
-	rtnl_lock();
+	if (!rtnl_trylock())
+		return restart_syscall();
 	if (dev_isalive(dev)) {
 		iw = get_wireless_stats(dev);
 		if (iw)
--- linux-ec2-2.6.32.orig/net/core/scm.c
+++ linux-ec2-2.6.32/net/core/scm.c
@@ -156,6 +156,8 @@
 		switch (cmsg->cmsg_type)
 		{
 		case SCM_RIGHTS:
+			if (!sock->ops || sock->ops->family != PF_UNIX)
+				goto error;
 			err=scm_fp_copy(cmsg, &p->fp);
 			if (err<0)
 				goto error;
--- linux-ec2-2.6.32.orig/net/core/skbuff.c
+++ linux-ec2-2.6.32/net/core/skbuff.c
@@ -581,6 +581,10 @@
 	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
 	n->cloned = 1;
 	n->nohdr = 0;
+#ifdef CONFIG_XEN
+	C(proto_data_valid);
+	C(proto_csum_blank);
+#endif
 	n->destructor = NULL;
 	C(tail);
 	C(end);
@@ -2575,6 +2579,10 @@
 		__copy_skb_header(nskb, skb);
 		nskb->mac_len = skb->mac_len;
 
+		/* nskb and skb might have different headroom */
+		if (nskb->ip_summed == CHECKSUM_PARTIAL)
+			nskb->csum_start += skb_headroom(nskb) - headroom;
+
 		skb_reset_mac_header(nskb);
 		skb_set_network_header(nskb, skb->mac_len);
 		nskb->transport_header = (nskb->network_header +
@@ -2705,7 +2713,7 @@
 		return -E2BIG;
 
 	headroom = skb_headroom(p);
-	nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p));
+	nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
 	if (unlikely(!nskb))
 		return -ENOMEM;
 
@@ -2726,6 +2734,7 @@
 	*NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
 	skb_shinfo(nskb)->frag_list = p;
 	skb_shinfo(nskb)->gso_size = pinfo->gso_size;
+	pinfo->gso_size = 0;
 	skb_header_release(p);
 	nskb->prev = p;
 
--- linux-ec2-2.6.32.orig/net/core/sock.c
+++ linux-ec2-2.6.32/net/core/sock.c
@@ -1181,6 +1181,10 @@
 
 		if (newsk->sk_prot->sockets_allocated)
 			percpu_counter_inc(newsk->sk_prot->sockets_allocated);
+
+		if (sock_flag(newsk, SOCK_TIMESTAMP) ||
+		    sock_flag(newsk, SOCK_TIMESTAMPING_RX_SOFTWARE))
+			net_enable_timestamp();
 	}
 out:
 	return newsk;
--- linux-ec2-2.6.32.orig/net/core/ethtool.c
+++ linux-ec2-2.6.32/net/core/ethtool.c
@@ -216,22 +216,34 @@
 	return 0;
 }
 
-static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr)
+static int ethtool_set_rxnfc(struct net_device *dev,
+			     u32 cmd, void __user *useraddr)
 {
-	struct ethtool_rxnfc cmd;
+	struct ethtool_rxnfc info;
+	size_t info_size = sizeof(info);
 
 	if (!dev->ethtool_ops->set_rxnfc)
 		return -EOPNOTSUPP;
 
-	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
+	/* struct ethtool_rxnfc was originally defined for
+	 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
+	 * members.  User-space might still be using that
+	 * definition. */
+	if (cmd == ETHTOOL_SRXFH)
+		info_size = (offsetof(struct ethtool_rxnfc, data) +
+			     sizeof(info.data));
+
+	if (copy_from_user(&info, useraddr, info_size))
 		return -EFAULT;
 
-	return dev->ethtool_ops->set_rxnfc(dev, &cmd);
+	return dev->ethtool_ops->set_rxnfc(dev, &info);
 }
 
-static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr)
+static int ethtool_get_rxnfc(struct net_device *dev,
+			     u32 cmd, void __user *useraddr)
 {
 	struct ethtool_rxnfc info;
+	size_t info_size = sizeof(info);
 	const struct ethtool_ops *ops = dev->ethtool_ops;
 	int ret;
 	void *rule_buf = NULL;
@@ -239,13 +251,22 @@
 	if (!ops->get_rxnfc)
 		return -EOPNOTSUPP;
 
-	if (copy_from_user(&info, useraddr, sizeof(info)))
+	/* struct ethtool_rxnfc was originally defined for
+	 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
+	 * members.  User-space might still be using that
+	 * definition. */
+	if (cmd == ETHTOOL_GRXFH)
+		info_size = (offsetof(struct ethtool_rxnfc, data) +
+			     sizeof(info.data));
+
+	if (copy_from_user(&info, useraddr, info_size))
 		return -EFAULT;
 
 	if (info.cmd == ETHTOOL_GRXCLSRLALL) {
 		if (info.rule_cnt > 0) {
-			rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
-					   GFP_USER);
+			if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
+				rule_buf = kzalloc(info.rule_cnt * sizeof(u32),
+						   GFP_USER);
 			if (!rule_buf)
 				return -ENOMEM;
 		}
@@ -256,7 +277,7 @@
 		goto err_out;
 
 	ret = -EFAULT;
-	if (copy_to_user(useraddr, &info, sizeof(info)))
+	if (copy_to_user(useraddr, &info, info_size))
 		goto err_out;
 
 	if (rule_buf) {
@@ -290,7 +311,7 @@
 	if (regs.len > reglen)
 		regs.len = reglen;
 
-	regbuf = kmalloc(reglen, GFP_USER);
+	regbuf = kzalloc(reglen, GFP_USER);
 	if (!regbuf)
 		return -ENOMEM;
 
@@ -309,6 +330,26 @@
 	return ret;
 }
 
+static int ethtool_reset(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value reset;
+	int ret;
+
+	if (!dev->ethtool_ops->reset)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&reset, useraddr, sizeof(reset)))
+		return -EFAULT;
+
+	ret = dev->ethtool_ops->reset(dev, &reset.data);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(useraddr, &reset, sizeof(reset)))
+		return -EFAULT;
+	return 0;
+}
+
 static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
@@ -1111,12 +1152,12 @@
 	case ETHTOOL_GRXCLSRLCNT:
 	case ETHTOOL_GRXCLSRULE:
 	case ETHTOOL_GRXCLSRLALL:
-		rc = ethtool_get_rxnfc(dev, useraddr);
+		rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
 		break;
 	case ETHTOOL_SRXFH:
 	case ETHTOOL_SRXCLSRLDEL:
 	case ETHTOOL_SRXCLSRLINS:
-		rc = ethtool_set_rxnfc(dev, useraddr);
+		rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
 		break;
 	case ETHTOOL_GGRO:
 		rc = ethtool_get_gro(dev, useraddr);
@@ -1127,6 +1168,9 @@
 	case ETHTOOL_FLASHDEV:
 		rc = ethtool_flash_device(dev, useraddr);
 		break;
+	case ETHTOOL_RESET:
+		rc = ethtool_reset(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}
--- linux-ec2-2.6.32.orig/net/core/stream.c
+++ linux-ec2-2.6.32/net/core/stream.c
@@ -140,10 +140,10 @@
 
 		set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 		sk->sk_write_pending++;
-		sk_wait_event(sk, &current_timeo, !sk->sk_err &&
-						  !(sk->sk_shutdown & SEND_SHUTDOWN) &&
-						  sk_stream_memory_free(sk) &&
-						  vm_wait);
+		sk_wait_event(sk, &current_timeo, sk->sk_err ||
+						  (sk->sk_shutdown & SEND_SHUTDOWN) ||
+						  (sk_stream_memory_free(sk) &&
+						  !vm_wait));
 		sk->sk_write_pending--;
 
 		if (vm_wait) {
--- linux-ec2-2.6.32.orig/net/core/neighbour.c
+++ linux-ec2-2.6.32/net/core/neighbour.c
@@ -945,7 +945,10 @@
 {
 	struct hh_cache *hh;
 	void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
-		= neigh->dev->header_ops->cache_update;
+		= NULL;
+
+	if (neigh->dev->header_ops)
+		update = neigh->dev->header_ops->cache_update;
 
 	if (update) {
 		for (hh = neigh->hh; hh; hh = hh->hh_next) {
--- linux-ec2-2.6.32.orig/net/core/dev.c
+++ linux-ec2-2.6.32/net/core/dev.c
@@ -136,6 +136,12 @@
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
 
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+#include <net/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#endif
+
 /*
  *	The list of packet types we will receive (as opposed to discard)
  *	and the routines to invoke.
@@ -1037,13 +1043,21 @@
 void dev_load(struct net *net, const char *name)
 {
 	struct net_device *dev;
+	int no_module;
 
 	read_lock(&dev_base_lock);
 	dev = __dev_get_by_name(net, name);
 	read_unlock(&dev_base_lock);
 
-	if (!dev && capable(CAP_NET_ADMIN))
-		request_module("%s", name);
+	no_module = !dev;
+	if (no_module && capable(CAP_NET_ADMIN))
+		no_module = request_module("netdev-%s", name);
+	if (no_module && capable(CAP_SYS_MODULE)) {
+		if (!request_module("%s", name))
+			pr_err("Loading kernel module for a network device "
+"with CAP_SYS_MODULE (deprecated).  Use CAP_NET_ADMIN and alias netdev-%s "
+"instead\n", name);
+	}
 }
 EXPORT_SYMBOL(dev_load);
 
@@ -1484,10 +1498,10 @@
 
 static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 {
-	return ((features & NETIF_F_GEN_CSUM) ||
-		((features & NETIF_F_IP_CSUM) &&
+	return ((features & NETIF_F_NO_CSUM) ||
+		((features & NETIF_F_V4_CSUM) &&
 		 protocol == htons(ETH_P_IP)) ||
-		((features & NETIF_F_IPV6_CSUM) &&
+		((features & NETIF_F_V6_CSUM) &&
 		 protocol == htons(ETH_P_IPV6)) ||
 		((features & NETIF_F_FCOE_CRC) &&
 		 protocol == htons(ETH_P_FCOE)));
@@ -1747,6 +1761,14 @@
 
 		skb->next = nskb->next;
 		nskb->next = NULL;
+
+		/*
+		 * If device doesnt need nskb->dst, release it right now while
+		 * its hot in this cpu cache
+		 */
+		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
+			skb_dst_drop(nskb);
+
 		rc = ops->ndo_start_xmit(nskb, dev);
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			nskb->next = skb->next;
@@ -1804,6 +1826,58 @@
 	return netdev_get_tx_queue(dev, queue_index);
 }
 
+#if defined(CONFIG_XEN) || defined(CONFIG_PARAVIRT_XEN)
+inline int skb_checksum_setup(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	unsigned char *th;
+	int err = -EPROTO;
+
+#ifdef CONFIG_XEN
+	if (!skb->proto_csum_blank)
+		return 0;
+#endif
+
+	if (skb->protocol != htons(ETH_P_IP))
+		goto out;
+
+	iph = ip_hdr(skb);
+	th = skb_network_header(skb) + 4 * iph->ihl;
+	if (th >= skb_tail_pointer(skb))
+		goto out;
+
+	skb->csum_start = th - skb->head;
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		skb->csum_offset = offsetof(struct tcphdr, check);
+		break;
+	case IPPROTO_UDP:
+		skb->csum_offset = offsetof(struct udphdr, check);
+		break;
+	default:
+		if (net_ratelimit())
+			printk(KERN_ERR "Attempting to checksum a non-"
+			       "TCP/UDP packet, dropping a protocol"
+			       " %d packet", iph->protocol);
+		goto out;
+	}
+
+	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+		goto out;
+
+#ifdef CONFIG_XEN
+	skb->ip_summed = CHECKSUM_PARTIAL;
+	skb->proto_csum_blank = 0;
+#endif
+
+	err = 0;
+
+out:
+	return err;
+}
+EXPORT_SYMBOL(skb_checksum_setup);
+#endif
+
 static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 				 struct net_device *dev,
 				 struct netdev_queue *txq)
@@ -1870,6 +1944,12 @@
 	struct Qdisc *q;
 	int rc = -ENOMEM;
 
+ 	/* If a checksum-deferred packet is forwarded to a device that needs a
+ 	 * checksum, correct the pointers and force checksumming.
+ 	 */
+ 	if (skb_checksum_setup(skb))
+ 		goto out_kfree_skb;
+
 	/* GSO will handle the following emulations directly. */
 	if (netif_needs_gso(dev, skb))
 		goto gso;
@@ -2328,6 +2408,19 @@
 	}
 #endif
 
+#ifdef CONFIG_XEN
+	switch (skb->ip_summed) {
+	case CHECKSUM_UNNECESSARY:
+		skb->proto_data_valid = 1;
+		break;
+	case CHECKSUM_PARTIAL:
+		/* XXX Implement me. */
+	default:
+		skb->proto_data_valid = 0;
+		break;
+	}
+#endif
+
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
 		    ptype->dev == orig_dev) {
@@ -2440,7 +2533,7 @@
 }
 EXPORT_SYMBOL(napi_gro_flush);
 
-int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
 	struct sk_buff **pp = NULL;
 	struct packet_type *ptype;
@@ -2448,7 +2541,7 @@
 	struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
 	int same_flow;
 	int mac_len;
-	int ret;
+	enum gro_result ret;
 
 	if (!(skb->dev->features & NETIF_F_GRO))
 		goto normal;
@@ -2519,7 +2612,7 @@
 			put_page(skb_shinfo(skb)->frags[0].page);
 			memmove(skb_shinfo(skb)->frags,
 				skb_shinfo(skb)->frags + 1,
-				--skb_shinfo(skb)->nr_frags);
+				--skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
 		}
 	}
 
@@ -2532,7 +2625,8 @@
 }
 EXPORT_SYMBOL(dev_gro_receive);
 
-static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+static gro_result_t
+__napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
 	struct sk_buff *p;
 
@@ -2549,24 +2643,25 @@
 	return dev_gro_receive(napi, skb);
 }
 
-int napi_skb_finish(int ret, struct sk_buff *skb)
+gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
-	int err = NET_RX_SUCCESS;
-
 	switch (ret) {
 	case GRO_NORMAL:
-		return netif_receive_skb(skb);
+		if (netif_receive_skb(skb))
+			ret = GRO_DROP;
+		break;
 
 	case GRO_DROP:
-		err = NET_RX_DROP;
-		/* fall through */
-
 	case GRO_MERGED_FREE:
 		kfree_skb(skb);
 		break;
+
+	case GRO_HELD:
+	case GRO_MERGED:
+		break;
 	}
 
-	return err;
+	return ret;
 }
 EXPORT_SYMBOL(napi_skb_finish);
 
@@ -2586,7 +2681,7 @@
 }
 EXPORT_SYMBOL(skb_gro_reset_offset);
 
-int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
 	skb_gro_reset_offset(skb);
 
@@ -2598,6 +2693,8 @@
 {
 	__skb_pull(skb, skb_headlen(skb));
 	skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+	skb->dev = napi->dev;
+	skb->iif = 0;
 
 	napi->skb = skb;
 }
@@ -2623,31 +2720,30 @@
 }
 EXPORT_SYMBOL(napi_get_frags);
 
-int napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, int ret)
+gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
+			       gro_result_t ret)
 {
-	int err = NET_RX_SUCCESS;
-
 	switch (ret) {
 	case GRO_NORMAL:
 	case GRO_HELD:
-		skb->protocol = eth_type_trans(skb, napi->dev);
-
-		if (ret == GRO_NORMAL)
-			return netif_receive_skb(skb);
+		skb->protocol = eth_type_trans(skb, skb->dev);
 
-		skb_gro_pull(skb, -ETH_HLEN);
+		if (ret == GRO_HELD)
+			skb_gro_pull(skb, -ETH_HLEN);
+		else if (netif_receive_skb(skb))
+			ret = GRO_DROP;
 		break;
 
 	case GRO_DROP:
-		err = NET_RX_DROP;
-		/* fall through */
-
 	case GRO_MERGED_FREE:
 		napi_reuse_skb(napi, skb);
 		break;
+
+	case GRO_MERGED:
+		break;
 	}
 
-	return err;
+	return ret;
 }
 EXPORT_SYMBOL(napi_frags_finish);
 
@@ -2688,12 +2784,12 @@
 }
 EXPORT_SYMBOL(napi_frags_skb);
 
-int napi_gro_frags(struct napi_struct *napi)
+gro_result_t napi_gro_frags(struct napi_struct *napi)
 {
 	struct sk_buff *skb = napi_frags_skb(napi);
 
 	if (!skb)
-		return NET_RX_DROP;
+		return GRO_DROP;
 
 	return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb));
 }
@@ -4860,6 +4956,11 @@
 		rollback_registered(dev);
 		dev->reg_state = NETREG_UNREGISTERED;
 	}
+	/*
+	 *	Prevent userspace races by waiting until the network
+	 *	device is fully setup before sending notifications.
+	 */
+	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
 
 out:
 	return ret;
@@ -5398,6 +5499,12 @@
 	/* Notify protocols, that a new device appeared. */
 	call_netdevice_notifiers(NETDEV_REGISTER, dev);
 
+	/*
+	 *	Prevent userspace races by waiting until the network
+	 *	device is fully setup before sending notifications.
+	 */
+	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+
 	synchronize_net();
 	err = 0;
 out:
--- linux-ec2-2.6.32.orig/net/core/iovec.c
+++ linux-ec2-2.6.32/net/core/iovec.c
@@ -38,7 +38,7 @@
 
 int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
 {
-	int size, err, ct;
+	int size, ct, err;
 
 	if (m->msg_namelen) {
 		if (mode == VERIFY_READ) {
@@ -60,14 +60,13 @@
 	err = 0;
 
 	for (ct = 0; ct < m->msg_iovlen; ct++) {
-		err += iov[ct].iov_len;
-		/*
-		 * Goal is not to verify user data, but to prevent returning
-		 * negative value, which is interpreted as errno.
-		 * Overflow is still possible, but it is harmless.
-		 */
-		if (err < 0)
-			return -EMSGSIZE;
+		size_t len = iov[ct].iov_len;
+
+		if (len > INT_MAX - err) {
+			len = INT_MAX - err;
+			iov[ct].iov_len = len;
+		}
+		err += len;
 	}
 
 	return err;
--- linux-ec2-2.6.32.orig/net/core/dst.c
+++ linux-ec2-2.6.32/net/core/dst.c
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <net/net_namespace.h>
+#include <linux/sched.h>
 
 #include <net/dst.h>
 
@@ -79,6 +80,7 @@
 	while ((dst = next) != NULL) {
 		next = dst->next;
 		prefetch(&next->next);
+		cond_resched();
 		if (likely(atomic_read(&dst->__refcnt))) {
 			last->next = dst;
 			last = dst;
--- linux-ec2-2.6.32.orig/net/core/rtnetlink.c
+++ linux-ec2-2.6.32/net/core/rtnetlink.c
@@ -1334,13 +1334,11 @@
 	case NETDEV_UNREGISTER:
 		rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
 		break;
-	case NETDEV_REGISTER:
-		rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
-		break;
 	case NETDEV_UP:
 	case NETDEV_DOWN:
 		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
 		break;
+	case NETDEV_REGISTER:
 	case NETDEV_CHANGE:
 	case NETDEV_GOING_DOWN:
 		break;
--- linux-ec2-2.6.32.orig/net/rds/rdma.c
+++ linux-ec2-2.6.32/net/rds/rdma.c
@@ -447,7 +447,7 @@
 		goto out;
 	}
 
-	if (args->nr_local > (u64)UINT_MAX) {
+	if (args->nr_local > UIO_MAXIOV) {
 		ret = -EMSGSIZE;
 		goto out;
 	}
@@ -473,6 +473,17 @@
 
 		max_pages = max(nr, max_pages);
 		nr_pages += nr;
+
+		/*
+		 * nr for one entry in limited to (UINT_MAX>>PAGE_SHIFT)+1
+		 * so nr_pages cannot overflow without becoming bigger than
+		 * INT_MAX first. If nr cannot overflow then max_pages should
+		 * be ok.
+		 */
+		if (nr_pages > INT_MAX) {
+			ret = -EINVAL;
+			goto out;
+		}
 	}
 
 	pages = kcalloc(max_pages, sizeof(struct page *), GFP_KERNEL);
@@ -605,18 +616,32 @@
 int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
 			  struct cmsghdr *cmsg)
 {
+	struct rds_rdma_args *args;
 	struct rds_rdma_op *op;
+	int ret = 0;
 
 	if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct rds_rdma_args))
-	 || rm->m_rdma_op != NULL)
-		return -EINVAL;
+	 || rm->m_rdma_op != NULL) {
+		ret = -EINVAL;
+		goto out;
+        }
+
+	args = CMSG_DATA(cmsg);
+
+	if (args->nr_local > UIO_MAXIOV) {
+		ret = -EMSGSIZE;
+		goto out;
+	}
 
 	op = rds_rdma_prepare(rs, CMSG_DATA(cmsg));
-	if (IS_ERR(op))
-		return PTR_ERR(op);
+	if (IS_ERR(op)) {
+		ret = PTR_ERR(op);
+		goto out;
+	}
 	rds_stats_inc(s_send_rdma);
 	rm->m_rdma_op = op;
-	return 0;
+out:
+	return ret;
 }
 
 /*
--- linux-ec2-2.6.32.orig/net/rds/recv.c
+++ linux-ec2-2.6.32/net/rds/recv.c
@@ -296,7 +296,7 @@
 int rds_notify_queue_get(struct rds_sock *rs, struct msghdr *msghdr)
 {
 	struct rds_notifier *notifier;
-	struct rds_rdma_notify cmsg;
+	struct rds_rdma_notify cmsg = { 0 }; /* fill holes with zero */
 	unsigned int count = 0, max_messages = ~0U;
 	unsigned long flags;
 	LIST_HEAD(copy);
--- linux-ec2-2.6.32.orig/net/rds/page.c
+++ linux-ec2-2.6.32/net/rds/page.c
@@ -56,30 +56,23 @@
 	unsigned long ret;
 	void *addr;
 
-	if (to_user)
+	addr = kmap(page);
+	if (to_user) {
 		rds_stats_add(s_copy_to_user, bytes);
-	else
+		ret = access_ok(VERIFY_WRITE, ptr, bytes);
+		if (!ret)
+			return -EFAULT;
+		ret = copy_to_user(ptr, addr + offset, bytes);
+	} else {
 		rds_stats_add(s_copy_from_user, bytes);
-
-	addr = kmap_atomic(page, KM_USER0);
-	if (to_user)
-		ret = __copy_to_user_inatomic(ptr, addr + offset, bytes);
-	else
-		ret = __copy_from_user_inatomic(addr + offset, ptr, bytes);
-	kunmap_atomic(addr, KM_USER0);
-
-	if (ret) {
-		addr = kmap(page);
-		if (to_user)
-			ret = copy_to_user(ptr, addr + offset, bytes);
-		else
-			ret = copy_from_user(addr + offset, ptr, bytes);
-		kunmap(page);
-		if (ret)
+		ret = access_ok(VERIFY_READ, ptr, bytes);
+		if (!ret)
 			return -EFAULT;
+		ret = copy_from_user(addr + offset, ptr, bytes);
 	}
+	kunmap(page);
 
-	return 0;
+	return ret ? -EFAULT : 0;
 }
 EXPORT_SYMBOL_GPL(rds_page_copy_user);
 
--- linux-ec2-2.6.32.orig/net/netfilter/xt_recent.c
+++ linux-ec2-2.6.32/net/netfilter/xt_recent.c
@@ -142,6 +142,25 @@
 	t->entries--;
 }
 
+/*
+ * Drop entries with timestamps older then 'time'.
+ */
+static void recent_entry_reap(struct recent_table *t, unsigned long time)
+{
+	struct recent_entry *e;
+
+	/*
+	 * The head of the LRU list is always the oldest entry.
+	 */
+	e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
+
+	/*
+	 * The last time stamp is the most recent.
+	 */
+	if (time_after(time, e->stamps[e->index-1]))
+		recent_entry_remove(t, e);
+}
+
 static struct recent_entry *
 recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr,
 		  u_int16_t family, u_int8_t ttl)
@@ -173,10 +192,10 @@
 
 static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
 {
+	e->index %= ip_pkt_list_tot;
 	e->stamps[e->index++] = jiffies;
 	if (e->index > e->nstamps)
 		e->nstamps = e->index;
-	e->index %= ip_pkt_list_tot;
 	list_move_tail(&e->lru_list, &t->lru_list);
 }
 
@@ -260,11 +279,15 @@
 		for (i = 0; i < e->nstamps; i++) {
 			if (info->seconds && time_after(time, e->stamps[i]))
 				continue;
-			if (++hits >= info->hit_count) {
+			if (!info->hit_count || ++hits >= info->hit_count) {
 				ret = !ret;
 				break;
 			}
 		}
+
+		/* info->seconds must be non-zero */
+		if (info->check_set & XT_RECENT_REAP)
+			recent_entry_reap(t, time);
 	}
 
 	if (info->check_set & XT_RECENT_SET ||
@@ -292,7 +315,10 @@
 		      XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1)
 		return false;
 	if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) &&
-	    (info->seconds || info->hit_count))
+	    (info->seconds || info->hit_count ||
+	    (info->check_set & XT_RECENT_MODIFIERS)))
+		return false;
+	if ((info->check_set & XT_RECENT_REAP) && !info->seconds)
 		return false;
 	if (info->hit_count > ip_pkt_list_tot)
 		return false;
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_ftp.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_ftp.c
@@ -323,24 +323,24 @@
 			  struct nf_ct_ftp_master *info, int dir,
 			  struct sk_buff *skb)
 {
-	unsigned int i, oldest = NUM_SEQ_TO_REMEMBER;
+	unsigned int i, oldest;
 
 	/* Look for oldest: if we find exact match, we're done. */
 	for (i = 0; i < info->seq_aft_nl_num[dir]; i++) {
 		if (info->seq_aft_nl[dir][i] == nl_seq)
 			return;
-
-		if (oldest == info->seq_aft_nl_num[dir] ||
-		    before(info->seq_aft_nl[dir][i],
-			   info->seq_aft_nl[dir][oldest]))
-			oldest = i;
 	}
 
 	if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
 		info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
-	} else if (oldest != NUM_SEQ_TO_REMEMBER &&
-		   after(nl_seq, info->seq_aft_nl[dir][oldest])) {
-		info->seq_aft_nl[dir][oldest] = nl_seq;
+	} else {
+		if (before(info->seq_aft_nl[dir][0], info->seq_aft_nl[dir][1]))
+			oldest = 0;
+		else
+			oldest = 1;
+
+		if (after(nl_seq, info->seq_aft_nl[dir][oldest]))
+			info->seq_aft_nl[dir][oldest] = nl_seq;
 	}
 }
 
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_core.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_core.c
@@ -30,6 +30,7 @@
 #include <linux/netdevice.h>
 #include <linux/socket.h>
 #include <linux/mm.h>
+#include <linux/nsproxy.h>
 #include <linux/rculist_nulls.h>
 
 #include <net/netfilter/nf_conntrack.h>
@@ -63,8 +64,6 @@
 struct nf_conn nf_conntrack_untracked __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
 
-static struct kmem_cache *nf_conntrack_cachep __read_mostly;
-
 static int nf_conntrack_hash_rnd_initted;
 static unsigned int nf_conntrack_hash_rnd;
 
@@ -86,9 +85,10 @@
 	return ((u64)h * size) >> 32;
 }
 
-static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
+static inline u_int32_t hash_conntrack(const struct net *net,
+				       const struct nf_conntrack_tuple *tuple)
 {
-	return __hash_conntrack(tuple, nf_conntrack_htable_size,
+	return __hash_conntrack(tuple, net->ct.htable_size,
 				nf_conntrack_hash_rnd);
 }
 
@@ -296,7 +296,7 @@
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct hlist_nulls_node *n;
-	unsigned int hash = hash_conntrack(tuple);
+	unsigned int hash = hash_conntrack(net, tuple);
 
 	/* Disable BHs the entire time since we normally need to disable them
 	 * at least once for the stats anyway.
@@ -366,10 +366,11 @@
 
 void nf_conntrack_hash_insert(struct nf_conn *ct)
 {
+	struct net *net = nf_ct_net(ct);
 	unsigned int hash, repl_hash;
 
-	hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-	repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
 	__nf_conntrack_hash_insert(ct, hash, repl_hash);
 }
@@ -397,8 +398,8 @@
 	if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
 		return NF_ACCEPT;
 
-	hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-	repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
 	/* We're not in hash table, and we refuse to set up related
 	   connections for unconfirmed conns.  But packet copies and
@@ -468,7 +469,7 @@
 	struct net *net = nf_ct_net(ignored_conntrack);
 	struct nf_conntrack_tuple_hash *h;
 	struct hlist_nulls_node *n;
-	unsigned int hash = hash_conntrack(tuple);
+	unsigned int hash = hash_conntrack(net, tuple);
 
 	/* Disable BHs the entire time since we need to disable them at
 	 * least once for the stats anyway.
@@ -503,7 +504,7 @@
 	int dropped = 0;
 
 	rcu_read_lock();
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < net->ct.htable_size; i++) {
 		hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash],
 					 hnnode) {
 			tmp = nf_ct_tuplehash_to_ctrack(h);
@@ -517,7 +518,8 @@
 			ct = NULL;
 		if (ct || cnt >= NF_CT_EVICTION_RANGE)
 			break;
-		hash = (hash + 1) % nf_conntrack_htable_size;
+
+		hash = (hash + 1) % net->ct.htable_size;
 	}
 	rcu_read_unlock();
 
@@ -551,7 +553,7 @@
 
 	if (nf_conntrack_max &&
 	    unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
-		unsigned int hash = hash_conntrack(orig);
+		unsigned int hash = hash_conntrack(net, orig);
 		if (!early_drop(net, hash)) {
 			atomic_dec(&net->ct.count);
 			if (net_ratelimit())
@@ -566,7 +568,7 @@
 	 * Do not use kmem_cache_zalloc(), as this cache uses
 	 * SLAB_DESTROY_BY_RCU.
 	 */
-	ct = kmem_cache_alloc(nf_conntrack_cachep, gfp);
+	ct = kmem_cache_alloc(net->ct.nf_conntrack_cachep, gfp);
 	if (ct == NULL) {
 		pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
 		atomic_dec(&net->ct.count);
@@ -605,7 +607,7 @@
 	nf_ct_ext_destroy(ct);
 	atomic_dec(&net->ct.count);
 	nf_ct_ext_free(ct);
-	kmem_cache_free(nf_conntrack_cachep, ct);
+	kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_free);
 
@@ -1008,7 +1010,7 @@
 	struct hlist_nulls_node *n;
 
 	spin_lock_bh(&nf_conntrack_lock);
-	for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
+	for (; *bucket < net->ct.htable_size; (*bucket)++) {
 		hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) {
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			if (iter(ct, data))
@@ -1107,9 +1109,12 @@
 
 static void nf_conntrack_cleanup_init_net(void)
 {
+	/* wait until all references to nf_conntrack_untracked are dropped */
+	while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
+		schedule();
+
 	nf_conntrack_helper_fini();
 	nf_conntrack_proto_fini();
-	kmem_cache_destroy(nf_conntrack_cachep);
 }
 
 static void nf_conntrack_cleanup_net(struct net *net)
@@ -1121,15 +1126,14 @@
 		schedule();
 		goto i_see_dead_people;
 	}
-	/* wait until all references to nf_conntrack_untracked are dropped */
-	while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
-		schedule();
 
 	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     nf_conntrack_htable_size);
+			     net->ct.htable_size);
 	nf_conntrack_ecache_fini(net);
 	nf_conntrack_acct_fini(net);
 	nf_conntrack_expect_fini(net);
+	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
+	kfree(net->ct.slabname);
 	free_percpu(net->ct.stat);
 }
 
@@ -1169,7 +1173,8 @@
 	if (!hash) {
 		*vmalloced = 1;
 		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
-		hash = __vmalloc(sz, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+		hash = __vmalloc(sz, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+				 PAGE_KERNEL);
 	}
 
 	if (hash && nulls)
@@ -1184,10 +1189,12 @@
 {
 	int i, bucket, vmalloced, old_vmalloced;
 	unsigned int hashsize, old_size;
-	int rnd;
 	struct hlist_nulls_head *hash, *old_hash;
 	struct nf_conntrack_tuple_hash *h;
 
+	if (current->nsproxy->net_ns != &init_net)
+		return -EOPNOTSUPP;
+
 	/* On boot, we can set this without any fancy locking. */
 	if (!nf_conntrack_htable_size)
 		return param_set_uint(val, kp);
@@ -1200,33 +1207,29 @@
 	if (!hash)
 		return -ENOMEM;
 
-	/* We have to rehahs for the new table anyway, so we also can
-	 * use a newrandom seed */
-	get_random_bytes(&rnd, sizeof(rnd));
-
 	/* Lookups in the old hash might happen in parallel, which means we
 	 * might get false negatives during connection lookup. New connections
 	 * created because of a false negative won't make it into the hash
 	 * though since that required taking the lock.
 	 */
 	spin_lock_bh(&nf_conntrack_lock);
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < init_net.ct.htable_size; i++) {
 		while (!hlist_nulls_empty(&init_net.ct.hash[i])) {
 			h = hlist_nulls_entry(init_net.ct.hash[i].first,
 					struct nf_conntrack_tuple_hash, hnnode);
 			hlist_nulls_del_rcu(&h->hnnode);
-			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+			bucket = __hash_conntrack(&h->tuple, hashsize,
+						  nf_conntrack_hash_rnd);
 			hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]);
 		}
 	}
-	old_size = nf_conntrack_htable_size;
+	old_size = init_net.ct.htable_size;
 	old_vmalloced = init_net.ct.hash_vmalloc;
 	old_hash = init_net.ct.hash;
 
-	nf_conntrack_htable_size = hashsize;
+	init_net.ct.htable_size = nf_conntrack_htable_size = hashsize;
 	init_net.ct.hash_vmalloc = vmalloced;
 	init_net.ct.hash = hash;
-	nf_conntrack_hash_rnd = rnd;
 	spin_unlock_bh(&nf_conntrack_lock);
 
 	nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
@@ -1265,15 +1268,6 @@
 	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
 	       nf_conntrack_max);
 
-	nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
-						sizeof(struct nf_conn),
-						0, SLAB_DESTROY_BY_RCU, NULL);
-	if (!nf_conntrack_cachep) {
-		printk(KERN_ERR "Unable to create nf_conn slab cache\n");
-		ret = -ENOMEM;
-		goto err_cache;
-	}
-
 	ret = nf_conntrack_proto_init();
 	if (ret < 0)
 		goto err_proto;
@@ -1282,13 +1276,19 @@
 	if (ret < 0)
 		goto err_helper;
 
+	/* Set up fake conntrack: to never be deleted, not in any hashes */
+#ifdef CONFIG_NET_NS
+	nf_conntrack_untracked.ct_net = &init_net;
+#endif
+	atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
+	/*  - and look it like as a confirmed connection */
+	set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
+
 	return 0;
 
 err_helper:
 	nf_conntrack_proto_fini();
 err_proto:
-	kmem_cache_destroy(nf_conntrack_cachep);
-err_cache:
 	return ret;
 }
 
@@ -1310,7 +1310,24 @@
 		ret = -ENOMEM;
 		goto err_stat;
 	}
-	net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+
+	net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net);
+	if (!net->ct.slabname) {
+		ret = -ENOMEM;
+		goto err_slabname;
+	}
+
+	net->ct.nf_conntrack_cachep = kmem_cache_create(net->ct.slabname,
+							sizeof(struct nf_conn), 0,
+							SLAB_DESTROY_BY_RCU, NULL);
+	if (!net->ct.nf_conntrack_cachep) {
+		printk(KERN_ERR "Unable to create nf_conn slab cache\n");
+		ret = -ENOMEM;
+		goto err_cache;
+	}
+
+	net->ct.htable_size = nf_conntrack_htable_size;
+	net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size,
 					     &net->ct.hash_vmalloc, 1);
 	if (!net->ct.hash) {
 		ret = -ENOMEM;
@@ -1327,15 +1344,6 @@
 	if (ret < 0)
 		goto err_ecache;
 
-	/* Set up fake conntrack:
-	    - to never be deleted, not in any hashes */
-#ifdef CONFIG_NET_NS
-	nf_conntrack_untracked.ct_net = &init_net;
-#endif
-	atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
-	/*  - and look it like as a confirmed connection */
-	set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
-
 	return 0;
 
 err_ecache:
@@ -1344,8 +1352,12 @@
 	nf_conntrack_expect_fini(net);
 err_expect:
 	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     nf_conntrack_htable_size);
+			     net->ct.htable_size);
 err_hash:
+	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
+err_cache:
+	kfree(net->ct.slabname);
+err_slabname:
 	free_percpu(net->ct.stat);
 err_stat:
 	return ret;
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_helper.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_helper.c
@@ -192,7 +192,7 @@
 	/* Get rid of expecteds, set helpers to NULL. */
 	hlist_nulls_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode)
 		unhelp(h, me);
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < net->ct.htable_size; i++) {
 		hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode)
 			unhelp(h, me);
 	}
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_standalone.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_standalone.c
@@ -51,7 +51,7 @@
 	struct hlist_nulls_node *n;
 
 	for (st->bucket = 0;
-	     st->bucket < nf_conntrack_htable_size;
+	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
 		n = rcu_dereference(net->ct.hash[st->bucket].first);
 		if (!is_a_nulls(n))
@@ -69,7 +69,7 @@
 	head = rcu_dereference(head->next);
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
-			if (++st->bucket >= nf_conntrack_htable_size)
+			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
 		head = rcu_dereference(net->ct.hash[st->bucket].first);
@@ -358,7 +358,7 @@
 	{
 		.ctl_name       = NET_NF_CONNTRACK_BUCKETS,
 		.procname       = "nf_conntrack_buckets",
-		.data           = &nf_conntrack_htable_size,
+		.data           = &init_net.ct.htable_size,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0444,
 		.proc_handler   = proc_dointvec,
@@ -429,6 +429,7 @@
 		goto out_kmemdup;
 
 	table[1].data = &net->ct.count;
+	table[2].data = &net->ct.htable_size;
 	table[3].data = &net->ct.sysctl_checksum;
 	table[4].data = &net->ct.sysctl_log_invalid;
 
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_expect.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_expect.c
@@ -569,7 +569,7 @@
 #endif /* CONFIG_PROC_FS */
 }
 
-module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
 
 int nf_conntrack_expect_init(struct net *net)
 {
@@ -577,7 +577,7 @@
 
 	if (net_eq(net, &init_net)) {
 		if (!nf_ct_expect_hsize) {
-			nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+			nf_ct_expect_hsize = net->ct.htable_size / 256;
 			if (!nf_ct_expect_hsize)
 				nf_ct_expect_hsize = 1;
 		}
--- linux-ec2-2.6.32.orig/net/netfilter/xt_conntrack.c
+++ linux-ec2-2.6.32/net/netfilter/xt_conntrack.c
@@ -113,7 +113,8 @@
 }
 
 static bool
-conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
+conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par,
+             u16 state_mask, u16 status_mask)
 {
 	const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
 	enum ip_conntrack_info ctinfo;
@@ -136,7 +137,7 @@
 			if (test_bit(IPS_DST_NAT_BIT, &ct->status))
 				statebit |= XT_CONNTRACK_STATE_DNAT;
 		}
-		if (!!(info->state_mask & statebit) ^
+		if (!!(state_mask & statebit) ^
 		    !(info->invert_flags & XT_CONNTRACK_STATE))
 			return false;
 	}
@@ -172,7 +173,7 @@
 		return false;
 
 	if ((info->match_flags & XT_CONNTRACK_STATUS) &&
-	    (!!(info->status_mask & ct->status) ^
+	    (!!(status_mask & ct->status) ^
 	    !(info->invert_flags & XT_CONNTRACK_STATUS)))
 		return false;
 
@@ -192,11 +193,17 @@
 static bool
 conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
 {
-	const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo;
-	struct xt_match_param newpar = *par;
+	const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
 
-	newpar.matchinfo = *info;
-	return conntrack_mt(skb, &newpar);
+	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
+}
+
+static bool
+conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+	const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
+
+	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
 }
 
 static bool conntrack_mt_check(const struct xt_mtchk_param *par)
@@ -209,45 +216,11 @@
 	return true;
 }
 
-static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par)
-{
-	struct xt_conntrack_mtinfo1 *info = par->matchinfo;
-	struct xt_conntrack_mtinfo2 *up;
-	int ret = conntrack_mt_check(par);
-
-	if (ret < 0)
-		return ret;
-
-	up = kmalloc(sizeof(*up), GFP_KERNEL);
-	if (up == NULL) {
-		nf_ct_l3proto_module_put(par->family);
-		return -ENOMEM;
-	}
-
-	/*
-	 * The strategy here is to minimize the overhead of v1 matching,
-	 * by prebuilding a v2 struct and putting the pointer into the
-	 * v1 dataspace.
-	 */
-	memcpy(up, info, offsetof(typeof(*info), state_mask));
-	up->state_mask  = info->state_mask;
-	up->status_mask = info->status_mask;
-	*(void **)info  = up;
-	return true;
-}
-
 static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
 {
 	nf_ct_l3proto_module_put(par->family);
 }
 
-static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par)
-{
-	struct xt_conntrack_mtinfo2 **info = par->matchinfo;
-	kfree(*info);
-	conntrack_mt_destroy(par);
-}
-
 static struct xt_match conntrack_mt_reg[] __read_mostly = {
 	{
 		.name       = "conntrack",
@@ -255,8 +228,8 @@
 		.family     = NFPROTO_UNSPEC,
 		.matchsize  = sizeof(struct xt_conntrack_mtinfo1),
 		.match      = conntrack_mt_v1,
-		.checkentry = conntrack_mt_check_v1,
-		.destroy    = conntrack_mt_destroy_v1,
+		.checkentry = conntrack_mt_check,
+		.destroy    = conntrack_mt_destroy,
 		.me         = THIS_MODULE,
 	},
 	{
@@ -264,7 +237,7 @@
 		.revision   = 2,
 		.family     = NFPROTO_UNSPEC,
 		.matchsize  = sizeof(struct xt_conntrack_mtinfo2),
-		.match      = conntrack_mt,
+		.match      = conntrack_mt_v2,
 		.checkentry = conntrack_mt_check,
 		.destroy    = conntrack_mt_destroy,
 		.me         = THIS_MODULE,
--- linux-ec2-2.6.32.orig/net/netfilter/nf_log.c
+++ linux-ec2-2.6.32/net/netfilter/nf_log.c
@@ -83,6 +83,8 @@
 
 int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger)
 {
+	if (pf >= ARRAY_SIZE(nf_loggers))
+		return -EINVAL;
 	mutex_lock(&nf_log_mutex);
 	if (__find_logger(pf, logger->name) == NULL) {
 		mutex_unlock(&nf_log_mutex);
@@ -96,6 +98,8 @@
 
 void nf_log_unbind_pf(u_int8_t pf)
 {
+	if (pf >= ARRAY_SIZE(nf_loggers))
+		return;
 	mutex_lock(&nf_log_mutex);
 	rcu_assign_pointer(nf_loggers[pf], NULL);
 	mutex_unlock(&nf_log_mutex);
--- linux-ec2-2.6.32.orig/net/netfilter/nf_conntrack_netlink.c
+++ linux-ec2-2.6.32/net/netfilter/nf_conntrack_netlink.c
@@ -594,7 +594,7 @@
 
 	rcu_read_lock();
 	last = (struct nf_conn *)cb->args[1];
-	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
+	for (; cb->args[0] < init_net.ct.htable_size; cb->args[0]++) {
 restart:
 		hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]],
 					 hnnode) {
--- linux-ec2-2.6.32.orig/net/netfilter/ipvs/ip_vs_ctl.c
+++ linux-ec2-2.6.32/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2714,6 +2714,8 @@
 	if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr))))
 		return -EINVAL;
 
+	memset(usvc, 0, sizeof(*usvc));
+
 	usvc->af = nla_get_u16(nla_af);
 #ifdef CONFIG_IP_VS_IPV6
 	if (usvc->af != AF_INET && usvc->af != AF_INET6)
@@ -2901,6 +2903,8 @@
 	if (!(nla_addr && nla_port))
 		return -EINVAL;
 
+	memset(udest, 0, sizeof(*udest));
+
 	nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr));
 	udest->port = nla_get_u16(nla_port);
 
--- linux-ec2-2.6.32.orig/net/netfilter/ipvs/ip_vs_conn.c
+++ linux-ec2-2.6.32/net/netfilter/ipvs/ip_vs_conn.c
@@ -146,6 +146,7 @@
 	hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
 	ct_write_lock(hash);
+	spin_lock(&cp->lock);
 
 	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
 		list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
@@ -158,6 +159,7 @@
 		ret = 0;
 	}
 
+	spin_unlock(&cp->lock);
 	ct_write_unlock(hash);
 
 	return ret;
@@ -177,6 +179,7 @@
 	hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
 	ct_write_lock(hash);
+	spin_lock(&cp->lock);
 
 	if (cp->flags & IP_VS_CONN_F_HASHED) {
 		list_del(&cp->c_list);
@@ -186,6 +189,7 @@
 	} else
 		ret = 0;
 
+	spin_unlock(&cp->lock);
 	ct_write_unlock(hash);
 
 	return ret;
--- linux-ec2-2.6.32.orig/net/econet/af_econet.c
+++ linux-ec2-2.6.32/net/econet/af_econet.c
@@ -30,6 +30,7 @@
 #include <linux/wireless.h>
 #include <linux/skbuff.h>
 #include <linux/udp.h>
+#include <linux/vmalloc.h>
 #include <net/sock.h>
 #include <net/inet_common.h>
 #include <linux/stat.h>
@@ -275,12 +276,12 @@
 #endif
 #ifdef CONFIG_ECONET_AUNUDP
 	struct msghdr udpmsg;
-	struct iovec iov[msg->msg_iovlen+1];
+	struct iovec iov[2];
 	struct aunhdr ah;
 	struct sockaddr_in udpdest;
 	__kernel_size_t size;
-	int i;
 	mm_segment_t oldfs;
+	char *userbuf;
 #endif
 
 	/*
@@ -296,23 +297,14 @@
 
 	mutex_lock(&econet_mutex);
 
-	if (saddr == NULL) {
-		struct econet_sock *eo = ec_sk(sk);
-
-		addr.station = eo->station;
-		addr.net     = eo->net;
-		port	     = eo->port;
-		cb	     = eo->cb;
-	} else {
-		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
-			mutex_unlock(&econet_mutex);
-			return -EINVAL;
-		}
-		addr.station = saddr->addr.station;
-		addr.net = saddr->addr.net;
-		port = saddr->port;
-		cb = saddr->cb;
-	}
+        if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+                mutex_unlock(&econet_mutex);
+                return -EINVAL;
+        }
+        addr.station = saddr->addr.station;
+        addr.net = saddr->addr.net;
+        port = saddr->port;
+        cb = saddr->cb;
 
 	/* Look for a device with the right network number. */
 	dev = net2dev_map[addr.net];
@@ -327,17 +319,17 @@
 		}
 	}
 
-	if (len + 15 > dev->mtu) {
-		mutex_unlock(&econet_mutex);
-		return -EMSGSIZE;
-	}
-
 	if (dev->type == ARPHRD_ECONET) {
 		/* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
 		unsigned short proto = 0;
 		int res;
 
+		if (len + 15 > dev->mtu) {
+			mutex_unlock(&econet_mutex);
+			return -EMSGSIZE;
+		}
+
 		dev_hold(dev);
 
 		skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
@@ -350,7 +342,6 @@
 
 		eb = (struct ec_cb *)&skb->cb;
 
-		/* BUG: saddr may be NULL */
 		eb->cookie = saddr->cookie;
 		eb->sec = *saddr;
 		eb->sent = ec_tx_done;
@@ -414,6 +405,11 @@
 		return -ENETDOWN;		/* No socket - can't send */
 	}
 
+	if (len > 32768) {
+		err = -E2BIG;
+		goto error;
+	}
+
 	/* Make up a UDP datagram and hand it off to some higher intellect. */
 
 	memset(&udpdest, 0, sizeof(udpdest));
@@ -438,43 +434,33 @@
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
+	memset(&ah, 0, sizeof(ah));
 	ah.port = port;
 	ah.cb = cb & 0x7f;
 	ah.code = 2;		/* magic */
-	ah.pad = 0;
 
 	/* tack our header on the front of the iovec */
 	size = sizeof(struct aunhdr);
-	/*
-	 * XXX: that is b0rken.  We can't mix userland and kernel pointers
-	 * in iovec, since on a lot of platforms copy_from_user() will
-	 * *not* work with the kernel and userland ones at the same time,
-	 * regardless of what we do with set_fs().  And we are talking about
-	 * econet-over-ethernet here, so "it's only ARM anyway" doesn't
-	 * apply.  Any suggestions on fixing that code?		-- AV
-	 */
 	iov[0].iov_base = (void *)&ah;
 	iov[0].iov_len = size;
-	for (i = 0; i < msg->msg_iovlen; i++) {
-		void __user *base = msg->msg_iov[i].iov_base;
-		size_t len = msg->msg_iov[i].iov_len;
-		/* Check it now since we switch to KERNEL_DS later. */
-		if (!access_ok(VERIFY_READ, base, len)) {
-			mutex_unlock(&econet_mutex);
-			return -EFAULT;
-		}
-		iov[i+1].iov_base = base;
-		iov[i+1].iov_len = len;
-		size += len;
+
+	userbuf = vmalloc(len);
+	if (userbuf == NULL) {
+		err = -ENOMEM;
+		goto error;
 	}
 
+	iov[1].iov_base = userbuf;
+	iov[1].iov_len = len;
+	err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
+	if (err)
+		goto error_free_buf;
+
 	/* Get a skbuff (no data, just holds our cb information) */
 	if ((skb = sock_alloc_send_skb(sk, 0,
 				       msg->msg_flags & MSG_DONTWAIT,
-				       &err)) == NULL) {
-		mutex_unlock(&econet_mutex);
-		return err;
-	}
+				       &err)) == NULL)
+		goto error_free_buf;
 
 	eb = (struct ec_cb *)&skb->cb;
 
@@ -490,7 +476,7 @@
 	udpmsg.msg_name = (void *)&udpdest;
 	udpmsg.msg_namelen = sizeof(udpdest);
 	udpmsg.msg_iov = &iov[0];
-	udpmsg.msg_iovlen = msg->msg_iovlen + 1;
+	udpmsg.msg_iovlen = 2;
 	udpmsg.msg_control = NULL;
 	udpmsg.msg_controllen = 0;
 	udpmsg.msg_flags=0;
@@ -498,9 +484,13 @@
 	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
 	err = sock_sendmsg(udpsock, &udpmsg, size);
 	set_fs(oldfs);
+
+error_free_buf:
+	vfree(userbuf);
 #else
 	err = -EPROTOTYPE;
 #endif
+	error:
 	mutex_unlock(&econet_mutex);
 
 	return err;
@@ -669,6 +659,9 @@
 	err = 0;
 	switch (cmd) {
 	case SIOCSIFADDR:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
 		edev = dev->ec_ptr;
 		if (edev == NULL) {
 			/* Magic up a new one. */
@@ -851,8 +844,12 @@
 	struct iphdr *ip = ip_hdr(skb);
 	unsigned char stn = ntohl(ip->saddr) & 0xff;
 	struct sock *sk;
+	struct dst_entry *dst = skb_dst(skb);
+	struct ec_device *edev = NULL;
 	struct sk_buff *newskb;
-	struct ec_device *edev = skb->dev->ec_ptr;
+
+	if (dst)
+		edev = dst->dev->ec_ptr;
 
 	if (! edev)
 		goto bad;
--- linux-ec2-2.6.32.orig/net/decnet/af_decnet.c
+++ linux-ec2-2.6.32/net/decnet/af_decnet.c
@@ -1555,6 +1555,8 @@
 			if (r_len > sizeof(struct linkinfo_dn))
 				r_len = sizeof(struct linkinfo_dn);
 
+			memset(&link, 0, sizeof(link));
+
 			switch(sock->state) {
 				case SS_CONNECTING:
 					link.idn_linkstate = LL_CONNECTING;
--- linux-ec2-2.6.32.orig/net/x25/x25_facilities.c
+++ linux-ec2-2.6.32/net/x25/x25_facilities.c
@@ -35,7 +35,7 @@
 		struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
 {
 	unsigned char *p = skb->data;
-	unsigned int len = *p++;
+	unsigned int len;
 
 	*vc_fac_mask = 0;
 
@@ -50,9 +50,19 @@
 	memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
 	memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
 
+	if (skb->len < 1)
+		return 0;
+
+	len = *p++;
+
+	if (len >= skb->len)
+		return -1;
+
 	while (len > 0) {
 		switch (*p & X25_FAC_CLASS_MASK) {
 		case X25_FAC_CLASS_A:
+			if (len < 2)
+				return 0;
 			switch (*p) {
 			case X25_FAC_REVERSE:
 				if((p[1] & 0x81) == 0x81) {
@@ -96,6 +106,8 @@
 			len -= 2;
 			break;
 		case X25_FAC_CLASS_B:
+			if (len < 3)
+				return 0;
 			switch (*p) {
 			case X25_FAC_PACKET_SIZE:
 				facilities->pacsize_in  = p[1];
@@ -117,6 +129,8 @@
 			len -= 3;
 			break;
 		case X25_FAC_CLASS_C:
+			if (len < 4)
+				return 0;
 			printk(KERN_DEBUG "X.25: unknown facility %02X, "
 			       "values %02X, %02X, %02X\n",
 			       p[0], p[1], p[2], p[3]);
@@ -124,26 +138,26 @@
 			len -= 4;
 			break;
 		case X25_FAC_CLASS_D:
+			if (len < p[1] + 2)
+				return 0;
 			switch (*p) {
 			case X25_FAC_CALLING_AE:
-				if (p[1] > X25_MAX_DTE_FACIL_LEN)
-					break;
+				if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1)
+					return 0;
 				dte_facs->calling_len = p[2];
 				memcpy(dte_facs->calling_ae, &p[3], p[1] - 1);
 				*vc_fac_mask |= X25_MASK_CALLING_AE;
 				break;
 			case X25_FAC_CALLED_AE:
-				if (p[1] > X25_MAX_DTE_FACIL_LEN)
-					break;
+				if (p[1] > X25_MAX_DTE_FACIL_LEN || p[1] <= 1)
+					return 0;
 				dte_facs->called_len = p[2];
 				memcpy(dte_facs->called_ae, &p[3], p[1] - 1);
 				*vc_fac_mask |= X25_MASK_CALLED_AE;
 				break;
 			default:
 				printk(KERN_DEBUG "X.25: unknown facility %02X,"
-					"length %d, values %02X, %02X, "
-					"%02X, %02X\n",
-					p[0], p[1], p[2], p[3], p[4], p[5]);
+					"length %d\n", p[0], p[1]);
 				break;
 			}
 			len -= p[1] + 2;
@@ -247,6 +261,8 @@
 	memcpy(new, ours, sizeof(*new));
 
 	len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
+	if (len < 0)
+		return len;
 
 	/*
 	 *	They want reverse charging, we won't accept it.
--- linux-ec2-2.6.32.orig/net/x25/x25_link.c
+++ linux-ec2-2.6.32/net/x25/x25_link.c
@@ -391,8 +391,12 @@
 	write_lock_bh(&x25_neigh_list_lock);
 
 	list_for_each_safe(entry, tmp, &x25_neigh_list) {
+		struct net_device *dev;
+
 		nb = list_entry(entry, struct x25_neigh, node);
+		dev = nb->dev;
 		__x25_remove_neigh(nb);
+		dev_put(dev);
 	}
 	write_unlock_bh(&x25_neigh_list_lock);
 }
--- linux-ec2-2.6.32.orig/net/x25/x25_in.c
+++ linux-ec2-2.6.32/net/x25/x25_in.c
@@ -89,6 +89,7 @@
 static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
 {
 	struct x25_address source_addr, dest_addr;
+	int len;
 
 	switch (frametype) {
 		case X25_CALL_ACCEPTED: {
@@ -106,11 +107,19 @@
 			 *	Parse the data in the frame.
 			 */
 			skb_pull(skb, X25_STD_MIN_LEN);
-			skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
-			skb_pull(skb,
-				 x25_parse_facilities(skb, &x25->facilities,
+
+			len = x25_parse_address_block(skb, &source_addr,
+						&dest_addr);
+			if (len > 0)
+				skb_pull(skb, len);
+
+			len = x25_parse_facilities(skb, &x25->facilities,
 						&x25->dte_facilities,
-						&x25->vc_facil_mask));
+						&x25->vc_facil_mask);
+			if (len > 0)
+				skb_pull(skb, len);
+			else
+				return -1;
 			/*
 			 *	Copy any Call User Data.
 			 */
--- linux-ec2-2.6.32.orig/net/x25/af_x25.c
+++ linux-ec2-2.6.32/net/x25/af_x25.c
@@ -81,6 +81,41 @@
 };
 #endif
 
+
+int x25_parse_address_block(struct sk_buff *skb,
+		struct x25_address *called_addr,
+		struct x25_address *calling_addr)
+{
+	unsigned char len;
+	int needed;
+	int rc;
+
+	if (skb->len < 1) {
+		/* packet has no address block */
+		rc = 0;
+		goto empty;
+	}
+
+	len = *skb->data;
+	needed = 1 + (len >> 4) + (len & 0x0f);
+
+	if (skb->len < needed) {
+		/* packet is too short to hold the addresses it claims
+		   to hold */
+		rc = -1;
+		goto empty;
+	}
+
+	return x25_addr_ntoa(skb->data, called_addr, calling_addr);
+
+empty:
+	*called_addr->x25_addr = 0;
+	*calling_addr->x25_addr = 0;
+
+	return rc;
+}
+
+
 int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
 		  struct x25_address *calling_addr)
 {
@@ -871,16 +906,26 @@
 	/*
 	 *	Extract the X.25 addresses and convert them to ASCII strings,
 	 *	and remove them.
+	 *
+	 *	Address block is mandatory in call request packets
 	 */
-	addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr);
+	addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr);
+	if (addr_len <= 0)
+		goto out_clear_request;
 	skb_pull(skb, addr_len);
 
 	/*
 	 *	Get the length of the facilities, skip past them for the moment
 	 *	get the call user data because this is needed to determine
 	 *	the correct listener
+	 *
+	 *	Facilities length is mandatory in call request packets
 	 */
+	if (skb->len < 1)
+		goto out_clear_request;
 	len = skb->data[0] + 1;
+	if (skb->len < len)
+		goto out_clear_request;
 	skb_pull(skb,len);
 
 	/*
--- linux-ec2-2.6.32.orig/net/tipc/socket.c
+++ linux-ec2-2.6.32/net/tipc/socket.c
@@ -393,6 +393,7 @@
 	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
 
+	memset(addr, 0, sizeof(*addr));
 	if (peer) {
 		if ((sock->state != SS_CONNECTED) &&
 			((peer != 2) || (sock->state != SS_DISCONNECTING)))
--- linux-ec2-2.6.32.orig/net/tipc/bearer.h
+++ linux-ec2-2.6.32/net/tipc/bearer.h
@@ -114,7 +114,7 @@
 
 struct link;
 
-extern struct bearer *tipc_bearers;
+extern struct bearer tipc_bearers[];
 
 void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
 struct sk_buff *tipc_media_get_names(void);
--- linux-ec2-2.6.32.orig/net/tipc/net.c
+++ linux-ec2-2.6.32/net/tipc/net.c
@@ -116,7 +116,8 @@
 */
 
 DEFINE_RWLOCK(tipc_net_lock);
-struct network tipc_net = { NULL };
+struct _zone *tipc_zones[256] = { NULL, };
+struct network tipc_net = { tipc_zones };
 
 struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref)
 {
@@ -158,28 +159,12 @@
 	}
 }
 
-static int net_init(void)
-{
-	memset(&tipc_net, 0, sizeof(tipc_net));
-	tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC);
-	if (!tipc_net.zones) {
-		return -ENOMEM;
-	}
-	return 0;
-}
-
 static void net_stop(void)
 {
 	u32 z_num;
 
-	if (!tipc_net.zones)
-		return;
-
-	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
+	for (z_num = 1; z_num <= tipc_max_zones; z_num++)
 		tipc_zone_delete(tipc_net.zones[z_num]);
-	}
-	kfree(tipc_net.zones);
-	tipc_net.zones = NULL;
 }
 
 static void net_route_named_msg(struct sk_buff *buf)
@@ -282,9 +267,7 @@
 	tipc_named_reinit();
 	tipc_port_reinit();
 
-	if ((res = tipc_bearer_init()) ||
-	    (res = net_init()) ||
-	    (res = tipc_cltr_init()) ||
+	if ((res = tipc_cltr_init()) ||
 	    (res = tipc_bclink_init())) {
 		return res;
 	}
--- linux-ec2-2.6.32.orig/net/tipc/bearer.c
+++ linux-ec2-2.6.32/net/tipc/bearer.c
@@ -45,10 +45,10 @@
 
 #define MAX_ADDR_STR 32
 
-static struct media *media_list = NULL;
+static struct media media_list[MAX_MEDIA];
 static u32 media_count = 0;
 
-struct bearer *tipc_bearers = NULL;
+struct bearer tipc_bearers[MAX_BEARERS];
 
 /**
  * media_name_valid - validate media name
@@ -108,9 +108,11 @@
 	int res = -EINVAL;
 
 	write_lock_bh(&tipc_net_lock);
-	if (!media_list)
-		goto exit;
 
+	if (tipc_mode != TIPC_NET_MODE) {
+		warn("Media <%s> rejected, not in networked mode yet\n", name);
+		goto exit;
+	}
 	if (!media_name_valid(name)) {
 		warn("Media <%s> rejected, illegal name\n", name);
 		goto exit;
@@ -660,33 +662,10 @@
 
 
 
-int tipc_bearer_init(void)
-{
-	int res;
-
-	write_lock_bh(&tipc_net_lock);
-	tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC);
-	media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC);
-	if (tipc_bearers && media_list) {
-		res = 0;
-	} else {
-		kfree(tipc_bearers);
-		kfree(media_list);
-		tipc_bearers = NULL;
-		media_list = NULL;
-		res = -ENOMEM;
-	}
-	write_unlock_bh(&tipc_net_lock);
-	return res;
-}
-
 void tipc_bearer_stop(void)
 {
 	u32 i;
 
-	if (!tipc_bearers)
-		return;
-
 	for (i = 0; i < MAX_BEARERS; i++) {
 		if (tipc_bearers[i].active)
 			tipc_bearers[i].publ.blocked = 1;
@@ -695,10 +674,6 @@
 		if (tipc_bearers[i].active)
 			bearer_disable(tipc_bearers[i].publ.name);
 	}
-	kfree(tipc_bearers);
-	kfree(media_list);
-	tipc_bearers = NULL;
-	media_list = NULL;
 	media_count = 0;
 }
 
--- linux-ec2-2.6.32.orig/net/irda/iriap.c
+++ linux-ec2-2.6.32/net/irda/iriap.c
@@ -501,7 +501,8 @@
 		IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
 
 		/* Make sure the string is null-terminated */
-		fp[n+value_len] = 0x00;
+		if (n + value_len < skb->len)
+			fp[n + value_len] = 0x00;
 		IRDA_DEBUG(4, "Got string %s\n", fp+n);
 
 		/* Will truncate to IAS_MAX_STRING bytes */
@@ -654,10 +655,16 @@
 	n = 1;
 
 	name_len = fp[n++];
+
+	IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
+
 	memcpy(name, fp+n, name_len); n+=name_len;
 	name[name_len] = '\0';
 
 	attr_len = fp[n++];
+
+	IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
+
 	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
--- linux-ec2-2.6.32.orig/net/irda/af_irda.c
+++ linux-ec2-2.6.32/net/irda/af_irda.c
@@ -810,8 +810,8 @@
 
 	err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
 	if (err < 0) {
-		kfree(self->ias_obj->name);
-		kfree(self->ias_obj);
+		irias_delete_object(self->ias_obj);
+		self->ias_obj = NULL;
 		return err;
 	}
 
@@ -2164,6 +2164,14 @@
 
 	switch (optname) {
 	case IRLMP_ENUMDEVICES:
+
+		/* Offset to first device entry */
+		offset = sizeof(struct irda_device_list) -
+			sizeof(struct irda_device_info);
+
+		if (len < offset)
+			return -EINVAL;
+
 		/* Ask lmp for the current discovery log */
 		discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
 						    self->nslots);
@@ -2173,15 +2181,9 @@
 		err = 0;
 
 		/* Write total list length back to client */
-		if (copy_to_user(optval, &list,
-				 sizeof(struct irda_device_list) -
-				 sizeof(struct irda_device_info)))
+		if (copy_to_user(optval, &list, offset))
 			err = -EFAULT;
 
-		/* Offset to first device entry */
-		offset = sizeof(struct irda_device_list) -
-			sizeof(struct irda_device_info);
-
 		/* Copy the list itself - watch for overflow */
 		if(list.len > 2048)
 		{
--- linux-ec2-2.6.32.orig/net/irda/parameters.c
+++ linux-ec2-2.6.32/net/irda/parameters.c
@@ -298,6 +298,8 @@
 
 	p.pi = pi;     /* In case handler needs to know */
 	p.pl = buf[1]; /* Extract length of value */
+	if (p.pl > 32)
+		p.pl = 32;
 
 	IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d\n", __func__,
 		   p.pi, p.pl);
@@ -318,7 +320,7 @@
 		   (__u8) str[0], (__u8) str[1]);
 
 	/* Null terminate string */
-	str[p.pl+1] = '\0';
+	str[p.pl] = '\0';
 
 	p.pv.c = str; /* Handler will need to take a copy */
 
--- linux-ec2-2.6.32.orig/net/irda/irnet/irnet_ppp.c
+++ linux-ec2-2.6.32/net/irda/irnet/irnet_ppp.c
@@ -106,6 +106,9 @@
 	      while(isspace(start[length - 1]))
 		length--;
 
+	      DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
+		     -EINVAL, CTRL_ERROR, "Invalid nickname.\n");
+
 	      /* Copy the name for later reuse */
 	      memcpy(ap->rname, start + 5, length - 5);
 	      ap->rname[length - 5] = '\0';
--- linux-ec2-2.6.32.orig/net/irda/irlan/irlan_common.c
+++ linux-ec2-2.6.32/net/irda/irlan/irlan_common.c
@@ -1101,7 +1101,7 @@
 	memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
 	le16_to_cpus(&val_len); n+=2;
 
-	if (val_len > 1016) {
+	if (val_len >= 1016) {
 		IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
 		return -RSP_INVALID_COMMAND_FORMAT;
 	}
--- linux-ec2-2.6.32.orig/net/ax25/ax25_out.c
+++ linux-ec2-2.6.32/net/ax25/ax25_out.c
@@ -92,6 +92,12 @@
 #endif
 	}
 
+	/*
+	 * There is one ref for the state machine; a caller needs
+	 * one more to put it back, just like with the existing one.
+	 */
+	ax25_cb_hold(ax25);
+
 	ax25_cb_add(ax25);
 
 	ax25->state = AX25_STATE_1;
--- linux-ec2-2.6.32.orig/net/ax25/af_ax25.c
+++ linux-ec2-2.6.32/net/ax25/af_ax25.c
@@ -1391,6 +1391,7 @@
 	ax25_cb *ax25;
 	int err = 0;
 
+	memset(fsa, 0, sizeof(*fsa));
 	lock_sock(sk);
 	ax25 = ax25_sk(sk);
 
@@ -1402,7 +1403,6 @@
 
 		fsa->fsa_ax25.sax25_family = AF_AX25;
 		fsa->fsa_ax25.sax25_call   = ax25->dest_addr;
-		fsa->fsa_ax25.sax25_ndigis = 0;
 
 		if (ax25->digipeat != NULL) {
 			ndigi = ax25->digipeat->ndigi;
--- linux-ec2-2.6.32.orig/net/packet/af_packet.c
+++ linux-ec2-2.6.32/net/packet/af_packet.c
@@ -1028,8 +1028,20 @@
 
 		status = TP_STATUS_SEND_REQUEST;
 		err = dev_queue_xmit(skb);
-		if (unlikely(err > 0 && (err = net_xmit_errno(err)) != 0))
-			goto out_xmit;
+		if (unlikely(err > 0)) {
+			err = net_xmit_errno(err);
+			if (err && __packet_get_status(po, ph) ==
+				   TP_STATUS_AVAILABLE) {
+				/* skb was destructed already */
+				skb = NULL;
+				goto out_status;
+			}
+			/*
+			 * skb was dropped but not destructed yet;
+			 * let's treat it like congestion or err < 0
+			 */
+			err = 0;
+		}
 		packet_increment_head(&po->tx_ring);
 		len_sum += tp_len;
 	} while (likely((ph != NULL) || ((!(msg->msg_flags & MSG_DONTWAIT))
@@ -1039,9 +1051,6 @@
 	err = len_sum;
 	goto out_put;
 
-out_xmit:
-	skb->destructor = sock_wfree;
-	atomic_dec(&po->tx_ring.pending);
 out_status:
 	__packet_set_status(po, ph, status);
 	kfree_skb(skb);
@@ -1517,7 +1526,7 @@
 	uaddr->sa_family = AF_PACKET;
 	dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex);
 	if (dev) {
-		strlcpy(uaddr->sa_data, dev->name, 15);
+		strncpy(uaddr->sa_data, dev->name, 14);
 		dev_put(dev);
 	} else
 		memset(uaddr->sa_data, 0, 14);
@@ -1540,6 +1549,7 @@
 	sll->sll_family = AF_PACKET;
 	sll->sll_ifindex = po->ifindex;
 	sll->sll_protocol = po->num;
+	sll->sll_pkttype = 0;
 	dev = dev_get_by_index(sock_net(sk), po->ifindex);
 	if (dev) {
 		sll->sll_hatype = dev->type;
--- linux-ec2-2.6.32.orig/net/llc/af_llc.c
+++ linux-ec2-2.6.32/net/llc/af_llc.c
@@ -977,7 +977,8 @@
 {
 	struct sock *sk = sock->sk;
 	struct llc_sock *llc = llc_sk(sk);
-	int rc = -EINVAL, opt;
+	unsigned int opt;
+	int rc = -EINVAL;
 
 	lock_sock(sk);
 	if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
--- linux-ec2-2.6.32.orig/net/sunrpc/rpc_pipe.c
+++ linux-ec2-2.6.32/net/sunrpc/rpc_pipe.c
@@ -47,7 +47,7 @@
 		return;
 	do {
 		msg = list_entry(head->next, struct rpc_pipe_msg, list);
-		list_del(&msg->list);
+		list_del_init(&msg->list);
 		msg->errno = err;
 		destroy_msg(msg);
 	} while (!list_empty(head));
@@ -207,7 +207,7 @@
 	if (msg != NULL) {
 		spin_lock(&inode->i_lock);
 		msg->errno = -EAGAIN;
-		list_del(&msg->list);
+		list_del_init(&msg->list);
 		spin_unlock(&inode->i_lock);
 		rpci->ops->destroy_msg(msg);
 	}
@@ -267,7 +267,7 @@
 	if (res < 0 || msg->len == msg->copied) {
 		filp->private_data = NULL;
 		spin_lock(&inode->i_lock);
-		list_del(&msg->list);
+		list_del_init(&msg->list);
 		spin_unlock(&inode->i_lock);
 		rpci->ops->destroy_msg(msg);
 	}
@@ -587,6 +587,8 @@
 	struct dentry *dentry;
 
 	dentry = __rpc_lookup_create(parent, name);
+	if (IS_ERR(dentry))
+		return dentry;
 	if (dentry->d_inode == NULL)
 		return dentry;
 	dput(dentry);
--- linux-ec2-2.6.32.orig/net/sunrpc/svcsock.c
+++ linux-ec2-2.6.32/net/sunrpc/svcsock.c
@@ -968,6 +968,7 @@
 	return len;
  err_delete:
 	set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+	svc_xprt_received(&svsk->sk_xprt);
  err_again:
 	return -EAGAIN;
 }
--- linux-ec2-2.6.32.orig/net/sunrpc/cache.c
+++ linux-ec2-2.6.32/net/sunrpc/cache.c
@@ -1234,8 +1234,10 @@
 	if (!cd || !try_module_get(cd->owner))
 		return -EACCES;
 	han = __seq_open_private(file, &cache_content_op, sizeof(*han));
-	if (han == NULL)
+	if (han == NULL) {
+		module_put(cd->owner);
 		return -ENOMEM;
+	}
 
 	han->cd = cd;
 	return 0;
--- linux-ec2-2.6.32.orig/net/sunrpc/sched.c
+++ linux-ec2-2.6.32/net/sunrpc/sched.c
@@ -627,14 +627,12 @@
 			save_callback = task->tk_callback;
 			task->tk_callback = NULL;
 			save_callback(task);
-		}
-
-		/*
-		 * Perform the next FSM step.
-		 * tk_action may be NULL when the task has been killed
-		 * by someone else.
-		 */
-		if (!RPC_IS_QUEUED(task)) {
+		} else {
+			/*
+			 * Perform the next FSM step.
+			 * tk_action may be NULL when the task has been killed
+			 * by someone else.
+			 */
 			if (task->tk_action == NULL)
 				break;
 			task->tk_action(task);
--- linux-ec2-2.6.32.orig/net/sunrpc/svcauth_unix.c
+++ linux-ec2-2.6.32/net/sunrpc/svcauth_unix.c
@@ -655,23 +655,25 @@
 		return NULL;
 }
 
-static int unix_gid_find(uid_t uid, struct group_info **gip,
-			 struct svc_rqst *rqstp)
+static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
 {
-	struct unix_gid *ug = unix_gid_lookup(uid);
+	struct unix_gid *ug;
+	struct group_info *gi;
+	int ret;
+
+	ug = unix_gid_lookup(uid);
 	if (!ug)
-		return -EAGAIN;
-	switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
+		return ERR_PTR(-EAGAIN);
+	ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
+	switch (ret) {
 	case -ENOENT:
-		*gip = NULL;
-		return 0;
+		return ERR_PTR(-ENOENT);
 	case 0:
-		*gip = ug->gi;
-		get_group_info(*gip);
+		gi = get_group_info(ug->gi);
 		cache_put(&ug->h, &unix_gid_cache);
-		return 0;
+		return gi;
 	default:
-		return -EAGAIN;
+		return ERR_PTR(-EAGAIN);
 	}
 }
 
@@ -681,6 +683,8 @@
 	struct sockaddr_in *sin;
 	struct sockaddr_in6 *sin6, sin6_storage;
 	struct ip_map *ipm;
+	struct group_info *gi;
+	struct svc_cred *cred = &rqstp->rq_cred;
 
 	switch (rqstp->rq_addr.ss_family) {
 	case AF_INET:
@@ -722,6 +726,17 @@
 			ip_map_cached_put(rqstp, ipm);
 			break;
 	}
+
+	gi = unix_gid_find(cred->cr_uid, rqstp);
+	switch (PTR_ERR(gi)) {
+	case -EAGAIN:
+		return SVC_DROP;
+	case -ENOENT:
+		break;
+	default:
+		put_group_info(cred->cr_group_info);
+		cred->cr_group_info = gi;
+	}
 	return SVC_OK;
 }
 
@@ -818,19 +833,11 @@
 	slen = svc_getnl(argv);			/* gids length */
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
-	if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
-	    == -EAGAIN)
+	cred->cr_group_info = groups_alloc(slen);
+	if (cred->cr_group_info == NULL)
 		return SVC_DROP;
-	if (cred->cr_group_info == NULL) {
-		cred->cr_group_info = groups_alloc(slen);
-		if (cred->cr_group_info == NULL)
-			return SVC_DROP;
-		for (i = 0; i < slen; i++)
-			GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
-	} else {
-		for (i = 0; i < slen ; i++)
-			svc_getnl(argv);
-	}
+	for (i = 0; i < slen; i++)
+		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
--- linux-ec2-2.6.32.orig/net/sunrpc/svc_xprt.c
+++ linux-ec2-2.6.32/net/sunrpc/svc_xprt.c
@@ -209,6 +209,7 @@
 	spin_lock(&svc_xprt_class_lock);
 	list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
 		struct svc_xprt *newxprt;
+		unsigned short newport;
 
 		if (strcmp(xprt_name, xcl->xcl_name))
 			continue;
@@ -227,8 +228,9 @@
 		spin_lock_bh(&serv->sv_lock);
 		list_add(&newxprt->xpt_list, &serv->sv_permsocks);
 		spin_unlock_bh(&serv->sv_lock);
+		newport = svc_xprt_local_port(newxprt);
 		clear_bit(XPT_BUSY, &newxprt->xpt_flags);
-		return svc_xprt_local_port(newxprt);
+		return newport;
 	}
  err:
 	spin_unlock(&svc_xprt_class_lock);
@@ -430,8 +432,13 @@
 {
 	BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
 	xprt->xpt_pool = NULL;
+	/* As soon as we clear busy, the xprt could be closed and
+	 * 'put', so we need a reference to call svc_xprt_enqueue with:
+	 */
+	svc_xprt_get(xprt);
 	clear_bit(XPT_BUSY, &xprt->xpt_flags);
 	svc_xprt_enqueue(xprt);
+	svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_received);
 
@@ -711,7 +718,10 @@
 	spin_unlock_bh(&pool->sp_lock);
 
 	len = 0;
-	if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
+	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+		dprintk("svc_recv: found XPT_CLOSE\n");
+		svc_delete_xprt(xprt);
+	} else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
 		struct svc_xprt *newxpt;
 		newxpt = xprt->xpt_ops->xpo_accept(xprt);
 		if (newxpt) {
@@ -737,7 +747,7 @@
 			svc_xprt_received(newxpt);
 		}
 		svc_xprt_received(xprt);
-	} else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+	} else {
 		dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
 			rqstp, pool->sp_id, xprt,
 			atomic_read(&xprt->xpt_ref.refcount));
@@ -750,11 +760,6 @@
 		dprintk("svc: got len=%d\n", len);
 	}
 
-	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
-		dprintk("svc_recv: found XPT_CLOSE\n");
-		svc_delete_xprt(xprt);
-	}
-
 	/* No data, incomplete (TCP) read, or accept() */
 	if (len == 0 || len == -EAGAIN) {
 		rqstp->rq_res.len = 0;
@@ -900,11 +905,8 @@
 	if (test_bit(XPT_TEMP, &xprt->xpt_flags))
 		serv->sv_tmpcnt--;
 
-	for (dr = svc_deferred_dequeue(xprt); dr;
-	     dr = svc_deferred_dequeue(xprt)) {
-		svc_xprt_put(xprt);
+	while ((dr = svc_deferred_dequeue(xprt)) != NULL)
 		kfree(dr);
-	}
 
 	svc_xprt_put(xprt);
 	spin_unlock_bh(&serv->sv_lock);
--- linux-ec2-2.6.32.orig/net/sunrpc/xprtsock.c
+++ linux-ec2-2.6.32/net/sunrpc/xprtsock.c
@@ -238,7 +238,8 @@
 	 * State of TCP reply receive
 	 */
 	__be32			tcp_fraghdr,
-				tcp_xid;
+				tcp_xid,
+				tcp_calldir;
 
 	u32			tcp_offset,
 				tcp_reclen;
@@ -742,6 +743,8 @@
 	if (sk == NULL)
 		return;
 
+	transport->srcport = 0;
+
 	write_lock_bh(&sk->sk_callback_lock);
 	transport->inet = NULL;
 	transport->sock = NULL;
@@ -961,7 +964,7 @@
 {
 	size_t len, used;
 	u32 offset;
-	__be32	calldir;
+	char *p;
 
 	/*
 	 * We want transport->tcp_offset to be 8 at the end of this routine
@@ -970,26 +973,33 @@
 	 * transport->tcp_offset is 4 (after having already read the xid).
 	 */
 	offset = transport->tcp_offset - sizeof(transport->tcp_xid);
-	len = sizeof(calldir) - offset;
+	len = sizeof(transport->tcp_calldir) - offset;
 	dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)\n", len);
-	used = xdr_skb_read_bits(desc, &calldir, len);
+	p = ((char *) &transport->tcp_calldir) + offset;
+	used = xdr_skb_read_bits(desc, p, len);
 	transport->tcp_offset += used;
 	if (used != len)
 		return;
 	transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
-	transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
-	transport->tcp_flags |= TCP_RCV_COPY_DATA;
 	/*
 	 * We don't yet have the XDR buffer, so we will write the calldir
 	 * out after we get the buffer from the 'struct rpc_rqst'
 	 */
-	if (ntohl(calldir) == RPC_REPLY)
+	switch (ntohl(transport->tcp_calldir)) {
+	case RPC_REPLY:
+		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+		transport->tcp_flags |= TCP_RCV_COPY_DATA;
 		transport->tcp_flags |= TCP_RPC_REPLY;
-	else
+		break;
+	case RPC_CALL:
+		transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
+		transport->tcp_flags |= TCP_RCV_COPY_DATA;
 		transport->tcp_flags &= ~TCP_RPC_REPLY;
-	dprintk("RPC:       reading %s CALL/REPLY flag %08x\n",
-			(transport->tcp_flags & TCP_RPC_REPLY) ?
-				"reply for" : "request with", calldir);
+		break;
+	default:
+		dprintk("RPC:       invalid request message type\n");
+		xprt_force_disconnect(&transport->xprt);
+	}
 	xs_tcp_check_fraghdr(transport);
 }
 
@@ -1009,12 +1019,10 @@
 		/*
 		 * Save the RPC direction in the XDR buffer
 		 */
-		__be32	calldir = transport->tcp_flags & TCP_RPC_REPLY ?
-					htonl(RPC_REPLY) : 0;
-
 		memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
-			&calldir, sizeof(calldir));
-		transport->tcp_copied += sizeof(calldir);
+			&transport->tcp_calldir,
+			sizeof(transport->tcp_calldir));
+		transport->tcp_copied += sizeof(transport->tcp_calldir);
 		transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
 	}
 
@@ -1335,10 +1343,11 @@
 	if (!(xprt = xprt_from_sock(sk)))
 		goto out;
 	dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
-	dprintk("RPC:       state %x conn %d dead %d zapped %d\n",
+	dprintk("RPC:       state %x conn %d dead %d zapped %d sk_shutdown %d\n",
 			sk->sk_state, xprt_connected(xprt),
 			sock_flag(sk, SOCK_DEAD),
-			sock_flag(sk, SOCK_ZAPPED));
+			sock_flag(sk, SOCK_ZAPPED),
+			sk->sk_shutdown);
 
 	switch (sk->sk_state) {
 	case TCP_ESTABLISHED:
@@ -1809,10 +1818,25 @@
 {
 	unsigned int state = transport->inet->sk_state;
 
-	if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED)
-		return;
-	if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT))
-		return;
+	if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) {
+		/* we don't need to abort the connection if the socket
+		 * hasn't undergone a shutdown
+		 */
+		if (transport->inet->sk_shutdown == 0)
+			return;
+		dprintk("RPC:       %s: TCP_CLOSEd and sk_shutdown set to %d\n",
+				__func__, transport->inet->sk_shutdown);
+	}
+	if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) {
+		/* we don't need to abort the connection if the socket
+		 * hasn't undergone a shutdown
+		 */
+		if (transport->inet->sk_shutdown == 0)
+			return;
+		dprintk("RPC:       %s: ESTABLISHED/SYN_SENT "
+				"sk_shutdown set to %d\n",
+				__func__, transport->inet->sk_shutdown);
+	}
 	xs_abort_connection(xprt, transport);
 }
 
@@ -1926,6 +1950,11 @@
 	case -EALREADY:
 		xprt_clear_connecting(xprt);
 		return;
+	case -EINVAL:
+		/* Happens, for instance, if the user specified a link
+		 * local IPv6 address without a scope-id.
+		 */
+		goto out;
 	}
 out_eagain:
 	status = -EAGAIN;
--- linux-ec2-2.6.32.orig/net/sunrpc/auth_gss/gss_mech_switch.c
+++ linux-ec2-2.6.32/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -252,7 +252,7 @@
 		       struct gss_ctx		**ctx_id)
 {
 	if (!(*ctx_id = kzalloc(sizeof(**ctx_id), GFP_KERNEL)))
-		return GSS_S_FAILURE;
+		return -ENOMEM;
 	(*ctx_id)->mech_type = gss_mech_get(mech);
 
 	return mech->gm_ops
--- linux-ec2-2.6.32.orig/net/sunrpc/auth_gss/auth_gss.c
+++ linux-ec2-2.6.32/net/sunrpc/auth_gss/auth_gss.c
@@ -485,7 +485,7 @@
 	dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
 								cred->cr_uid);
 	gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
-	if (IS_ERR(gss_msg) == -EAGAIN) {
+	if (PTR_ERR(gss_msg) == -EAGAIN) {
 		/* XXX: warning on the first, under the assumption we
 		 * shouldn't normally hit this case on a refresh. */
 		warn_gssd();
@@ -644,7 +644,22 @@
 	p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
 	if (IS_ERR(p)) {
 		err = PTR_ERR(p);
-		gss_msg->msg.errno = (err == -EAGAIN) ? -EAGAIN : -EACCES;
+		switch (err) {
+		case -EACCES:
+			gss_msg->msg.errno = err;
+			err = mlen;
+			break;
+		case -EFAULT:
+		case -ENOMEM:
+		case -EINVAL:
+		case -ENOSYS:
+			gss_msg->msg.errno = -EAGAIN;
+			break;
+		default:
+			printk(KERN_CRIT "%s: bad return from "
+				"gss_fill_context: %ld\n", __func__, err);
+			BUG();
+		}
 		goto err_release_msg;
 	}
 	gss_msg->ctx = gss_get_ctx(ctx);
@@ -702,17 +717,18 @@
 	struct rpc_inode *rpci = RPC_I(inode);
 	struct gss_upcall_msg *gss_msg;
 
+restart:
 	spin_lock(&inode->i_lock);
-	while (!list_empty(&rpci->in_downcall)) {
+	list_for_each_entry(gss_msg, &rpci->in_downcall, list) {
 
-		gss_msg = list_entry(rpci->in_downcall.next,
-				struct gss_upcall_msg, list);
+		if (!list_empty(&gss_msg->msg.list))
+			continue;
 		gss_msg->msg.errno = -EPIPE;
 		atomic_inc(&gss_msg->count);
 		__gss_unhash_msg(gss_msg);
 		spin_unlock(&inode->i_lock);
 		gss_release_msg(gss_msg);
-		spin_lock(&inode->i_lock);
+		goto restart;
 	}
 	spin_unlock(&inode->i_lock);
 
@@ -1258,9 +1274,8 @@
 	rqstp->rq_release_snd_buf = priv_release_snd_buf;
 	return 0;
 out_free:
-	for (i--; i >= 0; i--) {
-		__free_page(rqstp->rq_enc_pages[i]);
-	}
+	rqstp->rq_enc_pages_num = i;
+	priv_release_snd_buf(rqstp);
 out:
 	return -EAGAIN;
 }
--- linux-ec2-2.6.32.orig/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ linux-ec2-2.6.32/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -131,8 +131,10 @@
 	struct	krb5_ctx *ctx;
 	int tmp;
 
-	if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS)))
+	if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) {
+		p = ERR_PTR(-ENOMEM);
 		goto out_err;
+	}
 
 	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
 	if (IS_ERR(p))
--- linux-ec2-2.6.32.orig/net/sctp/output.c
+++ linux-ec2-2.6.32/net/sctp/output.c
@@ -91,7 +91,6 @@
 	SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__,
 			  packet, vtag);
 
-	sctp_packet_reset(packet);
 	packet->vtag = vtag;
 
 	if (ecn_capable && sctp_packet_empty(packet)) {
--- linux-ec2-2.6.32.orig/net/sctp/transport.c
+++ linux-ec2-2.6.32/net/sctp/transport.c
@@ -108,6 +108,8 @@
 			(unsigned long)peer);
 	setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event,
 			(unsigned long)peer);
+	setup_timer(&peer->proto_unreach_timer,
+		    sctp_generate_proto_unreach_event, (unsigned long)peer);
 
 	/* Initialize the 64-bit random nonce sent with heartbeat. */
 	get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
--- linux-ec2-2.6.32.orig/net/sctp/protocol.c
+++ linux-ec2-2.6.32/net/sctp/protocol.c
@@ -1157,7 +1157,8 @@
 
 	/* Set the pressure threshold to be a fraction of global memory that
 	 * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
-	 * memory, with a floor of 128 pages.
+	 * memory, with a floor of 128 pages, and a ceiling that prevents an
+	 * integer overflow.
 	 * Note this initalizes the data in sctpv6_prot too
 	 * Unabashedly stolen from tcp_init
 	 */
@@ -1165,6 +1166,7 @@
 	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
 	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
 	limit = max(limit, 128UL);
+	limit = min(limit, INT_MAX * 4UL / 3 / 2);
 	sysctl_sctp_mem[0] = limit / 4 * 3;
 	sysctl_sctp_mem[1] = limit;
 	sysctl_sctp_mem[2] = sysctl_sctp_mem[0] * 2;
--- linux-ec2-2.6.32.orig/net/sctp/auth.c
+++ linux-ec2-2.6.32/net/sctp/auth.c
@@ -542,16 +542,20 @@
 		id = ntohs(hmacs->hmac_ids[i]);
 
 		/* Check the id is in the supported range */
-		if (id > SCTP_AUTH_HMAC_ID_MAX)
+		if (id > SCTP_AUTH_HMAC_ID_MAX) {
+			id = 0;
 			continue;
+		}
 
 		/* See is we support the id.  Supported IDs have name and
 		 * length fields set, so that we can allocated and use
 		 * them.  We can safely just check for name, for without the
 		 * name, we can't allocate the TFM.
 		 */
-		if (!sctp_hmac_list[id].hmac_name)
+		if (!sctp_hmac_list[id].hmac_name) {
+			id = 0;
 			continue;
+		}
 
 		break;
 	}
--- linux-ec2-2.6.32.orig/net/sctp/sm_make_chunk.c
+++ linux-ec2-2.6.32/net/sctp/sm_make_chunk.c
@@ -107,7 +107,7 @@
 	cpu_to_be16(sizeof(struct sctp_paramhdr)),
 };
 
-/* A helper to initialize to initialize an op error inside a
+/* A helper to initialize an op error inside a
  * provided chunk, as most cause codes will be embedded inside an
  * abort chunk.
  */
@@ -124,6 +124,29 @@
 	chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
 }
 
+/* A helper to initialize an op error inside a
+ * provided chunk, as most cause codes will be embedded inside an
+ * abort chunk.  Differs from sctp_init_cause in that it won't oops
+ * if there isn't enough space in the op error chunk
+ */
+int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
+		      size_t paylen)
+{
+	sctp_errhdr_t err;
+	__u16 len;
+
+	/* Cause code constants are now defined in network order.  */
+	err.cause = cause_code;
+	len = sizeof(sctp_errhdr_t) + paylen;
+	err.length  = htons(len);
+
+	if (skb_tailroom(chunk->skb) < len)
+		return -ENOSPC;
+	chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk,
+						     sizeof(sctp_errhdr_t),
+						     &err);
+	return 0;
+}
 /* 3.3.2 Initiation (INIT) (1)
  *
  * This chunk is used to initiate a SCTP association between two
@@ -207,7 +230,8 @@
 	sp = sctp_sk(asoc->base.sk);
 	num_types = sp->pf->supported_addrs(sp, types);
 
-	chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types);
+	chunksize = sizeof(init) + addrs_len;
+	chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));
 	chunksize += sizeof(ecap_param);
 
 	if (sctp_prsctp_enable)
@@ -237,14 +261,14 @@
 		/* Add HMACS parameter length if any were defined */
 		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
 		if (auth_hmacs->length)
-			chunksize += ntohs(auth_hmacs->length);
+			chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
 		else
 			auth_hmacs = NULL;
 
 		/* Add CHUNKS parameter length */
 		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
 		if (auth_chunks->length)
-			chunksize += ntohs(auth_chunks->length);
+			chunksize += WORD_ROUND(ntohs(auth_chunks->length));
 		else
 			auth_chunks = NULL;
 
@@ -254,7 +278,8 @@
 
 	/* If we have any extensions to report, account for that */
 	if (num_ext)
-		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;
+		chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
+					num_ext);
 
 	/* RFC 2960 3.3.2 Initiation (INIT) (1)
 	 *
@@ -396,13 +421,13 @@
 
 		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
 		if (auth_hmacs->length)
-			chunksize += ntohs(auth_hmacs->length);
+			chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
 		else
 			auth_hmacs = NULL;
 
 		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
 		if (auth_chunks->length)
-			chunksize += ntohs(auth_chunks->length);
+			chunksize += WORD_ROUND(ntohs(auth_chunks->length));
 		else
 			auth_chunks = NULL;
 
@@ -411,7 +436,8 @@
 	}
 
 	if (num_ext)
-		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;
+		chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
+					num_ext);
 
 	/* Now allocate and fill out the chunk.  */
 	retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
@@ -1125,6 +1151,24 @@
 	return retval;
 }
 
+/* Create an Operation Error chunk of a fixed size,
+ * specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
+ * This is a helper function to allocate an error chunk for
+ * for those invalid parameter codes in which we may not want
+ * to report all the errors, if the incomming chunk is large
+ */
+static inline struct sctp_chunk *sctp_make_op_error_fixed(
+	const struct sctp_association *asoc,
+	const struct sctp_chunk *chunk)
+{
+	size_t size = asoc ? asoc->pathmtu : 0;
+
+	if (!size)
+		size = SCTP_DEFAULT_MAXSEGMENT;
+
+	return sctp_make_op_error_space(asoc, chunk, size);
+}
+
 /* Create an Operation Error chunk.  */
 struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
 				 const struct sctp_chunk *chunk,
@@ -1365,6 +1409,18 @@
 	return target;
 }
 
+/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
+ * space in the chunk
+ */
+void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
+			     int len, const void *data)
+{
+	if (skb_tailroom(chunk->skb) >= len)
+		return sctp_addto_chunk(chunk, len, data);
+	else
+		return NULL;
+}
+
 /* Append bytes from user space to the end of a chunk.  Will panic if
  * chunk is not big enough.
  * Returns a kernel err value.
@@ -1968,13 +2024,12 @@
 		 * returning multiple unknown parameters.
 		 */
 		if (NULL == *errp)
-			*errp = sctp_make_op_error_space(asoc, chunk,
-					ntohs(chunk->chunk_hdr->length));
+			*errp = sctp_make_op_error_fixed(asoc, chunk);
 
 		if (*errp) {
-			sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
+			sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,
 					WORD_ROUND(ntohs(param.p->length)));
-			sctp_addto_chunk(*errp,
+			sctp_addto_chunk_fixed(*errp,
 					WORD_ROUND(ntohs(param.p->length)),
 					param.v);
 		} else {
@@ -3309,21 +3364,6 @@
 	sctp_chunk_free(asconf);
 	asoc->addip_last_asconf = NULL;
 
-	/* Send the next asconf chunk from the addip chunk queue. */
-	if (!list_empty(&asoc->addip_chunk_list)) {
-		struct list_head *entry = asoc->addip_chunk_list.next;
-		asconf = list_entry(entry, struct sctp_chunk, list);
-
-		list_del_init(entry);
-
-		/* Hold the chunk until an ASCONF_ACK is received. */
-		sctp_chunk_hold(asconf);
-		if (sctp_primitive_ASCONF(asoc, asconf))
-			sctp_chunk_free(asconf);
-		else
-			asoc->addip_last_asconf = asconf;
-	}
-
 	return retval;
 }
 
--- linux-ec2-2.6.32.orig/net/sctp/input.c
+++ linux-ec2-2.6.32/net/sctp/input.c
@@ -427,11 +427,25 @@
 {
 	SCTP_DEBUG_PRINTK("%s\n",  __func__);
 
-	sctp_do_sm(SCTP_EVENT_T_OTHER,
-		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
-		   asoc->state, asoc->ep, asoc, t,
-		   GFP_ATOMIC);
+	if (sock_owned_by_user(sk)) {
+		if (timer_pending(&t->proto_unreach_timer))
+			return;
+		else {
+			if (!mod_timer(&t->proto_unreach_timer,
+						jiffies + (HZ/20)))
+				sctp_association_hold(asoc);
+		}
 
+	} else {
+		if (timer_pending(&t->proto_unreach_timer) &&
+		    del_timer(&t->proto_unreach_timer))
+			sctp_association_put(asoc);
+
+		sctp_do_sm(SCTP_EVENT_T_OTHER,
+			   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+			   asoc->state, asoc->ep, asoc, t,
+			   GFP_ATOMIC);
+	}
 }
 
 /* Common lookup code for icmp/icmpv6 error handler. */
--- linux-ec2-2.6.32.orig/net/sctp/sm_sideeffect.c
+++ linux-ec2-2.6.32/net/sctp/sm_sideeffect.c
@@ -397,6 +397,41 @@
 	sctp_transport_put(transport);
 }
 
+/* Handle the timeout of the ICMP protocol unreachable timer.  Trigger
+ * the correct state machine transition that will close the association.
+ */
+void sctp_generate_proto_unreach_event(unsigned long data)
+{
+	struct sctp_transport *transport = (struct sctp_transport *) data;
+	struct sctp_association *asoc = transport->asoc;
+
+	sctp_bh_lock_sock(asoc->base.sk);
+	if (sock_owned_by_user(asoc->base.sk)) {
+		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+
+		/* Try again later.  */
+		if (!mod_timer(&transport->proto_unreach_timer,
+				jiffies + (HZ/20)))
+			sctp_association_hold(asoc);
+		goto out_unlock;
+	}
+
+	/* Is this structure just waiting around for us to actually
+	 * get destroyed?
+	 */
+	if (asoc->base.dead)
+		goto out_unlock;
+
+	sctp_do_sm(SCTP_EVENT_T_OTHER,
+		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+		   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
+
+out_unlock:
+	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_association_put(asoc);
+}
+
+
 /* Inject a SACK Timeout event into the state machine.  */
 static void sctp_generate_sack_event(unsigned long data)
 {
@@ -962,6 +997,29 @@
 }
 
 
+/* Sent the next ASCONF packet currently stored in the association.
+ * This happens after the ASCONF_ACK was succeffully processed.
+ */
+static void sctp_cmd_send_asconf(struct sctp_association *asoc)
+{
+	/* Send the next asconf chunk from the addip chunk
+	 * queue.
+	 */
+	if (!list_empty(&asoc->addip_chunk_list)) {
+		struct list_head *entry = asoc->addip_chunk_list.next;
+		struct sctp_chunk *asconf = list_entry(entry,
+						struct sctp_chunk, list);
+		list_del_init(entry);
+
+		/* Hold the chunk until an ASCONF_ACK is received. */
+		sctp_chunk_hold(asconf);
+		if (sctp_primitive_ASCONF(asoc, asconf))
+			sctp_chunk_free(asconf);
+		else
+			asoc->addip_last_asconf = asconf;
+	}
+}
+
 
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
@@ -1615,6 +1673,9 @@
 			}
 			error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
 			break;
+		case SCTP_CMD_SEND_NEXT_ASCONF:
+			sctp_cmd_send_asconf(asoc);
+			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
--- linux-ec2-2.6.32.orig/net/sctp/sm_statefuns.c
+++ linux-ec2-2.6.32/net/sctp/sm_statefuns.c
@@ -3670,8 +3670,14 @@
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
 
 		if (!sctp_process_asconf_ack((struct sctp_association *)asoc,
-					     asconf_ack))
+					     asconf_ack)) {
+			/* Successfully processed ASCONF_ACK.  We can
+			 * release the next asconf if we have one.
+			 */
+			sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF,
+					SCTP_NULL());
 			return SCTP_DISPOSITION_CONSUME;
+		}
 
 		abort = sctp_make_abort(asoc, asconf_ack,
 					sizeof(sctp_errhdr_t));
--- linux-ec2-2.6.32.orig/net/mac80211/iface.c
+++ linux-ec2-2.6.32/net/mac80211/iface.c
@@ -15,12 +15,14 @@
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/mac80211.h>
+#include <net/ieee80211_radiotap.h>
 #include "ieee80211_i.h"
 #include "sta_info.h"
 #include "debugfs_netdev.h"
 #include "mesh.h"
 #include "led.h"
 #include "driver-ops.h"
+#include "wme.h"
 
 /**
  * DOC: Interface list locking
@@ -642,6 +644,12 @@
 	WARN_ON(flushed);
 }
 
+static u16 ieee80211_netdev_select_queue(struct net_device *dev,
+					 struct sk_buff *skb)
+{
+	return ieee80211_select_queue(IEEE80211_DEV_TO_SUB_IF(dev), skb);
+}
+
 static const struct net_device_ops ieee80211_dataif_ops = {
 	.ndo_open		= ieee80211_open,
 	.ndo_stop		= ieee80211_stop,
@@ -650,8 +658,35 @@
 	.ndo_set_multicast_list = ieee80211_set_multicast_list,
 	.ndo_change_mtu 	= ieee80211_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_select_queue	= ieee80211_netdev_select_queue,
 };
 
+static u16 ieee80211_monitor_select_queue(struct net_device *dev,
+					  struct sk_buff *skb)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_radiotap_header *rtap = (void *)skb->data;
+
+	if (local->hw.queues < 4)
+		return 0;
+
+	if (skb->len < 4 ||
+	    skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */)
+		return 0; /* doesn't matter, frame will be dropped */
+
+	hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
+
+	if (!ieee80211_is_data(hdr->frame_control)) {
+		skb->priority = 7;
+		return ieee802_1d_to_ac[skb->priority];
+	}
+
+	skb->priority = 0;
+	return ieee80211_downgrade_queue(local, skb);
+}
+
 static const struct net_device_ops ieee80211_monitorif_ops = {
 	.ndo_open		= ieee80211_open,
 	.ndo_stop		= ieee80211_stop,
@@ -660,6 +695,7 @@
 	.ndo_set_multicast_list = ieee80211_set_multicast_list,
 	.ndo_change_mtu 	= ieee80211_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_select_queue	= ieee80211_monitor_select_queue,
 };
 
 static void ieee80211_if_setup(struct net_device *dev)
@@ -768,8 +804,8 @@
 
 	ASSERT_RTNL();
 
-	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
-			    name, ieee80211_if_setup);
+	ndev = alloc_netdev_mq(sizeof(*sdata) + local->hw.vif_data_size,
+			       name, ieee80211_if_setup, local->hw.queues);
 	if (!ndev)
 		return -ENOMEM;
 	dev_net_set(ndev, wiphy_net(local->hw.wiphy));
--- linux-ec2-2.6.32.orig/net/mac80211/ibss.c
+++ linux-ec2-2.6.32/net/mac80211/ibss.c
@@ -455,6 +455,10 @@
 
 	ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
 
+	if (time_before(jiffies, ifibss->last_scan_completed +
+		       IEEE80211_IBSS_MERGE_INTERVAL))
+		return;
+
 	if (ieee80211_sta_active_ibss(sdata))
 		return;
 
@@ -639,7 +643,7 @@
 	}
 	if (pos[1] != 0 &&
 	    (pos[1] != ifibss->ssid_len ||
-	     !memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
+	     memcmp(pos + 2, ifibss->ssid, ifibss->ssid_len))) {
 		/* Ignore ProbeReq for foreign SSID */
 		return;
 	}
--- linux-ec2-2.6.32.orig/net/mac80211/driver-trace.h
+++ linux-ec2-2.6.32/net/mac80211/driver-trace.h
@@ -655,7 +655,7 @@
 		__entry->ret = ret;
 		__entry->action = action;
 		__entry->tid = tid;
-		__entry->ssn = *ssn;
+		__entry->ssn = ssn ? *ssn : 0;
 	),
 
 	TP_printk(
--- linux-ec2-2.6.32.orig/net/mac80211/tx.c
+++ linux-ec2-2.6.32/net/mac80211/tx.c
@@ -496,7 +496,8 @@
 	struct ieee80211_hdr *hdr = (void *)tx->skb->data;
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_rate *rate;
-	int i, len;
+	int i;
+	u32 len;
 	bool inval = false, rts = false, short_preamble = false;
 	struct ieee80211_tx_rate_control txrc;
 	u32 sta_flags;
@@ -505,7 +506,7 @@
 
 	sband = tx->local->hw.wiphy->bands[tx->channel->band];
 
-	len = min_t(int, tx->skb->len + FCS_LEN,
+	len = min_t(u32, tx->skb->len + FCS_LEN,
 			 tx->local->hw.wiphy->frag_threshold);
 
 	/* set up the tx rate control struct we give the RC algo */
@@ -1401,6 +1402,7 @@
 
 	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
 	    local->hw.conf.dynamic_ps_timeout > 0 &&
+	    !local->quiescing &&
 	    !(local->scanning) && local->ps_sdata) {
 		if (local->hw.conf.flags & IEEE80211_CONF_PS) {
 			ieee80211_stop_queues_by_reason(&local->hw,
@@ -1481,7 +1483,7 @@
 				return;
 			}
 
-	ieee80211_select_queue(local, skb);
+	ieee80211_set_qos_hdr(local, skb);
 	ieee80211_tx(sdata, skb, false);
 	dev_put(sdata->dev);
 }
@@ -1880,6 +1882,7 @@
 void ieee80211_tx_pending(unsigned long data)
 {
 	struct ieee80211_local *local = (struct ieee80211_local *)data;
+	struct ieee80211_sub_if_data *sdata;
 	unsigned long flags;
 	int i;
 	bool txok;
@@ -1920,6 +1923,11 @@
 			if (!txok)
 				break;
 		}
+
+		if (skb_queue_empty(&local->pending[i]))
+			list_for_each_entry_rcu(sdata, &local->interfaces, list)
+				netif_tx_wake_queue(
+					netdev_get_tx_queue(sdata->dev, i));
 	}
 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 
@@ -2225,6 +2233,9 @@
 	if (!encrypt)
 		info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 
+	/* send all internal mgmt frames on VO */
+	skb_set_queue_mapping(skb, 0);
+
 	/*
 	 * The other path calling ieee80211_xmit is from the tasklet,
 	 * and while we can handle concurrent transmissions locking
--- linux-ec2-2.6.32.orig/net/mac80211/mlme.c
+++ linux-ec2-2.6.32/net/mac80211/mlme.c
@@ -269,12 +269,6 @@
 	if (wk->bss->wmm_used)
 		wmm = 1;
 
-	/* get all rates supported by the device and the AP as
-	 * some APs don't like getting a superset of their rates
-	 * in the association request (e.g. D-Link DAP 1353 in
-	 * b-only mode) */
-	rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
-
 	if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
 	    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
 		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
@@ -309,6 +303,17 @@
 	*pos++ = wk->ssid_len;
 	memcpy(pos, wk->ssid, wk->ssid_len);
 
+	if (wk->bss->supp_rates_len) {
+		/* get all rates supported by the device and the AP as
+		 * some APs don't like getting a superset of their rates
+		 * in the association request (e.g. D-Link DAP 1353 in
+		 * b-only mode) */
+		rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates);
+	} else {
+		rates = ~0;
+		rates_len = sband->n_bitrates;
+	}
+
 	/* add all rates which were marked to be used above */
 	supp_rates_len = rates_len;
 	if (supp_rates_len > 8)
@@ -650,8 +655,11 @@
 	} else {
 		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
 			ieee80211_send_nullfunc(local, sdata, 1);
-		conf->flags |= IEEE80211_CONF_PS;
-		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+
+		if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
+			conf->flags |= IEEE80211_CONF_PS;
+			ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+		}
 	}
 }
 
@@ -742,6 +750,7 @@
 		container_of(work, struct ieee80211_local,
 			     dynamic_ps_enable_work);
 	struct ieee80211_sub_if_data *sdata = local->ps_sdata;
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	/* can only happen when PS was just disabled anyway */
 	if (!sdata)
@@ -750,11 +759,16 @@
 	if (local->hw.conf.flags & IEEE80211_CONF_PS)
 		return;
 
-	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
+	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
+	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))
 		ieee80211_send_nullfunc(local, sdata, 1);
 
-	local->hw.conf.flags |= IEEE80211_CONF_PS;
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+	if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ||
+	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
+		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
+		local->hw.conf.flags |= IEEE80211_CONF_PS;
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+	}
 }
 
 void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -904,6 +918,14 @@
 	sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
 				IEEE80211_STA_BEACON_POLL);
 
+	/*
+	 * Always handle WMM once after association regardless
+	 * of the first value the AP uses. Setting -1 here has
+	 * that effect because the AP values is an unsigned
+	 * 4-bit value.
+	 */
+	sdata->u.mgd.wmm_last_param_set = -1;
+
 	ieee80211_led_assoc(local, 1);
 
 	sdata->vif.bss_conf.assoc = 1;
@@ -1945,7 +1967,9 @@
 			rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
 			break;
 		case IEEE80211_STYPE_ACTION:
-			/* XXX: differentiate, can only happen for CSA now! */
+			if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
+				break;
+
 			ieee80211_sta_process_chanswitch(sdata,
 					&mgmt->u.action.u.chan_switch.sw_elem,
 					ifmgd->associated);
@@ -2448,6 +2472,7 @@
 	list_add(&wk->list, &ifmgd->work_list);
 
 	ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
+	ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 
 	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
 		if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
--- linux-ec2-2.6.32.orig/net/mac80211/wme.h
+++ linux-ec2-2.6.32/net/mac80211/wme.h
@@ -20,7 +20,11 @@
 
 extern const int ieee802_1d_to_ac[8];
 
-void ieee80211_select_queue(struct ieee80211_local *local,
-			    struct sk_buff *skb);
+u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+			   struct sk_buff *skb);
+void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb);
+u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
+                              struct sk_buff *skb);
+
 
 #endif /* _WME_H */
--- linux-ec2-2.6.32.orig/net/mac80211/Kconfig
+++ linux-ec2-2.6.32/net/mac80211/Kconfig
@@ -15,8 +15,12 @@
 
 if MAC80211 != n
 
+config MAC80211_HAS_RC
+	def_bool n
+
 config MAC80211_RC_PID
 	bool "PID controller based rate control algorithm" if EMBEDDED
+	select MAC80211_HAS_RC
 	---help---
 	  This option enables a TX rate control algorithm for
 	  mac80211 that uses a PID controller to select the TX
@@ -24,12 +28,14 @@
 
 config MAC80211_RC_MINSTREL
 	bool "Minstrel" if EMBEDDED
+	select MAC80211_HAS_RC
 	default y
 	---help---
 	  This option enables the 'minstrel' TX rate control algorithm
 
 choice
 	prompt "Default rate control algorithm"
+	depends on MAC80211_HAS_RC
 	default MAC80211_RC_DEFAULT_MINSTREL
 	---help---
 	  This option selects the default rate control algorithm
@@ -62,6 +68,9 @@
 
 endif
 
+comment "Some wireless drivers require a rate control algorithm"
+	depends on MAC80211_HAS_RC=n
+
 config MAC80211_MESH
 	bool "Enable mac80211 mesh networking (pre-802.11s) support"
 	depends on MAC80211 && EXPERIMENTAL
--- linux-ec2-2.6.32.orig/net/mac80211/ieee80211_i.h
+++ linux-ec2-2.6.32/net/mac80211/ieee80211_i.h
@@ -264,6 +264,7 @@
 	IEEE80211_STA_DISABLE_11N	= BIT(4),
 	IEEE80211_STA_CSA_RECEIVED	= BIT(5),
 	IEEE80211_STA_MFP_ENABLED	= BIT(6),
+	IEEE80211_STA_NULLFUNC_ACKED	= BIT(7),
 };
 
 /* flags for MLME request */
@@ -808,6 +809,7 @@
 	unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
 	bool pspolling;
+	bool scan_ps_enabled;
 	/*
 	 * PS can only be enabled when we have exactly one managed
 	 * interface (and monitors) in PS, this then points there.
--- linux-ec2-2.6.32.orig/net/mac80211/cfg.c
+++ linux-ec2-2.6.32/net/mac80211/cfg.c
@@ -338,7 +338,8 @@
 	sinfo->rx_packets = sta->rx_packets;
 	sinfo->tx_packets = sta->tx_packets;
 
-	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+	if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
+	    (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
 		sinfo->filled |= STATION_INFO_SIGNAL;
 		sinfo->signal = (s8)sta->last_signal;
 	}
@@ -1305,6 +1306,9 @@
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 	struct ieee80211_conf *conf = &local->hw.conf;
 
+	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+		return -EOPNOTSUPP;
+
 	if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
 		return -EOPNOTSUPP;
 
--- linux-ec2-2.6.32.orig/net/mac80211/scan.c
+++ linux-ec2-2.6.32/net/mac80211/scan.c
@@ -62,7 +62,7 @@
 			  bool beacon)
 {
 	struct ieee80211_bss *bss;
-	int clen;
+	int clen, srlen;
 	s32 signal = 0;
 
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
@@ -94,23 +94,24 @@
 	if (bss->dtim_period == 0)
 		bss->dtim_period = 1;
 
-	bss->supp_rates_len = 0;
+	/* replace old supported rates if we get new values */
+	srlen = 0;
 	if (elems->supp_rates) {
-		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+		clen = IEEE80211_MAX_SUPP_RATES;
 		if (clen > elems->supp_rates_len)
 			clen = elems->supp_rates_len;
-		memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates,
-		       clen);
-		bss->supp_rates_len += clen;
+		memcpy(bss->supp_rates, elems->supp_rates, clen);
+		srlen += clen;
 	}
 	if (elems->ext_supp_rates) {
-		clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
+		clen = IEEE80211_MAX_SUPP_RATES - srlen;
 		if (clen > elems->ext_supp_rates_len)
 			clen = elems->ext_supp_rates_len;
-		memcpy(&bss->supp_rates[bss->supp_rates_len],
-		       elems->ext_supp_rates, clen);
-		bss->supp_rates_len += clen;
+		memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
+		srlen += clen;
 	}
+	if (srlen)
+		bss->supp_rates_len = srlen;
 
 	bss->wmm_used = elems->wmm_param || elems->wmm_info;
 
@@ -196,7 +197,8 @@
 static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_local *local = sdata->local;
-	bool ps = false;
+
+	local->scan_ps_enabled = false;
 
 	/* FIXME: what to do when local->pspolling is true? */
 
@@ -204,12 +206,13 @@
 	cancel_work_sync(&local->dynamic_ps_enable_work);
 
 	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
-		ps = true;
+		local->scan_ps_enabled = true;
 		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 
-	if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
+	if (!(local->scan_ps_enabled) ||
+	    !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
 		/*
 		 * If power save was enabled, no need to send a nullfunc
 		 * frame because AP knows that we are sleeping. But if the
@@ -230,7 +233,7 @@
 
 	if (!local->ps_sdata)
 		ieee80211_send_nullfunc(local, sdata, 0);
-	else {
+	else if (local->scan_ps_enabled) {
 		/*
 		 * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
 		 * will send a nullfunc frame with the powersave bit set
@@ -246,6 +249,16 @@
 		 */
 		local->hw.conf.flags |= IEEE80211_CONF_PS;
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+	} else if (local->hw.conf.dynamic_ps_timeout > 0) {
+		/*
+		 * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
+		 * had been running before leaving the operating channel,
+		 * restart the timer now and send a nullfunc frame to inform
+		 * the AP that we are awake.
+		 */
+		ieee80211_send_nullfunc(local, sdata, 0);
+		mod_timer(&local->dynamic_ps_timer, jiffies +
+			  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 	}
 }
 
@@ -264,10 +277,14 @@
 
 	mutex_lock(&local->scan_mtx);
 
-	if (WARN_ON(!local->scanning)) {
-		mutex_unlock(&local->scan_mtx);
-		return;
-	}
+	/*
+	 * It's ok to abort a not-yet-running scan (that
+	 * we have one at all will be verified by checking
+	 * local->scan_req next), but not to complete it
+	 * successfully.
+	 */
+	if (WARN_ON(!local->scanning && !aborted))
+		aborted = true;
 
 	if (WARN_ON(!local->scan_req)) {
 		mutex_unlock(&local->scan_mtx);
@@ -392,6 +409,16 @@
 	if (local->scan_req)
 		return -EBUSY;
 
+	if (req != local->int_scan_req &&
+	    sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    !list_empty(&ifmgd->work_list)) {
+		/* actually wait for the work it's doing to finish/time out */
+		set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
+		local->scan_req = req;
+		local->scan_sdata = sdata;
+		return 0;
+	}
+
 	if (local->ops->hw_scan) {
 		u8 *ies;
 		int ielen;
@@ -412,14 +439,6 @@
 	local->scan_req = req;
 	local->scan_sdata = sdata;
 
-	if (req != local->int_scan_req &&
-	    sdata->vif.type == NL80211_IFTYPE_STATION &&
-	    !list_empty(&ifmgd->work_list)) {
-		/* actually wait for the work it's doing to finish/time out */
-		set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
-		return 0;
-	}
-
 	if (local->ops->hw_scan)
 		__set_bit(SCAN_HW_SCANNING, &local->scanning);
 	else
--- linux-ec2-2.6.32.orig/net/mac80211/sta_info.c
+++ linux-ec2-2.6.32/net/mac80211/sta_info.c
@@ -276,6 +276,7 @@
 	memcpy(sta->sta.addr, addr, ETH_ALEN);
 	sta->local = local;
 	sta->sdata = sdata;
+	sta->last_rx = jiffies;
 
 	sta->rate_ctrl = rate_control_get(local->rate_ctrl);
 	sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
--- linux-ec2-2.6.32.orig/net/mac80211/mesh_hwmp.c
+++ linux-ec2-2.6.32/net/mac80211/mesh_hwmp.c
@@ -813,7 +813,7 @@
 	}
 
 	if (mpath->flags & MESH_PATH_ACTIVE) {
-		if (time_after(jiffies, mpath->exp_time +
+		if (time_after(jiffies, mpath->exp_time -
 			msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
 				&& !memcmp(sdata->dev->dev_addr, hdr->addr4,
 					   ETH_ALEN)
--- linux-ec2-2.6.32.orig/net/mac80211/mesh.h
+++ linux-ec2-2.6.32/net/mac80211/mesh.h
@@ -186,8 +186,9 @@
  */
 #define MESH_PREQ_MIN_INT	10
 #define MESH_DIAM_TRAVERSAL_TIME 50
-/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
- * expiration
+/* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before
+ * timing out.  This way it will remain ACTIVE and no data frames will be
+ * unnecesarily held in the pending queue.
  */
 #define MESH_PATH_REFRESH_TIME			1000
 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
--- linux-ec2-2.6.32.orig/net/mac80211/main.c
+++ linux-ec2-2.6.32/net/mac80211/main.c
@@ -441,6 +441,7 @@
 	rcu_read_lock();
 
 	sband = local->hw.wiphy->bands[info->band];
+	fc = hdr->frame_control;
 
 	sta = sta_info_get(local, hdr->addr1);
 
@@ -522,6 +523,20 @@
 			local->dot11FailedCount++;
 	}
 
+	if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
+	    (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
+	    !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
+	    local->ps_sdata && !(local->scanning)) {
+		if (info->flags & IEEE80211_TX_STAT_ACK) {
+			local->ps_sdata->u.mgd.flags |=
+				IEEE80211_STA_NULLFUNC_ACKED;
+			ieee80211_queue_work(&local->hw,
+					     &local->dynamic_ps_enable_work);
+		} else
+			mod_timer(&local->dynamic_ps_timer, jiffies +
+				  msecs_to_jiffies(10));
+	}
+
 	/* this was a transmitted frame, but now we want to reuse it */
 	skb_orphan(skb);
 
@@ -844,6 +859,8 @@
 	 * and we need some headroom for passing the frame to monitor
 	 * interfaces, but never both at the same time.
 	 */
+	BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
+			sizeof(struct ieee80211_tx_status_rtap_hdr));
 	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
 				   sizeof(struct ieee80211_tx_status_rtap_hdr));
 
--- linux-ec2-2.6.32.orig/net/mac80211/agg-tx.c
+++ linux-ec2-2.6.32/net/mac80211/agg-tx.c
@@ -177,10 +177,10 @@
 
 	/* check if the TID waits for addBA response */
 	spin_lock_bh(&sta->lock);
-	if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) !=
+	if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK |
+		       HT_AGG_STATE_REQ_STOP_BA_MSK)) !=
 						HT_ADDBA_REQUESTED_MSK) {
 		spin_unlock_bh(&sta->lock);
-		*state = HT_AGG_STATE_IDLE;
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "timer expired on tid %d but we are not "
 				"(or no longer) expecting addBA response there",
--- linux-ec2-2.6.32.orig/net/mac80211/rx.c
+++ linux-ec2-2.6.32/net/mac80211/rx.c
@@ -1220,7 +1220,8 @@
 		     (rx->key || rx->sdata->drop_unencrypted)))
 		return -EACCES;
 	if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
-		if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+		if (unlikely(!ieee80211_has_protected(fc) &&
+			     ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
 			     rx->key))
 			return -EACCES;
 		/* BIP does not use Protected field, so need to check MMIE */
@@ -1514,7 +1515,6 @@
 			mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata);
 		} else {
 			spin_lock_bh(&mppath->state_lock);
-			mppath->exp_time = jiffies;
 			if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0)
 				memcpy(mppath->mpp, hdr->addr4, ETH_ALEN);
 			spin_unlock_bh(&mppath->state_lock);
@@ -1549,7 +1549,9 @@
 			memset(info, 0, sizeof(*info));
 			info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
 			info->control.vif = &rx->sdata->vif;
-			ieee80211_select_queue(local, fwd_skb);
+			skb_set_queue_mapping(skb,
+				ieee80211_select_queue(rx->sdata, fwd_skb));
+			ieee80211_set_qos_hdr(local, skb);
 			if (is_multicast_ether_addr(fwd_hdr->addr1))
 				IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
 								fwded_mcast);
@@ -1589,6 +1591,7 @@
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
 	struct net_device *dev = rx->dev;
+	struct ieee80211_local *local = rx->local;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 	__le16 fc = hdr->frame_control;
 	int err;
@@ -1611,6 +1614,13 @@
 	dev->stats.rx_packets++;
 	dev->stats.rx_bytes += rx->skb->len;
 
+	if (ieee80211_is_data(hdr->frame_control) &&
+	    !is_multicast_ether_addr(hdr->addr1) &&
+	    local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) {
+		mod_timer(&local->dynamic_ps_timer, jiffies +
+			  msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
+	}
+
 	ieee80211_deliver_skb(rx);
 
 	return RX_QUEUED;
@@ -1808,7 +1818,16 @@
 			return RX_CONTINUE;
 		}
 		break;
+	case WLAN_CATEGORY_MESH_PLINK:
+	case WLAN_CATEGORY_MESH_PATH_SEL:
+		if (ieee80211_vif_is_mesh(&sdata->vif))
+			return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
+		break;
 	default:
+		/* do not process rejected action frames */
+		if (mgmt->u.action.category & 0x80)
+			return RX_DROP_MONITOR;
+
 		return RX_CONTINUE;
 	}
 
--- linux-ec2-2.6.32.orig/net/mac80211/util.c
+++ linux-ec2-2.6.32/net/mac80211/util.c
@@ -269,6 +269,7 @@
 				   enum queue_stop_reason reason)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
 
 	if (WARN_ON(queue >= hw->queues))
 		return;
@@ -279,7 +280,12 @@
 		/* someone still has this queue stopped */
 		return;
 
-	if (!skb_queue_empty(&local->pending[queue]))
+	if (skb_queue_empty(&local->pending[queue])) {
+		rcu_read_lock();
+		list_for_each_entry_rcu(sdata, &local->interfaces, list)
+			netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
+		rcu_read_unlock();
+	} else
 		tasklet_schedule(&local->tx_pending_tasklet);
 }
 
@@ -305,11 +311,17 @@
 				   enum queue_stop_reason reason)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_sub_if_data *sdata;
 
 	if (WARN_ON(queue >= hw->queues))
 		return;
 
 	__set_bit(reason, &local->queue_stop_reasons[queue]);
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &local->interfaces, list)
+		netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
+	rcu_read_unlock();
 }
 
 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@ -579,7 +591,7 @@
 		if (elen > left)
 			break;
 
-		if (calc_crc && id < 64 && (filter & BIT(id)))
+		if (calc_crc && id < 64 && (filter & (1ULL << id)))
 			crc = crc32_be(crc, pos - 2, elen + 2);
 
 		switch (id) {
@@ -1031,7 +1043,19 @@
 
 	/* restart hardware */
 	if (local->open_count) {
+		/*
+		 * Upon resume hardware can sometimes be goofy due to
+		 * various platform / driver / bus issues, so restarting
+		 * the device may at times not work immediately. Propagate
+		 * the error.
+		 */
 		res = drv_start(local);
+		if (res) {
+			WARN(local->suspended, "Harware became unavailable "
+			     "upon resume. This is could be a software issue"
+			     "prior to suspend or a harware issue\n");
+			return res;
+		}
 
 		ieee80211_led_radio(local, true);
 	}
@@ -1113,6 +1137,14 @@
 		}
 	}
 
+	rcu_read_lock();
+	if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
+		list_for_each_entry_rcu(sta, &local->sta_list, list) {
+			ieee80211_sta_tear_down_BA_sessions(sta);
+		}
+	}
+	rcu_read_unlock();
+
 	/* add back keys */
 	list_for_each_entry(sdata, &local->interfaces, list)
 		if (netif_running(sdata->dev))
--- linux-ec2-2.6.32.orig/net/mac80211/wme.c
+++ linux-ec2-2.6.32/net/mac80211/wme.c
@@ -44,22 +44,62 @@
 }
 
 
-/* Indicate which queue to use.  */
-static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
+/* Indicate which queue to use. */
+u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
+			   struct sk_buff *skb)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta = NULL;
+	u32 sta_flags = 0;
+	const u8 *ra = NULL;
+	bool qos = false;
 
-	if (!ieee80211_is_data(hdr->frame_control)) {
-		/* management frames go on AC_VO queue, but are sent
-		* without QoS control fields */
-		return 0;
+	if (local->hw.queues < 4 || skb->len < 6) {
+		skb->priority = 0; /* required for correct WPA/11i MIC */
+		return min_t(u16, local->hw.queues - 1,
+			     ieee802_1d_to_ac[skb->priority]);
+	}
+
+	rcu_read_lock();
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_AP:
+		ra = skb->data;
+		break;
+	case NL80211_IFTYPE_WDS:
+		ra = sdata->u.wds.remote_addr;
+		break;
+#ifdef CONFIG_MAC80211_MESH
+	case NL80211_IFTYPE_MESH_POINT:
+		/*
+		 * XXX: This is clearly broken ... but already was before,
+		 * because ieee80211_fill_mesh_addresses() would clear A1
+		 * except for multicast addresses.
+		 */
+		break;
+#endif
+	case NL80211_IFTYPE_STATION:
+		ra = sdata->u.mgd.bssid;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ra = skb->data;
+		break;
+	default:
+		break;
 	}
 
-	if (0 /* injected */) {
-		/* use AC from radiotap */
+	if (!sta && ra && !is_multicast_ether_addr(ra)) {
+		sta = sta_info_get(local, ra);
+		if (sta)
+			sta_flags = get_sta_flags(sta);
 	}
 
-	if (!ieee80211_is_data_qos(hdr->frame_control)) {
+	if (sta_flags & WLAN_STA_WME)
+		qos = true;
+
+	rcu_read_unlock();
+
+	if (!qos) {
 		skb->priority = 0; /* required for correct WPA/11i MIC */
 		return ieee802_1d_to_ac[skb->priority];
 	}
@@ -68,6 +108,12 @@
 	 * data frame has */
 	skb->priority = cfg80211_classify8021d(skb);
 
+	return ieee80211_downgrade_queue(local, skb);
+}
+
+u16 ieee80211_downgrade_queue(struct ieee80211_local *local,
+			      struct sk_buff *skb)
+{
 	/* in case we are a client verify acm is not set for this ac */
 	while (unlikely(local->wmm_acm & BIT(skb->priority))) {
 		if (wme_downgrade_ac(skb)) {
@@ -85,24 +131,17 @@
 	return ieee802_1d_to_ac[skb->priority];
 }
 
-void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb)
+void ieee80211_set_qos_hdr(struct ieee80211_local *local, struct sk_buff *skb)
 {
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	u16 queue;
-	u8 tid;
-
-	queue = classify80211(local, skb);
-	if (unlikely(queue >= local->hw.queues))
-		queue = local->hw.queues - 1;
-
-	/*
-	 * Now we know the 1d priority, fill in the QoS header if
-	 * there is one (and we haven't done this before).
-	 */
+	struct ieee80211_hdr *hdr = (void *)skb->data;
+
+	/* Fill in the QoS header if there is one. */
 	if (ieee80211_is_data_qos(hdr->frame_control)) {
 		u8 *p = ieee80211_get_qos_ctl(hdr);
-		u8 ack_policy = 0;
+		u8 ack_policy = 0, tid;
+
 		tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+
 		if (unlikely(local->wifi_wme_noack_test))
 			ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
 					QOS_CONTROL_ACK_POLICY_SHIFT;
@@ -110,6 +149,4 @@
 		*p++ = ack_policy | tid;
 		*p = 0;
 	}
-
-	skb_set_queue_mapping(skb, queue);
 }
--- linux-ec2-2.6.32.orig/net/rose/af_rose.c
+++ linux-ec2-2.6.32/net/rose/af_rose.c
@@ -677,7 +677,7 @@
 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
 		return -EINVAL;
 
-	if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
 		return -EINVAL;
 
 	if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) {
@@ -737,7 +737,7 @@
 	if (addr_len == sizeof(struct sockaddr_rose) && addr->srose_ndigis > 1)
 		return -EINVAL;
 
-	if (addr->srose_ndigis > ROSE_MAX_DIGIS)
+	if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS)
 		return -EINVAL;
 
 	/* Source + Destination digis should not exceed ROSE_MAX_DIGIS */
--- linux-ec2-2.6.32.orig/net/rose/rose_route.c
+++ linux-ec2-2.6.32/net/rose/rose_route.c
@@ -234,6 +234,8 @@
 
 	if ((s = rose_neigh_list) == rose_neigh) {
 		rose_neigh_list = rose_neigh->next;
+		if (rose_neigh->ax25)
+			ax25_cb_put(rose_neigh->ax25);
 		kfree(rose_neigh->digipeat);
 		kfree(rose_neigh);
 		return;
@@ -242,6 +244,8 @@
 	while (s != NULL && s->next != NULL) {
 		if (s->next == rose_neigh) {
 			s->next = rose_neigh->next;
+			if (rose_neigh->ax25)
+				ax25_cb_put(rose_neigh->ax25);
 			kfree(rose_neigh->digipeat);
 			kfree(rose_neigh);
 			return;
@@ -810,6 +814,7 @@
 
 	if (rose_neigh != NULL) {
 		rose_neigh->ax25 = NULL;
+		ax25_cb_put(ax25);
 
 		rose_del_route_by_neigh(rose_neigh);
 		rose_kill_by_neigh(rose_neigh);
--- linux-ec2-2.6.32.orig/net/rose/rose_link.c
+++ linux-ec2-2.6.32/net/rose/rose_link.c
@@ -101,13 +101,17 @@
 static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
 {
 	ax25_address *rose_call;
+	ax25_cb *ax25s;
 
 	if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
 		rose_call = (ax25_address *)neigh->dev->dev_addr;
 	else
 		rose_call = &rose_callsign;
 
+	ax25s = neigh->ax25;
 	neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+	if (ax25s)
+		ax25_cb_put(ax25s);
 
 	return (neigh->ax25 != NULL);
 }
@@ -120,13 +124,17 @@
 static int rose_link_up(struct rose_neigh *neigh)
 {
 	ax25_address *rose_call;
+	ax25_cb *ax25s;
 
 	if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
 		rose_call = (ax25_address *)neigh->dev->dev_addr;
 	else
 		rose_call = &rose_callsign;
 
+	ax25s = neigh->ax25;
 	neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
+	if (ax25s)
+		ax25_cb_put(ax25s);
 
 	return (neigh->ax25 != NULL);
 }
--- linux-ec2-2.6.32.orig/net/rose/rose_subr.c
+++ linux-ec2-2.6.32/net/rose/rose_subr.c
@@ -289,10 +289,15 @@
 				facilities->source_ndigis = 0;
 				facilities->dest_ndigis   = 0;
 				for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
-					if (pt[6] & AX25_HBIT)
+					if (pt[6] & AX25_HBIT) {
+						if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
+							return -1;
 						memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
-					else
+					} else {
+						if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
+							return -1;
 						memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
+					}
 				}
 			}
 			p   += l + 2;
@@ -332,6 +337,11 @@
 
 		case 0xC0:
 			l = p[1];
+
+			/* Prevent overflows*/
+			if (l < 10 || l > 20)
+				return -1;
+
 			if (*p == FAC_CCITT_DEST_NSAP) {
 				memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
 				memcpy(callsign, p + 12,   l - 10);
@@ -372,12 +382,16 @@
 			switch (*p) {
 			case FAC_NATIONAL:		/* National */
 				len = rose_parse_national(p + 1, facilities, facilities_len - 1);
+				if (len < 0)
+					return 0;
 				facilities_len -= len + 1;
 				p += len + 1;
 				break;
 
 			case FAC_CCITT:		/* CCITT */
 				len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
+				if (len < 0)
+					return 0;
 				facilities_len -= len + 1;
 				p += len + 1;
 				break;
--- linux-ec2-2.6.32.orig/net/8021q/vlan_core.c
+++ linux-ec2-2.6.32/net/8021q/vlan_core.c
@@ -74,8 +74,9 @@
 }
 EXPORT_SYMBOL(vlan_dev_vlan_id);
 
-static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
-			   unsigned int vlan_tci, struct sk_buff *skb)
+static gro_result_t
+vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
+		unsigned int vlan_tci, struct sk_buff *skb)
 {
 	struct sk_buff *p;
 
@@ -101,11 +102,12 @@
 	return GRO_DROP;
 }
 
-int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
-		     unsigned int vlan_tci, struct sk_buff *skb)
+gro_result_t vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp,
+			      unsigned int vlan_tci, struct sk_buff *skb)
 {
 	if (netpoll_rx_on(skb))
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci);
+		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
+			? GRO_DROP : GRO_NORMAL;
 
 	skb_gro_reset_offset(skb);
 
@@ -113,17 +115,18 @@
 }
 EXPORT_SYMBOL(vlan_gro_receive);
 
-int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
-		   unsigned int vlan_tci)
+gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
+			    unsigned int vlan_tci)
 {
 	struct sk_buff *skb = napi_frags_skb(napi);
 
 	if (!skb)
-		return NET_RX_DROP;
+		return GRO_DROP;
 
 	if (netpoll_rx_on(skb)) {
 		skb->protocol = eth_type_trans(skb, skb->dev);
-		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci);
+		return vlan_hwaccel_receive_skb(skb, grp, vlan_tci)
+			? GRO_DROP : GRO_NORMAL;
 	}
 
 	return napi_frags_finish(napi, skb,
--- linux-ec2-2.6.32.orig/net/ipv4/devinet.c
+++ linux-ec2-2.6.32/net/ipv4/devinet.c
@@ -1025,6 +1025,21 @@
 	return mtu >= 68;
 }
 
+static void inetdev_send_gratuitous_arp(struct net_device *dev,
+					struct in_device *in_dev)
+
+{
+	struct in_ifaddr *ifa = in_dev->ifa_list;
+
+	if (!ifa)
+		return;
+
+	arp_send(ARPOP_REQUEST, ETH_P_ARP,
+		 ifa->ifa_address, dev,
+		 ifa->ifa_address, NULL,
+		 dev->dev_addr, NULL);
+}
+
 /* Called only under RTNL semaphore */
 
 static int inetdev_event(struct notifier_block *this, unsigned long event,
@@ -1077,16 +1092,12 @@
 		ip_mc_up(in_dev);
 		/* fall through */
 	case NETDEV_CHANGEADDR:
+		if (!IN_DEV_ARP_NOTIFY(in_dev))
+			break;
+		/* fall through */
+	case NETDEV_NOTIFY_PEERS:
 		/* Send gratuitous ARP to notify of link change */
-		if (IN_DEV_ARP_NOTIFY(in_dev)) {
-			struct in_ifaddr *ifa = in_dev->ifa_list;
-
-			if (ifa)
-				arp_send(ARPOP_REQUEST, ETH_P_ARP,
-					 ifa->ifa_address, dev,
-					 ifa->ifa_address, NULL,
-					 dev->dev_addr, NULL);
-		}
+		inetdev_send_gratuitous_arp(dev, in_dev);
 		break;
 	case NETDEV_DOWN:
 		ip_mc_down(in_dev);
@@ -1351,14 +1362,19 @@
 {
 	int *valp = ctl->data;
 	int val = *valp;
+	loff_t pos = *ppos;
 	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 
 	if (write && *valp != val) {
 		struct net *net = ctl->extra2;
 
 		if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
-			if (!rtnl_trylock())
+			if (!rtnl_trylock()) {
+				/* Restore the original values before restarting */
+				*valp = val;
+				*ppos = pos;
 				return restart_syscall();
+			}
 			if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
 				inet_forward_change(net);
 			} else if (*valp) {
@@ -1450,6 +1466,7 @@
 		DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
 		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
 					"accept_source_route"),
+		DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
 		DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
 		DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
 		DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
--- linux-ec2-2.6.32.orig/net/ipv4/tcp_output.c
+++ linux-ec2-2.6.32/net/ipv4/tcp_output.c
@@ -2037,6 +2037,9 @@
 	int mib_idx;
 	int fwd_rexmitting = 0;
 
+	if (!tp->packets_out)
+		return;
+
 	if (!tp->lost_out)
 		tp->retransmit_high = tp->snd_una;
 
--- linux-ec2-2.6.32.orig/net/ipv4/tcp.c
+++ linux-ec2-2.6.32/net/ipv4/tcp.c
@@ -386,8 +386,6 @@
 	 */
 
 	mask = 0;
-	if (sk->sk_err)
-		mask = POLLERR;
 
 	/*
 	 * POLLHUP is certainly not done right. But poll() doesn't
@@ -451,11 +449,17 @@
 				if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk))
 					mask |= POLLOUT | POLLWRNORM;
 			}
-		}
+		} else
+			mask |= POLLOUT | POLLWRNORM;
 
 		if (tp->urg_data & TCP_URG_VALID)
 			mask |= POLLPRI;
 	}
+	/* This barrier is coupled with smp_wmb() in tcp_reset() */
+	smp_rmb();
+	if (sk->sk_err)
+		mask |= POLLERR;
+
 	return mask;
 }
 
@@ -934,7 +938,7 @@
 		goto out_err;
 
 	while (--iovlen >= 0) {
-		int seglen = iov->iov_len;
+		size_t seglen = iov->iov_len;
 		unsigned char __user *from = iov->iov_base;
 
 		iov++;
@@ -1334,6 +1338,7 @@
 		sk_eat_skb(sk, skb, 0);
 		if (!desc->count)
 			break;
+		tp->copied_seq = seq;
 	}
 	tp->copied_seq = seq;
 
@@ -1975,11 +1980,8 @@
 		}
 	}
 	if (sk->sk_state != TCP_CLOSE) {
-		int orphan_count = percpu_counter_read_positive(
-						sk->sk_prot->orphan_count);
-
 		sk_mem_reclaim(sk);
-		if (tcp_too_many_orphans(sk, orphan_count)) {
+		if (tcp_too_many_orphans(sk, 0)) {
 			if (net_ratelimit())
 				printk(KERN_INFO "TCP: too many of orphaned "
 				       "sockets\n");
@@ -2115,7 +2117,7 @@
 		/* Values greater than interface MTU won't take effect. However
 		 * at the point when this call is done we typically don't yet
 		 * know which interface is going to be used */
-		if (val < 8 || val > MAX_TCP_WINDOW) {
+		if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) {
 			err = -EINVAL;
 			break;
 		}
@@ -2880,7 +2882,7 @@
 {
 	struct sk_buff *skb = NULL;
 	unsigned long nr_pages, limit;
-	int order, i, max_share;
+	int i, max_share, cnt;
 
 	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
 
@@ -2929,31 +2931,23 @@
 		INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
 	}
 
-	/* Try to be a bit smarter and adjust defaults depending
-	 * on available memory.
-	 */
-	for (order = 0; ((1 << order) << PAGE_SHIFT) <
-			(tcp_hashinfo.bhash_size * sizeof(struct inet_bind_hashbucket));
-			order++)
-		;
-	if (order >= 4) {
-		tcp_death_row.sysctl_max_tw_buckets = 180000;
-		sysctl_tcp_max_orphans = 4096 << (order - 4);
-		sysctl_max_syn_backlog = 1024;
-	} else if (order < 3) {
-		tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
-		sysctl_tcp_max_orphans >>= (3 - order);
-		sysctl_max_syn_backlog = 128;
-	}
+
+	cnt = tcp_hashinfo.ehash_size;
+
+	tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
+	sysctl_tcp_max_orphans = cnt / 2;
+	sysctl_max_syn_backlog = max(128, cnt / 256);
 
 	/* Set the pressure threshold to be a fraction of global memory that
 	 * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
-	 * memory, with a floor of 128 pages.
+	 * memory, with a floor of 128 pages, and a ceiling that prevents an
+	 * integer overflow.
 	 */
 	nr_pages = totalram_pages - totalhigh_pages;
 	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
 	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
 	limit = max(limit, 128UL);
+	limit = min(limit, INT_MAX * 4UL / 3 / 2);
 	sysctl_tcp_mem[0] = limit / 4 * 3;
 	sysctl_tcp_mem[1] = limit;
 	sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
--- linux-ec2-2.6.32.orig/net/ipv4/tcp_input.c
+++ linux-ec2-2.6.32/net/ipv4/tcp_input.c
@@ -3969,6 +3969,8 @@
 	default:
 		sk->sk_err = ECONNRESET;
 	}
+	/* This barrier is coupled with smp_rmb() in tcp_poll() */
+	smp_wmb();
 
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_error_report(sk);
@@ -5699,11 +5701,9 @@
 
 				/* tcp_ack considers this ACK as duplicate
 				 * and does not calculate rtt.
-				 * Fix it at least with timestamps.
+				 * Force it here.
 				 */
-				if (tp->rx_opt.saw_tstamp &&
-				    tp->rx_opt.rcv_tsecr && !tp->srtt)
-					tcp_ack_saw_tstamp(sk, 0);
+				tcp_ack_update_rtt(sk, 0, 0);
 
 				if (tp->rx_opt.tstamp_ok)
 					tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
--- linux-ec2-2.6.32.orig/net/ipv4/fib_frontend.c
+++ linux-ec2-2.6.32/net/ipv4/fib_frontend.c
@@ -251,6 +251,8 @@
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
 		rpf = IN_DEV_RPFILTER(in_dev);
+		if (mark && !IN_DEV_SRC_VMARK(in_dev))
+			fl.mark = 0;
 	}
 	rcu_read_unlock();
 
--- linux-ec2-2.6.32.orig/net/ipv4/ip_output.c
+++ linux-ec2-2.6.32/net/ipv4/ip_output.c
@@ -476,9 +476,8 @@
 	 * we can switch to copy when see the first bad fragment.
 	 */
 	if (skb_has_frags(skb)) {
-		struct sk_buff *frag;
+		struct sk_buff *frag, *frag2;
 		int first_len = skb_pagelen(skb);
-		int truesizes = 0;
 
 		if (first_len - hlen > mtu ||
 		    ((first_len - hlen) & 7) ||
@@ -491,18 +490,18 @@
 			if (frag->len > mtu ||
 			    ((frag->len & 7) && frag->next) ||
 			    skb_headroom(frag) < hlen)
-			    goto slow_path;
+				goto slow_path_clean;
 
 			/* Partially cloned skb? */
 			if (skb_shared(frag))
-				goto slow_path;
+				goto slow_path_clean;
 
 			BUG_ON(frag->sk);
 			if (skb->sk) {
 				frag->sk = skb->sk;
 				frag->destructor = sock_wfree;
-				truesizes += frag->truesize;
 			}
+			skb->truesize -= frag->truesize;
 		}
 
 		/* Everything is OK. Generate! */
@@ -512,7 +511,6 @@
 		frag = skb_shinfo(skb)->frag_list;
 		skb_frag_list_init(skb);
 		skb->data_len = first_len - skb_headlen(skb);
-		skb->truesize -= truesizes;
 		skb->len = first_len;
 		iph->tot_len = htons(first_len);
 		iph->frag_off = htons(IP_MF);
@@ -564,6 +562,15 @@
 		}
 		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
 		return err;
+
+slow_path_clean:
+		skb_walk_frags(skb, frag2) {
+			if (frag2 == frag)
+				break;
+			frag2->sk = NULL;
+			frag2->destructor = NULL;
+			skb->truesize += frag2->truesize;
+		}
 	}
 
 slow_path:
@@ -860,8 +867,10 @@
 	    !exthdrlen)
 		csummode = CHECKSUM_PARTIAL;
 
+	skb = skb_peek_tail(&sk->sk_write_queue);
+
 	inet->cork.length += length;
-	if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+	if (((length > mtu) || (skb && skb_is_gso(skb))) &&
 	    (sk->sk_protocol == IPPROTO_UDP) &&
 	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
 		err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -879,7 +888,7 @@
 	 * adding appropriate IP header.
 	 */
 
-	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+	if (!skb)
 		goto alloc_new_skb;
 
 	while (length > 0) {
@@ -1108,7 +1117,8 @@
 		return -EINVAL;
 
 	inet->cork.length += size;
-	if ((sk->sk_protocol == IPPROTO_UDP) &&
+	if ((size + skb->len > mtu) &&
+	    (sk->sk_protocol == IPPROTO_UDP) &&
 	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
 		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
--- linux-ec2-2.6.32.orig/net/ipv4/route.c
+++ linux-ec2-2.6.32/net/ipv4/route.c
@@ -2712,6 +2712,11 @@
 
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
+static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
+{
+	return NULL;
+}
+
 static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
@@ -2720,7 +2725,7 @@
 	.family			=	AF_INET,
 	.protocol		=	cpu_to_be16(ETH_P_IP),
 	.destroy		=	ipv4_dst_destroy,
-	.check			=	ipv4_dst_check,
+	.check			=	ipv4_blackhole_dst_check,
 	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,
 	.entries		=	ATOMIC_INIT(0),
 };
--- linux-ec2-2.6.32.orig/net/ipv4/tcp_timer.c
+++ linux-ec2-2.6.32/net/ipv4/tcp_timer.c
@@ -65,18 +65,18 @@
 static int tcp_out_of_resources(struct sock *sk, int do_reset)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	int orphans = percpu_counter_read_positive(&tcp_orphan_count);
+	int shift = 0;
 
 	/* If peer does not open window for long time, or did not transmit
 	 * anything for long time, penalize it. */
 	if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
-		orphans <<= 1;
+		shift++;
 
 	/* If some dubious ICMP arrived, penalize even more. */
 	if (sk->sk_err_soft)
-		orphans <<= 1;
+		shift++;
 
-	if (tcp_too_many_orphans(sk, orphans)) {
+	if (tcp_too_many_orphans(sk, shift)) {
 		if (net_ratelimit())
 			printk(KERN_INFO "Out of socket memory\n");
 
--- linux-ec2-2.6.32.orig/net/ipv4/xfrm4_output.c
+++ linux-ec2-2.6.32/net/ipv4/xfrm4_output.c
@@ -81,7 +81,7 @@
 #endif
 
 	skb->protocol = htons(ETH_P_IP);
-	return xfrm_output(skb);
+	return skb_checksum_setup(skb) ?: xfrm_output(skb);
 }
 
 int xfrm4_output(struct sk_buff *skb)
--- linux-ec2-2.6.32.orig/net/ipv4/xfrm4_policy.c
+++ linux-ec2-2.6.32/net/ipv4/xfrm4_policy.c
@@ -71,7 +71,7 @@
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 		    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-		    xdst->u.rt.fl.fl4_tos == fl->fl4_tos &&
+                    !((xdst->u.rt.fl.fl4_tos ^ fl->fl4_tos) & IPTOS_RT_MASK) &&
 		    xfrm_bundle_ok(policy, xdst, fl, AF_INET, 0)) {
 			dst_clone(dst);
 			break;
@@ -83,7 +83,7 @@
 
 static int xfrm4_get_tos(struct flowi *fl)
 {
-	return fl->fl4_tos;
+	return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */
 }
 
 static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
--- linux-ec2-2.6.32.orig/net/ipv4/ipip.c
+++ linux-ec2-2.6.32/net/ipv4/ipip.c
@@ -853,3 +853,4 @@
 module_init(ipip_init);
 module_exit(ipip_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETDEV("tunl0");
--- linux-ec2-2.6.32.orig/net/ipv4/inet_diag.c
+++ linux-ec2-2.6.32/net/ipv4/inet_diag.c
@@ -489,9 +489,11 @@
 {
 	struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
 
-	if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
+	if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
 		struct inet_diag_entry entry;
-		struct rtattr *bc = (struct rtattr *)(r + 1);
+		const struct nlattr *bc = nlmsg_find_attr(cb->nlh,
+							  sizeof(*r),
+							  INET_DIAG_REQ_BYTECODE);
 		struct inet_sock *inet = inet_sk(sk);
 
 		entry.family = sk->sk_family;
@@ -511,7 +513,7 @@
 		entry.dport = ntohs(inet->dport);
 		entry.userlocks = sk->sk_userlocks;
 
-		if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
+		if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry))
 			return 0;
 	}
 
@@ -526,9 +528,11 @@
 {
 	struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
 
-	if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
+	if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
 		struct inet_diag_entry entry;
-		struct rtattr *bc = (struct rtattr *)(r + 1);
+		const struct nlattr *bc = nlmsg_find_attr(cb->nlh,
+							  sizeof(*r),
+							  INET_DIAG_REQ_BYTECODE);
 
 		entry.family = tw->tw_family;
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -547,7 +551,7 @@
 		entry.dport = ntohs(tw->tw_dport);
 		entry.userlocks = 0;
 
-		if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
+		if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry))
 			return 0;
 	}
 
@@ -617,7 +621,7 @@
 	struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct listen_sock *lopt;
-	struct rtattr *bc = NULL;
+	const struct nlattr *bc = NULL;
 	struct inet_sock *inet = inet_sk(sk);
 	int j, s_j;
 	int reqnum, s_reqnum;
@@ -637,8 +641,9 @@
 	if (!lopt || !lopt->qlen)
 		goto out;
 
-	if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) {
-		bc = (struct rtattr *)(r + 1);
+	if (nlmsg_attrlen(cb->nlh, sizeof(*r))) {
+		bc = nlmsg_find_attr(cb->nlh, sizeof(*r),
+				     INET_DIAG_REQ_BYTECODE);
 		entry.sport = inet->num;
 		entry.userlocks = sk->sk_userlocks;
 	}
@@ -671,8 +676,8 @@
 					&ireq->rmt_addr;
 				entry.dport = ntohs(ireq->rmt_port);
 
-				if (!inet_diag_bc_run(RTA_DATA(bc),
-						    RTA_PAYLOAD(bc), &entry))
+				if (!inet_diag_bc_run(nla_data(bc),
+						      nla_len(bc), &entry))
 					continue;
 			}
 
--- linux-ec2-2.6.32.orig/net/ipv4/igmp.c
+++ linux-ec2-2.6.32/net/ipv4/igmp.c
@@ -946,7 +946,6 @@
 		break;
 	case IGMP_HOST_MEMBERSHIP_REPORT:
 	case IGMPV2_HOST_MEMBERSHIP_REPORT:
-	case IGMPV3_HOST_MEMBERSHIP_REPORT:
 		/* Is it our report looped back? */
 		if (skb_rtable(skb)->fl.iif == 0)
 			break;
@@ -960,6 +959,7 @@
 		in_dev_put(in_dev);
 		return pim_rcv_v1(skb);
 #endif
+	case IGMPV3_HOST_MEMBERSHIP_REPORT:
 	case IGMP_DVMRP:
 	case IGMP_TRACE:
 	case IGMP_HOST_LEAVE_MESSAGE:
--- linux-ec2-2.6.32.orig/net/ipv4/ip_gre.c
+++ linux-ec2-2.6.32/net/ipv4/ip_gre.c
@@ -1708,3 +1708,4 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_RTNL_LINK("gre");
 MODULE_ALIAS_RTNL_LINK("gretap");
+MODULE_ALIAS_NETDEV("gre0");
--- linux-ec2-2.6.32.orig/net/ipv4/udp.c
+++ linux-ec2-2.6.32/net/ipv4/udp.c
@@ -1292,6 +1292,9 @@
 
 	uh   = udp_hdr(skb);
 	ulen = ntohs(uh->len);
+	saddr = ip_hdr(skb)->saddr;
+	daddr = ip_hdr(skb)->daddr;
+
 	if (ulen > skb->len)
 		goto short_packet;
 
@@ -1305,9 +1308,6 @@
 	if (udp4_csum_init(skb, uh, proto))
 		goto csum_error;
 
-	saddr = ip_hdr(skb)->saddr;
-	daddr = ip_hdr(skb)->daddr;
-
 	if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
 		return __udp4_lib_mcast_deliver(net, skb, uh,
 				saddr, daddr, udptable);
@@ -1832,12 +1832,14 @@
 	udp_table_init(&udp_table);
 	/* Set the pressure threshold up by the same strategy of TCP. It is a
 	 * fraction of global memory that is up to 1/2 at 256 MB, decreasing
-	 * toward zero with the amount of memory, with a floor of 128 pages.
+	 * toward zero with the amount of memory, with a floor of 128 pages,
+	 * and a ceiling that prevents an integer overflow.
 	 */
 	nr_pages = totalram_pages - totalhigh_pages;
 	limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
 	limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
 	limit = max(limit, 128UL);
+	limit = min(limit, INT_MAX * 4UL / 3 / 2);
 	sysctl_udp_mem[0] = limit / 4 * 3;
 	sysctl_udp_mem[1] = limit;
 	sysctl_udp_mem[2] = sysctl_udp_mem[0] * 2;
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -60,6 +60,10 @@
 		newport = tuple->dst.u.udp.port;
 		portptr = &hdr->dest;
 	}
+
+	if (skb_checksum_setup(skb))
+		return false;
+
 	if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) {
 		inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
 		inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -32,7 +32,7 @@
 	struct hlist_nulls_node *n;
 
 	for (st->bucket = 0;
-	     st->bucket < nf_conntrack_htable_size;
+	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
 		n = rcu_dereference(net->ct.hash[st->bucket].first);
 		if (!is_a_nulls(n))
@@ -50,7 +50,7 @@
 	head = rcu_dereference(head->next);
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
-			if (++st->bucket >= nf_conntrack_htable_size)
+			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
 		head = rcu_dereference(net->ct.hash[st->bucket].first);
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -75,6 +75,9 @@
 	if (hdrsize < sizeof(*hdr))
 		return true;
 
+	if (skb_checksum_setup(skb))
+		return false;
+
 	inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
 	inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
 	return true;
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -14,6 +14,7 @@
 #include <net/route.h>
 #include <net/ip.h>
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
 
@@ -34,6 +35,20 @@
 	return err;
 }
 
+static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
+					      struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP_DEFRAG_CONNTRACK_IN;
+	else
+		return IP_DEFRAG_CONNTRACK_OUT;
+}
+
 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
 					  struct sk_buff *skb,
 					  const struct net_device *in,
@@ -50,10 +65,8 @@
 #endif
 	/* Gather fragments. */
 	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (nf_ct_ipv4_gather_frags(skb,
-					    hooknum == NF_INET_PRE_ROUTING ?
-					    IP_DEFRAG_CONNTRACK_IN :
-					    IP_DEFRAG_CONNTRACK_OUT))
+		enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
+		if (nf_ct_ipv4_gather_frags(skb, user))
 			return NF_STOLEN;
 	}
 	return NF_ACCEPT;
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -666,8 +666,11 @@
 	struct clusterip_config *c = pde->data;
 	unsigned long nodenum;
 
-	if (copy_from_user(buffer, input, PROC_WRITELEN))
+	if (size > PROC_WRITELEN)
+		return -EIO;
+	if (copy_from_user(buffer, input, size))
 		return -EFAULT;
+	buffer[size] = 0;
 
 	if (*buffer == '+') {
 		nodenum = simple_strtoul(buffer+1, NULL, 10);
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -213,7 +213,7 @@
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
 		.procname	= "ip_conntrack_buckets",
-		.data		= &nf_conntrack_htable_size,
+		.data		= &init_net.ct.htable_size,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0444,
 		.proc_handler	= proc_dointvec,
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/ip_tables.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/ip_tables.c
@@ -1132,10 +1132,10 @@
 	if (t && !IS_ERR(t)) {
 		struct ipt_getinfo info;
 		const struct xt_table_info *private = t->private;
-
 #ifdef CONFIG_COMPAT
+		struct xt_table_info tmp;
+
 		if (compat) {
-			struct xt_table_info tmp;
 			ret = compat_table_info(private, &tmp);
 			xt_compat_flush_offsets(AF_INET);
 			private = &tmp;
@@ -1290,6 +1290,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1820,6 +1821,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2044,6 +2046,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IPT_SO_GET_REVISION_TARGET)
 			target = 1;
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/arp_tables.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/arp_tables.c
@@ -925,10 +925,10 @@
 	if (t && !IS_ERR(t)) {
 		struct arpt_getinfo info;
 		const struct xt_table_info *private = t->private;
-
 #ifdef CONFIG_COMPAT
+		struct xt_table_info tmp;
+
 		if (compat) {
-			struct xt_table_info tmp;
 			ret = compat_table_info(private, &tmp);
 			xt_compat_flush_offsets(NFPROTO_ARP);
 			private = &tmp;
@@ -1086,6 +1086,7 @@
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1508,6 +1509,7 @@
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1763,6 +1765,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
 							 rev.revision, 1, &ret),
--- linux-ec2-2.6.32.orig/net/ipv4/netfilter/nf_nat_core.c
+++ linux-ec2-2.6.32/net/ipv4/netfilter/nf_nat_core.c
@@ -35,9 +35,6 @@
 
 static struct nf_conntrack_l3proto *l3proto __read_mostly;
 
-/* Calculated at init based on memory size */
-static unsigned int nf_nat_htable_size __read_mostly;
-
 #define MAX_IP_NAT_PROTO 256
 static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
 						__read_mostly;
@@ -72,7 +69,7 @@
 
 /* We keep an extra hash for each conntrack, for fast searching. */
 static inline unsigned int
-hash_by_src(const struct nf_conntrack_tuple *tuple)
+hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple)
 {
 	unsigned int hash;
 
@@ -80,7 +77,7 @@
 	hash = jhash_3words((__force u32)tuple->src.u3.ip,
 			    (__force u32)tuple->src.u.all,
 			    tuple->dst.protonum, 0);
-	return ((u64)hash * nf_nat_htable_size) >> 32;
+	return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -147,7 +144,7 @@
 		     struct nf_conntrack_tuple *result,
 		     const struct nf_nat_range *range)
 {
-	unsigned int h = hash_by_src(tuple);
+	unsigned int h = hash_by_src(net, tuple);
 	const struct nf_conn_nat *nat;
 	const struct nf_conn *ct;
 	const struct hlist_node *n;
@@ -330,7 +327,7 @@
 	if (have_to_hash) {
 		unsigned int srchash;
 
-		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+		srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		spin_lock_bh(&nf_nat_lock);
 		/* nf_conntrack_alter_reply might re-allocate exntension aera */
 		nat = nfct_nat(ct);
@@ -679,8 +676,10 @@
 
 static int __net_init nf_nat_net_init(struct net *net)
 {
-	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
-						      &net->ipv4.nat_vmalloced, 0);
+	/* Leave them the same for the moment. */
+	net->ipv4.nat_htable_size = net->ct.htable_size;
+	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size,
+						       &net->ipv4.nat_vmalloced, 0);
 	if (!net->ipv4.nat_bysource)
 		return -ENOMEM;
 	return 0;
@@ -703,7 +702,7 @@
 	nf_ct_iterate_cleanup(net, &clean_nat, NULL);
 	synchronize_rcu();
 	nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced,
-			     nf_nat_htable_size);
+			     net->ipv4.nat_htable_size);
 }
 
 static struct pernet_operations nf_nat_net_ops = {
@@ -724,9 +723,6 @@
 		return ret;
 	}
 
-	/* Leave them the same for the moment. */
-	nf_nat_htable_size = nf_conntrack_htable_size;
-
 	ret = register_pernet_subsys(&nf_nat_net_ops);
 	if (ret < 0)
 		goto cleanup_extend;
--- linux-ec2-2.6.32.orig/net/netrom/nr_route.c
+++ linux-ec2-2.6.32/net/netrom/nr_route.c
@@ -842,12 +842,13 @@
 	dptr  = skb_push(skb, 1);
 	*dptr = AX25_P_NETROM;
 
-	ax25s = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
-	if (nr_neigh->ax25 && ax25s) {
-		/* We were already holding this ax25_cb */
+	ax25s = nr_neigh->ax25;
+	nr_neigh->ax25 = ax25_send_frame(skb, 256,
+					 (ax25_address *)dev->dev_addr,
+					 &nr_neigh->callsign,
+					 nr_neigh->digipeat, nr_neigh->dev);
+	if (ax25s)
 		ax25_cb_put(ax25s);
-	}
-	nr_neigh->ax25 = ax25s;
 
 	dev_put(dev);
 	ret = (nr_neigh->ax25 != NULL);
--- linux-ec2-2.6.32.orig/net/wireless/wext.c
+++ linux-ec2-2.6.32/net/wireless/wext.c
@@ -854,6 +854,22 @@
 		}
 	}
 
+	if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
+		/*
+		 * If this is a GET, but not NOMAX, it means that the extra
+		 * data is not bounded by userspace, but by max_tokens. Thus
+		 * set the length to max_tokens. This matches the extra data
+		 * allocation.
+		 * The driver should fill it with the number of tokens it
+		 * provided, and it may check iwp->length rather than having
+		 * knowledge of max_tokens. If the driver doesn't change the
+		 * iwp->length, this ioctl just copies back max_token tokens
+		 * filled with zeroes. Hopefully the driver isn't claiming
+		 * them to be valid data.
+		 */
+		iwp->length = descr->max_tokens;
+	}
+
 	err = handler(dev, info, (union iwreq_data *) iwp, extra);
 
 	iwp->length += essid_compat;
@@ -1013,7 +1029,7 @@
 	} else if (!iwp->pointer)
 		return -EFAULT;
 
-	extra = kmalloc(extra_size, GFP_KERNEL);
+	extra = kzalloc(extra_size, GFP_KERNEL);
 	if (!extra)
 		return -ENOMEM;
 
--- linux-ec2-2.6.32.orig/net/wireless/mlme.c
+++ linux-ec2-2.6.32/net/wireless/mlme.c
@@ -43,10 +43,10 @@
 		}
 	}
 
-	WARN_ON(!done);
-
-	nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
-	cfg80211_sme_rx_auth(dev, buf, len);
+	if (done) {
+		nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
+		cfg80211_sme_rx_auth(dev, buf, len);
+	}
 
 	wdev_unlock(wdev);
 }
@@ -94,7 +94,18 @@
 			}
 		}
 
-		WARN_ON(!bss);
+		/*
+		 * We might be coming here because the driver reported
+		 * a successful association at the same time as the
+		 * user requested a deauth. In that case, we will have
+		 * removed the BSS from the auth_bsses list due to the
+		 * deauth request when the assoc response makes it. If
+		 * the two code paths acquire the lock the other way
+		 * around, that's just the standard situation of a
+		 * deauth being requested while connected.
+		 */
+		if (!bss)
+			goto out;
 	} else if (wdev->conn) {
 		cfg80211_sme_failed_assoc(wdev);
 		need_connect_result = false;
--- linux-ec2-2.6.32.orig/net/wireless/reg.c
+++ linux-ec2-2.6.32/net/wireless/reg.c
@@ -1714,7 +1714,7 @@
 	request->wiphy_idx = WIPHY_IDX_STALE;
 	request->alpha2[0] = alpha2[0];
 	request->alpha2[1] = alpha2[1];
-	request->initiator = NL80211_REGDOM_SET_BY_USER,
+	request->initiator = NL80211_REGDOM_SET_BY_USER;
 
 	queue_regulatory_request(request);
 
--- linux-ec2-2.6.32.orig/net/wireless/scan.c
+++ linux-ec2-2.6.32/net/wireless/scan.c
@@ -270,6 +270,7 @@
 {
 	struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
 	struct cfg80211_internal_bss *bss, *res = NULL;
+	unsigned long now = jiffies;
 
 	spin_lock_bh(&dev->bss_lock);
 
@@ -278,6 +279,10 @@
 			continue;
 		if (channel && bss->pub.channel != channel)
 			continue;
+		/* Don't get expired BSS structs */
+		if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
+		    !atomic_read(&bss->hold))
+			continue;
 		if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
 			res = bss;
 			kref_get(&res->ref);
--- linux-ec2-2.6.32.orig/net/wireless/core.h
+++ linux-ec2-2.6.32/net/wireless/core.h
@@ -385,6 +385,8 @@
 		  struct wireless_dev *for_wdev,
 		  int freq, enum nl80211_channel_type channel_type);
 
+u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
 #define CFG80211_DEV_WARN_ON(cond)	WARN_ON(cond)
 #else
--- linux-ec2-2.6.32.orig/net/wireless/nl80211.c
+++ linux-ec2-2.6.32/net/wireless/nl80211.c
@@ -1562,39 +1562,6 @@
 	return 0;
 }
 
-static u16 nl80211_calculate_bitrate(struct rate_info *rate)
-{
-	int modulation, streams, bitrate;
-
-	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
-		return rate->legacy;
-
-	/* the formula below does only work for MCS values smaller than 32 */
-	if (rate->mcs >= 32)
-		return 0;
-
-	modulation = rate->mcs & 7;
-	streams = (rate->mcs >> 3) + 1;
-
-	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
-			13500000 : 6500000;
-
-	if (modulation < 4)
-		bitrate *= (modulation + 1);
-	else if (modulation == 4)
-		bitrate *= (modulation + 2);
-	else
-		bitrate *= (modulation + 3);
-
-	bitrate *= streams;
-
-	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
-		bitrate = (bitrate / 9) * 10;
-
-	/* do NOT round down here */
-	return (bitrate + 50000) / 100000;
-}
-
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1641,8 +1608,8 @@
 		if (!txrate)
 			goto nla_put_failure;
 
-		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
-		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
 		if (bitrate > 0)
 			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
--- linux-ec2-2.6.32.orig/net/wireless/sme.c
+++ linux-ec2-2.6.32/net/wireless/sme.c
@@ -655,6 +655,7 @@
 	memset(&wrqu, 0, sizeof(wrqu));
 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 	wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+	wdev->wext.connect.ssid_len = 0;
 #endif
 }
 
--- linux-ec2-2.6.32.orig/net/wireless/util.c
+++ linux-ec2-2.6.32/net/wireless/util.c
@@ -682,3 +682,36 @@
 
 	return err;
 }
+
+u16 cfg80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
--- linux-ec2-2.6.32.orig/net/wireless/wext-compat.c
+++ linux-ec2-2.6.32/net/wireless/wext-compat.c
@@ -1227,10 +1227,7 @@
 	if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
 		return -EOPNOTSUPP;
 
-	rate->value = 0;
-
-	if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
-		rate->value = 100000 * sinfo.txrate.legacy;
+	rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
 
 	return 0;
 }
@@ -1361,6 +1358,9 @@
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 
+	data->flags = 0;
+	data->length = 0;
+
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_ADHOC:
 		return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
--- linux-ec2-2.6.32.orig/net/bridge/br_netfilter.c
+++ linux-ec2-2.6.32/net/bridge/br_netfilter.c
@@ -600,6 +600,9 @@
 
 	pskb_trim_rcsum(skb, len);
 
+	/* BUG: Should really parse the IP options here. */
+	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+
 	nf_bridge_put(skb->nf_bridge);
 	if (!nf_bridge_alloc(skb))
 		return NF_DROP;
@@ -797,9 +800,11 @@
 	if (skb->nfct != NULL &&
 	    (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) &&
 	    skb->len > skb->dev->mtu &&
-	    !skb_is_gso(skb))
+	    !skb_is_gso(skb)) {
+		/* BUG: Should really parse the IP options here. */
+		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
 		return ip_fragment(skb, br_dev_queue_push_xmit);
-	else
+	} else
 		return br_dev_queue_push_xmit(skb);
 }
 #else
--- linux-ec2-2.6.32.orig/net/bridge/netfilter/ebtables.c
+++ linux-ec2-2.6.32/net/bridge/netfilter/ebtables.c
@@ -979,6 +979,8 @@
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
 
+	tmp.name[sizeof(tmp.name) - 1] = 0;
+
 	countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
 	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
@@ -1406,6 +1408,9 @@
 {
 	int ret;
 
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
 	switch(cmd) {
 	case EBT_SO_SET_ENTRIES:
 		ret = do_replace(sock_net(sk), user, len);
@@ -1425,6 +1430,9 @@
 	struct ebt_replace tmp;
 	struct ebt_table *t;
 
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
 	if (copy_from_user(&tmp, user, sizeof(tmp)))
 		return -EFAULT;
 
--- linux-ec2-2.6.32.orig/net/unix/af_unix.c
+++ linux-ec2-2.6.32/net/unix/af_unix.c
@@ -671,6 +671,7 @@
 	static u32 ordernum = 1;
 	struct unix_address *addr;
 	int err;
+	unsigned int retries = 0;
 
 	mutex_lock(&u->readlock);
 
@@ -696,9 +697,17 @@
 	if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
 				      addr->hash)) {
 		spin_unlock(&unix_table_lock);
-		/* Sanity yield. It is unusual case, but yet... */
-		if (!(ordernum&0xFF))
-			yield();
+		/*
+		 * __unix_find_socket_byname() may take long time if many names
+		 * are already in use.
+		 */
+		cond_resched();
+		/* Give up if all names seems to be in use. */
+		if (retries++ == 0xFFFFF) {
+			err = -ENOSPC;
+			kfree(addr);
+			goto out;
+		}
 		goto retry;
 	}
 	addr->hash ^= sk->sk_type;
@@ -1314,9 +1323,25 @@
 	sock_wfree(skb);
 }
 
+#define MAX_RECURSION_LEVEL 4
+
 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 {
 	int i;
+	unsigned char max_level = 0;
+	int unix_sock_count = 0;
+
+	for (i = scm->fp->count - 1; i >= 0; i--) {
+		struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+
+		if (sk) {
+			unix_sock_count++;
+			max_level = max(max_level,
+					unix_sk(sk)->recursion_level);
+		}
+	}
+	if (unlikely(max_level > MAX_RECURSION_LEVEL))
+		return -ETOOMANYREFS;
 
 	/*
 	 * Need to duplicate file references for the sake of garbage
@@ -1327,10 +1352,12 @@
 	if (!UNIXCB(skb).fp)
 		return -ENOMEM;
 
-	for (i = scm->fp->count-1; i >= 0; i--)
-		unix_inflight(scm->fp->fp[i]);
+	if (unix_sock_count) {
+		for (i = scm->fp->count - 1; i >= 0; i--)
+			unix_inflight(scm->fp->fp[i]);
+	}
 	skb->destructor = unix_destruct_fds;
-	return 0;
+	return max_level;
 }
 
 /*
@@ -1352,6 +1379,7 @@
 	struct sk_buff *skb;
 	long timeo;
 	struct scm_cookie tmp_scm;
+	int max_level = 0;
 
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
@@ -1392,8 +1420,9 @@
 	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 	if (siocb->scm->fp) {
 		err = unix_attach_fds(siocb->scm, skb);
-		if (err)
+		if (err < 0)
 			goto out_free;
+		max_level = err + 1;
 	}
 	unix_get_secdata(siocb->scm, skb);
 
@@ -1474,6 +1503,8 @@
 	}
 
 	skb_queue_tail(&other->sk_receive_queue, skb);
+	if (max_level > unix_sk(other)->recursion_level)
+		unix_sk(other)->recursion_level = max_level;
 	unix_state_unlock(other);
 	other->sk_data_ready(other, len);
 	sock_put(other);
@@ -1504,6 +1535,7 @@
 	int sent = 0;
 	struct scm_cookie tmp_scm;
 	bool fds_sent = false;
+	int max_level = 0;
 
 	if (NULL == siocb->scm)
 		siocb->scm = &tmp_scm;
@@ -1568,10 +1600,11 @@
 		/* Only send the fds in the first buffer */
 		if (siocb->scm->fp && !fds_sent) {
 			err = unix_attach_fds(siocb->scm, skb);
-			if (err) {
+			if (err < 0) {
 				kfree_skb(skb);
 				goto out_err;
 			}
+			max_level = err + 1;
 			fds_sent = true;
 		}
 
@@ -1588,6 +1621,8 @@
 			goto pipe_err_free;
 
 		skb_queue_tail(&other->sk_receive_queue, skb);
+		if (max_level > unix_sk(other)->recursion_level)
+			unix_sk(other)->recursion_level = max_level;
 		unix_state_unlock(other);
 		other->sk_data_ready(other, size);
 		sent += size;
@@ -1804,6 +1839,7 @@
 		unix_state_lock(sk);
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		if (skb == NULL) {
+			unix_sk(sk)->recursion_level = 0;
 			if (copied >= target)
 				goto unlock;
 
--- linux-ec2-2.6.32.orig/net/unix/garbage.c
+++ linux-ec2-2.6.32/net/unix/garbage.c
@@ -97,7 +97,7 @@
 unsigned int unix_tot_inflight;
 
 
-static struct sock *unix_get_socket(struct file *filp)
+struct sock *unix_get_socket(struct file *filp)
 {
 	struct sock *u_sock = NULL;
 	struct inode *inode = filp->f_path.dentry->d_inode;
@@ -269,9 +269,16 @@
 }
 
 static bool gc_in_progress = false;
+#define UNIX_INFLIGHT_TRIGGER_GC 16000
 
 void wait_for_unix_gc(void)
 {
+	/*
+	 * If number of inflight sockets is insane,
+	 * force a garbage collect right now.
+	 */
+	if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+		unix_gc();
 	wait_event(unix_gc_wait, gc_in_progress == false);
 }
 
--- linux-ec2-2.6.32.orig/debian.master/changelog
+++ linux-ec2-2.6.32/debian.master/changelog
@@ -0,0 +1,8914 @@
+linux (2.6.32-33.70) lucid-proposed; urgency=low
+
+  [Steve Conklin]
+
+  * Release Tracking Bug
+    - LP: #807175
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "x86: Flush TLB if PGD entry is changed in i386 PAE mode"
+    - LP: #805209
+
+ -- Steve Conklin <sconklin@canonical.com>  Thu, 07 Jul 2011 14:08:13 -0500
+
+linux (2.6.32-33.69) lucid-proposed; urgency=low
+
+  [Steve Conklin]
+
+  * Release Tracking Bug
+    - LP: #802554
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "af_unix: Only allow recv on connected seqpacket sockets."
+
+ -- Steve Conklin <sconklin@canonical.com>  Wed, 22 Jun 2011 10:53:16 -0500
+
+linux (2.6.32-33.68) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Release Tracking Bug
+    - LP: #798305
+  * Fix abi directory
+
+ -- Steve Conklin <sconklin@canonical.com>  Fri, 17 Jun 2011 09:41:35 -0500
+
+linux (2.6.32-33.67) lucid-proposed; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "iwlagn: Support new 5000 microcode."
+
+ -- Steve Conklin <sconklin@canonical.com>  Thu, 16 Jun 2011 10:51:45 -0500
+
+linux (2.6.32-33.66) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #794098
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "xhci: Fix full speed bInterval encoding."
+  * Revert "USB: xhci - fix math in xhci_get_endpoint_interval()"
+  * Revert "USB: xhci - fix unsafe macro definitions"
+
+ -- Brad Figg <brad.figg@canonical.com>  Tue, 07 Jun 2011 08:06:27 -0700
+
+linux (2.6.32-33.65) lucid-proposed; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * xhci: Fix full speed bInterval encoding.
+    - LP: #792959
+
+ -- Steve Conklin <sconklin@canonical.com>  Sat, 04 Jun 2011 18:41:10 -0500
+
+linux (2.6.32-33.64) lucid-proposed; urgency=low
+
+  [ Herton R. Krzesinski ]
+
+   * Release Tracking Bug
+     - LP: #789325
+
+  [ Leann Ogasawara ]
+
+  * SAUCE: (no-up) Fix up KVM: VMX: Fix host userspace gsbase corruption
+    - LP: #787675
+
+  [ Thomas Schlichter ]
+
+  * SAUCE: vesafb: mtrr module parameter is uint, not bool
+    - LP: #778043
+
+  [ Tim Gardner ]
+
+  * Revert "(pre-stable): input: Support Clickpad devices in ClickZone
+    mode"
+    - LP: #780588
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "GFS2: Fix writing to non-page aligned gfs2_quota structures"
+    - LP: #780588
+  * Revert "mmc: build fix: mmc_pm_notify is only available with
+    CONFIG_PM=y"
+    - LP: #780588
+  * Revert "mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume"
+    - LP: #780588
+  * Revert "econet: fix CVE-2010-3848"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "dell-laptop: Add another Dell laptop family to the DMI
+    whitelist"
+    - LP: #780588
+  * Revert "xen: set max_pfn_mapped to the last pfn mapped"
+  * cifs: always do is_path_accessible check in cifs_mount
+    - LP: #770050
+  * video: sn9c102: world-wirtable sysfs files
+    - LP: #770050
+  * UBIFS: restrict world-writable debugfs files
+    - LP: #770050
+  * NET: cdc-phonet, handle empty phonet header
+    - LP: #770050
+  * x86: Fix a bogus unwind annotation in lib/semaphore_32.S
+    - LP: #770050
+  * tioca: Fix assignment from incompatible pointer warnings
+    - LP: #770050
+  * mca.c: Fix cast from integer to pointer warning
+    - LP: #770050
+  * ramfs: fix memleak on no-mmu arch
+    - LP: #770050
+  * MAINTAINERS: update STABLE BRANCH info
+    - LP: #770050
+  * UBIFS: fix oops when R/O file-system is fsync'ed
+    - LP: #770050
+  * x86, cpu: AMD errata checking framework
+    - LP: #770050
+  * x86, cpu: Clean up AMD erratum 400 workaround
+    - LP: #770050
+  * x86, AMD: Set ARAT feature on AMD processors
+    - LP: #770050
+  * x86, amd: Disable GartTlbWlkErr when BIOS forgets it
+    - LP: #770050
+  * USB: ftdi_sio: Added IDs for CTI USB Serial Devices
+    - LP: #770050
+  * USB: ftdi_sio: add PID for OCT DK201 docking station
+    - LP: #770050
+  * USB: ftdi_sio: add ids for Hameg HO720 and HO730
+    - LP: #770050
+  * USB: option: Add new ONDA vendor id and product id for ONDA MT825UP
+    - LP: #770050
+  * USB: option: Added support for Samsung GT-B3730/GT-B3710 LTE USB modem.
+    - LP: #770050
+  * next_pidmap: fix overflow condition
+    - LP: #770050
+  * proc: do proper range check on readdir offset
+    - LP: #770050
+  * USB: EHCI: unlink unused QHs when the controller is stopped
+    - LP: #770050
+  * USB: fix formatting of SuperSpeed endpoints in /proc/bus/usb/devices
+    - LP: #770050
+  * USB: xhci - fix unsafe macro definitions
+    - LP: #770050
+  * USB: xhci - fix math in xhci_get_endpoint_interval()
+    - LP: #770050
+  * x86, cpu: Fix regression in AMD errata checking code
+    - LP: #770050
+  * Linux 2.6.32.39
+    - LP: #770050
+  * fs/partitions/ldm.c: fix oops caused by corrupted partition table,
+    CVE-2011-1017
+    - LP: #771382
+    - CVE-2011-1017
+  * drm/i915: set DIDL using the ACPI video output device _ADR method
+    return.
+    - LP: #775547
+  * drm/radeon/kms: MC vram map needs to be >= pci aperture size
+    - LP: #775547
+  * drm/radeon/kms: make sure blit addr masks are 64 bit
+    - LP: #775547
+  * drm/radeon/kms: fix handling of tex lookup disable in cs checker on
+    r2xx
+    - LP: #775547
+  * drm/i915: Free hardware status page on unload when physically mapped
+    - LP: #775547
+  * drm/i915/overlay: Ensure that the reg_bo is in the GTT prior to
+    writing.
+    - LP: #775547
+  * drm/radeon/kms/atom: set sane defaults in atombios_get_encoder_mode()
+    - LP: #775547
+  * drm/radeon/kms: fix typos in disabled vbios code
+    - LP: #775547
+  * drm/radeon/kms: add workaround for dce3 ddc line vbios bug
+    - LP: #775547
+  * drm/radeon/kms: fix interlaced and doublescan handling
+    - LP: #775547
+  * drm/i915/sdvo: Always add a 30ms delay to make SDVO TV detection
+    reliable
+    - LP: #775547
+  * drm/radeon/kms: don't apply 7xx HDP flush workaround on AGP
+    - LP: #775547
+  * drm/ttm: Fix two race conditions + fix busy codepaths
+    - LP: #775547
+  * drm/i915: overlay on gen2 can't address above 1G
+    - LP: #775547
+  * drm/i915: fix memory corruption with GM965 and >4GB RAM
+    - LP: #775547
+  * drm/radeon: add quirk to make HP nx6125 laptop resume.
+    - LP: #775547
+  * drm/radeon/kms: add quirk to make HP DV5000 laptop resume
+    - LP: #775547
+  * ath: add missing regdomain pair 0x5c mapping
+    - LP: #780588
+  * block, blk-sysfs: Fix an err return path in blk_register_queue()
+    - LP: #780588
+  * p54: Initialize extra_len in p54_tx_80211
+    - LP: #780588
+  * intel-iommu: Unlink domain from iommu
+    - LP: #780588
+  * intel-iommu: Fix get_domain_for_dev() error path
+    - LP: #780588
+  * NFS: nfs_wcc_update_inode() should set nfsi->attr_gencount
+    - LP: #780588
+  * serial/imx: read cts state only after acking cts change irq
+    - LP: #780588
+  * ASoC: Fix output PGA enabling in wm_hubs CODECs
+    - LP: #780588
+  * kconfig: Avoid buffer underrun in choice input
+    - LP: #780588
+  * UBIFS: fix master node recovery
+    - LP: #780588
+  * Remove extra struct page member from the buffer info structure
+    - LP: #780588
+  * dasd: correct device table
+    - LP: #780588
+  * iwlagn: Support new 5000 microcode.
+    - LP: #780588
+  * atl1c: duplicate atl1c_get_tpd
+    - LP: #780588
+  * udp: Fix bogus UFO packet generation
+    - LP: #780588
+  * slub: fix panic with DISCONTIGMEM
+    - LP: #780588
+  * set memory ranges in N_NORMAL_MEMORY when onlined
+    - LP: #780588
+  * FLEXCOP-PCI: fix __xlate_proc_name-warning for flexcop-pci
+    - LP: #780588
+  * m68k/mm: Set all online nodes in N_NORMAL_MEMORY
+    - LP: #780588
+  * nfs: don't lose MS_SYNCHRONOUS on remount of noac mount
+    - LP: #780588
+  * NFSv4.1: Ensure state manager thread dies on last umount
+    - LP: #780588
+  * agp: fix arbitrary kernel memory writes
+    - LP: #780588
+  * agp: fix OOM and buffer overflow
+    - LP: #780588
+  * Input: xen-kbdfront - fix mouse getting stuck after save/restore
+    - LP: #780588
+  * pmcraid: reject negative request size
+    - LP: #780588
+  * mpt2sas: prevent heap overflows and unchecked reads
+    - LP: #780588
+  * put stricter guards on queue dead checks
+    - LP: #780588
+  * mmc: sdhci-pci: Fix error case in sdhci_pci_probe_slot()
+    - LP: #780588
+  * mmc: sdhci: Check mrq->cmd in sdhci_tasklet_finish
+    - LP: #780588
+  * mmc: sdhci: Check mrq != NULL in sdhci_tasklet_finish
+    - LP: #780588
+  * USB: fix regression in usbip by setting has_tt flag
+    - LP: #780588
+  * af_unix: Only allow recv on connected seqpacket sockets.
+    - LP: #780588
+  * ARM: 6891/1: prevent heap corruption in OABI semtimedop
+    - LP: #780588
+  * i8k: Tell gcc that *regs gets clobbered
+    - LP: #780588
+  * Fix gcc 4.5.1 miscompiling drivers/char/i8k.c (again)
+    - LP: #780588
+  * Open with O_CREAT flag set fails to open existing files on non writable
+    directories
+    - LP: #780588
+  * can: Add missing socket check in can/bcm release.
+    - LP: #780588
+  * netxen: module firmware hints
+    - LP: #780588
+  * bnx2x: declare MODULE_FIRMWARE
+    - LP: #780588
+  * cxgb3: declare MODULE_FIRMWARE
+    - LP: #780588
+  * myri10ge: declare MODULE_FIRMWARE
+    - LP: #780588
+  * netx: declare MODULE_FIRMWARE
+    - LP: #780588
+  * pcnet-cs: declare MODULE_FIRMWARE
+    - LP: #780588
+  * spider-net: declare MODULE_FIRMWARE
+    - LP: #780588
+  * tms380tr: declare MODULE_FIRMWARE
+    - LP: #780588
+  * Input: Add support of Synaptics Clickpad device
+    - LP: #780588
+  * Input: elantech - do not advertise relative events
+    - LP: #780588
+  * Input: elantech - fix firmware version check
+    - LP: #780588
+  * Input: elantech - allow forcing Elantech protocol
+    - LP: #780588
+  * Input: elantech - ignore high bits in the position coordinates
+    - LP: #780588
+  * Input: elantech - use all 3 bytes when checking version
+    - LP: #780588
+  * Input: elantech - relax signature checks
+    - LP: #780588
+  * Input: elantech - discard the first 2 positions on some firmwares
+    - LP: #780588
+  * Staging: rtl8192su: check for skb == NULL
+    - LP: #780588
+  * Staging: rtl8192su: Clean up in case of an error in module
+    initialisation
+    - LP: #780588
+  * Staging: rtl8192su: Fix procfs code for interfaces not named wlan0
+    - LP: #780588
+  * Staging: rtl8192su: remove device ids
+    - LP: #780588
+  * Staging: rtl8192su: add device ids
+    - LP: #780588
+  * USB: retain USB device power/wakeup setting across reconfiguration
+    - LP: #780588
+  * USB: don't enable remote wakeup by default
+    - LP: #780588
+  * USB: teach "devices" file about Wireless and SuperSpeed USB
+    - LP: #780588
+  * GFS2: Clean up gfs2_adjust_quota() and do_glock()
+    - LP: #780588
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - LP: #780588
+  * GFS2: BUG in gfs2_adjust_quota
+    - LP: #780588
+  * SUNRPC: fix NFS client over TCP hangs due to packet loss (Bug 16494)
+    - LP: #780588
+  * nfs4: Ensure that ACL pages sent over NFS were not allocated from the
+    slab (v3)
+    - LP: #780588
+  * nfs: fix compilation warning
+    - LP: #780588
+  * Fix corrupted OSF partition table parsing
+    - LP: #780588
+  * Increase OSF partition limit from 8 to 18
+    - LP: #780588
+  * Please add support for Microsoft MN-120 PCMCIA network card
+    - LP: #780588
+  * hwmon: (applesmc) Add iMac9,1 and MacBookPro2,2 support
+    - LP: #780588
+  * hwmon: (applesmc) Add support for MacBook Pro 5,3 and 5,4
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 6
+    - LP: #780588
+  * hwmon: (applesmc) Add generic support for MacBook Pro 7
+    - LP: #780588
+  * hwmon: (applesmc) Add MacBookAir3,1(3,2) support
+    - LP: #780588
+  * ALSA: emux: Add trivial compat ioctl handler
+    - LP: #780588
+  * ALSA: powermac - Reverse HP detection on G4 DA
+    - LP: #780588
+  * ALSA: powermac - Lineout detection on G4 DA
+    - LP: #780588
+  * ALSA: hda - Add support for the new 27 inch IMacs
+    - LP: #780588
+  * ALSA: hda - MacBookPro 5,3 line-in support
+    - LP: #780588
+  * ALSA: hda - Add model=mbp55 entry for MacBookPro 7,1
+    - LP: #780588
+  * ALSA: hda - MacBookAir3,1(3,2) alsa support
+    - LP: #780588
+  * virtio_net: fix oom handling on tx
+    - LP: #780588
+  * mac80211: Add define for TX headroom reserved by mac80211 itself.
+    - LP: #780588
+  * rt2x00: Centralize setting of extra TX headroom requested by rt2x00.
+    - LP: #780588
+  * rt2x00: Properly request tx headroom for alignment operations.
+    - LP: #780588
+  * rt2x00: use correct headroom for transmission
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 6,2
+    - LP: #780588
+  * Bluetooth: Add support Bluetooth controller of MacbookPro 7,1
+    - LP: #780588
+  * Bluetooth: Add MacBookAir3,1(2) support
+    - LP: #780588
+  * perf tools: Display better error messages on missing packages
+    - LP: #780588
+  * perf tools: Add 'make DEBUG=1' to remove the -O6 cflag
+    - LP: #780588
+  * perf tools: Test -fstack-protector-all compiler option for inclusion in
+    CFLAGS
+    - LP: #780588
+  * perf tools: Support static build
+    - LP: #780588
+  * perf tools: Add V=2 option to help debug config issues
+    - LP: #780588
+  * perf tools: Suggest static libraries as well
+    - LP: #780588
+  * perf: Use default compiler mode by default
+    - LP: #780588
+  * perf tools: Move QUIET_STDERR def to before first use
+    - LP: #780588
+  * perf tools: Check if /dev/null can be used as the -o gcc argument
+    - LP: #780588
+  * perf symbols: allow forcing use of cplus_demangle
+    - LP: #780588
+  * V4L/DVB: Add Elgato EyeTV Diversity to dibcom driver
+    - LP: #780588
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #780588
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #780588
+  * b43: Fix warning at drivers/mmc/core/core.c:237 in mmc_wait_for_cmd
+    - LP: #780588
+  * econet: Fix redeclaration of symbol len
+    - LP: #780588
+  * econet: fix CVE-2010-3848
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop to the DMI whitelist
+    - LP: #780588
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #780588
+  * scsi_dh_emc: fix mode select request setup
+    - LP: #780588
+  * scsi_dh_emc: request flag cleanup
+    - LP: #780588
+  * cifs: fix another memleak, in cifs_root_iget
+    - LP: #780588
+  * e1000e: Reset 82577/82578 PHY before first PHY register read
+    - LP: #780588
+  * e1000: fix Tx hangs by disabling 64-bit DMA
+    - LP: #780588
+  * btrfs: Require CAP_SYS_ADMIN for filesystem rebalance
+    - LP: #780588
+  * af_unix: limit recursion level
+    - LP: #780588
+  * init, sched: Fix race between init and kthreadd
+    - LP: #780588
+  * backlight: MacBookAir3,1(3,2) mbp-nvidia-bl support
+    - LP: #780588
+  * bonding: Ensure that we unshare skbs prior to calling pskb_may_pull
+    - LP: #780588
+  * HID: add MacBookAir 3,1 and 3,2 support
+    - LP: #780588
+  * intel-iommu: Force-disable IOMMU for iGFX on broken Cantiga revisions.
+    - LP: #780588
+  * ipg: Remove device claimed by dl2k from pci id table
+    - LP: #780588
+  * ipv6: Silence privacy extensions initialization
+    - LP: #780588
+  * l2tp: Fix UDP socket reference count bugs in the pppol2tp driver
+    - LP: #780588
+  * MIPS: DMA: Fix computation of DMA flags from device's
+    coherent_dma_mask.
+    - LP: #780588
+  * mpt2sas: fix the incorrect scsi_dma_map error checking
+    - LP: #780588
+  * Phonet: device notifier only runs on initial namespace
+    - LP: #780588
+  * powerpc/boot/dts: Install dts from the right directory
+    - LP: #780588
+  * rt2500usb: fallback to SW encryption for TKIP+AES
+    - LP: #780588
+  * sata_via: Delay on vt6420 when starting ATAPI DMA write
+    - LP: #780588
+  * tehuti: Firmware filename is tehuti/bdx.bin
+    - LP: #780588
+  * wireless: b43: fix error path in SDIO
+    - LP: #780588
+  * libata: set queue DMA alignment to sector size for ATAPI too
+    - LP: #780588
+  * usb: musb: core: set has_tt flag
+    - LP: #780588
+  * iwlwifi: fix skb usage after free
+    - LP: #780588
+  * can: add missing socket check in can/raw release
+    - LP: #780588
+  * fix oops in scsi_run_queue()
+    - LP: #780588
+  * Linux 2.6.32.40
+    - LP: #780588
+  * PCI: allow matching of prefetchable resources to non-prefetchable
+    windows
+    - LP: #424142
+  * cifs: check for bytes_remaining going to zero in CIFS_SessSetup
+    - LP: #788602
+  * Validate size of EFI GUID partition entries.
+    - LP: #788602
+  * dccp: handle invalid feature options length
+    - LP: #788602
+  * CIFS: Fix memory over bound bug in cifs_parse_mount_options
+    - LP: #788602
+  * Fix time() inconsistencies caused by intermediate xtime_cache values
+    being read
+    - LP: #788602
+  * ehea: fix wrongly reported speed and port
+    - LP: #788602
+  * NET: slip, fix ldisc->open retval
+    - LP: #788602
+  * ne-h8300: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * hydra: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * libertas: fix cmdpendingq locking
+    - LP: #788602
+  * zorro8390: Fix regression caused during net_device_ops conversion
+    - LP: #788602
+  * cifs: add fallback in is_path_accessible for old servers
+    - LP: #788602
+  * x86, AMD: Fix ARAT feature setting again
+    - LP: #788602
+  * clocksource: Install completely before selecting
+    - LP: #788602
+  * tick: Clear broadcast active bit when switching to oneshot
+    - LP: #788602
+  * x86, apic: Fix spurious error interrupts triggering on all non-boot APs
+    - LP: #788602
+  * x86, mce, AMD: Fix leaving freed data in a list
+    - LP: #788602
+  * megaraid_sas: Sanity check user supplied length before passing it to
+    dma_alloc_coherent()
+    - LP: #788602
+  * vmxnet3: Fix inconsistent LRO state after initialization
+    - LP: #788602
+  * netxen: Remove references to unified firmware file
+    - LP: #788602
+  * Linux 2.6.32.41
+    - LP: #788602
+  * drm/radeon/kms: fix bad shift in atom iio table parser
+    - LP: #788602
+  * Linux 2.6.32.41+drm33.18
+    - LP: #788602
+
+ -- Steve Conklin <sconklin@canonical.com>  Tue, 31 May 2011 13:22:59 -0500
+
+linux (2.6.32-32.62) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #767370
+
+  [ Stefan Bader ]
+
+  * (config) Disable CONFIG_NET_NS
+    - LP: #720095
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "drm/radeon/kms: Fix retrying ttm_bo_init() after it failed
+    once."
+    - LP: #736234
+  * Revert "drm/radeon: fall back to GTT if bo creation/validation in VRAM
+    fails."
+    - LP: #736234
+  * x86: pvclock: Move scale_delta into common header
+  * KVM: x86: Fix a possible backwards warp of kvmclock
+  * KVM: x86: Fix kvmclock bug
+  * cpuset: add a missing unlock in cpuset_write_resmask()
+    - LP: #736234
+  * keyboard: integer underflow bug
+    - LP: #736234
+  * RxRPC: Fix v1 keys
+    - LP: #736234
+  * ixgbe: fix for 82599 erratum on Header Splitting
+    - LP: #736234
+  * mm: fix possible cause of a page_mapped BUG
+    - LP: #736234
+  * powerpc/kdump: CPUs assume the context of the oopsing CPU
+    - LP: #736234
+  * powerpc/kdump: Use chip->shutdown to disable IRQs
+    - LP: #736234
+  * powerpc: Use more accurate limit for first segment memory allocations
+    - LP: #736234
+  * powerpc/pseries: Add hcall to read 4 ptes at a time in real mode
+    - LP: #736234
+  * powerpc/kexec: Speedup kexec hash PTE tear down
+    - LP: #736234
+  * powerpc/crashdump: Do not fail on NULL pointer dereferencing
+    - LP: #736234
+  * powerpc/kexec: Fix orphaned offline CPUs across kexec
+    - LP: #736234
+  * netfilter: nf_log: avoid oops in (un)bind with invalid nfproto values
+    - LP: #736234
+  * nfsd: wrong index used in inner loop
+    - LP: #736234
+  * r8169: use RxFIFO overflow workaround for 8168c chipset.
+    - LP: #736234
+  * Staging: comedi: jr3_pci: Don't ioremap too much space. Check result.
+    - LP: #736234
+  * net: don't allow CAP_NET_ADMIN to load non-netdev kernel modules,
+    CVE-2011-1019
+    - LP: #736234
+    - CVE-2011-1019
+  * ip6ip6: autoload ip6 tunnel
+    - LP: #736234
+  * Linux 2.6.32.33
+    - LP: #736234
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934, #736234
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934, #736234
+  * drm: fix unsigned vs signed comparison issue in modeset ctl ioctl,
+    CVE-2011-1013
+    - LP: #736234
+    - CVE-2011-1013
+  * Linux 2.6.32.33+drm33.15
+    - LP: #736234
+  * econet: Fix crash in aun_incoming(). CVE-2010-4342
+    - LP: #736394
+    - CVE-2010-4342
+  * igb: only use vlan_gro_receive if vlans are registered, CVE-2010-4263
+    - LP: #737024
+    - CVE-2010-4263
+  * irda: prevent integer underflow in IRLMP_ENUMDEVICES, CVE-2010-4529
+    - LP: #737823
+    - CVE-2010-4529
+  * hwmon/f71882fg: Set platform drvdata to NULL later
+    - LP: #742056
+  * mtd: add "platform:" prefix for platform modalias
+    - LP: #742056
+  * libata: no special completion processing for EH commands
+    - LP: #742056
+  * MIPS: MTX-1: Make au1000_eth probe all PHY addresses
+    - LP: #742056
+  * x86/mm: Handle mm_fault_error() in kernel space
+    - LP: #742056
+  * ftrace: Fix memory leak with function graph and cpu hotplug
+    - LP: #742056
+  * x86: Fix panic when handling "mem={invalid}" param
+    - LP: #553464, #742056
+  * x86: Emit "mem=nopentium ignored" warning when not supported
+    - LP: #553464, #742056
+  * ahci: AHCI and RAID mode SATA patch for Intel Patsburg DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel DH89xxCC DeviceIDs
+    - LP: #742056
+  * ahci: AHCI mode SATA patch for Intel Patsburg SATA RAID controller
+    - LP: #742056
+  * RDMA/cma: Fix crash in request handlers
+    - LP: #742056
+  * IB/cm: Bump reference count on cm_id before invoking callback
+    - LP: #742056
+  * ath9k_hw: Fix incorrect macversion and macrev checks
+    - LP: #742056
+  * USB: serial/kobil_sct, fix potential tty NULL dereference
+    - LP: #742056
+  * USB: serial: ch341: add new id
+    - LP: #742056
+  * xhci: Fix cycle bit calculation during stall handling.
+    - LP: #742056
+  * ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
+    - LP: #742056
+  * PCI: remove quirk for pre-production systems
+    - LP: #742056
+  * PCI: add more checking to ICH region quirks
+    - LP: #742056
+  * PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH
+    - LP: #742056
+  * PCI: sysfs: Fix failure path for addition of "vpd" attribute
+    - LP: #742056
+  * ALSA: ctxfi - Fix incorrect SPDIF status bit mask
+    - LP: #742056
+  * ALSA: ctxfi - Fix SPDIF status retrieval
+    - LP: #742056
+  * ALSA: ctxfi - Clear input settings before initialization
+    - LP: #742056
+  * SUNRPC: Ensure we always run the tk_callback before tk_action
+    - LP: #742056
+  * perf, powerpc: Handle events that raise an exception without
+    overflowing
+    - LP: #742056
+  * ext3: Always set dx_node's fake_dirent explicitly.
+    - LP: #742056
+  * call_function_many: fix list delete vs add race
+    - LP: #742056
+  * call_function_many: add missing ordering
+    - LP: #742056
+  * x86: Flush TLB if PGD entry is changed in i386 PAE mode
+    - LP: #742056
+  * isdn: avoid calling tty_ldisc_flush() in atomic context
+    - LP: #742056
+  * smp_call_function_many: handle concurrent clearing of mask
+    - LP: #742056
+  * fix per-cpu flag problem in the cpu affinity checkers
+    - LP: #742056
+  * i2c: Fix typo in instantiating-devices document
+    - LP: #742056
+  * mmc: sdio: remember new card RCA when redetecting card
+    - LP: #742056
+  * powerpc/kexec: Fix race in kexec shutdown
+    - LP: #742056
+  * powerpc/kdump: Fix race in kdump shutdown
+    - LP: #742056
+  * powerpc: rtas_flash needs to use rtas_data_buf
+    - LP: #742056
+  * x86, binutils, xen: Fix another wrong size directive
+    - LP: #742056
+  * hwmon: (sht15) Fix integer overflow in humidity calculation
+    - LP: #742056
+  * Linux 2.6.32.34
+    - LP: #742056
+  * Linux 2.6.32.35
+    - LP: #742056
+  * aio: wake all waiters when destroying ctx
+    - LP: #744921
+  * shmem: let shared anonymous be nonlinear again
+    - LP: #744921
+  * PCI hotplug: acpiphp: set current_state to D0 in register_slot
+    - LP: #744921
+  * xen: set max_pfn_mapped to the last pfn mapped
+    - LP: #744921
+  * PCI: return correct value when writing to the "reset" attribute
+    - LP: #744921
+  * Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal
+    code
+    - LP: #744921
+  * ext3: skip orphan cleanup on rocompat fs
+    - LP: #744921
+  * procfs: fix /proc/<pid>/maps heap check
+    - LP: #744921
+  * proc: protect mm start_code/end_code in /proc/pid/stat, CVE-2011-0726
+    - LP: #744921
+    - CVE-2011-0726
+  * fbcon: Bugfix soft cursor detection in Tile Blitting
+    - LP: #744921
+  * nfsd41: modify the members value of nfsd4_op_flags
+    - LP: #744921
+  * nfsd: wrong index used in inner loop
+    - LP: #744921
+  * uvcvideo: Fix uvc_fixup_video_ctrl() format search
+    - LP: #744921
+  * ehci-hcd: Bug fix: don't set a QH's Halt bit
+    - LP: #744921
+  * USB: uss720 fixup refcount position
+    - LP: #744921
+  * USB: cdc-acm: fix memory corruption / panic
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference
+    - LP: #744921
+  * USB: cdc-acm: fix potential null-pointer dereference on disconnect
+    - LP: #744921
+  * Input: xen-kbdfront - advertise either absolute or relative coordinates
+    - LP: #744921
+  * SUNRPC: Never reuse the socket port after an xs_close()
+    - LP: #744921
+  * fs: call security_d_instantiate in d_obtain_alias V2
+    - LP: #744921
+  * dcdbas: force SMI to happen when expected
+    - LP: #744921
+  * Linux 2.6.32.36
+    - LP: #744921
+  * drm/radeon/kms: check AA resolve registers on r300, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * drm/radeon: fix regression with AA resolve checking, CVE-2011-1016
+    - LP: #745686
+    - CVE-2011-1016
+  * xen: events: do not unmask event channels on resume
+    - LP: #681083
+  * drm/radeon/kms: check AA resolve registers on r300
+    - LP: #754584
+  * drm/radeon: fix regression with AA resolve checking
+    - LP: #754584
+  * Linux 2.6.32.36+drm33.16
+    - LP: #754584
+  * ALSA: hda - Fix SPDIF out regression on ALC889
+    - LP: #764685
+  * ALSA: Fix yet another race in disconnection
+    - LP: #764685
+  * perf: Better fit max unprivileged mlock pages for tools needs
+    - LP: #764685
+  * myri10ge: fix rmmod crash
+    - LP: #764685
+  * cciss: fix lost command issue
+    - LP: #764685
+  * sound/oss/opl3: validate voice and channel indexes
+    - LP: #764685
+  * mac80211: initialize sta->last_rx in sta_info_alloc
+    - LP: #764685
+  * ses: show devices for enclosures with no page 7
+    - LP: #764685
+  * ses: Avoid kernel panic when lun 0 is not mapped
+    - LP: #764685
+  * eCryptfs: Unlock page in write_begin error path
+    - LP: #764685
+  * eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix
+    - LP: #764685
+  * staging: usbip: bugfixes related to kthread conversion
+    - LP: #764685
+  * staging: usbip: bugfix add number of packets for isochronous frames
+    - LP: #764685
+  * staging: usbip: bugfix for isochronous packets and optimization
+    - LP: #764685
+  * staging: hv: Fix GARP not sent after Quick Migration
+    - LP: #764685
+  * staging: hv: use sync_bitops when interacting with the hypervisor
+    - LP: #764685
+  * Relax si_code check in rt_sigqueueinfo and rt_tgsigqueueinfo
+    - LP: #764685
+  * xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1
+    - LP: #764685
+  * irda: validate peer name and attribute lengths
+    - LP: #764685
+  * irda: prevent heap corruption on invalid nickname
+    - LP: #764685
+  * nilfs2: fix data loss in mmap page write for hole blocks
+    - LP: #764685
+  * ASoC: Explicitly say registerless widgets have no register
+    - LP: #764685
+  * ALSA: ens1371: fix Creative Ectiva support
+    - LP: #764685
+  * ROSE: prevent heap corruption with bad facilities
+    - LP: #764685
+  * Btrfs: Fix uninitialized root flags for subvolumes
+    - LP: #764685
+  * x86, mtrr, pat: Fix one cpu getting out of sync during resume
+    - LP: #764685
+  * ath9k: fix a chip wakeup related crash in ath9k_start
+    - LP: #764685
+  * UBIFS: do not read flash unnecessarily
+    - LP: #764685
+  * UBIFS: fix oops on error path in read_pnode
+    - LP: #764685
+  * UBIFS: fix debugging failure in dbg_check_space_info
+    - LP: #764685
+  * quota: Don't write quota info in dquot_commit()
+    - LP: #764685
+  * mm: avoid wrapping vm_pgoff in mremap()
+    - LP: #764685
+  * p54usb: IDs for two new devices
+    - LP: #764685
+  * b43: allocate receive buffers big enough for max frame len + offset
+    - LP: #764685
+  * Bluetooth: sco: fix information leak to userspace
+    - LP: #764685
+  * bridge: netfilter: fix information leak
+    - LP: #764685
+  * Bluetooth: bnep: fix buffer overflow
+    - LP: #764685
+  * Bluetooth: add support for Apple MacBook Pro 8,2
+    - LP: #764685
+  * Treat writes as new when holes span across page boundaries
+    - LP: #764685
+  * char/tpm: Fix unitialized usage of data buffer
+    - LP: #764685
+  * netfilter: ip_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: arp_tables: fix infoleak to userspace
+    - LP: #764685
+  * netfilter: ipt_CLUSTERIP: fix buffer overflow
+    - LP: #764685
+  * ipv6: netfilter: ip6_tables: fix infoleak to userspace
+    - LP: #764685
+  * mfd: ab3100: world-writable debugfs *_priv files
+    - LP: #764685
+  * drivers/rtc/rtc-ds1511.c: world-writable sysfs nvram file
+    - LP: #764685
+  * drivers/misc/ep93xx_pwm.c: world-writable sysfs files
+    - LP: #764685
+  * econet: 4 byte infoleak to the network
+    - LP: #764685
+  * sound/oss: remove offset from load_patch callbacks
+    - LP: #764685
+  * sound: oss: midi_synth: check get_user() return value
+    - LP: #764685
+  * repair gdbstub to match the gdbserial protocol specification
+    - LP: #764685
+  * gro: Reset dev pointer on reuse
+    - LP: #764685
+  * gro: reset skb_iif on reuse
+    - LP: #764685
+  * x86, amd-ucode: Remove needless log messages
+    - LP: #764685
+  * x86, microcode, AMD: Extend ucode size verification
+    - LP: #764685
+  * powerpc/kexec: Add ifdef CONFIG_PPC_STD_MMU_64 to PPC64 code
+    - LP: #764685
+  * powerpc: Fix default_machine_crash_shutdown #ifdef botch
+    - LP: #764685
+  * Squashfs: handle corruption of directory structure
+    - LP: #764685
+  * sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
+    - LP: #764685
+  * atm/solos-pci: Don't include frame pseudo-header on transmit hex-dump
+    - LP: #764685
+  * ext4: fix credits computing for indirect mapped files
+    - LP: #764685
+  * nfsd: fix auth_domain reference leak on nlm operations
+    - LP: #764685
+  * CAN: Use inode instead of kernel address for /proc file
+    - LP: #764685
+  * exec: make argv/envp memory visible to oom-killer
+    - LP: #764685
+  * exec: copy-and-paste the fixes into compat_do_execve() paths
+    - LP: #764685
+  * xfs: zero proper structure size for geometry calls
+    - LP: #764685
+  * Linux 2.6.32.37
+    - LP: #764685
+  * Linux 2.6.32.38
+    - LP: #764685
+
+ -- Brad Figg <brad.figg@canonical.com>  Wed, 20 Apr 2011 08:28:25 -0700
+
+linux (2.6.32-31.61) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #754842
+
+  [ Upstream Kernel Changes ]
+
+  * x86, quirk: Fix SB600 revision check
+    - LP: #742056
+
+ -- Brad Figg <brad.figg@canonical.com>  Fri, 08 Apr 2011 10:08:30 -0700
+
+linux (2.6.32-31.60) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #734950
+
+  [ Paolo Pisati ]
+
+  * SAUCE: Clear new_profile in error path
+    - LP: #732700
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_BOOT_PRINTK_DELAY=y
+    - LP: #733191
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "drm/radeon/bo: add some fallback placements for VRAM only
+    objects."
+    - LP: #652934
+  * drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
+    - LP: #652934
+  * drm/radeon/kms: Fix retrying ttm_bo_init() after it failed once.
+    - LP: #652934
+  * xfs: always use iget in bulkstat
+    - LP: #692848
+  * drm/radeon/kms: make the mac rv630 quirk generic
+    - LP: #728687
+  * drm/radeon/kms: add pll debugging output
+    - LP: #728687
+  * drm/radeon: remove 0x4243 pci id
+    - LP: #728687
+  * drm/radeon/kms: fix s/r issues with bios scratch regs
+    - LP: #728687
+  * drm/i915/lvds: Add AOpen i915GMm-HFS to the list of false-positive LVDS
+    - LP: #728687
+  * drm/i915: Add dependency on CONFIG_TMPFS
+    - LP: #728687
+  * Linux 2.6.32.29+drm33.14
+    - LP: #728687
+  * NFSD: memory corruption due to writing beyond the stat array
+    - LP: #728687
+  * mptfusion: mptctl_release is required in mptctl.c
+    - LP: #728687
+  * mptfusion: Fix Incorrect return value in mptscsih_dev_reset
+    - LP: #728687
+  * ocfs2_connection_find() returns pointer to bad structure
+    - LP: #728687
+  * x25: decrement netdev reference counts on unload
+    - LP: #728687
+  * x86, hpet: Disable per-cpu hpet timer if ARAT is supported
+    - LP: #728687
+  * OHCI: work around for nVidia shutdown problem
+    - LP: #728687
+  * x86/pvclock: Zero last_value on resume
+    - LP: #728687
+  * av7110: check for negative array offset
+    - LP: #728687
+  * CRED: Fix get_task_cred() and task_state() to not resurrect dead
+    credentials
+    - LP: #728687
+  * bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion
+    - LP: #728687
+  * CRED: Fix kernel panic upon security_file_alloc() failure.
+    - LP: #728687
+  * CRED: Fix BUG() upon security_cred_alloc_blank() failure
+    - LP: #728687
+  * CRED: Fix memory and refcount leaks upon security_prepare_creds()
+    failure
+    - LP: #728687
+  * sendfile(): check f_op.splice_write() rather than f_op.sendpage()
+    - LP: #728687
+  * isdn: hisax: Replace the bogus access to irq stats
+    - LP: #728687
+  * ixgbe: add support for 82599 based Express Module X520-P2
+    - LP: #728687
+  * ixgbe: prevent speculative processing of descriptors before ready
+    - LP: #728687
+  * scsi_dh_alua: add netapp to dev list
+    - LP: #728687
+  * scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list
+    - LP: #728687
+  * dm raid1: fail writes if errors are not handled and log fails
+    - LP: #728687
+  * GFS2: Fix bmap allocation corner-case bug
+    - LP: #728687
+  * dm raid1: fix null pointer dereference in suspend
+    - LP: #728687
+  * sunrpc/cache: fix module refcnt leak in a failure path
+    - LP: #728687
+  * be2net: Maintain tx and rx counters in driver
+    - LP: #728687
+  * tcp: Make TCP_MAXSEG minimum more correct.
+    - LP: #728687
+  * nfsd: correctly handle return value from nfsd_map_name_to_*
+    - LP: #728687
+  * s390: remove task_show_regs
+    - LP: #728687
+  * PM / Hibernate: Return error code when alloc_image_page() fails
+    - LP: #728687
+  * fs/partitions: Validate map_count in Mac partition tables
+    - LP: #728687
+  * ALSA: HDA: Add position_fix quirk for an Asus device
+    - LP: #718402, #728687
+  * ALSA: caiaq - Fix possible string-buffer overflow
+    - LP: #728687
+  * radio-aimslab.c needs #include <linux/delay.h>
+    - LP: #728687
+  * ARM: Ensure predictable endian state on signal handler entry
+    - LP: #728687
+  * acer-wmi: Fix capitalisation of GUID
+    - LP: #728687
+  * eCryptfs: Copy up lower inode attrs in getattr
+    - LP: #728687
+  * platform: x86: acer-wmi: world-writable sysfs threeg file
+    - LP: #728687
+  * platform: x86: asus_acpi: world-writable procfs files
+    - LP: #728687
+  * platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial
+    files
+    - LP: #728687
+  * genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now
+    - LP: #728687
+  * usb: musb: omap2430: fix kernel panic on reboot
+    - LP: #728687
+  * USB: add quirks entry for Keytouch QWERTY Panel
+    - LP: #728687
+  * USB: Add Samsung SGH-I500/Android modem ID switch to visor driver
+    - LP: #728687
+  * USB: Add quirk for Samsung Android phone modem
+    - LP: #728687
+  * p54pci: update receive dma buffers before and after processing
+    - LP: #728687
+  * sierra: add new ID for Airprime/Sierra USB IP modem
+    - LP: #728687
+  * staging: usbip: vhci: update reference count for usb_device
+    - LP: #728687
+  * staging: usbip: vhci: give back URBs from in-flight unlink requests
+    - LP: #728687
+  * staging: usbip: vhci: refuse to enqueue for dead connections
+    - LP: #728687
+  * staging: usbip: vhci: use urb->dev->portnum to find port
+    - LP: #728687
+  * epoll: prevent creating circular epoll structures
+    - LP: #728687
+  * ldm: corrupted partition table can cause kernel oops
+    - LP: #728687
+  * md: correctly handle probe of an 'mdp' device.
+    - LP: #728687
+  * x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems
+    - LP: #728687
+  * xhci: Avoid BUG() in interrupt context
+    - LP: #728687
+  * xhci: Clarify some expressions in the TRB math
+    - LP: #728687
+  * xhci: Fix errors in the running total calculations in the TRB math
+    - LP: #728687
+  * xhci: Fix an error in count_sg_trbs_needed()
+    - LP: #728687
+  * x25: Do not reference freed memory.
+    - LP: #728687
+  * Linux 2.6.32.30
+    - LP: #728687
+  * Linux 2.6.32.31
+    - LP: #728687
+  * Ocfs2/refcounttree: Fix a bug for refcounttree to writeback clusters in
+    a right number.
+    - LP: #731226
+  * mfd: Fix NULL pointer due to non-initialized ucb1x00-ts absinfo
+    - LP: #731226
+  * x86: Use u32 instead of long to set reset vector back to 0
+    - LP: #731226
+  * fuse: fix hang of single threaded fuseblk filesystem
+    - LP: #731226
+  * clockevents: Prevent oneshot mode when broadcast device is periodic
+    - LP: #731226
+  * ext2: Fix link count corruption under heavy link+rename load
+    - LP: #731226
+  * sctp: Fix oops when sending queued ASCONF chunks
+    - LP: #731226
+  * virtio: set pci bus master enable bit
+    - LP: #731226
+  * netxen: fix set mac addr
+    - LP: #731226
+  * HID: add support for Acan FG-8100 barcode reader
+    - LP: #731226
+  * p54usb: add Senao NUB-350 usbid
+    - LP: #731226
+  * dccp: fix oops on Reset after close
+    - LP: #731226
+  * e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup
+    instead
+    - LP: #731226
+  * r8169: disable ASPM
+    - LP: #731226
+  * usb: iowarrior: don't trust report_size for buffer size
+    - LP: #731226
+  * arp_notify: unconditionally send gratuitous ARP for
+    NETDEV_NOTIFY_PEERS.
+    - LP: #731226
+  * CIFS: Fix oplock break handling (try #2)
+    - LP: #731226
+  * Linux 2.6.32.32
+    - LP: #731226
+
+ -- Brad Figg <brad.figg@canonical.com>  Mon, 14 Mar 2011 07:24:45 -0700
+
+linux (2.6.32-30.59) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Release Tracking Bug
+    - LP: #727336
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_IRQ_TIME_ACCOUNTING=n
+    - LP: #723819
+
+  [ Upstream Kernel Changes ]
+
+  * virtio_net: Add schedule check to napi_enable call
+    - LP: #579276
+  * NFS: fix the return value of nfs_file_fsync()
+    - LP: #585657
+  * block: check for proper length of iov entries earlier in
+    blk_rq_map_user_iov(), CVE-2010-4163
+    - LP: #721504
+    - CVE-2010-4163
+  * filter: make sure filters dont read uninitialized memory
+    - LP: #721282
+    - CVE-2010-4158
+  * tty: Make tiocgicount a handler, CVE-2010-4076, CVE-2010-4077
+    - LP: #720189
+    - CVE-2010-4077
+  * staging: usbip: remove double giveback of URB
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD SB800
+    - LP: #723819
+  * rt2x00: add device id for windy31 usb device
+    - LP: #723819
+  * ALSA: snd-usb-us122l: Fix missing NULL checks
+    - LP: #723819
+  * hwmon: (via686a) Initialize fan_div values
+    - LP: #723819
+  * USB: serial: handle Data Carrier Detect changes
+    - LP: #723819
+  * USB: CP210x Add two device IDs
+    - LP: #723819
+  * USB: CP210x Removed incorrect device ID
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for Cypress ATACB
+    - LP: #723819
+  * USB: usb-storage: unusual_devs update for TrekStor DataStation maxi g.u
+    external hard drive enclosure
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for CamSport Evo
+    - LP: #723819
+  * USB: usb-storage: unusual_devs entry for Coby MP3 player
+    - LP: #723819
+  * USB: serial: Updated support for ICOM devices
+    - LP: #723819
+  * USB: adding USB support for Cinterion's HC2x, EU3 and PH8 products
+    - LP: #723819
+  * USB: EHCI: ASPM quirk of ISOC on AMD Hudson
+    - LP: #723819
+  * USB: EHCI: fix DMA deallocation bug
+    - LP: #723819
+  * USB: g_printer: fix bug in module parameter definitions
+    - LP: #723819
+  * USB: io_edgeport: fix the reported firmware major and minor
+    - LP: #723819
+  * USB: ti_usb: fix module removal
+    - LP: #723819
+  * USB: Storage: Add unusual_devs entry for VTech Kidizoom
+    - LP: #723819
+  * USB: ftdi_sio: add ST Micro Connect Lite uart support
+    - LP: #723819
+  * USB: cdc-acm: Adding second ACM channel support for Nokia N8
+    - LP: #723819
+  * USB: ftdi_sio: Add VID=0x0647, PID=0x0100 for Acton Research
+    spectrograph
+    - LP: #723819
+  * USB: prevent buggy hubs from crashing the USB stack
+    - LP: #723819
+  * staging: comedi: add support for newer jr3 1-channel pci board
+    - LP: #723819
+  * staging: comedi: ni_labpc: Use shared IRQ for PCMCIA card
+    - LP: #723819
+  * Staging: hv: fix sysfs symlink on hv block device
+    - LP: #723819
+  * staging: hv: Enable sending GARP packet after live migration
+    - LP: #723819
+  * hvc_iucv: allocate memory buffers for IUCV in zone DMA
+    - LP: #723819
+  * iwlagn: enable only rfkill interrupt when device is down
+    - LP: #723819
+  * ath9k: Fix bug in delimiter padding computation
+    - LP: #723819
+  * correct vdso version string
+    - LP: #723819
+  * fix medium error problems with some arrays which can cause data
+    corruption
+    - LP: #723819
+  * libsas: fix runaway error handler problem
+    - LP: #723819
+  * mpt2sas: Fix device removal handshake for zoned devices
+    - LP: #723819
+  * mpt2sas: Correct resizing calculation for max_queue_depth
+    - LP: #723819
+  * mpt2sas: Kernel Panic during Large Topology discovery
+    - LP: #723819
+  * radio-aimslab.c: Fix gcc 4.5+ bug
+    - LP: #723819
+  * em28xx: Fix audio input for Terratec Grabby
+    - LP: #723819
+  * ALSA : au88x0 - Limit number of channels to fix Oops via OSS emu
+    - LP: #723819
+  * ALSA: HDA: Fix dmesg output of HDMI supported bits
+    - LP: #723819
+  * ALSA: hda - Fix memory leaks in conexant jack arrays
+    - LP: #723819
+  * input: bcm5974: Add support for MacBookAir3
+    - LP: #723819
+  * ALSA: hrtimer: handle delayed timer interrupts
+    - LP: #723819
+  * ASoC: WM8990: msleep() takes milliseconds not jiffies
+    - LP: #723819
+  * ASoC: Blackfin AC97: fix build error after multi-component update
+    - LP: #723819
+  * NFS: Fix "kernel BUG at fs/aio.c:554!"
+    - LP: #723819
+  * rtc-cmos: fix suspend/resume
+    - LP: #723819
+  * iwlagn: Re-enable RF_KILL interrupt when down
+    - LP: #723819
+  * rapidio: fix hang on RapidIO doorbell queue full condition
+    - LP: #723819
+  * PCI: pci-stub: ignore zero-length id parameters
+    - LP: #723819
+  * virtio: remove virtio-pci root device
+    - LP: #723819
+  * ds2760_battery: Fix calculation of time_to_empty_now
+    - LP: #723819
+  * p54: fix sequence no. accounting off-by-one error
+    - LP: #723819
+  * i2c: Unregister dummy devices last on adapter removal
+    - LP: #723819
+  * serial: unbreak billionton CF card
+    - LP: #723819
+  * ptrace: use safer wake up on ptrace_detach()
+    - LP: #723819
+  * x86, mtrr: Avoid MTRR reprogramming on BP during boot on UP platforms
+    - LP: #723819
+  * fix jiffy calculations in calibrate_delay_direct to handle overflow
+    - LP: #723819
+  * USB: serial: pl2303: Hybrid reader Uniform HCR331
+    - LP: #723819
+  * drivers: update to pl2303 usb-serial to support Motorola cables
+    - LP: #723819
+  * klist: Fix object alignment on 64-bit.
+    - LP: #723819
+  * powerpc: Fix some 6xx/7xxx CPU setup functions
+    - LP: #723819
+  * parisc : Remove broken line wrapping handling pdc_iodc_print()
+    - LP: #723819
+  * kernel/smp.c: fix smp_call_function_many() SMP race
+    - LP: #723819
+  * hostap_cs: fix sleeping function called from invalid context
+    - LP: #723819
+  * md: fix regression with re-adding devices to arrays with no metadata
+    - LP: #723819
+  * pata_mpc52xx: inherit from ata_bmdma_port_ops
+    - LP: #723819
+  * TPM: Long default timeout fix
+    - LP: #723819
+  * tpm_tis: Use timeouts returned from TPM
+    - LP: #723819
+  * SELinux: define permissions for DCB netlink messages
+    - LP: #723819
+  * SELinux: do not compute transition labels on mountpoint labeled
+    filesystems
+    - LP: #723819
+  * ieee80211: correct IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK macro
+    - LP: #723819
+  * dm: dont take i_mutex to change device size
+    - LP: #723819
+  * dm mpath: disable blk_abort_queue
+    - LP: #723819
+  * x86, mm: avoid possible bogus tlb entries by clearing prev mm_cpumask
+    after switching mm
+    - LP: #723819
+  * usb: Realloc xHCI structures after a hub is verified.
+    - LP: #723819
+  * sched: Remove USER_SCHED
+    - LP: #723819
+  * sched: Remove remaining USER_SCHED code
+    - LP: #723819
+  * sched: Move sched_avg_update() to update_cpu_load()
+    - LP: #723819
+  * sched: Increment cache_nice_tries only on periodic lb
+    - LP: #723819
+  * sched: Try not to migrate higher priority RT tasks
+    - LP: #723819
+  * sched: Give CPU bound RT tasks preference
+    - LP: #723819
+  * sched: suppress RCU lockdep splat in task_fork_fair
+    - LP: #723819
+  * sched: fix RCU lockdep splat from task_group()
+    - LP: #723819
+  * sched: Do not consider SCHED_IDLE tasks to be cache hot
+    - LP: #723819
+  * sched: Set group_imb only a task can be pulled from the busiest cpu
+    - LP: #723819
+  * sched: Force balancing on newidle balance if local group has capacity
+    - LP: #723819
+  * sched: Drop group_capacity to 1 only if local group has extra capacity
+    - LP: #723819
+  * sched: Fix softirq time accounting
+    - LP: #723819
+  * sched: Consolidate account_system_vtime extern declaration
+    - LP: #723819
+  * sched: Remove unused PF_ALIGNWARN flag
+    - LP: #723819
+  * sched: Add a PF flag for ksoftirqd identification
+    - LP: #723819
+  * sched: Add IRQ_TIME_ACCOUNTING, finer accounting of irq time
+    - LP: #723819
+  * x86: Add IRQ_TIME_ACCOUNTING
+    - LP: #723819
+  * sched: Do not account irq time to current task
+    - LP: #723819
+  * sched: Remove irq time from available CPU power
+    - LP: #723819
+  * sched: Call tick_check_idle before __irq_enter
+    - LP: #723819
+  * sched: Export account_system_vtime()
+    - LP: #723819
+  * sched, cgroup: Fixup broken cgroup movement
+    - LP: #723819
+  * sched: Use group weight, idle cpu metrics to fix imbalances during idle
+    - LP: #723819
+  * sched: Fix cross-sched-class wakeup preemption
+    - LP: #723819
+  * sched: Fix volanomark performance regression
+    - LP: #723819
+  * sched: Fix idle balancing
+    - LP: #723819
+  * sched: Fix wake_affine() vs RT tasks
+    - LP: #723819
+  * sched: Remove some dead code
+    - LP: #723819
+  * kernel/user.c: add lock release annotation on free_user()
+    - LP: #723819
+  * Linux 2.6.32.29
+    - LP: #723819
+  * rds: Integer overflow in RDS cmsg handling, CVE-2010-4175
+    - LP: #721455
+    - CVE-2010-4175
+
+ -- Steve Conklin <sconklin@canonical.com>  Tue, 01 Mar 2011 12:09:35 -0600
+
+linux (2.6.32-29.58) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Release Tracking Bug
+    - LP: #716551
+
+  [ Upstream Kernel Changes ]
+
+  * net: fix rds_iovec page count overflow, CVE-2010-3865
+    - LP: #709153
+    - CVE-2010-3865
+  * net: ax25: fix information leak to userland, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: ax25: fix information leak to userland harder, CVE-2010-3875
+    - LP: #710714
+    - CVE-2010-3875
+  * net: packet: fix information leak to userland, CVE-2010-3876
+    - LP: #710714
+    - CVE-2010-3876
+  * net: tipc: fix information leak to userland, CVE-2010-3877
+    - LP: #711291
+    - CVE-2010-3877
+  * inet_diag: Make sure we actually run the same bytecode we audited,
+    CVE-2010-3880
+    - LP: #711865
+    - CVE-2010-3880
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 10 Feb 2011 09:13:43 -0800
+
+linux (2.6.32-29.57) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Tracking Bug
+    - LP: #708864
+
+  [ Tim Gardner ]
+
+  * [Config] Set CONFIG_NR_CPUS=256 for amd64 server
+    - LP: #706058
+
+  [ Upstream Kernel Changes ]
+
+  * Input: i8042 - introduce 'notimeout' blacklist for Dell Vostro V13
+    - LP: #380126
+  * tun: avoid BUG, dump packet on GSO errors
+    - LP: #698883
+  * TTY: Fix error return from tty_ldisc_open()
+    - LP: #705045
+  * x86, hotplug: Use mwait to offline a processor, fix the legacy case
+    - LP: #705045
+  * fuse: verify ioctl retries
+    - LP: #705045
+  * fuse: fix ioctl when server is 32bit
+    - LP: #705045
+  * ALSA: hda: Use model=lg quirk for LG P1 Express to enable playback and
+    capture
+    - LP: #595482, #705045
+  * nohz: Fix printk_needs_cpu() return value on offline cpus
+    - LP: #705045
+  * nohz: Fix get_next_timer_interrupt() vs cpu hotplug
+    - LP: #705045
+  * nfsd: Fix possible BUG_ON firing in set_change_info
+    - LP: #705045
+  * NFS: Fix fcntl F_GETLK not reporting some conflicts
+    - LP: #705045
+  * sunrpc: prevent use-after-free on clearing XPT_BUSY
+    - LP: #705045
+  * hwmon: (adm1026) Allow 1 as a valid divider value
+    - LP: #705045
+  * hwmon: (adm1026) Fix setting fan_div
+    - LP: #705045
+  * amd64_edac: Fix interleaving check
+    - LP: #705045
+  * IB/uverbs: Handle large number of entries in poll CQ
+    - LP: #705045
+  * PM / Hibernate: Fix PM_POST_* notification with user-space suspend
+    - LP: #705045
+  * ACPICA: Fix Scope() op in module level code
+    - LP: #705045
+  * ACPI: EC: Add another dmi match entry for MSI hardware
+    - LP: #705045
+  * orinoco: fix TKIP countermeasure behaviour
+    - LP: #705045
+  * orinoco: clear countermeasure setting on commit
+    - LP: #705045
+  * x86, amd: Fix panic on AMD CPU family 0x15
+    - LP: #705045
+  * md: fix bug with re-adding of partially recovered device.
+    - LP: #705045
+  * tracing: Fix panic when lseek() called on "trace" opened for writing
+    - LP: #705045
+  * x86, gcc-4.6: Use gcc -m options when building vdso
+    - LP: #705045
+  * x86: Enable the intr-remap fault handling after local APIC setup
+    - LP: #705045
+  * x86, vt-d: Handle previous faults after enabling fault handling
+    - LP: #705045
+  * x86, vt-d: Fix the vt-d fault handling irq migration in the x2apic mode
+    - LP: #705045
+  * x86, vt-d: Quirk for masking vtd spec errors to platform error handling
+    logic
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove
+    - LP: #705045
+  * hvc_console: Fix race between hvc_close and hvc_remove, again
+    - LP: #705045
+  * HID: hidraw: fix window in hidraw_release
+    - LP: #705045
+  * bfa: fix system crash when reading sysfs fc_host statistics
+    - LP: #705045
+  * net: release dst entry while cache-hot for GSO case too
+    - LP: #705045
+  * install_special_mapping skips security_file_mmap check.
+    - LP: #705045
+  * USB: misc: uss720.c: add another vendor/product ID
+    - LP: #705045
+  * USB: ftdi_sio: Add D.O.Tec PID
+    - LP: #705045
+  * USB: usb-storage: unusual_devs entry for the Samsung YP-CP3
+    - LP: #705045
+  * p54usb: add 5 more USBIDs
+    - LP: #705045
+  * p54usb: New USB ID for Gemtek WUBI-100GW
+    - LP: #705045
+  * sound: Prevent buffer overflow in OSS load_mixer_volumes
+    - LP: #705045
+  * mv_xor: fix race in tasklet function
+    - LP: #705045
+  * ima: fix add LSM rule bug
+    - LP: #705045
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #705045
+  * ALSA: hda: Use LPIB quirk for Dell Inspiron m101z/1120
+    - LP: #705045
+  * block: Deprecate QUEUE_FLAG_CLUSTER and use queue_limits instead
+    - LP: #705045
+  * sctp: Fix a race between ICMP protocol unreachable and connect()
+    - LP: #705045
+  * posix-cpu-timers: workaround to suppress the problems with mt exec
+    - LP: #705045
+  * Linux 2.6.32.28
+    - LP: #705045
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * dell-laptop: Add another Dell laptop family to the DMI whitelist
+    - LP: #693078
+  * drm/ttm: Clear the ghost cpu_writers flag on
+    ttm_buffer_object_transfer.
+    - LP: #708769
+  * drm/kms: remove spaces from connector names (v2)
+    - LP: #708769
+  * Linux 2.6.32.28+drm33.13
+    - LP: #708769
+
+ -- Steve Conklin <sconklin@canonical.com>  Fri, 27 Jan 2011 14:56:42 -0600
+
+linux (2.6.32-28.56) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * Tracking Bug
+    - LP: #705565
+
+  * Just a build number increment for a new upload. There was an issue
+    in the previous upload that prevented ARMEL from building. The
+    issue has been resolved in the PPA and a new upload should produce
+    the requisite images.
+
+ -- Brad Figg <brad.figg@canonical.com>  Thu, 20 Jan 2011 10:29:06 -0800
+
+linux (2.6.32-28.55) lucid-proposed; urgency=low
+
+  * Another version bump because of abi check failure
+  * Tracking Bug
+    - LP: #699885
+
+ -- Steve Conklin <sconklin@canonical.com>  Mon, 10 Jan 2011 14:51:10 -0600
+
+linux (2.6.32-28.54) lucid-proposed; urgency=low
+
+  * Another version bump because of upload failure
+
+ -- Steve Conklin <sconklin@canonical.com>  Mon, 10 Jan 2011 10:31:00 -0600
+
+linux (2.6.32-28.53) lucid-proposed; urgency=low
+
+  * Another version bump because of upload failure
+
+ -- Steve Conklin <sconklin@canonical.com>  Thu, 06 Jan 2011 21:08:00 -0600
+
+linux (2.6.32-28.52) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * (removed old tracking bug link)
+
+ -- Steve Conklin <sconklin@canonical.com>  Thu, 06 Jan 2011 15:37:00 -0600
+
+linux (2.6.32-28.51) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * bumped version due to build fail
+
+ -- Steve Conklin <sconklin@canonical.com>  Wed, 05 Jan 2011 21:01:00 -0600
+
+linux (2.6.32-28.50) lucid-proposed; urgency=low
+
+  [ Tim Gardner ]
+
+  * SAUCE: Change nodelayacct boot parameter polarity.
+    - LP: #493156
+  * [Config] CONFIG_TASK_DELAY_ACCT=y
+    - LP: #493156
+
+  [ Upstream Kernel Changes ]
+
+  * ipc: initialize structure memory to zero for compat functions
+  * tcp: Increase TCP_MAXSEG socket option minimum.
+    - CVE-2010-4165
+  * perf_events: Fix perf_counter_mmap() hook in mprotect()
+    - CVE-2010-4169
+  * af_unix: limit unix_tot_inflight
+    - CVE-2010-4249
+  * AppArmor: fix the upper bound check for the next/check table
+    - LP: #581525
+  * NFS: Fix panic after nfs_umount()
+    - LP: #683938
+  * block: Ensure physical block size is unsigned int
+    - LP: #688669
+  * block: limit vec count in bio_kmalloc() and bio_alloc_map_data()
+    - LP: #688669
+  * block: take care not to overflow when calculating total iov length
+    - LP: #688669
+  * block: check for proper length of iov entries in blk_rq_map_user_iov()
+    - LP: #688669
+  * jme: Fix PHY power-off error
+    - LP: #688669
+  * irda: Fix parameter extraction stack overflow
+    - LP: #688669
+  * irda: Fix heap memory corruption in iriap.c
+    - LP: #688669
+  * i2c-pca-platform: Change device name of request_irq
+    - LP: #688669
+  * microblaze: Fix build with make 3.82
+    - LP: #688669
+  * Staging: asus_oled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * Staging: asus_oled: fix up my fixup for some sysfs attribute
+    permissions
+    - LP: #688669
+  * Staging: line6: fix up some sysfs attribute permissions
+    - LP: #688669
+  * hpet: fix unwanted interrupt due to stale irq status bit
+    - LP: #688669
+  * hpet: unmap unused I/O space
+    - LP: #688669
+  * olpc_battery: Fix endian neutral breakage for s16 values
+    - LP: #688669
+  * percpu: fix list_head init bug in __percpu_counter_init()
+    - LP: #688669
+  * um: remove PAGE_SIZE alignment in linker script causing kernel
+    segfault.
+    - LP: #688669
+  * um: fix global timer issue when using CONFIG_NO_HZ
+    - LP: #688669
+  * numa: fix slab_node(MPOL_BIND)
+    - LP: #688669
+  * hwmon: (lm85) Fix ADT7468 frequency table
+    - LP: #688669
+  * mm: fix return value of scan_lru_pages in memory unplug
+    - LP: #688669
+  * mm: fix is_mem_section_removable() page_order BUG_ON check
+    - LP: #688669
+  * ssb: b43-pci-bridge: Add new vendor for BCM4318
+    - LP: #688669
+  * sgi-xpc: XPC fails to discover partitions with all nasids above 128
+    - LP: #688669
+  * xen: ensure that all event channels start off bound to VCPU 0
+    - LP: #688669
+  * xen: don't bother to stop other cpus on shutdown/reboot
+    - LP: #688669
+  * sys_semctl: fix kernel stack leakage
+    - LP: #688669
+  * net: NETIF_F_HW_CSUM does not imply FCoE CRC offload
+    - LP: #688669
+  * drivers/char/vt_ioctl.c: fix VT_OPENQRY error value
+    - LP: #688669
+  * viafb: use proper register for colour when doing fill ops
+    - LP: #688669
+  * eCryptfs: Clear LOOKUP_OPEN flag when creating lower file
+    - LP: #688669
+  * md/raid1: really fix recovery looping when single good device fails.
+    - LP: #688669
+  * md: fix return value of rdev_size_change()
+    - LP: #688669
+  * x86: AMD Northbridge: Verify NB's node is online
+    - LP: #688669
+  * tty: prevent DOS in the flush_to_ldisc
+    - LP: #688669
+  * TTY: restore tty_ldisc_wait_idle
+    - LP: #688669
+  * tty_ldisc: Fix BUG() on hangup
+    - LP: #688669
+  * TTY: ldisc, fix open flag handling
+    - LP: #688669
+  * KVM: VMX: fix vmx null pointer dereference on debug register access
+    - LP: #688669
+    - CVE-2010-0435
+  * KVM: x86: fix information leak to userland
+    - LP: #688669
+  * firewire: cdev: fix information leak
+    - LP: #688669
+  * firewire: core: fix an information leak
+    - LP: #688669
+  * firewire: ohci: fix buffer overflow in AR split packet handling
+    - LP: #688669
+  * firewire: ohci: fix race in AR split packet handling
+    - LP: #688669
+  * ALSA: ac97: Apply quirk for Dell Latitude D610 binding Master and
+    Headphone controls
+    - LP: #669279, #688669
+  * ALSA: HDA: Add an extra DAC for Realtek ALC887-VD
+    - LP: #688669
+  * ALSA: hda: Use "alienware" model quirk for another SSID
+    - LP: #683695, #688669
+  * netfilter: nf_conntrack: allow nf_ct_alloc_hashtable() to get highmem
+    pages
+    - LP: #688669
+  * latencytop: fix per task accumulator
+    - LP: #688669
+  * mm/vfs: revalidate page->mapping in do_generic_file_read()
+    - LP: #688669
+  * bio: take care not overflow page count when mapping/copying user data
+    - LP: #688669
+  * libata-scsi passthru: fix bug which truncated LBA48 return values
+    - LP: #688669
+  * libata: fix NULL sdev dereference race in atapi_qc_complete()
+    - LP: #688669
+  * PCI: fix size checks for mmap() on /proc/bus/pci files
+    - LP: #688669
+  * PCI: fix offset check for sysfs mmapped files
+    - LP: #688669
+  * efifb: check that the base address is plausible on pci systems
+    - LP: #688669
+  * USB: gadget: AT91: fix typo in atmel_usba_udc driver
+    - LP: #688669
+  * USB: ftdi_sio: add device IDs for Milkymist One JTAG/serial
+    - LP: #688669
+  * USB: option: fix when the driver is loaded incorrectly for some Huawei
+    devices.
+    - LP: #688669
+  * usb: misc: sisusbvga: fix information leak to userland
+    - LP: #688669
+  * usb: misc: iowarrior: fix information leak to userland
+    - LP: #688669
+  * usb: core: fix information leak to userland
+    - LP: #688669
+  * USB: EHCI: fix obscure race in ehci_endpoint_disable
+    - LP: #688669
+  * USB: storage: sierra_ms: fix sysfs file attribute
+    - LP: #688669
+  * USB: atm: ueagle-atm: fix up some permissions on the sysfs files
+    - LP: #688669
+  * USB: misc: cypress_cy7c63: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: misc: usbled: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: revert "USB: ftdi_sio: fix DTR/RTS line modes"
+    - LP: #688669
+  * USB: misc: trancevibrator: fix up a sysfs attribute permission
+    - LP: #688669
+  * USB: misc: usbsevseg: fix up some sysfs attribute permissions
+    - LP: #688669
+  * USB: ftdi_sio: Add ID for RT Systems USB-29B radio cable
+    - LP: #688669
+  * USB: serial: ftdi_sio: Vardaan USB RS422/485 converter PID added
+    - LP: #688669
+  * acpi-cpufreq: fix a memleak when unloading driver
+    - LP: #688669
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #688669
+  * fuse: fix attributes after open(O_TRUNC)
+    - LP: #688669
+  * do_exit(): make sure that we run with get_fs() == USER_DS
+    - LP: #688669
+  * uml: disable winch irq before freeing handler data
+    - LP: #688669
+  * backlight: grab ops_lock before testing bd->ops
+    - LP: #688669
+  * nommu: yield CPU while disposing VM
+    - LP: #688669
+  * DECnet: don't leak uninitialized stack byte
+    - LP: #688669
+  * ARM: 6489/1: thumb2: fix incorrect optimisation in usracc
+    - LP: #688669
+  * ARM: 6482/2: Fix find_next_zero_bit and related assembly
+    - LP: #688669
+  * Staging: frontier: fix up some sysfs attribute permissions
+    - LP: #688669
+  * staging: rtl8187se: Change panic to warn when RF switch turned off
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_ioctl
+    - LP: #688669
+  * HID: hidraw, fix a NULL pointer dereference in hidraw_write
+    - LP: #688669
+  * gianfar: Fix crashes on RX path (Was Re: [Bugme-new] [Bug 19692] New:
+    linux-2.6.36-rc5 crash with gianfar ethernet at full line rate traffic)
+    - LP: #688669
+  * Limit sysctl_tcp_mem and sysctl_udp_mem initializers to prevent integer
+    overflows.
+    - LP: #688669
+  * sparc64: Fix race in signal instruction flushing.
+    - LP: #688669
+  * sparc: Don't mask signal when we can't setup signal frame.
+    - LP: #688669
+  * sparc: Prevent no-handler signal syscall restart recursion.
+    - LP: #688669
+  * x86, UV: Delete unneeded boot messages
+    - LP: #688669
+  * x86, UV: Fix initialization of max_pnode
+    - LP: #688669
+  * drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook
+    Pro 5,1
+    - LP: #688669
+  * efifb: support the EFI framebuffer on more Apple hardware
+    - LP: #688669
+  * V4L/DVB (13154): uvcvideo: Handle garbage at the end of streaming
+    interface descriptors
+    - LP: #688669
+  * Input: i8042 - add Sony VAIO VPCZ122GX to nomux list
+    - LP: #688669
+  * x25: Patch to fix bug 15678 - x25 accesses fields beyond end of packet.
+    - LP: #688669
+  * memory corruption in X.25 facilities parsing
+    - LP: #688669
+  * can-bcm: fix minor heap overflow
+    - LP: #688669
+  * V4L/DVB: ivtvfb: prevent reading uninitialized stack memory
+    - LP: #688669
+  * x25: Prevent crashing when parsing bad X.25 facilities
+    - LP: #688669
+  * crypto: padlock - Fix AES-CBC handling on odd-block-sized input
+    - LP: #688669
+  * x86-32: Separate 1:1 pagetables from swapper_pg_dir
+    - LP: #688669
+  * x86, mm: Fix CONFIG_VMSPLIT_1G and 2G_OPT trampoline
+    - LP: #688669
+  * x86-32: Fix dummy trampoline-related inline stubs
+    - LP: #688669
+  * rds: Integer overflow in RDS cmsg handling
+    - LP: #688669
+  * net: Truncate recvfrom and sendto length to INT_MAX.
+    - LP: #688669
+  * net: Limit socket I/O iovec total length to INT_MAX.
+    - LP: #688669
+  * nmi: fix clock comparator revalidation
+    - LP: #688669
+  * UV - XPC: pass nasid instead of nid to gru_create_message_queue
+    - LP: #688669
+  * x86: uv: XPC receive message reuse triggers invalid BUG_ON()
+    - LP: #688669
+  * X86: uv: xpc_make_first_contact hang due to not accepting ACTIVE state
+    - LP: #688669
+  * x86: uv: xpc NULL deref when mesq becomes empty
+    - LP: #688669
+  * Linux 2.6.32.27
+    - LP: #688669
+
+ -- Steve Conklin <sconklin@canonical.com>  Wed, 05 Jan 2011 13:42:00 -0600
+
+linux (2.6.32-27.49) lucid-proposed; urgency=low
+
+  [ Leann Ogasawara ]
+
+  - LP: #683425
+  * Revert "SAUCE: AF_ECONET prevent kernel stack overflow"
+  * Revert "SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges"
+  * Revert "SAUCE: AF_ECONET saddr->cookie prevent NULL pointer
+    dereference"
+
+  [ Tim Gardner ]
+
+  * [Config] Added be2net, be2scsi to udebs
+    - LP: #628776
+  * [Config] Use correct be2iscsi module name in d-i/modules/scsi-modules
+    - LP: #628776
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume"
+  * Revert "mm: (pre-stable) Move vma_stack_continue into mm.h"
+  * x86, cpu: After uncapping CPUID, re-run CPU feature detection
+    - LP: #668380
+  * ALSA: sound/pci/rme9652: prevent reading uninitialized stack memory
+    - LP: #668380
+  * ALSA: oxygen: fix analog capture on Claro halo cards
+    - LP: #668380
+  * ALSA: hda - Add Dell Latitude E6400 model quirk
+    - LP: #643891, #668380
+  * ALSA: rawmidi: fix oops (use after free) when unloading a driver module
+    - LP: #668380
+  * USB: fix bug in initialization of interface minor numbers
+    - LP: #668380
+  * usb: musb: gadget: fix kernel panic if using out ep with FIFO_TXRX
+    style
+    - LP: #668380
+  * usb: musb: gadget: restart request on clearing endpoint halt
+    - LP: #668380
+  * oprofile: Add Support for Intel CPU Family 6 / Model 29
+    - LP: #668380
+  * RDMA/cxgb3: Turn off RX coalescing for iWARP connections
+    - LP: #668380
+  * mmc: sdhci-s3c: fix NULL ptr access in sdhci_s3c_remove
+    - LP: #668380
+  * x86/amd-iommu: Set iommu configuration flags in enable-loop
+    - LP: #668380
+  * x86/amd-iommu: Fix rounding-bug in __unmap_single
+    - LP: #668380
+  * x86/amd-iommu: Work around S3 BIOS bug
+    - LP: #668380
+  * tracing/x86: Don't use mcount in pvclock.c
+    - LP: #668380
+  * tracing/x86: Don't use mcount in kvmclock.c
+    - LP: #668380
+  * v4l1: fix 32-bit compat microcode loading translation
+    - LP: #668380
+  * V4L/DVB: cx231xx: Avoid an OOPS when card is unknown (card=0)
+    - LP: #668380
+  * V4L/DVB (13966): DVB-T regression fix for saa7134 cards
+    - LP: #668380
+  * Input: joydev - fix JSIOCSAXMAP ioctl
+    - LP: #668380
+  * x86, hpet: Fix bogus error check in hpet_assign_irq()
+    - LP: #668380
+  * x86, irq: Plug memory leak in sparse irq
+    - LP: #668380
+  * ubd: fix incorrect sector handling during request restart
+    - LP: #668380
+  * ring-buffer: Fix typo of time extends per page
+    - LP: #668380
+  * dmaengine: fix interrupt clearing for mv_xor
+    - LP: #668380
+  * hrtimer: Preserve timer state in remove_hrtimer()
+    - LP: #668380
+  * i2c-pca: Fix waitforcompletion() return value
+    - LP: #668380
+  * wext: fix potential private ioctl memory content leak
+    - LP: #668380
+  * atl1: fix resume
+    - LP: #668380
+  * x86, AMD, MCE thresholding: Fix the MCi_MISCj iteration order
+    - LP: #668380
+  * De-pessimize rds_page_copy_user
+    - LP: #668380
+  * xfrm4: strip ECN and IP Precedence bits in policy lookup
+    - LP: #668380
+  * tcp: Fix >4GB writes on 64-bit.
+    - LP: #668380
+  * net: Fix the condition passed to sk_wait_event()
+    - LP: #668380
+  * Phonet: Correct header retrieval after pskb_may_pull
+    - LP: #668380
+  * net: Fix IPv6 PMTU disc. w/ asymmetric routes
+    - LP: #668380
+  * ip: fix truesize mismatch in ip fragmentation
+    - LP: #668380
+  * net: clear heap allocations for privileged ethtool actions
+    - LP: #668380
+  * tcp: Fix race in tcp_poll
+    - LP: #668380
+  * netxen: dont set skb->truesize
+    - LP: #668380
+  * net: blackhole route should always be recalculated
+    - LP: #668380
+  * skge: add quirk to limit DMA
+    - LP: #668380
+  * r8169: allocate with GFP_KERNEL flag when able to sleep
+    - LP: #668380
+  * bsg: fix incorrect device_status value
+    - LP: #668380
+  * r6040: fix r6040_multicast_list
+    - LP: #668380
+  * r6040: Fix multicast list iteration when hash filter is used
+    - LP: #668380
+  * powerpc: Initialise paca->kstack before early_setup_secondary
+    - LP: #668380
+  * powerpc: Don't use kernel stack with translation off
+    - LP: #668380
+  * b44: fix carrier detection on bind
+    - LP: #668380
+  * ACPI: enable repeated PCIEXP wakeup by clearing PCIEXP_WAKE_STS on
+    resume
+    - LP: #613381, #668380
+  * intel_idle: PCI quirk to prevent Lenovo Ideapad s10-3 boot hang
+    - LP: #668380
+  * ACPI: EC: add Vista incompatibility DMI entry for Toshiba Satellite
+    L355
+    - LP: #668380
+  * ACPI: delete ZEPTO idle=nomwait DMI quirk
+    - LP: #668380
+  * ACPI: Disable Windows Vista compatibility for Toshiba P305D
+    - LP: #668380
+  * x86: detect scattered cpuid features earlier
+    - LP: #668380
+  * fix 2.6.32.23 suspend regression caused by commit 6f6198a
+    - LP: #668380
+  * setup_arg_pages: diagnose excessive argument size
+    - LP: #668380
+  * execve: improve interactivity with large arguments
+    - LP: #668380
+  * execve: make responsive to SIGKILL with large arguments
+    - LP: #668380
+  * Phonet: disable network namespace support
+    - LP: #668380
+  * mm: Move vma_stack_continue into mm.h
+    - LP: #668380
+  * Linux 2.6.32.25
+    - LP: #668380
+  * xfs: validate untrusted inode numbers during lookup
+    - CVE-2010-2943
+  * xfs: rename XFS_IGET_BULKSTAT to XFS_IGET_UNTRUSTED
+    - CVE-2010-2943
+  * xfs: remove block number from inode lookup code
+    - CVE-2010-2943
+  * xfs: fix untrusted inode number lookup
+    - CVE-2010-2943
+  * drm/i915: Sanity check pread/pwrite
+    - CVE-2010-2962
+  * drm/i915: Rephrase pwrite bounds checking to avoid any potential
+    overflow
+    - CVE-2010-2962
+  * net: clear heap allocation for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3861
+  * ipc: shm: fix information leak to userland
+    - CVE-2010-4072
+  * staging: usbip: Notify usb core of port status changes
+    - LP: #681132
+  * staging: usbip: Process event flags without delay
+    - LP: #681132
+  * powerpc/perf: Fix sampling enable for PPC970
+    - LP: #681132
+  * pcmcia: synclink_cs: fix information leak to userland
+    - LP: #681132
+  * sched: Fix string comparison in /proc/sched_features
+    - LP: #681132
+  * bluetooth: Fix missing NULL check
+    - LP: #681132
+  * futex: Fix errors in nested key ref-counting
+    - LP: #681132
+  * mm, x86: Saving vmcore with non-lazy freeing of vmas
+    - LP: #681132
+  * x86, cpu: Fix renamed, not-yet-shipping AMD CPUID feature bit
+    - LP: #681132
+  * x86, kexec: Make sure to stop all CPUs before exiting the kernel
+    - LP: #681132
+  * x86, olpc: Don't retry EC commands forever
+    - LP: #681132
+  * x86, mtrr: Assume SYS_CFG[Tom2ForceMemTypeWB] exists on all future AMD
+    CPUs
+    - LP: #681132
+  * x86, intr-remap: Set redirection hint in the IRTE
+    - LP: #681132
+  * x86, kdump: Change copy_oldmem_page() to use cached addressing
+    - LP: #681132
+  * KVM: SVM: Fix wrong intercept masks on 32 bit
+    - LP: #681132
+  * KVM: MMU: fix direct sps access corrupted
+    - LP: #681132
+  * KVM: MMU: fix conflict access permissions in direct sp
+    - LP: #681132
+  * KVM: VMX: Fix host GDT.LIMIT corruption
+    - LP: #681132
+  * KVM: SVM: Adjust tsc_offset only if tsc_unstable
+    - LP: #681132
+  * KVM: x86: Fix SVM VMCB reset
+    - LP: #681132
+  * KVM: x86: Move TSC reset out of vmcb_init
+    - LP: #681132
+  * KVM: Fix fs/gs reload oops with invalid ldt
+    - LP: #681132
+  * KVM: Correct ordering of ldt reload wrt fs/gs reload
+  * KVM: VMX: Fix host userspace gsbase corruption
+  * pipe: fix failure to return error code on ->confirm()
+    - LP: #681132
+  * p54usb: fix off-by-one on !CONFIG_PM
+    - LP: #681132
+  * p54usb: add five more USBIDs
+    - LP: #681132
+  * drivers/net/wireless/p54/eeprom.c: Return -ENOMEM on memory allocation
+    failure
+    - LP: #681132
+  * USB: ftdi_sio: Add PID for accesio products
+    - LP: #681132
+  * USB: add PID for FTDI based OpenDCC hardware
+    - LP: #681132
+  * USB: ftdi_sio: new VID/PIDs for various Papouch devices
+    - LP: #681132
+  * USB: ftdi_sio: add device ids for ScienceScope
+    - LP: #681132
+  * usb: musb: blackfin: call gpio_free() on error path in
+    musb_platform_init()
+    - LP: #681132
+  * USB: option: Add more ZTE modem USB id's
+    - LP: #681132
+  * USB: cp210x: Add Renesas RX-Stick device ID
+    - LP: #681132
+  * USB: cp210x: Add WAGO 750-923 Service Cable device ID
+    - LP: #681132
+  * USB: atmel_usba_udc: force vbus_pin at -EINVAL when gpio_request
+    failled
+    - LP: #681132
+  * USB: disable endpoints after unbinding interfaces, not before
+    - LP: #681132
+  * USB: opticon: Fix long-standing bugs in opticon driver
+    - LP: #681132
+  * USB: accept some invalid ep0-maxpacket values
+    - LP: #681132
+  * sd name space exhaustion causes system hang
+    - LP: #681132
+  * libsas: fix NCQ mixing with non-NCQ
+    - LP: #681132
+  * gdth: integer overflow in ioctl
+    - LP: #681132
+  * Fix race when removing SCSI devices
+    - LP: #681132
+  * Fix regressions in scsi_internal_device_block
+    - LP: #681132
+  * sgi-xp: incoming XPC channel messages can come in after the channel's
+    partition structures have been torn down
+    - LP: #681132
+  * Linux 2.6.32.26
+    - LP: #681132
+  * drm/radeon: fix PCI ID 5657 to be an RV410
+    - LP: #683257
+  * Linux 2.6.32.26+drm33.12
+    - LP: #683257
+  * econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849
+    - CVE-2010-3849
+  * econet: fix CVE-2010-3850
+    - CVE-2010-3850
+  * econet: fix CVE-2010-3848
+    - CVE-2010-3848
+
+ -- Leann Ogasawara <leann.ogasawara@canonical.com>  Tue, 30 Nov 2010 11:20:00 -0800
+
+linux (2.6.32-26.48) lucid-security; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * SAUCE: AF_ECONET prevent kernel stack overflow
+    - CVE-2010-3848
+  * SAUCE: AF_ECONET SIOCSIFADDR ioctl does not check privileges
+    - CVE-2010-3850
+  * SAUCE: AF_ECONET saddr->cookie prevent NULL pointer dereference
+    - CVE-2010-3849
+
+ -- Leann Ogasawara <leann.ogasawara@canonical.com>  Fri, 19 Nov 2010 16:10:05 -0800
+
+linux (2.6.32-26.47) lucid-proposed; urgency=low
+
+  [ Steve Conklin ]
+
+  * Revert "SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell
+    E6510"
+  * Revert "[Config] Added be2net, be2scsi to udebs"
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony
+    laptops with ALC269"
+  * Revert "(pre-stable) ALSA: HDA: Correctly apply position_fix quirks for
+    ATI and VIA controllers"
+  * Revert "ALSA: hda: Use LPIB for another mainboard"
+  * Revert "ALSA: hda: Use LPIB for ASUS M2V"
+  * Revert "ALSA: hda: Use LPIB for an ASUS device"
+  * Buglink Fixup for reverted unverified fixes
+
+ -- Steve Conklin <sconklin@canonical.com>  Mon, 15 Nov 2010 14:59:39 -0500
+
+linux (2.6.32-26.46) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510
+    - See: #605047, #628961
+
+  [ Tim Gardner ]
+
+  * [Config] Added be2net, be2scsi to udebs
+    - See: #628776
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure we shut off the panel in eDP
+    configs"
+    - LP: #645444
+  * Revert "(pre-stable) drm/i915: make sure eDP panel is turned on"
+    - LP: #645444
+  * Revert "(pre-stable) drm/radeon/kms: initialize set_surface_reg reg for
+    rs600 asic"
+    - LP: #645371
+  * Revert "drm/nouveau: Fix fbcon corruption with font width not divisible
+    by 8"
+    - LP: #663176
+  * mmc: fix all hangs related to mmc/sd card insert/removal during
+    suspend/resume
+    - LP: #477106
+  * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y
+    - LP: #477106
+  * hwmon: (k8temp) Differentiate between AM2 and ASB1
+    - LP: #644694
+  * xen: handle events as edge-triggered
+    - LP: #644694
+  * xen: use percpu interrupts for IPIs and VIRQs
+    - LP: #644694
+  * ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763
+    - LP: #605101, #644694
+  * sata_mv: fix broken DSM/TRIM support (v2)
+    - LP: #644694
+  * x86, tsc, sched: Recompute cyc2ns_offset's during resume from sleep
+    states
+    - LP: #644694
+  * PCI: MSI: Remove unsafe and unnecessary hardware access
+    - LP: #644694
+  * PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
+    - LP: #644694
+  * sched: kill migration thread in CPU_POST_DEAD instead of CPU_DEAD
+    - LP: #644694
+  * sched: revert stable c6fc81a sched: Fix a race between ttwu() and
+    migrate_task()
+    - LP: #644694
+  * staging: hv: Fix missing functions for net_device_ops
+    - LP: #644694
+  * staging: hv: Fixed bounce kmap problem by using correct index
+    - LP: #644694
+  * staging: hv: Fixed the value of the 64bit-hole inside ring buffer
+    - LP: #644694
+  * staging: hv: Increased storvsc ringbuffer and max_io_requests
+    - LP: #644694
+  * staging: hv: Fixed lockup problem with bounce_buffer scatter list
+    - LP: #644694
+  * fuse: flush background queue on connection close
+    - LP: #644694
+  * ath9k_hw: fix parsing of HT40 5 GHz CTLs
+    - LP: #644694
+  * ocfs2: Fix incorrect checksum validation error
+    - LP: #644694
+  * USB: ehci-ppc-of: problems in unwind
+    - LP: #644694
+  * USB: Fix kernel oops with g_ether and Windows
+    - LP: #644694
+  * USB: CP210x Add new device ID
+    - LP: #644694
+  * USB: cp210x: Add B&G H3000 link cable ID
+    - LP: #644694
+  * USB: ftdi_sio: Added custom PIDs for ChamSys products
+    - LP: #644694
+  * USB: serial: Extra device/vendor ID for mos7840 driver
+    - LP: #644694
+  * usb: serial: mos7840: Add USB ID to support the B&B Electronics
+    USOPTL4-2P.
+    - LP: #644694
+  * USB: mos7840: fix DMA buffers on stack and endianess bugs
+    - LP: #644694
+  * usb: serial: mos7840: Add USB IDs to support more B&B USB/RS485
+    converters.
+    - LP: #644694
+  * USB: Exposing second ACM channel as tty for Nokia S60 phones.
+    - LP: #644694
+  * USB: cdc-acm: add another device quirk
+    - LP: #644694
+  * USB: Expose vendor-specific ACM channel on Nokia 5230
+    - LP: #644694
+  * USB: cdc-acm: Adding second ACM channel support for various Nokia and
+    one Samsung phones
+    - LP: #644694
+  * USB: cdc-acm: Add pseudo modem without AT command capabilities
+    - LP: #644694
+  * USB: cdc-acm: Fixing crash when ACM probing interfaces with no endpoint
+    descriptors.
+    - LP: #644694
+  * ALSA: hda - Fix auto-parser of ALC269vb for HP pin NID 0x21
+    - LP: #644694
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - LP: #644694
+  * sysfs: checking for NULL instead of ERR_PTR
+    - LP: #644694
+  * tun: Don't add sysfs attributes to devices without sysfs directories
+    - LP: #644694
+  * oprofile: fix crash when accessing freed task structs
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs error handling
+    - LP: #644694
+  * oprofile, x86: fix init_sysfs() function stub
+    - LP: #644694
+  * HID: usbhid: initialize interface pointers early enough
+    - LP: #644694
+  * HID: fix suspend crash by moving initializations earlier
+    - LP: #644694
+  * libata: skip EH autopsy and recovery during suspend
+    - LP: #644694
+  * tracing: Fix a race in function profile
+    - LP: #644694
+  * tracing: Do not allow llseek to set_ftrace_filter
+    - LP: #644694
+  * tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread
+    - LP: #644694
+  * irda: off by one
+    - LP: #644694
+  * gcov: fix null-pointer dereference for certain module types
+    - LP: #644694
+  * tmio_mmc: don't clear unhandled pending interrupts
+    - LP: #644694
+  * mmc: fix the use of kunmap_atomic() in tmio_mmc.h
+    - LP: #644694
+  * bounce: call flush_dcache_page() after bounce_copy_vec()
+    - LP: #644694
+  * kernel/groups.c: fix integer overflow in groups_search
+    - LP: #644694
+  * binfmt_misc: fix binfmt_misc priority
+    - LP: #644694
+  * Input: i8042 - fix device removal on unload
+    - LP: #644694
+  * memory hotplug: fix next block calculation in is_removable
+    - LP: #644694
+  * perf: Initialize callchains roots's childen hits
+    - LP: #644694
+  * p54: fix tx feedback status flag check
+    - LP: #644694
+  * ath5k: check return value of ieee80211_get_tx_rate
+    - LP: #644694
+  * wireless extensions: fix kernel heap content leak
+    - LP: #644694
+  * x86, tsc: Fix a preemption leak in restore_sched_clock_state()
+    - LP: #644694
+  * sched: Protect task->cpus_allowed access in sched_getaffinity()
+    - LP: #644694
+  * sched: Protect sched_rr_get_param() access to task->sched_class
+    - LP: #644694
+  * sched: Consolidate select_task_rq() callers
+    - LP: #644694
+  * sched: Remove unused cpu_nr_migrations()
+    - LP: #644694
+  * sched: Remove rq->clock coupling from set_task_cpu()
+    - LP: #644694
+  * sched: Clean up ttwu() rq locking
+    - LP: #644694
+  * sched: Sanitize fork() handling
+    - LP: #644694
+  * sched: Remove forced2_migrations stats
+    - LP: #644694
+  * sched: Make wakeup side and atomic variants of completion API irq safe
+    - LP: #644694
+  * sched: Use rcu in sys_sched_getscheduler/sys_sched_getparam()
+    - LP: #644694
+  * sched: Use rcu in sched_get/set_affinity()
+    - LP: #644694
+  * sched: Use rcu in sched_get_rr_param()
+    - LP: #644694
+  * sched: Fix set_cpu_active() in cpu_down()
+    - LP: #644694
+  * sched: Use TASK_WAKING for fork wakups
+    - LP: #644694
+  * sched: Ensure set_task_cpu() is never called on blocked tasks
+    - LP: #644694
+  * sched: Make warning less noisy
+    - LP: #644694
+  * sched: Fix broken assertion
+    - LP: #644694
+  * sched: Fix sched_exec() balancing
+    - LP: #644694
+  * sched: Fix select_task_rq() vs hotplug issues
+    - LP: #644694
+  * sched: Add pre and post wakeup hooks
+    - LP: #644694
+  * sched: Remove the cfs_rq dependency from set_task_cpu()
+    - LP: #644694
+  * sched: Fix hotplug hang
+    - LP: #644694
+  * sched: Fix fork vs hotplug vs cpuset namespaces
+    - LP: #644694
+  * sched: Fix incorrect sanity check
+    - LP: #644694
+  * sched: Fix race between ttwu() and task_rq_lock()
+    - LP: #644694
+  * sched: Extend enqueue_task to allow head queueing
+    - LP: #644694
+  * sched: Implement head queueing for sched_rt
+    - LP: #644694
+  * sched: Queue a deboosted task to the head of the RT prio queue
+    - LP: #644694
+  * sched: set_cpus_allowed_ptr(): Don't use rq->migration_thread after
+    unlock
+    - LP: #644694
+  * sched: Kill the broken and deadlockable
+    cpuset_lock/cpuset_cpus_allowed_locked code
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Take rq->lock around
+    select_fallback_rq()
+    - LP: #644694
+  * sched: move_task_off_dead_cpu(): Remove retry logic
+    - LP: #644694
+  * sched: sched_exec(): Remove the select_fallback_rq() logic
+    - LP: #644694
+  * sched: _cpu_down(): Don't play with current->cpus_allowed
+    - LP: #644694
+  * sched: Make select_fallback_rq() cpuset friendly
+    - LP: #644694
+  * sched: Fix TASK_WAKING vs fork deadlock
+    - LP: #644694
+  * sched: Optimize task_rq_lock()
+    - LP: #644694
+  * sched: Fix nr_uninterruptible count
+    - LP: #644694
+  * sched: Fix rq->clock synchronization when migrating tasks
+    - LP: #644694
+  * sched: Remove unnecessary RCU exclusion
+    - LP: #644694
+  * sched: apply RCU protection to wake_affine()
+    - LP: #644694
+  * sched: Cleanup select_task_rq_fair()
+    - LP: #644694
+  * sched: More generic WAKE_AFFINE vs select_idle_sibling()
+    - LP: #644694
+  * sched: Fix vmark regression on big machines
+    - LP: #644694
+  * sched: Fix select_idle_sibling()
+    - LP: #644694
+  * sched: Pre-compute cpumask_weight(sched_domain_span(sd))
+    - LP: #644694
+  * sched: Fix select_idle_sibling() logic in select_task_rq_fair()
+    - LP: #644694
+  * sched: cpuacct: Use bigger percpu counter batch values for stats
+    counters
+    - LP: #644694
+  * ALSA: hda - Handle missing NID 0x1b on ALC259 codec
+    - LP: #644694
+  * ALSA: hda - Handle pin NID 0x1a on ALC259/269
+    - LP: #644694
+  * arm: fix really nasty sigreturn bug
+    - LP: #644694
+  * hwmon: (f75375s) Shift control mode to the correct bit position
+    - LP: #644694
+  * hwmon: (f75375s) Do not overwrite values read from registers
+    - LP: #644694
+  * apm_power: Add missing break statement
+    - LP: #644694
+  * NFS: Fix a typo in nfs_sockaddr_match_ipaddr6
+    - LP: #644694
+  * SUNRPC: Fix race corrupting rpc upcall
+    - LP: #644694
+  * Linux 2.6.32.22
+    - LP: #644694
+  * drm/i915: don't access FW_BLC_SELF on 965G
+    - LP: #645444
+  * drm/i915: gen3 page flipping fixes
+    - LP: #645444
+  * drm/i915: don't queue flips during a flip pending event
+    - LP: #645444
+  * drm/i915: Hold the spinlock whilst resetting unpin_work along error
+    path
+    - LP: #645444
+  * drm/i915: handle shared framebuffers when flipping
+    - LP: #645444
+  * drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #645444
+  * drm/i915: make sure eDP panel is turned on
+    - LP: #645444
+  * drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #645444
+  * Linux 2.6.32.22+drm33.9
+    - LP: #645444
+  * drm/radeon/kms/igp: sideport is AMD only
+    - LP: #645371
+  * drm/radeon/kms: flush HDP cache on GART table updates.
+    - LP: #645371
+  * drm/radeon/kms/r7xx: add workaround for hw issue with HDP flush
+    - LP: #645371
+  * drm/i915: Check overlay stride errata for i830 and i845
+    - LP: #645371
+  * i915: fix ironlake edp panel setup (v4)
+    - LP: #645371
+  * drm/radeon/kms: add additional quirk for Acer rv620 laptop
+    - LP: #645371
+  * drm/i915: fixup pageflip ringbuffer commands for i8xx
+    - LP: #645371
+  * drm/i915: i8xx also doesn't like multiple oustanding pageflips
+    - LP: #645371
+  * drm/i915/edp: Flush the write before waiting for PLLs
+    - LP: #645371
+  * drm/radeon/kms: disable MSI on IGP chips
+    - LP: #645371
+  * drm/radeon/kms: don't enable MSIs on AGP boards
+    - LP: #645371
+  * drm/radeon/kms: fix typo in radeon_compute_pll_gain
+    - LP: #645371
+  * drm/radeon/kms/DCE3+: switch pads to ddc mode when going i2c
+    - LP: #645371
+  * drm/radeon/kms: fix sideport detection on newer rs880 boards
+    - LP: #645371
+  * drm/i915: Don't touch PORT_HOTPLUG_EN in intel_dp_detect()
+    - LP: #645371
+  * drm/i915: Kill dangerous pending-flip debugging
+    - LP: #645371
+  * drm/radeon/kms: release AGP bridge at suspend
+    - LP: #645371
+  * drm/radeon/kms: initialize set_surface_reg reg for rs600 asic
+    - LP: #645371
+  * drm/radeon/kms: fix a regression on r7xx AGP due to the HDP flush fix
+    - LP: #645371
+  * Linux 2.6.32.22+drm33.10
+    - LP: #645371
+  * USB: serial/mos*: prevent reading uninitialized stack memory
+    - LP: #649483
+  * sparc: Provide io{read,write}{16,32}be().
+    - LP: #649483
+  * gro: fix different skb headrooms
+    - LP: #649483
+  * gro: Re-fix different skb headrooms
+    - LP: #649483
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - LP: #649483
+  * tcp: select(writefds) don't hang up when a peer close connection
+    - LP: #649483
+  * tcp: Combat per-cpu skew in orphan tests.
+    - LP: #649483
+  * tcp: fix three tcp sysctls tuning
+    - LP: #649483
+  * bridge: Clear IPCB before possible entry into IP stack
+    - LP: #649483
+  * bridge: Clear INET control block of SKBs passed into ip_fragment().
+    - LP: #649483
+  * net: Fix oops from tcp_collapse() when using splice()
+    - LP: #649483
+  * rds: fix a leak of kernel memory
+    - LP: #649483
+  * tcp: Prevent overzealous packetization by SWS logic.
+    - LP: #649483
+  * UNIX: Do not loop forever at unix_autobind().
+    - LP: #649483
+  * r8169: fix random mdio_write failures
+    - LP: #649483
+  * r8169: fix mdio_read and update mdio_write according to hw specs
+    - LP: #649483
+  * sparc64: Get rid of indirect p1275 PROM call buffer.
+    - LP: #649483
+  * drivers/net/usb/hso.c: prevent reading uninitialized memory
+    - LP: #649483
+  * drivers/net/cxgb3/cxgb3_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * drivers/net/eql.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * bonding: correctly process non-linear skbs
+    - LP: #649483
+  * Staging: vt6655: fix buffer overflow
+    - LP: #649483
+  * net/llc: make opt unsigned in llc_ui_setsockopt()
+    - LP: #649483
+  * pid: make setpgid() system call use RCU read-side critical section
+    - LP: #649483
+  * sched: Fix user time incorrectly accounted as system time on 32-bit
+    - LP: #649483
+  * oprofile: Add Support for Intel CPU Family 6 / Model 22 (Intel Celeron
+    540)
+    - LP: #649483
+  * char: Mark /dev/zero and /dev/kmem as not capable of writeback
+    - LP: #649483
+  * drivers/pci/intel-iommu.c: fix build with older gcc's
+    - LP: #649483
+  * drivers/video/sis/sis_main.c: prevent reading uninitialized stack
+    memory
+    - LP: #649483
+  * percpu: fix pcpu_last_unit_cpu
+    - LP: #649483
+  * aio: check for multiplication overflow in do_io_submit
+    - LP: #649483
+  * inotify: send IN_UNMOUNT events
+    - LP: #649483
+  * SCSI: mptsas: fix hangs caused by ATA pass-through
+    - LP: #649483
+  * ext4: Fix remaining racy updates of EXT4_I(inode)->i_flags
+    - LP: #649483
+  * IA64: fix siglock
+    - LP: #649483
+  * IA64: Optimize ticket spinlocks in fsys_rt_sigprocmask
+    - LP: #649483
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - LP: #649483
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - LP: #649483
+  * xfs: prevent reading uninitialized stack memory
+    - LP: #649483
+  * drivers/video/via/ioctl.c: prevent reading uninitialized stack memory
+    - LP: #649483
+  * ACPI: disable _OSI(Windows 2009) on Asus K50IJ
+    - LP: #649483
+  * bnx2: Fix netpoll crash.
+    - LP: #649483
+  * bnx2: Fix hang during rmmod bnx2.
+    - LP: #649483
+  * AT91: change dma resource index
+    - LP: #649483
+  * cxgb3: fix hot plug removal crash
+    - LP: #649483
+  * mm: page allocator: drain per-cpu lists after direct reclaim allocation
+    fails
+    - LP: #649483
+  * mm: page allocator: calculate a better estimate of NR_FREE_PAGES when
+    memory is low and kswapd is awake
+    - LP: #649483
+  * mm: page allocator: update free page counters after pages are placed on
+    the free list
+    - LP: #649483
+  * guard page for stacks that grow upwards
+    - LP: #649483
+  * Fix unprotected access to task credentials in waitid()
+    - LP: #649483
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - LP: #649483
+  * 3c503: Fix IRQ probing
+    - LP: #649483
+  * asix: fix setting mac address for AX88772
+    - LP: #649483
+  * dasd: use correct label location for diag fba disks
+    - LP: #649483
+  * clocksource: sh_tmu: compute mult and shift before registration
+    - LP: #649483
+  * gro: Fix bogus gso_size on the first fraglist entry
+    - LP: #649483
+  * hostap_pci: set dev->base_addr during probe
+    - LP: #649483
+  * inotify: fix inotify oneshot support
+    - LP: #649483
+  * Input: add compat support for sysfs and /proc capabilities output
+    - LP: #649483
+  * MIPS: Quit using undefined behavior of ADDU in 64-bit atomic
+    operations.
+    - LP: #649483
+  * MIPS: Set io_map_base for several PCI bridges lacking it
+    - LP: #649483
+  * MIPS: uasm: Add OR instruction.
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for Promise UDMA33 cards
+    - LP: #649483
+  * pata_pdc202xx_old: fix UDMA mode for PDC2026x chipsets
+    - LP: #649483
+  * MIPS: Sibyte: Fix M3 TLB exception handler workaround.
+    - LP: #649483
+  * sis-agp: Remove SIS 760, handled by amd64-agp
+    - LP: #649483
+  * alpha: Fix printk format errors
+    - LP: #649483
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #649483
+  * Linux 2.6.32.23
+    - LP: #649483
+  * (pre-stable) [SCSI] megaraid_sas: Add new megaraid SAS 2 controller
+    support to the driver
+    - LP: #546091
+  * (pre-stable) [SCSI] megaraid_sas: allocate the application cmds to sas2
+    controller
+    - LP: #546091
+  * Xen: fix typo in previous patch
+    - LP: #655456
+  * Linux 2.6.32.24
+    - LP: #655456
+  * (ore-stable) ALSA: hda - Apply ALC269 VAIO fix-up to all Sony laptops
+    with ALC269
+    - See: #546769, #598938, #637291, #642892, #648871, #655386
+  * (pre-stable) ALSA: HDA: Correctly apply position_fix quirks for ATI and
+    VIA controllers
+    - See: #465942, #580749, #587546
+  * (pre-stable) ACPI: enable repeated PCIEXP wakeup by clearing
+    PCIEXP_WAKE_STS on resume
+    - LP: #613381
+  * i915: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * i915_gem: return -EFAULT if copy_to_user fails
+    - LP: #663176
+  * drm/i915: Prevent double dpms on
+    - LP: #663176
+  * drm: Only decouple the old_fb from the crtc is we call mode_set*
+    - LP: #663176
+  * drm/radeon/kms: fix potential segfault in r600_ioctl_wait_idle
+    - LP: #663176
+  * drm/i915: Unset cursor if out-of-bounds upon mode change (v4)
+    - LP: #586325, #663176
+  * drm/i915: disable FBC when more than one pipe is active
+    - LP: #663176
+  * drm/radeon/kms: fix macbookpro connector quirk
+    - LP: #663176
+  * drm/nouveau: use ALIGN instead of open coding it
+    - LP: #663176
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #663176
+  * drm/i915,agp/intel: Add second set of PCI-IDs for B43
+    - LP: #640214, #663176
+  * Linux 2.6.32.24+drm33.11
+    - LP: #663176
+
+ -- Brad Figg <brad.figg@canonical.com>  Fri, 22 Oct 2010 10:41:58 -0700
+
+linux (2.6.32-25.45) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * v4l: disable dangerous buggy compat function
+    - CVE-2010-2963
+  * Local privilege escalation vulnerability in RDS sockets
+    - CVE-2010-3904
+  * mm: (pre-stable) Move vma_stack_continue into mm.h
+    - LP: #646114
+  * net sched: fix some kernel memory leaks
+    - CVE-2010-2942
+  * irda: Correctly clean up self->ias_obj on irda_bind() failure.
+    - CVE-2010-2954
+  * wireless extensions: fix kernel heap content leak
+    - CVE-2010-2955
+  * KEYS: Fix RCU no-lock warning in keyctl_session_to_parent()
+    - CVE-2010-2960
+  * KEYS: Fix bug in keyctl_session_to_parent() if parent has no session
+    keyring
+    - CVE-2010-2960
+  * aio: check for multiplication overflow in do_io_submit
+    - CVE-2010-3067
+  * xfs: prevent reading uninitialized stack memory
+    - CVE-2010-3078
+  * ALSA: seq/oss - Fix double-free at error path of snd_seq_oss_open()
+    - CVE-2010-3080
+  * niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL
+    - CVE-2010-3084
+  * rose: Fix signedness issues wrt. digi count.
+    - CVE-2010-3310
+  * sctp: Do not reset the packet during sctp_packet_config().
+    - CVE-2010-3432
+  * Fix pktcdvd ioctl dev_minor range check
+    - CVE-2010-3437
+  * ALSA: prevent heap corruption in snd_ctl_new()
+    - CVE-2010-3442
+  * net sched: fix kernel leak in act_police
+    - CVE-2010-3477
+  * Fix out-of-bounds reading in sctp_asoc_get_hmac()
+    - CVE-2010-3705
+  * ocfs2: Don't walk off the end of fast symlinks.
+    - CVE-2010-NNN2
+
+ -- Steve Conklin <sconklin@canonical.com>  Wed, 06 Oct 2010 16:16:20 +0100
+
+linux (2.6.32-25.44) lucid-proposed; urgency=low
+
+  [ Brad Figg ]
+
+  * SAUCE: (no-up) Modularize vesafb -- fix initialization
+    - LP: #611471
+
+  [ Stefan Bader ]
+
+  * Revert "SAUCE: sync before umount to reduce time taken by ext4 umount"
+    - LP: #543617, #585092
+
+  [ Steve Conklin ]
+
+  * Revert "SAUCE: tulip: Let dmfe handle davicom on non-sparc"
+    - LP: #607824
+
+  [ Tim Gardner ]
+
+  * [Config] Added ums-cypress to udeb
+    - LP: #576066
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "PCI quirk: Disable MSI on VIA K8T890 systems"
+    - LP: #607824
+  * Revert "PCI quirks: disable msi on AMD rs4xx internal gfx bridges"
+    - LP: #607824
+  * Revert "(pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting"
+    - LP: #607824
+  * Revert "jbd: jbd-debug and jbd2-debug should be writable"
+    - LP: #607824
+  * Revert "ext4: Make fsync sync new parent directories in no-journal
+    mode"
+    - LP: #615548
+  * Revert "ext4: Fix compat EXT4_IOC_ADD_GROUP"
+    - LP: #615548
+  * Revert "ext4: Conditionally define compat ioctl numbers"
+    - LP: #615548
+  * Revert "ext4: restart ext4_ext_remove_space() after transaction
+    restart"
+    - LP: #615548
+  * Revert "ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted"
+    - LP: #615548
+  * Revert "ext4: Avoid crashing on NULL ptr dereference on a filesystem
+    error"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify i_flags in struct
+    ext4_inode_info"
+    - LP: #615548
+  * Revert "ext4: Show journal_checksum option"
+    - LP: #615548
+  * Revert "ext4: check for a good block group before loading buddy pages"
+    - LP: #615548
+  * Revert "ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate"
+    - LP: #615548
+  * Revert "ext4: Remove extraneous newlines in ext4_msg() calls"
+    - LP: #615548
+  * Revert "ext4: init statistics after journal recovery"
+    - LP: #615548
+  * Revert "ext4: clean up inode bitmaps manipulation in ext4_free_inode"
+    - LP: #615548
+  * Revert "ext4: Do not zero out uninitialized extents beyond i_size"
+    - LP: #615548
+  * Revert "ext4: don't scan/accumulate more pages than mballoc will
+    allocate"
+    - LP: #615548
+  * Revert "ext4: stop issuing discards if not supported by device"
+    - LP: #615548
+  * Revert "ext4: check s_log_groups_per_flex in online resize code"
+    - LP: #615548
+  * Revert "ext4: fix quota accounting in case of fallocate"
+    - LP: #615548
+  * Revert "ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode"
+    - LP: #615548
+  * Revert "ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()"
+    - LP: #615548
+  * Revert "ext4: Remove unnecessary call to ext4_get_group_desc() in
+    mballoc"
+    - LP: #615548
+  * Revert "ext4: fix memory leaks in error path handling of
+    ext4_ext_zeroout()"
+    - LP: #615548
+  * Revert "ext4: check missed return value in ext4_sync_file()"
+    - LP: #615548
+  * Revert "ext4: Issue the discard operation *before* releasing the blocks
+    to be reused"
+    - LP: #615548
+  * Revert "ext4: Fix buffer head leaks after calls to
+    ext4_get_inode_loc()"
+    - LP: #615548
+  * Revert "ext4: Fix possible lost inode write in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Fixed inode allocator to correctly track a flex_bg's
+    used_dirs"
+    - LP: #615548
+  * Revert "ext4: Fix estimate of # of blocks needed to write
+    indirect-mapped files"
+    - LP: #615548
+  * Revert "ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl"
+    - LP: #615548
+  * Revert "ext4: Fix the NULL reference in double_down_write_data_sem()"
+    - LP: #615548
+  * Revert "ext4: Fix insertion point of extent in
+    mext_insert_across_blocks()"
+    - LP: #615548
+  * Revert "ext4: make "offset" consistent in ext4_check_dir_entry()"
+    - LP: #615548
+  * Revert "ext4: Handle non empty on-disk orphan link"
+    - LP: #615548
+  * Revert "ext4: explicitly remove inode from orphan list after failed
+    direct io"
+    - LP: #615548
+  * Revert "ext4: fix error handling in migrate"
+    - LP: #615548
+  * Revert "ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation."
+    - LP: #615548
+  * Revert "ext4: Add flag to files with blocks intentionally past EOF"
+    - LP: #615548
+  * Revert "ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode"
+    - LP: #615548
+  * Revert "ext4: Use bitops to read/modify EXT4_I(inode)->i_state"
+    - LP: #615548
+  * Revert "ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag"
+    - LP: #615548
+  * Revert "ext4: Fix quota accounting error with fallocate"
+    - LP: #615548
+  * Revert "ext4: Handle -EDQUOT error on write"
+    - LP: #615548
+  * Revert "ext4: Calculate metadata requirements more accurately"
+    - LP: #615548
+  * Revert "ext4: Fix accounting of reserved metadata blocks"
+    - LP: #615548
+  * Revert "ext4: Patch up how we claim metadata blocks for quota purposes"
+    - LP: #615548
+  * Revert "ext4: Ensure zeroout blocks have no dirty metadata"
+    - LP: #615548
+  * Revert "ext4: return correct wbc.nr_to_write in ext4_da_writepages"
+    - LP: #615548
+  * Revert "ext4: Eliminate potential double free on error path"
+    - LP: #615548
+  * Revert "ext4, jbd2: Add barriers for file systems with exernal
+    journals"
+    - LP: #615548
+  * Revert "ext4: replace BUG() with return -EIO in ext4_ext_get_blocks"
+    - LP: #615548
+  * Revert "ext4: Fix potential quota deadlock"
+    - LP: #615548
+  * Revert "ext4: don't return to userspace after freezing the fs with a
+    mutex held"
+    - LP: #615548
+  * ixgbe: Fix return of invalid txq
+    - LP: #607824
+  * oprofile/x86: fix uninitialized counter usage during cpu hotplug
+    - LP: #607824
+  * oprofile: remove double ring buffering
+    - LP: #607824
+  * cpumask: fix compat getaffinity
+    - LP: #607824
+  * NFSD: don't report compiled-out versions as present
+    - LP: #607824
+  * sata_nv: use ata_pci_sff_activate_host() instead of ata_host_activate()
+    - LP: #607824
+  * ARCNET: Limit com20020 PCI ID matches for SOHARD cards
+    - LP: #607824
+  * rtl8180: fix tx status reporting
+    - LP: #607824
+  * Staging: add Add Sitecom WL-349 to rtl8192su
+    - LP: #607824
+  * staging: vt6655: Fix kernel BUG on driver wpa initialization
+    - LP: #607824
+  * Fix racy use of anon_inode_getfd() in perf_event.c
+    - LP: #607824
+  * posix_timer: Fix error path in timer_create
+    - LP: #607824
+  * libata: disable ATAPI AN by default
+    - LP: #607824
+  * libata: don't flush dcache on slab pages
+    - LP: #607824
+  * mutex: Fix optimistic spinning vs. BKL
+    - LP: #607824
+  * ALSA: hda: Fix model quirk for Dell M1730
+    - LP: #576160, #607824
+  * ALSA: hda: Use LPIB for Toshiba A100-259
+    - LP: #549560, #607824
+  * ALSA: hda: Use LPIB for Acer Aspire 5110
+    - LP: #583983, #607824
+  * ALSA: hda: Use LPIB for Sony VPCS11V9E
+    - LP: #586347, #607824
+  * ALSA: hda: Use LPIB for a Shuttle device
+    - LP: #551949, #607824
+  * ACPI: video: fix acpi_backlight=video
+    - LP: #573120, #607824
+  * V4L/DVB: gspca - stv06xx: Remove the 046d:08da from the stv06xx driver
+    - LP: #607824
+  * HID: Add the GYR4101US USB ID to hid-gyration
+    - LP: #607824
+  * ar9170usb: add a couple more USB IDs
+    - LP: #607824
+  * ar9170usb: fix panic triggered by undersized rxstream buffer
+    - LP: #607824
+  * USB: visor: fix memory leak
+    - LP: #607824
+  * USB: CP210x New Device IDs 11 New device IDs
+    - LP: #607824
+  * USB: kobil: fix memory leak
+    - LP: #607824
+  * USB: option: add PID for ZTE product
+    - LP: #607824
+  * USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem
+    interface is 0xff
+    - LP: #607824
+  * USB: serial: option: add cinterion device id
+    - LP: #607824
+  * USB: option.c: OLIVETTI OLICARD100 support
+    - LP: #607824
+  * USB: ir-usb: fix double free
+    - LP: #607824
+  * USB: kl5usb105: fix memory leak
+    - LP: #607824
+  * USB: mxc: gadget: Fix bitfield for calculating maximum packet size
+    - LP: #607824
+  * USB: unusual-dev: Add bad sense flag for Appotech ax203 based picture
+    frames
+    - LP: #607824
+  * USB: EHCI: clear PHCD before resuming
+    - LP: #607824
+  * USB: xhci: Fix issue with set interface after stall.
+    - LP: #607824
+  * USB: xhci: Fix check for room on the ring.
+    - LP: #607824
+  * USB: xHCI: Fix wrong usage of macro TRB_TYPE
+    - LP: #607824
+  * mac80211: give warning if building w/out rate ctrl algorithm
+    - LP: #607824
+  * mac80211: Fix robust management frame handling (MFP)
+    - LP: #607824
+  * mac80211: fix rts threshold check
+    - LP: #607824
+  * drivers/base/cpu.c: fix the output from /sys/devices/system/cpu/offline
+    - LP: #607824
+  * can: Fix SJA1000 command register writes on SMP systems
+    - LP: #607824
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #607824
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #607824
+  * PCI: Disable MSI for MCP55 on P5N32-E SLI
+    - LP: #607824
+  * virtio_net: Make delayed refill more reliable
+    - LP: #607824
+  * mm: hugetlb: fix clear_huge_page()
+    - LP: #607824
+  * powerpc: Fix handling of strncmp with zero len
+    - LP: #607824
+  * powerpc/pseries: Only call start-cpu when a CPU is stopped
+    - LP: #607824
+  * powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu
+    - LP: #607824
+  * powerpc/oprofile: fix potential buffer overrun in op_model_cell.c
+    - LP: #607824
+  * writeback: disable periodic old data writeback for
+    !dirty_writeback_centisecs
+    - LP: #607824
+  * md/raid1: fix counting of write targets.
+    - LP: #607824
+  * md: Fix read balancing in RAID1 and RAID10 on drives > 2TB
+    - LP: #607824
+  * md: set mddev readonly flag on blkdev BLKROSET ioctl
+    - LP: #607824
+  * x86/amd-iommu: Fix suspend/resume with IOMMU
+    - LP: #607824
+  * exofs: confusion between kmap() and kmap_atomic() api
+    - LP: #607824
+  * mn10300: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * m68k: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * rtc-cmos: do dev_set_drvdata() earlier in the initialization
+    - LP: #607824
+  * rtc: s3c: initialize driver data before using it
+    - LP: #607824
+  * frv: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * xtensa: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * Blackfin: set ARCH_KMALLOC_MINALIGN
+    - LP: #607824
+  * tmpfs: insert tmpfs cache pages to inactive list at first
+    - LP: #607824
+  * mlx4_core: Fix possible chunk sg list overflow in mlx4_alloc_icm()
+    - LP: #607824
+  * ARM: 6166/1: Proper prefetch abort handling on pre-ARMv6
+    - LP: #607824
+  * ARM: 6164/1: Add kto and kfrom to input operands list.
+    - LP: #607824
+  * ARM: 6146/1: sa1111: Prevent deadlock in resume path
+    - LP: #607824
+  * ARM: 6144/1: TCM memory bug freeing bug
+    - LP: #607824
+  * ARM: VFP: Fix vfp_put_double() for d16-d31
+    - LP: #607824
+  * ASoC: Fix dB scales for WM835x
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8400
+    - LP: #607824
+  * ASoC: Fix dB scales for WM8990
+    - LP: #607824
+  * hwmon: (ltc4245) Read only one GPIO pin
+    - LP: #607824
+  * signals: check_kill_permission(): don't check creds if
+    same_thread_group()
+    - LP: #607824
+  * do_generic_file_read: clear page errors when issuing a fresh read of
+    the page
+    - LP: #607824
+  * ipmi: handle run_to_completion properly in deliver_recv_msg()
+    - LP: #607824
+  * x86, setup: Phoenix BIOS fixup is needed on Dell Inspiron Mini 1012
+    - LP: #607824
+  * xen: ensure timer tick is resumed even on CPU driving the resume
+    - LP: #607824
+  * xen: avoid allocation causing potential swap activity on the resume
+    path
+    - LP: #607824
+  * ALSA: hda: Use LPIB for an ASUS device
+    - See: #465942, #607824
+  * ALSA: hda: Use mb31 quirk for an iMac model
+    - LP: #542550, #607824
+  * ALSA: hda: Use LPIB for another mainboard
+    - See: #580749, #607824
+  * ALSA: hda: Use LPIB for ASUS M2V
+    - LP: #587546, #607824
+  * Staging: comedi - correct parameter gainlkup for DAQCard-6024E in
+    driver ni_mio_cs.c
+    - LP: #607824
+  * clocksource: sh_cmt: compute mult and shift before registration
+    - LP: #607824
+  * ath5k: retain promiscuous setting
+    - LP: #607824
+  * ahci: add pci quirk for JMB362
+    - LP: #607824
+  * firewire: core: check for 1394a compliant IRM, fix inaccessibility of
+    Sony camcorder
+    - LP: #607824
+  * perf_events: Fix resource leak in x86 __hw_perf_event_init()
+    - LP: #607824
+  * sata_nv: don't diddle with nIEN on mcp55
+    - LP: #607824
+  * sata_via: magic vt6421 fix for transmission problems w/ WD drives
+    - LP: #422994, #607824
+  * USB: mos7840: fix null-pointer dereference
+    - LP: #607824
+  * USB: xhci: Wait for host to start running.
+    - LP: #607824
+  * USB: xhci: Wait for controller to be ready after reset.
+    - LP: #607824
+  * USB: ftdi_sio: fix DTR/RTS line modes
+    - LP: #607824
+  * USB: cdc-acm: fix resource reclaim in error path of acm_probe
+    - LP: #607824
+  * p54usb: Add device ID for Dell WLA3310 USB
+    - LP: #607824
+  * atl1e: Allow TX checksum offload and TSO to be disabled and reenabled
+    - LP: #607824
+  * via-velocity: Give RX descriptors to the NIC later on open or MTU
+    change
+    - LP: #607824
+  * dmfe/tulip: Let dmfe handle DM910x except for SPARC on-board chips
+    - LP: #607824
+  * Documentation/3c509: document ethtool support
+    - LP: #607824
+  * wireless: report reasonable bitrate for MCS rates through wext
+    - LP: #607824
+  * ath9k: add support for 802.11n bonded out AR2427
+    - LP: #607824
+  * wrong type for 'magic' argument in simple_fill_super()
+    - LP: #607824
+  * iwlwifi: check for aggregation frame and queue
+    - LP: #607824
+  * iwlwifi: recalculate average tpt if not current
+    - LP: #607824
+  * iwlwifi: update supported PCI_ID list for 5xx0 series
+    - LP: #607824
+  * wl1251: fix a memory leak in probe
+    - LP: #607824
+  * vfs: add NOFOLLOW flag to umount(2)
+    - LP: #607824
+  * l2tp: Fix oops in pppol2tp_xmit
+    - LP: #607824
+  * ucc_geth: Fix empty TX queue processing
+    - LP: #607824
+  * ucc_geth: Fix netdev watchdog triggering on link changes
+    - LP: #607824
+  * ucc_geth: Fix full TX queue processing
+    - LP: #607824
+  * Input: psmouse - reset all types of mice before reconnecting
+    - LP: #607824
+  * KVM: s390: Fix possible memory leak of in kvm_arch_vcpu_create()
+    - LP: #607824
+  * KVM: PPC: Do not create debugfs if fail to create vcpu
+    - LP: #607824
+  * x86, paravirt: Add a global synchronization point for pvclock
+    - LP: #607824
+  * KVM: Don't allow lmsw to clear cr0.pe
+    - LP: #607824
+  * KVM: x86: Check LMA bit before set_efer
+    - LP: #607824
+  * KVM: MMU: Segregate shadow pages with different cr0.wp
+    - LP: #607824
+  * KVM: VMX: enable VMXON check with SMX enabled (Intel TXT)
+    - LP: #607824
+  * KVM: MMU: Don't read pdptrs with mmu spinlock held in mmu_alloc_roots
+    - LP: #607824
+  * KVM: Fix wallclock version writing race
+    - LP: #607824
+  * KVM: x86: Add missing locking to arch specific vcpu ioctls
+    - LP: #607824
+  * KVM: x86: Inject #GP with the right rip on efer writes
+    - LP: #607824
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #607824
+  * parisc: clear floating point exception flag on SIGFPE signal
+    - LP: #607824
+  * dm snapshot: simplify sector_to_chunk expression
+    - LP: #607824
+  * KEYS: Return more accurate error codes
+    - LP: #607824
+  * qla2xxx: Disable MSI on qla24xx chips other than QLA2432.
+    - LP: #607824
+  * Linux 2.6.32.16
+    - LP: #607824
+  * drm/i915: Fix 82854 PCI ID, and treat it like other 85X
+    - LP: #607824
+  * drm/i915: Reject bind_to_gtt() early if object > aperture
+    - LP: #607824
+  * drm/edid: Fix 1024x768@85Hz
+    - LP: #607824
+  * drm/radeon/kms: reset ddc_bus in object header parsing
+    - LP: #607824
+  * drm/radeon/kms/atom: fix typo in LVDS panel info parsing
+    - LP: #607824
+  * drm/radeon: r100/r200 ums: block ability for userspace app to trash 0
+    page and beyond
+    - LP: #607824
+  * drm/radeon: fix the r100/r200 ums block 0 page fix
+    - LP: #607824
+  * drm/i915: Rebind bo if currently bound with incorrect alignment.
+    - LP: #607824
+  * Linux 2.6.32.16+drm33.6
+    - LP: #607824
+  * virtio-pci: disable msi at startup
+    - LP: #615548
+  * hwmon: (k8temp) Bypass core swapping on single-core processors
+    - LP: #615548
+  * hwmon: (k8temp) Fix temperature reporting for ASB1 processor revisions
+    - LP: #615548
+  * hwmon: (coretemp) Properly label the sensors
+    - LP: #615548
+  * hwmon: (coretemp) Skip duplicate CPU entries
+    - LP: #615548
+  * hwmon: (it87) Fix in7 on IT8720F
+    - LP: #615548
+  * cifs: remove bogus first_time check in NTLMv2 session setup code
+    - LP: #615548
+  * cifs: don't attempt busy-file rename unless it's in same directory
+    - LP: #615548
+  * CIFS: Fix a malicious redirect problem in the DNS lookup code
+    - LP: #615548
+  * ALSA: hda - Add Macbook 5,2 quirk
+    - LP: #463178, #615548
+  * cpmac: do not leak struct net_device on phy_connect errors
+    - LP: #615548
+  * sky2: enable rx/tx in sky2_phy_reinit()
+    - LP: #615548
+  * sparc: Fix use of uid16_t and gid16_t in asm/stat.h
+    - LP: #615548
+  * math-emu: correct test for downshifting fraction in _FP_FROM_INT()
+    - LP: #615548
+  * NFSv4: Fix an embarassing typo in encode_attrs()
+    - LP: #615548
+  * NFSv4: Ensure that /proc/self/mountinfo displays the minor version
+    number
+    - LP: #615548
+  * SUNRPC: Fix a re-entrancy bug in xs_tcp_read_calldir()
+    - LP: #615548
+  * ath5k: drop warning on jumbo frames
+    - LP: #615548
+  * ath9k: re-enable ps by default for new single chip families
+    - LP: #615548
+  * ath9k: Avoid corrupt frames being forwarded to mac80211.
+    - LP: #615548
+  * hostap: Protect against initialization interrupt
+    - LP: #615548
+  * TPM: ReadPubEK output struct fix
+    - LP: #615548
+  * fb: fix colliding defines for fb flags.
+    - LP: #615548
+  * iwlwifi: cancel scan watchdog in iwl_bg_abort_scan
+    - LP: #615548
+  * mac80211: do not wip out old supported rates
+    - LP: #615548
+  * mac80211: Handle mesh action frames in ieee80211_rx_h_action
+    - LP: #615548
+  * Btrfs: fix checks in BTRFS_IOC_CLONE_RANGE
+    - LP: #615548
+  * p54pci: add Symbol AP-300 minipci adapters pciid
+    - LP: #615548
+  * dynamic debug: move ddebug_remove_module() down into free_module()
+    - LP: #615548
+  * tpm_tis: fix subsequent suspend failures
+    - LP: #615548
+  * ipvs: Add missing locking during connection table hashing and unhashing
+    - LP: #615548
+  * netfilter: ip6t_REJECT: fix a dst leak in ipv6 REJECT
+    - LP: #615548
+  * SCSI: aacraid: Eliminate use after free
+    - LP: #615548
+  * amd64-agp: Probe unknown AGP devices the right way
+    - LP: #615548
+  * perf: Resurrect flat callchains
+    - LP: #615548
+  * x86: Fix vsyscall on gcc 4.5 with -Os
+    - LP: #615548
+  * x86, Calgary: Increase max PHB number
+    - LP: #615548
+  * x86, Calgary: Limit the max PHB number to 256
+    - LP: #615548
+  * sched: Prevent compiler from optimising the sched_avg_update() loop
+    - LP: #615548
+  * sched: Fix over-scheduling bug
+    - LP: #615548
+  * genirq: Deal with desc->set_type() changing desc->chip
+    - LP: #615548
+  * serial: cpm_uart: implement the cpm_uart_early_write() function for
+    console poll
+    - LP: #615548
+  * cmd640: fix kernel oops in test_irq() method
+    - LP: #615548
+  * ide: Fix IDE taskfile with cfq scheduler
+    - LP: #615548
+  * net/core: neighbour update Oops
+    - LP: #615548
+  * tcp: fix crash in tcp_xmit_retransmit_queue
+    - LP: #615548
+  * rtc: fix ds1388 time corruption
+    - LP: #615548
+  * ethtool: Fix potential kernel buffer overflow in ETHTOOL_GRXCLSRLALL
+    - LP: #615548
+  * sdhci-s3c: add missing remove function
+    - LP: #615548
+  * ASoC: Remove duplicate AUX definition from WM8776
+    - LP: #615548
+  * x86: Fix x2apic preenabled system with kexec
+    - LP: #615548
+  * IPoIB: Fix world-writable child interface control sysfs attributes
+    - LP: #615548
+  * Input: i8042 - add Gigabyte Spring Peak to dmi_noloop_table
+    - LP: #580664, #615548
+  * Input: twl40300-keypad - fix handling of "all ground" rows
+    - LP: #615548
+  * ARM: 6201/1: RealView: Do not use outer_sync() on ARM11MPCore boards
+    with L220
+    - LP: #615548
+  * ARM: 6226/1: fix kprobe bug in ldr instruction emulation
+    - LP: #615548
+  * x86: Do not try to disable hpet if it hasn't been initialized before
+    - LP: #615548
+  * staging: rtl8192su: add USB VID/PID for HWNUm-300
+    - LP: #615548
+  * Staging: rtl8192su: add USB ID for 0bda:8171
+    - LP: #615548
+  * USB: obey the sysfs power/wakeup setting
+    - LP: #615548
+  * USB: g_serial: don't set low_latency flag
+    - LP: #615548
+  * USB: g_serial: fix tty cleanup on unload
+    - LP: #615548
+  * USB: option: add support for 1da5:4518
+    - LP: #615548
+  * USB: Add PID for Sierra 250U to drivers/usb/serial/sierra.c
+    - LP: #599569, #615548
+  * USB: ftdi_sio: support for Signalyzer tools based on FTDI chips
+    - LP: #615548
+  * USB: option: Add support for AMOI Skypephone S2
+    - LP: #615548
+  * USB: adds Artisman USB dongle to list of quirky devices
+    - LP: #615548
+  * USB: sisusbvga: Fix for USB 3.0
+    - LP: #615548
+  * USB: add quirk for Broadcom BT dongle
+    - LP: #615548
+  * USB: FTDI: Add support for the RT System VX-7 radio programming cable
+    - LP: #615548
+  * ethtool: Fix potential user buffer overflow for ETHTOOL_{G, S}RXFH
+    - LP: #615548
+  * ext4: Fix potential quota deadlock
+    - LP: #615548
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #615548
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #615548
+  * ext4: Eliminate potential double free on error path
+    - LP: #615548
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #615548
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #615548
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #615548
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #615548
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #615548
+  * ext4: Handle -EDQUOT error on write
+    - LP: #615548
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #615548
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #615548
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #615548
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #615548
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #615548
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #615548
+  * ext4: fix error handling in migrate
+    - LP: #615548
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #615548
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #615548
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #615548
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #615548
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #615548
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #615548
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #615548
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #615548
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #615548
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #615548
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #615548
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #615548
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #615548
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #615548
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #615548
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #615548
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #615548
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #615548
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #615548
+  * ext4: stop issuing discards if not supported by device
+    - LP: #615548
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #615548
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #615548
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #615548
+  * ext4: init statistics after journal recovery
+    - LP: #615548
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #615548
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #615548
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #615548
+  * ext4: Show journal_checksum option
+    - LP: #615548
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #615548
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #615548
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #615548
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #615548
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #615548
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #615548
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #615548
+  * KVM: MMU: Remove user access when allowing kernel access to gpte.w=0
+    page
+    - LP: #615548
+  * KVM: SVM: Handle MCEs early in the vmexit process
+    - LP: #615548
+  * KVM: SVM: Implement workaround for Erratum 383
+    - LP: #615548
+  * KVM: MMU: invalidate and flush on spte small->large page size change
+    - LP: #615548
+  * futex: futex_find_get_task remove credentails check
+    - LP: #615548
+  * GFS2: Fix up system xattrs
+    - LP: #615548
+  * PM / x86: Save/restore MISC_ENABLE register
+    - LP: #615548
+  * ACPI: skip checking BM_STS if the BIOS doesn't ask for it
+    - LP: #615548
+  * ACPI: Unconditionally set SCI_EN on resume
+    - LP: #615548
+  * libertas/sdio: 8686: set ECSI bit for 1-bit transfers
+    - LP: #615548
+  * dm9000: fix "BUG: spinlock recursion"
+    - LP: #615548
+  * firmware_class: fix memory leak - free allocated pages
+    - LP: #615548
+  * revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second
+    call site)"
+    - LP: #615548
+  * ALSA: Echoaudio, fix Guru Meditation #00000005.48454C50
+    - LP: #615548
+  * V4L/DVB: dvb-core: Fix ULE decapsulation bug
+    - LP: #615548
+  * V4L/DVB: FusionHDTV: Use quick reads for I2C IR device probing
+    - LP: #615548
+  * forcedeth: fix tx limit2 flag check
+    - LP: #615548
+  * staging: rtl8192su: add Support for Belkin F5D8053 v6
+    - LP: #615548
+  * MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1
+    - LP: #615548
+  * V4L/DVB: budget: Select correct frontends
+    - LP: #615548
+  * cxgb3: fix linkup issue
+    - LP: #615548
+  * mac80211: fix supported rates IE if AP doesn't give us it's rates
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for unbranded Arkmicro 18ec:3290 webcams
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for Packard Bell EasyNote MX52
+    integrated webcam
+    - LP: #615548
+  * V4L/DVB: uvcvideo: Add support for V4L2_PIX_FMT_Y16
+    - LP: #615548
+  * iwlagn: verify flow id in compressed BA packet
+    - LP: #615548
+  * kbuild: Fix modpost segfault
+    - LP: #615548
+  * eeepc-laptop: check wireless hotplug events
+    - LP: #615548
+  * Fix spinaphore down_spin()
+    - LP: #615548
+  * ath5k: initialize ah->ah_current_channel
+    - LP: #615548
+  * Input: RX51 keymap - fix recent compile breakage
+    - LP: #615548
+  * V4L/DVB (13830): uvcvideo: add another YUYV format GUID for iSight
+    cameras
+    - LP: #615548
+  * Linux 2.6.32.17
+    - LP: #615548
+  * drm/i915: fix hibernation since i915 self-reclaim fixes
+    - LP: #615548
+  * drm/i915: add 'reclaimable' to i915 self-reclaimable page allocations
+    - LP: #615548
+  * i915: fix lock imbalance on error path...
+    - LP: #615548
+  * drm/i915: Define MI_ARB_STATE bits
+    - LP: #615548
+  * drm/i915: enable low power render writes on GEN3 hardware.
+    - LP: #615548
+  * drm/i915: Make G4X-style PLL search more permissive
+    - LP: #615548
+  * drm/radeon/r200: handle more hw tex coord types
+    - LP: #615548
+  * drm/radeon/r100/r200: fix calculation of compressed cube maps
+    - LP: #615548
+  * drm/radeon/kms: CS checker texture fixes for r1xx/r2xx/r3xx
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc handling
+    - LP: #615548
+  * drm/radeon/kms: fix shared ddc harder
+    - LP: #615548
+  * drm/radeon/kms: add quirk for ASUS HD 3600 board
+    - LP: #615548
+  * drm/radeon/kms: fix possible mis-detection of sideport on rs690/rs740
+    - LP: #615548
+  * drm/radeon/kms: fix legacy LVDS dpms sequence
+    - LP: #615548
+  * drm/radeon/kms: fix legacy tv-out pal mode
+    - LP: #615548
+  * Linux 2.6.32.17+drm33.7
+    - LP: #615548
+  * (pre-stable) writeback: remove the always false
+    bdi_cap_writeback_dirty() test
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove unused nonblocking and congestion checks
+    - LP: #543617, #585092
+  * (pre-stable) vfs: improve writeback_inodes_wb()
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing kernel-doc notation
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback completion notifications
+    - LP: #543617, #585092
+  * (pre-stable) writeback: queue work on stack in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: enforce s_umount locking in writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix writeback_inodes_wb from
+    writeback_inodes_sb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify wakeup_flusher_threads
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify and split bdi_start_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: add missing requeue_io in writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: fix pin_sb_for_writeback
+    - LP: #543617, #585092
+  * (pre-stable) writeback: remove writeback_inodes_wbc
+    - LP: #543617, #585092
+  * (pre-stable) writeback: split writeback_inodes_wb
+    - LP: #543617, #585092
+  * (pre-stable) writeback: simplify the write back thread queue
+    - LP: #543617, #585092
+  * (pre-stable) Fix compiling NFS when backporting writeback
+    - LP: #543617, #585092
+  * sched: cgroup: Implement different treatment for idle shares
+    - LP: #620755
+  * mm: fix ia64 crash when gcore reads gate area
+    - LP: #620755
+  * acl trouble after upgrading ubuntu
+    - LP: #620755
+  * comedi: Uncripple 8255-based DIO subdevices
+    - LP: #620755
+  * NFS: kswapd must not block in nfs_release_page
+    - LP: #620755
+  * PARISC: led.c - fix potential stack overflow in led_proc_write()
+    - LP: #620755
+  * arm/imx/gpio: add spinlock protection
+    - LP: #620755
+  * parisc: pass through '\t' to early (iodc) console
+    - LP: #620755
+  * amd64_edac: Fix DCT base address selector
+    - LP: #620755
+  * amd64_edac: Correct scrub rate setting
+    - LP: #620755
+  * e1000e: don't inadvertently re-set INTX_DISABLE
+    - LP: #620755
+  * e1000e: 82577/82578 PHY register access issues
+    - LP: #620755
+  * 9p: strlen() doesn't count the terminator
+    - LP: #620755
+  * ath9k: enable serialize_regmode for non-PCIE AR9160
+    - LP: #620755
+  * ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation
+    - LP: #620755
+  * ath9k: fix TSF after reset on AR913x
+    - LP: #620755
+  * ath9k: fix yet another buffer leak in the tx aggregation code
+    - LP: #620755
+  * iwlwifi: fix scan abort
+    - LP: #620755
+  * cfg80211: ignore spurious deauth
+    - LP: #620755
+  * cfg80211: don't get expired BSSes
+    - LP: #620755
+  * xfs: prevent swapext from operating on write-only files
+    - LP: #620755
+  * SCSI: enclosure: fix error path - actually return ERR_PTR() on error
+    - LP: #620755
+  * GFS2: rename causes kernel Oops
+    - LP: #620755
+  * slow-work: use get_ref wrapper instead of directly calling get_ref
+    - LP: #620755
+  * CIFS: Remove __exit mark from cifs_exit_dns_resolver()
+    - LP: #620755
+  * CIFS: Fix compile error with __init in cifs_init_dns_resolver()
+    definition
+    - LP: #620755
+  * xen: drop xen_sched_clock in favour of using plain wallclock time
+    - LP: #620755
+  * ssb: do not read SPROM if it does not exist
+    - LP: #620755
+  * ssb: Look for SPROM at different offset on higher rev CC
+    - LP: #620755
+  * ssb: fix NULL ptr deref when pcihost_wrapper is used
+    - LP: #620755
+  * ssb: Handle alternate SSPROM location
+    - LP: #620755
+  * Linux 2.6.32.18
+    - LP: #620755
+  * ata_piix: fix locking around SIDPR access
+    - LP: #622877
+  * powerpc: fix build with make 3.82
+    - LP: #622877
+  * nvram: Fix write beyond end condition; prove to gcc copy is safe
+    - LP: #622877
+  * x86: Add memory modify constraints to xchg() and cmpxchg()
+    - LP: #622877
+  * x86, vmware: Preset lpj values when on VMware.
+    - LP: #622877
+  * Staging: line6: needs to select SND_PCM
+    - LP: #622877
+  * Staging: panel: Prevent double-calling of parport_release - fix oops.
+    - LP: #622877
+  * PCI: Do not run NVidia quirks related to MSI with MSI disabled
+    - LP: #622877
+  * PCI: disable MSI on VIA K8M800
+    - LP: #622877
+  * solos-pci: Fix race condition in tasklet RX handling
+    - LP: #622877
+  * splice: fix misuse of SPLICE_F_NONBLOCK
+    - LP: #622877
+  * drivers/video/w100fb.c: ignore void return value / fix build failure
+    - LP: #622877
+  * ide-cd: Do not access completed requests in the irq handler
+    - LP: #622877
+  * md/raid10: fix deadlock with unaligned read during resync
+    - LP: #622877
+  * blkdev: cgroup whitelist permission fix
+    - LP: #622877
+  * eCryptfs: Handle ioctl calls with unlocked and compat functions
+    - LP: #622877
+  * ecryptfs: release reference to lower mount if interpose fails
+    - LP: #622877
+  * fs/ecryptfs/file.c: introduce missing free
+    - LP: #622877
+  * bio, fs: update RWA_MASK, READA and SWRITE to match the corresponding
+    BIO_RW_* bits
+    - LP: #622877
+  * signalfd: fill in ssi_int for posix timers and message queues
+    - LP: #622877
+  * smsc911x: Add spinlocks around registers access
+    - LP: #622877
+  * ARM: 6299/1: errata: TLBIASIDIS and TLBIMVAIS operations can broadcast
+    a faulty ASID
+    - LP: #622877
+  * ARM: 6280/1: imx: Fix build failure when including <mach/gpio.h>
+    without <linux/spinlock.h>
+    - LP: #622877
+  * USB: resizing usbmon binary interface buffer causes protection faults
+    - LP: #622877
+  * USB delay init quirk for logitech Harmony 700-series devices
+    - LP: #622877
+  * USB: serial: enabling support for Segway RMP in ftdi_sio
+    - LP: #622877
+  * USB: option: Huawei ETS 1220 support added
+    - LP: #622877
+  * USB: option: add huawei k3765 k4505 devices to work properly
+    - LP: #622877
+  * USB: ftdi_sio: device id for Navitator
+    - LP: #622877
+  * USB: cp210x: Add four new device IDs
+    - LP: #622877
+  * USB: usbtest: avoid to free coherent buffer in atomic context
+    - LP: #622877
+  * USB: fix thread-unsafe anchor utiliy routines
+    - LP: #622877
+  * drm/edid: Fix the HDTV hack sync adjustment
+    - LP: #622877
+  * Bluetooth: Added support for controller shipped with iMac i5
+    - LP: #622877
+  * jfs: don't allow os2 xattr namespace overlap with others
+    - LP: #622877
+  * arp_notify: allow drivers to explicitly request a notification event.
+    - LP: #622877
+  * xen: netfront: explicitly generate arp_notify event after migration.
+    - LP: #622877
+  * net: Fix NETDEV_NOTIFY_PEERS to not conflict with
+    NETDEV_BONDING_DESLAVE.
+    - LP: #622877
+  * irq: Add new IRQ flag IRQF_NO_SUSPEND
+    - LP: #622877
+  * xen: Do not suspend IPI IRQs.
+    - LP: #622877
+  * drm/i915: Use RSEN instead of HTPLG for tfp410 monitor detection.
+    - LP: #622877
+  * Btrfs: Avoid superfluous tree-log writeout
+    - LP: #622877
+  * Btrfs: Add btrfs_duplicate_item
+    - LP: #622877
+  * Btrfs: Rewrite btrfs_drop_extents
+    - LP: #622877
+  * Btrfs: Fix disk_i_size update corner case
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup while replaying log
+    - LP: #622877
+  * Btrfs: Avoid orphan inodes cleanup during committing transaction
+    - LP: #622877
+  * Btrfs: Make fallocate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Make truncate(2) more ENOSPC friendly
+    - LP: #622877
+  * Btrfs: Pass transaction handle to security and ACL initialization
+    functions
+    - LP: #622877
+  * Btrfs: Add delayed iput
+    - LP: #622877
+  * Btrfs: Fix btrfs_drop_extent_cache for skip pinned case
+    - LP: #622877
+  * Btrfs: Fix per root used space accounting
+    - LP: #622877
+  * Btrfs: don't add extent 0 to the free space cache v2
+    - LP: #622877
+  * Btrfs: fail mount on bad mount options
+    - LP: #622877
+  * Btrfs: deny sys_link across subvolumes.
+    - LP: #622877
+  * Btrfs: Show discard option in /proc/mounts
+    - LP: #622877
+  * Btrfs: make metadata chunks smaller
+    - LP: #622877
+  * Btrfs: make sure fallocate properly starts a transaction
+    - LP: #622877
+  * btrfs: fix missing last-entry in readdir(3)
+    - LP: #622877
+  * Btrfs: align offsets for btrfs_ordered_update_i_size
+    - LP: #622877
+  * Btrfs, fix memory leaks in error paths
+    - LP: #622877
+  * Btrfs: Fix race in btrfs_mark_extent_written
+    - LP: #622877
+  * Btrfs: fix regression in orphan cleanup
+    - LP: #622877
+  * Btrfs: deal with NULL acl sent to btrfs_set_acl
+    - LP: #622877
+  * Btrfs: fix possible panic on unmount
+    - LP: #622877
+  * Btrfs: Use correct values when updating inode i_size on fallocate
+    - LP: #622877
+  * Btrfs: fix a memory leak in btrfs_init_acl
+    - LP: #622877
+  * Btrfs: run orphan cleanup on default fs root
+    - LP: #622877
+  * Btrfs: do not mark the chunk as readonly if in degraded mode
+    - LP: #622877
+  * Btrfs: check return value of open_bdev_exclusive properly
+    - LP: #622877
+  * Btrfs: check total number of devices when removing missing
+    - LP: #622877
+  * Btrfs: fix race between allocate and release extent buffer.
+    - LP: #622877
+  * Btrfs: make error return negative in btrfs_sync_file()
+    - LP: #622877
+  * Btrfs: remove BUG_ON() due to mounting bad filesystem
+    - LP: #622877
+  * Btrfs: Fix oopsen when dropping empty tree.
+    - LP: #622877
+  * Btrfs: do not try and lookup the file extent when finishing ordered io
+    - LP: #622877
+  * Btrfs: apply updated fallocate i_size fix
+    - LP: #622877
+  * Btrfs: btrfs_mark_extent_written uses the wrong slot
+    - LP: #622877
+  * Btrfs: kfree correct pointer during mount option parsing
+    - LP: #622877
+  * nohz: Introduce arch_needs_cpu
+    - LP: #622877
+  * nohz: Reuse ktime in sub-functions of tick_check_idle.
+    - LP: #622877
+  * timekeeping: Fix clock_gettime vsyscall time warp
+    - LP: #622877
+  * sched: Fix granularity of task_u/stime()
+    - LP: #622877
+  * sched, cputime: Introduce thread_group_times()
+    - LP: #622877
+  * mutex: Don't spin when the owner CPU is offline or other weird cases
+    - LP: #622877
+  * fix SBA IOMMU to handle allocation failure properly
+    - LP: #622877
+  * crypto: testmgr - Fix complain about lack test for internal used
+    algorithm
+    - LP: #622877
+  * memory hotplug: fix a bug on /dev/mem for 64-bit kernels
+    - LP: #622877
+  * x86: Fix out of order of gsi
+    - LP: #622877
+  * HWPOISON: remove the anonymous entry
+    - LP: #622877
+  * HWPOISON: abort on failed unmap
+    - LP: #622877
+  * powerpc/eeh: Fix a bug when pci structure is null
+    - LP: #622877
+  * ACPI: Fix regression where _PPC is not read at boot even when
+    ignore_ppc=0
+    - LP: #622877
+  * ext4: Make sure the MOVE_EXT ioctl can't overwrite append-only files
+    - LP: #622877
+  * ext4: Fix optional-arg mount options
+    - LP: #622877
+  * reiserfs: properly honor read-only devices
+    - LP: #622877
+  * reiserfs: fix oops while creating privroot with selinux enabled
+    - LP: #622877
+  * dlm: always use GFP_NOFS
+    - LP: #622877
+  * dlm: fix ordering of bast and cast
+    - LP: #622877
+  * dlm: send reply before bast
+    - LP: #622877
+  * ocfs2: Find proper end cpos for a leaf refcount block.
+    - LP: #622877
+  * ocfs2: Set MS_POSIXACL on remount
+    - LP: #622877
+  * Skip check for mandatory locks when unlocking
+    - LP: #622877
+  * loop: Update mtime when writing using aops
+    - LP: #622877
+  * aic79xx: check for non-NULL scb in ahd_handle_nonpkt_busfree
+    - LP: #622877
+  * ibmvfc: Fix command completion handling
+    - LP: #622877
+  * ibmvfc: Reduce error recovery timeout
+    - LP: #622877
+  * md/raid1: delay reads that could overtake behind-writes.
+    - LP: #622877
+  * mm: fix corruption of hibernation caused by reusing swap during image
+    saving
+    - LP: #622877
+  * Linux 2.6.32.19
+    - LP: #622877
+  * Linux 2.6.32.20
+    - LP: #622882
+  * memstick: fix hangs on unexpected device removal in mspro_blk
+    - LP: #625392
+  * ASoC: Fix inverted mute controls for WM8580
+    - LP: #625392
+  * ASoC: Remove DSP mode support for WM8776
+    - LP: #625392
+  * ALSA: riptide - Fix detection / load of firmware files
+    - LP: #625392
+  * ALSA: emu10k1 - delay the PCM interrupts (add pcm_irq_delay parameter)
+    - LP: #625392
+  * ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA
+    codec
+    - LP: #625392
+  * ocfs2: do not overwrite error codes in ocfs2_init_acl
+    - LP: #625392
+  * ocfs2/dlm: fix a dead lock
+    - LP: #625392
+  * ocfs2 fix o2dlm dlm run purgelist (rev 3)
+    - LP: #625392
+  * ocfs2: Count more refcount records in file system fragmentation.
+    - LP: #625392
+  * ocfs2/dlm: avoid incorrect bit set in refmap on recovery master
+    - LP: #625392
+  * ocfs2/dlm: remove potential deadlock -V3
+    - LP: #625392
+  * x86, hotplug: Serialize CPU hotplug to avoid bringup concurrency issues
+    - LP: #625392
+  * x86, apic: Fix apic=debug boot crash
+    - LP: #625392
+  * Fix the nested PR lock calling issue in ACL
+    - LP: #625392
+  * hwmon: (pc87360) Fix device resource declaration
+    - LP: #625392
+  * ARM: Tighten check for allowable CPSR values
+    - LP: #625392
+  * nfs: Add "lookupcache" to displayed mount options
+    - LP: #625392
+  * ath5k: disable ASPM L0s for all cards
+    - LP: #625392
+  * pxa3xx: fix ns2cycle equation
+    - LP: #625392
+  * dm mpath: fix NULL pointer dereference when path parameters missing
+    - LP: #625392
+  * dm ioctl: release _hash_lock between devices in remove_all
+    - LP: #625392
+  * mm: make the vma list be doubly linked
+    - LP: #625392
+  * mm: make the mlock() stack guard page checks stricter
+    - LP: #625392
+  * mm: make stack guard page logic use vm_prev pointer
+    - LP: #625392
+  * slab: fix object alignment
+    - LP: #625392
+  * sunxvr500: Ignore secondary output PCI devices.
+    - LP: #625392
+  * sparc64: Add missing ID to parport probing code.
+    - LP: #625392
+  * sparc64: Fix rwsem constant bug leading to hangs.
+    - LP: #625392
+  * sparc64: Fix atomic64_t routine return values.
+    - LP: #625392
+  * net: Fix a memmove bug in dev_gro_receive()
+    - LP: #625392
+  * isdn: fix information leak
+    - LP: #625392
+  * act_nat: the checksum of ICMP doesn't have pseudo header
+    - LP: #625392
+  * vmscan: raise the bar to PAGEOUT_IO_SYNC stalls
+    - LP: #625392
+  * pcmcia: avoid buffer overflow in pcmcia_setup_isa_irq
+    - LP: #625392
+  * ext4: consolidate in_range() definitions
+    - LP: #625392
+  * Oprofile: Change CPUIDS from decimal to hex, and add some comments
+    - LP: #625392
+  * oprofile: add support for Intel processor model 30
+    - LP: #625392
+  * fixes for using make 3.82
+    - LP: #625392
+  * ALSA: intel8x0: Mute External Amplifier by default for ThinkPad X31
+    - LP: #619439, #625392
+  * netlink: fix compat recvmsg
+    - LP: #625392
+  * powerpc: Fix typo in uImage target
+    - LP: #625392
+  * USB: option: add Celot CT-650
+    - LP: #625392
+  * USB: add device IDs for igotu to navman
+    - LP: #625392
+  * USB: pl2303: New vendor and product id
+    - LP: #625392
+  * USB: CP210x Fix Break On/Off
+    - LP: #625392
+  * USB: ftdi_sio: fix endianess of max packet size
+    - LP: #625392
+  * USB: io_ti: check firmware version before updating
+    - LP: #625392
+  * USB: xhci: Remove buggy assignment in next_trb()
+    - LP: #625392
+  * USB: ftdi_sio: Add ID for Ionics PlugComputer
+    - LP: #625392
+  * USB: ftdi_sio: add product ID for Lenz LI-USB
+    - LP: #625392
+  * x86, apic: ack all pending irqs when crashed/on kexec
+    - LP: #625392
+  * Linux 2.6.32.21
+    - LP: #625392
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 31 Aug 2010 15:17:31 +0200
+
+linux (2.6.32-24.43) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * x86-64, compat: Test %rax for the syscall number, not %eax
+    - CVE-2010-3301
+  * x86-64, compat: Retruncate rax after ia32 syscall entry tracing
+    - CVE-2010-3301
+  * compat: Make compat_alloc_user_space() incorporate the access_ok()
+    - CVE-2010-3081
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 16 Sep 2010 10:27:21 +0200
+
+linux (2.6.32-24.42) lucid-proposed; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * (pre-stable) drm/i915: add PANEL_UNLOCK_REGS definition
+    - LP: #561802, #578673
+  * (pre-stable) drm/i915: make sure eDP panel is turned on
+    - LP: #578673
+  * (pre-stable) drm/i915: make sure we shut off the panel in eDP configs
+    - LP: #578673
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 19 Aug 2010 15:20:42 +0200
+
+linux (2.6.32-24.41) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * (pre-stable) ext4: fix freeze deadlock under IO
+    - LP: #595489
+  * drm: Initialize ioctl struct when no user data is present
+    - CVE-2010-2803
+  * can: add limit for nframes and clean up signed/unsigned variables
+    - CVE-2010-2959
+  * mm: keep a guard page below a grow-down stack segment
+    - CVE-2010-2240
+  * mm: fix missing page table unmap for stack guard page failure case
+    - CVE-2010-2240
+  * mm: fix page table unmap for stack guard page properly
+    - CVE-2010-2240
+  * mm: fix up some user-visible effects of the stack guard page
+    - CVE-2010-2240
+  * x86: don't send SIGBUS for kernel page faults
+    - CVE-2010-2240
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 18 Aug 2010 14:24:07 +0200
+
+linux (2.6.32-24.39) lucid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * sctp: Fix skb_over_panic resulting from multiple invalid parameter
+    errors (CVE-2010-1173) (v4)
+    - CVE-2010-1173
+  * sctp: fix append error cause to ERROR chunk correctly
+    - CVE-2010-1173
+  * GFS2: Fix writing to non-page aligned gfs2_quota structures
+    - CVE-2010-1436
+  * KEYS: find_keyring_by_name() can gain access to a freed keyring
+    - CVE-2010-1437
+  * GFS2: Fix permissions checking for setflags ioctl()
+    - CVE-2010-1641
+  * Btrfs: should add a permission check for setfacl
+    - CVE-2010-2071
+  * ecryptfs: Bugfix for error related to ecryptfs_hash_buckets
+    - CVE-2010-2492
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 21 Jul 2010 10:48:54 +0200
+
+linux (2.6.32-24.38) lucid-proposed; urgency=low
+
+  [ Keng-Yu Lin ]
+
+  * SAUCE: dell-laptop: fire SMI when toggling hardware killswitch
+    (revised)
+    - LP: #590607
+
+  [ Upstream Kernel Changes ]
+
+  * sfc: Wait at most 10ms for the MC to finish reading out MAC statistics
+    - LP: #590783
+  * sfc: Always close net device at the end of a disabling reset
+    - LP: #590783
+  * sfc: Change falcon_probe_board() to fail for unsupported boards
+    - LP: #590783
+  * ext4: Fix potential quota deadlock
+    - LP: #588069
+  * jbd: jbd-debug and jbd2-debug should be writable
+    - LP: #588069
+  * ext4: replace BUG() with return -EIO in ext4_ext_get_blocks
+    - LP: #588069
+  * ext4, jbd2: Add barriers for file systems with exernal journals
+    - LP: #588069
+  * ext4: Eliminate potential double free on error path
+    - LP: #588069
+  * ext4: return correct wbc.nr_to_write in ext4_da_writepages
+    - LP: #588069
+  * ext4: Ensure zeroout blocks have no dirty metadata
+    - LP: #588069
+  * ext4: Patch up how we claim metadata blocks for quota purposes
+    - LP: #588069
+  * ext4: Fix accounting of reserved metadata blocks
+    - LP: #588069
+  * ext4: Calculate metadata requirements more accurately
+    - LP: #588069
+  * ext4: Handle -EDQUOT error on write
+    - LP: #588069
+  * ext4: Fix quota accounting error with fallocate
+    - LP: #588069
+  * ext4: Drop EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE flag
+    - LP: #588069
+  * ext4: Use bitops to read/modify EXT4_I(inode)->i_state
+    - LP: #588069
+  * ext4: Fix BUG_ON at fs/buffer.c:652 in no journal mode
+    - LP: #588069
+  * ext4: Add flag to files with blocks intentionally past EOF
+    - LP: #588069
+  * ext4: Fix fencepost error in chosing choosing group vs file
+    preallocation.
+    - LP: #588069
+  * ext4: fix error handling in migrate
+    - LP: #588069
+  * ext4: explicitly remove inode from orphan list after failed direct io
+    - LP: #588069
+  * ext4: Handle non empty on-disk orphan link
+    - LP: #588069
+  * ext4: make "offset" consistent in ext4_check_dir_entry()
+    - LP: #588069
+  * ext4: Fix insertion point of extent in mext_insert_across_blocks()
+    - LP: #588069
+  * ext4: Fix the NULL reference in double_down_write_data_sem()
+    - LP: #588069
+  * ext4: Code cleanup for EXT4_IOC_MOVE_EXT ioctl
+    - LP: #588069
+  * ext4: Fix estimate of # of blocks needed to write indirect-mapped files
+    - LP: #588069
+  * ext4: Fixed inode allocator to correctly track a flex_bg's used_dirs
+    - LP: #588069
+  * ext4: Fix possible lost inode write in no journal mode
+    - LP: #588069
+  * ext4: Fix buffer head leaks after calls to ext4_get_inode_loc()
+    - LP: #588069
+  * ext4: Issue the discard operation *before* releasing the blocks to be
+    reused
+    - LP: #588069
+  * ext4: check missed return value in ext4_sync_file()
+    - LP: #588069
+  * ext4: fix memory leaks in error path handling of ext4_ext_zeroout()
+    - LP: #588069
+  * ext4: Remove unnecessary call to ext4_get_group_desc() in mballoc
+    - LP: #588069
+  * ext4: rename ext4_mb_release_desc() to ext4_mb_unload_buddy()
+    - LP: #588069
+  * ext4: allow defrag (EXT4_IOC_MOVE_EXT) in 32bit compat mode
+    - LP: #588069
+  * ext4: fix quota accounting in case of fallocate
+    - LP: #588069
+  * ext4: check s_log_groups_per_flex in online resize code
+    - LP: #588069
+  * ext4: don't return to userspace after freezing the fs with a mutex held
+    - LP: #588069
+  * ext4: stop issuing discards if not supported by device
+    - LP: #588069
+  * ext4: don't scan/accumulate more pages than mballoc will allocate
+    - LP: #588069
+  * ext4: Do not zero out uninitialized extents beyond i_size
+    - LP: #588069
+  * ext4: clean up inode bitmaps manipulation in ext4_free_inode
+    - LP: #588069
+  * ext4: init statistics after journal recovery
+    - LP: #588069
+  * ext4: Remove extraneous newlines in ext4_msg() calls
+    - LP: #588069
+  * ext4: Prevent creation of files larger than RLIMIT_FSIZE using
+    fallocate
+    - LP: #588069
+  * ext4: check for a good block group before loading buddy pages
+    - LP: #588069
+  * ext4: Show journal_checksum option
+    - LP: #588069
+  * ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
+    - LP: #588069
+  * ext4: Avoid crashing on NULL ptr dereference on a filesystem error
+    - LP: #588069
+  * ext4: Clear the EXT4_EOFBLOCKS_FL flag only when warranted
+    - LP: #588069
+  * ext4: restart ext4_ext_remove_space() after transaction restart
+    - LP: #588069
+  * ext4: Conditionally define compat ioctl numbers
+    - LP: #588069
+  * ext4: Fix compat EXT4_IOC_ADD_GROUP
+    - LP: #588069
+  * ext4: Make fsync sync new parent directories in no-journal mode
+    - LP: #588069
+  * (pre-stable) ahci,ata_generic: let ata_generic handle new MBP w/ MCP89
+    - LP: #576601
+  * (pre-stable) ata_generic: implement ATA_GEN_* flags and force enable
+    DMA on MBP 7,1
+    - LP: #576601
+
+ -- Steve Conklin <sconklin@canonical.com>  Fri, 2 Jul 2010 11:06:32 -0500
+
+linux (2.6.32-23.37) lucid-proposed; urgency=low
+
+  [ Alex Deucher ]
+
+  * SAUCE: drm/radeon/kms/atom: fix dual-link DVI on DCE3.2/4.0
+    - LP: #564559
+
+  [ Andy Whitcroft ]
+
+  * [Config] ports -- build in dm-mod to enable LVM boot
+    - LP: #560717
+  * tools -- fix perf version extraction for multi-part flavours
+    - LP: #555130
+  * SAUCE: ACPI: EC: Allow multibyte access to EC (v3)
+    - LP: #526354
+  * [Config] enforce -- ensure dm_mod is built-in for LVM
+    - LP: #560717
+  * update to ubuntu-debian:7e708d33054c373faf41da23b73e8b48c342d958
+    - LP: #570500, #576274
+
+  [ Chase Douglas ]
+
+  * Revert "(pre-stable): input: ALPS - Add signature for HP Pavilion dm3
+    laptops"
+    - LP: #550625
+  * Enable ftrace function profiler
+    - LP: #570389
+  * enforce CONFIG_TMPFS_POSIX_ACL=y
+    - LP: #575940
+
+  [ Leann Ogasawara ]
+
+  * Revert "staging/comdi -- disable"
+    - LP: #563436
+  * [Config] Enable multicast routing for sparc
+    - LP: #416266
+  * [Config] Add ahci.ko to virtual sub-flavour
+    - LP: #570542
+
+  [ Stefan Bader ]
+
+  * Revert "SAUCE: drm/i915: Disable FBC on 915GM and 945GM"
+    - LP: #588832
+
+  [ Tim Gardner ]
+
+  * ubuntu: rtl8192se -- update to version 0015.0127.2010
+    - LP: #567016
+  * [Config] Add atl1c to nic-modules udeb
+    - LP: #557130
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) iwlwifi: fix nfreed--"
+    - LP: #575853
+  * Revert "backlight: mbp_nvidia_bl - add five more MacBook variants"
+    - LP: #575853
+  * Revert "(pre-stable) pata_via: Add VIA VX900 support"
+    - LP: #575853
+  * Revert "(pre-stable) x86-32, resume: do a global tlb flush in S4
+    resume"
+    - LP: #575853
+  * Revert "x86: disable IOMMUs on kernel crash"
+    - LP: #575853
+  * Revert "sunrpc: fix peername failed on closed listener"
+    - LP: #575853
+  * Revert "sunrpc: move the close processing after do recvfrom method"
+    - LP: #575853
+  * Revert "(pre-stable) drm/edid: allow certain bogus edids to hit a fixup
+    path rather than fail"
+    - LP: #575853
+  * Revert "drm/radeon/kms: don't print error on -ERESTARTSYS."
+    - LP: #575853
+  * Revert "ath9k: fix lockdep warning when unloading module" on stable
+    kernels
+    - LP: #588832
+  * Staging: comedi: removed "depricated" from COMEDI_CB_BLOCK
+    - LP: #483343
+  * fat: fix buffer overflow in vfat_create_shortname()
+    - LP: #575853
+  * xfs: simplify inode teardown
+    - LP: #575853
+  * xfs: fix mmap_sem/iolock inversion in xfs_free_eofblocks
+    - LP: #575853
+  * xfs: I/O completion handlers must use NOFS allocations
+    - LP: #575853
+  * xfs: Wrapped journal record corruption on read at recovery
+    - LP: #575853
+  * xfs: Fix error return for fallocate() on XFS
+    - LP: #575853
+  * xfs: check for not fully initialized inodes in xfs_ireclaim
+    - LP: #575853
+  * xfs: fix timestamp handling in xfs_setattr
+    - LP: #575853
+  * xfs: Don't flush stale inodes
+    - LP: #575853
+  * xfs: Ensure we force all busy extents in range to disk
+    - LP: #575853
+  * xfs: reclaim inodes under a write lock
+    - LP: #575853
+  * xfs: Avoid inodes in reclaim when flushing from inode cache
+    - LP: #575853
+  * xfs: reclaim all inodes by background tree walks
+    - LP: #575853
+  * xfs: fix stale inode flush avoidance
+    - LP: #575853
+  * xfs: xfs_swap_extents needs to handle dynamic fork offsets
+    - LP: #575853
+  * xfs: quota limit statvfs available blocks
+    - LP: #575853
+  * xfs: don't hold onto reserved blocks on remount, ro
+    - LP: #575853
+  * xfs: remove invalid barrier optimization from xfs_fsync
+    - LP: #575853
+  * xfs: Non-blocking inode locking in IO completion
+    - LP: #575853
+  * xfs: fix locking for inode cache radix tree tag updates
+    - LP: #575853
+  * sh: Enable the mmu in start_secondary()
+    - LP: #575853
+  * sh: Fix FDPIC binary loader
+    - LP: #575853
+  * libiscsi: Fix recovery slowdown regression
+    - LP: #575853
+  * Freezer: Fix buggy resume test for tasks frozen with cgroup freezer
+    - LP: #575853
+  * iwlwifi: counting number of tfds can be free for 4965
+    - LP: #575853
+  * iwlwifi: fix nfreed--
+    - LP: #575853
+  * iwlwifi: range checking issue
+    - LP: #575853
+  * setup correct int pipe type in ar9170_usb_exec_cmd
+    - LP: #575853
+  * mac80211: move netdev queue enabling to correct spot
+    - LP: #575853
+  * mac80211: tear down all agg queues when restart/reconfig hw
+    - LP: #575853
+  * WATCHDOG: hpwdt - fix lower timeout limit
+    - LP: #575853
+  * WATCHDOG: iTCO_wdt: TCO Watchdog patch for additional Intel Cougar
+    Point DeviceIDs
+    - LP: #575853
+  * genirq: Force MSI irq handlers to run with interrupts disabled
+    - LP: #575853
+  * lis3: fix show rate for 8 bits chips
+    - LP: #575853
+  * pata_ali: Fix regression with old devices
+    - LP: #575853
+  * HID: fix oops in gyration_event()
+    - LP: #575853
+  * raw: fsync method is now required
+    - LP: #575853
+  * readahead: fix NULL filp dereference
+    - LP: #575853
+  * ALSA: mixart: range checking proc file
+    - LP: #575853
+  * ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981
+    - LP: #551606, #575853
+  * x86, amd: Get multi-node CPU info from NodeId MSR instead of PCI config
+    space
+    - LP: #575853
+  * resource: move kernel function inside __KERNEL__
+    - LP: #575853
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #575853
+  * pata_via: Add VIA VX900 support
+    - LP: #575853
+  * ext3: Don't update the superblock in ext3_statfs()
+    - LP: #575853
+  * ext3: journal all modifications in ext3_xattr_set_handle
+    - LP: #575853
+  * eeepc-laptop: disable cpu speed control on EeePC 701
+    - LP: #575853
+  * eeepc-laptop: dmi blacklist to disable pci hotplug code
+    - LP: #575853
+  * eeepc-laptop: add hotplug_disable parameter
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1201N
+    - LP: #575853
+  * eeepc-laptop: disable wireless hotplug for 1005PE
+    - LP: #575853
+  * libata: disable NCQ on Crucial C300 SSD
+    - LP: #575853
+  * cifs: Fix a kernel BUG with remote OS/2 server (try #3)
+    - LP: #575853
+  * CIFS: initialize nbytes at the beginning of CIFSSMBWrite()
+    - LP: #575853
+  * iwlwifi: need check for valid qos packet before free
+    - LP: #575853
+  * ARM: 6031/1: fix Thumb-2 decompressor
+    - LP: #575853
+  * x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #575853
+  * x86: hpet: Make WARN_ON understandable
+    - LP: #575853
+  * x86, hpet: Erratum workaround for read after write of HPET comparator
+    - LP: #575853
+  * x86: Fix double enable_IR_x2apic() call on SMP kernel on !SMP boards
+    - LP: #575853
+  * sched: sched_getaffinity(): Allow less than NR_CPUS length
+    - LP: #575853
+  * sched: Fix sched_getaffinity()
+    - LP: #575853
+  * NFSv4: Fall back to ordinary lookup if nfs4_atomic_open() returns
+    EISDIR
+    - LP: #575853
+  * NFSv4: fix delegated locking
+    - LP: #575853
+  * ALSA: hda - add a quirk for Clevo M570U laptop
+    - LP: #575853
+  * ALSA: usb - Fix Oops after usb-midi disconnection
+    - LP: #575853
+  * hwmon: (sht15) Fix sht15_calc_temp interpolation function
+    - LP: #575853
+  * hwmon: (sht15) Properly handle the case CONFIG_REGULATOR=n
+    - LP: #575853
+  * x86/amd-iommu: Use helper function to destroy domain
+    - LP: #575853
+  * x86/amd-iommu: enable iommu before attaching devices
+    - LP: #575853
+  * x86, lib: Add wbinvd smp helpers
+    - LP: #575853
+  * x86, cacheinfo: Fix disabling of L3 cache indices
+    - LP: #575853
+  * intel-agp: Switch to wbinvd_on_all_cpus
+    - LP: #575853
+  * x86, cacheinfo: Add cache index disable sysfs attrs only to L3 caches
+    - LP: #575853
+  * x86, cacheinfo: Calculate L3 indices
+    - LP: #575853
+  * x86, cacheinfo: Remove NUMA dependency, fix for AMD Fam10h rev D1
+    - LP: #575853
+  * x86, cacheinfo: Enable L3 CID only on AMD
+    - LP: #575853
+  * vgaarb: fix "target=default" passing
+    - LP: #575853
+  * x86-32: clean up rwsem inline asm statements
+    - LP: #575853
+  * x86: clean up rwsem type system
+    - LP: #575853
+  * x86-64, rwsem: 64-bit xadd rwsem implementation
+    - LP: #575853
+  * x86-64: support native xadd rwsem implementation
+    - LP: #575853
+  * x86: Fix breakage of UML from the changes in the rwsem system
+    - LP: #575853
+  * x86-64, rwsem: Avoid store forwarding hazard in __downgrade_write
+    - LP: #575853
+  * fix NFS4 handling of mountpoint stat
+    - LP: #575853
+  * dm mpath: fix stall when requeueing io
+    - LP: #575853
+  * quota: Fix possible dq_flags corruption
+    - LP: #575853
+  * Staging: comedi: fix usbdux timeout bug
+    - LP: #483343, #575853
+  * Staging: comedi: usbdux.c: fix locking up of the driver when the comedi
+    ringbuffer runs empty
+    - LP: #483343, #575853
+  * ocfs2: set i_mode on disk during acl operations
+    - LP: #575853
+  * ocfs2: Change bg_chain check for ocfs2_validate_gd_parent.
+    - LP: #575853
+  * 9p: Skip check for mandatory locks when unlocking
+    - LP: #575853
+  * fc class: fail fast bsg requests
+    - LP: #575853
+  * SCSI: add scsi target reset support to scsi ioctl
+    - LP: #575853
+  * PCIe AER: prevent AER injection if hardware masks error reporting
+    - LP: #575853
+  * vgaarb: Fix VGA arbiter to accept PCI domains other than 0
+    - LP: #575853
+  * SCSI: fc-transport: Use packed modifier for fc_bsg_request structure.
+    - LP: #575853
+  * pci: Update pci_set_vga_state() to call arch functions
+    - LP: #575853
+  * PCI: kill off pci_register_set_vga_state() symbol export.
+    - LP: #575853
+  * PCI: fix nested spinlock hang in aer_inject
+    - LP: #575853
+  * IPoIB: Fix TX queue lockup with mixed UD/CM traffic
+    - LP: #575853
+  * x86/PCI: irq and pci_ids patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda_intel: ALSA HD Audio patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ALSA: hda - enable snoop for Intel Cougar Point
+    - LP: #575853
+  * ata_piix: IDE Mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * ahci: AHCI and RAID mode SATA patch for Intel Cougar Point DeviceIDs
+    - LP: #575853
+  * i2c-i801: Add Intel Cougar Point device IDs
+    - LP: #575853
+  * b43: Remove reset after fatal DMA error
+    - LP: #575853
+  * b43: Allow PIO mode to be selected at module load
+    - LP: #575853
+  * b43: fall back gracefully to PIO mode after fatal DMA errors
+    - LP: #575853
+  * ALSA: hda - Add position_fix quirk for Biostar mobo
+    - LP: #575853
+  * agp/hp: fixup hp agp after ACPI changes
+    - LP: #575853
+  * b43: Optimize PIO scratchbuffer usage
+    - LP: #575853
+  * ecryptfs: fix use with tmpfs by removing d_drop from
+    ecryptfs_destroy_inode
+    - LP: #575853
+  * eCryptfs: Decrypt symlink target for stat size
+    - LP: #575853
+  * ecryptfs: fix error code for missing xattrs in lower fs
+    - LP: #575853
+  * sched: Fix a race between ttwu() and migrate_task()
+    - LP: #575853
+  * USB: cdc-acm: Update to new autopm API
+    - LP: #575853
+  * USB: cdc-acm: Fix stupid NULL pointer in resume()
+    - LP: #575853
+  * iwlwifi: clear all tx queues when firmware ready
+    - LP: #575853
+  * iwlwifi: fix scan race
+    - LP: #575853
+  * e1000e: stop cleaning when we reach tx_ring->next_to_use
+    - LP: #575853
+  * tcp: fix ICMP-RTO war
+    - LP: #575853
+  * perf_events, x86: Implement Intel Westmere/Nehalem-EX support
+    - LP: #575853
+  * Input: wacom - switch mode upon system resume
+    - LP: #575853
+  * md: deal with merge_bvec_fn in component devices better.
+    - LP: #575853
+  * nfsd4: don't try to map gid's in generic rpc code
+    - LP: #575853
+  * nfsd: ensure sockets are closed on error
+    - LP: #575853
+  * ALSA: hda: Set Front Mic to input vref 50% for Lenovo 3000 Y410
+    - LP: #479373, #575853
+  * mac80211: fix deferred hardware scan requests
+    - LP: #575853
+  * fs-writeback: Add helper function to start writeback if idle
+    - LP: #575853
+  * ext4: flush delalloc blocks when space is low
+    - LP: #575853
+  * ext4: fix async i/o writes beyond 4GB to a sparse file
+    - LP: #575853
+  * tpm: autoload tpm_tis based on system PnP IDs
+    - LP: #575853
+  * IB/iser: Rewrite SG handling for RDMA logic
+    - LP: #575853
+  * mptctl : Remove printk which floods unnecessary messages to
+    var/log/message
+    - LP: #575853
+  * mptspi: Fix for incorrect data underrun errata
+    - LP: #575853
+  * sched: Use proper type in sched_getaffinity()
+    - LP: #575853
+  * KVM: SVM: Fix memory leaks that happen when svm_create_vcpu() fails
+    - LP: #575853
+  * KVM: Don't spam kernel log when injecting exceptions due to bad cr
+    writes
+    - LP: #575853
+  * KVM: allow bit 10 to be cleared in MSR_IA32_MC4_CTL
+    - LP: #575853
+  * KVM: VMX: Save/restore rflags.vm correctly in real mode
+    - LP: #575853
+  * KVM: MMU: fix kvm_mmu_zap_page() and its calling path
+    - LP: #575853
+  * KVM: fix the handling of dirty bitmaps to avoid overflows
+    - LP: #575853
+  * KVM: Increase NR_IOBUS_DEVS limit to 200
+    - LP: #575853
+  * KVM: x86: Fix TSS size check for 16-bit tasks
+    - LP: #575853
+  * x86/gart: Disable GART explicitly before initialization
+    - LP: #575853
+  * r8169: clean up my printk uglyness
+    - LP: #562742, #575853
+  * Linux 2.6.32.12
+    - LP: #575853
+  * drm/edid: allow certain bogus edids to hit a fixup path rather than
+    fail
+    - LP: #575853
+  * drm/radeon: add new RS880 pci id
+    - LP: #575853
+  * drm: remove the EDID blob stored in the EDID property when it is
+    disconnected
+    - LP: #575853
+  * drm/radeon/kms: never treat rs4xx as AGP
+    - LP: #575853
+  * drm/radeon/kms: Fix NULL pointer dereference if memory allocation
+    failed in a simple way
+    - LP: #575853
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #575853
+  * drm/radeon/kms: fix pal tv-out support on legacy IGP chips
+    - LP: #575853
+  * drm: Return ENODEV if the inode mapping changes
+    - LP: #575853
+  * drm/edid/quirks: Envision EN2028
+    - LP: #575853
+  * drm/radeon: R300 AD only has one quad pipe.
+    - LP: #575853
+  * drm/radeon/kms: fix washed out image on legacy tv dac
+    - LP: #575853
+  * drm/radeon/kms/combios: verify dac_adj values are valid
+    - LP: #575853
+  * drm/i915: Add no_lvds entry for the Clientron U800
+    - LP: #544671, #575853
+  * drm/radeon/kms: more atom parser fixes (v2)
+    - LP: #575853
+  * drm/radeon/kms: disable the tv encoder when tv/cv is not in use
+    - LP: #575853
+  * drm/radeon/kms: fix tv dac conflict resolver
+    - LP: #575853
+  * drm/radeon/kms: fix rs600 tlb flush
+    - LP: #575853
+  * drm/radeon/kms: add FireMV 2400 PCI ID.
+    - LP: #575853
+  * Linux 2.6.32.12+drm33.3
+    - LP: #575853
+  * USB: EHCI: defer reclamation of siTDs
+    - LP: #583414
+  * p54usb: Add usbid for Corega CG-WLUSB2GT.
+    - LP: #583414
+  * md/raid5: allow for more than 2^31 chunks.
+    - LP: #583414
+  * md/raid5: fix previous patch.
+    - LP: #583414
+  * libata: fix locking around blk_abort_request()
+    - LP: #583414
+  * libata: ensure NCQ error result taskfile is fully initialized before
+    returning it via qc->result_tf.
+    - LP: #583414
+  * w1: w1 temp: fix negative termperature calculation
+    - LP: #583414
+  * memcg: fix prepare migration
+    - LP: #583414
+  * mac80211: remove bogus TX agg state assignment
+    - LP: #583414
+  * flex_array: fix the panic when calling flex_array_alloc() without
+    __GFP_ZERO
+    - LP: #583414
+  * core, x86: make LIST_POISON less deadly
+    - LP: #583414
+  * hugetlb: fix infinite loop in get_futex_key() when backed by huge pages
+    - LP: #583414
+  * reiserfs: fix corruption during shrinking of xattrs
+    - LP: #583414
+  * nfsd4: bug in read_buf
+    - LP: #583414
+  * keys: the request_key() syscall should link an existing key to the dest
+    keyring
+    - LP: #583414
+  * staging: usbip: Fix deadlock
+    - LP: #583414
+  * USB: fix remote wakeup settings during system sleep
+    - LP: #583414
+  * USB: Add id for HP ev2210 a.k.a Sierra MC5725 miniPCI-e Cell Modem.
+    - LP: #511066, #583414
+  * USB: fix testing the wrong variable in fs_create_by_name()
+    - LP: #583414
+  * USB: don't choose configs with no interfaces
+    - LP: #583414
+  * USB: OHCI: don't look at the root hub to get the number of ports
+    - LP: #583414
+  * USB: xhci: properly set the "Mult" field of the endpoint context.
+    - LP: #583414
+  * USB: xhci: properly set endpoint context fields for periodic eps.
+    - LP: #583414
+  * procfs: fix tid fdinfo
+    - LP: #583414
+  * ocfs2: Update VFS inode's id info after reflink.
+    - LP: #583414
+  * ocfs2: potential ERR_PTR dereference on error paths
+    - LP: #583414
+  * ocfs2: Compute metaecc for superblocks during online resize.
+    - LP: #583414
+  * ocfs2_dlmfs: Fix math error when reading LVB.
+    - LP: #583414
+  * powernow-k8: Fix frequency reporting
+    - LP: #572348, #583414
+  * nfs d_revalidate() is too trigger-happy with d_drop()
+    - LP: #583414
+  * NFS: rsize and wsize settings ignored on v4 mounts
+    - LP: #583414
+  * Staging: hv: Fix a bug affecting IPv6
+    - LP: #583414
+  * Staging: hv: Fix up memory leak on HvCleanup
+    - LP: #583414
+  * Staging: hv: name network device ethX rather than sethX
+    - LP: #583414
+  * i2c: Fix probing of FSC hardware monitoring chips
+    - LP: #583414
+  * perf: Fix resource leak in failure path of perf_event_open()
+    - LP: #583414
+  * raid6: fix recovery performance regression
+    - LP: #583414
+  * serial: 8250_pnp - add Fujitsu Wacom device
+    - LP: #583414
+  * block: ensure jiffies wrap is handled correctly in
+    blk_rq_timed_out_timer
+    - LP: #583414
+  * dm9601: fix phy/eeprom write routine
+    - LP: #583414
+  * p54pci: fix bugs in p54p_check_tx_ring
+    - LP: #583414
+  * edac, mce: Fix wrong mask and macro usage
+    - LP: #583414
+  * x86-64: Clear a 64-bit FS/GS base on fork if selector is nonzero
+    - LP: #583414
+  * x86: Disable large pages on CPUs with Atom erratum AAE44
+    - LP: #583414
+  * x86, k8 nb: Fix boot crash: enable k8_northbridges unconditionally on
+    AMD systems
+    - LP: #583414
+  * x86, AMD: Fix stale cpuid4_info shared_map data in shared_cpu_map
+    cpumasks
+    - LP: #583414
+  * ALSA: hda: Use LPIB quirk for DG965OT board version AAD63733-203
+    - LP: #459083, #583414
+  * ALSA: hda - Add PCI quirk for HP dv6-1110ax.
+    - LP: #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio XPS 1645
+    - LP: #553002, #583414
+  * ALSA: hda: Use STAC_DELL_M6_BOTH quirk for Dell Studio 1558
+    - LP: #568600, #583414
+  * ALSA: hda: Use ALC880_F1734 quirk for Fujitsu Siemens AMILO Xi 1526
+    - LP: #567494, #583414
+  * ALSA: snd-meastro3: Add amp_gpio quirk for Compaq EVO N600C
+    - LP: #583414
+  * ALSA: snd-meastro3: Ignore spurious HV interrupts during suspend /
+    resume
+    - LP: #583414
+  * ALSA: hda: Fix max PCM level to 0 dB for Fujitsu-Siemens laptops using
+    CX20549 (Venice)
+    - LP: #583414
+  * ALSA: hda: Fix 0 dB for Packard Bell models using Conexant CX20549
+    (Venice)
+    - LP: #541802, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite Pro T130-15F
+    - LP: #573284, #583414
+  * ALSA: hda: Use olpc-xo-1_5 quirk for Toshiba Satellite
+    P500-PSPGSC-01800T
+    - LP: #549267, #583414
+  * libata: Fix accesses at LBA28 boundary (old bug, but nasty) (v2)
+    - LP: #583414
+  * ext4: correctly calculate number of blocks for fiemap
+    - LP: #474597, #583414
+  * initramfs: handle unrecognised decompressor when unpacking
+    - LP: #583414
+  * CRED: Fix a race in creds_are_invalid() in credentials debugging
+    - LP: #583414
+  * jfs: fix diAllocExt error in resizing filesystem
+    - LP: #583414
+  * ACPI: introduce kernel parameter acpi_sleep=sci_force_enable
+    - LP: #553498, #583414
+  * p54pci: rx frame length check
+    - LP: #583414
+  * drivers/net/wireless/p54/txrx.c Fix off by one error
+    - LP: #583414
+  * dccp_probe: Fix module load dependencies between dccp and dccp_probe
+    - LP: #583414
+  * KVM: remove unused load_segment_descriptor_to_kvm_desct
+    - LP: #583414
+  * kgdb: don't needlessly skip PAGE_USER test for Fsl booke
+    - LP: #583414
+  * r8169: use correct barrier between cacheable and non-cacheable memory
+    - LP: #562742, #583414
+  * r8169: fix broken register writes
+    - LP: #562742, #583414
+  * r8169: more broken register writes workaround
+    - LP: #562742, #583414
+  * PCI: Ensure we re-enable devices on resume
+    - LP: #566149, #583414
+  * skip sense logging for some ATA PASS-THROUGH cdbs
+    - LP: #583128, #583414
+  * tg3: Fix INTx fallback when MSI fails
+    - LP: #583414
+  * xfs: add a shrinker to background inode reclaim
+    - LP: #583414
+  * qla2xxx: Properly handle UNDERRUN completion statuses.
+    - LP: #583414
+  * bnx2: Fix lost MSI-X problem on 5709 NICs.
+    - LP: #583414
+  * tracing: Fix ftrace_event_call alignment for use with gcc 4.5
+    - LP: #583414
+  * security: testing the wrong variable in create_by_name()
+    - LP: #583414
+  * md: restore ability of spare drives to spin down.
+    - LP: #583414
+  * virtio: initialize earlier
+    - LP: #583414
+  * md/raid6: Fix raid-6 read-error correction in degraded state
+    - LP: #583414
+  * V4L/DVB: budget: Oops: "BUG: unable to handle kernel NULL pointer
+    dereference"
+    - LP: #583414
+  * ACPI: DMI init_set_sci_en_on_resume for multiple Lenovo ThinkPads
+    - LP: #583414
+  * power_meter: acpi_device_class "power_meter_resource" too long
+    - LP: #583414
+  * ACPI: sleep: init_set_sci_en_on_resume for Dell Studio 155x
+    - LP: #553498, #583414
+  * cpuidle: Fix incorrect optimization
+    - LP: #583414
+  * pxa/colibri: fix missing #include <mach/mfp.h> in colibri.h
+    - LP: #583414
+  * SCSI: fix locking around blk_abort_request()
+    - LP: #583414
+  * SCSI: libiscsi: regression: fix header digest errors
+    - LP: #583414
+  * scsi_debug: virtual_gb ignores sector_size
+    - LP: #583414
+  * Enable retries for SYNCRONIZE_CACHE commands to fix I/O error
+    - LP: #583414
+  * SCSI: Retry commands with UNIT_ATTENTION sense codes to fix ext3/ext4
+    I/O error
+    - LP: #583414
+  * MIPS: Sibyte: Apply M3 workaround only on affected chip types and
+    versions.
+    - LP: #583414
+  * Linux 2.6.32.13
+    - LP: #583414
+  * drm/i915: Add initial bits for VGA modesetting bringup on Sandybridge.
+    - LP: #583414
+  * drm/i915: fix tiling limits for i915 class hw v2
+    - LP: #583414
+  * Linux 2.6.32.13+drm33.4
+    - LP: #583414
+  * (pre-stable) Input: psmouse - reset all types of mice before
+    reconnecting
+    - LP: #551234
+  * ipv4: udp: fix short packet and bad checksum logging
+    - LP: #588832
+  * hp_accel: fix race in device removal
+    - LP: #588832
+  * fbdev: bfin-t350mcqb-fb: fix fbmem allocation with blanking lines
+    - LP: #588832
+  * hugetlbfs: kill applications that use MAP_NORESERVE with SIGBUS instead
+    of OOM-killer
+    - LP: #588832
+  * dma-mapping: fix dma_sync_single_range_*
+    - LP: #588832
+  * ACPI: sleep: eliminate duplicate entries in acpisleep_dmi_table[]
+    - LP: #588832
+  * mmc: atmel-mci: fix two parameters swapped
+    - LP: #588832
+  * mmc: atmel-mci: prevent kernel oops while removing card
+    - LP: #588832
+  * mmc: atmel-mci: remove data error interrupt after xfer
+    - LP: #588832
+  * ptrace: fix return value of do_syscall_trace_enter()
+    - LP: #588832
+  * powerpc/perf_event: Fix oops due to perf_event_do_pending call
+    - LP: #588832
+  * cifs: guard against hardlinking directories
+    - LP: #588832
+  * serial: imx.c: fix CTS trigger level lower to avoid lost chars
+    - LP: #588832
+  * ALSA: ice1724 - Fix ESI Maya44 capture source control
+    - LP: #588832
+  * ALSA: hda: Fix 0 dB for Lenovo models using Conexant CX20549 (Venice)
+    - LP: #588832
+  * inotify: race use after free/double free in inotify inode marks
+    - LP: #588832
+  * inotify: don't leak user struct on inotify release
+    - LP: #588832
+  * profile: fix stats and data leakage
+    - LP: #588832
+  * x86, k8: Fix build error when K8_NB is disabled
+    - LP: #588832
+  * x86, cacheinfo: Turn off L3 cache index disable feature in virtualized
+    environments
+    - LP: #588832
+  * x86, amd: Check X86_FEATURE_OSVW bit before accessing OSVW MSRs
+    - LP: #588832
+  * Btrfs: check for read permission on src file in the clone ioctl
+    - LP: #588832
+  * ALSA: hda - New Intel HDA controller
+    - LP: #588832
+  * proc: partially revert "procfs: provide stack information for threads"
+    - LP: #588832
+  * revert "procfs: provide stack information for threads" and its fixup
+    commits
+    - LP: #588832
+  * iwlwifi: clear all the stop_queue flag after load firmware
+    - LP: #588832
+  * p54: disable channels with incomplete calibration data sets
+    - LP: #588832
+  * CacheFiles: Fix error handling in cachefiles_determine_cache_security()
+    - LP: #588832
+  * megaraid_sas: fix for 32bit apps
+    - LP: #588832
+  * mmap_min_addr check CAP_SYS_RAWIO only for write
+    - LP: #588832
+  * nilfs2: fix sync silent failure
+    - LP: #588832
+  * crypto: authenc - Add EINPROGRESS check
+    - LP: #588832
+  * Linux 2.6.32.14
+    - LP: #588832
+  * drm/i915: use PIPE_CONTROL instruction on Ironlake and Sandy Bridge
+    - LP: #588832
+  * drm/i915: fix non-Ironlake 965 class crashes
+    - LP: #588832
+  * drm/i915: Disable FBC on 915GM and 945GM.
+    - LP: #492392, #588832
+  * Linux 2.6.32.14+drm33.5
+    - LP: #588832
+  * Linux 2.6.32.15+drm33.5
+    - LP: #588832
+  * HID: remove MODULE_VERSION from new drivers
+    - LP: #583531
+  * HID: fix N-trig touch panel with recent firmware
+    - LP: #583531
+  * HID: ntrig: explain firmware quirk
+    - LP: #583531
+  * HID: ntrig: Emit TOUCH with DOUBLETAP for single touch
+    - LP: #583531
+  * HID: ntrig: TipSwitch for single touch mode touch.
+    - LP: #583531
+  * HID: ntrig: Remove unused macro, TripleTap and QuadTap
+    - LP: #583531
+  * (pre-stable) drm/radeon/kms: initialize set_surface_reg reg for rs600
+    asic
+    - LP: #544590
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 09 Jun 2010 17:01:09 +0200
+
+linux (2.6.32-22.36) lucid-security; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "kvm: restrict writing of segment selectors to segment
+    registers"
+    - LP: #589223
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 03 Jun 2010 17:11:27 +0100
+
+linux (2.6.32-22.35) lucid-security; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * kvm: restrict writing of segment selectors to segment registers
+    - CVE-2010-0419
+
+  [ Upstream Kernel Changes ]
+
+  * tty: release_one_tty() forgets to put pids
+    - CVE-2010-1162
+  * oom: fix the unsafe usage of badness() in proc_oom_score()
+    - CVE-2010-1488
+  * Attempt #2 to handle null nameidata
+    - CVE-2010-1148
+  * reiserfs: fix permissions on .reiserfs_priv
+    - CVE-2010-1146
+  * r8169: offical fix for CVE-2009-4537 (overlength frame DMAs)
+    - CVE-2009-4537
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 01 Jun 2010 11:44:28 +0200
+
+linux (2.6.32-22.33) lucid-proposed; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: ACPI: EC: Allow multibyte access to EC (v3)
+    - LP: #526354
+
+  [ Tim Gardner ]
+
+  * ubuntu: rtl8192se -- update to version 0015.0127.2010
+    - LP: #567016
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 19 Apr 2010 11:06:35 +0100
+
+linux (2.6.32-21.32) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: i915 KMS -- support disabling KMS for known broken devices
+    - LP: #563277
+  * SAUCE: i915 KMS -- blacklist i830
+    - LP: #542208, #563277
+  * SAUCE: i915 KMS -- blacklist i845g
+    - LP: #541492, #563277
+  * SAUCE: i915 KMS -- blacklist i855
+    - LP: #511001, #541511, #563277
+  * SAUCE: radeon KMS -- support disabling KMS for known broken devices
+    - LP: #546743
+  * SAUCE: radeon KMS -- blacklist ES1000
+    - LP: #546743
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 15 Apr 2010 17:18:49 +0100
+
+linux (2.6.32-21.31) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * allow modules.builtin to be optional
+  * d-i: add mpt2sas to the message-modules udeb
+    - LP: #530361
+
+  [ Christopher James Halse Rogers ]
+
+  * SAUCE: Nouveau: Add quirk framework to disable acceleration
+    - LP: #544088, #546393
+  * SAUCE: Nouveau: Disable acceleration on MacBook Pros
+    - LP: #546393
+  * SAUCE: Nouveau: Disable acceleration on GeForce3 cards
+    - LP: #544088
+  * SAUCE: Nouveau: Disable acceleration on 6100 cards
+    - LP: #542950
+
+  [ Stefan Bader ]
+
+  * SAUCE: dma-mapping: Remove WARN_ON in dma_free_coherent
+    - LP: #458201
+
+  [ Surbhi Palande ]
+
+  * SAUCE: sync before umount to reduce time taken by ext4 umount
+    - LP: #543617
+
+  [ Upstream Kernel Changes ]
+
+  * tipc: Fix oops on send prior to entering networked mode (v3)
+    - CVE-2010-1187
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - LP: #561425
+  * KVM: x86 emulator: fix memory access during x86 emulation
+    - LP: #561425
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - LP: #561425
+  * KVM: x86 emulator: Fix popf emulation
+    - LP: #561425
+  * KVM: Fix segment descriptor loading
+    - LP: #561425
+  * KVM: VMX: Update instruction length on intercepted BP
+    - LP: #561425
+  * KVM: VMX: Use macros instead of hex value on cr0 initialization
+    - LP: #561425
+  * KVM: SVM: Reset cr0 properly on vcpu reset
+    - LP: #561425
+  * KVM: VMX: Disable unrestricted guest when EPT disabled
+    - LP: #561425
+  * KVM: x86: disable paravirt mmu reporting
+    - LP: #561425
+  * AppArmor: Fix put of unassigned ns if aa_unpack fails
+  * AppArmor: Fix refcount bug when exec fails
+    - LP: #562063
+  * AppArmor: Take refcount on cxt->profile to ensure it remains a valid
+    reference
+    - LP: #367499
+  * AppArmor: fix typo in scrubbing environment variable warning
+    - LP: #562060
+  * AppArmor: fix regression by setting default to mediate deleted files
+    - LP: #562056
+  * AppArmor: fix refcount order bug that can trigger during replacement
+    - LP: #367499
+  * AppArmor: Make sure to unmap aliases for vmalloced dfas before they are
+    live
+    - LP: #529288
+  * AppArmor: address performance regression of replaced profile
+    - LP: #549428
+  * AppArmor: make the global side the correct type
+    - LP: #562047
+  * AppArmor: use the kernel shared workqueue to free vmalloc'ed dfas
+  * sky2: add register definitions for new chips
+    - LP: #537168
+  * sky2: 88E8059 support
+    - LP: #537168
+  * net: Fix Yukon-2 Optima TCP offload setup
+    - LP: #537168
+  * net: Add missing TST_CFG_WRITE bits around sky2_pci_write
+    - LP: #537168
+  * sky2: print Optima chip name
+    - LP: #537168
+  * (Upstream) dell-laptop: defer dell_rfkill_update to worker thread
+    - LP: #555261
+  * drm/nv40: add LVDS table quirk for Dell Latitude D620
+    - LP: #539730
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 13 Apr 2010 18:50:58 +0100
+
+linux (2.6.32-20.30) lucid; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) ACPI: EC: Allow multibyte access to EC"
+    - LP: #561151
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 12 Apr 2010 15:46:31 +0100
+
+linux (2.6.32-20.29) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915"
+    - LP: #542251
+  * add Breaks: against hardy lvm2
+    - LP: #528155
+
+  [ Colin Watson ]
+
+  * d-i -- enable udebs for generic-pae
+    - LP: #160366
+
+  [ Stefan Bader ]
+
+  * [Config] Add xen netboot support
+    - LP: #160366
+
+  [ Takashi Iwai ]
+
+  * (pre-stable): input: Support Clickpad devices in ClickZone mode
+    - LP: #516329
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) Bluetooth: Fix sleeping function in RFCOMM within
+    invalid context"
+    - LP: #553837
+  * Revert "(pre-stable) USB: fix usbfs regression"
+    - LP: #553837
+  * Revert "(pre-stable) softlockup: Stop spurious softlockup messages due
+    to overflow"
+    - LP: #553837
+  * Revert "(pre-stable) drm/nouveau: report unknown connector state if lid
+    closed"
+    - LP: #553837
+  * drivers/scsi/ses.c: eliminate double free
+    - LP: #553837
+  * decompress: fix new decompressor for PIC
+    - LP: #553837
+  * ARM: Fix decompressor's kernel size estimation for ROM=y
+    - LP: #553837
+  * MIPS: Cleanup forgotten label_module_alloc in tlbex.c
+    - LP: #553837
+  * tg3: Fix tg3_poll_controller() passing wrong pointer to tg3_interrupt()
+    - LP: #553837
+  * tg3: Fix 5906 transmit hangs
+    - LP: #553837
+  * ALSA: hda - Fix input source elements of secondary ADCs on Realtek
+    - LP: #553837
+  * ALSA: hda: enable MSI for Gateway M-6866
+    - LP: #538918, #553837
+  * timekeeping: Prevent oops when GENERIC_TIME=n
+    - LP: #553837
+  * Input: alps - add support for the touchpad on Toshiba Tecra A11-11L
+    - LP: #553837
+  * Input: i8042 - add ALDI/MEDION netbook E1222 to qurik reset table
+    - LP: #553837
+  * i2c-i801: Don't use the block buffer for I2C block writes
+    - LP: #553837
+  * ath5k: dont use external sleep clock in AP mode
+    - LP: #553837
+  * ath5k: fix setup for CAB queue
+    - LP: #553837
+  * ring-buffer: Move disabled check into preempt disable section
+    - LP: #553837
+  * function-graph: Init curr_ret_stack with ret_stack
+    - LP: #553837
+  * Bluetooth: Fix sleeping function in RFCOMM within invalid context
+    - LP: #553837
+  * tracing: Use same local variable when resetting the ring buffer
+    - LP: #553837
+  * tracing: Disable buffer switching when starting or stopping trace
+    - LP: #553837
+  * tracing: Do not record user stack trace from NMI context
+    - LP: #553837
+  * PCI: unconditionally clear AER uncorr status register during cleanup
+    - LP: #553837
+  * efifb: fix framebuffer handoff
+    - LP: #553837
+  * coredump: suppress uid comparison test if core output files are pipes
+    - LP: #553837
+  * V4L/DVB (13961): em28xx-dvb: fix memleak in dvb_fini()
+    - LP: #553837
+  * hrtimer: Tune hrtimer_interrupt hang logic
+    - LP: #553837
+  * x86, apic: Don't use logical-flat mode when CPU hotplug may exceed 8
+    CPUs
+    - LP: #553837
+  * mvsas: add support for Adaptec ASC-1045/1405 SAS/SATA HBA
+    - LP: #553837
+  * pci: add support for 82576NS serdes to existing SR-IOV quirk
+    - LP: #553837
+  * sched: Mark boot-cpu active before smp_init()
+    - LP: #553837
+  * sparc64: Make prom entry spinlock NMI safe.
+    - LP: #553837
+  * sysctl: require CAP_SYS_RAWIO to set mmap_min_addr
+    - LP: #553837
+  * e1000e: enable new 82567V-3 device
+    - LP: #553837
+  * ixgbe: add support for 82599 KR device 0x1517
+    - LP: #553837
+  * ath9k: fix lockdep warning when unloading module
+    - LP: #553837
+  * mqueue: fix mq_open() file descriptor leak on user-space processes
+    - LP: #553837
+  * virtio: fix out of range array access
+    - LP: #553837
+  * sched: Fix SCHED_MC regression caused by change in sched cpu_power
+    - LP: #553837
+  * readahead: add blk_run_backing_dev
+    - LP: #553837
+  * ALSA: hda: Use LPIB and 6stack-dig for eMachines T5212
+    - LP: #538895, #553837
+  * ALSA: hda - Disable MSI for Nvidia controller
+    - LP: #553837
+  * ALSA: hda - Fix secondary ADC of ALC260 basic model
+    - LP: #553837
+  * ALSA: hda: Fix 0 dB offset for HP laptops using CX20551 (Waikiki)
+    - LP: #420578, #553837
+  * ALSA: cmipci: work around invalid PCM pointer
+    - LP: #553837
+  * gigaset: correct clearing of at_state strings on RING
+    - LP: #553837
+  * gigaset: prune use of tty_buffer_request_room
+    - LP: #553837
+  * perf: Make the install relative to DESTDIR if specified
+    - LP: #553837
+  * perf_event: Fix oops triggered by cpu offline/online
+    - LP: #553837
+  * tmpfs: fix oops on mounts with mpol=default
+    - LP: #553837
+  * tmpfs: mpol=bind:0 don't cause mount error.
+    - LP: #553837
+  * tmpfs: handle MPOL_LOCAL mount option properly
+    - LP: #553837
+  * tmpfs: cleanup mpol_parse_str()
+    - LP: #553837
+  * doc: add the documentation for mpol=local
+    - LP: #553837
+  * SCSI: scsi_transport_fc: Fix synchronization issue while deleting vport
+    - LP: #553837
+  * NFSv4: Don't ignore the NFS_INO_REVAL_FORCED flag in
+    nfs_revalidate_inode()
+    - LP: #553837
+  * NFS: Avoid a deadlock in nfs_release_page
+    - LP: #553837
+  * NFS: Prevent another deadlock in nfs_release_page()
+    - LP: #553837
+  * tty: Keep the default buffering to sub-page units
+    - LP: #553837
+  * tty: Take a 256 byte padding into account when buffering below sub-page
+    units
+    - LP: #553837
+  * USB: fix usbfs regression
+    - LP: #553837
+  * USB: EHCI: fix ITD list order
+    - LP: #553837
+  * USB: EHCI: adjust ehci_iso_stream for changes in ehci_qh
+    - LP: #553837
+  * USB: qcserial: add new device ids
+    - LP: #553837
+  * USB: xHCI: re-initialize cmd_completion
+    - LP: #553837
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #553837
+  * USB: option: fix incorrect manufacturer name in usb/serial/option:
+    MAXON->CMOTECH
+    - LP: #553837
+  * USB: option: move hardcoded PID to a macro in usb/serial/option
+    - LP: #553837
+  * USB: option: add support for a new CMOTECH device to usb/serial/option
+    - LP: #553837
+  * usb: r8a66597-hcd: fix removed from an attached hub
+    - LP: #553837
+  * wl1251: fix potential crash
+    - LP: #553837
+  * jme: Fix VLAN memory leak
+    - LP: #553837
+  * jme: Protect vlgrp structure by pause RX actions.
+    - LP: #553837
+  * edac, mce: Filter out invalid values
+    - LP: #553837
+  * iwlwifi: use dma_alloc_coherent
+    - LP: #553837
+  * iwlwifi: Silence tfds_in_queue message
+    - LP: #553837
+  * SUNRPC: Fix a potential memory leak in auth_gss
+    - LP: #553837
+  * sunrpc: handle allocation errors from __rpc_lookup_create()
+    - LP: #553837
+  * if_tunnel.h: add missing ams/byteorder.h include
+    - LP: #553837
+  * fs/partitions/msdos: add support for large disks
+    - LP: #553837
+  * fs/partition/msdos: fix unusable extended partition for > 512B sector
+    - LP: #553837
+  * PCI: fix return value from pcix_get_max_mmrbc()
+    - LP: #553837
+  * PCI: fix access of PCI_X_CMD by pcix get and set mmrbc functions
+    - LP: #553837
+  * PCI: cleanup error return for pcix get and set mmrbc functions
+    - LP: #553837
+  * rt2860sta: Fix argument to linux_pci_unmap_single()
+    - LP: #553837
+  * ath9k: fix BUG_ON triggered by PAE frames
+    - LP: #553837
+  * cpuset: fix the problem that cpuset_mem_spread_node() returns an
+    offline node
+    - LP: #553837
+  * softlockup: Stop spurious softlockup messages due to overflow
+    - LP: #553837
+  * netfilter: xt_recent: fix regression in rules using a zero hit_count
+    - LP: #553837
+  * x86: Fix placement of FIX_OHCI1394_BASE
+    - LP: #553837
+  * x86, amd: Restrict usage of c1e_idle()
+    - LP: #553837
+  * hwmon: (coretemp) Add missing newline to dev_warn() message
+    - LP: #553837
+  * ALSA: hda: Use LPIB for ga-ma770-ud3 board
+    - LP: #553837
+  * ALSA: ac97: Add Toshiba P500 to ac97 jack sense blacklist
+    - LP: #481058, #553837
+  * ALSA: ac97: Add IBM ThinkPad R40e to Headphone/Line Jack Sense
+    blacklist
+    - LP: #303789, #553837
+  * ALSA: hda: Use ALC260_WILL quirk for another Acer model (0x1025007f)
+    - LP: #418627, #553837
+  * ath9k: Enable TIM timer interrupt only when needed.
+    - LP: #553837
+  * mac80211: Retry null data frame for power save
+    - LP: #553837
+  * ath9k: Enable IEEE80211_HW_REPORTS_TX_ACK_STATUS flag for ath9k
+    - LP: #553837
+  * mac80211: Reset dynamic ps timer in Rx path.
+    - LP: #553837
+  * leds-gpio: fix default state handling on OF platforms
+    - LP: #553837
+  * quota: manage reserved space when quota is not active [v2]
+    - LP: #553837
+  * quota: Fix warning when a delayed write happens before quota is enabled
+    - LP: #553837
+  * ahci: use BIOS date in broken_suspend list
+    - LP: #553837
+  * Bluetooth: Fix potential bad memory access with sysfs files
+    - LP: #553837
+  * Bluetooth: Fix kernel crash on L2CAP stress tests
+    - LP: #553837
+  * sh: Fix zImage boot using fixed PMB.
+    - LP: #553837
+  * b43: Workaround circular locking in hw-tkip key update callback
+    - LP: #553837
+  * block: Backport of various I/O topology fixes from 2.6.33 and 2.6.34
+    - LP: #553837
+  * s3cmci: initialize default platform data no_wprotect and no_detect with
+    1
+    - LP: #553837
+  * x86: Fix sched_clock_cpu for systems with unsynchronized TSC
+    - LP: #553837
+  * GFS2: Skip check for mandatory locks when unlocking
+    - LP: #553837
+  * Linux 2.6.32.11
+    - LP: #553837
+  * drm/i915: fix small leak on overlay error path
+    - LP: #553837
+  * drm/i915: Avoid NULL deref in get_pages() unwind after error.
+    - LP: #553837
+  * drm/nouveau: report unknown connector state if lid closed
+    - LP: #553837
+  * Linux-2.6.32.11+drm33.2
+    - LP: #553837
+  * mmc: add module parameter to set whether cards are assumed removable
+    - LP: #477106
+  * (pre-stable) ACPI: EC: Allow multibyte access to EC
+    - LP: #526354
+  * PCI quirks: disable msi on AMD rs4xx internal gfx bridges
+    - LP: #509273
+  * drm/i915: Add dependency on the intel agp module
+    - LP: #542251
+  * (pre-stable) drm/edid: allow certain bogus edids to hit a fixup path
+    rather than fail
+    - LP: #540632
+  * drm/radeon/kms: rework pll algo selection
+    - LP: #538377
+  * drm/radeon/kms: update new pll algo
+    - LP: #538377
+  * PCI quirk: Disable MSI on VIA K8T890 systems
+    - LP: #544741
+  * sched: update load count only once per cpu in 10 tick update window
+    - LP: #513848
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 09 Apr 2010 17:44:41 +0100
+
+linux (2.6.32-19.28) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] enable various multitouch devices
+    - LP: #541453
+
+  [ Chase Douglas ]
+
+  * (pre-stable): input: ALPS - Add signature for HP Pavilion dm3 laptops
+    - LP: #545307
+  * SAUCE: Disable function tracing after hitting __schedule_bug
+  * SAUCE: Reduce ACPI resource conflict message to KERN_INFO, printf
+    cleanup
+    - LP: #440470
+
+  [ Jesse Barnes ]
+
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Remove null_profile's use of PFLAG_NO_LIST_REF
+    - LP: #539437
+  * SAUCE: AppArmor: Stop page allocation warnings that can occur on policy
+    load
+    - LP: #458299
+  * SAUCE: AppArmor: Return string len rather than the allocation size
+    - LP: #551844
+  * SAUCE: AppArmor: Fix oops in profile verification if profile unpack
+    fails.
+
+  [ Luke Yelavich ]
+
+  * [Config] Enable Nouveau DRM module on powerpc
+
+  [ Stefan Bader ]
+
+  * SAUCE: Pull in thinkpad-acpi from v2.6.34-rc1
+    - LP: #357673
+  * [Config] Enable thinkpad-acpi ALSA volume control
+    - LP: #357673
+
+  [ Steve Conklin ]
+
+  * SAUCE: drm/i915: Disable FBC on 915GM and 945GM
+    - LP: #492392, #539609
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP,
+    Dell Inspiron 700m"
+    - LP: #515246
+  * (pre-stable) softlockup: Stop spurious softlockup messages due to
+    overflow
+    - LP: #551068
+  * backlight: mbp_nvidia_bl - add five more MacBook variants
+    - LP: #511965
+  * drm/nv04-nv40: Fix up the programmed horizontal sync pulse delay.
+    - LP: #529130
+  * drm/nouveau: Fix fbcon corruption with font width not divisible by 8
+    - LP: #544739
+  * (pre-stable) USB: fix usbfs regression
+  * drm/radeon/bo: add some fallback placements for VRAM only objects.
+    - LP: #507148
+  * drm/radeon/kms: don't print error on -ERESTARTSYS.
+    - LP: #507148
+  * Input: add the ABS_MT_PRESSURE event
+    - LP: #541453
+  * HID: Support for 3M multitouch panel
+    - LP: #541453
+  * HID: make 3M PCT touchscreen driver standalone config option
+    - LP: #541453
+  * HID: add support for Stantum multitouch panel
+    - LP: #541453
+  * HID: make Stantum driver standalone config option
+    - LP: #541453
+  * HID: add support for Acer T230H multitouch
+    - LP: #541453
+  * HID: add support for Pixart Imaging Optical Touch Screen
+    - LP: #541453
+  * HID: fixed bug in single-touch emulation on the stantum panel
+    - LP: #541453
+  * HID: add pressure support for the Stantum multitouch panel
+    - LP: #541453
+  * HID: Support for MosArt multitouch panel
+    - LP: #541453
+  * HID: hid-ntrig add multi input quirk and clean up
+    - LP: #541453
+  * HID: n-trig: remove unnecessary tool switching
+    - LP: #541453
+  * HID: hid-ntrig: multitouch cleanup and fix
+    - LP: #541453
+  * HID: hid-ntrig: Single touch mode tap
+    - LP: #541453
+  * hid: ntrig touch events
+    - LP: #541453
+  * (pre-stable) x86-32, resume: do a global tlb flush in S4 resume
+    - LP: #531309
+  * drm/i915: Part of: Add initial bits for VGA modesetting bringup on
+    Sandybridge.
+    - LP: #515246
+  * drm/i915: Stop trying to use ACPI lid status to determine LVDS
+    connection.
+    - LP: #515246
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 31 Mar 2010 15:14:32 +0100
+
+linux (2.6.32-18.27) lucid; urgency=low
+
+  [ Chase Douglas ]
+
+  * SAUCE: Don't register vga16fb framebuffer if other framebuffers are
+    present
+    - LP: #527369
+
+  [ Loïc Minier ]
+
+  * [Config] armel/versatile: Set CRAMFS=m
+    - LP: #524893
+  * [Config] armel: Reset default command-line
+    - LP: #524893
+
+  [ Stefan Bader ]
+
+  * build/modules: Update d-i to reflect recent config changes
+    - LP: #546929
+
+  [ Upstream Kernel Changes ]
+
+  * (pre-stable) drm/nouveau: report unknown connector state if lid closed
+    - LP: #523072
+  * (pre-stable) Staging: rt2870: Add USB ID for Buffalo Airstation
+    WLI-UC-GN
+    - LP: #441990
+  * (pre-stable) iwlwifi: fix nfreed--
+    - LP: #545585
+  * (pre-stable) pata_via: Add VIA VX900 support
+    - LP: #548675
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 26 Mar 2010 18:39:42 +0100
+
+linux (2.6.32-17.26) lucid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] SECURITY_FILE_CAPABILITIES dissapeared in 2.6.33
+
+  [ Andy Whitcroft ]
+
+  * rules -- allow architecture configurations to be missing
+  * SAUCE: cdrom -- default to not locking the tray when in use
+    - LP: #397734
+  * expose the kernel EXTRAVERSION in dmesg and /proc/version_signature
+  * record the drm version in EXTRAVERSION
+  * linux-tools -- pull out the perf binary into a binary package
+  * [Config] enable MMIOTRACE for graphics debugging
+  * [Config] enable BLK_DEV_BSG
+  * debian -- fix builds when tools are disabled
+  * allow us to build default configs for automated builds
+  * config -- allow locally specified configuration overrides
+  * [Config] de-modularise PATA disk controllers
+  * [Config] de-modularise SATA disk controllers
+
+  [ Stefan Bader ]
+
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow"
+    - LP: #540231
+  * Revert "SAUCE: (pre-stable) netfilter: xt_recent: fix false match"
+    - LP: #540231
+  * [Config] Update configs for 2.6.32.10
+    - LP: #540231
+
+  [ Tim Gardner ]
+
+  * [Config] Add vmw_pvscsi and vmxnet3 to -virtual flavour
+    - LP: #531017
+  * SAUCE: igb: Supress an upstream compiler complaint
+  * [Config] Fix sub-flavours package conflicts
+    - LP: #454827
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "tpm_tis: TPM_STS_DATA_EXPECT workaround"
+    - LP: #540231
+  * Revert "(pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()"
+    - LP: #540231
+  * (pre-stable) Bluetooth: Fix sleeping function in RFCOMM within invalid
+    context
+    - LP: #534549
+  * igb: remove unused temp variable from stats clearing path
+  * igb: update comments for serdes config and update to handle duplex
+  * igb: update the approach taken to acquiring and releasing the phy lock
+  * igb: add locking to reads of the i2c interface
+  * igb: add combined function for setting rar and pool bits
+  * igb: make use of the uta to allow for promiscous mode filter
+  * igb: add support for 82576NS SerDes adapter
+  * igb: add function to handle mailbox lock
+  * igb: fix a few items where weren't correctly setup for mbx timeout
+  * igb: change how we handle alternate mac addresses
+  * igb: remove microwire support from igb
+  * igb: move the generic copper link setup code into e1000_phy.c
+  * igb: add code to retry a phy read in the event of failure on link check
+  * igb: add additional error handling to the phy code
+  * igb: add flushes between RAR writes when setting mac address
+  * igb: Use the instance of net_device_stats from net_device.
+  * igb: Fix erroneous display of stats by ethtool -S
+  * igb: add new data structure for handling interrupts and NAPI
+  * igb: remove rx checksum good counter
+  * igb: increase minimum rx buffer size to 1K
+  * igb: move the tx and rx ring specific config into seperate functions
+  * igb: remove rx_ps_hdr_len
+  * igb: move SRRCTL register configuration into ring specific config
+  * igb: change the head and tail offsets into pointers
+  * igb: add pci device pointer to ring structure
+  * igb: move rx_buffer_len into the ring structure
+  * igb: move alloc_failed and csum_err stats into per rx-ring stat
+  * igb: add a flags value to the ring
+  * igb: place a pointer to the netdev struct in the ring itself
+  * igb: move the multiple receive queue configuration into seperate
+    function
+  * igb: delay VF reset notification until after interrupts are enabed
+  * igb: setup vlan tag replication stripping in igb_vmm_control
+  * igb: re-use ring configuration code in ethtool testing
+  * igb: make tx ring map and free functionality non-static
+  * igb: make ethtool use core xmit map and free functionality
+  * igb: add single vector msi-x testing to interrupt test
+  * igb: cleanup "todo" code found in igb_ethtool.c
+  * igb: add support for seperate tx-usecs setting in ethtool
+  * igb: cleanup some of the code related to hw timestamping
+  * igb: misc cleanups within igb_ethtool.c
+  * igb: use packet buffer sizes from RXPBS register
+  * igb: replace the VF clear_to_send with a flags value
+  * igb: rework use of VMOLR in regards to PF and VFs
+  * igb: rework handling of the vfta and vlvf registers in relation to
+    mng_vlan
+  * igb: move vf init into a seperate function
+  * igb: only process global stats in igb_update_stats
+  * igb: move global_quad_port_a from global into local static define
+  * igb: make tx hang check multiqueue, check eop descriptor
+  * igb: cleanup code related to ring resource allocation and free
+  * igb: change queue ordering for 82576 based adapters
+  * igb: cleanup interrupt enablement in regards to msix_other
+  * igb: Remove invalid stats counters
+  * igb: cleanup igb.h header whitespace and some structure formatting
+  * igb: cleanup igb xmit frame path
+  * igb: cleanup clean_rx_irq_adv and alloc_rx_buffers_adv
+  * igb: replace unecessary &adapter->hw with just hw where applicable
+  * igb: add pci_dev in few spots to clean up use of dev_err/info/warn
+  * igb: limit minimum mtu to 68 to keep ip bound to interface
+  * igb: open up SCTP checksum offloads to all MACs 82576 and newer
+  * igb: cleanup whitespace issues in igb_main.c
+  * igb: Fix warnings in igb_set_ringparam()
+  * igb: change type for ring sizes to u16 in igb_set_ring_param
+  * igb: move timesync init into a seperate function
+  * igb: when number of CPUs > 4 combine tx/rx queues to allow more queues
+  * igb: Rework how netdev->stats is handled
+  * igb: removed unused tx/rx total bytes/packets from adapter struct
+  * igb: check for packets on all tx rings when link is down
+  * igb: only recycle page if it is on our numa node
+  * igb: add support for the 82580 phy
+  * igb: add support for 82580 MAC
+  * igb: Add full support for 82580 devices
+  * igb: remove use of skb_dma_map from driver
+  * igb: fix handling of mailbox collisions between PF/VF
+  * igb: do not force pcs link when in KX mode
+  * igb: do not force retry count to 1 on 82580 phy
+  * igb: correctly offset 82575 flow control watermarks by 16 bytes
+  * igb: check both function bits in status register in wol exception
+  * igb: make certain to reassign legacy interrupt vectors after reset
+  * igb/igbvf: cleanup exception handling in tx_map_adv
+  * fix LOOKUP_FOLLOW on automount "symlinks"
+    - LP: #540231
+  * ARM: 5944/1: scsi: fix timer setup in fas216.c
+    - LP: #540231
+  * V4L/DVB: dvb: l64781.ko broken with gcc 4.5
+    - LP: #540231
+  * bfin: fix max timeout calculation
+    - LP: #540231
+  * V4L/DVB: Video : pwc : Fix regression in pwc_set_shutter_speed caused
+    by bad constant => sizeof conversion.
+    - LP: #540231
+  * V4L/DVB: bttv: Move I2C IR initialization
+    - LP: #540231
+  * V4L/DVB: cxusb: Select all required frontend and tuner modules
+    - LP: #540231
+  * memcg: fix oom killing a child process in an other cgroup
+    - LP: #540231
+  * fs/exec.c: fix initial stack reservation
+    - LP: #540231
+  * iwlwifi: error checking for number of tfds in queue
+    - LP: #540231
+  * iwlwifi: set HT flags after channel in rxon
+    - LP: #540231
+  * iwlwifi: sanity check before counting number of tfds can be free
+    - LP: #540231
+  * netlabel: fix export of SELinux categories > 127
+    - LP: #540231
+  * ahci: disable FPDMA auto-activate optimization on NVIDIA AHCI
+    - LP: #540231
+  * PCI hotplug: ibmphp: read the length of ebda and map entire ebda region
+    - LP: #540231
+  * PCI hotplug: check ioremap() return value in ibmphp_ebda.c
+    - LP: #540231
+  * ACPI: remove Asus P2B-DS from acpi=ht blacklist
+    - LP: #540231
+  * ACPI: fix "acpi=ht" boot option
+    - LP: #540231
+  * thinkpad-acpi: wrong thermal attribute_group removed in thermal_exit()
+    - LP: #540231
+  * ACPI: Be in TS_POLLING state during mwait based C-state entry
+    - LP: #540231
+  * mpt2sas: Delete volume before HBA detach.
+    - LP: #540231
+  * slab: initialize unused alien cache entry as NULL at
+    alloc_alien_cache().
+    - LP: #540231
+  * mac80211: quit addba_resp_timer if Tx BA session is torn down
+    - LP: #540231
+  * V4L/DVB (13991): gspca_mr973010a: Fix cif type 1 cameras not streaming
+    on UHCI controllers
+    - LP: #540231
+  * vfs: take f_lock on modifying f_mode after open time
+    - LP: #540231
+  * readahead: introduce FMODE_RANDOM for POSIX_FADV_RANDOM
+    - LP: #540231
+  * HID: remove TENX iBuddy from blacklist
+    - LP: #540231
+  * HID: add multi-input quirk for NextWindow Touchscreen.
+    - LP: #540231
+  * HID: usbhid: introduce timeout for stuck ctrl/out URBs
+    - LP: #540231
+  * airo: fix setting zero length WEP key
+    - LP: #540231
+  * idr: fix a critical misallocation bug, take#2
+    - LP: #540231
+  * Switch proc/self to nd_set_link()
+    - LP: #540231
+  * sparc: Align clone and signal stacks to 16 bytes.
+    - LP: #540231
+  * sparc32: Fix page_to_phys().
+    - LP: #540231
+  * sparc32: Fix struct stat uid/gid types.
+    - LP: #540231
+  * sparc: leds_resource.end assigned to itself in clock_board_probe()
+    - LP: #540231
+  * sparc64: Fix sun4u execute bit check in TSB I-TLB load.
+    - LP: #540231
+  * net: Fix sysctl restarts...
+    - LP: #540231
+  * net-sysfs: Use rtnl_trylock in wireless sysfs methods.
+    - LP: #540231
+  * net: bug fix for vlan + gro issue
+    - LP: #540231
+  * inet: Remove bogus IGMPv3 report handling
+    - LP: #540231
+  * ipv6: conntrack: Add member of user to nf_ct_frag6_queue structure
+    - LP: #540231
+  * drivers/net: ks8851_mll ethernet network driver
+    - LP: #540231
+  * sky2: fix transmit DMA map leakage
+    - LP: #540231
+  * SCSI: qla2xxx: Obtain proper host structure during response-queue
+    processing.
+    - LP: #540231
+  * rtc-core: fix memory leak
+    - LP: #540231
+  * offb: Add support for framebuffer handoff to offb.
+    - LP: #540231
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #540231
+  * rndis_wlan: handle NL80211_AUTHTYPE_AUTOMATIC
+    - LP: #540231
+  * rndis_wlan: fix buffer overflow in rndis_query_oid
+    - LP: #540231
+  * rndis_wlan: disable stall workaround
+    - LP: #540231
+  * net/via-rhine: Fix scheduling while atomic bugs
+    - LP: #540231
+  * clocksource: Fix up a registration/IRQ race in the sh drivers.
+    - LP: #540231
+  * SCSI: qla1280: Drop host_lock while requesting firmware
+    - LP: #540231
+  * Staging: hv: add a pci device table
+    - LP: #540231
+  * Staging: hv: match on DMI values to know if we should run.
+    - LP: #540231
+  * Staging: mimio: remove the mimio driver
+    - LP: #540231
+  * dvb-core: Fix DoS bug in ULE decapsulation code that can be triggered
+    by an invalid Payload Pointer
+    - LP: #540231
+  * V4L/DVB (13148): uvcvideo: Handle V4L2_CTRL_TYPE_BUTTON control type in
+    VIDIOC_QUERYCTRL
+    - LP: #540231
+  * PM / Hibernate: Fix preallocating of memory
+    - LP: #540231
+  * macintosh/therm_adt746x: Fix sysfs attributes lifetime
+    - LP: #540231
+  * macintosh/hwmon/ams: Fix device removal sequence
+    - LP: #540231
+  * oprofile/x86: fix perfctr nmi reservation for mulitplexing
+    - LP: #540231
+  * oprofile: remove tracing build dependency
+    - LP: #540231
+  * oprofile/x86: remove node check in AMD IBS initialization
+    - LP: #540231
+  * oprofile/x86: use kzalloc() instead of kmalloc()
+    - LP: #540231
+  * oprofile/x86: fix msr access to reserved counters
+    - LP: #540231
+  * ALSA: hda: Use 3stack quirk for Toshiba Satellite L40-10Q
+    - LP: #524948, #540231
+  * ALSA: via82xx: add quirk for D1289 motherboard
+    - LP: #540231
+  * ALSA: pcm core - fix fifo_size channels interval check
+    - LP: #540231
+  * ALSA: USB MIDI support for Access Music VirusTI
+    - LP: #540231
+  * ALSA: hda: Use LPIB for Dell Latitude 131L
+    - LP: #530346, #540231
+  * ALSA: hda: Use LPIB for a Biostar Microtech board
+    - LP: #523953, #540231
+  * ALSA: hda - Add a position_fix quirk for MSI Wind U115
+    - LP: #540231
+  * ALSA: hda - Add position_fix quirk for HP dv3
+    - LP: #540231
+  * ALSA: hda-intel: Add position_fix quirk for ASUS M2V-MX SE.
+    - LP: #540231
+  * ASoC: fix ak4104 register array access
+    - LP: #540231
+  * driver-core: fix race condition in get_device_parent()
+    - LP: #540231
+  * Driver-Core: devtmpfs - reset inode permissions before unlinking
+    - LP: #540231
+  * tty: Fix the ldisc hangup race
+    - LP: #540231
+  * serial: imx: fix NULL dereference Oops when pdata == NULL
+    - LP: #540231
+  * USB: serial: sierra driver indat_callback fix
+    - LP: #511157, #540231
+  * USB: SIS USB2VGA DRIVER: support KAIREN's USB VGA adaptor
+    USB20SVGA-MB-PLUS
+    - LP: #540231
+  * USB: fix I2C API usage in ohci-pnx4008.
+    - LP: #540231
+  * p54usb: Add the USB ID for Belkin (Accton) FD7050E ver 1010ec
+    - LP: #540231
+  * p54pci: handle dma mapping errors
+    - LP: #540231
+  * gpiolib: Actually set output state in wm831x_gpio_direction_output()
+    - LP: #540231
+  * hwmon: (tmp421) Fix temperature conversions
+    - LP: #540231
+  * hwmon: (tmp421) Restore missing inputs
+    - LP: #540231
+  * pata_hpt3x2n: always stretch UltraDMA timing
+    - LP: #540231
+  * scm: Only support SCM_RIGHTS on unix domain sockets.
+    - LP: #540231
+  * ath9k: fix beacon timer restart after a card reset
+    - LP: #540231
+  * ath9k: fix rate control fallback rate selection
+    - LP: #540231
+  * ath9k: disable RIFS search for AR91xx based chips
+    - LP: #540231
+  * ath5k: use correct packet type when transmitting
+    - LP: #540231
+  * b43/b43legacy: Wake queues in wireless_core_start
+    - LP: #540231
+  * netfilter: xt_recent: fix buffer overflow
+    - LP: #540231
+  * netfilter: xt_recent: fix false match
+    - LP: #540231
+  * sunxvr500: Additional PCI id for sunxvr500 driver
+    - LP: #540231
+  * thinkpad-acpi: fix poll thread auto-start
+    - LP: #540231
+  * thinkpad-acpi: R52 brightness_mode has been confirmed
+    - LP: #540231
+  * thinkpad-acpi: document HKEY event 3006
+    - LP: #540231
+  * thinkpad-acpi: make driver events work in NVRAM poll mode
+    - LP: #540231
+  * thinkpad-acpi: fix bluetooth/wwan resume
+    - LP: #540231
+  * ocfs2: Only bug out in direct io write for reflinked extent.
+    - LP: #540231
+  * x86, ia32_aout: do not kill argument mapping
+    - LP: #540231
+  * x86: Add iMac9,1 to pci_reboot_dmi_table
+    - LP: #540231
+  * x86, xen: Disable highmem PTE allocation even when CONFIG_HIGHPTE=y
+    - LP: #540231
+  * x86: Avoid race condition in pci_enable_msix()
+    - LP: #540231
+  * x86: Fix SCI on IOAPIC != 0
+    - LP: #540231
+  * USB: xhci: Fix finding extended capabilities registers
+    - LP: #540231
+  * USB: fix the idProduct value for USB-3.0 root hubs
+    - LP: #540231
+  * USB: fix crash in uhci_scan_schedule
+    - LP: #540231
+  * USB: remove debugging message for uevent constructions
+    - LP: #540231
+  * USB: Move hcd free_dev call into usb_disconnect to fix oops
+    - LP: #540231
+  * USB: ftdi_sio: isolate all device IDs to new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: sort PID/VID entries in new ftdi_sio_ids.h header
+    - LP: #540231
+  * USB: ftdi_sio: new device id for papouch AD4USB
+    - LP: #540231
+  * USB: ftdi_sio: add device IDs (several ELV, one Mindstorms NXT)
+    - LP: #540231
+  * USB: add new ftdi_sio device ids
+    - LP: #540231
+  * USB: serial: ftdi: add CONTEC vendor and product id
+    - LP: #540231
+  * USB: cp210x: Add 81E8 (Zephyr Bioharness)
+    - LP: #540231
+  * USB: unusual_devs: Add support for multiple Option 3G sticks
+    - LP: #540231
+  * sunrpc: remove unnecessary svc_xprt_put
+    - LP: #540231
+  * SUNRPC: Handle EINVAL error returns from the TCP connect operation
+    - LP: #540231
+  * s3cmci: s3cmci_card_present: Use no_detect to decide whether there is a
+    card detect pin
+    - LP: #540231
+  * rtc-coh901331: fix braces in resume code
+    - LP: #540231
+  * NFS: Fix an allocation-under-spinlock bug
+    - LP: #540231
+  * dm: free dm_io before bio_endio not after
+    - LP: #540231
+  * KVM: x86 emulator: Add group8 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Forbid modifying CS segment register by mov
+    instruction
+    - LP: #540231
+  * KVM: x86 emulator: Add group9 instruction decoding
+    - LP: #540231
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - LP: #540231
+  * sched: Fix sched_mv_power_savings for !SMT
+    - LP: #540231
+  * sched: Fix SMT scheduler regression in find_busiest_queue()
+    - LP: #540231
+  * sched: Don't use possibly stale sched_class
+    - LP: #540231
+  * x86, mm: Allow highmem user page tables to be disabled at boot time
+    - LP: #540231
+  * Linux 2.6.32.10
+    - LP: #540231
+  * drm/i915: give up on 8xx lid status
+    - LP: #540231
+  * drm/i915: Use a dmi quirk to skip a broken SDVO TV output.
+    - LP: #540231
+  * drm/ttm: handle OOM in ttm_tt_swapout
+    - LP: #540231
+  * drm/radeon/kms/atom: fix shr/shl ops
+    - LP: #540231
+  * Linux 2.6.32.10+drm33.1
+    - LP: #540231
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 19 Mar 2010 19:17:09 +0000
+
+linux (2.6.32-16.25) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * linux-tools -- move to Suggests: with explicit seeding
+    - LP: #534635
+
+  [ Tim Gardner ]
+
+  * [Config] CONFIG_HID=m
+
+  [ Upstream Kernel Changes ]
+
+  * (pre-stable) sched: Fix SMT scheduler regression in
+    find_busiest_queue()
+  * KVM: introduce kvm_vcpu_on_spin
+  * KVM: VMX: Add support for Pause-Loop Exiting
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 09 Mar 2010 14:13:51 +0000
+
+linux (2.6.32-16.24) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * armel -- perf userspace does not support arm
+  * ia64 -- libelf-dev/binutils-dev to not provide necessary libraries
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 06 Mar 2010 11:42:12 +0000
+
+linux (2.6.32-16.23) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: PM report driver and device suspend/resume times -- move config
+  * update to standards version 3.8.4.0
+  * printenv -- expose all of the package selectors
+  * source package -- cleanup source content control
+  * doc package -- ensure we do build package content on buildd
+  * lintian -- correct the address in the debian/copyright
+  * lintian -- update debhelper package version dependancy
+  * lintian -- fix ghostscript dependancy
+  * lintian -- add required misc:Depends
+  * lintian -- move our debhelper compat level to debian/compat
+  * perf -- build the kernel carried tools
+  * perf -- add linux-tools carrying the version switches and manuals
+  * SAUCE: fix up Kconfig for staging drivers
+  * [Config] enable NOUVEAU etc following drm backport
+  * update DRM to mainline v2.6.33
+  * [Config] Remove AppArmor config options that no longer exist (ports)
+  * [Config] updateportsconfigs following drm update
+
+  [ John Johansen ]
+
+  * ubuntu: AppArmor -- update to mainline 2010-03-04
+  * SAUCE: AppArmor: Reintroduce AppArmor 2.4 compatibility
+  * SAUCE: AppArmor: replace strim with strstrip for 2.6.32 kernels
+  * [Config] Remove AppArmor config options that no longer exist
+
+  [ Manoj Iyer ]
+
+  * ubuntu: rtl8192se -- version 2010-0115,0014
+    - LP: #530275
+  * [Config] added CONFIG_RTL8192SE module.
+    - LP: #530275
+
+  [ Tim Gardner ]
+
+  * [Config] Added vmw_pvscsi to d-i/scsi-modules
+    - LP: #531017
+  * [Upstream] netfilter: xt_recent: Add an entry reaper
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Fix popf emulation"
+  * Revert "KVM: x86 emulator: Check IOPL level during io instruction
+    emulation"
+  * Revert "KVM: x86 emulator: Add Virtual-8086 mode of emulation"
+  * Revert "KVM: fix memory access during x86 emulation."
+  * Add vlan (8021.Q) module package for d-i.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+  * [Upstream] docbook: need xmldoclinks for all doc types
+  * x86: set_personality_ia32() misses force_personality32
+  * lib: Introduce generic list_sort function
+  * drm/nv50: Implement ctxprog/state generation.
+  * drm/nv50: Remove redundant/incorrect ctxvals initialisation.
+  * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell
+    Inspiron 700m
+    - LP: #515246
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 05 Mar 2010 15:40:38 +0000
+
+linux (2.6.32-15.22) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT"
+  * Revert "SAUCE: PM report driver and device suspend/resume times."
+  * [Config] set CONFIG_SR_REPORT_TIME_LIMIT
+
+  [ Manoj Iyer ]
+
+  * SAUCE: PM report driver and device suspend/resume times.
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 02 Mar 2010 01:35:37 +0000
+
+linux (2.6.32-15.21) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "(pre-stable) drm/i915: Increase fb alignment to 64k"
+  * Revert "[Config] lenovo-sl-laptop -- enable"
+  * Revert "ubuntu: lenovo-sl-laptop -- git tip (b19a08f81f)"
+  * armel -- cramfs module will no longer be built
+  * d-i -- make all modules optional
+  * rename the debug packages to match archive standard
+    - LP: #527837
+  * lenovo-sl-laptop is no longer built
+
+  [ Colin Ian King ]
+
+  * Disable 4MB page tables for Atom, work around errata AAE44
+    - LP: #523112
+
+  [ Colin Watson ]
+
+  * ubuntu: dm-raid4-5: Depend on XOR_BLOCKS
+  * ubuntu: fsam7400: Depend on CHECK_SIGNATURE
+
+  [ Jesse Barnes ]
+
+  * SAUCE: drm/i915: don't change DRM configuration when releasing load
+    detect pipe
+    - LP: #488328
+
+  [ Loïc Minier ]
+
+  * [Config] armel Update versatile initrd configs
+    - LP: #524893
+  * SAUCE: [um] Don't use nx_enabled under UML
+    - LP: #524849
+
+  [ Manoj Iyer ]
+
+  * [Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT
+
+  [ Mario Limonciello ]
+
+  * SAUCE: v3 - Add Dell Business Class Netbook LED driver
+
+  [ Rafael J. Wysocki ]
+
+  * SAUCE: PM report driver and device suspend/resume times.
+
+  [ Surbhi Palande ]
+
+  * Revert "[Upstream] e1000e: enhance frame fragment detection"
+    - CVE-2009-4538
+  * Revert "[Upstream] e1000: enhance frame fragment detection"
+    - CVE-2009-4536
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CONFIG_LEDS_DELL_NETBOOKS=m
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow
+  * SAUCE: (pre-stable) netfilter: xt_recent: fix false match
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) eCryptfs: Add getattr function"
+  * Fix potential crash with sys_move_pages
+  * futex_lock_pi() key refcnt fix
+  * futex: Handle user space corruption gracefully
+  * futex: Handle futex value corruption gracefully
+  * Fix race in tty_fasync() properly
+  * hwmon: (w83781d) Request I/O ports individually for probing
+  * hwmon: (lm78) Request I/O ports individually for probing
+  * hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT
+  * ALSA: ctxfi - fix PTP address initialization
+  * drm/i915: disable hotplug detect before Ironlake CRT detect
+  * drm/i915: enable self-refresh on 965
+  * drm/i915: Disable SR when more than one pipe is enabled
+  * drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.
+  * drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list
+  * drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop
+  * drm/i915: Add MALATA PC-81005 to ACPI LID quirk list
+  * usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers.
+  * i2c-tiny-usb: Fix on big-endian systems
+  * drm/i915: handle FBC and self-refresh better
+  * drm/i915: Increase fb alignment to 64k
+  * drm/i915: Update write_domains on active list after flush.
+  * regulator: Fix display of null constraints for regulators
+  * ALSA: hda-intel: Avoid divide by zero crash
+  * CPUFREQ: Fix use after free of struct powernow_k8_data
+  * freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb
+  * cciss: Make cciss_seq_show handle holes in the h->drv[] array
+  * ioat: fix infinite timeout checking in ioat2_quiesce
+  * resource: add helpers for fetching rlimits
+  * fs/exec.c: restrict initial stack space expansion to rlimit
+  * cifs: fix length calculation for converted unicode readdir names
+  * NFS: Fix a reference leak in nfs_wb_cancel_page()
+  * NFS: Try to commit unstable writes in nfs_release_page()
+  * NFSv4: Don't allow posix locking against servers that don't support it
+  * NFSv4: Ensure that the NFSv4 locking can recover from stateid errors
+  * NFS: Fix an Oops when truncating a file
+  * NFS: Fix a umount race
+  * NFS: Fix a bug in nfs_fscache_release_page()
+  * NFS: Fix the mapping of the NFSERR_SERVERFAULT error
+  * md: fix 'degraded' calculation when starting a reshape.
+  * V4L/DVB: dvb-core: fix initialization of feeds list in demux filter
+  * Export the symbol of getboottime and mmonotonic_to_bootbased
+  * kvmclock: count total_sleep_time when updating guest clock
+  * KVM: PIT: control word is write-only
+  * tpm_infineon: fix suspend/resume handler for pnp_driver
+  * amd64_edac: Do not falsely trigger kerneloops
+  * netfilter: nf_conntrack: fix memory corruption with multiple namespaces
+  * netfilter: nf_conntrack: per netns nf_conntrack_cachep
+  * netfilter: nf_conntrack: restrict runtime expect hashsize modifications
+  * netfilter: xtables: compat out of scope fix
+  * netfilter: nf_conntrack: fix hash resizing with namespaces
+  * drm/i915: remove full registers dump debug
+  * drm/i915: add i915_lp_ring_sync helper
+  * drm/i915: Don't wait interruptible for possible plane buffer flush
+  * dasd: remove strings from s390dbf
+  * crypto: padlock-sha - Add import/export support
+  * wmi: Free the allocated acpi objects through wmi_get_event_data
+  * dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value
+  * /dev/mem: introduce size_inside_page()
+  * devmem: check vmalloc address on kmem read/write
+  * devmem: fix kmem write bug on memory holes
+  * SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead
+    of value 0.
+  * sh: Couple kernel and user write page perm bits for CONFIG_X2TLB
+  * ALSA: hda - use WARN_ON_ONCE() for zero-division detection
+  * dst: call cond_resched() in dst_gc_task()
+  * ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support
+  * befs: fix leak
+  * rtc-fm3130: add missing braces
+  * Call flush_dcache_page after PIO data transfers in libata-sff.c
+  * ahci: add Acer G725 to broken suspend list
+  * pktgen: Fix freezing problem
+  * x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt
+  * x86/amd-iommu: Fix deassignment of a device from the pt_domain
+  * x86: Re-get cfg_new in case reuse/move irq_desc
+  * Staging: fix rtl8187se compilation errors with mac80211
+  * ALSA: usb-audio - Avoid Oops after disconnect
+  * serial: 8250: add serial transmitter fully empty test
+  * sysfs: sysfs_sd_setattr set iattrs unconditionally
+  * class: Free the class private data in class_release
+  * USB: usbfs: only copy the actual data received
+  * USB: usbfs: properly clean up the as structure on error paths
+  * rtl8187: Add new device ID
+  * ACPI: Add NULL pointer check in acpi_bus_start
+  * ACPI: fix High cpu temperature with 2.6.32
+  * drm/radeon/kms: use udelay for short delays
+  * NFS: Too many GETATTR and ACCESS calls after direct I/O
+  * eCryptfs: Add getattr function
+  * b43: Fix throughput regression
+  * ath9k: Fix sequence numbers for PAE frames
+  * mac80211: Fix probe request filtering in IBSS mode
+  * iwlwifi: Fix to set correct ht configuration
+  * dm stripe: avoid divide by zero with invalid stripe count
+  * dm log: userspace fix overhead_size calcuations
+  * Linux 2.6.32.9
+  * sfc: Fix SFE4002 initialisation
+  * sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll()
+  * sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances
+  * (pre-stable) HID: handle joysticks with large number of buttons
+    - LP: #492056
+  * (pre-stable) HID: extend mask for BUTTON usage page
+    - LP: #492056
+  * PM: Measure device suspend and resume times
+  * e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+  * KVM: fix memory access during x86 emulation.
+    - CVE-2010-0306
+  * KVM: x86 emulator: Add Virtual-8086 mode of emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check IOPL level during io instruction emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Fix popf emulation
+    - CVE-2010-0306
+  * KVM: x86 emulator: Check CPL level during privilege instruction
+    emulation
+    - CVE-2010-0306
+  * Input: wacom - ensure the device is initialized properly upon resume
+  * Input: wacom - add defines for packet lengths of various devices
+  * Input: wacom - add support for new LCD tablets
+    - LP: #516777
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 01 Mar 2010 22:56:28 +0000
+
+linux (2.6.32-14.20) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebuild following the GCC update to match compiler for out of tree modules
+  * Revert "[Config] drbd -- enable"
+  * Revert "ubuntu: drbd -- version 8.3.1"
+  * SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU
+    - LP: #510937
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 19 Feb 2010 18:47:18 +0000
+
+linux (2.6.32-14.19) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * ensure we build the source package contents when enabled
+    - LP: #522308
+  * [Config] enable CONFIG_X86_MCE_XEON75XX
+  * SAUCE: AppArmor -- add linux/kref.h for struct kref
+  * [Config] enable CONFIG_HID_ORTEK
+  * enable udeb generation for arm versatile flavour
+    - LP: #522515
+
+  [ John Johansen ]
+
+  * ubuntu: AppArmor -- update to mainline 2010-02-18
+    - LP: #439560, #496110, #507069
+
+  [ Johnathon Harris ]
+
+  * SAUCE: HID: add support for Ortek WKB-2000
+    - LP: #405390
+
+  [ Upstream Kernel Changes ]
+
+  * tpm_tis: TPM_STS_DATA_EXPECT workaround
+    - LP: #490487
+  * x86, mce: Xeon75xx specific interface to get corrected memory error
+    information
+  * x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll
+  * x86, mce: Make xeon75xx memory driver dependent on PCI
+  * drm/edid: Unify detailed block parsing between base and extension
+    blocks
+    - LP: #500999
+  * (pre-stable) eCryptfs: Add getattr function
+    - LP: #390833
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 18 Feb 2010 19:22:02 +0000
+
+linux (2.6.32-13.18) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "enforcer -- make the enforcement configuration common"
+  * Revert "(pre-stable) Input: ALPS - add interleaved protocol support
+    (Dell E6x00 series)"
+  * Revert "(pre-stable) driver-core: fix devtmpfs crash on s390"
+  * Revert "(pre-stable) Driver-Core: devtmpfs - set root directory mode to
+    0755"
+  * Revert "SAUCE: Adds support for COMPAL JHL90 webcam"
+  * Revert "SAUCE: fix kernel oops in VirtualBox during paravirt patching"
+  * Revert "SAUCE: make fc transport removal of target configurable"
+  * enforcer -- make the enforcement configuration common
+  * getabis -- add preempt flavour to the list
+  * [Config] enforce DEVTMPFS options
+  * [Config] armel -- cleanup to-be builtin modules
+  * [Config] cleanup ports configs
+  * [Config] enable CRYPTO_GHASH_CLMUL_NI_INTEL
+    - LP: #485536
+  * add printdebian target to find branch target
+  * distclean -- do not remove debian.env
+  * [Config] generic-pae switch to M586TSC
+    - LP: #519448
+  * git-ubuntu-log -- commonise duplicated log handling
+  * git-ubuntu-log -- tighten up Bug: NNNN matching
+  * git-ubuntu-log -- sort the bug numbers
+
+  [ Chris Wilson ]
+
+  * (pre-stable) drm/i915: Increase fb alignment to 64k
+    - LP: #404064
+
+  [ Eric Miao ]
+
+  * arm -- enable ubuntu/ directory
+
+  [ Huang Ying ]
+
+  * SAUCE: crypto: ghash - Add PCLMULQDQ accelerated implementation
+  * SAUCE: crypto: ghash-intel - Fix building failure on x86_32
+
+  [ Loïc Minier ]
+
+  * [Config] cleanup preempt configuration
+  * [Config] versatile: Fix video output
+    - LP: #517594
+  * [Config] armel DEFAULT_MMAP_MIN_ADDR=32768
+  * [Config] Large update to armel/versatile
+  * [Config] versatile: Add RTC support
+  * [Config] armel: Enable NEON
+  * [Config] versatile: Builtin MMC support
+  * [Config] versatile Builtin SCSI controller
+  * [Config] armel Disable dma_cache_sync callers
+  * [Config] armel Disable asm/time.h users
+  * [Config] armel Disable out of range udelay()
+  * [Config] armel Disable flush_cache_range() users
+  * [Config] armel -- Enable ubuntu/ drivers
+
+  [ Steve Conklin ]
+
+  * SAUCE: drm/i915: Add display hotplug event on Ironlake
+  * SAUCE: drm/i915: Add ACPI OpRegion support for Ironlake
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Upstream]: oprofile/x86: add Xeon 7500 series support"
+  * Revert "Revert "[Bluetooth] Eliminate checks for impossible conditions
+    in IRQ handler""
+  * clockevent: Don't remove broadcast device when cpu is dead
+  * clockevents: Add missing include to pacify sparse
+  * ACPI: don't cond_resched if irq is disabled
+  * be2net: Add support for next generation of BladeEngine device.
+  * be2net: Add the new PCI IDs to PCI_DEVICE_TABLE.
+  * mpt2sas: New device SAS2208 support is added
+  * ar9170: Add support for D-Link DWA 160 A2
+  * powerpc/fsl: Add PCI device ids for new QoirQ chips
+  * davinci: dm646x: Add support for 3.x silicon revision
+  * Input: ALPS - add interleaved protocol support (Dell E6x00 series)
+  * Driver-Core: devtmpfs - set root directory mode to 0755
+  * driver-core: fix devtmpfs crash on s390
+  * vfs: get_sb_single() - do not pass options twice
+  * ALSA: hda - Add PCI IDs for Nvidia G2xx-series
+  * V4L/DVB (13569): smsusb: add autodetection support for five additional
+    Hauppauge USB IDs
+  * USB: mos7840: add device IDs for B&B electronics devices
+  * USB: ftdi_sio: add USB device ID's for B&B Electronics line
+  * V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134
+    SubVendor ID: 0x1043 Device ID: 0x4847)
+  * iTCO_wdt: Add support for Intel Ibex Peak
+  * atl1c:use common_task instead of reset_task and link_chg_task
+  * atl1e:disable NETIF_F_TSO6 for hardware limit
+  * V4L/DVB (13680a): DocBook/media: copy images after building HTML
+  * V4L/DVB (13680b): DocBook/media: create links for included sources
+  * netfilter: xtables: fix conntrack match v1 ipt-save output
+  * partitions: read whole sector with EFI GPT header
+  * partitions: use sector size for EFI GPT
+  * ALSA: ice1724 - Patch for suspend/resume for ESI Juli@
+  * sched: Fix isolcpus boot option
+  * sched: Fix missing sched tunable recalculation on cpu add/remove
+  * nohz: Prevent clocksource wrapping during idle
+  * nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups
+  * timers, init: Limit the number of per cpu calibration bootup messages
+  * PCI: Always set prefetchable base/limit upper32 registers
+  * iscsi class: modify handling of replacement timeout
+  * NFS: Revert default r/wsize behavior
+  * HID: fixup quirk for NCR devices
+  * scsi_devinfo: update Hitachi entries (v2)
+  * scsi_dh: create sysfs file, dh_state for all SCSI disk devices
+  * scsi_transport_fc: remove invalid BUG_ON
+  * lpfc: fix hang on SGI ia64 platform
+  * libfc: fix typo in retry check on received PRLI
+  * libfc: fix ddp in fc_fcp for 0 xid
+  * fcoe: remove redundant checking of netdev->netdev_ops
+  * libfc: Fix wrong scsi return status under FC_DATA_UNDRUN
+  * libfc: lport: fix minor documentation errors
+  * libfc: don't WARN_ON in lport_timeout for RESET state
+  * fcoe: initialize return value in fcoe_destroy
+  * libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data
+  * libfc: fix memory corruption caused by double frees and bad error
+    handling
+  * libfc: fix free of fc_rport_priv with timer pending
+  * libfc: remote port gets stuck in restart state without really
+    restarting
+  * fcoe, libfc: fix an libfc issue with queue ramp down in libfc
+  * fcoe: Fix checking san mac address
+  * fcoe: Fix getting san mac for VLAN interface
+  * qlge: Remove explicit setting of PCI Dev CTL reg.
+  * qlge: Set PCIE max read request size.
+  * qlge: Don't fail open when port is not initialized.
+  * qlge: Add handler for DCBX firmware event.
+  * qlge: Bonding fix for mode 6.
+  * PCI: AER: fix aer inject result in kernel oops
+  * DMI: allow omitting ident strings in DMI tables
+  * Input: i8042 - remove identification strings from DMI tables
+  * Input: i8042 - add Gigabyte M1022M to the noloop list
+  * Input: i8042 - add Dritek quirk for Acer Aspire 5610.
+  * ALSA: hda - select IbexPeak handler for Calpella
+  * ALSA: hda - Fix quirk for Maxdata obook4-1
+  * ALSA: hda - Add missing Line-Out and PCM switches as slave
+  * iTCO_wdt.c - cleanup chipset documentation
+  * iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC
+  * iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs
+  * ahci: disable SNotification capability for ich8
+  * ata_piix: fix MWDMA handling on PIIX3
+  * md: fix small irregularity with start_ro module parameter
+  * V4L/DVB (13826): uvcvideo: Fix controls blacklisting
+  * cio: fix double free in case of probe failure
+  * cio: dont panic in non-fatal conditions
+  * netiucv: displayed TX bytes value much too high
+  * ipc ns: fix memory leak (idr)
+  * ALSA: hda - Fix HP T5735 automute
+  * hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog
+  * UBI: fix memory leak in update path
+  * UBI: initialise update marker
+  * ASoC: fix a memory-leak in wm8903
+  * mac80211: check that ieee80211_set_power_mgmt only handles STA
+    interfaces.
+  * cfg80211: fix channel setting for wext
+  * KVM: S390: fix potential array overrun in intercept handling
+  * KVM: only allow one gsi per fd
+  * KVM: Fix race between APIC TMR and IRR
+  * KVM: MMU: bail out pagewalk on kvm_read_guest error
+  * KVM: x86: Fix host_mapping_level()
+  * KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks
+  * KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init()
+  * KVM: fix lock imbalance in kvm_*_irq_source_id()
+  * KVM: only clear irq_source_id if irqchip is present
+  * IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc()
+  * x86: Reenable TSC sync check at boot, even with NONSTOP_TSC
+  * ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
+    - LP: #516325
+  * iwlwifi: Fix throughput stall issue in HT mode for 5000
+  * fnctl: f_modown should call write_lock_irqsave/restore
+  * x86, msr/cpuid: Pass the number of minors when unregistering MSR and
+    CPUID drivers.
+  * Linux 2.6.32.7
+  * scsi_lib: Fix bug in completion of bidi commands
+  * mptsas: Fix issue with chain pools allocation on katmai
+  * mm: add new 'read_cache_page_gfp()' helper function
+  * drm/i915: Selectively enable self-reclaim
+  * firewire: ohci: fix crashes with TSB43AB23 on 64bit systems
+  * S390: fix single stepped svcs with TRACE_IRQFLAGS=y
+  * x86: Set hotpluggable nodes in nodes_possible_map
+  * x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG)
+  * libata: retry FS IOs even if it has failed with AC_ERR_INVALID
+  * zcrypt: Do not remove coprocessor for error 8/72
+  * dasd: fix possible NULL pointer errors
+  * ACPI: Add a generic API for _OSC -v2
+  * ACPI: Add platform-wide _OSC support.
+  * ACPI: fix OSC regression that caused aer and pciehp not to load
+  * ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes
+  * UBI: fix volume creation input checking
+  * e1000/e1000e: don't use small hardware rx buffers
+  * drm/i915: Reload hangcheck timer too for Ironlake
+  * Fix a leak in affs_fill_super()
+  * Fix failure exits in bfs_fill_super()
+  * fix oops in fs/9p late mount failure
+  * fix leak in romfs_fill_super()
+  * Fix remount races with symlink handling in affs
+  * fix affs parse_options()
+  * Fix failure exit in ipathfs
+  * mm: fix migratetype bug which slowed swapping
+  * FDPIC: Respect PT_GNU_STACK exec protection markings when creating
+    NOMMU stack
+  * Split 'flush_old_exec' into two functions
+  * sparc: TIF_ABI_PENDING bit removal
+  * x86: get rid of the insane TIF_ABI_PENDING bit
+  * Input: winbond-cir - remove dmesg spam
+  * x86: Disable HPET MSI on ATI SB700/SB800
+  * iwlwifi: set default aggregation frame count limit to 31
+  * drm/i915: only enable hotplug for detected outputs
+  * firewire: core: add_descriptor size check
+  * SECURITY: selinux, fix update_rlimit_cpu parameter
+  * regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints
+  * x86: Add Dell OptiPlex 760 reboot quirk
+    - LP: #488319
+  * x86: Add quirk for Intel DG45FC board to avoid low memory corruption
+  * x86/amd-iommu: Fix possible integer overflow
+  * clocksource: fix compilation if no GENERIC_TIME
+  * tcp: update the netstamp_needed counter when cloning sockets
+  * sky2: Fix oops in sky2_xmit_frame() after TX timeout
+  * net: restore ip source validation
+  * af_packet: Don't use skb after dev_queue_xmit()
+  * ax25: netrom: rose: Fix timer oopses
+  * KVM: allow userspace to adjust kvmclock offset
+  * oprofile/x86: add Xeon 7500 series support
+  * oprofile/x86: fix crash when profiling more than 28 events
+  * libata: retry link resume if necessary
+  * mm: percpu-vmap fix RCU list walking
+  * mm: purge fragmented percpu vmap blocks
+  * block: fix bio_add_page for non trivial merge_bvec_fn case
+  * Fix 'flush_old_exec()/setup_new_exec()' split
+  * random: drop weird m_time/a_time manipulation
+  * random: Remove unused inode variable
+  * block: fix bugs in bio-integrity mempool usage
+  * usb: r8a66597-hdc disable interrupts fix
+  * connector: Delete buggy notification code.
+  * be2net: Bug fix to support newer generation of BE ASIC
+  * be2net: Fix memset() arg ordering.
+  * mm: flush dcache before writing into page to avoid alias
+  * mac80211: fix NULL pointer dereference when ftrace is enabled
+  * imxfb: correct location of callbacks in suspend and resume
+  * mx3fb: some debug and initialisation fixes
+  * starfire: clean up properly if firmware loading fails
+  * kernel/cred.c: use kmem_cache_free
+  * uartlite: fix crash when using as console
+  * pktcdvd: removing device does not remove its sysfs dir
+  * ath9k: fix eeprom INI values override for 2GHz-only cards
+  * ath9k: fix beacon slot/buffer leak
+  * powerpc: TIF_ABI_PENDING bit removal
+  * NET: fix oops at bootime in sysctl code
+  * Linux 2.6.32.8
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 10 Feb 2010 18:56:52 +0000
+
+linux (2.6.32-12.17) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * restore linux-image prefix -- master
+  * enforce -- we require SELINUX enabled -- master
+  * enforce -- ensure APPARMOR is our default LSM -- master
+  * make doc package completely optional -- master
+  * make source package completely optional -- master
+  * make linux-libc-dev completly optional -- master
+  * convert package disable to a deps list -- master
+  * allow common headers to switch from indep to arch -- master
+  * convert binary package disable to a deps list -- master
+  * add configuration option for a full source build tree -- master
+  * add support for uImage kernels in package control scripts
+  * getabis -- cleanup and parameterise repository list -- master
+  * getabis -- move configuration to etc/getabi -- master
+  * kernelconfig -- move configuration to etc -- master
+  * rules -- make debian/debian.env master for branch name
+  * set the current branch name -- master
+  * pull back common debian.master files into debian -- master
+  * enforcer -- make the enforcement configuration common
+  * insert-changes -- correctly link to debian/rules in DROOT
+
+  [ Colin Watson ]
+
+  * future-proof ddeb handling against buildd changes
+
+  [ Eric Miao ]
+
+  * SAUCE: Make CONFIG_{OMNIBOOK, AVERATEC_5100P, PACKARDBELL_E5} depend on
+    X86
+
+  [ Loïc Minier ]
+
+  * Add modules.builtin.bin to prerm rm list
+    - LP: #516584
+
+  [ Tim Gardner ]
+
+  * [Config] Implement the amd64 preempt flavour
+
+  [ Upstream Kernel Changes ]
+
+  * syslog: distinguish between /proc/kmsg and syscalls
+    - LP: #515623
+  * sfc: Fix polling for slow MCDI operations
+  * sfc: Fix conditions for MDIO self-test
+  * sfc: QT202x: Remove unreliable MMD check at initialisation
+  * sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer
+  * sfc: Use fixed-size buffers for MCDI NVRAM requests
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 05 Feb 2010 07:09:31 +0000
+
+linux (2.6.32-12.16) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: acpi battery -- delay first lookup of the battery until
+    first use"
+  * SAUCE: acpi battery -- move first lookup asynchronous
+    - LP: #507211
+  * [Config] update configs to cleanup generic configs
+  * [Config] disable CONFIG_X86_CPU_DEBUG for amd64
+  * [Config] enable USER_NS
+    - LP: #480739, #509808
+
+  [ Heiko Carstens ]
+
+  * (pre-stable) driver-core: fix devtmpfs crash on s390
+    - LP: #512370
+
+  [ John Johansen ]
+
+  * [Config] for server and virtual flavours make CONFIG_SCSI_SYM53C8XX_2=y
+    - LP: #494565
+  * [Config] VIRTIO=y for server/virtual flavours
+    - LP: #494565
+
+  [ Kay Sievers ]
+
+  * (pre-stable) Driver-Core: devtmpfs - set root directory mode to 0755
+    - LP: #512370
+
+  [ Kees Cook ]
+
+  * SAUCE: x86: brk away from exec rand area
+    - LP: #452175
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] e1000: enhance frame fragment detection
+    - CVE-2009-4536
+  * [Upstream] e1000e: enhance frame fragment detection
+    - CVE-2009-4538
+
+  [ Sebastian Kapfer ]
+
+  * (pre-stable) Input: ALPS - add interleaved protocol support (Dell E6x00
+    series)
+    - LP: #296610
+
+  [ Upstream Kernel Changes ]
+
+  * inotify: do not reuse watch descriptors
+    - LP: #485556
+  * inotify: only warn once for inotify problems
+  * revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC
+    Framebuffer"
+  * memcg: ensure list is empty at rmdir
+  * drm/i915: remove loop in Ironlake interrupt handler
+  * block: Fix incorrect reporting of partition alignment
+  * x86, mce: Thermal monitoring depends on APIC being enabled
+  * futexes: Remove rw parameter from get_futex_key()
+  * page allocator: update NR_FREE_PAGES only when necessary
+  * x86, apic: use physical mode for IBM summit platforms
+  * edac: i5000_edac critical fix panic out of bounds
+  * x86: SGI UV: Fix mapping of MMIO registers
+  * mfd: WM835x GPIO direction register is not locked
+  * mfd: Correct WM835x ISINK ramp time defines
+  * ALSA: hda - Fix missing capture mixer for ALC861/660 codecs
+  * V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned.
+  * reiserfs: truncate blocks not used by a write
+  * HID: add device IDs for new model of Apple Wireless Keyboard
+  * PCI/cardbus: Add a fixup hook and fix powerpc
+  * Input: pmouse - move Sentelic probe down the list
+  * asus-laptop: add Lenovo SL hotkey support
+  * sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
+  * sparc64: Fix NMI programming when perf events are active.
+  * sparc64: Fix Niagara2 perf event handling.
+  * i2c: Do not use device name after device_unregister
+  * i2c/pca: Don't use *_interruptible
+  * serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device
+  * sched: Fix task priority bug
+  * vfs: Fix vmtruncate() regression
+  * Linux 2.6.32.5
+  * x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers
+  * V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges.
+  * Staging: asus_oled: fix oops in 2.6.32.2
+  * Staging: hv: fix smp problems in the hyperv core code
+  * tty: fix race in tty_fasync
+  * ecryptfs: use after free
+  * ecryptfs: initialize private persistent file before dereferencing
+    pointer
+  * nozomi: quick fix for the close/close bug
+  * serial: 8250_pnp: use wildcard for serial Wacom tablets
+  * usb: serial: fix memory leak in generic driver
+  * USB: fix bitmask merge error
+  * USB: Don't use GFP_KERNEL while we cannot reset a storage device
+  * USB: EHCI: fix handling of unusual interrupt intervals
+  * USB: EHCI & UHCI: fix race between root-hub suspend and port resume
+  * USB: add missing delay during remote wakeup
+  * USB: add speed values for USB 3.0 and wireless controllers
+  * ACPI: EC: Accelerate query execution
+  * ACPI: EC: Add wait for irq storm
+  * SCSI: enclosure: fix oops while iterating enclosure_status array
+  * drm/i915: Read the response after issuing DDC bus switch command
+  * drm/i915: try another possible DDC bus for the SDVO device with
+    multiple outputs
+  * block: bdev_stack_limits wrapper
+  * DM: Fix device mapper topology stacking
+  * x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled
+  * USB: fix usbstorage for 2770:915d delivers no FAT
+  * vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE
+  * perf timechart: Use tid not pid for COMM change
+  * perf events: Dont report side-band events on each cpu for
+    per-task-per-cpu events
+  * perf: Honour event state for aux stream data
+  * Linux 2.6.32.6
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 27 Jan 2010 16:40:23 +0000
+
+linux (2.6.32-11.15) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "(pre-stable) drm/radeon/kms: fix crtc vblank update for r600"
+  * Revert "(pre-stable) sched: Fix balance vs hotplug race"
+  * Revert "[Upstream] acerhdf: Limit modalias matching to supported
+    boards"
+  * Revert "[Upstream] mmc: prevent dangling block device from accessing
+    stale queues"
+  * Revert "SAUCE: Fix nx_enable reporting"
+  * Revert "SAUCE: [x86] fix report of cs-limit nx-emulation"
+  * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32"
+  * SAUCE: i915 -- disable powersave by default
+    - LP: #492392
+
+  [ Kees Cook ]
+
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+
+  [ Tim Gardner ]
+
+  * [Upstream] b43: Declare all possible firmware files.
+    - LP: #488636
+  * [Config] updateconfigs after adding pvscsi
+    - LP: #497156
+  * [Config] CONFIG_BT=m
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu
+    for pre-Pentium"
+  * SCSI: ipr: fix EEH recovery
+  * SCSI: qla2xxx: dpc thread can execute before scsi host has been added
+  * SCSI: st: fix mdata->page_order handling
+  * SCSI: fc class: fix fc_transport_init error handling
+  * sched: Fix task_hot() test order
+  * x86, cpuid: Add "volatile" to asm in native_cpuid()
+  * sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE
+  * clockevents: Prevent clockevent_devices list corruption on cpu hotplug
+  * pata_hpt3x2n: fix clock turnaround
+  * pata_cmd64x: fix overclocking of UDMA0-2 modes
+  * ASoC: wm8974: fix a wrong bit definition
+  * sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer
+  * ALSA: hda - Fix missing capsrc_nids for ALC88x
+  * acerhdf: limit modalias matching to supported
+    - LP: #435958
+  * ACPI: EC: Fix MSI DMI detection
+  * ACPI: Use the return result of ACPI lid notifier chain correctly
+  * powerpc: Handle VSX alignment faults correctly in little-endian mode
+  * ASoC: Do not write to invalid registers on the wm9712.
+  * drm/radeon: fix build on 64-bit with some compilers.
+  * USB: emi62: fix crash when trying to load EMI 6|2 firmware
+  * USB: option: support hi speed for modem Haier CE100
+  * USB: Fix a bug on appledisplay.c regarding signedness
+  * USB: musb: gadget_ep0: avoid SetupEnd interrupt
+  * Bluetooth: Prevent ill-timed autosuspend in USB driver
+  * USB: rename usb_configure_device
+  * USB: fix bugs in usb_(de)authorize_device
+  * drivers/net/usb: Correct code taking the size of a pointer
+  * x86: SGI UV: Fix writes to led registers on remote uv hubs
+  * md: Fix unfortunate interaction with evms
+  * dma: at_hdmac: correct incompatible type for argument 1 of
+    'spin_lock_bh'
+  * dma-debug: Do not add notifier when dma debugging is disabled.
+  * dma-debug: Fix bug causing build warning
+  * cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS
+    referrals
+  * x86/amd-iommu: Fix initialization failure panic
+  * ioat3: fix p-disabled q-continuation
+  * ioat2,3: put channel hardware in known state at init
+  * KVM: MMU: remove prefault from invlpg handler
+  * KVM: LAPIC: make sure IRR bitmap is scanned after vm load
+  * Libertas: fix buffer overflow in lbs_get_essid()
+  * iwmc3200wifi: fix array out-of-boundary access
+  * mac80211: fix propagation of failed hardware reconfigurations
+  * mac80211: fix WMM AP settings application
+  * mac80211: Fix IBSS merge
+  * cfg80211: fix race between deauth and assoc response
+  * ath5k: fix SWI calibration interrupt storm
+  * ath9k: wake hardware for interface IBSS/AP/Mesh removal
+  * ath9k: Fix TX queue draining
+  * ath9k: fix missed error codes in the tx status check
+  * ath9k: wake hardware during AMPDU TX actions
+  * ath9k: fix suspend by waking device prior to stop
+  * ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on
+    64-bit
+  * ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value
+    in 0x4054
+  * iwl3945: disable power save
+  * iwl3945: fix panic in iwl3945 driver
+  * iwlwifi: fix EEPROM/OTP reading endian annotations and a bug
+  * iwlwifi: fix more eeprom endian bugs
+  * iwlwifi: fix 40MHz operation setting on cards that do not allow it
+  * mac80211: fix race with suspend and dynamic_ps_disable_work
+  * NOMMU: Optimise away the {dac_,}mmap_min_addr tests
+  * 'sysctl_max_map_count' should be non-negative
+  * kernel/sysctl.c: fix the incomplete part of
+    sysctl_max_map_count-should-be-non-negative.patch
+  * V4L/DVB (13596): ov511.c typo: lock => unlock
+  * x86/ptrace: make genregs[32]_get/set more robust
+  * memcg: avoid oom-killing innocent task in case of use_hierarchy
+  * e100: Fix broken cbs accounting due to missing memset.
+  * ipv6: reassembly: use seperate reassembly queues for conntrack and
+    local delivery
+  * netfilter: fix crashes in bridge netfilter caused by fragment jumps
+  * hwmon: (sht15) Off-by-one error in array index + incorrect constants
+  * b43: avoid PPC fault during resume
+  * Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture
+    support
+  * sched: Fix balance vs hotplug race
+  * drm/radeon/kms: fix crtc vblank update for r600
+  * drm: disable all the possible outputs/crtcs before entering KMS mode
+  * S390: dasd: support DIAG access for read-only devices
+  * xen: fix is_disconnected_device/exists_disconnected_device
+  * xen: improvement to wait_for_devices()
+  * xen: wait up to 5 minutes for device connetion
+  * orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled
+  * udf: Try harder when looking for VAT inode
+  * Add unlocked version of inode_add_bytes() function
+  * quota: decouple fs reserved space from quota reservation
+  * ext4: Convert to generic reserved quota's space management.
+  * ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
+  * x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus
+  * cpumask: use modern cpumask style in drivers/edac/amd64_edac.c
+  * amd64_edac: unify MCGCTL ECC switching
+  * x86, msr: Add support for non-contiguous cpumasks
+  * x86, msr: msrs_alloc/free for CONFIG_SMP=n
+  * amd64_edac: fix driver instance freeing
+  * amd64_edac: make driver loading more robust
+  * amd64_edac: fix forcing module load/unload
+  * sched: Sched_rt_periodic_timer vs cpu hotplug
+  * ext4: Update documentation to correct the inode_readahead_blks option
+    name
+  * lguest: fix bug in setting guest GDT entry
+  * vmscan: do not evict inactive pages when skipping an active list scan
+  * ksm: fix mlockfreed to munlocked
+  * rt2x00: Disable powersaving for rt61pci and rt2800pci.
+  * generic_permission: MAY_OPEN is not write access
+  * Linux 2.6.32.3
+  * untangle the do_mremap() mess
+  * fasync: split 'fasync_helper()' into separate add/remove functions
+  * ASoC: fix params_rate() macro use in several codecs
+  * modules: Skip empty sections when exporting section notes
+  * exofs: simple_write_end does not mark_inode_dirty
+  * nfsd: make sure data is on disk before calling ->fsync
+  * sunrpc: fix peername failed on closed listener
+  * SUNRPC: Fix up an error return value in
+    gss_import_sec_context_kerberos()
+  * SUNRPC: Fix the return value in gss_import_sec_context()
+  * sunrpc: on successful gss error pipe write, don't return error
+  * drm/i915: Update LVDS connector status when receiving ACPI LID event
+  * drm/i915: fix order of fence release wrt flushing
+  * drm/i915: Permit pinning whilst the device is 'suspended'
+  * drm: remove address mask param for drm_pci_alloc()
+  * drm/i915: Enable/disable the dithering for LVDS based on VBT setting
+  * drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in
+    pipeconf on Ironlake
+  * drm/i915: Select the correct BPC for LVDS on Ironlake
+  * drm/i915: fix unused var
+  * rtc_cmos: convert shutdown to new pnp_driver->shutdown
+  * drivers/cpuidle/governors/menu.c: fix undefined reference to
+    `__udivdi3'
+  * cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput()
+  * lib/rational.c needs module.h
+  * dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with
+    DMA_FROM_DEVICE and
+  * kernel/signal.c: fix kernel information leak with print-fatal-signals=1
+  * mmc_block: add dev_t initialization check
+  * mmc_block: fix probe error cleanup bug
+  * mmc_block: fix queue cleanup
+  * ALSA: hda - Fix ALC861-VD capture source mixer
+  * ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense
+    blacklist
+  * ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2
+    - LP: #498863
+  * ASoC: Fix WM8350 DSP mode B configuration
+  * netfilter: ebtables: enforce CAP_NET_ADMIN
+  * netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq()
+  * hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs
+  * hwmon: (adt7462) Fix pin 28 monitoring
+  * quota: Fix dquot_transfer for filesystems different from ext4
+  * xen: fix hang on suspend.
+  * iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr
+  * ath5k: Fix eeprom checksum check for custom sized eeproms
+  * cfg80211: fix syntax error on user regulatory hints
+  * iwl: off by one bug
+  * mac80211: add missing sanity checks for action frames
+  * drm/i915: remove render reclock support
+  * libertas: Remove carrier signaling from the scan code
+  * kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr
+  * mac80211: fix skb buffering issue (and fixes to that)
+  * fix braindamage in audit_tree.c untag_chunk()
+  * fix more leaks in audit_tree.c tag_chunk()
+  * module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y
+  * ipv6: skb_dst() can be NULL in ipv6_hop_jumbo().
+  * agp/intel-agp: Clear entire GTT on startup
+  * Linux 2.6.32.4
+  * ethtool: Add reset operation
+  * gro: Name the GRO result enumeration type
+  * gro: Change all receive functions to return GRO result codes
+  * sfc: 10Xpress: Initialise pause advertising flags
+  * sfc: 10Xpress: Report support for pause frames
+  * sfc: Remove redundant header gmii.h
+  * sfc: Remove redundant hardware initialisation
+  * sfc: Rename Falcon-specific board code and types
+  * sfc: Remove boards.h, moving last remaining declaration to falcon.h
+  * sfc: Remove versioned bitfield macros
+  * sfc: Move RX data FIFO thresholds out of struct efx_nic_type
+  * sfc: Update hardware definitions for Siena
+  * sfc: Rename register I/O header and functions used by both Falcon and
+    Siena
+  * sfc: Eliminate indirect lookups of queue size constants
+  * sfc: Define DMA address mask explicitly in terms of descriptor field
+    width
+  * sfc: Move all TX DMA length limiting into tx.c
+  * sfc: Change order of device removal to reverse of probe order
+  * sfc: Remove declarations of nonexistent functions
+  * sfc: Move efx_xmit_done() declaration into correct stanza
+  * sfc: Move shared members of struct falcon_nic_data into struct efx_nic
+  * sfc: Maintain interrupt moderation values in ticks, not microseconds
+  * sfc: Removed kernel-doc for nonexistent member of efx_phy_operations
+  * sfc: Remove pointless abstraction of memory BAR number
+  * sfc: Remove incorrect assertion from efx_pci_remove_main()
+  * sfc: Remove unnecessary tests of efx->membase
+  * sfc: Move MTD probe after netdev registration and name allocation
+  * sfc: Remove unused code for non-autoneg speed/duplex switching
+  * sfc: Rename 'xfp' file and functions to reflect reality
+  * sfc: Really allow RX checksum offload to be disabled
+  * sfc: Feed GRO result into RX allocation policy and interrupt moderation
+  * sfc: Enable heuristic selection between page and skb RX buffers
+  * sfc: Remove pointless abstraction of memory BAR number (2)
+  * sfc: Remove redundant gotos from __efx_rx_packet()
+  * sfc: Remove ridiculously paranoid assertions
+  * sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro()
+  * sfc: Record RX queue number on GRO path
+  * sfc: SFT9001: Reset LED configuration correctly after blinking
+  * sfc: Use a single blink implementation
+  * sfc: Rename efx_board::init_leds to init_phy and use for SFN4111T
+  * sfc: Make board information explicitly Falcon-specific
+  * sfc: Move definition of struct falcon_nic_data into falcon.h
+  * sfc: Move struct falcon_board into struct falcon_nic_data
+  * sfc: Move all I2C stuff into struct falcon_board
+  * sfc: Gather link state fields in struct efx_nic into new struct
+    efx_link_state
+  * sfc: Remove unnecessary casts to struct sk_buff *
+  * sfc: Remove redundant efx_xmit() function
+  * sfc: Combine high-level header files
+  * sfc: Log interrupt and reset type names, not numbers
+  * sfc: Fix descriptor cache sizes
+  * sfc: Treat all MAC registers as 128-bit
+  * sfc: Strengthen EFX_ASSERT_RESET_SERIALISED
+  * sfc: Comment corrections
+  * sfc: Remove unused constant
+  * sfc: Clean up struct falcon_board and struct falcon_board_data
+  * sfc: Fix bugs in RX queue flushing
+  * sfc: Remove unused function efx_flush_queues()
+  * sfc: Only switch Falcon MAC clocks as necessary
+  * sfc: Hold MAC lock for longer in efx_init_port()
+  * sfc: Split MAC stats DMA initiation and completion
+  * sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c
+  * sfc: Simplify XMAC link polling
+  * sfc: Change MAC promiscuity and multicast hash at the same time
+  * sfc: Move inline comment into kernel-doc
+  * sfc: Do not set net_device::trans_start in self-test
+  * sfc: Simplify PHY polling
+  * sfc: QT202x: Reset before reading PHY id
+  * sfc: Replace MDIO spinlock with mutex
+  * sfc: Always start Falcon using the XMAC
+  * sfc: Limit some hardware workarounds to Falcon
+  * sfc: Remove EFX_WORKAROUND_9141 macro
+  * sfc: Remove another unused workaround macro
+  * sfc: Remove some redundant whitespace
+  * sfc: Decouple NIC revision number from Falcon PCI revision number
+  * sfc: Move descriptor cache base addresses to struct efx_nic_type
+  * sfc: Clean up RX event handling
+  * sfc: Remove redundant writes to INT_ADR_KER
+  * sfc: Remove duplicate hardware structure definitions
+  * sfc: Turn pause frame generation on and off at the MAC, not the RX FIFO
+  * sfc: Move Falcon NIC operations to efx_nic_type
+  * sfc: Refactor link configuration
+  * sfc: Generalise link state monitoring
+  * sfc: Add power-management and wake-on-LAN support
+  * sfc: Implement ethtool reset operation
+  * sfc: Add efx_nic_type operation for register self-test
+  * sfc: Add efx_nic_type operation for NVRAM self-test
+  * sfc: Add efx_nic_type operation for identity LED control
+  * sfc: Separate shared NIC code from Falcon-specific and rename
+    accordingly
+  * sfc: Fold falcon_probe_nic_variant() into falcon_probe_nic()
+  * sfc: Extend loopback mode enumeration
+  * sfc: Remove static PHY data and enumerations
+  * sfc: Extend MTD driver for use with new NICs
+  * sfc: Allow for additional checksum offload features
+  * sfc: Rename falcon.h to nic.h
+  * sfc: Move shared NIC code from falcon.c to new source file nic.c
+  * sfc: Add firmware protocol definitions (MCDI)
+  * sfc: Add support for SFC9000 family (1)
+  * sfc: Add support for SFC9000 family (2)
+  * sfc: Implement TSO for TCP/IPv6
+  * sfc: Update version, copyright dates, authors
+  * drivers/net/sfc: Correct code taking the size of a pointer
+  * sfc: Move PHY software state initialisation from init() into probe()
+  * sfc: Include XGXS in XMAC link status check except in XGMII loopback
+  * sfc: Fix DMA mapping cleanup in case of an error in TSO
+  * sfc: QT2025C: Work around PHY bug
+  * sfc: QT2025C: Switch into self-configure mode when not in loopback
+  * sfc: QT2025C: Work around PHY firmware initialisation bug
+  * sfc: QT2025C: Add error message for suspected bad SFP+ cables
+  * sfc: Disable TX descriptor prefetch watchdog
+  * [SCSI] vmw_pvscsi: SCSI driver for VMware's virtual HBA.
+    - LP: #497156
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 19 Jan 2010 16:12:47 +0000
+
+linux (2.6.32-10.14) lucid; urgency=low
+
+  [ Alex Deucher ]
+
+  * SAUCE: drm/radeon/kms: fix LVDS setup on r4xx
+    - LP: #493795
+
+  [ Andy Whitcroft ]
+
+  * Revert "(pre-stable) acpi: Use the ARB_DISABLE for the CPU which model
+    id is less than 0x0f."
+  * config-check -- ensure the checks get run at build time
+  * config-check -- check the processed config during updateconfigs
+  * config-check -- CONFIG_SECCOMP may not be present
+  * TUN is now built in ignore
+  * SAUCE: acpi battery -- delay first lookup of the battery until first
+    use
+  * SAUCE: async_populate_rootfs: move rootfs init earlier
+  * ubuntu: AppArmor -- update to mainline 2010-01-06
+  * SAUCE: move RLIMIT_CORE pipe dumper marker to 1
+    - LP: #498525
+
+  [ Dave Airlie ]
+
+  * (pre-stable) drm/radeon/kms: fix crtc vblank update for r600
+
+  [ Leann Ogasawara ]
+
+  * Add asix to nic-usb-modules file
+    - LP: #499785
+
+  [ Peter Zijlstra ]
+
+  * (pre-stable) sched: Fix balance vs hotplug race
+
+  [ Tim Gardner ]
+
+  * [Config] Enable CONFIG_FUNCTION_TRACER
+    - LP: #497989
+  * [Config] Drop lpia from getabis
+  * [Config] Build in TUN/TAP driver
+    - LP: #499491
+  * [Config] DH_COMPAT=5
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "(pre-stable) drm/i915: Avoid NULL dereference with
+    component_only tv_modes"
+  * Revert "(pre-stable) drm/i915: Fix sync to vblank when VGA output is
+    turned off"
+  * USB: usb-storage: fix bug in fill_inquiry
+  * USB: option: add pid for ZTE
+  * firewire: ohci: handle receive packets with a data length of zero
+  * rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling
+    of ->completed counter
+  * rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed
+    counter
+  * rcu: Fix note_new_gpnum() uses of ->gpnum
+  * rcu: Remove inline from forward-referenced functions
+  * perf_event: Fix invalid type in ioctl definition
+  * perf_event: Initialize data.period in perf_swevent_hrtimer()
+  * perf: Don't free perf_mmap_data until work has been done
+  * PM / Runtime: Fix lockdep warning in __pm_runtime_set_status()
+  * sched: Check for an idle shared cache in select_task_rq_fair()
+  * sched: Fix affinity logic in select_task_rq_fair()
+  * sched: Rate-limit newidle
+  * sched: Fix and clean up rate-limit newidle code
+  * x86/amd-iommu: attach devices to pre-allocated domains early
+  * x86/amd-iommu: un__init iommu_setup_msi
+  * x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking
+    up the PCI tree
+  * x86: Fix iommu=nodac parameter handling
+  * x86: GART: pci-gart_64.c: Use correct length in strncmp
+  * x86: ASUS P4S800 reboot=bios quirk
+    - LP: #366682
+  * x86, apic: Enable lapic nmi watchdog on AMD Family 11h
+  * ssb: Fix range check in sprom write
+  * ath5k: allow setting txpower to 0
+  * ath5k: enable EEPROM checksum check
+  * hrtimer: Fix /proc/timer_list regression
+  * ALSA: hrtimer - Fix lock-up
+  * ALSA: hda - Terradici HDA controllers does not support 64-bit mode
+  * KVM: x86 emulator: limit instructions to 15 bytes
+  * KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c
+  * KVM: s390: Make psw available on all exits, not just a subset
+  * KVM: fix irq_source_id size verification
+  * KVM: x86: include pvclock MSRs in msrs_to_save
+  * x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage
+  * x86: Use -maccumulate-outgoing-args for sane mcount prologues
+  * x86, mce: don't restart timer if disabled
+  * x86/mce: Set up timer unconditionally
+  * x86: SGI UV: Fix BAU initialization
+  * x86: Fix duplicated UV BAU interrupt vector
+  * x86: Add new Intel CPU cache size descriptors
+  * x86: Fix typo in Intel CPU cache size descriptor
+  * pata_hpt{37x|3x2n}: fix timing register masks (take 2)
+  * s390: clear high-order bits of registers after sam64
+  * V4L/DVB: Fix test in copy_reg_bits()
+  * bsdacct: fix uid/gid misreporting
+  * UBI: flush wl before clearing update marker
+  * jbd2: don't wipe the journal on a failed journal checksum
+  * USB: xhci: Add correct email and files to MAINTAINERS entry.
+  * USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again
+  * USB: option.c: add support for D-Link DWM-162-U5
+  * USB: usbtmc: repeat usb_bulk_msg until whole message is transfered
+  * USB: usb-storage: add BAD_SENSE flag
+  * USB: Close usb_find_interface race v3
+  * pxa/em-x270: fix usb hub power up/reset sequence
+  * hfs: fix a potential buffer overflow
+  * SUNRPC: IS_ERR/PTR_ERR confusion
+  * NFS: Fix nfs_migrate_page()
+  * md/bitmap: protect against bitmap removal while being updated.
+  * futex: Take mmap_sem for get_user_pages in fault_in_user_writeable
+  * devpts_get_tty() should validate inode
+  * debugfs: fix create mutex racy fops and private data
+  * Driver core: fix race in dev_driver_string
+  * Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN
+  * mac80211: Fix bug in computing crc over dynamic IEs in beacon
+  * mac80211: Fixed bug in mesh portal paths
+  * mac80211: Revert 'Use correct sign for mesh active path refresh'
+  * mac80211: fix scan abort sanity checks
+  * wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC
+  * rtl8187: Fix wrong rfkill switch mask for some models
+  * x86: Fix bogus warning in apic_noop.apic_write()
+  * mm: hugetlb: fix hugepage memory leak in mincore()
+  * mm: hugetlb: fix hugepage memory leak in walk_page_range()
+  * powerpc/windfarm: Add detection for second cpu pump
+  * powerpc/therm_adt746x: Record pwm invert bit at module load time]
+  * powerpc: Fix usage of 64-bit instruction in 32-bit altivec code
+  * drm/radeon/kms: Add quirk for HIS X1300 board
+  * drm/radeon/kms: handle vblanks properly with dpms on
+  * drm/radeon/kms: fix legacy crtc2 dpms
+  * drm/radeon/kms: fix vram setup on rs600
+  * drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size
+  * drm/ttm: Fix build failure due to missing struct page
+  * drm/i915: Set the error code after failing to insert new offset into mm
+    ht.
+  * drm/i915: Add the missing clonemask for display port on Ironlake
+  * xen/xenbus: make DEVICE_ATTR()s static
+  * xen: re-register runstate area earlier on resume.
+  * xen: restore runstate_info even if !have_vcpu_info_placement
+  * xen: correctly restore pfn_to_mfn_list_list after resume
+  * xen: register timer interrupt with IRQF_TIMER
+  * xen: register runstate on secondary CPUs
+  * xen: don't call dpm_resume_noirq() with interrupts disabled.
+  * xen: register runstate info for boot CPU early
+  * xen: call clock resume notifier on all CPUs
+  * xen: improve error handling in do_suspend.
+  * xen: don't leak IRQs over suspend/resume.
+  * xen: use iret for return from 64b kernel to 32b usermode
+  * xen: explicitly create/destroy stop_machine workqueues outside
+    suspend/resume region.
+  * Xen balloon: fix totalram_pages counting.
+  * xen: try harder to balloon up under memory pressure.
+  * dm exception store: free tmp_store on persistent flag error
+  * dm snapshot: only take lock for statustype info not table
+  * dm crypt: move private iv fields to structs
+  * dm crypt: restructure essiv error path
+  * dm: avoid _hash_lock deadlock
+  * dm snapshot: cope with chunk size larger than origin
+  * dm crypt: separate essiv allocation from initialisation
+  * dm crypt: make wipe message also wipe essiv key
+  * slc90e66: fix UDMA handling
+  * tcp: Stalling connections: Fix timeout calculation routine
+  * ip_fragment: also adjust skb->truesize for packets not owned by a
+    socket
+  * b44 WOL setup: one-bit-off stack corruption kernel panic fix
+  * sparc64: Don't specify IRQF_SHARED for LDC interrupts.
+  * sparc64: Fix overly strict range type matching for PCI devices.
+  * sparc64: Fix stack debugging IRQ stack regression.
+  * sparc: Set UTS_MACHINE correctly.
+  * b43legacy: avoid PPC fault during resume
+  * tracing: Fix event format export
+  * ath9k: Fix TX hang poll routine
+  * ath9k: fix processing of TX PS null data frames
+  * ath9k: Fix maximum tx fifo settings for single stream devices
+  * ath9k: fix tx status reporting
+  * mac80211: Fix dynamic power save for scanning.
+  * drm/i915: Fix sync to vblank when VGA output is turned off
+  * memcg: fix memory.memsw.usage_in_bytes for root cgroup
+  * thinkpad-acpi: fix default brightness_mode for R50e/R51
+  * thinkpad-acpi: preserve rfkill state across suspend/resume
+  * ipw2100: fix rebooting hang with driver loaded
+  * matroxfb: fix problems with display stability
+  * acerhdf: add new BIOS versions
+  * asus-laptop: change light sens default values.
+  * vmalloc: conditionalize build of pcpu_get_vm_areas()
+  * ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f.
+  * net: Fix userspace RTM_NEWLINK notifications.
+  * ext3: Fix data / filesystem corruption when write fails to copy data
+  * V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added.
+  * bcm63xx_enet: fix compilation failure after get_stats_count removal
+  * x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value
+  * drm/i915: Avoid NULL dereference with component_only tv_modes
+  * drm/i915: PineView only has LVDS and CRT ports
+  * drm/i915: Fix LVDS stability issue on Ironlake
+  * mm: sigbus instead of abusing oom
+  * ipvs: zero usvc and udest
+  * jffs2: Fix long-standing bug with symlink garbage collection.
+  * intel-iommu: Detect DMAR in hyperspace at probe time.
+  * intel-iommu: Apply BIOS sanity checks for interrupt remapping too.
+  * intel-iommu: Check for an RMRR which ends before it starts.
+  * intel-iommu: Fix oops with intel_iommu=igfx_off
+  * intel-iommu: ignore page table validation in pass through mode
+  * netfilter: xtables: document minimal required version
+  * perf_event: Fix incorrect range check on cpu number
+  * implement early_io{re,un}map for ia64
+  * Linux 2.6.32.2
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 07 Jan 2010 15:28:43 +0000
+
+linux (2.6.32-9.13) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] enable CONFIG_B43_PHY_LP
+    - LP: #493059
+  * include modules.builtin in the binary debs
+  * config-check -- add a configuration enforcer
+  * config-check -- add a unit-test suite to the checker
+  * [Config] Enable CONFIG_SYN_COOKIES for versatile
+  * [Config] Enable CONFIG_SECURITY_SMACK for ports
+  * [Config] Enable CONFIG_SECURITY_FILE_CAPABILITIES for ports
+  * [Config] Disable CONFIG_COMPAT_BRK for ports
+  * getabis -- add armel versatile to the list
+
+  [ Brad Figg ]
+
+  * SAUCE: Increase the default prealloc buffer for HDA audio devices
+    (non-modem)
+
+  [ Manoj Iyer ]
+
+  * ubuntu: onmibook -- Added missing BOM file
+
+  [ Tim Gardner ]
+
+  * ubuntu: fsam7400 -- Cleanup Makefile
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT"
+  * signal: Fix alternate signal stack check
+  * SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects
+  * SCSI: osd_protocol.h: Add missing #include
+  * SCSI: megaraid_sas: fix 64 bit sense pointer truncation
+  * ext4: fix potential buffer head leak when add_dirent_to_buf() returns
+    ENOSPC
+  * ext4: avoid divide by zero when trying to mount a corrupted file system
+  * ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails
+  * ext4: fix lock order problem in ext4_move_extents()
+  * ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT
+  * ext4: plug a buffer_head leak in an error path of ext4_iget()
+  * ext4: make sure directory and symlink blocks are revoked
+  * ext4: fix i_flags access in ext4_da_writepages_trans_blocks()
+  * ext4: journal all modifications in ext4_xattr_set_handle
+  * ext4: don't update the superblock in ext4_statfs()
+  * ext4: fix uninit block bitmap initialization when s_meta_first_bg is
+    non-zero
+  * ext4: fix block validity checks so they work correctly with meta_bg
+  * ext4: avoid issuing unnecessary barriers
+  * ext4: fix error handling in ext4_ind_get_blocks()
+  * ext4: make trim/discard optional (and off by default)
+  * ext4: make "norecovery" an alias for "noload"
+  * ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT
+  * ext4: initialize moved_len before calling ext4_move_extents()
+  * ext4: move_extent_per_page() cleanup
+  * jbd2: Add ENOMEM checking in and for
+    jbd2_journal_write_metadata_buffer()
+  * ext4: Return the PTR_ERR of the correct pointer in
+    setup_new_group_blocks()
+  * ext4: Avoid data / filesystem corruption when write fails to copy data
+  * ext4: wait for log to commit when umounting
+  * ext4: remove blocks from inode prealloc list on failure
+  * ext4: ext4_get_reserved_space() must return bytes instead of blocks
+  * ext4: quota macros cleanup
+  * ext4: fix incorrect block reservation on quota transfer.
+  * ext4: Wait for proper transaction commit on fsync
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+  * ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem)
+  * Linux 2.6.32.1
+  * kbuild: generate modules.builtin
+  * (pre-stable) drm/i915: Fix sync to vblank when VGA output is turned off
+    - LP: #494461
+  * (pre-stable) drm/i915: Avoid NULL dereference with component_only
+    tv_modes
+    - LP: #494045
+
+  [ Zhao Yakui ]
+
+  * (pre-stable) acpi: Use the ARB_DISABLE for the CPU which model id is
+    less than 0x0f.
+    - LP: #481765
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 17 Dec 2009 15:41:21 +0000
+
+linux (2.6.32-8.12) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: AppArmor -- add linux/err.h for ERR_PTR
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 12 Dec 2009 10:56:16 +0000
+
+linux (2.6.32-8.11) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches
+    up"
+  * Revert "SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition."
+  * Revert "SAUCE: AppArmor: Fix refcounting bug causing leak of creds"
+  * Revert "SAUCE: AppArmor: Fix cap audit_caching preemption disabling"
+  * Revert "SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds"
+  * Revert "SAUCE: AppArmor: Fix oops after profile removal"
+  * Revert "SAUCE: AppArmor: AppArmor disallows truncate of deleted files."
+  * Revert "SAUCE: AppArmor: AppArmor fails to audit change_hat correctly"
+  * Revert "SAUCE: AppArmor: Policy load and replacement can fail to alloc
+    mem"
+  * Revert "SAUCE: AppArmor: AppArmor wrongly reports allow perms as
+    denied"
+  * Revert "SAUCE: AppArmor: Fix mediation of "deleted" paths"
+  * Revert "SAUCE: AppArmor: Fix off by 2 error in getprocattr mem
+    allocation"
+  * Revert "SAUCE: AppArmor: Set error code after structure
+    initialization."
+  * Revert "AppArmor -- fix pstrace_may_access rename"
+  * Revert "ubuntu: AppArmor security module"
+  * Revert "SAUCE: Add config option to set a default LSM"
+  * Revert "ubuntu: fsam7400 -- sw kill switch driver"
+  * Revert "[Config] fsam7400 -- enable"
+  * Revert "[Config] AUFS -- enable"
+  * Revert "ubuntu: AUFS -- aufs2-30 20090727"
+  * Revert "ubuntu: AUFS -- export various core functions -- fixes"
+  * Revert "ubuntu: AUFS -- export various core functions"
+  * Revert "[Config] ubuntu/iscsitarget -- disable"
+  * Revert "[Config] iscsitarget -- enable"
+  * Revert "ubuntu: iscsitarget -- SVN revision r214"
+  * update Vcs-Git to point to the correct repository
+    - LP: #493589
+  * update build environment overrides to lucid
+    - LP: #493589
+  * [Config] enable CONFIG_DEVTMPFS
+  * [Config] update all configs following AppArmor 2009-12-08 update
+  * SAUCE: isapnp_init: make isa PNP scans occur async
+  * [Config] fsam7400 -- enable
+  * [Config] omnibook -- enable
+  * [Config] cleanup CONFIG_AUDIT
+  * ubuntu: AUFS -- export various core functions (aufs2-base.patch)
+  * ubuntu: AUFS -- export various core functions (aufs2-standalone.patch)
+  * ubuntu: AUFS -- aufs2 20091209
+  * [Config] AUFS -- enable
+  * [Config] iscsitarget -- enable
+
+  [ Arjan van de Ven ]
+
+  * SAUCE: KMS: cache the EDID information of the LVDS
+
+  [ Colin Watson ]
+
+  * bnx2: update d-i firmware filenames
+    - LP: #494052
+  * add cdc_ether to nic-usb-modules udeb
+    - LP: #495060
+
+  [ John Johansen ]
+
+  * ubuntu: AppArmor -- mainline 2009-10-08
+
+  [ Manoj Iyer ]
+
+  * ubuntu: fsam7400 -- kill switch for Fujitsu Siemens Amilo M 7400
+  * ubuntu: omnibook -- support Toshiba (HP) netbooks
+  * ubuntu: iscsitarget --- version 1.4.19
+    - LP: #494693
+
+  [ Surbhi Palande ]
+
+  * SAUCE: Make populate_rootfs asynchronous
+
+  [ Tim Gardner ]
+
+  * Parallelize flavour builds and packaging
+  * [Config] Enable CONFIG_KSM
+
+  [ Upstream Kernel Changes ]
+
+  * Config option to set a default LSM
+  * LSM: Add security_path_chroot().
+  * LSM: Add security_path_chroot().
+  * LSM: Move security_path_chmod()/security_path_chown() to after
+    mutex_lock().
+  * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 11 Dec 2009 17:45:19 +0000
+
+linux (2.6.32-7.10) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] disable CONFIG_THUMB2_KERNEL to fix arm FTBFS
+
+ -- Andy Whitcroft <apw@canonical.com>  Sun, 06 Dec 2009 12:56:48 +0000
+
+linux (2.6.32-7.9) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: set /proc/acpi/video/*/DOS to 4 by default
+    - LP: #458982
+  * SAUCE: ensure vga16fb loads if no other driver claims the VGA device
+  * [Config] update configs following versatile switch to V7
+  * rebased to v2.6.32
+  * [Config] update configs following rebase to v2.6.32
+  * [Config] update ports configs following rebase to v2.6.32
+  * SAUCE: default ATI Radeon KMS to off until userspace catches up
+
+  [ Arjan van de Ven ]
+
+  * SAUCE: vfs: Add a trace point in the mark_inode_dirty function
+
+  [ Leann Ogasawara ]
+
+  * [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable
+    permissions
+    - CVE-2009-3939
+
+  [ Loic Minier ]
+
+  * SAUCE: select a v7 CPU for versatile
+
+  [ Takashi Iwai ]
+
+  * SAUCE: ALSA: hda - Add power on/off counter
+
+  [ Upstream changes ]
+
+  * rebased to v2.6.32
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 04 Dec 2009 10:44:50 +0000
+
+linux (2.6.32-6.8) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] disable SSB devices for armel
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 28 Nov 2009 12:16:40 +0000
+
+linux (2.6.32-6.7) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches up"
+  * Revert "SAUCE: Dell XPS710 reboot quirk"
+  * Revert "SAUCE: Link acpi-cpufreq.o first"
+  * Revert "SAUCE: LPIA  Logical reset of USB port on resume"
+  * Revert "SAUCE: LPIA Reboot fix for Intel Crownbeach development boards"
+  * Revert "SAUCE: Enable HDMI audio codec on Studio XPS 1340"
+  * Revert "SAUCE: Dell laptop digital mic does not work, PCI 1028:0271"
+  * Revert "Add Dell Dimension 9200 reboot quirk"
+  * Revert "SAUCE: Correctly blacklist Thinkpad r40e in ACPI"
+  * Revert "SAUCE: tulip: Define ULI PCI ID's"
+  * Revert "SAUCE: Lower warning level of some PCI messages"
+  * Revert "mac80211: fix two issues in debugfs"
+    Drop a number of known redundant commits as identified in the Ubuntu
+    delta review blueprint.
+
+  * reenable armel versatile flavour
+  * [Config] disable CONFIG_USB_DEVICEFS
+
+  [ Tim Gardner ]
+
+  * [Config] udeb: Add squashfs to fs-core-modules
+    - LP: #352615
+  * [Config] Create a real squashfs udeb
+    - LP: #352615
+
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 27 Nov 2009 17:31:16 +0000
+
+linux (2.6.32-5.6) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.32-rc8
+  * update configs following rebase to v2.6.32-rc8
+  * update ports configs since rebase to v2.6.32-rc8
+  * [Config] enable cgroup options
+    - LP: #480739
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v2.6.32-rc8
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 23 Nov 2009 11:16:14 +0000
+
+linux (2.6.32-4.5) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * rebase to v2.6.32-rc7
+  * resync with Karmic proposed
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix oops after profile removal
+    - LP: #475619
+  * SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds
+    - LP: #437258
+  * SAUCE: AppArmor: Fix cap audit_caching preemption disabling
+    - LP: #479102
+  * SAUCE: AppArmor: Fix refcounting bug causing leak of creds
+    - LP: #479115
+  * SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe
+    transition.
+    - LP: #480112
+
+  [ Ubuntu Changes ]
+
+  * resync with Karmic proposed (ddbc670a86a3dee18541a3734149f250ff307adf)
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v2.6.32-rc7
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 13 Nov 2009 11:35:13 +0000
+
+linux (2.6.32-3.4) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] SERIO_LIBPS2 and SERIO_I8042 must match
+  * [Upstream] add local prefix to oss local change_bits
+
+  [ Upstream Kernel Changes ]
+
+  * mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/
+  * mtd/maps: gpio-addr-flash: depend on GPIO arch support
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 11 Nov 2009 14:47:04 +0000
+
+linux (2.6.32-3.3) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.32-rc6
+  * [Config] update configs following rebase to v2.6.32-rc6
+  * [Config] update ports configs following rebase to v2.6.32-rc6
+  * resync with Karmic Ubuntu-2.6.31-15.49
+  * [Config] add module ignores for broken drivers
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: AppArmor wrongly reports allow perms as denied
+    - LP: #453335
+  * SAUCE: AppArmor: Policy load and replacement can fail to alloc mem
+    - LP: #458299
+  * SAUCE: AppArmor: AppArmor fails to audit change_hat correctly
+    - LP: #462824
+  * SAUCE: AppArmor: AppArmor disallows truncate of deleted files.
+    - LP: #451375
+
+  [ Kees Cook ]
+
+  * SAUCE: Fix nx_enable reporting
+    - LP: #454285
+
+  [ Scott James Remnant ]
+
+  * Revert "SAUCE: trace: add trace_event for the open() syscall"
+  * SAUCE: trace: add trace events for open(), exec() and uselib()
+    - LP: #462111
+
+  [ Stefan Bader ]
+
+  * SAUCE: Fix sub-flavour script to not stop on missing directories
+    - LP: #453073
+
+  [ Ubuntu Changes ]
+
+  * resync with Karmic Ubuntu-2.6.31-15.49
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v2.6.32-rc6
+    - LP: #464552
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 10 Nov 2009 15:00:57 +0000
+
+linux (2.6.32-2.2) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * install the full changelog with the binary package
+  * changelog -- explicitly note rebases and clean history
+  * reinstate armel.mk with no flavours
+    - LP: #449637
+  * [Upstream] block: silently error unsupported empty barriers too
+    - LP: #420423
+  * [Config] udate configs following karmic resync
+  * [Config] update ports configs following karmic resync
+  * [Upstream] lirc -- follow removal of .id element
+
+  [ Colin Watson ]
+
+  * Use section 'admin' rather than 'base'
+  * Add more e100 firmware to nic-modules
+    - LP: #451872
+  * Add qla1280 firmware to scsi-modules
+    - LP: #381037
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Set error code after structure initialization.
+    - LP: #427948
+  * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation
+    - LP: #446595
+  * SAUCE: AppArmor: Fix mediation of "deleted" paths
+
+  [ Kees Cook ]
+
+  * SAUCE: [x86] fix report of cs-limit nx-emulation
+    - LP: #454285
+
+  [ Leann Ogasawara ]
+
+  * SAUCE: (drop after 2.6.31) input: Add support for filtering input
+    events
+    - LP: #430809
+  * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi
+    toggle switch press
+    - LP: #430809
+
+  [ Luke Yelavich ]
+
+  * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc
+  * [Config] Add sd_mod to scsi-modules udeb for powerpc
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Update to LIRC 0.8.6
+    - LP: #432678
+  * SAUCE: dell-laptop: Store the HW switch status internally rather than
+    requerying every time
+    - LP: #430809
+  * SAUCE: dell-laptop: Blacklist machines not supporting dell-laptop
+    - LP: #430809
+
+  [ Stefan Bader ]
+
+  * [Upstream] acerhdf: Limit modalias matching to supported boards
+    - LP: #435958
+
+  [ Tim Gardner ]
+
+  * [Upstream] i915: Fix i2c init message
+    - LP: #409361
+  * [Config] Add sym53c8xx.ko to virtual sub-flavour
+    - LP: #439415
+  * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules
+    - LP: #439456
+  * [Config] Set default I/O scheduler back to CFQ for desktop flavours
+    - LP: #381300
+  * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros
+    - LP: #430694
+  * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915
+    - LP: #430694
+  * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y
+    - LP: #416325
+  * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT
+    - LP: #430694
+  * SAUCE: Raise the default console 'quiet' level to 2
+  * [Config] CONFIG_X86_PAT=y
+  * [Config] Add armel arch to linux-libc-dev arches.
+    - LP: #449637
+  * [Config] CONFIG_X86_MCE
+  * [Upstream] (drop after 2.6.31) Input: synaptics - add another Protege
+    M300 to rate blacklist
+    - LP: #433801
+
+  [ Upstream Kernel Changes ]
+
+  * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584
+  * drm/i915: Fix FDI M/N setting according with correct color depth
+    - LP: #416792
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 22 Oct 2009 16:53:33 +0100
+
+linux (2.6.32-1.1) lucid; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.32-rc3
+  * [Config] update configs following rebase to 2.6.32-rc3
+  * [Config] update ports configs following rebase to 2.6.32-rc3
+  * AppArmor -- fix pstrace_may_access rename
+  * staging/android -- disable
+  * ubuntu: dm-raid-45 -- update to compile with 2.6.32
+  * ubuntu: drbd -- disable
+  * staging/comdi -- disable
+  * staging/go7007 -- disable
+  * [Config] staging/winbond -- disable
+  * [Config] ubuntu/iscsitarget -- disable
+  * [d-i] cbc and ecb are builtin make them optional in udebs
+  * rebase to v2.6.32-rc5
+  * [Config] update configs following rebase to v2.6.32-rc5
+  * [Config] update ports configs following rebase to v2.6.31-rc5
+
+  [ Tim Gardner ]
+
+  * [Config] Add cpio as a build dependency.
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v2.6.32-rc3
+  * rebase to v2.6.32-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 05 Oct 2009 15:48:58 +0100
+
+linux (2.6.31-11.37) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Increase kernel log buffer to 256K for amd64 flavours
+    - LP: #424810
+  * [Config] Set HZ=100 for amd64 flavours
+    - LP: #438234
+  * [Upstream] e1000e: Emit notice instead of an error when
+    pci_enable_pcie_error_reporting() fails
+    - LP: #436370
+
+  [ Upstream Kernel Changes ]
+
+  * n_tty: honor opost flag for echoes
+  * n_tty: move echoctl check and clean up logic
+    - LP: #438310
+
+  * Revert "[Upstream] drm/i915: Check that the relocation points to within
+    the target" - Use upstream cherry-pick.
+  * drm/i915: Check that the relocation points to within the target
+    - LP: #429241
+
+  * drm/i915: fix tiling on IGDNG
+  * drm/i915: add B43 chipset support
+  * agp/intel: Add B43 chipset support
+    Intel request from kernel team mailing list.
+
+  * HID: completely remove apple mightymouse from blacklist
+    - LP: #428111
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 28 Sep 2009 11:47:29 -0600
+
+linux (2.6.31-11.36) karmic; urgency=low
+
+  [ Brian Rogers ]
+
+  * SAUCE: (drop after 2.6.31) em28xx: ir-kbd-i2c init data needs a
+    persistent object
+  * SAUCE: (drop after 2.6.31) saa7134: ir-kbd-i2c init data needs a
+    persistent object
+
+  [ Takashi Iwai ]
+
+  * [Upstream] ALSA: hda - Add another entry for Nvidia HDMI device
+    - LP: #416482
+
+  [ Tyler Hicks ]
+
+  * SAUCE: (drop after 2.6.31) eCryptfs: Prevent lower dentry from going
+    negative during unlink
+
+  [ Upstream Kernel Changes ]
+
+  * sg: fix oops in the error path in sg_build_indirect()
+  * mpt2sas : Rescan topology from Interrupt context instead of work thread
+  * mpt2sas: Prevent sending command to FW while Host Reset
+  * mpt2sas: setting SDEV into RUNNING state from Interrupt context
+  * mpt2sas: Raid 10 Volume is showing as Raid 1E in dmesg
+  * SCSI: fix oops during scsi scanning
+  * SCSI: libsrp: fix memory leak in srp_ring_free()
+  * cfg80211: fix looping soft lockup in find_ie()
+  * ath5k: write PCU registers on initial reset
+  * binfmt_elf: fix PT_INTERP bss handling
+  * TPM: Fixup boot probe timeout for tpm_tis driver
+  * md: Fix "strchr" [drivers/md/dm-log-userspace.ko] undefined!
+  * x86/amd-iommu: fix broken check in amd_iommu_flush_all_devices
+  * fix undefined reference to user_shm_unlock
+  * perf_counter: Fix buffer overflow in perf_copy_attr()
+  * perf_counter: Start counting time enabled when group leader gets
+    enabled
+  * powerpc/perf_counters: Reduce stack usage of power_check_constraints
+  * powerpc: Fix bug where perf_counters breaks oprofile
+  * powerpc/ps3: Workaround for flash memory I/O error
+  * block: don't assume device has a request list backing in nr_requests
+    store
+  * agp/intel: remove restore in resume
+  * ALSA: cs46xx - Fix minimum period size
+  * ASoC: Fix WM835x Out4 capture enumeration
+  * sound: oxygen: work around MCE when changing volume
+  * mlx4_core: Allocate and map sufficient ICM memory for EQ context
+  * perf stat: Change noise calculation to use stddev
+  * x86: Fix x86_model test in es7000_apic_is_cluster()
+  * x86/i386: Make sure stack-protector segment base is cache aligned
+  * PCI: apply nv_msi_ht_cap_quirk on resume too
+  * x86, pat: Fix cacheflush address in change_page_attr_set_clr()
+  * ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic()
+    with highmem
+  * KVM guest: do not batch pte updates from interrupt context
+  * KVM: Fix coalesced interrupt reporting in IOAPIC
+  * KVM: VMX: Check cpl before emulating debug register access
+  * KVM guest: fix bogus wallclock physical address calculation
+  * KVM: x86: Disallow hypercalls for guest callers in rings > 0
+  * KVM: VMX: Fix cr8 exiting control clobbering by EPT
+  * KVM: x86 emulator: Implement zero-extended immediate decoding
+  * KVM: MMU: make __kvm_mmu_free_some_pages handle empty list
+  * KVM: x86 emulator: fix jmp far decoding (opcode 0xea)
+  * KVM: limit lapic periodic timer frequency
+  * libata: fix off-by-one error in ata_tf_read_block()
+  * PCI quirk: update 82576 device ids in SR-IOV quirks list
+  * PCI: Unhide the SMBus on the Compaq Evo D510 USDT
+  * powerpc/pseries: Fix to handle slb resize across migration
+  * Linux 2.6.31.1
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 24 Sep 2009 13:04:28 -0600
+
+linux (2.6.31-10.35) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Disable CONFIG_UEVENT_HELPER_PATH
+
+  [ Andy Whitcroft ]
+
+  * [Config] Enable CONFIG_USB_GADGET_DUMMY_HCD
+  * remove the tlsup driver
+  * remove lmpcm logitech driver support
+
+  [ Bryan Wu ]
+
+  * Add 3 missing files to prerm remove file list
+    - LP: #345623, #415832
+
+  [ Chris Wilson ]
+
+  * [Upstream] drm/i915: Check that the relocation points to within the
+    target
+    - LP: #429241
+
+  [ Luke Yelavich ]
+
+  * [Config] Set CONFIG_EXT4_FS=y on ports architectures
+
+  [ Manoj Iyer ]
+
+  * SAUCE: Added quirk to recognize GE0301 3G modem as an interface.
+    - LP: #348861
+
+  [ Tim Gardner ]
+
+  * Revert "[Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux) white-list"
+  * Revert "[Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux) white-list"
+  * Revert "[Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux) white-list"
+  * Revert "[Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux) white-list"
+  * Revert "[Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux) white-list"
+    Upstream suggests that this is not the right approach.
+
+  * [Config] Set default I/O scheduler to DEADLINE
+    CFQ seems to have some load related problems which are often exacerbated by sreadahead.
+    - LP: #381300
+
+  [ ubuntu@tjworld.net ]
+
+  * SAUCE: ipw2200: Enable LED by default
+    - LP: #21367
+
+  [ Upstream Kernel Changes ]
+
+  * ALSA: hda - Add support for new AMD HD audio devices
+    - LP: #430564
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 16 Sep 2009 15:37:49 +0100
+
+linux (2.6.31-10.34) karmic; urgency=low
+
+  [ Ted Tso ]
+
+  * [Upstream] ext3: Don't update superblock write time when filesystem is
+    read-only
+    - LP: #427822
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 15 Sep 2009 16:00:45 -0600
+
+linux (2.6.31-10.33) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] dvb-usb: fix tuning with Cinergy T2
+    - LP: #421258
+
+  [ Tim Gardner ]
+
+  * [Config] Unconditionally copy files from sub-flavours lists.
+    (really, really fix it this time)
+    - LP: #423426
+  * [Config] Set CONFIG_CACHEFILES=m for all flavours
+
+  [ Upstream Kernel Changes ]
+
+  * ext4: Don't update superblock write time when filesystem is read-only
+    - LP: #427822
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 15 Sep 2009 07:50:21 -0600
+
+linux (2.6.31-10.32) karmic; urgency=low
+
+  [ Eric Miao ]
+
+  * [Config] enable module support for memory stick
+    - LP: #159951
+
+  [ Tim Gardner ]
+
+  * [Config] Unconditionally copy files from sub-flavours lists.
+    - LP: #423426
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 10 Sep 2009 15:57:55 -0600
+
+linux (2.6.31-10.31) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.31 final
+
+  [ Colin Watson ]
+
+  * [Config] Recommend grub-pc in linux-image
+    - LP: #385741
+
+  [ Ike Panhc ]
+
+  * [Upstream] Pull latest update of lenovo-sl-laptop
+
+  [ Peter Feuerer ]
+
+  * [Upstream] (drop after 2.6.31) acerhdf: fix fan control for AOA150
+    model
+    - LP: #426691
+
+  [ Tim Gardner ]
+
+  * [Config] De-macro some package names.
+
+  [ Upstream Changes ]
+
+  * rebase to 2.6.31 final.
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 10 Sep 2009 09:38:10 +0100
+
+linux (2.6.31-10.30) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Enable CONFIG_USB_DEVICEFS
+    - LP: #417748
+  * [Config] Populate the config-update template a bit more
+
+  [ Andy Whitcroft ]
+
+  * rebase to v2.6.31-rc9
+  * [Config] update configs following rebase to v2.6.31-rc9
+  * [Config] update ports configs following rebase to v2.6.31-rc9
+
+  [ Colin Ian King ]
+
+  * SAUCE: wireless: hostap, fix oops due to early probing interrupt
+    - LP: #254837
+
+  [ Jerone Young ]
+
+  * [Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux)
+    white-list
+    - LP: #281732
+  * [Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux)
+    white-list
+    - LP: #281732
+
+  [ John Johansen ]
+
+  * SAUCE: AppArmor: Fix profile attachment for regexp based profile names
+    - LP: #419308
+  * SAUCE: AppArmor: Return the correct error codes on profile
+    addition/removal
+    - LP: #408473
+  * SAUCE: AppArmor: Fix OOPS in profile listing, and display full list
+    - LP: #408454
+  * SAUCE: AppArmor: Fix mapping of pux to new internal permission format
+    - LP: #419222
+  * SAUCE: AppArmor: Fix change_profile failure
+    - LP: #401931
+  * SAUCE: AppArmor: Tell git to ignore generated include files
+    - LP: #419505
+
+  [ Stefan Bader ]
+
+  * [Upstream] acpi: video: Loosen strictness of video bus detection code
+    - LP: #333386
+  * SAUCE: Remove ov511 driver from ubuntu subdirectory
+
+  [ Tim Gardner ]
+
+  * [Config] Exclude char-modules from non-x86 udeb creation
+  * SAUCE: Notify the ACPI call chain of AC events
+  * [Config] CONFIG_SATA_VIA=m
+    - LP: #403385
+  * [Config] Build in all phylib support modules.
+  * [Config] Don't fail when sub-flavour files are missing
+    - LP: #423426
+  * [Config] Set CONFIG_LSM_MMAP_MIN_ADDR=0
+    - LP: #423513
+
+  [ Upstream ]
+
+  * Rebased against v2.6.31-rc9
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 07 Sep 2009 11:33:45 +0100
+
+linux (2.6.31-9.29) karmic; urgency=low
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] agp/intel: support for new chip variant of IGDNG mobile
+    - LP: #419993
+  * [Config] d-i/modules: Add new char-modules file, initialize with
+    intel-agp
+    - LP: #420605
+
+  [ Upstream ]
+
+  * Rebased against 2.6.31-rc8 plus some inotify regression patches:
+    up through git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+    adda766193ea1cf3137484a9521972d080d0b7af.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 28 Aug 2009 06:31:30 -0600
+
+linux (2.6.31-8.28) karmic; urgency=low
+
+  [ Ike Panhc ]
+
+  * [Config] Let nic-shared-modules depends on crypto-modules
+    - LP: #360966
+
+  [ Leann Ogasawara ]
+
+  * [Upstream] (drop after 2.6.31) drm/i915: increase default latency
+    constant
+    - LP: #412492
+
+  [ Mario Limonciello ]
+
+  * [Upstream]: (drop after 2.6.31) dell-laptop: don't change softblock
+    status if HW switch is disabled
+    - LP: #418721
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Add support for known
+    Compal made Dell laptops
+  * [Upstream]: (drop after 2.6.31) compal-laptop: Replace sysfs support
+    with rfkill support
+
+  [ Tim Gardner ]
+
+  * [Config] Add acpiphp to virtual sub-flavour
+    - LP: #364916
+  * Drop KSM patch set for now because of instabilities with encrypted swap.
+    - LP: #418781
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 26 Aug 2009 08:14:26 -0600
+
+linux (2.6.31-7.27) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] updateconfigs updateportsconfigs after 2.6.31-rc7 rebase
+  * SAUCE: (drop after 2.6.31) Added KSM from mmotm-2009-08-20-19-18
+    Replaces previous ksm patches from 2.6.31-6.25
+  * [Config] KSM=y
+
+  [ Upstream ]
+
+  * Rebased against v2.6.31-rc7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 22 Aug 2009 20:32:11 -0600
+
+linux (2.6.31-6.26) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] enable CONFIG_AUFS_BR_RAMFS
+    - LP: #414738
+  * split out debian directory ready for abstraction
+  * add printdebian target to find branch target
+  * abstracted debian -- debian/files is not abstracted
+  * abstracted debian -- packages must be built in debian/<pkg>
+  * abstracted debian -- kernel-wedge needs to work in debian/
+  * abstracted debian -- ensure we install the copyright file
+  * abstracted-debian -- drop the debian directories from headers
+  * abstracted-debian -- drop the debian directories from headers part 2
+  * SAUCE: ubuntu-insert-changes -- follow abstracted debian
+  * [Upstream] aoe: ensure we initialise the request_queue correctly V2
+    - LP: #410198
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Disable CONFIG_CPU_FREQ_DEBUG on powerpc-smp
+  * [Config] Ports: Re-enable windfarm modules on powerpc64-smp
+    - LP: #413150
+  * [Config] Ports: Build all cpu frequency scaling governors into ports
+    kernels
+  * [Config] Ports: Build ext2 and ext3 modules into ports kernels
+  * [Config] Ports: CONFIG_PACKET=y for all ports kernels
+  * [Config] Ports: Enable PS3 network driver
+
+  [ Stefan Bader ]
+
+  * abstracted debian -- call $(DEBIAN)/rules using make
+
+  [ Tim Gardner ]
+
+  * [Config] Abstract the debian directory
+  * SAUCE: Improve error reporting in postinst
+    - LP: #358564
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 16 Aug 2009 20:33:28 -0600
+
+linux (2.6.31-6.25) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * script to generate Ubuntu changes from changelog
+  * [Config] standardise ANDROID options
+  * [Config] standardise CONFIG_ATM as module
+  * [Config] standardise CONFIG_LIB80211 as module
+  * [Config] disable CONFIG_PRINT_QUOTA_WARNING
+  * [Config] set CONFIG_CRAMFS as module
+  * [Config] enable CONFIG_DAB and modules
+  * [Config] set CONFIG_MAC80211_HWSIM as module
+  * [Config] set CONFIG_NET_CLS_FLOW as module
+  * [Config] set CONFIG_NF_CONNTRACK_SANE as module
+  * [Config] set CONFIG_NF_CT_PROTO_DCCP as module
+  * [Config] set CONFIG_RTC_DRV_DS1511 as module
+  * [Config] set CONFIG_RTC_DRV_R9701 as module
+  * [Config] set CONFIG_RTC_DRV_S35390A as module
+  * [Config] set CONFIG_TOIM3232_DONGLE as module
+  * [Config] standardise CONFIG_USB_MIDI_GADGET as module
+  * [Config] standardise CONFIG_USB_G_PRINTER as module
+  * [Config] standardise CONFIG_USB_SERIAL_IR as module
+  * [Config] set CONFIG_USB_SERIAL_IUU as module
+  * [Config] standardise CONFIG_USB_STORAGE_CYPRESS_ATACB as module
+  * [Config] standardise CONFIG_USB_STORAGE_ONETOUCH as module
+  * cleanup remains of dm-loop
+  * drop thinkpad ec and smapi support
+  * drop appleir
+  * [Config] update configs following rebase to v2.6.31-rc6
+  * rebase to v2.6.31-rc6
+
+  [ Hugh Dickins ]
+
+  * SAUCE: ksm patch 1, drop after 2.6.31
+  * SAUCE: ksm patch 2, drop after 2.6.31
+  * SAUCE: ksm patch 3, drop after 2.6.31
+  * SAUCE: ksm patch 4, drop after 2.6.31
+  * SAUCE: ksm patch 5, drop after 2.6.31
+  * SAUCE: ksm patch 7, drop after 2.6.31
+
+  [ Izik Eidus ]
+
+  * SAUCE: ksm patch 0, drop after 2.6.31
+  * SAUCE: ksm patch 6, drop after 2.6.31
+  * SAUCE: ksm patch 8, drop after 2.6.31
+  * SAUCE: ksm patch 9, drop after 2.6.31
+
+  [ Luke Yelavich ]
+
+  * [Config] Ports: Re-add PS3 modules to udebs
+
+  [ Michael Casadevall ]
+
+  * [Config] Update SPARC config and d-i files to reflect what can be built
+
+  [ Tim Gardner ]
+
+  * [Config] Removed armel package support
+  * [Config] Enabled CONFIG_KSM=y
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased against v2.6.31-rc6
+  * ARM: Cleanup: Revert "ARM: Add more cache memory types macros"
+  * ARM: Cleanup: Revert "Do not use OOB with MLC NAND"
+  * ARM: Cleanup: Revert "ARM: Make ARM arch aware of ubuntu/ drivers"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make video capture drivers compile"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix isl29003 HWMON driver for i2c
+    changes"
+  * ARM: Cleanup: Revert "ARM: IMX51: IPU irq handler deadlock fix"
+  * ARM: Cleanup: Revert "ARM: IMX51: Babbage 2.5 needs a different system
+    revision"
+  * ARM: Cleanup: Revert "ARM: IMX51: Compile-in the IMX51 cpufreq driver
+    by default"
+  * ARM: Cleanup: Revert "ARM: IMX51: Enable ZONE_DMA for ARCH_MXC"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make ARCH_MXC auto-enable
+    ARCH_MXC_CANONICAL"
+  * ARM: Cleanup: Revert "ARM: IMX51: Unconditionally disable
+    CONFIG_GPIOLIB"
+  * ARM: Cleanup: Revert "ARM: IMX51: Minimal changes for USB to work on
+    2.6.31"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix plat-mxc/timer.c to handle imx51"
+  * ARM: Cleanup: Revert "ARM: IMX51: Make it compile."
+  * ARM: Cleanup: Revert "ARM: IMX51: Clean-up the craziness of including
+    mxc_uart.h _everywhere_"
+  * ARM: Cleanup: Revert "ARM: IMX51: Move board-mx51* header files to the
+    correct location"
+  * ARM: Cleanup: Revert "ARM: IMX51: Changed from snd_card_new to
+    snd_card_create"
+  * ARM: Cleanup: Revert "ARM: IMX51: Fix up merge error in Kconfig"
+  * ARM: Cleanup: Revert "ARM: IMX51: mxc_timer_init prototype"
+  * ARM: Cleanup: Revert "ARM: IMX51: Removed the mxc_gpio_port structure."
+  * ARM: Cleanup: Revert "ARM: IMX51: Added external declaration for
+    mxc_map_io."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name."
+  * ARM: Cleanup: Revert "ARM: IMX51: snd_soc_machine structure replaced
+    with snd_soc_card."
+  * ARM: Cleanup: Revert "ARM: IMX51: codec structure was moved to the card
+    structure"
+  * ARM: Cleanup: Revert "ARM: IMX51: Hack to add defines for
+    DMA_MODE_READ/WRITE/MASK"
+  * ARM: Cleanup: Revert "ARM: IMX51: Add SoC and board support for
+    Freescale mx51 platform"
+  * Driver core: add new device to bus's list before probing
+  * [Upstream] (drop after 2.6.31) ALSA: hda - Reduce click noise at
+    power-saving
+    - LP: #381693, #399750, #380892
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 14 Aug 2009 11:32:23 +0100
+
+linux (2.6.31-5.24) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Make video capture drivers compile
+  * [Config] IMX51: Config updates
+
+  [ Andy Whitcroft ]
+
+  * remove leftovers of dm-bbr
+
+  [ Leann Ogasawara ]
+
+  * Add pata_cs5535 to pata-modules
+    - LP: #318805
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_PPC64=y for powerpc64-smp
+  * [Config] Set the maximum number of CPUs to 1024 for powerpc64-smp
+  * [Config] CONFIG_PPC_PS3=y for powerpc64-smp
+  * [Config] CONFIG_PPC_MAPLE=y on powerpc64-smp
+  * [Config] CONFIG_PPC_PASEMI=y on powerpc64-smp
+  * [Config] CONFIG_CPU_FREQ_PMAC64=y on powerpc64-smp
+  * [Config] Enable all PS3 drivers in powerpc64-smp
+
+  [ Mario Limonciello ]
+
+  * LIRC -- fix lirc-i2c 2.6.31 compilation
+
+  [ Matthew Garrett ]
+
+  * [Upstream] dell-laptop: Fix rfkill state queries
+
+  [ Tim Gardner ]
+
+  * [Config] Ignore armel ABI and module changes
+  * [Config] Update configs after rebase against 2.6.31-rc5
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc5
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 28 Jul 2009 10:10:09 +0100
+
+linux (2.6.31-4.23) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * AUFS -- update to aufs2-30 20090727
+  * [Config] enable AUFS FUSE support
+
+  [ Luke Yelavich ]
+
+  * [Config] CONFIG_JFS_FS=m on sparc
+
+  [ Tim Gardner ]
+
+  * [Upstream] dell-laptop: Fix rfkill state setting.
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 27 Jul 2009 11:11:47 +0100
+
+linux (2.6.31-4.22) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM: IMX51: Add SoC and board support for Freescale mx51 platform
+  * ARM: IMX51: Move board-mx51* header files to the correct location
+  * ARM: IMX51: Clean-up the craziness of including mxc_uart.h _everywhere_
+  * ARM: IMX51: Make it compile.
+  * ARM: IMX51: Unconditionally disable CONFIG_GPIOLIB
+  * ARM: IMX51: Make ARCH_MXC auto-enable ARCH_MXC_CANONICAL
+  * ARM: IMX51: Enable ZONE_DMA for ARCH_MXC
+  * ARM: IMX51: Compile-in the IMX51 cpufreq driver by default
+  * ARM: IMX51: Fix isl29003 HWMON driver for i2c changes
+  * ARM: USB: musb: Refer to musb_otg_timer_func under correct #ifdef
+  * ARM: staging: udlfb: Add vmalloc.h include
+  * UBUNTU [Config]: Bring imx51 config upto date with other flavours
+
+  [ Brad Figg ]
+
+  * ARM: IMX51: Hack to add defines for DMA_MODE_READ/WRITE/MASK
+  * ARM: IMX51: codec structure was moved to the card structure
+  * ARM: IMX51: snd_soc_machine structure replaced with snd_soc_card.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Get to bus_id by calling dev_name.
+  * ARM: IMX51: Added external declaration for mxc_map_io.
+  * ARM: IMX51: Removed the mxc_gpio_port structure.
+  * ARM: IMX51: mxc_timer_init prototype
+  * ARM: IMX51: Fix up merge error in Kconfig
+  * ARM: IMX51: Changed from snd_card_new to snd_card_create
+
+  [ Dinh Nguyen ]
+
+  * ARM: IMX51: Fix plat-mxc/timer.c to handle imx51
+  * ARM: IMX51: Minimal changes for USB to work on 2.6.31
+  * ARM: IMX51: Babbage 2.5 needs a different system revision
+  * ARM: IMX51: IPU irq handler deadlock fix
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CONFIG_CAN=m
+    - LP: #327243
+  * [Config] Enabled CONFIG_SERIAL=m
+    - LP: #397189
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 24 Jul 2009 06:19:10 -0600
+
+linux (2.6.31-4.21) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * dm-raid-4-5: Add missing brackets around test_bit()
+
+  [ John Johansen ]
+
+  * AppArmor: Fix change_profile failing lpn401931
+  * AppArmor: Fix determination of forced AUDIT messages.
+  * AppArmor: Fix oops in auditing of the policy interface offset
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 19:18:30 +0100
+
+linux (2.6.31-4.20) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: iscsitarget -- update to SVN revision r214
+  * SAUCE: iscsitarget -- renable driver
+  * [Config] consolidate lpia/lpia and i386/generic configs
+  * [Config] enable CRYPTO modules for all architectures
+  * [Config] enable cryptoloop
+  * [Config] enable various filesystems for armel
+  * [Config] sync i386 generic and generic-pae
+  * [Config] add the 386 (486 processors and above) flavour
+  * [Config] re-set DEFAULT_MMAP_MIN_ADDR
+    - LP: #399914
+  * add genconfigs/genportsconfigs to extract the built configs
+  * updateconfigs -- alter concatenation order allow easier updates
+  * intelfb -- INTELFB now conflicts with DRM_I915
+  * printchanges -- rebase tree does not have stable tags use changelog
+  * AppArmor: fix argument size missmatch on 64 bit builds
+
+  [ Ike Panhc ]
+
+  * Ship bnx2x firmware in nic-modules udeb
+    - LP: #360966
+
+  [ Jeff Mahoney ]
+
+  * AppArmor: fix build failure on ia64
+
+  [ John Johansen ]
+
+  * AppArmour: ensure apparmor enabled parmater is off if AppArmor fails to
+    initialize.
+  * AppArmour: fix auditing of domain transitions to include target profile
+    information
+  * AppArmor: fix C99 violation
+  * AppArmor: revert reporting of create to write permission.
+  * SAUCE: Add config option to set a default LSM
+  * [Config] enable AppArmor by default
+  * AppArmor: Fix NULL pointer dereference oops in profile attachment.
+
+  [ Keith Packard ]
+
+  * SAUCE: drm/i915: Allow frame buffers up to 4096x4096 on 915/945 class
+    hardware
+    - LP: #351756
+
+  [ Luke Yelavich ]
+
+  * [Config] add .o files found in arch/powerpc/lib to all powerpc kernel
+    header packages
+    - LP: #355344
+
+  [ Michael Casadevall ]
+
+  * [Config] update SPARC config files to allow success build
+
+  [ Scott James Remnant ]
+
+  * SAUCE: trace: add trace_event for the open() syscall
+
+  [ Stefan Bader ]
+
+  * SAUCE: jfs: Fix early release of acl in jfs_get_acl
+    - LP: #396780
+
+  [ Tim Gardner ]
+
+  * [Upstream] Fix Soltech TA12 volume hotkeys not sending key release
+    - LP: #397499
+  * [Upstream] USB Option driver - Add USB ID for Novatel MC727/U727/USB727
+    refresh
+    - LP: #365291
+  * [Config] SSB/B44 are common across all arches/flavours.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc4
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 23 Jul 2009 08:41:39 +0100
+
+linux (2.6.31-3.19) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "[Config] Disabled NDISWRAPPER"
+  * ndiswrapper -- fix i386 compilation failures on cmpxchg8b
+  * AUFS -- export various core functions
+  * AUFS -- export various core functions -- fixes
+  * AUFS -- core filesystem
+  * AUFS -- track changes in v2.6.31
+  * [Config] Enable AUFS
+  * droppped 'iwl3945: do not send scan command if channel count zero' as it
+    is already upstream but failed to auto-drop on rebase.
+
+  [ Eric Paris ]
+
+  * SAUCE: fsnotify: use def_bool in kconfig instead of letting the user
+    choose
+  * SAUCE: inotify: check filename before dropping repeat events
+  * SAUCE: fsnotify: fix inotify tail drop check with path entries
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 14 Jul 2009 12:52:55 +0100
+
+linux (2.6.31-3.18) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "Add splice-2.6.23.patch from AUFS to export a symbol needed by
+    AUFS"
+  * Revert "Add put_filp.patch from AUFS to export a symbol needed by AUFS"
+  * Revert "Add sec_perm-2.6.24.patch from AUFS - export
+    security_inode_permission"
+  * clear out left over AUFS files and modifications
+
+  [ Luke Yelavich ]
+
+  * [Config] Enable CONFIG_USB_ISP116X_HCD on sparc
+  * SAUCE: Explicitly include header files to allow apparmor to build on
+    powerpc
+  * [Config] Enable CONFIG_BLK_DEV_IDECD on powerpc
+
+  [ Tim Gardner ]
+
+  * [Config] Dropped ubuntu/misc/wireless/acx
+  * [Config] Disabled NDISWRAPPER until the compile issues are fixed.
+
+  [ Upstream ]
+
+  * Rebased to 2.6.31-rc3
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 18:59:33 +0100
+
+linux (2.6.31-2.17) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_BLK_DEV_CRYPTOLOOP=m for sparc
+  * compcache -- remove redundant Kconfig entries part 2
+  * compcache -- clean up CCFLAGS declarations
+  * [Config] enable AppArmor
+  * AppArmor: fix operator precidence issue in as_path_link
+
+  [ John Johansen ]
+
+  * AppArmor security module
+  * AppArmor: Correct mapping of file permissions.
+  * AppArmor: Turn auditing of ptrace on
+
+  [ Luke Yelavich ]
+
+  * [Config] disable CONFIG_DM_RAID45 on powerpc
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 10 Jul 2009 15:02:05 +0100
+
+linux (2.6.31-2.16) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * compcache -- remove redundant Kconfig entries
+    added ignore and ignore.modules for all arches since the compcache update
+    changes the modules names as well as some compcache ABI values.
+
+  [ Manoj Iyer ]
+
+  * SAUCE: updated dm-raid45 module version to 2009.04.24 (2.6.30-rc3)
+  * SAUCE: update compcache version to 0.5.3
+
+  [ Tim Gardner ]
+
+  * [Config]: Fix sparc FTBS by adding ignore.modules
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 06 Jul 2009 13:35:29 -0600
+
+linux (2.6.31-2.15) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: default ATI Radeon KMS to off until userspace catches up
+  * [Config] Update configs following rebase to 2.6.31-rc2
+  * [Config] update ports configs following update to 2.6.31-rc2
+
+  [ Luke Yelavich ]
+
+  * [Config] powerpc - Disable CONFIG_RDS
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to mainline 2.6.31-rc2
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 04 Jul 2009 17:39:13 +0100
+
+linux (2.6.31-1.14) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update ndiswrapper to 1.55
+  * remove leftovers of gfs
+  * [Config] powerpc: enable CONFIG_PPC_DISABLE_WERROR
+
+  [ Luke Yelavich ]
+
+  * [Config] re-enable and build the ide-pmac driver into powerpc kernels
+  * [Config] Build the ServerWorks Frodo / Apple K2 SATA driver into the
+    kernel
+
+  [ Manoj Iyer ]
+
+  * Remove snd-bt-sco ubuntu driver
+
+  [ Michael Casadevall ]
+
+  * [Config] updates ia64 config and d-i folders to allow succesful build
+  * [Config] Update powerpc and sparc for 2.6.31
+
+  [ Upstream Kernel Changes ]
+
+  * intel-iommu: fix Identity Mapping to be arch independent
+    - LP: #384695
+  * ACPI: video: prevent NULL deref in acpi_get_pci_dev()
+
+ -- Andy Whitcroft <apw@canonical.com>  Tue, 30 Jun 2009 17:47:32 +0100
+
+linux (2.6.31-1.13) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * REBASE: rebased to mainline 2.6.31-rc1
+    - "UBUNTU: SAUCE: UHCI USB quirk for resume"
+      no longer applies, using deprecated interfaces, LPIA only, dropped
+    - "UBUNTU: SAUCE: Mask off garbage in Dell WMI scan code data"
+      changes now upstream, dropped
+  * [Config] Update configs following rebase to 2.6.31-rc1
+  * [Config] update ports configs following update to 2.6.31-rc1
+
+  * [Config] disable broken staging driver CONFIG_STLC45XX
+  * SAUCE: fix compcache to use updates accessors
+  * [Config] disable staging driver CONFIG_VT6655
+  * SAUCE: fix DRDB to use updates accessors
+  * [Disable] ndiswrapper needs update
+  * [Disable] LIRC I2C needs update
+  * [Disable] CONFIG_LENOVO_SL_LAPTOP needs update
+  * [Config] disable I2C_DESIGNWARE does not compile
+  * [Config] disable CONFIG_TLSUP for lpia
+  * [Config] disable CONFIG_FB_UDL for arm
+  * SAUCE: disable adding scsi headers to linux-libc-dev
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Add LIRC drivers
+
+ -- Andy Whitcroft <apw@canonical.com>  Thu, 25 Jun 2009 12:06:22 +0100
+
+linux (2.6.30-10.12) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] split out the ports configs into their own family
+  * [Config] update configs following introduction of ports family
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "Rename linux-doc-PKGVER to linux-doc and clean up its
+    description". Fixes linux-doc package name conflicts for now.
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 22 Jun 2009 09:17:14 -0600
+
+linux (2.6.30-10.11) karmic; urgency=low
+
+  [ Amit Kucheria ]
+
+  * [Config] Comment splitconfig.pl and misc cleanup
+  * [Config] Rename all configs to the new naming scheme
+  * [Config] Splitconfig rework
+  * [Config] Rename scripts/misc/oldconfig to kernelconfig
+  * [Config] Fix build system for new config split
+  * [Config] Run updateconfigs after the splitconfig rework
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: Default to i915.modeset=0 if CONFIG_DRM_I915_KMS=y"
+  * [Config] standardise CONFIG_STAGING=y
+  * [Config] standardise CONFIG_RD_LZMA=y
+  * [Config] CONFIG_PCI_IOV=y
+  * [Config] CONFIG_PCI_STUB=m
+  * [Config] merge kernel configs more agressively
+
+  [ Colin Watson ]
+
+  * [Config] Run kernel-wedge in $(builddir) rather than at the top level
+  * [Config] Add support for including firmware in udebs
+  * [Config] Ship bnx2 firmware in nic-modules udeb
+    - LP: #384861
+
+  [ Luke Yelavich ]
+
+  * [Config] ports - Import of ports architectures into kernel packaging
+    infrastructure
+  * [Config] ports - Do not update ports kernel configurations by default
+  * [Config] ports - Disable ABI checking for ports architectures
+  * [Config] ports - Build drivers in ubuntu sub-directory on powerpc
+  * [Config] ports - Add control.d/vars.* files for ports architectures
+  * [Config] ports - Add ports architectures for linux-libc-dev
+  * [Config] ports - Create powerpc specific message-modules and
+    block-modules udebs
+  * [Config] ports - Add configuration files for ports architectures
+
+  [ Manoj Iyer ]
+
+  * [Config] Enable CONFIG_BLK_DEV_AEC62XX=m for amd64 and i386
+    - LP: #329864
+
+  [ Michael Casadevall ]
+
+  * [Config] ports - Fix compression of kernels
+
+  [ Stefan Bader ]
+
+  * [Upstream] mmc: prevent dangling block device from accessing stale
+    queues
+    - LP: #383668
+
+  [ Tim Gardner ]
+
+  * [Config] Recommend grub-pc in linux-image
+    - LP: #385741
+  * [Config] Implement i386 generic and generic-pae flavours
+  * [Config] ports - Add control info after integrating ports arches
+  * [Config] Removed auto-generated files from git
+  * [Config] Added netxen_nic to nic-modules
+    - LP: #389603
+
+  [ Matt Zimmerman ]
+
+  * Rename linux-doc-PKGVER to linux-doc and clean up its description
+    - LP: #382115
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 15 Jun 2009 14:38:26 -0600
+
+linux (2.6.30-9.10) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * [Config] CONFIG_SECURITY_TOMOYO=y (amd64, i386, lpia)
+  * [Config] CONFIG_KEXEC_JUMP=y (amd64, lpia)
+  * [Config] CONFIG_LENOVO_SL_LAPTOP=m (amd64, lpia)
+  * [Config] CONFIG_POHMELFS_CRYPTO=y (i386, amd64)
+  * [Config] CONFIG_SERIAL_MAX3100=m (i386, amd64, lpia)
+  * [Config] CONFIG_VIDEO_GO7007=m (amd64, i386)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30 final
+
+ -- Andy Whitcroft <apw@canonical.com>  Fri, 05 Jun 2009 11:42:53 +0100
+
+linux (2.6.30-8.9) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Config update removed the following options:
+        CONFIG_EDAC_AMD8111=m
+        CONFIG_EDAC_AMD8131=m
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc8
+
+ -- Andy Whitcroft <apw@canonical.com>  Wed, 03 Jun 2009 09:21:13 +0100
+
+linux (2.6.30-7.8) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Enabled NEW configration options:
+      Paravirtualization layer for spinlocks (PARAVIRT_SPINLOCKS) [N/y/?] Y
+      Cisco FNIC Driver (FCOE_FNIC) [N/m/y/?] M
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc7
+
+ -- Andy Whitcroft <apw@canonical.com>  Sat, 23 May 2009 23:47:24 +0100
+
+linux (2.6.30-6.7) karmic; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Dropped: UBUNTU: SAUCE: input: Blacklist digitizers from joydev.c (now
+    upstream)
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc6
+
+ -- Andy Whitcroft <apw@canonical.com>  Mon, 18 May 2009 18:05:54 +0100
+
+linux (2.6.30-5.6) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enable Keyspan USB serial device firmware in kernel module
+    - LP: #334285
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc5
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 11 May 2009 12:02:16 -0600
+
+linux (2.6.30-4.5) karmic; urgency=low
+
+  [ Colin Watson ]
+
+  * Build-Conflict with findutils (= 4.4.1-1ubuntu1), to avoid
+    /usr/include/asm/* going missing
+    - LP: #373214
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 May 2009 11:09:08 +0200
+
+linux (2.6.30-3.4) karmic; urgency=low
+
+  [ Kees Cook ]
+
+  * SAUCE: [x86] implement cs-limit nx-emulation for ia32
+    - LP: #369978
+
+  [ Stefan Bader ]
+
+  * SAUCE: input: Blacklist digitizers from joydev.c
+    - LP: #300143
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 01 May 2009 14:00:42 -0600
+
+linux (2.6.30-2.3) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] Enabled CC_STACKPROTECTOR=y for all x86en
+    - LP: #369152
+  * SAUCE: Default to i915_modeset=0 if CONFIG_DRM_I915_KMS=y
+  * [Config] CONFIG_DRM_I915_KMS=y
+  * [Config] Set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR to appropriate ARCH
+    minimums
+
+  [ Upstream Kernel Changes ]
+
+  * rebased to 2.6.30-rc4
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 30 Apr 2009 09:17:05 -0600
+
+linux (2.6.30-1.2) karmic; urgency=low
+
+  [ Tim Gardner ]
+
+  * [Config] armel: disable staging drivers, fixes FTBS
+  * [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS
+
+  [ Upstream Kernel Changes ]
+
+  * mpt2sas: Change reset_type enum to avoid namespace collision.
+    Submitted upstream.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 28 Apr 2009 16:54:41 -0600
+
+linux (2.6.30-1.1) karmic; urgency=low
+
+  * Initial release after rebasing against v2.6.30-rc3
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 12 Mar 2009 19:16:07 -0600
--- linux-ec2-2.6.32.orig/debian.master/changelog.historical
+++ linux-ec2-2.6.32/debian.master/changelog.historical
@@ -0,0 +1,4171 @@
+
+linux (2.6.28-9.31) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: cpufreq-nforce2: probe failures are not errors
+    - LP: #332170
+  * SAUCE: mmc: add MODALIAS linkage for MMC/SD devices
+    - LP: #30335
+  * remove test-suspend script
+    - LP: #333856
+
+  [ Kees Cook ]
+
+  * handle relative paths in modules.dep
+    Fixes 2.6.28-9.30 FTBS.
+
+  [ Upstream Kernel Changes ]
+
+  * ricoh_mmc: Handle newer models of Ricoh controllers
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 11 Mar 2009 08:19:24 -0600
+
+linux (2.6.28-9.30) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * ARM:mx51 Add SoC and board support for mx51 platforms
+  * ARM:mx51 Add CONFIG_ARCH_MXC_CANONICAL to disable parts of Freescale's
+    code
+  * MMC: Add support for 8-bit cards
+  * Add ARM:MX51 SoC support to the build system
+  * ARM: Make ARM arch aware of ubuntu/ drivers
+  * ARM: Add imx51 configuration
+  * Disable d-i modules for imx51 and mv78xx0
+  * Disable Apparmor on boot for ARM
+  * Updating imx51 config
+
+  [ Jason Liu ]
+
+  * Do not use OOB with MLC NAND
+
+  [ Richard Zhu ]
+
+  * Support the eMMC4.3 card
+
+  [ Rob Herring ]
+
+  * ARM: Add more cache memory types macros
+
+  [ Tim Gardner ]
+
+  * Set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y for i386/amd64/lpia
+
+  [ Manoj Iyer ]
+
+  * Enable CONFIG_RTL8187SE=m
+
+  [ Upstream Kernel Changes ]
+
+  * USB: EHCI: slow down ITD reuse
+    - LP: #329437
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 08 Mar 2009 14:14:15 -0600
+
+linux (2.6.28-9.29) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * link-headers -- only link directories which do not already exist
+    - LP: #315252
+
+  [ Daniel Marjamäki ]
+
+  * SAUCE: (drop after 2.6.28) netxen: fix memory leak in
+    drivers/net/netxen_nic_init.c
+    - LP: #330813
+
+  [ Dhananjay Phadke ]
+
+  * SAUCE: (drop after 2.6.28) netxen: fix endianness in firmware commands
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix ipv6 offload and tx cleanup
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix link speed reporting for some
+    boards
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: firmware init fix
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: cleanup mac list on driver unload
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: hold tx lock while sending firmware
+    commands
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: handle dma mapping failures
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: avoid invalid iounmap
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: include ipv6.h (fixes build failure)
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix vlan tso/checksum offload
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: reduce memory footprint
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: revert jumbo ringsize
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: fix msi-x interrupt handling
+    - LP: #330813
+  * SAUCE: (drop after 2.6.28) netxen: remove pcie workaround
+    - LP: #330813
+
+  [ Hannes Eder ]
+
+  * SAUCE: (drop after 2.6.28) drivers/net/netxen: fix sparse warnings: use
+    NULL pointer instead of plain integer
+    - LP: #330813
+
+  [ Huaxu Wan ]
+
+  * SAUCE: report rfkill changes event if interface is down
+    - LP: #193970
+
+  [ Tim Gardner ]
+
+  * MV78XX0 must specify a target in the vars definition.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "ext4: wait on all pending commits in ext4_sync_fs()"
+  * jbd2: Fix return value of jbd2_journal_start_commit()
+  * jbd2: Avoid possible NULL dereference in
+    jbd2_journal_begin_ordered_truncate()
+  * ext4: Fix to read empty directory blocks correctly in 64k
+  * ext4: Fix lockdep warning
+  * ext4: Initialize preallocation list_head's properly
+  * ext4: Implement range_cyclic in ext4_da_writepages instead of
+    write_cache_pages
+  * ext4: Fix NULL dereference in ext4_ext_migrate()'s error handling
+  * ext4: Add fallback for find_group_flex
+  * ext4: Fix deadlock in ext4_write_begin() and ext4_da_write_begin()
+  * Added mv78xx0 flavor
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 06 Mar 2009 06:13:31 -0700
+
+linux (2.6.28-8.28) jaunty; urgency=low
+
+  [ Alexey Starikovskiy ]
+
+  * SAUCE: ACPI: EC: Limit workaround for ASUS notebooks even more
+    - LP: #288385
+
+  [ Scott James Remnant ]
+
+  * SAUCE: Auto-load esp module when device opened.
+  * SAUCE: Auto-load bridge module when socket opened.
+  * SAUCE: Auto-load af_netlink module when socket opened.
+  * SAUCE: Auto-load wanrouter module when socket opened.
+  * SAUCE: Auto-load ip_queue module when socket opened.
+  * SAUCE: Auto-load ip6_queue module when socket opened.
+  * SAUCE: Auto-load cn module when socket opened.
+  * SAUCE: Auto-load scsi_transport_iscsi module when socket opened.
+  * SAUCE: Auto-load ftl module when device opened.
+  * SAUCE: Auto-load pcd module when device opened.
+  * SAUCE: Auto-load pf module when device opened.
+  * SAUCE: Auto-load nftl module when device opened.
+  * SAUCE: Auto-load mousedev module when psaux device opened.
+  * SAUCE: Auto-load mousedev module when /dev/input/mice opened.
+  * SAUCE: Auto-load rng-core module when device opened.
+  * SAUCE: Auto-load openprom module when device opened.
+  * SAUCE: Auto-load applicom module when device opened.
+  * SAUCE: Auto-load toshiba module when device opened.
+  * SAUCE: Auto-load cyclades module when device opened.
+  * SAUCE: Auto-load riscom8 module when device opened.
+  * SAUCE: Auto-load specialix module when device opened.
+  * SAUCE: Auto-load videodev module when device opened.
+  * SAUCE: Auto-load i2c_dev module when device opened.
+  * SAUCE: Auto-load mtdchar module when device opened.
+  * SAUCE: Auto-load pt module when device opened.
+  * SAUCE: Auto-load pg module when device opened.
+  * SAUCE: Auto-load cdc_acm module when device opened.
+  * SAUCE: Auto-load msr module when device opened.
+  * SAUCE: Auto-load cpuid module when device opened.
+  * SAUCE: quickcam: Enable double-buffering by default
+  * SAUCE: libata: Ignore HPA by default.
+  * SAUCE: hostap: Change initial operation mode to managed (infra)
+  * SAUCE: floppy: Provide a PnP device table in the module.
+    - LP: #255651
+  * SAUCE: Auto-load mwave module when device opened.
+  * Build CONFIG_FUSE_FS into kernel, not as module.
+
+  [ Stefan Bader ]
+
+  * Enable build of ext4 as a module on LPIA
+    - LP: #331848
+
+  [ Tim Gardner ]
+
+  * Update configs to fix LPIA FTBS
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 05 Mar 2009 10:43:24 -0700
+
+linux (2.6.28-8.27) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs (arm:ixp4xx)
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: enable Intel HDMI output
+
+  [ Manoj Iyer ]
+
+  * SAUCE: Added quirk for Linksys WUSB600N USB wifi-n networking adapter
+    - LP: #323473
+
+  [ Steve Beattie ]
+
+  * fix apparmor memory leak on unlinked file ops
+    - LP: #329489
+
+  [ Tim Gardner ]
+
+  * SAUCE: Dell XPS710 reboot quirk
+    - LP: #323592
+  * SAUCE: (drop after 2.6.28) ieee80211: Add infrastructure to obsolete
+    scan results
+    - LP: #336055
+  * Add modules.order to the linux-image package.
+
+  [ Upstream Kernel Changes ]
+
+  * iwlwifi: fix time interval misuse in iwl_poll_{direct_}bit
+  * x86: only scan the root bus in early PCI quirks
+    - LP: #267295
+  * ALSA: hda - Intel HDMI audio support
+  * ALSA: hda - Fix unused function in patch_intelhdmi.c
+  * ALSA: handle SiI1392 HDMI codec in patch_intelhdmi.c
+  * ALSA: hda-intel: reorder HDMI audio enabling sequence
+  * ALSA: introduce snd_print_pcm_rates()
+  * ALSA: create hda_eld.c for ELD routines and proc interface
+  * ALSA: ELD proc interface for HDMI sinks
+  * ALSA: hda: make standalone hdmi_fill_audio_infoframe()
+  * ALSA: hda: make global snd_print_channel_allocation()
+  * ALSA: hda: HDMI channel allocations for audio infoframe
+  * ALSA: hda: HDMI channel mapping cleanups
+  * ALSA: hda: minor code cleanups
+  * ALSA: hda: rename sink_eld to hdmi_eld
+  * ALSA: hda - Release ELD proc file
+  * ALSA: hda - minor HDMI code cleanups
+  * ALSA: hda - report selected CA index for Audio InfoFrame
+  * ALSA: hda - Add Intel vendor id string
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 25 Feb 2009 14:23:46 -0700
+
+linux (2.6.28-8.26) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs (armel:ixp4xx)
+    - LP: #331510
+
+  [ Tim Gardner ]
+
+  * Add more missing modules
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 24 Feb 2009 06:58:53 -0700
+
+linux (2.6.28-8.25) jaunty; urgency=low
+
+  [ Scott James Remnant ]
+
+  * SAUCE: Prefer powernow-k8 to acpi-cpufreq
+  * Change CONFIG_X86_P4_CLOCKMOD to be a module again.
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Initialize the new
+    group descriptor when resizing the filesystem"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add sanity check
+    to make_indexed_dir"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: only use
+    i_size_high for regular files"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add sanity checks
+    for the superblock before mounting the filesystem"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix
+    s_dirty_blocks_counter if block allocation failed with nodelalloc"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Init the complete
+    page while building buddy cache"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Don't allow new
+    groups to be added during block allocation"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: mark the
+    blocks/inode bitmap beyond end of group as used"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Use new
+    buffer_head flag to check uninit group bitmaps initialization"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix the race
+    between read_inode_bitmap() and ext4_new_inode()"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix race between
+    read_block_bitmap() and mark_diskspace_used()"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: don't use blocks
+    freed but not yet committed in buddy cache init"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: cleanup mballoc
+    header files"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Use
+    EXT4_GROUP_INFO_NEED_INIT_BIT during resize"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add blocks added
+    during resize to bitmap"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Don't overwrite
+    allocation_context ac_status"
+  * Revert "SAUCE: (revert before 2.6.28.y update) jbd2: Add barrier not
+    supported test to journal_wait_on_commit_record"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Widen type of
+    ext4_sb_info.s_mb_maxs[]"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: avoid ext4_error
+    when mounting a fs with a single bg"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Fix the delalloc
+    writepages to allocate blocks at the right offset."
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: tone down
+    ext4_da_writepages warnings"
+  * Revert "SAUCE: (revert before 2.6.28.y update) ext4: Add support for
+    non-native signed/unsigned htree hash algorithms"
+  * Enabled X86_ACPI_CPUFREQ=y
+
+  [ Upstream Kernel Changes ]
+
+  * ath9k: quiet harmless ForceXPAon messages
+    - LP: #321474
+  * [WATCHDOG] iTCO_wdt: fix SMI_EN regression 2
+    - LP: #314050
+  * pid: implement ns_of_pid
+  * mqueue: fix si_pid value in mqueue do_notify()
+  * powerpc/vsx: Fix VSX alignment handler for regs 32-63
+  * sata_nv: give up hardreset on nf2
+  * Fix Intel IOMMU write-buffer flushing
+  * SCSI: libiscsi: fix iscsi pool leak
+  * x86/cpa: make sure cpa is safe to call in lazy mmu mode
+  * sched: SCHED_OTHER vs SCHED_IDLE isolation
+  * x86, vm86: fix preemption bug
+  * Add support for VT6415 PCIE PATA IDE Host Controller
+  * ext2/xip: refuse to change xip flag during remount with busy inodes
+  * 3c505: do not set pcb->data.raw beyond its size
+  * Bluetooth: Fix TX error path in btsdio driver
+  * ext4: Add support for non-native signed/unsigned htree hash algorithms
+  * ext4: tone down ext4_da_writepages warnings
+  * ext4: Fix the delalloc writepages to allocate blocks at the right
+    offset.
+  * ext4: avoid ext4_error when mounting a fs with a single bg
+  * ext4: Widen type of ext4_sb_info.s_mb_maxs[]
+  * jbd2: Add barrier not supported test to journal_wait_on_commit_record
+  * ext4: Don't overwrite allocation_context ac_status
+  * ext4: Add blocks added during resize to bitmap
+  * ext4: Use EXT4_GROUP_INFO_NEED_INIT_BIT during resize
+  * ext4: cleanup mballoc header files
+  * ext4: don't use blocks freed but not yet committed in buddy cache init
+  * ext4: Fix race between read_block_bitmap() and mark_diskspace_used()
+  * ext4: Fix the race between read_inode_bitmap() and ext4_new_inode()
+  * ext4: Use new buffer_head flag to check uninit group bitmaps
+    initialization
+  * ext4: mark the blocks/inode bitmap beyond end of group as used
+  * ext4: Don't allow new groups to be added during block allocation
+  * ext4: Init the complete page while building buddy cache
+  * ext4: Fix s_dirty_blocks_counter if block allocation failed with
+    nodelalloc
+  * ext4: Add sanity checks for the superblock before mounting the
+    filesystem
+  * ext4: only use i_size_high for regular files
+  * ext4: Add sanity check to make_indexed_dir
+  * ext4: Initialize the new group descriptor when resizing the filesystem
+  * Fix longstanding "error: storage size of '__mod_dmi_device_table' isn't
+    known"
+  * Linux 2.6.28.7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 19 Feb 2009 06:45:55 -0700
+
+linux (2.6.28-8.24) jaunty; urgency=low
+
+  [ Scott James Remnant ]
+
+  * Change CPU_FREQ_DEFAULT_GOV_ONDEMAND to y
+  * SAUCE: Link acpi-cpufreq.o first
+
+  [ Tim Gardner ]
+
+  * Build in CPU Frequency scaling drivers
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 18 Feb 2009 06:12:24 -0700
+
+linux (2.6.28-8.23) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * include the kernel configuration in the sub-flavour images
+    - LP: #328859
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: (drop after 2.6.28) [eCryptfs] Regression in unencrypted
+    filename symlinks" in favor of upstream commit.
+  * Fix compile issues with qc-usb
+  * SAUCE: (remove after 2.6.28) V4L/DVB (10216): saa7127: fix broken
+    S-Video with saa7129
+    - LP: #329267
+
+  [ Upstream Kernel Changes ]
+
+  * Subject:SAUCE: LP#193970 iwlagn: fix hw-rfkill while the interface is
+    down
+    - LP: #193970
+  * x86, vmi: put a missing paravirt_release_pmd in pgd_dtor
+  * nbd: fix I/O hang on disconnected nbds
+  * mac80211: restrict to AP in outgoing interface heuristic
+  * w1: w1 temp calculation overflow fix
+  * zd1211rw: adding 0ace:0xa211 as a ZD1211 device
+  * zd1211rw: treat MAXIM_NEW_RF(0x08) as UW2453_RF(0x09) for TP-Link
+    WN322/422G
+  * parport: parport_serial, don't bind netmos ibm 0299
+  * syscall define: fix uml compile bug
+  * kernel-doc: fix syscall wrapper processing
+  * Fix page writeback thinko, causing Berkeley DB slowdown
+  * write-back: fix nr_to_write counter
+  * writeback: fix break condition
+  * mm: rearrange exit_mmap() to unlock before arch_exit_mmap
+  * powerpc/fsl-booke: Fix mapping functions to use phys_addr_t
+  * lockd: fix regression in lockd's handling of blocked locks
+  * sctp: Fix crc32c calculations on big-endian arhes.
+  * sctp: Correctly start rtx timer on new packet transmissions.
+  * sctp: Properly timestamp outgoing data chunks for rtx purposes
+  * net: Fix frag_list handling in skb_seq_read
+  * net: Fix OOPS in skb_seq_read().
+  * drivers/net/skfp: if !capable(CAP_NET_ADMIN): inverted logic
+  * ipv4: fix infinite retry loop in IP-Config
+  * net: Fix userland breakage wrt. linux/if_tunnel.h
+  * net: packet socket packet_lookup_frame fix
+  * packet: Avoid lock_sock in mmap handler
+  * sungem: Soft lockup in sungem on Netra AC200 when switching interface
+    up
+  * udp: Fix UDP short packet false positive
+  * udp: increments sk_drops in __udp_queue_rcv_skb()
+  * ipv6: Disallow rediculious flowlabel option sizes.
+  * ipv6: Copy cork options in ip6_append_data
+  * net: 4 bytes kernel memory disclosure in SO_BSDCOMPAT gsopt try #2
+  * sky2: fix hard hang with netconsoling and iface going up
+  * tun: Add some missing TUN compat ioctl translations.
+  * tun: Fix unicast filter overflow
+  * virtio_net: Fix MAX_PACKET_LEN to support 802.1Q VLANs
+  * tcp: splice as many packets as possible at once
+  * tcp: Fix length tcp_splice_data_recv passes to skb_splice_bits.
+  * sparc: Enable syscall wrappers for 64-bit (CVE-2009-0029)
+  * sparc64: Annotate sparc64 specific syscalls with SYSCALL_DEFINEx()
+  * ALSA: hda - Add missing terminator in slave dig-out array
+  * ALSA: mtpav - Fix initial value for input hwport
+  * HID: adjust report descriptor fixup for MS 1028 receiver
+  * ide/libata: fix ata_id_is_cfa() (take 4)
+  * libata: fix EH device failure handling
+  * netfilter: fix tuple inversion for Node information request
+  * netfilter: xt_sctp: sctp chunk mapping doesn't work
+  * x86: microcode_amd: fix wrong handling of equivalent CPU id
+  * ide-cd: fix DMA for non bio-backed requests
+  * net: Fix data corruption when splicing from sockets.
+  * Linux 2.6.28.6
+  * eCryptfs: Regression in unencrypted filename symlinks
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 16 Feb 2009 06:43:51 -0700
+
+linux (2.6.28-8.22) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Remove perm-blacklist
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: psmouse/synaptics: ensure we reset the device on resume
+    - LP: #317270
+
+  [ Tim Gardner ]
+
+  * Add lpia to getabi script
+  * SAUCE: tracer for sreadahead
+
+ -- Amit Kucheria <amit.kucheria@ubuntu.com>  Fri, 13 Feb 2009 15:23:21 +0200
+
+linux (2.6.28-8.21) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: switch the Asus Pundit P1-AH2 to old acpi sleep ordering
+    - LP: #327267
+
+  [ Tim Gardner ]
+
+  * Added LPIA arch support
+  * Added libdrm-dev as a 'Replaces' to linux-libc-dev
+  * SAUCE: LPIA support for 9202 HDA Sigmatel codec
+  * SAUCE: Add an X86_LPIA Kconfig option
+  * SAUCE: UHCI USB quirk for resume
+  * SAUCE: LPIA Reboot fix for Intel Crownbeach development boards
+  * SAUCE: LPIA  Logical reset of USB port on resume
+  * Set CONFIG_WIRELESS_OLD_REGULATORY=n, added wireless-crda
+    as an install dependency.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "Revert "x86, early_ioremap: fix fencepost error""
+    - LP: #312554
+  * drm/i915: capture last_vblank count at IRQ uninstall time too
+    - LP: #320813
+  * drm/i915: add get_vblank_counter function for GM45
+    - LP: #320813
+  * Staging: comedi: fix Kbuild
+  * Staging: meilhaus: fix Kbuild
+  * Staging: android: binder: fix arm build errors
+  * Staging: android: timed_gpio: Fix build to build on kernels after
+    2.6.25.
+  * Staging: android: fix build error on 64bit boxes
+  * Staging: android: Add lowmemorykiller documentation.
+  * Staging: android: task_get_unused_fd_flags: fix the wrong usage of
+    tsk->signal
+  * staging: agnx: drivers/staging/agnx/agnx.h needs <linux/io.h>
+  * Staging: usbip: usbip_start_threads(): handle kernel_thread failure
+  * Staging: poch: fix verification of memory area
+  * Documentation: move DMA-mapping.txt to Doc/PCI/
+  * sgi-xp: fix writing past the end of kzalloc()'d space
+  * do_wp_page: fix regression with execute in place
+  * wait: prevent exclusive waiter starvation
+  * shm: fix shmctl(SHM_INFO) lockup with !CONFIG_SHMEM
+  * revert "rlimit: permit setting RLIMIT_NOFILE to RLIM_INFINITY"
+  * prevent kprobes from catching spurious page faults
+  * sound: usb-audio: handle wMaxPacketSize for FIXED_ENDPOINT devices
+  * md: Ensure an md array never has too many devices.
+  * md: Fix a bug in linear.c causing which_dev() to return the wrong
+    device.
+  * ACPI: Enable bit 11 in _PDC to advertise hw coord
+  * ACPI: dock: Don't eval _STA on every show_docked sysfs read
+  * ieee1394: ohci1394: increase AT req. retries, fix ack_busy_X from
+    Panasonic camcorders and others
+  * firewire: ohci: increase AT req. retries, fix ack_busy_X from Panasonic
+    camcorders and others
+  * firewire: sbp2: fix DMA mapping leak on the failure path
+  * firewire: sbp2: add workarounds for 2nd and 3rd generation iPods
+  * ieee1394: sbp2: add workarounds for 2nd and 3rd generation iPods
+  * module: remove over-zealous check in __module_get()
+  * x86: APIC: enable workaround on AMD Fam10h CPUs
+  * eeepc-laptop: fix oops when changing backlight brightness during
+    eeepc-laptop init
+  * eeepc-laptop: Add support for extended hotkeys
+  * e1000: fix bug with shared interrupt during reset
+  * e1000: Fix PCI enable to honor the need_ioport flag
+  * agp/intel: Fix broken ® symbol in device name.
+  * ALSA: hda - Add quirk for FSC Amilo Xi2550
+  * ALSA: hda - Add missing COEF initialization for ALC887
+  * ALSA: hda - Add missing initialization for ALC272
+  * asus_acpi: Add R1F support
+  * panasonic-laptop: fix X[ ARRAY_SIZE(X) ]
+  * ACPI: Skip the first two elements in the _BCL package
+  * ACPI: proc_dir_entry 'video/VGA' already registered
+  * ACPI: disable ACPI cleanly when bad RSDP found
+  * ACPICA: Fix table entry truncation calculation
+  * PCI: properly clean up ASPM link state on device remove
+  * PCI: return error on failure to read PCI ROMs
+  * seq_file: move traverse so it can be used from seq_read
+  * seq_file: fix big-enough lseek() + read()
+  * serial: set correct baud_base for Oxford Semiconductor Ltd EXSYS
+    EX-41092 Dual 16950 Serial adapter
+  * Add support for '8-port RS-232 MIC-3620 from advantech'
+  * mm: fix error case in mlock downgrade reversion
+  * elf core dump: fix get_user use
+  * ACPI: video: Fix reversed brightness behavior on ThinkPad SL series
+  * ipw2200: fix scanning while associated
+  * XFS: set b_error from bio error in xfs_buf_bio_end_io
+  * Revert USB: option: add Pantech cards
+  * USB: option: New mobile broadband modems to be supported
+  * USB: new id for ti_usb_3410_5052 driver
+  * USB: two more usb ids for ti_usb_3410_5052
+  * USB: usb-storage: add Pentax to the bad-vendor list
+  * sata_via: Add VT8261 support
+  * nbd: do not allow two clients at the same time
+  * sctp: Fix another socket race during accept/peeloff
+  * Linux 2.6.28.5
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 09 Feb 2009 16:11:28 -0700
+
+linux (2.6.28-7.20) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * SAUCE: Input: atkbd - Samsung NC10 key repeat fix
+
+  [ Upstream Kernel Changes ]
+
+  * Manually revert "mlock: downgrade mmap sem while populating mlocked
+    regions"
+  * xen: make sysfs files behave as their names suggest
+  * sata_mv: fix 8-port timeouts on 508x/6081 chips
+  * m68knommu: set NO_DMA
+  * PCI/MSI: bugfix/utilize for msi_capability_init()
+  * x86: use early clobbers in usercopy*.c
+  * netfilter: ctnetlink: fix scheduling while atomic
+  * orinoco: move kmalloc(..., GFP_KERNEL) outside spinlock in
+    orinoco_ioctl_set_genie
+  * fbdev/atyfb: Fix DSP config on some PowerMacs & PowerBooks
+  * kmalloc: return NULL instead of link failure
+  * sata_nv: rename nv_nf2_hardreset()
+  * sata_nv: fix MCP5x reset
+  * sata_nv: ck804 has borked hardreset too
+  * Fix memory corruption in console selection
+  * Add enable_ms to jsm driver
+  * nfsd: only set file_lock.fl_lmops in nfsd4_lockt if a stateowner is
+    found
+  * nfsd: Ensure nfsv4 calls the underlying filesystem on LOCKT
+  * iwlwifi: fix rs_get_rate WARN_ON()
+  * p54: fix lm87 checksum endianness
+  * p54: fix p54_read_eeprom to cope with tx_hdr_len
+  * p54usb: rewriting rx/tx routines to make use of usb_anchor's facilities
+  * minstrel: fix warning if lowest supported rate index is not 0
+  * PCI: irq and pci_ids patch for Intel Tigerpoint DeviceIDs
+  * cpuidle: Add decaying history logic to menu idle predictor
+  * ACPI: Avoid array address overflow when _CST MWAIT hint bits are set
+  * video: always update the brightness when poking "brightness"
+  * Newly inserted battery might differ from one just removed, so update of
+    battery info fields is required.
+  * ACPI: Do not modify SCI_EN directly
+  * dlm: initialize file_lock struct in GETLK before copying conflicting
+    lock
+  * sata_mv: Fix chip type for Hightpoint RocketRaid 1740/1742
+  * ACPICA: Allow multiple backslash prefix in namepaths
+  * Linux 2.6.28.4
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 07 Feb 2009 18:53:42 -0700
+
+linux (2.6.28-7.19) jaunty; urgency=low
+
+  * Fix missing modules FTBS
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 05 Feb 2009 15:28:15 -0700
+
+linux (2.6.28-7.18) jaunty; urgency=low
+
+  [ Alok Kataria ]
+
+  * SAUCE: (drop after 2.6.29) x86: add a synthetic TSC_RELIABLE feature
+    bit
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: add X86_FEATURE_HYPERVISOR feature bit
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Hypervisor detection and get tsc_freq
+    from hypervisor
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Add a synthetic TSC_RELIABLE feature
+    bit.
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: Skip verification by the watchdog for
+    TSC clocksource.
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: VMware: Fix vmware_get_tsc code
+    - LP: #319945
+  * SAUCE: (drop after 2.6.29) x86: vmware: look for DMI string in the
+    product serial key
+    - LP: #319945
+
+  [ Andy Whitcroft ]
+
+  * SAUCE: toshiba_acpi -- pull in current -dev version of driver
+    - LP: #269831
+  * SAUCE: toshiba_acpi -- add acpi hotkey kernel thread
+    - LP: #269831
+  * move toshiba laptops back from tlsup to toshiba_acpi
+    - LP: #269831
+
+  [ Aneesh Kumar K.V ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix the delalloc
+    writepages to allocate blocks at the right offset.
+  * SAUCE: (revert before 2.6.28.y update) ext4: avoid ext4_error when
+    mounting a fs with a single bg
+  * SAUCE: (revert before 2.6.28.y update) ext4: Don't overwrite
+    allocation_context ac_status
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add blocks added during
+    resize to bitmap
+  * SAUCE: (revert before 2.6.28.y update) ext4: Use
+    EXT4_GROUP_INFO_NEED_INIT_BIT during resize
+  * SAUCE: (revert before 2.6.28.y update) ext4: cleanup mballoc header
+    files
+  * SAUCE: (revert before 2.6.28.y update) ext4: don't use blocks freed but
+    not yet committed in buddy cache init
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix race between
+    read_block_bitmap() and mark_diskspace_used()
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix the race between
+    read_inode_bitmap() and ext4_new_inode()
+  * SAUCE: (revert before 2.6.28.y update) ext4: Use new buffer_head flag
+    to check uninit group bitmaps initialization
+  * SAUCE: (revert before 2.6.28.y update) ext4: mark the blocks/inode
+    bitmap beyond end of group as used
+  * SAUCE: (revert before 2.6.28.y update) ext4: Don't allow new groups to
+    be added during block allocation
+  * SAUCE: (revert before 2.6.28.y update) ext4: Init the complete page
+    while building buddy cache
+  * SAUCE: (revert before 2.6.28.y update) ext4: Fix s_dirty_blocks_counter
+    if block allocation failed with nodelalloc
+
+  [ Hannes Eder ]
+
+  * SAUCE: (drop after 2.6.29) x86: vmware - fix sparse warnings
+    - LP: #319945
+
+  [ Luke Yelavich ]
+
+  * hid modules have hyphens instead of underscores in their names
+
+  [ Mark Fasheh ]
+
+  * SAUCE: (revert before 2.6.28.y update) jbd2: Add BH_JBDPrivateStart
+
+  [ Theodore Ts'o ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add support for non-native
+    signed/unsigned htree hash algorithms
+  * SAUCE: (revert before 2.6.28.y update) ext4: tone down
+    ext4_da_writepages warnings
+  * SAUCE: (revert before 2.6.28.y update) jbd2: Add barrier not supported
+    test to journal_wait_on_commit_record
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add sanity checks for the
+    superblock before mounting the filesystem
+  * SAUCE: (revert before 2.6.28.y update) ext4: only use i_size_high for
+    regular files
+  * SAUCE: (revert before 2.6.28.y update) ext4: Add sanity check to
+    make_indexed_dir
+  * SAUCE: (revert before 2.6.28.y update) jbd2: On a __journal_expect()
+    assertion failure printk "JBD2", not "EXT3-fs"
+  * SAUCE: (revert before 2.6.28.y update) ext4: Initialize the new group
+    descriptor when resizing the filesystem
+
+  [ Tyler Hicks ]
+
+  * SAUCE: (drop after 2.6.28) [eCryptfs] Regression in unencrypted
+    filename symlinks
+    - LP: #322532
+
+  [ Upstream Kernel Changes ]
+
+  * Input: atkbd - broaden the Dell DMI signatures
+    - LP: #261721
+  * ti_usb_3410_5052: support alternate firmware
+  * ath5k: fix mesh point operation
+  * mac80211: decrement ref count to netdev after launching mesh discovery
+  * inotify: clean up inotify_read and fix locking problems
+  * fuse: destroy bdi on umount
+  * fuse: fix missing fput on error
+  * fuse: fix NULL deref in fuse_file_alloc()
+  * x86, mm: fix pte_free()
+  * klist.c: bit 0 in pointer can't be used as flag
+  * sysfs: fix problems with binary files
+  * x86: fix page attribute corruption with cpa()
+  * USB: fix toggle mismatch in disable_endpoint paths
+  * sound: virtuoso: enable UART on Xonar HDAV1.3
+  * USB: usbmon: Implement compat_ioctl
+  * USB: fix char-device disconnect handling
+  * USB: storage: add unusual devs entry
+  * alpha: nautilus - fix compile failure with gcc-4.3
+  * alpha: fix vmalloc breakage
+  * resources: skip sanity check of busy resources
+  * rtl8187: Add termination packet to prevent stall
+  * it821x: Add ultra_mask quirk for Vortex86SX
+  * libata: pata_via: support VX855, future chips whose IDE controller use
+    0x0571
+  * serial_8250: support for Sealevel Systems Model 7803 COMM+8
+  * drm: stash AGP include under the do-we-have-AGP ifdef
+  * Fix OOPS in mmap_region() when merging adjacent VM_LOCKED file segments
+  * bnx2x: Block nvram access when the device is inactive
+  * ext3: Add sanity check to make_indexed_dir
+  * rtl8187: Fix error in setting OFDM power settings for RTL8187L
+  * epoll: drop max_user_instances and rely only on max_user_watches
+  * gpiolib: fix request related issue
+  * sgi-xpc: Remove NULL pointer dereference.
+  * sgi-xpc: ensure flags are updated before bte_copy
+  * include/linux: Add bsg.h to the Kernel exported headers
+  * ALSA: hda - Fix PCM reference NID for STAC/IDT analog outputs
+  * ALSA: hda - add another MacBook Pro 4, 1 subsystem ID
+  * ALSA: hda - Add quirk for HP DV6700 laptop
+  * crypto: authenc - Fix zero-length IV crash
+  * crypto: ccm - Fix handling of null assoc data
+  * x86, pat: fix reserve_memtype() for legacy 1MB range
+  * x86, pat: fix PTE corruption issue while mapping RAM using /dev/mem
+  * PCI hotplug: fix lock imbalance in pciehp
+  * dmaengine: fix dependency chaining
+  * NET: net_namespace, fix lock imbalance
+  * relay: fix lock imbalance in relay_late_setup_files
+  * Linux 2.6.28.3
+  * ALSA: Enable SPDIF output on ALC655
+  * ALSA: hda - Add ASUS V1Sn support
+  * ALSA: hda - support detecting HD Audio devices with PCI class code
+  * ALSA: hda: alc883 model for ASUS P5Q-EM boards
+  * ALSA: hda - Add quirk for MSI 7260 mobo
+  * ALSA: hda - Add quirk for Sony VAIO VGN-SR19XN
+  * ALSA: oxygen: add Claro halo support
+  * ALSA: hda - Add a new function to seek for a codec ID
+  * ALSA: patch_sigmatel: Add missing Gateway entries and autodetection
+  * ALSA: hda - More fixes on Gateway entries
+  * ALSA: hda - Add MCP67 HDMI support
+  * ALSA: hda - fix name for ALC1200
+  * LSA: hda - Add HP Acacia detection
+  * ALSA: hda - Add quirk for HP 2230s
+  * ALSA: hda - Add quirk for Dell Inspiron Mini9
+  * ALSA: hda - add support for Intel DX58SO board
+  * ALSA: hda - Fix silent headphone output on Panasonic CF-74
+  * ALSA: USB quirk for Logitech Quickcam Pro 9000 name
+  * ALSA: hda - add quirks for some 82801H variants to use ALC883_MITAC
+
+  [ Yasunori Goto ]
+
+  * SAUCE: (revert before 2.6.28.y update) ext4: Widen type of
+    ext4_sb_info.s_mb_maxs[]
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 02 Feb 2009 23:07:13 -0700
+
+linux (2.6.28-6.17) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Updating configs: ARMEL/versatile
+
+ -- Amit Kucheria <amit.kucheria@ubuntu.com>  Fri, 30 Jan 2009 13:36:59 +0200
+
+linux (2.6.28-6.16) jaunty; urgency=low
+
+  [ Luke Yelavich ]
+
+  * Add hid quirks to input-modules udeb
+
+  [ Tim Gardner ]
+
+  * Revert "[arm] Fix kexec on ARM by properly calling the relocation
+    function". This patch was deemed 'bogus' by Russell King on the
+    ARM mailing list.
+
+  [ Upstream Kernel Changes ]
+
+  * PCI: keep ASPM link state consistent throughout PCIe hierarchy
+  * security: introduce missing kfree
+  * rt2x00: add USB ID for the Linksys WUSB200.
+  * p54usb: Add USB ID for Thomson Speedtouch 121g
+  * lib/idr.c: use kmem_cache_zalloc() for the idr_layer cache
+  * sgi-xp: eliminate false detection of no heartbeat
+  * sched: fix update_min_vruntime
+  * IA64: Turn on CONFIG_HAVE_UNSTABLE_CLOCK
+  * sound: virtuoso: do not overwrite EEPROM on Xonar D2/D2X
+  * ALSA: hda - Add quirk for another HP dv5
+  * ALSA: hda - Fix HP dv5 mic input
+  * ALSA: hda - Don't reset HP pinctl in patch_sigmatel.c
+  * ALSA: hda - make laptop-eapd model back for AD1986A
+  * drivers/net/irda/irda-usb.c: fix buffer overflow
+  * usb-storage: add last-sector hacks
+  * usb-storage: set CAPACITY_HEURISTICS flag for bad vendors
+  * pkt_sched: sch_htb: Fix deadlock in hrtimers triggered by HTB
+  * ipv6: Fix fib6_dump_table walker leak
+  * sctp: Avoid memory overflow while FWD-TSN chunk is received with bad
+    stream ID
+  * pkt_sched: cls_u32: Fix locking in u32_change()
+  * r6040: fix wrong logic in mdio code
+  * r6040: save and restore MIER correctly in the interrupt routine
+  * r6040: bump release number to 0.19
+  * tcp: don't mask EOF and socket errors on nonblocking splice receive
+  * p54usb: fix traffic stalls / packet drop
+  * netfilter: x_tables: fix match/target revision lookup
+  * netfilter: ebtables: fix inversion in match code
+  * netfilter: nf_conntrack: fix ICMP/ICMPv6 timeout sysctls on big-endian
+  * dell_rbu: use scnprintf() instead of less secure sprintf()
+  * powerpc: is_hugepage_only_range() must account for both 4kB and 64kB
+    slices
+  * hwmon: (abituguru3) Fix CONFIG_DMI=n fallback to probe
+  * mm: write_cache_pages cyclic fix
+  * mm: write_cache_pages early loop termination
+  * mm: write_cache_pages writepage error fix
+  * mm: write_cache_pages integrity fix
+  * mm: write_cache_pages cleanups
+  * mm: write_cache_pages optimise page cleaning
+  * mm: write_cache_pages terminate quickly
+  * mm: write_cache_pages more terminate quickly
+  * mm: do_sync_mapping_range integrity fix
+  * mm: direct IO starvation improvement
+  * fs: remove WB_SYNC_HOLD
+  * fs: sync_sb_inodes fix
+  * fs: sys_sync fix
+  * Linux 2.6.28.2
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 25 Jan 2009 13:36:16 -0700
+
+linux (2.6.28-5.15) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Revert "Enabled CONFIG_PID_NS=y for i386/amd64"
+    Somehow this commit also reverted the 7 prior commits (which is bad).
+  * Enabled CONFIG_PID_NS=y for i386/amd64 (version 2)
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 22 Jan 2009 13:48:34 -0700
+
+linux (2.6.28-5.14) jaunty; urgency=low
+
+  [ Ben Collins ]
+
+  * lirc_gpio: Forward ported to current kernel (jaunty)
+  * configs: Enable LIRC_GPIO on 64-bit/32-bit x86
+    - LP: #298791
+
+  [ Jeff Layton ]
+
+  * SAUCE: cifs: make sure we allocate enough storage for socket address
+    - LP: #318565
+
+  [ Tim Gardner ]
+
+  * check-abi: Return success when ABI skip is requested and no ABI files exist.
+    This ought to fix the armel FTBS.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 22 Jan 2009 06:42:49 -0700
+
+linux (2.6.28-5.13) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: don't use buggy _BCL/_BCM/_BQC for backlight control"
+
+  [ Tim Gardner ]
+
+  * Fix udeb generation breakage caused by the previous armel versatile
+    flavour config update.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 21 Jan 2009 12:38:35 -0700
+
+linux (2.6.28-5.12) jaunty; urgency=low
+
+  [ Ante ]
+
+  * Update drbd to 8.3.0
+
+  [ Dave Airlie ]
+
+  * i915/drm: provide compat defines for userspace for certain struct
+
+  [ Eric Anholt ]
+
+  * drm/i915: Don't double-unpin buffers if we take a signal in
+  * drm/i915: Don't complain when interrupted while pinning in execbuffers.
+  * drm/i915: Don't allow objects to get bound while VT switched.
+
+  [ Jani Monoses ]
+
+  * Fix webcam having USB ID 0ac8:303b
+    - LP: #292086
+
+  [ Jesse Barnes ]
+
+  * drm/i915: set vblank enabled flag correctly across IRQ
+  * drm/i915: don't enable vblanks on disabled pipes
+
+  [ Michael Casadevall ]
+
+  * [arm] Fix kexec on ARM by properly calling the relocation function
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_PID_NS=y for i386/amd64
+  * SAUCE: Increase ATA_TMOUT_PMP_SRST_WAIT to 5 seconds.
+    - LP: #318978
+  * Update armel versatile config
+    - LP: #314789
+  * Enabled CONFIG_RT2860=m for i386/amd64
+  * Enabled CONFIG_RT2870=m for i386/amd64
+
+  [ Upstream Kernel Changes ]
+
+  * Input: atkbd - add keyboard quirk for HP Pavilion ZV6100 laptop
+    - LP: #291878
+  * ALSA: hda - Add quirk for another HP dv7
+  * ALSA: hda - Add quirk for HP6730B laptop
+  * ALSA: caiaq - Fix Oops with MIDI
+  * ALSA: hda - Fix typos for AD1882 codecs
+  * x86: fix intel x86_64 llc_shared_map/cpu_llc_id anomolies
+  * x86: default to SWIOTLB=y on x86_64
+  * CIFS: make sure that DFS pathnames are properly formed
+  * ring-buffer: prevent false positive warning
+  * ring-buffer: fix dangling commit race
+  * iwlwifi: use GFP_KERNEL to allocate Rx SKB memory
+  * tx493[89]ide: Fix length for __ide_flush_dcache_range
+  * tx4939ide: Do not use zero count PRD entry
+  * SCSI: eata: fix the data buffer accessors conversion regression
+  * USB: emi26: fix oops on load
+  * x86, UV: remove erroneous BAU initialization
+  * x86: fix incorrect __read_mostly on _boot_cpu_pda
+  * vmalloc.c: fix flushing in vmap_page_range()
+  * fs: symlink write_begin allocation context fix
+  * cgroups: fix a race between cgroup_clone and umount
+  * dm raid1: fix error count
+  * dm log: fix dm_io_client leak on error paths
+  * minix: fix add link's wrong position calculation
+  * md: fix bitmap-on-external-file bug.
+  * sched_clock: prevent scd->clock from moving backwards, take #2
+  * devices cgroup: allow mkfifo
+  * SCSI: aha152x_cs: Fix regression that keeps driver from using shared
+    interrupts
+  * ioat: fix self test for multi-channel case
+  * USB: isp1760: use a specific PLX bridge instead of any bdridge
+  * USB: isp1760: Fix probe in PCI glue code
+  * USB: unusual_devs.h additions for Pentax K10D
+  * inotify: fix type errors in interfaces
+  * Move compat system call declarations to compat header file
+  * Convert all system calls to return a long
+  * Rename old_readdir to sys_old_readdir
+  * Remove __attribute__((weak)) from sys_pipe/sys_pipe2
+  * Make sys_pselect7 static
+  * Make sys_syslog a conditional system call
+  * System call wrapper infrastructure
+  * powerpc: Enable syscall wrappers for 64-bit
+  * s390: enable system call wrappers
+  * System call wrapper special cases
+  * System call wrappers part 01
+  * System call wrappers part 02
+  * System call wrappers part 03
+  * System call wrappers part 04
+  * System call wrappers part 05
+  * System call wrappers part 06
+  * System call wrappers part 07
+  * System call wrappers part 08
+  * System call wrappers part 09
+  * System call wrappers part 10
+  * System call wrappers part 11
+  * System call wrappers part 12
+  * System call wrappers part 13
+  * System call wrappers part 14
+  * System call wrappers part 15
+  * System call wrappers part 16
+  * System call wrappers part 17
+  * System call wrappers part 18
+  * System call wrappers part 19
+  * System call wrappers part 20
+  * System call wrappers part 21
+  * System call wrappers part 22
+  * System call wrappers part 23
+  * System call wrappers part 24
+  * System call wrappers part 25
+  * System call wrappers part 26
+  * System call wrappers part 27
+  * System call wrappers part 28
+  * System call wrappers part 29
+  * System call wrappers part 30
+  * System call wrappers part 31
+  * System call wrappers part 32
+  * System call wrappers part 33
+  * s390 specific system call wrappers
+  * x86: fix RIP printout in early_idt_handler
+  * Fix timeouts in sys_pselect7
+  * USB: another unusual_devs entry for another bad Argosy storage device
+  * USB: storage: extend unusual range for 067b:3507
+  * USB: storage: recognizing and enabling Nokia 5200 cell phoes
+  * HID: fix error condition propagation in hid-sony driver
+  * fix switch_names() breakage in short-to-short case
+  * nfs: remove redundant tests on reading new pages
+  * eCryptfs: check readlink result was not an error before using it
+  * mvsas: increase port type detection delay to suit Seagate's 10k6 drive ST3450856SS 0003
+  * x86: avoid theoretical vmalloc fault loop
+  * ath9k: enable RXing of beacons on STA/IBSS
+  * mm lockless pagecache barrier fix
+  * powerpc: Disable Collaborative Memory Manager for kdump
+  * ibmvfc: Delay NPIV login retry and add retries
+  * ibmvfc: Improve async event handling
+  * getrusage: RUSAGE_THREAD should return ru_utime and ru_stime
+  * ath5k: ignore the return value of ath5k_hw_noise_floor_calibration
+  * mm: fix assertion
+  * XFS: truncate readdir offsets to signed 32 bit values
+  * Linux 2.6.28.1
+  * eCryptfs: Filename Encryption: Tag 70 packets
+  * eCryptfs: Filename Encryption: Header updates
+  * eCryptfs: Filename Encryption: Encoding and encryption functions
+  * eCryptfs: Filename Encryption: filldir, lookup, and readlink
+  * eCryptfs: Filename Encryption: mount option
+  * eCryptfs: Replace %Z with %z
+  * eCryptfs: Fix data types (int/size_t)
+  * eCryptfs: kerneldoc for ecryptfs_parse_tag_70_packet()
+  * eCryptfs: Clean up ecryptfs_decode_from_filename()
+  * fs/ecryptfs/inode.c: cleanup kerneldoc
+  * staging-p80211: Kill directly reference of netdev->priv
+  * staging-slicoss: Kill directly reference of netdev->priv
+  * staging-winbond: Kill directly reference of netdev->priv
+  * Staging: go7007: fixes due to video_usercopy api change
+  * Staging: go7007: fixes due v4l2_file_operations api change
+  * staging: correct dubious use of !x & y
+  * Staging: w35und: make wb35_probe() and wb35_disconnect() funtions static
+  * Staging: w35und: remove unused wb35_open() and wb35_close() functions
+  * Staging: w35und: use msleep() and udelay()
+  * Staging: w35und: remove the no-op pa_stall_execution macro
+  * Staging: w35und: purb typedef removal
+  * Staging: w35und: reg queue struct typedef removal
+  * Staging: w35und: wb35reg struct typedef removal
+  * Staging: w35und: padapter struct typedef removal
+  * Staging: w35und: merge wblinux struct to adapter
+  * Staging: w35und: wb35_probe() cleanup
+  * Staging: w35und: remove usb_submit_urb wrapper function
+  * Staging: w35und: remove usb_alloc_urb wrapper function
+  * w35und: remove dead code from wbusb_f.h
+  * Staging: w35und: remove true/false boolean macros
+  * Staging: w35und: OS_MEMORY_ALLOC wrapper removal
+  * Staging: w35und: usb_put_dev() is missing from wb35_disconnect()
+  * Staging: w35und: remove macro magic from MLME_GetNextPacket()
+  * Staging: w35und: plug memory leak in wbsoft_tx()
+  * Staging: w35und: move supported band initialization out of wb35_probe()
+  * Staging: w35und: remove timer wrappers
+  * Staging: w35und: remove atomic op wrappers
+  * Staging: w35und: remove memcpy/memcmp wrappers
+  * Staging: w35und: remove abs() and BIT() macros
+  * Staging: w35und: remove unused macros from common.h
+  * Staging: w35und: remove unused link status code
+  * Staging: w35und: #include cleanup
+  * Staging: w35und: remove some dead code
+  * Staging: w35und: move source files to one directory
+  * Staging: w35und: move struct wbsoft_priv to core.h and use it
+  * Staging: w35und: remove ->adapter from struct _HW_DATA_T
+  * Staging: w35und: clean up adapter.h a bit
+  * Staging: w35und: merge struct wb35_adapter to struct wbsoft_priv
+  * Staging: w35und: remove global struct ieee80211_hw
+  * Staging: w35und: inline DRIVER_AUTHOR and DRIVER_DESC macros
+  * Staging: w35und: clean up wblinux.c a bit
+  * Staging: w35und: remove unused ->ShutDowned member from struct
+    LOCAL_PARA
+  * Staging: w35und: move global wbsoft_enabled to struct wbsoft_priv
+  * Staging: w35und: move packet_came() to wb35rx.c
+  * Staging: w35und: remove ->skb_array from struct wbsoft_priv
+  * Staging: w35und: remove ->shutdown from struct wbsoft_priv
+  * Staging: w35und: make functions local to mds.c static
+  * Staging: w35und: make functions local to mlmetxrx.c static
+  * Staging: w35und: remove dead code from mto.c
+  * Staging: w35und: make functions local to wb35rx.c static
+  * Staging: w35und: make functions local to wb35tx.c static
+  * Staging: w35und: remove dead code from wbhal.c
+  * Staging: w35und: remove rxisr.c as dead code
+  * Staging: w35und: fix Kconfig
+  * Staging: w35und: fix config build warnings
+  * Staging: wlan-ng: Remove PCI/PLX/PCMCIA files.
+  * Staging: wlan-ng: Update Help text to mention prism3 devices.
+  * Staging: wlan-ng: Delete PCI/PLX/PCMCIA-specific code.
+  * Staging: wlan-ng: Make wlan-ng use WEXT mode by default.
+  * Staging: wlan-ng: Eliminate more <2.6 kernel support.
+  * Staging: wlan-ng: Eliminate all backwards-compatibility for <2.6.13 kernels.
+  * Staging: wlan-ng: Eliminate a boatload of tertiaryAP-only code.
+  * Staging: wlan-ng: Remove AP-only code from MLME functions.
+  * Staging: wlan-ng: Get rid of the MTU tests in the rx conversion path.
+  * Staging: wlan-ng: Eliminate one more rx mtu test.
+  * Staging: wlan-ng: Eliminate local 'version.h'
+  * Staging: wlan-ng: Eliminate usage of procfs.
+  * Staging: wlan-ng: Use standard kernel integer (u32/s32/etc) types.
+  * Staging: wlan-ng: Eliminate all backwards-compatible kernel code.
+  * Staging: wlan-ng: Wireless Extension support is mandatory.
+  * Staging: wlan-ng: use WIRELESS_EXT, not CONFIG_WIRELESS_EXT
+  * Staging: wlan-ng: Delete a large pile of now-unused code.
+  * Staging: wlan-ng: Delete a pile of unused mibs. And fix WEXT SET_TXPOWER.
+  * Staging: wlan-ng: Consolidate wlan-ng into a single module.
+  * Staging: wlan-ng: Purge all MIBs not used internally.
+  * Staging: wlan-ng: p80211netdev.c fix netdev alloc to prevent oops on device start
+  * Staging: wlan-ng: prism2_usb.c always enable the card in probe_usb
+  * Staging: wlan-ng: hfa384x_usb.c use newest version of 384x_drvr_start
+  * Staging: wlan-ng: p80211wext.c add latest changes & remove extra nulls from wext_handlers
+  * Staging: wlan-ng: p80211wext don't set default key id twice
+  * Staging: wlan-ng: hfa384x_usbin_callback: check for hardware removed
+  * Staging: wlan-ng: p80211conv.c copy code from wlan-ng-devel branch to not drop packets
+  * Staging: wlan-ng: remove unused #include <version.h>
+  * Staging: wlan-ng: p80211wext.c: use ARRAY_SIZE
+  * Staging: wlan-ng: fix compiler warnings
+  * Staging: wlan-ng: skb_p80211_to_ether() - payload_length is unsigned, check before subtraction
+  * Staging: at76_usb: update drivers/staging/at76_usb w/ mac80211 port
+  * Staging: at76_usb: fix build breakage
+  * Staging: at76_usb: remove compiler warnings
+  * Staging: at76_usb: fix up all remaining checkpatch.pl warnings
+  * Staging: at76_usb: cleanup dma on stack issues
+  * Staging: poch: Block size bug fix
+  * Staging: poch: Update TODO list
+  * Staging: poch: Correct pages from bytes.
+  * Staging: poch: minor fixes
+  * Staging: poch: Fix build warnings
+  * Staging: poch: Rx control register init
+  * Staging: poch: Fix user space protocol syncing
+  * Staging: poch: Fine grained locking
+  * Staging: sxg: remove typedefs
+  * Staging: sxg: break the build in a cleaner way when !x86
+  * Staging: sxg: update README
+  * staging: struct device - replace bus_id with dev_name(), dev_set_name()
+  * Staging: echo: remove typedefs
+  * Staging: echo: Lindent drivers/staging/echo
+  * Staging: go7007: saa7134 updates
+  * Staging: go7007: add sensoray 2250/2251 support
+  * Staging: go7007: Convert driver to use video_ioctl2
+  * Staging: go7007: annotate code pointers
+  * Staging: go7007: fix minor build warnings
+  * Staging: go7007: small cleanup
+  * Staging: go7007: add some more v4l2 ioctls
+  * Staging: et131x: Cleanup et131x_debug.h defines
+  * Staging: et131x: fix build failure
+  * Staging: et131x: remove unused variable in et1310_tx.c
+  * Staging: usbip: cleanup kerneldoc
+  * Staging: slicoss: use kzalloc
+  * Staging: slicoss: use correct type for memory allcations
+  * Staging: slicoss: use request_firmware
+  * Staging: add agnx wireless driver
+  * Staging: agnx: fix build errors due to ssid removal
+  * Staging: agnx: fix build errors due to rate control API changes
+  * Staging: agnx: fix build warnings
+  * Staging: add otus Atheros wireless network driver
+  * Staging: otus: fix netdev->priv usage
+  * Staging: otus: fix name clash
+  * Staging: otus: fix urb callback function type
+  * Staging: otus: remove dependence on kernel version
+  * Staging: add rt2860 wireless driver
+  * Staging: rt2860: disable root hack for reading files
+  * Staging: rt2860: fix up netdev->priv usage
+  * Staging: rt2860: use standard bit-reverse function
+  * Staging: rt2860: Fix minor compiler warnings
+  * Staging: rt2860: enable WPA_SUPPLICANT support
+  * Staging: Add ServerEngines benet 10Gb ethernet driver
+  * Staging: benet: fix netif api breakage
+  * Staging: benet: fix up netdev->priv change
+  * Staging: benet: build is broken unless CONFIG_NETPOLL is enabled
+  * Staging: benet: patch to remove subdirectories
+  * Staging: benet: fix build errors when CONFIG_NETPOLL is off
+  * Staging: benet: fix build error.
+  * Staging: benet: patch to use offsetof() instead of AMAP_BYTE_OFFSET()
+  * Staging: benet: fix problems reported by checkpatch
+  * Staging: benet: cleanup a check while posting rx buffers
+  * Staging: add comedi core
+  * Staging: comedi: fix up a lot of checkpatch.pl warnings
+  * Staging: comedi: fix checkpatch.pl errors in comedi_fops.c
+  * Staging: comedi: fix build error in comedilib.h
+  * Staging: comedi: add kcomedilib to the tree
+  * Staging: comedi: set up infrastructure for individual drivers
+  * Staging: comedi: add local copy of interrupt.h
+  * Staging: comedi: add pci and usb wrapper header files
+  * Staging: comedi: comedi driver common function module
+  * Staging: comedi: add mite comedi pci driver
+  * Staging: comedi: add usb usbdux driver
+  * Staging: comedi: add usb usbduxfast driver
+  * Staging: comedi: add usb dt9812 driver
+  * Staging: comedi: add comedi_bond driver
+  * Staging: comedi: add comedi_test driver
+  * Staging: comedi: add comedi_parport driver
+  * Staging: comedi: dt9812: fix up a lot of coding style issues
+  * Staging: comedi: dt9812: remove dt9812.h
+  * Staging: comedi: dt9812: remove typedefs
+  * Staging: comedi: dt9812: fix sparse warnings
+  * Staging: comedi: usbdux: remove kernel version checks
+  * Staging: comedi: usbdux: code style cleanups
+  * Staging: comedi: usbdux: remove // comments
+  * Staging: comedi: usbdux: fix up printk calls
+  * Staging: comedi: usbdux: remove checkpatch.pl warnings
+  * Staging: comedi: usbdux: remove typedef
+  * Staging: comedi: usbdux: remove comedi usb wrappers
+  * Staging: comedi: usbduxfast: remove comedi usb wrappers
+  * Staging: comedi: dt9812: remove #ifdef that is not needed
+  * Staging: comedi: remove usb wrappers
+  * Staging: comedi: remove PCI wrappers
+  * Staging: comedi: add icp_multi driver
+  * Staging: comedi: add me4000 driver
+  * Staging: comedi: fix checkpatch.pl issues in comedi_bond.c
+  * Staging: comedi: fix checkpatch.pl issues in comedi_fc.c
+  * Staging: comedi: remove typedefs from comedi_bond.c
+  * Staging: comedi: fix sparse issues in comedi_bond.c
+  * Staging: comedi: fix checkpatch.pl issues in comedi_test.c
+  * Staging: comedi: fix sparse issues in comedi_test.c
+  * Staging: comedi: remove typedefs from comedi_test.c
+  * Staging: comedi: fix comedi_parport.c checkpatch.pl issues.
+  * Staging: comedi: fix comedi_fc.h checkpatch.pl issues.
+  * Staging: comedi: fix comedi_pci.h checkpatch.pl issues.
+  * Staging: comedi: comedi_pci.h: remove unneeded wrapper
+  * Staging: comedi: comedi_pci.h: remove comedi_pci_enable_no_regions
+  * Staging: comedi: comedi_pci.h: remove comedi_pci_disable_no_regions
+  * Staging: comedi: add s626 driver
+  * Staging: comedi: add rtd520 driver
+  * Staging: comedi: add me_daq driver
+  * Staging: comedi: me_daq: fix checkpatch.pl issues
+  * Staging: comedi: me_daq: remove typedefs
+  * Staging: comedi: me_daq: fix sparse issues
+  * Staging: comedi: fix checkpatch.pl warning in interrupt.h
+  * Staging: comedi: fix build if CONFIG_PROC_FS is not set
+  * Staging: add asus_oled driver
+  * Staging: asus_oled: fix build dependancy
+  * Staging: Add the Meilhaus ME-IDS driver package
+  * Staging: meilhaus: fix __symbol_get problems
+  * Staging: add lcd-panel driver
+  * Staging: panel: major checkpatch cleanup
+  * Staging: panel: remove ifdefs and code for pre-2.6 kernels
+  * Staging: panel: remove support for smartcards
+  * Staging: add Driver for Altera PCI Express Chaining DMA reference design
+  * Staging: add rtl8187se driver
+  * Staging: rtl8187se: remove unneeded files
+  * Staging: rtl8187se: make the built module be the proper name
+  * Staging: rtl8187se: remove duplicate pci ids
+  * Staging: me4000: switch to list_for_each*()
+  * Staging: usbip: switch to list_for_each_entry()
+  * Staging: add princeton instruments usb camera driver
+  * Staging: add mimio xi driver
+  * Staging: add rt2870 wireless driver
+  * Staging: rt2870: disable root hack for reading files
+  * Staging: rt2870: fix up netdev->priv usage
+  * Staging: add frontier tranzport and alphatrack drivers
+  * Staging: frontier: remove unused alphatrack_sysfs.c file
+  * Staging: frontier: fix compiler warnings
+  * Staging: add epl stack
+  * Staging: epl: run Lindent on all kernel/*.h files
+  * Staging: epl: run Lindent on all user/*.h files
+  * Staging: epl: run Lindent on *.h files
+  * Staging: epl: run Lindent on *.c files
+  * Staging: epl: hr timers all run in hard irq context now
+  * Staging: epl: fix netdev->priv b0rkage
+  * Staging: add android framework
+  * Staging: android: add binder driver
+  * Staging: android: binder: Fix gcc warnings about improper format specifiers for size_t in printk
+  * staging: android: binder: Fix use of euid
+  * Staging: android: add logging driver
+  * Staging: android: add ram_console driver
+  * Staging: android: add timed_gpio driver
+  * Staging: android: timed_gpio: Rename android_timed_gpio to timed_gpio
+  * Staging: android: remove dummy android.c driver
+  * Staging: android: add lowmemorykiller driver
+  * Staging: android: binder: fix build errors
+  * staging: __FUNCTION__ is gcc-specific, use __func__
+  * V4L/DVB (10176a): Switch remaining clear_user_page users over to
+    clear_user_highpage
+
+  [ Zhenyu Wang ]
+
+  * agp/intel: add support for G41 chipset
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 18 Jan 2009 20:22:54 -0700
+
+linux (2.6.28-4.11) jaunty; urgency=low
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Enable HDMI audio codec on Studio XPS 1340
+    - LP: #309508
+
+  [ Tim Gardner ]
+
+  * Fix armel d-i FTBSs
+
+  [ Upstream Kernel Changes ]
+
+  * USB: re-enable interface after driver unbinds
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 13 Jan 2009 16:33:08 -0700
+
+linux (2.6.28-4.10) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update kernel bootloader recommends: to prefer grub
+    - LP: #314004
+  * SAUCE: don't use buggy _BCL/_BCM/_BQC for backlight control
+    - LP: #311716
+  * SAUCE: test-suspend -- add the suspend test scripts
+    - LP: #316419
+
+  [ Colin Watson ]
+
+  * Enable udebs for armel
+
+  [ Tim Gardner ]
+
+  * SAUCE: Dell laptop digital mic does not work, PCI 1028:0271
+    - LP: #309508
+  * Enable CIFS_XATTR=y and CONFIG_CIFS_POSIX=y
+    - LP: #220658
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 08 Jan 2009 10:38:22 -0700
+
+linux (2.6.28-4.9) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Restore DM_CRYPT, AES, ECB, and CBC as modules. This fixes
+    some installer issues with encrypted /home and Private directories.
+  * Take one more stab at building armel without module or ABI errors.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 06 Jan 2009 08:38:23 -0700
+
+linux (2.6.28-4.8) jaunty; urgency=low
+
+  * Fix i386/amd64 FTBS by ignoring all module and ABI changes,
+    not something you would normally do, but I'm sure the ABI
+    has not changed. This will probably also allow the ARM builds to complete.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 05 Jan 2009 14:42:58 -0700
+
+linux (2.6.28-4.7) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Enable CONFIG_ATH5K=m for i386/amd64
+    - LP: #306719
+  * Build all i386/amd64 AGP/DRM components as modules.
+    - LP: #312721
+  * git commands are now installed outside the default $PATH
+    Use 'git  CMD' instead of 'git-CMD'.
+  * Build in most PATA/SATA drivers. This should allow most i386/amd64 systems to boot
+    without an initramfs, though some support work is still required in initramfs-tools
+    and grub.
+    - LP: #311730
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 02 Jan 2009 07:33:09 -0700
+
+linux (2.6.28-4.6) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Enable CONFIG_X86_E_POWERSAVER=m for i386 generic
+    - LP: #237405
+  * Build i386 AGP drivers as modules
+    - LP: #312721
+  * Build i386 DRM as a module
+    - LP: #312721
+
+  [ Upstream Kernel Changes ]
+
+  * drm/i915: Add missing userland definitions for gem init/execbuffer.
+    - LP: #308387
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 29 Dec 2008 09:16:47 -0700
+
+linux (2.6.28-4.5) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * clean up module dependancy information on package removal/purge
+    - LP: #300773
+
+  [ Tim Gardner ]
+
+  * Update iscsitarget to 0.4.17
+  * Build in ext{234}
+  * Build in Crypto modules AES, CBC, ECB
+  * Build in ACPI AC,BATTERY,BUTTON,FAN,PCI_SLOT,PROCESSOR,SBS,THERMAL,WMI
+  * Build in AGP intel,via,sis,ali,amd,amd64,efficeon,nvidia,sworks
+  * Build in ata,dev_dm,dev_loop,dev_md,dev_sd,dev_sr
+  * Build in BT l2cap,rfcomm,sco
+  * Reduce CONFIG_LEGACY_PTY_COUNT to 0
+  * Build in CDROM_PKTCDVD and CHR_DEV_SG
+  * Build in CPU_FREQ
+    GOV_CONSERVATIVE,GOV_ONDEMAND,GOV_POWERSAVE,GOV_USERSPACE,STAT,TABLE
+  * Build in DM CRYPT,MIRROR,MULTIPATH,SNAPSHOT
+  * Build in DRM
+  * Build in HID
+  * Build in HOTPLUG PCI,PCIE
+  * Build in I2C
+  * Build in IEEE1394 OHCI1394
+  * Build in INPUT EVDEV
+  * Build in IPV6
+  * Build in MMC
+  * Build in PACKET
+  * Enable both IEEE1394 (Firewire) stacks as modules
+    - LP: #276463
+  * Disable SUNRPC_REGISTER_V4
+    - LP: #306016
+  * Enable dm-raid4-5
+    - LP: #309378
+  * Build in PPP
+  * Build in RFKILL
+  * Build in USB SERIAL
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 18 Dec 2008 21:18:44 -0700
+
+linux (2.6.28-3.4) jaunty; urgency=low
+
+  [ Tim Gardner ]
+
+  * Build ecryptfs into the kernel
+    - LP: #302870
+  * Deprecated gnbd
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28-rc8
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 10 Dec 2008 22:45:13 -0700
+
+linux (2.6.28-2.3) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * update the templates so that we have spaces following the title line
+
+  [ Tim Gardner ]
+
+  * Add upload number to kernel version signature. This has the side effect
+    of renaming kernel packages back to the original way, e.g., without '-ub'
+    in the name.
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 04 Dec 2008 12:18:31 -0700
+
+linux (2.6.28-2.2) jaunty; urgency=low
+
+  [ Andy Whitcroft ]
+
+  * Revert "SAUCE: (no-up) version: Implement version_signature proc file."
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: serial: RS485 ioctl structure uses __u32 include linux/types.h
+    - LP: #303711
+
+  [ Tim Gardner ]
+
+  * UBUNTU: Removed CONFIG_DRM_VIA_CHROME9 since it is upstream.
+  * UBUNTU: Removed ubuntu/via_chrome9
+
+  [ Upstream Kernel Changes ]
+
+  * Rebased to v2.6.28-rc7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 02 Dec 2008 07:33:32 -0700
+
+linux (2.6.28-1.1) jaunty; urgency=low
+
+  [ Amit Kucheria ]
+
+  * SAUCE: make fc transport removal of target configurable
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+  * SAUCE: Adds support for COMPAL JHL90 webcam
+  * Map armel to arm to all editconfigs to work correctly
+  * Add armel to getabis for completeness sake
+  * Add -ub to our versioning to allow kerneloops.org to identify us
+
+  [ Andy Whitcroft ]
+
+  * Fix Vcs-Git path for the kernel repository.
+    - LP: #296915
+
+  [ Ben Collins ]
+
+  * SAUCE: Lower warning level of some PCI messages
+    - LP: #159241
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: (no-up) connector.h: Add idx/val for drbd
+  * SAUCE: (no-up) swap: Add notify_swap_entry_free callback for compcache
+  * SAUCE: drivers: Remove some duplicate device entries in various modules
+  * SAUCE: (no-up) [AppArmor] merge with upstream subversion r1291
+  * SAUCE: (no-up) Enable ubuntu extra subdirectory
+  * SAUCE: (no-up) ACPI: initramfs DSDT override support
+  * ubuntu: Add drbd module
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Add BOM for iscsitarget
+  * ubuntu: Add squashfs driver
+  * SAUCE: (no-up) Check for squashfs superblock in initramfs mounting.
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Added et131x driver
+  * ubuntu: Add dm-raid4-5 driver
+  * ubuntu: Add ndiswrapper driver
+  * ubuntu: Added ram backed compressed swap module (compcache)
+  * ubuntu: Add misc drivers from hardy lum
+  * ubuntu: Add heci driver 3.2.0.24
+  * ubuntu: Add ov511 and bt-sco drivers
+  * ubuntu: Add acx, prism2_usb wireless drivers
+  * ubuntu: Add at76 driver to build
+  * ubuntu: Add fsam7400 sw kill switch driver
+  * ubuntu: Added qc-usb driver
+  * ubuntu: e1000e: Upgraded module to 0.4.1.7
+  * ubuntu: Added rfkill drivers
+  * ubuntu: VIA - Add VIA DRM Chrome9 3D engine
+  * ubuntu: unionfs: Added v1.4 module from hardy
+  * ubuntu: Add LIRC driver
+  * ubuntu: Add GFS driver
+  * ubuntu: New tlsup driver for toshiba laptops
+  * SAUCE: (no-up) Export lookup_has for aufs
+  * SAUCE: (no-up) Modularize vesafb
+  * ubuntu: Config files
+  * Disable some modules that need porting to 2.6.28
+  * ubuntu: Fixup headers creation to include arch/*/include
+  * ubuntu/module-check: Ignore comment lines
+
+  [ Chuck Short ]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+
+  [ cking ]
+
+  * SAUCE: Enable speedstep for sonoma processors.
+
+  [ Colin Ian King ]
+
+  * ubuntu: Add dm-loop
+  * SAUCE: cx88: Support Leadtek WinFast DTV2000 H version J.
+  * SAUCE: fix kernel oops in VirtualBox during paravirt patching
+  * SAUCE: qc-usb: Enable Logitech QuickCam Messenger
+  * SAUCE: appleir: Enable driver for new MacBook Pro
+
+  [ Colin Watson ]
+
+  * Enable configfs, fuse, jfs, reiserfs, and xfs for armel
+  * Extend debian/d-i/ modules handling to make armel easier to support
+  * Create udebs for armel
+
+  [ Fabio M. Di Nitto ]
+
+  * ubuntu: update GFS Cluster File System
+
+  [ Kees Cook ]
+
+  * SAUCE: AppArmor: update to upstream subversion r1302
+
+  [ Leann Ogasawara ]
+
+  * Add automatic model setting for Samsung Q45
+  * Add Dell Dimension 9200 reboot quirk
+
+  [ Mackenzie Morgan ]
+
+  * SAUCE: Add quirk for ASUS Z37E to make sound audible after resume
+
+  [ Matthew Garrett ]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [ Michael Frey (Senior Manager, MID ]
+
+  * SAUCE: Send HCI_RESET for Broadcomm 2046
+
+  [ Michael Haas ]
+
+  * add proper aufs source tree from 20080922
+  * Fix AUFS compilation in vfsub.c
+  * Add splice-2.6.23.patch from AUFS to export a symbol needed by AUFS
+  * Add put_filp.patch from AUFS to export a symbol needed by AUFS
+  * Add deny_write_access.patch from AUFS - export deny_write_access
+  * Add sec_perm-2.6.24.patch from AUFS - export security_inode_permission
+  * make sure TMPFS_MAGIC is defined in AUFS Makefile
+  * SAUCE: Revert aufs changes from AppArmor merge
+
+  [ Mohamed Abbas ]
+
+  * SAUCE: iwlagn -- fix rfkill when on when driver loaded
+
+  [ Phillip Lougher ]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [ Stefan Bader ]
+
+  * SAUCE: (no-up) Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers
+  * gfs1: GFS1 can't create more than 4kb file
+  * uvcvideo: Commit streaming parameters when enabling the video stream.
+
+  [ Tim Gardner ]
+
+  * SAUCE: Add extra headers to linux-libc-dev
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: (no-up) Take care of orinoco_cs overlap with hostap_cs
+  * ubuntu: Add GNBD driver
+  * SAUCE: e1000e: Map NV RAM dynamically only when needed.
+  * SAUCE: Correctly blacklist Thinkpad r40e in ACPI
+  * SAUCE: Update Wacom tablet driver to 1.49
+  * SAUCE: Fix Wacom tablet 1.49 porting errors
+  * SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit controller
+  * SAUCE: Fix Oops in wlan_setup
+  * SAUCE: ipw2200: change default policy for auto-associate
+  * Dell Wireless 365 needs BTUSB_RESET quirk.
+  * ndiswrapper remote buffer overflows on long ESSIDs (CVE 2008-4395)
+  * Disabled ubuntu/e1000e config
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+  * Revert "x86, early_ioremap: fix fencepost error"
+  * mac80211: fix two issues in debugfs
+  * iwl3945: do not send scan command if channel count zero
+
+ --  Ben Collins <ben.collins@canonical.com>  Fri, 07 Nov 2008 09:37:42 -0700
+
+linux (2.6.27-8.17) intrepid-proposed; urgency=low
+
+  [ John W. Linville ]
+
+  * SAUCE: iwlagn: avoid sleep in softirq context
+    -LP: #286285
+
+  [ Tim Gardner ]
+
+  * Dell Wireless 365 needs BTUSB_RESET quirk.
+    - LP: #293670
+  * SAUCE: ALSA: hda: make a STAC_DELL_EQ option (version 2)
+    - LP: #293271
+
+  [ Upstream Kernel Changes ]
+
+  * iwlagn: downgrade BUG_ON in interrupt
+  * Input: atkbd - expand Latitude's force release quirk to other Dells
+  * fbcon_set_all_vcs: fix kernel crash when switching the rotated consoles
+  * modules: fix module "notes" kobject leak
+  * Driver core: Fix cleanup in device_create_vargs().
+  * Driver core: Clarify device cleanup.
+  * ath9k/mac80211: disallow fragmentation in ath9k, report to userspace
+  * md: Fix rdev_size_store with size == 0
+  * xfs: fix remount rw with unrecognized options
+  * OHCI: Allow broken controllers to auto-stop
+  * USB: OHCI: fix endless polling behavior
+  * USB: Fix s3c2410_udc usb speed handling
+  * USB: EHCI: log a warning if ehci-hcd is not loaded first
+  * usb gadget: cdc ethernet notification bugfix
+  * usb: musb_hdrc build fixes
+  * drm/i915: fix ioremap of a user address for non-root (CVE-2008-3831)
+  * DVB: au0828: add support for another USB id for Hauppauge HVR950Q
+  * DVB: sms1xxx: support two new revisions of the Hauppauge WinTV
+    MiniStick
+  * security: avoid calling a NULL function pointer in
+    drivers/video/tvaudio.c
+  * Linux 2.6.27.3
+    -LP: #294152
+
+  * gpiolib: fix oops in gpio_get_value_cansleep()
+  * edac cell: fix incorrect edac_mode
+  * x86 ACPI: fix breakage of resume on 64-bit UP systems with SMP kernel
+  * sched: fix the wrong mask_len
+  * USB: cdc-wdm: make module autoload work
+  * USB: don't rebind drivers after failed resume or reset
+  * USB: fix memory leak in cdc-acm
+  * USB: Speedtouch: add pre_reset and post_reset routines
+  * dm kcopyd: avoid queue shuffle
+  * dm snapshot: fix primary_pe race
+  * amd_iommu: fix nasty bug that caused ILLEGAL_DEVICE_TABLE_ENTRY errors
+  * CIFS: fix saving of resume key before CIFSFindNext
+  * netfilter: xt_iprange: fix range inversion match
+  * netfilter: snmp nat leaks memory in case of failure
+  * netfilter: restore lost ifdef guarding defrag exception
+  * anon_vma_prepare: properly lock even newly allocated entries
+  * hvc_console: Fix free_irq in spinlocked section
+  * ACPI Suspend: Enable ACPI during resume if SCI_EN is not set
+  * ACPI suspend: Blacklist HP xw4600 Workstation for old code ordering
+  * ACPI suspend: Always use the 32-bit waking vector
+  * proc: fix vma display mismatch between /proc/pid/{maps,smaps}
+  * SCSI: scsi_dh: add Dell product information into rdac device handler
+  * PCI hotplug: cpqphp: fix kernel NULL pointer dereference
+  * V4L/DVB (9300): pvrusb2: Fix deadlock problem
+  * Linux 2.6.27.4
+    -LP: #294155
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Tue, 04 Nov 2008 12:16:07 -0700
+
+linux (2.6.27-7.16) intrepid-security; urgency=low
+
+  [ Tim Gardner ]
+
+  * ndiswrapper remote buffer overflows on long ESSIDs (CVE 2008-4395)
+    - LP: #275860
+
+  [ Upstream Kernel Changes ]
+
+  * ext[234]: Avoid printk floods in the face of directory corruption
+    (CVE-2008-3528)
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 03 Nov 2008 13:34:42 -0700
+
+linux (2.6.27-7.15) intrepid-security; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * tcp: Restore ordering of TCP options for the sake of inter-operability
+    - LP: #264019
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Mon, 27 Oct 2008 19:28:06 -0600
+
+linux (2.6.27-7.14) intrepid; urgency=low
+
+  [ Tim Gardner ]
+
+  * Disable ath5k in 2.6.27
+    - LP: #288148
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Thu, 23 Oct 2008 07:40:43 -0600
+
+linux (2.6.27-7.13) intrepid; urgency=low
+
+  [ Stefan Bader ]
+
+  * gfs1: GFS1 can't create more than 4kb file
+
+  [ Tim Gardner ]
+
+  * Revert "SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors
+    bitmap.". Use upstream commit to avoid future conflicts.
+  * Revert "STABLE queue: mac80211: fix two issues in debugfs".
+    Use upstream commit to avoid future conflicts.
+  * Revert "x86, early_ioremap: fix fencepost error"
+    Use upstream commit to avoid future conflicts.
+
+  [ Upstream Kernel Changes ]
+
+  * sched_rt.c: resch needed in rt_rq_enqueue() for the root rt_rq
+  * x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap.
+  * mac80211: fix two issues in debugfs
+  * Fix barrier fail detection in XFS
+  * tty: Termios locking - sort out real_tty confusions and lock reads
+  * CIFS: make sure we have the right resume info before calling
+    CIFSFindNext
+  * rfkill: update LEDs for all state changes
+  * libertas: clear current command on card removal
+  * b43legacy: Fix failure in rate-adjustment mechanism
+  * x86, early_ioremap: fix fencepost error
+  * x86: SB450: skip IRQ0 override if it is not routed to INT2 of IOAPIC
+  * x86: improve UP kernel when CPU-hotplug and SMP is enabled
+  * sky2: Fix WOL regression
+  * netdrvr: atl1e: Don't take the mdio_lock in atl1e_probe
+  * Linux 2.6.27.2
+
+  [ Amit Kucheria ]
+
+  * Ubuntu: agp: Fix stolen memory counting on G4X.
+    -LP: 285572
+
+  [ Scott Remnant ]
+
+  * add MODULE_ALIAS to load ipmi_devintf with ipmi_si
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 19 Oct 2008 10:06:21 -0600
+
+linux (2.6.27-7.12) intrepid; urgency=low
+
+  [ Chuck Short ]
+
+  * xen: Add xen modules to virtual flavours.
+
+  [ Mario Limonciello ]
+
+  * SAUCE: Add back in lost commit for Apple BT Wireless Keyboard
+    - LP: #162083
+
+  [ Tim Gardner ]
+
+  * Remove depmod created files from packages.
+    - LP: #250511
+  *  Changed default TCP congestion algorithm to 'cubic' (again)
+    - LP: #278801
+  * Update configs for 'disable CONFIG_DYNAMIC_FTRACE'
+    - LP: #263555
+
+  [ Upstream Kernel Changes ]
+
+  * x86: register a platform RTC device if PNP doesn't describe it
+  * disable CONFIG_DYNAMIC_FTRACE due to possible memory corruption on
+    module unload
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 17 Oct 2008 11:25:39 -0600
+
+linux (2.6.27-7.11) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * STABLE queue: mac80211: fix two issues in debugfs
+    - LP: #275227
+  * SAUCE: Adds support for COMPAL JHL90 webcam
+
+  [ Ben Collins ]
+
+  * SAUCE: (no-up) x86: Quiet "Kernel alive" messages
+    - LP: #39985
+  * SAUCE: (no-up) Modularize vesafb
+  * build/config: Enable vesafb module
+  * build: Switch to vesafb as preferred.
+
+  [ Leann Ogasawara ]
+
+  * Add Dell Dimension 9200 reboot quirk
+    - LP: #271370
+
+  [ Michael Haas ]
+
+  * SAUCE: Revert aufs changes from AppArmor merge
+
+  [ Tim Gardner ]
+
+  * fix virtio udeb layout
+    - LP: #257739
+  * Enabled CONFIG_EXT4DEV_FS=m
+  * Changed default TCP congestion algorithm to 'cubic'
+    - LP: #278801
+  * SAUCE: ipw2200: change default policy for auto-associate
+    - LP: #264104
+
+  [ Upstream Kernel Changes ]
+
+  * x86, early_ioremap: fix fencepost error
+    - LP: #263543
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sat, 11 Oct 2008 08:07:42 -0600
+
+linux (2.6.27-7.10) intrepid; urgency=low
+
+  [ Alexey Starikovskiy ]
+
+  * SAUCE: ACPI: EC: do transaction from interrupt context
+    - LP: #277802
+
+  [ Ben Collins ]
+
+  * build/d-i: Change virtio-modules udeb to prio standard
+
+  [ Colin Ian King ]
+
+  * SAUCE: Blacklist IBM 2656 in serio/i8042
+    - LP: #21558
+
+  [ Henrik Rydberg ]
+
+  * Revert "SAUCE: applesmc: Add MacBookAir"
+  * SAUCE: [PATCH 1/5] hwmon: applesmc: Specified number of bytes to read
+    should match actual
+  * SAUCE: [PATCH 2/5] hwmon: applesmc: Fix the 'wait status failed: c !=
+    8' problem
+  * SAUCE: [PATCH 3/5] hwmon: applesmc: Prolong status wait
+  * SAUCE: [PATCH 4/5] hwmon: applesmc: Allow for variable ALV0 and ALV1
+    package length
+  * SAUCE: [PATCH 5/5] hwmon: applesmc: Add support for Macbook Air
+  * SAUCE: hwmon: applesmc: Add support for Macbook Pro 4
+  * SAUCE: hwmon: applesmc: Add support for Macbook Pro 3
+  * SAUCE: hwmon: applesmc: Lighter wait mechanism, drastic improvement
+
+  [ Leann Ogasawara ]
+
+  * Add automatic model setting for Samsung Q45
+    - LP: #200210
+
+  [ Tim Gardner ]
+
+  * SAUCE: Correctly blacklist Thinkpad r40e in ACPI
+    - LP: #278794
+  * SAUCE: Update Wacom tablet driver to 1.49
+    - LP: #260675
+  * SAUCE: ALPS touchpad for Dell Latitude E6500/E6400
+    - LP: #270643
+  * SAUCE: Fix Wacom tablet 1.49 porting errors
+  * SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit controller
+  * SAUCE: Fix Oops in wlan_setup
+    - LP: #263309
+
+  [ Upstream Kernel Changes ]
+
+  * ath9k: fix oops on trying to hold the wrong spinlock
+  * [Bluetooth] Fix double frees on error paths of btusb and bpa10x drivers
+  * [Bluetooth] Add reset quirk for new Targus and Belkin dongles
+  * [Bluetooth] Add reset quirk for A-Link BlueUSB21 dongle
+  * Revert "ax25: Fix std timer socket destroy handling."
+  * ax25: Quick fix for making sure unaccepted sockets get destroyed.
+  * netrom: Fix sock_orphan() use in nr_release
+  * Revert "V4L/DVB (8904): cx88: add missing unlock_kernel"
+  * SLOB: fix bogus ksize calculation
+  * net: only invoke dev->change_rx_flags when device is UP
+  * tcp: Fix possible double-ack w/ user dma
+  * net: Fix netdev_run_todo dead-lock
+  * tcp: Fix tcp_hybla zero congestion window growth with small rho and large cwnd.
+  * [MIPS] Sibyte: Register PIO PATA device only for Swarm and Litte Sur
+  * eeepc-laptop: Fix hwmon interface
+  * hwmon: (it87) Prevent power-off on Shuttle SN68PT
+  * hwmon: Define sysfs interface for energy consumption register
+  * hwmon: (adt7473) Fix some bogosity in documentation file
+  * hwmon: (abituguru3) Enable reading from AUX3 fan on Abit AT8 32X
+  * hwmon: (abituguru3) Enable DMI probing feature on Abit AT8 32X
+  * [CPUFREQ] correct broken links and email addresses
+  * SLOB: fix bogus ksize calculation fix
+  * Don't allow splice() to files opened with O_APPEND
+  * Linux 2.6.27
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Wed, 08 Oct 2008 21:19:34 -0600
+
+linux (2.6.27-6.9) intrepid; urgency=low
+
+  [ Kees Cook ]
+
+  * SAUCE: AppArmor: update to upstream subversion r1302
+    - LP: #269921
+
+  [ Stefan Bader ]
+
+  * Update configuration files to be compliant to desktop specs
+    - LP: #279019
+
+  [ Tim Gardner ]
+
+  * Add support in e1000e for a couple of ICH10 PCI IDs
+  * Enable CONFIG_INPUT_PCSPKR=m
+    - LP: #275453
+
+  [ Upstream Kernel Changes ]
+
+  * V4L/DVB (8559a): Fix a merge conflict at gspca/sonixb
+  * V4L/DVB (8789): wm8739: remove wrong kfree
+  * V4L/DVB (8883): w9968cf: Fix order of usb_alloc_urb validation
+  * V4L/DVB (8884): em28xx-audio: fix memory leak
+  * V4L/DVB (8885): cpia2_usb: fix memory leak
+  * V4L/DVB (8886): ov511: fix memory leak
+  * V4L/DVB (8887): gspca: fix memory leak
+  * V4L/DVB (8892): pvrusb2: Handle USB ID 2040:2950 same as 2040:2900
+  * V4L/DVB (8904): cx88: add missing unlock_kernel
+  * V4L/DVB (8905): ov511: fix exposure sysfs attribute bug
+  * V4L/DVB (8909): gspca: PAC 7302 webcam 093a:262a added.
+  * hrtimer: migrate pending list on cpu offline
+  * hrtimer: fix migration of CB_IRQSAFE_NO_SOFTIRQ hrtimers
+  * hrtimer: mark migration state
+  * hrtimer: prevent migration of per CPU hrtimers
+  * [IA64] Put the space for cpu0 per-cpu area into .data section
+  * powerpc: Fix PCI in Holly device tree
+  * powerpc: Fix failure to shutdown with CPU hotplug
+  * mfd: Fix Kconfig accroding to the new gpiolib symbols
+  * mfd: Fix asic3 compilation
+  * x86: fix typo in enable_mtrr_cleanup early parameter
+  * ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space
+  * iucv: Fix mismerge again.
+  * ALSA: ASoC: Fix cs4270 error path
+  * ALSA: hda - Fix model for Dell Inspiron 1525
+  * sctp: Fix kernel panic while process protocol violation parameter
+  * x86: Fix broken LDT access in VMI
+  * x86, vmi: fix broken LDT access
+  * tcp: Fix NULL dereference in tcp_4_send_ack()
+  * ipv6: NULL pointer dereferrence in tcp_v6_send_ack
+  * XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep
+  * af_key: Free dumping state on socket close
+  * dm: always allow one page in dm_merge_bvec
+  * dm: cope with access beyond end of device in dm_merge_bvec
+  * dm mpath: add missing path switching locking
+  * MN10300: Fix IRQ handling
+  * pxa2xx_spi: fix build breakage
+  * e1000e: write protect ICHx NVM to prevent malicious write/erase
+  * powerpc: Fix boot hang regression on MPC8544DS
+  * ASoC: Set correct name for WM8753 rec mixer output
+  * ALSA: snd-powermac: mixers for PowerMac G4 AGP
+  * ALSA: snd-powermac: HP detection for 1st iMac G3 SL
+  * fbcon: fix monochrome color value calculation
+  * inotify: fix lock ordering wrt do_page_fault's mmap_sem
+  * braille_console: only register notifiers when the braille console is used
+  * fix error-path NULL deref in alloc_posix_timer()
+  * memory hotplug: missing zone->lock in test_pages_isolated()
+  * mm: tiny-shmem nommu fix
+  * mm: handle initialising compound pages at orders greater than MAX_ORDER
+  * e1000e: reset swflag after resetting hardware
+  * e1000e: do not ever sleep in interrupt context
+  * e1000e: remove phy read from inside spinlock
+  * e1000e: drop stats lock
+  * e1000e: debug contention on NVM SWFLAG
+  * e1000e: update version from k4 to k6
+  * Check mapped ranges on sysfs resource files
+  * e1000e: Fix incorrect debug warning
+  * [MIPS] Build fix: Fix irq flags type
+  * [MIPS] SMTC: Build fix: Fix filename in Makefile
+  * [MIPS] SMTC: Fix holes in SMTC and FPU affinity support.
+  * [MIPS] SMTC: Close tiny holes in the SMTC IPI replay system.
+  * [MIPS] SMTC: Fix SMTC dyntick support.
+  * [S390] nohz: Fix __udelay.
+  * [S390] qdio: prevent stack clobber
+  * Fix init/main.c to use regular printk with '%pF' for initcall fn
+  * x86 setup: correct segfault in generation of 32-bit reloc kernel
+  * selinux: Fix an uninitialized variable BUG/panic in selinux_secattr_to_sid()
+  * rtc: fix kernel panic on second use of SIGIO nofitication
+  * fbdev: fix recursive notifier and locking when fbdev console is blanked
+  * orion_spi: fix handling of default transfer speed
+  * include/linux/stacktrace.h: declare struct task_struct
+  * cpusets: remove pj from cpuset maintainers
+  * MAINTAINERS: add mailing list for man-pages
+  * SubmitChecklist: interfaces changes should CC linux-api@
+  * Documentation/HOWTO: info about interface changes should CC linux-api@vger
+  * dw_dmac: fix copy/paste bug in tasklet
+  * leds-fsg: change order of initialization and deinitialization
+  * leds-pca955x: add proper error handling and fix bogus memory handling
+  * ACPI: Make /proc/acpi/wakeup interface handle PCI devices (again)
+  * clockevents: check broadcast tick device not the clock events device
+  * V4L/DVB (8919): cx18: Fix tuner audio input for Compro H900 cards
+  * V4L/DVB (8926): gspca: Bad fix of leak memory (changeset 43d2ead315b1).
+  * V4L/DVB (8933): gspca: Disable light frquency for zc3xx cs2102 Kokom.
+  * V4L/DVB (8935): em28xx-cards: Remove duplicate entry (EM2800_BOARD_KWORLD_USB2800)
+  * V4L/DVB (8955): bttv: Prevent NULL pointer dereference in radio_open
+  * V4L/DVB (8957): zr36067: Restore the default pixel format
+  * V4L/DVB (8958): zr36067: Return proper bytes-per-line value
+  * V4L/DVB (8960): drivers/media/video/cafe_ccic.c needs mm.h
+  * V4L/DVB (8961): zr36067: Fix RGBR pixel format
+  * V4L/DVB (8963): s2255drv field count fix
+  * V4L/DVB (8967): Use correct XC3028L firmware for AMD ATI TV Wonder 600
+  * V4L/DVB (8978): sms1xxx: fix product name for Hauppauge WinTV MiniStick
+  * V4L/DVB (8979): sms1xxx: Add new USB product ID for Hauppauge WinTV MiniStick
+  * V4L/DVB (9029): Fix deadlock in demux code
+  * V4L/DVB (9037): Fix support for Hauppauge Nova-S SE
+  * V4L/DVB (9043): S5H1420: Fix size of shadow-array to avoid overflow
+  * V4L/DVB (9053): fix buffer overflow in uvc-video
+  * V4L/DVB (9075): gspca: Bad check of returned status in i2c_read() spca561.
+  * V4L/DVB (9080): gspca: Add a delay after writing to the sonixj sensors.
+  * V4L/DVB (9092): gspca: Bad init values for sonixj ov7660.
+  * V4L/DVB (9099): em28xx: Add detection for K-WORLD DVB-T 310U
+  * V4L/DVB (9103): em28xx: HVR-900 B3C0 - fix audio clicking issue
+  * x86: gart iommu have direct mapping when agp is present too
+  * ide-cd: temporary tray close fix
+  * ide-dma: fix ide_build_dmatable() for TRM290
+  * IDE: Fix platform device registration in Swarm IDE driver (v2)
+  * ide-cd: Optiarc DVD RW AD-7200A does play audio
+  * ide: workaround for bogus gcc warning in ide_sysfs_register_port()
+  * [MIPS] Fix CMP Kconfig configuration and mark as broken.
+  * [MIPS] IP27: Fix build errors if CONFIG_MAPPED_KERNEL=y
+  * x86 ACPI: Blacklist two HP machines with buggy BIOSes
+  * kgdb, x86: Avoid invoking kgdb_nmicallback twice per NMI
+  * kgdb: call touch_softlockup_watchdog on resume
+  * atmel-mci: Initialize BLKR before sending data transfer command
+  * Marker depmod fix core kernel list
+  * Linux 2.6.27-rc9
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 05 Oct 2008 21:27:49 -0600
+
+linux (2.6.27-5.8) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * Update AUFS-related Kconfig
+    - LP: #264048
+
+  [ Michael Haas ]
+
+  * add proper aufs source tree from 20080922
+  * Fix AUFS compilation in vfsub.c
+  * Add splice-2.6.23.patch from AUFS to export a symbol needed by AUFS
+  * Add put_filp.patch from AUFS to export a symbol needed by AUFS
+  * apply (modified) lhash.patch from AUFS to export __lookup_hash()
+  * Add deny_write_access.patch from AUFS - export deny_write_access
+  * Add sec_perm-2.6.24.patch from AUFS - export security_inode_permission
+  * make sure TMPFS_MAGIC is defined in AUFS Makefile
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_IPWIRELESS
+    - LP: #274748
+  * Enabled CONFIG_E1000E, disabled CONFIG_E1000E_NEW
+    This takes advantage of the upstream NVM protection fix in
+    commit 4a7703582836f55a1cbad0e2c1c6ebbee3f9b3a7.
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+  * [SCSI] qla2xxx: Defer enablement of RISC interrupts until ISP
+    initialization completes.
+  * PCI: Fix pcie_aspm=force
+  * PCI: fix compiler warnings in pci_get_subsys()
+  * UBIFS: create the name of the background thread in every case
+  * UBIFS: TNC / GC race fixes
+  * UBIFS: remove incorrect assert
+  * UBIFS: fix printk format warnings
+  * AMD IOMMU: set iommu sunc flag after command queuing
+  * AMD IOMMU: protect completion wait loop with iommu lock
+  * sparc64: Fix disappearing PCI devices on e3500.
+  * x86, oprofile: BUG scheduling while atomic
+  * ALSA: ASoC: Fix at32-pcm build breakage with PM enabled
+  * ath9k: connectivity is lost after Group rekeying is done
+  * wireless: zd1211rw: add device ID fix wifi dongle "trust nw-3100"
+  * [IA64] Ski simulator doesn't need check_sal_cache_flush
+  * [IA64] kexec fails on systems with blocks of uncached memory
+  * ath9k: Fix IRQ nobody cared issue with ath9k
+  * [Bluetooth] Fix I/O errors on MacBooks with Broadcom chips
+  * [Bluetooth] Fix wrong URB handling of btusb driver
+  * [Bluetooth] Fix USB disconnect handling of btusb driver
+  * sparc64: Fix missing devices due to PCI bridge test in
+    of_create_pci_dev().
+  * [WATCHDOG] ibmasr: remove unnecessary spin_unlock()
+  * [WATCHDOG] wdt285: fix sparse warnings
+  * [WATCHDOG] unlocked_ioctl changes
+  * x86: fix 27-rc crash on vsmp due to paravirt during module load
+  * sched: fix init_hrtick() section mismatch warning
+  * clockevents: prevent cpu online to interfere with nohz
+  * x86: prevent stale state of c1e_mask across CPU offline/online
+  * clockevents: prevent stale tick_next_period for onlining CPUs
+  * clockevents: check broadcast device not tick device
+  * clockevents: prevent mode mismatch on cpu online
+  * x86: prevent C-states hang on AMD C1E enabled machines
+  * x86: c1e_idle: don't mark TSC unstable if CPU has invariant TSC
+  * timers: fix build error in !oneshot case
+  * ALSA: ASoC: maintainers - update email address for Liam Girdwood
+  * ibmasr: remove unnecessary spin_unlock()
+  * smb.h: do not include linux/time.h in userspace
+  * kernel-doc: allow structs whose members are all private
+  * kexec: fix segmentation fault in kimage_add_entry
+  * Documentation/DMA-mapping.txt: update for pci_dma_mapping_error()
+    changes
+  * sys_paccept: disable paccept() until API design is resolved
+  * mm: tiny-shmem fix lock ordering: mmap_sem vs i_mutex
+  * Documentation/sysctl/kernel.txt: fix softlockup_thresh description
+  * memcg: check under limit at shrink_usage
+  * atmel_serial: update the powersave handler to match serial core
+  * [SCSI] Fix hang with split requests
+  * USB Storage: Sierra: Non-configurable TRU-Install
+  * USB Serial: Sierra: Device addition & version rev
+  * USB: ehci: fix some ehci hangs and crashes
+  * USB: Fix the Nokia 6300 storage-mode.
+  * USB: Correct Sierra Wireless USB EVDO Modem Device ID
+  * USB: fix hcd interrupt disabling
+  * USB: update of Documentation/usb/anchors.txt
+  * usb gadget: fix omap_udc DMA regression
+  * USB: Fixing Nokia 3310c in storage mode
+  * usb: musb: fix include path
+  * USB: fix EHCI periodic transfers
+  * usb-serial: Add Siemens EF81 to PL-2303 hack triggers
+  * USB: SERIAL CP2101 add device IDs
+  * USB: unusual_devs addition for RockChip MP3 player
+  * USB: fsl_usb2_udc: fix VDBG() format string
+  * usb serial: ti_usb_3410_5052 obviously broken by firmware changes
+  * USB: ftdi_sio: Add 0x5050/0x0900 USB IDs (Papouch Quido USB 4/4)
+  * USB: serial: add ZTE CDMA Tech id to option driver
+  * USB Serial: Sierra: Add MC8785 VID/PID
+  * USB: drivers/usb/musb/: disable it on SuperH
+  * usb: ftdi_sio: add support for Domintell devices
+  * usb: unusual devs patch for Nokia 5310 Music Xpress
+  * USB: revert recovery from transient errors
+  * [MIPS] au1000: Fix gpio direction
+  * [MIPS] Fixe the definition of PTRS_PER_PGD
+  * x86: prevent stale state of c1e_mask across CPU offline/online, fix
+  * x86: disable apm on the olpc
+  * i2c-powermac: Fix section for probe and remove functions
+  * i2c-dev: Return correct error code on class_create() failure
+  * i2c: Fix mailing lists in two MAINTAINERS entries
+  * ath9k: disable MIB interrupts to fix interrupt storm
+  * 9p: implement proper trans module refcounting and unregistration
+  * 9p-trans_fd: fix trans_fd::p9_conn_destroy()
+  * 9p-trans_fd: clean up p9_conn_create()
+  * 9p-trans_fd: don't do fs segment mangling in p9_fd_poll()
+  * 9p-trans_fd: fix and clean up module init/exit paths
+  * 9p: introduce missing kfree
+  * 9p: use an IS_ERR test rather than a NULL test
+  * 9p: fix put_data error handling
+  * netfilter: ip6t_{hbh,dst}: Rejects not-strict mode on rule insertion
+  * MN10300: Move asm-arm/cnt32_to_63.h to include/linux/
+  * MN10300: Make sched_clock() report time since boot
+  * ALSA: fix locking in snd_pcm_open*() and snd_rawmidi_open*()
+  * ALSA: remove unneeded power_mutex lock in snd_pcm_drop
+  * IPoIB: Fix crash when path record fails after path flush
+  * [XFS] Fix extent list corruption in xfs_iext_irec_compact_full().
+  * [XFS] Remove xfs_iext_irec_compact_full()
+  * kgdb: could not write to the last of valid memory with kgdb
+  * kgdb, x86, arm, mips, powerpc: ignore user space single stepping
+  * kgdb, x86_64: gdb serial has BX and DX reversed
+  * kgdb, x86_64: fix PS CS SS registers in gdb serial
+  * kgdboc,tty: Fix tty polling search to use name correctly
+  * ARM: Delete ARM's own cnt32_to_63.h
+  * m32r: remove the unused NOHIGHMEM option
+  * m32r: don't offer CONFIG_ISA
+  * m32r: export empty_zero_page
+  * m32r: export __ndelay
+  * m32r/kernel/: cleanups
+  * [MIPS] au1000: Make sure GPIO value is zero or one
+  * [MIPS] IP27: Switch to dynamic interrupt routing avoding panic on
+    error.
+  * [MIPS] BCM47xx: Fix build error due to missing PCI functions
+  * [SSB] Initialise dma_mask for SSB_BUSTYPE_SSB devices
+  * Swarm: Fix crash due to missing initialization
+  * ide-tape: fix vendor strings
+  * ide: note that IDE generic may prevent other drivers from attaching
+  * cdrom: update ioctl documentation
+  * [SCSI] qlogicpti: fix sg list traversal error in continuation entries
+  * sata_nv: reinstate nv_hardreset() for non generic controllers
+  * scsi: fix fall out of sg-chaining patch in qlogicpti
+  * ALSA: make the CS4270 driver a new-style I2C driver
+  * ALSA: ASoC: Fix another cs4270 error path
+  * Fix NULL pointer dereference in proc_sys_compare
+  * kconfig: fix silentoldconfig
+  * kconfig: readd lost change count
+  * mm owner: fix race between swapoff and exit
+  * Linux 2.6.27-rc8
+  * e1000e: write protect ICHx NVM to prevent malicious write/erase
+
+ -- Amit Kucheria <amit.kucheria@canonical.com>  Tue, 30 Sep 2008 18:22:35 +0300
+
+linux (2.6.27-4.7) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/abi: Add gfs1 to perm blacklist
+  * build/abi: Ignored changes in gfs2 symbols
+
+  [ Fabio M. Di Nitto ]
+
+  * Revert "SAUCE: Export gfs2 symbols required for gfs1 kernel module"
+  * ubuntu: update GFS Cluster File System
+
+  [ Stefan Bader ]
+
+  * SAUCE: x86: Reserve FIRST_DEVICE_VECTOR in used_vectors bitmap.
+    - LP: #276334
+
+  [ Tim Gardner ]
+
+  * Revert "Disable e1000e until the NVRAM corruption problem is found."
+  * Add atl1e and atl2 to Debian installer bits
+    - LP: #273904
+  * SAUCE: e1000e: Map NV RAM dynamically only when needed.
+    - LP: #263555
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Fri, 26 Sep 2008 20:51:22 -0600
+
+linux (2.6.27-4.6) intrepid; urgency=low
+
+  [ Tim Gardner ]
+
+  * Disable e1000e until the NVRAM corruption problem is found.
+    - LP: #263555
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "[Bluetooth] Eliminate checks for impossible conditions in IRQ
+    handler"
+
+ -- Ben Collins <ben.collins@canonical.com>  Tue, 23 Sep 2008 09:53:57 -0400
+
+linux (2.6.27-4.5) intrepid; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "b43/b43legacy: add RFKILL_STATE_HARD_BLOCKED support"
+  * udf: Fix lock inversion between iprune_mutex and alloc_mutex (v2)
+  * udf: Fix error paths in udf_new_inode()
+  * [SCSI] sd: select CRC_T10DIF only when necessary
+  * [SCSI] zfcp: Fix request queue locking
+  * [SCSI] zfcp: Correctly query end flag in gpn_ft response
+  * [SCSI] zfcp: Simplify ccw notify handler
+  * [SCSI] zfcp: Fix reference counter for remote ports
+  * [SCSI] zfcp: channel cannot be detached due to refcount imbalance
+  * [SCSI] zfcp: Remove duplicated unlikely() macros.
+  * [SCSI] scsi_dh: make check_sense return ADD_TO_MLQUEUE
+  * [SCSI] make scsi_check_sense HARDWARE_ERROR return ADD_TO_MLQUEUE on
+    retry
+  * [SCSI] fix check of PQ and PDT bits for WLUNs
+  * pcm037: add rts/cts support for serial port
+  * i.MX serial: fix init failure
+  * imx serial: set RXD mux bit on i.MX27 and i.MX31
+  * imx serial: fix rts handling for non imx1 based hardware
+  * mlx4_core: Set RAE and init mtt_sz field in FRMR MPT entries
+  * udf: add llseek method
+  * PCI/iommu: blacklist DMAR on Intel G31/G33 chipsets
+  * PCI: Fix printk warnings in probe.c
+  * PCI: Fix printk warnings in setup-bus.c
+  * PCI Hotplug: fakephp: fix deadlock... again
+  * clockevents: remove WARN_ON which was used to gather information
+  * ocfs2: Fix a bug in direct IO read.
+  * arch/x86/kernel/kdebugfs.c: introduce missing kfree
+  * [IA64] fix compile failure with non modular builds
+  * [IA64] fix up bte.h
+  * [IA64] arch/ia64/sn/pci/tioca_provider.c: introduce missing kfree
+  * PCI: fix pciehp_free_irq()
+  * [IA64] prevent ia64 from invoking irq handlers on offline CPUs
+  * ide: Fix pointer arithmetic in hpt3xx driver code (3rd try)
+  * add deprecated ide-scsi to feature-removal-schedule.txt
+  * swiotlb: fix back-off path when memory allocation fails
+  * sparc64: Fix interrupt register calculations on Psycho and Sabre.
+  * VIDEO_SH_MOBILE_CEU should depend on HAS_DMA
+  * m68k: Update defconfigs for 2.6.27-rc6
+  * sparc32: Fix function signature of of_bus_sbus_get_flags().
+  * sched: fix 2.6.27-rc5 couldn't boot on tulsa machine randomly
+  * sched: fix deadlock in setting scheduler parameter to zero
+  * KVM: SVM: fix random segfaults with NPT enabled
+  * KVM: SVM: fix guest global tlb flushes with NPT
+  * KVM: VMX: Always return old for clear_flush_young() when using EPT
+  * clocksource, acpi_pm.c: fix check for monotonicity
+  * [ARM] OMAP: Fix MMC device data
+  * block: disable sysfs parts of the disk command filter
+  * ath9k: Assign seq# when mac80211 requests this
+  * sg: disable interrupts inside sg_copy_buffer
+  * MN10300: Change the fault handler to check in_atomic() not
+    in_interrupt()
+  * [Bluetooth] Fix regression from using default link policy
+  * netlink: fix overrun in attribute iteration
+  * x86: fix possible x86_64 and EFI regression
+  * sparc64: Fix PCI error interrupt registry on PSYCHO.
+  * sparc: Fix user_regset 'n' field values.
+  * niu: panic on reset
+  * PCI: re-add debug prints for unmodified BARs
+  * [ARM] 5245/1: Fix warning about unused return value in drivers/pcmcia
+  * [ARM] 5246/1: tosa: add proper clock alias for tc6393xb clock
+  * [ARM] 5247/1: tosa: SW_EAR_IN support
+  * [ARM] Fix PCI_DMA_BUS_IS_PHYS for ARM
+  * ata: duplicate variable sparse warning
+  * sata_inic162x: enable LED blinking
+  * [libata] LBA28/LBA48 off-by-one bug in ata.h
+  * proc: more debugging for "already registered" case
+  * include/linux/ioport.h: add missing macro argument for devm_release_*
+    family
+  * cpuset: avoid changing cpuset's cpus when -errno returned
+  * cpuset: hotplug documentation fix
+  * coredump_filter: add description of bit 4
+  * bfs: fix Lockdep warning
+  * mm: ifdef Quicklists in /proc/meminfo
+  * spi_mpc83xx: fix clockrate calculation for low speed
+  * spi_mpc83xx: reject invalid transfer sizes
+  * pxa2xx_spi: chipselect bugfixes
+  * pxa2xx_spi: dma bugfixes
+  * mm: mark the correct zone as full when scanning zonelists
+  * Documentation/ABI: /sys/class/gpio
+  * MAINTAINERS: fix USB VIDEO CLASS mail list address
+  * ia64: fix panic during `modprobe -r xpc'
+  * atmel_lcdfb: disable LCD and DMA engines when suspending
+  * spi_s3c24xx: fix section warning
+  * rescan_partitions(): make device capacity errors non-fatal
+  * memstick: fix MSProHG 8-bit interface mode support
+  * Add Uwe Kleine-König to .mailmap
+  * xen: fix for xen guest with mem > 3.7G
+  * x86/paravirt: Remove duplicate paravirt_pagetable_setup_{start, done}()
+  * crypto: talitos - Avoid consecutive packets going out with same IV
+  * slub: fixed uninitialized counter in struct kmem_cache_node
+  * udp: Fix rcv socket locking
+  * IB/mlx4: Fix up fast register page list format
+  * [MIPS] VR41xx: unsigned irq cannot be negative
+  * x86: completely disable NOPL on 32 bits
+  * [S390] cio: Fix driver_data handling for ccwgroup devices.
+  * [S390] cio: fix orb initialization in cio_start_key
+  * sparc64: Fix OOPS in psycho_pcierr_intr_other().
+  * sparc64: Fix SMP bootup with CONFIG_STACK_DEBUG or ftrace.
+  * RDMA/nes: Fix client side QP destroy
+  * IPoIB: Fix deadlock on RTNL between bcast join comp and ipoib_stop()
+  * clockevents: make device shutdown robust
+  * powerpc: Fix interrupt values for DMA2 in MPC8610 HPCD device tree
+  * hpplus: fix build regression
+  * Fix PNP build failure, bugzilla #11276
+  * warn: Turn the netdev timeout WARN_ON() into a WARN()
+  * [XFS] Move memory allocations for log tracing out of the critical path
+  * [XFS] Fix regression introduced by remount fixup
+  * [XFS] Prevent direct I/O from mapping extents beyond eof
+  * [XFS] Fix barrier status change detection.
+  * [XFS] Prevent lockdep false positives when locking two inodes.
+  * [XFS] Fix use-after-free with buffers
+  * [XFS] Don't do I/O beyond eof when unreserving space
+  * powerpc: Holly board needs dtbImage target
+  * Fix compile failure with non modular builds
+  * [ARM] 5249/1: davinci: remove redundant check in davinci_psc_config()
+  * [ARM] omap: back out 'internal_clock' support
+  * sctp: set the skb->ip_summed correctly when sending over loopback.
+  * [ARM] 5255/1: Update jornada ssp to remove build errors/warnings
+  * sctp: do not enable peer features if we can't do them.
+  * sctp: Fix oops when INIT-ACK indicates that peer doesn't support AUTH
+  * bnx2: Promote vector field in bnx2_irq structure from u16 to unsigned
+    int
+  * forcedeth: call restore mac addr in nv_shutdown path
+  * e1000: prevent corruption of EEPROM/NVM
+  * e100: Use pci_pme_active to clear PME_Status and disable PME#
+  * md: Don't wait UNINTERRUPTIBLE for other resync to finish
+  * atstk1000: fix build breakage with BOARD_ATSTK100X_SW2_CUSTOM=y
+  * avr32: add .gitignore files
+  * avr32: add generic_find_next_le_bit bit function
+  * avr32: fix sys_sync_file_range() call convention
+  * avr32: nmi_enter() without nmi_exit()
+  * KVM: ia64: 'struct fdesc' build fix
+  * hwmon: (atxp1) Fix device detection logic
+  * hwmon: (it87) Fix fan tachometer reading in IT8712F rev 0x7 (I)
+  * hwmon: (ad7414) Make ad7414_update_device() static
+  * tmio_mmc: fix compilation with debug enabled
+  * atmel-mci: debugfs: enable clock before dumping regs
+  * atmel-mci: Fix memory leak in atmci_regs_show
+  * atmel-mci: Fix bogus debugfs file size
+  * atmel-mci: Set MMC_CAP_NEEDS_POLL if no detect_pin
+  * mmc_block: handle error from mmc_register_driver()
+  * mmc_test: initialize mmc_test_lock statically
+  * [MIPS] Fix 64-bit IP checksum code
+  * [MIPS] SMTC: Clear TIF_FPUBOUND on clone / fork.
+  * [MIPS] Fix potential latency problem due to non-atomic cpu_wait.
+  * [MIPS] vmlinux.lds.S: handle .text.*
+  * MAINTAINERS: Trivial whitespace cleanups
+  * MAINTAINERS: Various fixes
+  * Linux 2.6.27-rc7
+
+ --  Tim Gardner <tim.gardner@canonical.com>  Sun, 21 Sep 2008 21:49:28 -0600
+
+linux (2.6.27-3.4) intrepid; urgency=low
+
+  [ Colin Ian King ]
+
+  * SAUCE: fix kernel oops in VirtualBox during paravirt patching
+    - LP: #246067
+  * SAUCE: qc-usb: Enable Logitech QuickCam Messenger
+    - LP: #209901
+  * SAUCE: appleir: Enable driver for new MacBook Pro
+    - LP: #157919
+
+  [ Tim Gardner ]
+
+  * Enabled CONFIG_DEBUG_RODATA=y
+
+  [ Upstream Kernel Changes ]
+
+  * Revert "ALSA: hda - Added model selection for iMac 24""
+  * Revert "x86: fix HPET regression in 2.6.26 versus 2.6.25, check hpet
+    against BAR, v3"
+  * Revert "[ARM] use the new byteorder headers"
+  * Revert "mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM"
+  * Revert "crypto: camellia - Use kernel-provided bitops, unaligned access
+    helpers"
+  * svcrdma: Fix race between svc_rdma_recvfrom thread and the dto_tasklet
+  * sched, cpuset: rework sched domains and CPU hotplug handling (v4)
+  * ACPI: Fix now signed module parameter.
+  * ACPI: Change package length error to warning
+  * ACPI: Fix now signed module parameter.
+  * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board"
+  * acpi: add checking for NULL early param
+  * UBIFS: fix zero-length truncations
+  * Input: bcm5974 - add maintainer entry
+  * sh64: re-add the __strnlen_user() prototype
+  * sh: fix ptrace_64.c:user_disable_single_step()
+  * PNPACPI: ignore the producer/consumer bit for extended IRQ descriptors
+  * UBIFS: always read hashed-key nodes under TNC mutex
+  * UBIFS: allow for racing between GC and TNC
+  * [CIFS] Fix plaintext authentication
+  * sparc32: Implement smp_call_function_single().
+  * sh: crash kernel resource fix
+  * sh: fix kexec entry point for crash kernels
+  * sh: fix platform_resource_setup_memory() section mismatch
+  * sh: update Migo-R defconfig
+  * sh: update AP325RXA defconfig
+  * sh: fix semtimedop syscall
+  * cifs: fix O_APPEND on directio mounts
+  * [CIFS] update cifs change log
+  * [CIFS] Turn off Unicode during session establishment for plaintext
+    authentication
+  * ACPI: thinkpad-acpi: wan radio control is not experimental
+  * sparc: Fix resource flags for PCI children in OF device tree.
+  * remove blk_register_filter and blk_unregister_filter in gendisk
+  * ALSA: oxygen: fix distorted output on AK4396-based cards
+  * ipv6: When we droped a packet, we should return NET_RX_DROP instead of
+    0
+  * pkt_sched: Fix locking of qdisc_root with qdisc_root_sleeping_lock()
+  * net: Unbreak userspace usage of linux/mroute.h
+  * Don't trigger softlockup detector on network fs blocked tasks
+  * Resource handling: add 'insert_resource_expand_to_fit()' function
+  * sparc64: setup_valid_addr_bitmap_from_pavail() should be __init
+  * UBIFS: do not update min_idx_lebs in stafs
+  * UBIFS: push empty flash hack down
+  * UBIFS: remove incorrect index space check
+  * UBIFS: improve statfs reporting
+  * UBIFS: fix assertion
+  * UBIFS: add forgotten gc_idx_lebs component
+  * UBIFS: introduce LEB overhead
+  * UBIFS: improve statfs reporting even more
+  * UBIFS: fill f_fsid
+  * drm/radeon: downgrade debug message from info to debug.
+  * Remove invalidate_partition call from do_md_stop.
+  * Fix problem with waiting while holding rcu read lock in md/bitmap.c
+  * ALSA: hda: Distortion fix for dell_m6_core_init
+  * ALSA: ASoC: fix pxa2xx-i2s clk_get call
+  * block: restore original behavior of /proc/partition when there's no
+    partition
+  * debugobjects: fix lockdep warning
+  * avr32: Fix lockup after Java stack underflow in user mode
+  * avr32: pm_standby low-power ram bug fix
+  * nfsd: fix compound state allocation error handling
+  * sunrpc: fix possible overrun on read of /proc/sys/sunrpc/transports
+  * nfsd: fix buffer overrun decoding NFSv4 acl
+  * audit: Moved variable declaration to beginning of function
+  * Fix modules_install on RO nfs-exported trees.
+  * Remove '#include <stddef.h>' from mm/page_isolation.c
+  * dabusb_fpga_download(): fix a memory leak
+  * [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl()
+  * ALSA: hda - Fix ALC663 auto-probe
+  * ALSA: hda - Add mic-boost controls to ALC662/663 auto configuration
+  * Un-break printk strings in x86 PCI probing code
+  * kernel/resource.c: fix new kernel-doc warning
+  * softlockup: minor cleanup, don't check task->state twice
+  * fix typo in arch/parisc/hpux/fs.c
+  * m68k: atari_keyb_init operator precedence fix
+  * ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board"
+  * don't diff generated firmware files
+  * IDE: compile fix for sff_dma_ops
+  * IDE: palm_bk3710: fix compile warning for unused variable
+  * ide: fix hwif_to_node()
+  * palm_bk3710: improve IDE registration
+  * ide-disk: remove stale init_idedisk_capacity() documentation
+  * ide/Kconfig: mark ide-scsi as deprecated
+  * net/wireless/Kconfig: clarify the description for
+    CONFIG_WIRELESS_EXT_SYSFS
+  * iwlwifi: do not use GFP_DMA in iwl_tx_queue_init
+  * iwlwifi: workaround interrupt handling no some platforms
+  * iwlwifi: fix apm_stop (wrong bit polarity for FLAG_INIT_DONE)
+  * iwlwifi: fix 64bit platform firmware loading
+  * orinoco: Multicast to the specified addresses
+  * wireless/libertas/if_cs.c: fix memory leaks
+  * mac80211: Fix debugfs union misuse and pointer corruption
+  * rt2x00: Compiler warning unmasked by fix of BUILD_BUG_ON
+  * ath9k: Incorrect key used when group and pairwise ciphers are
+    different.
+  * ath9: Fix ath_rx_flush_tid() for IRQs disabled kernel warning message.
+  * net/xfrm: Use an IS_ERR test rather than a NULL test
+  * ipv: Re-enable IP when MTU > 68
+  * NTFS: update homepage
+  * mm: make setup_zone_migrate_reserve() aware of overlapping nodes
+  * VFS: fix dio write returning EIO when try_to_release_page fails
+  * acer-wmi: remove debugfs entries upon unloading
+  * mm/bootmem: silence section mismatch warning -
+    contig_page_data/bootmem_node_data
+  * MAINTAINERS: add a maintainer for the BCM5974 multitouch driver
+  * 8250: improve workaround for UARTs that don't re-assert THRE correctly
+  * mmc: at91_mci: don't use coherent dma buffers
+  * pid_ns: zap_pid_ns_processes: fix the ->child_reaper changing
+  * pid_ns: (BUG 11391) change ->child_reaper when init->group_leader exits
+  * cirrusfb: check_par fixes
+  * devcgroup: fix race against rmdir()
+  * mm: show quicklist usage in /proc/meminfo
+  * mm: size of quicklists shouldn't be proportional to the number of CPUs
+  * ipc: document the new auto_msgmni proc file
+  * hp-wmi: update to match current rfkill semantics
+  * hp-wmi: add proper hotkey support
+  * tdfxfb: fix SDRAM memory size detection
+  * tdfxfb: fix frame buffer name overrun
+  * rtc_time_to_tm: fix signed/unsigned arithmetic
+  * ibft: fix target info parsing in ibft module
+  * sysfs: document files in /sys/firmware/sgi_uv/
+  * rtc-cmos: wake again from S5
+  * pm_qos_requirement might sleep
+  * drivers/char/random.c: fix a race which can lead to a bogus BUG()
+  * ipsec: Fix deadlock in xfrm_state management.
+  * [x86] Fix TSC calibration issues
+  * tipc: Don't use structure names which easily globally conflict.
+  * sparc64: Fix IPI call locking.
+  * [ARM] omap: fix gpio.c build error
+  * sparc64: Prevent sparc64 from invoking irq handlers on offline CPUs
+  * powerpc: Fix uninitialised variable in VSX alignment code
+  * powerpc: Only make kernel text pages of linear mapping executable
+  * powerpc: Make sure _etext is after all kernel text
+  * powerpc: Work around gcc's -fno-omit-frame-pointer bug
+  * powerpc: Fix build error with 64K pages and !hugetlbfs
+  * powerpc: Fix for getting CPU number in power_save_ppc32_restore()
+  * UBIFS: amend f_fsid
+  * net/usb/pegasus: avoid hundreds of diagnostics
+  * ixgbe: initialize interrupt throttle rate
+  * pcnet-cs, axnet_cs: add new IDs, remove dup ID with less info
+  * netxen: Remove workaround for chipset quirk
+  * Split up PIT part of TSC calibration from native_calibrate_tsc
+  * iwlwifi: W/A for the TSF correction in IBSS
+  * iwlwifi: fix hidden ssid discovery in passive channels
+  * iwlwifi: remove false rxon if rx chain changes
+  * iwlwifi: fix station mimo power save values
+  * iwlwifi: fix rx_chain computation
+  * iwlwifi: fix Tx cmd memory allocation failure handling
+  * iwlwifi: call apm stop on exit
+  * iwlwifi: fix STATUS_EXIT_PENDING is not set on pci_remove
+  * ath9k: Fix TX status reporting
+  * ath9k: Fix TX control flag use for no ACK and RTS/CTS
+  * V4L/DVB (8555): au8522: add mechanism to configure IF frequency for vsb
+    and qam
+  * V4L/DVB (8556): au0828: add support for Hauppauge Woodbury
+  * V4L/DVB (8598): au8522: clean up function au8522_set_if
+  * V4L/DVB (8599): au8522: remove if frequency settings from vsb/qam
+    modulation tables
+  * V4L/DVB (8600): au0828: explicitly set 6 MHz IF frequency in
+    hauppauge_hvr950q_config
+  * V4L/DVB (8629): v4l2-ioctl: do not try to handle private V4L1 ioctls
+  * V4L/DVB (8633): ivtv: update ivtv version number
+  * V4L/DVB (8648): ivtv: improve CC support
+  * V4L/DVB (8660): gspca: Simplify the scan of URB packets in pac7311.
+  * V4L/DVB (8661): gspca: Bug in the previous changeset about pac7311.
+  * V4L/DVB (8663): gspca: Webcam 0c45:6128 added in sonixj.
+  * V4L/DVB (8664): gspca: The bridge/sensor of the webcam 093a:2621 is a
+    PAC 7302.
+  * V4L/DVB (8665): gspca: Fix the 640x480 resolution of the webcam
+    093a:2621.
+  * V4L/DVB (8666): gspca: Bad scanning of frames in pac7311.
+  * V4L/DVB (8667): gspca: Bad probe of Z-Star/Vimicro webcams with pas106
+    sensor.
+  * V4L/DVB (8668): gspca: Conflict GSPCA / ET61X251 for the webcam
+    102c:6251.
+  * V4L/DVB (8669): gspca: Add white balance control for spca561 rev 012A.
+  * V4L/DVB (8671): gspca: Remove the unused field 'dev_name' of the device
+    structure.
+  * V4L/DVB (8672): gspca: Big rewrite of spca561.
+  * V4L/DVB (8673): gspca: Bad frame scanning again and bad init in
+    pac7311.
+  * V4L/DVB (8674): gspca: Webcam 0c45:612e added in sonixj.
+  * V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated
+    by pac7311.
+  * V4L/DVB (8678): Remove the dead CONFIG_RADIO_MIROPCM20{,_RDS} code
+  * V4L/DVB (8681): v4l2-ioctl.c: fix warning
+  * V4L/DVB (8682): V4L: fix return value of register video func
+  * V4L/DVB (8701): cx18: Add missing lock for when the irq handler
+    manipulates the queues
+  * V4L/DVB (8703): gspca: Do controls work for spca561 revision 12a.
+  * V4L/DVB (8705): gspca: Adjust some control limits in spca561.
+  * V4L/DVB (8706): Make contrast and brightness work for pac7302.
+  * V4L/DVB (8707): gspca: Colors, hflip and vflip controls added for
+    pac7302.
+  * V4L/DVB (8709): gspca: Fix initialization and controls of sn9x110 -
+    ov7630.
+  * V4L/DVB (8710): gspca: Bad color control in sonixj.
+  * V4L/DVB (8711): gspca: Bad controls and quantization table of pac7311.
+  * V4L/DVB (8712): gspca: Bad start of sonixj webcams since changeset
+    a8779025e7e8.
+  * V4L/DVB (8713): gspca: Bad color control again in sonixj.
+  * V4L/DVB (8714): gspca: Bad start of sn9c110 and sensor om6802.
+  * V4L/DVB (8715): gspca: Change the name of some webcam in the gspca doc.
+  * V4L/DVB (8716): gspca: Bad start of sn9c110 and sensor ov7630.
+  * V4L/DVB (8717): gspca: Frame buffer too small for small resolutions
+    (sonixj and t613).
+  * V4L/DVB (8718): gspca: suspend/resume added.
+  * V4L/DVB (8719): gspca: Have VIDIOC_QUERYCTRL more compliant to the
+    spec.
+  * V4L/DVB (8720): gspca: V4L2_CAP_SENSOR_UPSIDE_DOWN added as a cap for
+    some webcams.
+  * V4L/DVB (8722): sms1xxx: fix typo in license header
+  * V4L/DVB (8726): link tuner before saa7134
+  * V4L/DVB (8727): V4L1: make PMS not autoprobe when builtin.
+  * V4L/DVB (8728): 1-make-pms-not-autoprobe-when-builtin update
+  * V4L/DVB (8749): Fix error code, when camera is not turned on by sonypi
+  * V4L/DVB (8750): V4L: check inval in video_register_device_index()
+  * V4L/DVB (8751): vivi: Fix some issues at vivi register routine
+  * V4L/DVB (8757): v4l-dvb: fix a bunch of sparse warnings
+  * V4L/DVB (8769): cx18: Simplify queue flush logic to prevent oops in
+    cx18_flush_queues()
+  * V4L/DVB (8778): radio: fix incorrect video_register_device result check
+  * V4L/DVB (8779): v4l: fix more incorrect video_register_device result
+    checks
+  * V4L/DVB (8790): saa7115: call i2c_set_clientdata only when state !=
+    NULL
+  * V4L/DVB (8803): s5h1409: Enable QAM_AUTO mode
+  * V4L/DVB (8804): s5h1411: Enable QAM_AUTO mode
+  * V4L/DVB (8805): Steven Toth email address change
+  * V4L/DVB (8809): gspca: Revert commit
+    9a9335776548d01525141c6e8f0c12e86bbde982
+  * V4L/DVB (8810): gspca: Compile error when CONFIG_PM not defined.
+  * V4L/DVB (8812): gspca: Do pac73xx webcams work.
+  * V4L/DVB (8813): gspca: Adjust SOF detection for pac73xx.
+  * V4L/DVB (8814): gspca: Set DISABLED the disabled controls at query
+    control time.
+  * V4L/DVB (8815): gspca: Fix problems with disabled controls.
+  * V4L/DVB (8816): gspca: Set disabled ctrls and fix a register pb with
+    ovxxxx in sonixb.
+  * V4L/DVB (8817): gspca: LED and proble changes in sonixb.
+  * V4L/DVB (8818): gspca: Reinitialize the device on resume.
+  * V4L/DVB (8819): gspca: Initialize the ov519 at open time and source
+    cleanup.
+  * V4L/DVB (8820): gspca: Change initialization and gamma of zc3xx -
+    pas106.
+  * V4L/DVB (8822): gspca: Change some subdriver functions for
+    suspend/resume.
+  * V4L/DVB (8823): gspca: H and V flips work for ov7670 only in ov519.
+  * V4L/DVB (8824): gspca: Too much code removed in the suspend/resume
+    changeset.
+  * V4L/DVB (8825): gspca: More controls for pac73xx and new webcam
+    093a:2624.
+  * V4L/DVB (8826): gspca: Webcam Labtec 2200 (093a:2626) added in pac7311.
+  * V4L/DVB (8827): gspca: Stop pac7302 autogain oscillation.
+  * V4L/DVB (8828): gspca: Set the clock at the end of initialization in
+    sonixj.
+  * V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB
+    exchanges.
+  * V4L/DVB (8830): gspca: Move some probe code to the new init function.
+  * V4L/DVB (8831): gspca: Resolve webcam conflicts between some drivers.
+  * V4L/DVB (8832): gspca: Bad pixelformat of vc0321 webcams.
+  * V4L/DVB (8833): gspca: Cleanup the sonixb code.
+  * V4L/DVB (8834): gspca: Have a bigger buffer for sn9c10x compressed
+    images.
+  * V4L/DVB (8835): gspca: Same pixfmt as the sn9c102 driver and raw Bayer
+    added in sonixb.
+  * V4L/DVB (8837): dvb: fix I2C adapters name size
+  * V4L/DVB (8839): dib0700: add comment to identify 35th USB id pair
+  * V4L/DVB (8840): dib0700: add basic support for Hauppauge Nova-TD-500
+    (84xxx)
+  * V4L/DVB (8842): vivi_release(): fix use-after-free
+  * V4L/DVB (8843): tda10048_firmware_upload(): fix a memory leak
+  * V4L/DVB (8844): dabusb_fpga_download(): fix a memory leak
+  * bnx2x: Accessing un-mapped page
+  * SELinux: memory leak in security_context_to_sid_core
+  * x86: add io delay quirk for Presario F700
+  * mmap: fix petty bug in anonymous shared mmap offset handling
+  * x86: Change warning message in TSC calibration.
+  * PCI: fix pbus_size_mem() resource alignment for CardBus controllers
+  * [ARM] omap: fix build error in ohci-omap.c
+  * [ARM] remove unused #include <version.h>
+  * ACPI: Make Len Brown the ACPI maintainer again
+  * fujitsu-laptop: fix regression for P8010 in 2.6.27-rc
+  * ACPI: Avoid bogus timeout about SMbus check
+  * acer-wmi: remove debugfs entries upon unloading
+  * forgotten refcount on sysctl root table
+  * V4L/DVB (8868): gspca: Support for vga modes with sif sensors in
+    sonixb.
+  * V4L/DVB (8869): gspca: Move the Sonix webcams with TAS5110C1B from
+    sn9c102 to gspca.
+  * V4L/DVB (8870): gspca: Fix dark room problem with sonixb.
+  * V4L/DVB (8872): gspca: Bad image format and offset with rev072a of
+    spca561.
+  * V4L/DVB (8873): gspca: Bad image offset with rev012a of spca561 and
+    adjust exposure.
+  * V4L/DVB (8874): gspca: Adjust hstart for sn9c103/ov7630 and update
+    usb-id's.
+  * [ARM] omap: fix virtual vs physical address space confusions
+  * V4L/DVB (8876): budget: udelay changed to mdelay
+  * V4L/DVB (8877): b2c2 and bt8xx: udelay to mdelay
+  * V4L/DVB (8880): PATCH: Fix parents on some webcam drivers
+  * V4L/DVB (8881): gspca: After 'while (retry--) {...}', retry will be -1
+    but not 0.
+  * powerpc/spufs: Fix multiple get_spu_context()
+  * powerpc/spufs: Fix race for a free SPU
+  * Input: bcm5974 - small formatting cleanup
+  * Input: bcm5974 - improve finger tracking and counting
+  * Input: bcm5974 - add BTN_TOUCH event for mousedev benefit
+  * Input: i8042 - make Lenovo 3000 N100 blacklist entry more specific
+  * sh: resume_kernel fix for kernel oops built with CONFIG_BKL_PREEMPT=y.
+  * sh64: resume_kernel fix for kernel oops built with
+    CONFIG_BKL_PREEMPT=y.
+  * i2c: fix i2c-sh_mobile timing issues
+  * clockevents: prevent clockevent event_handler ending up handler_noop
+  * clockevents: prevent endless loop in periodic broadcast handler
+  * clockevents: enforce reprogram in oneshot setup
+  * clockevents: prevent multiple init/shutdown
+  * clockevents: prevent endless loop lockup
+  * HPET: make minimum reprogramming delta useful
+  * [MTD] [NAND] tmio_nand: fix base address programming
+  * Fix conditional export of kvh.h and a.out.h to userspace.
+  * async_tx: fix the bug in async_tx_run_dependencies
+  * sched_clock: fix NOHZ interaction
+  * sched: fix process time monotonicity
+  * UBIFS: fix division by zero
+  * UBIFS: make minimum fanout 3
+  * [MIPS] Fix data bus error recovery
+  * [MIPS] Fix WARNING: at kernel/smp.c:290
+  * [MIPS] TXx9: Fix txx9_pcode initialization
+  * [MIPS] TX39xx: Add missing local_flush_icache_range initialization
+  * [MIPS] Probe initrd header only if explicitly specified
+  * res_counter: fix off-by-one bug in setting limit
+  * forcedeth: fix kexec regression
+  * atmel_lcdfb: fix oops in rmmod when framebuffer fails to register
+  * tracehook: comment pasto fixes
+  * drivers/mmc/card/block.c: fix refcount leak in mmc_block_open()
+  * x86: boot: stub out unimplemented CPU feature words
+  * x86: add NOPL as a synthetic CPU feature bit
+  * x86: use X86_FEATURE_NOPL in alternatives
+  * clockevents: broadcast fixup possible waiters
+  * x86: HPET fix moronic 32/64bit thinko
+  * x86: HPET: read back compare register before reading counter
+  * Fix CONFIG_AC97_BUS dependency
+  * [ARM] 5241/1: provide ioremap_wc()
+  * ntp: fix calculation of the next jiffie to trigger RTC sync
+  * clocksource, acpi_pm.c: use proper read function also in errata mode
+  * clocksource, acpi_pm.c: check for monotonicity
+  * x86: delay early cpu initialization until cpuid is done
+  * x86: move mtrr cpu cap setting early in early_init_xxxx
+  * sched: arch_reinit_sched_domains() must destroy domains to force
+    rebuild
+  * x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags
+  * x86: pda_init(): fix memory leak when using CPU hotplug
+  * x86: cpu_init(): fix memory leak when using CPU hotplug
+  * powerpc/spufs: Fix possible scheduling of a context to multiple SPEs
+  * netfilter: nf_conntrack_sip: de-static helper pointers
+  * netfilter: nf_conntrack_gre: more locking around keymap list
+  * netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet
+  * netfilter: nf_conntrack_irc: make sure string is terminated before
+    calling simple_strtoul
+  * pkt_sched: Fix qdisc state in net_tx_action()
+  * powerpc: Fix rare boot build breakage
+  * ahci, pata_marvell: play nicely together
+  * sata_mv: add RocketRaid 1720 PCI ID to driver
+  * ahci: disable PMP for marvell ahcis
+  * sata_nv: disable hardreset for generic
+  * libata-sff: kill spurious WARN_ON() in ata_hsm_move()
+  * pata_sil680: remove duplicate pcim_enable_device
+  * ahci: RAID mode SATA patch for Intel Ibex Peak DeviceIDs
+  * [MIPS] IP22: Fix detection of second HPC3 on Challenge S
+  * xen: fix 2.6.27-rc5 xen balloon driver warnings
+  * x86: disable static NOPLs on 32 bits
+  * netns : fix kernel panic in timewait socket destruction
+  * bridge: don't allow setting hello time to zero
+  * NFS: Restore missing hunk in NFS mount option parser
+  * usb: fix null deferences in low level usb serial
+  * Fix format of MAINTAINERS
+  * sparc64: Disable timer interrupts in fixup_irqs().
+  * [Bluetooth] Fix reference counting during ACL config stage
+  * [Bluetooth] Enforce correct authentication requirements
+  * [Bluetooth] Reject L2CAP connections on an insecure ACL link
+  * [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit
+    mode
+  * [S390] cio: Correct cleanup on error.
+  * [S390] cio: handle ssch() return codes correctly.
+  * [S390] cio: allow offline processing for disconnected devices
+  * ipsec: Restore larval states and socket policies in dump
+  * update Documentation/filesystems/Locking for 2.6.27 changes
+  * MAINTAINERS: add Atheros maintainer for atlx
+  * lib: Correct printk %pF to work on all architectures
+  * x86: fix memmap=exactmap boot argument
+  * clockevents: remove WARN_ON which was used to gather information
+  * ipv6: Fix OOPS in ip6_dst_lookup_tail().
+  * Linux 2.6.27-rc6
+
+ -- Ben Collins <ben.collins@canonical.com>  Tue, 02 Sep 2008 12:45:56 -0400
+
+linux (2.6.27-2.3) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/retag: Make script save .orig of tags for later use
+  * ubuntu/lirc: Fix device_create call
+  * build/firmware: Put in-kernel firmware into version specific subdir
+    - LP: #262115
+  * Rebase on linux-2.6 git.
+  * ABI bump
+
+  [ Herton Ronaldo Krzesinski ]
+
+  * SAUCE: (no-up) Apparmor warning fixes
+
+  [ John Johansen ]
+
+  * SAUCE: (no-up) Proper AppArmor ptrace updates for newer lsm API
+
+  [ Mackenzie Morgan ]
+
+  * SAUCE: Add quirk for ASUS Z37E to make sound audible after resume
+    - LP: #25896
+
+ -- Ben Collins <ben.collins@canonical.com>  Wed, 27 Aug 2008 14:03:05 -0400
+
+linux (2.6.27-1.2) intrepid; urgency=low
+
+  [ Amit Kucheria ]
+
+  * SAUCE: make fc transport removal of target configurable
+  * SAUCE: pm: Config option to disable handling of console during
+    suspend/resume
+
+  [ Ben Collins ]
+
+  * SAUCE: Lower warning level of some PCI messages
+  * SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps
+  * SAUCE: tulip: Let dmfe handle davicom on non-sparc
+  * SAUCE: tulip: Define ULI PCI ID's
+  * SAUCE: (no-up) version: Implement version_signature proc file.
+  * SAUCE: (no-up) connector.h: Add idx/val for drbd
+  * SAUCE: (no-up) swap: Add notify_swap_entry_free callback for compcache
+  * SAUCE: drivers: Remove some duplicate device entries in various modules
+  * SAUCE: (no-up) [AppArmor] merge with upstream subversion r1291
+  * SAUCE: apparmor: Update for changes to ptrace lsm hooks
+  * SAUCE: (no-up) Enable ubuntu extra subdirectory
+  * SAUCE: applesmc: Add MacBookAir
+  * SAUCE: (no-up) ACPI: initramfs DSDT override support
+  * ubuntu: Add drbd module
+  * ubuntu: Add iscsitarget module
+  * ubuntu: Add BOM for iscsitarget
+  * ubuntu: Add squashfs driver
+  * SAUCE: (no-up) Check for squashfs superblock in initramfs mounting.
+  * ubuntu: Add aufs module
+  * ubuntu: Added atl2 driver
+  * ubuntu: Added et131x driver
+  * ubuntu: Add dm-raid4-5 driver
+  * ubuntu: Add ndiswrapper driver
+  * ubuntu: Added ram backed compressed swap module (compcache)
+  * ubuntu: Add misc drivers from hardy lum
+  * ubuntu: Add heci driver 3.2.0.24
+  * ubuntu: Add ov511 and bt-sco drivers
+  * ubuntu: Add acx, prism2_usb wireless drivers
+  * ubuntu: Add at76 driver to build
+  * ubuntu: Add fsam7400 sw kill switch driver
+  * ubuntu: Added qc-usb driver
+  * ubuntu: e1000e: Upgraded module to 0.4.1.7
+  * ubuntu: Added rfkill drivers
+  * ubuntu: VIA - Add VIA DRM Chrome9 3D engine
+  * ubuntu: unionfs: Added v1.4 module from hardy
+  * ubuntu: Add LIRC driver
+  * ubuntu: Add GFS driver
+  * ubuntu: New tlsup driver for toshiba laptops
+  * Update config files
+  * build/d-i: Remove obsolete dm modules
+
+  [ Chuck Short ]
+
+  * SAUCE: ata: blacklist FUJITSU MHW2160BH PL
+
+  [ Colin Ian King ]
+
+  * ubuntu: Add dm-loop
+  * SAUCE: Enable speedstep for sonoma processors.
+
+  [ Dennis Noordsij ]
+
+  * SAUCE: Work around ACPI corruption upon suspend on some Dell machines.
+
+  [ Fabio M. Di Nitto ]
+
+  * SAUCE: Export gfs2 symbols required for gfs1 kernel module
+
+  [ Matthew Garrett ]
+
+  * SAUCE: hostap: send events on data interface as well as master
+    interface
+
+  [ Michael Frey (Senior Manager, MID ]
+
+  * SAUCE: Send HCI_RESET for Broadcomm 2046
+
+  [ Phillip Lougher ]
+
+  * SAUCE: r8169: disable TSO by default for RTL8111/8168B chipsets.
+
+  [ Stefan Bader ]
+
+  * SAUCE: (no-up) Export dm_disk function of device-mapper
+  * SAUCE: Restore VT fonts on switch
+  * SAUCE: mmc: Increase power_up deleay to fix TI readers
+
+  [ Tim Gardner ]
+
+  * SAUCE: Add extra headers to linux-libc-dev
+  * SAUCE: Catch nonsense keycodes and silently ignore
+  * SAUCE: Added support for HDAPS on various ThinkPads from Lenovo and IBM
+  * SAUCE: Guest OS does not recognize a lun with non zero target id on
+    Vmware ESX Server
+  * SAUCE: (no-up) Take care of orinoco_cs overlap with hostap_cs
+  * ubuntu: Add GNBD driver
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 23 Aug 2008 15:48:35 -0400
+
+linux (2.6.27-0.0) intrepid; urgency=low
+
+  * Not uploaded, placeholder for new release
+
+ -- Ben Collins <ben.collins@canonical.com>  Sat, 23 Aug 2008 15:48:35 -0400
+
+linux (2.6.26-5.17) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * build/abi: Add tosh_smm symbol to blacklist
+
+ -- Ben Collins <ben.collins@canonical.com>  Fri, 15 Aug 2008 09:29:34 -0400
+
+linux (2.6.26-5.16) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * Revert "SAUCE: toshiba_acpi: Rewrote most of the proc entry bits."
+  * Revert "SAUCE: Update toshiba_acpi.c to version 0.19a"
+  * build/config: Disable in-kernel toshiba driver(s)
+  * ubuntu/tlsup: New driver for toshiba laptops
+  * build/config: Enable TLSUP driver
+  * SAUCE: e1000e: Fix E1000E_ENABLED logic to check for our E1000E_NEW
+    driver as well
+  * ubuntu/e1000e: Remove E1000E_ENABLED option in local config
+  * build/config: Update configs to have E1000E_ENABLED set
+  * ubuntu/prism2: Remove duplicate device
+
+  [ Fabio M. Di Nitto ]
+
+  * SAUCE: Export gfs2 symbols required for gfs1 kernel module
+
+  [ Stefan Bader ]
+
+  * SAUCE: x86: HPET rework for SB700
+    - LP: #255910
+
+  [ Tim Gardner ]
+
+  * Add GNBD driver
+  * Enable GNBD driver
+  * SAUCE: Add GFS driver
+  * SAUCE: Enable gfs driver configs
+  * b43: Linksys WMP54G (BCM4306/3) card in a PCI format has an SPROM
+    coding
+
+  [ Upstream Kernel Changes ]
+
+  * KVM: x86 emulator: emulate clflush
+  * USB: quirk PLL power down mode
+
+ -- Ben Collins <ben.collins@canonical.com>  Mon, 11 Aug 2008 13:19:28 -0400
+
+linux (2.6.26-5.15) intrepid; urgency=low
+
+  [ Ben Collins ]
+
+  * Revert "SAUCE: Add blacklist support to fix Belkin bluetooth dongle."
+    - Superceded by upstream changes.
+  * build/config: New option enabled for uvcvideo
+  * build/control: Add Vcs-Git meta data to control file
+  * SAUCE: toshiba_acpi: Rewrote most of the new code
+  * abi/perm-blacklist: Add emu10k1 driver to blacklist
+
+  [ Upstream Kernel Changes ]
+
+  * pxamci: trivial fix of DMA alignment register bit clearing
+  * udplite: Protection against coverage value wrap-around
+  * ipv6: use timer pending
+  * ipv6: __KERNEL__ ifdef struct ipv6_devconf
+  * hdlcdrv: Fix CRC calculation.
+  * quota: fix possible infinite loop in quota code
+  * isofs: fix minor filesystem corruption
+  * KVM: VMX: Fix a wrong usage of vmcs_config
+  * KVM: SVM: fix suspend/resume support
+  * KVM: mmu_shrink: kvm_mmu_zap_page requires slots_lock to be held
+  * KVM: VMX: Add ept_sync_context in flush_tlb
+  * KVM: x86 emulator: Fix HLT instruction
+  * KVM: MMU: nuke shadowed pgtable pages and ptes on memslot destruction
+  * KVM: MMU: Fix potential race setting upper shadow ptes on nonpae hosts
+  * Patch Upstream: x86 ptrace: fix PTRACE_GETFPXREGS error
+  * rcu: fix rcu_try_flip_waitack_needed() to prevent grace-period stall
+  * Fix typos from signal_32/64.h merge
+  * x86 reboot quirks: add Dell Precision WorkStation T5400
+  * USB: fix usb serial pm counter decrement for disconnected interfaces
+  * x86, suspend, acpi: enter Big Real Mode
+  * markers: fix duplicate modpost entry
+  * Fix build on COMPAT platforms when CONFIG_EPOLL is disabled
+  * proc: fix /proc/*/pagemap some more
+  * cpusets: fix wrong domain attr updates
+  * x86: fix crash due to missing debugctlmsr on AMD K6-3
+  * ide-cd: fix oops when using growisofs
+  * rtc-at91rm9200: avoid spurious irqs
+  * vmlinux.lds: move __attribute__((__cold__)) functions back into final
+    .text section
+  * ARM: fix fls() for 64-bit arguments
+  * tcp: Clear probes_out more aggressively in tcp_ack().
+  * sparc64: Fix lockdep issues in LDC protocol layer.
+  * sparc64: Fix cpufreq notifier registry.
+  * sparc64: Do not define BIO_VMERGE_BOUNDARY.
+  * iop-adma: fix platform driver hotplug/coldplug
+  * myri10ge: do not forget to setup the single slice pointers
+  * myri10ge: do not use mgp->max_intr_slots before loading the firmware
+  * ALSA: trident - pause s/pdif output
+  * V4L: cx18: Upgrade to newer firmware & update documentation
+  * DVB: dib0700: add support for Hauppauge Nova-TD Stick 52009
+  * V4L: uvcvideo: Fix a buffer overflow in format descriptor parsing
+  * V4L: uvcvideo: Use GFP_NOIO when allocating memory during resume
+  * V4L: uvcvideo: Don't free URB buffers on suspend
+  * V4L: uvcvideo: Make input device support optional
+  * V4L: uvcvideo: Add support for Medion Akoya Mini E1210 integrated
+    webcam
+  * V4L: saa7134: Copy tuner data earlier to avoid overwriting manual tuner
+    type
+  * V4L: cx23885: Bugfix for concurrent use of /dev/video0 and /dev/video1
+  * DVB: cx23885: Ensure PAD_CTRL is always reset to a sensible default
+  * DVB: cx23885: DVB Transport cards using DVB port VIDB/TS1 did not
+    stream
+  * DVB: cx23885: Reallocated the sram to avoid concurrent VIDB/C issues
+  * DVB: cx23885: SRAM changes for the 885 and 887 silicon parts
+  * x86: fix kernel_physical_mapping_init() for large x86 systems
+  * eCryptfs: use page_alloc not kmalloc to get a page of memory
+  * UML - Fix boot crash
+  * ixgbe: remove device ID for unsupported device
+  * mpc52xx_psc_spi: fix block transfer
+  * tmpfs: fix kernel BUG in shmem_delete_inode
+  * markers: fix markers read barrier for multiple probes
+  * VFS: increase pseudo-filesystem block size to PAGE_SIZE
+  * cpufreq acpi: only call _PPC after cpufreq ACPI init funcs got called
+    already
+  * b43legacy: Release mutex in error handling code
+  * ath5k: don't enable MSI, we cannot handle it yet
+  * Fix off-by-one error in iov_iter_advance()
+  * Linux 2.6.26.1
+  * ftrace: remove unneeded documentation
+  * romfs_readpage: don't report errors for pages beyond i_size
+  * netfilter: nf_nat_sip: c= is optional for session
+  * SCSI: bsg: fix bsg_mutex hang with device removal
+  * x86: idle process - add checking for NULL early param
+  * x86: io delay - add checking for NULL early param
+  * Close race in md_probe
+  * Kprobe smoke test lockdep warning
+  * netfilter: xt_time: fix time's time_mt()'s use of do_div()
+  * linear: correct disk numbering error check
+  * SCSI: ch: fix ch_remove oops
+  * NFS: Ensure we zap only the access and acl caches when setting new acls
+  * jbd: fix race between free buffer and commit transaction
+  * Input: i8042 - add Intel D845PESV to nopnp list
+  * Input: i8042 - add Gericom Bellagio to nomux blacklist
+  * Input: i8042 - add Acer Aspire 1360 to nomux blacklist
+  * Bluetooth: Signal user-space for HIDP and BNEP socket errors
+  * Add compat handler for PTRACE_GETSIGINFO
+  * ALSA: hda - Fix wrong volumes in AD1988 auto-probe mode
+  * ALSA: hda - Fix DMA position inaccuracy
+  * ALSA: hda - Add missing Thinkpad Z60m support
+  * ALSA: emu10k1 - Fix i
[file cut: first 33554432 bytes kept]
[document cut: first 30900773 of 33523446 characters kept]
